[
  {
    "path": ".dir-locals.el",
    "content": "((nil .\n      ((c-file-style . \"gnu\")\n       (indent-tabs-mode . nil)\n       (fill-column . 72)))\n (change-log-mode . ((indent-tabs-mode . t)))\n (makefile-mode . ((indent-tabs-mode . t))))\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 2\nindent_style = space\ninsert_final_newline = true\n\n[*.{am,mk}]\nindent_size = tab\nindent_style = tab\n"
  },
  {
    "path": ".gitattributes",
    "content": "# line endings in repository match line endings on disc\n* -text\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# Set update schedule for GitHub Actions\n\nversion: 2\nupdates:\n\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      # Check for updates to GitHub Actions every week\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yaml",
    "content": "name: \"CodeQL\"\n\non:\n  schedule:\n    # Run job every Monday and Thursday at 16:30 UTC\n    - cron: '30 16 * * 1,4'\n  workflow_dispatch:\n\njobs:\n  ubuntu:\n    name: CodeQL analysis (Ubuntu)\n    runs-on: ubuntu-latest\n\n    strategy:\n      fail-fast: false\n      matrix:\n        # Override automatic language detection by changing the below list\n        # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']\n        language: ['cpp']\n        # Learn more...\n        # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection\n\n    steps:\n      - name: checkout repository\n        uses: actions/checkout@v6\n\n      - name: install dependencies\n        run: |\n          sudo apt -qq update\n          sudo apt install -y autoconf automake bison dvipng epstool fig2dev \\\n            flex g++ gcc gfortran gnuplot-x11 gperf gzip icoutils \\\n            libarpack2-dev libblas-dev libcurl4-gnutls-dev libfftw3-dev \\\n            libfltk1.3-dev libfontconfig1-dev libfreetype6-dev \\\n            libgl1-mesa-dev libgl2ps-dev libglpk-dev libgraphicsmagick++1-dev \\\n            libhdf5-dev liblapack-dev libosmesa6-dev libpcre2-dev \\\n            libqhull-dev libqscintilla2-qt5-dev libqrupdate-dev \\\n            libreadline-dev librsvg2-bin libsndfile1-dev libsuitesparse-dev \\\n            libsundials-dev libtool libxft-dev make openjdk-8-jdk \\\n            perl portaudio19-dev pstoedit qtbase5-dev qttools5-dev \\\n            qttools5-dev-tools rapidjson-dev rsync tar zlib1g-dev\n\n      - name: bootstrap\n        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap\n\n      - name: configure\n        run: |\n          mkdir .build\n          cd .build && ../configure \\\n            CPPFLAGS=\"-I/usr/include/hdf5/serial -I/usr/include/suitesparse\" \\\n            LDFLAGS=\"-L/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/hdf5/serial\" \\\n            --disable-docs\n\n      - name: initialize CodeQL\n        # Initialize the CodeQL tools for scanning.\n        uses: github/codeql-action/init@v4\n        with:\n          languages: ${{ matrix.language }}\n          # If you wish to specify custom queries, you can do so here or in a config file.\n          # By default, queries listed here will override any specified in a config file.\n          # Prefix the list here with \"+\" to use these queries and those in the config file.\n          # queries: ./path/to/local/query, your-org/your-repo/queries@main\n\n      - name: build\n        run: make -C ./.build all -j2 V=1\n\n      - name: perform CodeQL analysis\n        uses: github/codeql-action/analyze@v4\n\n\n  windows:\n    name: CodeQL analysis (Windows)\n    runs-on: windows-latest\n\n    defaults:\n      run:\n        # Use MSYS2 as default shell\n        shell: msys2 {0}\n\n    strategy:\n      fail-fast: false\n      matrix:\n        # Override automatic language detection by changing the below list\n        # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']\n        language: ['cpp']\n        # Learn more...\n        # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection\n        msystem: ['MINGW64']\n        include:\n          - msystem: 'MINGW64'\n\n    env:\n      CHERE_INVOKING: 1\n      # perl uses cmd shell by default\n      PERL5SHELL: bash -l -c\n\n    steps:\n      - uses: msys2/setup-msys2@v2\n        with:\n          update: true\n\n          # Use pre-installed version to save disc space on partition with source.\n          # We need that space for building.\n          release: false\n\n          # The packages are listed in (alphabetically sorted) blocks:\n          # The first block is for mandatory dependencies.\n          # The second block is for optional dependencies needed when building from a release tarball.\n          # The third block is for additional dependencies needed when building from a repository checkout.\n          pacboy: >-\n            autotools:p\n            cc:p\n            fc:p\n            gperf:p\n            openblas:p\n            pcre2:p\n            readline:p\n\n            arpack:p\n            curl:p\n            fftw:p\n            fltk:p\n            gl2ps:p\n            glpk:p\n            ghostscript:p\n            gnuplot:p\n            graphicsmagick:p\n            hdf5:p\n            libsndfile:p\n            portaudio:p\n            qhull:p\n            qrupdate:p\n            qscintilla:p\n            qt5-base:p\n            qt5-imageformats:p\n            qt5-svg:p\n            qt5-tools:p\n            rapidjson:p\n            suitesparse:p\n            sundials:p\n\n            ccache:p\n            icoutils:p\n            librsvg:p\n            texinfo:p\n\n          install: >-\n            base-devel\n\n            git\n            texinfo\n\n          msystem: ${{ matrix.msystem }}\n\n      - name: checkout repository\n        uses: actions/checkout@v6\n\n      - name: bootstrap\n        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap\n\n      - name: configure\n        # configure sometimes hangs while compiling 32bit Fortran.\n        # It should take much less than 30 minutes. Cancel the step if it takes longer.\n        timeout-minutes: 30\n        # FIXME: Fix building with Java support. Override JAVA_HOME for now.\n        # FIXME: How do we get a working TeX environment in MSYS2? Disable building the documentation for now.\n        # Linking with ncurses fails. Use termcap library instead.\n        run: |\n          mkdir .build\n          cd .build && ../configure \\\n            JAVA_HOME=\"\" \\\n            --disable-docs \\\n            --with-qt=5\n\n      - name: initialize CodeQL\n        # Initialize the CodeQL tools for scanning.\n        uses: github/codeql-action/init@v4\n        with:\n          languages: ${{ matrix.language }}\n          # If you wish to specify custom queries, you can do so here or in a config file.\n          # By default, queries listed here will override any specified in a config file.\n          # Prefix the list here with \"+\" to use these queries and those in the config file.\n          # queries: ./path/to/local/query, your-org/your-repo/queries@main\n\n      - name: build\n        # Spawning processes seems to have a big overhead on this platform.\n        # Use a somewhat larger number of parallel processes to compensate for that.\n        run: make -C ./.build all -j8 V=1\n\n      - name: perform CodeQL analysis\n        uses: github/codeql-action/analyze@v4\n"
  },
  {
    "path": ".github/workflows/make-alpine.yaml",
    "content": "name: make-alpine\non:\n  workflow_dispatch:\n  push:\nconcurrency: ci-alpine-${{ github.ref }}\n\njobs:\n\n  alpine:\n    runs-on: ubuntu-latest\n\n    name: Alpine (x86, musl)\n\n    defaults:\n      run:\n        # Use emulated shell as default\n        shell: alpine.sh {0}\n\n    env:\n      LIBGL_ALWAYS_SOFTWARE: \"1\"\n\n    steps:\n      - name: get CPU information\n        shell: bash\n        run: |\n          cat /proc/cpuinfo\n\n      - name: checkout repository\n        uses: actions/checkout@v6\n\n      - name: install dependencies\n        uses: jirutka/setup-alpine@v1\n        with:\n          # For available CPU architectures, see:\n          # https://github.com/marketplace/actions/setup-alpine-linux-environment\n          arch: x86\n          # QScintilla-Qt6 is currently not distributed by Alpine Linux. When\n          # it is, consider switching to Qt6 packages:\n          # qt6-qt5compat-dev\n          # qt6-qttools-dev\n          # The following packages are only needed to buid and install gl2ps:\n          # cmake\n          # wget\n          # libpng\n          # sudo\n          # ARPACK as distributed for Alpine latest-stable seems to be broken:\n          # arpack-dev\n          packages: >\n            build-base\n            autoconf\n            automake\n            m4\n            git\n            ccache\n            coreutils\n            gfortran\n            flex\n            gperf\n            icoutils\n            mesa-dri-gallium\n            libtool\n            libltdl\n            rsvg-convert\n            texlive-dvi\n            bison\n            curl-dev\n            fftw-dev\n            fltk-dev\n            fontconfig-dev\n            freetype-dev\n            ghostscript-dev\n            glpk-dev\n            glu-dev\n            gnuplot\n            graphicsmagick-dev\n            hdf5-dev\n            lcms2-dev\n            libsm-dev\n            libsndfile-dev\n            openblas-dev\n            pcre2-dev\n            perl\n            portaudio-dev\n            qhull-dev\n            qrupdate-dev\n            qscintilla-dev\n            qt5-qttools-dev\n            qscintilla-dev\n            rapidjson-dev\n            readline-dev\n            suitesparse-dev\n            texinfo\n            texmf-dist-lang\n            texmf-dist-latexrecommended\n            texmf-dist-plaingeneric\n            xvfb-run\n            xz-dev\n            zlib-dev\n            bzip2\n            gzip\n            tar\n            zip\n            cmake\n            wget\n            libpng\n            sudo\n\n      - name: prepare ccache\n        # create key with human readable timestamp\n        # used in action/cache/restore and action/cache/save steps\n        id: ccache-prepare\n        run: |\n          echo \"key=ccache:alpine:x86:${{ github.ref }}:$(date +\"%Y-%m-%d_%H-%M-%S\"):${{ github.sha }}\" >> $GITHUB_OUTPUT\n\n      - name: restore ccache\n        # setup the github cache used to maintain the ccache from one job to the next\n        uses: actions/cache/restore@v5\n        with:\n          # location of the ccache of the chroot in the root file system\n          path: /home/runner/rootfs/alpine-latest-x86/home/runner/.ccache\n          key: ${{ steps.ccache-prepare.outputs.key }}\n          restore-keys: |\n            ccache:alpine:x86:${{ github.ref }}\n            ccache:alpine:x86:refs/heads/default\n\n      - name: configure ccache\n        run: |\n          test -d ~/.ccache || mkdir ~/.ccache\n          echo \"max_size = 1G\" >> ~/.ccache/ccache.conf\n          echo \"compression = true\" >> ~/.ccache/ccache.conf\n          ccache --version\n          ccache -p\n          ccache -s\n          echo \"/usr/lib/ccache/bin\" >> $GITHUB_PATH\n\n      - name: build gl2ps\n        # gl2ps is currently not distributed by Alpine Linux.\n        # We need it for printing.\n        # As of 2025/12/14, gl2ps is in the Alpine Linux testing repository.\n        run: |\n          mkdir -p gl2ps && cd gl2ps\n          printf \"::group::\\033[0;32m==>\\033[0m Download tarball\\n\"\n          wget -O gl2ps-1.4.2.tgz https://geuz.org/gl2ps/src/gl2ps-1.4.2.tgz\n          echo \"::endgroup::\"\n          printf \"::group::\\033[0;32m==>\\033[0m Unpack tarball\\n\"\n          tar zxvf gl2ps-1.4.2.tgz\n          echo \"::endgroup::\"\n          printf \"::group::\\033[0;32m==>\\033[0m Configure\\n\"\n          mkdir -p build && cd build\n          cmake \\\n            -DCMAKE_BUILD_TYPE=Release \\\n            -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \\\n            ../gl2ps-1.4.2\n          echo \"::endgroup::\"\n          printf \"::group::\\033[0;32m==>\\033[0m Build\\n\"\n          cmake --build .\n          echo \"::endgroup::\"\n          printf \"::group::\\033[0;32m==>\\033[0m Install\\n\"\n          sudo cmake --install .\n          echo \"::endgroup::\"\n\n      - name: bootstrap\n        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap\n\n      - name: configure\n        id: configure\n        timeout-minutes: 30\n        run: |\n          echo $PATH\n          echo which ccache\n          which ccache\n          which gcc\n          echo gcc --version\n          gcc --version\n          which g++\n          echo g++ --version\n          g++ --version\n          which gfortran\n          echo gfortran --version\n          gfortran --version\n          mkdir .build\n          echo \"::group::Run configure script\"\n          # The default stack size for \"new threads\" is a measly 128 kiB for\n          # musl.  Manually, set the stack size for \"new threads\" to 1.5 MiB\n          # which is still a lot smaller than the current default of 8 MiB that\n          # is used, e.g., by Ubuntu 24.10.  Without that, running Octave fails\n          # at \"random\" tests.\n          cd .build && ../configure LDFLAGS=\"-Wl,-z,stack-size=1572864\"\n          echo \"::endgroup::\"\n\n      - name: display config.log\n        if: always() && (steps.configure.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/config.log\n\n      - name: build\n        # Parallel make seems to fail intermittently when creating the figures\n        # for the manual. The error message says it fails to connect to a\n        # display. Maybe an xvfb issue?\n        # Use single job make for now which seems to work more reliably.\n        run: |\n          XDG_RUNTIME_DIR=$RUNNER_TEMP xvfb-run -a make -C ./.build all V=1\n\n      - name: ccache status\n        run: ccache -s\n\n      - name: save ccache\n        # Save the cache after we are done (successfully) building\n        uses: actions/cache/save@v5\n        with:\n          path: /home/runner/rootfs/alpine-latest-x86/home/runner/.ccache\n          key: ${{ steps.ccache-prepare.outputs.key }}\n\n      - name: check\n        id: run-test-suite\n        timeout-minutes: 60\n        run: |\n          ./.build/run-octave --no-init-file --no-history --eval \"version -blas, version -lapack\"\n          XDG_RUNTIME_DIR=$RUNNER_TEMP \\\n            xvfb-run -a make -C ./.build check | tee ./test-suite.log\n\n      - name: display test suite log\n        if: always() && (steps.run-test-suite.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/test/fntests.log\n\n      - name: test history file creation\n        # see bug #62365\n        # Pipe to an interactive session to trigger appending the command to\n        # the history.  This will trigger the creation of a history file.\n        run:  |\n          echo \"history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')\" | ./.build/run-octave -i\n          [ -f ./a/b/c/history ] || echo \"::warning::Creating history file failed\"\n\n      - name: install\n        run: |\n          sudo make -C ./.build install\n\n      - name: test stand-alone executable\n        run: |\n          cd examples/code\n          mkoctfile --link-stand-alone embedded.cc -o embedded\n          LD_LIBRARY_PATH=\"/usr/local/lib/octave/$(octave --eval \"disp(version())\")\" ./embedded\n\n      - name: test Octave packages\n        env:\n          # colon separated list of packages\n          # reasons for including these packages in the CI tests:\n          # * control: builds .oct files from C++ and Fortran sources\n          # * stk: builds .mex files from C sources\n          PACKAGE_NAMES: \"control:stk\"\n        run: |\n          unset CC\n          unset CXX\n          IFS=:\n          for package in ${PACKAGE_NAMES}; do\n            printf \"   \\033[0;32m==>\\033[0m Octave package \\033[0;32m${package}\\033[0m\\n\"\n            echo \"::group::Install ${package}\"\n            octave --eval \"pkg install -verbose -forge ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test ${package}\"\n            octave --eval \"pkg test ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test log for ${package}\"\n            cat ${GITHUB_WORKSPACE}/fntests.log\n            echo \"::endgroup::\"\n           done\n\n      - name: analyze test suite results\n        # Make sure the test summary lists 0 \"FAIL\"s and no \"REGRESSION\"\n        run:  |\n          [ -n \"$(grep -e \"FAIL\\s*0\" ./test-suite.log)\" ] \\\n            || echo \"::warning::At least one test failed\"\n          [ -z \"$(grep -e \"REGRESSION\" ./test-suite.log)\" ] \\\n            || echo \"::warning::At least one regression in test suite\"\n          echo Finished analyzing test suite results.\n"
  },
  {
    "path": ".github/workflows/make-cross.yaml",
    "content": "name: make-cross-build\non:\n  workflow_dispatch:\n  # schedule:\n  #   # Run job every Wednesday and Saturday at 16:30 UTC\n  #   - cron: '30 16 * * 3,6'\n  push:\nconcurrency: ci-cross-build-${{ github.ref }}\n\njobs:\n\n  cross-build:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      # Allow other runners in the matrix to continue if some fail\n      fail-fast: false\n\n      matrix:\n        # List of architectures that are supported by Ubuntu:\n        # https://canonical-ubuntu-packaging-guide.readthedocs-hosted.com/en/latest/reference/architectures/\n        arch: [armhf, ppc64el, s390x, riscv64]\n        include:\n          - arch: armhf\n            target-triple: arm-linux-gnueabihf\n            os: ubuntu-24.04-arm\n            ccache-max: 1G\n            qemu-user:\n          - arch: ppc64el\n            target-triple: powerpc64le-linux-gnu\n            os: ubuntu-24.04-arm\n            ccache-max: 1G\n            qemu-user: qemu-ppc64le\n          - arch: s390x\n            target-triple: s390x-linux-gnu\n            os: ubuntu-24.04\n            ccache-max: 1G\n            qemu-user: qemu-s390x\n          - arch: riscv64\n            target-triple: riscv64-linux-gnu\n            os: ubuntu-24.04-arm\n            ccache-max: 1.4G\n            qemu-user: qemu-riscv64\n\n    name: cross ${{ matrix.arch }}\n\n    env:\n      CC: ${{ matrix.target-triple }}-gcc\n      CXX: ${{ matrix.target-triple }}-g++\n      F77: ${{ matrix.target-triple }}-gfortran\n\n    steps:\n      - name: get CPU information\n        run: lscpu\n\n      - name: checkout repository\n        uses: actions/checkout@v6\n\n      - name: install toolchain for ${{ matrix.arch }}\n        run: |\n          sudo apt -qq update\n          sudo apt install -y \\\n            g++-${{ matrix.target-triple }} \\\n            gfortran-${{ matrix.target-triple }} \\\n            autoconf automake bison ccache \\\n            dvipng epstool fig2dev flex gnuplot-x11 gperf gzip icoutils \\\n            libtool make perl pstoedit qt6-tools-dev-tools rsync tar texinfo \\\n            ${{ matrix.arch == 'armhf' && ' ' || 'qemu-user-binfmt' }}\n\n      - name: add repositories for ${{ matrix.arch }} packages\n        # deb822-style format:\n        # https://manpages.ubuntu.com/manpages/noble/man5/sources.list.5.html\n        run: |\n          sudo dpkg --add-architecture ${{ matrix.arch }}\n          case ${{ matrix.os }} in\n            \"ubuntu-24.04-arm\")\n              sudo bash -c 'cat - >/etc/apt/sources.list.d/ubuntu.sources' <<-EOF\n          Types: deb\n          URIs: http://ports.ubuntu.com/ubuntu-ports/\n          Suites: noble noble-updates noble-backports\n          Components: main restricted universe multiverse\n          Architectures: arm64 ${{ matrix.arch }}\n          Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\n          \n          Types: deb\n          URIs: http://security.ports.ubuntu.com/ubuntu-ports/\n          Suites: noble-security\n          Components: main restricted universe multiverse\n          Architectures: arm64 ${{ matrix.arch }}\n          Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\n          \n          EOF\n              ;;\n            \"ubuntu-24.04\")\n              sudo bash -c 'cat - >/etc/apt/sources.list.d/ubuntu.sources' <<-EOF\n          Types: deb\n          URIs: http://archive.ubuntu.com/ubuntu/\n          Suites: noble noble-updates noble-backports\n          Components: main restricted universe multiverse\n          Architectures: amd64\n          Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\n          \n          Types: deb\n          URIs: http://security.ubuntu.com/ubuntu/\n          Suites: noble-security\n          Components: main restricted universe multiverse\n          Architectures: amd64\n          Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\n          \n          Types: deb\n          URIs: http://ports.ubuntu.com/ubuntu-ports/\n          Suites: noble noble-updates noble-backports\n          Components: main restricted universe multiverse\n          Architectures: ${{ matrix.arch }}\n          Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\n          \n          Types: deb\n          URIs: http://security.ports.ubuntu.com/ubuntu-ports/\n          Suites: noble-security\n          Components: main restricted universe multiverse\n          Architectures: ${{ matrix.arch }}\n          Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\n          \n          EOF\n              ;;\n          esac\n          sudo apt update\n\n      - name: install dependencies for ${{ matrix.arch }}\n        run: |\n          sudo apt install -y \\\n            libarpack2-dev:${{ matrix.arch }} \\\n            libblas-dev:${{ matrix.arch }} \\\n            libcurl4-gnutls-dev:${{ matrix.arch }} \\\n            libfftw3-dev:${{ matrix.arch }} \\\n            libfltk1.3-dev:${{ matrix.arch }} \\\n            libfontconfig1-dev:${{ matrix.arch }} \\\n            libfreetype6-dev:${{ matrix.arch }} \\\n            libgl1-mesa-dev:${{ matrix.arch }} \\\n            libgl2ps-dev:${{ matrix.arch }} \\\n            libglpk-dev:${{ matrix.arch }} \\\n            libgraphicsmagick++1-dev:${{ matrix.arch }} \\\n            libhdf5-dev:${{ matrix.arch }} \\\n            liblapack-dev:${{ matrix.arch }} \\\n            libosmesa6-dev:${{ matrix.arch }} \\\n            libpcre2-dev:${{ matrix.arch }} \\\n            libqhull-dev:${{ matrix.arch }} \\\n            libqscintilla2-qt6-dev:${{ matrix.arch }} \\\n            libqrupdate-dev:${{ matrix.arch }} \\\n            libreadline-dev:${{ matrix.arch }} \\\n            librsvg2-bin:${{ matrix.arch }} \\\n            libsndfile1-dev:${{ matrix.arch }} \\\n            libsuitesparse-dev:${{ matrix.arch }} \\\n            libxft-dev:${{ matrix.arch }} \\\n            portaudio19-dev:${{ matrix.arch }} \\\n            qt6-5compat-dev:${{ matrix.arch }} \\\n            qt6-base-dev:${{ matrix.arch }} \\\n            qt6-tools-dev:${{ matrix.arch }} \\\n            rapidjson-dev:${{ matrix.arch }} \\\n            zlib1g-dev:${{ matrix.arch }}\n\n      - name: prepare ccache\n        # create key with human readable timestamp\n        # used in action/cache/restore and action/cache/save steps\n        id: ccache-prepare\n        run: |\n          echo \"key=ccache:cross:${{ matrix.os }}:${{ matrix.arch }}:${{ github.ref }}:$(date +\"%Y-%m-%d_%H-%M-%S\"):${{ github.sha }}\" >> $GITHUB_OUTPUT\n\n      - name: restore ccache\n        # setup the github cache used to maintain the ccache from one job to the next\n        uses: actions/cache/restore@v5\n        with:\n          path: ~/.ccache\n          key: ${{ steps.ccache-prepare.outputs.key }}\n          restore-keys: |\n            ccache:cross:${{ matrix.os }}:${{ matrix.arch }}:${{ github.ref }}\n            ccache:cross:${{ matrix.os }}:${{ matrix.arch }}:refs/heads/default\n\n      - name: configure ccache\n        env:\n          CCACHE_MAX: ${{ matrix.ccache-max }}\n        run: |\n          test -d ~/.ccache || mkdir ~/.ccache\n          echo \"max_size = $CCACHE_MAX\" >> ~/.ccache/ccache.conf\n          ccache -s\n          echo \"/usr/lib/ccache\" >> $GITHUB_PATH\n\n      - name: bootstrap\n        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap\n\n      - name: configure\n        id: configure\n        timeout-minutes: 30\n        run: |\n          echo $PATH\n          echo which ccache\n          which ccache\n          which $CC\n          echo $CC --version\n          $CC --version\n          which ${CXX% *}\n          echo ${CXX% *} --version\n          ${CXX% *} --version\n          which $F77\n          echo $F77 --version\n          $F77 --version\n          mkdir .build\n          echo \"::group::Run configure script\"\n          cd .build && ../configure \\\n            --host=${{ matrix.target-triple }} \\\n            --disable-docs \\\n            --disable-java \\\n            JAVA_HOME=\"\" \\\n            PKG_CONFIG_PATH=/usr/lib/${{ matrix.target-triple }}/pkgconfig/\n          echo \"::endgroup::\"\n\n      - name: display config.log\n        if: always() && (steps.configure.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/config.log\n\n      - name: build\n        run: XDG_RUNTIME_DIR=$RUNNER_TEMP make -C ./.build -j $(nproc) all V=1\n\n      - name: ccache status\n        run: ccache -s\n\n      - name: save ccache\n        # Save the cache after we are done (successfully) building\n        uses: actions/cache/save@v5\n        with:\n          path: ~/.ccache\n          key: ${{ steps.ccache-prepare.outputs.key }}\n\n      - name: check\n        id: run-test-suite\n        timeout-minutes: 60\n        env:\n          driver: ${{ matrix.qemu-user }}\n        # Without \"-cli\", there are deadlocks or crashes while running some\n        # tests that are related to graphics. This might be due to using qemu\n        # or xvfb-run or a combination of the two or an actual issue in Octave.\n        run: |\n          ./.build/run-octave --no-init-file --no-history --eval \"version -blas, version -lapack\"\n          XDG_RUNTIME_DIR=$RUNNER_TEMP RUN_OCTAVE_OPTIONS=\"-cli\" \\\n            make -C ./.build check | tee ./test-suite.log\n\n      - name: display test suite log\n        if: always() && (steps.run-test-suite.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/test/fntests.log\n\n      - name: test history file creation\n        # see bug #62365\n        # Pipe to an interactive session to trigger appending the command to\n        # the history.  This will trigger the creation of a history file.\n        run:  |\n          echo \"history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')\" | ./.build/run-octave -i\n          [ -f ./a/b/c/history ] || echo \"::warning::Creating history file failed\"\n\n      - name: install\n        run: |\n          sudo make -C ./.build install\n\n      - name: test stand-alone executable\n        run: |\n          unset CC\n          unset CXX\n          cd examples/code\n          mkoctfile --link-stand-alone embedded.cc -o embedded\n          LD_LIBRARY_PATH=\"/usr/local/lib/octave/$(octave --eval \"disp(version())\")\" \\\n            ./embedded\n\n      - name: test Octave packages\n        env:\n          # colon separated list of packages\n          # reasons for including these packages in the CI tests:\n          # * control: builds .oct files from C++ and Fortran sources\n          # * stk: builds .mex files from C sources\n          PACKAGE_NAMES: \"control:stk\"\n        run: |\n          unset CC\n          unset CXX\n          IFS=':' read -r -a packages <<< \"${PACKAGE_NAMES}\"\n          for package in \"${packages[@]}\"; do\n            printf \"   \\033[0;32m==>\\033[0m Octave package \\033[0;32m${package}\\033[0m\\n\"\n            echo \"::group::Install ${package}\"\n            octave --eval \"pkg install -verbose -forge ${package}\"\n            echo \"::endgroup::\"\n            if [ ${{ matrix.arch }} = \"armhf\" ]; then\n              echo \"::group::Test ${package}\"\n              octave --eval \"pkg test ${package}\"\n              echo \"::endgroup::\"\n              echo \"::group::Test log for ${package}\"\n              cat ${GITHUB_WORKSPACE}/fntests.log\n              echo \"::endgroup::\"\n            fi\n           done\n\n      - name: analyze test suite results\n        # Make sure the test summary lists 0 \"FAIL\"s and no \"REGRESSION\"\n        run:  |\n          [ -n \"$(grep -e \"FAIL\\s*0\" ./test-suite.log)\" ] || exit 1\n          [ -z \"$(grep -e \"REGRESSION\" ./test-suite.log)\" ] || exit 1\n          echo No unknown failing tests.\n"
  },
  {
    "path": ".github/workflows/make-cygwin.yaml",
    "content": "name: make-cygwin\non:\n  workflow_dispatch:\n  push:\nconcurrency: ci-cygwin-${{ github.ref }}\n\njobs:\n\n  cygwin:\n    runs-on: ${{ matrix.os }}\n\n    defaults:\n      run:\n        # Use Cygwin bash as default shell\n        shell: C:\\cygwin\\bin\\bash.exe --login -eo pipefail -o igncr '{0}'\n\n    strategy:\n      # Allow other runners in the matrix to continue if some fail\n      fail-fast: false\n\n      matrix:\n        # For available GitHub-hosted runners, see: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners\n        os: [windows-latest]\n\n    env:\n      CHERE_INVOKING: \"1\"\n      CC:  gcc\n      CXX:  g++\n      F77:  gfortran\n      # ccache 3.1 doesn't read configuration files\n      CCACHE_COMPRESS: \"1\"\n\n    steps:\n      - name: get CPU name\n        shell: pwsh\n        run : |\n          Get-CIMInstance -Class Win32_Processor | Select-Object -Property Name\n\n      - name: checkout repository\n        # This must be done before installing Cygwin because their git is\n        # incompatible with this action.\n        uses: actions/checkout@v6\n\n      - name: install Cygwin build environment\n        uses: cygwin/cygwin-install-action@v6\n        with:\n          # The packages are listed in (alphabetically sorted) blocks:\n          # The first block is for mandatory dependencies.\n          # The second block is for optional dependencies needed when building from a release tarball.\n          # The third block is for additional dependencies needed when building from a repository checkout.\n          # The fourth block is for additional run-time dependencies (to run test suite) that aren't needed to build.\n\n          # FIXME: libklu-devel should depend on libbtf-devel.  Install it manually even if Octave doesn't explicitly use it.\n          packages: >-\n            autoconf\n            automake\n            make\n            gcc-g++\n            gcc-fortran\n            bison\n            dash\n            flex\n            gperf\n            libtool\n            liblapack-devel\n            libpcre2-devel\n            libreadline-devel\n\n            ghostscript\n            gnuplot-base\n            libamd-devel\n            libarpack-devel\n            libbtf-devel\n            libbz2-devel\n            libcamd-devel\n            libccolamd-devel\n            libcholmod-devel\n            libcolamd-devel\n            libcurl-devel\n            libcxsparse-devel\n            libfftw3-devel\n            libfltk-devel\n            libfontconfig-devel\n            libfreetype-devel\n            libGL-devel\n            libgl2ps-devel\n            libglpk-devel\n            libGLU-devel\n            libgomp1\n            libGraphicsMagick-devel\n            libhdf5-devel\n            libiconv-devel\n            libklu-devel\n            libportaudio-devel\n            libqhull-devel\n            libqrupdate-devel\n            libqscintilla2_qt5-devel\n            libQt5Core-devel\n            libQt5Gui-devel\n            libQt5Help-devel\n            libsndfile-devel\n            libsuitesparseconfig-devel\n            libsundials-devel\n            libspqr-devel\n            libumfpack-devel\n            qt5-doc-tools\n            rapidjson-devel\n\n            ccache\n            git\n            icoutils\n            python\n            rsvg\n            texinfo\n\n            unzip\n            zip\n\n      - name: prepare ccache\n        # create key with human readable timestamp\n        # used in action/cache/restore and action/cache/save steps\n        id: ccache-prepare\n        run: |\n          echo \"ccachedir=$(cygpath -m ~/.ccache)\" >> $GITHUB_OUTPUT\n          echo \"key=ccache:${{ matrix.os }}:cygwin:${{ github.ref }}:$(date +\"%Y-%m-%d_%H-%M-%S\"):${{ github.sha }}\" >> $GITHUB_OUTPUT\n\n      - name: restore ccache\n        # Setup a github cache used to maintain the ccache from one run to the next\n        uses: actions/cache/restore@v5\n        with:\n          path: ${{ steps.ccache-prepare.outputs.ccachedir }}\n          key: ${{ steps.ccache-prepare.outputs.key }}\n          restore-keys: |\n            ccache:${{ matrix.os }}:cygwin:${{ github.ref }}\n            ccache:${{ matrix.os }}:cygwin:refs/heads/default\n\n      - name: configure ccache\n        run: |\n          # work around issue with ccache calling itself recursively\n          [ -f /usr/bin/ccache.exe ] && mv /usr/bin/ccache.exe /usr/bin/ccache\n          which ccache\n          ccache -V\n          # ccache 3.1 doesn't read configuration files\n          # test -d ${{ steps.ccache-prepare.outputs.ccachedir }} || mkdir -p ${{ steps.ccache-prepare.outputs.ccachedir }}\n          # echo \"max_size = 0.9G\" > ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf\n          # echo \"compression = true\" >> ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf\n          # limit maximum cache size to avoid exceeding the total disk or cache quota\n          ccache -M 0.9G\n          ccache -s\n          # create ccache symlinks for all compilers\n          test -d /usr/lib/ccache/bin || mkdir -p /usr/lib/ccache/bin\n          ln -s /usr/bin/ccache /usr/lib/ccache/bin/${CC}.exe\n          ln -s /usr/bin/ccache /usr/lib/ccache/bin/${CXX}.exe\n          ln -s /usr/bin/ccache /usr/lib/ccache/bin/${F77}.exe\n          # prepend path to ccache symlinks to PATH\n          echo 'export PATH=\"/usr/lib/ccache/bin:$PATH\"' >> ~/.bash_profile\n\n      - name: bootstrap\n        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap\n\n      - name: configure\n        id: configure\n        # FIXME: Fix building with Java support.  Override JAVA_HOME for now.\n        # FIXME: How do we get a working TeX environment in Cygwin?  Disable building the documentation for now.\n        # FIXME: Exporting symbols for instantiated template classes doesn't work currently. Maybe, test again when Cygwin updated to a newer compiler than GCC 11.4.0?\n        run: |\n          echo $PATH\n          which $CC\n          echo $CC --version\n          $CC --version\n          which $CXX\n          echo $CXX --version\n          $CXX --version\n          which $F77\n          echo $F77 --version\n          $F77 --version\n          mkdir .build\n          echo \"::group::Run configure script\"\n          cd .build && ../configure \\\n            --libexecdir=/usr/lib \\\n            --enable-shared \\\n            --disable-java \\\n            --disable-docs \\\n            JAVA_HOME=\"\" \\\n            EGREP=\"grep -E\" \\\n            FLIBS=\"-lgfortran -lquadmath\"\n          echo \"::endgroup::\"\n\n      - name: display config.log\n        if: always() && (steps.configure.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/config.log\n\n      - name: build\n        # Spawning processes seems to have a big overhead on this platform.  Use a somewhat larger number of parallel processes to compensate for that.\n        run: |\n          EGREP=\"grep -E\" make -C ./.build all -j8 V=1\n\n      - name: ccache status\n        continue-on-error: true\n        run: ccache -s\n\n      - name: save ccache\n        # Save the cache after we are done (successfully) building\n        uses: actions/cache/save@v5\n        with:\n          path: ${{ steps.ccache-prepare.outputs.ccachedir }}\n          key: ${{ steps.ccache-prepare.outputs.key }}\n\n      - name: rebase binaries\n        run: |\n          find ${GITHUB_WORKSPACE}/.build -name \"*.oct\" -or -name \"*.dll\" | tee binaries.list\n          rebase -O -T binaries.list\n\n      - name: check\n        id: run-test-suite\n        # Continuing on error in this step means that jobs will be \"green\" even\n        # if the test suite crashes.  But if we don't continue, we'll loose the\n        # ccache.\n        # It would be nice if we could mark the job as \"yellow\" (and continue)\n        # in that case.  The second best thing is to display a warning in the\n        # job summary (see below).\n        continue-on-error: true\n        timeout-minutes: 60\n\n        # mkoctfile seems to have trouble when gcc is called via ccache.  So,\n        # remove the directory with the ccache wrappers from PATH.\n\n        run: |\n          export PATH=$(echo \"$PATH\" | sed -e \"s|/usr/lib/ccache/bin:||g\")\n          ./.build/run-octave --no-init-file --no-history --eval \"version -blas, version -lapack\"\n          EGREP=\"grep -E\" make -C ./.build check | tee ./test-suite.log\n\n      - name: display test suite log\n        if: always() && (steps.run-test-suite.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long.  Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/test/fntests.log\n\n      - name: test history file creation\n        # see bug #62365\n        # Pipe to an interactive session to trigger appending the command to\n        # the history.  This will trigger the creation of a history file.\n        run: |\n          echo \"history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')\" | ./.build/run-octave -i\n          [ -f ./a/b/c/history ] || echo \"::warning::Creating history file failed\"\n\n      - name: install\n        run: |\n          make -C ./.build install\n\n      - name: test stand-alone executable\n        run: |\n          unset CC\n          unset CXX\n          export PATH=$(echo \"$PATH\" | sed -e \"s|/usr/lib/ccache/bin:||g\")\n          cd examples/code\n          mkoctfile --link-stand-alone embedded.cc -o embedded\n          ./embedded.exe\n\n      - name: test Octave packages\n        env:\n          # colon separated list of packages\n          # reasons for including these packages in the CI tests:\n          # * control: builds .oct files from C++ and Fortran sources\n          # * stk: builds .mex files from C sources\n          PACKAGE_NAMES: \"control:stk\"\n        run: |\n          unset CC\n          unset CXX\n          export PATH=$(echo \"$PATH\" | sed -e \"s|/usr/lib/ccache/bin:||g\")\n          IFS=':' read -r -a packages <<< \"${PACKAGE_NAMES}\"\n          for package in \"${packages[@]}\"; do\n            printf \"   \\033[0;32m==>\\033[0m Octave package \\033[0;32m${package}\\033[0m\\n\"\n            echo \"::group::Install ${package}\"\n            octave --eval \"pkg install -verbose -forge ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test ${package}\"\n            octave --eval \"pkg test ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test log for ${package}\"\n            cat ${GITHUB_WORKSPACE}/fntests.log\n            echo \"::endgroup::\"\n           done\n\n      - name: analyze test suite results\n        # Make sure the test summary lists 0 \"FAIL\"s and no \"REGRESSION\"\n        run: |\n          [ -n \"$(grep -e \"FAIL\\s*0\" ./test-suite.log)\" ] || echo \"::warning::At least one test failed\"\n          [ -z \"$(grep -e \"REGRESSION\" ./test-suite.log)\" ] || echo \"::warning::At least one regression in test suite\"\n          echo Finished analyzing test suite results.\n"
  },
  {
    "path": ".github/workflows/make-macos.yaml",
    "content": "name: make-macos\non:\n  workflow_dispatch:\n  push:\nconcurrency: ci-macos-${{ github.ref }}\n\njobs:\n\n  macos:\n    runs-on: ${{ matrix.os }}\n\n    name: ${{ matrix.os }} Qt${{ matrix.qt }}\n\n    strategy:\n      # Allow other runners in the matrix to continue if some fail\n      fail-fast: false\n\n      matrix:\n        # For available GitHub-hosted runners, see: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners\n        os: [macos-14, macos-15]\n        # Most (or all) homebrew packages are compiled with clang and link\n        # against libc++.  So we also use clang to avoid issues with symbols\n        # that don't match.\n        # compiler: [real-gcc, clang]\n        compiler: [clang]\n        qt: [6]\n        include:\n          # - compiler: real-gcc\n          #   cc: \"/usr/local/bin/gcc-10\"\n          #   cxx: \"/usr/local/bin/g++-10\"\n          #   cppflags: \"-I/usr/local/opt/hdf5/include -I/usr/local/opt/gl2ps/include -I/usr/local/opt/glpk/include -I/usr/local/opt/pcre/include -I/usr/local/opt/qscintilla2/include -I/usr/local/opt/suite-sparse/include -I/usr/local/opt/sundials/include\"\n          #   ldflags: \"-L/usr/local/opt/hdf5/lib -L/usr/local/opt/gl2ps/lib -L/usr/local/opt/glpk/lib -L/usr/local/opt/pcre/lib -L/usr/local/opt/qscintilla2/lib -L/usr/local/opt/suite-sparse/lib -L/usr/local/opt/sundials/lib\"\n          - compiler: clang\n            cc: \"clang\"\n            cxx: \"clang++\"\n          - os: macos-15-intel\n            qt: \"5\"\n            cc: \"clang\"\n            cxx: \"clang++\"\n\n    env:\n      CC: ${{ matrix.cc }}\n      CXX: ${{ matrix.cxx }}\n      F77: gfortran\n\n    steps:\n      - name: checkout repository\n        uses: actions/checkout@v6\n\n      - name: install dependencies\n        # This step sometimes takes long and still recovers. But sometimes it\n        # seems to hang indefinitely.\n        # Use a pretty long timeout (but still less than the default 6 hours).\n        timeout-minutes: 75\n\n        # Homebrew's Python conflicts with the Python that comes pre-installed\n        # on the GitHub runners. Some of Octave's dependencies depend on\n        # different versions of Homebrew's Python. Enforce using the ones from\n        # Homebrew to avoid errors on updates.\n        # See: https://github.com/orgs/Homebrew/discussions/3928\n\n        # It looks like \"gfortran\" isn't working correctly unless \"gcc\" is\n        # re-installed.\n\n        # See also: https://formulae.brew.sh/formula/octave#default\n        # The packages are listed in (alphabetically sorted) blocks:\n        # The first block is for \"direct\" dependencies.\n        # The second block is for additional dependencies needed when building from a release tarball.\n        # The third block is for additional dependencies needed when building from a repository checkout.\n        run: |\n          brew update\n          brew install --overwrite python@3.12 python@3.13\n          brew reinstall gcc\n          brew install arpack epstool fast_float fftw fig2dev fltk fontconfig \\\n            freetype ghostscript gl2ps glpk gnuplot graphicsmagick hdf5 \\\n            libiconv libsndfile libtool openblas pcre2 portaudio pstoedit \\\n            qhull qrupdate qscintilla2 \\\n            rapidjson readline suite-sparse sundials texinfo \\\n            ccache gnu-sed openjdk pkg-config \\\n            automake autoconf bison gettext icoutils librsvg mactex-no-gui\n          brew install --overwrite \\\n            ${{ matrix.qt == '6' && 'qt5compat qtbase qttools' || 'qt@5' }}\n          eval \"$(/usr/libexec/path_helper)\"\n          HOMEBREW_PREFIX=$(brew --prefix)\n          echo \"HOMEBREW_PREFIX=$(brew --prefix)\" >> $GITHUB_ENV\n          echo \"/Library/TeX/texbin\" >> $GITHUB_PATH\n          echo \"${HOMEBREW_PREFIX}/opt/qt@${{ matrix.qt }}/bin\" >> $GITHUB_PATH\n          echo \"${HOMEBREW_PREFIX}/opt/texinfo/bin\" >> $GITHUB_PATH\n          echo \"${HOMEBREW_PREFIX}/opt/bison/bin\" >> $GITHUB_PATH\n          echo \"${HOMEBREW_PREFIX}/opt/gnu-sed/libexec/gnubin\" >> $GITHUB_PATH\n          echo \"${HOMEBREW_PREFIX}/opt/libiconv/bin\" >> $GITHUB_PATH\n\n      - name: prepare ccache\n        # create key with human readable timestamp\n        # used in action/cache/restore and action/cache/save steps\n        id: ccache-prepare\n        run: |\n          echo \"key=ccache:${{ matrix.os }}:${{ matrix.compiler }}:qt${{ matrix.qt }}:${{ github.ref }}:$(date +\"%Y-%m-%d_%H-%M-%S\"):${{ github.sha }}\" >> $GITHUB_OUTPUT\n\n      - name: restore ccache\n        # setup the github cache used to maintain the ccache from one job to the next\n        uses: actions/cache/restore@v5\n        id: restore-ccache\n        with:\n          path: /Users/runner/Library/Caches/ccache\n          key: ${{ steps.ccache-prepare.outputs.key }}\n          restore-keys: |\n            ccache:${{ matrix.os }}:${{ matrix.compiler }}:qt${{ matrix.qt }}:${{ github.ref }}\n            ccache:${{ matrix.os }}:${{ matrix.compiler }}:qt${{ matrix.qt }}:refs/heads/default\n\n      - name: configure ccache\n        # The cache doesn't seem to compress well on macOS. Is it already compressed?\n        # Limit the maximum size to avoid exceeding the total cache limits.\n        run: |\n          test -d /Users/runner/Library/Preferences/ccache || mkdir /Users/runner/Library/Preferences/ccache\n          echo \"max_size = 0.9G\" >> /Users/runner/Library/Preferences/ccache/ccache.conf\n          ccache -s\n          echo \"${HOMEBREW_PREFIX}/opt/ccache/libexec\" >> $GITHUB_PATH\n\n      - name: bootstrap\n        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap\n\n      - name: configure\n        id: configure\n        timeout-minutes: 30\n        env:\n          MY_CPPFLAGS: ${{ matrix.cppflags }}\n          MY_LDFLAGS: ${{ matrix.ldflags }}\n        # This is a hodgepodge of configure flags put together from the\n        # buildbot rules:\n        # https://hg.octave.org/octave-buildbot/file/tip/master.cfg#l543\n        # And the homebrew formula:\n        # https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/octave.rb\n        # Amended with additional flags that seem to be needed.\n        # Not all of those might be needed or be correct.\n        run: |\n          echo $PATH\n          echo which ccache\n          which ccache\n          which $CC\n          echo $CC --version\n          $CC --version\n          which $CXX\n          echo $CXX --version\n          $CXX --version\n          which $F77\n          echo $F77 --version\n          $F77 --version\n          mkdir .build\n          echo \"::group::Run configure script\"\n          cd .build && ../configure \\\n            CPPFLAGS=\"-I${HOMEBREW_PREFIX}/opt/gettext/include -I${HOMEBREW_PREFIX}/opt/icu4c/include -I${HOMEBREW_PREFIX}/opt/libiconv/include -I${HOMEBREW_PREFIX}/opt/qt@${{ matrix.qt }}/include -I${HOMEBREW_PREFIX}/opt/readline/include -I${HOMEBREW_PREFIX}/opt/sqlite/include $MY_CPPFLAGS -I${HOMEBREW_PREFIX}/include\" \\\n            CXXFLAGS=\"-O2 -g\" \\\n            LDFLAGS=\"-L${HOMEBREW_PREFIX}/opt/bison/lib -L${HOMEBREW_PREFIX}/opt/gettext/lib -L${HOMEBREW_PREFIX}/opt/icu4c/lib -L${HOMEBREW_PREFIX}/opt/libiconv/lib -L${HOMEBREW_PREFIX}/opt/readline/lib -L${HOMEBREW_PREFIX}/opt/sqlite/lib $MY_LDFLAGS -L${HOMEBREW_PREFIX}/lib\" \\\n            PKG_CONFIG_PATH=\"${HOMEBREW_PREFIX}/opt/openblas/lib/pkgconfig:${HOMEBREW_PREFIX}/opt/icu4c/lib/pkgconfig:${HOMEBREW_PREFIX}/opt/qt@${{ matrix.qt }}/lib/pkgconfig\" \\\n            --with-qt=${{ matrix.qt }} \\\n            QCOLLECTIONGENERATOR=\"qhelpgenerator\" \\\n            --with-x=no \\\n            --with-blas=\"-L${HOMEBREW_PREFIX}/opt/openblas/lib -lopenblas\" \\\n            --with-java-homedir=\"${HOMEBREW_PREFIX}/opt/openjdk\" \\\n            --prefix=\"${HOME}/usr\"\n          echo \"::endgroup::\"\n\n      - name: display config.log\n        if: always() && (steps.configure.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/config.log\n\n      - name: build\n        run: make -C ./.build all -j3 V=1\n\n      - name: ccache status\n        run: ccache -s\n\n      - name: save ccache\n        # Save the cache after we are done (successfully) building\n        uses: actions/cache/save@v5\n        with:\n          path: /Users/runner/Library/Caches/ccache\n          key: ${{ steps.ccache-prepare.outputs.key }}\n\n      - name: check\n        id: run-test-suite\n        # Continuing on error in this step means that jobs will be \"green\" even\n        # if the test suite crashes.  But if we don't continue, we'll loose the\n        # ccache and other jobs will be cancelled, too.\n        # It would be nice if we could mark the job as \"yellow\" (and continue)\n        # in that case.  The second best thing is to display a warning in the\n        # job summary (see below).\n        continue-on-error: true\n        timeout-minutes: 60\n        run: |\n          echo 'makeinfo_program (\"${HOMEBREW_PREFIX}/opt/texinfo/bin/makeinfo\");' >> ./scripts/startup/site-rcfile\n          ./.build/run-octave --no-init-file --no-history --eval \"version -blas, version -lapack\"\n          make -C ./.build check | tee ./test-suite.log\n\n      - name: display test suite log\n        if: always() && (steps.run-test-suite.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/test/fntests.log\n\n      - name: test history file creation\n        # see bug #62365\n        # Pipe to an interactive session to trigger appending the command to\n        # the history.  This will trigger the creation of a history file.\n        run:  |\n          echo \"history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')\" | ./.build/run-octave -i\n          [ -f ./a/b/c/history ] || echo \"::warning::Creating history file failed\"\n\n      - name: install\n        run: |\n          mkdir -p /Users/runner/usr\n          make -C ./.build install\n\n      - name: test stand-alone executable\n        run: |\n          unset CC\n          unset CXX\n          cd examples/code\n          PATH=\"/Users/runner/usr/bin:$PATH\" \\\n            mkoctfile --link-stand-alone embedded.cc -o embedded\n          ./embedded\n\n      - name: test Octave packages\n        env:\n          # colon separated list of packages\n          # reasons for including these packages in the CI tests:\n          # * control: builds .oct files from C++ and Fortran sources\n          # * stk: builds .mex files from C sources\n          PACKAGE_NAMES: \"control:stk\"\n        run: |\n          unset CC\n          unset CXX\n          export F77=gfortran\n          export PATH=\"/Users/runner/usr/bin:$PATH\"\n          IFS=':' read -r -a packages <<< \"${PACKAGE_NAMES}\"\n          for package in \"${packages[@]}\"; do\n            printf \"   \\033[0;32m==>\\033[0m Octave package \\033[0;32m${package}\\033[0m\\n\"\n            echo \"::group::Install ${package}\"\n            octave --eval \"pkg install -verbose -forge ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test ${package}\"\n            octave --eval \"pkg test ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test log for ${package}\"\n            cat ${GITHUB_WORKSPACE}/fntests.log\n            echo \"::endgroup::\"\n          done\n\n      - name: analyze test suite results\n        # Make sure the test summary lists 0 \"FAIL\"s and no \"REGRESSION\"\n        run: |\n          [ -n \"$(grep -e \"FAIL\\s*0\" ./test-suite.log)\" ] || exit 1\n          [ -z \"$(grep -e \"REGRESSION\" ./test-suite.log)\" ] || exit 1\n          echo No unknown failing tests.\n"
  },
  {
    "path": ".github/workflows/make-mingw.yaml",
    "content": "name: make-mingw\non:\n  workflow_dispatch:\n  push:\nconcurrency: ci-mingw-${{ github.ref }}\n\njobs:\n\n  mingw:\n    runs-on: ${{ matrix.os }}\n\n    name: mingw-w64 ${{ matrix.msystem }}\n\n    defaults:\n      run:\n        # Use MSYS2 as default shell\n        shell: msys2 {0}\n\n    strategy:\n      # Allow other runners in the matrix to continue if some fail\n      fail-fast: false\n\n      matrix:\n        # For available GitHub-hosted runners, see: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners\n        msystem: [MINGW64, CLANG64, CLANGARM64]\n        include:\n          - msystem: MINGW64\n            os: windows-latest\n            mingw-prefix: mingw64\n            cc: gcc\n            cxx: g++\n            f77: gfortran\n            extra-config-flags: \"\"\n            ccache-max: 0.9G\n            allow-error: false\n          - msystem: CLANG64\n            os: windows-latest\n            mingw-prefix: clang64\n            cc: clang\n            cxx: clang++\n            f77: flang\n            # Clang seems to require a different set of dllexport attributes than GCC.\n            extra-config-flags:\n              --disable-lib-visibility-flags\n            ccache-max: 400M\n            # This configuration is not fully supported yet\n            allow-error: true\n          - msystem: CLANGARM64\n            os: windows-11-arm\n            mingw-prefix: clangarm64\n            cc: clang\n            cxx: clang++\n            f77: flang\n            # Clang seems to require a different set of dllexport attributes than GCC.\n            extra-config-flags:\n              --disable-lib-visibility-flags\n            ccache-max: 400M\n            # This configuration is not fully supported yet\n            allow-error: true\n\n    env:\n      CHERE_INVOKING: 1\n      CC:  ${{ matrix.cc }}\n      CXX:  ${{ matrix.cxx }}\n      F77:  ${{ matrix.f77 }}\n      # perl uses cmd shell by default\n      PERL5SHELL: bash -l -c\n\n    steps:\n      - name: get runner hardware information\n        shell: pwsh\n        run : |\n          Get-PSDrive -PSProvider FileSystem\n          Get-CIMInstance -Class Win32_Processor | Select-Object -Property Name\n\n      - name: install MSYS2 build environment\n        uses: msys2/setup-msys2@v2\n        with:\n          update: true\n\n          # Use pre-installed version if possible to save disc space on\n          # partition with source.  We need that space for building.\n          release: ${{ matrix.msystem == 'CLANGARM64' }}\n\n          msystem: ${{ matrix.msystem }}\n\n          # The packages are listed in (alphabetically sorted) blocks:\n          # The first block is for mandatory dependencies.\n          # The second block is for optional dependencies needed when building from a release tarball.\n          # The third block is for additional dependencies needed when building from a repository checkout.\n          # The fourth block is for additional run-time dependencies (to run test suite) that aren't needed to build.\n          pacboy: >-\n            autotools:p\n            cc:p\n            fc:p\n            gperf:p\n            openblas:p\n            pcre2:p\n            readline:p\n\n            arpack:p\n            curl:p\n            fftw:p\n            fltk:p\n            gl2ps:p\n            glpk:p\n            ghostscript:p\n            gnuplot:p\n            graphicsmagick:p\n            hdf5:p\n            libsndfile:p\n            portaudio:p\n            qhull:p\n            qrupdate:p\n            qscintilla:p\n            qt5-base:p\n            qt5-imageformats:p\n            qt5-svg:p\n            qt5-tools:p\n            rapidjson:p\n            suitesparse:p\n            sundials:p\n\n            ccache:p\n            icoutils:p\n            librsvg:p\n            texinfo:p\n\n          install: >-\n            base-devel\n\n            git\n\n            unzip\n            zip\n\n      - name: checkout repository\n        uses: actions/checkout@v6\n\n      - name: prepare ccache\n        # create key with human readable timestamp\n        # used in action/cache/restore and action/cache/save steps\n        id: ccache-prepare\n        run: |\n          echo \"ccachedir=$(cygpath -m $(ccache -k cache_dir))\" >> $GITHUB_OUTPUT\n          echo \"key=ccache:${{ matrix.os }}:${{ matrix.msystem }}:${{ github.ref }}:$(date +\"%Y-%m-%d_%H-%M-%S\"):${{ github.sha }}\" >> $GITHUB_OUTPUT\n          echo \"timestamp=$(date +\"%Y-%m-%d_%H-%M-%S\")\" >> $GITHUB_OUTPUT\n\n      - name: restore ccache\n        # Setup the github cache used to maintain the ccache from one job to the next\n        uses: actions/cache/restore@v5\n        with:\n          path: ${{ steps.ccache-prepare.outputs.ccachedir }}\n          key: ${{ steps.ccache-prepare.outputs.key }}\n          restore-keys: |\n            ccache:${{ matrix.os }}:${{ matrix.msystem }}:${{ github.ref }}\n            ccache:${{ matrix.os }}:${{ matrix.msystem }}:refs/heads/default\n\n      - name: configure ccache\n        # Limit the maximum size and switch on compression to avoid exceeding the total disk or cache quota.\n        run: |\n          which ccache\n          test -d ${{ steps.ccache-prepare.outputs.ccachedir }} || mkdir -p ${{ steps.ccache-prepare.outputs.ccachedir }}\n          echo \"max_size = ${{ matrix.ccache-max }}\" > ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf\n          echo \"compression = true\" >> ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf\n          ccache -p\n          ccache -s\n          # prepend path to ccache helper scripts to PATH\n          echo 'export PATH=\"$MINGW_PREFIX/lib/ccache/bin:$PATH\"' >> ~/.bash_profile\n\n      - name: bootstrap\n        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap\n\n      - name: configure\n        id: configure\n        # configure sometimes hangs while compiling 32bit Fortran.\n        # It should take much less than 30 minutes. Cancel the step if it takes longer.\n        timeout-minutes: 30\n        # FIXME: Fix building with Java support. Override JAVA_HOME for now.\n        # FIXME: How do we get a working TeX environment in MSYS2? Disable building the documentation for now.\n        run: |\n          echo $PATH\n          which $CC\n          echo $CC --version\n          $CC --version\n          which ${CXX% *}\n          echo ${CXX% *} --version\n          ${CXX% *} --version\n          which $F77\n          echo $F77 --version\n          $F77 --version\n          mkdir .build\n          echo \"::group::Run configure script\"\n          cd .build && ../configure \\\n            JAVA_HOME=\"\" \\\n            --enable-relocate-all \\\n            --disable-docs \\\n            --with-qt=5 \\\n            ${{ matrix.extra-config-flags }}\n          echo \"::endgroup::\"\n\n      - name: display config.log\n        if: always() && (steps.configure.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/config.log\n\n      - name: build\n        # Spawning processes seems to have a big overhead on this platform. Use a somewhat larger number of parallel processes to compensate for that.\n        run: |\n          make -C ./.build all -j8 V=1\n\n      - name: ccache status\n        continue-on-error: true\n        run: ccache -s\n\n      - name: save ccache\n        # Save the cache after we are done (successfully) building\n        uses: actions/cache/save@v5\n        with:\n          path: ${{ steps.ccache-prepare.outputs.ccachedir }}\n          key: ${{ steps.ccache-prepare.outputs.key }}\n\n      - name: check\n        id: run-test-suite\n        # Continuing on error in this step means that jobs will be \"green\" even\n        # if the test suite crashes.  But if we don't continue, we'll loose the\n        # ccache and other jobs will be cancelled, too.\n        # It would be nice if we could mark the job as \"yellow\" (and continue)\n        # in that case.  The second best thing is to display a warning in the\n        # job summary (see below).\n        continue-on-error: true\n        timeout-minutes: 60\n\n        # mkoctfile seems to have trouble when gcc is called via ccache. So,\n        # remove the directory with the ccache wrappers from PATH.\n\n        run: |\n          export PATH=$(echo \"$PATH\" | sed -e \"s|$MINGW_PREFIX/lib/ccache/bin:||g\")\n          ./.build/run-octave --no-init-file --no-history --no-gui-libs --eval \"version -blas, version -lapack\"\n          make -C ./.build check RUN_OCTAVE_OPTIONS=\"--no-gui-libs\" | tee ./test-suite.log\n\n      - name: display test suite log\n        if: always() && (steps.run-test-suite.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/test/fntests.log\n\n      - name: test history file creation\n        # see bug #62365\n        # Pipe to an interactive session to trigger appending the command to\n        # the history.  This will trigger the creation of a history file.\n        run:  |\n          echo \"history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')\" | ./.build/run-octave -i\n          [ -f ./a/b/c/history ] || echo \"::warning::Creating history file failed\"\n\n      - name: install\n        run: |\n          mkdir -p /c/octave/pkg\n          make -C ./.build DESTDIR=/c/octave/pkg install\n\n      - name: test stand-alone executable\n        continue-on-error: ${{ matrix.allow-error }}\n        run: |\n          unset CC\n          unset CXX\n          export PATH=$(echo \"$PATH\" | sed -e \"s|$MINGW_PREFIX/lib/ccache/bin:||g\")\n          export PATH=\"/c/octave/pkg/${{ matrix.mingw-prefix }}/bin:$PATH\"\n          cd examples/code\n          mkoctfile --link-stand-alone embedded.cc -o embedded\n          ./embedded.exe\n\n      - name: test Octave packages\n        continue-on-error: ${{ matrix.allow-error }}\n        env:\n          # colon separated list of packages\n          # reasons for including these packages in the CI tests:\n          # * control: builds .oct files from C++ and Fortran sources\n          # * stk: builds .mex files from C sources\n          PACKAGE_NAMES: \"control:stk\"\n        run: |\n          unset CC\n          unset CXX\n          export PATH=$(echo \"$PATH\" | sed -e \"s|$MINGW_PREFIX/lib/ccache/bin:||g\")\n          export PATH=\"/c/octave/pkg/${{ matrix.mingw-prefix }}/bin:$PATH\"\n          IFS=':' read -r -a packages <<< \"${PACKAGE_NAMES}\"\n          for package in \"${packages[@]}\"; do\n            printf \"   \\033[0;32m==>\\033[0m Octave package \\033[0;32m${package}\\033[0m\\n\"\n            echo \"::group::Install ${package}\"\n            octave --eval \"pkg install -verbose -forge ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test ${package}\"\n            octave --eval \"pkg test ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test log for ${package}\"\n            cat ${GITHUB_WORKSPACE}/fntests.log\n            echo \"::endgroup::\"\n           done\n\n      - name: analyze test suite results\n        # Make sure the test summary lists 0 \"FAIL\"s and no \"REGRESSION\"\n        run: |\n          [ -n \"$(grep -e \"FAIL\\s*0\" ./test-suite.log)\" ] || echo \"::warning::At least one test failed\"\n          [ -z \"$(grep -e \"REGRESSION\" ./test-suite.log)\" ] || echo \"::warning::At least one regression in test suite\"\n          echo Finished analyzing test suite results.\n\n      - name: compress build artifact\n        if: matrix.msystem == 'MINGW64'\n        continue-on-error: true\n        run: |\n          cd /c/octave/pkg\n          tar -cvzf octave.tar.gz *\n\n      - name: upload build artifact\n        if: matrix.msystem == 'MINGW64'\n        continue-on-error: true\n        uses: actions/upload-artifact@v6\n        with:\n          name: ${{ matrix.mingw-prefix }}-octave-${{ steps.ccache-prepare.outputs.timestamp }}\n          path: C:\\octave\\pkg\\octave.tar.gz\n          retention-days: 7\n"
  },
  {
    "path": ".github/workflows/make-ubuntu.yaml",
    "content": "name: make-ubuntu\non:\n  workflow_dispatch:\n  push:\nconcurrency: ci-ubuntu-${{ github.ref }}\n\njobs:\n\n  ubuntu:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      # Allow other runners in the matrix to continue if some fail\n      fail-fast: false\n\n      matrix:\n        # For available GitHub-hosted runners, see:\n        # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners\n        os: [ubuntu-22.04, ubuntu-24.04, ubuntu-24.04-arm]\n        compiler: [gcc, clang]\n        include:\n          - compiler: gcc\n            compiler-pkgs: \"g++ gcc\"\n            cc: \"gcc\"\n            cxx: \"g++\"\n            extra-config-flags: \"\"\n          - compiler: clang\n            compiler-pkgs: \"clang libc++-dev libc++abi-dev\"\n            cc: \"clang\"\n            cxx: \"clang++ -stdlib=libc++\"\n            extra-config-flags: \"--without-spqr --without-magick\"\n          # Clang seems to generally require less cache size (smaller object files?).\n          - ccache-max: 1.2G\n          - os: ubuntu-24.04\n            compiler: gcc\n            ccache-max: 1.2G\n          - os: ubuntu-22.04\n            compiler: gcc\n            ccache-max: 1.2G\n          - os: ubuntu-24.04-arm\n            compiler: gcc\n            ccache-max: 1.2G\n          - os: ubuntu-24.04\n            compiler: clang\n            ccache-max: 400M\n          - os: ubuntu-22.04\n            compiler: clang\n            ccache-max: 400M\n          - os: ubuntu-24.04-arm\n            compiler: clang\n            ccache-max: 400M\n\n    name: ${{ matrix.os }} ${{ matrix.compiler }}\n\n    env:\n      CC: ${{ matrix.cc }}\n      CXX: ${{ matrix.cxx }}\n\n    steps:\n      - name: get CPU information\n        run: lscpu\n\n      - name: checkout repository\n        uses: actions/checkout@v6\n\n      - name: install dependencies\n        env:\n          COMPILER_PKGS: ${{ matrix.compiler-pkgs }}\n        run: |\n          sudo apt -qq update\n          sudo apt install -y $COMPILER_PKGS autoconf automake bison ccache \\\n            dvipng epstool fig2dev flex gfortran gnuplot-x11 gperf gzip \\\n            icoutils libarpack2-dev libblas-dev libcurl4-gnutls-dev \\\n            libfftw3-dev libfltk1.3-dev libfontconfig1-dev libfreetype6-dev \\\n            libgl1-mesa-dev libgl2ps-dev libglpk-dev libgraphicsmagick++1-dev \\\n            libhdf5-dev liblapack-dev libosmesa6-dev libpcre2-dev \\\n            libqhull-dev libqscintilla2-qt5-dev libqrupdate-dev \\\n            libreadline-dev librsvg2-bin libsndfile1-dev libsuitesparse-dev \\\n            libsundials-dev libtool libxft-dev make openjdk-8-jdk \\\n            perl portaudio19-dev pstoedit qtbase5-dev qttools5-dev \\\n            qttools5-dev-tools rapidjson-dev rsync tar texinfo \\\n            texlive-latex-extra xvfb zlib1g-dev \\\n            ${{ (matrix.os != 'ubuntu-22.04' && matrix.compiler == 'clang') && 'libfast-float-dev' || '' }}\n\n      - name: prepare ccache\n        # create key with human readable timestamp\n        # used in action/cache/restore and action/cache/save steps\n        id: ccache-prepare\n        run: |\n          echo \"key=ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}:$(date +\"%Y-%m-%d_%H-%M-%S\"):${{ github.sha }}\" >> $GITHUB_OUTPUT\n\n      - name: restore ccache\n        # setup the github cache used to maintain the ccache from one job to the next\n        uses: actions/cache/restore@v5\n        with:\n          path: ~/.ccache\n          key: ${{ steps.ccache-prepare.outputs.key }}\n          restore-keys: |\n            ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}\n            ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/default\n\n      - name: configure ccache\n        env:\n          CCACHE_MAX: ${{ matrix.ccache-max }}\n        run: |\n          test -d ~/.ccache || mkdir ~/.ccache\n          echo \"max_size = $CCACHE_MAX\" >> ~/.ccache/ccache.conf\n          ccache -s\n          echo \"/usr/lib/ccache\" >> $GITHUB_PATH\n\n      - name: build fast-float\n        # There is no fast-float package for Ubuntu 22.04.\n        # We need it as a fallback for LLVM libc++ before version 20.\n        if: matrix.os == 'ubuntu-22.04' && matrix.compiler == 'clang'\n        run: |\n          mkdir -p fast-float && cd fast-float\n          printf \"::group::\\033[0;32m==>\\033[0m Download tarball\\n\"\n          wget -O fast-float-8.1.0.tar.gz https://github.com/fastfloat/fast_float/archive/refs/tags/v8.1.0.tar.gz\n          echo \"::endgroup::\"\n          printf \"::group::\\033[0;32m==>\\033[0m Unpack tarball\\n\"\n          tar zxvf fast-float-8.1.0.tar.gz\n          echo \"::endgroup::\"\n          printf \"::group::\\033[0;32m==>\\033[0m Configure\\n\"\n          mkdir -p build && cd build\n          cmake -DCMAKE_BUILD_TYPE=Release ../fast_float-8.1.0\n          echo \"::endgroup::\"\n          printf \"::group::\\033[0;32m==>\\033[0m Build\\n\"\n          cmake --build .\n          echo \"::endgroup::\"\n          printf \"::group::\\033[0;32m==>\\033[0m Install\\n\"\n          sudo cmake --install .\n          echo \"::endgroup::\"\n\n      - name: bootstrap\n        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap\n\n      - name: configure\n        id: configure\n        timeout-minutes: 30\n        run: |\n          echo $PATH\n          echo which ccache\n          which ccache\n          which $CC\n          echo $CC --version\n          $CC --version\n          which ${CXX% *}\n          echo ${CXX% *} --version\n          ${CXX% *} --version\n          which gfortran\n          echo gfortran --version\n          gfortran --version\n          mkdir .build\n          echo \"::group::Run configure script\"\n          cd .build && ../configure \\\n            CPPFLAGS=\"-I/usr/include/hdf5/serial -I/usr/include/suitesparse\" \\\n            LDFLAGS=\"-L/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/hdf5/serial\" \\\n            ${{ matrix.extra-config-flags }}\n          echo \"::endgroup::\"\n\n      - name: display config.log\n        if: always() && (steps.configure.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/config.log\n\n      - name: build\n        # Parallel make seems to fail intermittently when creating the figures\n        # for the manual. The error message says it fails to connect to a\n        # display. Maybe an xvfb issue?\n        # Use single job make for now which seems to work more reliably.\n        run: XDG_RUNTIME_DIR=$RUNNER_TEMP xvfb-run -a make -C ./.build all V=1\n\n      - name: ccache status\n        run: ccache -s\n\n      - name: save ccache\n        # Save the cache after we are done (successfully) building\n        uses: actions/cache/save@v5\n        with:\n          path: ~/.ccache\n          key: ${{ steps.ccache-prepare.outputs.key }}\n\n      - name: check\n        id: run-test-suite\n        timeout-minutes: 60\n        run: |\n          ./.build/run-octave --no-init-file --no-history --eval \"version -blas, version -lapack\"\n          XDG_RUNTIME_DIR=$RUNNER_TEMP \\\n            xvfb-run -a make -C ./.build check | tee ./test-suite.log\n\n      - name: display test suite log\n        if: always() && (steps.run-test-suite.outcome != 'skipped')\n        continue-on-error: true\n        # Displaying the log shouldn't take long. Cancel the step if it does.\n        timeout-minutes: 5\n        run: cat ./.build/test/fntests.log\n\n      - name: test history file creation\n        # see bug #62365\n        # Pipe to an interactive session to trigger appending the command to\n        # the history.  This will trigger the creation of a history file.\n        run:  |\n          echo \"history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')\" | ./.build/run-octave -i\n          [ -f ./a/b/c/history ] || echo \"::warning::Creating history file failed\"\n\n      - name: install\n        run: |\n          sudo make -C ./.build install\n\n      - name: test stand-alone executable\n        run: |\n          unset CC\n          unset CXX\n          cd examples/code\n          mkoctfile --link-stand-alone embedded.cc -o embedded\n          LD_LIBRARY_PATH=\"/usr/local/lib/octave/$(octave --eval \"disp(version())\")\" \\\n            ./embedded\n\n      - name: test Octave packages\n        env:\n          # colon separated list of packages\n          # reasons for including these packages in the CI tests:\n          # * control: builds .oct files from C++ and Fortran sources\n          # * stk: builds .mex files from C sources\n          PACKAGE_NAMES: \"control:stk\"\n        run: |\n          unset CC\n          unset CXX\n          IFS=':' read -r -a packages <<< \"${PACKAGE_NAMES}\"\n          for package in \"${packages[@]}\"; do\n            printf \"   \\033[0;32m==>\\033[0m Octave package \\033[0;32m${package}\\033[0m\\n\"\n            echo \"::group::Install ${package}\"\n            octave --eval \"pkg install -verbose -forge ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test ${package}\"\n            octave --eval \"pkg test ${package}\"\n            echo \"::endgroup::\"\n            echo \"::group::Test log for ${package}\"\n            cat ${GITHUB_WORKSPACE}/fntests.log\n            echo \"::endgroup::\"\n           done\n\n      - name: analyze test suite results\n        # Make sure the test summary lists 0 \"FAIL\"s and no \"REGRESSION\"\n        run:  |\n          [ -n \"$(grep -e \"FAIL\\s*0\" ./test-suite.log)\" ] || exit 1\n          [ -z \"$(grep -e \"REGRESSION\" ./test-suite.log)\" ] || exit 1\n          echo No unknown failing tests.\n"
  },
  {
    "path": ".hgignore",
    "content": "syntax: regexp\n## The recurrent (^|/) idiom in the regexps below should be understood\n## to mean \"at any directory\" while the ^ idiom means \"from the\n## project's top-level directory\".\n\n## gnulib related files\n(^|/)gnulib$\n# This directory gets created by gnulib during the build.\n(^|/)libgnu$\n# gnulib makes these silly backup files.\n.~$\n\n## m4 related files\n# This directory mostly contains cruft during build time, but it does\n# contain some Octave code, so be more careful about what we ignore here.\n^m4/(?!ax_).+\\.m4$\n\n## Autoconf, Automake automatically generated files\n^aclocal\\.m4$\n^autom4te\\.cache$\n^config\\.in\\.h$\n^configure$\n(^|/)config.cache$\n(^|/)config.h$\n(^|/)config.log$\n(^|/)config.status$\n\n(^|/)Makefile\\.in$\n^INSTALL$\n\n## CMake associated files\n# Octave doesn't use CMake, but some IDEs use this index file to indicate\n# what files are part of a project (e.g., CLion).  Ignore it (bug #55901).\n^CMakeLists.txt$\n\n## Emacs associated files\n(^|/)TAGS$\n(^|/)semantic.cache$\n\n## Scripts associated with building Octave\n^build-aux/config\\.(guess|rpath|sub)$\n(^|/)build-aux/check-subst-vars\\.sh$\n^build-aux/compile$\n^build-aux/depcomp$\n(^|/)build-aux/find-defun-files\\.sh$\n(^|/)build-aux/find-files-with-tests\\.sh$\n^build-aux/install-sh$\n^build-aux/ltmain\\.sh$\n^build-aux/mdate-sh$\n^build-aux/missing$\n^build-aux/move-if-change$\n(^|/)build-aux/subst-config-vals\\.sh$\n(^|/)build-aux/subst-cross-config-vals\\.sh$\n(^|/)build-aux/subst-script-vals\\.sh$\n^build-aux/texinfo\\.tex$\n^build-aux/ylwrap$\n\n## Mercurial associated files\n(^|/)HG-ID$\n\n## Timestamp files used in build process\n.*/\\.dirstamp$\n.*/\\.octave-dirstamp$\n\n## Intermediate compilation results for libraries\n\\.la$\n.*/\\.libs/\n\\.Plo$\n\\.Po$\n\n## DLDFCN associated files\n^libinterp/dldfcn/module\\.mk$\n(^|/)libinterp/dldfcn/PKG_ADD$\n(^|/)libinterp/dldfcn/.*\\.oct$\n\n## liboctave/ directory associated patterns\n# E.g., liboctave/operators/smx-op-inc.mk\n^liboctave/operators/\\w+-op-\\w+\\.mk$\n\n## scripts/ directory associated patterns\n# Package files\n(^|/)scripts/.*/PKG_ADD$\n# Java files\n(^|/)scripts/java/octave\\.jar$\n(^|/)scripts/java/org/octave/.*\\.class$\n\n## libgui/ directory associated patterns\n# Files generated by moc tool\n(^|/)libgui/.*/moc-.*\\.(cc|h)$\n(^|/)libgui/languages/.*\\.qm$\n(^|/)libgui/languages/__octave_temp_gui_sources__/*\n\n## Ignore patterns associated with documentation\n# Info generated files\n# E.g., doc/faq/OctaveFAQ.info, doc/interpreter/octave.info-4\n^doc/\\w+/\\w+\\.info(-\\d+)?$\n\n# Texinfo created temporary directories\n(^|/)doc/(interpreter|liboctave)/(octave|liboctave)\\.t2(d|p)/\n# Texinfo created files\n(^|/)doc/interpreter/.*\\.texi$\n\n# DOCSTRINGS files built in the source tree\n(^|/)(libinterp|scripts)/DOCSTRINGS$\n\n# Generated HTML directories\n(^|/)doc/interpreter/octave\\.html/\n(^|/)doc/liboctave/liboctave\\.html/\n\n# Miscellaneous auto-generated files\n(^|/)doc/interpreter/octave\\.dvi$\n(^|/)doc/interpreter/octave\\.ps$\n(^|/)doc/interpreter/doc-cache$\n(^|/)doc/interpreter/octave_interpreter\\.q(ch|hc)$\n\n# Images and scripts for documentation\n^doc/interpreter/images\\.mk$\n(^|/)doc/interpreter/.*\\.eps$\n(^|/)doc/interpreter/.*\\.pdf$\n(^|/)doc/interpreter/.*\\.png$\n(^|/)doc/interpreter/.*\\.txt$\n\n# timestamps for doc directory\n^doc/\\w+/stamp-(vti|\\d+)$\n^doc/\\w+/version-\\w+\\.texi$\n\n## Test associated patterns\n-tst$\n\n^.build/*\n"
  },
  {
    "path": ".hgtags",
    "content": "d56e0d75e7c9760f2a3e750c2d71a5c52bb76b98 ss-2-1-45\ndece11da64ed86ac2347f48ffa13fd046bef7de3 ss-2-1-52\ne759d01692dbb69ff28b6d70940239d93ff77a9d ss-2-1-53\nadf8d68d71438b8b394cbbce59e817a557db5ecd ss-2-1-54\n6279796dc2b9ee28e0624b4b91bba1eec6ed292d ss-2-1-55\nd0aa1a59b73b879fe18eafb8df54e451f870058c ss-2-1-56\nc1cdf2a32cdbf4e0d68aead4bfa597106e844989 ss-2-1-57\nce01dbd7e026c095d9e50beac529e8e955a303f8 ss-2-1-58\n1c65a8e44ef95fd4b2b11eb19071e3ecbbe77b76 ss-2-1-59\n1e6f653ef1e332fbaab48ac44149b0eb2d3bcfc8 ss-2-1-61\n1bf9abc0256be1800b553acdb30b099b4c2a3abb ss-2-1-62\n8386cf9811ee90243a965a3782b1b4f6cb107845 ss-2-1-63\n5a92c3177fc6c038bc93745f6ebc6a055e602b96 before-gnuplot-split\ne2ed74b9bfa052ce499b7f419e8d204123c49af0 after-gnuplot-split\n996a08a3eb068ce8002f54170fae755f9142d9a4 ss-2-9-0\n5c2f5830179082f18658d5a9e68087938444581e ss-2-9-1\n57b5030f5737ef9a1ac588b32e6c828358fac801 before-64-bit-merge\n9302581b820d71e6e3ae722b68e5923aebd46157 ss-2-9-2\n06585668a971b21818cacedbab1e11a98c11c5a0 ss-2-9-3\nf16c05db625059770b94eec0af027bbe74d2ce62 ss-2-9-4\ncda6a105ae9a30f9cd8032b1f49c2cfecfc04f6c before-ov-branch\nacb4a1e0b311c47bc957a48bf6af7f77e9c80fab ss-2-9-6\nb2e1be30c8e94902e6557c1edba2c4f37ff7bdf8 ss-2-9-7\nd542d919783961dce51ee8fc06f65b8f2cfe4156 ss-2-9-8\n60f9ced8ab534e65f27d95a712d97ba6add6cd8d ss-2-9-9\n12b676a0b18395af2fa0ccceb516447d8be6ad03 before-graphics-branch\na848b846cb3ac279782b7fef8270a62ca4578539 ss-2-9-10\n3e2cfed6c87e2019cb1584211068b9c581331ccb before-object-branch\n10da0f6d85c260bb5f640436e42d633a57ccda9b ss-2-9-11\ndb6d908e8a03a42760a45c7fd29eae074e505f7c ss-2-9-12\nafbd31bb7b4e001c6c16d41eb908aa66bed64352 ss-2-9-13\nfc55a5e1760b832a672d9de3b53888a3d6793d21 ss-2-9-14\n0b91144f9533b05d14fb5692ed67d8c6f500230f ss-2-9-15\n5608935ff5228a90d34fa80dce3dab2462d20fd3 ss-2-9-16\n77de8319c337b39a477d5433348e4597ad61abe0 ss-2-9-17\n9f02c32eb70d3e6d0c42a2fd5f3b862f4d6c6bcc ss-2-9-18\n89d546610556ee47ec634ab8c3e441e1db248873 ss-2-9-19\n274d9642ac1032fcc4996a3cac80cfe5fd20f8a4 release-3-0-0\naf10baa6391596c3713385d7b6c66c93ee935e87 ss-3-1-50\na5d1e27ee1f4c3fd66c489e83fdb40f92bf1bf43 ss-3-1-51\n739141cde75a22b9ac9b5b327ea30c61fd357748 ss-3-1-52\nbd1b1fe9c6e952202bf5878cd042a168f6df6ddd ss-3-1-53\n3c3cbe8f18e03c73cc34494c8037d8a45a30bf7d ss-3-1-54\n5e276a0b999747b72af34e72eb63f64640da6399 ss-3-1-55\na1d20052517a950033896f5a876de8f3ee520138 release-3-2-0\n74be4b7273e43952e1afcd9ad979d35667c7f82e ss-3-3-50\n79a56d0a6a0d693ebf461c456951b20dfbcde140 ss-3-3-51\n229675bb7647f7e7e499bcb5acacc8eabe7f3697 ss-3-3-52\n6c69a7c39039bccd5a2fe481fcc7f896c82b160b ss-3-3-53\n3cbc0d77db48aec32bcb202d09a036d2cb9cc3b9 ss-3-3-53\nbd2643f0ce57d070963bedd48857405f6924aa85 ss-3-3-54\n695141f1c05cf1b240592bdd18e7a1503bb2a539 ss-3-3-55\n901d466ee55ac902a875ec0ade6f1eccef0841dc release-3-4-1\n3666e8e6f96e6899b8306d6ea9614aadf0500d67 release-3-4-2\nb0e70a71647b671ebcfa7a79af1ae6d3c0f52065 release-3-4-3\n3781981be535e80d44c85373b8fdaa60ca5cd097 ss-3-5-90\nff5588774680d4f54567311fc109c8e351950f1c ss-3-5-91\na737b3fb9c4d89d3694da6b4e623aeee64b212e1 ss-3-5-92\n72aebe6196414e38ef802469ff6e238f914f04c9 rc-3-6-0-0\n64d9f33313cc8c691974bcd123357e24bccbabdc rc-3-6-0-1\n704f7895eef03008dd79848eb9da4bfb40787d73 release-3.6.0\n95c43fc8dbe1a07a46fefb3372df5b2309d874fd rc-3-6-1-0\n0000000000000000000000000000000000000000 release-3-2-4\ne320928eeb3aa2370b792e83dafc3e0ddecdc871 release-3-2-4\nba4d6343524b406b0d15aee34579f80783581c54 release-3-6-1\n704f7895eef03008dd79848eb9da4bfb40787d73 release-3-6-0\nf947d2922febf12dcd1fb6e21b356756ecb54e55 rc-3-6-2-0\n4460c4fb20e6a5d3b1972fa737d4e00eb921545a rc-3-6-2-2\n551566201318bf615b27c60ccf9368f4844008bd release-3-6-2\na95432e7309ca6fc776c02939264bb6d443f3525 release-3-6-3\n2e8eb9ac43a5f8cfaf0423814a312ed47cb80485 rc-3-6-4-0\ndf1aceb8f0bc6b5b5062907931cc663467f57d93 ss-3-7-1\n858cbf6fc2ec1c232f5cf1d75dc344439b39a89c rc-3-6-4-1\nfaefa1bea8ddae3cab170afdeab68d3d15c4e623 ss-3-7-2\n0000000000000000000000000000000000000000 ss-3-7-2\n23a7661e529ae9bfc91693618f8c314c31f695ca ss-3-7-2\ncc5a7d1233f3acea85648baeb754fc0e8f225225 rc-3-6-4-2\nb29b10fbb7448cdfe29322446e1a589e7fe1a40a release-3-6-4\n4e50bd2946d8563d3e201cc04b3ba0720c991b06 ss-3-7-4\n608e307b49149b32a6d09c2f06493d04d3af9be4 ss-3-7-5\n3a9efb68272df556dccb84c87933dd8238e88902 ss-3-7-6\ncc13924a4266fb0359f59fabdce11071e6051d48 ss-3-7-7\nd734216aa2b1022c190e6b07d7ccdd59fe15678f rc-3-8-0-1\nf1fa148766d623f7f24cf541ea8b88d8c1b63d33 rc-3-8-0-2\nb72bcf5f78cc2231e9bf2735d3b8d92779fc4dff release-3-8-0\n85d31344fb23725791bc687337295d47416b9c17 rc-3-8-1-2\n02ce68d63fba31cd14ac060c087212a032ae3202 rc-3-8-1-3\ndd669c2ae76c167613f54d6f4db0130fa2124cac rc-3-8-1-4\n43cc202335dc4a53a3d8fc9ca90acaa81d2e63d3 release-3-8-1\n492c5614953571a0b07f4c1621cc7bc5c85c0251 rc-3-8-2-1\n46df2c7b8f4dec400ce353370f2e47a02926026d rc-3-8-2-2\na66548dc07b0fc9b7d37a4be065aa15e8243c96a release-3-8-2\n52d2bbf49c922440621b42b1c1679f0e55462485 rc-4-0-0-1\neba80000fa0dad32ba0f1cd767dd826d1ce1aba6 rc-4-0-0-2\n065f933ef08318e40b81f7fe75236e6175088117 rc-4-0-0-3\n42bb3a776c9fcc008669f382d2409297c4a901b3 rc-4-0-0-4\n3ccc2d02e64b61c6827009d42e5b12274e7ba5fc release-4-0-0\n20b17dda0e0c838646dfdccec153ec8cdf6d3c37 rc-4-0-1-1\n0cfcc178432bfc7cfdef5dca96e74ec5884ba752 rc-4-0-1-2\na58d5e6df908199c4aea83f78077b81289d2a0ad rc-4-0-1-3\n2b66f30a0de7a09801c2a3566021cde7e194d3d3 rc-4-0-1-4\n5162cdfb56d8e31ad00dc260a26d1c92c69c2acf release-4-0-1\nacaf1e137c5e6f201a6689a99a6568d0dfe9e9ed release-4-0-2\n00f7b278defd1b6b911cde1ff20390fb298f4c5b release-4-0-3\nb8eeca55fa8113853a19b1b1ab4d0bb6471dea18 rc-4-2-0-1\n9d50627498141d150755d18ab8e71a3220e40147 rc-4-2-0-2\n96817eafc7997e19a1f89873c05098e08fea1c02 rc-4-2-0-3\n69ac19073ae630b276ff7788b78f72782f281657 rc-4-2-0-4\n708a4fcb73820484a3af94dd4d18453c4d9b29c9 release-4-2-0\n1327ea4f5a931a6cc2a6d4790af58cf16de4702b release-4-2-1\n94f8e2b5a88b79974084c0ae541cacbcc62d64f6 release-4-2-2\na5ad9c053e41ed39a8c69ff99936cbcf18256abf rc-4-3-90\nff59be58f0282e418fb3447d5442fa1d618cfe10 rc-4-3-91\n4c14c002cabeb60cf693d5a032b6285f92804643 rc-4-3-92\ncf84db75ab57d4fc5d18682c6ecf9d2e1f66ea94 release-4-4-0\n1f46d371968c5c2e9d5fac537046db8005b71e41 release-4-4-1\n82865ccb62c2aa2f1273683b8343a80e2e6a0e83 rc-5-0-90\naf47f245a2ada829fa87f339bbe8e7c64a189bda rc-5-0-91\nd05d6eebde105895c0972d8bb8bc7f090295cb86 release-5-1-0\nec0690a6955c8d5236b29b975c09a1f2a5a1559c rc-5-1-90\neb46a9f471647626d3a199e40d0c235d54e2b256 release-5-2-0\n844b3b9bab7a137c08cbec7cb0ae3bca2ae0b70d rc-6-0-90\nc67f39732d1441a685a524586ebcf2246641b4f5 rc-6-0-92\n9f39338a23cbbff9bb2681d536451340cb08df12 release-6-1-0\n5cfdf97c5350d41018311dace50e3486176eefa6 release-6-2-0\n55008004bb9a6e95256d57e882e3716ac45b15ee rc-6-1-90\n9d70a797d54a194b185f89829b0d9cefb93e58ff rc-6-2-90\n754013c3658760136fe473911ba96165a07cb1f5 release-6-3-0\n3dc9decc98f97d0b05fff9dbb66b2400d6139830 rc-6-3-90\n8d7671609955afabf79ceff678cc41eea61583f2 release-6-4-0\n347dbc9049d55b63435d710e1d9d826cbfe5e54c rc-7-0-90\n266610d855194b2a55e6b501ccc302e6c0d8f6d0 rc-7-0-92\n04120d65778a403e11ac4280bf53f330eded75e3 release-7-1-0\n48fcfbaea2cdcfffaf1058c95832a33f70419a6f rc-7-1-90\n6c1e310b223029c3a21abe9629f4200560024c3a release-7-2-0\n2c037ce004502260228925e651dc077573366ba2 release-7-3-0\n74aa32d5fd08ec0398ac8261d4bf5dbd75e8f6a4 rc-8-0-90\n75b1efe727d495ae579b9e27a620219dc72d9205 release-8-1-0\nfdadf31961bb5b089f5a2b7cd660351434b31de0 release-8-2-0\n6fc591af58baccd1f9be398245eda017374d3283 release-8-3-0\n78c13a2594f359474f28a93e43b288c9b40afa2c release-8-4-0\n99d90c3bd48561b7de68077ac1e116f196f4dd4b rc-9-0-90\nd0c18b1446dfce3dd2c9953fb8d51341b680f384 release-9-1-0\n75ef583dd829d9190a90295b7e530364c3ff0ed7 rc-9-1-90\nf7f956555e4ab8a05d52a9be4c24209670b870d2 release-9-2-0\n5854a65df8f59c0071eea5c51ed386ab779729bc release-9-3-0\ndf465cbba05afa74d56e66204badaff3c50fd503 release-9-4-0\n520f82ccab593e1d1c63c1319ab0ee08ecc5f382 rc-10-0-90\n417c47651ed55ca2c397500f7a598ab583bc38a2 release-10-1-0\n8d42ee70e124180e1ef00e9be2e080b71fd92099 release-10-2-0\n8ee1afeed21ef0e5995416e41348457d966abe2a release-10-3-0\n1b2865990371a5896f337cb51c3b45a5538b2807 rc-11-0-90\n0f2de96b6e238a85b8c277a8ca63786abbf3203e rc-11-0-91\n8d2d7049b8a9c51023dc665c17e2c26323db55d0 rc-11-0-92\nfa4747e9b5c0790d5c647bf3106a1b76753e9e93 remove\n0f2de96b6e238a85b8c277a8ca63786abbf3203e rc-11-0-91\nfa4747e9b5c0790d5c647bf3106a1b76753e9e93 rc-11-0-91\nfa4747e9b5c0790d5c647bf3106a1b76753e9e93 remove\n0000000000000000000000000000000000000000 remove\nfa4747e9b5c0790d5c647bf3106a1b76753e9e93 rc-11-0-91\n0000000000000000000000000000000000000000 rc-11-0-91\n4fde0ba0d88a06e97d5f6befa235f006de64c9fd release-11-1-0\n"
  },
  {
    "path": "CITATION",
    "content": "To cite GNU Octave in publications use:\n\n  John W. Eaton, David Bateman, Søren Hauberg, Rik Wehbring (2026).\n  GNU Octave version 11.1.0 manual: a high-level interactive language for\n  numerical computations.\n  URL https://www.gnu.org/software/octave/doc/v11.1.0/\n\nA BibTeX entry for LaTeX users is:\n\n  @manual{,\n    title     = {{GNU Octave} version 11.1.0 manual: a high-level interactive language for numerical computations},\n    author    = {John W. Eaton and David Bateman and S{\\o}ren Hauberg and Rik Wehbring},\n    year      = {2026},\n    url       = {https://www.gnu.org/software/octave/doc/v11.1.0/},\n  }\n\nWe have invested a lot of time and effort in creating GNU Octave, please\ncite it when using it.  See also 'citation pkgname' for citing Octave packages.\n"
  },
  {
    "path": "COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "COPYRIGHT.md",
    "content": "\nOctave is free software: you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nOctave is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with Octave; see the file COPYING.  If not, see\n<https://www.gnu.org/licenses/>.\n\n\nCopyright:\n\n- 1987-1988, 1991-1997, 2003-2018  Free Software Foundation\n- 1992-2024  John W. Eaton\n- 1993  Fook Fah Yap\n- 1993  Friedrich Leisch\n- 1993  Gerhard Kircher\n- 1993  John C. Campbell\n- 1993  Per Bothner\n- 1993  R. Bruce Tenison\n- 1993  Teresa Twaroch\n- 1993, 1995  Auburn University\n- 1993, 1995, 1998-2002, 2004, 2006-2007  A. Scottedward Hodel\n- 1993, 1996-1999, 2001-2002, 2005-2006  Kurt Hornik\n- 1993-1997  O. Weber\n- 1993-1998  Karl Berry\n- 1994  Castor Fu\n- 1994  Mark Odegard\n- 1994  Romolo Manfredini\n- 1994, 2009  Anthony Richardson\n- 1994-1995  David Clem\n- 1994-1997  Frederick (Rick) A Niles\n- 1995  Paul Eggert\n- 1995  Thomas Baier\n- 1995  Vinayak Dutt\n- 1995, 1997  Klaus Gebhardt\n- 1997  Ram'on Garc'ia Fern'andez\n- 1997  Rex A. Dieter\n- 1997, 1999-2000, 2008  Rolf Fabian\n- 1997-1999, 2001-2003  Mumit Khan\n- 1998  Eric Norum\n- 1998  Philippe Defert\n- 1998  Richard Allan Holcombe\n- 1998  Roman Hodek\n- 1998  Tomislav Goles\n- 1998, 2000  Georg Thimm\n- 1998, 2000  John Smith\n- 1998-2000, 2002-2006, 2012  Andy Adler\n- 1999  Daniel Calvelo\n- 1999  Eduardo Gallestey\n- 1999  Geoff Jacobsen\n- 1999  James B. Rawlings\n- 1999  James Macnicol\n- 1999  Massimo Lorenzin\n- 1999-2000  Joao Cardoso\n- 1999-2000  Stephen Eglen\n- 1999-2002  Ben Sapp\n- 2000  Joerg Specht\n- 2000  Marcus Brinkmann\n- 2000  Michael Reifenberger\n- 2000  Thomas Walter\n- 2000, 2002, 2012  Steven G. Johnson\n- 2000, 2002-2004  Teemu Ikonen\n- 2000, 2003  Cyril Humbert\n- 2000, 2003, 2005  Mats Jansson\n- 2000, 2003, 2007-2008  Gabriele Pannocchia\n- 2000, 2004, 2006  Etienne Grossmann\n- 2000, 2005, 2021  James R. Van Zandt\n- 2000-2001  Matthew W. Roberts\n- 2000-2002  Cai Jianming\n- 2000-2002, 2007-2011  Kai Habel\n- 2000-2007  Paul Kienzle\n- 2001  Albert Chin-A-Young\n- 2001  Christoph Spiel\n- 2001  David Livings\n- 2001  Heinz Bauschke\n- 2001  Ondrej Popp\n- 2001  Ross Lippert\n- 2001  Thomas Stuart\n- 2001, 2005-2009, 2012-2016, 2022  Rafael Laboissiere\n- 2001, 2007  Jean-Francois Cardoso\n- 2001-2003  Python Software Foundation\n- 2002  David Billinghurst\n- 2002  Dirk Laurie\n- 2002  JD Cole\n- 2002  Jeff Cunningham\n- 2002  Matt Tenny\n- 2002  Nicholas Piper\n- 2002  Nix\n- 2002  Peter Van Wieren\n- 2002, 2006-2009  Francesco Potortì\n- 2002, 2017  Andreas Stahel\n- 2002, 2017  Bill Lash\n- 2002-2003  Dirk Eddelbuettel\n- 2002-2003, 2007  Joseph P. Skudlarek\n- 2002-2004  Per Persson\n- 2003  Aaron A. King\n- 2003  Danilo Piazzalunga\n- 2003  David Castelow\n- 2003  Duncan Temple Lang\n- 2003  Eric S. Raymond\n- 2003  Heine Kolltveit\n- 2003  Lute Kamstra\n- 2003  Melqart\n- 2003  Richard Stallman\n- 2003  Roger Banks\n- 2003  Russell Standish\n- 2003  Stefan Monnier\n- 2003  Thorsten Ohl\n- 2003, 2005  Arno J. Klaassen\n- 2003, 2008, 2010-2011  Alois Schlögl\n- 2003, 2008-2010, 2012, 2014-2015, 2018-2019  Doug Stewart\n- 2003-2004  Al Niessner\n- 2003-2004  Petter Risholm\n- 2003-2007  Quentin H. Spencer\n- 2003-2013, 2015  David Bateman\n- 2004  Balint Reczey\n- 2004  Claude Lacoursiere\n- 2004  David Hoover\n- 2004  Federico Zenith\n- 2004  Fredrik Lingvall\n- 2004  Glenn Golden\n- 2004  Hans Ekkehard Plesser\n- 2004  Heikki Junes\n- 2004  Jakub Bogusz\n- 2004  Martin Dalecki\n- 2004  Oyvind Kristiansen\n- 2004  Volker Kuhlmann\n- 2004, 2007-2010  Shai Ayal\n- 2004, 2011, 2015, 2018  Orion Poplawski\n- 2004-2005  Stefan van der Walt\n- 2004-2006  Keith Goodman\n- 2004-2006, 2008, 2010-2012  Pascal A. Dupuis\n- 2005  Antoine Moreau\n- 2005  Benjamin Hall\n- 2005  Clinton Chee\n- 2005  Daniel\n- 2005  Driss Ghaddab\n- 2005  Erik de Castro Lopo\n- 2005  Ivana Varekova\n- 2005  Joel Andersson\n- 2005  Julius Smith\n- 2005  Kevin Ruland\n- 2005  Ludwig Schwardt\n- 2005  Miroslaw Kwasniak\n- 2005  Mohamed Kamoun\n- 2005  Nicolo' Giorgetti\n- 2005  Orestes Mas\n- 2005  Shan G. Smith\n- 2005  Todd Neal\n- 2005  Tom Holroyd\n- 2005  Toni Saarela\n- 2005  Walter Landry\n- 2005  cctsim\n- 2005, 2007  Michael Zeising\n- 2005, 2007-2009, 2012-2018, 2020  Daniel J. Sebald\n- 2005, 2010  Ben Barrowes\n- 2005-2006  Jorge Barros de Abreu\n- 2005-2006  William Poetra Yoga Hadisoeseno\n- 2005-2006, 2008, 2012  Dmitri A. Sergatskov\n- 2005-2008  Bill Denney\n- 2005-2010  Søren Hauberg\n- 2006  Atsushi Kajita\n- 2006  Christopher Hulbert\n- 2006  Don Bindner\n- 2006  Geoffrey Knauth\n- 2006  Henry Mollet\n- 2006  Jim Peterson\n- 2006  Kai Labusch\n- 2006  Ken Kouno\n- 2006  Larrie Carr\n- 2006  Martin Costabel\n- 2006  Stephen Fegan\n- 2006  Yozo Hida\n- 2006, 2011  Michael Creel\n- 2006-2007  Arno Onken\n- 2006-2007  Bob Weigel\n- 2006-2007  Luis F. Ortiz\n- 2006-2007, 2009  Olli Saarela\n- 2006-2008  Juhani Saastamoinen\n- 2006-2008, 2010  Kim Hansen\n- 2006-2009  Alexander Barth\n- 2006-2009  Thomas Treichl\n- 2006-2009, 2011  Benjamin Lindner\n- 2006-2011  Thomas Weber\n- 2006-2015  Michael Goffioul\n- 2007  Alex Zvoleff\n- 2007  Alexander Klimov\n- 2007  Aquil H. Abdullah\n- 2007  Baylis Shanks\n- 2007  Christian Cornelssen\n- 2007  Christof Zeile\n- 2007  Christoph Mayer\n- 2007  Claudio Belotti\n- 2007  D. Martin\n- 2007  Donald Parsons\n- 2007  Geordie McBain\n- 2007  Jim Langston\n- 2007  Kristan Onu\n- 2007  Laurent Mazet\n- 2007  Luther Tychonievich\n- 2007  Marcus W. Reble\n- 2007  Matthias Drochner\n- 2007  Michael Weitzel\n- 2007  Moritz Borgmann\n- 2007  Peter A. Gustafson\n- 2007  Sebastian Schubert\n- 2007  Steve M. Robbins\n- 2007  Steven Mestdagh\n- 2007  Tarmigan Casebolt\n- 2007  Thomas Kasper\n- 2007  Ulrich Tipp\n- 2007  Utkarsh Upadhyay\n- 2007  Vittoria Rezzonico\n- 2007  Zhi Wang\n- 2007, 2009  Joel Keay\n- 2007, 2009-2015, 2017-2018, 2022  Olaf Till\n- 2007-2008  Muthiah Annamalai\n- 2007-2009  Brian Gough\n- 2007-2009  Jason Riedy\n- 2007-2013, 2015-2019, 2023  Marco Caliari\n- 2007-2013, 2018  John P. Swensen\n- 2007-2016, 2018-2020  Carlo de Falco\n- 2007-2016, 2019  Ben Abbott\n- 2008  Emil Lucretiu\n- 2008  G. (Gert) van Antwerpen\n- 2008  James Packer\n- 2008  Jarkko Kaleva\n- 2008  Jonathan Stickel\n- 2008  Julian Schnidder\n- 2008  Julien Pommier\n- 2008  Krzesimir Nowak\n- 2008  Maciek Gajewski\n- 2008  Mark van Rossum\n- 2008  Martin Weiser\n- 2008  Primozz Peterlin\n- 2008  Richard Bovey\n- 2008  Ryan Hinton\n- 2008  Sebastien Loisel\n- 2008  Tetsuro KURITA\n- 2008  Thomas L. Scofield\n- 2008  Timo Lindfors\n- 2008, 2010  Brett Stewart\n- 2008, 2010-2012  Konstantinos Poulios\n- 2008, 2011, 2013-2019  Andreas Weber\n- 2008, 2011-2012  Kris Thielemans\n- 2008, 2018  Dave Goel\n- 2008-2009  Ivan Sutoris\n- 2008-2009  Radek Salac\n- 2008-2010  Ryan Rusaw\n- 2008-2010  VZLU Prague\n- 2008-2011  Jaroslav Hajek\n- 2008-2011  Thorsten Meyer\n- 2008-2011, 2015-2016, 2018-2019  Tatsuro Matsuoka\n- 2008-2013, 2018  Marco Atzeri\n- 2008-2015, 2017  Michael D. Godfrey\n- 2009  Aleksej Saushev\n- 2009  Alexander Mamonov\n- 2009  Ansgar Burchardt\n- 2009  Aravindh Krishnamoorthy\n- 2009  Bernard Desgraups\n- 2009  Bertrand Roessli\n- 2009  Carmine Paolino\n- 2009  Carsten Clark\n- 2009  Christophe Tournery\n- 2009  Daniel Gualberto\n- 2009  E. Joshua Rigler\n- 2009  Eric Chassande-Mottin\n- 2009  Frederick Umminger\n- 2009  Joe Rothweiler\n- 2009  Kacper Kowalik\n- 2009  Kai NODA\n- 2009  Kristian Rumberg\n- 2009  Nokia Corporation and/or its subsidiary(-ies).\n- 2009  Peter L. Søndergaard\n- 2009  Peter O'Gorman\n- 2009  Pieter Eendebak\n- 2009  Rob Mahurin\n- 2009  Robert Millan\n- 2009  Stefan Hepp\n- 2009  Steffen Groot\n- 2009  Steven Verstoep\n- 2009  Thomas D. Dean\n- 2009, 2011  Lukas Reichlin\n- 2009, 2011-2012  Robert T. Short\n- 2009-2010, 2012  Martin Helm\n- 2009-2011  David Grundberg\n- 2009-2011  Petr Mikulik\n- 2009-2024  Rik Wehbring\n- 2010  Brad Froehle\n- 2010  Christos Dimitrakakis\n- 2010  Daisuke TAKAGO\n- 2010  David Gesswein\n- 2010  Gunnar Farnebäck\n- 2010  Joshua Redstone\n- 2010  Judd Storrs\n- 2010  Jyh-Miin Lin\n- 2010  Liam Groener\n- 2010  Marc Vinyals\n- 2010  Pedro Gonnet\n- 2010  Peter van den Biggelaar\n- 2010  Qianqian Fang\n- 2010-2012  Iain Murray\n- 2010-2017  Jordi Gutiérrez Hermoso\n- 2010  Nicholas J. Higham\n- 2010  Awad H. Al-Mohy\n- 2011  Alexander Klein\n- 2011  Andriy Shinkarchuck\n- 2011  Andy Buckle\n- 2011  David Finkel\n- 2011  David Wells\n- 2011  Fabian Deutsch\n- 2011  Giles Anderson\n- 2011  Hannes Müller\n- 2011  John Bradshaw\n- 2011  Karsten Trulsen\n- 2011  Matthias Jüschke\n- 2011  Patrick Häcker\n- 2011  Paul Boven\n- 2011  Richard Campbell\n- 2011  Roman Belov\n- 2011  Sean Young\n- 2011  Vanya Sergeev\n- 2011-2012  Fotios Kasolis\n- 2011-2012  Jacob Dawid\n- 2011-2012  Jarno Rajahalme\n- 2011-2012  John Hunt\n- 2011-2012, 2014, 2016  Daniel Kraft\n- 2011-2013  Júlio Hoffimann Mendes\n- 2011-2018, 2020, 2024  David Miguel Susano Pinto (carandraug)\n- 2011-2023  Philip Nienhuis\n- 2011-2025  Torsten Lilge\n- 2012  Alexander Graf\n- 2012  Alexander Hansen\n- 2012  Corbin Champion\n- 2012  Elias Pipping\n- 2012  Fabio Rossi\n- 2012  Garrett G Euler\n- 2012  Israel Herraiz\n- 2012  Jen Stewart\n- 2012  Melvin Robinson\n- 2012  Miguel Bazdresch\n- 2012  Nicholas Musolino\n- 2012  Ronald van der Meer\n- 2012  Ryan Starret\n- 2012  Sergey Dudoladov\n- 2012  Stefan Husmann\n- 2012  Sunghyun Cho\n- 2012  Vivek Dogra\n- 2012, 2014-2019, 2022  Colin Macdonald\n- 2012-2013  Axel Mathéi\n- 2012-2013  Ed Meyer\n- 2012-2013  Erik Kjellson\n- 2012-2013  Max Brister\n- 2012-2013  Muhali\n- 2012-2013  Richard Crozier\n- 2012-2013  Thorsten Liebig\n- 2012-2016, 2018-2019, 2024  Juan Pablo Carbajal\n- 2012-2024  Pantxo Diribarne\n- 2012-2021  Mike Miller\n- 2013  Adam H Aitkenhead\n- 2013  Amod Mulay\n- 2013  Andre da Costa Barros\n- 2013  Andy Register\n- 2013  Artem Krosheninnikov\n- 2013, 2021-2025  Arun Giridhar\n- 2013, 2023  Ben Kurtz\n- 2013  Carl Osterwisch\n- 2013  Catalin Codreanu\n- 2013  Clemens Buchacher\n- 2013  Corey Thomasson\n- 2013  Craig Hudson\n- 2013  David Turner\n- 2013  FZI Forschungszentrum Informatik Karlsruhe\n- 2013  Falk Tannhäuser\n- 2013  Janne Olavi Paanajärvi\n- 2013  Jens Restemeier\n- 2013  Leopoldo Cerbaro\n- 2013  Marco Cecchetti\n- 2013  Patrick Noffke\n- 2013  Risto Vanhanen\n- 2013  Rüdiger Sonderfeld\n- 2013  Serhiy Zahoriya\n- 2013  Vytautas Jančauskas\n- 2013, 2015-2019, 2023-2024  Sébastien Villemot\n- 2013, 2016  Sander van Rijn\n- 2013, 2018, 2020  Valentin Ortega\n- 2013-2014  Kyle Guinn\n- 2013-2014  LYH\n- 2013-2014  Markus Appel\n- 2013-2014  Mike Sander\n- 2013-2014  Philipp Kutin\n- 2013-2014  PrasannaKumar Muralidharan\n- 2013-2014, 2016-2017, 2022  Nir Krakauer\n- 2013-2014, 2016-2019, 2022  Julien Bect\n- 2013-2015  Stefan Mahr\n- 2013-2015, 2018, 2022  Felipe G. Nievinski\n- 2013-2022  Kai T. Ohlhus\n- 2013-2020, 2022-2023  John Donoghue\n- 2014  Ahsan Ali Shahid\n- 2014  Branden Archer\n- 2014  Colin Foster\n- 2014  David Spies\n- 2014  Drew Abbot\n- 2014  Edmund Grimley Evans\n- 2014  Eduardo Ramos Fernández\n- 2014  Endre Kozma\n- 2014  Jason Alan Palmer\n- 2014  Joachim Wiesemann\n- 2014  Johannes Zarl\n- 2014  José Vallet\n- 2014  Lasse Schuirmann\n- 2014  Marco Vitetta\n- 2014  Marko Seric\n- 2014  Markus Bergholz\n- 2014  Nathan Podlich\n- 2014  Pedro Angelo\n- 2014  Pooja Rao\n- 2014  Rolando Pereira\n- 2014  Sergey Plotnikov\n- 2014  Serviscope Minor\n- 2014  Stefan Beller\n- 2014  Vaibhav Gupta\n- 2014  Willem Atsma\n- 2014, 2019  Michael C. Grant\n- 2014-2015  Allan Jacobs\n- 2014-2016  Eugenio Gianniti\n- 2014-2016  Stefan Miereis\n- 2014-2016, 2018  Massimiliano Fasi\n- 2015  Akira Noda\n- 2015  Amro\n- 2015  Armin Müller\n- 2015  Bernardo Sulzbach\n- 2015  Cillian O'Driscoll\n- 2015  Claudius Zingerli\n- 2015  Ederag\n- 2015  Ethan Biery\n- 2015  Ilya Kurdyukov\n- 2015  Johannes Leuschner\n- 2015, 2022  Ken Marek\n- 2015  Michele Zaffalon\n- 2015  Rafael Monteiro\n- 2015  Sahil Badyal\n- 2015  Yu Liu\n- 2015, 2017  Michael Barnes\n- 2015, 2017  Piotr Held\n- 2015-2016  Dmitry Roshchin\n- 2015-2016  Jacapo Corno\n- 2015-2016, 2021-2023  José Luis García Pallero\n- 2015-2016  Oliver Heimlich\n- 2015-2016, 2018  Sebastian Schöps\n- 2015-2016, 2019  Hartmut Gimpel\n- 2015-2017  Avinoam Kalma\n- 2015-2017  Lachlan Andrew\n- 2015-2025  Nicholas R. Jankowski\n- 2015  Mudit Sharma\n- 2016  Abhinav Tripathi\n- 2016  Andrew Thornton\n- 2016  Atri Bhattacharya\n- 2016  Barbara Lócsi\n- 2016  Damjan Angelovski\n- 2016  Francesco Faccio\n- 2016  Garrett Euler\n- 2016  Joakim Andén\n- 2016  NVS Abhilash\n- 2016, 2021  Robert Jenssen\n- 2016  Stephen Montgomery-Smith\n- 2016-2017  Ernst Reissner\n- 2016-2020, 2022  Lars Kindermann\n- 2016-2025  Markus Mützel\n- 2017  Brad Kennedy\n- 2017, 2022  Georg Wiora\n- 2017  Hugo Raguet\n- 2017  Lasse Kliemann\n- 2017  Richard Zweig\n- 2017  Tejaswi D Prakash\n- 2017  Victor Norton\n- 2017-2019, 2023  Alexander Wilms\n- 2017-2023  Guillaume Flandin\n- 2017-2019, 2021-2022  Michael Leitner\n- 2017-2019, 2021  Michele Ginesi\n- 2017-2019  Sahil Yadav\n- 2018  Avlas\n- 2018  Cristiano Dorigo\n- 2018  Dildar Sk\n- 2018, 2021  Gene Harvey\n- 2018  Joe Winegarden\n- 2018  Maor Shutman\n- 2018  Ronny Standtke\n- 2018  Stefan Schlögl\n- 2018  Stevie Schraudner\n- 2018-2024  Antonius R. Burgers\n- 2018-2021  Andrew Janke\n- 2018-2019, 2022-2023  Jun Wang\n- 2019  Anthony Morast\n- 2019  Bill Greene\n- 2019, 2021  Christian Himpe\n- 2019  Daniel Davis\n- 2019  Eddy Xiao\n- 2019  Juho Iipponen\n- 2019  Nguyễn Gia Phong\n- 2019  Tomi Pannila\n- 2019  William Greene\n- 2019-2021, 2024  Markus Meisinger\n- 2020-2021  Abdallah Elshamy\n- 2020  Dmitry Astankov\n- 2020-2024  Fernando Alvarruiz\n- 2020  Marcel Jacobse\n- 2020  Martin Köhler\n- 2020  Michael Witten\n- 2020  Simon Hau\n- 2020  Valdas\n- 2021-2022  Stefan Brüns\n- 2021, 2023-2024  Petter Tomner\n- 2021, 2023  Óvári\n- 2021, 2023  Serkan Önder\n- 2021  Stefano Guidoni\n- 2021  Steven Waldrip\n- 2022-2023  Reinhard Resch\n- 2022  Adam Dodd\n- 2022  Andreas Bertsatos\n- 2022  Christof Kaufmann\n- 2022  Farid Partonia\n- 2022  Gaël Bonithon\n- 2022  Kasper H. Filtenborg\n- 2022  Luis Eduardo Ribeiro Guerra\n- 2022  Maged Rifaat\n- 2022  Remi Thebault\n- 2022  Shreya Gupta\n- 2022  Tommi Höynälänmaa\n- 2023-2024  Hendrik Koerner\n- 2023  Johannes Pfeifer\n- 2023  Leonardo\n- 2023  Linton Miller\n- 2023  paulo\n- 2023  Peter Konowski\n- 2024  Helmut Podhaisky\n- 2024  Jörg Sommrey\n\nSee also the list of contributors in the Octave manual (the file\ndoc/interpreter/contributors.in in the sources).\n"
  },
  {
    "path": "Makefile.am",
    "content": "# Makefile for Octave\n\n########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# This Makefile requires GNU Make features.\n\nexport AWK\nexport GREP\nexport FIND\nexport SED\nexport SHELL\nexport PERL\nexport TAR_OPTIONS\n\nversion := ${OCTAVE_VERSION}\napi_version := ${OCTAVE_API_VERSION}\n\n# Lex flags\n\nAM_LFLAGS = @LFLAGS@\n\n# Until modern Bison rules are handled by autoconf/automake.\n\nAM_V_BISON = $(am__v_BISON_$(V))\nam__v_BISON_ = $(am__v_BISON_$(AM_DEFAULT_VERBOSITY))\nam__v_BISON_0 = @echo \"  BISON   \" $@;\nam__v_BISON_1 =\n\nBISON = @BISON@\nBISONCOMPILE = $(BISON) $(AM_BISONFLAGS) $(BISONFLAGS)\n\n# Define YACC to pacify automake\n\nYACC = $(BISON)\n\nif AMCOND_LIB_VISIBILITY_FLAGS\n  OCTAVE_VISIBILITY_FLAGS = ${CFLAG_VISIBILITY}\nendif\n\n# Fortran compiler flags.\n\nAM_FFLAGS = ${FPICFLAG} @FFLAGS@ $(OCTAVE_VISIBILITY_FLAGS)\n\n# C compiler flags.\n\nAM_CFLAGS = ${CPICFLAG} ${XTRA_CFLAGS} ${WARN_CFLAGS} $(OCTAVE_VISIBILITY_FLAGS)\n\n# ifeq (${INCLUDE_DEPS},no)\n#   omit_deps = true;\n# endif\n\n# C++ compiler flags.\n\nAM_CXXFLAGS = ${CXXPICFLAG} ${XTRA_CXXFLAGS} ${WARN_CXXFLAGS} $(OCTAVE_VISIBILITY_FLAGS)\n\nADDRESS_SANITIZER_ENABLED = @ADDRESS_SANITIZER_ENABLED@\nADDRESS_SANITIZER_OPTIONS = @ADDRESS_SANITIZER_OPTIONS@\n\nFFTW_XCPPFLAGS = @FFTW_XCPPFLAGS@\nFFTW_XLDFLAGS = @FFTW_XLDFLAGS@\nFFTW_XLIBS = @FFTW_XLIBS@\n\nSPARSE_XCPPFLAGS = @SPARSE_XCPPFLAGS@\nSPARSE_XLDFLAGS = @SPARSE_XLDFLAGS@\nSPARSE_XLIBS = @SPARSE_XLIBS@\n\n# Linker flags and dependencies\n\nif AMCOND_CLANG_PTHREAD_WARNING\n  AM_LDFLAGS = -Wc,-Qunused-arguments\nendif\n\nGNULIB_LINK_DEPS = @GNULIB_LINK_DEPS@\n\nLIBOCTAVE_LINK_DEPS = @LIBOCTAVE_LINK_DEPS@\nLIBOCTAVE_LINK_OPTS = @LIBOCTAVE_LINK_OPTS@\n\nLIBOCTINTERP_LINK_DEPS = @LIBOCTINTERP_LINK_DEPS@\nLIBOCTINTERP_LINK_OPTS = @LIBOCTINTERP_LINK_OPTS@\n\nOCTAVE_LINK_DEPS = @OCTAVE_LINK_DEPS@\nOCTAVE_LINK_OPTS = @OCTAVE_LINK_OPTS@\n\nOCT_LINK_DEPS = @OCT_LINK_DEPS@\nOCT_LINK_OPTS = @OCT_LINK_OPTS@\n\nLIBOCTGUI_LINK_DEPS = @LIBOCTGUI_LINK_DEPS@\nLIBOCTGUI_LINK_OPTS = @LIBOCTGUI_LINK_OPTS@\n\nOCTAVE_GUI_LINK_DEPS = @OCTAVE_GUI_LINK_DEPS@\nOCTAVE_GUI_LINK_OPTS = @OCTAVE_GUI_LINK_OPTS@\n\n# Options used for creating the source distribution.\n\nGZIP_ENV = '--best --no-name'\nSOURCE_MTIME := \\\n  $(shell $(SHELL) $(top_srcdir)/build-aux/get-source-mtime.sh \"$(srcdir)\")\nTAR_OPTIONS = $(REPRODUCIBLE_TAR_FLAGS) --mtime=@$(SOURCE_MTIME)\n\n# The arguments passed to configure.\n\nCONFIG_SUBDIRS = @subdirs@\n\nnull =\nldpreloadsep = ${null}@ldpreloadsep@${null}\n\nimage_DATA =\noctdata_DATA =\noctdoc_DATA =\noctetc_DATA =\noctfonts_DATA =\noctlocale_DATA =\n\nOCT_FILES =\nOCT_FILE_LIBS =\nOCT_FILE_PKG_ADD_FILES =\n\nDOC_TARGETS =\n\nBUILT_DISTFILES =\nBUILT_NODISTFILES =\nEXTRA_DIST =\n\nGEN_CONFIG_SHELL =\n\nBUILT_DISTFILES += \\\n  AUTHORS \\\n  BUGS \\\n  ChangeLog \\\n  HG-ID \\\n  INSTALL.OCTAVE \\\n  NEWS\n\nif AMCOND_ENABLE_HG_ID\nDISABLE_HG_ID_OPTION :=\nelse\nDISABLE_HG_ID_OPTION := --disable\nendif\n\n## The mk-hg-id.sh script will be executed each time Make runs to\n## update the HG-ID file in the build tree if it is out of date.\n\nHG-ID:\n\t$(AM_V_GEN)$(SHELL) $(top_srcdir)/build-aux/mk-hg-id.sh \"$(srcdir)\" $(DISABLE_HG_ID_OPTION) > $@-t && \\\n\t$(simple_move_if_change_rule)\n.PHONY: HG-ID\n\nHG_ID_VAR = $(shell cat ${top_builddir}/HG-ID)\n\nEXTRA_DIST += \\\n  CITATION \\\n  COPYING \\\n  INSTALL \\\n  README \\\n  octave.doap \\\n  run-octave.in \\\n  $(BUILT_DISTFILES)\n\nAUTOCONF_SUBST_VARS = @AUTOCONF_SUBST_VARS@\nALL_SUBST_VARS = \\\n  $(AUTOCONF_SUBST_VARS) \\\n  abs_top_builddir \\\n  abs_top_srcdir \\\n  api_version \\\n  version\n\nDIRSTAMP_FILES =\n\noctave_dirstamp = $(am__leading_dot)octave-dirstamp\n\n$(DIRSTAMP_FILES):\n\t$(AM_V_GEN)$(MKDIR_P) $(@D) && \\\n\t: > $@\n\nCLEANFILES =\nDISTCLEANFILES =\nMAINTAINERCLEANFILES =\ninfo_TEXINFOS =\nBUILT_SOURCES =\nTEST_FILES =\nnoinst_TEST_FILES =\n\nDOC_IMAGES_SRC =\nBUILT_DOC_IMAGES =\nBUILT_DOC_IMAGES_EPS =\nBUILT_DOC_IMAGES_PDF =\nBUILT_DOC_IMAGES_PNG =\nBUILT_DOC_IMAGES_TXT =\nDOC_IMAGES =\nDOC_IMAGES_EPS =\nDOC_IMAGES_PDF =\nDOC_IMAGES_PNG =\nDOC_IMAGES_TXT =\n\nFCN_FILE_DIRS =\nFCN_FILES =\nGEN_FCN_FILES =\nPKG_ADD_FILES =\nSCRIPTS_IMAGES =\nJAR_FILES =\nDOCSTRING_FILES =\n\nbin_PROGRAMS =\narchlib_PROGRAMS =\nnoinst_HEADERS =\nnodist_noinst_HEADERS =\nOCTAVE_VERSION_LINKS =\nOCTAVE_CROSS_TOOLS =\nOCTAVE_INTERPRETER_TARGETS =\n\noctlib_LTLIBRARIES =\nnoinst_LTLIBRARIES =\n\noctinclude_HEADERS =\nnodist_octinclude_HEADERS =\n\nDIST_SRC =\n\nALL_LOCAL_TARGETS =\n\n# Subdirectories in which to run make recursively.\n# Other directories are handled directly from this Makefile,\n# but also review the included module.mk makefile fragments.\n\nSUBDIRS = libgnu test\n\n# All of build depends on having libgnu.\n# Add the library to BUILT_SOURCES so it is created early in the build process\n# This is only a partial solution which works when 'make all' is used.\n# See bug #45578.\nBUILT_SOURCES += libgnu/libgnu.la\n\nlibgnu/libgnu.la: oct-conf-post-private.h oct-conf-post-public.h\n\tcd libgnu && $(MAKE) $(AM_MAKEFLAGS) all\n\ninclude liboctave/module.mk\ninclude libinterp/module.mk\ninclude libmex/module.mk\ninclude libgui/module.mk\ninclude src/module.mk\ninclude scripts/module.mk\ninclude doc/module.mk\ninclude etc/module.mk\ninclude examples/module.mk\ninclude m4/module.mk\ninclude build-aux/module.mk\n\nDIST_HOOKS := \\\n  doc-interpreter-dist-hook \\\n  docs-dist-hook \\\n  fix-file-perms-dist-hook \\\n  hg-id-dist-hook \\\n  metainfo-dist-hook \\\n  icons-dist-hook \\\n  scripts-dist-hook\n\ndist-hook: $(DIST_HOOKS)\n\nif AMCOND_BUILD_DOCS\ndocs-dist-hook:\nelse\ndocs-dist-hook:\n\t@echo \"Documentation disabled.  Cannot package distribution!\" ; exit 1;\nendif\n\n## Ensure file permissions are consistent on all files included in the\n## distribution.  Automake takes care of normalizing some permissions of\n## normal files and directories.  Automake does not ensure that files don't\n## have unnecessarily lax write permissions.  It also does not ensure that\n## executable permissions are set for group and other users.\nfix-file-perms-dist-hook:\n\t-chmod -R go-w \"$(distdir)\"\n\t-find \"$(distdir)\" -type f -perm -100 -exec chmod a+rx {} \\;\n.PHONY: fix-file-perms-dist-hook\n\nif AMCOND_ENABLE_HG_ID\nhg-id-dist-hook:\n\t@test x\"$(DIST_IGNORE_HG_STATE)\" != x \\\n\t  || echo $(HG_ID_VAR) | $(GREP) '^[0-9a-f]\\{12\\}$$' >/dev/null 2>&1 \\\n\t  || { echo ; \\\n\t       echo \"Packaging distribution requires a clean hg working tree with no uncommitted changes.\" ; \\\n\t       echo \"Please commit or revert your changes first, or pass DIST_IGNORE_HG_STATE=1.\" ; \\\n\t       echo \"Cannot package distribution!\" ; \\\n\t       echo ; exit 1; }\nelse\nhg-id-dist-hook:\n\t@echo \"Octave was configured with --disable-hg-id.  Cannot package distribution!\" 1>&2 ; exit 1;\nendif\n.PHONY: hg-id-dist-hook\n\nif AMCOND_HAVE_ICON_TOOLS\nicons-dist-hook:\nelse\nicons-dist-hook:\n\t@echo \"Packaging distribution requires icotool and rsvg-convert.\" ; exit 1;\nendif\n\nBUILT_SOURCES += \\\n  oct-conf-post-private.h \\\n  oct-conf-post-public.h \\\n  octave-config.h \\\n  run-octave \\\n  $(DIRSTAMP_FILES)\n\nnoinst_SCRIPTS = run-octave\n\nCLEANFILES += \\\n  config-vars \\\n  make-vars \\\n  oct-file-pkg-add \\\n  octave-config.h \\\n  run-octave\n\nDISTCLEANFILES += \\\n  $(DIRSTAMP_FILES) \\\n  $(GEN_CONFIG_INC) \\\n  $(GEN_CONFIG_SHELL) \\\n  .gdbinit\n\nMAINTAINERCLEANFILES += \\\n  $(BUILT_DISTFILES)\n\nCONFIG_FILES = @ac_config_headers@ @ac_config_files@\n\nnodist_octinclude_HEADERS += \\\n  oct-conf-post-public.h \\\n  octave-config.h\n\nOCTAVE_INTERPRETER_TARGETS += \\\n  $(OCT_FILE_PKG_ADD_FILES)\n\nALL_LOCAL_TARGETS += \\\n  $(OCTAVE_INTERPRETER_TARGETS) \\\n  .gdbinit \\\n  $(DOC_TARGETS)\n\nall-local: $(ALL_LOCAL_TARGETS)\n\t@echo \"\"\n\t@echo \"Octave successfully built.  Now choose from the following:\"\n\t@echo \"\"\n\t@echo \"   ./run-octave    - to run in place to test before installing\"\n\t@echo \"   make check      - to run the tests\"\n\t@echo \"   make install    - to install (PREFIX=$(prefix))\"\n\t@echo \"\"\n\t@echo \"   HG ID for this build is \\\"$(HG_ID_VAR)\\\"\"\n\t@echo \"\"\n\nrun-octave: run-octave.in build-aux/subst-script-vals.sh\n\t$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-script-vals.sh) && \\\n\tchmod a+rx $@\n\noctave-config.h: config.h build-aux/mk-octave-config-h.sh\n\t$(AM_V_GEN)$(SHELL) $(srcdir)/build-aux/mk-octave-config-h.sh $< > $@-t && \\\n\t$(simple_move_if_change_rule)\n\nconfig-vars: $(GEN_CONFIG_SHELL)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(SED) -n 's/  *\"$$/\"/; s/^\\([A-Za-z_][A-Za-z0-9_]*\\)=\" *\\(.*\\)\" *$$/\\1 \\2/p' $^ | sort -u > $@-t && \\\n\tmv $@-t $@\n\n## We always have to create this file because values for Make variables\n## may be passed on the command line.\n\nmake-vars:\n\t$(file >$@-t) $(foreach v, $(ALL_SUBST_VARS), $(file >>$@-t,$(v) $(value $(v))))\n\t$(AM_V_GEN)mv $@-t $@\n.PHONY: make-vars\n\ncheck-subst-vars: build-aux/check-subst-vars.sh make-vars config-vars\n\t@$(SHELL) -f build-aux/check-subst-vars.sh make-vars config-vars\n.PHONY: check-subst-vars\n\n.gdbinit: etc/gdbinit\n\t$(AM_V_GEN)$(gdbinit-install-rule)\n\nNEWS: etc/NEWS.$(OCTAVE_MAJOR_VERSION).md\n\t$(AM_V_GEN)rm -f $@ && \\\n\tcp $< $@\n\ndefine changelog-from-hg-log\n  rm -f $@-t && \\\n  if [ -d $(srcdir)/.hg ]; then \\\n    ( cd $(srcdir); \\\n      hg log --no-graph --style=build-aux/changelog.tmpl --prune=b0e60ad4ae26 --only-branch=`hg branch`; \\\n      echo \"\"; \\\n      echo \"See the files in the directory etc/OLD-ChangeLogs for changes before 2011-04-19\"; \\\n    ) > $@-t && \\\n    mv $@-t $@; \\\n  elif [ ! -f $@ ] && [ ! -f $(srcdir)/$@ ]; then \\\n    echo \"Empty ChangeLog generated because no hg log available\" > $@-t && \\\n    mv $@-t $@; \\\n  fi\nendef\n\nChangeLog:\n\t$(AM_V_GEN)$(changelog-from-hg-log)\n.PHONY: ChangeLog\n\noctetc_DATA += \\\n  CITATION \\\n  NEWS\n\nif AMCOND_INSTALL_BUILD_LOGS\noctetc_DATA += config.log\nendif\n\nDIRS_TO_MAKE = \\\n  $(localfcnfiledir) \\\n  $(localapifcnfiledir) \\\n  $(localapipkgdir) \\\n  $(localverfcnfiledir) \\\n  $(localoctfiledir) \\\n  $(localapioctfiledir) \\\n  $(localveroctfiledir) \\\n  $(localarchlibdir) \\\n  $(localapiarchlibdir) \\\n  $(localverarchlibdir)\n\ninstalldirs-local:\n\t$(MKDIR_P) $(addprefix $(DESTDIR), $(DIRS_TO_MAKE))\n\ninstall-data-local: installdirs-local\n\noct-file-pkg-add: $(OCT_FILE_PKG_ADD_FILES)\n\tcat $(OCT_FILE_PKG_ADD_FILES) > $@-t \\\n\t  && mv $@-t $@\n\ninstall-oct: oct-file-pkg-add\n\t$(MKDIR_P) $(DESTDIR)$(octfiledir)\n\tif [ -n \"`cat $(OCT_FILE_PKG_ADD_FILES)`\" ]; then \\\n\t  $(INSTALL_DATA) oct-file-pkg-add $(DESTDIR)$(octfiledir)/PKG_ADD; \\\n\tfi\n\ttop_build_dir=`pwd` && \\\n\tcd $(DESTDIR)$(octlibdir) && \\\n\tfor ltlib in $(OCT_FILE_LIBS); do \\\n\t  f=`echo $$ltlib | $(SED) 's,.*/,,'`; \\\n\t  dl=`$(SED) -n -e \"s/dlname='\\([^']*\\)'/\\1/p\" < $$top_build_dir/$$ltlib`; \\\n\t  if [ -n \"$$dl\" ]; then \\\n\t    $(INSTALL_PROGRAM) $$dl $(DESTDIR)$(octfiledir)/`echo $$f | $(SED) 's,^lib,,; s,\\.la$$,.oct,'`; \\\n\t  else \\\n\t    echo \"error: dlname is empty in $$ltlib!\"; \\\n\t    exit 1; \\\n\t  fi; \\\n\t  lnames=`$(SED) -n -e \"s/library_names='\\([^']*\\)'/\\1/p\" < $$top_build_dir/$$ltlib`; \\\n\t  if [ -n \"$$lnames\" ]; then \\\n\t    rm -f $$f $$lnames $$dl; \\\n\t  fi \\\n\tdone\n.PHONY: install-oct\n\nuninstall-oct:\n\tfor f in $(notdir $(OCT_FILES)); do \\\n\t  rm -f $(DESTDIR)$(octfiledir)/$$f; \\\n\tdone\n\trm -f $(DESTDIR)$(octfiledir)/PKG_ADD\n.PHONY: uninstall-oct\n\nclean-local: doc-clean\n\ndistclean-local:\n\tif [ \"x${srcdir}\" != \"x.\" ]; then rm -f HG-ID; fi\n\nmaintainer-clean-local: doc-maintainer-clean\n\n## The 'clean-aminfo' target is defined by Automake >= 1.11.  We want to\n## distribute all Texinfo docs with the source distribution and not delete\n## them on 'clean', so we override this target to do nothing by default.\n\nclean-aminfo:\n\ndefine move_if_change_rule\n  if [ -s $(1) ]; then \\\n    ${SHELL} ${top_srcdir}/build-aux/move-if-change $(1) $(2); \\\n  else \\\n    echo \"$(1) is empty!\" 1>&2; \\\n    rm -f $(1); \\\n    exit 1; \\\n  fi\nendef\n\ndefine simple_move_if_change_rule\n  $(call move_if_change_rule,$@-t,$@)\nendef\n\ndefine build-info-commands\n  rm -f $@-t && \\\n  $(SED) \\\n    -e \"s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by Makefile|\" \\\n    -e \"s|%OCTAVE_HG_ID%|$(HG_ID_VAR)|\" $< > $@-t && \\\n  $(simple_move_if_change_rule)\nendef\n\ndefine simple-filter-rule\n  rm -f $@-t $@ && \\\n  ${SHELL} $(1) < $< > $@-t && \\\n  mv $@-t $@\nendef\n\ndefine gdbinit-install-rule\n  if [ -f $@ ] && ! cmp -s $< $@; then \\\n    echo \"refusing to overwrite $@ with newer version from $<\" 1>&2; \\\n  else \\\n    cp $< $@; \\\n  fi\nendef\n\ndefine test-file-commands\n  rm -f $@-t $@ && \\\n  ( echo \"## DO NOT EDIT!  Generated automatically from $(<F) by Make.\"; \\\n    $(GREP) '^%!' $< \\\n  ) > $@-t && \\\n  mv $@-t $@\nendef\n\n%.cc-tst : %.cc\n\t$(AM_V_GEN)$(test-file-commands)\n\n%.yy-tst : %.yy\n\t$(AM_V_GEN)$(test-file-commands)\n\n%.ll-tst : %.ll\n\t$(AM_V_GEN)$(test-file-commands)\n"
  },
  {
    "path": "README",
    "content": "GNU Octave -- a high-level language for numerical computations\n==============================================================\n\nCopyright (C) 1996-2026 The Octave Project Developers\n\nSee the file COPYRIGHT.md in the top-level directory of this\ndistribution or <https://octave.org/copyright/>.\n\nOverview\n--------\n\nGNU Octave is a high-level interpreted language, primarily intended\nfor numerical computations.  It provides capabilities for the\nnumerical solution of linear and nonlinear problems, and for\nperforming other numerical experiments.  It also provides extensive\ngraphics capabilities for data visualization and manipulation.  GNU\nOctave is normally used through its interactive interface (CLI and\nGUI), but it can also be used to write non-interactive programs.\nThe GNU Octave language is quite similar to Matlab so that most\nprograms are easily portable.\n\nGNU Octave is free software: you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nGNU Octave is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with Octave; see the file COPYING.  If not, see\n<https://www.gnu.org/licenses/>.\n\nAvailability\n------------\n\nThe latest released version of Octave is always available from\n<https://ftp.gnu.org/gnu/octave/> and many mirror sites around the\nworld.  You may also find links to binary distributions at\n<https://www.octave.org/download.html>.  The current development\nsources may be found under the Source Code tab on\n[Savannah](https://savannah.gnu.org/projects/octave/).\n\nYou are encouraged to verify the Octave installation file you download\n(such as `octave-11.1.0.tar.xz`) as follows:\n* First, ensure that you are downloading from the official Octave website, or\nfrom a GNU mirror linked from the official Octave website.\n* Next, download the corresponding signature file for the installation file\nyou downloaded, for example `octave-11.1.0.tar.xz.sig`.\n* Next, run the command\n```\n  gpg --keyserver hkps://keys.gnupg.net --recv-keys B05F05B75D36644B\n```\nto import John W. Eaton's public key (this needs to be done only once).\n* Verify the integrity of the file you downloaded with a command like\n```\n  gpg --verify octave-11.1.0.tar.xz.sig\n```\n* If all is well, then the output should say\n```\n  gpg: Good signature from \"John W. Eaton <jwe@gnu.org>\n```\n* If the file you downloaded was corrupted or changed by anyone else, then\nthe output will say\n```\n  gpg: BAD signature from \"John W. Eaton <jwe@gnu.org>\"\n```\nIf so, you should not install Octave from that file, but should start over.\n\nInstallation\n------------\n\nBuilding Octave from source requires approximately 475 MB of disk space (or\napproximately 3.8 GB with debugging symbols).  Once installed, Octave uses\napproximately 75 MB of disk space (or approximately 415 MB if shared libraries\nare not built or binaries include debugging symbols).\n\nTo compile Octave, you will need a recent version of:\n\n- [GNU Make](https://www.gnu.org/software/make/)\n- [GNU G++](https://gcc.gnu.org/) or a different C++17 compiler\n- [GNU Fortran](https://gcc.gnu.org/fortran/), a different Fortran 77 compiler,\n  or [f2c](http://www.netlib.org/f2c/)\n\nOctave's Makefiles use features of GNU Make that are not present in\nother versions of make.  If you use `f2c`, you will need a script\nlike `fort77` that works like a normal Fortran compiler by combining\n`f2c` with your C compiler in a single script.\n\nSee the file `INSTALL.OCTAVE` or the wiki at <https://wiki.octave.org/Building>\nfor more detailed installation instructions.\n\nBugs and Patches\n----------------\n\nThe files `BUGS` and `doc/interpreter/bugs.txi` explain the recommended\nprocedure for reporting bugs on the [bug tracker](https://bugs.octave.org)\nor contributing patches; online resources are also available\n[here](https://octave.org/support).\n\nDocumentation\n-------------\n\n* [Octave's manual](https://docs.octave.org/interpreter/) is a\n  comprehensive user guide covering introductive and more advanced\n  topics.\n* [Octave's wiki](https://wiki.octave.org) is a user community page,\n  covering various topics and answering [FAQ](https://wiki.octave.org/FAQ).\n* [Octave's Doxygen](https://docs.octave.org/doxygen/) documentation\n  explains the C++ class libraries.\n\nIf you notice omissions or inconsistencies in the documentation, please\nreport them at our bug tracker.  Specific suggestions for ways to improve\nOctave and its documentation are always welcome.  Reports with patches are\neven more welcome.\n\nAdditional Information\n----------------------\n\nThe Octave website is <https://www.octave.org>, and there is a forum\nat <https://octave.discourse.group/>.\n"
  },
  {
    "path": "autogen.sh",
    "content": "#!/bin/sh\n# Convenience script for regenerating all autogeneratable files that are\n# omitted from the version control repository. In particular, this script\n# also regenerates all aclocal.m4, config.h.in, Makefile.in, configure files\n# with new versions of autoconf or automake.\n\n# Copyright (C) 2003-2025 Free Software Foundation, Inc.\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Originally written by Paul Eggert.  The canonical version of this\n# script is maintained as top/autogen.sh in gnulib.  However, to be\n# useful to your package, you should place a copy of it under version\n# control in the top-level directory of your package.  The intent is\n# that all customization can be done with a bootstrap.conf file also\n# maintained in your version control; gnulib comes with a template\n# build-aux/bootstrap.conf to get you started.\n#\n# Alternatively, you can use an autogen.sh script that is specific\n# to your package.\n\nme=\"$0\"\nmedir=`dirname \"$me\"`\n\n# Read the function library and the configuration.\n. \"$medir\"/bootstrap-funclib.sh\n\nautogen \"$@\"\n"
  },
  {
    "path": "autopull.sh",
    "content": "#!/bin/sh\n# Convenience script for fetching auxiliary files that are omitted from\n# the version control repository of this package.\n\n# Copyright (C) 2003-2025 Free Software Foundation, Inc.\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Originally written by Paul Eggert.  The canonical version of this\n# script is maintained as top/autopull.sh in gnulib.  However, to be\n# useful to your package, you should place a copy of it under version\n# control in the top-level directory of your package.  The intent is\n# that all customization can be done with a bootstrap.conf file also\n# maintained in your version control; gnulib comes with a template\n# build-aux/bootstrap.conf to get you started.\n#\n# Alternatively, you can use an autopull.sh script that is specific\n# to your package.\n\nme=\"$0\"\nmedir=`dirname \"$me\"`\n\n# Read the function library and the configuration.\n. \"$medir\"/bootstrap-funclib.sh\n\nautopull \"$@\"\n"
  },
  {
    "path": "bootstrap",
    "content": "#! /bin/sh\n# Bootstrap this package from checked-out sources.\n\nscriptversion=2025-06-10.02; # UTC\n\n# Copyright (C) 2003-2025 Free Software Foundation, Inc.\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Originally written by Paul Eggert.  The canonical version of this\n# script is maintained as top/bootstrap in gnulib. However, to be\n# useful to your package, you should place a copy of it under version\n# control in the top-level directory of your package.  The intent is\n# that all customization can be done with a bootstrap.conf file also\n# maintained in your version control; gnulib comes with a template\n# build-aux/bootstrap.conf to get you started.\n\n# Please report bugs or propose patches to bug-gnulib@gnu.org.\n\nme=\"$0\"\nmedir=`dirname \"$me\"`\n\n# Read the function library and the configuration.\n. \"$medir\"/bootstrap-funclib.sh\n\nusage() {\n  cat <<EOF\nUsage: $me [OPTION]...\nBootstrap this package from the checked-out sources.\n\nOptional environment variables:\n  GNULIB_SRCDIR            Specifies the local directory where gnulib\n                           sources reside.  Use this if you already\n                           have gnulib sources on your machine, and\n                           you want to use these sources.\n  GNULIB_REFDIR            Specifies the local directory where a gnulib\n                           repository (with a .git subdirectory) resides.\n                           Use this if you already have gnulib sources\n                           and history on your machine, and do not want\n                           to waste your bandwidth downloading them again.\n                           Only used for phase 1 (--pull).\n  GNULIB_URL               URL of the gnulib repository.  The default is\n                           $default_gnulib_url,\n                           which is Gnulib's upstream repository.\n                           Only used for phase 1 (--pull).\n\nOptions:\n\n  --pull                   Do phase 1: Pull files from the network.\n  --gen                    Do phase 2: Generate files from local files\n                           (no network access).\n                           (The default is to do both phases.)\n\n  --gnulib-srcdir=DIRNAME  Specifies the local directory where gnulib\n                           sources reside.  Use this if you already\n                           have gnulib sources on your machine, and\n                           you want to use these sources.  Defaults\n                           to \\$GNULIB_SRCDIR.\n  --gnulib-refdir=DIRNAME  Specifies the local directory where a gnulib\n                           repository (with a .git subdirectory) resides.\n                           Use this if you already have gnulib sources\n                           and history on your machine, and do not want\n                           to waste your bandwidth downloading them again.\n                           Defaults to \\$GNULIB_REFDIR.\n                           Only used for phase 1 (--pull).\n\n  --bootstrap-sync         If this bootstrap script is not identical to\n                           the version in the local gnulib sources,\n                           update this script, and then restart it with\n                           /bin/sh or the shell \\$CONFIG_SHELL.\n  --no-bootstrap-sync      Do not check whether bootstrap is out of sync.\n\n  --copy                   Copy files instead of creating symbolic links.\n                           Only used for phase 2 (--gen).\n  --force                  Attempt to bootstrap even if the sources seem\n                           not to have been checked out.\n  --no-git                 Do not use git to update gnulib.  Requires that\n                           \\$GNULIB_SRCDIR or the --gnulib-srcdir option\n                           points to a gnulib repository with the correct\n                           revision.\n                           Only used for phase 1 (--pull).\n  --skip-po                Do not download *.po files.\n                           Only used for phase 1 (--pull).\nEOF\n  bootstrap_print_option_usage_hook\n  cat <<EOF\nIf the file bootstrap.conf exists in the same directory as this script, its\ncontents are read as shell variables to configure the bootstrap.\n\nFor build prerequisites, environment variables like \\$AUTOCONF and \\$AMTAR\nare honored.\n\nGnulib sources can be fetched in various ways:\n\n * If GNULIB_SRCDIR is set (either as an environment variable or via the\n   --gnulib-srcdir option), then sources are fetched from that local\n   directory.  If it is a git repository and the configuration variable\n   GNULIB_REVISION is set in bootstrap.conf, then that revision is\n   checked out.\n\n * Otherwise, if this package is in a git repository with a 'gnulib'\n   submodule configured, then that submodule is initialized and updated\n   and sources are fetched from there.  If GNULIB_REFDIR is set (either\n   as an environment variable or via the --gnulib-refdir option) and is\n   a git repository, then it is used as a reference.\n\n * Otherwise, if the 'gnulib' directory does not exist, Gnulib sources\n   are cloned into that directory using git from \\$GNULIB_URL, defaulting\n   to $default_gnulib_url; if GNULIB_REFDIR is set and is a git repository\n   its contents may be used to accelerate the process.\n   If the configuration variable GNULIB_REVISION is set in bootstrap.conf,\n   then that revision is checked out.\n\n * Otherwise, the existing Gnulib sources in the 'gnulib' directory are\n   used.  If it is a git repository and the configuration variable\n   GNULIB_REVISION is set in bootstrap.conf, then that revision is\n   checked out.\n\nIf you maintain a package and want to pin a particular revision of the\nGnulib sources that has been tested with your package, then there are\ntwo possible approaches: either configure a 'gnulib' submodule with the\nappropriate revision, or set GNULIB_REVISION (and if necessary\nGNULIB_URL) in bootstrap.conf.\n\nRunning without arguments will suffice in most cases.\nEOF\n}\n\n# Parse options.\n\n# Whether to pull and generate.\npull=false\ngen=false\n\n# Whether to use copies instead of symlinks.\ncopy=false\n\n# Use git to update gnulib sources\nuse_git=true\n\nfor option\ndo\n  case $option in\n  --help)\n    usage\n    exit;;\n  --version)\n    set -e\n    echo \"bootstrap $scriptversion lib $scriptlibversion\"\n    echo \"$copyright\"\n    exit 0\n    ;;\n  --pull)\n    pull=true;;\n  --gen)\n    gen=true;;\n  --gnulib-srcdir=*)\n    GNULIB_SRCDIR=${option#--gnulib-srcdir=};;\n  --gnulib-refdir=*)\n    GNULIB_REFDIR=${option#--gnulib-refdir=};;\n  --skip-po)\n    SKIP_PO=t;;\n  --force)\n    checkout_only_file=;;\n  --copy)\n    copy=true;;\n  --bootstrap-sync)\n    bootstrap_sync=true;;\n  --no-bootstrap-sync)\n    bootstrap_sync=false;;\n  --no-git)\n    use_git=false;;\n  *)\n    bootstrap_option_hook $option || die \"$option: unknown option\";;\n  esac\ndone\n\n# Default is to do both.\n$pull || $gen || pull=true gen=true\n\n$use_git || test -n \"$GNULIB_SRCDIR\" \\\n  || die \"Error: --no-git requires \\$GNULIB_SRCDIR environment variable\" \\\n         \"or --gnulib-srcdir option\"\ntest -z \"$GNULIB_SRCDIR\" || test -d \"$GNULIB_SRCDIR\" \\\n  || die \"Error: \\$GNULIB_SRCDIR environment variable or --gnulib-srcdir\" \\\n         \"option is specified, but does not denote a directory\"\n\nif test -n \"$checkout_only_file\" && test ! -r \"$checkout_only_file\"; then\n  die \"Bootstrapping from a non-checked-out distribution is risky.\"\nfi\n\ncheck_build_prerequisites $use_git\n\nif $bootstrap_sync; then\n  prepare_GNULIB_SRCDIR\n  upgrade_bootstrap \"$@\"\n  # Since we have now upgraded if needed, no need to try it a second time below.\n  bootstrap_sync=false\nfi\n\necho \"$0: Bootstrapping from checked-out $package sources...\"\n\n# Pass GNULIB_SRCDIR and GNULIB_REFDIR to any subsidiary commands that care.\nexport GNULIB_SRCDIR\nexport GNULIB_REFDIR\n\nif $pull && { $use_git || test -z \"$SKIP_PO\"; }; then\n  autopull \\\n      `if $bootstrap_sync; then\n         echo ' --bootstrap-sync'\n       else\n         echo ' --no-bootstrap-sync'\n       fi` \\\n      `if test -z \"$checkout_only_file\"; then echo ' --force'; fi` \\\n      `if ! $use_git; then echo ' --no-git'; fi` \\\n      `if test -n \"$SKIP_PO\"; then echo ' --skip-po'; fi` \\\n    || die \"could not fetch auxiliary files\"\nfi\n\nif $gen; then\n  autogen \\\n      `if $copy; then echo ' --copy'; fi` \\\n      `if test -z \"$checkout_only_file\"; then echo ' --force'; fi` \\\n    || die \"could not generate auxiliary files\"\nfi\n\n# ----------------------------------------------------------------------------\n\n# Local Variables:\n# eval: (add-hook 'before-save-hook 'time-stamp nil t)\n# time-stamp-start: \"scriptversion=\"\n# time-stamp-format: \"%Y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC0\"\n# time-stamp-end: \"; # UTC\"\n# End:\n"
  },
  {
    "path": "bootstrap-funclib.sh",
    "content": "# A library of shell functions for autopull.sh, autogen.sh, and bootstrap.\n\nscriptlibversion=2025-11-12.14; # UTC\n\n# Copyright (C) 2003-2025 Free Software Foundation, Inc.\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Originally written by Paul Eggert.  The canonical version of this\n# script is maintained as top/bootstrap-funclib.sh in gnulib.  However,\n# to be useful to your package, you should place a copy of it under\n# version control in the top-level directory of your package.  The\n# intent is that all customization can be done with a bootstrap.conf\n# file also maintained in your version control; gnulib comes with a\n# template build-aux/bootstrap.conf to get you started.\n\nnl='\n'\n\n# Ensure file names are sorted consistently across platforms.\nLC_ALL=C\nexport LC_ALL\n\n# Honor $PERL, but work even if there is none.\nPERL=\"${PERL-perl}\"\n\ndefault_gnulib_url=https://https.git.savannah.gnu.org/git/gnulib.git\n\n# Copyright year, for the --version output.\ncopyright_year=`echo \"$scriptlibversion\" | sed -e 's/[^0-9].*//'`\ncopyright=\"Copyright (C) ${copyright_year} Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\"\n\n# warnf_ FORMAT-STRING ARG1...\nwarnf_ ()\n{\n  warnf_format_=$1\n  shift\n  nl='\n'\n  case $* in\n    *$nl*) me_=$(printf \"$me\"|tr \"$nl|\" '??')\n       printf \"$warnf_format_\" \"$@\" | sed \"s|^|$me_: |\" ;;\n    *) printf \"$me: $warnf_format_\" \"$@\" ;;\n  esac >&2\n}\n\n# warn_ WORD1...\nwarn_ ()\n{\n  # If IFS does not start with ' ', set it and emit the warning in a subshell.\n  case $IFS in\n    ' '*) warnf_ '%s\\n' \"$*\";;\n    *)    (IFS=' '; warn_ \"$@\");;\n  esac\n}\n\n# die WORD1...\ndie() { warn_ \"$@\"; exit 1; }\n\n# ------------------------------ Configuration. ------------------------------\n\n# Directory that contains package-specific gnulib modules and/or overrides.\nlocal_gl_dir=gl\n\n# Name of the Makefile.am\n# XXX Not used.\ngnulib_mk=gnulib.mk\n\n# List of gnulib modules needed.\ngnulib_modules=\n\n# Any gnulib files needed that are not in modules.\ngnulib_files=\n\n# A function to be called for each unrecognized option.  Returns 0 if\n# the option in $1 has been processed by the function.  Returns 1 if\n# the option has not been processed by the function.  Override it via\n# your own definition in bootstrap.conf\nbootstrap_option_hook() { return 1; }\n\n# A function to be called in order to print the --help information\n# corresponding to user-defined command-line options.\nbootstrap_print_option_usage_hook() { :; }\n\n# A function to be called at the end of autopull.sh.\n# Override it via your own definition in bootstrap.conf.\nbootstrap_post_pull_hook() { :; }\n\n# A function to be called right after gnulib-tool is run.\n# Override it via your own definition in bootstrap.conf.\nbootstrap_post_import_hook() { :; }\n\n# A function to be called after everything else in this script.\n# Override it via your own definition in bootstrap.conf.\nbootstrap_epilogue() { :; }\n\n# The command to download all .po files for a specified domain into a\n# specified directory.  Fill in the first %s with the destination\n# directory and the second with the domain name.\npo_download_command_format=\\\n\"wget --mirror --level=1 -nd -nv -A.po -P '%s' \\\n https://translationproject.org/latest/%s/\"\n\n# When extracting the package name from an AC_INIT invocation,\n# prefer a non-empty tarname (4th argument of AC_INIT if given), else\n# fall back to the package name (1st argument with munging).\nextract_package_name='\n  /^AC_INIT(\\[*/{\n     s///\n     /^[^,]*,[^,]*,[^,]*,[ []*\\([^][ ,)]\\)/{\n       s//\\1/\n       s/[],)].*//\n       p\n       q\n     }\n     s/[],)].*//\n     p\n  }\n'\nnormalize_package_name='\n  s/^GNU //\n  y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/\n  s/[^abcdefghijklmnopqrstuvwxyz0123456789_]/-/g\n'\npackage=$(${AUTOCONF:-autoconf} --trace 'AC_INIT:$4' configure.ac 2>/dev/null)\nif test -z \"$package\"; then\n  package=$(sed -n \"$extract_package_name\" configure.ac) \\\n      || die 'cannot find package name in configure.ac'\nfi\npackage=$(echo \"$package\" | sed \"$normalize_package_name\")\ngnulib_name=lib$package\n\nbuild_aux=build-aux\nsource_base=lib\nm4_base=m4\ndoc_base=doc\ntests_base=tests\ngnulib_extra_files=\"\n        build-aux/install-sh\n        build-aux/mdate-sh\n        build-aux/texinfo.tex\n        build-aux/depcomp\n        build-aux/config.guess\n        build-aux/config.sub\n        doc/INSTALL\n\"\n\n# Additional gnulib-tool options to use.  Use \"\\newline\" to break lines.\ngnulib_tool_option_extras=\n\n# Other locale categories that need message catalogs.\nEXTRA_LOCALE_CATEGORIES=\n\n# Additional xgettext options to use.  Use \"\\\\\\newline\" to break lines.\nXGETTEXT_OPTIONS='\\\\\\\n --flag=_:1:pass-c-format\\\\\\\n --flag=N_:1:pass-c-format\\\\\\\n --flag=error:3:c-format --flag=error_at_line:5:c-format\\\\\\\n'\n\n# Package bug report address and copyright holder for gettext files\nCOPYRIGHT_HOLDER='Free Software Foundation, Inc.'\nMSGID_BUGS_ADDRESS=bug-$package@gnu.org\n\n# Files we don't want to import.\n# XXX Not used.\nexcluded_files=\n\n# File that should exist in the top directory of a checked out hierarchy,\n# but not in a distribution tarball.\ncheckout_only_file=README-hacking\n\n# Set this to '.cvsignore .gitignore' in bootstrap.conf if you want\n# those files to be generated in directories like lib/, m4/, and po/.\n# Or set it to 'auto' to make this script select which to use based\n# on which version control system (if any) is used in the source directory.\nvc_ignore=auto\n\n# Set this to true in bootstrap.conf to enable --bootstrap-sync by\n# default.\nbootstrap_sync=false\n\n# Override the default configuration, if necessary.\n# Make sure that bootstrap.conf is sourced from the current directory\n# if we were invoked as \"sh bootstrap\".\nconffile=`dirname \"$me\"`/bootstrap.conf\ntest -r \"$conffile\" && . \"$conffile\"\n\n# ------------------------- Build-time prerequisites -------------------------\n\ncheck_exists() {\n  if test \"$1\" = \"--verbose\"; then\n    ($2 --version </dev/null) >/dev/null 2>&1\n    if test $? -ge 126; then\n      # If not found, run with diagnostics as one may be\n      # presented with env variables to set to find the right version\n      ($2 --version </dev/null)\n    fi\n  else\n    ($1 --version </dev/null) >/dev/null 2>&1\n  fi\n\n  test $? -lt 126\n}\n\n# Note this deviates from the version comparison in automake\n# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a\n# but this should suffice as we won't be specifying old\n# version formats or redundant trailing .0 in bootstrap.conf.\n# If we did want full compatibility then we should probably\n# use m4_version_compare from autoconf.\nsort_ver() { # sort -V is not generally available\n  ver1=\"$1\"\n  ver2=\"$2\"\n\n  # split on '.' and compare each component\n  i=1\n  while : ; do\n    p1=$(echo \"$ver1\" | cut -d. -f$i)\n    p2=$(echo \"$ver2\" | cut -d. -f$i)\n    if [ ! \"$p1\" ]; then\n      echo \"$1 $2\"\n      break\n    elif [ ! \"$p2\" ]; then\n      echo \"$2 $1\"\n      break\n    elif [ ! \"$p1\" = \"$p2\" ]; then\n      if [ \"$p1\" -gt \"$p2\" ] 2>/dev/null; then # numeric comparison\n        echo \"$2 $1\"\n      elif [ \"$p2\" -gt \"$p1\" ] 2>/dev/null; then # numeric comparison\n        echo \"$1 $2\"\n      else # numeric, then lexicographic comparison\n        lp=$(printf \"%s\\n%s\\n\" \"$p1\" \"$p2\" | LANG=C sort -n | tail -n1)\n        if [ \"$lp\" = \"$p2\" ]; then\n          echo \"$1 $2\"\n        else\n          echo \"$2 $1\"\n        fi\n      fi\n      break\n    fi\n    i=$(($i+1))\n  done\n}\n\nget_version_sed='\n# Move version to start of line.\ns/.*[v ]\\([0-9]\\)/\\1/\n\n# Skip lines that do not start with version.\n/^[0-9]/!d\n\n# Remove characters after the version.\ns/[^.a-z0-9-].*//\n\n# The first component must be digits only.\ns/^\\([0-9]*\\)[a-z-].*/\\1/\n\n#the following essentially does s/5.005/5.5/\ns/\\.0*\\([1-9]\\)/.\\1/g\np\nq'\n\nget_version() {\n  app=$1\n\n  $app --version >/dev/null 2>&1 || { $app --version; return 1; }\n\n  $app --version 2>&1 | sed -n \"$get_version_sed\"\n}\n\ncheck_versions() {\n  ret=0\n\n  while read app req_ver; do\n    # We only need libtoolize from the libtool package.\n    if test \"$app\" = libtool; then\n      app=libtoolize\n    fi\n    # Exempt git if git is not needed.\n    if test \"$app\" = git; then\n      $check_git || continue\n    fi\n    # Honor $APP variables ($TAR, $AUTOCONF, etc.)\n    appvar=$(echo $app | LC_ALL=C tr '[a-z]-' '[A-Z]_')\n    test \"$appvar\" = TAR && appvar=AMTAR\n    case $appvar in\n        GZIP) ;; # Do not use $GZIP:  it contains gzip options.\n        PERL::*) ;; # Keep perl modules as-is\n        *) eval \"app=\\${$appvar-$app}\" ;;\n    esac\n\n    # Handle the still-experimental Automake-NG programs specially.\n    # They remain named as the mainstream Automake programs (\"automake\",\n    # and \"aclocal\") to avoid gratuitous incompatibilities with\n    # preexisting usages (by, say, autoreconf, or custom autogen.sh\n    # scripts), but correctly identify themselves (as being part of\n    # \"GNU automake-ng\") when asked their version.\n    case $app in\n      automake-ng|aclocal-ng)\n        app=${app%-ng}\n        ($app --version | grep '(GNU automake-ng)') >/dev/null 2>&1 || {\n          warn_ \"Error: '$app' not found or not from Automake-NG\"\n          ret=1\n          continue\n        } ;;\n      # Another check is for perl modules.  These can be written as\n      # e.g. perl::XML::XPath in case of XML::XPath module, etc.\n      perl::*)\n        # Extract module name\n        app=\"${app#perl::}\"\n        if ! $PERL -m\"$app\" -e 'exit 0' >/dev/null 2>&1; then\n          warn_ \"Error: perl module '$app' not found\"\n          ret=1\n        fi\n        continue\n        ;;\n    esac\n    if [ \"$req_ver\" = \"-\" ]; then\n      # Merely require app to exist; not all prereq apps are well-behaved\n      # so we have to rely on $? rather than get_version.\n      if ! check_exists --verbose $app; then\n        warn_ \"Error: '$app' not found\"\n        ret=1\n      fi\n    else\n      # Require app to produce a new enough version string.\n      inst_ver=$(get_version $app)\n      if [ ! \"$inst_ver\" ]; then\n        warn_ \"Error: '$app' not found\"\n        ret=1\n      else\n        latest_ver=$(sort_ver $req_ver $inst_ver | cut -d' ' -f2)\n        if [ ! \"$latest_ver\" = \"$inst_ver\" ]; then\n          warnf_ '%s\\n'                                        \\\n              \"Error: '$app' version == $inst_ver is too old\"  \\\n              \"       '$app' version >= $req_ver is required\"\n          ret=1\n        fi\n      fi\n    fi\n  done\n\n  return $ret\n}\n\nprint_versions() {\n  echo \"Program    Min_version\"\n  echo \"----------------------\"\n  printf %s \"$buildreq\"\n  echo \"----------------------\"\n  # can't depend on column -t\n}\n\n# check_build_prerequisites check_git\ncheck_build_prerequisites()\n{\n  check_git=\"$1\"\n\n  # gnulib-tool requires at least automake and autoconf.\n  # If either is not listed, add it (with minimum version) as a prerequisite.\n  case $buildreq in\n    *automake*) ;;\n    *) buildreq=\"automake 1.9\n$buildreq\" ;;\n  esac\n  case $buildreq in\n    *autoconf*) ;;\n    *) buildreq=\"autoconf 2.59\n$buildreq\" ;;\n  esac\n\n  # When we can deduce that gnulib-tool will require patch,\n  # and when patch is not already listed as a prerequisite, add it, too.\n  if test -d \"$local_gl_dir\" \\\n     && ! find \"$local_gl_dir\" -name '*.diff' -exec false {} +; then\n    case $buildreq in\n      *patch*) ;;\n      *) buildreq=\"patch -\n$buildreq\" ;;\n    esac\n  fi\n\n  if ! printf '%s' \"$buildreq\" | check_versions; then\n    echo >&2\n    if test -f README-prereq; then\n      die \"See README-prereq for how to get the prerequisite programs\"\n    else\n      die \"Please install the prerequisite programs\"\n    fi\n  fi\n\n  # Warn the user if autom4te appears to be broken; this causes known\n  # issues with at least gettext 0.18.3.\n  probe=$(echo 'm4_quote([hi])' | autom4te -l M4sugar -t 'm4_quote:$%' -)\n  if test \"x$probe\" != xhi; then\n    warn_ \"WARNING: your autom4te wrapper eats stdin;\"\n    warn_ \"if bootstrap fails, consider upgrading your autotools\"\n  fi\n}\n\n# find_tool ENVVAR NAMES...\n# -------------------------\n# Search for a required program.  Use the value of ENVVAR, if set,\n# otherwise find the first of the NAMES that can be run.\n# If found, set ENVVAR to the program name, die otherwise.\n#\n# FIXME: code duplication, see also gnu-web-doc-update.\nfind_tool ()\n{\n  find_tool_envvar=$1\n  shift\n  find_tool_names=$@\n  eval \"find_tool_res=\\$$find_tool_envvar\"\n  if test x\"$find_tool_res\" = x; then\n    for i; do\n      if check_exists $i; then\n        find_tool_res=$i\n        break\n      fi\n    done\n  fi\n  if test x\"$find_tool_res\" = x; then\n    warn_ \"one of these is required: $find_tool_names;\"\n    die   \"alternatively set $find_tool_envvar to a compatible tool\"\n  fi\n  eval \"$find_tool_envvar=\\$find_tool_res\"\n  eval \"export $find_tool_envvar\"\n}\n\n# --------------------- Preparing GNULIB_SRCDIR for use. ---------------------\n# This is part of autopull.sh, but bootstrap needs it too, for self-upgrading.\n\n# cleanup_gnulib fails, removing the directory $gnulib_path first.\ncleanup_gnulib() {\n  status=$?\n  rm -fr \"$gnulib_path\"\n  exit $status\n}\n\ngit_modules_config () {\n  test -f .gitmodules && git config --file .gitmodules \"$@\"\n}\n\nprepare_GNULIB_SRCDIR ()\n{\n  if test -n \"$GNULIB_SRCDIR\"; then\n    # Use GNULIB_SRCDIR directly.\n    # We already checked that $GNULIB_SRCDIR references a directory.\n    # Verify that it contains a gnulib checkout.\n    test -f \"$GNULIB_SRCDIR/gnulib-tool\" \\\n      || die \"Error: --gnulib-srcdir or \\$GNULIB_SRCDIR is specified,\" \\\n             \"but does not contain gnulib-tool\"\n    if test -n \"$GNULIB_REVISION\" && $use_git; then\n      # The 'git checkout \"$GNULIB_REVISION\"' command succeeds if the\n      # GNULIB_REVISION is a commit hash that exists locally, or if it is\n      # branch name that can be fetched from origin. It fails, however,\n      # if the GNULIB_REVISION is a commit hash that only exists in\n      # origin. In this case, we need a 'git fetch' and then retry\n      # 'git checkout \"$GNULIB_REVISION\"'.\n      git -C \"$GNULIB_SRCDIR\" checkout \"$GNULIB_REVISION\" 2>/dev/null \\\n      || { git -C \"$GNULIB_SRCDIR\" fetch origin \\\n           && git -C \"$GNULIB_SRCDIR\" checkout \"$GNULIB_REVISION\"; } \\\n      || exit $?\n    fi\n  else\n    if ! $use_git; then\n      die \"Error: --no-git is specified,\" \\\n          \"but neither --gnulib-srcdir nor \\$GNULIB_SRCDIR is specified\"\n    fi\n    if git submodule -h | grep -- --reference > /dev/null; then\n      :\n    else\n      die \"git version is too old, git >= 1.6.4 is required\"\n    fi\n    gnulib_path=$(git_modules_config submodule.gnulib.path)\n    if test -n \"$gnulib_path\"; then\n      # A submodule 'gnulib' is configured.\n      # Get gnulib files.  Populate $gnulib_path, updating the submodule.\n      if test -n \"$GNULIB_REFDIR\" && test -d \"$GNULIB_REFDIR\"/.git; then\n        # Use GNULIB_REFDIR as a reference.\n        echo \"$0: getting gnulib files...\"\n        git submodule update --init --reference \"$GNULIB_REFDIR\" \"$gnulib_path\"\\\n          || exit $?\n      else\n        # GNULIB_REFDIR is not set or not usable. Ignore it.\n        if git_modules_config submodule.gnulib.url >/dev/null; then\n          echo \"$0: getting gnulib files...\"\n          git submodule init -- \"$gnulib_path\" || exit $?\n          git submodule update -- \"$gnulib_path\" || exit $?\n        else\n          die \"Error: submodule 'gnulib' has no configured url\"\n        fi\n      fi\n    else\n      gnulib_path='gnulib'\n      if test ! -d \"$gnulib_path\"; then\n        # The subdirectory 'gnulib' does not yet exist. Clone into it.\n        echo \"$0: getting gnulib files...\"\n        trap cleanup_gnulib HUP INT PIPE TERM\n        gnulib_url=${GNULIB_URL:-$default_gnulib_url}\n        if test -n \"$GNULIB_REFDIR\" && test -d \"$GNULIB_REFDIR\"/.git; then\n          # Use GNULIB_REFDIR as a reference.\n          git clone \"$GNULIB_REFDIR\" \"$gnulib_path\" \\\n          && git -C \"$gnulib_path\" remote set-url origin \"$gnulib_url\" \\\n          && if test -z \"$GNULIB_REVISION\"; then\n               git -C \"$gnulib_path\" pull origin \\\n               && {\n                 # We want the default branch of \"$gnulib_url\" (since that's\n                 # the behaviour if GNULIB_REFDIR is not specified), not the\n                 # current branch of \"$GNULIB_REFDIR\".\n                 default_branch=`LC_ALL=C git -C \"$gnulib_path\" \\\n                                              remote show origin \\\n                                 | sed -n -e 's/^ *HEAD branch: //p'`\n                 test -n \"$default_branch\" || default_branch='master'\n                 git -C \"$gnulib_path\" checkout \"$default_branch\"\n               }\n             else\n               # The 'git checkout \"$GNULIB_REVISION\"' command succeeds if the\n               # GNULIB_REVISION is a commit hash that exists locally, or if it\n               # is a branch name that can be fetched from origin. It fails,\n               # however, if the GNULIB_REVISION is a commit hash that only\n               # exists in origin. In this case, we need a 'git fetch' and then\n               # retry 'git checkout \"$GNULIB_REVISION\"'.\n               git -C \"$gnulib_path\" checkout \"$GNULIB_REVISION\" 2>/dev/null \\\n               || { git -C \"$gnulib_path\" fetch origin \\\n                    && git -C \"$gnulib_path\" checkout \"$GNULIB_REVISION\"; }\n             fi \\\n          || cleanup_gnulib\n        else\n          # GNULIB_REFDIR is not set or not usable. Ignore it.\n          shallow='--depth 2'\n          if test -z \"$GNULIB_REVISION\"; then\n            git clone $shallow \"$gnulib_url\" \"$gnulib_path\" \\\n              || cleanup_gnulib\n          else\n            # Only want a shallow checkout of $GNULIB_REVISION, but git does not\n            # support cloning by commit hash. So attempt a shallow fetch by\n            # commit hash to minimize the amount of data downloaded and changes\n            # needed to be processed, which can drastically reduce download and\n            # processing time for checkout. If the fetch by commit fails, a\n            # shallow fetch cannot be performed because we do not know what the\n            # depth of the commit is without fetching all commits. So fall back\n            # to fetching all commits.\n            # $GNULIB_REVISION can be a commit id, a tag name, or a branch name.\n            mkdir -p \"$gnulib_path\"\n            # Use a -c option to silence an annoying message\n            # \"hint: Using 'master' as the name for the initial branch.\"\n            # (cf. <https://stackoverflow.com/questions/65524512/>).\n            git -C \"$gnulib_path\" -c init.defaultBranch=master init\n            git -C \"$gnulib_path\" remote add origin \"$gnulib_url\"\n            if git -C \"$gnulib_path\" fetch $shallow origin \"$GNULIB_REVISION\"\n            then\n              # \"git fetch\" of the specific commit succeeded.\n              git -C \"$gnulib_path\" reset --hard FETCH_HEAD \\\n                || cleanup_gnulib\n              # \"git fetch\" does not fetch tags (at least in git version 2.43).\n              # If $GNULIB_REVISION is a tag (not a commit id or branch name),\n              # add the tag explicitly.\n              revision=`git -C \"$gnulib_path\" log -1 --pretty=format:%H`\n              branch=`LC_ALL=C git -C \"$gnulib_path\" remote show origin \\\n                      | sed -n -e 's/^    \\([^ ]*\\) * tracked$/\\1/p'`\n              test \"$revision\" = \"$GNULIB_REVISION\" \\\n                || test \"$branch\" = \"$GNULIB_REVISION\" \\\n                || git -C \"$gnulib_path\" tag \"$GNULIB_REVISION\"\n            else\n              # Fetch the entire repository.\n              git -C \"$gnulib_path\" fetch origin \\\n                || cleanup_gnulib\n              git -C \"$gnulib_path\" checkout \"$GNULIB_REVISION\" \\\n                || cleanup_gnulib\n            fi\n          fi\n        fi\n        trap - HUP INT PIPE TERM\n      else\n        # The subdirectory 'gnulib' already exists.\n        if test -n \"$GNULIB_REVISION\"; then\n          if test -d \"$gnulib_path/.git\"; then\n            # The 'git checkout \"$GNULIB_REVISION\"' command succeeds if the\n            # GNULIB_REVISION is a commit hash that exists locally, or if it\n            # is a branch name that can be fetched from origin. It fails,\n            # however, if the GNULIB_REVISION is a commit hash that only\n            # exists in origin. In this case, we need a 'git fetch' and then\n            # retry 'git checkout \"$GNULIB_REVISION\"'.\n            git -C \"$gnulib_path\" checkout \"$GNULIB_REVISION\" 2>/dev/null \\\n            || { git -C \"$gnulib_path\" fetch origin \\\n                 && git -C \"$gnulib_path\" checkout \"$GNULIB_REVISION\"; } \\\n            || exit $?\n          else\n            die \"Error: GNULIB_REVISION is specified in bootstrap.conf,\" \\\n                \"but '$gnulib_path' contains no git history\"\n          fi\n        fi\n      fi\n    fi\n    # Verify that $gnulib_path contains a gnulib checkout.\n    test -f \"$gnulib_path/gnulib-tool\" \\\n      || die \"Error: '$gnulib_path' is supposed to contain a gnulib checkout,\" \\\n             \"but does not contain gnulib-tool\"\n    GNULIB_SRCDIR=$gnulib_path\n  fi\n  # $GNULIB_SRCDIR now points to the version of gnulib to use, and\n  # we no longer need to use git or $gnulib_path below here.\n}\n\n# -------- Upgrading bootstrap to the version found in GNULIB_SRCDIR. --------\n\nupgrade_bootstrap ()\n{\n  if test -f \"$medir\"/bootstrap-funclib.sh; then\n    update_lib=true\n    { cmp -s \"$medir\"/bootstrap \"$GNULIB_SRCDIR/top/bootstrap\" \\\n      && cmp -s \"$medir\"/bootstrap-funclib.sh \\\n                \"$GNULIB_SRCDIR/top/bootstrap-funclib.sh\" \\\n      && cmp -s \"$medir\"/autopull.sh \"$GNULIB_SRCDIR/top/autopull.sh\" \\\n      && cmp -s \"$medir\"/autogen.sh \"$GNULIB_SRCDIR/top/autogen.sh\"; \\\n    }\n  else\n    update_lib=false\n    cmp -s \"$medir\"/bootstrap \"$GNULIB_SRCDIR/build-aux/bootstrap\"\n  fi || {\n    if $update_lib; then\n      echo \"$0: updating bootstrap & companions and restarting...\"\n    else\n      echo \"$0: updating bootstrap and restarting...\"\n    fi\n    case $(sh -c 'echo \"$1\"' -- a) in\n      a) ignored=--;;\n      *) ignored=ignored;;\n    esac\n    u=$update_lib\n    exec sh -c \\\n      '{ if '$u' && test -f \"$1\"; then cp \"$1\" \"$3\"; else cp \"$2\" \"$3\"; fi; } &&\n       { if '$u' && test -f \"$4\"; then cp \"$4\" \"$5\"; else rm -f \"$5\"; fi; } &&\n       { if '$u' && test -f \"$6\"; then cp \"$6\" \"$7\"; else rm -f \"$7\"; fi; } &&\n       { if '$u' && test -f \"$8\"; then cp \"$8\" \"$9\"; else rm -f \"$9\"; fi; } &&\n       shift && shift && shift && shift && shift &&\n       shift && shift && shift && shift &&\n       exec \"${CONFIG_SHELL-/bin/sh}\" \"$@\"' \\\n      $ignored \\\n      \"$GNULIB_SRCDIR/top/bootstrap\" \"$GNULIB_SRCDIR/build-aux/bootstrap\" \\\n      \"$medir/bootstrap\" \\\n      \"$GNULIB_SRCDIR/top/bootstrap-funclib.sh\" \"$medir/bootstrap-funclib.sh\" \\\n      \"$GNULIB_SRCDIR/top/autopull.sh\" \"$medir/autopull.sh\" \\\n      \"$GNULIB_SRCDIR/top/autogen.sh\" \"$medir/autogen.sh\" \\\n      \"$0\" \"$@\" --no-bootstrap-sync\n  }\n}\n\n# ----------------------------------------------------------------------------\n\nif test x\"$gnulib_modules$gnulib_files$gnulib_extra_files\" = x; then\n  use_gnulib=false\nelse\n  use_gnulib=true\nfi\n\n# -------- Fetch auxiliary files from the network.  --------------------------\n\nautopull_usage() {\n  cat <<EOF\nUsage: $me [OPTION]...\nBootstrap this package from the checked-out sources, phase 1:\nPull files from the network.\n\nOptional environment variables:\n  GNULIB_SRCDIR            Specifies the local directory where gnulib\n                           sources reside.  Use this if you already\n                           have gnulib sources on your machine, and\n                           you want to use these sources.\n  GNULIB_REFDIR            Specifies the local directory where a gnulib\n                           repository (with a .git subdirectory) resides.\n                           Use this if you already have gnulib sources\n                           and history on your machine, and do not want\n                           to waste your bandwidth downloading them again.\n  GNULIB_URL               URL of the gnulib repository.  The default is\n                           $default_gnulib_url,\n                           which is Gnulib's upstream repository.\n\nOptions:\n\n  --bootstrap-sync         If this bootstrap script is not identical to\n                           the version in the local gnulib sources,\n                           update this script, and then restart it with\n                           /bin/sh or the shell \\$CONFIG_SHELL.\n  --no-bootstrap-sync      Do not check whether bootstrap is out of sync.\n\n  --force                  Attempt to bootstrap even if the sources seem\n                           not to have been checked out.\n  --no-git                 Do not use git to update gnulib.  Requires that\n                           \\$GNULIB_SRCDIR points to a gnulib repository\n                           with the correct revision.\n  --skip-po                Do not download *.po files.\nEOF\n  bootstrap_print_option_usage_hook\n  cat <<EOF\nIf the file bootstrap.conf exists in the same directory as this script, its\ncontents are read as shell variables to configure the bootstrap.\n\nFor build prerequisites, environment variables like \\$AUTOCONF and \\$AMTAR\nare honored.\n\nGnulib sources can be fetched in various ways:\n\n * If the environment variable GNULIB_SRCDIR is set, then sources are\n   fetched from that local directory.  If it is a git repository and the\n   configuration variable GNULIB_REVISION is set in bootstrap.conf, then\n   that revision is checked out.\n\n * Otherwise, if this package is in a git repository with a 'gnulib'\n   submodule configured, then that submodule is initialized and updated\n   and sources are fetched from there.  If the environment variable\n   GNULIB_REFDIR is set and is a git repository, then it is used as a\n   reference.\n\n * Otherwise, if the 'gnulib' directory does not exist, Gnulib sources\n   are cloned into that directory using git from \\$GNULIB_URL, defaulting\n   to $default_gnulib_url; if GNULIB_REFDIR is set and is a git repository\n   its contents may be used to accelerate the process.\n   If the configuration variable GNULIB_REVISION is set in bootstrap.conf,\n   then that revision is checked out.\n\n * Otherwise, the existing Gnulib sources in the 'gnulib' directory are\n   used.  If it is a git repository and the configuration variable\n   GNULIB_REVISION is set in bootstrap.conf, then that revision is\n   checked out.\n\nIf you maintain a package and want to pin a particular revision of the\nGnulib sources that has been tested with your package, then there are\ntwo possible approaches: either configure a 'gnulib' submodule with the\nappropriate revision, or set GNULIB_REVISION (and if necessary\nGNULIB_URL) in bootstrap.conf.\n\nRunning without arguments will suffice in most cases.\nEOF\n}\n\n# Fetch auxiliary files that are omitted from the version control\n# repository of this package.\nautopull()\n{\n  # Ensure that CDPATH is not set.  Otherwise, the output from cd\n  # would cause trouble in at least one use below.\n  (unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n  # Parse options.\n\n  # Use git to update gnulib sources\n  use_git=true\n\n  for option\n  do\n    case $option in\n    --help)\n      autopull_usage\n      return;;\n    --version)\n      set -e\n      echo \"autopull.sh $scriptlibversion\"\n      echo \"$copyright\"\n      return 0\n      ;;\n    --skip-po)\n      SKIP_PO=t;;\n    --force)\n      checkout_only_file=;;\n    --bootstrap-sync)\n      bootstrap_sync=true;;\n    --no-bootstrap-sync)\n      bootstrap_sync=false;;\n    --no-git)\n      use_git=false;;\n    *)\n      bootstrap_option_hook $option || die \"$option: unknown option\";;\n    esac\n  done\n\n  $use_git || test -n \"$GNULIB_SRCDIR\" \\\n    || die \"Error: --no-git requires \\$GNULIB_SRCDIR environment variable\" \\\n           \"or --gnulib-srcdir option\"\n  test -z \"$GNULIB_SRCDIR\" || test -d \"$GNULIB_SRCDIR\" \\\n    || die \"Error: \\$GNULIB_SRCDIR environment variable\" \\\n           \"or --gnulib-srcdir option is specified,\" \\\n           \"but does not denote a directory\"\n\n  if test -n \"$checkout_only_file\" && test ! -r \"$checkout_only_file\"; then\n    die \"Running this script from a non-checked-out distribution is risky.\"\n  fi\n\n  check_build_prerequisites $use_git\n\n  if $use_gnulib || $bootstrap_sync; then\n    prepare_GNULIB_SRCDIR\n    if $bootstrap_sync; then\n      upgrade_bootstrap \"$@\"\n    fi\n  fi\n\n  # Find sha1sum, named gsha1sum on MacPorts, shasum on Mac OS X 10.6.\n  # Also find the compatible sha1 utility on the BSDs\n  if test x\"$SKIP_PO\" = x; then\n    find_tool SHA1SUM sha1sum gsha1sum shasum sha1\n  fi\n\n  # See if we can use gnulib's git-merge-changelog merge driver.\n  if $use_git && test -d .git && check_exists git; then\n    if git config merge.merge-changelog.driver >/dev/null ; then\n      :\n    elif check_exists git-merge-changelog; then\n      echo \"$0: initializing git-merge-changelog driver\"\n      git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver'\n      git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B \"%Y\"'\n    else\n      echo \"$0: consider installing git-merge-changelog from gnulib\"\n    fi\n  fi\n\n  case $SKIP_PO in\n  '')\n    if test -d po; then\n      update_po_files po $package || return\n    fi\n\n    if test -d runtime-po; then\n      update_po_files runtime-po $package-runtime || return\n    fi;;\n  esac\n\n  # ---------------------------------------------------------------------------\n\n  bootstrap_post_pull_hook \\\n    || die \"bootstrap_post_pull_hook failed\"\n\n  # Don't proceed if there are uninitialized submodules.  In particular,\n  # autogen.sh will remove dangling links, which might be links into\n  # uninitialized submodules.\n  # But it's OK if the 'gnulib' submodule is uninitialized, as long as\n  # GNULIB_SRCDIR is set.\n  if $use_git; then\n    # Uninitialized submodules are listed with an initial dash.\n    uninitialized=`git submodule | grep '^-' | awk '{ print $2 }'`\n    if test -n \"$GNULIB_SRCDIR\"; then\n      uninitialized=`echo \"$uninitialized\" | grep -v '^gnulib$'`\n    fi\n    if test -n \"$uninitialized\"; then\n      uninit_comma=`echo \"$uninitialized\" | tr '\\n' ',' | sed -e 's|,$|.|'`\n      die \"Some git submodules are not initialized: \"$uninit_comma \\\n          \"Either use option '--no-git',\" \\\n          \"or run 'git submodule update --init' and bootstrap again.\"\n    fi\n  fi\n\n  if test -f \"$medir\"/autogen.sh; then\n    echo \"$0: done.  Now you can run '$medir/autogen.sh'.\"\n  fi\n}\n\n# ----------------------------- Get translations. -----------------------------\n\ndownload_po_files() {\n  subdir=$1\n  domain=$2\n  echo \"$me: getting translations into $subdir for $domain...\"\n  cmd=$(printf \"$po_download_command_format\" \"$subdir\" \"$domain\")\n  eval \"$cmd\"\n}\n\n# Mirror .po files to $po_dir/.reference and copy only the new\n# or modified ones into $po_dir.  Also update $po_dir/LINGUAS.\n# Note po files that exist locally only are left in $po_dir but will\n# not be included in LINGUAS and hence will not be distributed.\nupdate_po_files() {\n  # Directory containing primary .po files.\n  # Overwrite them only when we're sure a .po file is new.\n  po_dir=$1\n  domain=$2\n\n  # Mirror *.po files into this dir.\n  # Usually contains *.s1 checksum files.\n  ref_po_dir=\"$po_dir/.reference\"\n\n  test -d $ref_po_dir || mkdir $ref_po_dir || return\n  download_po_files $ref_po_dir $domain \\\n    && ls \"$ref_po_dir\"/*.po 2>/dev/null |\n      sed 's|.*/||; s|\\.po$||' > \"$po_dir/LINGUAS\" || return\n\n  for po in x $(ls $ref_po_dir | sed -n 's/\\.po$//p'); do\n    case $po in x) continue;; esac\n    new_po=\"$ref_po_dir/$po.po\"\n    cksum_file=\"$ref_po_dir/$po.s1\"\n    if ! test -f \"$cksum_file\" ||\n        ! test -f \"$po_dir/$po.po\" ||\n        ! $SHA1SUM -c \"$cksum_file\" < \"$new_po\" > /dev/null 2>&1; then\n      echo \"$me: updated $po_dir/$po.po...\"\n      cp \"$new_po\" \"$po_dir/$po.po\" \\\n          && $SHA1SUM < \"$new_po\" > \"$cksum_file\" || return\n    fi\n  done\n}\n\n# -------- Generate files automatically from existing sources.  --------------\n\nautogen_usage() {\n  cat <<EOF\nUsage: $me [OPTION]...\nBootstrap this package from the checked-out sources, phase 2:\nGenerate files from local files (no network access).\n\nOptional environment variables:\n  GNULIB_SRCDIR            Specifies the local directory where gnulib\n                           sources reside.  Use this if you already\n                           have gnulib sources on your machine, and\n                           you want to use these sources.\n\nOptions:\n  --copy                   Copy files instead of creating symbolic links.\n  --force                  Attempt to bootstrap even if the sources seem\n                           not to have been checked out.\nEOF\n  bootstrap_print_option_usage_hook\n  cat <<EOF\nIf the file bootstrap.conf exists in the same directory as this script, its\ncontents are read as shell variables to configure the bootstrap.\n\nFor build prerequisites, environment variables like \\$AUTOCONF and \\$AMTAR\nare honored.\n\nGnulib sources are assumed to be present:\n  * in \\$GNULIB_SRCDIR, if that environment variable is set,\n  * otherwise, in the 'gnulib' submodule, if such a submodule is configured,\n  * otherwise, in the 'gnulib' subdirectory.\n\nRunning without arguments will suffice in most cases.\nEOF\n}\n\n\nversion_controlled_file() {\n  parent=$1\n  file=$2\n  if test -d .git; then\n    git rm -n \"$file\" > /dev/null 2>&1\n  elif test -d .svn; then\n    svn log -r HEAD \"$file\" > /dev/null 2>&1\n  elif test -d CVS; then\n    grep -F \"/${file##*/}/\" \"$parent/CVS/Entries\" 2>/dev/null |\n             grep '^/[^/]*/[0-9]' > /dev/null\n  else\n    warn_ \"no version control for $file?\"\n    false\n  fi\n}\n\n# Strip blank and comment lines to leave significant entries.\ngitignore_entries() {\n  sed '/^#/d; /^$/d' \"$@\"\n}\n\n# If $STR is not already on a line by itself in $FILE, insert it at the start.\n# Entries are inserted at the start of the ignore list to ensure existing\n# entries starting with ! are not overridden.  Such entries support\n# whitelisting exceptions after a more generic blacklist pattern.\ninsert_if_absent() {\n  file=$1\n  str=$2\n  test -f $file || touch $file\n  test -r $file || die \"Error: failed to read ignore file: $file\"\n  duplicate_entries=$(gitignore_entries $file | sort | uniq -d)\n  if [ \"$duplicate_entries\" ] ; then\n    die \"Error: Duplicate entries in $file: \" $duplicate_entries\n  fi\n  linesold=$(gitignore_entries $file | wc -l)\n  linesnew=$( { echo \"$str\"; cat $file; } | gitignore_entries | sort -u | wc -l)\n  if [ $linesold != $linesnew ] ; then\n    { echo \"$str\" | cat - $file > $file.bak && mv $file.bak $file; } \\\n      || die \"insert_if_absent $file $str: failed\"\n  fi\n}\n\n# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with\n# insert_if_absent.\ninsert_vc_ignore() {\n  vc_ignore_file=\"$1\"\n  pattern=\"$2\"\n  case $vc_ignore_file in\n  *.gitignore)\n    # A .gitignore entry that does not start with '/' applies\n    # recursively to subdirectories, so prepend '/' to every\n    # .gitignore entry.\n    pattern=$(echo \"$pattern\" | sed s,^,/,);;\n  esac\n  insert_if_absent \"$vc_ignore_file\" \"$pattern\"\n}\n\nsymlink_to_dir()\n{\n  src=$1/$2\n  dst=${3-$2}\n\n  test -f \"$src\" && {\n\n    # If the destination directory doesn't exist, create it.\n    # This is required at least for \"lib/uniwidth/cjk.h\".\n    dst_dir=$(dirname \"$dst\")\n    if ! test -d \"$dst_dir\"; then\n      mkdir -p \"$dst_dir\"\n\n      # If we've just created a directory like lib/uniwidth,\n      # tell version control system(s) it's ignorable.\n      # FIXME: for now, this does only one level\n      parent=$(dirname \"$dst_dir\")\n      for dot_ig in x $vc_ignore; do\n        test $dot_ig = x && continue\n        ig=$parent/$dot_ig\n        insert_vc_ignore $ig \"${dst_dir##*/}/\"\n      done\n    fi\n\n    if $copy; then\n      {\n        test ! -h \"$dst\" || {\n          echo \"$me: rm -f $dst\" &&\n          rm -f \"$dst\"\n        }\n      } &&\n      test -f \"$dst\" &&\n      cmp -s \"$src\" \"$dst\" || {\n        echo \"$me: cp -fp $src $dst\" &&\n        cp -fp \"$src\" \"$dst\"\n      }\n    else\n      # Leave any existing symlink alone, if it already points to the source,\n      # so that broken build tools that care about symlink times\n      # aren't confused into doing unnecessary builds.  Conversely, if the\n      # existing symlink's timestamp is older than the source, make it afresh,\n      # so that broken tools aren't confused into skipping needed builds.  See\n      # <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00326.html>.\n      test -h \"$dst\" &&\n      src_ls=$(ls -diL \"$src\" 2>/dev/null) && set $src_ls && src_i=$1 &&\n      dst_ls=$(ls -diL \"$dst\" 2>/dev/null) && set $dst_ls && dst_i=$1 &&\n      test \"$src_i\" = \"$dst_i\" &&\n      both_ls=$(ls -dt \"$src\" \"$dst\") &&\n      test \"X$both_ls\" = \"X$dst$nl$src\" || {\n        dot_dots=\n        case $src in\n        /*) ;;\n        *)\n          case /$dst/ in\n          *//* | */../* | */./* | /*/*/*/*/*/)\n             die \"invalid symlink calculation: $src -> $dst\";;\n          /*/*/*/*/)    dot_dots=../../../;;\n          /*/*/*/)      dot_dots=../../;;\n          /*/*/)        dot_dots=../;;\n          esac;;\n        esac\n\n        echo \"$me: ln -fs $dot_dots$src $dst\" &&\n        ln -fs \"$dot_dots$src\" \"$dst\"\n      }\n    fi\n  }\n}\n\n# Regenerate all autogeneratable files that are omitted from the\n# version control repository.  In particular, regenerate all\n# aclocal.m4, config.h.in, Makefile.in, configure files with new\n# versions of autoconf or automake.\nautogen()\n{\n  # Ensure that CDPATH is not set.  Otherwise, the output from cd\n  # would cause trouble in at least one use below.\n  (unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n  # Environment variables that may be set by the user.\n  : \"${AUTOPOINT=autopoint}\"\n  : \"${AUTORECONF=autoreconf}\"\n\n  if test \"$vc_ignore\" = auto; then\n    vc_ignore=\n    test -d .git && vc_ignore=.gitignore\n    test -d CVS && vc_ignore=\"$vc_ignore .cvsignore\"\n  fi\n\n\n  # Parse options.\n\n  # Whether to use copies instead of symlinks.\n  copy=false\n\n  for option\n  do\n    case $option in\n    --help)\n      autogen_usage\n      return;;\n    --version)\n      set -e\n      echo \"autogen.sh $scriptlibversion\"\n      echo \"$copyright\"\n      return 0\n      ;;\n    --force)\n      checkout_only_file=;;\n    --copy)\n      copy=true;;\n    *)\n      bootstrap_option_hook $option || die \"$option: unknown option\";;\n    esac\n  done\n\n  test -z \"$GNULIB_SRCDIR\" || test -d \"$GNULIB_SRCDIR\" \\\n    || die \"Error: \\$GNULIB_SRCDIR environment variable or --gnulib-srcdir\" \\\n           \"option is specified, but does not denote a directory\"\n\n  if test -n \"$checkout_only_file\" && test ! -r \"$checkout_only_file\"; then\n    die \"Running this script from a non-checked-out distribution is risky.\"\n  fi\n\n  if $use_gnulib; then\n    if test -z \"$GNULIB_SRCDIR\"; then\n      gnulib_path=$(test -f .gitmodules &&\n                    git config --file .gitmodules submodule.gnulib.path)\n      test -z \"$gnulib_path\" && gnulib_path=gnulib\n      GNULIB_SRCDIR=$gnulib_path\n    fi\n  fi\n\n  # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.\n  found_aux_dir=no\n  grep '^[\t ]*AC_CONFIG_AUX_DIR(\\['\"$build_aux\"'])' configure.ac \\\n      >/dev/null && found_aux_dir=yes\n  grep '^[\t ]*AC_CONFIG_AUX_DIR('\"$build_aux\"')' configure.ac \\\n      >/dev/null && found_aux_dir=yes\n  test $found_aux_dir = yes \\\n    || die \"configure.ac lacks 'AC_CONFIG_AUX_DIR([$build_aux])'; add it\"\n\n  # If $build_aux doesn't exist, create it now, otherwise some bits\n  # below will malfunction.  If creating it, also mark it as ignored.\n  if test ! -d $build_aux; then\n    mkdir $build_aux\n    for dot_ig in x $vc_ignore; do\n      test $dot_ig = x && continue\n      insert_vc_ignore $dot_ig $build_aux/\n    done\n  fi\n\n  check_build_prerequisites false\n\n  use_libtool=0\n  # We'd like to use grep -E, to see if any of LT_INIT,\n  # AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,\n  # but that's not portable enough (e.g., for Solaris).\n  grep '^[\t ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \\\n    && use_libtool=1\n  grep '^[\t ]*LT_INIT' configure.ac >/dev/null \\\n    && use_libtool=1\n  if test $use_libtool = 1; then\n    find_tool LIBTOOLIZE glibtoolize libtoolize\n  fi\n\n  if $use_gnulib; then\n    gnulib_tool=$GNULIB_SRCDIR/gnulib-tool\n    <$gnulib_tool || return\n  fi\n\n  # NOTE: we have to be careful to run both autopoint and libtoolize\n  # before gnulib-tool, since gnulib-tool is likely to provide newer\n  # versions of files \"installed\" by these two programs.\n  # Then, *after* gnulib-tool (see below), we have to be careful to\n  # run autoreconf in such a way that it does not run either of these\n  # two just-pre-run programs.\n\n  # Import from gettext.\n  with_gettext=yes\n  grep '^[\t ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \\\n      with_gettext=no\n\n  if test $with_gettext = yes || test $use_libtool = 1; then\n\n    tempbase=.bootstrap$$\n    trap \"rm -f $tempbase.0 $tempbase.1\" HUP INT PIPE TERM\n\n    > $tempbase.0 > $tempbase.1 &&\n    find . ! -type d -print | sort > $tempbase.0 || return\n\n    if test $with_gettext = yes; then\n      # Released autopoint has the tendency to install macros that have been\n      # obsoleted in current gnulib, so run this before gnulib-tool.\n      echo \"$0: $AUTOPOINT --force\"\n      $AUTOPOINT --force || return\n    fi\n\n    # Autoreconf runs aclocal before libtoolize, which causes spurious\n    # warnings if the initial aclocal is confused by the libtoolized\n    # (or worse out-of-date) macro directory.\n    # libtoolize 1.9b added the --install option; but we support back\n    # to libtoolize 1.5.22, where the install action was default.\n    if test $use_libtool = 1; then\n      install=\n      case $($LIBTOOLIZE --help) in\n        *--install*) install=--install ;;\n      esac\n      echo \"running: $LIBTOOLIZE $install --copy\"\n      $LIBTOOLIZE $install --copy\n    fi\n\n    find . ! -type d -print | sort >$tempbase.1\n    old_IFS=$IFS\n    IFS=$nl\n    for file in $(comm -13 $tempbase.0 $tempbase.1); do\n      IFS=$old_IFS\n      parent=${file%/*}\n      version_controlled_file \"$parent\" \"$file\" || {\n        for dot_ig in x $vc_ignore; do\n          test $dot_ig = x && continue\n          ig=$parent/$dot_ig\n          insert_vc_ignore \"$ig\" \"${file##*/}\"\n        done\n      }\n    done\n    IFS=$old_IFS\n\n    rm -f $tempbase.0 $tempbase.1\n    trap - HUP INT PIPE TERM\n  fi\n\n  # Import from gnulib.\n\n  if $use_gnulib; then\n    gnulib_tool_options=\"\\\n     --no-changelog\\\n     --aux-dir=$build_aux\\\n     --doc-base=$doc_base\\\n     --lib=$gnulib_name\\\n     --m4-base=$m4_base/\\\n     --source-base=$source_base/\\\n     --tests-base=$tests_base\\\n     --local-dir=$local_gl_dir\\\n     $gnulib_tool_option_extras\\\n    \"\n    if test $use_libtool = 1; then\n      case \"$gnulib_tool_options \" in\n        *' --libtool '*) ;;\n        *) gnulib_tool_options=\"$gnulib_tool_options --libtool\" ;;\n      esac\n    fi\n    echo \"$0: $gnulib_tool $gnulib_tool_options --import ...\"\n    $gnulib_tool $gnulib_tool_options --import $gnulib_modules \\\n      || die \"gnulib-tool failed\"\n\n    if test $with_gettext = yes && test ! -f $m4_base/gettext.m4; then\n      # The gnulib-tool invocation has removed $m4_base/gettext.m4, that the\n      # AUTOPOINT invocation had installed. This can occur when the gnulib\n      # module 'gettext' was previously present but is now not present any more.\n      # Repeat the AUTOPOINT invocation and the gnulib-tool invocation.\n\n      echo \"$0: $AUTOPOINT --force\"\n      $AUTOPOINT --force || return\n\n      echo \"$0: $gnulib_tool $gnulib_tool_options --import ...\"\n      $gnulib_tool $gnulib_tool_options --import $gnulib_modules \\\n        || die \"gnulib-tool failed\"\n    fi\n\n    for file in $gnulib_files; do\n      symlink_to_dir \"$GNULIB_SRCDIR\" $file \\\n        || die \"failed to symlink $file\"\n    done\n  fi\n\n  bootstrap_post_import_hook \\\n    || die \"bootstrap_post_import_hook failed\"\n\n  # Remove any dangling symlink matching \"*.m4\" or \"*.[ch]\" in some\n  # gnulib-populated directories.  Such .m4 files would cause aclocal to fail.\n  # The following requires GNU find 4.2.3 or newer.  Considering the usual\n  # portability constraints of this script, that may seem a very demanding\n  # requirement, but it should be ok.  Ignore any failure, which is fine,\n  # since this is only a convenience to help developers avoid the relatively\n  # unusual case in which a symlinked-to .m4 file is git-removed from gnulib\n  # between successive runs of this script.\n  find \"$m4_base\" \"$source_base\" \\\n    -depth \\( -name '*.m4' -o -name '*.[ch]' \\) \\\n    -type l -xtype l -delete > /dev/null 2>&1\n\n  # Invoke autoreconf with --force --install to ensure upgrades of tools\n  # such as ylwrap.\n  AUTORECONFFLAGS=\"--verbose --install --force $ACLOCAL_FLAGS\"\n  AUTORECONFFLAGS=\"$AUTORECONFFLAGS --no-recursive\"\n\n  # Tell autoreconf not to invoke autopoint or libtoolize; they were run above.\n  echo \"running: AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS\"\n  AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS \\\n    || die \"autoreconf failed\"\n\n  # Get some extra files from gnulib, overriding existing files.\n  for file in $gnulib_extra_files; do\n    case $file in\n      */INSTALL) dst=INSTALL;;\n      build-aux/*) dst=$build_aux/${file#build-aux/};;\n      *) dst=$file;;\n    esac\n    symlink_to_dir \"$GNULIB_SRCDIR\" $file $dst \\\n      || die \"failed to symlink $file\"\n  done\n\n  if test $with_gettext = yes; then\n    # Create gettext configuration.\n    echo \"$0: Creating po/Makevars from po/Makevars.template ...\"\n    rm -f po/Makevars\n    sed '\n      /^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '\"$EXTRA_LOCALE_CATEGORIES\"'/\n      /^COPYRIGHT_HOLDER *=/s/=.*/= '\"$COPYRIGHT_HOLDER\"'/\n      /^MSGID_BUGS_ADDRESS *=/s|=.*|= '\"$MSGID_BUGS_ADDRESS\"'|\n      /^XGETTEXT_OPTIONS *=/{\n        s/$/ \\\\/\n        a\\\n            '\"$XGETTEXT_OPTIONS\"' $${end_of_xgettext_options+}\n      }\n    ' po/Makevars.template >po/Makevars \\\n      || die 'cannot generate po/Makevars'\n\n    # If the 'gettext' module is in use, grab the latest Makefile.in.in.\n    # If only the 'gettext-h' module is in use, assume autopoint already\n    # put the correct version of this file into place.\n    case $gnulib_modules in\n      *gettext-h*) ;;\n      *gettext*)\n        cp $GNULIB_SRCDIR/build-aux/po/Makefile.in.in po/Makefile.in.in \\\n          || die \"cannot create po/Makefile.in.in\"\n        ;;\n    esac\n\n    if test -d runtime-po; then\n      # Similarly for runtime-po/Makevars, but not quite the same.\n      rm -f runtime-po/Makevars\n      sed '\n        /^DOMAIN *=.*/s/=.*/= '\"$package\"'-runtime/\n        /^subdir *=.*/s/=.*/= runtime-po/\n        /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'\"$package\"'@gnu.org/\n        /^XGETTEXT_OPTIONS *=/{\n          s/$/ \\\\/\n          a\\\n              '\"$XGETTEXT_OPTIONS_RUNTIME\"' $${end_of_xgettext_options+}\n        }\n      ' po/Makevars.template >runtime-po/Makevars \\\n      || die 'cannot generate runtime-po/Makevars'\n\n      # Copy identical files from po to runtime-po.\n      cp -p po/Makefile.in.in po/*-quot po/*.header po/*.sed po/*.sin runtime-po\n    fi\n  fi\n\n  bootstrap_epilogue\n\n  echo \"$0: done.  Now you can run './configure'.\"\n}\n\n# ----------------------------------------------------------------------------\n\n# Local Variables:\n# eval: (add-hook 'before-save-hook 'time-stamp nil t)\n# time-stamp-start: \"scriptlibversion=\"\n# time-stamp-format: \"%Y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC0\"\n# time-stamp-end: \"; # UTC\"\n# End:\n"
  },
  {
    "path": "bootstrap.conf",
    "content": "# Bootstrap configuration.\n\n########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# gnulib modules used by this package.\ngnulib_modules=\"\n  _Exit\n  access\n  areadlink\n  base64\n  bison\n  canonicalize\n  chdir\n  close\n  closedir\n  crypto/md2-buffer\n  crypto/md4-buffer\n  crypto/md5-buffer\n  crypto/sha1-buffer\n  crypto/sha256-buffer\n  crypto/sha512-buffer\n  dup\n  dup2\n  execl\n  execv\n  execvp\n  fcntl\n  fflush\n  filemode\n  fnmatch\n  fpucw\n  frexp\n  frexpf\n  fseeko\n  ftello\n  ftruncate\n  getcwd\n  gethostname\n  gethrxtime\n  getopt-gnu\n  getrusage\n  gettimeofday\n  glob\n  intprops\n  isatty\n  largefile\n  lib-symbol-visibility\n  link\n  localcharset\n  lstat\n  malloc-gnu\n  memcpy\n  mkdir\n  mkfifo\n  mkostemp\n  mkostemps\n  mktime\n  nanosleep\n  nproc\n  nstrftime\n  open\n  opendir\n  perror\n  pipe-posix\n  progname\n  raise\n  readdir\n  readline\n  rewinddir\n  rmdir\n  select\n  setenv\n  setlocale\n  sigaction\n  signal-h\n  sigprocmask\n  stat\n  stat-time\n  stddef-h\n  stdio-h\n  strcase\n  strdup-posix\n  strerror\n  strptime\n  strsignal\n  symlink\n  sys_stat-h\n  sys_time-h\n  sys_times-h\n  sys_wait-h\n  tempname\n  uname\n  unicase/u8-tolower\n  unicase/u8-toupper\n  uniconv/u16-conv-from-enc\n  uniconv/u16-conv-to-enc\n  uniconv/u32-conv-to-enc\n  uniconv/u8-conv-from-enc\n  uniconv/u8-conv-to-enc\n  unictype/ctype-alnum\n  unictype/ctype-alpha\n  unictype/ctype-blank\n  unictype/ctype-cntrl\n  unictype/ctype-digit\n  unictype/ctype-graph\n  unictype/ctype-lower\n  unictype/ctype-print\n  unictype/ctype-punct\n  unictype/ctype-space\n  unictype/ctype-upper\n  unictype/ctype-xdigit\n  unistd-h\n  unistr/u16-to-u8\n  unistr/u32-to-u8\n  unistr/u8-check\n  unistr/u8-mbsnlen\n  unistr/u8-strmblen\n  unistr/u8-strmbtouc\n  unistr/u8-to-u16\n  unistr/u8-to-u32\n  unlink\n  unsetenv\n  vasprintf\n  waitpid\n  windows-spawn\n\"\n\n# Additional gnulib files and scripts used by Octave's buildsystem.\ngnulib_files=\"\n  build-aux/move-if-change\n\"\n\n# Additional xgettext options to use.  Use \"\\\\\\newline\" to break lines.\nXGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\\\\\n --from-code=UTF-8\\\\\\\n --flag=asprintf:2:c-format --flag=vasprintf:2:c-format\\\\\\\n --flag=asnprintf:3:c-format --flag=vasnprintf:3:c-format\\\\\\\n --flag=wrapf:1:c-format\\\\\\\n'\n\n# If \"AM_GNU_GETTEXT(external\" or \"AM_GNU_GETTEXT([external]\"\n# appears in configure.ac, exclude some unnecessary files.\n# Without grep's -E option (not portable enough, pre-configure),\n# the following test is ugly.  Also, this depends on the existence\n# of configure.ac, not the obsolescent-named configure.in.  But if\n# you're using this infrastructure, you should care about such things.\n\ngettext_external=0\ngrep '^[\t ]*AM_GNU_GETTEXT(external\\>' configure.ac > /dev/null &&\n  gettext_external=1\ngrep '^[\t ]*AM_GNU_GETTEXT(\\[external\\]' configure.ac > /dev/null &&\n  gettext_external=1\n\nif test $gettext_external = 1; then\n  # Gettext supplies these files, but we don't need them since\n  # we don't have an intl subdirectory.\n  excluded_files='\n      m4/glibc2.m4\n      m4/intdiv0.m4\n      m4/lcmessage.m4\n      m4/lock.m4\n      m4/printf-posix.m4\n      m4/size_max.m4\n      m4/uintmax_t.m4\n      m4/ulonglong.m4\n      m4/visibility.m4\n      m4/xsize.m4\n  '\nfi\n\n# Build prerequisites\nbuildreq=\"\\\nautoconf   2.59\nautomake   1.9.6\ngit        1.5.5\ntar        -\n\"\ncheckout_only_file=etc/HACKING.md\ngnulib_tool_option_extras=\"--libtool\"\ngnulib_name=\"libgnu\"\nsource_base=\"libgnu\"\n\n# Go to https://git.savannah.gnu.org/cgit/gnulib.git to find out the latest\n# revision ID.  Paste it below and then run\n#\n#   ./bootstrap --bootstrap-sync\n#\n# to update the ./bootstrap file from the selected gnulib revision.\n#\n# See also: https://lists.gnu.org/archive/html/bug-gnulib/2020-08/msg00150.html\n\n: ${GNULIB_REVISION=8e0af4b8fcba7e38c06af5db29030715189a102b}\n\n# Don't check for translations since we don't have any in Octave yet.\n# This avoids the need for sha1sum or compatible utility in bootstrap.\nSKIP_PO=true\n\nbootstrap_post_import_hook ()\n{\n  SHELL=${CONFIG_SHELL-/bin/sh}\n  export SHELL\n\n  ## Check for files that automake --gnu would normally look for, except\n  ## AUTHORS, which we autogenerate from the documentation files along\n  ## with building the rest of Octave, and INSTALL, which is linked from\n  ## gnulib/doc/INSTALL by the bootstrap script.  NEWS is autogenerated\n  ## from etc/NEWS.x.\n\n  for f in README COPYING CITATION; do\n    if ! test -f $f; then\n      echo \"required file $f is missing\" 2>&1\n      exit 1\n    fi\n  done\n\n  echo \"generating source lists for liboctave/operators/module.mk...\"\n\n  rm -f liboctave/operators/*-op-*.mk\n  (cd liboctave/operators && $SHELL config-ops.sh)\n\n  echo \"generating doc/interpreter/images.mk...\"\n\n  rm -f doc/interpreter/images.mk\n  (cd doc/interpreter && $SHELL config-images.sh)\n\n  echo \"generating libinterp/dldfcn/module.mk...\"\n\n  rm -f libinterp/dldfcn/module.mk\n  (cd libinterp/dldfcn && $SHELL config-module.sh)\n}\n"
  },
  {
    "path": "build-aux/OctJavaQry.java",
    "content": "// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n\n// Code used by configure script to locate Java installation variables.\n// Only compiled code, OctJavaQry.class, is distributed.\n\npublic class OctJavaQry\n{\n  public static void main (String[] args)\n  {\n    if (args.length > 0)\n    {\n      if (args[0].equals (\"JAVA_HOME\"))\n      {\n        System.out.println (System.getProperty (\"java.home\"));\n      }\n      else if (args[0].equals (\"JAVA_LDPATH\"))\n      {\n        System.out.println (System.getProperty (\"java.library.path\"));\n      }\n      else if (args[0].equals (\"JAVA_BOOTPATH\"))\n      {\n        System.out.println (System.getProperty (\"sun.boot.library.path\"));\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "build-aux/changelog.tmpl",
    "content": "########################################################################\n##\n## Copyright (C) 2011-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nheader = '{date|shortdate}  {author|person}  <{author|email}>\\n\\n'\nchangeset = '\\t{desc|tabindent|strip}\\n\\n\\tFiles: {files|stringify|fill68|tabindent|strip}\\n\\n'\n"
  },
  {
    "path": "build-aux/check-subst-vars.in.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n: ${AWK=@AWK@}\n: ${SED=@SED@}\n\nif test $# -ne 2; then\n  echo \"usage: check-subst-vars.sh make-vars-file config-vars-file\" 2>&1\n  exit 1\nfi\n\nawk_script=\"check-subst-vars-$$.awk\"\n\ntrap \"rm -f $awk_script; exit 1\" 1 2 15\n\nmake_vars=\"$1\"\nconfig_vars=\"$2\"\n\n## Generate awk script to check variable consistency.\n\ncat << EOF > $awk_script\nBEGIN {\n  status = 0;\nEOF\n\nwhile read var val; do\n  val=`echo \"$val\" | $SED 's/\"/\\\\\\\\\"/g'`\n  echo \"make_vars[\\\"$var\\\"] = \\\"$val\\\";\" >> $awk_script\ndone < $make_vars\n\ncat << EOF >> $awk_script\n} {\n  line = \\$0;\n  idx = index (line, \" \");\n  var = substr (line, 1, idx-1);\n  val = substr (line, idx+1);\n  if (val != make_vars[var])\n    {\n      printf (\"error: mismatch for configuration variable '%s'\\n\", var);\n      printf (\"  value set in configuration files: %s\\n\", val);\n      printf (\"  value set in Make: %s\\n\", make_vars[var]);\n      status = 1;\n    }\n} END {\n  exit status;\n}\nEOF\n\n## Execute it.\n\n$AWK -f $awk_script $config_vars 1>&2\n\nrm -f $awk_script\n"
  },
  {
    "path": "build-aux/find-defun-files.in.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nset -e\n\n: ${SED=@SED@}\n: ${EGREP=@EGREP@}\n\n# Some stupid egreps don't like empty elements in alternation patterns,\n# so we have to repeat ourselves because some stupid egreps don't like\n# empty elements in alternation patterns.\n\nDEFUN_PATTERN=\"^[ \\t]*DEF(CONSTFUN|CONSTMETHOD|METHOD|METHOD(_|_STATIC_)DLD|METHODX|METHODX(_|_STATIC_)DLD|UN|UN(_|_STATIC_)DLD|UNX|UNX(_|_STATIC_)DLD)[ \\t]*\\\\(\"\n\nsrcdir=\"$1\"\nif [ \"$1\" ]; then\n  shift\nfi\n\nfor arg\ndo\n  if [ -f \"$arg\" ]; then\n    file=\"$arg\"\n  else\n    file=\"$srcdir/$arg\"\n  fi\n  if [ -f \"$file\" ]; then\n    if [ \"`$EGREP -l \"$DEFUN_PATTERN\" $file`\" ]; then\n      echo \"$file\" | $SED \"s,\\\\$srcdir/,,\"\n    fi\n  fi\ndone\n"
  },
  {
    "path": "build-aux/find-files-with-tests.in.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nset -e\n\n: ${GREP=@GREP@}\n: ${SED=@SED@}\n\nsrcdir=\"$1\"\nif [ \"$1\" ]; then\n  shift\nfi\n\nfor arg\ndo\n  if [ -f \"$arg\" ]; then\n    file=\"$arg\"\n  else\n    file=\"$srcdir/$arg\"\n  fi\n  if [ -f \"$file\" ]; then\n    if [ \"`$GREP -l '^%!' $file`\" ]; then\n      echo \"$file\" | $SED \"s,\\\\$srcdir/,,\"\n    fi\n  fi\ndone\n"
  },
  {
    "path": "build-aux/get-source-mtime.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# Generate a timestamp that best represents the last modification time\n# of this source tree.  The time value is printed on stdout in units of\n# time_t.  If a reasonable representation of the source tree last\n# modification time can't be determined, then the current system time is\n# printed instead.  A valid time_t value is always printed on stdout.\n\nset -e\n\nPERL=${PERL:-perl}\nSED=${SED:-sed}\n\nif [ $# -ne 1 ]; then\n  echo \"usage: get-source-mtime.sh SRCDIR\" 1>&2\n  exit 1\nfi\n\nsrcdir=\"$1\"\n\n## A user's ~/.hgrc may redefine or add default options to any hg subcommand,\n## potentially altering its behavior and possibly its standard output.  Always\n## run hg subcommands with configuration variables set to ensure that the\n## user's preferences do not influence the expected behavior.\nhg_safe ()\n{\n  cmd=$1; shift\n  hg --config alias.${cmd}=${cmd} --config defaults.${cmd}= ${cmd} \"$@\"\n}\n\nif [ x\"$SOURCE_DATE_EPOCH\" != x ]; then\n  # Allow the source modification time to be overridden by SOURCE_DATE_EPOCH\n  t=$SOURCE_DATE_EPOCH\nelif [ -d $srcdir/.hg ]; then\n  t=$( cd $srcdir && hg_safe log --rev . --template '{date|hgdate}' )\n  t=$( echo $t | $SED -n 's/^\\([0-9]\\+\\) .*/\\1/p' )\nelif [ -f $srcdir/HG-ID ]; then\n  t=$( $PERL -e '@s = stat($ARGV[0]); print($s[9]) if @s;' $srcdir/HG-ID )\nelif [ -f $srcdir/configure ]; then\n  t=$( $PERL -e '@s = stat($ARGV[0]); print($s[9]) if @s;' $srcdir/configure )\nfi\n\nif [ x\"$t\" = x ]; then\n  t=$( date +%s )\nfi\n\necho $t\n"
  },
  {
    "path": "build-aux/inplace-edit.pl",
    "content": "#!/usr/bin/perl -w\n\n################################################################################\n## File: inplace-edit.pl\n## Usage: perl inplace-edit.pl 'PERL_CODE' file1 [file2] [...]\n## Purpose: Run snippet of PERL_CODE on each line in a file and replace\n## existing line with the results of running the code.\n## This replaces perl -i -pe 'PERL_CODE' file1 [file2] ...\n## due to a problem in Perl 5.28 which restricts the number of files\n################################################################################\n\n## Create Perl code from first argument (-e CODE)\neval \"sub per_line_code { $ARGV[0]; }\";\nshift @ARGV;\n\n## Loop over each file\nforeach $fname (@ARGV)\n{\n  rename ($fname, \"$fname.$$\") or die \"Rename failed:$fname:$!\";\n  open (my $FHI, \"<\", \"$fname.$$\") or die \"Open failed:$fname.$$:$!\";\n  open (my $FHO, \">\", \"$fname\") or die \"Open failed:$fname:$!\";\n\n  ## Loop over each line\n  while (<$FHI>)\n  {\n    per_line_code ();\n    print $FHO $_;\n  }\n\n  close ($FHI);\n  close ($FHO);\n  unlink \"$fname.$$\" or die \"Delete failed:$fname.$$:$!\";\n}\n"
  },
  {
    "path": "build-aux/make-gnu-dist-files",
    "content": "#! /bin/bash\n\n################################################################################\n# USAGE: make-gnu-dist-files DIRECTORY1 DIRECTORY2 ...\n################################################################################\n\nset -e\n\n# The GPG ID used to sign the distribution.  Currently, this is jwe's ID.\ngpg_id=0x5D36644B\n\nfor arg\ndo\n  subdir=$(dirname $arg)\n  if [ \"$subdir\" = \".\" ]; then\n    dir=\"octave\"\n  else\n    dir=\"octave/$subdir\"\n  fi\n\n  cat << EOF > $arg.directive\nversion: 1.2\ndirectory: $dir\nfilename: $(basename $arg)\nEOF\n\n  gpg --local-user $gpg_id -b $arg\n  gpg --local-user $gpg_id --clearsign $arg.directive\n  rm -f $arg.directive\n\ndone\n\ncat << EOF\n***\n*** Upload the files to the incoming/ftp directory on ftp-upload.gnu.org.\n*** (or incoming/alpha, for snapshots).\n***\nEOF\n"
  },
  {
    "path": "build-aux/mk-hg-id.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Display the Mercurial ID of the current revision.  If the source tree\n## does not appear to be a Mercurial repo but does contain a file named\n## HG-ID, display the contents of that file.  If that file does not\n## exist, or the Mercurial fails to provide the ID, display\n## \"unknown-hg-id\".  If invoked with the --disable option, display\n## \"hg-id-disabled\".\n\nset -e\n\nif [ $# -ne 1 ] && [ $# -ne 2 ]; then\n  echo \"usage: mk-hg-id.sh SRCDIR [--disable]\" 1>&2\n  exit 1\nfi\n\nsrcdir=\"$1\"\n\nhg_id=HG-ID\n\n## A user's ~/.hgrc may redefine or add default options to any hg subcommand,\n## potentially altering its behavior and possibly its standard output.  Always\n## run hg subcommands with configuration variables set to ensure that the\n## user's preferences do not influence the expected behavior.\n\nhg_safe ()\n{\n  cmd=$1; shift\n  hg --config alias.${cmd}=${cmd} --config defaults.${cmd}= ${cmd} \"$@\"\n}\n\nif [ $# -eq 2 ] && [ x\"$2\" = x--disable ]; then\n  echo \"hg-id-disabled\"\nelif [ -d \"$srcdir/.hg\" ]; then\n  ( cd \"$srcdir\" && hg_safe identify --id || echo \"unknown-hg-id\" )\nelif [ -d \"$srcdir/.git\" ]; then\n  ( cd \"$srcdir\" && echo \"git:\"$(git rev-parse --short HEAD) || echo \"unknown-hg-id\" )\nelif [ ! -f \"$srcdir/$hg_id\" ]; then\n  echo \"WARNING: $srcdir/$hg_id is missing!\" 1>&2\n  echo \"unknown-hg-id\"\nelse\n  cat \"$srcdir/$hg_id\"\nfi\n"
  },
  {
    "path": "build-aux/mk-octave-config-h.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# Generate a header file that provides the public symbols from Octave's\n# autoconf-generated config.h file.  See the notes at the top of the\n# generated octave-config.h file for more details.\n\nSED=${SED:-sed}\n\nif [ $# -ne 1 ]; then\n  echo \"usage: mk-octave-config-h.sh CONFIG-FILE\" 1>&2\n  exit 1\nfi\n\nconfig_h_file=$1\n\ncat << EOF\n// DO NOT EDIT!  Generated by mk-octave-config-h.sh.\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// All Octave source files should begin with\n//\n//   #if defined (HAVE_CONFIG_H)\n//   #  include \"config.h\"\n//   #endif\n//\n// All public Octave header files should have the form\n//\n//   #if ! defined (INCLUSION_GUARD_SYMBOL)\n//   #define INCLUSION_GUARD_SYMBOL 1\n//\n//   #include \"octave-config.h\"\n//\n//   ... Contents of header file ...\n//\n//   #endif\n\n// In Octave source files, INCLUSION_GUARD_SYMBOL should have the form\n//\n//   octave_NAME_h\n//\n// with NAME formed from the header file name with '-' replaced by '_'.\n//\n// It is safe to include octave-config.h unconditionally since it will\n// expand to an empty file if it is included after Octave's\n// autoconf-generated config.h file.\n//\n// Users of Octave's libraries should not need to include octave-config.h\n// since all of Octave's header files already include it.\n\n#if ! defined (octave_octave_config_h)\n#define octave_octave_config_h 1\n\n#if ! defined (OCTAVE_AUTOCONFIG_H_INCLUDED)\nEOF\n\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_ENABLE_64.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_ENABLE_BOUNDS_CHECK.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_ENABLE_INTERNAL_CHECKS.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_ENABLE_LIB_VISIBILITY_FLAGS.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_ENABLE_OPENMP.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_F77_INT_TYPE.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_HAVE_LONG_LONG_INT.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_HAVE_OVERLOAD_CHAR_INT8_TYPES.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_IDX_TYPE.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_SIZEOF_F77_INT_TYPE.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_SIZEOF_IDX_TYPE.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) OCTAVE_SIZEOF_INT.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) gid_t.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) uid_t.*$\\)/#  \\1/p' $config_h_file\n$SED -n 's/#\\(\\(undef\\|define\\) nlink_t.*$\\)/#  \\1/p' $config_h_file\n\nif grep \"#undef HAVE_DEV_T\" $config_h_file > /dev/null; then\n  cat << EOF\ntypedef short dev_t;\nEOF\nelse\n  cat << EOF\n/* typedef short dev_t; */\nEOF\nfi\n\nif grep \"#undef HAVE_INO_T\" $config_h_file > /dev/null; then\n    cat << EOF\ntypedef unsigned long ino_t;\nEOF\nelse\n    cat << EOF\n/* typedef unsigned long ino_t; */\nEOF\nfi\n\necho \"\"\n\nhave_roundl=no\nif grep \"#define HAVE_ROUNDL\" $config_h_file > /dev/null; then\n  have_roundl=yes\nfi\n\nsizeof_long_double=\"`$SED -n 's/#define SIZEOF_LONG_DOUBLE \\([0-9]*\\)/\\1/p' $config_h_file`\"\n\nif test -z \"$sizeof_long_double\"; then\n  echo \"mk-octave-config-h.sh: failed to find SIZEOF_LONG_DOUBLE in $config_h_file\" 1>&2\n  exit 1\nfi\n\nif test $sizeof_long_double -ge 10 && test $have_roundl = yes; then\n  echo \"#  define OCTAVE_INT_USE_LONG_DOUBLE 1\"\n  if test $sizeof_long_double -lt 16; then\n    cat << EOF\n#  if (defined (__i386__) || defined (__x86_64__)) && defined (__GNUC__)\n#    define OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED 1\n#  endif\nEOF\n  else\n    cat << EOF\n/* #  undef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED */\nEOF\n  fi\nelse\n  cat << EOF\n/* #  undef OCTAVE_INT_USE_LONG_DOUBLE */\n/* #  undef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED */\nEOF\nfi\n\necho \"\"\n\n$SED -n 's/#\\(\\(undef\\|define\\) F77_USES_.*$\\)/#  \\1/p' $config_h_file\n\necho \"\"\n\n$SED -n 's/#\\(\\(undef\\|define\\) F77_FUNC.*$\\)/#  \\1/p' $config_h_file\n\ncat << EOF\n\n/* Enable inline functions or typedefs that provide access to\n   symbols that have been moved to the octave namespace so that\n   users of Octave may continue to access symbols using the\n   deprecated names.  */\n#  define OCTAVE_PROVIDE_DEPRECATED_SYMBOLS 1\n\n#  include \"oct-conf-post-public.h\"\n\n#endif\n\n#endif\nEOF\n"
  },
  {
    "path": "build-aux/mk-opts.pl",
    "content": "#! /usr/bin/perl -w\n\n########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# Generate option handling code from a simpler input files for\n# Octave's functions like lsode, dassl, etc.\n\n# FIXME:\n#\n# * Improve default documentation and/or individual documentation\n#   in data files.\n#\n# * Fix print/show code to display/return something more informative\n#   for special values (for example, -1 ==> infinite in some cases).\n#   Probably need more information in the data files for this.\n\n# Input file format:\n#\n# CLASS = string\n# FCN_NAME = string\n# INCLUDE = file\n# DOC_STRING doc END_DOC_STRING\n# OPTION\n#   NAME = string\n#   DOC_ITEM doc END_DOC_ITEM\n#   TYPE = string\n#   SET_ARG_TYPE = string   (optional, defaults to TYPE)\n#   INIT_VALUE = string | INIT_BODY code END_INIT_BODY\n#   SET_EXPR = string | SET_BODY code END_SET_BODY | SET_CODE code END_SET_CODE\n# END_OPTION\n#\n# END_* must appear at beginning of line (whitespace ignored).\n\n################################################################################\n# Load packages to\n# 1) process command line options\n################################################################################\nuse Getopt::Long;\n\n################################################################################\n# Extract command line arguments\n&parse_options;\n\n$DEFN_FILE = shift @ARGV;\nopen (DEFN_FILE) or die \"unable to open input definition file $DEFN_FILE\";\n\n################################################################################\n# Initialize variables\n$BLANK_LINE = qr/^\\s*$/;\n$COMMENT = qr/^\\s*#/;\n\n################################################################################\n# Process file\n$OPT_NUM = 0;\n\n&parse_input;\n\n&process_data;\n\n# Produce desired style of output\n&emit_opt_class_header if $opt_class_header;\n&emit_opt_handler_fcns if $opt_handler_fcns;\n&emit_options_debug if $opt_debug;\n\n# End of main code\n\n################################################################################\n# Subroutines\n################################################################################\n\nsub parse_input\n{\n  LINE: while (<DEFN_FILE>)\n    {\n      next LINE if /$BLANK_LINE/;\n      next LINE if /$COMMENT/;\n\n      if (/^\\s*OPTION\\s*$/)\n        {\n          &parse_option_block;\n        }\n      elsif (/^\\s*CLASS\\s*=\\s*\"(\\w+)\"\\s*$/)\n        {\n          die \"duplicate CLASS\" if defined $CLASS;\n          $CLASS = $1;\n          $CLASS_NAME = \"${CLASS}_options\";\n          $STRUCT_NAME = \"${CLASS_NAME}_struct\";\n          $STATIC_TABLE_NAME = \"${CLASS_NAME}_table\";\n        }\n      elsif (/^\\s*FCN_NAME\\s*=\\s*\"(\\w+)\"\\s*$/)\n        {\n          die \"duplicate FCN_NAME\" if defined $FCN_NAME;\n          $FCN_NAME = $1;\n        }\n      elsif (/^\\s*INCLUDE\\s*=\\s*\"(\\S+)\"\\s*$/)\n        {\n          $INCLUDE .= qq (#include \"$1\"\\n);\n        }\n      elsif (/^\\s*DOC_STRING\\s*$/)\n        {\n          die \"duplicate DOC_STRING\" if defined $DOC_STRING;\n          while (defined ($_ = <DEFN_FILE>) and not /^\\s*END_DOC_STRING\\s*$/)\n          {\n            $DOC_STRING .= $_;\n          }\n          $DOC_STRING =~ s/\\n/\\\\n\\\\\\n/g;\n        }\n      else\n        {\n          die \"mk-opts.pl: unknown command: $_\\n\"\n        }\n    }\n  $INCLUDE = \"\" if not defined $INCLUDE;   # Initialize value if required\n}\n\nsub parse_option_block\n{\n  while (<DEFN_FILE>)\n    {\n      next if /$BLANK_LINE/;\n\n      die \"missing END_OPTION\" if /^\\s*OPTION\\s*$/;\n\n      last if /^\\s*END_OPTION\\s*$/;\n\n      if (/^\\s*NAME\\s*=\\s*\"(.*)\"\\s*$/)\n        {\n          die \"duplicate NAME\" if defined $NAME[$OPT_NUM];\n          $NAME[$OPT_NUM] = $1;\n          ($OPT[$OPT_NUM] = $NAME[$OPT_NUM]) =~ s/\\s+/_/g;\n          $OPTVAR[$OPT_NUM] = 'm_' . $OPT[$OPT_NUM];\n          $KW_TOK[$OPT_NUM] = [ split (' ', $NAME[$OPT_NUM]) ];\n          $N_TOKS[$OPT_NUM] = @{$KW_TOK[$OPT_NUM]};\n        }\n      elsif (/^\\s*DOC_ITEM\\s*$/)\n        {\n          die \"duplicate DOC_ITEM\" if defined $DOC_ITEM[$OPT_NUM];\n          while (defined ($_ = <DEFN_FILE>) and not /^\\s*END_DOC_ITEM\\s*$/)\n          {\n            $DOC_ITEM[$OPT_NUM] .= $_;\n          }\n        }\n      elsif (/^\\s*TYPE\\s*=\\s*\"(.*)\"\\s*$/)\n        {\n          die \"duplicate TYPE\" if defined $TYPE[$OPT_NUM];\n          $TYPE[$OPT_NUM] = $1;\n        }\n      elsif (/^\\s*SET_ARG_TYPE\\s*=\\s*\"(.*)\"\\s*$/)\n        {\n          die \"duplicate SET_ARG_TYPE\" if defined $SET_ARG_TYPE[$OPT_NUM];\n          $SET_ARG_TYPE[$OPT_NUM] = $1;\n        }\n      elsif (/^\\s*INIT_VALUE\\s*=\\s*\"(.*)\"\\s*$/)\n        {\n          die \"duplicate INIT_VALUE\" if defined $INIT_VALUE[$OPT_NUM];\n          $INIT_VALUE[$OPT_NUM] = $1;\n        }\n      elsif (/^\\s*SET_EXPR\\s*=\\s*\"(.*)\"\\s*$/)\n        {\n          die \"duplicate SET_EXPR\" if defined $SET_EXPR[$OPT_NUM];\n          $SET_EXPR[$OPT_NUM] = $1;\n        }\n      elsif (/^\\s*INIT_BODY\\s*$/)\n        {\n          die \"duplicate INIT_BODY\" if defined $INIT_BODY[$OPT_NUM];\n          while (defined ($_ = <DEFN_FILE>) and not /^\\s*END_INIT_BODY\\s*$/)\n          {\n            $INIT_BODY[$OPT_NUM] .= $_;\n          }\n        }\n      elsif (/^\\s*SET_BODY\\s*$/)\n        {\n          die \"duplicate SET_BODY\" if defined $INIT_BODY[$OPT_NUM];\n          while (defined ($_ = <DEFN_FILE>) and not /^\\s*END_SET_BODY\\s*$/)\n          {\n            $SET_BODY[$OPT_NUM] .= $_;\n          }\n        }\n      elsif (/^\\s*SET_CODE\\s*$/)\n        {\n          die \"duplicate SET_CODE\" if defined $SET_CODE[$OPT_NUM];\n          while (defined ($_ = <DEFN_FILE>) and not /^\\s*END_SET_CODE\\s*$/)\n          {\n            $SET_CODE[$OPT_NUM] .= $_;\n          }\n        }\n    }\n\n  if (not defined $SET_ARG_TYPE[$OPT_NUM])\n    {\n      $SET_ARG_TYPE[$OPT_NUM] = $TYPE[$OPT_NUM];\n    }\n  else\n    {\n      $SET_ARG_TYPE[$OPT_NUM]\n        = substopt ($SET_ARG_TYPE[$OPT_NUM], $OPTVAR[$OPT_NUM],\n                    $OPT[$OPT_NUM], $TYPE[$OPT_NUM]);\n    }\n\n  $OPT_NUM++;\n}\n\nsub process_data\n{\n  $MAX_TOKENS = max (@N_TOKS);\n\n  &get_min_match_len_info;\n\n  $FCN_NAME = lc ($CLASS) if not defined $FCN_NAME;\n\n  $OPT_FCN_NAME = \"${FCN_NAME}_options\" if not defined $OPT_FCN_NAME;\n\n  $STATIC_OBJECT_NAME = \"${FCN_NAME}_opts\";\n\n  if (not defined $DOC_STRING)\n    {\n      $DOC_STRING = \"Query or set options for the function \\@code{$FCN_NAME}.\n\nWhen called with no arguments, the names of all available options and\ntheir current values are displayed.\n\nGiven one argument, return the value of the option \\@var{opt}.\n\nWhen called with two arguments, \\@code{$OPT_FCN_NAME} sets the option\n\\@var{opt} to value \\@var{val}.\";\n    }\n}\n\n## FIXME: What does this routine do?  And can it be simpler to understand?\nsub get_min_match_len_info\n{\n  my ($i, $j, $k);\n\n  for ($i = 0; $i < $OPT_NUM; $i++)\n    {\n      for ($j = 0; $j < $MAX_TOKENS; $j++)\n        {\n          $MIN_TOK_LEN_TO_MATCH[$i][$j] = 0;\n        }\n\n      $MIN_TOKS_TO_MATCH[$i] = 1;\n\n    L1: for ($k = 0; $k < $OPT_NUM; $k++)\n        {\n          my $duplicate = 1;\n\n          if ($i != $k)\n            {\n            L2: for ($j = 0; $j < $MAX_TOKENS; $j++)\n                {\n                  if ($j < $N_TOKS[$i])\n                    {\n                      if ($KW_TOK[$i][$j] eq $KW_TOK[$k][$j])\n                        {\n                          if ($MIN_TOK_LEN_TO_MATCH[$i][$j] == 0)\n                            {\n                              $MIN_TOK_LEN_TO_MATCH[$i][$j] = 1;\n                            }\n\n                          $MIN_TOKS_TO_MATCH[$i]++;\n                        }\n                      else\n                        {\n                          $duplicate = 0;\n\n                          if ($MIN_TOK_LEN_TO_MATCH[$i][$j] == 0)\n                            {\n                              $MIN_TOK_LEN_TO_MATCH[$i][$j] = 1;\n                            }\n\n                          my @s = split (//, $KW_TOK[$i][$j]);\n                          my @t = split (//, $KW_TOK[$k][$j]);\n\n                          my ($n, $ii);\n                          $n = scalar (@s);\n                          $n = scalar (@t) if (@t < $n);\n\n                          for ($ii = 0; $ii < $n; $ii++)\n                            {\n                              if (\"$s[$ii]\" eq \"$t[$ii]\")\n                                {\n                                  if ($ii + 2 > $MIN_TOK_LEN_TO_MATCH[$i][$j])\n                                    {\n                                      $MIN_TOK_LEN_TO_MATCH[$i][$j]++;\n                                    }\n                                }\n                              else\n                                {\n                                  last L2;\n                                }\n                            }\n\n                          last L1;\n                        }\n                    }\n                  else\n                    {\n                      die qq|ambiguous options \"$NAME[$i]\" and \"$NAME[$k]\"| if $duplicate;\n                    }\n                }\n            }\n        }\n    }\n}  # end of get_min_match_len_info\n\n\nsub emit_copy_body\n{\n  my ($pfx, $var) = @_;\n\n  for (my $i = 0; $i < $OPT_NUM; $i++)\n    {\n      print \"${pfx}$OPTVAR[$i] = ${var}.$OPTVAR[$i];\\n\";\n    }\n\n  print \"${pfx}m_reset = ${var}.m_reset;\\n\";\n}\n\n## To silence GCC warnings, we create an initialization list even\n## though the init function actually does the work of initialization.\n\nsub emit_default_init_list\n{\n  my ($prefix) = @_;\n\n  print \"$OPTVAR[0] (),\\n\" unless ($OPT_NUM == 0);\n\n  for (my $i = 1; $i < $OPT_NUM; $i++)\n    {\n      print \"${prefix}$OPTVAR[$i] (),\\n\";\n    }\n\n  print \"${prefix}m_reset ()\\n\";\n}\n\nsub emit_copy_ctor_init_list\n{\n  my ($prefix, $var) = @_;\n\n  print \"$OPTVAR[0] ($var.$OPTVAR[0]),\\n\" unless ($OPT_NUM == 0);\n\n  for (my $i = 1; $i < $OPT_NUM; $i++)\n    {\n      print \"${prefix}$OPTVAR[$i] ($var.$OPTVAR[$i]),\\n\";\n    }\n\n  print \"${prefix}m_reset ($var.m_reset)\\n\";\n}\n\nsub emit_opt_class_header\n{\n  my ($i, $s);\n\n  print <<\"_END_EMIT_OPT_CLASS_HEADER_\";\n// DO NOT EDIT!\n// Generated automatically from $DEFN_FILE.\n\n#if ! defined (octave_${CLASS_NAME}_h)\n#define octave_${CLASS_NAME}_h 1\n\n#include <cmath>\n\n#include <limits>\n\n$INCLUDE\n\nclass\n$CLASS_NAME\n{\npublic:\n\n  $CLASS_NAME ()\n_END_EMIT_OPT_CLASS_HEADER_\n\n  print '    : ';\n  emit_default_init_list (\"      \");\n\n  print \"    {\n      init ();\n    }\n\n  $CLASS_NAME (const ${CLASS_NAME}& opt)\n    : \";\n\n  emit_copy_ctor_init_list (\"      \", \"opt\");\n\n  print \"    { }\n\n  ${CLASS_NAME}& operator = (const ${CLASS_NAME}& opt)\n    {\n      if (this != &opt)\n        {\\n\";\n\n  emit_copy_body ('          ', 'opt');\n\n  print \"        }\n\n      return *this;\n    }\n\n  ~$CLASS_NAME () { }\\n\";\n\n  print \"\\n  void init ()\\n    {\\n\";\n\n  for ($i = 0; $i < $OPT_NUM; $i++)\n    {\n      if (defined $INIT_VALUE[$i])\n        {\n          print \"      $OPTVAR[$i] = $INIT_VALUE[$i];\\n\";\n        }\n      elsif ($INIT_BODY[$i])\n        {\n          $s = substopt ($INIT_BODY[$i], $OPTVAR[$i], $OPT[$i], $TYPE[$i]);\n          chomp ($s);\n          $s =~ s/^\\s*/      /g;\n          $s =~ s/\\n\\s*/\\n      /g;\n          print $s,\"\\n\";\n        }\n    }\n\n  print \"      m_reset = true;\\n\",\n        \"    }\\n\";\n\n  ## For backward compatibility and because set_options is probably\n  ## a better name in some contexts:\n\n  print \"\\n  void set_options (const ${CLASS_NAME}& opt)\\n\",\n        \"    {\\n\";\n\n  emit_copy_body ('      ', 'opt');\n\n  print \"    }\\n\\n  void set_default_options () { init (); }\\n\";\n\n  for ($i = 0; $i < $OPT_NUM; $i++)\n    {\n      if ($SET_EXPR[$i])\n        {\n          emit_set_decl ($i);\n\n          print \"\\n    { $OPTVAR[$i] = $SET_EXPR[$i]; m_reset = true; }\\n\";\n        }\n      elsif ($SET_BODY[$i])\n        {\n          emit_set_decl ($i);\n\n          $s = substopt ($SET_BODY[$i], $OPTVAR[$i], $OPT[$i], $TYPE[$i]);\n          chomp ($s);\n          $s = '  ' . $s;\n          $s =~ s/\\n/\\n  /g;\n          print \"\\n    {\\n$s\\n      m_reset = true;\\n    }\\n\";\n        }\n      elsif ($SET_CODE[$i])\n        {\n          $s = substopt ($SET_CODE[$i], $OPTVAR[$i], $OPT[$i], $TYPE[$i]);\n          chomp ($s);\n          $s =~ s/^  //g;\n          $s =~ s/\\n  /\\n/g;\n          print \"\\n\",$s,\"\\n\";\n        }\n    }\n\n  for ($i = 0; $i < $OPT_NUM; $i++)\n    {\n      print \"  $TYPE[$i] $OPT[$i] () const\\n    { return $OPTVAR[$i]; }\\n\\n\";\n    }\n\n  print \"private:\\n\\n\";\n\n  for ($i = 0; $i < $OPT_NUM; $i++)\n    {\n      print \"  $TYPE[$i] $OPTVAR[$i];\\n\";\n    }\n\n  print \"\\nprotected:\\n\\n  bool m_reset;\\n};\\n\\n#endif\\n\";\n}\n\nsub emit_set_decl\n{\n  my ($i) = @_;\n\n  print \"\\n  void set_$OPT[$i] ($SET_ARG_TYPE[$i] val)\";\n}\n\nsub emit_opt_handler_fcns\n{\n  my $header = $DEFN_FILE;\n  $header =~ s/[.]\\w*$/.h/;      # replace .in with .h\n  $header =~ s|^.*/([^/]*)$|$1|; # strip directory part\n\n  print <<\"_END_EMIT_OPT_HANDLER_FCNS_\";\n// DO NOT EDIT!\n// Generated automatically from $DEFN_FILE.\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <iomanip>\n#include <ostream>\n#include <sstream>\n\n#include \"$header\"\n\n#include \"defun.h\"\n#include \"pr-output.h\"\n\n#include \"ovl.h\"\n#include \"utils.h\"\n#include \"pager.h\"\n\nstatic $CLASS_NAME $STATIC_OBJECT_NAME;\n\n_END_EMIT_OPT_HANDLER_FCNS_\n\n  &emit_struct_decl;\n\n  &emit_struct_def;\n\n  &emit_print_function;\n\n  &emit_set_functions;\n\n  &emit_show_function;\n\n  &emit_options_function;\n}\n\nsub emit_struct_decl\n{\n  print <<\"_END_PRINT_STRUCT_DECL_\";\n#define MAX_TOKENS $MAX_TOKENS\n\nstruct $STRUCT_NAME\n{\n  const char *keyword;\n  const char *kw_tok[MAX_TOKENS + 1];\n  int min_len[MAX_TOKENS + 1];\n  int min_toks_to_match;\n};\n\n_END_PRINT_STRUCT_DECL_\n}\n\nsub emit_struct_def\n{\n  my $i;\n\n  print \"#define NUM_OPTIONS $OPT_NUM\\n\\n\";\n\n  print \"static $STRUCT_NAME $STATIC_TABLE_NAME [] =\\n{\\n\";\n\n  for ($i = 0; $i < ($OPT_NUM - 1); $i++)\n    {\n      emit_option_table_entry ($i, 0);\n      print \"\\n\";\n    }\n  emit_option_table_entry ($i, 0);\n\n  print \"};\\n\\n\";\n}\n\nsub emit_option_table_entry\n{\n  my ($i, $empty) = @_;\n\n  my $k;\n\n  if ($empty)\n    {\n      print \"  { nullptr,\\n\";\n    }\n  else\n    {\n      print \"  { \\\"$NAME[$i]\\\",\\n\";\n    }\n\n  my $n = scalar $#{$KW_TOK[$i]};\n  print \"    {\";\n  for $k (0 .. $MAX_TOKENS)\n    {\n      if ($empty or $k > $n)\n        {\n          print \" nullptr,\";\n        }\n      else\n        {\n          print \" \\\"$KW_TOK[$i][$k]\\\",\";\n        }\n    }\n  print \" },\\n\";\n\n  print \"    {\";\n  for $k (0 .. $MAX_TOKENS)\n    {\n      if ($empty or $k > $n)\n        {\n          print \" 0,\";\n        }\n      else\n        {\n          print \" $MIN_TOK_LEN_TO_MATCH[$i][$k],\";\n        }\n    }\n  print \" }, $MIN_TOKS_TO_MATCH[$i], \";\n\n  print \"},\\n\";\n}\n\nsub emit_print_function\n{\n  ## FIXME: determine the width of the table automatically.\n\n  print qq|static void\nprint_$CLASS_NAME (std::ostream& os)\n{\n  std::ostringstream buf;\n\n  os << \"\\\\n\"\n     << \"Options for $CLASS include:\\\\n\\\\n\"\n     << \"  keyword                                             value\\\\n\"\n     << \"  -------                                             -----\\\\n\";\n\n  $STRUCT_NAME *list = $STATIC_TABLE_NAME;\\n\\n|;\n\n  for (my $i = 0; $i < $OPT_NUM; $i++)\n    {\n      print qq|  {\\n    os << \"  \"\n        << std::setiosflags (std::ios::left) << std::setw (50)\n        << list[$i].keyword\n        << std::resetiosflags (std::ios::left)\n        << \"  \";\\n\\n|;\n\n      if ($TYPE[$i] eq \"double\")\n        {\n          print qq|    double val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n|;\n          print qq|    os << val << \"\\\\n\";\\n|;\n        }\n      elsif ($TYPE[$i] eq \"float\")\n        {\n          print qq|    float val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n|;\n          print qq|    os << val << \"\\\\n\";\\n|;\n        }\n      elsif ($TYPE[$i] eq \"int\" or $TYPE[$i] eq \"octave_idx_type\")\n        {\n          print qq|    int val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n|;\n          print qq|    os << val << \"\\\\n\";\\n|;\n        }\n      elsif ($TYPE[$i] eq \"std::string\")\n        {\n          print qq|    os << $STATIC_OBJECT_NAME.$OPT[$i] () << \"\\\\n\";\\n|;\n        }\n      elsif ($TYPE[$i] eq \"Array<int>\" or $TYPE[$i] eq \"Array<octave_idx_type>\")\n        {\n          my $elt_type;\n          if ($TYPE[$i] eq \"Array<int>\")\n            {\n              $elt_type = \"int\";\n            }\n          else\n            {\n              $elt_type = \"octave_idx_type\";\n            }\n          print qq|    Array<$elt_type> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n|;\n          print qq|    if (val.numel () == 1)\n      {\n        os << val(0) << \"\\\\n\";\n      }\n    else\n      {\n        os << \"\\\\n\\\\n\";\n        octave_idx_type len = val.numel ();\n        Matrix tmp (len, 1);\n        for (octave_idx_type i = 0; i < len; i++)\n          tmp(i,0) = val(i);\n        octave_print_internal (os, tmp, false, 2);\n        os << \"\\\\n\\\\n\";\n      }\\n|;\n        }\n      elsif ($TYPE[$i] eq \"Array<double>\")\n        {\n          print qq|    Array<double> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n|;\n          print qq|    if (val.numel () == 1)\n      {\n        os << val(0) << \"\\\\n\";\n      }\n    else\n      {\n        os << \"\\\\n\\\\n\";\n        Matrix tmp = Matrix (ColumnVector (val));\n        octave_print_internal (os, tmp, false, 2);\n        os << \"\\\\n\\\\n\";\n      }\\n|;\n        }\n      elsif ($TYPE[$i] eq \"Array<float>\")\n        {\n          print qq|    Array<float> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n|;\n          print qq|    if (val.numel () == 1)\n      {\n        os << val(0) << \"\\\\n\";\n      }\n    else\n      {\n        os << \"\\\\n\\\\n\";\n        FloatMatrix tmp = FloatMatrix (FloatColumnVector (val));\n        octave_print_internal (os, tmp, false, 2);\n        os << \"\\\\n\\\\n\";\n      }\\n|;\n        }\n      else\n        {\n          die (\"unknown type $TYPE[$i]\");\n        }\n\n      print \"  }\\n\\n\";\n    }\n\n  print qq|  os << \"\\\\n\";\\n}\\n\\n|;\n}\n\nsub emit_set_functions\n{\n  print \"static void\nset_$CLASS_NAME (const std::string& keyword, const octave_value& val)\n{\n  $STRUCT_NAME *list = $STATIC_TABLE_NAME;\\n\\n\";\n\n  my $iftok = \"if\";\n\n  for (my $i = 0; $i < $OPT_NUM; $i++)\n    {\n      $iftok = \"else if\" if ($i > 0);\n\n      print \"  $iftok (octave::keyword_almost_match (list[$i].kw_tok, list[$i].min_len,\n           keyword, list[$i].min_toks_to_match, MAX_TOKENS))\n    {\\n\";\n\n      if ($TYPE[$i] eq \"double\")\n        {\n          print \"      double tmp = val.double_value ();\\n\\n\";\n          print \"      $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\\n\";\n        }\n      elsif ($TYPE[$i] eq \"float\")\n        {\n          print \"      float tmp = val.float_value ();\\n\\n\";\n          print \"      $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\\n\";\n        }\n      elsif ($TYPE[$i] eq \"int\" or $TYPE[$i] eq \"octave_idx_type\")\n        {\n          print \"      int tmp = val.int_value ();\\n\\n\";\n          print \"      $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\\n\";\n        }\n      elsif ($TYPE[$i] eq \"std::string\")\n        {\n          print \"      std::string tmp = val.string_value ();\\n\\n\";\n          print \"      $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\\n\";\n        }\n      elsif ($TYPE[$i] eq \"Array<int>\" or $TYPE[$i] eq \"Array<octave_idx_type>\")\n        {\n          print \"      Array<int> tmp = val.int_vector_value ();\\n\\n\";\n          print \"      $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\\n\";\n        }\n      elsif ($TYPE[$i] eq \"Array<double>\")\n        {\n          print \"      Array<double> tmp = val.vector_value ();\\n\\n\";\n          print \"      $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\\n\";\n        }\n      elsif ($TYPE[$i] eq \"Array<float>\")\n        {\n          print \"      Array<float> tmp = val.float_vector_value ();\\n\\n\";\n          print \"      $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\\n\";\n        }\n      else\n        {\n          die (\"unknown type $TYPE[$i]\");\n        }\n\n      print \"    }\\n\";\n    }\n\n  print qq|  else\n    {\n      warning (\"$OPT_FCN_NAME: no match for `%s'\", keyword.c_str ());\n    }\n}\\n\\n|;\n}\n\nsub emit_show_function\n{\n  print \"static octave_value_list\nshow_$CLASS_NAME (const std::string& keyword)\n{\n  octave_value retval;\n\n  $STRUCT_NAME *list = $STATIC_TABLE_NAME;\\n\\n\";\n\n  my $iftok = \"if\";\n\n  for (my $i = 0; $i < $OPT_NUM; $i++)\n    {\n      $iftok = \"else if\" if ($i > 0);\n\n      print \"  $iftok (octave::keyword_almost_match (list[$i].kw_tok, list[$i].min_len,\n           keyword, list[$i].min_toks_to_match, MAX_TOKENS))\n    {\\n\";\n\n      if ($TYPE[$i] eq \"double\")\n        {\n          print \"      double val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n\";\n          print \"      retval = val;\\n\";\n        }\n      elsif ($TYPE[$i] eq \"float\")\n        {\n          print \"      float val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n\";\n          print \"      retval = val;\\n\";\n        }\n      elsif ($TYPE[$i] eq \"int\" or $TYPE[$i] eq \"octave_idx_type\")\n        {\n          print \"      int val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n\";\n          print \"      retval = static_cast<double> (val);\\n\";\n        }\n      elsif ($TYPE[$i] eq \"std::string\")\n        {\n          print \"      retval = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\";\n        }\n      elsif ($TYPE[$i] eq \"Array<int>\" or $TYPE[$i] eq \"Array<octave_idx_type>\")\n        {\n          my $elt_type;\n          if ($TYPE[$i] eq \"Array<int>\")\n            {\n              $elt_type = \"int\";\n            }\n          else\n            {\n              $elt_type = \"octave_idx_type\";\n            }\n          print \"      Array<$elt_type> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n\";\n          print \"      if (val.numel () == 1)\n        {\n          retval = static_cast<double> (val(0));\n        }\n      else\n        {\n          octave_idx_type len = val.numel ();\n          ColumnVector tmp (len);\n          for (octave_idx_type i = 0; i < len; i++)\n            tmp(i) = val(i);\n          retval = tmp;\n        }\\n\";\n        }\n      elsif ($TYPE[$i] eq \"Array<double>\")\n        {\n          print \"      Array<double> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n\";\n          print \"      if (val.numel () == 1)\n        {\n          retval = val(0);\n        }\n      else\n        {\n          retval = ColumnVector (val);\n        }\\n\";\n        }\n      elsif ($TYPE[$i] eq \"Array<float>\")\n        {\n          print \"      Array<float> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\\n\\n\";\n          print \"      if (val.numel () == 1)\n        {\n          retval = val(0);\n        }\n      else\n        {\n          retval = FloatColumnVector (val);\n        }\\n\";\n        }\n      else\n        {\n          die (\"unknown type $TYPE[$i]\");\n        }\n\n      print \"    }\\n\";\n    }\n\n  print qq|  else\n    {\n      warning (\"$OPT_FCN_NAME: no match for `%s'\", keyword.c_str ());\n    }\n\n  return retval;\\n}\\n\\n|;\n}\n\nsub emit_options_function\n{\n  print <<\"_END_EMIT_OPTIONS_FUNCTION_HDR_\";\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN ($OPT_FCN_NAME, args, ,\n       doc: /* -*- texinfo -*-\n\\@deftypefn  {} {} $OPT_FCN_NAME ()\n\\@deftypefnx {} {val =} $OPT_FCN_NAME (\\@var{opt})\n\\@deftypefnx {} {} $OPT_FCN_NAME (\\@var{opt}, \\@var{val})\n$DOC_STRING\n\nOptions include\n\n\\@table \\@asis\n_END_EMIT_OPTIONS_FUNCTION_HDR_\n# FIXME: Add extra newline above\n\n  for (my $i = 0; $i < $OPT_NUM; $i++)\n    {\n      print '@item @qcode{\"', $NAME[$i], '\"}', \"\\n\";\n      print $DOC_ITEM[$i] if $DOC_ITEM[$i];\n    }\n\n  print <<\"_END_EMIT_OPTIONS_FUNCTION_BODY_\";\n\\@end table\n\\@end deftypefn */)\n{\n  octave_value_list retval;\n\n  int nargin = args.length ();\n\n  if (nargin > 2)\n    print_usage ();\n\n  if (nargin == 0)\n    {\n      print_$CLASS_NAME (octave_stdout);\n    }\n  else\n    {\n      std::string keyword = args(0).xstring_value (\"$OPT_FCN_NAME: expecting keyword as first argument\");\n\n      if (nargin == 1)\n        retval = show_$CLASS_NAME (keyword);\n      else\n        set_$CLASS_NAME (keyword, args(1));\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n_END_EMIT_OPTIONS_FUNCTION_BODY_\n\n}\n\nsub emit_options_debug\n{\n  print qq|CLASS = \"$CLASS\"\\n|;\n\n  for (my $i = 0; $i < $OPT_NUM; $i++)\n    {\n      print \"\\nOPTION\\n\";\n      print qq|  NAME = \"$NAME[$i]\"\\n|;\n      print qq|  TYPE = \"$TYPE[$i]\"\\n|;\n      if ($SET_ARG_TYPE[$i])\n        {\n          print eval (\"\\\"  SET_ARG_TYPE = \\\\\\\"$SET_ARG_TYPE[$i]\\\\\\\"\\\"\") . \"\\n\";\n        }\n      if ($INIT_VALUE[$i])\n        {\n          print qq|  INIT_VALUE = \"$INIT_VALUE[$i]\"\\n|;\n        }\n      if ($INIT_BODY[$i])\n        {\n          print \"  INIT_BODY\\n\";\n          print &substopt ($INIT_BODY[$i]);\n          print \"  END_INIT_BODY\\n\";\n        }\n      if ($SET_EXPR[$i])\n        {\n          print qq|  SET_EXPR = \"$SET_EXPR[$i]\"\\n|;\n        }\n      if ($SET_BODY[$i])\n        {\n          print \"  SET_BODY\\n\";\n          print &substopt ($SET_BODY[$i]);\n          print \"  END_SET_BODY\\n\";\n        }\n      if ($SET_CODE[$i])\n        {\n          print \"  SET_CODE\\n\";\n          print &substopt ($SET_CODE[$i]);\n          print \"  END_SET_CODE\\n\";\n        }\n      print \"END_OPTION\\n\";\n    }\n}\n\nsub substopt\n{\n  my ($string, $optvar, $opt, $type) = @_;\n\n  $string =~ s/\\$OPTVAR/$optvar/g;\n  $string =~ s/\\$OPT/$opt/g;\n  $string =~ s/\\$TYPE/$type/g;\n\n  return $string;\n}\n\nsub max\n{\n  my $max = shift;\n\n  foreach (@_)\n    {\n      $max = $_ if $max < $_;\n    }\n\n  return $max;\n}\n\n################################################################################\n# Subroutine processes any command line arguments\n################################################################################\nsub parse_options\n{\n  my $result;\n\n  $opt_help = 0;\n  $opt_class_header = 0;\n  $opt_handler_fcns = 0;\n  $opt_debug = 0;\n\n  $result = GetOptions (\"opt-class-header\" => \\$opt_class_header,\n                        \"opt-handler-fcns\" => \\$opt_handler_fcns,\n                        \"debug\" => \\$opt_debug,\n                        \"help\"  => \\$opt_help);\n\n  # give user info if options incorrect or -h(elp) given\n  &usage_info if (!$result or (@ARGV != 1) or $opt_help);\n  if ($opt_class_header and $opt_handler_fcns)\n  {\n    die \"Only one of [-opt-class-header | -opt-handler-fcns ] may be specified\";\n  }\n\n}\n\n################################################################################\n# Subroutine displays usage information\n################################################################################\nsub usage_info\n{\n   warn <<_END_OF_USAGE_;\n//////////////////////////////////////////////////////////////////////////////\nUSAGE : mk-opts.pl -opt-class-header|-opt-handler-fcns [-debug] [-help] DEFN_FILE\n//////////////////////////////////////////////////////////////////////////////\n\nAutomatically generate C++ code for option handling code (DASSL, DASRT, etc.)\nfrom definition file.\n\nSee the head of mk-opts.pl for a description of the format that is parsed.\n_END_OF_USAGE_\n\n  exit(1);    # exit with error code\n}\n"
  },
  {
    "path": "build-aux/mk-pkg-add.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Attempt to get traditional sort behavior based on byte values.\nLC_ALL=C\nexport LC_ALL\n\nset -e\n\nSED=${SED:-sed}\n\nsrcdir=\"$1\"\nshift\n\nfor arg\ndo\n  src_file=\"$srcdir/$arg\"\n\n  if [ -f \"$src_file\" ]; then\n\n    ## Compute and print the autoloads.\n\n    base=`basename \"$src_file\" | $SED 's/\\.cc$//'`\n    fcns=`$SED -n \\\n      -e 's/^ *DEF\\(METHOD\\|UN\\)_\\(\\|STATIC_\\)DLD *( *\\([^, ]*\\) *,.*$/\\3/p' \\\n      -e 's/^ *DEF\\(METHOD\\|UN\\)X_\\(\\|STATIC_\\)DLD *( *\"\\([^\"]*\\)\".*$/\\3/p' \\\n      \"$src_file\" | \\\n      sort -u`\n    if [ -n \"$fcns\" ]; then\n      for n in $fcns; do\n        if [ \"$n\" = \"$base\" ]; then\n          true\n        else\n          echo \"autoload (\\\"$n\\\", \\\"$base.oct\\\");\"\n        fi\n      done\n    fi\n\n    ## Process PKG_ADD directives after autoloads so that all\n    ## necessary functions can be found before they are used.\n\n    $SED -n -e 's,^//* *PKG_ADD: *,,p' \\\n            -e 's,^/\\* *PKG_ADD: *\\(.*\\) *\\*/ *$,\\1,p' \"$src_file\"\n\n  fi\ndone\n\nexit $?\n"
  },
  {
    "path": "build-aux/module.mk",
    "content": "EXTRA_DIST += \\\n  %reldir%/OctJavaQry.class \\\n  %reldir%/OctJavaQry.java \\\n  %reldir%/changelog.tmpl \\\n  %reldir%/check-subst-vars.in.sh \\\n  %reldir%/find-defun-files.in.sh \\\n  %reldir%/find-files-with-tests.in.sh \\\n  %reldir%/get-source-mtime.sh \\\n  %reldir%/inplace-edit.pl \\\n  %reldir%/mk-hg-id.sh \\\n  %reldir%/mk-octave-config-h.sh \\\n  %reldir%/mk-opts.pl \\\n  %reldir%/mk-pkg-add.sh \\\n  %reldir%/move-if-change \\\n  %reldir%/subst-config-vals.in.sh \\\n  %reldir%/subst-cross-config-vals.in.sh \\\n  %reldir%/subst-script-vals.in.sh \\\n  %reldir%/update-bug-status.sh\n\nGEN_CONFIG_SHELL += \\\n  %reldir%/subst-config-vals.sh \\\n  %reldir%/subst-cross-config-vals.sh \\\n  %reldir%/subst-script-vals.sh\n\n$(GEN_CONFIG_SHELL) : %.sh : %.in.sh config.status\n\t$(AM_V_GEN)$(SHELL) config.status $@-tmp $@\n\nGEN_CONFIG_INC = \\\n  oct-conf-post-private.h \\\n  oct-conf-post-public.h\n\n$(GEN_CONFIG_INC) : %.h : %.in.h config.status\n\t$(AM_V_GEN)$(SHELL) config.status $@-tmp $@\n\n### utility rules to aid development\n\nALL_TEST_FILES = \\\n  $(addprefix $(srcdir)/, $(LIBOCTAVE_TST_FILES_SRC)) \\\n  $(addprefix $(srcdir)/, $(LIBINTERP_TST_FILES_SRC)) \\\n  $(addprefix $(srcdir)/, $(FCN_FILES_WITH_TESTS)) \\\n  $(addprefix $(srcdir)/, $(TEST_FILES))\n\n## Tag bug IDs in tests as fixed\nupdate-bug-status:\n\t$(SHELL) $(srcdir)/%reldir%/update-bug-status.sh $(ALL_TEST_FILES)\n.PHONY: update-bug-status\n"
  },
  {
    "path": "build-aux/subst-config-vals.in.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n: ${SED=@SED@}\n\ncanonical_host_type=\"@canonical_host_type@\"\nDEFAULT_PAGER=\"@DEFAULT_PAGER@\"\nEXEEXT=\"@EXEEXT@\"\nman1ext=\"@man1ext@\"\napi_version=\"@OCTAVE_API_VERSION@\"\nOCTAVE_RELEASE=\"\"\nversion=\"@PACKAGE_VERSION@\"\n\nprefix=\"@prefix@\"\nexec_prefix=\"@exec_prefix@\"\n\narchlibdir=`echo \"@archlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nbindir=`echo \"@bindir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlibdir=`echo \"@libdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlibexecdir=`echo \"@libexecdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalapiarchlibdir=`echo \"@localapiarchlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalapioctfiledir=`echo \"@localapioctfiledir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalarchlibdir=`echo \"@localarchlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocaloctfiledir=`echo \"@localoctfiledir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalverarchlibdir=`echo \"@localverarchlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalveroctfiledir=`echo \"@localveroctfiledir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\noctfiledir=`echo \"@octfiledir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\noctlibdir=`echo \"@octlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\n\ndatadir=`echo \"@datadir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ndatarootdir=`echo \"@datarootdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ndoc_cache_file=`echo \"@doc_cache_file@\" | $SED \"s|^${prefix}/\\\\+||\"`\nexec_prefix=`echo \"@exec_prefix@\" | $SED \"s|^${prefix}/\\\\+||\"`\nfcnfiledir=`echo \"@fcnfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nimagedir=`echo \"@imagedir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nincludedir=`echo \"@includedir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ninfodir=`echo \"@infodir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ninfofile=`echo \"@infofile@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalapifcnfiledir=`echo \"@localapifcnfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalapipkgdir=`echo \"@localapipkgdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalfcnfiledir=`echo \"@localfcnfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalstartupfiledir=`echo \"@localstartupfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalapiarchlibdir=`echo \"@localapiarchlibdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalverfcnfiledir=`echo \"@localverfcnfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nman1dir=`echo \"@man1dir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nmandir=`echo \"@mandir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctdatadir=`echo \"@octdatadir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctdocdir=`echo \"@octdocdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctetcdir=`echo \"@octetcdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctfontsdir=`echo \"@octfontsdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctincludedir=`echo \"@octincludedir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctlocaledir=`echo \"@octlocaledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nocttestsdir=`echo \"@octtestsdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nstartupfiledir=`echo \"@startupfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ntexi_macros_file=`echo \"@texi_macros_file@\" | $SED \"s|^${prefix}/\\\\+||\"`\n\n## FIXME: Some of these flags might contain double quotes.\n##        Is it ok to use single quotes here?\nif [ \"x@OCTAVE_RELOCATE_ALL@\" = \"xyes\" ]; then\n  ## Replace portions of compiler flags that depend on prefix on target\n  if [ \"x@OCTAVE_RELOCATE_WITH_CYGPATH@\" = \"xyes\" ]; then\n    ## Replace all path forms of the prefix\n    cppflags=`echo '@CPPFLAGS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    fftw3f_ldflags=`echo '@FFTW3F_LDFLAGS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    fftw3_ldflags=`echo '@FFTW3_LDFLAGS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    flibs=`echo '@FLIBS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    ldflags=`echo '@LDFLAGS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    oct_link_opts=`echo '@OCT_LINK_OPTS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    mkoctfile_octave_link_deps=`echo '@MKOCTFILE_OCTAVE_LINK_DEPS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    mkoctfile_oct_link_deps=`echo '@MKOCTFILE_OCT_LINK_DEPS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  else\n    cppflags=`echo '@CPPFLAGS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    fftw3f_ldflags=`echo '@FFTW3F_LDFLAGS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    fftw3_ldflags=`echo '@FFTW3_LDFLAGS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    flibs=`echo '@FLIBS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    ldflags=`echo '@LDFLAGS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    oct_link_opts=`echo '@OCT_LINK_OPTS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    mkoctfile_octave_link_deps=`echo '@MKOCTFILE_OCTAVE_LINK_DEPS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    mkoctfile_oct_link_deps=`echo '@MKOCTFILE_OCT_LINK_DEPS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  fi\nelse\n  cppflags=`echo '@CPPFLAGS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  fftw3f_ldflags=`echo '@FFTW3F_LDFLAGS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  fftw3_ldflags=`echo '@FFTW3_LDFLAGS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  flibs=`echo '@FLIBS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  ldflags=`echo '@LDFLAGS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  oct_link_opts=`echo '@OCT_LINK_OPTS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  mkoctfile_octave_link_deps=`echo '@MKOCTFILE_OCTAVE_LINK_DEPS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  mkoctfile_oct_link_deps=`echo '@MKOCTFILE_OCT_LINK_DEPS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\nfi\n\n\nsrcdir=\"@srcdir@\"\ntop_srcdir=\"@top_srcdir@\"\nabs_srcdir=\"@abs_srcdir@\"\nabs_top_srcdir=\"@abs_top_srcdir@\"\n\nNO_OCT_FILE_STRIP=\"@NO_OCT_FILE_STRIP@\"\nAMD_CPPFLAGS=\"@AMD_CPPFLAGS@\"\nAMD_LDFLAGS=\"@AMD_LDFLAGS@\"\nAMD_LIBS=\"@AMD_LIBS@\"\nAR=\"@AR@\"\nARFLAGS=\"@ARFLAGS@\"\nARPACK_CPPFLAGS=\"@ARPACK_CPPFLAGS@\"\nARPACK_LDFLAGS=\"@ARPACK_LDFLAGS@\"\nARPACK_LIBS=\"@ARPACK_LIBS@\"\nBLAS_LIBS=\"@BLAS_LIBS@\"\nCAMD_CPPFLAGS=\"@CAMD_CPPFLAGS@\"\nCAMD_LDFLAGS=\"@CAMD_LDFLAGS@\"\nCAMD_LIBS=\"@CAMD_LIBS@\"\nCARBON_LIBS=\"@CARBON_LIBS@\"\nCC=\"@CC@\"\nCCOLAMD_CPPFLAGS=\"@CCOLAMD_CPPFLAGS@\"\nCCOLAMD_LDFLAGS=\"@CCOLAMD_LDFLAGS@\"\nCCOLAMD_LIBS=\"@CCOLAMD_LIBS@\"\nCFLAGS=\"@CFLAGS@\"\nCHOLMOD_CPPFLAGS=\"@CHOLMOD_CPPFLAGS@\"\nCHOLMOD_LDFLAGS=\"@CHOLMOD_LDFLAGS@\"\nCHOLMOD_LIBS=\"@CHOLMOD_LIBS@\"\nCOLAMD_CPPFLAGS=\"@COLAMD_CPPFLAGS@\"\nCOLAMD_LDFLAGS=\"@COLAMD_LDFLAGS@\"\nCOLAMD_LIBS=\"@COLAMD_LIBS@\"\nCPICFLAG=\"@CPICFLAG@\"\nCURL_CPPFLAGS=\"@CURL_CPPFLAGS@\"\nCURL_LDFLAGS=\"@CURL_LDFLAGS@\"\nCURL_LIBS=\"@CURL_LIBS@\"\nCXSPARSE_CPPFLAGS=\"@CXSPARSE_CPPFLAGS@\"\nCXSPARSE_LDFLAGS=\"@CXSPARSE_LDFLAGS@\"\nCXSPARSE_LIBS=\"@CXSPARSE_LIBS@\"\nCXX=\"@CXX@\"\nCXXCPP=\"@CXXCPP@\"\nCXXFLAGS=\"@CXXFLAGS@\"\nCXXPICFLAG=\"@CXXPICFLAG@\"\nDEFAULT_PAGER=\"@DEFAULT_PAGER@\"\nDEFS=\"@DEFS@\"\nDEPEND_FLAGS=\"@DEPEND_FLAGS@\"\nDEPEND_EXTRA_SED_PATTERN=\"@DEPEND_EXTRA_SED_PATTERN@\"\nDL_LDFLAGS=\"@DL_LDFLAGS@\"\nEXEEXT=\"@EXEEXT@\"\nGCC_VERSION=\"@GCC_VERSION@\"\nGXX_VERSION=\"@GXX_VERSION@\"\nF77=\"@F77@\"\nF77_FLOAT_STORE_FLAG=\"@F77_FLOAT_STORE_FLAG@\"\nF77_INTEGER_8_FLAG=\"@F77_INTEGER_8_FLAG@\"\nFFLAGS=\"@FFLAGS@\"\nFFTW3_CPPFLAGS=\"@FFTW3_CPPFLAGS@\"\nFFTW3_LIBS=\"@FFTW3_LIBS@\"\nFFTW3F_CPPFLAGS=\"@FFTW3F_CPPFLAGS@\"\nFFTW3F_LIBS=\"@FFTW3F_LIBS@\"\nFLTK_CPPFLAGS=\"@FLTK_CPPFLAGS@\"\nFLTK_LDFLAGS=\"@FLTK_LDFLAGS@\"\nFLTK_LIBS=\"@FLTK_LIBS@\"\nFONTCONFIG_CPPFLAGS=\"@FONTCONFIG_CPPFLAGS@\"\nFONTCONFIG_LIBS=\"@FONTCONFIG_LIBS@\"\nFPICFLAG=\"@FPICFLAG@\"\nFT2_CPPFLAGS=\"@FT2_CPPFLAGS@\"\nFT2_LIBS=\"@FT2_LIBS@\"\nGLPK_CPPFLAGS=\"@GLPK_CPPFLAGS@\"\nGLPK_LDFLAGS=\"@GLPK_LDFLAGS@\"\nGLPK_LIBS=\"@GLPK_LIBS@\"\nGNUPLOT=\"@GNUPLOT@\"\nHDF5_CPPFLAGS=\"@HDF5_CPPFLAGS@\"\nHDF5_LDFLAGS=\"@HDF5_LDFLAGS@\"\nHDF5_LIBS=\"@HDF5_LIBS@\"\nKLU_CPPFLAGS=\"@KLU_CPPFLAGS@\"\nKLU_LDFLAGS=\"@KLU_LDFLAGS@\"\nKLU_LIBS=\"@KLU_LIBS@\"\nLAPACK_LIBS=\"@LAPACK_LIBS@\"\nLD_STATIC_FLAG=\"@LD_STATIC_FLAG@\"\nLEX=\"@LEX@\"\nLEXLIB=\"@LEXLIB@\"\nLFLAGS=\"@LFLAGS@\"\nLIBOCTAVE=\"@LIBOCTAVE@\"\nLIBOCTINTERP=\"@LIBOCTINTERP@\"\nLIBS=\"@LIBS@\"\nLN_S=\"@LN_S@\"\nMAGICK_CPPFLAGS=\"@MAGICK_CPPFLAGS@\"\nMAGICK_LDFLAGS=\"@MAGICK_LDFLAGS@\"\nMAGICK_LIBS=\"@MAGICK_LIBS@\"\nMKOCTFILE_AR=\"@MKOCTFILE_AR@\"\nMKOCTFILE_CC=\"@MKOCTFILE_CC@\"\nMKOCTFILE_CXX=\"@MKOCTFILE_CXX@\"\nMKOCTFILE_DL_LDFLAGS=\"@MKOCTFILE_DL_LDFLAGS@\"\nMKOCTFILE_F77=\"@MKOCTFILE_F77@\"\nMKOCTFILE_RANLIB=\"@MKOCTFILE_RANLIB@\"\nOCTAVE_LINK_DEPS=\"@OCTAVE_LINK_DEPS@\"\nOCTAVE_LINK_OPTS=\"@OCTAVE_LINK_OPTS@\"\nOCT_LINK_DEPS=\"@OCT_LINK_DEPS@\"\nOPENGL_LIBS=\"@OPENGL_LIBS@\"\nPCRE_CPPFLAGS=\"@PCRE_CPPFLAGS@\"\nPCRE_LDFLAGS=\"@PCRE_LDFLAGS@\"\nPCRE_LIBS=\"@PCRE_LIBS@\"\nPTHREAD_CFLAGS=\"@PTHREAD_CFLAGS@\"\nPTHREAD_LIBS=\"@PTHREAD_LIBS@\"\nQHULL_CPPFLAGS=\"@QHULL_CPPFLAGS@\"\nQHULL_LDFLAGS=\"@QHULL_LDFLAGS@\"\nQHULL_LIBS=\"@QHULL_LIBS@\"\nQRUPDATE_CPPFLAGS=\"@QRUPDATE_CPPFLAGS@\"\nQRUPDATE_LDFLAGS=\"@QRUPDATE_LDFLAGS@\"\nQRUPDATE_LIBS=\"@QRUPDATE_LIBS@\"\nQT_CPPFLAGS=\"@QT_CPPFLAGS@\"\nQT_LDFLAGS=\"@QT_LDFLAGS@\"\nQT_LIBS=\"@QT_LIBS@\"\nRANLIB=\"@RANLIB@\"\nRDYNAMIC_FLAG=\"@RDYNAMIC_FLAG@\"\nREADLINE_LIBS=\"@LIBREADLINE@\"\nSHARED_LIBS=\"@SHARED_LIBS@\"\nSH_LDFLAGS=\"@SH_LDFLAGS@\"\nSTATIC_LIBS=\"@STATIC_LIBS@\"\nSUITESPARSECONFIG_LIBS=\"@SUITESPARSECONFIG_LIBS@\"\nSUNDIALS_IDA_CPPFLAGS=\"@SUNDIALS_IDA_CPPFLAGS@\"\nSUNDIALS_IDA_LDFLAGS=\"@SUNDIALS_IDA_LDFLAGS@\"\nSUNDIALS_IDA_LIBS=\"@SUNDIALS_IDA_LIBS@\"\nSUNDIALS_NVECSERIAL_CPPFLAGS=\"@SUNDIALS_NVECSERIAL_CPPFLAGS@\"\nSUNDIALS_NVECSERIAL_LDFLAGS=\"@SUNDIALS_NVECSERIAL_LDFLAGS@\"\nSUNDIALS_NVECSERIAL_LIBS=\"@SUNDIALS_NVECSERIAL_LIBS@\"\nSUNDIALS_SUNLINSOLKLU_CPPFLAGS=\"@SUNDIALS_SUNLINSOLKLU_CPPFLAGS@\"\nSUNDIALS_SUNLINSOLKLU_LDFLAGS=\"@SUNDIALS_SUNLINSOLKLU_LDFLAGS@\"\nSUNDIALS_SUNLINSOLKLU_LIBS=\"@SUNDIALS_SUNLINSOLKLU_LIBS@\"\nUMFPACK_CPPFLAGS=\"@UMFPACK_CPPFLAGS@\"\nUMFPACK_LDFLAGS=\"@UMFPACK_LDFLAGS@\"\nUMFPACK_LIBS=\"@UMFPACK_LIBS@\"\nversion=\"@PACKAGE_VERSION@\"\nWARN_CFLAGS=\"@WARN_CFLAGS@\"\nWARN_CXXFLAGS=\"@WARN_CXXFLAGS@\"\nX11_INCFLAGS=\"@X11_INCFLAGS@\"\nX11_LIBS=\"@X11_LIBS@\"\nXTRA_CFLAGS=\"@XTRA_CFLAGS@\"\nXTRA_CXXFLAGS=\"@XTRA_CXXFLAGS@\"\nYACC=\"@YACC@\"\nYFLAGS=\"@YFLAGS@\"\nZ_CPPFLAGS=\"@Z_CPPFLAGS@\"\nZ_LDFLAGS=\"@Z_LDFLAGS@\"\nZ_LIBS=\"@Z_LIBS@\"\nconfig_opts=\"@config_opts@\"\n\n$SED \\\n  -e \"s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by subst-config-vals.|\" \\\n  -e \"s|%NO_OCT_FILE_STRIP%|${NO_OCT_FILE_STRIP}|\" \\\n  -e \"s|%OCTAVE_API_VERSION%|\\\"${api_version}\\\"|\" \\\n  -e \"s|%OCTAVE_ARCHLIBDIR%|\\\"${archlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_BINDIR%|\\\"${bindir}\\\"|\" \\\n  -e \"s|%OCTAVE_BINDIR%|\\\"${bindir}\\\"|\" \\\n  -e \"s|%OCTAVE_CANONICAL_HOST_TYPE%|\\\"${canonical_host_type}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_AMD_CPPFLAGS%|\\\"${AMD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_AMD_LDFLAGS%|\\\"${AMD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_AMD_LIBS%|\\\"${AMD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_AR%|\\\"${AR}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_ARFLAGS%|\\\"${ARFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_ARPACK_CPPFLAGS%|\\\"${ARPACK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_ARPACK_LDFLAGS%|\\\"${ARPACK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_ARPACK_LIBS%|\\\"${ARPACK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_BLAS_LIBS%|\\\"${BLAS_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CAMD_CPPFLAGS%|\\\"${CAMD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CAMD_LDFLAGS%|\\\"${CAMD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CAMD_LIBS%|\\\"${CAMD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CARBON_LIBS%|\\\"${CARBON_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CC%|\\\"${CC}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CCOLAMD_CPPFLAGS%|\\\"${CCOLAMD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CCOLAMD_LDFLAGS%|\\\"${CCOLAMD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CCOLAMD_LIBS%|\\\"${CCOLAMD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CFLAGS%|\\\"${CFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CHOLMOD_CPPFLAGS%|\\\"${CHOLMOD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CHOLMOD_LDFLAGS%|\\\"${CHOLMOD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CHOLMOD_LIBS%|\\\"${CHOLMOD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_COLAMD_CPPFLAGS%|\\\"${COLAMD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_COLAMD_LDFLAGS%|\\\"${COLAMD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_COLAMD_LIBS%|\\\"${COLAMD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CPICFLAG%|\\\"${CPICFLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CPPFLAGS%|\\\"${cppflags}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CURL_CPPFLAGS%|\\\"${CURL_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CURL_LDFLAGS%|\\\"${CURL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CURL_LIBS%|\\\"${CURL_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXSPARSE_CPPFLAGS%|\\\"${CXSPARSE_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXSPARSE_LDFLAGS%|\\\"${CXSPARSE_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXSPARSE_LIBS%|\\\"${CXSPARSE_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXX%|\\\"${CXX}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXXCPP%|\\\"${CXXCPP}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXXFLAGS%|\\\"${CXXFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXXPICFLAG%|\\\"${CXXPICFLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DEFAULT_PAGER%|\\\"${DEFAULT_PAGER}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DEFS%|\\\"${DEFS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%|\\\"${DEPEND_EXTRA_SED_PATTERN}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DEPEND_FLAGS%|\\\"${DEPEND_FLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DL_LDFLAGS%|\\\"${DL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_EXEC_PREFIX%|\\\"${exec_prefix}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_EXEEXT%|\\\"${EXEEXT}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_F77%|\\\"${F77}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_F77_FLOAT_STORE_FLAG%|\\\"${F77_FLOAT_STORE_FLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_F77_INTEGER_8_FLAG%|\\\"${F77_INTEGER_8_FLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFLAGS%|\\\"${FFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3F_CPPFLAGS%|\\\"${FFTW3F_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3F_LDFLAGS%|\\\"${fftw3f_ldflags}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3F_LIBS%|\\\"${FFTW3F_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3_CPPFLAGS%|\\\"${FFTW3_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3_LDFLAGS%|\\\"${fftw3_ldflags}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3_LIBS%|\\\"${FFTW3_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FLIBS%|\\\"${flibs}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FLTK_CPPFLAGS%|\\\"${FLTK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FLTK_LDFLAGS%|\\\"${FLTK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FLTK_LIBS%|\\\"${FLTK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FONTCONFIG_CPPFLAGS%|\\\"${FONTCONFIG_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FONTCONFIG_LIBS%|\\\"${FONTCONFIG_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FPICFLAG%|\\\"${FPICFLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FT2_CPPFLAGS%|\\\"${FT2_CPPFLAGS}\\\"|\" | \\\n  $SED \\\n  -e \"s|%OCTAVE_CONF_FT2_LIBS%|\\\"${FT2_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GCC_VERSION%|\\\"${GCC_VERSION}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GLPK_CPPFLAGS%|\\\"${GLPK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GLPK_LDFLAGS%|\\\"${GLPK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GLPK_LIBS%|\\\"${GLPK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GNUPLOT%|\\\"${GNUPLOT}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GXX_VERSION%|\\\"${GXX_VERSION}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_HDF5_CPPFLAGS%|\\\"${HDF5_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_HDF5_LDFLAGS%|\\\"${HDF5_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_HDF5_LIBS%|\\\"${HDF5_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_INCLUDEDIR%|\\\"${includedir}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_KLU_CPPFLAGS%|\\\"${KLU_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_KLU_LDFLAGS%|\\\"${KLU_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_KLU_LIBS%|\\\"${KLU_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LAPACK_LIBS%|\\\"${LAPACK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LDFLAGS%|\\\"${ldflags}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LD_STATIC_FLAG%|\\\"${LD_STATIC_FLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LEX%|\\\"${LEX}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LEXLIB%|\\\"${LEXLIB}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LFLAGS%|\\\"${LFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LIBDIR%|\\\"${libdir}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LIBOCTAVE%|\\\"${LIBOCTAVE}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LIBOCTINTERP%|\\\"${LIBOCTINTERP}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LIBS%|\\\"${LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LN_S%|\\\"${LN_S}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MAGICK_CPPFLAGS%|\\\"${MAGICK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MAGICK_LDFLAGS%|\\\"${MAGICK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MAGICK_LIBS%|\\\"${MAGICK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_AR%|\\\"${MKOCTFILE_AR}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_CC%|\\\"${MKOCTFILE_CC}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_CXX%|\\\"${MKOCTFILE_CXX}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%|\\\"${MKOCTFILE_DL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_F77%|\\\"${MKOCTFILE_F77}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_OCTAVE_LINK_DEPS%|\\\"${mkoctfile_octave_link_deps}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_OCT_LINK_DEPS%|\\\"${mkoctfile_oct_link_deps}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_RANLIB%|\\\"${MKOCTFILE_RANLIB}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCTAVE_LINK_DEPS%|\\\"${OCTAVE_LINK_DEPS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCTAVE_LINK_OPTS%|\\\"${OCTAVE_LINK_OPTS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCTINCLUDEDIR%|\\\"${octincludedir}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCTLIBDIR%|\\\"${octlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCT_LINK_DEPS%|\\\"${OCT_LINK_DEPS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCT_LINK_OPTS%|\\\"${oct_link_opts}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OPENGL_LIBS%|\\\"${OPENGL_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PCRE_CPPFLAGS%|\\\"${PCRE_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PCRE_LDFLAGS%|\\\"${PCRE_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PCRE_LIBS%|\\\"${PCRE_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PREFIX%|\\\"${prefix}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PTHREAD_CFLAGS%|\\\"${PTHREAD_CFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PTHREAD_LIBS%|\\\"${PTHREAD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QHULL_CPPFLAGS%|\\\"${QHULL_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QHULL_LDFLAGS%|\\\"${QHULL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QHULL_LIBS%|\\\"${QHULL_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QRUPDATE_CPPFLAGS%|\\\"${QRUPDATE_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QRUPDATE_LDFLAGS%|\\\"${QRUPDATE_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QRUPDATE_LIBS%|\\\"${QRUPDATE_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QT_CPPFLAGS%|\\\"${QT_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QT_LDFLAGS%|\\\"${QT_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QT_LIBS%|\\\"${QT_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_RANLIB%|\\\"${RANLIB}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_RDYNAMIC_FLAG%|\\\"${RDYNAMIC_FLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_READLINE_LIBS%|\\\"${READLINE_LIBS}\\\"|\" | \\\n  $SED \\\n  -e \"s|%OCTAVE_CONF_SHARED_LIBS%|\\\"${SHARED_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SH_LDFLAGS%|\\\"${SH_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_STATIC_LIBS%|\\\"${STATIC_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUITESPARSECONFIG_LIBS%|\\\"${SUITESPARSECONFIG_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_IDA_CPPFLAGS%|\\\"${SUNDIALS_IDA_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_IDA_LDFLAGS%|\\\"${SUNDIALS_IDA_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_IDA_LIBS%|\\\"${SUNDIALS_IDA_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_CPPFLAGS%|\\\"${SUNDIALS_NVECSERIAL_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_LDFLAGS%|\\\"${SUNDIALS_NVECSERIAL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_LIBS%|\\\"${SUNDIALS_NVECSERIAL_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_CPPFLAGS%|\\\"${SUNDIALS_SUNLINSOLKLU_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LDFLAGS%|\\\"${SUNDIALS_SUNLINSOLKLU_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LIBS%|\\\"${SUNDIALS_SUNLINSOLKLU_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_UMFPACK_CPPFLAGS%|\\\"${UMFPACK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_UMFPACK_LDFLAGS%|\\\"${UMFPACK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_UMFPACK_LIBS%|\\\"${UMFPACK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_VERSION%|\\\"${version}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_WARN_CFLAGS%|\\\"${WARN_CFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_WARN_CXXFLAGS%|\\\"${WARN_CXXFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_X11_INCFLAGS%|\\\"${X11_INCFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_X11_LIBS%|\\\"${X11_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_XTRA_CFLAGS%|\\\"${XTRA_CFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_XTRA_CXXFLAGS%|\\\"${XTRA_CXXFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_YACC%|\\\"${YACC}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_YFLAGS%|\\\"${YFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_Z_CPPFLAGS%|\\\"${Z_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_Z_LDFLAGS%|\\\"${Z_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_Z_LIBS%|\\\"${Z_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_config_opts%|\\\"${config_opts}\\\"|\" \\\n  -e \"s|%OCTAVE_DATADIR%|\\\"${datadir}\\\"|\" \\\n  -e \"s|%OCTAVE_DATAROOTDIR%|\\\"${datarootdir}\\\"|\" \\\n  -e \"s|%OCTAVE_DEFAULT_PAGER%|\\\"${DEFAULT_PAGER}\\\"|\" \\\n  -e \"s|%OCTAVE_DOCDIR%|\\\"${docdir}\\\"|\" \\\n  -e \"s|%OCTAVE_DOC_CACHE_FILE%|\\\"${doc_cache_file}\\\"|\" \\\n  -e \"s|%OCTAVE_EXEC_PREFIX%|\\\"${exec_prefix}\\\"|\" \\\n  -e \"s|%OCTAVE_EXEEXT%|\\\"${EXEEXT}\\\"|\" \\\n  -e \"s|%OCTAVE_FCNFILEDIR%|\\\"${fcnfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_IMAGEDIR%|\\\"${imagedir}\\\"|\" \\\n  -e \"s|%OCTAVE_INCLUDEDIR%|\\\"${includedir}\\\"|\" \\\n  -e \"s|%OCTAVE_INFODIR%|\\\"${infodir}\\\"|\" \\\n  -e \"s|%OCTAVE_INFOFILE%|\\\"${infofile}\\\"|\" \\\n  -e \"s|%OCTAVE_LIBDIR%|\\\"${libdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LIBEXECDIR%|\\\"${libexecdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALAPIARCHLIBDIR%|\\\"${localapiarchlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALAPIFCNFILEDIR%|\\\"${localapifcnfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALAPIOCTFILEDIR%|\\\"${localapioctfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALAPIPKGDIR%|\\\"${localapipkgdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALARCHLIBDIR%|\\\"${localarchlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALFCNFILEDIR%|\\\"${localfcnfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALOCTFILEDIR%|\\\"${localoctfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALSTARTUPFILEDIR%|\\\"${localstartupfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALVERARCHLIBDIR%|\\\"${localverarchlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALVERFCNFILEDIR%|\\\"${localverfcnfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALVEROCTFILEDIR%|\\\"${localveroctfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_MAN1DIR%|\\\"${man1dir}\\\"|\" \\\n  -e \"s|%OCTAVE_MAN1EXT%|\\\"${man1ext}\\\"|\" \\\n  -e \"s|%OCTAVE_MANDIR%|\\\"${mandir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTDATADIR%|\\\"${octdatadir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTDOCDIR%|\\\"${octdocdir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTETCDIR%|\\\"${octetcdir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTFILEDIR%|\\\"${octfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTFONTSDIR%|\\\"${octfontsdir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTINCLUDEDIR%|\\\"${octincludedir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTLIBDIR%|\\\"${octlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTLOCALEDIR%|\\\"${octlocaledir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTTESTSDIR%|\\\"${octtestsdir}\\\"|\" \\\n  -e \"s|%OCTAVE_PREFIX%|\\\"${prefix}\\\"|\" \\\n  -e \"s|%OCTAVE_RELEASE%|\\\"${OCTAVE_RELEASE}\\\"|\" \\\n  -e \"s|%OCTAVE_STARTUPFILEDIR%|\\\"${startupfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_TEXI_MACROS_FILE%|\\\"${texi_macros_file}\\\"|\" \\\n  -e \"s|%OCTAVE_VERSION%|\\\"${version}\\\"|\"\n"
  },
  {
    "path": "build-aux/subst-cross-config-vals.in.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n: ${SED=@SED@}\n\n## The subst-config-vals and subst-cross-config-vals scripts differ only\n## in the definitions of the following variables.\n##\n##   OCTAVE_CONF_MKOCTFILE_AR\n##   OCTAVE_CONF_MKOCTFILE_CC\n##   OCTAVE_CONF_MKOCTFILE_CXX\n##   OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS\n##   OCTAVE_CONF_MKOCTFILE_F77\n##   OCTAVE_CONF_MKOCTFILE_RANLIB\n\ncanonical_host_type=\"@canonical_host_type@\"\nDEFAULT_PAGER=\"@DEFAULT_PAGER@\"\nEXEEXT=\"@EXEEXT@\"\nman1ext=\"@man1ext@\"\napi_version=\"@OCTAVE_API_VERSION@\"\nOCTAVE_RELEASE=\"\"\nversion=\"@PACKAGE_VERSION@\"\n\nprefix=\"@prefix@\"\nexec_prefix=\"@exec_prefix@\"\n\narchlibdir=`echo \"@archlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nbindir=`echo \"@bindir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlibdir=`echo \"@libdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlibexecdir=`echo \"@libexecdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalapiarchlibdir=`echo \"@localapiarchlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalapioctfiledir=`echo \"@localapioctfiledir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalarchlibdir=`echo \"@localarchlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocaloctfiledir=`echo \"@localoctfiledir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalverarchlibdir=`echo \"@localverarchlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\nlocalveroctfiledir=`echo \"@localveroctfiledir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\noctfiledir=`echo \"@octfiledir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\noctlibdir=`echo \"@octlibdir@\" | $SED \"s|^${exec_prefix}/\\\\+||\"`\n\ndatadir=`echo \"@datadir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ndatarootdir=`echo \"@datarootdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ndoc_cache_file=`echo \"@doc_cache_file@\" | $SED \"s|^${prefix}/\\\\+||\"`\nexec_prefix=`echo \"@exec_prefix@\" | $SED \"s|^${prefix}/\\\\+||\"`\nfcnfiledir=`echo \"@fcnfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nimagedir=`echo \"@imagedir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nincludedir=`echo \"@includedir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ninfodir=`echo \"@infodir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ninfofile=`echo \"@infofile@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalapifcnfiledir=`echo \"@localapifcnfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalapipkgdir=`echo \"@localapipkgdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalfcnfiledir=`echo \"@localfcnfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalstartupfiledir=`echo \"@localstartupfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalapiarchlibdir=`echo \"@localapiarchlibdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nlocalverfcnfiledir=`echo \"@localverfcnfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nman1dir=`echo \"@man1dir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nmandir=`echo \"@mandir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctdatadir=`echo \"@octdatadir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctdocdir=`echo \"@octdocdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctetcdir=`echo \"@octetcdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctfontsdir=`echo \"@octfontsdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctincludedir=`echo \"@octincludedir@\" | $SED \"s|^${prefix}/\\\\+||\"`\noctlocaledir=`echo \"@octlocaledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nocttestsdir=`echo \"@octtestsdir@\" | $SED \"s|^${prefix}/\\\\+||\"`\nstartupfiledir=`echo \"@startupfiledir@\" | $SED \"s|^${prefix}/\\\\+||\"`\ntexi_macros_file=`echo \"@texi_macros_file@\" | $SED \"s|^${prefix}/\\\\+||\"`\n\n## FIXME: Some of these flags might contain double quotes.\n##        Is it ok to use single quotes here?\nif [ \"x@OCTAVE_RELOCATE_ALL@\" = \"xyes\" ]; then\n  ## Replace portions of compiler flags that depend on prefix on target\n  if [ \"x@OCTAVE_RELOCATE_WITH_CYGPATH@\" = \"xyes\" ]; then\n    ## Replace all path forms of the prefix\n    cppflags=`echo '@CPPFLAGS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    fftw3f_ldflags=`echo '@FFTW3F_LDFLAGS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    fftw3_ldflags=`echo '@FFTW3_LDFLAGS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    flibs=`echo '@FLIBS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    ldflags=`echo '@LDFLAGS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    oct_link_opts=`echo '@OCT_LINK_OPTS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    mkoctfile_octave_link_deps=`echo '@MKOCTFILE_OCTAVE_LINK_DEPS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    mkoctfile_oct_link_deps=`echo '@MKOCTFILE_OCT_LINK_DEPS@' | sed \"s|$(@CYGPATH@ -m @prefix@)|\\$\\{prefix}|g\" | sed \"s|$(echo $(@CYGPATH@ -w @prefix@) | sed 's|\\\\\\\\|\\\\\\\\\\\\\\\\|g')|\\$\\{prefix}|g\" | sed \"s|$(@CYGPATH@ -u @prefix@)|\\$\\{prefix}|g\" | $SED \"s|(@prefix@)|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  else\n    cppflags=`echo '@CPPFLAGS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    fftw3f_ldflags=`echo '@FFTW3F_LDFLAGS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    fftw3_ldflags=`echo '@FFTW3_LDFLAGS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    flibs=`echo '@FLIBS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    ldflags=`echo '@LDFLAGS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    oct_link_opts=`echo '@OCT_LINK_OPTS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    mkoctfile_octave_link_deps=`echo '@MKOCTFILE_OCTAVE_LINK_DEPS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n    mkoctfile_oct_link_deps=`echo '@MKOCTFILE_OCT_LINK_DEPS@' | $SED \"s|@prefix@|\\$\\{prefix\\}|g\" | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  fi\nelse\n  cppflags=`echo '@CPPFLAGS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  fftw3f_ldflags=`echo '@FFTW3F_LDFLAGS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  fftw3_ldflags=`echo '@FFTW3_LDFLAGS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  flibs=`echo '@FLIBS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  ldflags=`echo '@LDFLAGS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  oct_link_opts=`echo '@OCT_LINK_OPTS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  mkoctfile_octave_link_deps=`echo '@MKOCTFILE_OCTAVE_LINK_DEPS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\n  mkoctfile_oct_link_deps=`echo '@MKOCTFILE_OCT_LINK_DEPS@' | $SED 's|\\\"|\\\\\\\\\\\\\\\"|g'`\nfi\n\n\nsrcdir=\"@srcdir@\"\ntop_srcdir=\"@top_srcdir@\"\nabs_srcdir=\"@abs_srcdir@\"\nabs_top_srcdir=\"@abs_top_srcdir@\"\n\nNO_OCT_FILE_STRIP=\"@NO_OCT_FILE_STRIP@\"\nAMD_CPPFLAGS=\"@AMD_CPPFLAGS@\"\nAMD_LDFLAGS=\"@AMD_LDFLAGS@\"\nAMD_LIBS=\"@AMD_LIBS@\"\nAR=\"@AR@\"\nARFLAGS=\"@ARFLAGS@\"\nARPACK_CPPFLAGS=\"@ARPACK_CPPFLAGS@\"\nARPACK_LDFLAGS=\"@ARPACK_LDFLAGS@\"\nARPACK_LIBS=\"@ARPACK_LIBS@\"\nBLAS_LIBS=\"@BLAS_LIBS@\"\nCAMD_CPPFLAGS=\"@CAMD_CPPFLAGS@\"\nCAMD_LDFLAGS=\"@CAMD_LDFLAGS@\"\nCAMD_LIBS=\"@CAMD_LIBS@\"\nCARBON_LIBS=\"@CARBON_LIBS@\"\nCC=\"@CC@\"\nCCOLAMD_CPPFLAGS=\"@CCOLAMD_CPPFLAGS@\"\nCCOLAMD_LDFLAGS=\"@CCOLAMD_LDFLAGS@\"\nCCOLAMD_LIBS=\"@CCOLAMD_LIBS@\"\nCFLAGS=\"@CFLAGS@\"\nCHOLMOD_CPPFLAGS=\"@CHOLMOD_CPPFLAGS@\"\nCHOLMOD_LDFLAGS=\"@CHOLMOD_LDFLAGS@\"\nCHOLMOD_LIBS=\"@CHOLMOD_LIBS@\"\nCOLAMD_CPPFLAGS=\"@COLAMD_CPPFLAGS@\"\nCOLAMD_LDFLAGS=\"@COLAMD_LDFLAGS@\"\nCOLAMD_LIBS=\"@COLAMD_LIBS@\"\nCPICFLAG=\"@CPICFLAG@\"\nCURL_CPPFLAGS=\"@CURL_CPPFLAGS@\"\nCURL_LDFLAGS=\"@CURL_LDFLAGS@\"\nCURL_LIBS=\"@CURL_LIBS@\"\nCXSPARSE_CPPFLAGS=\"@CXSPARSE_CPPFLAGS@\"\nCXSPARSE_LDFLAGS=\"@CXSPARSE_LDFLAGS@\"\nCXSPARSE_LIBS=\"@CXSPARSE_LIBS@\"\nCXX=\"@CXX@\"\nCXXCPP=\"@CXXCPP@\"\nCXXFLAGS=\"@CXXFLAGS@\"\nCXXPICFLAG=\"@CXXPICFLAG@\"\nDEFAULT_PAGER=\"@DEFAULT_PAGER@\"\nDEFS=\"@DEFS@\"\nDEPEND_FLAGS=\"@DEPEND_FLAGS@\"\nDEPEND_EXTRA_SED_PATTERN=\"@DEPEND_EXTRA_SED_PATTERN@\"\nDL_LDFLAGS=\"@DL_LDFLAGS@\"\nEXEEXT=\"@EXEEXT@\"\nGCC_VERSION=\"@GCC_VERSION@\"\nGXX_VERSION=\"@GXX_VERSION@\"\nF77=\"@F77@\"\nF77_FLOAT_STORE_FLAG=\"@F77_FLOAT_STORE_FLAG@\"\nF77_INTEGER_8_FLAG=\"@F77_INTEGER_8_FLAG@\"\nFFLAGS=\"@FFLAGS@\"\nFFTW3_CPPFLAGS=\"@FFTW3_CPPFLAGS@\"\nFFTW3_LIBS=\"@FFTW3_LIBS@\"\nFFTW3F_CPPFLAGS=\"@FFTW3F_CPPFLAGS@\"\nFFTW3F_LIBS=\"@FFTW3F_LIBS@\"\nFLTK_CPPFLAGS=\"@FLTK_CPPFLAGS@\"\nFLTK_LDFLAGS=\"@FLTK_LDFLAGS@\"\nFLTK_LIBS=\"@FLTK_LIBS@\"\nFONTCONFIG_CPPFLAGS=\"@FONTCONFIG_CPPFLAGS@\"\nFONTCONFIG_LIBS=\"@FONTCONFIG_LIBS@\"\nFPICFLAG=\"@FPICFLAG@\"\nFT2_CPPFLAGS=\"@FT2_CPPFLAGS@\"\nFT2_LIBS=\"@FT2_LIBS@\"\nGLPK_CPPFLAGS=\"@GLPK_CPPFLAGS@\"\nGLPK_LDFLAGS=\"@GLPK_LDFLAGS@\"\nGLPK_LIBS=\"@GLPK_LIBS@\"\nGNUPLOT=\"@GNUPLOT@\"\nHDF5_CPPFLAGS=\"@HDF5_CPPFLAGS@\"\nHDF5_LDFLAGS=\"@HDF5_LDFLAGS@\"\nHDF5_LIBS=\"@HDF5_LIBS@\"\nKLU_CPPFLAGS=\"@KLU_CPPFLAGS@\"\nKLU_LDFLAGS=\"@KLU_LDFLAGS@\"\nKLU_LIBS=\"@KLU_LIBS@\"\nLAPACK_LIBS=\"@LAPACK_LIBS@\"\nLD_STATIC_FLAG=\"@LD_STATIC_FLAG@\"\nLEX=\"@LEX@\"\nLEXLIB=\"@LEXLIB@\"\nLFLAGS=\"@LFLAGS@\"\nLIBOCTAVE=\"@LIBOCTAVE@\"\nLIBOCTINTERP=\"@LIBOCTINTERP@\"\nLIBS=\"@LIBS@\"\nLN_S=\"@LN_S@\"\nMAGICK_CPPFLAGS=\"@MAGICK_CPPFLAGS@\"\nMAGICK_LDFLAGS=\"@MAGICK_LDFLAGS@\"\nMAGICK_LIBS=\"@MAGICK_LIBS@\"\nOCTAVE_LINK_DEPS=\"@OCTAVE_LINK_DEPS@\"\nOCTAVE_LINK_OPTS=\"@OCTAVE_LINK_OPTS@\"\nOCT_LINK_DEPS=\"@OCT_LINK_DEPS@\"\nOPENGL_LIBS=\"@OPENGL_LIBS@\"\nPCRE_CPPFLAGS=\"@PCRE_CPPFLAGS@\"\nPCRE_LDFLAGS=\"@PCRE_LDFLAGS@\"\nPCRE_LIBS=\"@PCRE_LIBS@\"\nPTHREAD_CFLAGS=\"@PTHREAD_CFLAGS@\"\nPTHREAD_LIBS=\"@PTHREAD_LIBS@\"\nQHULL_CPPFLAGS=\"@QHULL_CPPFLAGS@\"\nQHULL_LDFLAGS=\"@QHULL_LDFLAGS@\"\nQHULL_LIBS=\"@QHULL_LIBS@\"\nQRUPDATE_CPPFLAGS=\"@QRUPDATE_CPPFLAGS@\"\nQRUPDATE_LDFLAGS=\"@QRUPDATE_LDFLAGS@\"\nQRUPDATE_LIBS=\"@QRUPDATE_LIBS@\"\nQT_CPPFLAGS=\"@QT_CPPFLAGS@\"\nQT_LDFLAGS=\"@QT_LDFLAGS@\"\nQT_LIBS=\"@QT_LIBS@\"\nRANLIB=\"@RANLIB@\"\nRDYNAMIC_FLAG=\"@RDYNAMIC_FLAG@\"\nREADLINE_LIBS=\"@LIBREADLINE@\"\nSHARED_LIBS=\"@SHARED_LIBS@\"\nSH_LDFLAGS=\"@SH_LDFLAGS@\"\nSTATIC_LIBS=\"@STATIC_LIBS@\"\nSUITESPARSECONFIG_LIBS=\"@SUITESPARSECONFIG_LIBS@\"\nSUNDIALS_IDA_CPPFLAGS=\"@SUNDIALS_IDA_CPPFLAGS@\"\nSUNDIALS_IDA_LDFLAGS=\"@SUNDIALS_IDA_LDFLAGS@\"\nSUNDIALS_IDA_LIBS=\"@SUNDIALS_IDA_LIBS@\"\nSUNDIALS_NVECSERIAL_CPPFLAGS=\"@SUNDIALS_NVECSERIAL_CPPFLAGS@\"\nSUNDIALS_NVECSERIAL_LDFLAGS=\"@SUNDIALS_NVECSERIAL_LDFLAGS@\"\nSUNDIALS_NVECSERIAL_LIBS=\"@SUNDIALS_NVECSERIAL_LIBS@\"\nSUNDIALS_SUNLINSOLKLU_CPPFLAGS=\"@SUNDIALS_SUNLINSOLKLU_CPPFLAGS@\"\nSUNDIALS_SUNLINSOLKLU_LDFLAGS=\"@SUNDIALS_SUNLINSOLKLU_LDFLAGS@\"\nSUNDIALS_SUNLINSOLKLU_LIBS=\"@SUNDIALS_SUNLINSOLKLU_LIBS@\"\nUMFPACK_CPPFLAGS=\"@UMFPACK_CPPFLAGS@\"\nUMFPACK_LDFLAGS=\"@UMFPACK_LDFLAGS@\"\nUMFPACK_LIBS=\"@UMFPACK_LIBS@\"\nversion=\"@PACKAGE_VERSION@\"\nWARN_CFLAGS=\"@WARN_CFLAGS@\"\nWARN_CXXFLAGS=\"@WARN_CXXFLAGS@\"\nX11_INCFLAGS=\"@X11_INCFLAGS@\"\nX11_LIBS=\"@X11_LIBS@\"\nXTRA_CFLAGS=\"@XTRA_CFLAGS@\"\nXTRA_CXXFLAGS=\"@XTRA_CXXFLAGS@\"\nYACC=\"@YACC@\"\nYFLAGS=\"@YFLAGS@\"\nZ_CPPFLAGS=\"@Z_CPPFLAGS@\"\nZ_LDFLAGS=\"@Z_LDFLAGS@\"\nZ_LIBS=\"@Z_LIBS@\"\nconfig_opts=\"@config_opts@\"\n\n$SED \\\n  -e \"s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by subst-cross-config-vals.|\" \\\n  -e \"s|%NO_OCT_FILE_STRIP%|${NO_OCT_FILE_STRIP}|\" \\\n  -e \"s|%OCTAVE_API_VERSION%|\\\"${api_version}\\\"|\" \\\n  -e \"s|%OCTAVE_ARCHLIBDIR%|\\\"${archlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_BINDIR%|\\\"${bindir}\\\"|\" \\\n  -e \"s|%OCTAVE_BINDIR%|\\\"${bindir}\\\"|\" \\\n  -e \"s|%OCTAVE_CANONICAL_HOST_TYPE%|\\\"${canonical_host_type}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_AMD_CPPFLAGS%|\\\"${AMD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_AMD_LDFLAGS%|\\\"${AMD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_AMD_LIBS%|\\\"${AMD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_AR%|\\\"${AR}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_ARFLAGS%|\\\"${ARFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_ARPACK_CPPFLAGS%|\\\"${ARPACK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_ARPACK_LDFLAGS%|\\\"${ARPACK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_ARPACK_LIBS%|\\\"${ARPACK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_BLAS_LIBS%|\\\"${BLAS_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CAMD_CPPFLAGS%|\\\"${CAMD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CAMD_LDFLAGS%|\\\"${CAMD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CAMD_LIBS%|\\\"${CAMD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CARBON_LIBS%|\\\"${CARBON_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CC%|\\\"${CC}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CCOLAMD_CPPFLAGS%|\\\"${CCOLAMD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CCOLAMD_LDFLAGS%|\\\"${CCOLAMD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CCOLAMD_LIBS%|\\\"${CCOLAMD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CFLAGS%|\\\"${CFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CHOLMOD_CPPFLAGS%|\\\"${CHOLMOD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CHOLMOD_LDFLAGS%|\\\"${CHOLMOD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CHOLMOD_LIBS%|\\\"${CHOLMOD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_COLAMD_CPPFLAGS%|\\\"${COLAMD_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_COLAMD_LDFLAGS%|\\\"${COLAMD_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_COLAMD_LIBS%|\\\"${COLAMD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CPICFLAG%|\\\"${CPICFLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CPPFLAGS%|\\\"${cppflags}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CURL_CPPFLAGS%|\\\"${CURL_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CURL_LDFLAGS%|\\\"${CURL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CURL_LIBS%|\\\"${CURL_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXSPARSE_CPPFLAGS%|\\\"${CXSPARSE_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXSPARSE_LDFLAGS%|\\\"${CXSPARSE_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXSPARSE_LIBS%|\\\"${CXSPARSE_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXX%|\\\"${CXX}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXXCPP%|\\\"${CXXCPP}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXXFLAGS%|\\\"${CXXFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_CXXPICFLAG%|\\\"${CXXPICFLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DEFAULT_PAGER%|\\\"${DEFAULT_PAGER}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DEFS%|\\\"${DEFS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%|\\\"${DEPEND_EXTRA_SED_PATTERN}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DEPEND_FLAGS%|\\\"${DEPEND_FLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_DL_LDFLAGS%|\\\"${DL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_EXEC_PREFIX%|\\\"${exec_prefix}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_EXEEXT%|\\\"${EXEEXT}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_F77%|\\\"${F77}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_F77_FLOAT_STORE_FLAG%|\\\"${F77_FLOAT_STORE_FLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_F77_INTEGER_8_FLAG%|\\\"${F77_INTEGER_8_FLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFLAGS%|\\\"${FFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3F_CPPFLAGS%|\\\"${FFTW3F_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3F_LDFLAGS%|\\\"${fftw3f_ldflags}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3F_LIBS%|\\\"${FFTW3F_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3_CPPFLAGS%|\\\"${FFTW3_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3_LDFLAGS%|\\\"${fftw3_ldflags}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FFTW3_LIBS%|\\\"${FFTW3_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FLIBS%|\\\"${flibs}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FLTK_CPPFLAGS%|\\\"${FLTK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FLTK_LDFLAGS%|\\\"${FLTK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FLTK_LIBS%|\\\"${FLTK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FONTCONFIG_CPPFLAGS%|\\\"${FONTCONFIG_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FONTCONFIG_LIBS%|\\\"${FONTCONFIG_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FPICFLAG%|\\\"${FPICFLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_FT2_CPPFLAGS%|\\\"${FT2_CPPFLAGS}\\\"|\" | \\\n  $SED \\\n  -e \"s|%OCTAVE_CONF_FT2_LIBS%|\\\"${FT2_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GCC_VERSION%|\\\"${GCC_VERSION}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GLPK_CPPFLAGS%|\\\"${GLPK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GLPK_LDFLAGS%|\\\"${GLPK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GLPK_LIBS%|\\\"${GLPK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GNUPLOT%|\\\"${GNUPLOT}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_GXX_VERSION%|\\\"${GXX_VERSION}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_HDF5_CPPFLAGS%|\\\"${HDF5_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_HDF5_LDFLAGS%|\\\"${HDF5_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_HDF5_LIBS%|\\\"${HDF5_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_INCLUDEDIR%|\\\"${includedir}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_KLU_CPPFLAGS%|\\\"${KLU_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_KLU_LDFLAGS%|\\\"${KLU_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_KLU_LIBS%|\\\"${KLU_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LAPACK_LIBS%|\\\"${LAPACK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LDFLAGS%|\\\"${ldflags}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LD_STATIC_FLAG%|\\\"${LD_STATIC_FLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LEX%|\\\"${LEX}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LEXLIB%|\\\"${LEXLIB}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LFLAGS%|\\\"${LFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LIBDIR%|\\\"${libdir}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LIBOCTAVE%|\\\"${LIBOCTAVE}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LIBOCTINTERP%|\\\"${LIBOCTINTERP}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LIBS%|\\\"${LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_LN_S%|\\\"${LN_S}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MAGICK_CPPFLAGS%|\\\"${MAGICK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MAGICK_LDFLAGS%|\\\"${MAGICK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MAGICK_LIBS%|\\\"${MAGICK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_AR%|\\\"${AR}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_CC%|\\\"${CC}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_CXX%|\\\"${CXX}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%|\\\"${DL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_F77%|\\\"${F77}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_OCTAVE_LINK_DEPS%|\\\"${mkoctfile_octave_link_deps}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_OCT_LINK_DEPS%|\\\"${mkoctfile_oct_link_deps}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_MKOCTFILE_RANLIB%|\\\"${RANLIB}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCTAVE_LINK_DEPS%|\\\"${OCTAVE_LINK_DEPS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCTAVE_LINK_OPTS%|\\\"${OCTAVE_LINK_OPTS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCTINCLUDEDIR%|\\\"${octincludedir}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCTLIBDIR%|\\\"${octlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCT_LINK_DEPS%|\\\"${OCT_LINK_DEPS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OCT_LINK_OPTS%|\\\"${oct_link_opts}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_OPENGL_LIBS%|\\\"${OPENGL_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PCRE_CPPFLAGS%|\\\"${PCRE_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PCRE_LDFLAGS%|\\\"${PCRE_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PCRE_LIBS%|\\\"${PCRE_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PREFIX%|\\\"${prefix}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PTHREAD_CFLAGS%|\\\"${PTHREAD_CFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_PTHREAD_LIBS%|\\\"${PTHREAD_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QHULL_CPPFLAGS%|\\\"${QHULL_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QHULL_LDFLAGS%|\\\"${QHULL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QHULL_LIBS%|\\\"${QHULL_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QRUPDATE_CPPFLAGS%|\\\"${QRUPDATE_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QRUPDATE_LDFLAGS%|\\\"${QRUPDATE_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QRUPDATE_LIBS%|\\\"${QRUPDATE_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QT_CPPFLAGS%|\\\"${QT_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QT_LDFLAGS%|\\\"${QT_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_QT_LIBS%|\\\"${QT_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_RANLIB%|\\\"${RANLIB}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_RDYNAMIC_FLAG%|\\\"${RDYNAMIC_FLAG}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_READLINE_LIBS%|\\\"${READLINE_LIBS}\\\"|\" | \\\n  $SED \\\n  -e \"s|%OCTAVE_CONF_SHARED_LIBS%|\\\"${SHARED_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SH_LDFLAGS%|\\\"${SH_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_STATIC_LIBS%|\\\"${STATIC_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUITESPARSECONFIG_LIBS%|\\\"${SUITESPARSECONFIG_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_IDA_CPPFLAGS%|\\\"${SUNDIALS_IDA_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_IDA_LDFLAGS%|\\\"${SUNDIALS_IDA_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_IDA_LIBS%|\\\"${SUNDIALS_IDA_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_CPPFLAGS%|\\\"${SUNDIALS_NVECSERIAL_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_LDFLAGS%|\\\"${SUNDIALS_NVECSERIAL_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_LIBS%|\\\"${SUNDIALS_NVECSERIAL_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_CPPFLAGS%|\\\"${SUNDIALS_SUNLINSOLKLU_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LDFLAGS%|\\\"${SUNDIALS_SUNLINSOLKLU_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LIBS%|\\\"${SUNDIALS_SUNLINSOLKLU_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_UMFPACK_CPPFLAGS%|\\\"${UMFPACK_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_UMFPACK_LDFLAGS%|\\\"${UMFPACK_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_UMFPACK_LIBS%|\\\"${UMFPACK_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_VERSION%|\\\"${version}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_WARN_CFLAGS%|\\\"${WARN_CFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_WARN_CXXFLAGS%|\\\"${WARN_CXXFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_X11_INCFLAGS%|\\\"${X11_INCFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_X11_LIBS%|\\\"${X11_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_XTRA_CFLAGS%|\\\"${XTRA_CFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_XTRA_CXXFLAGS%|\\\"${XTRA_CXXFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_YACC%|\\\"${YACC}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_YFLAGS%|\\\"${YFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_Z_CPPFLAGS%|\\\"${Z_CPPFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_Z_LDFLAGS%|\\\"${Z_LDFLAGS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_Z_LIBS%|\\\"${Z_LIBS}\\\"|\" \\\n  -e \"s|%OCTAVE_CONF_config_opts%|\\\"${config_opts}\\\"|\" \\\n  -e \"s|%OCTAVE_DATADIR%|\\\"${datadir}\\\"|\" \\\n  -e \"s|%OCTAVE_DATAROOTDIR%|\\\"${datarootdir}\\\"|\" \\\n  -e \"s|%OCTAVE_DEFAULT_PAGER%|\\\"${DEFAULT_PAGER}\\\"|\" \\\n  -e \"s|%OCTAVE_DOCDIR%|\\\"${docdir}\\\"|\" \\\n  -e \"s|%OCTAVE_DOC_CACHE_FILE%|\\\"${doc_cache_file}\\\"|\" \\\n  -e \"s|%OCTAVE_EXEC_PREFIX%|\\\"${exec_prefix}\\\"|\" \\\n  -e \"s|%OCTAVE_EXEEXT%|\\\"${EXEEXT}\\\"|\" \\\n  -e \"s|%OCTAVE_FCNFILEDIR%|\\\"${fcnfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_IMAGEDIR%|\\\"${imagedir}\\\"|\" \\\n  -e \"s|%OCTAVE_INCLUDEDIR%|\\\"${includedir}\\\"|\" \\\n  -e \"s|%OCTAVE_INFODIR%|\\\"${infodir}\\\"|\" \\\n  -e \"s|%OCTAVE_INFOFILE%|\\\"${infofile}\\\"|\" \\\n  -e \"s|%OCTAVE_LIBDIR%|\\\"${libdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LIBEXECDIR%|\\\"${libexecdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALAPIARCHLIBDIR%|\\\"${localapiarchlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALAPIFCNFILEDIR%|\\\"${localapifcnfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALAPIOCTFILEDIR%|\\\"${localapioctfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALAPIPKGDIR%|\\\"${localapipkgdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALARCHLIBDIR%|\\\"${localarchlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALFCNFILEDIR%|\\\"${localfcnfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALOCTFILEDIR%|\\\"${localoctfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALSTARTUPFILEDIR%|\\\"${localstartupfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALVERARCHLIBDIR%|\\\"${localverarchlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALVERFCNFILEDIR%|\\\"${localverfcnfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_LOCALVEROCTFILEDIR%|\\\"${localveroctfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_MAN1DIR%|\\\"${man1dir}\\\"|\" \\\n  -e \"s|%OCTAVE_MAN1EXT%|\\\"${man1ext}\\\"|\" \\\n  -e \"s|%OCTAVE_MANDIR%|\\\"${mandir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTDATADIR%|\\\"${octdatadir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTDOCDIR%|\\\"${octdocdir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTETCDIR%|\\\"${octetcdir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTFILEDIR%|\\\"${octfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTFONTSDIR%|\\\"${octfontsdir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTINCLUDEDIR%|\\\"${octincludedir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTLIBDIR%|\\\"${octlibdir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTLOCALEDIR%|\\\"${octlocaledir}\\\"|\" \\\n  -e \"s|%OCTAVE_OCTTESTSDIR%|\\\"${octtestsdir}\\\"|\" \\\n  -e \"s|%OCTAVE_PREFIX%|\\\"${prefix}\\\"|\" \\\n  -e \"s|%OCTAVE_RELEASE%|\\\"${OCTAVE_RELEASE}\\\"|\" \\\n  -e \"s|%OCTAVE_STARTUPFILEDIR%|\\\"${startupfiledir}\\\"|\" \\\n  -e \"s|%OCTAVE_TEXI_MACROS_FILE%|\\\"${texi_macros_file}\\\"|\" \\\n  -e \"s|%OCTAVE_VERSION%|\\\"${version}\\\"|\"\n"
  },
  {
    "path": "build-aux/subst-script-vals.in.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n: ${SED=@SED@}\n\nAWK=\"@AWK@\"\nFIND=\"@FIND@\"\nSED=\"@SED@\"\nADDRESS_SANITIZER_ENABLED=\"@ADDRESS_SANITIZER_ENABLED@\"\nADDRESS_SANITIZER_OPTIONS=\"@ADDRESS_SANITIZER_OPTIONS@\"\nabs_top_srcdir=\"@abs_top_srcdir@\"\nabs_top_builddir=\"@abs_top_builddir@\"\nhost_os=\"@host_os@\"\n\n$SED \\\n  -e \"s|%AWK%|${AWK}|g\" \\\n  -e \"s|%FIND%|${FIND}|g\" \\\n  -e \"s|%SED%|${SED}|g\" \\\n  -e \"s|%ADDRESS_SANITIZER_ENABLED%|${ADDRESS_SANITIZER_ENABLED}|g\" \\\n  -e \"s|%ADDRESS_SANITIZER_OPTIONS%|${ADDRESS_SANITIZER_OPTIONS}|g\" \\\n  -e \"s|%abs_top_srcdir%|${abs_top_srcdir}|\" \\\n  -e \"s|%builddir%|${abs_top_builddir}|\" \\\n  -e \"s|%host_os%|${host_os}|\"\n"
  },
  {
    "path": "build-aux/update-bug-status.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nbug_numbers=$(for file in \"$@\"; do\n  sed -n \"s/.*<\\([0-9][0-9][0-9][0-9]*\\)>.*/\\1/p\" \"$file\"\ndone | sort -u)\n\nfixed_bug_numbers=$(for num in $bug_numbers; do\n  status=$(wget -q -O - https://octave.org/testfailure/?$num | tr -d '\\n' | sed -n 's/.*>Status:<\\/span><\\/span>&nbsp;<\\/td> *<td valign=\"middle\" width=\"35%\">\\([^<]*\\)<.*/\\1/p');\n  if [ \"$status\" = \"Fixed\" ]; then echo \"$num\"; fi\ndone)\n\nif [ -z \"$fixed_bug_numbers\" ]; then\n  echo \"no change in bug status\"\n  exit 0;\nfi\n\nfixed_bug_pattern=`echo $fixed_bug_numbers | sed 's/ /\\\\\\\\|/g; s/^/<\\\\\\\\(/; s/$/\\\\\\\\)>/'`\n\nfor file in \"$@\"; do\n   sed -i \"s/$fixed_bug_pattern/<*\\1>/\" \"$file\"\ndone\n"
  },
  {
    "path": "configure.ac",
    "content": "dnl Process this file with autoconf to produce a configure script.\ndnl\n########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n### Initialize Autoconf\nAC_PREREQ([2.65])\nAC_INIT([GNU Octave], [12.0.0],\n        [https://bugs.octave.org], [octave], [https://www.octave.org])\nAC_CONFIG_MACRO_DIRS([m4])\nAC_CONFIG_AUX_DIR([build-aux])\n\n### Declare version numbers\n\ndnl Note that the version number is duplicated here and in AC_INIT because\ndnl AC_INIT requires it to be static, not computed from shell variables.\n\n## The description of the Octave version number in the etc/HACKING.md\n## explains how to update these numbers for release and development\n## versions.\n\nOCTAVE_MAJOR_VERSION=12\nOCTAVE_MINOR_VERSION=0\nOCTAVE_PATCH_VERSION=0\n\ndnl PACKAGE_VERSION is set by the AC_INIT VERSION argument.\nOCTAVE_VERSION=\"$PACKAGE_VERSION\"\n\nOCTAVE_COPYRIGHT=\"Copyright (C) 1993-2026 The Octave Project Developers.\"\n\nOCTAVE_RELEASE_DATE=\"2026-02-03\"\n\n## The \"API version\" is used as a way of checking that interfaces in the\n## liboctave and libinterp libraries haven't changed in a backwardly\n## incompatible way when loading .oct files.  A better way to do this is with\n## library versioning, but not all systems support it.\n##\n## NOTE: This macro will be removed in a future version of Octave!\n## If you insist on checking for features using a version number, use the\n## OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, and OCTAVE_PATCH_VERSION\n## macros instead.\ndnl\ndnl FIXME: Since we also set libtool versions for liboctave and libinterp,\ndnl perhaps we should be computing the \"api version\" from those versions numbers\ndnl in some way instead of setting it independently here.\nOCTAVE_API_VERSION=\"api-v61\"\n\nAC_SUBST(OCTAVE_MAJOR_VERSION)\nAC_SUBST(OCTAVE_MINOR_VERSION)\nAC_SUBST(OCTAVE_PATCH_VERSION)\nAC_SUBST(OCTAVE_VERSION)\nAC_SUBST(OCTAVE_COPYRIGHT)\nAC_SUBST(OCTAVE_RELEASE_DATE)\nAC_SUBST(OCTAVE_API_VERSION)\n\ndnl FIXME: We should auto-insert the Mercurial changeset ID into the\ndnl        AC_REVISION field whenever configure.ac is modified.\ndnl AC_REVISION($Revision: 1.603 $)\nAC_CONFIG_SRCDIR([libinterp/octave.cc])\nAC_CONFIG_HEADERS([config.h:config.in.h])\n\n### Initialize Automake\nAM_INIT_AUTOMAKE([1.14 -Wno-portability -Wno-override subdir-objects info-in-builddir tar-ustar dist-lzip dist-xz])\n\n## Add option to enable silent rules and make silent the default behavior.\nAM_SILENT_RULES([yes])\n\nOCTAVE_CANONICAL_HOST\n\nAC_DEFINE(OCTAVE_SOURCE, 1, [Define to 1 if this is Octave.])\n\nAC_USE_SYSTEM_EXTENSIONS\n\n### Make configure args available in variable form for other uses.\n\nconfig_opts=$ac_configure_args\nAC_SUBST(config_opts)\n\n### Set default file locations.\n\n## Where to install libraries like liboctave.a, liboctinterp.a, and other\n## architecture-dependent binaries.\nOCTAVE_SET_DEFAULT([octlibdir], '${libdir}/octave/${version}')\n\n## Where to put executables to be run by Octave, rather than the user.\n## This path usually includes the Octave version and configuration name, so\n## that configurations for multiple versions of Octave may be installed at once.\n## Windows search paths and relocation oddities require all binaries must be\n## installed in the same directory.\ncase $host_os in\n  mingw* | msdosmsvc)\n    OCTAVE_SET_DEFAULT([archlibdir], '${bindir}') ;;\n  *)\n    OCTAVE_SET_DEFAULT([archlibdir],\n      '${libexecdir}/octave/${version}/exec/${canonical_host_type}') ;;\nesac\n\n## Where to put executables to be run by Octave, rather than the user, that\n## are specific to this site.\nOCTAVE_SET_DEFAULT([localarchlibdir],\n  '${libexecdir}/octave/site/exec/${canonical_host_type}')\n\nOCTAVE_SET_DEFAULT([localapiarchlibdir],\n  '${libexecdir}/octave/${api_version}/site/exec/${canonical_host_type}')\n\nOCTAVE_SET_DEFAULT([localverarchlibdir],\n  '${libexecdir}/octave/${version}/site/exec/${canonical_host_type}')\n\n## Where to put object files that will by dynamically loaded.\n## This path includes the Octave version and configuration name, so that\n## configurations for multiple versions of Octave may be installed at once.\nOCTAVE_SET_DEFAULT([octfiledir],\n  '${libdir}/octave/${version}/oct/${canonical_host_type}')\n\n## Directories that Octave should search for object files that will be\n## dynamically loaded and that are specific to this site (i.e., customizations),\n## before consulting ${octfiledir}.  This should be a colon-separated list of\n## directories.\nOCTAVE_SET_DEFAULT([localoctfiledir],\n  '${libdir}/octave/site/oct/${canonical_host_type}')\n\nOCTAVE_SET_DEFAULT([localapioctfiledir],\n  '${libdir}/octave/site/oct/${api_version}/${canonical_host_type}')\n\nOCTAVE_SET_DEFAULT([localveroctfiledir],\n  '${libdir}/octave/${version}/site/oct/${canonical_host_type}')\n\n## Where to install Octave's include files.\nOCTAVE_SET_DEFAULT([octincludedir], '${includedir}/octave-${version}/octave')\n\n## Where to install the function files distributed with Octave.\n## This includes the Octave version, so that the function files for different\n## versions of Octave will be installed in separate directories.\nOCTAVE_SET_DEFAULT([fcnfiledir], '${datadir}/octave/${version}/m')\n\n## Directories that Octave should search for function files specific to this\n## site (i.e., customizations), before consulting ${fcnfiledir}.\n## This should be a colon-separated list of directories.\nOCTAVE_SET_DEFAULT([localfcnfiledir], '${datadir}/octave/site/m')\n\nOCTAVE_SET_DEFAULT([localapifcnfiledir],\n  '${datadir}/octave/site/${api_version}/m')\n\nOCTAVE_SET_DEFAULT([localverfcnfiledir], '${datadir}/octave/${version}/site/m')\n\n## Where to install extra files like NEWS and doc-cache.\nOCTAVE_SET_DEFAULT([octetcdir], '${datadir}/octave/${version}/etc')\n\n## Where to install the language files for the GUI.\nOCTAVE_SET_DEFAULT([octlocaledir], '${datadir}/octave/${version}/locale')\n\n## The full path to the default doc-cache file.\nOCTAVE_SET_DEFAULT([doc_cache_file], '${octetcdir}/doc-cache')\n\n## Where to install test files.\nOCTAVE_SET_DEFAULT([octtestsdir], '${octetcdir}/tests')\n\n## The full path to the default texi macros file.\nOCTAVE_SET_DEFAULT([texi_macros_file], '${octetcdir}/macros.texi')\n\n## Where Octave will search to find image files.\nOCTAVE_SET_DEFAULT([imagedir], '${datadir}/octave/${version}/imagelib')\n\n## Where Octave will search for example data files shipped with distribution.\nOCTAVE_SET_DEFAULT([octdatadir], '${datadir}/octave/${version}/data')\n\n## Where Octave will search for Qt help files shipped with distribution.\nOCTAVE_SET_DEFAULT([octdocdir], '${datadir}/octave/${version}/doc')\n\n## Where Octave will search for fallback font files shipped with distribution.\nOCTAVE_SET_DEFAULT([octfontsdir], '${datadir}/octave/${version}/fonts')\n\n## Where Octave will look for startup files.\nOCTAVE_SET_DEFAULT([startupfiledir], '${fcnfiledir}/startup')\nOCTAVE_SET_DEFAULT([localstartupfiledir], '${localfcnfiledir}/startup')\n\n## Directory where site-wide (global) list of installed packages is kept\nOCTAVE_SET_DEFAULT([localapipkgdir],\n  '${datadir}/octave/site/${api_version}')\n\n## Where Octave will look for man and info files.\nOCTAVE_SET_DEFAULT([man1dir], '${mandir}/man1')\nOCTAVE_SET_DEFAULT([man1ext], '.1')\nOCTAVE_SET_DEFAULT([infofile], '${infodir}/octave.info')\n\n### Check for programs used in building, installing, and running Octave.\n\n## Programs used in configuring Octave.\ndnl Find pkg-config executable (sets $PKG_CONFIG)\nPKG_PROG_PKG_CONFIG\n## And where we will install our own .pc files.\nPKG_INSTALLDIR\nAC_SUBST([liboctave_pkgconfigdir], [$pkgconfigdir])\nAC_SUBST([libinterp_pkgconfigdir], [$pkgconfigdir])\nAC_SUBST([libmex_pkgconfigdir], [$pkgconfigdir])\n\n## Programs used in Makefiles.\nAC_PROG_AWK\nAC_PROG_GREP\nAC_PROG_EGREP\nOCTAVE_PROG_FIND\nOCTAVE_PROG_SED\nOCTAVE_PROG_PERL\n\n## Programs used to build parts of Octave.\nOCTAVE_PROG_GPERF\n\nOCTAVE_PROG_FLEX\nAC_SUBST([LEX_OUTPUT_ROOT], [lex.octave_])\n\nOCTAVE_PROG_BISON\n\nOCTAVE_PROG_MAKEINFO\nOCTAVE_PROG_TEXI2DVI\nOCTAVE_PROG_TEXI2PDF\n\nOCTAVE_PROG_TAR_REPRODUCIBLE\n\n## Programs used when installing Octave.\nAC_PROG_LN_S\nAC_PROG_MKDIR_P\n\nAC_PROG_INSTALL\nINSTALL_SCRIPT=\"${INSTALL}\"\nAC_SUBST(INSTALL_SCRIPT)\n\n## Programs used when running Octave.\nOCTAVE_PROG_GHOSTSCRIPT\nOCTAVE_PROG_GNUPLOT\nOCTAVE_PROG_PAGER\nOCTAVE_PROG_PYTHON\n\n## Programs used to generate icons file formats.\nOCTAVE_PROG_ICOTOOL\nOCTAVE_PROG_RSVG_CONVERT\nAM_CONDITIONAL([AMCOND_HAVE_ICON_TOOLS],\n  [test -n \"$ICOTOOL\" && test -n \"$RSVG_CONVERT\"])\n\n### Determine path separator.\n\nsepchar=':'\nAC_ARG_WITH([sepchar],\n  [AS_HELP_STRING([--with-sepchar=<char>],\n    [use <char> as the path separation character])])\ncase $with_sepchar in\n  yes | \"\")\n    case $host_os in\n      mingw* | msdosmsvc)\n        sepchar=';' ;;\n    esac\n  ;;\n  no)\n    AC_MSG_ERROR([You are required to define a path separation character])\n    ;;\n  *)\n    sepchar=$with_sepchar\n  ;;\nesac\nAC_SUBST(sepchar)\nAC_DEFINE_UNQUOTED(SEPCHAR, ['$sepchar'],\n  [Define this to be the path separator for your system, as a character constant.])\nAC_DEFINE_UNQUOTED(SEPCHAR_STR, [\"$sepchar\"],\n  [Define this to be the path separator for your system, as a string.])\n\n### Define the path to the shell on the host system.\ndnl Most systems will ensure /bin/sh is the default shell so this can be safely\ndnl ignored by almost everyone.  However, there are exceptions, such as\ndnl Android, where this will need to be set.\nSHELL_PATH=/bin/sh\nAC_ARG_WITH([shell],\n  [AS_HELP_STRING([--with-shell=SHELL],\n    [use SHELL as the shell interpreter (default: /bin/sh)])])\ncase $with_shell in\n  no)\n    AC_MSG_ERROR([A shell interpreter is required])\n  ;;\n  yes | \"\")\n  ;;\n  *)\n    SHELL_PATH=$with_shell\n  ;;\nesac\nAC_DEFINE_UNQUOTED([SHELL_PATH], [\"$SHELL_PATH\"],\n  [Define this to be the path to the shell command interpreter.])\n\n### Determine which C++ compiler to use (we expect to find g++ or clang++).\n\n# AC_PROG_CXX attempts to find the compiler flags for activating support for\n# C++11.  As of autoconf version 2.71, the source code that it uses for that\n# test includes parts that are invalid in C++20.\n# We are using AX_CXX_COMPILE_STDCXX to determine the potentially needed flags\n# for the C++ version that Octave requires.  So, skip the (unnecessary and\n# broken) test for C++11 in AC_PROG_CXX by setting the following (undocumented)\n# flag:\nac_cv_prog_cxx_cxx11=\"\"\nAC_PROG_CXX\nAC_PROG_CXXCPP\n\n## Ensure that the C++ compiler fully supports C++17.\n## Preferably with GNU extensions if flags are required.\nAX_CXX_COMPILE_STDCXX(17, [], mandatory)\n\nENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR=yes\nAC_ARG_ENABLE(std-pmr-polymorphic-allocator,\n  [AS_HELP_STRING([--disable-std-pmr-polymorphic-allocator],\n                  [build libraries without support for std::pmr::polymorphic_allocator, less efficient transfer of arrays to external MEX files])],\n  [case $enableval in\n     yes) ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR=yes ;;\n     no) ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR=no ;;\n     *) AC_MSG_ERROR([bad value $enableval for --enable-std-pmr-polymorphic-allocator]) ;;\n   esac])\n\nAC_ARG_WITH([qt],\n  [AS_HELP_STRING([--with-qt=VER], [use the Qt major version VER])\ndnl Second help string must not be indented for correct alignment\nAS_HELP_STRING([--without-qt], [don't use Qt libraries, disable Qt GUI])],\n  [case $withval in\n     yes | \"\")\n     ;;\n     no)\n       QT_VERSIONS=\n     ;;\n     *)\n       QT_VERSIONS=\"$withval\"\n     ;;\n   esac])\n\n### Determine C++ compiler capabilities.\n\nif test $ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR = yes; then\n  OCTAVE_CHECK_STD_PMR_POLYMORPHIC_ALLOCATOR\nelse\n  HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR=\"no\"\nfi\n\n### Determine which C compiler to use (we expect to find gcc or clang).\n\nAC_PROG_CC\nAC_PROG_CPP\n\n## Save and restore CFLAGS and CXXFLAGS globally.\ndnl These variables are for users, so we shouldn't be touching them.\ndnl Instead, we should set the corresponding AM_ flags (currently by way of the\ndnl XTRA_ variables).  However, for the duration of the configure script, we\ndnl may set CFLAGS and CXXFLAGS so that subsequent tests succeed.  Temporary\ndnl settings like this are currently done for pthreads and openmp, for example.\noriginal_octave_configure_CFLAGS=\"$CFLAGS\"\noriginal_octave_configure_CXXFLAGS=\"$CXXFLAGS\"\n\n## Check for MSVC\nhave_msvc=no\ncase $host_os in\n  msdosmsvc)\n    have_msvc=yes\n  ;;\n  mingw*)\n    AC_MSG_CHECKING([for MSVC compiler])\n    AC_PREPROC_IFELSE([AC_LANG_SOURCE([[\n        #if ! defined (_MSC_VER)\n        #error \"Not MSVC compiler\"\n        #endif\n        ]])],\n      have_msvc=yes, have_msvc=no)\n    AC_MSG_RESULT([$have_msvc])\n  ;;\nesac\n\n### gnulib initialization: part 1\ndnl Must take place immediately after a compiler is determined\n\ngl_EARLY\n\n### Record version number when using g++.\n\nGXX_VERSION=\nif test \"$GXX\" = yes; then\n  AC_CACHE_CHECK([g++ compiler version number],\n    [octave_cv_gxx_version],\n    [octave_cv_gxx_version=[`$CXX -v 2>&1 | $GREP \"^.*g.. version\" | $SED -e 's/^.*g.. version *//' -e 's/cygnus-//' -e 's/egcs-//' -e 's/ .*//'`]\n  ])\n\n  GXX_VERSION=$octave_cv_gxx_version\nfi\nAC_SUBST(GXX_VERSION)\n\n### Record version number when using gcc.\ndnl It might be different from the g++ version number.\n\nGCC_VERSION=\nif test \"$GCC\" = yes; then\n  AC_CACHE_CHECK([gcc compiler version number],\n    [octave_cv_gcc_version],\n    [octave_cv_gcc_version=[`$CC -v 2>&1 | $GREP \"^.*gcc version\" | $SED -e 's/^.*g.. version *//' -e 's/cygnus-//' -e 's/egcs-//' -e 's/ .*//'`]\n  ])\n\n  GCC_VERSION=$octave_cv_gcc_version\nfi\nAC_SUBST(GCC_VERSION)\n\n## It seems that there are some broken inline assembly functions in GNU libc.\n## Since it is uncertain how to test whether Octave is linked against GNU libc,\n## just disable them for all platforms.\n\nAC_MSG_NOTICE([defining __NO_MATH_INLINES avoids buggy GNU libc exp function])\nAC_DEFINE(__NO_MATH_INLINES, 1,\n  [Define to 1 if your version of GNU libc has buggy inline assembly code for math functions like exp.])\n\n### Determine the compiler flag necessary to create dependencies.\n\n## Assume GCC.\nINCLUDE_DEPS=yes\nDEPEND_FLAGS=\"-M\"\nDEPEND_EXTRA_SED_PATTERN=\"\"\nif test \"$GCC\" != yes; then\n  case $canonical_host_type in\n    sparc-sun-solaris2* | i386-pc-solaris2*)\n      DEPEND_FLAGS=\"-xM1\"\n      DEPEND_EXTRA_SED_PATTERN=\"-e '/\\/opt\\/SUNWspro/d'\"\n    ;;\n    *-*-msdosmsvc)\n    ;;\n    *-*-mingw*)\n      if test $have_msvc = no; then\n        INCLUDE_DEPS=no\n      fi\n    ;;\n    *)\n      INCLUDE_DEPS=no\n    ;;\n  esac\nfi\nAC_SUBST(INCLUDE_DEPS)\nAC_SUBST(DEPEND_FLAGS)\nAC_SUBST(DEPEND_EXTRA_SED_PATTERN)\n\n### Check for math library.\ndnl If found, this will add -lm to LIBS.\n\ndnl Keep this check before the check for the Fortran compiler,\ndnl in case -lm is needed to compile Fortran programs.\nAC_CHECK_LIB(m, sin)\n\n### Determine the Fortran compiler and how to invoke it.\n\n## Prefer gfortran, but the user's F77 environment variable will override.\nAC_PROG_F77([gfortran])\nif test -z \"$F77\"; then\n  ## No gfortran found, search for any other installed compiler.\n  AC_PROG_F77\nfi\nif test \"$F77\" = g77; then\n  AC_MSG_ERROR([g77 is not a supported Fortran compiler.  Select another compiler by setting the environment variable F77 and re-running configure.])\nfi\n\nAC_MSG_CHECKING([whether a usable Fortran compiler was found])\nif test -n \"$F77\"; then\n  AC_MSG_RESULT(yes)\nelse\n  AC_MSG_RESULT(no)\n  AC_MSG_ERROR([a Fortran compiler is required to build Octave])\nfi\n\nAC_F77_LIBRARY_LDFLAGS\nAC_F77_DUMMY_MAIN\nAC_F77_WRAPPERS\n\n## Must appear after checks for Fortran compiler.\nOCTAVE_CHECK_FORTRAN_SYMBOL_AND_CALLING_CONVENTIONS\n\n## Must appear after checks for all compilers.\nOCTAVE_DEFINE_MKOCTFILE_DYNAMIC_LINK_OPTIONS\n\n### Use a 64-bit integer type for array dimensions and indexing, if possible.\n\nAC_CHECK_SIZEOF([int])\nAC_DEFINE_UNQUOTED(OCTAVE_SIZEOF_INT, [$ac_cv_sizeof_int],\n  [Define to the size of int.])\n\nAC_CHECK_SIZEOF([void *])\nif test $ac_cv_sizeof_void_p -ge 8; then\n  ENABLE_64=yes\nelse\n  ENABLE_64=no\nfi\n\nAC_ARG_ENABLE(64,\n  [AS_HELP_STRING([--disable-64],\n    [don't use 64-bit integers for array dimensions and indexing])],\n  [case $enableval in\n     yes) ENABLE_64=yes ;;\n     no) ENABLE_64=no ;;\n     *) AC_MSG_ERROR([bad value $enableval for --enable-64]) ;;\n   esac])\n\nif test $ENABLE_64 = yes; then\n  if test $ac_cv_sizeof_void_p -ge 8; then\n    OCTAVE_IDX_TYPE=int64_t\n  else\n    warn_64_bit=\"--enable-64 option given but pointers are less than 64-bits wide; disabling 64-bit indexing\"\n    OCTAVE_CONFIGURE_WARNING([warn_64_bit])\n    OCTAVE_IDX_TYPE=int32_t\n    ENABLE_64=no\n  fi\nelse\n  OCTAVE_IDX_TYPE=int32_t\nfi\n\nAC_SUBST(ENABLE_64)\nif test $ENABLE_64 = yes; then\n  octave_sizeof_octave_idx_type=8\n  AC_DEFINE(OCTAVE_ENABLE_64, 1,\n    [Define to 1 to use 64-bit integers for array dimensions and indexing.])\nelse\n  octave_sizeof_octave_idx_type=4\nfi\n\nAC_DEFINE_UNQUOTED(OCTAVE_SIZEOF_IDX_TYPE, [$octave_sizeof_octave_idx_type],\n  [Define to the size of the octave_idx_type (8 or 4).])\n\nAC_SUBST(OCTAVE_IDX_TYPE)\nAC_DEFINE_UNQUOTED(OCTAVE_IDX_TYPE, [$OCTAVE_IDX_TYPE],\n  [Define to the type of octave_idx_type (64 or 32 bit signed integer).])\n\n### Check for LLVM or Apple libc++ library.\n\nOCTAVE_LLVM_LIBCXX\n\n### Check for BSD or Apple libc library.\n\nOCTAVE_BSD_LIBC\n\n### Check for pthread library.\n\nAX_PTHREAD\ndnl Include pthread libs and flags early in case other config tests need them.\ndnl They seem to be required for the OpenGL tests on Debian systems.\nLIBS=\"$PTHREAD_LIBS $LIBS\"\nXTRA_CFLAGS=\"$XTRA_CFLAGS $PTHREAD_CFLAGS\"\nXTRA_CXXFLAGS=\"$XTRA_CXXFLAGS $PTHREAD_CFLAGS\"\ndnl Set these for any other tests that may require them.\ndnl They will be reset before output files are generated.\nCFLAGS=\"$CFLAGS $PTHREAD_CFLAGS\"\nCXXFLAGS=\"$CXXFLAGS $PTHREAD_CFLAGS\"\n\ndnl Clang compiler will produce bogus warning during linking only.\nAM_CONDITIONAL([AMCOND_CLANG_PTHREAD_WARNING],\n               [test $ax_cv_PTHREAD_CLANG = yes])\n\ndnl Check if glibc uses wrong stack size\nOCTAVE_CHECK_BROKEN_PTHREAD_STACKSIZE\nAM_CONDITIONAL([OCTAVE_CHECK_BROKEN_PTHREAD_STACKSIZE],\n  [test $octave_cv_broken_pthread_stacksize = yes])\n\n### Test whether the compiler supports OpenMP.\ndnl This is enabled by default to allow the option of using OpenMP in\ndnl loadable modules.\n\nENABLE_OPENMP=no\ncheck_for_openmp=yes\nAC_ARG_ENABLE([openmp],\n  [AS_HELP_STRING([--disable-openmp],\n    [disable OpenMP SMP multi-threading])],\n  [if test \"$enableval\" = no; then check_for_openmp=no; fi], [])\nif test $check_for_openmp = yes; then\n  AC_LANG_PUSH(C)\n  AX_OPENMP([XTRA_CFLAGS=\"$XTRA_CFLAGS $OPENMP_CFLAGS\"; ENABLE_OPENMP=yes], [])\n  AC_LANG_POP(C)\n  AC_LANG_PUSH(C++)\n  AX_OPENMP([XTRA_CXXFLAGS=\"$XTRA_CXXFLAGS $OPENMP_CXXFLAGS\"; ENABLE_OPENMP=yes], [])\n  AC_LANG_POP(C++)\nfi\n\ndnl Set these for any other tests that may require them.\ndnl They will be reset before output files are generated.\nCFLAGS=\"$CFLAGS $OPENMP_CFLAGS\"\nCXXFLAGS=\"$CXXFLAGS $OPENMP_CXXFLAGS\"\n\ndnl Define here since it is skipped if the first argument to AX_OPENMP\ndnl is not empty.\nif test $ENABLE_OPENMP = yes; then\n  AC_CHECK_HEADERS([omp.h])\n  AC_CHECK_FUNCS([omp_get_num_threads])\n  AC_DEFINE(OCTAVE_ENABLE_OPENMP, 1, [Define to 1 if OpenMP is enabled])\nfi\n\n### Start determination of shared vs. static libraries.\n\n## Use -static if compiling on Alpha OSF/1 1.3 systems.\ncase $canonical_host_type in\n  alpha*-dec-osf1.3)\n    LD_STATIC_FLAG=-static\n  ;;\nesac\nif test -n \"$LD_STATIC_FLAG\"; then\n  AC_MSG_NOTICE([defining LD_STATIC_FLAG to be $LD_STATIC_FLAG])\nfi\nAC_SUBST(LD_STATIC_FLAG)\n\n## Check for programs necessary for shared libraries (ar, libtool)\nOCTAVE_PROG_AR\n\nifdef([LT_INIT], [], [\n  errprint([error: you must have libtool 2.2.2 or a more recent version\n])\n  m4exit([1])])\n\nLT_PREREQ([2.2.2])\nLT_INIT([disable-static dlopen win32-dll])\n\nif test $enable_shared = yes; then\n  SHARED_LIBS=yes\nelse\n  SHARED_LIBS=no\n  # Note: Octave doesn't build currently without shared libraries.  And it\n  #       might not work or make sense at all to build static Octave libraries.\n  #       All existing logic for this use-case is still in place in case\n  #       someone would like to base on that to build static versions of the\n  #       libraries.\n  AC_MSG_ERROR([Building shared libraries is required!])\nfi\nAC_SUBST(SHARED_LIBS)\n\nif test $enable_static = yes; then\n  STATIC_LIBS=yes\nelse\n  STATIC_LIBS=no\nfi\nAC_SUBST(STATIC_LIBS)\n\nXTRA_EXTERNAL_SH_LDFLAGS=\ncase $host_os in\n  msdosmsvc | mingw* | cygwin*)\n    FLIBS=\"$FLIBS -lkernel32\"\n    XTRA_EXTERNAL_SH_LDFLAGS=\"-Wl,liboctave/external/external.def\"\n  ;;\nesac\nAC_SUBST(XTRA_EXTERNAL_SH_LDFLAGS)\n\nif test $STATIC_LIBS = no && test $SHARED_LIBS = no; then\n  AC_MSG_ERROR([You can't disable building both static AND shared libraries!])\nfi\n\n### More configure argument checking related to linking\n\ncase $host_os in\n  msdosmsvc | mingw* | cygwin* | AIX | BeOS | OS/2 )\n    DEFAULT_NO_UNDEFINED_LDFLAG=\"-no-undefined\"\n  ;;\n  *)\n    DEFAULT_NO_UNDEFINED_LDFLAG=\"\"\n  ;;\nesac\nAC_ARG_ENABLE([no-undefined],\n  [AS_HELP_STRING([--enable-no-undefined],\n    [pass -no-undefined to libtool when linking Octave and its shared libraries.  This is done by default for msdosmsvc, mingw*, cygwin*, AIX, BeOS, or OS/2 hosts.])],\n  [case $enableval in\n     yes) NO_UNDEFINED_LDFLAG=\"-no-undefined\" ;;\n     no)  NO_UNDEFINED_LDFLAG=\"\" ;;\n     *) AC_MSG_ERROR([bad value $enableval for --enable-no-undefined]) ;;\n   esac],\n  [NO_UNDEFINED_LDFLAG=\"$DEFAULT_NO_UNDEFINED_LDFLAG\"])\nAC_SUBST(NO_UNDEFINED_LDFLAG)\n\ncase $host_os in\n  cygwin* )\n    DEFAULT_LINK_ALL_DEPS=\"yes\"\n  ;;\n  *)\n    DEFAULT_LINK_ALL_DEPS=\"no\"\n  ;;\nesac\nAC_ARG_ENABLE([link-all-dependencies],\n  [AS_HELP_STRING([--enable-link-all-dependencies],\n    [link Octave and its shared libraries with all dependencies, not just those immediately referenced (should not be needed on most systems).  This is done by default for cygwin* hosts.])],\n  [case $enableval in\n     yes) link_all_deps=yes ;;\n     no)  link_all_deps=no ;;\n     *) AC_MSG_ERROR([bad value $enableval for --enable-link-all-dependencies])\n     ;;\n   esac],\n  [link_all_deps=\"$DEFAULT_LINK_ALL_DEPS\"])\nAM_CONDITIONAL([AMCOND_LINK_ALL_DEPS], [test $link_all_deps = yes])\n\nAC_ARG_VAR([OCTAVE_CLI_LTLDFLAGS],\n  [additional flags when linking octave-cli with libtool])\n\nAC_ARG_VAR([OCTAVE_GUI_LTLDFLAGS],\n  [additional flags when linking octave-gui with libtool])\n\n### Check for BLAS and LAPACK libraries.\n\n## Need to adjust FFLAGS to include correct integer size.\nsave_FFLAGS=\"$FFLAGS\"\nFFLAGS=\"$FFLAGS $F77_INTEGER_8_FLAG\"\n\nOCTAVE_BLAS\nAX_LAPACK\n\n## Restore FFLAGS.\nFFLAGS=\"$save_FFLAGS\"\n\n## If necessary, try again with -ff2c in FFLAGS\nif test $ax_blas_ok = no; then\n  save_FFLAGS=\"$FFLAGS\"\n  FFLAGS=\"-ff2c $FFLAGS $F77_INTEGER_8_FLAG\"\n\n  OCTAVE_BLAS\n  AX_LAPACK\n\n  ## Restore FFLAGS, with -ff2c if that was helpful\n  if test $ax_blas_ok = yes; then\n    FFLAGS=\"-ff2c $save_FFLAGS\"\n  else\n    FFLAGS=\"$save_FFLAGS\"\n  fi\nfi\n\n## On OSX, try again with a wrapper library (without -ff2c!)\nif test $ax_blas_ok = no; then\n  case $host_os in\n    darwin*)\n      ## test if wrapper functions help\n      octave_blaswrap_save_CFLAGS=\"$CFLAGS\"\n      CFLAGS=\"$CFLAGS -DUSE_BLASWRAP\"\n      AC_LANG_PUSH(C)\n      AC_COMPILE_IFELSE([AC_LANG_SOURCE([[\n          #include \"liboctave/util/blaswrap.c\"\n        ]])],\n        [mv conftest.$ac_objext blaswrap.$ac_objext\n         octave_blaswrap_save_BLAS_LIBS=\"$BLAS_LIBS\"\n         BLAS_LIBS=\"blaswrap.$ac_objext -framework vecLib\"\n\n         save_FFLAGS=\"$FFLAGS\"\n         FFLAGS=\"$FFLAGS $F77_INTEGER_8_FLAG\"\n\n         OCTAVE_BLAS\n         AX_LAPACK\n\n         ## Restore FFLAGS.\n         FFLAGS=\"$save_FFLAGS\"\n\n         dnl remove temp file\n         rm -f blaswrap.$ac_objext],\n        [AC_MSG_FAILURE([cannot compile liboctave/util/blaswrap.c])])\n      AC_LANG_POP(C)\n      CFLAGS=\"$octave_blaswrap_save_CFLAGS\"\n\n      if test $ax_blas_ok = no; then\n        BLAS_LIBS=\"$octave_blaswrap_save_BLAS_LIBS\"\n      else\n        ## wrapper in liboctave/util, remove from BLAS_LIBS\n        BLAS_LIBS=`echo $BLAS_LIBS | $SED -e 's/blaswrap.[[^ ]]* //g'`\n        AC_DEFINE(USE_BLASWRAP, 1,\n          [Define to 1 if BLAS functions need to be wrapped (potentially needed for 64-bit OSX only).])\n      fi\n    ;;\n  esac\nfi\n\nif test $ax_blas_ok = no || test $ax_lapack_ok = no; then\n  AC_MSG_ERROR([BLAS and LAPACK libraries are required])\nfi\n\ncase $ax_cv_blas_integer_size in\n  4)\n    HAVE_64_BIT_BLAS=no\n  ;;\n  8)\n    HAVE_64_BIT_BLAS=yes\n  ;;\n  *)\n    AC_MSG_ERROR([unrecognized BLAS library integer size])\n  ;;\nesac\n\nOCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER\nif test $octave_cv_sizeof_fortran_integer -ne $ax_cv_blas_integer_size; then\n  if test $ax_cv_blas_integer_size -eq 8; then\n    case $F77 in\n      *gfortran*)\n        case $F77_INTEGER_8_FLAG in\n          *-fdefault-integer-8*)\n          ;;\n          *)\n            case $FFLAGS in\n              *-fdefault-integer-8*)\n                AC_MSG_NOTICE([setting -fdefault-integer-8 in F77_INTEGER_8_FLAG instead of FFLAGS])\n                FFLAGS=`echo $FFLAGS | $SED 's/-fdefault-integer-8//g'`\n                F77_INTEGER_8_FLAG=\"-fdefault-integer-8\"\n              ;;\n              *)\n                AC_MSG_NOTICE([adding -fdefault-integer-8 to F77_INTEGER_8_FLAG])\n                F77_INTEGER_8_FLAG=\"-fdefault-integer-8\"\n                ## Invalidate the cache and try again.\n                $as_unset octave_cv_sizeof_fortran_integer\n              ;;\n            esac\n          ;;\n        esac\n      ;;\n    esac\n    if test -z \"$octave_cv_sizeof_fortran_integer\"; then\n      OCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER\n    fi\n  fi\n  ## We intentionally don't attempt to fix things up if the default\n  ## Fortran integer size is 8 but BLAS appears to use 4-byte integers.\n  if test $octave_cv_sizeof_fortran_integer -ne $ax_cv_blas_integer_size; then\n    AC_MSG_ERROR([your Fortran compiler must have an option for setting the default integer size to be the same size as your BLAS library uses ($ax_cv_blas_integer_size bytes).  See the file INSTALL for more information.])\n  fi\nfi\nAC_SUBST(F77_INTEGER_8_FLAG)\n\ncase $octave_cv_sizeof_fortran_integer in\n  8)\n    OCTAVE_F77_INT_TYPE=int64_t\n  ;;\n  4)\n    OCTAVE_F77_INT_TYPE=int32_t\n  ;;\nesac\nAC_SUBST(OCTAVE_F77_INT_TYPE)\nAC_DEFINE_UNQUOTED(OCTAVE_F77_INT_TYPE, [$OCTAVE_F77_INT_TYPE],\n  [Define to the type of octave_f77_int_type (64 or 32 bit signed integer).])\nAC_DEFINE_UNQUOTED(OCTAVE_SIZEOF_F77_INT_TYPE,\n  [$octave_cv_sizeof_fortran_integer],\n  [Define to the size of the octave_f77_int_type (8 or 4).])\n\nOCTAVE_F77_FLAG([-ffloat-store], [\n  AC_MSG_RESULT([setting F77_FLOAT_STORE_FLAG to -ffloat-store])\n  F77_FLOAT_STORE_FLAG=-ffloat-store\n  AC_SUBST(F77_FLOAT_STORE_FLAG)\n])\n\nif test $ac_cv_f77_compiler_gnu = yes; then\n  OCTAVE_F77_FLAG([-std=legacy])\nfi\n\nBUILD_EXTERNAL_LIBXERBLA=\ncase $host_os in\n  msdosmsvc | mingw*)\n    BUILD_EXTERNAL_LIBXERBLA=yes\n  ;;\nesac\n\nAM_CONDITIONAL([AMCOND_BUILD_EXTERNAL_LIBXERBLA],\n  [test -n \"$BUILD_EXTERNAL_LIBXERBLA\"])\n\n### Set options for dynamic linking if enabled.\ndnl Options set only if we are building shared libs and some API for\ndnl dynamic linking has been detected.\n\ndnl FIXME: A lot of the following duplicates the functionality of\ndnl code generated by the dlopen option for LT_INIT.\n\nRDYNAMIC_FLAG=\nDL_API_MSG=\"\"\ndlopen_api=no\nloadlibrary_api=no\n\ncase $lt_cv_dlopen in\n  dlopen)\n    dlopen_api=yes\n    DL_API_MSG=\"dlopen\"\n    AC_DEFINE(HAVE_DLOPEN_API, 1,\n      [Define to 1 if system has dlopen, dlsym, dlerror, and dlclose for dynamic linking.])\n    OCTAVE_CXX_FLAG([-rdynamic], [RDYNAMIC_FLAG=-rdynamic])\n  ;;\n  LoadLibrary)\n    loadlibrary_api=yes\n    DL_API_MSG=\"LoadLibrary\"\n    AC_DEFINE(HAVE_LOADLIBRARY_API, 1,\n      [Define to 1 if system has LoadLibrary for dynamic linking.])\n  ;;\n  *)\n    AC_MSG_ERROR([Octave requires some way to perform dynamic linking.])\n  ;;\nesac\n\nDL_LIBS=\"$lt_cv_dlopen_libs\"\n\nif test $SHARED_LIBS = yes; then\n  LIBOCTINTERP=\"-loctinterp\"\n  LIBOCTAVE=\"-loctave\"\n  LIBOCTMEX=\"-loctmex\"\nelse\n  LIBOCTINTERP=\"${top_builddir}/libinterp/liboctinterp.a\"\n  LIBOCTAVE=\"${top_builddir}/liboctave/liboctave.a\"\n  LIBOCTMEX=\"${top_builddir}/liboctave/liboctmex.a\"\nfi\n\nAC_SUBST(RDYNAMIC_FLAG)\nAC_SUBST(LIBOCTINTERP)\nAC_SUBST(LIBOCTAVE)\nAC_SUBST(LIBOCTMEX)\n\nif test \"$cross_compiling\" = yes && test -n \"$ac_tool_prefix\"; then\n  CROSS_TOOL_PREFIX=\"$ac_tool_prefix\"\n  MKOCTFILE_AR=`echo \"$AR\" | $SED \"s,$CROSS_TOOL_PREFIX,,\"`\n  MKOCTFILE_CC=`echo \"$CC\" | $SED \"s,$CROSS_TOOL_PREFIX,,\"`\n  MKOCTFILE_CXX=`echo \"$CXX\" | $SED \"s,$CROSS_TOOL_PREFIX,,\"`\n  MKOCTFILE_F77=`echo \"$F77\" | $SED \"s,$CROSS_TOOL_PREFIX,,\"`\n  MKOCTFILE_RANLIB=`echo \"$RANLIB\" | $SED \"s,$CROSS_TOOL_PREFIX,,\"`\nelse\n  MKOCTFILE_AR=\"$AR\"\n  MKOCTFILE_CC=\"$CC\"\n  MKOCTFILE_CXX=\"$CXX\"\n  MKOCTFILE_F77=\"$F77\"\n  MKOCTFILE_RANLIB=\"$RANLIB\"\nfi\nAC_MSG_NOTICE([defining CROSS_TOOL_PREFIX to be $CROSS_TOOL_PREFIX])\nAC_MSG_NOTICE([defining MKOCTFILE_AR to be $MKOCTFILE_AR])\nAC_MSG_NOTICE([defining MKOCTFILE_CC to be $MKOCTFILE_CC])\nAC_MSG_NOTICE([defining MKOCTFILE_CXX to be $MKOCTFILE_CXX])\nAC_MSG_NOTICE([defining MKOCTFILE_F77 to be $MKOCTFILE_F77])\nAC_MSG_NOTICE([defining MKOCTFILE_RANLIB to be $MKOCTFILE_RANLIB])\nAC_SUBST(CROSS_TOOL_PREFIX)\nAC_SUBST(MKOCTFILE_AR)\nAC_SUBST(MKOCTFILE_CC)\nAC_SUBST(MKOCTFILE_CXX)\nAC_SUBST(MKOCTFILE_F77)\nAC_SUBST(MKOCTFILE_RANLIB)\n\n### Enable internal checks\n\n## The checks slow down the execution and are redundant,\n## but useful for debugging or verifying GNU Octave.\nENABLE_INTERNAL_CHECKS=no\nAC_ARG_ENABLE([internal-checks],\n  [AS_HELP_STRING([--enable-internal-checks],\n    [Enable internal checks that are redundant but useful to debug or verify GNU Octave])],\n  [if test \"$enableval\" = yes; then ENABLE_INTERNAL_CHECKS=yes; fi], [])\nif test $ENABLE_INTERNAL_CHECKS = yes; then\n  AC_DEFINE(OCTAVE_ENABLE_INTERNAL_CHECKS, 1,\n    [Define to 1 to enable internal checks.])\nfi\n\n### Determine extra CFLAGS, CXXFLAGS that may be necessary for Octave.\n\n## On Intel systems with gcc, we need to compile with -mieee-fp to get full\n## support for IEEE floating point.\n##\n## On Alpha/OSF systems, we require -mieee or -ieee for full support.\n\nieee_fp_flag=\ncase $canonical_host_type in\n  i[[3456789]]86-*-*)\n    if test \"$GCC\" = yes; then\n      OCTAVE_CC_FLAG([-mieee-fp], [\n        ieee_fp_flag=-mieee-fp\n        XTRA_CFLAGS=\"$XTRA_CFLAGS -mieee-fp\"\n        AC_MSG_NOTICE([adding -mieee-fp to XTRA_CFLAGS])])\n    fi\n    if test \"$GXX\" = yes; then\n      OCTAVE_CXX_FLAG([-mieee-fp], [\n        ieee_fp_flag=-mieee-fp\n        XTRA_CXXFLAGS=\"$XTRA_CXXFLAGS -mieee-fp\"\n        AC_MSG_NOTICE([adding -mieee-fp to XTRA_CXXFLAGS])])\n    fi\n  ;;\n  alpha*-*-*)\n    if test \"$GCC\" = yes; then\n      OCTAVE_CC_FLAG([-mieee], [\n        ieee_fp_flag=-mieee\n        XTRA_CFLAGS=\"$XTRA_CFLAGS -mieee\"\n        AC_MSG_NOTICE([adding -mieee to XTRA_CFLAGS])])\n    else\n      OCTAVE_CC_FLAG([-ieee], [\n        ieee_fp_flag=-ieee\n        XTRA_CFLAGS=\"$XTRA_CFLAGS -ieee\"\n        AC_MSG_NOTICE([adding -ieee to XTRA_CFLAGS])])\n    fi\n    if test \"$GXX\" = yes; then\n      OCTAVE_CXX_FLAG([-mieee], [\n        ieee_fp_flag=-mieee\n        XTRA_CXXFLAGS=\"$XTRA_CXXFLAGS -mieee\"\n        AC_MSG_NOTICE([adding -mieee to XTRA_CXXFLAGS])])\n    else\n      OCTAVE_CXX_FLAG([-ieee], [\n        ieee_fp_flag=-ieee\n        XTRA_CXXFLAGS=\"$XTRA_CXXFLAGS -ieee\"\n        AC_MSG_NOTICE([adding -ieee to XTRA_CXXFLAGS])])\n    fi\n  ;;\n  *ibm-aix4*)\n    OCTAVE_CC_FLAG([-mminimal-toc], [\n      XTRA_CFLAGS=\"$XTRA_CFLAGS -mminimal-toc\"])\n\n    OCTAVE_CXX_FLAG([-mminimal-toc], [\n      XTRA_CXXFLAGS=\"$XTRA_CXXFLAGS -mminimal-toc\"])\n  ;;\nesac\n\n## Check if C and Fortran compilers support -fexceptions to support unwinding\n## the stack for C++ exceptions through frames in C or Fortran code.\n\n# CFLAGS are used only in the configure script.\n# XTRA_CFLAGS are used only after the configure script.\nOCTAVE_CC_FLAG([-fexceptions], [\n  CFLAGS=\"$CFLAGS -fexceptions\"\n  XTRA_CFLAGS=\"$XTRA_CFLAGS -fexceptions\"\n  AC_MSG_NOTICE([adding -fexceptions to XTRA_CFLAGS])])\nOCTAVE_F77_FLAG([-fexceptions])\n\nAC_SUBST(XTRA_CFLAGS)\nAC_SUBST(XTRA_CXXFLAGS)\nAC_SUBST(XTRA_LDFLAGS)\n\n### Defaults for cross compiling.\ndnl BUILD_CC and BUILD_CXX are the compilers that we use for building tools\ndnl on the build system.  For now, we assume that the only cross compiling we\ndnl can do is with gcc on a Unixy system, but the dedicated hacker can\ndnl override these.\n\nif test \"$cross_compiling\" = yes; then\n  BUILD_CC=\"gcc\"\n  BUILD_CFLAGS=\"-O2 -g\"\n  BUILD_CXX=\"g++ -std=gnu++17\"\n  BUILD_CXXFLAGS=\"-O2 -g\"\n  BUILD_LDFLAGS=\"\"\n  BUILD_EXEEXT=\"\"\nelse\n  BUILD_CC=\"${CC}\"\n  BUILD_CFLAGS=\"${CFLAGS}\"\n  BUILD_CXX=\"${CXX}\"\n  BUILD_CXXFLAGS=\"${CXXFLAGS}\"\n  BUILD_LDFLAGS=\"${LDFLAGS}\"\n  BUILD_EXEEXT=\"${EXEEXT}\"\nfi\n\nAC_ARG_VAR([BUILD_CC],\n  [build system C compiler (used if cross compiling)])\nAC_ARG_VAR([BUILD_CFLAGS],\n  [build system C compiler flags (used if cross compiling)])\nAC_ARG_VAR([BUILD_CXX],\n  [build system C++ compiler (used if cross compiling)])\nAC_ARG_VAR([BUILD_CXXFLAGS],\n  [build system C++ compiler flags (used if cross compiling)])\nAC_ARG_VAR([BUILD_LDFLAGS],\n  [build system C++ compiler link flags (used if cross compiling)])\nAC_ARG_VAR([BUILD_EXEEXT],\n  [build system executable extension (used if cross compiling)])\n\n### Determine whether to create cross-mkoctfile and other cross-tools.\n\ncross_tools=no\nAC_ARG_ENABLE([cross-tools],\n  [AS_HELP_STRING([--enable-cross-tools],\n    [build cross tools (mkoctfile, octave-config) if cross compiling])],\n  [if test \"$enableval\" = yes; then cross_tools=yes; fi])\n\nif test \"$cross_tools\" = yes; then\n  if test \"$cross_compiling\" = no; then\n    AC_MSG_WARN([ignoring --enable-cross-tools when not cross compiling])\n    cross_tools=no\n  fi\nfi\nAM_CONDITIONAL([AMCOND_CROSS_TOOLS], [test $cross_tools = yes])\n\n### Check compiler characteristics.\ndnl FIXME: How many of these are necessary now that C++11 is required?\n\n## Check if C++ compiler can auto allocate variable sized arrays.\nOCTAVE_CXX_DYNAMIC_AUTO_ARRAYS\n\n## Check that C compiler and libraries support IEEE754 data format.\nOCTAVE_IEEE754_DATA_FORMAT\n\n## Are bit_and, bit_or, and bit_xor defined as templated operators?\nOCTAVE_CXX_BITWISE_OP_TEMPLATES\n\n## Can complex class set components independently?\nOCTAVE_CXX_COMPLEX_SETTERS\n\n## Are there functions to access real/imag parts of numbers via references?\nOCTAVE_CXX_COMPLEX_REFERENCE_ACCESSORS\n\n## Does the C compiler handle alloca and const correctly?\nAC_FUNC_ALLOCA\n\n## Does the C compiler support Automake subdir-objects option?\nAM_PROG_CC_C_O\n\n## Set the target Windows version early so that gnulib can use all functions\n## that are available in that version.\ncase $host_os in\n  msdosmsvc | mingw*)\n    AC_MSG_CHECKING([for required _WIN32_WINNT])\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <windows.h>\n        #if _WIN32_WINNT < 0x0601\n        #error \"Wrong version\"\n        #endif\n        ]], [])],\n      [AC_MSG_RESULT([none])],\n      [AC_DEFINE(_WIN32_WINNT, 0x0601,\n        [Define to 0x0601 to access SetCurrentProcessExplicitAppUserModelID.])\n       AC_MSG_RESULT([0x0601])])\n  ;;\nesac\n\n### gnulib initialization: part 2\ndnl Must take place after part 1, and after standard compiler options and\ndnl search paths have been established, and at the same priority level as\ndnl system library function and header checks, but before checks for all\ndnl external library dependencies.\n\ngl_SET_CRYPTO_CHECK_DEFAULT([auto-gpl-compat])\ngl_INIT\n\n### Checks for header files.\n\nAC_HEADER_SYS_WAIT\n\n## C headers\n\ndnl Use multiple AC_CHECKs to avoid line continuations '\\' in list.\nAC_CHECK_HEADERS([dlfcn.h floatingpoint.h fpu_control.h grp.h])\nAC_CHECK_HEADERS([ieeefp.h pthread.h pwd.h sys/ioctl.h])\nAC_CHECK_HEADERS([stropts.h sys/stropts.h])\n\n## Find a termio header to include.\n\nAC_CHECK_HEADERS([termios.h], have_termios_h=yes, have_termios_h=no)\nAC_CHECK_HEADERS([termio.h], have_termio_h=yes, have_termio_h=no)\nAC_CHECK_HEADERS([sgtty.h], have_sgtty_h=yes, have_sgtty_h=no)\nAC_CHECK_HEADERS([conio.h], have_conio_h=yes, have_conio_h=no)\n\nif test $have_termios_h != yes \\\n    && test $have_termio_h != yes \\\n    && test $have_sgtty_h != yes; then\n  AC_MSG_WARN([couldn't find one of termios.h, termio.h, or sgtty.h!])\nfi\n\n## For MSVC compilers, avoid #define of min/max from windows.h header.\nif test $have_msvc = yes; then\n  AC_DEFINE(NOMINMAX, 1, [Define to 1 to avoid min/max macro definition in Windows headers.])\nfi\n\n### Determine types and size of types.\n\nAC_TYPE_INT64_T\nAC_TYPE_MODE_T\nAC_TYPE_OFF_T\nAC_TYPE_PID_T\nAC_TYPE_SIZE_T\nAC_TYPE_SSIZE_T\nAC_TYPE_UID_T\nAC_TYPE_UINT64_T\nAC_CHECK_TYPES([dev_t, ino_t])\nAC_CHECK_TYPES([ptrdiff_t])\n\nAC_CHECK_TYPES([long long int])\nif test $ac_cv_type_long_long_int = yes; then\n  AC_DEFINE(OCTAVE_HAVE_LONG_LONG_INT, 1,\n    [Define to 1 if the system has the type 'long long int'.])\nfi\n\nAC_CHECK_TYPES([unsigned long long int])\nif test $ac_cv_type_unsigned_long_long_int = yes; then\n  AC_DEFINE(OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT, 1,\n    [Define to 1 if the system has the type 'unsigned long long int'.])\nfi\n\n## Check for long double type (may be used for 64-bit integer computations).\nAC_CHECK_SIZEOF([long double])\n\n### Check structures and existence of necessary members.\n\nAC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_blocks,\n                  struct stat.st_rdev])\nAC_CHECK_MEMBERS([struct group.gr_passwd])\n\nAC_STRUCT_TIMEZONE\n\n## Check if C++ compiler allows overload of char, int8_t, and uint8_t.\nAC_CACHE_CHECK([whether ${CXX-g++} allows overload of char, int8_t, and uint8_t],\n  [octave_cv_overload_char_int8_t],\n  [AC_LANG_PUSH(C++)\n  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[\n    #include <cstdint>\n    void somefunc(char x) {};\n    void somefunc(int8_t x) {};\n    void somefunc(uint8_t x) {};\n    ]])],\n    octave_cv_overload_char_int8_t=yes,\n    octave_cv_overload_char_int8_t=no)\n  AC_LANG_POP(C++)\n  ])\nif test $octave_cv_overload_char_int8_t = yes; then\n  AC_DEFINE(OCTAVE_HAVE_OVERLOAD_CHAR_INT8_TYPES, 1,\n    [Define to 1 if C++ allows overload of char, int8_t, and uint8_t types.])\nfi\n\n## Check whether encoding of quiet NaN value is conformant to IEEE 754-2008\nOCTAVE_IEEE754_QNAN\n\n## Check whether quiet NaN values retain their payload on arithmetic operations\nOCTAVE_QNAN_WITH_PAYLOAD\n\n## Check whether the C++ STL supports std::from_chars for double precision\n## floating-point\nAC_CACHE_CHECK([whether C++ STL supports std::from_chars for double precision floating-point],\n  [octave_cv_std_from_chars_double],\n  [AC_LANG_PUSH(C++)\n  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[\n    #include <charconv>\n    #include <string>\n\n    void test_from_chars_double ()\n    {\n      double num = 0.0;\n      std::string str = \"3.14\";\n      const char *chars_start = str.data ();\n      const char *chars_end = chars_start + str.size ();\n      auto [ptr, ec] = std::from_chars (chars_start, chars_end, num);\n    }\n    ]], [[\n    test_from_chars_double ();\n    ]])],\n    octave_cv_std_from_chars_double=yes,\n    octave_cv_std_from_chars_double=no)\n  AC_LANG_POP(C++)\n  ])\n\nif test $octave_cv_std_from_chars_double = yes; then\n  AC_DEFINE(OCTAVE_HAVE_STD_FROM_CHARS_DOUBLE, 1,\n    [Define to 1 if C++ STL supports std::from_chars for double precision floating-point.])\nelse\n  ## Check whether fast-float header-only library is available\n  AC_LANG_PUSH(C++)\n  AC_CHECK_HEADER([fast_float/fast_float.h],\n                  [have_fast_float=yes],\n                  [have_fast_float=no])\n  AC_LANG_POP(C++)\n\n  if test $have_fast_float = yes; then\n    AC_DEFINE(OCTAVE_HAVE_FAST_FLOAT, 1,\n      [Define to 1 if fast-float header-only library is available.])\n  else\n    AC_MSG_ERROR([If the C++ STL does not support std::from_chars for double precision floating-point, the fast-float header-only library needs to be installed.])\n  fi\nfi\n\n\n### Checks for functions and variables.\n\ndnl The list of functions is short because we use gnulib to guarantee\ndnl valid implementations for many common problematic functions.\n\ndnl These checks define/undefine HAVE_FUNCNAME in config.h.\ndnl Code tests HAVE_FUNCNAME and either uses function or provides workaround.\ndnl Use multiple AC_CHECKs to avoid line continuations '\\' in list\nAC_CHECK_FUNCS([ctermid dup2])\nAC_CHECK_FUNCS([endgrent endpwent execvp fork])\nAC_CHECK_FUNCS([getegid geteuid getgid getgrent getgrgid getgrnam])\nAC_CHECK_FUNCS([getpgrp getpid getppid getpwent getpwuid getuid])\nAC_CHECK_FUNCS([isascii kill])\nAC_CHECK_FUNCS([lgamma_r lgammaf_r])\nAC_CHECK_FUNCS([realpath resolvepath])\nAC_CHECK_FUNCS([select setgrent setpwent setsid siglongjmp strsignal])\nAC_CHECK_FUNCS([tcgetattr tcsetattr toascii])\nAC_CHECK_FUNCS([umask waitpid])\nAC_CHECK_FUNCS([_getch _kbhit])\n\n## Check for math defines such as M_LN2 in math.h\nAC_CACHE_CHECK([for MATH DEFINES in math.h],\n  [octave_cv_header_math_defines],\n  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n    #include <math.h>\n    ]], [[\n    double x = M_LN2;]])],\n    octave_cv_header_math_defines=yes,\n    octave_cv_header_math_defines=no)\n  ])\n\nif test $octave_cv_header_math_defines = no; then\n  ## Check again and try defining _USE_MATH_DEFINES\n  AC_CACHE_CHECK([whether _USE_MATH_DEFINES needs to be defined],\n    [octave_cv_header__use_math_defines],\n    [save_CPPFLAGS=\"$CPPFLAGS\"\n    CPPFLAGS=\"$CPPFLAGS -D_USE_MATH_DEFINES\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n      #include <math.h>\n      ]], [[\n      double x = M_LN2;]])],\n      octave_cv_header__use_math_defines=yes,\n      octave_cv_header__use_math_defines=no)\n    CPPFLAGS=\"$save_CPPFLAGS\"\n    ])\n  if test $octave_cv_header__use_math_defines = yes; then\n    octave_cv_header_math_defines=yes\n    AC_DEFINE(_USE_MATH_DEFINES, 1,\n      [Define to 1 if _USE_MATH_DEFINES is required to get math constants like M_LN2.])\n    CPPFLAGS=\"$CPPFLAGS -D_USE_MATH_DEFINES\"\n  fi\nfi\n\nif test $octave_cv_header_math_defines = yes; then\n  AC_DEFINE(HAVE_MATH_DEFINES, 1,\n    [Define to 1 if defines such as M_PI are available in math.h])\nelse\n  AC_MSG_ERROR([MATH DEFINES in math.h such as M_PI are required to build Octave])\nfi\n\n## Use Unicode aware functions on Windows\ncase $host_os in\n  msdosmsvc | mingw*)\n    AC_DEFINE(_UNICODE, 1, [Use Unicode CRT functions on Windows by default.])\n    AC_DEFINE(UNICODE, 1, [Use Windows Unicode API by default.])\n  ;;\nesac\n\nOCTAVE_UNICODE_EXE_LDFLAGS=\"\"\ncase $host_os in\n  mingw*)\n    OCTAVE_UNICODE_EXE_LDFLAGS=\"-municode\"\n  ;;\nesac\n\nAC_SUBST(OCTAVE_UNICODE_EXE_LDFLAGS)\n\ncase $host_os in\n  msdosmsvc | mingw*)\n    AC_CACHE_CHECK([whether locale can be set to UTF-8],\n      [octave_cv_windows_utf8_locale],\n      [AC_COMPILE_IFELSE([AC_LANG_SOURCE([[\n        #if defined (__MINGW32__)\n          /* We need to include this header or __MSVCRT_VERSION__ might not be\n             defined to the correct value */\n        #  include <_mingw.h>\n        #endif\n        /* Windows supports UTF-8 locales when using UCRT */\n        #if ! ((defined (__MSVCRT_VERSION__) && __MSVCRT_VERSION__ == 0x0E00) \\\n               || (defined (_MSC_VER) && _MSC_VER >= 1900))\n        #  error \"UTF-8 locale is unsupported\"\n        #endif\n        ]])],\n        octave_cv_windows_utf8_locale=yes,\n        octave_cv_windows_utf8_locale=no)\n      ])\n    if test $octave_cv_windows_utf8_locale = yes; then\n      AC_DEFINE(OCTAVE_HAVE_WINDOWS_UTF8_LOCALE, 1,\n        [Define to 1 if Windows supports UTF-8 locales.])\n    fi\n  ;;\nesac\n\n## Windows-specific use of functions\ncase $host_os in\n  msdosmsvc | mingw*)\n    AC_CHECK_FUNCS([setvbuf], [],\n                   [AC_MSG_ERROR([Missing function required to build Octave])])\n\n    ## We need this for GetDeviceCaps.  Should we actually check for\n    ## the function and library?\n    LIBS=\"-lgdi32 $LIBS\"\n  ;;\nesac\n\n## Windows-specific module used for winqueryreg function\ncase $host_os in\n  msdosmsvc | mingw*)\n    AC_CHECK_HEADERS([psapi.h],\n      [CPPFLAGS=\"-DPSAPI_VERSION=2 $CPPFLAGS\"],\n      [AC_MSG_ERROR([Missing PSAPI required to build for Windows target.])],\n      [#include <windows.h>])\n  ;;\nesac\n\n## Windows-specific module used for canonical UNC paths\ncase $host_os in\n  msdosmsvc | mingw*)\n    AC_CHECK_HEADERS([shlwapi.h],\n      [LIBS=\"-lshlwapi $LIBS\"],\n      [AC_MSG_ERROR([Missing SHLWAPI required to build for Windows target.])],\n      [#include <windows.h>])\n  ;;\nesac\n\n## Cygwin kluge for getrusage.\nAC_CHECK_FUNCS([getrusage])\ncase $host_os in\n  cygwin*)\n    AC_DEFINE(RUSAGE_TIMES_ONLY, 1,\n      [Define to 1 if the struct rusage only has time information.])\n  ;;\nesac\n\nAC_CHECK_FUNCS([getpwnam], [], [AC_CHECK_LIB([sun], [getpwnam])])\n\nAC_FUNC_CLOSEDIR_VOID\n\n## Check return type of matherr\nAC_CACHE_CHECK([for struct exception in math.h],\n  [octave_cv_func_matherr_type],\n  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n      #include <math.h>\n      ]], [[\n      struct exception *x;\n      x->type;\n      x->name;\n      ]])],\n    octave_cv_func_matherr_type=yes,\n    octave_cv_func_matherr_type=no)\n  ])\nif test $octave_cv_func_matherr_type = yes; then\n  AC_DEFINE(EXCEPTION_IN_MATH, 1,\n    [Define to 1 if math.h declares struct exception for matherr.])\nfi\n\n## Signal stuff.\n\nAC_CHECK_DECLS([sys_siglist], [], [],\n[[#include <signal.h>\n/* NetBSD declares sys_siglist in unistd.h.  */\n#if HAVE_UNISTD_H\n# include <unistd.h>\n#endif\n]])\n\n### Configure Bison as push or pull parser.\n\nENABLE_COMMAND_LINE_PUSH_PARSER=yes\nAC_ARG_ENABLE([command-line-push-parser],\n  [AS_HELP_STRING([--disable-command-line-push-parser],\n    [don't use Bison's push parser interface in the command line REPL])],\n  [if test \"$enableval\" = no; then ENABLE_COMMAND_LINE_PUSH_PARSER=no; fi], [])\nif test $ENABLE_COMMAND_LINE_PUSH_PARSER = yes; then\n  AC_DEFINE(OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER, 1,\n    [Define to 1 to use Bison's push parser interface in the command line REPL.])\nfi\n\n### Check for PCRE2 or PCRE regex library, requiring one to exist.\n\nhave_pcre2=no\nhave_pcre=no\nsave_CPPLAGS=\"$CPPFLAGS\"\nCPPFLAGS=\"-DPCRE2_CODE_UNIT_WIDTH=8 $CPPFLAGS\"\nOCTAVE_CHECK_LIB(pcre2, PCRE2,\n  [], [pcre2.h pcre2/pcre2.h], [pcre2_compile_8], [], [],\n  [OCTAVE_CHECK_LIB_PCRE2_OK([have_pcre2=yes],\n    [AC_MSG_ERROR([PCRE2 library must be built with UTF support (--enable-utf)])])],\n  [libpcre2-8])\nCPPFLAGS=\"$save_CPPFLAGS\"\n\nif test $have_pcre2 = no; then\n  OCTAVE_CHECK_LIB(pcre, PCRE,\n    [], [pcre.h pcre/pcre.h], [pcre_compile], [], [],\n    [OCTAVE_CHECK_LIB_PCRE_OK([have_pcre=yes],\n      [AC_MSG_ERROR([PCRE library must be built with UTF support (--enable-utf)])])],\n    [libpcre])\nfi\n\nif test $have_pcre2 = yes; then\n  AC_DEFINE(HAVE_PCRE2, 1, [Define to 1 if PCRE2 is available.])\n\n  ## Only one of PCRE2 or PCRE is used, so avoid having to define and use\n  ## both PCRE2_* and PCRE_* variables everywhere.\n\n  PCRE_CPPFLAGS=\"$PCRE2_CPPFLAGS\"\n  PCRE_LDFLAGS=\"$PCRE2_LDFLAGS\"\n  PCRE_LIBS=\"$PCRE2_LIBS\"\n\nelif test $have_pcre = yes; then\n  AC_DEFINE(HAVE_PCRE, 1, [Define to 1 if PCRE is available.])\nelse\n  AC_MSG_ERROR([to build Octave, you must have the PCRE or PCRE2 library and header files installed])\nfi\n\n### Check for Qhull library.\n\nQHULL_CPPFLAGS=\nQHULL_LDFLAGS=\nQHULL_LIBS=\nOCTAVE_CHECK_LIB(qhull_r, QHull,\n  [Qhull library not found.  This will result in loss of functionality for some geometry functions.],\n  [libqhull_r/libqhull_r.h libqhull_r.h],\n  [qh_qhull], [], [],\n  [warn_qhull_r=\n  OCTAVE_CHECK_QHULL_VERSION\n  OCTAVE_CHECK_LIB_QHULL_OK(\n    [AC_DEFINE(HAVE_QHULL, 1, [Define to 1 if Qhull is available.])\n     QHULL_CPPFLAGS=\"$QHULL_R_CPPFLAGS\"\n     QHULL_LDFLAGS=\"$QHULL_R_LDFLAGS\"\n     QHULL_LIBS=\"$QHULL_R_LIBS\"],\n    [warn_qhull_r=\"Qhull library found, but does not seem to work properly.  This will result in loss of functionality for some geometry functions.  Please try recompiling the library with -fno-strict-aliasing.\"])])\nAC_SUBST(QHULL_CPPFLAGS)\nAC_SUBST(QHULL_LDFLAGS)\nAC_SUBST(QHULL_LIBS)\n\n### Check for RapidJSON header-only library.\n\ncheck_for_rapidjson=yes\nAC_ARG_ENABLE([rapidjson],\n  [AS_HELP_STRING([--disable-rapidjson],\n    [disable RapidJSON])],\n  [if test \"$enableval\" = no; then check_for_rapidjson=no; fi], [])\nwarn_rapidjson=\nif test $check_for_rapidjson = yes; then\n  AC_LANG_PUSH(C++)\n  AC_CHECK_HEADER([rapidjson/rapidjson.h],\n                  [have_rapidjson=yes],\n                  [have_rapidjson=no\n                   warn_rapidjson=\"RapidJSON library not found.  Octave will not be able to read or write JSON files.\"])\n\n  if test $have_rapidjson = yes; then\n    AC_DEFINE(HAVE_RAPIDJSON, 1, [Define to 1 if RapidJSON is available.])\n\n    ## Additional check on RapidJSON library that was found\n    ## Some features of the version of RapidJSON that is packaged in many\n    ## distributions do not build correctly with newer compilers.\n    ## See also:\n    ## https://github.com/Tencent/rapidjson/issues/909\n    ## https://github.com/Tencent/rapidjson/issues/1718\n    AC_CACHE_CHECK([for working PrettyWriter in RapidJSON],\n      [octave_cv_rapidjson_has_prettywriter],\n      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <rapidjson/prettywriter.h>\n        ]], [[\n        rapidjson::StringBuffer json;\n        rapidjson::PrettyWriter<rapidjson::StringBuffer, rapidjson::UTF8<>,\n                                rapidjson::UTF8<>, rapidjson::CrtAllocator,\n                                rapidjson::kWriteNanAndInfFlag> writer (json);\n        ]])],\n        [octave_cv_rapidjson_has_prettywriter=yes],\n        [octave_cv_rapidjson_has_prettywriter=no])\n      ])\n    if test $octave_cv_rapidjson_has_prettywriter = yes; then\n      AC_DEFINE(HAVE_RAPIDJSON_PRETTYWRITER, 1,\n        [Define to 1 if the RapidJSON PrettyWriter function is available.])\n    else\n      warn_rapidjson='RapidJSON library found, but some features do not seem to work properly.  The \"PrettyWriter\" option in jsonencode will be disabled.'\n    fi\n  fi\n  AC_LANG_POP([C++])\nfi\n\nif test -n \"$warn_rapidjson\"; then\n  OCTAVE_CONFIGURE_WARNING([warn_rapidjson])\nfi\n\n### Check for readline library.\n\nOCTAVE_ENABLE_READLINE\n\n### Check whether functions from libiconv are available.\n\nOCTAVE_CHECK_ICONVLIST\n\nOCTAVE_CHECK_ICONV_CANONICALIZE\n\n### Check for ZLIB library.\n\nOCTAVE_CHECK_LIB(z, ZLIB,\n  [ZLIB library not found.  Octave will not be able to load or save compressed data files or HDF5 files.],\n  [zlib.h], [gzclearerr])\n\n## Also define HAVE_ZLIB if libz is found.\nif test -n \"$Z_LIBS\"; then\n  AC_DEFINE(HAVE_ZLIB, 1, [Define to 1 if ZLIB is available.])\nfi\n\n### Check for BZIP2 library.\n\nOCTAVE_CHECK_LIB(bz2, BZIP2,\n  [BZIP2 library not found.  Octave will not be able to compress or decompress bzip2 files.],\n  [bzlib.h], [BZ2_bzCompressInit], [], [], [], [bzip2])\n\n### Check for HDF5 library.\n\nsave_CPPFLAGS=\"$CPPFLAGS\"\nsave_LIBS=\"$LIBS\"\nCPPFLAGS=\"$Z_CPPFLAGS $CPPFLAGS\"\nLIBS=\"$Z_LDFLAGS $Z_LIBS $LIBS\"\nOCTAVE_CHECK_LIB(hdf5, HDF5,\n  [HDF5 library not found.  Octave will not be able to load or save HDF5 data files.],\n  [hdf5.h], [H5Gget_num_objs], [], [],\n  [warn_hdf5=\n   OCTAVE_CHECK_HDF5_HAS_VER_16_API\n   OCTAVE_CHECK_HDF5_HAS_UTF8_API\n   AC_DEFINE(HAVE_HDF5, 1,\n     [Define to 1 if HDF5 is available and newer than version 1.6.])\n   if test $have_msvc = yes; then\n     OCTAVE_CHECK_LIB_HDF5_DLL\n   fi\n  ])\nCPPFLAGS=\"$save_CPPFLAGS\"\nLIBS=\"$save_LIBS\"\n\ndnl FIXME: Should we check for this now, or wait until some version of HDF5\ndnl actually supports this feature?\nhave_hdf5_int2float_conversions=no\nif test $have_hdf5_int2float_conversions = yes; then\n  AC_DEFINE(HAVE_HDF5_INT2FLOAT_CONVERSIONS, 1,\n    [Define to 1 if/when HDF5 supports automatic conversion between integer and floating-point binary data.])\nfi\n\n### Check for FFTW library.\ndnl Default to Fortran FFTPACK if it is not available.\n\n## Check for FFTW header and library.\nOCTAVE_CHECK_LIB(fftw3, FFTW3,\n  [FFTW3 library not found.  Octave will not be able to perform fft calculations.],\n  [fftw3.h], [fftw_plan_dft_1d])\n\nOCTAVE_CHECK_LIB(fftw3f, FFTW3F,\n  [FFTW3F library not found.  Octave will not be able to perform fft calculations.],\n  [fftw3.h], [fftwf_plan_dft_1d])\n\n## Check command line for the option to disable multi-threaded FFTW.\nbuild_fftw_threads=yes\nAC_ARG_ENABLE([fftw-threads],\n  [AS_HELP_STRING([--disable-fftw-threads],\n    [disable Multi-threaded FFTW])],\n  [if test \"$enableval\" = no; then\n     build_fftw_threads=no\n   fi],\n  [])\n\ndnl Octave is currently unable to use FFTW unless both float and double\ndnl versions are available.\n\nAM_CONDITIONAL([AMCOND_HAVE_FFTW],\n  [test -n \"$FFTW3_LIBS\" && test -n \"$FFTW3F_LIBS\"])\n\nif test -n \"$FFTW3_LIBS\" && test -n \"$FFTW3F_LIBS\"; then\n  AC_DEFINE(HAVE_FFTW, 1, [Define to 1 if both FFTW3 and FFTW3F libraries are available.])\nelse\n  dnl --without-fftw3 given, or one of the FFTW3 libs not installed.\n  dnl Don't check for FFTW threads as this is now pointless.\n  build_fftw_threads=no\nfi\n\n## Check for multithreaded FFTW library.\n## Fallback to singlethreaded if not found or disabled.\nif test $build_fftw_threads = yes; then\n  OCTAVE_CHECK_FFTW_THREADS(fftw3, fftw_plan_with_nthreads)\n  OCTAVE_CHECK_FFTW_THREADS(fftw3f, fftwf_plan_with_nthreads)\nfi\n\n## Collections of flags.\ndnl These are here instead of just in the Makefile.am file because we\ndnl substitute some of them into other source files like mkoctfile.\n\n## Order matters, at least on some systems (Cygwin, for example).\n\nFFTW_XCPPFLAGS=\"$FFTW3_CPPFLAGS $FFTW3F_CPPFLAGS\"\n\nFFTW_XLDFLAGS=\"$FFTW3_LDFLAGS $FFTW3F_LDFLAGS\"\n\nFFTW_XLIBS=\"$FFTW3_LIBS $FFTW3F_LIBS\"\n\nAC_SUBST(FFTW_XCPPFLAGS)\nAC_SUBST(FFTW_XLDFLAGS)\nAC_SUBST(FFTW_XLIBS)\n\n## Subdirectory of liboctave/external to build if FFTW is not found.\nFFT_DIR=\"fftpack\"\nAC_SUBST(FFT_DIR)\n\n### Check for GLPK library and header.\n\nsave_CPPFLAGS=\"$CPPFLAGS\"\nsave_LIBS=\"$LIBS\"\nCPPFLAGS=\"$Z_CPPFLAGS $CPPFLAGS\"\nLIBS=\"$Z_LDFLAGS $Z_LIBS $LIBS\"\nOCTAVE_CHECK_LIB(glpk, GLPK,\n  [GLPK library not found.  The glpk function for solving linear programs will be disabled.],\n  [glpk.h glpk/glpk.h], [glp_simplex], [], [],\n  [warn_glpk=\n   OCTAVE_CHECK_LIB_GLPK_OK(\n    [AC_DEFINE(HAVE_GLPK, 1, [Define to 1 if GLPK is available.])],\n    [warn_glpk=\"GLPK library found, but does not seem to work properly; disabling glpk function\"])])\nLIBS=\"$save_LIBS\"\nCPPFLAGS=\"$save_CPPFLAGS\"\n\n### Check for cURL library existence and functionality.\n\nsave_CPPFLAGS=\"$CPPFLAGS\"\nsave_LIBS=\"$LIBS\"\nCPPFLAGS=\"$Z_CPPFLAGS $CPPFLAGS\"\nLIBS=\"$Z_LDFLAGS $Z_LIBS $LIBS\"\nOCTAVE_CHECK_LIB(curl, cURL,\n  [cURL library not found.  The ftp objects, urlread, and urlwrite functions will be disabled.],\n  [curl/curl.h], [curl_easy_escape], [], [], [], [libcurl])\nif test -n \"$CURL_LIBS\"; then\n  ## Additional check on cURL library that was found\n  AC_CACHE_CHECK([for CURLOPT_DIRLISTONLY in curl/curl.h],\n    [octave_cv_curl_has_curlopt_dirlistonly],\n    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n      #include <curl/curl.h>\n      ]], [[\n      curl_easy_setopt ((CURL*)NULL, CURLOPT_DIRLISTONLY, 0);\n      ]])],\n      [octave_cv_curl_has_curlopt_dirlistonly=yes],\n      [octave_cv_curl_has_curlopt_dirlistonly=no])\n    ])\n  if test $octave_cv_curl_has_curlopt_dirlistonly = no; then\n    AC_DEFINE(CURLOPT_DIRLISTONLY, CURLOPT_FTPLISTONLY,\n      [Define to the legacy option name if using an older version of cURL.])\n  fi\nfi\nLIBS=\"$save_LIBS\"\nCPPFLAGS=\"$save_CPPFLAGS\"\n\n### Check for sndfile library.\n\nOCTAVE_CHECK_LIB(sndfile, sndfile,\n  [sndfile library not found.  The audioinfo, audioread, and audiowrite functions will be disabled.],\n  [sndfile.h], [sf_open],\n  [], [don't use sndfile library, disable audio file I/O],\n  [warn_sndfile=\n   OCTAVE_CHECK_LIB_SNDFILE_OK(\n    [AC_DEFINE(HAVE_SNDFILE, 1, [Define to 1 if sndfile is available.])\n     OCTAVE_CHECK_LIB_SNDFILE_FORMATS],\n    [warn_sndfile=\"sndfile library found, but does not seem to work properly; disabling audio file I/O functions\"])])\n\n### Check for PortAudio library.\n\nOCTAVE_CHECK_LIB(portaudio, PortAudio,\n  [PortAudio library not found.  The audioplayer, audiorecorder, and audiodevinfo functions will be disabled.],\n  [portaudio.h], [Pa_GetDeviceCount],\n  [], [don't use PortAudio library, disable audio playback and recording],\n  [], [portaudio-2.0])\n\n### Check for either of GraphicsMagick++/ImageMagick++ libraries.\n\ncheck_magick=yes\nuse_magick=no\nAC_ARG_WITH([magick],\n  [AS_HELP_STRING([--with-magick=LIB],\n    [select library to use for image I/O (options: GraphicsMagick++ (default) or ImageMagick++)])\ndnl Second help string must not be indented for correct alignment\nAS_HELP_STRING([--without-magick], [don't use Magick library, disable imread, imwrite, imformats, imfinfo])],\n  [case $withval in\n     yes | \"\")\n       magick=\"GraphicsMagick++\"\n     ;;\n     no)\n       check_magick=no\n     ;;\n     *)\n       magick=\"$withval\"\n     ;;\n   esac],\n  [magick=\"GraphicsMagick++\"])\n\nif test $check_magick = yes; then\n\n  MAGICK_CPPFLAGS=\n  MAGICK_LDFLAGS=\n  MAGICK_LIBS=\n\n  PKG_CHECK_EXISTS([$magick], [\n    dnl We are using --cflags now instead of --cflags-only-I because some\n    dnl Graphics/ImageMagick++ packages will provide -D options for\n    dnl MAGICKCORE_HDRI_ENABLE and MAGICKCORE_QUANTUM_DEPTH that are needed\n    dnl for building with a particular verison of the library.  If there\n    dnl are other flags in the output from pkg-config --cflags that cause\n    dnl trouble, then we may need to go back to using --cflags-only-I and\n    dnl have a configure test to determine the proper definitions of\n    dnl MAGICKCORE_HDRI_ENABLE and MAGICKCORE_QUANTUM_DEPTH.\n    dnl See also bug #49563.\n    MAGICK_CPPFLAGS=\"$($PKG_CONFIG --cflags $magick | $SED -e 's/^ *$//')\"\n    MAGICK_LDFLAGS=\"$($PKG_CONFIG --libs-only-L $magick | $SED -e 's/^ *$//')\"\n    MAGICK_LIBS=\"$($PKG_CONFIG --libs-only-l $magick | $SED -e 's/^ *$//')\"\n\n    warn_magick=\"$magick library fails tests.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional.\"\n\n    save_CPPFLAGS=\"$CPPFLAGS\"\n    save_LIBS=\"$LIBS\"\n    CPPFLAGS=\"$MAGICK_CPPFLAGS $CPPFLAGS\"\n    LIBS=\"$MAGICK_LDFLAGS $MAGICK_LIBS $LIBS\"\n    AC_LANG_PUSH(C++)\n    AC_CHECK_HEADER([Magick++.h], [\n      AC_CACHE_CHECK([for Magick::ColorRGB and Magick::PixelPacket in Magick++.h],\n        [octave_cv_func_magick],\n        [AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n          #include <Magick++.h>\n          ]], [[\n          Magick::ColorRGB c;\n          Magick::PixelPacket pix;\n          ]])],\n          octave_cv_func_magick=yes,\n          octave_cv_func_magick=no)\n        ])\n      if test $octave_cv_func_magick = yes; then\n        use_magick=yes\n        warn_magick=\n      fi\n    ])\n    AC_LANG_POP(C++)\n    CPPFLAGS=\"$save_CPPFLAGS\"\n    LIBS=\"$save_LIBS\"\n  ],\n  [use_magick=no\n   warn_magick=\"$magick library not found.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional.\"])\nfi\n\nif test $use_magick = yes; then\n  AC_DEFINE(HAVE_MAGICK, 1,\n    [Define to 1 if Graphics/ImageMagick++ is available.])\nelse\n  if test -n \"$warn_magick\"; then\n    OCTAVE_CONFIGURE_WARNING([warn_magick])\n  fi\n  MAGICK_CPPFLAGS=\n  MAGICK_LDFLAGS=\n  MAGICK_LIBS=\nfi\nAC_SUBST(MAGICK_CPPFLAGS)\nAC_SUBST(MAGICK_LDFLAGS)\nAC_SUBST(MAGICK_LIBS)\n\n### Check for X11 libraries.\n\nAC_PATH_X\nif test \"$have_x\" = yes; then\n  AC_DEFINE(HAVE_X_WINDOWS, 1, [Define to 1 if X11 is available.])\n\n  if test \"$x_includes\" != \"NONE\"; then\n    X11_INCFLAGS=\"$x_includes\"\n  fi\n  AC_SUBST(X11_INCFLAGS)\n\n  if test -z \"$x_libraries\"; then\n    AC_CHECK_LIB([X11], XrmInitialize, [X11_LIBS=\"-lX11\"], [X11_LIBS=])\n  elif test \"$x_libraries\" != \"NONE\"; then\n    AC_CHECK_LIB([X11], XrmInitialize,\n      [X11_LIBS=\"-L$x_libraries -lX11\"], [X11_LIBS=], \"-L$x_libraries\")\n  fi\n  AC_SUBST(X11_LIBS)\nfi\n\n### Check for Wayland client library\n\noctave_cv_no_window_manager_warn=\ncase $host_os in\n  msdosmsvc | mingw* | cygwin* | darwin*)\n    # do not warn about missing X11 or Wayland client on Windows or macOS\n  ;;\n  *)\n    if test \"$have_x\" != yes; then\n      # do not warn about Wayland client if the X11 libraries have been found\n      octave_cv_no_window_manager_warn=\"Neither X11 nor Wayland client libraries found.\"\n    fi\n  ;;\nesac\n\nOCTAVE_CHECK_LIB(wayland-client, Wayland client,\n  [$octave_cv_no_window_manager_warn],\n  [wayland-client.h], [wl_display_connect])\n\n### Check for the Carbon framework on macOS systems.\n\nOCTAVE_HAVE_FRAMEWORK([Carbon],\n  [[#include <Carbon/Carbon.h>]], [[CGMainDisplayID ()]],\n  [have_framework_carbon=yes], [have_framework_carbon=no])\nif test $have_framework_carbon = yes; then\n  AC_DEFINE(HAVE_FRAMEWORK_CARBON, 1,\n    [Define to 1 if framework CARBON is available.])\n  CARBON_LIBS=\"-framework Carbon\"\n  AC_MSG_NOTICE([adding -framework Carbon to CARBON_LIBS])\n  AC_SUBST(CARBON_LIBS)\nfi\n\n## Check for the CGDisplayBitsPerPixel function.\nif test $have_framework_carbon = yes; then\n  OCTAVE_CARBON_CGDISPLAYBITSPERPIXEL\nfi\n\n### Check for OpenGL and helper libraries used by OpenGL graphics renderer.\n\ncheck_opengl=yes\nAC_ARG_WITH([opengl],\n  [AS_HELP_STRING([--without-opengl],\n    [don't use OpenGL libraries, disable OpenGL graphics])],\n  [if test x\"$withval\" = xno; then\n     check_opengl=no\n   fi])\n\n## Check for OpenGL library\nif test $check_opengl = yes; then\n  OCTAVE_CHECK_LIB_OPENGL\n  if test -z \"$OPENGL_LIBS\"; then\n    warn_opengl_libs=\"OpenGL libs (GL and GLU) not found.  OpenGL graphics will be disabled.\"\n    OCTAVE_CONFIGURE_WARNING([warn_opengl_libs])\n  fi\nfi\n\n## Check for FreeType 2 library\n\ncheck_freetype=yes\nwarn_freetype=\nAC_ARG_WITH([freetype],\n  [AS_HELP_STRING([--without-freetype],\n    [don't use FreeType library, OpenGL graphics will not be fully functional])],\n  [if test x\"$withval\" = xno; then\n     check_freetype=no\n   fi])\n\nif test $check_freetype = yes; then\n  PKG_CHECK_MODULES([FT2], [freetype2], [\n    min_ft2_version=9.03\n    AC_MSG_CHECKING([for FreeType2 version >= $min_ft2_version])\n    $PKG_CONFIG freetype2 --atleast-version=$min_ft2_version\n    ac_status=$?\n    if test \"$ac_status\" = 0; then\n      AC_MSG_RESULT(yes)\n      AC_DEFINE(HAVE_FREETYPE, 1, [Define to 1 if Freetype is available.])\n      save_LIBS=\"$LIBS\"\n      LIBS=\"$FT2_LIBS $LIBS\"\n      AC_CHECK_FUNCS([FT_Reference_Face])\n      LIBS=\"$save_LIBS\"\n    else\n      AC_MSG_RESULT(no)\n      warn_freetype=\"FreeType library >= 9.03 not found.  OpenGL graphics will not be fully functional.\"\n    fi],\n    [warn_freetype=\"FreeType library not found.  OpenGL graphics will not be fully functional.\"])\nfi\n\nif test -n \"$warn_freetype\"; then\n  FT2_CFLAGS=\n  FT2_LIBS=\n  OCTAVE_CONFIGURE_WARNING([warn_freetype])\nelse\n  dnl Alias CPPFLAGS to CFLAGS.  This is closer to the true meaning\n  dnl of `pkg-config --cflags` output.\n  FT2_CPPFLAGS=\"$FT2_CFLAGS\"\n  AC_SUBST(FT2_CPPFLAGS)\nfi\n\n## Check for fontconfig library\n\nOCTAVE_CHECK_LIB(fontconfig, fontconfig,\n  [Fontconfig library not found.  OpenGL graphics will not be fully functional.],\n  [fontconfig.h fontconfig/fontconfig.h], [FcInit],\n  [], [don't use fontconfig library, OpenGL graphics will not be fully functional])\n\n### GUI/Qt related tests.\n\nif test -z ${QT_VERSIONS+x}; then\n  ## If QT_VERSIONS is unset, choose default depending on compiler support.\n  if test $HAVE_CXX17 = 0; then\n    dnl Qt6 requires support for C++17.\n    QT_VERSIONS=\"5\"\n  else\n    QT_VERSIONS=\"6 5\"\n  fi\nfi\n\ncheck_qscintilla=yes\nAC_ARG_WITH([qscintilla],\n  [AS_HELP_STRING([--without-qscintilla], [disable QScintilla editor])],\n  [if test x\"$withval\" = xno; then\n     check_qscintilla=no\n   fi])\n\nOCTAVE_CHECK_QT([$QT_VERSIONS])\n\n## Default terminal font for the GUI.\n\ncase $host_os in\n  mingw* | msdosmsvc)\n    DEFAULT_TERMINAL_FONT=\"Lucida Console\"\n  ;;\n  *)\n    DEFAULT_TERMINAL_FONT=\"Courier\"\n  ;;\nesac\nDEFAULT_TERMINAL_FONT_SIZE=10\nAC_SUBST(DEFAULT_TERMINAL_FONT)\nAC_SUBST(DEFAULT_TERMINAL_FONT_SIZE)\n\n### Check for FLTK library.\n\ncheck_fltk=yes\nbuild_fltk_graphics=no\n\nAC_ARG_WITH([fltk],\n  [AS_HELP_STRING([--without-fltk],\n    [don't use FLTK libraries, disable OpenGL graphics with FLTK widgets])],\n  [if test x\"$withval\" = xno; then\n     check_fltk=no\n   fi])\n\nFLTK_CPPFLAGS=\nFLTK_LDFLAGS=\nFLTK_LIBS=\n\nif test $check_fltk = yes; then\n  AC_ARG_WITH([fltk-prefix],\n    [AS_HELP_STRING([--with-fltk-prefix=PFX],\n      [prefix where FLTK is installed])],\n    [fltk_prefix=\"$withval\"],\n    [fltk_prefix=\"\"])\n\n  AC_ARG_WITH([fltk-exec-prefix],\n    [AS_HELP_STRING([--with-fltk-exec-prefix=PFX],\n      [exec prefix where FLTK is installed])],\n    [fltk_exec_prefix=\"$withval\"],\n    [fltk_exec_prefix=\"\"])\n\n  if test \"x$fltk_exec_prefix\" != x; then\n    fltk_args=\"$fltk_args --exec-prefix=$fltk_exec_prefix\"\n    if test \"x${FLTK_CONFIG+set}\" != xset ; then\n      FLTK_CONFIG=\"$fltk_exec_prefix/bin/fltk-config\"\n    fi\n  fi\n\n  if test \"x$fltk_prefix\" != x; then\n    fltk_args=\"$fltk_args --prefix=$fltk_prefix\"\n    if test x${FLTK_CONFIG+set} != xset ; then\n      FLTK_CONFIG=\"$fltk_prefix/bin/fltk-config\"\n    fi\n  fi\n\n  AC_PATH_PROG([FLTK_CONFIG], [fltk-config], [no])\n\n  warn_fltk_config=\n  warn_fltk_opengl=\n\n  if test \"$FLTK_CONFIG\" = no; then\n    warn_fltk_config=\"FLTK config script not found.  FLTK toolkit will be disabled.\"\n    OCTAVE_CONFIGURE_WARNING([warn_fltk_config])\n  else\n    ## Only include -I options in FLTK_CPPFLAGS\n    fltk_cflags=`$FLTK_CONFIG $fltkconf_args --use-gl --cflags`\n    for fltk_option in $fltk_cflags; do\n      case $fltk_option in\n        -I*)\n          FLTK_CPPFLAGS=\"$FLTK_CPPFLAGS $fltk_option\"\n        ;;\n      esac\n    done\n    FLTK_CPPFLAGS=`echo \"$FLTK_CPPFLAGS\" | $SED -e 's/^ \\+//'`\n\n    ## Split -L and -l options into FLTK_LDFLAGS and FLTK_LIBS\n    fltk_ldflags=`$FLTK_CONFIG $fltkconf_args --use-gl --ldflags`\n    for fltk_option in $fltk_ldflags; do\n      case $fltk_option in\n        -l*)\n          FLTK_LIBS=\"$FLTK_LIBS $fltk_option\"\n        ;;\n        *)\n          FLTK_LDFLAGS=\"$FLTK_LDFLAGS $fltk_option\"\n        ;;\n      esac\n    done\n    FLTK_LIBS=`echo \"$FLTK_LIBS\" | $SED -e 's/^ \\+//'`\n    FLTK_LDFLAGS=`echo \"$FLTK_LDFLAGS\" | $SED -e 's/^ \\+//'`\n\n    case $host_os in\n      mingw*)\n        FLTK_LDFLAGS=`echo $FLTK_LDFLAGS | $SED -e 's/-mwindows//g'`\n      ;;\n    esac\n    AC_LANG_PUSH(C++)\n    AC_CACHE_CHECK([for OpenGL support in FLTK],\n      [octave_cv_fltk_opengl_support],\n      [save_CPPFLAGS=\"$CPPFLAGS\"\n      CPPFLAGS=\"$CFLAGS $FLTK_CPPFLAGS\"\n      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <FL/gl.h>\n        ]], [[\n        int nothing = 0;\n        ]])],\n        octave_cv_fltk_opengl_support=yes,\n        octave_cv_fltk_opengl_support=no)\n      CPPFLAGS=\"$save_CPPFLAGS\"\n      ])\n    if test $octave_cv_fltk_opengl_support = no; then\n      warn_fltk_opengl=\"FLTK does not have OpenGL support.  OpenGL graphics with FLTK widgets will be disabled.\"\n    else\n      build_fltk_graphics=yes\n      AC_DEFINE(HAVE_FLTK, 1, [Define to 1 if FLTK is available.])\n    fi\n    AC_LANG_POP(C++)\n\n    if test -n \"$warn_fltk_opengl\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_fltk_opengl])\n    fi\n  fi\nfi\n\nAC_SUBST(FLTK_CPPFLAGS)\nAC_SUBST(FLTK_LDFLAGS)\nAC_SUBST(FLTK_LIBS)\n\n### Final determination of whether OpenGL graphics features should\n### be built.  Note that there is no longer a way to build the Qt GUI\n### without also building a Qt widget that uses OpenGL graphics so we\n### check $build_qt_gui instead of $build_qt_graphics here.\nif test $build_qt_gui = no && test $build_fltk_graphics = no; then\n  opengl_graphics=no\nelse\n  opengl_graphics=yes\nfi\n\n## Check for gl2ps which is required for printing with OpenGL graphics.\n\nif test $opengl_graphics = yes; then\n  AC_CHECK_HEADERS([gl2ps.h],\n    [GL2PS_LIBS=\"-lgl2ps\"],\n    [warn_gl2ps=\"gl2ps library not found.  Printing of OpenGL graphics will be disabled.\"])\n\n  if test -n \"$warn_gl2ps\"; then\n    OCTAVE_CONFIGURE_WARNING([warn_gl2ps])\n  else\n    save_LIBS=\"$LIBS\"\n    LIBS=\"$GL2PS_LIBS $LIBS\"\n    AC_CHECK_FUNCS([gl2psLineJoin])\n    LIBS=\"$save_LIBS\"\n  fi\n\n  AC_SUBST(GL2PS_LIBS)\nfi\n\n### Use the system-wide installation of GNU FreeFont if the user requests it.\ndnl By default, Octave includes its own copy of the FreeSans font which it\ndnl installs in its own directory for use as a fallback default font.  If this\ndnl configuration option is used, then do not install our own copy of the fonts\ndnl and assume they can be found in the provided system directory.\nSYSTEM_FREEFONT_DIR=\nAC_ARG_WITH([system-freefont],\n  [AS_HELP_STRING([--with-system-freefont=DIR],\n    [use FreeSans fonts in DIR (default: install and use internal copy)])])\ncase $with_system_freefont in\n  no | \"\")\n    SYSTEM_FREEFONT_DIR=\n    ;;\n  yes)\n    AC_MSG_ERROR([directory argument required for --with-system-freefont])\n    ;;\n  *)\n    SYSTEM_FREEFONT_DIR=$with_system_freefont\n    ;;\nesac\nif test -n \"$SYSTEM_FREEFONT_DIR\"; then\n  AC_MSG_NOTICE([configuring Octave to use system fonts in $SYSTEM_FREEFONT_DIR])\n  AC_DEFINE_UNQUOTED([SYSTEM_FREEFONT_DIR], [\"$SYSTEM_FREEFONT_DIR\"],\n    [Define this to be the system directory containing the GNU FreeFont fonts.])\nfi\nAM_CONDITIONAL([AMCOND_INSTALL_INTERNAL_FONT_FILES],\n  [test -z \"$SYSTEM_FREEFONT_DIR\"])\n\n### Check for qrupdate library.\n\ndnl No need to adjust FFLAGS because only link is attempted.\ndnl Must supply proper LIBS, however.\nsave_LIBS=\"$LIBS\"\nLIBS=\"$LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS\"\nOCTAVE_CHECK_LIB(qrupdate, qrupdate,\n  [qrupdate not found.  The QR & Cholesky updating functions will be slow.],\n  [],\n  [sqr1up],\n  [Fortran 77], [don't use qrupdate, disable QR & Cholesky updating functions])\n\n## Additional check to see if qrupdate lib found supports LU updates\nif test -n \"$QRUPDATE_LIBS\"; then\n  AC_CACHE_CHECK([for slup1up in $QRUPDATE_LIBS],\n    [octave_cv_func_slup1up],\n    [LIBS=\"$LIBS $QRUPDATE_LIBS\"\n    AC_LANG_PUSH([Fortran 77])\n    AC_LINK_IFELSE([AC_LANG_CALL([], [slup1up])],\n      octave_cv_func_slup1up=yes, octave_cv_func_slup1up=no)\n    AC_LANG_POP([Fortran 77])\n  ])\n  if test $octave_cv_func_slup1up = yes; then\n    AC_DEFINE(HAVE_QRUPDATE_LUU, 1, [Define to 1 if qrupdate supports LU updates.])\n  fi\nfi\nLIBS=\"$save_LIBS\"\n\nif test $ENABLE_64 = yes; then\n  CHOLMOD_TAG=\"_l_\"\n  CXSPARSE_TAG=\"_dl_\"\n  UMFPACK_TAG=\"_zl_\"\nelse\n  CHOLMOD_TAG=\"_\"\n  CXSPARSE_TAG=\"_di_\"\n  UMFPACK_TAG=\"_zi_\"\nfi\n\n## On some systems, explicitly linking with -lsuitesparseconfig is needed\n## when using SuiteSparse libraries.  If so, the checks below for specific\n## SuiteSparse libraries may fail without it.  Include LIB_CLOCK_GETTIME (from\n## gnulib) on systems where needed.\n\nsave_LIBS=\"$LIBS\"\nLIBS=\"$LIB_CLOCK_GETTIME $LIBS\"\nOCTAVE_CHECK_LIB(suitesparseconfig, SUITESPARSECONFIG,\n  [], [], [SuiteSparse_time], [],\n  [don't link directly with suitesparseconfig library],\n  [],\n  SuiteSparse_config)\nLIBS=\"$save_LIBS\"\n\nif test -n \"$SUITESPARSECONFIG_LIBS\" && test -n \"$LIB_CLOCK_GETTIME\"; then\n  SUITESPARSECONFIG_LIBS=\"$SUITESPARSECONFIG_LIBS $LIB_CLOCK_GETTIME\"\nfi\n\n## Save and restore LIBS after all checks for SuiteSparse libraries.\nsuitesparse_save_LIBS=\"$LIBS\"\nLIBS=\"$SUITESPARSECONFIG_LIBS $LIBS\"\n\n### Check for AMD library.\n\nOCTAVE_CHECK_LIB(amd, AMD,\n  [AMD library not found.  This will result in some lack of functionality for sparse matrices.],\n  [amd.h suitesparse/amd.h amd/amd.h],\n  [amd_postorder],\n  [], [don't use AMD library, disable some sparse matrix functionality],\n  [],\n  AMD)\n\n### Check for CAMD library.\n\nOCTAVE_CHECK_LIB(camd, CAMD,\n  [CAMD library not found.  This will result in some lack of functionality for sparse matrices.],\n  [camd.h suitesparse/camd.h camd/camd.h],\n  [camd_postorder],\n  [], [don't use CAMD library, disable some sparse matrix functionality],\n  [],\n  CAMD)\n\n### Check for COLAMD library.\n\nOCTAVE_CHECK_LIB(colamd, COLAMD,\n  [COLAMD library not found.  This will result in some lack of functionality for sparse matrices.],\n  [colamd.h suitesparse/colamd.h colamd/colamd.h],\n  [colamd],\n  [], [don't use COLAMD library, disable some sparse matrix functionality],\n  [],\n  COLAMD)\n\n### Check for CCOLAMD library.\n\nOCTAVE_CHECK_LIB(ccolamd, CCOLAMD,\n  [CCOLAMD library not found.  This will result in some lack of functionality for sparse matrices.],\n  [ccolamd.h suitesparse/ccolamd.h ccolamd/ccolamd.h],\n  [ccolamd],\n  [], [don't use CCOLAMD library, disable some sparse matrix functionality],\n  [],\n  CCOLAMD)\n\n### Check for CHOLMOD library.\ndnl If your cholmod library requires cblas, then you will need to configure\ndnl with --with-cholmod=\"-lcholmod -lcblas\".\n\nsave_LIBS=\"$LIBS\"\nLIBS=\"$COLAMD_LDFLAGS $COLAMD_LIBS $AMD_LDFLAGS $AMD_LIBS $LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS\"\nOCTAVE_CHECK_LIB(cholmod, CHOLMOD,\n  [CHOLMOD library not found.  This will result in some lack of functionality for sparse matrices.],\n  [cholmod.h suitesparse/cholmod.h cholmod/cholmod.h],\n  [cholmod${CHOLMOD_TAG}start],\n  [], [don't use CHOLMOD library, disable some sparse matrix functionality],\n  [],\n  CHOLMOD)\nLIBS=\"$save_LIBS\"\n\n### Check for SPQR library.\n\nsave_LIBS=\"$LIBS\"\nLIBS=\"$CHOLMOD_LIBS $LIBS\"\nOCTAVE_CHECK_LIB(spqr, SPQR,\n  [SPQR library not found.  This will result in some lack of functionality for sparse matrices.],\n  [SuiteSparseQR.hpp suitesparse/SuiteSparseQR.hpp],\n  [SuiteSparseQR_C],\n  [C++], [don't use SPQR library, disable some sparse matrix functionality],\n  [],\n  SPQR)\nLIBS=\"$save_LIBS\"\n\n### Check for CXSparse library.\n\nOCTAVE_CHECK_LIB(cxsparse, CXSparse,\n  [CXSparse library not found.  This will result in some lack of functionality for sparse matrices.],\n  [cs.h suitesparse/cs.h cxsparse/cs.h],\n  [cs${CXSPARSE_TAG}sqr],\n  [C++], [don't use CXSparse library, disable some sparse matrix functionality],\n  [],\n  CXSparse)\n\nif test -n \"$CXSPARSE_LIBS\"; then\n  ## Additional check for CXSparse version >= 2.2\n  if test $octave_cv_lib_cxsparse = yes; then\n    OCTAVE_CHECK_CXSPARSE_VERSION_OK\n    if test $octave_cv_cxsparse_version_ok = no; then\n      AC_MSG_ERROR([CXSparse library is too old (< version 2.2).  Upgrade CXSparse (SuiteSparse) or configure Octave with --without-cxsparse\"])\n    fi\n  fi\nfi\n\n### Check for UMFPACK library.\n\nsave_LIBS=\"$LIBS\"\nsave_CPPFLAGS=\"$CPPFLAGS\"\nLIBS=\"$AMD_LDFLAGS $AMD_LIBS $BLAS_LIBS $FLIBS $LIBS\"\nCPPFLAGS=\"$AMD_CPPFLAGS $CPPFLAGS\"\nOCTAVE_CHECK_LIB([umfpack], UMFPACK,\n  [UMFPACK not found.  This will result in some lack of functionality for sparse matrices.],\n  [umfpack.h suitesparse/umfpack.h umfpack/umfpack.h],\n  [umfpack${UMFPACK_TAG}get_determinant],\n  [], [don't use UMFPACK, disable some sparse matrix functionality],\n  [],\n  UMFPACK)\nCPPFLAGS=\"$save_CPPFLAGS\"\nLIBS=\"$save_LIBS\"\n\nif test -z \"$UMFPACK_LIBS\"; then\n  ## Invalidate the cache and try again with -lcblas.\n  $as_unset ac_cv_lib_umfpack_umfpack${UMFPACK_TAG}get_determinant\n  $as_unset octave_cv_lib_umfpack\n  save_LIBS=\"$LIBS\"\n  LIBS=\"-lcblas $AMD_LDFLAGS $AMD_LIBS $BLAS_LIBS $FLIBS $LIBS\"\n  OCTAVE_CHECK_LIB([umfpack], UMFPACK,\n    [UMFPACK not found.  This will result in some lack of functionality for sparse matrices.],\n    [umfpack.h suitesparse/umfpack.h umfpack/umfpack.h],\n    [umfpack${UMFPACK_TAG}get_determinant],\n    [], [don't use UMFPACK, disable some sparse matrix functionality],\n    [],\n    UMFPACK)\n  if test -n \"$UMFPACK_LIBS\"; then\n    UMFPACK_LIBS=\"$UMFPACK_LIBS -lcblas\"\n  fi\n  LIBS=\"$save_LIBS\"\nfi\n\n### Check for KLU library and header.\n\nOCTAVE_CHECK_LIB(klu, KLU,\n  [KLU library not found.  This will result in some lack of functionality for sparse matrices.],\n  [klu.h suitesparse/klu.h klu/klu.h], [klu_solve],\n  [], [don't use KLU library, disable some sparse matrix functionality],\n  [],\n  KLU)\n\n## Restore LIBS after all suitesparse configuration tests\nLIBS=\"$suitesparse_save_LIBS\"\n\n## Collections of flags.\ndnl These are here instead of just in the Makefile.am file because we\ndnl substitute some of them into other source files like mkoctfile.\n\n## Order matters, at least on some systems (Cygwin, for example).\n\nSPARSE_XCPPFLAGS=\"$CHOLMOD_CPPFLAGS $UMFPACK_CPPFLAGS $AMD_CPPFLAGS $CAMD_CPPFLAGS $COLAMD_CPPFLAGS $CCOLAMD_CPPFLAGS $CXSPARSE_CPPFLAGS $SPQR_CPPFLAGS\"\n\nSPARSE_XLDFLAGS=\"$CHOLMOD_LDFLAGS $UMFPACK_LDFLAGS $AMD_LDFLAGS $CAMD_LDFLAGS $COLAMD_LDFLAGS  $CCOLAMD_LDFLAGS $CXSPARSE_LDFLAGS $SPQR_LDFLAGS\"\n\nSPARSE_XLIBS=\"$CHOLMOD_LIBS $UMFPACK_LIBS $AMD_LIBS $CAMD_LIBS $COLAMD_LIBS $CCOLAMD_LIBS $CXSPARSE_LIBS $SUITESPARSECONFIG_LIBS $SPQR_LIBS\"\n\nAC_SUBST(SPARSE_XCPPFLAGS)\nAC_SUBST(SPARSE_XLDFLAGS)\nAC_SUBST(SPARSE_XLIBS)\n\n### Check sizes of integer types that are used for indexing for SuiteSparse.\n\nOCTAVE_CHECK_SUITESPARSE_SIZEOF_IDX_TYPES\n\n## Check for UMFPACK separately split complex matrix and RHS.\nif test -n \"$UMFPACK_LIBS\"; then\n  save_CPPFLAGS=\"$CPPFLAGS\"\n  save_LDFLAGS=\"$LDFLAGS\";\n  save_LIBS=\"$LIBS\";\n\n  CPPFLAGS=\"$SPARSE_XCPPFLAGS $CPPFLAGS\"\n  LDFLAGS=\"$SPARSE_XLDFLAGS $LDFLAGS\"\n  LIBS=\"$SPARSE_XLIBS $LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS $xtra_libs\"\n\n  OCTAVE_UMFPACK_SEPARATE_SPLIT\n\n  CPPFLAGS=\"$save_CPPFLAGS\"\n  LDFLAGS=\"$save_LDFLAGS\"\n  LIBS=\"$save_LIBS\"\nfi\n\n### Check for SUNDIALS NVECTOR serial library and header.\n\nOCTAVE_CHECK_LIB(sundials_nvecserial, [SUNDIALS NVECTOR],\n  [SUNDIALS NVECTOR serial library not found.  The solvers ode15i and ode15s will be disabled.],\n  [nvector/nvector_serial.h], [N_VNew_Serial],\n  [C++], [don't use SUNDIALS NVECTOR library, disable solvers ode15i and ode15s])\n\n### Check for SUNDIALS IDA library and header.\n\nif test -n \"$SUNDIALS_NVECSERIAL_LIBS\"; then\n\n  save_CPPFLAGS=\"$CPPFLAGS\"\n  save_LDFLAGS=\"$LDFLAGS\"\n  save_LIBS=\"$LIBS\"\n  LIBS=\"$SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS $BLAS_LIBS $FLIBS $LIBS\"\n  LDFLAGS=\"$SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS $BLAS_LDFLAGS $LDFLAGS\"\n  CPPFLAGS=\"$SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS $BLAS_CPPFLAGS $CPPFLAGS\"\n  OCTAVE_CHECK_LIB(sundials_ida, [SUNDIALS IDA],\n    [SUNDIALS IDA library not found.  The solvers ode15i and ode15s will be disabled.],\n    [ida.h ida/ida.h], [IDAInit],\n    [], [don't use SUNDIALS IDA library, disable solvers ode15i and ode15s])\n  CPPFLAGS=\"$save_CPPFLAGS\"\n  LDFLAGS=\"$save_LDFLAGS\"\n  LIBS=\"$save_LIBS\"\nfi\n\nif test -n \"$SUNDIALS_IDA_LIBS\" \\\n    && test -n \"$SUNDIALS_NVECSERIAL_LIBS\"; then\n  octave_have_sundials_libs=yes\nelse\n  octave_have_sundials_libs=no\nfi\n\n### Check for SUNDIALS library features, some required, some optional.\n\nif test \"x$octave_have_sundials_libs\" == xyes; then\n\n  CPPFLAGS=\"$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS $BLAS_CPPFLAGS $CPPFLAGS\"\n  LDFLAGS=\"$SUNDIALS_IDA_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS $BLAS_LDFLAGS $LDFLAGS\"\n  LIBS=\"$SUNDIALS_IDA_LIBS $SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS $BLAS_LIBS $FLIBS $LIBS\"\n  if test -z \"$warn_sundials_nvecserial\" && test -z \"$warn_sundials_ida\"; then\n    dnl Any of the following tests could determine that SUNDIALS is\n    dnl incompatible and should be disabled.  In that event, they all populate\n    dnl the same variable with appropriate warning messages, and further tests\n    dnl should be skipped if a warning message has already been generated that\n    dnl SUNDIALS is disabled.\n    warn_sundials_disabled=\n    if test -z \"$warn_sundials_disabled\"; then\n      OCTAVE_CHECK_SUNDIALS_COMPATIBLE_API\n    fi\n    if test -z \"$warn_sundials_disabled\"; then\n      OCTAVE_CHECK_SUNDIALS_SUNREALTYPE\n      OCTAVE_CHECK_SUNDIALS_SIZEOF_REALTYPE\n    fi\n    if test -z \"$warn_sundials_disabled\"; then\n      OCTAVE_CHECK_SUNDIALS_SUNLINSOL_DENSE\n    fi\n    dnl The following tests determine whether certain optional features are\n    dnl present in the SUNDIALS libraries, but will not disable using SUNDIALS.\n    if test -z \"$warn_sundials_disabled\"; then\n      OCTAVE_CHECK_SUNDIALS_SUNLINSOL_KLU\n    fi\n  fi\n  CPPFLAGS=\"$save_CPPFLAGS\"\n  LDFLAGS=\"$save_LDFLAGS\"\n  LIBS=\"$save_LIBS\"\nfi\n\ndnl Define this way instead of with an #if in oct-conf-post-private.h so that\ndnl the build features script will get the correct value.\ndnl\ndnl FIXME: The test on the sunlinsol_klu.h header is a bit of a kluge.\ndnl How can we do a better job here?  Do we need to disable sundials\ndnl any tests fail, or can we fix __ode15__.cc so that it still partially\ndnl works when some things are missing (for example, KLU)?\nif test \"x$octave_have_sundials_libs\" == xyes; then\n  if test \"x$octave_cv_sundials_sunlinsol_dense\" = xyes \\\n      && test \"x$octave_cv_sundials_realtype_is_double\" = xyes \\\n      && test \"x$octave_have_sundials_compatible_api\" = xyes; then\n    AC_DEFINE(HAVE_SUNDIALS, 1, [Define to 1 if SUNDIALS is available.])\n\n    ## Options needed to build with SUNDIALS and its dependencies.\n    SUNDIALS_XCPPFLAGS=\"$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_SUNLINSOLKLU_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $SUNDIALS_CORE_CPPFLAGS $KLU_CPPFLAGS\"\n    SUNDIALS_XLDFLAGS=\"$SUNDIALS_IDA_LDFLAGS $SUNDIALS_SUNLINSOLKLU_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $SUNDIALS_CORE_LDFLAGS $KLU_LDFLAGS\"\n    SUNDIALS_XLIBS=\"$SUNDIALS_IDA_LIBS $SUNDIALS_SUNLINSOLKLU_LIBS $SUNDIALS_NVECSERIAL_LIBS $SUNDIALS_CORE_LIBS $KLU_LIBS\"\n  else\n    SUNDIALS_IDA_CPPFLAGS=\n    SUNDIALS_IDA_LDFLAGS=\n    SUNDIALS_IDA_LIBS=\n    SUNDIALS_SUNLINSOLKLU_CPPFLAGS=\n    SUNDIALS_SUNLINSOLKLU_LDFLAGS=\n    SUNDIALS_SUNLINSOLKLU_LIBS=\n    SUNDIALS_NVECSERIAL_CPPFLAGS=\n    SUNDIALS_NVECSERIAL_LDFLAGS=\n    SUNDIALS_NVECSERIAL_LIBS=\n    SUNDIALS_CORE_CPPFLAGS=\n    SUNDIALS_CORE_LDFLAGS=\n    SUNDIALS_CORE_LIBS=\n    SUNDIALS_XCPPFLAGS=\n    SUNDIALS_XLDFLAGS=\n    SUNDIALS_XLIBS=\n    dnl Emit a fallback warning message in case SUNDIALS has been disabled for\n    dnl some reason that hasn't already generated one of these known warnings.\n    if test -z \"$warn_sundials_nvecserial\" && test -z \"$warn_sundials_ida\" \\\n        && test -z \"$warn_sundials_disabled\"; then\n      warn_sundials_disabled=\"SUNDIALS libraries are missing some feature.  The solvers ode15i and ode15s will be disabled.\"\n      OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])\n    fi\n  fi\nfi\n\nAC_SUBST(SUNDIALS_XCPPFLAGS)\nAC_SUBST(SUNDIALS_XLDFLAGS)\nAC_SUBST(SUNDIALS_XLIBS)\n\n### Check for ARPACK library.\n\nsave_LIBS=\"$LIBS\"\nLIBS=\"$LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS\"\nOCTAVE_CHECK_LIB([arpack], ARPACK,\n  [ARPACK not found.  The eigs function will be disabled.],\n  [],\n  [dseupd],\n  [Fortran 77], [don't use the ARPACK library, disable eigs function],\n  [warn_arpack=\n   OCTAVE_CHECK_LIB_ARPACK_OK_1(\n     [AC_DEFINE(HAVE_ARPACK, 1, [Define to 1 if ARPACK is available.])],\n     [warn_arpack=\"ARPACK library found, but does not seem to work properly; disabling eigs function\"])\n   if test -n \"$ARPACK_LIBS\"; then\n     OCTAVE_CHECK_LIB_ARPACK_OK_2([],\n       [AC_MSG_WARN([ARPACK library found, but is buggy; upgrade library (>= v3.3.0) for better results])])\n   fi\n   ])\nLIBS=\"$save_LIBS\"\n\n### Check for Java.\n\nbuild_java=yes\nAC_ARG_ENABLE([java],\n  [AS_HELP_STRING([--disable-java],\n    [disable Java interface])],\n  [if test \"$enableval\" = no; then\n     build_java=no\n   fi],\n  [])\n\nAC_ARG_WITH([java-homedir],\n  [AS_HELP_STRING([--with-java-homedir=DIR],\n    [Java JDK directory in DIR])],\n  [JAVA_HOMEDIR=\"$withval\"])\n\nAC_ARG_WITH([java-includedir],\n  [AS_HELP_STRING([--with-java-includedir=DIR],\n    [look for java include file <jni.h> in DIR])],\n  [JAVA_CPPFLAGS=\"$withval\"], [JAVA_CPPFLAGS=\"\"])\n\nAC_ARG_WITH([java-libdir],\n  [AS_HELP_STRING([--with-java-libdir=DIR],\n    [look for java library libjvm in DIR])],\n  [JAVA_LDPATH=\"$withval\"], [JAVA_LDPATH=\"\"])\n\n## Grab JAVA_HOME from environment variable if it exists\nAC_ARG_VAR([JAVA_HOME], [path to Java JDK installation])\n## But --with-java-homedir option overrides environment variable\nif test -n \"$JAVA_HOMEDIR\"; then\n  JAVA_HOME=$JAVA_HOMEDIR\nfi\nJAVA=\nJAVAC=\nJAR=\nJAVA_LIBS=\n\ndnl Fake loop so that \"break\" can be used to skip code blocks.\nwarn_java=\nwhile test $build_java = yes\ndo\n  ## Unset build_java.  Variable is set only if all configuration tests pass.\n  build_java=no\n\n  ## Warn if JAVA_HOME is unset.  It is *strongly* advised to specify JAVA_HOME.\n  if test -z \"$JAVA_HOME\"; then\n    warn_java_home=\"JAVA_HOME environment variable not initialized.  Auto-detection will proceed but is unreliable.\"\n    OCTAVE_CONFIGURE_WARNING([warn_java_home])\n  fi\n\n  ## Search for a viable Java executable.\n  if test -z \"$JAVA_HOME\"; then\n    JAVA_PATH=\"$PATH\"\n  else\n    JAVA_PATH=\"${JAVA_HOME}$PATH_SEPARATOR${JAVA_HOME}/jre/bin$PATH_SEPARATOR${JAVA_HOME}/bin$PATH_SEPARATOR${JAVA_HOME}/../bin$PATH_SEPARATOR${PATH}\"\n  fi\n  AC_PATH_PROG(JAVA, java, [], [$JAVA_PATH])\n\n  if test -z \"$JAVA\"; then\n    warn_java=\"No Java executable found.  Octave will not be able to call Java methods.\"\n    break\n  fi\n\n  if test -z \"$JAVA_HOME\"; then\n    ## Find JAVA_HOME for JRE by running java and querying properties.\n    java_tmp_home=`\"$JAVA\" -classpath ${srcdir}/build-aux OctJavaQry JAVA_HOME`\n    ## Strip directory back to top-level installation dir (JAVA_HOME for JDK).\n    JAVA_HOME=`echo $java_tmp_home | $SED -e 's|[[/\\\\]]bin[[/\\\\]]\\?$||' | $SED -e 's|[[/\\\\]]jre[[/\\\\]]\\?$||'`\n  fi\n\n  case $build_os in\n    mingw* | msdosmsvc)\n      ## Under Win32 platform, we want JAVA_HOME to be in MSYS format; that is,\n      ## without colon and backslashes, as it is also used as path separator.\n      ## Use quoted paths as Java may be installed in a path with whitespaces\n      ## (e.g., C:\\Program Files\\Java\\...).\n      if test -n \"$JAVA_HOME\"; then\n        JAVA_HOME=`cd \"$JAVA_HOME\" && pwd`\n      fi\n    ;;\n  esac\n\n  ## Amend search path for JAVAC and JAR.\n  if test -z \"$JAVA_HOME\"; then\n    JAVA_PATH=\"$PATH\"\n  else\n    JAVA_PATH=\"${JAVA_HOME}$PATH_SEPARATOR${JAVA_HOME}/bin$PATH_SEPARATOR${JAVA_HOME}/../bin$PATH_SEPARATOR${PATH}\"\n  fi\n\n  AC_PATH_PROG(JAVAC, javac, [], [$JAVA_PATH])\n  AC_PATH_PROG(JAR, jar, [], [$JAVA_PATH])\n\n  if test -z \"$JAVAC\" || test -z \"$JAR\"; then\n    warn_java=\"No javac compiler or jar executable found.  Octave will not be able to call Java methods.\"\n    break\n  fi\n\n  ## Check Java version is recent enough.\n  AC_CACHE_CHECK([for Java version],\n    [octave_cv_java_version],\n    [octave_cv_java_version=[`\"$JAVA\" -version 2>&1 | $SED -n -e 's/^[^ ]* version[^0-9\"]*\"\\([^\"]*\\)\".*/\\1/p'`]\n  ])\n\n  java_major=[`echo $octave_cv_java_version | $SED -e 's/^\\([0-9][0-9]*\\)\\.\\([0-9][0-9]*\\)\\..*$/\\1/'`]\n  java_minor=[`echo $octave_cv_java_version | $SED -e 's/^\\([0-9][0-9]*\\)\\.\\([0-9][0-9]*\\)\\..*$/\\2/'`]\n\n  if test $java_major -gt 1 || (test $java_major -eq 1 && test $java_minor -ge 9); then\n    :  # Version is OK.  Do nothing.\n  else\n    warn_java=\"Java version is too old (< 1.9).  Octave will not be able to call Java methods.\"\n    break\n  fi\n\n  ## At this point Win32 systems have enough configuration data.\n  ## We assume that all appropriate variables (e.g., INCLUDE and LIB) already\n  ## contain the required paths to compile and link against JDK.\n  case $host_os in\n    msdosmsvc)\n      build_java=yes\n      JAVA_LIBS=-ladvapi32\n      AC_DEFINE(HAVE_JAVA, 1,\n        [Define to 1 if Java is available and is at least version 1.5])\n      break\n    ;;\n    mingw* | cygwin*)\n      build_java=yes\n      JAVA_LIBS=-ladvapi32\n      if test $have_msvc = no; then\n        if test -n \"$JAVA_CPPFLAGS\"; then\n          JAVA_CPPFLAGS=\"-I\\\"${JAVA_CPPFLAGS}\\\" -I\\\"${JAVA_CPPFLAGS}/win32\\\"\"\n        else\n          JAVA_CPPFLAGS=\"-I\\\"${JAVA_HOME}/include\\\" -I\\\"${JAVA_HOME}/include/win32\\\"\"\n        fi\n      fi\n      AC_DEFINE(HAVE_JAVA, 1,\n        [Define to 1 if Java is available and is at least version 1.5])\n      break\n    ;;\n  esac\n\n  ## Determine which library filename to search for.\n  case $host_os in\n    darwin*)\n      jvmlib=libjvm.dylib\n    ;;\n    *)\n      jvmlib=libjvm.so\n    ;;\n  esac\n\n  AC_MSG_CHECKING([for $jvmlib])\n\n  AC_CACHE_VAL([octave_cv_java_ldpath],[\n    if test -z \"$JAVA_LDPATH\"; then\n      ## Run Java to try and determine library path to libjvm.so.\n      JAVA_TMP_LDPATH=`$JAVA -classpath ${srcdir}/build-aux OctJavaQry JAVA_LDPATH`\n      JAVA_TMP_LDPATH=`echo $JAVA_TMP_LDPATH | $SED -e \"s/${PATH_SEPARATOR}/ /g\"`\n      for dir in $JAVA_TMP_LDPATH; do\n        if test -f \"$dir/$jvmlib\"; then\n          JAVA_LDPATH=$dir\n          break\n        fi\n      done\n    fi\n\n    if test -z \"$JAVA_LDPATH\"; then\n      ## Nothing found.  Try Java again using bootpath argument.\n      JAVA_TMP_LDPATH=`$JAVA -classpath ${srcdir}/build-aux OctJavaQry JAVA_BOOTPATH`\n      JAVA_TMP_LDPATH=\"${JAVA_TMP_LDPATH} ${JAVA_TMP_LDPATH}/client ${JAVA_TMP_LDPATH}/server\"\n      for dir in $JAVA_TMP_LDPATH; do\n        if test -f \"$dir/$jvmlib\"; then\n          JAVA_LDPATH=$dir\n          break\n        fi\n      done\n    fi\n\n    if test -z \"$JAVA_LDPATH\"; then\n      ## Java failed to find its own library path.  Guess wildly.\n      JAVA_TMP_LDPATH=`ls -d $JAVA_HOME/jre/lib/*/client`\n      JAVA_TMP_LDPATH=\"${JAVA_TMP_LDPATH} `ls -d $JAVA_HOME/jre/lib/*/server`\"\n      ## Add some paths that might work on Macs.\n      JAVA_TMP_LDPATH=\"${JAVA_TMP_LDPATH} ${JAVA_HOME}/../Libraries ${JAVA_HOME}/Libraries\"\n      ## Add some paths that might work on MinGW\n      JAVA_TMP_LDPATH=\"${JAVA_TMP_LDPATH} ${JAVA_HOME}/bin/client ${JAVA_HOME}/bin/server\"\n      for dir in $JAVA_TMP_LDPATH; do\n        if test -f \"$dir/$jvmlib\"; then\n          JAVA_LDPATH=$dir\n          break\n        fi\n      done\n    fi\n\n    ## Verify value passed in option --with-java-libdir\n    if test -n \"$JAVA_LDPATH\"; then\n      if test -f \"${JAVA_LDPATH}/$jvmlib\"; then\n        :  # libjvm found\n      else\n        JAVA_LDPATH=\"\"\n      fi\n    fi\n\n    octave_cv_java_ldpath=$JAVA_LDPATH\n  ])\n  JAVA_LDPATH=$octave_cv_java_ldpath\n  if test -z \"$JAVA_LDPATH\"; then\n    AC_MSG_RESULT([not found])\n    warn_java=\"Library $jvmlib not found.  Octave will not be able to call Java methods.\"\n    break\n  else\n    AC_MSG_RESULT([$JAVA_LDPATH])\n  fi\n\n  AC_MSG_CHECKING([for include file <jni.h>])\n\n  ## Java and JVM found.  Set up flags.\n  case $host_os in\n    darwin*)\n      if test -n \"$JAVA_CPPFLAGS\"; then\n        JAVA_CPPFLAGS=\"-I${JAVA_CPPFLAGS} -I${JAVA_CPPFLAGS}/darwin\"\n      else\n        JAVA_CPPFLAGS=\"-I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin\"\n      fi\n    ;;\n    freebsd*)\n      if test -n \"$JAVA_CPPFLAGS\"; then\n        JAVA_CPPFLAGS=\"-I${JAVA_CPPFLAGS} -I${JAVA_CPPFLAGS}/freebsd\"\n      else\n        JAVA_CPPFLAGS=\"-I${JAVA_HOME}/include -I${JAVA_HOME}/include/freebsd\"\n      fi\n    ;;\n    solaris2*)\n      if test -n \"$JAVA_CPPFLAGS\"; then\n        JAVA_CPPFLAGS=\"-I${JAVA_CPPFLAGS} -I${JAVA_CPPFLAGS}/solaris\"\n      else\n        JAVA_CPPFLAGS=\"-I${JAVA_HOME}/include -I${JAVA_HOME}/include/solaris\"\n      fi\n    ;;\n    *)\n      if test -n \"$JAVA_CPPFLAGS\"; then\n        JAVA_CPPFLAGS=\"-I${JAVA_CPPFLAGS} -I${JAVA_CPPFLAGS}/linux\"\n      else\n        JAVA_CPPFLAGS=\"-I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux\"\n      fi\n    ;;\n  esac\n\n  ## Verify jni.h include file exists.\n  AC_CACHE_VAL([octave_cv_java_have_jni],[\n    JNI_PATH=`echo $JAVA_CPPFLAGS | $SED -e 's/-I//g'`\n    octave_cv_java_have_jni=no\n    for dir in $JNI_PATH; do\n      if test -f \"${dir}/jni.h\"; then\n        octave_cv_java_have_jni=yes\n        octave_cv_java_jni_h_path=$dir\n        break\n      fi\n    done\n  ])\n  if test $octave_cv_java_have_jni = yes; then\n    AC_MSG_RESULT([$octave_cv_java_jni_h_path])\n  else\n    AC_MSG_RESULT([not found])\n    warn_java=\"Include file <jni.h> not found.  Octave will not be able to call Java methods.\"\n    break\n  fi\n\n  ## Test if jar supports --date for reproducible builds\n  AC_CACHE_CHECK([whether jar supports '--date' option],\n    [octave_cv_jar_has_date_option],\n    [octave_cv_jar_has_date_option=no\n    if $JAR --help | $GREP -- '--date=' >/dev/null 2>&1; then\n      octave_cv_jar_has_date_option=yes\n    fi\n  ])\n  JAR_SUPPORTS_DATE=$octave_cv_jar_has_date_option\n\n  ## Passed all configuration tests.  A workable Java installation was found.\n  build_java=yes\n  AC_DEFINE(HAVE_JAVA, 1,\n    [Define to 1 if Java is available and is at least version 1.5])\n  break\ndone\nif test -n \"$warn_java\"; then\n  OCTAVE_CONFIGURE_WARNING([warn_java])\nfi\n\nAM_CONDITIONAL([AMCOND_HAVE_JAVA], [test $build_java = yes])\nAC_SUBST(JAVA)\nAC_SUBST(JAVAC)\nAC_SUBST(JAR)\nAC_SUBST(JAR_SUPPORTS_DATE)\nAC_SUBST(JAVA_CPPFLAGS)\nAC_SUBST(JAVA_LIBS)\nAC_DEFINE_UNQUOTED([JAVA_HOME], [\"$JAVA_HOME\"], [Java home (top-level installation dir)])\nAC_DEFINE_UNQUOTED([JAVA_LDPATH], [\"$JAVA_LDPATH\"], [Java library path (libjvm)])\n\n### Determine if documentation should and can be built.\n\nENABLE_DOCS=yes\nAC_ARG_ENABLE([docs],\n  [AS_HELP_STRING([--disable-docs], [don't build documentation files])],\n  [if test \"$enableval\" = no; then\n     ENABLE_DOCS=no\n     warn_docs=\"building documentation disabled; make dist will fail.\"\n     OCTAVE_CONFIGURE_WARNING([warn_docs])\n   fi], [])\n\nif test $ENABLE_DOCS = yes; then\n  if test $opengl_graphics = no; then\n    if test -n \"$warn_gnuplot\"; then\n      ENABLE_DOCS=no\n      warn_docs_graphics=\"building documentation disabled because no suitable graphics toolkit is available; make dist will fail.\"\n      OCTAVE_CONFIGURE_WARNING([warn_docs_graphics])\n    fi\n  fi\n  if test -n \"$warn_makeinfo\"; then\n    ENABLE_DOCS=no\n    warn_docs_makeinfo=\"building documentation disabled because makeinfo was not found or does not support @sortas; make dist will fail.\"\n    OCTAVE_CONFIGURE_WARNING([warn_docs_makeinfo])\n  fi\nfi\nif test $ENABLE_DOCS = yes; then\n  AC_DEFINE(ENABLE_DOCS, 1,\n    [Define to 1 to build Octave documentation files.])\nfi\n\nAM_CONDITIONAL([AMCOND_BUILD_DOCS], [test $ENABLE_DOCS = yes])\n\nAM_CONDITIONAL([AMCOND_BUILD_QT_DOCS],\n               [test $ENABLE_DOCS = yes && test $build_qt_gui = yes])\n\nOCTAVE_RELOCATE_ALL=no\nAC_ARG_ENABLE([relocate-all],\n  [AS_HELP_STRING([--enable-relocate-all],\n    [assume that all dependencies that are installed under the same prefix are relocated when Octave is relocated])],\n  [if test \"$enableval\" = yes; then OCTAVE_RELOCATE_ALL=yes; fi], [])\nAC_SUBST(OCTAVE_RELOCATE_ALL)\nif test $OCTAVE_RELOCATE_ALL = yes; then\n  AC_DEFINE(OCTAVE_REPLACE_PREFIX, 1, [Replace prefix in mkoctfile flags.])\nfi\nAM_CONDITIONAL([AMCOND_RELOCATE_ALL], [test $OCTAVE_RELOCATE_ALL = yes])\n\nOCTAVE_RELOCATE_WITH_CYGPATH=\"no\"\nCYGPATH=\"\"\nif test $OCTAVE_RELOCATE_ALL = yes; then\n  case $host_os in\n    mingw*)\n      # If this is on MSYS2, paths (including the installation prefix) can be\n      # represented in UNIX or Windows compatible form.  The prefix should be\n      # relocated no matter in which form it appears.\n\n      # Check for the tool \"cygpath\" that can be used to convert between the\n      # different forms.\n      AC_CHECK_TOOL(CYGPATH, [cygpath])\n      if test -n \"$CYGPATH\"; then\n        OCTAVE_RELOCATE_WITH_CYGPATH=\"yes\"\n      fi\n    ;;\n  esac\nfi\nAC_SUBST(OCTAVE_RELOCATE_WITH_CYGPATH)\nAC_SUBST(CYGPATH)\n\n### Determine whether Mercurial ID should be embedded in library binaries.\n\nENABLE_HG_ID=yes\nAC_ARG_ENABLE([hg-id],\n  [AS_HELP_STRING([--disable-hg-id],\n    [disable embedding of hg id in libraries])],\n  [if test \"$enableval\" = no; then ENABLE_HG_ID=no; fi], [])\nAM_CONDITIONAL([AMCOND_ENABLE_HG_ID], [test $ENABLE_HG_ID = yes])\n\n### Determine whether to install build logs with Octave.\n\ninstall_build_logs=no\nAC_ARG_ENABLE([install-build-logs],\n  [AS_HELP_STRING([--enable-install-build-logs],\n    [install build logs (i.e., config.log) with Octave])],\n  [if test \"$enableval\" = yes; then install_build_logs=yes; fi])\nAM_CONDITIONAL([AMCOND_INSTALL_BUILD_LOGS], [test $install_build_logs = yes])\n\n### Determine whether libraries should be linked with visibility attributes.\n\nENABLE_LIB_VISIBILITY_FLAGS=yes\nAC_ARG_ENABLE(lib-visibility-flags,\n  [AS_HELP_STRING([--disable-lib-visibility-flags],\n    [don't build libraries with visibility flags (export all symbols)])],\n  [case $enableval in\n     yes) ENABLE_LIB_VISIBILITY_FLAGS=yes ;;\n     no) ENABLE_LIB_VISIBILITY_FLAGS=no ;;\n     *) AC_MSG_ERROR([bad value $enableval for --enable-lib-visibility-flags]) ;;\n   esac])\n\ncase $host_os in\n  msdosmsvc | mingw* | cygwin*)\n    # Assume that symbol export is working on that platform\n  ;;\n  *)\n    if test $ENABLE_LIB_VISIBILITY_FLAGS = yes && test $HAVE_VISIBILITY = 0; then\n      AC_MSG_NOTICE([cannot build with visibility flags on this platform])\n      ENABLE_LIB_VISIBILITY_FLAGS=no\n    fi\n  ;;\nesac\n\nif test $ENABLE_LIB_VISIBILITY_FLAGS = yes; then\n  AC_DEFINE(OCTAVE_ENABLE_LIB_VISIBILITY_FLAGS, 1,\n    [Define to 1 if building libraries with visibility flags])\nelse\n  case $host_os in\n    msdosmsvc | mingw* | cygwin*)\n      LDFLAGS=\"$LDFLAGS -Wl,--export-all-symbols\"\n    ;;\n  esac\nfi\n\nAM_CONDITIONAL([AMCOND_LIB_VISIBILITY_FLAGS],\n  [test $ENABLE_LIB_VISIBILITY_FLAGS = yes])\n\n### Set flags for symbol visibility.\n\nif test $ENABLE_LIB_VISIBILITY_FLAGS = yes; then\n  EXTERNAL_DLL_DEFS=\"-DEXTERNAL_DLL\"\n  OCTAVE_DLL_DEFS=\"-DOCTAVE_DLL\"\n  OCTINTERP_DLL_DEFS=\"-DOCTINTERP_DLL\"\n  OCTMEX_DLL_DEFS=\"-DOCTMEX_DLL\"\n  OCTGUI_DLL_DEFS=\"-DOCTGUI_DLL\"\nelse\n  EXTERNAL_DLL_DEFS=\n  OCTAVE_DLL_DEFS=\n  OCTINTERP_DLL_DEFS=\n  OCTMEX_DLL_DEFS=\n  OCTGUI_DLL_DEFS=\nfi\nAC_MSG_NOTICE([defining EXTERNAL_DLL_DEFS to be $EXTERNAL_DLL_DEFS])\nAC_MSG_NOTICE([defining OCTAVE_DLL_DEFS to be $OCTAVE_DLL_DEFS])\nAC_MSG_NOTICE([defining OCTINTERP_DLL_DEFS to be $OCTINTERP_DLL_DEFS])\nAC_MSG_NOTICE([defining OCTMEX_DLL_DEFS to be $OCTMEX_DLL_DEFS])\nAC_MSG_NOTICE([defining OCTGUI_DLL_DEFS to be $OCTGUI_DLL_DEFS])\n\nAC_SUBST(EXTERNAL_DLL_DEFS)\nAC_SUBST(OCTAVE_DLL_DEFS)\nAC_SUBST(OCTINTERP_DLL_DEFS)\nAC_SUBST(OCTMEX_DLL_DEFS)\nAC_SUBST(OCTGUI_DLL_DEFS)\n\n### Add extra compiler flags now that feature testing is complete.\n\n## Add warning flags\n\nGCC_EXTRA_FLAGS=\"-Wall -W -Wshadow -Wformat -Wpointer-arith -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings -Wcast-align -Wcast-qual\"\nGXX_EXTRA_FLAGS=\"-Wall -W -Wshadow -Woverloaded-virtual -Wold-style-cast -Wformat -Wpointer-arith -Wwrite-strings -Wcast-align -Wcast-qual\"\n\ntry_extra_warning_flags=yes\nAC_ARG_ENABLE([extra-warning-flags],\n  [AS_HELP_STRING([--disable-extra-warning-flags],\n    [don't add -Wall, -W, -Wformat, -Wold-style-cast, and other warning options to CFLAGS and CXXFLAGS])],\n  [if test \"$enableval\" = no; then\n     try_extra_warning_flags=no\n   fi],\n  [])\n\nif test $try_extra_warning_flags = yes; then\n  for flag in $GCC_EXTRA_FLAGS; do\n    OCTAVE_CC_FLAG([$flag], [\n      WARN_CFLAGS=\"$WARN_CFLAGS $flag\";\n      AC_MSG_RESULT([adding $flag to WARN_CFLAGS])])\n  done\n  for flag in $GXX_EXTRA_FLAGS; do\n    OCTAVE_CXX_FLAG([$flag], [\n      WARN_CXXFLAGS=\"$WARN_CXXFLAGS $flag\";\n      AC_MSG_RESULT([adding $flag to WARN_CXXFLAGS])])\n  done\nfi\n\n## Add strict warning flags\nGCC_STRICT_FLAGS=\"-Wconversion\"\nGXX_STRICT_FLAGS=\"-Wconversion -Weffc++\"\n\ntry_strict_warning_flags=no\nAC_ARG_ENABLE([strict-warning-flags],\n  [AS_HELP_STRING([--enable-strict-warning-flags],\n    [add extra strict warning options to CFLAGS and CXXFLAGS])],\n  [if test \"$enableval\" = yes; then\n     try_strict_warning_flags=yes\n   fi],\n  [])\n\nif test $try_strict_warning_flags = yes; then\n  for flag in $GCC_STRICT_FLAGS; do\n    OCTAVE_CC_FLAG([$flag], [\n      WARN_CFLAGS=\"$WARN_CFLAGS $flag\";\n      AC_MSG_RESULT([adding $flag to WARN_CFLAGS])])\n  done\n  for flag in $GXX_STRICT_FLAGS; do\n    OCTAVE_CXX_FLAG([$flag], [\n      WARN_CXXFLAGS=\"$WARN_CXXFLAGS $flag\";\n      AC_MSG_RESULT([adding $flag to WARN_CXXFLAGS])])\n  done\nfi\n\n## Add sanitizer flags\nGCC_ADDRESS_SANITIZER_FLAGS=\"-fsanitize=address -fno-omit-frame-pointer\"\nGXX_ADDRESS_SANITIZER_FLAGS=\"-fsanitize=address -fno-omit-frame-pointer\"\nLD_ADDRESS_SANITIZER_FLAGS=\"-fsanitize=address\"\n\ntry_address_sanitizer_flags=no\nAC_ARG_ENABLE([address-sanitizer-flags],\n  [AS_HELP_STRING([--enable-address-sanitizer-flags],\n    [add extra -fsanitize=address and -fno-omit-frame-pointer options to CFLAGS, CXXFLAGS, and LDFLAGS])],\n  [if test \"$enableval\" = yes; then\n     try_address_sanitizer_flags=yes\n   fi],\n  [])\n\nif test $try_address_sanitizer_flags = yes; then\n  ADDRESS_SANITIZER_OPTIONS=\"symbolize=1\"\n  AC_SUBST(ADDRESS_SANITIZER_OPTIONS)\nfi\n\nAM_CONDITIONAL([AMCOND_ADDRESS_SANITIZER_ENABLED],\n  [test $try_address_sanitizer_flags = yes])\n\nADDRESS_SANITIZER_ENABLED=no\nif test $try_address_sanitizer_flags = yes; then\n  ADDRESS_SANITIZER_ENABLED=yes\n  for flag in $GCC_ADDRESS_SANITIZER_FLAGS; do\n    OCTAVE_CC_FLAG([$flag], [\n      XTRA_CFLAGS=\"$XTRA_CFLAGS $flag\";\n      AC_MSG_RESULT([adding $flag to XTRA_CFLAGS])])\n  done\n  for flag in $GXX_ADDRESS_SANITIZER_FLAGS; do\n    OCTAVE_CXX_FLAG([$flag], [\n      XTRA_CXXFLAGS=\"$XTRA_CXXFLAGS $flag\";\n      AC_MSG_RESULT([adding $flag to XTRA_CXXFLAGS])])\n  done\n  dnl FIXME: do we really need an LD-specific test, or is this good enough?\n  for flag in $LD_ADDRESS_SANITIZER_FLAGS; do\n    OCTAVE_CC_FLAG([$flag], [\n      XTRA_LDFLAGS=\"$XTRA_LDFLAGS $flag\";\n      AC_MSG_RESULT([adding $flag to XTRA_LDFLAGS])])\n  done\nfi\nAC_SUBST(ADDRESS_SANITIZER_ENABLED)\n\nAC_SUBST(WARN_CFLAGS)\nAC_SUBST(WARN_CXXFLAGS)\nAC_SUBST(WARN_LDFLAGS)\n\n### Check for GCC-specific pragmas to control warnings.\n\nAC_LANG_PUSH(C++)\nAC_CACHE_CHECK([for @%:@pragma GCC diagnostic push/pop/ignored],\n  [octave_cv_gcc_has_pragma_GCC_diagnostic],\n  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n  int three = (int) 3.1415926;\n#pragma GCC diagnostic pop\n    ]])],\n    [octave_cv_gcc_has_pragma_GCC_diagnostic=yes],\n    [octave_cv_gcc_has_pragma_GCC_diagnostic=no])],\n  ])\nAC_LANG_POP(C++)\n\nif test $octave_cv_gcc_has_pragma_GCC_diagnostic = yes; then\n  AC_DEFINE(HAVE_PRAGMA_GCC_DIAGNOSTIC, 1,\n    [Define to 1 if compiler supports @%:@pragma GCC diagnostic ...])\nfi\n\nAC_CACHE_CHECK([for @%:@pragma GCC visibility push/pop],\n  [octave_cv_gcc_has_pragma_GCC_visiblity],\n  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[\n#pragma GCC visibility push(default)\n  int three = 3;\n#pragma GCC visiblity pop(default)\n    ]])],\n    [octave_cv_gcc_has_pragma_GCC_visiblity=yes],\n    [octave_cv_gcc_has_pragma_GCC_visiblity=no])],\n  ])\n\nif test $octave_cv_gcc_has_pragma_GCC_visiblity = yes; then\n  AC_DEFINE(HAVE_PRAGMA_GCC_VISIBILITY, 1,\n    [Define to 1 if compiler supports @%:@pragma GCC visiblity ...])\nfi\n\n## Check for one unusual warning used in pragmas that is not always available\nif test $octave_cv_gcc_has_pragma_GCC_diagnostic = yes; then\n  OCTAVE_CC_FLAG([-Wimplicit-fallthrough],\n    [AC_DEFINE(HAVE_WARN_IMPLICIT_FALLTHROUGH, 1,\n      [Define to 1 if compiler supports -Wimplicit-fallthrough warning])])\nfi\n\n### Recommendations from the gnulib bootstrap script.\n\n## Notes\n## 1) Because Octave uses libtool the version of the variable for certain\n##    libraries has the prefix $LT.\n## 2) The readline library ($LTLIBREADLINE) is used in liboctinterp, not\n##    liboctave, and is therefore not in this list.\n\nGNULIB_LINK_DEPS=\"$CLOCK_TIME_LIB $FREXPF_LIBM $FREXP_LIBM $GETHOSTNAME_LIB $GETHRXTIME_LIB $GETLOCALENAME_L_LIB $GETLOGIN_LIB $GETRANDOM_LIB $HARD_LOCALE_LIB $LIBPTHREAD $LIBSOCKET $LIBTHREAD $LIB_CRYPTO $LTLIBC32CONV $LTLIBICONV $LTLIBINTL $LTLIBUNISTRING $MBRTOWC_LIB $NANOSLEEP_LIB $POSIX_SPAWN_LIB $PTHREAD_ONCE_LIB $PTHREAD_SIGMASK_LIB $SELECT_LIB $SETLOCALE_LIB $SETLOCALE_NULL_LIB $INTL_MACOSX_LIBS\"\n\n## FIXME: This is a kluge to transform $libdir/libiconv.dll.a to -liconv.\n## It would probably be better to fix gnulib to not give us an absolute\n## file name...\n\ncase $host_os in\n  mingw*)\n    ## Don't use $libdir here because that's defined to be\n    ## ${exec_prefix}/lib and at this point, ${exec_prefix} is \"NONE\"!\n    tmp_libiconv_dll=\"$LIBICONV_PREFIX/lib/libiconv.dll.a\"\n    MKOCTFILE_LIBICONV=`echo $LIBICONV | sed \"s|$tmp_libiconv_dll|-liconv|\"`\n  ;;\n  *)\n    MKOCTFILE_LIBICONV=\"$LIBICONV\"\n  ;;\nesac\n\n## The build system does *not* use libtool for building `mkoctfile`.\n## Therefore the variable for certain libraries does not use prefix $LT.\n\nMKOCTFILE_GNULIB_LINK_DEPS=\"$CLOCK_TIME_LIB $FREXPF_LIBM $FREXP_LIBM $GETHOSTNAME_LIB $GETHRXTIME_LIB $GETLOCALENAME_L_LIB $GETLOGIN_LIB $GETRANDOM_LIB $HARD_LOCALE_LIB $LIBPTHREAD $LIBSOCKET $LIBTHREAD $LIB_CRYPTO $LIBC32CONV $MKOCTFILE_LIBICONV $LIBINTL $LIBUNISTRING $MBRTOWC_LIB $NANOSLEEP_LIB $POSIX_SPAWN_LIB $PTHREAD_ONCE_LIB $PTHREAD_SIGMASK_LIB $SELECT_LIB $SETLOCALE_LIB $SETLOCALE_NULL_LIB $INTL_MACOSX_LIBS\"\n\nAC_SUBST(GNULIB_LINK_DEPS)\n\n### Set variables for link dependencies and options.\n\nBASE_LIBOCTAVE_LINK_DEPS=\"$CURL_LIBS $LIBGLOB $PCRE_LIBS $FFTW_XLIBS $ARPACK_LIBS $QRUPDATE_LIBS $SPARSE_XLIBS $LAPACK_LIBS $BLAS_LIBS $DL_LIBS $FLIBS $PTHREAD_LIBS $LIBS\"\n\nLIBOCTAVE_LINK_DEPS=\"$BASE_LIBOCTAVE_LINK_DEPS $GNULIB_LINK_DEPS\"\n\nMKOCTFILE_LIBOCTAVE_LINK_DEPS=\"$BASE_LIBOCTAVE_LINK_DEPS $MKOCTFILE_GNULIB_LINK_DEPS\"\n\nLIBOCTAVE_LINK_OPTS=\"$CURL_LDFLAGS $PCRE_LDFLAGS $FFTW_XLDFLAGS $ARPACK_LDFLAGS $QRUPDATE_LDFLAGS $SPARSE_XLDFLAGS\"\n\nAC_SUBST(LIBOCTAVE_LINK_DEPS)\nAC_SUBST(LIBOCTAVE_LINK_OPTS)\n\nLIBOCTINTERP_LINK_DEPS=\"$LTLIBREADLINE $HDF5_LIBS $MAGICK_LIBS $Z_LIBS $FFTW_XLIBS $SPARSE_XLIBS $FONTCONFIG_LIBS $FT2_LIBS $FREETYPE_LIBS $WAYLAND_CLIENT_LIBS $X11_LIBS $CARBON_LIBS $GL2PS_LIBS $OPENGL_LIBS $JAVA_LIBS $LAPACK_LIBS\"\n\nLIBOCTINTERP_LINK_OPTS=\"$HDF5_LDFLAGS $MAGICK_LDFLAGS $Z_LDFLAGS $FFTW_XLDFLAGS $SPARSE_XLDFLAGS $FT2_LDFLAGS $WAYLAND_CLIENT_LDFLAGS\"\n\nOCTAVE_LINK_DEPS=\"\"\nOCTAVE_LINK_OPTS=\"\"\n\nOCT_LINK_DEPS=\"\"\nOCT_LTLINK_DEPS=\"\"\nOCT_GUI_LINK_DEPS=\"\"\n\nOCT_LINK_OPTS=\"$LDFLAGS\"\nOCT_GUI_LINK_OPTS=\"$LDFLAGS\"\n\nif test $link_all_deps = yes; then\n  AC_DEFINE(OCTAVE_LINK_ALL_DEPS, 1, [Link with all dependencies.])\n\n  OCT_LINK_DEPS=\"libinterp/liboctinterp.la liboctave/liboctave.la\"\n  OCT_LTLINK_DEPS=\"$OCT_LINK_DEPS\"\n  OCT_GUI_LINK_DEPS=\"libgui/liboctgui.la $OCT_LINK_DEPS\"\n\n  MKOCTFILE_OCTAVE_LINK_DEPS=\"$LIBOCTINTERP_LINK_DEPS $MKOCTFILE_LIBOCTAVE_LINK_DEPS\"\n  MKOCTFILE_OCT_LINK_DEPS=\"-L${octlibdir} $LIBOCTINTERP $LIBOCTAVE\"\n\n  LIBOCTINTERP_LINK_DEPS=\"$LIBOCTINTERP_LINK_DEPS $LIBOCTAVE_LINK_DEPS\"\n  LIBOCTINTERP_LINK_OPTS=\"$LIBOCTINTERP_LINK_OPTS $LIBOCTAVE_LINK_OPTS\"\n\n  OCTAVE_LINK_DEPS=\"$LIBOCTINTERP_LINK_DEPS\"\n  OCTAVE_LINK_OPTS=\"$LIBOCTINTERP_LINK_OPTS\"\nelse\n  case $host_os in\n    mingw* | msdosmsvc)\n      OCT_LINK_DEPS=\"libinterp/liboctinterp.la liboctave/liboctave.la\"\n      OCT_LTLINK_DEPS=\"$OCT_LINK_DEPS\"\n      OCT_GUI_LINK_DEPS=\"libgui/liboctgui.la $OCT_LINK_DEPS\"\n\n      MKOCTFILE_OCT_LINK_DEPS=\"-L${octlibdir} $LIBOCTINTERP $LIBOCTAVE\"\n    ;;\n    darwin*)\n      dnl Contains variables that are defined and undefined at this point,\n      dnl so use appropriate quoting to defer expansion of\n      dnl ${abs_top_builddir}, ${bindir}, and ${version}.\n      OCT_LINK_DEPS='-bundle_loader ${abs_top_builddir}/src/octave'\"${EXEEXT}\"\n      MKOCTFILE_OCT_LINK_DEPS='-bundle_loader ${bindir}/octave-${version}'\"${EXEEXT}\"\n    ;;\n  esac\nfi\n\nAC_SUBST(LIBOCTINTERP_LINK_DEPS)\nAC_SUBST(LIBOCTINTERP_LINK_OPTS)\n\nAC_SUBST(OCTAVE_LINK_DEPS)\nAC_SUBST(OCTAVE_LINK_OPTS)\n\nAC_SUBST(OCT_LINK_DEPS)\nAC_SUBST(OCT_LTLINK_DEPS)\nAC_SUBST(OCT_LINK_OPTS)\n\nAC_SUBST(OCT_GUI_LINK_DEPS)\nAC_SUBST(OCT_GUI_LINK_OPTS)\n\nAC_SUBST(MKOCTFILE_OCTAVE_LINK_DEPS)\nAC_SUBST(MKOCTFILE_OCT_LINK_DEPS)\n\nLIBOCTGUI_LINK_DEPS=\"\"\nLIBOCTGUI_LINK_OPTS=\"\"\n\nOCTAVE_GUI_LINK_DEPS=\"\"\nOCTAVE_GUI_LINK_OPTS=\"\"\n\nif test $build_qt_gui = yes; then\n  LIBOCTGUI_LINK_DEPS=\"$QT_LIBS\"\n  LIBOCTGUI_LINK_OPTS=\"$QT_LDFLAGS\"\n\n  if test $link_all_deps = yes || test -n \"$QT_LDFLAGS\"; then\n    LIBOCTGUI_LINK_DEPS=\"$LIBOCTGUI_LINK_DEPS $LIBOCTINTERP_LINK_DEPS\"\n    LIBOCTGUI_LINK_OPTS=\"$LIBOCTGUI_LINK_OPTS $LIBOCTINTERP_LINK_OPTS\"\n\n    OCTAVE_GUI_LINK_DEPS=\"$OCTAVE_GUI_LINK_DEPS $LIBOCTGUI_LINK_DEPS\"\n    OCTAVE_GUI_LINK_OPTS=\"$OCTAVE_GUI_LINK_OPTS $LIBOCTGUI_LINK_OPTS\"\n  fi\nfi\n\nAC_SUBST(LIBOCTGUI_LINK_DEPS)\nAC_SUBST(LIBOCTGUI_LINK_OPTS)\n\nAC_SUBST(OCTAVE_GUI_LINK_DEPS)\nAC_SUBST(OCTAVE_GUI_LINK_OPTS)\n\n##############################################################################\n### Configuration tests done.\n\n### Restore original compilation flags.\nCFLAGS=\"$original_octave_configure_CFLAGS\"\nCXXFLAGS=\"$original_octave_configure_CXXFLAGS\"\n\n### Add footer to config.h\n\nAH_BOTTOM([#include \"oct-conf-post-private.h\"])\nAH_BOTTOM([#include \"oct-conf-post-public.h\"])\n\n### Make all AC_DEFINES available to testif feature of test.m function.\ndnl This must reside at the bottom of configure.ac after all AC_DEFINES\ndnl have been made.\n\nAC_OUTPUT_MAKE_DEFS\n\nAC_CONFIG_COMMANDS_PRE([\n  ## Fully expand all directory variables.  These are normally left\n  ## unexpanded (as explained and recommended by the autoconf manual).\n  ## But we store configuration info in files and expect whatever\n  ## is set at configure time to stay the same when Make is executed.\n  ## Doing things like\n  ##\n  ##   configure --prefix=/some/where\n  ##   make --prefix=/some/where/else\n  ##\n  ## won't work properly and is not allowed when building Octave.\n\n  eval prefix=\"\\\"$prefix\\\"\"\n  eval exec_prefix=\"\\\"$exec_prefix\\\"\"\n  eval bindir=\"\\\"$bindir\\\"\"\n  eval sbindir=\"\\\"$sbindir\\\"\"\n  eval libexecdir=\"\\\"$libexecdir\\\"\"\n  eval datarootdir=\"\\\"$datarootdir\\\"\"\n  eval datadir=\"\\\"$datadir\\\"\"\n  eval sysconfdir=\"\\\"$sysconfdir\\\"\"\n  eval sharedstatedir=\"\\\"$sharedstatedir\\\"\"\n  eval localstatedir=\"\\\"$localstatedir\\\"\"\n  eval runstatedir=\"\\\"$runstatedir\\\"\"\n  eval includedir=\"\\\"$includedir\\\"\"\n  eval oldincludedir=\"\\\"$oldincludedir\\\"\"\n  eval docdir=\"\\\"$docdir\\\"\"\n  eval infodir=\"\\\"$infodir\\\"\"\n  eval htmldir=\"\\\"$htmldir\\\"\"\n  eval dvidir=\"\\\"$dvidir\\\"\"\n  eval pdfdir=\"\\\"$pdfdir\\\"\"\n  eval psdir=\"\\\"$psdir\\\"\"\n  eval libdir=\"\\\"$libdir\\\"\"\n  eval localedir=\"\\\"$localedir\\\"\"\n  eval mandir=\"\\\"$mandir\\\"\"\n\n  version=\"$OCTAVE_VERSION\"\n  api_version=\"$OCTAVE_API_VERSION\"\n\n  eval octlibdir=\"\\\"$octlibdir\\\"\"\n  eval archlibdir=\"\\\"$archlibdir\\\"\"\n  eval localarchlibdir=\"\\\"$localarchlibdir\\\"\"\n  eval localapiarchlibdir=\"\\\"$localapiarchlibdir\\\"\"\n  eval localverarchlibdir=\"\\\"$localverarchlibdir\\\"\"\n  eval octfiledir=\"\\\"$octfiledir\\\"\"\n  eval localoctfiledir=\"\\\"$localoctfiledir\\\"\"\n  eval localapioctfiledir=\"\\\"$localapioctfiledir\\\"\"\n  eval localveroctfiledir=\"\\\"$localveroctfiledir\\\"\"\n  eval octincludedir=\"\\\"$octincludedir\\\"\"\n  eval fcnfiledir=\"\\\"$fcnfiledir\\\"\"\n  eval localfcnfiledir=\"\\\"$localfcnfiledir\\\"\"\n  eval localapifcnfiledir=\"\\\"$localapifcnfiledir\\\"\"\n  eval localverfcnfiledir=\"\\\"$localverfcnfiledir\\\"\"\n  eval octetcdir=\"\\\"$octetcdir\\\"\"\n  eval octlocaledir=\"\\\"$octlocaledir\\\"\"\n  eval doc_cache_file=\"\\\"$doc_cache_file\\\"\"\n  eval octtestsdir=\"\\\"$octtestsdir\\\"\"\n  eval texi_macros_file=\"\\\"$texi_macros_file\\\"\"\n  eval imagedir=\"\\\"$imagedir\\\"\"\n  eval octdatadir=\"\\\"$octdatadir\\\"\"\n  eval octdocdir=\"\\\"$octdocdir\\\"\"\n  eval octfontsdir=\"\\\"$octfontsdir\\\"\"\n  eval startupfiledir=\"\\\"$startupfiledir\\\"\"\n  eval localstartupfiledir=\"\\\"$localstartupfiledir\\\"\"\n  eval localapipkgdir=\"\\\"$localapipkgdir\\\"\"\n  eval man1dir=\"\\\"$man1dir\\\"\"\n  eval man1ext=\"\\\"$man1ext\\\"\"\n  eval infofile=\"\\\"$infofile\\\"\"\n\n  ## Also expand the following variables because they may depend on the values\n  ## of variables expanded above.\n\n  eval MKOCTFILE_DL_LDFLAGS=\"\\\"$MKOCTFILE_DL_LDFLAGS\\\"\"\n  eval MKOCTFILE_OCT_LINK_DEPS=\"\\\"$MKOCTFILE_OCT_LINK_DEPS\\\"\"\n])\n\n### Do substitutions in Makefiles and other files that hold configuration info.\n\nAUTOCONF_SUBST_VARS=\"`echo $ac_subst_vars`\"\n\nAC_SUBST(AUTOCONF_SUBST_VARS)\nAC_SUBST(ac_config_files)\nAC_SUBST(ac_config_headers)\n\nAC_CONFIG_FILES([\n  Makefile\n  build-aux/check-subst-vars.sh:build-aux/check-subst-vars.in.sh\n  build-aux/find-defun-files.sh:build-aux/find-defun-files.in.sh\n  build-aux/find-files-with-tests.sh:build-aux/find-files-with-tests.in.sh\n  doc/doxyhtml/Doxyfile\n  libgnu/Makefile\n  test/Makefile\n  liboctave/octave.pc:liboctave/octave.in.pc\n  libinterp/octinterp.pc:libinterp/octinterp.in.pc\n  libmex/octmex.pc:libmex/octmex.in.pc])\n\ndnl We use a .in.h file for oct-conf-post-private.h and\ndnl oct-conf-post-public.h simply to copy it to the build tree\ndnl so that we don't have to add the -I${top_srcdir} to any CPPFLAGS variables.\n\nAC_CONFIG_FILES([\n  oct-conf-post-private.h-tmp:oct-conf-post-private.in.h\n  oct-conf-post-public.h-tmp:oct-conf-post-public.in.h])\n\nAC_CONFIG_COMMANDS([oct-conf-post-private.h],\n  [$SHELL $srcdir/build-aux/move-if-change oct-conf-post-private.h-tmp oct-conf-post-private.h])\n\nAC_CONFIG_COMMANDS([oct-conf-post-public.h],\n  [$SHELL $srcdir/build-aux/move-if-change oct-conf-post-public.h-tmp oct-conf-post-public.h])\n\nOCTAVE_CONFIG_MOVE_IF_CHANGE_FILES([\n  liboctave/external/mk-f77-def.sh\n  liboctave/mk-version-h.sh\n  libinterp/corefcn/mk-mxtypes-h.sh\n  build-aux/subst-config-vals.sh\n  build-aux/subst-cross-config-vals.sh\n  build-aux/subst-script-vals.sh])\n\nAC_OUTPUT\n\n### Print a summary of the build configuration.\n\nAC_MSG_NOTICE([\n\nOctave is now configured for $canonical_host_type\n\n  Source directory:              $srcdir\n  Installation prefix:           $prefix\n  C compiler:                    $CC $XTRA_CFLAGS $WARN_CFLAGS $CFLAGS\n  C++ compiler:                  $CXX $XTRA_CXXFLAGS $WARN_CXXFLAGS $CXXFLAGS\n  Fortran compiler:              $F77 $FFLAGS\n  CPPFLAGS:                      $CPPFLAGS\n  Fortran libraries:             $FLIBS\n  Lex libraries:                 $LEXLIB\n  LIBS:                          $LIBS\n  LDFLAGS:                       $LDFLAGS\n  Extra LDFLAGS:                 $XTRA_LDFLAGS $WARN_LDFLAGS\n\n  AMD CPPFLAGS:                  $AMD_CPPFLAGS\n  AMD LDFLAGS:                   $AMD_LDFLAGS\n  AMD libraries:                 $AMD_LIBS\n  ARPACK CPPFLAGS:               $ARPACK_CPPFLAGS\n  ARPACK LDFLAGS:                $ARPACK_LDFLAGS\n  ARPACK libraries:              $ARPACK_LIBS\n  BLAS libraries:                $BLAS_LIBS\n  BZ2 CPPFLAGS:                  $BZ2_CPPFLAGS\n  BZ2 LDFLAGS:                   $BZ2_LDFLAGS\n  BZ2 libraries:                 $BZ2_LIBS\n  CAMD CPPFLAGS:                 $CAMD_CPPFLAGS\n  CAMD LDFLAGS:                  $CAMD_LDFLAGS\n  CAMD libraries:                $CAMD_LIBS\n  CARBON libraries:              $CARBON_LIBS\n  CCOLAMD CPPFLAGS:              $CCOLAMD_CPPFLAGS\n  CCOLAMD LDFLAGS:               $CCOLAMD_LDFLAGS\n  CCOLAMD libraries:             $CCOLAMD_LIBS\n  CHOLMOD CPPFLAGS:              $CHOLMOD_CPPFLAGS\n  CHOLMOD LDFLAGS:               $CHOLMOD_LDFLAGS\n  CHOLMOD libraries:             $CHOLMOD_LIBS\n  COLAMD CPPFLAGS:               $COLAMD_CPPFLAGS\n  COLAMD LDFLAGS:                $COLAMD_LDFLAGS\n  COLAMD libraries:              $COLAMD_LIBS\n  CURL CPPFLAGS:                 $CURL_CPPFLAGS\n  CURL LDFLAGS:                  $CURL_LDFLAGS\n  CURL libraries:                $CURL_LIBS\n  CXSPARSE CPPFLAGS:             $CXSPARSE_CPPFLAGS\n  CXSPARSE LDFLAGS:              $CXSPARSE_LDFLAGS\n  CXSPARSE libraries:            $CXSPARSE_LIBS\n  DL libraries:                  $DL_LIBS\n  FFTW3 CPPFLAGS:                $FFTW3_CPPFLAGS\n  FFTW3 LDFLAGS:                 $FFTW3_LDFLAGS\n  FFTW3 libraries:               $FFTW3_LIBS\n  FFTW3F CPPFLAGS:               $FFTW3F_CPPFLAGS\n  FFTW3F LDFLAGS:                $FFTW3F_LDFLAGS\n  FFTW3F libraries:              $FFTW3F_LIBS\n  FLTK CPPFLAGS:                 $FLTK_CPPFLAGS\n  FLTK LDFLAGS:                  $FLTK_LDFLAGS\n  FLTK libraries:                $FLTK_LIBS\n  fontconfig CPPFLAGS:           $FONTCONFIG_CPPFLAGS\n  fontconfig libraries:          $FONTCONFIG_LIBS\n  FreeType2 CPPFLAGS:            $FT2_CPPFLAGS\n  FreeType2 libraries:           $FT2_LIBS\n  GLPK CPPFLAGS:                 $GLPK_CPPFLAGS\n  GLPK LDFLAGS:                  $GLPK_LDFLAGS\n  GLPK libraries:                $GLPK_LIBS\n  HDF5 CPPFLAGS:                 $HDF5_CPPFLAGS\n  HDF5 LDFLAGS:                  $HDF5_LDFLAGS\n  HDF5 libraries:                $HDF5_LIBS\n  Java home:                     $JAVA_HOME\n  Java JVM path:                 $JAVA_LDPATH\n  Java CPPFLAGS:                 $JAVA_CPPFLAGS\n  Java libraries:                $JAVA_LIBS\n  KLU CPPFLAGS:                  $KLU_CPPFLAGS\n  KLU LDFLAGS:                   $KLU_LDFLAGS\n  KLU libraries:                 $KLU_LIBS\n  LAPACK libraries:              $LAPACK_LIBS\n  Magick++ CPPFLAGS:             $MAGICK_CPPFLAGS\n  Magick++ LDFLAGS:              $MAGICK_LDFLAGS\n  Magick++ libraries:            $MAGICK_LIBS\n  OpenGL libraries:              $OPENGL_LIBS\n  PCRE CPPFLAGS:                 $PCRE_CPPFLAGS\n  PCRE LDFLAGS:                  $PCRE_LDFLAGS\n  PCRE libraries:                $PCRE_LIBS\n  PortAudio CPPFLAGS:            $PORTAUDIO_CPPFLAGS\n  PortAudio LDFLAGS:             $PORTAUDIO_LDFLAGS\n  PortAudio libraries:           $PORTAUDIO_LIBS\n  PTHREAD flags:                 $PTHREAD_CFLAGS\n  PTHREAD libraries:             $PTHREAD_LIBS\n  QHULL CPPFLAGS:                $QHULL_CPPFLAGS\n  QHULL LDFLAGS:                 $QHULL_LDFLAGS\n  QHULL libraries:               $QHULL_LIBS\n  QRUPDATE CPPFLAGS:             $QRUPDATE_CPPFLAGS\n  QRUPDATE LDFLAGS:              $QRUPDATE_LDFLAGS\n  QRUPDATE libraries:            $QRUPDATE_LIBS\n  Qt CPPFLAGS:                   $QT_CPPFLAGS\n  Qt LDFLAGS:                    $QT_LDFLAGS\n  Qt GUI libraries:              $QT_LIBS\n  Qt moc:                        $MOC $MOCFLAGS\n  Qt uic:                        $UIC $UICFLAGS\n  Qt rcc:                        $RCC $RCCFLAGS\n  Qt lrelease:                   $LRELEASE $LRELEASEFLAGS\n  Qt qcollectiongenerator:       $QCOLLECTIONGENERATOR $QCOLLECTIONGENERATORFLAGS\n  Qt qhelpgenerator:             $QHELPGENERATOR $QHELPGENERATORFLAGS\n  READLINE libraries:            $LIBREADLINE\n  Sndfile CPPFLAGS:              $SNDFILE_CPPFLAGS\n  Sndfile LDFLAGS:               $SNDFILE_LDFLAGS\n  Sndfile libraries:             $SNDFILE_LIBS\n  SPQR CPPFLAGS:                 $SPQR_CPPFLAGS\n  SPQR LDFLAGS:                  $SPQR_LDFLAGS\n  SPQR libraries:                $SPQR_LIBS\n  SuiteSparse config libraries:  $SUITESPARSECONFIG_LIBS\n  SUNDIALS core CPPFLAGS:        $SUNDIALS_CORE_CPPFLAGS\n  SUNDIALS core LDFLAGS:         $SUNDIALS_CORE_LDFLAGS\n  SUNDIALS core libraries:       $SUNDIALS_CORE_LIBS\n  SUNDIALS IDA CPPFLAGS:         $SUNDIALS_IDA_CPPFLAGS\n  SUNDIALS IDA LDFLAGS:          $SUNDIALS_IDA_LDFLAGS\n  SUNDIALS IDA libraries:        $SUNDIALS_IDA_LIBS\n  SUNDIALS NVECTOR CPPFLAGS:     $SUNDIALS_NVECSERIAL_CPPFLAGS\n  SUNDIALS NVECTOR LDFLAGS:      $SUNDIALS_NVECSERIAL_LDFLAGS\n  SUNDIALS NVECTOR libraries:    $SUNDIALS_NVECSERIAL_LIBS\n  SUNLINSOL KLU CPPFLAGS:        $SUNDIALS_SUNLINSOLKLU_CPPFLAGS\n  SUNLINSOL KLU LDFLAGS:         $SUNDIALS_SUNLINSOLKLU_LDFLAGS\n  SUNLINSOL KLU libraries:       $SUNDIALS_SUNLINSOLKLU_LIBS\n  UMFPACK CPPFLAGS:              $UMFPACK_CPPFLAGS\n  UMFPACK LDFLAGS:               $UMFPACK_LDFLAGS\n  UMFPACK libraries:             $UMFPACK_LIBS\n  Wayland client CPPFLAGS:       $WAYLAND_CLIENT_CPPFLAGS\n  Wayland client LDFLAGS:        $WAYLAND_CLIENT_LDFLAGS\n  Wayland client libraries:      $WAYLAND_CLIENT_LIBS\n  X11 include flags:             $X11_INCFLAGS\n  X11 libraries:                 $X11_LIBS\n  Z CPPFLAGS:                    $Z_CPPFLAGS\n  Z LDFLAGS:                     $Z_LDFLAGS\n  Z libraries:                   $Z_LIBS\n\n  Default pager:                 $DEFAULT_PAGER\n  gnuplot:                       $GNUPLOT_BINARY\n\n  Build Octave Qt GUI:                  $BUILD_QT_SUMMARY_MSG\n  Build Java interface:                 $build_java\n  Build static libraries:               $STATIC_LIBS\n  Build shared libraries:               $SHARED_LIBS\n  Dynamic Linking API:                  $DL_API_MSG\n  Use library visibility flags:         $ENABLE_LIB_VISIBILITY_FLAGS\n  64-bit array dims and indexing:       $ENABLE_64\n  64-bit BLAS array dims and indexing:  $HAVE_64_BIT_BLAS\n  Use std::pmr::polymorphic_allocator:  $HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR\n  OpenMP SMP multithreading:            $ENABLE_OPENMP\n  Include support for GNU readline:     $USE_READLINE\n  Use push parser in command line REPL: $ENABLE_COMMAND_LINE_PUSH_PARSER\n  Build cross tools:                    $cross_tools\n  Build docs:                           $ENABLE_DOCS\n  Embed Mercurial ID in libraries:      $ENABLE_HG_ID\n  Install build logs:                   $install_build_logs\n])\n\nwarn_msg_printed=false\n\nOCTAVE_CONFIGURE_WARNING_SUMMARY\n\nif test $opengl_graphics = no; then\n  AC_MSG_WARN([])\n  AC_MSG_WARN([The libraries needed for OpenGL graphics were not found.])\n  AC_MSG_WARN([Creating plots is still possible if gnuplot is installed.])\n  warn_msg_printed=true\nfi\n\nif $warn_msg_printed; then\n  AC_MSG_NOTICE([])\n  AC_MSG_NOTICE([NOTE: Libraries or auxiliary programs may be skipped if they are not found])\n  AC_MSG_NOTICE([NOTE: OR if they are missing required features on your system.])\nfi\n\n### End of configure.\n"
  },
  {
    "path": "doc/doxyhtml/Doxyfile.in",
    "content": "# -*- mode: conf; -*-\n\n########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# Doxyfile for Doxygen 1.8.11\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) for GNU Octave.\n#\n# All text after a double hash (##) is considered a comment and is placed in\n# front of the TAG it is preceding.\n#\n# All text after a single hash (#) is considered a comment and will be ignored.\n# The format is:\n# TAG = value [value, ...]\n# For lists, items can also be appended using:\n# TAG += value [value, ...]\n# Values that contain spaces should be placed between quotes (\\\" \\\").\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\n\n# This tag specifies the encoding used for all characters in the config file\n# that follow. The default is UTF-8 which is also the encoding used for all text\n# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv\n# built into libc) for the transcoding. See https://www.gnu.org/software/libiconv\n# for the list of possible encodings.\n# The default value is: UTF-8.\n\nDOXYFILE_ENCODING      = UTF-8\n\n# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by\n# double-quotes, unless you are using Doxywizard) that should identify the\n# project for which the documentation is generated. This name is used in the\n# title of most generated pages and in a few other places.\n# The default value is: My Project.\n\nPROJECT_NAME           = \"GNU Octave\"\n\n# The public stable API version (unrelated to the internal API version).\n\nPROJECT_NUMBER         = @PACKAGE_VERSION@\n\n# Using the PROJECT_BRIEF tag one can provide an optional one line description\n# for a project that appears at the top of each page and should give viewer a\n# quick idea about the purpose of the project. Keep the description short.\n\nPROJECT_BRIEF          = \"A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab\"\n\n# With the PROJECT_LOGO tag one can specify a logo or an icon that is included\n# in the documentation. The maximum height of the logo should not exceed 55\n# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy\n# the logo to the output directory.\n\nPROJECT_LOGO           = @abs_top_srcdir@/etc/icons/octave-logo-48.png\n\n# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path\n# into which the generated documentation will be written. If a relative path is\n# entered, it will be relative to the location where doxygen was started. If\n# left blank the current directory will be used.\n\nOUTPUT_DIRECTORY       = @abs_top_builddir@/doc\n\n# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-\n# directories (in 2 levels) under the output directory of each output format and\n# will distribute the generated files over these directories. Enabling this\n# option can be useful when feeding doxygen a huge amount of source files, where\n# putting all generated files in the same directory would otherwise causes\n# performance problems for the file system.\n# The default value is: NO.\n\nCREATE_SUBDIRS         = YES\n\n# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII\n# characters to appear in the names of generated files. If set to NO, non-ASCII\n# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode\n# U+3044.\n# The default value is: NO.\n\nALLOW_UNICODE_NAMES    = NO\n\n# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all constant output in the proper language.\n# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,\n# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),\n# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,\n# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),\n# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,\n# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,\n# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,\n# Ukrainian and Vietnamese.\n# The default value is: English.\n\nOUTPUT_LANGUAGE        = English\n\n# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member\n# descriptions after the members that are listed in the file and class\n# documentation (similar to Javadoc). Set to NO to disable this.\n# The default value is: YES.\n\nBRIEF_MEMBER_DESC      = YES\n\n# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief\n# description of a member or function before the detailed description\n#\n# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the\n# brief descriptions will be completely suppressed.\n# The default value is: YES.\n\nREPEAT_BRIEF           = YES\n\n# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then\n# Doxygen will generate a detailed section even if there is only a brief\n# description.\n# The default value is: NO.\n\nALWAYS_DETAILED_SEC    = NO\n\n# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all\n# inherited members of a class in the documentation of that class as if those\n# members were ordinary class members. Constructors, destructors and assignment\n# operators of the base classes will not be shown.\n# The default value is: NO.\n\nINLINE_INHERITED_MEMB  = NO\n\n# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path\n# before files name in the file list and in the header files. If set to NO the\n# shortest path that makes the file name unique will be used\n# The default value is: YES.\n\nFULL_PATH_NAMES        = YES\n\n# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.\n# Stripping is only done if one of the specified strings matches the left-hand\n# part of the path. The tag can be used to show relative paths in the file list.\n# If left blank the directory from which doxygen is run is used as the path to\n# strip.\n#\n# Note that you can specify absolute paths here, but also relative paths, which\n# will be relative from the directory where doxygen is started.\n# This tag requires that the tag FULL_PATH_NAMES is set to YES.\n\nSTRIP_FROM_PATH        = @abs_top_srcdir@\n\n# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the\n# first line (until the first dot) of a Javadoc-style comment as the brief\n# description. If set to NO, the Javadoc-style will behave just like regular Qt-\n# style comments (thus requiring an explicit @brief command for a brief\n# description.)\n# The default value is: NO.\n\nJAVADOC_AUTOBRIEF      = YES\n\n# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first\n# line (until the first dot) of a Qt-style comment as the brief description. If\n# set to NO, the Qt-style will behave just like regular Qt-style comments (thus\n# requiring an explicit \\brief command for a brief description.)\n# The default value is: NO.\n\nQT_AUTOBRIEF           = NO\n\n# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the\n# documentation from any documented member that it re-implements.\n# The default value is: YES.\n\nINHERIT_DOCS           = YES\n\n# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new\n# page for each member. If set to NO, the documentation of a member will be part\n# of the file/class/namespace that contains it.\n# The default value is: NO.\n\nSEPARATE_MEMBER_PAGES  = NO\n\n# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen\n# uses this value to replace tabs by spaces in code fragments.\n# Minimum value: 1, maximum value: 16, default value: 4.\n\nTAB_SIZE               = 2\n\n# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments\n# according to the Markdown format, which allows for more readable\n# documentation. See http://daringfireball.net/projects/markdown/ for details.\n# The output of markdown processing is further processed by doxygen, so you can\n# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in\n# case of backward compatibilities issues.\n# The default value is: YES.\n\nMARKDOWN_SUPPORT       = YES\n\n# When enabled doxygen tries to link words that correspond to documented\n# classes, or namespaces to their corresponding documentation. Such a link can\n# be prevented in individual cases by putting a % sign in front of the word or\n# globally by setting AUTOLINK_SUPPORT to NO.\n# The default value is: YES.\n\nAUTOLINK_SUPPORT       = YES\n\n# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want\n# to include (a tag file for) the STL sources as input, then you should set this\n# tag to YES in order to let doxygen match functions declarations and\n# definitions whose arguments contain STL classes (e.g. func(std::string);\n# versus func(std::string) {}). This also make the inheritance and collaboration\n# diagrams that involve STL classes more complete and accurate.\n# The default value is: NO.\n\nBUILTIN_STL_SUPPORT    = YES\n\n# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC\n# tag is set to YES then doxygen will reuse the documentation of the first\n# member in the group (if any) for the other members of the group. By default\n# all members of a group must be documented explicitly.\n# The default value is: NO.\n\nDISTRIBUTE_GROUP_DOC   = YES\n\n# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This\n# cache is used to resolve symbols given their name and scope. Since this can be\n# an expensive process and often the same symbol appears multiple times in the\n# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small\n# doxygen will become slower. If the cache is too large, memory is wasted. The\n# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range\n# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536\n# symbols. At the end of a run doxygen will report the cache usage and suggest\n# the optimal cache size from a speed point of view.\n# Minimum value: 0, maximum value: 9, default value: 0.\n\nLOOKUP_CACHE_SIZE      = 2\n\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\n\n# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in\n# documentation are documented, even if no documentation was available. Private\n# class members and static file members will be hidden unless the\n# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.\n# Note: This will also disable the warnings about undocumented members that are\n# normally produced when WARNINGS is set to YES.\n# The default value is: NO.\n\nEXTRACT_ALL            = YES\n\n# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will\n# be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIVATE        = NO\n\n# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal\n# scope will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PACKAGE        = NO\n\n# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be\n# included in the documentation.\n# The default value is: NO.\n\nEXTRACT_STATIC         = NO\n\n# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined\n# locally in source files will be included in the documentation. If set to NO,\n# only classes defined in header files are included. Does not have any effect\n# for Java sources.\n# The default value is: YES.\n\nEXTRACT_LOCAL_CLASSES  = NO\n\n\n# If this flag is set to YES, the members of anonymous namespaces will be\n# extracted and appear in the documentation as a namespace called\n# 'anonymous_namespace{file}', where file will be replaced with the base name of\n# the file that contains the anonymous namespace. By default anonymous namespace\n# are hidden.\n# The default value is: NO.\n\nEXTRACT_ANON_NSPACES   = YES\n\n# The INTERNAL_DOCS tag determines if documentation that is typed after a\n# \\internal command is included. If the tag is set to NO then the documentation\n# will be excluded. Set it to YES to include the internal documentation.\n# The default value is: NO.\n\nINTERNAL_DOCS          = NO\n\n# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file\n# names in lowercase letters. If set to YES, uppercase letters are also\n# allowed. This is useful if you have classes or files whose names only differ\n# in case and if your file system supports case sensitive file names. Windows\n# and Mac users are advised to set this option to NO.\n# The default value is: system dependent.\n\nCASE_SENSE_NAMES       = YES\n\n# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include\n# files with double quotes in the documentation rather than with sharp brackets.\n# The default value is: NO.\n\nFORCE_LOCAL_INCLUDES   = YES\n\n# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the\n# documentation for inline members.\n# The default value is: YES.\n\nINLINE_INFO            = YES\n\n# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the\n# (detailed) documentation of file and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order.\n# The default value is: YES.\n\nSORT_MEMBER_DOCS       = YES\n\n# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief\n# descriptions of file, namespace and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order. Note that\n# this will also influence the order of the classes in the class list.\n# The default value is: NO.\n\nSORT_BRIEF_DOCS        = YES\n\n# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the\n# (brief and detailed) documentation of class members so that constructors and\n# destructors are listed first. If set to NO the constructors will appear in the\n# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.\n# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief\n# member documentation.\n# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting\n# detailed member documentation.\n# The default value is: NO.\n\nSORT_MEMBERS_CTORS_1ST = YES\n\n\n# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces\n# page. This will remove the Namespaces entry from the Quick Index and from the\n# Folder Tree View (if specified).\n# The default value is: YES.\n\nSHOW_NAMESPACES        = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\n\n\n#---------------------------------------------------------------------------\n# Configuration options related to the input files\n#---------------------------------------------------------------------------\n\n# The INPUT tag is used to specify the files and/or directories that contain\n# documented source files. You may enter file names like myfile.cpp or\n# directories like /usr/src/myproject. Separate the files or directories with\n# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING\n# Note: If this tag is empty the current directory is searched.\n\nINPUT                  = @abs_top_srcdir@/src/ \\\n                         @abs_top_srcdir@/liboctave/ \\\n                         @abs_top_srcdir@/libinterp \\\n                         @abs_top_srcdir@/doc/doxyhtml/pages \\\n                         @abs_top_builddir@/doc/doxyhtml/pages\n\n# The EXCLUDE tag is used to exclude files and/or directories that would\n# otherwise be included by the INPUT tag.\nEXCLUDE                =\n\n# This tag is used to exclude files and/or directories that would otherwise be\n# included by the INPUT tag using a pattern rather than an exact name as\n# the EXCLUDE tag does.\n\nEXCLUDE_PATTERNS       = *.in.h\n\n# This tag can be used to specify the character encoding of the source files\n# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses\n# libiconv (or the iconv built into libc) for the transcoding. See the libiconv\n# documentation (see: https://www.gnu.org/software/libiconv) for the list of\n# possible encodings.\n# The default value is: UTF-8.\n\nINPUT_ENCODING         = UTF-8\n\n# The RECURSIVE tag can be used to specify whether or not subdirectories should\n# be searched for input files as well.\n# The default value is: NO.\n\nRECURSIVE              = YES\n\n# The EXAMPLE_PATH tag can be used to specify one or more files or directories\n# that contain example code fragments that are included (see the \\include\n# command).\n\nEXAMPLE_PATH           = @abs_top_srcdir@/examples/\n\n# If the value of the EXAMPLE_PATH tag contains directories, you can use the\n# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and\n# *.h) to filter out the source-files in the directories. If left blank all\n# files are included.\n\nEXAMPLE_PATTERNS       =\n\n# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be\n# searched for input files to be used with the \\include or \\dontinclude commands\n# irrespective of the value of the RECURSIVE tag.\n# The default value is: NO.\n\nEXAMPLE_RECURSIVE      = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to source browsing\n#---------------------------------------------------------------------------\n\n# If the SOURCE_BROWSER tag is set to YES then a list of source files will be\n# generated. Documented entities will be cross-referenced with these sources.\n#\n# Note: To get rid of all source code in the generated output, make sure that\n# also VERBATIM_HEADERS is set to NO.\n# The default value is: NO.\n\nSOURCE_BROWSER         = YES\n\n# Setting the INLINE_SOURCES tag to YES will include the body of functions,\n# classes and enums directly into the documentation.\n# The default value is: NO.\n\nINLINE_SOURCES         = NO\n\n# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any\n# special comment blocks from generated source code fragments. Normal C, C++ and\n# Fortran comments will always remain visible.\n# The default value is: YES.\n\nSTRIP_CODE_COMMENTS    = NO\n\n# If the REFERENCED_BY_RELATION tag is set to YES then for each documented\n# function all documented functions referencing it will be listed.\n# The default value is: NO.\n\nREFERENCED_BY_RELATION = YES\n\n# If the REFERENCES_RELATION tag is set to YES then for each documented function\n# all documented entities called/used by that function will be listed.\n# The default value is: NO.\n\nREFERENCES_RELATION    = YES\n\n# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set\n# to YES then the hyperlinks from functions in REFERENCES_RELATION and\n# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will\n# link to the documentation.\n# The default value is: YES.\n\nREFERENCES_LINK_SOURCE = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the HTML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output\n# The default value is: YES.\n\nGENERATE_HTML          = YES\n\n# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: html. i.e. @abs_top_builddir@/doc/doxyhtml\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_OUTPUT            = doxyhtml\n\n# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML\n# page will contain the date and time when the page was generated. Setting this\n# to YES can help to show when doxygen was last run and thus if the\n# documentation is up to date.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_TIMESTAMP         = YES\n\n# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and\n# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that\n# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help\n# (.qch) of the generated HTML documentation.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_QHP           = NO\n\n# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify\n# the file name of the resulting .qch file. The path specified is relative to\n# the HTML output folder.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQCH_FILE               = ./octave-cpp-api.qch\n\n# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help\n# Project output. For more information please see Qt Help Project / Namespace\n# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_NAMESPACE          = org.octave.cpp-api\n\n# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt\n# Help Project output. For more information please see Qt Help Project / Virtual\n# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-\n# folders).\n# The default value is: doc.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_VIRTUAL_FOLDER     = doc\n\n# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom\n# filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_NAME   = \"Octave C++ API\"\n\n# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the\n# custom filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_ATTRS  = \"core cpp\"\n\n# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this\n# project's filter section matches. Qt Help Project / Filter Attributes (see:\n# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_SECT_FILTER_ATTRS  = \"core cpp\"\n\n# The QHG_LOCATION tag can be used to specify the location of Qt's\n# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the\n# generated .qhp file.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHG_LOCATION           = @QHELPGENERATOR@\n\n# If you want full control over the layout of the generated HTML pages it might\n# be necessary to disable the index and replace it with your own. The\n# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top\n# of each HTML page. A value of NO enables the index and the value YES disables\n# it. Since the tabs in the index contain the same information as the navigation\n# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nDISABLE_INDEX          = YES\n\n# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index\n# structure should be generated to display hierarchical information. If the tag\n# value is set to YES, a side panel will be generated containing a tree-like\n# index structure (just like the one that is generated for HTML Help). For this\n# to work a browser that supports JavaScript, DHTML, CSS and frames is required\n# (i.e. any modern browser). Windows users are probably better off using the\n# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can\n# further fine-tune the look of the index. As an example, the default style\n# sheet generated by doxygen has an example that shows how to put an image at\n# the root of the tree instead of the PROJECT_NAME. Since the tree basically has\n# the same information as the tab index, you could consider setting\n# DISABLE_INDEX to YES when enabling this option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_TREEVIEW      = YES\n\n# When the SEARCHENGINE tag is enabled doxygen will generate a search box for\n# the HTML output. The underlying search engine uses javascript and DHTML and\n# should work on any modern browser. Note that when using HTML help\n# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)\n# there is already a search function so this one should typically be disabled.\n# For large projects the javascript based search engine can be slow, then\n# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to\n# search using the keyboard; to jump to the search box use <access key> + S\n# (what the <access key> is depends on the OS and browser, but it is typically\n# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down\n# key> to jump into the search results window, the results can be navigated\n# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel\n# the search. The filter options can be selected when the cursor is inside the\n# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>\n# to select a filter and <Enter> or <escape> to activate or cancel the filter\n# option.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nSEARCHENGINE           = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.\n# The default value is: YES.\n\nGENERATE_LATEX         = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\n\n# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all\n# C-preprocessor directives found in the sources and include files.\n# The default value is: YES.\n\nENABLE_PREPROCESSING   = YES\n\n# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names\n# in the source code. If set to NO, only conditional compilation will be\n# performed. Macro expansion can be done in a controlled way by setting\n# EXPAND_ONLY_PREDEF to YES.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nMACRO_EXPANSION        = YES\n\n# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then\n# the macro expansion is limited to the macros specified with the PREDEFINED and\n# EXPAND_AS_DEFINED tags.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_ONLY_PREDEF     = NO\n\n# If the SEARCH_INCLUDES tag is set to YES, the include files in the\n# INCLUDE_PATH will be searched if a #include is found.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSEARCH_INCLUDES        = YES\n\n# The INCLUDE_PATH tag can be used to specify one or more directories that\n# contain include files that are not input files but should be processed by the\n# preprocessor.\n# This tag requires that the tag SEARCH_INCLUDES is set to YES.\n\nINCLUDE_PATH           = @abs_top_srcdir@/libgnu \\\n                         @abs_top_srcdir@/libinterp/corefcn \\\n                         @abs_top_srcdir@/libinterp/octave-value \\\n                         @abs_top_srcdir@/libinterp/operators \\\n                         @abs_top_srcdir@/libinterp/parse-tree \\\n                         @abs_top_srcdir@/libinterp/template-inst \\\n                         @abs_top_srcdir@/liboctave/array \\\n                         @abs_top_srcdir@/liboctave/numeric \\\n                         @abs_top_srcdir@/liboctave/operators \\\n                         @abs_top_srcdir@/liboctave/system \\\n                         @abs_top_srcdir@/liboctave/util \\\n                         @abs_top_srcdir@/src\n\n# The PREDEFINED tag can be used to specify one or more macro names that are\n# defined before the preprocessor is started (similar to the -D option of e.g.\n# gcc). The argument of the tag is a list of macros of the form: name or\n# name=definition (no spaces). If the definition and the \"=\" are omitted, \"=1\"\n# is assumed. To prevent a macro definition from being undefined via #undef or\n# recursively expanded use the := operator instead of the = operator.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n#\n# So that features that are behind #if defined (HAVE_FOO) macros\n# get processed by Doxygen\n\nPREDEFINED             = HAVE_ARPACK=1 \\\n                         HAVE_CCOLAMD=1 \\\n                         HAVE_CHOLMOD=1 \\\n                         HAVE_CURL=1 \\\n                         HAVE_CXSPARSE=1 \\\n                         HAVE_FFTW=1 \\\n                         HAVE_FFTW3=1 \\\n                         HAVE_FFTW3F=1 \\\n                         HAVE_FFTW3F_THREADS=1 \\\n                         HAVE_FFTW3_THREADS=1 \\\n                         HAVE_FREETYPE=1 \\\n                         HAVE_GLPK=1 \\\n                         HAVE_HDF5=1 \\\n                         HAVE_JAVA=1 \\\n                         HAVE_MAGICK=1 \\\n                         HAVE_OPENGL=1 \\\n                         HAVE_OPENMP=1 \\\n                         HAVE_PCRE_COMPILE=1 \\\n                         HAVE_PCRE_H=1 \\\n                         HAVE_QHULL=1 \\\n                         HAVE_QRUPDATE=1 \\\n                         HAVE_QRUPDATE_LUU=1 \\\n                         HAVE_QSCINTILLA=1 \\\n                         HAVE_QT=1 \\\n                         HAVE_UMFPACK=1 \\\n                         HAVE_X_WINDOWS=1 \\\n                         HAVE_ZLIB=1 \\\n                         OCTARRAY_API= \\\n                         OCTARRAY_CLASS_TEMPLATE_INSTANTIATION_API= \\\n                         OCTARRAY_EXCEPTION_API= \\\n                         OCTARRAY_EXTERN_TEMPLATE_API= \\\n                         OCTARRAY_OVERRIDABLE_FUNC_API= \\\n                         OCTARRAY_TEMPLATE_API= \\\n                         OCTAVE_API= \\\n                         OCTAVE_CLASS_TEMPLATE_INSTANTIATION_API= \\\n                         OCTAVE_EXCEPTION_API= \\\n                         OCTAVE_EXPORT= \\\n                         OCTAVE_EXTERN_TEMPLATE_API= \\\n                         OCTAVE_IMPORT= \\\n                         OCTAVE_OVERRIDABLE_FUNC_API= \\\n                         OCTAVE_TEMPLATE_API= \\\n                         OCTGRAPHICS_API= \\\n                         OCTGRAPHICS_CLASS_TEMPLATE_INSTANTIATION_API= \\\n                         OCTGRAPHICS_EXCEPTION_API= \\\n                         OCTGRAPHICS_EXTERN_TEMPLATE_API= \\\n                         OCTGRAPHICS_OVERRIDABLE_FUNC_API= \\\n                         OCTGRAPHICS_TEMPLATE_API= \\\n                         OCTGUI_API= \\\n                         OCTGUI_CLASS_TEMPLATE_INSTANTIATION_API= \\\n                         OCTGUI_EXCEPTION_API= \\\n                         OCTGUI_EXTERN_TEMPLATE_API= \\\n                         OCTGUI_OVERRIDABLE_FUNC_API= \\\n                         OCTGUI_TEMPLATE_API= \\\n                         OCTINTERP_API= \\\n                         OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API= \\\n                         OCTINTERP_EXCEPTION_API= \\\n                         OCTINTERP_EXTERN_TEMPLATE_API= \\\n                         OCTINTERP_OVERRIDABLE_FUNC_API= \\\n                         OCTINTERP_TEMPLATE_API\n\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool\n#---------------------------------------------------------------------------\n\n# If set to YES the inheritance and collaboration graphs will hide inheritance\n# and usage relations if the target is undocumented or is not a class.\n# The default value is: YES.\n\nHIDE_UNDOC_RELATIONS   = NO\n\n# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is\n# available from the path. This tool is part of Graphviz (see:\n# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent\n# Bell Labs. The other options in this section have no effect if this option is\n# set to NO\n# The default value is: NO.\n\nHAVE_DOT               = NO\n\n\n# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes\n# that will be shown in the graph. If the number of nodes in a graph becomes\n# larger than this value, doxygen will truncate the graph, which is visualized\n# by representing a node as a red box. Note that doxygen if the number of direct\n# children of the root node in a graph is already larger than\n# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that\n# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.\n# Minimum value: 0, maximum value: 10000, default value: 50.\n# This tag requires that the tag HAVE_DOT is set to YES.\n# Some of our dependency graphs are really huge...\n\nDOT_GRAPH_MAX_NODES    = 300\n\n# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot\n# files that are used to generate the various graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_CLEANUP            = YES\n"
  },
  {
    "path": "doc/doxyhtml/README.md",
    "content": "This directory contains Doxygen documentation for Octave's source code.\nIt is not created by default.  To generate the Doxygen documentation use\n\n    make doxyhtml\n\nDoxygen documentation can be helpful for developers of Octave, but is not\nneeded by users of Octave.  In addition, the documentation requires\napproximately 3 GB of storage space.  For these reasons it is not maintained\nunder version control nor distributed in tarballs.\n"
  },
  {
    "path": "doc/doxyhtml/module.mk",
    "content": "# Generate README.md from README and replace first line by a Doxygen\n# specific one.\n%reldir%/pages/README.md: $(srcdir)/README\n\t$(AM_V_GEN)$(MKDIR_P) $(@D) && \\\n\tcat $< | $(SED) '1s/.*/notitle {#mainpage}/; 2s/.*/=======/' > $@\n\nDOXYGEN_PAGES = \\\n  %reldir%/pages/macros.dox \\\n  %reldir%/pages/README.md\n\ndoxyhtml: %reldir%/Doxyfile $(DOXYGEN_PAGES) | %reldir%/$(octave_dirstamp)\n\tdoxygen %reldir%/Doxyfile\n\n# This target is important for in source tree builds.\ndoxyhtml-maintainer-clean:\n\t$(RM) %reldir%/pages/README.md\n\t$(RM) -r `ls -d %reldir%/* 2>/dev/null | $(GREP) -v 'module\\.mk\\|Doxyfile\\.in\\|README\\|pages$$'`\n\ndoc_EXTRA_DIST += \\\n  $(DOXYGEN_PAGES) \\\n  %reldir%/Doxyfile.in \\\n  %reldir%/README.md\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "doc/doxyhtml/pages/macros.dox",
    "content": "/** @page Macros Important Macros\n\n@tableofcontents\n\nBuiltin function and method definition   {#macros_defun}\n======================================\n\nIn Octave a function is called from the interpreter by for example\n\n    [a, b, c] = foo (d, e);\n\nIf `foo` should be defined as **builtin function**, it has to have the type\n`octave_builtin::fcn` or equivalently:\n\n```{.cc}\noctave_value_list\nFfoo (const octave_value_list& args_name, int nargout_name)\n```\n\n> Notice the **F** prefix of `foo`!\n\nBasically, an `octave_value_list` goes in (referenced within that function by\n`args_name`) and another `octave_value_list` comes out.  The integer\n`nargout_name` indicates, how many outputs arguments the caller of this\nfunctions expects.\n\nThus in the example above, `d` and `e` are available via `args_name` and\n`nargout_name` takes the value `3`, because three output arguments `a`, `b`,\nand `c` are expected.\n\nVery similar to builtin functions are **builtin methods**.  Builtin methods\nhave to have the type `octave_builtin::meth` or equivalently:\n\n```{.cc}\noctave_value_list\nFfoo (octave::interpreter& interp_name,\n      const octave_value_list& args_name, int nargout_name)\n```\n\nNotice again the `F` prefix of `foo`.\n\n> The difference between builtin functions and builtin methods is, that builtin\n> methods have access to the `octave::interpreter`, which is referenced by\n> `interp_name`.\n\nTo make a builtin function or builtin method available to the interpreter, it\nis not sufficient to just define them somewhere inside `libinterp`.  Octave\nprovides two convenience macros, to define them properly:\n\n```{.cc}\nDEFUN     (foo,              args_name, nargout_name, doc)\nDEFMETHOD (foo, interp_name, args_name, nargout_name, doc)\n```\n\n> For a usage example, see the definition of `#Feig`.\n\nThe last argument of both macros `doc` will not appear in the builtin function\nor builtin method definition but is further processed.  The idea is, that code\nand documentation should be at one place.\n\nThe macros #DEFUN or #DEFMETHOD fulfill two tasks:\n\n1. Proper builtin function or builtin method definition.\n2. Defining a fixed pattern for further processing by\n   - `mk-builtins.pl` (installation on `octave::symbol_table`)\n   - `mk-doc.pl` (docstring `doc` extraction for the help system)\n\nIn addition to #DEFUN and #DEFMETHOD, there are two specialized versions of\nboth macros, that should only be used with reason:\n\nIf the name `foo` cannot be used directly (for example if it is already\ndefined as a macro), one can use instead one of\n```{.cc}\nDEFUNX     (\"foo\", Ffoo,              args_name, nargout_name, doc)\nDEFMETHODX (\"foo\", Ffoo, interp_name, args_name, nargout_name, doc)\n```\nwhere `\"foo\"` is the name for the interpreter, protected by macro expansion\ninside a string, and `Ffoo` is the actual builtin function or builtin method\nname.\n\nLast but not least, there is #DEFALIAS.  As the name suggests, this macro can\nbe used to define an alias for an existing builtin function.\n\nDynamic builtin function and method definition  {#macros_defun_dld}\n==============================================\n\nWhen making use of the [OCT-file interface][OCT], it is desired to define\nfunctions or methods, than can be loaded dynamically at run time, e.g. those\nare not loaded at Octave startup.\n\n[OCT]: https://www.gnu.org/software/octave/doc/interpreter/Oct_002dFiles.html\n\nTo achieve this, analog to #DEFUN and #DEFMETHOD, there are:\n\n```{.cc}\nDEFUN_DLD     (name,              args_name, nargout_name, doc)\nDEFMETHOD_DLD (name, interp_name, args_name, nargout_name, doc)\n```\n\n**/\n"
  },
  {
    "path": "doc/interpreter/arith.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Arithmetic\n@chapter Arithmetic\n\nUnless otherwise noted, all of the functions described in this chapter\nwill work for real and complex scalar, vector, or matrix arguments.  Functions\ndescribed as @dfn{mapping functions} apply the given operation individually to\neach element when given a matrix argument.  For example:\n\n@example\n@group\nsin ([1, 2; 3, 4])\n     @xresult{}  0.84147   0.90930\n         0.14112  -0.75680\n@end group\n@end example\n\n@menu\n* Exponents and Logarithms::\n* Complex Arithmetic::\n* Trigonometry::\n* Sums and Products::\n* Utility Functions::\n* Special Functions::\n* Rational Approximations::\n* Coordinate Transformations::\n* Mathematical Constants::\n@end menu\n\n@node Exponents and Logarithms\n@section Exponents and Logarithms\n\n@DOCSTRING(exp)\n\n@DOCSTRING(expm1)\n\n@DOCSTRING(log)\n\n@DOCSTRING(reallog)\n\n@DOCSTRING(log1p)\n\n@DOCSTRING(log10)\n\n@DOCSTRING(log2)\n\n@DOCSTRING(pow2)\n\n@DOCSTRING(nextpow2)\n\n@DOCSTRING(realpow)\n\n@DOCSTRING(sqrt)\n\n@DOCSTRING(realsqrt)\n\n@DOCSTRING(cbrt)\n\n@DOCSTRING(nthroot)\n\n@node Complex Arithmetic\n@section Complex Arithmetic\n\nIn the descriptions of the following functions,\n@tex\n$z$ is the complex number $x + iy$, where $i$ is defined as\n$\\sqrt{-1}$.\n@end tex\n@ifnottex\n@var{z} is the complex number @var{x} + @var{i}@var{y}, where @var{i} is\ndefined as @code{sqrt (-1)}.\n@end ifnottex\n\n@DOCSTRING(abs)\n\n@DOCSTRING(arg)\n\n@DOCSTRING(conj)\n\n@DOCSTRING(cplxpair)\n\n@DOCSTRING(imag)\n\n@DOCSTRING(real)\n\n@node Trigonometry\n@section Trigonometry\n\nOctave provides the following trigonometric functions where angles are\nspecified in radians.  To convert from degrees to radians multiply by\n@tex\n$\\pi/180$\n@end tex\n@ifnottex\n@code{pi/180}\n@end ifnottex\nor use the @code{deg2rad} function.  For example, @code{sin (30 * pi/180)}\nreturns the sine of 30 degrees.  As an alternative, Octave provides a number of\ntrigonometric functions which work directly on an argument specified in\ndegrees.  These functions are named after the base trigonometric function with\na @samp{d} suffix.  As an example, @code{sin} expects an angle in radians while\n@code{sind} expects an angle in degrees.\n\nOctave uses the C library trigonometric functions.  It is expected that these\nfunctions are defined by the ISO/IEC 9899 Standard.  This Standard is available\nat: @url{http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf}.\nSection F.9.1 deals with the trigonometric functions.  The behavior of most of\nthe functions is relatively straightforward.  However, there are some\nexceptions to the standard behavior.  Many of the exceptions involve the\nbehavior for -0.  The most complex case is atan2.  Octave exactly implements\nthe behavior given in the Standard.  Including\n@tex\n$atan2(\\pm0, -0)$ returns $\\pm \\pi$.\n@end tex\n@ifnottex\n@code{atan2(+- 0, 0)} returns @code{+- pi}.\n@end ifnottex\n\nIt should be noted that @sc{matlab} uses different definitions which apparently\ndo not distinguish -0.\n\n@DOCSTRING(deg2rad)\n@DOCSTRING(rad2deg)\n\n@DOCSTRING(sin)\n@DOCSTRING(cos)\n@DOCSTRING(tan)\n@DOCSTRING(sec)\n@DOCSTRING(csc)\n@DOCSTRING(cot)\n\n@DOCSTRING(asin)\n@DOCSTRING(acos)\n@DOCSTRING(atan)\n@DOCSTRING(asec)\n@DOCSTRING(acsc)\n@DOCSTRING(acot)\n\n@DOCSTRING(sinh)\n@DOCSTRING(cosh)\n@DOCSTRING(tanh)\n@DOCSTRING(sech)\n@DOCSTRING(csch)\n@DOCSTRING(coth)\n\n@DOCSTRING(asinh)\n@DOCSTRING(acosh)\n@DOCSTRING(atanh)\n@DOCSTRING(asech)\n@DOCSTRING(acsch)\n@DOCSTRING(acoth)\n\n@DOCSTRING(atan2)\n\nOctave provides the following trigonometric functions where angles are\nspecified in degrees.  These functions produce true zeros at the appropriate\nintervals rather than the small round-off error that occurs when using\nradians.  For example:\n\n@example\n@group\ncosd (90)\n     @xresult{} 0\ncos (pi/2)\n     @xresult{} 6.1230e-17\n@end group\n@end example\n\n@DOCSTRING(sind)\n@DOCSTRING(cosd)\n@DOCSTRING(tand)\n@DOCSTRING(secd)\n@DOCSTRING(cscd)\n@DOCSTRING(cotd)\n\n@DOCSTRING(asind)\n@DOCSTRING(acosd)\n@DOCSTRING(atand)\n@DOCSTRING(atan2d)\n@DOCSTRING(asecd)\n@DOCSTRING(acscd)\n@DOCSTRING(acotd)\n\nFinally, there are two trigonometric functions that calculate special\narguments with increased accuracy.\n\n@DOCSTRING(sinpi)\n@DOCSTRING(cospi)\n\n@node Sums and Products\n@section Sums and Products\n\n@DOCSTRING(sum)\n\n@DOCSTRING(prod)\n\n@DOCSTRING(cumsum)\n\n@DOCSTRING(cumprod)\n\n@DOCSTRING(sumsq)\n\n@node Utility Functions\n@section Utility Functions\n\n@DOCSTRING(ceil)\n\n@DOCSTRING(fix)\n\n@DOCSTRING(floor)\n\n@DOCSTRING(round)\n\n@DOCSTRING(roundb)\n\n@DOCSTRING(max)\n\n@DOCSTRING(min)\n\n@DOCSTRING(cummax)\n\n@DOCSTRING(cummin)\n\n@DOCSTRING(hypot)\n\n@DOCSTRING(gradient)\n\n@DOCSTRING(dot)\n\n@DOCSTRING(cross)\n\n@DOCSTRING(divergence)\n\n@DOCSTRING(curl)\n\n@DOCSTRING(del2)\n\n@DOCSTRING(factorial)\n\n@DOCSTRING(factor)\n\n@DOCSTRING(gcd)\n\n@DOCSTRING(lcm)\n\n@DOCSTRING(rem)\n\n@DOCSTRING(mod)\n\n@DOCSTRING(primes)\n\n@DOCSTRING(list_primes)\n\n@DOCSTRING(sign)\n\n@DOCSTRING(signbit)\n\n@node Special Functions\n@section Special Functions\n\n@DOCSTRING(airy)\n\n@DOCSTRING(besselj)\n\n@DOCSTRING(bessely)\n\n@DOCSTRING(besseli)\n\n@DOCSTRING(besselk)\n\n@DOCSTRING(besselh)\n\n@DOCSTRING(beta)\n\n@DOCSTRING(betainc)\n\n@DOCSTRING(betaincinv)\n\n@DOCSTRING(betaln)\n\n@DOCSTRING(bincoeff)\n\n@DOCSTRING(commutation_matrix)\n\n@DOCSTRING(cosint)\n\n@DOCSTRING(duplication_matrix)\n\n@DOCSTRING(dawson)\n\n@DOCSTRING(ellipj)\n\n@DOCSTRING(ellipke)\n\n@DOCSTRING(erf)\n\n@DOCSTRING(erfc)\n\n@DOCSTRING(erfcx)\n\n@DOCSTRING(erfi)\n\n@DOCSTRING(erfinv)\n\n@DOCSTRING(erfcinv)\n\n@DOCSTRING(expint)\n\n@DOCSTRING(gamma)\n\n@DOCSTRING(gammainc)\n\n@DOCSTRING(gammaincinv)\n\n@DOCSTRING(legendre)\n\n@anchor{XREFgammaln}\n@DOCSTRING(lgamma)\n\n@DOCSTRING(psi)\n\n@DOCSTRING(sinint)\n\n@node Rational Approximations\n@section Rational Approximations\n\n@DOCSTRING(rat)\n\n@DOCSTRING(rats)\n\n@node Coordinate Transformations\n@section Coordinate Transformations\n\n@DOCSTRING(cart2pol)\n\n@DOCSTRING(pol2cart)\n\n@DOCSTRING(cart2sph)\n\n@DOCSTRING(sph2cart)\n\n@node Mathematical Constants\n@section Mathematical Constants\n\n@DOCSTRING(e)\n\n@DOCSTRING(pi)\n\n@DOCSTRING(I)\n\n@DOCSTRING(Inf)\n\n@DOCSTRING(NaN)\n\n@DOCSTRING(eps)\n\n@DOCSTRING(realmax)\n\n@DOCSTRING(realmin)\n"
  },
  {
    "path": "doc/interpreter/audio.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@c Written by Kurt Hornik <Kurt.Hornik@wu-wien.ac.at> on 1996/05/14\n\n@node Audio Processing\n@chapter Audio Processing\n\n@menu\n* Audio File Utilities::\n* Audio Device Information::\n* Audio Player::\n* Audio Recorder::\n* Audio Data Processing::\n@end menu\n\n@node Audio File Utilities\n@section Audio File Utilities\n\nThe following functions allow you to read, write and retrieve\ninformation about audio files.  Various formats are supported including\nwav, flac and ogg vorbis.\n\n@DOCSTRING(audioinfo)\n\n@DOCSTRING(audioread)\n\n@DOCSTRING(audiowrite)\n\n@DOCSTRING(audioformats)\n\n@node Audio Device Information\n@section Audio Device Information\n\n@DOCSTRING(audiodevinfo)\n\n@node Audio Player\n@section Audio Player\n\nThe following methods are used to create and use audioplayer\nobjects.  These objects can be used to play back audio data stored in\nOctave matrices and arrays.  The audioplayer object supports playback\nfrom various devices available to the system, blocking and non-blocking\nplayback, convenient pausing and resuming and much more.\n\n@DOCSTRING(@audioplayer/audioplayer)\n\n@menu\n* Playback::\n* Player Properties::\n@end menu\n\n@node Playback\n@subsection Playback\n\nThe following methods are used to control player playback.\n\n@DOCSTRING(@audioplayer/play)\n\n@DOCSTRING(@audioplayer/playblocking)\n\n@DOCSTRING(@audioplayer/pause)\n\n@DOCSTRING(@audioplayer/resume)\n\n@DOCSTRING(@audioplayer/stop)\n\n@DOCSTRING(@audioplayer/isplaying)\n\n@node Player Properties\n@subsection Player Properties\n\nThe remaining couple of methods are used to get and set various\nproperties of the audioplayer object.\n\n@DOCSTRING(@audioplayer/get)\n\n@DOCSTRING(@audioplayer/set)\n\n@node Audio Recorder\n@section Audio Recorder\n\nThe following methods are used to create and use audiorecorder\nobjects.  These objects can be used to record audio data from various\ndevices available to the system.  You can use convenient methods to\nretrieve that data or audioplayer objects created from that\ndata.  Methods for blocking and non-blocking recording, pausing and\nresuming recording and much more is available.\n\n@DOCSTRING(@audiorecorder/audiorecorder)\n\n@menu\n* Recording::\n* Data Retrieval::\n* Recorder Properties::\n@end menu\n\n@node Recording\n@subsection Recording\n\nThe following methods control the recording process.\n\n@DOCSTRING(@audiorecorder/record)\n\n@DOCSTRING(@audiorecorder/recordblocking)\n\n@DOCSTRING(@audiorecorder/pause)\n\n@DOCSTRING(@audiorecorder/resume)\n\n@DOCSTRING(@audiorecorder/stop)\n\n@DOCSTRING(@audiorecorder/isrecording)\n\n@node Data Retrieval\n@subsection Data Retrieval\n\nThe following methods allow you to retrieve recorded audio data in\nvarious ways.\n\n@DOCSTRING(@audiorecorder/getaudiodata)\n\n@DOCSTRING(@audiorecorder/getplayer)\n\n@DOCSTRING(@audiorecorder/play)\n\n@node Recorder Properties\n@subsection Recorder Properties\n\nThe remaining two methods allow you to read or alter the properties of\naudiorecorder objects.\n\n@DOCSTRING(@audiorecorder/get)\n\n@DOCSTRING(@audiorecorder/set)\n\n@node Audio Data Processing\n@section Audio Data Processing\n\nOctave provides a few functions for dealing with audio data.  An audio\n`sample' is a single output value from an A/D converter, i.e., a small\ninteger number (usually 8 or 16 bits), and audio data is just a series\nof such samples.  It can be characterized by three parameters: the\nsampling rate (measured in samples per second or Hz, e.g., 8000 or\n44100), the number of bits per sample (e.g., 8 or 16), and the number of\nchannels (1 for mono, 2 for stereo, etc.).\n\nThere are many different formats for representing such data.  Currently,\nonly the two most popular, @emph{linear encoding} and @emph{mu-law\nencoding}, are supported by Octave.  There is an excellent FAQ on audio\nformats by @nospell{Guido van Rossum} @email{guido@@cwi.nl} which can be\nfound at any FAQ ftp site, in particular in the directory\n@file{/pub/usenet/news.answers/audio-fmts} of the archive site\n@code{rtfm.mit.edu}.\n\nOctave simply treats audio data as vectors of samples (non-mono data are\nnot supported yet).  It is assumed that audio files using linear\nencoding have one of the extensions @file{lin} or @file{raw}, and that\nfiles holding data in mu-law encoding end in @file{au}, @file{mu}, or\n@file{snd}.\n\n@DOCSTRING(lin2mu)\n\n@DOCSTRING(mu2lin)\n\n@DOCSTRING(record)\n\n@DOCSTRING(sound)\n\n@DOCSTRING(soundsc)\n"
  },
  {
    "path": "doc/interpreter/basics.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Getting Started\n@chapter Getting Started\n\nThis chapter explains some of Octave's basic features, including how to\nstart an Octave session, get help at the command prompt, edit the\ncommand line, and write Octave programs that can be executed as commands\nfrom your shell.\n\n@menu\n* Invoking Octave from the Command Line::\n* Quitting Octave::\n* Getting Help::\n* Command Line Editing::\n* How Octave Reports Errors::\n* Executable Octave Programs::\n* Comments in Octave Programs::\n@end menu\n\n@node Invoking Octave from the Command Line\n@section Invoking Octave from the Command Line\n\nNormally, Octave is used interactively by running the program\n@samp{octave} without any arguments.  Once started, Octave reads\ncommands from the terminal until you tell it to exit.\n\nYou can also specify the name of a file on the command line, and Octave\nwill read and execute the commands from the named file and then exit\nwhen it is finished.\n\nYou can further control how Octave starts by using the command-line\noptions described in the next section, and Octave itself can remind you\nof the options available.  Type @samp{octave --help} to display all\navailable options and briefly describe their use (@samp{octave -h} is a\nshorter equivalent).\n\n@menu\n* Command Line Options::\n* Startup Files::\n@end menu\n\n@node Command Line Options\n@subsection Command Line Options\n@cindex Octave command options\n@cindex command options\n@cindex options, Octave command\n\nHere is a complete list of the command line options that Octave\naccepts.\n\n@table @code\n\n@item --built-in-docstrings-file @var{filename}\n@cindex @sortas{options, Octave command --built-in-docstrings-file} @ @ @code{--built-in-docstrings-file @var{filename}}\nSpecify the name of the file containing documentation strings for the\nbuilt-in functions of Octave.  This value is normally correct and should\nonly need to be specified in extraordinary situations.\n\n@c FIXME: Disabled debug option for parser 2023-12-29.\n@c Uncomment and restore code if Octave adds capability to\n@c immediately enter debug mode for a script.\n@c @item  --debug\n@c @itemx -d\n@c @cindex @sortas{options, Octave command --debug} @ @ @code{--debug}\n@c @cindex @sortas{options, Octave command -d} @ @ @code{-d}\n@c Enter debugging mode.\n\n@item --doc-cache-file @var{filename}\n@cindex @sortas{options, Octave command --doc-cache-file} @ @ @code{--doc-cache-file @var{filename}}\nSpecify the name of the documentation cache file to use.  The value of\n@var{filename} specified on the command line will override any value of\n@w{@env{OCTAVE_DOC_CACHE_FILE}}@ found in the environment, but not any commands\nin the system or user startup files that use the @code{doc_cache_file}\nfunction.\n\n@item  --echo-commands\n@itemx -x\n@cindex @sortas{options, Octave command --echo-commands} @ @ @code{--echo-commands}\n@cindex @sortas{options, Octave command -x} @ @ @code{-x}\nEcho commands as they are executed.\n\n@item  --eval @var{code}\n@itemx -e @var{code}\n@cindex @sortas{options, Octave command --eval} @ @ @code{--eval @var{code}}\nEvaluate @var{code} and exit when finished unless @option{--persist} is also\nspecified.\n\n@item --exec-path @var{path}\n@cindex @sortas{options, Octave command --exec-path} @ @ @code{--exec-path @var{path}}\nSpecify the path to search for programs to run.  The value of @var{path}\nspecified on the command line will override any value of\n@w{@env{OCTAVE_EXEC_PATH}}@ found in the environment, but not any commands\nin the system or user startup files that call the\n@w{@env{EXEC_PATH}}@ function.\n\n@item  --gui\n@itemx -g\n@cindex @sortas{options, Octave command --gui} @ @ @code{--gui}\nStart the graphical user interface (GUI).\n\n@item  --help\n@itemx -h\n@cindex @sortas{options, Octave command --help} @ @ @code{--help}\n@cindex @sortas{options, Octave command -h} @ @ @code{-h}\nPrint short help message and exit.\n\n@item --image-path @var{path}\n@cindex @sortas{options, Octave command --image-path} @ @ @code{--image-path @var{path}}\nAdd path to the head of the search path for images.  The value of\n@var{path} specified on the command line will override any value of\n@w{@env{OCTAVE_IMAGE_PATH}}@ found in the environment, but not any commands\nin the system or user startup files that call the\n@w{@env{IMAGE_PATH}}@ function.\n\n@item --info-file @var{filename}\n@cindex @sortas{options, Octave command --info-file} @ @ @code{--info-file @var{filename}}\nSpecify the name of the info file to use.  The value of @var{filename}\nspecified on the command line will override any value of\n@w{@env{OCTAVE_INFO_FILE}}@ found in the environment, but not any commands\nin the system or user startup files that use the @code{info_file}\nfunction.\n\n@item --info-program @var{program}\n@cindex @sortas{options, Octave command --info-program} @ @ @code{--info-program @var{program}}\nSpecify the name of the info program to use.  The value of @var{program}\nspecified on the command line will override any value of\n@w{@env{OCTAVE_INFO_PROGRAM}}@ found in the environment, but not any\ncommands in the system or user startup files that use the\n@code{info_program} function.\n\n@item  --init-trace\n@cindex @sortas{options, Octave command --init-trace} @ @ @code{--init-trace}\nPrint the name of each configuration as it is read and executed during\ninitialization.\n\n@item  --interactive\n@itemx -i\n@cindex @sortas{options, Octave command --interactive} @ @ @code{--interactive}\n@cindex @sortas{options, Octave command -i} @ @ @code{-i}\nForce interactive behavior.  This can be useful for running Octave via a\nremote shell command or inside an Emacs shell buffer.\n\n@item --line-editing\n@cindex @sortas{options, Octave command --line-editing} @ @ @code{--line-editing}\nForce readline use for command-line editing.\n\n@item  --no-gui\n@itemx -G\n@cindex @sortas{options, Octave command --no-gui} @ @ @code{--no-gui}\nDisable the graphical user interface (GUI) and use the command line\ninterface (CLI) instead.  This is the default behavior, but this option\nmay be useful to override a previous @option{--gui}.\n\n@item  --no-history\n@itemx -H\n@cindex @sortas{options, Octave command --no-history} @ @ @code{--no-history}\n@cindex @sortas{options, Octave command -H} @ @ @code{-H}\nDisable recording of command-line history.\n\n@item  --no-init-all\n@itemx --norc\n@itemx -f\n@cindex @sortas{options, Octave command --no-init-all} @ @ @code{--no-init-all}\n@cindex @sortas{options, Octave command --norc} @ @ @code{--norc}\n@cindex @sortas{options, Octave command -f} @ @ @code{-f}\nDon't read any of the system or user initialization files at startup.\nThis is equivalent to using both of the options @option{--no-site-file}\nand @option{--no-init-user}.\n\n@item --no-init-path\n@cindex @sortas{options, Octave command --no-init-path} @ @ @code{--no-init-path}\nDon't initialize the search path for function files to include default\nlocations.\n\n@item --no-init-site\n@cindex @sortas{options, Octave command --no-init-site} @ @ @code{--no-init-site}\n@cindex site startup file\nDon't read the site-wide @file{octaverc} initialization files.\n\n@item --no-init-user\n@cindex @sortas{options, Octave command --no-init-user} @ @ @code{--no-init-user}\n@cindex @sortas{octaverc ~/.octaverc} @code{~/.octaverc}\n@cindex @sortas{octaverc .octaverc} @code{.octaverc}\nDon't read the user initialization files @file{~/.octaverc} and\n@file{.octaverc}.\n\n@item --no-line-editing\n@cindex @sortas{options, Octave command --no-line-editing} @ @ @code{--no-line-editing}\nDisable command-line editing.\n\n@item  --no-window-system\n@itemx -W\n@cindex @sortas{options, Octave command --no-window-system} @ @ @code{--no-window-system}\n@cindex @sortas{options, Octave command -W} @ @ @code{-W}\nDisable use of a windowing system including graphics.  This forces a\nstrictly terminal-only environment.\n\n@item  --path @var{path}\n@itemx -p @var{path}\n@cindex @sortas{options, Octave command --path} @ @ @code{--path @var{path}}\n@cindex @sortas{options, Octave command -p} @ @ @code{-p @var{path}}\nAdd path to the head of the search path for function files.  The\nvalue of @var{path} specified on the command line will override any value\nof @w{@env{OCTAVE_PATH}}@ found in the environment, but not any commands in the\nsystem or user startup files that set the internal load path through one\nof the path functions.\n\n@item --persist\n@cindex @sortas{options, Octave command --persist} @ @ @code{--persist}\nGo to interactive mode after @option{--eval} or reading from a file\nnamed on the command line.\n\n@item  --quiet\n@itemx --silent\n@itemx -q\n@cindex @sortas{options, Octave command --quiet} @ @ @code{--quiet}\n@cindex @sortas{options, Octave command --silent} @ @ @code{--silent}\n@cindex @sortas{options, Octave command -q} @ @ @code{-q}\nDon't print the usual greeting and version message at startup.\n\n@item --texi-macros-file @var{filename}\n@cindex @sortas{options, Octave command --texi-macros-file} @ @ @code{--texi-macros-file @var{filename}}\nSpecify the name of the file containing Texinfo macros for use by makeinfo.\n\n@item  --traditional\n@itemx --braindead\n@cindex @sortas{options, Octave command --traditional} @ @ @code{--traditional}\n@cindex @sortas{options, Octave command --braindead} @ @ @code{--braindead}\nFor compatibility with @sc{matlab}, set initial values for\nuser preferences to the following values\n\n@example\n@group\nPS1                             = \">> \"\nPS2                             = \"\"\nPS4                             = \"\"\nbeep_on_error                   = true\nconfirm_recursive_rmdir         = false\ncrash_dumps_octave_core         = false\noptimize_diagonal_matrix        = false\noptimize_permutation_matrix     = false\noptimize_range                  = false\nfixed_point_format              = true\nhistory_timestamp_format_string = \"%%-- %D %I:%M %p --%%\"\nprint_struct_array_contents     = true\nsave_default_options            = \"-mat-binary\"\nstruct_levels_to_print          = 0\n@end group\n@end example\n\n@noindent\nand disable the following warnings\n\n@example\n@group\nOctave:abbreviated-property-match\nOctave:colon-nonscalar-argument\nOctave:data-file-in-path\nOctave:empty-index\nOctave:function-name-clash\nOctave:possible-matlab-short-circuit-operator\n@end group\n@end example\n\n@noindent\nNote that this does not enable the @code{Octave:language-extension}\nwarning, which you might want if you want to be told about writing code\nthat works in Octave but not @sc{matlab} (@pxref{XREFwarning,,warning},\n@ref{XREFwarning_ids,,warning_ids}).\n\n@item  --version\n@itemx -v\n@cindex @sortas{options, Octave command --version} @ @ @code{--version}\n@cindex @sortas{options, Octave command -v} @ @ @code{-v}\nPrint program version information and exit.\n\n@item @var{file}\nExecute commands from @var{file}.  Exit when done unless @option{--persist} is\nalso specified.\n@end table\n\nOctave also includes several functions which return information about the\ncommand line, including the number of arguments and all of the options.\n\n@DOCSTRING(argv)\n\n@DOCSTRING(cmdline_options)\n\n@DOCSTRING(program_name)\n\n@DOCSTRING(program_invocation_name)\n\nHere is an example of using these functions to reproduce the command\nline which invoked Octave.\n\n@example\n@group\nprintf (\"%s\", program_name ());\narg_list = argv ();\nfor i = 1:nargin\n  printf (\" %s\", arg_list@{i@});\nendfor\nprintf (\"\\n\");\n@end group\n@end example\n\n@noindent\n@xref{Indexing Cell Arrays}, for an explanation of how to retrieve objects\nfrom cell arrays, and @ref{Defining Functions}, for information about the\nvariable @code{nargin}.\n\n@node Startup Files\n@subsection Startup Files\n@cindex initialization\n@cindex startup\n\nWhen Octave starts, it looks for commands to execute from the files in\nthe following list.  These files may contain any valid Octave commands,\nincluding function definitions.\n\n@cindex startup files\n\n@table @code\n@item @var{octave-home}/share/octave/site/m/startup/octaverc\n@cindex site startup file\nwhere @code{@var{octave-home}} is the directory in which Octave is installed\n(the default is @file{/usr/local}).\nThis file is provided so that changes to the default Octave environment\ncan be made globally for all users at your site for all versions of Octave\nyou have installed.  Care should be taken when making changes to this file\nsince all users of Octave at your site will be affected.  The default file\nmay be overridden by the environment variable @w{@env{OCTAVE_SITE_INITFILE}}.\n\n@item @var{octave-home}/share/octave/@var{version}/m/startup/octaverc\n@cindex version startup file\nwhere @code{@var{octave-home}} is the directory in which Octave is installed\n(the default is @file{/usr/local}), and @code{@var{version}} is the version\nnumber of Octave.  This file is provided so that changes to the default\nOctave environment can be made globally for all users of a particular version\nof Octave.  Care should be taken when making changes to this file since all\nusers of Octave at your site will be affected.  The default file may be\noverridden by the environment variable @w{@env{OCTAVE_VERSION_INITFILE}}.\n\n@item @var{config-dir}/octave/octaverc\n@cindex personal startup file\nwhere @code{@var{config-dir}} is the platform-dependent location for user\nlocal configuration files (e.g., @w{@env{$XDG_CONFIG_HOME}}@ on many Unix-like\noperating systems or @w{@env{%APPDATA%}}@ on Windows).\n\n@item ~/.octaverc\n@cindex personal startup file\n@cindex @sortas{octaverc ~/.octaverc} @code{~/.octaverc}\nThis file is used to make personal changes to the default Octave environment.\n\n@item .octaverc\n@cindex project startup file\n@cindex @sortas{octaverc .octaverc} @code{.octaverc}\nThis file can be used to make changes to the default Octave environment for a\nparticular project.  Octave searches for this file in the current directory\nafter it reads @file{~/.octaverc}.  Any use of the @code{cd} command in the\n@file{~/.octaverc} file will affect the directory where Octave searches for\n@file{.octaverc}.\n\nIf you start Octave in your home directory, commands from the file\n@file{~/.octaverc} will only be executed once.\n\n@item startup.m\n@cindex @code{startup.m}\nThis file is used to make personal changes to the default Octave environment.\nIt is executed for @sc{matlab} compatibility, but @file{~/.octaverc} is the\npreferred location for configuration changes.\n@end table\n\nA message will be displayed as each of the startup files is read if you\ninvoke Octave with the @option{--verbose} option but without the\n@option{--quiet} option.\n\nThe startup files are always processed in the system's locale charset\n(independent of the m-file encoding that is set, for example, in the GUI\nproperties).  In other words, the system's locale charset is in effect until a\nuser manually sets the m-file encoding (e.g., in one of the startup files) and\ntriggers re-parsing of any relevant m-files.  Octave can be forced to use a\nnew encoding with the function @code{mfile_encoding}:\n\n@example\n@group\nmfile_encoding (\"utf-8\");  # set new encoding\nclear (\"functions\");  # re-parse all .m files in the new encoding\n@end group\n@end example\n\nThis changes the encoding that is used to interpret all subsequently run\nstartup and m-files (not including the currently executing file).\n\n@node Quitting Octave\n@section Quitting Octave\n@cindex exiting octave\n@cindex quitting octave\n@cindex finish.m\n@cindex site exiting file\n\nShutdown is initiated with the @code{exit} or @code{quit} commands (they are\nequivalent).  Similar to startup, Octave has a shutdown process that can be\ncustomized by user script files.  During shutdown Octave will search for the\nscript file @file{finish.m} in the function load path.  Commands to save all\nworkspace variables or cleanup temporary files may be placed there.  Additional\nfunctions to execute on shutdown may be registered with @code{atexit}.\n\n@DOCSTRING(quit)\n\n@DOCSTRING(atexit)\n\n@node Getting Help\n@section Commands for Getting Help\n@cindex online help\n@cindex help, online\n\nThe entire text of this manual is available from the Octave prompt\nvia the command @kbd{doc}.  In addition, the documentation for\nindividual user-written functions and variables is also available via\nthe @kbd{help} command.  This section describes the commands used for\nreading the manual and the documentation strings for user-supplied\nfunctions and variables.  @xref{Function Files}, for more information\nabout how to document the functions you write.\n\n@DOCSTRING(help)\n\n@DOCSTRING(doc)\n\n@DOCSTRING(lookfor)\n\nTo see what is new in the current release of Octave, use the @code{news}\nfunction.\n\n@DOCSTRING(news)\n\n@DOCSTRING(info)\n\n@DOCSTRING(warranty)\n\nThe following functions can be used to change which programs are used\nfor displaying the documentation, and where the documentation can be\nfound.\n\n@DOCSTRING(info_file)\n\n@DOCSTRING(info_program)\n\n@DOCSTRING(makeinfo_program)\n\n@DOCSTRING(texi_macros_file)\n\n@DOCSTRING(doc_cache_file)\n\n@DOCSTRING(built_in_docstrings_file)\n\n@DOCSTRING(suppress_verbose_help_message)\n\nThe following functions are principally used internally by Octave for\ngenerating the documentation.  They are documented here for completeness\nand because they may occasionally be useful for users.\n\n@DOCSTRING(doc_cache_create)\n\n@DOCSTRING(get_help_text)\n\n@DOCSTRING(get_help_text_from_file)\n\n@DOCSTRING(get_first_help_sentence)\n\n@node Command Line Editing\n@section Command Line Editing\n@cindex command-line editing\n@cindex editing the command line\n\nOctave uses the GNU Readline library to provide an extensive set of\ncommand-line editing and history features.  Only the most common\nfeatures are described in this manual.  In addition, all of the editing\nfunctions can be bound to different key strokes at the user's discretion.\nThis manual assumes no changes from the default Emacs bindings.  See the GNU\nReadline Library manual for more information on customizing Readline and\nfor a complete feature list.\n\nTo insert printing characters (letters, digits, symbols, etc.), simply\ntype the character.  Octave will insert the character at the cursor and\nadvance the cursor forward.\n\nMany of the command-line editing functions operate using control\ncharacters.  For example, the character @kbd{Control-a} moves the cursor\nto the beginning of the line.  To type @kbd{C-a}, hold down @key{CTRL}\nand then press @key{a}.  In the following sections, control characters\nsuch as @kbd{Control-a} are written as @kbd{C-a}.\n\nAnother set of command-line editing functions use Meta characters.  To\ntype @kbd{M-u}, hold down the @key{META} key and press @key{u}.  Depending\non the keyboard, the @key{META} key may be labeled @key{ALT} or\neven @key{WINDOWS}.  If your terminal does not have a @key{META} key, you\ncan still type Meta characters using two-character sequences starting\nwith @kbd{ESC}.  Thus, to enter @kbd{M-u}, you would type\n@key{ESC} @key{u}.  The @kbd{ESC} character sequences are also allowed on\nterminals with real Meta keys.  In the following sections, Meta\ncharacters such as @kbd{Meta-u} are written as @kbd{M-u}.\n\n\n@menu\n* Cursor Motion::\n* Killing and Yanking::\n* Commands for Changing Text::\n* Commands for Completion::\n* Commands for Manipulating the History::\n* Customizing readline::\n* Customizing the Prompt::\n* Diary and Echo Commands::\n@end menu\n\n@node Cursor Motion\n@subsection Cursor Motion\n\nThe following commands allow you to position the cursor.\n\n@table @kbd\n@item C-b\nMove back one character.\n\n@item C-f\nMove forward one character.\n\n@item @key{BACKSPACE}\nDelete the character to the left of the cursor.\n\n@item @key{DEL}\nDelete the character underneath the cursor.\n\n@item C-d\nDelete the character underneath the cursor.\n\n@item M-f\nMove forward a word.\n\n@item M-b\nMove backward a word.\n\n@item C-a\nMove to the start of the line.\n\n@item C-e\nMove to the end of the line.\n\n@item C-l\nClear the screen, reprinting the current line at the top.\n\n@item  C-_\n@itemx C-/\nUndo the last action.  You can undo all the way back to an empty line.\n\n@item M-r\nUndo all changes made to this line.  This is like typing the `undo'\ncommand enough times to get back to the beginning.\n@end table\n\nThe above table describes the most basic possible keystrokes that you need\nin order to do editing of the input line.  On most terminals, you can\nalso use the left and right arrow keys in place of @kbd{C-f} and @kbd{C-b}\nto move forward and backward.\n\nNotice how @kbd{C-f} moves forward a character, while @kbd{M-f} moves\nforward a word.  It is a loose convention that control keystrokes\noperate on characters while meta keystrokes operate on words.\n\n@cindex clearing the screen\n\nThe function @code{clc} will allow you to clear the screen from within\nOctave programs.\n\n@DOCSTRING(clc)\n\n@node Killing and Yanking\n@subsection Killing and Yanking\n\n@dfn{Killing} text means to delete the text from the line, but to save\nit away for later use, usually by @dfn{yanking} it back into the line.\nIf the description for a command says that it `kills' text, then you can\nbe sure that you can get the text back in a different (or the same)\nplace later.\n\nHere is the list of commands for killing text.\n\n@table @kbd\n@item C-k\nKill the text from the current cursor position to the end of the line.\n\n@item M-d\nKill from the cursor to the end of the current word, or if between\nwords, to the end of the next word.\n\n@item M-@key{DEL}\nKill from the cursor to the start of the previous word, or if between\nwords, to the start of the previous word.\n\n@item C-w\nKill from the cursor to the previous whitespace.  This is different than\n@kbd{M-@key{DEL}} because the word boundaries differ.\n@end table\n\nAnd, here is how to @dfn{yank} the text back into the line.  Yanking\nmeans to copy the most-recently-killed text from the kill buffer.\n\n@table @kbd\n@item C-y\nYank the most recently killed text back into the buffer at the cursor.\n\n@item M-y\nRotate the kill-ring, and yank the new top.  You can only do this if\nthe prior command is @kbd{C-y} or @kbd{M-y}.\n@end table\n\nWhen you use a kill command, the text is saved in a @dfn{kill-ring}.\nAny number of consecutive kills save all of the killed text together, so\nthat when you yank it back, you get it in one clean sweep.  The kill\nring is not line specific; the text that you killed on a previously\ntyped line is available to be yanked back later, when you are typing\nanother line.\n\n@node Commands for Changing Text\n@subsection Commands for Changing Text\n\nThe following commands can be used for entering characters that would\notherwise have a special meaning (e.g., @key{TAB}, @kbd{C-q}, etc.), or\nfor quickly correcting typing mistakes.\n\n@table @kbd\n@item  C-q\n@itemx C-v\nAdd the next character that you type to the line verbatim.  This is\nhow to insert things like @kbd{C-q} for example.\n\n@item M-@key{TAB}\nInsert a tab character.\n\n@item C-t\nDrag the character before the cursor forward over the character at the\ncursor, also moving the cursor forward.  If the cursor is at the end of\nthe line, then transpose the two characters before it.\n\n@item M-t\nDrag the word behind the cursor past the word in front of the cursor\nmoving the cursor over that word as well.\n\n@item M-u\nUppercase the characters following the cursor to the end of the current\n(or following) word, moving the cursor to the end of the word.\n\n@item M-l\nLowercase the characters following the cursor to the end of the current\n(or following) word, moving the cursor to the end of the word.\n\n@item M-c\nUppercase the character following the cursor (or the beginning of the\nnext word if the cursor is between words), moving the cursor to the end\nof the word.\n@end table\n\n@node Commands for Completion\n@subsection Commands for Completion\n@cindex command completion\n\nThe following commands allow Octave to complete command and variable\nnames for you.\n\n@table @kbd\n@item @key{TAB}\nAttempt to do completion on the text before the cursor.  Octave can\ncomplete the names of commands and variables.\n\n@item M-?\nList the possible completions of the text before the cursor.\n@end table\n\n@DOCSTRING(completion_append_char)\n\n@DOCSTRING(completion_matches)\n\n@node Commands for Manipulating the History\n@subsection Commands for Manipulating the History\n@cindex command history\n@cindex input history\n@cindex history of commands\n\nOctave normally keeps track of the commands you type so that you can\nrecall previous commands to edit or execute them again.  When you exit\nOctave, the most recent commands you have typed, up to the number\nspecified by the variable @code{history_size}, are saved in a file.\nWhen Octave starts, it loads an initial list of commands from the file\nnamed by the variable @code{history_file}.\n\nHere are the commands for simple browsing and searching the history\nlist.\n\n@table @kbd\n@item  @key{LFD}\n@itemx @key{RET}\nAccept the current line regardless of where the cursor is.  If the line is\nnon-empty, add it to the history list.  If the line was a history\nline, then restore the history line to its original state.\n\n@item C-p\nMove `up' through the history list.\n\n@item C-n\nMove `down' through the history list.\n\n@item M-<\nMove to the first line in the history.\n\n@item M->\nMove to the end of the input history, i.e., the line you are entering!\n\n@item C-r\nSearch backward starting at the current line and moving `up' through\nthe history as necessary.  This is an incremental search.\n\n@item C-s\nSearch forward starting at the current line and moving `down' through\nthe history as necessary.\n@end table\n\nOn most terminals, you can also use the up and down arrow keys in place\nof @kbd{C-p} and @kbd{C-n} to move through the history list.\n\nIn addition to the keyboard commands for moving through the history\nlist, Octave provides three functions for viewing, editing, and\nre-running chunks of commands from the history list.\n\n@DOCSTRING(history)\n\n@DOCSTRING(edit_history)\n\n@DOCSTRING(run_history)\n\n@noindent\nOctave also allows you customize the details of when, where, and how history\nis saved.\n\n@DOCSTRING(history_save)\n\n@DOCSTRING(history_control)\n\n@DOCSTRING(history_file)\n\n@DOCSTRING(history_size)\n\n@DOCSTRING(history_timestamp_format_string)\n\n@DOCSTRING(EDITOR)\n\n@node Customizing readline\n@subsection Customizing @code{readline}\n@cindex @sortas{inputrc ~/.inputrc} @code{~/.inputrc}\n@cindex customizing @code{readline}\n@cindex @code{readline} customization\n\nOctave uses the GNU Readline library for command-line editing and\nhistory features.  Readline is very flexible and can be modified through\na configuration file of commands (See the GNU Readline library for the\nexact command syntax).  The default configuration file is normally\n@file{~/.inputrc}.\n\nOctave provides two commands for initializing Readline and thereby changing\nthe command line behavior.\n\n@DOCSTRING(readline_read_init_file)\n\n@DOCSTRING(readline_re_read_init_file)\n\n@node Customizing the Prompt\n@subsection Customizing the Prompt\n@cindex prompt customization\n@cindex customizing the prompt\n\nThe following variables are available for customizing the appearance of\nthe command-line prompts.  Octave allows the prompt to be customized by\ninserting a number of backslash-escaped special characters that are\ndecoded as follows:\n\n@table @samp\n@item \\t\nThe time.\n\n@item \\d\nThe date.\n\n@item \\n\nBegins a new line by printing the equivalent of a carriage return\nfollowed by a line feed.\n\n@item \\s\nThe name of the program (usually just @samp{octave}).\n\n@item \\w\nThe current working directory.\n\n@item \\W\nThe basename of the current working directory.\n\n@item \\u\nThe username of the current user.\n\n@item \\h\nThe hostname, up to the first `.'.\n\n@item \\H\nThe hostname.\n\n@item \\#\nThe command number of this command, counting from when Octave starts.\n\n@item \\!\nThe history number of this command.  This differs from @samp{\\#} by the\nnumber of commands in the history list when Octave starts.\n\n@item \\$\nIf the effective UID is 0, a @samp{#}, otherwise a @samp{$}.\n\n@item \\nnn\nThe character whose character code in octal is @var{nnn}.\n\n@item \\\\\nA backslash.\n@end table\n\n@DOCSTRING(PS1)\n\n@DOCSTRING(PS2)\n\n@DOCSTRING(PS4)\n\n@node Diary and Echo Commands\n@subsection Diary and Echo Commands\n@cindex diary of commands and output\n@cindex command and output logs\n@cindex logging commands and output\n@cindex echoing executing commands\n@cindex command echoing\n\nOctave's diary feature allows you to keep a log of all or part of an\ninteractive session by recording the input you type and the output that\nOctave produces in a separate file.\n\n@DOCSTRING(diary)\n\nSometimes it is useful to see the commands in a function or script as\nthey are being evaluated.  This can be especially helpful for debugging\nsome kinds of problems.\n\n@DOCSTRING(echo)\n\n@node How Octave Reports Errors\n@section How Octave Reports Errors\n@cindex error messages\n@cindex messages, error\n\nOctave reports two kinds of errors for invalid programs.\n\nA @dfn{parse error} occurs if Octave cannot understand something you\nhave typed.  For example, if you misspell a keyword,\n\n@example\noctave:13> function z = f (x, y) z = x ||| 2; endfunction\n@end example\n\n@noindent\nOctave will respond immediately with a message like this:\n\n@example\n@group\nparse error:\n\n  syntax error\n\n>>> function z = f (x, y) z = x ||| y; endfunction\n                                  ^\n@end group\n@end example\n\n@noindent\nFor most parse errors, Octave uses a caret (@samp{^}) to mark the point\non the line where it was unable to make sense of your input.  In this\ncase, Octave generated an error message because the keyword for\nthe logical or operator (@code{||}) was misspelled.  It marked the error\nat the third @samp{|} because the code leading up to this was correct\nbut the final @samp{|} was not understood.\n\nIn the case where Octave is reading instructions from a function or script\nfile, it can be configured to report parsing errors in minimal form (file name,\nline number, column number) or in an extended form that prints the problematic\nline of code and a caret (@samp{^}) at the point where parsing failed.\n@xref{XREFdiagnostics_show_caret,,diagnostics_show_caret}.\n\nAnother class of error message occurs at evaluation time.  These\nerrors are called @dfn{run-time errors}, or sometimes\n@dfn{evaluation errors}, because they occur when your program is being\n@dfn{run}, or @dfn{evaluated}.  For example, if after correcting the\nmistake in the previous function definition, you type\n\n@example\noctave:13> f ()\n@end example\n\n@noindent\nOctave will respond with\n\n@example\n@group\nerror: `x' undefined near line 1 column 24\nerror: called from:\nerror:   f at line 1, column 22\n@end group\n@end example\n\n@noindent\nThis error message has several parts, and gives quite a bit of\ninformation to help you locate the source of the error.  The messages\nare generated from the point of the innermost error, and provide a\ntraceback of enclosing expressions and function calls.\n\nIn the example above, the first line indicates that a variable named\n@samp{x} was found to be undefined near line 1 and column 24 of some\nfunction or expression.  For errors occurring within functions, lines\nare counted from the beginning of the file containing the function\ndefinition.  For errors occurring outside of an enclosing function,\nthe line number indicates the input line number, which is usually displayed\nin the primary prompt string.\n\nThe second and third lines of the error message indicate that the error\noccurred within the function @code{f}.  If the function @code{f} had been\ncalled from within another function, for example, @code{g}, the list of\nerrors would have ended with one more line:\n\n@example\nerror:   g at line 1, column 17\n@end example\n\nThese lists of function calls make it fairly easy to trace the\npath your program took before the error occurred, and to correct the\nerror before trying again.\n\n@node Executable Octave Programs\n@section Executable Octave Programs\n@cindex executable scripts\n@cindex scripts\n@cindex batch processing\n@cindex self contained programs\n@cindex program, self contained\n\n@opindex @code{#!} self-contained script\nOnce you have learned Octave, you may want to write self-contained\nOctave scripts, using the @samp{#!} script mechanism.  You can do this\non GNU systems and on many Unix systems @footnote{The @samp{#!}\nmechanism works on Unix systems derived from Berkeley Unix, System V\nRelease 4, and some System V Release 3 systems.}.\n\nSelf-contained Octave scripts are useful when you want to write a\nprogram which users can invoke without knowing that the program is\nwritten in the Octave language.  Octave scripts are also used for batch\nprocessing of data files.  Once an algorithm has been developed and tested\nin the interactive portion of Octave, it can be committed to an executable\nscript and used again and again on new data files.\n\nAs a trivial example of an executable Octave script, you might create a\ntext file named @file{hello}, containing the following lines:\n\n@example\n@group\n#! @var{octave-interpreter-name} -qf\n# a sample Octave program\nprintf (\"Hello, world!\\n\");\n@end group\n@end example\n\n@noindent\n(where @var{octave-interpreter-name} should be replaced with the full\npath and name of your Octave binary).  Note that this will only work if\n@samp{#!} appears at the very beginning of the file.  After making the\nfile executable (with the @code{chmod} command on Unix systems), you can\nsimply type:\n\n@example\nhello\n@end example\n\n@noindent\nat the shell, and the system will arrange to run Octave as if you had\ntyped:\n\n@example\noctave hello\n@end example\n\nThe line beginning with @samp{#!} lists the full path and filename of an\ninterpreter to be run, and an optional initial command line argument to\npass to that interpreter.  The operating system then runs the\ninterpreter with the given argument and the full argument list of the\nexecuted program.  The first argument in the list is the full filename\nof the Octave executable.  The rest of the argument list will either be\noptions to Octave, or data files, or both.  The @samp{-qf} options are\nusually specified in stand-alone Octave programs to prevent them from\nprinting the normal startup message, and to keep them from behaving\ndifferently depending on the contents of a particular user's\n@file{~/.octaverc} file.  @xref{Invoking Octave from the Command Line}.\n\nNote that some operating systems may place a limit on the number of\ncharacters that are recognized after @samp{#!}.  Also, the arguments\nappearing in a @samp{#!} line are parsed differently by various\nshells/systems.  The majority of them group all the arguments together in one\nstring and pass it to the interpreter as a single argument.  In this case, the\nfollowing script:\n\n@example\n@group\n#! @var{octave-interpreter-name} -q -f # comment\n@end group\n@end example\n\n@noindent\nis equivalent to typing at the command line:\n\n@example\n@group\noctave \"-q -f # comment\"\n@end group\n@end example\n\n@noindent\nwhich will produce an error message.  Unfortunately, it is\nnot possible for Octave to determine whether it has been called from the\ncommand line or from a @samp{#!} script, so some care is needed when using the\n@samp{#!} mechanism.\n\n@menu\n* Passing Arguments to Executable Scripts::\n* Dual-Purpose Executable Scripts and Octave Functions::\n@end menu\n\n@node Passing Arguments to Executable Scripts\n@subsection Passing Arguments to Executable Scripts\n\nNote that when Octave is started from an executable script, the built-in\nfunction @code{argv} returns a cell array containing the command line\narguments passed to the executable Octave script, not the arguments\npassed to the Octave interpreter on the @samp{#!} line of the script.\nFor example, the following program will reproduce the command line that\nwas used to execute the script, not @samp{-qf}.\n\n@example\n@group\n#! /bin/octave -qf\nprintf (\"%s\", program_name ());\narg_list = argv ();\nfor i = 1:nargin\n  printf (\" %s\", arg_list@{i@});\nendfor\nprintf (\"\\n\");\n@end group\n@end example\n\n@node Dual-Purpose Executable Scripts and Octave Functions\n@subsection Dual-Purpose Executable Scripts and Octave Functions\n\nTo write m-files that can act as executable programs when called from the shell\nor as normal functions when called from within Octave, use default input\narguments initialized with the @code{argv} function.\n\nIf a function is called from the shell Octave will not pass any input\nparameters to the function and therefore the default argument is used.  But\nwhen a function is called from the interpreter any arguments @emph{are} passed\nto the function and these override the default.\n\nAdditionally, the file must end with the extension @file{.m} so that the\ninterpreter will recognize it as an Octave function.  Finally, the output from\n@code{argv} is a cell array of strings.  It may be necessary to convert this\nto a numeric value with @code{str2double} or @code{str2num} before processing.\n\nAs a complete example, consider the following code located in the file\n@file{mysin.m}.\n\n@example\n@group\n#! /bin/octave -qf\nfunction retval = mysin (x = str2double (argv()@{end@}))\n  retval = sin (x)\nendfunction\n@end group\n@end example\n\nThis can be called from the shell with\n\n@example\nmysin.m 1.5\n@end example\n\n@noindent\nor from Octave with\n\n@example\nmysin (1.5)\n@end example\n\n@node Comments in Octave Programs\n@section Comments in Octave Programs\n@cindex comments\n@cindex use of comments\n@cindex documenting Octave programs\n\nA @dfn{comment} is some text that is included in a program for the sake\nof human readers, and which is NOT an executable part of the program.\nComments can explain what the program does, and how it works.  Nearly all\nprogramming languages have provisions for comments, because programs are\ntypically hard to understand without them.\n\n@menu\n* Single Line Comments::\n* Block Comments::\n* Comments and the Help System::\n@end menu\n\n@node Single Line Comments\n@subsection Single Line Comments\n\n@opindex @code{#} comment marker\n@opindex @code{%} comment marker\nIn the Octave language, a comment starts with either the sharp sign\ncharacter, @samp{#}, or the percent symbol @samp{%} and continues to the\nend of the line.  Any text following the sharp sign or percent symbol is\nignored by the Octave interpreter and not executed.  The following example\nshows whole line and partial line comments.\n\n@example\n@group\nfunction countdown\n  # Count down for main rocket engines\n  disp (3);\n  disp (2);\n  disp (1);\n  disp (\"Blast Off!\");  # Rocket leaves pad\nendfunction\n@end group\n@end example\n\n@node Block Comments\n@subsection Block Comments\n@cindex block comments\n@cindex multi-line comments\n\n@opindex @code{#@{} block comment marker\n@opindex @code{%@{} block comment marker\nEntire blocks of code can be commented by enclosing the code between\nmatching @samp{#@{} and @samp{#@}} or @samp{%@{} and @samp{%@}} markers.\nFor example,\n\n@example\n@group\nfunction quick_countdown\n  # Count down for main rocket engines\n  disp (3);\n #@{\n  disp (2);\n  disp (1);\n #@}\n  disp (\"Blast Off!\");  # Rocket leaves pad\nendfunction\n@end group\n@end example\n\n@noindent\nwill produce a very quick countdown from @qcode{'3'} to @qcode{\"Blast Off\"} as\nthe lines \"@code{disp (2);}\" and \"@code{disp (1);}\" won't be executed.\n\nThe block comment markers must appear alone as the only characters on a line\n(excepting whitespace) in order to be parsed correctly.\n\n@node Comments and the Help System\n@subsection Comments and the Help System\n@cindex documenting functions\n@cindex documenting user scripts\n@cindex help, user-defined functions\n\nThe @code{help} command (@pxref{Getting Help}) is able to find the first\nblock of comments in a function and return those as a documentation\nstring.  This means that the same commands used to get help\non built-in functions are available for properly formatted user-defined\nfunctions.  For example, after defining the function @code{f} below,\n\n@example\n@group\nfunction xdot = f (x, t)\n\n# usage: f (x, t)\n#\n# This function defines the right-hand\n# side functions for a set of nonlinear\n# differential equations.\n\n  r = 0.25;\n  @dots{}\nendfunction\n@end group\n@end example\n\n@noindent\nthe command @kbd{help f} produces the output\n\n@example\n@group\n usage: f (x, t)\n\n This function defines the right-hand\n side functions for a set of nonlinear\n differential equations.\n@end group\n@end example\n\nAlthough it is possible to put comment lines into keyboard-composed,\nthrow-away Octave programs, it usually isn't very useful because the\npurpose of a comment is to help you or another person understand the\nprogram at a later time.\n\nThe @code{help} parser currently only recognizes single line comments\n(@pxref{Single Line Comments}) and not block comments for the initial\nhelp text.\n"
  },
  {
    "path": "doc/interpreter/bugs.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@c The text of this file appears in the file BUGS in the Octave\n@c distribution, as well as in the Octave manual.\n\n@ifclear BUGSONLY\n@node Trouble\n@appendix Known Causes of Trouble\n@end ifclear\n\n@ifset BUGSONLY\n@include macros.texi\n\nThis file documents known bugs in Octave and describes where and how to\nreport any bugs that you may find.\n\nCopyright (C) 1996-2026 The Octave Project Developers\nmodify it freely as long as you preserve this copyright notice and\npermission notice.\n\n@node Trouble\n@chapter Known Causes of Trouble with Octave\n@end ifset\n\n@cindex bugs, known\n@cindex installation trouble\n@cindex known causes of trouble\n@cindex troubleshooting\n\nThis section describes known problems that affect users of Octave.  Most\nof these are not Octave bugs per @nospell{se}---if they were, we would fix\nthem.  But the result for a user may be like the result of a bug.\n\nSome of these problems are due to bugs in other software, some are\nmissing features that are too much work to add, and some are places\nwhere people's opinions differ as to what is best.\n\n@menu\n* Actual Bugs::                 Bugs we will fix later.\n* Reporting Bugs::\n* How To Get Help with Octave::\n* How to Distinguish Between Octave and Matlab::\n@end menu\n\n@node Actual Bugs\n@appendixsec Actual Bugs We Haven't Fixed Yet\n\n@itemize @bullet\n@item\nOutput that comes directly from Fortran functions is not sent through\nthe pager and may appear out of sequence with other output that is sent\nthrough the pager.  One way to avoid this is to force pending output to\nbe flushed before calling a function that will produce output from\nwithin Fortran functions.  To do this, use the command\n\n@example\nfflush (stdout)\n@end example\n\nAnother possible workaround is to use the command\n\n@example\npage_screen_output (false);\n@end example\n\n@noindent\nto turn the pager off.\n@end itemize\n\nA list of ideas for future enhancements is distributed with Octave.  See\nthe file @file{PROJECTS} in the top level directory in the source\ndistribution.\n\n@node Reporting Bugs\n@appendixsec Reporting Bugs\n@cindex bugs\n@cindex reporting bugs\n\nYour bug reports play an essential role in making Octave reliable.\n\nWhen you encounter a problem, the first thing to do is to see if it is\nalready known.  @xref{Trouble}.  If it isn't known, then you should\nreport the problem.\n\nReporting a bug may help you by bringing a solution to your problem, or\nit may not.  In any case, the principal function of a bug report is\nto help the entire community by making the next version of Octave work\nbetter.  Bug reports are your contribution to the maintenance of Octave.\n\nIn order for a bug report to serve its purpose, you must include the\ninformation that makes it possible to fix the bug.\n\n@menu\n* Bug Criteria::\n* Bug Tracker::        Where to submit your bug report.\n* Bug Reporting::      How to report a bug effectively.\n* Sending Patches::    How to send a patch for Octave.\n@end menu\n\n@node Bug Criteria\n@appendixsubsec Have You Found a Bug?\n@cindex bug criteria\n\nIf you are not sure whether you have found a bug, here are some guidelines:\n\n@itemize @bullet\n@cindex fatal signal\n@cindex core dump\n@item\nIf Octave gets a fatal signal, for any input whatever, that is\na bug.  Reliable interpreters never crash.\n\n@cindex incorrect output\n@cindex incorrect results\n@cindex results, incorrect\n@cindex answers, incorrect\n@cindex erroneous results\n@cindex wrong answers\n@item\nIf Octave produces incorrect results, for any input whatever,\nthat is a bug.\n\n@cindex undefined behavior\n@cindex undefined function value\n@item\nSome output may appear to be incorrect when it is in fact due to a\nprogram whose behavior is undefined, which happened by chance to give\nthe desired results on another system.  For example, the range operator\nmay produce different results because of differences in the way floating\npoint arithmetic is handled on various systems.\n\n@cindex erroneous messages\n@cindex incorrect error messages\n@cindex error messages, incorrect\n@item\nIf Octave produces an error message for valid input, that is a bug.\n\n@cindex invalid input\n@item\nIf Octave does not produce an error message for invalid input, that is\na bug.  However, you should note that your idea of ``invalid input''\nmight be my idea of ``an extension'' or ``support for traditional\npractice''.\n\n@cindex improving Octave\n@cindex suggestions\n@item\nIf you are an experienced user of programs like Octave, your suggestions\nfor improvement are welcome in any case.\n@end itemize\n\n@node Bug Tracker\n@appendixsubsec Where to Report Bugs\n@cindex bug tracker\n@cindex reporting bugs\n@cindex bugs, reporting\n\nTo report a bug in Octave, submit a bug report to the Octave bug tracker\n@url{https://bugs.octave.org}.\n\n@strong{Do not send bug reports to @samp{help-octave}}.  Most users of\nOctave do not want to receive bug reports.\n\n@node Bug Reporting\n@appendixsubsec How to Report Bugs\n@cindex bugs, reporting\n\nSubmit bug reports for Octave to the Octave bug tracker\n@url{https://bugs.octave.org}.\n\nThe fundamental principle of reporting bugs usefully is this:\n@strong{report all the facts}.  If you are not sure whether to state a\nfact or leave it out, state it!\n\nOften people omit facts because they think they know what causes the\nproblem and they conclude that some details don't matter.  Thus, you might\nassume that the name of the variable you use in an example does not matter.\nWell, probably it doesn't, but one cannot be sure.  Perhaps the bug is a\nstray memory reference which happens to fetch from the location where that\nname is stored in memory; perhaps, if the name were different, the contents\nof that location would fool the interpreter into doing the right thing\ndespite the bug.  Play it safe and give a specific, complete example.\n\nKeep in mind that the purpose of a bug report is to enable someone to\nfix the bug if it is not known.  Always write your bug reports on\nthe assumption that the bug is not known.\n\nSometimes people give a few sketchy facts and ask, ``Does this ring a\nbell?''  This cannot help us fix a bug.  It is better to send a complete\nbug report to begin with.\n\nTry to make your bug report self-contained.  If we have to ask you for\nmore information, it is best if you include all the previous information\nin your response, as well as the information that was missing.\n\nTo enable someone to investigate the bug, you should include all these\nthings:\n\n@itemize @bullet\n@item\nThe version of Octave.  You can get this by noting the version number\nthat is printed when Octave starts, or running it with the @samp{-v}\noption.\n\n@item\nA complete input file that will reproduce the bug.\n\nA single statement may not be enough of an example---the bug might\ndepend on other details that are missing from the single statement where\nthe error finally occurs.\n\n@item\nThe command arguments you gave Octave to execute that example\nand observe the bug.  To guarantee you won't omit something important,\nlist all the options.\n\nIf we were to try to guess the arguments, we would probably guess wrong\nand then we would not encounter the bug.\n\n@item\nThe type of machine you are using, and the operating system name and\nversion number.\n\n@item\nThe command-line arguments you gave to the @code{configure} command when\nyou installed the interpreter.\n\n@item\nA complete list of any modifications you have made to the interpreter\nsource.\n\nBe precise about these changes---show a context diff for them.\n\n@item\nDetails of any other deviations from the standard procedure for installing\nOctave.\n\n@cindex incorrect output\n@cindex incorrect results\n@cindex results, incorrect\n@cindex answers, incorrect\n@cindex erroneous results\n@cindex wrong answers\n@item\nA description of what behavior you observe that you believe is\nincorrect.  For example, \"The interpreter gets a fatal signal,\" or, \"The\noutput produced at line 208 is incorrect.\"\n\nOf course, if the bug is that the interpreter gets a fatal signal, then\none can't miss it.  But if the bug is incorrect output, we might not\nnotice unless it is glaringly wrong.\n\nEven if the problem you experience is a fatal signal, you should still\nsay so explicitly.  Suppose something strange is going on, such as, your\ncopy of the interpreter is out of sync, or you have encountered a bug\nin the C library on your system.  Your copy might crash and the copy\nhere would not.  If you said to expect a crash, then when the\ninterpreter here fails to crash, we would know that the bug was not\nhappening.  If you don't say to expect a crash, then we would not know\nwhether the bug was happening.  We would not be able to draw any\nconclusion from our observations.\n\nOften the observed symptom is incorrect output when your program is run.\nUnfortunately, this is not enough information unless the program is\nshort and simple.  It is very helpful if you can include an explanation\nof the expected output, and why the actual output is incorrect.\n\n@item\nIf you wish to suggest changes to the Octave source, send them as\ncontext diffs.  If you even discuss something in the Octave source,\nrefer to it by context, not by line number, because the line numbers in\nthe development sources probably won't match those in your sources.\n@end itemize\n\nHere are some things that are not necessary:\n\n@itemize @bullet\n@cindex bugs, investigating\n@item\nA description of the envelope of the bug.\n\nOften people who encounter a bug spend a lot of time investigating which\nchanges to the input file will make the bug go away and which changes\nwill not affect it.  Such information is usually not necessary to enable\nus to fix bugs in Octave, but if you can find a simpler example to\nreport @emph{instead} of the original one, that is a convenience.\nErrors in the output will be easier to spot, running under the debugger\nwill take less time, etc.  Most Octave bugs involve just one function, so\nthe most straightforward way to simplify an example is to delete all the\nfunction definitions except the one in which the bug occurs.\n\nHowever, simplification is not vital; if you don't want to do\nthis, report the bug anyway and send the entire test case you\nused.\n\n@item\nA patch for the bug.  Patches can be helpful, but if you find a bug, you\nshould report it, even if you cannot send a fix for the problem.\n@end itemize\n\n@node Sending Patches\n@appendixsubsec Sending Patches for Octave\n@cindex improving Octave\n@cindex diffs, submitting\n@cindex patches, submitting\n@cindex submitting diffs\n@cindex submitting patches\n\nIf you would like to write bug fixes or improvements for Octave, that is\nvery helpful.  When you send your changes, please follow these\nguidelines to avoid causing extra work for us in studying the patches.\n\nIf you don't follow these guidelines, your information might still be\nuseful, but using it will take extra work.  Maintaining Octave is a lot\nof work in the best of circumstances, and we can't keep up unless you do\nyour best to help.\n\n@itemize @bullet\n@item\nSend an explanation with your changes of what problem they fix or what\nimprovement they bring about.  For a bug fix, just include a copy of the\nbug report, and explain why the change fixes the bug.\n\n@item\nAlways include a proper bug report for the problem you think you have\nfixed.  We need to convince ourselves that the change is right before\ninstalling it.  Even if it is right, we might have trouble judging it if\nwe don't have a way to reproduce the problem.\n\n@item\nInclude all the comments that are appropriate to help people reading the\nsource in the future understand why this change was needed.\n\n@item\nDon't mix together changes made for different reasons.\nSend them @emph{individually}.\n\nIf you make two changes for separate reasons, then we might not want to\ninstall them both.  We might want to install just one.\n\n@item\nUse @samp{diff -c} to make your diffs.  Diffs without context are hard\nfor us to install reliably.  More than that, they make it hard for us to\nstudy the diffs to decide whether we want to install them.  Unified diff\nformat is better than contextless diffs, but not as easy to read as\n@samp{-c} format.\n\nIf you have GNU diff, use @samp{diff -cp}, which shows the name of the\nfunction that each change occurs in.\n\n@item\nWrite the change log entries for your changes.\n\nRead the @file{ChangeLog} file to see what sorts of information to put\nin, and to learn the style that we use.  The purpose of the change log\nis to show people where to find what was changed.  So you need to be\nspecific about what functions you changed; in large functions, it's\noften helpful to indicate where within the function the change was made.\n\nOn the other hand, once you have shown people where to find the change,\nyou need not explain its purpose.  Thus, if you add a new function, all\nyou need to say about it is that it is new.  If you feel that the\npurpose needs explaining, it probably does---but the explanation will be\nmuch more useful if you put it in comments in the code.\n\nIf you would like your name to appear in the header line for who made\nthe change, send us the header line.\n@end itemize\n\n@node How To Get Help with Octave\n@appendixsec How To Get Help with Octave\n@cindex help, where to find\n\nThe mailing list @email{help@@octave.org} exists for the discussion of\nmatters related to using and installing Octave.  If would like to join\nthe discussion, please send a short note to\n@email{help-request@@octave.org}.\n\n@strong{Please do not} send requests to be added or removed from the\nmailing list, or other administrative trivia to the list itself.\n\nIf you think you have found a bug in Octave or in the installation\nprocedure, however, you should submit a complete bug report to\nthe Octave bug tracker at @url{https://bugs.octave.org}.\nBut before you submit a bug report, please read\n@url{https://www.octave.org/bugs.html} to learn how to submit a useful\nbug report.\n\n@node How to Distinguish Between Octave and Matlab\n@appendixsec How to Distinguish Between Octave and Matlab\n@cindex Octave and @sc{matlab}, how to distinguish between\n\nOctave and @sc{matlab} are very similar, but handle Java slightly different.\nTherefore it may be necessary to detect the environment and use the appropriate\nfunctions.  The following function can be used to detect the environment.  Due\nto the persistent variable it can be called repeatedly without a heavy\nperformance hit.\n\nExample:\n\n@example\n@group\n%%\n%% Return: true if the environment is Octave.\n%%\nfunction retval = isOctave\n  persistent cacheval;  % speeds up repeated calls\n\n  if isempty (cacheval)\n    cacheval = (exist (\"OCTAVE_VERSION\", \"builtin\") > 0);\n  end\n\n  retval = cacheval;\nend\n@end group\n@end example\n"
  },
  {
    "path": "doc/interpreter/config-images.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nset -e\n\nAWK=${AWK:-awk}\nSHELL=${SHELL:-/bin/sh}\n\nif [ $# -eq 1 ]; then\n  top_srcdir=\"$1\"\nelse\n  top_srcdir=\"../..\"\nfi\n\nmove_if_change=\"$top_srcdir/build-aux/move-if-change\"\n\ninterp_dir=$top_srcdir/doc/interpreter\n\n$AWK -v dir=doc/interpreter -f $interp_dir/images.awk < $interp_dir/images > $interp_dir/images.mk-t\n\n$SHELL $move_if_change $interp_dir/images.mk-t $interp_dir/images.mk\n"
  },
  {
    "path": "doc/interpreter/container.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Data Containers\n@chapter Data Containers\n@cindex containers\n\nOctave includes support for three different mechanisms to contain arbitrary\ndata types in the same variable: Structures, which are C-like, and are indexed\nwith named fields; containers.Map objects, which store data in key/value pairs;\nand cell arrays, where each element of the array can have a different data type\nand or shape.  Multiple input arguments and return values of functions are\norganized as another data container, the comma-separated list.\n\n@menu\n* Structures::\n* containers.Map::\n* Cell Arrays::\n* Comma-Separated Lists::\n@end menu\n\n@node Structures\n@section Structures\n@cindex structures\n@cindex data structures\n\nOctave includes support for organizing data in structures.  The current\nimplementation uses an associative array with indices limited to\nstrings, but the syntax is more like C-style structures.\n\n@menu\n* Basic Usage and Examples::\n* Structure Arrays::\n* Creating Structures::\n* Manipulating Structures::\n* Processing Data in Structures::\n@end menu\n\n@node Basic Usage and Examples\n@subsection Basic Usage and Examples\n\nHere are some examples of using data structures in Octave.\n\nElements of structures can be of any value type.  For example, the three\nexpressions\n\n@example\n@group\nx.a = 1;\nx.b = [1, 2; 3, 4];\nx.c = \"string\";\n@end group\n@end example\n\n@opindex @code{.} structure field access\n@noindent\ncreate a structure with three elements.  The @samp{.} character separates\nthe structure name (in the example above @code{x}) from the field name and\nindicates to Octave that this variable is a structure.  To print the value\nof the structure you can type its name, just as for any other variable:\n\n@example\n@group\nx\n     @xresult{} x =\n\n         scalar structure containing the fields:\n\n           a =  1\n           b =\n\n              1   2\n              3   4\n\n           c = string\n@end group\n@end example\n\n@noindent\nNote that Octave may print the elements in any order.\n\nStructures may be copied just like any other variable:\n\n@example\n@group\ny = x\n     @xresult{} y =\n\n         scalar structure containing the fields:\n\n           a =  1\n           b =\n\n              1   2\n              3   4\n\n           c = string\n@end group\n@end example\n\nSince structures are themselves values, structure elements may reference\nother structures, as well.  The following statement adds the field @code{d}\nto the structure @code{x}.  The value of field @code{d} is itself a data\nstructure containing the single field @code{a}, which has a value of 3.\n\n@example\nx.d.a = 3;\nx.d\n     @xresult{} ans =\n\n         scalar structure containing the fields:\n\n           a =  3\n\nx\n     @xresult{} x =\n\n         scalar structure containing the fields:\n\n           a =  1\n           b =\n\n              1   2\n              3   4\n\n           c = string\n           d =\n\n             scalar structure containing the fields:\n\n               a =  3\n@end example\n\nNote that when Octave prints the value of a structure that contains\nother structures, only a few levels are displayed.  For example:\n\n@example\n@group\na.b.c.d.e = 1;\na\n     @xresult{} a =\n\n         scalar structure containing the fields:\n\n           b =\n\n             scalar structure containing the fields:\n\n               c =\n\n                 scalar structure containing the fields:\n\n                   d: 1x1 scalar struct\n@end group\n@end example\n\n@noindent\nThis prevents long and confusing output from large deeply nested\nstructures.  The number of levels to print for nested structures may be\nset with the function @code{struct_levels_to_print}, and the function\n@code{print_struct_array_contents} may be used to enable printing of the\ncontents of structure arrays.\n\n@DOCSTRING(struct_levels_to_print)\n\n@DOCSTRING(print_struct_array_contents)\n\nFunctions can return structures.  For example, the following function\nseparates the real and complex parts of a matrix and stores them in two\nelements of the same structure variable @code{y}.\n\n@example\n@group\nfunction y = f (x)\n  y.re = real (x);\n  y.im = imag (x);\nendfunction\n@end group\n@end example\n\nWhen called with a complex-valued argument, the function @code{f} returns\nthe data structure containing the real and imaginary parts of the original\nfunction argument.\n\n@example\n@group\nf (rand (2) + rand (2) * I)\n     @xresult{} ans =\n\n         scalar structure containing the fields:\n\n           re =\n\n              0.040239  0.242160\n              0.238081  0.402523\n\n           im =\n\n              0.26475  0.14828\n              0.18436  0.83669\n@end group\n@end example\n\nFunction return lists can include structure elements, and they may be\nindexed like any other variable.  For example:\n\n@example\n[ x.u, x.s(2:3,2:3), x.v ] = svd ([1, 2; 3, 4]);\nx\n\n     @xresult{} x =\n\n         scalar structure containing the fields:\n\n           u =\n\n             -0.40455  -0.91451\n             -0.91451   0.40455\n\n           s =\n\n              0.00000   0.00000   0.00000\n              0.00000   5.46499   0.00000\n              0.00000   0.00000   0.36597\n\n           v =\n\n             -0.57605   0.81742\n             -0.81742  -0.57605\n@end example\n\nIt is also possible to cycle through all the elements of a structure in\na loop, using a special form of the @code{for} statement\n(@pxref{Looping Over Structure Elements}).\n\n@node Structure Arrays\n@subsection Structure Arrays\n\nA structure array is a particular instance of a structure, where each of\nthe fields of the structure is represented by a cell array.  Each of\nthese cell arrays has the same dimensions.  Conceptually, a structure\narray can also be seen as an array of structures with identical\nfields.  An example of the creation of a structure array is\n\n@example\n@group\nx(1).a = \"string1\";\nx(2).a = \"string2\";\nx(1).b = 1;\nx(2).b = 2;\n@end group\n@end example\n\n@noindent\nwhich creates a 1-by-2 structure array with two fields.  Another way\nto create a structure array is with the @code{struct} function\n(@pxref{Creating Structures}).  As previously, to print the value of\nthe structure array, you can type its name:\n\n@example\n@group\nx\n     @xresult{} x =\n        @{\n          1x2 struct array containing the fields:\n\n            a\n            b\n        @}\n@end group\n@end example\n\nIndividual elements of the structure array can be returned by indexing\nthe variable like @code{@var{x}(1)}, which returns a structure with\ntwo fields:\n\n@example\n@group\nx(1)\n     @xresult{} ans =\n        @{\n          a = string1\n          b =  1\n        @}\n@end group\n@end example\n\nFurthermore, the structure array can return a comma-separated list of\nfield values (@pxref{Comma-Separated Lists}), if indexed by one of its\nown field names.  For example:\n\n@example\n@group\nx.a\n     @xresult{}\n        ans = string1\n        ans = string2\n@end group\n@end example\n\nHere is another example, using this comma-separated list on the\nleft-hand side of an assignment:\n\n@example\n@group\n[x.a] = deal (\"new string1\", \"new string2\");\n x(1).a\n     @xresult{} ans = new string1\n x(2).a\n     @xresult{} ans = new string2\n@end group\n@end example\n\nJust as for numerical arrays, it is possible to use vectors as indices\n(@pxref{Index Expressions}):\n\n@example\n@group\nx(3:4) = x(1:2);\n[x([1,3]).a] = deal (\"other string1\", \"other string2\");\nx.a\n     @xresult{}\n        ans = other string1\n        ans = new string2\n        ans = other string2\n        ans = new string2\n@end group\n@end example\n\nThe function @code{size} will return the size of the structure.  For\nthe example above\n\n@example\n@group\nsize (x)\n     @xresult{} ans =\n\n          1   4\n@end group\n@end example\n\nElements can be deleted from a structure array in a similar manner to a\nnumerical array, by assigning the elements to an empty matrix.  For\nexample\n\n@example\n@group\nin = struct (\"call1\", @{x, Inf, \"last\"@},\n             \"call2\", @{x, Inf, \"first\"@})\n     @xresult{} in =\n        @{\n          1x3 struct array containing the fields:\n\n            call1\n            call2\n        @}\n\nin(1) = [];\nin.call1\n     @xresult{}\n       ans = Inf\n       ans = last\n@end group\n@end example\n\n@node Creating Structures\n@subsection Creating Structures\n@cindex dynamic naming\n\nBesides the index operator @qcode{\".\"}, Octave can use dynamic naming\n@qcode{\"(var)\"} or the @code{struct} function to create structures.  Dynamic\nnaming uses the string value of a variable as the field name.  For example:\n\n@example\n@group\na = \"field2\";\nx.a = 1;\nx.(a) = 2;\nx\n     @xresult{} x =\n        @{\n          a =  1\n          field2 =  2\n        @}\n@end group\n@end example\n\n@noindent\nDynamic indexing also allows you to use arbitrary strings, not merely\nvalid Octave identifiers (note that this does not work on @sc{matlab}):\n\n@example\n@group\na = \"long field with spaces (and funny char$)\";\nx.a = 1;\nx.(a) = 2;\nx\n     @xresult{} x =\n        @{\n          a =  1\n          long field with spaces (and funny char$) =  2\n        @}\n@end group\n@end example\n\n@noindent\nThe warning id @code{Octave:language-extension} can be enabled to warn\nabout this usage.  @xref{XREFwarning_ids,,warning_ids}.\n\nMore realistically, all of the functions that operate on strings can be used\nto build the correct field name before it is entered into the data structure.\n\n@example\n@group\nnames = [\"Bill\"; \"Mary\"; \"John\"];\nages  = [37; 26; 31];\nfor i = 1:rows (names)\n  database.(names(i,:)) = ages(i);\nendfor\ndatabase\n     @xresult{} database =\n        @{\n          Bill =  37\n          Mary =  26\n          John =  31\n        @}\n@end group\n@end example\n\nThe third way to create structures is the @code{struct} command.  @code{struct}\ntakes pairs of arguments, where the first argument in the pair is the fieldname\nto include in the structure and the second is a scalar or cell array,\nrepresenting the values to include in the structure or structure array.  For\nexample:\n\n@example\n@group\nstruct (\"field1\", 1, \"field2\", 2)\n@xresult{} ans =\n      @{\n        field1 =  1\n        field2 =  2\n      @}\n@end group\n@end example\n\nIf the values passed to @code{struct} are a mix of scalar and cell\narrays, then the scalar arguments are expanded to create a\nstructure array with a consistent dimension.  For example:\n\n@example\n@group\ns = struct (\"field1\", @{1, \"one\"@}, \"field2\", @{2, \"two\"@},\n        \"field3\", 3);\ns.field1\n     @xresult{}\n        ans =  1\n        ans = one\n\ns.field2\n     @xresult{}\n        ans =  2\n        ans = two\n\ns.field3\n     @xresult{}\n        ans =  3\n        ans =  3\n@end group\n@end example\n\nIf you want to create a struct which contains a cell array as an\nindividual field, you must wrap it in another cell array as shown in\nthe following example:\n\n@example\n@group\nstruct (\"field1\", @{@{1, \"one\"@}@}, \"field2\", 2)\n     @xresult{} ans =\n        @{\n          field1 =\n\n        @{\n          [1,1] =  1\n          [1,2] = one\n        @}\n\n          field2 =  2\n        @}\n@end group\n@end example\n\n@DOCSTRING(struct)\n\nThe function @code{isstruct} can be used to test if an object is a\nstructure or a structure array.\n\n@DOCSTRING(isstruct)\n\n@node Manipulating Structures\n@subsection Manipulating Structures\n\nOther functions that can manipulate the fields of a structure are given below.\n\n@DOCSTRING(numfields)\n\n@DOCSTRING(fieldnames)\n\n@DOCSTRING(isfield)\n\n@DOCSTRING(setfield)\n\n@DOCSTRING(getfield)\n\n@DOCSTRING(rmfield)\n\n@DOCSTRING(orderfields)\n\n@DOCSTRING(substruct)\n\n@node Processing Data in Structures\n@subsection Processing Data in Structures\n\nThe simplest way to process data in a structure is within a @code{for}\nloop (@pxref{Looping Over Structure Elements}).  A similar effect can be\nachieved with the @code{structfun} function, where a user defined\nfunction is applied to each field of the structure.\n@xref{XREFstructfun,,structfun}.\n\nAlternatively, to process the data in a structure, the structure might\nbe converted to another type of container before being treated.\n\n@DOCSTRING(struct2cell)\n\n@DOCSTRING(namedargs2cell)\n\n@node containers.Map\n@section containers.Map\n@cindex Map\n@cindex key/value store\n@cindex hash table\n\n@c FIXME: Need to fill in documentation on what a Map is, when to use it over\n@c        other container types, how to perform basic operations with a Map.\n\n@c FIXME: Currently have trouble getting documentation for classdef functions.\n@DOCSTRING(containers.Map)\n\n@node Cell Arrays\n@section Cell Arrays\n@cindex cell arrays\n\nIt can be both necessary and convenient to store several variables of\ndifferent size or type in one variable.  A cell array is a container\nclass able to do just that.  In general cell arrays work just like\n@math{N}-dimensional arrays with the exception of the use of @samp{@{}\nand @samp{@}} as allocation and indexing operators.\n\n@menu\n* Basic Usage of Cell Arrays::\n* Creating Cell Arrays::\n* Indexing Cell Arrays::\n* Cell Arrays of Strings::\n* Processing Data in Cell Arrays::\n@end menu\n\n@node Basic Usage of Cell Arrays\n@subsection Basic Usage of Cell Arrays\n@opindex @{\n@opindex @}\nAs an example, the following code creates a cell array containing a\nstring and a 2-by-2 random matrix\n\n@example\nc = @{\"a string\", rand(2, 2)@};\n@end example\n\n@noindent\nTo access the elements of a cell array, it can be indexed with the @{\nand @} operators.  Thus, the variable created in the previous example\ncan be indexed like this:\n\n@example\n@group\nc@{1@}\n     @xresult{} ans = a string\n@end group\n@end example\n\n@noindent\nAs with numerical arrays several elements of a cell array can be\nextracted by indexing with a vector of indexes\n\n@example\n@group\nc@{1:2@}\n     @xresult{} ans = a string\n     @xresult{} ans =\n\n               0.593993   0.627732\n               0.377037   0.033643\n@end group\n@end example\n\nThe indexing operators can also be used to insert or overwrite elements\nof a cell array.  The following code inserts the scalar 3 on the\nthird place of the previously created cell array\n\n@example\n@group\nc@{3@} = 3\n     @xresult{} c =\n\n         @{\n           [1,1] = a string\n           [1,2] =\n\n              0.593993   0.627732\n              0.377037   0.033643\n\n           [1,3] =  3\n         @}\n@end group\n@end example\n\nDetails on indexing cell arrays are explained in @ref{Indexing Cell Arrays}.\n\nIn general nested cell arrays are displayed hierarchically as in the\nprevious example.  In some circumstances it makes sense to reference\nthem by their index, and this can be performed by the @code{celldisp}\nfunction.\n\n@DOCSTRING(celldisp)\n\nTo test if an object is a cell array, use the @code{iscell}\nfunction.  For example:\n\n@example\n@group\niscell (c)\n     @xresult{} ans = 1\n\niscell (3)\n     @xresult{} ans = 0\n\n@end group\n@end example\n\n@DOCSTRING(iscell)\n\n@node Creating Cell Arrays\n@subsection Creating Cell Arrays\n\nThe introductory example (@pxref{Basic Usage of Cell Arrays}) showed\nhow to create a cell array containing currently available variables.\nIn many situations, however, it is useful to create a cell array and\nthen fill it with data.\n\nThe @code{cell} function returns a cell array of a given size, containing\nempty matrices.  This function is similar to the @code{zeros}\nfunction for creating new numerical arrays.  The following example creates\na 2-by-2 cell array containing empty matrices\n\n@example\n@group\nc = cell (2,2)\n     @xresult{} c =\n\n         @{\n           [1,1] = [](0x0)\n           [2,1] = [](0x0)\n           [1,2] = [](0x0)\n           [2,2] = [](0x0)\n         @}\n@end group\n@end example\n\nJust like numerical arrays, cell arrays can be multi-dimensional.  The\n@code{cell} function accepts any number of positive integers to describe\nthe size of the returned cell array.  It is also possible to set the size\nof the cell array through a vector of positive integers.  In the\nfollowing example two cell arrays of equal size are created, and the size\nof the first one is displayed\n\n@example\n@group\nc1 = cell (3, 4, 5);\nc2 = cell ( [3, 4, 5] );\nsize (c1)\n     @xresult{} ans =\n         3   4   5\n@end group\n@end example\n\n@noindent\nAs can be seen, the @ref{XREFsize,,size} function also works\nfor cell arrays.  As do other functions describing the size of an\nobject, such as @ref{XREFlength,,length}, @ref{XREFnumel,,numel},\n@ref{XREFrows,,rows}, and @ref{XREFcolumns,,columns}.\n\n@DOCSTRING(cell)\n\nAs an alternative to creating empty cell arrays, and then filling them, it\nis possible to convert numerical arrays into cell arrays using the\n@code{num2cell}, @code{mat2cell} and @code{cellslices} functions.\n\n@DOCSTRING(num2cell)\n\n@DOCSTRING(mat2cell)\n\n@DOCSTRING(cellslices)\n\n@node Indexing Cell Arrays\n@subsection Indexing Cell Arrays\n\nAs shown in @pxref{Basic Usage of Cell Arrays} elements can be\nextracted from cell arrays using the @samp{@{} and @samp{@}}\noperators.  If you want to extract or access subarrays which are still\ncell arrays, you need to use the @samp{(} and @samp{)} operators.  The\nfollowing example illustrates the difference:\n\n@example\n@group\nc = @{\"1\", \"2\", \"3\"; \"x\", \"y\", \"z\"; \"4\", \"5\", \"6\"@};\nc@{2,3@}\n     @xresult{} ans = z\n\nc(2,3)\n     @xresult{} ans =\n        @{\n          [1,1] = z\n        @}\n@end group\n@end example\n\n@noindent So with @samp{@{@}} you access elements of a cell\narray, while with @samp{()} you access a sub array of a cell\narray.\n\nUsing the @samp{(} and @samp{)} operators, indexing works for cell\narrays like for multi-dimensional arrays.  As an example, all the rows\nof the first and third column of a cell array can be set to @code{0}\nwith the following command:\n\n@example\n@group\nc(:, [1, 3]) = @{0@}\n     @xresult{} =\n        @{\n          [1,1] = 0\n          [2,1] = 0\n          [3,1] = 0\n          [1,2] = 2\n          [2,2] = y\n          [3,2] = 5\n          [1,3] = 0\n          [2,3] = 0\n          [3,3] = 0\n        @}\n@end group\n@end example\n\nNote, that the above can also be achieved like this:\n\n@example\nc(:, [1, 3]) = 0;\n@end example\n\n@noindent Here, the scalar @samp{0} is automatically promoted to\ncell array @samp{@{0@}} and then assigned to the subarray of @code{c}.\n\nTo give another example for indexing cell arrays with @samp{()}, you\ncan exchange the first and the second row of a cell array as in the\nfollowing command:\n\n@example\n@group\nc = @{1, 2, 3; 4, 5, 6@};\nc([1, 2], :) = c([2, 1], :)\n     @xresult{} =\n        @{\n          [1,1] =  4\n          [2,1] =  1\n          [1,2] =  5\n          [2,2] =  2\n          [1,3] =  6\n          [2,3] =  3\n        @}\n@end group\n@end example\n\nAccessing multiple elements of a cell array with the @samp{@{} and\n@samp{@}} operators will result in a comma-separated list of all the\nrequested elements (@pxref{Comma-Separated Lists}).  Using the\n@samp{@{} and @samp{@}} operators the first two rows in the above\nexample can be swapped back like this:\n\n@example\n@group\n[c@{[1,2], :@}] = deal (c@{[2, 1], :@})\n     @xresult{} =\n        @{\n          [1,1] =  1\n          [2,1] =  4\n          [1,2] =  2\n          [2,2] =  5\n          [1,3] =  3\n          [2,3] =  6\n        @}\n@end group\n@end example\n\nAs for struct arrays and numerical arrays, the empty matrix @samp{[]}\ncan be used to delete elements from a cell array:\n\n@example\n@group\nx = @{\"1\", \"2\"; \"3\", \"4\"@};\nx(1, :) = []\n     @xresult{} x =\n        @{\n          [1,1] = 3\n          [1,2] = 4\n        @}\n@end group\n@end example\n\nThe following example shows how to just remove the contents of cell\narray elements but not delete the space for them:\n\n@example\n@group\nx = @{\"1\", \"2\"; \"3\", \"4\"@};\nx(1, :) = @{[]@}\n@xresult{} x =\n      @{\n        [1,1] = [](0x0)\n        [2,1] = 3\n        [1,2] = [](0x0)\n        [2,2] = 4\n      @}\n@end group\n@end example\n\nThe indexing operations operate on the cell array and not on the objects\nwithin the cell array.  By contrast, @code{cellindexmat} applies matrix\nindexing to the objects within each cell array entry and returns the requested\nvalues.\n\n@DOCSTRING(cellindexmat)\n\n@node Cell Arrays of Strings\n@subsection Cell Arrays of Strings\n\nOne common use of cell arrays is to store multiple strings in the same\nvariable.  It is also possible to store multiple strings in a\ncharacter matrix by letting each row be a string.  This, however,\nintroduces the problem that all strings must be of equal length.\nTherefore, it is recommended to use cell arrays to store multiple\nstrings.  For cases, where the character matrix representation is required\nfor an operation, there are several functions that convert a cell\narray of strings to a character array and back.  @code{char} and\n@code{strvcat} convert cell arrays to a character array\n(@pxref{Concatenating Strings}), while the function @code{cellstr}\nconverts a character array to a cell array of strings:\n\n@example\n@group\na = [\"hello\"; \"world\"];\nc = cellstr (a)\n     @xresult{} c =\n         @{\n           [1,1] = hello\n           [2,1] = world\n         @}\n@end group\n@end example\n\n@DOCSTRING(cellstr)\n\nOne further advantage of using cell arrays to store multiple strings is\nthat most functions for string manipulations included with Octave\nsupport this representation.  As an example, it is possible to compare\none string with many others using the @code{strcmp} function.  If one of\nthe arguments to this function is a string and the other is a cell array\nof strings, each element of the cell array will be compared to the string\nargument:\n\n@example\n@group\nc = @{\"hello\", \"world\"@};\nstrcmp (\"hello\", c)\n     @xresult{} ans =\n        1   0\n@end group\n@end example\n\n@noindent\nThe following string functions support cell arrays of strings: @code{char},\n@code{strvcat}, @code{strcat} (@pxref{Concatenating Strings}), @code{strcmp},\n@code{strncmp}, @code{strcmpi}, @code{strncmpi} (@pxref{Searching in Strings}),\n@code{str2double}, @code{deblank}, @code{strtrim}, @code{strtrunc},\n@code{strfind}, @code{strmatch}, , @code{regexp}, @code{regexpi}\n(@pxref{String Operations}) and @code{str2double} (@pxref{Converting Strings}).\n\nThe function @code{iscellstr} can be used to test if an object is a\ncell array of strings.\n\n@DOCSTRING(iscellstr)\n\n@node Processing Data in Cell Arrays\n@subsection Processing Data in Cell Arrays\n\nData that is stored in a cell array can be processed in several ways\ndepending on the actual data.  The simplest way to process that data\nis to iterate through it using one or more @code{for} loops.  The same\nidea can be implemented more easily through the use of the @code{cellfun}\nfunction that calls a user-specified function on all elements of a cell\narray.  @xref{XREFcellfun,,cellfun}.\n\nAn alternative is to convert the data to a different container, such as\na matrix or a data structure.  Depending on the data this is possible\nusing the @code{cell2mat} and @code{cell2struct} functions.\n\n@DOCSTRING(cell2mat)\n\n@DOCSTRING(cell2struct)\n\n@node Comma-Separated Lists\n@section Comma-Separated Lists\n@cindex comma-separated lists\n@cindex cs-lists\n\nComma-separated lists @footnote{Comma-separated lists are also sometimes\nreferred to as @dfn{cs-lists}.} are the basic argument type to all Octave\nfunctions---both for input and return arguments.  In the example\n\n@example\nmax (@var{a}, @var{b})\n@end example\n\n@noindent\n@samp{@var{a}, @var{b}} is a comma-separated list.  Comma-separated lists\ncan appear on both the right and left hand side of an assignment.  For\nexample\n\n@example\n@group\nx = [1 0 1 0 0 1 1; 0 0 0 0 0 0 7];\n[@var{i}, @var{j}] = find (@var{x}, 2, \"last\");\n@end group\n@end example\n\n@noindent\nHere, @samp{@var{x}, 2, \"last\"} is a comma-separated list constituting\nthe input arguments of @code{find}.  @code{find} returns a comma-separated list\nof output arguments which is assigned element by element to the comma-separated\nlist @samp{@var{i}, @var{j}}.\n\nAnother example of where comma-separated lists are used is in the creation of a\nnew array with @code{[]} (@pxref{Matrices}) or the creation of a cell array\nwith @code{@{@}} (@pxref{Basic Usage of Cell Arrays}).  In the expressions\n\n@example\n@group\na = [1, 2, 3, 4];\nc = @{4, 5, 6, 7@};\n@end group\n@end example\n\n@noindent\nboth @samp{1, 2, 3, 4} and @samp{4, 5, 6, 7} are comma-separated lists.\n\nComma-separated lists cannot be directly manipulated by the\nuser.  However, both structure arrays and cell arrays can be converted\ninto comma-separated lists, and thus used in place of explicitly\nwritten comma-separated lists.  This feature is useful in many ways,\nas will be shown in the following subsections.\n\n@menu\n* Comma-Separated Lists Generated from Cell Arrays::\n* Comma-Separated Lists Generated from Structure Arrays::\n@end menu\n\n@node Comma-Separated Lists Generated from Cell Arrays\n@subsection Comma-Separated Lists Generated from Cell Arrays\n\nAs has been mentioned above (@pxref{Indexing Cell Arrays}), elements\nof a cell array can be extracted into a comma-separated list with the\n@code{@{} and @code{@}} operators.  By surrounding this list with\n@code{[} and @code{]}, it can be concatenated into an array.  For example:\n\n@example\n@group\na = @{1, [2, 3], 4, 5, 6@};\nb = [a@{1:4@}]\n     @xresult{} b =\n         1   2   3   4   5\n@end group\n@end example\n\nSimilarly, it is possible to create a new cell array containing cell\nelements selected with @code{@{@}}.  By surrounding the list with\n@samp{@{} and @samp{@}} a new cell array will be created, as the\nfollowing example illustrates:\n\n@example\n@group\na = @{1, rand(2, 2), \"three\"@};\nb = @{ a@{ [1, 3] @} @}\n     @xresult{} b =\n         @{\n           [1,1] =  1\n           [1,2] = three\n         @}\n@end group\n@end example\n\nFurthermore, cell elements (accessed by @code{@{@}}) can be passed\ndirectly to a function.  The list of elements from the cell array will\nbe passed as an argument list to a given function as if it is called\nwith the elements as individual arguments.  The two calls to\n@code{printf} in the following example are identical but the latter is\nsimpler and can handle cell arrays of an arbitrary size:\n\n@example\n@group\nc = @{\"GNU\", \"Octave\", \"is\", \"Free\", \"Software\"@};\nprintf (\"%s \", c@{1@}, c@{2@}, c@{3@}, c@{4@}, c@{5@});\n     @print{} GNU Octave is Free Software\nprintf (\"%s \", c@{:@});\n     @print{} GNU Octave is Free Software\n@end group\n@end example\n\nIf used on the left-hand side of an assignment, a comma-separated list\ngenerated with @code{@{@}} can be assigned to.  An example is\n\n@example\nin@{1@} = [10, 20, 30];\nin@{2@} = inf;\nin@{3@} = \"last\";\nin@{4@} = \"first\";\nout = cell (4, 1);\n[out@{1:3@}] = in@{1 : 3@};\n[out@{4:6@}] = in@{[1, 2, 4]@})\n     @xresult{} out =\n        @{\n           [1,1] =\n\n              10   20   30\n\n           [2,1] = Inf\n           [3,1] = last\n           [4,1] =\n\n              10   20   30\n\n           [5,1] = Inf\n           [6,1] = first\n        @}\n@end example\n\n\n@node Comma-Separated Lists Generated from Structure Arrays\n@subsection Comma-Separated Lists Generated from Structure Arrays\nStructure arrays can equally be used to create comma-separated\nlists.  This is done by addressing one of the fields of a structure\narray.  For example:\n\n@example\n@group\nx = ceil (randn (10, 1));\nin = struct (\"call1\", @{x, 3, \"last\"@},\n             \"call2\", @{x, inf, \"first\"@});\nout = struct (\"call1\", cell (2, 1), \"call2\", cell (2, 1));\n[out.call1] = find (in.call1);\n[out.call2] = find (in.call2);\n@end group\n@end example\n"
  },
  {
    "path": "doc/interpreter/contributors.in",
    "content": "Ben Abbott\nDrew Abbot\nNVS Abhilash\nAndy Adler\nAdam H. Aitkenhead\nFernando Alvarruiz\nJoakim Andén\nGiles Anderson\nJoel Andersson\nLachlan Andrew\nPedro Angelo\nDamjan Angelovski\nMuthiah Annamalai\nMarkus Appel\nLeonardo Araujo\nBranden Archer\nWillem Atsma\nMarco Atzeri\nAnder Aurrekoetxea\nShai Ayal\nSahil Badyal\nJeff Bai\nRoger Banks\nBen Barrowes\nAlexander Barth\nDavid Bateman\nHeinz Bauschke\nMiguel Bazdresch\nJulien Bect\nAman Behera\nStefan Beller\nRoman Belov\nMarkus Bergholz\nKarl Berry\nAndreas Bertsatos\nAtri Bhattacharya\nEthan Biery\nDavid Billinghurst\nDon Bindner\nJakub Bogusz\nGaël Bonithon\nLeonardo S. Borges\nMoritz Borgmann\nPaul Boven\nRichard Bovey\nJohn Bradshaw\nMarcus Brinkmann\nMax Brister\nRemy Bruno\nStefan Brüns\nClemens Buchacher\nAnsgar Burchard\nAntonius Burgers\nMarco Caliari\nDaniel Calvelo\nJohn C. Campbell\nJuan Pablo Carbajal\nJean-Francois Cardoso\nJoao Cardoso\nLarrie Carr\nDavid Castelow\nVincent Cautaerts\nMarco Cecchetti\nCorbin Champion\nClinton Chee\nAlbert Chin-A-Young\nSunghyun Cho\nCarsten Clark\nCatalin Codreanu\nJ. D. Cole\nJacopo Corno\nAndre da Costa Barros\nMartin Costabel\nMichael Creel\nRichard Crozier\nJeff Cunningham\nMartin Dalecki\nJacob Dawid\nJorge Barros de Abreu\nCarlo de Falco\nThomas D. Dean\nPhilippe Defert\nBill Denney\nFabian Deutsch\nChristos Dimitrakakis\nPantxo Diribarne\nVivek Dogra\nJohn Donoghue\nDavid M. Doolin\nCarnë Draug\nSergey Dudoladov\nPascal A. Dupuis\nJohn W. Eaton\nDirk Eddelbuettel\nPieter Eendebak\nPaul Eggert\nStephen Eglen\nPeter Ekberg\nAbdallah K. Elshamy\nGarrett Euler\nEdmund Grimley Evans\nRolf Fabian\nFrancesco Faccio\nGunnar Farnebäck\nMassimiliano Fasi\nStephen Fegan\nRamon Garcia Fernandez\nKasper H. Filtenborg\nTorsten Finke\nDavid Finkel\nGuillaume Flandin\nColin Foster\nJose Daniel Munoz Frias\nBrad Froehle\nCastor Fu\nEduardo Gallestey\nWalter Gautschi\nKlaus Gebhardt\nDriss Ghaddab\nEugenio Gianniti\nHartmut Gimpel\nMichele Ginesi\nNicolo Giorgetti\nArun Giridhar\nMichael D. Godfrey\nDave Goel\nMichael Goffioul\nGlenn Golden\nTomislav Goles\nKeith Goodman\nBrian Gough\nAlexander Graf\nMichael C. Grant\nSteffen Groot\nEtienne Grossmann\nDavid Grundberg\nKyle Guinn\nVaibhav Gupta\nPeter Gustafson\nKai Habel\nPatrick Häcker\nWilliam P. Y. Hadisoeseno\nJaroslav Hajek\nBenjamin Hall\nAlexander Hansen\nKim Hansen\nGene Harvey\nSøren Hauberg\nDave Hawthorne\nOliver Heimlich\nDaniel Heiserer\nPiotr Held\nMartin Helm\nStefan Hepp\nMartin Hepperle\nJordi Gutiérrez Hermoso\nIsrael Herraiz\nYozo Hida\nChristian Himpe\nRyan Hinton\nRoman Hodek\nA. Scottedward Hodel\nJúlio Hoffimann\nRichard Allan Holcombe\nTom Holroyd\nDavid Hoover\nKurt Hornik\nCraig Hudson\nChristopher Hulbert\nCyril Humbert\nJohn Hunt\nStefan Husmann\nTeemu Ikonen\nAlan W. Irwin\nAllan Jacobs\nMarcel Jacobse\nGeoff Jacobsen\nVytautas Jančauskas\nAndrew Janke\nNicholas R. Jankowski\nMats Jansson\nRobert Jenssen\nCai Jianming\nSteven G. Johnson\nHeikki Junes\nMatthias Jüschke\nAtsushi Kajita\nJarkko Kaleva\nAvinoam Kalma\nMohamed Kamoun\nLute Kamstra\nFotios Kasolis\nThomas Kasper\nChristof Kaufmann\nJoel Keay\nMumit Khan\nPaul Kienzle\nLars Kindermann\nAaron A. King\nErik Kjellson\nArno J. Klaassen\nAlexander Klein\nLasse Kliemann\nGeoffrey Knauth\nHendrik Koerner\nMartin Köhler\nHeine Kolltveit\nThomas Kolman\nPeter Konowski\nSophia Koulen\nKen Kouno\nKacper Kowalik\nEndre Kozma\nDaniel Kraft\nNir Krakauer\nAravindh Krishnamoorthy\nOyvind Kristiansen\nArtem Krosheninnikov\nPiotr Krzyzanowski\nVolker Kuhlmann\nIlya Kurdyukov\nTetsuro Kurita\nBen Kurtz\nPhilipp Kutin\nMiroslaw Kwasniak\nRafael Laboissiere\nKai Labusch\nClaude Lacoursiere\nNithin Lakshmisha\nWalter Landry\nBill Lash\nDirk Laurie\nMaurice LeBrun\nFriedrich Leisch\nMichael Leitner\nJohannes Leuschner\nThorsten Liebig\nTorsten Lilge\nJyh-miin Lin\nTimo Lindfors\nBenjamin Lindner\nRoss Lippert\nYu Liu\nDavid Livings\nBarbara Locsi\nSebastien Loisel\nAndrej Lojdl\nErik de Castro Lopo\nMassimo Lorenzin\nEmil Lucretiu\nYi-Hong Lyu\nHoxide Ma\nColin Macdonald\nJames Macnicol\nJens-Uwe Mager\nStefan Mahr\nRob Mahurin\nAlexander Mamonov\nRicardo Marranita\nOrestes Mas\nAxel Mathéi\nMakoto Matsumoto\nTatsuro Matsuoka\nChristoph Mayer\nLaurent Mazet\nG. D. McBain\nRonald van der Meer\nMarkus Meisinger\nJúlio Hoffimann Mendes\nEd Meyer\nThorsten Meyer\nStefan Miereis\nPetr Mikulik\nLinton Miller\nMike Miller\nServiscope Minor\nStefan Monnier\nRafael Monteiro\nStephen Montgomery-Smith\nAnthony Morast\nAntoine Moreau\nKai P. Mueller\nAmod Mulay\nArmin Müller\nHannes Müller\nVictor Munoz\nPrasannaKumar Muralidharan\nIain Murray\nNicholas Musolino\nMarkus Mützel\nCarmen Navarrete\nTodd Neal\nPhilip Nienhuis\nAl Niessner\nFelipe G. Nievinski\nRick Niles\nTakuji Nishimura\nAkira Noda\nKai Noda\nPatrick Noffke\nVictor Norton\nEric Norum\nKrzesimir Nowak\nMichael O'Brien\nCillian O'Driscoll\nPeter O'Gorman\nThorsten Ohl\nKai T. Ohlhus\nSerkan Önder\nArno Onken\nValentin Ortega-Clavero\nLuis F. Ortiz\nCarl Osterwisch\nJanne Olavi Paanajärvi\nÓvári\nScott Pakin\nJosé Luis García Pallero\nJason Alan Palmer\nGabriele Pannocchia\nSylvain Pelissier\nRolando Pereira\nPer Persson\nPrimozz Peterlin\nJim Peterson\nJohannes Pfeifer\nDanilo Piazzalunga\nNicholas Piper\nElias Pipping\nRobert Platt\nHans Ekkehard Plesser\nSergey Plotnikov\nTom Poage\nNathan Podlich\nOrion Poplawski\nOndrej Popp\nJef Poskanzer\nFrancesco Potortì\nKonstantinos Poulios\nTejaswi D. Prakash\nJarno Rajahalme\nEduardo Ramos\nPooja Rao\nJames B. Rawlings\nEric S. Raymond\nBalint Reczey\nJoshua Redstone\nAndy Register\nLukas Reichlin\nMichael Reifenberger\nErnst Reissner\nReinhard Resch\nJens Restemeier\nAnthony Richardson\nJason Riedy\nE. Joshua Rigler\nSander van Rijn\nPetter Risholm\nMatthew W. Roberts\nMelvin Robinson\nDmitry Roshchin\nPeter Rosin\nAndrew Ross\nFabio Rossi\nMark van Rossum\nJoe Rothweiler\nDavid Rörich\nKevin Ruland\nKristian Rumberg\nRyan Rusaw\nOlli Saarela\nToni Saarela\nJuhani Saastamoinen\nRadek Salac\nMike Sander\nBen Sapp\nAleksej Saushev\nAlois Schlögl\nMichel D. Schmid\nJulian Schnidder\nSebastian Schöps\nNicol N. Schraudolph\nSebastian Schubert\nLasse Schuirmann\nLudwig Schwardt\nThomas L. Scofield\nDaniel J. Sebald\nDmitri A. Sergatskov\nVanya Sergeev\nMarko Seric\nAhsan Ali Shahid\nBaylis Shanks\nAndriy Shinkarchuck\nRobert T. Short\nPaulo Silva\nJoseph P. Skudlarek\nJohn Smith\nJulius Smith\nShan G. Smith\nPeter L. Sondergaard\nRüdiger Sonderfeld\nJoerg Specht\nQuentin H. Spencer\nChristoph Spiel\nDavid Spies\nImad-Eddine Srairi\nAndreas Stahel\nRichard Stallman\nRussell Standish\nRyan Starret\nBrett Stewart\nDoug Stewart\nJen Stewart\nJonathan Stickel\nJudd Storrs\nThomas Stuart\nBernardo Sulzbach\nIvan Sutoris\nJohn Swensen\nDaisuke Takago\nAriel Tankus\nFalk Tannhäuser\nDuncan Temple Lang\nMatthew Tennyhg\nRemi Thebault\nKris Thielemans\nGeorg Thimm\nPaul Thomas\nCorey Thomasson\nAndrew Thornton\nOlaf Till\nPetter Tomner\nChristophe Tournery\nThomas Treichl\nAbhinav Tripathi\nKarsten Trulsen\nDavid Turner\nFrederick Umminger\nUtkarsh Upadhyay\nJosé Vallet\nStefan van der Walt\nPeter Van Wieren\nJames R. Van Zandt\nRisto Vanhanen\nGregory Vanuxem\nMihas Varantsou\nIvana Varekova\nSébastien Villemot\nMarco Vitetta\nDaniel Wagenaar\nSteven Waldrip\nThomas Walter\nJun Wang\nAndreas Weber\nOlaf Weber\nThomas Weber\nRik Wehbring\nBob Weigel\nAndreas Weingessel\nMartin Weiser\nMichael Weitzel\nDavid Wells\nJoachim Wiesemann\nAlexander Wilms\nJoe Winegarden\nGeorg Wiora\nEddy Xiao\nSahil Yadav\nFook Fah Yap\nSean Young\nMichele Zaffalon\nSerhiy Zahoriya\nJohannes Zarl\nMichael Zeising\nFederico Zenith\nClaudius Zingerli\nAlex Zvoleff\nRichard Zweig\n"
  },
  {
    "path": "doc/interpreter/cp-idx.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Concept Index\n@unnumbered Concept Index\n\n@printindex cp\n"
  },
  {
    "path": "doc/interpreter/data.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Data Types\n@chapter Data Types\n@cindex data types\n\nAll versions of Octave include a number of built-in data types,\nincluding real and complex scalars and matrices, character strings,\na data structure type, and an array that can contain all data types.\n\nIt is also possible to define new specialized data types by writing a\nsmall amount of C++ code.  On some systems, new data types can be loaded\ndynamically while Octave is running, so it is not necessary to recompile\nall of Octave just to add a new type.  @xref{External Code Interface}, for\nmore information about Octave's dynamic linking capabilities.\n@ref{User-defined Data Types} describes what you must do to define a\nnew data type for Octave.\n\n@DOCSTRING(typeinfo)\n\n@menu\n* Built-in Data Types::\n* User-defined Data Types::\n* Object Sizes::\n@end menu\n\n@node Built-in Data Types\n@section Built-in Data Types\n@cindex data types, built-in\n@cindex built-in data types\n\nThe standard built-in data types are real and complex scalars and\nmatrices, ranges, character strings, a data structure type, and cell\narrays.  Additional built-in data types may be added in future versions.\nIf you need a specialized data type that is not currently provided as a\nbuilt-in type, you are encouraged to write your own user-defined data\ntype and contribute it for distribution in a future release of Octave.\n\nThe data type of a variable can be determined and changed through the\nuse of the following functions.\n\n@DOCSTRING(class)\n\n@DOCSTRING(isa)\n\n@DOCSTRING(cast)\n\n@DOCSTRING(typecast)\n\n@DOCSTRING(swapbytes)\n\n@DOCSTRING(bitpack)\n\n@DOCSTRING(bitunpack)\n\n@menu\n* Numeric Objects::\n* Missing Data::\n* String Objects::\n* Data Structure Objects::\n* Cell Array Objects::\n@end menu\n\n@node Numeric Objects\n@subsection Numeric Objects\n@cindex numeric constant\n@cindex numeric value\n\nOctave's built-in numeric objects include real, complex, and integer\nscalars and matrices.  All built-in floating point numeric data is\ncurrently stored as double precision numbers.  On systems that use\nIEEE@tie{}754 floating point format, values in the range of approximately\n@tex\n $2.2251\\times10^{-308}$ to $1.7977\\times10^{308}$\n@end tex\n@ifnottex\n 2.2251e-308 to 1.7977e+308\n@end ifnottex\n can be stored, and the relative precision is approximately\n@tex\n $2.2204\\times10^{-16}$.\n@end tex\n@ifnottex\n 2.2204e-16.\n@end ifnottex\nThe exact values are given by the variables @code{realmin},\n@code{realmax}, and @code{eps}, respectively.\n\nMatrix objects can be of any size, and can be dynamically reshaped and resized.\nIt is easy to extract individual rows, columns, or submatrices using a variety\nof powerful indexing features.  @xref{Index Expressions}.\n\n@xref{Numeric Data Types}, for more information.\n\n@node Missing Data\n@subsection Missing Data\n@cindex missing data\n\nIt is possible to represent missing data explicitly in Octave using NA (short\nfor ``@w{Not} @w{Available}'').  This is helpful in distinguishing between a\nproperty of the data (i.e., some of it was not recorded) and calculations on\nthe data which generated an error (i.e., created NaN values).  In short, if you\ndo not get the result you expect is it your data or your algorithm?\n\nThe missing data marker is a special case of the representation of NaN.\nBecause of that, it can only be used with data represented by floating point\nnumbers---no integer, logical, or char values.\n\nIn general, use NA and the test @code{isna}, to describe the dataset or to\nreduce the dataset to only valid entries.  Numerical calculations with NA will\ngenerally @qcode{\"poison\"} the results and conclude with an output NA@.\nHowever, this can not be guaranteed on all platforms and NA may be replaced by\nNaN.\n\nExample 1 : Describing the dataset\n\n@example\n@group\ndata = [1, NA, 3];\npercent_missing = 100 * sum (isna (data(:))) / numel (data);\nprintf ('%2.0f%% of the dataset is missing\\n', percent_missing);\n@print{} 33% of the dataset is missing\n@end group\n@end example\n\nExample 2 : Restrict calculations to valid data\n\n@example\n@group\nraw_data = [1, NA, 3];\nprintf ('mean of raw data is %.1f\\n', mean (raw_data));\n@print{} mean of raw data is NA\nvalid_data = raw_data (! isna (raw_data));\nprintf ('mean of valid data is %.1f\\n', mean (valid_data));\n@print{} mean of valid data is 2.0\n@end group\n@end example\n\n@DOCSTRING(NA)\n\n@DOCSTRING(isna)\n\n@node String Objects\n@subsection String Objects\n@cindex strings\n@cindex character strings\n@opindex \"\n@opindex @code{'}\n\nA character string in Octave consists of a sequence of characters\nenclosed in either double-quote or single-quote marks.  Internally,\nOctave currently stores strings as matrices of characters.  All the\nindexing operations that work for matrix objects also work for strings.\n\n@xref{Strings}, for more information.\n\n@node Data Structure Objects\n@subsection Data Structure Objects\n@cindex structures\n@cindex data structures\n\nOctave's data structure type can help you to organize related objects of\ndifferent types.  The current implementation uses an associative array\nwith indices limited to strings, but the syntax is more like C-style\nstructures.\n\n@xref{Structures}, for more information.\n\n@node Cell Array Objects\n@subsection Cell Array Objects\n@cindex cell arrays\n\nA Cell Array in Octave is general array that can hold any number of\ndifferent data types.\n\n@xref{Cell Arrays}, for more information.\n\n@node User-defined Data Types\n@section User-defined Data Types\n@cindex user-defined data types\n@cindex data types, user-defined\n\nSomeday I hope to expand this to include a complete description of\nOctave's mechanism for managing user-defined data types.  Until this\nfeature is documented here, you will have to make do by reading the code\nin the @file{ov.h}, @file{ops.h}, and related files from Octave's\n@file{src} directory.\n\n@node Object Sizes\n@section Object Sizes\n\nThe following functions allow you to determine the size of a variable or\nexpression.  These functions are defined for all objects.  They return\n@minus{}1 when the operation doesn't make sense.  For example, Octave's\ndata structure type doesn't have rows or columns, so the @code{rows} and\n@code{columns} functions return @minus{}1 for structure arguments.\n\n@DOCSTRING(ndims)\n\n@DOCSTRING(columns)\n\n@DOCSTRING(rows)\n\n@DOCSTRING(numel)\n\n@DOCSTRING(length)\n\n@DOCSTRING(size)\n\n@DOCSTRING(isempty)\n\n@DOCSTRING(isnull)\n\n@DOCSTRING(sizeof)\n\n@DOCSTRING(size_equal)\n\n@DOCSTRING(squeeze)\n"
  },
  {
    "path": "doc/interpreter/debug.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Debugging\n@chapter Debugging\n\nOctave includes a built-in debugger to aid in the development of\nscripts.  This can be used to interrupt the execution of an Octave script\nat a certain point, or when certain conditions are met.  Once execution\nhas stopped, and debug mode is entered, the symbol table at the point\nwhere execution has stopped can be examined and modified to check for\nerrors.\n\nThe normal command-line editing and history functions are available in\ndebug mode.\n\n@menu\n* Entering Debug Mode::\n* Leaving Debug Mode::\n* Breakpoints::\n* Debug Mode::\n* Call Stack::\n* Profiling::\n* Profiler Example::\n@end menu\n\n@node Entering Debug Mode\n@section Entering Debug Mode\n\nThere are two basic means of interrupting the execution of an Octave\nscript.  These are breakpoints (@pxref{Breakpoints}), discussed in the next\nsection, and interruption based on some condition.\n\nOctave supports three means to stop execution based on the values set in\nthe functions @code{debug_on_interrupt}, @code{debug_on_warning}, and\n@code{debug_on_error}.\n\n@DOCSTRING(debug_on_interrupt)\n\n@DOCSTRING(debug_on_warning)\n\n@DOCSTRING(debug_on_error)\n\n@node Leaving Debug Mode\n@section Leaving Debug Mode\n\nUse either @code{dbcont} or @code{return} to leave the debug mode and\ncontinue the normal execution of the script.\n\n@DOCSTRING(dbcont)\n\nTo quit debug mode and return directly to the prompt without executing\nany additional code use @code{dbquit}.\n\n@DOCSTRING(dbquit)\n\nFinally, typing @code{exit} or @code{quit} at the debug prompt will\nresult in Octave terminating normally.\n\n@node Breakpoints\n@section Breakpoints\n\nBreakpoints can be set in any m-file function by using the @code{dbstop}\nfunction.\n\n@DOCSTRING(dbstop)\n\n@noindent\nBreakpoints in class methods are also supported (e.g.,\n@code{dbstop (\"@@class/method\")}).  However, breakpoints cannot be set in\nbuilt-in functions (e.g., @code{sin}, etc.@:) or dynamically loaded functions\n(i.e., oct-files).\n\nTo set a breakpoint immediately upon entering a function use line number 1, or\nomit the line number entirely and just give the function name.  When setting\nthe breakpoint Octave will ignore the leading comment block, and the breakpoint\nwill be set on the first executable statement in the function.  For example:\n\n@example\n@group\ndbstop (\"asind\", 1)\n@xresult{} 29\n@end group\n@end example\n\n@noindent\nNote that the return value of @code{29} means that the breakpoint was\neffectively set to line 29.  The status of breakpoints in a function can\nbe queried with @code{dbstatus}.\n\n@DOCSTRING(dbstatus)\n\n@noindent\nReusing the previous example, @code{dbstatus (\"asind\")} will return\n29.  The breakpoints listed can then be cleared with the @code{dbclear}\nfunction.\n\n@DOCSTRING(dbclear)\n\n@noindent\n\nA breakpoint may also be set in a subfunction.  For example, if a file contains\nthe functions\n\n@example\n@group\nfunction y = func1 (x)\n  y = func2 (x);\nendfunction\nfunction y = func2 (x)\n  y = x + 1;\nendfunction\n@end group\n@end example\n\n@noindent\nthen a breakpoint can be set at the start of the subfunction directly with\n\n@example\n@group\ndbstop func1>func2\n@xresult{} 5\n@end group\n@end example\n\nNote that @samp{>} is the character that distinguishes subfunctions from the\nm-file containing them.\n\nAnother simple way of setting a breakpoint in an Octave script is the\nuse of the @code{keyboard} function.\n\n@DOCSTRING(keyboard)\n\n@noindent\nThe @code{keyboard} function is placed in a script at the point where the user\ndesires that the execution be stopped.  It automatically sets the running\nscript into the debug mode.\n\n@node Debug Mode\n@section Debug Mode\n\nThere are three additional support functions that allow the user to\nfind out where in the execution of a script Octave entered the debug\nmode, and to print the code in the script surrounding the point where\nOctave entered debug mode.\n\n@DOCSTRING(dbwhere)\n\n@DOCSTRING(dbtype)\n\n@DOCSTRING(dblist)\n\nYou may also use @code{isdebugmode} to determine whether the debugger is\ncurrently active.\n\n@DOCSTRING(isdebugmode)\n\nDebug mode also allows single line stepping through a function using\nthe command @code{dbstep}.\n\n@DOCSTRING(dbstep)\n\nWhen in debug mode the @key{RETURN} key will execute the last entered command.\nThis is useful, for example, after hitting a breakpoint and entering\n@code{dbstep} once.  After that, one can advance line by line through the code\nwith only a single key stroke.  This feature may be disabled using the\n@code{auto_repeat_debug_command} function.\n\n@DOCSTRING(auto_repeat_debug_command)\n\n@node Call Stack\n@section Call Stack\n\nThe function being debugged may be the leaf node of a series of function calls.\nAfter examining values in the current subroutine it may turn out that the\nproblem occurred in earlier pieces of code.  Use @code{dbup} and @code{dbdown}\nto move up and down through the series of function calls to locate where\nvariables first took on the wrong values.  @code{dbstack} shows the entire\nseries of function calls and at what level debugging is currently taking place.\n\n@DOCSTRING(dbstack)\n\n@DOCSTRING(dbup)\n\n@DOCSTRING(dbdown)\n\n@node Profiling\n@section Profiling\n@cindex profiler\n@cindex code profiling\n\nOctave supports profiling of code execution on a per-function level.  If\nprofiling is enabled, each call to a function (supporting built-ins,\noperators, functions in oct- and mex-files, user-defined functions in\nOctave code and anonymous functions) is recorded while running Octave\ncode.  After that, this data can aid in analyzing the code behavior, and\nis in particular helpful for finding ``hot spots'' in the code which use\nup a lot of computation time and are the best targets to spend\noptimization efforts on.\n\nThe main command for profiling is @code{profile}, which can be used to\nstart or stop the profiler and also to query collected data afterwards.\nThe data is returned in an Octave data structure which can then be\nexamined or further processed by other routines or tools.\n\n@DOCSTRING(profile)\n\nAn easy way to get an overview over the collected data is\n@code{profshow}.  This function takes the profiler data returned by\n@code{profile} as input and prints a flat profile, for instance:\n\n@example\n@group\n Function Attr     Time (s)        Calls\n----------------------------------------\n   >myfib    R        2.195        13529\nbinary <=             0.061        13529\n binary -             0.050        13528\n binary +             0.026         6764\n@end group\n@end example\n\nThis shows that most of the run time was spent executing the function\n@samp{myfib}, and some minor proportion evaluating the listed binary\noperators.  Furthermore, it is shown how often the function was called\nand the profiler also records that it is recursive.\n\n@DOCSTRING(profshow)\n\n@DOCSTRING(profexport)\n\n@DOCSTRING(profexplore)\n\n@node Profiler Example\n@section Profiler Example\n\nBelow, we will give a short example of a profiler session.\n@xref{Profiling}, for the documentation of the profiler functions in\ndetail.  Consider the code:\n\n@example\nglobal N A;\n\nN = 300;\nA = rand (N, N);\n\nfunction xt = timesteps (steps, x0, expM)\n  global N;\n\n  if (steps == 0)\n    xt = NA (N, 0);\n  else\n    xt = NA (N, steps);\n    x1 = expM * x0;\n    xt(:, 1) = x1;\n    xt(:, 2 : end) = timesteps (steps - 1, x1, expM);\n  endif\nendfunction\n\nfunction foo ()\n  global N A;\n\n  initial = @@(x) sin (x);\n  x0 = (initial (linspace (0, 2 * pi, N)))';\n\n  expA = expm (A);\n  xt = timesteps (100, x0, expA);\nendfunction\n\nfunction fib = bar (N)\n  if (N <= 2)\n    fib = 1;\n  else\n    fib = bar (N - 1) + bar (N - 2);\n  endif\nendfunction\n@end example\n\nIf we execute the two main functions, we get:\n\n@example\n@group\ntic; foo; toc;\n@xresult{} Elapsed time is 2.37338 seconds.\n\ntic; bar (20); toc;\n@xresult{} Elapsed time is 2.04952 seconds.\n@end group\n@end example\n\nBut this does not give much information about where this time is spent;\nfor instance, whether the single call to @code{expm} is more expensive\nor the recursive time-stepping itself.  To get a more detailed picture,\nwe can use the profiler.\n\n@example\n@group\nprofile on;\nfoo;\nprofile off;\n\ndata = profile (\"info\");\nprofshow (data, 10);\n@end group\n@end example\n\nThis prints a table like:\n\n@example\n@group\n   #  Function Attr     Time (s)        Calls\n---------------------------------------------\n   7      expm             1.034            1\n   3  binary *             0.823          117\n  41  binary \\             0.188            1\n  38  binary ^             0.126            2\n  43 timesteps    R        0.111          101\n  44        NA             0.029          101\n  39  binary +             0.024            8\n  34      norm             0.011            1\n  40  binary -             0.004          101\n  33   balance             0.003            1\n@end group\n@end example\n\nThe entries are the individual functions which have been executed (only\nthe 10 most important ones), together with some information for each of\nthem.  The entries like @samp{binary *} denote operators, while other\nentries are ordinary functions.  They include both built-ins like\n@code{expm} and our own routines (for instance @code{timesteps}).  From\nthis profile, we can immediately deduce that @code{expm} uses up the\nlargest proportion of the processing time, even though it is only called\nonce.  The second expensive operation is the matrix-vector product in the\nroutine @code{timesteps}.  @footnote{We only know it is the binary\nmultiplication operator, but fortunately this operator appears only at\none place in the code and thus we know which occurrence takes so much\ntime.  If there were multiple places, we would have to use the\nhierarchical profile to find out the exact place which uses up the time\nwhich is not covered in this example.}\n\nTiming, however, is not the only information available from the profile.\nThe attribute column shows us that @code{timesteps} calls itself\nrecursively.  This may not be that remarkable in this example (since it's\nclear anyway), but could be helpful in a more complex setting.  As to the\nquestion of why is there a @samp{binary \\} in the output, we can easily\nshed some light on that too.  Note that @code{data} is a structure array\n(@ref{Structure Arrays}) which contains the field @code{FunctionTable}.\nThis stores the raw data for the profile shown.  The number in the first\ncolumn of the table gives the index under which the shown function can\nbe found there.  Looking up @code{data.FunctionTable(41)} gives:\n\n@example\n@group\n  scalar structure containing the fields:\n\n    FunctionName = binary \\\n    TotalTime =  0.18765\n    NumCalls =  1\n    IsRecursive = 0\n    Parents =  7\n    Children = [](1x0)\n@end group\n@end example\n\nHere we see the information from the table again, but have additional\nfields @code{Parents} and @code{Children}.  Those are both arrays, which\ncontain the indices of functions which have directly called the function\nin question (which is entry 7, @code{expm}, in this case) or been called\nby it (no functions).  Hence, the backslash operator has been used\ninternally by @code{expm}.\n\nNow let's take a look at @code{bar}.  For this, we start a fresh\nprofiling session (@code{profile on} does this; the old data is removed\nbefore the profiler is restarted):\n\n@example\n@group\nprofile on;\nbar (20);\nprofile off;\n\nprofshow (profile (\"info\"));\n@end group\n@end example\n\nThis gives:\n\n@example\n@group\n   #            Function Attr     Time (s)        Calls\n-------------------------------------------------------\n   1                 bar    R        2.091        13529\n   2           binary <=             0.062        13529\n   3            binary -             0.042        13528\n   4            binary +             0.023         6764\n   5             profile             0.000            1\n   8               false             0.000            1\n   6              nargin             0.000            1\n   7           binary !=             0.000            1\n   9 __profiler_enable__             0.000            1\n@end group\n@end example\n\nUnsurprisingly, @code{bar} is also recursive.  It has been called 13,529\ntimes in the course of recursively calculating the Fibonacci number in a\nsuboptimal way, and most of the time was spent in @code{bar} itself.\n\nFinally, let's say we want to profile the execution of both @code{foo}\nand @code{bar} together.  Since we already have the run-time data\ncollected for @code{bar}, we can restart the profiler without clearing\nthe existing data and collect the missing statistics about @code{foo}.\nThis is done by:\n\n@example\n@group\nprofile resume;\nfoo;\nprofile off;\n\nprofshow (profile (\"info\"), 10);\n@end group\n@end example\n\nAs you can see in the table below, now we have both profiles mixed\ntogether.\n\n@example\n@group\n   #  Function Attr     Time (s)        Calls\n---------------------------------------------\n   1       bar    R        2.091        13529\n  16      expm             1.122            1\n  12  binary *             0.798          117\n  46  binary \\             0.185            1\n  45  binary ^             0.124            2\n  48 timesteps    R        0.115          101\n   2 binary <=             0.062        13529\n   3  binary -             0.045        13629\n   4  binary +             0.041         6772\n  49        NA             0.036          101\n@end group\n@end example\n"
  },
  {
    "path": "doc/interpreter/diagperm.txi",
    "content": "@c Copyright (C) 2009-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Diagonal and Permutation Matrices\n@chapter Diagonal and Permutation Matrices\n@cindex diagonal and permutation matrices\n@cindex matrices, diagonal and permutation\n\n@menu\n* Basic Usage::          Creation and Manipulation of Diagonal/Permutation Matrices\n* Matrix Algebra::       Linear Algebra with Diagonal/Permutation Matrices\n* Function Support::     Functions That Are Aware of These Matrices\n* Example Code::         Examples of Usage\n* Zeros Treatment::      Differences in Treatment of Zero Elements\n@end menu\n\n@node Basic Usage\n@section Creating and Manipulating Diagonal/Permutation Matrices\n\nA diagonal matrix is defined as a matrix that has zero entries outside the main\ndiagonal; that is,\n@tex\n$D_{ij} = 0$ if $i \\neq j$\n@end tex\n@ifnottex\n@code{D(i,j) == 0} if @code{i != j}.\n@end ifnottex\nMost often, square diagonal matrices are considered; however, the definition\ncan equally be applied to non-square matrices, in which case we usually speak\nof a rectangular diagonal matrix.\n\nA permutation matrix is defined as a square matrix that has a single element\nequal to unity in each row and each column; all other elements are zero.  That\nis, there exists a permutation (vector)\n@tex\n$p$ such that $P_{ij}=1$ if $j = p_i$ and\n$P_{ij}=0$ otherwise.\n@end tex\n@ifnottex\n@code{p} such that @code{P(i,j) == 1} if @code{j == p(i)} and\n@code{P(i,j) == 0} otherwise.\n@end ifnottex\n\nOctave provides special treatment of real and complex rectangular diagonal\nmatrices, as well as permutation matrices.  They are stored as special objects,\nusing efficient storage and algorithms, facilitating writing both readable and\nefficient matrix algebra expressions in the Octave language.  The special\ntreatment may be disabled by using the functions @dfn{optimize_diagonal_matrix}\nand @dfn{optimize_permutation_matrix}.\n\n@DOCSTRING(optimize_diagonal_matrix)\n\n@DOCSTRING(optimize_permutation_matrix)\n\nThe space savings are significant as demonstrated by the following code.\n\n@example\n@group\nx = diag (rand (10, 1));\nxf = full (x);\nsizeof (x)\n@xresult{} 80\nsizeof (xf)\n@xresult{} 800\n@end group\n@end example\n\n@menu\n* Creating Diagonal Matrices::\n* Creating Permutation Matrices::\n* Explicit and Implicit Conversions::\n@end menu\n\n@node Creating Diagonal Matrices\n@subsection Creating Diagonal Matrices\n\nThe most common and easiest way to create a diagonal matrix is using the\nbuilt-in function @dfn{diag}.  The expression @code{diag (v)}, with @var{v} a\nvector, will create a square diagonal matrix with elements on the main diagonal\ngiven by the elements of @var{v}, and size equal to the length of @var{v}.\n@code{diag (v, m, n)} can be used to construct a rectangular diagonal matrix.\nThe result of these expressions will be a special diagonal matrix object,\nrather than a general matrix object.\n\nDiagonal matrix with unit elements can be created using @dfn{eye}.\nSome other built-in functions can also return diagonal matrices.  Examples\ninclude\n@dfn{balance} or @dfn{inv}.\n\nExample:\n\n@example\n  diag (1:4)\n@xresult{}\nDiagonal Matrix\n\n   1   0   0   0\n   0   2   0   0\n   0   0   3   0\n   0   0   0   4\n\n  diag (1:3,5,3)\n\n@xresult{}\nDiagonal Matrix\n\n   1   0   0\n   0   2   0\n   0   0   3\n   0   0   0\n   0   0   0\n@end example\n\n@node Creating Permutation Matrices\n@subsection Creating Permutation Matrices\n\nFor creating permutation matrices, Octave does not introduce a new function,\nbut rather overrides an existing syntax: permutation matrices can be\nconveniently created by indexing an identity matrix by permutation vectors.\nThat is, if @var{q} is a permutation vector of length @var{n}, the expression\n\n@example\n  P = eye (n) (:, q);\n@end example\n\n@noindent\nwill create a permutation matrix - a special matrix object.\n\n@example\neye (n) (q, :)\n@end example\n\n@noindent\nwill also work (and create a row permutation matrix), as well as\n\n@example\neye (n) (q1, q2).\n@end example\n\nFor example:\n\n@example\n@group\n  eye (4) ([1,3,2,4],:)\n@xresult{}\nPermutation Matrix\n\n   1   0   0   0\n   0   0   1   0\n   0   1   0   0\n   0   0   0   1\n\n  eye (4) (:,[1,3,2,4])\n@xresult{}\nPermutation Matrix\n\n   1   0   0   0\n   0   0   1   0\n   0   1   0   0\n   0   0   0   1\n@end group\n@end example\n\nMathematically, an identity matrix is both diagonal and permutation matrix.\nIn Octave, @code{eye (n)} returns a diagonal matrix, because a matrix\ncan only have one class.  You can convert this diagonal matrix to a permutation\nmatrix by indexing it by an identity permutation, as shown below.\nThis is a special property of the identity matrix; indexing other diagonal\nmatrices generally produces a full matrix.\n\n@example\n@group\n  eye (3)\n@xresult{}\nDiagonal Matrix\n\n   1   0   0\n   0   1   0\n   0   0   1\n\n  eye(3)(1:3,:)\n@xresult{}\nPermutation Matrix\n\n   1   0   0\n   0   1   0\n   0   0   1\n@end group\n@end example\n\nSome other built-in functions can also return permutation matrices.  Examples\ninclude\n@dfn{inv} or @dfn{lu}.\n\n@node Explicit and Implicit Conversions\n@subsection Explicit and Implicit Conversions\n\nThe diagonal and permutation matrices are special objects in their own right.\nA number of operations and built-in functions are defined for these matrices\nto use special, more efficient code than would be used for a full matrix in\nthe same place.  Examples are given in further sections.\n\nTo facilitate smooth mixing with full matrices, backward compatibility, and\ncompatibility with @sc{matlab}, the diagonal and permutation matrices should\nallow any operation that works on full matrices, and will either treat it\nspecially, or implicitly convert themselves to full matrices.\n\nInstances include matrix indexing, except for extracting a single element or\na leading submatrix, indexed assignment, or applying most mapper functions,\nsuch as @dfn{exp}.\n\nAn explicit conversion to a full matrix can be requested using the built-in\nfunction @dfn{full}.  It should also be noted that the diagonal and permutation\nmatrix objects will cache the result of the conversion after it is first\nrequested (explicitly or implicitly), so that subsequent conversions will\nbe very cheap.\n\n@node Matrix Algebra\n@section Linear Algebra with Diagonal/Permutation Matrices\n\nAs has been already said, diagonal and permutation matrices make it\npossible to use efficient algorithms while preserving natural linear\nalgebra syntax.  This section describes in detail the operations that\nare treated specially when performed on these special matrix objects.\n\n@menu\n* Expressions Involving Diagonal Matrices::\n* Expressions Involving Permutation Matrices::\n@end menu\n\n@node Expressions Involving Diagonal Matrices\n@subsection Expressions Involving Diagonal Matrices\n@cindex diagonal matrix expressions\n\nAssume @var{D} is a diagonal matrix.  If @var{M} is a full matrix,\nthen @code{D*M} will scale the rows of @var{M}.  That means,\nif @code{S = D*M}, then for each pair of indices\ni,j it holds\n@tex\n$$S_{ij} = D_{ii} M_{ij}$$\n@end tex\n@ifnottex\n\n@example\nS(i,j) = D(i,i) * M(i,j).\n@end example\n\n@end ifnottex\nSimilarly, @code{M*D} will do a column scaling.\n\nThe matrix @var{D} may also be rectangular, m-by-n where @code{m != n}.\nIf @code{m < n}, then the expression @code{D*M} is equivalent to\n\n@example\nD(:,1:m) * M(1:m,:),\n@end example\n\n@noindent\ni.e., trailing @code{n-m} rows of @var{M} are ignored.  If @code{m > n},\nthen @code{D*M} is equivalent to\n\n@example\n[D(1:n,:) * M; zeros(m-n, columns (M))],\n@end example\n\n@noindent\ni.e., null rows are appended to the result.\nThe situation for right-multiplication @code{M*D} is analogous.\n\n@cindex pseudoinverse\nThe expressions @code{D \\ M} and @code{M / D} perform inverse scaling.\nThey are equivalent to solving a diagonal (or rectangular diagonal)\nin a least-squares minimum-norm sense.  In exact arithmetic, this is\nequivalent to multiplying by a pseudoinverse.  The pseudoinverse of\na rectangular diagonal matrix is again a rectangular diagonal matrix\nwith swapped dimensions, where each nonzero diagonal element is replaced\nby its reciprocal.\nThe matrix division algorithms do, in fact, use division rather than\nmultiplication by reciprocals for better numerical accuracy; otherwise, they\nhonor the above definition.  Note that a diagonal matrix is never truncated due\nto ill-conditioning; otherwise, it would not be of much use for scaling.  This\nis typically consistent with linear algebra needs.  A full matrix that only\nhappens to be diagonal (and is thus not a special object) is of course treated\nnormally.\n\nMultiplication and division by diagonal matrices work efficiently also when\ncombined with sparse matrices, i.e., @code{D*S}, where @var{D} is a diagonal\nmatrix and @var{S} is a sparse matrix scales the rows of the sparse matrix and\nreturns a sparse matrix.  The expressions @code{S*D}, @code{D\\S}, @code{S/D}\nwork analogically.\n\nIf @var{D1} and @var{D2} are both diagonal matrices, then the expressions\n\n@example\n@group\nD1 + D2\nD1 - D2\nD1 * D2\nD1 / D2\nD1 \\ D2\n@end group\n@end example\n\n@noindent\nagain produce diagonal matrices, provided that normal\ndimension matching rules are obeyed.  The relations used are same as described\nabove.\n\nAlso, a diagonal matrix @var{D} can be multiplied or divided by a scalar, or\nraised to a scalar power if it is square, producing diagonal matrix result in\nall cases.\n\nA diagonal matrix can also be transposed or conjugate-transposed, giving the\nexpected result.  Extracting a leading submatrix of a diagonal matrix, i.e.,\n@code{D(1:m,1:n)}, will produce a diagonal matrix, other indexing expressions\nwill implicitly convert to full matrix.\n\nAdding a diagonal matrix to a full matrix only operates on the diagonal\nelements.  Thus,\n\n@example\nA = A + eps * eye (n)\n@end example\n\n@noindent\nis an efficient method of augmenting the diagonal of a matrix.  Subtraction\nworks analogically.\n\nWhen involved in expressions with other element-by-element operators,\n@code{.*}, @code{./}, @code{.\\} or @code{.^}, an implicit conversion to full\nmatrix will take place.  This is not always strictly necessary but chosen to\nfacilitate better consistency with @sc{matlab}.\n\n@node Expressions Involving Permutation Matrices\n@subsection Expressions Involving Permutation Matrices\n\nIf @var{P} is a permutation matrix and @var{M} a matrix, the expression\n@code{P*M} will permute the rows of @var{M}.  Similarly, @code{M*P} will\nyield a column permutation.\nMatrix division @code{P\\M} and @code{M/P} can be used to do inverse\npermutation.\n\nThe previously described syntax for creating permutation matrices can actually\nhelp an user to understand the connection between a permutation matrix and\na permuting vector.  Namely, the following holds, where @code{I = eye (n)}\nis an identity matrix:\n\n@example\n  I(p,:) * M = (I*M) (p,:) = M(p,:)\n@end example\n\nSimilarly,\n\n@example\n  M * I(:,p) = (M*I) (:,p) = M(:,p)\n@end example\n\nThe expressions @code{I(p,:)} and @code{I(:,p)} are permutation matrices.\n\nA permutation matrix can be transposed (or conjugate-transposed, which is the\nsame, because a permutation matrix is never complex), inverting the\npermutation, or equivalently, turning a row-permutation matrix into a\ncolumn-permutation one.  For permutation matrices, transpose is equivalent to\ninversion, thus @code{P\\M} is equivalent to @code{P'*M}.  Transpose of a\npermutation matrix (or inverse) is a constant-time operation, flipping only a\nflag internally, and thus the choice between the two above equivalent\nexpressions for inverse permuting is completely up to the user's taste.\n\nMultiplication and division by permutation matrices works efficiently also when\ncombined with sparse matrices, i.e., @code{P*S}, where @var{P} is a permutation\nmatrix and @var{S} is a sparse matrix permutes the rows of the sparse matrix\nand returns a sparse matrix.  The expressions @code{S*P}, @code{P\\S},\n@code{S/P} work analogically.\n\nTwo permutation matrices can be multiplied or divided (if their sizes match),\nperforming a composition of permutations.  Also a permutation matrix can be\nindexed by a permutation vector (or two vectors), giving again a permutation\nmatrix.  Any other operations do not generally yield a permutation matrix and\nwill thus trigger the implicit conversion.\n\n@node Function Support\n@section Functions That Are Aware of These Matrices\n\nThis section lists the built-in functions that are aware of diagonal and\npermutation matrices on input, or can return them as output.  Passed to other\nfunctions, these matrices will in general trigger an implicit conversion.\n(Of course, user-defined dynamically linked functions may also work with\ndiagonal or permutation matrices).\n\n@menu\n* Diagonal Matrix Functions::\n* Permutation Matrix Functions::\n@end menu\n\n@node Diagonal Matrix Functions\n@subsection Diagonal Matrix Functions\n\n@dfn{inv} and @dfn{pinv} can be applied to a diagonal matrix, yielding again\na diagonal matrix.  @dfn{det} will use an efficient straightforward calculation\nwhen given a diagonal matrix, as well as @dfn{cond}.\nThe following mapper functions can be applied to a diagonal matrix\nwithout converting it to a full one:\n@dfn{abs}, @dfn{real}, @dfn{imag}, @dfn{conj}, @dfn{sqrt}.\nA diagonal matrix can also be returned from the @dfn{balance}\nand @dfn{svd} functions.\nThe @dfn{sparse} function will convert a diagonal matrix efficiently to a\nsparse matrix.\n\n@node Permutation Matrix Functions\n@subsection Permutation Matrix Functions\n@cindex matrix, permutation functions\n@cindex permutation matrix functions\n\n@dfn{inv} and @dfn{pinv} will invert a permutation matrix, preserving its\nspecialness.  @dfn{det} can be applied to a permutation matrix, efficiently\ncalculating the sign of the permutation (which is equal to the determinant).\n\nA permutation matrix can also be returned from the built-in functions\n@dfn{lu} and @dfn{qr}, if a pivoted factorization is requested.\n\nThe @dfn{sparse} function will convert a permutation matrix efficiently to a\nsparse matrix.\nThe @dfn{find} function will also work efficiently with a permutation matrix,\nmaking it possible to conveniently obtain the permutation indices.\n\n@node Example Code\n@section Examples of Usage\n\nThe following can be used to solve a linear system @code{A*x = b}\nusing the pivoted LU@tie{}factorization:\n\n@example\n@group\n  [L, U, P] = lu (A); ## now L*U = P*A\n  x = U \\ (L \\ P) * b;\n@end group\n@end example\n\n@noindent\nThis is one way to normalize columns of a matrix @var{X} to unit norm:\n\n@example\n@group\n  s = norm (X, \"columns\");\n  X /= diag (s);\n@end group\n@end example\n\n@noindent\nThe same can also be accomplished with broadcasting (@pxref{Broadcasting}):\n\n@example\n@group\n  s = norm (X, \"columns\");\n  X ./= s;\n@end group\n@end example\n\n@noindent\nThe following expression is a way to efficiently calculate the sign of a\npermutation, given by a permutation vector @var{p}.  It will also work\nin earlier versions of Octave, but slowly.\n\n@example\n  det (eye (length (p))(p, :))\n@end example\n\n@noindent\nFinally, here's how to solve a linear system @code{A*x = b}\nwith @nospell{Tikhonov} regularization (ridge regression) using SVD (a skeleton\nonly):\n\n@example\n@group\n  m = rows (A); n = columns (A);\n  [U, S, V] = svd (A);\n  ## determine the regularization factor alpha\n  ## alpha = @dots{}\n  ## transform to orthogonal basis\n  b = U'*b;\n  ## Use the standard formula, replacing A with S.\n  ## S is diagonal, so the following will be very fast and accurate.\n  x = (S'*S + alpha^2 * eye (n)) \\ (S' * b);\n  ## transform to solution basis\n  x = V*x;\n@end group\n@end example\n\n\n@node Zeros Treatment\n@section Differences in Treatment of Zero Elements\n@cindex matrix, zero elements\n\nMaking diagonal and permutation matrices special matrix objects in their own\nright and the consequent usage of smarter algorithms for certain operations\nimplies, as a side effect, small differences in treating zeros.\nThe contents of this section apply also to sparse matrices, discussed in\nthe following chapter.  (@pxref{Sparse Matrices})\n\nThe IEEE@tie{}754 floating point standard defines the result of the expressions\n@code{0*Inf} and @code{0*NaN} as @code{NaN}.  This is widely agreed to be a\ngood compromise and Octave strives to conform to this standard.  However,\ncertain algorithms designed for maximized efficiency with structured and sparse\nmatrices may not conform to the IEEE@tie{}754 floating point standard regarding\noperations with zero elements that should result in @code{NaN} such as\n@code{0*Inf}, @code{0/0}, or @code{0*NaN}.\n\nNumerical software dealing with structured and sparse matrices (including\nOctave) almost always makes a distinction between a @nospell{\"numerical zero\"}\nand an @nospell{\"assumed zero\"}.  A @nospell{\"numerical zero\"} is a zero value\noccurring in a place where any floating-point value could occur.  It is normally\nstored somewhere in memory as an explicit value.  An @nospell{\"assumed zero\"},\non the contrary, is a zero matrix element implied by the matrix structure\n(diagonal, triangular) or a sparsity pattern; its value is usually not stored\nexplicitly anywhere, but is implied by the underlying data structure.\n\nThe primary distinction is that an assumed zero, when multiplied or divided by\nany number, yields @strong{always} a zero, even when, e.g., multiplied by\n@code{Inf} or divided by @code{NaN}.  The reason for this behavior is that the\nnumerical multiplication is not actually performed anywhere by the underlying\nalgorithm; the result is just assumed to be zero.\n\nOctave mitigates this behavior by branching the underlying algorithm into\nspecialized implementations to handle operations that actually affect assumed\nzeros.  This is primarily a trade-off between computational efficiency and\nconformity to the floating point standard by treating assumed zeros as numerical\nzeros.  Besides the difference in computation speed, this behavior also affects\nsparsity patterns that should be taken into account when operating on very large\nsparse matrices which may result in out-of-memory errors.\n\nExamples of treating assumed zeros as numerical zeros in sparse matrices:\n\n@example\nspeye (3)\n@xresult{}\nCompressed Column Sparse (rows = 3, cols = 3, nnz = 3 [33%])\n\n  (1, 1) -> 1\n  (2, 2) -> 1\n  (3, 3) -> 1\n\nInf * speye (3)\n@xresult{}\nCompressed Column Sparse (rows = 3, cols = 3, nnz = 9 [100%])\n\n  (1, 1) -> Inf\n  (2, 1) -> NaN\n  (3, 1) -> NaN\n  (1, 2) -> NaN\n  (2, 2) -> Inf\n  (3, 2) -> NaN\n  (1, 3) -> NaN\n  (2, 3) -> NaN\n  (3, 3) -> Inf\n\nInf * full (eye (3))\n@xresult{}\n   Inf   NaN   NaN\n   NaN   Inf   NaN\n   NaN   NaN   Inf\n\nspeye (3) / 0\n@xresult{}\nCompressed Column Sparse (rows = 3, cols = 3, nnz = 9 [100%])\n\n  (1, 1) -> Inf\n  (2, 1) -> NaN\n  (3, 1) -> NaN\n  (1, 2) -> NaN\n  (2, 2) -> Inf\n  (3, 2) -> NaN\n  (1, 3) -> NaN\n  (2, 3) -> NaN\n  (3, 3) -> Inf\n\nfull (eye (3)) / 0\n@xresult{}\n   Inf   NaN   NaN\n   NaN   Inf   NaN\n   NaN   NaN   Inf\n\n@end example\n\nAlthough in sparse matrices only the sparsity pattern may be affected by certain\noperations, when dealing with diagonal matrices, such operations may also affect\nthe returned type.  The following rules apply:\n\n@itemize\n@item finite scalar * diagonal matrix is a diagonal matrix\n\n@item nonfinite scalar * diagonal matrix is a matrix\n\n@item diagonal matrix / 0 is a matrix\n\n@item diagonal matrix / NaN is a matrix\n\n@item diagonal matrix / any other scalar is a diagonal matrix\n@end itemize\n\nFor example:\n\n@example\n3 * eye (3)\n@xresult{}\n\nDiagonal Matrix\n\n   3   0   0\n   0   3   0\n   0   0   3\n\nInf * eye (3)\n@xresult{}\n\n      Inf      NaN      NaN\n      NaN      Inf      NaN\n      NaN      NaN      Inf\n\neye (3) / 0\n@xresult{}\n\n      Inf      NaN      NaN\n      NaN      Inf      NaN\n      NaN      NaN      Inf\n\neye (3) / NaN\n@xresult{}\n\n      NaN      NaN      NaN\n      NaN      NaN      NaN\n      NaN      NaN      NaN\n\neye (3) / Inf\n@xresult{}\n\nDiagonal Matrix\n\n   0   0   0\n   0   0   0\n   0   0   0\n\neye (3) / 2\n@xresult{}\n\nDiagonal Matrix\n\n   0.5000        0        0\n        0   0.5000        0\n        0        0   0.5000\n\n@end example\n\nNote that Octave (as well as @sc{matlab}) does not strictly conform to the\nIEEE@tie{}754 floating point standard and there are certain cases like in the\nfollowing examples where the underlying algorithms operate under assumed zeros\nwithout treating then as numerical zeros.  As of Octave 11, the intention is to\nmake Octave fully compliant with the IEEE@tie{}754 standard so that operations\non dense, sparse, or any other special matrix types produce the same consistent\nresults.  Thus, it is expected that the output in the following examples may\nchange in future Octave versions.\n\nExamples of effects of assumed zeros vs.@: numerical zeros:\n\n@example\n@group\ndiag (1:3) * [NaN; 1; 1]\n@xresult{}\n   NaN\n     2\n     3\n\nsparse (1:3,1:3,1:3) * [NaN; 1; 1]\n@xresult{}\n   NaN\n     2\n     3\n[1,0,0;0,2,0;0,0,3] * [NaN; 1; 1]\n@xresult{}\n   NaN\n   NaN\n   NaN\n@end group\n@end example\n"
  },
  {
    "path": "doc/interpreter/diffeq.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Differential Equations\n@chapter Differential Equations\n\nOctave has built-in functions for solving ordinary differential equations\n(ODEs), and differential-algebraic equations (DAEs).\n\n@menu\n* Ordinary Differential Equations::\n* Differential-Algebraic Equations::\n* Matlab-compatible solvers::\n@end menu\n\n@cindex differential equations\n@cindex ODE\n@cindex DAE\n\n@node Ordinary Differential Equations\n@section Ordinary Differential Equations\n\nThe function @code{lsode} can be used to solve ODEs of the form\n@tex\n$$\n {dx\\over dt} = f (x, t)\n$$\n@end tex\n@ifnottex\n\n@example\n@group\ndx\n-- = f (x, t)\ndt\n@end group\n@end example\n\n@end ifnottex\n\n@noindent\nusing @nospell{Hindmarsh's} ODE solver @sc{lsode}.\n\n@DOCSTRING(lsode)\n\n@DOCSTRING(lsode_options)\n\nHere is an example of solving a set of three differential equations using\n@code{lsode}.  Given the function\n\n@cindex oregonator\n\n@example\n@group\n## oregonator differential equation\nfunction xdot = f (x, t)\n\n  xdot = zeros (3,1);\n\n  xdot(1) = 77.27 * (x(2) - x(1)*x(2) + x(1) ...\n            - 8.375e-06*x(1)^2);\n  xdot(2) = (x(3) - x(1)*x(2) - x(2)) / 77.27;\n  xdot(3) = 0.161*(x(1) - x(3));\n\nendfunction\n@end group\n@end example\n\n@noindent\nand the initial condition @code{x0 = [ 4; 1.1; 4 ]}, the set of\nequations can be integrated using the command\n\n@example\n@group\nt = linspace (0, 500, 1000);\n\ny = lsode (\"f\", x0, t);\n@end group\n@end example\n\nIf you try this, you will see that the value of the result changes\ndramatically between @var{t} = 0 and 5, and again around @var{t} = 305.\nA more efficient set of output points might be\n\n@example\n@group\nt = [0, logspace(-1, log10(303), 150), ...\n        logspace(log10(304), log10(500), 150)];\n@end group\n@end example\n\nAn m-file for the differential equation used above is included with the\nOctave distribution in the examples directory under the name\n@file{oregonator.m}.\n\n\n@node Differential-Algebraic Equations\n@section Differential-Algebraic Equations\n\nThe function @code{daspk} can be used to solve DAEs of the form\n@tex\n$$\n 0 = f (\\dot{x}, x, t), \\qquad x(t=0) = x_0, \\dot{x}(t=0) = \\dot{x}_0\n$$\n@end tex\n@ifnottex\n\n@example\n0 = f (x-dot, x, t),    x(t=0) = x_0, x-dot(t=0) = x-dot_0\n@end example\n\n@end ifnottex\n\n@noindent\nwhere\n@tex\n$\\dot{x} = {dx \\over dt}$\n@end tex\n@ifnottex\n@math{x-dot}\n@end ifnottex\nis the derivative of @math{x}.  The equation is solved using\n@nospell{Petzold's} DAE solver @sc{daspk}.\n\n@DOCSTRING(daspk)\n\n@DOCSTRING(daspk_options)\n\nOctave also includes @sc{dassl}, an earlier version of @sc{daspk},\nand @sc{dasrt}, which can be used to solve DAEs with constraints\n(stopping conditions).\n\n@DOCSTRING(dassl)\n\n@DOCSTRING(dassl_options)\n\n@DOCSTRING(dasrt)\n\n@DOCSTRING(dasrt_options)\n\nSee @nospell{K. E. Brenan}, @w{et al.}, @cite{Numerical Solution of\nInitial-Value Problems in Differential-Algebraic Equations}, North-Holland,\n1989, @nospell{DOI}: @url{https://doi.org/10.1137/1.9781611971224},\nfor more information about the implementation of @sc{dassl}.\n\n\n@node Matlab-compatible solvers\n@section Matlab-compatible solvers\n\nOctave also provides a set of solvers for initial value problems for ordinary\ndifferential equations (ODEs) that have a @sc{matlab}-compatible interface.\nThe options for this class of methods are set using the functions.\n\n@itemize\n  @item @ref{XREFodeset,,odeset}\n\n  @item @ref{XREFodeget,,odeget}\n@end itemize\n\nCurrently implemented solvers are:\n\n@itemize\n  @item @nospell{Runge-Kutta} methods\n\n  @itemize\n    @item @ref{XREFode45,,ode45} integrates a system of non-stiff ODEs or\n    index-1 differential-algebraic equations (DAEs) using the high-order,\n    variable-step @nospell{Dormand-Prince} method.  It requires six function\n    evaluations per integration step, but may take larger steps on smooth\n    problems than @code{ode23}: potentially offering improved efficiency at\n    smaller tolerances.\n\n    @item @ref{XREFode23,,ode23} integrates a system of non-stiff ODEs or (or\n    index-1 DAEs).  It uses the third-order @nospell{Bogacki-Shampine} method\n    and adapts the local step size in order to satisfy a user-specified\n    tolerance.  The solver requires three function evaluations per integration\n    step.\n\n    @item @ref{XREFode23s,,ode23s} integrates a system of stiff ODEs (or\n    index-1 DAEs) using a modified second-order @nospell{Rosenbrock} method.\n  @end itemize\n\n  @item Linear multistep methods\n\n  @itemize\n    @item @ref{XREFode15s,,ode15s} integrates a system of stiff ODEs (or\n    index-1 DAEs) using a variable step, variable order method based on\n    Backward Difference Formulas (BDF).\n\n    @item @ref{XREFode15i,,ode15i} integrates a system of fully-implicit ODEs\n    (or index-1 DAEs) using the same variable step, variable order method as\n    @code{ode15s}.  @ref{XREFdecic,,decic} can be used to compute consistent\n    initial conditions for @code{ode15i}.\n  @end itemize\n@end itemize\n\nDetailed information on the solvers are given in @nospell{L. F. Shampine} and\n@nospell{M. W. Reichelt}, \"The MATLAB ODE Suite\", @cite{SIAM Journal on\nScientific Computing}, @w{Vol.@: 18}, @w{pp.@: 1}--22, 1997,\n@nospell{DOI}: @url{https://doi.org/10.1137/S1064827594276424}.\n\n@DOCSTRING(ode45)\n\n@DOCSTRING(ode23)\n\n@DOCSTRING(ode23s)\n\n@DOCSTRING(ode15s)\n\n@DOCSTRING(ode15i)\n\n@DOCSTRING(decic)\n\n@DOCSTRING(odeset)\n\n@DOCSTRING(odeget)\n\n@DOCSTRING(odeplot)\n"
  },
  {
    "path": "doc/interpreter/doccheck/README",
    "content": "################################################################################\n                                   README\n                             doccheck directory\n################################################################################\nThis directory contains scripts and data for validating Octave's Texinfo\ndocumentation.  These scripts are internal developer tools for ensuring\nconsistent documentation formats and avoiding misspellings.\n\nThe scripts provide 3 services:\n\n1) A spellchecker, built atop GNU aspell with a private dictionary of keywords\n   specific to Octave.\n\n2) A grammarchecker designed from scratch in Perl to ensure a common format\n   for Octave documentation and to make use of as many features of Texinfo as\n   possible.\n\n3) A list of undocumented functions, i.e, those missing an @DOCSTRING reference\n   in the .txi files.\n\n################################################################################\n                                   FILES\n################################################################################\nspellcheck : script to spellcheck a single .texi file.\naspell.conf: Octave-specific configuration file for Aspell.\naspell-octave.en.pws : private dictionary of Octave keywords for Aspell.\nadd_to_aspell_dict : script to add new words to the private Octave dictionary.\n\ngrammarcheck : Perl script to check Octave Texinfo documentation in a single\n               m-file(.m), C++ file(.cc), or Texinfo file(.txi, .texi).\n\nmk_undocumented_list : Perl script to make undocumented function list\n\n################################################################################\n                                   USAGE\n################################################################################\n\nSPELLING:\n\nFrom the top-level <OCTAVE_DIR>, type 'make spellcheck'.\nIf there are any misspellings in <filename>.texi they will be listed in the\nfile doc/interpreter/<filename>.scheck\n\nTo spellcheck a single file, type 'make doc/interpreter/<filename>.scheck'\nwhere the file to check is <filename>.texi (for example, \"tips.texi\").\n\n+Sample Flow\n\nmake doc/interpreter/arith.scheck\nvi doc/interpreter/arith.scheck\nvi doc/interpreter/arith.texi\n....\n  Review misspellings and identify where to correct the source (.m, .cc, .txi)\n  The original source file is marked with a comment:\n\n  @c FUNCTION_NAME SRC_DIR/SRC_FILE\n\n  When there is no source file comment, the source file is the .txi source.\n  Make corrections to the source files, *not* arith.texi which is derived.\n\n  There are generally three choices for resolving a reported misspelling:\n\n    1. The word is misspelled and should be corrected in the source.\n    2. The word should not be checked for spelling (for example, it might be\n       a proper name such as \"Lanczos\").  Use the @nospell{...} macro around\n       the word in the source (See Special Cases below).\n    3. The word is valid, but Octave-specific (for example, a function name\n       such as \"datenum\").  These words should be added to Octave's exception\n       dictionary (see Special Cases below).\n....\nmake       # propagate changes to arith.texi\n  repeat spellcheck until the words that remain are not misspellings.\n\n+Special Cases\n\nWords which are misspellings, but which can't be changed in the original\nsource, should be marked with the @nospell{WORD} macro.  This will cause aspell\nto ignore this particular instance of the word.\n\nFor example, in linalg.texi there is a citation of a paper from the\nManchester Centre for Computational Mathematics.  The proper spelling of Centre\nin the en_US locale is Center.  This word is not an Octave-specific exception\nwhich can be added to the private dictionary.  Instead the source is marked up:\nManchester @nospell{Centre} for Computational Mathematics.\n\naspell will no longer report any misspellings for linalg.texi.\n\nAny words remaining after all misspellings have been corrected are\nOctave-specific spellings and should be added to the Octave private dictionary.\nThe script invocation to add words to the dictionary is:\n\ndoccheck/add_to_aspell_dict file_of_misspellings\n\n\nGRAMMAR:\n\nTo be added\n\nUNDOCUMENTED FUNCTIONS:\n\nFrom the top-level <OCTAVE_DIR>, type 'make doc/interpreter/undocumented_list'.\nThis will produce the file \"undocumented_list\" with any undocumented functions.\n\nFunctions which don't require an @DOCSTRING reference can be added to the list\nof exceptions at the bottom of the mk_undocumented_list script.  This is often\nnecessary where a single DOCSTRING, such as besselj, is used to document\nmultiple functions.\n"
  },
  {
    "path": "doc/interpreter/doccheck/add-to-aspell-dict.pl",
    "content": "#!/usr/bin/perl -w\n\n########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n################################################################################\n# File   : add-to-aspell-dict.pl\n# Purpose: Merges a file of new words into an existing dictionary file.\n#          The resulting file is uniquified and sorted before being written out.\n# Usage  : add-to-aspell-dict.pl <filename-of-new-words>\n# Documentation: see README in doccheck directory\n################################################################################\n# Initialize variables\n# Private Octave dictionary for aspell\n$octdict_fname = './doccheck/aspell-octave.en.pws';\n\n################################################################################\n# Parse command line arguments\nunless (@ARGV == 1)\n{\n  die \"USAGE: add-to-aspell-dict.pl <filename-of-new-words>\\n\";\n}\n\n$new_words_fname = shift(@ARGV);\nif (! -r $new_words_fname)\n{\n  die \"Unable to read input file: $new_words_fname\\n\";\n}\n\n################################################################################\n# Add new words to a dictionary database\nopen (FH, \"<$new_words_fname\")\n  or die \"Unable to open file: $new_words_fname\\n\";\nwhile (<FH>) { $dict_db{$_} = 1; }\nclose (FH);\n\n# Add words from existing dictionary to dictionary database\nopen (FH, \"<$octdict_fname\")\n  or die \"Unable to open Octave dictionary: $octdict_fname\\n\";\n$header = <FH>;\nwhile (<FH>) { $dict_db{$_} = 1; }\nclose (FH);\n\n# Remove old dictionary file and write out new one\nunlink ($octdict_fname)\n  or die \"Unable to delete Octave dictionary: $octdict_fname\\n\";\nopen (FH, \">$octdict_fname\")\n  or die \"Unable to open file for writing: $octdict_fname\\n\";\nprint FH $header;\nprint FH sort { uc($a) cmp uc ($b) } keys(%dict_db);\nclose (FH);\n"
  },
  {
    "path": "doc/interpreter/doccheck/aspell-octave.en.pws",
    "content": "personal_ws-1.1 en 1\nAbsTol\naccumarray\nacknowledgements\nAcknowledgements\nadams\nAffero\nafterwards\nal\naleph\nallocatable\nAllowSemidefinite\namd\namongst\nanisotropic\nAPI\nAPIs\nappdata\napproximant\narg\nargs\nARMA\narpack\nArrayValued\nascii\nast\nasync\natan\nAttr\naudiodevinfo\naudioplayer\naudiorecorder\nAutoconf\nautocorrelated\nautocovariances\nAutoload\nautoload\nautoloaded\nAutoloading\nAutomake\nautoregression\nautoregressions\nAutoResizeChildren\nautoscaled\nAutoScaling\nAWK\nazimuthal\nbackend\nbackgroundcolor\nbacktrace\nbartlett\nBarycentric\nBaseValue\nbasevalue\nBDF\nbdf\nbenchmarking\nbetacdf\nbetainc\nbetainv\nbetaln\nbetapdf\nBFGS\nBICG\nBiConjugate\nbiharmonic\nbincoeff\nbinocdf\nbinoinv\nbinopdf\nBiomathematics\nbitwidth\nbitwise\nblas\nbmp\nboolean\nBooleans\nboolMatrix\nboxoff\nboxon\nbracketx\nbrackety\nbraindead\nbreakpoint\nbroadcastable\nBufSize\nbuiltin\nbulleted\nBulleted\nButtonDownFcn\nbuttondownfcn\nBV\nByRows\nBZ\nbzip\nCallbackObject\ncallee's\ncamd\nCancelString\ncauchy\ncaxis\nccolamd\ncd\ncdata\ncdatamapping\nCDF\ncdf\ncdot\nceil\ncellstr\ncellstrings\nChangeLog\ncharset\nchdir\nChebyshev\ncheckbox\ncheckboxes\nchecksums\nchisq\nchisquare\nchol\nCholesky\ncholmod\nchromaticity\ncindex\ncirc\ncircshift\ncirculant\ncircum\nclassdef\nclasspath\nclasspaths\nCLI\nclim\nclimmode\ncloserequestfcn\nclubsuit\nCMatrix\ncmember\nCMYK\ncodebases\ncodepage\ncoffset\ncolamd\nCollectOutput\ncolorbar\ncolorcube\ncolormap\ncolormaps\nColorOrder\ncolororder\nColorOrderIndex\ncolperm\ncommentstyle\nCommentStyle\nComparisonMethod\nComplexEqn\ncond\ncondest\nconformant\ncong\nconst\ncontextless\ncontourc\nConvertInfAndNaN\nconvhull\nConvolve\ncopyrightable\ncorrcoef\ncosecant\ncourseware\ncov\ncovariance\nCpost\nCpre\ncreatecancelbtn\nCreateFcn\nCRLF\ncrossflow\nCrout\ncrout\ncryptographic\nCSparse\nCSV\ncsymamd\nctranspose\nCTRL\nCtrl\ncubehelix\ncummax\ncummin\ncumprod\ncumsum\ncURL\nCurrentAxes\nCurrentFigure\nCurrentObject\ncurrentpoint\ncustomizations\ncxsparse\nCygwin\nDAE\nDAEs\ndaspk\ndasrt\ndassl\nDataAspectRatio\nDataScale\ndataset\ndatasource\nDataSource\ndatenum\ndatenums\ndatestr\ndatestrings\nddd\ndddd\ndeallocated\ndeallocating\ndeconv\nDeconvolve\ndecrement\ndefaultaxesbox\ndefaultuicontrolbackgroundcolor\ndeftypefn\nDelaunay\ndelaunay\ndelaunayn\ndeletefcn\nDeleteFcn\ndelim\ndeltaX\ndet\ndggsvd\ndiag\ndiagcomp\ndialogs\nDialogs\ndiamondsuit\ndifferentiable\ndigamma\ndimensionality\ndimensionally\ndir\ndiscretization\ndisp\ndisplayname\nDisplayName\ndisplayrange\ndMatrix\ndmperm\ndockcontrols\ndocstring\ndocstrings\ndOmega\ndoNotSpecify\ndotall\ndotexceptnewline\ndoublearrow\ndownarrow\ndowndate\ndroptol\ndt\ndx\ndy\neastoutside\nEastOutside\nEconometrics\nedgecolor\nEdgeLighting\nEi\nEIDORS\neigenpairs\neigenvector\neigenvectors\neigs\nelementwise\nelseif\nemacs\nemptyvalue\nEmptyValue\nencodings\nendfunction\nEndian\nendian\nendif\nendofline\nEndOfLine\nEndPoints\nEOF\nEOLs\neps\neq\nequidistributed\nEquilibration\nequilibration\nequispaced\nerf\nerfc\nerfi\nerrno\nErrorbar\nerrorbar\nerrorbars\nErrorbars\nerrordlg\nErrorHandler\nESC\net\netree\netreeplot\neval\nevalc\nExecutables\nExif\nexitflag\nexpcdf\nexpinv\nexppdf\nextendedtext\nextrema\nfacecolor\nFaceColor\nFaceLighting\nFaceNormals\nFaceVertexCData\nfacevertexcdata\nfactorizations\nfcdf\nfemmodel\nFFF\nFFT\nfft\nfftn\nfftpack\nFFTs\nfftw\nfieldname\nfieldnames\nFIFOs\nfilename\nFileName\nfilenames\nfilepaths\nFilesystem\nfiletype\nFinDiffType\nfinv\nFIRfilter\nfitboxtotext\nFIXME\nflac\nfltk\nFLTK\nfminsearch\nfminunc\nfontconfig\nFontConfig\nfontname\nFontName\nforall\nforcecelloutput\nforegroundcolor\nformfeed\nFortran\nfpdf\nfprintf\nFreeBSD\nFreeSans\nfreespacing\nfreetype\nFreeType\nFs\nFSF\nfullpath\nfullpathext\nfunc\nFunValCheck\ngamcdf\ngaminv\ngampdf\ngaussian\ngca\ngcbo\nGCC\ngcd\nge\nGECOS\ngejsv\ngeocdf\ngeoinv\ngeopdf\ngeotagging\ngeq\ngesdd\ngesvd\ngetaudiodata\ngetplayer\ngfortran\nGhostscript\nGhostscript's\nGIF\ngif\nglibc\nglobbing\nglpk\nGLS\ngls\nglyphs\nGMRES\nGnuplot\ngnuplot\nGNUTERM\nGoto\ngoto\ngouraud\ngperf\nGPL\nGPLK\ngplot\ngrabdemo\nGradObj\nGraphicsAlphaBits\nGraphicsMagick\ngrayscale\ngriddata\ngswin\ngui\nGUIs\ngzip\ngzipped\nHadamard\nHandleVisibility\nhandlevisibility\nHankel\nHanning\nhanning\nhardcode\nhardcoded\nhardcoding\nHDF\nhdf\nHeaderLines\nheaderlines\nheadlength\nheadstyle\nheadwidth\nheartsuit\nhelpdlg\nHelvetica\nHermitian\nHessenberg\nheteroscedascity\nheteroscedastic\nhggroup\nhggroups\nhgid\nhgload\nHH\nhh\nhistc\nholomorphic\nhorizontalalignment\nhorzcat\nhostname\nHSV\nhsv\nhtml\nhygecdf\nhygeinv\nhygepdf\nhyperthreading\nhypervolume\nichol\nict\nIDE\nIEC\nieee\nIEEE\nifelse\nifft\nifftn\nignorecase\nIgnoreCase\nij\nilu\nilutp\nIm\nimag\nImageMagick\nincludemissing\nincludenan\nincludezero\nIndices\nindices\ninfeasible\ninfty\ninit\nInitialSlope\nInitialStep\nInitialValue\ninline\ninmax\ninmin\ninpolygon\ninputdlg\ninputmax\ninputmin\ninputrc\nintegerhandle\nintegrand\nintegrands\nintegrations\nintegrators\ninternet\ninterp\ninterpderiv\ninterpft\ninterpn\ninterpolant\nInterpolants\ninterquartile\nINTMAX\ninuse\ninv\ninvariants\ninverthardcopy\ninvolutory\nipermute\nisa\nisclass\nisdir\nisempty\nishandle\nishghandle\nislogical\nismember\nisnumeric\nisolines\nisosurface\nisosurfaces\nisovalue\nisplaying\nisreal\nisrecording\nissparse\nisvector\niter\niteratively\nith\niy\niz\njacobian\nJacobian\nJacobians\njavaaddpath\njavamem\nJavascript\njbig\nJConstant\nJDK\nJIS\nJPattern\nJPEG\njpeg\njpg\nJSON\nJupyter\njvm\nJVM's\nkendall\nkeybindings\nkeypress\nkeypressfcn\nKeyType\nkron\nKrylov\nkurtosis\nLabelSpacing\nlangle\nlapack\nLaserJet\nLaTeX\nlceil\nldiv\nldivide\nldots\nle\nleaveInPlace\nleftarrow\nLeftarrow\nleftrightarrow\nleq\nlfloor\nlibcurl\nliblapack\nliboctave\nliboctinterp\nLibtool\nlicensors\nlineanchors\nlinearized\nlinefeeds\nlinesearch\nlinespec\nlinestyle\nLineStyleOrderIndex\nlinewidth\nlinkprop\nlistbox\nlistdlg\nListSize\nListString\nliteralspacing\nLM\nloadpath\nlogarithmically\nlogfile\nlogncdf\nlogninv\nlognpdf\nlookup\nLookup\nlookups\nlossless\nlsode\nlt\nlu\nluminance\nlvalue\nlvl\nlx\nly\nlz\nlzma\nlzw\nMagick\nmakefile\nmakefiles\nmakehgtform\nmakeinfo\nmakeValidName\nMandriva\nMAPE\nmape\nmarkeredgecolor\nmarkerfacecolor\nmarkersize\nMassSingular\nmatchcase\nmatlab\nMaxFunEvals\nmaxima\nMaxIntervalCount\nMaxIter\nMaxOrder\nMaxStep\nmdl\nmeansq\nMemoization\nmemoize\nmemoized\nmemoizing\nmenubar\nmenubars\nmenuselectedfcn\nMERCHANTABILITY\nMersenne\nmeshgrid\nmeshgridded\nmeshstyle\nmetadata\nMetafile\nmetafile\nMetaFile\nmetafiles\nmex\nmget\nmichol\nMinGW\nminima\nminimizer\nMinimizers\nMinitab\nminval\nMIP\nmiscompiled\nmkdir\nmkoctfile\nmldivide\nmmd\nmmm\nMMM\nmmmm\nmmmyy\nmmmyyyy\nmovegui\nmovfun\nmovmad\nmovmax\nmovmean\nmovmedian\nmovmin\nmovprod\nmovstd\nmovsum\nmovvar\nmpoles\nmpower\nmput\nmrdivide\nmsgbox\nMStateDependence\nMSYS\nmtimes\nMulti\nmulti\nmultibyte\nmultipage\nMultipleDelimsAsOne\nmultipledelimsasone\nMultiSelect\nmultistep\nMvPattern\nmxArray\nmyclass\nnabla\nnamespace\nNAMESPACE\nNaN\nnan\nnancond\nnanflag\nNaNs\nnanval\nnargin\nnargout\nnatively\nnbincdf\nnbininv\nnbinpdf\nnbsp\nncols\nnd\nndgrid\nndims\nne\nneq\nNextPlot\nnfft\nni\nNLP\nnnz\nnobalance\nnocompute\nnofill\nnolabel\nnoncommercially\nnonconformant\nnondecreasing\nnonincreasing\nnonnan\nNonNegative\nnonnegativity\nNonscalar\nnonscalar\nnonskew\nnonsmooth\nnonsparse\nnonzeros\nNOP\nnoperm\nnorc\nnormals\nnormcdf\nNormControl\nnormest\nnorminv\nnormpdf\nnortheastoutside\nNorthOutside\nnorthoutside\nnorthwestoutside\nnoscal\nnoshare\nnrows\nnthargout\nNTSC\nnumbertitle\nnumel\nnzmax\noct\noctaverc\nODEPACK\nODEs\noffscreen\nofig\nogg\nOgg\nOKString\nOLS\nomitmissing\nomitnan\nomitrows\nonCleanup\nonline\nOpenBLAS\nopengl\nOpenGL\nOpenJDK\noplus\noptimizations\nOrd\noregonator\nOrthogonalize\northonormal\noslash\notimes\noutdim\nouterposition\noutlier\noutliers\nOutputAllIndices\nOutputFcn\noutputfcn\nOutputSel\noverdetermined\noverridable\npaperorientation\nPaperPosition\npaperposition\npaperpositionmode\npapersize\nPaperUnits\npaperunits\nparametrically\nparfor\nparseparams\npartialrows\npbm\nPBMplus\npc\nPCG\npcg\npchip\npcr\nPCRE\npcre\nPCX\npdf\nPDF\npdflatex\npentadiagonal\nperiodogram\nperp\nPGF\nPGMRES\nPHP\npict\npiecewise\nPiecewise\npinv\nPixelRegion\nplayblocking\nPlotBoxAspectRatio\npng\nPNG\npoisscdf\npoissinv\npoisspdf\npolaraxes\npolyderiv\npolyeig\npolyfit\npolygamma\npolyval\npopupmenu\nPortAudio\npos\nPOSDEF\nPOSIX\npostorder\nPostScript\npowerset\npre\npreallocate\nprecisiondate\npreconditioner\npreconditioners\nPreformatted\npreformatted\npremultiplied\nPrepend\nprepended\npreprocessor\npreselected\npresolver\nPrettyPrint\nPrettyWriter\nprintf\npriori\nprodofsize\nProfiler\nprofiler\nprogrammatically\nprolate\nPromptString\npropto\nps\npseudoinverse\npseudonorm\npseudorandom\nPseudospectra\npseudospectrum\nptrace\npushbutton\npushbuttons\nPxx\nqhull\nQhull\nQP\nQQ\nQRUPDATE\nqrupdate\nQScintilla\nquadcc\nquadgk\nquadl\nquadpack\nquadv\nQuantile\nquantile\nquantiles\nquantization\nquartic\nquartile\nquestdlg\nQuickhull\nQZ\nqz\nradian\nradians\nradices\nradiobutton\nradix\nrande\nrandg\nrandi\nrandn\nrandp\nrandperm\nrangle\nranlib\nRapidJSON\nrasterized\nrceil\nrdivide\nreadline\nReadline\nrecordblocking\nRECT\nrecursing\nredistributable\nreentrant\nreflectance\nregex\nregressor\nrelicensing\nRelTol\nrenderer\nrenderers\nrenormalization\nrepelems\nreplacechildren\nReplacementStyle\nrepmat\nrepresentable\nreproducibility\nresampled\nresampling\nResize\nresize\nresized\nResizing\nresizing\nresnorm\nresparsify\nrestacks\nRESTful\nrestoreBG\nrestorePrevious\nRET\nretarget\nReturnOnError\nreturnonerror\nrfloor\nRGB\nrgb\nRGBImage\nRightarrow\nrightarrow\nrle\nrline\nrmdir\nrms\nRMS\nRMSE\nrmse\nrnd\nroffset\nrpath\nRPMs\nrtick\nrticklabels\nrticks\nruntime\nSamplePoint\nSamplePoints\nSAS\nScalable\nschar\nSchur\nscreenful\nScrollable\nsed\nseealso\nSelectionMode\nSep\nSHA\nshiftdim\nSIGNUM\nsignum\nsim\nSIMAX\nSIMD\nsimplechol\nsimplecholperm\nsimplematrix\nsimplexes\nsimplices\nsinc\nsinetone\nskewness\nslcidx\nslx\nsoutheastoutside\nSouthOutside\nsouthoutside\nsouthwestoutside\nsp\nspadesuit\nspalloc\nSPARSKIT\nspaugment\nspchol\nspcholperm\nspconvert\nspdiags\nSpearman's\nspecialness\nspecular\nspeye\nspfun\nsplinefit\nspmatrix\nspones\nspparms\nSPQR\nsprand\nsprandn\nsprandsym\nsprank\nSPSS\nspstats\nSQP\nsqrt\nsqrtm\nss\nsT\nstairstep\nstartup\nStartup\nstatinfo\nstdin\nstdout\nstepsize\nSTFT\nstr\nstrcmp\nstrcmpi\nstreamribbon\nstreamribbons\nStreamribbons\nstreamtube\nstreamtubes\nStreamtubes\nstringanchors\nstrncmp\nstrncmpi\nstrread\nstrread's\nstrsplit\nstruct\nstructs\nsubarrays\nSubclasses\nsubclasses\nsubdiagonal\nsubdiagonals\nsubdirectories\nsubdirectory\nsubexpressions\nsubfunction\nSubfunction\nsubfunctions\nSubfunctions\nsubinterval\nSubintervals\nsubintervals\nsublicenses\nSublicensing\nsubmatrices\nsubmatrix\nsubmenu\nsuboptimal\nsubprocess\nSubprocesses\nsubprocesses\nsubsasgn\nsubscripted\nSubscripted\nsubscripting\nsubseteq\nsubsindex\nsubspaces\nSubspaces\nsubsref\nsubstring\nsubstrings\nsubwindows\nSuiteSparse\nsumsq\nsuperclass\nSupercomputing\nsuperdiagonal\nsuperdiagonals\nsuperiorto\nsuperscripted\nsuperscripting\nsupset\nsupseteq\nsurd\nSV\nsvd\nSVD\nsvds\nSVG\nsvg\nsym\nSym\nSYMAMD\nsymamd\nsymbfact\nsymrcm\nsynonymously\nsyntaxes\nSyntaxes\ntcdf\nterminal's\ntex\ntexi\nTexinfo\ntexinfo\nTextAlphaBits\ntextarrow\ntextbackgroundcolor\ntextbox\ntextcolor\ntextedgecolor\ntextfield\ntextlinewidth\ntextmargin\ntextread\ntextrotation\ntextscan\nth\nthetatick\nthetaticklabels\nthetaticks\ntickaligned\nticklabels\nTikZ\nTimestamp\ntimestep\ntinv\ntmp\nToeplitz\ntogglebutton\ntogglebuttons\ntokenExtents\nTolFun\nTolX\ntoolchain\nToolkits\ntoolkits\ntoplevel\nTP\ntpdf\ntraceback\nTRANSA\ntrapz\nTreatAsEmpty\ntreatasempty\ntreelayout\ntreeplot\ntridiagonal\ntrigamma\ntrimesh\ntriplot\ntrisurf\ntrivariate\nTrueColor\ntruecolor\nttick\ntuples\ntxi\ntypedefs\nTypicalX\nUB\nub\nuchar\nUHESS\nUI\nuibuttongroup\nUibuttongroup\nuicontextmenu\nUicontextmenu\nUicontrol\nuicontrol\nuicontrols\nUID\nuifigure\nuimenu\nuint\nuipanel\nUipanel\nuipanels\nuipushtool\nUipushtool\nuipushtools\nuiputfile\nuitab\nUitable\nuitable\nuitoggletool\nUitoggletool\nuitoolbar\nUitoolbar\nulong\numfpack\numinus\nUnary\nunary\nunconvertible\nundirected\nundithered\nunifcdf\nunifinv\nUniformOutput\nUniformValues\nunifpdf\nunimodal\nUninstall\nuninstalled\nunivariate\nunix\nunmaintained\nunnorm\nunnormalized\nunordered\nunpadded\nunpermuted\nunpivoted\nunregister\nunregistering\nunscaled\nunshare\nUnshared\nunsymmetric\nuntabified\nuparrow\nuplus\nurl\nuserdata\nUsername\nushort\nUTC\nUTF\nValueType\nvariable's\nvarpi\nvarsigma\nvartheta\nvback\nvec\nvech\nvectorization\nvectorize\nvectorized\nVectorized\nvectorizing\nvee\nversa\nvertcat\nVertexNormals\nverticalalignment\nvertices\nviewable\nviridis\nVorbis\nvorbis\nvoronoi\nVoronoi\nwaitbar\nwaitbars\nWAV\nwav\nwaypoint\nWaypoints\nwaypoints\nWayPoints\nwblcdf\nwblinv\nwblpdf\nweboptions\nWestOutside\nwestoutside\nWhitespace\nwhitespace\nwhos\nWikipedia\nwildcard\nWildcards\nwildcards\nwindowbuttondownfcn\nwindowbuttonmotionfcn\nwindowbuttonupfcn\nWindowStyle\nwindowstyle\nWIPO\nwireframe\nwlen\nworkspace\nwp\nwriteable\nxb\nxboxes\nxc\nxcorr\nxdata\nxerrorbar\nxerrorbars\nXFig\nxfirst\nxGBTRF\nxGELSD\nxGETRF\nxGTSV\nxlast\nxlim\nxlimitmethod\nxlimmode\nxmax\nxmin\nxon\nxPBTRF\nxpos\nxPOTRF\nxPTSV\nxtest\nxtests\nxtick\nxticklabel\nxticklabelmode\nXTickLabelRotation\nxtickmode\nxticks\nxTRTRS\nxy\nxyboxes\nxyerrorbar\nxyerrorbars\nxyz\nyboxes\nyc\nydata\nyerrorbar\nyerrorbars\nyfirst\nylabel\nylast\nylim\nylimitmethod\nylimmode\nymax\nymin\nypos\nytick\nytickangle\nyticklabel\nyticklabelmode\nYTickLabelRotation\nyticklabels\nytickmode\nyticks\nyy\nYY\nyyyy\nYYYY\nyyyymmddTHHMMSS\nzggsvd\nZiggurat\nzlabel\nzlabels\nzlib\nzlim\nzlimitmethod\nzlimmode\nzmax\nzmin\nztick\nztickangle\nzticklabel\nzticklabelmode\nZTickLabelRotation\nzticklabels\nztickmode\nzticks\n"
  },
  {
    "path": "doc/interpreter/doccheck/aspell.conf",
    "content": "lang en_US\nmode texinfo\nadd-filter tex\nadd-texinfo-ignore  set\nadd-texinfo-ignore  ifclear\nadd-texinfo-ignore  ifset\nadd-texinfo-ignore  macro\nadd-texinfo-ignore  include\nadd-texinfo-ignore  anchor\nadd-texinfo-ignore  deftypefn\nadd-texinfo-ignore  deftypefnx\nadd-texinfo-ignore  printindex\nadd-texinfo-ignore  multitable\nadd-texinfo-ignore  nospell\npersonal ./doccheck/aspell-octave.en.pws\n"
  },
  {
    "path": "doc/interpreter/doccheck/mk-undocumented-list.pl",
    "content": "#!/usr/bin/perl -w\n\n########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n################################################################################\n# File: mk-undocumented-list.pl\n# Purpose: Create a list of functions present in Octave, but without a\n#          corresponding DOCSTRING entry in one of the *.txi files\n# Usage: make doc/interpreter/undocumented_list\n# Documentation: see README in doccheck directory\n################################################################################\n# Get a list from Octave of all visible functions\n@octave_output = <<`_END_OCT_SCRIPT_`;\n../../run-octave --norc --quiet --no-history --eval '\\\n  funclist = vertcat (__list_functions__ , __builtins__); \\\n  funclist = funclist(! strncmp (funclist, \\\"meta.\\\", 5)) \\\n  disp (\"#!-separator-!#\") \\\n  where = cellfun (\\@which, funclist, \\\"UniformOutput\\\", 0)'\n_END_OCT_SCRIPT_\n\nunless (@octave_output) { die \"Unable to invoke 'run-octave'.  Exiting\\n\" }\n\n################################################################################\n# Winnow list of functions that require a DOCSTRING\n\n# First, divide output in to list of functions and list of locations\n$idx = 0;\nwhile (($_ = $octave_output[$idx++]) !~ /^#!-separator-!#$/)\n{\n  push(@all_functions, $1) if (/] = (\\w+)$/);\n}\nwhile ($_ = $octave_output[$idx++])\n{\n  push(@where, $1) if (/] = (.+)$/);\n}\n\n# Sanity check that Octave script worked\nif ($#all_functions != $#where)\n{\n  die \"Unequal number of functions and locations.  Parsing failed\\n\";\n}\n\n# Second, remove functions based on directory location\n# deprecated directory, legacy directory, doc/interpreter directory,\n# test/ directory\nFUNC: foreach $idx (0 .. $#where)\n{\n  next FUNC if ($where[$idx] =~ /deprecated/i);\n  next FUNC if ($where[$idx] =~ /legacy/i);\n  next FUNC if ($where[$idx] =~ /interpreter/i);\n  next FUNC if ($where[$idx] =~ m#test/#i);\n\n  push (@functions, $all_functions[$idx]);\n}\n\n# Third, remove functions based on naming patterns\n# Remove internal functions from the list of features requiring a DOCSTRING\n@functions = grep (! /^__/, @functions);\n\n# Fourth, remove exceptions based on name that do not require documentation\n# Load list of function exceptions not requiring a DOCSTRING\n# Exception data is stored at the bottom of this script\nforeach $_ (<DATA>)\n{ chomp, $exceptions{$_}=1; }\n\n# Remove exception data from the list\n@functions = grep (! $exceptions{$_}, @functions);\n\n################################################################################\n# Get a list of all documented functions\nforeach $txi_file (glob(\"*.txi\"))\n{\n  open(TXI_FILE, $txi_file) or die \"Unable to open $txi_file for reading\\n\";\n  while (<TXI_FILE>)\n  {\n    $docstrings{$1} = 1 if (/\\@DOCSTRING\\((\\w+)\\)/);\n  }\n}\n\n################################################################################\n# Find features which have not been documented in the txi files\n@undocumented = grep (! $docstrings{$_}, @functions);\n\n# Exit successfully if no undocumented functions\nexit(0) if (! @undocumented);\n\n$, = \"\\n\";  # Set output record separator\nprint sort(@undocumented);\nprint \"\\n\";\nexit(1);\n\n################################################################################\n# Exception list of functions not requiring a DOCSTRING\n################################################################################\n# desktop : Remove when terminal widget is no longer experimental\n################################################################################\n__DATA__\nangle\nbessel\nbesselh\nbesseli\nbesselk\nbessely\nbug_report\nchdir\ndbnext\ndebug\ndesktop\nend\nexit\nF_DUPFD\nF_GETFD\nF_GETFL\nF_SETFD\nF_SETFL\nfact\nfinite\nflipdim\nfmod\ngammaln\ngui_mainfcn\nheight\nhome\ni\nifelse\nimport\ninf\ninverse\nisbool\nisfinite\nJ\nj\njava2mat\nlstat\nmetaclass\nnan\nnargchk\nO_APPEND\nO_ASYNC\nO_CREAT\nO_EXCL\nO_NONBLOCK\nO_RDONLY\nO_RDWR\nO_SYNC\nO_TRUNC\nO_WRONLY\nputenv\nrticks\nsetenv\nslash\nthetaticks\ntolower\ntoupper\nwidth\nylabel\nylim\nytickangle\nyticklabels\nyticks\nzlabel\nzlim\nztickangle\nzticklabels\nzticks\n"
  },
  {
    "path": "doc/interpreter/doccheck/spellcheck",
    "content": "#!/usr/bin/perl -w\n\n########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n################################################################################\n# File   : spellcheck\n# Purpose: Spellcheck a single Texinfo file\n#          written in Perl, rather than the shell, to be more portable to OS\n#          without good command lines such as Windows.\n# Usage  : spellcheck FILENAME.texi\n# Documentation: see README in doccheck directory\n################################################################################\nuse File::Temp \":POSIX\";\n\n# Initialize variables\n# Octave specific configuration file for aspell\n$aspell_conf = './doccheck/aspell.conf';\n\n################################################################################\n# Parse command line arguments\nif (@ARGV != 1)\n{\n  die (\"USAGE: spellcheck <filename.texi>\\n\",\n       \"       invoked from doc/interpreter directory\\n\");\n}\n\n################################################################################\n# Run aspell with Octave-specific configuration file.\n# Avoid use of pipes and use temporary files for portability\n$fname = shift(@ARGV);\n$tmp_fname = &tmpnam();  # from File::Temp\nsystem (\"aspell --conf=$aspell_conf list < $fname > $tmp_fname\");\n\nif ($?)\n{\n  unlink ($tmp_fname);\n  die (\"aspell command unsuccessful.  Cannot continue\\n\");\n}\n\nopen (FH, \"<$tmp_fname\")\n  or die \"Unable to open misspelled words file: $tmp_fname\\n\";\nwhile (<FH>) { $words{$_} = 1; }\nclose (FH);\n\n# Print out sorted and uniquified list of misspelled words\nprint sort { uc($a) cmp uc ($b) } keys(%words);\n\n################################################################################\n# Clean up temporary files\nunlink ($tmp_fname) or die \"Unable to delete temporary file: $tmp_fname\\n\";\n"
  },
  {
    "path": "doc/interpreter/errors.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Errors and Warnings\n@chapter Errors and Warnings\n\nOctave includes several functions for printing error and warning\nmessages.  When you write functions that need to take special action\nwhen they encounter abnormal conditions, you should print the error\nmessages using the functions described in this chapter.\n\nSince many of Octave's functions use these functions, it is also useful\nto understand them, so that errors and warnings can be handled.\n\n@menu\n* Handling Errors::\n* Handling Warnings::\n@end menu\n\n@node Handling Errors\n@section Handling Errors\n\nAn error is something that occurs when a program is in a state where\nit doesn't make sense to continue.  An example is when a function is\ncalled with too few input arguments.  In this situation the function\nshould abort with an error message informing the user of the lacking\ninput arguments.\n\nSince an error can occur during the evaluation of a program, it is\nvery convenient to be able to detect that an error occurred, so that\nthe error can be fixed.  This is possible with the @code{try} statement\ndescribed in @ref{The try Statement}.\n\n@menu\n* Raising Errors::\n* Catching Errors::\n* Recovering From Errors::\n@end menu\n\n@node Raising Errors\n@subsection Raising Errors\n\nThe most common use of errors is for checking input arguments to\nfunctions.  The following example calls the @code{error} function if\nthe function @code{f} is called without any input arguments.\n\n@example\n@group\nfunction f (arg1)\n  if (nargin == 0)\n    error (\"not enough input arguments\");\n  endif\nendfunction\n@end group\n@end example\n\nWhen the @code{error} function is called, it prints the given message\nand returns to the Octave prompt.  This means that no code following\na call to @code{error} will be executed.\n\nIt is also possible to assign an identification string to an error.\nIf an error has such an ID the user can catch this error\nas will be described in the next section.  To assign an ID to an error,\nsimply call @code{error} with two string arguments, where the first\nis the identification string, and the second is the actual error.  Note\nthat error IDs are in the format @qcode{\"NAMESPACE:ERROR-NAME\"}.  The namespace\n@qcode{\"Octave\"} is used for Octave's own errors.  Any other string is\navailable as a namespace for user's own errors.\n\n@DOCSTRING(error)\n\nSince it is common to use errors when there is something wrong with\nthe input to a function, Octave supports functions to simplify such code.\nWhen the @code{print_usage} function is called, it reads the help text\nof the function calling @code{print_usage}, and presents a useful error.\nIf the help text is written in Texinfo it is possible to present an\nerror message that only contains the function prototypes as described\nby the @code{@@deftypefn} parts of the help text.  When the help text\nisn't written in Texinfo, the error message contains the entire help\nmessage.\n\nConsider the following function.\n\n@example\n@group\n## -*- texinfo -*-\n## @@deftypefn @{@} f (@@var@{arg1@})\n## Function help text goes here@dots{}\n## @@end deftypefn\nfunction f (arg1)\n  if (nargin == 0)\n    print_usage ();\n  endif\nendfunction\n@end group\n@end example\n\n@noindent\nWhen it is called with no input arguments it produces the following\nerror.\n\n@example\n@group\nf ()\n\n@print{}  error: Invalid call to f.  Correct usage is:\n@print{}\n@print{}   -- f (ARG1)\n@print{}\n@print{}\n@print{}  Additional help for built-in functions and operators is\n@print{}  available in the online version of the manual.  Use the command\n@print{}  'doc <topic>' to search the manual index.\n@print{}\n@print{}  Help and information about Octave is also available on the WWW\n@print{}  at https://www.octave.org and via the help@@octave.org\n@print{}  mailing list.\n@end group\n@end example\n\n@DOCSTRING(print_usage)\n\n@DOCSTRING(beep)\n\n@DOCSTRING(beep_on_error)\n\n@node Catching Errors\n@subsection Catching Errors\n\nWhen an error occurs, it can be detected and handled using the\n@code{try} statement as described in @ref{The try Statement}.\nAs an example, the following piece of code counts the number of errors\nthat occurs during a @code{for} loop.\n\n@example\n@group\nnumber_of_errors = 0;\nfor n = 1:100\n  try\n    @dots{}\n  catch\n    number_of_errors++;\n  end_try_catch\nendfor\n@end group\n@end example\n\nThe above example treats all errors the same.  In many situations it\ncan however be necessary to discriminate between errors, and take\ndifferent actions depending on the error.  The @code{lasterror}\nfunction returns a structure containing information about the last\nerror that occurred.  As an example, the code above could be changed\nto count the number of errors related to the @samp{*} operator.\n\n@example\n@group\nnumber_of_errors = 0;\nfor n = 1:100\n  try\n    @dots{}\n  catch\n    msg = lasterror.message;\n    if (strfind (msg, \"operator *\"))\n      number_of_errors++;\n    endif\n  end_try_catch\nendfor\n@end group\n@end example\n\n@noindent\nAlternatively, the output of the @code{lasterror} function can be found\nin a variable indicated immediately after the @code{catch} keyword, as\nin the example below showing how to redirect an error as a warning:\n\n@example\n@group\ntry\n  @dots{}\ncatch err\n  warning(err.identifier, err.message);\n  @dots{}\nend_try_catch\n@end group\n@end example\n\n@DOCSTRING(lasterror)\n\n@DOCSTRING(lasterr)\n\nThe next example counts indexing errors.  The errors are caught using the\nfield identifier of the structure returned by the function @code{lasterror}.\n\n@example\n@group\nnumber_of_errors = 0;\nfor n = 1:100\n  try\n    @dots{}\n  catch\n    id = lasterror.identifier;\n    if (strcmp (id, \"Octave:invalid-indexing\"))\n      number_of_errors++;\n    endif\n  end_try_catch\nendfor\n@end group\n@end example\n\nThe functions distributed with Octave can issue one of the following\nerrors.\n\n@DOCSTRING(error_ids)\n\nWhen an error has been handled it is possible to raise it again.  This\ncan be useful when an error needs to be detected, but the program should\nstill abort.  This is possible using the @code{rethrow} function.  The\nprevious example can now be changed to count the number of errors\nrelated to the @samp{*} operator, but still abort if another kind of\nerror occurs.\n\n@example\n@group\nnumber_of_errors = 0;\nfor n = 1:100\n  try\n    @dots{}\n  catch\n    msg = lasterror.message;\n    if (strfind (msg, \"operator *\"))\n      number_of_errors++;\n    else\n      rethrow (lasterror);\n    endif\n  end_try_catch\nendfor\n@end group\n@end example\n\n@DOCSTRING(rethrow)\n\n@c FIXME: I have no idea what the rest of the functions are used for...\n\n@DOCSTRING(errno)\n\n@DOCSTRING(errno_list)\n\n@node Recovering From Errors\n@subsection Recovering From Errors\n\nOctave provides several ways of recovering from errors.  There are\n@code{try}/@code{catch} blocks,\n@code{unwind_protect}/@code{unwind_protect_cleanup} blocks,\nand finally the @code{onCleanup} command.\n\nThe @code{onCleanup} command associates an ordinary Octave variable (the\ntrigger) with an arbitrary function (the action).  Whenever the Octave variable\nceases to exist---whether due to a function return, an error, or simply because\nthe variable has been removed with @code{clear}---then the assigned function\nis executed.\n\nThe function can do anything necessary for cleanup such as closing open file\nhandles, printing an error message, or restoring global variables to their\ninitial values.  The last example is a very convenient idiom for Octave code.\nFor example:\n\n@example\n@group\nfunction rand42\n  old_state = rand (\"state\");\n  restore_state = onCleanup (@@() rand (\"state\", old_state));\n  rand (\"state\", 42);\n  @dots{}\nendfunction  # rand generator state restored by onCleanup\n@end group\n@end example\n\n@DOCSTRING(onCleanup)\n\n@node Handling Warnings\n@section Handling Warnings\n\nLike an error, a warning is issued when something unexpected happens.\nUnlike an error, a warning doesn't abort the currently running program.\nA simple example of a warning is when a number is divided by zero.  In\nthis case Octave will issue a warning and assign the value @code{Inf}\nto the result.\n\n@example\n@group\na = 1/0\n     @print{} warning: division by zero\n     @xresult{} a = Inf\n@end group\n@end example\n\n@menu\n* Issuing Warnings::\n* Enabling and Disabling Warnings::\n@end menu\n\n@node Issuing Warnings\n@subsection Issuing Warnings\n\nIt is possible to issue warnings from any code using the @code{warning}\nfunction.  In its most simple form, the @code{warning} function takes a\nstring describing the warning as its input argument.  As an example,\nthe following code controls if the variable @samp{a} is non-negative,\nand if not issues a warning and sets @samp{a} to zero.\n\n@example\n@group\na = -1;\nif (a < 0)\n  warning (\"'a' must be non-negative.  Setting 'a' to zero.\");\n  a = 0;\nendif\n     @print{} 'a' must be non-negative.  Setting 'a' to zero.\n@end group\n@end example\n\nSince warnings aren't fatal to a running program, it is not possible\nto catch a warning using the @code{try} statement or something similar.\nIt is however possible to access the last warning as a string using the\n@code{lastwarn} function.\n\nIt is also possible to assign an identification string to a warning.\nIf a warning has such an ID the user can enable and disable this warning\nas will be described in the next section.  To assign an ID to a warning,\nsimply call @code{warning} with two string arguments, where the first\nis the identification string, and the second is the actual warning.  Note\nthat warning IDs are in the format @qcode{\"NAMESPACE:WARNING-NAME\"}.  The\nnamespace @qcode{\"Octave\"} is used for Octave's own warnings.  Any other string\nis available as a namespace for user's own warnings.\n\n@DOCSTRING(warning)\n\n@DOCSTRING(lastwarn)\n\nThe functions distributed with Octave can issue one of the following\nwarnings.\n\n@DOCSTRING(warning_ids)\n\n@node Enabling and Disabling Warnings\n@subsection Enabling and Disabling Warnings\n\nThe @code{warning} function also allows you to control which warnings\nare actually printed to the screen.  If the @code{warning} function\nis called with a string argument that is either @qcode{\"on\"} or @qcode{\"off\"}\nall warnings will be enabled or disabled.\n\nIt is also possible to enable and disable individual warnings through\ntheir string identifications.  The following code will issue a warning\n\n@example\n@group\nwarning (\"example:non-negative-variable\",\n         \"'a' must be non-negative.  Setting 'a' to zero.\");\n@end group\n@end example\n\n@noindent\nwhile the following won't issue a warning\n\n@example\n@group\nwarning (\"off\", \"example:non-negative-variable\");\nwarning (\"example:non-negative-variable\",\n         \"'a' must be non-negative.  Setting 'a' to zero.\");\n@end group\n@end example\n"
  },
  {
    "path": "doc/interpreter/eval.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Evaluation\n@chapter Evaluation\n\nNormally, you evaluate expressions simply by typing them at the Octave\nprompt, or by asking Octave to interpret commands that you have saved in\na file.\n\nSometimes, you may find it necessary to evaluate an expression that has\nbeen computed and stored in a string, which is exactly what the\n@code{eval} function lets you do.\n\n@DOCSTRING(eval)\n\nThe @code{evalc} function additionally captures any console output\nproduced by the evaluated expression.\n\n@DOCSTRING(evalc)\n\n@menu\n* Calling a Function by its Name::\n* Evaluation in a Different Context::\n@end menu\n\n@node Calling a Function by its Name\n@section Calling a Function by its Name\n\nThe @code{feval} function allows you to call a function from a string\ncontaining its name.  This is useful when writing a function that needs to\ncall user-supplied functions.  The @code{feval} function takes the name\nof the function to call as its first argument, and the remaining\narguments are given to the function.\n\nThe following example is a simple-minded function using @code{feval}\nthat finds the root of a user-supplied function of one variable using\nNewton's method.\n\n@example\nfunction result = newtroot (fname, x)\n\n# usage: newtroot (fname, x)\n#\n#   fname : a string naming a function f(x).\n#   x     : initial guess\n\n  delta = tol = sqrt (eps);\n  maxit = 200;\n  fx = feval (fname, x);\n  for i = 1:maxit\n    if (abs (fx) < tol)\n      result = x;\n      return;\n    else\n      fx_new = feval (fname, x + delta);\n      deriv = (fx_new - fx) / delta;\n      x = x - fx / deriv;\n      fx = fx_new;\n    endif\n  endfor\n\n  result = x;\n\nendfunction\n@end example\n\nNote that this is only meant to be an example of calling user-supplied\nfunctions and should not be taken too seriously.  In addition to using a\nmore robust algorithm, any serious code would check the number and type\nof all the arguments, ensure that the supplied function really was a\nfunction, etc.  @xref{Predicates for Numeric Objects},\nfor a list of predicates for numeric objects, and @pxref{Status of Variables},\nfor a description of the @code{exist} function.\n\n@DOCSTRING(feval)\n\nA similar function @code{run} exists for calling user script files, that\nare not necessarily on the user path\n\n@DOCSTRING(run)\n\n@node Evaluation in a Different Context\n@section Evaluation in a Different Context\n\nBefore you evaluate an expression you need to substitute\nthe values of the variables used in the expression.  These\nare stored in the symbol table.  Whenever the interpreter\nstarts a new function it saves the current symbol table\nand creates a new one, initializing it with the list of\nfunction parameters and a couple of predefined variables\nsuch as @code{nargin}.  Expressions inside the function use the\nnew symbol table.\n\nSometimes you want to write a function so that when you\ncall it, it modifies variables in your own context.  This\nallows you to use a pass-by-name style of function,\nwhich is similar to using a pointer in programming languages such\nas C.\n\nConsider how you might write @code{save} and @code{load} as\nm-files.  For example:\n\n@example\n@group\nfunction create_data\n  x = linspace (0, 10, 10);\n  y = sin (x);\n  save mydata x y\nendfunction\n@end group\n@end example\n\nWith @code{evalin}, you could write @code{save} as follows:\n\n@example\n@group\nfunction save (file, name1, name2)\n  f = open_save_file (file);\n  save_var (f, name1, evalin (\"caller\", name1));\n  save_var (f, name2, evalin (\"caller\", name2));\nendfunction\n@end group\n@end example\n\n@noindent\nHere, @samp{caller} is the @code{create_data} function and @code{name1}\nis the string @qcode{\"x\"}, which evaluates simply as the value of @code{x}.\n\nYou later want to load the values back from @code{mydata}\nin a different context:\n\n@example\n@group\nfunction process_data\n  load mydata\n  @dots{} do work @dots{}\nendfunction\n@end group\n@end example\n\n@noindent\nWith @code{assignin}, you could write @code{load} as follows:\n\n@example\n@group\nfunction load (file)\n  f = open_load_file (file);\n  [name, val] = load_var (f);\n  assignin (\"caller\", name, val);\n  [name, val] = load_var (f);\n  assignin (\"caller\", name, val);\nendfunction\n@end group\n@end example\n\n@noindent\nHere, @samp{caller} is the @code{process_data} function.\n\nYou can set and use variables at the command prompt\nusing the context @samp{base} rather than @samp{caller}.\n\nThese functions are rarely used in practice.  One\nexample is the @code{fail (@samp{code}, @samp{pattern})} function\nwhich evaluates @samp{code} in the caller's context and\nchecks that the error message it produces matches\nthe given pattern.  Other examples such as @code{save} and @code{load}\nare written in C++ where all Octave variables\nare in the @samp{caller} context and @code{evalin} is not needed.\n\n@DOCSTRING(evalin)\n\n@DOCSTRING(assignin)\n"
  },
  {
    "path": "doc/interpreter/expr.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Expressions\n@chapter Expressions\n@cindex expressions\n\nExpressions are the basic building block of statements in Octave.  An\nexpression evaluates to a value, which you can print, test, store in a\nvariable, pass to a function, or assign a new value to a variable with\nan assignment operator.\n\nAn expression can serve as a statement on its own.  Most other kinds of\nstatements contain one or more expressions which specify data to be\noperated on.  As in other languages, expressions in Octave include\nvariables, array references, constants, and function calls, as well as\ncombinations of these with various operators.\n\n@menu\n* Index Expressions::\n* Calling Functions::\n* Arithmetic Ops::\n* Comparison Ops::\n* Boolean Expressions::\n* Assignment Ops::\n* Increment Ops::\n* Operator Precedence::\n@end menu\n\n@node Index Expressions\n@section Index Expressions\n\n@opindex (\n@opindex )\n@opindex :\n\nAn @dfn{index expression} allows you to reference or extract selected\nelements of a vector, a matrix (2-D), or a higher-dimensional array.  Arrays\nmay be indexed in one of three ways:\n@ref{XREFComponentIndexing,,Component Indexing},\n@ref{XREFLinearIndexing,,Linear Indexing}, and\n@ref{XREFLogicalIndexing,,Logical Indexing}.\n\n@anchor{XREFComponentIndexing}\n@subheading Component Indexing\n@cindex Component Indexing\nComponent indices may be scalars, vectors, ranges, or the special operator\n@samp{:}, which selects entire rows, columns, or higher-dimensional slices.\n\nComponent index expression consists of a set of parentheses enclosing @math{M}\nexpressions separated by commas.  Each individual index value, or component,\nis used for the respective dimension of the object that it is applied to.  In\nother words, the first index component is used for the first dimension (rows)\nof the object, the second index component is used for the second dimension\n(columns) of the object, and so on.  The number of index components @math{M}\ndefines the dimensionality of the index expression.  An index with two\ncomponents would be referred to as a 2-D index because it has two dimensions.\n\nIn the simplest case, 1) all components are scalars, and 2) the dimensionality\nof the index expression @math{M} is equal to the dimensionality of the object\nit is applied to.  For example:\n\n@example\n@group\nA = reshape (1:8, 2, 2, 2)  # Create 3-D array\nA =\n\nans(:,:,1) =\n\n   1   3\n   2   4\n\nans(:,:,2) =\n\n   5   7\n   6   8\n\nA(2, 1, 2)   # second row, first column of second slice\n             # in third dimension: ans = 6\n@end group\n@end example\n\nThe size of the returned object in a specific dimension is equal to the number\nof elements in the corresponding component of the index expression.  When all\ncomponents are scalars, the result is a single output value.  However, if any\ncomponent is a vector or range then the returned values are the Cartesian\nproduct of the indices in the respective dimensions.  For example:\n\n@example\n@group\nA([1, 2], 1, 2) @equiv{} [A(1,1,2); A(2,1,2)]\n@xresult{}\nans =\n   5\n   6\n@end group\n@end example\n\nThe total number of returned values is the product of the number of elements\nreturned for each index component.  In the example above, the total is 2*1*1 =\n2 elements.\n\nNotice that the size of the returned object in a given dimension is equal to\nthe number of elements in the index expression for that dimension.  In the code\nabove, the first index component (@code{[1, 2]}) was specified as a row vector,\nbut its shape is unimportant.  The important fact is that the component\nspecified two values, and hence the result must have a size of two in the first\ndimension; and because the first dimension corresponds to rows, the overall\nresult is a column vector.\n\n@example\n@group\nA(1, [2, 1, 1], 1)    # result is a row vector: ans = [3, 1, 1]\nA(ones (2, 2), 1, 1)  # result is a column vector: ans = [1; 1; 1; 1]\n@end group\n@end example\n\nThe first line demonstrates again that the size of the output in a given\ndimension is equal to the number of elements in the respective indexing\ncomponent.  In this case, the output has three elements in the second dimension\n(which corresponds to columns), so the result is a row vector.  The example\nalso shows how repeating entries in the index expression can be used to\nreplicate elements in the output.  The last example further proves that the\nshape of the indexing component is irrelevant, it is only the number of\nelements (2x2 = 4) which is important.\n\nThe above rules apply whenever the dimensionality of the index expression\nis greater than one (@math{M > 1}).  However, for one-dimensional index\nexpressions special rules apply and the shape of the output @strong{is}\ndetermined by the shape of the indexing component.  For example:\n\n@example\n@group\nA([1, 2])  # result is a row vector: ans = [1, 2]\nA([1; 2])  # result is a column vector: ans = [1; 2]\n@end group\n@end example\n\nThe shape rules for @var{A}(@var{P}) are:\n\n@itemize @bullet\n@item When at least one of @var{A} or @var{P} has two or more dimensions, then\n@var{A}(@var{P}) takes the shape of @var{P}.  This happens when at least one\nof the variables is a 2-D matrix or an N-D array.\n\n@item When both @var{A} and @var{P} are 1-D vectors, then @var{A}(@var{P}) takes\nthe shape of @var{A} itself.  In particular, when @var{A} is a row vector, then\n@var{A}(@var{P}) is also a row vector irrespective of @var{P}'s shape.  The\ncase when @var{A} is a column vector is analogous.\n@end itemize\n\n@opindex :, indexing expressions\n\nA colon (@samp{:}) may be used as an index component to select all of the\nelements in a specified dimension.  Given the matrix,\n\n@example\nA = [1, 2; 3, 4]\n@end example\n\n@noindent\nall of the following expressions are equivalent and select the first row of the\nmatrix.\n\n@example\n@group\nA(1, [1, 2])  # row 1, columns 1 and 2\nA(1, 1:2)     # row 1, columns in range 1-2\nA(1, :)       # row 1, all columns\n@end group\n@end example\n\nWhen a colon is used in the special case of 1-D indexing the result is always a\ncolumn vector.  Creating column vectors with a colon index is a very frequently\nencountered code idiom and is faster and generally clearer than calling\n@code{reshape} for this case.\n\n@example\n@group\nA(:)    # result is column vector: ans = [1; 2; 3; 4]\nA(:)'   # result is row vector: ans = [1, 2, 3, 4]\n@end group\n@end example\n\n@cindex @code{end}, indexing\n@cindex @sortas{end:} @code{end:} and @code{:end}\n\nIn index expressions the keyword @code{end} automatically refers to the last\nentry for a particular dimension.  This magic index can also be used in ranges\nand typically eliminates the needs to call @code{size} or @code{length} to\ngather array bounds before indexing.  For example:\n\n@example\n@group\nA(1:end/2)        # first half of A => [1, 2]\nA(end + 1) = 5;   # append element\nA(end) = [];      # delete element\nA(1:2:end)        # odd elements of A => [1, 3]\nA(2:2:end)        # even elements of A => [2, 4]\nA(end:-1:1)       # reversal of A => [4, 3, 2, 1]\n@end group\n@end example\n\nFor more information see the @ref{XREFend,,@qcode{\"end\"} keyword}.\n\n@anchor{XREFLinearIndexing}\n@subheading Linear Indexing\n@cindex Linear Indexing\nIt is permissible to use a 1-D index with a multi-dimensional object.  This is\nalso called @dfn{linear indexing}.  In this case, the elements of the\nmulti-dimensional array are taken in column-first order like in Fortran.  That\nis, the columns of the array are imagined to be stacked on top of each other\nto form a column vector and then the single linear index is applied to this\nvector.\n\n@example\n@group\nA = [1, 2, 3; 4, 5, 6; 7, 8, 9];\n\nA(4)    # linear index of 4th element in 2-D array: ans = 2\nA(3:5)  # result has shape of index component: ans = [7, 2, 5]\nA([1, 2, 2, 1]) # result includes repeated elements: ans = [1, 4, 4, 1]\n@end group\n@end example\n\n@anchor{XREFLogicalIndexing}\n@subheading Logical Indexing\n@cindex Logical Indexing\nLogical values can also be used to index matrices and cell arrays.\nWhen indexing with a logical array the result will be a vector containing\nthe values corresponding to @code{true} parts of the logical array.  The\nfollowing examples illustrates this.\n\n@example\n@group\ndata = [ 1, 2; 3, 4 ];\nidx = [true, false; false true];\ndata(idx)\n     @xresult{} ans = [ 1; 4 ]\n\nidx = (data <= 2);\ndata(idx)\n     @xresult{} ans = [ 1; 2 ]\n@end group\n@end example\n\n@noindent\nInstead of creating the @code{idx} array it is possible to replace\n@code{data(idx)} with @w{@code{data( data <= 2 )}}@ in the above code.\n\nWhile the size of the logical index expressions is usually the same as that\nof the array being indexed, this is not a necessary condition.  If the logical\nindex is a different size than the array, then elements from the array are\nmatched against elements from the logical index based on their linear order,\njust as with linear indexing.\n\n@example\n@group\ndata = [ 1, 2, 3; 4, 5, 6 ];\nidx = [ true, false, false, true ];\ndata(idx)\n     @xresult{} ans = [ 1 5 ]  # idx selected the 1st and 4th position elements\n@end group\n@end example\n\nIf the logical index is larger than then array an out of bounds error will\noccur if any true values attempt to select a linear position larger than the\nnumber of elements in the array.\n\n@example\n@group\nidx = [ true, true, false; false, true, false; true; false; false ];\ndata(idx)\n     @xresult{} ans = [ 1; 2; 5; 3 ] # returns positions 1, 3, 4, 5 in a column\n\nidx = [ true, true, false; false, true, false; true; false; true ];\ndata(idx)\n     @xresult{} error: a(9): out of bound 6 (dimensions are 2x3)\n@end group\n@end example\n\nFalse elements of a logical index outside the array size are ignored, but when\nthe ninth element of the logical index is true it triggers an error as it tries\nto select a nonexistent 9th element of the array.\n\n@menu\n* Advanced Indexing::\n@end menu\n\n@node Advanced Indexing\n@subsection Advanced Indexing\n\n@subsubheading Chained indexing\n@cindex Chained indexing\nOctave permits the use of repeated (chained) index expressions to extract\nsubsets of an array in a single command without the need to use intermediate\nvariables.  This can make it easier to write code with either complicated\nindexing operations or using multiple indexing methods.  The following example\nshows two equivalent index extraction operations:\n\n@example\n@group\nA = reshape (1:16, 4, 4);\nB = A(2:4, 2:3);\nC = B(3:5);\nD = C( [ true, false, true ] )\n     @xresult{} D = [ 8, 11 ]\n\nD = A(2:4, 2:3)(3:5)([ true, false, true ])\n     @xresult{} D = [ 8, 11 ]\n@end group\n@end example\n\nChained indexing will necessarily be slower than a single index expression\nproducing the same results, but is usually more computationally efficient\nthan performing multiple discrete indexing operations with intermediate\nvariable assignments.\n\nNote that chained indexing is only compatible with right-hand expressions and\ncan not be used on the left-hand side of assignment operations.\n\n@subsubheading Component to linear index conversion\nWhen it is necessary to extract subsets of entries out of an array whose\nindices cannot be written as a Cartesian product of components, linear\nindexing together with the function @code{sub2ind} can be used.  For example:\n\n@example\n@group\nA = reshape (1:8, 2, 2, 2)  # Create 3-D array\nA =\n\nans(:,:,1) =\n\n   1   3\n   2   4\n\nans(:,:,2) =\n\n   5   7\n   6   8\n\nA(sub2ind (size (A), [1, 2, 1], [1, 1, 2], [1, 2, 1]))\n   @xresult{} ans = [A(1, 1, 1), A(2, 1, 2), A(1, 2, 1)]\n@end group\n@end example\n\n@DOCSTRING(sub2ind)\n\n@DOCSTRING(ind2sub)\n\n@DOCSTRING(isindex)\n\n@subsubheading Component count not equal to dimensionality\nAn array with @samp{nd} dimensions can be indexed by an index expression which\nhas from 1 to @samp{nd} components.  For the ordinary and most common case, the\nnumber of components @samp{M} matches the number of dimensions @samp{nd}.  In\nthis case the ordinary indexing rules apply and each component corresponds to\nthe respective dimension of the array.\n\nHowever, if the number of indexing components exceeds the number of dimensions\n(@w{@code{M > nd}}) then the excess components must all be singletons\n(@code{1}).  Moreover, if @w{@code{M < nd}}, the behavior is equivalent to\nreshaping the input object so as to merge the trailing\n@w{@code{nd - M}}@ dimensions into the last index dimension @code{M}.  Thus,\nthe result will have the dimensionality of the index expression, and not the\noriginal object.  This is the case whenever dimensionality of the index is\ngreater than one (@w{@code{M > 1}}), so that the special rules for linear\nindexing are not applied.  This is easiest to understand with an example:\n\n@smallexample\nA = reshape (1:8, 2, 2, 2)  # Create 3-D array\nA =\n\nans(:,:,1) =\n\n   1   3\n   2   4\n\nans(:,:,2) =\n\n   5   7\n   6   8\n\n## 2-D indexing causes third dimension to be merged into second dimension.\n## Equivalent array for indexing, Atmp, is now 2x4.\nAtmp = reshape (A, 2, 4)\nAtmp =\n\n   1   3   5   7\n   2   4   6   8\n\n\nA(2,1)   # Reshape to 2x4 matrix, second entry of first column: ans = 2\nA(2,4)   # Reshape to 2x4 matrix, second entry of fourth column: ans = 8\nA(:,:)   # Reshape to 2x4 matrix, select all rows & columns, ans = Atmp\n@end smallexample\n\n@noindent\nNote here the elegant use of the double colon to replace the call to the\n@code{reshape} function.\n\n@subsubheading Array replication\nAnother advanced use of linear indexing is to create arrays filled with a\nsingle value.  This can be done by using an index of ones on a scalar value.\nThe result is an object with the dimensions of the index expression and every\nelement equal to the original scalar.  For example, the following statements\n\n@example\n@group\na = 13;\na(ones (1, 4))\n@end group\n@end example\n\n@noindent\nproduce a row vector whose four elements are all equal to 13.\n\nSimilarly, by indexing a scalar with two vectors of ones it is possible to\ncreate a matrix.  The following statements\n\n@example\n@group\na = 13;\na(ones (1, 2), ones (1, 3))\n@end group\n@end example\n\n@noindent\ncreate a 2x3 matrix with all elements equal to 13.  This could also have been\nwritten as\n\n@example\n13(ones (2, 3))\n@end example\n\nIt is more efficient to use indexing rather than the code construction\n@code{scalar * ones (M, N, @dots{})} because it avoids the unnecessary\nmultiplication operation.  Moreover, multiplication may not be defined for the\nobject to be replicated whereas indexing an array is always defined.  The\nfollowing code shows how to create a 2x3 cell array from a base unit which is\nnot itself a scalar.\n\n@example\n@group\n@{\"Hello\"@}(ones (2, 3))\n@end group\n@end example\n\nIt should be noted that @code{ones (1, n)} (a row vector of ones) results in a\nrange object (with zero increment).  A range is stored internally as a starting\nvalue, increment, end value, and total number of values; hence, it is more\nefficient for storage than a vector or matrix of ones whenever the number of\nelements is greater than 4.  In particular, when @samp{r} is a row vector, the\nexpressions\n\n@example\n  r(ones (1, n), :)\n@end example\n\n@example\n  r(ones (n, 1), :)\n@end example\n\n@noindent\nwill produce identical results, but the first one will be significantly faster,\nat least for @samp{r} and @samp{n} large enough.  In the first case the index\nis held in compressed form as a range which allows Octave to choose a more\nefficient algorithm to handle the expression.\n\nA general recommendation for users unfamiliar with these techniques is to use\nthe function @code{repmat} for replicating smaller arrays into bigger ones,\nwhich uses such tricks.\n\n@subsubheading Indexing for performance enhancement\nA second use of indexing is to speed up code.  Indexing is a fast operation\nand judicious use of it can reduce the requirement for looping over individual\narray elements, which is a slow operation.\n\nConsider the following example which creates a 10-element row vector\n@math{a} containing the values\n@tex\n$a_i = \\sqrt{i}$.\n@end tex\n@ifnottex\na(i) = sqrt (i).\n@end ifnottex\n\n@example\n@group\nfor i = 1:10\n  a(i) = sqrt (i);\nendfor\n@end group\n@end example\n\n@noindent\nIt is quite inefficient to create a vector using a loop like this.  In this\ncase, it would have been much more efficient to use the expression\n\n@example\na = sqrt (1:10);\n@end example\n\n@noindent\nwhich avoids the loop entirely.\n\nIn cases where a loop cannot be avoided, or a number of values must be combined\nto form a larger matrix, it is generally faster to set the size of the matrix\nfirst (pre-allocate storage), and then insert elements using indexing commands.\nFor example, given a matrix @code{a},\n\n@example\n@group\n[nr, nc] = size (a);\nx = zeros (nr, n * nc);\nfor i = 1:n\n  x(:,(i-1)*nc+1:i*nc) = a;\nendfor\n@end group\n@end example\n\n@noindent\nis considerably faster than\n\n@example\n@group\nx = a;\nfor i = 1:n-1\n  x = [x, a];\nendfor\n@end group\n@end example\n\n@noindent\nbecause Octave does not have to repeatedly resize the intermediate result.\n\nFor more performance improvement suggestions see\n@ref{Vectorization and Faster Code Execution}.\n\n@node Calling Functions\n@section Calling Functions\n\nA @dfn{function} is a name for a particular calculation.  Because it has\na name, you can ask for it by name at any point in the program.  For\nexample, the function @code{sqrt} computes the square root of a number.\n\nA fixed set of functions are @dfn{built-in}, which means they are\navailable in every Octave program.  The @code{sqrt} function is one of\nthese.  In addition, you can define your own functions.\n@xref{Functions and Scripts}, for information about how to do this.\n\n@cindex arguments in function call\nThe way to use a function is with a @dfn{function call} expression,\nwhich consists of the function name followed by a list of\n@dfn{arguments} in parentheses.  The arguments are expressions which give\nthe raw materials for the calculation that the function will do.  When\nthere is more than one argument, they are separated by commas.  If there\nare no arguments, you can omit the parentheses, but it is a good idea to\ninclude them anyway, to clearly indicate that a function call was\nintended.  Here are some examples:\n\n@example\n@group\nsqrt (x^2 + y^2)      # @r{One argument}\nones (n, m)           # @r{Two arguments}\nrand ()               # @r{No arguments}\n@end group\n@end example\n\nEach function expects a particular number of arguments.  For example, the\n@code{sqrt} function must be called with a single argument, the number\nto take the square root of:\n\n@example\nsqrt (@var{argument})\n@end example\n\nSome of the built-in functions take a variable number of arguments,\ndepending on the particular usage, and their behavior is different\ndepending on the number of arguments supplied.\n\nLike every other expression, the function call has a value, which is\ncomputed by the function based on the arguments you give it.  In this\nexample, the value of @code{sqrt (@var{argument})} is the square root of\nthe argument.  A function can also have side effects, such as assigning\nthe values of certain variables or doing input or output operations.\n\nUnlike most languages, functions in Octave may return multiple values.\nFor example, the following statement\n\n@example\n[u, s, v] = svd (a)\n@end example\n\n@noindent\ncomputes the singular value decomposition of the matrix @code{a} and\nassigns the three result matrices to @code{u}, @code{s}, and @code{v}.\n\nThe left side of a multiple assignment expression is itself a list of\nexpressions, that is, a list of variable names potentially qualified by\nindex expressions.  See also @ref{Index Expressions}, and\n@ref{Assignment Ops,,Assignment Expressions}.\n\n@menu\n* Call by Value::\n* Recursion::\n* Access via Handle::\n@end menu\n\n@node Call by Value\n@subsection Call by Value\n\nIn Octave, unlike Fortran, function arguments are passed by value, which\nmeans that each argument in a function call is evaluated and assigned to\na temporary location in memory before being passed to the function.\nThere is currently no way to specify that a function parameter should be\npassed by reference instead of by value.  This means that it is\nimpossible to directly alter the value of a function parameter in the\ncalling function.  It can only change the local copy within the function\nbody.  For example, the function\n\n@example\n@group\nfunction f (x, n)\n  while (n-- > 0)\n    disp (x);\n  endwhile\nendfunction\n@end group\n@end example\n\n@noindent\ndisplays the value of the first argument @var{n} times.  In this\nfunction, the variable @var{n} is used as a temporary variable without\nhaving to worry that its value might also change in the calling\nfunction.  Call by value is also useful because it is always possible to\npass constants for any function parameter without first having to\ndetermine that the function will not attempt to modify the parameter.\n\nThe caller may use a variable as the expression for the argument, but\nthe called function does not know this: it only knows what value the\nargument had.  For example, given a function called as\n\n@example\n@group\nfoo = \"bar\";\nfcn (foo)\n@end group\n@end example\n\n@noindent\nyou should not think of the argument as being ``the variable\n@code{foo}.''  Instead, think of the argument as the string value,\n@qcode{\"bar\"}.\n\nEven though Octave uses pass-by-value semantics for function arguments,\nvalues are not copied unnecessarily.  For example,\n\n@example\n@group\nx = rand (1000);\nf (x);\n@end group\n@end example\n\n@noindent\ndoes not actually force two 1000 by 1000 element matrices to exist\n@emph{unless} the function @code{f} modifies the value of its\nargument.  Then Octave must create a copy to avoid changing the\nvalue outside the scope of the function @code{f}, or attempting (and\nprobably failing!) to modify the value of a constant or the value of a\ntemporary result.\n\n@node Recursion\n@subsection Recursion\n@cindex factorial function\n\nWith some restrictions@footnote{Some of Octave's functions are\nimplemented in terms of functions that cannot be called recursively.\nFor example, the ODE solver @code{lsode} is ultimately implemented in a\nFortran subroutine that cannot be called recursively, so @code{lsode}\nshould not be called either directly or indirectly from within the\nuser-supplied function that @code{lsode} requires.  Doing so will result\nin an error.}, recursive function calls are allowed.  A\n@dfn{recursive function} is one which calls itself, either directly or\nindirectly.  For example, here is an inefficient@footnote{It would be\nmuch better to use @code{prod (1:n)}, or @code{gamma (n+1)} instead,\nafter first checking to ensure that the value @code{n} is actually a\npositive integer.} way to compute the factorial of a given integer:\n\n@example\n@group\nfunction retval = fact (n)\n  if (n > 0)\n    retval = n * fact (n-1);\n  else\n    retval = 1;\n  endif\nendfunction\n@end group\n@end example\n\n@noindent\nThis function is recursive because it calls itself directly.  It\neventually terminates because each time it calls itself, it uses an\nargument that is one less than was used for the previous call.  Once the\nargument is no longer greater than zero, it does not call itself, and\nthe recursion ends.\n\nThe function @code{max_recursion_depth} may be used to specify a limit\nto the recursion depth and prevents Octave from recursing infinitely.\nSimilarly, the function @code{max_stack_depth} may be used to specify\nlimit to the depth of function calls, whether recursive or not.  These\nlimits help prevent stack overflow on the computer Octave is running on,\nso that instead of exiting with a signal, the interpreter will throw an\nerror and return to the command prompt.\n\n@DOCSTRING(max_recursion_depth)\n\n@DOCSTRING(max_stack_depth)\n\n@node Access via Handle\n@subsection Access via Handle\n@cindex function handle\n@cindex indirect function call\n\n@opindex @@ function handle\nA function may be abstracted and referenced via a function handle acquired\nusing the special operator @samp{@@}.  For example,\n\n@example\n@group\nf = @@plus;\nf (2, 2)\n@xresult{}  4\n@end group\n@end example\n\n@noindent\nis equivalent to calling @code{plus (2, 2)} directly.  Beyond abstraction for\ngeneral programming, function handles find use in callback methods for figures\nand graphics by adding listeners to properties or assigning pre-existing\nactions, such as in the following example:\n\n@cindex figure deletefcn\n\n@example\n@group\nfunction mydeletefcn (h, ~, msg)\n  printf (msg);\nendfunction\nsombrero;\nset (gcf, \"deletefcn\", @{@@mydeletefcn, \"Bye!\\n\"@});\nclose;\n@end group\n@end example\n\n@noindent\nThe above will print @qcode{\"Bye!\"} to the terminal upon the closing\n(deleting) of the figure.  There are many graphics property actions for which\na callback function may be assigned, including, @code{buttondownfcn},\n@code{windowscrollwheelfcn}, @code{createfcn}, @code{deletefcn},\n@code{keypressfcn}, etc.\n\nNote that the @samp{@@} character also plays a role in defining class\nfunctions, i.e., methods, but not as a syntactical element.  Rather it begins a\ndirectory name containing methods for a class that shares the directory name\nsans the @samp{@@} character.  @xref{Object Oriented Programming}.\n\n@node Arithmetic Ops\n@section Arithmetic Operators\n@cindex arithmetic operators\n@cindex operators, arithmetic\n@cindex addition\n@cindex subtraction\n@cindex multiplication\n@cindex matrix multiplication\n@cindex division\n@cindex quotient\n@cindex negation\n@cindex unary minus\n@cindex exponentiation\n@cindex transpose\n@cindex Hermitian operator\n@cindex transpose, complex-conjugate\n@cindex complex-conjugate transpose\n\nThe following arithmetic operators are available, and work on scalars\nand matrices.  The element-by-element operators and functions broadcast\n(@pxref{Broadcasting}).\n\n@table @asis\n@item @var{x} + @var{y}\n@opindex +\nAddition (always works element by element).  If both operands are\nmatrices, the number of rows and columns must both agree, or they must\nbe broadcastable to the same shape.\n\n@item @var{x} - @var{y}\n@opindex -\nSubtraction (always works element by element).  If both operands are\nmatrices, the number of rows and columns of both must agree, or they\nmust be broadcastable to the same shape.\n\n@item @var{x} * @var{y}\n@opindex *\nMatrix multiplication.  The number of columns of @var{x} must agree with\nthe number of rows of @var{y}.\n\n@item @var{x} .* @var{y}\n@opindex .*\nElement-by-element multiplication.  If both operands are matrices, the\nnumber of rows and columns must both agree, or they must be\nbroadcastable to the same shape.\n\n@item @var{x} / @var{y}\n@opindex /\nRight division.  This is conceptually equivalent to the expression\n\n@example\n(inv (y') * x')'\n@end example\n\n@noindent\nbut it is computed without forming the inverse of @var{y'}.\n\nIf the system is not square, or if the coefficient matrix is singular,\na minimum norm solution is computed.\n\n@item @var{x} ./ @var{y}\n@opindex ./\nElement-by-element right division.\n\n@item @var{x} \\ @var{y}\n@opindex \\\nLeft division.  This is conceptually equivalent to the expression\n\n@example\ninv (x) * y\n@end example\n\n@noindent\nbut it is computed without forming the inverse of @var{x}.\n\nIf the system is not square, or if the coefficient matrix is singular,\na minimum norm solution is computed.\n\n@item @var{x} .\\ @var{y}\n@opindex .\\\nElement-by-element left division.  Each element of @var{y} is divided\nby each corresponding element of @var{x}.\n\n@item  @var{x} ^ @var{y}\n@opindex ^\nPower operator.  If @var{x} and @var{y} are both scalars, this operator\nreturns @var{x} raised to the power @var{y}.  If @var{x} is a scalar and\n@var{y} is a square matrix, the result is computed using an eigenvalue\nexpansion.  If @var{x} is a square matrix, the result is computed by\nrepeated multiplication if @var{y} is an integer, and by an eigenvalue\nexpansion if @var{y} is not an integer.  An error results if both\n@var{x} and @var{y} are matrices.\n\nThe implementation of this operator needs to be improved.\n\n@item  @var{x} .^ @var{y}\n@opindex .^\nElement-by-element power operator.  If both operands are matrices, the\nnumber of rows and columns must both agree, or they must be\nbroadcastable to the same shape.  If several complex results are\npossible, the one with smallest non-negative argument (angle) is taken.\nThis rule may return a complex root even when a real root is also possible.\nUse @code{realpow}, @code{realsqrt}, @code{cbrt}, or @code{nthroot} if a\nreal result is preferred.\n\n@item -@var{x}\n@opindex -\nNegation.\n\n@item +@var{x}\n@opindex +\nUnary plus.  This operator has no effect on the operand.\n\n@item @var{x}'\n@opindex @code{'}\nComplex conjugate transpose.  For real arguments, this operator is the\nsame as the transpose operator.  For complex arguments, this operator is\nequivalent to the expression\n\n@example\nconj (x.')\n@end example\n\n@item @var{x}.'\n@opindex @code{.'}\nTranspose.\n@end table\n\nNote that because Octave's element-by-element operators begin with a\n@samp{.}, there is a possible ambiguity for statements like\n\n@example\n1./m\n@end example\n\n@noindent\nbecause the period could be interpreted either as part of the constant\nor as part of the operator.  To resolve this conflict, Octave treats the\nexpression as if you had typed\n\n@example\n(1) ./ m\n@end example\n\n@noindent\nand not\n\n@example\n(1.) / m\n@end example\n\n@noindent\nAlthough this is inconsistent with the normal behavior of Octave's\nlexer, which usually prefers to break the input into tokens by\npreferring the longest possible match at any given point, it is more\nuseful in this case.\n\nNote also that some combinations of binary operators and whitespace can\ncreate apparent ambiguities with the Command Syntax form of calling\nfunctions.  @xref{Command Syntax and Function Syntax} for a description\nof how Octave treats that syntax.\n\n@opindex @code{'}\n@DOCSTRING(ctranspose)\n\n@DOCSTRING(pagectranspose)\n\n@opindex .\\\n@DOCSTRING(ldivide)\n\n@opindex -\n@DOCSTRING(minus)\n\n@opindex \\\n@DOCSTRING(mldivide)\n\n@opindex ^\n@DOCSTRING(mpower)\n\n@opindex /\n@DOCSTRING(mrdivide)\n\n@opindex *\n@DOCSTRING(mtimes)\n\n@opindex +\n@DOCSTRING(plus)\n\n@opindex .^\n@DOCSTRING(power)\n\n@opindex ./\n@DOCSTRING(rdivide)\n\n@opindex .*\n@DOCSTRING(times)\n\n@opindex @code{.'}\n@DOCSTRING(transpose)\n\n@DOCSTRING(pagetranspose)\n\n@opindex -\n@DOCSTRING(uminus)\n\n@opindex +\n@DOCSTRING(uplus)\n\n@node Comparison Ops\n@section Comparison Operators\n@cindex comparison expressions\n@cindex expressions, comparison\n@cindex relational operators\n@cindex operators, relational\n@cindex less than operator\n@cindex greater than operator\n@cindex equality operator\n@cindex tests for equality\n@cindex equality, tests for\n\n@dfn{Comparison operators} compare numeric values for relationships\nsuch as equality.  They are written using\n@emph{relational operators}.\n\nAll of Octave's comparison operators return a value of 1 if the\ncomparison is true, or 0 if it is false.  For matrix values, they all\nwork on an element-by-element basis.  Broadcasting rules apply.\n@xref{Broadcasting}.  For example:\n\n@example\n@group\n[1, 2; 3, 4] == [1, 3; 2, 4]\n     @xresult{}  1  0\n         0  1\n@end group\n@end example\n\nAccording to broadcasting rules, if one operand is a scalar and the\nother is a matrix, the scalar is compared to each element of the matrix\nin turn, and the result is the same size as the matrix.\n\n@table @code\n@item @var{x} < @var{y}\n@opindex <\nTrue if @var{x} is less than @var{y}.\n\n@item @var{x} <= @var{y}\n@opindex <=\nTrue if @var{x} is less than or equal to @var{y}.\n\n@item @var{x} == @var{y}\n@opindex ==\nTrue if @var{x} is equal to @var{y}.\n\n@item @var{x} >= @var{y}\n@opindex >=\nTrue if @var{x} is greater than or equal to @var{y}.\n\n@item @var{x} > @var{y}\n@opindex >\nTrue if @var{x} is greater than @var{y}.\n\n@item  @var{x} != @var{y}\n@itemx @var{x} ~= @var{y}\n@opindex !=\n@opindex ~=\nTrue if @var{x} is not equal to @var{y}.\n@end table\n\nFor complex numbers, the following ordering is defined:\n@var{z1} < @var{z2}\nif and only if\n\n@example\n@group\n  abs (@var{z1}) < abs (@var{z2})\n  || (abs (@var{z1}) == abs (@var{z2}) && arg (@var{z1}) < arg (@var{z2}))\n@end group\n@end example\n\nThis is consistent with the ordering used by @dfn{max}, @dfn{min} and\n@dfn{sort}, but is not consistent with @sc{matlab}, which only compares the real\nparts.\n\nString comparisons may also be performed with the @code{strcmp}\nfunction, not with the comparison operators listed above.\n@xref{Strings}.\n\n@opindex ==\n@DOCSTRING(eq)\n\n@opindex >=\n@DOCSTRING(ge)\n\n@opindex >\n@DOCSTRING(gt)\n\n@DOCSTRING(isequal)\n\n@DOCSTRING(isequaln)\n\n@opindex <=\n@DOCSTRING(le)\n\n@opindex <\n@DOCSTRING(lt)\n\n@opindex !=\n@opindex ~=\n@DOCSTRING(ne)\n\n@node Boolean Expressions\n@section Boolean Expressions\n@cindex expressions, boolean\n@cindex boolean expressions\n@cindex expressions, logical\n@cindex logical expressions\n@cindex operators, boolean\n@cindex boolean operators\n@cindex logical operators\n@cindex operators, logical\n@cindex and operator\n@cindex or operator\n@cindex not operator\n\n@menu\n* Element-by-element Boolean Operators::\n* Short-circuit Boolean Operators::\n@end menu\n\n@node Element-by-element Boolean Operators\n@subsection Element-by-element Boolean Operators\n@cindex element-by-element evaluation\n\nAn @dfn{element-by-element boolean expression} is a combination of\ncomparison expressions using the boolean\noperators ``or'' (@samp{|}), ``and'' (@samp{&}), and ``not'' (@samp{!}),\nalong with parentheses to control nesting.  The truth of the boolean\nexpression is computed by combining the truth values of the\ncorresponding elements of the component expressions.  A value is\nconsidered to be false if it is zero, and true otherwise.\n\nElement-by-element boolean expressions can be used wherever comparison\nexpressions can be used.  They can be used in @code{if} and @code{while}\nstatements.  However, a matrix value used as the condition in an\n@code{if} or @code{while} statement is only true if @emph{all} of its\nelements are nonzero.\n\nLike comparison operations, each element of an element-by-element\nboolean expression also has a numeric value (1 if true, 0 if false) that\ncomes into play if the result of the boolean expression is stored in a\nvariable, or used in arithmetic.\n\nHere are descriptions of the three element-by-element boolean operators.\n\n@table @code\n@item @var{boolean1} & @var{boolean2}\n@opindex &\nElements of the result are true if both corresponding elements of\n@var{boolean1} and @var{boolean2} are true.\n\n@item @var{boolean1} | @var{boolean2}\n@opindex |\nElements of the result are true if either of the corresponding elements\nof @var{boolean1} or @var{boolean2} is true.\n\n@item  ! @var{boolean}\n@itemx ~ @var{boolean}\n@opindex ~\n@opindex !\nEach element of the result is true if the corresponding element of\n@var{boolean} is false.\n@end table\n\nThese operators work on an element-by-element basis.  For example, the\nexpression\n\n@example\n[1, 0; 0, 1] & [1, 0; 2, 3]\n@end example\n\n@noindent\nreturns a two by two identity matrix.\n\nFor the binary operators, broadcasting rules apply.  @xref{Broadcasting}.\nIn particular, if one of the operands is a scalar and the other a\nmatrix, the operator is applied to the scalar and each element of the\nmatrix.\n\nFor the binary element-by-element boolean operators, both subexpressions\n@var{boolean1} and @var{boolean2} are evaluated before computing the\nresult.  This can make a difference when the expressions have side\neffects.  For example, in the expression\n\n@example\na & b++\n@end example\n\n@noindent\nthe value of the variable @var{b} is incremented even if the variable\n@var{a} is zero.\n\nThis behavior is necessary for the boolean operators to work as\ndescribed for matrix-valued operands.\n\n@opindex &\n@DOCSTRING(and)\n\n@opindex ~\n@opindex !\n@DOCSTRING(not)\n\n@opindex |\n@DOCSTRING(or)\n\n@node Short-circuit Boolean Operators\n@subsection Short-circuit Boolean Operators\n@cindex short-circuit evaluation\n\nCombined with the implicit conversion to scalar values in @code{if} and\n@code{while} conditions, Octave's element-by-element boolean operators\nare often sufficient for performing most logical operations.  However,\nit is sometimes desirable to stop evaluating a boolean expression as\nsoon as the overall truth value can be determined.  Octave's\n@dfn{short-circuit} boolean operators work this way.\n\n@table @code\n@item @var{boolean1} && @var{boolean2}\n@opindex &&\nThe expression @var{boolean1} is evaluated and converted to a scalar using\nthe equivalent of the operation @code{all (@var{boolean1}(:))}.  If\n@var{boolean1} is not a logical value, it is considered true if its value\nis nonzero, and false if its value is zero.  If @var{boolean1} is an array,\nit is considered true only if it is non-empty and all elements are\nnonzero.  If @var{boolean1} evaluates to false, the result of the overall\nexpression is false.  If it is true, the expression @var{boolean2} is\nevaluated in the same way as @var{boolean1}.  If it is true, the result of\nthe overall expression is true.  Otherwise the result of the overall\nexpression is false.\n\n@strong{Warning:} the one exception to the equivalence with evaluating\n@code{all (@var{boolean1}(:))} is when @code{boolean1} an the empty array.\nFor @sc{matlab} compatibility, the truth value of an empty array is always\n@code{false} so @code{[] && true} evaluates to @code{false} even though\n@code{all ([])} is @code{true}.\n\n@item @var{boolean1} || @var{boolean2}\n@opindex ||\nThe expression @var{boolean1} is evaluated and converted to a scalar using\nthe equivalent of the operation @code{all (@var{boolean1}(:))}.  If\n@var{boolean1} is not a logical value, it is considered true if its value\nis nonzero, and false if its value is zero.  If @var{boolean1} is an array,\nit is considered true only if it is non-empty and all elements are\nnonzero.  If @var{boolean1} evaluates to true, the result of the overall\nexpression is true.  If it is false, the expression @var{boolean2} is\nevaluated in the same way as @var{boolean1}.  If it is true, the result of\nthe overall expression is true.  Otherwise the result of the overall\nexpression is false.\n\n@strong{Warning:} the truth value of an empty matrix is always\n@code{false}, see the previous list item for details.\n@end table\n\nThe fact that both operands may not be evaluated before determining the\noverall truth value of the expression can be important.  For example, in\nthe expression\n\n@example\na && b++\n@end example\n\n@noindent\nthe value of the variable @var{b} is only incremented if the variable\n@var{a} is nonzero.\n\nThis can be used to write somewhat more concise code.  For example, it\nis possible write\n\n@example\n@group\nfunction f (a, b, c)\n  if (nargin > 2 && ischar (c))\n    @dots{}\n@end group\n@end example\n\n@noindent\ninstead of having to use two @code{if} statements to avoid attempting to\nevaluate an argument that doesn't exist.  For example, without the\nshort-circuit feature, it would be necessary to write\n\n@example\n@group\nfunction f (a, b, c)\n  if (nargin > 2)\n    if (ischar (c))\n      @dots{}\n@end group\n@end example\n\n@noindent\nWriting\n\n@example\n@group\nfunction f (a, b, c)\n  if (nargin > 2 & ischar (c))\n    @dots{}\n@end group\n@end example\n\n@noindent\nwould result in an error if @code{f} were called with one or two\narguments because Octave would be forced to try to evaluate both of the\noperands for the operator @samp{&}.\n\n@sc{matlab} has special behavior that allows the operators @samp{&} and\n@samp{|} to short-circuit when used in the truth expression for @code{if}\nand @code{while} statements.  Octave behaves the same way for\ncompatibility, however, the use of the @samp{&} and @samp{|} operators in\nthis way is strongly discouraged and a warning will be issued.  Instead,\nyou should use the @samp{&&} and @samp{||} operators that always have\nshort-circuit behavior.\n\nFinally, the ternary operator (?:) is not supported in Octave.  If\nshort-circuiting is not important, it can be replaced by the @code{ifelse}\nfunction.\n\n@DOCSTRING(merge)\n\n@node Assignment Ops\n@section Assignment Expressions\n@cindex assignment expressions\n@cindex assignment operators\n@cindex operators, assignment\n@cindex expressions, assignment\n\n@opindex =\n\nAn @dfn{assignment} is an expression that stores a new value into a\nvariable.  For example, the following expression assigns the value 1 to\nthe variable @code{z}:\n\n@example\nz = 1\n@end example\n\n@noindent\nAfter this expression is executed, the variable @code{z} has the value 1.\nWhatever old value @code{z} had before the assignment is forgotten.\nThe @samp{=} sign is called an @dfn{assignment operator}.\n\nAssignments can store string values also.  For example, the following\nexpression would store the value @qcode{\"this food is good\"} in the\nvariable @code{message}:\n\n@example\n@group\nthing = \"food\"\npredicate = \"good\"\nmessage = [ \"this \" , thing , \" is \" , predicate ]\n@xresult{} \"this food is good\"\n@end group\n@end example\n\n@noindent\n(This also illustrates concatenation of strings.)\n\n@cindex side effect\nMost operators (addition, concatenation, and so on) have no effect\nexcept to compute a value.  If you ignore the value, you might as well\nnot use the operator.  An assignment operator is different.  It does\nproduce a value, but even if you ignore the value, the assignment still\nmakes itself felt through the alteration of the variable.  We call this\na @dfn{side effect}.\n\n@cindex lvalue\nThe left-hand operand of an assignment need not be a variable\n(@pxref{Variables}).  It can also be an element of a matrix\n(@pxref{Index Expressions}) or a list of return values\n(@pxref{Calling Functions}).  These are all called @dfn{lvalues}, which\nmeans they can appear on the left-hand side of an assignment operator.\nThe right-hand operand may be any expression.  It produces the new value\nwhich the assignment stores in the specified variable, matrix element,\nor list of return values.\n\nIt is important to note that variables do @emph{not} have permanent types.\nThe type of a variable is simply the type of whatever value it happens\nto hold at the moment.  In the following program fragment, the variable\n@code{foo} has a numeric value at first, and a string value later on:\n\n@example\n@group\n>> foo = 1\nfoo = 1\n>> foo = \"bar\"\nfoo = bar\n@end group\n@end example\n\n@noindent\nWhen the second assignment gives @code{foo} a string value, the fact that\nit previously had a numeric value is forgotten.\n\nAssignment of a scalar to an indexed matrix sets all of the elements\nthat are referenced by the indices to the scalar value.  For example, if\n@code{a} is a matrix with at least two columns,\n\n@example\na(:, 2) = 5\n@end example\n\n@noindent\nsets all the elements in the second column of @code{a} to 5.\n\nWhen an assignment sets the value of a vector, matrix, or array element at a\nposition or dimension outside of that variable's current size, the array size\nwill be increased to accommodate the new values:\n\n@example\n@group\n>> a = [1, 2, 3]\na = 1 2 3\n>> a(4) = 4\na = 1 2 3 4\n>> a(2, :) = [5, 6, 7, 8]\na =\n   1   2   3   4\n   5   6   7   8\n@end group\n@end example\n\nAttempting to increase the size of an array such that the desired output size\nis ambiguous will result in an error:\n\n@example\n@group\n>> a(9) = 10\n@print{} error: Invalid resizing operation or ambiguous assignment to an\nout-of-bounds array element\n@end group\n@end example\n\nThis is because adding the 9th element creates an ambiguity in the desired\narray position for the value 10, each possibility requiring a different array\nsize expansion to accommodate the assignment.\n\nAssignments may be made with fewer specified elements than would be required to\nfill the newly expanded array as long as the assignment is unambiguous.  In\nthese cases the array will be automatically padded with @emph{null} values:\n\n@example\n@group\n>> a = [1, 2]\na =   1   2\n>> a(4) = 5\na =   1   2   0   5\n>> a(3, :) = [6, 7, 8, 9]\na =\n   1   2   0   5\n   0   0   0   0\n   6   7   8   9\n>> a(4, 5) = 10\na =\n    1    2    0    5    0\n    0    0    0    0    0\n    6    7    8    9    0\n    0    0    0    0   10\n@end group\n@end example\n\nFor all built-in types, the @emph{null} value will be appropriate to that object\ntype.\n\nNumeric arrays:\n\n@example\n@group\n>> a = int32 ([1, 2])\na = 1, 2\n>> a(4) = 5\na = 1 2 0 5\n@end group\n@end example\n\nLogical arrays:\n\n@example\n@group\n>> a = [true, false, true]\na = 1 0 1\n>> d(5) = true\nd = 1 0 1 0 1\n@end group\n@end example\n\nCharacter arrays:\n\n@example\n@group\n>> a = \"abc\"\na = abc\n>> a(5) = \"d\"\na = abcd\n>> double (a)\nans = 97 98 99 0 100\n@end group\n@end example\n\nCell arrays:\n\n@example\n@group\n>> e = @{1, \"foo\", [3, 4]@};\n>> e(5) = \"bar\"\ne =\n@{\n  [1,1] = 1\n  [1,2] = foo\n  [1,3] =\n\n     3   4\n\n  [1,4] = [](0x0)\n  [1,5] = bar\n@}\n@end group\n@end example\n\nStruct arrays:\n\n@example\n@group\n>> a = struct(\"foo\",1,\"bar\",2);\n>> a(3) = struct(\"foo\",3,\"bar\",9)\na =\n\n  1x3 struct array containing the fields:\n\n    foo\n    bar\n\n>> a.foo\nans = 1\nans = [](0x0)\nans = 3\n>> a.bar\nans = 2\nans = [](0x0)\nans = 9\n@end group\n@end example\n\nNote that Octave currently is unable to concatenate arbitrary object types\ninto arrays.  Such behavior must be explicitly defined within the object class\nor attempts at concatenation will result in an error.\n@xref{Object Oriented Programming}.\n\nAssigning an empty matrix @samp{[]} works in most cases to allow you to\ndelete rows or columns of matrices and vectors.  @xref{Empty Matrices}.\nFor example, given a 4 by 5 matrix @var{A}, the assignment\n\n@example\nA (3, :) = []\n@end example\n\n@noindent\ndeletes the third row of @var{A}, and the assignment\n\n@example\nA (:, 1:2:5) = []\n@end example\n\n@noindent\ndeletes the first, third, and fifth columns.\n\nDeleting part of an array object will necessarily resize the object.  When the\ndeletion allows for consistent size reduction across a dimension, e.g., one\nelement of a vector, or one row or column of a matrix, the size along that\ndimension will be reduced while preserving dimensionality.  If, however,\ndimensionality cannot be maintained, the object will be reshaped into a vector\nfollowing column-wise element ordering:\n\n@example\n@group\n>> a = [1, 2, 3, 4; 5, 6, 7, 8]\na =\n   1   2   3   4\n   5   6   7   8\n>> a(:, 3) = []\na =\n   1   2   4\n   5   6   8\n>> a(4) = []\na = 1 5 2 4 8\n@end group\n@end example\n\nAn assignment is an expression, so it has a value.  Thus, @code{z = 1}\nas an expression has the value 1.  One consequence of this is that you\ncan write multiple assignments together:\n\n@example\nx = y = z = 0\n@end example\n\n@noindent\nstores the value 0 in all three variables.  It does this because the\nvalue of @code{z = 0}, which is 0, is stored into @code{y}, and then\nthe value of @code{y = z = 0}, which is 0, is stored into @code{x}.\n\nThis is also true of assignments to lists of values, so the following is\na valid expression\n\n@example\n[a, b, c] = [u, s, v] = svd (a)\n@end example\n\n@noindent\nthat is exactly equivalent to\n\n@example\n@group\n[u, s, v] = svd (a)\na = u\nb = s\nc = v\n@end group\n@end example\n\nIn expressions like this, the number of values in each part of the\nexpression need not match.  For example, the expression\n\n@example\n[a, b] = [u, s, v] = svd (a)\n@end example\n\n@noindent\nis equivalent to\n\n@example\n@group\n[u, s, v] = svd (a)\na = u\nb = s\n@end group\n@end example\n\n@noindent\nThe number of values on the left side of the expression can, however,\nnot exceed the number of values on the right side.  For example, the\nfollowing will produce an error.\n\n@example\n@group\n[a, b, c, d] = [u, s, v] = svd (a);\n@print{} error: element number 4 undefined in return list\n@end group\n@end example\n\nThe symbol @code{~} may be used as a placeholder in the list of lvalues,\nindicating that the corresponding return value should be ignored and not stored\nanywhere:\n\n@example\n@group\n[~, s, v] = svd (a);\n@end group\n@end example\n\nThis is cleaner and more memory efficient than using a dummy variable.\nThe @code{nargout} value for the right-hand side expression is not affected.\nIf the assignment is used as an expression, the return value is a\ncomma-separated list with the ignored values dropped.\n\n@opindex +=\nA very common programming pattern is to increment an existing variable\nwith a given value, like this\n\n@example\na = a + 2;\n@end example\n\n@noindent\nThis can be written in a clearer and more condensed form using the\n@code{+=} operator\n\n@example\na += 2;\n@end example\n\n@noindent\n@opindex -=\n@opindex *=\n@opindex /=\nSimilar operators also exist for subtraction (@code{-=}),\nmultiplication (@code{*=}), and division (@code{/=}).  An expression\nof the form\n\n@example\n@var{expr1} @var{op}= @var{expr2}\n@end example\n\n@noindent\nis evaluated as\n\n@example\n@var{expr1} = (@var{expr1}) @var{op} (@var{expr2})\n@end example\n\n@noindent\nwhere @var{op} can be either @code{+}, @code{-}, @code{*}, or @code{/},\nas long as @var{expr2} is a simple expression with no side effects.  If\n@var{expr2} also contains an assignment operator, then this expression\nis evaluated as\n\n@example\n@group\n@var{temp} = @var{expr2}\n@var{expr1} = (@var{expr1}) @var{op} @var{temp}\n@end group\n@end example\n\n@noindent\nwhere @var{temp} is a placeholder temporary value storing the computed\nresult of evaluating @var{expr2}.  So, the expression\n\n@example\na *= b+1\n@end example\n\n@noindent\nis evaluated as\n\n@example\na = a * (b+1)\n@end example\n\n@noindent\nand @emph{not}\n\n@example\na = a * b + 1\n@end example\n\nYou can use an assignment anywhere an expression is called for.  For\nexample, it is valid to write @code{x != (y = 1)} to set @code{y} to 1\nand then test whether @code{x} equals 1.  But this style tends to make\nprograms hard to read.  Except in a one-shot program, you should rewrite\nit to get rid of such nesting of assignments.  This is never very hard.\n\n@cindex increment operator\n@cindex decrement operator\n@cindex operators, increment\n@cindex operators, decrement\n\n@node Increment Ops\n@section Increment Operators\n\n@emph{Increment operators} increase or decrease the value of a variable\nby 1.  The operator to increment a variable is written as @samp{++}.  It\nmay be used to increment a variable either before or after taking its\nvalue.\n\nFor example, to pre-increment the variable @var{x}, you would write\n@code{++@var{x}}.  This would add one to @var{x} and then return the new\nvalue of @var{x} as the result of the expression.  It is exactly the\nsame as the expression @code{@var{x} = @var{x} + 1}.\n\nTo post-increment a variable @var{x}, you would write @code{@var{x}++}.\nThis adds one to the variable @var{x}, but returns the value that\n@var{x} had prior to incrementing it.  For example, if @var{x} is equal\nto 2, the result of the expression @code{@var{x}++} is 2, and the new\nvalue of @var{x} is 3.\n\nFor matrix and vector arguments, the increment and decrement operators\nwork on each element of the operand.\n\nThe increment and decrement operators must \"hug\" their corresponding\nvariable.  That means, no white spaces are allowed between these\noperators and the variable they affect.\n\nHere is a list of all the increment and decrement expressions.\n\n@table @code\n@item ++@var{x}\n@opindex ++\nThis expression increments the variable @var{x}.  The value of the\nexpression is the @emph{new} value of @var{x}.  It is equivalent to the\nexpression @code{@var{x} = @var{x} + 1}.\n\n@item --@var{x}\n@opindex @code{--}\nThis expression decrements the variable @var{x}.  The value of the\nexpression is the @emph{new} value of @var{x}.  It is equivalent to the\nexpression @code{@var{x} = @var{x} - 1}.\n\n@item @var{x}++\n@opindex ++\nThis expression causes the variable @var{x} to be incremented.  The\nvalue of the expression is the @emph{old} value of @var{x}.\n\n@item @var{x}--\n@opindex @code{--}\nThis expression causes the variable @var{x} to be decremented.  The\nvalue of the expression is the @emph{old} value of @var{x}.\n@end table\n\n@node Operator Precedence\n@section Operator Precedence\n@cindex operator precedence\n\n@dfn{Operator precedence} determines how operators are grouped, when\ndifferent operators appear close by in one expression.  For example,\n@samp{*} has higher precedence than @samp{+}.  Thus, the expression\n@code{a + b * c} means to multiply @code{b} and @code{c}, and then add\n@code{a} to the product (i.e., @code{a + (b * c)}).\n\nYou can overrule the precedence of the operators by using parentheses.\nYou can think of the precedence rules as saying where the parentheses\nare assumed if you do not write parentheses yourself.  In fact, it is\nwise to use parentheses whenever you have an unusual combination of\noperators, because other people who read the program may not remember\nwhat the precedence is in this case.  You might forget as well, and then\nyou too could make a mistake.  Explicit parentheses will help prevent\nany such mistake.\n\nWhen operators of equal precedence are used together, the leftmost\noperator groups first, except for the assignment operators, which group\nin the opposite order.  Thus, the expression @code{a - b + c} groups as\n@code{(a - b) + c}, but the expression @code{a = b = c} groups as\n@code{a = (b = c)}.\n\nThe precedence of prefix unary operators is important when another\noperator follows the operand.  For example, @code{-x^2} means\n@code{-(x^2)}, because @samp{-} has lower precedence than @samp{^}.\n\nHere is a table of the operators in Octave, in order of decreasing\nprecedence.  Unless noted, all operators group left to right.\n\n@table @code\n@item function call and array indexing, cell array indexing, and structure element indexing\n@samp{()}  @samp{@{@}} @samp{.}\n\n@item postfix increment, and postfix decrement\n@samp{++}  @samp{--}\n\nThese operators group right to left.\n\n@item transpose and exponentiation\n@samp{'} @samp{.'} @samp{^} @samp{.^}\n\n@item unary plus, unary minus, prefix increment, prefix decrement, and logical \"not\"\n@samp{+} @samp{-} @samp{++}  @samp{--} @samp{~} @samp{!}\n\n@item multiply and divide\n@samp{*} @samp{/} @samp{\\} @samp{.\\} @samp{.*} @samp{./}\n\n@item add, subtract\n@samp{+} @samp{-}\n\n@item colon\n@samp{:}\n\n@item relational\n@samp{<} @samp{<=} @samp{==} @samp{>=} @samp{>} @samp{!=} @samp{~=}\n\n@item element-wise \"and\"\n@samp{&}\n\n@item element-wise \"or\"\n@samp{|}\n\n@item logical \"and\"\n@samp{&&}\n\n@item logical \"or\"\n@samp{||}\n\n@item assignment\n@samp{=} @samp{+=} @samp{-=} @samp{*=} @samp{/=} @samp{\\=}\n@samp{^=} @samp{.*=} @samp{./=} @samp{.\\=} @samp{.^=} @samp{|=}\n@samp{&=}\n\nThese operators group right to left.\n@end table\n"
  },
  {
    "path": "doc/interpreter/external.txi",
    "content": "@c Copyright (C) 2007-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node External Code Interface\n@appendix External Code Interface\n@cindex dynamic-linking\n@cindex Dynamically Linked Functions\n@cindex Octave API\n\n\"The sum of human wisdom is not contained in any one language\"\n\n                                               --- Ezra Pound\n\nOctave is a fantastic language for solving many problems in science and\nengineering.  However, it is not the only computer language and there are times\nwhen you may want to use code written in other languages.  Good reasons for\ndoing so include: 1) not re-inventing the wheel; existing function libraries\nwhich have been thoroughly tested and debugged or large scale simulation\ncodebases are a good example, 2) accessing unique capabilities of a different\nlanguage; for example the well-known regular expression functions of Perl (but\ndon't do that because @code{regexp} already exists in Octave).\n\nPerformance should generally @strong{not} be a reason for using compiled\nextensions.  Although compiled extensions can run faster, particularly if they\nreplace a loop in Octave code, this is almost never the best path to take.\nFirst, there are many techniques to speed up Octave performance while remaining\nwithin the language.  Second, Octave is a high-level language that makes it\neasy to perform common mathematical tasks.  Giving that up means shifting the\nfocus from solving the real problem to solving a computer programming problem.\nIt means returning to low-level constructs such as pointers, memory management,\nmathematical overflow/underflow, etc.  Because of the low level nature, and the\nfact that the compiled code is executed outside of Octave, there is the very\nreal possibility of crashing the interpreter and losing work.\n\nBefore going further, you should first determine if you really need to bother\nwriting code outside of Octave.\n\n@itemize @bullet\n@item\nCan I get the same functionality using the Octave scripting language alone?\n\nEven when a function already exists outside the language, it may be better to\nsimply reproduce the behavior in an m-file rather than attempt to interface to\nthe outside code.\n\n@item\nIs the code thoroughly optimized for Octave?\n\nIf performance is an issue you should always start with the in-language\ntechniques for getting better performance.  Chief among these is vectorization\n(@pxref{Vectorization and Faster Code Execution}) which not only makes the code\nconcise and more understandable but improves performance (10X-100X).  If loops\nmust be used, make sure that the allocation of space for variables takes place\noutside the loops using an assignment to a matrix of the right size, or zeros.\n\n@item\nDoes the code make as much use as possible of existing built-in library\nroutines?\n\nThese routines are highly optimized and many do not carry the overhead of being\ninterpreted.\n\n@item\nDoes writing a dynamically linked function represent a useful investment of\nyour time, relative to staying in Octave?\n\nIt will take time to learn Octave's interface for external code and there will\ninevitably be issues with tools such as compilers.\n@end itemize\n\nWith that said, Octave offers a versatile interface for including chunks of\ncompiled code as dynamically linked extensions.  These dynamically linked\nfunctions can be called from the interpreter in the same manner as any ordinary\nfunction.  The interface is bi-directional and external code can call Octave\nfunctions (like @code{plot}) which otherwise might be very difficult to\ndevelop.\n\nThe interface is centered around supporting the languages C++, C, and Fortran.\nOctave itself is written in C++ and can call external C++/C code through its\nnative oct-file interface.  The C language is also supported through the\nmex-file interface for compatibility with @sc{matlab}.  Fortran code is easiest\nto reach through the oct-file interface.\n\nBecause many other languages provide C or C++ APIs it is relatively simple to\nbuild bridges between Octave and other languages.  This is also a way to bridge\nto hardware resources which often have device drivers written in C.\n\n@menu\n* Oct-Files::\n* Mex-Files::\n* Standalone Programs::\n* Java Interface::\n@end menu\n\n@node Oct-Files\n@section Oct-Files\n@cindex oct-files\n@cindex mkoctfile\n@cindex oct\n\n@menu\n* Getting Started with Oct-Files::\n* Matrices and Arrays in Oct-Files::\n* Character Strings in Oct-Files::\n* Cell Arrays in Oct-Files::\n* Structures in Oct-Files::\n* Sparse Matrices in Oct-Files::\n* Accessing Global Variables in Oct-Files::\n* Calling Octave Functions from Oct-Files::\n* Calling External Code from Oct-Files::\n* Allocating Local Memory in Oct-Files::\n* Input Parameter Checking in Oct-Files::\n* Exception and Error Handling in Oct-Files::\n* Documentation and Testing of Oct-Files::\n@c * Application Programming Interface for Oct-Files::\n@end menu\n\n@node Getting Started with Oct-Files\n@subsection Getting Started with Oct-Files\n\nOct-files are pieces of C++ code that have been compiled with the Octave API\ninto a dynamically loadable object.  They take their name from the file which\ncontains the object which has the extension @file{.oct}.\n\nFinding a C++ compiler, using the correct switches, adding the right include\npaths for header files, etc.@: is a difficult task.  Octave automates this by\nproviding the @code{mkoctfile} command with which to build oct-files.  The\ncommand is available from within Octave or at the shell command line.\n\n@DOCSTRING(mkoctfile)\n\nConsider the following short example which introduces the basics of writing a\nC++ function that can be linked to Octave.\n\n@example\n@group\n@EXAMPLEFILE(helloworld.cc)\n@end group\n@end example\n\nThe first critical line is @code{#include <octave/oct.h>} which makes available\nmost of the definitions necessary for a C++ oct-file.  Note that\n@file{octave/oct.h} is a C++ header and cannot be directly @code{#include}'ed\nin a C source file, nor any other language.\n\nIncluded by @file{oct.h} is a definition for the macro\n@w{@code{DEFUN_DLD}}@ which creates a dynamically loaded function.  This macro\ntakes four arguments:\n\n@enumerate 1\n@item The function name as it will be seen in Octave,\n\n@item The list of arguments to the function of type @code{octave_value_list},\n\n@item The number of output arguments, which can be---and often is---omitted if\nnot used, and\n\n@item The string to use for the help text of the function.\n@end enumerate\n\nThe return type of functions defined with @w{@code{DEFUN_DLD}}@ is always\n@code{octave_value_list}.\n\nThere are a couple of important considerations in the choice of function name.\nFirst, it must be a valid Octave function name and so must be a sequence of\nletters, digits, and underscores not starting with a digit.  Second, as Octave\nuses the function name to define the filename it attempts to find the function\nin, the function name in the @w{@code{DEFUN_DLD}}@ macro must match the filename\nof the oct-file.  Therefore, the above function should be in a file\n@file{helloworld.cc}, and would be compiled to an oct-file using the command\n\n@example\nmkoctfile helloworld.cc\n@end example\n\nThis will create a file called @file{helloworld.oct} that is the compiled\nversion of the function.  It should be noted that it is perfectly acceptable to\nhave more than one @w{@code{DEFUN_DLD}}@ function in a source file.  However,\nthere must either be a symbolic link to the oct-file for each of the functions\ndefined in the source code with the @w{@code{DEFUN_DLD}}@ macro or the\n@code{autoload} (@pxref{Function Files}) function should be used.\n\nThe rest of the function shows how to find the number of input arguments, how\nto print through the Octave pager, and how to return from the function.  After\ncompiling this function as above, an example of its use is\n\n@example\n@group\nhelloworld (1, 2, 3)\n@print{} Hello World has 3 input arguments and 0 output arguments.\n@end group\n@end example\n\nSubsequent sections show how to use specific classes from Octave's core\ninternals.  Base classes like @code{dMatrix} (a matrix of double values) are\nfound in the directory @file{liboctave/array}.  The definitive reference for\nhow to use a particular class is the header file itself.  However, it is often\nenough simply to study the examples in the manual in order to be able to use a\nclass.\n\n@node Matrices and Arrays in Oct-Files\n@subsection Matrices and Arrays in Oct-Files\n\nOctave supports a number of different array and matrix classes, the majority of\nwhich are based on the @code{Array} class.  The exception are the sparse matrix\ntypes discussed separately below.  There are three basic matrix types:\n\n@table @code\n@item Matrix\nA double precision matrix class defined in @file{dMatrix.h}\n\n@item ComplexMatrix\nA complex matrix class defined in @file{CMatrix.h}\n\n@item BoolMatrix\nA boolean matrix class defined in @file{boolMatrix.h}\n@end table\n\nThese are the basic two-dimensional matrix types of Octave.  In addition there\nare a number of multi-dimensional array types including\n\n@table @code\n@item NDArray\nA double precision array class defined in @file{dNDArray.h}\n\n@item ComplexNDarray\nA complex array class defined in @file{CNDArray.h}\n\n@item boolNDArray\nA boolean array class defined in @file{boolNDArray.h}\n\n@item  int8NDArray\n@itemx int16NDArray\n@itemx int32NDArray\n@itemx int64NDArray\n8, 16, 32, and 64-bit signed array classes defined in\n@file{int8NDArray.h}, @file{int16NDArray.h}, etc.\n\n@item  uint8NDArray\n@itemx uint16NDArray\n@itemx uint32NDArray\n@itemx uint64NDArray\n8, 16, 32, and 64-bit unsigned array classes defined in\n@file{uint8NDArray.h}, @file{uint16NDArray.h}, etc.\n@end table\n\nThere are several basic ways of constructing matrices or multi-dimensional\narrays.  Using the class @code{Matrix} as an example one can\n\n@itemize @bullet\n@item\nCreate an empty matrix or array with the empty constructor.  For example:\n\n@example\nMatrix a;\n@end example\n\nThis can be used for all matrix and array types.\n\n@item\nDefine the dimensions of the matrix or array with a dim_vector which has the\nsame characteristics as the vector returned from @code{size}.  For example:\n\n@example\n@group\ndim_vector dv (2, 3);  // 2 rows, 3 columns\nMatrix a (dv);\n@end group\n@end example\n\nThis can be used for all matrix and array types.\n\n@item\nDefine the number of rows and columns in the matrix.  For example:\n\n@example\nMatrix a (2, 2)\n@end example\n\nThis constructor can @strong{only} be used with matrix types.\n@end itemize\n\nThese types all share a number of basic methods and operators.  Many bear a\nresemblance to functions that exist in the interpreter.  A selection of useful\nmethods include\n\n@deftypefn  {Method} {T&} operator () (octave_idx_type)\n@deftypefnx {Method} {T&} elem (octave_idx_type)\nThe @code{()} operator or @code{elem} method allow the values of the matrix or\narray to be read or set.  These methods take a single argument, which is of\ntype @code{octave_idx_type}, that is the index into the matrix or array.\nAdditionally, the matrix type allows two argument versions of the @code{()}\noperator and @code{elem} method, giving the row and column index of the value\nto get or set.\n@end deftypefn\n\nNote that these functions do significant error checking and so in some\ncircumstances the user might prefer to access the data of the array or matrix\ndirectly through the @code{rwdata} method discussed below.\n\n@deftypefn {Method} {octave_idx_type} numel () const\nThe total number of elements in the matrix or array.\n@end deftypefn\n\n@deftypefn {Method} {size_t} byte_size () const\nThe number of bytes used to store the matrix or array.\n@end deftypefn\n\n@deftypefn {Method} {dim_vector} dims () const\nThe dimensions of the matrix or array in value of type @code{dim_vector}.\n@end deftypefn\n\n@deftypefn {Method} {int} ndims () const\nThe number of dimensions of the matrix or array.  Matrices are always 2-D, but\narrays can be N-dimensional.\n@end deftypefn\n\n@deftypefn  {Method} {void} resize (const dim_vector&)\n@deftypefnx {Method} {void} resize (nrows, ncols)\nA method taking either an argument of type @code{dim_vector}, or, in the case\nof a matrix, two arguments of type @code{octave_idx_type} defining the number\nof rows and columns in the matrix.\n@end deftypefn\n\n@deftypefn {Method} {T *} rwdata ()\nThis method returns a pointer to the underlying data of the matrix or array so\nthat it can be manipulated directly, either within Octave or by an external\nlibrary.\n@end deftypefn\n\nOperators such as @code{+}, @code{-}, or @code{*} can be used on the majority\nof the matrix and array types.  In addition there are a number of methods that\nare of interest only for matrices such as @code{transpose}, @code{hermitian},\n@code{solve}, etc.\n\nThe typical way to extract a matrix or array from the input arguments of\n@w{@code{DEFUN_DLD}}@ function is as follows\n\n@example\n@group\n@EXAMPLEFILE(addtwomatrices.cc)\n@end group\n@end example\n\nTo avoid segmentation faults causing Octave to abort, this function explicitly\nchecks that there are sufficient arguments available before accessing these\narguments.  It then obtains two multi-dimensional arrays of type @code{NDArray}\nand adds these together.  Note that the @code{array_value} method is called\nwithout using the @code{is_matrix_type} method.  If an error occurs when\nattempting to extract the value, Octave will print a message and throw an\nexception.  The reason to prefer this coding structure is that the arguments\nmight be a type which is not an @code{NDArray}, but for which it would make\nsense to convert them to one.  The @code{array_value} method allows this\nconversion to be performed transparently when possible.  If you need to catch\nerrors like this, and perform some kind of cleanup or other operation, you can\ncatch the @code{octave_execution_error} exception.\n\n@code{A + B}, operating on two @code{NDArray} objects returns an\n@code{NDArray}, which is cast to an @code{octave_value} on the return from the\nfunction.  An example of the use of this demonstration function is\n\n@example\n@group\naddtwomatrices (ones (2, 2), eye (2, 2))\n      @xresult{}  2  1\n          1  2\n@end group\n@end example\n\nA list of the basic @code{Matrix} and @code{Array} types, the methods to\nextract these from an @code{octave_value}, and the associated header file is\nlisted below.\n\n@multitable @columnfractions .3 .4 .3\n@headitem Type @tab Function @tab Source Code\n@item @code{RowVector} @tab @code{row_vector_value} @tab @file{dRowVector.h}\n@item @code{ComplexRowVector} @tab @code{complex_row_vector_value} @tab @file{CRowVector.h}\n@item @code{ColumnVector} @tab @code{column_vector_value} @tab @file{dColVector.h}\n@item @code{ComplexColumnVector} @tab @code{complex_column_vector_value} @tab @file{CColVector.h}\n@item @code{Matrix} @tab @code{matrix_value} @tab @file{dMatrix.h}\n@item @code{ComplexMatrix} @tab @code{complex_matrix_value} @tab @file{CMatrix.h}\n@item @code{boolMatrix} @tab @code{bool_matrix_value} @tab @file{boolMatrix.h}\n@item @code{charMatrix} @tab @code{char_matrix_value} @tab @file{chMatrix.h}\n@item @code{NDArray} @tab @code{array_value} @tab @file{dNDArray.h}\n@item @code{ComplexNDArray} @tab @code{complex_array_value} @tab @file{CNDArray.h}\n@item @code{boolNDArray} @tab @code{bool_array_value} @tab @file{boolNDArray.h}\n@item @code{charNDArray} @tab @code{char_array_value} @tab @file{charNDArray.h}\n@item @code{int8NDArray} @tab @code{int8_array_value} @tab @file{int8NDArray.h}\n@item @code{int16NDArray} @tab @code{int16_array_value} @tab @file{int16NDArray.h}\n@item @code{int32NDArray} @tab @code{int32_array_value} @tab @file{int32NDArray.h}\n@item @code{int64NDArray} @tab @code{int64_array_value} @tab @file{int64NDArray.h}\n@item @code{uint8NDArray} @tab @code{uint8_array_value} @tab @file{uint8NDArray.h}\n@item @code{uint16NDArray} @tab @code{uint16_array_value} @tab @file{uint16NDArray.h}\n@item @code{uint32NDArray} @tab @code{uint32_array_value} @tab @file{uint32NDArray.h}\n@item @code{uint64NDArray} @tab @code{uint64_array_value} @tab @file{uint64NDArray.h}\n@end multitable\n\n@node Character Strings in Oct-Files\n@subsection Character Strings in Oct-Files\n\nA character string in Octave is just a special @code{Array} class.  Consider\nthe example:\n\n@example\n@EXAMPLEFILE(stringdemo.cc)\n@end example\n\nAn example of the use of this function is\n\n@example\n@group\ns0 = [\"First String\"; \"Second String\"];\n[s1,s2] = stringdemo (s0)\n@xresult{} s1 = Second String\n        First String\n\n@xresult{} s2 = First String\n        Second String\n\ntypeinfo (s2)\n@xresult{} sq_string\ntypeinfo (s1)\n@xresult{} string\n@end group\n@end example\n\nOne additional complication of strings in Octave is the difference between\nsingle quoted and double quoted strings.  To find out if an @code{octave_value}\ncontains a single or double quoted string use one of the predicate tests shown\nbelow.\n\n@example\n@group\nif (args(0).is_sq_string ())\n  octave_stdout << \"First argument is a single quoted string\\n\";\nelse if (args(0).is_dq_string ())\n  octave_stdout << \"First argument is a double quoted string\\n\";\n@end group\n@end example\n\nNote, however, that both types of strings are represented by the\n@code{charNDArray} type, and so when assigning to an @code{octave_value}, the\ntype of string should be specified.  For example:\n\n@example\n@group\noctave_value_list retval;\ncharNDArray ch;\n@dots{}\n// Create single quoted string\nretval(1) = octave_value (ch);   // default constructor is sq_string\n           OR\nretval(1) = octave_value (ch, '\\'');  // explicitly create sq_string\n\n// Create a double quoted string\nretval(0) = octave_value (ch, '\"');\n@end group\n@end example\n\n@node Cell Arrays in Oct-Files\n@subsection Cell Arrays in Oct-Files\n\nOctave's cell type is also available from within oct-files.  A cell array is\njust an @code{Array} of @code{octave_value}s, and thus each element of the cell\narray can be treated like any other @code{octave_value}.  A simple example is\n\n@example\n@EXAMPLEFILE(celldemo.cc)\n@end example\n\nNote that cell arrays are used less often in standard oct-files and so the\n@file{Cell.h} header file must be explicitly included.  The rest of the example\nextracts the @code{octave_value}s one by one from the cell array and returns\nthem as individual output arguments.  For example:\n\n@example\n@group\n[b1, b2, b3] = celldemo (@{1, [1, 2], \"test\"@})\n@xresult{}\nb1 =  1\nb2 =\n\n   1   2\n\nb3 = test\n@end group\n@end example\n\n@node Structures in Oct-Files\n@subsection Structures in Oct-Files\n\nA structure in Octave is a map between a number of fields represented and their\nvalues.  The Standard Template Library @code{map} class is used, with the pair\nconsisting of a @code{std::string} and an Octave @code{Cell} variable.\n\nA simple example demonstrating the use of structures within oct-files is\n\n@example\n@EXAMPLEFILE(structdemo.cc)\n@end example\n\nAn example of its use is\n\n@example\n@group\nx.a = 1; x.b = \"test\"; x.c = [1, 2];\nstructdemo (x, \"b\")\n@xresult{} selected = test\n@end group\n@end example\n\nThe example above specifically uses the @code{octave_scalar_map} class which is\nfor representing a single struct.  For structure arrays, the @code{octave_map}\nclass is used instead.  The commented code shows how the demo could be modified\nto handle a structure array.  In that case, the @code{contents} method returns\na @code{Cell} which may have more than one element.  Therefore, to obtain the\nunderlying @code{octave_value} in the single struct example we would write\n\n@example\noctave_value tmp = arg0.contents (arg1)(0);\n@end example\n\n@noindent\nwhere the trailing @code{(0)} is the @code{()} operator on the @code{Cell}\nobject.  If this were a true structure array with multiple elements we could\niterate over the elements using the @code{()} operator.\n\nStructures are a relatively complex data container and there are more functions\navailable in @file{oct-map.h} which make coding with them easier than relying\non just @code{contents}.\n\n@node Sparse Matrices in Oct-Files\n@subsection Sparse Matrices in Oct-Files\n\nThere are three classes of sparse objects that are of interest to the user.\n\n@table @code\n@item SparseMatrix\nA double precision sparse matrix class\n\n@item SparseComplexMatrix\nA complex sparse matrix class\n\n@item SparseBoolMatrix\nA boolean sparse matrix class\n@end table\n\nAll of these classes inherit from the @code{Sparse<T>} template class, and so\nall have similar capabilities and usage.  The @code{Sparse<T>} class was based\non Octave's @code{Array<T>} class and users familiar with Octave's\n@code{Array} classes will be comfortable with the use of the sparse classes.\n\nThe sparse classes will not be entirely described in this section, due to their\nsimilarity with the existing @code{Array} classes.  However, there are a few\ndifferences due the nature of sparse objects, and these will be described.\nFirst, although it is fundamentally possible to have N-dimensional sparse\nobjects, the Octave sparse classes do not allow them at this time; All\ninstances of the sparse classes @strong{must} be 2-dimensional.  This means\nthat @code{SparseMatrix} is actually more similar to Octave's @code{Matrix}\nclass than it is to the @code{NDArray} class.\n\n@menu\n* Array and Sparse Class Differences::\n* Creating Sparse Matrices in Oct-Files::\n* Using Sparse Matrices in Oct-Files::\n@end menu\n\n@node Array and Sparse Class Differences\n@subsubsection Array and Sparse Class Differences\n\nThe number of elements in a sparse matrix is considered to be the number\nof nonzero elements, rather than the product of the dimensions.  Therefore,\n\n@example\n@group\nSparseMatrix sm;\n@dots{}\nint nnz = sm.nelem ();\n@end group\n@end example\n\n@noindent\nreturns the number of nonzero elements (like the interpreter function\n@code{nnz}).  If the user really requires the number of elements in the matrix,\nincluding the nonzero elements, they should use @code{numel} rather than\n@code{nelem}.  Note that for very large matrices, where the product of the two\ndimensions is larger than the representation of an unsigned int, @code{numel}\ncan overflow.  An example is @code{speye (1e6)} which will create a matrix with\na million rows and columns, but only a million nonzero elements.  In this case,\nthe number of rows multiplied by the number of columns is more than two hundred\ntimes the maximum value that can be represented by an unsigned 32-bit int.  The\nuse of @code{numel} should, therefore, be avoided unless it is known that it\nwill not overflow.\n\nExtreme care is also required when using the @code{elem} method or the\n@code{()} operator which perform essentially the same function.  The reason is\nthat if a sparse object is non-const, then Octave will assume that a request\nfor a zero element in a sparse matrix is in fact a request to create this\nelement so it can be filled.  Therefore, a piece of code like\n\n@example\n@group\nSparseMatrix sm;\n@dots{}\nfor (int j = 0; j < nc; j++)\n  for (int i = 0; i < nr; i++)\n    std::cerr << \" (\" << i << \",\" << j << \"): \" << sm(i,j) << \"\\n\";\n@end group\n@end example\n\n@noindent\nis a great way of turning a sparse matrix into a dense one, and a very slow\nway at that since it reallocates the sparse object for each zero element in the\nmatrix.\n\nA simple way of preventing the above from happening is to create a temporary\nconstant version of the sparse matrix.  Note that only the container for the\nsparse matrix will be copied, while the actual representation of the data will\nbe shared between the two versions of the sparse matrix; This is not a costly\noperation.  The example above, re-written to prevent sparse-to-dense\nconversion, is\n\n@example\n@group\nSparseMatrix sm;\n@dots{}\nconst SparseMatrix tmp (sm);\nfor (int j = 0; j < nc; j++)\n  for (int i = 0; i < nr; i++)\n    std::cerr << \" (\" << i << \",\" << j << \"): \" << tmp(i,j) << \"\\n\";\n@end group\n@end example\n\nFinally, because the sparse types aren't represented by a contiguous block of\nmemory, the @nospell{@code{rwdata}} method of @code{Array<T>} is not\navailable.  It is, however, replaced by three separate methods @code{ridx},\n@code{cidx}, and @code{data}, that access the raw compressed column format that\nOctave sparse matrices are stored in.  These methods can be used in a manner\nsimilar to @code{elem} to allow the matrix to be accessed or filled.  However,\nit is up to the user to respect the sparse matrix compressed column format or\nthe matrix will become corrupted.\n\n@node Creating Sparse Matrices in Oct-Files\n@subsubsection Creating Sparse Matrices in Oct-Files\n\nThere are two useful strategies for creating a sparse matrix.  The first is to\ncreate three vectors representing the row index, column index, and data values,\nand from these create the matrix.  The second alternative is to create a sparse\nmatrix with the appropriate amount of space, and then fill in the values.  Both\ntechniques have their advantages and disadvantages.\n\nBelow is an example of creating a small sparse matrix using the first technique\n\n@example\n@group\nint nz, nr, nc;\nnz = 4, nr = 3, nc = 4;\n\nColumnVector ridx (nz);\nColumnVector cidx (nz);\nColumnVector data (nz);\n\nridx(0) = 1; cidx(0) = 1; data(0) = 1;\nridx(1) = 2; cidx(1) = 2; data(1) = 2;\nridx(2) = 2; cidx(2) = 4; data(2) = 3;\nridx(3) = 3; cidx(3) = 4; data(3) = 4;\nSparseMatrix sm (data, ridx, cidx, nr, nc);\n@end group\n@end example\n\n@noindent\nwhich creates the matrix given in section @ref{Storage of Sparse Matrices}.\nNote that the compressed matrix format is not used at the time of the creation\nof the matrix itself, but is used internally.\n\nAs discussed in the chapter on Sparse Matrices, the values of the sparse matrix\nare stored in increasing column-major ordering.  Although the data passed by\nthe user need not respect this requirement, pre-sorting the data will\nsignificantly speed up creation of the sparse matrix.\n\nThe disadvantage of this technique for creating a sparse matrix is that there\nis a brief time when two copies of the data exist.  For extremely memory\nconstrained problems this may not be the best technique for creating a sparse\nmatrix.\n\nThe alternative is to first create a sparse matrix with the desired number of\nnonzero elements and then later fill those elements in.  Sample code:\n\n@example\n@group\nint nz, nr, nc;\nnz = 4, nr = 3, nc = 4;\nSparseMatrix sm (nr, nc, nz);\nsm(0,0) = 1; sm(0,1) = 2; sm(1,3) = 3; sm(2,3) = 4;\n@end group\n@end example\n\nThis creates the same matrix as previously.  Again, although not strictly\nnecessary, it is significantly faster if the sparse matrix is created and the\nelements are added in column-major ordering.  The reason for this is that when\nelements are inserted at the end of the current list of known elements then no\nelement in the matrix needs to be moved to allow the new element to be\ninserted; Only the column indices need to be updated.\n\nThere are a few further points to note about this method of creating a sparse\nmatrix.  First, it is possible to create a sparse matrix with fewer elements\nthan are actually inserted in the matrix.  Therefore,\n\n@example\n@group\nint nr, nc;\nnr = 3, nc = 4;\nSparseMatrix sm (nr, nc, 0);\nsm(0,0) = 1; sm(0,1) = 2; sm(1,3) = 3; sm(2,3) = 4;\n@end group\n@end example\n\n@noindent\nis perfectly valid.  However, it is a very bad idea because as each new element\nis added to the sparse matrix the matrix needs to request more space and\nreallocate memory.  This is an expensive operation that will significantly slow\nthis means of creating a sparse matrix.  It is possible to create a sparse\nmatrix with excess storage, so having @var{nz} greater than 4 in this example\nis also valid.  The disadvantage is that the matrix occupies more memory than\nstrictly needed.\n\nOf course, it is not always possible to know the number of nonzero elements\nprior to filling a matrix.  For this reason the additional unused storage of a\nsparse matrix can be removed after its creation with the @code{maybe_compress}\nfunction.  In addition to deallocating unused storage, @code{maybe_compress}\ncan also remove zero elements from the matrix.  The removal of zero elements\nfrom the matrix is controlled by setting the argument of the\n@code{maybe_compress} function to be @code{true}.  However, the cost of\nremoving the zeros is high because it implies re-sorting the elements.  If\npossible, it is better for the user to avoid adding the unnecessary zeros in\nthe first place.  An example of the use of @code{maybe_compress} is\n\n@example\n@group\nint nz, nr, nc;\nnz = 6, nr = 3, nc = 4;\n\nSparseMatrix sm1 (nr, nc, nz);\nsm1(0,0) = 1; sm1(0,1) = 2; sm1(1,3) = 3; sm1(2,3) = 4;\nsm1.maybe_compress ();   // No zero elements were added\n\nSparseMatrix sm2 (nr, nc, nz);\nsm2(0,0) = 1; sm2(0,1) = 2; sm(0,2) = 0; sm(1,2) = 0;\nsm1(1,3) = 3; sm1(2,3) = 4;\nsm2.maybe_compress (true);  // Zero elements were added\n@end group\n@end example\n\nThe use of the @code{maybe_compress} function should be avoided if possible as\nit will slow the creation of the matrix.\n\nA third means of creating a sparse matrix is to work directly with the data in\ncompressed row format.  An example of this advanced technique might be\n\n@example\noctave_value arg;\n@dots{}\nint nz, nr, nc;\nnz = 6, nr = 3, nc = 4;   // Assume we know the max # nz\nSparseMatrix sm (nr, nc, nz);\nMatrix m = arg.matrix_value ();\n\nint ii = 0;\nsm.cidx (0) = 0;\nfor (int j = 1; j < nc; j++)\n  @{\n    for (int i = 0; i < nr; i++)\n      @{\n        double tmp = m(i,j);\n        if (tmp != 0.)\n          @{\n            sm.data(ii) = tmp;\n            sm.ridx(ii) = i;\n            ii++;\n          @}\n      @}\n    sm.cidx(j+1) = ii;\n @}\nsm.maybe_compress ();  // If don't know a priori the final # of nz.\n@end example\n\n@noindent\nwhich is probably the most efficient means of creating a sparse matrix.\n\nFinally, it may sometimes arise that the amount of storage initially created is\ninsufficient to completely store the sparse matrix.  Therefore, the method\n@code{change_capacity} exists to reallocate the sparse memory.  The above\nexample would then be modified as\n\n@example\noctave_value arg;\n@dots{}\nint nz, nr, nc;\nnz = 6, nr = 3, nc = 4;   // Guess the number of nz elements\nSparseMatrix sm (nr, nc, nz);\nMatrix m = arg.matrix_value ();\n\nint ii = 0;\nsm.cidx (0) = 0;\nfor (int j = 1; j < nc; j++)\n  @{\n    for (int i = 0; i < nr; i++)\n      @{\n        double tmp = m(i,j);\n        if (tmp != 0.)\n          @{\n            if (ii == nz)\n              @{\n                nz += 2;   // Add 2 more elements\n                sm.change_capacity (nz);\n              @}\n            sm.data(ii) = tmp;\n            sm.ridx(ii) = i;\n            ii++;\n          @}\n      @}\n    sm.cidx(j+1) = ii;\n @}\nsm.maybe_compress ();  // If don't know a priori the final # of nz.\n@end example\n\nNote that both increasing and decreasing the number of nonzero elements in a\nsparse matrix is expensive as it involves memory reallocation.  Also because\nparts of the matrix, though not its entirety, exist as old and new copies at\nthe same time, additional memory is needed.  Therefore, if possible avoid\nchanging capacity.\n\n@node Using Sparse Matrices in Oct-Files\n@subsubsection Using Sparse Matrices in Oct-Files\n\nMost of the same operators and functions for sparse matrices that are available\nfrom the Octave interpreter are also available within oct-files.  The basic\nmeans of extracting a sparse matrix from an @code{octave_value}, and returning\nit as an @code{octave_value}, can be seen in the following example.\n\n@example\n@group\noctave_value_list retval;\n\nSparseMatrix sm = args(0).sparse_matrix_value ();\nSparseComplexMatrix scm = args(1).sparse_complex_matrix_value ();\nSparseBoolMatrix sbm = args(2).sparse_bool_matrix_value ();\n@dots{}\nretval(2) = sbm;\nretval(1) = scm;\nretval(0) = sm;\n@end group\n@end example\n\nThe conversion to an @code{octave_value} is handled by the sparse\n@code{octave_value} constructors, and so no special care is needed.\n\n@node Accessing Global Variables in Oct-Files\n@subsection Accessing Global Variables in Oct-Files\n\nGlobal variables allow variables in the global scope to be accessed.  Global\nvariables can be accessed within oct-files by using the support functions\n@w{@code{global_varval}}@ and @w{@code{global_assign}}@ from the current\ninterpreter's symbol table.  Both functions take as first argument a string\nrepresenting the variable name to be obtained or assigned.  The second\nargument of @w{@code{global_assign}}@ is the value to be assigned.  An\nexample of the use of these two functions is\n\n@example\n@EXAMPLEFILE(globaldemo.cc)\n@end example\n\nAn example of its use is\n\n@example\n@group\nglobal a b\nb = 10;\nglobaldemo (\"b\")\n@xresult{} 10\nglobaldemo (\"c\")\n@xresult{} \"Global variable not found\"\nnum2str (a)\n@xresult{} 42\n@end group\n@end example\n\n@node Calling Octave Functions from Oct-Files\n@subsection Calling Octave Functions from Oct-Files\n\nThere is often a need to be able to call another Octave function from within an\noct-file, and there are many examples of such within Octave itself.  For\nexample, the @code{quad} function is an oct-file that calculates the definite\nintegral by quadrature over a user-supplied function.\n\nThere are also many ways in which a function could be given as input.  It might\nbe passed as one of\n\n@enumerate 1\n@item Function Handle\n\n@item Anonymous Function Handle\n\n@item String\n@end enumerate\n\nThe code below demonstrates all four methods of passing a function to an\noct-file.\n\n@example\n@EXAMPLEFILE(funcdemo.cc)\n@end example\n\nThe first input to the demonstration code is a user-supplied function and the\nremaining arguments are all passed to the function.\n\n@example\n@group\nfuncdemo (@@sin, 1)\n@xresult{} 0.84147\nfuncdemo (@@(x) sin (x), 1)\n@xresult{} 0.84147\nfuncdemo (\"sin\", 1)\n@xresult{} 0.84147\nfuncdemo (@@atan2, 1, 1)\n@xresult{} 0.78540\n@end group\n@end example\n\nWhen the user function is passed as a string the treatment of the function is\ndifferent.  In some cases it is necessary to have the user supplied function as\nan @code{octave_function} object.  In that case the string argument can be used\nto create a temporary function as demonstrated below.\n\n@example\n@group\nstd::octave fcn_name = unique_symbol_name (\"__fcn__\");\nstd::string fcode = \"function y = \";\nfcode.append (fcn_name);\nfcode.append (\"(x) y = \");\nfcn = extract_function (args(0), \"funcdemo\", fcn_name,\n                        fcode, \"; endfunction\");\n@dots{}\nif (fcn_name.length ())\n  clear_function (fcn_name);\n@end group\n@end example\n\nThere are two important things to know in this case.  First, the number of\ninput arguments to the user function is fixed, and in the above example is a\nsingle argument.  Second, to avoid leaving the temporary function in the Octave\nsymbol table it should be cleared after use.  Also, by convention all internal\nfunction names begin and end with the character sequence @samp{__}.\n\n@node Calling External Code from Oct-Files\n@subsection Calling External Code from Oct-Files\n\nLinking external C code to Octave is relatively simple, as the C functions can\neasily be called directly from C++.  One possible issue is that the\ndeclarations of the external C functions may need to be explicitly defined as C\nfunctions to the compiler.  If the declarations of the external C functions are\nin the header @file{foo.h}, then the tactic to ensure that the C++ compiler\ntreats these declarations as C code is\n\n@example\n@group\n#ifdef __cplusplus\nextern \"C\"\n@{\n#endif\n#include \"foo.h\"\n#ifdef __cplusplus\n@}  /* end extern \"C\" */\n#endif\n@end group\n@end example\n\nWhen calling functions that are implemented in Fortran code, some peculiarities\nhave to be taken into account.  Symbol names in Fortran are case-insensitive,\nand depending on the used Fortran compiler, function names are either exported\nwith all lowercase or with all uppercase characters.  Additionally, some\ncompilers append none, one or two underscores \"@code{_}\" at the end of\nexported function names.  This is called \"name-mangling\".\n\nOctave supplies macros that allow writing code that automatically handles the\nname-mangling for a number of different Fortran compilers.  These macros are\n@w{@env{F77_FUNC}} and @w{@env{F77_FUNC_}}.  The former should be used for\nFortran functions that do not contain any underscores in their name.  The\nlatter should be used for Fortran functions with underscores in their names.\nBoth macros take two arguments: The first is the Fortran function name in all\nlowercase characters.  The second is the same Fortran function name in all\nuppercase characters.\n\nAdditionally to the name-mangling, different compilers are using different\ncalling conventions for some types.  Octave defines the following preprocessor\nmacros to allow writing code that can be used with different Fortran calling\nconventions.\n\nNote that we don't attempt to handle Fortran functions, we always use\nsubroutine wrappers for them and pass the return value as an extra argument.\n\nUse the following macros to pass character strings from C to Fortran:\n\n@example\n@group\n  F77_CHAR_ARG(x)\n  F77_CONST_CHAR_ARG(x)\n  F77_CXX_STRING_ARG(x)\n  F77_CHAR_ARG_LEN(l)\n  F77_CHAR_ARG_DECL\n  F77_CONST_CHAR_ARG_DECL\n  F77_CHAR_ARG_LEN_DECL\n@end group\n@end example\n\nUse the following macros to write C-language functions that accept\nFortran-style character strings:\n\n@example\n@group\n  F77_CHAR_ARG_DEF(s, len)\n  F77_CONST_CHAR_ARG_DEF(s, len)\n  F77_CHAR_ARG_LEN_DEF(len)\n  F77_CHAR_ARG_USE(s)\n  F77_CHAR_ARG_LEN_USE(s, len)\n@end group\n@end example\n\nUse the following macros for Fortran types in C++ code:\n\n@table @code\n@item F77_INT4\nEquivalent to Fortran @code{INTEGER*4} type\n\n@item F77_DBLE\nEquivalent to Fortran @code{DOUBLE PRECISION} type\n\n@item F77_REAL\nEquivalent to Fortran @code{REAL} type\n\n@item F77_CMPLX\nEquivalent to Fortran @code{COMPLEX} type\n\n@item F77_DBLE_CMPLX\nEquivalent to Fortran @code{DOUBLE COMPLEX} type\n\n@item F77_LOGICAL\nEquivalent to Fortran @code{LOGICAL} type\n\n@item F77_RET_T\nReturn type of a C++ function that acts like a Fortran subroutine.\n@end table\n\nUse the following macros to return from C-language functions that are supposed\nto act like Fortran subroutines.  @w{@env{F77_NORETURN}} is intended to be used\nas the last statement of such a function that has been tagged with a\n@nospell{@qcode{\"noreturn\"}} attribute.\n\n@example\n@group\n  F77_RETURN(retval)\n  F77_NORETURN(retval)\n@end group\n@end example\n\nThe underlying Fortran code should use the @code{XSTOPX} function to replace\nthe Fortran @code{STOP} function.  @code{XSTOPX} uses the Octave exception\nhandler to treat failing cases in the Fortran code explicitly.  Note that\nOctave supplies its own replacement @sc{blas} @code{XERBLA} function, which\nuses @code{XSTOPX}.\n\nThe following example shows the inclusion of a Fortran function in an oct-file,\nwhere the C++ wrapper is\n\n@example\n@EXAMPLEFILE(fortrandemo.cc)\n@end example\n\n@noindent\nand the Fortran function is\n\n@example\n@EXAMPLEFILE(fortransub.f)\n@end example\n\nThis example demonstrates most of the features needed to link to an external\nFortran function, including passing arrays and strings, as well as exception\nhandling.  Both the Fortran and C++ files need to be compiled in order for the\nexample to work.\n\n@example\n@group\nmkoctfile fortrandemo.cc fortransub.f\n[b, s] = fortrandemo (1:3)\n@xresult{}\n  b = 1.00000   0.50000   0.33333\n  s = There are   3 values in the input vector\n[b, s] = fortrandemo (0:3)\nerror: fortrandemo: fortransub: divide by zero\n@end group\n@end example\n\n@node Allocating Local Memory in Oct-Files\n@subsection Allocating Local Memory in Oct-Files\n\nAllocating memory within an oct-file might seem easy, as the C++ new/delete\noperators can be used.  However, in that case great care must be taken to avoid\nmemory leaks.  The preferred manner in which to allocate memory for use locally\nis to use the @w{@code{OCTAVE_LOCAL_BUFFER}}@ macro.  An example of its use is\n\n@example\nOCTAVE_LOCAL_BUFFER (double, tmp, len)\n@end example\n\n@noindent\nthat returns a pointer @code{tmp} of type @code{double *} of length @code{len}.\n\nIn this case, Octave itself will worry about reference counting and variable\nscope and will properly free memory without programmer intervention.\n\n@node Input Parameter Checking in Oct-Files\n@subsection Input Parameter Checking in Oct-Files\n\nBecause oct-files are compiled functions they open up the possibility of\ncrashing Octave through careless function calls or memory faults.  It is quite\nimportant that each and every function have a sufficient level of parameter\nchecking to ensure that Octave behaves well.\n\nThe minimum requirement, as previously discussed, is to check the number of\ninput arguments before using them to avoid referencing a nonexistent argument.\nHowever, in some cases this might not be sufficient as the underlying code\nimposes further constraints.  For example, an external function call might be\nundefined if the input arguments are not integers, or if one of the arguments\nis zero, or if the input is complex and a real value was expected.  Therefore,\noct-files often need additional input parameter checking.\n\nThere are several functions within Octave that can be useful for the purposes\nof parameter checking.  These include the methods of the @code{octave_value}\nclass like @code{is_real_matrix}, @code{is_numeric_type}, etc.@: (see\n@file{ov.h}).  Often, with a knowledge of the Octave m-file language, you can\nguess at what the corresponding C++ routine will.  In addition there are some\nmore specialized input validation functions of which a few are demonstrated\nbelow.\n\n@example\n@EXAMPLEFILE(paramdemo.cc)\n@end example\n\n@noindent\nAn example of its use is:\n\n@example\n@group\nparamdemo ([1, 2, NaN, Inf])\n@xresult{} Properties of input array:\n     includes Inf or NaN values\n     includes other values than 1 and 0\n     includes only int, Inf or NaN values\n@end group\n@end example\n\n@node Exception and Error Handling in Oct-Files\n@subsection Exception and Error Handling in Oct-Files\n\nAnother important feature of Octave is its ability to react to the user typing\n@key{Control-C} during extended calculations.  This ability is based on the C++\nexception handler, where memory allocated by the C++ new/delete methods is\nautomatically released when the exception is treated.  When writing an oct-file\nwhich may run for a long time the programmer must periodically use the macro\n@w{@code{OCTAVE_QUIT}}, in order to allow Octave to check and possibly respond\nto a user typing @key{Control-C}.  For example:\n\n@example\n@group\nfor (octave_idx_type i = 0; i < a.nelem (); i++)\n  @{\n    OCTAVE_QUIT;\n    b.elem (i) = 2. * a.elem (i);\n  @}\n@end group\n@end example\n\nThe presence of the @w{@code{OCTAVE_QUIT}}@ macro in the inner loop allows\nOctave to detect and acknowledge a @key{Control-C} key sequence.  Without this\nmacro, the user must either wait for the oct-file function to return before the\ninterrupt is processed, or the user must press @key{Control-C} three times\nwhich will force Octave to exit completely.\n\nThe @w{@code{OCTAVE_QUIT}}@ macro does impose a very small performance penalty;\nFor loops that are known to be small it may not make sense to include\n@w{@code{OCTAVE_QUIT}}.\n\nWhen creating an oct-file that uses an external library, the function might\nspend a significant portion of its time in the external library.  It is not\ngenerally possible to use the @w{@code{OCTAVE_QUIT}}@ macro in this case.  The\nalternative code in this case is\n\n@example\n@group\nBEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;\n@dots{} some code that calls a \"foreign\" function @dots{}\nEND_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;\n@end group\n@end example\n\nThe disadvantage of this is that if the foreign code allocates any memory\ninternally, then this memory might be lost during an interrupt, without being\ndeallocated.  Therefore, ideally Octave itself should allocate any memory that\nis needed by the foreign code, with either the @nospell{@code{rwdata}}\nmethod or the @w{@code{OCTAVE_LOCAL_BUFFER}}@ macro.\n\nThe Octave @code{unwind_protect} mechanism\n(@pxref{The unwind_protect Statement}) can also be used in oct-files.  In\nconjunction with the exception handling of Octave, it ensures that certain\nrecovery code is always run even if an exception occurs.  An example of the use\nof this mechanism is\n\n@example\n@EXAMPLEFILE(unwinddemo.cc)\n@end example\n\nAs can be seen in the example:\n\n@example\n@group\nunwinddemo (1, 0)\n@xresult{} Inf\n1 / 0\n@xresult{} warning: division by zero\n   Inf\n@end group\n@end example\n\nThe warning for division by zero (and in fact all warnings) are disabled in the\n@code{unwinddemo} function.\n\n@node Documentation and Testing of Oct-Files\n@subsection Documentation and Testing of Oct-Files\n\nThe documentation for an oct-file is contained in the fourth string parameter\nof the @w{@code{DEFUN_DLD}}@ macro.  This string can be formatted in the same\nmanner as the help strings for user functions, however there are some issues\nthat are particular to the formatting of help strings within oct-files.\n\nThe major issue is that the help string will typically be longer than a single\nline of text, and so the formatting of long multi-line help strings needs to be\ntaken into account.  There are several possible solutions, but the most common\nis illustrated in the following example,\n\n@example\n@group\nDEFUN_DLD (do_what_i_want, args, nargout,\n  \"-*- texinfo -*-\\n\\\n@@deftypefn @{@} @{@} do_what_i_say (@@var@{n@})\\n\\\nA function that does what the user actually wants rather\\n\\\nthan what they requested.\\n\\\n@@end deftypefn\")\n@{\n@dots{}\n@}\n@end group\n@end example\n\n@noindent\nwhere each line of text is terminated by @code{\\n\\} which is an embedded\nnewline in the string together with a C++ string continuation character.  Note\nthat the final @code{\\} must be the last character on the line.\n\nOctave also includes the ability to embed test and demonstration code for a\nfunction within the code itself (@pxref{Test and Demo Functions}).  This can be\nused from within oct-files (or in fact any file) with certain provisos.  First,\nthe test and demo functions of Octave look for @code{%!} as the first two\ncharacters of a line to identify test and demonstration code.  This is a\nrequirement for oct-files as well.  In addition, the test and demonstration\ncode must be wrapped in a comment block to avoid it being interpreted by the\ncompiler.  Finally, the Octave test and demonstration code must have access to\nthe original source code of the oct-file---not just the compiled code---as the\ntests are stripped from the compiled code.  An example in an oct-file might be\n\n@example\n@group\n/*\n%!assert (sin ([1,2]), [sin(1),sin(2)])\n%!error (sin ())\n%!error (sin (1,1))\n*/\n@end group\n@end example\n\n@c @node Application Programming Interface for Oct-Files\n@c @subsection Application Programming Interface for Oct-Files\n@c\n@c WRITE ME, using Coda section 1.3 as a starting point.\n\n@node Mex-Files\n@section Mex-Files\n@cindex mex-files\n@cindex mex\n\nOctave includes an interface to allow legacy mex-files to be compiled and used\nwith Octave.  This interface can also be used to share compiled code between\nOctave and @sc{matlab} users.  However, as mex-files expose @sc{matlab}'s\ninternal API, and the internal structure of Octave is different, a mex-file can\nnever have the same performance in Octave as the equivalent oct-file.  In\nparticular, to support the manner in which variables are passed to mex\nfunctions there are a significant number of additional copies of memory blocks\nwhen invoking or returning from a mex-file function.  For this reason, it is\nrecommended that any new code be written with the oct-file interface previously\ndiscussed.\n\n@menu\n* Getting Started with Mex-Files::\n* Working with Matrices and Arrays in Mex-Files::\n* Character Strings in Mex-Files::\n* Cell Arrays with Mex-Files::\n* Structures with Mex-Files::\n* Sparse Matrices with Mex-Files::\n* Calling Other Functions in Mex-Files::\n@c * Application Programming Interface for Mex-Files::\n@end menu\n\n@node Getting Started with Mex-Files\n@subsection Getting Started with Mex-Files\n\nThe basic command to build a mex-file is either @code{mkoctfile --mex} or\n@code{mex}.  The first command can be used either from within Octave or from\nthe command line.  To avoid issues with @sc{matlab}'s own @code{mex} command,\nthe use of the command @code{mex} is limited to within Octave.  Compiled\nmex-files have the extension @file{.mex}.\n\n@DOCSTRING(mex)\n\n@DOCSTRING(mexext)\n\nConsider the following short example:\n\n@example\n@group\n@EXAMPLEFILE(mex_hellodemo.c)\n@end group\n@end example\n\nThe first line @code{#include \"mex.h\"} makes available all of the definitions\nnecessary for a mex-file.  One important difference between Octave and\n@sc{matlab} is that the header file @qcode{\"matrix.h\"} is implicitly included\nthrough the inclusion of @qcode{\"mex.h\"}.  This is necessary to avoid a\nconflict with the Octave file @qcode{\"Matrix.h\"} for operating systems and\ncompilers that don't distinguish between filenames in uppercase and lowercase.\n\nThe entry point into the mex-file is defined by @code{mexFunction}.  The\nfunction takes four arguments:\n\n@enumerate 1\n@item The number of return arguments (# of left-hand side args).\n\n@item An array of pointers to return arguments.\n\n@item The number of input arguments (# of right-hand side args).\n\n@item An array of pointers to input arguments.\n@end enumerate\n\nNote that the function name definition is not explicitly included in\n@code{mexFunction} and so there can only be a single @code{mexFunction} entry\npoint per file.  Instead, the name of the function as seen in Octave is\ndetermined by the name of the mex-file itself minus the extension.  If the\nabove function is in the file @file{mex_hellodemo.c}, it can be compiled with\n\n@example\nmkoctfile --mex mex_hellodemo.c\n@end example\n\n@noindent\nwhich creates a file @file{mex_hellodemo.mex}.  The function can then be run\nfrom Octave as\n\n@example\n@group\nmex_hellodemo (1,2,3)\n@xresult{} Hello, World!\n@xresult{} I have 3 inputs and 0 outputs\n@end group\n@end example\n\nIt should be noted that the mex-file contains no help string.  To document\nmex-files, there should exist an m-file in the same directory as the mex-file\nitself.  Taking the above as an example, there would need to be a file\n@file{mex_hellodemo.m} which might contain the text\n\n@example\n%MYHELLO Simple test of the functionality of a mex-file.\n@end example\n\nIn this case, the function that will be executed within Octave will be given by\nthe mex-file, while the help string will come from the m-file.  This can also\nbe useful to allow a sample implementation of the mex-file within the Octave\nlanguage itself for testing purposes.\n\nAlthough there cannot be multiple entry points in a single mex-file, one can\nuse the @code{mexFunctionName} function to determine what name the mex-file was\ncalled with.  This can be used to alter the behavior of the mex-file based on\nthe function name.  For example, if\n\n@example\n@group\n@EXAMPLEFILE(mex_funcdemo.c)\n@end group\n@end example\n\n@noindent\nis in the file @file{mex_funcdemo.c}, and is compiled with\n\n@example\n@group\nmkoctfile --mex mex_funcdemo.c\nln -s mex_funcdemo.mex mexfunc.mex\n@end group\n@end example\n\n@noindent\nthen as can be seen by\n\n@example\n@group\nmex_funcdemo ()\n@xresult{} You called function: mex_funcdemo\n    This is the principal function\nmexfunc ()\n@xresult{} You called function: mexfunc\n@end group\n@end example\n\n@noindent\nthe behavior of the mex-file can be altered depending on the function's name.\n\nAlthough the user should only include @file{mex.h} in their code, Octave\ndeclares additional functions, typedefs, etc., available to the user to write\nmex-files in the headers @file{mexproto.h} and @file{mxarray.h}.\n\n@node Working with Matrices and Arrays in Mex-Files\n@subsection Working with Matrices and Arrays in Mex-Files\n\nThe basic mex type of all variables is @code{mxArray}.  Any object, such as a\nmatrix, cell array, or structure, is stored in this basic type.  @code{mxArray}\nserves essentially the same purpose as the @code{octave_value} class in\noct-files in that it acts as a container for all the more specialized types.\n\nThe @code{mxArray} structure contains at a minimum, the name of the variable it\nrepresents, its dimensions, its type, and whether the variable is real or\ncomplex.  It can also contain a number of additional fields depending on the\ntype of the @code{mxArray}.  There are a number of functions to create\n@code{mxArray} structures, including @code{mxCreateDoubleMatrix},\n@code{mxCreateCellArray}, @code{mxCreateSparse}, and the generic\n@code{mxCreateNumericArray}.\n\nThe basic function to access the data in an array is @code{mxGetPr}.  Because\nthe mex interface assumes that real and imaginary parts of a complex array are\nstored separately, there is an equivalent function @code{mxGetPi} that gets the\nimaginary part.  Both of these functions are only for use with double precision\nmatrices.  The generic functions @code{mxGetData} and @code{mxGetImagData}\nperform the same operation for all matrix types.  For example:\n\n@example\n@group\nmxArray *m;\nmwSize *dims;\nUINT32_T *pr;\n\ndims = (mwSize *) mxMalloc (2 * sizeof (mwSize));\ndims[0] = 2; dims[1] = 2;\nm = mxCreateNumericArray (2, dims, mxUINT32_CLASS, mxREAL);\npr = (UINT32_T *) mxGetData (m);\n@end group\n@end example\n\nThere are also the functions @code{mxSetPr}, etc., that perform the inverse,\nand set the data of an array to use the block of memory pointed to by the\nargument of @code{mxSetPr}.\n\nNote the type @code{mwSize} used above, and also @code{mwIndex}, are defined as\nthe native precision of the indexing in Octave on the platform on which the\nmex-file is built.  This allows both 32- and 64-bit platforms to support\nmex-files.  @code{mwSize} is used to define array dimensions and the maximum\nnumber or elements, while @code{mwIndex} is used to define indexing into\narrays.\n\nAn example that demonstrates how to work with arbitrary real or complex double\nprecision arrays is given by the file @file{mex_pow2demo.c} shown below.\n\n@example\n@EXAMPLEFILE(mex_pow2demo.c)\n@end example\n\n@noindent\nAn example of its use is\n\n@example\n@group\nb = randn (4,1) + 1i * randn (4,1);\nall (b.^2 == mex_pow2demo (b))\n@xresult{} 1\n@end group\n@end example\n\nThe example above uses the functions @code{mxGetDimensions},\n@code{mxGetNumberOfElements}, and @code{mxGetNumberOfDimensions} to work with\nthe dimensions of multi-dimensional arrays.  The functions @code{mxGetM}, and\n@code{mxGetN} are also available to find the number of rows and columns in a\n2-D matrix (@nospell{MxN} matrix).\n\n@node Character Strings in Mex-Files\n@subsection Character Strings in Mex-Files\n\nAs mex-files do not make the distinction between single and double quoted\nstrings that Octave does, there is perhaps less complexity in the use of\nstrings and character matrices.  An example of their use that parallels the\ndemo in @file{stringdemo.cc} is given in the file @file{mex_stringdemo.c}, as\nshown below.\n\n@smallexample\n@EXAMPLEFILE(mex_stringdemo.c)\n@end smallexample\n\n@noindent\nAn example of its expected output is\n\n@example\n@group\nmex_stringdemo ([\"First String\"; \"Second String\"])\n@xresult{} Second String\n   First String\n@end group\n@end example\n\nOther functions in the mex interface for handling character strings are\n@code{mxCreateString}, @code{mxArrayToString}, and\n@code{mxCreateCharMatrixFromStrings}.  In a mex-file, a character string is\nconsidered to be a vector rather than a matrix.  This is perhaps an arbitrary\ndistinction as the data in the @code{mxArray} for the matrix is consecutive in\nany case.\n\n@node Cell Arrays with Mex-Files\n@subsection Cell Arrays with Mex-Files\n\nOne can perform exactly the same operations on Cell arrays in mex-files as in\noct-files.  An example that duplicates the function of the @file{celldemo.cc}\noct-file in a mex-file is given by @file{mex_celldemo.c} as shown below.\n\n@example\n@EXAMPLEFILE(mex_celldemo.c)\n@end example\n\n@noindent\nThe output is identical to the oct-file version as well.\n\n@example\n@group\n[b1, b2, b3] = mex_celldemo (@{1, [1, 2], \"test\"@})\n@xresult{}\nb1 =  1\nb2 =\n\n   1   2\n\nb3 = test\n@end group\n@end example\n\nNote in the example the use of the @code{mxDuplicateArray} function.  This is\nneeded as the @code{mxArray} pointer returned by @code{mxGetCell} might be\ndeallocated.  The inverse function to @code{mxGetCell}, used for setting Cell\nvalues, is @code{mxSetCell} and is defined as\n\n@example\nvoid mxSetCell (mxArray *ptr, int idx, mxArray *val);\n@end example\n\nFinally, to create a cell array or matrix, the appropriate functions are\n\n@example\n@group\nmxArray *mxCreateCellArray (int ndims, const int *dims);\nmxArray *mxCreateCellMatrix (int m, int n);\n@end group\n@end example\n\n@node Structures with Mex-Files\n@subsection Structures with Mex-Files\n\nThe basic function to create a structure in a mex-file is\n@code{mxCreateStructMatrix} which creates a structure array with a two\ndimensional matrix, or @code{mxCreateStructArray}.\n\n@example\n@group\nmxArray *mxCreateStructArray (int ndims, int *dims,\n                              int num_keys,\n                              const char **keys);\nmxArray *mxCreateStructMatrix (int rows, int cols,\n                               int num_keys,\n                               const char **keys);\n@end group\n@end example\n\nAccessing the fields of the structure can then be performed with\n@code{mxGetField} and @code{mxSetField} or alternatively with the\n@code{mxGetFieldByNumber} and @code{mxSetFieldByNumber} functions.\n\n@example\n@group\nmxArray *mxGetField (const mxArray *ptr, mwIndex index,\n                     const char *key);\nmxArray *mxGetFieldByNumber (const mxArray *ptr,\n                             mwIndex index, int key_num);\nvoid mxSetField (mxArray *ptr, mwIndex index,\n                 const char *key, mxArray *val);\nvoid mxSetFieldByNumber (mxArray *ptr, mwIndex index,\n                         int key_num, mxArray *val);\n@end group\n@end example\n\nA difference between the oct-file interface to structures and the mex-file\nversion is that the functions to operate on structures in mex-files directly\ninclude an @code{index} over the elements of the arrays of elements per\n@code{field}; Whereas, the oct-file structure includes a Cell Array per field\nof the structure.\n\nAn example that demonstrates the use of structures in a mex-file can be found\nin the file @file{mex_structdemo.c} shown below.\n\n@smallexample\n@EXAMPLEFILE(mex_structdemo.c)\n@end smallexample\n\nAn example of the behavior of this function within Octave is then\n\n@example\n@group\na(1).f1 = \"f11\"; a(1).f2 = \"f12\";\na(2).f1 = \"f21\"; a(2).f2 = \"f22\";\nb = mex_structdemo (a);\n@xresult{}  field f1(0) = f11\n    field f1(1) = f21\n    field f2(0) = f12\n    field f2(1) = f22\nb\n@xresult{} 2x2 struct array containing the fields:\n\n     this\n     that\n\nb(3)\n@xresult{} scalar structure containing the fields:\n\n     this = this3\n     that = that3\n@end group\n@end example\n\n@node Sparse Matrices with Mex-Files\n@subsection Sparse Matrices with Mex-Files\n\nThe Octave format for sparse matrices is identical to the mex format in that it\nis a compressed column sparse format.  Also, in both implementations sparse\nmatrices are required to be two-dimensional.  The only difference of importance\nto the programmer is that the real and imaginary parts of the matrix are stored\nseparately.\n\nThe mex-file interface, in addition to using @code{mxGetM}, @code{mxGetN},\n@code{mxSetM}, @code{mxSetN}, @code{mxGetPr}, @code{mxGetPi}, @code{mxSetPr},\nand @code{mxSetPi}, also supplies the following functions.\n\n@example\n@group\nmwIndex *mxGetIr (const mxArray *ptr);\nmwIndex *mxGetJc (const mxArray *ptr);\nmwSize mxGetNzmax (const mxArray *ptr);\n\nvoid mxSetIr (mxArray *ptr, mwIndex *ir);\nvoid mxSetJc (mxArray *ptr, mwIndex *jc);\nvoid mxSetNzmax (mxArray *ptr, mwSize nzmax);\n@end group\n@end example\n\n@noindent\n@code{mxGetNzmax} gets the maximum number of elements that can be stored in the\nsparse matrix.  This is not necessarily the number of nonzero elements in the\nsparse matrix.  @code{mxGetJc} returns an array with one additional value than\nthe number of columns in the sparse matrix.  The difference between consecutive\nvalues of the array returned by @code{mxGetJc} define the number of nonzero\nelements in each column of the sparse matrix.  Therefore,\n\n@example\n@group\nmwSize nz, n;\nmwIndex *Jc;\nmxArray *m;\n@dots{}\nn = mxGetN (m);\nJc = mxGetJc (m);\nnz = Jc[n];\n@end group\n@end example\n\n@noindent\nreturns the actual number of nonzero elements stored in the matrix in\n@code{nz}.  As the arrays returned by @code{mxGetPr} and @code{mxGetPi} only\ncontain the nonzero values of the matrix, we also need a pointer to the rows of\nthe nonzero elements, and this is given by @code{mxGetIr}.  A complete example\nof the use of sparse matrices in mex-files is given by the file\n@file{mex_sparsedemo.c} shown below.\n\n@example\n@EXAMPLEFILE(mex_sparsedemo.c)\n@end example\n\nA sample usage of @code{mex_sparsedemo} is\n\n@example\n@group\nsm = sparse ([1, 0; 0, pi]);\nmex_sparsedemo (sm)\n@xresult{}\nMatrix is 2-by-2 real sparse matrix with 2 elements\nlast nonzero element (2, 2) = 3.14159\n@end group\n@end example\n\n@node Calling Other Functions in Mex-Files\n@subsection Calling Other Functions in Mex-Files\n\nIt is possible to call other Octave functions from within a mex-file using\n@code{mexCallMATLAB}.  An example of the use of @code{mexCallMATLAB} can be see\nin the example below.\n\n@smallexample\n@EXAMPLEFILE(mex_fevaldemo.c)\n@end smallexample\n\nIf this code is in the file @file{mex_fevaldemo.c}, and is compiled to\n@file{mex_fevaldemo.mex}, then an example of its use is\n\n@example\n@group\na = mex_fevaldemo (\"sin\", 1)\n@xresult{} Starting file mex_fevaldemo.mex\n   I have 2 inputs and 1 outputs\n   I'm going to call the interpreter function sin\n   a =  0.84147\n@end group\n@end example\n\nNote that it is not possible to use function handles within a mex-file.\n\n@c @node Application Programming Interface for Mex-Files\n@c @subsection Application Programming Interface for Mex-Files\n@c\n@c WRITE ME, refer to mex.h and mexproto.h\n\n@node Standalone Programs\n@section Standalone Programs\n\nThe libraries Octave uses itself can be utilized in standalone applications.\nThese applications then have access, for example, to the array and matrix\nclasses, as well as to all of the Octave algorithms.  The following C++\nprogram, uses class Matrix from @file{liboctave.a} or @file{liboctave.so}.\n\n@example\n@EXAMPLEFILE(standalone.cc)\n@end example\n\n@noindent\nmkoctfile can be used to build a standalone application with a command like\n\n@example\n@group\n$ mkoctfile --link-stand-alone standalone.cc -o standalone\n$ ./standalone\nHello Octave world!\n  11 12\n  21 22\n$\n@end group\n@end example\n\nNote that the application @code{standalone} will be dynamically linked against\nthe Octave libraries and any Octave support libraries.  The above allows the\nOctave math libraries to be used by an application.  It does not, however,\nallow the script files, oct-files, or built-in functions of Octave to be used\nby the application.  To do that, the Octave interpreter needs to be initialized\nfirst.  An example of how to do this can then be seen in the code\n\n@example\n@EXAMPLEFILE(embedded.cc)\n@end example\n\n@noindent\nwhich, as before, is compiled and run as a standalone application with\n\n@example\n@group\n$ mkoctfile --link-stand-alone embedded.cc -o embedded\n$ ./embedded\nGCD of [10, 15] is 5\n$\n@end group\n@end example\n\nIt is worth re-iterating that, if only built-in functions are to be called from\na C++ standalone program then it does not need to initialize the interpreter.\nThe general rule is that for a built-in function named @code{function_name} in\nthe interpreter, there will be a C++ function named @code{Ffunction_name} (note\nthe prepended capital @code{F}) accessible in the C++ API@.  The declarations\nfor all built-in functions are collected in the header file\n@code{builtin-defun-decls.h}.  This feature should be used with care as the\nlist of built-in functions can change.  No guarantees can be made that a\nfunction that is currently a built-in won't be implemented as a @file{.m} file\nor as a dynamically linked function in the future.  An example of how to call\nbuilt-in functions from C++ can be seen in the code\n\n@example\n@EXAMPLEFILE(standalonebuiltin.cc)\n@end example\n\n@noindent\nwhich is compiled and run as a standalone application with\n\n@example\n@group\n$ mkoctfile --link-stand-alone standalonebuiltin.cc -o standalonebuiltin\n$ ./standalonebuiltin\nThis is a matrix:\n 11 12\n 21 22\n\nThis is the norm of the matrix:\n34.4952\n$\n@end group\n@end example\n\n@node Java Interface\n@section Java Interface\n\n@cindex using Octave with Java\n@cindex Java, using with Octave\n@cindex calling Java from Octave\n@cindex Java, calling from Octave\n@cindex calling Octave from Java\n@cindex Octave, calling from Java\n\nThe Java Interface is designed for calling Java functions from within Octave.\nIf you want to do the reverse, and call Octave from within Java, try a library\nlike @code{joPas} (@url{http://jopas.sourceforge.net}).\n\n@menu\n* Making Java Classes Available::\n* How to use Java from within Octave::\n* Set up the JVM::\n* Java Interface Functions::\n@end menu\n\n\n@node Making Java Classes Available\n@subsection Making Java Classes Available\n\n@c - index -\n@cindex classpath, setting\n@cindex classpath, difference between static and dynamic\n@cindex static classpath\n@cindex dynamic classpath\n@cindex @file{javaclasspath.txt}\n@cindex @file{classpath.txt}\n@cindex classes, making available to Octave\n@c - index -\n\nJava finds classes by searching a @var{classpath} which is a list of Java\narchive files and/or directories containing class files.  In Octave the\n@var{classpath} is composed of two parts:\n\n@itemize\n@item the @var{static classpath} is initialized once at startup of the JVM, and\n\n@item the @var{dynamic classpath} which can be modified at runtime.\n@end itemize\n\nOctave searches the @var{static classpath} first, and then the\n@var{dynamic classpath}.  Classes appearing in the @var{static classpath}, as\nwell as in the @var{dynamic classpath}, will therefore be found in the\n@var{static classpath} and loaded from this location.  Classes which will be\nused frequently, or must be available to all users, should be added to the\n@var{static classpath}.  The @var{static classpath} is populated once from the\ncontents of a plain text file named @file{javaclasspath.txt} (or\n@file{classpath.txt} historically) when the Java Virtual Machine starts.  This\nfile contains one line for each individual classpath to be added to the\n@var{static classpath}.  These lines can identify directories containing class\nfiles, or Java archives with complete class file hierarchies.  Comment lines\nstarting with a @samp{#} or a @samp{%} character are ignored.\n\nThe search rules for the file @file{javaclasspath.txt} (or\n@file{classpath.txt}) are:\n\n@itemize\n@item\nFirst, Octave tries to locate it in the current directory (where Octave was\nstarted from).  If such a file is found, it is read and defines the initial\n@var{static classpath}.  Thus, it is possible to define a static classpath on a\n'per Octave invocation' basis.\n\n@item\nNext, Octave searches in the user's home directory.  If a file\n@file{javaclasspath.txt} exists here, its contents are appended to the static\nclasspath (if any).  Thus, it is possible to build an initial static classpath\non a @nospell{'per user'} basis.\n\n@item\nFinally, Octave looks for a @file{javaclasspath.txt} in the m-file directory\nwhere Octave Java functions live.  This is where the function\n@file{javaclasspath.m} resides, usually something like\n@file{@w{@env{OCTAVE_HOME}}/share/octave/@w{@env{OCTAVE_VERSION}}/m/java/}.\nYou can find this directory by executing the command\n\n@example\nwhich javaclasspath\n@end example\n\nIf this file exists here, its contents are also appended to the\n@var{static classpath}.  Note that the archives and class directories defined\nin this last step will affect all users.\n@end itemize\n\nClasses which are used only by a specific script should be placed in the\n@var{dynamic classpath}.  This portion of the classpath can be modified at\nruntime using the @code{javaaddpath} and @code{javarmpath} functions.\n\nExample:\n\n@example\noctave> base_path = \"C:/Octave/java_files\";\n\noctave> # add two JAR archives to the dynamic classpath\noctave> javaaddpath ([base_path, \"/someclasses.jar\"]);\noctave> javaaddpath ([base_path, \"/moreclasses.jar\"]);\n\noctave> # check the dynamic classpath\noctave> p = javaclasspath;\noctave> disp (p@{1@});\nC:/Octave/java_files/someclasses.jar\noctave> disp (p@{2@});\nC:/Octave/java_files/moreclasses.jar\n\noctave> # remove the first element from the classpath\noctave> javarmpath ([base_path, \"/someclasses.jar\"]);\noctave> p = javaclasspath;\noctave> disp (p@{1@});\nC:/Octave/java_files/moreclasses.jar\n\noctave> # provoke an error\noctave> disp (p@{2@});\nerror: A(I): Index exceeds matrix dimension.\n@end example\n\nAnother way to add files to the @var{dynamic classpath} exclusively for your\nuser account is to use the file @file{.octaverc} which is stored in your home\ndirectory.  All Octave commands in this file are executed each time you start a\nnew instance of Octave.  The following example adds the directory @file{octave}\nto Octave's search path and the archive @file{myclasses.jar} in this directory\nto the Java search path.\n\n@example\n@group\n# contents of .octaverc:\naddpath (\"~/octave\");\njavaaddpath (\"~/octave/myclasses.jar\");\n@end group\n@end example\n\n@c ------------------------------------------------------------------------\n@node How to use Java from within Octave\n@subsection How to use Java from within Octave\n\nThe function @ref{XREFjavaObject,,javaObject} creates Java objects.  In fact it\ninvokes the public constructor of the class with the given name and with the\ngiven parameters.\n\nThe following example shows how to invoke the constructors\n@code{BigDecimal(double)} and @code{BigDecimal(String)} of the builtin Java\nclass @code{java.math.BigDecimal}.\n\n@example\n@group\njavaObject (\"java.math.BigDecimal\",  1.001 );\njavaObject (\"java.math.BigDecimal\", \"1.001\");\n@end group\n@end example\n\nNote that parameters of the Octave type @code{double} are implicitly converted\ninto the Java type @code{double} and the Octave type (array of) @code{char} is\nconverted into the java type @code{String}.  A Java object created by\n@ref{XREFjavaObject,,javaObject} is never automatically converted into an Octave\ntype but remains a Java object.  It can be assigned to an Octave variable.\n\n@example\n@group\na = 1.001;\nb = javaObject (\"java.math.BigDecimal\", a);\n@end group\n@end example\n\nUsing @ref{XREFisjava,,isjava}, it is possible to check whether a variable is a\nJava object and its class can be determined as well.  In addition to the\nprevious example:\n\n@example\n@group\nisjava (a)\n@xresult{} ans = 0\nclass (a)\n@xresult{} ans = double\nisjava (b)\n@xresult{} ans = 1\nclass (b)\n@xresult{} ans = java.math.BigDecimal\n@end group\n@end example\n\nThe example above can be carried out using only Java objects:\n\n@example\n@group\na = javaObject (\"java.lang.Double\", 1.001);\nb = javaObject (\"java.math.BigDecimal\", a);\n\nisjava (a)\n@xresult{} ans = 1\nclass (a)\n@xresult{} ans = java.lang.Double\nisjava (b)\n@xresult{} ans = 1\nclass (b)\n@xresult{} ans = java.math.BigDecimal\n@end group\n@end example\n\nOne can see, that even a @code{java.lang.Double} is not converted to an Octave\n@code{double}, when created by @ref{XREFjavaObject,,javaObject}.  But\nambiguities might arise, if the Java classes @code{java.lang.Double} or\n@code{double} are parameters of a method (or a constructor).  In this case they\ncan be converted into one another, depending on the context.\n\nVia @ref{XREFjavaObject,,javaObject} one may create all kinds of Java objects\nbut arrays.  The latter are created through @ref{XREFjavaArray,,javaArray}.\n\nIt is possible to invoke public member methods on Java objects in Java syntax:\n\n@example\n@group\na.toString\n@xresult{} ans = 1.001\nb.toString\n@xresult{} ans = 1.000999999999999889865...\n@end group\n@end example\n\nThe second result may be surprising, but simply comes from the fact, that\n@code{1.001} cannot exactly be represented as @code{double}, due to rounding.\nNote that unlike in Java, in Octave methods without arguments can be invoked\nwith and without parentheses @code{()}.\n\nCurrently it is not possible to invoke static methods with a Java like syntax\nfrom within Octave.  Instead, one has to use the function\n@ref{XREFjavaMethod,,javaMethod} as in the following example:\n\n@example\n@group\njava.math.BigDecimal.valueOf(1.001);                    # does not work\njavaMethod (\"valueOf\", \"java.math.BigDecimal\", 1.001);  # workaround\n@end group\n@end example\n\nAs mentioned before, method and constructor parameters are converted\nautomatically between Octave and Java types, if appropriate.  For functions\nthis is also true with return values, whereas for constructors this is not.\n\nIt is also possible to access public fields of Java objects from within Octave\nusing Java syntax, with the limitation of static fields:\n\n@example\n@group\njava.math.BigDecimal.ONE;                  # does not work\njava_get (\"java.math.BigDecimal\", \"ONE\");  # workaround\n@end group\n@end example\n\nAccordingly, with @ref{XREFjava_set,,java_set} the value of a field can be set.\nNote that only public Java fields are accessible from within Octave.\n\nThe following example indicates that in Octave empty brackets @code{[]}\nrepresent Java's @code{null} value and how Java exceptions are represented.\n\n@example\n@group\njavaObject (\"java.math.BigDecimal\", []);\n@xresult{} error: [java] java.lang.NullPointerException\n@end group\n@end example\n\nIt is not recommended to represent Java's @code{null} value by empty brackets\n@code{[]}, because @code{null} has no type whereas @code{[]} has type\n@code{double}.\n\nIn Octave it is possible to provide limited Java reflection by listing the\npublic fields and methods of a Java object, both static or not.\n\n@example\n@group\nfieldnames (<Java object>)\nmethods (<Java object>)\n@end group\n@end example\n\nFinally, an examples is shown how to access the stack trace from within Octave,\nwhere the function @ref{XREFdebug_java,,debug_java} is used to set and to get\nthe current debug state.  In debug mode, the Java error and the stack trace are\ndisplayed.\n\n@example\n@group\ndebug_java (true)  # use \"false\" to omit display of stack trace\ndebug_java ()\n@xresult{} ans = 1\njavaObject (\"java.math.BigDecimal\", \"1\") ...\n  .divide (javaObject (\"java.math.BigDecimal\", \"0\"))\n@end group\n@end example\n\n\n@node Set up the JVM\n@subsection Set up the JVM\n@cindex memory, limitations on JVM\n@cindex select JVM version\n\nIn order to execute Java code Octave creates a Java Virtual Machine (JVM).  By\ndefault the version of the JVM is used that was detected during configuration\non Unix-like systems or that is pointed to from the registry keys at\n@file{HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JRE} or\n@file{HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment} on\nWindows.  The default path to the JVM can be overridden by setting the\nenvironment variable @w{@env{JAVA_HOME}}@ to the path where the JVM is\ninstalled.  On Windows that might be, for example,\n@file{C:\\Program Files\\Java\\jre-10.0.2}.  Make sure that you select a directory\nthat contains the JVM with a @nospell{bit-ness} that matches Octave's.\n\nThe JVM is only loaded once per Octave session.  Thus, to change the used\nversion of the JVM, you might have to re-start Octave.  To check which version\nof the JVM is currently being used, run @code{version -java}.\n\nThe JVM allocates a fixed amount of initial memory and may expand this pool up\nto a fixed maximum memory limit.  The default values depend on the Java version\n(@pxref{XREFjavamem,,javamem}).  The memory pool is shared by all Java objects\nrunning in the JVM@.  This strict memory limit is intended mainly to avoid\nrunaway applications inside web browsers or in enterprise servers which can\nconsume all memory and crash the system.  When the maximum memory limit is hit,\nJava code will throw exceptions so that applications will fail or behave\nunexpectedly.\n\nYou can specify options for the creation of the JVM inside a file named\n@file{java.opts}.  This is a text file where enter you enter lines containing\n@option{-X} and @option{-D} options that are then passed to the JVM during\ninitialization.\n\nThe directory where the Java options file is located is specified by the\nenvironment variable @w{@env{OCTAVE_JAVA_DIR}}.  If unset the directory where\n@file{javaclasspath.m} resides is used instead (typically\n@file{@w{@env{OCTAVE_HOME}}/share/octave/@w{@env{OCTAVE_VERSION}}/m/java/}).\nYou can find this directory by executing\n\n@example\nwhich javaclasspath\n@end example\n\nThe @option{-X} options allow you to increase the maximum amount of memory\navailable to the JVM@.  The following example allows up to 256 Megabytes to be\nused by adding the following line to the @file{java.opts} file:\n\n@example\n-Xmx256m\n@end example\n\nThe maximum possible amount of memory depends on your system.  On a Windows\nsystem with 2 Gigabytes main memory you should be able to set this maximum to\nabout 1 Gigabyte.\n\nIf your application requires a large amount of memory from the beginning, you\ncan also specify the initial amount of memory allocated to the JVM@.  Adding\nthe following line to the @file{java.opts} file starts the JVM with 64\nMegabytes of initial memory:\n\n@example\n-Xms64m\n@end example\n\nFor more details on the available @option{-X} options of your Java Virtual\nMachine issue the command @samp{java -X} at the operating system command prompt\nand consult the Java documentation.\n\nThe @option{-D} options can be used to define system properties which can then\nbe used by Java classes inside Octave.  System properties can be retrieved by\nusing the @code{getProperty()} methods of the @code{java.lang.System} class.\nThe following example line defines the property @var{MyProperty} and assigns it\nthe string @code{12.34}.\n\n@example\n-DMyProperty=12.34\n@end example\n\nThe value of this property can then be retrieved as a string by a Java object\nor in Octave:\n\n@example\n@group\noctave> javaMethod (\"getProperty\", \"java.lang.System\", \"MyProperty\");\nans = 12.34\n@end group\n@end example\n\n\n@node Java Interface Functions\n@subsection Java Interface Functions\n\nThe following functions are the core of the Java Interface.  They provide a way\nto create a Java object, get and set its data fields, and call Java methods\nwhich return results to Octave.\n\n@cindex object, creating a Java object\n@cindex instance, creating a Java instance\n@DOCSTRING(javaObject)\n\n@cindex array, creating a Java array\n@DOCSTRING(javaArray)\n\nThere are many different variable types in Octave, but only ones created\nthrough @code{javaObject} can use Java functions.  Before using Java with an\nunknown object the type can be checked with @code{isjava}.\n\n@DOCSTRING(isjava)\n\nOnce an object has been created it is natural to find out what fields the\nobject has, and to read (get) and write (set) them.\n\n@cindex fields, displaying available fields of a Java object\nIn Octave the @code{fieldnames} function for structures has been overloaded\nto return the fields of a Java object.  For example:\n\n@example\n@group\ndobj = javaObject (\"java.lang.Double\", pi);\nfieldnames (dobj)\n@xresult{}\n@{\n  [1,1] = public static final double java.lang.Double.POSITIVE_INFINITY\n  [1,2] = public static final double java.lang.Double.NEGATIVE_INFINITY\n  [1,3] = public static final double java.lang.Double.NaN\n  [1,4] = public static final double java.lang.Double.MAX_VALUE\n  [1,5] = public static final double java.lang.Double.MIN_NORMAL\n  [1,6] = public static final double java.lang.Double.MIN_VALUE\n  [1,7] = public static final int java.lang.Double.MAX_EXPONENT\n  [1,8] = public static final int java.lang.Double.MIN_EXPONENT\n  [1,9] = public static final int java.lang.Double.SIZE\n  [1,10] = public static final java.lang.Class java.lang.Double.TYPE\n@}\n@end group\n@end example\n\n@cindex field, returning value of Java object field\nThe analogy of objects with structures is carried over into reading and writing\nobject fields.  To read a field the object is indexed with the @samp{.}\noperator from structures.  This is the preferred method for reading fields, but\nOctave also provides a function interface to read fields with @code{java_get}.\nAn example of both styles is shown below.\n\n@example\n@group\ndobj = javaObject (\"java.lang.Double\", pi);\ndobj.MAX_VALUE\n@xresult{}  1.7977e+308\njava_get (\"java.lang.Float\", \"MAX_VALUE\")\n@xresult{}  3.4028e+38\n@end group\n@end example\n\n@DOCSTRING(java_get)\n\n@cindex field, setting value of Java object field\n@DOCSTRING(java_set)\n\n@cindex methods, displaying available methods of a Java object\nTo see what functions can be called with an object use @code{methods}.  For\nexample, using the previously created @var{dobj}:\n\n@example\n@group\nmethods (dobj)\n@xresult{}\nMethods for class java.lang.Double:\nboolean equals(java.lang.Object)\njava.lang.String toString(double)\njava.lang.String toString()\n@dots{}\n@end group\n@end example\n\nTo call a method of an object the same structure indexing operator @samp{.} is\nused.  Octave also provides a functional interface to calling the methods of an\nobject through @code{javaMethod}.  An example showing both styles is shown\nbelow.\n\n@example\n@group\ndobj = javaObject (\"java.lang.Double\", pi);\ndobj.equals (3)\n@xresult{}  0\njavaMethod (\"equals\", dobj, pi)\n@xresult{}  1\n@end group\n@end example\n\n@cindex method, invoking a method of a Java object\n@DOCSTRING(javaMethod)\n\nThe following three functions are used to display and modify the class path\nused by the Java Virtual Machine.  This is entirely separate from Octave's\n@env{PATH} variable and is used by the JVM to find the correct code to execute.\n\n@cindex classpath, displaying\n@cindex classpath, dynamic\n@cindex dynamic classpath\n@cindex classpath, static\n@cindex static classpath\n@DOCSTRING(javaclasspath)\n\n@findex javaaddpath\n@cindex classpath, adding new path\n@cindex path, adding to classpath\n@cindex classpath, dynamic\n@cindex dynamic classpath, adding new path\n@DOCSTRING(javaaddpath)\n\n@cindex classpath, removing path\n@cindex path, removing from classpath\n@DOCSTRING(javarmpath)\n\nThe following functions provide information and control over the interface\nbetween Octave and the Java Virtual Machine.\n\n@DOCSTRING(javachk)\n\n@DOCSTRING(usejava)\n\n@cindex memory, displaying Java memory status\n@DOCSTRING(javamem)\n\n@DOCSTRING(java_matrix_autoconversion)\n\n@DOCSTRING(java_unsigned_autoconversion)\n\n@DOCSTRING(debug_java)\n"
  },
  {
    "path": "doc/interpreter/fn-idx.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Function Index\n@unnumbered Function Index\n\n@printindex fn\n"
  },
  {
    "path": "doc/interpreter/func.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Functions and Scripts\n@chapter Functions and Scripts\n@cindex defining functions\n@cindex user-defined functions\n@cindex functions, user-defined\n@cindex script files\n\nComplicated Octave programs can often be simplified by defining functions.\nFunctions can be defined directly on the command line during interactive\nOctave sessions, or in external files, and can be called just like built-in\nfunctions.\n\n@menu\n* Introduction to Function and Script Files::\n* Defining Functions::\n* Returning from a Function::\n* Multiple Return Values::\n* Variable-length Return Lists::\n* Variable-length Argument Lists::\n* Ignoring Arguments::\n* Default Arguments::\n* Validating Arguments::\n* Function Files::\n* Script Files::\n* Function Handles and Anonymous Functions::\n* Command Syntax and Function Syntax::\n* Organization of Functions::\n@end menu\n\n@node Introduction to Function and Script Files\n@section Introduction to Function and Script Files\n\nThere are seven different things covered in this section.\n@enumerate\n@item\nTyping in a function at the command prompt.\n\n@item\nStoring a group of commands in a file --- called a script file.\n\n@item\nStoring a function in a file---called a function file.\n\n@item\nSubfunctions in function files.\n\n@item\nMultiple functions in one script file.\n\n@item\nPrivate functions.\n\n@item\nNested functions.\n@end enumerate\n\nBoth function files and script files end with an extension of .m, for\n@sc{matlab} compatibility.  If you want more than one independent\nfunctions in a file, it must be a script file (@pxref{Script Files}),\nand to use these functions you must execute the script file before you\ncan use the functions that are in the script file.\n\n@node Defining Functions\n@section Defining Functions\n@cindex @code{function} statement\n@cindex @code{endfunction} statement\n\nIn its simplest form, the definition of a function named @var{name}\nlooks like this:\n\n@example\n@group\nfunction @var{name}\n  @var{body}\nendfunction\n@end group\n@end example\n\n@noindent\nA valid function name is like a valid variable name: a sequence of\nletters, digits and underscores, not starting with a digit.  Functions\nshare the same pool of names as variables.\n\nThe function @var{body} consists of Octave statements.  It is the\nmost important part of the definition, because it says what the function\nshould actually @emph{do}.\n\nFor example, here is a function that, when executed, will ring the bell\non your terminal (assuming that it is possible to do so):\n\n@example\n@group\nfunction wakeup\n  printf (\"\\a\");\nendfunction\n@end group\n@end example\n\nThe @code{printf} statement (@pxref{Input and Output}) simply tells\nOctave to print the string @qcode{\"@backslashchar{}a\"}.  The special character\n@samp{\\a} stands for the alert character (ASCII 7).  @xref{Strings}.\n\nOnce this function is defined, you can ask Octave to evaluate it by\ntyping the name of the function.\n\nNormally, you will want to pass some information to the functions you\ndefine.  The syntax for passing parameters to a function in Octave is\n\n@example\n@group\nfunction @var{name} (@var{arg-list})\n  @var{body}\nendfunction\n@end group\n@end example\n\n@noindent\nwhere @var{arg-list} is a comma-separated list of the function's\narguments.  When the function is called, the argument names are used to\nhold the argument values given in the call.  The list of arguments may\nbe empty, in which case this form is equivalent to the one shown above.\n\nTo print a message along with ringing the bell, you might modify the\n@code{wakeup} to look like this:\n\n@example\n@group\nfunction wakeup (message)\n  printf (\"\\a%s\\n\", message);\nendfunction\n@end group\n@end example\n\nCalling this function using a statement like this\n\n@example\nwakeup (\"Rise and shine!\");\n@end example\n\n@noindent\nwill cause Octave to ring your terminal's bell and print the message\n@samp{Rise and shine!}, followed by a newline character (the @samp{\\n}\nin the first argument to the @code{printf} statement).\n\nIn most cases, you will also want to get some information back from the\nfunctions you define.  Here is the syntax for writing a function that\nreturns a single value:\n\n@example\n@group\nfunction @var{ret-var} = @var{name} (@var{arg-list})\n  @var{body}\nendfunction\n@end group\n@end example\n\n@noindent\nThe symbol @var{ret-var} is the name of the variable that will hold the\nvalue to be returned by the function.  This variable must be defined\nbefore the end of the function body in order for the function to return\na value.\n\nVariables used in the body of a function are local to the\nfunction.  Variables named in @var{arg-list} and @var{ret-var} are also\nlocal to the function.  @xref{Global Variables}, for information about\nhow to access global variables inside a function.\n\nFor example, here is a function that computes the average of the\nelements of a vector:\n\n@example\n@group\nfunction retval = avg (v)\n  retval = sum (v) / length (v);\nendfunction\n@end group\n@end example\n\nIf we had written @code{avg} like this instead,\n\n@example\n@group\nfunction retval = avg (v)\n  if (isvector (v))\n    retval = sum (v) / length (v);\n  endif\nendfunction\n@end group\n@end example\n\n@noindent\nand then called the function with a matrix instead of a vector as the\nargument, Octave would have printed an error message like this:\n\n@example\n@group\nerror: value on right hand side of assignment is undefined\n@end group\n@end example\n\n@noindent\nbecause the body of the @code{if} statement was never executed, and\n@code{retval} was never defined.  To prevent obscure errors like this,\nit is a good idea to always make sure that the return variables will\nalways have values, and to produce meaningful error messages when\nproblems are encountered.  For example, @code{avg} could have been\nwritten like this:\n\n@example\n@group\nfunction retval = avg (v)\n  retval = 0;\n  if (isvector (v))\n    retval = sum (v) / length (v);\n  else\n    error (\"avg: expecting vector argument\");\n  endif\nendfunction\n@end group\n@end example\n\nThere is still one remaining problem with this function.  What if it is\ncalled without an argument?  Without additional error checking, Octave\nwill probably print an error message that won't really help you track\ndown the source of the error.  To allow you to catch errors like this,\nOctave provides each function with an automatic variable called\n@code{nargin}.  Each time a function is called, @code{nargin} is\nautomatically initialized to the number of arguments that have actually\nbeen passed to the function.  For example, we might rewrite the\n@code{avg} function like this:\n\n@example\n@group\nfunction retval = avg (v)\n  retval = 0;\n  if (nargin != 1)\n    usage (\"avg (vector)\");\n  endif\n  if (isvector (v))\n    retval = sum (v) / length (v);\n  else\n    error (\"avg: expecting vector argument\");\n  endif\nendfunction\n@end group\n@end example\n\nOctave automatically reports an error for functions written in .m file code\nif they are called with more arguments than expected.  Octave does not\nautomatically report an error if a function is called with too few arguments,\nsince functions in general may have default arguments, but any attempt to use\na variable that has not been given a value will result in an error.\nFunctions can check the arguments they are called with to avoid such problems\nand to provide more context-specific error messages.\n\n@DOCSTRING(nargin)\n\n@DOCSTRING(inputname)\n\n@DOCSTRING(silent_functions)\n\n@node Returning from a Function\n@section Returning from a Function\n\nThe body of a user-defined function can contain a @code{return} statement.\nThis statement returns control to the rest of the Octave program.  It\nlooks like this:\n\n@example\nreturn\n@end example\n\nUnlike the @code{return} statement in C, Octave's @code{return}\nstatement cannot be used to return a value from a function.  Instead,\nyou must assign values to the list of return variables that are part of\nthe @code{function} statement.  The @code{return} statement simply makes\nit easier to exit a function from a deeply nested loop or conditional\nstatement.\n\nHere is an example of a function that checks to see if any elements of a\nvector are nonzero.\n\n@example\n@group\nfunction retval = any_nonzero (v)\n  retval = 0;\n  for i = 1:length (v)\n    if (v (i) != 0)\n      retval = 1;\n      return;\n    endif\n  endfor\n  printf (\"no nonzero elements found\\n\");\nendfunction\n@end group\n@end example\n\nNote that this function could not have been written using the\n@code{break} statement to exit the loop once a nonzero value is found\nwithout adding extra logic to avoid printing the message if the vector\ndoes contain a nonzero element.\n\n@deftypefn {} {} return\nWhen Octave encounters the keyword @code{return} inside a function or\nscript, it returns control to the caller immediately.  At the top level,\nthe return statement is ignored.  A @code{return} statement is assumed\nat the end of every function definition.\n@end deftypefn\n\n@node Multiple Return Values\n@section Multiple Return Values\n\nUnlike many other computer languages, Octave allows you to define\nfunctions that return more than one value.  The syntax for defining\nfunctions that return multiple values is\n\n@example\n@group\nfunction [@var{ret-list}] = @var{name} (@var{arg-list})\n  @var{body}\nendfunction\n@end group\n@end example\n\n@noindent\nwhere @var{name}, @var{arg-list}, and @var{body} have the same meaning\nas before, and @var{ret-list} is a comma-separated list of variable\nnames that will hold the values returned from the function.  The list of\nreturn values must have at least one element.  If @var{ret-list} has\nonly one element, this form of the @code{function} statement is\nequivalent to the form described in the previous section.\n\nHere is an example of a function that returns two values, the maximum\nelement of a vector and the index of its first occurrence in the vector.\n\n@example\n@group\nfunction [max, idx] = vmax (v)\n  idx = 1;\n  max = v (idx);\n  for i = 2:length (v)\n    if (v (i) > max)\n      max = v (i);\n      idx = i;\n    endif\n  endfor\nendfunction\n@end group\n@end example\n\nIn this particular case, the two values could have been returned as\nelements of a single array, but that is not always possible or\nconvenient.  The values to be returned may not have compatible\ndimensions, and it is often desirable to give the individual return\nvalues distinct names.\n\nIt is possible to use the @code{nthargout} function to obtain only some\nof the return values or several at once in a cell array.\n@xref{Cell Array Objects}.\n\n@DOCSTRING(nthargout)\n\nIn addition to setting @code{nargin} each time a function is called,\nOctave also automatically initializes @code{nargout} to the number of\nvalues that are expected to be returned.  This allows you to write\nfunctions that behave differently depending on the number of values that\nthe user of the function has requested.  The implicit assignment to the\nbuilt-in variable @code{ans} does not figure in the count of output\narguments, so the value of @code{nargout} may be zero.\n\nThe @code{svd} and @code{hist} functions are examples of built-in\nfunctions that behave differently depending on the value of\n@code{nargout}.  For example, @code{hist} will draw a histogram when called\nwith no output variables, but if called with outputs it will return the\nfrequency counts and/or bin centers without creating a plot.\n\nIt is possible to write functions that only set some return values.  For\nexample, calling the function\n\n@example\n@group\nfunction [x, y, z] = f ()\n  x = 1;\n  z = 2;\nendfunction\n@end group\n@end example\n\n@noindent\nas\n\n@example\n[a, b, c] = f ()\n@end example\n\n@noindent\nproduces:\n\n@example\n@group\na = 1\n\nb = [](0x0)\n\nc = 2\n@end group\n@end example\n\n@noindent\nalong with a warning.\n\n@DOCSTRING(nargout)\n\n@node Variable-length Return Lists\n@section Variable-length Return Lists\n@cindex variable-length return lists\n@cindex @code{varargout}\n@anchor{XREFvarargout}\n\nIt is possible to return a variable number of output arguments from a\nfunction using a syntax that's similar to the one used with the\nspecial @code{varargin} parameter name.  To let a function return a\nvariable number of output arguments the special output parameter name\n@code{varargout} is used.  As with @code{varargin}, @code{varargout} is\na cell array that will contain the requested output arguments.\n\nAs an example the following function sets the first output argument to\n1, the second to 2, and so on.\n\n@example\n@group\nfunction varargout = one_to_n ()\n  for i = 1:nargout\n    varargout@{i@} = i;\n  endfor\nendfunction\n@end group\n@end example\n\n@noindent\nWhen called this function returns values like this\n\n@example\n@group\n[a, b, c] = one_to_n ()\n     @xresult{} a =  1\n     @xresult{} b =  2\n     @xresult{} c =  3\n@end group\n@end example\n\nIf @code{varargin} (@code{varargout}) does not appear as the last\nelement of the input (output) parameter list, then it is not special,\nand is handled the same as any other parameter name.\n\n@DOCSTRING(deal)\n\n@node Variable-length Argument Lists\n@section Variable-length Argument Lists\n@cindex variable-length argument lists\n@cindex @code{varargin}\n@anchor{XREFvarargin}\n\nSometimes the number of input arguments is not known when the function\nis defined.  As an example think of a function that returns the smallest\nof all its input arguments.  For example:\n\n@example\n@group\na = smallest (1, 2, 3);\nb = smallest (1, 2, 3, 4);\n@end group\n@end example\n\n@noindent\nIn this example both @code{a} and @code{b} would be 1.  One way to write\nthe @code{smallest} function is\n\n@example\n@group\nfunction val = smallest (arg1, arg2, arg3, arg4, arg5)\n  @var{body}\nendfunction\n@end group\n@end example\n\n@noindent\nand then use the value of @code{nargin} to determine which of the input\narguments should be considered.  The problem with this approach is\nthat it can only handle a limited number of input arguments.\n\nIf the special parameter name @code{varargin} appears at the end of a\nfunction parameter list it indicates that the function takes a variable\nnumber of input arguments.  Using @code{varargin} the function\nlooks like this\n\n@example\n@group\nfunction val = smallest (varargin)\n  @var{body}\nendfunction\n@end group\n@end example\n\n@noindent\nIn the function body the input arguments can be accessed through the\nvariable @code{varargin}.  This variable is a cell array containing\nall the input arguments.  @xref{Cell Arrays}, for details on working\nwith cell arrays.  The @code{smallest} function can now be defined\nlike this\n\n@example\n@group\nfunction val = smallest (varargin)\n  val = min ([varargin@{:@}]);\nendfunction\n@end group\n@end example\n\n@noindent\nThis implementation handles any number of input arguments, but it's also\na very simple solution to the problem.\n\nA slightly more complex example of @code{varargin} is a function\n@code{print_arguments} that prints all input arguments.  Such a function\ncan be defined like this\n\n@example\n@group\nfunction print_arguments (varargin)\n  for i = 1:length (varargin)\n    printf (\"Input argument %d: \", i);\n    disp (varargin@{i@});\n  endfor\nendfunction\n@end group\n@end example\n\n@noindent\nThis function produces output like this\n\n@example\n@group\nprint_arguments (1, \"two\", 3);\n     @print{} Input argument 1:  1\n     @print{} Input argument 2: two\n     @print{} Input argument 3:  3\n@end group\n@end example\n\n@DOCSTRING(parseparams)\n\n@node Ignoring Arguments\n@section Ignoring Arguments\n\nIn the formal argument list, it is possible to use the dummy placeholder\n@code{~} instead of a name.  This indicates that the corresponding argument\nvalue should be ignored and not stored to any variable.\n\n@example\n@group\nfunction val = pick2nd (~, arg2)\n  val = arg2;\nendfunction\n@end group\n@end example\n\nThe value of @code{nargin} is not affected by using this declaration.\n\nReturn arguments can also be ignored using the same syntax.  For example, the\nsort function returns both the sorted values, and an index vector for the\noriginal input which will result in a sorted output.  Ignoring the second\noutput is simple---don't request more than one output.  But ignoring the first,\nand calculating just the second output, requires the use of the @code{~}\nplaceholder.\n\n@example\n@group\nx = [2, 3, 1];\n[s, i] = sort (x)\n@xresult{}\ns =\n\n   1   2   3\n\ni =\n\n   3   1   2\n\n[~, i] = sort (x)\n@xresult{}\ni =\n\n   3   1   2\n@end group\n@end example\n\nWhen using the @code{~} placeholder, commas---not whitespace---must be used\nto separate output arguments.  Otherwise, the interpreter will view @code{~} as\nthe logical not operator.\n\n@example\n@group\n[~ i] = sort (x)\nparse error:\n\n  invalid left hand side of assignment\n@end group\n@end example\n\nFunctions may take advantage of ignored outputs to reduce the number of\ncalculations performed.  To do so, use the @code{isargout} function to query\nwhether the output argument is wanted.  For example:\n\n@example\n@group\nfunction [out1, out2] = long_function (x, y, z)\n  if (isargout (1))\n    ## Long calculation\n    @dots{}\n    out1 = result;\n  endif\n  @dots{}\nendfunction\n@end group\n@end example\n\n@DOCSTRING(isargout)\n\n@node Default Arguments\n@section Default Arguments\n@cindex default arguments\n\nSince Octave supports variable number of input arguments, it is very useful\nto assign default values to some input arguments.  When an input argument\nis declared in the argument list it is possible to assign a default\nvalue to the argument like this\n\n@example\n@group\nfunction @var{name} (@var{arg1} = @var{val1}, @dots{})\n  @var{body}\nendfunction\n@end group\n@end example\n\n@noindent\nIf no value is assigned to @var{arg1} by the user, it will have the\nvalue @var{val1}.\n\nAs an example, the following function implements a variant of the classic\n``Hello, World'' program.\n\n@example\n@group\nfunction hello (who = \"World\")\n  printf (\"Hello, %s!\\n\", who);\nendfunction\n@end group\n@end example\n\n@noindent\nWhen called without an input argument the function prints the following\n\n@example\n@group\nhello ();\n     @print{} Hello, World!\n@end group\n@end example\n\n@noindent\nand when it's called with an input argument it prints the following\n\n@example\n@group\nhello (\"Beautiful World of Free Software\");\n     @print{} Hello, Beautiful World of Free Software!\n@end group\n@end example\n\nSometimes it is useful to explicitly tell Octave to use the default value\nof an input argument.  This can be done writing a @samp{:} as the value\nof the input argument when calling the function.\n\n@example\n@group\nhello (:);\n     @print{} Hello, World!\n@end group\n@end example\n\n@node Validating Arguments\n@section Validating Arguments\n@cindex validating arguments\n\nOctave is a weakly typed programming language.  Thus it is possible to\ncall a function with arguments, that probably cause errors or might have\nundesirable side effects.  For example calling a string processing function\nwith a huge sparse matrix.\n\nIt is good practice at the head of a function to verify that it has been\ncalled correctly.  Octave offers several functions for this purpose.\n\n@menu\n* Validating the number of Arguments::\n* Validating the type of Arguments::\n* Parsing Arguments::\n@end menu\n\n@node Validating the number of Arguments\n@subsection Validating the number of Arguments\n\nIn Octave the following idiom is seen frequently at the beginning of a\nfunction definition:\n\n@example\n@group\nif (nargin < min_#_inputs || nargin > max_#_inputs)\n  print_usage ();\nendif\n@end group\n@end example\n\n@noindent\nwhich stops the function execution and prints a message about the correct\nway to call the function whenever the number of inputs is wrong.\n\nSimilar error checking is provided by @code{narginchk} and\n@code{nargoutchk}.\n\n@DOCSTRING(narginchk)\n\n@DOCSTRING(nargoutchk)\n\n@node Validating the type of Arguments\n@subsection Validating the type of Arguments\n\nBesides the number of arguments, inputs can be checked for various\nproperties.  @code{validatestring} is used for string arguments and\n@code{validateattributes} for numeric arguments.\n\n@DOCSTRING(validatestring)\n\n@DOCSTRING(validateattributes)\n\nAs alternatives to @code{validateattributes} there are several shorter\nconvenience functions to check for individual properties.\n\n@DOCSTRING(mustBeFinite)\n\n@DOCSTRING(mustBeGreaterThan)\n\n@DOCSTRING(mustBeGreaterThanOrEqual)\n\n@DOCSTRING(mustBeInteger)\n\n@DOCSTRING(mustBeLessThan)\n\n@DOCSTRING(mustBeLessThanOrEqual)\n\n@DOCSTRING(mustBeMember)\n\n@DOCSTRING(mustBeNegative)\n\n@DOCSTRING(mustBeNonempty)\n\n@DOCSTRING(mustBeNonNan)\n\n@DOCSTRING(mustBeNonnegative)\n\n@DOCSTRING(mustBeNonpositive)\n\n@DOCSTRING(mustBeNonsparse)\n\n@DOCSTRING(mustBeNonzero)\n\n@DOCSTRING(mustBeNumeric)\n\n@DOCSTRING(mustBeNumericOrLogical)\n\n@DOCSTRING(mustBePositive)\n\n@DOCSTRING(mustBeReal)\n\n@node Parsing Arguments\n@subsection Parsing Arguments\n\nIf none of the preceding validation functions is sufficient there is also\nthe class @code{inputParser} which can perform extremely complex input\nchecking for functions.\n\n@DOCSTRING(inputParser)\n\n@node Function Files\n@section Function Files\n@cindex function file\n\nExcept for simple one-shot programs, it is not practical to have to\ndefine all the functions you need each time you need them.  Instead, you\nwill normally want to save them in a file so that you can easily edit\nthem, and save them for use at a later time.\n\nOctave does not require you to load function definitions from files\nbefore using them.  You simply need to put the function definitions in a\nplace where Octave can find them.\n\nWhen Octave encounters an identifier that is undefined, it first looks\nfor variables or functions that are already compiled and currently\nlisted in its symbol table.  If it fails to find a definition there, it\nsearches a list of directories (the @dfn{path}) for files ending in\n@file{.m} that have the same base name as the undefined\nidentifier.@footnote{The @samp{.m} suffix was chosen for compatibility\nwith @sc{matlab}.}  Once Octave finds a file with a name that matches,\nthe contents of the file are read.  If it defines a @emph{single}\nfunction, it is compiled and executed.  @xref{Script Files}, for more\ninformation about how you can define more than one function in a single\nfile.\n\nWhen Octave defines a function from a function file, it saves the full\nname of the file it read and the time stamp on the file.  If the time\nstamp on the file changes, Octave may reload the file.  When Octave is\nrunning interactively, time stamp checking normally happens at most once\neach time Octave prints the prompt.  Searching for new function\ndefinitions also occurs if the current working directory changes.\n\nChecking the time stamp allows you to edit the definition of a function\nwhile Octave is running, and automatically use the new function\ndefinition without having to restart your Octave session.\n\nTo avoid degrading performance unnecessarily by checking the time stamps\non functions that are not likely to change, Octave assumes that function\nfiles in the directory tree\n@file{@var{octave-home}/share/octave/@var{version}/m}\nwill not change, so it doesn't have to check their time stamps every time the\nfunctions defined in those files are used.  This is normally a very good\nassumption and provides a significant improvement in performance for the\nfunction files that are distributed with Octave.\n\nIf you know that your own function files will not change while you are\nrunning Octave, you can improve performance by calling\n@code{ignore_function_time_stamp (\"all\")}, so that Octave will\nignore the time stamps for all function files.  Passing\n@qcode{\"system\"} to this function resets the default behavior.\n\n@c FIXME: note about time stamps on files in NFS environments?\n\n@DOCSTRING(edit)\n\n@DOCSTRING(mfilename)\n\n@DOCSTRING(ignore_function_time_stamp)\n\n@menu\n* Manipulating the Load Path::\n* Subfunctions::\n* Private Functions::\n* Nested Functions::\n* Overloading and Autoloading::\n* Function Locking::\n* Function Precedence::\n@end menu\n\n@node Manipulating the Load Path\n@subsection Manipulating the Load Path\n\nWhen a function is called, Octave searches a list of directories for\na file that contains the function declaration.  This list of directories\nis known as the load path.  By default the load path contains\na list of directories distributed with Octave plus the current\nworking directory.  To see your current load path call the @code{path}\nfunction without any input or output arguments.\n\nIt is possible to add or remove directories to or from the load path\nusing @code{addpath} and @code{rmpath}.  As an example, the following\ncode adds @samp{~/Octave} to the load path.\n\n@example\naddpath (\"~/Octave\")\n@end example\n\n@noindent\nAfter this the directory @samp{~/Octave} will be searched for functions.\n\n@DOCSTRING(addpath)\n\n@DOCSTRING(genpath)\n\n@DOCSTRING(rmpath)\n\n@DOCSTRING(savepath)\n\n@DOCSTRING(path)\n\n@DOCSTRING(pathdef)\n\n@DOCSTRING(pathsep)\n\n@DOCSTRING(rehash)\n\n@DOCSTRING(file_in_loadpath)\n\n@DOCSTRING(restoredefaultpath)\n\n@DOCSTRING(command_line_path)\n\n@DOCSTRING(dir_in_loadpath)\n\n@DOCSTRING(mfile_encoding)\n\n@DOCSTRING(dir_encoding)\n\n@node Subfunctions\n@subsection Subfunctions\n\nA function file may contain secondary functions called\n@dfn{subfunctions}.  These secondary functions are only visible to the\nother functions in the same function file.  For example, a file\n@file{f.m} containing\n\n@example\n@group\nfunction f ()\n  printf (\"in f, calling g\\n\");\n  g ()\nendfunction\nfunction g ()\n  printf (\"in g, calling h\\n\");\n  h ()\nendfunction\nfunction h ()\n  printf (\"in h\\n\")\nendfunction\n@end group\n@end example\n\n@noindent\ndefines a main function @code{f} and two subfunctions.  The\nsubfunctions @code{g} and @code{h} may only be called from the main\nfunction @code{f} or from the other subfunctions, but not from outside\nthe file @file{f.m}.\n\n@DOCSTRING(localfunctions)\n\n@node Private Functions\n@subsection Private Functions\n\nIn many cases one function needs to access one or more helper\nfunctions.  If the helper function is limited to the scope of a single\nfunction, then subfunctions as discussed above might be used.  However,\nif a single helper function is used by more than one function, then\nthis is no longer possible.  In this case the helper functions might\nbe placed in a subdirectory, called \"private\", of the directory in which\nthe functions needing access to this helper function are found.\n\nAs a simple example, consider a function @code{func1}, that calls a helper\nfunction @code{func2} to do much of the work.  For example:\n\n@example\n@group\nfunction y = func1 (x)\n  y = func2 (x);\nendfunction\n@end group\n@end example\n\n@noindent\nThen if the path to @code{func1} is @code{<directory>/func1.m}, and if\n@code{func2} is found in the directory @code{<directory>/private/func2.m},\nthen @code{func2} is only available for use of the functions, like\n@code{func1}, that are found in @code{<directory>}.\n\n@node Nested Functions\n@subsection Nested Functions\n\nNested functions are similar to subfunctions in that only the main function is\nvisible outside the file.  However, they also allow for child functions to\naccess the local variables in their parent function.  This shared access mimics\nusing a global variable to share information --- but a global variable which is\nnot visible to the rest of Octave.  As a programming strategy, sharing data\nthis way can create code which is difficult to maintain.  It is recommended to\nuse subfunctions in place of nested functions when possible.\n\nAs a simple example, consider a parent function @code{foo}, that calls a nested\nchild function @code{bar}, with a shared variable @var{x}.\n\n@example\n@group\nfunction y = foo ()\n  x = 10;\n  bar ();\n  y = x;\n\n  function bar ()\n    x = 20;\n  endfunction\nendfunction\n\nfoo ()\n @xresult{} 20\n@end group\n@end example\n\n@noindent\nNotice that there is no special syntax for sharing @var{x}.  This can lead to\nproblems with accidental variable sharing between a parent function and its\nchild.  While normally variables are inherited, child function parameters and\nreturn values are local to the child function.\n\nNow consider the function @code{foobar} that uses variables @var{x} and\n@var{y}.  @code{foobar} calls a nested function @code{foo} which takes\n@var{x} as a parameter and returns @var{y}.  @code{foo} then calls @code{bat}\nwhich does some computation.\n\n@example\n@group\nfunction z = foobar ()\n  x = 0;\n  y = 0;\n  z = foo (5);\n  z += x + y;\n\n  function y = foo (x)\n    y = x + bat ();\n\n    function z = bat ()\n      z = x;\n    endfunction\n  endfunction\nendfunction\n\nfoobar ()\n    @xresult{} 10\n@end group\n@end example\n\n@noindent\nIt is important to note that the @var{x} and @var{y} in @code{foobar} remain\nzero, as in @code{foo} they are a return value and parameter respectively.  The\n@var{x} in @code{bat} refers to the @var{x} in @code{foo}.\n\nVariable inheritance leads to a problem for @code{eval} and scripts.  If a\nnew variable is created in a parent function, it is not clear what should\nhappen in nested child functions.  For example, consider a parent function\n@code{foo} with a nested child function @code{bar}:\n\n@example\n@group\nfunction y = foo (to_eval)\n  bar ();\n  eval (to_eval);\n\n  function bar ()\n    eval (\"x = 100;\");\n    eval (\"y = x;\");\n  endfunction\nendfunction\n\nfoo (\"x = 5;\")\n    @xresult{} error: can not add variable \"x\" to a static workspace\n\nfoo (\"y = 10;\")\n    @xresult{} 10\n\nfoo (\"\")\n    @xresult{} 100\n@end group\n@end example\n\n@noindent\nThe parent function @code{foo} is unable to create a new variable\n@var{x}, but the child function @code{bar} was successful.  Furthermore, even\nin an @code{eval} statement @var{y} in @code{bar} is the same @var{y} as in its\nparent function @code{foo}.  The use of @code{eval} in conjunction with nested\nfunctions is best avoided.\n\nAs with subfunctions, only the first nested function in a file may be called\nfrom the outside.  Inside a function the rules are more complicated.  In\ngeneral a nested function may call:\n\n@enumerate 0\n@item\nGlobally visible functions\n\n@item\nAny function that the nested function's parent can call\n\n@item\nSibling functions (functions that have the same parents)\n\n@item\nDirect children\n\n@end enumerate\n\nAs a complex example consider a parent function @code{ex_top} with two\nchild functions, @code{ex_a} and @code{ex_b}.  In addition, @code{ex_a} has two\nmore child functions, @code{ex_aa} and @code{ex_ab}.  For example:\n\n@example\nfunction ex_top ()\n  ## Can call: ex_top, ex_a, and ex_b\n  ## Can NOT call: ex_aa and ex_ab\n\n  function ex_a ()\n    ## Can call everything\n\n    function ex_aa ()\n      ## Can call everything\n    endfunction\n\n    function ex_ab ()\n      ## Can call everything\n    endfunction\n  endfunction\n\n  function ex_b ()\n    ## Can call: ex_top, ex_a, and ex_b\n    ## Can NOT call: ex_aa and ex_ab\n  endfunction\nendfunction\n@end example\n\n@node Overloading and Autoloading\n@subsection Overloading and Autoloading\n\nFunctions can be overloaded to work with different input arguments.  For\nexample, the operator '+' has been overloaded in Octave to work with single,\ndouble, uint8, int32, and many other arguments.  The preferred way to overload\nfunctions is through classes and object oriented programming\n(@pxref{Function Overloading}).  Occasionally, however, one needs to undo\nuser overloading and call the default function associated with a specific\ntype.  The @code{builtin} function exists for this purpose.\n\n@DOCSTRING(builtin)\n\nA single dynamically linked file might define several\nfunctions.  However, as Octave searches for functions based on the\nfunctions filename, Octave needs a manner in which to find each of the\nfunctions in the dynamically linked file.  On operating systems that\nsupport symbolic links, it is possible to create a symbolic link to the\noriginal file for each of the functions which it contains.\n\nHowever, there is at least one well known operating system that doesn't\nsupport symbolic links.  Making copies of the original file for each of\nthe functions is undesirable as it increases the\namount of disk space used by Octave.  Instead Octave supplies the\n@code{autoload} function, that permits the user to define in which\nfile a certain function will be found.\n\n@DOCSTRING(autoload)\n\n@node Function Locking\n@subsection Function Locking\n\nIt is sometime desirable to lock a function into memory with the @code{mlock}\nfunction.  This is typically used for dynamically linked functions in\noct-files or mex-files that contain some initialization, and it is desirable\nthat calling @code{clear} does not remove this initialization.\n\nAs an example,\n\n@example\n@group\nfunction my_function ()\n  mlock ();\n  @dots{}\nendfunction\n@end group\n@end example\n\n@noindent\nprevents @code{my_function} from being removed from memory after it is called,\neven if @code{clear} is called.  It is possible to determine if a function is\nlocked into memory with the @code{mislocked}, and to unlock a function with\n@code{munlock}, which the following code illustrates.\n\n@example\n@group\nmy_function ();\nmislocked (\"my_function\")\n@xresult{} ans = 1\nmunlock (\"my_function\");\nmislocked (\"my_function\")\n@xresult{} ans = 0\n@end group\n@end example\n\nA common use of @code{mlock} is to prevent persistent variables from being\nremoved from memory, as the following example shows:\n\n@example\n@group\nfunction count_calls ()\n  mlock ();\n  persistent calls = 0;\n  printf (\"count_calls() has been called %d times\\n\", ++calls);\nendfunction\n\ncount_calls ();\n@print{} count_calls() has been called 1 times\n\nclear count_calls\ncount_calls ();\n@print{} count_calls() has been called 2 times\n@end group\n@end example\n\n@code{mlock} might also be used to prevent changes to an m-file, such as in an\nexternal editor, from having any effect in the current Octave session; A\nsimilar effect can be had with the @code{ignore_function_time_stamp} function.\n\n@DOCSTRING(mlock)\n\n@DOCSTRING(munlock)\n\n@DOCSTRING(mislocked)\n\n@node Function Precedence\n@subsection Function Precedence\n\nGiven the numerous different ways that Octave can define a function, it\nis possible and even likely that multiple versions of a function, might be\ndefined within a particular scope.  The precedence of which function will be\nused within a particular scope is given by\n\n@enumerate 1\n@item Subfunction\nA subfunction with the required function name in the given scope.\n\n@item Private function\nA function defined within a private directory of the directory\nwhich contains the current function.\n\n@item Class constructor\nA function that constructs a user class as defined in chapter\n@ref{Object Oriented Programming}.\n\n@item Class method\nAn overloaded function of a class as in chapter\n@ref{Object Oriented Programming}.\n\n@item Command-line Function\nA function that has been defined on the command-line.\n\n@item Autoload function\nA function that is marked as autoloaded with @ref{XREFautoload,,autoload}.\n\n@item A Function on the Path\nA function that can be found on the users load-path.  There can also be\nOct-file, mex-file or m-file versions of this function and the precedence\nbetween these versions are in that order.\n\n@item Built-in function\nA function that is a part of core Octave such as @code{numel}, @code{size},\netc.\n@end enumerate\n\n@node Script Files\n@section Script Files\n\nA script file is a file containing (almost) any sequence of Octave\ncommands.  It is read and evaluated just as if you had typed each\ncommand at the Octave prompt, and provides a convenient way to perform a\nsequence of commands that do not logically belong inside a function.\n\nUnlike a function file, a script file must @emph{not} begin with the\nkeyword @code{function}.  If it does, Octave will assume that it is a\nfunction file, and that it defines a single function that should be\nevaluated as soon as it is defined.\n\nA script file also differs from a function file in that the variables\nnamed in a script file are not local variables, but are in the same\nscope as the other variables that are visible on the command line.\n\nEven though a script file may not begin with the @code{function}\nkeyword, it is possible to define more than one function in a single\nscript file and load (but not execute) all of them at once.  To do\nthis, the first token in the file (ignoring comments and other white\nspace) must be something other than @code{function}.  If you have no\nother statements to evaluate, you can use a statement that has no\neffect, like this:\n\n@example\n@group\n# Prevent Octave from thinking that this\n# is a function file:\n\n1;\n\n# Define function one:\n\nfunction one ()\n  @dots{}\n@end group\n@end example\n\nTo have Octave read and compile these functions into an internal form,\nyou need to make sure that the file is in Octave's load path\n(accessible through the @code{path} function), then simply type the\nbase name of the file that contains the commands.  (Octave uses the\nsame rules to search for script files as it does to search for\nfunction files.)\n\nIf the first token in a file (ignoring comments) is @code{function},\nOctave will compile the function and try to execute it, printing a\nmessage warning about any non-whitespace characters that appear after\nthe function definition.\n\nNote that Octave does not try to look up the definition of any identifier\nuntil it needs to evaluate it.  This means that Octave will compile the\nfollowing statements if they appear in a script file, or are typed at\nthe command line,\n\n@example\n@group\n# not a function file:\n1;\nfunction foo ()\n  do_something ();\nendfunction\nfunction do_something ()\n  do_something_else ();\nendfunction\n@end group\n@end example\n\n@noindent\neven though the function @code{do_something} is not defined before it is\nreferenced in the function @code{foo}.  This is not an error because\nOctave does not need to resolve all symbols that are referenced by a\nfunction until the function is actually evaluated.\n\nSince Octave doesn't look for definitions until they are needed, the\nfollowing code will always print @samp{bar = 3} whether it is typed\ndirectly on the command line, read from a script file, or is part of a\nfunction body, even if there is a function or script file called\n@file{bar.m} in Octave's path.\n\n@example\n@group\neval (\"bar = 3\");\nbar\n@end group\n@end example\n\nCode like this appearing within a function body could fool Octave if\ndefinitions were resolved as the function was being compiled.  It would\nbe virtually impossible to make Octave clever enough to evaluate this\ncode in a consistent fashion.  The parser would have to be able to\nperform the call to @code{eval} at compile time, and that would be\nimpossible unless all the references in the string to be evaluated could\nalso be resolved, and requiring that would be too restrictive (the\nstring might come from user input, or depend on things that are not\nknown until the function is evaluated).\n\nAlthough Octave normally executes commands from script files that have\nthe name @file{@var{file}.m}, you can use the function @code{source} to\nexecute commands from any file.\n\n@DOCSTRING(source)\n\n@menu\n* Publish Octave Script Files::\n* Publishing Markup::\n* Jupyter Notebooks::\n@end menu\n\n@node Publish Octave Script Files\n@subsection Publish Octave Script Files\n\nThe function @code{publish} provides a dynamic possibility to document your\nscript file.  Unlike static documentation, @code{publish} runs the script\nfile, saves any figures and output while running the script, and presents them\nalongside static documentation in a desired output format.  The static\ndocumentation can make use of @ref{Publishing Markup} to enhance and\ncustomize the output.\n\n@DOCSTRING(publish)\n\nThe counterpart to @code{publish} is @code{grabcode}:\n\n@DOCSTRING(grabcode)\n\n@node Publishing Markup\n@subsection Publishing Markup\n\n@menu\n* Using Publishing Markup in Script Files::\n* Text Formatting::\n* Sections::\n* Preformatted Code::\n* Preformatted Text::\n* Bulleted Lists::\n* Numbered Lists::\n* Including File Content::\n* Including Graphics::\n* Including URLs::\n* Mathematical Equations::\n* HTML Markup::\n* LaTeX Markup::\n@end menu\n\n@node Using Publishing Markup in Script Files\n@subsubsection Using Publishing Markup in Script Files\n\nTo use Publishing Markup, start by typing @samp{##} or @samp{%%} at the\nbeginning of a new line.  For @sc{matlab} compatibility @samp{%%%} is treated\nthe same way as @samp{%%}.\n\nThe lines following @samp{##} or @samp{%%} start with one of either\n@samp{#} or @samp{%} followed by at least one space.  These lines are\ninterpreted as section.  A section ends at the first line not starting\nwith @samp{#} or @samp{%}, or when the end of the document is reached.\n\nA section starting in the first line of the document, followed by another\nstart of a section that might be empty, is interpreted as a document\ntitle and introduction text.\n\nSee the example below for clarity:\n\n@example\n@group\n%% Headline title\n%\n% Some *bold*, _italic_, or |monospaced| Text with\n% a <https://www.octave.org link to GNU Octave>.\n%%\n\n# \"Real\" Octave commands to be evaluated\nsombrero ()\n\n## Octave comment style supported as well\n#\n# * Bulleted list item 1\n# * Bulleted list item 2\n#\n# # Numbered list item 1\n# # Numbered list item 2\n@end group\n@end example\n\n@node Text Formatting\n@subsubsection Text Formatting\n\nBasic text formatting is supported inside sections, see the example\ngiven below:\n\n@example\n@group\n##\n# @b{*bold*}, @i{_italic_}, or |monospaced| Text\n@end group\n@end example\n\nAdditionally two trademark symbols are supported, just embrace the letters\n@samp{TM} or @samp{R}.\n\n@example\n@group\n##\n# (TM) or (R)\n@end group\n@end example\n\n@node Sections\n@subsubsection Sections\n\nA section is started by typing @samp{##} or @samp{%%} at the beginning of\na new line.  A section title can be provided by writing it, separated by a\nspace, in the first line after @samp{##} or @samp{%%}.  Without a section\ntitle, the section is interpreted as a continuation of the previous section.\nFor @sc{matlab} compatibility @samp{%%%} is treated the same way as @samp{%%}.\n\n@example\n@group\nsome_code ();\n\n## Section 1\n#\n## Section 2\n\nsome_code ();\n\n##\n# Still in section 2\n\nsome_code ();\n\n%%% Section 3\n%\n%\n@end group\n@end example\n\n@node Preformatted Code\n@subsubsection Preformatted Code\n\nTo write preformatted code inside a section, indent the code by three\nspaces after @samp{#} at the beginning of each line and leave the lines\nabove and below the code blank, except for @samp{#} at the beginning of\nthose lines.\n\n@example\n@group\n##\n# This is a syntax highlighted for-loop:\n#\n#   for i = 1:5\n#     disp (i);\n#   endfor\n#\n# And more usual text.\n@end group\n@end example\n\n@node Preformatted Text\n@subsubsection Preformatted Text\n\nTo write preformatted text inside a section, indent the code by two spaces\nafter @samp{#} at the beginning of each line and leave the lines above and\nbelow the preformatted text blank, except for @samp{#} at the beginning of\nthose lines.\n\n@example\n@group\n##\n# This following text is preformatted:\n#\n#  \"To be, or not to be: that is the question:\n#  Whether 'tis nobler in the mind to suffer\n#  The slings and arrows of outrageous fortune,\n#  Or to take arms against a sea of troubles,\n#  And by opposing end them?  To die: to sleep;\"\n#\n#  --\"Hamlet\" by W. Shakespeare\n@end group\n@end example\n\n@node Bulleted Lists\n@subsubsection Bulleted Lists\n\nTo create a bulleted list, type\n\n@example\n@group\n##\n#\n# * Bulleted list item 1\n# * Bulleted list item 2\n#\n@end group\n@end example\n\n@noindent\nto get output like\n\n@itemize @bullet\n@item Bulleted list item 1\n\n@item Bulleted list item 2\n@end itemize\n\nNotice the blank lines, except for the @samp{#} or @samp{%} before and\nafter the bulleted list!\n\n@node Numbered Lists\n@subsubsection Numbered Lists\n\nTo create a numbered list, type\n\n@example\n@group\n##\n#\n# # Numbered list item 1\n# # Numbered list item 2\n#\n@end group\n@end example\n\n@noindent\nto get output like\n\n@enumerate\n@item Numbered list item 1\n\n@item Numbered list item 2\n@end enumerate\n\nNotice the blank lines, except for the @samp{#} or @samp{%} before and\nafter the numbered list!\n\n@node Including File Content\n@subsubsection Including File Content\n\nTo include the content of an external file, e.g., a file called\n@samp{my_function.m} at the same location as the published Octave script,\nuse the following syntax to include it with Octave syntax highlighting.\n\nAlternatively, you can write the full or relative path to the file.\n\n@example\n@group\n##\n#\n# <include>my_function.m</include>\n#\n# <include>/full/path/to/my_function.m</include>\n#\n# <include>../relative/path/to/my_function.m</include>\n#\n@end group\n@end example\n\n@node Including Graphics\n@subsubsection Including Graphics\n\nTo include external graphics, e.g., a graphic called @samp{my_graphic.png}\nat the same location as the published Octave script, use the following syntax.\n\nAlternatively, you can write the full path to the graphic.\n\n@example\n@group\n##\n#\n# <<my_graphic.png>>\n#\n# <</full/path/to/my_graphic.png>>\n#\n# <<../relative/path/to/my_graphic.png>>\n#\n@end group\n@end example\n\n@node Including URLs\n@subsubsection Including URLs\n\nBasically, a URL is written between an opening @samp{<} and a closing @samp{>}\nangle.\n\n@example\n@group\n##\n# <https://www.octave.org>\n@end group\n@end example\n\nText that is within these angles and separated by at least one space from the\nURL is a displayed text for the link.\n\n@example\n@group\n##\n# <https://www.octave.org GNU Octave>\n@end group\n@end example\n\nA link starting with @samp{<octave:} followed by the name of a GNU Octave\nfunction, optionally with a displayed text, results in a link to the online\nGNU Octave documentations function index.\n\n@example\n@group\n##\n# <octave:DISP The display function>\n@end group\n@end example\n\n@node Mathematical Equations\n@subsubsection Mathematical Equations\n\nOne can insert @LaTeX{} inline math, surrounded by single @samp{$} signs, or\ndisplayed math, surrounded by double @samp{$$} signs, directly inside\nsections.\n\n@example\n@group\n##\n# Some shorter inline equation $e^@{ix@} = \\cos x + i\\sin x$.\n#\n# Or more complicated formulas as displayed math:\n# $$e^x = \\lim_@{n\\rightarrow\\infty@}\\left(1+\\dfrac@{x@}@{n@}\\right)^@{n@}.$$\n@end group\n@end example\n\n@node HTML Markup\n@subsubsection HTML Markup\n\nIf the published output is a HTML report, you can insert HTML markup,\nthat is only visible in this kind of output.\n\n@example\n@group\n##\n# <html>\n# <table style=\"border:1px solid black;\">\n# <tr><td>1</td><td>2</td></tr>\n# <tr><td>3</td><td>3</td></tr>\n# </html>\n@end group\n@end example\n\n@node LaTeX Markup\n@subsubsection LaTeX Markup\n\nIf the published output is a @LaTeX{} or PDF report, you can insert @LaTeX{}\nmarkup, that is only visible in this kind of output.\n\n@example\n@group\n##\n# <latex>\n# Some output only visible in @nospell{LaTeX} or PDF reports.\n# \\begin@{equation@}\n# e^x = \\lim\\limits_@{n\\rightarrow\\infty@}\\left(1+\\dfrac@{x@}@{n@}\\right)^@{n@}\n# \\end@{equation@}\n# </latex>\n@end group\n@end example\n\n@node Jupyter Notebooks\n@subsection Jupyter Notebooks\n@cindex Jupyter Notebooks\n\nJupyter notebooks are one popular technique for displaying code, text, and\ngraphical output together in a comprehensive manner.  Octave can publish\nresults to a Jupyter notebook with the function @code{jupyter_notebook}.\n\n@DOCSTRING(jupyter_notebook)\n\n@node Function Handles and Anonymous Functions\n@section Function Handles and Anonymous Functions\n@cindex handle, function handles\n@cindex anonymous functions\n\nIt can be very convenient store a function in a variable so that it\ncan be passed to a different function.  For example, a function that\nperforms numerical minimization needs access to the function that\nshould be minimized.\n\n@menu\n* Function Handles::\n* Anonymous Functions::\n@end menu\n\n@node Function Handles\n@subsection Function Handles\n\nA function handle is a pointer to another function and is defined with\nthe syntax\n\n@example\n@@@var{function-name}\n@end example\n\n@noindent\nFor example,\n\n@example\nf = @@sin;\n@end example\n\n@noindent\ncreates a function handle called @code{f} that refers to the\nfunction @code{sin}.\n\nFunction handles are used to call other functions indirectly, or to pass\na function as an argument to another function like @code{quad} or\n@code{fsolve}.  For example:\n\n@example\n@group\nf = @@sin;\nquad (f, 0, pi)\n    @xresult{} 2\n@end group\n@end example\n\nYou may use @code{feval} to call a function using function handle, or\nsimply write the name of the function handle followed by an argument\nlist.  If there are no arguments, you must use an empty argument list\n@samp{()}.  For example:\n\n@example\n@group\nf = @@sin;\nfeval (f, pi/4)\n    @xresult{} 0.70711\nf (pi/4)\n    @xresult{} 0.70711\n@end group\n@end example\n\n@DOCSTRING(is_function_handle)\n\n@DOCSTRING(functions)\n\n@DOCSTRING(func2str)\n\n@DOCSTRING(str2func)\n\n@DOCSTRING(symvar)\n\n@node Anonymous Functions\n@subsection Anonymous Functions\n\nAnonymous functions are defined using the syntax\n\n@example\n@@(@var{argument-list}) @var{expression}\n@end example\n\n@noindent\nAny variables that are not found in the argument list are inherited from\nthe enclosing scope.  Anonymous functions are useful for creating simple\nunnamed functions from expressions or for wrapping calls to other\nfunctions to adapt them for use by functions like @code{quad}.  For\nexample,\n\n@example\n@group\nf = @@(x) x.^2;\nquad (f, 0, 10)\n    @xresult{} 333.33\n@end group\n@end example\n\n@noindent\ncreates a simple unnamed function from the expression @code{x.^2} and\npasses it to @code{quad},\n\n@example\n@group\nquad (@@(x) sin (x), 0, pi)\n    @xresult{} 2\n@end group\n@end example\n\n@noindent\nwraps another function, and\n\n@example\n@group\na = 1;\nb = 2;\nquad (@@(x) betainc (x, a, b), 0, 0.4)\n    @xresult{} 0.13867\n@end group\n@end example\n\n@noindent\nadapts a function with several parameters to the form required by\n@code{quad}.  In this example, the values of @var{a} and @var{b} that\nare passed to @code{betainc} are inherited from the current\nenvironment.\n\nNote that for performance reasons it is better to use handles to existing\nOctave functions, rather than to define anonymous functions which wrap an\nexisting function.  The integration of @code{sin (x)} is 5X faster if the code\nis written as\n\n@example\nquad (@@sin, 0, pi)\n@end example\n\n@noindent\nrather than using the anonymous function @code{@@(x) sin (x)}.  There are many\noperators which have functional equivalents that may be better choices than an\nanonymous function.  Instead of writing\n\n@example\nf = @@(x, y) x + y\n@end example\n\n@noindent\nthis should be coded as\n\n@example\nf = @@plus\n@end example\n\n@xref{Operator Overloading}, for a list of operators which also have a\nfunctional form.\n\n@node Command Syntax and Function Syntax\n@section Command Syntax and Function Syntax\n@cindex commands functions\n\nIn addition to the function syntax described above (i.e., calling a function\nlike @code{fun (arg1, arg2, @dots{})}), a function can be called using command\nsyntax (for example, calling a function like @code{fun arg1 arg2 @dots{}}).  In\nthat case, all arguments are passed to the function as strings.  For example,\n\n@example\nmy_command hello world\n@end example\n\n@noindent\nis equivalent to\n\n@example\nmy_command (\"hello\", \"world\")\n@end example\n\n@noindent\nThe general form of a command call is\n\n@example\ncmdname arg1 arg2 @dots{}\n@end example\n\n@noindent\nwhich translates directly to\n\n@example\ncmdname (\"arg1\", \"arg2\", @dots{})\n@end example\n\nIf an argument including spaces should be passed to a function in command\nsyntax, (double-)quotes can be used.  For example,\n\n@example\nmy_command \"first argument\" \"second argument\"\n@end example\n\n@noindent\nis equivalent to\n\n@example\nmy_command (\"first argument\", \"second argument\")\n@end example\n\nAny function can be used as a command if it accepts string input arguments.\nFor example:\n\n@example\n@group\nupper lower_case_arg\n   @xresult{} ans = LOWER_CASE_ARG\n@end group\n@end example\n\nSince the arguments are passed as strings to the corresponding function, it is\nnot possible to pass input arguments that are stored in variables.  In that\ncase, a command must be called using the function syntax.  For example:\n\n@example\n@group\nstrvar = \"hello world\";\nupper strvar\n   @xresult{} ans = STRVAR\nupper (strvar)\n   @xresult{} ans = HELLO WORLD\n@end group\n@end example\n\nAdditionally, the return values of functions cannot be assigned to variables\nusing the command syntax.  Only the first return argument is assigned to the\nbuilt-in variable @code{ans}.  If the output argument of a command should be\nassigned to a variable, or multiple output arguments of a function should be\nreturned, the function syntax must be used.\n\nIt should be noted that mixing command syntax and binary operators can\ncreate apparent ambiguities with mathematical and logical expressions that\nuse function syntax.  For example, all three of the statements\n\n@example\n@group\narg1 - arg2\narg1 -arg2\narg1-arg2\n@end group\n@end example\n\n@noindent\ncould be intended by a user to be subtraction operations between\n@code{arg1} and @code{arg2}.  The first two, however, could also have been\nmeant as a command syntax call to function @code{arg1}, in the first case\nwith options @code{-} and @code{arg2}, and in the second case with option\n@option{-arg2}.\n\nOctave uses whitespace to interpret such expressions according to the\nfollowing rules:\n\n@itemize @bullet\n@item\nStatements consisting of plain symbols without any operators that are\nseparated only by whitespace are always treated as command syntax:\n\n@example\narg1 arg2 arg3 ... argn\n@end example\n\n@item\nStatements without any whitespace are always treated as function syntax:\n\n@example\n@group\narg1+arg2\narg1&&arg2||arg3\narg1+=arg2*arg3\n@end group\n@end example\n\n@item\nIf the first symbol is a constant (or special-valued named constant pi, i,\nI, j, J, e, NaN, or Inf) followed by a binary operator, the statement is\ntreated as function syntax regardless of any whitespace or what follows the\nsecond symbol:\n\n@example\n@group\n7 -arg2\npi+ arg2\nj * arg2 -arg3\n@end group\n@end example\n\n@item\nIf the first symbol is a function or variable and there is no whitespace\nseparating the operator and the second symbol, the statement is treated\nas command syntax:\n\n@example\n@group\narg1 -arg2\narg1 &&arg2 ||arg3\narg1 +=arg2*arg3\n@end group\n@end example\n\n@item\nAny other whitespace combination will result in the statement being treated\nas function syntax.\n@end itemize\n\nNote 1: If a special-valued named constant has been redefined as a\nvariable, the interpreter will still process the statement with function\nsyntax.\n\nNote 2: Attempting to use a variable as @code{arg1} in a command being\nprocessed as command syntax will result in an error.\n\n\n@node Organization of Functions\n@section Organization of Functions Distributed with Octave\n\nMany of Octave's standard functions are distributed as function files.\nThey are loosely organized by topic, in subdirectories of\n@file{@var{octave-home}/share/octave/@var{version}/m}, to make it easier\nto find them.\n\nThe following is a list of all the function file subdirectories, and the\ntypes of functions you will find there.\n\n@table @file\n@item @@ftp\nClass functions for the FTP object.\n\n@item +containers\nPackage for the containers classes.\n\n@item audio\nFunctions for playing and recording sounds.\n\n@item deprecated\nOut-of-date functions which will eventually be removed from Octave.\n\n@item elfun\nElementary functions, principally trigonometric.\n\n@item general\nMiscellaneous matrix manipulations, like @code{flipud}, @code{rot90},\nand @code{triu}, as well as other basic functions, like\n@code{ismatrix}, @code{narginchk}, etc.\n\n@item geometry\nFunctions related to Delaunay triangulation.\n\n@item gui\nFunctions for GUI elements like dialog, message box, etc.\n\n@item help\nFunctions for Octave's built-in help system.\n\n@item image\nImage processing tools.  These functions require the X Window System.\n\n@item io\nInput-output functions.\n\n@item java\nFunctions related to the Java integration.\n\n@item linear-algebra\nFunctions for linear algebra.\n\n@item miscellaneous\nFunctions that don't really belong anywhere else.\n\n@item ode\nFunctions to solve ordinary differential equations (ODEs).\n\n@item optimization\nFunctions related to minimization, optimization, and root finding.\n\n@item path\nFunctions to manage the directory path Octave uses to find functions.\n\n@item pkg\nPackage manager for installing external packages of functions in Octave.\n\n@item plot\nFunctions for displaying and printing two- and three-dimensional graphs.\n\n@item polynomial\nFunctions for manipulating polynomials.\n\n@item prefs\nFunctions implementing user-defined preferences.\n\n@item set\nFunctions for creating and manipulating sets of unique values.\n\n@item signal\nFunctions for signal processing applications.\n\n@item sparse\nFunctions for handling sparse matrices.\n\n@item specfun\nSpecial functions such as @code{bessel} or @code{factor}.\n\n@item special-matrix\nFunctions that create special matrix forms such as Hilbert or\n@nospell{Vandermonde} matrices.\n\n@item startup\nOctave's system-wide startup file.\n\n@item statistics\nStatistical functions.\n\n@item strings\nMiscellaneous string-handling functions.\n\n@item testfun\nFunctions for performing unit tests on other functions.\n\n@item time\nFunctions related to time and date processing.\n@end table\n"
  },
  {
    "path": "doc/interpreter/genpropdoc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{retval} =} genpropdoc (@var{OBJNAME}, @var{FILENAME})\n##\n## Print FILENAME texinfo source file associated to OBJNAME objects.  This\n## function is meant to be run for generating octave documentation\n## (see doc/interpreter/graphics_properties.mk).\n##\n## All the hard coded documentation is written in getdoc function.  See the\n## comments in getdoc bellow for instruction on how to document a graphics\n## property.\n##\n## @seealso{}\n## @end deftypefn\n\nfunction genpropdoc (objname, fname = \"\", props = {})\n  objnames = {\"root\", \"figure\", \"axes\", \"legend\", ...\n              \"image\", \"light\", \"line\", \"patch\", \"scatter\", \"surface\", ...\n              \"text\", \"uibuttongroup\", \"uicontextmenu\", \"uicontrol\", ...\n              \"uipanel\", \"uimenu\", \"uipushtool\", \"uitable\", ...\n              \"uitoggletool\", \"uitoolbar\"\n             };\n\n  ## Base properties\n  base = getstructure (\"base\");\n\n  ## Object properties\n  if (any (strcmp (objname, objnames)))\n    obj = getstructure (objname, base, props);\n  else\n    error (\"genpropdoc: unknown object %s\", objname);\n  endif\n\n  ## Docstring\n  str = printdoc (objname, obj, ! isempty (props));\n\n  if (! isempty (fname))\n    fid = fopen (fname,  \"w+\");\n    if (fid < 0)\n      error (\"genpropdoc: couldn't open %s.\", fname);\n    endif\n  else\n    fid = stdout;\n  endif\n\n  fprintf (fid, str);\n\n  if (nargin == 2)\n    fclose (fid);\n  endif\n\nendfunction\n\nfunction s = getdoc (objname, field, base)\n  ## Properties are represented by a struct with fields :\n  ##\n  ## -\"doc\": string to be printed verbatim after being expanded\n  ##   through expand_doc function.  Special keywords are:\n  ##   \"__objname__\" : replaced by the current object name;\n  ##   \"__prop__\"    : replaced by the current property name;\n  ##   \"__modemsg__\" : replaced by a message explaining that\n  ##                   the propmode will be toggled to \"manual\".\n  ##   \"__fcnmsg__\"  : replaced by a message explaining where to find\n  ##                   documentation on the form of a callback function.\n  ##   You may also cross reference properties using the label format\n  ##   OBJNAMEPROPERTY, e.g., \"@xref{XREFaxescolor,,axes color property}.\"\n  ##\n  ## -\"valid\": string that describes valid values for the current property.\n  ##   Use \"packopt\" function to join options with \" | \" separator\n  ##   and \"markdef\" to mark default among valid values between curly braces.\n  ##   If not provided, valid values for radio properties are automatically\n  ##   retrieved using set function.\n  ##\n  ## -\"default\": string.  If not provided the default value is automatically\n  ##   retrieved using get function.\n  ##\n  ## -\"printdefault\": a boolean (def. true) that specifies whether the\n  ##   default value should be printed.  It is useful for properties\n  ##   like root \"screendepth\" that default to screen dependent values.\n  ##\n  ## -\"category\": a string that is used to group properties.  Properties\n  ##   without category designations will be defaulted into a \"Miscellaneous\"\n  ##   category.  The \"Miscellaneous\" and (if it is used) the \"Unused\"\n  ##   categories will be sorted to the end of each document.\n\n  packopt = @(c) strjoin (c, \" | \");\n  markdef = @(s) [\"@{\" s \"@}\"];\n\n  ## Some generic templates:\n  valid_color = \"colorspec\";\n  valid_handle = \"graphics handle\";\n  valid_string = \"string\";\n  valid_fcn = packopt ({\"string\", \"function handle\"});\n  valid_cellstring = packopt ({\"string\", \"cell array of strings\"});\n  valid_2elvec = \"two-element vector\";\n  valid_3elvec = \"three-element vector\";\n  valid_4elvec = \"four-element vector\";\n  valid_vecmat = packopt ({\"vector\", \"matrix\"});\n  valid_scalmat = packopt ({\"scalar\", \"matrix\"});\n  valid_scalmatarr = packopt ({\"scalar\", \"matrix\", \"array\"});\n\n  doc_notimpl = \"%s is not yet implemented for __objname__ objects.  \\\n__prop__ is unused.\";\n  doc_unused =  \"__prop__ is unused.\";\n\n  doc_fontangle = \"Control whether the font is italic or normal.\";\n  doc_fontsize = \"Size of the font used for text rendering.  \\\n@xref{XREF__objname__fontunits,,fontunits property}.\";\n  doc_fontname = \"Name of font used for text rendering.  When setting \\\nthis property, the text rendering engine will search for a matching \\\nfont in your system.  If none is found then text is rendered using a \\\ndefault sans serif font (same as the default @qcode{\\\"*\\\"} value).\\n\\n\\\nProgramming Note: On systems that don’t use FontConfig natively \\\n(all but Linux), the font cache is built when Octave is installed.  \\\nYou will need to run @code{system (\\\"fc-cache -fv\\\")} manually after \\\ninstalling new fonts.\";\n  doc_fontunits = \"Units used to interpret the @qcode{\\\"fontsize\\\"} property.\";\n  doc_fontweight = \"Control the variant of the base font used for \\\ntext rendering.\";\n\n  ## Initialize structure\n  if (isfield (base, field))\n    s = base.(field);\n  else\n    s = struct (\"valid\", \"\", \"default\", \"\", \"doc\", \"\", ...\n                \"printdefault\", true, \"category\", \"Miscellaneous\");\n  endif\n\n  ## Base properties: Write generic documentation because it will be included\n  ## in the list of each graphics object.  If a given graphics object\n  ## interprets the property differently than others, then the doc will have\n  ## to be rewritten for this object.\n  if (strcmp (objname, \"base\"))\n    switch (field)\n\n      case \"beingdeleted\"\n        s.doc  = \"Property indicating that a function has initiated deletion \\\nof the object.  __prop__ is set to true until the object no longer exists.\";\n        s.category = \"Creation/Deletion\";\n\n      case \"busyaction\"\n        s.doc = \"Define how Octave handles the execution of this object's \\\ncallback properties when it is unable to interrupt another object's \\\nexecuting callback.  This is only relevant when the currently executing \\\ncallback object has its @code{interruptible} property set to \\\n\\@qcode{\\\"off\\\"}.  The __prop__ property of the interrupting callback object \\\nindicates whether the interrupting callback is queued (@qcode{\\\"queue\\\"} \\\n(default)) or discarded (@qcode{\\\"cancel\\\"}).\\n\\\n@xref{Callbacks,,@w{Callbacks section}}.\";\n        s.category = \"Callback Execution\";\n\n      case \"buttondownfcn\"\n        s.doc = \"__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Mouse Interaction\";\n\n      case \"children\"\n        s.doc = \"Graphics handles of the __objname__'s children.\";\n        s.valid = \"vector of graphics handles\";\n        s.category = \"Parent/Children\";\n\n      case \"clipping\"\n        s.doc = \"If __prop__ is @qcode{\\\"on\\\"}, the __objname__ is \\\nclipped in its parent axes limits.\";\n        s.category = \"Display\";\n\n      case \"contextmenu\"\n        s.doc = \"Graphics handle of the uicontextmenu object that is \\\ncurrently associated to this __objname__ object.\";\n        s.valid = valid_handle;\n        s.category = \"Mouse Interaction\";\n\n      case \"createfcn\"\n        s.doc = \"Callback function executed immediately after __objname__ \\\nhas been created.  Function is set by using default property on root object, \\\ne.g., @code{set (groot, \\\"default__objname__createfcn\\\", \\\n'disp (\\\"__objname__ created!\\\")')}.\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Creation/Deletion\";\n\n      case \"deletefcn\"\n        s.doc = \"Callback function executed immediately before __objname__ \\\nis deleted.\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Creation/Deletion\";\n\n      case \"handlevisibility\"\n        s.doc = \"If __prop__ is @qcode{\\\"off\\\"}, the __objname__'s \\\nhandle is not visible in its parent's @qcode{\\\"children\\\"} property.\";\n        s.category = \"Parent/Children\";\n\n      case \"hittest\"\n        s.doc = \"Specify whether __objname__ processes mouse events \\\nor passes them to ancestors of the object.  When enabled, the object may \\\nrespond to mouse clicks by evaluating the @qcode{\\\"buttondownfcn\\\"}, showing \\\nthe uicontextmenu, and eventually becoming the root \\\n@qcode{\\\"currentobject\\\"}.  This property is only relevant when the object \\\ncan accept mouse clicks which is determined by the @qcode{\\\"pickableparts\\\"} \\\nproperty.  @xref{XREF__objname__pickableparts,,@w{pickableparts property}}.\";\n        s.category = \"Mouse Interaction\";\n\n      case \"interruptible\"\n        s.doc = \"Specify whether this object's callback functions may be \\\ninterrupted by other callbacks.  By default __prop__ is @qcode{\\\"on\\\"} \\\nand callbacks that make use of @code{drawnow}, @code{figure}, @code{waitfor}, \\\n@code{getframe} or @code{pause} functions are eventually interrupted.\\n\\\n@xref{Callbacks,,@w{Callbacks section}}.\";\n        s.category = \"Callback Execution\";\n\n      case \"parent\"\n        s.doc = \"Handle of the parent graphics object.\";\n        s.valid = valid_handle;\n        s.category = \"Parent/Children\";\n\n      case \"pickableparts\"\n        s.doc = \"Specify whether __objname__ will accept mouse clicks.  \\\nBy default, __prop__ is @qcode{\\\"visible\\\"} and only visible parts of the \\\n__objname__ or its children may react to mouse clicks.  When __prop__ is \\\n@qcode{\\\"all\\\"} both visible and invisible parts (or children) may react to \\\nmouse clicks.  When __prop__ is @qcode{\\\"none\\\"} mouse clicks on the object \\\nare ignored and transmitted to any objects underneath this one.  When an \\\nobject is configured to accept mouse clicks the @qcode{\\\"hittest\\\"} property \\\nwill determine how they are processed.  \\\n@xref{XREF__objname__hittest,,@w{hittest property}}.\";\n        s.category = \"Mouse Interaction\";\n\n      case \"selected\"\n        s.doc = \"Property indicates whether this __objname__ is selected.\";\n        s.category = \"Mouse Interaction\";\n\n      case \"selectionhighlight\"\n        s.doc = \"If __prop__ is @qcode{\\\"on\\\"}, then the __objname__'s \\\nselection state is visually highlighted.\";\n        s.category = \"Mouse Interaction\";\n\n      case \"tag\"\n        s.doc = \"A user-defined string to label the graphics object.\";\n        s.valid = valid_string;\n        s.category = \"Object Identification\";\n\n      case \"type\"\n        s.doc = \"Class name of the graphics object.  __prop__ is \\\nalways @qcode{\\\"__objname__\\\"}.\";\n        s.valid = valid_string;\n        s.printdefault = false;\n        s.category = \"Object Identification\";\n\n      case \"userdata\"\n        s.doc = \"User-defined data to associate with the graphics object.\";\n        s.valid = \"Any Octave data\";\n        s.category = \"Object Identification\";\n\n      case \"visible\"\n        s.doc = \"If __prop__ is @qcode{\\\"off\\\"}, the __objname__ is \\\nnot rendered on screen.\";\n        s.category = \"Display\";\n    endswitch\n\n  ## Root properties:\n  elseif (strcmp (objname, \"root\"))\n    switch (field)\n      ## Overridden shared properties\n      case {\"beingdeleted\", \"busyaction\", \"buttondownfcn\", ...\n            \"clipping\", \"createfcn\", \"deletefcn\", ...\n            \"hittest\", \"interruptible\", \"pickableparts\", \"selected\", ...\n            \"selectionhighlight\", \"uicontextmenu\", \"visible\"}\n        s.doc = doc_unused;\n        s.category = \"Unused\";\n\n      case \"handlevisibility\"\n        s.doc = \"The root object handle is always visible.  Changing this \\\nsetting to @qcode{\\\"callback\\\"} or @qcode{\\\"off\\\"} has no effect.\";\n        ## Use base category.\n\n      case \"parent\"\n        s.doc = \"Root object has no parent graphics object.  __prop__ \\\nis always empty.\";\n        ## Use base category.\n\n      ## Specific properties\n      case \"callbackobject\"\n        s.doc = \"Graphics handle of the current object whose callback is \\\nexecuting.\";\n        s.valid = valid_handle;\n        s.category = \"Callback Execution\";\n\n      case \"commandwindowsize\"\n        s.doc = \"The number of columns and rows displayed in a newly created \\\ncommand window.\";\n        s.valid = valid_2elvec;\n        s.category = \"Command Window Display\";\n\n      case \"currentfigure\"\n        s.doc = \"Graphics handle of the current figure.\";\n        s.valid = valid_handle;\n        s.category = \"Object Identification\";\n\n      case \"diary\"\n        s.doc = \"If __prop__ is @qcode{\\\"on\\\"}, the Octave command window \\\nsession is saved to file.  @xref{XREFrootdiaryfile,,@w{diaryfile property}}.\";\n        s.category = \"Command Logging\";\n\n      case \"diaryfile\"\n        s.doc = \"The name of the diary file.  \\\n@xref{XREFdiary,,@w{diary function}}.\";\n        s.valid = valid_string;\n        s.category = \"Command Logging\";\n\n      case \"echo\"\n        s.doc = \"Control whether Octave displays commands executed from \\\nscripts.  @xref{XREFecho,,@w{echo function}}.\";\n        s.category = \"Command Window Display\";\n\n      case \"fixedwidthfontname\"\n        s.doc = \"Name of the fixed-width font that will be used for \\\ngraphics objects when the @qcode{\\\"fontname\\\"} property is set to \\\n@qcode{\\\"FixedWidth\\\"}.\";\n        s.valid = valid_string;\n        s.category = \"Command Window Display\";\n\n      case \"format\"\n        s.doc = \"This property is a wrapper around the @code{format} function.\\\n  @xref{XREFformat,,@w{format function}}.\";\n        s.category = \"Command Window Display\";\n\n      case \"formatspacing\"\n        s.doc = \"This property is a wrapper around the @code{format} function.\\\n  @xref{XREFformat,,@w{format function}}.\";\n        s.category = \"Command Window Display\";\n\n      case \"monitorpositions\"\n        s.doc = \"Reports the width and height of connected monitors.  Note: \\\nOctave only partially implements __prop__.  Only information about the primary \\\nmonitor is stored in __prop__ which is the same information stored in the \\\n@ref{XREFrootscreensize,,@w{@qcode{\\\"screensize\\\"} property}}.\";\n        s.printdefault = false;\n        s.valid = valid_4elvec;\n        s.category = \"Screen Information\";\n\n      case \"pointerlocation\"\n        s.doc = [sprintf(doc_notimpl, \"Global pointer location \\\n        tracking\"), \"  __prop__ for __objname__ objects will always be \\\n        [0 0].\"];\n        s.valid = valid_2elvec;\n        s.category = \"Pointer Information\";\n\n      case \"pointerwindow\"\n        s.doc = [sprintf(doc_notimpl, \"Pointer window tracking\"), ...\n        \"  __prop__ value for __objname__ objects will always be 0.\"];\n        s.valid = valid_handle;\n        s.category = \"Pointer Information\";\n\n      case \"screendepth\"\n        s.doc = \"Color depth in bits per pixel of the display.\";\n        s.valid = \"double\";\n        s.printdefault = false;\n        s.category = \"Screen Information\";\n\n      case \"screenpixelsperinch\"\n        s.doc = \"The screen resolution of the primary display in units of \\\npixels per inch.\";\n        s.valid = \"double\";\n        s.printdefault = false;\n        s.category = \"Screen Information\";\n\n      case \"screensize\"\n        s.doc = \"Size of the primary display represented as the four-element \\\nvector [left, bottom, width, height].\";\n        s.valid = valid_4elvec;\n        s.printdefault = false;\n        s.category = \"Screen Information\";\n\n      case \"showhiddenhandles\"\n        s.doc = \"If __prop__ is @qcode{\\\"on\\\"}, all graphics objects handles \\\nare visible in their parents' children list, regardless of the value of their \\\n@code{handlevisibility} property.\";\n        s.category = \"Parent/Children\";\n\n      case \"units\"\n        s.doc = \"The unit type used for the \\\n@ref{XREFrootmonitorpositions,,@qcode{\\\"monitorpositions\\\"}}, \\\n@ref{XREFrootpointerlocation,,@qcode{\\\"pointerlocation\\\"}}, and \\\n@ref{XREFrootscreensize,,@qcode{\\\"screensize\\\"}} properties.\";\n        s.category = \"Screen Information\";\n\n    endswitch\n\n  ## Figure properties\n  elseif (strcmp (objname, \"figure\"))\n    switch (field)\n      ## Overridden shared properties\n      case {\"clipping\", \"pickableparts\"}\n        s.doc = doc_unused;\n        s.category = \"Unused\";\n\n      ## Specific properties\n      case \"alphamap\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Appearance\";\n\n      case \"closerequestfcn\"\n        s.doc = \"Function that is executed when a figure is deleted.  \\\n@xref{XREFclosereq,,closereq function}.\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Creation/Deletion\";\n\n      case \"color\"\n        s.doc = \"Color of the figure background.  \\\n@xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"colormap\"\n        s.doc = \"A matrix containing the RGB colormap for the current axes.\";\n        s.valid = \"N-by-3 matrix\";\n        s.category = \"Appearance\";\n\n      case \"currentaxes\"\n        s.doc = \"Handle to the graphics object of the current axes.\";\n        s.valid = valid_handle;\n        s.category = \"Object Identification\";\n\n      case \"currentcharacter\"\n        s.doc = sprintf (doc_notimpl, \"Tracking of the last key pressed\");\n        s.category = \"Object Identification\";\n\n      case \"currentobject\"\n        s.doc = \"Handle to the most recently active graphics object in the \\\nfigure.\";\n        s.valid = valid_handle;\n        s.category = \"Object Identification\";\n\n      case \"currentpoint\"\n        s.doc = \"A 1-by-2 vector which holds the coordinates of the point \\\nover which the mouse pointer was when a mouse event occurred.  The X and Y \\\ncoordinates are in units defined by the figure's @code{units} property \\\nand their origin is the lower left corner of the plotting area.\\n\\\n\\n\\\nEvents which set @code{currentpoint} are\\n\\\n@table @asis\\n\\\n@item A mouse button was pressed\\n\\\nalways\\n\\\n@item A mouse button was released\\n\\\nonly if the figure's callback @code{windowbuttonupfcn} is defined\\n\\\n@item The pointer was moved while pressing the mouse button (drag)\\n\\\nonly if the figure's callback @code{windowbuttonmotionfcn} is defined\\n\\\n@end table\";\n        s.valid = valid_2elvec;\n        s.category = \"Mouse Interaction\";\n\n      case \"dockcontrols\"\n        s.doc = sprintf (doc_notimpl, \"Interactive figure docking\");\n        s.category = \"Object Position\";\n\n      case \"filename\"\n        s.doc = \"The filename used when saving the plot figure.\";\n        s.valid = valid_string;\n        s.category = \"Printing/Saving\";\n\n      case \"graphicssmoothing\"\n        s.doc = \"Use smoothing techniques to reduce the appearance of jagged \\\nlines.\";\n        s.category = \"Appearance\";\n\n      case \"innerposition\"\n        s.doc = \"The @qcode{\\\"innerposition\\\"} property is the same as the \\\n@ref{XREFfigureposition,,@w{@qcode{\\\"position\\\"} property}}.\";\n        s.valid = valid_4elvec;\n        s.category = \"Object Position\";\n\n      case \"integerhandle\"\n        s.doc = \"Assign the next lowest unused integer as the Figure number.\";\n        s.category = \"Object Identification\";\n\n      case \"inverthardcopy\"\n        s.doc = \"Replace the figure and axes background color with white when \\\nprinting.\";\n        s.category = \"Printing/Saving\";\n\n      case \"keypressfcn\"\n        s.doc = \"Callback function executed when a key is pressed while the \\\nfigure has focus.  The first argument to the function is the handle of the \\\ncalling figure.  The second argument holds an event structure which has the \\\nfollowing members:\\n\\\n@table @code\\n\\\n@item Character:\\n\\\nThe ASCII value of the key\\n\\\n@item Modifier:\\n\\\nA cell array containing strings representing the modifiers pressed with the \\\nkey.\\n\\\n@item Key:\\n\\\nLowercase description of the key\\n\\\n@item Source:\\n\\\nGraphics handle of the object executing the callback function\\n\\\n@item EventName:\\n\\\n\\\"KeyPress\\\"\\n\\\n@end table\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Keyboard Interaction\";\n\n      case \"keyreleasefcn\"\n        s.doc = \"Callback function executed when a key is release while the \\\nfigure has focus.  The first argument to the function is the handle of the \\\ncalling figure.  The second argument holds an event structure which has the \\\nfollowing members:\\n\\\n@table @code\\n\\\n@item Character:\\n\\\nThe ASCII value of the key\\n\\\n@item Modifier:\\n\\\nA cell array containing strings representing the modifiers pressed with the \\\nkey.\\n\\\n@item Key:\\n\\\nLowercase description of the key\\n\\\n@item Source:\\n\\\nGraphics handle of the object executing the callback function\\n\\\n@item EventName:\\n\\\n\\\"KeyRelease\\\"\\n\\\n@end table\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Keyboard Interaction\";\n\n      case \"menubar\"\n        s.doc = \"Control the display of the figure menu bar at the top \\\nof the figure.\";\n        s.category = \"Mouse Interaction\";\n\n      case \"name\"\n        s.doc = \"Name to be displayed in the figure title bar.  The name is \\\ndisplayed to the right of any title determined by the @code{numbertitle} \\\nproperty.\";\n        s.valid = valid_string;\n        s.category = \"Appearance\";\n\n      case \"nextplot\"\n        s.doc = \"__prop__ is used by high level plotting functions to \\\ndecide what to do with axes already present in the figure.  \\\n@xref{XREFnewplot,,@w{newplot function}}.\";\n        s.category = \"Object Identification\";\n\n      case \"number\"\n        s.doc = \"Number of the current __objname__.\";\n        s.valid = \"double\";\n        s.category = \"Object Identification\";\n\n      case \"numbertitle\"\n        s.doc = \"Display @qcode{\\\"Figure\\\"} followed by the numerical figure \\\nhandle value in the figure title bar.\";\n        s.category = \"Appearance\";\n\n      case \"outerposition\"\n        s.doc = \"Specify the position and size of the figure including \\\nthe top menubar and the bottom status bar.  \\\nThe four elements of the vector are the coordinates of the lower left corner \\\nand width and height of the figure.  \\\n@xref{XREFfigureunits,,@w{units property}}.\";\n        s.valid = valid_4elvec;\n        s.category = \"Object Position\";\n\n      case \"paperorientation\"\n        s.doc = \"The value for the @code{papersize}, and @code{paperposition} \\\nproperties depends upon __prop__.  The horizontal and vertical values for \\\n@code{papersize} and @code{paperposition} reverse order \\\nwhen __prop__ is switched between @code{\\\"portrait\\\"} and \\\n@code{\\\"landscape\\\"}.\";\n        s.category = \"Printing/Saving\";\n\n      case \"paperposition\"\n        s.doc = \"Vector @code{[left bottom width height]} defining the \\\nposition and size of the figure (in @code{paperunits} units) on the printed \\\npage.  The position @code{[left bottom]} defines the lower left corner of the \\\nfigure on the page, and the size is defined by @code{[width height]}.  For \\\noutput formats not implicitly rendered on paper, @code{width} and \\\n@code{height} define the size of the image and the position information is \\\nignored.  __modemsg__\";\n        s.valid = valid_4elvec;\n        s.category = \"Printing/Saving\";\n\n      case \"paperpositionmode\"\n        s.doc = \"If __prop__ is set to @qcode{\\\"auto\\\"}, the \\\n@code{paperposition} property is automatically computed: the printed \\\nfigure will have the same size as the on-screen figure and will be centered \\\non the output page.  Setting the __prop__ to @code{\\\"auto\\\"} does not modify \\\nthe value of the @code{paperposition} property.\";\n        s.category = \"Printing/Saving\";\n\n      case \"papersize\"\n        s.doc = \"Vector @code{[width height]} defining the size of the \\\npaper for printing.  Setting the __prop__ property to a value, not associated \\\nwith one of the defined @code{papertypes} and consistent with the setting for \\\n@code{paperorientation}, forces the @code{papertype} property to the value \\\n@qcode{\\\"<custom>\\\"}.  If __prop__ is set to a value associated with a \\\nsupported @code{papertype} and consistent with the @code{paperorientation}, \\\nthe @code{papertype} value is modified to the associated value.\";\n        s.valid = valid_2elvec;\n        s.category = \"Printing/Saving\";\n\n      case \"papertype\"\n        s.doc = \"Name of the paper used for printed output.  \\\nSetting __prop__ also changes @code{papersize}, while maintaining consistency \\\nwith the @code{paperorientation} property.\";\n        s.category = \"Printing/Saving\";\n\n      case \"paperunits\"\n        s.doc = \"The unit used to compute the @code{paperposition} property.  \\\nThe conversion from physical units (e.g., @code{\\\"inches\\\"}) is dependent on \\\nthe @code{screenpixelsperinch} property of the root object.\";\n        s.category = \"Printing/Saving\";\n\n      case \"pointer\"\n        s.doc = \"Name of the mouse pointer shape associated with the canvas \\\nof the figure.  When __prop__ is @qcode{\\\"custom\\\"}, the shape is determined \\\nby the @code{pointershapecdata} property.\\n\\n\\\n__prop__ has no effect when the figure is in zoom, pan, or rotate mode.  \\\nIn this case, Octave automatically uses a pointer shape appropriate \\\nto the mode.\";\n        s.category = \"Mouse Interaction\";\n\n      case \"pointershapecdata\"\n        s.doc = \"m-by-m matrix defining a custom pointer.  Each \\\nelement defines a pixel with the element (1,1) representing the \\\ntop-left pixel.  A value of 1 is colored black, a value of 2 is colored white, \\\nand all other values are rendered as transparent.\";\n        s.valid = \"16-by-16 or 32-by-32 Matrix\";\n        s.category = \"Mouse Interaction\";\n\n      case \"pointershapehotspot\"\n        s.doc = \"For custom pointers only __prop__ defines the row and \\\ncolumn of the pixel in @code{pointershapecdata} that is used as the pointer \\\nlocation.\";\n        s.valid = valid_2elvec;\n        s.category = \"Mouse Interaction\";\n\n      case \"position\"\n        s.doc = \"Specify the position and size of the figure canvas.  \\\nThe four elements of the vector are the coordinates of the lower left corner \\\nand width and height of the figure.  \\\n@xref{XREFfigureunits,,@w{units property}}.\";\n        s.valid = valid_4elvec;\n        s.category = \"Object Position\";\n\n      case \"renderer\"\n        s.doc = \"Rendering engine used for printing when @code{renderermode} \\\nis @qcode{\\\"manual\\\"}.  __modemsg__\";\n        s.category = \"Printing/Saving\";\n\n      case \"renderermode\"\n        s.doc = \"Control whether the rendering engine used for printing is \\\nchosen automatically or specified by the @code{renderer} property.  \\\n@xref{XREFprint,,@w{print function}}.\";\n        s.category = \"Printing/Saving\";\n\n      case \"resize\"\n        s.doc = \"Control whether the figure can be resized by dragging the \\\nwindow borders and corners using a mouse.  When __prop__ is @qcode{\\\"off\\\"} \\\nmouse interactions are disabled but the figure can still be resized by \\\nchanging its @qcode{\\\"position\\\"} property.\";\n        s.category = \"Mouse Interaction\";\n\n      case \"resizefcn\"\n        s.doc = \"__prop__ is deprecated.  Use @code{sizechangedfcn} instead.\";\n        s.valid = valid_fcn;\n        s.category = \"Mouse Interaction\";\n\n      case \"selectiontype\"\n        s.doc = \"Selection type of the latest mouse click.\\n\\n\\\n__prop__ may take different values depending on the combination of mouse \\\nbutton and keyboard modifier that were used:\\n\\\n@table @code\\n\\\n@item normal:\\n\\\nLeft-click.\\n\\\n@item alt:\\n\\\nRight-click or Ctrl+Left-click.\\n\\\n@item extend:\\n\\\nShift+Left-click, Middle click, or combined Left-click and Right-click.\\n\\\n@item open:\\n\\\nDouble Left-click.\\n\\\n@end table\";\n        s.category = \"Mouse Interaction\";\n\n      case \"sizechangedfcn\"\n        s.doc = \"Callback triggered when the figure window size is changed.\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Mouse Interaction\";\n\n      case \"toolbar\"\n        s.doc = \"Control the display of the toolbar (along the bottom of the \\\nmenubar) and the status bar.  When set to @qcode{\\\"auto\\\"}, the display is \\\nbased on the value of the @ref{XREFfiguremenubar,,@qcode{\\\"menubar\\\"}} \\\nproperty.\";\n        s.category = \"Mouse Interaction\";\n\n      case \"units\"\n        s.doc = \"The unit used to compute the \\\n@ref{XREFfigureposition,,position} and \\\n@ref{XREFfigureouterposition,,outerposition} properties.\";\n        s.category = \"Object Position\";\n\n      case \"windowbuttondownfcn\"\n        s.doc = \"@xref{XREFfigurewindowbuttonupfcn,,\\\n@w{windowbuttonupfcn property}}.\";\n        s.valid = valid_fcn;\n        s.category = \"Mouse Interaction\";\n\n      case \"windowbuttonmotionfcn\"\n        s.doc = \"@xref{XREFfigurewindowbuttonupfcn,,\\\n@w{windowbuttonupfcn property}}.\";\n        s.valid = valid_fcn;\n        s.category = \"Mouse Interaction\";\n\n      case \"windowbuttonupfcn\"\n        s.doc = \"With @code{windowbuttondownfcn} and \\\n@code{windowbuttonmotionfcn}, the mouse callback functions.  These \\\ncallback functions are called when a mouse button is pressed, dragged, or \\\nreleased respectively.  When these callback functions are executed, the \\\n@code{currentpoint} property holds the current coordinates of the cursor.\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Mouse Interaction\";\n\n      case \"windowkeypressfcn\"\n        s.doc = \"Function that is executed when a key is pressed and \\\nthe figure has focus.\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Keyboard Interaction\";\n\n      case \"windowkeyreleasefcn\"\n        s.doc = \"Function that is executed when a key is released and \\\nthe figure has focus.\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Keyboard Interaction\";\n\n      case \"windowscrollwheelfcn\"\n        s.doc = \"Function that is executed when a user manipulates \\\nthe mouse wheel over this figure.  \\\nThe function is called with two input arguments.  The first \\\nargument holds the handle of the calling figure.  The second argument holds \\\nan event structure which has the following members:\\n\\\n@table @code\\n\\\n@item VerticalScrollCount:\\n\\\nThe number of wheel steps, typically 1 when scrolling down and -1 when \\\nscrolling up.\\n\\\n@item VerticalScrollAmount:\\n\\\nThe number of lines a wheel step should scroll.  This value is always 3.\\n\\\n@item EventName:\\n\\\nThe event name which is @qcode{\\\"WindowScrollWheel\\\"}.\\n\\\n@end table\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Mouse Interaction\";\n\n      case \"windowstate\"\n        s.doc = sprintf (doc_notimpl, \"Window state adjustment\");\n        s.category = \"Display\";\n\n      case \"windowstyle\"\n        s.doc = \"The window style of a figure.  One of the following values:\\n\\\n@table @code\\n\\\n@item normal\\n\\\nThe window may be unselected and other windows may be shown in front of the \\\nwindow.\\n\\\n@item modal\\n\\\nThe window will stay on top of all normal figures until it is dismissed.\\n\\\n@item docked\\n\\\nUnimplemented.\\n\\\n@end table\\n\\\n\\n\\\nChanging modes of a visible figure may cause the figure to close and reopen.\";\n        s.category = \"Display\";\n\n    endswitch\n\n  ## Axes properties\n  elseif (strcmp (objname, \"axes\") || strcmp (objname, \"legend\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"clipping\"\n        s.doc = sprintf (doc_notimpl, \"Axes-children clipping control\");\n        ## Use base category.\n\n      ## Specific properties\n      case \"alim\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Color and Transparency\";\n\n      case \"alimmode\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Color and Transparency\";\n\n      case \"alphamap\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Color and Transparency\";\n\n      case \"alphascale\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Color and Transparency\";\n\n      case \"ambientlightcolor\"\n        s.doc = sprintf (doc_notimpl, \"Uniform background axes lighting\");\n        s.category = \"Color and Transparency\";\n\n      case \"box\"\n        s.doc = \"Control whether the __objname__ has a surrounding box.\";\n        if (strcmp (objname, \"legend\"))\n          s.category = \"Legend Appearance\";\n        else\n          s.category = \"Axes Box Appearance\";\n        endif\n\n      case \"boxstyle\"\n        s.doc = \"For 3-D axes, control whether the @qcode{\\\"full\\\"} \\\nbox is drawn or only the 3 @qcode{\\\"back\\\"} axes.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"cameraposition\"\n        s.doc = \"Coordinates of the camera position viewing the \\\n__objname__.  __modemsg__\";\n        s.valid = valid_3elvec;\n        s.category = \"Camera and View Controls\";\n\n      case \"camerapositionmode\"\n        s.doc = \"Current state of the camera position property, whether \\\nautomatically set according to the @ref{XREFview,,view function}, or \\\nmanually set with the \\\n@ref{XREFaxescameraposition,,@w{@qcode{\\\"cameraposition\\\"} property}}.\";\n        s.category = \"Camera and View Controls\";\n\n      case \"cameratarget\"\n        s.doc = \"Coordinates of the point at which the viewing camera is \\\naimed.  __modemsg__\";\n        s.valid = valid_3elvec;\n        s.category = \"Camera and View Controls\";\n\n      case \"cameratargetmode\"\n        s.doc = \"Current state of camera target property, either manually \\\nset with the \\\n@ref{XREFaxescameratarget,,@w{@qcode{\\\"cameratarget\\\"} property}} or \\\nautomatically positioned at the center of the axes plot area.\";\n        s.category = \"Camera and View Controls\";\n\n      case \"cameraupvector\"\n        s.doc = \"A 3-element vector defining the upward direction of the \\\ncurrent view.  Note that the default is [0 1 0] for 2-D plots and [0 0 1] for \\\n3-D plots.  __modemsg__\";\n        s.valid = valid_3elvec;\n        s.category = \"Camera and View Controls\";\n\n      case \"cameraupvectormode\"\n        s.doc = \"Current state of camera up vector property, set to manual \\\nwhen the \\\n@ref{XREFaxescameraupvector,,@w{@qcode{\\\"cameraupvector\\\"} property}} is \\\nused to change the vector from the 2-D or 3-D default values.\";\n        s.category = \"Camera and View Controls\";\n\n      case \"cameraviewangle\"\n        s.doc = \"The camera's field of view defined as an angle between 0 \\\nand 180 degrees.  __modemsg__\";\n        s.valid = \"scalar\";\n        s.category = \"Camera and View Controls\";\n\n      case \"cameraviewanglemode\"\n        s.doc = \"Current state of the camera view angle property, either \\\nmanually set with the \\\n@ref{XREFaxescameraviewangle,,@w{@qcode{\\\"cameraviewangle\\\"} property}} \\\nor automatically set by Octave to include all visible objects.\";\n        s.category = \"Camera and View Controls\";\n\n      case \"clim\"\n        s.doc = \"Define limits for the color axis of __objname__ \\\nchildren that have the @code{cdata} property.  \\\n__modemsg__\";\n        s.valid = valid_2elvec;\n        s.category = \"Color and Transparency\";\n\n      case \"climmode\"\n        s.doc = \"Current state of the color limit mode, either \\\nmanually set by the \\\n@ref{XREFaxesclim,,@w{@qcode{\\\"clim\\\"} property}} or automatically set by \\\nOctave to the minimum and maximum @code{cdata} values of __objname__'s \\\nchildren.\";\n        s.category = \"Color and Transparency\";\n\n      case \"clippingstyle\"\n        s.doc = sprintf (doc_notimpl, \"Axes-children clipping control\");\n        s.category = \"Display\";\n\n      case \"color\"\n        s.doc = \"Color of the __objname__ background.  \\\n@xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n        if (strcmp (objname, \"legend\"))\n          s.category = \"Legend Appearance\";\n        else\n          s.category = \"Axes Box Appearance\";\n        endif\n\n      case \"colormap\"\n        s.doc = \"A matrix containing the RGB colormap for this __objname__ \\\nobject.\";\n        s.valid = \"N-by-3 matrix\";\n        s.category = \"Color and Transparency\";\n\n      case \"colororder\"\n        s.doc = \"RGB values used by plot function for child object coloring.\";\n        s.valid = \"N-by-3 RGB matrix\";\n        s.category = \"Automatic Child Properties\";\n\n      case \"colororderindex\"\n        s.doc = \"Index of the next color from the \\\n@ref{XREFaxescolororder,,@w{@qcode{\\\"colororder\\\"} property}} to be used \\\nby Axes-child objects.\";\n        s.valid = \"integer\";\n        s.category = \"Automatic Child Properties\";\n\n      case \"colorscale\"\n        s.doc = sprintf (doc_notimpl, \"Automatic linear/log color scaling\");\n        s.category = \"Color and Transparency\";\n\n      case \"currentpoint\"\n        s.doc = \"Matrix @code{[xf, yf, zf; xb, yb, zb]} which holds the \\\ncoordinates (in axes data units) of the point over which the mouse pointer \\\nwas when the mouse button was pressed.  If a mouse callback function is \\\ndefined, @code{currentpoint} holds the pointer coordinates at the time \\\nthe mouse button was pressed.  For 3-D plots, the first row of the returned \\\nmatrix specifies the point nearest to the current camera position and the \\\nsecond row the furthest point.  The two points forms a line which is \\\nperpendicular to the screen.\";\n        s.valid = \"2-by-3 matrix\";\n        s.category = \"Mouse Interaction\";\n\n      case \"dataaspectratio\"\n        s.doc = \"Specify the relative height and width of the data \\\ndisplayed in the axes.  Setting @code{dataaspectratio} to \\\n@w{@code{[1, 2]}} causes the length of one unit as displayed on the x-axis \\\nto be the same as the length of 2 units on the y-axis.  \\\n@xref{XREFdaspect,,daspect function}.  __modemsg__\";\n        s.valid = valid_3elvec;\n        s.category = \"Axes Box Appearance\";\n\n      case \"dataaspectratiomode\"\n        s.doc = \"Current state of the data aspect ratio mode, either \\\nmanually set by the \\\n@ref{XREFaxesdataaspectratio,,@w{@qcode{\\\"dataaspectratio\\\"} property}} or \\\nautomatically set by Octave in combination with other display properties to \\\nfit the data in the current view.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"fontangle\"\n        s.doc = doc_fontangle;\n        s.category = \"Text Appearance\";\n\n      case \"fontname\"\n        s.doc = doc_fontname;\n        s.valid = valid_string;\n        s.category = \"Text Appearance\";\n\n      case \"fontsize\"\n        s.doc = [doc_fontsize, \"  __modemsg__\"];\n        s.valid = \"scalar\";\n        s.category = \"Text Appearance\";\n\n      case \"fontsizemode\"\n        s.doc = \"Current state of the fontsize mode, either manually set by \\\nthe @ref{XREFaxesfontsize,,@w{@qcode{\\\"fontsize\\\"} property}} or \\\nautomatically set by Octave to maintain readability.\";\n        s.category = \"Text Appearance\";\n\n      case \"fontsmoothing\"\n        s.doc = \"Control whether any text associated with __objname__ is \\\nanti-aliased.\";\n        s.category = \"Text Appearance\";\n\n      case \"fontunits\"\n        s.doc = doc_fontunits;\n        s.category = \"Text Appearance\";\n\n      case \"fontweight\"\n        s.doc = doc_fontweight;\n        s.category = \"Text Appearance\";\n\n      case \"gridalpha\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Axes Grid Appearance\";\n\n      case \"gridalphamode\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Axes Grid Appearance\";\n\n      case \"gridcolor\"\n        s.doc = \"Color of the major grid lines.  \\\n@xref{Colors,,colorspec}.  __modemsg__\";\n        s.valid = packopt ({markdef(valid_color), \"@qcode{\\\"none\\\"}\"});\n        s.category = \"Axes Grid Appearance\";\n\n      case \"gridcolormode\"\n        s.doc = \"Current state of the gridcolor mode, either manually set by \\\nthe @ref{XREFaxesgridcolor,,@w{@qcode{\\\"gridcolor\\\"} property}} or \\\nautomatically set by Octave to the default value.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"gridlinestyle\"\n        s.doc = \"@xref{Line Styles}.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"innerposition\"\n        s.doc = \"The @qcode{\\\"innerposition\\\"} property is the same as the \\\n@ref{XREFaxesposition,,@w{@qcode{\\\"position\\\"} property}}.\";\n        s.valid = valid_4elvec;\n        s.category = \"Axes Grid Appearance\";\n\n      case \"interactions\"\n        s.doc = sprintf (doc_notimpl, \"Interaction objects\");\n        s.category = \"Callback Execution\";\n\n      case \"labelfontsizemultiplier\"\n        s.doc = \"Ratio between the x/y/zlabel fontsize and the tick label \\\nfontsize.\";\n        s.category = \"Text Appearance\";\n\n      case \"layer\"\n        s.doc = \"Control whether the axes is drawn below child graphics \\\nobjects (ticks, labels, etc.@: covered by plotted objects) or above.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"layout\"\n        s.doc = sprintf (doc_notimpl, \"Tiled and gridded chart layout\");\n        s.category = \"Axes Box Appearance\";\n\n      case \"legend\"\n        s.doc = [sprintf(doc_notimpl, \"Legend property control\"), \"  Use \\\nthe @ref{XREFlegend,,legend function} to set legend properties.\"];\n        s.category = \"Text Appearance\";\n\n      case \"linestyleorder\"\n        s.doc = \"List of linestyles to be used in order by axes child \\\nobjects, specified as a cell array of line specification strings.  Note that \\\nthe linestyle is only incremented after cycling through the full \\\n@ref{XREFaxescolororder,,@qcode{\\\"colororder\\\"}} list.  \\\n@xref{Line Styles}.\";\n        s.category = \"Automatic Child Properties\";\n\n      case \"linestyleorderindex\"\n        s.doc = \"Index of the next linestyle from the \\\n@ref{XREFaxeslinestyleorder,,@w{@qcode{\\\"linestyleorder\\\"} property}} to \\\nbe used by Axes-child objects.\";\n        s.valid = \"whole number scalar\";\n        s.category = \"Automatic Child Properties\";\n\n      case \"linewidth\"\n        s.doc = \"Width of the main axes lines.\";\n        s.valid = \"scalar\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"minorgridalpha\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Axes Grid Appearance\";\n\n      case \"minorgridalphamode\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Axes Grid Appearance\";\n\n      case \"minorgridcolor\"\n        s.doc = \"Color of the minor grid lines.  \\\n@xref{Colors,,colorspec}.  __modemsg__\";\n        s.valid = packopt ({markdef(valid_color), \"@qcode{\\\"none\\\"}\"});\n        s.category = \"Axes Grid Appearance\";\n\n      case \"minorgridcolormode\"\n        s.doc = \"Current state of the minorgridcolor mode, either manually \\\nset by the \\\n@ref{XREFaxesminorgridcolor,,@w{@qcode{\\\"minorgridcolor\\\"} property}} or \\\nautomatically set by Octave to the default value.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"minorgridlinestyle\"\n        s.doc = \"@xref{Line Styles}.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"mousewheelzoom\"\n        s.doc = \"Fraction of axes limits to zoom for each wheel movement.\";\n        s.valid = \"scalar in the range (0, 1)\";\n        s.category = \"Mouse Interaction\";\n\n      case \"nextplot\"\n        s.doc = \"__prop__ is used by high level plotting functions to \\\ndecide what to do with graphics objects already present in the axes.  \\\n@xref{XREFnewplot,,@w{newplot function}}.  The state of __prop__ \\\nis typically controlled using the @code{hold} function.  \\\n@xref{XREFhold,,@w{hold function}}.\";\n        s.category = \"Object Identification\";\n\n      case \"nextseriesindex\"\n        s.doc = \"Current index value into the \\\n@ref{XREFaxescolororder,,\\\"colororder\\\"} and \\\n@ref{XREFaxeslinestyleorder,,\\\"linestyleorder\\\"} \\\nproperties, indicating the item that will be used by the next child object\";\n        s.valid = \"whole number scalar\";\n        s.category = \"Automatic Child Properties\";\n\n      case \"outerposition\"\n        s.doc = \"Specify the position of the plot including titles, \\\naxes, and legend.  The four elements of the vector are the \\\ncoordinates of the lower left corner and width and height of the \\\nplot, in units normalized to the width and height of the plot \\\nwindow.  For example, @code{[0.2, 0.3, 0.4, 0.5]} sets the lower \\\nleft corner of the axes at @math{(0.2, 0.3)} and the width and \\\nheight to be 0.4 and 0.5 respectively.  \\\n@xref{XREFaxesposition,,@w{position property}}.\";\n        s.valid = valid_4elvec;\n        s.category = \"Object Position\";\n\n      case \"plotboxaspectratio\"\n        s.doc = \"@xref{XREFpbaspect,,pbaspect function}.  __modemsg__\";\n        s.category = \"Object Position\";\n\n      case \"plotboxaspectratiomode\"\n        s.doc = \"Current state of the plot box aspect ratio mode, either \\\nmanually set by the \\\n@ref{XREFaxesdataaspectratio,,@w{@qcode{\\\"dataaspectratio\\\"} property}} or \\\nautomatically set by Octave in combination with other display properties to \\\nfit the data in the current view.\";\n        s.category = \"Object Position\";\n\n      case \"position\"\n        if (strcmp (objname, \"legend\"))\n          s.doc = \"Specify the position of the legend excluding its title.  \\\nThe four elements of the vector are the coordinates of the lower left corner \\\nand width and height of the legend.  Changing this property also \\\nswitches the @qcode{\\\"location\\\"} to @qcode{\\\"none\\\"}.\";\n          s.printdefault = false;\n\n        else\n          s.doc = \"Specify the position of the plot excluding titles, \\\naxes, and legend.  The four elements of the vector are the \\\ncoordinates of the lower left corner and width and height of the \\\nplot, in units normalized to the width and height of the plot \\\nwindow.  For example, @code{[0.2, 0.3, 0.4, 0.5]} sets the lower \\\nleft corner of the axes at @math{(0.2, 0.3)} and the width and \\\nheight to be 0.4 and 0.5 respectively.  \\\n@xref{XREFaxesouterposition,,@w{outerposition property}}.\";\n        endif\n        s.valid = valid_4elvec;\n        s.category = \"Object Position\";\n\n      case \"positionconstraint\"\n        s.doc = \"Specify which of @qcode{\\\"innerposition\\\"} or \\\n@qcode{\\\"outerposition\\\"} properties takes precedence when axes \\\nannotations extent changes.  \\\n@xref{XREFaxesinnerposition,,@w{\\\"innerposition\\\" property}}, \\\nand @ref{XREFaxesouterposition,,@w{\\\"outerposition\\\" property}}.\";\n        s.category = \"Object Position\";\n\n      case \"projection\"\n        s.doc = sprintf (doc_notimpl, \"Orthographic/perspective projection \\\nadjustment\");\n        s.category = \"Camera and View Controls\";\n\n      case \"sortmethod\"\n        s.doc = sprintf (doc_notimpl, \"Child display order control\");\n        s.category = \"Parent/Children\";\n\n      case \"tickdir\"\n        s.doc = \"Control whether axes tick marks project @qcode{\\\"in\\\"} to \\\nthe plot box or @qcode{\\\"out\\\"}.  The value @qcode{\\\"both\\\"} will draw tick \\\nmarks both in and out.  The value @qcode{\\\"none\\\"} means no tick marks will \\\nbe drawn, although tick labels will still be rendered.  __modemsg__  Note \\\nthat the default is @qcode{\\\"in\\\"} for 2-D and @qcode{\\\"out\\\"} for 3-D \\\nplots.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"tickdirmode\"\n        s.doc = \"Current state of the tickdir mode, either manually set by \\\nthe @ref{XREFaxestickdir,,@w{@qcode{\\\"tickdir\\\"} property}} or \\\nautomatically set to the default for the current view.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"ticklabelinterpreter\"\n        s.doc = \"Control the way x/y/zticklabel properties are interpreted.\\n\\\n@xref{Use of the \\\"interpreter\\\" Property,,@w{Use of the @qcode{\\\"interpreter\\\"} Property}}.\";\n        s.category = \"Text Appearance\";\n\n      case \"ticklength\"\n        s.doc = \"Two-element vector @code{[2Dlen 3Dlen]} specifying the \\\nlength of the tickmarks relative to the longest visible axis.\";\n        s.valid = valid_2elvec;\n        s.category = \"Axes Box Appearance\";\n\n      case \"tightinset\"\n        s.doc = \"Size of the @code{[left bottom right top]} margins around \\\nthe axes that enclose labels and title annotations.\";\n        s.valid = valid_4elvec;\n        s.printdefault = false;\n        s.category = \"Text Appearance\";\n\n      case \"title\"\n        s.doc = \"Graphics handle of the title text object.\";\n        s.valid = valid_handle;\n        s.category = \"Object Identification\";\n\n      case \"titlefontsizemultiplier\"\n        s.doc = \"Ratio between the title fontsize and the tick label \\\nfontsize.\";\n        s.valid = \"positive scalar\";\n        s.category = \"Text Appearance\";\n\n      case \"titlefontweight\"\n        s.doc = \"Control variant of base font used for the axes title.\";\n        s.category = \"Text Appearance\";\n\n      case \"toolbar\"\n        s.doc = [sprintf(doc_notimpl, \"AxesToolbar objects\")];\n        s.category = \"Axes Box Appearance\";\n\n      case \"units\"\n        if (strcmp (objname, \"legend\"))\n          s.doc = \"Units used to interpret the @qcode{\\\"position\\\"} \\\nproperty.\";\n        else\n          s.doc = \"Units used to interpret the @qcode{\\\"position\\\"}, \\\n@qcode{\\\"outerposition\\\"}, and @qcode{\\\"tightinset\\\"} properties.\";\n        endif\n        s.category = \"Object Position\";\n\n      case \"view\"\n        s.doc = \"Two-element vector @code{[azimuth elevation]} specifying \\\nthe viewpoint for three-dimensional plots.\";\n        s.valid = valid_2elvec;\n        s.category = \"Camera and View Controls\";\n\n      case \"xaxis\"\n        s.doc = [sprintf(doc_notimpl, \"Axes Ruler objects\")];\n        s.category = \"Axes Box Appearance\";\n\n      case \"xaxislocation\"\n        s.doc = \"Control the x-axis location.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"xcolor\"\n        s.doc = \"Color of the x-axis.  @xref{Colors,,colorspec}.  \\\n__modemsg__\";\n        s.valid = packopt ({markdef(valid_color), \"@qcode{\\\"none\\\"}\"});\n        s.category = \"Axes Box Appearance\";\n\n      case \"xcolormode\"\n        s.doc = \"Current state of the setting determining the color that is \\\napplied to the x-axis grid lines.  If set to @qcode{\\\"auto\\\"} and/or the \\\n@ref{XREFaxesgridcolormode,,@w{@qcode{\\\"gridcolormode\\\"} property}} is set \\\nto @qcode{\\\"manual\\\"}, the x-axis grid color will be defined by the \\\n@ref{XREFaxesgridcolor,,@w{@qcode{\\\"gridcolor\\\"} property}}.  Otherwise \\\nthe x-axis grid color will be defined by the \\\n@ref{XREFaxesxcolor,,@w{@qcode{\\\"xcolor\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"xdir\"\n        s.doc = \"Direction of the x-axis: @qcode{\\\"normal\\\"} is left to \\\nright in default 2-D and 3-D views.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"xgrid\"\n        s.doc = \"Control whether major x grid lines are displayed.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"xlabel\"\n        s.doc = \"Graphics handle of the x label text object.\";\n        s.valid = valid_handle;\n        s.category = \"Text Appearance\";\n\n      case \"xlim\"\n        s.doc = \"Two-element vector @code{[xmin xmax]} specifying the limits \\\nfor the x-axis.  __modemsg__   @xref{XREFxlim,,@w{xlim function}}.\";\n        s.valid = valid_2elvec;\n        s.category = \"Axes Box Appearance\";\n\n      case \"xlimitmethod\"\n        s.doc = \"Method used to determine the x-axis limits when the \\\n@code{xlimmode} property is @qcode{\\\"auto\\\"}.  The default value, \\\n@qcode{\\\"tickaligned\\\"} makes limits align with the closest ticks.  With \\\nvalue @qcode{\\\"tight\\\"} the limits are adjusted to enclose all the graphics \\\nobjects in the axes, while with value @qcode{\\\"padded\\\"}, an additional \\\nmargin of about 7%% of the data extent is added around the objects.  \\\n@xref{XREFaxis,,@w{axis function}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"xlimmode\"\n        s.doc = \"Current state of the x-axis limit selection method, either \\\nmanually set with the @ref{XREFaxesxlim,,@w{@qcode{\\\"xlim\\\"} property}} \\\nor automatically set to span the plotted data according to the \\\n@ref{XREFaxesxlimitmethod,,@w{@qcode{\\\"xlimitmethod\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"xminorgrid\"\n        s.doc = \"Control whether minor x grid lines are displayed.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"xminortick\"\n        s.doc = \"Control whether minor x tick marks are displayed.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"xminortickvalues\"\n        s.doc = \"Position of minor tick marks.  __modemsg__\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"xminortickvaluesmode\"\n        s.doc = \"Setting to determine whether the xminortick locations and \\\nspacing are set automatically by Octave or manually using the \\\n@ref{XREFaxesxminortickvalues,,@w{@qcode{\\\"xminortickvalues\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"xscale\"\n        s.doc = \"Set the x-axis to a linear or logarithmic scale.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"xtick\"\n        s.doc = \"Position of x tick marks.  __modemsg__\";\n        s.valid = \"vector\";\n        s.printdefault = false;\n        s.category = \"Axes Box Appearance\";\n\n      case \"xticklabel\"\n        s.doc = \"Labels of x tick marks.  __modemsg__\";\n        s.valid = valid_cellstring;\n        s.category = \"Text Appearance\";\n\n      case \"xticklabelmode\"\n        s.doc = \"Setting to determine whether the xtick labels are set \\\nautomatically by Octave or manually using the \\\n@ref{XREFaxesxticklabel,,@w{@qcode{\\\"xticklabel\\\"} property}}.\";\n        s.category = \"Text Appearance\";\n\n      case \"xticklabelrotation\"\n        s.doc = [sprintf(doc_notimpl, \"Axis label rotation\")];\n        s.category = \"Text Appearance\";\n\n      case \"xtickmode\"\n        s.doc = \"Setting to determine whether the xtick locations and \\\nspacing are set automatically by Octave or manually using the \\\n@ref{XREFaxesxtick,,@w{@qcode{\\\"xtick\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"yaxis\"\n        s.doc = [sprintf(doc_notimpl, \"Axes Ruler objects\")];\n        s.category = \"Axes Box Appearance\";\n\n      case \"yaxislocation\"\n        s.doc = \"Control the y-axis location.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"ycolor\"\n        s.doc = \"Color of the y-axis.  @xref{Colors,,colorspec}.\";\n        s.valid = packopt ({markdef(valid_color), \"@qcode{\\\"none\\\"}\"});\n        s.category = \"Axes Box Appearance\";\n\n      case \"ycolormode\"\n        s.doc = \"Current state of the setting determining the color that is \\\napplied to the y-axis grid lines.  If set to @qcode{\\\"auto\\\"} and/or the \\\n@ref{XREFaxesgridcolormode,,@w{@qcode{\\\"gridcolormode\\\"} property}} is set \\\nto @qcode{\\\"manual\\\"}, the y-axis grid color will be defined by the \\\n@ref{XREFaxesgridcolor,,@w{@qcode{\\\"gridcolor\\\"} property}}.  Otherwise \\\nthe y-axis grid color will be defined by the \\\n@ref{XREFaxesycolor,,@w{@qcode{\\\"ycolor\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"ydir\"\n        s.doc = \"Direction of the y-axis: @qcode{\\\"normal\\\"} is bottom \\\nto top in 2-D and front to back in 3-D default views.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"ygrid\"\n        s.doc = \"Control whether major y grid lines are displayed.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"ylabel\"\n        s.doc = \"Graphics handle of the y label text object.\";\n        s.valid = valid_handle;\n        s.category = \"Text Appearance\";\n\n      case \"ylim\"\n        s.doc = \"Two-element vector @code{[ymin ymax]} specifying the limits \\\nfor the y-axis.  __modemsg__  @xref{XREFylim,,@w{ylim function}}.\";\n        s.valid = valid_2elvec;\n        s.category = \"Axes Box Appearance\";\n\n      case \"ylimitmethod\"\n        s.doc = \"Method used to determine the y-axis limits when the \\\n@code{xlimmode} property is @qcode{\\\"auto\\\"}.  The default value, \\\n@qcode{\\\"tickaligned\\\"} makes limits align with the closest ticks.  With \\\nvalue @qcode{\\\"tight\\\"} the limits are adjusted to enclose all the graphics \\\nobjects in the axes, while with value @qcode{\\\"padded\\\"}, an additional \\\nmargin of about 7%% of the data extent is added around the objects.  \\\n@xref{XREFaxis,,@w{axis function}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"ylimmode\"\n        s.doc = \"Current state of the y-axis limit selection method, either \\\nmanually set with the @ref{XREFaxesylim,,@w{@qcode{\\\"ylim\\\"} property}} \\\nor automatically set to span the plotted data according to the \\\n@ref{XREFaxesylimitmethod,,@w{@qcode{\\\"ylimitmethod\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"yminorgrid\"\n        s.doc = \"Control whether minor y grid lines are displayed.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"yminortick\"\n        s.doc = \"Control whether minor y tick marks are displayed.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"yminortickvalues\"\n        s.doc = \"Position of minor tick marks.  __modemsg__\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"yminortickvaluesmode\"\n        s.doc = \"Setting to determine whether the yminortick locations and \\\nspacing are set automatically by Octave or manually using the \\\n@ref{XREFaxesyminortickvalues,,@w{@qcode{\\\"yminortickvalues\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"yscale\"\n        s.doc = \"Set the y-axis to a linear or logarithmic scale.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"ytick\"\n        s.doc = \"Position of y tick marks.  __modemsg__\";\n        s.valid = \"vector\";\n        s.printdefault = false;\n        s.category = \"Axes Box Appearance\";\n\n      case \"yticklabel\"\n        s.doc = \"Labels of y tick marks.  __modemsg__\";\n        s.valid = valid_cellstring;\n        s.category = \"Text Appearance\";\n\n      case \"yticklabelmode\"\n        s.doc = \"Setting to determine whether the ytick labels are set \\\nautomatically by Octave or manually using the \\\n@ref{XREFaxesyticklabel,,@w{@qcode{\\\"yticklabel\\\"} property}}.\";\n        s.category = \"Text Appearance\";\n\n      case \"yticklabelrotation\"\n        s.doc = [sprintf(doc_notimpl, \"Axis label rotation\")];\n        s.category = \"Text Appearance\";\n\n      case \"ytickmode\"\n        s.doc = \"Setting to determine whether the ytick locations and \\\nspacing are set automatically by Octave or manually using the \\\n@ref{XREFaxesytick,,@w{@qcode{\\\"ytick\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"zaxis\"\n        s.doc = [sprintf(doc_notimpl, \"Axes Ruler objects\")];\n        s.category = \"Axes Box Appearance\";\n\n      case \"zcolor\"\n        s.doc = \"Color of the z-axis.  @xref{Colors,,colorspec}.\";\n        s.valid = packopt ({markdef(valid_color), \"@qcode{\\\"none\\\"}\"});\n        s.category = \"Axes Box Appearance\";\n\n      case \"zcolormode\"\n        s.doc = \"Current state of the setting determining the color that is \\\napplied to the z-axis grid lines.  If set to @qcode{\\\"auto\\\"} and/or the \\\n@ref{XREFaxesgridcolormode,,@w{@qcode{\\\"gridcolormode\\\"} property}} is set \\\nto @qcode{\\\"manual\\\"}, the z-axis grid color will be defined by the \\\n@ref{XREFaxesgridcolor,,@w{@qcode{\\\"gridcolor\\\"} property}}.  Otherwise \\\nthe z-axis grid color will be defined by the \\\n@ref{XREFaxeszcolor,,@w{@qcode{\\\"zcolor\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"zdir\"\n        s.doc = \"Direction of the z-axis: @qcode{\\\"normal\\\"} is bottom \\\nto top in default 3-D views.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"zgrid\"\n        s.doc = \"Control whether major z grid lines are displayed.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"zlabel\"\n        s.doc = \"Graphics handle of the z label text object.\";\n        s.valid = valid_handle;\n        s.category = \"Text Appearance\";\n\n      case \"zlim\"\n        s.doc = \"Two-element vector @code{[zmin zmax]} specifying the limits \\\nfor the z-axis.  __modemsg__  @xref{XREFzlim,,@w{zlim function}}.\";\n        s.valid = valid_2elvec;\n        s.category = \"Axes Box Appearance\";\n\n      case \"zlimitmethod\"\n        s.doc = \"Method used to determine the z-axis limits when the \\\n@code{xlimmode} property is @qcode{\\\"auto\\\"}.  The default value, \\\n@qcode{\\\"tickaligned\\\"} makes limits align with the closest ticks.  With \\\nvalue @qcode{\\\"tight\\\"} the limits are adjusted to enclose all the graphics \\\nobjects in the axes, while with value @qcode{\\\"padded\\\"}, an additional \\\nmargin of about 7%% of the data extent is added around the objects.  \\\n@xref{XREFaxis,,@w{axis function}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"zlimmode\"\n        s.doc = \"Current state of the z-axis limit selection method, either \\\nmanually set with the @ref{XREFaxeszlim,,@w{@qcode{\\\"zlim\\\"} property}} \\\nor automatically set to span the plotted data according to the \\\n@ref{XREFaxeszlimitmethod,,@w{@qcode{\\\"zlimitmethod\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"zminorgrid\"\n        s.doc = \"Control whether minor z grid lines are displayed.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"zminortick\"\n        s.doc = \"Control whether minor z tick marks are displayed.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"zminortickvalues\"\n        s.doc = \"Position of minor tick marks.  __modemsg__\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"zminortickvaluesmode\"\n        s.doc = \"Setting to determine whether the zminortick locations and \\\nspacing are set automatically by Octave or manually using the \\\n@ref{XREFaxeszminortickvalues,,@w{@qcode{\\\"zminortickvalues\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      case \"zscale\"\n        s.doc = \"Set the z-axis to a linear or logarithmic scale.\";\n        s.category = \"Axes Grid Appearance\";\n\n      case \"ztick\"\n        s.doc = \"Position of z tick marks.  __modemsg__\";\n        s.valid = \"vector\";\n        s.printdefault = false;\n        s.category = \"Axes Box Appearance\";\n\n      case \"zticklabel\"\n        s.doc = \"Labels of z tick marks.  __modemsg__\";\n        s.valid = valid_cellstring;\n        s.category = \"Text Appearance\";\n\n      case \"zticklabelmode\"\n        s.doc = \"Setting to determine whether the ztick labels are set \\\nautomatically by Octave or manually using the \\\n@ref{XREFaxeszticklabel,,@w{@qcode{\\\"zticklabel\\\"} property}}.\";\n        s.category = \"Text Appearance\";\n\n      case \"zticklabelrotation\"\n        s.doc = [sprintf(doc_notimpl, \"Axis label rotation\")];\n        s.category = \"Text Appearance\";\n\n      case \"ztickmode\"\n        s.doc = \"Setting to determine whether the ztick locations and \\\nspacing are set automatically by Octave or manually using the \\\n@ref{XREFaxesztick,,@w{@qcode{\\\"ztick\\\"} property}}.\";\n        s.category = \"Axes Box Appearance\";\n\n      ## Legend specific properties\n      case \"autoupdate\"\n        s.doc = \"Control whether the number of legend items is updated \\\nautomatically when objects are added to (or deleted from) the peer axes.\\n\\\nFor example:\\n\\\n@example\\n\\\n@group\\n\\\n## Create a single plot with its legend.\\n\\\nfigure ();\\n\\\nplot (1:10);\\n\\\nlegend (\\\"Slope 1\\\");\\n\\\n## Add another plot and specify its displayname so that\\n\\\n## the legend is correctly updated.\\n\\\nhold on;\\n\\\nplot ((1:10) * 2, \\\"displayname\\\", \\\"Slope 2\\\");\\n\\\n## Stop automatic updates for further plots.\\n\\\nlegend (\\\"autoupdate\\\", \\\"off\\\");\\n\\\nplot ((1:10) * 3);\\n\\\n@end group\\n\\\n@end example\";\n        s.category = \"Layout\";\n\n      case \"edgecolor\"\n        s.doc = \"Control the color of the legend outline.\";\n        s.valid = valid_color;\n        s.category = \"Legend Appearance\";\n\n      case \"itemhitfcn\"\n        s.doc = \"Callback function which is executed when a legend item \\\nis clicked.  @xref{Callbacks,,@w{Callbacks section}}.\\n\\\n\\n\\\nThe callback function must have the following prototype \\\n@code{fcn (hlegend, evnt)}, where @code{hlegend} is the legend object handle \\\nand @code{evnt} is a structure with the following fields:\\n\\\n@table @code\\n\\\n@item Peer\\n\\\nHandle of the plot object to which the clicked item is associated.\\n\\\n@item Region\\n\\\nMay be @qcode{\\\"icon\\\"} or @qcode{\\\"label\\\"} depending on which part of \\\nthe item is clicked.\\n\\\n@item SelectionType\\n\\\nOne of @qcode{\\\"normal\\\"}, @qcode{\\\"extend\\\"}, @qcode{\\\"open\\\"}, or \\\n@qcode{\\\"alt\\\"}.  \\\n@xref{XREFfigureselectiontype,,@w{Figure @qcode{\\\"selectiontype\\\"}}}.\\n\\\n@item Source\\n\\\nHandle of the legend object.\\n\\\n@item EventName\\n\\\nName is @qcode{\\\"ItemHit\\\"}.\\n\\\n@end table\";\n        s.category = \"Callback Execution\";\n\n      case \"location\"\n        s.doc = \"Control the location of the legend.\";\n        s.category = \"Object Position\";\n\n      case \"numcolumns\"\n        s.doc = \"Control the number of columns used in the layout of the \\\nlegend items.  \\\nFor example:\\n\\\n@example\\n\\\n@group\\n\\\nfigure ();\\n\\\nplot (rand (30));\\n\\\nlegend (\\\"numcolumns\\\", 3);\\n\\\n@end group\\n\\\n@end example\\n\\\n__modemsg__\";\n        s.valid = \"scalar integer\";\n        s.category = \"Layout\";\n\n      case \"orientation\"\n        s.doc = \"Control whether the legend items are arranged vertically \\\n(column-wise) or horizontally (row-wise).\";\n        s.category = \"Layout\";\n\n      case \"string\"\n        s.doc = \"List of labels for the legend items.  For example:\\n\\\n@example\\n\\\n@group\\n\\\nfigure ();\\n\\\nplot (rand (20));\\n\\\n## Let legend choose names automatically\\n\\\nhl = legend ();\\n\\\n## Selectively change some names\\n\\\nstr = get (hl, \\\"string\\\");\\n\\\nstr(1:5:end) = \\\"Garbage\\\";\\n\\\nset (hl, \\\"string\\\", str);\\n\\\n@end group\\n\\\n@end example\";\n        s.valid = valid_cellstring;\n        s.printdefault = false;\n        s.category = \"Text Appearance\";\n\n      case \"textcolor\"\n        s.doc = \"Control the color of the text strings for legend items.\";\n        s.valid = valid_color;\n        s.category = \"Text Appearance\";\n\n      case \"textposition\"\n        s.doc = \"Control whether text strings are displayed on the left or \\\nright of their corresponding icon.\";\n        s.category = \"Text Appearance\";\n\n    endswitch\n\n  ## Line properties\n  elseif (strcmp (objname, \"line\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"children\"\n        s.doc = sprintf (doc_notimpl, \"Child objects for lines\");\n        ## Use base category.\n\n      ## Specific properties\n      case \"color\"\n        s.doc = \"Color of the line object.  @xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n        s.category = \"Line Appearance\";\n\n      case \"displayname\"\n        s.doc = \"Text for the legend entry corresponding to this line.\";\n        s.valid = valid_cellstring;\n        s.category = \"Legend Options\";\n\n      case \"linestyle\"\n        s.doc = \"@xref{Line Styles}.\";\n        s.category = \"Line Appearance\";\n\n      case \"linewidth\"\n        s.doc = \"Width of the line object measured in points.\";\n        s.valid = \"scalar\";\n        s.category = \"Line Appearance\";\n\n      case \"linejoin\"\n        s.doc = \"Control the shape of the junction of line segments.  \\\nThis property currently only affects the printed output.\";\n        s.category = \"Line Appearance\";\n\n      case \"marker\"\n        s.doc = \"Shape of the marker for each data point.  \\\n@xref{Marker Styles}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markeredgecolor\"\n        s.doc = \"Color of the edge of the markers.  When set to \\\n@qcode{\\\"auto\\\"}, the marker edges have the same color as the line.  If set \\\nto @qcode{\\\"none\\\"}, no marker edges are displayed.  This property can also \\\nbe set to any color.  @xref{Colors,,colorspec}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markerfacecolor\"\n        s.doc = \"Color of the face of the markers.  When set to \\\n@qcode{\\\"auto\\\"}, the marker faces have the same color as the line.  If set \\\nto @qcode{\\\"none\\\"}, the marker faces are not displayed.  This property \\\ncan also be set to any color.  @xref{Colors,,colorspec}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markersize\"\n        s.doc = \"Size of the markers measured in points.\";\n        s.valid = \"scalar\";\n        s.category = \"Marker Appearance\";\n\n      case \"xdata\"\n        s.doc = \"Vector of x data to be plotted.\";\n        s.valid = \"vector\";\n        s.category = \"Coordinate Data\";\n\n      case \"xdatasource\"\n        s.doc = \"Name of a vector in the current base workspace to use as \\\nx data.\";\n        s.valid = valid_string;\n        s.category = \"Coordinate Data\";\n\n      case \"ydata\"\n        s.doc = \"Vector of y data to be plotted.\";\n        s.valid = \"vector\";\n        s.category = \"Coordinate Data\";\n\n      case \"ydatasource\"\n        s.doc = \"Name of a vector in the current base workspace to use as \\\ny data.\";\n        s.valid = valid_string;\n        s.category = \"Coordinate Data\";\n\n      case \"zdata\"\n        s.doc = \"Vector of z data to be plotted.\";\n        s.valid = \"vector\";\n        s.category = \"Coordinate Data\";\n\n      case \"zdatasource\"\n        s.doc = \"Name of a vector in the current base workspace to use as \\\nz data.\";\n        s.valid = valid_string;\n        s.category = \"Coordinate Data\";\n\n    endswitch\n\n  ## Text properties\n  elseif (strcmp (objname, \"text\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"children\"\n        s.doc = [\"__objname__ objects have no child objects.  \", doc_unused];\n        ## Use base category.\n\n      ## Specific properties\n      case \"backgroundcolor\"\n        s.doc = \"Color of the background area.  @xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n        s.category = \"Text Box Appearance\";\n\n      case \"color\"\n        s.doc = \"Color of the text.  @xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n        s.category = \"Text Appearance\";\n\n      case \"edgecolor\"\n        s.doc = \"Color of the outline of the background area.  \\\n@xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n        s.category = \"Text Box Appearance\";\n\n      case \"editing\"\n        s.doc = sprintf (doc_notimpl, \"Interactive text editing\");\n        s.category = \"Text Appearance\";\n\n      case \"extent\"\n        s.doc = \"Vector @code{[x0 y0 width height]} indicating the size and \\\nlocation of the text string.\";\n        s.valid = valid_4elvec;\n        s.printdefault = false;\n        s.category = \"Object Position\";\n\n      case \"fontangle\"\n        s.doc = doc_fontangle;\n        s.category = \"Text Appearance\";\n\n      case \"fontname\"\n        s.doc = doc_fontname;\n        s.valid = valid_string;\n        s.category = \"Text Appearance\";\n\n      case \"fontsmoothing\"\n        s.doc = \"Control whether anti-aliasing is used when rendering text.\";\n        s.category = \"Text Appearance\";\n\n      case \"fontsize\"\n        s.doc = doc_fontsize;\n        s.valid = \"scalar\";\n        s.category = \"Text Appearance\";\n\n      case \"fontunits\"\n        s.doc = doc_fontunits;\n        s.category = \"Text Appearance\";\n\n      case \"fontweight\"\n        s.doc = doc_fontweight;\n        s.category = \"Text Appearance\";\n\n      case \"horizontalalignment\"\n        s.doc = \"Specifies the horizontal location of the point set by the \\\n@ref{XREFtextposition,,@w{@qcode{\\\"position\\\"} property}} relative to the \\\ntext.\";\n        s.category = \"Object Position\";\n\n      case \"interpreter\"\n        s.doc = \"Control the way the @qcode{\\\"string\\\"} property is \\\ninterpreted.\\n\\\n@xref{Use of the \\\"interpreter\\\" Property,,@w{Use of the @qcode{\\\"interpreter\\\"} Property}}.\";\n        s.category = \"Text Appearance\";\n\n      case \"linestyle\"\n        s.doc = \"Style of the text box outline.  @xref{Line Styles}.\";\n        s.category = \"Text Box Appearance\";\n\n      case \"linewidth\"\n        s.doc = \"Width of the text box outline.\";\n        s.valid = \"scalar\";\n        s.category = \"Text Box Appearance\";\n\n      case \"margin\"\n        s.doc = \"Margins between the borders of the background area \\\nand the texts.  The value is currently interpreted as pixels, regardless \\\nof the @qcode{\\\"fontunits\\\"} property.\";\n        s.valid = \"scalar\";\n        s.category = \"Text Box Appearance\";\n\n      case \"position\"\n        s.doc = \"Vector @code{[X0 Y0 Z0]} where X0, Y0, and Z0 indicate the \\\nposition of the text anchor as defined by @code{verticalalignment} and \\\n@code{horizontalalignment}.\";\n        s.valid = valid_3elvec;\n        s.category = \"Object Position\";\n\n      case \"rotation\"\n        s.doc = \"The angle of rotation for the displayed text, measured in \\\ndegrees.\";\n        s.valid = \"scalar\";\n        s.category = \"Object Position\";\n\n      case \"string\"\n        s.doc = \"The __objname__ object string content.\";\n        s.valid = valid_string;\n        s.category = \"Text Appearance\";\n\n      case \"units\"\n        s.doc = \"Sets the measurement unit or method applied to the \\\n@ref{XREFtextposition,,@qcode{\\\"position\\\"}} and \\\n@ref{XREFtextextent,,@qcode{\\\"extent\\\"}} properties.  The default \\\noption @qcode{\\\"data\\\"} uses the same units and limits as the data plotted in \\\nthe figure.  The @qcode{\\\"normalized\\\"} option applies a unitless 0 to 1 scale \\\nto the limits along each axis of the displayed data.\";\n        s.category = \"Object Position\";\n\n      case \"verticalalignment\"\n        s.doc = \"Specifies the vertical location of the point set by the \\\n@ref{XREFtextposition,,@w{@qcode{\\\"position\\\"} property}} relative to the \\\ntext.  Note that @qcode{\\\"top\\\"} and @qcode{\\\"bottom\\\"} align to the edge of \\\nthe text box while @qcode{\\\"cap\\\"} and @qcode{\\\"baseline\\\"} refer to the edges \\\nof the text itself.\";\n        s.category = \"Object Position\";\n\n    endswitch\n\n  ## Image properties\n  elseif (strcmp (objname, \"image\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"children\"\n        s.doc = sprintf (doc_notimpl, \"Child objects of Images\");\n        ## Use base category.\n\n      ## Specific properties\n      case \"alphadata\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.valid = valid_scalmat;\n        s.category = \"Image Data\";\n\n      case \"alphadatamapping\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Image Data\";\n\n      case \"cdata\"\n        s.doc = \"Color data for the image object.  Data is either stored as \\\na 2-D matrix where each element's value determines that pixel's color \\\naccording to the current colormap, or as a 3-D array where the third \\\ndimension contains separate red, blue, and green components for each pixel.  \\\nFor RGB arrays, the values that map to minimum and maximum color value \\\ndepend on the class of @qcode{\\\"cdata\\\"}.  Floating point and logical values \\\nrange from 0 to 1 while integer value range from @code{intmin} to \\\n@code{intmax} for that integer class.\";\n        s.valid = \"array\";\n        s.category = \"Image Data\";\n\n      case \"cdatamapping\"\n        s.doc = \"Sets the method for mapping data from the \\\n@ref{XREFimagecdata,,@w{@qcode{\\\"cdata\\\"} property}} to the current \\\ncolormap.  @qcode{\\\"Direct\\\"} mapping selects the color using the \\\n@qcode{\\\"cdata\\\"} value as an index to the current colormap.  \\\n@qcode{\\\"Scaled\\\"} mapping scales the @qcode{\\\"cdata\\\"} values to the range \\\nspecified in the @ref{XREFaxesclim,,@w{@qcode{\\\"clim\\\"} axes property}}.\";\n        s.category = \"Image Data\";\n\n      case \"displayname\"\n        s.doc = \"Text for the legend entry corresponding to this image.\";\n        s.valid = valid_cellstring;\n        s.category = \"Legend Options\";\n\n      case \"xdata\"\n        s.doc = \"Two-element vector @code{[xfirst xlast]} specifying the x \\\ncoordinates of the centers of the first and last columns of the image.\\n\\\n\\n\\\nSetting @code{xdata} to the empty matrix ([]) will restore the default value \\\nof @code{[1 columns(image)]}.\";\n        s.valid = valid_2elvec;\n        s.category = \"Image Data\";\n\n      case \"ydata\"\n        s.doc = \"Two-element vector @code{[yfirst ylast]} specifying the y \\\ncoordinates of the centers of the first and last rows of the image.\\n\\\n\\n\\\nSetting @code{ydata} to the empty matrix ([]) will restore the default value \\\nof @code{[1 rows(image)]}.\";\n        s.valid = valid_2elvec;\n        s.category = \"Image Data\";\n\n    endswitch\n\n  ## Surface properties\n  elseif (strcmp (objname, \"surface\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"children\"\n        s.doc = sprintf (doc_notimpl, \"Child objects for Surfaces\");\n        ## Use base category.\n\n      ## Specific properties\n      case \"alphadata\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.valid = valid_scalmat;\n        s.category = \"Color and Transparency\";\n\n      case \"alphadatamapping\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Color and Transparency\";\n\n      case \"ambientstrength\"\n        s.doc = \"Strength of the ambient light.  Value between 0.0 and 1.0.\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"backfacelighting\"\n        s.doc = \"@qcode{\\\"lit\\\"}: The normals are used as is for lighting.  \\\n@qcode{\\\"reverselit\\\"}: The normals are always oriented towards the point of \\\nview.  @qcode{\\\"unlit\\\"}: Faces with normals pointing away from the point of \\\nview are unlit.\";\n        s.category = \"Lighting\";\n\n      case \"cdata\"\n        s.doc = \"Color data values for __objname__ vertices.  Data is stored \\\neither as a 2-D matrix the same size as \\\n@ref{XREFsurfacezdata,,@qcode{\\\"zdata\\\"}} where each element's value \\\ndetermines that vertex's color according to the current colormap, or as a \\\n3-D array where the third dimension contains separate red, blue, and green \\\ncomponents for each vertex.\";\n        s.valid = \"array\";\n        s.category = \"Color and Transparency\";\n\n      case \"cdatamapping\"\n        s.doc = \"Sets the method for mapping data from the \\\n@ref{XREFsurfacecdata,,@w{@qcode{\\\"cdata\\\"} property}} to the current \\\ncolormap.  @qcode{\\\"Direct\\\"} mapping selects the color using the \\\n@qcode{\\\"cdata\\\"} value as an index to the current colormap.  \\\n@qcode{\\\"Scale\\\"} mapping scales the @qcode{\\\"cdata\\\"} values to the range \\\nspecified in the @ref{XREFaxesclim,,@w{@qcode{\\\"clim\\\"} axes property}}.\";\n        s.category = \"Color and Transparency\";\n\n      case \"cdatasource\"\n        s.doc = \"The name of a workspace variable that contains data that \\\nwill be used for the \\\n@ref{XREFsurfacecdata,,@w{@qcode{\\\"cdata\\\"} property}}.  Data is \\\ntransferred into @qcode{\\\"cdata\\\"} using the \\\n@ref{XREFrefreshdata,,@w{refreshdata function}}.\";\n        s.valid = valid_string;\n        s.category = \"Color and Transparency\";\n\n      case \"diffusestrength\"\n        s.doc = \"Strength of the diffuse reflection.  Value between 0.0 (no \\\ndiffuse reflection) and 1.0 (full diffuse reflection).\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"displayname\"\n        s.doc = \"Text for the legend entry corresponding to this surface.\";\n        s.category = \"Legend Options\";\n\n      case \"edgealpha\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.valid = \"scalar\";\n        s.category = \"Outline Appearance\";\n\n      case \"edgecolor\"\n        s.doc = \"Color of the edges of the __objname__ object, specified as \\\neither a valid color specification or one of @qcode{\\\"none\\\"}, \\\n@qcode{\\\"flat\\\"}, or @qcode{\\\"interp\\\"}.  @qcode{\\\"flat\\\"} and \\\n@qcode{\\\"interp\\\"} will set either a single color for each edge or a color \\\ninterpolated between two adjacent vertices using the color value data stored \\\nin @ref{XREFsurfacecdata,,@qcode{\\\"cdata\\\"}}.  \\\n@xref{Colors,,colorspec}.\";\n        s.valid = packopt ({valid_color, ...\n                            \"@qcode{\\\"none\\\"}\", ...\n                            \"@qcode{\\\"flat\\\"}\", ...\n                            \"@qcode{\\\"interp\\\"}\"});\n        s.category = \"Outline Appearance\";\n\n      case \"edgelighting\"\n        s.doc = \"When set to a value other than @qcode{\\\"none\\\"}, the edges \\\nof the object are drawn with light and shadow effects.  Supported values are \\\n@qcode{\\\"none\\\"} (no lighting effects), @qcode{\\\"flat\\\"} (faceted look), and \\\n@qcode{\\\"gouraud\\\"} (linear interpolation of the lighting effects between \\\nthe vertices).  @qcode{\\\"phong\\\"} is deprecated and has the same effect as \\\n@qcode{\\\"gouraud\\\"}.\";\n        s.category = \"Outline Appearance\";\n\n      case \"facealpha\"\n        s.doc = \"Transparency level of the faces of the surface object.  Only \\\ndouble values are supported at present where a value of 0 means complete \\\ntransparency and a value of 1 means solid faces without transparency.  Setting \\\nthe property to @qcode{\\\"flat\\\"}, @qcode{\\\"interp\\\"} or @qcode{\\\"texturemap\\\"} \\\ncauses the faces to not being rendered.  Additionally, the faces are not \\\nsorted from back to front which might lead to unexpected results when \\\nrendering layered transparent faces.\";\n        s.valid = packopt ({\"scalar\", ...\n                            \"@qcode{\\\"flat\\\"}\", ...\n                            \"@qcode{\\\"interp\\\"}\", ...\n                            \"@qcode{\\\"texturemap\\\"}\"});\n        s.category = \"Faces Appearance\";\n\n      case \"facecolor\"\n        s.doc = \"Color of the faces of the __objname__ object, specified as \\\neither a valid color specification or one of @qcode{\\\"none\\\"}, \\\n@qcode{\\\"flat\\\"}, or @qcode{\\\"interp\\\"}.  @qcode{\\\"flat\\\"} and \\\n@qcode{\\\"interp\\\"} will set either a single color for each face or a color \\\ninterpolated across the face's vertices using the color value data stored in \\\n@ref{XREFsurfacecdata,,@qcode{\\\"cdata\\\"}}.  \\\n@xref{Colors,,colorspec}.\";\n        s.valid = packopt ({valid_color, ...\n                            \"@qcode{\\\"none\\\"}\", ...\n                            \"@qcode{\\\"flat\\\"}\", ...\n                            \"@qcode{\\\"interp\\\"}\"});\n        s.category = \"Faces Appearance\";\n\n      case \"facelighting\"\n        s.doc = \"When set to a value other than @qcode{\\\"none\\\"}, the faces \\\nof the object are drawn with light and shadow effects.  Supported values are \\\n@qcode{\\\"none\\\"} (no lighting effects), @qcode{\\\"flat\\\"} (faceted look), and \\\n@qcode{\\\"gouraud\\\"} (linear interpolation of the lighting effects between \\\nthe vertices).  @qcode{\\\"phong\\\"} is deprecated and has the same effect as \\\n@qcode{\\\"gouraud\\\"}.\";\n        s.category = \"Faces Appearance\";\n\n      case \"facenormals\"\n        s.doc = \"Face normals are used for lighting the edges or faces if the \\\n@code{edgelighting} or @code{facelighting} properties are set to \\\n@qcode{\\\"flat\\\"}.  __modemsg__\";\n        s.category = \"Faces Appearance\";\n\n      case \"facenormalsmode\"\n        s.doc = \"If this property is set to @qcode{\\\"auto\\\"}, \\\n@code{facenormals} are automatically calculated if the @code{edgelighting} or \\\n@code{facelighting} property are set to @qcode{\\\"flat\\\"} and at least one \\\n@code{light} object is present and visible in the same axes.\";\n        s.category = \"Faces Appearance\";\n\n      case \"linestyle\"\n        s.doc = \"@xref{Line Styles}.\";\n        s.category = \"Outline Appearance\";\n\n      case \"linewidth\"\n        s.doc = \"@xref{XREFlinelinewidth,,@w{line linewidth property}}.\";\n        s.valid = \"scalar\";\n        s.category = \"Outline Appearance\";\n\n      case \"marker\"\n        s.doc = \"@xref{Marker Styles}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markeredgecolor\"\n        s.doc = \"@xref{XREFlinemarkeredgecolor,,\\\n@w{line markeredgecolor property}}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markerfacecolor\"\n        s.doc = \"@xref{XREFlinemarkerfacecolor,,\\\n@w{line markerfacecolor property}}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markersize\"\n        s.doc = \"@xref{XREFlinemarkersize,,\\\n@w{line markersize property}}.\";\n        s.valid = \"scalar\";\n        s.category = \"Marker Appearance\";\n\n      case \"meshstyle\"\n        s.doc = \"Specifies whether to display the edges associated with the \\\n        surface data's rows, columns, or both.\";\n        s.category = \"Outline Appearance\";\n\n      case \"specularcolorreflectance\"\n        s.doc = \"Reflectance for specular color.  Value between 0.0 (color \\\nof underlying face) and 1.0 (color of light source).\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"specularexponent\"\n        s.doc = \"Exponent for the specular reflection.  The lower the value, \\\nthe more the reflection is spread out.\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"specularstrength\"\n        s.doc = \"Strength of the specular reflection.  Value between 0.0 (no \\\nspecular reflection) and 1.0 (full specular reflection).\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"vertexnormals\"\n        s.doc = \"Vertex normals are used for lighting the edges or faces if \\\nthe @code{edgelighting} or @code{facelighting} properties are set to \\\n@qcode{\\\"gouraud\\\"}.  __modemsg__\";\n        s.category = \"Lighting\";\n\n      case \"vertexnormalsmode\"\n        s.doc = \"If this property is set to @qcode{\\\"auto\\\"}, \\\n@code{vertexnormals} are automatically calculated if the @code{edgelighting} \\\nor @code{facelighting} property are set to @qcode{\\\"gouraud\\\"} and at least \\\none @code{light} object is present and visible in the same axes.\";\n        s.category = \"Lighting\";\n\n      case \"xdata\"\n        s.doc = \"Data for the x-coordinate.\";\n        s.valid = \"matrix\";\n        s.category = \"Coordinate Data\";\n\n      case \"xdatasource\"\n        s.doc = \"The name of a workspace variable that contains data that \\\nwill be used for the \\\n@ref{XREFsurfacexdata,,@w{@qcode{\\\"xdata\\\"} property}}.  Data is \\\ntransferred into @qcode{\\\"xdata\\\"} using the \\\n@ref{XREFrefreshdata,,@w{refreshdata function}}.\";\n        s.valid = valid_string;\n        s.category = \"Coordinate Data\";\n\n      case \"ydata\"\n        s.doc = \"Data for the y-coordinate.\";\n        s.valid = \"matrix\";\n        s.category = \"Coordinate Data\";\n\n      case \"ydatasource\"\n        s.doc = \"The name of a workspace variable that contains data that \\\nwill be used for the \\\n@ref{XREFsurfaceydata,,@w{@qcode{\\\"ydata\\\"} property}}.  Data is \\\ntransferred into @qcode{\\\"ydata\\\"} using the \\\n@ref{XREFrefreshdata,,@w{refreshdata function}}.\";\n        s.valid = valid_string;\n        s.category = \"Coordinate Data\";\n\n      case \"zdata\"\n        s.doc = \"Data for the z-coordinate.\";\n        s.valid = \"matrix\";\n        s.category = \"Coordinate Data\";\n\n      case \"zdatasource\"\n        s.doc = \"The name of a workspace variable that contains data that \\\nwill be used for the \\\n@ref{XREFsurfacezdata,,@w{@qcode{\\\"zdata\\\"} property}}.  Data is \\\ntransferred into @qcode{\\\"zdata\\\"} using the \\\n@ref{XREFrefreshdata,,@w{refreshdata function}}.\";\n        s.valid = valid_string;\n        s.category = \"Coordinate Data\";\n\n    endswitch\n\n  ## Patch properties\n  elseif (strcmp (objname, \"patch\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"children\"\n        s.doc = sprintf (doc_notimpl, \"Child objects for Patch objects\");\n        ## Use base category.\n\n      ## Specific properties\n      case \"alphadatamapping\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.category = \"Color and Transparency\";\n\n      case \"ambientstrength\"\n        s.doc = \"Strength of the ambient light.  Value between 0.0 and 1.0.\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"backfacelighting\"\n        s.doc =  \"@qcode{\\\"lit\\\"}: The normals are used as is for lighting.  \\\n@qcode{\\\"reverselit\\\"}: The normals are always oriented towards the point of \\\nview.  @qcode{\\\"unlit\\\"}: Faces with normals pointing away from the point of \\\nview are unlit.\";\n        s.category = \"Lighting\";\n\n      case \"cdata\"\n        s.doc = \"Data defining the patch object color relative to its \\\nx/y/z-coordinate data.  Patch color can be defined using indices into the \\\ncurrent colormap or as RGB triplets, where the RGB colors are defined along \\\nthe third dimension.  These colors can be separately defined for the entire \\\npatch object, for individual faces, or for individual vertices, and is \\\ndetermined by the shape of @qcode{\\\"cdata\\\"} as follows:\\n\\\n\\n\\\nIf @qcode{\\\"cdata\\\"} is a scalar index into the current colormap or a 1-by-1-by-3 \\\nRGB triplet, it defines the color of all faces and edges.\\n\\\n\\n\\\nIf the patch object has N faces, and @qcode{\\\"cdata\\\"} is a 1-by-N vector of \\\ncolormap indices or a 1-by-N-by-3 RGB array, it defines the color of each \\\nface.\\n\\\n\\n\\\nIf the patch object has N faces and M vertices per face, and @code{cdata} is \\\na M-by-N matrix of colormap indices or a M-by-N-by-3 RGB array, it defines \\\nthe color at each vertex. (The shape of @qcode{\\\"cdata\\\"} should match that of \\\n@ref{XREFpatchxdata,,@qcode{\\\"xdata\\\"}}, \\\n@ref{XREFpatchydata,,@qcode{\\\"ydata\\\"}}, and \\\n@ref{XREFpatchzdata,,@qcode{\\\"zdata\\\"}}.)\";\n        s.valid = valid_scalmatarr;\n        s.category = \"Color and Transparency\";\n\n      case \"cdatamapping\"\n        s.doc = \"Sets the method for mapping data from the \\\n@ref{XREFpatchcdata,,@qcode{\\\"cdata\\\"}} or \\\n@ref{XREFpatchcdata,,@qcode{\\\"cdata\\\"}} property to the current \\\ncolormap.  @qcode{\\\"Direct\\\"} mapping selects the color using the \\\n@qcode{\\\"cdata\\\"} or @qcode{\\\"facevertexcdata\\\"} value as an index to the \\\ncurrent colormap.  @qcode{\\\"Scaled\\\"} mapping scales the @qcode{\\\"cdata\\\"} \\\nor @qcode{\\\"facevertexcdata\\\"} values to the range \\\nspecified in the @ref{XREFaxesclim,,@w{@qcode{\\\"clim\\\"} axes property}}.\";\n        s.category = \"Color and Transparency\";\n\n      case \"diffusestrength\"\n        s.doc = \"Strength of the diffuse reflection.  Value between 0.0 (no \\\ndiffuse reflection) and 1.0 (full diffuse reflection).\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"displayname\"\n        s.doc = \"Text of the legend entry corresponding to this patch.\";\n        s.category = \"Legend Options\";\n\n      case \"edgealpha\"\n        s.doc = sprintf (doc_notimpl, \"Transparency\");\n        s.valid = valid_scalmat;\n        s.category = \"Outline Appearance\";\n\n      case \"edgecolor\"\n        s.doc = \"Color of the edges of the __objname__ object, specified as \\\neither a valid color specification or one of @qcode{\\\"none\\\"}, \\\n@qcode{\\\"flat\\\"}, or @qcode{\\\"interp\\\"}.  @qcode{\\\"flat\\\"} and \\\n@qcode{\\\"interp\\\"} will set either a single color for each edge or a color \\\ninterpolated between edge's vertices using the color value data stored in \\\n@ref{XREFpatchcdata,,@qcode{\\\"cdata\\\"}}.  \\\n@xref{Colors,,colorspec}.\";\n        s.valid = packopt ({valid_color, ...\n                            \"@qcode{\\\"none\\\"}\", ...\n                            \"@qcode{\\\"flat\\\"}\", ...\n                            \"@qcode{\\\"interp\\\"}\"});\n        s.category = \"Outline Appearance\";\n\n      case \"edgelighting\"\n        s.doc = \"When set to a value other than @qcode{\\\"none\\\"}, the edges \\\nof the object are drawn with light and shadow effects.  Supported values are \\\n@qcode{\\\"none\\\"} (no lighting effects), @qcode{\\\"flat\\\"} (faceted look), and \\\n@qcode{\\\"gouraud\\\"} (linear interpolation of the lighting effects between \\\nthe vertices).  @qcode{\\\"phong\\\"} is deprecated and has the same effect as \\\n@qcode{\\\"gouraud\\\"}.\";\n        s.category = \"Outline Appearance\";\n\n      case \"facealpha\"\n        s.doc = \"Transparency level of the faces of the patch object.  Only \\\ndouble values are supported at present where a value of 0 means complete \\\ntransparency and a value of 1 means solid faces without transparency.  Setting \\\nthe property to @qcode{\\\"flat\\\"} or @qcode{\\\"interp\\\"} causes the faces to not \\\nbeing rendered.  Additionally, the faces are not sorted from back to front \\\nwhich might lead to unexpected results when rendering layered transparent \\\nfaces.\";\n        s.valid = packopt ({\"scalar\", ...\n                            \"@qcode{\\\"flat\\\"}\", ...\n                            \"@qcode{\\\"interp\\\"}\"});\n        s.category = \"Color and Transparency\";\n\n      case \"facecolor\"\n        s.doc = \"Color of the faces of the __objname__ object, specified as \\\neither a valid color specification or one of @qcode{\\\"none\\\"}, \\\n@qcode{\\\"flat\\\"}, or @qcode{\\\"interp\\\"}.  @qcode{\\\"flat\\\"} and \\\n@qcode{\\\"interp\\\"} will set either a single color for each face or a color \\\ninterpolated across the face's vertices using the color value data stored in \\\neither the @ref{XREFpatchcdata,,@qcode{\\\"cdata\\\"}} or \\\n@ref{XREFpatchfacevertexcdata,,@qcode{\\\"facevertexcdata\\\"}} \\\nproperties.  @xref{Colors,,colorspec}.\";\n        ## Don't provide a default value, and mark colorspec with\n        ## braces, this forces the default RGB triplet to be displayed\n        s.valid = packopt ({markdef(valid_color), ...\n                            \"@qcode{\\\"none\\\"}\", ...\n                            \"@qcode{\\\"flat\\\"}\", ...\n                            \"@qcode{\\\"interp\\\"}\"});\n        s.category = \"Color and Transparency\";\n\n      case \"facelighting\"\n        s.doc = \"When set to a value other than @qcode{\\\"none\\\"}, the faces \\\nof the object are drawn with light and shadow effects.  Supported values are \\\n@qcode{\\\"none\\\"} (no lighting effects), @qcode{\\\"flat\\\"} (faceted look), and \\\n@qcode{\\\"gouraud\\\"} (linear interpolation of the lighting effects between \\\nthe vertices).  @qcode{\\\"phong\\\"} is deprecated and has the same effect as \\\n@qcode{\\\"gouraud\\\"}.\";\n        s.category = \"Color and Transparency\";\n\n      case \"facenormals\"\n        s.doc = \"Face normals are used for lighting the edges or faces if the \\\n@code{edgelighting} or @code{facelighting} properties are set to \\\n@qcode{\\\"flat\\\"}.  __modemsg__\";\n        s.category = \"Lighting\";\n\n      case \"facenormalsmode\"\n        s.doc = \"If this property is set to @qcode{\\\"auto\\\"}, \\\n@code{facenormals} are automatically calculated if the @code{edgelighting} or \\\n@code{facelighting} property are set to @qcode{\\\"flat\\\"} and at least one \\\n@code{light} object is present and visible in the same axes.\";\n        s.category = \"Lighting\";\n\n      case \"faces\"\n        s.doc = \"__objname__ faces connectivity list stored as an M x N \\\nmatrix, with each of the M faces defined by a row of up to N vertices, \\\nand each element contains the row index of a vertex stored in the \\\n@ref{XREFpatchvertices,,@w{vertices property}}.  Faces with fewer than N \\\nvertices use NaN values to fill empty row elements.\";\n        s.valid = valid_vecmat;\n        s.category = \"Coordinate Data\";\n\n      case \"facevertexalphadata\"\n        s.doc = sprintf (doc_notimpl, \"Face-Vertex transparency control\");\n        s.category = \"Color and Transparency\";\n\n      case \"facevertexcdata\"\n        s.doc = \"Data defining the patch object color relative to its \\\nface-vertex data.  Patch color can be defined using indices into the \\\ncurrent colormap or as RGB triplets, where the RGB colors are defined in the \\\nrows of @qcode{\\\"facevertexcdata\\\"}.  These colors can be separately defined \\\nfor the entire patch object, for individual faces, or for individual vertices, \\\nand is determined by the shape of @qcode{\\\"facevertexcdata\\\"} as follows:\\n\\\n\\n\\\nIf @code{facevertexcdata} is a scalar index into the current colormap or a \\\n1-by-3 RGB triplet, it defines the color of all faces and edges.\\n\\\n\\n\\\nIf the patch object has N faces, and @code{facevertexcdata} is a N-by-1 column \\\nvector of indices or a N-by-3 RGB matrix, it defines the color of each one \\\nof the N faces.\\n\\\n\\n\\\nIf the patch object has M vertices, and @code{facevertexcdata} is a M-by-1 \\\ncolumn vector of indices or a M-by-3 RGB matrix, it defines the color at \\\neach vertex.\";\n        s.valid = valid_scalmat;\n        s.category = \"Color and Transparency\";\n\n      case \"linestyle\"\n        s.doc = \"@xref{Line Styles}.\";\n        s.category = \"Outline Appearance\";\n\n      case \"linewidth\"\n        s.doc = \"@xref{XREFlinelinewidth,,@w{line linewidth property}}.\";\n        s.valid = \"scalar\";\n        s.category = \"Outline Appearance\";\n\n      case \"marker\"\n        s.doc = \"@xref{XREFlinemarker,,@w{line marker property}}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markeredgecolor\"\n        s.doc = \"@xref{XREFlinemarkeredgecolor,,\\\n@w{line markeredgecolor property}}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markerfacecolor\"\n        s.doc = \"@xref{XREFlinemarkerfacecolor,,\\\n@w{line markerfacecolor property}}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markersize\"\n        s.doc = \"@xref{XREFlinemarkersize,,@w{line markersize property}}.\";\n        s.valid = \"scalar\";\n        s.category = \"Marker Appearance\";\n\n      case \"specularcolorreflectance\"\n        s.doc = \"Reflectance for specular color.  Value between 0.0 (color \\\nof underlying face) and 1.0 (color of light source).\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"specularexponent\"\n        s.doc = \"Exponent for the specular reflection.  The lower the value, \\\nthe more the reflection is spread out.\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"specularstrength\"\n        s.doc = \"Strength of the specular reflection.  Value between 0.0 (no \\\nspecular reflection) and 1.0 (full specular reflection).\";\n        s.valid = \"scalar\";\n        s.category = \"Lighting\";\n\n      case \"vertexnormals\"\n        s.doc = \"Vertex normals are used for lighting the edges or faces if \\\nthe @code{edgelighting} or @code{facelighting} properties are set to \\\n@qcode{\\\"gouraud\\\"}.  __modemsg__\";\n        s.category = \"Lighting\";\n\n      case \"vertexnormalsmode\"\n        s.doc = \"If this property is set to @qcode{\\\"auto\\\"}, \\\n@code{vertexnormals} are automatically calculated if the @code{edgelighting} \\\nor @code{facelighting} property are set to @qcode{\\\"gouraud\\\"} and at least \\\none @code{light} object is present and visible in the same axes.\";\n        s.category = \"Lighting\";\n\n      case \"vertices\"\n        s.doc = \"__objname__ vertex list stored as an N x 3 matrix, with \\\neach row containing the x, y, and z coordinates of the vector, and used \\\nwith the @ref{XREFpatchfaces,,@w{faces property}} to define patch \\\nstructure.\";\n        s.valid = valid_vecmat;\n        s.category = \"Coordinate Data\";\n\n      case \"xdata\"\n        s.doc = \"__objname__ vertex x-coordinates.\";\n        s.valid = valid_vecmat;\n        s.category = \"Coordinate Data\";\n\n      case \"ydata\"\n        s.doc = \"__objname__ vertex y-coordinates.\";\n        s.valid = valid_vecmat;\n        s.category = \"Coordinate Data\";\n\n      case \"zdata\"\n        s.doc = \"__objname__ vertex z-coordinates.\";\n        s.valid = valid_vecmat;\n        s.category = \"Coordinate Data\";\n\n    endswitch\n\n  ## Scatter properties\n  elseif (strcmp (objname, \"scatter\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"children\"\n        s.doc = sprintf (doc_notimpl, \"Child objects for Scatter plots\");\n        ## Use base category.\n\n      ## Specific properties\n      case \"annotation\"\n        s.doc = sprintf (doc_notimpl, \"Legend appearance toggling from within \\\n        the __objname__ object\");\n        s.category = \"Legend Options\";\n\n      case \"cdata\"\n        s.doc = \"Data defining the scatter object color.\\n\\\n\\n\\\nIf @code{cdata} is a scalar index into the current colormap or a RGB triplet, \\\nit defines the color of all scatter markers.\\n\\\n\\n\\\nIf @code{cdata} is an N-by-1 vector of indices or an N-by-3 (RGB) matrix, \\\nit defines the color of each one of the N scatter markers.\";\n        s.valid = valid_scalmat;\n        s.category = \"Color Data\";\n\n      case \"cdatamode\"\n        s.doc = \"If @code{cdatamode} is @qcode{\\\"auto\\\"}, @code{cdata} is set \\\nto the color from the @code{colororder} of the ancestor axes corresponding to \\\nthe @code{seriesindex}.\";\n        s.category = \"Color Data\";\n\n      case \"cdatasource\"\n        s.doc = \"The name of a workspace variable that contains data that \\\nwill be used for the \\\n@ref{XREFpatchcdata,,@w{@qcode{\\\"cdata\\\"} property}}.  Data is \\\ntransferred into @qcode{\\\"cdata\\\"} using the \\\n@ref{XREFrefreshdata,,@w{refreshdata function}}.\";\n        s.valid = valid_string;\n        s.category = \"Color Data\";\n\n      case \"datatiptemplate\"\n        s.doc = sprintf (doc_notimpl, \"Data tip objects\");\n        s.category = \"Mouse Interaction\";\n\n      case \"displayname\"\n        s.doc = \"Text of the legend entry corresponding to this scatter \\\nobject.\";\n        s.category = \"Legend Options\";\n\n      case \"latitudedata\"\n        s.doc = sprintf (doc_notimpl, \"Geographic coordinate scatter plotting\");\n        s.category = \"Coordinate Data\";\n\n      case \"latitudedatasource\"\n        s.doc = sprintf (doc_notimpl, \"Geographic coordinate scatter plotting\");\n        s.category = \"Coordinate Data\";\n\n      case \"linewidth\"\n        s.doc = \"Line width of the edge of the markers.\";\n        s.valid = \"scalar\";\n        s.category = \"Marker Appearance\";\n\n      case \"longitudedata\"\n        s.doc = sprintf (doc_notimpl, \"Geographic coordinate scatter plotting\");\n        s.category = \"Coordinate Data\";\n\n      case \"longitudedatasource\"\n        s.doc = sprintf (doc_notimpl, \"Geographic coordinate scatter plotting\");\n        s.category = \"Coordinate Data\";\n\n      case \"marker\"\n        s.doc = \"@xref{XREFlinemarker,,@w{line marker property}}.\";\n        s.category = \"Marker Appearance\";\n\n      case \"markeredgealpha\"\n        s.doc = \"Transparency level of the faces of the markers where a \\\nvalue of 0 means complete transparency and a value of 1 means solid faces \\\nwithout transparency.  Note that the markers are not sorted from back to \\\nfront which might lead to unexpected results when rendering layered \\\ntransparent markers or in combination with other transparent objects.\";\n        s.valid = \"scalar\";\n        s.category = \"Marker Appearance\";\n\n      case \"markeredgecolor\"\n        s.doc = \"Color of the edge of the markers.  @qcode{\\\"none\\\"} means \\\nthat the edges are transparent and @qcode{\\\"flat\\\"} means that the value \\\nfrom @code{cdata} is used.  @xref{XREFlinemarkeredgecolor,,\\\n@w{line markeredgecolor property}}.\";\n        s.valid = packopt ({markdef(\"@qcode{\\\"none\\\"}\"), ...\n                            \"@qcode{\\\"flat\\\"}\", ...\n                            valid_color});\n        s.category = \"Marker Appearance\";\n\n      case \"markerfacealpha\"\n        s.doc = \"Transparency level of the faces of the markers where a \\\nvalue of 0 means complete transparency and a value of 1 means solid faces \\\nwithout transparency.  Note that the markers are not sorted from back to \\\nfront which might lead to unexpected results when rendering layered \\\ntransparent markers or in combination with other transparent objects.\";\n        s.valid = \"scalar\";\n        s.category = \"Marker Appearance\";\n\n      case \"markerfacecolor\"\n        s.doc = \"Color of the face of the markers.  @qcode{\\\"none\\\"} means \\\nthat the faces are transparent, @qcode{\\\"flat\\\"} means that the value from \\\n@code{cdata} is used, and @qcode{\\\"auto\\\"} uses the @code{color} property of \\\nthe ancestor axes.  @xref{XREFlinemarkerfacecolor,,\\\n@w{line markerfacecolor property}}.\";\n        s.valid = packopt ({markdef(\"@qcode{\\\"none\\\"}\"), ...\n                            \"@qcode{\\\"flat\\\"}\", ...\n                            \"@qcode{\\\"auto\\\"}\", ...\n                            valid_color});\n        s.category = \"Marker Appearance\";\n\n      case \"rdata\"\n        s.doc = sprintf (doc_notimpl, \"Polar coordinates for scatter plotting\");\n        s.category = \"Coordinate Data\";\n\n      case \"rdatasource\"\n        s.doc = sprintf (doc_notimpl, \"Polar coordinates for scatter plotting\");\n        s.category = \"Coordinate Data\";\n\n      case \"seriesindex\"\n        s.doc = \"Each scatter object in the same axes is assigned an \\\nincrementing integer.  This corresponds to the index into the \\\n@code{colororder} of the ancestor axes that is used if @code{cdatamode} is \\\nset to @qcode{\\\"auto\\\"}.\";\n        s.category = \"Color Data\";\n\n      case \"sizedata\"\n        s.doc = \"Size of the area of the marker.  A scalar value applies to \\\nall markers.  If @code{cdata} is an N-by-1 vector, it defines the color of \\\neach one of the N scatter markers.\";\n        s.valid =  packopt ({\"[]\", \"scalar\", \"vector\"});\n        s.category = \"Marker Appearance\";\n\n      case \"sizedatasource\"\n        s.doc = sprintf (doc_notimpl, \"Data from workspace variables\");\n        s.category = \"Marker Appearance\";\n\n      case \"thetadata\"\n        s.doc = sprintf (doc_notimpl, \"Polar coordinates for scatter plotting\");\n        s.category = \"Coordinate Data\";\n\n      case \"thetadatasource\"\n        s.doc = sprintf (doc_notimpl, \"Polar coordinates for scatter plotting\");\n        s.category = \"Coordinate Data\";\n\n      case \"xdata\"\n        s.doc = \"Vector with the x coordinates of the scatter object.\";\n        s.valid = \"vector\";\n        s.category = \"Coordinate Data\";\n\n        case \"xdatasource\"\n        s.doc = \"The name of a workspace variable that contains data that \\\nwill be used for the \\\n@ref{XREFscatterxdata,,@w{@qcode{\\\"xdata\\\"} property}}.  Data is \\\ntransferred into @qcode{\\\"xdata\\\"} using the \\\n@ref{XREFrefreshdata,,@w{refreshdata function}}.\";\n        s.valid = valid_string;\n        s.category = \"Coordinate Data\";\n\n      case \"ydata\"\n        s.doc = \"Vector with the y coordinates of the scatter object.\";\n        s.valid = \"vector\";\n        s.category = \"Coordinate Data\";\n\n      case \"ydatasource\"\n        s.doc = \"The name of a workspace variable that contains data that \\\nwill be used for the \\\n@ref{XREFscatterydata,,@w{@qcode{\\\"ydata\\\"} property}}.  Data is \\\ntransferred into @qcode{\\\"ydata\\\"} using the \\\n@ref{XREFrefreshdata,,@w{refreshdata function}}.\";\n        s.valid = valid_string;\n        s.category = \"Coordinate Data\";\n\n      case \"zdata\"\n        s.doc = \"For 3-D data, vector with the y coordinates of the scatter \\\nobject.\";\n        s.valid = packopt ({\"[]\", \"vector\"});\n        s.category = \"Coordinate Data\";\n\n      case \"zdatasource\"\n        s.doc = \"The name of a workspace variable that contains data that \\\nwill be used for the \\\n@ref{XREFscatterzdata,,@w{@qcode{\\\"zdata\\\"} property}}.  Data is \\\ntransferred into @qcode{\\\"zdata\\\"} using the \\\n@ref{XREFrefreshdata,,@w{refreshdata function}}.\";\n        s.valid = valid_string;\n        s.category = \"Coordinate Data\";\n\n    endswitch\n\n  ## Light properties\n  elseif (strcmp (objname, \"light\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"children\"\n        s.doc = [\"__objname__ objects have no child objects.  \", doc_unused];\n        ## Use base category.\n\n      ## Specific properties\n      case \"color\"\n        s.doc = \"Color of the light source.  @xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n        s.category = \"Lighting\";\n\n      case \"position\"\n        s.doc = \"Position of the light source.\";\n        s.category = \"Lighting\";\n\n      case \"style\"\n        s.doc = \"This string defines whether the light emanates from a \\\nlight source at infinite distance (@qcode{\\\"infinite\\\"}) or from a local \\\npoint source (@qcode{\\\"local\\\"}).\";\n        s.category = \"Lighting\";\n\n    endswitch\n\n  ## uimenu properties\n  elseif (strcmp (objname, \"uimenu\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"buttondownfcn\"\n        s.doc = doc_unused;\n        ## Use base category.\n\n      ## Specific properties\n      case \"accelerator\"\n        s.doc = \"A character that when pressed together with CTRL will \\\nexecute this menu entry (e.g., @qcode{\\\"x\\\"} for @code{CTRL+x}).\";\n        s.valid = \"character\";\n        s.category = \"Keyboard Interaction\";\n\n      case \"callback\"\n        s.doc = \"A string consisting of a valid Octave expression that will \\\nbe executed whenever this menu item is selected.\";\n        s.valid = \"string\";\n        s.category = \"Callback Execution\";\n\n      case \"checked\"\n        s.doc = \"Sets whether or not a mark appears at this menu entry.\";\n        s.category = \"Menu Options\";\n\n      case \"enable\"\n        s.doc = \"Sets whether this menu entry is active or is grayed out.\";\n        s.category = \"Menu Options\";\n\n      case \"foregroundcolor\"\n        s.doc = \"The color value of the text for this menu entry.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"menuselectedfcn\"\n        s.doc = \"Function that is called when this menu item is executed.  \\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Callback Execution\";\n\n      case \"position\"\n        s.doc = \"A scalar value containing the relative menu position from \\\nthe left or top depending on the orientation of the menu.\";\n        s.valid = \"scalar\";\n        s.category = \"Object Position\";\n\n      case \"separator\"\n        s.doc = \"State indicating whether a separator line will be drawn \\\nabove the current menu position.\";\n        s.category = \"Appearance\";\n\n      case \"text\"\n        s.doc = \"The text for this menu entry.  A @qcode{\\\"&\\\"} character \\\ncan be used to mark the \\\n@ref{XREFuimenuaccelerator,,@w{@qcode{\\\"accelerator\\\"} key}}\";\n        s.valid = \"string\";\n        s.category = \"Menu Options\";\n\n    endswitch\n\n  ## uicontextmenu properties\n  elseif (strcmp (objname, \"uicontextmenu\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"buttondownfcn\"\n        s.doc = doc_unused;\n        ## Use base category.\n\n      ## Specific properties\n      case \"callback\"\n        s.doc = \"A string consisting of a valid Octave expression that will \\\nbe executed whenever this item is selected.\";\n        s.valid = \"string\";\n        s.category = \"Callback Execution\";\n\n      case \"position\"\n        s.doc = sprintf (doc_notimpl, \"Manually setting location for \\\nuicontextmenu to appear\");\n        s.category = \"Object Position\";\n\n    endswitch\n\n  ## uipanel properties\n  elseif (strcmp (objname, \"uipanel\"))\n    switch (field)\n      ## Overridden shared properties\n\n      ## Specific properties\n    case \"backgroundcolor\"\n        s.doc = \"The color value of the background of this panel.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"bordertype\"\n        s.doc = \"Sets whether or not a line border will surround the panel.\";\n        s.category = \"Appearance\";\n\n      case \"borderwidth\"\n        s.doc = \"The width of the line border in pixels.\";\n        s.valid = \"whole number scalar\";\n        s.category = \"Appearance\";\n\n      case \"fontangle\"\n        s.doc = doc_fontangle;\n        s.category = \"Text Appearance\";\n\n      case \"fontname\"\n        s.doc = doc_fontname;\n        s.valid = valid_string;\n        s.category = \"Text Appearance\";\n\n      case \"fontsize\"\n        s.doc = doc_fontsize;\n        s.valid = \"scalar\";\n        s.category = \"Text Appearance\";\n\n      case \"fontunits\"\n        s.doc = doc_fontunits;\n        s.category = \"Text Appearance\";\n\n      case \"fontweight\"\n        s.doc = doc_fontweight;\n        s.category = \"Text Appearance\";\n\n      case \"foregroundcolor\"\n        s.doc = \"The color value of the title text for this panel.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"highlightcolor\"\n        s.doc = \"The color value of the line bordering this panel.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"position\"\n        s.doc = \"Size of the panel represented as the four-element vector \\\n[left, bottom, width, height].\";\n        s.valid = valid_4elvec;\n        s.category = \"Object Position\";\n\n      case \"resizefcn\"\n        s.doc = \"__prop__ is deprecated.  Use @code{sizechangedfcn} instead.\";\n        s.valid = valid_fcn;\n        s.category = \"Callback Execution\";\n\n      case \"shadowcolor\"\n        s.doc = \"The color value of the line surrounding the border line \\\naround this panel.  @xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n\n        s.category = \"Appearance\";\n\n      case \"sizechangedfcn\"\n        s.doc = \"Callback triggered when the panel size is changed.\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Callback Execution\";\n\n      case \"title\"\n        s.doc = \"The text for the panel title.\";\n        s.valid = \"string\";\n        s.category = \"Text Appearance\";\n\n      case \"titleposition\"\n        s.doc = \"Relative position of the title within the panel.\";\n        s.category = \"Text Appearance\";\n\n      case \"units\"\n        s.doc = \"Unit of measurement used to interpret the \\\n@qcode{\\\"position\\\"} property.\";\n        s.category = \"Object Position\";\n\n    endswitch\n\n  ## uibuttongroup properties\n  elseif (strcmp (objname, \"uibuttongroup\"))\n    switch (field)\n      ## Overridden shared properties\n\n      ## Specific properties\n      case \"backgroundcolor\"\n        s.doc = \"The color value of the background of this buttongroup.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"bordertype\"\n        s.doc = \"Sets whether or not a line border will surround the \\\nbuttongroup.\";\n        s.category = \"Appearance\";\n\n      case \"borderwidth\"\n        s.doc = \"The width of the line border in pixels.\";\n        s.valid = \"whole number scalar\";\n        s.category = \"Appearance\";\n\n      case \"fontangle\"\n        s.doc = doc_fontangle;\n        s.category = \"Text Appearance\";\n\n      case \"fontname\"\n        s.doc = doc_fontname;\n        s.valid = valid_string;\n        s.category = \"Text Appearance\";\n\n      case \"fontsize\"\n        s.doc = doc_fontsize;\n        s.valid = \"scalar\";\n        s.category = \"Text Appearance\";\n\n      case \"fontunits\"\n        s.doc = doc_fontunits;\n        s.category = \"Text Appearance\";\n\n      case \"fontweight\"\n        s.doc = doc_fontweight;\n        s.category = \"Text Appearance\";\n\n      case \"foregroundcolor\"\n        s.doc = \"The color value of the title text for this buttongroup.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"highlightcolor\"\n        s.doc = \"The color value of the line bordering this buttongroup.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"position\"\n        s.doc = \"Size of the buttongroup represented as the four-element \\\nvector [left, bottom, width, height].\";\n        s.valid = valid_4elvec;\n        s.category = \"Object Position\";\n\n      case \"resizefcn\"\n        s.doc = \"__prop__ is deprecated.  Use @code{sizechangedfcn} instead.\";\n        s.valid = valid_fcn;\n        s.category = \"Callback Execution\";\n\n      case \"selectedobject\"\n        s.doc = \"Graphic handle of the currently selected item in the \\\nbuttongroup.\";\n        s.category = \"Button Group Operation\";\n\n      case \"selectionchangedfcn\"\n        s.doc = \"Callback triggered when the selected item within the \\\nbuttongroup is changed.\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Callback Execution\";\n\n      case \"shadowcolor\"\n        s.doc = \"The color value of the line surrounding the border line \\\naround this buttongroup.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"sizechangedfcn\"\n        s.doc = \"Callback triggered when the buttongroup size is changed.\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Appearance\";\n\n      case \"title\"\n        s.doc = \"The text for the buttongroup title.\";\n        s.valid = \"string\";\n        s.category = \"Text Appearance\";\n\n      case \"titleposition\"\n        s.doc = \"Relative position of the title within the buttongroup.\";\n        s.category = \"Text Appearance\";\n\n      case \"units\"\n        s.doc = \"Unit of measurement used to interpret the \\\n@qcode{\\\"position\\\"} property.\";\n        s.category = \"Object Position\";\n\n\n    endswitch\n\n  ## uicontrol properties\n  elseif (strcmp (objname, \"uicontrol\"))\n    switch (field)\n      ## Overridden shared properties\n\n      ## Specific properties\n      case \"backgroundcolor\"\n        s.doc = \"The color value of the background of this control object.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"callback\"\n        s.doc = \"A string consisting of a valid Octave expression that will \\\nbe executed whenever this control is activated.\";\n        s.valid = \"string\";\n        s.category = \"Callback Execution\";\n\n      case \"cdata\"\n        s.doc = \"Image data used to represent the control object, stored as \\\na M x N x 3 RGB array.\";\n        s.valid = \"array\";\n        s.category = \"Appearance\";\n\n      case \"enable\"\n        s.doc = \"Sets whether this control object is active or is grayed \\\nout.\";\n        s.category = \"Control Options\";\n\n      case \"extent\"\n        s.doc = \"Size of the text string associated to the uicontrol \\\nreturned in the form @code{[0 0 width height]} (the two first elements \\\nare always zero).\\n\\n\\\nFor multi-line strings the returned @code{width} and @code{height} \\\nindicate the size of the rectangle enclosing all lines.\";\n        s.valid = valid_4elvec;\n        s.printdefault = false;\n        s.category = \"Appearance\";\n\n      case \"fontangle\"\n        s.doc = doc_fontangle;\n        s.category = \"Text Appearance\";\n\n      case \"fontname\"\n        s.doc = doc_fontname;\n        s.valid = valid_string;\n        s.category = \"Text Appearance\";\n\n      case \"fontsize\"\n        s.doc = doc_fontsize;\n        s.valid = \"scalar\";\n        s.category = \"Text Appearance\";\n\n      case \"fontunits\"\n        s.doc = doc_fontunits;\n        s.category = \"Text Appearance\";\n\n      case \"fontweight\"\n        s.doc = doc_fontweight;\n        s.category = \"Text Appearance\";\n\n      case \"foregroundcolor\"\n        s.doc = \"The color value of the text for this control object.  \\\n@xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"horizontalalignment\"\n        s.doc = \"Specifies the horizontal justification of the text within \\\nthe uicontrol object.\";\n        s.category = \"Text Appearance\";\n\n      case \"keypressfcn\"\n        s.doc = \"Callback function executed when a key is pressed while the \\\nuicontrol object has focus.  The first argument to the function is the handle \\\nof the calling uicontrol.  The second argument holds an event structure which \\\nhas the following members:\\n\\\n@table @code\\n\\\n@item Character:\\n\\\nThe ASCII value of the key\\n\\\n@item Modifier:\\n\\\nA cell array containing strings representing the modifiers pressed with the \\\nkey.\\n\\\n@item Key:\\n\\\nLowercase description of the key\\n\\\n@item Source:\\n\\\nGraphics handle of the object executing the callback function\\n\\\n@item EventName:\\n\\\n\\\"KeyPress\\\"\\n\\\n@end table\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Callback Execution\";\n\n      case \"listboxtop\"\n        s.doc = \"The index of the string option that will appear at the top of \\\n\\\"listbox\\\" controls \";\n        s.valid = \"scalar\";\n        s.category = \"Control Options\";\n\n      case \"max\"\n        s.doc = \"The maximum control value, whose effect on the control is \\\ndependent on the control type.  For @qcode{\\\"checkbox\\\"}, \\\n@qcode{\\\"togglebutton\\\"}, and @qcode{\\\"radiobutton\\\"} controls, the \\\n@qcode{\\\"max\\\"} value is assigned to the @qcode{\\\"value\\\"} property when the \\\ncontrol object is selected.  For @qcode{\\\"slider\\\"} controls, \\\n@qcode{\\\"max\\\"} defines the maximum value of the slider.  For \\\n@qcode{\\\"edit\\\"} and @qcode{\\\"listbox\\\"} controls, if @code{Max - Min > 1}, \\\nthen the control will permit multiple line entries or list item selections, \\\nrespectively.\";\n        s.valid = \"scalar\";\n        s.category = \"Control Options\";\n\n      case \"min\"\n        s.doc = \"The minimum control value, whose effect on the control is \\\ndependent on the control type.  For @qcode{\\\"checkbox\\\"}, \\\n@qcode{\\\"togglebutton\\\"}, and @qcode{\\\"radiobutton\\\"} controls, the \\\n@qcode{\\\"min\\\"} value is assigned to the @qcode{\\\"value\\\"} property when the \\\ncontrol object is not selected.  For @qcode{\\\"slider\\\"} controls, \\\n@qcode{\\\"min\\\"} defines the minimum value of the slider.  For \\\n@qcode{\\\"edit\\\"} and @qcode{\\\"listbox\\\"} controls, if @code{Max - Min > 1}, \\\nthen the control will permit multiple line entries or list item selections, \\\nrespectively.\";\n        s.valid = \"scalar\";\n        s.category = \"Control Options\";\n\n      case \"position\"\n        s.doc = \"Size of the control object represented as the four-element \\\nvector [left, bottom, width, height].\";\n        s.valid = valid_4elvec;\n        s.category = \"Object Position\";\n\n      case \"sliderstep\"\n        s.doc = \"The fractional step size, measured relative to the \\\n@code{Min - Max} span of the slider, that the slider moves when the user \\\nclicks on the object.  @qcode{\\\"sliderstep\\\"} is specified as a two-element \\\nvector consisting of @code{[minor major]}, where @qcode{\\\"minor\\\"} is the \\\nstep size for clicking on the slider arrows, and @qcode{\\\"major\\\"} is the \\\nstep size for clicking within the slider bar.\";\n        s.valid = valid_2elvec;\n        s.category = \"Control Options\";\n\n      case \"string\"\n        s.doc = \"The text appearing with the control object.\";\n        s.valid = \"string\";\n        s.category = \"Text Appearance\";\n\n      case \"style\"\n        s.doc = \"The type of control object created.  For a complete \\\ndescription of available control styles, see the \\\n@ref{XREFuicontrol,,@w{@qcode{\\\"uicontrol\\\"} function}}\";\n        s.category = \"Appearance\";\n\n      case \"tooltipstring\"\n        s.doc = \"A text string that appears in a tooltip when the mouse \\\npointer hovers over the control object.\";\n        s.valid = \"string\";\n        s.category = \"Mouse Interaction\";\n\n      case \"units\"\n        s.doc = \"Unit of measurement used to interpret the \\\n@qcode{\\\"position\\\"} property.\";\n        s.category = \"Object Position\";\n\n      case \"value\"\n        s.doc = \"A numerical value associated with the current state of the \\\ncontrol object, with the meaning of the value dependent on the \\\"style\\\" of \\\nthe control object.\";\n        s.valid = \"scalar\";\n        s.category = \"Control Options\";\n\n      case \"verticalalignment\"\n        s.doc = \"Specifies the vertical position of the text in the \\\nuicontrol object.\";\n        s.category = \"Text Appearance\";\n\n    endswitch\n\n  ## uitable Properties\n  elseif (strcmp (objname, \"uitable\"))\n    switch (field)\n      ## Overridden shared properties\n\n      ## Specific properties\n      case \"backgroundcolor\"\n        s.doc = \"Color of the background of the table specified as a \\\n3-element RBG vector.  If __prop__ has multiple rows, the colors cycle \\\nrepeatedly if the \\\n@ref{XREFuitablerowstriping,,@qcode{\\\"rowstriping\\\"} property} is on.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"celleditcallback\"\n        s.doc = \"A string consisting of a valid Octave expression that will \\\nbe executed whenever a table cell is edited.\";\n        s.valid = \"string\";\n        s.category = \"Callback Execution\";\n\n      case \"cellselectioncallback\"\n        s.doc = \"A string consisting of a valid Octave expression that will \\\nbe executed whenever a table cell is selected.\";\n        s.valid = \"string\";\n        s.category = \"Callback Execution\";\n\n      case \"columneditable\"\n        s.doc = \"A logical indicator of whether the columns are editable.  \\\nIt consists of either a 1 x N vector of logical values where true or false \\\nindicate the corresponding column is or is not editable, respectively, or \\\nan empty logical array indicating that no column is editable.\";\n        s.valid = \"logical row vector\";\n        s.category = \"Table Operation\";\n\n      case \"columnformat\"\n        s.doc = \"The display format for numeric data in each column.  \\\nValid formats include @qcode{\\\"char\\\"}, @qcode{\\\"logical\\\"}, \\\n@qcode{\\\"numeric\\\"}, or a valid format setting from the \\\n@ref{XREFformat,,format function}\";\n        s.category = \"Table Data\";\n\n      case \"columnname\"\n        s.doc = \"Column names specified as either @qcode{\\\"numbered\\\"} or a \\\n1 x N cell string vector containing the names to be used for each column \\\nheading.\";\n        s.category = \"Table Data\";\n\n      case \"columnwidth\"\n        s.doc = \"Setting for determining width of each column, valid \\\noptions include: @qcode{\\\"auto\\\"}, @qcode{\\\"fit\\\"}, evenly divided \\\nmultiples specified as @qcode{\\\"1x\\\"}, @qcode{\\\"2x\\\"}, etc., or a 1 x N cell \\\nvector where each element corresponds to one of N table columns, and \\\ncontains any of the above string options or a fixed width specified in pixels.\\\n  The @qcode{\\\"1x\\\"} property is not yet implemented.\";\n        s.category = \"Table Data\";\n\n      case \"data\"\n        s.doc = \"The data contained in the table specified as either a \\\n2-D numeric, logical, or cell array.\";\n        s.valid = \"matrix\";\n        s.category = \"Table Data\";\n\n      case \"enable\"\n        s.doc = \"Sets whether this table object is active or is grayed out.\";\n        s.category = \"Table Operation\";\n\n      case \"extent\"\n        s.doc = \"A four-element vector indicating the size of the table.  \\\nThe first two elements of the array are always zero, while the third and \\\nfourth elements contain the height and width of the table.\";\n        s.valid = valid_4elvec;\n        s.printdefault = false;\n        s.category = \"Object Position\";\n\n      case \"fontangle\"\n        s.doc = doc_fontangle;\n        s.category = \"Text Appearance\";\n\n      case \"fontname\"\n        s.doc = doc_fontname;\n        s.valid = valid_string;\n        s.category = \"Text Appearance\";\n\n      case \"fontsize\"\n        s.doc = doc_fontsize;\n        s.valid = \"scalar\";\n        s.category = \"Text Appearance\";\n\n      case \"fontunits\"\n        s.doc = doc_fontunits;\n        s.category = \"Text Appearance\";\n\n      case \"fontweight\"\n        s.doc = doc_fontweight;\n        s.category = \"Text Appearance\";\n\n      case \"foregroundcolor\"\n        s.doc = \"Color of the data text in this table.  \\\n@xref{Colors,,colorspec}.\";\n        s.valid = valid_color;\n        s.category = \"Appearance\";\n\n      case \"keypressfcn\"\n        s.doc = \"Callback function executed when a key is pressed while the \\\ntable object has focus.  The first argument to the function is the handle of \\\nthe calling table.  The second argument holds an event structure which has the \\\nfollowing members:\\n\\\n@table @code\\n\\\n@item Character:\\n\\\nThe ASCII value of the key\\n\\\n@item Modifier:\\n\\\nA cell array containing strings representing the modifiers pressed with the \\\nkey.\\n\\\n@item Key:\\n\\\nLowercase description of the key\\n\\\n@item Source:\\n\\\nGraphics handle of the object executing the callback function\\n\\\n@item EventName:\\n\\\n\\\"KeyPress\\\"\\n\\\n@end table\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Callback Execution\";\n\n      case \"keyreleasefcn\"\n        s.doc = \"Callback function executed when a key is released while the \\\ntable object has focus.  The first argument to the function is the handle of \\\nthe calling table.  The second argument holds an event structure which has the \\\nfollowing members:\\n\\\n@table @code\\n\\\n@item Character:\\n\\\nThe ASCII value of the key\\n\\\n@item Modifier:\\n\\\nA cell array containing strings representing the modifiers pressed with the \\\nkey.\\n\\\n@item Key:\\n\\\nLowercase description of the key\\n\\\n@item Source:\\n\\\nGraphics handle of the object executing the callback function\\n\\\n@item EventName:\\n\\\n\\\"KeyRelease\\\"\\n\\\n@end table\\\n\\n\\n__fcnmsg__\";\n        s.valid = valid_fcn;\n        s.category = \"Callback Execution\";\n\n      case \"position\"\n        s.doc = \"The position and size of the table.  The four elements of \\\nthe vector are the coordinates of the lower left corner and width and height \\\nof the figure.  @xref{XREFuitableunits,,@w{units property}}.\";\n        s.valid = valid_4elvec;\n        s.category = \"Object Position\";\n\n      case \"rearrangeablecolumns\"\n        s.doc = \"Indicates whether or not the ability to move columns by \\\nclicking and dragging the column headers.\";\n        s.category = \"Table Operation\";\n\n      case \"rowname\"\n        s.doc = \"Row names specified as either @qcode{\\\"numbered\\\"} or a \\\nN x 1 cell string vector containing the names to be used for each row \\\nheading.\";\n        s.category = \"Table Data\";\n\n      case \"rowstriping\"\n        s.doc = \"Setting to indicate whether the table background color \\\nwill use different colors for each row.  Colors are drawn from the \\\n@ref{XREFuitablebackgroundcolor,,@qcode{\\\"backgroundcolor\\\"} property} in \\\na repeating pattern.\";\n        s.category = \"Appearance\";\n\n      case \"tooltipstring\"\n        s.doc = \"A text string that appears in a tooltip when the mouse \\\npointer hovers over the table object.\";\n        s.valid = \"string\";\n        s.category = \"Mouse Interaction\";\n\n      case \"units\"\n        s.doc = \"Unit of measurement used to interpret the \\\n@qcode{\\\"position\\\"} property.\";\n        s.category = \"Object Position\";\n\n    endswitch\n\n  ## uitoolbar properties\n  elseif (strcmp (objname, \"uitoolbar\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"buttondownfcn\"\n        s.doc = doc_unused;\n        ## Use base category.\n\n    endswitch\n\n  ## uipushtool properties\n  elseif (strcmp (objname, \"uipushtool\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"buttondownfcn\"\n        s.doc = doc_unused;\n        ## Use base category.\n\n      ## Specific properties\n      case \"__named_icon__\"\n        s.doc = \"The name of an bundled icon file to use as the image for \\\nthe pushtool object.\";\n        s.valid = \"string\";\n        s.category = \"Appearance\";\n\n      case \"cdata\"\n        s.doc = \"Image data used to represent the pushtool object, stored as \\\na M x N x 3 RGB array.\";\n        s.valid = \"array\";\n        s.category = \"Appearance\";\n\n      case \"clickedcallback\"\n        s.doc = \"A string consisting of a valid Octave expression that will \\\nbe executed whenever this control object is clicked.\";\n        s.valid = \"string\";\n        s.category = \"Callback Execution\";\n\n      case \"enable\"\n              s.doc = \"Sets whether this pushtool object is active or is \\\ngrayed out.\";\n        s.category = \"Pushtool Operation\";\n\n      case \"separator\"\n        s.doc = \"State indicating whether a separator line will be drawn \\\nnext to the current pushtool position.\";\n        s.category = \"Appearance\";\n\n      case \"tooltipstring\"\n        s.doc = \"A text string that appears in a tooltip when the mouse \\\npointer hovers over the pushtool object.\";\n        s.valid = \"string\";\n        s.category = \"Mouse Interaction\";\n\n    endswitch\n\n  ## uitoggletool properties\n  elseif (strcmp (objname, \"uitoggletool\"))\n    switch (field)\n      ## Overridden shared properties\n      case \"buttondownfcn\"\n        s.doc = doc_unused;\n        ## Use base category.\n\n      ## Specific properties\n      case \"__named_icon__\"\n        s.doc = \"The name of an bundled icon file to use as the image for \\\nthe toggletool object.\";\n        s.valid = \"string\";\n        s.category = \"Appearance\";\n\n      case \"cdata\"\n        s.doc = \"Image data used to represent the toggletool object, stored \\\nas a M x N x 3 RGB array.\";\n        s.valid = \"array\";\n        s.category = \"Appearance\";\n\n      case \"clickedcallback\"\n        s.doc = \"A string consisting of a valid Octave expression that will \\\nbe executed whenever this control object is clicked.\";\n        s.valid = \"string\";\n        s.category = \"Callback Execution\";\n\n      case \"enable\"\n        s.doc = \"Sets whether this toggletool object is active or is grayed \\\nout.\";\n        s.category = \"Toggle Operation\";\n\n      case \"offcallback\"\n        s.doc = \"A string consisting of a valid Octave expression that will \\\nbe executed whenever this control object is toggled off.\";\n        s.valid = \"string\";\n        s.category = \"Callback Execution\";\n\n      case \"oncallback\"\n        s.doc = \"A string consisting of a valid Octave expression that will \\\nbe executed whenever this control object is toggled on.\";\n        s.valid = \"string\";\n        s.category = \"Callback Execution\";\n\n      case \"separator\"\n        s.doc = \"Setting to draw a vertical line to the left of the \\\ntoggletool.\";\n        s.category = \"Appearance\";\n\n      case \"state\"\n        s.doc = \"The current @qcode{\\\"on\\\"} or @qcode{\\\"off\\\"} state of the \\\ntoggletool object.\";\n        s.category = \"Toggle Operation\";\n\n      case \"tooltipstring\"\n        s.doc = \"A text string that appears in a tooltip when the mouse \\\npointer hovers over the toggletool object.\";\n        s.valid = \"string\";\n        s.category = \"Mouse Interaction\";\n\n    endswitch\n  endif\n\n  ## Replace keywords\n  if (! isempty (s.doc) && ! strcmp (objname, \"base\"))\n    s.doc = expand_doc (s.doc, field, objname);\n  endif\n\nendfunction\n\nfunction strout = expand_doc (strin, field, objname)\n  strout = strrep (strin, \"__objname__\", objname);\n  strout = strrep (strout, \"__prop__\", [\"@code{\" field \"}\"]);\n\n  modemsg = \"Setting @code{%s} also forces the @code{%smode} \\\nproperty to be set to @qcode{\\\"manual\\\"}.\";\n  modemsg = sprintf (modemsg, field, field);\n  strout = strrep (strout, \"__modemsg__\", modemsg);\n  fcnmsg = \"For information on how to write graphics listener \\\nfunctions, @pxref{Callbacks,,@w{Callbacks section}}.\";\n  strout = strrep (strout, \"__fcnmsg__\", fcnmsg);\nendfunction\n\nfunction s = getstructure (objname, base = [], props = {})\n  hf = [];\n  if (! strcmp (objname, \"root\"))\n    ## Use an improbable number to avoid ishghandle to return true for 1\n    hf = figure (2265465, \"visible\", \"off\");\n  endif\n\n  ## Build a default object to extract its properties list and default values.\n  if (strcmp (objname, \"base\"))\n    ## Base properties are extracted from hggroup that only have 1 additional\n    ## regular (non-hidden) property, \"displayname\".\n    h = hggroup ();\n  elseif (strcmp (objname, \"root\"))\n    h = 0;\n  elseif (strcmp (objname, \"figure\"))\n    h = hf;\n  elseif (strcmp (objname, \"legend\"))\n    line ();\n    h = legend ();\n    if (isempty (props))\n        props = {\"autoupdate\", \"box\", \"color\", \"edgecolor\", \"fontangle\", ...\n                 \"fontname\", \"fontsize\", \"fontunits\", \"fontweight\", ...\n                 \"itemhitfcn\", \"location\", \"numcolumns\", \"orientation\", ...\n                 \"position\", \"string\", \"textcolor\", \"title\", \"units\"};\n    endif\n  elseif (strcmp (objname, \"scatter\"))\n    ## Make sure to get a scatter object independent of graphics toolkit\n    hax = axes (hf);\n    h = __go_scatter__ (hax);\n  else\n    eval ([\"h = \" objname \" ();\"]);\n  endif\n\n  gprop = get (h);\n  sprop = set (h);\n\n  if (! isempty (props))\n    flds = fieldnames (gprop);\n    idx = cellfun (@(s) ! any (strcmp (props, s)), flds);\n    gprop = rmfield (gprop, flds(idx));\n    flds = fieldnames (sprop);\n    idx = cellfun (@(s) ! any (strcmp (props, s)), flds);\n    sprop = rmfield (sprop, flds(idx));\n  endif\n\n  fields = fieldnames (gprop);\n  nf = numel (fields);\n  args = cell (2*nf, 1);\n  for ii = 1:nf\n    field = fields{ii};\n\n    ## Get hard coded documentation\n    val = getdoc (objname, field, base);\n\n    ## Extract the default values that are not hard coded in getdoc\n    if (isempty (val.default) && val.printdefault)\n      val.default = getdefault (h, objname, field);\n    endif\n\n    val.isreadonly = ! isfield (sprop, field);\n\n    ## Extract the valid values that are not hard coded in getdoc\n    if (! val.isreadonly && isempty (val.valid))\n      val.valid = sprop.(field);\n      if (! isempty (val.valid) && iscellstr (val.valid))\n        ## Add double quotes around string radio properties\n        val.valid = cellfun (@(s) [\"@qcode{\\\"\" s \"\\\"}\"], val.valid,\n                             \"uniformoutput\", false);\n        val.valid = strjoin (val.valid, \" | \");\n      endif\n    endif\n\n    args{2*(ii-1)+1} = field;\n    args{2*ii} = val;\n  endfor\n\n  ## Build struct and remove unused fields in base properties\n  s = struct (args{:});\n\n  if (strcmp (objname, \"base\"))\n    s = rmfield (s, \"displayname\");\n  endif\n\n  if (isfigure (hf))\n    close (hf)\n  endif\n\nendfunction\n\nfunction def = getdefault (h, objname, field)\n  ## This function is meant to be run without initialization file so\n  ## that the properties we get are the default.\n  def = get (h, field);\n\n  ## Don't print default values for graphics handles\n  if (ishghandle (def) && isscalar (def) && def != 0)\n    def = \"\";\n  else\n    if (ischar (def))\n      def = ['@qcode{\"' def '\"}'];\n    else\n      if ((isvector (def) && numel (def) < 5) || isempty (def))\n        ## Use disp to print the default value for short vectors and\n        ## empty values\n        str = disp (def);\n        str(end) = [];          # remove linefeed\n        str = strtrim (str);    # remove leading space\n\n        ## Add [] around vector values\n        if (ismatrix (def) && numel (def) > 1)\n          str = [\"[\" str \"]\"];\n          ## Add \";\" between columns vector values\n          if (rows (def) != 1)\n            str = strrep (str, \"\\n\", \"; \");\n          endif\n        endif\n\n        ## Replace texinfo reserved characters\n        def = strrep (str, \"@\", \"@@\");  # must occur first\n        def = strrep (def, \"{\", \"@{\");\n        def = strrep (def, \"}\", \"@}\");\n\n        def = [\"@code{\" def \"}\"];\n      else\n        args = arrayfun (@(x) num2str (x), size (def), \"uniformoutput\", false);\n        def = [strjoin(args, \"-by-\") \" \" class(def)];\n      endif\n    endif\n  endif\n\nendfunction\n\nfunction str = printdoc (objname, obj, is_prop_subset)\n  ## File header and beginning of properties table\n  str = warn_autogen ();\n  if (strcmp (objname, \"root\"))\n    str = sprintf (\"%s\\n\\nProperties of the root graphics object:\", str);\n  elseif (is_prop_subset)\n    ## Do nothing\n  else\n    str = sprintf (\"%s\\n\\nProperties of @code{%s} objects (@pxref{XREF%s,,%s}):\",\n                   str, objname, objname, objname);\n  endif\n\n  ## Sort fields by category, put the special categories \"Miscellaneous\" and\n  ## \"Unused\" last if they are used.\n  allfields = fieldnames (obj);\n  allcategories = cellfun (@(s) obj.(s).category, allfields, \"uni\", false);\n  categories = unique (allcategories);\n  idx = strcmp (categories, \"Miscellaneous\");\n  categories = [categories(!idx); categories(idx)];\n  idx = strcmp (categories, \"Unused\");\n  categories = [categories(!idx); categories(idx)];\n\n  ## Add links to categories at the top\n  str = sprintf (\"%s\\n\\n@subsubheading Categories:\\n\\n\", str);\n\n  for ii = 1:numel (categories);\n    str = sprintf (\"%s@ref{XREF%scategory%s,,@w{%s}}@: \", str, objname, strrep (categories{ii}, \" \", \"\"), categories{ii});\n    if (ii < numel (categories))\n      str = sprintf (\"%s| \", str);\n    endif\n  endfor\n\n  idx = [];\n  for ii = 1:numel (categories)\n    fields = sort (allfields(strcmp (allcategories, categories{ii})));\n    nf = numel (fields);\n    str = sprintf (\"%s\\n\\n@anchor{XREF%scategory%s}\\n\", str, ...\n                   objname, strrep (categories{ii}, \" \", \"\"));\n    str = sprintf (\"%s@subsubheading %s\\n\", str, categories{ii});\n    str = sprintf (\"%s\\n@table @asis\", str);\n\n    for jj = 1:nf\n      field = fields{jj};\n      str = sprintf (\"%s\\n\\n\", str);\n\n      if (! is_prop_subset)\n        ## @anchor: cross reference using XREFobjnamefield label\n        ## Concept index: call info from octave with 'doc (\"objname field\")'\n        str = sprintf (\"%s@anchor{XREF%s%s}\\n@prindex %s %s\\n\",\n                       str, objname, field, objname, field);\n      endif\n\n      ## Item\n      str = sprintf (\"%s@item @code{%s}\", str, field);\n\n     ## Mark item read-only if needed\n      if (obj.(field).isreadonly)\n        str = sprintf (\"%s (read-only):\", str);\n      else\n        str = sprintf (\"%s:\", str);\n      endif\n\n      ## Print valid and default values\n      tmp = print_options (obj.(field).valid,\n                           obj.(field).default);\n      if (! isempty (tmp))\n        str = sprintf (\"%s %s\\n\", str, tmp);\n      else\n        str = sprintf (\"%s\\n\", str);\n      endif\n\n      ## Print documentation\n      str = sprintf (\"%s%s\\n\", str, obj.(field).doc);\n    endfor\n\n    ## End of properties table\n    str = sprintf (\"%s\\n@end table\", str);\n  endfor\n\nendfunction\n\nfunction str = warn_autogen ()\n  str = \"@c DO NOT EDIT!  Generated automatically by genpropdoc.m.\\n\\\n\\n\\\n@c Copyright (C) 2014-2026 The Octave Project Developers\\n\\\n@c\\n\\\n@c See the file COPYRIGHT.md in the top-level directory of this\\n\\\n@c distribution or <https://octave.org/copyright/>.\\n\\\n@c\\n\\\n@c This file is part of Octave.\\n\\\n@c\\n\\\n@c Octave is free software: you can redistribute it and/or modify it\\n\\\n@c under the terms of the GNU General Public License as published by\\n\\\n@c the Free Software Foundation, either version 3 of the License, or\\n\\\n@c (at your option) any later version.\\n\\\n@c\\n\\\n@c Octave is distributed in the hope that it will be useful, but\\n\\\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\\n\\\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n\\\n@c GNU General Public License for more details.\\n\\\n@c\\n\\\n@c You should have received a copy of the GNU General Public License\\n\\\n@c along with Octave; see the file COPYING.  If not, see\\n\\\n@c <https://www.gnu.org/licenses/>.\";\nendfunction\n\nfunction str = print_options (val, default)\n  str = \"\";\n  if (! isempty (val))\n    tmp = strrep (val, default, [\"@{\" default \"@}\"]);\n    if (length (tmp) == length (val) && ! isempty (default))\n      str = [tmp \", def. \" default];\n    else\n      str = tmp;\n    endif\n  elseif (! isempty (default))\n    str = [\"def. \" default];\n  endif\n\nendfunction\n"
  },
  {
    "path": "doc/interpreter/geometry.txi",
    "content": "@c Copyright (C) 2007-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Geometry\n@chapter Geometry\n\nMuch of the geometry code in Octave is based on the Qhull\nlibrary@footnote{@nospell{C.B. Barber, D.P. Dobkin, H.T. Huhdanpaa},\n\"The Quickhull Algorithm for Convex Hulls\",\n@cite{@nospell{ACM Trans.@: on Mathematical Software}}, 22(4),\n@w{pp.@: 469}--483, Dec 1996, @url{http://www.qhull.org}}.\nSome of the documentation for Qhull, particularly for the options that\ncan be passed to @code{delaunay}, @code{voronoi} and @code{convhull},\netc., is relevant to Octave users.\n\n@menu\n* Delaunay Triangulation::\n* Voronoi Diagrams::\n* Convex Hull::\n* Interpolation on Scattered Data::\n* Vector Rotation Matrices::\n@end menu\n\n@node Delaunay Triangulation\n@section Delaunay Triangulation\n\nThe Delaunay triangulation is constructed from a set of\ncircum-circles.  These circum-circles are chosen so that there are at\nleast three of the points in the set to triangulation on the\ncircumference of the circum-circle.  None of the points in the set of\npoints falls within any of the circum-circles.\n\nIn general there are only three points on the circumference of any\ncircum-circle.  However, in some cases, and in particular for the\ncase of a regular grid, 4 or more points can be on a single\ncircum-circle.  In this case the Delaunay triangulation is not unique.\n\n@DOCSTRING(delaunay)\n\nFor 3-D inputs @code{delaunay} returns a set of tetrahedra that satisfy the\nDelaunay circum-circle criteria.  Similarly, @code{delaunayn} returns the\nN-dimensional simplex satisfying the Delaunay circum-circle criteria.\nThe N-dimensional extension of a triangulation is called a tessellation.\n\n@DOCSTRING(delaunayn)\n\nAn example of a Delaunay triangulation of a set of points is\n\n@example\n@group\nrand (\"state\", 1);\nx = rand (1, 10);\ny = rand (1, 10);\nT = delaunay (x, y);\nX = [ x(T(:,1)); x(T(:,2)); x(T(:,3)); x(T(:,1)) ];\nY = [ y(T(:,1)); y(T(:,2)); y(T(:,3)); y(T(:,1)) ];\naxis ([0, 1, 0, 1]);\nplot (X, Y, \"b\", x, y, \"r*\");\n@end group\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:delaunay}.\n\n@float Figure,fig:delaunay\n@center @image{delaunay,4in}\n@caption{Delaunay triangulation of a random set of points}\n@end float\n@end ifnotinfo\n\n@menu\n* Plotting the Triangulation::\n* Identifying Points in Triangulation::\n@end menu\n\n@node Plotting the Triangulation\n@subsection Plotting the Triangulation\n\nOctave has the functions @code{triplot}, @code{trimesh}, and @code{trisurf}\nto plot the Delaunay triangulation of a 2-dimensional set of points.\n@code{tetramesh} will plot the triangulation of a 3-dimensional set of points.\n\n@DOCSTRING(triplot)\n\n@DOCSTRING(trimesh)\n\n@DOCSTRING(trisurf)\n\n@DOCSTRING(tetramesh)\n\nThe difference between @code{triplot}, and @code{trimesh} or @code{trisurf},\nis that the former only plots the 2-dimensional triangulation itself, whereas\nthe second two plot the value of a function @code{f (@var{x}, @var{y})}.  An\nexample of the use of the @code{triplot} function is\n\n@example\n@group\nrand (\"state\", 2)\nx = rand (20, 1);\ny = rand (20, 1);\ntri = delaunay (x, y);\ntriplot (tri, x, y);\n@end group\n@end example\n\n@noindent\nwhich plots the Delaunay triangulation of a set of random points in\n2-dimensions.\n@ifnotinfo\nThe output of the above can be seen in @ref{fig:triplot}.\n\n@float Figure,fig:triplot\n@center @image{triplot,4in}\n@caption{Delaunay triangulation of a random set of points}\n@end float\n@end ifnotinfo\n\n@node Identifying Points in Triangulation\n@subsection Identifying Points in Triangulation\n\nIt is often necessary to identify whether a particular point in the\nN-dimensional space is within the Delaunay tessellation of a set of\npoints in this N-dimensional space, and if so which N-simplex contains\nthe point and which point in the tessellation is closest to the desired\npoint.  The function @code{tsearch} performs this function in a triangulation,\nand the functions @code{tsearchn} and @code{dsearchn} in an N-dimensional\ntessellation.\n\nTo identify whether a particular point represented by a vector @var{p}\nfalls within one of the simplices of an N-simplex, we can write the\nCartesian coordinates of the point in a parametric form with respect to\nthe N-simplex.  This parametric form is called the Barycentric\nCoordinates of the point.  If the points defining the N-simplex are given\nby @var{N} + 1 vectors @code{@var{t}(@var{i},:)}, then the Barycentric\ncoordinates defining the point @var{p} are given by\n\n@example\n@var{p} = @var{beta} * @var{t}\n@end example\n\n@noindent\nwhere @var{beta} contains @var{N} + 1 values that together as a vector\nrepresent the Barycentric coordinates of the point @var{p}.  To ensure a unique\nsolution for the values of @var{beta} an additional criteria of\n\n@example\nsum (@var{beta}) == 1\n@end example\n\n@noindent\nis imposed, and we can therefore write the above as\n\n@example\n@group\n@var{p} - @var{t}(end, :) = @var{beta}(1:end-1) * (@var{t}(1:end-1, :)\n                - ones (@var{N}, 1) * @var{t}(end, :)\n@end group\n@end example\n\n@noindent\nSolving for @var{beta} we can then write\n\n@example\n@group\n@var{beta}(1:end-1) = (@var{p} - @var{t}(end, :)) /\n                (@var{t}(1:end-1, :) - ones (@var{N}, 1) * @var{t}(end, :))\n@var{beta}(end) = sum (@var{beta}(1:end-1))\n@end group\n@end example\n\n@noindent\nwhich gives the formula for the conversion of the Cartesian coordinates\nof the point @var{p} to the Barycentric coordinates @var{beta}.  An\nimportant property of the Barycentric coordinates is that for all points\nin the N-simplex\n\n@example\n0 <= @var{beta}(@var{i}) <= 1\n@end example\n\n@noindent\nTherefore, the test in @code{tsearch} and @code{tsearchn} essentially\nonly needs to express each point in terms of the Barycentric coordinates\nof each of the simplices of the N-simplex and test the values of\n@var{beta}.  This is exactly the implementation used in\n@code{tsearchn}.  @code{tsearch} is optimized for 2-dimensions and the\nBarycentric coordinates are not explicitly formed.\n\n@DOCSTRING(tsearch)\n\n@DOCSTRING(tsearchn)\n\nAn example of the use of @code{tsearch} can be seen with the simple\ntriangulation\n\n@example\n@group\n@var{x} = [-1; -1; 1; 1];\n@var{y} = [-1; 1; -1; 1];\n@var{tri} = [1, 2, 3; 2, 3, 4];\n@end group\n@end example\n\n@noindent\nconsisting of two triangles defined by @var{tri}.  We can then identify\nwhich triangle a point falls in like\n\n@example\n@group\ntsearch (@var{x}, @var{y}, @var{tri}, -0.5, -0.5)\n@xresult{} 1\ntsearch (@var{x}, @var{y}, @var{tri}, 0.5, 0.5)\n@xresult{} 2\n@end group\n@end example\n\n@noindent\nand we can confirm that a point doesn't lie within one of the triangles like\n\n@example\n@group\ntsearch (@var{x}, @var{y}, @var{tri}, 2, 2)\n@xresult{} NaN\n@end group\n@end example\n\nThe @code{dsearchn} function finds the closest point in a tessellation to the\ndesired point.  The desired point does not necessarily have to be in the\ntessellation, and even if it the returned point of the tessellation does not\nhave to be one of the vertices of the N-simplex within which the desired point\nis found.\n\n@DOCSTRING(dsearchn)\n\nAn example of the use of @code{dsearchn}, using the above values of @var{x},\n@var{y} and @var{tri} is\n\n@example\n@group\ndsearchn ([@var{x}, @var{y}], @var{tri}, [-2, -2])\n@xresult{} 1\n@end group\n@end example\n\nIf you wish the points that are outside the tessellation to be flagged,\nthen @code{dsearchn} can be used as\n\n@example\n@group\ndsearchn ([@var{x}, @var{y}], @var{tri}, [-2, -2], NaN)\n@xresult{} NaN\ndsearchn ([@var{x}, @var{y}], @var{tri}, [-0.5, -0.5], NaN)\n@xresult{} 1\n@end group\n@end example\n\n@noindent\nwhere the point outside the tessellation are then flagged with @code{NaN}.\n\n@node Voronoi Diagrams\n@section Voronoi Diagrams\n\nA Voronoi diagram or Voronoi tessellation of a set of points @var{s} in\nan N-dimensional space, is the tessellation of the N-dimensional space\nsuch that all points in @code{@var{v}(@var{p})}, a partitions of the\ntessellation where @var{p} is a member of @var{s}, are closer to @var{p}\nthan any other point in @var{s}.  The Voronoi diagram is related to the\nDelaunay triangulation of a set of points, in that the vertices of the\nVoronoi tessellation are the centers of the circum-circles of the\nsimplices of the Delaunay tessellation.\n\n@DOCSTRING(voronoi)\n\n@DOCSTRING(voronoin)\n\nAn example of the use of @code{voronoi} is\n\n@example\n@group\nrand (\"state\",9);\nx = rand (10,1);\ny = rand (10,1);\ntri = delaunay (x, y);\n[vx, vy] = voronoi (x, y, tri);\ntriplot (tri, x, y, \"b\");\nhold on;\nplot (vx, vy, \"r\");\n@end group\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:voronoi}.  Note that the\ncircum-circle of one of the triangles has been added to this figure, to\nmake the relationship between the Delaunay tessellation and the Voronoi\ndiagram clearer.\n\n@float Figure,fig:voronoi\n@center @image{voronoi,4in}\n@caption{Delaunay triangulation (blue lines) and Voronoi diagram (red lines)\nof a random set of points}\n@end float\n@end ifnotinfo\n\nAdditional information about the size of the facets of a Voronoi\ndiagram, and which points of a set of points is in a polygon can be had\nwith the @code{polyarea} and @code{inpolygon} functions respectively.\n\n@DOCSTRING(polyarea)\n\nAn example of the use of @code{polyarea} might be\n\n@example\n@group\nrand (\"state\", 2);\nx = rand (10, 1);\ny = rand (10, 1);\n[c, f] = voronoin ([x, y]);\naf = zeros (size (f));\nfor i = 1 : length (f)\n  af(i) = polyarea (c (f @{i, :@}, 1), c (f @{i, :@}, 2));\nendfor\n@end group\n@end example\n\nFacets of the Voronoi diagram with a vertex at infinity have infinity\narea.  A simplified version of @code{polyarea} for rectangles is\navailable with @code{rectint}\n\n@DOCSTRING(rectint)\n\n@DOCSTRING(inpolygon)\n\nAn example of the use of @code{inpolygon} might be\n\n@example\n@group\nrandn (\"state\", 2);\nx = randn (100, 1);\ny = randn (100, 1);\nvx = cos (pi * [-1 : 0.1: 1]);\nvy = sin (pi * [-1 : 0.1 : 1]);\nin = inpolygon (x, y, vx, vy);\nplot (vx, vy, x(in), y(in), \"r+\", x(!in), y(!in), \"bo\");\naxis ([-2, 2, -2, 2]);\n@end group\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:inpolygon}.\n\n@float Figure,fig:inpolygon\n@center @image{inpolygon,4in}\n@caption{Demonstration of the @code{inpolygon} function to determine the\npoints inside a polygon}\n@end float\n@end ifnotinfo\n\n@node Convex Hull\n@section Convex Hull\n\nThe convex hull of a set of points is the minimum convex envelope\ncontaining all of the points.  Octave has the functions @code{convhull}\nand @code{convhulln} to calculate the convex hull of 2-dimensional and\nN-dimensional sets of points.\n\n@DOCSTRING(convhull)\n\n@DOCSTRING(convhulln)\n\nAn example of the use of @code{convhull} is\n\n@example\n@group\nx = -3:0.05:3;\ny = abs (sin (x));\nk = convhull (x, y);\nplot (x(k), y(k), \"r-\", x, y, \"b+\");\naxis ([-3.05, 3.05, -0.05, 1.05]);\n@end group\n@end example\n\n@ifnotinfo\n@noindent\nThe output of the above can be seen in @ref{fig:convhull}.\n\n@float Figure,fig:convhull\n@center @image{convhull,4in}\n@caption{The convex hull of a simple set of points}\n@end float\n@end ifnotinfo\n\n@node Interpolation on Scattered Data\n@section Interpolation on Scattered Data\n\nAn important use of the Delaunay tessellation is that it can be used to\ninterpolate from scattered data to an arbitrary set of points.  To do\nthis the N-simplex of the known set of points is calculated with\n@code{delaunay} or @code{delaunayn}.  Then the simplices in to which the\ndesired points are found are identified.  Finally the vertices of the simplices\nare used to interpolate to the desired points.  The functions that perform this\ninterpolation are @code{griddata}, @code{griddata3} and @code{griddatan}.\n\n@DOCSTRING(griddata)\n\n@DOCSTRING(griddata3)\n\n@DOCSTRING(griddatan)\n\nAn example of the use of the @code{griddata} function is\n\n@example\n@group\nrand (\"state\", 1);\nx = 2*rand (1000,1) - 1;\ny = 2*rand (size (x)) - 1;\nz = sin (2*(x.^2+y.^2));\n[xx,yy] = meshgrid (linspace (-1,1,32));\nzz = griddata (x, y, z, xx, yy);\nmesh (xx, yy, zz);\n@end group\n@end example\n\n@noindent\nthat interpolates from a random scattering of points, to a uniform grid.\n@ifnotinfo\nThe output of the above can be seen in @ref{fig:griddata}.\n\n@float Figure,fig:griddata\n@center @image{griddata,4in}\n@caption{Interpolation from a scattered data to a regular grid}\n@end float\n@end ifnotinfo\n\n@node Vector Rotation Matrices\n@section Vector Rotation Matrices\n\nAlso included in Octave's geometry functions are primitive functions to enable\nvector rotations in 3-dimensional space.  Separate functions are provided for\nrotation about each of the principle axes, @var{x}, @var{y}, and @var{z}.\nAccording to Euler's rotation theorem, any arbitrary rotation, @var{R}, of any\nvector, @var{p}, can be expressed as a product of the three principle\nrotations:\n\n@tex\n$p' = R \\cdot p = R_z \\cdot R_y \\cdot R_x \\cdot p$\n@end tex\n@ifnottex\n\n@example\np' = Rp = Rz*Ry*Rx*p\n@end example\n@end ifnottex\n\n@DOCSTRING(rotx)\n\n@DOCSTRING(roty)\n\n@DOCSTRING(rotz)\n"
  },
  {
    "path": "doc/interpreter/geometryimages.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nfunction geometryimages (d, nm, typ)\n\n  if (strcmp (typ, \"txt\"))\n    image_as_txt (d, nm);\n    return;\n  endif\n\n  set_graphics_toolkit ();\n  set_print_size ();\n  hide_output ();\n  outfile = fullfile (d, [nm \".\" typ]);\n  if (strcmp (typ, \"png\"))\n    set (groot, \"defaulttextfontname\", \"*\");\n  endif\n  if (strcmp (typ, \"eps\"))\n    d_typ = \"-depsc2\";\n  else\n    d_typ = [\"-d\" typ];\n  endif\n\n  if (! __have_feature__ (\"QHULL\")\n      && any (strcmp (nm, {\"voronoi\", \"griddata\", \"convhull\", \"delaunay\", ...\n                           \"triplot\"})))\n    sombreroimage (outfile, typ, d_typ);\n  elseif (strcmp (nm, \"voronoi\"))\n    rand (\"state\", 9);\n    x = rand (10, 1);\n    y = rand (10, 1);\n    tri = delaunay (x, y);\n    [vx, vy] = voronoi (x, y, tri);\n    triplot (tri, x, y, \"b\");\n    hold on;\n    plot (vx, vy, \"r\");\n    [r, c] = tri2circ (tri(end,:), x, y);\n    pc = [-1:0.01:1];\n    xc = r * sin (pi*pc) + c(1);\n    yc = r * cos (pi*pc) + c(2);\n    plot (xc, yc, \"g-\", \"LineWidth\", 3);\n    axis ([0, 1, 0, 1]);\n    set (gca, \"dataaspectratio\", [1, 1, 1],\n              \"plotboxaspectratio\", [1, 1, 1]);\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"triplot\"))\n    rand (\"state\", 2)\n    x = rand (20, 1);\n    y = rand (20, 1);\n    tri = delaunay (x, y);\n    triplot (tri, x, y);\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"griddata\"))\n    rand (\"state\", 1);\n    x = 2 * rand (1000,1) - 1;\n    y = 2 * rand (size (x)) - 1;\n    z = sin (2 * (x.^2 + y.^2));\n    [xx,yy] = meshgrid (linspace (-1,1,32));\n    zz = griddata (x, y, z, xx, yy);\n    mesh (xx, yy, zz);\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"convhull\"))\n    x = -3:0.05:3;\n    y = abs (sin (x));\n    k = convhull (x, y);\n    plot (x(k),y(k),'r-', x,y,'b+');\n    axis ([-3.05, 3.05, -0.05, 1.05]);\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"delaunay\"))\n    rand (\"state\", 1);\n    x = rand (1, 10);\n    y = rand (1, 10);\n    T = delaunay (x, y);\n    X = [ x(T(:,1)); x(T(:,2)); x(T(:,3)); x(T(:,1)) ];\n    Y = [ y(T(:,1)); y(T(:,2)); y(T(:,3)); y(T(:,1)) ];\n    axis ([0, 1, 0, 1]);\n    plot (X,Y,\"b\", x,y,\"r*\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"inpolygon\"))\n    randn (\"state\", 2);\n    x = randn (100, 1);\n    y = randn (100, 1);\n    vx = cos (pi * [-1 : 0.1: 1]);\n    vy = sin (pi * [-1 : 0.1 : 1]);\n    in = inpolygon (x, y, vx, vy);\n    plot (vx, vy, x(in), y(in), \"r+\", x(!in), y(!in), \"bo\");\n    axis ([-2, 2, -2, 2]);\n    print (outfile, d_typ);\n  else\n    error (\"unrecognized plot requested\");\n  endif\n  hide_output ();\nendfunction\n\nfunction [r, c] = tri2circ (tri, xx, yy)\n  x = xx(tri);\n  y = yy(tri);\n  m = (y(1:end-1) - y(2:end)) ./ (x(1:end-1) - x(2:end));\n  xc = (prod(m) .* (y(1) - y(end)) + m(end)*(x(1)+x(2)) - m(1)*(x(2)+x(3))) ...\n        ./ (2 * (m(end) - m(1)));\n  yc = - (xc - (x(2) + x(3))./2) ./ m(end) + (y(2) + y(3)) / 2;\n  c = [xc, yc];\n  r = sqrt ((xc - x(1)).^2 + (yc - y(1)).^2);\nendfunction\n\nfunction sombreroimage (outfile, typ, d_typ)\n  if (strcmp (typ, \"txt\"))\n    fid = fopen (outfile, \"wt\");\n    fputs (fid, \"+-----------------------------+\\n\");\n    fputs (fid, \"| Image unavailable because   |\\n\");\n    fputs (fid, \"| of a missing QHULL library. |\\n\");\n    fputs (fid, \"+-----------------------------+\\n\");\n    fclose (fid);\n    return;\n  else\n    [x, y, z] = sombrero ();\n    unwind_protect\n      mesh (x, y, z);\n      title ({\"Sorry, graphics are unavailable because Octave was\",\n              \"compiled without the QHULL library.\"});\n    unwind_protect_cleanup\n      print (outfile, d_typ);\n      hide_output ();\n    end_unwind_protect\n  endif\nendfunction\n\n## This function no longer sets the graphics toolkit; That is now done\n## automatically by C++ code which will ordinarily choose 'qt', but might\n## choose gnuplot on older systems.  Only a complete lack of plotting is a\n## problem.\nfunction set_graphics_toolkit ()\n  if (isempty (available_graphics_toolkits ()))\n    error (\"no graphics toolkit available for plotting\");\n  elseif (strcmp (\"qt\", graphics_toolkit ()))\n    ## Use qt with QOffscreenSurface for plot\n  elseif (! strcmp (\"gnuplot\", graphics_toolkit ()))\n    if (! any (strcmp (\"gnuplot\", available_graphics_toolkits ())))\n      error (\"no graphics toolkit available for offscreen plotting\");\n    else\n      graphics_toolkit (\"gnuplot\");\n    endif\n  endif\nendfunction\n\nfunction set_print_size ()\n  image_size = [5.0, 3.5]; # in inches, 16:9 format\n  border = 0;              # For postscript use 50/72\n  set (groot, \"defaultfigurepapertype\", \"<custom>\");\n  set (groot, \"defaultfigurepaperorientation\", \"landscape\");\n  set (groot, \"defaultfigurepapersize\", image_size + 2*border);\n  set (groot, \"defaultfigurepaperposition\", [border, border, image_size]);\n  ## FIXME: Required until listener for legend exists (bug #39697)\n  set (groot, \"defaultfigureposition\", [ 72*[border, border, image_size] ]);\nendfunction\n\n## Use this function before plotting commands and after every call to print\n## since print() resets output to stdout (unfortunately, gnuplot can't pop\n## output as it can the terminal type).\nfunction hide_output ()\n  hf = figure (1, \"visible\", \"off\");\nendfunction\n\n## generate something for the texinfo @image command to process\nfunction image_as_txt (d, nm)\n  fid = fopen (fullfile (d, [nm \".txt\"]), \"wt\");\n  fputs (fid, \"\\n\");\n  fputs (fid, \"+---------------------------------+\\n\");\n  fputs (fid, \"| Image unavailable in text mode. |\\n\");\n  fputs (fid, \"+---------------------------------+\\n\");\n  fclose (fid);\nendfunction\n"
  },
  {
    "path": "doc/interpreter/gpl.txi",
    "content": "@c Copyright (C) 2007 Free Software Foundation, Inc.\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Copying\n@appendix GNU GENERAL PUBLIC LICENSE\n@cindex warranty\n@cindex copyright\n\n@center Version 3, 29 June 2007\n\n@display\nCopyright @copyright{} 2007 Free Software Foundation, Inc. @url{https://fsf.org/}\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n@end display\n\n@heading Preamble\n\nThe GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\nThe licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom\nto share and change all versions of a program---to make sure it remains\nfree software for all its users.  We, the Free Software Foundation,\nuse the GNU General Public License for most of our software; it\napplies also to any other work released this way by its authors.  You\ncan apply it to your programs, too.\n\nWhen we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\nTo protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you\nhave certain responsibilities if you distribute copies of the\nsoftware, or if you modify it: responsibilities to respect the freedom\nof others.\n\nFor example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too,\nreceive or can get the source code.  And you must show them these\nterms so they know their rights.\n\nDevelopers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\nFor the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\nSome devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the\nmanufacturer can do so.  This is fundamentally incompatible with the\naim of protecting users' freedom to change the software.  The\nsystematic pattern of such abuse occurs in the area of products for\nindividuals to use, which is precisely where it is most unacceptable.\nTherefore, we have designed this version of the GPL to prohibit the\npractice for those products.  If such problems arise substantially in\nother domains, we stand ready to extend this provision to those\ndomains in future versions of the GPL, as needed to protect the\nfreedom of users.\n\nFinally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish\nto avoid the special danger that patents applied to a free program\ncould make it effectively proprietary.  To prevent this, the GPL\nassures that patents cannot be used to render the program non-free.\n\nThe precise terms and conditions for copying, distribution and\nmodification follow.\n\n@heading TERMS AND CONDITIONS\n\n@enumerate 0\n@item Definitions.\n\n``This License'' refers to version 3 of the GNU General Public License.\n\n``Copyright'' also means copyright-like laws that apply to other kinds\nof works, such as semiconductor masks.\n\n``The Program'' refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as ``you''.  ``Licensees'' and\n``recipients'' may be individuals or organizations.\n\nTo ``modify'' a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of\nan exact copy.  The resulting work is called a ``modified version'' of\nthe earlier work or a work ``based on'' the earlier work.\n\nA ``covered work'' means either the unmodified Program or a work based\non the Program.\n\nTo ``propagate'' a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\nTo ``convey'' a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user\nthrough a computer network, with no transfer of a copy, is not\nconveying.\n\nAn interactive user interface displays ``Appropriate Legal Notices'' to\nthe extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n@item Source Code.\n\nThe ``source code'' for a work means the preferred form of the work for\nmaking modifications to it.  ``Object code'' means any non-source form\nof a work.\n\nA ``Standard Interface'' means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\nThe ``System Libraries'' of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n``Major Component'', in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\nThe ``Corresponding Source'' for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users can\nregenerate automatically from other parts of the Corresponding Source.\n\nThe Corresponding Source for a work in source code form is that same\nwork.\n\n@item Basic Permissions.\n\nAll rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\nYou may make, run and propagate covered works that you do not convey,\nwithout conditions so long as your license otherwise remains in force.\nYou may convey covered works to others for the sole purpose of having\nthem make modifications exclusively for you, or provide you with\nfacilities for running those works, provided that you comply with the\nterms of this License in conveying all material for which you do not\ncontrol copyright.  Those thus making or running the covered works for\nyou must do so exclusively on your behalf, under your direction and\ncontrol, on terms that prohibit them from making any copies of your\ncopyrighted material outside their relationship with you.\n\nConveying under any other circumstances is permitted solely under the\nconditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n@item Protecting Users' Legal Rights From Anti-Circumvention Law.\n\nNo covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\nWhen you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such\ncircumvention is effected by exercising rights under this License with\nrespect to the covered work, and you disclaim any intention to limit\noperation or modification of the work as a means of enforcing, against\nthe work's users, your or third parties' legal rights to forbid\ncircumvention of technological measures.\n\n@item Conveying Verbatim Copies.\n\nYou may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\nYou may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n@item Conveying Modified Source Versions.\n\nYou may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these\nconditions:\n\n@enumerate a\n@item\nThe work must carry prominent notices stating that you modified it,\nand giving a relevant date.\n\n@item\nThe work must carry prominent notices stating that it is released\nunder this License and any conditions added under section 7.  This\nrequirement modifies the requirement in section 4 to ``keep intact all\nnotices''.\n\n@item\nYou must license the entire work, as a whole, under this License to\nanyone who comes into possession of a copy.  This License will\ntherefore apply, along with any applicable section 7 additional terms,\nto the whole of the work, and all its parts, regardless of how they\nare packaged.  This License gives no permission to license the work in\nany other way, but it does not invalidate such permission if you have\nseparately received it.\n\n@item\nIf the work has interactive user interfaces, each must display\nAppropriate Legal Notices; however, if the Program has interactive\ninterfaces that do not display Appropriate Legal Notices, your work\nneed not make them do so.\n@end enumerate\n\nA compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n``aggregate'' if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n@item  Conveying Non-Source Forms.\n\nYou may convey a covered work in object code form under the terms of\nsections 4 and 5, provided that you also convey the machine-readable\nCorresponding Source under the terms of this License, in one of these\nways:\n\n@enumerate a\n@item\nConvey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by the\nCorresponding Source fixed on a durable physical medium customarily\nused for software interchange.\n\n@item\nConvey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by a written\noffer, valid for at least three years and valid for as long as you\noffer spare parts or customer support for that product model, to give\nanyone who possesses the object code either (1) a copy of the\nCorresponding Source for all the software in the product that is\ncovered by this License, on a durable physical medium customarily used\nfor software interchange, for a price no more than your reasonable\ncost of physically performing this conveying of source, or (2) access\nto copy the Corresponding Source from a network server at no charge.\n\n@item\nConvey individual copies of the object code with a copy of the written\noffer to provide the Corresponding Source.  This alternative is\nallowed only occasionally and noncommercially, and only if you\nreceived the object code with such an offer, in accord with subsection\n6b.\n\n@item\nConvey the object code by offering access from a designated place\n(gratis or for a charge), and offer equivalent access to the\nCorresponding Source in the same way through the same place at no\nfurther charge.  You need not require recipients to copy the\nCorresponding Source along with the object code.  If the place to copy\nthe object code is a network server, the Corresponding Source may be\non a different server (operated by you or a third party) that supports\nequivalent copying facilities, provided you maintain clear directions\nnext to the object code saying where to find the Corresponding Source.\nRegardless of what server hosts the Corresponding Source, you remain\nobligated to ensure that it is available for as long as needed to\nsatisfy these requirements.\n\n@item\nConvey the object code using peer-to-peer transmission, provided you\ninform other peers where the object code and Corresponding Source of\nthe work are being offered to the general public at no charge under\nsubsection 6d.\n\n@end enumerate\n\nA separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\nA ``User Product'' is either (1) a ``consumer product'', which means any\ntangible personal property which is normally used for personal,\nfamily, or household purposes, or (2) anything designed or sold for\nincorporation into a dwelling.  In determining whether a product is a\nconsumer product, doubtful cases shall be resolved in favor of\ncoverage.  For a particular product received by a particular user,\n``normally used'' refers to a typical or common use of that class of\nproduct, regardless of the status of the particular user or of the way\nin which the particular user actually uses, or expects or is expected\nto use, the product.  A product is a consumer product regardless of\nwhether the product has substantial commercial, industrial or\nnon-consumer uses, unless such uses represent the only significant\nmode of use of the product.\n\n``Installation Information'' for a User Product means any methods,\nprocedures, authorization keys, or other information required to\ninstall and execute modified versions of a covered work in that User\nProduct from a modified version of its Corresponding Source.  The\ninformation must suffice to ensure that the continued functioning of\nthe modified object code is in no case prevented or interfered with\nsolely because modification has been made.\n\nIf you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\nThe requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or\nupdates for a work that has been modified or installed by the\nrecipient, or for the User Product in which it has been modified or\ninstalled.  Access to a network may be denied when the modification\nitself materially and adversely affects the operation of the network\nor violates the rules and protocols for communication across the\nnetwork.\n\nCorresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n@item Additional Terms.\n\n``Additional permissions'' are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\nWhen you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders\nof that material) supplement the terms of this License with terms:\n\n@enumerate a\n@item\nDisclaiming warranty or limiting liability differently from the terms\nof sections 15 and 16 of this License; or\n\n@item\nRequiring preservation of specified reasonable legal notices or author\nattributions in that material or in the Appropriate Legal Notices\ndisplayed by works containing it; or\n\n@item\nProhibiting misrepresentation of the origin of that material, or\nrequiring that modified versions of such material be marked in\nreasonable ways as different from the original version; or\n\n@item\nLimiting the use for publicity purposes of names of licensors or\nauthors of the material; or\n\n@item\nDeclining to grant rights under trademark law for use of some trade\nnames, trademarks, or service marks; or\n\n@item\nRequiring indemnification of licensors and authors of that material by\nanyone who conveys the material (or modified versions of it) with\ncontractual assumptions of liability to the recipient, for any\nliability that these contractual assumptions directly impose on those\nlicensors and authors.\n@end enumerate\n\nAll other non-permissive additional terms are considered ``further\nrestrictions'' within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions; the\nabove requirements apply either way.\n\n@item Termination.\n\nYou may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\nHowever, if you cease all violation of this License, then your license\nfrom a particular copyright holder is reinstated (a) provisionally,\nunless and until the copyright holder explicitly and finally\nterminates your license, and (b) permanently, if the copyright holder\nfails to notify you of the violation by some reasonable means prior to\n60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\nTermination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n@item Acceptance Not Required for Having Copies.\n\nYou are not required to accept this License in order to receive or run\na copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n@item Automatic Licensing of Downstream Recipients.\n\nEach time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\nAn ``entity transaction'' is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n@item Patents.\n\nA ``contributor'' is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's ``contributor version''.\n\nA contributor's ``essential patent claims'' are all patent claims owned\nor controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, ``control'' includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\nIn the following three paragraphs, a ``patent license'' is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To ``grant'' such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  ``Knowingly relying'' means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\nA patent license is ``discriminatory'' if it does not include within the\nscope of its coverage, prohibits the exercise of, or is conditioned on\nthe non-exercise of one or more of the rights that are specifically\ngranted under this License.  You may not convey a covered work if you\nare a party to an arrangement with a third party that is in the\nbusiness of distributing software, under which you make payment to the\nthird party based on the extent of your activity of conveying the\nwork, and under which the third party grants, to any of the parties\nwho would receive the covered work from you, a discriminatory patent\nlicense (a) in connection with copies of the covered work conveyed by\nyou (or copies made from those copies), or (b) primarily for and in\nconnection with specific products or compilations that contain the\ncovered work, unless you entered into that arrangement, or that patent\nlicense was granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n@item No Surrender of Others' Freedom.\n\nIf conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey\na covered work so as to satisfy simultaneously your obligations under\nthis License and any other pertinent obligations, then as a\nconsequence you may not convey it at all.  For example, if you agree\nto terms that obligate you to collect a royalty for further conveying\nfrom those to whom you convey the Program, the only way you could\nsatisfy both those terms and this License would be to refrain entirely\nfrom conveying the Program.\n\n@item Use with the GNU Affero General Public License.\n\nNotwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n@item Revised Versions of this License.\n\nThe Free Software Foundation may publish revised and/or new versions\nof the GNU General Public License from time to time.  Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies that a certain numbered version of the GNU General Public\nLicense ``or any later version'' applies to it, you have the option of\nfollowing the terms and conditions either of that numbered version or\nof any later version published by the Free Software Foundation.  If\nthe Program does not specify a version number of the GNU General\nPublic License, you may choose any version ever published by the Free\nSoftware Foundation.\n\nIf the Program specifies that a proxy can decide which future versions\nof the GNU General Public License can be used, that proxy's public\nstatement of acceptance of a version permanently authorizes you to\nchoose that version for the Program.\n\nLater license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n@item Disclaimer of Warranty.\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW@.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT\nWARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE@.  THE ENTIRE RISK AS TO THE QUALITY AND\nPERFORMANCE OF THE PROGRAM IS WITH YOU@.  SHOULD THE PROGRAM PROVE\nDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR\nCORRECTION.\n\n@item Limitation of Liability.\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR\nCONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES\nARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT\nNOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR\nLOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM\nTO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER\nPARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n@item Interpretation of Sections 15 and 16.\n\nIf the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n@end enumerate\n\n@heading END OF TERMS AND CONDITIONS\n\n@heading How to Apply These Terms to Your New Programs\n\nIf you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these\nterms.\n\nTo do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe ``copyright'' line and a pointer to where the full notice is found.\n\n@smallexample\n@var{one line to give the program's name and a brief idea of what it does.}\nCopyright (C) @var{year} @var{name of author}\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or (at\nyour option) any later version.\n\nThis program is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE@.  See the GNU\nGeneral Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see @url{https://www.gnu.org/licenses/}.\n@end smallexample\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n@smallexample\n@var{program} Copyright (C) @var{year} @var{name of author}\nThis program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}.\nThis is free software, and you are welcome to redistribute it\nunder certain conditions; type @samp{show c} for details.\n@end smallexample\n\nThe hypothetical commands @samp{show w} and @samp{show c} should show\nthe appropriate parts of the General Public License.  Of course, your\nprogram's commands might be different; for a GUI interface, you would\nuse an ``about box''.\n\nYou should also get your employer (if you work as a programmer) or school,\nif any, to sign a ``copyright disclaimer'' for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n@url{https://www.gnu.org/licenses/}.\n\nThe GNU General Public License does not permit incorporating your\nprogram into proprietary programs.  If your program is a subroutine\nlibrary, you may consider it more useful to permit linking proprietary\napplications with the library.  If this is what you want to do, use\nthe GNU Lesser General Public License instead of this License.  But\nfirst, please read @url{https://www.gnu.org/licenses/why-not-lgpl.html}.\n"
  },
  {
    "path": "doc/interpreter/grammar.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Grammar and Parser\n@appendix Grammar and Parser\n@cindex grammar rules\n@cindex language definition\n\nThis appendix will eventually contain a semi-formal description of Octave's\nlanguage.\n\n@menu\n* Keywords::\n* Parser::\n@end menu\n\n@node Keywords\n@section Keywords\n@cindex keywords\n\nThe function @code{iskeyword} can be used to check whether an identifier is\nreserved by Octave.\n\n@DOCSTRING(iskeyword)\n\n@subsubheading Keyword Categories\n\n@ref{XREFkwcategoryVariableDeclaration,,@w{Variable Declaration}}@: |\n@ref{XREFkwcategoryFunctionDefinition,,@w{Function Definition}}@: |\n@ref{XREFkwcategoryControlStructures,,@w{Control Statements}}@: |\n@ref{XREFkwcategoryIteratingStructures,,@w{Iterating Structures}}@: |\n@ref{XREFkwcategoryClassdefStructures,,@w{Classdef Structures}}@: |\n@ref{XREFkwcategoryExecutionEnvironment,,@w{Execution Environment}}@:\n\n@subsubheading Alphabetical Keyword Listing\n\nThe identifiers below are keywords, and may not be used as variable or function\nnames.\n\n@noindent\n@ref{XREF__FILE__,,__FILE__}@: |\n@ref{XREF__LINE__,,__LINE__}@: |\n@ref{XREFarguments,,arguments}@: |\n@ref{XREFbreak,,break}@: |\n@ref{XREFcase,,case}@: |\n@ref{XREFcatch,,catch}@: |\n@ref{XREFclassdef,,classdef}@: |\n@ref{XREFcontinue,,continue}@: |\n@ref{XREFdo,,do}@: |\n@ref{XREFelse,,else}@: |\n@ref{XREFelseif,,elseif}@: |\n@ref{XREFend,,end}@: |\n@ref{XREFend_try_catch,,end_try_catch}@: |\n@ref{XREFend_unwind_protect,,end_unwind_protect}@: |\n@ref{XREFendarguments,,endarguments}@: |\n@ref{XREFendclassdef,,endclassdef}@: |\n@ref{XREFendenumeration,,endenumeration}@: |\n@ref{XREFendevents,,endevents}@: |\n@ref{XREFendfor,,endfor}@: |\n@ref{XREFendfunction,,endfunction}@: |\n@ref{XREFendif,,endif}@: |\n@ref{XREFendmethods,,endmethods}@: |\n@ref{XREFendparfor,,endparfor}@: |\n@ref{XREFendproperties,,endproperties}@: |\n@ref{XREFendswitch,,endswitch}@: |\n@ref{XREFendwhile,,endwhile}@: |\n@ref{XREFenumeration,,enumeration}@: |\n@ref{XREFevents,,events}@: |\n@ref{XREFfor,,for}@: |\n@ref{XREFfunction,,function}@: |\n@ref{XREFglobal,,global}@: |\n@ref{XREFif,,if}@: |\n@ref{XREFkwpropertymethods,,methods}@: |\n@ref{XREFotherwise,,otherwise}@: |\n@ref{XREFparfor,,parfor}@: |\n@ref{XREFpersistent,,persistent}@: |\n@ref{XREFkwpropertyproperties,,properties}@: |\n@ref{XREFreturn,,return}@: |\n@ref{XREFswitch,,switch}@: |\n@ref{XREFtry,,try}@: |\n@ref{XREFuntil,,until}@: |\n@ref{XREFunwind_protect,,unwind_protect}@: |\n@ref{XREFunwind_protect_cleanup,,unwind_protect_cleanup}@: |\n@ref{XREFwhile,,while}@:\n\n\n@anchor{XREFkwcategoryVariableDeclaration}\n@subheading Variable Declaration\n\n@DOCSTRING(global)\n\n@DOCSTRING(persistent)\n\n@anchor{XREFkwcategoryFunctionDefinition}\n@subheading Function Definition\n\n@DOCSTRING(function)\n\n@DOCSTRING(endfunction)\n\n@DOCSTRING(end)\n\n@DOCSTRING(return)\n\n@DOCSTRING(arguments)\n\n@DOCSTRING(endarguments)\n\n@anchor{XREFkwcategoryControlStructures}\n@subheading Control Statements\n\n@DOCSTRING(if)\n\n@DOCSTRING(else)\n\n@DOCSTRING(elseif)\n\n@DOCSTRING(endif)\n\n@DOCSTRING(switch)\n\n@DOCSTRING(case)\n\n@DOCSTRING(otherwise)\n\n@DOCSTRING(endswitch)\n\n@DOCSTRING(try)\n\n@DOCSTRING(catch)\n\n@DOCSTRING(end_try_catch)\n\n@DOCSTRING(unwind_protect)\n\n@DOCSTRING(unwind_protect_cleanup)\n\n@DOCSTRING(end_unwind_protect)\n\n@anchor{XREFkwcategoryIteratingStructures}\n@subheading Iterating Structures\n\n@DOCSTRING(for)\n\n@DOCSTRING(endfor)\n\n@DOCSTRING(while)\n\n@DOCSTRING(endwhile)\n\n@DOCSTRING(do)\n\n@DOCSTRING(until)\n\n@DOCSTRING(parfor)\n\n@DOCSTRING(endparfor)\n\n@DOCSTRING(break)\n\n@DOCSTRING(continue)\n\n@anchor{XREFkwcategoryClassdefStructures}\n@subheading Classdef Structures\n\n@DOCSTRING(classdef)\n\n@DOCSTRING(endclassdef)\n\n@c properties definition must be manually created to avoid\n@c collision with function of the same name.\n@anchor{XREFkwpropertyproperties}\n@html\n<span style=\"display:block; margin-top:-4.5ex;\">&nbsp;</span>\n@end html\n\n@deftypefn {} {} properties\nMark the beginning of a block of properties in a classdef definition.\n\nNote that the @ref{XREFproperties,,function @qcode{\"properties\"}} is not a\nkeyword, but rather an ordinary function that lists the properties of a classdef\nclass or object.\n@seealso{@ref{XREFendproperties,,endproperties}}\n@end deftypefn\n\n@DOCSTRING(endproperties)\n\n@c methods definition must be manually created to avoid\n@c collision with function of the same name.\n@anchor{XREFkwpropertymethods}\n@html\n<span style=\"display:block; margin-top:-4.5ex;\">&nbsp;</span>\n@end html\n\n@deftypefn {} {} methods\nMark the beginning of a block of methods in a classdef definition.\n\nNote that the @ref{XREFmethods,,function @qcode{\"methods\"}} is not a keyword,\nbut rather an ordinary function that lists the methods of a class or object.\n@seealso{@ref{XREFendmethods,,endmethods}}\n@end deftypefn\n\n@DOCSTRING(endmethods)\n\n@DOCSTRING(events)\n\n@DOCSTRING(endevents)\n\n@DOCSTRING(enumeration)\n\n@DOCSTRING(endenumeration)\n\n@anchor{XREFkwcategoryExecutionEnvironment}\n@subheading Execution Environment\n\n@DOCSTRING(__FILE__)\n\n@DOCSTRING(__LINE__)\n\n@node Parser\n@section Parser\n@cindex parser\n\nThe parser has a number of variables that affect its internal operation.\nThese variables are generally documented in the manual alongside the code that\nthey affect.\n\nIn addition, there are three non-specific parser customization functions.\n@w{@code{add_input_event_hook}} can be used to schedule a user function for\nperiodic evaluation.  @w{@code{remove_input_event_hook}} will stop a user\nfunction from being evaluated periodically.\n\n@DOCSTRING(add_input_event_hook)\n\n@DOCSTRING(remove_input_event_hook)\n\nFinally, when the parser cannot identify an input token it calls a particular\nfunction to handle this.  By default, this is the internal function\n@qcode{\"__unimplemented__\"} which makes suggestions about possible Octave\nsubstitutes for @sc{matlab} functions.\n\n@DOCSTRING(missing_function_hook)\n\n@subheading Syntax Errors\n\n@DOCSTRING(diagnostics_show_caret)\n"
  },
  {
    "path": "doc/interpreter/graphics-properties.mk",
    "content": "GRAPH_PROP_TEXI_SRC= \\\n  interpreter/plot-axesproperties.texi \\\n  interpreter/plot-figureproperties.texi \\\n  interpreter/plot-imageproperties.texi \\\n  interpreter/plot-lineproperties.texi \\\n  interpreter/plot-patchproperties.texi \\\n  interpreter/plot-rootproperties.texi \\\n  interpreter/plot-scatterproperties.texi \\\n  interpreter/plot-surfaceproperties.texi \\\n  interpreter/plot-textproperties.texi\n\ndefine gen-propdoc-texi\n  rm -f $@-t $@ && \\\n  $(top_builddir)/run-octave -disable-asan --norc --quiet --no-history --path $(srcdir)/interpreter --eval \"genpropdoc ('$(1)');\" > $@-t && \\\n  mv $@-t $@\nendef\n\ninterpreter/plot-axesproperties.texi: interpreter/genpropdoc.m\n\t$(AM_V_GEN)$(call gen-propdoc-texi,axes)\n\ninterpreter/plot-figureproperties.texi: interpreter/genpropdoc.m\n\t$(AM_V_GEN)$(call gen-propdoc-texi,figure)\n\ninterpreter/plot-imageproperties.texi: interpreter/genpropdoc.m\n\t$(AM_V_GEN)$(call gen-propdoc-texi,image)\n\ninterpreter/plot-lineproperties.texi: interpreter/genpropdoc.m\n\t$(AM_V_GEN)$(call gen-propdoc-texi,line)\n\ninterpreter/plot-patchproperties.texi: interpreter/genpropdoc.m\n\t$(AM_V_GEN)$(call gen-propdoc-texi,patch)\n\ninterpreter/plot-rootproperties.texi: interpreter/genpropdoc.m\n\t$(AM_V_GEN)$(call gen-propdoc-texi,root)\n\ninterpreter/plot-surfaceproperties.texi: interpreter/genpropdoc.m\n\t$(AM_V_GEN)$(call gen-propdoc-texi,surface)\n\ninterpreter/plot-scatterproperties.texi: interpreter/genpropdoc.m\n\t$(AM_V_GEN)$(call gen-propdoc-texi,scatter)\n\ninterpreter/plot-textproperties.texi: interpreter/genpropdoc.m\n\t$(AM_V_GEN)$(call gen-propdoc-texi,text)\n"
  },
  {
    "path": "doc/interpreter/gui.txi",
    "content": "@c Copyright (C) 2012-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node GUI Development\n@chapter GUI Development\n\nOctave is principally a batch or command-line language.  However, it does\noffer some features for constructing graphical interfaces that interact with\nusers.\n\nThe GUI elements available are I/O dialogs, a progress bar, and UI elements\nfor plot windows.  For example, rather than hardcoding a filename for output\nresults a script can open a dialog box and allow the user to choose a file.\nSimilarly, if a calculation is expected to take a long time a script can\ndisplay a progress bar.  The various UI elements can be used to fully customize\nthe plot window with menubars, toolbars, context menus, pushbuttons, sliders,\netc.\n\nSeveral utility functions make it possible to store private data for use with\na GUI which will not pollute the user's variable space.\n\nFinally, a program written in Octave might want to have long term storage of\npreferences or state variables.  This can be done with user-defined\npreferences.\n\n@menu\n* I/O Dialogs::\n* Progress Bar::\n* UI Elements::\n* GUI Utility Functions::\n* User-Defined Preferences::\n* Octave Workspace Windows::\n@end menu\n\n@node I/O Dialogs\n@section I/O Dialogs\n\nSimple dialog menus are available for choosing directories or files.  They\nreturn a string variable which can then be used with any command requiring\na filename.\n\n@cindex dialog, displaying a dialog for selecting directories\n@DOCSTRING(uigetdir)\n\n@cindex dialog, displaying a dialog for selecting files\n@DOCSTRING(uigetfile)\n\n@cindex dialog, displaying a dialog for storing files\n@DOCSTRING(uiputfile)\n\nAdditionally, there are dialog boxes for displaying help messages, warnings, or\nerrors, and for getting text input from the user.\n\n@cindex dialog, displaying an error dialog\n@DOCSTRING(errordlg)\n\n@cindex dialog, displaying a help dialog\n@DOCSTRING(helpdlg)\n\n@cindex dialog, displaying an input dialog\n@DOCSTRING(inputdlg)\n\n@cindex dialog, displaying a list dialog\n@DOCSTRING(listdlg)\n\n@cindex dialog, displaying a message dialog\n@DOCSTRING(msgbox)\n\n@cindex dialog, displaying a question dialog\n@DOCSTRING(questdlg)\n\n@cindex dialog, displaying a warning dialog\n@DOCSTRING(warndlg)\n\n@cindex dialog, displaying a font selection dialog\n@DOCSTRING(uisetfont)\n\nFor creating new dialog types, there is a dialog function.\n\n@cindex dialog, displaying a modal dialog\n@DOCSTRING(dialog)\n\n@node Progress Bar\n@section Progress Bar\n@cindex Progress Bar\n\n@DOCSTRING(waitbar)\n\n@node UI Elements\n@section UI Elements\n\nThe @nospell{ui*} series of functions work best with the @code{qt} graphics\ntoolkit, although some functionality is available with the @code{fltk} toolkit.\nThere is no support for the @code{gnuplot} toolkit.\n\n@DOCSTRING(uifigure)\n\n@DOCSTRING(uipanel)\n\n@DOCSTRING(uibuttongroup)\n\n@DOCSTRING(uicontrol)\n\n@DOCSTRING(uitable)\n\n@DOCSTRING(uimenu)\n\n@DOCSTRING(uicontextmenu)\n\n@DOCSTRING(uitoolbar)\n\n@DOCSTRING(uipushtool)\n\n@DOCSTRING(uitoggletool)\n\n@node GUI Utility Functions\n@section GUI Utility Functions\n\nThese functions do not implement a GUI element but are useful when developing\nprograms that do.  The functions @code{uiwait}, @code{uiresume}, and\n@code{waitfor} are only available with the @code{qt} or @code{fltk} toolkits.\n\n@DOCSTRING(guidata)\n\n@DOCSTRING(guihandles)\n\n@DOCSTRING(have_window_system)\n\n@DOCSTRING(isguirunning)\n\n@DOCSTRING(getpixelposition)\n\n@DOCSTRING(listfonts)\n\n@DOCSTRING(movegui)\n\n@DOCSTRING(openvar)\n\n@DOCSTRING(uiwait)\n\n@DOCSTRING(uiresume)\n\n@DOCSTRING(waitfor)\n\n@node User-Defined Preferences\n@section User-Defined Preferences\n\n@DOCSTRING(getpref)\n\n@DOCSTRING(setpref)\n\n@DOCSTRING(addpref)\n\n@DOCSTRING(rmpref)\n\n@DOCSTRING(ispref)\n\n@DOCSTRING(prefdir)\n\n@DOCSTRING(preferences)\n\n@node Octave Workspace Windows\n@section Octave Workspace Windows\n\nThe functions below make windows that are a part of Octave's own GUI interface\nvisible, and move the keyboard focus to the selected window.  Their utility\nlies in the ability to call these functions from a script and highlight a\nwindow without using a mouse for selection.\n\n@DOCSTRING(commandhistory)\n\n@DOCSTRING(commandwindow)\n\n@DOCSTRING(filebrowser)\n\n@DOCSTRING(workspace)\n"
  },
  {
    "path": "doc/interpreter/image.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Image Processing\n@chapter Image Processing\n\nSince an image is basically a matrix, Octave is a very powerful\nenvironment for processing and analyzing images.  To illustrate\nhow easy it is to do image processing in Octave, the following\nexample will load an image, smooth it by a 5-by-5 averaging filter,\nand compute the gradient of the smoothed image.\n\n@example\n@group\nI = imread (\"myimage.jpg\");\nS = conv2 (I, ones (5, 5) / 25, \"same\");\n[Dx, Dy] = gradient (S);\n@end group\n@end example\n\n@noindent\nIn this example @code{S} contains the smoothed image, and @code{Dx}\nand @code{Dy} contains the partial spatial derivatives of the image.\n\n@menu\n* Loading and Saving Images::\n* Displaying Images::\n* Representing Images::\n* Plotting on top of Images::\n* Color Conversion::\n@end menu\n\n@node Loading and Saving Images\n@section Loading and Saving Images\n\nThe first step in most image processing tasks is to load an image\ninto Octave which is done with the @code{imread} function.\nThe @code{imwrite} function is the corresponding function\nfor writing images to the disk.\n\nIn summary, most image processing code will follow the structure of this code\n\n@example\n@group\nI = imread (\"my_input_image.img\");\nJ = process_my_image (I);\nimwrite (J, \"my_output_image.img\");\n@end group\n@end example\n\n@DOCSTRING(imread)\n\n@DOCSTRING(imwrite)\n\n@DOCSTRING(IMAGE_PATH)\n\nIt is possible to get information about an image file on disk, without actually\nreading it into Octave.  This is done using the @code{imfinfo} function which\nprovides read access to many of the parameters stored in the header of the\nimage file.\n\n@DOCSTRING(imfinfo)\n\nBy default, Octave's image IO functions (@code{imread}, @code{imwrite},\nand @code{imfinfo}) use the @code{GraphicsMagick} library for their\noperations.  This means a vast number of image formats is supported\nbut considering the large amount of image formats in science and\nits commonly closed nature, it is impossible to have a library\ncapable of reading them all.  Because of this, the function\n@code{imformats} keeps a configurable list of available formats,\ntheir extensions, and what functions should the image IO functions\nuse.  This allows one to expand Octave's image IO capabilities by\ncreating functions aimed at acting on specific file formats.\n\nWhile it would be possible to call the extra functions directly,\nproperly configuring Octave with @code{imformats} allows one to keep a\nconsistent code that is abstracted from file formats.\n\nIt is important to note that a file format is not actually defined by its\nfile extension and that @code{GraphicsMagick} is capable to read and write\nmore file formats than the ones listed by @code{imformats}.  What this\nmeans is that even with an incorrect or missing extension the image may\nstill be read correctly, and that even unlisted formats are not necessarily\nunsupported.\n\n@DOCSTRING(imformats)\n\n@node Displaying Images\n@section Displaying Images\n\nA natural part of image processing is visualization of an image.\nThe most basic function for this is the @code{imshow} function that\nshows the image given in the first input argument.\n\n@DOCSTRING(imshow)\n\n@DOCSTRING(image)\n\n@DOCSTRING(imagesc)\n\n@node Representing Images\n@section Representing Images\n\nIn general Octave supports four different kinds of images, grayscale\nimages, RGB images, binary images, and indexed images.  A grayscale\nimage is represented with an M-by-N matrix in which each\nelement corresponds to the intensity of a pixel.  An RGB image is\nrepresented with an M-by-N-by-3 array where each\n3-vector corresponds to the red, green, and blue intensities of each\npixel.\n\nThe actual meaning of the value of a pixel in a grayscale or RGB\nimage depends on the class of the matrix.  If the matrix is of class\n@code{double} pixel intensities are between 0 and 1, if it is of class\n@code{uint8} intensities are between 0 and 255, and if it is of class\n@code{uint16} intensities are between 0 and 65535.\n\nA binary image is an M-by-N matrix of class @code{logical}.\nA pixel in a binary image is black if it is @code{false} and white\nif it is @code{true}.\n\nAn indexed image consists of an M-by-N matrix of integers\nand a C-by-3 colormap.  Each integer corresponds to an\nindex in the colormap, and each row in the colormap corresponds to\nan RGB color.  The colormap must be of class @code{double} with values\nbetween 0 and 1.\n\nThe following convenience functions are available for conversion between image\nformats.\n\n@DOCSTRING(im2double)\n\n@DOCSTRING(gray2ind)\n\n@DOCSTRING(ind2gray)\n\n@DOCSTRING(rgb2ind)\n\n@DOCSTRING(ind2rgb)\n\nThe following function allows processing an existing image.\n\n@DOCSTRING(dither)\n\nOctave also provides tools to produce and work with movie frame structures.\nThose structures encapsulate the image data (@qcode{\"cdata\"} field) together\nwith the corresponding colormap (@qcode{\"colormap\"} field).\n\n@DOCSTRING(getframe)\n\n@DOCSTRING(movie)\n\n@DOCSTRING(frame2im)\n\n@DOCSTRING(im2frame)\n\nThe @code{colormap} function is used to change the colormap of the current\naxes or figure.\n\n@DOCSTRING(colormap)\n\n@DOCSTRING(iscolormap)\n\nThe following functions return predefined colormaps, the same that can be\nrequested by name using the @code{colormap} function.\n\n@DOCSTRING(rgbplot)\n\n@DOCSTRING(autumn)\n\n@DOCSTRING(bone)\n\n@DOCSTRING(colorcube)\n\n@DOCSTRING(cool)\n\n@DOCSTRING(copper)\n\n@DOCSTRING(cubehelix)\n\n@DOCSTRING(flag)\n\n@DOCSTRING(gray)\n\n@DOCSTRING(hot)\n\n@DOCSTRING(hsv)\n\n@DOCSTRING(jet)\n\n@DOCSTRING(lines)\n\n@DOCSTRING(ocean)\n\n@DOCSTRING(pink)\n\n@DOCSTRING(prism)\n\n@DOCSTRING(rainbow)\n\n@DOCSTRING(spring)\n\n@DOCSTRING(summer)\n\n@DOCSTRING(turbo)\n\n@DOCSTRING(viridis)\n\n@DOCSTRING(white)\n\n@DOCSTRING(winter)\n\n@DOCSTRING(contrast)\n\nThe following three functions modify the existing colormap rather than\nreplace it.\n\n@DOCSTRING(brighten)\n\n@DOCSTRING(spinmap)\n\n@DOCSTRING(whitebg)\n\nThe following functions can be used to manipulate colormaps.\n\n@DOCSTRING(cmunique)\n\n@DOCSTRING(cmpermute)\n\n@node Plotting on top of Images\n@section Plotting on top of Images\n\nIf gnuplot is being used to display images it is possible to plot on\ntop of images.  Since an image is a matrix it is indexed by row and\ncolumn values.  The plotting system is, however, based on the\ntraditional @math{(x, y)} system.  To minimize the difference between\nthe two systems Octave places the origin of the coordinate system in\nthe point corresponding to the pixel at @math{(1, 1)}.  So, to plot\npoints given by row and column values on top of an image, one should\nsimply call @code{plot} with the column values as the first argument\nand the row values as the second.  As an example the following code\ngenerates an image with random intensities between 0 and 1, and shows\nthe image with red circles over pixels with an intensity above\n@math{0.99}.\n\n@example\n@group\nI = rand (100, 100);\n[row, col] = find (I > 0.99);\nhold (\"on\");\nimshow (I);\nplot (col, row, \"ro\");\nhold (\"off\");\n@end group\n@end example\n\n@node Color Conversion\n@section Color Conversion\n\nOctave supports conversion from the RGB color system to the HSV color system\nand vice versa.  It is also possible to convert from a color RGB image to a\ngrayscale image.\n\n@DOCSTRING(rgb2hsv)\n\n@DOCSTRING(hsv2rgb)\n\n@DOCSTRING(rgb2gray)\n"
  },
  {
    "path": "doc/interpreter/images",
    "content": "geometryimages.m voronoi triplot griddata convhull delaunay inpolygon\ninterpimages.m interpft interpn interpderiv1 interpderiv2\nplotimages.m plot hist errorbar polar mesh plot3 extended precisiondate\nsparseimages.m gplot grid spmatrix spchol spcholperm\nsplineimages.m splinefit1 splinefit2 splinefit3 splinefit4 splinefit6\n"
  },
  {
    "path": "doc/interpreter/images.awk",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nBEGIN {\n  print \"## DO NOT EDIT -- generated from module-files by images.awk\";\n  print \"\";\n  print \"if AMCOND_BUILD_DOCS\";\n\n  if (dir !~ /\\/$/)\n      dir = dir \"/\";\n\n  exts[1] = \"eps\";\n  exts[2] = \"pdf\";\n  exts[3] = \"png\";\n  exts[4] = \"txt\";\n} {\n  script = $1;\n  basename = script;\n  sub (/\\.m$/, \"\", basename);\n  ubasename = toupper (basename);\n  printf (\"DOC_IMAGES_SRC += %s%s\\n\", dir, script);\n  for (i = 1; i <= 4; i++) {\n    ext = exts[i];\n    uext = toupper (ext);\n\n    printf (\"%s_%s =\", ubasename, uext);\n    for (j = 2; j <= NF; j++)\n      printf (\" %s%s.%s\", dir, $j, ext);\n    printf (\"\\n\");\n\n    printf (\"BUILT_DOC_IMAGES_%s += $(%s_%s)\\n\", uext, ubasename, uext);\n\n    for (j = 2; j <= NF; j++) {\n      printf (\"%s%s.%s: %s%s\\n\", dir, $j, ext, dir, script);\n      printf (\"\\t$(AM_V_GEN)$(SHELL) run-octave -disable-asan --norc --quiet --no-history --path $(abs_top_srcdir)/%s --eval \\\"%s ('%s', '%s', '%s');\\\"\\n\",\n              dir, basename, dir, $j, ext);\n    }\n  }\n}\nEND {\n  print \"endif\";\n  print \"\";\n  print \"doc_MAINTAINERCLEANFILES += $(srcdir)/%reldir%/images.mk\";\n}\n"
  },
  {
    "path": "doc/interpreter/install.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@c The text of this file appears in the file INSTALL in the Octave\n@c distribution, as well as in the Octave manual.\n\n@ifclear INSTALLONLY\n@node Installing Octave\n@appendix Installing Octave\n@end ifclear\n\n@ifset INSTALLONLY\n@include macros.texi\n\nThis file documents the installation of Octave.\n\nOctave is free software: you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by the\nFree Software Foundation.\n\n@strong{Note}: This file is automatically generated from\n@file{doc/interpreter/install.txi} in the Octave sources.  To update\nthe documentation make changes to the .txi source file rather than this\nderived file.\n\n@node Installing Octave\n@chapter Installing Octave\n@end ifset\n\n@cindex installing Octave\n\nThe procedure for installing Octave from source on a Unix-like system is\ndescribed next.  Building on other platforms will follow similar\nsteps.  Note that this description applies to Octave releases.  Building\nthe development sources from the Mercurial archive requires additional\nsteps as described in the development source itself.\n\n@menu\n* Build Dependencies::\n* Running Configure and Make::\n* Compiling Octave with 64-bit Indexing::\n* Installation Problems::\n@end menu\n\n@node Build Dependencies\n@section Build Dependencies\n\nOctave is a fairly large program with many build dependencies.  You may\nbe able to find pre-packaged versions of the dependencies distributed as\npart of your system, or you may have to build some or all of them\nyourself.\n\n@menu\n* Obtaining the Dependencies Automatically::\n* Build Tools::\n* External Packages::\n@end menu\n\n@node Obtaining the Dependencies Automatically\n@subsection Obtaining the Dependencies Automatically\n\nOn some systems you can obtain many of Octave's build dependencies\nautomatically.  The commands for doing this vary by system.  Similarly, the\nnames of pre-compiled packages vary by system and do not always match exactly\nthe names listed in @ref{Build Tools} and @ref{External Packages}.\n\nYou will usually need the development version of an external dependency\nso that you get the libraries and header files for building software,\nnot just for running already compiled programs.  These packages\ntypically have names that end with the suffix @code{-dev} or @code{-devel}.\n\nOn systems with @code{apt-get} (Debian, Ubuntu, etc.), you may be able\nto install most of the tools and external packages using a command\nsimilar to\n\n@example\napt-get build-dep octave\n@end example\n\n@noindent\nThe specific package name may be @code{octave3.2} or @code{octave3.4}.\nThe set of required tools and external dependencies does not change\nfrequently, so it is not important that the version match exactly, but\nyou should use the most recent one available.\n\nOn systems with @code{yum} (Fedora, Red Hat, etc.), you may be able to\ninstall most of the tools and external packages using a command similar to\n\n@example\nyum-builddep octave\n@end example\n\n@noindent\nThe @code{yum-builddep} utility is part of the @code{yum-utils} package.\n\nFor either type of system, the package name may include a version\nnumber.  The set of required tools and external dependencies does not\nchange frequently, so it is not important that the version exactly match\nthe version you are installing, but you should use the most recent one\navailable.\n\n@node Build Tools\n@subsection Build Tools\n\nThe following tools are required:\n\n@table @asis\n@item C++, C, and Fortran compilers\nThe Octave sources are primarily written in C++, but some portions are\nalso written in C and Fortran.  The Octave sources are intended to be\nportable.  Recent versions of the GNU compiler collection (GCC) should\nwork (@url{https://gcc.gnu.org}).  If you use GCC, you should avoid\nmixing versions.  For example, be sure that you are not using the\nobsolete @code{g77} Fortran compiler with modern versions of @code{gcc}\nand @code{g++}.\n\n@item GNU Make\nTool for building software (@url{https://www.gnu.org/software/make}).\nOctave's build system requires GNU Make.  Other versions of Make will\nnot work.  Fortunately, GNU Make is highly portable and easy to install.\n\n@item AWK, sed, and other Unix utilities\nBasic Unix system utilities are required for building Octave.  All will\nbe available with any modern Unix system and also on Windows with either\nCygwin or MinGW and MSYS.\n@end table\n\nAdditionally, the following tools may be needed:\n\n@table @asis\n@item Bison\nParser generator (@url{https://www.gnu.org/software/bison}).\nYou will need Bison if you modify the @code{oct-parse.yy} source file or\nif you delete the files that are generated from it.\n\n@item Flex\nLexer analyzer (@url{https://www.gnu.org/software/flex}).  You will need\nFlex if you modify the @code{lex.ll} source file or if you delete the\nfiles that are generated from it.\n\n@item Autoconf\nPackage for software configuration\n(@url{https://www.gnu.org/software/autoconf}).  Autoconf is required if\nyou modify Octave's @code{configure.ac} file or other files that it\nrequires.\n\n@item Automake\nPackage for Makefile generation\n(@url{https://www.gnu.org/software/automake}).  Automake is required if\nyou modify Octave's @code{Makefile.am} files or other files that they\ndepend on.\n\n@item Libtool\nPackage for building software libraries\n(@url{https://www.gnu.org/software/libtool}).  Libtool is required by\nAutomake.\n\n@item gperf\nPerfect hash function generator (@url{https://www.gnu.org/software/gperf}).\nYou will need gperf if you modify the @code{octave.gperf} file or if you\ndelete the file that is generated from it.\n\n@item Texinfo\nPackage for generating online and print documentation\n(@url{https://www.gnu.org/software/texinfo}).  You will need Texinfo to\nbuild Octave's documentation or if you modify the documentation source\nfiles or the docstring of any Octave function.\n@end table\n\n@node External Packages\n@subsection External Packages\n\nThe following external packages are required:\n\n@table @asis\n@item BLAS\nBasic Linear Algebra Subroutine library.  Accelerated @sc{blas} libraries such\nas OpenBLAS (@url{https://www.openblas.net/}) or\nATLAS (@url{http://math-atlas.sourceforge.net}) are recommended for best\nperformance.  The reference implementation (@url{http://www.netlib.org/blas})\nis slow and suffers from certain bugs in corner case inputs.\n\n@item LAPACK\nLinear Algebra Package (@url{http://www.netlib.org/lapack}).\n\n@item PCRE\nThe Perl Compatible Regular Expression library (@url{https://www.pcre.org}).\n@end table\n\nThe following external package is optional but strongly recommended:\n\n@table @asis\n@item GNU Readline\nCommand-line editing library (@url{https://www.gnu.org/s/readline}).\n@end table\n\nIf you wish to build Octave without GNU readline installed, you must use\nthe @option{--disable-readline} option when running the configure script.\n\nThe following external software packages are optional.  Octave can be\nbuilt without them but certain features might be missing:\n\n@table @asis\n@item ARPACK\nLibrary for the solution of large-scale eigenvalue problems\n(@url{https://forge.scilab.org/index.php/p/arpack-ng}).  @sc{arpack} is\nrequired to provide the functions @code{eigs} and @code{svds}.\n\n@item cURL\nLibrary for transferring data with URL syntax\n(@url{https://curl.haxx.se}).  cURL is required to provide the\n@code{urlread} and @code{urlwrite} functions and the @code{ftp} class.\n\n@item FFTW3\nLibrary for computing discrete Fourier transforms\n(@url{http://www.fftw.org}).  FFTW3 is used to provide better\nperformance for functions that compute discrete Fourier transforms\n(@code{fft}, @code{ifft}, @code{fft2}, etc.)\n\n@item FLTK\nPortable GUI toolkit (@url{http://www.fltk.org}).  FLTK can be\nused to provide windows for Octave's OpenGL-based graphics functions.\n\n@item fontconfig\nLibrary for configuring and customizing font access\n(@url{https://www.freedesktop.org/wiki/Software/fontconfig}).  Fontconfig\nis used to manage fonts for Octave's OpenGL-based graphics functions.\n\n@item FreeType\nPortable font engine (@url{https://www.freetype.org}).  FreeType is used\nto perform font rendering for Octave's OpenGL-based graphics functions.\n\n@item GLPK\nGNU Linear Programming Kit (@url{https://www.gnu.org/software/glpk}).\nGPLK is required for the function @code{glpk}.\n\n@item @nospell{gl2ps}\nOpenGL to PostScript printing library (@url{https://www.geuz.org/gl2ps/}).\n@nospell{gl2ps} is required for printing when using OpenGL-based\ngraphics toolkits (currently either FLTK or Qt).\n\n@item gnuplot\nInteractive graphics program (@url{http://www.gnuplot.info}).  gnuplot\ncan be used as a graphics renderer for Octave; prior to Octave 4.0,\ngnuplot was the default graphics renderer.\n\n@item GraphicsMagick++\nImage processing library (@url{http://www.graphicsmagick.org}).\nGraphicsMagick++ is used to provide the @code{imread} and @code{imwrite}\nfunctions.\n\n@item HDF5\nLibrary for manipulating portable data files\n(@url{https://www.hdfgroup.org/HDF5}).  @sc{hdf5} is required for Octave's\n@code{load} and @code{save} commands to read and write HDF data files.\n\n@item Java Development Kit\nJava programming language compiler and libraries.  The OpenJDK free\nsoftware implementation is recommended (@url{http://openjdk.java.net/}),\nalthough other JDK implementations may work.  Java is required to be able\nto call Java functions from within Octave.\n\n@item OpenGL\nAPI for portable 2-D and 3-D graphics (@url{https://www.opengl.org}).  An\nOpenGL implementation can be used to provide a renderer for Octave's\ngraphics functions.  Octave's OpenGL-based graphics functions usually\noutperform the gnuplot-based graphics functions because plot data can be\nrendered directly instead of sending data and commands to gnuplot for\ninterpretation and rendering.  Since Octave 4.0, the default graphics\nrenderer (@qcode{\"qt\"}) has been OpenGL-based.\n\n@item PortAudio\nPortAudio (@url{http://www.portaudio.com/}) provides a very simple API\nfor recording and/or playing sound using a simple callback function or\na blocking read/write interface.  It is required for the audio processing\nfunctions @code{audioplayer}, @code{audiorecorder}, and\n@code{audiodevinfo}.\n\n@item Qhull\nComputational geometry library (@url{http://www.qhull.org}).  Qhull is\nrequired to provide the functions @code{convhull}, @code{convhulln},\n@code{delaunay}, @code{delaunayn}, @code{voronoi}, and @code{voronoin}.\n\n@item QRUPDATE\nQR factorization updating library\n(@url{https://sourceforge.net/projects/qrupdate}).  QRUPDATE is used to\nprovide improved performance for the functions @code{qrdelete},\n@code{qrinsert}, @code{qrshift}, and @code{qrupdate}.\n\n@item QScintilla\nSource code highlighter and manipulator; a Qt port of Scintilla\n(@url{http://www.riverbankcomputing.co.uk/software/qscintilla}).\nQScintilla is used for syntax highlighting and code completion in the\nGUI.\n\n@item Qt\nGUI and utility libraries (@url{https://www.qt.io}).  Qt is required for\nbuilding the GUI@.  It is a large framework, but the only components\nrequired are the GUI, core, and network modules.  Since Octave 4.0, the\ndefault graphics renderer (@qcode{\"qt\"}) has been Qt-based, which has\nbeen OpenGL-based.\n\n@item RapidJSON\nA fast JSON parser/generator for C++ with both @nospell{SAX/DOM} style API\n(@url{https://rapidjson.org/}).  RapidJSON is required to read or write\nfrom or to JSON files with the functions @code{jsondecode} and\n@code{jsonencode}.\n\n@item SuiteSparse\nSparse matrix factorization library\n(@url{http://faculty.cse.tamu.edu/davis/suitesparse.html}).\nSuiteSparse is required to provide sparse matrix factorizations and\nsolution of linear equations for sparse systems.\n\n@item SUNDIALS\n@nospell{The SUite of Nonlinear and DIfferential/ALgebraic Equation Solvers}\n(@url{https://computation.llnl.gov/projects/sundials}) is required for\nthe Ordinary Differential Equations (ODE) solvers @code{ode15i} and\n@code{ode15s}.\n\n@item zlib\nData compression library (@url{https://zlib.net}).  The zlib library is\nrequired for Octave's @code{load} and @code{save} commands to handle\ncompressed data, including @sc{matlab} v5 MAT files.\n@end table\n\n@node Running Configure and Make\n@section Running Configure and Make\n\n@itemize @bullet\n@item\nRun the shell script @file{configure}.  This will determine the features\nyour system has (or doesn't have) and create a file named\n@file{Makefile} from each of the files named @file{Makefile.in}.\n\nFor a complete list of configure options, run @file{configure --help}.\nHere is a summary of the configure options that are most frequently used\nwhen building Octave:\n\n@table @code\n@item --help\nPrint a summary of the options recognized by the configure script.\n\n@item --prefix=@var{prefix}\nInstall Octave in subdirectories below @var{prefix}.  The default value\nof @var{prefix} is @file{/usr/local}.\n\n@item --srcdir=@var{dir}\nLook for Octave sources in the directory @var{dir}.\n\n@item --disable-64\nDisable using 64-bit integers for indexing arrays and use 32-bit\nintegers instead.  On systems with 32-bit pointers, this option is\nalways disabled.  If the configure script determines that your @sc{blas}\nlibrary uses 32-bit integers, then operations using the following\nlibraries are limited to arrays with dimensions that are smaller than\n@math{2^{31}} elements:\n\n@itemize @bullet\n@item @sc{blas}\n\n@item @sc{lapack}\n\n@item QRUPDATE\n\n@item SuiteSparse\n\n@item @sc{arpack}\n@end itemize\n\nAdditionally, the following libraries use @code{int} internally, so\nmaximum problem sizes are always limited:\n\n@itemize @bullet\n@item @sc{glpk}\n\n@item Qhull\n@end itemize\n\n@xref{Compiling Octave with 64-bit Indexing}, for more details\nabout building Octave with more complete support for large arrays.\n\n@item --enable-address-sanitizer-flags\nEnable compiler options @option{-fsanitize=address} and\n@option{-fomit-frame-pointer} for memory access checking.  This option is\nprimarily used for debugging Octave.  Building Octave with this option\nhas a negative impact on performance and is not recommended for general\nuse.  It may also interfere with proper functioning of the GUI.\n\n@item --disable-docs\nDisable building all forms of the documentation (Info, PDF, HTML).  The\ndefault is to build documentation, but your system will need functioning\nTexinfo and @TeX{} installs for this to succeed.\n\n@item --enable-float-truncate\nThis option allows for truncation of intermediate floating point results\nin calculations.  It is only necessary for certain platforms.\n\n@item --enable-readline\nUse the readline library to provide for editing of the command line in\nterminal environments.  This option is on by default.\n\n@item --enable-shared\nCreate shared libraries (this is the default).  If you are planning to\nuse the dynamic loading features, you will probably want to use this\noption.  It will make your @file{.oct} files much smaller and on some\nsystems it may be necessary to build shared libraries in order to use\ndynamically linked functions.\n\nYou may also want to build a shared version of @code{libstdc++}, if your\nsystem doesn't already have one.\n\n@item --with-blas=<lib>\nBy default, configure looks for the best @sc{blas} matrix libraries on\nyour system, including optimized implementations such as the free ATLAS\n3.0, as well as vendor-tuned libraries.  (The use of an optimized\n@sc{blas} will generally result in several-times faster matrix\noperations.)  Use this option to specify a particular @sc{blas} library\nthat Octave should use.\n\n@item --with-lapack=<lib>\nBy default, configure looks for the best @sc{lapack} matrix libraries on\nyour system, including optimized implementations such as the free ATLAS\n3.0, as well as vendor-tuned libraries.  (The use of an optimized\n@sc{lapack} will generally result in several-times faster matrix\noperations.)  Use this option to specify a particular @sc{lapack}\nlibrary that Octave should use.\n\n@item --with-magick=<lib>\nSelect the Magick++ library to use for image I/O@.  For many\ndistributions, possible values are @qcode{\"GraphicsMagick++\"} (default)\nor @qcode{\"ImageMagick++\"}.\n\n@item --with-sepchar=<char>\nUse <char> as the path separation character.  This option can help when\nrunning Octave on non-Unix systems.\n\n@item --without-amd\nDon't use @sc{amd}, disable some sparse matrix functionality.\n\n@item --without-camd\nDon't use @sc{camd}, disable some sparse matrix functionality.\n\n@item --without-colamd\nDon't use @sc{colamd}, disable some sparse matrix functionality.\n\n@item --without-ccolamd\nDon't use @sc{ccolamd}, disable some sparse matrix functionality.\n\n@item --without-cholmod\nDon't use @sc{cholmod}, disable some sparse matrix functionality.\n\n@item --without-curl\nDon't use the cURL library, disable the ftp objects, @code{urlread} and\n@code{urlwrite} functions.\n\n@item --without-cxsparse\nDon't use @sc{cxsparse}, disable some sparse matrix functionality.\n\n@item --without-fftw3\nUse the included @sc{fftpack} library for computing Fast Fourier\nTransforms instead of the @sc{fftw3} library.\n\n@item --without-fftw3f\nUse the included @sc{fftpack} library for computing Fast Fourier\nTransforms instead of the @sc{fftw3} library when operating on single\nprecision (float) values.\n\n@item --without-glpk\nDon't use the @sc{glpk} library for linear programming.\n\n@item --without-hdf5\nDon't use the @sc{hdf5} library, disable reading and writing of\n@sc{hdf5} files.\n\n@item --without-opengl\nDon't use OpenGL, disable native graphics toolkit for plotting.  You\nwill need @code{gnuplot} installed in order to make plots.\n\n@item --without-qhull_r\nDon't use (re-entrant) Qhull, disable @code{delaunay}, @code{convhull},\nand related functions.\n\n@item --without-qrupdate\nDon't use @sc{qrupdate}, disable QR and Cholesky update functions.\n\n@item --without-umfpack\nDon't use @sc{umfpack}, disable some sparse matrix functionality.\n\n@item --without-z\nDon't use the zlib library, disable data file compression and support\nfor recent MAT file formats.\n\n@item --without-framework-carbon\nDon't use framework Carbon headers, libraries, or specific source code\neven if the configure test succeeds (the default is to use Carbon\nframework if available).  This is a platform specific configure option\nfor Mac systems.\n\n@item --without-framework-opengl\nDon't use framework OpenGL headers, libraries, or specific source code\neven if the configure test succeeds.  If this option is given then\nOpenGL headers and libraries in standard system locations are tested\n(the default value is @option{--with-framework-opengl}).  This is a\nplatform specific configure option for Mac systems.\n\n@end table\n\nSee the file @file{INSTALL} for more general information about the\ncommand line options used by configure.  That file also contains\ninstructions for compiling in a directory other than the one where\nthe source is located.\n\n@item\nRun make.\n\nYou will need a recent version of GNU Make as Octave relies on certain\nfeatures not generally available in all versions of make.  Modifying\nOctave's makefiles to work with other make programs is probably not\nworth your time; instead, we simply recommend installing GNU Make.\n\nThere are currently three options for plotting in Octave: the external\nprogram gnuplot, the internal graphics engine using OpenGL coupled with\neither FLTK or Qt widgets.  Gnuplot is a command-driven interactive\nfunction plotting program.\n\nTo compile Octave, you will need a recent version of @code{g++} or other\nANSI C++ compiler.  In addition, you will need a Fortran 77 compiler or\n@code{f2c}.  If you use @code{f2c}, you will need a script like\n@code{fort77} that works like a normal Fortran compiler by combining\n@code{f2c} with your C compiler in a single script.\n\nIf you plan to modify the parser you will also need GNU @code{bison} and\n@code{flex}.  If you modify the documentation, you will need GNU\nTexinfo.\n\nGNU Make, @code{gcc} (and @code{libstdc++}), @code{gnuplot},\n@code{bison}, @code{flex}, and Texinfo are all available from many\nanonymous ftp archives.  The primary site is @url{ftp://ftp.gnu.org}, but it\nis often very busy.  A list of sites that mirror the software on\n@url{ftp://ftp.gnu.org} is available by anonymous ftp from\n@url{ftp://ftp.gnu.org/pub/gnu/GNUinfo/FTP}.\n\nOctave requires approximately 1.4 GB of disk storage to unpack and\ncompile from source (significantly less, 400 MB, if you don't compile\nwith debugging symbols).  To compile without debugging symbols try the\ncommand\n\n@example\nmake CFLAGS=-O CXXFLAGS=-O LDFLAGS=\n@end example\n\n@noindent\ninstead of just @command{make}.\n\n@item\nIf you encounter errors while compiling Octave, first\nsee @ref{Installation Problems} for a list of\nknown problems and if there is a workaround or solution for\nyour problem.  If not, see\n@ifclear INSTALLONLY\n@ref{Trouble}\n@end ifclear\n@ifset INSTALLONLY\nthe file BUGS\n@end ifset\nfor information about how to report bugs.\n\n@item\nOnce you have successfully compiled Octave, run @code{make install}.\n\nThis will install a copy of Octave, its libraries, and its documentation\nin the destination directory.  As distributed, Octave is installed in\nthe following directories.  In the table below, @var{prefix} defaults to\n@file{/usr/local}, @var{version} stands for the current version number\nof the interpreter, and @var{arch} is the type of computer on which\nOctave is installed (for example, @samp{i586-unknown-gnu}).\n\n@table @file\n@item @var{prefix}/bin\nOctave and other binaries that people will want to run directly.\n\n@item @var{prefix}/lib/octave-@var{version}\nLibraries like liboctave.a and liboctinterp.a.\n\n@item @var{prefix}/include/octave-@var{version}/octave\nInclude files distributed with Octave.\n\n@item @var{prefix}/share\nArchitecture-independent data files.\n\n@item @var{prefix}/share/man/man1\nUnix-style man pages describing Octave.\n\n@item @var{prefix}/share/info\nInfo files describing Octave.\n\n@item @var{prefix}/share/octave/@var{version}/m\nFunction files distributed with Octave.  This includes the Octave\nversion, so that multiple versions of Octave may be installed at the\nsame time.\n\n@item @var{prefix}/libexec/octave/@var{version}/exec/@var{arch}\nExecutables to be run by Octave rather than the user.\n\n@item @var{prefix}/lib/octave/@var{version}/oct/@var{arch}\nObject files that will be dynamically loaded.\n\n@item @var{prefix}/share/octave/@var{version}/imagelib\nImage files that are distributed with Octave.\n@end table\n@end itemize\n\n@node Compiling Octave with 64-bit Indexing\n@section Compiling Octave with 64-bit Indexing\n\nNote: the following only applies to systems that have 64-bit pointers.\nConfiguring Octave with @option{--enable-64} cannot magically make a\n32-bit system have a 64-bit address space.\n\nOn 64-bit systems, Octave uses 64-bit integers for indexing arrays\nby default.  If the configure script determines that your @sc{blas}\nlibrary uses 32-bit integers, then operations using the following\nlibraries are limited to arrays with dimensions that are smaller than\n@math{2^{31}} elements:\n\n@itemize @bullet\n@item @sc{blas}\n\n@item @sc{lapack}\n\n@item QRUPDATE\n\n@item SuiteSparse\n\n@item @sc{sundials @nospell{ida}}\n\n@item @sc{arpack}\n@end itemize\n\nAdditionally, the following libraries use @code{int} internally, so\nmaximum problem sizes are always limited:\n\n@itemize @bullet\n@item @sc{glpk}\n\n@item Qhull\n@end itemize\n\nExcept for @sc{glpk} and Qhull, these libraries may also be configured\nto use 64-bit integers, but most systems do not provide packages built\nthis way.  If you wish to experiment with large arrays, the following\ninformation may be helpful.\n\nTo determine the integer size of the @sc{blas} library used by Octave, the\nfollowing code can be executed:\n\n@example\n@group\nclear all;\nN = 2^31;\n## The following line requires about 8 GB of RAM!\na = b = ones (N, 1, \"single\");\nc = a' * b\n@end group\n@end example\n\nIf the @sc{blas} library uses 32-bit integers, an error will be thrown:\n\n@example\n@group\nerror: integer dimension or index out of range for Fortran\nINTEGER type\n@end group\n@end example\n\nOtherwise, if the @sc{blas} library uses 64-bit integers, the result is:\n\n@example\nc = 2^31 = 2147483648\n@end example\n\nNote that the test case above usually requires twice the memory, if\n@var{a} and @var{b} are not assigned by @code{a = b = @dots{}}.\nNote further, that the data type @code{single} has a precision of\nabout 23 binary bits.  In this particular example no rounding errors\noccur.\n\nGenerally, it is best to have all of these libraries in versions that\nsupport 32-bit indexing, or all of these libraries must support 64-bit\nindexing.  Mixing libraries with 64-bit indexing with libraries with\n32-bit indexing can cause unpredictable behavior including program\ncrashes with possible loss of data.\n\nThe following instructions were tested with the development version of\nOctave and GCC 4.3.4 on an x86_64 Debian system and may be out of date\nnow.  Please report any problems or corrections on the Octave bug\ntracker.\n\nThe versions listed below are the versions used for testing.  If newer\nversions of these packages are available, you should try to use them,\nalthough there may be some differences.\n\nAll libraries and header files will be installed in subdirectories of\n@code{$prefix64} (you must choose the location of this directory).\n\n@itemize @bullet\n@item @sc{blas} and @sc{lapack} (@url{http://www.netlib.org/lapack})\n\nReference versions for both libraries are included in the reference\n@sc{lapack} 3.2.1 distribution from @url{http://www.netlib.org/}.\n\n@itemize @minus\n@item\nCopy the file @file{make.inc.example} and name it @file{make.inc}.\nThe options @option{-fdefault-integer-8} and @option{-fPIC} (on 64-bit\nCPU) have to be added to the variable @code{OPTS} and @code{NOOPT}.\n\n@item\nOnce you have compiled this library make sure that you use it for\ncompiling Suite Sparse and Octave.  In the following we assume that\nyou installed the @sc{lapack} library as $prefix64/lib/liblapack.a.\n@end itemize\n\n@item QRUPDATE (@url{https://sourceforge.net/projects/qrupdate})\n\nIn the @file{Makeconf} file:\n\n@itemize @minus\n@item\nAdd @option{-fdefault-integer-8} to @env{FFLAGS}.\n\n@item\nAdjust the @sc{blas} and @sc{lapack} variables as needed if your 64-bit\naware @sc{blas} and @sc{lapack} libraries are in a non-standard\nlocation.\n\n@item\nSet @env{PREFIX} to the top-level directory of your install tree.\n\n@item\nRun @code{make solib} to make a shared library.\n\n@item\nRun @code{make install} to install the library.\n@end itemize\n\n@item\nSuiteSparse (@url{http://faculty.cse.tamu.edu/davis/suitesparse.html})\n\nPass the following options to @command{make} to enable 64-bit integers\nfor @sc{blas} library calls.  On 64-bit Windows systems, use\n@code{-DLONGBLAS=\"long long\"} instead.\n\n@example\n@group\nCFLAGS='-DLONGBLAS=long'\nCXXFLAGS='-DLONGBLAS=long'\n@end group\n@end example\n\nThe SuiteSparse makefiles don't generate shared libraries.  On some\nsystems, you can generate them by doing something as simple as\n\n@example\n@group\ntop=$(pwd)\nfor f in *.a; do\n  mkdir tmp\n  cd tmp\n  ar vx ../$f\n  gcc -shared -o ../$@{f%%.a@}.so *.o\n  cd $top\n  rm -rf tmp\ndone\n@end group\n@end example\n\n@noindent\nOther systems may require a different solution.\n\n@item @sc{sundials @nospell{ida}}\n(@url{https://computing.llnl.gov/projects/sundials/ida})\n\nWhen configuring with @code{cmake} add the flag\n@option{-DSUNDIALS_INDEX_SIZE=64}.\n\n@item @sc{arpack} (@url{https://forge.scilab.org/index.php/p/arpack-ng/})\n\n@itemize @minus\n@item Add @option{-fdefault-integer-8} to @env{FFLAGS} when running configure.\n\n@item Run @code{make} to build the library.\n\n@item Run @code{make install} to install the library.\n@end itemize\n\n@item ATLAS instead of reference @sc{blas} and @sc{lapack}\n\nSuggestions on how to compile ATLAS would be most welcome.\n\n@item @sc{glpk}\n\n@item Qhull (@url{http://www.qhull.org})\n\nBoth @sc{glpk} and Qhull use @code{int} internally so maximum problem\nsizes may be limited.\n\n@item Octave\n\nOctave's 64-bit index support is activated with the configure option\n@option{--enable-64}.\n\n@example\n@group\n./configure \\\n  LD_LIBRARY_PATH=\"$prefix64/lib\" \\\n  CPPFLAGS=\"-I$prefix64/include\" LDFLAGS=\"-L$prefix64/lib\" \\\n  --enable-64\n@end group\n@end example\n\nYou must ensure that all Fortran sources, except those in the\n@file{liboctave/external/ranlib} directory, are compiled such that INTEGERS are\n8-bytes wide.  If you are using gfortran, the configure script should\nautomatically set the Makefile variable @w{@env{F77_INTEGER_8_FLAG}}@ to\n@option{-fdefault-integer-8}.  If you are using another compiler, you\nmust set this variable yourself.  You should NOT set this flag in\n@env{FFLAGS}, otherwise the files in @file{liboctave/external/ranlib} will be\nmiscompiled.\n\n@item Other dependencies\n\nProbably nothing special needs to be done for the following\ndependencies.  If you discover that something does need to be done,\nplease submit a bug report.\n\n@itemize @minus\n@item pcre\n\n@item zlib\n\n@item hdf5\n\n@item fftw3\n\n@item cURL\n\n@item GraphicsMagick++\n\n@item OpenGL\n\n@item freetype\n\n@item fontconfig\n\n@item fltk\n@end itemize\n\n@end itemize\n\n@node Installation Problems\n@section Installation Problems\n\nThis section contains a list of problems (and some apparent problems\nthat don't really mean anything is wrong) that may show up during\ninstallation of Octave.\n\n@itemize @bullet\n@item\nOn some @nospell{SCO} systems, @code{info} fails to compile if\n@w{@code{HAVE_TERMIOS_H}}@ is defined in @file{config.h}.  Simply\nremoving the definition from @file{info/config.h} should allow it to\ncompile.\n\n@item\nIf @code{configure} finds @code{dlopen}, @code{dlsym}, @code{dlclose},\nand @code{dlerror}, but not the header file @file{dlfcn.h}, you need to\nfind the source for the header file and install it in the directory\n@file{usr/include}.  This is reportedly a problem with Slackware 3.1.\nFor Linux/GNU systems, the source for @file{dlfcn.h} is in the\n@code{ldso} package.\n\n@item\nBuilding @file{.oct} files doesn't work.\n\nYou should probably have a shared version of @code{libstdc++}.  A patch\nis needed to build shared versions of version 2.7.2 of @code{libstdc++}\non the HP-PA architecture.  You can find the patch at\n@url{ftp://ftp.cygnus.com/pub/g++/libg++-2.7.2-hppa-gcc-fix}.\n\n@item\nOn some DEC alpha systems there may be a problem with the @code{libdxml}\nlibrary, resulting in floating point errors and/or segmentation faults\nin the linear algebra routines called by Octave.  If you encounter such\nproblems, then you should modify the configure script so that\n@w{@code{SPECIAL_MATH_LIB}}@ is not set to @code{-ldxml}.\n\n@item\nOn FreeBSD systems Octave may hang while initializing some internal\nconstants.  The fix appears to be to use\n\n@example\noptions      GPL_MATH_EMULATE\n@end example\n\n@noindent\nrather than\n\n@example\noptions      MATH_EMULATE\n@end example\n\n@noindent\nin the kernel configuration files (typically found in the directory\n@file{/sys/i386/conf}).  After making this change, you'll need to rebuild\nthe kernel, install it, and reboot.\n\n@item\nIf you encounter errors like\n\n@example\n@group\npassing `void (*)()' as argument 2 of\n  `octave_set_signal_handler(int, void (*)(int))'\n@end group\n@end example\n\n@noindent\nor\n\n@example\n@group\nwarning: ANSI C++ prohibits conversion from `(int)'\n         to `(@dots{})'\n@end group\n@end example\n\n@noindent\nwhile compiling @file{sighandlers.cc}, you may need to edit some files\nin the @code{gcc} include subdirectory to add proper prototypes for\nfunctions there.  For example, @nospell{Ultrix} 4.2 needs proper declarations\nfor the @code{signal} function and the @w{@code{SIG_IGN}}@ macro in the file\n@file{signal.h}.\n\nOn some systems the @w{@code{SIG_IGN}}@ macro is defined to be something\nlike this:\n\n@example\n#define  SIG_IGN  (void (*)())1\n@end example\n\n@noindent\nwhen it should really be something like:\n\n@example\n#define  SIG_IGN  (void (*)(int))1\n@end example\n\n@noindent\nto match the prototype declaration for the @code{signal} function.  This\nchange should also be made for the @w{@code{SIG_DFL}}@ and\n@w{@code{SIG_ERR}}@ symbols.  It may be necessary to change the\ndefinitions in @file{sys/signal.h} as well.\n\nThe @code{gcc} @code{fixincludes} and @code{fixproto} scripts should\nprobably fix these problems when @code{gcc} installs its modified set of\nheader files, but I don't think that's been done yet.\n\n@strong{You should not change the files in @file{/usr/include}}.  You\ncan find the @code{gcc} include directory tree by running the command\n\n@example\ngcc -print-libgcc-file-name\n@end example\n\n@noindent\nThe directory of @code{gcc} include files normally begins in the same\ndirectory that contains the file @file{libgcc.a}.\n\n@item\nSome of the Fortran subroutines may fail to compile with older versions\nof the Sun Fortran compiler.  If you get errors like\n\n@example\n@group\nzgemm.f:\n        zgemm:\nwarning: unexpected parent of complex expression subtree\nzgemm.f, line 245: warning: unexpected parent of complex\n  expression subtree\nwarning: unexpected parent of complex expression subtree\nzgemm.f, line 304: warning: unexpected parent of complex\n  expression subtree\nwarning: unexpected parent of complex expression subtree\nzgemm.f, line 327: warning: unexpected parent of complex\n  expression subtree\npcc_binval: missing IR_CONV in complex op\nmake[2]: *** [zgemm.o] Error 1\n@end group\n@end example\n\n@noindent\nwhen compiling the Fortran subroutines in the @file{liboctave/external}\nsubdirectory, you should either upgrade your compiler or try compiling\nwith optimization turned off.\n\n@item\nOn @nospell{NeXT} systems, if you get errors like this:\n\n@example\n@group\n/usr/tmp/cc007458.s:unknown:Undefined local\n      symbol LBB7656\n/usr/tmp/cc007458.s:unknown:Undefined local\n      symbol LBE7656\n@end group\n@end example\n\n@noindent\nwhen compiling @file{Array.cc} and @file{Matrix.cc}, try recompiling\nthese files without @option{-g}.\n\n@item\nSome people have reported that calls to system() and the pager do not\nwork on @nospell{SunOS} systems.  This is apparently due to having\n@w{@code{G_HAVE_SYS_WAIT}}@ defined to be 0 instead of 1 when compiling\n@code{libg++}.\n\n@item\nOn systems where the reference @sc{blas} library is used the following\nmatrix-by-vector multiplication incorrectly handles NaN values of the\nform @code{NaN * 0}.\n\n@example\n@group\n[NaN, 1; 0, 0] * [0; 1]\n@xresult{}\n[ 1\n  0 ]\n\ncorrect result @xresult{}\n[ NaN\n  0   ]\n@end group\n@end example\n\nInstall a different @sc{blas} library such as OpenBLAS or ATLAS to correct\nthis issue.\n\n@item\nOn @nospell{NeXT} systems, linking to @file{libsys_s.a} may fail to resolve the\nfollowing functions\n\n@example\n@group\n_tcgetattr\n_tcsetattr\n_tcflow\n@end group\n@end example\n\n@noindent\nwhich are part of @file{libposix.a}.  Unfortunately, linking Octave with\n@option{-posix} results in the following undefined symbols.\n\n@example\n@group\n.destructors_used\n.constructors_used\n_objc_msgSend\n_NXGetDefaultValue\n_NXRegisterDefaults\n.objc_class_name_NXStringTable\n.objc_class_name_NXBundle\n@end group\n@end example\n\nOne kluge around this problem is to extract @file{termios.o} from\n@file{libposix.a}, put it in Octave's @file{src} directory, and add it\nto the list of files to link together in the makefile.  Suggestions for\nbetter ways to solve this problem are welcome!\n\n@item\nIf Octave crashes immediately with a floating point exception, it is\nlikely that it is failing to initialize the IEEE@tie{}754 floating point values\nfor infinity and NaN.\n\nIf your system actually does support IEEE@tie{}754 arithmetic, you should be\nable to fix this problem by modifying the function @code{octave_ieee_init} in\nthe file @file{lo-ieee.cc} to correctly initialize Octave's internal\ninfinity and NaN variables.\n\nIf your system does not support IEEE@tie{}754 arithmetic but Octave's configure\nscript incorrectly determined that it does, you can work around the\nproblem by editing the file @file{config.h} to not define\n@w{@code{HAVE_ISINF}}, @w{@code{HAVE_FINITE}}, and\n@w{@code{HAVE_ISNAN}}.\n\nIn any case, please report this as a bug since it might be possible to\nmodify Octave's configuration script to automatically determine the\nproper thing to do.\n\n@item\nIf Octave is unable to find a header file because it is installed in a\nlocation that is not normally searched by the compiler, you can add the\ndirectory to the include search path by specifying (for example)\n@code{CPPFLAGS=-I/some/nonstandard/directory} as an argument to\n@code{configure}.  Other variables that can be specified this way are\n@env{CFLAGS}, @env{CXXFLAGS}, @env{FFLAGS}, and @env{LDFLAGS}.  Passing\nthem as options to the configure script also records them in the\n@file{config.status} file.  By default, @env{CPPFLAGS} and @env{LDFLAGS}\nare empty, @env{CFLAGS} and @env{CXXFLAGS} are set to @qcode{\"-g -O2\"} and\n@env{FFLAGS} is set to @qcode{\"-O\"}.\n\n@end itemize\n"
  },
  {
    "path": "doc/interpreter/interp.txi",
    "content": "@c Copyright (C) 2007-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Interpolation\n@chapter Interpolation\n\n@menu\n* One-dimensional Interpolation::\n* Multi-dimensional Interpolation::\n@end menu\n\n@node One-dimensional Interpolation\n@section One-dimensional Interpolation\n\nOctave supports several methods for one-dimensional interpolation, most\nof which are described in this section.  @ref{Polynomial Interpolation}\nand @ref{Interpolation on Scattered Data} describe additional methods.\n\n@DOCSTRING(interp1)\n\nThere are some important differences between the various interpolation\nmethods.  The @qcode{\"spline\"} method enforces that both the first and second\nderivatives of the interpolated values have a continuous derivative,\nwhereas the other methods do not.  This means that the results of the\n@qcode{\"spline\"} method are generally smoother.  If the function to be\ninterpolated is in fact smooth, then @qcode{\"spline\"} will give excellent\nresults.  However, if the function to be evaluated is in some manner\ndiscontinuous, then @qcode{\"pchip\"} interpolation might give better results.\n\nThis can be demonstrated by the code\n\n@example\n@group\nt = -2:2;\ndt = 1;\nti =-2:0.025:2;\ndti = 0.025;\ny = sign (t);\nys = interp1 (t,y,ti,\"spline\");\nyp = interp1 (t,y,ti,\"pchip\");\nddys = diff (diff (ys)./dti) ./ dti;\nddyp = diff (diff (yp)./dti) ./ dti;\nfigure (1);\nplot (ti,ys,\"r-\", ti,yp,\"g-\");\nlegend (\"spline\", \"pchip\", 4);\nfigure (2);\nplot (ti,ddys,\"r+\", ti,ddyp,\"g*\");\nlegend (\"spline\", \"pchip\");\n@end group\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:interpderiv1} and\n@ref{fig:interpderiv2}.\n\n@float Figure,fig:interpderiv1\n@center @image{interpderiv1,4in}\n@caption{Comparison of @qcode{\"pchip\"} and @qcode{\"spline\"} interpolation methods for a\nstep function}\n@end float\n\n@float Figure,fig:interpderiv2\n@center @image{interpderiv2,4in}\n@caption{Comparison of the second derivative of the @qcode{\"pchip\"} and @qcode{\"spline\"}\ninterpolation methods for a step function}\n@end float\n@end ifnotinfo\n\nFourier interpolation, is a resampling technique where a signal is\nconverted to the frequency domain, padded with zeros and then\nreconverted to the time domain.\n\n@DOCSTRING(interpft)\n\nThere are two significant limitations on Fourier interpolation.  First,\nthe function signal is assumed to be periodic, and so non-periodic\nsignals will be poorly represented at the edges.  Second, both the\nsignal and its interpolation are required to be sampled at equispaced\npoints.  An example of the use of @code{interpft} is\n\n@example\n@group\nt = 0 : 0.3 : pi; dt = t(2)-t(1);\nn = length (t); k = 100;\nti = t(1) + [0 : k-1]*dt*n/k;\ny = sin (4*t + 0.3) .* cos (3*t - 0.1);\nyp = sin (4*ti + 0.3) .* cos (3*ti - 0.1);\nplot (ti, yp, \"g\", ti, interp1 (t, y, ti, \"spline\"), \"b\", ...\n      ti, interpft (y, k), \"c\", t, y, \"r+\");\nlegend (\"sin(4t+0.3)cos(3t-0.1)\", \"spline\", \"interpft\", \"data\");\n@end group\n@end example\n\n@noindent\n@ifinfo\nwhich demonstrates the poor behavior of Fourier interpolation for non-periodic\nfunctions.\n@end ifinfo\n@ifnotinfo\nwhich demonstrates the poor behavior of Fourier interpolation for non-periodic\nfunctions, as can be seen in @ref{fig:interpft}.\n\n@float Figure,fig:interpft\n@center @image{interpft,4in}\n@caption{Comparison of @code{interp1} and @code{interpft} for non-periodic data}\n@end float\n@end ifnotinfo\n\nIn addition, the support functions @code{spline} and @code{lookup} that\nunderlie the @code{interp1} function can be called directly.\n\n@DOCSTRING(spline)\n\n@node Multi-dimensional Interpolation\n@section Multi-dimensional Interpolation\n\nThere are three multi-dimensional interpolation functions in Octave, with\nsimilar capabilities.  Methods using Delaunay tessellation are described\nin @ref{Interpolation on Scattered Data}.\n\n@DOCSTRING(interp2)\n\n@DOCSTRING(interp3)\n\n@DOCSTRING(interpn)\n\nA significant difference between @code{interpn} and the other two\nmulti-dimensional interpolation functions is the fashion in which the\ndimensions are treated.  For @code{interp2} and @code{interp3}, the y-axis is\nconsidered to be the columns of the matrix, whereas the x-axis corresponds to\nthe rows of the array.  As Octave indexes arrays in column major order, the\nfirst dimension of any array is the columns, and so @code{interpn} effectively\nreverses the 'x' and 'y' dimensions.  Consider the example,\n\n@example\n@group\nx = y = z = -1:1;\nf = @@(x,y,z) x.^2 - y - z.^2;\n[xx, yy, zz] = meshgrid (x, y, z);\nv = f (xx,yy,zz);\nxi = yi = zi = -1:0.1:1;\n[xxi, yyi, zzi] = meshgrid (xi, yi, zi);\nvi = interp3 (x, y, z, v, xxi, yyi, zzi, \"spline\");\n[xxi, yyi, zzi] = ndgrid (xi, yi, zi);\nvi2 = interpn (x, y, z, v, xxi, yyi, zzi, \"spline\");\nmesh (zi, yi, squeeze (vi2(1,:,:)));\n@end group\n@end example\n\n@noindent\nwhere @code{vi} and @code{vi2} are identical.  The reversal of the\ndimensions is treated in the @code{meshgrid} and @code{ndgrid} functions\nrespectively.\n@ifnotinfo\nThe result of this code can be seen in @ref{fig:interpn}.\n\n@float Figure,fig:interpn\n@center @image{interpn,4in}\n@caption{Demonstration of the use of @code{interpn}}\n@end float\n@end ifnotinfo\n"
  },
  {
    "path": "doc/interpreter/interpimages.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nfunction interpimages (d, nm, typ)\n\n  if (strcmp (typ, \"txt\"))\n    image_as_txt (d, nm);\n    return;\n  endif\n\n  set_graphics_toolkit ();\n  set_print_size ();\n  hide_output ();\n  outfile = fullfile (d, [nm \".\" typ]);\n  if (strcmp (typ, \"png\"))\n    set (groot, \"defaulttextfontname\", \"*\");\n  endif\n  if (strcmp (typ, \"eps\"))\n    d_typ = \"-depsc2\";\n  else\n    d_typ = [\"-d\", typ];\n  endif\n\n  if (strcmp (nm, \"interpft\"))\n    t = 0 : 0.3 : pi; dt = t(2)-t(1);\n    n = length (t); k = 100;\n    ti = t(1) + [0 : k-1]*dt*n/k;\n    y = sin (4*t + 0.3) .* cos (3*t - 0.1);\n    yp = sin (4*ti + 0.3) .* cos (3*ti - 0.1);\n    plot (ti, yp, \"g\", ti, interp1 (t, y, ti, \"spline\"), \"b\", ...\n          ti, interpft (y, k), \"c\", t, y, \"r+\");\n    legend (\"sin(4t+0.3)cos(3t-0.1)\", \"spline\", \"interpft\", \"data\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"interpn\"))\n    x = y = z = -1:1;\n    f = @(x,y,z) x.^2 - y - z.^2;\n    [xx, yy, zz] = meshgrid (x, y, z);\n    v = f (xx,yy,zz);\n    xi = yi = zi = -1:0.1:1;\n    [xxi, yyi, zzi] = ndgrid (xi, yi, zi);\n    vi = interpn (x, y, z, v, xxi, yyi, zzi, \"spline\");\n    mesh (zi, yi, squeeze (vi(1,:,:)));\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"interpderiv1\"))\n    t = -2:2;\n    dt = 1;\n    ti =-2:0.025:2;\n    dti = 0.025;\n    y = sign (t);\n    ys = interp1 (t,y,ti,\"spline\");\n    yp = interp1 (t,y,ti,\"pchip\");\n    plot (ti, ys,\"r-\", ti, yp,\"g-\");\n    legend (\"spline\",\"pchip\", \"location\", \"southeast\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"interpderiv2\"))\n    t = -2:2;\n    dt = 1;\n    ti =-2:0.025:2;\n    dti = 0.025;\n    y = sign (t);\n    ddys = diff (diff (interp1 (t,y,ti,\"spline\"))./dti)./dti;\n    ddyp = diff (diff (interp1 (t,y,ti,\"pchip\"))./dti)./dti;\n    plot (ti(2:end-1),ddys,\"r*\", ti(2:end-1),ddyp,\"g+\");\n    legend (\"spline\", \"pchip\");\n    print (outfile, d_typ);\n  endif\n  hide_output ();\nendfunction\n\n## This function no longer sets the graphics toolkit; That is now done\n## automatically by C++ code which will ordinarily choose 'qt', but might\n## choose gnuplot on older systems.  Only a complete lack of plotting is a\n## problem.\nfunction set_graphics_toolkit ()\n  if (isempty (available_graphics_toolkits ()))\n    error (\"no graphics toolkit available for plotting\");\n  elseif (strcmp (\"qt\", graphics_toolkit ()))\n    ## Use qt with QOffscreenSurface for plot\n  elseif (! strcmp (\"gnuplot\", graphics_toolkit ()))\n    if (! any (strcmp (\"gnuplot\", available_graphics_toolkits ())))\n      error (\"no graphics toolkit available for offscreen plotting\");\n    else\n      graphics_toolkit (\"gnuplot\");\n    endif\n  endif\nendfunction\n\nfunction set_print_size ()\n  image_size = [5.0, 3.5]; # in inches, 16:9 format\n  border = 0;              # For postscript use 50/72\n  set (groot, \"defaultfigurepapertype\", \"<custom>\");\n  set (groot, \"defaultfigurepaperorientation\", \"landscape\");\n  set (groot, \"defaultfigurepapersize\", image_size + 2*border);\n  set (groot, \"defaultfigurepaperposition\", [border, border, image_size]);\n  ## FIXME: Required until listener for legend exists (bug #39697)\n  set (groot, \"defaultfigureposition\", [ 72*[border, border, image_size] ]);\nendfunction\n\n## Use this function before plotting commands and after every call to print\n## since print() resets output to stdout (unfortunately, gnuplot can't pop\n## output as it can the terminal type).\nfunction hide_output ()\n  hf = figure (1, \"visible\", \"off\");\nendfunction\n\n## generate something for the texinfo @image command to process\nfunction image_as_txt (d, nm)\n  fid = fopen (fullfile (d, [nm \".txt\"]), \"wt\");\n  fputs (fid, \"\\n\");\n  fputs (fid, \"+---------------------------------+\\n\");\n  fputs (fid, \"| Image unavailable in text mode. |\\n\");\n  fputs (fid, \"+---------------------------------+\\n\");\n  fclose (fid);\nendfunction\n"
  },
  {
    "path": "doc/interpreter/intro.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Introduction\n@chapter A Brief Introduction to Octave\n@cindex introduction\n\nGNU Octave is a high-level language primarily intended for numerical\ncomputations.  It is typically used for such problems as solving\nlinear and nonlinear equations, numerical linear algebra, statistical\nanalysis, and for performing other numerical experiments.  It may also\nbe used as a batch-oriented language for automated data processing.\n\nThe current version of Octave executes in a graphical user interface\n(GUI).  The GUI hosts an Integrated Development Environment (IDE)\nwhich includes a code editor with syntax highlighting, built-in\ndebugger, documentation browser, as well as the interpreter for the\nlanguage itself.  A command-line interface for Octave is also available.\n\nGNU Octave is freely redistributable software.  You may redistribute\nit and/or modify it under the terms of the GNU General Public License\nas published by the Free Software Foundation.  The GPL is included in\nthis manual, @pxref{Copying}.\n\nThis manual provides comprehensive documentation on how to install,\nrun, use, and extend GNU Octave.  Additional chapters describe how\nto report bugs and help contribute code.\n\nThis document corresponds to Octave version @value{VERSION}.\n\n@menu\n* Running Octave::\n* Simple Examples::\n* Conventions::\n@end menu\n\n@node Running Octave\n@section Running Octave\n\nIf you installed Octave from an installer program, it will likely have\ncreated some icons on your desktop for you to start Octave, either with\nthe graphical user interface (GUI) or a command line interface (CLI).\nYou can also typically find Octave in the \"Start Menu\" or equivalent\nof your computer.  You can also type @code{octave} in a command shell;\nas long as you have Octave in your path, it will start.\n\nIf you start Octave with the GUI, the central window is the Octave's\nown command-line interface (also called a @nospell{REPL} by other programming\nlanguages for Read-Evaluate-Print-Loop).  In this window Octave displays an\ninitial message and then a prompt like @code{>> } or @code{octave:1> }\nindicating it is ready to accept input.  If you have chosen the traditional\ncommand-line interface then the command prompt appears in the same window\nthat was running a command shell.  In either case, you can immediately begin\ntyping Octave commands.\n\nIf you get into trouble, you can usually interrupt Octave by typing\n@kbd{Control-C}.  Doing this will normally return you to Octave's\nprompt.\n\n@cindex exiting octave\n@cindex quitting octave\nTo exit Octave, type @kbd{quit} or @kbd{exit} at the Octave prompt.\n\nOn systems that support job control, you can suspend Octave by sending\nit a @code{SIGTSTP} signal, usually by typing @kbd{Ctrl-z}.\n\n@node Simple Examples\n@section Simple Examples\n\nThe following chapters describe all of Octave's features in detail, but\nbefore doing that, it might be helpful to give a sampling of some of its\ncapabilities.\n\nIf you are new to Octave, we recommend that you try these examples to\nbegin learning Octave by using it.  Lines marked like so,\n@samp{octave:13>} or @samp{>> }, are lines you type, ending each with a\ncarriage return.  (Don't type the text @samp{octave:13>} itself!  That is only\nthe Octave prompt, which also looks like @code{>> } in the GUI.\nOctave will respond to your commands with an answer, or by displaying a graph.\n\n@menu\n* Elementary Calculations::\n* Creating a Matrix::\n* Matrix Arithmetic::\n* Solving Systems of Linear Equations::\n* Integrating Differential Equations::\n* Producing Graphical Output::\n* Help and Documentation::\n* Editing What You Have Typed::\n@end menu\n\n@node Elementary Calculations\n@subsection Elementary Calculations\n\nOctave can easily be used for basic numerical calculations.  Octave\nknows about arithmetic operations (+,-,*,/), exponentiation (^),\nnatural logarithms/exponents (log, exp), and the trigonometric\nfunctions (sin, cos, @dots{}).  Moreover, Octave calculations work\non real or imaginary numbers (i,j).  In addition, some mathematical\nconstants such as the base of the natural logarithm (e) and the ratio\nof a circle's circumference to its diameter (pi) are pre-defined.\n\n@noindent\nFor example, to verify @nospell{Euler's} Identity,\n@tex\n$$e^{\\imath\\pi} = -1$$\n@end tex\n@ifnottex\n@display\n\n i*pi\ne     = -1\n@end display\n@end ifnottex\n\n@noindent\ntype the following which will evaluate to @code{-1} within the\ntolerance of the calculation.\n\n@example\noctave:1> exp (i*pi)\n@end example\n\n@node Creating a Matrix\n@subsection Creating a Matrix\n\nVectors and matrices are the basic building blocks for numerical\nanalysis.  To create a new matrix and store it in a variable so that you\ncan refer to it later, type the command\n\n@example\noctave:1> A = [ 1, 1, 2; 3, 5, 8; 13, 21, 34 ]\n@end example\n\n@noindent\nOctave will respond by printing the matrix in neatly aligned columns.\nOctave uses a comma or space to separate entries in a row, and a\nsemicolon or carriage return to separate one row from the next.\nEnding a command with a semicolon tells Octave not to print the result\nof the command.  For example,\n\n@example\noctave:2> B = rand (3, 2);\n@end example\n\n@noindent\nwill create a 3 row, 2 column matrix with each element set to a random\nvalue between zero and one.\n\nTo display the value of a variable, simply type the name of the\nvariable at the prompt.  For example, to display the value stored in the\nmatrix @code{B}, type the command\n\n@example\noctave:3> B\n@end example\n\n@node Matrix Arithmetic\n@subsection Matrix Arithmetic\n\nOctave uses standard mathematical notation with the advantage over\nlow-level languages that operators may act on scalars, vector, matrices,\nor N-dimensional arrays.  For example, to multiply the matrix @code{A}\nby a scalar value, type the command\n\n@example\noctave:4> 2 * A\n@end example\n\n@noindent\nTo multiply the two matrices @code{A} and @code{B}, type the command\n\n@example\noctave:5> A * B\n@end example\n\n@noindent\nand to form the matrix product\n@tex\n$@code{A}^T@code{A}$,\n@end tex\n@ifnottex\n@code{transpose (A) * A},\n@end ifnottex\ntype the command\n\n@example\noctave:6> A' * A\n@end example\n\n@node Solving Systems of Linear Equations\n@subsection Solving Systems of Linear Equations\n\nSystems of linear equations are ubiquitous in numerical analysis.\nTo solve the set of linear equations @code{A@var{x} = b},\nuse the left division operator, @samp{\\}:\n\n@example\n@var{x} = A \\ b\n@end example\n\n@noindent\nThis is conceptually equivalent to\n@tex\n$@code{A}^{-1}@code{b}$,\n@end tex\n@ifnottex\n@code{inv (A) * b},\n@end ifnottex\nbut avoids computing the inverse of a matrix directly.\n\nIf the coefficient matrix is singular, Octave will print a warning\nmessage and compute a minimum norm solution.\n\nA simple example comes from chemistry and the need to obtain balanced\nchemical equations.  Consider the burning of hydrogen and oxygen to\nproduce water.\n@tex\n$$ {\\rm H_{2}} + {\\rm O_{2}} \\rightarrow {\\rm H_{2}O} $$\n@end tex\n@ifnottex\n\n@example\nH2 + O2 --> H2O\n@end example\n\n@end ifnottex\n@noindent\nThe equation above is not accurate.  The Law of Conservation of Mass requires\nthat the number of molecules of each type balance on the left- and right-hand\nsides of the equation.  Writing the variable overall reaction with\nindividual equations for hydrogen and oxygen one finds:\n@tex\n\\vbox{\n$$ x_{1}{\\rm H_{2}} + x_{2}{\\rm O_{2}} \\rightarrow {\\rm H_{2}O} $$\n$$ {\\rm H:}\\quad 2x_{1} + 0x_{2} \\rightarrow 2 $$\n$$ {\\rm O:}\\quad 0x_{1} + 2x_{2} \\rightarrow 1 $$\n}\n@end tex\n@ifnottex\n\n@example\n@group\nx1*H2 + x2*O2 --> H2O\nH: 2*x1 + 0*x2 --> 2\nO: 0*x1 + 2*x2 --> 1\n@end group\n@end example\n\n@end ifnottex\n@noindent\nThe solution in Octave is found in just three steps.\n\n@example\n@group\noctave:1> A = [ 2, 0; 0, 2 ];\noctave:2> b = [ 2; 1 ];\noctave:3> x = A \\ b\n@end group\n@end example\n\n@node Integrating Differential Equations\n@subsection Integrating Differential Equations\n\nOctave has built-in functions for solving nonlinear differential\nequations of the form\n@tex\n$$\n {dx \\over dt} = f(x,t), \\qquad x(t=t_0) = x_0\n$$\n@end tex\n@ifnottex\n\n@example\n@group\ndx\n-- = f (x, t)\ndt\n@end group\n@end example\n\n@noindent\nwith the initial condition\n\n@example\nx(t = t0) = x0\n@end example\n\n@end ifnottex\n@noindent\nFor Octave to integrate equations of this form, you must first provide a\ndefinition of the function\n@tex\n$f (x, t)$.\n@end tex\n@ifnottex\n@code{f(x,t)}.\n@end ifnottex\nThis is straightforward, and may be accomplished by entering the\nfunction body directly on the command line.  For example, the following\ncommands define the right-hand side function for an interesting pair of\nnonlinear differential equations.  Note that while you are entering a\nfunction, Octave responds with a different prompt, to indicate that it\nis waiting for you to complete your input.\n\n@example\n@group\noctave:1> function xdot = f (x, t)\n>\n>  r = 0.25;\n>  k = 1.4;\n>  a = 1.5;\n>  b = 0.16;\n>  c = 0.9;\n>  d = 0.8;\n>\n>  xdot(1) = r*x(1)*(1 - x(1)/k) - a*x(1)*x(2)/(1 + b*x(1));\n>  xdot(2) = c*a*x(1)*x(2)/(1 + b*x(1)) - d*x(2);\n>\n> endfunction\n@end group\n@end example\n\n@noindent\nGiven the initial condition\n\n@example\noctave:2> x0 = [1; 2];\n@end example\n\n@noindent\nand the set of output times as a column vector (note that the first\noutput time corresponds to the initial condition given above)\n\n@example\noctave:3> t = linspace (0, 50, 200)';\n@end example\n\n@noindent\nit is easy to integrate the set of differential equations:\n\n@example\noctave:4> x = lsode (\"f\", x0, t);\n@end example\n\n@noindent\nThe function @code{lsode} uses the Livermore Solver for Ordinary\nDifferential Equations, described in @nospell{A. C. Hindmarsh},\n\"ODEPACK, a Systematized Collection of ODE Solvers\",\n@cite{Scientific Computing}, @nospell{R. S. Stepleman} @w{et al.@:} (Eds.),\nNorth-Holland, Amsterdam, 1983, @w{pp.@: 55}--64.\n\n@node Producing Graphical Output\n@subsection Producing Graphical Output\n\nTo display the solution of the previous example graphically, use the\ncommand\n\n@example\noctave:1> plot (t, x)\n@end example\n\n@noindent\nOctave will automatically create a separate window to display the plot.\n\nTo save a plot once it has been displayed on the screen, use the print\ncommand.  For example,\n\n@example\nprint foo.pdf\n@end example\n\n@noindent\nwill create a file called @file{foo.pdf} that contains a rendering of\nthe current plot in Portable Document Format.  The command\n\n@example\nhelp print\n@end example\n\n@noindent\nexplains more options for the @code{print} command and provides a list\nof additional output file formats.\n\n@node Help and Documentation\n@subsection Help and Documentation\n\nOctave has an extensive help facility.  The same documentation that is\navailable in printed form is also available from the Octave prompt,\nbecause both forms of the documentation are created from the same input\nfile.\n\nIn order to get good help you first need to know the name of the command\nthat you want to use.  The name of this function may not always be\nobvious, but a good place to start is to type @code{help --list}.\nThis will show you all the operators, keywords, built-in functions,\nand loadable functions available in the current session of Octave.  An\nalternative is to search the documentation using the @code{lookfor}\nfunction (described in @ref{Getting Help}).\n\nOnce you know the name of the function you wish to use, you can get more\nhelp on the function by simply including the name as an argument to help.\nFor example,\n\n@example\nhelp plot\n@end example\n\n@noindent\nwill display the help text for the @code{plot} function.\n\nThe part of Octave's help facility that allows you to read the complete\ntext of the printed manual from within Octave normally uses a separate\nprogram called Info.  When you invoke Info you will be put into a menu\ndriven program that contains the entire Octave manual.  Help for using\nInfo is provided in this manual, @pxref{Getting Help}.\n\n@node Editing What You Have Typed\n@subsection Editing What You Have Typed\n\nAt the Octave prompt, you can recall, edit, and reissue previous\ncommands using Emacs- or vi-style editing commands.  The default\nkeybindings use Emacs-style commands.  For example, to recall the\nprevious command, press @kbd{Control-p} (written @kbd{C-p} for\nshort).  Doing this will normally bring back the previous line of input.\n@kbd{C-n} will bring up the next line of input, @kbd{C-b} will move\nthe cursor backward on the line, @kbd{C-f} will move the cursor forward\non the line, etc.\n\nA complete description of the command line editing capability is given\nin this manual, @pxref{Command Line Editing}.\n\n@node Conventions\n@section Conventions\n\nThis section explains the notation conventions that are used in this\nmanual.  You may want to skip this section and refer back to it later.\n\n@menu\n* Fonts::\n* Evaluation Notation::\n* Printing Notation::\n* Error Messages::\n* Format of Descriptions::\n@end menu\n\n@node Fonts\n@subsection Fonts\n@cindex documentation fonts\n\nExamples of Octave code appear in this font or form: @w{@code{svd (a)}}.\nNames that represent variables or function arguments appear in this font\nor form: @var{first-number}.  Commands that you type at the shell prompt\nappear in this font or form: @w{@samp{octave --no-init-file}}.  Commands\nthat you type at the Octave prompt sometimes appear in this font or\nform: @w{@kbd{foo --bar --baz}}.  Specific keys on your keyboard appear\nin this font or form: @key{RET}.\n\n@node Evaluation Notation\n@subsection Evaluation Notation\n@cindex evaluation notation\n@cindex documentation notation\n\nIn the examples in this manual, results from expressions that you\nevaluate are indicated with @samp{@xresult{}}.  For example:\n\n@example\n@group\nsqrt (2)\n     @xresult{} 1.4142\n@end group\n@end example\n\n@noindent\nYou can read this as ``@code{sqrt (2)} evaluates to 1.4142''.\n\nIn some cases, matrix values that are returned by expressions are\ndisplayed like this\n\n@example\n@group\n[1, 2; 3, 4] == [1, 3; 2, 4]\n     @xresult{} [ 1, 0; 0, 1 ]\n@end group\n@end example\n\n@noindent\nand in other cases, they are displayed like this\n\n@example\n@group\neye (3)\n     @xresult{}  1  0  0\n         0  1  0\n         0  0  1\n@end group\n@end example\n\n@noindent\nin order to clearly show the structure of the result.\n\nSometimes to help describe one expression, another expression is shown\nthat produces identical results.  The exact equivalence of expressions\nis indicated with @samp{@equiv{}}.  For example:\n\n@example\n@group\nrot90 ([1, 2; 3, 4], -1)\n@equiv{}\nrot90 ([1, 2; 3, 4], 3)\n@equiv{}\nrot90 ([1, 2; 3, 4], 7)\n@end group\n@end example\n\n@node Printing Notation\n@subsection Printing Notation\n@cindex printing notation\n\nMany of the examples in this manual print text when they are evaluated.\nIn this manual the printed text resulting from an example is indicated\nby @samp{@print{}}.  The value that is returned by evaluating the\nexpression is displayed with @samp{@xresult{}} (@code{1} in the next\nexample) and follows on a separate line.\n\n@example\n@group\nprintf (\"foo %s\\n\", \"bar\")\n     @print{} foo bar\n     @xresult{} 1\n@end group\n@end example\n\n@node Error Messages\n@subsection Error Messages\n@cindex error message notation\n\nSome examples signal errors.  This normally displays an error message\non your terminal.  Error messages are shown on a line beginning with\n@code{error:}.\n\n@example\n@group\nfieldnames ([1, 2; 3, 4])\nerror: fieldnames: Invalid input argument\n@end group\n@end example\n\n@node Format of Descriptions\n@subsection Format of Descriptions\n@cindex description format\n\nFunctions and commands are described in this manual in a uniform format.\nThe first line of a description contains the name of the item followed\nby its arguments, if any.  If there are multiple ways to invoke the\nfunction then each allowable form is listed.\n\nThe description follows on succeeding lines, sometimes with examples.\n\n@menu\n* A Sample Function Description::\n* A Sample Command Description::\n@end menu\n\n@node A Sample Function Description\n@subsubsection A Sample Function Description\n@cindex function descriptions\n\nIn a function description, the name of the function being described\nappears first.  It is followed on the same line by a list of parameters.\nThe names used for the parameters are also used in the body of the\ndescription.\n\nAfter all of the calling forms have been enumerated, the next line is a\nconcise one-sentence summary of the function.\n\nAfter the summary there may be documentation on the inputs and outputs,\nexamples of function usage, notes about the algorithm used, and references\nto related functions.\n\nHere is a description of an imaginary function @code{foo}:\n\n@need 4000\n@deftypefn  {} {} foo (@var{x})\n@deftypefnx {} {} foo (@var{x}, @var{y})\n@deftypefnx {} {} foo (@var{x}, @var{y}, @dots{})\nSubtract @var{x} from @var{y}, then add any remaining arguments to the\nresult.\n\nThe input @var{x} must be a numeric scalar, vector, or array.\n\nThe optional input @var{y} defaults to 19 if it is not supplied.\n\nExample:\n\n@example\n@group\nfoo (1, [3, 5], 3, 9)\n     @xresult{} [ 14, 16 ]\nfoo (5)\n     @xresult{} 14\n@end group\n@end example\n\nMore generally,\n\n@example\n@group\nfoo (@var{w}, @var{x}, @var{y}, @dots{})\n@equiv{}\n@var{x} - @var{w} + @var{y} + @dots{}\n@end group\n@end example\n\n@b{See also:} bar\n@end deftypefn\n\nAny parameter whose name contains the name of a type (e.g.,\n@var{integer} or @var{matrix}) is expected to be of that\ntype.  Parameters named @var{object} may be of any type.  Parameters\nwith other sorts of names (e.g., @var{new_file}) are discussed\nspecifically in the description of the function.  In some sections,\nfeatures common to parameters of several functions are described at the\nbeginning.\n\n@node A Sample Command Description\n@subsubsection A Sample Command Description\n@cindex command descriptions\n\nCommands are functions that may be called without surrounding their arguments\nin parentheses.  Command descriptions have a format similar to function\ndescriptions.  For example, here is the description for Octave's @code{diary}\ncommand:\n\n@need 4000\n@deftypefn  {} {} diary\n@deftypefnx {} {} diary on\n@deftypefnx {} {} diary off\n@deftypefnx {} {} diary @var{filename}\n@deftypefnx {} {[@var{status}, @var{diaryfile}] =} diary\nRecord a list of all commands @emph{and} the output they produce, mixed\ntogether just as they appear on the terminal.\n\nValid options are:\n\n@table @asis\n@item on\nStart recording a session in a file called @file{diary} in the current working\ndirectory.\n\n@item off\nStop recording the session in the diary file.\n\n@item @var{filename}\nRecord the session in the file named @var{filename}.\n@end table\n\nWith no input or output arguments, @code{diary} toggles the current diary\nstate.\n\nIf output arguments are requested, @code{diary} ignores inputs and returns\nthe current status.  The boolean @var{status} indicates whether recording is on\nor off, and @var{diaryfile} is the name of the file where the session is\nstored.\n@seealso{history, evalc}\n@end deftypefn\n"
  },
  {
    "path": "doc/interpreter/io.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Input and Output\n@chapter Input and Output\n\nOctave supports several ways of reading and writing data to or from the\nprompt or a file.  The simplest functions for data Input and Output\n(I/O) are easy to use, but only provide limited control of how\ndata is processed.  For more control, a set of functions modeled\nafter the C standard library are also provided by Octave.\n\n@menu\n* Basic Input and Output::\n* C-Style I/O Functions::\n@end menu\n\n@node Basic Input and Output\n@section Basic Input and Output\n\n@c We could use a two-line introduction here...\n\n@menu\n* Terminal Output::\n* Terminal Input::\n* Simple File I/O::\n@end menu\n\n@node Terminal Output\n@subsection Terminal Output\n\nSince Octave normally prints the value of an expression as soon as it\nhas been evaluated, the simplest of all I/O functions is a simple\nexpression.  For example, the following expression will display the\nvalue of @samp{pi}\n\n@example\n@group\npi\n     @print{} ans =  3.1416\n@end group\n@end example\n\nThis works well as long as it is acceptable to have the name of the\nvariable (or @samp{ans}) printed along with the value.  To print the\nvalue of a variable without printing its name, use the function\n@code{disp}.\n\nThe @code{format} command offers some control over the way Octave prints\nvalues with @code{disp} and through the normal echoing mechanism.\n\n@DOCSTRING(disp)\n\n@DOCSTRING(list_in_columns)\n\n@DOCSTRING(terminal_size)\n\n@DOCSTRING(format)\n\n@menu\n* Paging Screen Output::\n@end menu\n\n@node Paging Screen Output\n@subsubsection Paging Screen Output\n\nWhen running interactively, Octave normally sends all output directly to the\nCommand Window.  However, when using the CLI version of Octave this can create\na problem because large volumes of data will stream by before you can read\nthem.  In such cases, it is better to use a paging program such as @code{less}\nor @code{more} which displays just one screenful at a time.  With @code{less}\n(and some versions of @code{more}) you can also scan forward and backward, and\nsearch for specific items.  The pager is enabled by the command @code{more on}.\n\nNormally, no output is displayed by the pager until just before Octave is ready\nto print the top level prompt, or read from the standard input (for example, by\nusing the @code{fscanf} or @code{scanf} functions).  This means that there may\nbe some delay before any output appears on your screen if you have asked Octave\nto perform a significant amount of work with a single command statement.  The\nfunction @code{fflush} may be used to force output to be sent to the pager (or\nany other stream) immediately.\n\nYou can select the program to run as the pager with the @code{PAGER} function,\nand configure the pager itself with the @code{PAGER_FLAGS} function.\n\n@DOCSTRING(more)\n\n@DOCSTRING(PAGER)\n\n@DOCSTRING(PAGER_FLAGS)\n\n@DOCSTRING(page_screen_output)\n\n@DOCSTRING(page_output_immediately)\n\n@DOCSTRING(fflush)\n\n@c FIXME: maybe this would be a good place to describe the following message:\n@c\n@c warning: connection to external pager (pid = 9334) lost --\n@c warning: pending computations and output may be lost\n@c warning: broken pipe\n\n@node Terminal Input\n@subsection Terminal Input\n\nOctave has three functions that make it easy to prompt users for\ninput.  The @code{input} and @code{menu} functions are normally\nused for managing an interactive dialog with a user, and the\n@code{keyboard} function is normally used for doing simple debugging.\n\n@DOCSTRING(input)\n\n@DOCSTRING(menu)\n\n@DOCSTRING(yes_or_no)\n\nFor @code{input}, the normal command line history and editing functions\nare available at the prompt.\n\nOctave also has a function that makes it possible to get a single\ncharacter from the keyboard without requiring the user to type a\ncarriage return.\n\n@DOCSTRING(kbhit)\n\n@node Simple File I/O\n@subsection Simple File I/O\n\n@cindex saving data\n@cindex loading data\nThe @code{save} and @code{load} commands allow data to be written to and\nread from disk files in various formats.  The default format of files\nwritten by the @code{save} command can be controlled using the functions\n@code{save_default_options} and @code{save_precision}.\n\nAs an example the following code creates a 3-by-3 matrix and saves it\nto the file @samp{myfile.mat}.\n\n@example\n@group\nA = [ 1:3; 4:6; 7:9 ];\nsave myfile.mat A\n@end group\n@end example\n\nOnce one or more variables have been saved to a file, they can be\nread into memory using the @code{load} command.\n\n@example\n@group\nload myfile.mat\nA\n     @print{} A =\n     @print{}\n     @print{}    1   2   3\n     @print{}    4   5   6\n     @print{}    7   8   9\n@end group\n@end example\n\n@DOCSTRING(save)\n\nThere are three functions that modify the behavior of @code{save}.\n\n@DOCSTRING(save_default_options)\n\n@DOCSTRING(save_precision)\n\n@DOCSTRING(save_header_format_string)\n\n@DOCSTRING(load)\n\n@DOCSTRING(fileread)\n\n@DOCSTRING(native_float_format)\n\nIt is possible to write data to a file in a similar way to the\n@code{disp} function for writing data to the screen.  The @code{fdisp}\nworks just like @code{disp} except its first argument is a file pointer\nas created by @code{fopen}.  As an example, the following code writes\nto data @samp{myfile.txt}.\n\n@example\n@group\nfid = fopen (\"myfile.txt\", \"w\");\nfdisp (fid, \"3/8 is \");\nfdisp (fid, 3/8);\nfclose (fid);\n@end group\n@end example\n\n@noindent\n@xref{Opening and Closing Files}, for details on how to use @code{fopen}\nand @code{fclose}.\n\n@DOCSTRING(fdisp)\n\nOctave can also read and write matrices text files such as comma\nseparated lists.\n\n@DOCSTRING(dlmwrite)\n\n@DOCSTRING(dlmread)\n\n@DOCSTRING(csvwrite)\n\n@DOCSTRING(csvread)\n\nFormatted data from can be read from, or written to, text files as well.\n\n@DOCSTRING(textread)\n\n@DOCSTRING(textscan)\n\nThe @code{importdata} function has the ability to work with a wide\nvariety of data.\n\n@DOCSTRING(importdata)\n\nAfter importing, the data may need to be transformed before further analysis.\nThe @code{rescale} function can shift and normalize a data set to a specified\nrange.\n\n@DOCSTRING(rescale)\n\n@menu\n* Saving Data on Unexpected Exits::\n@end menu\n\n@node Saving Data on Unexpected Exits\n@subsubsection Saving Data on Unexpected Exits\n\nIf Octave for some reason exits unexpectedly it will by default save the\nvariables available in the workspace to a file in the current directory.\nBy default this file is named @samp{octave-workspace} and can be loaded\ninto memory with the @code{load} command.  While the default behavior\nmost often is reasonable it can be changed through the following\nfunctions.\n\n@DOCSTRING(crash_dumps_octave_core)\n\n@DOCSTRING(sighup_dumps_octave_core)\n\n@DOCSTRING(sigquit_dumps_octave_core)\n\n@DOCSTRING(sigterm_dumps_octave_core)\n\n@DOCSTRING(octave_core_file_options)\n\n@DOCSTRING(octave_core_file_limit)\n\n@DOCSTRING(octave_core_file_name)\n\n@node C-Style I/O Functions\n@section C-Style I/O Functions\n\nOctave's C-style input and output functions provide most of the\nfunctionality of the C programming language's standard I/O library.  The\nargument lists for some of the input functions are slightly different,\nhowever, because Octave has no way of passing arguments by reference.\n\nIn the following, @var{file} refers to a filename and @code{fid} refers\nto an integer file number, as returned by @code{fopen}.\n\nThere are three files that are always available.  Although these files\ncan be accessed using their corresponding numeric file ids, you should\nalways use the symbolic names given in the table below, since it will\nmake your programs easier to understand.\n\n@DOCSTRING(stdin)\n\n@DOCSTRING(stdout)\n\n@DOCSTRING(stderr)\n\n@menu\n* Opening and Closing Files::\n* Simple Output::\n* Line-Oriented Input::\n* Formatted Output::\n* Output Conversion for Matrices::\n* Output Conversion Syntax::\n* Table of Output Conversions::\n* Integer Conversions::\n* Floating-Point Conversions::\n* Other Output Conversions::\n* Formatted Input::\n* Input Conversion Syntax::\n* Table of Input Conversions::\n* Numeric Input Conversions::\n* String Input Conversions::\n* Binary I/O::\n* Temporary Files::\n* EOF (End of File) and Errors::\n* File Positioning::\n@end menu\n\n@node Opening and Closing Files\n@subsection Opening and Closing Files\n\nWhen reading data from a file it must be opened for reading first, and\nlikewise when writing to a file.  The @code{fopen} function returns a\npointer to an open file that is ready to be read or written.  Once all\ndata has been read from or written to the opened file it should be closed.\nThe @code{fclose} function does this.  The following code illustrates\nthe basic pattern for writing to a file, but a very similar pattern is\nused when reading a file.\n\n@example\n@group\nfilename = \"myfile.txt\";\nfid = fopen (filename, \"w\");\n# Do the actual I/O here@dots{}\nfclose (fid);\n@end group\n@end example\n\n@DOCSTRING(fopen)\n\n@DOCSTRING(fclose)\n\n@DOCSTRING(is_valid_file_id)\n\n@node Simple Output\n@subsection Simple Output\n\nOnce a file has been opened for writing a string can be written to the\nfile using the @code{fputs} function.  The following example shows\nhow to write the string @samp{Free Software is needed for Free Science}\nto the file @samp{free.txt}.\n\n@example\n@group\nfilename = \"free.txt\";\nfid = fopen (filename, \"w\");\nfputs (fid, \"Free Software is needed for Free Science\");\nfclose (fid);\n@end group\n@end example\n\n@DOCSTRING(fputs)\n\nA function much similar to @code{fputs} is available for writing data\nto the screen.  The @code{puts} function works just like @code{fputs}\nexcept it doesn't take a file pointer as its input.\n\n@DOCSTRING(puts)\n\n@node Line-Oriented Input\n@subsection Line-Oriented Input\n\nTo read from a file it must be opened for reading using @code{fopen}.\nThen a line can be read from the file using @code{fgetl} as the following\ncode illustrates\n\n@example\n@group\nfid = fopen (\"free.txt\");\ntxt = fgetl (fid)\n     @print{} Free Software is needed for Free Science\nfclose (fid);\n@end group\n@end example\n\n@noindent\nThis of course assumes that the file @samp{free.txt} exists and contains\nthe line @samp{Free Software is needed for Free Science}.\n\n@DOCSTRING(fgetl)\n\n@DOCSTRING(fgets)\n\n@DOCSTRING(fskipl)\n\n@node Formatted Output\n@subsection Formatted Output\n\nThis section describes how to call @code{printf} and related functions.\n\nThe following functions are available for formatted output.  They are\nmodeled after the C language functions of the same name, but they\ninterpret the format template differently in order to improve the\nperformance of printing vector and matrix values.\n\nImplementation Note: For compatibility with @sc{matlab}, escape sequences in\nthe template string (e.g., @qcode{\"@backslashchar{}n\"} => newline) are\nexpanded even when the template string is defined with single quotes.\n\n@DOCSTRING(printf)\n\n@DOCSTRING(fprintf)\n\n@DOCSTRING(sprintf)\n\nThe @code{printf} function can be used to print any number of arguments.\nThe template string argument you supply in a call provides\ninformation not only about the number of additional arguments, but also\nabout their types and what style should be used for printing them.\n\nOrdinary characters in the template string are simply written to the\noutput stream as-is, while @dfn{conversion specifications} introduced by\na @samp{%} character in the template cause subsequent arguments to be\nformatted and written to the output stream.  For example,\n@cindex conversion specifications (@code{printf})\n\n@example\n@group\npct = 37;\nfilename = \"foo.txt\";\nprintf (\"Processed %d%% of '%s'.\\nPlease be patient.\\n\",\n        pct, filename);\n@end group\n@end example\n\n@noindent\nproduces output like\n\n@example\n@group\nProcessed 37% of 'foo.txt'.\nPlease be patient.\n@end group\n@end example\n\nThis example shows the use of the @samp{%d} conversion to specify that a\nscalar argument should be printed in decimal notation, the @samp{%s}\nconversion to specify printing of a string argument, and the @samp{%%}\nconversion to print a literal @samp{%} character.\n\nThere are also conversions for printing an integer argument as an\nunsigned value in octal, decimal, or hexadecimal radix (@samp{%o},\n@samp{%u}, or @samp{%x}, respectively); or as a character value\n(@samp{%c}).\n\nFloating-point numbers can be printed in normal, fixed-point notation\nusing the @samp{%f} conversion or in exponential notation using the\n@samp{%e} conversion.  The @samp{%g} conversion uses either @samp{%e}\nor @samp{%f} format, depending on what is more appropriate for the\nmagnitude of the particular number.\n\nYou can control formatting more precisely by writing @dfn{modifiers}\nbetween the @samp{%} and the character that indicates which conversion\nto apply.  These slightly alter the ordinary behavior of the conversion.\nFor example, most conversion specifications permit you to specify a\nminimum field width and a flag indicating whether you want the result\nleft- or right-justified within the field.\n\nThe specific flags and modifiers that are permitted and their\ninterpretation vary depending on the particular conversion.  They're all\ndescribed in more detail in the following sections.\n\n@node Output Conversion for Matrices\n@subsection Output Conversion for Matrices\n\nWhen given a matrix value, Octave's formatted output functions cycle\nthrough the format template until all the values in the matrix have been\nprinted.  For example:\n\n@example\n@group\nprintf (\"%4.2f %10.2e %8.4g\\n\", hilb (3));\n\n     @print{} 1.00   5.00e-01   0.3333\n     @print{} 0.50   3.33e-01     0.25\n     @print{} 0.33   2.50e-01      0.2\n@end group\n@end example\n\nIf more than one value is to be printed in a single call, the output\nfunctions do not return to the beginning of the format template when\nmoving on from one value to the next.  This can lead to confusing output\nif the number of elements in the matrices are not exact multiples of the\nnumber of conversions in the format template.  For example:\n\n@example\n@group\nprintf (\"%4.2f %10.2e %8.4g\\n\", [1, 2], [3, 4]);\n\n     @print{} 1.00   2.00e+00        3\n     @print{} 4.00\n@end group\n@end example\n\nIf this is not what you want, use a series of calls instead of just one.\n\n@node Output Conversion Syntax\n@subsection Output Conversion Syntax\n\nThis section provides details about the precise syntax of conversion\nspecifications that can appear in a @code{printf} template\nstring.\n\nCharacters in the template string that are not part of a\nconversion specification are printed as-is to the output stream.\n\nThe conversion specifications in a @code{printf} template string have\nthe general form:\n\n@example\n% @var{flags} @var{width} @r{[} . @var{precision} @r{]} @var{type} @var{conversion}\n@end example\n\nFor example, in the conversion specifier @samp{%-10.8ld}, the @samp{-}\nis a flag, @samp{10} specifies the field width, the precision is\n@samp{8}, the letter @samp{l} is a type modifier, and @samp{d} specifies\nthe conversion style.  (This particular type specifier says to print a\nnumeric argument in decimal notation, with a minimum of 8 digits\nleft-justified in a field at least 10 characters wide.)\n\nIn more detail, output conversion specifications consist of an\ninitial @samp{%} character followed in sequence by:\n\n@itemize @bullet\n@item\nZero or more @dfn{flag characters} that modify the normal behavior of\nthe conversion specification.\n@cindex flag character (@code{printf})\n\n@item\nAn optional decimal integer specifying the @dfn{minimum field width}.\nIf the normal conversion produces fewer characters than this, the field\nis padded with spaces to the specified width.  This is a @emph{minimum}\nvalue; if the normal conversion produces more characters than this, the\nfield is @emph{not} truncated.  Normally, the output is right-justified\nwithin the field.\n@cindex minimum field width (@code{printf})\n\nYou can also specify a field width of @samp{*}.  This means that the\nnext argument in the argument list (before the actual value to be\nprinted) is used as the field width.  The value is rounded to the\nnearest integer.  If the value is negative, this means to set the\n@samp{-} flag (see below) and to use the absolute value as the field\nwidth.\n\n@item\nAn optional @dfn{precision} to specify the number of digits to be\nwritten for the numeric conversions.  If the precision is specified, it\nconsists of a period (@samp{.}) followed optionally by a decimal integer\n(which defaults to zero if omitted).\n@cindex precision (@code{printf})\n\nYou can also specify a precision of @samp{*}.  This means that the next\nargument in the argument list (before the actual value to be printed) is\nused as the precision.  The value must be an integer, and is ignored\nif it is negative.\n\n@item\nAn optional @dfn{type modifier character}.  This character is ignored by\nOctave's @code{printf} function, but is recognized to provide\ncompatibility with the C language @code{printf}.\n\n@item\nA character that specifies the conversion to be applied.\n@end itemize\n\nThe exact options that are permitted and how they are interpreted vary\nbetween the different conversion specifiers.  See the descriptions of the\nindividual conversions for information about the particular options that\nthey use.\n\n@node Table of Output Conversions\n@subsection Table of Output Conversions\n@cindex output conversions, for @code{printf}\n\nHere is a table summarizing what all the different conversions do:\n\n@table @asis\n@item @samp{%d}, @samp{%i}\nPrint an integer as a signed decimal number.  @xref{Integer Conversions}, for\ndetails.  @samp{%d} and @samp{%i} are synonymous for\noutput, but are different when used with @code{scanf} for input\n(@pxref{Table of Input Conversions}).\n\n@item @samp{%o}\nPrint an integer as an unsigned octal number.  @xref{Integer Conversions}, for\ndetails.\n\n@item @samp{%u}\nPrint an integer as an unsigned decimal number.  @xref{Integer Conversions},\nfor details.\n\n@item @samp{%x}, @samp{%X}\nPrint an integer as an unsigned hexadecimal number.  @samp{%x} uses\nlowercase letters and @samp{%X} uses uppercase.  @xref{Integer Conversions},\nfor details.\n\n@item @samp{%f}\nPrint a floating-point number in normal (fixed-point) notation.\n@xref{Floating-Point Conversions}, for details.\n\n@item @samp{%e}, @samp{%E}\nPrint a floating-point number in exponential notation.  @samp{%e} uses\nlowercase letters and @samp{%E} uses uppercase.\n@xref{Floating-Point Conversions}, for details.\n\n@item @samp{%g}, @samp{%G}\nPrint a floating-point number in either normal (fixed-point) or\nexponential notation, whichever is more appropriate for its magnitude.\n@samp{%g} uses lowercase letters and @samp{%G} uses uppercase.\n@xref{Floating-Point Conversions}, for details.\n\n@item @samp{%c}\nPrint a single character.  @xref{Other Output Conversions}.\n\n@item @samp{%s}\nPrint a string.  @xref{Other Output Conversions}.\n\n@item @samp{%%}\nPrint a literal @samp{%} character.  @xref{Other Output Conversions}.\n@end table\n\nIf the syntax of a conversion specification is invalid, unpredictable\nthings will happen, so don't do this.  In particular, @sc{matlab} allows\na bare percentage sign @samp{%} with no subsequent conversion character.\nOctave will emit an error and stop if it sees such code.  When the string\nvariable to be processed cannot be guaranteed to be free of potential format\ncodes it is better to use the two argument form of any of the @code{printf}\nfunctions and set the format string to @code{%s}.  Alternatively, for code\nwhich is not required to be backwards-compatible with @sc{matlab} the\nOctave function @code{puts} or @code{disp} can be used.\n\n@example\n@group\nprintf (strvar);        # Unsafe if strvar contains format codes\nprintf (\"%s\", strvar);  # Safe\nputs (strvar);          # Safe\n@end group\n@end example\n\nIf there aren't enough function arguments provided to supply values for all\nthe conversion specifications in the template string, or if the arguments are\nnot of the correct types, the results are unpredictable.  If you supply more\narguments than conversion specifications, the extra argument values are\nsimply ignored; this is sometimes useful.\n\n@node Integer Conversions\n@subsection Integer Conversions\n\nThis section describes the options for the @samp{%d}, @samp{%i},\n@samp{%o}, @samp{%u}, @samp{%x}, and @samp{%X} conversion\nspecifications.  These conversions print integers in various formats.\n\nThe @samp{%d} and @samp{%i} conversion specifications both print an\nnumeric argument as a signed decimal number; while @samp{%o},\n@samp{%u}, and @samp{%x} print the argument as an unsigned octal,\ndecimal, or hexadecimal number (respectively).  The @samp{%X} conversion\nspecification is just like @samp{%x} except that it uses the characters\n@samp{ABCDEF} as digits instead of @samp{abcdef}.\n\nThe following flags are meaningful:\n\n@table @asis\n@item @samp{-}\nLeft-justify the result in the field (instead of the normal\nright-justification).\n\n@item @samp{+}\nFor the signed @samp{%d} and @samp{%i} conversions, print a\nplus sign if the value is positive.\n\n@item @samp{ }\nFor the signed @samp{%d} and @samp{%i} conversions, if the result\ndoesn't start with a plus or minus sign, prefix it with a space\ncharacter instead.  Since the @samp{+} flag ensures that the result\nincludes a sign, this flag is ignored if you supply both of them.\n\n@item @samp{#}\nFor the @samp{%o} conversion, this forces the leading digit to be\n@samp{0}, as if by increasing the precision.  For @samp{%x} or\n@samp{%X}, this prefixes a leading @samp{0x} or @samp{0X} (respectively)\nto the result.  This doesn't do anything useful for the @samp{%d},\n@samp{%i}, or @samp{%u} conversions.\n\n@item @samp{0}\nPad the field with zeros instead of spaces.  The zeros are placed after\nany indication of sign or base.  This flag is ignored if the @samp{-}\nflag is also specified, or if a precision is specified.\n@end table\n\nIf a precision is supplied, it specifies the minimum number of digits to\nappear; leading zeros are produced if necessary.  If you don't specify a\nprecision, the number is printed with as many digits as it needs.  If\nyou convert a value of zero with an explicit precision of zero, then no\ncharacters at all are produced.\n\n@node Floating-Point Conversions\n@subsection Floating-Point Conversions\n\nThis section discusses the conversion specifications for floating-point\nnumbers: the @samp{%f}, @samp{%e}, @samp{%E}, @samp{%g}, and @samp{%G}\nconversions.\n\nThe @samp{%f} conversion prints its argument in fixed-point notation,\nproducing output of the form\n@w{[@code{-}]@var{ddd}@code{.}@var{ddd}},\nwhere the number of digits following the decimal point is controlled\nby the precision you specify.\n\nThe @samp{%e} conversion prints its argument in exponential notation,\nproducing output of the form\n@w{[@code{-}]@var{d}@code{.}@var{ddd}@code{e}[@code{+}|@code{-}]@var{dd}}.\nAgain, the number of digits following the decimal point is controlled by\nthe precision.  The exponent always contains at least two digits.  The\n@samp{%E} conversion is similar but the exponent is marked with the letter\n@samp{E} instead of @samp{e}.\n\nThe @samp{%g} and @samp{%G} conversions print the argument in the style\nof @samp{%e} or @samp{%E} (respectively) if the exponent would be less\nthan -4 or greater than or equal to the precision; otherwise they use the\n@samp{%f} style.  Trailing zeros are removed from the fractional portion\nof the result and a decimal-point character appears only if it is\nfollowed by a digit.\n\nThe following flags can be used to modify the behavior:\n@c Not @samp so we can have ' ' as an item.\n\n@table @asis\n@item @samp{-}\nLeft-justify the result in the field.  Normally the result is\nright-justified.\n\n@item @samp{+}\nAlways include a plus or minus sign in the result.\n\n@item @samp{ }\nIf the result doesn't start with a plus or minus sign, prefix it with a\nspace instead.  Since the @samp{+} flag ensures that the result includes\na sign, this flag is ignored if you supply both of them.\n\n@item @samp{#}\nSpecifies that the result should always include a decimal point, even\nif no digits follow it.  For the @samp{%g} and @samp{%G} conversions,\nthis also forces trailing zeros after the decimal point to be left\nin place where they would otherwise be removed.\n\n@item @samp{0}\nPad the field with zeros instead of spaces; the zeros are placed\nafter any sign.  This flag is ignored if the @samp{-} flag is also\nspecified.\n@end table\n\nThe precision specifies how many digits follow the decimal-point\ncharacter for the @samp{%f}, @samp{%e}, and @samp{%E} conversions.  For\nthese conversions, the default precision is @code{6}.  If the precision\nis explicitly @code{0}, this suppresses the decimal point character\nentirely.  For the @samp{%g} and @samp{%G} conversions, the precision\nspecifies how many significant digits to print.  Significant digits are\nthe first digit before the decimal point, and all the digits after it.\nIf the precision is @code{0} or not specified for @samp{%g} or\n@samp{%G}, it is treated like a value of @code{1}.  If the value being\nprinted cannot be expressed precisely in the specified number of digits,\nthe value is rounded to the nearest number that fits.\n\n@node Other Output Conversions\n@subsection Other Output Conversions\n\nThis section describes miscellaneous conversions for @code{printf}.\n\nThe @samp{%c} conversion prints a single character.  The @samp{-}\nflag can be used to specify left-justification in the field, but no\nother flags are defined, and no precision or type modifier can be given.\nFor example:\n\n@example\nprintf (\"%c%c%c%c%c\", \"h\", \"e\", \"l\", \"l\", \"o\");\n@end example\n\n@noindent\nprints @samp{hello}.\n\nThe @samp{%s} conversion prints a string.  The corresponding argument\nmust be a string.  A precision can be specified to indicate the maximum\nnumber of characters to write; otherwise characters in the string up to\nbut not including the terminating null character are written to the\noutput stream.  The @samp{-} flag can be used to specify\nleft-justification in the field, but no other flags or type modifiers\nare defined for this conversion.  For example:\n\n@example\nprintf (\"%3s%-6s\", \"no\", \"where\");\n@end example\n\n@noindent\nprints @samp{ nowhere } (note the leading and trailing spaces).\n\n@node Formatted Input\n@subsection Formatted Input\n\nOctave provides the @code{scanf}, @code{fscanf}, and @code{sscanf}\nfunctions to read formatted input.  There are two forms of each of these\nfunctions.  One can be used to extract vectors of data from a file, and\nthe other is more `C-like'.\n\n@DOCSTRING(fscanf)\n\n@DOCSTRING(scanf)\n\n@DOCSTRING(sscanf)\n\nCalls to @code{scanf} are superficially similar to calls to\n@code{printf} in that arbitrary arguments are read under the control of\na template string.  While the syntax of the conversion specifications in\nthe template is very similar to that for @code{printf}, the\ninterpretation of the template is oriented more towards free-format\ninput and simple pattern matching, rather than fixed-field formatting.\nFor example, most @code{scanf} conversions skip over any amount of\n``white space'' (including spaces, tabs, and newlines) in the input\nfile, and there is no concept of precision for the numeric input\nconversions as there is for the corresponding output conversions.\nOrdinarily, non-whitespace characters in the template are expected to\nmatch characters in the input stream exactly.  For example, note that\n@code{sscanf} parses the string and whitespace differently when using\nmixed numeric and string output types:\n@cindex conversion specifications (@code{scanf})\n\n@example\n@group\nteststr = \"1 is a lonely number\";\nsscanf (teststr, \"%s is a %s\")\n@xresult{} 1lonelynumber\n\nsscanf (teststr, \"%g is a %s\")\n@xresult{}\n     1\n   108\n   111\n   110\n   101\n   108\n   121\n\n[a, b, c] = sscanf (\"1 is a lonely number\", \"%g is a %s %s\", \"C\")\n@xresult{} a =  1\n@xresult{} b = lonely\n@xresult{} c = number\n@end group\n@end example\n\nWhen a @dfn{matching failure} occurs, @code{scanf} returns immediately,\nleaving the first non-matching character as the next character to be\nread from the stream, and @code{scanf} returns all the items that were\nsuccessfully converted.\n@cindex matching failure, in @code{scanf}\n\nThe formatted input functions are not used as frequently as the\nformatted output functions.  Partly, this is because it takes some care\nto use them properly.  Another reason is that it is difficult to recover\nfrom a matching error.\n\nThe specific flags and modifiers that are permitted in the template string\nand their interpretation are all described in more detail in the following\nsections.\n\n@node Input Conversion Syntax\n@subsection Input Conversion Syntax\n\nA @code{scanf} template string is a string that contains ordinary\nmultibyte characters interspersed with conversion specifications that\nstart with @samp{%}.\n\nAny whitespace character in the template causes any number of whitespace\ncharacters in the input stream to be read and discarded.  The whitespace\ncharacters that are matched need not be exactly the same whitespace\ncharacters that appear in the template string.  For example, write\n@samp{ , } in the template to recognize a comma with optional whitespace\nbefore and after.\n\nOther characters in the template string that are not part of conversion\nspecifications must match characters in the input stream exactly; if\nthis is not the case, a matching failure occurs.\n\nThe conversion specifications in a @code{scanf} template string\nhave the general form:\n\n@example\n% @var{flags} @var{width} @var{type} @var{conversion}\n@end example\n\nIn more detail, an input conversion specification consists of an initial\n@samp{%} character followed in sequence by:\n\n@itemize @bullet\n@item\nAn optional @dfn{flag character} @samp{*}, which says to ignore the text\nread for this specification.  When @code{scanf} finds a conversion\nspecification that uses this flag, it reads input as directed by the\nrest of the conversion specification, but it discards this input, does\nnot return any value, and does not increment the count of\nsuccessful assignments.\n@cindex flag character (@code{scanf})\n\n@item\nAn optional decimal integer that specifies the @dfn{maximum field\nwidth}.  Reading of characters from the input stream stops either when\nthis maximum is reached or when a non-matching character is found,\nwhichever happens first.  Most conversions discard initial whitespace\ncharacters, and these discarded characters don't count towards the\nmaximum field width.  Conversions that do not discard initial whitespace\nare explicitly documented.\n@cindex maximum field width (@code{scanf})\n\n@item\nAn optional type modifier character.  This character is ignored by\nOctave's @code{scanf} function, but is recognized to provide\ncompatibility with the C language @code{scanf}.\n\n@item\nA character that specifies the conversion to be applied.\n@end itemize\n\nThe exact options that are permitted and how they are interpreted vary\nbetween the different conversion specifiers.  See the descriptions of the\nindividual conversions in @ref{Table of Input Conversions} for\ninformation about the particular options that they allow.\n\n@node Table of Input Conversions\n@subsection Table of Input Conversions\n@cindex input conversions, for @code{scanf}\n\nHere is a table that summarizes the various conversion specifications:\n\n@table @asis\n@item @samp{%d}\nMatches an optionally signed integer written in decimal.\n@xref{Numeric Input Conversions}.\n\n@item @samp{%i}\nMatches an optionally signed integer in any of the formats that the C\nlanguage defines for specifying an integer constant.\n@xref{Numeric Input Conversions}.\n\n@item @samp{%o}\nMatches an unsigned integer written in octal radix.\n@xref{Numeric Input Conversions}.\n\n@item @samp{%u}\nMatches an unsigned integer written in decimal radix.\n@xref{Numeric Input Conversions}.\n\n@item @samp{%x}, @samp{%X}\nMatches an unsigned integer written in hexadecimal radix.\n@xref{Numeric Input Conversions}.\n\n@item @samp{%e}, @samp{%f}, @samp{%g}, @samp{%E}, @samp{%G}\nMatches an optionally signed floating-point number.\n@xref{Numeric Input Conversions}.\n\n@item @samp{%s}\nMatches a string containing only non-whitespace characters.\n@xref{String Input Conversions}.\n\n@item @samp{%c}\nMatches a string of one or more characters; the number of characters\nread is controlled by the maximum field width given for the conversion.\n@xref{String Input Conversions}.\n\n@item @samp{%%}\nThis matches a literal @samp{%} character in the input stream.  No\ncorresponding argument is used.\n@end table\n\nIf the syntax of a conversion specification is invalid, the behavior is\nundefined.  If there aren't enough function arguments provided to supply\naddresses for all the conversion specifications in the template strings\nthat perform assignments, or if the arguments are not of the correct\ntypes, the behavior is also undefined.  On the other hand, extra\narguments are simply ignored.\n\n@node Numeric Input Conversions\n@subsection Numeric Input Conversions\n\nThis section describes the @code{scanf} conversions for reading numeric\nvalues.\n\nThe @samp{%d} conversion matches an optionally signed integer in decimal\nradix.\n\nThe @samp{%i} conversion matches an optionally signed integer in any of\nthe formats that the C language defines for specifying an integer\nconstant.\n\nFor example, any of the strings @samp{10}, @samp{0xa}, or @samp{012}\ncould be read in as integers under the @samp{%i} conversion.  Each of\nthese specifies a number with decimal value @code{10}.\n\nThe @samp{%o}, @samp{%u}, and @samp{%x} conversions match unsigned\nintegers in octal, decimal, and hexadecimal radices, respectively.\n\nThe @samp{%X} conversion is identical to the @samp{%x} conversion.  They\nboth permit either uppercase or lowercase letters to be used as digits.\n\nBy default, integers are read as 32-bit quantities.  With the @samp{h}\nmodifier, 16-bit integers are used, and with the @samp{l} modifier,\n64-bit integers are used.\n\nThe @samp{%e}, @samp{%f}, @samp{%g}, @samp{%E}, and @samp{%G} conversions\nmatch optionally signed floating-point numbers.  All five conversion\nspecifications behave identically, and will read in numerical values of\nany floating point display style.\n\n@node String Input Conversions\n@subsection String Input Conversions\n\nThis section describes the @code{scanf} input conversions for reading\nstring and character values: @samp{%s} and @samp{%c}.\n\nThe @samp{%c} conversion is the simplest: it matches a fixed number of\ncharacters, always.  The maximum field with says how many characters to\nread; if you don't specify the maximum, the default is 1.  This\nconversion does not skip over initial whitespace characters.  It reads\nprecisely the next @var{n} characters, and fails if it cannot get that\nmany.\n\nThe @samp{%s} conversion matches a string of non-whitespace characters.\nIt skips and discards initial whitespace, but stops when it encounters\nmore whitespace after having read something.\n\nFor example, reading the input:\n\n@example\n hello, world\n@end example\n\n@noindent\nwith the conversion @samp{%10c} produces @qcode{\" hello, wo\"}, but\nreading the same input with the conversion @samp{%10s} produces\n@qcode{\"hello,\"}.\n\n@node Binary I/O\n@subsection Binary I/O\n\nOctave can read and write binary data using the functions @code{fread}\nand @code{fwrite}, which are patterned after the standard C functions\nwith the same names.  They are able to automatically swap the byte order\nof integer data and convert among the supported floating point formats\nas the data are read.\n\n@DOCSTRING(fread)\n\n@DOCSTRING(fwrite)\n\n@node Temporary Files\n@subsection Temporary Files\n\nSometimes one needs to write data to a file that is only temporary.\nThis is most commonly used when an external program launched from\nwithin Octave needs to access data.  When Octave exits all temporary\nfiles will be deleted, so this step need not be executed manually.\n\n@DOCSTRING(mkstemp)\n\n@DOCSTRING(tmpfile)\n\n@DOCSTRING(tempname)\n\n@DOCSTRING(tempdir)\n\n@DOCSTRING(P_tmpdir)\n\n@node EOF (End of File) and Errors\n@subsection EOF (End of File) and Errors\n\nOnce a file has been opened its status can be acquired.  As an example\nthe @code{feof} functions determines if the end of the file has been\nreached.  This can be very useful when reading small parts of a file\nat a time.  The following example shows how to read one line at a time\nfrom a file until the end has been reached.\n\n@example\n@group\nfilename = \"myfile.txt\";\nfid = fopen (filename, \"r\");\nwhile (! feof (fid) )\n  text_line = fgetl (fid);\nendwhile\nfclose (fid);\n@end group\n@end example\n\n@noindent\nNote that in some situations it is more efficient to read the entire\ncontents of a file and then process it, than it is to read it line by\nline.  This has the potential advantage of removing the loop in the\nabove code.\n\n@DOCSTRING(feof)\n\n@DOCSTRING(ferror)\n\n@DOCSTRING(fclear)\n\n@DOCSTRING(freport)\n\n@node File Positioning\n@subsection File Positioning\n\nThree functions are available for setting and determining the position of\nthe file pointer for a given file.\n\n@DOCSTRING(ftell)\n\n@DOCSTRING(fseek)\n\n@DOCSTRING(SEEK_SET)\n\n@DOCSTRING(SEEK_CUR)\n\n@DOCSTRING(SEEK_END)\n\n@DOCSTRING(frewind)\n\nThe following example stores the current file position in the variable\n@code{marker}, moves the pointer to the beginning of the file, reads\nfour characters, and then returns to the original position.\n\n@example\n@group\nmarker = ftell (myfile);\nfrewind (myfile);\nfourch = fgets (myfile, 4);\nfseek (myfile, marker, SEEK_SET);\n@end group\n@end example\n"
  },
  {
    "path": "doc/interpreter/linalg.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Linear Algebra\n@chapter Linear Algebra\n@cindex linear algebra\n\nThis chapter documents the linear algebra functions provided in Octave.\nReference material for many of these functions may be found in\n@nospell{Golub and Van Loan}, @cite{Matrix Computations, 2nd Ed.},\nJohns Hopkins, 1989, and in the @cite{@sc{lapack} Users' Guide}, SIAM, 1992.\nThe @cite{@sc{lapack} Users' Guide} is available at:\n@cite{http://www.netlib.org/lapack/lug/}.\n\nA common text for engineering courses is @nospell{G. Strang},\n@cite{Linear Algebra and Its Applications, 4th Edition}.  It has become a\nwidespread reference for linear algebra.  An alternative is @nospell{P. Lax},\n@cite{Linear Algebra and Its Applications}, and also is a good choice.  It\nclaims to be suitable for high school students with substantial mathematical\ninterests as well as first-year undergraduates.\n\n@menu\n* Techniques Used for Linear Algebra::\n* Basic Matrix Functions::\n* Matrix Factorizations::\n* Functions of a Matrix::\n* Specialized Solvers::\n@end menu\n\n@node Techniques Used for Linear Algebra\n@section Techniques Used for Linear Algebra\n@cindex linear algebra, techniques\n\nOctave includes a polymorphic solver that selects an appropriate matrix\nfactorization depending on the properties of the matrix itself.\nGenerally, the cost of determining the matrix type is small relative to\nthe cost of factorizing the matrix itself.  In any case the matrix type\nis cached once it is calculated so that it is not re-determined each\ntime it is used in a linear equation.\n\nThe selection tree for how the linear equation is solved or a matrix\ninverse is formed is given by:\n\n@enumerate 1\n@item If the matrix is upper or lower triangular sparse use a forward or\nbackward substitution using the @sc{lapack} xTRTRS function, and goto 4.\n\n@c Permuted triangular matrices currently disabled in the code\n@c\n@c @item If the matrix is a upper triangular matrix with column permutations\n@c or lower triangular matrix with row permutations, perform a forward or\n@c backward substitution, and goto 5.\n\n@item If the matrix is square, Hermitian with a real positive diagonal,\nattempt Cholesky@tie{}factorization using the @sc{lapack} xPOTRF function.\n\n@item If the Cholesky@tie{}factorization failed or the matrix is not\nHermitian with a real positive diagonal, and the matrix is square, factorize\nusing the @sc{lapack} xGETRF function.\n\n@item If the matrix is not square, or any of the previous solvers flags\na singular or near singular matrix, find a least squares solution using\nthe @sc{lapack} xGELSD function.\n@end enumerate\n\nThe user can force the type of the matrix with the @code{matrix_type}\nfunction.  This overcomes the cost of discovering the type of the matrix.\nHowever, it should be noted that identifying the type of the matrix incorrectly\nwill lead to unpredictable results, and so @code{matrix_type} should be\nused with care.\n\nIt should be noted that the test for whether a matrix is a candidate for\nCholesky@tie{}factorization, performed above, and by the @code{matrix_type}\nfunction, does not make certain that the matrix is\nHermitian.  However, the attempt to factorize the matrix will quickly\ndetect a non-Hermitian matrix.\n\n@node Basic Matrix Functions\n@section Basic Matrix Functions\n@cindex matrix functions, basic\n\n@DOCSTRING(balance)\n\n@DOCSTRING(bandwidth)\n\n@DOCSTRING(cond)\n\n@DOCSTRING(condeig)\n\n@DOCSTRING(det)\n\n@DOCSTRING(eig)\n\n@DOCSTRING(givens)\n\n@DOCSTRING(gsvd)\n\n@DOCSTRING(planerot)\n\n@DOCSTRING(inv)\n\n@DOCSTRING(linsolve)\n\n@DOCSTRING(matrix_type)\n\n@DOCSTRING(norm)\n\n@DOCSTRING(null)\n\n@DOCSTRING(orth)\n\n@DOCSTRING(mgorth)\n\n@DOCSTRING(pinv)\n@cindex pseudoinverse\n\n@DOCSTRING(rank)\n\n@DOCSTRING(rcond)\n\n@DOCSTRING(trace)\n\n@DOCSTRING(rref)\n\n@DOCSTRING(vecnorm)\n\n@node Matrix Factorizations\n@section Matrix Factorizations\n@cindex matrix factorizations\n\n@DOCSTRING(chol)\n\n@DOCSTRING(cholinv)\n\n@DOCSTRING(chol2inv)\n\n@DOCSTRING(cholupdate)\n\n@DOCSTRING(cholinsert)\n\n@DOCSTRING(choldelete)\n\n@DOCSTRING(cholshift)\n\n@DOCSTRING(hess)\n\n@DOCSTRING(lu)\n\n@DOCSTRING(luupdate)\n\n@DOCSTRING(qr)\n\n@DOCSTRING(qrupdate)\n\n@DOCSTRING(qrinsert)\n\n@DOCSTRING(qrdelete)\n\n@DOCSTRING(qrshift)\n\n@DOCSTRING(qz)\n\n@DOCSTRING(qzhess)\n\n@DOCSTRING(schur)\n\n@DOCSTRING(rsf2csf)\n\n@DOCSTRING(ordschur)\n\n@DOCSTRING(trexc)\n\n@DOCSTRING(ordqz)\n\n@DOCSTRING(ordeig)\n\n@DOCSTRING(subspace)\n\n@DOCSTRING(svd)\n\n@DOCSTRING(svd_driver)\n\n@c FIXME: should there be a new section here?\n\n@DOCSTRING(housh)\n\n@DOCSTRING(krylov)\n\n@node Functions of a Matrix\n@section Functions of a Matrix\n@cindex matrix, functions of\n\n@DOCSTRING(expm)\n\n@DOCSTRING(logm)\n\n@DOCSTRING(sqrtm)\n\n@DOCSTRING(funm)\n\n@DOCSTRING(kron)\n\n@DOCSTRING(tensorprod)\n\n@DOCSTRING(blkmm)\n\n@DOCSTRING(sylvester)\n\n@node Specialized Solvers\n@section Specialized Solvers\n@cindex matrix, specialized solvers\n\n@DOCSTRING(bicg)\n\n@DOCSTRING(bicgstab)\n\n@DOCSTRING(cgs)\n\n@DOCSTRING(gmres)\n\n@DOCSTRING(qmr)\n\n@DOCSTRING(tfqmr)\n"
  },
  {
    "path": "doc/interpreter/macros.texi",
    "content": "@c ---------------------------------------------------------------------\n@c\n@c Copyright (C) 2012-2026 The Octave Project Developers\n@c\n@c See the file COPYRIGHT.md in the top-level directory of this\n@c or <https://octave.org/copyright/>.\n@c\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n@c\n@c ---------------------------------------------------------------------\n\n@c The following macro marks words that aspell should ignore during\n@c spellchecking.  Within Texinfo it has no effect as it merely replaces\n@c the macro call with the argument itself.\n\n@macro nospell {arg}\n\\arg\\\n@end macro\n\n@c The following macro works around the Info/plain text expansion of @code{XXX}\n@c which is `XXX'.  This looks particularly bad when the macro body is\n@c single or double-quoted text, such as a property value `\"position\"'.\n@c The mnemonic to remember this macro is Quoted CODE.\n\n@ifinfo\n@macro qcode{arg}\n\\arg\\\n@end macro\n@end ifinfo\n@ifnotinfo\n@macro qcode{arg}\n@code{\\arg\\}\n@end macro\n@end ifnotinfo\n\n@c The following macro works around the Info/plain text expansion of @code{XXX}\n@c which is `XXX'.  This can be confusing when the macro body itself\n@c ends with a transpose character, such as `x''.\n@c The mnemonic to remember this macro is Transpose CODE.\n\n@ifinfo\n@macro tcode{arg}\n\\arg\\\n@end macro\n@end ifinfo\n@ifnotinfo\n@macro tcode{arg}\n@code{\\arg\\}\n@end macro\n@end ifnotinfo\n\n@c The following macro is used for the on-line help system, but we don't want\n@c lots of `See also: foo, bar, and baz' strings cluttering the printed manual\n@c (that information should be in the supporting text for each group of\n@c functions and variables).\n@c\n@c Implementation Note:\n@c For TeX, @vskip produces a nice separation.\n@c For Texinfo, '@sp 1' should work, but in practice produces ugly results.\n@c For HTML, a simple blank line produces the correct behavior.\n@c\n@c The macro is named @xseealso now because Texinfo introduced its own @seealso\n@c command.  But, instead of modifying all source files, the build system uses\n@c the munge-texi script to convert @seealso to @xseealso.\n\n@macro xseealso {args}\n@iftex\n@vskip 2pt\n@end iftex\n@ifnottex\n\n@end ifnottex\n@ifnotinfo\n@noindent\n@strong{See also:} \\args\\.\n@end ifnotinfo\n@ifinfo\n@noindent\nSee also: \\args\\.\n@end ifinfo\n@end macro\n\n@c The following macro works around the HTML expansion of @result{} which is\n@c a single glyph (right arrow \"&rarr\").  All other formats expand to a\n@c sequence that is 2-characters wide.  The resulting one-character difference\n@c throws off alignment of columns in the documentation.  Only for HTML,\n@c expand @xresult to \"right arrow\" + \"SPACE\".\n\n@ifhtml\n@macro xresult\n@result{} \n@end macro\n@end ifhtml\n@ifnothtml\n@alias xresult=result\n@end ifnothtml\n"
  },
  {
    "path": "doc/interpreter/matrix.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Matrix Manipulation\n@chapter Matrix Manipulation\n\nThere are a number of functions available for checking to see if the\nelements of a matrix meet some condition, and for rearranging the\nelements of a matrix.  For example, Octave can easily tell you if all\nthe elements of a matrix are finite, or are less than some specified\nvalue.  Octave can also rotate the elements, extract the upper- or\nlower-triangular parts, or sort the columns of a matrix.\n\n@menu\n* Finding Elements and Checking Conditions::\n* Rearranging Matrices::\n* Special Utility Matrices::\n* Famous Matrices::\n@end menu\n\n@node Finding Elements and Checking Conditions\n@section Finding Elements and Checking Conditions\n\nThe functions @code{any} and @code{all} are useful for determining\nwhether any or all of the elements of a matrix satisfy some condition.\nThe @code{find} function is also useful in determining which elements of\na matrix meet a specified condition.\n\n@DOCSTRING(any)\n\n@DOCSTRING(all)\n\nSince the comparison operators (@pxref{Comparison Ops}) return matrices\nof ones and zeros, it is easy to test a matrix for many things, not just\nwhether the elements are nonzero.  For example,\n\n@example\n@group\nall (all (rand (5) < 0.9))\n     @xresult{} 0\n@end group\n@end example\n\n@noindent\ntests a random 5 by 5 matrix to see if all of its elements are less\nthan 0.9.\n\nNote that in conditional contexts (like the test clause of @code{if} and\n@code{while} statements) Octave treats the test as if you had typed\n@code{all (all (condition))}.\n\n@DOCSTRING(xor)\n\n@DOCSTRING(diff)\n\n@DOCSTRING(isinf)\n\n@DOCSTRING(isnan)\n\n@DOCSTRING(isfinite)\n\n@DOCSTRING(common_size)\n\n@DOCSTRING(find)\n\n@DOCSTRING(lookup)\n\nIf you wish to check if a variable exists at all, instead of properties\nits elements may have, @pxref{Status of Variables}.\n\n@node Rearranging Matrices\n@section Rearranging Matrices\n\n@DOCSTRING(fliplr)\n\n@DOCSTRING(flipud)\n\n@DOCSTRING(flip)\n\n@DOCSTRING(rot90)\n\n@DOCSTRING(rotdim)\n\n@DOCSTRING(cat)\n\n@DOCSTRING(horzcat)\n\n@DOCSTRING(vertcat)\n\n@DOCSTRING(permute)\n\n@DOCSTRING(ipermute)\n\n@DOCSTRING(reshape)\n\n@DOCSTRING(resize)\n\n@DOCSTRING(circshift)\n\n@DOCSTRING(shiftdim)\n\n@DOCSTRING(sort)\n\n@DOCSTRING(sortrows)\n\n@DOCSTRING(issorted)\n\n@DOCSTRING(nth_element)\n\n@DOCSTRING(tril)\n\n@DOCSTRING(triu)\n\n@DOCSTRING(vec)\n\n@DOCSTRING(vech)\n\n@DOCSTRING(prepad)\n\n@DOCSTRING(postpad)\n\n@DOCSTRING(diag)\n\n@DOCSTRING(blkdiag)\n\n@node Special Utility Matrices\n@section Special Utility Matrices\n\n@DOCSTRING(eye)\n\n@DOCSTRING(ones)\n\n@DOCSTRING(zeros)\n\n@DOCSTRING(repmat)\n\n@DOCSTRING(repelems)\n\n@DOCSTRING(repelem)\n\nThe functions @code{linspace} and @code{logspace} make it very easy to\ncreate vectors with evenly or logarithmically spaced elements.\n@xref{Ranges}.\n\n@DOCSTRING(linspace)\n\n@DOCSTRING(logspace)\n\n@DOCSTRING(rand)\n\n@DOCSTRING(randi)\n\n@DOCSTRING(randn)\n\n@DOCSTRING(rande)\n\n@DOCSTRING(randp)\n\n@DOCSTRING(randg)\n\n@DOCSTRING(rng)\n\nThe generators operate in the new or old style together, it is not\npossible to mix the two.  Initializing any generator with\n@qcode{\"state\"} or @qcode{\"seed\"} causes the others to switch to the\nsame style for future calls.\n\nThe state of each generator is independent and calls to different\ngenerators can be interleaved without affecting the final result.  For\nexample,\n\n@example\n@group\nrand (\"state\", [11, 22, 33]);\nrandn (\"state\", [44, 55, 66]);\nu = rand (100, 1);\nn = randn (100, 1);\n@end group\n@end example\n\n@noindent\nand\n\n@example\n@group\nrand (\"state\", [11, 22, 33]);\nrandn (\"state\", [44, 55, 66]);\nu = zeros (100, 1);\nn = zeros (100, 1);\nfor i = 1:100\n  u(i) = rand ();\n  n(i) = randn ();\nend\n@end group\n@end example\n\n@noindent\nproduce equivalent results.  When the generators are initialized in\nthe old style with @qcode{\"seed\"} only @code{rand} and @code{randn} are\nindependent, because the old @code{rande}, @code{randg} and\n@code{randp} generators make calls to @code{rand} and @code{randn}.\n\nThe generators are initialized with random states at start-up, so\nthat the sequences of random numbers are not the same each time you run\nOctave.@footnote{The old versions of @code{rand} and @code{randn}\nobtain their initial seeds from the system clock.} If you really do\nneed to reproduce a sequence of numbers exactly, you can set the state\nor seed to a specific value.\n\nIf invoked without arguments, @code{rand} and @code{randn} return a\nsingle element of a random sequence.\n\nThe original @code{rand} and @code{randn} functions use Fortran code from\n@sc{ranlib}, a library of Fortran routines for random number generation,\ncompiled by Barry W. Brown and @nospell{James Lovato} of the Department of\nBiomathematics at The University of Texas, M.D. Anderson Cancer Center,\nHouston, TX 77030.\n\n@DOCSTRING(randperm)\n\n@node Famous Matrices\n@section Famous Matrices\n\nThe following functions return famous matrix forms.\n\n@DOCSTRING(gallery)\n\n@DOCSTRING(hadamard)\n\n@DOCSTRING(hankel)\n\n@DOCSTRING(hilb)\n\n@DOCSTRING(invhilb)\n\n@DOCSTRING(magic)\n\n@DOCSTRING(pascal)\n\n@DOCSTRING(rosser)\n\n@DOCSTRING(toeplitz)\n\n@DOCSTRING(vander)\n\n@DOCSTRING(wilkinson)\n"
  },
  {
    "path": "doc/interpreter/mk-doc-cache.pl",
    "content": "#!/usr/bin/perl\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# This script is based on the old mk_doc_cache.m file.\n\nuse strict;\nuse warnings;\n\nuse File::Spec;\nuse File::Temp;\n\nmy $doc_delim = \"\\x{1d}\";\nmy $tex_delim_ptn = qr/\\Q-*- texinfo -*-\\E/;\n\n## Returns a File::Temp object with Texinfo code.\nsub make_texinfo_file\n{\n  my $srcdir = shift;\n  my $macro_fpath = shift;\n  my @docstrings = @_;\n\n  my $tmpfile = File::Temp->new (UNLINK => 1);\n\n  ## Only the first file is the macro file.  Copy its contents verbatim.\n  open (my $FH_macro, \"<\", $macro_fpath)\n    or die \"Unable to open $macro_fpath for reading: $!\\n\";\n  while (<$FH_macro>) {  print {$tmpfile} $_;  }\n  close ($FH_macro);\n\n  foreach my $filepath (@docstrings)\n    {\n      ## DOCSTRINGS files may exist in the current (build) directory or in\n      ## the source directory when building from a release.\n      if (! -e $filepath)\n        {\n          ## Only triggered when re-building doc-cache outside source\n          ## tree, from released sources.\n          $filepath = File::Spec->catfile ($srcdir, $filepath);\n        }\n      open (my $FH, \"<\", $filepath)\n        or die \"Unable to open $filepath for reading: $!\\n\";\n\n      my $in_header = 1;\n      while (my $line = <$FH>)\n        {\n          ## DOCSTRINGS header ends once we find the first function.\n          if ($in_header && $line =~ m/^$doc_delim/)\n            {\n              $in_header = 0;\n            }\n          next if ($in_header);\n          next if ($line =~ /$tex_delim_ptn/);\n\n          ## Change @seealso to private @xseealso macro\n          if ($line =~ m'@seealso')\n          {\n            ## Combine @seealso macro spread over multiple lines\n            while ($line !~ m/}$/) {  $line .= <$FH>;  }\n\n            ## escape @ characters in old-style class names like @ftp\n            $line =~ s/\\@(\\w)/\\@\\@$1/g;\n            $line =~ s'@@seealso'@xseealso';\n          }\n\n          ## escape {}@ characters in Texinfo anchor name (e.g., @ftp/dir.m)\n          $line =~ s/([{}@])/\\@$1/g if ($line =~ m/^$doc_delim/);\n\n          print {$tmpfile} $line;\n        }\n      close ($FH);\n    }\n\n  print {$tmpfile} $doc_delim;\n\n  $tmpfile->flush ();\n\n  return $tmpfile;\n}\n\nsub get_info_text\n{\n  my $texi_path = shift;\n\n  my $makeinfo_command = \"makeinfo --no-headers --no-warn --force --no-validate --fill-column=1024 '$texi_path'\";\n  my $info_text = `$makeinfo_command`;\n\n  die \"Unable to start makeinfo command '$makeinfo_command'\"\n    if (! defined $info_text);\n\n  die \"makeinfo produced no output!\"\n    if (! $info_text);\n\n  return $info_text;\n}\n\nsub split_info\n{\n  my $info_text = shift;\n\n  ## Constant patterns.  We only check for two underscores at the end,\n  ## and not at the start, to also skip @class/__method__\n  my $private_name_ptn = qr/__$/;\n\n  my @formatted = ();\n\n  my $beg_idx = index ($info_text, $doc_delim);\n  while ($beg_idx >= 0)\n    {\n      my $end_idx = index ($info_text, $doc_delim, $beg_idx+1);\n      if ($end_idx < 1)\n        {\n          $beg_idx = -1;\n          next;\n        }\n      my $block = substr ($info_text, $beg_idx+1, $end_idx-$beg_idx-1);\n      $beg_idx = $end_idx;\n\n      my ($symbol, $doc) = split (/[\\r\\n]/, $block, 2);\n\n      next if (length ($symbol) > 2 && $symbol =~ m/$private_name_ptn/);\n\n      if (! defined ($doc))\n      {\n        warn \"mk-doc-cache.pl: function '$symbol' may be undocumented\";\n        next;\n      }\n\n      $doc =~ s/^[\\r\\n]+//;\n      next if (! $doc);\n\n      (my $tmp = $doc) =~ s/^[\\r\\n]*  *-- .*[\\r\\n]//mg;\n      next if (! $tmp);\n\n      (my $first_sentence = $tmp) =~ s/(\\.|[\\r\\n][\\r\\n]).*/$1/s;\n      $first_sentence =~ s/([\\r\\n]| {2,})/ /g;\n      $first_sentence =~ s/   *$/ /g;\n      $first_sentence =~ s/^ +//;\n\n      push (@formatted, [($symbol, $doc, $first_sentence)]);\n    }\n\n  return @formatted;\n}\n\nsub print_element\n{\n  my ($str) = @_;\n  my $len = length ($str);\n\n  print <<__END_OF_ELEMENT__;\n# name: <cell-element>\n# type: sq_string\n# elements: 1\n# length: $len\n$str\\n\\n\n__END_OF_ELEMENT__\n}\n\nsub print_cache\n{\n  my $num = @_;\n\n  print <<__END_OF_CACHE_HDR__;\n# created by mk-doc-cache.pl\n# name: cache\n# type: cell\n# rows: 3\n# columns: $num\n__END_OF_CACHE_HDR__\n\n  foreach my $elt (@_)\n    {\n      my $symbol = $elt->[0];\n      my $doc = $elt->[1];\n      my $first_sentence = $elt->[2];\n\n      print_element ($symbol);\n      print_element ($doc);\n      print_element ($first_sentence);\n      print \"\\n\";\n    }\n}\n\n## FIXME: This is a very C/C++ way of coding things.\n## Perl convention would just be to have the executable code at end of file.\nsub main\n{\n  my $srcdir = shift;\n  my $macro_texi = shift;\n  my @docstrings = @_;\n  ## Everything else left in @_ are DOCSTRINGS files\n\n  die \"usage: mk_doc_cache SRCDIR MACRO-FILE DOCSTRINGS-FILE ...\"\n    if (@docstrings < 1);\n\n  my $texi_file = make_texinfo_file ($srcdir, $macro_texi, @docstrings);\n\n  my $info_text = get_info_text ($texi_file->filename);\n\n  my @cache_blocks = split_info ($info_text);\n\n  print_cache (@cache_blocks);\n}\n\nmain (@ARGV);\n"
  },
  {
    "path": "doc/interpreter/mk-qthelp.pl",
    "content": "#!/usr/bin/env perl\n\n################################################################################\n# File    : mk-qthelp.pl\n# Purpose : Transform Octave HTML documentation into intermediate formats\n#           for Qt Help Project (.qhp) and Qt Help Collection Project (.qhcp).\n# Usage   : mk-qthelp.pl input_htmldir output_filename\n################################################################################\nuse warnings;              # report warnings for questionable run-time code\nuse strict qw(refs subs);  # check at compile-time for bad programming style\nuse File::Basename;        # For splitting paths between dir and file\nuse File::Spec;            # For combining dirs and filenames into paths\n\n################################################################################\n# Extract command line arguments\nif ($#ARGV != 1)\n{ die \"USAGE: $0 input_htmldir output_filename\"; }\n\n$htmldir = basename ($ARGV[0]);\n$basedir = File::Spec->rel2abs (dirname ($ARGV[1]));\n$fname   = File::Spec->catfile ($basedir, basename ($ARGV[1]));\n\n################################################################################\n# Parse index.html to retrieve the table of contents\n$htmlfname = File::Spec->catfile ($basedir, $htmldir, \"index.html\");\nopen (my $HTML, \"<\", $htmlfname) or die \"Unable to open $htmlfname\";\n\n# Skip through preamble of file to find start of list\nwhile (defined ($_ = <$HTML>) and ! /^<div class=\"contents\">/ ) {;}\nwhile (defined ($_ = <$HTML>)\n         and ! /^<ul class=\"(?:no-bullet|toc-numbered-mark)\">/ ) {;}\n\ndie \"index.html: reached EOF without finding data start pattern\" if eof ($HTML);\n\n$level = 0;\nwhile (<$HTML>)\n{\n  if (/^\\s*<li>/)\n  {\n    ($href, $text) = m|href=\"([^\"]*)\"[^<>]*>(.*)</a>|;\n    # Sanitize text\n    $text =~ s/<[^>]*>//g;         # remove xml-looking blocks like <code>\n    $text =~ s/&rsquo;/&#8217;/g;  # Code for apostrophe\n\n    push (@toc, { \"href\" => $href, \"text\" => $text,\n                  \"level\" => $level, \"sectionstart\" => 0 });\n  }\n  elsif (/^\\s+<ul /)\n  {\n    $level++;\n    # Get last node and amend it to have a section start\n    %node = %{ $toc[-1] };\n    $node{sectionstart} = 1;\n    $toc[-1] = { %node };\n  }\n  elsif (m|^\\s+</ul>|)\n  {  $level--; }\n  elsif (m|^</ul>$|)\n  {  last;  }\n  else\n  {  die \"error:unrecognized input:$htmlfname:$.:$_\"; }\n}\n\nclose ($HTML);\n\ndie \"Failed to parse index.html\" if ($level != 0);\n\n################################################################################\n# Parse Function-Index.html to retrieve the function reference\n$htmlfname = File::Spec->catfile ($basedir, $htmldir, \"Function-Index.html\");\nopen ($HTML, \"<\", $htmlfname) or die \"Unable to open $htmlfname\";\n\n# Skip through preamble of file to find start of list\nwhile (defined ($_ = <$HTML>)\n         and ! /<table\\b[^>]*\\bclass=\"[^\"]*\\b\n                 (?:\n                   index-fn |\n                   fn-entries |\n                   fn-entries-printindex\n                 )\\b/x ) {;}\n\ndie \"Function-Index.html: reached EOF without finding data start pattern\"\n  if eof ($HTML);\n\nwhile (<$HTML>)\n{\n  if (m|<a href=\"([^\"]*)\"><code>(.*)</code>|)\n  {\n    $href = $1, $name = $2;\n    # Keep only the first link for each entry\n    if (! $kword{$name})\n    { $kword{$name} = $href; }\n  }\n  elsif (m|^</table>$|)\n  { last; }\n}\n\nclose ($HTML);\n\ndie \"Failed to parse Function-Index.html\" if (! m|^</table>$|);\n\n################################################################################\n# Prepare Qt Help Project document (.qhp file)\nopen (my $FH, \">\", \"$fname.qhp\") or die \"Unable to open $fname.qhcp\";\n\n$htmlfname = File::Spec->catfile ($htmldir, \"index.html\");\n\n# Add header to file\nprint $FH <<__EOT1__;\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--DO NOT EDIT!  Generated automatically by $0-->\n<QtHelpProject version=\"1.0\">\n  <namespace>org.octave.interpreter-1.0</namespace>\n  <virtualFolder>doc</virtualFolder>\n  <customFilter name=\"Octave Manual\">\n    <filterAttribute>core</filterAttribute>\n    <filterAttribute>manual</filterAttribute>\n  </customFilter>\n  <customFilter name=\"Octave C++ API\">\n    <filterAttribute>core</filterAttribute>\n    <filterAttribute>cpp</filterAttribute>\n  </customFilter>\n  <filterSection>\n    <filterAttribute>core</filterAttribute>\n    <filterAttribute>manual</filterAttribute>\n    <toc>\n      <section title=\"GNU Octave Manual\" ref=\"$htmlfname\">\n__EOT1__\n\n# Print out an XML block for each TOC section\n$level = 0;\n$indent = 4;\nforeach $hashref (@toc)\n{\n  %node = %{$hashref};\n  while ($node{level} < $level)\n  {\n    # Unindent and close section\n    $level--;\n    print $FH \"  \" x ($indent + $level);\n    print $FH \"</section>\\n\";\n  }\n  $level = $node{level};\n\n  print $FH \"  \" x ($indent + $node{level});\n  print $FH qq|<section title=\"$node{text}\" |;\n  print $FH qq|ref=\"|, File::Spec->catfile ($htmldir, $node{href});\n  print $FH ($node{sectionstart} ? qq|\">\\n| : qq|\"/>\\n|);\n}\n\n# Spacer between TOC and Keywords\nprint $FH <<__EOT2__;\n      </section>\n    </toc>\n    <keywords>\n__EOT2__\n\n# Print out sorted keywords\nforeach $kw (sort {lc($a) cmp lc($b)} (keys (%kword)))\n{\n  print $FH qq|      <keyword name=\"$kw\" id=\"$kw\" |;\n  print $FH qq|ref=\"|, File::Spec->catfile ($htmldir, $kword{$kw}), qq|\"/>\\n|;\n}\n\n# Footer of file\n$htmlfiles = File::Spec->catfile ($htmldir, \"*.html\");\n$pngfiles = File::Spec->catfile ($htmldir, \"*.png\");\n$cssfiles = File::Spec->catfile ($htmldir, \"*.css\");\nprint $FH <<__EOT3__;\n    </keywords>\n    <files>\n      <file>$htmlfiles</file>\n      <file>$pngfiles</file>\n      <file>$cssfiles</file>\n    </files>\n  </filterSection>\n</QtHelpProject>\n__EOT3__\n\nclose ($FH);\n\n################################################################################\n# Prepare Qt Help Collection Project document (.qhcp file)\nopen ($FH, \">\", \"$fname.qhcp\") or die \"Unable to open $fname.qhcp\";\n\n$qhpfile = basename ($fname) . \".qhp\";\n$qchfile = basename ($fname) . \".qch\";\n\n# This is the entire file\nprint $FH <<__EOT4__;\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--DO NOT EDIT! Generated automatically by $0-->\n<QHelpCollectionProject version=\"1.0\">\n  <docFiles>\n    <generate>\n      <file>\n        <input>$qhpfile</input>\n        <output>$qchfile</output>\n      </file>\n    </generate>\n    <register>\n      <file>$qchfile</file>\n    </register>\n  </docFiles>\n</QHelpCollectionProject>\n__EOT4__\n"
  },
  {
    "path": "doc/interpreter/mkcontrib.awk",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n{ x[NR] = $0; } END {\n  print \"@multitable @columnfractions .33 .33 .33\";\n  rem = NR % 3;\n  n = NR - rem;\n  for (i = 1; i <= n; i += 3)\n    printf (\"@item %s @tab %s @tab %s\\n\", x[i], x[i+1], x[i+2]);\n  if (rem == 1)\n    printf (\"@item %s\\n\", x[NR]);\n  else if (rem == 2)\n    printf (\"@item %s @tab %s\\n\", x[NR-1], x[NR]);\n  print \"@end multitable\";\n}\n"
  },
  {
    "path": "doc/interpreter/mkoctfile.1",
    "content": ".\\\" --------------------------------------------------------------------\n.\\\"\n.\\\" Copyright (C) 2000-2026 The Octave Project Developers\n.\\\"\n.\\\" See the file COPYRIGHT.md in the top-level directory of this\n.\\\" or <https://octave.org/copyright/>.\n.\\\"\n.\\\" This file is part of Octave.\n.\\\"\n.\\\" Octave is free software: you can redistribute it and/or modify it\n.\\\" under the terms of the GNU General Public License as published by\n.\\\" the Free Software Foundation, either version 3 of the License, or\n.\\\" (at your option) any later version.\n.\\\"\n.\\\" Octave is distributed in the hope that it will be useful, but\n.\\\" WITHOUT ANY WARRANTY; without even the implied warranty of\n.\\\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n.\\\" GNU General Public License for more details.\n.\\\"\n.\\\" You should have received a copy of the GNU General Public License\n.\\\" along with Octave; see the file COPYING.  If not, see\n.\\\" <https://www.gnu.org/licenses/>.\n.\\\"\n.\\\" --------------------------------------------------------------------\n.\\\"\n.de Vb \\\" (V)erbatim (b)egin.  Use fixed width font and no justification\n.ft CW\n.nf\n..\n.de Ve \\\" (V)erbatim (e)nd.  Return to regular font and justification\n.ft R\n.fi\n..\n.\\\" --------------------------------------------------------------------\n.TH MKOCTFILE 1 \"3 January 2014\" \"GNU Octave\"\n.SH NAME\nmkoctfile \\- Compile dynamic-load modules for GNU Octave\n.SH SYNOPSIS\n\\fBmkoctfile\\fP [\\fIOPTION\\fP]... file...\n.SH DESCRIPTION\n\\fBmkoctfile\\fP is used to compile C, C++, or Fortran source code in\nto a dynamically loadable \\fI.oct\\fP file for\n.BR octave (1).\n.SH OPTIONS\n.TP 8\n\\fB\\-h\\fP, \\fB\\-?\\fP, \\fB\\-\\-help\\fP\nPrint help message.\n.TP\n.B \\-I\\fIdir\\fP\nAdd include directory \\fIdir\\fP to compile commands.\n.TP\n.B \\-idirafter\\fIdir\\fP\nAdd include directory to second include search path after '\\fB\\-I\\fP'.\n.TP\n.B \\-D\\fIdef\\fP\nAdd definition \\fIdef\\fP to compiler command.\n.TP\n.B \\-l\\fIlib\\fP\nAdd library \\fIlib\\fP to link command.\n.TP\n.B \\-L\\fIdir\\fP\nAdd library directory \\fIdir\\fP to link command.\n.TP\n.B \\-R\\fIdir\\fP\nPass \\fB\\-R\\fP\\fIdir\\fP to link command.\n.TP\n.B \\-g\nEnable debugging option for all compilers.\n.TP\n.B \\-pthread\nAdd \\fB\\-pthread\\fP to link command.\n.TP\n.B \\-W...\nPass flags to the compiler such as \\fB\\-Wa,\\fP\\fIOPTION\\fP.\n.TP\n.B \\-Wl,...\nPass flags to the linker such as \\fB\\-Wl,\\-rpath=...\\fP\n.TP\n.B \\-M\\fR,\\fB \\-\\-depend\nGenerate dependency files (.d) for C and C++ source files.\n.TP\n.B \\-c\nCompile but do not link.\n.TP\n.B \\-\\-link\\-stand\\-alone\nLink a stand-alone executable file.\n.TP\n.B \\-s\\fR,\\fB \\-\\-strip\nStrip the output file.\n.TP\n.B \\-\\-mex\nCreate a MEX file.  Set the default output extension to \\fB.mex\\fP.\n.TP\n.B \\-o \\fIfile\\fP\\fR,\\fB \\-\\-output \\fIfile\\fP\nOutput filename.  Default extension is \\fB.oct\\fP (or \\fB.mex\\fP if \\-\\-mex is\nspecified) unless linking a stand-alone executable.\n.TP\n.B \\-p \\fIVAR\\fP\\fR,\\fB \\-\\-print \\fIVAR\\fP\nPrint configuration variable \\fIVAR\\fP.  There are three categories of\nvariables:\n.IP\nOctave configuration variables that users may override with environment\nvariables.  These are used in commands that mkoctfile executes.\n.RS\n.Vb\n    ALL_CFLAGS                  INCLUDEDIR\n    ALL_CXXFLAGS                LAPACK_LIBS\n    ALL_FFLAGS                  LDFLAGS\n    ALL_LDFLAGS                 LD_STATIC_FLAG\n    BLAS_LIBS                   LFLAGS\n    CC                          LIBDIR\n    CFLAGS                      LIBOCTAVE\n    CPICFLAG                    LIBOCTINTERP\n    CPPFLAGS                    OCTAVE_LINK_OPTS\n    CXX                         OCTINCLUDEDIR\n    CXXFLAGS                    OCTAVE_LIBS\n    CXXLD                       OCTAVE_LINK_DEPS\n    CXXPICFLAG                  OCTLIBDIR\n    DL_LDFLAGS                  OCT_LINK_DEPS\n    F77                         OCT_LINK_OPTS\n    F77_INTEGER8_FLAG           RDYNAMIC_FLAG\n    FFLAGS                      SPECIAL_MATH_LIB\n    FPICFLAG                    XTRA_CFLAGS\n    INCFLAGS                    XTRA_CXXFLAGS\n.Ve\n.RE\n.IP\nOctave configuration variables as above, but currently unused by mkoctfile.\n.RS\n.Vb\n    AR\n    DEPEND_EXTRA_SED_PATTERN\n    DEPEND_FLAGS\n    FFTW3F_LDFLAGS\n    FFTW3F_LIBS\n    FFTW3_LDFLAGS\n    FFTW3_LIBS\n    FFTW_LIBS\n    FLIBS\n    LIBS\n    RANLIB\n    READLINE_LIBS\n.Ve\n.RE\n.IP\nOctave configuration variables that are provided for informational purposes\nonly.  Except for OCTAVE_HOME and OCTAVE_EXEC_HOME, users may not override\nthese variables.\n.IP\nIf OCTAVE_HOME or OCTAVE_EXEC_HOME are set in the environment, then other\nvariables are adjusted accordingly with OCTAVE_HOME or OCTAVE_EXEC_HOME\nsubstituted for the original value of the directory specified by the\n\\-\\-prefix or \\-\\-exec\\-prefix options that were used when Octave was\nconfigured.\n.RS\n.Vb\n    API_VERSION                 LOCALARCHLIBDIR\n    ARCHLIBDIR                  LOCALFCNFILEDIR\n    BINDIR                      LOCALOCTFILEDIR\n    CANONICAL_HOST_TYPE         LOCALSTARTUPFILEDIR\n    DATADIR                     LOCALVERARCHLIBDIR\n    DATAROOTDIR                 LOCALVERFCNFILEDIR\n    DEFAULT_PAGER               LOCALVEROCTFILEDIR\n    EXEC_PREFIX                 MAN1DIR\n    EXEEXT                      MAN1EXT\n    FCNFILEDIR                  MANDIR\n    IMAGEDIR                    OCTAVE_EXEC_HOME\n    INCLUDEDIR                  OCTAVE_HOME\n    INFODIR                     OCTDATADIR\n    INFOFILE                    OCTDOCDIR\n    LIBDIR                      OCTFILEDIR\n    LIBEXECDIR                  OCTFONTSDIR\n    LOCALAPIARCHLIBDIR          OCTINCLUDEDIR\n    LOCALAPIFCNFILEDIR          OCTLIBDIR\n    LOCALAPIOCTFILEDIR          STARTUPFILEDIR\n    LOCALAPIPKGDIR              VERSION\n.Ve\n.RE\n.TP\n.B \\-v\\fR,\\fB \\-\\-verbose\nEcho commands as they are executed.\n.TP\n.B file\nCompile or link file.  Recognized file types are:\n.RS\n.Vb\n   .c    C source\n   .cc   C++ source\n   .cp   C++ source\n   .cpp  C++ source\n   .CPP  C++ source\n   .cxx  C++ source\n   .c++  C++ source\n   .C    C++ source\n   .f    Fortran source (fixed form)\n   .F    Fortran source (fixed form)\n   .f90  Fortran source (free form)\n   .F90  Fortran source (free form)\n   .o    object file\n   .a    library file\n.Ve\n.RE\n.SH AUTHOR\nJohn W. Eaton <jwe@octave.org>\n\nThis manual page was contributed by Dirk Eddelbuettel\n<edd@debian.org> for the Debian GNU/Linux distribution but\nmay be used by others.\n.SH \"SEE ALSO\"\noctave (1).\n"
  },
  {
    "path": "doc/interpreter/module.mk",
    "content": "if AMCOND_BUILD_DOCS\n\nGRAPH_PROP_TEXI_SRC = \\\n  %reldir%/plot-axesproperties.texi \\\n  %reldir%/plot-figureproperties.texi \\\n  %reldir%/plot-imageproperties.texi \\\n  %reldir%/plot-legendproperties.texi \\\n  %reldir%/plot-lightproperties.texi \\\n  %reldir%/plot-lineproperties.texi \\\n  %reldir%/plot-patchproperties.texi \\\n  %reldir%/plot-rootproperties.texi \\\n  %reldir%/plot-scatterproperties.texi \\\n  %reldir%/plot-surfaceproperties.texi \\\n  %reldir%/plot-textproperties.texi \\\n  %reldir%/plot-uimenuproperties.texi \\\n  %reldir%/plot-uibuttongroupproperties.texi \\\n  %reldir%/plot-uicontextmenuproperties.texi \\\n  %reldir%/plot-uipanelproperties.texi \\\n  %reldir%/plot-uicontrolproperties.texi \\\n  %reldir%/plot-uitableproperties.texi \\\n  %reldir%/plot-uitoolbarproperties.texi \\\n  %reldir%/plot-uipushtoolproperties.texi \\\n  %reldir%/plot-uitoggletoolproperties.texi\n\n$(GRAPH_PROP_TEXI_SRC): | $(OCTAVE_INTERPRETER_TARGETS)\n\ndefine gen-propdoc-texi\n  rm -f $@-t $@ && \\\n  $(SHELL) run-octave -disable-asan --norc --quiet --no-history --path $(srcdir)/doc/interpreter --eval \"genpropdoc ('$(1)');\" > $@-t && \\\n  mv $@-t $@\nendef\n\nGRAPHICS_PROPS_SRC = libinterp/corefcn/graphics.in.h libinterp/corefcn/genprops.awk\n\n%reldir%/plot-axesproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,axes)\n\n%reldir%/plot-figureproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,figure)\n\n%reldir%/plot-imageproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,image)\n\n%reldir%/plot-legendproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,legend)\n\n%reldir%/plot-lightproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,light)\n\n%reldir%/plot-lineproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,line)\n\n%reldir%/plot-patchproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,patch)\n\n%reldir%/plot-rootproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,root)\n\n%reldir%/plot-scatterproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,scatter)\n\n%reldir%/plot-surfaceproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,surface)\n\n%reldir%/plot-textproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,text)\n\n%reldir%/plot-uimenuproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,uimenu)\n\n%reldir%/plot-uibuttongroupproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,uibuttongroup)\n\n%reldir%/plot-uicontextmenuproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,uicontextmenu)\n\n%reldir%/plot-uipanelproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,uipanel)\n\n%reldir%/plot-uicontrolproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,uicontrol)\n\n%reldir%/plot-uitableproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,uitable)\n\n%reldir%/plot-uitoolbarproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,uitoolbar)\n\n%reldir%/plot-uipushtoolproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,uipushtool)\n\n%reldir%/plot-uitoggletoolproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)\n\t$(AM_V_GEN)$(call gen-propdoc-texi,uitoggletool)\n\ndist_man_MANS = \\\n  %reldir%/mkoctfile.1 \\\n  %reldir%/octave-cli.1 \\\n  %reldir%/octave-config.1 \\\n  %reldir%/octave.1\n\nBUILT_DOC_IMAGES += \\\n  $(BUILT_DOC_IMAGES_EPS) \\\n  $(BUILT_DOC_IMAGES_PDF) \\\n  $(BUILT_DOC_IMAGES_PNG) \\\n  $(BUILT_DOC_IMAGES_TXT)\n\nDOC_IMAGES_EPS += $(BUILT_DOC_IMAGES_EPS)\nDOC_IMAGES_PDF += $(BUILT_DOC_IMAGES_PDF)\nDOC_IMAGES_PNG += $(BUILT_DOC_IMAGES_PNG)\nDOC_IMAGES_TXT += $(BUILT_DOC_IMAGES_TXT)\n\nDOC_IMAGES += \\\n  $(BUILT_DOC_IMAGES)\n\n$(BUILT_DOC_IMAGES): | $(OCTAVE_INTERPRETER_TARGETS)\n\nHTMLDIR_IMAGES = $(patsubst %reldir%/%.png, %reldir%/octave.html/%.png, $(DOC_IMAGES_PNG))\n\nLOGOS = \\\n  %reldir%/octave-logo.eps \\\n  %reldir%/octave-logo.pdf\n\nDOC_IMAGES_EPS += %reldir%/octave-logo.eps\nDOC_IMAGES_PDF += %reldir%/octave-logo.pdf\n\nMUNGED_TEXI_SRC = \\\n  %reldir%/arith.texi \\\n  %reldir%/audio.texi \\\n  %reldir%/basics.texi \\\n  %reldir%/bugs.texi \\\n  %reldir%/container.texi \\\n  %reldir%/cp-idx.texi \\\n  %reldir%/data.texi \\\n  %reldir%/debug.texi \\\n  %reldir%/diffeq.texi \\\n  %reldir%/diagperm.texi \\\n  %reldir%/external.texi \\\n  %reldir%/errors.texi \\\n  %reldir%/eval.texi \\\n  %reldir%/expr.texi \\\n  %reldir%/fn-idx.texi \\\n  %reldir%/func.texi \\\n  %reldir%/geometry.texi \\\n  %reldir%/gui.texi \\\n  %reldir%/gpl.texi \\\n  %reldir%/grammar.texi \\\n  %reldir%/image.texi \\\n  %reldir%/install.texi \\\n  %reldir%/interp.texi \\\n  %reldir%/intro.texi \\\n  %reldir%/io.texi \\\n  %reldir%/linalg.texi \\\n  %reldir%/matrix.texi \\\n  %reldir%/nonlin.texi \\\n  %reldir%/numbers.texi \\\n  %reldir%/obsolete.texi \\\n  %reldir%/oop.texi \\\n  %reldir%/op-idx.texi \\\n  %reldir%/optim.texi \\\n  %reldir%/package.texi \\\n  %reldir%/plot.texi \\\n  %reldir%/poly.texi \\\n  %reldir%/preface.texi \\\n  %reldir%/pr-idx.texi \\\n  %reldir%/quad.texi \\\n  %reldir%/set.texi \\\n  %reldir%/signal.texi \\\n  %reldir%/sparse.texi \\\n  %reldir%/stats.texi \\\n  %reldir%/stmt.texi \\\n  %reldir%/strings.texi \\\n  %reldir%/system.texi \\\n  %reldir%/testfun.texi \\\n  %reldir%/var.texi \\\n  %reldir%/vectorize.texi\n\nTXI_SRC = $(MUNGED_TEXI_SRC:.texi=.txi)\n\nBUILT_OCTAVE_TEXI_SRC = \\\n  %reldir%/contributors.texi \\\n  $(GRAPH_PROP_TEXI_SRC) \\\n  $(MUNGED_TEXI_SRC)\n\ninfo_TEXINFOS += \\\n  %reldir%/octave.texi\n\noctave_TEXINFOS = \\\n  %reldir%/macros.texi \\\n  $(BUILT_OCTAVE_TEXI_SRC)\n\nINFO_DEPS += %reldir%/octave.info\nDVIS += %reldir%/octave.dvi\nPDFS += %reldir%/octave.pdf\nPSS += %reldir%/octave.ps\nHTMLS += %reldir%/octave.html\n\n## As of version 1.14.1, automake does not seem to generate\n## rules for DVI, PDF, or HTML output that work for us when\n## there are additional dependencies, so we include our own\n## versions of the rules here.\n\nOCTAVE_HTML_DIR = %reldir%/octave.html\nOCTAVE_HTML_TMP_DIR = $(OCTAVE_HTML_DIR:.html=.htp)\nOCTAVE_HTML_STAMP = $(OCTAVE_HTML_DIR)/.octave-html-stamp\n\nOCTAVE_CSS = %reldir%/octave.css\nHTMLDIR_CSS = $(OCTAVE_HTML_DIR)/octave.css\n\n%reldir%/octave.info: $(DOC_IMAGES_TXT) $(octave_TEXINFOS)\n%reldir%/octave.dvi: $(DOC_IMAGES_EPS) $(octave_TEXINFOS)\n%reldir%/octave.pdf: $(DOC_IMAGES_PDF) $(octave_TEXINFOS)\n$(OCTAVE_HTML_STAMP): $(DOC_IMAGES_PNG) $(octave_TEXINFOS)\n\nendif\n\n## Even if Octave was configured with --disable-docs, we will install\n## OCTAVE_QTHELP_FILES if they already exist.\n\n## Don't add these files to octdoc_DATA.  We want custom rules for\n## installing them.\nOCTAVE_QTHELP_FILES = \\\n  %reldir%/octave_interpreter.qhc \\\n  %reldir%/octave_interpreter.qch\n\ninstall-data-local: install-qthelp-files\n\nuninstall-local: uninstall-qthelp-files\n\n## Don't depend on $(OCTAVE_QTHELP_FILES) because we don't want to fail\n## if they can't be generated, but we want to install them if they exist\n## anyway (for example, they were included with a tarball distribution\n## file).\ninstall-qthelp-files: qthelp-installdir\n\t@for f in $(OCTAVE_QTHELP_FILES); do \\\n\t  if [ -f $$f ]; then \\\n\t    echo \" $(INSTALL_DATA) $$f '$(DESTDIR)$(octdocdir)'\"; \\\n\t    $(INSTALL_DATA) $$f '$(DESTDIR)$(octdocdir)'; \\\n\t  elif [ -f $(srcdir)/$$f ]; then \\\n\t    echo \" $(INSTALL_DATA) $(srcdir)/$$f '$(DESTDIR)$(octdocdir)'\"; \\\n\t    $(INSTALL_DATA) $(srcdir)/$$f '$(DESTDIR)$(octdocdir)'; \\\n\t  else \\\n\t    echo \"warning: unable to install $$f\"; \\\n\t  fi; \\\n\tdone\n.PHONY: install-qthelp-files\n\nuninstall-qthelp-files:\n\tfor f in $(OCTAVE_QTHELP_FILES); do \\\n\t  base=`echo $$f | $(SED) 's,^%reldir%/,,'`; \\\n\t  rm -f $(DESTDIR)$(octdocdir)/$$base; \\\n\tdone\n.PHONY: uninstall-qthelp-files\n\nqthelp-installdir:\n\t$(MKDIR_P) '$(DESTDIR)$(octdocdir)'\n.PHONY: qthelp-installdir\n\nif AMCOND_BUILD_DOCS\n\nif AMCOND_BUILD_QT_DOCS\n\n## The Qt help collection generator command produces two output files\n## with the same base name.  Use a pattern rule so that GNU Make will\n## only invoke the rule once to generate both files.\n\n%.qhc %.qch : $(OCTAVE_HTML_STAMP) $(HTMLDIR_CSS) %reldir%/mk-qthelp.pl\n\t$(AM_V_GEN)rm -f $(OCTAVE_QTHELP_FILES) && \\\n\trm -rf %reldir%/octave.qdoc.html && \\\n\tcp -r %reldir%/octave.html %reldir%/octave.qdoc.html && \\\n\t$(PERL) $(srcdir)/build-aux/inplace-edit.pl 's|<a[^>]+class=.copiable[^>]+> &para;</a>||g' %reldir%/octave.qdoc.html/* && \\\n\t$(PERL) $(srcdir)/%reldir%/mk-qthelp.pl octave.qdoc.html %reldir%/octave_interpreter && \\\n\t$(QCOLLECTIONGENERATOR) $(QCOLLECTIONGENERATORFLAGS) %reldir%/octave_interpreter.qhcp -o %reldir%/octave_interpreter.qhc >/dev/null && \\\n\trm -f %reldir%/octave_interpreter.qhcp %reldir%/octave_interpreter.qhp && \\\n\trm -rf %reldir%/octave.qdoc.html\n\nendif\n\n# Create a version file where EDITION variable only holds MAJOR number\n$(srcdir)/%reldir%/octave-doc-version.texi: $(srcdir)/%reldir%/version-octave.texi\n\t$(AM_V_GEN)rm -f $@-t $@ ; \\\n\t$(SED) 's#\\(@set EDITION [0-9]\\+\\)\\..*$$#\\1#' $(srcdir)/%reldir%/version-octave.texi > $@-t ; \\\n\tmv $@-t $@\n\n%reldir%/octave.info: %reldir%/octave.texi $(srcdir)/%reldir%/octave-doc-version.texi\n\t$(AM_V_MAKEINFO)restore=: && backupdir=\"$(am__leading_dot)am$$$$\" && \\\n\tam__cwd=`pwd` && $(am__cd) $(srcdir) && \\\n\trm -rf $$backupdir && mkdir $$backupdir && \\\n\tif ($(MAKEINFO) --version) >/dev/null 2>&1; then \\\n\t  for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \\\n\t    if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \\\n\t  done; \\\n\telse :; fi && \\\n\tcd \"$$am__cwd\"; \\\n\tif $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc/interpreter -I $(abs_top_srcdir)/doc/interpreter \\\n\t -o $@ $(srcdir)/%reldir%/octave.texi; \\\n\tthen \\\n\t  rc=0; \\\n\t  $(am__cd) $(srcdir); \\\n\telse \\\n\t  rc=$$?; \\\n\t  $(am__cd) $(srcdir) && \\\n\t  $$restore $$backupdir/* `echo \"./$@\" | sed 's|[^/]*$$||'`; \\\n\tfi; \\\n\trm -rf $$backupdir; exit $$rc\n\n%reldir%/octave.dvi: %reldir%/octave.texi $(srcdir)/%reldir%/octave-doc-version.texi | %reldir%/$(am__dirstamp)\n\t$(AM_V_TEXI2DVI)TEXINPUTS=\"$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS\" \\\n\tMAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc/interpreter -I $(srcdir)/doc/interpreter' \\\n\t$(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \\\n\t`test -f '%reldir%/octave.texi' || echo '$(abs_top_srcdir)/'`%reldir%/octave.texi\n\n%reldir%/octave.pdf: %reldir%/octave.texi $(srcdir)/%reldir%/octave-doc-version.texi | %reldir%/$(am__dirstamp)\n\t$(AM_V_TEXI2PDF)TEXINPUTS=\"$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS\" \\\n\tMAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc/interpreter -I $(abs_top_srcdir)/doc/interpreter' \\\n\t$(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \\\n\t`test -f '%reldir%/octave.texi' || echo '$(abs_top_srcdir)/'`%reldir%/octave.texi\n\n%reldir%/octave.html: $(OCTAVE_HTML_STAMP)\n\n$(OCTAVE_HTML_STAMP): %reldir%/octave.texi $(srcdir)/%reldir%/octave-doc-version.texi | %reldir%/$(am__dirstamp)\n\t$(AM_V_MAKEINFO)rm -rf $(OCTAVE_HTML_DIR)\n\t$(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) \\\n\t -I doc/interpreter -I $(abs_top_srcdir)/doc/interpreter \\\n\t --css-ref=octave.css \\\n\t -o $(OCTAVE_HTML_TMP_DIR) `test -f '%reldir%/octave.texi' || echo '$(abs_top_srcdir)/'`%reldir%/octave.texi; \\\n\tthen \\\n\t  $(PERL) $(srcdir)/build-aux/inplace-edit.pl 's|<span class=\"category[^\"]*\">: </span>||g' $(OCTAVE_HTML_TMP_DIR)/* && \\\n\t  rm -rf $(OCTAVE_HTML_DIR) && \\\n\t  mv $(OCTAVE_HTML_TMP_DIR) $(OCTAVE_HTML_DIR) && \\\n\t  touch $@; \\\n\telse \\\n\t  rm -rf $(OCTAVE_HTML_TMP_DIR); exit 1; \\\n\tfi\n\n$(HTMLDIR_IMAGES) $(HTMLDIR_CSS) : %reldir%/octave.html/%: %reldir%/% $(OCTAVE_HTML_STAMP)\n\t$(AM_V_GEN)cp $< $@\n\nDOC_TARGETS += \\\n  %reldir%/octave.info \\\n  %reldir%/doc-cache \\\n  %reldir%/octave.ps \\\n  %reldir%/octave.pdf \\\n  $(OCTAVE_HTML_STAMP) \\\n  $(HTMLDIR_IMAGES) \\\n  $(HTMLDIR_CSS)\n\nif AMCOND_BUILD_QT_DOCS\nDOC_TARGETS += \\\n  $(OCTAVE_QTHELP_FILES)\n\nendif\n\n## Distribute both OCTAVE_CSS and HTMLDIR_CSS so that the rules for\n## building HTMLDIR_CSS work properly.\n\ndoc_EXTRA_DIST += \\\n  $(BUILT_OCTAVE_TEXI_SRC) \\\n  %reldir%/octave.info \\\n  %reldir%/doc-cache \\\n  %reldir%/octave.dvi \\\n  %reldir%/octave.ps \\\n  %reldir%/octave.pdf \\\n  %reldir%/octave.html \\\n  $(HTMLDIR_IMAGES) \\\n  $(OCTAVE_CSS) \\\n  $(HTMLDIR_CSS) \\\n  $(OCTAVE_QTHELP_FILES)\n\n# Prevent packaging of distribution unless all libraries\n# necessary to create documentation are present\ndoc-interpreter-dist-hook:\n\t@$(GREP) '#define HAVE_COLAMD 1' $(top_builddir)/config.h > /dev/null || { echo \"Documentation creation requires missing COLAMD library.  Cannot package distribution!\" ; exit 1; }\n\t@$(GREP) '#define HAVE_CHOLMOD 1' $(top_builddir)/config.h > /dev/null || { echo \"Documentation creation requires missing CHOLMOD library.  Cannot package distribution!\" ; exit 1; }\n\t@$(GREP) '#define HAVE_UMFPACK 1' $(top_builddir)/config.h > /dev/null || { echo \"Documentation creation requires missing UMFPACK library.  Cannot package distribution!\" ; exit 1; }\n\t@$(GREP) '#define HAVE_QHULL 1' $(top_builddir)/config.h > /dev/null || { echo \"Documentation creation requires missing QHULL library.  Cannot package distribution!\" ; exit 1; }\n\n$(MUNGED_TEXI_SRC): $(DOCSTRING_FILES)\n\n## These two texi files have an additional dependency through the\n## @EXAMPLEFILE macro.\n%reldir%/oop.texi: $(examples_code_SRC)\n%reldir%/external.texi: $(examples_code_SRC)\n\n%.texi : %.txi %reldir%/munge-texi.pl | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(PERL) $(srcdir)/%reldir%/munge-texi.pl $(top_srcdir) $(DOCSTRING_FILES) < $< > $@-t && \\\n\tmv $@-t $@\n\n%reldir%/contributors.texi: %reldir%/contributors.in | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(AWK) -f $(srcdir)/%reldir%/mkcontrib.awk $(srcdir)/%reldir%/contributors.in > $@-t && \\\n\tmv $@-t $@\n\n%reldir%/preface.texi: %reldir%/contributors.texi\n\nAUTHORS: %reldir%/preface.texi %reldir%/contributors.texi | %reldir%/$(octave_dirstamp)\n\t$(AM_V_MAKEINFO)rm -f $@-t $@ && \\\n\tif [ \"x$(srcdir)\" != \"x.\" ] && [ -f $(srcdir)/%reldir%/contributors.texi ] && [ ! -f %reldir%/contributors.texi ]; then \\\n\t\tcp $(srcdir)/%reldir%/contributors.texi %reldir%/contributors.texi; \\\n\t\ttouch -r $(srcdir)/%reldir%/contributors.texi %reldir%/contributors.texi; \\\n\tfi && \\\n\t$(MAKEINFO) -D AUTHORSONLY -I $(srcdir)/%reldir%/ \\\n\t  --no-validate --no-headers --no-split --output $@-t $< && \\\n\tmv $@-t $@\n\nBUGS: %reldir%/bugs.texi | %reldir%/$(octave_dirstamp)\n\t$(AM_V_MAKEINFO)rm -f $@-t $@ && \\\n\t$(MAKEINFO) -D BUGSONLY -I $(srcdir)/doc/interpreter \\\n\t  --no-validate --no-headers --no-split --output $@-t $< && \\\n\tmv $@-t $@\n\nINSTALL.OCTAVE: %reldir%/install.texi %reldir%/macros.texi | %reldir%/$(octave_dirstamp)\n\t$(AM_V_MAKEINFO)rm -f $@-t $@ && \\\n\t$(MAKEINFO) -D INSTALLONLY -I $(srcdir)/doc/interpreter \\\n\t  --no-validate --no-headers --no-split --output $@-t $< && \\\n\tmv $@-t $@\n\ndoc_EXTRA_DIST += \\\n  %reldir%/config-images.sh \\\n  %reldir%/contributors.in \\\n  %reldir%/doc-cache \\\n  %reldir%/genpropdoc.m \\\n  %reldir%/graphics-properties.mk \\\n  %reldir%/images \\\n  %reldir%/images.awk \\\n  %reldir%/images.mk \\\n  %reldir%/macros.texi \\\n  %reldir%/mk-doc-cache.pl \\\n  %reldir%/mk-qthelp.pl \\\n  %reldir%/mkcontrib.awk \\\n  %reldir%/munge-texi.pl \\\n  %reldir%/octave-doc-version.texi \\\n  $(DOC_IMAGES) \\\n  $(DOC_IMAGES_SRC) \\\n  $(LOGOS) \\\n  $(TXI_SRC)\n\ndoc_MAINTAINERCLEANFILES += \\\n  AUTHORS \\\n  %reldir%/octave-doc-version.texi \\\n  $(BUILT_DOC_IMAGES) \\\n  $(BUILT_OCTAVE_TEXI_SRC) \\\n  $(OCTAVE_QTHELP_FILES)\n\n## The TeX software suite is used to create both PDF and PS output formats.\n## In order to avoid race conditions between simultaneous TeX commands, the\n## PDF and PS builds are forced to run serially through the following rule.\n%reldir%/octave.pdf: %reldir%/octave.ps\n\nendif\n\n## These actions should happen even if we are not building docs\n\ninclude doc/interpreter/images.mk\n\n$(srcdir)/%reldir%/images.mk: $(srcdir)/%reldir%/config-images.sh $(srcdir)/%reldir%/images.awk $(srcdir)/%reldir%/images\n\t$(AM_V_GEN)$(SHELL) $(srcdir)/%reldir%/config-images.sh $(top_srcdir)\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\n## The doc-cache file can be built without TeX but it does require\n## makeinfo, but that is needed to display function docstrings at the\n## Octave command line.  The macros.texi file must also be installed\n## to display docstrings at the command line.\n\ndoc_MAINTAINERCLEANFILES += \\\n  %reldir%/doc-cache\n\noctetc_DATA += \\\n  %reldir%/doc-cache \\\n  %reldir%/macros.texi\n\n%reldir%/doc-cache: $(DOCSTRING_FILES) %reldir%/mk-doc-cache.pl | $(OCTAVE_INTERPRETER_TARGETS) %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(PERL) $(srcdir)/%reldir%/mk-doc-cache.pl $(srcdir) $(srcdir)/%reldir%/macros.texi $(DOCSTRING_FILES) > $@-t && \\\n\tmv $@-t $@\n\n%reldir%/undocumented_list:\n\trm -f $@-t $@\n\t-cd $(srcdir)/%reldir%; $(PERL) ./doccheck/mk-undocumented-list.pl > $(@F)-t\n\tmv $@-t $@\n\t[ -s $@ ] || rm -f $@\n\t@cd $(srcdir)/%reldir% ; \\\n\tif ls undocumented_list >/dev/null 2>&1 ; then \\\n\t\techo \"Undocumented function check failed\"; \\\n\t\techo \"Review doc/interpreter/undocumented_list\"; \\\n\t\texit 1 ; \\\n\telse \\\n\t\techo \"Undocumented function check passed\"; \\\n\tfi\n\n.PHONY: %reldir%/undocumented_list\n\nSPELLCHECK_FILES = $(MUNGED_TEXI_SRC:.texi=.scheck)\n\n%.scheck: %.texi | %reldir%/$(octave_dirstamp)\n\tcd $(srcdir)/%reldir%; ./doccheck/spellcheck $(<F) > $(@F)-t\n\tmv $@-t $@\n\t[ -s $@ ] || rm -f $@\n\nspellcheck: $(SPELLCHECK_FILES)\n\t@cd $(srcdir)/%reldir% ; \\\n\tif ls *.scheck >/dev/null 2>&1 ; then \\\n\t\techo \"Spellcheck failed\"; \\\n\t\techo \"Review the following files:\"; \\\n\t\tls *.scheck ; \\\n\t\texit 1 ; \\\n\telse \\\n\t\techo \"Spellcheck passed\"; \\\n\tfi\n.PHONY: spellcheck\n\ndoc-interpreter-clean:\n\trm -rf %reldir%/octave.t2d\n\trm -rf %reldir%/octave.t2p\n\trm -rf %reldir%/octave.qdoc.html\n\n"
  },
  {
    "path": "doc/interpreter/munge-texi.pl",
    "content": "#!/usr/bin/perl -w\n\n########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# Validate program call\ndie \"usage: munge-texi TOP-SRCDIR DOCSTRING-FILE < file\" if (@ARGV < 2);\n\n$top_srcdir = shift (@ARGV);\n\n# Constant patterns\n$doc_delim = qr/^\\x{1d}/;\n$tex_delim = qr/\\Q-*- texinfo -*-\\E/;\n$comment_line = qr/^\\s*(?:$|#)/;\n# Pre-declare hash size for efficiency\nkeys(%help_text) = 1800;\n\n################################################################################\n# Load DOCSTRINGS into memory while expanding @seealso references\nforeach $DOCSTRING_file (@ARGV)\n{\n  ## DOCSTRINGS files may exist in the current (build) directory OR\n  ## in the source directory when building from a release.\n  $DOCSTRING_file_srcdir = \"$top_srcdir/$DOCSTRING_file\";\n\n  open (DOCFH, $DOCSTRING_file) or open (DOCFH, $DOCSTRING_file_srcdir)\n    or die \"Unable to open $DOCSTRING_file\\n\";\n\n  # Skip comments\n  while (defined ($_ = <DOCFH>) and /$comment_line/o) {;}\n\n  # Validate DOCSTRING file format\n  die \"invalid doc file format\\n\" if (! /$doc_delim/o);\n\n  do\n  {\n    s/\\s*$//;   # strip EOL character(s)\n    $symbol = substr ($_, 1);\n    $docstring = extract_docstring ();\n    if ($help_text{$symbol})\n    {\n      warn \"$DOCSTRING_file:$.:warning: ignoring duplicate entry for $symbol\\n\";\n    }\n    else\n    {\n      $help_text{$symbol} = $docstring;\n    }\n\n  } while (! eof);\n\n}\n\n################################################################################\n# Process .txi to .texi by expanding @DOCSTRING, @EXAMPLEFILE macros\n\n# Add warning header\nprint '@c DO NOT EDIT!  Generated automatically by munge-texi.pl.',\"\\n\\n\";\n\nTXI_LINE: while (<STDIN>)\n{\n  s'@seealso'@xseealso'g;\n\n  if (/^\\s*\\@DOCSTRING\\((\\S+)\\)/)\n  {\n    $func = $1;\n    $docstring = $help_text{$func};\n    if (! $docstring)\n    {\n      warn \"warning: no DOCSTRING entry for $func\\n\";\n      next TXI_LINE;\n    }\n\n    $func =~ s/^@/@@/;   # Texinfo uses @@ to produce '@'\n    $func =~ s/\\./_/g;   # Texinfo doesn't like '.' in node names\n    # Replace texinfo start tag by an anchor.  QtHelp requires a string\n    # directly following the anchor.  Adding a &nbsp; in html mode adds an\n    # additional vertical space which is compensated by span-tag with\n    # negativ top margin\n    $docstring =~ s/^$tex_delim$/\\@anchor{XREF$func}\\n\\@html\\n<span style=\\\"display:block; margin-top:-4.5ex;\\\">&nbsp;<\\/span>\\n\\@end html\\n\\n/m;\n    print $docstring,\"\\n\";\n\n    next TXI_LINE;\n  }\n  if (/^\\s*\\@EXAMPLEFILE\\((\\S+)\\)/)\n  {\n    $fname = \"$top_srcdir/examples/code/$1\";\n    print '@verbatim',\"\\n\";\n    open (EXAMPFH, $fname) or die \"unable to open example file $fname\\n\";\n    while (<EXAMPFH>)\n    {\n      print $_;\n      print \"\\n\" if (eof and substr ($_, -1) ne \"\\n\");\n    }\n    close (EXAMPFH);\n    print '@end verbatim',\"\\n\";\n\n    next TXI_LINE;\n  }\n\n  # pass ordinary lines straight through to output\n  print $_;\n}\n\n\n################################################################################\n# Subroutines\n################################################################################\nsub extract_docstring\n{\n  my ($docstring, $arg_list, $func_list, $repl, $rest_of_line);\n\n  while (defined ($_ = <DOCFH>) and ! /$doc_delim/o)\n  {\n    # expand any @seealso references\n    if (m'^@seealso\\{')\n    {\n      # join multiple lines until full macro body found\n      while (! /}/m) { $_ .= <DOCFH>; }\n\n      ($arg_list, $rest_of_line) = m'^@seealso\\{(.*)\\}(.*)?'s;\n\n      $func_list = $arg_list;\n      $func_list =~ s/\\s+//gs;\n      $repl = \"\";\n      foreach $func (split (/,/, $func_list))\n      {\n        $func =~ s/^@/@@/;     # Texinfo uses @@ to produce '@'\n        $node = $func;\n        $node =~ s/\\./_/g;     # Texinfo doesn't like '.' in node names\n        $repl .= \"\\@ref{XREF$node,,$func}, \";\n      }\n      substr($repl,-2) = \"\";   # Remove last ', '\n      # write out @xseealso because we have our own macro that conflicts\n      # with the one introduced in Texinfo 6.\n      $_ = \"\\@xseealso{$repl}$rest_of_line\";\n    }\n\n    $docstring .= $_;\n  }\n\n  return $docstring;\n}\n"
  },
  {
    "path": "doc/interpreter/nonlin.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Nonlinear Equations\n@chapter Nonlinear Equations\n@cindex nonlinear equations\n@cindex equations, nonlinear\n\n@menu\n* Solvers::\n* Minimizers::\n@end menu\n\n@node Solvers\n@section Solvers\n\nOctave can solve sets of nonlinear equations of the form\n@tex\n$$\n f (x) = 0\n$$\n@end tex\n@ifnottex\n\n@example\nF (x) = 0\n@end example\n\n@end ifnottex\n\n@noindent\nusing the function @code{fsolve}, which is based on the @sc{minpack}\nsubroutine @code{hybrd}.  This is an iterative technique so a starting\npoint must be provided.  This also has the consequence that\nconvergence is not guaranteed even if a solution exists.\n\n@DOCSTRING(fsolve)\n\nThe following is a complete example.  To solve the set of equations\n@tex\n$$\n \\eqalign{-2x^2 + 3xy + 4\\sin(y) - 6 &= 0\\cr\n           3x^2 - 2xy^2 + 3\\cos(x) + 4 &= 0}\n$$\n@end tex\n@ifnottex\n\n@example\n@group\n-2x^2 + 3xy   + 4 sin(y) = 6\n 3x^2 - 2xy^2 + 3 cos(x) = -4\n@end group\n@end example\n\n@end ifnottex\n\n@noindent\nyou first need to write a function to compute the value of the given\nfunction.  For example:\n\n@example\n@group\nfunction y = f (x)\n  y = zeros (2, 1);\n  y(1) = -2*x(1)^2 + 3*x(1)*x(2)   + 4*sin(x(2)) - 6;\n  y(2) =  3*x(1)^2 - 2*x(1)*x(2)^2 + 3*cos(x(1)) + 4;\nendfunction\n@end group\n@end example\n\nThen, call @code{fsolve} with a specified initial condition to find the\nroots of the system of equations.  For example, given the function\n@code{f} defined above,\n\n@example\n[x, fval, info] = fsolve (@@f, [1; 2])\n@end example\n\n@noindent\nresults in the solution\n\n@example\n@group\nx =\n\n  0.57983\n  2.54621\n\nfval =\n\n  -5.7184e-10\n   5.5460e-10\n\ninfo = 1\n@end group\n@end example\n\n@noindent\nA value of @code{info = 1} indicates that the solution has converged.\n\nWhen no Jacobian is supplied (as in the example above) it is approximated\nnumerically.  This requires more function evaluations, and hence is\nless efficient.  In the example above we could compute the Jacobian\nanalytically as\n\n@iftex\n@tex\n$$\n\\left[\\matrix{ {\\partial f_1 \\over \\partial x_1} &\n               {\\partial f_1 \\over \\partial x_2} \\cr\n               {\\partial f_2 \\over \\partial x_1} &\n               {\\partial f_2 \\over \\partial x_2} \\cr}\\right] =\n\\left[\\matrix{ 3 x_2 - 4 x_1                  &\n               4 \\cos(x_2) + 3 x_1            \\cr\n               -2 x_2^2 - 3 \\sin(x_1) + 6 x_1 &\n               -4 x_1 x_2                     \\cr }\\right]\n$$\n@end tex\nand compute it with the following Octave function\n@end iftex\n\n@example\n@group\nfunction [y, jac] = f (x)\n  y = zeros (2, 1);\n  y(1) = -2*x(1)^2 + 3*x(1)*x(2)   + 4*sin(x(2)) - 6;\n  y(2) =  3*x(1)^2 - 2*x(1)*x(2)^2 + 3*cos(x(1)) + 4;\n  if (nargout == 2)\n    jac = zeros (2, 2);\n    jac(1,1) =  3*x(2) - 4*x(1);\n    jac(1,2) =  4*cos(x(2)) + 3*x(1);\n    jac(2,1) = -2*x(2)^2 - 3*sin(x(1)) + 6*x(1);\n    jac(2,2) = -4*x(1)*x(2);\n  endif\nendfunction\n@end group\n@end example\n\n@noindent\nThe Jacobian can then be used with the following call to @code{fsolve}:\n\n@example\n[x, fval, info] = fsolve (@@f, [1; 2], optimset (\"jacobian\", \"on\"));\n@end example\n\n@noindent\nwhich gives the same solution as before.\n\n@DOCSTRING(fzero)\n\n@node Minimizers\n@section Minimizers\n@cindex local minimum\n@cindex finding minimums\n\nOften it is useful to find the minimum value of a function rather than just\nthe zeroes where it crosses the x-axis.  @code{fminbnd} is designed for the\nsimpler, but very common, case of a univariate function where the interval\nto search is bounded.  For unbounded minimization of a function with\npotentially many variables use @code{fminunc} or @code{fminsearch}.  The two\nfunctions use different internal algorithms and some knowledge of the objective\nfunction is required.  For functions which can be differentiated,\n@code{fminunc} is appropriate.  For functions with discontinuities, or for\nwhich a gradient search would fail, use @code{fminsearch}.\n@xref{Optimization} for minimization with the presence of constraint\nfunctions.  Note that searches can be made for maxima by simply inverting the\nobjective function\n@tex\n($F_{max} = -F_{min}$).\n@end tex\n@ifnottex\n(@code{Fto_max = -Fto_min}).\n@end ifnottex\n\n@DOCSTRING(fminbnd)\n\n@DOCSTRING(fminunc)\n\n@DOCSTRING(fminsearch)\n\nCertain minimization operations require additional parameters be passed to\nthe function, @code{F}, being minimized.  E.g., @w{@code{F = F(x, C)}}.\nOctave's minimizer functions are designed to only pass one optimization\nvariable to @code{F}, but parameter passing can be accomplished by defining\nan @ref{Anonymous Functions,,Anonymous Function} that contains the necessary\nparameter(s).  See the example below:\n\n@example\n@group\nA = 2; B = 3;\nf = @@(x) sin (A*x + B);\nfminbnd (f, 0, 2)\n   @xresult{}   0.8562\n@end group\n@end example\n\nNote that anonymous functions retain the value of parameters at the time they\nare defined.  Changing a parameter value after function definition will not\naffect output of the function until it is redefined:\n\n@example\n@group\nB = 4;\nfminbnd (f, 0, 2)\n   @xresult{}   0.8562\nf = @@(x) sin (A*x + B);\nfminbnd (f, 0, 2)\n   @xresult{}   0.3562\n@end group\n@end example\n\nThe function @code{humps} is a useful function for testing zero and\nextrema finding functions.\n\n@DOCSTRING(humps)\n"
  },
  {
    "path": "doc/interpreter/numbers.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Numeric Data Types\n@chapter Numeric Data Types\n@cindex numeric constant\n@cindex numeric value\n\nA @dfn{numeric constant} may be a scalar, a vector, or a matrix, and it may\ncontain complex values.\n\nThe simplest form of a numeric constant, a scalar, is a single number.  Note\nthat by default numbers are represented within Octave by IEEE@tie{}754 double\nprecision (binary64) floating-point format (complex constants are stored as\npairs of binary64 values).  It is, however, possible to represent true integers\nas described in @ref{Integer Data Types}.\n\nIf the numeric constant is a real integer, it can be defined in decimal,\nhexadecimal, or binary notation.  An important difference, however, is that\ndecimal constants will be stored as binary64 values while using hexadecimal or\nbinary notation will result in a true integer with a storage class just large\nenough to hold the specified number.  Hexadecimal notation starts with\n@samp{0x} or @samp{0X}, binary notation starts with @samp{0b} or @samp{0B},\notherwise decimal notation is assumed.  As a consequence, @samp{0b} is not a\nhexadecimal number, in fact, it is not a valid number at all.\n\nFor better readability, digits may be partitioned by the underscore separator\n@samp{_}, which is ignored by the Octave interpreter.  Here are some examples\nof real-valued integer constants, which all represent the same value:\n\n@example\n@group\n42            # decimal notation, binary64\n0x2A          # hexadecimal notation\n0b101010      # binary notation\n0b10_1010     # underscore notation\nround (42.1)  # also binary64\n@end group\n@end example\n\nIn decimal notation, the numeric constant may be denoted as decimal fraction\nor even in scientific (exponential) notation.  Note that this is not possible\nfor hexadecimal or binary notation.  Again, in the following example all\nnumeric constants represent the same value:\n\n@example\n@group\n.105\n1.05e-1\n.00105e+2\n@end group\n@end example\n\nUnlike most programming languages, complex numeric constants are denoted as\nthe sum of real and imaginary parts.  The imaginary part is denoted by a\nreal-valued numeric constant followed immediately by a complex value indicator\n(@samp{i}, @samp{j}, @samp{I}, or @samp{J} which represents\n@tex\n  $\\sqrt{-1}$).\n@end tex\n@ifnottex\n  @code{sqrt (-1)}).\n@end ifnottex\nNo spaces are allowed between the numeric constant and the complex value\nindicator.  All complex values are stored as pairs of binary64 values and the\nuse of hexadecimal or binary notation does @emph{not} result in a true integer.\nSome examples of complex numeric constants that all represent the same value:\n\n@example\n@group\n3 + 42i\n3 + 42j\n3 + 42I\n3 + 42J\n3.0 + 42.0i\n3.0 + 0x2Ai\n3.0 + 0b10_1010i\n0.3e1 + 420e-1i\n@end group\n@end example\n\n@DOCSTRING(double)\n\n@DOCSTRING(complex)\n\nOctave automatically \"narrows\" complex types to real types when the imaginary\npart is zero.  The interpreter performs this narrowing whenever it gets the\nopportunity, in order to save memory, and to emulate @sc{matlab} behavior.  For\nexample, if a variable initially has the complex value @code{4 + 2i} and\nsubsequently the value @code{2i} is subtracted from it, then it becomes the\nreal type @code{4} and not the complex type @code{4 + 0i}.  Testing whether the\nresultant type is complex using the expression @code{iscomplex (4+2i - 2i)}\nreturns false.\n\nTo ensure that a value is of complex type even with a zero imaginary part,\nuse @code{complex (4, 0)} instead of @code{4 + 0i}.  But even then, the\ninterpreter will still narrow the type to real at the next change done to it\n(such as adding 1 to it), unless its imaginary part truly becomes nonzero.\n\n@menu\n* Matrices::\n* Ranges::\n* Single Precision Data Types::\n* Integer Data Types::\n* Bit Manipulations::\n* Logical Values::\n* Automatic Conversion of Data Types::\n* Predicates for Numeric Objects::\n@end menu\n\n@node Matrices\n@section Matrices\n@cindex matrices\n\n@opindex [\n@opindex ]\n@opindex ;\n@opindex ,\n\nIt is easy to define a matrix of values in Octave.  The size of the\nmatrix is determined automatically, so it is not necessary to explicitly\nstate the dimensions.  The expression\n\n@example\na = [1, 2; 3, 4]\n@end example\n\n@noindent\nresults in the matrix\n@tex\n$$ a = \\left[ \\matrix{ 1 & 2 \\cr 3 & 4 } \\right] $$\n@end tex\n@ifnottex\n\n@example\n@group\n\n        /      \\\n        | 1  2 |\n  a  =  |      |\n        | 3  4 |\n        \\      /\n\n@end group\n@end example\n\n@end ifnottex\n\nElements of a matrix may be arbitrary expressions, provided that the\ndimensions all make sense when combining the various pieces.  For\nexample, given the above matrix, the expression\n\n@example\n[ a, a ]\n@end example\n\n@noindent\nproduces the matrix\n\n@example\n@group\nans =\n\n  1  2  1  2\n  3  4  3  4\n@end group\n@end example\n\n@noindent\nbut the expression\n\n@example\n[ a, 1 ]\n@end example\n\n@noindent\nproduces the error\n\n@example\nerror: number of rows must match (1 != 2) near line 13, column 6\n@end example\n\n@noindent\n(assuming that this expression was entered as the first thing on line\n13, of course).\n\nInside the square brackets that delimit a matrix expression, Octave\nlooks at the surrounding context to determine whether spaces and newline\ncharacters should be converted into element and row separators, or\nsimply ignored, so an expression like\n\n@example\n@group\na = [ 1 2\n      3 4 ]\n@end group\n@end example\n\n@noindent\nwill work.  However, some possible sources of confusion remain.  For\nexample, in the expression\n\n@example\n[ 1 - 1 ]\n@end example\n\n@noindent\nthe @samp{-} is treated as a binary operator and the result is the\nscalar 0, but in the expression\n\n@example\n[ 1 -1 ]\n@end example\n\n@noindent\nthe @samp{-} is treated as a unary operator and the result is the\nvector @code{[ 1, -1 ]}.  Similarly, the expression\n\n@example\n[ sin (pi) ]\n@end example\n\n@noindent\nwill be parsed as\n\n@example\n[ sin, (pi) ]\n@end example\n\n@noindent\nand will result in an error since the @code{sin} function will be\ncalled with no arguments.  To get around this, you must omit the space\nbetween @code{sin} and the opening parenthesis, or enclose the\nexpression in a set of parentheses:\n\n@example\n[ (sin (pi)) ]\n@end example\n\nWhitespace surrounding the single quote character (@samp{'}, used as a\ntranspose operator and for delimiting character strings) can also cause\nconfusion.  Given @code{a = 1}, the expression\n\n@example\n[ 1 a' ]\n@end example\n\n@noindent\nresults in the single quote character being treated as a\ntranspose operator and the result is the vector @code{[ 1, 1 ]}, but the\nexpression\n\n@example\n[ 1 a ' ]\n@end example\n\n@noindent\nproduces the error message\n\n@example\n@group\nparse error:\n\n  syntax error\n\n>>> [ 1 a ' ]\n              ^\n@end group\n@end example\n\n@noindent\nbecause not doing so would cause trouble when parsing the valid expression\n\n@example\n[ a 'foo' ]\n@end example\n\nFor clarity, it is probably best to always use commas and semicolons to\nseparate matrix elements and rows.\n\nThe maximum number of elements in a matrix is fixed when Octave is compiled.\nThe allowable number can be queried with the function @code{sizemax}.  Note\nthat other factors, such as the amount of memory available on your machine,\nmay limit the maximum size of matrices to something smaller.\n\n@DOCSTRING(sizemax)\n\nWhen you type a matrix or the name of a variable whose value is a\nmatrix, Octave responds by printing the matrix in with neatly aligned\nrows and columns.  If the rows of the matrix are too large to fit on the\nscreen, Octave splits the matrix and displays a header before each\nsection to indicate which columns are being displayed.  You can use the\nfollowing variables to control the format of the output.\n\n@DOCSTRING(output_precision)\n\nIt is possible to achieve a wide range of output styles by using\ndifferent values of @code{output_precision}.  Reasonable combinations can be\nset using the @code{format} function.  @xref{Basic Input and Output}.\n\n@DOCSTRING(split_long_rows)\n\nOctave automatically switches to scientific notation when values become\nvery large or very small.  This guarantees that you will see several\nsignificant figures for every value in a matrix.  If you would prefer to\nsee all values in a matrix printed in a fixed point format, you can use\nthe function @code{fixed_point_format}.  But doing so is not\nrecommended, because it can produce output that can easily be\nmisinterpreted.\n\n@DOCSTRING(fixed_point_format)\n\n@menu\n* Empty Matrices::\n@end menu\n\n@node Empty Matrices\n@subsection Empty Matrices\n\nA matrix may have one or both dimensions zero, and operations on empty\nmatrices are handled as described by @nospell{Carl de Boor} in\n@qcode{\"An Empty Exercise\"}, @cite{SIGNUM}, @w{Vol.@: 25}, @w{pp.@: 2}--6, 1990\nand @nospell{C. N. Nett and W. M. Haddad}, in @qcode{\"A System-Theoretic\nAppropriate Realization of the Empty Matrix Concept\"}, @cite{IEEE Transactions\non Automatic Control}, @w{Vol.@: 38}, @w{No.@: 5}, @w{May 1993}.\n@tex\nBriefly, given a scalar $s$, an $m\\times n$ matrix $M_{m\\times n}$,\nand an $m\\times n$ empty matrix $[\\,]_{m\\times n}$ (with either one or\nboth dimensions equal to zero), the following are true:\n$$\n\\eqalign{%\ns \\cdot [\\,]_{m\\times n} = [\\,]_{m\\times n} \\cdot s &= [\\,]_{m\\times n}\\cr\n[\\,]_{m\\times n} + [\\,]_{m\\times n} &= [\\,]_{m\\times n}\\cr\n[\\,]_{0\\times m} \\cdot M_{m\\times n} &= [\\,]_{0\\times n}\\cr\nM_{m\\times n} \\cdot [\\,]_{n\\times 0} &= [\\,]_{m\\times 0}\\cr\n[\\,]_{m\\times 0} \\cdot [\\,]_{0\\times n} &=  0_{m\\times n}}\n$$\n@end tex\n@ifnottex\nBriefly, given a scalar @var{s}, an @var{m} by\n@var{n} matrix @code{M(mxn)}, and an @var{m} by @var{n} empty matrix\n@code{[](mxn)} (with either one or both dimensions equal to zero), the\nfollowing are true:\n\n@example\n@group\ns * [](mxn) = [](mxn) * s = [](mxn)\n\n    [](mxn) + [](mxn) = [](mxn)\n\n    [](0xm) *  M(mxn) = [](0xn)\n\n     M(mxn) * [](nx0) = [](mx0)\n\n    [](mx0) * [](0xn) =  0(mxn)\n@end group\n@end example\n\n@end ifnottex\n\nBy default, dimensions of the empty matrix are printed along with the\nempty matrix symbol, @samp{[]}.  The built-in variable\n@code{print_empty_dimensions} controls this behavior.\n\n@DOCSTRING(print_empty_dimensions)\n\nEmpty matrices may also be used in assignment statements as a convenient\nway to delete rows or columns of matrices.\n@xref{Assignment Ops,,Assignment Expressions}.\n\nWhen Octave parses a matrix expression, it examines the elements of the\nlist to determine whether they are all constants.  If they are, it\nreplaces the list with a single matrix constant.\n\n@node Ranges\n@section Ranges\n@cindex range expressions\n@cindex expression, range\n\n@opindex :, range expressions\n\nA @dfn{range} is a convenient way to write a row vector with evenly\nspaced elements.  A range expression is defined by the value of the first\nelement in the range, an optional value for the increment between\nelements, and a maximum value which the elements of the range will not\nexceed.  The base, increment, and limit are separated by colons (the\n@samp{:} character) and may contain any arithmetic expressions and\nfunction calls.  If the increment is omitted, it is assumed to be 1.\nFor example, the range\n\n@example\n1 : 5\n@end example\n\n@noindent\ndefines the set of values @code{[ 1, 2, 3, 4, 5 ]}, and the range\n\n@example\n1 : 3 : 5\n@end example\n\n@noindent\ndefines the set of values @code{[ 1, 4 ]}.\n\nAlthough a range constant specifies a row vector, Octave does @emph{not}\nnormally convert range constants to vectors unless it is necessary to do so.\nThis allows you to write a constant like @code{1 : 10000} without using\n80,000 bytes of storage on a typical workstation.\n\nA common example of when it does become necessary to convert ranges into\nvectors occurs when they appear within a vector (i.e., inside square\nbrackets).  For instance, whereas\n\n@example\nx = 0 : 0.1 : 1;\n@end example\n\n@noindent\ndefines @var{x} to be a variable of type @code{double_range} and occupies 24\nbytes of memory, the expression\n\n@example\ny = [ 0 : 0.1 : 1];\n@end example\n\n@noindent\ndefines @var{y} to be of type @code{matrix} and occupies 88 bytes of\nmemory.\n\nThis space saving optimization may be disabled using the function\n@code{optimize_range}.\n\n@DOCSTRING(optimize_range)\n\nNote that the upper (or lower, if the increment is negative) bound on\nthe range is not always included in the set of values.  This can be useful\nin some contexts.  For example:\n\n@example\n@group\n## x is some predefined range or vector or matrix or array\nx(1:2:end) += 1;   # increment all  odd-numbered elements\nx(2:2:end) -= 1;   # decrement all even-numbered elements\n@end group\n@end example\n\nThe above code works correctly whether @var{x} has an odd number of elements\nor not: there is no need to treat the two cases differently.\n\nOctave uses floating point arithmetic to compute the values in the\nrange.  As a result, defining ranges with floating-point values can result\nin pitfalls like these:\n\n@example\n@group\na = -2\nb = (0.3 - 0.2 - 0.1)\nx = a : b\n@end group\n@end example\n\nDue to floating point rounding, @var{b} may or may not equal zero exactly,\nand if it does not, it may be above zero or below zero, hence the final range\n@var{x} may or may not include zero as its final value.  Similarly:\n\n@example\n@group\nx = 1.80 : 0.05 : 1.90\ny = 1.85 : 0.05 : 1.90\n@end group\n@end example\n\n@noindent\nis not as predictable as it looks.  As of Octave 8.3, the results obtained are\nthat @var{x} has three elements (1.80, 1.85, and 1.90), and @var{y} has only\none element (1.85 but not 1.90).  Thus, when using floating points in ranges,\nchanging the start of the range can easily affect the end of the range even\nthough the ending value was not touched in the above example.\n\nTo avoid such pitfalls with floating-points in ranges, you can use one of\nthe following patterns.  This change to the previous code:\n\n@example\n@group\nx = (0:2) * 0.05 + 1.80\ny = (0:1) * 0.05 + 1.85\n@end group\n@end example\n\n@noindent\nuse integers to construct the range and then converts to floating point making\nthe overall expression safe and repeatable across platforms, compilers, and\ncompiler settings.  If you know the number of elements, you can use the\n@code{linspace} function (@pxref{Special Utility Matrices}), which will include\nthe endpoints of a range.  You can also make judicious use of @code{round},\n@code{floor}, @code{ceil}, @code{fix}, etc.@: to set the limits and the\nincrement without getting interference from floating-point rounding.  For\nexample, the earlier example can be made safer with one of the following:\n\n@example\n@group\na = -2\nb = round ((0.3 - 0.2 - 0.1) * 1e12) / 1e12   # rounds to 12 digits\nc = floor (0.3 - 0.2 - 0.1)                   # floors as integer\nd = floor ((0.3 - 0.2 - 0.1) * 1e12) / 1e12   # floors at 12 digits\nx = a : b\ny = a : c\nz = a : d\n@end group\n@end example\n\nIf the result of the range expression is empty then Octave returns an empty\n@code{matrix}, not an empty @code{double_range}.  Similarly, if there is just\na single element in the range then Octave returns a @code{scalar}, not a\n@code{double_range} with one element.\n\n@node Single Precision Data Types\n@section Single Precision Data Types\n\nOctave includes support for single precision data types, and most of the\nfunctions in Octave accept single precision values and return single\nprecision answers.  A single precision variable is created with the\n@code{single} function.\n\n@DOCSTRING(single)\n\nfor example:\n\n@example\n@group\nsngl = single (rand (2, 2))\n     @xresult{} sngl =\n        0.37569   0.92982\n        0.11962   0.50876\nclass (sngl)\n    @xresult{} single\n@end group\n@end example\n\nMany functions can also return single precision values directly.  For\nexample\n\n@example\n@group\nones (2, 2, \"single\")\nzeros (2, 2, \"single\")\neye (2, 2,  \"single\")\nrand (2, 2, \"single\")\nNaN (2, 2, \"single\")\nNA (2, 2, \"single\")\nInf (2, 2, \"single\")\n@end group\n@end example\n\n@noindent\nwill all return single precision matrices.\n\n@node Integer Data Types\n@section Integer Data Types\n\nOctave supports integer matrices as an alternative to using double precision.\nIt is possible to use both signed and unsigned integers represented by 8, 16,\n32, or 64 bits.  It should be noted that most computations require floating\npoint data, meaning that integers will often change type when involved in\nnumeric computations.  For this reason integers are most often used to store\ndata, and not for calculations.\n\nIn general, most integer matrices are created by casting existing matrices to\nintegers.  The following example shows how to cast a matrix into 32-bit\nintegers.\n\n@example\n@group\nfloat = rand (2, 2)\n     @xresult{} float = 0.37569   0.92982\n                0.11962   0.50876\ninteger = int32 (float)\n     @xresult{} integer = 0  1\n                  0  1\n@end group\n@end example\n\n@noindent\nAs can be seen, floating point values are rounded to the nearest integer when\nconverted.\n\n@DOCSTRING(isinteger)\n\n@DOCSTRING(int8)\n\n@DOCSTRING(uint8)\n\n@DOCSTRING(int16)\n\n@DOCSTRING(uint16)\n\n@DOCSTRING(int32)\n\n@DOCSTRING(uint32)\n\n@DOCSTRING(int64)\n\n@DOCSTRING(uint64)\n\n@DOCSTRING(intmax)\n\n@DOCSTRING(intmin)\n\n@DOCSTRING(flintmax)\n\n@menu\n* Hexadecimal and Binary Integer Constants::\n* Integer Arithmetic::\n@end menu\n\n@node Hexadecimal and Binary Integer Constants\n@subsection Hexadecimal and Binary Integer Constants\n\nThe use of hexadecimal or binary notation to define a number will automatically\ncreate an unsigned integer using a representation that is just large enough to\nhold the specified value.  For example:\n\n@example\n@group\n0b101        # uint8\n0x100        # uint16\n0xDEADBEEF   # uint32\n0x1DEADBEEF  # uint64\n@end group\n@end example\n\nThe storage class can be specified by adding a suffix.  Use @samp{s} for signed\nintegers and @samp{u} for unsigned integers along with a size (@samp{8},\n@samp{16}, @samp{32}, @samp{64}).  The use of the underscore separator @samp{_}\ncan improve readability.  For example:\n\n@example\n@group\n0b101s16        # int16\n0b101_s16       # int16, value and representation separated\n0xDEADBEEFs32   # int32\n0xDEADBEEF_u64  # uint64\n@end group\n@end example\n\nNote that when defining matrices of integer constants the overall matrix will\nhave the storage class of its first element.  The matrix\n@code{[0x1; 0x100; 0x10000]} will be of type @code{uint8} and the larger values\nwill be truncated because of the saturation semantics of integer values.  To\navoid this issue either: 1) declare the first integer to be of the desired size\nsuch as @code{0x1u32; 0x100; 0x10000]}, or 2) pad constants in array\nexpressions with leading zeros so that they use the same number of digits for\neach value such as @code{[0x00_00_01; 0x00_01_00; 0x01_00_00]}.\n\n@node Integer Arithmetic\n@subsection Integer Arithmetic\n\nWhile many numerical computations can't be carried out in integers,\nOctave does support basic operations like addition and multiplication\non integers.  The operators @code{+}, @code{-}, @code{.*}, and @code{./}\nwork on integers of the same type.  So, it is possible to add two 32-bit\nintegers, but not to add a 32-bit integer and a 16-bit integer.\n\nWhen doing integer arithmetic one should consider the possibility of\nunderflow and overflow.  This happens when the result of the computation\ncan't be represented using the chosen integer type.  As an example it is\nnot possible to represent the result of @math{10 - 20} when using\nunsigned integers.  Octave makes sure that the result of integer\ncomputations is the integer that is closest to the true result.  So, the\nresult of @math{10 - 20} when using unsigned integers is zero.\n\nWhen doing integer division Octave will round the result to the nearest\ninteger.  This is different from most programming languages, where the\nresult is often floored to the nearest integer.  So, the result of\n@code{int32 (5) ./ int32 (8)} is @code{1}.\n\n@DOCSTRING(idivide)\n\n@node Bit Manipulations\n@section Bit Manipulations\n\nOctave provides a number of functions for the manipulation of numeric\nvalues on a bit by bit basis.  The basic functions to set and obtain the\nvalues of individual bits are @code{bitset} and @code{bitget}.\n\n@DOCSTRING(bitset)\n\n@DOCSTRING(bitget)\n\nThe arguments to all of Octave's bitwise operations can be scalar or\narrays, except for @code{bitcmp}, whose @var{k} argument must a\nscalar.  In the case where more than one argument is an array, then all\narguments must have the same shape, and the bitwise operator is applied\nto each of the elements of the argument individually.  If at least one\nargument is a scalar and one an array, then the scalar argument is\nduplicated.  Therefore\n\n@example\nbitget (100, 8:-1:1)\n@end example\n\n@noindent\nis the same as\n\n@example\nbitget (100 * ones (1, 8), 8:-1:1)\n@end example\n\nIt should be noted that all values passed to the bit manipulation\nfunctions of Octave are treated as integers.  Therefore, even though the\nexample for @code{bitset} above passes the floating point value\n@code{10}, it is treated as the bits @code{[1, 0, 1, 0]} rather than the\nbits of the native floating point format representation of @code{10}.\n\nAs the maximum value that can be represented by a number is important\nfor bit manipulation, particularly when forming masks, Octave supplies\ntwo utility functions: @code{flintmax} for floating point integers, and\n@code{intmax} for integer objects (@code{uint8}, @code{int64}, etc.).\n\nOctave also includes the basic bitwise 'and', 'or', and 'exclusive or'\noperators.\n\n@DOCSTRING(bitand)\n\n@DOCSTRING(bitor)\n\n@DOCSTRING(bitxor)\n\nThe bitwise 'not' operator is a unary operator that performs a logical\nnegation of each of the bits of the value.  For this to make sense, the\nmask against which the value is negated must be defined.  Octave's\nbitwise 'not' operator is @code{bitcmp}.\n\n@DOCSTRING(bitcmp)\n\nOctave also includes the ability to left-shift and right-shift values bitwise.\n\n@DOCSTRING(bitshift)\n\nBits that are shifted out of either end of the value are lost.  Octave\nalso uses arithmetic shifts, where the sign bit of the value is kept\nduring a right shift.  For example:\n\n@example\n@group\nbitshift (-10, -1)\n@xresult{} -5\nbitshift (int8 (-1), -1)\n@xresult{} -1\n@end group\n@end example\n\nNote that @code{bitshift (int8 (-1), -1)} is @code{-1} since the bit\nrepresentation of @code{-1} in the @code{int8} data type is @code{[1, 1,\n1, 1, 1, 1, 1, 1]}.\n\n@node Logical Values\n@section Logical Values\n\nOctave has built-in support for logical values, i.e., variables that\nare either @code{true} or @code{false}.  When comparing two variables,\nthe result will be a logical value whose value depends on whether or\nnot the comparison is true.\n\nThe basic logical operations are @code{&}, @code{|}, and @code{!},\nwhich correspond to ``Logical And'', ``Logical Or'', and ``Logical\nNegation''.  These operations all follow the usual rules of logic.\n\nIt is also possible to use logical values as part of standard numerical\ncalculations.  In this case @code{true} is converted to @code{1}, and\n@code{false} to 0, both represented using double precision floating\npoint numbers.  So, the result of @code{true*22 - false/6} is @code{22}.\n\nLogical values can also be used to index matrices and cell arrays.\nWhen indexing with a logical array the result will be a vector containing\nthe values corresponding to @code{true} parts of the logical array.\n@xref{XREFLogicalIndexing,,Logical Indexing}.\n\nLogical values can also be constructed by\ncasting numeric objects to logical values, or by using the @code{true}\nor @code{false} functions.\n\n@DOCSTRING(logical)\n\n@DOCSTRING(true)\n\n@DOCSTRING(false)\n\n@node Automatic Conversion of Data Types\n@section Automatic Conversion of Data Types\n\nMany operators and functions can work with mixed data types.  For example,\n\n@example\n@group\nuint8 (1) + 1\n    @xresult{} 2\n@end group\n\n@group\nsingle (1) + 1\n    @xresult{} 2\n@end group\n\n@group\nmin (single (1), 0)\n   @xresult{} 0\n@end group\n@end example\n\n@noindent\nwhere the results are respectively of types uint8, single, and single\nrespectively.  This is done for @sc{matlab} compatibility.  Valid mixed\noperations are defined as follows:\n\n@multitable @columnfractions .2 .3 .3 .2\n@headitem @tab Mixed Operation @tab Result @tab\n@item @tab double OP single @tab single @tab\n@item @tab double OP integer @tab integer @tab\n@item @tab double OP char @tab double @tab\n@item @tab double OP logical @tab double @tab\n@item @tab single OP integer @tab integer @tab\n@item @tab single OP char @tab single @tab\n@item @tab single OP logical @tab single @tab\n@end multitable\n\nWhen functions expect a double but are passed other types, automatic\nconversion is function-dependent:\n\n@example\n@group\na = det (int8 ([1 2; 3 4]))\n    @xresult{} a = -2\nclass (a)\n    @xresult{} double\n@end group\n\n@group\na = eig (int8 ([1 2; 3 4]))\n    @xresult{} error: eig: wrong type argument 'int8 matrix'\n@end group\n@end example\n\nWhen two operands are both integers but of different widths, then some cases\nconvert them to the wider bitwidth, and other cases throw an error:\n\n@example\n@group\na = min (int8 (100), int16 (200))\n    @xresult{} 100\nclass (a)\n    @xresult{} int16\n@end group\n\n@group\nint8 (100) + int16 (200)\n   @xresult{} error: binary operator '+' not implemented\n   for 'int8 scalar' by 'int16 scalar' operations\n@end group\n@end example\n\nFor two integer operands, they typically need to both be signed or both be\nunsigned.  Mixing signed and unsigned usually causes an error, even if they\nare of the same bitwidth.\n\n@example\n@group\nmin (int16 (100), uint16 (200))\n   @xresult{} error: min: cannot compute min (int16 scalar, uint16 scalar)\n@end group\n@end example\n\nIn the case of mixed type indexed assignments, the type is not\nchanged.  For example,\n\n@example\n@group\nx = ones (2, 2);\nx(1, 1) = single (2)\n   @xresult{} x = 2   1\n          1   1\n@end group\n@end example\n\n@noindent\nwhere @code{x} remains of the double precision type.\n\n@node Predicates for Numeric Objects\n@section Predicates for Numeric Objects\n\nSince the type of a variable may change during the execution of a\nprogram, it can be necessary to do type checking at run-time.  Doing this\nalso allows you to change the behavior of a function depending on the\ntype of the input.  As an example, this naive implementation of @code{abs}\nreturns the absolute value of the input if it is a real number, and the\nlength of the input if it is a complex number.\n\n@example\n@group\nfunction a = abs (x)\n  if (isreal (x))\n    a = sign (x) .* x;\n  elseif (iscomplex (x))\n    a = sqrt (real(x).^2 + imag(x).^2);\n  endif\nendfunction\n@end group\n@end example\n\nThe following functions are available for determining the type of a\nvariable.\n\n@DOCSTRING(isnumeric)\n\n@DOCSTRING(islogical)\n\n@DOCSTRING(isfloat)\n\n@DOCSTRING(isreal)\n\n@DOCSTRING(iscomplex)\n\n@DOCSTRING(ismatrix)\n\n@DOCSTRING(isvector)\n\n@DOCSTRING(isrow)\n\n@DOCSTRING(iscolumn)\n\n@DOCSTRING(isscalar)\n\n@DOCSTRING(issquare)\n\n@DOCSTRING(issymmetric)\n\n@DOCSTRING(ishermitian)\n\n@DOCSTRING(isdefinite)\n\n@DOCSTRING(isbanded)\n\n@DOCSTRING(isdiag)\n\n@DOCSTRING(istril)\n\n@DOCSTRING(istriu)\n\n@DOCSTRING(isprime)\n\n@DOCSTRING(isuniform)\n\nIf instead of knowing properties of variables, you wish to know which\nvariables are defined and to gather other information about the\nworkspace itself, @pxref{Status of Variables}.\n"
  },
  {
    "path": "doc/interpreter/obsolete.txi",
    "content": "@c Copyright (C) 2010-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@c The text of this file appears in the file BUGS in the Octave\n@c distribution, as well as in the Octave manual.\n\n@node Obsolete Functions\n@appendix Obsolete Functions\n\n@cindex obsolete functions\n@cindex deprecated functions\n@cindex functions, obsolete\n@cindex functions, deprecated\n\nAfter being marked as deprecated for two major releases, the following\nfunctions have been removed from Octave.  The third column of the table\nshows the version of Octave in which the function was removed.  Prior to\nremoval, each function in the list was marked as deprecated for at least\ntwo major releases.  All deprecated functions issue warnings explaining\nthat they will be removed in a future version of Octave, and which\nfunction should be used instead.\n\nReplacement functions do not always accept precisely the same arguments\nas the obsolete function, but should provide equivalent functionality.\n\n@multitable @columnfractions .3 .3 .15\n@headitem Obsolete Function @tab Replacement @tab Version\n@item @code{beta_cdf} @tab @code{betacdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{beta_inv} @tab @code{betainv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{beta_pdf} @tab @code{betapdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{beta_rnd} @tab @code{betarnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{binomial_cdf} @tab @code{binocdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{binomial_inv} @tab @code{binoinv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{binomial_pdf} @tab @code{binopdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{binomial_rnd} @tab @code{binornd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{chisquare_cdf} @tab @code{chi2cdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{chisquare_inv} @tab @code{chi2inv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{chisquare_pdf} @tab @code{chi2pdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{chisquare_rnd} @tab @code{chi2rnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{clearplot} @tab @code{clf} @tab 3.4.0\n@item @code{com2str} @tab @code{num2str} @tab 3.4.0\n@item @code{exponential_cdf} @tab @code{expcdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{exponential_inv} @tab @code{expinv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{exponential_pdf} @tab @code{exppdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{exponential_rnd} @tab @code{exprnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{f_cdf} @tab @code{fcdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{f_inv} @tab @code{finv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{f_pdf} @tab @code{fpdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{f_rnd} @tab @code{frnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{gamma_cdf} @tab @code{gamcdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{gamma_inv} @tab @code{gaminv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{gamma_pdf} @tab @code{gampdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{gamma_rnd} @tab @code{gamrnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{geometric_cdf} @tab @code{geocdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{geometric_inv} @tab @code{geoinv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{geometric_pdf} @tab @code{geopdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{geometric_rnd} @tab @code{geornd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{hypergeometric_cdf} @tab @code{hygecdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{hypergeometric_inv} @tab @code{hygeinv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{hypergeometric_pdf} @tab @code{hygepdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{hypergeometric_rnd} @tab @code{hygernd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{intersection} @tab @code{intersect} @tab 3.4.0\n@item @code{is_bool} @tab @code{isbool} @tab 3.4.0\n@item @code{is_complex} @tab @code{iscomplex} @tab 3.4.0\n@item @code{is_list} @tab None @tab 3.4.0\n@item @code{is_matrix} @tab @code{ismatrix} @tab 3.4.0\n@item @code{is_scalar} @tab @code{isscalar} @tab 3.4.0\n@item @code{is_square} @tab @code{issquare} @tab 3.4.0\n@item @code{is_stream} @tab None @tab 3.4.0\n@item @code{is_struct} @tab @code{isstruct} @tab 3.4.0\n@item @code{is_symmetric} @tab @code{issymmetric} @tab 3.4.0\n@item @code{is_vector} @tab @code{isvector} @tab 3.4.0\n@item @code{lognormal_cdf} @tab @code{logncdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{lognormal_inv} @tab @code{logninv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{lognormal_pdf} @tab @code{lognpdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{lognormal_rnd} @tab @code{lognrnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{meshdom} @tab @code{meshgrid} @tab 3.4.0\n@item @code{normal_cdf} @tab @code{normcdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{normal_inv} @tab @code{norminv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{normal_pdf} @tab @code{normpdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{normal_rnd} @tab @code{normrnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{pascal_cdf} @tab @code{nbincdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{pascal_inv} @tab @code{nbininv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{pascal_pdf} @tab @code{nbinpdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{pascal_rnd} @tab @code{nbinrnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{poisson_cdf} @tab @code{poisscdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{poisson_inv} @tab @code{poissinv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{poisson_pdf} @tab @code{poisspdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{poisson_rnd} @tab @code{poissrnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{polyinteg} @tab @code{polyint} @tab 3.4.0\n@item @code{struct_contains} @tab @code{isfield} @tab 3.4.0\n@item @code{struct_elements} @tab @code{fieldnames} @tab 3.4.0\n@item @code{t_cdf} @tab @code{tcdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{t_inv} @tab @code{tinv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{t_pdf} @tab @code{tpdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{t_rnd} @tab @code{trnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{uniform_cdf} @tab @code{unifcdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{uniform_inv} @tab @code{unifinv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{uniform_pdf} @tab @code{unifpdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{uniform_rnd} @tab @code{unifrnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{weibull_cdf} @tab @code{wblcdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{weibull_inv} @tab @code{wblinv} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{weibull_pdf} @tab @code{wblpdf} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{weibull_rnd} @tab @code{wblrnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{wiener_rnd} @tab @code{wienrnd} in Octave Forge statistics pkg @tab 3.4.0\n@item @code{create_set} @tab @code{unique} @tab 3.6.0\n@item @code{dmult} @tab @code{diag (A) * B} @tab 3.6.0\n@item @code{iscommand} @tab None @tab 3.6.0\n@item @code{israwcommand} @tab None @tab 3.6.0\n@item @code{lchol} @tab @code{chol (@dots{}, \"lower\")} @tab 3.6.0\n@item @code{loadimage} @tab @code{load} or @code{imread} @tab 3.6.0\n@item @code{mark_as_command} @tab None @tab 3.6.0\n@item @code{mark_as_rawcommand} @tab None @tab 3.6.0\n@item @code{spatan2} @tab @code{atan2} @tab 3.6.0\n@item @code{spchol} @tab @code{chol} @tab 3.6.0\n@item @code{spchol2inv} @tab @code{chol2inv} @tab 3.6.0\n@item @code{spcholinv} @tab @code{cholinv} @tab 3.6.0\n@item @code{spcumprod} @tab @code{cumprod} @tab 3.6.0\n@item @code{spcumsum} @tab @code{cumsum} @tab 3.6.0\n@item @code{spdet} @tab @code{det} @tab 3.6.0\n@item @code{spdiag} @tab @code{sparse (diag (@dots{}))} @tab 3.6.0\n@item @code{spfind} @tab @code{find} @tab 3.6.0\n@item @code{sphcat} @tab @code{horzcat} @tab 3.6.0\n@item @code{spinv} @tab @code{inv} @tab 3.6.0\n@item @code{spkron} @tab @code{kron} @tab 3.6.0\n@item @code{splchol} @tab @code{chol (@dots{}, \"lower\")} @tab 3.6.0\n@item @code{split} @tab @code{char (strsplit (s, t))} @tab 3.6.0\n@item @code{splu} @tab @code{lu} @tab 3.6.0\n@item @code{spmax} @tab @code{max} @tab 3.6.0\n@item @code{spmin} @tab @code{min} @tab 3.6.0\n@item @code{spprod} @tab @code{prod} @tab 3.6.0\n@item @code{spqr} @tab @code{qr} @tab 3.6.0\n@item @code{spsum} @tab @code{sum} @tab 3.6.0\n@item @code{spsumsq} @tab @code{sumsq} @tab 3.6.0\n@item @code{spvcat} @tab @code{vertcat} @tab 3.6.0\n@item @code{str2mat} @tab @code{char} @tab 3.6.0\n@item @code{unmark_command} @tab None @tab 3.6.0\n@item @code{unmark_rawcommand} @tab None @tab 3.6.0\n@item @code{autocor} @tab @code{xcorr} in Octave Forge signal pkg @tab 3.8.0\n@item @code{autocov} @tab @code{xcov} in Octave Forge signal pkg @tab 3.8.0\n@item @code{betai} @tab @code{betainc} @tab 3.8.0\n@item @code{cellidx} @tab @code{ismember} @tab 3.8.0\n@item @code{cquad} @tab @code{quadcc} @tab 3.8.0\n@item @code{dispatch} @tab None @tab 3.8.0\n@item @code{fstat} @tab @code{stat} @tab 3.8.0\n@item @code{gammai} @tab @code{gammainc} @tab 3.8.0\n@item @code{glpkmex} @tab @code{glpk} @tab 3.8.0\n@item @code{is_duplicate_entry} @tab @code{unique} @tab 3.8.0\n@item @code{is_global} @tab @code{isglobal} @tab 3.8.0\n@item @code{krylovb} @tab @code{[Uret, ~, Ucols] = krylov (@dots{})} @tab 3.8.0\n@item @code{perror} @tab None @tab 3.8.0\n@item @code{replot} @tab @code{refresh} @tab 3.8.0\n@item @code{saveimage} @tab @code{imwrite} @tab 3.8.0\n@item @code{setstr} @tab @code{char} @tab 3.8.0\n@item @code{strerror} @tab None @tab 3.8.0\n@item @code{values} @tab @code{unique} @tab 3.8.0\n@item @code{cut} @tab @code{histc} @tab 4.0.0\n@item @code{cor} @tab @code{corr} @tab 4.0.0\n@item @code{corrcoef} @tab @code{corr} @tab 4.0.0\n@item @code{__error_text__} @tab @code{lasterr} @tab 4.0.0\n@item @code{error_text} @tab @code{lasterr} @tab 4.0.0\n@item @code{polyderiv} @tab @code{polyder} @tab 4.0.0\n@item @code{shell_cmd} @tab @code{system} @tab 4.0.0\n@item @code{studentize} @tab @code{zscore} @tab 4.0.0\n@item @code{sylvester_matrix} @tab @code{hadamard (2^k)} @tab 4.0.0\n@item @code{default_save_options} @tab @code{save_default_options} @tab 4.2.0\n@item @code{gen_doc_cache} @tab @code{doc_cache_create} @tab 4.2.0\n@item @code{interp1q} @tab @code{interp1} @tab 4.2.0\n@item @code{isequalwithequalnans} @tab @code{isequaln} @tab 4.2.0\n@item @code{java_convert_matrix} @tab @code{java_matrix_autoconversion} @tab 4.2.0\n@item @code{java_debug} @tab @code{debug_java} @tab 4.2.0\n@item @code{java_invoke} @tab @code{javaMethod} @tab 4.2.0\n@item @code{java_new} @tab @code{javaObject} @tab 4.2.0\n@item @code{java_unsigned_conversion} @tab @code{java_unsigned_autoconversion} @tab 4.2.0\n@item @code{javafields} @tab @code{fieldnames} @tab 4.2.0\n@item @code{javamethods} @tab @code{methods} @tab 4.2.0\n@item @code{re_read_readline_init_file} @tab @code{readline_re_read_init_file} @tab 4.2.0\n@item @code{read_readline_init_file} @tab @code{readline_read_init_file} @tab 4.2.0\n@item @code{saving_history} @tab @code{history_save} @tab 4.2.0\n@item @code{allow_noninteger_range_as_index} @tab None @tab 4.4.0\n@item @code{bicubic} @tab @code{interp2} @tab 4.4.0\n@item @code{delaunay3} @tab @code{delaunay} @tab 4.4.0\n@item @code{do_braindead_shortcircuit_evaluation} @tab None @tab 4.4.0\n@item @code{dump_prefs} @tab @code{} None 4.4.0\n@item @code{find_dir_in_path} @tab @code{dir_in_loadpath} @tab 4.4.0\n@item @code{finite} @tab @code{isfinite} @tab 4.4.0\n@item @code{fmod} @tab @code{rem} @tab 4.4.0\n@item @code{fnmatch} @tab @code{glob} or @code{regexp} @tab 4.4.0\n@item @code{gmap40} @tab None @tab 4.4.0\n@item @code{loadaudio} @tab @code{audioread} @tab 4.4.0\n@item @code{luinc} @tab @code{ichol} or @code{ilu} @tab 4.4.0\n@item @code{mouse_wheel_zoom} @tab @code{mousehweelzoom} property @tab 4.4.0\n@item @code{nfields} @tab @code{numfields} @tab 4.4.0\n@item @code{octave_tmp_file_name} @tab @code{tempname} @tab 4.4.0\n@item @code{playaudio} @tab @code{audioplayer} @tab 4.4.0\n@item @code{saveaudio} @tab @code{audiowrite} @tab 4.4.0\n@item @code{setaudio} @tab None @tab 4.4.0\n@item @code{syl} @tab @code{sylvester} @tab 4.4.0\n@item @code{usage} @tab @code{print_usage} @tab 4.4.0\n@item @code{bitmax} @tab @code{flintmax} @tab 5.1.0\n@item @code{mahalanobis} @tab @code{mahal} in Octave Forge statistics pkg @tab 5.1.0\n@item @code{md5sum} @tab @code{hash} @tab 5.1.0\n@item @code{octave_config_info} @tab @code{__octave_config_info__} @tab 5.1.0\n@item @code{onenormest} @tab @code{normest1} @tab 5.1.0\n@item @code{sleep} @tab @code{pause} @tab 5.1.0\n@item @code{usleep} @tab @code{pause} @tab 5.1.0\n@item @code{wavread} @tab @code{audioread} @tab 5.1.0\n@item @code{wavwrite} @tab @code{audiowrite} @tab 5.1.0\n@item @code{output_max_field_width} @tab @code{output_precision} @tab 7.1.0\n@item @code{is_keyword} @tab @code{iskeyword} @tab 7.1.0\n@item @code{runtests} @tab @code{oruntests} @tab 8.1.0\n@item @code{disable_diagonal_matrix} @tab @code{optimize_diagonal_matrix} @tab 9.1.0\n@item @code{disable_permutation_matrix} @tab @code{optimize_permutation_matrix} @tab 9.1.0\n@item @code{disable_range} @tab @code{optimize_range} @tab 9.1.0\n@item @code{shift} @tab @code{circshift} @tab 10.1.0\n@item @code{sparse_auto_mutate} @tab None @tab 10.1.0\n@end multitable\n"
  },
  {
    "path": "doc/interpreter/octave-cli.1",
    "content": ".\\\" ---------------------------------------------------------------------\n.\\\"\n.\\\" Copyright (C) 1996-2026 The Octave Project Developers\n.\\\"\n.\\\" See the file COPYRIGHT.md in the top-level directory of this\n.\\\" or <https://octave.org/copyright/>.\n.\\\"\n.\\\" This file is part of Octave.\n.\\\"\n.\\\" Octave is free software: you can redistribute it and/or modify it\n.\\\" under the terms of the GNU General Public License as published by\n.\\\" the Free Software Foundation, either version 3 of the License, or\n.\\\" (at your option) any later version.\n.\\\"\n.\\\" Octave is distributed in the hope that it will be useful, but\n.\\\" WITHOUT ANY WARRANTY; without even the implied warranty of\n.\\\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n.\\\" GNU General Public License for more details.\n.\\\"\n.\\\" You should have received a copy of the GNU General Public License\n.\\\" along with Octave; see the file COPYING.  If not, see\n.\\\" <https://www.gnu.org/licenses/>.\n.\\\"\n.\\\" --------------------------------------------------------------------\n.\\\"\n.de Vb \\\" (V)erbatim (b)egin.  Use fixed width font and no justification\n.ft CW\n.nf\n..\n.de Ve \\\" (V)erbatim (e)nd.  Return to regular font and justification\n.ft R\n.fi\n..\n.\\\" --------------------------------------------------------------------\n.TH OCTAVE-CLI 1 \"03 January 2014\" \"GNU Octave\"\n.SH NAME\noctave-cli \\- A high-level interactive language for numerical computations.\n.SH SYNOPSIS\n\\fBoctave-cli\\fP [\\fIoptions\\fP]... [\\fIfile\\fP]\n.SH DESCRIPTION\nOctave is a high-level language, primarily intended for numerical\ncomputations.  It provides a convenient command line interface for\nsolving linear and nonlinear problems numerically.  \\fBoctave-cli\\fP\nhas been compiled without any GUI support (Qt) which makes it smaller\nthan the default \\fBoctave\\fP executable, but also limits it to\nproviding just the command line interface (CLI).\n.SH OPTIONS\nThe complete set of command-line options for \\fBoctave-cli\\fP is available\nby running the following command from the shell.\n.Vb\n\n    octave-cli \\-\\-help\n.Ve\n.SH DOCUMENTATION\nThe primary documentation for Octave is written using Texinfo, the GNU\ndocumentation system, which allows the same source files to be used to\nproduce online and printed versions of the manual.\n.PP\nYou can read the online copy of the Octave documentation by issuing\nthe following command from within Octave.\n.Vb\n\n    octave:1> doc\n\n.Ve\nThe Info files may also be read with a stand-alone program such as\n\\fBinfo\\fP or \\fBxinfo\\fP.  HTML, Postscript, or PDF versions of the\ndocumentation are installed on many systems as well.\n.SH BUGS\nThe Octave project maintains a bug tracker at https://bugs.octave.org.\nBefore submitting a new item please read the instructions at\nhttps://www.octave.org/bugs.html on how to submit a useful report.\n.SH FILES\nUpon startup Octave looks for four initialization files.  Each file\nmay contain any number of valid Octave commands.\n.TP\n\\fIoctave-home\\fP/share/octave/site/m/startup/octaverc\nSite-wide initialization file which changes options for all users.\n\\fIoctave-home\\fP is the directory where Octave was installed such as\n\\fB/usr/local\\fP.\n.TP\n\\fIoctave-home\\fP/share/octave/\\fIversion\\fP/m/startup/octaverc\nSite-wide initialization file for Octave version \\fIversion\\fP.\n.TP\n~/.octaverc\nUser's personal initialization file.\n.TP\n\\&\\.octaverc\nProject-specific initialization file located in the current directory.\n.SH AUTHOR\nJohn W. Eaton <jwe@octave.org>\n.SH SEE ALSO\noctave (1)\n"
  },
  {
    "path": "doc/interpreter/octave-config.1",
    "content": ".\\\" --------------------------------------------------------------------\n.\\\"\n.\\\" Copyright (C) 2003-2026 The Octave Project Developers\n.\\\"\n.\\\" See the file COPYRIGHT.md in the top-level directory of this\n.\\\" or <https://octave.org/copyright/>.\n.\\\"\n.\\\" This file is part of Octave.\n.\\\"\n.\\\" Octave is free software: you can redistribute it and/or modify it\n.\\\" under the terms of the GNU General Public License as published by\n.\\\" the Free Software Foundation, either version 3 of the License, or\n.\\\" (at your option) any later version.\n.\\\"\n.\\\" Octave is distributed in the hope that it will be useful, but\n.\\\" WITHOUT ANY WARRANTY; without even the implied warranty of\n.\\\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n.\\\" GNU General Public License for more details.\n.\\\"\n.\\\" You should have received a copy of the GNU General Public License\n.\\\" along with Octave; see the file COPYING.  If not, see\n.\\\" <https://www.gnu.org/licenses/>.\n.\\\"\n.\\\" --------------------------------------------------------------------\n.\\\"\n.de Vb \\\" (V)erbatim (b)egin.  Use fixed width font and no justification\n.ft CW\n.nf\n..\n.de Ve \\\" (V)erbatim (e)nd.  Return to regular font and justification\n.ft R\n.fi\n..\n.\\\" --------------------------------------------------------------------\n.TH OCTAVE-CONFIG 1 \"3 January 2014\" \"GNU Octave\"\n.SH NAME\noctave-config - GNU Octave component and library information retrieval\n.SH SYNOPSIS\n\\fBoctave-config\\fP [\\fIOPTION\\fP]...\n.SH DESCRIPTION\n.B octave-config\nis a tool to obtain directory information for \\fB.oct\\fP and \\fB.m\\fP files for\n.BR octave (1).\n.SH OPTIONS\n.TP 8\n.B \\-\\-m-site-dir\nDisplay the main directory for local, or site-specific, \\fB.m\\fP script files.\n.TP\n.B \\-\\-oct-site-dir\nDisplay the main directory for local, or site-specific, \\fB.oct\\fP dynamic-link libraries.\n.TP\n.B \\-p \\fIVAR\\fP\\fR,\\fB \\-\\-print \\fIVAR\\fP\nPrint the default value of the Octave configuration variable \\fIVAR\\fP.\nRecognized variables are:\n.RS\n.Vb\n    API_VERSION                 LOCALARCHLIBDIR\n    ARCHLIBDIR                  LOCALFCNFILEDIR\n    BINDIR                      LOCALOCTFILEDIR\n    CANONICAL_HOST_TYPE         LOCALSTARTUPFILEDIR\n    DATADIR                     LOCALVERARCHLIBDIR\n    DATAROOTDIR                 LOCALVERFCNFILEDIR\n    DEFAULT_PAGER               LOCALVEROCTFILEDIR\n    EXEC_PREFIX                 MAN1DIR\n    EXEEXT                      MAN1EXT\n    FCNFILEDIR                  MANDIR\n    IMAGEDIR                    OCTAVE_EXEC_HOME\n    INCLUDEDIR                  OCTAVE_HOME\n    INFODIR                     OCTDATADIR\n    INFOFILE                    OCTDOCDIR\n    LIBDIR                      OCTFILEDIR\n    LIBEXECDIR                  OCTFONTSDIR\n    LOCALAPIARCHLIBDIR          OCTINCLUDEDIR\n    LOCALAPIFCNFILEDIR          OCTLIBDIR\n    LOCALAPIOCTFILEDIR          STARTUPFILEDIR\n    LOCALAPIPKGDIR              VERSION\n.Ve\n.RE\n.TP\n.B \\-v\\fR,\\fB \\-\\-version\nDisplay the version number of\n.BR octave (1).\n.TP\n\\fB\\-h\\fP, \\fB\\-?\\fP, \\fB\\-\\-help\\fP\nPrint help message.\n.SH AUTHOR\nJohn W. Eaton <jwe@octave.org>\n\nThis manual page was contributed by Dirk Eddelbuettel <edd@debian.org>\nfor the Debian GNU/Linux distribution but may be used by others.\n.SH \"SEE ALSO\"\noctave (1).\n"
  },
  {
    "path": "doc/interpreter/octave-logo.eps",
    "content": "%!PS-Adobe-3.0 EPSF-3.0\n%%Creator: cairo 1.8.8 (http://cairographics.org)\n%%CreationDate: Thu Feb  3 18:31:36 2011\n%%Pages: 1\n%%BoundingBox: 1 1 229 230\n%%DocumentData: Clean7Bit\n%%LanguageLevel: 2\n%%EndComments\n%%BeginProlog\n/cairo_eps_state save def\n/dict_count countdictstack def\n/op_count count 1 sub def\nuserdict begin\n/q { gsave } bind def\n/Q { grestore } bind def\n/cm { 6 array astore concat } bind def\n/w { setlinewidth } bind def\n/J { setlinecap } bind def\n/j { setlinejoin } bind def\n/M { setmiterlimit } bind def\n/d { setdash } bind def\n/m { moveto } bind def\n/l { lineto } bind def\n/c { curveto } bind def\n/h { closepath } bind def\n/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto\n      0 exch rlineto 0 rlineto closepath } bind def\n/S { stroke } bind def\n/f { fill } bind def\n/f* { eofill } bind def\n/B { fill stroke } bind def\n/B* { eofill stroke } bind def\n/n { newpath } bind def\n/W { clip } bind def\n/W* { eoclip } bind def\n/BT { } bind def\n/ET { } bind def\n/pdfmark where { pop globaldict /?pdfmark /exec load put }\n    { globaldict begin /?pdfmark /pop load def /pdfmark\n    /cleartomark load def end } ifelse\n/BDC { mark 3 1 roll /BDC pdfmark } bind def\n/EMC { mark /EMC pdfmark } bind def\n/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def\n/Tj { show currentpoint cairo_store_point } bind def\n/TJ {\n  {\n    dup\n    type /stringtype eq\n    { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse\n  } forall\n  currentpoint cairo_store_point\n} bind def\n/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore\n    cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def\n/Tf { pop /cairo_font exch def /cairo_font_matrix where\n      { pop cairo_selectfont } if } bind def\n/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n      /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point\n      /cairo_font where { pop cairo_selectfont } if } bind def\n/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def\n      cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def\n/g { setgray } bind def\n/rg { setrgbcolor } bind def\n/d1 { setcachedevice } bind def\n%%EndProlog\n%%Page: 1 1\n%%BeginPageSetup\n%%PageBoundingBox: 1 1 229 230\n%%EndPageSetup\nq\n1 0.498039 0.164706 rg\n16.258 153.068 m 61.023 153.068 l 67.812 153.068 73.277 147.599 73.277\n140.81 c 73.277 96.048 l 73.277 89.259 67.812 83.791 61.023 83.791 c\n16.258 83.791 l 9.469 83.791 4.004 89.259 4.004 96.048 c 4.004 140.81 l\n4.004 147.599 9.469 153.068 16.258 153.068 c h\n16.258 153.068 m f\n0.831373 0.333333 0 rg\n5.030871 w\n0 J\n0 j\n[] 0.0 d\n4 M q 1 0 0 -1 0 230.399994 cm\n16.258 77.332 m 61.023 77.332 l 67.812 77.332 73.277 82.801 73.277\n89.59 c 73.277 134.352 l 73.277 141.141 67.812 146.609 61.023 146.609 c\n16.258 146.609 l 9.469 146.609 4.004 141.141 4.004 134.352 c 4.004\n89.59 l 4.004 82.801 9.469 77.332 16.258 77.332 c h\n16.258 77.332 m S Q\nQ q\nq 0 0 231 231 rectclip\n% Fallback Image: x=19, y=1, w=210, h=228 res=300dpi size=2499228\n[ 0.24 0 0 0.24 19 1.159994 ] concat\n/DeviceRGB setcolorspace\n8 dict dup begin\n  /ImageType 1 def\n  /Width 876 def\n  /Height 951 def\n  /BitsPerComponent 8 def\n  /Decode [ 0 1 0 1 0 1 ] def\n  /DataSource currentfile /ASCII85Decode filter /LZWDecode filter def\n  /ImageMatrix [ 1 0 0 -1 0 951 ] def\nend\nimage\nJ3Vsg3$]7K#D>EP:q1$o*=mro@So+\\<\\5,H7Uo<*jE<[.O@Wn[3@'nb-^757;Rp>H>q_R=Al\n C^cenm@9:1mM9jS\"!dTMT<$3[GQ$8#0$s<4ZX!SPQ1`C/m<k<ioH)<bk^Hj`\\=EYZP^B4!g\n 3;B=(iZ<kDqOh(X4@+3qpEmDSXE[N7)FF1(;OFM-38=+\\!\"mSZ!7M720<,1go\\RZ:oJ9`37\n XA_`&!@u03iE15H4'/LfI@Uh@?Cc:^b>HHFlMi:-ncYKoBDKd&.l'7:d1hjHP\"/@`m`GlpO\n c85>dbKY(%>)m]_@F1F^W:<L3'=hf;GHY9?(+ZBHd!%Wk:NmK&o'^t@/l1e_fBr>1IXb_>k\n P+oS^^pnX!PjdJ%0N?fM=c69a-lF/*J^E.Ga7^]5&MBOJZNr)/os!l$t_6,.MsMbRU7\"#FA\n WcA0jJ!\"`Xu``-^WuFBcBOH]QG47OhnLF8*0Z$+ik9IKI@ZAglWmS10g@sap-Ln,g(.lW@Q\n ->bc<4N;(T:qbOZ.U1!C:K\\Lu+g$+MT)VXW)H*$`:kEY,+9bXi`Y9J1K'X>tOqR>^\\UHp.q\n &&OXq[9bg+EP\\hF2dM.Ze8^`j*/;0WCl28/c->D1[(JGuE`C!-Tq`0X10W-'#V<PBgeb+&n\n =iCt9?Wu%r]ldOK;13d.f?m!1**ALIN?Lj@-';c[EdX9fg\"(8S/6[)EW?f\\d/[]ELP>oqJg\n Xck_EJeg;b&1JY9[kR07dEZc%l9UfC7OAO0NU?5!Rc63Vh+2WY-4ZTJ`)nJ%>3UV:)/KAQu\n 3q\"iQI)UDo'FD!`g9GBdCb1:0>;@S$ct9-5X3699Ni=:/P0F=`%Z8jd\"YC>@s:oK4&=,r+@\n )'p+CW&=ZR\"[BZ`@^T5*U+]rc.qQL:.rgiistED76Ld;s(A^9r$>L(Uu!lh^=kYR:nJfO^Q\n u&Z0T4#1:tK*R?1sD&u3['RjL1cLnm>S*p6in/MrB_=3@#k'`kVRGN9+a!'A5cQg8pEJr(L\n Q<kLm^GF)T>jjD3F;[;3Q#q:X?'t:*5&H^1Q0*\"UFnQT#T6?@QQ.tM'L5Xm^>!A4Il$@Q-V\n Wsa*VfHQ6\\!=&]HP`6WqAsRMkNi9B76)?/_:%`l`];Ur*\"0UU9lRj#c1ClU:Y#.:T5WQ[WR\n T&fD=47Rb]o>qD,,*Zr3nZcgtVpOcjBb<3!SSP,RK#3V3j;f<9mgo2-3PhS?mBc\"kid_BFo\n %;ZtMSji<-o@NBQ75G,5N%9IXarWTcb$W=.RQ0nmMa.[n/SCBIdS&>r2u%FNf\\Nu@7)_si,\n i#`TGU6qN54/ga!=SJ00cnf&nA=q3:D,M/T(1s3T[3Jb7)@f-F\\Z&SlT=N)/Jqk]9K.?_Kf\n h#lT\"EIog_$F>OBm9n,JO%CAK62,]p,Q_(mE09-HB8k?3>Utq2EYq/(*@#*Id\"\\<=8]an6,\n iQ8hLEhI@+gFj'*p_]'_qFRa.%r*O7&cGLY#\\0J>q=P]q]F/.]o,h)WC((7)rW\\.9A%'6UA\n Vip&X\"ro=c\"ln/-qY@Xj]PgSK\">o&9X(4C*NHA2;mPB=g@[<8,,FoA0g,<Z5Ra@=B-PK[#]\n r>7Wh'Y/L;[TnX^E>9LE;l(K5'h*0%=J$]\"0K#K3I)'Fo^k=q*d]71#Ye/<*%PqLf*HU-et\n :c@lBt&k1I*UD.I%dCMJ2B[\">[oT#&3.?,5p744&c/iGt^h_X;Gd>h$u3_``H:\"DEFVb8@$\n 8*RiL,TT14oaTtQ\\^'doAP&G8/a6%,SNNftRAs3<DUgJQ(.KG'%`uph+b=l!#E[gaN(R#Fb\n 0=)T7;8l(Y-qB\\!*oi^_Q3fE4N4#.jlkfOU\\3o6=3CJ2kq'`JP5:G;M[N-e9eE3*2ODYpV+\n fg42Q\"r4S5#J(mHNunVsoG7:+D)-.P0e^oeN@=g6GV\"V,3a`>1Q\\H=D\\,EZjUQ'4cL&p-V!\n =c(b=rp%rq8HXp)YO<t=4p>E*XDX*:^6a@N#/_J93<]!(f#^\"lnlFmbfGYVm!Z7N2e\\lp]m\n <F\"u(pfGud4PgQd6d`Ok5G@f2+R=hhpqH<.OBJ76^ZrJ!G>&-]Zk>eIr<j(%^>-!4VNE*D(\n 0*Pb1bVFqRN%tIZa%um$E\\PKN_cUge@GEu^hiQ)L,'C@!dnN=\"LtK[+Y3BDbX`e]50tS1gm\n GhCWGUu$=J/=6b7bc77R>'mo=0=U@f4R\"I7!u^o/LB)YQBra8S\\HtHdGMJPJ1WBVP#eU4jk\n 8sNo*)8?0\\Ze>SB[I@?ro7;FV+lKUcCjo),nH'_o,eESb'jHcWT^#B@;f!8!*K\\\"+5:>6,b\n J]a@F4\\0,80E=eg(n0#i35(hlZNNNV\\.]K#4Oj1EEo7a=9(\\I+bc81B[r`UD>YaeND0JX!I\n \"T;\\/]dGO>.QCA'\\bLdI_leKIIn8?%o7aj4(h2AP_TNF+;CiP=7'Je25ocJJ65Aa].[J%Vn\n gK8Ik%(%3(b^`u)\\gVB4:!Idh5*=7IYB=OfAYjU*n$!Q89O7$I^%CGLa-qo.X\"?m-oe[H*r\n !ucfRkZj9p%?l3`r#'NafR5Y=4[1Vs6He0YOFu`bo6nIi16\"8[O36Z*/lGS!:k2b*eYEoVM\n B$&?-E&!1$2`c_5L4Mj+I`+$1;1G$^%X=7_\\-N>GIp1?AkTT7dSQ-a%LO/Zb:R[39j`.:ML\n 5>^F=ktaBSp2E(l7kS^+<\\R^o81#mlkVIT>c?;i0E\"/XJ6m(t[H)Nd\"caaS>d\\jBE<L-JnS\n XXdIuV\\\\(k.EN$XKQ\"B*L0?/7o*TR'KA!CKe<1'?6Bs^r+kM66cH+uMhH7qYLhN)dNS_ND<\n QVR3:5H*h88#JM(i87^e`c'_?A3/O(]q'N,,OQ\":3(9:p?'g:F0%\">lL&:8Ki^ieAGMN1OY\n O:1i2#\"behDlC%qd'*e%H,$9KM!2U_oCQfs!.@>8*TtZYP&S`bWSJCW%gT:htc.erVsA&oD\n Jd=J)<TW:]T=T<rd/<YHFPkc0Y-VW0o;Q!Ne]^bsq\"mLA+B!pSkC`#WV0B]ZKL)m)d8iCo7\n \"V=S\\!0q6&ZZl/qD1<;MZQ_63G-&7Fsf]),pL#*<L.#::,JHr)!O*pAFYY^m'6Ka;XRcb[a\n e_+suJlMkgjrt(Y!:n7ORr:H'LoP[G2m25naR1!lp!=rB8/uJ_@%fsrL!Y?L3l)+TB:BJjf\n !tGg_O+d[tjN7rNm-m9kDUsq'QNX=Sq9)V=:,<'Vmar(X&?iDEE=iD['',b\"&WG?]i<VJ\\-\n lrE1P`Ue9nM(\\32%sYrXq*!&JC6:tMAH;s'QBfS&Q&l)<=1FX'sIcJ%G_#g\\JA!Odh'J,.*\n 2+!5jJYP%1=Bi:Nj%E.h0gU%LeZiLd_fX52jhM%kpKaOS5ZX:u_!I\"`X\\LOUVLL%hV[L#14\n 2\\Yo+N9^eLK]Ea_McJZLM;aV0fi*O4E@n_d:VHlo&.Ic0W3@Dq@A9cn@H+-B>6EDmtM\"TOR\n a(!s&tn,j%r'^=\"[os&E9E5q1f58T2e!`=E,XGGC6Eqe^Npb@g(EK^LCbms0ii[npKOeR-j\n r6(3&qCl%`Dm(*459&\"^&MF)';&^KqF!krE%&&h(!A&*(O?t\\b*\\r^'nrY@VPUbp0+5reE_\n %]Y[RMTD<#a,!6nOkAEr?'Gi/$]1+n>.85`?=VF+VA3\"EmW8(^FaIL(CS1jLt<i0K-JSA(_\n A279ALhL[i!@o,R(4o;!f-Yobkjd,r))>;5XR1>1`=P)\\QX8mRJUf,l=le19u$X_7^H>%UO\n sA*[0<&17'gR75T'W1nmM\\KA7.#)@Ji])j79@o3XC18N$(J.oU:81N=qn#:pJi+O<Il'7dY\n l(G.3f+fi-so8p43FFeDTp@3N30\"DF3nDJ;C,I7+2Er;\"pM`YOE,`**eM:3aa`63(k)NUX3\n ZPs(RAMOoH-F;Ma'B(_<j;YnA9q_P^_/+SZg)hL41t2CfoDq33i:.t@4CIAJ&PY/^@5`3F6\n $+,*PA`@cE@[5u6F1kNP/doNK.O=S3-7:`db)0QP:`^83HF.?WuUjF,s!KW%?:e0&2PQZq[\n RC%4-,@_dg%/Aq(U8,-#C1JC_8f_mlbZt)me9^Zf<Esk=IBG5,#V\"bha,1#d+jF9!k]moW[\n 'ncBO8Y*?_@N'!*#$_b>.k5uc*&Zm/:%-S#jQ9scJpOJtu2Ik8uU6h?,;du:*Nh*bm57*8e\n (%\"C;,dj#HW,=Hf<ZM+GpRl_n%0G0WGoQ(..q`JtI0e].i%=LcB2b9$;8FgUhF[8T!77i0e\n 8^sCQ_.YNRe1S,7<OH+4ojFHua;BfM%jO+@TlWmnEE?.c9U0s+FO*8Fd6Z8.=L2p?e1Xr=i\n A]&C:6H8+<:)86]_0eM:NMdR##d-CBeGJp:m19Dc[A7ohbdAjiGk*DZuEB.^eIdR4EPtN0r\n mGLY<>f-)`9cAdVi)B8Q9j*<23>!6W3D^bSKC0*X!9[2A'@U'k(_\\*WtC9A2\"AOC'\\6c)V-\n ?=p+]Y\"2-:TK=>UapeCS4c9j(HQ//=RJ<LlLBUKS&1:G\"G-YSU*aR.g$q>E)9.`ID+tD(eQ\n B7T6Q]Q@Vo]7kdrn7oR;Zp5ml`/J%O7-.V0LFmD2U5@5'Q?a]]Ep%Mhp^M?lW$\\Nm?\"?%)a\n bp^\"<CpqT)p<ZY@-m&I.116:.eh:o!.rJBDA!ZFu[=rNVK4Gbn'UD<n1bE81k<kL\"AX)Xe<\n aA+Z@:i0U:^bZ_dd(,dV.WfHlo'7oEKMpHCt:HdGkE@rp\"L\"BhUe#HW`:nD[5e$Umj==oFg\n eDD[JtD.[rtQ]*!%C'_4!M<05WXnGIN!Eij<)ZP^Drg*&d&+p?-]Z/U:AUDYKW1eiQuWqd`\n b+A@DScpB:o22Y@jqAS\\\\A.g9Mr'lfMFER[o`<*2U+.9n_B>_d`@$A!8>\"*:HdB[NGo/gka\n [;e`QUC%XE\"1lHKr^M=WmJ?jB7QXt^aB7Xk?*&)ITJZs$q'mLQEK\"*Caia@4$C5TgF21UBi\n \\3:h`6\\IC\\H$E&:\\\"@Qj;cd#mH8bA@F<tl#AI5iP:,fW;Qb?/G'+>Zl>1+[m[C%3c<?h1dI\n <KlsfA0;Ji:rS_Bp\\'^2:lP\"-u7H,mPjq$=8d7Y!E6G)8JhnZfEja/'9%/PJPQ=W6^AJNXY\n ],0K,EF(pu.5W)BNE*@KG$e79tRk6'$7ZO-iLa=A+>b<KMEqA!gJ^p-28P6&'Te2mbB'pB`\n D'F*joSHkVQre44nICM&d$EXHN$:'E\\#?[]C:7X$Ul(ZeNedrXf:MH5js\\?BVp@:#1V?J)l\n )Geo_(6\\/BcN0^j?0*2NVIM$'5-t2>4=QPr2Q'le.4ot?jJ[-:]R(>P9(>/MQq\":*nrK!?K\n O;Y`bfN4S&?$[6BO]9knRF(-LC@nr4dJ5.bpig<F0eM'8a4WHS3/;N6Mac&QEk%6rUna1I)\n jN;.BUA%MR9`^sb;!./qH7HG)/EtfWM4P,N&c$>3I?^qHo3p8URF:ai6G(,S/n<90,^1RqG\n F(ENZCc?&u7I'iN\\i]7@MqAVRa1*>&g#l]7g!p@en!)\\Ik?Wc$G[CSN.XDR3?NoDaV&aE;;\n \"fEG_:h8Y3..T(Zrl2$]b!7A$t\"B=\"d_'cC[`]:dfOF;Uot<gP,$)iGUVJ,1C?3H(X<0<T>\n <UH7dc=unNE5Hc4!)?J#hJ`=td<NpfVYceuOiURS6lj2!1VRgKHqId)pD5TF5RlLGGRk^ge\n It]q9ZaaG6pT:CEQ`2j3OulC/n?ni@?`I2J>7RiafS'bNdV!m7O#d/DH3&kAjfDJ2488+r]\n $Cn4@6FFDXgr.g1F'%]=c<0FCARCo>G85^V6=B-G+gH+@Fp)Sn$(QW]=Y_nJ]9>D$o7m?@\\\n A;g_5k6-X0LD*Z5_K1q^]B@YGZa3@_4R\\Pf^8?pS`?RZoe4R(/_k!af0KpWS-6ne4$d5l*]\n #:Wn/>n(l;l1A[\\IaX1A82pm%LVH*!<i;HNAkRtl*sflZXFMg&13=9l!t/O\"NR\\bi;.>[bV\n 0[Q!.43Pfg=!UC!f^W1_Ia/T=a.7pd1c+KaP]j-Q1*07d[h8t#uah'.=>'6aUV6_-0W#<^l\n HAQrp7DJZMS[G**dtb>5H$i2GWgPd^Plu6_5jQ'3B7\"P6\\)!]Rl\"F1k_m9ZeqU)!Z0<K'.`\n /gt$ppm,eEOi_^FrR-o];`e5'=pP\\`aQRiADe,7IAES.a5&>qr@iYFS.]DtZ(-`o*C7A%6c\n hF?^&4;JgEju]jhA>_H(4?Sp@6<\"V8&KcW;URqg]]6V$&9FgLKkF=4;DHj),L/N(V)]R>.&\n C@/Q\"TNc<4#$UrCWj%uNL>Ilc%Kr:tHeZOiX$\"rIM,r<_7=&#4O`Y8nG7r+\"-fe29UB&#AP\n .irU;7f@)nIhS&8`Gj$6#2GYHZ'S(]LTr[)L7GrSce:%kK>b0CC:XrYu^3lib?\"(JEp\"\"Ms\n W-l)*q:2j>D9L90f=j?d)cb+An''JP>?oXo>hOqghnnk?g\"i?p]^)7$-+GM6`'(EoRuQ0n!\n Q=p?Y$K#c>nPl*($L$VURg#ahN0\\Sb&%/M@l7=P^$k5MV<VRiTts8e)5\\>o\"m^U<l^eF@rX\n 8&k&_.rE^\"sXKrZ0P'eYh7KmC6<M=V%k8Mnf+JbI^J9HVnb=6eFJ)L\\>BAh2gY5F.\\YqM#8\n u?r&(.7S[Z2RQ+a3)rNBNHMb$\"?chih/?@051=7^UAgmh[+*fJjH7Hm$+2rM965o^gedMek\n SlCVATs'RA?ab+$Y$:ci:hf7tsFl5K.lp#pJ50MnISa?;ViV]Ur]/f:!Z0kX_m[p$A*HV'?\n GH%+Kmp1FNG^K<KWJEb@PPp^7S1F*]P?bH%jnd$[59$:Rh=<KrgH>E<h7G\"];;<6RkPFN9h\n 9#:Rp#uGOoY3d:#F::5JE_?nT<IGU/f>+R6fJ[pPYNYBMacY<R+-\"6*KN_O&fDCD8L9QljV\n !t\\Y$!?C9BHm*Pg3u#Rn`&ZRFLYM4eGO6'H$F)f^ppQgS=GB<g?@TO=Bi<X[8p`W`A:o'sg\n rK>clUo(&JYDKXPZ!D\"_X5Y17Brg\",m*OUC,j\\_V05@NEJ_HG3bTfGj5MLq%5/E;46=0,9J\n b[IC^1`_.bCb@L/h>b5Z5SBkg>);LVtEnA`R[(:ZdVcftMCA%GZJK8jbg24:1IFdS,\\82d9\n ]FFlGM8S@mM(?$T-^W!<F8=W5Dbm(Vl#fQj`m8;,g?s1^hA43d[H-lRI3*l>S(['\"qYf6E@\n eI)!qY`V8T?$?)9jX;boDnp,0I-l*5R$cl\"UVD,)$Rj\\8=^%'B%/+6_N;,U-^WuF2\\*`eoK\n s0XE;Vn:_f7\\d'ZG&[>87JL!Oin8;2f-,7^9e<.)n!sFWO'CoRe3B7L?OJ8CB&M,tTk&OD[\n UPH%RNfEeLJB$?EebDG(Vt[4Y+(TnI;W1E=@h9_1*i1<jl.felHTWf]91Z^g>A:@k3A.o0+\n &]04Khm/K?gPP#23:t.oA78W.1Y<l+9D')>I1o2<G(oHsZ9[a^+4&/`:n?Yef<=MGs<4,.d\n <E/Ws;cATD0u$gk<K1Wq<jfcX/_2f8F^A/Bon-S/Aj(9GfTnCYA6F((\\RLOF=i=;[7rd=3T\n 8FAiD-M2F]5LpJ\"iG=bG9tFR>k^\\9F^93&gNOu7+mOH9L2\"T'hWeD9V^f18Z$r^qP/=D1GS\n UXgXc%W?Ke5s?m>#,[K*8tDGb-D'ip:82a\"`OR0oohT\"$Y+CGnrg#AF5[\\f]@BG>humBIU_\n 0D=egnD\\F$>tSN?T,Xe06DS&\"IUH5;2.kjOGgV.giPjShA>^8%VlYSO:>C@HluX[1<U1CS'\n g^;CCJOVCHo`)1&F(Mtm3D]3KiG245-EX(bO7P\\52]l-!nV(50-pB)kfo(NMEnFLQ32t:s5\n )oWb[[.DC[4H0M0o(3/C7WWZI3CVA<LI9F1B'h`Uo_g^C<qUTJ>?>tG@D,mrSYp,RfQIL>@\n <XUoHY%EP@D?H\"<[b[m*!DtBFW6+(nTXg.LSO*[I]'74HN(skm<a<F]C1+13VZ5ca$>Hjhd\n 8hDoj;q;gONZ+,0,=b3$&lhXk6Z!LT^[>.>^:`r*^Gt\"(P#=O;W9Qa4Vo8JS^=3_\"Lb2).B\n XZ9YfN$<c81FZ,LAfFe6G3IWV#-ie2.XVF#Hi$6!XDC(ReNT>n$biJU`P/TMcIG/W#OoJp_\n >S[(WVbhAd)Ci*jZ\\>,FOgY9).DQ*ZN\\$VU]>QduDks<0GGcql\\PE1W^1+p)t`8qZN@WG4H\n brLU(kG(tH;(d\\t\\k(WA<<R>am`%=LkjIdO_mWW$n_-((!:F.Q^Q=K[A3;j`ZW8K-)P`g8N\n q)I&T)=e8P#b4IGqgXVe=2YbG#(^*5Xu(;rZB\"YD[t-aD*ds(.?^t.YIRuRT6'LfAPr9HGN\n ?Tt`4LKhp&3).oYmI3_CuC1@mELD![^hfJIj_P)AjbW@#WQGE)pa?GW*hodl2pnFq;jkI0j\n Nuie:<s'[Cle$_!;5C,!qW6RZp`RbTrqOR]To)=\\6\"1e!4An[LuE!C,>P\",Vj=-d[+4i1d=\n \\E)C@$3+TiAW0C\\aN]o3qFR^8Z6thR?IZGnuh+2%-KT;:^:e-sO*[t!cO4:RBa;9%o<ZAiO\n OqpJK8oZ%EpidVYOC8Wmk!%lPTr=4lUJuQ%;JK3)WKfB><:X-Ja)L\\[6O9L1lEMjSe>nlGY\n #rEKCA[+_\\:0L`qc7uf0H]CkQuE+95Zs.Q+<1]jL1UWkG\"H!ePS:6cm*j4(/RVu9gRC!F&D\n 2=<F!hnpKTi-O6G\":aVcAq8&B`0RC#M2@dp8QLma!#Dok7e37%^oRJOGlh6#BRrTeSmc,e0\n g@,+T4PM/\"]uH7'Nm_ip%$DDU&?#=n\"DSto5tj!e[)Ea;*]V0&Rt>kLZ]SZI7$<6FLT3c0%\n N4ZB9<kVfVAC,q'*p)eq\\W*XhuH>cgL]pH2%?Mi]-#D1P>\":QDQR^mlc`VZ^Fp923Q`IM%O\n AAFAn?WNWE0Pag:Xgg6H<u`A=->!poP<QY<F#dU)VAbo0@_fg:ZXDqVi3>8)E*0^gA8HE>K\n m$@:iq_JD0pM7KPJsWVq<Z`c'`#+Wq]@$Y\")8FmX.Ycaf@nlR6LB\\`U)>i,>F_BUBUucEFD\n B`2bCu6r\"XCPB:6Sqq_/lptbuOL9l/m,$9J]Y#OOVh=h:oK17egS!,+NVS<NgdkepG`2pHN\n <h!MFNMI3Bj5=_D]@/r$l\"(5#OT%86@pn)fbI21%u'lG8\"O%:tkeEVeUP%kk.eC4CIh[hp)\n 0>cX-4_Nija=,7fN23o1<[K=6R/40Xs22Kk'K+qG?9oC`+OD-\\d(LnJJNNCtqZa87(m/'M<\n gMT=2OX_^==pIAL4Aa.F.P#&qCQu:C\\>#BhhSrcJQ*(O2b?8lF`uC;1eCJ-@)3NP,/#A^&Z\n GOl@ojm4mF.@jJ`sa1<E/Cj23sRb>+*nHQE;h$!GaB*'S6(U]J[@O0\\7e^-5EBL75GU-.,L\n Tb*P=kd4b\"BsM^nm5k<e_9dq3Ir.cjNigR?O[sf!\"8*a')R$Ig!0f*]ElS_G.+)Y<#P5fGa\n d!FT$sC2DjbagEOh69pL]Aei;uO;eT[_pU#8^VqS8rCZIm=Oul_\"gXaPdd/Muk[jQ7>.Dp5\n pCp2]*9uHFW.sLFH8\\BEbFl(m$kAQ=(RVoluhj8,.E\"=(rGSoB0@=2UG!A$.L=Q1Bsl\\kT=\n 60N_5U\\(.Edlel<50)lK)M=EWEZ\\`24dRAR\\l4c!s)FpLecY$*pJ:&q?s<AtUojRE\\FYY*!\n N'2)kISODF<@4'0^^%HN6bc$Hq2WXn(Sd%3u%$7_:0BH0C!3EX8[?XZN\"!3a\"[30FoA/DZ5\n 7'*gLDFEYOUA^ekGKnJh=U9!&kfM]=\\2(6bPEO^:.T(ZKqcJ6SLH__SD(U\\%BSoW^\".+I5>\n ZZ2u>TtLi9qr&0<ea*]Q[paE7^^H3_XB_-@aAC_oBb(dX)r\"uq5:T^;dD=gW8']o3stl]Af\n dg:b*k]upC%UYVcQh`5K1\\U3;>;r]_sj>j`i^1694Esk#\"kr\"t^[B&T,T\\hde0H&(%3_Ng@\n CbmVPnO#rX^FF@eZPfjfX[A\"Y^M8,1K-%WCIm9Fu]0ioo_mR8&DSOqF[gTc4'LOt!1,i-RP\n LK`IlbC5N^qb<5\\\"!ae16oL>1dJuR5hlf$gOR6=SO!Y+*^!:&=DS45D$Q3d6'PD=Cfa&Q=@\n J0O*l*#Ud!c*GB87`P#,GPDll=\"\"*_$PYZtpjS.f;UQA2!8668RIToHcMF-88\\=2(R\\+X=6\n WO._48F^2rGRgi#O.Tu-FU^;M`ie8m/smmB18^Bt]C@Wk+[AA;'F5@aCSZQ:\\DHm1AP[]DY\n N_u-st[_rRQa;QSI/;#^J!j\\mr]@9<UbX]U!#Xjm``3bArg^?'b9s[cJ7-kE)lC:9WO@:>Q\n KJE$%Z].DDPY\"Q68R.QQCmPF[@#$^dV+>DkoNjuaS4UAa7MHq6*$3*V+KF4-_B`^\"gQnlc-\n ,'L/`fqjY1aoSe.QQ97`oJ^DWKfs]&4\\\"J6R4Ck4>XQjFi.+!7roM37!Lc9AOiM.5CBm`%\"\n ,Z,4\\+Qs^U-3r\"@'ZVJA`BS83B6ke:bUg76iqXbT)DDjG9S,MG-Yu`6?4`;glI*NP'Y\"3!>\n >^*6Ub^5pU,Y#Cq0CI*YLacqOqr9cH6NE-qoC5)*Hb8[R&?bgsnkT1S)c]tE&Z4JBVRh9%h\n :8k\\*b>\\Z9pCJ&p[8rF%risSJdDl0>30_B@r1p0>2Y<t^\"b7s53CT:.@G0;`08!LBuRiFr(\n +%q!/98iX:l@R(QKLcb&9@SO9jS'<e6oR6Dc^]a!AAZ,m_lctX8?1jk_EU<0$quQF_\">c@'\n [+i[b+rEe#/jM9,mR7p#Z-Ke:mlN]^i>-S-&eAGd+m5Lm+=ns&4trU;&WM1]\\>ndA^/\\\":#\n p!%,c4&<V`mc7:*\\lCS\"<AD*(&^>7h\"O]/?[9NV,!GR7qEl!D!X&BmDk/G/C_'lD\"'g)nJb\n a(/PN^i]Xu@ooduF%4-T`kH,e0fhFnX[9H<pl\"T1ZW_9^p8cgrqh\"NSk'%8\\:#:dmEA4Z`d\n 3CPP/lSo\"g5m6=PJ5ZA1Y#iKo^aF/]fAVU^)8_$8ZCn/b7fY*gg8de8=3rd>OpX)mF7YBV9\n A8/o'(b:!m2-at3AK*tT*6q-B6L>gX]]W/ikF)Pt-RBt[#kuLf2UY7!b=*aQo,UJ>BMs`:;\n OW-^1Mb<([8P0#^\\%6Jm:S@/^XEKLc^Y,:,*(!\\im5e%`3!oQm#/Ze2b;Fn.BPTur6!VS3k\n UhL`B4i#<C,5bGZTlM=.E=r0S9FOg=177;\"]62I7R3E8PQ<!d5=SA_>%!Y:=3UK<;dWY\"c$\n (tW)YDfc8;ObNDtn.<`mSJ<IGuiM4W7e@*YlXO%ikLI9eRu?:UPn+lt)pF84<+IEsJpbFN0\n !4_5T2/Y\"[O;Y;^`XG+,_qUW>9<m<HlPr2V-kgo[O<sn9BJ_sN\\!n4Q!>*KUb,SN<#cW?sF\n >2?>bmB806H`nheL7!$NfH*?'Ze+$@=7(H@D%G7r*`S\\]e?ic9`+E+=hq1g(fOYjkCBr7P^\n ^PXJ0Vq_#X]8@pji8*;5/!\"Zm>oEfF]f`I+_;nRX7J],bW<]13o-'ph3OO!Q^_Pq-l$5Mbq\n %+6JBqM5;WPRCHAbg_7+qGg5ZC6W):DR5eQPDt.:o>Or/B?HEPUX39Uj.*:#fEQb<[$,#2\"\n &'0RMNuYMP9'?Cg@fWTXQ%GR(H)O]AdFmBg3u[G,i4?OcR1KV)J5+^:_*>I(NN9\\n4ZhV7-\n g=E:k&K]1](OP$@HfY*2?e\\ml(*kFdB?lF\">K]ua,>?N8q;FSgQ23afR-I2Qt@%C_3'q!FF\n \\juGBekOZBe^_k!f3o!,?%i#ZP2KLNO&j6Sg+:0Jh)4$U2Vn4t>'8e-Jt(Jc**tTY4Le053\n -W?LlXC>I@NH_&.$fZ[Ig$SL0=YcRn7lEU-sm`=?R>6^\"\\@8L&77fYfHn,]2>5%4pGm@kfN\n f:tm80GRqc+nY>UB>D4oX5!j]L$6i!ACO--!#e\"!K9\"gmq[-?'AZ5bi!op6_q-%\"^p-q.:B\n hufq&XG[4G_O-/$JO=l!`DlAX[X^\"0V+h6Q'H_WFYUUYY\"Nf*3*<\"r]o')bBqfiQ^FGQna=\n lE.qR*LT9q)2Hsb,>\\22(#=*V@duFXr*JKShif5DD#%Ce3.cR%1il1LPVCbcK+ur+G<6d2?\n 7JJQ2q,hLK2+>=.Sbtt4DW>n\"B,uq.gb.W^?!MPq3bAKWB^TBeGX!43gq7l!L-[BQ6;ht5j\n >8tlL.,Ap7Sc2WjF\"UJoR^KTf'#[`jKo\"iVA&%=iah(o8<Y^g%#Rtn1YQFYh@<Lk-$*X(OC\n `82\"'!eS]U:5^8S-J<BjR*>Cs`G8F9dmR$oVLJSsnoHA*,\\?AhGQF<hF*oAn&F+e>7_*jCM\n qoKBB<1iu58KnVH>\\s'nZ2d@peSD8T`B<F>Xh=PY'3?98WsOCs\"FCE)hSp3Kk)bu.i4B?gf\n rk'g^@7),N\\kREto)^OW!A`u9hkZ/:/ASL5A5iG1g`.^#2V)7.Rh<;]0jXW5tVGtMEOQC(T\n \",pK>.&,s$QYaslCu3H#\"4[YHnV9(FAepm'-IZ\\;@;4#YD,t68D7=+o\\C_Pgk)2p\\7,7'-(\n $<,*B$.Pl4o4=.qr:r@k6pJ9-9(*?X_Qmkj1__2mQ@o^GiRq3CGW!V7XJCsHshl9BA1aKJg\n &qhZXD$.A9HC;`LL?88`:AtC\\GPWIG.58M)+c?:Y*Hq\"NB_.`b=.f,UURj^<#dBO\\DuC>9I\n WdcHboD\"E7-?02>gYcnc\"udd9O2E/t:l<sraAf4kL?C(CedHV*K\\Bl18imDVfbAJXQRqG%O\n Y@ofT<V8BINX@EIT:1_E4?KU$\\Yj3Y\"kFUu\"!dA:hAntsblZV^W7doO>$sbBjmj8N_15>6c\n K'uaSi?j<JDYNUK'kHb.f&$:El.GIC$d=#!kiRpkp;q7X<W_m9KJblI!I8Wk3-1-@F.)H1L\n 7)bQe*s7toA9lA:7^mgSoE\"A6-e+i51ro5&2_)o(_76]:>KZ&hCrR!>Pr;T%i3$jWuuTGo\\\n 8Wu:39kZY@goVm[$g&QKg$)+'%1aEXqJ$G9T[lml$cJ=cXja24CY%88g]*?\"Q]B:53G)TP/\n p8mtjYIo>5PAqXXj1B[Z6cgGe^U3UdP8p66.O]?:EZ:'U32@JO_\\Vf-bYE-DS\\V&mu*-IMG\n RFE?&UoB)Qas*&<e%!RaA<.:NM^COf0ol1L2is1#?mCd,O1?s?\\j$sjLSo<Y$ic0`K>Xo[5\n (E1rgk#)F]mZ'I#i;.)gP]^+4F`#HBk?)a`=`4Bcl_W'NAXdhg-hZ;dEgFFJ*GJ1P.n\"#Y4\n 832LG@P<oDY@-/jYnr$+.mA)C3gCI]Y?</!&FgeE.s*gYF@lQ(T2S/W-X8\\LLZ&@:gsY'Fa\n DAWHJ`l-+*[>^62-tDF=a'V4C[qXU[]%nFD\\\\_H2MYI]5!*nC6mgY0,L$8L&8r,mRs;LIE$\n 9?+8DHK>aL@a5?,Bm[:\"^6mb_*d^Q<5lO`)#Hq)5k<^F4A7QJ(FNC],tnT##]Tq.qp`Dm##\n WL5br]?=c?7H1u%OD<(IGfK?mj#9[OC^SuXrgjRLg#,l_NYU>.GCjO^9rYOR8k<NlsH$]sh\n HR>H\\^=lq#U_i^:GPAR`hgh?fJa/;JX.P%%c\\228j*qTRHh=H<#Dm>G1jGq8FZf$g3NRJVm\n /151nh,C;+!c+Raa#ODP%Vs&k\",gZ9nM.M0VFM@/05N4L-d'1\\9p1K<FN@GO_Ch&2&V::UT\n sOZH:&g;8Q_,n3Ef?3PY5R^d_)/]0UYXIPBiR)MVan\"-ZduEre0,ZcKMW-2(\"GYUXNpVl=D\n BN`c'Al[7[i=Z!2.4lBUZ%I`5a$=:8qkm@qp@[T`'0b=07^Ek5Lnf/l9@OPmfZ06c1Trrmk\n g?uWV;l$8HM`FCWIe-f:%gj-UUq0^1p24Mm(F4pKrLIIudBlr'W7]07een]E^rJ&@(ZeB8>\n gO7*)Fh?LKGME*%#DL(TEHp8f7YPO7G7YO,6.3`Md:nWl?!b9MZ.nYiHThAkK>$72O#d2OV\n k_f*p3M.^hLEA@o(m`_h`nm-nb`97H/\\:,C-W=E!s-3a/.hq%Jb`to_2raX#Js;r.0gWmZn\n NT=nC06'_oAX+$cFb&72!P$4@^!>-*aKc`N`rZ(rd/UWZ`.tZu$dPn]Z8!a3iCU>KAQ:Kcs\n !m,`O(<_An7V8TJX@-d#>+Lg1kHXKO-I'&9lIb;.2C.a03Wa\"kk;4NJ_k1Kgn=9s\\Bd2[IC\n EY;sn7V!U:j'AW%?cVsK35D\\FKYsHaD,n38i'NqXc:m?)A8((@r.7d><8TnoK'\\,!6e(!bN\n :/k3k7o7ZD;0Zp-'ie14e^\\MF<Z<5g;d*4EX`7Rs<OI*Wf<sFT-5WQ(Kjn/-/WjPr7`_$)R\n oXBuB3H(AV/\"]Fori1g[`,^m>F*'qE*Pl__fB\"+/]oH-k1/\"*?$C/EGMZDDghkkKZ%%..=2\n \"EWM?X*jJ)E9j\"bP[\"3OU?o(fh<(iRi#kL'gBV[u'+SVCdbe(u?l_@X.GKO5sFR88]PQ1'a\n $)=\\`+a+rP\\QR%cU4@\"T\\;`c7KBkpf8rUj;fDTV\\(i>am'd5)lA-WX=0Ol'c(TW2]W^UT3T\n Ko!GI`>0aF[/:-m0YH;\"IgTiES]'?qF>>!toD9PK-_sU`U*P/MWBYMHK`o5Kl+\",g,_!kSN\n $,Z2e57tj(>[JAgn_AU;aRWT..+Y#Gnbblq7l.-i\\m4jJnaoTn8^R+5)qOb+>u+T#p!;f-s\n )oETAHTbS[rDPfE//_ppX\"j`%X;:g58;&m1f<;MnW[DCq4;t:*loChW?')Y5I'PO;OjL0Hf\n \"+C/kc3\\aY-@%1s,@eo8MZ%c2W1kps;6r!W)dom1i\"g?dJO>da.ai.7Hf.eMIG/YT<iTKjL\n jR>Ra^`rWk%<,d8De&QmCcAANtcYu[UHK@\"cQ/bQd_f';'s$_A%bBN2WGUb%5Cc$lk(o*f&\n c#%2E,)ae3T%bQ.k@OqP>0mJB`@O!10Ck<p#G#le\\>YQ>WadU0cTbQ1b*+q!/S$U+bc_AlV\n Mp2Zr1kK\\pUD$EOELE]3Ggt7g>?3+gE3;\\8[+HUu?YiH&4>q64gD`P/D,&GD2]2\\PbM.4qn\n f>;r6'aK!LufZ[k^JTU.jX2OQ'0R%9M(X0-KO6YPL=nV8eY_sg\\>P3DLthJq,HUTA##<lS^\n P+$<dSDAZBieU>WYG^mTmC1Q]D%$Tilp8d-S`=O!8*sVipY6UX5Ei2<qk3Ie=c:fgui_n%H\n iN2I@upI+*Kt5,Zjhha?j\\PF;/?GOITMV!NQPdJgng)*D:&Q%1[A\"OEGE5+k61J^?,RchK(\n Wi11\"&Whp3OQo;8/!nO'LIM\"nM,=LKi-_diAFMeGC$Y\\<PL3.k^0;rp..3(:%e=I_cpko^9\n j@+n[)ONpKSJ)lW98\\j'RT\"5PcD&9@MfeqNP\"<C9C*>6h<?<n.GgTF3*,V\\&ZD\\JIj]'C`F\n _ipA4]Rflfd#NmO3P+!<Z)3GgSBRAdNHPb;5-&TJF=Q-MRZ_+j]q,JFfs9O]N:Qp?KA'<*W\n t1GW(Bm/j^!L\\'\"Z\"S$\"%0'Q&V)mk$-$0-\"LTKQ']Pr@E^5Ymp79ZZa1uig&tD3D'[GQP=F\n %r3NHoW_r.#-\\o-7?_)S>E[%-jHFJd19DWblMIhU,c:Fh,^DC\"sQPOdd1]9K7lrQUul(?eS\n AV*V%Z)S4:9LL$936`?goKTos8;0Z/4D^?C!1jY83>L^M=6pJB/8s\\?Q=\\C2lon_s`RGX<7\n :8uM:VZ]be;oWfRC'7e?EIOW]LrY+hb\\+c:3i:FGT,Y#.8#hPd36,d=L8raKX*&b#<SG8l.\n hmVtFdj(GK,,]OaQX]Ih8!+9AW6/V29+;+*+PL]Nq))$(LrPO\";Daa:6n9dGoFS&>a8_K?&\n ?\\3.F_JqB9_4HOil6B/5+d+AWTo[QoTR$=kSY!hCQgV8=F1'RnIL.Q>N)D^=FQTZ^gE'<47\n )/Db_1lD'*&oSJhAd>O-ProHJIM3Zd57=m_s5^!!rBpIHc\\T0P6/$_Z3[khSiIFnFK#e(8X\n /l536?BXXaA&AF0>Q/d/S\"mEX=if[3/hlO#8o;-Q?qpQCI9m,PSA_6MQlj@reFs[CFd<>]Z\n P$<OH@5b*P6YKmkV1a_l)8dCuX&X#E*UrLQX8@AX@Ve]IlQ.LVqjp4d&R%0U,a$-Z^NaZ;j\n h1>bp\"nH\\)i=*j3f^(,hq8frAB^7QZ<g;afgCE6>btr9Sl`4CB8:'B\\X0h$^pDg&A*.YcM=\n X`Ec#Z[BB'69Ro7nU:]UitE/G!\\[Y']9a\"$^\"L$_Y&.1E-*6iD3++UD0;\\kLqs!>jX$DoZo\n t;G=LliRMg:Ur=II[G>`Q&a/Z<qX1]NZIqp'5f%:`)ldVs1CO>)i[F6G:>5F^qm=j8^V?6/\n 4F1>0YQ%CJC8\\plX#OM#.[.(6JC:IUYmCYB5]HhgA>D!OU/4njF2WjPL/\\I)Dj>4h!bT4UQ\n I!M>Ak5=D5oA4uDH3*ac6m0bpS,X`&+&V;_+0@S/+\"-q'?,Jh'&GFmDgi4htQYbOoZ^bM[A\n m7XBm2mDEet8&daf3CrAocuNe!0$U<M):#IHDVXF`Ugnp=&1ak8Gl?F5DJDIiSCM>mj>JJ(\n 4_6<h+d?2u%M*T!ic!ir6Nar)'S!rn\"lfeaC0&Ag$G7D!Z\"Zm##?*Y0LSGf%;V-^^.+F#dW\n kL#UIQMmV_CEU2KEpo'am!muIJ&c*G6K7e!KCnBV[$%i#7Ba>#5Fh!3,S0-V!:YT4n2*oZb\n `0QRIqG6a4V#LIr+\"+D:WoH/V;-X^s1!MoC,<=+^b$-ul7OJ;F[VVs1?iGbsYYAW=G[Qa/%\n b@bqkYep/$aS5llbjU:SDE?g]Pkch/q5[Wo&E:,/V%/Mi%aV6=;\"@;@\\E;05d*%%<c?B+6\"\n T5M3r.kj\\m3YhOdh.V!<mTLuYMeZ!V#F$#'$d<PW\\Wk%2X8Ok'?ehi:]/e+7_R.R'[Fl%lg\n Y!1<nHg]!KDWsn08!SB*-IqBTP\"P0K.VppB.[Hn#E2e0nPF)8D?s8(s)FT$plU$=W*8;OK`\n ![iP>^C((=W9h+cND/_p[e[i:IA)puD?&]1_[ar[8I$UpTm&=!PVdg9ua*NrSeE1f7RW:j&\n f4:c2LKAR&6p@e[N$dL+.:+5lkb!V9:+NKeTYgdtQg>kr_c7n2Pnfm17kaTreqPhRI:U(FK\n [3Le0qlp/I#PAXJ#3YLe,cr?UE`3Qi*@6ctTa`pn\"c!^`[cu0lrbY.(cD:Ip3*oDV'CYf41\n 4l=L8H9>u!/<Q8dZYE-'T)?c.F8tPO^c+&.2Is.!q,M-#g3=4G/>t`\"4$iJ%C$b4M&>Wn),\n eas0NT.?f,?6c)KDQ-@-SX2a;Ts9*)c5Y'([bSpFh^+2PI/Ai0Ho2fc>,A*Di\"-Z/5kmjW5\n jP*g7Z(1%=.`\\KA*P+4#-QlS0M;\"!DR(j\"Sk'muJV;Bap4D8!4qhOQ<h<UEXb_99Lkb&i1a\n dr?JEL&2&#8;fa53%4(3:&Q=-Z;&^h1LF+\\1->bmYZ]camQD2fO3RWC<$:Q@=s!X\"$.*fdH\n 0i9B[d4)Ap($kfJ8pr1KN[(j4_%CYSd<(?\\^FRaK(f(5bC9]=pNpuVe)04=\\9MZQ?pF[-V/\n `A=#J`@$!rBQST5h$<1'GB:(IN62`3Ph[KP7Ku:-S[G.*R4aAOJ<k:m2iVr1/P52PX<PL1C\n N7[1Mjjo;`c+C6O`N\"psVk2;c)P]<CVb],*#e%P@EZ*rAKg%8(2A=:3fB))`Mks,dA\"/1PJ\n CqOX:d2rUD6^PE@3W.2+IYlEm`BchA,K\\N6qrf!DO[Yu(MM[\\e,\\44D!tZDT1R%2R3R4VG\"\n _9HQE^k1[,[:=)DuEJjt'#sP]]5;AWl:gZGMh_!d7)1f^B_9sAr,sbNM;:Qad'dHUH*Yi+r\n *J:+R;[l'92,f\\N6M3Pt<&HD<774C(p,\"uU1FlI)77=LRpX03fMa$p$B/EV(7M6R![;pV9C\n Gg%.%^^:I1M'(?CKQU68.?4k9bfUoN;RdZTMeucCSa\"kX#TaF-Io8P<3&$=:J12'9.aF1Ee\n OK+MX34C^64`]oZ5Xkc!>oC4>7p@FlPU,LJ@+M:+`4WeEHAmh\\],m:K#ES[/1\"a!FUZD/[Y\n fR()&pM((at$*+A.<'dmHk-XrAl@b*.fiAh*mE=\"N_)HK\"2eMgDb7m`J,6IFakOJ,Y)<j>Y\n $QEr/T#A6G]Imis<1XoK,PZoteC.6Zk+jf+['mTQiI5TG+2?_!$:Tm9sQ@>*Z\\93sb24&&Q\n K/aCh=r+;F<1OXZX_X/ue2=X<;kI:>YtJ*799d+_[(ua+ZX#>Q'p[NIk$ME`,s70J?>L8W'\n @SIKT3kUk/1.tm2?,jRnR,8@:\\4'n2@iVb(NGK[$pg*t!E:%)h&A3h@i$e>(Gg,62Y8jD&Y\n Z!?[R\"E47q;9bA62Q*[6o(:7mf1;<46!=&b/kfAs[QnG0I?oo/Ti(01C__7F9Xf'lc]@+Z4\n =@BU+!ZmU'Z\\ASIBVS^s<\\1.LGMVcf!&=j8<t2mQOD[<mUqCUBpB(;CLg;f#8$>OapNC.hf\n QX^'7LD3W(Xe%'?Si7N$\\Ib!H[G4-4?o1g(q.sCes2!])S\"\"]]2?nmhF[h\"$eT5ekG:mMhJ\n i9;k&VB-*%F-nV5(c-eH2QfhF+2IhOpI0267tau5FV[Pk2G]$-;g\"9E6^M'\"em-@!BiT7FG\n 4GZ&(ijiM<=H?`%5rE!epR:9F_ENVBQS/op5HH0GA1'8H)1Zi0>D69KmK)bHL3/.;hk7;]5\n )M`Hh3LLf\"epWb.O(e'Gf\"UQI,[jeCPDQVDZlTfBFaYlY^grDUdDV[H_I+mV3R@4gBKeEJI\n =L$XaB-E4?Qh\\/0_&phpumOjj.8!u;Q8/09jBK:+BV))IIZ2E7Du++a7u6I5qq?\\Fb;KXjg\n !f2Ir88VM:S6RrCr(ghG$;g)2OL4f/2E5@<1CPS3o1_j_Kp32<hh2%GTBMdl*\\W^,2NHo0m\n M>3Vdo5U3f%=2!.\\FY!8(ThGYJVuLo>'-<=[%iQoWI/L#N/jlraD5VDeOustNKh>/m`g2;b\n Dpl5ME'n:GjO*#nN?RA?J#-+R/_[OpJ1+X?eGa)E)/[L%?W[jOa8+#pD[O+hAP:l)55l<ff\n >g22kug'UVekn@JC8*%?t:tUq03`q+IPd9pKs!*LU,cH!]F>ATd6?L/>42\\oQdiDl8goQ[!\n Y>[W.Z'd?latGV`'=F&RnJOa-6]Gq$q)\\=7csTROAC;44I1RBqdWI3i%,CDj`1n(ft6_Lsh\n []@b(_H-V->d\\I]-lW;\\tGMB9'ikDq\\m5O4\"f]c*YXa_2V.bO?bf_;$Pf8nVjO>QL#oAtMU\n %=nf`O]N'5;VdK3,;%k*)e%>`62@;Q2m\\u8Zdg0=N*m$)SYZ'Q[(8trRT$Us;2#rnV:o?gf\n NGX^2l=,piE9k_)/ZiMpQmgYB!6Q[2gK$g2lNpB1tn\"X[u$L5V5^n]WUTG7Q^Ok?S#Xn*MK\n P2b>I(f-[n/Wq]>uFjl`I7J6$tZ0S?n\\h\\'8`S_2T2KSZQIop!8WOl^i7NY<21Rq=1Ym.=X\n n+YUgTOP.RB+5@9DRYr;ikEKQr?&TJd/n[TNG)C<6r+q7tL*+=jJJa'N=2oD.I_pE]ME,H$\n !FrNM=`7n#*)HX>9=+km*V6SX\\&_j0ZV5B_uauaU`)/m!2H?Rn\\bSu0CR!c7[M_pocGZKAb\n HC%^COWo.E,9*C[HDenUn%-'/](Vo2=KT3#T8QpgMgE@4(V].%`e8Zbrqk0']@VHKf<+r-'\n Y<BSp!I%`m([o;DAhqVH1\\%<q-KQj.p<$nRg[S?JY9XbJ=@:8[gB=A_kGg._A=#oRjX?7_@\n b&eEgnr(rA2o.2q*^r*<GLK5c;Pj:UM39e=07QSQ!N)>uP!<0mHp2>]%Kcmrgj0Vd\"A3)LI\n 5ZI><#j1]2pN(kJ&ZNN!n[=+$9hq3@r4Q`;%!W`bt:>cXn&Y7R&$X(W6kGHo?I\\',l)]Q.f\n 3P&\\^b`mk'p(h'o^U.u-5O;m-6)SkDOJ]$=F`SP\"noYCAC!R'@@p\"qq,hdHF%+j8db\"lLNm\n )8X<&@@A0B'B+BS%3lVt!raJ'Zm**?^*Y_?NH]hHc]23!.Q[<1*;!n`qUp8omi;FYr<I8r$\n ZHsg:HB/oS/8Hd)dp9&\"l1E?FqPc;cl%DS(ZEd`G:h:XLZk=fkf4kerBRS1YQicPl(Os<rD\n 1BrV8ZcAV*&&6Ps'8:A&`9pepD.t4`)s&EFq=YQX+l*4ad$1JE*2SW8!C$)j@7&M]uAoI(Y\n tC\\tciAVn-U$ME_'/hZMU*Q\\t/^gR5a5NB>?e`.VNu+CNVNILI3)&/o!$'!Q$`6+S(f>WI@\n Z6(s;Z@HJJcg`-@Y+$Pi060@fJn8dbGOobOS62DU1n/m-P+!I\\:Tp*A;IN8IM(1G9)iD:Kp\n g(U@Y&co-U!<[EDj5(os/I#\"r=ln[ehp1!HcQ5NIHN0VCZYs/ITKEI?gCM[/&^_f[d;m^uS\n /^V8cfZD()'Qk8+i4gfBH<f<diOSM+7oM>p,>:^*23F/>dajZp66='#)#;In7ZT0*ta8riX\n nJn_5.s,`Zn@5jF0#8*6'7E.3tKZ.?_j)/MYJX?S7^>k#5E=l<?5^cDQkoo^7/i=Z#>A8f\\\n \\08#9(^PaZGASOFSNg6F_$;QX*'<pK'<m8C]*YZU6m>7I1GBX:lWKB8k+h/KjYDO3Gmaf%F\n -2/cR>h=gr\"_-aC(>V7\"GL;`(+=CMIr+P\"NnZ8k%U(kT22k&YgLk'oOfC64b+D'k`FVq#O)\n RZ0)[?a1bj2L@$Q^k]GU27GZlhY2T*+taeh4tdS/alIL;m=$-;ER<rkqOJ6P>Hl`Fp:EK%p\n I'tNC\\W:+0.3C:l14]L*m[oLNk0%SIXa#KhsL79[L\"$/lhLKF0E_U[M'^i[\"$mJ\\'*^aAF;\n 5'IY`'Y,M+-C0$UYK<1CccknZjIXnI.\\q7'S\"5&]HI]<>7l@\\<pTl0na*T`c8A$*#g)9H>O\n $:$+Mp^7gTT<*5pgCFV[IZhI2s&RAb>$a!pA'*s^d&J'0Us[k:=ZoY3(R1DIkb9X?S%1e\\O\n urcat^iP9a]-@sruQfgZq<?)6`0-h*,.,JO*6ICU-$??\"QDG_*J%j-[`&\\1D0'R_2u;KT;m\n 9N&7B01^tt)7r[D'`CBs<-7o;;q35^;,u.HAR8hGFbm/&f!Uc]=rX3L@pR\\djaUW>2<_8RS\n (8mF@bCBSP@bcNc&65feqL#9>.0EoC0MI]W%Ak+rO[\"&f*037>Jf4@F;ss;eTBVkEK>6K!o\n ;sa?8o:SDi9s9omGY@p%s8HK'AA9@!F:1K4-`/(PC\\V<ZQo&`_\"\"'@[N`;N+2S0^b=\\lmQ$\n >=3<i!7j/3A\\2&W;0MKU&):1'B#3L4<HB\">?gS7ak5GFiHXp4&`K3YmLFBY$*_UhMkjQ_nK\n .G(=U.,'1\\VTj\"`8X<ECo,`:p!iZ=.+3tB8l-##imQ#,\\/BUJ2!B&91u.IQ8hmV7WQ]IEa/\n n%G]8d_!9`.cT!q/W3sH_XS!XlF_,,Eo+U9S<##5Z$`kr`cE]C.F*!^o.\\QK%.?^62/RP3e\n 2=A3<nk(=F+W:m4bmY.3K@%!gii+dVWdc&o=NpBSeJj4Gcu%Gp\\@!/`;DiKDk?nlrfdTN^l\n O^+lp@;n-gl=.`&eEU56o\"?I'IctoR,Oi?Pn]5)7VdHV\\(=mSHX#MG8UWgk&2;R_\"8^Yor#\n Sb#m!s)o7/'6rsY2s/4UQG'+#dHN?QF_7S)K<$>p;%W&U[toGU]/M@i/i6EAXY-WRCI>f*m\n c$PgOo=0T[]6SZ0XejMHOd+N8'[BgBEgco\"9O`85uKb0Skm>24V,qk(A]jbaN?gI8372Vs^\n fR-b/O^X&7[N<FjZsSa=H'5H]`lTGN(M(aW8I_BE4@dcrJC2@s7l]`RA$gH@&`u5H\\G74Vo\n RDr8\"YPf_r\"DgM<GO0m6qE'Hf&UmY+O-%R&d]i;,dV6&,cS:3ib[BhS=a])Ktb\\fq'fOi:2\n ir.Y\"G#o.pOp6ED@Op\\C0g**2A[;ZK9<@H$8<Y>G#u6<62X\"M!/G*UNKK]e%2G\\lQ()mG)j\n Z$br9\\1VR4l6Y5R3OZ_$\\6o>*M,+m%!0`Ap^md!<[rk.OpMoahenSe#^`^!mPed/<Tb0<0F\n aFBB@/pja7bOAHD&eh4usnJ_SKHbbHr+K0DnBLD-9&*0TOL1orqU<3_=_:0N\\GiT7M(iM^m\n 2[@j^,ZN-NPeq*6$7TL<V@^.>6R@Eq.ASt,[,N%BaFOl$jZckP'lq5bL:AEi98PMI-e,Yr]\n jdH3MR>W\"<B.<b@cJ&1EJCR\"\\B@r`4D&-oU'l_'S2gd_FJ9MI[8sll>AJA\"Xqese=$#SL7g\n &_sB#'\"X)YYH:<I^,d6GZ4I\"XL0+P\\dX79?E?\"-Z!mpPELL.=Z5Xrm'NRomIF60\\Q:<JoWa\n \\tKXT'.8M(=g\\$Zk6?<XmfCM\"$ZQj-;p\\k.qHAlG[sF$=3j[pM!>Mm.D(?Js(pHZ<ZZ`ga;\n djZG!:3?D2FS5Z0H4W3&JY-J5&=(Zba\\%OsXo_4u6>UQ;^fYI]0eK\"&5G7=m54JR=I^)+bZ\n %^GLee\"%AOBcoMHn\\u>EN?k=lVNauY>CgL7Y,5%1\"Y6$UK5%WrVcZB\"e-^PVE2(aY<>,g@C\n 6OE^>tp1nKmZkt8Q8cF<3#_k'JO:0(b4<JX3mCS7QSGH=YQ6_N4&`D/:!:rp-6V9#9dV?M3\n 2<+jW:2X-:i,`?SZJHan>eN=;J;PjF)\\t(*Z?3[_lSFonnrYL<!FJaXEuCR*?M?<*@mSRnC\n )_Zke-N()^bUD(V`R)<TLCh\"bbu'sG&l#%QDI#r=0aLRK\"U76;HDULppSdLP\\`]K;I%/q0.\n tcPGcjSN/cL^\"&^#L@%bu^A*fb@T]?MBoZV03/;J)*Wt2G&(K3n[C3P<l!/]J']Lf:8FdGs\n FERoZU,bR=,#buZARJ1BJZ3f!VDp(2;dH?+l-@n9(f$]?]IgTH`C8Q!D\\#gIPDC]#+iLcUF\n YG;IMYD#W@CWdl<Q`(8CA'Qe6\\IErnYN=0`rFs:#D$hX$,LjF#A.JH=Tosj2=cJsiZ(03nN\n <Y5ppO5HR;0Xlb8&&h(1OQ^H;S9Y-^q-_-d<qIc=ZFrSF`(#Q9![J90DahD0C9PH2?/e4)<\n /ZUr^#+(\":pZS^C_[^X6Zf7nnnoUi&[ud[`m\"c5eX9[*?kEH>cT%\\_j@^p\"[/MA1.iEZlS%\n cU)Tl/A<*qY4;2oEmN'8$Nh']8hq4YB_lu>k:q!WJ*$qH<\"r1tc#d*fmLKGBdD\"tXr\\%HfI\n _`gP`mRiW'=+2@KeN4F^[K!kD<q)#OcPLmjmCd!npr9\"Z$]4Df4%I;tmU!reHTu63ICH][$\n &j(8:p>ZKQ;QX+\"5i38.q!D<(MfOZj`0Y%@lXe?ZCI!?EhB>QV&q5b*5e+U*b/o0Pd[u,Ku\n nCcaQBi/3jr;j5rq2`qg'XY\\$Ja'9cfZ\":1$cE*DY_h:9W2tno;7`FY9Fb^`r,,\"9Y7eZ%g\n UfT9)u5aD$EL.QrF>^n_;pcu,KF>UVR'L<+IhE+T=g^c$9HQ%K7Q.g@\\SC:m2U4AfV$CMpt\n ?+L_a#+reZjZ$*e'bSRU-_;ihS\"<Y;Q/\\MhF4Y%D<$e-CoI\"T%?L@I7=X=(l<.)M2t_PAZM\n 89ptT0\"W5EKlc1hoA@F^.)$r]UgrIQ1Q94<9\"ngn\\GF7[J=F9BOpTV'6_fksdl'D2Y.i[S\\\n V'@bn@Q63nN\"MXV;q244.\\J0oo.r)XgllqK;1YhUd(:$\\mjVdZhu0!rAp&,]!P5Iq\"DK2:(\n O,&5Ul$1q$@+2$\\PBi#7LhB?ttj^M)D@b7AM@cE./!gQF7'B\"1jPF_-+Db'\"3a-_+V]^$l6\n Zha2*.7WXKcbF;hV-EP]h>YoCrs9@$)G+>I@B_Agrj19a)=,TsTO##K:CU4^FT>/sTba(0A\n 6FEb#5H\\^O.K,@u#gb&eiHq2[=_ZYG&'JVSC1.+.`Rd9(Q9K#(L`jlL:1E8BqF6^ZMLmumV\n \\Qh<^j6abURD]4o8E2m%(rO9JSXeb03V5d%$U[=8Pe'PR`2o93FA+`K9gmK,5O=i\"KE4LUS\n 4+]$*q1iuLe.fTF9WssTE5-aKVQRiHUjH9PFti;CV>KP6&+rs_)oNR1h0!B`PHY-9&pgTU`\n )P2b<a&e7\\jf^ghah9ZpsB/R&hLF/9+=56co[X]6pDI[(FN\"]Z\\g<RHT%+TJ[G]IE0PabS5\n FpoJ\"/kJP9$p9O^Q&eAoHpKZHP?ZP5DjHof?$l:@^551Im!\\\\gt]R7%EG*3;Ik/<IElP!hj\n c8Mg)t6hj'68O'SK5It]+Zi/.eRmd21O'GMZ7%KDN,nN$t'FOL<'IQQ7jN9R9L\\.GKX1S[F\n 3X0PCQ0_sG1_id&S&S.(2UiSdlO$8^B?L_R`ge$blcp]]D,4-<QmB)ECpuPa\\46ji),OkB`\n 8se5r6Nmkcf>EU#_)rEGYB[*:aEm(1rDi]`(0I=8.<MJ_rT$pK1qJh,h.Q>>0+d3P\"`h(\\O\n =]QAC&X+M_h.naO8PYl^LH;e&4A2*8K'rSCYVpf?oi8Zs;;![$W2qR5D#%8Y`=\\oUQO+nV5\n CV-jX+6.!QtWL<o65bJ8?IG[ZA(H%`FJ\"%aY2ZkQ9Z'[\"Rh7V(s[oOl>MBZh*q:Fu-64LA$\n SGY`Asc\\*N=PC1CV:-6[F8i7qo[6)jV4O__CP?:!Q=E&hf!mhqie.i&/4[[9milDKWcuQuo\n 1QBbOKZp6H9XErPN=JY*1XP\\n9_Aubm1N,.'>tU61[Pq!%2UiA(sQkec%MBWPY4`Fi_dSR`\n 8+V3jW;h09MtS$!gm>LfLCUgF+uP#bOfo*h.+XTEY>$J#9\\6o'31?U(J;@m:><`cm;&Efn@\n ',ecP^e&.s'$!CX69CYt[*h,]?>'q9t%?LBot\"-uR=!A65%Af;3fFZ'U-?@+5HqfA1l)*Il\n Qj\"].o]:h/M7CQ$\\iaAe)[<1JZlXURgd9KojYS/kAW[1H%?44P%n;,*(q72=??T@&=Ud?Kn\n aSWggb=Ac`c^WbKTSQsFh!\"[F)&`?%i-tC\\as4=rTcd7!YQt)P$.>L_TR%7s:`@\\O;Cf9hq\n <mqK.m;>u%&6B2gf-RGs`3r.qH:IjTf4B(ZW%h6G=].?gg#]No27)%*]*2EOfBb-ED15RrJ\n 5dfs<(2@%%>)J<K=JmRb`%3WAIC\\ULVB=9=H*g7jU\\\\GMq%@dd4J2IjO)'IaON/ic!AJo[?\n =NqP-*ga=[YkZZU`\\Z9\\FP/fo95@\\0d:s5c=rs'>7l0:\"Rfr22:)i\"^1a*Wr?0XCJO!Ib2&\n o>rG9pcnP^,@>)RJq1Ncm.p/`iIg;=b/7/5L/kb,F>&eIHc^iY?XpYCPjhW=1^o72Q&K8;t\n *h^,a9NUtnp_-=$n<*b,I*J@7Kps>jk_efe:%1M#4_UQiJ>XcQc9b?)Xce-JTgk+'V,`gUT\n 5X/9Q\\cn4U<E:q>c;f9paaMOXNR?:Ydk5;mR$_.0BR6r>n)5!E#=DWp@!@7]BSRj?g-'2rh\n 5+P5B%Gclf&UOD,TU'ZjB!BChHf9iIHT>?Y2U,EOqP&*(hpJQ&`Qh;iasO4k[m_K*XQ]SgP\n .3;V12i@\\PP`,?Y)Z5FU,fI^/Tg$?_)q.V86-=_I)'`htAtd\"uilC!P,%dS=Ti1<>J^A#!Z\n E!8O`tB:!Vf'cbuqgXu.5\"YjbeG/B>\"?LK*;hc6m.VH&$Au\"j2IN+DM-8/J]qo>!ee9rSK_\n ki7?_^hBj2n\"llVK*aVNWiUo*<\"g1dNe6\\eeK*`\\)=pNe/8EJE.jlTm;Qu/cu+9djA!MEKQ\n [I[uoAE'I<@a':'*bW\\kp<6h:gYM[8*VmpM^h2.S/?Ukj;`3J#E84c>XW>F3!Q\\cHdb*sj>\n bYV/%2[Pp<Fb]&j9:e+UeBXR*8n_+V\\J(o^d9FW[>1>Yjn=;W5^<UeIKestKH<f&mG;9#:Z\n 7+J>&/*=,BDm%bu6I*j]7DNNTO[K+Q<l5g@e\\2QpSq$FpH*:kVeakG*h2jFHW:C%5),Ak$r\n ,6/*9<l@]j<M9g`NHp#>YW>Lc5U[=r*804Qhne?qp2rV^@4MF5qpj+Pcl5'%+WFMAl>j1YZ\n 2:!6pV4us_/@#\\57VEm7\\I,,Q*eYk'^r)[F#Q>))ag#4iEj:)?M5E[I/b0Gjt<f4-4MnHIW\n `ib<I7TJ[FF%^CPhM*3<.3W8i2GTWPP)d+i[`e$V42Sd^!l/)rcCF.=d-89ll/pFVDP,[TT\n jm/Xcu*T51kY1LqJ'&J?acih`c#UC]]tWok9d3e/id%aa4266<A$C*(3e;'b\\*6I7\"u\"`4d\n Bo>6>+jXNefe3#\\(4@Jo&a\"g#Di5fNHW^4K&^)BU85QVGUN>iTS4chDW8Q($07$O6(5\"kn[\n B-Q<A$T+_@`UT>OrPk5XoU!5b4/#OjYd-I?TVd;VRFl/)^-<b,q<T5@R3k*%7Z.S&M4/T$\\\n *D5>>A]#e]9g]jA+fWO+KmbfZT!o/5d5;qOr:-EJiYus\"'lSXml7F4)MI#ci,OLRr<\\9*KH\n GjlLmh1]DFcr1/LG(WLRU\"8gNrq'm4okY\\._;8-pVN5%Y`GB.Kn%Qht%[.M:5VGBF0<ZR@2\n `(%mJ-9XsJXBJmLB[0K3:K]Ko;6*d57)'84L0+BE44A;`hV;VCigHHoHt1,cOk.-&ofh0*)\n @7VNtj6:(.9cuj3Fl6Y8K`Ok$6d^Xp4)aVWhVfD?Wtii<;:6:K-)%fERHdKV9XmnT\\jC:[A\n --Eg!88-S'!t/8S(CATmq:DNZs)0QQt4)+\\b%G09JJAG0)9X%6:rpi^^lBQfGMo7o@\"Y6K'\n O#BR?'F2lb_(HsAT$`l!H6WZS.s$G556THdSoKg6%F\\[$cGgRS6A\"MY'[E3;=Y=(k@?uC5#\n %XI@mHL?6/j;Mk;3+@X;?3_m'`Kt1]FqImHIYIkN\":J5jekgC9);Z,Ig4q.o/f`tJpiY0`=\n #Do)[`<P$r:V18A[YiE2i%3aR/)l=#$iX._^>)L2gN_.o9X7gmqm@U3cL)NE1U_:\"64IrC@\n -aknD+HG71=%BW::BdpNr4uB<1G!X7regB30J&T,2UQIWWT7nYA_Jjj/&>iIf&[#&0D!T=<\n g!F1%>[#A>oV(KdoF=hLA1b9$@$Iun]cOaIcop#Y?32dc.EPkeZp?F+\"t&%I\"BaS_/U,TqI\n 9+Lh1(bk]jLH1u*\"m[SS5drsn9k'(`Qn\"\\BFUpA=Cl:5o*0+R_PW::+9HCL1GXUjgd`Un=q\n GJ<&4n]Z4.\"a%1tDHGip0'<$m7We.cL9NkeQu+6Qao7SR2:,kOBLAsnMu1D1psr=>it(qZ>\n ]5)d]_=!aG@+9m`:(acq+s&L%G?NWl2R+GpjUJ>W<<(MBmeh:J*1Qopjb1jMV&UU#6fcH`e\n rso1)CCU6fLr+@+HhEBZ6`$Lt$Sb2HR7r&h+6L9dQ#q,uOr3Z<XT!bU)iuT\\a*8Bhg$SH0\"\n +63*8#9'IjP%NCBX?)FKr&17(_6;sI?IU;`uiX&^_CRcSG#=rgVE/NXu=`FlJ[#AYZWY1md\n %>](?>IFdM'\\m<@72Poj=I(s'.(d%UkH[N`iYo(,S2\\V7lA22aVi;%'9b@WO*SE=`Pe/te2\n \\fDiM8Z1$PFLj?4ZWo`Glo\"Y\\B`i.[C@/JlNRmi-6!H3k*%ha4NQ's985!R(0:U2KFF\"rkI\n l2/qlk$c,Y0V$h6gseRh@C]dalFWu)W$db'lqkj1Ycj!PMQ95r-j-&^ZY@hs1f0S\"TcE#/.\n D]t&53fB_2rIR#Jq%2,mhGMX=Xgt&Bm!4SO^Ni<?*B*e7G-oabk\")d6pbE`K=D2'cY$;N,Q\n ^5Uh:Ud&\\N4(MfG86*_4WeJK`(nfoI1FnhcITa\\ksG,K]*GUFF=uXJI/\"VEr$LbAu+C0?_f\n Q].qMC,fD>R-NqgS9f$&12U2O-^GO5WPj(9Te'.,<S297(AC%Ucs$3)!!L6!uoJI2!N+Q52\n ?6(DX2bDG^XY!2p'[8L0e!05_:Xg*g78_R\"/M;LEa7.el)kiBrBEi$b@9HVgSS_Q^'r?\"c+\n \\4J<K\\,n^,)TKG.OL/.#ka@@=c$<[PM+NEB5+5DWb@\\GC%\\lMgPLNBV-E[$P,]uj,,]I\\Wp\n 7!7h,e@?GHBDJd<MhgWq1S@(X;<XYY6YGJ$=lt\"NiKE/dI\"aXSY''@@17Se2;K*,h\"Z2Sh/\n Q)%H]M'j,NYeO1=ufP2WuIY\"OtiNoj=041T.Po4AL`f(BTOM9'V,B>mT9kF(adTBI1'Kq[^\n lbtrnX7q(UIRYN_((hri*:E7C.Y,SElZ50bj8((/G->W0gXXZs?0$,Nc]1g2O9\\XC,2pIhP\n iOD[)`p5d*e/%^D:ik_5^X5.Q(/(-P=n/9N]MB9]nXOM<a7:42-->_>!>oJi[;hnbF&gJ'?\n 1Zk]ART\\H%o$P9Q9SAY=^>m6AQg+6T@p$+]rc$mf%PIgpK#h`E%*sKc/IIp3gY%rMZ)@Uq3\n R_EI:!fJV<HeR\"oQ5`fKZcqH[%msLLFO\")U%,bMcGUC\\BZc\"j*:=RggiX07c`YK2H0M7\\R4\n roAbhP:Fi4:**+O\\m\\QB:Ai'[m&:bDr._8JK,aIO9FYV;oNUsp!'=%@4DWjT?!esbo4KM@:\n L[W][tgFI)o9s,6ijNa9\"S1m\\ihAS>=nD>2>I8CCS7Dm(Y*laT0*5gQ[5hM&.i^?@p;(a1`\n fUR[bd,Q/7EEC+L2\\f>>U3#jAcT5'W(Yp=8N)$'U]&f7rh1N(X91Y:/QZ2@5jDfBZH/Q_EJ\n K<Sl`fDEGj[[pcnm6)%OA\"!d4UDPhj>5AL:LWZ^f=^ialem/29ng;a/G\\15l]Y,XNkWtkr7\n MdXA1uM316u&AV*k/C6.&&ZESs!SI'Ju8c<<kDCk`1nr#_ZcEt8iD!2-r\"K9H`b_=kDoi?Z\n N]/Ue?kBMdD+Cb(4g9t/\"ejY`6,2/a.F]#0B;T],KoLOl75N\\Qh]LTItU;m(:=g\"eaQKLQo\n U`-[-BK,(<&=GlWgcqi<'(T7G6+]46L`^n??enf,q;5r<sf\\Em0PJ)1#rea3Zp@2YIaJ2W+\n 5ge2U+t3YKUa&W']m<@ZUkFc)1-L<48&ZaL]B5tdWgZMGeL)f`n<=I+;&gHGrMg\"\"IqN.G,\n &s!uVi=9I<A(.Jep]iE\\Bu>WfL(Wqc5)Oi_LluJX%ZV]1)eZcKQW/ael8b.X$k@;;dQn\"(?\n 7<RK6`sUjh8qVHJjD_LD?SGGZ>*A?gIrIYZ;7N7,d8lLYu#G,@5cD],MKZeWHKR\"u&jt%7)\n P`ATd]a1XNYbBB+CMNY0Qn>!d3tA%TUQ(9FL_\\Gl'UI3+JLNnRA[$V>%a/%8KWJk7J?po07\n hVUl98;jf^el/g$O'`R5eG$#PM#i$7!S9WZO$[(mVft1<nEPVZ2iBm**X&X?66-5+3i=*l1\n E0b.nfMbu>9[nd(])\"cRD-UM^3j*V^r`<ML2MY-&QWJ),?sF.ln4!^K[J2eYHQPGUI?'4Aq\n T2OPH\"F(Y@'_[)A'g%ZB.Wa\"NOFRsP?Ub<h<h/[<jIY(X'J3^Q8'l?ejJ2.CIod_-c\\.5Q=\n JJVDs;A-\\1aFI8ZHQGAG*uQf.*B7)jpU7M:W'Nn8*uU^,nj>Lr!54/nNhNjMu\\)'k<&D#%\\\n :%AgQQ>eUobdXPGZcF_2Tea#[Q1[=)h-p7%E*\\R2E1?*jZg%g,@D%X<hsoL=\\b=t`?)Ys:3\n ;:(boV6V:d'.i,4`RBl@H%Q_cnLSIS:To1uFi^L,0.#k-bfW:oYh-@O$p+IrKb!G&MD2gEh\n Cpt8DPZu@[YG@.2fM\"(Edl`PNp-qW``p4sfg3o2-^dL6C6u!3Oi''ZnNS@ZUDJdoNiQ(H#*\n <XGkN]bdZDanTF=haT'mG0R>Xn(=?F$+)nn\\+7bqesrAIUC4<39la4gY<<kE*a!iL/@.VA0\n 4D%/fhi7mM+YZrsWVD3JQQ8T[VtO;;rs=WN?r7jA,SPnlYF?3CCj<4K^qR*aH>Mc8XlHmi<\n 6MH-Q$U5fal[iFH_\\ZLUc9afL\\>%:J1]L>;FZr@b$ihOHgrnB)cHe37P?cW<&\"kM:Q)G3:I\n 9S[Y5!hNMHT<rDcbn':aTqtE@9)Y,jVS@uMi5Iu&FmG6l[kT7Y*+d^ItV0i4Q_KoFCX'RC:\n pr=2gr[p!Hlp[n!%OSQs9l0+<;6/a*jjmJI=n;N*b^BTDf:J\"dF,b\\6q:<IHR1Y819p:aK;\n ]Fq\"nE0t;IQ#1ej6n&XhL\"%d1o5GNWnh#?ebD;Z2eQI1gW/G`50LXO4`T@bWZCfZXJ3Y3gM\n kh]hgOCqp\\t;bb9Qd8MrD/'In,%f?5*$WDCbV*:PmQ71QAJs*QNPg+S)%`<Ebtf>OO8rcSi\n cR4TMWqf'j5X/nh^GJH;rL0eZGG036`NI0-R%p'*MM@tNE#X:lb]*<GTDDo2]s8Hc$L)e%e\n L!?)mXdRWWIps<D>O-&[gPhkE)lqhZX:$V)InBZ$M^M_cmT_rN\"3Zi<8#k3r_0U+d&,`!RP\n 'k*dBmfa&:dgD'addINED[td1jKgHqrf'>T,#7\\?aOK\\Pno$)?ciV1J#3B]8[SK6jlu)oC8\n G(9q\\#kDJDcm-[?M3e?\\BL<LUlIWnFU<$s&Fg<_Mn0uR._l%q(u`8G&7XrZB\"`.ulgDY(.A\n [8co'HnV#O^0XYHC_fg42Jjktr*/0i\\s*'H%&u#%_-K;.U(GWtqnii\\0$o/2\"gn&FiQZ$h1\n n0m6qGe,1S;9%57YN0pHp%g@LE_jm_:K/TgWFBb'VROjG<`:akM2qNEW4kTbZciH?.@BH0=\n pmVuAM1\"@:VJr!k-'$mpW,\\lX\"-PEK1''N0fYr):(3r0FNc]LKM0S9/ZaAKd(iDJ8O1)1sH\n g)ZtO#_MjfE2*aQ,o4k0,4$N^&(q>1Gmgej(^r\\0&B+T(8IY-K))76_EL.Q;],C!O%T0$a0\n rZL>Y9p8N)_Y2%EcguY.`h.o\\D[]2lM0*H)(;eM.-3?,cM&@\\ek.[\\h+Q>p/E6JEF!!uS+0\n ^\"d1'#YHW>&7CLQ:4*j?ia,OY!f_/EV\\j^t9K4]-://,*Ln/E\\S@#kq6]E,>9U4M?+sLIf?\n E3(ePS]N(YG],8gkh)/`@DP8,CJ%1Wp_-7/BrO%TN$XN0i%1?1YJEOb\\eI`W_0(SS,OV'@Q\n *8MmbI65#M);&UH?\\IroJ.PPQdD;?\\iWumH`DN_C4d^]Vq7f)Q0^Z!]G+o=+fM)_i#6NKRo\n +k818jZ/Nm,1E4mnT?K<i>8]\\0<i8GnjN$:oX&X4`=iZSdh<1N=OpATOHO$,n.RQGq_GK,%\n h+'l0_j;l30Rik&HSUGU#`HlO$BuL5ND;SY4jep>55(Z*m2S_7`dQNp2.-RRa?A8Z3$ND#:\n n*V&#b)!d#C:)3CC.P)QD'fV.9c2<Z1M\"/i6?V;kktj)_VeG01lC$N\\`?:6R6Z,4/s;TPJI\n 4jGqg\"\\O-:ABZ<m.oeNGVJ4ba&%nnf<Z0cO'S-``%1JU/8$OWbE%9(]AJL`RW])B/*L2:,n\n m&M6:@cSi-KD3Q+.dJk<\\-Cb`q^Q.1<i85qK\\:Crm:A\"&s@HblWS3$:5)>*r*1eU7p#o8]i\n 7<D`pFC.)5\\JNW+7ZS?>$5kNr]gkap8$=R.E`Ye2K08E`8@'HXDJK9;QW0_+-P.R[;`-b6A\n ._,'*45H\"FRrOUBdj(j\"X]TVnt+[#V$>Iu6'N6].C1rdV)NB]6DYDl,n:@\"QlJDNW>02P25\n L-Mp/(Dc:_ZQ+o`%aoRmdtM;&'ToZs:Jt@)GtaT[b2I<,F<GE-F/jo!L1]<A^I.3<5;!!7a\n G-_VIcnD+R[]@'rgo[8e/[1'u@JpE_+hFqnG+'H,lb*l.G50e#dnmnAYs9_?RZo[?,^[k\"k\n I:%aZGmbS@@%Md.^*>TN(2H8(TGd!C?>;fno(1g]m]j%p^3VC9YQ?'8G'jR\"A,IPiZ&jWe0\n [f7'k7ka[.E`$.BIlrsJ;mRD]'gZSR'df2;?gg]s,<nc^+:a)**J?ReG/\\9;&?ip/*F\\/ui\n Q1=c.7#h>',?'leV.+g[8![eA.%j;<qI@bZ5mBH/=+Cs2[$?.fH0#F#Qh,>p1Itr'jHs6>S\n _GhFiMlGIa^,aZW\"2\"[3X7eg*Ut![$/Afp6rtNlODF?-2$ikG-)7^rH5OL8ZRDM@n6lXQk_\n p\"*L9QAGBJ+J^`S8.(LbT15gUB7`;'&[KMh8Kp>\\HIk=oq\\=OI@k\"W(<:gecr:)SscACpS>\n P\\U1=*%KoN1iD^]h`Gp+HEE=)k[iJ;s,B=QF(H-[XQRd+C4'a<LBXD\\'[4>rK055Y/,us2D\n lX=,p$$A(_?^'5eec0DZM'l]F\\fnU!(VPEF./1RCb99It!SRqbZq.P9Gnqs\"(,:J[a\"%MMA\n !;%Ff:sk`qg+:Zcsb';2T(-VBniPp(/1oZ\\931CbC(0EL\\K&AG&Meqh.LHpEc*70W5E:*B6\n ,pTIhgXd<foK5d9\\PkJ-n\"WO#qlU*FDjG03;3:[]su-(h)H(&WI&<2Z\\Zcfo</$C]X5BMuc\n 2OH#;/sKNFJr2k,L8-$g7SH<*CZ\\HEA_\"<4&u+#r)=3>?+Wc5r\\O#@_+sGKGW..=CoALXp$\n m<)\\U^gPGQMEgPmP1Tp7+L@MdI;Kk0r(\\j_LXYBOS[C8ci\\@H?V]p?1E<,u]3F\\@:9N]f[M\n YF-2o3J?X9:`f]@g:6I%(>gU/8Rj=>q=GhJQr?=oObL7;mGQ;nTpoKdLRYie6Rr!BbG15'a\n ca1\\P8VbEGL`7/LQf:);)dHu(mNKp7pQt&Ph\"BN(o:Nk=*,<a4BG%'34(4Q:H]O(8D\"N*=q\n l>T0FNG^)e$D`3PV;7.,/0rl<rP#=cuA/6VP%[H't?>\\G4C[<)B!`:)U32jVf*^G5#/jV>=\n Rb@8?]&bE@0gVRb$9qK7TSfn`ck,1r\":R70u`lY'Adrn1&+QB.Z*WEpD>;`Y#=3FdS^4dOa\n 7oN?0m=r/+!,S4JH*nRlu3lS1:'obNW((0gF,h&/@n\"\\P+lkc-nGF`6SWK7neOB8@q%*<]S\n afi5jJ:[1p!Z@mRc*4ctP.B&)g3K6u+,JV->Zj7rG:TVYl)=FJF)]0b0-t]-8ZDOeQ1TX#H\n 4*[JXgGM1N&VJMg(js(JegaAYM3Ko/.mmZj;hFWUUQMVg-LD7h5\"r;Y..V$g/F)6qeu?,[T\n el59)K)nDm5]A\\bhqQ\\p(D;BsF+RLmoEKRY.29-N5umEu@Rp)_cG]QZLjWJ%%eP%lLA%3OE\n R7Wr#G_4&o7QUE!^AS\"#VV47p->:*/?b@T-d)Fapktor^<O=Lq,^H\\/EQ?#O-\\HPa(j>PH!\n X;AH,X\\iUA=)khY+WOdB*]%fRY>(<g3\\$B1mBGuec]>LTco;PqO%,3cA[mDKieE'd9FP1;L\n )rV8gjd/FH%.`$kG7DEZM9)^uGJX6SU#ZXC8Rf=9DB&rf4:SH8foOo'V\"k,/Tu%=7#T\\Kf6\n [Xm;1d/oGoEV+C_d(U,4Op]A4%.i,`&k6/r8e_79,Dm:]BTdCD*tsR5G*;IWO_u6fWSV.f>\n d?O^\"Nq9GRq1rPJ1NP&@.\"kgr7]i.&fMn+(=rVnsbZoENSaeb'SN*]WCtB(Rj(JDd_]G!Qd\n StMpf:E1r/<EI+,u]C\"@X-c($q\\4Pu?LZe)K9cEH'Bo(UH>4eDE:`M[:[\\Q-uqd@]f1d$I>\n Ndi$1T\"/,!p^.ir$UIfXFg\"$&7gZdW8\"6pBo!:.<[auag.Hk&pFmA/J'H@(D6i7NQZlO^bG\n hXT)4!QlH+?$q(tf\"BVch?1#'F0R__B\"UX)h10To]8:o6]GiE^SWURT?bH2;crjZ.)ah<-X\n 3j\"'d<`-6ko:!qE#R]%9&9%!5#dhqO;;9I*WX0]HZ;?\"d>qHu\\%U?fh:p*Nhof0-=eVLgIT\n P`PO&dB\\0:i.-4pU!eRG_@jl1M7<p2/bBX5SHniMD14U*7ie`Ml\"aZWprerLEp02:/k@j.b\n )O=_lau*\"(2m)u:lET&oBRRuS%]\"hnWOhJ988Djiefe6EZ)rC`t-:QSa\\(q$(*T+p_P%Y.l\n M)?1f9rgiV/Qe))hl90@9ri'NoXk5c)iV`<,4B^\"%/$jTK`b!3W\\RF2rgY/7Jj8RZXP9q2u\n bq5)!bT@Yq5BMIe[N;*uJ6L^:3^18@60BB9(dXr.+^c&d&ej4F'1!ZL+]8jOVA=^G#D%%-^\n gItOfEK%#qqo$_s2Fn#ao!7*r.!&iTq2`Z?lPd,#(PJ.+5d&^l2H2\"ra53p^[qI)p&Df%+9\n unUFp/#\"_-mn\"<#QV\\L;Mos(kbX+'o>AROa,A,nhtEZLlOlsH.8iZ44l#1ZY>O!H97bj)3i\n E\\24I>'':IA<Gs.cqkS+pM%Z*WL;<\\d`<A'\\6Vc2jpeq:6k0NGHub,WEqZWjV77J3\\h50%6\n >=mVH425]&B[p#h4Apqhd=1[2Tf9U[#<m\\QfYIFEF#75pu%$ce\\7Oo.1a('-,ba(I@Oih5>\n C=\\,P2k&$)o@b2M5\\R95l#cc=7^#goeEPN<%?T%K[+Xhj%2#b`GIlXLpY6eWoPC^EnTatL7\n k^.PjRQJZ?AcLqe`h5QSKYaH[aOU<qjnl'LiBS4H$oU08$CJ1Bb#OJ%tDXaoD<pM$Po,mp&\n +d'YQOn+5JbhA!h+'j'*CO>6hDCb7[tP+_@Vq^$:=6P1CHQH`&8YPAu%X&`\"<\\V&k(lTnn\"\n ==\\bLWR0na$S7WG5>)b0A9EudbjjEht=ncXRg89,u5W(!WK6>rEhl&K\\?P'!BFatfcj.gr4\n ?_(85WbdT5uZNRfn9Cj.?0,Z,?cSWl[<80<*k5`7R:.G<\"A/jRf>#c8)35Ao2+YfiE!%+A=\n !)U$c%7F'8<?\"?RoOT19;Db3t92\\a..nnC`eN6N)o\\Dl1<)j)l;cL.n8QAW0)7DO/B/r(5*\n i?2oJ\"OdRNEoV.ja1?9p'$&E+-jX=>ajsFP-.r&rKsfA$Z2QGg,>e)[BB5?ok^f>gBtd$f)\n <>+ZI^<OF'NoPb0Vth?/![`NIBc229iPogtp;fADt$7gP()7/n:N(i,3V?lT7'q%dL\\;*ZK\n iBm\\AG,icpb7r'%X&mu0Fa$iQ,r\\HEk66!50F\"2fCP4-`1$AlG!`d2ld0&gj<tIb,>NF.Hr\n hk'N_5q?DSGBR2\"`?Q2Ltn2m'D,c.D2\\pU\\8baPE,X%^+Ch)4MEeC6;kk%QG>%`TX6&(L8X\n ;m^Cg<nk\"Kqe\"frDEF`Y]5Cil&8_l-):hk#a4]BmkhINn_f5NCJl3OX:g-hdelA3]E]f>`B\n l`pN0koBijg;^+2YTRX0=OGEEqIsZ;g2N,(KYn=2lC/5h]8Q^J)B)$qVknrjosW\"h?FYOiQ\n i8_iaK?th;mR_hDOJ+3;a#CqCj6jlX[`L?0u3PhHLD#!V'i<'k[!h`;KX*e+J-=BA<0/s+_\n /6f*,m.GL\"55U]!frY-Iu@p9'_8l>R5\"fNjArrY1*C=TH^s]XN,+\"CQlrJac\\H6\"h\\Ni6mW\n (TkFOk+M9lC+P(uqQ4lT0:p>^WpE)Z]fXTn2$ll\"eL5o!Q6[(<r>d8*dX)]8J-U?nT'&n$'\n (\"BgNOCDL#96I+Gf>RDom9Q3i?V]G57:lPgimYV&%h:6HQ]2hg.hR&(Q0(P[T^uYbms8u]k\n rjbm*+$85NfS3B1;JJn7]<p=K>J>Cq#MUK'SDL1(.1W5RQ1VWq@Ea&F$I%5e6iCXJ21-+VL\n [/L7Sp)qiC-$4-oV>V'VUbQAlD;^:FTjCX&G]o!=hCB(J!-H*:b:X96kLa\"57FC'(s;_-u0\n 7MZ!N3,(*$\"ZW=ReV4t?(,B0%7:&n3smRRSnV3m\"U=,(m+hMomM<.&@[7bI:lAEcR\\i'c5M\n %@X.>Zjj*YG)X!;$NR(I`a!fm=ffXJ=YBk[$3:nq\\8Fi*((5#G0&OL/2$_`7d>`\\Do3QHqc\n 9bK`@8NJRPTBM(Ei]q+0clFU8'WImkZBEWs9hK+g.o=,g0ED440SLe^VNfZ$,CuRh!Hc)SO\n N*m8k92No'9\\au(1Y7=Pqsmhc\\QX.dS3?-2!U=VM6gfoY.;#B9iU#NMro\"Zq8jE841q+;$F\n <L[a''NPAtBU/2-0ID4_&U/Y*%\"Y=*a^sJj?d`_ans3>&Reb'n``V(;j6rIQC!/q[eBZF4\"\n Nh7V&?Z94<K_NKHsY6FAA@<1_E=gHfI('q_jJKQ;p2bWgm0pTYLBf2G.V5D#oUW#!sVe(KF\n mC)od!<?C#HWfjgUA](M?:8lE>NA^-':5UtgDUmFUDJKC8G86-Z7B4OS=>]B8Q+$-_$0PQ'\n I.iQmepP0\"nNTj39j$FpGhU>JHuG;A^6dFJ96qX2a\"[#l<)ol\")E!%D&8r?Dr*KZ4<G?DPU\n qr@P#2m-7KOD=F%\\UUbNe+fjnCAP,U82Z:]5:?K(*TUll=%meH&?J/A%4<G]A-#I@I?<8\\B\n _+Tj*@n1VX!fb)#!6#2>_O%&^@pfT'b*u\\JZVThdUeb-S`fb>d$<QA=';XKgBrA7j.FG3--\n `ar5\"bA(1TmFSe_S4W?^m,hm-&M4UT#'1BQJF_AUr1kBnSI1U_STMB\\Af&a2)A#%Z)L'dF4\n YnijnSeAR[1&a8J1M<Z%F`HkSBXaFEOD?S4`fZ#+F>EPimNQ\\?ANu_5jI<9K,=Ltnu=%1o(\n XB8e\"erLn\"4M79WkGD,.O%1ZqU`FbX^fVDU1)=P?Og9.2bLr;CRud)Q3CeU.^WfBn-4p5,K\n ^d=r!$=Akr:RR@mc*\"@N_r*h&3P\\\\[+W(#G8-_P1<1/idJMOA@U1@qFM='[;^Y:=S7.@6%g\n 0h?P&'?0SZ92#XN1VK+l.?jOa*0`X[dS>cPs^?@qNEs>5n->d'><Ze12Vf^QW\\e;9F/`LQO\n sf5)h,D[@cZ0'k3hL\"eZO>H.M'>S\"#u?mWtabYZq3$d9CY*Oi`@!miKH'HYEt`e,#@WlAIH\n Iom2b8qU43Kg36?^9gr$k2E9Y4mO@jT_o\"Q;&E35TF\\](gGACi4ah2C:ALkjpEh:(=_/GGG\n dIG>):P8/.(W1K@FKl)Boc<\">/CARV)[4=#U\\'>7q0mnWH2jB*)=KeNU!u%!8#+8dS7%>in\n 'lb];UR^08T2@Pefj3\\i#R1!FrnIV],mf<>USEPNDnR!T5E-69=SbD.E1jbG.\\jT\\bF:kKS\n %jk)dWW_H;Cg>Ib3?OKe.)JOQ84<)H*lYA6oJE=m%p!Sc,1apO9/&6*3uYqnL^tN)@k_]jL\n [0?hU/+He1EF!>^;'[+T=V$VnCY)DqoYSTE\\r6f:4fL:(6o21)g?OR55\"%6e#,28eQ0'>1j\n @kT75dL%oMl6gMLo'gZ(?6#4CO5YWs-;?Rgf^Ou6rZhM;K*C7hF#;AjS6l//s>:kX[\"i+o)\n ?rT:!s$,Qj2lkOb1]b:Ih`r[M4h@LU;qrj]#-+`0U3kh14:/_A$U-*LVd'\\CPRb<uoJOd:5\n '($ioFeu%7)BX!6``@:].sVA@KeS.6gPi2oH$C'*!_\"'Kg\\$k3VWbto\"mY)6tAbRA4T$k7m\n _QN6B\"PFMqU#;\">Pid7-ShK_brhd.)Pkg^n`\\MXAhP9iOb\"O^/PV#e6!cF2`:-kK!R#BZp[\n @,>t*OT-r>>ILikNO5stQZ6k!PE*+JsKCP*0)LZ!F_>[GF,Tb9U6&(F*99P_L]8B0-Y7&/A\n P]I>#J.OJCp_Rp&m3uYuj*5HoS`?Hd!$W]G:$GJ<!7:TOh<.%,n&&AX6)%\\2\"ctiqZ7E1RD\n 81]Ba3V<V\"9*5T588MeWHt:<>4pNK0\"!iOj\\R,KUR`<R37`6RlglOpfs2OXE2rp/Sr,KM/E\n h*n?6HO:=;QNAuZT)1r4qr7Z*-oM$ZcB>*7<=DXe=]=kncE&@#9,9d`2$\"!V+Ol7#KUrjct\n \\0B!Q^M*8;+\"aN2n6aC4a5&0Xu!mA?ZZUFt?`7N(f8MCl_4W[7#D)8ITJk'TsW@E'fMJ_Q0\n i_]U$ZUQkt.<6M(Pk<-U$kGq0k\\0$Kn;9V4DJTY>5kX4V2@Eqi99a\\85I9W4[VTJB-Pbt?3\n ]9^L#sWmcSWb=rhM[to\"H4Od\"tCs-qO3fLSK,a6E=ZqICE_R'Hd7(gJ8hF.M.8Xp%+Ej&'@\n <lI`f5f@ud4BBMH=2SK))$hF?Y\\OH9G6bM':9<bV]W_Y!H&$'K!o'6hjNl-\\n4t%M'hn%G8\n ='R/lq^`RLCe`d_OZF#'nnnbbtPOi<;]C:f$Daac$Y\\p%,!e6\"$N`ta#',WaN7*0;bQISbP\n JBc$?8`XZ:WP%333S59JslGk(]6F&HHDJ=F*bS&Q'P]6o]>nO@E\"[o$L_X;/Ge;5^!=(7o:\n iN\"2R(FQtFab*)Es`:X&dbr;O1T!6pKI2t[3_gm,h=geq>q:#.0c''IV`0MW>gah`R&/60t\n ^[8=[5:13r\"d.7FWqba1F;_9dhfPQ7k'N%\\E!pBal5W\"\"aH%Vb##Ilks&:B,O&l[%<e($W\\\n rBF6j51CT<<$ah0/OWQ$78u-6<)#j3>t7kR85u-Me?);A[7XE39iTA';m6j4Qk*,G$<(U@;\n ,oH(9f((ra;f=Bc_VX^F]_G@r6am.cfJA#h#C$4,0'i?5Wmdo`?nDM\"[250<\\0\\5\"Y)#2i^\n qAS:oqR8>Vt#k0*PeTeP0g[]kfWPQ%h]QL@$o)W&fJ0ItRM2<ul>5-$*-^FB;ahf55Y3F`p\n i7GuouO=+u!&SU8tjHro-P=7(CerI.iPIom/3=<3#r'mA1/&61\"%LTkY#?#7[i3<gmM<IIp\n #]o,bD=kMP6b@Oo$D3.=0+][%m<SRXDbp0g],c6Q/fkgl:jX8Dd.+UM)ekG&LPDIS]%+)DR\n ;WPeA=A(2fLtWlD=t;7]5Z*08X+se8!4@F27Ank!KA)Th>+M]tXfP^&X]iE?g<Hd%+E[cg$\n VIpN\"X#n\\1lI+#VF!_1<K2slFS]\"6>#GNb\\t+u'rKCA9,?=,rN%G0!`F7$Y-k0G>(W?Y\\<L\n c-nB%\"qq-ZnH3To=X)Ad8s(gI9:j^!&#EK1M)JK6Ri/mEf&8Y?`0qh'LHS/_\"&heQk%Z>j)\n VfOD]mAbfCnaL(J6,IC@tVgfW*ef]9BnV#AiffNZl+e`n8WqB4Pk-<pu`ehmZbUu93KS(:i\n ]=jf!%e=PHC%Kg*J#4R%!IG*KenR!2%LZj,@[&D-;c<CP]h+cI-Fnf6JptpMq?`j03]n#!N\n A7%sZ9TAU1U7@\"3'nndji$JK\\e[T!UgtS+O8H\"Y,!o.\"m-sOp,=[]l+m/u$]FC&OpZ/mE>2\n 4H?1.k\\g,24_b27I:UQ^BW&1LX:KWrYT(()'=*MLB)#-78aB`qd5p9@GW)5`ZO1-+CZ@8L[\n [M/9nl@\"Hj:3siLD$C//)DT.:>%9?qoJ:[CG.3hUSb7>H<-:!o;e2,2P+N:b1;W<0q\"SR3q\n V<fraLA^(K&C`Q?s&@71T!F\"O]c-Y)!sA*K\\BLh$[\"A-\\bg!<+-P4s8o],%O_BA6qc-`AsD\n Mc3K/9Km#[Ek[fNGH/bCsjR,cP^'.f^#%HDL@dLR1&SKrI0j.0Oi5M!ic<)Qm-TF:Ii:Z;B\n \"uju4l;4'4eoj+*JFim,#R5ORAA2Pc5%GDlFbP?6_uOY+hui%XBk1gjA:A:USnhVDB=@Gg#\n ?Y+3?=^dc1-$+GihfLa2Ge$]\"Q^X#AMseA%PV,,<G.d:@'iX77$_62QXa%Y8Y*`$Q4UQL38\n @Lb?G7*$f^f9>E/B<gk\\c/hGoT->1dh=bK/a2\"`f+NDNFpIpkiRk[0Je6D5R/u<\"'14?(hp\n &MEp#WPBjPpn%9Ve)Nb<LGj[6([>M3L4Q\"RuPAWD2lL0A6V^Lb-0A^//,*a[W5B7utIkru\"\n [I]*TME.gb06i_K7O:LLBX_?Rnkk;2pmAG`\"X@*&-KMX(3Mj/j5@><t\\B1B@EDR\\Vk/89hB\n imkU&IP4E=$\"FHk>L&dNEoQ+I#&47GAZ9q;qC:bg3+^r,BJ+ptkW/o-E%R*WCp(rt\\=3]t5\n _9\\8#H0]b%^9^1d;&[.m1.QGrm(TJ5R@-/Cr9ihfQ[Y8\"7'W4mA?4cNneEIQegel@ck=;VO\n MAhiFf;oB>-0\"<hF8)IU!r4%CO+??,Z#'K,u]t1<=csfba%!m;CdYL@@BXj?QYJ&a_LID(b\n Es54[\\SnO*TM!Trf.5Wb-Pg2EPaD786e^:8%2\\_+@Ic!K;rrOZ^$s3M.&li*J^:46].jm4n\n \"Cej/ahSrI-&t!&MKqN19\"S_A7%<107mr%WI`prL]o^O\"8EA$lh(A5b'p@.)rLE-&>CaAJH\n g@)3`EM!*s`g:W$*E^&TdJ!WFVVpQ3!^`K*8QQ#KpB97U_DNqUlom>sG(B(B&oNhdL%o\\DN\n tuc^/Rio78;?YS-PQ(^0QS<L=+:q.mhPEJ%F$gLF)MueQQ0qXFE-0(na>:McTG\\9i:7o%E&\n QbG7ca,@=mRc7?@Kh3H7\\WQ`ks2sg(uVgIn3k;0$Nc;o.NaX(JF?I9NS\\Z_8eD)MYMs)7=g\n 8sF*ARG2`PlF)tT[\"CSs74pH8!F#k/RlF5l%tp'baOFDtSRnok<+G:;m?7B8C+=Jj5`#@r!\n PCil0eFK\\F2f4]9PBkG[d`\\1-];T\"/aB*TOnKf;s%IrKT2EH@1@l#/V&hcJ`[=SH%Nle5f^\n `09l7,P2J<oH,E!@]f3M>]`J)BHZO@Ca01+_\"Pg#GV'hWA7G7VB_Hpipg8e[^M:baC\\TZS#\n EX=gi#.F(DME(hog`urpD\\<(O`s#kCUPg/V-J4c8o>\\)ngbONSlbU7FRiZAFm_/1s!ZhBIZ\n C'AO4<DF#E!g<Th_eE7Se__DkqVjV0II^E<c,Ss.QEr:Bn=NGi,QFpT+$)OEh(nF]R>m8!@\n L3Fa6B;EY!D9n!?bP5L$rh@o&OdkF6%l6i#%rft^L?gh;\"p]mJP=H7SZ75Ge3PVL0K%=(d?\n (=,Hh6>eElV\"b:=`ccCFQDgL<%pCFG$0<b1)Z$bD+op7df2jS*JSR+OgU)056++&:9k',CN\n pZ-T%M'lQ3`I4B4812/<hnXUe_#<0HG[JA)ho,Jn6\\W7.r/ZkcQfJ'@Nr6)_IV/J)a00b8:\n j5]YI.qgWVg&(LSGQ#fI4MMl:L3jFFo.5,:'Z5eJoZH@^-P9JIrG'L8)(lCh#&h^J#D0\":Z\n '\"Oi;\\*h!lTTp!2WB6JO(Dt=@=2F#)3JLm+?DH*taAuimB0iXreQoa!9!B\"Em-R<(CJn\\NH\n ``/!N[PU;]J\\@5=4ok0mJOdW@'?Z_s#Om/D])U/38f3^\"7@8/EbDo\\+^STi7pjC+Sn'3jVq\n j=)4)th1iUPYZU89nUdpkC:)^^f%Ynae1jt1/sg@UhXu0.?5`nlAcDj__-q;MHlaXEMSrun\n UGZgS+d0q-o%@9f;4oaHZu_Z%mXI[!dV(GZm67=[W7C1@RXqWZAC9&s2LA`LTPUfFmb/n>K\n 1VBoH,'.0IRbcNbN<kkh#<(!V:4^PHJO%jB=6L^GC/0G#D^:Ynp,W>In-Eelh5[RhZ&AOjn\n &=s)op@d:oXNoIm7l<!<9i1oEbN5YT+)T^Lt(G&YJ+Y<<pApKI$uBOLuqL_U-de%E$QZ5n6\n :Zr'q=:OZZ>P`3EQE(.D):@2Hp\\FD2T3OC1Q^5k3WP*l/HdG5I&UXGJ.BdQEX;a\\NMAFe4C\n $R4'4,A>^oNBIYKj9/>3RLnj2K_(X#()H<$Hdk&k2VWlU^2Q&!mQDI>K9^+O^Z^RhncSO:V\n Z;8Y+rj'mM$HT`Zl]huKYA<eI7^&n1+N@;QFX'L59Y3/U;bYA(do3XN9%MKdHX0OWXikQ\\e\n J1H!9:Em`QWVg=SS;9Ye\\,s-f2^XP?J!a+JRH4<`-i[t(+kXk7hN.s);29sSS6^mSY'ZN<j\n eoBgK)Rs**G0W_/Iu3'np\\`f0.Md%ON@2.2:3ih^_<^^$(3o\\%K+r9?A4M0]/iR?%C/o&mm\n TUdq0+M:33i]L#LLkSN]hA[NqeJPQij.j\"r>\"6Y\"d6k.]6mAjj5Y\\NM=);Ts8B9X?`r5u1H\n ?SP<!]H*('#k>b'o@%2r9r-r!5*f6WTg-1XpkuqD]VWlf]W?GMI5,iMdYO.ZngD\\qVY1oE-\n ^TVGm*lYG(G4r,HlJ#QdEbZPBiOIJ%1$X.?Lje*(Dc`8#HHR,V!IXB8*W<kEQlcnsnKr).K\n Q5II)i/MsSf`jLSA$A1F'-19NN(S/'@8>A+%_XWGumk-oiZKAQI?_4@@Cg,So*3E4hGGNQ:\n @J0I-t;?J`-<0+,T\"PhER.4l<@;e[V]3n_s$HYQHe[jhQO3LHWJ/6kBl''gAH4\\+3F)a,Z1\n (Omlt+<p>1:JqtJ:(([!@=p]'c8Ip?/]`rF7'auLdj!)p4iF\"Bo.5aOUr9)G>n%Y[;3<_3G\n ;];]o?XpZ(:>g)'aRs%VVR59V3c4sKg(*e?Q^1^LRiFFNod(U>a(hB^S>Mj^fh/GL^Y4g_r\n 4,;2V+@F5(&(&MUHk>9^J-Og<iabbbUYL;/ctk3:HgGZh[O\\Ndi8:9hoPcJ6r4dFa7bgsSI\n o$$`Y``Js+<56K72c7u(`*7HA99>@3X@.39a$\\c)1rP#$bFtObTR(n;pO)/_DP.0L+qMAdQ\n U2n)'pQhUm7+cjr21+2\"T(17$H\"&:W,7Z.-2/>7$/B58sjH.T+mWWd_,1/dCMC`['bf&Z7X\n 7bjVT36]o5kf1-`:m^uIi%-S_ncb_QVg,EZ&fdEZDcW:;^t$l\"b?RQj=\\Z=@:tJp!4pE(Gi\n (WBr;H)PaN`O1A[[k@EtNe%U'&(PsJM<1@`Dl;C4lofd$LVOt3^&P@m]4dR.jSl?ba&+HYQ\n 7^sk4oKFhLBXI\\NTaR3O>`6f3`o3d8*H@4A1t!8,)lXfrR?X9Fbo*,o90C^b/rj_lBI>_!\"\n Z2^tFk=]<FU4l^^)WobK[^oo;!K>qW7;mRcUnF*AE\")kofdk*)?Eh&KLDJ4&uHom%8n\\:1E\n ,;`HI1W==K</LXOKRobGm-1lX:Zi28(]kkP.ZH2'HC,-B_Gr+Z!_I/$IDkQUcl-9OOt[Yg[\n ;Xdtn:,.GWm[K1%q__8TJlV3S@;?HcQ=O]&3u91O'_WE!.kBPf%p[&nYTeXJUL@U5G1cP/U\n &Tu1\"LIC-(uU>/Ta+'Pf,J![NO[o'^n^akql9iQ_Uf6U)1goW!.[&W=fb$P8,\"bW[Q(;sLI\n D.9KTOdm1EgB<XV22@:i+-sY5?CTJkmq(lM2KI>T'FAG)2>+>#g=+rK9knM;X$:d9pL\"bo4\n YJKE'gk%:@%1qLCH]8<Z$,#0$$gLUKuLpZdc=i\"G@%F`G[`Tn&7$dcLn+Fn`6m`55q6`/lq\n NDMVJ>S:'gAT$#j*0f$QNZHFcQ\"RYJ(hHq)+!jII\\]\\aLC1T4e)7sXS)Y7\\NO2T@C/)\"<O^\n -(<sIcV+dV#ND7CE\\iC6J\"EGeMi_mu=#@MfQ1o4/6531go6**IHU?/1pZ`^9u^OuRK:IF$U\n H5\\M!IO7HgQ^6p'2A8N'EFB[G@Gm:A2m00<3W)\"2H=\"<I)(R;;V]\"upnpu*^WQmM]OUY1rq\n @Ehf-M>_gu)7L5a/Dl=9-FM-fhJD@g4.Zm065F'-G)qL1V)B[>f\\7KY/0,%m/G=kH]0Ac%*\n >>fS.Ljb:1J)DR[!5&ZlQ0H(;WW<cVRI?&e$YeQgW`0*n?20&HCBoHCsB!O7=39]LKJJX]r\n ^Y)[`)8h3O5c02sb7L(.3UrD8$b%ph(&pa,=Ni%OJHiV\\Rp5?YE6k+2k(cg#;jVkQcAP\\-?\n RkjI;?tBt_iF1?E6+GY`Nu?/KY06tkGhf2kk<STK)(K&;YS37BJ^^b`,G]8XZc$o,??\\Hbj\n nh*7iSINu8WpCuX->E&6HYuS6@bfQB%W:BuPH%C6(jP,HrmTriG\\RqGh)M0U4pB.B>%e+Ic\n erXs$l'cnJcdk5ONa4jQcrhGXf,1t5kArZp\"b>&AA's1W+!p\"GVj5<G'<c5tXk((uSb&G$l\n 1)Kd\\,-DriBjV`%_gEWqaTQ3I_W>^^!ip#p7pb5f9uA\\2-kR[XLZ%=HumVf1pK1rn<7@VG^\n 0D,fk?us\"/jUr+/SW/V!dMsB<(#W60Gi:h##99d=%'I<rT90$UX&nHHo1LIp_U:*OBg6+6D\n kdO1!f3L\\rJOm2<ORNq]\\qhX5LT%u0R+IP&m+VJhXea>E,%3XS/p)WC7#&'G$9.g\"'MI'9^\n 5M,a(b])-G2\"40A&0>dm+<qNUMc_82s61>$gf_nWQrK#gjN`PPm>6`FAbO9>Y:\\Kb9G4.'W\n pWPb_-kQH@MW`<D#m$Y!#l=X!RUqR!1I7$A!TaIrWs[4W$O2Xo:I]*'3rAD8\";&<-&4m7`_\n $'85`uuQD+j1'#gC:=7##3,!:ZVeZY5X8umR_g3:\\=B7q$51+#VZ0*Y_L]tN9@DR:sbM*n=\n 9!i\\dm\\\\*\"^L1;(!!=.Ya!=\"K\\\"!d)-NY_%Y',%$/>AYg3s*d/m^+3$:oM0i\\\\0>ntak((f\n L)$Hip>hZi=grm\"pO/1Us^M%B#k#S@3Wmsu=;#4LsR#qH/9biKG!RPEhH#GGTF6-aAQ9,c3\n ])\\KA<&@W?EEr/]u'<oFq0L$7+12Tl[)bV_!_9O*!=WPmk(%C*%0OkSiB-+<l%]m&JnSndE\n D&7-^(SoLZV]cm4$;Q]hF\"rX)&J0OKQKV29nB[X$&^qqe.jECp)j/@9n\\6&@_'@AhZuO7tU\n ^\\=W/u[^l(nnV`iL)!3=WUFK%C'He&Sh;_i=?N@?Ol<*E;KmF!>lCN+N]reN7SWfN?OAo+j\n UN?&!@8l(`uR%,grG;;PslM1F-K9'66;WEj[EPbp6/u,`g%sMR`\"]q!=]F-*cDTP1:l+k9^\n ht-;j4YOn0@WlQ<>!-W'TTmV*L$!@T`'(ig0sdYet+)]:3c.5-eY8o,>QcGoFq1(tlf:FRd\n A_(--Y.rmp31H*!c]-Bs1,dShga^cETdk,W:1t(,1o2d7ojW;b./s>H@Aa9jSk:\\.]+=iL#\n c0$JgHRMer0Th>Cl<q3nR5&CU%0;,$P=7KqRlSb/1:'/I;_]f/3AXU6oJ8W[n4bH4StP#[(\n SS/m1>+dR;(^4&rDMZ6&87CCD'+sVUG2F$&pY;BG7Y@>UpGUq1P5CCL75@^39(u7JY3r*i#\n ^@\\5njtu9R/ZT[js8<65-If7@u+%UoQn=6##6tc%H6T<YU+O4EJb8;b]CgcLoXkrU\\\\'P@i\n \"Dml&YUUQapb;YpFB!<<af&@2a(;\\%BBMau)%&1]%o1l\"VdMR,,Y1;EoVoHus]Yt;/i4&hA\n gZU7:)AeaU/\"OoY/1dOc5b=\"0S7'g#ao3XpAk*FM!8orp0FC;VBEdtH1+Hq4C_L\"LG#=h]!\n 5L>ZM0G;spFuUYp*oZca[0KNn$D'):6Hk+^e<s0uSPc5[6F4-nPmiA>\\eee[96E$`<B!;[]\n i3EN7+B15F4@YJ<7CF(7C:QOEW0qLgqsflEO50@'^IuJmdO#3:N2]5+YjtPd8H6Z=;?FN'b\n Lk]QVl:o8b=<,1m:g[KR!UJ*l7LQ[(0A*2-RB!<#)`5'gj;?8IffO(=^\\RF]CU_=SEI%pJk\n W,o]9A<>6$@6<m_FJNVc5jrafJt(4iKC!W-$Mqd7nQZZ.]]B:E#RP?AVB1Nf$]/,q]>!/4i\n Jq=Uk!<B4Mg5>1Uk9J]mHPYkZX9O62e?IW7.1t\\0Qd7/9.eMZ)(eS/>HnQp*a=\"tIF_,ckF\n *G3l@B*Oi-Oh5#0&Rb<]o@=Wb[@:eUiX4rg@Wekg<g.\"c[4PE8<&M>;Pg$TP5f,9q\\2/$*1\n h9uL#+5&G2mujadM08Lo0<B`$-U=1EhR0TgMPNu=-e%sepD'GI:1WY8i@JIPVI%\\NZ=*'Bp\n L2e<gR9]/TB3.C)'6KQ8`%]CK2(tCD:,\\e73%;HY_24Eu!M$&-Z+97r6ac)?FLk/e`0496A\n c\\8G;-0QK`;\\m<-^ZBMlBTQV_@h3*\"m06hbO;GBIj`$$XsiGSRc6<uC=J4L]Cf2O>Y!G:-D\n !\\P;cp:,QSg2Haj[$Zl\"+/tf3\\+gGmNBm\\IHHiqK5:U,&/?ZigBd?e?0f4TIWbR/o?)V9+\\\n =*&>)H[aMMGVugI1Xg>cbAjb%A/34%2G&2E?ZPItC^H5MQTK#l?B8'5(W\"1k(YaP/.tYd9?\n rWqW(X%4Cc\\'K7I86biQnDHKdon?>GB`;*3*1<jl\\3r?IhrW\"F[\\t^V&pM4U3@Z\\G\"#,LR6\n GgF5.D)^GS8PO(M1!kHK>nMTm@YQR=ps\"MASp4E]&K:5D-Gh^GnRW(e9H0D+`d;IX#\"L=Mo\n j&@>r_mL02oZQ\\U=HWIPeI<B$1nG^Y+N]1s-VF#@T9k:q:l4b:un0;4@4Ge9'*$[^O('2tl\n ffb]PX4c<2qMjXuS1Vaqhac(KuN*+D[p6gnBB7FpcG`uEg(-dfq+buC1CKQ,uf:e6AUjtAB\n JW4/8+M\\f0[usm4QPSD>%lKJP)j-Mjg6j#Jp)B>EG.aOD\"_HSSfe]%@_g_D=>.H^nq*/k%6\n N.ilIG%7uGiX>+#u.k=Lfj7i(laTW!J/]=1&6`u=k?b9G6GFVQeCDd%$b`h#9<PrSV:kqLe\n n5*7N$LKR@,dt\\M9NK$^t+eNHu7t\\,T\\n[?UEPPq9n>;g!-V?&6#b5Br54E0:SPGT/W5T/o\n ?8</I0h4.[>QSlpOng$=8[f9/0a4i$\"?=okLgrLeH=V\\mUM\\Mo7(&X1h%J!mDcH5UJ/*GYE\n mNgH60GFtBd/I5N6:H?Ua9MQCk-)MTaWtV,$X6$/R<M_ajH^\\)U:WICBZ;r.>++a=o,%IL\\\n s.A!GVY]>GRX(>=dAPS,RZQKX[hkMNF+?9]>e*d5g*r'X`5B.-Q71rn^o3rn]<'a/Z4\\mE3\n lckuH_hZ7X3(I19sL<0,!KFg*22Dp]19\"#9;afS[2;uCGgE&T8Z3E\"YB+'S\\rE2*OdiqGU0\n @l%\\;>NXTMN05SACd4f131%Mn%0@X)9;jgG?C/^m(<I\"M.sMj1Go=OrPE4XkU1o)We@%1UV\n Go[CN3Cq5\\77B89MTJ6F15HBqsL=MoIpUA$TQ)PhG)RMN`@BGs1JHhY::;7S.CX1Oq<>;0m\n i`LbH$Zb-&s5^YF.Z,,0hXrC<OR@ULM^UuK;]R#4C\\D9<[c`$@)]ii+EH[!1>_mdp8UIZ1X\n S/'#5>6:;nX#pL\"S7fC3:Vb[fHofHi_pfWVi#_e<]3HN#>_BZ$-c3NWRQBo2)Y9152lN!;Y\n PW1+ek7q^_gre#Q2FEoH\"%$;@N&\\EMEH+,>fQ>>@+i/Y^jKqB8%#oA6,>\\)42F']]Re@uLT\n S4KaLmY.gm)TdR/PcL#(/G#4?^-be!o*7Yd^C:S?oq3q3E0T)MMVF*@K9q*R)b;boCHB4Z>\n ]tDmGlFa'C/W+Mji.lc>VkcMT!=>J8?f/&LjYcd#>5)+DnKm@i/9<I4n0\\s]e6S^EYo(r0r\n DU#+F-7G-FVfY&p?SMSN=2;-M'e(bHb4[[m)ZX8!@)8/nmh7(o2:!X_r]DZ$]S&M'Z29FOV\n C>B8X>XP`DH+i$]NS>%![\">T3X5;\\#arQ_3HtD!EqnQIj^0@GdiI?Gb[G/D+i8)/uID^:-?\n YTEo(&A`Zh:'MKkLWqjhE!17CA$FSkUqFX)kl74rUJs?9#+a*@%E_7Sc.7>$:d3tLE6WO_#\n tWa_r0BigRG\\&I.?0`3S]\"KiXo\\OH*>f2BtYP=b'eKI^,=(T3Qk'i%H3*^hG*:,WkD_9ZF(\n M1^:33pU#l5;8poO]_iP/:^#pFKk<@A9Se\\.EH]rn!2#UoXIF%,j$0&R8ir#k)3EtNWhrCH\n D)$/1nT#^>m$EKc&q`_FR^/siXD;YmMk$9;R6096h7MJ.Rm/Jm/??ORY471UcmLrUHhBhU$\n rJhn<krphX4aZY2J&L?f$3>#_qt9I9C\\Gm]nHH\\bT,[<DlgaC)ls?b-J[-:\\//_fSptmsr+\n .(L6g\"[TPiP'f>rQE<sLK)#]khJC<*SK[`1\\I?/WVmd2+\\Kn,DuAM<Sf`!P^:F!1g-rc*dQ\n `BLT[jr'\\+q+!rr4_EJ+rc2q8+<Ub7^cs:e2QA&I4\"UTRpin4dQY7`$/&\\Ubtcg'1QJOW8r\n Cj+caT2nX1m_:FVK\"jV#ZpThN[t9VsU+[+94RSI/sb`anps4eY[8F2i&8OJ\\f$WAM2/(f[D\n Fe7s+UV-^9,Wj>-:.d_8i@B`l\"p0.$]\\S)`3Xd5H!Y1tR-1TjePS_!=T]j7&CeP5c;I_]@\\\n =Bl=X$&HK.E+7p-595j+jDpYNZTN30BY9s5a8UQSU![QGRU%hD;5r)\\opX][^L=D#D\"a?([\n bl)8h/;tVh=gl\"_;TA.S6e,rOic^*q4-;c5D\\/[NuE^K#?S+[lur83hTp\\^i9to<SS,Lk7f\n P]1]jB#l\\)HfOHbQ*oYKuV3r-nYFhp_N&5O]?h!^I;R#6VcG6l-\"mYY6,C616d&o\"7f+.h\"\n OZe1BhhNeBV.6noBG&iGI94rQ*5)+8%)EGSbo7DU-:A]A_kBcBPs`-30@Z.+1C8+I@H)Bic\n d)'d6Y1+\\:(Z=KPa,RGHe.O7T-Y*R6[<4%U]l.!C#-RkL9U.hm=cCl]PACi\\5We.UZ.s$[/\n ZRh\"KlT?`aHJ5l)Zf9?EYETJ#]s2Z8'gsd@4VYgiXHakt1*d0nEC@1A02,;$eMg6%[.QX[<\n &GC\\;H1%]:?9<sbV'FUF`]PK_DRPu=i(oMDd-:#X`n#OQ.:4h=7scb=4NToMcI[&7@.Uh[U\n HCaT$`L*C.7j(VI`;=\"h/>QZ6d&\"aO_,gEQKthS;Z29FK6k5f5aG696ZW*0['&&m[^;ceBN\n E?1N_9HWO&,RJkeqfo/gA:`;`!ZZgjMO:eTXi7H1[L/OhIZM_@S(#IU+aA2tDqP%;*]:R#E\n N<`bSu<E37j=S[r<o0!i^Dd_`D(3Q3]3VIZhkILdAoOaMWO/#i\\DO757XVj<<SJK5CC?h,0\n ^Md?qf!DMM[jJj9C_o:UFJ?6VcZc0$S@Q($GHThN9R#pfIUAH@mt\"lV*Y#hl)t`S^@JglX\\\n 7.QY-Fr.V<\\MI&38GW/(WP$sb&Y/(0?eK\"f/Lur]_+@Qko$*`d6%#]K@FR\\(K],ZSQB%JFn\n Ql7dV.ID2l1Tof67f8jnZ<bGWMt-Y3UDSO5k\"W0:/mcq^'eUm+Y=6G2=0Tj6U+/f&;#EZU_\n ]WD\\r`!Vf.&C$btY*\"s(R/X,djLIP_QON;fHG**Sj[GBs1;^[qJU&-`/#3!fU[6_S\\kQ3=d\n CAF#n0Z%;C&#XLEr\"],!5G-GQ^1Db*5T_'<__t=[q''9Ik)V9Z2$#;Y*=RmVM4aE$A)*I')\n %:4T&HB\"VA[^^SU?K=<u07G''2oQA-H[L5.p%?%b(Af:sK45A-_nR#Sj'o&,#D0a*%tXL?@\n 0Bqr&V`#036<%J1h)\"IC':nW)$FGk'TMTc3(Gsi*Da$ZK5p#V_:['U>klhiUXg(eW<XR)</\n 6.r^-tBQ)%7R&O+pG\")^P3$,tSM.HLbYj4gjekhZTQZ09T/G<qRnN;sKVWq=d;^*u*gXM2K\n a#qTC#dV'GWAQP/Fd9=]=$Ab!Tr1$UV^W7r=;N5q=7-9Fo#OFLcYCRB\"*5\"k^Mab8U&*:ag\n [9rLoJA4579D^KG2Qt&-S7$<;rV<Z0:f-Y%GDJh8M:.b`T&E5O@.8_F?0R/pK=B)>o&OlLa\n -fGg(1Q<<J\\9cD')+/([&#'b-M)*b:1aWjTR'SE)9\\MK_..nO>P<N[-AWh0!SL7BfN*_LC\\\n P$Pi.Adc)7*+'%9cc^bL2Df>e$[d;C%KoHmpqd2.5rWS1Z=R@,rSQ/OSU?s9Q2fm-qa=??R\n S%C@j+NNNI\"H'C@tr8'o&to1LERb*G;,Ug5jY86!J,9Dlmd6O\\pEqmO:#(Y6R%9&)mEoMNo\n fUPeOrc3PT!\"AMouWg#UV>EB5Xmm#om'G7r\"V;.m\"t.$NL3eB!hQ,u%6nn%,Mf3j0:;+PIi\n 9k1*YI=_hksYCDh+\\lOI$7Vd]qXu>:q>C19nl`IKTo1mqC1N#(K<IhUq$:@`2%1;H%Lp7^N\n 84,u!:EGbf]*VN[=Xu\"\"/B(,c2(HjRa\\?EBAQ#m7&ur3.AGlOjWu9s1I#kmrI;cOf^DH&2+\n o>hhkd@k.2Y-q,4*Q5ne\\8JZ-K*L&pOc12U)O33jOcRB2_Jq(\\edR?;k,h1m^=2]2F=$A\\:\n &S!RU3WDVL2]19iE]&:UCb?o\\R40?#;$H%YGU:i9Y`MEV;W<([h:\\X8cA-/k<][,6MJcAV)\n N<^URDNrJ)PP2fPnAb8=-n@=+DNnD5%f3-OQ8X/hY+^*9,XP0)^29\\cPCDdV+RnQnhWBCiK\n )``@hF=um%<<(OhF_oF3>4UIg(2M[WE%k#qe!Ksg58^\\J48=rSHJ#c%9d2*36$LsmVo%'G^\n flEKcm),26IF?$!3pUC4d@-lMh4Akl3+BP^5&kJL.sSd-hM@_p.]c\\VZ\"SR&/MjYT2TOJi-\n -Ku(/KT\"OPM-pJBk[=-V/doL_4)q*%\\`5Q[.`D#2?QfCX\\G/CDQ&:NX#\"M2VlR'TCu-&A=X\n K%aSFsjl`YmZ?<BP'3C;GK5;VQ&-4pf&M2[<8C1Mc@DNO3l,&)l;6C:d1V`D4F?i=qqi^TG\n >N2\\.\"Zqi7'3>t\\Y97UsZpK'^t[ePNf\"n]eOmR;Z>3SK$FsQ!*E8lg*3C7TepsHtT-p5)I[\n 50s]bC>%2I,Vo6*#:$N9kCNQNG1P<J'kk00g%+3,9HM8Q;=a*`NDFrMbp0uQ7W_)X&e'%E6\n 1#<kpbO\\-Vc)Pr2WVc(;F3OJg_C2`/RhMmu57-:r2TZot#U4*@RQX$B+R.`QW;/';Y_T0\"\"\n <K@QMf@ql7mQg_SfWW?6#JQkruUhST93kPc,jd/.'^IcF`ts9gUVd;?G4L-G=M1pEH_/jh<\n B[ga5S=5JE6?0-fo`jR=.R2M@(D?MN7bs#<\\p9npb;pTT?#Urft55iTqfq6**+0(X89+l4F\n )\\1[4p`@*:a;Z>OSd3-dWKp.^V%0(%IA]7KB5ds<mN]=YC1\\\\]Z,&luL3Lk`HR^I/=BKF#A\n VC54K<K4FAS:ic^m#en4D^=3Y.k]4Jo$n_NW\"?8(;!+cB@=u6WoUF9d\\=F'uR:q]Ns6*)$=\n ;m@rjf!>JU[nHXg/,cIMgHY:s4,]Lig]=5k!kGr$43O0LR]6F.>6_GN6F88[`%7Q(Fp47&_\n '4dAcn0c)&4$.K_\"9FDY\\\\p<!lFf@\"HZ9/r\"Onl1'Uj##7u3:e1Dg4:VSFuL/^B)oCp)>)`\n 8$E6ntaWX84\\8fJu<A*fM7&CGi_O,<uAW-aY0[X*_$$-T0[-2=#_pQtZd^4[gVo`ACM]=Et\n *Q=Mnn3#E.lb,W%kF=KT5;JE0b0YX*t&:;`;V\"6aJ)3.7jg<$1Tj\"s@hP\"<'a'6,mG$0Uqk\n eS4(A]7Ctr0\\P%(U@hHR'8\\Mt``3[\"m_n*e9\"%;1>ZceoC;WAVl@RjsPa)lNiaF\"40C;n&s\n #1PMcn36qI>\"+s1`KIZbkWXPcHc'?I^5t=.^gG(I'gn'`#8h[*J^8p-=GE>WaKujTF@&OJ)\n odM.60(Hr4<Gq5+<H2,,eS!'Hu>PB!3/Ci7*FIF_ulq8:H.4G!^\"1gN1A#>S]TgJL[]_IaD\n -=FK\"@^hLG1O\"jF9\\\\J'(of5nF=BWf)UjTn<ne#4.&!$onD$AVUP/LS0%:l)+cm@=]Ou#$d\n )(r+/N#[)QpAaNK[`3t+[`Bt$2o4%sG.Hu-E28Nj]cVj*JdZuE_F-:]U7a#b/l=D,?9YfpX\n tb]Lmb-uT4G*Qj7t#>d8XXJX->c,sI&LJ5ocWjDr>3.\\RmL.n\\iACSjhE.br?#:Ou74NJBg\n B0$1&9sh=H%(As\\[_5(hQGej-U.7\\Q847O,bL9M66+0?`grB0Z4lW<Y)gj`c:<Y_QL4FFPU\n tJMmmEXd9#=qgHo['`DUO\\;RJOIaVm.AUhqbK&HcOu-=cpr_Idg$<X9#Re7+oP1#ObEh7c+\n LJ\\r+4'\"!P&?j1A'MM\"HaKWOsHj`[qt-'KM\"o8k.h[t/DTI$]U9-X?31C7L6U?:h%7sK&\\_\n (h#7tWGHNaVp/:]-mK7FDdoZg6<))>`MJP?p\\gbh\\M'WAN%\"h7mbV'+#FqnZ)__,+nPLjRM\n m<!0(.`^JT[K`G#0Zqr%)3:-f=oXVLY\"YfS]:,A0a\"UI[n^I_]<'264a,f2F__TA90KHOlk\n XX2G]3Raat#2hQDN?0\\HC]_BR#8f2rG]s7/%#:31JFIi:TFZgS7+>L2<+SSLF\\(#!8^rGd<\n 0^)*`Cn_292t\"HeEou[oha0B;:PPBeJ2\"_,u`>o<.Op8<Gb*&&.I%_#LhT4;ptmRi&6.7+]\n #2gca;4p^cI4+EehUF;lNKC3*?HQ&-W>MemN%8%4Tkn.o\"g.d_Qf!eSLQ-/kI':4e2g$h(_\n Z)1,23R:3AB>,a_Y5%26;H\"t4Q\"'k>j\\H.SfY#B3t%c!/=AK3./_fCaPo\"b,)1dY):.KLK3\n L73U4beHIN&=/eiJ\\h9+fB@s%mer;+\\`@=ojNRjl0bDcVL!pIh7CJHFDf*\"XZm0M!CF%!\\L\n 6<t!G4a%ZU)MMR3c%-P\\I@T!@SZX)aLU_Va\\1`A\\J_DE$=uCf`4egY!V7r%'K'3FA+C\\L`?\n Ws:4g9k;4>WG\\9E/)_bLW,hs\"PO*OMUlo^gEgLb]sPl\"N`)rkf_pk!7?Fb0D?r[o^X\\O_j`\n )aj#rR^.;a$IG9pcTj2Blfn\"rM74\"iT1r`N'PkK`F*d<QNlgakC=K>a<Ie_!m$P7\"[>F#6f\n e7]rKf)X96[D5?44Y@,qJ1#hqMK?$3I/Ksb%-.,/UI:bB/c-#HQ9Oj56W&rjP*%),%[Q.%6\n df0-o>'m2\\;l'&&H#2jX[:$CH!l)!TlLN%9gW%A!4bMM@(?M2P!rU/PDdY<9'J3YuGk[e#l\n p\"^AVh$pI1:fU&7l4,4+L-T\\5D:i4?ZrWaN:_h_em47#2B\\Sbc>GCCeZ5cdOD-doo=!bUT%\n HLZ?j[@qe$BT=aXKZ'/%H-@YT`B.f&38V`&`4'2h]<D=4j!os7>\"&&>khjgIM^mics7V+9%\n \\*;r3,&JhL`7B#.=EcINVpUro,5_?*41`]spAah,`)/h=Zt>>eSf_b$]YWbQW)^*Pk/%-p9\n 1'iq>%c!SpoJH%sBr^@i4K7Ps-p2;q:g_'!6?&.F1>@KrtOA$u&>V5h\\R4pIBq7MXE_#h]6\n /Zsje;iXLfT/cT$],\\1Jq@T5_Q/,NW4r)WL&if)r+BmO6hH!l@X:50*G,#e\\iBEp.TjYg'!\n 6'd;!Ba*F0K\"(jA<]=N#=QQD_hY:f:YQ9C?<J<=miJp\"YSigN4eHL2<#DQ3;CMjC(%tt!ok\n %4L%5%nPo+_4U+b@W!Y4Y1-%qHKg\"ie3M)R4R2@Eo&[>c@/SbOZJ54TOpZ:kB;'8>jouK>@\n j+HjfWrCVL+!;8-=Z$@>8-&#(PbN@+qtJ6_JE()fFhhdY8<RLPBI*L1]L)C$(D\\Auu$p`W.\n ^$!N-,K:dH.3G\"TU\\i)rKgB,ki&.O&EsFC;$dKj\\REhEYa\\RH^T;OU-FAk^Ea:639&ll1TM\n i#(1/!klmG8Jab>8[XSMdV.^?GkS>%Gc@SEF5UOH[B7Na3Y]K#gB4c%`kao!=7Vc\\O7Hi#d\n <kXT.ooVuj8nRZNgW\"3c<\\!+B^ZRa;$D982&8l3j^$FgpNbEirLiipC1e#-Ol2ICC2T4rNI\n q+!;K0WfKG,9#@(i!Z\\l>?6.-E+hD>M\"V!\"19LkhU(QUM.j'?kb`'0*c#OC.d#<hbFXg]D;\n XEf]]@>rl]t<(PaA_L;23/6lh96(#2kLAH\\Vl@#.Q?ZL;dsmjmH13kGVtokQh9P>(su<l<_\n VN`p;o5mH>&(hfLj\\3D'NYHp%sa!e=I/Y0h\"Hp$YqcD*Ekg:AEmfNBt#(kl1IArbg_E[r%\\\n ok73^?93LF=,H>-gLP7$l(Bj5/\"c\\Uj#2j%s\\1iH!k%nB3E44pJ2Wt-k3sC.:m^E_pcH>S;\n bAel-BH:DHO@KMteE:tE!DnaD<uC<Gp$[(uD,$\".T,d(O8+G_Y]lr%Hglk&Gg=tKbCRXb[c\n #fH-+/7?kEd&o%JCMW$C50ee!<3GrY7,I'/E:DQK,>&MLg#Mb/quW1F!g9o#;g>DbOI4/C6\n '&p:h1g]A-X-YEL-<<T0)SGdr0uGDj9&If(r$p*aR(h@W\"c(0%dE=P\"@k^@\\pe6B)p;]\\sO\n m-L-$FHO%f2t9S_PO#@MKR-mWiR;=`UB@q\\ts\\01r.?\\X%doli1_5;`&\"2YEs[me-=,FN\"K\n [@HB\\-k^P_g#<[/G4`fdqm70D#0%KS0qf2/cnck4grjUY68)>U<l!FK!OB;_VG')VZp@fqK\n ^i]fg6\"P4AFY@h,k>Q$->Q>U6KRc&an7.4I=7\\@QGIMni=+'U82K9fPFhIPS!,mX1;m:doo\n =oqO%efTT4k>C!F8%rpK&uVLOmR>hn(25LDZ8lR7qWT3mDgJoTOrsI4Egafq)8G3TPB2d._\n O)LG?:,VL7nf\"1'$N$\"^k>SVk!LrSTiZsq=f@4k;VGNe(X2mirD?h5D42%K_f=iG\\1]8G)U\n MYD!9pToJ_\\M6S`Fq+a0K<oS/TGSo]K;=U(dfq_tkL!.K^EHO!)@\"5mqri!&q+FSV!.W408\n :?abUN8Hti-H0;s<hn]'V_=8>7kSJa&XjZ8%@H#im\"lO4n=315VKl;Hph1$BpT4MdsWh(Sq\n lW9#@haVW*rpi\"/`s=e^3,j47ebs*oo]UGpctie,$[]@orO9?j#MB*d]l`^\\%/>&UkVX'P^\n j!iYFcW0fT'^n`VgLq6\"ce@In/m?tB`+3nrjV1TJ#DZmb[NN1rqD9(LM\"(UXO(=5D3OqaJM\n -`k.oS2IKjEm?Dts?uRg8G2#JbQg&5i`%56:7g!jI1T>(ocU%LWDl6=CG84>moaL-srt(o0\n JM'8sh>&\\->61EVWJ,LRGTN_L^^8Rgdh$[DS5GVGACkL8Di2k3WTm&+XK]#\\hdkVNV](5YP\n TdV))397iR,VUOg1)P_ht9rlgF'tVq=Y2QS:=Z-X.I)sKN3Ss58e[F:P\\6NoQ4/LNqGJ%7#\n =1dSfrI;GnhlkuWKp3ZU13\"/4:+mWIaC?u-r16D-Qc+[o/=b:42kA<.oNCQ.F@1f3ZF)a,7\n ^lC#ehVnN/XFju[G5Wn>A`NcHb80SGQL%+&XCAsEHtf<?R:p^;6p$=/rrf1ea.E??%1[D\\_\n Igs)1EYLMok/RH@3H32iHD5p\\]Hs5DR_IV.L%K+0X#Zr;OJBi(j28An28O^lV5!\"[JbI9P-\n T;KHCK:OIRm/)1bI'%7;i)4V#CAj?uoaYgc;Y7)nKNHa\")u>o1KmN+EmHOfWC=`t?O<*QO<\n /I36NC%##kGOt;S;aV%:4--;<bl?s[C!S1BcB)rDe)WLN5PtQrr\\s1Ce%)F[Ao.7j:9TqTg\n O38YnX<em@OVoPe$i)>jSSBpEUeaqSOK#5o%08^E1b-%'/'BLYZ;HMT&8RgaoUSS%PcZKSS\n d2k]b0uU24Ng\\<lQX]_XW9u3eBHZW<ONWX?WX`PMgnm><Ma81[gmP&k1>W'T'obkm=ar\\2C\n 4+A]anD4A\\Cm'lY\"o%MsUJYQE@-%_04$7D*aKS0ac\\)]tjumE=>'Ph%<%G*L3L],thP\\NTG\n HBQ`]Y%h\\XQ1IG^CYrI<`B%IAM6a\"cdm([#dc:7W[rpi;PX)8o#PVZ@&J)rqQeN8o063KN4\n R%Qfg6)(%e8jV^6^P@^.W>F\"='Na\\@;q6\":uAspAURUX,l-7YO]Yf2?XQr,qtQhV`I)kN!\"\n fOgXpo_5?M8m88]lKYJ`XjH@h)b$hu$''0MQkmrQaX,oaGLQ4#h6u_d%6%6c]<:AH<RkYf]\n eq[]rEF4U`rB;q[G?8K=PQW/`Rt*(Ve0(-=!7';<eKe_^)\"\\i!:s7a\\'Ng\\*Q?F]2`FHQo^\n O'V@2lgK?.\\cjO(I#<SZcnbpDqS&h=mK/I=)oHm]/NrR\\]tbcsB&2Y#.B#_rn+2H(8mra5Q\n pQq]2XmC)l1%5%OQFIc^+t?S:BN<Bj\"(^2H5Q@DMA^O5]p(r%II6fDKh1`ID7`-KLg%O`Je\n Xb,lI@k9*-]F:3*n/[n.4@!^m=n4hE,!B`6[6eR)gD@Stb4U9pK+bW[P&jf\\p$.n[0)agU`\n ]P(QAR`!7%:GNhGf\"V[5.,c2nU)kT<oJ)*tiJ:9Xo>F_P&Y!icI5*1^^;fmDNJm@H:XU[32\n t#Y!_6e]SD>hH(K`BsE@\">Ch0tEYb!T6nJNDMA9\\k!n-,D%!U/Wq0q=R@-h`-ID@mQO.nr?\n ()&[N5P7IKk@j32(/FGcb-e6Pl'???D9T$8=1CTu&e0W;;T2D&.i1E],*\\i-XpI,YD1\".H4\n #oPu\"Bl7/:+%U5W';;,1:`BCQaK]NU6@EW4/%*rodPac*P8BuYFX)IRAsJ^M&@5mSn(!H=t\n TUZfP9afRG_`7^VYDJi2%]f5*U7MoX:H,upk,2PGAGu@7X8Jl>H`$j1W$bgT)d\"!X$N1lkA\n NZq)P9_kUWUQogR\\k<=%X.l]%Teb&$:t(aaV;2`5dfPCl.>\\'M,\\WrO-B:?u)`(u=(lfgp.\n gqKC4_[>6V,XU`;VGDLl%LiiU+&W.C2EENFR,)HmB04T`\\@^&AYr?\"&rIj!533MNPV`<9:`\n %;@-l_EDd_:B2Wi[jX%1\\^XieU7],l]2#'pqj]Z9V#?k3GFXX\\38ff%HXI`#-Z;2%I3!>4#\n V]`HeXem_1dAfKMgXAM\"VQF2I3`3iV3-:sduV4Yc6pX6_)PA(Z3/M_..C<;iI*DPkq[UFRg\n Z#HF)ML\"]_6/ZR=1X1#17XGXu4cXg[^oql67H9GHqr6DcEJT?Y,\\iVI&_73PVi`o]IEUH96\n (Ls+`=A,2GCc[6S;mN#*&On`'h8t!g5+pSU1O&+QS\\.r^`RP>^'5\\I_Dml82<JLl]m7b*lf\n ?Vr9qdC>DQ2+SuT%dJ*f3>B2+%8`+m9j0.Jac,8_,r>p3p#3@`i/(2p(eKDWt,YU9K*A8=E\n '<uo7L>IZlA&4%Z0_<GHjT(WHXOA=ijNdZ%B!h2N#silt^>[^,^[%f,dBG_\\cEkqR1V=@p=\n 7?K!5@g#(iphc!3PunqL#a=\\gMY>cdT'cs\\JM:;U9TFbV'@2o66S.lLfi1rhL#)&]Ihh@*D\n RnTJobC3(6KH!>U\"V<u:kdeM]-jc=>V'$'b+N+c<$OY*G\"d7<4BTl@e#7a>Sn>#.b)>qMoF\n `.8Y?Y:`S.%>D+de\"+a<ERZQq]n>i?c!%:aB&-a_1S1k!RF^tBMao=<[X+tLp=3@&\"0_>;Y\n dS_u6nOB7Om?R$6/jG.N]g1Ep4guK>>K!N<@p'5n8fKMP>:(0Tr9-+U8Oi:`k>\"g[?>K<(P\n ?@$B\"UjMFae5b>0Ap8h.^NpZqeqnkC+@uGl@7>!E_Dg+BoiqOL?c1^XR:cMc%8OG=N8)>Yg\n 5s?7j)bORO=GG7!Bs&XY2E?PQ;=Mkk<P/4Prmj]fK#k7-HrEGkE*)rC2TSFaL<eI9JuCOp9\n sH,1JT_pI0d7.@]&\"30>gjLm4DFP`S;qLs2in?Yo1b&OpDQ&3C%N+EJBcs$:'49^N#Q1\"(b\n fm/'\"ef;`=Dc7t,-n[=,k.?'9>-lNEf0/RmB:qL2KeW?Hs4I,b#_MSE1PaofSt1YVGi'P%r\n .gDeZ4)0dHKE\\cnO_csB95mI,7=@30codfZMIm1g%fOVm568ZG1Y'q-!rR;SEIL7NW3&Vh`\n ftBhMV(+M/@\\HK8j;5>RbU=nbu&#q-Pf;.8bG5!oV*<raRSRL:+OoT[ZD[1qaA\"j?<H#W;L\n \"Xe`PangRE,cI=98;qd8,sICk<ehW40Qc3iYg(VdDNn%j*V'FujmqiCs]E!ZNK%05DA?/Yi\n 'J^!sDVWtB.o-kOJDm6-Ip)66@nLtM,!LOlNj9))<r,5@.0?ENV<<UE7p!?[`0@Ws^AD^0s\n \"tSR0.N\\S.Cnbk9rm,tnc[c%TOF^h,)ZeCiE/=k)N<o$8g;1QGJas2bO;m[/qN)p'Dli7u0\n GfY8!.j,H_,Uk^]*j_5(]e(Z^pFZH$Oj8b&CAl8@'pG?gC98#%PZiO@($W_%1]W2%aa_VE:\n jaGo+1?c&AYdenHBJd#8\"-P&FgJHd2<NN)\\I'1&htOBE?>gu,ne#)&E+-50fKbC3>:pG'JV\n Z`@(['P%hu9E'[]bmEE*aY;\\eh*((jgf0khDCD&,ug(*L='+V,B/HP_fm(bpRYEISh1Kc&3\n o)\"Ek-JAE+cS.P4[)A/S[0rZ(2XVt'A)R6R[5nFG:\\Jrr.)tCle1!(CI^^Ms.*<?`m;:un>\n QknXJ$dn&E&a9\\nm2g99*jP5W@?;4tkSca1*l59&+n-I;W(I*)+//*DE0DHN*?jts+t-8%/\n 4T`fUC)#qYcoNP002r1enP6J0Mf2Q&kG`;8kh'<,k=q\\dTIkO>:\";q-8K!VEaL0!AL>i>-K\n Nef+=%o!mKR+>&\\tJVT_]]1L(p?J)hF:sU$NgU,q8DY.PdhMALnmt\":Zdj,1!(m;Defb3<G\n mF]+RU]'$2M!F\"Hn*/J?;[1>+7\"h(;O`/[FCgo&V0kZjhOTBHY5?+\\6<FWA!iD0J`kd@e(?\n :dN3G:!UqB[-D_r-^?\\??*!+'bO-_J?/M=?n1G^[?;_^(L4YsE11Qt6`o0spt[LN:6*<AP<\n JaOL$V(e*A2D\\o&E/Ir[!6l/j.uDM*c`[\\mRLtX81:'>)PDM8?NARu(34\"f.o9D>BR5s7j)\n h@,U_:TNS*A>lU4#=9+F1CIc]H2Xn$a6Bc1Dr<PV`0c!!hlLO:Q[ZdQTarr4u8lr;rKo]m6\n 7lH5(XgoTWS9'`\"?CO*at]X+o_\"1]0Q!#5r9:uTfa:1feG680m\"\\XWt:\"@3[p`sbmtT\\'D4\n Q]4$PPb6o71tF?`1#77=ol1uM7PiIVb0r#^OD6$-[-FD44Eo->LU%1;2`'\":!J]0-i\\*!(^\n 5;Aes];+U=T8Mj\"1<09aoSOp2],Jg_r?pYmMF;\"^h-Icm*FLb&O]UKJ:*`RCl'RN/gHmf\\Z\n e3N$HU%6=O)bMrZ8X/=32!IaLm7qcl4lN[Ti&<<R^JFM':c/B/0+oABn/<In9QVL<9g)3'Z\n kbsM*Y0>g2(;<9/P`],;RJ5XFYk?e^(:9r*s'A\"[0K[=9iUd^D%kJAeJ12gb>F6`6Dop_#n\n .e>ifK3=;meD_FZENgF]Yu%=7eZpTX\"R6ckM#u-B&72247UTSQY$<&[6sh[)k%&@55(#e3Q\n L@F`UX7]i[/,=B37DFhq=hg`'Y^\"bH._MGICjh-K^4?6ii/61bQEJQe<T9^ac##p+Au,@6D\n (>ZK$RQ3C[)$\"3H3@3RBD^q'PthAAOK?</@]Ft$mpF\"AKh?PQpT:TIMk5*?F?*EE8N((F\\Q\n 8S%NhAN!1W+ik:h^`T9>*k!Y4G%kQr!@kq^%3j20<NTbo1LH!m)^4<9:7#O8;/\"N\\B_I^*2\n OQ_WU]nU**5T$peu<DmX[)3=9N>A%[)ZAC)d>,H/\"m*_1cF@%O_j`XD&/UX2VDqf:`@-^!Q\n !n9_/3r\\m;DXf.THfcmC-_no1[X[;8j(aJ_ap505Xc&D7:0qf,&G7GT*6Z!45iB<qC@@/TU\n >=):o77f!fGF@j>Or%j@_g[+sYb*H@D\\FZ30?G>E&7=ZW5sEu/D2GA-Ul#f8M\\>.6Y!(-OD\n :a%3[6F]Vdl=,D'dMg0A&*<AbC(Me<*SU'WQ)hI072RdlhG3\\gK2k]Bh@J<%4,C(*AGk]1%\n f?&Crn/YqD&GMlHGM.DH0SMgCG;I?[%QeJ.ZYM0>I+S%=GP?Koq1%JH-'YJE(YsVO%=md\\l\n f%RE_81S%4(m.IC]N0,_8[Q59%lSR%)=*?3&cIl3J7)iKK)&HGX7\"M7>/0JK_SQ#fNEnf>D\n 7<-L,`UrG[H38AVSiOLA5nH3-g8rI><&sLU_nkG_Ls`K8B;ZM&;5/315VJBH1F$!TCm(5T1\n U\"^]@lT$_S%M@($'OX9u`HJ#'hDJ-I&\\Q52FlNB#IJCP,i\"g'`,*N]+G.=0D-q^a\\q\";GF5\n 'i)Cfnq2a2*O8/s@3=1cb%?PiGOLYscGnlIP'9W).Or5:'3@U,:/Ws6kP.<B3q)+AH3Ks7t\n PW:mk=[A9t9pE1cPaPO9q,`hA=dAegQ8p345kY>SkRN,,*C/0W\\?#^>W[4%N+b?^&J/'LVQ\n ]7DqR5pM.Q#7[oaHG37Nd7I:\\05@f2@Sg[BrA,fH!uuK]plRKQ<D+pq8Jl7adi1ISN4rc=j\n `dch4;+8SXJT1q$%qVquo)u\"6%Z;+=J0oZiJ_S)^*W5!Vd^R+dmWgTfNmV_.\"C8iL2d%J_#\n 0sQ@E]O:`N-6g0*U13U*<M3MZF0UcLZ7>!\\s19r,?tUmb;Zq;r`kli\\KVK0cRGpqqUbha\"W\n nTmCjZH?b*Bg)n,[OSU,\\<dB_4.-&1iLI(JQNME=r;l,qVWVWHjg8V)5X/^KJX#dMdHEWE=\n p^_mM*?`i5Trnb'#B\\qU(',)H]%O3sgk0$U*9#qV@DANtM6?\\&Nj:SfRL\\$I];o-8X.'-oH\n NgXc\"0hY/Yo=.W3@l8Fq?6oMXE_H%=&j8@$6GnF(qSV2HTAF1@+tp^*.$kPfr)\"lN8*Y0P+\n faroO?8g't*oVZ$U&j)eZT@Bt!nU[lY?I+S#Z&V?+-T)^*Q2g'b*r4h1BO\\L$MWo+/3HV6l\n SkR^t\"Z_*;.`1Ue<=]0!:0HZcri[Ca&e]DKR/@H7n`3ZB3K!4It/5o9rUQ+d(R^*K%AT]R-\n Nagp/!^Gk>_p-#fLefPi7d[RqcHc*Xga2#>\"_#+q_g_l6d*!HA]$t()i!TY,lBtdh,_`TbG\n @>o#ln[]Y/R[P[W.hP(JJC<3l_0cp84B]XN?,^&W`O_W]T\\KVMX(cVB\"BC`)I!NcFHnU31%\n lFs:r'SQ:o=A!e.]bNJ+k=@J\"i^CNaulB?Ht1<hV96HUOb)Q*fmg;ng`7P9&);ZYI*'U,hA\n Nd1aI;G9eZ$<A%MQ2iao&Kfh!*+3mE5@scFibQ60JfO6*.ZD@0*A95S,\"\\cum\"Gd6/5bT`!\n %Se\\iF\"Jc&$,glr[B_9'=kb'`s4I.bt$n'g)Qe,;_\"iU.366lR&h=5h:8!6`c<?.Ji1)<'E\n nh&j3*foDSb2eS8u*)=Yi6eD9&fKDaW?%LXUjrW5`VL!#h22D7KoGrp^efCU@HJT0o1\"O\"h\n dQ@'8OJj--2q%Vpdp7gcI>ummc.nl9gq*b35ir1(]2M#@'B%d%Sa#\"B(NVn.gD]=N?+EZ2W\n Y9/sb+7#>IF6ude_pE5i>LDl!8ms%24.bc+(=2??1$Xc/V)s?g;1ti?#A>$7Er]=gYpW:/>\n (lb:#Ol(iEfOG4ZFG>ciR3(*C3X9*\\ZZiD1.r%h`a-^Sit[G-b=\\!b!&ti*f9!-Ms,VLiE>\n LN33iQAo1raQ7K#%)ri,1kls8QDaF8@!IC%?@UZ_)%[6`QHCdI;,c05/Sks!G\\>JM<\\n-\"0\n s>N+Ta^9-h;m:tUI-_Ro(*dR)-DohpnC.NE@//R]'%IH@jm@P-`3Q'so-Vko&&KmY4s!dNI\n /'&m-j*pgiSCO?7s)ZnW*^TP\"N\"tlT&bQ)>ocHp$3_R<JZ3qc]:)b`+J`Ii$/b]3a=ojc'h\n YHbl]CVUUo@>ki-]/X)`Z>'eoj=!WT3(j'QheJU%Nmc-+kd^j-hfj1q_^uOi9#?7pTD8ZkF\n MG#/NiU?`3K-H^u(^YT:c(sg&:s&Ob((OhOR`!\\dq&Eqd9$rFMGA;j<+W71O]K1A&4iB\\3)\n 5S$\\OchnJ;$h-PD:Q=Uk_UC,6fi7q<4R'RiOi=LfI`q,FM\"/XK,m',d%[Bf2ASk7a95i;P3\n UcY)k7\"V-5TT[DtfMDZ`K9;b[f'\\\\O1V,aNql?/Q'C9_!H=)8Vp'n423Z<?PFRk:ejCpdJb\n (AjB.l#F;ikH?+tFf8:??Z5]*\"qLlk^u=dMN&E%$Mn_HH:'ocQ.@&(fo,4(LD`OB7BCm)_(\n 6;%`dqSInSQ;psXk.@^)]b6jBsl]4pD][SRJ-W0)]=Ya0+K!3j$OuP:/kGbhi`'A4UEc8e\\\n QVt?e`<HDXZDnGOHRopPZlJo6Ga*:KO1?l1TK&h]Hd_iGrfP5oABYn+HY\"5EGWq?B^E1$Ni\n Z`6k]_iE+Bmm61BOP#srU,.gn]5`%oN%a\"cT4TPc!7ijfOLQAWWN1+qe0DO[Hd(?[^<%7Y'\n 4jSHmdZuZ\"5;8dZ#8$W8C+\\2)CK-EkT@Gj*IDtF&X8[=!JEY:_\"Be)gH`3V$gEoahc9Ci;(\n 0hcX6b06I?iVG?u7gqS56kLF!&Od1G;M2s9AFSiC`c9\"H]+[\"I,1(@!#pW:=2%r=(F@@'9;\n 7)#uoUhoB:hpEr'Vd%jo[K=GN8WLo;,hZa92eg_78m2dF_+cY6Npo:GKn[6jUsQ%[-:jb;/\n Gi23bA-8H.D?=,tD)0NKI^R2J&4f=]U6GB[K<uap:qQjg.\\9C]X$GRhd<fEEm]6bB$q_7FQ\n BbG@FTu+(sNOABh@_lSm+3]l.05BU&1>7>%S4E]Z3q>A)Yl7Lt2VG\\.VDiHTMjLb:'Jl4;V\n bjgC%$#C1hr@(?J/O^r_a99Wo^7T3<OB)11b?I95R>>D`*Far#R_4#Qh\\PkeNiVEa)T]c.e\n MkXn]*g4.-_t[,F$Im?YWFIua!-ApM`d=h'HKMiCC\\n=RZ\"/Vun9p573Ph'=q2T)mB\"-fk?\n fpS*!br_P)_7^tg/ds_DnH;M_/K5kHuKK:AiH^Z:YEZTMEB-/a`;d,/'Du2a\"ku(7`j2goD\n <]B?1&B?kL2J(g#d['8V[W(E'8[YflfNV@G=sU=OmlMS`^d')e4t2ep)WkMrT']8!E%.-J@\n I-F8:Q!d*>jTF1QJSIll`b]q962HiEcWmehP9b'OW7%st>NbW2[SJB.3VIX-F@lhc/2a7K7\n ZC!copNb>$>'8$!rcW'&?G&S7RaQO]*mGgB4+S_UfjFU3/$:/iadfE@5C+l_#35P/H7e?P2\n OHpPHGYnfV;X53Q[!KM(5lhXh#%l/O4UL)[4!8ndJoLE)6hiAI+nS&`K6/aHQdl^Ld.A5Cm\n M3\\8TbLt#;i6];\">E+#1P[50H8*Ig*1'5+=i,InBsDlCf7spt<'lS,&iI\\mgB:\"hA-)3M&%\n +.I0*Kd*O-0-#8,30.A.^F1#fJ;`fXVfk/7Crn+Hd)J`]N3SEKZI$91J_3-\"P1/*C6V2a([\n eILJY)aOq(D_Gu6&&<3(%2TRMV`fcf8fZ\\C2_l:Au,%>bDA*(/gQ3Jf[KACSM[o+GJ*;qO0\n !E#=foh'W\\`80-f&e!cJ$CJB)YW^SW\"*R`(ub?(Q-+f!VT7#5+YETH7o4R8B`[U`.Th`H]<\n mg]>4B$AZH-GrO1T9Jtu:\\k)W:b-*!@<Js%kn-6dADplni\\<64!l3q$ntM>fMba[77::rA%\n Noe=^;QI\"`/n2r<0i_GH;R:K;*#;a@!'RA&M5D0D37SRRk)Pk1l$VTEn\"]ZdAhanl4lL*j3\n 0N7l9@(`8Dt.H5*aXoTi>cl;j@GaGRo+.5j=6bH;rHL;gEF$aU!bBj//Et)MqWJ<C<m2V#$\n -Kl3Jk5FrV\\G-.PWX?>J)<YE(8e#>q'Q.`gMJFO%&4BP0]3_S:XhJ8u0/o]5=\\PHD8o[TRr\n *>H<HuU_\\,d='G'\"D&&hQQBouTJTs3\\Q%Q;`EeW')94FGD@N5H#QJ!c?Ao6)/\\!CL2=h<d/\n Wa0eTpD2doH]`>K,d*F8L=TA*%8<mVDlaX9('[X%3(Ku_D`7%@?2M<[D=#-L(CKak90mU%<\n U7>b[eCpG7*BIrKXqsl(f8=mF_#7%(8uEEhE1g`0Fd$W<;uI<X3QoI:%,oc2[<ag+DG4kqB\n 38mf%h'VFQXZQ,_<fa&&nn-0IA$[GaAKk7NI'J%A1.t7i,Y4@>o2g/J-rAFCAtNCTu'>Tss\n =t&eUMVgC>XQR%#;ZI#O3X<XHm'mfh`6Tp0S`;m_0,(LrBfQ>tH1^DQg:&jZp`LIOYQ3?p=\n jI*n?]-;2/m[c,p[WLS$qF3^!L&.e#NQ8$#GVKm?giO7fh`rP`R/UK>:I+=s57Z1C%ZPBa(\n T:L(iPL>n#572tZ2fGjF_\\r1X>:fnG`9]M2g+,PUI8-_`?n0RW2S*AR/Za)\\Zdt2mFZ*X70\n h1l,b;L/#>5WYpF9*>m(M`@qX\\l+l<ls$`VcMsHS\"t20e(U9mCH%@hR\"EVpf9u(JBBs&oQ/\n q,!4!RaAh3Y\\H<iapM4fRg#YIo(FoA5S7(N$j0VYAZTa#\\EPD@ONPK>>kSX`&<#IFl=p:'R\n j_],##glbn%7'B4n54,1AR^,GEVbBH`Hl2e%M8%U80>aL-7IMWO(DQ^YL_i\"$a@Ea\"[(_p4\n eHuZ:_Y;ksd\\s`Uk%AD=o3CbFX4V+;X%Tg\"sIl$>[2lCci$9Fht\\Js>]DKDDSYOB2tbJA^f\n NrenNff)=cSKG00<e\\tHEVeeQ6aq7<iS7-=K,TB3X*%aP^H:$'hpg,HBECq$HQQkhSYNOdF\n rB#EA01-ObK\"l-+ll4N_Au\"i]D$b5QFlQiVQeE+VqaV[r'uM2^5p_fmhO9XL9U5T\\(>s*i'\n &jq@O\"'D?#u&#ep6$QkF@!j%.&]3]e@:qT,5tccVrQA2i[MQ2s5SekU+=-lh9/plZo%L2u!\n Wl7)CKjk!+Ri^*gu!T8^=.T,+<<B@-UL\\+aSkZ93oWeb[$jc0tYB,=jf[Cs7\\*^D$Z4quI<\n 9oK?,s]jpfP9Ed[c.Kbes^SBPqbPO?K6pB:mKlT`!oCG3U%DWqn.sm#c9?\"YN#!jdR5s\"*6\n 3-W/jlTN/m\\_DWLb7=gsd$IuJ6+d]DbOIhJjT#Dr5suh^$m@.:G)+.f3i!NR_lU/^(dH)u.\n FOe(A/ml4.Di,u5n!iV<$/ss/jenX-kJ]a]Hk:NlbZkd5J+ZX#nmH2TGMDp6DPVhHW3;l&J\n B1;_YcM`bWR7C?jB5J6Q?lZ,T\"?chD4;P3q.))Ha+AT3CA`q6\\Iu;,W\\98[Qm5D`4Sc3b!6\n 3:1n-aK_uokR1VGs+NsLhOYOQ_QCe2Kl<A,%X\\9'gNe6,51=s)*^.<JBR,UGUt?:&GaN[o[\n j/6'T!@RXO35TEkCX#J#!Ak$TL+3G@SXB`[PC.'$K5K$o`q:(s<F%'nS`q3cBXCT8Eji\"N=\n a#nH68]hM+Ifh*0LBM>-A8=+\"l%I],U\"!u\"r-_'DIQK*#Z!:DO<.RR[Jf,D#5+Hl:e3QM9q\n 8MoDUF:)XEH4PPMFZHZ]1abAlh*b)K#m;>8GRC__i[J`C.6p']B_)($d-P\\Mb.`6a`>Nor+\n -9.JB7q`8\\CQ-$%b.PEChF$87XNr]JPX&63aF%(EA@U9UJFV'ZeLd\\m1cJN2]F;;Aikcan1\n 9VXIq]*Tfh?VW$--&<0tcJYpX(M7jK0IjJkjX[S(<D#1;U+`0/9ePKN/.4:JI:A?sD.^(us\n >W_Al)FMUWj_@=nE\")-W9PX%mCH54#IbKR7bm(LW#hb3l.bRDA4bfri6ek3<g9$C,NjG(Q<\n [g)*I'm.RB9Z^\"2n]\\?kbf%e$N7gpmc(8Tr9`2HGbf2?Q3A%IYbs^,W<6@rJ787f7c%OeG9\n ]]#OR@#,T8aOf!N82PQd66\"-#XC5,$TjVYi_BpN:)h-oFL3#ujA'7W:H[c3YUiP6gds?)^<\n GF>6(JnP<DMoM:V?QC7,pQQ[803j:]15e[.V_7p/!<r:O@Q6Y_E:;m8'hPccl^ALoJ_U/Pk\n a6:q[93Ob*[5m*HaGcnlP2gen4WGDDkVPsksS`<fC4\\Bq!P\\:k@=N>YHP:<1$Kd.IrIblTi\n JlGX`0#5DNBob:8/,#M>b)uUR2N=/US-;nZZ#*=%a[2ZO(*)YN&dGrH\\lnHRB;c.*Mde+iB\n ]d0q#o$VY:;`nYJ]@mJn.>ILFd_+jCbC9TOJVS=l'eM+<bqI,f0qVH$dmZN$$qr\\VF]3-8d\n tIlug?D$d)&4G\\;[l8sGkBJNQI9&)<4tsoOCO&RH;laO<;e=EeMtoDCP2+j#;nVBh+6'r8I\n @%A8qfshNEJ]==\"#b@eFbb#\"[l0M*mGVf;kS&a8d:Oq<n1Jc<[b0%I.C7E=k7G&63D%Z79i\n j3?-NgI#Uig^7:K8.DH8o<`0Bd_d;;h\\B@e_V4HNo%<GBte2q8Xe6S2Wk8[X2oJl^]G=1r-\n FpomdscW;E6fDU4\\Kf]P\"HrjTYfKEupQ\"u0mEiagIf?J\\EeVMSCE6<OXd=m,'c&Fo#4;\\fc\n <i(#`PslFF8J<D+=ZqU/SVk`2p/gpHfmT5HTMpUGG(R55#47K'AWYU$GZ0`OK;-06I?`G+M\n 98hI4Cr,-NMTf_M7En=fs#AJKq-dYG1@&&<j`MUY]$ll0j-r>g*A1P4cA$*Z<JiHPQ3Fm5]\n >AASQ_kug9$%]mAu';<4'oQgBG5nrNFrjQJ,'>>Q)>pOj42+W*<iB>Wn0P]q.KX=Tb*E>J7\n ^RouTEU^+Vpi>Ren^b;fbOb1nS<gbl(\\4e>-6`X!E$LT8FYouZ!K]Y?&@aPDe[e_+5t3JX\"\n e[b[n;rS:Vq\\)$Gj?2^j+Li:)JP*54_hEBGljk%:2f\\NCe?@+(&l[iC7gto0[e^`(!Hd(*;\n @9thPh.?(NmH'YiQX5C;?TQRpW-;REp0#)pfL>/_qol:4/m_!9hY_k+?#_WBbMPbg?i&2SF\n nX[ol<etL?]@q%i)tgc_%P;q@\"%r&\"nAfsrnmtg@(N>D\\1e1P!T5\"$?q'HDbu7V./`;?[iB\n 0TfST3Sj$t4#i.7cl3Y]Jaih;&7l>YV`SFKRq[#85#i@K$PB@a8+f=CHY'@QLL<Af>&'h;J\n 8,?3Ut[i^2.//)gaI@L\\T3*W=omk2Ji`@etU+G^TY%)WNFs?FCg/p)M.X]fW&C'\"0<#N[uD\n e'goDF@g5&*b#8C7m,KEKia*R/7CM5]XYRtT#E,hHL,n8-7U]$i=LI:$ek'D@CP9$eA+i,t\n \"uB_36=J?c()\\$#Q:Bq>&nA\"8ipKEM:/rP,:ZTMOAC`SJ(0P292GdnVjUP1\"c;DC>;\\/itj\n ^)>,$06kLI#$Q[#4>1HIV!)MpZ819!tfg6dU/*U;.ct:;FX19-8&mGDJ&/_9L*T05%N^QA`\n O<\"k&YoJKIGu[CZfS@jXtB/gmV`eDeH5\"*FMPFfQCgAS*(hpB/VU+IR42DDb^$9k-fKsEjX\n rqraeQGk^J=/+CN+\\IV)&uk:U?*Fp$`Wgue\\IBL\\(s;4qT5Aa#/<BfY0;k$r)=MeR'=kPcg\n l%NJm[C'P;rZmcAs%YX*$B'CR]k]W2*%\\XgLN!BiMkcU:bAsmA/('T'ol->E*k,@KMGiXT@\n C'LBscE.sZ95!+IC-Iqu:4QoANQo7&L6_1gVO_L/WKo`?$pJ%`hRREi<e^D#CBg,@%ZG$Hh\n J4H(l=4]hejMo/#jZ*%Cc`j,Gee*T\\nl9)'c;\"I^+k?`]^2esCYfS:?@cgf]/M0)CMq(-!q\n L*/D.WEeCjslN8Q,^6N.SL\\CW=Q`jsB*NRROfo&>$dVcI\"dEdU1kND-#S4#qUa60l;)ED18\n \\V:<Ml;pMAC-B]FIB,^8C=#OU*hm^h6@<dEuMiGS)P',XiINoP%!jD;9dBD0PeDSKbRpqM`\n LOG<(>NnqrthWhP4mf*-&aYMRnnnpY_DuQ*l:8Ml8kK+iHLCeZG0)=t%llQ`)92=nnf*QDa\n $g*P#!mkB\\pAXM%oC216mUj2qD4YN,[#f21EBaVb:C$:e$?9u#%DY+D(Cfb\\o'M1nE<b-&p\n jiYBgET3%EDHf0%d`Yedd)Y:nUDg)8DJn3*:]X#E9@4@^B%^pk?6_Q#?Z9`G8,'6+;t1oni\n nFA%l\"N<A+IYfF$C1PNuW2Bhh8^lEn;r8O\"MLB0CY#Wo=mBsHX#Vk)KL<knD?(nQJ#rt2FI\n ]Y#7MN47kO@?3EHD:Dmd=N[lj;T8e\"8@#7!'Vs$-,cjmo#9EQf24[[[n)7WY2\"Ok2YdY>o^\n If7YljoZoaENuN306/t.g:bZ&'d04YW7eQ/+FFPLjLK8R?@LY3+LN\"a8f3*8u=n>\\qFTeeN\n XuDG,??J261LD=lmhU(\"DK[\"5p.0)q#?Z%;..@0nn0REjV@A:XG'$f$pO?sOpMBJW#^5Z`G\n IYhOHm<h?IWf@REdpi-G?X;QK0HE8GB\\<*YD#2*H1EV*pW&)2^bc^;IeOA&pE+qOf7E#?6G\n jsKn5!eCLP>Loq=RO>q*1)MT&KuFMYOApp1K?Rs%dSTF1'@[TDsRi+.[%_PBfrrH2)lCBj#\n _!b'+Y[pqN3b7ud$L2?N)nNk[uAc^jkZW__6$`J6-n#H`#;AtaFCGdjo&IqA@-JRsU@L@Am\n )M$!OG[UmdVqVSf+l@O?^YPT,VG&NfD-/U'+K,-,&HiL+O=0(VqL\\m.MD?)AH5Iu.o`d8ed\n HRD*o:%s:rHB.0sr\"%!eJ%,>?c?35SCIcA@#FBa$=aEl'I$T;Y3,]&('91nmrI,%Mhp21m4\n G<KILL8F,&%cr@aEa,Kntu*Vm.q1CfR2#\\$Fe]:Vr_t0c@V]t#3Xe>DpeK,R!nG\"I7@@Q,^\n b%gj8SN-Dl6uUQA5BGnoGf\"#KQ!3kOeb7d<olgp]p,3cC!BH4aaI$IfJF#kN)Xrrc\"23#Q\\\n 4ch't+JOB1=@#7>@d+jd`OFKGY%`1iB=Zt:dg@RQuraRk3Q+=kKCXk>h69e1+I(p3%E_HpG\n V2r=#Dli)#gSkj\"Jq?7(W4$SUpoNFBrO\\;NLBf,Zt6CguR<9i!``E'<HX]K;'qV?n>@^&u$\n eltS+eRu;DD3k'A`nPRE>qT2_`SU92^0Y`e]0\"O-+DMWV(gK6D&W=V<EB*l.6QM<3@@S`d>\n n8f^c=_4Or<A$GUXEjug3lGg<NF\\dFkZeKa(;U2D0FZ^`ohKVhJ[VmrW`[^_r>Z\\gjVa@?u\n T^;TcEha4rY*u6R-T2]PFbomRXsq8S\"huiJu-0de8m<mE!%hE$\"oVa5-=]I/`#1a4'_UrVh\n ;-qu$N0YT*ZBYY68h\"L:j..gA:9CG*iA:n/sA_U,qM%)Yos3=`sRr':n4;&i.?`6g\\E'Xbk\n fXE6K/3Xg[&Y,#au7aB.7n&J2o6LdRl,$L>1,uMO'4cg?c,fp[(#pr5ACnW6!;KSldb-IP>\n /BVoo)_Sttr#IJr&<'UEbgS]%1sJs(ff%+(I,R'1;k3)5`C3).G/a(-UDh-iS8R[i;;t(dd\n '\"H%+42_k?9t$81lj4\\oUR:#b7qW=9N'Bb3DIuPeNldMP6AQR<0]ED1/?A*=]X)'I:67/<L\n mi-f%%HR>*rr\"k<;?Mr+/)p<\"4[(d$->u79N1F^13YqiV\\0b[1,>qg6TFSCtc>RZ#3cHmD3\n VgFZ%9=gsB&$>hrIefll3'IGoG-=.ST%hTZ):H65$;I6ZW1N,_/((.F9Qi7;&BD&u3dVf1P\n Fp*\"D73.<02ig@G-N5-5McZ7PQmF-FC=WU.tjOl^oPiZ%S=]cb9l26Cj&WURnTf*qk@c0eS\n #t)?B4FiW]B-H5gj&j;QUZkrWRA=QN?D\"+/R-$W5j3nK*QKq`2\\ZY8PrkYi*>92?SR:d!)R\n `5*Hs+'9'epAFr%hTTnkh;?mW:*oEq7Q1.hYk73HD[m+nCL#^Z>j,V)924%Ij)o(>afh()Q\n ,dJRr*GhCU\\B1h@#rh1'#C+*#=`n_/K9Z<S$X[Ip(EHg4p!Pn@H!I`:BJVH/A;Os+0,'?5n\n i$)s:iijNk1;fq%O(2ar>dB^*N_T.Upmm.OcCA+'5#pUTar4g/krlMAh`o_i-(g%PC%J)QS\n -a$JhKF'D_4k0P+HMn&UYN,HBbjRsZ(\"agk%nN^b$![(FFI#d%h1'_q!@&+Nhcs@,HQo,)n\n 5h6tYh>9MTo&h+Lc?%>-kbt152[<RjJWRSL_\\a=$+e1<BL`!t?BQX'@aqB>grZFTGKb35h7\n =A[UI#kd*rRnORD6TFZ6A:Sa\"0g)kE4QuWQtmJr]NU5uEZ%.;G6ChHk_RWX1e*k_)WP@F<h\n XK!`4,+ISEs'AnOXdb^p5[akr0t:qCbAV_'%b8Kof1MVa`([,1'S,NRC!]8Jrg\"jJ8&\"_9?\n M]kOB30>]b7Rg(V%5j@]]Y+#ia3<(KSZ+sgd#Q,W#W7S.-$A9=-'db\\5%R<:.B@OuR5DE1A\n r7jmFBes$b9;'WqQ/4UiOPk(hf9%fsik*4DbL'AX=aN\"FWoXp[BIW/%\"`AlY7U`7W(@7eSh\n ^L8;6J!7T/&cih,a$e7BdnY9dH1a&Xb^u-:DJ^8)-TNS$\"ea?dKM[qM0#o[9Qntau8a23*h\n #l&N+eWBV)=9X9h#4\"tG*#S@Rm6*FZBhjIPZ!rM9'Kn=3?qAn\"YkWt.!qAV;]\\$EPn#l\"8\\\n CiuI\\5%,JPbVEeYJAR7T+P<;X.gfWRX22'G8bVa5&KiQ!0X%\\^O::V)b9jFCU?Ikte<*6*/\n V&ZrC5S?g9cSUsomQf,EaUl_S`jMa2aq;@QX+`EK.(qQ<[UhaLWl`Z;IM[8raJ@dI*SYpE#\n NdT:9`X0n4uem?R'Qf8n=2129Dp:o<!feHn]K<*)[5`IWDDX:qq[C3fi>6tmPC.&W=Q>52Z\n RrrW9j'<1*5]U#mY>\"6+U1UfRdn1>b(e-dJFU%!]>oR9qm<-p;1M5@lj<7b[mG5D+IdgYYe\n 0HE<_RNY_LYRc+^sV*(*olPL?#/PEDl(mrYVt3@VQF_((&bo!rr?F@5Uf1lmC_#\"\"C,aXB]\n Sj.Y_7[?<\\*3Yn>5iqf?XiSCU&>kac=-'$P6be7>UIWZPQS\"\"5H\"=BJ2f'=>l?[@-6B<765\n _2G\\8\")N-0hog.K+<8Q9-r99A]k7EF.%Arb:)MK3:H`S!G2cIN#Bg#1Ztc<hONgpN1ujuLV\n `#9VpTacNelA^&i\"1g?Zlos/Hc_)SbL?C[iH0p*1ZUEjeiSA1Zdp3k,0pn[$l32psGC!bQU\n 6ti#g4GV;]$<b,7B'gn&D%2'=KOuJ?_el&'k'tk5o1s$NJCZ@8MU^@P<,.i@5_e]fdTO$Mk\n 8e*:mo<X;UGF31]g&E;#//WS_bk\"r[l8G1`RroeA4FA^Si(\\oef%%N8_iK:UTgg>8Jp1IrH\n G^Cp=upB#=5kZM6_=PjkSU]pBQ8@3At_1g\"JqSm2Vh%?fQ:#]4Z&#S\\)W0eO&%0N`p1'dD5\n N)\"lRXe7(Ia\"2`P-idX'3ummRF\")a:jjS*POnShV#TrkcS.$\\S!k7EG9KoFiHcF`>&p]K'R\n RhHEup]^8faM8?OY>[O\"BIWY;Ymbons(R\"D3L!]Z?D&#EgGB1D8]=MUXjgi84mlk4f;6\\^p\n 6f4AQ^2ql9hckIJpOH'la3f5]AaJ6D'+;Y%4F1($iRk&pdr)(k#3`\\dI:oa+hY#J^inj#AG\n uX>EdGXpML%*+gAC`Bfds,e,jh8[9oeWm%#3bFB*UgZ8h_F9b\"rlnef:[A<7Hj[tV)..>G`\n R7o2Z-oTp\"R6ZHQODqEJ.+,U'fFrIl6Zlcb8q-9>C)e6g;<4`VA:0EfXZ%lMbFTq;/m,HS-\n K6ftXpaY*V8?07W]okM5gNUYtE%L[kBljo!nmGj+%SlNRmdqB*Jlq]=_h1RH[[K=lTrUL3c\n 1kM?0a^+>>^bYQ7Vn-]6C%bR[UVGGkGO';4ZhSCjWmSE0mJYkRt@/mG3\"#)Y%O9EI_#ltT)\n \"AhS3^q^f']_uc;rXYV\"0HfX7?B`3?*2\\VnDuTp$2$VEJZ4B(e$Jbgr8I,l[#YY()MDGDhg\n BCCnl*+FD0OEI/lk89a*DeHq:i?]fWnVJTUp,=SE4ZM)^9Z\\hMU7CbY`T*NcMgV7!_G:_+S\n </TW<X!p$Lm-b&@D'?\"Ukt6%oDu*_%9K5aUf$1mE_O6Yh\"Z,C((9:%M7e8OKf:S^CJV=%hS\n OLOXh'e=:ud]*>&A^Yfd2i57*:>$-d'XiS`+Y>7n+^'erafE?_A:-PGrZ(/\\\\5iACs>3>W8\n 1q=-fdE*sk5XS\";F&^a_r;23RSGj!I\"lu?_WOdd61-kpC@$6as6Z#]fiPl:,t&BdQ18-Ur6\n M&[+e(p3`S%mGqk\\Jaqd*DtC9Tit!lVAjO6)UONYn/i4',6!Uu)kf_?lOOs)`>gVQ+=U5(b\n 24(Vfc^tA+\\1B)n7NdT*u^:)%+26p:L+csTb,6q*:\\_*;?8#j3npqJ*:[G\\E_@\\+:3$AcIZ\n biq0rZ3l-R)FR(NJm%nTo7!gu>U=,SC>,np#nP7\"!D0,nbt]P)<T)Or[uq-'DCT;6(nF>:,\n K@+O+#l\"'$_sY:$W]Fu\"TVdRbk8^FU#7?B?]Zd[)9.cRI;k*g*]#&7$bO\\G7Z52);EaEj[N\n T\"Y5KY/(2BiP5?oOAfG=u/CI`VP$]e=@5/C+)_u+P&b9#jE#u<e0%21#ZRVmDo\"T5>0Cq+Y\n P<)FWnfKXm1f>PQ'+Z:N'e0dCjjP2<iF3d@SM\"t40(WX4LM7a4HRL[-1XgP,PBoW*cM9`!/\n JCW.ZUm\"%f.$3U0p+lPJMcI%,r3qb2KPVYo5>L&F!1(&4&`UMKJji:n/l_*34$XbP+)b6P;\n Q(p0u4.i1LiJ0V`kci<)]n=dka'A]0?u#5=:)F@J1eL`B7(U4L7Zs1Jp/2db551Cs\"Uue)N\n U_j[&$i1C)5b;tiW.01,h@*hmX>&ZJ#OLI;fr4OXrqPF\".G?4-f=\\`6CMe6>6R>mFmP2\\>F\n AoJ8tdDasn$6_UtZF9P&h7haBF5n[q+iR^0o:IZ%^7J)oH1[.AC\\OSKO8lVZDlE*QuHUK[q\n 3:od*'&+lfAsB(B7?j33<$P)9YsqZq7[0lHPhSpKrX2%S9(Y8APK?HQd7=t*2(fl*@=EZiO\n \\D#B9[s8E'IQKehbb+%6PSN![-'rDlU1=3;H36\\ZqV+2dSCJQ1pkS*PrhfOm82#Z6F@P-Pt\n NO@\\/9e1;:Q[WeL*VI?Sq;X,4h1c@3ccmdngcD;jDK(_qe9Ca&I1U=B1,\"+NR^9=&Kau<O2\n p.PRShd9QM?P%J7\\BQ)du/Xspc-d$95cQ+L8JBir3c$/pA2ougJQb?8rW<YPp4;7)Npb&l0\n T>8=8A[Hh$fb?L7H?WHh2<Pr'M[pSgS<KurPe@-mWSP.IeD.3nqAYM#Hk@,1l0\"(,sP\\XWl\n 04PRf?e*8*p&eGTc\"$Fq0U8,'<@q7&\\>jT11fbi-Q<Qp].+i]!Al`OW[PqS03F%jRA+_'W<\n _62rLC'nAlN9XgQA]3J3G&`>AsSctOLo,U4(f<pC/rSj;[l-<&S0*b(km6Dp5a\"??#/GXBd\n k!.2OeO6cKsKCUGefXp=j*.Ve:/Z<OR<Yd<RUu@:aW\"DcX\\mJsgFm\"(Kj/E*!82(8#>\"fkp\n G*>o)O0QK_FJBG9T4CUX+YG)\\f]ro<_TE0iM)N_<Kj]l=i!FB7@BQ?dJ97pU=;CD;L8Cp@Z\n ?.s;^X?C*A/p<.NdDg)YKF8&%=f10g=j(_Vq37f/pXP+1:f5c'eGunJ$f4]rKF*\\Xsj>V5u\n iO*lrYA-!29,/aUQW%;c9(jbpq_n%h=-n<@BmJ\"CH<8^HNQMXMq-8-GHFL/'[bH.06ZhmeH\n de+\"CP3&2KH$dsI$`*.Q^GrtddT1QICL)EN/@udL)ZK>Jlh,ZfIM'QJTTMS>uhCsp?L'Lg8\n C]3J@EjXOKX3JKn6a4KhH]Bp`kBWjb=T9GF.c<GVrm;Y?e4C0I@Zj=:KqnI05j4G1]lPR#8\n 40>Cq*0L%o5$G\\MdgH[g.JK>G)R\"%.`dYD<SJLfbCJfXm'b1BD`aN*)EufOogQnV5ZgK:&J\n S!I>aU]JK>fL\\U$/R(&\"KmuIj'N-LVKR$iE4ItIH2MAXrG1+F$T`GYiAN`d0V.hdrqo9't8\n Y+b/G^ml4nqi$ptO8(;`eWkVD2hr\"rE\\B#\"\\ET-d(uk?5P$(kOMO=>cq3&S%Q8nW)Qmn5ED\n j.^8PPGN;Y*?SYmuBD(Qs!,g)-)s4O-p=f*D3;s3Lc3-CQfRrQMA^d2n+$7Gmr(a&0[hh\\?\n 2-D;4Is_R+[[nRED$)WZO6lQ<BiD3MD%MVhqq0GWBu-=[Mf'0T,[!S2lFuC&+9Ec(GsVP/4\n jR@I]mkeXbCJQIu.t(DWD3.5]u%&R\"drqCA1to:Pj_UKTR8Pf'0i0;0:!RQ;=X3NJ@re!(]\n E'?]qdZrSuNqkDePL4SIsJ3Qb)4qSp.URHD)Lsd1Bg`F$kSU-'WH:=.1iKkGDRb;n&R9u([\n A#^G\"gS*U:+??=a8fV7b$[R0#R_\":UN)uI%XBF5PH53Cpfp=[jFS2(BJa6l72l9d=W[D$li\n 8+Q^Y-t%J'4B:igAA(p.\\VFRXEo`!)[iaYbH1HEWE@Q0EglY:LSak1Z<F'86.ud`0s:r>*<\n A\\@gAeM65(,_,OT:lTgBXZ\\'9cTkUtOq-'LeimE3*P2Y$3?\\C%r]6ecNH=Ob)!sJHrP$J%,\n `0'[cfbJ[N#\"9shLR[2?rh2smkqFg\\Z[<WRdm38q\"ZCV(O!\\tR1RTHCX7A0&L.',uS:S'#`\n e3ZDMZ\\@^A'3siUSMm3&=[97REpUh9gB;td9[X7_!TtCcK'>*JJ*atcZ>Kst=%Vu.kSt\"EC\n fe9l4gTZ$kN16<=)kX67D%hSZ;d6H?>I2)$&/r?e!*fSQ_=ATI]>5Ic`C<l?$WY$5?c!dmW\n -fnJ>Ua;J/Yr7_,%3YSW*?]84ieU(T&K)Ii'kS?+<$oY!5\\RTJbR-2T?7@+&$(9$*#m&U+2\n .S``gP_uHuZ_5k9==_)`;WUr.W&dc>Q#\"%=g+QkA2)Fi[ETWc<TL<+Q@58X3/&:b<+acgq0\n tA0?aI*i@A!84O(r0d!Pl0$m6G4X7d,jU!B2RdRA0b2,hg@*Rc\"1cWW]^Ro>9X(!l^?6m2=\n E+j%J^&_.m356:Zm^f/067m<thZXE7MI;@EQ?j]oT$))^grA2n\"pVJtNfN`:C4MQ\"&0H=@o\n eQiX;M-_6lCXK('*T;AZh/D$'Y\"fi_+2)m.h0IbGJ'U5g[/G^-h2/k6GC3\\]ftEa&-70_*a\n oX`#G/<YfJZ[ZIn)\"8n*7'o)rOptAIGc,mdp9r+]XOS_5CU;lL;:E$4k8B&+5MO`eUUO9i3\n 330jAc5b%%o?45!.fC:)bibhn?Y_S\\a5HZ.\"&bgmkq6)B66YM1=KpiSGg8IVOEWi!p[-egr\n d#@3Q(c5Nj/?6c\"m65\"Fhms5714jZD;Vfqm$O'ejr=-se(ZhIok3\\-nrAis)Y,_0?W\"L$Tk\n t6D8K@U#YA99AeTijS^n!I6$6Ac-+RmgKZc(T'P[W<$#H0\"5^J0_=ATi^$K).n3`!H4,N>g\n cfj6;m9P:d?<>Ie>K6W\"0R,n*__pl=X7HNI^VCTQKhr_]mKS.GoNt'H_(A^f&b,g!nU?b]S\n sf-(CUIJSO>9ru)Vul,0D?JeWh+?)m7&+IC_As(pg8b6T`uDYapEWF)a@3e+.M?J\"ms$(e%\n ]DB(hk$)611?5o09TR62D+b:`COa!5CR\"JZ9(X#TmL6bb'ajT@u.fihJ`$)aEH[T+UU#=n/\n +iqL/sc]$hRL!7lBXhsa`)*XmN55N,G[>W*`9M*n#\"(p$Ia)2q&En^u?;3?OASA<I6UN_^s\n c9'&t(9YOX`QV;\"T3OHqK24VqS;q^72G<qitVTsfb;5dIp;JC6QANlY^VUXlG8sNG^=/@lQ\n jL@X-_-sTNm$:j5T$_8[>4%X1FhZgS\\QnQh>IE>XH+dPQQeV35!J/'pn<dH=*ta@K@e#i@G\n !@.4a^jt.@d=K79O>/K=j5PVHJ6_ZZoU?.QV,!>C5KOHG->:KeSL^Z9t&Af[FGrBmB,OJHb\n \\NYG`BE\")1T`hEVSW\"\")jaWkOa(k5'oTNos7KlPRd'o_;Fd,]Ug2uO3Qq]HMmd\"=1d/Sq0Z\n ^kK><JH<<1Tbhr!JnXZt/>R!>\"[>:ThB0N8hm6*PGQ#XU50-ON2EZnDhT0[r#k6a6/'I@nR\n O>0fU<lT3M%O]56-2=50f(WJ&MDV[deUM/Vr&_(j[\\Sb'.+36(!L?cj?H'3<ANn`M>5&tH'\n -d\"2dV^P0#PcH?-o$jco9.D+_5D:HR]EH\"]'[JR00H-0l%)C!_I@i4kk;lAE[-p+Q1Xu._:\n UB]n5Ys9P#=9QR;=8kNm+iBi1[RS38&^U5-Q#<pZu\"O<N[/gCa0Ghr:e7u-Sm\\*:Pa=#GEq\n NL6<OGP.<`TrX@p2oU[:Gi,^mrq39m,iPrZ*:Mqa/rD2329N2H?)U=giIFBNd<ZVM#lO*>r\n ZjFEJaE7?(\"lE(3gG`uDL0mE\\O+Pm'BJe8cFOF.P6XCKt24[;UEK\\&J)i?an;[IO:tCi!n;\n *21:,$k-28sT4`GqC19/g-]2BC[P*SL37^$KA#i1X;d2(r7rMV=NPBIE/Ubf_;`@-&F^:.G\n AKs`W\\]T/'GReqIB:&mMTP+*:IA1C9+m:rhk,>B[i>QiiVq6\\Y3&TaM[]ccJ3nCdCCV'5SY\n Z^'r^ikQGk!tP2R4d*U;OLHn9BD;U?b/35?=tEeftML4k^#/e^Ml4e\"i,))2[dPI8$MCn)W\n J71K^q0b-3+sYa:*J;B+Di)F1h63cu_De8()Lh\\L;6a)_n\\Lm5ENePN:+th:c`aDf;\"e/hU\n k,8>V0_GNW4,&&NS*-]d6^4u\\bf+]#=3C^U4b-)c.(Tup\":>rT7\\HbT6hn9dG:a7:c+l(2p\n <IoanID&2!]DYC\\kjgaF(:Na9nS&C%^S0rBpH#NrL^c.Y^?k`fqO;s^M@-e.g]@)\"e7EQrc\n WYU+Eq&KQWo\"hgr#@R0GKFikM68TGq\"t8>VDR&mrpY+>lMstTQ`VR2ik5F&7SptS(rkJ1(!\n b(^,L_)$X`$g6Lg*#ts@!HGjB-@E;F4Q3.Uf.Ms8JP^A=,RZ&/Od1ZkQg>N+5o?/_O+70@:\n QKq&A@lg8*K@a]Ph]QJ5VBcgAiES7?8#n4\\'bk*b4.\\*PoAt+-rB1,W$-8j((\"JnbPEZe6S\n 4M7S-03.4&N3QU0mVIE\"b&-QdH&71d114#OnB@r!WF%dH$QnO,<+A9O$^`]hR*s\"(\"JZtRA\n L5(\\@,)*ik2Qk;J;%j@/g,fI`k'..9a\\X>6a\\C*GoH>,^V5oI\\dBmqh'D'JdNV<(?lQ\"MFE\n b4p<8V_koS'&Ib+H.I<d5TUk1BELpG%ksGsi=R4oB2?)65A0WgTG.Qj$`7o#iDg,AZW[\"HK\n dAY=1c(C/^)KQS1cC+gYamSUNDZ-)4)\"8p+$o6+NZc=DVkkc4a7V?AU%UT^]`P&F`gKadBh\n `<I%hmu>FjOlK2'Xk&To);sXpM]ZTs[C&Jm<-?o#XC8h&iWH7]9<GLG\"-ClO@6,CH2/f4_j\n U'$K)>=NF@H6lSW=W'rJB>]%C+Q(ss>1p4Q#kkr!7a6'RJRU/;2/2s?[MWDtXWeLI2\"CaFk\n :Q6@VUC9Rkr^f^Z&G0*XFW]GiIKWV[pbuqY=B5I3B%-&=Gf.,lXfbJa#ZoYn<8\\INg<Ipn\\\n -J;L:B4A!NZ6&EfF,\"W\\j.;g+\\.sH?NWBCtL\\Uij[XR=C]:!_XFjFPgKRZH7[:q.n#.2dP;\n 8W`q\\>h#8YKCNqgBl&?mA9!Yf;@9>iVXdK8G*IcJ9;(#.Q7Fe#I8O\\r@jA>)?B.VYZF0m?p\n \"aHE&Iqg6]?=%S#orbFIp*%!q\"\".<;c(Aj1HjZnl4AqH8+aO_q9Zn&&@rHa/F.a\"0=B]EPN\n DVAQt##mblug''4Wtoc#+p\"Co)iO)akXa9D?KNhPWgE]&!V154C>]=T\"9^#6<<p8&7^auMg\n C&^&d:/*3;3QLa`QbSbUYjo!)cF!bPDH)EH1XO3L.G&>MBZT2XqkF?UjGL\"n)3p40GT/5&H\n cl)jLBC-\"uF=r3mg*]:$TuT_p%PA^ZHj'tp\\cO\"&^W'Gi)I*lT=@[n\\'c@6RC->.fFZ)DuD\n 3H4&qld&65\"U1t:;#ZB=flK5;_5Lu9k->3Y4_M\"fGaKllhuOBFsb8^HRE<>XYMsAaHk?Q7q\n lg'WO6HMN>eR^-#2gKBkUQ)_HAN!=0'#um;5AF\"d<P9]pH?S7df*%^Nj`<l+As`oA9Ar?O)\n ,H(BleOb*uUdE'=TEGViP4j!\\m6Z*V>+mbHe:g4eiB)n?hmk!lQ7FI#)_a*5iOh].E4E\\9Z\n !q)9V]*0YXQi8bWgOI-l8Qr&a(i''Zg#Nm)iSTDMif4+OT$3mPcF?Uqeok+o+etSjH?8&F$\n K'D<,Mj*_7Vq$&g<pH5_X`^5GeiN=n)Jq/eLN(B=KXet^rM,_bJVZ71mr.V7a16CON&Yc`7\n ,b8?LNHkudI;nK[/<jBlV\"tjNW2j,4b'X-^D5dVB92S38&om.+Kl!69FIQd4EbVig&1#I!h\n s47N>.T44ZB;3*iIO2d=OCaQ[&3EpS2s3Ogo6t[+r>Tqfm_/jSeh<p`<AmHiJljIOE/c6S'\n bgOI@<18\"]D18'^h%L_.O=cl\\(%ec!7npO;ko/qSIg%_lN1IlD`ChTPS==C&G6cPC]\\'cMr\n ?a0'kMp\\;MdjF=B'rr;Th\\O]p,!\"XX27Kk=+5+Da@;j[^?BnnM65_KEYPR5(^5)+#r^FTf.\n >M6\"I^cG-)24LI+d;ajGDMMHn5NENnr\"VI\"(.!$W_1WS]W(-r',66(_\"l'8FPT<\"^Z[hgH\"\n upZX>REeC,/Q/][\\,5W&8hP??&$9,5<HPDgaTIK=?X#&5D.ak.QOCON^8m__0dq&N%i-p0u\n GeW#&#Of5VIcR3rk2F_g#WXN&\\Z73kg\\/L!XVP6p8HK5/ZsR#Ddd5j<fW\"6:->R5i_LEHk.\n 6MpG-7k-K>K')BM6;1;af!`3`4U4AA5^9p7C7!;IFb?r9:]3(5Ya76EXtlrAbUZ:\"Ok`Iq@\n 4P(3aUG))k[7DpQA4=NKO7'LJX3`H[*Ji8<ks$9%K7-nI&jCQ>!Ak#^I#)Fc0(dEY/.`&W#\n `@OtXe83.K<C,OZKcjr^W-sH^=iW@?a$b$D^f-!WG\"'VA_K8.6jB]]'?SY#=5AT#lK;Od(>\n 6c=c7'(\"A'PGK4B1Ok1a>mT25V`@R)MCp_J:L8s,`'Iq;o[mV78+`Ce5_.td77/saTR^I&^\n pjoBEof,a[BE)S<^sMHGZEC8&FX]F/?ar)9;B\"3g>6;7%MHLT#aTt_\\cg6fEd)]5(go^KW&\n >#Unu.sMFbC;b(OZRg`?I%d0>f_aW.D)e?-mPN'^Jj7uX[mKX&R^QGc1Xb<ttpP^Q-&EJ<q\n -`]TkbjIf/1]$$n]]\"h\\Ti!P)b4G.;TKU?(<A;SHF_TX:Cb'_.K`)XcQ+,*g0LYJHDm)dJI\n b07+T#@Moagm#u-Yt'1f42cJ6<%B_'[QG\\_4_[j(<4benf$.aWbJ`$_kZrf(%\"dt4\"/lP0T\n O.\\D9*QBmb#H8P*9#0WM+gmIaNVXpfLH-ZEQl)Yc@kE,OU6au,#%(`b7r;pAC3u%[3iO;8Y\n ]Gn.j@WFfZuD+:H[<+<:l'8B`b46\"R%XmYU0Ja6cqZ%c34'io_hMn_p0P-:+YI&'WFi+l%$\n iL\"u'm!G^E2V#1.Jtd\"&ue$h;N\\cHrr(cIA1Wdr/\"R@'*)s#$?$]<7T<*oMII<d6/,W^fl?\n b%tfBo!uM])BN<C?)UI4Yc2AVXr>j5nj3Bc*4#eJhG\\G<d#gtRTdR>F>5WqkZ$IX%_a^ha)\n gpEVgR)6M(a4P5UKa(C#'[lXg;[!n7'4qF+/qC`&\"+VhOcpNK-#Kfb\":&R$\"I2l+l*7M:o;\n <7dVe>GuG+%i&_KYV:,/L=@B6I[jt50tbgm3g8ncVfG&;N3/!9OLX!&I-U,La=\\&%560N:\"\n 8i2YLL5cQq%6d,(eH2\"1T%u?rYU/<n!<neV.()NB1(9442RYe',YWo`<P:@K>Ue\"upQ,Pt]\n [j@b*DHaS9Y.OF1#=B%1oMe;[!sSS>#rmnG>a*N3sE*DKN;:0.$`f)/3rBIeTm=b?D[\"L'_\n 6i&lXR/:ut_!Vf\"bTFV0U=b(Uif=58@c$e,j=]b9FfBlbjXZTV&K%&7UdJSuUOBI=40NLVt\n fS,-u5ZrjRGLgn+fYl+eMt50RLs7/Hd_WDgd'AFG?%gIcffbO%7?uP+QJ#!!fk$ORFdUjYR\n G#!9=iHi_c(!D:T%W4tg\"i=Soq>OmSHj\"q\"2I9VfI[3H3a-*m>&C1kQ)NE5W*6U.g:aN?`N\n @kEY1gBK>'7%NeZi=)YhM%?gHDjs7CClM[bF>6!o:(bNOW2X]%a'ngRZ\"3[Coe`YQEq$>Q?\n fhrP;_J_;$obgdT(b<Q!Tt`8\"qA\"5UduLb;r'b1r9*gni5\"Lb@K=c@_t=>lDuS\"ju,p.Kel\n uJlk8@3$ADA8-,ANK]!Su:f;iM7YQ?sKV2c0`SFhEh:Lb:=2j+S\"l\\;9J(9O/?9MM!<Ir]6\n 4kMVU<TWG\\i)-%>M-dUUhS[kH2*k?XmaQXn^I=1\"XXdGcOIKp#7iLHh3*dIG\"GDS=hf\\^$I\n JD]rq;8UU?cDm!c26DKrnli;hqe?`84d0C!am&Ni'mh,<Wc`A\"Q4/$i-#BV<WZZr@,S0qi2\n -q@[LHWa%H-peJ65Bt((fFG&Rd\"\"iAMD//f!>7(1C5ZiJ&0-OC8,s8n\"S9@BLR.ef<Z2*+A\n >F?,e!q[NOQV+lYC'@R_QtjsAj?-Je);iapp$r[H\\>.UGj0@`:@a?%H\"X>hCoe;s]KoojA\"\n >A_t]gj$kl8-nU/ZD?<(/=NtL8oWd9W8QMVs]r_eSI3P^_,6_Ig?hOM.#!h5r60'piA4?LU\n IRW1T#\\8*JA:=hmk\"4M18mq'[i$K<\"G\"q&K:>qd?AEFJ4mN(9c;<9\\Xi[uM95#gWU-t7?Jj\n b?jr[TVUljC6Cbimm1#h)f*=k?a-R^d'9$OD3?j2.eaVk!L/E3-tn]2ho=bAp-2pSiYoGC=\n 93oe>OgVHH_+/EsI^ljA&)*#'&fAEp!p%jG%d>7WmdP9Ot;MkB;&\\#'o;/HK>W`jOR8k-@P\n (.<omA3kOr!@(0>/qiao9FBLR=1^4k[o/nNhrAaKHW\"T^kR9gEl4kf/SFda&*ZDe=_`Ar\\l\n c(-(P*C0q\\CY_p'pfO6j^c%;dHB-q]aNg]&gRUf09A<*2E`^XU$954*E@+KX:`d;G9U?*.g\n l:-5;:4VG4VW\\59kT3jcQ@n:rKP4t&<M#!0G)0IRY3#X:^6fB5fOK[\"GZ*[`lUJ8I;O@TCC\n Bm=ik'iD%L1t?B$L'H1:ut;6E&!(qDlhl3d1?K>2O`tZR;=LFCdn0ahKE^ASSAALl0cUW2P\n KK7algsFkLRlBG,B#'<GIiGjd)o`(51eXdc/!Cm6ps;N?7BhKSCcr#)hj10\"()Dg?l1<K,A\n &%p:+u%\\a-EUkp;<iQ&]Xt^=`APSWG`68^4@+0nm\\bCehlcQK[b6Rd=qXlt/h*L7dgm&8EQ\n \\m&ohm(<pSpo'GN1i\\o.uL4\\]np?ac=eS`mcY1;Y-M9mA:+%G#Rf)>'s&Z\"\"7l]2&3L:V73\n n(?F_mOZcC-'/^03sK6Y/G?B)YQj%t\"CHWd\"qM,]f*gq0%dor\"DPlc:G7ibNmdB6OL(;CF(\n DZBK(%3Ldj[RMbQHncV)Xh:cmrkdNL5,!Dj_q#QD/QRS3+E0&G,0Tdnjatr;:;BcG]3m8l^\n %\\DQFh)uQK^PnE*hT;9\"3:gjb%MZ#2]mZcOP\"<1@l;<o-Wbls#'<Vm-uG^EA&#G2T]rO'le\n +fEJF&G*qXHLVXISNn]n0)h]6X$0'`*ln$H#F!*+c(I,jB9oS6!0OfJUY#6I+<nqR6dNriF\n t]B6IMCXCI^I^^q;F0JaQ8l%9b2_oMW<qU):Fb_km[lAN-a)dkWjJP(^f/hkl4S-l_Fp@X2\n rSMV8@e&%DfFK%lT0qW<+OCZc#!d-LT5\"\"sC7(A>j)7SFa),qE!-IA]DA<TN];+]=:+3F2K\n Ba-CG?+BMFn^):ooCtSQP\"G=m<-G9kC6e/^KtI.?Ymb\"oC%5\"[peQndWdY/p.&Wd<n-[;_f\n SFY!2*!i-t4(7CO!=Hpq]6XY^H/rNoPn4FN9L8f.$Fui,n^5k.E2J5]<Etk6HfjLYrY=7sF\n ]G=8B%hq58L^Nl1Up2s5*>H3On(f:h_IIrj3Zp'r6j-I;;odI\\J2F=pkoCrCL=Ck6\\ILP3o\n sc`R',Y)qRDLCeZSpMK^*ZM>S[mIucj=)d`4nF0*)0Sinf+lKR99*Toeq5:n$\\%R(-Sb8>a\n q=gKPO*l/c%f.Q$r(!N#-`$$?V>).0pc#,E:0hG_WSWAdK.4/'pW`X!cB)EuT1?0b(UJHYO\n nSf(AuE+[rrkQa@?iVLLXIi,BMaFb^4!K(rPuYHB:XDSEI8R+r#`fG8&P<Q)>mQcp_T`IpO\n W6l@rrN?qM0e$QY'>aWl6qtpHQuQfBrRq_>T1>!eAYr+0pADOF'3SE$(8??NY0c??nn>.JR\n QH1BRf5nbp5YJ%tpW\\))Vs`I7f;0L7-9'G:WSKL+PSW$F*M%Z!J];#$PM.)?(_fMS$kC,mA\n s87Sqc\"Hl2\"PY'n#`1mZB/sa]C;]2CIKFO6m-M*YdmX7-h:De/1)H)J`U/G[S5]Tk[9rHI?\n 'fqU\\U;I5bX#5dbG.Ct^K@8;.*K%sOZW_1R0S3GaD7A9&(H[o4L_3;9ml-0Tp@ob+1)qqp_\n uC1$`+!^g]Oj)CO2tjP=ZiQ_/XO[nF'60<G<MSFBQRE@-C7H)e7s,0]k4`ZYLmZ7><Sk8D7\n A;<G?_cCpNk//]h$>4\\K,eEj)R-WSnB^:8E]VL*=e]7WRN2rgDumCCUr?kG^I.h#EuMe?8d\n 3QY>;@XmIZS@5;pj2lh(('IilG?oU&sS0DknP5Xsc>ha%fI'ZZ#@=eGm1-4D%(684o]$H!F\n N2%.<@bW-3Od0r)K_I-%^'-L.7<><E76sUPHnSDVOTdVa7)TN+_D]Ku,[![bP#eDROUs^fN\n ,Ge9pP*r2qA=T*bl3`!3b#57+/#a/uPbY79]Xohsb6kp;//&rQZqTdbcsa)8N86D:X5r?Tc\n AUnL=.2Y<r-q\"Rm/9/q'Fb43d$-*k6dZTB'h-N7D&l-p'TFBb'.1iLiL9DVRcRJ4gQLm6eI\n /DK<0&V)nPo0+hY's7>Lra;[=r/j<cs>L!ETg5dX.TcSUEsFB0kVn6kL\\5@bDM[Q\"*s_/7W\n >4Q@rg`g/`TFCWA?OG_O3nr.T$_E^Z14gfH%n-s[I&djWA*Co;L#GDrqTbK@3.HE-Q_oeG?\n f>h+>Jo7H@\\:\",R03j43>QuQ4&DB4Ml(lfo!ig?l#MrPZ\"23$X`LrNmC[)PMn;pKMIP>i8<\n ;j>fmD,HYLY8(=;<OnrAS(=\"Nr;pVdamOU\"\\F,%%MhS^DAD+CtOeq;GDNbN5[Z72!C2nC(X\n 4o\\[\\Spf\"p:Pu^f-HQagerRNZg?,JiHH\\*cJ<b=QaZ\"'9=N^\"]AHO^om\\Q\\*rS%#fJ`rGJq\n UstA\";_BLW/eRD]Qmh*02Dfnslm8bOZ->b^,ma*AZVqfe-(Jj`M>AQt=s3<:]0sY?dZ!h2b\n uH5XL<VD0%k`+E&;+\\/qDZRX]tKl/!bZW9TsMO_X1thj\\FtqX),%CmuNKZ$Qc=c0a=K=1u$\n j>DL.l?N2Y@]6tL`!PV9Q-f)Ss+,PdhP\\+(RHlmdgp&4o_n,34D\"9F$L%K\\mo1+UBNmW6`,\n OtpZ<kaa4R<)0:t3eh&.@)Fm8:<j<@5f>BHoEKL_e6rg,N=\"Gm.<n[gB/NdrntCEUCJR)54\n W&!s?E;b*nE'$i\\9uudqeM!`NOQ)]bhWp?lA86o]tUl'qqM<O/e/<(Kslr4+V\\(;;/S!TfY\n &*]\"C[6c&3R2,)!BpGRXrkgdQ2'sW8O_WK$(']6'YRX*L%Rf+j=MX(rkTkE;(G^@DbEf=!?\n W]M1n_X(s(32%3^su7e#6u8Q$Q>+l&K@9qi`CaG0I/>XalKDBm)DdbZ'F9pJ/=-q_qD'arr\n g)Io4#b?8[6ji\"]r;XRjafm#ZK!)#CNSmjt:7g%e!&TmQcAk*^)lXRl\\5CsS`%U\"2!`.6)P\n ?lV]G$+W!lm,+=3L2m\\/'d=f3l&bHk(f&\\N%-N;,P0Zkdab_r>U$S;A9r:`T(>BEF,c,Bi6\n ;u6/[4:0WI>UbtJjhpW-:TE1*FmB1d98+jkf\"F7<,R^ndpOjL9Z;uDJs&T[OYPulDiQZW3M\n \"9a*FmUIFs:%)%[oMu#LNDk^pm4\"WQ-tJ\"[AqaQD)T<eN)n]bFOnN(s*,U%;2M7HBN#j<Ca\n 5?Wl4k:8PW-d8P)25!r/G:U%V<N=[O]-;2TnN;[h(95)85YY#WcY='Fuslc\"-hiXfd`8k!+\n O/LQ,aV?orM>@HQeY)_#S4:5N04\"JaB(=k[Dfij5Dl4',Yod4c`er`lYF\\SGb4W[0f9\\:i%\n pU)F_XO\"Je5G&Bk[S=ae>?:&&kUd(*Ek6t/=6(6[9p)qe%cU_tNH+ATaYLcrSHSQ5?n!,DN\n DuY;.JjE,l\",US1qhMi)\"]FN..Fc>/11f+V.HaQl+In9btZqQHeNV8^.UrD<;THRaLtT]=7\n 4Y]lX;0_h-Ifq$JSdD%9[PuB=G-4.LIo53\\MNd_H9S@@9bC<hpB@`6dFn(gB/BG(\"\\%\\,4)\n >!\\MPr2GoItVFcT3MTSC8M*hY3=?H^lGEP=HQf>>j)\\K-(YIA=kXDYqaa=-;t,q7j05s4[q\n bgb:\"N_!e$$en]Ou;lCTJ@i/ohgg?E>#%>_YO\"t<GC*P$r*kG=:1ZB8+@:iBb`41s<dgHlp\n YuGreA&s#ZA/60i#i*GR%if7VFZFI(4NJEm'Am&KO_U0XdS$1`BiWi:13ESQeV=3,4K3oi#\n $5a0(`A3>Qomm`ER3@B<bgGrX7_1d+)1'jMrD(4[Dj<\"Z*QFQ\"-8u?egA\\n0,1GfgAWsd\\f\n L7t%FGUoZh,ltd.aG+e9!LA/Ik(<>A`S(/+9;)9Ua(ElR(/`T;M*1l-n(Y:h=CjK+k1h(B[\n tpCn9t,pW!$d>ODG!dF^S`0([[TYC\\eT6,E6g#s0$R@)kB*Sg2)R:KuG\")^.'rG)\"K+4Du3\n V>^FmSrup-#3dGEG/%@T*,2@829Q\"]).'ecob'UG#DX80C=>5pW\"-\\W6hL3`H#=7QG(e9QO\n cbN#b8DnnK@qP&/_Qb0ll;\"Zooj%'9!q=)H]aWP50PW$@B,or99<i!?XiKf.,/.<F)KKYR\\\n 9ij>PJ,;.o%hX92!&0%Fd&9K^#.*Ca;(EO(iq[>\\`*HVM=Fn*`Yd+t:4eS@)dO]2E%K](pb\n /#Z]HWR*fH[UY#7nGVW&b?q)<4Ff^`6k!ZM%(\"f_pNfj3JZ\\G.`UbG5&Nl)'bBA?<6f;IkJ\n 0O#JAetpS[oSmI0c@^&jEb15A^\"=2(HpI:',Lrl,]j_k_SR?B`&$pIt0;8#L.H73\":\"TKN0\n W'OmaL/H3bh$Ne[iqVPfKs0lV-*M!i:XFBPni9eU)pQ,Z-%t9<FJs5Wjaq'A9muHOhWaIKG\n b5mD*TjepX-N5\\V\")p7&YWS6Q#T<`dqp7n3%kRWs`4Bm0l4@(r:8IMN?9a!+)hHTCj$4Rbi\n Z@#%-*Qn>&:FKHJ=H\">a3Cp;DubVh\"KHA\"!3YD2baAJWXT<:cjsBT\\DYX>ePihG%0-L62iP\n ,TD_$i$:$uj:-Ja2d`Qks2;\"L#QLY*ANSi<9eQ\"`Bq'biJ^Vn@NVkiWIUEY?).-3\"Y&3*&)\n ^F0RjY;AH.\\8p8^U9N?7gc./0j[!9BO&WC#_9(u6kd$I=hB!mK.bU&m[P((b0k&PWu0;&(f\n b:SDsE+Gg6Jh%gRT\"Yes-D0F1nm/7El%k:iqDakU]rtT#n*sR6!@6b\\b&J4Jt&C>t6B9*#6\n h$E/J#pb94Of\\<&keGK;Hk<*^OJoVUppUhu!`673N3jG<W]2_e*HBaQZ/$G\\/<$:A(#c>;O\n P(]E:DT&Q33P=>crdmlGn2T:4X%Z`Jb'ob+r<P\\*NFtsah&_4JKb^Q)0(iXN\\_Qo>6qC^)G\n 6[;&L/4_HP1pG'$%a+U6u%bob3#&h59o\\\"PO&G8f<EPIkhT_Z>CrZE<BY+eKBkg+gE)OJJM\n .;(,4Jb9;)iM;#K_t(N<^t`E&?1K-ql^$Ld4'E[)auYq#=P.akjX19Db+^uM[6Z`t?m;E2%\n g+F8#R)Y-9CdRbC?0M<\"lk#'#'nlZ>U>V3ag(4iFe18QYq!AH;4fcaQCEe>F8k:lGr.$3=.\n DoF.;rhWKp.BMr;J?I6T\"u0Q)0RtDtd^q#M]ehN21ikl3ngQEcR3N0E)@Df^kpJ&8:F$S+)\n _dlOZ:cf)]d4$),soEfC_\\THM$pQ&1GakIZ]-s1NXVjP0_:\\\\Eu+[.CH=3E1(eQuo-V'tlj\n ]YO*#\"Dg!>LU$9/KSb1m>m@ZUZQ%/M']kST@nJZWp#,?sD(1mLn7%o%pF2E?t'3,r4d\"ZL8\n Ir-?(0b'Td)lZjf:m&O@j^)_c=nZOoLp'fjbi1\"2sInbX+5cNVW]cG9dTZk1b2qus*I4EO.\n We4Vog;'H\\#lr-kOElqS3DZDTR!-\"8oU.[)Emg:lB/lQm4&0F.-><jIh\"!KNB&_00HO\\%Bp\n 8S<,X+fZOP?5h<68ouF8EfEDgRmQW16Skng7VEIO[m7;5(W\"$1e5&d19hdHC4OdFMFB\\^M2\n $gPG)MQ'e<,<k%B\\\\`Z57`LWEp!e9qZ7I^9pC;`!+P9qf(r@6;0<aR[2`XQL`aF*5STtkZP\n -7/+]B!?9!X4Eo;>5ZP;4k86V@tj@;['C`CW>'(;[%G'\\?@X>ui_e9sL0=B7iY6@6Nt67W3\n KGomK$2pIA3Zmh>FSFTRDb#=&mD0#3bg!N*Df.8fc7>'6fJU_FWK$W>KM(DXDX28)<)T2W,\n %6BB5f'JWQe8@q7?)F<.\"e<V)JjrY6t(j0Cj'\\-Nt>ulpo7C@*qFCPUlGoF)<^K#hCdc\";J\n 1JdXl/2M]W;*YSaIN*F3@Wj20[Oa:dm#SQ^@s'Y=[Cog$)':`Ui,bkH;\"#ikZ5npe;.1dhi\n Q5FAmq+HEAol\"\";q2c9qaM/;jL,.c[Kcf@$V)^W,fe\"sW0:?Go3!OX'EKWc<\\J1\\TkZK]0q\n lhf5`-@8[qdl^>I:A>of6P?aYEJ596JWTWL+#eD,K^J#9ch[[UEd6ASq,32&'1ob*>,dWD7\n V_^GP=cPk*q%KkQZk=K2ZdQ5OC:$!C\\m!b!\\uTlbiDVfF^BEciE:.VigD0jBsU>Sb(8(;j[\n \"FTlieAG+A5T[jtoLK[!8_dXX(<o\\>riH@%XDNrspe6Qu.F`1/@/QVa^(B4(E%2/@H8!aNq\n p(q/GQMFoN'7l/^e;nX:TmAYo0Jt'F+gZ5J[<#EWCR.,)QGF>\\6$)<cCj&NPG0E%!%n\"mKK\n Rp[Vf4B+Ah*gsQg6ZY$2KO(AkuY4RLGX!Q-/3B<s)>E/-#\\s'oS\"UmR8GW8H?^<Y\\/c;-F&\n `3pB\\4\\Z3%]2/^O*@CA/@C-d;<F%74EB-'JW6ab2+4j8/%\\ZIQ-5>\\)2?fk-K9t20@i'GO]\n Tqp;n-JGVt0o\\-$^&#rg6s$'h&b(a\"S/ObkbK%:P27pa_3`NI)KsF*9^!O^WmhkBrX`l7cL\n J%h3!+-68IVL%r]I[:aZD@:,@?dC&u.[s#M'Ekdrj/_BqsR!iYu!I4>N'EH;c<MPCR!K];E\n hgr!Q!UYaFXcXGNMH@8bfJAZbXXKR@i0ZfPGKf><XcV,,$UJQ.\\6Y'GaclF0L+D)7DF'#`h\n 2S^%#rpspR--ZclUQ.($C2I#q\"I<F%N.h9OEl,<\\U;q9&t6?GJshIX32;VHOb3?cOr$3;pV\n UfEDGtg4KM_8np7NDr$j+<;PSq#r=[P=Hd1J1dIb<8;<WS3Oj`e&qQ1@G22hl2%It2[(J?d\n 23K%q),ZlN;!T6^7)X-+M5;@,X2)Yo/Ug's/^)4=VLHeBX,C.4;m\\@Y#9KXW;fiQ[k&^S;Z\n 4IWf_$[W_B_d70O-gf`<jR!E@dELo1+E>BOr+=qKJK2iffVKusRW]Uu7BF%b!TXkN)32`0d\n ,CB+&Hr`gs=f0g:&.a>^*-Wa-62h,J;An1GS(ad836s`>Vk^e\"D`Q'\"qEm/!Iu[?r:KgN/3\n G#$hJYe]r\\$qY?iMmoLl_`CtY'T;jD]U\"9Wn,mG)VXq`RWk.1I@1uiR<^#3\\fGlRNI7X%'7\n '1q+fO;V(_U80Wk0^[RD#A`9kQH=U\\RuH):b#+a)DjnJ/Ig,=S88LI]X_p'LA(:>3iTn@C@\n Q`&&I/,HYdBLqlfi,[p&r]3sTQTKkq\\=>e-V/3f\\>KFM'RM&:oo_)_7rCTt0i1X&NG\\qS&-\n i5.*;$S_H_\\\\FX[kO`;eB#_?.t+mearA\\C1U]k8+=!5e&+Dm,XM^3b(<\\pKi*)7THpYdR!!\n PGOuhb#Er$#<3Qu+oDOQ8/ZcH_0[cF)lL#'4hAp5Ui6d=\\RD<2]4\"ml[29>\\5dD0AXY8G^`\n -b.pV0p75l+T8[^7,#7gB#&/@=+L:RCOW3r,!OFMGp\"*(SS'GntUc0RN3R5FhA[0S\"n'27D\n \\f?L7>6EZf/LhIDV)8!;;,Jg###!24dk[_j].aJDqCH\\W?Y_b^@OVV#Cjd#K;&Oc$SKi]C2\n .miK;cl62UJmf>YN;EXZVIO<FCQ*0&;BOdl95d9Ip<fCR-g8[LM4XLVoc)\"FGM\\[<r6&-7h\n RSB]L\\1\".@_^gZX:>X?ioftO!,[ldsG]6e%XB?m#]YhX.`giJo[c4E`pO?@qZ6']e:O4QIi\n S1P>i)RjoN<RCWLXB_a:Ra8@R2jW8D[t-U(h)3maU\"U_\\&=-VO*Ndfh7GBsme@]#8pU/O5p\n Vr\\Wi8%afTg;@4GSolV73-C(]`VTId,WaHajkUX(\\QF.ViH/*dC+tFgJ,<uDR[(l(nkQHrM\n AHO&`FrQ*-)L?]s\"W1Z.j[s`LD#)]ORl<;pN'ZcIsAF0N]/<KpV0-ID+P!]liDliR`s<hH+\n ^6;dn&Wa+nj@f_td%3n:l4s/\"\\4VDV<2?@D#81(b\\(*53NY^*DWc\\'<b[R/H!a*Pp9OS`?!\n UcNBs_U$EisHle1'\"T^e)4l,2u_5b3/fA)k%P0r.@Z)g#QfY&0FpPI'T:P_WlXh*Dm5(W/$\n n\\$i\\+$b]!iNMJ%+n.XsgKp$,>ts>XS^)@:\\2ZS#^8L#/W7IZMbZT:i03RBY1$h+\\IU6\"[=\n )HfCc)]N#h]3BtSnIHICV0MP]I9EV:S0FQ$h$;kp3L<_a^tf9=n!MUkl1tD?O`\\N&a@$%nX\n >6gFL0c!7LnPsY!CY1?GH=92g-7_aaJWPSIMp^e[o!Xhg\\MNgV)#W=KOOo*AnT*T?[</O<$\n c7i$#5s!NYsE\"k3M5ia7&WIt,H:S\"X1(K79NZ<B_N7Ji`0#\"G+Bt&9p6QZKcqWiXm#l:+6p\n 97H4uIe8@8eO%87D)&/*&-'Lp[D^W`t9V,bqOphYL!\"+dU9r>7BeE2$9T2+S@3Y]Sh187Y0\n e=%sAO\\DTMC)$N03iPuNJ`\\hE\"_tSNY?'u^ec6j;_6R4F[X2#Ofk@it_)>MU#3U->?1+&08\n kS>q^#*cFr\"])'$GtcS3,D>7'ofp/dVLIh9-]YDATJ__emCA(c3\"]</I%,#UXNq\"$m9GC=/\n shep\"LL)XbX:<,rWAp^?((Z9(.!$mKX8V`SZ=Cr0AELQceH3dbMQm5H!&rFo%%NJm!rbme8\n f\\V+Wi,pjL:J*hQN;g$SN\\rZ<5Kcft-\"IK(C]fC/P6s$,uU!s(Z+,RX]>n3d1HR\\r,s>8j_\n f+U<flZ)n@\"d&\\l06SRRP>JnhgKb)+!$pGiQd6XlJ`DK<0+r:Hj?PpcpP\\V1,k.G%@QP&#\"\n *CiFIGp&RH*/bt2ng&H)(FHe]-HVEmUF8`TI&e\\gdUEoC95%#/?l\\?o'/<1%,g-%P#8uC#-\n `R=(2GNH6iAW/7[-FX9b,k%p:G_)$Yg;V=!jPR:qUW-XZo&K0;/=Dp]2?cs\"%]Y<P8?kHe@\n QR91R-o_:G]B^3mBMK,th-8NLO?U[T-7K=#Z,nG2kQB%;T--[DSU!=)PpWm+:q%U@23&\"1T\n NiVMXYfT<gDEB3Fq^UM3nTV5nB8p;O@T>B],?Dd2GYepF#u6#pa-2ae_n_f3TLG!f+IitC3\n g,Zf=]\\&;p-7b?F6)9:.cIt6Ht:(&:SdR:9m8sikgLJ%-e]87M_WUk(<pr5(K%Yb;#3FhZ@\n 6TO4Q!d-]QF7rIrAGKd'6;UVc?EI((5&6Taq8F5Ad^5lu8^gYaK1o6J,sS-R/Bpr>kuB<:V\n cC-9@9;#;I:oT]eX^hff:(6@?L.I\\M!s\\>EFNXS-gCShD0omL[r)\"sj10&SVX(j3qo$]K)M\n ^3!$#f_6h[]-WV<&>/pW`.BEI:d^a'[6&!Qe_O7k955G],BmF*N)3LuKV0Hu0t[<qFd^n'.\n )GKr#*@P4eVe@?PdiVH9#D]si(<-@(nehbZ>2K1%<%hi\"$X=oN^-YOol)TJ9V7USE-X#+=d\n 73dk/u<B?JYW`Ju2_6/03hSEUtcIIiX]>DcAIWV,Nj8\".RVsF5/s2Xa0It-M4Et;.?&J2!l\n J;^E0%9Ei;:s4TEMp94+p%%.plk=Cl;@>0K/s7@#SV)r;%_:Z16,TYE*)H8A6?42(a$B2JD\n TWbW7qW65/%]uoe_NT'o']_74([jeRliI]nW\\+8Gu5<K1aen.7LRXY&N1t!F\\L6;K@u-:^$\n dg:Wn&BCid@kNnhoXHq9I/mCdFFp%@9]p,?/H<Og[2<pu*3\"Yl,W\\`-[LVUch2_`?&MW>n7\n O+.\\m3!O>7;586HNJ,ZKP]E[F7Hq&L_kCm1\"p;FsG_0dYo1QBRJD:<C%0-tLu'']NL\\#uM]\n lj\\2V<;RTUuq,S_mR$A9Sc<AC_D(]D<\\.[6@?ACOj0P0mo%[-NpM#!)eAi.]!!a]K_nEDa+\n Ll`'TGYWuZ7Oc4<V\\W\\d=q(0YjP\\PJElfcU60ZbZ*;K^N,@ko:.H'&N!6,uI^)99Em64Ye1\n ktVqIRBHO%\\`5SLWnU!6mCpekYd[kd3=?6arp?cr)/D/<E)CJ0[sG+hg@8'>=Ibef-;\"T3q\n 8@*#=4#%B8nF<PdZoVqI*'3Gl/UMY^$YN?93dRKH+Gl/WJ-J%>MB%!b5%VJ-q96.QpA&PqJ\n t6WhE@+NDHQS<iT/GVcIQ?>,rBUY>s;m=\">\"mXEB9'<dN\"oCFs>('sb5Jg>Q9$GfL3-9Nd+\n cA1'as;\\7q:3JQKP-:2+H)2SE86+8R/lr5'ZN'q!4@H1%_P2@?UU`0Y<R6IO^S$Q&IJ&@11\n 5DkF%TIL\"pcq&^S-p,M+e1KfNWZ'7JQ*Z=n;CGaq1DOTQ=GlWhNuU2HE)(O$N&6gm2B`&T`\n s%[;QT\"#3qk8+LOo17\"89>2(mPb6@0,fCD!EU2qG]*cGY#gMOhFl+>Daj!)pU9a$le-XRQ/\n EQH>QKaJedM[XL^h1.<=>i>3@@O[^gnF*Z!4,X<cHS0K?sf/+baQA`Y5\\G;;#+L7>>I:Ukb\n 8)e3j.\"C8)aoM\"m7rgDaOtmA1E'WfDs@L7<(#Q+`rTDVps7Kh,4g`2&WcZ%uhQ3,hncaI*h\n hA:0L<LZ%hH\"129h0t86TQ1<\"`_^f(VYEa.J>K^/n/EQf?Qnn@!)IZ_JM\\+SO\"5&eK_'iKH\n #WI;*Q&?\"/r,(Mbn::^UbT'_X$Kq?cL$]?ed#=k4BQ@TsnH!U:G`eP#l5,=+FgAurZ7\"Z10\n h#s1S%\"Vuggb_K(\\JI*\\?1MG^7c:61X<&OR^Z@5rEt)0aQ=F/PYD@%X;=-6A(R-,?Y1=0YB\n CDjfNT/$Cjh(B`^jA:!_bla0W6LV$O=t%&^CXoSiJZggHJEGIfodM1\\;.mgmS=cV_&:2Zl:\n X)\\9E.1XVHYj7Z`G;97%NR=2&dW8^fC]:-H+hVk3=LMjW[[A&luXNpr,JgM:\\GrZT4)QP6q\n ti,K2\\`ZtW$e\\9cWAF](RZ8iF;jBS%7EdgNG`dh.k_Iu,eJ?17)onhDXeL(]d^,n<P4!_^c\n GRn1+DDrX!ka`6+DS=TK8p6$Hbg-gg%3)shVC'`9VBt]5/T!4p9],AA)I(JmpinW&i>3;a*\n Pj3^#;84,S[Z(OrnuQVT^a#]J2e!7YQ6a[-LZ>W^3BSTi-XpFn/Q[cKn'^Y6qD8'!n_4(>R\n !%*GkUPh</c[mW&a]4kOY5\\cBFgJk^#`mLL!89ocBmXoT*%H]k;cirjP<Wm250e%oD$J8&=\n jF4k/L'#bAdg1rhP@pn&A_I\".6+LR?F),@E;.T*aGg0@Tc)=6TU4WV/N`=;Sf4&-a:I.f=p\n h#t!up2MfiQIP=h=K3-=nn)=/mB;4WkLXL(t9gQ.1qe$tNHG*a[4`g]=qq/:)))qWJ4fMRI\n ]&1+=*Ao@#1%X:W+A`9@F?`_55g0[&gZ&P.IL\"MIKePYBlL2I2'0b1c51C<54;G\\+(,ELeJ\n 1s7lGWn>0.YDDF#5erp0Qrd\"%trSF^Q[!\\)u-lmqEd822ermfb1+*lr]fru\\%7@+`%!KX!i\n Wa71unfabM5'-go1tCResG)nEpGcCI#NQ_b;pT>W+94I><&gL@@D.lk[L?(Vt2U6aStn]KJ\n H9liKF\"\"e]G8W(Vl^GJe4=L%oX$:mdY!!X*aT`-b+oKLnS58jp<``6:e>'I'X6,X88n5J)-\n NHr<2i-T\\&&5QiOLHi]sX/\"XZ]](:J<>V<W&0;@d<NjLOVQqn9(6q.#]7LW]Ii-L-^@\"uHP\n JAaXhjCUd7B1?-=`b]<E(gd@f&-D?#\"e,OI&f&D*\\-'f\\L?P/GZqWs,E^r657ndsD>Y[]J:\n WI^U71t0b4F/hp;aPf]a35tqCb!D=M5[b0`J`G=S$5.fgV@jf`QI3_=nP%I9th<[8;rBrS;\n J*OG_S1XL8Z[(4DDg\"O%,(i8F2GZr/iJ]AV/hEK0W7e+qGJ$o>mti$!;YX\\7S6!Fih\"\\7oZ\n ##]M(h3,!?%(7ta^U;;]6#&B-_$a35sN;bBRPIZ04eZ&C6T)c\"PW>0&g1Rd>_Q)r?VI$&#g\n %]3L^r*3r3gZOb]3KucnHhuUqNP\"U1bbD`o'Pdj\"mB7e2-\"-?4[W@NSq@0Yf!\\_(^'BR52J\n aN<5U8^t^NjMjcuT/n6k7/V<aoQmb=Gpkd''T@I7<2W/pIRjUg%3+!&gb\"NGYbKp+6NdZ^'\n X\"')8VVkQ9FTTKSD$]9Mhcgk\"X<Ab%(XXL]$:/a:(6#T'46KM.tB$*K_S?+EP7,igGk9hL6\n -H\"9ZG:]l;#\"X7\"iUf'MqJ^U,m!T`@;s']R3.?L.YtVb'_MVXFSOud@TEN4g_8T][Xp=0XW\n `l:WQ%\\E,j0Ns%iRn7M'hL?s/5_/:]S9cqN@o<8p_k##6\"I!n[^/peuls?7^d1\\:?\"3OD3\"\n YlHoJ?;%0&<r=VllTYaCl;+mf\\XJ<hJH-0&!cU\"5Jldnafd7=u\":Pd_!4Sh[miQo/B9kgkc\n ?tN4%%+79a;G4KS^iG1FCBEu1:jiMqSHi&h.8m9!.bJ24!\"9)tFM8bA20a9L\\:\"A@9a30];\n $?77<AmNn'!0UO;)K(Q`:6O.UbO.=N!.DE>oGZP)c=GLbq*$qiuCqh+?3(=%e)f>9-I4C7o\n Xn-1,+04^j:af3<<D9eBKLCh(7(;9h>>(\"<\\oon:$/S8@;Q+LCeY:eMPfn2:Zfg:>-O`Mfd\n 12i)?`ncQiG:K_)dW?W6=ae,62fSO#U(6<#Z&<':(G(d*NqDa-rper=BERQ-'F8cnZ]f$-u\n kh+lPgD*Fn@\"].HbUHAYB@YXPX=%ucJ>rG]F2V\"W;e\"(bV0gesf]i3$F;r\"7r<>s2!Y#GLR\n b-N#4RB4t-XjRXURh.KaZYrnkLKJt\\*C+h'!)Q_pMcSqtf(Fu(gF^TVH3U$L=Gm>@n/qm2B\n 3/(kf4C1<h02)SGfgb*$Pdt/,s/&\"?:nL18*'?em9re=JCZ<(9gs\\8<J3^V0aK#r=V[c:?)\n ACt=bb:=!oO5ac)On-Wn>k'>.eAG_O<L8VQP/`LR<Gh\\4_Q&Q.]0E=\\Z;,BU`(UUtLYoe\\h\n >e[@=j8SBjp#fArl3o@[4K\"OYb082VI(I+;=Zo[lb.!jGj_WH\"58YM=QI>_rOf!'u2gX5(C\n h>g9A*e]\\!q>6@%1/oY!Kn9,,?[9GfCgJ&2_AN<GKn&Lued<*T:X^9W.Hs=kN%%X!EotX@g\n A)&=7gbc0=6*Z#L=9b.<LXf=/%H^u6k7:sF\"t3GUlDXug1BuJa!'\"nL!!S,h0`Z05\"\"4D0-\n o1j_nm=9Fh`^X>:%hp_pKq5#hei-qSbZWpptrd]?cDnLc2M)+s'O=W?g[pOrW-CZ!an1mi(\n aA^<Wlf9p]hos!-iI8&-h\"D\"btAUcpc553q!<XD2(dJWKE2Fjj[]jeR:R`;ghg%IMN9U\\-j\n =f6>bCS`S+D<)'4LF?,W\\poc2U!^tK7U855gL>VUgI<X+(u%lP!Y?7',pMEpZZL<qgZ's!)\n 9/H@JH\"$d0JQoT]dIY6hu#P^N7<\\\\)21#jlC@m2b[2E#&?2WJ+&@u`NYSi>]43FfKYA%k*9\n c9>aX5@`P7j6f0C*^O<h5ib*qA4Aps:.AbJIKSLALPRqji,\\uS#mS0r]@IFkbW,^t-Ril\"!\n Q\\2oDA-;N;e7M#=*:tm`Y[HiHX!>9:Gs.r]c#eRIa&>9ef7h$p\"s!h6K/HkiZ'\\5n/I'CL>\n *J>k\"]JmJ9Q_Z;:rs/?Jp,3TF^+$7:s8LB$Nj-hJ?fdD.`3TB)Zd^p2XdUEp\"KbA+4tX*_?\n @qDM%?\\fZ8An\\7+N'GR\"\"+!1<!#BLbINIXibpkRN)U*`QQ9l=F!3^SY&jM43O[Hf;+HYuTT\n *<ZU#XTAAnlc`F6\\'h\"Zj'nm31L;8!<Y'Xk8P>sWk<4,D)edMO:/cbTeBo[9!Soj4_Rd$]=\n C!N5_hOEctSS@dPLNkcYhFqJ1c%#e5\">D+c3]R@OD$O%1BGQ,3-E1a_WbT8IlHXnC2QfmSa\n 5pP&?$sde2MW!$Lh3ER<Wc\"V_ujT#W`fUcej/9N2IW4S&;97X##oL*B\"i'Ig8!k;<;:Qf8.\n #Uk564NOlqX-g<hO8H`b^+Cm#K,&QH3T#7tEho!/4+Q1KfIX^E[\\T\"mBdfeuWVpdVV1sD,/\n O@5-ERN'j#j;iGO@sAU<%4LZOcFBT&qTSfM%rWF=oFe/ht4P9&lKiYrF;K[=34^i0NrcgH8\n G8<@fo==DO-lMq38\",IG'Y3p,'mqeTbDXR#^rpanZnmbdF\"(2Mb]=NWTkbD.tJXB;h?IWgu\n qX;/KDoVZkDQ`:(fYn'JlR(A%2V_6^h.p\"TD=nk6F+@Et*UXj(DC!cE2NF7D$3\\.RKd^`T5\n 54R8%mNm=LN%;r`hQ1oCBD!H#G,[K2Y$<U(3+fpnTPi?LDb*72[=RdJC&&^i+mrN#m]sJ#K\n I@Ik\\e&#$'\"r_E_cQ'?MebTK%FnlflblZ*jHmEf]t.le'6V][fejL\"_b=cbq?Ng\"T*//U@>\n 5jceTgd+#\\1USd/A#\"C0pUfDl/<3<8LdF3b`qh]$Y\"4`g'WF8eE0BK&,/D?ku.\"`H=Ai)k`\n lFau+mFH7d@T-\\F4en$c>EgmL,%YePCRb,R8@E./8]E7L*Mrj'Xjo16TT&XUcZ.<T,)c&oq\n T3=*]m4RKqF<D!6(I*'25kXkXFoPln%a*eRU=A+?KMX(>WVsj;DY1,GFI-\\5VQ\"Lq[IT<cn\n ,!N8k1Wt8):dUGXa[WjQS+O<h=+u@kf3s20/@4u1L_^=Npn\\7A]FFVH[!'`LWFQAjPf6W#'\n MA%GRn6X(P$`PK6T\"6B35l)`/[`kN;tqeLWdha_>1P/+b`a*p7I=fQ]?0cCM5qK))lDQV0Q\n 41:A4B`FU)pJY>Oda[TEKN'lLO*>*%AZGLg,GNo2,cE+m];I<_Z_H3uWeE*`[s\\aHtTK?+[\n M7tQ&*KDKehH@Mo6TR$^=&5F'g#*</;&c%2JMLbE^Gi*7_+0g(BO4.?XGoocOXVLEA!V[)Z\n q-R!C/-9kkhrqP;iWiIUc/BESS=:?5KeR*Cj.H22_gFKBLDWR6e@Fo_$@7cSHABUgT?7\"lb\n %F7bK,lAgU_&11`#k(M#9\\6k8=99-Nr:oBDpPc?O-&Z1U%p8/p?m\\4J!G'3\\`L0\"Haa1O2n\n \\`'NI1'1ol0@#+A[__A<R8Er_MVpY\\aJU&kNlQJ/6?+\\*A@El[6J4rl=>[^c[/f\\_Ni%r`T\n #LJ7aQYe:0^3s%]YD>rP1?f-gmVEjq8+r1s4F\\T]FV6FYcl\"ScQk#D`Hj*0l(@+E1FN*Y&^\n 46Pse+KJk+e91:&?poIpX)2a([bXhAX59Z1\\j5G[?).;6B^ZEo>KZ7RZRS@DCH,Sif4.]5\\\n e+s4PKgVS3B[h>s-C%6$;eabXKgqn;W`<faHGsK>rdI&\"V19deWW9;,/9Y5dT%.G]>&C^[F\n iMG`1B_(JnQ\"H;GeII&Qi#VDrIVgmnCUu8',?;Aic1@`G\"3L8aCR,0>fL,.QHj)`\\\\.Wk6)\n 2cjFBWKRJAM`*>P6_+Ku7K)Cmm`AXiBOH]A@IMeCX?&Y-VjD&^1/4,EKt/Er\"LnLGu!Sl#h\n <CI\\18Tg?#+**T/;t`S^62I(hg(QjSm^HMtS(GK8\\6p\\fNUA:k!SqY^?mcg1Z25Yq:_!5OZ\n J%fF-i\";_9Y:ja,d!<e73$,WpB/I]N.fn'@DORtUF`)-q7&-4&@3tt*Q9N`+Ld6JE`7Rder\n )Fe_JC'Bc4'QkHeEU85uaAMSd+NUi*(ePWC9U@%sP'ifKQp>JQ.S=`_Yq+!q[&@EVZM>q&9\n JZ__K1s`Fd\"nCZSCE?>LtppJ,=s@R3mNQf,YOMXR@nRZoDJ\\Tcr;\"l6I=4F&Ob#G>o?,YkJ\n >5T2D'8g8^c+g`d3Z=\"&D\\!Pk.aKe.iug;Ue](8Q4/>9j(FqeQlM-*TMZ/9@B*=D+b5O$2T\n #jZupq-fN'\"2Gb6A9<)8o7h3dP3Y2u?ig/`?pke.bDcYU9J)s$l[QL2Ka5k$YQ!o2BJcN(f\n .NS/I1cce6ShH,]s'1@&O97+WZgfo4rn[8H<7edjR,@Jq@%jU%21nc8TfPVW\\9/r0F/500Y\n ac+Fl<6pS!#[H&Ec$:;j2rq;umZUE!;F1Z86[=3!T1A4\"@V4<-ELc2phKb^Ug&?P2Sjm.\">\n gjG-O%GeW\\-.9l_+e-9C0HXs=R+V3YH$n,hR0NP3rMBnO'sr+Uhnd8b'TX*Q@lX5gO=*VSV\n NjX8JkL!UMB6:hY\"VO2V#'Ln/NIdDfFJ`dDXhQ<RZ\"ppM;\"nhN6nJH!_Q)msSQUh>\\5J=:P\n Y`iB84odc#47V207LQ7:DEGd]Jg9RWKsNqV-Q75iDY2gLX!Sc2\\Oji/F3=INlBn9s^G?^^'\n PhLD6_qHfb>Fr&#VdA6YD3l]\\NReF:rHljHLo)(^:an0u<:Y<H%@c.d`qk'?]Go:1SWVld'\n g58lL,GYCMk4gUF*!1Z8rW0L;!s76sJoIqWDltH(\"PddOEK33k3>LK6+QDu[Na[=P'MQ98,\n Fij0S^9&l9^*Q[/Ra[ALVj7^l^4b2Fthb+1$E`Hh:&lhagjCCeE66<9>Pj\\bYnqdZoc=7r/\n &fb-q+uL']Pog2rgE)#7'?+hUuH\\@B9i#f@:_u'P2]4Sh`ckbo1)$TH'fZ/jDn<>/t$Y&eS\n ;08!fSa\"q]Tnn.l'FGl]&K'SVW(*^WDR%g$9GH@_(`81fW?iS]WKK$[Cg_,rPT,ib&?Y#Te\n YQpiEnlm7n#V9d;KB+$\"r/!\\K$=?<<\"%4.dRG*([@_maAI+mcmdE<]f==bOqh(a'L0+C>U%\n h]AY*c'd$EBMBA?UB_Wu$W4o[1i_LpJF%'@dAh.Tfu#c3']kjKSA^H'fELE]EdhMo;[9;\"4\n QiGl++s?<\"JK!U:/$M:dMdVVWWbY$%#f`M2?q8!'JJO<%>%JmLe3se-K*&5PS/EUb\"=LIAM\n kJsP,_J88QuS!HO6!;S^ojsD!ToB/Tro7QogaJ&)n<](ip/EZIJO9^o3Y<U1e8$C$SU\\,t4\n c_*i)4j_BM<gmA\\(+H&\"XL3[ZcEWmt.O<D'Z!lIi!S_70qRq:qdd0V/`]-F?g:RQH;7qZQL\n 3Jkug95jOt\\Y*99G=-]=CjGS\\SZoUiOMZlLb*>P<U?4U/*6\"8X!Vm4UCO?+jaAEb<GV%Ue4\n d^q@h-,hU*Er$m$p.oANI5m%d%b)l!jtMPJqdu+nfNT;+D!e(,.Kb&`KIXrCLT#A!20RnXb\n Cru7*Po7P*V>BmiWh'jF)8aU8qm^jFRGhX)Ion\\,J*8cl`K!GpMtoC(_^70,n.!OSk<*XeO\n 5`UL8'cI`7T_p@jN-8K\\,&+=U7kqn)]e>o#b.h\\SY!9]K(0/HI,==D.s9`VK`lP@QZ?9/;B\n PY*olPNiLDc[nE(aP6[1eIbF;VYR.h*kNoOT<Mi-pl/B(`#(`:*M*5M7mS[29I@I/,?Kj`U\n T;tfZd%#'d`,_rR)MS7B,Pln3YJA%;P_4XHW-Z=_0K=B;\\;<o;pEoiIi\\+[u%pgJ\\o-3_2J\n k6'k7Gtd^,^ql-CSA[`YKH:s_'S@rMh2HQLoB(JIg&4?K$q56B[O&le^I2Pu'o[6@M:%HH)\n <5!/V\"#Q-`u5%R9ec>s#51Erq%lhA)A/+tm\\QV#!_MJO<KqEN<0N_RpsHaYL[rt:Z8_%`Ac\n !oIo+\\FQ\\-k+@r7-BTA%BEtgBU,]GI#42)&$Ks<TEI&[.^BIg=ol'kUd1=>>Bt$]73?7mDZ\n Ro*oSkX7r?9e0=EfM:nH_B-&UZVW3lQshO8dh8A!'EY;PRp#I@Fl$6bYpp9EQ-cWP$8COPl\n i>t#W`LcTC!`+`8eZ^I9.CeI.8o7\"d+=iK?9bTItH.,MAUf66_V<Qb,KB\\Q]hFI#$`MDln?\n gt^e-o:Bf=[mr.8cd-b)hLtL@K?:7U,CA\\cQ+ab8q7Kr\"#&jJ=^boa+P<9IPlN\\rAn#fm<H\n o@(+*Hd`XQY!s<T8V.S1RbOC`m)g'AD2K$ZN>bJ_Ur@lpR_'7qr?,dqfAC/5%i0Oa#ieI(W\n :Ph`Qro:NA\\BS^A/OlgkVO79Kac#H(QfWFWUD$GF,9gNiTs/T!#<i@tX9B]<*a+[auCDZ$R\n 1/`9becV4FG8p9`;RGim%jgk)&/9pc=[\\C/]09B:JmQ1EEXJ*&Q!_>&KpoY.5[qS,a$ps5P\n bI##rCb61r\\^^PQPhb3m]C.!+)V:7$i;uPR:dD8S_X8PJCl]s2Xb'q/t[GUrLDePGS.f_u?\n fIY8@/V]%AGg3BPp[7%.Non2(oE.gZ'VV`O0>@T#1BUH3.$'nf0KqA?UAE5+q[cBrn4s1>!\n ;fSXXA?G1OBtb7'H(>rr:\"J!cu-qN3e7goYHL9UYMe]hg=<B%oe$[Pkt(h&9)iR&p.iV]lS\n /_PB)lX]!3FK?7Qg(AHL:2?j5fG!:a6ARL(469)hIK#JboW_dg].)q%,[YcrfF)]`g+Q\"OQ\n B:&F/G;B_uWq\"jkp5_fcGSEZ4F`r=KDKO4;9'q%6!-#Km2T0cnJ6L=NH6b3r=0%pIqQ?BoI\n -$)DnJ%Og]TDZJ0SQYnYg,hi\"4:BAa.$nrfK@\"&i!Sf@dl*q91Fd;Kg0r=.-ICsYT]&FUGI\n m2/]LS?Q'(nW+3cEu@<=+#(tFiDLQ@#oZWZh[jo.Da+-))F!WM&eK`gd3ejr;$cAS#q%Y<D\n da<AdR]Kap9:G/:o[3NY\"\\@\\Zr'`.Ye%[@>lk=k)$+UoiS,5j\"!CJGW:>'A%iZ>4K,Baf+]\n 96rB!3'!GZ&OF+He3&iRApboE:jKkn0m>d1%>cm1BH.#Dj_JZ;2FF;Z:7Z&rRJ;d#etPob0\n dq'=$(.O961D.io0T!=sA6Nnj_p)&6n/'s`^AAF^Rg!Z;$SjROlOd[quoocVYBN\\V7knuj4\n \"Yp%Q$1X[KjmF7TQUF\\`j]&DiS63sa0\";.>W/Q17REn`2Zh_%g_/s=s-E^9p]OU#m1hiY:>\n n:9FP<^K[$#h!'\"P%%d\\cMrus*Di@TmqjFJE+<p7QVlsWOmNO;JH>>$+%M-3_9sBuo.4rQ1\n m:ODd\\e9`%-E_\\23PL#F'gf,cOWpg+S$s<dr$L`BH*Ytr*b,;'&tUMk;X-13)b_p1@[!f7h\n KaG0>m*0&\\(+=,h:=HPV6)'Z-'g6*6XL\\0p&-rdi`e]G0LUkm>r&(YdVgiL<aj%$fFbo!Kr\n j\"QT#T@5*P7j1Jp&kTak\",2Db4pPQ((B]df%l2Uh%WTc=r$`Aj'B6$+&*e/^O>m^s3t40nZ\n -ceR&,TgM3O0M3oNNjg^_009eYln]SKe%H)%_&_sm*`@DAdXpm!nDk.q7YLC8JMAT/QRT9N\n 8!J?j_M(2g#<u-g5SO)S'T5Nl(I1ns2:N\"(o5G,3F;ko;8sCDie/:mN,eMPT6IE+c%n.d#\"\n $00b3g;uY%_XSR8J?0W$*t]oc%.WKaKtK^VN]CKo/0!Yf`DeJ#gMEM60'+%T28Mm:m?T(NO\n q`GO&8l9;3[76'UM$;\\L]TE8!05^TS=1iTh;\\s;jB:?dcX7qnJ]<E,brIAZ+!C]\\O3//9W'\n I9bO&\"25>>$i7./#gdW7N-j$fh2-h+N5$l_Z4]h_Qd(m9s`.?50BG>a]m=d)QVeKT?\\X\\mW\n H;0Aj8VSQ.EKi1Tc=gSV_!V?NC3E,T49(g5'F[D0'PuOiQ6P+`7E.M#*X$c/.3mfT]1UAf9\n Bhagf<qKBS;<'Eok>%.::=Xnk'nobSCKRD*.0/S>ONe4L]4+eg(DWQH<MMd$X(,/5A!O-TF\n gFp(a%=i2/4$_$J1`)>c!7\\Y>aASR(\"$!$8P?JE&[S)Ap#6f'>2^4^9_$;51!s?L]3hr%@T\n EECeE%&R\"sL<-'iflBFqhe+O_R;V#GG*7iN=2tIq4kSCQL8[e<sK@2e1FXCmI,0ej3IDc\")\n \"0.KPVN_;YKH+rF?\\A_(\"%Q<tmgMd9@q>Elm.ePb=+EG&9XKQ@_FeRh</CB)_#$<;&\\F`h(\n Cf2oBe=8&+kp7GH-O(\"A5fqMBC!R0X@flU:bjd*Yu,?ntBc#m(-F`tnap<d@CeP^T_5&\\:Y\n @uM6?mr$a$DRDK(2YT4NHZ.:PB$?ld<Tb[ZGubVL4&ejd2/MX&01A\\DEYac<2^^`\\Im$Y3C\n (6SGFr,N+VA=`]*>:e`Qd:'h!Hcq'FVZcU\\)2=pj)r^K2L!h>QY1_&D@lo4*&i\"a\\,C32Iq\n CWkl8OH%[u46c`p5RG3jH_3n<I$q\\BGa,BTNC2f<%elYql\"\\4Z8jXQSW]L^F9.T=[?X=_:a\n ;t;h[lDI;sOT2s#K)kCtqQFqg?]GZQ)^e/*\\BJ/<Kd[sNX'oK'D3&XX\"\\p\"t<T^H-TW?C2a\n YQ162G-#n.(48:<]0hGai0kiU(L_hNc\\347:]*oNFKI$1!_1!>3jrZnbLD\\d*b(k\\[:+^]t\n L0.lEf^!$lCQ;A`Ii.&o:#638?lF9>OI1H-PEUNALu5XVM&(#\\:[&.l6$ZN>Jb<T\"[+C11a\n [He-H?A0IppFg8l\\io(N\"afO1HUP^_'o@r'VUm3@F-&trK^SuMV-s<_V's:B9)e1Nt_DO=`\n ,hDDjHNM*hi9LJ8c3rRuk,ZOP-$SR1Y6P')e#`JJSENnl^g7?'9,/P.73Km;nI>=_N\"\"HC1\n sNoNOcYZM2t[N)79S2nf?e0Gq*[*#9]bH1.@1T9dfqQT98^fmB@ZDjU!>Qs'\"s!QS\":4=*\"\n STp_B9H(`ZP9:D7f9N[QRQ]ZjB)gR`uiV+(#=K'j(X]IO-4F,>=3Ce,;=.Qh6N4DrbTQ_:T\n SfL,[T\\=1Y`cn&\"pRf\"tVjVh.d>=N@p+3c_VX\\KtcRMUFWYa+6WF6aF\\t>sjUT)rdRF:J@2\n +<r[X`'UDLt;[%Zo_:!1O40RUQtMB.:8T`D1_RJUtE4lGWAOq<J240V7GGY5V*R7M@f8hAp\n 6V@])Su<#H'S#Vg<ij\\c]2OQ%$/.<r.ZW0`2a'_B$E'&cmV;3h`R#1UA#ZW`qKi3iet)6)s\n V,OZKtGHG&OPO-2JlE1/_*)EW68D58%0Ufp=A=[B1B2jANq.%456gOGddE!Od\"_P-5!qiA9\n $m_h1(n5nGN3t8b?SuS63Qki,O]9=GJCk+:sZeN*u]>([V_5Y%4]TE`3\\-Z-g]2]`KlM7V;\n HWQ\\?`LFJHXP,h->@u*+CRh`M=*=bV3`1h00%jB'.(\\fU()]UD:`,lC)55#>Ha1F-+t4H8g\n Ns=>>7\\UjUTmN>\\uFMjga*Cq/l0*u`1+Z_gV(Q&_7Z&Z[!2gB]?i]FeEWN\"]j\"J_]B,NJID\n 2/qKt&S%QA^($qnN!b[s:W^Q5.3iK35L\"#Q\\$G%.h!a6-<H0-X8*;4>\"H50>h&'nTu(N9:`\n uuW<N@p(h(%p]MZonccoZ]L`BX\",FOZs)9/0#U=^9r(3dJs?(:R%[Q6X:Hh5;TD4L>FSNCs\n M);209UTV9HaaG,3)<WG`gL<:ad[[/Vf42uD\\][,pdn6mVO.XWZ.g>]jLR_;mgsadNf<ZGu\n 90D%)3k**dgH!t:M)rJB4S*O2s/`kY^AS!Y)*?2K9@0,'aINj_gO4-J&(t![7fXjgZu?5C:\n )Ta]*22?@?*CdZ0#W/ob?_a/S\\-bL5EC4[gCQ0&!FQgO<S^qZh4$RXQ[RE3Xj/u>]phs6eo\n R<CnO,@/a*[32I=6+KJV*fRd(BBeg?$EP=kS3@g\"dV+TI350is^X$NLe8Pg$dZoo@ohNj./\n 9e\"]O2ZDqpp;!uZt<J9fjSf@:pDj]\\X`duh<>-/P2,Rb[3rh!_Y=-f:HgP9'Uc:]]KW4YhA\n (i3o&V3'Gq9)<%-YiSKq*5t2_XC)cqFjIWE-*]$>n2riaVj8QPFSjM1\\8*\\F7kb7\\RiBeDG\n >M[$Djdb\"tqQBd'A_();k+(Z7G6aU`a-+,[kKS:e*IkN/fB@P87K/:2S-=j4kK,dNl(/jah\n O\"\\%E#R]T*d%SOIkPZ1YcM0=lb9k\"h8/Fne*LEqqq;T')AF%&g%A\\'h4<GA*b!=d8[R>ec>\n *gErpeS]pYWX\\Jq!aX56Jtc,?LKFXre2%*YY]J(UtP+q4/E+TfO%Op`,eGoUi0\\Il/AK3U>\n QeqgUX\\Im\\BD8,CQ\"/@J@lIol$Pe'3AJ/T8u'5A0D3BATcrpAOT%S9(d(GLqUIi\"=^`_>qI\n XV'&T**#9+k#:3Jk\\83o@&Vrj-@/+89.i417@t=3Y<^.Xe8E<YkJm!pXPfb:Mfjpa\"QXWX#\n F\"*pAD)l&.VGkUlp45H%\"HsM1/J=%7Uf%GtVL'?/nUK'RQ!1S%Z!\"20l]p2sI_fHt=R;>X2\n 4i30[9Ds`gNC6hEOf?BQWplSnThfL>K>.O:oXN2@'DUQ2AZsY`F8:]S7XtepH/`=kODSS0:\n 'goo3'koIlX1JBQT\\+2N(G/eEQX0h.FE'Z.Eg#)a1X]EO=P=pNrIns*_`?nG!ttbK/feaCB\n Lc^32T3b]0FO=2).NZ.\\MfqjlU<I`fd2KMmaO&iG+#o_L^Whe0^Unb7FF+$[6dn`sQXs(L<\n Urr,/9oE8NOA981]^sGIc\"[T@d%K\\s.OadYROIRg063MZb%=jQ,57U(8nU:P%joe<j`6gtS\n 'h#hl+CIY.N+!SnZ(u:Ua\"arD*(E1U@3:jL%#5rrV>q/uQnh'p,ft(KRj<P?N2C\"*;QQiJ9\n -fb&/V,\\D^Fi2&<4=TL1G$j-9f\"W7\"d3I3gGdC+K]b?jZ]+?6:D7[ao$<%)rBO/c'`RZrAe\n bbC:pa4573O':+%ILHOsN\\oLrD!+dg54kOOL0T4Hh)U>t1/[Bu4Xb<9^-*<[]h?L7Y@:P*K\n 1L!22)UNTL8OFrohq_-gA''o-7#[Pa+V=Z09HAhIlarogo\\D51iLCf;V%3)2'7D-O/#^M[9\n lottfTG;[?]>dmGRF^;HIOQBZSQ03ErY+)J(h`'*[IUBSU\\6karE#Bq8n\"pVJ@5#n@KOJg@\n *roa],RF]AOFAbb__AMXNFT3B71_k4'L<L'3AsME7sS'\\Q:I?bG9TRU2Ii,rnn)g08TN%[S\n kAhN]eJXg'Z$G:'4-`p9XE$24)'o0T01IW-E!h=e4gg^CAQI'KBp,.#tf\"^U)csE[*:C'D)\n D'D;XLk)<E1DNNFBCuqmC4P<e__E>Qi\"HPYmn462c<&]JgA>EBI;=`c8X[T6a\\rO!_g\"(Nn\n ?REr=J@c>u,:2pZS/#=m,4]Z&jPE`]GDkrP>Y?eBNbQY*UjB'IkL7Moc^LLImjH%t<B(+4r\n 'fWU?oq&&0Gk';4WT98sF6sGlOR9j6dqYo&YmUff!CFEg;%W.d\"q<uM#kW1!*Us37\\K;X/Z\n Ds+&og8tVWlSMqWrDAf;?;`A39#*@/VVj0TD,;C`[cL'7ab+Vc$Dgfi2X7AJd7\\C(+he@e2\n A*oQdMZPfGrnPg$\"5Y<Kb1*r6F-AnSP1\\ZB._:fB1V6[Uc4%Tjr2.IE=X5B4bs<]e3b(/lP\n tfVKom].7(AUjKen;\\W#^Kj&K!0qUfNAX?7eTIJJVVVpNUTl0VA*)).#t\\A'[.D1)S[9&DP\n Z[Z,Q+DM!5o,oA+#>Fe$0*q\"^]VkXuGgogh%!+]DnCIS\\N`2&Gd->,1tX&+r?*p:gT3*1)2\n 8SccEUf)hUE%$V*U\\]Ql[h5)Y?Pn!+c6+AfV7**=V_Z4P6Ja,F.Cq#`Dk$:WjGnV0N7>;Bk\n kefB00k'^pLbg5b9UV;(k&eaN0b.Vd3J(`b7(o''Ao0l>0Jl9B\"$I66/5A4E3F^4qGO^-):\n 70&k*Y`3r%k9E^1bTeSMp[Oujm,'tq&O,7GC/l>4\\+/uc/]\"WO>7:;d'qgu>!ctd1e'l13?\n L[sbP\\+B2?6Ub.fcO?RXhN+\"O]3]\"/'KYD@f986!@Bk,to.)19sp/0o?6)nAl6;6un?NqV`\n dW5H#;$Ti=(/=XF!qQk^o_R5prsC2D4qeOHK;3hKDeOh@,]<i&3.>u>A0?`XVD7#[hW3N\".\n dXOX1i7Hr8_-Zs?:'>h:LMWl%W[<G$\";LM%as'KF1/rqgn_'Bp,@:)0QBCZCa84jmGT7muR\n ;D%`0RjfUrbPIBfArj_b.7e.SS<L=C:st.A\"KaJ$Pgm,L;[Z^/l'*0bODGmDJXe@u&FZ\\Yk\n 1s7RH#HdO8#oW6C!92O<@Y]&\\CW(egq/\\i%NS]QG=C(WH[U$S[FZs\\jC&MOeQM>5h5o/4nO\n >\"e46&Hn]]^hk7]G\\mYB>2qESA07,]d@3Z7rN/MZ$@uploSps.T2la&sAg74bPV:j-0(fpX\n p6,fQ=\\nna?78N]N1*\"8ZeU/KsULJ-CHYJ_.%/dm652TL(9],7F\\@_>j%9\"i$O<sBOAbF=K\n /<]7M@k8\\!ED_Z-`_T#7&Y2\\f)O_r0S(Lq(H<fEGjnnd<uFggl&2iW-(ZP^B$B\"Uoahd3V\\\n EFh)T0j\"8@@.2&;bnM)7?d&O[luiK:)90cGHk/[4[Wf%p2[7sF\"_Y'&Qbn`_$driI\"Dpnh[\n <Qu1@N/aN@+Z8/6Pqln0tKGHp.!LLB2**M;iEI90j;%\"*b29uWAQT/eJacRj8=P-h.l`6R`\n AQ!b'Y!/W7B\"84'cWlUDKhFjK:LLG\\*?0QS3A(^);DSfDFf\\1G+0m2s1+dMA;UsDV&Rs(HL\n .glQ`W7GgB8eKjal$TC@jUZnO+r>!37-ZpcRo<jl\"AlXRUt-mKDc-Cg)nmQS\\ZZeuf.JT*E\n WVmUEEe68o,C46u!G\\7QGd0E]e%:(is*sCUDA]=,sr\"TBke(6^;-h9Br3o^EDN-3G<?HuZn\n EnkNb3IquY4e\"ZZI075g9/YkFX^a%#f\\9[9aiNfZ\\)`k7kl`4p8W<U=F:RTCSOSjtH<#_ZI\n e)e.(IiPYBE]],0GL99<fOB9:Uo\"hm2`+4'j_?g3(>a`]uPqQ/gK16[r[uc-\\M-Q'6QBDJ+\n *g_I#l,?';5@Lf6icgEc2i!r-'W^>8Lc>pSG1.ZR4hH1;@mW\"ghe-e+=XQo]Gujd'hd8kan\n ]IqRIu`Ct@^o]:P++q*2Ih[oE)/T<$+Z0.M;1o[1?s@f.m4&g7#0KRO0fI(u(lHZ'YfJ-1K\n !NpH@\"^X`3'?\\NJaU%_5&Iega6nJAA55=.oB)BL-rGcKBU3A6E*^-_GX:0Zg-a-XM&e,<WW\n \"dttRcS+%DU\\iFa'@JQBdm-2^]i.!U@lpo(NkL'c\\ng!.96<!/PIG<:/Q'*gMUsenhnC:9_\n $FM%cs)7/C56JK^Dn!)A/:n4kI]JM5+CoQZl6cV)nsf@*=M:$MI=1%(IA6IM`?&Bn08*@oY\n 4nS_GeFa/,-S@G<_9B4Hd<73kRJ13'>D9Oi,I&K/BMWclY@O3V3Cl;`R*93^?p\"3\\dbPH:o\n r62o(nI]qJ4e\\Pg5aSNY_P4mY>FqaNjk&V.)[\"t2;3k\\UP!G_`pT6rZUn@:hfXkb\\b+_9<l\n be4RZT9>m4R60(Qd<$0%p:W3=6#H3%Ui#jVHotjrZY7((A;tr6QQ+9ii3HQaSHi,Ys/NhHB\n 6K=S$!M)IfoKs4b[_k'f4CXb#DQ'Wo^iS*M\"/Vg:F!*S*\\qE,H/3CZ%6br\"V_#/&`*\"b[4D\n T;_d\"P@2dX%F\\4>=AsBa&I2>KL`cIksUb/7*KpHUeF:Z]0tFu[<,27A:D@6H:8qt\"ZU,57\"\n W9K?C5h90/Qcd]NHn'@n;5)\\Whri`/;=q1<&S*`VP7h>;o\"jTL1PtUf:kCP[um<2TBP=`dB\n bQ\":DLLgUC[m]u3%&]KN`g5/uYJ`r$F!kY?jl6&%pL#Cq2Wgj_pQUWPj$a)iAs/9o4BVoP=\n +8%bh(7\"!-dBuf;1b1#GWJ:%US*'4R]780t\\]S%=7-ajG<3F%=Vj81ii>:\\c>aKtk1oId\\u\n 01ak![]I0[,)Af)1R!KT0M?@S>GSU\\Pq[l).28+<S<u,YR6]8j1eaB(oADn;S]o#k5oY1U8\n 482?ECq4Fb1tCh,Oro]:+dKq8u/E1AC\\qHW@F.59gZ!?K[S,O^e3g=JY5kp>d7#pP\"RM'85\n Y7&'SaJp=icP*aIFeGgptDYs3&=\\[\\M3mglFJnlc]LH^f(A2jHD`C_\\@c:4cI?*j)dPna$@\n Sa8X.=Nm)hfIb=Tq%ajeR)r6>FEc\\IFpc+O#$j+0oeI2u\"Z9l/HY*<OK6\"#uLX9q.#4bl5t\n 1J@)P/!J\"\"$;K2[<.aY\\4:s@h?+tc;pKZc\\;:+Wfu4GV+\"&Al#,bEV/+gl'/4kf*2Y\\`E%k\n /<@S/m7&n*cK#1)o^G4inNE,U7ZgNYPfLJ\\6TVQS7`l00j?HG*-dST-!?b2C84A8HEDOZ):\n jjqDip4qgX-T\"O:d$P[,r/:c1Q;gr:]_ifD(a:Y9SZGk#LF:6V$th\\$rb+S;p>cj<Bd<#i/\n `9Eb=j=f<>*Jk>!K[]]Y(eo`943J(`s/?9@T!+\"MV=h*'H-p7SLZj4D%@t`\"]U%\\obqTXWl\n (c,I_e@^uY5]]dC4qq:10I4r#N$84EesEJKeW;ghs%ib['A\"dZPN;_;G,7:K1Q\"4L7(1)/H\n mm:N`@FjlEh\"V>6D]ffE(C=^?g4@MLGeI[f'6<#^cd5tl3K]Z-;F/T741H`;$AP#>p)FGMa\n )Dpg#/PR.k:,#sL3`SujPa5)s+gA?G6aZMd9P]o9-+_W.:PC4INJ:>ac3,h4LC%:PrF]6?M\n kM_0dok7&'k5hgA(EN!cn/eZ!9M[HN*/L):l#u`j_WM]4kYO):u`s#q\"dr)&PGuYb@K[24V\n Z)!7QfKC5P0o@<>ec+0iYQ+eAWD/[<tY!PZ7Q>cQ.L8,a[%;$s4b1<E,EubkK5si74*sfQA\n Uak[T7t@YXAm#FKmA9t&eshk>1Ua+VuG'p)Pr]%b0S=XB&nQ'9sN^T.'Q2sf@T?'eeRR+(.\n ,_Grj(]l2:=SQ?76<()RGoq5ALFV6i.:6g#VolrV?Gt[fMh%E1SgM^8:4ONecg68C6'n=r;\n P1mKE>0S<p2\"oYgQs0@<fPTI!'G5lNEM\\J.L>[;27DN4ej1$\\NgZ+/nmCQ\\I]\\\\(KWh$iS;\n chgEl`JstJ\\//A4dY$uQW]ji6>Me(Hmi6FMqQq.:/,b.<M.ZMbM!Qt=(Eu-c$.[6Gg=\"!>o\n fct/FM=Vn(NKGi\"`7`D\"Ci;C/m[Cg>.D3ABN`M>[?Hri/?P?E+7b+8-UIsL\"L2GJ9?X<lsU\n )0Mg^RkW5`.\\k[?pE?B,bo`TgZh`EW$J@?Op@a;kF<B&;qqfo>LY*=uR-0inICc961&V/j,\n ;FC0I?=sY$@il'XBp0@hphqc[`BrTMEs&[Zhi\"X,f,1'^S`ncXXh5'aM]AH^jh-KG*gE$^^\n @TVKd.#\"%'\"itY<Eh;6]46+,X@3ueL*Y[L5']EXgj:WPCFlhJg4QJhG<QKV[(*$RK8)F4cf\n $bu$AT'?+SDQcVgmmJ2XnU=^pl[N]hlMi-%Og5bH6c68f=V=;mF7U/IN'TaYasCr/d+YK<T\n %0;7a;7Q\"ps<hq;Z?#@s2:8-ldq3B*AQV#=Kapr^>mkj($q5@5YW,*^F>GC?EBEA1eLR%N+\n >WDkT^I`?66SVB'3-F50HoA?I$-`ZX/69supO2I4KNS]k&]q8h*]?aZ\\@2:1GPe6hR*htfl\n O%P:Q]nj\\XC=:R%;*\\eC!1/+8p\\\"6o;p'G50@-GU>!Bgc`n8VBdMWY2*e_Y!%j6:0Q5j:aR\n ktZ&T(2`#ZDeTuSSYT,<i#m_EBBM1Ce'/A8>_QVr6K/\\/?WiP$2>:QJ>j&M;g*S/0egHXsI\n ]RuIeBBc!hH!!U/D?,:ipML,*X\"Nq>NO,4A_o5SmU,9;.-SrbCK=hni(f\"l3!KY+#)IDWVO\n ;5,gM%uNj7\\c(k*9`UCh\\',B'YB@^;?R=RK>;;C\"@B:L36Y#iDC)WjO,pKL*GMhP38[7bH2\n TD`Qd;C;W#][C6bZ2VL`KjJni:W^m8,2/88kkC>GH7`l84^Nj;jnMf$H>lV?9u,X@)BhZ@#\n CKlCo7=FF\\f_eqk<ld!=\\0l6)dkNhR\"C\\ZoU%I324jR0k&LVpt1GZY09`U=\"&Y4eHt7`fBS\n EGVYfm(F-Mb;*W3k\\TMSAKE4+^!H'T)sn[rD(NNj4k*jLKB8,H9O9C6Xat>DLM2Fr<GdH<G\n 22CG&ae_gmH[=1pBn9`('PglKLF.A0R?5Ym-t2?mTo,DhWaPgl#B/(DQR;a^C]pTIlQ@<[D\n ).sAaaGY*ne!Ch`6Y^R?-VR'P]7GjRY+c<R\"ubcg#]N<47:_SlKGFs&[ePD.V=<,W]m!;f.\n P\"D3g!b<aK9+#BL)WAg[lBY7#4I$?JIB!8($N3&63GCka?Z#E,p.Ilb(]&_71\"nP9hdO$:^\n A($%:ho=%#OC7^4M1bqiFCgS.&7@WIa*q)hsAF?5Rrlr+E,B'0Nn#e'W\\bGZ,<:AZoEde\"/\n N`^=n=n8_uo\"Kju[fko[ghj>+kc\\.5cSBP[=7\\@Uo1n0DfV^[aBP@]<FqYY_`^=h!5BG^mp\n -]pC\"KV/2@J57^WUMpEQUPG=C@l'Jghod%Nd($mGk)=hmqM+Q:!E'c8G(3S>\"V0NbAC^k/+\n $']C=cDW:BKPdY\\8Kio&TOcp'>VeJ+/eTlVCf-5D&YW[Y@:2#0:2-+F%cgB_[1`p+39<5<a\n >$AU(iQG&5ZOIu*mi@KZsH#6/IYY&s+K7c_!O6C.6#<M&pq8jD2WpHHo9e^!gDVtBD,?fuW\n U%TUpEK&qI38RBtM\"k[Cq/GI[pomMM_AQSX2MY4H0FiReaVh9;uhZ:%:\"Ft-?+EOB_O8B)f\n ?<369%[6\\6ZhVSJa1mVdhi@RE[uU5Rbk`jc-1:KP*qnKV>_eVE5B#nt8bX*gq3IlLc^SS1S\n Dol2kQO\\)L0%I6Tl:LDpTH)\\B*5V]='.rGqJKX9IZ*m6WG>ReI2As\\W!n@3A&0R/KnsW3l[\n O8:f<k\"Oj5d*72mn!&Ac97-qd^Q@GM%?5m\"ENP-NINNY/]oEZL!$`:+*_ccb=4n^Md2hEZV\n #pIXCu?Rd[.sC59c\"+.i-He9lHhE#0ubIb4/1LN:s$I*[95&'i3#W9+W<qR?;#QSSXj:khM\n %1n\\E889o9LJ3Vsg3$]7K#D>EP:q1$o*=mro@So+\\<\\5,H7Uo<*jE<[.O@Wn[34!#d4),Kq\n &t*\")=YH+8A[=CMdUb;+8tP3s)uT[bT26p-)C5lQ6DRIm1jW.[R89[/C\"4\\e:9@Nt<@_'qh\n .F3)Y?5SK3sCedA[GV-<bl9DgL>FJ_pb$]f'.CJhJTJQM/#V3^gM+`4=1jRLW!YA=M.7oY3\n 5q^Qf&!Uq^IiRjmuWFk$pQD?N>,X/Imh9V:92Z8CdF;>HHFmFrN=<YA0'OmWR>m*_Ugohsb\n jF4pFOa`oJfJr2rgH#`n(h3W1\"s:Sn:cYWEl.cYpMQm\"(<.%i:GMjn*is?>jJSgZnt:r[\\S\n PfB)a7!YR%+fCS_8^^p>9\"Met*K*\"=-1_9eQ:co[$6-tQ6#Q[b<.U^-_bUj:A&82hNQr*]J\n &4BAH8JB$^9MH6i!+@9a7F?cq(rh].?3\\F>ab:^)ER]7R(ifb48k:]_LE`*nE@W<VE`AGSa\n jP,M--Bg>X\"2>UbcFH1Ep+St9Ch_b#SP-&aYQVs4Ol:4TSY:1:\"+dQ36m_Xls^#pI.KHr;s\n a<EJjdQI5u9BY%78F7R4r*t<+Qk8dM.*F$54a<.8*RG]erL4Pf5d[e+DiS9%7H)92j?*8W!\n lh7Q\"=M<OI6d=OrakD->H_BJ*#He_,m#PpUJhB,kP%k'SnL9pK;CQ>N1*g(o[DOWVXVP'!:\n *M26'bUI\\k,0$De]EN_sfHF9m,:!n*cpMJH)?'g!$Gi\"d@m<RR_XmphqMi-\\;?l':VE\\D4q\n Vh<qF:)/KAQu3pY(1ug`\"MARU/C*8Aq`</8NBTDQZE9<tOlT6#FPJg#7TAC/NYYgX3R2MQk\n %9X[V45',_nPPORG51EBFeF$pZRYgm.rpb5*#]Yg2<;W_/NGO\"N!uaXfB5le2seu:qTl5`>\n \\q_Z,L^aA[CaNN.2pdOmIE?8Ge@&.*9*&Tt<ope?LNB;P_.DbZkS.1iSs)cT9?V:D#S4Hu/\n c%:_V@cajBs^'1l'Vbp1H^*:5i6<':[D<)hCL8^^Z\\9l&9\\4`+P5Fqrpi?3u=JVG3M71!k6\n =3.HA6p`9s\"iV86Qk'\\>*0sl'0jftm&'aAlTB,-%i@=ihC&$c1?fB)VmqqhkUnbaIV`U`sL\n 5Lo@RT)JWTrZ9Vl^+\\=rmJHo*ch789jr)6&!/`F>0F`t+;`r+Y6QTbbc&t?38o5G=-\\>%'$\n 62E^bZUu&3R$HO1RL;NNrqOu/IiCM-qr#l9IXZeXSK6q\"Oj&k:hji9WZ\\aQK]0OECT)7oN#\n 'ACgC-AaLnV2NB$h3[>Af9P/L*[7i=h@VFDgVC]XPt`hVuG%E%-Mo3!Tk]*%YK;C#1ST(sM\n %\\CR0rT<C8dVgu];dTT2cr3]\\W_*Si8l<3EMj3k5+RQ)h/kWq&FVTf=dDOL,q#ON3COn35a\n jOciU;8kE+X2MZhV&48-k\"&W/V_-!WRY>.tY(TR/cP67('`U4D[f(r`iYEi)+>\"]0=/EOOP\n QP/Y[^A1h`j]'&BO4$Zp=cG/u7*1Ue9QcC]2PT+S)OaSo\"L8?9\"5n\"KAC*e`1:SgWk6)Wl:\n hgJ8=?d(\"\"<qK?Q5!*If[?Hl9857J(dhD<4kdh6T.ohb28hKd+rp]W&JcV<<n,l5A4h^n/g\n nV-nO)<JIA/H%^dZnb(S_+?N%QS8;:cI\"*.8uiMBXpgG;U?h6_'1Ac9\"qU7ii[3WfOFeRSu\n .P+Xt?^Vc!d1M:%>!`PC(?@r-8u&b@7p<Cs/i/uD<tN^!\\Dg`9g:?&a\\-1MXU+PZ!e28nY7\n V.g3Y7ZKe_gRa!K94_:`1Y-h<adeerf@@0snR`nBn?0fITY>sqK%KYQP_(_Dt'1Ti(@kT]U\n 6joJ\\3lXH7]*.'\"Odn+?b!G5QA^5tnZU]``cHA@`B8rU=E4UA&aD#AIS2m3Y@NO7Q4V4OqZ\n %u?lg/*]E6CW=BTs7(C74=uJBUi2![gg/NRuKnm4W]Qb16GH<!D.0Z`/XD\\l;Gg-9('WDV@\n hgW8,Km`A/4($1'uWmCWfLC3*1CBKPM'KdQNB9I(i\\-qHm,Q5?=`&*<XAEN+'F/KiF_0<GJ\n UC4:QjQ)prtPT\"/7[\"'Fl;Cr/'A$\"7'fL%(ZO_SqOB=$/WuJ-C,1fT-YS>YP+:<U^3eOChT\n tVdYtJ$C]1fCh$Qib3XDdZ;Z1<:,k%jm)>9';kkO3X$8\\J\"RVclZ5$P:SN\\Vn276BJI9Pn6\n Q0jh<[MI.5>?9':ErnA2F>5#pl[%Bi#&/up>;f?:O`Be`*6qEIk@[jB8FDJdcUpt!h0N?IB\n oUin=+<PBj`Ph?76>Zr0(Wc\"b9;To9m4BUBb\"\"U4I/GadopZb5@M=(\"IRUW_%9_.0NKXf`i\n .D`VZ^C%?%MKN?`ojD&!JOfL@rP'f/RPOCYa9>p\"<oo\\:\\6'X@9%17`j=f/AK^(N%5*e0%s\n FJ)<2rA@k:joZ.S&SA%fR;/?Ij$f`^X%>;q^(7Rq.CM^?6nl'(;=n]Ejj.Dr.^Q*S^2b@me\n ,:e\\cE)d[%4=dk+74OnCl?,Y!_%ZPGWgN'fWB=YK0kgE#V8orj=j&u5FkUcl$1c7/O0!b\"\\\n Y\"a1e7ZQRt(_\"K)L+A\"7LDaTXAe'sa56pc0fpqN&F4)U\"S`$%niD-'2^5]/(7]bhM[fbpn&\n VDs<`F)m,?Ygdaeb05MlJ6*U99\"_VHN_1;r;3dC?Hpe$aS[-R>Zm%\\Vi0]&M;\"i%)f;*d[g\n gVFg\\CZ[*,WaRcDKcq40'XfIG8GEL@F&F6[IJ!XUfX,>4P4BIc]=&^[9X@DL%k+n:*U<]a\"\n tk*fi>O)k\"XX7i(c#kDX`D2kPMMT&]Q^<Ur@kaKGf)jJr*AkhggWD_E[ZrsRcebZGeg!8A8\n ?8k2j@ch%-inf<A<I6=4Q(<+qZeR5FWIDMEI\\mOF\\4WC9t?C3NpL:-tXZ`80)[JTuJn`t\\N\n pjYVmfDf2d>TJmhs53bSlL)Cfr!f?G)c#8/cK(FslN(nmmchOU7Tf,]^rT>#go8fm9/t`\\$\n Nk45\"0@gY.Hp;=j?ZQ[hMeW-lX'.!p<,*=T[,7pmKC!o#mP,io?IuCn8R@1hXn$so^(q'mO\n F361:h?_p+6.8DELh!$MOm>pMY/O07`/&HME=-$BKq'i&VOfO:!EN&tu$>Tr8u_kiYbC%'[\n ra`Jbl^6lQ0T$kNaLJPI*/]aetm%^3VWcc#'D`mml/l-IfC9L/Q[m1=4%&?k1,d0UBId/O[\n XlnA/CnKAN\",_\"\\X)$.N0O:K8?k3c%_Z#-r`lu`?sp=q+=!iaEH%#k@M#i-\"%\"2i.^$0q^g\n k6.t-\"UqX>EH).Y>o.5ci\"0;f:'U<M#mSS)oI^pb8i4(s9]BtgcL4f[$`*IBM$VM-j%tia0\n UE_-!t\"BhpQ23jmsPPj`<rll$K7$?_3bZ4HlG@F)^3WLKoZjdjW7khk<Z$eU$<7b6ja0h\"X\n -PWZ2GdWrua'!%Zp-%ndPF-pCC.=l-'GEn+@kKlOZo*,-_jp1,1!$1Eu(0Xth:8X?p=Bkp1\n :@,c.:MiM[aV+u4-pmI1b.;*'9u5jo7-!Y?XGNr[6U:hOcL-`BfUYWgn6K`lFPL<EX$d;3S\n o,:RH>(QU-ad\\,MQJBY9Oo9\"j=:iR?@8Js7Kc;9!@n:HX]L8?S]p$,a\"mqE_;R#ga-)mR3d\n 0uG!9`uNOj/mri;@@duQMAsBL*!+dhZ;!#,ar[8M+/+!#@GVOrPT1ft('16R_3lF/#;U<'1\n 9q8tdM\"DL(Cr;^&#huA&+_V(_'5%&1pT%snhi9\\9^<9.,P!,mo*%$.AN\"!a(K1/3_'Bjp1@\n >c]RdI?\\P%M!376#=+'WoIG&pAqJ<B4l[h2IgOD\\U>%;^gs3.4P95174^g>&;M=[a8KWOD+\n 6iCHQ>\\.k?Go$]c0%Gq8;3)A/R:d`/+]bq,\\W/I_pXo$l`_\\E'sS5G`WXZK4>,ks/(H\")<2\n h:1+T@NZ6qf)o:1?lf0mf,d0sb)St2MTe[O[c3p=j)ZX'+;^\"OP9enOq6rPZmP9huj1EdDh\n +gX*)F$0C1AMd=k,&(=?;c,DoF[n967gWrgZtW&[LEohH8@4@IiZ]9ae/i!W;R:O''7.Z^I\n nFRc!QZK4X!Ka,JL<0Igsj!-F.\"DnfdIN*['GH&:Dl3O=Pi]&LXWM&o<g%:><B*<46dbI0o\n %lMdhpCu4UO,29^*FRlRXY?4u&s!EN;:,Bc@`U;6OskZhZ3@=$RH);RIq\\^bht>1)T[C;da\n q*!9b8.\\u9&gdc'Xd'i9-,/ft*pW^,hd_7U\"j?j.67<g60VoL2gq9364,7.kss1fmd9?U`8\n )r6mqW&(sGEG=U2M=gWNYeX0\\XJQW;12AK.oos$hL`mXom'Hr`5mAW].'dbJM3&Ieml+]kc\n `>$G?!qa6$<T,sc>X($<\">ck1;/#LLg@>s:4\"i$X<WO[(?FMK-4;+[PeFa$QppdPP#?:c!e\n (G!?h$?lS/<plXk<hGY5qR7?5>p<IoDJ@U-U<th;V\"J8<BF,[<E#2b;d`iETpQ5HF;k6')<\n &XR6-:5LjR\"h2B;5AEMZ+=QQ4??l#IS2F[ZDAlD/\"0W=#QUNPYFS)V*u!r=B&EGo/Ton+%C\n CP1c%^+p;'oj`EF&!,B]nRWEEEUI;O/\\*_MA5@#>\\9UF!A5'5ajVFK$TdXP:(:-IGCXFkD>\n QP=uNFE2h`$8``Xt'hoG59h_TpFPC0QqF.gohpr!gPjJZU%_)-F(phIqPl/fb+\"PkF4gX$T\n Ml>Yll!k2b@nL<0e+1lZ5>jC.G-IlTpMj`qF_*I6GIMirF:9#\\K6T)U(uTu\\_4V9\\6ki!0)\n :XrndgL$$efKU.)(YGK+jLO*JfB5^'qq?)p0i=LR=&)XAepeK<g.q(D/&ZcIC?%To-nG*X_\n TeMWqDEi%`<)Ua)!ZWIs:j@YN'HkKb;gkH<:W,nKK&Jn-f>8)V)ZAfHFLaWr]M?>njV`no8\n V\"LL&Om?8i=5%hW-Q@p\\Is?T0&0pEO]uFDOmaM&.d]QSOEIn=gQ!@95Xef0YEo\\oAK0N>2b\n B'b&ER&VtX8;0QAW[p^kPp<bcc/ep$`31h2BIq?-hGY3C/Gd!#bXc$RL'>]h;(VC3NJ/a%n\n )I^i,@EKWI!J(d]0VSC_iS5KsU)dY7'#9kMTrT:Y9kG7:I!<Jhq#-:5bE+[5I5qabetJ3`H\n [YYGIT0O#Qg&to#=pfHJ/A$Ep]$Ep/P#@pP&@+5=P8p!7-Dj;&+]H.(@+R.md><GDceGJ<3\n ZKa0KHMN?+1#NoY[\"Pa+OgjKM,$mPG\\Q3O`D%PKm6U)nspS=l#RK8L0$:X(HX,W(RemT.s'\n 0pAFG;O+,B8;FZ(b+QW]-kP4lDJS>C4'(n\"9'CPk.*A@SO]fW066[>Pm2Ss0X$)=O1J\"eOX\n g=<OuL+U'T/:)bA,H,8XBq*qP2gl^QS*9#ljX4k=^]F!6[\"a!3:_+5GgqkJE3US4*NR0AZi\n #EX3=I2Yh-pXuB''7Lj&Ok-_!&f6^3\\mUpVP?Mge3cU@0FC\"YFVJ#(B\\eD#'K]g07N7(cdF\n i<^6o1F/MK!tQ.n0`iEO-\\;1-^f+0eB%ft@@-PCQoIdrfMS_/-(*ALEn1D%=COi=B428^Xg\n tD93NWO17u*F(@TQ>V=h\\s$=.Be4S5qRl2E@<D6(M(qG?N\\)aUas>'qTaiT\">r6=n/,2-*f\n T\\\"-Bpr_3)&-J/Q/4(Ep!o!KnE'5eWkAJ+ZNqg4j\"uFrqlf*9#rmOk^L6Q5hU6)^'Cf)DS!\n j1UfGk[sNP4=uE)/6+D50\\@P%hR1H+&f9'6:O`m_#P:p\\FkA*hU'nFYr)*LI#CSs43VgGtd\n qn+F_H[cGePT*Q6qp<94GT7m^J2;>53EJ/M>?nW2WUkt4G6+^f\"feY^K@Il@2\\W6;JT85S3\n k:)SR`RWN>0H\\ITj#npNXJWDh1jY@LDo/kHKS`Ul\\F%=Y8P$kqY.ohr4A>[SC_>V;8%/+eZ\n esS*4m#Y(OMb.+0h:aZ5d\\b>;=/[0?8Dqa.\"dk+clgM5T(\\lg&Sfu@/Ll#^_=(3(=N+!.@S\n 44,J>9;NPWP8qALDT=rh#m)?IrnJ\\2=[S-A)M\"M-D5_3`Cde]dsE\\/Te>gOH]%L!G!/cC.8\n 5g.Ah;ooU6iC-/&MZs0B\\@/V%JVq/Oa>J&9E_9lK)d@81g43OQBWR?2C^7h_P!(`4B?+r(&\n WG_*glQ;EDHbThFK3G7,R]V5@<8D][-oVl%3kN1r^T9$WR/Lm'ZCdP0@@=^WRJPTk\\8OM-0\n 8EAN_blo+fss9bo8$X?/D\"-f3rpp<;$n6Jd@=FG*O3TZho8k@gUqIE]-j3JFiV2;gjFSZ>_\n 1]odG85nh-J_JiK+1N6lA79'qq9-p_jVCKH#IT)54t^_5nX8?t*>D*^R.RiTqSYmeP6TH3*\n j]J`%U.PeUX;)r]Q0!RMDB3\"BN.$TgHUc<peA=9O1E)1G0<hFlr/<TQDIbrjb*IU2(udEVZ\n )c9$6qRu,G&O3[`KI,+Il]:5X$Tt1#*+Pd:6gTf,G\\%@&-d=.YN^7e^.+6c+']\\P+'riiA.\n 'H]ShH9F3='W':K4he>M^>2;Z1Q@^)/XGl^^X,!V\"7a/rRrOR'ESA5ieD7r#<P`ae_6TnF[\n -uVfX4SCB:VDL%S2-l;2k,1V:q`1+\\\\j5OSr\\7lYT9U==IWiLZ.ek*Sj,BX4D3F$ZeQWoZ5\n q31hbi4Cg\"kOgh&YDU^L-[thtDP.p0]uriKO!8F8#Z'>JOtg+eAuL8d`CP)W8dZIQ/:?\"#5\n 27*1@uiiE3*GCG3MY*5UZ]_;lM2`#EDG*%`n=@J=DCpb4=>+2Qm6s3;]pf(to>*u$7ITqIg\n IM>G&40`buAeq>&02+'YF=Fg)f%#4S_K%qt2Rfq9::k#Q\\M\\OCO)Ms^mMT$dV72mj:*0&!L\n &c!,e8Kj8<`2Z:3VH5759BFTq1s0LTRE_V8EAEfI4.abGe/AJZ:ILs6.(\"jp,Z,/NZRPPcF\n \\\\VB'\\05mb.VPr>H>)Gp(]H:a'rY<PkKGuU=F+h>6T2>M`0a><Z2/O6DstYI(eEV(]5$F$%\n ]tOnCX5bh!cP<T>aq1N^G+Xb%:-hS@32fS'P_h)9iqH8\"n@Fo\\,igY>MCOCN^WpQFgk9g?e\n OfS]:,:^\"mV8D^1Wr'o1ghGo2QC)9.dj5PcBAQVXU2lZN(FT%@nkh=#Rc*Zl2ZalW,>r>qS\n 4YM&=;Hi>*/Qd;c/IQpMaQFHr4^A^@Cli-p70C/sO5gVn,\"[MP?\"@ea)F<Ln+0Vg'(([uN#\n 7`/'`1CSeEEISNf;%,r.7'T%,!^nbJ<>J$nFCG:`nPj3?`j*I#)h=`0JK@>/m!g0L1$B$:(\n _SZf,KV]OQR>@&KUXC3i&m&MQkI'<.naIS&4i0DoYE3)1F1!oJMTF:@*K?ieM[FRPh.n?'9\n qfD:@j8V4O7UJofg]cn.nT_<##^*d'Q4P78VKF'1U>V@45P^1n>pb;Y7@B#1HQ1Kh^%Gm6=\n G\\L)i3Ne<Mmi<)eBf.Ugl8I9frUFd62:f%%Tl>Lum\"FpF2\\eU_)[2C4,eJcr?8A6Dr-QY0I\n 0JVXSpp6DUkg:\"u(CP#T`\\7/[o\"hSbYjMf5^!`pu$F53FV0OikIIGK-SGEpqj'.,=\"I,>aj\n qgMoHh?/78=9'k!@)af2Kja[aM@1(e2BRb7(mZ\\0@ecNNMdok>/kq_cp-Fc#3@77[(r4-UP\n iWc`>F&jYaZ*em3M'fNB)/lVRcet9H'nb&l&VKN=q6=_BY\"I.V!2JTQ)<f7G+qa\")HNi:lF\n P!=WIoloOfiKRm_?#C3p8Z2m,gd^[-\\f/3`#-)IbhMOH^<_''BW'Y]^Hfjqn@\"283Tjh4<F\n aDE;VX._XW\"D)8cR\\$'WGN>`U4i\"m\\r<AqgILS.d,U#sr3F4Wd,@FFb&Re<sTL>LdlpB49D\n 84f;nMG3HteMt^pEHBIsD5D\"om$#ba]G_sjijX1A?L7e;,(S7H!C1\"!@qWaEOW[l6\\\\upDG\n 2o;luCNA%uI&h#I\\Lf>Co&[D75Mu9c/0c\"P2i[k/r-rShqu&bBq#B7d!J$75\"$egV!FS;'I\n tn<h5<%O(@\"\\&2V`afAGVKD1e/O%%Fq6n65mUm5,D;.h71>m,!79F$5VTSM6M(p\"&6]f8:t\n ?OPF>eoJbWA1jD%iX7JIg-H/Vo5\",,6DcNM9<2M.l9#,RC')idt'cM*<Dc33\\QDdTB/)DCq\n _b`>E(d@86!t1FCW<SE!R_:9\"(K-j\\b'`X7`dMCprgq!atV_Ng1Em7Jic5p0\\>UK$e!<Cg\\\n %XCP59O_WEQ8G.A6<U.GaM\\\\pdFeZ4nA=H_;Bkp<5ZR?UCj'4*`;D$GJ.T]lU?Alg)9%Dk8\n jc]\\1C_Br+2AX/3Cq3s_DI5,TI`EcK&nJ)$@n]oib2uVTR;BR%Ze;\"sVMdX,N7\"E-8[1/,)\n cCDAG&B/aXZ0M.ibM8?F#H&(fc+2^D6:(O2]:Q0-]<.e%Jd]`G4adaD#9i'ouBl&.6q./\"*\n 1a_A@ctZ6<u/NFUlQL4'E]lk``5p%do5%=+NhHr>TuLD<$frNCY*`bbT?Gk<0_[o:DXJV3J\n 'Y'h>T(?Lus\"%s5*UGK!;\"Hfq;FTX[1jRepKVoVcmH_7sY$!bt_,WK8U-<4\\]#C5#Td<E?'\n KHBeT42+3%=E98/(93>sEA#tr]ZW;D\">&.,R49ETA%^6e:iF2eA<Rr#)(i^\"H[<dV9p)P<t\n KSjRS8?e3t,\"1/t'+r/\\Z&q0k`HraCXHZkG[T5\"`FKZP11h*e2Ou(*[d$s'!G`@R.2odFEC\n #cn-Nn1X$W4;c&A*pR`C51Im#n_&c4H-b43^u[Y+XEk:Qai2\\@EGR4-<<g3PW(Ktb%m\\\"DN\n q)bCT?\\mWF3DNIG1!rG$82ID_CJm]\"F3g@,?0[H=e*:AFh#=bfes$R<6olP=k^H<cp<h7+o\n =rIAgNHT/eS>j..#&FZ'!L4\"#1YSldk]cPc,'B<-9Le+/#t>Ur)g'aDQN:4uHd'o2\"D&B'r\n s'0E3IMB14cUU[cK4?>bukm\\n`FHi1kHuS^![4]L1nsMYBJP@m71OPGJZW#YA:FZBg0,8CQ\n <RZk(.`GGgR85>E>d9PLelU%?B.dce=&uV]A#n,i$J*GKRWDMFc'c%\"B)LS5L4JP1@!RQ01\n ^8Qt^3YNVm_$Gpr=:FWK@#FO_aJ>R@Zf2tM:\"f5B_s6SClXZNQ<Gpfb;EoheY(BWI5BS?5o\n VCLEOAiYelr#L*j(^4[W1lla=D0Poot;4f(MT!H\\&>;'#qGmo&EuC3HD9EU=bf%;s\\:p.^$\n J8?'f<mh76g8Y7B%8;Y'A7CXm_a?JAt6\\msUojg\\o=cbB/)r,-e^IdbhbRhtp>?jXldB.Hu\n te#.P#Sah=$IL_ro6OD(us+W5B\"2`>*%cP\\F61GHn`\"Xj<i`[SF?)B'FfVi@jqDlPMDDL7>\n f8ig'F%Tc)4f+ts+7aWbOX[CiV\\p;;;s]bF11Tar\\W\\D2Co*K/em7I,K:_\\KIF*9F6g*q<0\n lpZ`c-/(Yc94+aFT.u`HC%RqLN%<q61PK,j`AajgHJ]A_4T)fJ*`9g6GslRU3&PPd@IXOf\\\n IS'FJ!W[H;@2eM_1fQet06,Io+ip!NA0qEn(();d/QkicU<?ee[:KgSJ%k]U$(ZITGKEmkC\n t(#FemU1XBlAVm7q@b4Lk'B6o!\"[(TJtg:L_D0^Z45G3?0chURhX46&,@2nRkShf\\hpiUD&\n ?!T$ofXl+\\k^%^.%hk)fQE\"AXq\\1[p[HkV.k^TiRnf*pX<GDTcm.JQH3)Z6+;O(09ZN6,Zi\n `h0`&If;p\".;('M\"[=1$^[I;qH!eZU^p^6VRm7@WW]8#0/\"o3aU-LgE5YMAI6jGtZgH%Em5\n SGq(\"00/L$p`#G5hli7kk,1jI>@#=\"fQ1Ij0-&Z]JK0p3t\">?CI#L\"(b?W6_3uXV;n\"T!\\3\n #>S1o)0:dn<\"'bIcM'/G$Tm.o&2(,V;C\"[4>4h4=7I'`AMBp]OP$UHn-I8>=-NV2:CHr]3`\n /!@6ERY_]%Z#$o9N2A]%.,4[WkYMq17BC.!Q#2R;nW)f7sSff&/84gT,kb4r[1F?So(4p,s\n TgYk)4il\"H0\\#`%_@sk1aI_Kg2^6D5DUOk\\*9IL#/`7`5GgP2sHn&5Zj72tbVWSTiq(I^XJ\n 3:$5sqt;Hp*CYhK^Q_nVnsDkX+LtGK^YE-Ee!Ro:!'hN43P1fsHj7B>A4A[m7Pn^H9P0:N#\n sb;#.eBN&oP6q/CduWc7b]d'BP%J^'a=LL5s%9HA9/<`(V;48X;#h%\"<&gB)RN`g/6bY2as\n Y$\\HonDP41`Y;m!h>@^,5-%_Fq\\]<.d%H3PojT6?u'fMcN0G.Q+#Y/^,e(\\QD2ZN$OoH8DG\n pX\"4+k0A&CCU4Y/H,1cE6[HUF$_6]$?2UmDp74?]4&-6tarX?Ob<E^U>,6j%PL.s3N36bWr\n g8fU=0Z?/K^U`1jU\\(c>LX6@L.lH5&Z\\2/fVj+TnuL+$k8^@\\P+UPhPko#4;-0n`TN/6Bf3\n ONU:[b?S5cXBZgj?,+1V3Gc8^4C>XX@)/:@WpF37FMC:M^W(Z;9FSd3\"\"Zp#^!'(C7]^K$C\n r]4sa@qQ7%iAUX#^69B=%=45+a^Ia40cVDFZV]'4&jW?PT-\\tHTR,*a4)0T@OoL[+@6`8a;\n !>AFFl@YKMBQJaB[RgFGD_Wg.7.A_Rml[ZcT?I/[a@eaP'<G%-JncO3W]GcC8@QAEufKBI.\n HEa^je\\HoeGVR*Q1'Y@DLs.Up*0S/D0q6khmS,XOmeTZS55at%e\\9*Q>OV9d8ob&cf>SGtd\n [WmD0T`:X0P'Wt7oM+&qP9+;(RjAn\"\"ZbLQ#`K[c'C\\^2iqFccQbH,$blCQ2CC!4sR^b!@H\n *5bW2'N$Fs;*>YQPf-E6&<%UK9V!)!XW(-N*'h;WLOa^PH-o=7Y0?8V9a)^l\"EqC>GJTfua\n .1YqeCRTGerk^=42`8^r#ne9,;f8F_G&cV3Bg1(L/%<u6BpER*8sX;a2k;c8BTl-lcdH20[\n knRcBL'*'Ji<,49d(t2LOo@m$5lg3_pHX]qh,bjRcD6ohT-f8_K`Xr1>oaTY;=`6rO+^UZB\n b.UefL;7%8\\PjJYlPWC58;5.q$?`3.WR\"?;pTeQ[sN<EDg4o?/[c:lJK!;isn]lVPN):t/c\n >lC?5kp+gJ%bYe2Zm1r_c'\\5\\gem2ifCS0\"&@F9T*;4S]XX_UtNCf\\[k#FKoEi%\"tmC/P/;\n dN$S'9G^D<,L%ecdTh&qCjM6r-qDHOd[RknPq,B6JBb]'6<Z@t\"b/X'0uAm*;_uHbSM\\VTK\n HsPU8AsW=I#bWM3`Dk:8I[f(/Npd95>L<)]mW/l*C7f34uW(%:Intk>t-b8pJc80<0=$'PB\n k)NjN9&J2q:VjNDD`l:g)%?5/aL%/5K8?TI>3l34/t@J`+n%o[TbE:o1$h`3n.F>g&D35Lg\n 64naoZ^@Tpjj<]+FAm:KPpB3P8=>6rVWKrnArC0&lm>@\"[AD7:#UIh$ur#!d,t%<5)7]LPu\n 84#M-#>^0KL_cL:nf5nK(NPe'DH99Aua9=-MCa7BaaAVAX=8ahiKn.slJlj$M8=_V#SV=r:\n L9<+`c?4rV\"R8pulU`OJ=M*))?&YV^5WsN]?($XS$ZK5goN='-4nV<@I7UR7QW1)ShAUH<S\n GV!?#2-S7=k-?Y/?;brXPSq9722n.*)d-f=5#'d>!j1];tj;\"$GVR*bC/qbSR1$P?d$Ds><\n VZfmB0Y6Y[<Cb?_+K0PQk>LBhR!`gO9'.mJgPlC^$JLLL:B%*P9oJYu`auf0gHR9=8\";`EX\n T9=-a1ES]&sQHSjQ+68a0^/]h)\\KjbG5c2BD&b_XOrK?c@i>l?S0IMX93dE[ARfTjq<V:<1\n 1el1\\^@G>MPN:5T!O/<B@:G(?hrC,Pt6/CrT</$WID+[Tpi_QXG=enVQD<2`@k$DW^\\4rT%\n Q([!'&mhl&?Ht<!(%*,2=#$iH7?+2o?)TLV?;$RU3IMFq?2W90`R-\".hkg3[mQP.[4j5nEj\n 1Y/Eh>Q796tB%]A6`mS^ikL3'cQG`?pkaah?@:tdG+p2a..E@`HTR,GZ'P/dZf1)NQ'/6%G\n Z>_i:VOsoRu#%au*34aF,kH[M2h\"aPg,Vc;#/2$X_AI0jQ9kfUS)_]@0O!PZZLJ:@4'/[?\"\n c\"4\\mq%_tB1%7O2,0G$/-g=af5XZfOuq7p\\T\\eF%?)^+@49S`8@Rip2?Yrc_@QY[]9P<K8l\n 7(,XnHVH(>\">(,u%KjNXp3Qn)(>/im%ebA,75A3MOBMO:q=Ogcu4A8L;jCX9_Y)?u*2@#%c\n LY+'[LhYqA9'H\\sA@0_<mS)P[[UeIKAGmle'uS:F;W,Pngg)I*V@KA-&'-Y2i=\\62,!F`1`\n T=ai=A4V2@pJ-e?X\\l<iLZo0()kK#eR?I.iRVT!jk+0_+6J$S2VoV'5&+4ACLT@&i`gQfh3\n M@W-qZAV?8HtA'7WW'\\7[teVq,uEeojId0P>f6?G0BPSYJh)HI.to7>(AFApr]_Ib!;)Z6\"\n Oqc@T_iK4EJekZ5iBT$(ejb)F>rA1V/&Sr@Lbcts9?+T8g*pdPHiE<%F!_+hT,%L$Pu^J[L\n CADU)0?3s-9QgMpH@(J#USdeqII,'HWATc,Zk2T^T=kq#i;`:=$hP+9K?<Cb#>o$gML8N&k\n @QbcB=LP3]`iF\"TQKlA(@LfO\"(2;bTYMqF'lNs-E_JAHpi*q,%CKC9c7Od1X.d%k_:[W=?T\n )S&UK58&PCXlDE'r#?-\":6Ej^Ku9R-8ic6_mq\\Dg5\\.ak/O#?a6_krCmN:]^<H*H%ri#pm,\n !?#-I6NN'QHn`EEMjf#]YWE%$mdAA>YL;0%a^Sg#U_L;J)5*r__buhHX(#AObTck2B%S<ph\n SBDEN[/``ce/'5hV;DL9N7D:!0k3)4l^Ae[#cIdLm1A)YSuD[\"b](2%P51hMcNmnB5>AWq%\n TQ!O7dlUL^4pA8J-4B128eE6_>%fYdVa424`?BnFX-0f,t^@4n4E*ih0<d_0t2Xls?FIW/D\n >+8]gYOKjN`YO3s(D(QS:iu_7<dm@$L5>@a(3NDQF^J/ZOE3Iu*sFoB&2tM8:6JiDf\\>hY;\n HFmjD][[dQZ`ZaEXaMh*h$Y6gN#H*mNrKc?Y=CsjL&meXfj0g*aNZ=.sB2So$4('#B+M&;H\n U*$Ak-l_/ukbV+)`36C>Uo;7?TgbZ#<q)<.;.EQF$%CE:^AXCLVMZh#6CeVfW/.S0%`D?U?\n s>6gMu\"oL)VnoW[srinjD7FF0.nA!1>KPi\"BL>,P);2bn>T;=tGqGor/o.KaZ<O$K]QF`3R\n kDjPT?&;Ta8L%oMY<n>kU>H@34?uI%?%pnL,:jNWomF34UV((?F0PR]Jj^09VAt<sTW$B<S\n ;_MjLkA%E..V7LS:0/u]:?pX^leOIsHPpdH(GP:CB_*S?G>C$h?'\"_pAFjBfpQ\"rgL*ghmQ\n M88u@Z=%L^:*e-kMj5UHlELd'C>KXG5+j#CZi]D`kV.HH9Y+0FDcJB0*lg3b]ptin?5L(mu\n Hnd13DuKGpe^P0@G8.d.p2Y7\\gE;J(K*ufPL=_L<+LF-t.8\"cg?.%kqmSVhV)@lg\\(lGdZ7\n jSmpg57V+;\\>DB>=4&#e9]WV2W][>1gEc-FsBkfD@mfQXOXQZ$p5Z=13rDWc%TVfPtd[SI+\n us&riXLUh>)2g:=p6oHDb(VN!rqWhM'GOI\\9f>.^mGs9=\\W$%18/05N4L-d'1\\9p/s+Ag#9\n Yt2660c1J#=]*iLH9id<7taJ]<1[#:PtP\\Oq-:pF16`(,ZZ]=%F#]^cKShZmre!J0;.u2?*\n @?b<TF\"SV\\og?3;6!U[ibH/<QWUB@X+Fn51;RG(f^.0n6SM;E[G%aKqfThRVIj*$[nF-knT\n 5K&0?hW-!rmhcZZ*Es1Gr9J(c;Yn%!Fu[Oih5*fdt-E1RH@!EURtaNW+DBB_8l12Q'EQe*D\n -[m:O+EZ.a\"PgHE:&EP(%FG<>cd\"+A#FE;83@7i.B0j`>^;ra/0ddc8!#@I3]+[Fst\\45He\n Q7(!!bH$nIu8#Oo'p3V5Es+eYVoD3lahg`]0p&\"`<J'\\#n!5MDN#m.oh4:q_/VRbE,Kr?[.\n 7[MJ\\-OE,$]IaPYn;K7p_m'&!&Au:$*+-XH1eSM$;+t)!J<;Bi(If\",AK$)PHsI^]n]Z8!a\n 3h[08!jntLET3O4H1Ka`.<Icag,HJ.*<0mT.7u][&=)KP0nh59@DV2?i^CeK/(TV,gA0j'3\n Tnib`d/'2pP?\\kQI&ID!sG]'AW7D!E6Z1@*g_N!CG.3\\/%Z'<)\"/t;3ZJL8C=f8+\\GTs@45\n P_'\\,!6e(!b?#1PLJKi(gW,u%@%L)i]`<HW.e=4L\\u.Ugnn[;0!u<R#7`f<tF0?W]2iKEm[\n k%?G\"%(1!2:!X,cbBA,7tV/\"_M\\VLNSp<C'`>F,6$DZWtq`aW2^4iqg$`5U>OJlcO@G?o`e\n 0Oin*[Hi1s=3^MLJqVDIJ7&']$%_$e((l/W3#F/r@AYY!LuI!SM@1(e2D'ksps(mZj4MpKN\n oW1p/kq_d/l.[B).$=,!uZ8i@qGJ%A!qrpiK'Jk3Q?35kF)<nT]b#EE\"*JX5)l@OqG*HTl,\n G\\AUZsmpV5igL^7o.R3nZTsCV&Jd%MRS,a0BHM50^D9],oO6D7b8M\\F%66kIQ;XVXM-8)km\n IGn%8E$^i.:4-,QB=3[)G8.,$>oUKhh1ORcY;,+8#DLG#$:8Q'l+F33+\"V=[AM7](:M>,nQ\n E>tUipX5/*5XfX*7akEh3DfE41/!BV<pWM0;_>$\\?Lr(kt6PRO%Y1p_Qq9Jk&d5hc0WTj9)\n Vm5Oa5/4Mnqk!hsnGD)Z_=@H[]<(@E^L*E&q<nF)\"b'gNl2(D:^[_7%?f1\\Ys3LZE+2R)'L\n YuDQ_c7*g=;:m7&g0Qg2@(K`>)L]q'h%9*$mS:uNKJfRK?3`sU[`er&hG>^M%M8TPc5\"Q`%\n =UGI4hB6@$_O)B84d`1FEHMSDi1E:$Ld_-cgn3PVRngnJslo=HoVU>*b#f<DTU8V%cn_W`8\n Lp.k7B$(=e@K<bh/07MU+aQ6^$DELgR?R+/Ge>0^=[=_YnkUpsIlF^,O3EA\"*7\\YIU6?4m-\n ]8/:j4,UA\"KllCdNR1UXq>`E2$;2Ij>,fA:LQ\"0AfOi`nEb8F!EPEKpRaqeb@`\\TuHblUhN\n 8Q=!(CJ'l?[A:2jAC[NG=DFsa>W)f%g06,AD%cZS2Wj*T>C1^8;]WN\\.?rb&@tSbr+i@\"LU\n uNGBeK]a4aj#SjjsK,XS$$:i\\^s,,V\\>nscB<91Egg\"!>jQTn_:LadipA+gZZf@'\\@]5$52\n GIHGg@,`chEN1b\\QQnoH&W&EUFj`'Bab-5)2uOb=(QJ'V\\Q-N)=mY7B#;Y*^RjWd\"gFDBcH\n P(E!DP)RT2uEAM'b.^6hh;AH.>8dN\"o71-ic6!oSJiJ^jW.5tZh6d;0c#ctX\"V)O1RO)G,V\n 43YS<f=&e.$</$/i)8dr3$r[dTLD>+V<Z$4T@NB$98a[g(R#7U^ASm:s\\gFAsW2Lo2FGd)m\n ]L@NE(TZV&N-5+R.s6afX;knTZ*qS?_1s!]A8bW`dQ?,!o,fNZHa;&q5d)+a+=&`@Za)&N8\n BX;4jGg\"!$rTc&R4i=9dhe57[SL*67*R<[ZY%X[ge,2\".U!grC%hC->T%<.ji_#@f+qUaaa\n \\?c<5Z8q$KsF<V(o-BFd[;3lcgBV1bRgFR[8HC9mO'ik1nh+dt2M%$-;;m/Er\\rWq[8Wh`G\n bPo:?W4HTQ$6mdK63T8s3W:auP9N%p/'Ts,M7//:_daRp%9JrS0H4+qRM'>iBp$t3BsL%*Y\n 621r\\(!PB4?E>b2bU0o`T4B7:/AhD!S^DLH#AW\"KplQ1SY\\l5VS:au#K6hLos<(JN:i9!I]\n =WXE7\\t`3pAQPnb5,uKRZWAoQ?\\\\6*)aiDg=Hi,abI+(P`/MSHCPHE&q4>,uCt2g,enp=&i\n kDHCq-YEoFg/F5_H<(mSsDO!N`J3_7u[[`A+##UZ3&;(RlP,gA;+?uMb%\"l,f)&hPI0[Wel\n o+YVV)]f[Q8ll8kWf8/`*>5;QAYiR;&\\h'XsE1*aQtTQ)sD$`7D&rl>)fKFnOdJ]=2Zl9cL\n o+Y6bqaPA=]8Hdf:(2=$cVY`rJmV0f+7o@hgQH!cL&[caafT,75%?h],%W!;?;U3&>I/5(U\n S@G2c8?OpSYjh,f7*8]GrHgb81^>@6(%DZV!i_A-=LH(q:37!7sSe]-;B+<hT5*_1+p-/Wb\n \\/O#a$tIR?:i[=:Jsd:6<195<&`uaIeN5-i*`L4%T.NX&>F9!IAQ\\O'26>?/0lrfDRCV0f;\n YdK+`@To9Z\\2WJfu[:X:6f6KA8';T.Q;#>V4XiE<R>nr6Wn7<f&RU+Zgo20ko3.F['+%K)J\n c]oT%0b2oUs]>^/F658ZCfHWg3;X<a7i[X?5ObesA.\"CO;g1p!qU^c15K4fq#?0B\"oMd&'/\n R(PHjQskh2P2E:\"++kVf\"%g6]]mha^nZ0=.t=QfZuhs&HRAn#^fgPLp[;.NH<<!VXjDGR\"d\n =^:i\\)pY5;sqqltorYNO3USp&$Df<G*@?DQSUd&i0V=abbeb\\01lu8(X22=F,:A!k3j57h;\n IjZ;:)&r2<:Xo^G5\"pX\"Y:+l'X37fF>NRqQ/Fu!5=o#Q)b]!K:mX\"q/Gcf8D!6XlrCu3Gk(\n ?oZ#N,8!fcm$eRTWp'H!m;Y3DQL,rYlfn<d4dc3D&iaN#4,/YlmWq@bq,#QdaO6-e#QmDX(\n :W-6FMp;#0u:C%d^\\8o[U'I\\IDlU/S,2\\QIa@e#gX!K$&nCM'_/;Wn\\Q\"2/Vk8t.11Z#fl&\n SPl+5Qp[b<Auo<14I01,<8`[^FS%*cHp%D^ap>bB4Egqr7d@.k!>QO\\X#*<=LhO,WjpK+F(\n <&('t\\&Gm\"`U)[R^!RU--W^n/HF;#1k&^_[5&L.oc-PD's6%S;*6;Z\\nI1qKcr6NNaYL=1R\n CrnD(jJnmg%%@/M<olrPrf!l#&+53+oZN3,(=$s`%WMJdI2@jjc&`G!:_=O5:B>?o!QtQ_&\n 1$MAmcj3fl7ajU:c0.c$NmL@d8@&Q0#$Yr*sD#P)l=J#n5>F2>o\\r0A.W5;OCmnlDXNU*eI\n M*:n`'k:k1.cS#S-kV%g*++\"UPe;nI)Sk1'7j2#77+N$8%#?X2t^p0+0NPo5M52OM)i64=M\n u$S^0kP%nt`[]%doZ/25ZJOP_<Kg^q9o&J5QnTY(:[#:5K9-.)Z<nlmFRB#?p=$Qoa$mKS)\n jjr+8A'!d!8&q_T1LFA$l*oZf7T[4K`YnM&r'<HZCZD,E[7cZ0l'[2gW0A;*l=T2+X(%:N*\n 1;`19BWR9n/CAM=&U,g'#oE#[Y)j;6EK)SEjT2II!YXq*n0p\"fTc+N?cn;XCM\"L\"p5[CY&\"\n D.H5dCh83_$*Y6\"d:#JZ-^tHBekE;*Kr,scugBAkm+GD1WI$K0**/97[T5E1r5:\\EWmSiT%\n FYcfV1/F0.@8A*:hN#g!IJXE5<ae7%KF\\gF;4mni$/]4X;dJp*YY'i?Ao_EtKeR)PF/3+o2\n _B;'o5B-8VhPPHd0tZTEe5*s4kjOUrTXcl8.+4O_V>'@T*Cej!SD)^3W2!@AY(T.0:p'Cr1\n g'!E\"t[1tI//!3sbn*6s9ABPMX5feF+ch`H[E@is!/TH%Q%YHADM&;E<c>f%#Z'Q>JRf]\\m\n 0<d6#\"htt[3A>PI(m>B7o+OPi],XNu1(haZ;^DVZA@AbmmP3Hd&_Ss;ig)4k1U6=<'1F`3M\n b&hI#rI[11'IuJ=\\4IJ2=RA!0..oaB1e8mo2BQd1p\\Bh/AADFSo]LuF,%HVfh@H6%D[9'JS\n @5%FFBkB%NmbnFQ5G^k<$'8:/pMR!S.^1026MV1I8#K!\"'gap`FS1:t6(R'baGA-l_.)*oM\n >YiLN/na$.qIK(>ljPOti<q#/@3't$7je-/)o#lbKL/9O`S;/\\$#)#uK6<QrcU1>P9]-UQ4\n ?6S.Ul;3`e3S;hRack?9Z<(AVsYsd)<dBlt0FBKS@QI?OV*403FERL&W.n6qI1DFlZe97+`\n 3?F9381(Z\"0)nJK8Moq!2)51%FIP.']h.nO$?W*f;e[D]B/[dp2\\IOPoXMVVI1155gN/2\\<\n 6DuINWh^@).B$C+;%DP!ZW?\"!OV<)'^]@/nR=C*@Ui^`J@f5hfjSA3)dqS-2&Be(7q@oYAB\n \\7,!W3KpNZ6mb86%#e&OC#/0)ZQ#K,$6(PrQm.6YDNdX)I6%Lhf9K;*bppXS#X2<F8&URoV\n )n<g)J,(8F4dO(sjJ=&jNIFaHL,[kI=N=AH1jdg6sJ[kRK=CsL.*N@RHkf!U`Qe.c`KESXg\n dk?CEJ>E8G^f(3-#L:OW]f!WZP<R,P`f5QKW29Dmk0.U@Q(>4u<o6'MB!g-hgHV;Vk3*#uP\n :sgO(#7\\L_%\"M&^[/;]N^3Wg3FOhsb(,'f3:CjSaI9/j\\$:GjW'FGUOG1UYV(NXdjjqtqY*\n [!ueJWXOZ.qWoYB#m%`f97^\"4*d-=<\",Hc0k\"%e`Fs?&(A<`%%)Ze&PlS4'6<9cCOc*sLP=\n $/0C@jH#.hu.2VZR^GlLfp#Q&+b7b:qJ/I`<$iYZ5P*SC;Z:mFA7@QKN-cZQ9VDDX`'1meq\n 'k(N7qF+4Q?j8Xj\\)$#nGN8ep;C<uFW.20$go?PKnT1Ns7/.l\\&8K[p.rG;f-=a:Wsj$J.W\n &+iFds*Ha;DL=g9s(KZA:=s(XR,p3kU(-\"&-fG6ajGBf1*(mBeYQ9A[9+!L=ciGKS.LJlQs\n 58>u\";the%[Y2,\\Mq3B:'F-0bms;6S5q['U'j#a%H[E'QNQU]jEJ8d@VcN:/=#$+k0IM9^i\n E-d]C[STZ9bUXU7=OsV\"W#QUeXqt*qcYo6>**HK<O!S:H%<8MJG9d!p_d=6q/>nf2#&;$3%\n :(dKn@c\\EB#a\\=]0=*Y?ojIQ,cU>B2r<*/RQh&%6.9o<6Cik^_),4Lc8ctpK`Q\"LPK#jLA?\n g`Xo.)oKpWOB*oXaLfU812Vja$SA78:R!R_$<<l`gK551#s(3$6rFQF29H25d4,f=:@fo3=\n 9HMGlfQBR;rk3'1AMDh)e39IErbq@Z:=Hkg!G.?h%6Wc;+)OA9C[`Lrm^S-QWOV8Z\"q%nNp\n 2j([%J/7*!fE[R7l]Se-8+_:L3\"p4LM3F$^E\".\"_>#UZ.e@W1\"R[Hp?(cS<kXWd-jE]?:L(\n e(?*AV>ZMQD2i^(H%O1!\\`JJ'ENLu5ct*4I`,[%$XaAbT`&C]OfFh1WnE6/pJrADp]SF9$Q\n >A\"QU2Vk`WDk5+2RiCg=*0-f<(/b*$OAai.)OcT:<?kAlu6Kfu6m7\\G`qPSEO==2M$g/$S7\n 7ESat*d2mn\"#l&E7@HkPD1<i(hT_.qEeTG[?p<k49q2k\\a<O>'%`E(Qb6$Se\">*-_4QAkA`\n G-_h5gUKJeM\\iU.B/T2L\\\\GA^ZGT?4@4f&n@8U=IJ&e1)7&VCOVVKl1,RVO*.EMi'`Vfha3\n U:mJfCT&]TW,9O-iCFE.FfCds&>1,G)oJ\\f`N))CHU7V16,!a-(V@.a*5OTD>2-bqkJ!GNi\n M$#g_>Fk\\O;n62A`tFb]E>>T_i$I;S<6gTq94P\\du7A+_:;8NW-,?2^O%h@NHj'[et')6Mg\n TjtT9mg.XRhK2[=+Q<Z[*!5*)gZW'7Q4-[!Z2B4&!%#-,tctJ(/1pk$th=?>-r^UU`#-H:%\n )4E?A3$8=E;b\\Nk)C-\\?YMPhV+9>EP113[Yl9Q2@+2S?nN&Irb*?F#F+[\\5k54aq6oI]rhD\n W!71doaj$<qc.gLfj->Cm<JF?]X?>r3U$<R?NP=3FceSQI$=F`[clPGS'EOJgfWCYSe#u;2\n _!g0s>p@Eq\",o7ks#,_)f[\"7.''EI8_X;o5m+7jK+]bo5_tA\"sp91e\"8WS)M`;;VaH4bUQ6\n Q;F&f#\\ND:fkZGpVum([C5+jI!B<_lBU.UJJGr.q)&G*NK^joaZ<G2r0^-hSMhI]PoGd:I&\n XZ(Xgs;?b<)E@O%Hp.D7[#;]'il-iC\"N6PRB_qbk[Y:nFOpgkKY+6c+WI$R!JoZa:*S@h=k\n :r5hlLu\"5oaYi8+rmnr=fbl51\\S8=^CkS-RH3$YMNrMjjTig_bbd/]&G7BY5[J4=Z0C5I#n\n i_`6W)CA65fl.##&T?a\"GGLa#SUS*t2`EEeYrF_g&&]P[rf-qrP4&E?>='@_->2=nQH9Hf5\n C\"W?;JQ.?VH:p*,H.i(CV-Tq-+q<7a`MOWOgDc>L*P:ZCZ'I%5gcj'-[)84/f7dCa)1`P6!\n 3tGL!Z[lU!ZTOeIIZc3n*ch2hc$<S!Pf*d)=Dd;*J%l9h@]9b(\\++95G<lQJ`$[Na5RkKi_\n `;,RE+==S'kUtdZm5^qZjsm,);aTbSfG,^.Z?[]iJH;Y?N3/HRI>`6fo/hCE6T=4^YOeDmS\n 5#k?M5QSpSHuJ\"f,\\ps<AO>?R^#Qg$LTfT^`Xme,hhA*Ot([ouMkOHnN5<Mc:n$6+bsrN2q\n V2>i&9gK6VnPBGXOGKY*CK\\%m4Vg6K;!!n-2'k+\"$*t*6/I\\CKqn%o'S'gLVQ8/rBW#DGI;\n OI0i:*>+)qiUL$7=t(8I7UqR:oPQl6O@\\G1=U^ln.$I82:ID(/Zs*Vi$D7^$g1rX<:1ocIo\n ^72lTMXiO:]jh.$%>#Xch_cJTi%dglBPP\\?EmY8<pQ%)omX_cYup@Y>;`#\"Bsh.3QJ6PriG\n lD5m[%+XdId>oY?N,;Er6/l^u-nK<W2e*J&Ggd=PQY6#`lmaZ8k%U=##j>UY$HsmW1ObctM\n &3A;6FHVUTAR>2;rg=g6L3!;_,HdquYNDYE\"AM[+[Ghsbl\\4npCca^F[\"I'.*F--PM(H@9+\n d>SYZQY^:fTf6r5Y8[,j6:EPqNkOj,6StBr&(mJHVIXa#KhsKt=rkFCFg\\h&cn.@'W^Mk_1\n \"$nV/#R;!>*#f.!d\"EbQ6,7k\"$lErr2%7BAnLY2<!.73J6npA<9,NdZ<><DlFB]H2,e8aL7\n Zj3V*(KIc,ot%',^CKPdKG:u8+J&S,KV\\tQ3i`Z/=S$/dY+MI8\\h#T@`n8cYq8VSjM*:j1A\n &O>!j]bg@a,QccScW5Yr#rbo8MWg::$bb3R9Lgof*$6fo83m'E&#\":inFN$r?Li&OfR(AKD\n 8DL-6bQdT!%r92d[L2b[/7O>K_\"o`[c\\e9*WA<#FQL6WMZ:ARAM>2-H&Eeth\\I>LpeZ3)<U\n um<N&@2?eU@f=!,jA(`atQXgd'D4V6jer?A;=hsPkAD6b%Z#*^Rjff8[##3!TgfGfJF'U^V\n f5t;b&3s'[2hg@<hKQBnHl4(66=jMJmJ26>3!K'h'Ll+2KAbBO(PQ;-:*54\"(beI:ihfa*M\n rNC)85Ye\"junabq%c>\\A/R9qPN8Dd87gn.DHW<<3JLWLAsoojRcbR&EYB.aAp^05g'3>+B>\n HckU`#UbQ)*Yj=AVp6RYIZ;l?]n>W0BYWG+pBGp:IOWgCCrm)PXG;F,]%>pcaAq<o0,gH^<\n X$mQ7<7]5Kd6pUkF6f)*7$r\"9]l%q.341'.7o(U7tl-Qg>.#;J1q0&3ohb]>nu2pQKWpHR#\n H4VpW:FK7uVE#lali5,)f1BtiS%!Q1\"ZCS<TgTrH;7*kV@j#l#i/XM4Epq@Ddh)>72FQ0f:\n GFRa*mWYPj]'cJtl[&QZ_!a@Vj1tD:042Zlr3(22qY`WGklJRAGM</6s-+8o_/PJ($@`Vg3\n W;Cml5`9kN>\"Q*#`2E)/:e?Q'r.\"1\"(5Rq88/D;,SZQ-+KA%cct+Dt7&'upi_W<fKePh=aU\n (knCJ?7d'LIKI$WFtr:QWOU-rgE[@A8<ME90SWV&lA\\lp\"EG!Dc*@.&k`B7u5<I<lDCS',?\n \\@M@/>l/#?j^ebiKN;.4#eKp`_-9%@+-Kk[[N[i&[$A6lI:F[i4`)cn6X?BN5e0/`sJj0Wr\n 9bXO`Lkk;rio+>IF\"cZ&-Pfb7--'7Jj75BU.bN*c)A^'\\8aYn7d)Cn+;%2)>kk*m`%@oS[%\n ?;S%\\QkT[rST6K^a%E6Pj+ad>!(3D9JMHX85pLr!dcOe-[g+Q4e@h4^raAIaM(hL,pC?,;E\n e[sGfmjL4RM)c;9%&)E6GNaH6`=rbBt607o\\Z/PL2fsKaZ3ujk:S!hH]PDD/]P-\"0U'K04#\n uNkS](8H:?gZ)8bVUZ4TBYj!TLc$O[3Y*coB?8KY8b66RZrpHSe1X4mFHiBX?WEFCk&@VoX\n -j=o!JFJbC3)8Gg`noq`2Hr6i(Jra59qJ+*(2dl7Pf+AsnE1u\\\\6W#\\YVA.aEY!hho;M$:m\n E+%ib`Ur!C-;dhOYKTMc?<B*oW@>.d:ok#'hLi/pOlog,HKh+TMaUp$S6;t-8<7\\\"?>@M\\J\n MK)*8.sS03CUJ;Cd<<2m.)<4Uo%%%8R_Zq!f3r03L5h,\"3Nnnf^6fmaZ16C/ff8e=A,?at9\n P2OPQ8^!=oS^'H-'-.PB-ZdpP*38JeMBcM-EVB]PELCIat%0T)ORH45h9Vn96Y;ZE8(bN*O\n LA@j;`^6q@>iW@a$ilF)GR8\\T^O+>q;UjaHagLUVJj?Z-!qLLtW5)c=u&!H$Jd44rg;%1!Y\n ^1HZ+&q^)+fb?T[M#>e$pUA#Kg3l/:nUXRi%4jkScSmltbGUnCg:JDe!Ino/T\\TbK!`;#2+\n '%YYRCFA@bA=2&omjr^@CL%E_D8P!PR-[lbmPeUs596#%LVAR=>j#UlTBrJqHo]I5[qL+E4\n D*ihs%\\l=iND_6,8#eF6,ujY4$L4E<X&WW2jYZ^5o!Mq^R:SV6MU.W)17PD6KiHXuS!d9!E\n QnjU]&pN,Yq+XUMj_T\"f>tiIllLATq<#WJL\"0[So(e=^7mU:+$\"YqEKX7*jK3BcmUMU)[[$\n I1Q>.[]Z/UWtoZ<l2J\\NOe@*2!T>>Z2(SXoRo;VnDl\"Y=e9e2?Lr&-6O70lS<%R23tZ%)W+\n h9D0`:,m^q**#@M@2J$F/4`n6b&ASdp*Z8QmLg&!^AD*=`'G)k2.Rb2E[J-i86<o;FhKs(r\n )^&uF.mi;)VF`+nG]6AGehAaL\\(%Kp>a40LIjr4;=]DmF9('U>#\"lE^H)1nG=\"i9gEKc5=`\n _e<?liYZ-]@@+0Ppp&5A\\:]b\",KE=E1[)e;UD6!g8W+-l0;X`e):KR>NUaJ2VUXq\"A%[5N1\n &aK%'aCDn9SnnBnlEkX-RNpdSQ0tg;X#&gX^u`o=0fkBXEf:JFXkS%U./Y:foigG0\"IE,AT\n s&8^ThEFkLjYTK'a<e4_N'l)ftptcl*E[faSJJF>SNq<c*b.bobh)k)o-O>JXL61T!8mS@2\n J7T5![T,\"'FTg_Z=!GonKF]W[OihIk&X^G\"btf:MT*J'iQa8a$Jjlk[H.H2>9Yl[<u\\p)_9\n -(85J%LL[A%g[bF6g$uh]-3rIY#D7Cf&VGNi#GF7?k@%/RF1@jg_k0GWiU/`!GhjFZ]R,`<\n ?:+R8/h=p]Vj-bbAH4`62<Hma*5I#?qg$IPk?/=d_7H!3E]m+[I0]]t*fL%r_kaT5V)\"O;.\n f1eJ\"9Z6*\"L@SA3jQ1Te-D7c1qN!11MdE!ZT(4d@k6mTZ`?2EZa;OC[_W<i/7]C*K#]sJ\\Y\n I<j41l=pEJLno]g7js1isWmK$q:>8\\?!71qXmB;oHNT`\\\"HoJV[/-&7,G=%_X[G_HYI*A1,\n 69.)KdL_LsC*PUaPg/&K`jL@@A-fRF.iIQa2U_^%\"T1c*$;1oBbeLWFmr5[B,c!jDM^YRB>\n Ol.ri_i#W![^*A9/)hc-0?p7NN5&1M(CZmaNlTUdI^:T@mEUpimm(VOP\\J+Hrqsc[6Q:01>\n 5=>%I_jS8B(qH_F\\[nHKGoaYhq'nK'3W&`nF.ja%s#Mkm^][iV&fJ9%VT%$e7H5u8>[P(:+\n i%j#]$+WXHjN80YJsMFZ]hYgqm&KJ&&s`N4(JrCWl$oE`kbTa(aKp6CV).8]YTOG7jCMib=\n KJ1*N`hh61c9^6J93p:R[Xs\"L(c.GUtK^/],^^8*#*=oR075I`MqIa:s6I,B3pt0`[Sh#@M\n O=</8PJLrbg;aJ=]NQs^.9GC_JT^!hDIZ[\\n&4NS4c6faEJnC9L&j.9cAa^YVe$pq[=6p?8\n mYj=inZq%jJO2R6E8`LN'Z]dT^9Y\"+s^E]+6o,C++ogKLbb$q!^4B\"J&Sjc=RZ8>ZJgoE[\"\n -d'gq7D,e=#s?!K>bT'65VrX6%'rDBX.h]^3nlHkS7KFBA]APs^s$IJUhRG7C-`PL]52<\"1\n -.nc'ZTKY9Hl[:N5N#-)U)-oXSd.U`-!o;_FJ+QUssV)r#mol3!:?c82PnAoZk\\aK?X8@9a\n oFo1t'&lZ\\Oo\\\"g!VVFP\"cjfZfZ6Y@r6;fR<pq@#!SAN9$\"iS<(Rp4\\6VWc6ENb9]O6\"QUu\n \"[\\;ZeHP7954RQdO::83_9N1D%`m_kmhcJeXg`1Xjrn<!RCWMH?49D;%pVn[na78oesAG=&\n jX2!Fm7?h\"Kq^G/H?-=Ik9/QXRoX(>L[SRYEcm,bk1H.t&B0bL`(4<bf`+r$$^<?H]_*i.a\n 'Z.l_%)J1H/C\\^aAIkm_a0_\"!a%XRBjN:=fG<u.O8!J7O^c6p.e4h5,brltBPoA&h)q!1T8\n ,.1[3'GN_+OUuJdNp*c0Xh6OEsIL;(ZaI@]T>;SOhLtXaZJM-7$U.SjjMW>c>*e_Hpk]5kb\n uFhdj'jt]8o_:SuFj?WC64#r1_=Z:<GEb3Lo_;7.n<B<6o*T:P>fJo-M_WW_^#g\\m2L>1]t\n __W6b+Bchq6F<<1#q#Y%4kbETP1X:.p29SPt@1W9W!oY*uj'@=(r`r/f^eIG(h`R+0Db]ON\n AKH<u`9?adY;/KKfKHgZ90``\"0dEN_4m9eE*@+FpY<Wmo,pd\"s,0LHR\"en&IEF_B9Yg'>]J\n #O\"F-0Q2JDhoPI<c2_4s'B$da.b>Cb;S=U!*1\"^\"k0j/r;\\_!bV!?DZ&5tY'dnK.#qs[O*(\n Xn'-;j:&+URFtQJCDH81)0F\\h\"XLCq+lrN<\")pPjSR*l!)L`U<(sU;\"\\$\"n!'8',e<IGlUq\n #(]\"PFD@<7M1Pj:FuG:XG=>]7!P`*E,eO5?1(`eQl0KD%T(Y'%tf;]Id:!7*Hqg*JEW\\\"qW\n Ef[:3<.@G4^jg1@)6D5Ge@D?H7ALZ!K6KkT2ZXP24,g>gfiaEIlf+pD(]f%h`A]l2>hP>\\+\n 7f..*X4QSsgFMp7t>GULOA=QlA&D*H==0,!F]M$B\\n]E)B=6ggWq]+(k+'9NUe'tAL6i0g\\\n KuK\"Qc`N#YZiSZ=!mf[j7J0,ToEJ99X&'gs:b@aT4:>-#2q]cW=Za#o<S*Rc$<_2\\eKkZ-K\n Yp:m6<UE%7l?fBob1>RSif.Nbe/2-n08(O<!H/N!+i'7Ff8W#Vr!^%hOWl6+Dc[$%nL)Jg?\n n=bp$^cAn>@[a$?/iHW,mL*)4dmI?Y-T('t)dni`g3Y>C-Y1P)!+DkZ;o=f8]d7*:-TlmGJ\n _ocLnuq'n+4V_TG8C?tFlD9nH/@`j.2:^Up.DQ%]klL9cMh@-%5jbZrf#Yunu'e87_3%7oG\n H8^K%]h*bm]<4arWf$s)OiM/Nc$9210\\m<#(6%,0;SXWpH&(PM0<I(.l'[#8X+Po\"&L1=&6\n 0Ob+I$/VO.hR4ojXt/M//621VK7FX_b&-#O0]Np'j!HO>X*TQJ0nm\\a_j0q\"2>:/Pc<l9Fc\n 87f.:&<I10&)8>>GX#X[$oaoGTS6F^>1Y7XYsDen6?[t;iL9P2?qr);E;/(e'.Nc/NtpZ$t\n Rg6gnd;A]g<m%M3L18^d\\rArY!l6dTn173q\\Ta[MMT5e\\LOaje^U+MDenT\\BqqCfo@)hL\"t\n Yd+PkibeTPDtNZu]3G2bqo=oKa)n/qkd=MdHP@^[iM[VFsE/S<RL]T@#`cl7buGm@q;B-qZ\n ^2KS%HXbIC-#C$uMNO*,C.8CoYj/$a&SibBU6=\\RDA*fW8D>n&]5`^ShcFpsQ4J64ZI'JD/\n >UDs>Sk)e_8R,6f&f(dU4ppMmaQV'M@+8@jrf>5,&&m&'guadY*`KBL'B(dUiBsa/A-uU)$\n g!(9@=g1AOtu.->@l&V?)<nHk$H(;%H[k'iW`k$*b6j',MDK1d:Jss+<(Ia?A/qKJ`^ib[V\n Y6CD<f-Cg0eq(W%\\JGI0[K.lR&q'2RDEYBntn=#!d,-BM!pgGTFLX-gj\"TSpT48I,iL8lf/\n B%#/B@\"G3BD8BH@.TV?'Ur![!_^A6t!>QA6S@Le:\\Q74(W/-ArL;9NY$tm,G!HFb\\u^:h:7\n XjX#h!7[)q+-#%4Vh'si3AsldC(XQ`W5k`pr`Z\"*df\\'gC@Er1jopB1Ybj$N`)-,S77\\iO\\\n AMhu82\"#!HL_YUtAHV-\\K0X,PYQ8Lam-<a#C=_h@i1p?DG6RJ2lULI62Y6B+X9RU,LTi$-B\n P;1G4CaEIf+,E*VS\"<04><@Tde8.Iej%c8JSZJ&A0R+K1nS;HTPS'8luiNuJJ7C6p1T\\fCp\n h8n[L)0;c04$0jR1@/rfCt'53Wf>>hU65580:\\PsBNCZS%U3G#qfUeE)^Zcu.T'rnQVI52D\n G:D<f1/rh$gBTlLq-d.X6Ne_kI;j^'!?DJ`S$^_E5n.YNmW=tQN;h^e-h/8jW&o$ZFTk^3U\n HC%\"hPo-Z<b1taOtFTE(GB9)h$Q?r#,5LRQ!>D;rmjga3k%.F8allSF$mXe$f\"1]J+E)m':\n #6qq\"UNBH,gcVFkH3e2[W9h>I@%n-Mhb3J)U[\\PMD''C)0%4f/cYZC9h&<e*o<.J,]P3tjA\n Wee<[MeV]=MZ??oqrk+[ial?+].>G@L\",i5:\")%V'Op[,lX\\us!S(aA-'29L\"K+PJ0K$s/G\n >EDp89Of53mtX9nPucLU_X$5B$9$E;(&%#I&W3kW]8\"DZFCZ8Imb(G<\"2$4%'SW*fiDGk.k\n p7^qPjoE$#/,cGWen\"RKJ_.<WJYk6IXr7b@r9oSnIpT$:Mp:%7#\"fQRnbmh'7S6gZK<AN*H\n Y*`Z#Y(F#2F`b-/YIbEOi=4p)HD8tCGgq[LXT68H;Ad74/0:Sb=?Z&>Dp(<s#pEoSgWV/iU\n RYWKtGY/.l0S&n4p7H,HB;bTG`s1`i!N:>Li+;X)XSUPNqVuhh=F1*o=9b+8l_B&QL3d':H\n !dG^>D;sgG5l(HI:ridC`e-U*^am:6<D3ZE+afBG=CSAalJK)=;Q_27gmXe%/>knHtS<M7u\n M4#&`k)IP]osk7ho!I;Xn[(bD)DW<nQr7P\\$GUQId*Z=-o87>:c*`I:cjZe_PMjiVD)5E_i\n ;#->)gjGkrduRYV^_-tEEN6j*Kq!sfG6LSk&@j8N(qL?LaNY^$FL=,6R#?RN#U\\*O%6m&t)\n +4g5TcGI\"q![!rY;n&+4-XY'Eo4F;[:F5)Y#Vt]O:q\",2_Cf(:R?A8:N7,V+er\"b+d+FjSm\n lpqd$,m/e9Tb+_52A-Wr6)$(>PZB4I$)SQER+uF:+-/mCM3]]Q9-f]nAJ2O9[T+rG\"_<fD/\n CJAkS2!@PVDR^f4J,G`'KQ+-Kgqd?dqic!17(_6;s@_JSQ1YKX4=6OPiEgq?EVoH<Z<?:c\"\n \"*56V5ilY1md%>](=mh9tZ1]&#(6S#[b1Innn*3!MWf4b^f4Yo(,S2\\$kKjB3?/SkCIP:ZV\n +-N7N25S.@\"#3ZT9\"8Z1$NKB`Y9Y?S*[Cj$a\\Ib//>g'ABDS_!CV^#3i'@MK8$M8nQFq-9L\n >M+#MLF?0:@VbaGCludY<E?@EVb4#+PhDS2m7a(CL4T:scYMJL=H[\\.u.Zp(jqu+8O^Xr.E\n '0abFrrBir*\"3JpVIU8B5qlOa#/MHF,70d\"PUd)-_*Lb,6Vui&%`AqV2AF)L.@Cf:nCUc?)\n ++-97?k\\dCh\\dB$)f>(&\\N0)7oAVu+3/C1I3D,o*/u/a&gW_ea`:(C-cseqRjlJmUnoQa'\"\n kV&99RN2/^)TO_(j.)/AqN,U::DI&RpU\\BbuR&jZ1VMXR/*q'?p,4c]d_o5L:)R\"[UM\"/Ib\n (p'MT<2d?JJg8(&*2,tZOLXY!2p'[8L0e!/8JI@m;iP&LH?R=kX(jonU^<Ae&f<n/<I+CJ5\n MV.Wu`'tn`o=-_$W?.ZkTB42Vm-&l?d(+j,$&ge'UB3DZkV.eS;#SUh(p9h/BgK*MN8Qs^L\n ^Mqtp*R/O(=%1VHh)AosG28fs9mIRWV<rQc(Tm:UhcK4?\"qlY+!J+W<*Y!_Z+DqjHQrmB.L\n 1/_k-t2(:VC.8](qq=%&uH^1O(5^!7?HQ&IS5llGrATcAQ`_!Pi^hPA!uHsW$\"_MRD*a4B3\n FYJT:guY$_ccf/qSj%LjkM?,'muUV]t>^5`Y,uRQ-Z\"$\"gK1CPafaR\\r4G^8(%P-H`-$$1a\n ggD4=k_XDSBrjC9b\\Wlr\"+43G:J/c4u3^+YE%\"MHH^(C\\/7N,oiSnVg[)bAn#p,gWfEX$+W\n `%50T_[#Mg_g2lZ%7+XCMpJ'*.Y$7%=ohITVf=Lp5\\(S>G'>X0^h6Z5!^&@!Shn:]'oATI?\n `!,2:^-iJ3_@U@N#Pl`UV$q[3pT5#'nJ\"ph`?+A?'F86s>X=E\\!IuhU'0k#&I<.@#p\\j!1g\n \\LgjVrddT+2@LGJ!*C3*!&=i'nQjB%`-/_?pk<P:bDr;fGt(PKFrf4:'s9h/Ht(N),N\\VGn\n 5G*/B4Ef<KN4Q.^a[2ec[F'n?*HU`K%6tKJ-Gc9kZmrBakj%3EqU0D_6[^&(`?t>jJsF0*U\n 4DfAoM1E@lZ.`W!^k,Z.t>8Vff9*u3Fl(5kju/[;0=(YKd9A;mZH1=fRN)5As!Z)T]<7XWM\n AKPtKt&YmB;m*aTUGp2QA4uDeceVOZ6O=b?:25q#98W.#>9nGhmGoYM5K4ub\\8[c`1hV?kB\n =d)S>:,dG\\hMY6PDpjKX3&^ot*\".NUEirD%B,)rPBo6ou9ur`H/EIk^STBO^c-+-gkU$D,Q\n nF*@*%+N:SOq%JP:>(Qf4-VmUsO9[e_El#D`-ACflsc>i#_WMJ#<+dS51To][ri;hQ,*lo<\n *4!M;7fdleZuLIX2FP<\\hObOV:NP0FI<p$O2\\n!)N:d^R>HpkVW[>Zn@#.aq[9WKD?FZBEO\n 7`rX[%GWXo9bD@F$48*L1#Uf<A;;Hcddks[%t<3DDn!QI4;WX4?Y_@aZ=D$m8T/6?f4ACJV\n .%G%XHL9U6C6b%=OW^K./Yo]akfTd+bKhn^Ajseh_TYT3E=GkX@/lgQ:`FB?cN,aS.7TdtS\n @ngZsEOh`4.b`/m]QIo+'r=F!nK-`^;30-,6!)_I+tNnICXOf>':BpfX@7n];Hh(3=Z%OBJ\n Q@u?K$%4SpF.Z3UQlI\\c:Z\\#.j]h+Zr5%Mg0&JL/O>ekEq\\'X8V_*D';BU_,2*HnRkjBLe!\n a>*BY-3E24`7PRo=Li+\">*IhG)+^D_^G#CRmO79@]U%B'N/0kreCN,T4(+mL!Bk%##81$%c\n ,R#%8,f\":0DaJm^SAJQs)/E5N'V:hBlm'gu_Xq7da6LYpkZJ$7u69VYiGJFTo`!8u]E_\";X\n R5eR/N&F^O2TR2[WS3KNbp8+-p%Un-UL[bQl`)r'5@Tl5c8+?Nlj%sfJid\"5^XZ4=\"lP`]j\n I>ufP6H<(E*okt2;IU\\5WKA*rj@Z=L@Wk>C'j<(tg::8TKO)_tEj8(bX]]\\`B4]Vs/k46D>\n GI0rNYTSi=+&4ZU[<BP9hI\\&`i!4?5&b;'(.Mq'Bk!luG\\mo$`okMe-6&MAPPPTu\\,.tTXP\n Seuntsadir`t:Kr1/^9ZP>)/M:mHR5J$^f397WD!!pT[ec\"s>MF;\"Xl[<dqPrN>gP%R=6c;\n 4<P3$IHs)[?jdCM8'Fko3/Fm#(,T!rn1h<g&BJP`6^]-h1VXdQKrW1k+*6skR`V7!b7f@sM\n BD?F<;[<DQ+g`);oDBNgF`WkV^4/6q9h:]E[!&t[^a*I,*l+Qi\"p(1^BBb+Y54%J6$*S^mN\n n1G$`pbrN;]J\"qWc5\"6ALC`BL4,S#!/&_4l)<2]TMt,X]a11:SjBRIqO&=km\\OS+1>d'H6h\n He>#LG=CUb^C#;r%U\\3V,[*8SFbNKc_6=]kZn=!A%6APETKX0d/'SL--;91L-o2`+0&kOT9\n D=S:s&BGY#Xhd=4l>=lrd[IG$MX_ZLhnU*NlnR52BJ44a$0mh_b(0s-nASI;8Su^/uHRSZE\n t[cX%,EaZCN8MJ\\L%r[b28594<_IYdPqF%'6f)l%M7UXE==9A5pk0>.Oke\"2Ur)k1WA-;D#\n \"R\\SGKF1&$]J`PA5(K\\6I@lSV?\\[e0lhJ9[P4(j>b\\sj&nlog?up+OP?Rm1P5h4+$0?n9o;\n 8pbtNXn@.Y.hr`PmJX6!p\\spD\"bNC[IQu$O5<%j*+-77qOe)B!J+!:X^`!QrTIRtFlfMRCr\n dWi's6p$h0EhGq#lq%fK7WM\"JSZ7?%-NY#!UOS'$ukEd?Kf[nktj(uNh$8iUr]R'lE$*N/<\n 9$IR]?jil_piLn5RQ7=H%(%XO(AB0$p_Z_Zm3Xbc]m,N6^j-d'#(gc-GnKDZ'iWjKNIcn0o\n :FWtPe4%e0u(cjpu!:EIlEW%5%uZU3HpD^a\"i=RtcCQ8$+]9dl<haRdd&[80-<7l8]!f^t#\n Xe1XWXBpfHL<7J*V[ug%.COhl\"B+M1\\GU^H?/S)D3#b7rb&Ef_\\msIH]I_)Y4&aAHR:QX5p\n ]_RV]q9^bi0<Y/63>6>.qlrEa&OQCkf)5&3rD?8fDrgl4Q560o)WBPj:^n1[Bbmsj(@cA\\0\n m+:PGbec0*5UV>O3$MsM#mj4k\\ql'DNO)PQs&o6l\".NK&Z\"[\\3pIl@\";.m'`D$Js8F(9.@;\n o33b/!@_>6Z_(b7J:Pm(U\\=fZ\\6j#7u/%-CG+dkT^Xk*q5!SY_reu!=:HH+7/Y,cOQ,!'d0\n 6;$EkTr0WtiQ[.:7UdF'0/0/F#W.+5.ko<?TLOOXfD9-^3M%PZiO;!TBGo-CR1%rh1f0`:X\n -=SD7fGg1\"N/T241E=m&46SF-*X/u*%GnQ5c-h/u+&qp-:4XcAt'QT<M:VRVWR1ujKrW)'t\n _7\\o]q%p?=.e9hp1:8WQ\\LXtu`2liYiD:HodKK_A(pG5:-#4AQON0)B!mZu^0r!p;VHe,C0\n 'JE::dm$.T*20t0CVgm.'jmg^l)(4b-55--;,@5A7j6B1%96)mb]'Xm2iK]*tWuF1Gl<*qT\n b-.+:snfOp'+Z%14OC$?K&f.k_8>%h!G`E3R!?Z6]o7.h&^8%.Z\"g&Ce+.3B+!I,SEB8CMt\n KE>1GB)p*7`ko9CVa!>'*WpJD:lEbc6V'diGg-Sr\"TYonDAIj`L'-usq8nN//J`tOW!r%aH\n bYtl(,A/.D%'Z%-s;SPD:kruH@54e;/1\\Et@rZ<<Y+2KKH!QY@P8M(VbVfLMnP2.\"]hHI1V\n 61X=[Eq'7ZY:l+l04k#\"P5uWo\"WS0]b#8fjOj>$=(p-Zi*O'Lc1FYb1m*0G9mnrTsF#NLWp\n lTV^7d2-SCE#+6'd49=PO]Kq1)ibnm333R2K6V+E6BI>F#S'ddrIS\\dsgr]W4((;3)Jufo8\n :#`OO]P]-#88^d0D]CF#n5d3n2P)&KOSaM+sd=40^..'>mR`SNO394L<@0+e(VjbR!Dt)M-\n T`Zh[F?#uJ#=;\"YDt2&(ZuW\";7T)rMuOZk\"`f'.o)k6*qK-EofV#ku4r:6?0>!&4&Z]rBmq\n R*&@sBCon\\`'cbBD*E*nFm);CL,r2i11=>>B.euP6G`_MY7aj^]&cY@!#;jn&8+T^N1Ku`\"\n *CuB&$alXmd)/EgCEf\"1o@0<&<23Z75>&%D9+,f6;i&rq]+:.@>k2)Fp!l)X$V\\a93jmm31\n 3GZ8h)eTp?M*Ipo>OJtq'bg!4VF\"p!8\\QD]H0g`;0EO[2AKYD).Bro;*iVOU%/Z/HlG<f&n\n -DjCi*(W'.t\"U61m0'2*Dk^4&e+3M3UVhF?*oT;e<@<6r(j(dh>-SeQ,L^<g+b/d!%pWqc?\n a,+'*qK<IY;ErC7TUZ#ts]OJ,eJ;cs1L82Zf<e;6`HUIb\\*>-BqF26faD2+eO1>D[tl$Yru\n P<Es[c37:_c'Z\"&_NEpUt-<//8QK;F0d9^aH4*L.#npOk$_bS\\&'6NnT&%i*T<Z0jq)isZ#\n pD%[l)0*,+EVCU<!P&t\"'H4rI@oO%+=#C&e0`q#,A2QF4eN[TO04aF90GR/jPtsd6WFclJ6\n uZXJN4iiMDcX5F#Bk;m$MA&SrFe'7YSMt0Fb=AIcWH#W=Npq^\\!8+:QI-JE2:e`b<Mt.aD0\n i0uCK-^+-SoQ4\\Fe3:HfKHhM3Vo,[e96Q,o5)mNF?\\O\"\\ank?.S0cc[ef+Vd?adDcG`l2Ye\n bErI;(:?h$GiiH-!s^4Wm>JG9_-3#.!h)1eVF)55J\"9ACFE0SS(<F&kE%<^@W83HR/N6A=H\n A\\4(N49,k*2)td&3G?jKW>D9Ot#+'#j[W<K+E0\"%F=#2Q!2h-U)CM8[qG^+bD(QCq.Q[(HP\n M!HF'#tnF)/Qse^HBKXI9da-307-J^Ha^^J[`$ZpYD];[I$_r[Z;kb/aS+6=9QoBCp>jg`l\n #)gRHPc&]p[KXF_2bqtDtrj1!*oK=,T8tl5Ou^Cf`dI_$';\\,OSBG)_8IA0JN_O2;U?eD0p\n dN30k=?SKC\"SNG>0a!;hXs/@JEcD[U5825D?2HL$Z@)1#7S*-\\endLA,nI1grk!BI3D*=;H\n sR,*.Olfgh-tC\"J\\/Ga+FoT(9@bEB'XMR&$%XW:T_pRJ=%U,?]qC;g_ZiD!tMc97qXq\\9HH\n @pDD>KGMs,mjZ</#?C(*U\\E<U3m;KE0J&.Q[!GEC&SfM8(OW!\\]3VB\"iq4G\"Y(BM5jTQJjb\n d?4upP#7X1Ng#XKPB:mqPBf#)G>Y)JUNK8&PVW\\82Ii!'@oa:<1)*T/fir)hD3bBsGDtF'g\n /SE(DeQ\\(V;dE\"Nt[>Q(RQ&$PVnkSdpHj2A!mibVtRAeGHj`J\\MobLM_[M$e>o%Y?(2\\II.\n l\"^=Nc+Q^=ISIDD]\\0Pg[-AZ[TI6Ie17&2tpZ^iB1NC<+4u4EiYhdfr_jAXnq\"Z/laGGAfI\n Gr#(];_Q8`l00;/YkF8.bhMNsm_XeHP!AJuu=ROlT?=edrXUN^,e)Ej?H5ur;#B/EZWQZZr\n OAYhD&V0Qp5[tU/18XFCg=LijW\\V%;,$[K+5Ve61#p8aT<PBtoMW+g7/e[:iG\\!i/5WL(Z)\n gOqX+[AmBAWbK/*kCn?;`Jnr:NOlZjp?t(GeZ:XuS[\\DCTR%@3U)/\\oY$8`T42njZah4Q\"/\n 0S.[+CI=q>G08uYLFSs)(U?j7t_[MYl!qnHP<-C(Bk^30\\[[()^:7\\-WW;ZB)=3@RkpkP2B\n o_0LKd'],$UnU7sLDRVG[_tM)2$W&X[>kR'=!,<McVgUUJm12]Hh:\\?Dk.Gn'Y!9%$3hH\\\\\n TsUW0(DI6;I4S!C#(fUSALH+Tbf]\"7Z=j1;_kDgSajO0/u/N#Ua2*s),Kgni/@WQMlUb2i]\n D!WEeLXrSWc2fdN%q'0sg0qh9hYXjPRO?]I$nuA2R<4i#]G$O@e1p!2PUU(oTcu$SlEPYd_\n Bf\\qkHTI79-&7k9LV,4GZUM7pQ$F$;_j?_-d'L.uNMj\"q`0ln/fVc1qX2S:e`LT;Q>*Y#9@\n h,#CN&mZ%HukdGX,S*FGs$Q->.3%MhKrLcX;m;&>a!cjJ//0](W\"2Rr3=n&M:fM$f_XT,!W\n 3WtX;q:E34n!fPr!L63HQ*\"P5FX?r7S=-4/08MKc:uH)+eEY3O2o]*B@)ZHkW<'(9\\EX7GJ\n u/]0G/\"..CDKd6'/2e9eTlD:2]=`'#\\u>qre!K6mGlEudEBg6'lI?[OiGomKW*)iKZ%O5dL\n 8e[q6igRWdVB7>8E\\t*i3FQL+XS#kSa*`N$j*`_<N=lmA'JK2$3+gN+2Aj4u*^)@[!=r4oD\n Z->grYh)V([T2)O;qsB%cELU\"m'kdI.F3I6h-!kJ*S[o+hm8_`1Hc1:?0e?C'j+c5VLA+E>\n &WbQKsf]#ht2ib,5Z-21Z5TXRA3(,.=&nH):Wr4iVS7rrq1ZoD-YpL\\J(Nmr\\N+H2lg29j4\n oB8h/<#E7:/<;(.\"f7U!=]C?h1r`o)CH92%(rY@rVKh]@ALr&Y8)icf^`9P8r3!^JsLrhro\n 2Wg`5L^h8cf:AX**#L)^\\_r;(*`V['r:LE<Y9*TqYG\\'[*nh`FcoI`]!grJ@/;m9MC4SMb1\n H%[UM`%=LUQSf8qXXl;P;id>\\6&m*VqQ`C&lX#ts'XaBS!^#U7Q]$I;d@@/$#l;Si_rr;Ng\n 5P>%rH(Y2l+9V:03\"D$X6\"'1i6:HM7L;P1^(kbX*_$%Y\"nS#jY2'%X-;Gh-:JjguK8`V\"n9\n W`psQHLT&i*&j/1RcQ8e!\\/BD`sXeVgu^\\$ACmAd:j;@;[==0VUI!E)MLqY9juSQ#thmGZG\n QnnCXrjkL<3r3=98,R;\\%8m[G+\"3CLtZKF1Y^r(Ee<4M0lto0A%6Jn043.@;u!X7P>L9@K`\n pg%\":\\qPKO)m)#VZh24`$*!bmBALI\\)eC%U,F-rDe$f'>3J*JVmI[FoE*N)6[dGIlXLpY6=\n cBoU$inMo<q7k]qJj`@t`FP@b2eEQXQ*IaAc\\(tP<48nUJAN7a$H+^k@=/Xa8pNlf;d*d&t\n oD8DLhk.s92uN[mn*C&S^b=r7!l3m`%0XKY;328$cu^E9_D%c5$%oI80P!OIj>.<6AGe_*\"\n 0i8+&]Cp[4AVA\"<*9sTZ%QI!KB3,t)Fi,UD]M>&jDc83EVsP_'IHM/,05p(P9`_384$.@;K\n ST[atfcj-\\Oo#Pq5R+bdT5uZNRfn9Cj./&^8]iPr$Z`9\\2.TKc-4::/d,74&3-#krhf5gu8\n s2L0XaDckI3&6;R\\?&OdRZ9c6CI[\"1h]\"Or\\c8^aub/nP7YPrVRf[08cl\"U-WK;H20u:K:C\n P-rX0sk%.h#eeOHb;]2ucEEh$=O`\"s&k?7\"ufQJR!@p&FnP@[m?AXd=8p4]8U>'?aCCKgGN\n ZY`oijh#G8pBAHS>^%L;F'SH.drer?A_VE7pP%XQ??`73HX?GdJoR@@8R,r&#XTeoi)h0_O\n 5SYW4H\\T:2AhZ)pjutB@V,ssM^On'JW4.h8r\\mA\\E^)nA4iSjXlSd8;QVM9.`I`*Mh9iS/_\n Qlh]<7R=m(k@Nk'*B$N)#\"u0asA*b37'],0f@gp6a2a9g_RQ1l]e\\ghQ5jZJ;q#j+4AC/aK\n %63L^t]ZT-7RXgN\"-9>S)\">Chb.DJsFVq!RU'o_\\*(e*R3%HisTR6*Ou0\"N&NP'+48+]KZn\n DHuq.Y7/WiT(rb:N0?_EVjEo1n4To[L8Gso+,>,8.;q,q'-X/:tdk>2_c-pTH2AoHVF$01q\n ms@5pe/s>$:fN,jj&+<;1J<\"B<AREroad`neWiY*<Vj,2BC1%'[<-#8`F5E;)^eMXIim:_e\n +J-=BA<0/s+fY1IXe9]qgSRcoDO/gkPP92@?NXkLfP:$:mWk:#\"9@B#:%G>\"u,fp_jFpH@O\n tCa0pjZ7+O_9^Ck/@uk\">t_,U4h$Q'=UEXNMbc04g*]R^4tYc(U=]0!+iaZe00Bb]GmZ/Ku\n 8nG*LHb&YEcs7O'bm7+IaT=G]m4Y=/*\"E#U?,Clq`(SJ/Bailc1V/\\LSlo>]Tr'6oIQf^lT\n $p>7)fIrJ8j2]q2gK&`)8EH0OI+\\*Uq>`4\\aY\"]R\"oMUX<b^snRH:'_2%d27BVFcq*-Db?T\n ,TUBuP)d[W]*-4B*P@i):@_1B\\NoVIbJR0F$<\"N<OX_YUbu7Cm9g'q5oMl:NQB+mA]u=Zd!\n E,a(_\\d<PU$Ot8r54nc(1U$`OYUNJbF+PPB2&,p1hMus)^Dk=L9Z%_J:UmT&0_@pkT'enCu\n \\sn;KFQ`1C#:,kpPtPG8.PY#alY\\SrfM,_R<Z49,o[@\"hkmNp280L]JbNS$6@K>%+8fg5DX\n /;LC?_6eD`hnM:!r6;,^lSkgWFdO^=)Gf$P8t'O$G-Fh#G)b=Z7hGE!37QU^c(i*8*\\VK(I\n ^36:h8UZ*8SeFl(bLG^5)'Sr]N.R^&b*E#dFX--I@92t^A-.<9mG1BIF8f9iAWmYsQP+&RH\n ViOq$9WaSC\\lbs^cRiJ1[[/Xa=9QHT2$QnA*`GhG=*jCCCXmd8Q1hsoqZ1)@'n]aYTR)Z\\r\n @`]CXdc+aDnt*M8*:QuS9(8/flCX.k@L*gN,!RAq;FI!Pk(EiWd@O\";*SK;X\"G(f):0i@5o\n KV,LQ)oh:qLWX-u;5E2YJE7bCN+M%2k$;DCCHI5o$OqAo3cmk0dJ-(S_EiV&*$p;VSHMY15\n 8(Oj+)/GjS6Th)VAiqER&5K-9V\\/Z@28UXVo#l\"XL!WKK`L<@dN:lF$L^2.lkgMud\"[lbKT\n ('gu)-&M)t.BYehl#?K2`.Y_o5)T/4rO4Vcf0\\.2\\R!0'Lr'?-Y(*gbbQ1tk5nim8EcQ%J&\n :CNZ)3%TslZ?XsC_/+)//DTQtXE\"j3q`r3\"N^KC]Q?pE8=d!FJWh57$f4=beCoA5)[[C/;g\n RPNdmFGJt2Yr8-98AmP'3ViuPh+X&d;ku#,e<)=ku);jF`WftD_\\-UdegLI.@tm*pPSH\"gW\n ,t$e`Y;DqXiunB7')bMid\\Q7pfOEQ1)[h^FmD&8[QrrlJ;PcQk!$P9#ITC*3ReP3sF2ZV1\\\n )9bQU>'Ad>T&3$ndF`7igICOL3*Fk41VReL0)p!nc:n>7,aU`1h/(Q>GDP+7olP$)Xp9/5;\n Pa/'\"`=n7K5/KL_COIF\\[]31=Fo`;Jif.#GpcY[^1%,HmaLZQE8Qa69$bZiHHk%g\"0F&a=>\n FE]Xum,=Gnrc>[+(HU\"2n\"-l0E6jZq5Nh@STU^/eieWL\\?G.#!\\CQU/g,_^!9d>(LNg/Un:\n .jbsXerX0!Ro[.;sGnAJor[Sk*;gPC9Y?(#0>AagB4'hrdiFB(IRDW(Sc(rfIr!kmg?95\"d\n 2$63-K4=S@I`qZ!FDk3n3QNrHBDg/[WU)2e1V>IjXl;a15jf;V_cQF\\nQEDEF%Nh>Po\\;*F\n *UHe)]a)ridDcN1fPA6Ihs'^>*_&Y0FbGGVr%R,-%,9mDBNia,ZW;uI)#.N]J?ROc^([\"ZQ\n hQ_WV(LQ^n.9r:'SQfWO3f5fTWJYc(Lk#/NbC3:fp_D&;7@dSU9O+HeL(W6$?(ZTmmO^JC_\n n/gQ@@1C\")-,qR\\l;gjLF`4P93o=)oR0RP3*OjZV5NA@2/$eRp_mqOT2XQ_B\\+]dTh#\"PLC\n &*7kjur+F]BpTq^\\>MRHbh=]__-c64A1;Z]/r8NKK*2VS,2QgH\\]8/6+Dir]Z\\O3ih<mC%6\n XNK4X0_fqp[n>e%%d!4_tcX$eR<5QoTfQX!7d.Ws+'Q<JG`o#.Sa[dgSE6*C8I%60o[Zr#e\n <7+Vo\\E#N/8[LiS&d-bc@U2KB,<b0*!8.3Rr[/GlZd&?%Z0DRT_S5=;cl>ICq%p9LI'2d7i\n JMu#NAGrrn#^VdaZ;uO2K1V`Or\\+>,4*!/LMl+f,>&!R5W9EmIU#J?8C0*DToZ\\lQ(5e+a%\n 5hjXFe./#gd].B;`2hD(,Lo(Af/2h/3HD=>>M6D((6l/[L0tc#3+dgTAVUh@#Jbc)**>Xg=\n [eia7BB]^]\"Tl>>_`<&JoFfrQj#[T-S`3V50PIigT<[:mm=rC_TXThlgqRfZp.3k5>ruJ'6\n LOdpd7*t^RR/KA,AW/r53f]6]0nkX?%Q4!5lGM\\.h-B3gI?g\"[$lm4GrS`lp@li6aRh$Zno\n tIq926KJLX%75jV(GZqE[uPH(^=*P>*7e.fk!:q_u^_/l$`+\\=!4AqRU'LA5coTR=_sO\\$O\n U8M$&s4HrE/Ei,d^\",L=hgZZAA@D9B`af5`_jIA\\-AJkng8aJ#n,\\Wlf0-Q!&7^OnK/,-q;\n \\]3qe7f75JHu[&F^+Lt:/jsfrqu9/iP\"0:I7soO$PQej=5f^N'a2A8%1^YldbX_:p02-r8H\n -aEdq7.1N3?-Jh91qfkPdKMc7+tMVl^#Veg.8R)'Tb6X(iG)lG_`qs9PhaCI)o!?a\\83G#F\n KoEi(o*#F+M\\;#&K_ZUT:u=A'Gs.7U4D#bauQXT<13H9kfte)V.M2p-us.MtEgD9Jf+!D_:\n $h5J3r>r2RYnF@sE29%#=ZdZ_=CGW6tQ)q90n>dCk\\aid&p5brk47\"@pOcc^^Ga=Qd*I(E)\n ^]M#j67)D^Bm\"`DF^e\\3l`<;*`O>@(8D2,*_bbY,3]_kRLrD25J//Vt(5^<H!SH,%f9`-:n\n bgJsJ+&+g>7Va2B>16(O,t=CX`jBL'3n_D&%6KO(N4duUKJg(5i(B4n:(.%r,iQNA41l911\n Q:EfnhJF)29Qr[9-]274FKjq5u,#_^r/^fh&nA(n#q\\&Un!-:3SDU*L<iQ.'@_iON;\"$38H\n RgUL<*t^:jLCS/Q1CW;XH,8r@f<qGXZRDL4F:FO[)VE\"0B0=cqL\"WCt-gZB;_j<9mg\\2AD%\n jF$qAJNW'q3*AIkLdhT#d3e1D>$PcIYLX.([#4<oC!m2+92Gf0JP)r0W\"'^2^tl+EO7b>^o\n *`4!J++O9&\"4WP_>X:S/J,Z7RkYO(m]He6ST-r4YUK&Bo=^gdU1]$h*p<UF-nrErY8@2;CB\n #9\\6mn6?1%#R^`Idp/Bh<1Kj\\2mNkt1+bN2A1gT!$;)TP15.m66u>lpDEjA_c/be$NC-Pcg\n IF+7d7m&i,t=A((8CI=:0^\"V$c^Sg2q5u1dD@rolpOKP:f6i0bCrg#D'?S-,,Bom=D_)3h'\n UQZY#U]]Wt7#in8/AP/63dO=RD/OrK(.jP6Z&RLY,8:5TS)8d&0<GfkPY1S=VqReQ0=r9lb\n V^ghKd1JCaYQ<t,U;qfc*n&6'Y^7jW:6,t\".\"G>qE$f8SbAS&<a@HD<Vqf?CL']R)nt:\"T=\n a,L%9&AV)nd;FGoC5kOQLXbTn^<ngb9eV,>JH;^!cAV4AuL?/19XcZi4]j'=,>OB0d5\\^O3\n H9Q:c!8(!M/X='#2VE5?56Yei/I49-Ro\\%k+cW$O1tp3MgR8;=-s]*INM9KCUK:05%Ma3AA\n JISN!E=G/g7:f4P<<$cm8r6NfC\\?1\":El[buG2pfJVP,'nk=!Kq1rFa@u1k/[o%\\-Vn+a'T\n b?[-uT=BGR(XkhQ?*M^$K(Mm49*%#N1&bBPiN$.#!asJ7tBPIDsck#%(ZVTd@e2`B'pQb)8\n ^3e(!)9Fe9i=cF]pH.\")YqNHEPgdb7^Mc5if^FQ?;AHXL'1h1\\MBXW'nZgDj5K<;#'O%\"Qt\n nhpj<ahAj.3<E3?fLL*uiPQ2LnkWf>KE/+^ELW/Z>IMcLR).B*T+5h33!(M]NE<1VMXNgEF\n 9uadCR8]=?=flM[Q2._.DV<kCgsu>S'W'UXrms%-`td\"U2?C^de6jkQ;-\\9MAU7OG0e$\\6a\n .7W<AdI,?I+mZHdG9@=]^4/a%Gg]_`0F:m7.OafWRuPki?_S,i)YSg9STKeLP$<\"Y!ceq7:\n ]^oA8-/jC:XM[_uU_]?V;F!%+J`*nR$_i?]HD6DC)E5SfuB,ZG%a:\"t@<i.^K;Rh'JkkQ7c\n Y&eRJL\\a*'2[r\\DY,#FktO&2\":LAd[RHY[`R`>9$.CX,pi)Zt%@fi=tn9MZA?j>6_<7LA5r\n #(.Vu^D._XBB'sRQ.J!f6?H$;.\\^1`oDG*<moq;Q_f!ZdOV9,X[S5?;%jVB2p\"[:W<EM<'O\n Xk$L@VCUbG=4B[8]D_oaQ7tQV>Nf@?<3BNV`N81oXeWU<g@er7[ULL73Qlk^:Bf_6/nSVS9\n \\rSZKcjt0?+Pc%NTU5+Bl98OI[FHgHSE/&#>coSTPB\"5\\RG[k](U=&Kpl84,MBe,hkj6-[E\n Q7\"c&?fDg'fgtV9k3&!92\"L\\(4\\i2D7\\ZK]#k^7toS7p+r3[LtD'Oi2*TdSr;\"aN2.5!@+L\n @ro1<HB,Na,M.aT-NQplaKEJGSNl&NMorkN=[_,_S>#M;cUQu`=*=,)eA$IiSH`Al!5TYE+\n QR=9G4k'FoTUsRD`jYj!t9gMiD6>-e+im#qe^!l1.W+tIL:1dbb[YO/hg?UA!CHf+qSd];`\n [`!mX[!lRgArtbJ\\fJ9nPDrcN^fj1f*&,[SmV_3*Ict[.qZg;4K^?qb?s!Vp[apb9br23+(\n <NjOb3,(bl96P2h*,ZB%VOK<l@#An'r'n-q/&$jBIp7Mc.1pYKj\\MICAtHhhUuK;5\\R.=D8\n \"c``nfc@hTMLOmLEjZ?l=b;6K-:09O?t&^C5)-%<1*bLM2$icqi^F-\\[@jelZ@lk&o.-9e@\n ^]R9k.',s0A3o1bhKB?&6`rVg_Yd-(BYDjJi:Xt=S!ib__uisu'/56\"oRfk'TW@pY%0[G:7\n 0gtNSRB]fPi-FdiW&<fX7Kt(n%E,LG:mYC6@F\"]=j5;[FSjQn9l0W6E(OD8LV@I/aahffk)\n *uJh.-#Cluf)G>WB(f'pcs6kN?j>%oV*mE==R*n/lIPnn*nK?n,jP[]E!A/Kf-aG@2X%PEl\n W)e:erA)fNh&AkhBrP<c9MSa8(0/05%c`qIopiS=`p4,67>n>fQDfh?&$-)K]$?0<puG846\n 6&rF4WTg[i4Vq;Xqd#h#AF,AuWq=drH4VDo.Y(>Wq_>YAJ\\*oW?g9%bbkD-u^h7mDcQlcVW\n Z\"/+k3pePB,-&/H!/3o5Bt:]qd2VgN^7I<XRt0`tib.!Pj8@Ku$3Kc\"B6B#sLSGO25:Fu-M\n _W+\"d/I)b#Ab%D`:-YN.6+7r9NoN\\Hf-V*_cY3gCeh2^.[^,5<qEN.dMFS>oYYF&<Ii:>*F\n mO2Xump1WtD[0mBo-]\"_s.FZKTm@WjL9PiVW()MTE<6OdMbcCsG#!%$4D_Isp-,9sQTsj25\n kr(fj^4!/hYM7'O)c=XBLe0<O!Ec,P3mu[nn1Y3Q^.:sJbM<Zn4NHJ*b>\"_4;/;aJu:7)o*\n U7>@/;7fHnWBb5K\"m<l3G[8L<+Ih*F\"(#qGseuph(E>Y+p<MC\\CFWEPJX@G@tZNq\"jofpu:\n ?-ViU^,Vs<0%h1'<A[f>AVg3HaocF56LV^cm`Nba,BJIs8]SnYF%FCDhDr(l@%5NI8hjWB^\n ,L2_6iQptN2,T$28D[2!Wn&tDW:\\]^%=mq4,L&L3'*W6f&5M%#p5L_e+eT*5%qbKe3InFuN\n [qM,;pD;QQ2j\\_Q]3?Y*qob+X!elk:>;_VH=$rD>q1$:jd.i8`,nl/)@aTG=Ai1Nf7q9sB\"\n GT>iP\"B34GsnN0/!`h>deSR9AM]cLB%)%Dk&ibW:M8/Q\"U9ZJU/>URH:9/GnU/(%%EDVfJD\n 1g;=^]aS%^B3=f'Cl?a>k`fYurW$>=G.'&%1.oG0><FiH%Xrm\\'Hjk3[N.0Z\"-.-3\"'t_-q\n ;MFs'4,M8eJZR/D+e-&]mM1:_e0B.]?AA[A']reEY3cnPT9L+])sW7>[+RXh,DMm:t%[[V]\n RkA.]bD`9sfQN<#]ic'.t4cif'`oV8%I,9WCV9\\@JHG)#DD2m69p:HmppLl;@nhIe+D_IV9\n S7DEo^<_#DiUcgBIU@#dBfa<5Im7l<!<9i(3&^`NYTsY\\_%9iYA3mGF3sS)+JWL?Td&\\l.6\n P/$1%`7/j57j4p\"@j%lJE]91`A'b\\(<)DD4AVA\"N+X\"tOh>NNR3;;k*QPGGI3?TD*.K0R;D\n `n8'IHM=-:r5oTd>Ag)3cb?B#-`JSHgV[V+]87_(a)3*6Bt[dlc#7bu7m#2U0]uiAf+]SEW\n )[a]Z&rT#C/tF,VEeYS\"b;qREk.b=rJS:s5<h7]nRoqadniP5)VmbT/E2YY9ro:9kT*,gA+\n Rh+:JN[6$fV1i7;8<n3IFHW[aWPC6WDXt,W>f+&Ir?Fk:NY@+rf\"1r$pQ6X^d]f'#Pqq9;l\n T);bf]E8+:euSZMgJCnZ#!jr._$WMjoJm?8d+hD1>u<3,(WCTG?$JjOXm(,NOsH*9h\\Y(1I\n `^4:AlP29WJYU0`rXn?T4d6RL>gd6+c,,[SgfQVfY0)!j&k.uNoSdgEbjVZaeWtcKt4>s]p\n (uh78Xb1+\\+/LY%^K][*oVW;\\\\=XT')@r7A.#Q:5P[Oc$`ln<Y_3o>A:LADWB>pPE0*dec)\n g^3tDd[Y#uNOPk8cf<M?_PHSqPl>7_k-CKnE!\\Sp8\"T':422^\\'9_cKReFi=$.h0AEjZus5\n m=7uC,h]b?sBotl!`b1iTRJMDD*5=5Po3C05cL]ik6.#70+%aoQaj2GdRV,de8t#u5YZdKh\n 'JGd\"H'`MA;LRD;94pEd1;IOo*C3J7'eY0_kd=Dj=6X%>>Gu98St0'MFk3L#lMB,CmCBYh^\n $s[d&'8F#4%I])g08LK\\D,niiOaP?*qfBb[mp>on6?M\"'_'HI*B9DhOb'8/%KcuS$GrGra/\n KJhn3.+D(aT=CU_SL.?49,e2$W!u?Q16\"HO:pt3WiKu)aMnO%+\\hoh9.TdcLIC:#'?]u,<g\n @U+ri^hR.Ar]c=o!1eNG:\\&>BiiLrUgC^$(XmcD0<5Ys%Zd2SaL.46h^.<VEP:#2C;QmVZs\n f]!n$o\\JsU@Io#b9Y9s\\rf;^TV@jDcr6'rKXi7T75S89RO4!*GCI?2eT5Y)ar+QOf%OO>,0\n NoBIk`N\\5?U&8C0n;o/TL_hsGZ/%Lp2%3e\"SS(dM:ct.7%UnBeH*9OV6l2g7-!O*\"mp]BeV\n n3TX\"AY91:+8i%aVCFA=$J:B?q$sK(T&A^N\"[39`[R/jj#_dZdA1;<#hh%\"5bf3*A6b+6*]\n (hZarM_JICbgY39MRKSC='O:79Wnk@EtN`*@^N;4K[;R%7$HZ4d>6:c!WiMhU_=hb!$B@O2\n F@1%=I*]W\"USAPB%:'!`\\'f<\"[WI'TKpd,iGqT%E)R\\<kY7O=a%V(1QAODDNHIba7]Phnsl\n =d?\\FbKOBgkSGN`AQqe)fc86PPiH!D]TMuh`;!K>qW7;rb<19%I8%ddu,G9;gEMPT^4EUkF\n S7\\.f2%8[f4,3ACKL;\"n.:Lr2U!Wkm;(<_W-%-N''$e!<2oS7\\NHI@jI_8>&fbRe/-B#2K0\n A%'/9'diWR>\\LdJcpB2`H]c?K+MpXZ*l^5nF7Rm0$IIf2.l4:S[6mrcrq8/4NGhH(rM_cM4\n pe,K6^B$K!]1lYr4?%jIMsOJqVL>aU`/M%AGc[[@@\"AE7N2LXu3qQ7-a/0<c*/Y2`\\9D4/F\n Xsr?e?S*gT8DbtETX(C1el2[g;.-I_2$WWU\\tg+1^\"mq(n\"f=q#e)s)IhD*P>$gf]WqfHLN\n %iX<W]CP*d&1CU:QX8!`ggR1W\"n6r0&f)\"=[$7/n_c,RWFB&qQ(EH:Bic_M<H@+Xa68oZ*H\n ]._mW%$6)f\"&Q`OF\\$Q^>>])OAb=!ph]--rFcQ\"S4ic$5HJ25jlNM-h^Oq1o$_ad8`E:Fg7\n qrsn*2RQ,2@lna7k@9uM-I,H?$gg.-t0\\MF>G6c\\om^Uh.m0Kd3(HkTnH^2OUa/P&?d%JY\\\n Gk[j%o4EIF$UH5\\M/AT_'Rb:A\"I(%jCEqLCinf2QSqJ+hAB,T[\\Yt1^oneVh8Yo]up#K:g<\n iH/8K\\NH^TKIAgqeVF^o%%'+&L;R><U!0VTFn(fu\\>bV)H4L;0IUD%<823es:`d+]XQCn6i\n sp1DS&gH:_LoXI(S39M>,Uhl'R'qHKrg'Oo=(^a-+E2tOfXW*l`i?t\\)hS,lCe7T4f[^gG<\n Nig4B7oufl%L`LpbR#K6>mo&dYD3V'*CD$L%\\`5Q[YG=NgcpU7*[Sc\"VLTb@pjWco(,NBA[\n unOHC(=Y\\15?-O`PG^1\"2Rqm_(%Ub)M`FB).BK<IU6f:bFEKEa1_'o#6i`g+\\=r4P(UXU&g\n KY^=Wu?N[]n[26em'M_>D2tVcE$<?`\\CA[FX^.q!(6qI#UGE4[p\"D*Wj!Q7r];#7hBrRTqb\n ot@;Ief/<g?]?keJAPR!;1&`&FJ;YV0hWZN$<Cd<+@K!@j%_8?<[ikT737qJ1paEADQH,kp\n nmOU0.1*.ZL&.ZDjT/u/3o\\Q4iHCn4&rFJBpj1[sB1$1Y(b'N*#b[>U&BmtbrG8)`lhi<7N\n :5\"kepnO%\\NZeT^7h<c_4h,D84XK`Tn'q3k:[EL:Zh4G$a;c9`jG?'^-*!?,94+'.$S1oHL\n L@gCUBkn$%#-nu^S2fUH`?l!p&>!SrVt4D!\"]54:^6u^$NSNa!>#nF:_s.o)Ze;-!Y?RX:a\n Z=+.g\"'N!t[6j:cAK<3s3ho\";!C4+9~>Q\nQ\nshowpage\n%%Trailer\ncount op_count sub {pop} repeat\ncountdictstack dict_count sub {end} repeat\ncairo_eps_state restore\n%%EOF\n"
  },
  {
    "path": "doc/interpreter/octave.1",
    "content": ".\\\" --------------------------------------------------------------------\n.\\\"\n.\\\" Copyright (C) 1996-2026 The Octave Project Developers\n.\\\"\n.\\\" See the file COPYRIGHT.md in the top-level directory of this\n.\\\" or <https://octave.org/copyright/>.\n.\\\"\n.\\\" This file is part of Octave.\n.\\\"\n.\\\" Octave is free software: you can redistribute it and/or modify it\n.\\\" under the terms of the GNU General Public License as published by\n.\\\" the Free Software Foundation, either version 3 of the License, or\n.\\\" (at your option) any later version.\n.\\\"\n.\\\" Octave is distributed in the hope that it will be useful, but\n.\\\" WITHOUT ANY WARRANTY; without even the implied warranty of\n.\\\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n.\\\" GNU General Public License for more details.\n.\\\"\n.\\\" You should have received a copy of the GNU General Public License\n.\\\" along with Octave; see the file COPYING.  If not, see\n.\\\" <https://www.gnu.org/licenses/>.\n.\\\"\n.\\\" --------------------------------------------------------------------\n.\\\"\n.de Vb \\\" (V)erbatim (b)egin.  Use fixed width font and no justification\n.ft CW\n.nf\n..\n.de Ve \\\" (V)erbatim (e)nd.  Return to regular font and justification\n.ft R\n.fi\n..\n.\\\" --------------------------------------------------------------------\n.TH OCTAVE 1 \"3 January 2024\" \"GNU Octave\"\n.SH NAME\noctave \\- A high-level interactive programming language for numerical\ncomputations.\n.SH SYNOPSIS\n\\fBoctave\\fP [\\fIoptions\\fP]\\|.\\|.\\|.\\& [\\fIfile\\fP]\n.SH DESCRIPTION\nOctave is a high-level interactive scientific programming language.  It has a\npowerful mathematics-oriented syntax for solving problems numerically, as well\nas built-in 2-D/3-D plotting and visualization tools.  Octave provides an\nintegrated development environment in either graphical or command-line form.\nPrograms may also be run in batch mode to process data without interaction.\n.SH OPTIONS\nA list of the most useful command-line options for \\fBoctave\\fP is available by\nrunning the following command from the shell.\n.Vb\n\n.B    octave \\-\\-help\n.Ve\n.SH DOCUMENTATION\nThe primary documentation for Octave is written using Texinfo, the GNU\ndocumentation system, which allows the same source files to be used to produce\nonline and printed versions of the manual.\n.PP\nYou can read the built-in copy of the Octave documentation by issuing the\nfollowing command from within \\fBoctave\\fP.\n.Vb\n\n    octave:1> \\fBdoc\\fP\n\n.Ve\nThe Info files may also be read with a stand-alone program such as \\fBinfo\\fP\nor \\fBxinfo\\fP.  HTML, Postscript, or PDF versions of the documentation are\ninstalled on many systems as well.  The latest version of the documentation is\navailable at\n.UR https://\\:docs.octave.org/\\:latest\n.UE .\n.SH BUGS\nThe Octave project maintains a bug tracker at\n.UR https://\\:bugs.octave.org\n.UE .\nBefore submitting a new item please read the instructions at\n.UR https://\\:www.octave.org/\\:bugs.html\n.UE \\ on how to submit a useful report.\n.SH FILES\nUpon startup Octave looks for four initialization files.  Each file may contain\nany number of valid Octave commands.\n.TP\n\\fIoctave-home\\fP/share/octave/site/m/startup/octaverc\nSite-wide initialization file which changes options for all users.\n\\fIoctave-home\\fP is the directory where Octave was installed such as\n\\fI/usr/local\\fP.\n.TP\n\\fIoctave-home\\fP/share/octave/\\fIversion\\fP/m/startup/octaverc\nSite-wide initialization file for Octave version \\fIversion\\fP.\n.TP\n~/.octaverc\nUser's personal initialization file.\n.TP\n\\&\\.octaverc\nProject-specific initialization file located in the current directory.\n.SH AUTHOR\nJohn W. Eaton and many others.  The list of contributors to the Octave project\nmay be shown with \\fBinfo octave Acknowledgements\\fP.  The list is also\navailable online at\n.UR https://\\:docs.octave.org/\\:latest/\\:Acknowledgements.html\n.UE .\n"
  },
  {
    "path": "doc/interpreter/octave.css",
    "content": "/*\n\nCopyright (C) 2016-2026 The Octave Project Developers\n\nSee the file COPYRIGHT.md in the top-level directory of this\ndistribution or <https://octave.org/copyright/>.\n\nThis file is part of Octave.\n\nOctave is free software: you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nOctave is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with Octave; see the file COPYING.  If not, see\n<https://www.gnu.org/licenses/>.\n\n*/\n\n/* Import web font Roboto Condensed, Font Library Version 2015-06-06 */\n@font-face {\n  font-family: 'Roboto Condensed';\n  src: local('Roboto Condensed Bold'),\n       local('RobotoCondensed-Bold'),\n       url('https://fontlibrary.org/assets/fonts/roboto-condensed/71405335c70332d94afd24ae4f06c9b2/4b8b4b377e8cb358cf886d13c7bb287c/RobotoCondensedBold.ttf') format('truetype');\n  font-weight: bold;\n  font-style: normal; }\n\n@font-face\n{\n  font-family: 'Roboto Condensed';\n  src: local('Roboto Condensed Bold Italic'),\n       local('RobotoCondensed-BoldItalic'),\n       url('https://fontlibrary.org/assets/fonts/roboto-condensed/71405335c70332d94afd24ae4f06c9b2/9b1d05d1b332e5b95ad86e71ca8404fb/RobotoCondensedBoldItalic.ttf') format('truetype');\n  font-weight: bold;\n  font-style: italic;\n}\n\n@font-face\n{\n  font-family: 'Roboto Condensed';\n  src: local('Roboto Condensed Italic'),\n       local('RobotoCondensed-Italic'),\n       url('https://fontlibrary.org/assets/fonts/roboto-condensed/71405335c70332d94afd24ae4f06c9b2/d02fffb6890e4f28023dd149916d1b8a/RobotoCondensedItalic.ttf') format('truetype');\n  font-weight: normal;\n  font-style: italic;\n}\n\n@font-face\n{\n  font-family: 'Roboto Condensed';\n  src: local('Roboto Condensed Regular'),\n       local('RobotoCondensed-Regular'),\n       url('https://fontlibrary.org/assets/fonts/roboto-condensed/71405335c70332d94afd24ae4f06c9b2/b0b1845ecce8ab6a503971e808a8409c/RobotoCondensedRegular.ttf') format('truetype');\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* Import web font Fantasque Sans Mono, Font Library Version 2016-04-05 */\n@font-face\n{\n  font-family: 'Fantasque Sans Mono', FreeMono, 'Courier New', Cousine, Courier, monospace;\n  src: local('Fantasque Sans Mono Bold'),\n       local('FantasqueSansMono-Bold'),\n       url('https://fontlibrary.org/assets/fonts/fantasque-sans-mono/b0cbb25e73a9f8354e96d89524f613e7/a46033d3a07d9385620dc83b7655203f/FantasqueSansMonoBold.ttf') format('truetype');\n  font-weight: bold;\n  font-style: normal;\n}\n\n@font-face\n{\n  font-family: 'Fantasque Sans Mono', FreeMono, 'Courier New', Cousine, Courier,  'monospace';\n  src: local('Fantasque Sans Mono Bold Italic'),\n       local('FantasqueSansMono-BoldItalic'),\n       url('https://fontlibrary.org/assets/fonts/fantasque-sans-mono/b0cbb25e73a9f8354e96d89524f613e7/b0683ef4c834908aa372ec78dea42349/FantasqueSansMonoBoldItalic.ttf') format('truetype');\n  font-weight: bold;\n  font-style: italic;\n}\n\n@font-face\n{\n  font-family: 'Fantasque Sans Mono', FreeMono, 'Courier New', Cousine, Courier, monospace;\n  src: local('Fantasque Sans Mono Italic'),\n       local('FantasqueSansMono-Italic'),\n       url('https://fontlibrary.org/assets/fonts/fantasque-sans-mono/b0cbb25e73a9f8354e96d89524f613e7/b78d0a48e4443f797e8d45dcf97594f7/FantasqueSansMonoItalic.ttf') format('truetype');\n  font-weight: normal;\n  font-style: italic;\n}\n\n@font-face\n{\n  font-family: 'Fantasque Sans Mono', FreeMono, 'Courier New', Cousine, Courier, monospace;\n  src: local('Fantasque Sans Mono Regular'),\n       local('FantasqueSansMono-Regular'),\n       url('https://fontlibrary.org/assets/fonts/fantasque-sans-mono/b0cbb25e73a9f8354e96d89524f613e7/f3fdc4f0f26e4431f54e8b552d55480c/FantasqueSansMonoRegular.ttf') format('truetype');\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* Use custom fonts */\ncode, kbd, samp, tt, pre { font-family: 'Fantasque Sans Mono', FreeMono, 'Courier New', Cousine, Courier, monospace; }\n\ncode, kbd, samp, tt {\n  font-style: italic;\n  padding: 0 0.1ex; /* slightly increase margin to surrounding text */ }\n\nbody, .sansserif { font-family: 'Roboto Condensed', sans-serif; }\n\nh1, h2, h3, h4, h5, .menu-comment, .roman, .menu-preformatted {\n  font-family: 'Roboto Condensed', serif; }\n\n/* Use colors from the solarized color theme (sparsely), the main text\n   will remain in default colors for optimal readability (black on white).  */\n\npre.example, .header, .float-caption, hr {\n  /* base00 ~ body text in light solarized theme */\n  color: #657b83;\n  border-color: #657b83; }\n\npre.example {\n  /* base3 ~ background color in light solarized theme */\n  background-color: #fdf6e3;\n  padding: 0.5em; }\n\na { color: #268bd2; /* blue */ }\n\na:visited { color: #d33682; /* magenta */ }\n\n/* Center floating tables and images */\n.float table, .float img, .float object {\n  margin-left: auto;\n  margin-right: auto; }\n\n/* Decrease table width, but not on small screens */\n.float table { max-width: 38em; }\n\n/* Use horizontal lines: above/below tables and after table headers\n   (Chicago Style).  */\n.float table, .float th {\n  border-collapse: collapse;\n  border-top: 1px solid black;\n  border-bottom: 1px solid black; }\n\n.float th, .float td { padding: 0.5em; }\n\n/* Use horizontal ruler with double lines */\nhr { border-width: 0; border-top-width: 3px; border-style: double; }\n\n/* Smaller gap between subsequent @group blocks */\n.example { margin-bottom: 1em; }\n.example + .example { margin-top: -0.5em }\n\n/* Smaller gap between definition and its description */\ndd > p:first-child { margin-top: 0.5em; }\n\n/* Limit maximum body width such that text is easier to read */\nbody { max-width: 42em; margin-left: 0.5em; margin-right: 0.5em; }\n\n/* On small screens don't indent the code examples to prevent overflow */\ndiv.example { margin-left: auto; max-width: 38.8em; }\n\n/*\nUse left margin such that text is easier to read,\nbut don't sacrifice space on small screens.\n*/\n@media screen and (min-width: 43em)\n{\n  /* Smooth transition for screens between 43em and 57em */\n  body { margin-left: auto; margin-right: auto; }\n  @media (min-width: 57em)\n  {\n    body { margin-left: 7.5em; }\n  }\n}\n"
  },
  {
    "path": "doc/interpreter/octave.texi",
    "content": "% Copyright (C) 1996-2026 The Octave Project Developers\n%\n% This file is part of Octave.\n%\n% Octave is free software: you can redistribute it and/or modify it\n% under the terms of the GNU General Public License as published by\n% the Free Software Foundation, either version 3 of the License, or\n% (at your option) any later version.\n%\n% Octave is distributed in the hope that it will be useful, but\n% WITHOUT ANY WARRANTY; without even the implied warranty of\n% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n% GNU General Public License for more details.\n%\n% You should have received a copy of the GNU General Public License\n% along with Octave; see the file COPYING.  If not, see\n% <https://www.gnu.org/licenses/>.\n\n% MUST precede definition of \\input as Texinfo\n% Allow generated PDF output (Octave manual) at version level 1.7\n\\pdfminorversion=7\n\n\\input texinfo\n\n@documentencoding UTF-8\n\n@setfilename octave.info\n\n@dircategory Math\n@direntry\n* Octave: (octave).             Interactive language for numerical computations.\n@end direntry\n\n@include macros.texi\n\n@c Settings which control appearance\n@c ------------------------------------------------------------------------\n\n@c Use smaller indent for example blocks (better feel, more code on page)\n@exampleindent 2\n\n@c Best feel obtained by *not* setting paragraph indent (value is ~1.5)\n@c @paragraphindent 2\n\n@c Make the apostrophe in @code blocks cut-and-paste friendly so programmers\n@c can take examples from the Octave manual and run them directly in Octave.\n@codequoteundirected on\n\n@c Don't print ugly black squares for overfull hboxes in PDF output.\n@c Comment out this line when debugging overfull hbox warnings.\n@finalout\n\n@c Settings for printing on 8-1/2 by 11 inch paper (default):\n@c ----------------------------------------------------------\n@setchapternewpage odd\n@c Fix TOC margins in printed manual\n@tex\n{\\globaldefs = 1 \\contentsrightmargin = 0pt}\n@end tex\n\n@c Settings for small book format:\n@c ------------------------------\n@c @smallbook\n@c @setchapternewpage odd\n@c @finalout\n@c @iftex\n@c @cropmarks\n@c @end iftex\n\n@c Set color of links in PDF manual\n@tex\n  \\ifx\\rgbDarkRed\\thisisundefined\n    \\def\\rgbDarkRed{0.50 0.09 0.12}\n  \\fi\n  \\ifx\\linkcolor\\thisisundefined\n    \\relax\n  \\else\n    \\global\\def\\linkcolor{\\rgbDarkRed}\n  \\fi\n  \\ifx\\urlcolor\\thisisundefined\n    \\relax\n  \\else\n    \\global\\def\\urlcolor{\\rgbDarkRed}\n  \\fi\n  \\ifx\\urefurlonlylinktrue\\thisisundefined\n    \\relax\n  \\else\n    \\global\\urefurlonlylinktrue\n  \\fi\n@end tex\n\n@c ------------------------------------------------------------------------\n\n@c Create additional op(erator) and graphics pr(operties) indices\n@defindex op\n@defindex pr\n\n@c MUST include \"version-octave.texi\" in order for Automake to create file.\n@include version-octave.texi\n@c MUST include \"octave-doc-version.texi\" LAST as it overwrites file above.\n@include octave-doc-version.texi\n\n@settitle GNU Octave (version @value{VERSION})\n\n@ifnottex\n\nCopyright @copyright{} 1996-2026 The Octave Project Developers\n\nPermission is granted to make and distribute verbatim copies of\nthis manual provided the copyright notice and this permission notice\nare preserved on all copies.\n\n@ignore\nPermission is granted to process this file through Tex and print the\nresults, provided the printed document carries copying permission\nnotice identical to this one except for the removal of this paragraph\n(this paragraph not being relevant to the printed manual).\n@end ignore\n\nPermission is granted to copy and distribute modified versions of\nthis manual under the conditions for verbatim copying, provided that\nthe entire resulting derived work is distributed under the terms of\na permission notice identical to this one.\n\nPermission is granted to copy and distribute translations of this\nmanual into another language, under the above conditions for\nmodified versions.\n@end ifnottex\n\n@titlepage\n@title GNU Octave\n@subtitle A high-level interactive language for numerical computations\n@subtitle Edition @value{EDITION} for Octave version @value{VERSION}\n@subtitle @value{UPDATED-MONTH}\n@sp 2\n@multitable @columnfractions 0.4 0.026 0.65\n@item\n@flushright\n@image{octave-logo,2.1in}\n@end flushright\n@tab\n@c this is a spacer column\n@tab\n@sp 8\n@titlefont{Free Your Numbers}\n@end multitable\n@author John W. Eaton\n@author David Bateman\n@author S@o{}ren Hauberg\n@author Rik Wehbring\n@page\n@vskip 0pt plus 1filll\nCopyright @copyright{} 1996-2026 The Octave Project Developers\n\nThis is edition @value{EDITION} of the Octave documentation, and is consistent\nwith version @value{VERSION} of Octave.\n\nPermission is granted to make and distribute verbatim copies of\nthis manual provided the copyright notice and this permission notice\nare preserved on all copies.\n\nPermission is granted to copy and distribute modified versions of this\nmanual under the conditions for verbatim copying, provided that the entire\nresulting derived work is distributed under the terms of a permission\nnotice identical to this one.\n\nPermission is granted to copy and distribute translations of this manual\ninto another language, under the same conditions as for modified versions.\n\nPortions of this document have been adapted from the @code{gawk},\n@code{readline}, @code{gcc}, and C library manuals, published by the Free\nSoftware Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n02110-1301--1307, USA.\n@end titlepage\n\n@contents\n\n@ifnottex\n@node Top\n@top\n\nThis manual documents how to run, install and port GNU Octave, as well\nas its new features and incompatibilities, and how to report bugs.\nIt corresponds to GNU Octave version @value{VERSION}.\n@end ifnottex\n\n@c ------------------------------------------------------------------------\n\n@menu\n* Preface::\n* Introduction::                A brief introduction to Octave.\n* Getting Started::\n* Data Types::\n* Numeric Data Types::\n* Strings::\n* Data Containers::\n* Variables::\n* Expressions::\n* Evaluation::\n* Statements::                  Looping and program flow control.\n* Functions and Scripts::\n* Errors and Warnings::\n* Debugging::\n* Input and Output::\n* Plotting::\n* Matrix Manipulation::\n* Arithmetic::\n* Linear Algebra::\n* Vectorization and Faster Code Execution::\n* Nonlinear Equations::\n* Diagonal and Permutation Matrices::\n* Sparse Matrices::\n* Numerical Integration::\n* Differential Equations::\n* Optimization::\n* Statistics::\n* Sets::\n* Polynomial Manipulations::\n* Interpolation::\n* Geometry::\n* Signal Processing::\n* Image Processing::\n* Audio Processing::\n* Object Oriented Programming::\n* GUI Development::\n* System Utilities::\n* Packages::\n* External Code Interface::\n* Test and Demo Functions::\n* Obsolete Functions::\n* Trouble::                     If you have trouble installing Octave.\n* Installing Octave::           How to configure, compile, and install Octave.\n* Grammar and Parser::\n* Copying::                     The GNU General Public License.\n* Concept Index::               An item for each concept.\n* Function Index::              An item for each documented function.\n* Operator Index::              An item for each documented operator.\n* Graphics Properties Index::   An item for each graphics object property.\n\n@detailmenu\n --- The Detailed Node Listing ---\n\nPreface\n\n* Acknowledgements::\n* Citing Octave in Publications::\n* How You Can Contribute to Octave::\n* Distribution::\n\nIntroduction\n\n* Running Octave::\n* Simple Examples::\n* Conventions::\n\nConventions\n\n* Fonts::\n* Evaluation Notation::\n* Printing Notation::\n* Error Messages::\n* Format of Descriptions::\n\nFormat of Descriptions\n\n* A Sample Function Description::\n* A Sample Command Description::\n\nGetting Started\n\n* Invoking Octave from the Command Line::\n* Quitting Octave::\n* Getting Help::\n* Command Line Editing::\n* How Octave Reports Errors::\n* Executable Octave Programs::\n* Comments in Octave Programs::\n\nInvoking Octave from the Command Line\n\n* Command Line Options::\n* Startup Files::\n\nCommand Line Editing\n\n* Cursor Motion::\n* Killing and Yanking::\n* Commands for Changing Text::\n* Commands for Completion::\n* Commands for Manipulating the History::\n* Customizing readline::\n* Customizing the Prompt::\n* Diary and Echo Commands::\n\nExecutable Octave Programs\n\n* Passing Arguments to Executable Scripts::\n* Dual-Purpose Executable Scripts and Octave Functions::\n\nComments in Octave Programs\n\n* Single Line Comments::\n* Block Comments::\n* Comments and the Help System::\n\nData Types\n\n* Built-in Data Types::\n* User-defined Data Types::\n* Object Sizes::\n\nBuilt-in Data Types\n\n* Numeric Objects::\n* Missing Data::\n* String Objects::\n* Data Structure Objects::\n* Cell Array Objects::\n\nNumeric Data Types\n\n* Matrices::\n* Ranges::\n* Single Precision Data Types::\n* Integer Data Types::\n* Bit Manipulations::\n* Logical Values::\n* Automatic Conversion of Data Types::\n* Predicates for Numeric Objects::\n\nMatrices\n\n* Empty Matrices::\n\nInteger Data Types\n\n* Hexadecimal and Binary Integer Constants\n* Integer Arithmetic::\n\nStrings\n\n* Escape Sequences in String Constants::\n* Character Arrays::\n* String Operations::\n* Converting Strings::\n* Character Class Functions::\n\nString Operations\n\n* Common String Operations::\n* Concatenating Strings::\n* Splitting and Joining Strings::\n* Searching in Strings::\n* Searching and Replacing in Strings::\n\nConverting Strings\n\n* String encoding::\n* Numerical Data and Strings::\n* JSON data encoding/decoding::\n\nData Containers\n\n* Structures::\n* containers.Map::\n* Cell Arrays::\n* Comma-Separated Lists::\n\nStructures\n\n* Basic Usage and Examples::\n* Structure Arrays::\n* Creating Structures::\n* Manipulating Structures::\n* Processing Data in Structures::\n\nCell Arrays\n\n* Basic Usage of Cell Arrays::\n* Creating Cell Arrays::\n* Indexing Cell Arrays::\n* Cell Arrays of Strings::\n* Processing Data in Cell Arrays::\n\nComma-Separated Lists\n\n* Comma-Separated Lists Generated from Cell Arrays::\n* Comma-Separated Lists Generated from Structure Arrays::\n\nVariables\n\n* Global Variables::\n* Persistent Variables::\n* Status of Variables::\n\nExpressions\n\n* Index Expressions::\n* Calling Functions::\n* Arithmetic Ops::\n* Comparison Ops::\n* Boolean Expressions::\n* Assignment Ops::\n* Increment Ops::\n* Operator Precedence::\n\nIndex Expressions\n\n* Advanced Indexing::\n\nCalling Functions\n\n* Call by Value::\n* Recursion::\n* Access via Handle::\n\nBoolean Expressions\n\n* Element-by-element Boolean Operators::\n* Short-circuit Boolean Operators::\n\nEvaluation\n\n* Calling a Function by its Name::\n* Evaluation in a Different Context::\n\nStatements\n\n* The if Statement::\n* The switch Statement::\n* The while Statement::\n* The do-until Statement::\n* The for Statement::\n* The break Statement::\n* The continue Statement::\n* The unwind_protect Statement::\n* The try Statement::\n* Continuation Lines::\n\nThe switch Statement\n\n* Notes for the C Programmer::\n\nThe for Statement\n\n* Looping Over Structure Elements::\n\nFunctions and Scripts\n\n* Introduction to Function and Script Files::\n* Defining Functions::\n* Returning from a Function::\n* Multiple Return Values::\n* Variable-length Return Lists::\n* Variable-length Argument Lists::\n* Ignoring Arguments::\n* Default Arguments::\n* Validating Arguments::\n* Function Files::\n* Script Files::\n* Function Handles and Anonymous Functions::\n* Command Syntax and Function Syntax::\n* Organization of Functions::\n\nValidating Arguments\n\n* Validating the number of Arguments::\n* Validating the type of Arguments::\n* Parsing Arguments::\n\nFunction Files\n\n* Manipulating the Load Path::\n* Subfunctions::\n* Private Functions::\n* Nested Functions::\n* Overloading and Autoloading::\n* Function Locking::\n* Function Precedence::\n\nScript Files\n\n* Publish Octave Script Files::\n* Publishing Markup::\n* Jupyter Notebooks::\n\nPublishing Markup\n\n* Using Publishing Markup in Script Files::\n* Text Formatting::\n* Sections::\n* Preformatted Code::\n* Preformatted Text::\n* Bulleted Lists::\n* Numbered Lists::\n* Including File Content::\n* Including Graphics::\n* Including URLs::\n* Mathematical Equations::\n* HTML Markup::\n* LaTeX Markup::\n\nFunction Handles and Anonymous Functions\n\n* Function Handles::\n* Anonymous Functions::\n\nErrors and Warnings\n\n* Handling Errors::\n* Handling Warnings::\n\nHandling Errors\n\n* Raising Errors::\n* Catching Errors::\n* Recovering From Errors::\n\nHandling Warnings\n\n* Issuing Warnings::\n* Enabling and Disabling Warnings::\n\nDebugging\n\n* Entering Debug Mode::\n* Leaving Debug Mode::\n* Breakpoints::\n* Debug Mode::\n* Call Stack::\n* Profiling::\n* Profiler Example::\n\nInput and Output\n\n* Basic Input and Output::\n* C-Style I/O Functions::\n\nBasic Input and Output\n\n* Terminal Output::\n* Terminal Input::\n* Simple File I/O::\n\nTerminal Output\n\n* Paging Screen Output::\n\nSimple File I/O\n\n* Saving Data on Unexpected Exits::\n\nC-Style I/O Functions\n\n* Opening and Closing Files::\n* Simple Output::\n* Line-Oriented Input::\n* Formatted Output::\n* Output Conversion for Matrices::\n* Output Conversion Syntax::\n* Table of Output Conversions::\n* Integer Conversions::\n* Floating-Point Conversions::\n* Other Output Conversions::\n* Formatted Input::\n* Input Conversion Syntax::\n* Table of Input Conversions::\n* Numeric Input Conversions::\n* String Input Conversions::\n* Binary I/O::\n* Temporary Files::\n* EOF (End of File) and Errors::\n* File Positioning::\n\nPlotting\n\n* Introduction to Plotting::\n* High-Level Plotting::\n* Graphics Data Structures::\n* Advanced Plotting::\n\nHigh-Level Plotting\n\n* Two-Dimensional Plots::\n* Three-Dimensional Plots::\n* Plot Annotations::\n* Multiple Plots on One Page::\n* Multiple Plot Windows::\n* Manipulation of Plot Objects::\n* Manipulation of Plot Windows::\n* Use of the \"interpreter\" Property::\n* Printing and Saving Plots::\n* Interacting with Plots::\n* Test Plotting Functions::\n\nTwo-Dimensional Plots\n\n* Axis Configuration::\n* Two-dimensional Function Plotting::\n* Two-dimensional Geometric Shapes::\n\nThree-Dimensional Plots\n\n* Aspect Ratio::\n* Three-dimensional Function Plotting::\n* Three-dimensional Geometric Shapes::\n\nGraphics Data Structures\n\n* Introduction to Graphics Structures::\n* Graphics Objects::\n* Graphics Object Properties::\n* Searching Properties::\n* Managing Default Properties::\n\nGraphics Object Properties\n\n* Root Properties::\n* Figure Properties::\n* Axes Properties::\n* Legend Properties::\n* Line Properties::\n* Text Properties::\n* Image Properties::\n* Patch Properties::\n* Scatter Properties::\n* Surface Properties::\n* Light Properties::\n* Uimenu Properties::\n* Uibuttongroup Properties::\n* Uicontextmenu Properties::\n* Uipanel Properties::\n* Uicontrol Properties::\n* Uitable Properties::\n* Uitoolbar Properties::\n* Uipushtool Properties::\n* Uitoggletool Properties::\n\nAdvanced Plotting\n\n* Colors::\n* Line Styles::\n* Marker Styles::\n* Callbacks::\n* Application-defined Data::\n* Object Groups::\n* Transform Groups::\n* Graphics Toolkits::\n\nObject Groups\n\n* Data Sources in Object Groups::\n* Area Series::\n* Bar Series::\n* Contour Groups::\n* Error Bar Series::\n* Line Series::\n* Quiver Group::\n* Stair Group::\n* Stem Series::\n* Surface Group::\n\nGraphics Toolkits\n\n* Customizing Toolkit Behavior::\n* Hardware vs Software Rendering::\n* Precision issues::\n\nMatrix Manipulation\n\n* Finding Elements and Checking Conditions::\n* Rearranging Matrices::\n* Special Utility Matrices::\n* Famous Matrices::\n\nArithmetic\n\n* Exponents and Logarithms::\n* Complex Arithmetic::\n* Trigonometry::\n* Sums and Products::\n* Utility Functions::\n* Special Functions::\n* Rational Approximations::\n* Coordinate Transformations::\n* Mathematical Constants::\n\nLinear Algebra\n\n* Techniques Used for Linear Algebra::\n* Basic Matrix Functions::\n* Matrix Factorizations::\n* Functions of a Matrix::\n* Specialized Solvers::\n\nVectorization and Faster Code Execution\n\n* Basic Vectorization::        Basic techniques for code optimization\n* Broadcasting::               Broadcasting operations\n* Function Application::       Applying functions to arrays, cells, and structs\n* Accumulation::               Accumulation functions\n* Memoization::                Memoization techniques\n* Miscellaneous Techniques::   Other techniques for speeding up code\n* Examples::\n\nNonlinear Equations\n\n* Solvers::\n* Minimizers::\n\nDiagonal and Permutation Matrices\n\n* Basic Usage::          Creation and Manipulation of Diagonal/Permutation Matrices\n* Matrix Algebra::       Linear Algebra with Diagonal/Permutation Matrices\n* Function Support::     Functions That Are Aware of These Matrices\n* Example Code::         Examples of Usage\n* Zeros Treatment::      Differences in Treatment of Zero Elements\n\nBasic Usage\n\n* Creating Diagonal Matrices::\n* Creating Permutation Matrices::\n* Explicit and Implicit Conversions::\n\nMatrix Algebra\n\n* Expressions Involving Diagonal Matrices::\n* Expressions Involving Permutation Matrices::\n\nFunction Support\n\n* Diagonal Matrix Functions::\n* Permutation Matrix Functions::\n\nSparse Matrices\n\n* Basics::                      Creation and Manipulation of Sparse Matrices\n* Sparse Linear Algebra::       Linear Algebra on Sparse Matrices\n* Iterative Techniques::        Iterative Techniques\n* Real Life Example::           Using Sparse Matrices\n\nBasics\n\n* Storage of Sparse Matrices::\n* Creating Sparse Matrices::\n* Information::\n* Operators and Functions::\n\nOperators and Functions\n\n* Sparse Functions::\n* Return Types of Operators and Functions::\n* Mathematical Considerations::\n\nNumerical Integration\n\n* Functions of One Variable::\n* Orthogonal Collocation::\n* Functions of Multiple Variables::\n\nDifferential Equations\n\n* Ordinary Differential Equations::\n* Differential-Algebraic Equations::\n\nOrdinary Differential Equations\n\n* Matlab-compatible solvers::\n\nOptimization\n\n* Linear Programming::\n* Quadratic Programming::\n* Nonlinear Programming::\n* Linear Least Squares::\n\nStatistics\n\n* Descriptive Statistics::\n* Statistics on Sliding Windows of Data::\n* Basic Statistical Functions::\n* Correlation and Regression Analysis::\n* Distributions::\n* Random Number Generation::\n\nSets\n\n* Set Operations::\n\nPolynomial Manipulations\n\n* Evaluating Polynomials::\n* Finding Roots::\n* Products of Polynomials::\n* Derivatives / Integrals / Transforms::\n* Polynomial Interpolation::\n* Miscellaneous Functions::\n\nInterpolation\n\n* One-dimensional Interpolation::\n* Multi-dimensional Interpolation::\n\nGeometry\n\n* Delaunay Triangulation::\n* Voronoi Diagrams::\n* Convex Hull::\n* Interpolation on Scattered Data::\n* Vector Rotation Matrices::\n\nDelaunay Triangulation\n\n* Plotting the Triangulation::\n* Identifying Points in Triangulation::\n\nImage Processing\n\n* Loading and Saving Images::\n* Displaying Images::\n* Representing Images::\n* Plotting on top of Images::\n* Color Conversion::\n\nAudio Processing\n\n* Audio File Utilities::\n* Audio Device Information::\n* Audio Player::\n* Audio Recorder::\n* Audio Data Processing::\n\nAudio Player\n\n* Playback::\n* Player Properties::\n\nAudio Recorder\n\n* Recording::\n* Data Retrieval::\n* Recorder Properties::\n\nObject Oriented Programming\n\n* Creating a Class::\n* Class Methods::\n* Indexing Objects::\n* Overloading Objects::\n* Inheritance and Aggregation::\n* classdef Classes::\n\nIndexing Objects\n\n* Defining Indexing And Indexed Assignment::\n* Indexed Assignment Optimization::\n\nOverloading Objects\n\n* Function Overloading::\n* Operator Overloading::\n* Precedence of Objects::\n\nclassdef Classes\n\n* Creating a classdef Class::\n* Properties::\n* Methods::\n* Inheritance::\n* Value Classes vs.@: Handle Classes::\n\nGUI Development\n\n* I/O Dialogs::\n* Progress Bar::\n* UI Elements::\n* GUI Utility Functions::\n* User-Defined Preferences::\n* Octave Workspace Windows::\n\nSystem Utilities\n\n* Timing Utilities::\n* Filesystem Utilities::\n* File Archiving Utilities::\n* Networking Utilities::\n* Controlling Subprocesses::\n* Process ID Information::\n* Environment Variables::\n* Current Working Directory::\n* Password Database Functions::\n* Group Database Functions::\n* System Information::\n* Hashing Functions::\n\nNetworking Utilities\n\n* FTP Objects::\n* WWW Access::\n* Base64 and Binary Data Transmission::\n\nPackages\n\n* Installing and Removing Packages::\n* Using Packages::\n* Administrating Packages::\n* Creating Packages::\n\nCreating Packages\n\n* The DESCRIPTION File::\n* The INDEX File::\n* PKG_ADD and PKG_DEL Directives::\n* Missing Components::\n\nExternal Code Interface\n\n* Oct-Files::\n* Mex-Files::\n* Standalone Programs::\n* Java Interface::\n\nOct-Files\n\n* Getting Started with Oct-Files::\n* Matrices and Arrays in Oct-Files::\n* Character Strings in Oct-Files::\n* Cell Arrays in Oct-Files::\n* Structures in Oct-Files::\n* Sparse Matrices in Oct-Files::\n* Accessing Global Variables in Oct-Files::\n* Calling Octave Functions from Oct-Files::\n* Calling External Code from Oct-Files::\n* Allocating Local Memory in Oct-Files::\n* Input Parameter Checking in Oct-Files::\n* Exception and Error Handling in Oct-Files::\n* Documentation and Testing of Oct-Files::\n\nSparse Matrices in Oct-Files\n\n* Array and Sparse Class Differences::\n* Creating Sparse Matrices in Oct-Files::\n* Using Sparse Matrices in Oct-Files::\n\nMex-Files\n\n* Getting Started with Mex-Files::\n* Working with Matrices and Arrays in Mex-Files::\n* Character Strings in Mex-Files::\n* Cell Arrays with Mex-Files::\n* Structures with Mex-Files::\n* Sparse Matrices with Mex-Files::\n* Calling Other Functions in Mex-Files::\n\nJava Interface\n\n* Making Java Classes Available::\n* How to use Java from within Octave::\n* Set up the JVM::\n* Java Interface Functions::\n\nTest and Demo Functions\n\n* Test Functions::\n* Demonstration Functions::\n\nTrouble\n\n* Actual Bugs::                 Bugs we will fix later.\n* Reporting Bugs::\n* How To Get Help with Octave::\n* How to Distinguish Between Octave and Matlab::\n\nReporting Bugs\n\n* Bug Criteria::\n* Bug Tracker::        Where to submit your bug report.\n* Bug Reporting::      How to report a bug effectively.\n* Sending Patches::    How to send a patch for Octave.\n\nInstalling Octave\n\n* Build Dependencies::\n* Running Configure and Make::\n* Compiling Octave with 64-bit Indexing::\n* Installation Problems::\n\nBuild Dependencies\n\n* Obtaining the Dependencies Automatically::\n* Build Tools::\n* External Packages::\n\nGrammar and Parser\n\n* Keywords::\n* Parser::\n@end detailmenu\n@end menu\n\n@c ------------------------------------------------------------------------\n@c Chapters of manual.\n\n@include preface.texi\n@include intro.texi\n@include basics.texi\n@include data.texi\n@include numbers.texi\n@include strings.texi\n@include container.texi\n@include var.texi\n@include expr.texi\n@include eval.texi\n@include stmt.texi\n@include func.texi\n@include errors.texi\n@include debug.texi\n@include io.texi\n@include plot.texi\n@include matrix.texi\n@include arith.texi\n@include linalg.texi\n@include vectorize.texi\n@include nonlin.texi\n@include diagperm.texi\n@include sparse.texi\n@include quad.texi\n@include diffeq.texi\n@include optim.texi\n@include stats.texi\n@include set.texi\n@include poly.texi\n@include interp.texi\n@include geometry.texi\n@include signal.texi\n@include image.texi\n@include audio.texi\n@include oop.texi\n@include gui.texi\n@include system.texi\n@include package.texi\n\n@c ------------------------------------------------------------------------\n@c Appendices start here.\n\n@include external.texi\n@include testfun.texi\n@include obsolete.texi\n@include bugs.texi\n@include install.texi\n@include grammar.texi\n@include gpl.texi\n\n@c ------------------------------------------------------------------------\n@c Indices start here.\n\n@include cp-idx.texi\n@include fn-idx.texi\n@include op-idx.texi\n@include pr-idx.texi\n\n@bye\n"
  },
  {
    "path": "doc/interpreter/oop.txi",
    "content": "@c Copyright (C) 2008-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@c FIXME\n@c For now can't include \"@\" character in the path name, and so name\n@c the example directory without the \"@\"!!\n\n@node Object Oriented Programming\n@chapter Object Oriented Programming\n\nOctave has the ability to create user-defined classes---including the\ncapabilities of operator and function overloading.  Classes can protect\ninternal properties so that they may not be altered accidentally which\nfacilitates data encapsulation.  In addition, rules can be created to address\nthe issue of class precedence in mixed class operations.\n\nThis chapter discusses the means of constructing a user class, how to query and\nset the properties of a class, and how to overload operators and functions.\nThroughout this chapter real code examples are given using a class designed\nfor polynomials.\n\n@menu\n* Creating a Class::\n* Class Methods::\n* Indexing Objects::\n* Overloading Objects::\n* Inheritance and Aggregation::\n* classdef Classes::\n@end menu\n\n@node Creating a Class\n@section Creating a Class\n\nThis chapter illustrates user-defined classes and object oriented programming\nthrough a custom class designed for polynomials.  This class was chosen for\nits simplicity which does not distract unnecessarily from the discussion of\nthe programming features of Octave.  Even so, a bit of background on the goals\nof the polynomial class is necessary before the syntax and techniques of Octave\nobject oriented programming are introduced.\n\nThe polynomial class is used to represent polynomials of the form\n@tex\n$$\na_0 + a_1 x + a_2 x^2 + \\ldots a_n x^n\n$$\n@end tex\n@ifnottex\n\n@example\na0 + a1 * x + a2 * x^2 + @dots{} + an * x^n\n@end example\n\n@end ifnottex\n@noindent\nwhere\n@tex\n$a_0$, $a_1$, etc.\\ are elements of $\\Re$.\n@end tex\n@ifnottex\na0, a1, etc.@: are real scalars.\n@end ifnottex\nThus the polynomial can be represented by a vector\n\n@example\na = [a0, a1, a2, @dots{}, an];\n@end example\n\n@opindex @@ class methods\nThis is a sufficient specification to begin writing the constructor for the\npolynomial class.  All object oriented classes in Octave must be located in a\ndirectory that is the name of the class prepended with the @samp{@@} symbol.\nFor example, the polynomial class will have all of its methods defined in the\n@file{@@polynomial} directory.\n\nThe constructor for the class must be the name of the class itself; in this\nexample the constructor resides in the file @file{@@polynomial/polynomial.m}.\nIdeally, even when the constructor is called with no arguments it should return\na valid object.  A constructor for the polynomial class might look like\n\n@example\n@EXAMPLEFILE(@polynomial/polynomial.m)\n@end example\n\nNote that the return value of the constructor must be the output of the\n@code{class} function.  The first argument to the @code{class} function is a\nstructure and the second is the name of the class itself.  An example of\ncalling the class constructor to create an instance is\n\n@example\np = polynomial ([1, 0, 1]);\n@end example\n\nMethods are defined by m-files in the class directory and can have embedded\ndocumentation the same as any other m-file.  The help for the constructor can\nbe obtained by using the constructor name alone, that is, for the polynomial\nconstructor @code{help polynomial} will return the help string.  Help can be\nrestricted to a particular class by using the class directory name followed\nby the method.  For example, @code{help @@polynomial/polynomial} is another\nway of displaying the help string for the polynomial constructor.  This second\nmeans is the only way to obtain help for the overloaded methods and functions\nof a class.\n\nThe same specification mechanism can be used wherever Octave expects a function\nname.  For example @code{type @@polynomial/disp} will print the code of the\n@code{disp} method of the polynomial class to the screen, and\n@code{dbstop @@polynomial/disp} will set a breakpoint at the first executable\nline of the @code{disp} method of the polynomial class.\n\nTo check whether a variable belongs to a user class, the @code{isobject} and\n@code{isa} functions can be used.  For example:\n\n@example\n@group\np = polynomial ([1, 0, 1]);\nisobject (p)\n  @xresult{} 1\nisa (p, \"polynomial\")\n  @xresult{} 1\n@end group\n@end example\n\n@DOCSTRING(isobject)\n\n@noindent\nThe available methods of a class can be displayed with the @code{methods}\nfunction.\n\n@DOCSTRING(methods)\n\n@noindent\nTo inquire whether a particular method exists for a user class, the\n@code{ismethod} function can be used.\n\n@DOCSTRING(ismethod)\n\n@noindent\nFor a polynomial class it makes sense to have a method to compute its roots.\n\n@example\n@group\n@EXAMPLEFILE(@polynomial/roots.m)\n@end group\n@end example\n\nWe can check for the existence of the @code{roots}-method by calling:\n\n@example\n@group\np = polynomial ([1, 0, 1]);\nismethod (p, \"roots\")\n  @xresult{} 1\n@end group\n@end example\n\n@node Class Methods\n@section Class Methods\n\nThere are a number of basic class methods that can (and should) be defined to\nallow the contents of the classes to be queried and set.  The most basic of\nthese is the @code{disp} method.  The @code{disp} method is used by Octave\nwhenever a class should be displayed on the screen.  Usually this is the result\nof an Octave expression that doesn't end with a semicolon.  If this method is\nnot defined, then Octave won't print anything when displaying the contents of a\nclass which can be confusing.\n\n@noindent\nAn example of a @code{disp} method for the polynomial class might be\n\n@example\n@EXAMPLEFILE(@polynomial/disp.m)\n@end example\n\nTo be consistent with the Octave graphic handle classes, a class should also\ndefine the @code{get} and @code{set} methods.  The @code{get} method accepts\none or two arguments.  The first argument is an object of the appropriate\nclass.  If no second argument is given then the method should return a\nstructure with all the properties of the class.  If the optional second\nargument is given it should be a property name and the specified property\nshould be retrieved.\n\n@example\n@EXAMPLEFILE(@polynomial/get.m)\n@end example\n\n@noindent\nSimilarly, the first argument to the @code{set} method should be an object and\nany additional arguments should be property/value pairs.\n\n@example\n@EXAMPLEFILE(@polynomial/set.m)\n@end example\n\n@noindent\nNote that Octave does not implement pass by reference; Therefore, to modify an\nobject requires an assignment statement using the return value from the\n@code{set} method.\n\n@example\np = set (p, \"poly\", [1, 0, 0, 0, 1]);\n@end example\n\n@noindent\nThe @code{set} method makes use of the @code{subsasgn} method of the class, and\ntherefore this method must also be defined.  The @code{subsasgn} method is\ndiscussed more thoroughly in the next section (@pxref{Indexing Objects}).\n\nFinally, user classes can be considered to be a special type of a structure,\nand they can be saved to a file in the same manner as a structure.  For\nexample:\n\n@example\n@group\np = polynomial ([1, 0, 1]);\nsave userclass.mat p\nclear p\nload userclass.mat\n@end group\n@end example\n\n@noindent\nAll of the file formats supported by @code{save} and @code{load} are supported.\nIn certain circumstances a user class might contain a field that it doesn't\nmake sense to save, or a field that needs to be initialized before it is saved.\nThis can be done with the @code{saveobj} method of the class.\n\n@DOCSTRING(saveobj)\n\n@noindent\n@code{saveobj} is called just prior to saving the class to a file.  Similarly,\nthe @code{loadobj} method is called just after a class is loaded from a file,\nand can be used to ensure that any removed fields are reinserted into the user\nobject.\n\n@DOCSTRING(loadobj)\n\n@node Indexing Objects\n@section Indexing Objects\n\n@menu\n* Defining Indexing And Indexed Assignment::\n* Indexed Assignment Optimization::\n@end menu\n\n@node Defining Indexing And Indexed Assignment\n@subsection Defining Indexing And Indexed Assignment\n\nObjects can be indexed with parentheses or braces, either like\n@code{@var{obj}(@var{idx})} or like @code{@var{obj}@{@var{idx}@}}, or even\nlike @code{@var{obj}(@var{idx}).@var{field}}.  However, it is up to the\nprogrammer to decide what this indexing actually means.  In the case of the\npolynomial class @code{@var{p}(@var{n})} might mean either the coefficient of\nthe @var{n}-th power of the polynomial, or it might be the evaluation of the\npolynomial at @var{n}.  The meaning of this subscripted referencing is\ndetermined by the @code{subsref} method.\n\n@DOCSTRING(subsref)\n\nFor example, this class uses the convention that indexing with @qcode{\"()\"}\nevaluates the polynomial and indexing with @qcode{\"@{@}\"} returns the\n@var{n}-th coefficient (of the @var{n}-th power).  The code for the\n@code{subsref} method looks like\n\n@example\n@EXAMPLEFILE(@polynomial/subsref.m)\n@end example\n\nThe equivalent functionality for subscripted assignments uses the\n@code{subsasgn} method.\n\n@DOCSTRING(subsasgn)\n\n@DOCSTRING(optimize_subsasgn_calls)\n\nNote that the @code{subsref} and @code{subsasgn} methods always receive the\nwhole index chain, while they usually handle only the first element.  It is the\nresponsibility of these methods to handle the rest of the chain (if needed),\nusually by forwarding it again to @code{subsref} or @code{subsasgn}.\n\n@deftypefn {} {@var{n} =} numArgumentsFromSubscript (@var{obj}, @var{idx}, @var{unused})\nOverride @var{nargout} for overloaded @code{subsref} method.\n\n@var{obj} is the object for which the overloaded @code{subsref} method is\ncalled.\n\n@var{idx} is a structure array with fields @samp{type} and @samp{subs}.\nSee @ref{XREFsubsref,,subsref}@: for a description of that structure.\n\nThe third input argument @var{unused} is currently unused.  It is always the\nempty matrix @code{[]}.\n\nThe function must return a scalar integer which will be passed as @var{nargout}\nto the overloaded @code{subsref} method\n\n@seealso{@ref{XREFsubsref,,subsref}, @ref{XREFsubstruct,,substruct}}\n@end deftypefn\n\nIf you wish to use the @code{end} keyword in subscripted expressions of an\nobject, then there must be an @code{end} method defined.  For example, the\n@code{end} method for the polynomial class might look like\n\n@example\n@group\n@EXAMPLEFILE(@polynomial/end.m)\n@end group\n@end example\n\n@noindent\nwhich is a fairly generic @code{end} method that has a behavior similar to the\n@code{end} keyword for Octave Array classes.  An example using the polynomial\nclass is then\n\n@example\n@group\np = polynomial ([1,2,3,4]);\np@{end-1@}\n  @xresult{} 3\n@end group\n@end example\n\nObjects can also be used themselves as the index in a subscripted expression\nand this is controlled by the @code{subsindex} function.\n\n@DOCSTRING(subsindex)\n\nFinally, objects can be used like ranges by providing a @code{colon} method.\n\n@DOCSTRING(colon)\n\n@node Indexed Assignment Optimization\n@subsection Indexed Assignment Optimization\n\nOctave's ubiquitous lazily-copied pass-by-value semantics implies a problem for\nperformance of user-defined @code{subsasgn} methods.  Imagine the following\ncall to @code{subsasgn}\n\n@example\n@group\nss = substruct (\"()\", @{1@});\nx = subsasgn (x, ss, 1);\n@end group\n@end example\n\n@noindent\nwhere the corresponding method looking like this:\n\n@example\n@group\nfunction x = subsasgn (x, ss, val)\n  @dots{}\n  x.myfield (ss.subs@{1@}) = val;\nendfunction\n@end group\n@end example\n\nThe problem is that on entry to the @code{subsasgn} method, @code{x} is still\nreferenced from the caller's scope, which means that the method will first need\nto unshare (copy) @code{x} and @code{x.myfield} before performing the\nassignment.  Upon completing the call, unless an error occurs, the result is\nimmediately assigned to @code{x} in the caller's scope, so that the previous\nvalue of @code{x.myfield} is forgotten.  Hence, the Octave language implies a\ncopy of N elements (N being the size of @code{x.myfield}), where modifying just\na single element would actually suffice.  In other words, a constant-time\noperation is degraded to linear-time one.  This may be a real problem for user\nclasses that intrinsically store large arrays.\n\nTo partially solve the problem Octave uses a special optimization for\nuser-defined @code{subsasgn} methods coded as m-files.  When the method gets\ncalled as a result of the built-in assignment syntax (not a direct\n@code{subsasgn} call as shown above), i.e., @w{@code{x(1) = 1}},  @b{AND} if\nthe @code{subsasgn} method is declared with identical input and output\narguments, as in the example above, then Octave will ignore the copy of\n@code{x} inside the caller's scope; therefore, any changes made to @code{x}\nduring the method execution will directly affect the caller's copy as well.\nThis allows, for instance, defining a polynomial class where modifying a single\nelement takes constant time.\n\nIt is important to understand the implications that this optimization brings.\nSince no extra copy of @code{x} will exist in the caller's scope, it is\n@emph{solely} the callee's responsibility to not leave @code{x} in an invalid\nstate if an error occurs during the execution.  Also, if the method partially\nchanges @code{x} and then errors out, the changes @emph{will} affect @code{x}\nin the caller's scope.  Deleting or completely replacing @code{x} inside\nsubsasgn will not do anything, however, only indexed assignments matter.\n\nSince this optimization may change the way code works (especially if badly\nwritten), a function @code{optimize_subsasgn_calls} is provided to\ncontrol it.  This feature is enabled by default.  Another way to avoid\nthe optimization is to declare subsasgn methods with different output\nand input arguments like this:\n\n@example\n@group\nfunction y = subsasgn (x, ss, val)\n  @dots{}\nendfunction\n@end group\n@end example\n\n@node Overloading Objects\n@section Overloading Objects\n\n@menu\n* Function Overloading::\n* Operator Overloading::\n* Precedence of Objects::\n@end menu\n\n@node Function Overloading\n@subsection Function Overloading\n\nAny Octave function can be overloaded, and this allows an object-specific\nversion of a function to be called as needed.  A pertinent example for the\npolynomial class might be to overload the @code{polyval} function.\n\n@example\n@group\n@EXAMPLEFILE(@polynomial/polyval.m)\n@end group\n@end example\n\nThis function just hands off the work to the normal Octave @code{polyval}\nfunction.  Another interesting example of an overloaded function for the\npolynomial class is the @code{plot} function.\n\n@example\n@group\n@EXAMPLEFILE(@polynomial/plot.m)\n@end group\n@end example\n\n@noindent\nwhich allows polynomials to be plotted in the domain near the region of the\nroots of the polynomial.\n\nFunctions that are of particular interest for overloading are the class\nconversion functions such as @code{double}.  Overloading these functions allows\nthe @code{cast} function to work with a user class.  It can also aid in the\nuse of a class object with methods and functions from other classes since the\nobject can be transformed to the requisite input form for the new function.\nAn example @code{double} function for the polynomial class might look like\n\n@example\n@group\n@EXAMPLEFILE(@polynomial/double.m)\n@end group\n@end example\n\n@node Operator Overloading\n@subsection Operator Overloading\n@cindex addition\n@cindex and operator\n@cindex arithmetic operators\n@cindex boolean expressions\n@cindex boolean operators\n@cindex comparison expressions\n@cindex complex-conjugate transpose\n@cindex division\n@cindex equality operator\n@cindex equality, tests for\n@cindex exponentiation\n@cindex expressions, boolean\n@cindex expressions, comparison\n@cindex expressions, logical\n@cindex greater than operator\n@cindex Hermitian operator\n@cindex less than operator\n@cindex logical expressions\n@cindex logical operators\n@cindex matrix multiplication\n@cindex multiplication\n@cindex negation\n@cindex not operator\n@cindex operators, arithmetic\n@cindex operators, boolean\n@cindex operators, logical\n@cindex operators, relational\n@cindex or operator\n@cindex quotient\n@cindex relational operators\n@cindex subtraction\n@cindex tests for equality\n@cindex transpose\n@cindex transpose, complex-conjugate\n@cindex unary minus\n\n@c Need at least one plaintext sentence here between the @node and @float\n@c table below or the two will overlap due to a bug in Texinfo.\n@c This is not our fault; this *is* a ridiculous kluge.\nThe following table shows, for each built-in numerical operation, the\ncorresponding function name to use when providing an overloaded method for a\nuser class.\n\n@float Table,tab:overload_ops\n@opindex +\n@opindex -\n@opindex .*\n@opindex *\n@opindex ./\n@opindex /\n@opindex .\\\n@opindex \\\n@opindex .^\n@opindex ^\n@opindex <\n@opindex <=\n@opindex >\n@opindex >=\n@opindex ==\n@opindex !=\n@opindex ~=\n@opindex &\n@opindex |\n@opindex !\n@opindex @code{'}\n@opindex @code{.'}\n@opindex :\n@opindex <\n\n@multitable {@code{a(s@math{_1},@dots{},s@math{_n}) = b}} {@code{subsasgn (a, s, b)}} {Complex conjugate transpose}\n@headitem Operation @tab Method @tab Description\n@item @code{a + b} @tab @code{plus (a, b)} @tab Binary addition\n@item @code{a - b} @tab @code{minus (a, b)} @tab Binary subtraction\n@item @code{+a} @tab @code{uplus (a)} @tab Unary addition\n@item @code{-a} @tab @code{uminus (a)} @tab Unary subtraction\n@item @code{a .* b} @tab @code{times (a, b)} @tab Element-wise multiplication\n@item @code{a * b} @tab @code{mtimes (a, b)} @tab Matrix multiplication\n@item @code{a ./ b} @tab @code{rdivide (a, b)} @tab Element-wise right division\n@item @code{a / b} @tab @code{mrdivide (a, b)} @tab Matrix right division\n@item @code{a .\\ b} @tab @code{ldivide (a, b)} @tab Element-wise left division\n@item @code{a \\ b} @tab @code{mldivide (a, b)} @tab Matrix left division\n@item @code{a .^ b} @tab @code{power (a, b)} @tab Element-wise power\n@item @code{a ^ b} @tab @code{mpower (a, b)} @tab Matrix power\n@item @code{a < b} @tab @code{lt (a, b)} @tab Less than\n@item @code{a <= b} @tab @code{le (a, b)} @tab Less than or equal to\n@item @code{a > b} @tab @code{gt (a, b)} @tab Greater than\n@item @code{a >= b} @tab @code{ge (a, b)} @tab Greater than or equal to\n@item @code{a == b} @tab @code{eq (a, b)} @tab Equal to\n@item @code{a != b} @tab @code{ne (a, b)} @tab Not equal to\n@item @code{a & b} @tab @code{and (a, b)} @tab Logical and\n@item @code{a | b} @tab @code{or (a, b)} @tab Logical or\n@item @code{!a} @tab @code{not (a)} @tab Logical not\n@item @code{a'} @tab @code{ctranspose (a)} @tab Complex conjugate transpose\n@item @code{a.'} @tab @code{transpose (a)} @tab Transpose\n@item @code{a:b} @tab @code{colon (a, b)} @tab Two element range\n@item @code{a:b:c} @tab @code{colon (a, b, c)} @tab Three element range\n@item @code{[a, b]} @tab @code{horzcat (a, b)} @tab Horizontal concatenation\n@item @code{[a; b]} @tab @code{vertcat (a, b)} @tab Vertical concatenation\n@item @code{a(s@math{_1},@dots{},s@math{_n})} @tab @code{subsref (a, s)} @tab Subscripted reference\n@item @code{a(s@math{_1},@dots{},s@math{_n}) = b} @tab @code{subsasgn (a, s, b)} @tab Subscripted assignment\n@item @code{b(a)} @tab @code{subsindex (a)} @tab Convert object to index\n@item @code{disp} @tab @code{disp (a)} @tab Object display\n@end multitable\n@caption{Available overloaded operators and their corresponding class method}\n@end float\n\nAn example @code{mtimes} method for the polynomial class might look like\n\n@example\n@group\n@EXAMPLEFILE(@polynomial/mtimes.m)\n@end group\n@end example\n\n@node Precedence of Objects\n@subsection Precedence of Objects\n\nMany functions and operators take two or more arguments and the situation can\neasily arise where these functions are called with objects of different\nclasses.  It is therefore necessary to determine the precedence of which method\nfrom which class to call when there are mixed objects given to a function or\noperator.  To do this the @code{superiorto} and @code{inferiorto} functions can\nbe used\n\n@DOCSTRING(superiorto)\n\n@DOCSTRING(inferiorto)\n\nWith the polynomial class, consider the case\n\n@example\n2 * polynomial ([1, 0, 1]);\n@end example\n\n@noindent\nthat mixes an object of the class @qcode{\"double\"} with an object of the class\n@qcode{\"polynomial\"}.  In this case the return type should be\n@qcode{\"polynomial\"} and so the @code{superiorto} function is used in the class\nconstructor.  In particular the polynomial class constructor would be modified\nto\n\n@example\n@EXAMPLEFILE(@polynomial/polynomial_superiorto.m)\n@end example\n\nNote that user classes @emph{always} have higher precedence than built-in\nOctave types.  Thus, marking the polynomial class higher than the\n@qcode{\"double\"} class is not actually necessary.\n\nWhen confronted with two objects of equal precedence, Octave will use the\nmethod of the object that appears first in the list of arguments.\n\n@node Inheritance and Aggregation\n@section Inheritance and Aggregation\n\nUsing classes to build new classes is supported by Octave through the use of\nboth inheritance and aggregation.\n\nClass inheritance is provided by Octave using the @code{class} function in the\nclass constructor.  As in the case of the polynomial class, the Octave\nprogrammer will create a structure that contains the data fields required by\nthe class, and then call the @code{class} function to indicate that an object\nis to be created from the structure.  Creating a child of an existing object is\ndone by creating an object of the parent class and providing that object as the\nthird argument of the class function.\n\nThis is most easily demonstrated by example.  Suppose the programmer needs a\nFIR filter, i.e., a filter with a numerator polynomial but a denominator of 1.\nIn traditional Octave programming this would be performed as follows.\n\n@example\n@group\n>> x = [some data vector];\n>> n = [some coefficient vector];\n>> y = filter (n, 1, x);\n@end group\n@end example\n\nThe equivalent behavior can be implemented as a class @code{@@FIRfilter}.  The\nconstructor for this class is the file @file{FIRfilter.m} in the class\ndirectory @file{@@FIRfilter}.\n\n@example\n@EXAMPLEFILE(@FIRfilter/FIRfilter.m)\n@end example\n\nAs before, the leading comments provide documentation for the class\nconstructor.  This constructor is very similar to the polynomial class\nconstructor, except that a polynomial object is passed as the third argument to\nthe @code{class} function, telling Octave that the @code{FIRfilter} class will\nbe derived from the polynomial class.  The FIR filter class itself does not\nhave any data fields, but it must provide a struct to the @code{class}\nfunction.  Given that the @code{@@polynomial} constructor will add an element\nnamed @var{polynomial} to the object struct, the @code{@@FIRfilter} just\ninitializes a struct with a dummy field @var{polynomial} which will later be\noverwritten.\n\nNote that the sample code always provides for the case in which no arguments\nare supplied.  This is important because Octave will call a constructor with\nno arguments when loading objects from saved files in order to determine the\ninheritance structure.\n\nA class may be a child of more than one class (@pxref{XREFclass,,class}), and\ninheritance may be nested.  There is no limitation to the number of parents or\nthe level of nesting other than memory or other physical issues.\n\nFor the @code{FIRfilter} class, more control about the object display is\ndesired.  Therefore, the @code{display} method rather than the @code{disp}\nmethod is overloaded (@pxref{Class Methods}).  A simple example might be\n\n@example\n@group\n@EXAMPLEFILE(@FIRfilter/display.m)\n@end group\n@end example\n\nNote that the @code{FIRfilter}'s display method relies on the @code{disp}\nmethod from the @code{polynomial} class to actually display the filter\ncoefficients.  Furthermore, note that in the @code{display} method it makes\nsense to start the method with the line\n@code{@code{printf (\"%s =\", inputname (1))}} to be consistent with the\nrest of Octave which prints the variable name to be displayed followed by the\nvalue.  In general it is not recommended to overload the @code{display}\nfunction.\n\n@DOCSTRING(display)\n\nOnce a constructor and display method exist, it is possible to create an\ninstance of the class.  It is also possible to check the class type and examine\nthe underlying structure.\n\n@example\n@group\noctave:1> f = FIRfilter (polynomial ([1 1 1]/3))\nf.polynomial = 0.33333 + 0.33333 * X + 0.33333 * X ^ 2\noctave:2> class (f)\nans = FIRfilter\noctave:3> isa (f, \"FIRfilter\")\nans =  1\noctave:4> isa (f, \"polynomial\")\nans =  1\noctave:5> struct (f)\nans =\n\n  scalar structure containing the fields:\n\npolynomial = 0.33333 + 0.33333 * X + 0.33333 * X ^ 2\n@end group\n@end example\n\nThe only thing remaining to make this class usable is a method for processing\ndata.  But before that, it is usually desirable to also have a way of changing\nthe data stored in a class.  Since the fields in the underlying struct are\nprivate by default, it is necessary to provide a mechanism to access the\nfields.  The @code{subsref} method may be used for both tasks.\n\n@smallexample\n@EXAMPLEFILE(@FIRfilter/subsref.m)\n@end smallexample\n\nThe @qcode{\"()\"} case allows us to filter data using the polynomial provided\nto the constructor.\n\n@example\n@group\noctave:2> f = FIRfilter (polynomial ([1 1 1]/3));\noctave:3> x = ones (5,1);\noctave:4> y = f(x)\ny =\n\n   0.33333\n   0.66667\n   1.00000\n   1.00000\n   1.00000\n@end group\n@end example\n\nThe @qcode{\".\"} case allows us to view the contents of the polynomial field.\n\n@example\n@group\noctave:1> f = FIRfilter (polynomial ([1 1 1]/3));\noctave:2> f.polynomial\nans = 0.33333 + 0.33333 * X + 0.33333 * X ^ 2\n@end group\n@end example\n\nIn order to change the contents of the object a @code{subsasgn} method is\nneeded.  For example, the following code makes the polynomial field publicly\nwritable\n\n@example\n@group\n@EXAMPLEFILE(@FIRfilter/subsasgn.m)\n@end group\n@end example\n\n@noindent\nso that\n\n@example\n@group\noctave:1> f = FIRfilter ();\noctave:2> f.polynomial = polynomial ([1 2 3])\nf.polynomial = 1 + 2 * X + 3 * X ^ 2\n@end group\n@end example\n\nDefining the @w{FIRfilter}@ class as a child of the polynomial class implies\nthat a @w{FIRfilter}@ object may be used any place that a polynomial object may\nbe used.  This is not a normal use of a filter.  It may be a more sensible\ndesign approach to use aggregation rather than inheritance.  In this case, the\npolynomial is simply a field in the class structure.  A class constructor for\nthe aggregation case might be\n\n@example\n@EXAMPLEFILE(@FIRfilter/FIRfilter_aggregation.m)\n@end example\n\nFor this example only the constructor needs changing, and all other class\nmethods stay the same.\n\n@node classdef Classes\n@section @code{classdef} Classes\n\nSince version 4.0, Octave has limited support for @code{classdef} classes.  In\ncontrast to the aforementioned classes, called @dfn{old style classes} in this\nsection, @code{classdef} classes can be defined within a single m-file.  Other\ninnovations of @code{classdef} classes are:\n\n@itemize @bullet\n@item\n@b{access rights} for properties and methods,\n\n@item\n@b{static methods}, i.e., methods that are independent of an object, and\n\n@item\nthe distinction between @b{value and handle classes}.\n@end itemize\n\nSeveral features have to be added in future versions of Octave to be fully\ncompatible to @sc{matlab}.  An overview of what is missing can be found at\n@url{https://wiki.octave.org/Classdef}.\n\n@menu\n* Creating a classdef Class::\n* Properties::\n* Methods::\n* Inheritance::\n* Value Classes vs.@: Handle Classes::\n@end menu\n\n@node Creating a classdef Class\n@subsection Creating a @code{classdef} Class\n\nA very basic @code{classdef} value class\n(@pxref{Value Classes vs.@: Handle Classes}) is defined by:\n\n@example\n@group\nclassdef some_class\n  properties\n  endproperties\n\n  methods\n  endmethods\nendclassdef\n@end group\n@end example\n\nIn contrast to old style classes, the @code{properties}-@code{endproperties}\nblock as well as the @code{methods}-@code{endmethods} block can be used to\ndefine properties and methods of the class.  Because both blocks are empty,\nthey can be omitted in this particular case.\n\nFor simplicity, a more advanced implementation of a @code{classdef} class is\nshown using the @code{polynomial} example again (@pxref{Creating a Class}):\n\n@example\n@EXAMPLEFILE(polynomial2.m)\n@end example\n\n@noindent\nAn object of class @code{polynomial2} is created by calling the class\nconstructor:\n\n@example\n@group\n>> p = polynomial2 ([1, 0, 1])\n@xresult{} p =\n\n 1 + X ^ 2\n@end group\n@end example\n\n@node Properties\n@subsection Properties\n\nAll class properties must be defined within @code{properties} blocks.  The\ndefinition of a default value for a property is optional and can be omitted.\nThe default initial value for each class property is @code{[]}.\n\nA @code{properties} block can have additional attributes to specify access\nrights or to define constants:\n\n@example\n@group\nclassdef some_class\n  properties (Access = @var{mode})\n    @var{prop1}\n  endproperties\n\n  properties (SetAccess = @var{mode}, GetAccess = @var{mode})\n    @var{prop2}\n  endproperties\n\n  properties (Constant = true)\n    @var{prop3} = pi ()\n  endproperties\n\n  properties\n    @var{prop4} = 1337\n  endproperties\nendclassdef\n@end group\n@end example\n\n@noindent\nwhere @var{mode} can be one of:\n\n@table @code\n@item public\nThe properties can be accessed from everywhere.\n\n@item private\nThe properties can only be accessed from class methods.  Subclasses of that\nclass cannot access them.\n\n@item protected\nThe properties can only be accessed from class methods and from subclasses\nof that class.\n@end table\n\nWhen creating an object of @code{some_class}, @var{prop1} has the default\nvalue @code{[]} and reading from and writing to @var{prop1} is defined by\na single @var{mode}.  For @var{prop2} the read and write access can be set\ndifferently.  Finally, @var{prop3} is a constant property which can only be\ninitialized once within the @code{properties} block.\n\nBy default, in the example @var{prop4}, properties are not constant and have\npublic read and write access.\n\n@DOCSTRING(properties)\n\n@node Methods\n@subsection Methods\n\nAll class methods must be defined within @code{methods} blocks.  An exception\nto this rule is described at the end of this subsection.  Those @code{methods}\nblocks can have additional attributes specifying the access rights or whether\nthe methods are static, i.e., methods that can be called without creating an\nobject of that class.\n\n@example\nclassdef some_class\n  methods\n    function obj = some_class ()\n      disp (\"New instance created.\");\n    endfunction\n\n    function disp (obj)\n      disp (\"Here is some_class.\");\n    endfunction\n  endmethods\n\n  methods (Access = @var{mode})\n    function r = func (obj, r)\n      r = 2 * r;\n    endfunction\n  endmethods\n\n  methods (Static = true)\n    function c = circumference (radius)\n      c = 2 * pi () .* radius;\n    endfunction\n  endmethods\nendclassdef\n@end example\n\nThe constructor of the class is declared in the @code{methods} block and must\nhave the same name as the class and exactly one output argument which is an\nobject of its class.\n\nIt is also possible to overload built-in or inherited methods, like the\n@code{disp} function in the example above to tell Octave how objects of\n@code{some_class} should be displayed (@pxref{Class Methods}).\n\nIn general, the first argument in a method definition is always the object that\nit is called from.  Class methods can either be called by passing the object as\nthe first argument to that method or by calling the object followed by a dot\n(\"@code{.}\") and the method's name with subsequent arguments:\n\n@example\n@group\n>> obj = some_class ();\nNew instance created.\n>> disp (obj);   # both are\n>> obj.disp ();  # equal\n@end group\n@end example\n\nIn @code{some_class}, the method @code{func} is defined within a @code{methods}\nblock setting the @code{Access} attribute to @var{mode}, which is one of:\n\n@table @code\n@item public\nThe methods can be accessed from everywhere.\n\n@item private\nThe methods can only be accessed from other class methods.  Subclasses of that\nclass cannot access them.\n\n@item protected\nThe methods can only be accessed from other class methods and from subclasses\nof that class.\n@end table\n\n@noindent\nThe default access for methods is @code{public}.\n\nFinally, the method @code{circumference} is defined in a static @code{methods}\nblock and can be used without creating an object of @code{some_class}.  This is\nuseful for methods, that do not depend on any class properties.  The class name\nand the name of the static method, separated by a dot (\"@code{.}\"), call this\nstatic method.  In contrast to non-static methods, the object is not passed as\nfirst argument even if called using an object of @code{some_class}.\n\n@example\n@group\n>> some_class.circumference (3)\n@xresult{} ans =  18.850\n>> obj = some_class ();\nNew instance created.\n>> obj.circumference (3)\n@xresult{} ans =  18.850\n@end group\n@end example\n\nAdditionally, class methods can be defined as functions in a folder of the same\nname as the class prepended with the @samp{@@} symbol\n(@pxref{Creating a Class}).  The main @code{classdef} file has to be stored in\nthis class folder as well.\n\n@node Inheritance\n@subsection Inheritance\n\nClasses can inherit from other classes.  In this case all properties and\nmethods of the superclass are inherited to the subclass, considering their\naccess rights.  Use this syntax to inherit from @code{superclass}:\n\n@example\n@group\nclassdef subclass < superclass\n  @dots{}\nendclassdef\n@end group\n@end example\n\n@node Value Classes vs.@: Handle Classes\n@subsection Value Classes vs.@: Handle Classes\n\nThere are two intrinsically different types of @code{classdef} classes, whose\nmajor difference is the behavior regarding variable assignment.  The first type\nare @b{value classes}:\n\n@example\n@group\nclassdef value_class\n  properties\n    prop1\n  endproperties\n\n  methods\n    function obj = set_prop1 (obj, val)\n      obj.prop1 = val;\n    endfunction\n  endmethods\nendclassdef\n@end group\n@end example\n\n@noindent\nAssigning an object of that class to another variable essentially creates a new\nobject:\n\n@example\n@group\n>> a = value_class ();\n>> a.prop1 = 1;\n>> b = a;\n>> b.prop1 = 2;\n>> b.prop1\n@xresult{} ans =  2\n>> a.prop1\n@xresult{} ans =  1\n@end group\n@end example\n\nBut that also means that you might have to assign the output of a method that\nchanges properties back to the object manually:\n\n@example\n@group\n>> a = value_class ();\n>> a.prop1 = 1;\n>> a.set_prop1 (3);\n@xresult{} ans =\n\n<object value_class>\n\n>> ans.prop1\n@xresult{} ans =  3\n>> a.prop1\n@xresult{} ans =  1\n@end group\n@end example\n\nThe second type are @b{handle classes}.  Those classes have to be derived from\nthe abstract @code{handle} class:\n\n@example\n@group\nclassdef handle_class < handle\n  properties\n    prop1\n  endproperties\n\n  methods\n    function set_prop1 (obj, val)\n      obj.prop1 = val;\n    endfunction\n  endmethods\nendclassdef\n@end group\n@end example\n\nIn the following example, the variables @code{a} and @code{b} refer to the\nvery same object of class @code{handle_class}:\n\n@example\n@group\n>> a = handle_class ();\n>> a.prop1 = 1;\n>> b = a;\n>> b.prop1 = 2;\n>> b.prop1\n@xresult{} ans =  2\n>> a.prop1\n@xresult{} ans =  2\n@end group\n@end example\n\nObject properties that are modified by a method of an handle class are changed\npersistently:\n\n@example\n@group\n>> a.set_prop1 (3);\n>> a.prop1\n@xresult{} ans =  3\n@end group\n@end example\n"
  },
  {
    "path": "doc/interpreter/op-idx.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Operator Index\n@unnumbered Operator Index\n\n@printindex op\n"
  },
  {
    "path": "doc/interpreter/optim.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Optimization\n@chapter Optimization\n\nOctave comes with support for solving various kinds of optimization\nproblems.  Specifically Octave can solve problems in Linear Programming,\nQuadratic Programming, Nonlinear Programming, and Linear Least Squares\nMinimization.\n\n@menu\n* Linear Programming::\n* Quadratic Programming::\n* Nonlinear Programming::\n* Linear Least Squares::\n@end menu\n\n@c @cindex linear programming\n@cindex quadratic programming\n@cindex nonlinear programming\n@cindex optimization\n@cindex LP\n@cindex QP\n@cindex NLP\n\n@node Linear Programming\n@section Linear Programming\n\nOctave can solve Linear Programming problems using the @code{glpk}\nfunction.  That is, Octave can solve\n\n@tex\n$$\n  \\min_x c^T x\n$$\n@end tex\n@ifnottex\n\n@example\nmin C'*x\n@end example\n\n@end ifnottex\nsubject to the linear constraints\n@tex\n$Ax = b$ where $x \\geq 0$.\n@end tex\n@ifnottex\n@math{A*x = b} where @math{x @geq{} 0}.\n@end ifnottex\n\n@noindent\nThe @code{glpk} function also supports variations of this problem.\n\n@DOCSTRING(glpk)\n\n@node Quadratic Programming\n@section Quadratic Programming\n\nOctave can also solve Quadratic Programming problems, this is\n@tex\n$$\n \\min_x {1 \\over 2} x^T H x + x^T q\n$$\n@end tex\n@ifnottex\n\n@example\nmin 0.5 x'*H*x + x'*q\n@end example\n\n@end ifnottex\nsubject to\n@tex\n$$\n A x = b \\qquad lb \\leq x \\leq ub \\qquad A_{lb} \\leq A_{in} x \\leq A_{ub}\n$$\n@end tex\n@ifnottex\n\n@example\n@group\n     A*x = b\n     lb <= x <= ub\n     A_lb <= A_in*x <= A_ub\n@end group\n@end example\n\n@end ifnottex\n\n@DOCSTRING(qp)\n\n@DOCSTRING(pqpnonneg)\n\n@node Nonlinear Programming\n@section Nonlinear Programming\n\nOctave can also perform general nonlinear minimization using a\nsuccessive quadratic programming solver.\n\n@DOCSTRING(sqp)\n\n@node Linear Least Squares\n@section Linear Least Squares\n\nOctave also supports linear least squares minimization.  That is,\nOctave can find the parameter @math{b} such that the model\n@tex\n$y = xb$\n@end tex\n@ifnottex\n@math{y = x*b}\n@end ifnottex\nfits data @math{(x,y)} as well as possible, assuming zero-mean\nGaussian noise.  If the noise is assumed to be isotropic the problem\ncan be solved using the @samp{\\} or @samp{/} operators, or the @code{ols}\nfunction.  In the general case where the noise is assumed to be anisotropic\nthe @code{gls} is needed.\n\n@DOCSTRING(ols)\n\n@DOCSTRING(gls)\n\n@DOCSTRING(lsqnonneg)\n\n@DOCSTRING(lscov)\n\n@DOCSTRING(optimset)\n\n@DOCSTRING(optimget)\n"
  },
  {
    "path": "doc/interpreter/package.txi",
    "content": "@c Copyright (C) 2007-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Packages\n@chapter Packages\n\nSince Octave is Free Software users are encouraged to share their\nprograms with others.  To aid this sharing Octave supports the\ninstallation of extra packages maintained by the Octave community at\n@url{https://packages.octave.org}.\n\n@menu\n* Background Information::\n* Installing and Removing Packages::\n* Using Packages::\n* Administrating Packages::\n* Creating Packages::\n@end menu\n\n@findex pkg\n@node Background Information\n@section Background Information\n\nPackages can be installed globally (i.e., for all users of the system) or\nlocally (i.e., for the current user only).\n\nGlobal packages are installed by default in a system-wide location.  This is\nusually a subdirectory of the folder where Octave itself is installed.\nTherefore, Octave needs write access to this folder to install global packages,\nwhich is usually only available when Octave is run with administrative\nprivileges, such as when run as root (or superuser) on Unix-like systems, or\nrun with elevated privileges (\"Run as administrator\") on Windows.\n\nIn contrast, local packages are installed by default in the user's home\ndirectory (or user profile on Windows) and are only available to that specific\nuser.  Usually, they can be installed without administrative privileges.\n\nWhen Octave is running with administrative privileges, @code{pkg} will install\npackages to the global package location by default.  Otherwise, packages will\nbe installed to the local location by default.  The user can override this\ndefault installation location with optional arguments (@option{-local} or\n@option{-global}) as described below.  The currently used default package\ninstallation location can be queried with @code{pkg prefix}.\n\nFor global and local packages, there are separate databases holding the\ninformation about the installed packages.  If some package is installed\nglobally as well as locally, the local installation takes precedence over\n(\"shadows\") the global one.  Which (global or local) package installation is\nused can also be manipulated by using prefixes and/or using the\n@samp{local_list} input argument.  Using these mechanisms, several different\nreleases of the same package can be installed side by side as well (but cannot\nbe loaded simultaneously).\n\nPackages might depend on external software and/or other packages.  To be able\nto install such packages, these dependencies should be installed beforehand.\nA package that depends on other package(s) can still be installed using the\n@option{-nodeps} flag.  The effects of unsatisfied dependencies on external\nsoftware---like libraries---depends on the individual package.\n\nPackages must be loaded before they can be used.  When loading a package,\nOctave performs the following tasks:\n\n@enumerate\n@item\nIf the package depends on other packages (and @code{pkg load} is called without\nthe @option{-nodeps} option), the package is not loaded immediately.  Instead,\nthose dependencies are loaded first (recursively if needed).\n\n@item\nWhen all dependencies are satisfied, the package's subdirectories are added to\nthe search path.\n@end enumerate\n\nThis load order leads to functions that are provided by dependencies being\npotentially shadowed by functions of the same name that are provided by\ntop-level packages.\n\nEach time, a package is added to the search path, initialization script(s) for\nthe package are automatically executed if they are provided by the package.\n\n@node Installing and Removing Packages\n@section Installing and Removing Packages\n\nAssuming a package is available in the file @file{image-1.0.0.tar.gz}\nit can be installed from the Octave prompt with the command\n\n@example\npkg install image-1.0.0.tar.gz\n@end example\n\n@noindent\nIf the package is installed successfully nothing will be printed on\nthe prompt, but if a warning or error occurred during installation it\nwill be reported.  It is possible to install several packages at once\nby writing several package file names after the @code{pkg install}\ncommand.  If a different version of the package is already installed it\nwill be removed prior to installing the new package.  This makes it\neasy to upgrade and downgrade the version of a package, but makes it\nimpossible to have several versions of the same package installed at\nonce.\n\nTo see which packages are installed type\n\n@example\n@group\npkg list\n@print{} Package Name  | Version | Installation directory\n@print{} --------------+---------+-----------------------\n@print{}        image *|   1.0.0 | /home/jwe/octave/image-1.0.0\n@end group\n@end example\n\n@noindent\nIn this case, version 1.0.0 of the @code{image} package is installed.\nThe @qcode{'*'} character next to the package name shows that the image\npackage is loaded and ready for use.\n\nIt is possible to remove a package from the system using the\n@code{pkg uninstall} command like this\n\n@example\npkg uninstall image\n@end example\n\n@noindent\nIf the package is removed successfully nothing will be printed in the\nprompt, but if a warning or error occurred it will be reported.  It\nshould be noted that the package file used for installation is not\nneeded for removal, and that only the package name as reported by\n@code{pkg list} should be used when removing a package.  It is possible\nto remove several packages at once by writing several package names\nafter the @code{pkg uninstall} command.\n\nTo minimize the amount of code duplication between packages, it is\npossible that one package depends on another one.  If a package\ndepends on another, it will check if that package is installed\nduring installation.  If it is not, an error will be reported and\nthe package will not be installed.  This behavior can be disabled\nby passing the @option{-nodeps} flag to the @code{pkg install}\ncommand\n\n@example\npkg install -nodeps my_package_with_dependencies.tar.gz\n@end example\n\n@noindent\nSince the installed package expects its dependencies to be installed\nit may not function correctly.  Because of this it is not recommended\nto disable dependency checking.\n\n@DOCSTRING(pkg)\n\n@node Using Packages\n@section Using Packages\n\nBy default installed packages are not available from the Octave prompt,\nbut it is possible to control this using the @code{pkg load} and\n@code{pkg unload} commands.  The functions from a package can be\nadded to the Octave path by typing\n\n@example\npkg load package_name\n@end example\n\n@noindent\nwhere @code{package_name} is the name of the package to be added\nto the path.\n\nIn much the same way a package can be removed from the Octave path by\ntyping\n\n@example\npkg unload package_name\n@end example\n\n@node Administrating Packages\n@section Administrating Packages\n\nIt is possible to make both per-user (local) and system-wide (global)\ninstallations of a package.  If the user performing the installation is\n@code{root} (or Administrator with elevated privileges on Windows), the\npackages by default install in a system-wide directory that defaults to\n@file{@var{OCTAVE_HOME}/share/octave/packages/}.  If the user is not\n@code{root} (or Octave is running without elevated privileges),\npackages are installed locally.  The default installation directory for\nlocal packages is\n@file{@var{user_data_dir}/octave/@var{OCTAVE_API_VERSION}/packages}.\nPackages will be installed in a subdirectory of the installation\ndirectory that will be named after the package.  It is possible to\nchange the installation directory by using the @code{pkg prefix}\ncommand:\n\n@example\npkg prefix new_installation_directory\n@end example\n\n@noindent\nThe current installation directory can be retrieved by typing\n\n@example\ncurrent_installation_directory = pkg (\"prefix\")\n@end example\n\nThe package manager stores some information about the installed\npackages in configuration files.  For per-user (local) packages, this\ninformation is stored in the file\n@file{@var{user_config_dir}/octave/@var{OCTAVE_API_VERSION}/octave_packages}\nby default.  For system-wide (global) installations, it is stored in\n@file{@var{OCTAVE_HOME}/share/octave/octave_packages}.  The path to the\nper-user file can be changed with the @code{pkg local_list} command:\n\n@example\npkg local_list /path/to/new_file\n@end example\n\n@noindent\nFor system-wide installations, this can be changed in the same way\nusing the @code{pkg global_list} command.  If these commands are called\nwithout a new path, the current path will be returned.  To retain these\nsettings between sessions, they can be set in one of the startup files,\n@pxref{Startup Files}.\n\n@node Creating Packages\n@section Creating Packages\n\nInternally a package is simply a gzipped tar file that contains a\ntop level directory of any given name.  This directory will in the\nfollowing be referred to as @code{package} and may contain the\nfollowing files:\n\n@table @code\n@item package/CITATION\nThis is am optional file describing instructions on how to cite\nthe package for publication.  It will be displayed verbatim by the\nfunction @code{citation}.\n\n@item package/COPYING\nThis is a required file containing the license of the package.  No\nrestrictions is made on the license in general.  If however the\npackage contains dynamically linked functions the license must be\ncompatible with the GNU General Public License.\n\n@item package/DESCRIPTION\nThis is a required file containing information about the package.\n@xref{The DESCRIPTION File}, for details on this file.\n\n@item package/ChangeLog\nThis is an optional file describing all the changes made to the\npackage source files.\n\n@item package/INDEX\nThis is an optional file describing the functions provided by the\npackage.  If this file is not given then one with be created\nautomatically from the functions in the package and the\n@code{Categories} keyword in the @file{DESCRIPTION} file.\n@xref{The INDEX File}, for details on this file.\n\n@item package/NEWS\nThis is an optional file describing all user-visible changes worth\nmentioning.  As this file increases on size, old entries can be moved\ninto @file{package/ONEWS}.\n\n@item package/ONEWS\nThis is an optional file describing old entries from the @file{NEWS} file.\n\n@cindex PKG_ADD\n@anchor{XREFPKG_ADD}\n@item package/PKG_ADD\nAn optional file that includes commands that are run when the package\nis added to the users path.  Note that @w{@code{PKG_ADD}}@ directives in the\nsource code of the package will also be added to this file by the\nOctave package manager.  Note that symbolic links are to be avoided in\npackages, as symbolic links do not exist on some file systems, and so\na typical use for this file is the replacement of the symbolic link\n\n@example\nln -s foo.oct bar.oct\n@end example\n\n@noindent\nwith an autoload directive like\n\n@example\nautoload ('bar', which ('foo'));\n@end example\n\n@noindent\n@xref{PKG_ADD and PKG_DEL Directives}, for details on\n@w{@code{PKG_ADD}}@ directives.\n\n@cindex PKG_DEL\n@anchor{XREFPKG_DEL}\n@item package/PKG_DEL\nAn optional file that includes commands that are run when the package\nis removed from the users path.  Note that @w{@code{PKG_DEL}}@ directives in\nthe source code of the package will also be added to this file by the\nOctave package manager.\n@xref{PKG_ADD and PKG_DEL Directives}, for details on\n@w{@code{PKG_DEL}}@ directives.\n\n@item package/pre_install.m\nThis is an optional function that is run prior to the installation of a\npackage.  This function is called with a single argument, a struct with\nfields names after the data in the @file{DESCRIPTION}, and the paths where\nthe package functions will be installed.\n\n@item package/post_install.m\nThis is an optional function that is run after the installation of a\npackage.  This function is called with a single argument, a struct with\nfields names after the data in the @file{DESCRIPTION}, and the paths where\nthe package functions were installed.\n\n@item package/on_uninstall.m\nThis is an optional function that is run prior to the removal of a\npackage.  This function is called with a single argument, a struct with\nfields names after the data in the @file{DESCRIPTION}, the paths where\nthe package functions are installed, and whether the package is currently\nloaded.\n@end table\n\nBesides the above mentioned files, a package can also contain one or\nmore of the following directories:\n\n@table @code\n@item package/inst\nAn optional directory containing any files that are directly installed\nby the package.  Typically this will include any @code{m}-files.\n\n@item package/src\nAn optional directory containing code that must be built prior to the\npackages installation.  The Octave package manager will execute\n@file{./configure} in this directory if this script exists, and will\nthen call @code{make} if a file @file{Makefile} exists in this\ndirectory.  @code{make install} will however not be called.  The\nenvironment variables @env{MKOCTFILE}, @w{@env{OCTAVE_CONFIG}}, and\n@env{OCTAVE} will be set to the full paths of the programs\n@code{mkoctfile}, @code{octave-config}, and @code{octave}, respectively,\nof the correct version when @code{configure} and @code{make} are\ncalled.  If a file called @code{FILES} exists all files listed there\nwill be copied to the @code{inst} directory, so they also will be\ninstalled.  If the @code{FILES} file doesn't exist, @file{src/*.m} and\n@file{src/*.oct} will be copied to the @code{inst} directory.\n\n@item package/doc\nAn optional directory containing documentation for the package.  The\nfiles in this directory will be directly installed in a sub-directory\nof the installed package for future reference.\n\nIf the Octave GUI is running, the optional Qt help file\n@file{package/doc/pkg-name.qch} is added to the documentation browser\nwhile loading the package.  The help file is removed from the documentation\nbrowser when the package is unloaded.\n\n@item package/bin\nAn optional directory containing files that will be added to the\nOctave @w{@env{EXEC_PATH}}@ when the package is loaded.  This might contain\nexternal scripts, etc., called by functions within the package.\n@end table\n\n@menu\n* The DESCRIPTION File::\n* The INDEX File::\n* PKG_ADD and PKG_DEL Directives::\n* Missing Components::\n@end menu\n\n@node The DESCRIPTION File\n@subsection The DESCRIPTION File\n\nThe @file{DESCRIPTION} file contains various information about the\npackage, such as its name, author, and version.  This file has a very\nsimple format\n\n@itemize\n@item\nLines starting with @samp{#} are comments.\n\n@item\nLines starting with a blank character are continuations from the\nprevious line.\n\n@item\nEverything else is of the form @code{NameOfOption: ValueOfOption}.\n@end itemize\n\n@noindent\nThe following is a simple example of a @file{DESCRIPTION} file\n\n@example\n@group\nName: The name of my package\nVersion: 1.0.0\nDate: 2007-18-04\nAuthor: The name (and possibly email) of the package author.\nMaintainer: The name (and possibly email) of the current\n package maintainer.\nTitle: The title of the package\nDescription: A short description of the package.  If this\n description gets too long for one line it can continue\n on the next by adding a space to the beginning of the\n following lines.\nLicense: GPLv3+\n@end group\n@end example\n\nThe package manager currently recognizes the following keywords\n\n@table @code\n@item Name\nName of the package.\n\n@item Version\nVersion of the package.  A package version is typically digits separated by\ndots but may also contain @samp{+}, @samp{-}, @samp{~}, and alphanumeric\ncharacters (in the \"C\" locale).  For example, @qcode{\"2.1.0+\"} could indicate\na development version of a package.\n@c regexp in get_description.m:is_valid_pkg_version_string\nVersions are compared using @ref{XREFcompare_versions,,compare_versions}.\n\n@item Date\nDate of last update.\n\n@item Author\nOriginal author of the package.\n\n@item Maintainer\nMaintainer of the package.\n\n@item Title\nA one line description of the package.\n\n@item Description\nA one paragraph description of the package.\n\n@item Categories\nOptional keyword describing the package (if no @file{INDEX} file is\ngiven this is mandatory).\n\n@item Problems\nOptional list of known problems.\n\n@item Url\nOptional URL to the homepage or repository related to the package.\n\n@item Tracker\nOptional URL to the bug tracker related to the package.  It is highly\nencouraged that maintainers utilize a dedicated tracker for reporting issues\nrelated to the package's functionality in order to keep Octave's bug tracker at\nSavannah.org less bloated and solely for core Octave bug reports.\n\n@item Depends\nA list of other Octave packages that this package depends on.  This can include\ndependencies on particular versions, with the following format:\n\n@example\nDepends: package (>= 1.0.0)\n@end example\n\n@noindent\nPossible operators are @code{<}, @code{<=}, @code{==}, @code{>=} or @code{>}.\nIf the part of the dependency in @code{()} is missing, any version of the\npackage is acceptable.  Multiple dependencies can be defined as a comma\nseparated list.  This can be used to define a range of versions of a particular\npackage:\n\n@example\nDepends: package (>= 1.0.0), package (< 1.5.0)\n@end example\n\n@noindent\nIt is also possible to depend on particular versions of Octave core:\n\n@example\nDepends: octave (>= 3.8.0)\n@end example\n\n@item License\nAn optional short description of the used license (e.g., GPL version 3\nor newer).  This is optional since the file @file{COPYING} is mandatory.\n\n@item SystemRequirements\nThese are the external install dependencies of the package and are not\nchecked by the package manager.  This is here as a hint to the\ndistribution packager.  They follow the same conventions as the\n@code{Depends} keyword.\n\n@item BuildRequires\nThese are the external build dependencies of the package and are not checked by\nthe package manager.  This is here as a hint to the distribution packager.\nThey follow the same conventions as the @code{Depends} keyword.  Note that in\ngeneral, packaging systems such as @code{rpm} or @code{deb} autoprobe the\ninstall dependencies from the build dependencies, and therefore a\n@code{BuildRequires} dependency usually removes the need for a\n@code{SystemRequirements} dependency.\n\n@end table\n\n@noindent\nThe developer is free to add additional arguments to the\n@file{DESCRIPTION} file for their own purposes.  One further detail to\naid the packager is that the @code{SystemRequirements} and\n@code{BuildRequires} keywords can have a distribution dependent section,\nand the automatic build process will use these.  An example of the\nformat of this is\n\n@example\nBuildRequires: libtermcap-devel [Mandriva] libtermcap2-devel\n@end example\n\n@noindent\nwhere the first package name will be used as a default and if the\nRPMs are built on a Mandriva distribution, then the second package\nname will be used instead.\n\n@node The INDEX File\n@subsection The INDEX File\n\nThe optional @file{INDEX} file provides a categorical view of the\nfunctions in the package.  This file has a very simple format\n\n@itemize\n@item Lines beginning with @samp{#} are comments.\n\n@item The first non-comment line should look like this\n\n@example\ntoolbox >> Toolbox name\n@end example\n\n@item Lines beginning with an alphabetical character indicates a new\ncategory of functions.\n\n@item Lines starting with a white space character indicate that the\nfunction names on the line belong to the last mentioned category.\n@end itemize\n\n@noindent\nThe format can be summarized with the following example:\n\n@example\n@group\n# A comment\ntoolbox >> Toolbox name\nCategory Name 1\n function1 function2 function3\n function4\nCategory Name 2\n function2 function5\n@end group\n@end example\n\nIf you wish to refer to a function that users might expect\nto find in your package but is not there, providing a work around or\npointing out that the function is available elsewhere, you can use:\n\n@example\nfn = workaround description\n@end example\n\n@noindent\nThis workaround description will not appear when listing functions in the\npackage with @code{pkg describe} but they will be published\nin the HTML documentation online.\nWorkaround descriptions can use any HTML markup, but\nkeep in mind that it will be enclosed in a bold-italic environment.\nFor the special case of:\n\n@example\nfn = use <code>alternate expression</code>\n@end example\n\n@noindent\nthe bold-italic is automatically suppressed.  You will need\nto use @code{<code>} even in references:\n\n@example\nfn = use <a href=\"someothersite.html\"><code>fn</code></a>\n@end example\n\n@noindent\nSometimes functions are only partially compatible, in which\ncase you can list the non-compatible cases separately.  To\nrefer to another function in the package, use @code{<f>fn</f>}.\nFor example:\n\n@example\neig (a, b) = use <f>qz</f>\n@end example\n\n@noindent\nSince sites may have many missing functions, you can define\na macro rather than typing the same link over and again.\n\n@example\n$id = expansion\n@end example\n\n@noindent\ndefines the macro id.  You can use @code{$id} anywhere in the\ndescription and it will be expanded.  For example:\n\n@example\n@group\n$TSA = see <a href=\"link_to_spctools\">SPC Tools</a>\narcov = $TSA <code>armcv</code>\n@end group\n@end example\n\n@noindent\nid is any string of letters, numbers and @code{_}.\n\n@node PKG_ADD and PKG_DEL Directives\n@subsection PKG_ADD and PKG_DEL Directives\n\nIf the package contains files called @w{@code{PKG_ADD}}@ or @w{@code{PKG_DEL}}@\nthe commands in these files will be executed when the package is\nadded or removed from the users path.  In some situations such files\nare a bit cumbersome to maintain, so the package manager supports\nautomatic creation of such files.  If a source file in the package\ncontains a @w{@code{PKG_ADD}}@ or @w{@code{PKG_DEL}}@ directive they will be\nadded to either the @w{@code{PKG_ADD}}@ or @w{@code{PKG_DEL}}@ files.\n\nIn @code{m}-files a @w{@code{PKG_ADD}}@ directive looks like this\n\n@example\n## PKG_ADD: some_octave_command\n@end example\n\n@noindent\nSuch lines should be added before the @code{function} keyword.\nIn C++ files a @w{@code{PKG_ADD}}@ directive looks like this\n\n@example\n// PKG_ADD: some_octave_command\n@end example\n\n@noindent\nIn both cases @code{some_octave_command} should be replaced by the\ncommand that should be placed in the @w{@code{PKG_ADD}}@ file.\n@w{@code{PKG_DEL}}@ directives work in the same way, except the\n@w{@code{PKG_ADD}}@ keyword is replaced with @w{@code{PKG_DEL}}@ and the\ncommands get added to the @w{@code{PKG_DEL}}@ file.\n\n@node Missing Components\n@subsection Missing Components\n\nIf a package relies on a component, such as another Octave package, that may\nnot be present it may be useful to install a function which informs users what\nto do when a particular component is missing.  The function must be written by\nthe package maintainer and registered with Octave using\n@code{missing_component_hook}.\n\n@DOCSTRING(missing_component_hook)\n"
  },
  {
    "path": "doc/interpreter/plot.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Plotting\n@chapter Plotting\n@cindex plotting\n@cindex graphics\n\n@menu\n* Introduction to Plotting::\n* High-Level Plotting::\n* Graphics Data Structures::\n* Advanced Plotting::\n@end menu\n\n@node Introduction to Plotting\n@section Introduction to Plotting\n\nEarlier versions of Octave provided plotting through the use of gnuplot.  This\ncapability is still available.  But, newer versions of Octave offer more modern\nplotting capabilities using OpenGL@.  Which plotting system is used is\ncontrolled by the @code{graphics_toolkit} function.  @xref{Graphics Toolkits}.\n\nThe function call @code{graphics_toolkit (\"qt\")} selects the Qt/OpenGL system,\n@code{graphics_toolkit (\"fltk\")} selects the FLTK/OpenGL system, and\n@code{graphics_toolkit (\"gnuplot\")} selects the gnuplot system.  The three\nsystems may be used selectively through the use of the @code{graphics_toolkit}\nproperty of the graphics handle for each figure.  This is explained in\n@ref{Graphics Data Structures}.\n\n@strong{Caution:} The OpenGL-based toolkits use single precision variables\ninternally which limits the maximum value that can be displayed to\napproximately @math{10^{38}}.  If your data contains larger values you must use\nthe gnuplot toolkit which supports values up to @math{10^{308}}.  Similarly,\nsingle precision variables can accurately represent only 6-9 base10 digits.  If\nyour data contains very fine differences (approximately 1e-8) these cannot be\nresolved with the OpenGL-based graphics toolkits and the gnuplot toolkit\nis required.\n\n@strong{Note:} The gnuplot graphics toolkit uses the third party program\ngnuplot for plotting.  The communication from Octave to gnuplot is done via a\none-way pipe.  This has implications for performance and functionality.\nPerformance is significantly slower because the entire data set, which could\nbe many megabytes, must be passed to gnuplot over the pipe.  Functionality\nis negatively affected because the pipe is one-way from Octave to gnuplot.\nOctave has no way of knowing about user interactions with the plot window (be\nit resizing, moving, closing, or anything else).  It is recommended not to\ninteract with (or close) a gnuplot window if you will access the figure from\nOctave later on.\n\n@node High-Level Plotting\n@section High-Level Plotting\n@cindex plotting, high-level\n\nOctave provides simple means to create many different types of two- and\nthree-dimensional plots using high-level functions.\n\nIf you need more detailed control, @pxref{Graphics Data Structures} and\n@ref{Advanced Plotting}.\n\n@menu\n* Two-Dimensional Plots::\n* Three-Dimensional Plots::\n* Plot Annotations::\n* Multiple Plots on One Page::\n* Multiple Plot Windows::\n* Manipulation of Plot Objects::\n* Manipulation of Plot Windows::\n* Use of the \"interpreter\" Property::\n* Printing and Saving Plots::\n* Interacting with Plots::\n* Test Plotting Functions::\n@end menu\n\n@node Two-Dimensional Plots\n@subsection Two-Dimensional Plots\n\n@menu\n* Axis Configuration::\n* Two-dimensional Function Plotting::\n* Two-dimensional Geometric Shapes::\n@end menu\n\nThe @code{plot} function allows you to create simple x-y plots with\nlinear axes.  For example,\n\n@example\n@group\nx = -10:0.1:10;\nplot (x, sin (x));\nxlabel (\"x\");\nylabel (\"sin (x)\");\ntitle (\"Simple 2-D Plot\");\n@end group\n@end example\n\n@noindent\ndisplays a sine wave shown in @ref{fig:plot}.  On most systems, this\ncommand will open a separate plot window to display the graph.\n\n@float Figure,fig:plot\n@center @image{plot,4in}\n@caption{Simple Two-Dimensional Plot.}\n@end float\n\n@DOCSTRING(plot)\n\nThe @code{plotyy} function may be used to create a plot with two\nindependent y axes.\n\n@DOCSTRING(plotyy)\n\nThe functions @code{semilogx}, @code{semilogy}, and @code{loglog} are\nsimilar to the @code{plot} function, but produce plots in which one or\nboth of the axes use log scales.\n\n@DOCSTRING(semilogx)\n\n@DOCSTRING(semilogy)\n\n@DOCSTRING(loglog)\n\nThe functions @code{bar}, @code{barh}, @code{stairs}, and @code{stem}\nare useful for displaying discrete data.  For example,\n\n@example\n@group\nrandn (\"state\", 1);\nhist (randn (10000, 1), 30);\nxlabel (\"Value\");\nylabel (\"Count\");\ntitle (\"Histogram of 10,000 normally distributed random numbers\");\n@end group\n@end example\n\n@noindent\nproduces the histogram of 10,000 normally distributed random numbers\nshown in @ref{fig:hist}.  Note that, @code{randn (\"state\", 1);}, initializes\nthe random number generator for @code{randn} to a known value so that the\nreturned values are reproducible; This guarantees that the figure produced\nis identical to the one in this manual.\n\n@float Figure,fig:hist\n@center @image{hist,4in}\n@caption{Histogram.}\n@end float\n\n@DOCSTRING(bar)\n\n@DOCSTRING(barh)\n\n@DOCSTRING(hist)\n\n@DOCSTRING(stemleaf)\n\n@DOCSTRING(printd)\n\n@DOCSTRING(stairs)\n\n@DOCSTRING(stem)\n\n@DOCSTRING(stem3)\n\n@DOCSTRING(scatter)\n\n@DOCSTRING(plotmatrix)\n\n@DOCSTRING(pareto)\n\n@DOCSTRING(rose)\n\nThe @code{contour}, @code{contourf} and @code{contourc} functions\nproduce two-dimensional contour plots from three-dimensional data.\n\n@DOCSTRING(contour)\n\n@DOCSTRING(contourf)\n\n@DOCSTRING(contourc)\n\n@DOCSTRING(contour3)\n\nThe @code{errorbar}, @code{semilogxerr}, @code{semilogyerr}, and\n@code{loglogerr} functions produce plots with error bar markers.  For\nexample,\n\n@example\n@group\nrand (\"state\", 2);\nx = 0:0.1:10;\ny = sin (x);\nlerr = 0.1 .* rand (size (x));\nuerr = 0.1 .* rand (size (x));\nerrorbar (x, y, lerr, uerr);\naxis ([0, 10, -1.1, 1.1]);\nxlabel (\"x\");\nylabel (\"sin (x)\");\ntitle (\"Errorbar plot of sin (x)\");\n@end group\n@end example\n\n@noindent\nproduces the figure shown in @ref{fig:errorbar}.\n\n@float Figure,fig:errorbar\n@center @image{errorbar,4in}\n@caption{Errorbar plot.}\n@end float\n\n@DOCSTRING(errorbar)\n\n@DOCSTRING(semilogxerr)\n\n@DOCSTRING(semilogyerr)\n\n@DOCSTRING(loglogerr)\n\nFinally, the @code{polar} function allows you to easily plot data in\npolar coordinates.  However, the display coordinates remain rectangular\nand linear.  For example,\n\n@example\n@group\npolar (0:0.1:10*pi, 0:0.1:10*pi);\ntitle (\"Example polar plot from 0 to 10*pi\");\n@end group\n@end example\n\n@noindent\nproduces the spiral plot shown in @ref{fig:polar}.\n\n@float Figure,fig:polar\n@center @image{polar,4in}\n@caption{Polar plot.}\n@end float\n\n@DOCSTRING(polar)\n\n@DOCSTRING(pie)\n\n@DOCSTRING(pie3)\n\n@DOCSTRING(quiver)\n\n@DOCSTRING(quiver3)\n\n@DOCSTRING(streamribbon)\n\n@DOCSTRING(streamtube)\n\n@DOCSTRING(ostreamtube)\n\n@DOCSTRING(streamline)\n\n@DOCSTRING(stream2)\n\n@DOCSTRING(stream3)\n\n@DOCSTRING(compass)\n\n@DOCSTRING(feather)\n\n@DOCSTRING(pcolor)\n\n@DOCSTRING(area)\n\n@DOCSTRING(fill)\n\n@DOCSTRING(fill3)\n\n@DOCSTRING(comet)\n\n@DOCSTRING(comet3)\n\n@node Axis Configuration\n@subsubsection Axis Configuration\n\nThe axis function may be used to change the axis limits of an existing\nplot and various other axis properties, such as the aspect ratio and the\nappearance of tic marks.  By default, high level plotting functions such as\n@code{plot} reset axes properties.  Any customization of properties, for\nexample by calling @code{axis}, @code{xlim}, etc., should happen after the plot\nis done or, alternatively, after calling the @ref{XREFhold,,hold function}.\n\n@DOCSTRING(axis)\n\nSimilarly the axis limits of the colormap can be changed with the @code{clim}\nfunction.\n\n@DOCSTRING(clim)\n\nThe @code{xlim}, @code{ylim}, and @code{zlim} functions may be used to\nget or set individual axis limits.  Each has the same form.\n\n@DOCSTRING(xlim)\n\n@DOCSTRING(ylim)\n\n@DOCSTRING(zlim)\n\nThe @code{xticks}, @code{yticks}, @code{zticks}, @code{rticks}, and\n@code{thetaticks} functions may be used to get or set the tick mark locations\nand modes on the respective axis.  Each has the same form, although mode\noptions are not currently available for @code{rticks}, and @code{thetaticks}.\n\n@c FIXME: Update this section if polarplot and polar axes changes change the\n@c        associated axis properties.\n@DOCSTRING(xticks)\n\n@DOCSTRING(yticks)\n\n@DOCSTRING(zticks)\n\n@DOCSTRING(rticks)\n\n@DOCSTRING(thetaticks)\n\nThe @code{xticklabels}, @code{yticklabels}, and @code{zticklabels} functions\nmay be used to get or set the label assigned to each tick location and the\nlabeling mode on the respective axis.  Each has the same form.\n\n@c FIXME: Update this section if polarplot and polar axes changes the\n@c        associated axis properties.\n@c        Matlab also implements rticklabels and thetaticklabels.\n@DOCSTRING(xticklabels)\n\n@DOCSTRING(yticklabels)\n\n@DOCSTRING(zticklabels)\n\n@DOCSTRING(rticklabels)\n\n@DOCSTRING(thetaticklabels)\n\nThe @code{xtickangle}, @code{ytickangle}, and @code{ztickangle} functions\nmay be used to get or set the rotation angle of labels for the respective axis.\nEach has the same form.\n\n@DOCSTRING(xtickangle)\n\n@DOCSTRING(ytickangle)\n\n@DOCSTRING(ztickangle)\n\n@node Two-dimensional Function Plotting\n@subsubsection Two-dimensional Function Plotting\n@cindex plotting, two-dimensional functions\n\nOctave can plot a function from a function handle or string defining the\nfunction without the user needing to explicitly create the data to be\nplotted.  The function @code{fplot} also generates two-dimensional plots\nwith linear axes using a function name and limits for the range of the\nx-coordinate instead of the x and y data.  For example,\n\n@example\n@group\nfplot (@@sin, [-10, 10], 201);\n@end group\n@end example\n\n@noindent\nproduces a plot that is equivalent to the one above, but also includes a\nlegend displaying the name of the plotted function.\n\n@DOCSTRING(fplot)\n\nOther functions that can create two-dimensional plots directly from a\nfunction include @code{ezplot}, @code{ezcontour}, @code{ezcontourf} and\n@code{ezpolar}.\n\n@DOCSTRING(ezplot)\n\n@DOCSTRING(ezcontour)\n\n@DOCSTRING(ezcontourf)\n\n@DOCSTRING(ezpolar)\n\n@node Two-dimensional Geometric Shapes\n@subsubsection Two-dimensional Geometric Shapes\n\n@DOCSTRING(rectangle)\n\n@node Three-Dimensional Plots\n@subsection Three-Dimensional Plots\n@cindex plotting, three-dimensional\n\nThe function @code{mesh} produces mesh surface plots.  For example,\n\n@example\n@group\ntx = ty = linspace (-8, 8, 41)';\n[xx, yy] = meshgrid (tx, ty);\nr = sqrt (xx .^ 2 + yy .^ 2) + eps;\ntz = sin (r) ./ r;\nmesh (tx, ty, tz);\nxlabel (\"tx\");\nylabel (\"ty\");\nzlabel (\"tz\");\ntitle (\"3-D Sombrero plot\");\n@end group\n@end example\n\n@noindent\nproduces the familiar ``sombrero'' plot shown in @ref{fig:mesh}.  Note\nthe use of the function @code{meshgrid} to create matrices of X and Y\ncoordinates to use for plotting the Z data.  The @code{ndgrid} function\nis similar to @code{meshgrid}, but works for N-dimensional matrices.\n\n@float Figure,fig:mesh\n@center @image{mesh,4in}\n@caption{Mesh plot.}\n@end float\n\nThe @code{meshc} function is similar to @code{mesh}, but also produces a\nplot of contours for the surface.\n\nThe @code{plot3} function displays arbitrary three-dimensional data,\nwithout requiring it to form a surface.  For example,\n\n@example\n@group\nt = 0:0.1:10*pi;\nr = linspace (0, 1, numel (t));\nz = linspace (0, 1, numel (t));\nplot3 (r.*sin (t), r.*cos (t), z);\nxlabel (\"r.*sin (t)\");\nylabel (\"r.*cos (t)\");\nzlabel (\"z\");\ntitle (\"plot3 display of 3-D helix\");\n@end group\n@end example\n\n@noindent\ndisplays the spiral in three dimensions shown in @ref{fig:plot3}.\n\n@float Figure,fig:plot3\n@center @image{plot3,4in}\n@caption{Three-dimensional spiral.}\n@end float\n\nFinally, the @code{view} function changes the viewpoint for\nthree-dimensional plots.\n\n@DOCSTRING(mesh)\n\n@DOCSTRING(meshc)\n\n@DOCSTRING(meshz)\n\n@DOCSTRING(hidden)\n\n@DOCSTRING(surf)\n\n@DOCSTRING(surfc)\n\n@DOCSTRING(surfl)\n\n@DOCSTRING(surfnorm)\n\n@DOCSTRING(isosurface)\n\n@DOCSTRING(isonormals)\n\n@DOCSTRING(isocaps)\n\n@DOCSTRING(isocolors)\n\n@DOCSTRING(smooth3)\n\n@DOCSTRING(reducevolume)\n\n@DOCSTRING(reducepatch)\n\n@DOCSTRING(shrinkfaces)\n\n@DOCSTRING(diffuse)\n\n@DOCSTRING(specular)\n\n@DOCSTRING(lighting)\n\n@DOCSTRING(material)\n\n@DOCSTRING(camlight)\n\n@DOCSTRING(lightangle)\n\n@DOCSTRING(meshgrid)\n\n@DOCSTRING(ndgrid)\n\n@DOCSTRING(plot3)\n\n@DOCSTRING(view)\n\n@DOCSTRING(camlookat)\n\n@DOCSTRING(campos)\n\n@DOCSTRING(camorbit)\n\n@DOCSTRING(camroll)\n\n@DOCSTRING(camtarget)\n\n@DOCSTRING(camup)\n\n@DOCSTRING(camva)\n\n@DOCSTRING(camzoom)\n\n@DOCSTRING(slice)\n\n@DOCSTRING(ribbon)\n\n@DOCSTRING(shading)\n\n@DOCSTRING(scatter3)\n\n@DOCSTRING(waterfall)\n\n@menu\n* Aspect Ratio::\n* Three-dimensional Function Plotting::\n* Three-dimensional Geometric Shapes::\n@end menu\n\n@node Aspect Ratio\n@subsubsection Aspect Ratio\n\nFor three-dimensional plots the aspect ratio can be set for data with\n@code{daspect} and for the plot box with @code{pbaspect}.\n@xref{Axis Configuration}, for controlling the x-, y-, and z-limits for\nplotting.\n\n@DOCSTRING(daspect)\n\n@DOCSTRING(pbaspect)\n\n@node Three-dimensional Function Plotting\n@subsubsection Three-dimensional Function Plotting\n\n@DOCSTRING(ezplot3)\n\n@DOCSTRING(ezmesh)\n\n@DOCSTRING(ezmeshc)\n\n@DOCSTRING(ezsurf)\n\n@DOCSTRING(ezsurfc)\n\n@node Three-dimensional Geometric Shapes\n@subsubsection Three-dimensional Geometric Shapes\n\n@DOCSTRING(cylinder)\n\n@DOCSTRING(sphere)\n\n@DOCSTRING(ellipsoid)\n\n@node Plot Annotations\n@subsection Plot Annotations\n\nYou can add titles, axis labels, legends, and arbitrary text to an\nexisting plot.  For example:\n\n@example\n@group\nx = -10:0.1:10;\nplot (x, sin (x));\ntitle (\"sin(x) for x = -10:0.1:10\");\nxlabel (\"x\");\nylabel (\"sin (x)\");\ntext (pi, 0.7, \"arbitrary text\");\nlegend (\"sin (x)\");\n@end group\n@end example\n\nThe functions @code{grid} and @code{box} may also be used to add grid\nand border lines to the plot.  By default, the grid is off and the\nborder lines are on.\n\nFinally, arrows, text and rectangular or elliptic boxes can be added to\nhighlight parts of a plot using the @code{annotation} function.  Those objects\nare drawn in an invisible axes, on top of every other axes.\n\n@DOCSTRING(title)\n\n@DOCSTRING(legend)\n\n@DOCSTRING(text)\n\n@DOCSTRING(xlabel)\n\n@DOCSTRING(ylabel)\n\n@DOCSTRING(zlabel)\n\n@DOCSTRING(clabel)\n\n@DOCSTRING(box)\n\n@DOCSTRING(grid)\n\n@DOCSTRING(colorbar)\n\n@DOCSTRING(annotation)\n\n@node Multiple Plots on One Page\n@subsection Multiple Plots on One Page\n@cindex plotting, multiple plots per figure\n\nOctave can display more than one plot in a single figure.  The simplest\nway to do this is to use the @code{subplot} function to divide the plot\narea into a series of subplot windows that are indexed by an integer.\nFor example,\n\n@example\n@group\nsubplot (2, 1, 1)\nfplot (@@sin, [-10, 10]);\nsubplot (2, 1, 2)\nfplot (@@cos, [-10, 10]);\n@end group\n@end example\n\n@noindent\ncreates a figure with two separate axes, one displaying a sine wave and the\nother a cosine wave.  The first call to subplot divides the figure into two\nplotting areas (two rows and one column) and makes the first plot area active.\nThe grid of plot areas created by @code{subplot} is numbered in row-major order\n(left to right, top to bottom).  After plotting a sine wave, the next call to\nsubplot activates the second subplot area, but does not re-partition the\nfigure.\n\n@DOCSTRING(subplot)\n\n@node Multiple Plot Windows\n@subsection Multiple Plot Windows\n@cindex plotting, multiple plot windows\n\nYou can open multiple plot windows using the @code{figure} function.\nFor example,\n\n@example\n@group\nfigure (1);\nfplot (@@sin, [-10, 10]);\nfigure (2);\nfplot (@@cos, [-10, 10]);\n@end group\n@end example\n\n@noindent\ncreates two figures, with the first displaying a sine wave and\nthe second a cosine wave.  Figure numbers must be positive integers.\n\n@DOCSTRING(figure)\n\n@node Manipulation of Plot Objects\n@subsection Manipulation of Plot Objects\n@cindex plotting, object manipulation\n\n@DOCSTRING(pan)\n\n@DOCSTRING(rotate)\n\n@DOCSTRING(rotate3d)\n\n@DOCSTRING(zoom)\n\n@node Manipulation of Plot Windows\n@subsection Manipulation of Plot Windows\n@cindex plotting, window manipulation\n\nBy default, Octave refreshes the plot window when a prompt is printed,\nor when waiting for input.  The\n@code{drawnow} function is used to cause a plot window to be updated.\n\n@DOCSTRING(drawnow)\n\nOnly figures that are modified will be updated.  The @code{refresh}\nfunction can also be used to cause an update of the current figure, even if\nit is not modified.\n\n@DOCSTRING(refresh)\n\nNormally, high-level plot functions like @code{plot} or @code{mesh} call\n@code{newplot} to determine whether the state of the target axes should be\ninitialized (the default) or if subsequent plots should be drawn on top of\nprevious ones.  To have two plots drawn over one another, use the @code{hold}\nfunction or manually change the axes @ref{XREFaxesnextplot,,nextplot} property.\nFor example,\n\n@example\n@group\nhold on;\nx = -10:0.1:10;\nplot (x, sin (x));\nplot (x, cos (x));\nhold off;\n@end group\n@end example\n\n@noindent\ndisplays sine and cosine waves on the same axes.  If the hold state is\noff, consecutive plotting commands like this will only display the last\nplot.\n\n@DOCSTRING(newplot)\n\n@DOCSTRING(hold)\n\n@DOCSTRING(ishold)\nTo clear the current figure, call the @code{clf} function.  To clear the\ncurrent axis, call the @code{cla} function.  To bring the current figure\nto the top of the window stack, call the @code{shg} function.  To delete\na graphics object, call @code{delete} on its index.  To close the\nfigure window, call the @code{close} function.\n\n@DOCSTRING(clf)\n\n@DOCSTRING(cla)\n\n@DOCSTRING(shg)\n\n@DOCSTRING(delete)\n\n@DOCSTRING(close)\n\n@DOCSTRING(closereq)\n\n@node Use of the \"interpreter\" Property\n@subsection Use of the \"interpreter\" Property\n\n@code{text} (such as titles, labels, legend item) and @code{axes} objects\nfeature an @ref{XREFtextinterpreter,,\"interpreter\"} and a\n@ref{XREFaxesticklabelinterpreter,,\"ticklabelinterpreter\"} property\nrespectively.  It determines the manner in which special control sequences in\nthe text are rendered.\n\nThe interpreter property can take three values: @qcode{\"none\"}, @qcode{\"tex\"},\n@qcode{\"latex\"}.\n\n@menu\n* \"none\" interpreter::\n* \"tex\" interpreter::\n* \"latex\" interpreter::\n@end menu\n\n@node \"none\" interpreter\n@subsubsection \"none\" interpreter\n\nIf the interpreter is set to @qcode{\"none\"} then no special\nrendering occurs---the displayed text is a verbatim copy of the specified text.\n\n@node \"tex\" interpreter\n@subsubsection \"tex\" interpreter\n\nThe @qcode{\"tex\"} interpreter implements a subset of @TeX{} functionality when\nrendering text.  This allows the insertion of special glyphs such as Greek\ncharacters or mathematical symbols.  Special characters are inserted by using\na backslash (\\) character followed by a code, as shown in @ref{tab:extended}.\n\nBesides special glyphs, the formatting of the text can be changed within the\nstring by using the codes\n\n@multitable @columnfractions .2 .2 .6 .2\n@item @tab \\bf @tab Bold font @tab\n@item @tab \\it @tab Italic font @tab\n@item @tab \\sl @tab Oblique Font @tab\n@item @tab \\rm @tab Normal font @tab\n@end multitable\n\nThese codes may be used in conjunction with the @{ and @} characters to limit\nthe change to a part of the string.  For example,\n\n@example\nxlabel ('@{\\bf H@} = a @{\\bf V@}')\n@end example\n\n@noindent\nwhere the character @qcode{'a'} will not appear in bold font.  Note that to\navoid having Octave interpret the backslash character in the strings,\nthe strings themselves should be in single quotes.\n\nIt is also possible to change the fontname and size within the text\n\n@multitable @columnfractions .1 .4 .6 .1\n@item @tab \\fontname@{@var{fontname}@} @tab Specify the font to use @tab\n@item @tab \\fontsize@{@var{size}@} @tab Specify the size of the font to\nuse @tab\n@end multitable\n\nThe color of the text may also be changed inline using either a string (e.g.,\n\"red\") or numerically with a Red-Green-Blue (RGB) specification (e.g.,\n[1 0 0], also red).\n\n@multitable @columnfractions .1 .4 .6 .1\n@item @tab \\color@{@var{color}@} @tab Specify the color as a string @tab\n@item @tab \\color[rgb]@{@var{R} @var{G} @var{B}@} @tab Specify the color\nnumerically @tab\n@end multitable\n\nFinally, superscripting and subscripting can be controlled with the @qcode{'^'}\nand @qcode{'_'} characters.  If the @qcode{'^'} or @qcode{'_'} is followed by a\n@{ character, then all of the block surrounded by the @w{@{ @}}@ pair is\nsuperscripted or subscripted.  Without the @w{@{ @}}@ pair, only the character\nimmediately following the @qcode{'^'} or @qcode{'_'} is changed.\n\n@float Table,tab:extended\n@tex\n\\vskip 6pt\n\\newdimen\\cola \\cola=78pt\n\\newdimen\\colb \\colb=78pt\n\\newdimen\\colc \\colc=78pt\n\\def\\symtable#1#2#3{\n\\hbox to \\hsize {\\hfill\\vbox{\\offinterlineskip \\tabskip=0pt\n\\hskip36pt #1\n\\vskip6pt\n\\halign{\n\\vrule height2.0ex depth1.ex width 0.6pt #2\\tabskip=0.3em &\n#2 \\hfil & \\vrule #2 & #2 \\hfil & #2 \\vrule &\n#2 \\hfil & \\vrule #2 & #2 \\hfil & #2 \\vrule &\n#2 \\hfil & \\vrule #2 & #2 \\hfil & #2 \\vrule\nwidth 0.6pt \\tabskip=0pt\\cr\n\\noalign{\\hrule height 0.6pt}\n& Code && Sym && Code && Sym && Code && Sym &\\cr\n\\noalign{\\hrule}\n#3\n\\noalign{\\hrule height 0.6pt}\n}\n}\\hfill}}\n\\hoffset72pt\n\\symtable{Greek Lowercase Letters} {#}\n{& \\hbox to \\cola{$\\backslash$alpha }    && $\\alpha$\n&& \\hbox to \\colb{$\\backslash$beta }     && $\\beta$\n&& \\hbox to \\colc{$\\backslash$gamma}     && $\\gamma$     &\\cr\n& $\\backslash$delta      && $\\delta$\n&& $\\backslash$epsilon   && $\\epsilon$\n&& $\\backslash$zeta      && $\\zeta$      &\\cr\n& $\\backslash$eta        && $\\eta$\n&& $\\backslash$theta     && $\\theta$\n&& $\\backslash$vartheta  && $\\vartheta$  &\\cr\n& $\\backslash$iota       && $\\iota$\n&& $\\backslash$kappa     && $\\kappa$\n&& $\\backslash$lambda    && $\\lambda$    &\\cr\n& $\\backslash$mu         && $\\mu$\n&& $\\backslash$nu        && $\\nu$\n&& $\\backslash$xi        && $\\xi$        &\\cr\n& $\\backslash$o          && $o$\n&& $\\backslash$pi        && $\\pi$\n&& $\\backslash$varpi     && $\\varpi$     &\\cr\n& $\\backslash$rho        && $\\rho$\n&& $\\backslash$sigma     && $\\sigma$\n&& $\\backslash$varsigma  && $\\varsigma$  &\\cr\n& $\\backslash$tau        && $\\tau$\n&& $\\backslash$upsilon   && $\\upsilon$\n&& $\\backslash$phi       && $\\phi$       &\\cr\n& $\\backslash$chi        && $\\chi$\n&& $\\backslash$psi       && $\\psi$\n&& $\\backslash$omega     && $\\omega$     &\\cr}\n\\vskip12pt\n\\symtable{Greek Uppercase Letters} {#}\n{& \\hbox to \\cola{$\\backslash$Gamma}   && $\\Gamma$\n&& \\hbox to \\colb{$\\backslash$Delta}   && $\\Delta$\n&& \\hbox to \\colc{$\\backslash$Theta}   && $\\Theta$      &\\cr\n& $\\backslash$Lambda   && $\\Lambda$\n&& $\\backslash$Xi      && $\\Xi$\n&& $\\backslash$Pi      && $\\Pi$         &\\cr\n& $\\backslash$Sigma    && $\\Sigma$\n&& $\\backslash$Upsilon && $\\Upsilon$\n&& $\\backslash$Phi     && $\\Phi$        &\\cr\n& $\\backslash$Psi      && $\\Psi$\n&& $\\backslash$Omega   && $\\Omega$\n&&    &&       &\\cr}\n\\vskip12pt\n\\symtable{Misc Symbols Type Ord} {#}\n{& \\hbox to \\cola{$\\backslash$aleph}       && $\\aleph$\n&& \\hbox to \\colb{$\\backslash$wp}          && $\\wp$\n&& \\hbox to \\colc{$\\backslash$Re}          && $\\Re$      &\\cr\n& $\\backslash$Im           && $\\Im$\n&& $\\backslash$partial     && $\\partial$\n&& $\\backslash$infty       && $\\infty$       &\\cr\n& $\\backslash$prime        && $\\prime$\n&& $\\backslash$nabla       && $\\nabla$\n&& $\\backslash$surd        && $\\surd$        &\\cr\n& $\\backslash$angle        && $\\angle$\n&& $\\backslash$forall      && $\\forall$\n&& $\\backslash$exists      && $\\exists$      &\\cr\n& $\\backslash$neg          && $\\neg$\n&& $\\backslash$clubsuit    && $\\clubsuit$\n&& $\\backslash$diamondsuit && $\\diamondsuit$ &\\cr\n& $\\backslash$heartsuit    && $\\heartsuit$\n&& $\\backslash$spadesuit   && $\\spadesuit$\n&&    &&       &\\cr}\n\\vskip12pt\n\\symtable{``Large'' Operators} {#}\n{& \\hbox to \\cola{$\\backslash$int}   && $\\int$\n&& \\hbox to \\colb{}   &&\n&& \\hbox to \\colc{}   &&       &\\cr}\n\\vskip12pt\n\\symtable{Binary operators} {#}\n{& \\hbox to \\cola{$\\backslash$pm}     && $\\pm$\n&& \\hbox to \\colb{$\\backslash$cdot}   && $\\cdot$\n&& \\hbox to \\colc{$\\backslash$times}  && $\\times$      &\\cr\n& $\\backslash$ast     && $\\ast$\n&& $\\backslash$circ   && $\\circ$\n&& $\\backslash$bullet && $\\bullet$     &\\cr\n& $\\backslash$div     && $\\div$\n&& $\\backslash$cap    && $\\cap$\n&& $\\backslash$cup    && $\\cup$        &\\cr\n& $\\backslash$vee     && $\\vee$\n&& $\\backslash$wedge  && $\\wedge$\n&& $\\backslash$oplus  && $\\oplus$      &\\cr\n& $\\backslash$otimes  && $\\otimes$\n&& $\\backslash$oslash && $\\oslash$\n&&    &&      &\\cr}\n@end tex\n@ifnottex\n@multitable @columnfractions .25 .25 .25 .25\n@item Greek Lowercase Letters\n@item @tab  \\alpha      @tab  \\beta        @tab  \\gamma\n@item @tab  \\delta      @tab  \\epsilon     @tab  \\zeta\n@item @tab  \\eta        @tab  \\theta       @tab  \\vartheta\n@item @tab  \\iota       @tab  \\kappa       @tab  \\lambda\n@item @tab  \\mu         @tab  \\nu          @tab  \\xi\n@item @tab  \\o          @tab  \\pi          @tab  \\varpi\n@item @tab  \\rho        @tab  \\sigma       @tab  \\varsigma\n@item @tab  \\tau        @tab  \\upsilon     @tab  \\phi\n@item @tab  \\chi        @tab  \\psi         @tab  \\omega\n@item Greek Uppercase Letters\n@item @tab  \\Gamma      @tab  \\Delta       @tab  \\Theta\n@item @tab  \\Lambda     @tab  \\Xi          @tab  \\Pi\n@item @tab  \\Sigma      @tab  \\Upsilon     @tab  \\Phi\n@item @tab  \\Psi        @tab  \\Omega       @tab\n@item Misc Symbols Type Ord\n@item @tab  \\aleph      @tab  \\wp          @tab  \\Re\n@item @tab  \\Im         @tab  \\partial     @tab  \\infty\n@item @tab  \\prime      @tab  \\nabla       @tab  \\surd\n@item @tab  \\angle      @tab  \\forall      @tab  \\exists\n@item @tab  \\neg        @tab  \\clubsuit    @tab  \\diamondsuit\n@item @tab  \\heartsuit  @tab  \\spadesuit   @tab\n@item ``Large'' Operators\n@item @tab  \\int\n@item Binary Operators\n@item @tab  \\pm         @tab  \\cdot        @tab  \\times\n@item @tab  \\ast        @tab  \\circ        @tab  \\bullet\n@item @tab  \\div        @tab  \\cap         @tab  \\cup\n@item @tab  \\vee        @tab  \\wedge       @tab  \\oplus\n@item @tab  \\otimes     @tab  \\oslash      @tab\n@item Relations\n@item @tab  \\leq        @tab  \\subset      @tab  \\subseteq\n@item @tab  \\in         @tab  \\geq         @tab  \\supset\n@item @tab  \\supseteq   @tab  \\ni          @tab  \\mid\n@item @tab  \\equiv      @tab  \\sim         @tab  \\approx\n@item @tab  \\cong       @tab  \\propto      @tab  \\perp\n@item Arrows\n@item @tab  \\leftarrow  @tab  \\Leftarrow   @tab  \\rightarrow\n@item @tab  \\Rightarrow @tab  \\leftrightarrow @tab  \\uparrow\n@item @tab  \\downarrow  @tab               @tab\n@item Openings and Closings\n@item @tab  \\lfloor     @tab  \\langle      @tab  \\lceil\n@item @tab  \\rfloor     @tab  \\rangle      @tab  \\rceil\n@item Alternate Names\n@item @tab  \\neq\n@item Other\n@item @tab  \\ldots      @tab  \\0          @tab  \\copyright\n@item @tab  \\deg\n@end multitable\n@end ifnottex\n@caption{Available special characters in @TeX{} mode}\n@end float\n@float\n@tex\n\\vskip 6pt\n\\newdimen\\cola \\cola=78pt\n\\newdimen\\colb \\colb=78pt\n\\newdimen\\colc \\colc=78pt\n\\def\\symtable#1#2#3{\\hbox to \\hsize {\\hfill\\vbox{\\offinterlineskip \\tabskip=0pt\n\\hskip36pt #1\n\\vskip6pt\n\\halign{\n\\vrule height2.0ex depth1.ex width 0.6pt #2\\tabskip=0.3em &\n#2 \\hfil & \\vrule #2 & #2 \\hfil & #2 \\vrule &\n#2 \\hfil & \\vrule #2 & #2 \\hfil & #2 \\vrule &\n#2 \\hfil & \\vrule #2 & #2 \\hfil & #2 \\vrule\nwidth 0.6pt \\tabskip=0pt\\cr\n\\noalign{\\hrule height 0.6pt}\n& Code && Sym && Code && Sym && Code && Sym &\\cr\n\\noalign{\\hrule}\n#3\n\\noalign{\\hrule height 0.6pt}\n}\n}\\hfill}}\n\\hoffset72pt\n\\vskip12pt\n\\symtable{Relations} {#}\n{& \\hbox to \\cola{$\\backslash$leq}      && $\\leq$\n&& \\hbox to \\colb{$\\backslash$subset}   && $\\subset$\n&& \\hbox to \\colc{$\\backslash$subseteq} && $\\subseteq$    &\\cr\n& $\\backslash$in        && $\\in$\n&& $\\backslash$geq      && $\\geq$\n&& $\\backslash$supset   && $\\supset$      &\\cr\n& $\\backslash$supseteq  && $\\supseteq$\n&& $\\backslash$ni       && $\\ni$\n&& $\\backslash$mid      && $\\mid$         &\\cr\n& $\\backslash$equiv     && $\\equiv$\n&& $\\backslash$sim      && $\\sim$\n&& $\\backslash$approx   && $\\approx$      &\\cr\n& $\\backslash$cong      && $\\cong$\n&& $\\backslash$propto   && $\\propto$\n&& $\\backslash$perp     && $\\perp$        &\\cr}\n\\vskip12pt\n\\symtable{Arrows} {#}\n{& \\hbox to \\cola{$\\backslash$leftarrow}      && $\\leftarrow$\n&& \\hbox to \\colb{$\\backslash$Leftarrow}      && $\\Leftarrow$\n&& \\hbox to \\colc{$\\backslash$rightarrow}     && $\\rightarrow$      &\\cr\n& $\\backslash$Rightarrow      && $\\Rightarrow$\n&& $\\backslash$leftrightarrow && $\\leftrightarrow$\n&& $\\backslash$uparrow        && $\\uparrow$         &\\cr\n& $\\backslash$downarrow       && $\\downarrow$\n&&   &&\n&&   &&       &\\cr}\n\\vskip12pt\n\\symtable{Openings and Closings} {#}\n{& \\hbox to \\cola{$\\backslash$lfloor   }    && $\\lfloor$\n&& \\hbox to \\colb{$\\backslash$langle   }    && $\\langle$\n&& \\hbox to \\colc{$\\backslash$lceil    }    && $\\lceil$      &\\cr\n& $\\backslash$rfloor    && $\\rfloor$\n&& $\\backslash$rangle   && $\\rangle$\n&& $\\backslash$rceil    && $\\rceil$      &\\cr}\n\\vskip12pt\n\\symtable{Alternate Names} {#}\n{& \\hbox to \\cola{$\\backslash$neq}   && $\\neq$\n&& \\hbox to \\colb{}   &&\n&& \\hbox to \\colc{}   &&   &\\cr}\n\\vskip12pt\n\\symtable{Other (not in Appendix F Tables)} {#}\n{& \\hbox to \\cola{$\\backslash$ldots}     && $\\ldots$\n&& \\hbox to \\colb{$\\backslash$0}         && $\\oslash$\n&& \\hbox to \\colc{$\\backslash$copyright} && $\\copyright$      &\\cr\n& $\\backslash$deg        && $^\\circ$\n&&    &&\n&&    &&       &\\cr}\n\\vskip12pt\n\\hskip36pt Table 15.1: Available special characters in \\TeX\\ mode (cont.)\n@end tex\n@end float\n\n@strong{Caution: Degree Symbol}\n@cindex Degree Symbol\n\nConformance to both @TeX{} and @sc{matlab} with respect to the @code{\\circ}\nsymbol is impossible.  While @TeX{} translates this symbol to\n@w{Unicode 2218}@ (U+2218), @sc{matlab} maps this to @w{Unicode 00B0}@ (U+00B0)\ninstead.  Octave has chosen to follow the @TeX{} specification, but has added\nthe additional symbol @code{\\deg} which maps to the degree symbol (U+00B0).\n\n@node \"latex\" interpreter\n@subsubsection \"latex\" interpreter\n\nThe @qcode{\"latex\"} interpreter only works if an external @LaTeX{} tool chain\nis present.  Three binaries are needed: @code{latex}, @code{dvipng}, and\n@code{dvisvgm}.  If those binaries are installed but not on the path, one can\nstill provide their respective path using the following environment variables:\n@w{@env{OCTAVE_LATEX_BINARY}}, @w{@env{OCTAVE_DVIPNG_BINARY}}, and\n@w{@env{OCTAVE_DVISVG_BINARY}}.\n\nNote that Octave does not parse or validate the text strings when in\n@qcode{\"latex\"} mode---it is the responsibility of the programmer to generate\nvalid strings which may include wrapping sections that should appear in Math\nmode with @qcode{'$'} characters.\nSee, for example, @url{https://www.latex-project.org/help/documentation/} for\ndocumentation about @LaTeX{} typesetting.\n\nFor debugging purpose, a convenience environment variable,\n@w{@env{OCTAVE_LATEX_DEBUG}}, can be set to trigger more verbose output when\nOctave fails to have a given text compiled by an external @LaTeX{} engine.  For\nexample, @qcode{\"x^2\"} is not a valid @LaTeX{} string and the following example\nshould fail\n\n@example\n@group\nsetenv (\"OCTAVE_LATEX_DEBUG\", \"1\")\nx = 1:10;\nplot (x, x.^2)\ntitle (\"x^2\", \"interpreter\", \"latex\")\n@end group\n@end example\n\nSearching the terminal output you should find some helpful info about the\norigin of the failure:\n\n@example\n@group\n...\nNo file default.aux.\n! Missing $ inserted.\n<inserted text>\n                $\nl.6 x^\n      2\n! Missing $ inserted.\n...\n@end group\n@end example\n\nIf no usable @LaTeX{} tool chain is found at the first text rendering, using\nthe @qcode{\"latex\"} interpreter is equivalent to @qcode{\"none\"}.\n\n@node Printing and Saving Plots\n@subsection Printing and Saving Plots\n@cindex plotting, saving and printing plots\n@cindex printing plots\n@cindex saving plots\n\nThe @code{print} command allows you to send plots to your printer and\nto save plots in a variety of formats.  For example,\n\n@example\nprint -dpsc\n@end example\n\n@noindent\nprints the current figure to a color PostScript printer.  And,\n\n@example\nprint foo.pdf\n@end example\n\n@noindent\nsaves the current figure to a Portable Document encapsulated PostScript file\ncalled @file{foo.pdf}.\n\nThe current graphic toolkits produce very similar graphic displays, but the\ninterpreters differ in their capability to display unusual text and in their\nability to print such text.  In general, the @qcode{\"tex\"} interpreter\n(default) is the best all-around performer for both on-screen display and\nprinting.  However, for the reproduction of complicated text formulas the\n@qcode{\"latex\"} interpreter is preferred.  The @qcode{\"none\"} interpreter\nprints text verbatim (exactly as it appears) which is very portable, but there\nis no support for bold, italic, superscripts, subscripts, Greek letters, etc.\n\nWhen printing with the @option{-painters} renderer, the default for all vector\nformats, two options may be considered:\n\n@itemize @bullet\n@item\nUse the @option{-svgconvert} option to allow for rendering @LaTeX{} formulas.\nNote that the glyph are rendered as path and the original textual info are\nlost.\n\n@item\nUse one of the @option{-d*latex*} devices to produce a .tex file (plus\nsupporting .eps or .pdf files) to be further processed by an external @LaTeX{}\nengine.  Note that the @code{print} function will first set the interpreter of\nall strings to @qcode{\"latex\"}, which means all strings must be valid @LaTeX{}\nstrings.\n@end itemize\n\nA complete example showing the capabilities of text printing using the\n@option{-dpdflatexstandalone} option is:\n\n@example\n@group\nx = 0:0.01:3;\nhf = figure ();\nplot (x, erf (x));\nhold on;\nplot (x, x, \"r\");\naxis ([0, 3, 0, 1]);\ntext (0.65, 0.6175, ...\n      ['$\\displaystyle\\leftarrow x = @{2 \\over \\sqrt@{\\pi@}@}' ...\n       '\\int_@{0@}^@{x@} e^@{-t^2@} dt = 0.6175$'],\n      \"interpreter\", \"latex\");\nxlabel (\"x\");\nylabel (\"erf (x)\");\ntitle (\"erf (x) with text annotation\");\nprint (hf, \"plot15_7\", \"-dpdflatexstandalone\");\nsystem (\"pdflatex plot15_7\");\nopen plot15_7.pdf\n@end group\n@end example\n\n@ifnotinfo\n@noindent\nThe result of this example can be seen in @ref{fig:extendedtext}\n\n@float Figure,fig:extendedtext\n@center @image{extended,4in}\n@caption{Example of inclusion of text with use of @option{-dpdflatexstandalone}}\n@end float\n@end ifnotinfo\n\n@DOCSTRING(print)\n\n@DOCSTRING(saveas)\n\n@DOCSTRING(orient)\n\n@code{print} and @code{saveas} are used when work on a plot has finished\nand the output must be in a publication-ready format.  During intermediate\nstages it is often better to save the graphics object and all of its\nassociated information so that changes---to colors, axis limits, marker styles,\netc.---can be made easily from within Octave.  The @code{hgsave}/@code{hgload}\ncommands can be used to save and re-create a graphics object.\n\n@DOCSTRING(hgsave)\n\n@DOCSTRING(hgload)\n\n@DOCSTRING(openfig)\n\n@DOCSTRING(savefig)\n\n@node Interacting with Plots\n@subsection Interacting with Plots\n\nThe user can select points on a plot with the @code{ginput} function or\nselect the position at which to place text on the plot with the\n@code{gtext} function using the mouse.\n\n@DOCSTRING(ginput)\n\n@DOCSTRING(waitforbuttonpress)\n\n@DOCSTRING(gtext)\n\nMore sophisticated user interaction mechanisms can be obtained using the\n@nospell{ui*} family of functions, @pxref{UI Elements}.\n\n@node Test Plotting Functions\n@subsection Test Plotting Functions\n\nThe functions @code{sombrero} and @code{peaks} provide a way to check\nthat plotting is working.  Typing either @code{sombrero} or @code{peaks}\nat the Octave prompt should display a three-dimensional plot.\n\n@DOCSTRING(sombrero)\n\n@DOCSTRING(peaks)\n\n@node Graphics Data Structures\n@section Graphics Data Structures\n@cindex graphics data structures\n\n@menu\n* Introduction to Graphics Structures::\n* Graphics Objects::\n* Graphics Object Properties::\n* Searching Properties::\n* Managing Default Properties::\n@end menu\n\n@node Introduction to Graphics Structures\n@subsection Introduction to Graphics Structures\n@cindex introduction to graphics structures\n\nThe graphics functions use pointers, which are of class graphics_handle, in\norder to address the data structures which control visual display.  A\ngraphics handle may point to any one of a number of different base object\ntypes.  These objects are the graphics data structures themselves.  The\nprimitive graphic object types are: @code{figure}, @code{axes}, @code{line},\n@code{text}, @code{patch}, @code{scatter}, @code{surface}, @code{text},\n@code{image}, and @code{light}.\n\nEach of these objects has a function by the same name, and each of these\nfunctions returns a graphics handle pointing to an object of the corresponding\ntype.\n\nIn addition, there are several functions which operate on properties of the\ngraphics objects and which also return handles.  This includes but is not\nlimited to the following functions: The functions @code{plot} and @code{plot3}\nreturn a handle pointing to an object of type @code{line}.  The function\n@code{subplot} returns a handle pointing to an object of type @code{axes}.\nThe functions @code{fill}, @code{fill3}, @code{trimesh}, and @code{trisurf}\nreturn a handle pointing to an object of type patch.  The function\n@code{scatter3} returns a handle to an object of type scatter.  The functions\n@code{slice}, @code{surf}, @code{surfl}, @code{mesh}, @code{meshz},\n@code{pcolor}, and @code{waterfall} each return a handle of type surface.  The\nfunction @code{camlight} returns a handle to an object of type light.  The\nfunctions @code{area}, @code{bar}, @code{barh}, @code{contour},\n@code{contourf}, @code{contour3}, @code{surfc}, @code{meshc}, @code{errorbar},\n@code{quiver}, @code{quiver3}, @code{stair}, @code{stem}, @code{stem3} each\nreturn a handle to a complex data structure as documented in\n@ref{Data Sources in Object Groups,,Data Sources}.\n\nThe graphics objects are arranged in a hierarchy:\n\n1. The root object is returned by @code{groot} (historically, equivalent to\nthe handle 0).  In other words, @code{get (groot)} returns the properties of\nthe root object.\n\n2. Below the root are @code{figure} objects.\n\n3. Below the @code{figure} objects are @code{axes} or @code{hggroup} objects.\n\n4. Below the @code{axes} or @code{hggroup} objects are @code{line},\n@code{text}, @code{patch}, @code{scatter}, @code{surface}, @code{image}, and\n@code{light} objects.\n\nIt is possible to walk this hierarchical tree by querying the @qcode{\"parent\"}\nand @qcode{\"children\"} properties of the graphics objects.\n\nGraphics handles may be distinguished from function handles\n(@pxref{Function Handles}) by means of the function @code{ishghandle}.\n@code{ishghandle} returns true if its argument is a handle of a graphics\nobject.  In addition, a figure or axes object may be tested using\n@code{isfigure} or @code{isaxes} respectively.  To test for a specific type of\ngraphics handle, such as a patch or line object, use @code{isgraphics}.  The\nmore specific test functions return true only if the argument is both a\ngraphics handle and of the correct type (figure, axes, specified object type).\n\nThe @code{get} and @code{set} commands are used to obtain and set the values of\nproperties of graphics objects.  In addition, the @code{get} command may be\nused to obtain property names.\n\nFor example, the property @qcode{\"type\"} of the graphics object pointed to by\nthe graphics handle h may be displayed by:\n\n@example\nget (h, \"type\")\n@end example\n\nThe properties and their current values may be obtained in the form of a\nstructure using @code{s = get (h)}, where @code{h} is the handle of a graphics\nobject.  If only the names of the properties and the allowed values (for radio\nproperties only) are wanted, one may use @code{set (h)}.\n\nThus, for example:\n\n@example\nh = figure ();\nget (h, \"type\")\n@xresult{} ans = figure\nset (h)\n@xresult{}\n        alphamap:\n        beingdeleted:  [ @{off@} | on ]\n        busyaction:  [ cancel | @{queue@} ]\n        buttondownfcn:\n        clipping:  [ off | @{on@} ]\n        closerequestfcn:\n        color:\n        colormap:\n        createfcn:\n        currentaxes:\n        deletefcn:\n        dockcontrols:  [ @{off@} | on ]\n        filename:\n        graphicssmoothing:  [ off | @{on@} ]\n        handlevisibility:  [ callback | off | @{on@} ]\n        ...\n@end example\n\nThe uses of @code{get} and @code{set} are further explained in\n@ref{XREFget,,get}, @ref{XREFset,,set}.\n\n@DOCSTRING(isprop)\n\n@node Graphics Objects\n@subsection Graphics Objects\n@cindex graphics objects\n\nThe hierarchy of graphics objects was explained above.\n@xref{Introduction to Graphics Structures}.  Here the specific objects are\ndescribed, and the properties contained in these objects are discussed.  Keep\nin mind that graphics objects are always referenced by @dfn{handle}.\n\n@menu\n* Creating Graphics Objects::\n* Handle Functions::\n@end menu\n\n@table @asis\n@c @group\n\n@item root\n@cindex root graphics object\n@cindex graphics object, root\nThe top level of the hierarchy and the parent of all figure objects.\nUse @code{groot} to obtain the handle of the root graphics object.\n\n@item figure\n@cindex figure graphics object\n@cindex graphics object, figure\nA figure window.\n\n@item axes\n@cindex axes graphics object\n@cindex graphics object, axes\nA set of axes.  This object is a child of a figure object and may be a\nparent of line, text, image, patch, surface, or light objects.\n\n@item line\n@cindex line graphics object\n@cindex graphics object, line\nA line in two or three dimensions.\n\n@item text\n@cindex text graphics object\n@cindex graphics object, text\nText annotations.\n\n@item image\n@cindex image graphics object\n@cindex graphics object, image\nA bitmap image.\n\n@item patch\n@cindex patch graphics object\n@cindex graphics object, patch\nA filled polygon, currently limited to two dimensions.\n\n@item surface\n@cindex surface graphics object\n@cindex graphics object, surface\nA three-dimensional surface.\n\n@item light\n@cindex light graphics object\n@cindex graphics object, light\nA light object used for lighting effects on patches and surfaces.\n@c @end group\n@end table\n\n@node Creating Graphics Objects\n@subsubsection Creating Graphics Objects\n@cindex creating graphics objects\n\nYou can create any graphics object primitive by calling the function of the\nsame name as the object; In other words, @code{figure}, @code{axes},\n@code{line}, @code{text}, @code{image}, @code{patch}, @code{surface}, and\n@code{light} functions.  These fundamental graphic objects automatically become\nchildren of the current axes object as if @code{hold on} was in place.\nSeparately, axes will automatically become children of the current figure\nobject and figures will become children of the root object.\n\nIf this auto-joining feature is not desired then it is important to call\n@code{newplot} first to prepare a new figure and axes for plotting.\nAlternatively, the easier way is to call a high-level graphics routine which\nwill both create the plot and then populate it with low-level graphics objects.\nInstead of calling @code{line}, use @code{plot}.  Or use @code{surf} instead of\n@code{surface}.  Or use @code{fill} or @code{fill3} instead of @code{patch}.\n\n@DOCSTRING(axes)\n\n@DOCSTRING(line)\n\n@DOCSTRING(patch)\n\n@DOCSTRING(surface)\n\n@DOCSTRING(light)\n\n@node Handle Functions\n@subsubsection Handle Functions\n@cindex handle functions\n\nTo determine whether a variable is a graphics object index, or an index\nto an axes or figure, use the functions @code{ishghandle}, @code{isgraphics},\n@code{isaxes}, and @code{isfigure}.\n\n@DOCSTRING(ishghandle)\n\n@DOCSTRING(isgraphics)\n\n@DOCSTRING(ishandle)\n\n@DOCSTRING(isaxes)\n\n@DOCSTRING(isfigure)\n\nThe function @code{gcf} returns an index to the current figure object,\nor creates one if none exists.  Similarly, @code{gca} returns the\ncurrent axes object, or creates one (and its parent figure object) if\nnone exists.\n\n@DOCSTRING(groot)\n\n@DOCSTRING(gcf)\n\n@DOCSTRING(gca)\n\n@DOCSTRING(gco)\n\nThe @code{get} and @code{set} functions may be used to examine and set\nproperties for graphics objects.  For example,\n\n@example\n@group\nget (groot)\n    @xresult{} ans =\n       @{\n         type = root\n         currentfigure = [](0x0)\n         children = [](0x0)\n         visible = on\n         @dots{}\n       @}\n@end group\n@end example\n\n@noindent\nreturns a structure containing all the properties of the root graphics object.\nAs with all functions in Octave, the structure is returned by value, so\nmodifying it will not modify the internal root object.  To do that, you must\nuse the @code{set} function.  Also, note that in this case, the\n@code{currentfigure} property is empty, which indicates that there is no\ncurrent figure window.\n\nThe @code{get} function may also be used to find the value of a single\nproperty.  For example,\n\n@example\n@group\nget (gca (), \"xlim\")\n    @xresult{} [ 0 1 ]\n@end group\n@end example\n\n@noindent\nreturns the range of the x-axis for the current axes object in the\ncurrent figure.\n\nTo set graphics object properties, use the set function.  For example,\n\n@example\nset (gca (), \"xlim\", [-10, 10]);\n@end example\n\n@noindent\nsets the range of the x-axis for the current axes object in the current\nfigure to @samp{[-10, 10]}.\n\nDefault property values can also be queried if the @code{set} function is\ncalled without a value argument.  When only one argument is given (a graphic\nhandle) then a structure with defaults for all properties of the given object\ntype is returned.  For example,\n\n@example\nset (gca ())\n@end example\n\n@noindent\nreturns a structure containing the default property values for axes objects.\nIf @code{set} is called with two arguments (a graphic handle and a property\nname) then only the defaults for the requested property are returned.\n\n@DOCSTRING(get)\n\n@DOCSTRING(set)\n\n@DOCSTRING(ancestor)\n\n@DOCSTRING(allchild)\n\n@DOCSTRING(findfigs)\n\n@cindex saving graphics objects\n@cindex graphics objects, saving\n\nFigures can be printed or saved in many graphics formats with @code{print} and\n@code{saveas}.  Occasionally, however, it may be useful to save the original\nOctave handle graphic directly so that further modifications can be made such\nas modifying a title or legend.\n\nThis can be accomplished with the following functions by\n\n@example\n@group\nfig_struct = hdl2struct (gcf);\nsave myplot.fig -struct fig_struct;\n@dots{}\nfig_struct = load (\"myplot.fig\");\nstruct2hdl (fig_struct);\n@end group\n@end example\n\n@DOCSTRING(hdl2struct)\n\n@DOCSTRING(struct2hdl)\n\n@DOCSTRING(copyobj)\n\n@node Graphics Object Properties\n@subsection Graphics Object Properties\n@cindex graphics object properties\n\n@menu\n* Root Properties::\n* Figure Properties::\n* Axes Properties::\n* Legend Properties::\n* Line Properties::\n* Text Properties::\n* Image Properties::\n* Patch Properties::\n* Scatter Properties::\n* Surface Properties::\n* Light Properties::\n* Uimenu Properties::\n* Uibuttongroup Properties::\n* Uicontextmenu Properties::\n* Uipanel Properties::\n* Uicontrol Properties::\n* Uitable Properties::\n* Uitoolbar Properties::\n* Uipushtool Properties::\n* Uitoggletool Properties::\n@end menu\n\nIn this section the graphics object properties are discussed in detail, starting\nwith the root properties and continuing through the object hierarchy.  The\ndocumentation about a specific graphics object can be displayed using @code{doc}\nfunction, e.g., @code{doc (\"axes properties\")} will show @ref{Axes Properties}.\n\nThe allowed values for radio (string) properties can be retrieved\nprogrammatically or displayed using the one or two argument calling form of the\n@code{set} function.  @xref{XREFset,,set}.\n\nAny properties marked as either unused or unimplemented in the following\ndocumentation are accepted without error by Octave.  Values for those properties\nare stored in the object but have no effect on the object.\n\nDefault property values are enclosed in @{ @}.\n\n@node Root Properties\n@subsubsection Root Properties\n@prindex @sortas{@ Root Properties} Root Properties\n\n@include plot-rootproperties.texi\n\n\n@node Figure Properties\n@subsubsection Figure Properties\n@prindex @sortas{@ Figure Properties} Figure Properties\n\n@include plot-figureproperties.texi\n\n\n@node Axes Properties\n@subsubsection Axes Properties\n@prindex @sortas{@ Axes Properties} Axes Properties\n\n@include plot-axesproperties.texi\n\n\n@node Legend Properties\n@subsubsection Legend Properties\n@prindex @sortas{@ Legend Properties} Legend Properties\n\n@include plot-legendproperties.texi\n\n\n@node Line Properties\n@subsubsection Line Properties\n@prindex @sortas{@ Line Properties} Line Properties\n\n@include plot-lineproperties.texi\n\n\n@node Text Properties\n@subsubsection Text Properties\n@prindex @sortas{@ Text Properties} Text Properties\n\n@include plot-textproperties.texi\n\n\n@node Image Properties\n@subsubsection Image Properties\n@prindex @sortas{@ Image Properties} Image Properties\n\n@include plot-imageproperties.texi\n\n\n@node Patch Properties\n@subsubsection Patch Properties\n@prindex @sortas{@ Patch Properties} Patch Properties\n\n@include plot-patchproperties.texi\n\n\n@node Scatter Properties\n@subsubsection Scatter Properties\n@prindex @sortas{@ Scatter Properties} Scatter Properties\n\n@include plot-scatterproperties.texi\n\n\n@node Surface Properties\n@subsubsection Surface Properties\n@prindex @sortas{@ Surface Properties} Surface Properties\n\n@include plot-surfaceproperties.texi\n\n\n@node Light Properties\n@subsubsection Light Properties\n@prindex @sortas{@ Light Properties} Light Properties\n\n@include plot-lightproperties.texi\n\n\n@node Uimenu Properties\n@subsubsection Uimenu Properties\n@prindex @sortas{@ Uimenu Properties} Uimenu Properties\n\n@include plot-uimenuproperties.texi\n\n\n@node Uibuttongroup Properties\n@subsubsection Uibuttongroup Properties\n@prindex @sortas{@ Uibuttongroup Properties} Uibuttongroup Properties\n\n@include plot-uibuttongroupproperties.texi\n\n\n@node Uicontextmenu Properties\n@subsubsection Uicontextmenu Properties\n@prindex @sortas{@ Uicontextmenu Properties} Uicontextmenu Properties\n\n@include plot-uicontextmenuproperties.texi\n\n\n@node Uipanel Properties\n@subsubsection Uipanel Properties\n@prindex @sortas{@ Uipanel Properties} Uipanel Properties\n\n@include plot-uipanelproperties.texi\n\n\n@node Uicontrol Properties\n@subsubsection Uicontrol Properties\n@prindex @sortas{@ Uicontrol Properties} Uicontrol Properties\n\n@include plot-uicontrolproperties.texi\n\n\n@node Uitable Properties\n@subsubsection Uitable Properties\n@cindex uitable properties\n\n@include plot-uitableproperties.texi\n\n\n@node Uitoolbar Properties\n@subsubsection Uitoolbar Properties\n@prindex @sortas{@ Uitoolbar Properties} Uitoolbar Properties\n\n@include plot-uitoolbarproperties.texi\n\n\n@node Uipushtool Properties\n@subsubsection Uipushtool Properties\n@prindex @sortas{@ Uipushtool Properties} Uipushtool Properties\n\n@include plot-uipushtoolproperties.texi\n\n\n@node Uitoggletool Properties\n@subsubsection Uitoggletool Properties\n@prindex @sortas{@ Uitoggletool Properties} Uitoggletool Properties\n\n@include plot-uitoggletoolproperties.texi\n\n\n@node Searching Properties\n@subsection Searching Properties\n\n@DOCSTRING(findobj)\n\n@DOCSTRING(findall)\n@node Managing Default Properties\n@subsection Managing Default Properties\n@cindex default graphics properties\n@cindex graphics properties, default\n\nObject properties have two classes of default values, @dfn{factory\ndefaults} (the initial values) and @dfn{user-defined defaults}, which\nmay override the factory defaults.\n\nAlthough default values may be set for any object, they are set in\nparent objects and apply to child objects, of the specified object type.\nFor example, setting the default @code{color} property of @code{line}\nobjects to @qcode{\"green\"}, for the @code{root} object, will result in all\n@code{line} objects inheriting the @code{color} @qcode{\"green\"} as the default\nvalue.\n\n@example\nset (groot, \"defaultlinecolor\", \"green\");\n@end example\n\n@noindent\nsets the default line color for all objects.  The rule for constructing\nthe property name to set a default value is\n\n@example\ndefault + @var{object-type} + @var{property-name}\n@end example\n\nThis rule can lead to some strange looking names, for example\n@code{defaultlinelinewidth\"} specifies the default @code{linewidth}\nproperty for @code{line} objects.\n\nThe example above used the root object so the default property value will apply\nto all line objects.  However, default values are hierarchical, so defaults set\nin a figure objects override those set in the root object.  Likewise, defaults\nset in an axes object override those set in figure or root objects.  For\nexample,\n\n@example\n@group\nsubplot (2, 1, 1);\nset (groot, \"defaultlinecolor\", \"red\");\nset (1, \"defaultlinecolor\", \"green\");\nset (gca (), \"defaultlinecolor\", \"blue\");\nline (1:10, rand (1, 10));\nsubplot (2, 1, 2);\nline (1:10, rand (1, 10));\nfigure (2)\nline (1:10, rand (1, 10));\n@end group\n@end example\n\n@noindent\nproduces two figures.  The line in first subplot window of the first\nfigure is blue because it inherits its color from its parent axes\nobject.  The line in the second subplot window of the first figure is\ngreen because it inherits its color from its parent figure object.  The\nline in the second figure window is red because it inherits its color\nfrom the global root object.\n\nTo remove a user-defined default setting, set the default property to\nthe value @qcode{\"remove\"}.  For example,\n\n@example\nset (gca (), \"defaultlinecolor\", \"remove\");\n@end example\n\n@noindent\nremoves the user-defined default line color setting from the current axes\nobject.  To quickly remove all user-defined defaults use the @code{reset}\nfunction.\n\nBy default, high level plotting functions such as @code{plot} reset and\nredefine axes properties independently from the defaults.  An example of such\nproperty is the axes @code{box} property: it is set @code{on} by high level 2-D\ngraphics functions regardless of the property @qcode{\"defaultaxesbox\"}.  Use\nthe @code{hold} function to prevent this behavior:\n\n@example\n@group\nset (groot, \"defaultaxesbox\", \"off\");\nsubplot (2, 1, 1);\nplot (1:10)\ntitle (\"Box is on anyway\")\nsubplot (2, 1, 2);\nhold on\nplot (1:10)\ntitle (\"Box is off\")\n@end group\n@end example\n\n@DOCSTRING(reset)\n\nGetting the @qcode{\"default\"} property of an object returns a list of\nuser-defined defaults set for the object.  For example,\n\n@example\nget (gca (), \"default\");\n@end example\n\n@noindent\nreturns a list of user-defined default values for the current axes\nobject.\n\nFactory default values are stored in the root object.  The command\n\n@example\nget (groot, \"factory\");\n@end example\n\n@noindent\nreturns a list of factory defaults.\n\n@node Advanced Plotting\n@section Advanced Plotting\n\n\n@menu\n* Colors::\n* Line Styles::\n* Marker Styles::\n* Callbacks::\n* Application-defined Data::\n* Object Groups::\n* Transform Groups::\n* Graphics Toolkits::\n@end menu\n\n\n@node Colors\n@subsection Colors\n@cindex graphics colors\n@cindex colors, graphics\n\nColors may be specified in three ways: 1) RGB triplets, 2) by name, or 3) by\nHTML notation.\n\n@table @asis\n\n@item RGB triplet\n\nAn RGB triplet is a 1x3 vector where each value is between 0 and 1 inclusive.\nThe first value represents the percentage of Red, the second value the\npercentage of Green, and the third value the percentage of Blue.  For example,\n@code{[1, 0, 1]} represents full Red and Blue channels resulting in the color\nmagenta.\n\n@item short or long name\n\nEight colors can be specified directly by name or by a single character short\nname.\n\n@multitable @columnfractions 0.21 0.79\n@headitem Name @tab Color\n@item @samp{k}, @qcode{\"black\"}   @tab blacK\n@item @samp{r}, @qcode{\"red\"}     @tab Red\n@item @samp{g}, @qcode{\"green\"}   @tab Green\n@item @samp{b}, @qcode{\"blue\"}    @tab Blue\n@item @samp{y}, @qcode{\"yellow\"}  @tab Yellow\n@item @samp{m}, @qcode{\"magenta\"} @tab Magenta\n@item @samp{c}, @qcode{\"cyan\"}    @tab Cyan\n@item @samp{w}, @qcode{\"white\"}   @tab White\n@end multitable\n\n@item HTML notation\n\nHTML notation is a string that begins with the character @samp{#} and is\nfollowed by either 3 or 6 hexadecimal digits.  As with RGB triplets, each\nhexadecimal number represents the fraction of the Red, Green, and Blue channels\npresent in the specified color.  For example, @qcode{\"#FF00FF\"} represents\nthe color magenta.\n\n@end table\n\n@node Line Styles\n@subsection Line Styles\n@cindex line styles, graphics\n@cindex graphics line styles\n\nLine styles are specified by the following properties:\n\n@table @code\n@item linestyle\nMay be one of\n\n@table @asis\n@item @qcode{\"-\"}\nSolid line.  [default]\n\n@item @qcode{\"--\"}\nDashed line.\n\n@item @qcode{\":\"}\nDotted line.\n\n@item @qcode{\"-.\"}\nA dash-dot line.\n\n@item @qcode{\"none\"}\nNo line.  Points will still be marked using the current Marker Style.\n@end table\n\n@item linewidth\nA number specifying the width of the line.  The default is 1.  A value\nof 2 is twice as wide as the default, etc.\n@end table\n\n@node Marker Styles\n@subsection Marker Styles\n@cindex graphics marker styles\n@cindex marker styles, graphics\n\nMarker styles are specified by the following properties:\n\n@table @code\n@item marker\nA character indicating a plot marker to be place at each data point, or\n@qcode{\"none\"}, meaning no markers should be displayed.\n\n@item markeredgecolor\nThe color of the edge around the marker, or @qcode{\"auto\"}, meaning that\nthe edge color is the same as the face color.  @xref{Colors}.\n\n@item markerfacecolor\nThe color of the marker, or @qcode{\"none\"} to indicate that the marker\nshould not be filled.  @xref{Colors}.\n\n@item markersize\nA number specifying the size of the marker.  The default is 1.  A value\nof 2 is twice as large as the default, etc.\n@end table\n\nThe @code{colstyle} function will parse a @code{plot}-style specification\nand will return the color, line, and marker values that would result.\n\n@DOCSTRING(colstyle)\n\n@node Callbacks\n@subsection Callbacks\n@cindex callbacks\n\nCallback functions can be associated with graphics objects and triggered\nafter certain events occur.  The basic structure of all callback function\nis\n\n@example\n@group\nfunction mycallback (hsrc, evt)\n  @dots{}\nendfunction\n@end group\n@end example\n\n@noindent\nwhere @code{hsrc} is a handle to the source of the callback, and @code{evt}\ngives some event specific data.\n\nThe function can be provided as a function handle to a plain Octave function,\nas an anonymous function, or as a string representing an Octave command.  The\nlatter syntax is not recommended since syntax errors will only occur when the\nstring is evaluated.\n@xref{Function Handles and Anonymous Functions,,Function Handles}.\n\nThis can then be associated with an object either at the object's creation, or\nlater with the @code{set} function.  For example,\n\n@example\nplot (x, \"DeleteFcn\", @@(h, e) disp (\"Window Deleted\"))\n@end example\n\n@noindent\nwhere at the moment that the plot is deleted, the message\n@qcode{\"Window Deleted\"} will be displayed.\n\nAdditional user arguments can be passed to callback functions, and will be\npassed after the two default arguments.  For example:\n\n@example\n@group\nplot (x, \"DeleteFcn\", @{@@mycallback, \"1\"@})\n@dots{}\nfunction mycallback (h, evt, arg1)\n  fprintf (\"Closing plot %d\\n\", arg1);\nendfunction\n@end group\n@end example\n\n@strong{Caution:} The second argument in callback functions---@code{evt}---is\nonly partially implemented in the Qt graphics toolkit:\n\n@itemize @bullet\n@item Mouse click events:\n@code{evt} is a class @code{double} value: 1 for left, 2 for middle, and 3 for\nright click.\n\n@item Key press events:\n@code{evt} is a structure with fields @code{Key} (string), @code{Character}\n(string), and @code{Modifier} (cell array of strings).\n\n@item Other events:\n@code{evt} is a class @code{double} empty matrix.\n@end itemize\n\nThe basic callback functions that are available for all graphics objects are\n\n@itemize @bullet\n@item CreateFcn:\ncalled at the moment of the objects creation.  It is not called if the\nobject is altered in any way, and so it only makes sense to define this\ncallback in the function call that defines the object.  Callbacks that\nare added to @code{CreateFcn} later with the @code{set} function will\nnever be executed.\n\n@item DeleteFcn:\ncalled at the moment an object is deleted.\n\n@item ButtonDownFcn:\ncalled if a mouse button is pressed while the pointer is over this\nobject.  Note, that the gnuplot interface does not implement this\ncallback.\n@end itemize\n\nBy default callback functions are queued (they are executed one after the other\nin the event queue) unless the @code{drawnow}, @code{figure}, @code{waitfor},\n@code{getframe}, or @code{pause} functions are used.  If an executing callback\ninvokes one of those functions, it causes Octave to flush the event queue,\nwhich results in the executing callback being interrupted.\n\nIt is possible to specify that an object's callbacks should not be interrupted\nby setting the object's @code{interruptible} property to @qcode{\"off\"}.  In\nthis case, Octave decides what to do based on the @code{busyaction} property of\nthe @strong{interrupting} callback object:\n\n@table @asis\n@item @code{queue} (the default)\nThe interrupting callback is executed after the executing callback has\nreturned.\n\n@item @code{cancel}\nThe interrupting callback is discarded.\n@end table\n\nThe @code{interruptible} property has no effect when the interrupting callback\nis a @code{deletefcn}, or a figure @code{resizefcn} or @code{closerequestfcn}.\nThose callbacks always interrupt the executing callback.\n\nThe handle to the object that holds the callback being executed can be\nobtained with the @code{gcbo} function.  The handle to the ancestor figure\nof this object may be obtained using the @code{gcbf} function.\n\n@DOCSTRING(gcbo)\n\n@DOCSTRING(gcbf)\n\nCallbacks can equally be added to properties with the @code{addlistener}\nfunction described below.\n\n@node Application-defined Data\n@subsection Application-defined Data\n@cindex application-defined data\n\nOctave has a provision for attaching application-defined data to a graphics\nhandle.  The data can be anything which is meaningful to the application, and\nwill be completely ignored by Octave.\n\n@DOCSTRING(setappdata)\n\n@DOCSTRING(getappdata)\n\n@DOCSTRING(rmappdata)\n\n@DOCSTRING(isappdata)\n\n@node Object Groups\n@subsection Object Groups\n@cindex object groups\n\nA number of Octave high level plot functions return groups of other\ngraphics objects or they return graphics objects that have their\nproperties linked in such a way that changes to one of the properties\nresults in changes in the others.  A graphic object that groups other\nobjects is an @code{hggroup}\n\n@DOCSTRING(hggroup)\n\nFor example a simple use of a @code{hggroup} might be\n\n@example\n@group\nx = 0:0.1:10;\nhg = hggroup ();\nplot (x, sin (x), \"color\", [1, 0, 0], \"parent\", hg);\nhold on\nplot (x, cos (x), \"color\", [0, 1, 0], \"parent\", hg);\nset (hg, \"visible\", \"off\");\n@end group\n@end example\n\n@noindent\nwhich groups the two plots into a single object and controls their\nvisibility directly.  The default properties of an @code{hggroup} are\nthe same as the set of common properties for the other graphics\nobjects.  Additional properties can be added with the @code{addproperty}\nfunction.\n\n@DOCSTRING(addproperty)\n\nOnce a property in added to an @code{hggroup}, it is not linked to any\nother property of either the children of the group, or any other\ngraphics object.  Add so to control the way in which this newly added\nproperty is used, the @code{addlistener} function is used to define a\ncallback function that is executed when the property is altered.\n\n@DOCSTRING(addlistener)\n\n@DOCSTRING(dellistener)\n\nAn example of the use of these two functions might be\n\n@example\n@group\nx = 0:0.1:10;\nhg = hggroup ();\nh = plot (x, sin (x), \"color\", [1, 0, 0], \"parent\", hg);\naddproperty (\"linestyle\", hg, \"linelinestyle\", get (h, \"linestyle\"));\naddlistener (hg, \"linestyle\", @@update_props);\nhold on\nplot (x, cos (x), \"color\", [0, 1, 0], \"parent\", hg);\n\nfunction update_props (h, d)\n  set (get (h, \"children\"), \"linestyle\", get (h, \"linestyle\"));\nendfunction\n@end group\n@end example\n\n@noindent\nthat adds a @code{linestyle} property to the @code{hggroup} and\npropagating any changes its value to the children of the group.  The\n@code{linkprop} function can be used to simplify the above to be\n\n@example\n@group\nx = 0:0.1:10;\nhg = hggroup ();\nh1 = plot (x, sin (x), \"color\", [1, 0, 0], \"parent\", hg);\naddproperty (\"linestyle\", hg, \"linelinestyle\", get (h, \"linestyle\"));\nhold on\nh2 = plot (x, cos (x), \"color\", [0, 1, 0], \"parent\", hg);\nhlink = linkprop ([hg, h1, h2], \"color\");\n@end group\n@end example\n\n@DOCSTRING(linkprop)\n\n@DOCSTRING(linkaxes)\n\nThese capabilities are used in a number of basic graphics objects.\nThe @code{hggroup} objects created by the functions of Octave contain\none or more graphics object and are used to:\n\n@itemize @bullet\n@item group together multiple graphics objects,\n\n@item create linked properties between different graphics objects, and\n\n@item to hide the nominal user data, from the actual data of the objects.\n@end itemize\n\n@noindent\nFor example the @code{stem} function creates a stem series where each\n@code{hggroup} of the stem series contains two line objects representing\nthe body and head of the stem.  The @code{ydata} property of the\n@code{hggroup} of the stem series represents the head of the stem,\nwhereas the body of the stem is between the baseline and this value.  For\nexample\n\n@example\n@group\nh = stem (1:4)\nget (h, \"xdata\")\n@xresult{} [  1   2   3   4]'\nget (get (h, \"children\")(1), \"xdata\")\n@xresult{} [  1   1 NaN   2   2 NaN   3   3 NaN   4   4 NaN]'\n@end group\n@end example\n\n@noindent\nshows the difference between the @code{xdata} of the @code{hggroup}\nof a stem series object and the underlying line.\n\nThe basic properties of such group objects is that they consist of one\nor more linked @code{hggroup}, and that changes in certain properties of\nthese groups are propagated to other members of the group.  Whereas,\ncertain properties of the members of the group only apply to the current\nmember.\n\nIn addition the members of the group can also be linked to other\ngraphics objects through callback functions.  For example the baseline of\nthe @code{bar} or @code{stem} functions is a line object, whose length\nand position are automatically adjusted, based on changes to the\ncorresponding hggroup elements.\n\n@menu\n* Data Sources in Object Groups::\n* Area Series::\n* Bar Series::\n* Contour Groups::\n* Error Bar Series::\n* Line Series::\n* Quiver Group::\n* Stair Group::\n* Stem Series::\n* Surface Group::\n@end menu\n\n@node Data Sources in Object Groups\n@subsubsection Data Sources in Object Groups\n@cindex data sources in object groups\n\nAll of the group objects contain data source parameters.  There are\nstring parameters that contain an expression that is evaluated to update\nthe relevant data property of the group when the @code{refreshdata}\nfunction is called.\n\n@DOCSTRING(refreshdata)\n\n@anchor{XREFlinkdata}\n@c FIXME: Add the description of the linkdata function here when it is written.\n@c Remove the explicit anchor when you add the corresponding @DOCSTRING command.\n\n@node Area Series\n@subsubsection Area Series\n@cindex series objects\n@cindex area series\n\nArea series objects are created by the @code{area} function.  Each of the\n@code{hggroup} elements contains a single patch object.  The properties\nof the area series are\n\n@table @code\n@item basevalue\nThe value where the base of the area plot is drawn.\n\n@item  linewidth\n@itemx linestyle\nThe line width and style of the edge of the patch objects making up the\nareas.  @xref{Line Styles}.\n\n@item  edgecolor\n@itemx facecolor\nThe line and fill color of the patch objects making up the areas.\n@xref{Colors}.\n\n@item  xdata\n@itemx ydata\nThe x and y coordinates of the original columns of the data passed to\n@code{area} prior to the cumulative summation used in the @code{area}\nfunction.\n\n@item  xdatasource\n@itemx ydatasource\nData source variables.\n@end table\n\n@node Bar Series\n@subsubsection Bar Series\n@cindex series objects\n@cindex bar series\n\nBar series objects are created by the @code{bar} or @code{barh}\nfunctions.  Each @code{hggroup} element contains a single patch object.\nThe properties of the bar series are\n\n@table @code\n@item  showbaseline\n@itemx baseline\n@itemx basevalue\nThe property @code{showbaseline} flags whether the baseline of the bar\nseries is displayed (default is @qcode{\"on\"}).  The handle of the graphics\nobject representing the baseline is given by the @code{baseline} property and\nthe y-value of the baseline by the @code{basevalue} property.\n\nChanges to any of these properties are propagated to the other members of\nthe bar series and to the baseline itself.  Equally, changes in the\nproperties of the base line itself are propagated to the members of the\ncorresponding bar series.\n\n@item  barwidth\n@itemx barlayout\n@itemx horizontal\nThe property @code{barwidth} is the width of the bar corresponding to\nthe @var{width} variable passed to @code{bar} or @var{barh}.  Whether the\nbar series is @qcode{\"grouped\"} or @qcode{\"stacked\"} is determined by the\n@code{barlayout} property and whether the bars are horizontal or\nvertical by the @code{horizontal} property.\n\nChanges to any of these property are propagated to the other members of\nthe bar series.\n\n@item  linewidth\n@itemx linestyle\nThe line width and style of the edge of the patch objects making up the\nbars.  @xref{Line Styles}.\n\n@item  edgecolor\n@itemx facecolor\nThe line and fill color of the patch objects making up the bars.\n@xref{Colors}.\n\n@item xdata\nThe nominal x positions of the bars.  Changes in this property and\npropagated to the other members of the bar series.\n\n@item ydata\nThe y value of the bars in the @code{hggroup}.\n\n@item  xdatasource\n@itemx ydatasource\nData source variables.\n@end table\n\n@node Contour Groups\n@subsubsection Contour Groups\n@cindex series objects\n@cindex contour series\n\nContour group objects are created by the @code{contour}, @code{contourf}, and\n@code{contour3} functions.  They are also one of the handles returned by the\n@code{surfc} and @code{meshc} functions.  The properties of the contour group\nare\n\n@table @code\n@item contourmatrix\nA read only property that contains the data return by @code{contourc} used to\ncreate the contours of the plot.\n\n@item fill\nA radio property that can have the values @qcode{\"on\"} or @qcode{\"off\"} that\nflags whether the contours to plot are to be filled.\n\n@item  zlevelmode\n@itemx zlevel\nThe radio property @code{zlevelmode} can have the values @qcode{\"none\"},\n@qcode{\"auto\"}, or @qcode{\"manual\"}.  When its value is @qcode{\"none\"} there is\nno z component to the plotted contours.  When its value is @qcode{\"auto\"} the z\nvalue of the plotted contours is at the same value as the contour itself.  If\nthe value is @qcode{\"manual\"}, then the z value at which to plot the contour is\ndetermined by the @code{zlevel} property.\n\n@item  levellistmode\n@itemx levellist\n@itemx levelstepmode\n@itemx levelstep\nIf @code{levellistmode} is @qcode{\"manual\"}, then the levels at which to plot\nthe contours is determined by @code{levellist}.  If @code{levellistmode} is set\nto @qcode{\"auto\"}, then the distance between contours is determined by\n@code{levelstep}.  If both @code{levellistmode} and @code{levelstepmode} are\nset to @qcode{\"auto\"}, then there are assumed to be 10 equal spaced contours.\n\n@item  textlistmode\n@itemx textlist\n@itemx textstepmode\n@itemx textstep\nIf @code{textlistmode} is @qcode{\"manual\"}, then the labeled contours\nis determined by @code{textlist}.  If @code{textlistmode} is set to\n@qcode{\"auto\"}, then the distance between labeled contours is determined by\n@code{textstep}.  If both @code{textlistmode} and @code{textstepmode}\nare set to @qcode{\"auto\"}, then there are assumed to be 10 equal spaced\nlabeled contours.\n\n@item showtext\nFlag whether the contour labels are shown or not.\n\n@item labelspacing\nThe distance between labels on a single contour in points.\n\n@item linewidth\n\n@item linestyle\n\n@item linecolor\nThe properties of the contour lines.  The properties @code{linewidth} and\n@code{linestyle} are similar to the corresponding properties for lines.  The\nproperty @code{linecolor} is a color property (@pxref{Colors}), that can also\nhave the values of @qcode{\"none\"} or @qcode{\"auto\"}.  If @code{linecolor} is\n@qcode{\"none\"}, then no contour line is drawn.  If @code{linecolor} is\n@qcode{\"auto\"} then the line color is determined by the colormap.\n\n@item  xdata\n@itemx ydata\n@itemx zdata\nThe original x, y, and z data of the contour lines.\n\n@item  xdatasource\n@itemx ydatasource\n@itemx zdatasource\nData source variables.\n@end table\n\n@node Error Bar Series\n@subsubsection Error Bar Series\n@cindex series objects\n@cindex error bar series\n\nError bar series are created by the @code{errorbar} function.  Each\n@code{hggroup} element contains two line objects representing the data and\nthe errorbars separately.  The properties of the error bar series are\n\n@table @code\n@item color\nThe RGB color or color name of the line objects of the error bars.\n@xref{Colors}.\n\n@item  linewidth\n@itemx linestyle\nThe line width and style of the line objects of the error bars.\n@xref{Line Styles}.\n\n@item  marker\n@itemx markeredgecolor\n@itemx markerfacecolor\n@itemx markersize\nThe line and fill color of the markers on the error bars.  @xref{Colors}.\n\n@item  xdata\n@itemx ydata\n@itemx ldata\n@itemx udata\n@itemx xldata\n@itemx xudata\nThe original x, y, l, u, @nospell{xl, xu} data of the error bars.\n\n@item  xdatasource\n@itemx ydatasource\n@itemx ldatasource\n@itemx udatasource\n@itemx xldatasource\n@itemx xudatasource\nData source variables.\n@end table\n\n@node Line Series\n@subsubsection Line Series\n@cindex series objects\n@cindex line series\n\nLine series objects are created by the @code{plot}  and @code{plot3}\nfunctions and are of the type @code{line}.  The properties of the\nline series with the ability to add data sources.\n\n@table @code\n@item color\nThe RGB color or color name of the line objects.  @xref{Colors}.\n\n@item  linewidth\n@itemx linestyle\nThe line width and style of the line objects.  @xref{Line Styles}.\n\n@item  marker\n@itemx markeredgecolor\n@itemx markerfacecolor\n@itemx markersize\nThe line and fill color of the markers.  @xref{Colors}.\n\n@item  xdata\n@itemx ydata\n@itemx zdata\nThe original x, y and z data.\n\n@item  xdatasource\n@itemx ydatasource\n@itemx zdatasource\nData source variables.\n@end table\n\n@node Quiver Group\n@subsubsection Quiver Group\n@cindex group objects\n@cindex quiver group\n\nQuiver series objects are created by the @code{quiver} or @code{quiver3}\nfunctions.  Each @code{hggroup} element of the series contains three line\nobjects as children representing the body and head of the arrow,\ntogether with a marker as the point of origin of the arrows.  The\nproperties of the quiver series are\n\n@table @code\n@item  autoscale\n@itemx autoscalefactor\nFlag whether the length of the arrows is scaled or defined directly from\nthe @var{u}, @var{v} and @var{w} data.  If the arrow length is flagged\nas being scaled by the @code{autoscale} property, then the length of the\nautoscaled arrow is controlled by the @code{autoscalefactor}.\n\n@item maxheadsize\nThis property controls the size of the head of the arrows in the quiver\nseries.  The default value is 0.2.\n\n@item showarrowhead\nFlag whether the arrow heads are displayed in the quiver plot.\n\n@item color\nThe RGB color or color name of the line objects of the quiver.  @xref{Colors}.\n\n@item  linewidth\n@itemx linestyle\nThe line width and style of the line objects of the quiver.\n@xref{Line Styles}.\n\n@item  marker\n@itemx markerfacecolor\n@itemx markersize\nThe line and fill color of the marker objects at the original of the\narrows.  @xref{Colors}.\n\n@item  xdata\n@itemx ydata\n@itemx zdata\nThe origins of the values of the vector field.\n\n@item  udata\n@itemx vdata\n@itemx wdata\nThe values of the vector field to plot.\n\n@item  xdatasource\n@itemx ydatasource\n@itemx zdatasource\n@itemx udatasource\n@itemx vdatasource\n@itemx wdatasource\nData source variables.\n@end table\n\n@node Stair Group\n@subsubsection Stair Group\n@cindex group objects\n@cindex stair group\n\nStair series objects are created by the @code{stair} function.  Each\n@code{hggroup} element of the series contains a single line object as a\nchild representing the stair.  The properties of the stair series are\n\n@table @code\n@item color\nThe RGB color or color name of the line objects of the stairs.  @xref{Colors}.\n\n@item  linewidth\n@itemx linestyle\nThe line width and style of the line objects of the stairs.\n@xref{Line Styles}.\n\n@item  marker\n@itemx markeredgecolor\n@itemx markerfacecolor\n@itemx markersize\nThe line and fill color of the markers on the stairs.  @xref{Colors}.\n\n@item  xdata\n@itemx ydata\nThe original x and y data of the stairs.\n\n@item  xdatasource\n@itemx ydatasource\nData source variables.\n@end table\n\n@node Stem Series\n@subsubsection Stem Series\n@cindex series objects\n@cindex stem series\n\nStem series objects are created by the @code{stem} or @code{stem3}\nfunctions.  Each @code{hggroup} element contains a single line object\nas a child representing the stems.  The properties of the stem series\nare\n\n@table @code\n@item  showbaseline\n@itemx baseline\n@itemx basevalue\nThe property @code{showbaseline} flags whether the baseline of the\nstem series is displayed (default is @qcode{\"on\"}).  The handle of the graphics\nobject representing the baseline is given by the @code{baseline}\nproperty and the y-value (or z-value for @code{stem3}) of the baseline\nby the @code{basevalue} property.\n\nChanges to any of these property are propagated to the other members of\nthe stem series and to the baseline itself.  Equally changes in the\nproperties of the base line itself are propagated to the members of the\ncorresponding stem series.\n\n@item color\nThe RGB color or color name of the line objects of the stems.  @xref{Colors}.\n\n@item  linewidth\n@itemx linestyle\nThe line width and style of the line objects of the stems.  @xref{Line Styles}.\n\n@item  marker\n@itemx markeredgecolor\n@itemx markerfacecolor\n@itemx markersize\nThe line and fill color of the markers on the stems.  @xref{Colors}.\n\n@item  xdata\n@itemx ydata\n@itemx zdata\nThe original x, y and z data of the stems.\n\n@item  xdatasource\n@itemx ydatasource\n@itemx zdatasource\nData source variables.\n@end table\n\n@node Surface Group\n@subsubsection Surface Group\n@cindex group objects\n@cindex surface group\n\nSurface group objects are created by the @code{surf} or @code{mesh}\nfunctions, but are equally one of the handles returned by the @code{surfc}\nor @code{meshc} functions.  The surface group is of the type @code{surface}.\n\nThe properties of the surface group are\n\n@table @code\n@item edgecolor\n\n@item facecolor\nThe RGB color or color name of the edges or faces of the surface.\n@xref{Colors}.\n\n@item  linewidth\n@itemx linestyle\nThe line width and style of the lines on the surface.  @xref{Line Styles}.\n\n@item  marker\n@itemx markeredgecolor\n@itemx markerfacecolor\n@itemx markersize\nThe line and fill color of the markers on the surface.  @xref{Colors}.\n\n@item  xdata\n@itemx ydata\n@itemx zdata\n@itemx cdata\nThe original x, y, z and c data.\n\n@item  xdatasource\n@itemx ydatasource\n@itemx zdatasource\n@itemx cdatasource\nData source variables.\n@end table\n\n@node Transform Groups\n@subsection Transform Groups\n@cindex transform groups\n\n@c FIXME: Need to add documentation on transforms.\n\n@DOCSTRING(hgtransform)\n\n@c @DOCSTRING(makehgtform)\n\n@node Graphics Toolkits\n@subsection Graphics Toolkits\n@cindex graphics toolkits\n@cindex toolkits, graphics\n\n@DOCSTRING(graphics_toolkit)\n\n@DOCSTRING(available_graphics_toolkits)\n\n@DOCSTRING(loaded_graphics_toolkits)\n\n@DOCSTRING(register_graphics_toolkit)\n\n@menu\n* Customizing Toolkit Behavior::\n* Hardware vs Software Rendering::\n* Precision issues::\n@end menu\n\n@node Customizing Toolkit Behavior\n@subsubsection Customizing Toolkit Behavior\n@cindex toolkit customization\n\nThe specific behavior of the backend toolkit may be modified using the\nfollowing utility functions.  Note: Not all functions apply to every\ngraphics toolkit.\n\n@DOCSTRING(gnuplot_binary)\n\n@cindex GNUTERM\n\nIn addition, the gnuplot program usually provides a number of different\ninterfaces, known as terminals.  Octave normally chooses a default terminal,\nbut you can override this with the environment variable @env{GNUTERM}.  This\nvariable may be set in the shell before starting Octave or from within Octave\nbefore plotting for the first time.  For example:\n\n@example\n@group\nsetenv (\"GNUTERM\", \"wxt\")\ngraphics_toolkit (\"gnuplot\")\nplot (1:10)\n@end group\n@end example\n\n@node Hardware vs Software Rendering\n@subsubsection Hardware vs Software Rendering\n@cindex opengl rendering slow windows\n\nOn some platforms, it is possible to choose between hardware (GPU-accelerated)\nand software (CPU-based) OpenGL rendering through the use of the Mesa 3D\nsoftware implementation.  The choice between hardware or software rendering\nonly affects the OpenGL graphics toolkits (@qcode{\"qt\"}, @qcode{\"fltk\"}).\nUsing software rendering can avoid rendering and printing issues due to the\nimperfect OpenGL driver implementations of diverse graphic cards from different\nvendors (notably integrated Intel graphics).  The downside is that software\nrendering may be considerably slower than hardware-accelerated rendering.\n\nOn Linux and MacOS systems that have a Mesa 3-D based driver, switching to\nsoftware rendering is done at Octave startup (or at least before any graphics\nfunction has been called) by setting the environment variable\n@w{@env{LIBGL_ALWAYS_SOFTWARE}}, e.g.,\n@code{setenv (@w{\"LIBGL_ALWAYS_SOFTWARE\"}, \"1\")}.\n\nOn Windows, Octave is shipped with @file{opengl32.dll}, a Mesa 3-D based\nsoftware rendering library.  When using the Windows installer for Octave, the\nuser has the option to select between @w{@qcode{\"System OpenGL\"}} and\n@w{@qcode{\"Software OpenGL\"}} renderers.  The OpenGL driver may also be switched\nlater using the @w{@qcode{\"OpenGL Switcher\"}} application from the Start menu\nwhile Octave is closed.  Alternatively, one can rename the following file while\nOctave is closed:\n\n@file{@var{octave-home}\\bin\\opengl32.dll}\n\n@noindent\nwhere @var{octave-home} is the directory returned by\n@ref{XREFOCTAVE_HOME,,@w{@code{OCTAVE_HOME}}}, i.e., the directory in which\nOctave is installed (the default is\n@file{C:\\Program Files\\GNU Octave\\Octave\\Octave-@var{version}\\mingw64}).\nChange the file extension to @file{.bak} for hardware rendering or to\n@file{.dll} for software rendering.\n\n@node Precision issues\n@subsubsection Precision issues\n@cindex opengl single precision date time\n\nThe OpenGL graphics toolkits (@qcode{\"qt\"} and @qcode{\"fltk\"}) use single\nprecision for rendering.  This limitation in particular applies to plots of\ntime series against serial dates as used by the @code{datenum}, @code{datestr},\n@code{datestruct}, and @code{datetick} functions.\n\nSerial dates encode timestamps as days elapsed since the year zero with hours,\nminutes, seconds as the fractional part.  On December 31st 1999, the serial\ndate representation was 730485.  A double precision variable with this integer\npart allows for a resolution in its fractional part of 1.2e-10, representing\nabout 5 microseconds.  But with single precision, the resolution is reduced to\nabout 0.06, representing 45 minutes.  Any attempt to plot timestamped data\nwith finer granularity will result in a distorted graph.\n\nAs a workaround, it is possible to use the @qcode{\"gnuplot\"} graphics toolkit\nor subtract 2000 years---i.e., @code{datenum (2000, 0, 0)} or 730485---from the\ntime values.  Due to the fact that the calendar structure repeats every 2000\nyears, the relation between year, month, day of month and day of week will stay\nunchanged and the ticks and ticklabels produced by the @code{datetick} function\nwill still be correct.  Only years will lack the millennium digit.  Thus,\n\"2020\" will be printed as \"20\".  For example:\n\n@example\n@group\n# timestamps of 24 hours in one minute steps\nt = datenum (2020, 1, 1):(1/1440):datenum (2020, 1, 2);\n\n# some example time series data\nx = -cos (2*pi*t) + rand (size (t)) / 10;\n\nsubplot (1, 2, 1);\nplot (t, x);\ndatetick (\"x\");\nxlabel (\"serial date\");\ntitle (\"problem\");\n\nsubplot (1, 2, 2);\nplot (t - 730485, x);\ndatetick (\"x\");\nxlabel (\"2000 years off\");\ntitle (\"workaround\");\n@end group\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:precisiondate}.\n\n@float Figure,fig:precisiondate\n@center @image{precisiondate,4in}\n@caption{Single precision issues with OpenGL graphics toolkits}\n@end float\n@end ifnotinfo\n\nSimilarly, other data can be translated or re-scaled to work around this issue.\n"
  },
  {
    "path": "doc/interpreter/plotimages.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nfunction plotimages (d, nm, typ)\n\n  if (strcmp (typ , \"txt\"))\n    image_as_txt (d, nm);\n    return;\n  endif\n\n  set_graphics_toolkit ();\n  set_print_size ();\n  hide_output ();\n  outfile = fullfile (d, [nm \".\" typ]);\n  if (strcmp (typ, \"png\"))\n    set (groot, \"defaulttextfontname\", \"*\");\n  endif\n  if (strcmp (typ, \"eps\"))\n    d_typ = \"-depsc2\";\n  else\n    d_typ = [\"-d\", typ];\n  endif\n\n  if (strcmp (nm, \"plot\"))\n    x = -10:0.1:10;\n    plot (x, sin (x));\n    xlabel (\"x\");\n    ylabel (\"sin (x)\");\n    title (\"Simple 2-D Plot\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"hist\"))\n    randn (\"state\", 1);\n    hist (randn (10000, 1), 30);\n    xlabel (\"Value\");\n    ylabel (\"Count\");\n    title (\"Histogram of 10,000 normally distributed random numbers\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"errorbar\"))\n    rand (\"state\", 2);\n    x = 0:0.1:10;\n    y = sin (x);\n    lerr = 0.1 .* rand (size (x));\n    uerr = 0.1 .* rand (size (x));\n    errorbar (x, y, lerr, uerr);\n    axis ([0, 10, -1.1, 1.1]);\n    xlabel (\"x\");\n    ylabel (\"sin (x)\");\n    title (\"Errorbar plot of sin (x)\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"polar\"))\n    polar (0:0.1:10*pi, 0:0.1:10*pi);\n    title (\"Example polar plot from 0 to 10*pi\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"mesh\"))\n    tx = ty = linspace (-8, 8, 41)';\n    [xx, yy] = meshgrid (tx, ty);\n    r = sqrt (xx .^ 2 + yy .^ 2) + eps;\n    tz = sin (r) ./ r;\n    mesh (tx, ty, tz);\n    xlabel (\"tx\");\n    ylabel (\"ty\");\n    zlabel (\"tz\");\n    title (\"3-D Sombrero plot\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"plot3\"))\n    t = 0:0.1:10*pi;\n    r = linspace (0, 1, numel (t));\n    z = linspace (0, 1, numel (t));\n    plot3 (r.*sin (t), r.*cos (t), z);\n    xlabel (\"r.*sin (t)\");\n    ylabel (\"r.*cos (t)\");\n    zlabel (\"z\");\n    title (\"plot3 display of 3-D helix\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"extended\"))\n    x = 0:0.01:3;\n    plot (x, erf (x));\n    hold on;\n    plot (x, x, \"r\");\n    axis ([0, 3, 0, 1]);\n    xlabel (\"x\");\n    ylabel (\"erf (x)\");\n    title (\"erf (x) with text annotation\");\n    if (strcmp (typ, \"pdf\") && ! strcmp (graphics_toolkit, \"gnuplot\"))\n      text (0.65, 0.6175, ['$\\displaystyle\\leftarrow x = {2\\over\\sqrt{\\pi}}'...\n                           '\\int_{0}^{x}e^{-t^2} dt = 0.6175$'],\n            \"interpreter\", \"latex\");\n      ## Be very careful about modifying this.  pdflatex expects to be in\n      ## the same directory as the file it is operating on.\n      cd (make_absolute_filename (d));\n      print ([nm \".pdf\"], \"-dpdflatexstandalone\");\n      [status, output] = system ([\"pdflatex \" nm]);\n      if (status)\n        error (\"plotimages: Failed to run pdflatex on <extended.pdf>\");\n      endif\n      delete ([nm \".aux\"], [nm \"-inc.pdf\"], [nm \".log\"], [nm \".tex\"]);\n    else\n      text (0.65, 0.6175, ['\\leftarrow x = {2/\\surd\\pi {\\fontsize{16}' ...\n            '\\int_{\\fontsize{8}0}^{\\fontsize{8}x}} e^{-t^2} dt} = 0.6175']);\n      print (outfile, d_typ);\n    endif\n  elseif (strcmp (nm, \"precisiondate\"))\n    rand (\"state\", 1);\n    t = datenum (2020, 1, 1):(1/1440):datenum (2020, 1, 2);\n    x = -cos (2*pi*t) + rand (size (t)) / 10;\n    subplot (1, 2, 1);\n    plot (t, x);\n    datetick (\"x\");\n    xlabel (\"serial date\");\n    title (\"problem\");\n    subplot (1, 2, 2);\n    plot (t - 730485, x);\n    datetick (\"x\");\n    xlabel (\"2000 years off\");\n    title (\"workaround\");\n    # set wider aspect ratio\n    image_size = [8.25, 3.5]; # in inches, 5:2 format\n    border = 0;              # For postscript use 50/72\n    set (gcf, \"papersize\", image_size + 2*border);\n    set (gcf, \"paperposition\", [border, border, image_size]);\n    print (outfile, d_typ);\n  else\n    error (\"unrecognized plot requested\");\n  endif\n  hide_output ();\nendfunction\n\n## This function no longer sets the graphics toolkit; That is now done\n## automatically by C++ code which will ordinarily choose 'qt', but might\n## choose gnuplot on older systems.  Only a complete lack of plotting is a\n## problem.\nfunction set_graphics_toolkit ()\n  if (isempty (available_graphics_toolkits ()))\n    error (\"no graphics toolkit available for plotting\");\n  elseif (strcmp (\"qt\", graphics_toolkit ()))\n    ## Use qt with QOffscreenSurface for plot\n  elseif (! strcmp (\"gnuplot\", graphics_toolkit ()))\n    if (! any (strcmp (\"gnuplot\", available_graphics_toolkits ())))\n      error (\"no graphics toolkit available for offscreen plotting\");\n    else\n      graphics_toolkit (\"gnuplot\");\n    endif\n  endif\nendfunction\n\nfunction set_print_size ()\n  image_size = [5.0, 3.5]; # in inches, 16:9 format\n  border = 0;              # For postscript use 50/72\n  set (groot, \"defaultfigurepapertype\", \"<custom>\");\n  set (groot, \"defaultfigurepaperorientation\", \"landscape\");\n  set (groot, \"defaultfigurepapersize\", image_size + 2*border);\n  set (groot, \"defaultfigurepaperposition\", [border, border, image_size]);\nendfunction\n\n## Use this function before plotting commands and after every call to print\n## since print() resets output to stdout (unfortunately, gnuplot can't pop\n## output as it can the terminal type).\nfunction hide_output ()\n  hf = figure (1, \"visible\", \"off\");\nendfunction\n\n## generate something for the texinfo @image command to process\nfunction image_as_txt (d, nm)\n  fid = fopen (fullfile (d, [nm \".txt\"]), \"wt\");\n  fputs (fid, \"\\n\");\n  fputs (fid, \"+---------------------------------+\\n\");\n  fputs (fid, \"| Image unavailable in text mode. |\\n\");\n  fputs (fid, \"+---------------------------------+\\n\");\n  fclose (fid);\nendfunction\n"
  },
  {
    "path": "doc/interpreter/poly.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Polynomial Manipulations\n@chapter Polynomial Manipulations\n\nIn Octave, a polynomial is represented by its coefficients (arranged\nin descending order).  For example, a vector @var{c} of length\n@math{N+1} corresponds to the following polynomial of order\n@tex\n $N$\n$$\n p (x) = c_1 x^N + \\ldots + c_N x + c_{N+1}.\n$$\n@end tex\n@ifnottex\n @var{N}\n\n@example\np(x) = @var{c}(1) x^@var{N} + @dots{} + @var{c}(@var{N}) x + @var{c}(@var{N}+1).\n@end example\n\n@end ifnottex\n\n@menu\n* Evaluating Polynomials::\n* Finding Roots::\n* Products of Polynomials::\n* Derivatives / Integrals / Transforms::\n* Polynomial Interpolation::\n* Miscellaneous Functions::\n@end menu\n\n@node Evaluating Polynomials\n@section Evaluating Polynomials\n\nThe value of a polynomial represented by the vector @var{c} can be evaluated\nat the point @var{x} very easily, as the following example shows:\n\n@example\n@group\nN = length (c) - 1;\nval = dot (x.^(N:-1:0), c);\n@end group\n@end example\n\n@noindent\nWhile the above example shows how easy it is to compute the value of a\npolynomial, it isn't the most stable algorithm.  With larger polynomials\nyou should use more elegant algorithms, such as @nospell{Horner's} Method,\nwhich is exactly what the Octave function @code{polyval} does.\n\nIn the case where @var{x} is a square matrix, the polynomial given by\n@var{c} is still well-defined.  As when @var{x} is a scalar the obvious\nimplementation is easily expressed in Octave, but also in this case\nmore elegant algorithms perform better.  The @code{polyvalm} function\nprovides such an algorithm.\n\n@DOCSTRING(polyval)\n\n@DOCSTRING(polyvalm)\n\n@node Finding Roots\n@section Finding Roots\n\nOctave can find the roots of a given polynomial.  This is done by computing\nthe companion matrix of the polynomial (see the @code{compan} function\nfor a definition), and then finding its eigenvalues.\n\n@DOCSTRING(roots)\n\n@DOCSTRING(polyeig)\n\n@DOCSTRING(compan)\n\n@DOCSTRING(mpoles)\n\n@node Products of Polynomials\n@section Products of Polynomials\n\n@DOCSTRING(conv)\n\n@DOCSTRING(convn)\n\n@DOCSTRING(deconv)\n\n@DOCSTRING(conv2)\n\n@DOCSTRING(polygcd)\n\n@DOCSTRING(residue)\n\n@node Derivatives / Integrals / Transforms\n@section Derivatives / Integrals / Transforms\n\nOctave comes with functions for computing the derivative and the integral\nof a polynomial.  The functions @code{polyder} and @code{polyint}\nboth return new polynomials describing the result.  As an example we'll\ncompute the definite integral of @math{p(x) = x^2 + 1} from 0 to 3.\n\n@example\n@group\nc = [1, 0, 1];\nintegral = polyint (c);\narea = polyval (integral, 3) - polyval (integral, 0)\n@xresult{} 12\n@end group\n@end example\n\n@DOCSTRING(polyder)\n\n@DOCSTRING(polyint)\n\n@DOCSTRING(polyaffine)\n\n@node Polynomial Interpolation\n@section Polynomial Interpolation\n\nOctave comes with good support for various kinds of interpolation,\nmost of which are described in @ref{Interpolation}.  One simple alternative\nto the functions described in the aforementioned chapter, is to fit\na single polynomial, or a piecewise polynomial (spline) to some given\ndata points.  To avoid a highly fluctuating polynomial, one most often\nwants to fit a low-order polynomial to data.  This usually means that it\nis necessary to fit the polynomial in a least-squares sense, which just\nis what the @code{polyfit} function does.\n\n@DOCSTRING(polyfit)\n\nIn situations where a single polynomial isn't good enough, a solution\nis to use several polynomials pieced together.  The function\n@code{splinefit} fits a piecewise polynomial (spline) to a set of\ndata.\n\n@DOCSTRING(splinefit)\n\nThe number of @var{breaks} (or knots) used to construct the piecewise\npolynomial is a significant factor in suppressing the noise present in\nthe input data, @var{x} and @var{y}.  This is demonstrated by the example\nbelow.\n\n@example\n@group\nx = 2 * pi * rand (1, 200);\ny = sin (x) + sin (2 * x) + 0.2 * randn (size (x));\n## Uniform breaks\nbreaks = linspace (0, 2 * pi, 41); % 41 breaks, 40 pieces\npp1 = splinefit (x, y, breaks);\n## Breaks interpolated from data\npp2 = splinefit (x, y, 10);  % 11 breaks, 10 pieces\n## Plot\nxx = linspace (0, 2 * pi, 400);\ny1 = ppval (pp1, xx);\ny2 = ppval (pp2, xx);\nplot (x, y, \".\", xx, [y1; y2])\naxis tight\nylim auto\nlegend (@{\"data\", \"41 breaks, 40 pieces\", \"11 breaks, 10 pieces\"@})\n@end group\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:splinefit1}.\n\n@float Figure,fig:splinefit1\n@center @image{splinefit1,4in}\n@caption{Comparison of a fitting a piecewise polynomial with 41 breaks to one\nwith 11 breaks.  The fit with the large number of breaks exhibits a fast ripple\nthat is not present in the underlying function.}\n@end float\n@end ifnotinfo\n\nThe piecewise polynomial fit, provided by @code{splinefit}, has\ncontinuous derivatives up to the @var{order}-1.  For example, a cubic fit\nhas continuous first and second derivatives.  This is demonstrated by\nthe code\n\n@example\n## Data (200 points)\nx = 2 * pi * rand (1, 200);\ny = sin (x) + sin (2 * x) + 0.1 * randn (size (x));\n## Piecewise constant\npp1 = splinefit (x, y, 8, \"order\", 0);\n## Piecewise linear\npp2 = splinefit (x, y, 8, \"order\", 1);\n## Piecewise quadratic\npp3 = splinefit (x, y, 8, \"order\", 2);\n## Piecewise cubic\npp4 = splinefit (x, y, 8, \"order\", 3);\n## Piecewise quartic\npp5 = splinefit (x, y, 8, \"order\", 4);\n## Plot\nxx = linspace (0, 2 * pi, 400);\ny1 = ppval (pp1, xx);\ny2 = ppval (pp2, xx);\ny3 = ppval (pp3, xx);\ny4 = ppval (pp4, xx);\ny5 = ppval (pp5, xx);\nplot (x, y, \".\", xx, [y1; y2; y3; y4; y5])\naxis tight\nylim auto\nlegend (@{\"data\", \"order 0\", \"order 1\", \"order 2\", \"order 3\", \"order 4\"@})\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:splinefit2}.\n\n@float Figure,fig:splinefit2\n@center @image{splinefit2,4in}\n@caption{Comparison of a piecewise constant, linear, quadratic, cubic, and\nquartic polynomials with 8 breaks to noisy data.  The higher order solutions\nmore accurately represent the underlying function, but come with the\nexpense of computational complexity.}\n@end float\n@end ifnotinfo\n\nWhen the underlying function to provide a fit to is periodic, @code{splinefit}\nis able to apply the boundary conditions needed to manifest a periodic fit.\nThis is demonstrated by the code below.\n\n@example\n@group\n## Data (100 points)\nx = 2 * pi * [0, (rand (1, 98)), 1];\ny = sin (x) - cos (2 * x) + 0.2 * randn (size (x));\n## No constraints\npp1 = splinefit (x, y, 10, \"order\", 5);\n## Periodic boundaries\npp2 = splinefit (x, y, 10, \"order\", 5, \"periodic\", true);\n## Plot\nxx = linspace (0, 2 * pi, 400);\ny1 = ppval (pp1, xx);\ny2 = ppval (pp2, xx);\nplot (x, y, \".\", xx, [y1; y2])\naxis tight\nylim auto\nlegend (@{\"data\", \"no constraints\", \"periodic\"@})\n@end group\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:splinefit3}.\n\n@float Figure,fig:splinefit3\n@center @image{splinefit3,4in}\n@caption{Comparison of piecewise polynomial fits to a noisy periodic\nfunction with, and without, periodic boundary conditions.}\n@end float\n@end ifnotinfo\n\nMore complex constraints may be added as well.  For example, the code below\nillustrates a periodic fit with values that have been clamped at the endpoints,\nand a second periodic fit which is hinged at the endpoints.\n\n@example\n## Data (200 points)\nx = 2 * pi * rand (1, 200);\ny = sin (2 * x) + 0.1 * randn (size (x));\n## Breaks\nbreaks = linspace (0, 2 * pi, 10);\n## Clamped endpoints, y = y' = 0\nxc = [0, 0, 2*pi, 2*pi];\ncc = [(eye (2)), (eye (2))];\ncon = struct (\"xc\", xc, \"cc\", cc);\npp1 = splinefit (x, y, breaks, \"constraints\", con);\n## Hinged periodic endpoints, y = 0\ncon = struct (\"xc\", 0);\npp2 = splinefit (x, y, breaks, \"constraints\", con, \"periodic\", true);\n## Plot\nxx = linspace (0, 2 * pi, 400);\ny1 = ppval (pp1, xx);\ny2 = ppval (pp2, xx);\nplot (x, y, \".\", xx, [y1; y2])\naxis tight\nylim auto\nlegend (@{\"data\", \"clamped\", \"hinged periodic\"@})\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:splinefit4}.\n\n@float Figure,fig:splinefit4\n@center @image{splinefit4,4in}\n@caption{Comparison of two periodic piecewise cubic fits to a noisy periodic\nsignal.  One fit has its endpoints clamped and the second has its endpoints\nhinged.}\n@end float\n@end ifnotinfo\n\nThe @code{splinefit} function also provides the convenience of a @var{robust}\nfitting, where the effect of outlying data is reduced.  In the example below,\nthree different fits are provided.  Two with differing levels of outlier\nsuppression and a third illustrating the non-robust solution.\n\n@example\n## Data\nx = linspace (0, 2*pi, 200);\ny = sin (x) + sin (2 * x) + 0.05 * randn (size (x));\n## Add outliers\nx = [x, linspace(0,2*pi,60)];\ny = [y, -ones(1,60)];\n## Fit splines with hinged conditions\ncon = struct (\"xc\", [0, 2*pi]);\n## Robust fitting, beta = 0.25\npp1 = splinefit (x, y, 8, \"constraints\", con, \"beta\", 0.25);\n## Robust fitting, beta = 0.75\npp2 = splinefit (x, y, 8, \"constraints\", con, \"beta\", 0.75);\n## No robust fitting\npp3 = splinefit (x, y, 8, \"constraints\", con);\n## Plot\nxx = linspace (0, 2*pi, 400);\ny1 = ppval (pp1, xx);\ny2 = ppval (pp2, xx);\ny3 = ppval (pp3, xx);\nplot (x, y, \".\", xx, [y1; y2; y3])\nlegend (@{\"data with outliers\",\"robust, beta = 0.25\", ...\n         \"robust, beta = 0.75\", \"no robust fitting\"@})\naxis tight\nylim auto\n@end example\n\n@ifnotinfo\n@noindent\nThe result of which can be seen in @ref{fig:splinefit6}.\n\n@float Figure,fig:splinefit6\n@center @image{splinefit6,4in}\n@caption{Comparison of two different levels of robust fitting (@var{beta} = 0.25 and 0.75) to noisy data combined with outlying data.  A conventional fit, without\nrobust fitting (@var{beta} = 0) is also included.}\n@end float\n@end ifnotinfo\n\nA very specific form of polynomial interpretation is the Pad@'e approximant.\nFor control systems, a continuous-time delay can be modeled very simply with\nthe approximant.\n\n@DOCSTRING(padecoef)\n\nThe function, @code{ppval}, evaluates the piecewise polynomials, created\nby @code{mkpp} or other means, and @code{unmkpp} returns detailed\ninformation about the piecewise polynomial.\n\nThe following example shows how to combine two linear functions and a\nquadratic into one function.  Each of these functions is expressed\non adjoined intervals.\n\n@example\n@group\nx = [-2, -1, 1, 2];\np = [ 0,  1, 0;\n      1, -2, 1;\n      0, -1, 1 ];\npp = mkpp (x, p);\nxi = linspace (-2, 2, 50);\nyi = ppval (pp, xi);\nplot (xi, yi);\n@end group\n@end example\n\n@DOCSTRING(mkpp)\n\n@DOCSTRING(unmkpp)\n\n@DOCSTRING(ppval)\n\n@DOCSTRING(ppder)\n\n@DOCSTRING(ppint)\n\n@DOCSTRING(ppjumps)\n\n@node Miscellaneous Functions\n@section Miscellaneous Functions\n\n@DOCSTRING(poly)\n\n@DOCSTRING(polyout)\n\n@DOCSTRING(polyreduce)\n"
  },
  {
    "path": "doc/interpreter/pr-idx.txi",
    "content": "@c Copyright (C) 2017-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Graphics Properties Index\n@unnumbered Graphics Properties Index\n\n@printindex pr\n"
  },
  {
    "path": "doc/interpreter/preface.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@ifclear AUTHORSONLY\n@node Preface\n@unnumbered Preface\n@cindex contributors\n@cindex history\n\nOctave was originally intended to be companion software for an\nundergraduate-level textbook on chemical reactor design being written by\n@nospell{James B. Rawlings} of the University of Wisconsin-Madison and\n@nospell{John G. Ekerdt} of the University of Texas.\n\nClearly, Octave is now much more than just another `courseware' package\nwith limited utility beyond the classroom.  Although our initial goals\nwere somewhat vague, we knew that we wanted to create something that\nwould enable students to solve realistic problems, and that they could\nuse for many things other than chemical reactor design problems.\nWe find that most students pick up the basics of Octave quickly, and are\nusing it confidently in just a few hours.\n\nAlthough it was originally intended to be used to teach reactor design,\nit has been used in several other undergraduate and graduate\ncourses in the Chemical Engineering Department at the University of\nTexas, and the math department at the University of Texas has been using\nit for teaching differential equations and linear algebra as well.\nMore recently, Octave has been used as the primary computational tool\nfor teaching Stanford's online Machine Learning class\n(@url{http://ml-class.org}) taught by Andrew Ng.  Tens of thousands of students\nparticipated in the course.\n\nIf you find Octave useful, please let us know.  We are always interested\nto find out how Octave is being used.\n\nVirtually everyone thinks that the name Octave has something to do with\nmusic, but it is actually the name of one of John W. Eaton's former\nprofessors who wrote a famous textbook on chemical reaction engineering,\nand who was also well known for his ability to do quick `back of the\nenvelope' calculations.  We hope that this software will make it\npossible for many people to do more ambitious computations just as\neasily.\n\nEveryone is encouraged to share this software with others under the\nterms of the GNU General Public License (@pxref{Copying}).  You are\nalso encouraged to help make Octave more useful by writing and\ncontributing additional functions for it, and by reporting any problems\nyou may have.\n\n@menu\n* Acknowledgements::\n* Citing Octave in Publications::\n* How You Can Contribute to Octave::\n* Distribution::\n@end menu\n\n@node Acknowledgements\n@unnumberedsec Acknowledgements\n@cindex acknowledgements\n@end ifclear\n\nMany people have contributed to Octave's development.  The\nfollowing people have helped code parts of Octave or aided in\nvarious other ways (listed alphabetically).\n\n@include contributors.texi\n\n@ifclear AUTHORSONLY\nSpecial thanks to the following people and organizations for\nsupporting the development of Octave:\n\n@itemize @bullet\n@item\nThe United States Department of Energy, through grant number\n@nospell{DE-FG02-04ER25635}.\n\n@item\n@nospell{Ashok Krishnamurthy, David Hudak, Juan Carlos Chaves}, and\n@nospell{Stanley C. Ahalt} of the Ohio Supercomputer Center.\n\n@item\nThe National Science Foundation, through grant numbers @nospell{CTS-0105360},\n@nospell{CTS-9708497, CTS-9311420, CTS-8957123, and CNS-0540147}.\n\n@item\nThe industrial members of the Texas-Wisconsin Modeling and Control\nConsortium (@nospell{TWMCC}).\n\n@item\nThe @nospell{Paul A. Elfers} Endowed Chair in Chemical Engineering at the\nUniversity of Wisconsin-Madison.\n\n@item\nDigital Equipment Corporation, for an equipment grant as part of their\nExternal Research Program.\n\n@item\n@nospell{Sun Microsystems}, Inc., for an Academic Equipment grant.\n\n@item\nInternational Business Machines, Inc., for providing equipment as part\nof a grant to the University of Texas College of Engineering.\n\n@item\nTexaco Chemical Company, for providing funding to continue the\ndevelopment of this software.\n\n@item\nThe University of Texas College of Engineering, for providing a\nChallenge for Excellence Research Supplement, and for providing an\nAcademic Development Funds grant.\n\n@item\nThe State of Texas, for providing funding through the Texas\nAdvanced Technology Program under Grant No.@: 003658-078.\n\n@item\nNoel Bell, Senior Engineer, Texaco Chemical Company, Austin Texas.\n\n@item\nJohn A. Turner, Group Leader, Continuum Dynamics @nospell{(CCS-2)},\n@nospell{Los Alamos} National Laboratory, for registering the\n@url{https://octave.org} domain name.\n\n@item\n@nospell{James B. Rawlings}, Professor, University of Wisconsin-Madison,\nDepartment of Chemical and Biological Engineering.\n\n@item\n@nospell{Richard Stallman}, for writing GNU.\n@end itemize\n\nThis project would not have been possible without the GNU software used\nin and to produce Octave.\n\n@node Citing Octave in Publications\n@unnumberedsec Citing Octave in Publications\n@cindex Citing Octave\n@cindex Citations\n\nIn view of the many contributions made by numerous developers over many years\nit is common courtesy to cite Octave in publications when it has been used\nduring the course of research or the preparation of figures.  The\n@code{citation} function can automatically generate a recommended citation\ntext for Octave or any of its packages.  See the help text below on how to\nuse @code{citation}.\n\n@DOCSTRING(citation)\n\n@node How You Can Contribute to Octave\n@unnumberedsec How You Can Contribute to Octave\n@cindex contributing to Octave\n@cindex funding Octave development\n\nThere are a number of ways that you can contribute to help make Octave a\nbetter system.  Perhaps the most important way to contribute is to write\nhigh-quality code for solving new problems, and to make your code freely\navailable for others to use.  See\n@url{https://www.octave.org/get-involved.html} for detailed information.\n\nIf you find Octave useful, consider providing additional funding to\ncontinue its development.  Even a modest amount of additional funding\ncould make a significant difference in the amount of time that is\navailable for development and support.\n\nDonations supporting Octave development may be made on the web at\n@url{https://www.octave.org/donate}.\n\nIf you cannot provide funding or contribute code, you can still help\nmake Octave better and more reliable by reporting any bugs you find and\nby offering suggestions for ways to improve Octave.  @xref{Trouble}, for\ntips on how to write useful bug reports.\n\n@node Distribution\n@unnumberedsec Distribution\n@cindex distribution of Octave\n\nOctave is @dfn{free} software.  This means that everyone is free to\nuse it and free to redistribute it on certain conditions.  Octave\nis not, however, in the public domain.  It is copyrighted and there are\nrestrictions on its distribution, but the restrictions are designed to\nensure that others will have the same freedom to use and redistribute\nOctave that you have.  The precise conditions can be found in the\nGNU General Public License that comes with Octave and that also appears\nin @ref{Copying}.\n\nTo download a copy of Octave, please visit\n@url{https://www.octave.org/download.html}.\n\n@end ifclear\n"
  },
  {
    "path": "doc/interpreter/quad.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Numerical Integration\n@chapter Numerical Integration\n\nOctave comes with several built-in functions for computing the integral\nof a function numerically (termed quadrature).  These functions all solve\n1-dimensional integration problems.\n\n@menu\n* Functions of One Variable::\n* Orthogonal Collocation::\n* Functions of Multiple Variables::\n@end menu\n\n@node Functions of One Variable\n@section Functions of One Variable\n\nOctave supports five different adaptive quadrature algorithms for computing\nthe integral\n@tex\n$$\n \\int_a^b f(x) d x\n$$\n@end tex\nof a function @math{f} over the interval from @math{a} to @math{b}.  These are\n\n@table @code\n@item quad\nNumerical integration based on Gaussian quadrature.\n\n@item quadv\nNumerical integration using an adaptive vectorized Simpson's rule.\n\n@item quadl\nNumerical integration using an adaptive @nospell{Lobatto} rule.\n\n@item quadgk\nNumerical integration using an adaptive @nospell{Gauss-Konrod} rule.\n\n@item quadcc\nNumerical integration using adaptive @nospell{Clenshaw-Curtis} rules.\n\nIn addition, the following functions are also provided:\n\n@item integral\nA compatibility wrapper function that will choose between @code{quadv} and\n@code{quadgk} depending on the integrand and options chosen.\n\n@item trapz, cumtrapz\nNumerical integration of data using the trapezoidal method.\n@end table\n\n@noindent\nThe best quadrature algorithm to use depends on the integrand.  If you have\nempirical data, rather than a function, the choice is @code{trapz} or\n@code{cumtrapz}.  If you are uncertain about the characteristics of the\nintegrand, @code{quadcc} will be the most robust as it can handle\ndiscontinuities, singularities, oscillatory functions, and infinite intervals.\nWhen the integrand is smooth @code{quadgk} may be the fastest of the\nalgorithms.\n\n@multitable @columnfractions 0.05 0.15 .80\n@headitem @tab Function @tab Characteristics\n@item @tab quad   @tab Low accuracy with nonsmooth integrands\n@item @tab quadv  @tab Medium accuracy with smooth integrands\n@item @tab quadl  @tab Medium accuracy with smooth integrands.  Slower than quadgk.\n@item @tab quadgk @tab Medium accuracy (1e-6 -- 1e-9) with smooth integrands.\n@item @tab        @tab Handles oscillatory functions and infinite bounds\n@item @tab quadcc @tab Low to High accuracy with nonsmooth/smooth integrands\n@item @tab        @tab Handles oscillatory functions, singularities, and infinite bounds\n@end multitable\n\n\nHere is an example of using @code{quad} to integrate the function\n@tex\n$$\n f(x) = x \\sin (1/x) \\sqrt {|1 - x|}\n$$\nfrom $x = 0$ to $x = 3$.\n@end tex\n@ifnottex\n\n@example\n  @var{f}(@var{x}) = @var{x} * sin (1/@var{x}) * sqrt (abs (1 - @var{x}))\n@end example\n\n@noindent\nfrom @var{x} = 0 to @var{x} = 3.\n@end ifnottex\n\nThis is a fairly difficult integration (plot the function over the range\nof integration to see why).\n\nThe first step is to define the function:\n\n@example\n@group\nfunction y = f (x)\n  y = x .* sin (1./x) .* sqrt (abs (1 - x));\nendfunction\n@end group\n@end example\n\nNote the use of the `dot' forms of the operators.  This is not necessary for\nthe @code{quad} integrator, but is required by the other integrators.  In any\ncase, it makes it much easier to generate a set of points for plotting because\nit is possible to call the function with a vector argument to produce a vector\nresult.\n\nThe second step is to call quad with the limits of integration:\n\n@example\n@group\n[q, ier, nfun, err] = quad (\"f\", 0, 3)\n     @xresult{} 1.9819\n     @xresult{} 1\n     @xresult{} 5061\n     @xresult{} 1.1522e-07\n@end group\n@end example\n\nAlthough @code{quad} returns a nonzero value for @var{ier}, the result\nis reasonably accurate (to see why, examine what happens to the result\nif you move the lower bound to 0.1, then 0.01, then 0.001, etc.).\n\nThe function @qcode{\"f\"} can be the string name of a function or a\nfunction handle.  These options make it quite easy to do integration\nwithout having to fully define a function in an m-file.  For example:\n\n@example\n@group\n# Verify gamma function = (n-1)! for n = 4\nf = @@(x) x.^3 .* exp (-x);\nquadcc (f, 0, Inf)\n     @xresult{} 6.0000\n@end group\n@end example\n\n@DOCSTRING(quad)\n\n@DOCSTRING(quad_options)\n\n@DOCSTRING(quadv)\n\n@DOCSTRING(quadl)\n\n@DOCSTRING(quadgk)\n\n@DOCSTRING(quadcc)\n\n@DOCSTRING(integral)\n\nSometimes one does not have the function, but only the raw (x, y) points from\nwhich to perform an integration.  This can occur when collecting data in an\nexperiment.  The @code{trapz} function can integrate these values as shown in\nthe following example where \"data\" has been collected on the cosine function\nover the range [0, pi/2).\n\n@example\n@group\nx = 0:0.1:pi/2;  # Uniformly spaced points\ny = cos (x);\ntrapz (x, y)\n     @xresult{} 0.99666\n@end group\n@end example\n\nThe answer is reasonably close to the exact value of 1.  Ordinary quadrature\nis sensitive to the characteristics of the integrand.  Empirical integration\ndepends not just on the integrand, but also on the particular points chosen to\nrepresent the function.  Repeating the example above with the sine function\nover the range [0, pi/2) produces far inferior results.\n\n@example\n@group\nx = 0:0.1:pi/2;  # Uniformly spaced points\ny = sin (x);\ntrapz (x, y)\n     @xresult{} 0.92849\n@end group\n@end example\n\nHowever, a slightly different choice of data points can change the result\nsignificantly.  The same integration, with the same number of points, but\nspaced differently produces a more accurate answer.\n\n@example\n@group\nx = linspace (0, pi/2, 16);  # Uniformly spaced, but including endpoint\ny = sin (x);\ntrapz (x, y)\n     @xresult{} 0.99909\n@end group\n@end example\n\nIn general there may be no way of knowing the best distribution of points ahead\nof time.  Or the points may come from an experiment where there is no freedom\nto select the best distribution.  In any case, one must remain aware of this\nissue when using @code{trapz}.\n\n@DOCSTRING(trapz)\n\n@DOCSTRING(cumtrapz)\n\n@node Orthogonal Collocation\n@section Orthogonal Collocation\n\n@DOCSTRING(colloc)\n\nHere is an example of using @code{colloc} to generate weight matrices\nfor solving the second order differential equation\n@tex\n$u^\\prime - \\alpha u^{\\prime\\prime} = 0$ with the boundary conditions\n$u(0) = 0$ and $u(1) = 1$.\n@end tex\n@ifnottex\n@var{u}' - @var{alpha} * @var{u}'' = 0 with the boundary conditions\n@var{u}(0) = 0 and @var{u}(1) = 1.\n@end ifnottex\n\nFirst, we can generate the weight matrices for @var{n} points (including\nthe endpoints of the interval), and incorporate the boundary conditions\nin the right hand side (for a specific value of\n@tex\n$\\alpha$).\n@end tex\n@ifnottex\n@var{alpha}).\n@end ifnottex\n\n@example\n@group\nn = 7;\nalpha = 0.1;\n[r, a, b] = colloc (n-2, \"left\", \"right\");\nat = a(2:n-1,2:n-1);\nbt = b(2:n-1,2:n-1);\nrhs = alpha * b(2:n-1,n) - a(2:n-1,n);\n@end group\n@end example\n\nThen the solution at the roots @var{r} is\n\n@example\n@group\nu = [ 0; (at - alpha * bt) \\ rhs; 1]\n     @xresult{} [ 0.00; 0.004; 0.01 0.00; 0.12; 0.62; 1.00 ]\n@end group\n@end example\n\n@node Functions of Multiple Variables\n@section Functions of Multiple Variables\n\nOctave includes several functions for computing the integral of functions of\nmultiple variables.  This procedure can generally be performed by creating a\nfunction that integrates @math{f} with respect to @math{x}, and then integrates\nthat function with respect to @math{y}.  This procedure can be performed\nmanually using the following example which integrates the function:\n\n@tex\n$$\n  f(x, y) = \\sin(\\pi x y)\\sqrt{x y}\n$$\n@end tex\n@ifnottex\n\n@example\nf(x, y) = sin(pi*x*y) * sqrt(x*y)\n@end example\n\n@end ifnottex\nfor @math{x} and @math{y} between 0 and 1.\n\nUsing @code{quadgk} in the example below, a double integration can be\nperformed.  (Note that any of the 1-D quadrature functions can be used in this\nfashion except for @code{quad} since it is written in Fortran and cannot be\ncalled recursively.)\n\n@example\n@group\nfunction q = g(y)\n  q = ones (size (y));\n  for i = 1:length (y)\n    f = @@(x) sin (pi*x.*y(i)) .* sqrt (x.*y(i));\n    q(i) = quadgk (f, 0, 1);\n  endfor\nendfunction\n\nI = quadgk (\"g\", 0, 1)\n      @xresult{} 0.30022\n@end group\n@end example\n\nThe algorithm above is implemented in the function @code{dblquad} for integrals\nover two variables.  The 3-D equivalent of this process is implemented in\n@code{triplequad} for integrals over three variables.  As an example, the\nresult above can be replicated with a call to @code{dblquad} as shown below.\n\n@example\n@group\nI = dblquad (@@(x, y) sin (pi*x.*y) .* sqrt (x.*y), 0, 1, 0, 1)\n      @xresult{} 0.30022\n@end group\n@end example\n\n@DOCSTRING(dblquad)\n\n@DOCSTRING(triplequad)\n\nThe recursive algorithm for quadrature presented above is referred to as\n@qcode{\"iterated\"}.  A separate 2-D integration method is implemented in the\nfunction @code{quad2d}.  This function performs a @qcode{\"tiled\"} integration\nby subdividing the integration domain into rectangular regions and performing\nseparate integrations over those domains.  The domains are further subdivided\nin areas requiring refinement to reach the desired numerical accuracy.  For\ncertain functions this method can be faster than the 2-D iteration used in the\nother functions above.\n\n@DOCSTRING(quad2d)\n\nFinally, the functions @code{integral2} and @code{integral3} are provided\nas general 2-D and 3-D integration functions.  They will auto-select between\niterated and tiled integration methods and, unlike @code{dblquad} and\n@code{triplequad}, will work with non-rectangular integration domains.\n\n@DOCSTRING(integral2)\n\n@DOCSTRING(integral3)\n\nThe above integrations can be fairly slow, and that problem increases\nexponentially with the dimensionality of the integral.  Another possible\nsolution for 2-D integration is to use Orthogonal Collocation as described in\nthe previous section (@pxref{Orthogonal Collocation}).  The integral of a\nfunction @math{f(x,y)} for @math{x} and @math{y} between 0 and 1 can be\napproximated using @math{n} points by\n@tex\n$$\n \\int_0^1 \\int_0^1 f(x,y) d x d y \\approx \\sum_{i=1}^n \\sum_{j=1}^n q_i q_j f(r_i, r_j),\n$$\n@end tex\n@ifnottex\nthe sum over @code{i=1:n} and @code{j=1:n} of @code{q(i)*q(j)*f(r(i),r(j))},\n@end ifnottex\nwhere @math{q} and @math{r} is as returned by @code{colloc (n)}.  The\ngeneralization to more than two variables is straight forward.  The\nfollowing code computes the studied integral using @math{n=8} points.\n\n@example\n@group\nf = @@(x,y) sin (pi*x*y') .* sqrt (x*y');\nn = 8;\n[t, ~, ~, q] = colloc (n);\nI = q'*f(t,t)*q;\n      @xresult{} 0.30022\n@end group\n@end example\n\n@noindent\nIt should be noted that the number of points determines the quality\nof the approximation.  If the integration needs to be performed between\n@math{a} and @math{b}, instead of 0 and 1, then a change of variables is needed.\n"
  },
  {
    "path": "doc/interpreter/set.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Sets\n@chapter Sets\n\nOctave has a number of functions for managing sets of data.  A set is defined\nas a collection of unique elements and is typically represented by a vector of\nnumbers sorted in ascending order.  Any vector or matrix can be converted to a\nset by removing duplicates through the use of the @code{unique} function.\nHowever, it isn't necessary to explicitly create a set as all of the functions\nwhich operate on sets will convert their input to a set before proceeding.\n\n@DOCSTRING(unique)\n\n@DOCSTRING(uniquetol)\n\n@menu\n* Set Operations::\n@end menu\n\n@node Set Operations\n@section Set Operations\n\nOctave supports several basic set operations.  Octave can compute the union,\nintersection, and difference of two sets.  Octave also supports the\n@emph{Exclusive Or} set operation.\n\nThe functions for set operations all work in the same way by accepting two\ninput sets and returning a third set.  As an example, assume that @code{a} and\n@code{b} contains two sets, then\n\n@example\nunion (a, b)\n@end example\n\n@noindent\ncomputes the union of the two sets.\n\nFinally, determining whether elements belong to a set can be done with the\n@code{ismember} function.  Because sets are ordered this operation is very\nefficient and is of order O(log2(n)) which is preferable to the @code{find}\nfunction which is of order O(n).\n\n@DOCSTRING(intersect)\n\n@DOCSTRING(union)\n\n@DOCSTRING(setdiff)\n\n@DOCSTRING(setxor)\n\n@DOCSTRING(ismember)\n\n@DOCSTRING(ismembertol)\n\n@DOCSTRING(powerset)\n"
  },
  {
    "path": "doc/interpreter/signal.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Signal Processing\n@chapter Signal Processing\n\nThis chapter describes the signal processing and fast Fourier\ntransform functions available in Octave.  Fast Fourier transforms are\ncomputed with the @sc{fftw} or @sc{fftpack} libraries depending on how\nOctave is built.\n\n@DOCSTRING(fft)\n\n@DOCSTRING(ifft)\n\n@DOCSTRING(fft2)\n\n@DOCSTRING(ifft2)\n\n@DOCSTRING(fftn)\n\n@DOCSTRING(ifftn)\n\nOctave uses the @sc{fftw} libraries to perform FFT computations.  When Octave\nstarts up and initializes the @sc{fftw} libraries, they read a system wide\nfile (on a Unix system, it is typically @file{/etc/fftw/wisdom}) that\ncontains information useful to speed up FFT computations.  This\ninformation is called the @emph{wisdom}.  The system-wide file allows\nwisdom to be shared between all applications using the @sc{fftw} libraries.\n\nUse the @code{fftw} function to generate and save wisdom.  Using the\nutilities provided together with the @sc{fftw} libraries\n(@command{fftw-wisdom} on Unix systems), you can even add wisdom\ngenerated by Octave to the system-wide wisdom file.\n\n@DOCSTRING(fftw)\n\n@DOCSTRING(fftconv)\n\n@DOCSTRING(fftfilt)\n\n@DOCSTRING(filter)\n\n@DOCSTRING(filter2)\n\n@DOCSTRING(freqz)\n\n@DOCSTRING(freqz_plot)\n\n@DOCSTRING(sinc)\n\n@DOCSTRING(unwrap)\n\n@c FIXME: someone needs to organize these ...\n\n@DOCSTRING(arch_fit)\n\n@DOCSTRING(arch_rnd)\n\n@DOCSTRING(arch_test)\n\n@DOCSTRING(arma_rnd)\n\n@DOCSTRING(autoreg_matrix)\n\n@DOCSTRING(bartlett)\n\n@DOCSTRING(blackman)\n\n@DOCSTRING(detrend)\n\n@DOCSTRING(diffpara)\n\n@DOCSTRING(durbinlevinson)\n\n@DOCSTRING(fftshift)\n\n@DOCSTRING(ifftshift)\n\n@DOCSTRING(fractdiff)\n\n@DOCSTRING(hamming)\n\n@DOCSTRING(hanning)\n\n@DOCSTRING(hurst)\n\n@DOCSTRING(pchip)\n\n@DOCSTRING(periodogram)\n\n@DOCSTRING(sinetone)\n\n@DOCSTRING(sinewave)\n\n@DOCSTRING(spectral_adf)\n\n@DOCSTRING(spectral_xdf)\n\n@DOCSTRING(spencer)\n\n@DOCSTRING(stft)\n\n@DOCSTRING(synthesis)\n\n@DOCSTRING(yulewalker)\n"
  },
  {
    "path": "doc/interpreter/sparse.txi",
    "content": "@c Copyright (C) 2004-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@ifhtml\n@set htmltex\n@end ifhtml\n@iftex\n@set htmltex\n@end iftex\n\n@node Sparse Matrices\n@chapter Sparse Matrices\n\n@menu\n* Basics::                      Creation and Manipulation of Sparse Matrices\n* Sparse Linear Algebra::       Linear Algebra on Sparse Matrices\n* Iterative Techniques::        Iterative Techniques\n* Real Life Example::           Using Sparse Matrices\n@end menu\n\n@node Basics\n@section Creation and Manipulation of Sparse Matrices\n\nThe size of mathematical problems that can be treated at any particular\ntime is generally limited by the available computing resources.  Both,\nthe speed of the computer and its available memory place limitation on\nthe problem size.\n\nThere are many classes of mathematical problems which give rise to\nmatrices, where a large number of the elements are zero.  In this case\nit makes sense to have a special matrix type to handle this class of\nproblems where only the nonzero elements of the matrix are\nstored.  Not only does this reduce the amount of memory to store the\nmatrix, but it also means that operations on this type of matrix can\ntake advantage of the a priori knowledge of the positions of the\nnonzero elements to accelerate their calculations.\n\nA matrix type that stores only the nonzero elements is generally called\nsparse.  It is the purpose of this document to discuss the basics of the\nstorage and creation of sparse matrices and the fundamental operations\non them.\n\n@menu\n* Storage of Sparse Matrices::\n* Creating Sparse Matrices::\n* Information::\n* Operators and Functions::\n@end menu\n\n@node Storage of Sparse Matrices\n@subsection Storage of Sparse Matrices\n\nIt is not strictly speaking necessary for the user to understand how\nsparse matrices are stored.  However, such an understanding will help\nto get an understanding of the size of sparse matrices.  Understanding\nthe storage technique is also necessary for those users wishing to\ncreate their own oct-files.\n\nThere are many different means of storing sparse matrix data.  What all\nof the methods have in common is that they attempt to reduce the complexity\nand storage given a priori knowledge of the particular class of problems\nthat will be solved.  A good summary of the available techniques for storing\nsparse matrix is given by @nospell{Saad} @footnote{Y. Saad \"SPARSKIT: A basic\ntoolkit for sparse matrix computation\", 1994,\n@url{https://www-users.cs.umn.edu/~saad/software/SPARSKIT/paper.ps}}.\nWith full matrices, knowledge of the point of an element of the matrix\nwithin the matrix is implied by its position in the computers memory.\nHowever, this is not the case for sparse matrices, and so the positions\nof the nonzero elements of the matrix must equally be stored.\n\nAn obvious way to do this is by storing the elements of the matrix as\ntriplets, with two elements being their position in the array\n(rows and column) and the third being the data itself.  This is conceptually\neasy to grasp, but requires more storage than is strictly needed.\n\nThe storage technique used within Octave is the compressed column\nformat.  It is similar to the Yale format.\n@footnote{@url{https://en.wikipedia.org/wiki/Sparse_matrix#Yale_format}}\nIn this format the position of each element in a row and the data are\nstored as previously.  However, if we assume that all elements in the\nsame column are stored adjacent in the computers memory, then we only\nneed to store information on the number of nonzero elements in each\ncolumn, rather than their positions.  Thus assuming that the matrix has\nmore nonzero elements than there are columns in the matrix, we win in\nterms of the amount of memory used.\n\nIn fact, the column index contains one more element than the number of\ncolumns, with the first element always being zero.  The advantage of\nthis is a simplification in the code, in that there is no special case\nfor the first or last columns.  A short example, demonstrating this in\nC is.\n\n@example\n@group\n  for (j = 0; j < nc; j++)\n    for (i = cidx(j); i < cidx(j+1); i++)\n       printf (\"nonzero element (%i,%i) is %d\\n\",\n           ridx(i), j, data(i));\n@end group\n@end example\n\nA clear understanding might be had by considering an example of how the\nabove applies to an example matrix.  Consider the matrix\n\n@example\n@group\n    1   2   0  0\n    0   0   0  3\n    0   0   0  4\n@end group\n@end example\n\nThe nonzero elements of this matrix are\n\n@example\n@group\n   (1, 1)  @xresult{} 1\n   (1, 2)  @xresult{} 2\n   (2, 4)  @xresult{} 3\n   (3, 4)  @xresult{} 4\n@end group\n@end example\n\nThis will be stored as three vectors @var{cidx}, @var{ridx} and @var{data},\nrepresenting the column indexing, row indexing and data respectively.  The\ncontents of these three vectors for the above matrix will be\n\n@example\n@group\n  @var{cidx} = [0, 1, 2, 2, 4]\n  @var{ridx} = [0, 0, 1, 2]\n  @var{data} = [1, 2, 3, 4]\n@end group\n@end example\n\nNote that this is the representation of these elements with the first row\nand column assumed to start at zero, while in Octave itself the row and\ncolumn indexing starts at one.  Thus, the number of elements in the\n@var{i}-th column is given by\n@code{@var{cidx} (@var{i} + 1) - @var{cidx} (@var{i})}.\n\nAlthough Octave uses a compressed column format, it should be noted\nthat compressed row formats are equally possible.  However, in the\ncontext of mixed operations between mixed sparse and dense matrices,\nit makes sense that the elements of the sparse matrices are in the\nsame order as the dense matrices.  Octave stores dense matrices in\ncolumn major ordering, and so sparse matrices are equally stored in\nthis manner.\n\nA further constraint on the sparse matrix storage used by Octave is that\nall elements in the rows are stored in increasing order of their row\nindex, which makes certain operations faster.  However, it imposes\nthe need to sort the elements on the creation of sparse matrices.  Having\ndisordered elements is potentially an advantage in that it makes operations\nsuch as concatenating two sparse matrices together easier and faster, however\nit adds complexity and speed problems elsewhere.\n\n@node Creating Sparse Matrices\n@subsection Creating Sparse Matrices\n\nThere are several means to create sparse matrix.\n\n@table @asis\n@item Returned from a function\nThere are many functions that directly return sparse matrices.  These include\n@dfn{speye}, @dfn{sprand}, @dfn{diag}, etc.\n\n@item Constructed from matrices or vectors\nThe function @dfn{sparse} allows a sparse matrix to be constructed from\nthree vectors representing the row, column and data.  Alternatively, the\nfunction @dfn{spconvert} uses a three column matrix format to allow easy\nimportation of data from elsewhere.\n\n@item Created and then filled\nThe function @dfn{sparse} or @dfn{spalloc} can be used to create an empty\nmatrix that is then filled by the user\n\n@item From a user binary program\nThe user can directly create the sparse matrix within an oct-file.\n@end table\n\nThere are several basic functions to return specific sparse\nmatrices.  For example the sparse identity matrix, is a matrix that is\noften needed.  It therefore has its own function to create it as\n@code{speye (@var{n})} or @code{speye (@var{r}, @var{c})}, which\ncreates an @var{n}-by-@var{n} or @var{r}-by-@var{c} sparse identity\nmatrix.\n\nAnother typical sparse matrix that is often needed is a random distribution\nof random elements.  The functions @dfn{sprand} and @dfn{sprandn} perform\nthis for uniform and normal random distributions of elements.  They have\nexactly the same calling convention, where @code{sprand (@var{r}, @var{c},\n@var{d})}, creates an @var{r}-by-@var{c} sparse matrix with a density of\nfilled elements of @var{d}.\n\nOther functions of interest that directly create sparse matrices, are\n@dfn{diag} or its generalization @dfn{spdiags}, that can take the\ndefinition of the diagonals of the matrix and create the sparse matrix\nthat corresponds to this.  For example,\n\n@example\ns = diag (sparse (randn (1,n)), -1);\n@end example\n\n@noindent\ncreates a sparse (@var{n}+1)-by-(@var{n}+1) sparse matrix with a single\ndiagonal defined.\n\n@DOCSTRING(spdiags)\n\n@DOCSTRING(speye)\n\n@DOCSTRING(spones)\n\n@DOCSTRING(sprand)\n\n@DOCSTRING(sprandn)\n\n@DOCSTRING(sprandsym)\n\nThe recommended way for the user to create a sparse matrix, is to create\ntwo vectors containing the row and column index of the data and a third\nvector of the same size containing the data to be stored.  For example,\n\n@example\n@group\n  ri = ci = d = [];\n  for j = 1:c\n    ri = [ri; randperm(r,n)'];\n    ci = [ci; j*ones(n,1)];\n    d = [d; rand(n,1)];\n  endfor\n  s = sparse (ri, ci, d, r, c);\n@end group\n@end example\n\n@noindent\ncreates an @var{r}-by-@var{c} sparse matrix with a random distribution\nof @var{n} (<@var{r}) elements per column.  The elements of the vectors\ndo not need to be sorted in any particular order as Octave will sort\nthem prior to storing the data.  However, pre-sorting the data will\nmake the creation of the sparse matrix faster.\n\nThe function @dfn{spconvert} takes a three or four column real matrix.\nThe first two columns represent the row and column index respectively and\nthe third and four columns, the real and imaginary parts of the sparse\nmatrix.  The matrix can contain zero elements and the elements can be\nsorted in any order.  Adding zero elements is a convenient way to define\nthe size of the sparse matrix.  For example:\n\n@example\n@group\ns = spconvert ([1 2 3 4; 1 3 4 4; 1 2 3 0]')\n@xresult{} Compressed Column Sparse (rows=4, cols=4, nnz=3)\n      (1 , 1) -> 1\n      (2 , 3) -> 2\n      (3 , 4) -> 3\n@end group\n@end example\n\nAn example of creating and filling a matrix might be\n\n@example\n@group\nk = 5;\nnz = r * k;\ns = spalloc (r, c, nz)\nfor j = 1:c\n  idx = randperm (r);\n  s (:, j) = [zeros(r - k, 1); ...\n        rand(k, 1)] (idx);\nendfor\n@end group\n@end example\n\nIt should be noted, that due to the way that the Octave\nassignment functions are written that the assignment will reallocate\nthe memory used by the sparse matrix at each iteration of the above loop.\nTherefore the @dfn{spalloc} function ignores the @var{nz} argument and\ndoes not pre-assign the memory for the matrix.  Therefore, it is vitally\nimportant that code using to above structure should be vectorized\nas much as possible to minimize the number of assignments and reduce the\nnumber of memory allocations.\n\n@DOCSTRING(full)\n\n@DOCSTRING(spalloc)\n\n@DOCSTRING(sparse)\n\n@DOCSTRING(spconvert)\n\nThe above problem of memory reallocation can be avoided in\noct-files.  However, the construction of a sparse matrix from an oct-file\nis more complex than can be discussed here.  @xref{External Code Interface},\nfor a full description of the techniques involved.\n\n@node Information\n@subsection Finding Information about Sparse Matrices\n\nThere are a number of functions that allow information concerning\nsparse matrices to be obtained.  The most basic of these is\n@dfn{issparse} that identifies whether a particular Octave object is\nin fact a sparse matrix.\n\nAnother very basic function is @dfn{nnz} that returns the number of\nnonzero entries there are in a sparse matrix, while the function\n@dfn{nzmax} returns the amount of storage allocated to the sparse\nmatrix.  Note that Octave tends to crop unused memory at the first\nopportunity for sparse objects.  There are some cases of user created\nsparse objects where the value returned by @dfn{nzmax} will not be\nthe same as @dfn{nnz}, but in general they will give the same\nresult.  The function @dfn{spstats} returns some basic statistics on\nthe columns of a sparse matrix including the number of elements, the\nmean and the variance of each column.\n\n@DOCSTRING(issparse)\n\n@DOCSTRING(nnz)\n\n@DOCSTRING(nonzeros)\n\n@DOCSTRING(nzmax)\n\n@DOCSTRING(spstats)\n\nWhen solving linear equations involving sparse matrices Octave\ndetermines the means to solve the equation based on the type of the\nmatrix (@pxref{Sparse Linear Algebra}).  Octave probes the\nmatrix type when the div (/) or ldiv (\\) operator is first used with\nthe matrix and then caches the type.  However the @dfn{matrix_type}\nfunction can be used to determine the type of the sparse matrix prior\nto use of the div or ldiv operators.  For example,\n\n@example\n@group\na = tril (sprandn (1024, 1024, 0.02), -1) ...\n    + speye (1024);\nmatrix_type (a);\nans = Lower\n@end group\n@end example\n\n@noindent\nshows that Octave correctly determines the matrix type for lower\ntriangular matrices.  @dfn{matrix_type} can also be used to force\nthe type of a matrix to be a particular type.  For example:\n\n@example\n@group\na = matrix_type (tril (sprandn (1024, ...\n   1024, 0.02), -1) + speye (1024), \"Lower\");\n@end group\n@end example\n\nThis allows the cost of determining the matrix type to be\navoided.  However, incorrectly defining the matrix type will result in\nincorrect results from solutions of linear equations, and so it is\nentirely the responsibility of the user to correctly identify the\nmatrix type\n\nThere are several graphical means of finding out information about\nsparse matrices.  The first is the @dfn{spy} command, which displays\nthe structure of the nonzero elements of the\nmatrix.  @xref{fig:spmatrix}, for an example of the use of\n@dfn{spy}.  More advanced graphical information can be obtained with the\n@dfn{treeplot}, @dfn{etreeplot} and @dfn{gplot} commands.\n\n@float Figure,fig:spmatrix\n@center @image{spmatrix,4in}\n@caption{Structure of simple sparse matrix.}\n@end float\n\nOne use of sparse matrices is in graph theory, where the\ninterconnections between nodes are represented as an adjacency\nmatrix.  That is, if the i-th node in a graph is connected to the j-th\nnode.  Then the ij-th node (and in the case of undirected graphs the\n@nospell{ji-th} node) of the sparse adjacency matrix is nonzero.  If each node\nis then associated with a set of coordinates, then the @dfn{gplot}\ncommand can be used to graphically display the interconnections\nbetween nodes.\n\nAs a trivial example of the use of @dfn{gplot} consider the example,\n\n@example\n@group\nA = sparse ([2,6,1,3,2,4,3,5,4,6,1,5],\n    [1,1,2,2,3,3,4,4,5,5,6,6],1,6,6);\nxy = [0,4,8,6,4,2;5,0,5,7,5,7]';\ngplot (A,xy)\n@end group\n@end example\n\n@noindent\nwhich creates an adjacency matrix @code{A} where node 1 is connected\nto nodes 2 and 6, node 2 with nodes 1 and 3, etc.  The coordinates of\nthe nodes are given in the n-by-2 matrix @code{xy}.\n@ifset htmltex\n@xref{fig:gplot}.\n\n@float Figure,fig:gplot\n@center @image{gplot,4in}\n@caption{Simple use of the @dfn{gplot} command.}\n@end float\n@end ifset\n\nThe dependencies between the nodes of a Cholesky@tie{}factorization can be\ncalculated in linear time without explicitly needing to calculate the\nCholesky@tie{}factorization by the @code{etree} command.  This command\nreturns the elimination tree of the matrix and can be displayed\ngraphically by the command @code{treeplot (etree (A))} if @code{A} is\nsymmetric or @code{treeplot (etree (A+A'))} otherwise.\n\n@DOCSTRING(spy)\n\n@DOCSTRING(etree)\n\n@DOCSTRING(etreeplot)\n\n@DOCSTRING(gplot)\n\n@DOCSTRING(treeplot)\n\n@DOCSTRING(treelayout)\n\n@node Operators and Functions\n@subsection Basic Operators and Functions on Sparse Matrices\n\n@menu\n* Sparse Functions::\n* Return Types of Operators and Functions::\n* Mathematical Considerations::\n@end menu\n\n@node Sparse Functions\n@subsubsection Sparse Functions\n\nMany Octave functions have been overloaded to work with either sparse or full\nmatrices.  There is no difference in calling convention when using an\noverloaded function with a sparse matrix, however, there is also no access to\npotentially sparse-specific features.  At any time the sparse matrix specific\nversion of a function can be used by explicitly calling its function name.\n\nThe table below lists all of the sparse functions of Octave.  Note that the\nnames of the specific sparse forms of the functions are typically the same as\nthe general versions with a @dfn{sp} prefix.  In the table below, and in the\nrest of this article, the specific sparse versions of functions are used.\n\n@c Table includes in comments the missing sparse functions\n\n@table @asis\n@item Generate sparse matrices:\n  @dfn{spalloc}, @dfn{spdiags}, @dfn{speye}, @dfn{sprand},\n  @dfn{sprandn}, @dfn{sprandsym}\n\n@item Sparse matrix conversion:\n  @dfn{full}, @dfn{sparse}, @dfn{spconvert}\n\n@item Manipulate sparse matrices\n  @dfn{issparse}, @dfn{nnz}, @dfn{nonzeros}, @dfn{nzmax},\n  @dfn{spfun}, @dfn{spones}, @dfn{spy}\n\n@item Graph Theory:\n  @dfn{etree}, @dfn{etreeplot}, @dfn{gplot},\n  @dfn{treeplot}\n@c @dfn{treelayout}\n\n@item Sparse matrix reordering:\n  @dfn{amd}, @dfn{ccolamd}, @dfn{colamd}, @dfn{colperm}, @dfn{csymamd},\n  @dfn{dmperm}, @dfn{symamd}, @dfn{randperm}, @dfn{symrcm}\n\n@item Linear algebra:\n  @dfn{condest}, @dfn{eigs}, @dfn{matrix_type},\n  @dfn{normest}, @dfn{normest1}, @dfn{sprank}, @dfn{spaugment}, @dfn{svds}\n\n@item Iterative techniques:\n  @dfn{ichol}, @dfn{ilu}, @dfn{pcg}, @dfn{pcr}\n@c @dfn{bicg}, @dfn{bicgstab}, @dfn{cholinc}, @dfn{cgs}, @dfn{gmres},\n@c @dfn{lsqr}, @dfn{minres}, @dfn{qmr}, @dfn{symmlq}\n\n@item Miscellaneous:\n  @dfn{spparms}, @dfn{symbfact}, @dfn{spstats}\n@end table\n\nIn addition all of the standard Octave mapper functions (i.e., basic\nmath functions that take a single argument) such as @dfn{abs}, etc.@:\ncan accept sparse matrices.  The reader is referred to the documentation\nsupplied with these functions within Octave itself for further\ndetails.\n\n@node Return Types of Operators and Functions\n@subsubsection Return Types of Operators and Functions\n\nThe two basic reasons to use sparse matrices are to reduce the memory\nusage and to not have to do calculations on zero elements.  The two are\nclosely related in that the computation time on a sparse matrix operator\nor function is roughly linear with the number of nonzero elements.\n\nTherefore, there is a certain density of nonzero elements of a matrix\nwhere it no longer makes sense to store it as a sparse matrix, but rather\nas a full matrix.  For this reason operators and functions that have a\nhigh probability of returning a full matrix will always return one.  For\nexample adding a scalar constant to a sparse matrix will almost always\nmake it a full matrix, and so the example,\n\n@example\n@group\nspeye (3) + 0\n@xresult{}   1  0  0\n  0  1  0\n  0  0  1\n@end group\n@end example\n\n@noindent\nreturns a full matrix as can be seen.\n\nAs all of the mixed operators and functions between full and sparse\nmatrices exist, in general this does not cause any problems.  However,\none area where it does cause a problem is where a sparse matrix is\npromoted to a full matrix, where subsequent operations would resparsify\nthe matrix.  Such cases are rare, but can be artificially created, for\nexample @code{(fliplr (speye (3)) + speye (3)) - speye (3)} gives a full\nmatrix when it should give a sparse one.  In general, where such cases\noccur, they impose only a small memory penalty.\n\nThere is however one known case where this behavior of Octave's\nsparse matrices will cause a problem.  That is in the handling of the\n@dfn{diag} function.  Whether @dfn{diag} returns a sparse or full matrix\ndepending on the type of its input arguments.  So\n\n@example\n a = diag (sparse ([1,2,3]), -1);\n@end example\n\n@noindent\nshould return a sparse matrix.  To ensure this actually happens, the\n@dfn{sparse} function, and other functions based on it like @dfn{speye},\nalways returns a sparse matrix, even if the memory used will be larger\nthan its full representation.\n\n@node Mathematical Considerations\n@subsubsection Mathematical Considerations\n\nThe attempt has been made to make sparse matrices behave in exactly the\nsame manner as there full counterparts.  However, there are certain differences\nand especially differences with other products sparse implementations.\n\nFirst, the @qcode{\"./\"} and @qcode{\".^\"} operators must be used with care.\nConsider what the examples\n\n@example\n@group\n  s = speye (4);\n  a1 = s .^ 2;\n  a2 = s .^ s;\n  a3 = s .^ -2;\n  a4 = s ./ 2;\n  a5 = 2 ./ s;\n  a6 = s ./ s;\n@end group\n@end example\n\n@noindent\nwill give.  The first example of @var{s} raised to the power of 2 causes\nno problems.  However @var{s} raised element-wise to itself involves a\nlarge number of terms @code{0 .^ 0} which is 1.  There @code{@var{s} .^\n@var{s}} is a full matrix.\n\nLikewise @code{@var{s} .^ -2} involves terms like @code{0 .^ -2} which\nis infinity, and so @code{@var{s} .^ -2} is equally a full matrix.\n\nFor the \"./\" operator @code{@var{s} ./ 2} has no problems, but\n@code{2 ./ @var{s}} involves a large number of infinity terms as well\nand is equally a full matrix.  The case of @code{@var{s} ./ @var{s}}\ninvolves terms like @code{0 ./ 0} which is a @code{NaN} and so this\nis equally a full matrix with the zero elements of @var{s} filled with\n@code{NaN} values.\n\nThe above behavior is consistent with full matrices, but is not\nconsistent with sparse implementations in other products.\n\nA particular problem of sparse matrices comes about due to the fact that\nas the zeros are not stored, the sign-bit of these zeros is equally not\nstored.  In certain cases the sign-bit of zero is important.  For example:\n\n@example\n@group\n a = 0 ./ [-1, 1; 1, -1];\n b = 1 ./ a\n @xresult{} -Inf            Inf\n     Inf           -Inf\n c = 1 ./ sparse (a)\n @xresult{}  Inf            Inf\n     Inf            Inf\n@end group\n@end example\n\nTo correct this behavior would mean that zero elements with a negative\nsign-bit would need to be stored in the matrix to ensure that their\nsign-bit was respected.  This is not done at this time, for reasons of\nefficiency, and so the user is warned that calculations where the sign-bit\nof zero is important must not be done using sparse matrices.\n\nIn general any function or operator used on a sparse matrix will\nresult in a sparse matrix with the same or a larger number of nonzero\nelements than the original matrix.  This is particularly true for the\nimportant case of sparse matrix factorizations.  The usual way to\naddress this is to reorder the matrix, such that its factorization is\nsparser than the factorization of the original matrix.  That is the\nfactorization of @code{L * U = P * S * Q} has sparser terms @code{L}\nand @code{U} than the equivalent factorization @code{L * U = S}.\n\nSeveral functions are available to reorder depending on the type of the\nmatrix to be factorized.  If the matrix is symmetric positive-definite,\nthen @dfn{symamd} or @dfn{csymamd} should be used.  Otherwise\n@dfn{amd}, @dfn{colamd} or @dfn{ccolamd} should be used.  For completeness\nthe reordering functions @dfn{colperm} and @dfn{randperm} are\nalso available.\n\n@xref{fig:simplematrix}, for an example of the structure of a simple\npositive definite matrix.\n\n@float Figure,fig:simplematrix\n@center @image{spmatrix,4in}\n@caption{Structure of simple sparse matrix.}\n@end float\n\nThe standard Cholesky@tie{}factorization of this matrix can be\nobtained by the same command that would be used for a full\nmatrix.  This can be visualized with the command\n@code{r = chol (A); spy (r);}.\n@xref{fig:simplechol}.\nThe original matrix had\n@ifinfo\n@ifnothtml\n43\n@end ifnothtml\n@end ifinfo\n@ifset htmltex\n598\n@end ifset\nnonzero terms, while this Cholesky@tie{}factorization has\n@ifinfo\n@ifnothtml\n71,\n@end ifnothtml\n@end ifinfo\n@ifset htmltex\n10200,\n@end ifset\nwith only half of the symmetric matrix being stored.  This\nis a significant level of fill in, and although not an issue\nfor such a small test case, can represents a large overhead\nin working with other sparse matrices.\n\nThe appropriate sparsity preserving permutation of the original\nmatrix is given by @dfn{symamd} and the factorization using this\nreordering can be visualized using the command @code{q = symamd (A);\nr = chol (A(q,q)); spy (r)}.  This gives\n@ifinfo\n@ifnothtml\n29\n@end ifnothtml\n@end ifinfo\n@ifset htmltex\n399\n@end ifset\nnonzero terms which is a significant improvement.\n\nThe Cholesky@tie{}factorization itself can be used to determine the\nappropriate sparsity preserving reordering of the matrix during the\nfactorization, In that case this might be obtained with three return\narguments as @code{[r, p, q] = chol (A); spy (r)}.\n\n@float Figure,fig:simplechol\n@center @image{spchol,4in}\n@caption{Structure of the unpermuted Cholesky@tie{}factorization of the above matrix.}\n@end float\n\n@float Figure,fig:simplecholperm\n@center @image{spcholperm,4in}\n@caption{Structure of the permuted Cholesky@tie{}factorization of the above matrix.}\n@end float\n\nIn the case of an asymmetric matrix, the appropriate sparsity\npreserving permutation is @dfn{colamd} and the factorization using\nthis reordering can be visualized using the command\n@code{q = colamd (A); [l, u, p] = lu (A(:,q)); spy (l+u)}.\n\nFinally, Octave implicitly reorders the matrix when using the div (/)\nand ldiv (\\) operators, and so no the user does not need to explicitly\nreorder the matrix to maximize performance.\n\n@DOCSTRING(amd)\n\n@DOCSTRING(ccolamd)\n\n@DOCSTRING(colamd)\n\n@DOCSTRING(colperm)\n\n@DOCSTRING(csymamd)\n\n@DOCSTRING(dmperm)\n\n@DOCSTRING(symamd)\n\n@DOCSTRING(symrcm)\n\n@node Sparse Linear Algebra\n@section Linear Algebra on Sparse Matrices\n\nOctave includes a polymorphic solver for sparse matrices, where\nthe exact solver used to factorize the matrix, depends on the properties\nof the sparse matrix itself.  Generally, the cost of determining the matrix\ntype is small relative to the cost of factorizing the matrix itself, but in\nany case the matrix type is cached once it is calculated, so that it is not\nre-determined each time it is used in a linear equation.\n\nThe selection tree for how the linear equation is solve is\n\n@enumerate 1\n@item If the matrix is diagonal, solve directly and goto 8\n\n@item If the matrix is a permuted diagonal, solve directly taking into\naccount the permutations.  Goto 8\n\n@item If the matrix is square, banded and if the band density is less\nthan that given by @code{spparms (\"bandden\")} continue, else goto 4.\n\n@enumerate a\n@item If the matrix is tridiagonal and the right-hand side is not sparse\ncontinue, else goto 3b.\n\n@enumerate\n@item If the matrix is Hermitian, with a positive real diagonal, attempt\n      Cholesky@tie{}factorization using @sc{lapack} xPTSV.\n\n@item If the above failed or the matrix is not Hermitian with a positive\n      real diagonal use Gaussian elimination with pivoting using\n      @sc{lapack} xGTSV, and goto 8.\n@end enumerate\n\n@item If the matrix is Hermitian with a positive real diagonal, attempt\n      Cholesky@tie{}factorization using @sc{lapack} xPBTRF.\n\n@item if the above failed or the matrix is not Hermitian with a positive\n      real diagonal use Gaussian elimination with pivoting using\n      @sc{lapack} xGBTRF, and goto 8.\n@end enumerate\n\n@item If the matrix is upper or lower triangular perform a sparse forward\nor backward substitution, and goto 8\n\n@item If the matrix is an upper triangular matrix with column permutations\nor lower triangular matrix with row permutations, perform a sparse forward\nor backward substitution, and goto 8\n\n@item If the matrix is square, Hermitian with a real positive diagonal, attempt\nsparse Cholesky@tie{}factorization using @sc{cholmod}.\n\n@item If the sparse Cholesky@tie{}factorization failed or the matrix is not\nHermitian with a real positive diagonal, and the matrix is square, factorize,\nsolve, and perform one refinement iteration using @sc{umfpack}.\n\n@item If the matrix is not square, or any of the previous solvers flags\na singular or near singular matrix, find a minimum norm solution using\n@sc{cxsparse}@footnote{The @sc{cholmod}, @sc{umfpack} and @sc{cxsparse}\npackages were written by Tim Davis and are available at\n@url{http://faculty.cse.tamu.edu/davis/suitesparse.html}}.\n@end enumerate\n\nThe band density is defined as the number of nonzero values in the band\ndivided by the total number of values in the full band.  The banded\nmatrix solvers can be entirely disabled by using @dfn{spparms} to set\n@code{bandden} to 1 (i.e., @code{spparms (\"bandden\", 1)}).\n\nThe QR@tie{}solver factorizes the problem with a @nospell{Dulmage-Mendelsohn}\ndecomposition, to separate the problem into blocks that can be treated\nas over-determined, multiple well determined blocks, and a final\nover-determined block.  For matrices with blocks of strongly connected\nnodes this is a big win as LU@tie{}decomposition can be used for many\nblocks.  It also significantly improves the chance of finding a solution\nto over-determined problems rather than just returning a vector of\n@dfn{NaN}'s.\n\nAll of the solvers above, can calculate an estimate of the condition\nnumber.  This can be used to detect numerical stability problems in the\nsolution and force a minimum norm solution to be used.  However, for\nnarrow banded, triangular or diagonal matrices, the cost of\ncalculating the condition number is significant, and can in fact\nexceed the cost of factoring the matrix.  Therefore the condition\nnumber is not calculated in these cases, and Octave relies on simpler\ntechniques to detect singular matrices or the underlying @sc{lapack} code in\nthe case of banded matrices.\n\nThe user can force the type of the matrix with the @code{matrix_type}\nfunction.  This overcomes the cost of discovering the type of the matrix.\nHowever, it should be noted that identifying the type of the matrix incorrectly\nwill lead to unpredictable results, and so @code{matrix_type} should be\nused with care.\n\n@DOCSTRING(normest)\n\n@DOCSTRING(normest1)\n\n@DOCSTRING(condest)\n\n@DOCSTRING(spparms)\n\n@DOCSTRING(sprank)\n\n@DOCSTRING(symbfact)\n\nFor non square matrices, the user can also utilize the @code{spaugment}\nfunction to find a least squares solution to a linear equation.\n\n@DOCSTRING(spaugment)\n\nFinally, the function @code{eigs} can be used to calculate a limited\nnumber of eigenvalues and eigenvectors based on a selection criteria\nand likewise for @code{svds} which calculates a limited number of\nsingular values and vectors.\n\n@DOCSTRING(eigs)\n\n@DOCSTRING(svds)\n\n@node Iterative Techniques\n@section Iterative Techniques Applied to Sparse Matrices\n\nThe left division @code{\\} and right division @code{/} operators,\ndiscussed in the previous section, use direct solvers to resolve a\nlinear equation of the form @code{@var{x} = @var{A} \\ @var{b}} or\n@code{@var{x} = @var{b} / @var{A}}.  Octave also includes a number of\nfunctions to solve sparse linear equations using iterative techniques.\n\n@DOCSTRING(pcg)\n\n@DOCSTRING(pcr)\n\nThe speed with which an iterative solver converges to a solution can be\naccelerated with the use of a pre-conditioning matrix @var{M}.  In this\ncase the linear equation @code{@var{M}^-1 * @var{x} = @var{M}^-1 *\n@var{A} \\ @var{b}} is solved instead.  Typical pre-conditioning matrices\nare partial factorizations of the original matrix.\n\n@DOCSTRING(ichol)\n\n@DOCSTRING(ilu)\n\n@node Real Life Example\n@section Real Life Example using Sparse Matrices\n\nA common application for sparse matrices is in the solution of Finite\nElement Models.  Finite element models allow numerical solution of\npartial differential equations that do not have closed form solutions,\ntypically because of the complex shape of the domain.\n\nIn order to motivate this application, we consider the boundary value\nLaplace equation.  This system can model scalar potential fields, such\nas heat or electrical potential.  Given a medium\n@tex\n$\\Omega$ with boundary $\\partial\\Omega$.  At all points on the $\\partial\\Omega$\nthe boundary conditions are known, and we wish to calculate the potential in\n$\\Omega$.\n@end tex\n@ifnottex\nOmega with boundary dOmega.  At all points on the dOmega\nthe boundary conditions are known, and we wish to calculate the potential in\nOmega.\n@end ifnottex\nBoundary conditions may specify the potential (Dirichlet\nboundary condition), its normal derivative across the boundary\n(@nospell{Neumann} boundary condition), or a weighted sum of the potential and\nits derivative (Cauchy boundary condition).\n\nIn a thermal model, we want to calculate the temperature in\n@tex\n$\\Omega$\n@end tex\n@ifnottex\nOmega\n@end ifnottex\nand know the boundary temperature (Dirichlet condition)\nor heat flux (from which we can calculate the @nospell{Neumann} condition\nby dividing by the thermal conductivity at the boundary).  Similarly,\nin an electrical model, we want to calculate the voltage in\n@tex\n$\\Omega$\n@end tex\n@ifnottex\nOmega\n@end ifnottex\nand know the boundary voltage (Dirichlet) or current\n(@nospell{Neumann} condition after diving by the electrical conductivity).\nIn an electrical model, it is common for much of the boundary\nto be electrically isolated; this is a @nospell{Neumann} boundary condition\nwith the current equal to zero.\n\nThe simplest finite element models will divide\n@tex\n$\\Omega$\n@end tex\n@ifnottex\nOmega\n@end ifnottex\ninto simplexes (triangles in 2-D, pyramids in 3-D).\n@ifset htmltex\nWe take as a 3-D example a cylindrical liquid filled tank with a small\nnon-conductive ball from the EIDORS project@footnote{EIDORS - Electrical\nImpedance Tomography and Diffuse optical Tomography Reconstruction Software\n@url{http://eidors3d.sourceforge.net}}.  This is model is designed to reflect\nan application of electrical impedance tomography, where current patterns\nare applied to such a tank in order to image the internal conductivity\ndistribution.  In order to describe the FEM geometry, we have a matrix of\nvertices @code{nodes} and simplices @code{elems}.\n@end ifset\n\nThe following example creates a simple rectangular 2-D electrically\nconductive medium with 10 V and 20 V imposed on opposite sides\n(Dirichlet boundary conditions).  All other edges are electrically\nisolated.\n\n@example\n@group\n   node_y = [1;1.2;1.5;1.8;2]*ones(1,11);\n   node_x = ones(5,1)*[1,1.05,1.1,1.2, ...\n             1.3,1.5,1.7,1.8,1.9,1.95,2];\n   nodes = [node_x(:), node_y(:)];\n\n   [h,w] = size (node_x);\n   elems = [];\n   for idx = 1:w-1\n     widx = (idx-1)*h;\n     elems = [elems; ...\n       widx+[(1:h-1);(2:h);h+(1:h-1)]'; ...\n       widx+[(2:h);h+(2:h);h+(1:h-1)]' ];\n   endfor\n\n   E = size (elems,1);  # No. of simplices\n   N = size (nodes,1);  # No. of vertices\n   D = size (elems,2);  # dimensions+1\n@end group\n@end example\n\nThis creates a N-by-2 matrix @code{nodes} and a E-by-3 matrix\n@code{elems} with values, which define finite element triangles:\n\n@example\n@group\n  nodes(1:7,:)'\n    1.00 1.00 1.00 1.00 1.00 1.05 1.05 @dots{}\n    1.00 1.20 1.50 1.80 2.00 1.00 1.20 @dots{}\n\n  elems(1:7,:)'\n    1    2    3    4    2    3    4 @dots{}\n    2    3    4    5    7    8    9 @dots{}\n    6    7    8    9    6    7    8 @dots{}\n@end group\n@end example\n\nUsing a first order FEM, we approximate the electrical conductivity\ndistribution in\n@tex\n$\\Omega$\n@end tex\n@ifnottex\nOmega\n@end ifnottex\nas constant on each simplex (represented by the vector @code{conductivity}).\nBased on the finite element geometry, we first calculate a system (or\nstiffness) matrix for each simplex (represented as 3-by-3 elements on the\ndiagonal of the element-wise system matrix @code{SE}).  Based on @code{SE}\nand a N-by-DE connectivity matrix @code{C}, representing the connections\nbetween simplices and vertices, the global connectivity matrix @code{S} is\ncalculated.\n\n@example\n  ## Element conductivity\n  conductivity = [1*ones(1,16), ...\n         2*ones(1,48), 1*ones(1,16)];\n\n  ## Connectivity matrix\n  C = sparse ((1:D*E), reshape (elems', ...\n         D*E, 1), 1, D*E, N);\n\n  ## Calculate system matrix\n  Siidx = floor ([0:D*E-1]'/D) * D * ...\n         ones(1,D) + ones(D*E,1)*(1:D) ;\n  Sjidx = [1:D*E]'*ones (1,D);\n  Sdata = zeros (D*E,D);\n  dfact = factorial (D-1);\n  for j = 1:E\n     a = inv ([ones(D,1), ...\n         nodes(elems(j,:), :)]);\n     const = conductivity(j) * 2 / ...\n         dfact / abs (det (a));\n     Sdata(D*(j-1)+(1:D),:) = const * ...\n         a(2:D,:)' * a(2:D,:);\n  endfor\n  ## Element-wise system matrix\n  SE = sparse(Siidx,Sjidx,Sdata);\n  ## Global system matrix\n  S = C'* SE *C;\n@end example\n\nThe system matrix acts like the conductivity\n@tex\n$S$\n@end tex\n@ifnottex\n@code{S}\n@end ifnottex\nin Ohm's law\n@tex\n$SV = I$.\n@end tex\n@ifnottex\n@code{S * V = I}.\n@end ifnottex\nBased on the Dirichlet and @nospell{Neumann} boundary conditions, we are able\nto solve for the voltages at each vertex @code{V}.\n\n@example\n  ## Dirichlet boundary conditions\n  D_nodes = [1:5, 51:55];\n  D_value = [10*ones(1,5), 20*ones(1,5)];\n\n  V = zeros (N,1);\n  V(D_nodes) = D_value;\n  idx = 1:N; # vertices without Dirichlet\n             # boundary condns\n  idx(D_nodes) = [];\n\n  ## Neumann boundary conditions.  Note that\n  ## N_value must be normalized by the\n  ## boundary length and element conductivity\n  N_nodes = [];\n  N_value = [];\n\n  Q = zeros (N,1);\n  Q(N_nodes) = N_value;\n\n  V(idx) = S(idx,idx) \\ ( Q(idx) - ...\n            S(idx,D_nodes) * V(D_nodes));\n@end example\n\nFinally, in order to display the solution, we show each solved voltage\nvalue in the z-axis for each simplex vertex.\n@ifset htmltex\n@xref{fig:femmodel}.\n@end ifset\n\n@example\n@group\n  elemx = elems(:,[1,2,3,1])';\n  xelems = reshape (nodes(elemx, 1), 4, E);\n  yelems = reshape (nodes(elemx, 2), 4, E);\n  velems = reshape (V(elemx), 4, E);\n  plot3 (xelems,yelems,velems,\"k\");\n  print \"grid.eps\";\n@end group\n@end example\n\n\n@ifset htmltex\n@float Figure,fig:femmodel\n@center @image{grid,4in}\n@caption{Example finite element model the showing triangular elements.\nThe height of each vertex corresponds to the solution value.}\n@end float\n@end ifset\n"
  },
  {
    "path": "doc/interpreter/sparseimages.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nfunction sparseimages (d, nm, typ)\n\n  if (strcmp (typ, \"txt\"))\n    txtimages (d, nm, 15, typ);\n    return;\n  endif\n\n  set_graphics_toolkit ();\n  set_print_size ();\n  hide_output ();\n  outfile = fullfile (d, [nm \".\" typ]);\n  if (strcmp (typ, \"png\"))\n    set (groot, \"defaulttextfontname\", \"*\");\n  endif\n  if (strcmp (typ, \"eps\"))\n    d_typ = \"-depsc2\";\n  else\n    d_typ = [\"-d\" typ];\n  endif\n\n  if (! (__have_feature__ (\"COLAMD\")\n         && __have_feature__ (\"CHOLMOD\")\n         && __have_feature__ (\"UMFPACK\")))\n    ## There is no sparse matrix implementation available because\n    ## of missing libraries, plot sombreros instead.\n    sombreroimage (outfile, typ, d_typ);\n  elseif (strcmp (nm, \"gplot\"))\n    A = sparse ([2,6,1,3,2,4,3,5,4,6,1,5],\n                [1,1,2,2,3,3,4,4,5,5,6,6], 1, 6, 6);\n    xy = [0,4,8,6,4,2;5,0,5,7,5,7]';\n    gplot (A, xy);\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"grid\"))\n    femimages (outfile, d_typ);\n  elseif (strcmp (nm, \"spmatrix\"))\n    n = 200;\n    a = 10*speye (n) + sparse (1:n,ceil ([1:n]/2),1,n,n) + ...\n        sparse (ceil ([1:n]/2),1:n,1,n,n);\n    spy (a);\n    axis (\"ij\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"spchol\"))\n    n = 200;\n    a = 10*speye (n) + sparse (1:n,ceil ([1:n]/2),1,n,n) + ...\n        sparse (ceil ([1:n]/2),1:n,1,n,n);\n    r1 = chol (a);\n    spy (r1);\n    axis (\"ij\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"spcholperm\"))\n    n = 200;\n    a = 10*speye (n) + sparse (1:n,ceil ([1:n]/2),1,n,n) + ...\n        sparse (ceil ([1:n]/2),1:n,1,n,n);\n    [r2,p2,q2] = chol (a);\n    spy (r2);\n    axis (\"ij\");\n    print (outfile, d_typ);\n  else\n    error (\"unrecognized plot requested\");\n  endif\n  hide_output ();\nendfunction\n\nfunction txtimages (d, nm, n, typ)\n  outfile = fullfile (d, [nm \".\" typ]);\n  a = 10*speye (n) + sparse (1:n,ceil([1:n]/2),1,n,n) + ...\n      sparse (ceil ([1:n]/2),1:n,1,n,n);\n  if (strcmp (nm, \"gplot\") || strcmp (nm, \"grid\"))\n    fid = fopen (outfile, \"wt\");\n    fputs (fid, \"\\n\");\n    fputs (fid, \"+---------------------------------+\\n\");\n    fputs (fid, \"| Image unavailable in text mode. |\\n\");\n    fputs (fid, \"+---------------------------------+\\n\");\n    fclose (fid);\n  elseif (strcmp (nm, \"spmatrix\"))\n    printsparse (a, outfile);\n  elseif (strcmp (nm, \"spchol\"))\n    r1 = chol (a);\n    printsparse (r1, outfile);\n  elseif (strcmp (nm, \"spcholperm\"))\n    [r2,p2,q2] = chol (a);\n    printsparse (r2, outfile);\n  else\n    error (\"unrecognized plot requested\");\n  endif\nendfunction\n\nfunction printsparse (a, nm)\n  fid = fopen (nm, \"wt\");\n  fputs (fid, \"\\n\");\n  for i = 1:rows (a)\n    if (rem (i,5) == 0)\n      fprintf (fid, \"         %2d - \", i);\n    else\n      fprintf (fid, \"            | \");\n    endif\n    for j = 1:columns (a)\n      if (a(i,j) == 0)\n        fprintf (fid, \"  \");\n      else\n        fprintf (fid, \" *\");\n      endif\n    endfor\n    fprintf (fid, \"\\n\");\n  endfor\n  fprintf (fid, \"            |-\");\n  for j = 1:columns (a)\n    if (rem (j,5) == 0)\n      fprintf (fid, \"-|\");\n    else\n      fprintf (fid, \"--\");\n    endif\n  endfor\n  fprintf (fid, \"\\n\");\n  fprintf (fid, \"              \");\n  for j = 1:columns (a)\n    if (rem (j,5) == 0)\n      fprintf (fid, \"%2d\", j);\n    else\n      fprintf (fid, \"  \");\n    endif\n  endfor\n  fclose (fid);\nendfunction\n\nfunction femimages (outfile, d_typ)\n\n  ## build a rectangle\n  node_y = [1;1.2;1.5;1.8;2] * ones (1,11);\n  node_x = ones (5,1) * [1,1.05,1.1,1.2,1.3,1.5,1.7,1.8,1.9,1.95,2];\n  nodes = [node_x(:), node_y(:)];\n\n  [h,w] = size (node_x);\n  elems = [];\n  for idx = 1 : w-1\n    widx = (idx-1)*h;\n    elems = [elems; widx+[(1:h-1);(2:h);h+(1:h-1)]'];\n    elems = [elems; widx+[(2:h);h+(2:h);h+(1:h-1)]'];\n  endfor\n\n  E = size (elems,1);  # No. of elements\n  N = size (nodes,1);  # No. of elements\n  D = size (elems,2);  # dimensions+1\n\n  ## Plot FEM Geometry\n  elemx = elems(:,[1,2,3,1])';\n  xelems = reshape (nodes(elemx, 1), 4, E);\n  yelems = reshape (nodes(elemx, 2), 4, E);\n\n  ## Set element conductivity\n  conductivity = [1*ones(1,16), 2*ones(1,48), 1*ones(1,16)];\n\n  ## Dirichlet boundary conditions\n  D_nodes = [1:5, 51:55];\n  D_value = [10*ones(1,5), 20*ones(1,5)];\n\n  ## Neumann boundary conditions\n  ## Note that N_value must be normalized by the boundary\n  ##   length and element conductivity\n  N_nodes = [];\n  N_value = [];\n\n  ## Calculate connectivity matrix\n  C = sparse ((1:D*E), reshape (elems',D*E,1),1, D*E, N);\n\n  ## Calculate stiffness matrix\n  Siidx = floor ([0:D*E-1]'/D)*D*ones(1,D) + ones(D*E,1)*(1:D);\n  Sjidx = [1:D*E]'*ones (1,D);\n  Sdata = zeros (D*E,D);\n  dfact = prod (2:(D-1));\n  for j = 1:E\n    a = inv ([ ones(D,1), nodes( elems(j,:), : ) ]);\n    const = conductivity(j)*2/dfact/abs (det (a));\n    Sdata(D*(j-1)+(1:D),:) = const * a(2:D,:)'*a(2:D,:);\n  endfor\n\n  ## Element-wise system matrix\n  SE = sparse (Siidx,Sjidx,Sdata);\n  ## Global system matrix\n  S = C'* SE *C;\n\n  ## Set Dirichlet boundary\n  V = zeros (N,1);\n  V(D_nodes) = D_value;\n  idx = 1:N;\n  idx(D_nodes) = [];\n\n  ## Set Neumann boundary\n  Q = zeros (N,1);\n  Q(N_nodes) = N_value; # FIXME\n\n  V(idx) = S(idx,idx) \\ ( Q(idx) - S(idx,D_nodes)*V(D_nodes) );\n\n  velems = reshape (V(elemx), 4, E);\n\n  plot3 (xelems, yelems, velems);\n  view (80, 10);\n  print (outfile, d_typ);\nendfunction\n\n## There is no sparse matrix implementation available because of missing\n## libraries, plot sombreros instead.  Also plot a nice title that we are\n## sorry about that.\nfunction sombreroimage (outfile, typ, d_typ)\n  if (strcmp (typ, \"txt\"))\n    fid = fopen (outfile, \"wt\");\n    fputs (fid, \"+--------------------------------+\\n\");\n    fputs (fid, \"| Image unavailable because of a |\\n\");\n    fputs (fid, \"| missing SuiteSparse library.   |\\n\");\n    fputs (fid, \"+--------------------------------+\\n\");\n    fclose (fid);\n    return;\n  else\n    [x, y, z] = sombrero ();\n    unwind_protect\n      mesh (x, y, z);\n      title ({\"Sorry, graphics are unavailable because Octave was\",\n              \"compiled without the SuiteSparse library.\"});\n    unwind_protect_cleanup\n      print (outfile, d_typ);\n      hide_output ();\n    end_unwind_protect\n  endif\nendfunction\n\n## This function no longer sets the graphics toolkit; That is now done\n## automatically by C++ code which will ordinarily choose 'qt', but might\n## choose gnuplot on older systems.  Only a complete lack of plotting is a\n## problem.\nfunction set_graphics_toolkit ()\n  if (isempty (available_graphics_toolkits ()))\n    error (\"no graphics toolkit available for plotting\");\n  elseif (strcmp (\"qt\", graphics_toolkit ()))\n    ## Use qt with QOffscreenSurface for plot\n  elseif (! strcmp (\"gnuplot\", graphics_toolkit ()))\n    if (! any (strcmp (\"gnuplot\", available_graphics_toolkits ())))\n      error (\"no graphics toolkit available for offscreen plotting\");\n    else\n      graphics_toolkit (\"gnuplot\");\n    endif\n  endif\nendfunction\n\nfunction set_print_size ()\n  image_size = [5.0, 3.5]; # in inches, 16:9 format\n  border = 0;              # For postscript use 50/72\n  set (groot, \"defaultfigurepapertype\", \"<custom>\");\n  set (groot, \"defaultfigurepaperorientation\", \"landscape\");\n  set (groot, \"defaultfigurepapersize\", image_size + 2*border);\n  set (groot, \"defaultfigurepaperposition\", [border, border, image_size]);\nendfunction\n\n## Use this function before plotting commands and after every call to print\n## since print() resets output to stdout (unfortunately, gnuplot can't pop\n## output as it can the terminal type).\nfunction hide_output ()\n  hf = figure (1, \"visible\", \"off\");\nendfunction\n"
  },
  {
    "path": "doc/interpreter/splineimages.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nfunction splineimages (d, nm, typ)\n\n  if (strcmp (typ, \"txt\"))\n    image_as_txt (d, nm);\n    return;\n  endif\n\n  set_graphics_toolkit ();\n  set_print_size ();\n  hide_output ();\n  outfile = fullfile (d, [nm \".\" typ]);\n  if (strcmp (typ, \"png\"))\n    set (groot, \"defaulttextfontname\", \"*\");\n  endif\n  if (strcmp (typ, \"eps\"))\n    d_typ = \"-depsc2\";\n  else\n    d_typ = [\"-d\" typ];\n  endif\n\n  if (strcmp (nm, \"splinefit1\")) ## Breaks and Pieces\n    rand (\"state\", 1);\n    randn (\"state\", 1);\n    x = 2 * pi * rand (1, 200);\n    y = sin (x) + sin (2 * x) + 0.2 * randn (size (x));\n    ## Uniform breaks\n    breaks = linspace (0, 2 * pi, 41); ## 41 breaks, 40 pieces\n    pp1 = splinefit (x, y, breaks);\n    ## Breaks interpolated from data\n    pp2 = splinefit (x, y, 10);  ## 11 breaks, 10 pieces\n    ## Plot\n    xx = linspace (0, 2 * pi, 400);\n    y1 = ppval (pp1, xx);\n    y2 = ppval (pp2, xx);\n    plot (x, y, \".\", xx, [y1; y2]);\n    axis tight;\n    ylim ([-2.5 2.5]);\n    legend (\"data\", \"41 breaks, 40 pieces\", \"11 breaks, 10 pieces\");\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"splinefit2\")) ## Spline orders\n    ## Data (200 points)\n    rand (\"state\", 1);\n    randn (\"state\", 1);\n    x = 2 * pi * rand (1, 200);\n    y = sin (x) + sin (2 * x) + 0.1 * randn (size (x));\n    ## Splines\n    pp1 = splinefit (x, y, 8, \"order\", 0);  ## Piecewise constant\n    pp2 = splinefit (x, y, 8, \"order\", 1);  ## Piecewise linear\n    pp3 = splinefit (x, y, 8, \"order\", 2);  ## Piecewise quadratic\n    pp4 = splinefit (x, y, 8, \"order\", 3);  ## Piecewise cubic\n    pp5 = splinefit (x, y, 8, \"order\", 4);  ## Etc.\n    ## Plot\n    xx = linspace (0, 2 * pi, 400);\n    y1 = ppval (pp1, xx);\n    y2 = ppval (pp2, xx);\n    y3 = ppval (pp3, xx);\n    y4 = ppval (pp4, xx);\n    y5 = ppval (pp5, xx);\n    plot (x, y, \".\", xx, [y1; y2; y3; y4; y5]);\n    axis tight;\n    ylim ([-2.5 2.5]);\n    legend ({\"data\", \"order 0\", \"order 1\", \"order 2\", \"order 3\", \"order 4\"});\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"splinefit3\"))\n    ## Data (100 points)\n    rand (\"state\", 1);\n    randn (\"state\", 1);\n    x = 2 * pi * [0, (rand (1, 98)), 1];\n    y = sin (x) - cos (2 * x) + 0.2 * randn (size (x));\n    ## No constraints\n    pp1 = splinefit (x, y, 10, \"order\", 5);\n    ## Periodic boundaries\n    pp2 = splinefit (x, y, 10, \"order\", 5, \"periodic\", true);\n    ## Plot\n    xx = linspace (0, 2 * pi, 400);\n    y1 = ppval (pp1, xx);\n    y2 = ppval (pp2, xx);\n    plot (x, y, \".\", xx, [y1; y2]);\n    axis tight;\n    ylim ([-2 3]);\n    legend ({\"data\", \"no constraints\", \"periodic\"});\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"splinefit4\"))\n    ## Data (200 points)\n    rand (\"state\", 1);\n    randn (\"state\", 1);\n    x = 2 * pi * rand (1, 200);\n    y = sin (2 * x) + 0.1 * randn (size (x));\n    ## Breaks\n    breaks = linspace (0, 2 * pi, 10);\n    ## Clamped endpoints, y = y\" = 0\n    xc = [0, 0, 2*pi, 2*pi];\n    cc = [(eye (2)), (eye (2))];\n    con = struct (\"xc\", xc, \"cc\", cc);\n    pp1 = splinefit (x, y, breaks, \"constraints\", con);\n    ## Hinged periodic endpoints, y = 0\n    con = struct (\"xc\", 0);\n    pp2 = splinefit (x, y, breaks, \"constraints\", con, \"periodic\", true);\n    ## Plot\n    xx = linspace (0, 2 * pi, 400);\n    y1 = ppval (pp1, xx);\n    y2 = ppval (pp2, xx);\n    plot (x, y, \".\", xx, [y1; y2]);\n    axis tight;\n    ylim ([-1.5 1.5]);\n    legend ({\"data\", \"clamped\", \"hinged periodic\"});\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"splinefit5\"))\n    ## Truncated data\n    x = [0,  1,  2,  4,  8, 16, 24, 40, 56, 72, 80] / 80;\n    y = [0, 28, 39, 53, 70, 86, 90, 79, 55, 22,  2] / 1000;\n    xy = [x; y];\n    ## Curve length parameter\n    ds = sqrt (diff (x).^2 + diff (y).^2);\n    s = [0, cumsum(ds)];\n    ## Constraints at s = 0: (x,y) = (0,0), (dx/ds,dy/ds) = (0,1)\n    con = struct (\"xc\", [0 0], \"yc\", [0 0; 0 1], \"cc\", eye (2));\n    ## Fit a spline with 4 pieces\n    pp = splinefit (s, xy, 4, \"constraints\", con);\n    ## Plot\n    ss = linspace (0, s(end), 400);\n    xyfit = ppval (pp, ss);\n    xyb = ppval (pp, pp.breaks);\n    plot (x, y, \".\", xyfit(1,:), xyfit(2,:), \"r\", xyb(1,:), xyb(2,:), \"ro\");\n    legend ({\"data\", \"spline\", \"breaks\"});\n    axis tight;\n    ylim ([0 0.1]);\n    print (outfile, d_typ);\n  elseif (strcmp (nm, \"splinefit6\"))\n    ## Data\n    randn (\"state\", 1);\n    x = linspace (0, 2*pi, 200);\n    y = sin (x) + sin (2 * x) + 0.05 * randn (size (x));\n    ## Add outliers\n    x = [x, linspace(0,2*pi,60)];\n    y = [y, -ones(1,60)];\n    ## Fit splines with hinged conditions\n    con = struct (\"xc\", [0, 2*pi]);\n    pp1 = splinefit (x, y, 8, \"constraints\", con, \"beta\", 0.25); ## Robust fitting\n    pp2 = splinefit (x, y, 8, \"constraints\", con, \"beta\", 0.75); ## Robust fitting\n    pp3 = splinefit (x, y, 8, \"constraints\", con); ## No robust fitting\n    ## Plot\n    xx = linspace (0, 2*pi, 400);\n    y1 = ppval (pp1, xx);\n    y2 = ppval (pp2, xx);\n    y3 = ppval (pp3, xx);\n    plot (x, y, \".\", xx, [y1; y2; y3]);\n    legend ({\"data with outliers\",\"robust, beta = 0.25\", ...\n             \"robust, beta = 0.75\", \"no robust fitting\"});\n    axis tight;\n    ylim ([-2 2]);\n    print (outfile, d_typ);\n  endif\n  hide_output ();\nendfunction\n\n## This function no longer sets the graphics toolkit; That is now done\n## automatically by C++ code which will ordinarily choose 'qt', but might\n## choose gnuplot on older systems.  Only a complete lack of plotting is a\n## problem.\nfunction set_graphics_toolkit ()\n  if (isempty (available_graphics_toolkits ()))\n    error (\"no graphics toolkit available for plotting\");\n  elseif (strcmp (\"qt\", graphics_toolkit ()))\n    ## Use qt with QOffscreenSurface for plot\n  elseif (! strcmp (\"gnuplot\", graphics_toolkit ()))\n    if (! any (strcmp (\"gnuplot\", available_graphics_toolkits ())))\n      error (\"no graphics toolkit available for offscreen plotting\");\n    else\n      graphics_toolkit (\"gnuplot\");\n    endif\n  endif\nendfunction\n\nfunction set_print_size ()\n  image_size = [5.0, 3.5]; # in inches, 16:9 format\n  border = 0;              # For postscript use 50/72\n  set (groot, \"defaultfigurepapertype\", \"<custom>\");\n  set (groot, \"defaultfigurepaperorientation\", \"landscape\");\n  set (groot, \"defaultfigurepapersize\", image_size + 2*border);\n  set (groot, \"defaultfigurepaperposition\", [border, border, image_size]);\n  ## FIXME: Required until listener for legend exists (bug #39697)\n  set (groot, \"defaultfigureposition\", [ 72*[border, border, image_size] ]);\nendfunction\n\n## Use this function before plotting commands and after every call to print\n## since print() resets output to stdout (unfortunately, gnuplot can't pop\n## output as it can the terminal type).\nfunction hide_output ()\n  hf = figure (1, \"visible\", \"off\");\nendfunction\n\n## generate something for the texinfo @image command to process\nfunction image_as_txt (d, nm)\n  fid = fopen (fullfile (d, [nm \".txt\"]), \"wt\");\n  fputs (fid, \"\\n\");\n  fputs (fid, \"+---------------------------------+\\n\");\n  fputs (fid, \"| Image unavailable in text mode. |\\n\");\n  fputs (fid, \"+---------------------------------+\\n\");\n  fclose (fid);\nendfunction\n"
  },
  {
    "path": "doc/interpreter/stats.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Statistics\n@chapter Statistics\n\nOctave has support for various statistical methods, emphasizing basic\ndescriptive statistics.  More advanced functions for probability distributions,\nstatistical tests, random number generation, etc.@: are provided by the add-on\nStatistics package from Octave Packages.\n\nThe functions that analyze data all assume that multi-dimensional data is\narranged in a matrix where each row is an observation, and each column is a\nvariable.  Thus, the matrix defined by\n\n@example\n@group\na = [ 0.9, 0.7;\n      0.1, 0.1;\n      0.5, 0.4 ];\n@end group\n@end example\n\n@noindent\ncontains three observations from a two-dimensional distribution.  While this is\nthe default data arrangement, most functions support different arrangements.\n\nIt should be noted that the statistics functions don't test for data containing\nNaN, NA, or Inf.  These values need to be detected and dealt with explicitly.\nSee @ref{XREFisnan,,isnan}, @ref{XREFisna,,isna}, @ref{XREFisinf,,isinf},\nand @ref{XREFisfinite,,isfinite}.\n\n@menu\n* Descriptive Statistics::\n* Statistics on Sliding Windows of Data::\n* Basic Statistical Functions::\n* Forecasting Metrics::\n* Correlation and Regression Analysis::\n* Distributions::\n* Random Number Generation::\n@end menu\n\n@node Descriptive Statistics\n@section Descriptive Statistics\n\nOne principal goal of descriptive statistics is to represent the essence of a\nlarge data set concisely.  Octave provides the mean, median, and mode functions\nwhich all summarize a data set with just a single number corresponding to\nthe central tendency of the data.\n\n@DOCSTRING(mean)\n\n@DOCSTRING(median)\n\n@DOCSTRING(mode)\n\nUsing just one number, such as the mean, to represent an entire data set may\nnot give an accurate picture of the data.  One way to characterize the fit is\nto measure the dispersion of the data.  Octave provides several functions for\nmeasuring dispersion.\n\n@DOCSTRING(bounds)\n\n@DOCSTRING(range)\n\n@DOCSTRING(iqr)\n\n@DOCSTRING(mad)\n\n@DOCSTRING(meansq)\n\n@DOCSTRING(rms)\n\n@DOCSTRING(std)\n\nIn addition to knowing the size of a dispersion it is useful to know the shape\nof the data set.  For example, are data points massed to the left or right\nof the mean?  Octave provides several common measures to describe the shape\nof the data set.  Octave can also calculate moments allowing arbitrary shape\nmeasures to be developed.\n\n@DOCSTRING(var)\n\n@DOCSTRING(skewness)\n\n@DOCSTRING(kurtosis)\n\n@DOCSTRING(moment)\n\n@DOCSTRING(quantile)\n\n@DOCSTRING(prctile)\n\nA summary view of a data set can be generated quickly with the\n@code{statistics} function.\n\n@DOCSTRING(statistics)\n\n@node Statistics on Sliding Windows of Data\n@section Statistics on Sliding Windows of Data\n\nIt is often useful to calculate descriptive statistics over a subsection\n(i.e., window) of a full dataset.  Octave provides the function @code{movfun}\nwhich will call an arbitrary function handle with windows of data and\naccumulate the results.  Many of the most commonly desired functions, such as\nthe moving average over a window of data (@code{movmean}), are already\nprovided.\n\n@DOCSTRING(movfun)\n\n@DOCSTRING(movslice)\n\n@DOCSTRING(movmad)\n\n@DOCSTRING(movmax)\n\n@DOCSTRING(movmean)\n\n@DOCSTRING(movmedian)\n\n@DOCSTRING(movmin)\n\n@DOCSTRING(movprod)\n\n@DOCSTRING(movstd)\n\n@DOCSTRING(movsum)\n\n@DOCSTRING(movvar)\n\n@node Basic Statistical Functions\n@section Basic Statistical Functions\n\nOctave supports various helpful statistical functions.  Many are useful as\ninitial steps to prepare a data set for further analysis.  Others provide\ndifferent measures from those of the basic descriptive statistics.\n\n@DOCSTRING(center)\n\n@DOCSTRING(zscore)\n\n@DOCSTRING(normalize)\n\n@DOCSTRING(histc)\n\n@noindent\n@code{unique} function documented at @ref{XREFunique,,unique} is often\nuseful for statistics.\n\n@DOCSTRING(nchoosek)\n\n@DOCSTRING(perms)\n\n@DOCSTRING(ranks)\n\n@DOCSTRING(run_count)\n\n@DOCSTRING(runlength)\n\n@node Forecasting Metrics\n@section Forecasting Metrics\n\nOctave supports the following functions for calculating forecasting metrics.\n\n@DOCSTRING(mape)\n\n@DOCSTRING(rmse)\n\n@node Correlation and Regression Analysis\n@section Correlation and Regression Analysis\n\nOctave supports several functions for investigating the relationship between\nsets of quantitative variables.\n\n@DOCSTRING(cov)\n\n@DOCSTRING(corr)\n\n@DOCSTRING(corrcoef)\n\n@DOCSTRING(corrcov)\n\n@DOCSTRING(spearman)\n\n@DOCSTRING(kendall)\n\n@node Distributions\n@section Distributions\n\nOctave has functions for computing the Probability Density Function (PDF), the\nCumulative Distribution function (CDF), and the quantile (the inverse of the\nCDF) for arbitrary user-defined distributions (discrete) and for experimental\ndata (empirical).\n\nThe following table summarizes the supported distributions (in alphabetical\norder).\n\n@tex\n\\vskip 6pt\n{\\hbox to \\hsize {\\hfill\\vbox{\\offinterlineskip \\tabskip=0pt\n\\halign{\n\\vrule height2.0ex depth1.ex width 0.6pt #\\tabskip=0.3em &\n# \\hfil & \\vrule # & # \\hfil & \\vrule # & # \\hfil & \\vrule # & # \\hfil &\n# \\vrule width 0.6pt \\tabskip=0pt\\cr\n\\noalign{\\hrule height 0.6pt}\n& {\\bf Distribution} && {\\bf PDF}      && {\\bf CDF}     && {\\bf Quantile}&\\cr\n\\noalign{\\hrule}\n&Univariate Discrete       && discrete\\_pdf  && discrete\\_cdf && discrete\\_inv&\\cr\n&Empirical    && empirical\\_pdf  && empirical\\_cdf && empirical\\_inv&\\cr\n\\noalign{\\hrule height 0.6pt}\n}}\\hfill}}\n@end tex\n@ifnottex\n@multitable @columnfractions .31 .23 .23 .23\n@headitem Distribution\n  @tab PDF\n  @tab CDF\n  @tab Quantile\n@item Univariate Discrete Distribution\n  @tab @code{discrete_pdf}\n  @tab @code{discrete_cdf}\n  @tab @code{discrete_inv}\n@item Empirical Distribution\n  @tab @code{empirical_pdf}\n  @tab @code{empirical_cdf}\n  @tab @code{empirical_inv}\n@end multitable\n@end ifnottex\n\n@DOCSTRING(discrete_pdf)\n\n@DOCSTRING(discrete_cdf)\n\n@DOCSTRING(discrete_inv)\n\n@DOCSTRING(empirical_pdf)\n\n@DOCSTRING(empirical_cdf)\n\n@DOCSTRING(empirical_inv)\n\n@node Random Number Generation\n@section Random Number Generation\n\nOctave can generate random numbers from a large number of distributions.  The\nrandom number generators are based on the random number generators described in\n@ref{Special Utility Matrices}.\n\nThe following table summarizes the available random number generators (in\nalphabetical order).\n\n@tex\n\\vskip 6pt\n{\\hbox to \\hsize {\\hfill\\vbox{\\offinterlineskip \\tabskip=0pt\n\\halign{\n\\vrule height2.0ex depth1.ex width 0.6pt #\\tabskip=0.3em &\n# \\hfil & \\vrule # & # \\hfil & # \\vrule width 0.6pt \\tabskip=0pt\\cr\n\\noalign{\\hrule height 0.6pt}\n& {\\bf Distribution}                && {\\bf Function} &\\cr\n\\noalign{\\hrule}\n& Univariate Discrete Distribution  && discrete\\_rnd &\\cr\n& Empirical Distribution            && empirical\\_rnd &\\cr\n& Exponential Distribution          && rande &\\cr\n& Gamma Distribution                && randg &\\cr\n& Poisson Distribution              && randp &\\cr\n& Standard Normal Distribution      && randn &\\cr\n& Uniform Distribution              && rand &\\cr\n& Uniform Distribution (integers)   && randi &\\cr\n\\noalign{\\hrule height 0.6pt}\n}}\\hfill}}\n@end tex\n@ifnottex\n@multitable @columnfractions .4 .3\n@headitem Distribution                  @tab Function\n@item Univariate Discrete Distribution  @tab @code{discrete_rnd}\n@item Empirical Distribution            @tab @code{empirical_rnd}\n@item Exponential Distribution          @tab @code{rande}\n@item Gamma Distribution                @tab @code{randg}\n@item Poisson Distribution              @tab @code{randp}\n@item Standard Normal Distribution      @tab @code{randn}\n@item Uniform Distribution              @tab @code{rand}\n@item Uniform Distribution (integers)   @tab @code{randi}\n@end multitable\n@end ifnottex\n\n@DOCSTRING(discrete_rnd)\n\n@DOCSTRING(empirical_rnd)\n"
  },
  {
    "path": "doc/interpreter/stmt.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Statements\n@chapter Statements\n@cindex statements\n\nStatements may be a simple constant expression or a complicated list of\nnested loops and conditional statements.\n\n@dfn{Control statements} such as @code{if}, @code{while}, and so on\ncontrol the flow of execution in Octave programs.  All the control\nstatements start with special keywords such as @code{if} and\n@code{while}, to distinguish them from simple expressions.\nMany control statements contain other statements; for example, the\n@code{if} statement contains another statement which may or may not be\nexecuted.\n\n@cindex @code{end} statement\nEach control statement has a corresponding @dfn{end} statement that\nmarks the end of the control statement.  For example, the\nkeyword @code{endif} marks the end of an @code{if} statement, and\n@code{endwhile} marks the end of a @code{while} statement.  You can use\nthe keyword @code{end} anywhere a more specific end keyword is expected,\nbut using the more specific keywords is preferred because if you use\nthem, Octave is able to provide better diagnostics for mismatched or\nmissing end tokens.\n\nThe list of statements contained between keywords like @code{if} or\n@code{while} and the corresponding end statement is called the\n@dfn{body} of a control statement.\n\n@menu\n* The if Statement::\n* The switch Statement::\n* The while Statement::\n* The do-until Statement::\n* The for Statement::\n* The break Statement::\n* The continue Statement::\n* The unwind_protect Statement::\n* The try Statement::\n* Continuation Lines::\n@end menu\n\n@node The if Statement\n@section The if Statement\n@cindex @code{if} statement\n@cindex @code{else} statement\n@cindex @code{elseif} statement\n@cindex @code{endif} statement\n\nThe @code{if} statement is Octave's decision-making statement.  There\nare three basic forms of an @code{if} statement.  In its simplest form,\nit looks like this:\n\n@example\n@group\nif (@var{condition})\n  @var{then-body}\nendif\n@end group\n@end example\n\n@noindent\n@var{condition} is an expression that controls what the rest of the\nstatement will do.  The @var{then-body} is executed only if\n@var{condition} is true.\n\nThe condition in an @code{if} statement is considered true if its value\nis nonzero, and false if its value is zero.  If the value of the\nconditional expression in an @code{if} statement is a vector or a\nmatrix, it is considered true only if it is non-empty and @emph{all}\nof the elements are nonzero.  The conceptually equivalent code when\n@var{condition} is a matrix is shown below.\n\n@example\nif (@var{matrix}) @equiv{} if (all (@var{matrix}(:)))\n@end example\n\n@noindent\nThe second form of an if statement looks like this:\n\n@example\n@group\nif (@var{condition})\n  @var{then-body}\nelse\n  @var{else-body}\nendif\n@end group\n@end example\n\n@noindent\nIf @var{condition} is true, @var{then-body} is executed; otherwise,\n@var{else-body} is executed.\n\nHere is an example:\n\n@example\n@group\nif (rem (x, 2) == 0)\n  printf (\"x is even\\n\");\nelse\n  printf (\"x is odd\\n\");\nendif\n@end group\n@end example\n\nIn this example, if the expression @code{rem (x, 2) == 0} is true (that\nis, the value of @code{x} is divisible by 2), then the first\n@code{printf} statement is evaluated, otherwise the second @code{printf}\nstatement is evaluated.\n\nThe third and most general form of the @code{if} statement allows\nmultiple decisions to be combined in a single statement.  It looks like\nthis:\n\n@example\n@group\nif (@var{condition})\n  @var{then-body}\nelseif (@var{condition})\n  @var{elseif-body}\nelse\n  @var{else-body}\nendif\n@end group\n@end example\n\n@noindent\nAny number of @code{elseif} clauses may appear.  Each condition is\ntested in turn, and if one is found to be true, its corresponding\n@var{body} is executed.  If none of the conditions are true and the\n@code{else} clause is present, its body is executed.  Only one\n@code{else} clause may appear, and it must be the last part of the\nstatement.\n\nIn the following example, if the first condition is true (that is, the\nvalue of @code{x} is divisible by 2), then the first @code{printf}\nstatement is executed.  If it is false, then the second condition is\ntested, and if it is true (that is, the value of @code{x} is divisible\nby 3), then the second @code{printf} statement is executed.  Otherwise,\nthe third @code{printf} statement is performed.\n\n@example\n@group\nif (rem (x, 2) == 0)\n  printf (\"x is even\\n\");\nelseif (rem (x, 3) == 0)\n  printf (\"x is odd and divisible by 3\\n\");\nelse\n  printf (\"x is odd\\n\");\nendif\n@end group\n@end example\n\nNote that the @code{elseif} keyword must not be spelled @code{else if},\nas is allowed in Fortran.  If it is, the space between the @code{else}\nand @code{if} will tell Octave to treat this as a new @code{if}\nstatement within another @code{if} statement's @code{else} clause.  For\nexample, if you write\n\n@example\n@group\nif (@var{c1})\n  @var{body-1}\nelse if (@var{c2})\n  @var{body-2}\nendif\n@end group\n@end example\n\n@noindent\nOctave will expect additional input to complete the first @code{if}\nstatement.  If you are using Octave interactively, it will continue to\nprompt you for additional input.  If Octave is reading this input from a\nfile, it may complain about missing or mismatched @code{end} statements,\nor, if you have not used the more specific @code{end} statements\n(@code{endif}, @code{endfor}, etc.), it may simply produce incorrect\nresults, without producing any warning messages.\n\nIt is much easier to see the error if we rewrite the statements above\nlike this,\n\n@example\n@group\nif (@var{c1})\n  @var{body-1}\nelse\n  if (@var{c2})\n    @var{body-2}\n  endif\n@end group\n@end example\n\n@noindent\nusing the indentation to show how Octave groups the statements.\n@xref{Functions and Scripts}.\n\n@node The switch Statement\n@section The switch Statement\n@cindex @code{switch} statement\n@cindex @code{case} statement\n@cindex @code{otherwise} statement\n@cindex @code{endswitch} statement\n\nIt is very common to take different actions depending on the value of\none variable.  This is possible using the @code{if} statement in the\nfollowing way\n\n@example\n@group\nif (X == 1)\n  do_something ();\nelseif (X == 2)\n  do_something_else ();\nelse\n  do_something_completely_different ();\nendif\n@end group\n@end example\n\n@noindent\nThis kind of code can however be very cumbersome to both write and\nmaintain.  To overcome this problem Octave supports the @code{switch}\nstatement.  Using this statement, the above example becomes\n\n@example\n@group\nswitch (X)\n  case 1\n    do_something ();\n  case 2\n    do_something_else ();\n  otherwise\n    do_something_completely_different ();\nendswitch\n@end group\n@end example\n\n@noindent\nThis code makes the repetitive structure of the problem more explicit,\nmaking the code easier to read, and hence maintain.  Also, if the\nvariable @code{X} should change its name, only one line would need\nchanging compared to one line per case when @code{if} statements are\nused.\n\nThe general form of the @code{switch} statement is\n\n@example\n@group\nswitch (@var{expression})\n  case @var{label}\n    @var{command_list}\n  case @var{label}\n    @var{command_list}\n  @dots{}\n\n  otherwise\n    @var{command_list}\nendswitch\n@end group\n@end example\n\n@noindent\nwhere @var{label} can be any expression.  However, duplicate\n@var{label} values are not detected, and only the @var{command_list}\ncorresponding to the first match will be executed.  For the\n@code{switch} statement to be meaningful at least one\n@code{case @var{label} @var{command_list}} clause must be present,\nwhile the @code{otherwise @var{command_list}} clause is optional.\n\nIf @var{label} is a cell array the corresponding @var{command_list}\nis executed if @emph{any} of the elements of the cell array match\n@var{expression}.  As an example, the following program will print\n@samp{Variable is either 6 or 7}.\n\n@example\n@group\nA = 7;\nswitch (A)\n  case @{ 6, 7 @}\n    printf (\"variable is either 6 or 7\\n\");\n  otherwise\n    printf (\"variable is neither 6 nor 7\\n\");\nendswitch\n@end group\n@end example\n\nAs with all other specific @code{end} keywords, @code{endswitch} may be\nreplaced by @code{end}, but you can get better diagnostics if you use\nthe specific forms.\n\n@c Strings can be matched\n\nOne advantage of using the @code{switch} statement compared to using\n@code{if} statements is that the @var{label}s can be strings.  If an\n@code{if} statement is used it is @emph{not} possible to write\n\n@example\nif (X == \"a string\") # This is NOT valid\n@end example\n\n@noindent\nsince a character-to-character comparison between @code{X} and the\nstring will be made instead of evaluating if the strings are equal.\nThis special-case is handled by the @code{switch} statement, and it\nis possible to write programs that look like this\n\n@example\n@group\nswitch (X)\n  case \"a string\"\n    do_something\n  @dots{}\nendswitch\n@end group\n@end example\n\n@menu\n* Notes for the C Programmer::\n@end menu\n\n@node Notes for the C Programmer\n@subsection Notes for the C Programmer\n\nThe @code{switch} statement is also available in the widely used C\nprogramming language.  There are, however, some differences\nbetween the statement in Octave and C\n\n@itemize @bullet\n@item\nCases are exclusive, so they don't `fall through' as do the cases\nin the @code{switch} statement of the C language.\n\n@item\nThe @var{command_list} elements are not optional.  Making the list\noptional would have meant requiring a separator between the label and\nthe command list.  Otherwise, things like\n\n@example\n@group\nswitch (foo)\n  case (1) -2\n  @dots{}\n@end group\n@end example\n\n@noindent\nwould produce surprising results, as would\n\n@example\n@group\nswitch (foo)\n  case (1)\n  case (2)\n    doit ();\n  @dots{}\n@end group\n@end example\n\n@noindent\nparticularly for C programmers.  If @code{doit()} should be executed if\n@var{foo} is either @code{1} or @code{2}, the above code should be\nwritten with a cell array like this\n\n@example\n@group\nswitch (foo)\n  case @{ 1, 2 @}\n    doit ();\n  @dots{}\n@end group\n@end example\n\n@end itemize\n\n@node The while Statement\n@section The while Statement\n@cindex @code{while} statement\n@cindex @code{endwhile} statement\n@cindex loop\n@cindex body of a loop\n\nIn programming, a @dfn{loop} means a part of a program that is (or at least can\nbe) executed two or more times in succession.\n\nThe @code{while} statement is the simplest looping statement in Octave.\nIt repeatedly executes a statement as long as a condition is true.  As\nwith the condition in an @code{if} statement, the condition in a\n@code{while} statement is considered true if its value is nonzero, and\nfalse if its value is zero.  If the value of the conditional expression\nin a @code{while} statement is a vector or a matrix, it is considered\ntrue only if it is non-empty and @emph{all} of the elements are nonzero.\n\nOctave's @code{while} statement looks like this:\n\n@example\n@group\nwhile (@var{condition})\n  @var{body}\nendwhile\n@end group\n@end example\n\n@noindent\nHere @var{body} is a statement or list of statements that we call the\n@dfn{body} of the loop, and @var{condition} is an expression that\ncontrols how long the loop keeps running.\n\nThe first thing the @code{while} statement does is test @var{condition}.\nIf @var{condition} is true, it executes the statement @var{body}.  After\n@var{body} has been executed, @var{condition} is tested again, and if it\nis still true, @var{body} is executed again.  This process repeats until\n@var{condition} is no longer true.  If @var{condition} is initially\nfalse, the body of the loop is never executed.\n\nThis example creates a variable @code{fib} that contains the first ten\nelements of the Fibonacci sequence.\n\n@example\n@group\nfib = ones (1, 10);\ni = 3;\nwhile (i <= 10)\n  fib (i) = fib (i-1) + fib (i-2);\n  i++;\nendwhile\n@end group\n@end example\n\n@noindent\nHere the body of the loop contains two statements.\n\nThe loop works like this: first, the value of @code{i} is set to 3.\nThen, the @code{while} tests whether @code{i} is less than or equal to\n10.  This is the case when @code{i} equals 3, so the value of the\n@code{i}-th element of @code{fib} is set to the sum of the previous two\nvalues in the sequence.  Then the @code{i++} increments the value of\n@code{i} and the loop repeats.  The loop terminates when @code{i}\nreaches 11.\n\nA newline is not required between the condition and the\nbody; but using one makes the program clearer unless the body is very\nsimple.\n\n@node The do-until Statement\n@section The do-until Statement\n@cindex @code{do-until} statement\n\nThe @code{do-until} statement is similar to the @code{while} statement,\nexcept that it repeatedly executes a statement until a condition becomes\ntrue, and the test of the condition is at the end of the loop, so the\nbody of the loop is always executed at least once.  As with the\ncondition in an @code{if} statement, the condition in a @code{do-until}\nstatement is considered true if its value is nonzero, and false if its\nvalue is zero.  If the value of the conditional expression in a\n@code{do-until} statement is a vector or a matrix, it is considered\ntrue only if it is non-empty and @emph{all} of the elements are nonzero.\n\nOctave's @code{do-until} statement looks like this:\n\n@example\n@group\ndo\n  @var{body}\nuntil (@var{condition})\n@end group\n@end example\n\n@noindent\nHere @var{body} is a statement or list of statements that we call the\n@dfn{body} of the loop, and @var{condition} is an expression that\ncontrols how long the loop keeps running.\n\nThis example creates a variable @code{fib} that contains the first ten\nelements of the Fibonacci sequence.\n\n@example\n@group\nfib = ones (1, 10);\ni = 2;\ndo\n  i++;\n  fib (i) = fib (i-1) + fib (i-2);\nuntil (i == 10)\n@end group\n@end example\n\nA newline is not required between the @code{do} keyword and the\nbody; but using one makes the program clearer unless the body is very\nsimple.\n\n@node The for Statement\n@section The for Statement\n@cindex @code{for} statement\n@cindex @code{endfor} statement\n\nThe @code{for} statement makes it more convenient to count iterations of a\nloop.  The general form of the @code{for} statement looks like this:\n\n@example\n@group\nfor @var{var} = @var{expression}\n  @var{body}\nendfor\n@end group\n@end example\n\n@noindent\nwhere @var{body} stands for any statement or list of statements,\n@var{expression} is any valid expression, and @var{var} may take several\nforms.  Usually it is a simple variable name or an indexed variable.  If\nthe value of @var{expression} is a structure, @var{var} may also be a\nvector with two elements.  @xref{Looping Over Structure Elements}, below.\n\nThe assignment expression in the @code{for} statement works a bit\ndifferently than Octave's normal assignment statement.  Instead of\nassigning the complete result of the expression, it assigns each column\nof the expression to @var{var} in turn.  If @var{expression} is a range,\na row vector, or a scalar, the value of @var{var} will be a scalar each\ntime the loop body is executed.  If @var{var} is a column vector or a\nmatrix, @var{var} will be a column vector each time the loop body is\nexecuted.\n\nThe following example shows another way to create a vector containing\nthe first ten elements of the Fibonacci sequence, this time using the\n@code{for} statement:\n\n@example\n@group\nfib = ones (1, 10);\nfor i = 3:10\n  fib(i) = fib(i-1) + fib(i-2);\nendfor\n@end group\n@end example\n\n@noindent\nThis code works by first evaluating the expression @code{3:10}, to\nproduce a range of values from 3 to 10 inclusive.  Then the variable\n@code{i} is assigned the first element of the range and the body of the\nloop is executed once.  When the end of the loop body is reached, the\nnext value in the range is assigned to the variable @code{i}, and the\nloop body is executed again.  This process continues until there are no\nmore elements to assign.\n\nWithin Octave is it also possible to iterate over matrices or cell arrays\nusing the @code{for} statement.  For example consider\n\n@example\n@group\ndisp (\"Loop over a matrix\")\nfor i = [1,3;2,4]\n  i\nendfor\ndisp (\"Loop over a cell array\")\nfor i = @{1,\"two\";\"three\",4@}\n  i\nendfor\n@end group\n@end example\n\n@noindent\nIn this case the variable @code{i} takes on the value of the columns of\nthe matrix or cell matrix.  So the first loop iterates twice, producing\ntwo column vectors @code{[1;2]}, followed by @code{[3;4]}, and likewise\nfor the loop over the cell array.  This can be extended to loops over\nmulti-dimensional arrays.  For example:\n\n@example\n@group\na = [1,3;2,4]; c = cat (3, a, 2*a);\nfor i = c\n  i\nendfor\n@end group\n@end example\n\n@noindent\nIn the above case, the multi-dimensional matrix @var{c} is reshaped to a\ntwo-dimensional matrix as @code{reshape (c, rows (c), prod (size (c)(2:end)))}\nand then the same behavior as a loop over a two-dimensional matrix is produced.\n\nAlthough it is possible to rewrite all @code{for} loops as @code{while}\nloops, the Octave language has both statements because often a\n@code{for} loop is both less work to type and more natural to think of.\nCounting the number of iterations is very common in loops and it can be\neasier to think of this counting as part of looping rather than as\nsomething to do inside the loop.\n\n@menu\n* Looping Over Structure Elements::\n@end menu\n\n@node Looping Over Structure Elements\n@subsection Looping Over Structure Elements\n@cindex structure elements, looping over\n@cindex looping over structure elements\n\nA special form of the @code{for} statement allows you to loop over all\nthe elements of a structure:\n\n@example\n@group\nfor [ @var{val}, @var{key} ] = @var{expression}\n  @var{body}\nendfor\n@end group\n@end example\n\n@noindent\nIn this form of the @code{for} statement, the value of @var{expression}\nmust be a structure.  If it is, @var{key} and @var{val} are set to the\nname of the element and the corresponding value in turn, until there are\nno more elements.  For example:\n\n@example\n@group\nx.a = 1\nx.b = [1, 2; 3, 4]\nx.c = \"string\"\nfor [val, key] = x\n  key\n  val\nendfor\n\n     @print{} key = a\n     @print{} val = 1\n     @print{} key = b\n     @print{} val =\n     @print{}\n     @print{}   1  2\n     @print{}   3  4\n     @print{}\n     @print{} key = c\n     @print{} val = string\n@end group\n@end example\n\nThe elements are not accessed in any particular order.  If you need to\ncycle through the list in a particular way, you will have to use the\nfunction @code{fieldnames} and sort the list yourself.\n\n@node The break Statement\n@section The break Statement\n@cindex @code{break} statement\n\nThe @code{break} statement jumps out of the innermost @code{while},\n@code{do-until}, or @code{for} loop that encloses it.  The @code{break}\nstatement may only be used within the body of a loop.  The following\nexample finds the smallest divisor of a given integer, and also\nidentifies prime numbers:\n\n@example\n@group\nnum = 103;\ndiv = 2;\nwhile (div*div <= num)\n  if (rem (num, div) == 0)\n    break;\n  endif\n  div++;\nendwhile\nif (rem (num, div) == 0)\n  printf (\"Smallest divisor of %d is %d\\n\", num, div)\nelse\n  printf (\"%d is prime\\n\", num);\nendif\n@end group\n@end example\n\nWhen the remainder is zero in the first @code{while} statement, Octave\nimmediately @dfn{breaks out} of the loop.  This means that Octave\nproceeds immediately to the statement following the loop and continues\nprocessing.  (This is very different from the @code{exit} statement\nwhich stops the entire Octave program.)\n\nHere is another program equivalent to the previous one.  It illustrates\nhow the @var{condition} of a @code{while} statement could just as well\nbe replaced with a @code{break} inside an @code{if}:\n\n@example\n@group\nnum = 103;\ndiv = 2;\nwhile (1)\n  if (rem (num, div) == 0)\n    printf (\"Smallest divisor of %d is %d\\n\", num, div);\n    break;\n  endif\n  div++;\n  if (div*div > num)\n    printf (\"%d is prime\\n\", num);\n    break;\n  endif\nendwhile\n@end group\n@end example\n\n@node The continue Statement\n@section The continue Statement\n@cindex @code{continue} statement\n\nThe @code{continue} statement, like @code{break}, is used only inside\n@code{while}, @code{do-until}, or @code{for} loops.  It skips over the\nrest of the loop body, causing the next cycle around the loop to begin\nimmediately.  Contrast this with @code{break}, which jumps out of the\nloop altogether.\nHere is an example:\n\n@example\n@group\n# print elements of a vector of random\n# integers that are even.\n\n# first, create a row vector of 10 random\n# integers with values between 0 and 100:\n\nvec = round (rand (1, 10) * 100);\n\n# print what we're interested in:\n\nfor x = vec\n  if (rem (x, 2) != 0)\n    continue;\n  endif\n  printf (\"%d\\n\", x);\nendfor\n@end group\n@end example\n\nIf one of the elements of @var{vec} is an odd number, this example skips\nthe print statement for that element, and continues back to the first\nstatement in the loop.\n\nThis is not a practical example of the @code{continue} statement, but it\nshould give you a clear understanding of how it works.  Normally, one\nwould probably write the loop like this:\n\n@example\n@group\nfor x = vec\n  if (rem (x, 2) == 0)\n    printf (\"%d\\n\", x);\n  endif\nendfor\n@end group\n@end example\n\n@node The unwind_protect Statement\n@section The unwind_protect Statement\n@cindex @code{unwind_protect} statement\n@cindex @code{unwind_protect_cleanup}\n@cindex @code{end_unwind_protect}\n\nOctave supports a limited form of exception handling modeled after the\nunwind-protect form of Lisp.\n\nThe general form of an @code{unwind_protect} block looks like this:\n\n@example\n@group\nunwind_protect\n  @var{body}\nunwind_protect_cleanup\n  @var{cleanup}\nend_unwind_protect\n@end group\n@end example\n\n@noindent\nwhere @var{body} and @var{cleanup} are both optional and may contain any\nOctave expressions or commands.  The statements in @var{cleanup} are\nguaranteed to be executed regardless of how control exits @var{body}.\n\nThis is useful to protect temporary changes to global variables from\npossible errors.  For example, the following code will always restore\nthe original value of the global variable @code{frobnosticate}\neven if an error occurs in the first part of the @code{unwind_protect}\nblock.\n\n@example\n@group\nsave_frobnosticate = frobnosticate;\nunwind_protect\n  frobnosticate = true;\n  @dots{}\nunwind_protect_cleanup\n  frobnosticate = save_frobnosticate;\nend_unwind_protect\n@end group\n@end example\n\n@noindent\nWithout @code{unwind_protect}, the value of @var{frobnosticate}\nwould not be restored if an error occurs while evaluating the first part\nof the @code{unwind_protect} block because evaluation would stop at the\npoint of the error and the statement to restore the value would not be\nexecuted.\n\nIn addition to unwind_protect, Octave supports another form of\nexception handling, the @code{try} block.\n\n\n@node The try Statement\n@section The try Statement\n@cindex @code{try} statement\n@cindex @code{catch}\n@cindex @code{end_try_catch}\n\nThe original form of a @code{try} block looks like this:\n\n@example\n@group\ntry\n  @var{body}\ncatch\n  @var{cleanup}\nend_try_catch\n@end group\n@end example\n\n@noindent\nwhere @var{body} and @var{cleanup} are both optional and may contain any\nOctave expressions or commands.  The statements in @var{cleanup} are\nonly executed if an error occurs in @var{body}.\n\nNo warnings or error messages are printed while @var{body} is executing.\nIf an error does occur during the execution of @var{body}, @var{cleanup}\ncan use the functions @code{lasterr} or @code{lasterror} to access the\ntext of the message that would have been printed, as well as its\nidentifier.  The alternative form,\n\n@example\n@group\ntry\n  @var{body}\ncatch @var{err}\n  @var{cleanup}\nend_try_catch\n@end group\n@end example\n\n@noindent\nwill automatically store the output of @code{lasterror} in the structure\n@var{err}.  @xref{Errors and Warnings}, for more information about the\n@code{lasterr} and @code{lasterror} functions.\n\n\n@node Continuation Lines\n@section Continuation Lines\n@cindex continuation lines\n\n@opindex @code{...} continuation marker\nIn the Octave language, most statements end with a newline character and\nyou must tell Octave to ignore the newline character in order to\ncontinue a statement from one line to the next.  Lines that end with the\ncharacters @code{...} are joined with the following line before they are\ndivided into tokens by Octave's parser.  For example, the lines\n\n@example\n@group\nx = long_variable_name ...\n    + longer_variable_name ...\n    - 42\n@end group\n@end example\n\n@noindent\nform a single statement.\n\nAny text between the continuation marker and the newline character is\nignored.  For example, the statement\n\n@example\n@group\nx = long_variable_name ...    # comment one\n    + longer_variable_name ...comment two\n    - 42                      # last comment\n@end group\n@end example\n\n@noindent\nis equivalent to the one shown above.\n\n@opindex @code{\\} continuation marker\nInside double-quoted string constants, the character @code{\\} has to be\nused as continuation marker.  The @code{\\} must appear at the end of the\nline just before the newline character:\n\n@example\n@group\ns = \"This text starts in the first line \\\nand is continued in the second line.\"\n@end group\n@end example\n\n@noindent\nInput that occurs inside parentheses can be continued to the next line\nwithout having to use a continuation marker.  For example, it is\npossible to write statements like\n\n@example\n@group\nif (fine_dining_destination == on_a_boat\n    || fine_dining_destination == on_a_train)\n  seuss (i, will, not, eat, them, sam, i, am, i,\n         will, not, eat, green, eggs, and, ham);\nendif\n@end group\n@end example\n\n@noindent\nwithout having to add to the clutter with continuation markers.\n"
  },
  {
    "path": "doc/interpreter/strings.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Strings\n@chapter Strings\n@cindex strings\n@cindex character strings\n@opindex \"\n@opindex @code{'}\n\nA @dfn{string constant} consists of a sequence of characters enclosed in\neither double-quote or single-quote marks.  For example, both of the\nfollowing expressions\n\n@example\n@group\n\"parrot\"\n'parrot'\n@end group\n@end example\n\n@noindent\nrepresent the string whose contents are @samp{parrot}.  Strings in\nOctave can be of any length.\n\nSince the single-quote mark is also used for the transpose operator\n(@pxref{Arithmetic Ops}) but double-quote marks have no other purpose in\nOctave, it is best to use double-quote marks to denote strings.\n\nStrings can be concatenated using the notation for defining matrices.  For\nexample, the expression\n\n@example\n[ \"foo\" , \"bar\" , \"baz\" ]\n@end example\n\n@noindent\nproduces the string whose contents are @samp{foobarbaz}.\n@xref{Numeric Data Types}, for more information about creating matrices.\n\nWhile strings can in principle store arbitrary content, most functions expect\nthem to be UTF-8 encoded Unicode strings.\n\nFurthermore, it is possible to create a string without actually writing a text.\nThe function @code{blanks} creates a string of a given length consisting only\nof blank characters (ASCII code 32).\n\n@DOCSTRING(blanks)\n\n@menu\n* Escape Sequences in String Constants::\n* Character Arrays::\n* String Operations::\n* Converting Strings::\n* Character Class Functions::\n@end menu\n\n@node Escape Sequences in String Constants\n@section Escape Sequences in String Constants\n@cindex escape sequence notation\nIn double-quoted strings, the backslash character is used to introduce\n@dfn{escape sequences} that represent other characters.  For example,\n@samp{\\n} embeds a newline character in a double-quoted string and\n@samp{\\\"} embeds a double quote character.  In single-quoted strings, backslash\nis not a special character.  Here is an example showing the difference:\n\n@example\n@group\ndouble (\"\\n\")\n    @xresult{} 10\ndouble ('\\n')\n    @xresult{} [ 92 110 ]\n@end group\n@end example\n\nHere is a table of all the escape sequences used in Octave (within\ndouble quoted strings).  They are the same as those used in the C\nprogramming language.\n\n@table @code\n@item \\\\\nRepresents a literal backslash, @samp{\\}.\n\n@item \\\"\nRepresents a literal double-quote character, @samp{\"}.\n\n@item \\'\nRepresents a literal single-quote character, @samp{'}.\n\n@item \\0\nRepresents the null character, control-@@, ASCII code 0.\n\n@item \\a\nRepresents the ``alert'' character, control-g, ASCII code 7.\n\n@item \\b\nRepresents a backspace, control-h, ASCII code 8.\n\n@item \\f\nRepresents a formfeed, control-l, ASCII code 12.\n\n@item \\n\nRepresents a newline, control-j, ASCII code 10.\n\n@item \\r\nRepresents a carriage return, control-m, ASCII code 13.\n\n@item \\t\nRepresents a horizontal tab, control-i, ASCII code 9.\n\n@item \\v\nRepresents a vertical tab, control-k, ASCII code 11.\n\n@item \\@var{nnn}\nRepresents the octal value @var{nnn}, where @var{nnn} are one to three\ndigits between 0 and 7.  For example, the code for the ASCII ESC\n(escape) character is @samp{\\033}.\n\n@item \\x@var{hh}@dots{}\nRepresents the hexadecimal value @var{hh}, where @var{hh} are hexadecimal\ndigits (@samp{0} through @samp{9} and either @samp{A} through @samp{F} or\n@samp{a} through @samp{f}).  Like the same construct in @sc{ansi} C,\nthe escape sequence continues until the first non-hexadecimal digit is seen.\nHowever, using more than two hexadecimal digits produces undefined results.\n@end table\n\nIn a single-quoted string there is only one escape sequence: you may insert a\nsingle quote character using two single quote characters in succession.  For\nexample,\n\n@example\n@group\n'I can''t escape'\n    @xresult{} I can't escape\n@end group\n@end example\n\nIn scripts the two different string types can be distinguished if necessary\nby using @code{is_dq_string} and @code{is_sq_string}.\n\n@DOCSTRING(is_dq_string)\n\n@DOCSTRING(is_sq_string)\n\n@node Character Arrays\n@section Character Arrays\n\nThe string representation used by Octave is an array of characters, so\ninternally the string @nospell{@qcode{\"dddddddddd\"}} is actually a row vector\nof length 10 containing the value 100 in all places (100 is the ASCII code of\n@qcode{\"d\"}).  This lends itself to the obvious generalization to character\nmatrices.  Using a matrix of characters, it is possible to represent a\ncollection of same-length strings in one variable.  The convention used in\nOctave is that each row in a character matrix is a separate string, but letting\neach column represent a string is equally possible.\n\nThe easiest way to create a character matrix is to put several strings\ntogether into a matrix.\n\n@example\ncollection = [ \"String #1\"; \"String #2\" ];\n@end example\n\n@noindent\nThis creates a 2-by-9 character matrix.\n\nThe function @code{ischar} can be used to test if an object is a character\nmatrix.\n\n@DOCSTRING(ischar)\n\n@DOCSTRING(isstring)\n\nTo test if an object is a string (i.e., a @nospell{1xN} row vector of\ncharacters and not a character matrix) you can use the @code{ischar} function\nin combination with the @code{isrow} function as in the following example:\n\n@example\n@group\nischar (collection)\n     @xresult{} 1\n\nischar (collection) && isrow (collection)\n     @xresult{} 0\n\nischar (\"my string\") && isrow (\"my string\")\n     @xresult{} 1\n@end group\n@end example\n\nOne relevant question is, what happens when a character matrix is\ncreated from strings of different length.  The answer is that Octave\nputs blank characters at the end of strings shorter than the longest\nstring.  It is possible to use a different character than the\nblank character using the @code{string_fill_char} function.\n\n@DOCSTRING(string_fill_char)\n\nAnother useful function to control the text justification in this case is\nthe @code{strjust} function.\n\n@DOCSTRING(strjust)\n\nThis shows a problem with character matrices.  It simply isn't possible to\nrepresent strings of different lengths.  The solution is to use a cell array of\nstrings, which is described in @ref{Cell Arrays of Strings}.\n\n@node String Operations\n@section String Operations\n\nOctave supports a wide range of functions for manipulating strings.\nSince a string is just a matrix, simple manipulations can be accomplished\nusing standard operators.  The following example shows how to replace\nall blank characters with underscores.\n\n@example\n@group\nquote = ...\n  \"First things first, but not necessarily in that order\";\nquote( quote == \" \" ) = \"_\"\n@xresult{} quote =\n    First_things_first,_but_not_necessarily_in_that_order\n@end group\n@end example\n\nFor more complex manipulations, such as searching, replacing, and\ngeneral regular expressions, the following functions come with Octave.\n\n@menu\n* Common String Operations::\n* Concatenating Strings::\n* Splitting and Joining Strings::\n* Searching in Strings::\n* Searching and Replacing in Strings::\n@end menu\n\n@node Common String Operations\n@subsection Common String Operations\n\nThe following functions are useful to perform common String operations.\n\n@DOCSTRING(lower)\n\n@DOCSTRING(upper)\n\n@DOCSTRING(deblank)\n\n@DOCSTRING(strtrim)\n\n@DOCSTRING(strtrunc)\n\n@DOCSTRING(untabify)\n\n@DOCSTRING(do_string_escapes)\n\n@DOCSTRING(undo_string_escapes)\n\n@node Concatenating Strings\n@subsection Concatenating Strings\n\nStrings can be concatenated using matrix notation\n(@pxref{Strings}, @ref{Character Arrays}) which is often the most natural\nmethod.  For example:\n\n@example\n@group\nfullname = [fname \".txt\"];\nemail = [\"<\" user \"@@\" domain \">\"];\n@end group\n@end example\n\n@noindent\nIn each case it is easy to see what the final string will look like.  This\nmethod is also the most efficient.  When using matrix concatenation the parser\nimmediately begins joining the strings without having to process\nthe overhead of a function call and the input validation of the associated\nfunction.\n\nThe @code{newline} function can be used to join strings such that they appear\nas multiple lines of text when displayed.\n\n@DOCSTRING(newline)\n\nIn addition, there are several other functions for concatenating string\nobjects which can be useful in specific circumstances: @code{char},\n@code{strvcat}, @code{strcat}, and @code{cstrcat}.  Finally, the general\npurpose concatenation functions can be used: see @ref{XREFcat,,cat},\n@ref{XREFhorzcat,,horzcat}, and @ref{XREFvertcat,,vertcat}.\n\n@itemize @bullet\n@item All string concatenation functions except @code{cstrcat}\nconvert numerical input into character data by taking the corresponding UTF-8\ncharacter for each element (or multi-byte sequence), as in the following\nexample:\n\n@example\n@group\nchar ([98, 97, 110, 97, 110, 97])\n   @xresult{} banana\n@end group\n@end example\n\nFor conversion between locale encodings and UTF-8, see\n@ref{XREFunicode2native,,unicode2native} and\n@ref{XREFnative2unicode,,native2unicode}.\n\n@item\n@code{char} and @code{strvcat}\nconcatenate vertically, while @code{strcat} and @code{cstrcat} concatenate\nhorizontally.  For example:\n\n@example\n@group\nchar (\"an apple\", \"two pears\")\n    @xresult{} an apple\n       two pears\n@end group\n\n@group\nstrcat (\"oc\", \"tave\", \" is\", \" good\", \" for you\")\n     @xresult{} octave is good for you\n@end group\n@end example\n\n@item @code{char} generates an empty row in the output\nfor each empty string in the input.  @code{strvcat}, on the other hand,\neliminates empty strings.\n\n@example\n@group\nchar (\"orange\", \"green\", \"\", \"red\")\n    @xresult{} orange\n       green\n\n       red\n@end group\n\n@group\nstrvcat (\"orange\", \"green\", \"\", \"red\")\n    @xresult{} orange\n       green\n       red\n@end group\n@end example\n\n@item All string concatenation functions except @code{cstrcat} also accept cell\narray data (@pxref{Cell Arrays}).  @code{char} and\n@code{strvcat} convert cell arrays into character arrays, while @code{strcat}\nconcatenates within the cells of the cell arrays:\n\n@example\n@group\nchar (@{\"red\", \"green\", \"\", \"blue\"@})\n     @xresult{} red\n        green\n\n        blue\n@end group\n\n@group\nstrcat (@{\"abc\"; \"ghi\"@}, @{\"def\"; \"jkl\"@})\n     @xresult{}\n        @{\n          [1,1] = abcdef\n          [2,1] = ghijkl\n        @}\n@end group\n@end example\n\n@item @code{strcat} removes trailing white space in the arguments (except\nwithin cell arrays), while @code{cstrcat} leaves white space untouched.  Both\nkinds of behavior can be useful as can be seen in the examples:\n\n@example\n@group\nstrcat ([\"dir1\";\"directory2\"], [\"/\";\"/\"], [\"file1\";\"file2\"])\n     @xresult{} dir1/file1\n        directory2/file2\n@end group\n@group\n\ncstrcat ([\"thirteen apples\"; \"a banana\"], [\" 5$\";\" 1$\"])\n      @xresult{} thirteen apples 5$\n         a banana        1$\n@end group\n@end example\n\nNote that in the above example for @code{cstrcat}, the white space originates\nfrom the internal representation of the strings in a string array\n(@pxref{Character Arrays}).\n@end itemize\n\n@DOCSTRING(char)\n\n@DOCSTRING(strvcat)\n\n@DOCSTRING(strcat)\n\n@DOCSTRING(cstrcat)\n\n@node Splitting and Joining Strings\n@subsection Splitting and Joining Strings\n\n@DOCSTRING(substr)\n\n@DOCSTRING(strtok)\n\n@DOCSTRING(strsplit)\n\n@DOCSTRING(ostrsplit)\n\n@DOCSTRING(strjoin)\n\n@node Searching in Strings\n@subsection Searching in Strings\n\nSince a string is a character array, comparisons between strings work\nelement by element as the following example shows:\n\n@example\n@group\nGNU = \"GNU's Not UNIX\";\nspaces = (GNU == \" \")\n     @xresult{} spaces =\n       0   0   0   0   0   1   0   0   0   1   0   0   0   0\n@end group\n@end example\n\n@noindent To determine if two strings are identical it is necessary to use the\n@code{strcmp} function.  It compares complete strings and is case\nsensitive.  @code{strncmp} compares only the first @code{N} characters (with\n@code{N} given as a parameter).  @code{strcmpi} and @code{strncmpi} are the\ncorresponding functions for case-insensitive comparison.\n\n@DOCSTRING(strcmp)\n\n@DOCSTRING(strncmp)\n\n@DOCSTRING(strcmpi)\n\n@DOCSTRING(strncmpi)\n\nDespite those comparison functions, there are more specialized function to\nfind the index position of a search pattern within a string.\n\n@DOCSTRING(startsWith)\n\n@DOCSTRING(endsWith)\n\n@DOCSTRING(findstr)\n\n@DOCSTRING(strchr)\n\n@DOCSTRING(index)\n\n@DOCSTRING(rindex)\n\n@DOCSTRING(unicode_idx)\n\n@DOCSTRING(strfind)\n\n@DOCSTRING(strmatch)\n\n@node Searching and Replacing in Strings\n@subsection Searching and Replacing in Strings\n\n@DOCSTRING(strrep)\n\n@DOCSTRING(erase)\n\n@DOCSTRING(regexp)\n\n@DOCSTRING(regexpi)\n\n@DOCSTRING(regexprep)\n\n@DOCSTRING(regexptranslate)\n\n@node Converting Strings\n@section Converting Strings\n\nOctave offers several kinds of conversion functions for Strings.\n\n@menu\n* String encoding::\n* Numerical Data and Strings::\n* JSON data encoding/decoding::\n@end menu\n\n@node String encoding\n@subsection String encoding\n\n@DOCSTRING(unicode2native)\n\n@DOCSTRING(native2unicode)\n\n@node Numerical Data and Strings\n@subsection Numerical Data and Strings\n\nApart from the string concatenation functions (@pxref{Concatenating Strings})\nwhich cast numerical data to the corresponding UTF-8 encoded characters, there\nare several functions that format numerical data as strings.  @code{mat2str}\nand @code{num2str} convert real or complex matrices, while @code{int2str}\nconverts integer matrices.  @code{int2str} takes the real part of complex\nvalues and round fractional values to integer.  A more flexible way to format\nnumerical data as strings is the @code{sprintf} function\n(@pxref{Formatted Output}, @ref{XREFsprintf,,sprintf}).\n\n@DOCSTRING(mat2str)\n\n@DOCSTRING(num2str)\n\n@DOCSTRING(int2str)\n\n@DOCSTRING(str2double)\n\n@DOCSTRING(str2num)\n\n@DOCSTRING(bin2dec)\n\n@DOCSTRING(dec2bin)\n\n@DOCSTRING(dec2hex)\n\n@DOCSTRING(hex2dec)\n\n@DOCSTRING(dec2base)\n\n@DOCSTRING(base2dec)\n\n@DOCSTRING(num2hex)\n\n@DOCSTRING(hex2num)\n\n@DOCSTRING(strread)\n\n@node JSON data encoding/decoding\n@subsection JSON data encoding/decoding\n\nJavaScript Object Notation, in short JSON, is a very common human readable\nand structured data format.  GNU Octave supports encoding and decoding this\nformat with the following two functions.\n\n@DOCSTRING(jsonencode)\n\n@DOCSTRING(jsondecode)\n\n@node Character Class Functions\n@section Character Class Functions\n\nOctave also provides the following character class test functions\npatterned after the functions in the standard C library.  They all\noperate on string arrays and return matrices of zeros and ones.\nElements that are nonzero indicate that the condition was true for the\ncorresponding character in the string array.  For example:\n\n@example\n@group\nisalpha (\"!Q@@WERT^Y&\")\n     @xresult{} [ 0, 1, 0, 1, 1, 1, 1, 0, 1, 0 ]\n@end group\n@end example\n\n@DOCSTRING(isalnum)\n\n@DOCSTRING(isalpha)\n\n@DOCSTRING(isletter)\n\n@DOCSTRING(islower)\n\n@DOCSTRING(isupper)\n\n@DOCSTRING(isdigit)\n\n@DOCSTRING(isxdigit)\n\n@DOCSTRING(ispunct)\n\n@DOCSTRING(isspace)\n\n@DOCSTRING(iscntrl)\n\n@DOCSTRING(isgraph)\n\n@DOCSTRING(isprint)\n\n@DOCSTRING(isascii)\n\n@DOCSTRING(isstrprop)\n"
  },
  {
    "path": "doc/interpreter/system.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node System Utilities\n@chapter System Utilities\n\nThis chapter describes the functions that are available to allow you to\nget information about what is happening outside of Octave, while it is\nstill running, and use this information in your program.  For example,\nyou can get information about environment variables, the current time,\nand even start other programs from the Octave prompt.\n\n@menu\n* Timing Utilities::\n* Filesystem Utilities::\n* File Archiving Utilities::\n* Networking Utilities::\n* Controlling Subprocesses::\n* Process ID Information::\n* Environment Variables::\n* Current Working Directory::\n* Password Database Functions::\n* Group Database Functions::\n* System Information::\n* Hashing Functions::\n@end menu\n\n@node Timing Utilities\n@section Timing Utilities\n\nOctave's core set of functions for manipulating time values are\npatterned after the corresponding functions from the standard C library.\nSeveral of these functions use a data structure for time that includes\nthe following elements:\n\n@table @code\n@item usec\nMicroseconds after the second (0-999999).\n\n@item sec\nSeconds after the minute (0-60).  This number can be 60 to account\nfor leap seconds.\n\n@item min\nMinutes after the hour (0-59).\n\n@item hour\nHours since midnight (0-23).\n\n@item mday\nDay of the month (1-31).\n\n@item mon\nMonths since January (0-11).\n\n@item year\nYears since 1900.\n\n@item wday\nDays since Sunday (0-6).\n\n@item yday\nDays since January 1 (0-365).\n\n@item isdst\nDaylight saving time flag.\n\n@item gmtoff\nSeconds offset from UTC.\n\n@item zone\nTime zone.\n@end table\n\n@noindent\nIn the descriptions of the following functions, this structure is\nreferred to as a @var{tm_struct}.\n\n@DOCSTRING(time)\n\n@DOCSTRING(now)\n\n@DOCSTRING(ctime)\n\n@DOCSTRING(gmtime)\n\n@DOCSTRING(localtime)\n\n@DOCSTRING(mktime)\n\n@DOCSTRING(asctime)\n\n@DOCSTRING(strftime)\n\n@DOCSTRING(strptime)\n\nMost of the remaining functions described in this section are not\npatterned after the standard C library.  Some are available for\ncompatibility with @sc{matlab} and others are provided because they are\nuseful.\n\n@DOCSTRING(clock)\n\n@DOCSTRING(date)\n\n@DOCSTRING(etime)\n\n@DOCSTRING(cputime)\n\n@DOCSTRING(is_leap_year)\n\n@DOCSTRING(tic)\n\n@DOCSTRING(toc)\n\n@DOCSTRING(pause)\n\n@DOCSTRING(datenum)\n\n@DOCSTRING(datestr)\n\n@DOCSTRING(datevec)\n\n@DOCSTRING(addtodate)\n\n@DOCSTRING(calendar)\n\n@DOCSTRING(weekday)\n\n@DOCSTRING(eomday)\n\n@DOCSTRING(datetick)\n\n@node Filesystem Utilities\n@section Filesystem Utilities\n\nOctave includes many utility functions for copying, moving, renaming, and\ndeleting files; for creating, reading, and deleting directories; for retrieving\nstatus information on files; and for manipulating file and path names.\n\n@DOCSTRING(movefile)\n\n@DOCSTRING(rename)\n\n@DOCSTRING(copyfile)\n\n@DOCSTRING(unlink)\n\n@DOCSTRING(link)\n\n@DOCSTRING(symlink)\n\n@DOCSTRING(readlink)\n\n@DOCSTRING(mkdir)\n\n@DOCSTRING(rmdir)\n\n@DOCSTRING(confirm_recursive_rmdir)\n\n@DOCSTRING(mkfifo)\n\n@DOCSTRING(umask)\n\n@anchor{XREFlstat}\n@DOCSTRING(stat)\n\n@DOCSTRING(S_ISBLK)\n\n@DOCSTRING(S_ISCHR)\n\n@DOCSTRING(S_ISDIR)\n\n@DOCSTRING(S_ISFIFO)\n\n@DOCSTRING(S_ISLNK)\n\n@DOCSTRING(S_ISREG)\n\n@DOCSTRING(S_ISSOCK)\n\n@DOCSTRING(fileattrib)\n\n@DOCSTRING(isfile)\n\n@DOCSTRING(isdir)\n\n@DOCSTRING(isfolder)\n\n@DOCSTRING(readdir)\n\n@DOCSTRING(glob)\n\n@DOCSTRING(file_in_path)\n\n@DOCSTRING(filesep)\n\n@DOCSTRING(fileparts)\n\n@DOCSTRING(fullfile)\n\n@DOCSTRING(tilde_expand)\n\n@DOCSTRING(canonicalize_file_name)\n\n@DOCSTRING(make_absolute_filename)\n\n@DOCSTRING(is_absolute_filename)\n\n@DOCSTRING(is_same_file)\n\n@DOCSTRING(is_rooted_relative_filename)\n\n@DOCSTRING(recycle)\n\n@node File Archiving Utilities\n@section File Archiving Utilities\n\n@DOCSTRING(bunzip2)\n\n@DOCSTRING(gzip)\n\n@DOCSTRING(gunzip)\n\n@DOCSTRING(tar)\n\n@DOCSTRING(untar)\n\n@DOCSTRING(zip)\n\n@DOCSTRING(unzip)\n\n@DOCSTRING(unpack)\n\n@DOCSTRING(bzip2)\n\n@node Networking Utilities\n@section Networking Utilities\n\n@menu\n* FTP Objects::\n* WWW Access::\n* Base64 and Binary Data Transmission::\n@end menu\n\n@DOCSTRING(gethostname)\n\n@node FTP Objects\n@subsection FTP Objects\n\nOctave supports the FTP protocol through an object-oriented interface.\nUse the function @code{ftp} to create an FTP object which represents the\nconnection.  All FTP functions take an FTP object as the first argument.\n\n@DOCSTRING(@ftp/ftp)\n\n@DOCSTRING(@ftp/close)\n\n@DOCSTRING(@ftp/mget)\n\n@DOCSTRING(@ftp/mput)\n\n@DOCSTRING(@ftp/cd)\n\n@DOCSTRING(@ftp/dir)\n\n@DOCSTRING(@ftp/ascii)\n\n@DOCSTRING(@ftp/binary)\n\n@DOCSTRING(@ftp/delete)\n\n@DOCSTRING(@ftp/rename)\n\n@DOCSTRING(@ftp/mkdir)\n\n@DOCSTRING(@ftp/rmdir)\n\n@node WWW Access\n@subsection WWW Access\n\nOctave can communicate with websites across the Internet.  The @code{web}\nfunction will launch an external web browser to interactively view a site.  The\nremaining functions---@code{urlread}, @code{urlwrite}, @code{webread},\n@code{webwrite}---are internal Octave functions which can import or export\ndata to/from Octave and a website identified by a URL (Uniform Resource\nLocator).\n\n@DOCSTRING(web)\n\n@DOCSTRING(urlread)\n\n@DOCSTRING(urlwrite)\n\n@DOCSTRING(webread)\n\n@DOCSTRING(webwrite)\n\n@DOCSTRING(weboptions)\n\n@node Base64 and Binary Data Transmission\n@subsection Base64 and Binary Data Transmission\n\nSome transmission channels can not accept binary data.  It is customary to\nencode binary data in Base64 for transmission and to decode the data upon\nreception.\n\n@DOCSTRING(base64_encode)\n\n@DOCSTRING(base64_decode)\n\n@DOCSTRING(matlab.net.base64encode)\n\n@DOCSTRING(matlab.net.base64decode)\n\n@node Controlling Subprocesses\n@section Controlling Subprocesses\n\nOctave includes some high-level commands like @code{system} and\n@code{popen} for starting subprocesses.  If you want to run another\nprogram to perform some task and then look at its output, you will\nprobably want to use these functions.\n\nOctave also provides several very low-level Unix-like functions which\ncan also be used for starting subprocesses, but you should probably only\nuse them if you can't find any way to do what you need with the\nhigher-level functions.\n\n@DOCSTRING(system)\n\n@DOCSTRING(unix)\n\n@DOCSTRING(dos)\n\n@DOCSTRING(open)\n\n@DOCSTRING(perl)\n\n@DOCSTRING(python)\n\n@DOCSTRING(popen)\n\n@DOCSTRING(pclose)\n\n@DOCSTRING(popen2)\n\n@DOCSTRING(EXEC_PATH)\n\nIn most cases, the following functions simply decode their arguments and\nmake the corresponding Unix system calls.  For a complete example of how\nthey can be used, look at the definition of the function @code{popen2}.\n\n@DOCSTRING(fork)\n\n@DOCSTRING(_Exit)\n\n@DOCSTRING(exec)\n\n@DOCSTRING(pipe)\n\n@DOCSTRING(dup2)\n\n@DOCSTRING(waitpid)\n\n@DOCSTRING(WCONTINUE)\n\n@DOCSTRING(WCOREDUMP)\n\n@DOCSTRING(WEXITSTATUS)\n\n@DOCSTRING(WIFCONTINUED)\n\n@DOCSTRING(WIFSIGNALED)\n\n@DOCSTRING(WIFSTOPPED)\n\n@DOCSTRING(WIFEXITED)\n\n@DOCSTRING(WNOHANG)\n\n@DOCSTRING(WSTOPSIG)\n\n@DOCSTRING(WTERMSIG)\n\n@DOCSTRING(WUNTRACED)\n\n@DOCSTRING(fcntl)\n\n@DOCSTRING(kill)\n\n@DOCSTRING(SIG)\n\n@node Process ID Information\n@section Process, Group, and User IDs\n\n@DOCSTRING(getpgrp)\n\n@DOCSTRING(getpid)\n\n@DOCSTRING(getppid)\n\n@DOCSTRING(geteuid)\n\n@DOCSTRING(getuid)\n\n@DOCSTRING(getegid)\n\n@DOCSTRING(getgid)\n\n@node Environment Variables\n@section Environment Variables\n\n@DOCSTRING(getenv)\n\n@DOCSTRING(isenv)\n\n@DOCSTRING(setenv)\n\n@DOCSTRING(unsetenv)\n\n@DOCSTRING(get_home_directory)\n\n@node Current Working Directory\n@section Current Working Directory\n\n@DOCSTRING(cd)\n\n@DOCSTRING(ls)\n\n@DOCSTRING(ls_command)\n\n@DOCSTRING(dir)\n\n@DOCSTRING(pwd)\n\n@node Password Database Functions\n@section Password Database Functions\n\nOctave's password database functions return information in a structure\nwith the following fields.\n\n@table @code\n@item name\nThe user name.\n\n@item passwd\nThe encrypted password, if available.\n\n@item uid\nThe numeric user id.\n\n@item gid\nThe numeric group id.\n\n@item gecos\nThe GECOS field.\n\n@item dir\nThe home directory.\n\n@item shell\nThe initial shell.\n@end table\n\nIn the descriptions of the following functions, this data structure is\nreferred to as a @var{pw_struct}.\n\n@DOCSTRING(getpwent)\n\n@DOCSTRING(getpwuid)\n\n@DOCSTRING(getpwnam)\n\n@DOCSTRING(setpwent)\n\n@DOCSTRING(endpwent)\n\n@node Group Database Functions\n@section Group Database Functions\n\nOctave's group database functions return information in a structure\nwith the following fields.\n\n@table @code\n@item name\nThe user name.\n\n@item passwd\nThe encrypted password, if available.\n\n@item gid\nThe numeric group id.\n\n@item mem\nThe members of the group.\n@end table\n\nIn the descriptions of the following functions, this data structure is\nreferred to as a @var{grp_struct}.\n\n@DOCSTRING(getgrent)\n\n@DOCSTRING(getgrgid)\n\n@DOCSTRING(getgrnam)\n\n@DOCSTRING(setgrent)\n\n@DOCSTRING(endgrent)\n\n@node System Information\n@section System Information\n\n@DOCSTRING(computer)\n\n@DOCSTRING(uname)\n\n@DOCSTRING(nproc)\n\n@DOCSTRING(ispc)\n\n@DOCSTRING(isunix)\n\n@DOCSTRING(ismac)\n\n@DOCSTRING(isieee)\n\n@DOCSTRING(isdeployed)\n\n@DOCSTRING(isstudent)\n\n@DOCSTRING(OCTAVE_HOME)\n\n@DOCSTRING(OCTAVE_EXEC_HOME)\n\n@DOCSTRING(matlabroot)\n\n@DOCSTRING(user_config_dir)\n\n@DOCSTRING(user_data_dir)\n\n@DOCSTRING(OCTAVE_VERSION)\n\n@DOCSTRING(version)\n\n@DOCSTRING(ver)\n\n@DOCSTRING(compare_versions)\n\n@DOCSTRING(verLessThan)\n\n@DOCSTRING(license)\n\n@DOCSTRING(memory)\n\n@DOCSTRING(getrusage)\n\n@DOCSTRING(winqueryreg)\n\n@node Hashing Functions\n@section Hashing Functions\n\nIt is often necessary to find if two strings or files are identical.\nThis might be done by comparing them character by character and looking\nfor differences.  However, this can be slow, and so comparing a hash of\nthe string or file can be a rapid way of finding if the files differ.\n\nAnother use of the hashing function is to check for file integrity.  The\nuser can check the hash of the file against a known value and find if\nthe file they have is the same as the one that the original hash was\nproduced with.\n\nOctave supplies the @code{hash} function to calculate hash values of\nstrings and files, the latter in combination with the @code{fileread}\nfunction.  The @code{hash} function supports many commonly used hash\nmethods.\n\n@DOCSTRING(hash)\n"
  },
  {
    "path": "doc/interpreter/testfun.txi",
    "content": "@c Copyright (C) 2002-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Test and Demo Functions\n@appendix Test and Demo Functions\n@cindex test functions\n\nOctave includes a number of functions to allow the integration of testing\nand demonstration code in the source code of the functions themselves.\n\n@menu\n* Test Functions::\n* Demonstration Functions::\n@end menu\n\n@node Test Functions\n@section Test Functions\n\n@DOCSTRING(test)\n\n@code{test} scans the named script file looking for lines which start\nwith the identifier @samp{%!}.  The prefix is stripped off and the rest\nof the line is processed through the Octave interpreter.  If the code\ngenerates an error, then the test is said to fail.\n\nSince @code{eval()} will stop at the first error it encounters, you must\ndivide your tests up into blocks, with anything in a separate\nblock evaluated separately.  Blocks are introduced by valid keywords like\n@code{test}, @code{function}, or @code{assert} immediately following @samp{%!}.\nA block is defined by indentation as in Python.  Lines beginning with\n@samp{%!<whitespace>} are part of the preceding block.\n\nFor example:\n\n@example\n@group\n%!test error (\"this test fails!\")\n%!test \"test doesn't fail.  it doesn't generate an error\"\n@end group\n@end example\n\nWhen a test fails, you will see something like:\n\n@example\n@group\n  ***** test error (\"this test fails!\")\n!!!!! test failed\nthis test fails!\n@end group\n@end example\n\nGenerally, to test if something works, you want to assert that it\nproduces a correct value.  A real test might look something like\n\n@example\n@group\n%!test\n%! @var{a} = [1, 2, 3; 4, 5, 6]; B = [1; 2];\n%! expect = [ @var{a} ; 2*@var{a} ];\n%! get = kron (@var{b}, @var{a});\n%! if (any (size (expect) != size (get)))\n%!   error (\"wrong size: expected %d,%d but got %d,%d\",\n%!          size (expect), size (get));\n%! elseif (any (any (expect != get)))\n%!   error (\"didn't get what was expected.\");\n%! endif\n@end group\n@end example\n\nTo make the process easier, use the @code{assert} function.  For example,\nwith @code{assert} the previous test is reduced to:\n\n@example\n@group\n%!test\n%! @var{a} = [1, 2, 3; 4, 5, 6]; @var{b} = [1; 2];\n%! assert (kron (@var{b}, @var{a}), [ @var{a}; 2*@var{a} ]);\n@end group\n@end example\n\n@code{assert} can accept a tolerance so that you can compare results\nabsolutely or relatively.  For example, the following all succeed:\n\n@example\n@group\n%!test assert (1+eps, 1, 2*eps)           # absolute error\n%!test assert (100+100*eps, 100, -2*eps)  # relative error\n@end group\n@end example\n\nYou can also do the comparison yourself, but still have assert\ngenerate the error:\n\n@example\n@group\n%!test assert (isempty ([]))\n%!test assert ([1, 2; 3, 4] > 0)\n@end group\n@end example\n\nBecause @code{assert} is so frequently used alone in a test block, there\nis a shorthand form:\n\n@example\n%!assert (@dots{})\n@end example\n\n@noindent\nwhich is equivalent to:\n\n@example\n%!test assert (@dots{})\n@end example\n\nOccasionally a block of tests will depend on having optional\nfunctionality in Octave.  Before testing such blocks the availability of\nthe required functionality must be checked.  A @code{%!testif HAVE_XXX}\nblock will only be run if Octave was compiled with functionality\n@samp{HAVE_XXX}.  For example, the sparse single value decomposition,\n@code{svds()}, depends on having the @sc{arpack} library.  All of the tests\nfor @code{svds} begin with\n\n@example\n%!testif HAVE_ARPACK\n@end example\n\n@noindent\nReview @file{config.h} or @code{__octave_config_info__ (\"build_features\")}\nto see some of the possible values to check.\n\nSometimes during development there is a test that should work but is\nknown to fail.  You still want to leave the test in because when the\nfinal code is ready the test should pass, but you may not be able to\nfix it immediately.  To avoid unnecessary bug reports for these known\nfailures, mark the block with @code{xtest} rather than @code{test}:\n\n@example\n@group\n%!xtest assert (1==0)\n%!xtest fail (\"success=1\", \"error\")\n@end group\n@end example\n\n@noindent\nIn this case, the test will run and any failure will be reported.\nHowever, testing is not aborted and subsequent test blocks will be\nprocessed normally.  Another use of @code{xtest} is for statistical\ntests which should pass most of the time but are known to fail\noccasionally.\n\nEach block is evaluated in its own function environment, which means\nthat variables defined in one block are not automatically shared\nwith other blocks.  If you do want to share variables, then you\nmust declare them as @code{shared} before you use them.  For example, the\nfollowing declares the variable @var{a}, gives it an initial value (default\nis empty), and then uses it in several subsequent tests.\n\n@example\n@group\n%!shared @var{a}\n%! @var{a} = [1, 2, 3; 4, 5, 6];\n%!assert (kron ([1; 2], @var{a}), [ @var{a}; 2*@var{a} ])\n%!assert (kron ([1, 2], @var{a}), [ @var{a}, 2*@var{a} ])\n%!assert (kron ([1,2; 3,4], @var{a}), [ @var{a},2*@var{a}; 3*@var{a},4*@var{a} ])\n@end group\n@end example\n\nYou can share several variables at the same time:\n\n@example\n%!shared @var{a}, @var{b}\n@end example\n\nModifications to shared variables persist from one test to the next\n@strong{only} if the test succeeds.  Thus, if one test modifies a shared\nvariable, later tests cannot know which value of the shared variable to expect\nbecause the pass/fail status of earlier tests is unknown.  For this reason, it\nis not recommended to modify shared variables in tests.\n\nYou can also share test functions:\n\n@example\n@group\n%!function @var{a} = fn (@var{b})\n%!  @var{a} = 2*@var{b};\n%!endfunction\n%!assert (fn(2), 4)\n@end group\n@end example\n\nNote that all previous variables and values are lost when a new\nshared block is declared.\n\nRemember that @code{%!function} begins a new block and that\n@code{%!endfunction} ends this block.  Be aware that until a new block\nis started, lines starting with @samp{%!<space>} will be discarded as comments.\nThe following is nearly identical to the example above, but does nothing.\n\n@example\n@group\n%!function @var{a} = fn (@var{b})\n%!  @var{a} = 2*@var{b};\n%!endfunction\n%! assert (fn(2), 4)\n@end group\n@end example\n\n@noindent\nBecause there is a space after @samp{%!} the @code{assert} statement does\nnot begin a new block and this line is treated as a comment.\n\nError and warning blocks are like test blocks, but they only succeed\nif the code generates an error.  You can check the text of the error\nis correct using an optional regular expression @code{<pattern>}.\nFor example:\n\n@example\n%!error <passes!> error (\"this test passes!\")\n@end example\n\nIf the code doesn't generate an error, the test fails.  For example:\n\n@example\n%!error \"this is an error because it succeeds.\"\n@end example\n\n@noindent\nproduces\n\n@example\n@group\n  ***** error \"this is an error because it succeeds.\"\n!!!!! test failed: no error\n@end group\n@end example\n\nIt is important to automate the tests as much as possible, however\nsome tests require user interaction.  These can be isolated into\ndemo blocks, which if you are in batch mode, are only run when\ncalled with @code{demo} or the @code{verbose} option to @code{test}.\nThe code is displayed before it is executed.  For example,\n\n@example\n@group\n%!demo\n%! @var{t} = [0:0.01:2*pi]; @var{x} = sin (@var{t});\n%! plot (@var{t}, @var{x});\n%! # you should now see a sine wave in your figure window\n@end group\n@end example\n\n@noindent\nproduces\n\n@example\n@group\nfuncname example 1:\n @var{t} = [0:0.01:2*pi]; @var{x} = sin (@var{t});\n plot (@var{t}, @var{x});\n # you should now see a sine wave in your figure window\n\nPress <enter> to continue:\n@end group\n@end example\n\nNote that demo blocks cannot use any shared variables.  This is so\nthat they can be executed by themselves, ignoring all other tests.\n\nIf you want to temporarily disable a test block, put @code{#} in place\nof the block type.  This creates a comment block which is echoed\nin the log file but not executed.  For example:\n\n@example\n@group\n%!#demo\n%! @var{t} = [0:0.01:2*pi]; @var{x} = sin (@var{t});\n%! plot (@var{t}, @var{x});\n%! # you should now see a sine wave in your figure window\n@end group\n@end example\n\n@noindent\nThe following trivial code snippet provides examples for the use of\nfail, assert, error, and xtest:\n\n@example\n@group\nfunction @var{output} = must_be_zero (@var{input})\n  if (@var{input} != 0)\n    error (\"Nonzero input!\")\n  endif\n  @var{output} = @var{input};\nendfunction\n\n%!fail (\"must_be_zero (1)\")\n%!assert (must_be_zero (0), 0)\n%!error <Nonzero> must_be_zero (1)\n%!xtest error (\"This code generates an error\")\n@end group\n@end example\n\n@noindent\nWhen putting this in a file @file{must_be_zero.m}, and running the test, we see\n\n@example\n@group\ntest must_be_zero verbose\n\n@xresult{}\n>>>>> /path/to/must_be_zero.m\n***** fail (\"must_be_zero (1)\")\n***** assert (must_be_zero (0), 0)\n***** error <Nonzero> must_be_zero (1)\n***** xtest error (\"This code generates an error\")\n!!!!! known failure\nThis code generates an error\nPASSES 3 out of 4 tests (1 expected failure)\n@end group\n@end example\n\n@subsubheading Block type summary\n\n@table @code\n@item  %!test\n@itemx %!test <MESSAGE>\nCheck that entire block is correct.  If @code{<MESSAGE>} is present, the\ntest block is interpreted as for @code{xtest}.\n\n@item  %!testif HAVE_XXX\n@itemx %!testif HAVE_XXX, HAVE_YYY, @dots{}\n@itemx %!testif @dots{}; RUNTIME_COND\n@itemx %!testif @dots{} <MESSAGE>\nCheck block only if Octave was compiled with feature @w{@code{HAVE_XXX}}.\n@w{@env{RUNTIME_COND}}@ is an optional expression to evaluate to check\nwhether some condition is met when the test is executed.  If\n@w{@env{RUNTIME_COND}}@ is false, the test is skipped.  If @code{<MESSAGE>}\nis present, the test block is interpreted as for @code{xtest}.\n\n@item  %!xtest\n@itemx %!xtest <MESSAGE>\nCheck block, report a test failure but do not abort testing.  If\n@code{<MESSAGE>} is present, then the text of the message is displayed\nif the test fails, like this:\n\n@example\n!!!!! known bug:  MESSAGE\n@end example\n\n@noindent\nIf the message is an integer, it is interpreted as a bug ID for the\nOctave bug tracker and reported as\n\n@example\n!!!!! known bug: https://octave.org/testfailure/?BUG-ID\n@end example\n\n@noindent\nin which BUG-ID is the integer bug number.  The intent is to allow\nclearer documentation of known problems.\n\n@noindent\nIf @code{MESSAGE} is an integer preceeded by an asterisk (e.g.,\n@code{*12345}), it is interpreted as the id for a bug report that has\nbeen closed.  That usually means that the issue probed in this test has\nbeen resolved.  If such tests are failing, they are reported as\nregressions by the @code{test} function:\n\n@example\n!!!!! regression: https://octave.org/testfailure/?BUG-ID\n@end example\n\n\n@item  %!error\n@itemx %!error <MESSAGE>\n@itemx %!warning\n@itemx %!warning <MESSAGE>\nCheck for correct error or warning message.  If @code{<MESSAGE>} is\nsupplied it is interpreted as a regular expression pattern that is\nexpected to match the error or warning message.\n\n@item %!demo\nDemo only executes in interactive mode.\n\n@item %!#\nComment.  Ignore everything within the block\n\n@item %!shared x,y,z\nDeclare variables for use in multiple tests.\n\n@item %!function\nDefine a function for use in multiple tests.\n\n@item %!endfunction\nClose a function definition.\n\n@item %!assert (x, y, tol)\n\n@item %!assert <MESSAGE> (x, y, tol)\n\n@item %!fail (CODE, PATTERN)\n\n@item %!fail <MESSAGE> (CODE, PATTERN)\nShorthand for @code{%!test assert (x, y, tol)} or\n@code{%!test fail (CODE, PATTERN)}.  If @code{<MESSAGE>} is present, the\ntest block is interpreted as for @code{xtest}.\n\n@end table\n\n@anchor{test-message-anchor}\n\nWhen coding tests the Octave convention is that lines that begin with a block\ntype do not have a semicolon at the end.  Any code that is within a block,\nhowever, is normal Octave code and usually will have a trailing semicolon.\nFor example,\n\n@example\n@group\n## bare block instantiation\n%!assert (sin (0), 0)\n@end group\n@end example\n\n@noindent\nbut\n\n@example\n@group\n## test block with normal Octave code\n%!test\n%! assert (sin (0), 0);\n@end group\n@end example\n\nYou can also create test scripts for built-in functions and your own C++\nfunctions.  To do so, put a file with the bare function name (no .m\nextension) in a directory in the load path and it will be discovered by\nthe @code{test} function.  Alternatively, you can embed tests directly in your\nC++ code:\n\n@example\n@group\n/*\n%!test disp (\"this is a test\")\n*/\n@end group\n@end example\n\n@noindent\nor\n\n@example\n@group\n#if 0\n%!test disp (\"this is a test\")\n#endif\n@end group\n@end example\n\n@noindent\nHowever, in this case the raw source code will need to be on the load\npath and the user will have to remember to type\n@code{test (\"funcname.cc\")}.\n\n@DOCSTRING(assert)\n\n@DOCSTRING(assert_equal)\n\n@DOCSTRING(fail)\n\n@node Demonstration Functions\n@section Demonstration Functions\n\n@DOCSTRING(demo)\n\n@DOCSTRING(example)\n\n@DOCSTRING(oruntests)\n\n@DOCSTRING(rundemos)\n\n@DOCSTRING(speed)\n"
  },
  {
    "path": "doc/interpreter/var.txi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Variables\n@chapter Variables\n@cindex variables, user-defined\n@cindex user-defined variables\n\nVariables let you give names to values and refer to them later.  You have\nalready seen variables in many of the examples.  The name of a variable\nmust be a sequence of letters, digits and underscores, but it may not begin\nwith a digit.  Octave does not enforce a limit on the length of variable\nnames, but it is seldom useful to have variables with names longer than\nabout 30 characters.  The following are all valid variable names\n\n@example\n@group\nx\nx15\n__foo_bar_baz__\nfucnrdthsucngtagdjb\n@end group\n@end example\n\n@noindent\nHowever, names like @code{__foo_bar_baz__} that begin and end with two\nunderscores are understood to be reserved for internal use by Octave.\nYou should not use them in code you write, except to access Octave's\ndocumented internal variables and built-in symbolic constants.\n\nCase is significant in variable names.  The symbols @code{a} and\n@code{A} are distinct variables.\n\nA variable name is a valid expression by itself.  It represents the\nvariable's current value.  Variables are given new values with\n@dfn{assignment operators} and @dfn{increment operators}.\n@xref{Assignment Ops,,Assignment Expressions}.\n\nThere is one automatically created variable with a special meaning.  The\n@code{ans} variable always contains the result of the last computation,\nwhere the output wasn't assigned to any variable.  The code @code{a =\ncos (pi)} will assign the value -1 to the variable @code{a}, but will\nnot change the value of @code{ans}.  However, the code @code{cos (pi)}\nwill set the value of @code{ans} to -1.\n\nVariables in Octave do not have fixed types, so it is possible to first\nstore a numeric value in a variable and then to later use the same name\nto hold a string value in the same program.  Variables may not be used\nbefore they have been given a value.  Doing so results in an error.\n\n@cindex @code{ans}\n@DOCSTRING(ans)\n\n@DOCSTRING(isvarname)\n\n@DOCSTRING(matlab.lang.makeValidName)\n\n@DOCSTRING(matlab.lang.makeUniqueStrings)\n\n@DOCSTRING(namelengthmax)\n\n@menu\n* Global Variables::\n* Persistent Variables::\n* Status of Variables::\n@end menu\n\n@node Global Variables\n@section Global Variables\n@cindex global variables\n@cindex @code{global} statement\n@cindex variables, global\n\nSee keyword: @ref{XREFglobal,,global}\n\nA @dfn{global} variable is one that may be accessed anywhere within Octave.\nThis is in contrast to a local variable which can only be accessed outside\nof its current context if it is passed explicitly, such as by including it as a\nparameter when calling a function\n(@code{fcn (@var{local_var1}, @var{local_var2})}).\n\nA variable is declared global by using a @code{global} declaration statement.\nThe following statements are all global declarations.\n\n@example\n@group\nglobal a\nglobal a b\nglobal c = 2\nglobal d = 3 e f = 5\n@end group\n@end example\n\nNote that the @code{global} qualifier extends only to the next end-of-statement\nindicator which could be a comma (@samp{,}), semicolon (@samp{;}), or newline\n(@samp{'\\n'}).  For example, the following code declares one global variable,\n@var{a}, and one local variable @var{b} to which the value 1 is assigned.\n\n@example\nglobal a, b = 1\n@end example\n\nA global variable may only be initialized once in a @code{global} statement.\nFor example, after executing the following code\n\n@example\n@group\nglobal gvar = 1\nglobal gvar = 2\n@end group\n@end example\n\n@noindent\nthe value of the global variable @code{gvar} is 1, not 2.  Issuing a\n@samp{clear gvar} command does not change the above behavior, but\n@samp{clear all} does.\n\nIt is necessary declare a variable as global within a function body in order to\naccess the one universal variable.  For example,\n\n@example\n@group\nglobal x\nfunction f ()\n  x = 1;\nendfunction\nf ()\n@end group\n@end example\n\n@noindent\ndoes @emph{not} set the value of the global variable @code{x} to 1.  Instead,\na local variable, with name @code{x}, is created and assigned the value of 1.\nIn order to change the value of the global variable @code{x}, you must also\ndeclare it to be global within the function body, like this\n\n@example\n@group\nfunction f ()\n  global x;\n  x = 1;\nendfunction\n@end group\n@end example\n\nPassing a global variable in a function parameter list will make a local copy\nand @emph{not} modify the global value.  For example, given the function\n\n@example\n@group\nfunction f (x)\n  x = 0\nendfunction\n@end group\n@end example\n\n@noindent\nand the definition of @code{x} as a global variable at the top level,\n\n@example\nglobal x = 13\n@end example\n\n@noindent\nthe expression\n\n@example\nf (x)\n@end example\n\n@noindent\nwill display the value of @code{x} from inside the function as 0, but the value\nof @code{x} at the top level remains unchanged, because the function works with\na @emph{copy} of its argument.\n\nProgramming Note: While global variables occasionally are the right solution to\na coding problem, modern best practice discourages their use.  Code which\nrelies on global variables may behave unpredictably between different users\nand can be difficult to debug.  This is because global variables can introduce\nsystemic changes so that localizing a bug to a particular function, or to a\nparticular loop within a function, becomes difficult.\n\n@DOCSTRING(isglobal)\n\n@node Persistent Variables\n@section Persistent Variables\n@cindex persistent variables\n@cindex @code{persistent} statement\n@cindex variables, persistent\n\nSee keyword: @ref{XREFpersistent,,persistent}\n\nA variable that has been declared @dfn{persistent} within a function\nwill retain its contents in memory between subsequent calls to the\nsame function.  The difference between persistent variables and global\nvariables is that persistent variables are local in scope to a\nparticular function and are not visible elsewhere.\n\nThe following example uses a persistent variable to create a function\nthat prints the number of times it has been called.\n\n@example\n@group\nfunction count_calls ()\n  persistent calls = 0;\n  printf (\"'count_calls' has been called %d times\\n\",\n          ++calls);\nendfunction\n\nfor i = 1:3\n  count_calls ();\nendfor\n\n@print{} 'count_calls' has been called 1 times\n@print{} 'count_calls' has been called 2 times\n@print{} 'count_calls' has been called 3 times\n@end group\n@end example\n\nAs the example shows, a variable may be declared persistent using a\n@code{persistent} declaration statement.  The following statements are\nall persistent declarations.\n\n@example\n@group\npersistent a\npersistent a b\npersistent c = 2\npersistent d = 3 e f = 5\n@end group\n@end example\n\nThe behavior of persistent variables is equivalent to the behavior of\nstatic variables in C@.\n\nOne restriction for persistent variables is, that neither input nor\noutput arguments of a function can be persistent:\n\n@example\n@group\nfunction y = foo ()\n  persistent y = 0;  # Not allowed!\nendfunction\n\nfoo ()\n@print{} error: can't make function parameter y persistent\n@end group\n@end example\n\nLike global variables, a persistent variable may only be initialized once.\nFor example, after executing the following code\n\n@example\n@group\npersistent pvar = 1\npersistent pvar = 2\n@end group\n@end example\n\n@noindent\nthe value of the persistent variable @code{pvar} is 1, not 2.\n\nIf a persistent variable is declared but not initialized to a specific\nvalue, it will contain an empty matrix.  So, it is also possible to\ninitialize a persistent variable by checking whether it is empty, as the\nfollowing example illustrates.\n\n@example\n@group\nfunction count_calls ()\n  persistent calls;\n  if (isempty (calls))\n    calls = 0;\n  endif\n  printf (\"'count_calls' has been called %d times\\n\",\n          ++calls);\nendfunction\n@end group\n@end example\n\n@noindent\nThis implementation behaves in exactly the same way as the previous\nimplementation of @code{count_calls}.\n\nThe value of a persistent variable is kept in memory until it is\nexplicitly cleared.  Assuming that the implementation of @code{count_calls}\nis saved on disk, we get the following behavior.\n\n@example\nfor i = 1:2\n  count_calls ();\nendfor\n@print{} 'count_calls' has been called 1 times\n@print{} 'count_calls' has been called 2 times\n\nclear\nfor i = 1:2\n  count_calls ();\nendfor\n@print{} 'count_calls' has been called 3 times\n@print{} 'count_calls' has been called 4 times\n\nclear all\nfor i = 1:2\n  count_calls ();\nendfor\n@print{} 'count_calls' has been called 1 times\n@print{} 'count_calls' has been called 2 times\n\nclear count_calls\nfor i = 1:2\n  count_calls ();\nendfor\n@print{} 'count_calls' has been called 1 times\n@print{} 'count_calls' has been called 2 times\n@end example\n\n@noindent\nThat is, the persistent variable is only removed from memory when the\nfunction containing the variable is removed.  Note that if the function\ndefinition is typed directly into the Octave prompt, the persistent\nvariable will be cleared by a simple @code{clear} command as the entire\nfunction definition will be removed from memory.  If you do not want\na persistent variable to be removed from memory even if the function is\ncleared, you should use the @code{mlock} function\n(@pxref{Function Locking}).\n\n@node Status of Variables\n@section Status of Variables\n\nWhen creating simple one-shot programs it can be very convenient to\nsee which variables are available at the prompt.  The function @code{who}\nand its siblings @code{whos} and @code{whos_line_format} will show\ndifferent information about what is in memory, as the following shows.\n\n@example\n@group\nstr = \"A random string\";\nwho\n @print{} Variables in the current scope:\n @print{}\n @print{} ans  str\n@end group\n@end example\n\n@DOCSTRING(who)\n\n@DOCSTRING(whos)\n\n@DOCSTRING(whos_line_format)\n\nInstead of displaying which variables are in memory, it is possible\nto determine if a given variable is available.  That way it is possible\nto alter the behavior of a program depending on the existence of a\nvariable.  The following example illustrates this.\n\n@example\n@group\nif (! exist (\"meaning\", \"var\"))\n  disp (\"The program has no 'meaning'\");\nendif\n@end group\n@end example\n\n@DOCSTRING(exist)\n\nUsually Octave will manage the memory, but sometimes it can be practical\nto remove variables from memory manually.  This is usually needed when\nworking with large variables that fill a substantial part of the memory.\nOn a computer that uses the IEEE@tie{}754 floating point format, the following\nprogram allocates a matrix that requires around 128 MB memory.\n\n@example\nlarge_matrix = zeros (4000, 4000);\n@end example\n\n@noindent\nSince having this variable in memory might slow down other computations,\nit can be necessary to remove it manually from memory.  The @code{clear}\nor @code{clearvars} functions do this.\n\n@DOCSTRING(clear)\n\n@DOCSTRING(clearvars)\n\n@DOCSTRING(pack)\n\nInformation about a function or variable such as its location in the\nfile system can also be acquired from within Octave.  This is usually\nonly useful during development of programs, and not within a program.\n\n@DOCSTRING(type)\n\n@DOCSTRING(which)\n\n@DOCSTRING(what)\n"
  },
  {
    "path": "doc/interpreter/vectorize.txi",
    "content": "@c Copyright (C) 2012-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Vectorization and Faster Code Execution\n@chapter Vectorization and Faster Code Execution\n@cindex vectorization\n@cindex vectorize\n\nVectorization is a programming technique that uses vector operations\ninstead of element-by-element loop-based operations.  Besides frequently\nproducing more succinct Octave code, vectorization also allows for better\noptimization in the subsequent implementation.  The optimizations may occur\neither in Octave's own Fortran, C, or C++ internal implementation, or even at a\nlower level depending on the compiler and external numerical libraries used to\nbuild Octave.  The ultimate goal is to make use of your hardware's vector\ninstructions if possible or to perform other optimizations in software.\n\nVectorization is not a concept unique to Octave, but it is particularly\nimportant because Octave is a matrix-oriented language.  Vectorized\nOctave code will see a dramatic speed up (10X--100X) in most cases.\n\nThis chapter discusses vectorization and other techniques for writing faster\ncode.\n\n@menu\n* Basic Vectorization::        Basic techniques for code optimization\n* Broadcasting::               Broadcasting operations\n* Function Application::       Applying functions to arrays, cells, and structs\n* Accumulation::               Accumulation functions\n* Memoization::                Memoization techniques\n* Miscellaneous Techniques::   Other techniques for speeding up code\n* Examples::\n@end menu\n\n@node Basic Vectorization\n@section Basic Vectorization\n\nTo a very good first approximation, the goal in vectorization is to\nwrite code that avoids loops and uses whole-array operations.  As a\ntrivial example, consider\n\n@example\n@group\nfor i = 1:n\n  for j = 1:m\n    c(i,j) = a(i,j) + b(i,j);\n  endfor\nendfor\n@end group\n@end example\n\n@noindent\ncompared to the much simpler\n\n@example\nc = a + b;\n@end example\n\n@noindent\nThis isn't merely easier to write; it is also internally much easier to\noptimize.  Octave delegates this operation to an underlying\nimplementation which, among other optimizations, may use special vector\nhardware instructions or could conceivably even perform the additions in\nparallel.  In general, if the code is vectorized, the underlying\nimplementation has more freedom about the assumptions it can make\nin order to achieve faster execution.\n\nThis is especially important for loops with \"cheap\" bodies.  Often it\nsuffices to vectorize just the innermost loop to get acceptable\nperformance.  A general rule of thumb is that the \"order\" of the\nvectorized body should be greater or equal to the \"order\" of the\nenclosing loop.\n\nAs a less trivial example, instead of\n\n@example\n@group\nfor i = 1:n-1\n  a(i) = b(i+1) - b(i);\nendfor\n@end group\n@end example\n\n@noindent\nwrite\n\n@example\na = b(2:n) - b(1:n-1);\n@end example\n\nThis shows an important general concept about using arrays for indexing\ninstead of looping over an index variable.  @xref{Index Expressions}.\nAlso use boolean indexing generously.  If a condition needs to be tested,\nthis condition can also be written as a boolean index.  For instance,\ninstead of\n\n@example\n@group\nfor i = 1:n\n  if (a(i) > 5)\n    a(i) -= 20\n  endif\nendfor\n@end group\n@end example\n\n@noindent\nwrite\n\n@example\na(a>5) -= 20;\n@end example\n\n@noindent\nwhich exploits the fact that @code{a > 5} produces a boolean index.\n\nUse elementwise vector operators whenever possible to avoid looping\n(operators like @code{.*} and @code{.^}).  @xref{Arithmetic Ops}.\n\nAlso exploit broadcasting in these elementwise operators both to avoid\nlooping and unnecessary intermediate memory allocations.\n@xref{Broadcasting}.\n\nUse built-in and library functions if possible.  Built-in and compiled\nfunctions are very fast.  Even with an m-file library function, chances\nare good that it is already optimized, or will be optimized more in a\nfuture release.\n\nFor instance, even better than\n\n@example\na = b(2:n) - b(1:n-1);\n@end example\n\n@noindent\nis\n\n@example\na = diff (b);\n@end example\n\nMost Octave functions are written with vector and array arguments in\nmind.  If you find yourself writing a loop with a very simple operation,\nchances are that such a function already exists.  The following functions\noccur frequently in vectorized code:\n\n@itemize @bullet\n@item\nIndex manipulation\n\n@itemize\n@item\nfind\n\n@item\nsub2ind\n\n@item\nind2sub\n\n@item\nsort\n\n@item\nunique\n\n@item\nlookup\n\n@item\nifelse / merge\n@end itemize\n\n@item\nRepetition\n\n@itemize\n@item\nrepmat\n\n@item\nrepelems\n@end itemize\n\n@item\nVectorized arithmetic\n\n@itemize\n@item\nsum\n\n@item\nprod\n\n@item\ncumsum\n\n@item\ncumprod\n\n@item\nsumsq\n\n@item\ndiff\n\n@item\ndot\n\n@item\ncummax\n\n@item\ncummin\n@end itemize\n\n@item\nShape of higher dimensional arrays\n\n@itemize\n@item\nreshape\n\n@item\nresize\n\n@item\npermute\n\n@item\nsqueeze\n\n@item\ndeal\n@end itemize\n\n@end itemize\n\n@node Broadcasting\n@section Broadcasting\n@cindex broadcast\n@cindex broadcasting\n@cindex @nospell{BSX}\n@cindex recycling\n@cindex SIMD\n\n@menu\n* Broadcasting and Legacy Code::\n@end menu\n\nBroadcasting refers to how Octave binary operators and functions behave\nwhen their matrix or array operands or arguments differ in size.  Since\nversion 3.6.0, Octave now automatically broadcasts vectors, matrices,\nand arrays when using elementwise binary operators and functions.\nBroadly speaking, smaller arrays are ``broadcast'' across the larger\none, until they have a compatible shape.  The rule is that corresponding\narray dimensions must either\n\n@enumerate\n@item\nbe equal, or\n\n@item\none of them must be 1.\n@end enumerate\n\n@noindent\nIn case all dimensions are equal, no broadcasting occurs and ordinary\nelement-by-element arithmetic takes place.  For arrays of higher\ndimensions, if the number of dimensions isn't the same, then missing\ntrailing dimensions are treated as 1.  When one of the dimensions is 1,\nthe array with that singleton dimension gets copied along that dimension\nuntil it matches the dimension of the other array.  For example, consider\n\n@example\n@group\nx = [1 2 3;\n     4 5 6;\n     7 8 9];\n\ny = [10 20 30];\n\nx + y\n@end group\n@end example\n\n@noindent\nWithout broadcasting, @code{x + y} would be an error because the dimensions\ndo not agree.  However, with broadcasting it is as if the following\noperation were performed:\n\n@example\n@group\nx = [1 2 3\n     4 5 6\n     7 8 9];\n\ny = [10 20 30\n     10 20 30\n     10 20 30];\n\nx + y\n@xresult{}    11   22   33\n      14   25   36\n      17   28   39\n@end group\n@end example\n\n@noindent\nThat is, the smaller array of size @code{[1 3]} gets copied along the\nsingleton dimension (the number of rows) until it is @code{[3 3]}.  No\nactual copying takes place, however.  The internal implementation reuses\nelements along the necessary dimension in order to achieve the desired\neffect without copying in memory.\n\nBoth arrays can be broadcast across each other, for example, all\npairwise differences of the elements of a vector with itself:\n\n@example\n@group\ny - y'\n@xresult{}    0   10   20\n    -10    0   10\n    -20  -10    0\n@end group\n@end example\n\n@noindent\nHere the vectors of size @code{[1 3]} and @code{[3 1]} both get\nbroadcast into matrices of size @code{[3 3]} before ordinary matrix\nsubtraction takes place.\n\nA special case of broadcasting that may be familiar is when all\ndimensions of the array being broadcast are 1, i.e., the array is a\nscalar.  Thus, for example, operations like @code{x - 42} and\n@code{max (x, 2)} are basic examples of broadcasting.\n\nFor a higher-dimensional example, suppose @code{img} is an RGB image of\nsize @code{[m n 3]} and we wish to multiply each color by a different\nscalar.  The following code accomplishes this with broadcasting,\n\n@example\nimg .*= permute ([0.8, 0.9, 1.2], [1, 3, 2]);\n@end example\n\n@noindent\nNote the usage of permute to match the dimensions of the\n@code{[0.8, 0.9, 1.2]} vector with @code{img}.\n\nFor functions that are not written with broadcasting semantics,\n@code{bsxfun} can be useful for coercing them to broadcast.\n\n@DOCSTRING(bsxfun)\n\nBroadcasting is only applied if either of the two broadcasting\nconditions hold.  As usual, however, broadcasting does not apply when two\ndimensions differ and neither is 1:\n\n@example\n@group\nx = [1 2 3\n     4 5 6];\ny = [10 20\n     30 40];\nx + y\n@end group\n@end example\n\n@noindent\nThis will produce an error about nonconformant arguments.\n\nBesides common arithmetic operations, several functions of two arguments\nalso broadcast.  The full list of functions and operators that broadcast\nis\n\n@example\n      plus      +\n      minus     -\n      times     .*\n      rdivide   ./\n      ldivide   .\\\n      power     .^\n      lt        <\n      le        <=\n      eq        ==\n      gt        >\n      ge        >=\n      ne        !=  ~=\n      and       &\n      or        |\n      atan2\n      hypot\n      max\n      min\n      mod\n      rem\n      xor\n\n      +=  -=  .*=  ./=  .\\=  .^=  &=  |=\n@end example\n\nHere is a real example of the power of broadcasting.  The\n@nospell{Floyd-Warshall} algorithm is used to calculate the shortest path\nlengths between every pair of vertices in a graph.  A naive implementation for\na graph adjacency matrix of order @var{n} might look like this:\n\n@example\n@group\nfor k = 1:n\n  for i = 1:n\n    for j = 1:n\n      dist(i,j) = min (dist(i,j), dist(i,k) + dist(k,j));\n    endfor\n  endfor\nendfor\n@end group\n@end example\n\nUpon vectorizing the innermost loop, it might look like this:\n\n@example\n@group\nfor k = 1:n\n  for i = 1:n\n    dist(i,:) = min (dist(i,:), dist(i,k) + dist(k,:));\n  endfor\nendfor\n@end group\n@end example\n\nUsing broadcasting in both directions, it looks like this:\n\n@example\n@group\nfor k = 1:n\n  dist = min (dist, dist(:,k) + dist(k,:));\nendfor\n@end group\n@end example\n\nThe relative time performance of the three techniques for a given graph with\n100 vertices is 7.3 seconds for the naive code, 87 milliseconds for the\nsingly vectorized code, and 1.3 milliseconds for the fully broadcast code.\nFor a graph with 1000 vertices, vectorization takes 11.7 seconds while\nbroadcasting takes only 1.15 seconds.  Therefore in general it is worth\nwriting code with broadcasting semantics for performance.\n\nHowever, beware of resorting to broadcasting if a simpler operation will\nsuffice.  For matrices @var{a} and @var{b}, consider the following:\n\n@example\n@var{c} = sum (permute (@var{a}, [1, 3, 2]) .* permute (@var{b}, [3, 2, 1]), 3);\n@end example\n\n@noindent\nThis operation broadcasts the two matrices with permuted dimensions\nacross each other during elementwise multiplication in order to obtain a\nlarger 3-D array, and this array is then summed along the third dimension.\nA moment of thought will prove that this operation is simply the much\nfaster ordinary matrix multiplication, @code{@var{c} = @var{a}*@var{b};}.\n\nA note on terminology: ``broadcasting'' is the term popularized by the\n@nospell{Numpy} numerical environment in the Python programming language.  In\nother programming languages and environments, broadcasting may also be known\nas @emph{binary singleton expansion} (@nospell{BSX}, in @sc{matlab}, and the\norigin of the name of the @code{bsxfun} function), @emph{recycling} (R\nprogramming language), @emph{single-instruction multiple data} (SIMD),\nor @emph{replication}.\n\n@node Broadcasting and Legacy Code\n@subsection Broadcasting and Legacy Code\n\nThe new broadcasting semantics almost never affect code that worked\nin previous versions of Octave.  Consequently, all code inherited from\n@sc{matlab} that worked in previous versions of Octave should still work\nwithout change in Octave.  The only exception is code such as\n\n@example\n@group\ntry\n  c = a.*b;\ncatch\n  c = a.*a;\nend_try_catch\n@end group\n@end example\n\n@noindent\nthat may have relied on matrices of different size producing an error.\nBecause such operation is now valid Octave syntax, this will no longer\nproduce an error.  Instead, the following code should be used:\n\n@example\n@group\nif (isequal (size (a), size (b)))\n  c = a .* b;\nelse\n  c = a .* a;\nendif\n@end group\n@end example\n\n\n@node Function Application\n@section Function Application\n@cindex map\n@cindex apply\n@cindex function application\n\nAs a general rule, functions should already be written with matrix\narguments in mind and should consider whole matrix operations in a\nvectorized manner.  Sometimes, writing functions in this way appears\ndifficult or impossible for various reasons.  For those situations,\nOctave provides facilities for applying a function to each element of an\narray, cell, or struct.\n\n@DOCSTRING(arrayfun)\n\n@DOCSTRING(spfun)\n\n@DOCSTRING(cellfun)\n\n@DOCSTRING(structfun)\n\nConsistent with earlier advice, seek to use Octave built-in functions whenever\npossible for the best performance.  This advice applies especially to the four\nfunctions above.  For example, when adding two arrays together\nelement-by-element one could use a handle to the built-in addition function\n@code{@@plus} or define an anonymous function @code{@@(x,y) x + y}.  But, the\nanonymous function is 60% slower than the first method.\n@xref{Operator Overloading}, for a list of basic functions which might be used\nin place of anonymous ones.\n\n@node Accumulation\n@section Accumulation\n\nWhenever it's possible to categorize according to indices the elements\nof an array when performing a computation, accumulation functions can be\nuseful.\n\n@DOCSTRING(accumarray)\n\n@DOCSTRING(accumdim)\n\n@node Memoization\n@section Memoization\n\nMemoization is a technique to cache the results of slow function calls and\nreturn the cached value when the function is called with the same inputs again,\ninstead of reevaluating it.  It is very common to replace function calls with\nlookup tables if the same inputs are happening over and over again in a known,\npredictable way.  Memoization is, at its core, an extension of this practice\nwhere the lookup table is extended even during runtime for new arguments not\nseen previously.  A basic theoretical background can be found on Wikipedia or\nany undergraduate-level computer science textbook.\n\nOctave's @code{memoize} function provides drop-in memoization functionality for\nany user function or Octave function, including compiled functions.\n\n@DOCSTRING(memoize)\n\nTo memoize a function @code{z = foo(x, y)}, use this general pattern:\n\n@example\n@group\nfoo2 = memoize (@@(@var{x, y}) @var{foo(x, y)});\nz = foo2 (x, y);\n@end group\n@end example\n\nIn the above example, the first line creates a memoized version @code{foo2} of\nthe function @code{foo}.  For simple functions with only trivial wrapping, this\nline can also be shortened to:\n\n@example\n@group\nfoo2 = memoize (@@foo);\n@end group\n@end example\n\nThe second line @code{z = foo2 (x, y);} calls that memoized version @code{foo2}\ninstead of the original function, allowing @code{memoize} to intercept the call\nand replace it with a looked-up value from a table if the inputs have occurred\nbefore, instead of evaluating the original function again.\n\nNote that this will not accelerate the @emph{first} call to the function but\nonly subsequent calls.\n\nNote that due to the overhead incurred by @code{memoize} to create and manage\nthe lookup tables for each function, this technique is useful only for\nfunctions that take at least a couple of seconds to execute.  Such functions\ncan be replaced by table lookups taking only a millisecond or so, but if the\noriginal function itself was taking only milliseconds, memoizing it will not\nspeed it up.\n\nRecursive functions can be memoized as well, using a pattern like:\n\n@example\n@group\nfunction z = foo (x, y)\n  persistent foo2 = memoize (@@foo);\n  foo2.CacheSize = 1e6;\n\n  ## Call the memoized version when recursing\n  z = foo2 (x, y);\nendfunction\n@end group\n@end example\n\nThe @code{CacheSize} can be optionally increased in anticipation of a large\nnumber of function calls, such as from inside a recursive function.  If\n@code{CacheSize} is exceeded, the memoization tables are resized, causing a\nslowdown.  Increasing the @code{CacheSize} thus works like preallocation to\nspeed up execution.\n\nThe function @code{clearAllMemoizedCaches} clears the memoization tables when\nthey are no longer needed.\n\n@DOCSTRING(clearAllMemoizedCaches)\n\n@node Miscellaneous Techniques\n@section Miscellaneous Techniques\n@cindex execution speed\n@cindex speedups\n@cindex optimization\n\nHere are some other ways of improving the execution speed of Octave programs.\n\n@itemize @bullet\n\n@item Avoid computing costly intermediate results multiple times.\nOctave currently does not eliminate common subexpressions.  Also, certain\ninternal computation results are cached for variables.  For instance, if\na matrix variable is used multiple times as an index, checking the\nindices (and internal conversion to integers) is only done once.\n\n@item Be aware of lazy copies (copy-on-write).\n@cindex copy-on-write\n@cindex COW\n@cindex memory management\nWhen a copy of an object is created, the data is not immediately copied, but\nrather shared.  The actual copying is postponed until the copied data needs to\nbe modified.  For example:\n\n@example\n@group\na = zeros (1000); # create a 1000x1000 matrix\nb = a; # no copying done here\nb(1) = 1; # copying done here\n@end group\n@end example\n\nLazy copying applies to whole Octave objects such as matrices, cells,\nstruct, and also individual cell or struct elements (not array\nelements).\n\nAdditionally, index expressions also use lazy copying when Octave can\ndetermine that the indexed portion is contiguous in memory.  For example:\n\n@example\n@group\na = zeros (1000); # create a 1000x1000 matrix\nb = a(:,10:100);  # no copying done here\nb = a(10:100,:);  # copying done here\n@end group\n@end example\n\nThis applies to arrays (matrices), cell arrays, and structs indexed\nusing @samp{()}.  Index expressions generating comma-separated lists can also\nbenefit from shallow copying in some cases.  In particular, when @var{a} is a\nstruct array, expressions like @code{@{a.x@}, @{a(:,2).x@}} will use lazy\ncopying, so that data can be shared between a struct array and a cell array.\n\nMost indexing expressions do not live longer than their parent\nobjects.  In rare cases, however, a lazily copied slice outlasts its\nparent, in which case it becomes orphaned, still occupying unnecessarily\nmore memory than needed.  To provide a remedy working in most real cases,\nOctave checks for orphaned lazy slices at certain situations, when a\nvalue is stored into a \"permanent\" location, such as a named variable or\ncell or struct element, and possibly economizes them.  For example:\n\n@example\n@group\na = zeros (1000); # create a 1000x1000 matrix\nb = a(:,10:100);  # lazy slice\na = []; # the original \"a\" array is still allocated\nc@{1@} = b; # b is reallocated at this point\n@end group\n@end example\n\n@item Avoid deep recursion.\nFunction calls to m-file functions carry a relatively significant overhead, so\nrewriting a recursion as a loop often helps.  Also, note that the maximum level\nof recursion is limited.\n\n@item Avoid resizing matrices unnecessarily.\nWhen building a single result matrix from a series of calculations, set the\nsize of the result matrix first, then insert values into it.  Write\n\n@example\n@group\nresult = zeros (big_n, big_m)\nfor i = over:and_over\n  ridx = @dots{}\n  cidx = @dots{}\n  result(ridx, cidx) = new_value ();\nendfor\n@end group\n@end example\n\n@noindent\ninstead of\n\n@example\n@group\nresult = [];\nfor i = ever:and_ever\n  result = [ result, new_value() ];\nendfor\n@end group\n@end example\n\nSometimes the number of items can not be computed in advance, and\nstack-like operations are needed.  When elements are being repeatedly\ninserted or removed from the end of an array, Octave detects it as stack\nusage and attempts to use a smarter memory management strategy by\npre-allocating the array in bigger chunks.  This strategy is also applied\nto cell and struct arrays.\n\n@example\n@group\na = [];\nwhile (condition)\n  @dots{}\n  a(end+1) = value; # \"push\" operation\n  @dots{}\n  a(end) = []; # \"pop\" operation\n  @dots{}\nendwhile\n@end group\n@end example\n\n@item Avoid calling @code{eval} or @code{feval} excessively.\nParsing input or looking up the name of a function in the symbol table are\nrelatively expensive operations.\n\nIf you are using @code{eval} merely as an exception handling mechanism, and not\nbecause you need to execute some arbitrary text, use the @code{try}\nstatement instead.  @xref{The try Statement}.\n\n@item Use @code{ignore_function_time_stamp} when appropriate.\nIf you are calling lots of functions, and none of them will need to change\nduring your run, set the variable @code{ignore_function_time_stamp} to\n@qcode{\"all\"}.  This will stop Octave from checking the time stamp of a\nfunction file to see if it has been updated while the program is being run.\n@end itemize\n\n@node Examples\n@section Examples\n\nThe following are examples of vectorization questions asked by actual\nusers of Octave and their solutions.\n\n@c FIXME: We need a lot more examples here.\n\n@itemize @bullet\n@item\nFor a vector @code{A}, the following loop\n\n@example\n@group\nn = length (A) - 1;\nB = zeros (n, 2);\nfor i = 1:n\n  ## this will be two columns, the first is the difference and\n  ## the second the mean of the two elements used for the diff.\n  B(i,:) = [A(i+1)-A(i), (A(i+1) + A(i))/2];\nendfor\n@end group\n@end example\n\n@noindent\ncan be turned into the following one-liner:\n\n@example\nB = [diff(A)(:), 0.5*(A(1:end-1)+A(2:end))(:)]\n@end example\n\nNote the usage of colon indexing to flatten an intermediate result into\na column vector.  This is a common vectorization trick.\n\n@end itemize\n"
  },
  {
    "path": "doc/liboctave/array.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Arrays\n@chapter Arrays\n@cindex arrays\n\n@menu\n* Constructors and Assignment::\n@end menu\n\n@node Constructors and Assignment\n@section Constructors and Assignment\n\n@deftypefn Constructor {} Array<T> (void)\nCreate an array with no elements.\n@end deftypefn\n\n@deftypefn Constructor {} Array<T> (int @var{n} [, const T &@var{val}])\nCreate an array with @var{n} elements.  If the optional argument\n@var{val} is supplied, the elements are initialized to @var{val};\notherwise, they are left uninitialized.  If @var{n} is less than zero,\nthe current error handler is invoked (@pxref{Error Handling}).\n@end deftypefn\n\n@deftypefn Constructor {} Array<T> (const Array<T> &@var{a})\nCreate a copy of the @var{Array<T>} object @var{a}.  Memory for the\n@var{Array<T>} class is managed using a reference counting scheme, so\nthe cost of this operation is independent of the size of the array.\n@end deftypefn\n\n@deftypeop Assignment Array<T> Array<T>& {operator =} (const Array<T> &@var{a})\nAssignment operator.  Memory for the @var{Array<T>} class is managed\nusing a reference counting scheme, so the cost of this operation is\nindependent of the size of the array.\n@end deftypeop\n\n@deftypemethod Array<T> int capacity (void) const\n@deftypemethodx Array<T> int length (void) const\nReturn the length of the array.\n@end deftypemethod\n\n@deftypemethod Array<T> T& elem (int @var{n})\n@deftypemethodx Array<T> T& checkelem (int @var{n})\nIf @var{n} is within the bounds of the array, return a reference to the\nelement indexed by @var{n}; otherwise, the current error handler is\ninvoked (@pxref{Error Handling}).\n@end deftypemethod\n\n@deftypeop Indexing Array<T> T& {operator ()} (int @var{n})\n@end deftypeop\n\n@deftypemethod Array<T> T elem (int @var{n}) const\n@deftypemethodx Array<T> T checkelem (int @var{n}) const\nIf @var{n} is within the bounds of the array, return the value indexed\nby @var{n}; otherwise, call the current error handler.\n@xref{Error Handling}.\n@end deftypemethod\n\n@deftypeop Indexing Array<T> T {operator ()} (int @var{n}) const\n@end deftypeop\n\n@deftypemethod Array<T> T& xelem (int @var{n})\n@deftypemethodx Array<T> T xelem (int @var{n}) const\nReturn a reference to, or the value of, the element indexed by @var{n}.\nThese methods never perform bounds checking.\n@end deftypemethod\n\n@deftypemethod Array<T> void resize {(int @var{n} [, const T &@var{val}])}\nChange the size of the array to be @var{n} elements.  All elements are\nunchanged, except that if @var{n} is greater than the current size and\nthe optional argument @var{val} is provided, the additional elements are\ninitialized to @var{val}; otherwise, any additional elements are left\nuninitialized.  In the current implementation, if @var{n} is less than\nthe current size, the length is updated but no memory is released.\n@end deftypemethod\n\n@deftypemethod Array<T> {const T*} data (void) const\n@end deftypemethod\n\n@c Should this be public?\n@c\n@c T *fortran_vec (void)\n\n@deftypefn Constructor {} Array2<T> Array2<T> Array2 (void)\n@deftypefnx Constructor {} Array2<T> (int @var{n}, int @var{m})\n@deftypefnx Constructor {} Array2<T> (int @var{n}, int @var{m}, const T &@var{val})\n@deftypefnx Constructor {} Array2<T> (const Array2<T> &@var{a})\n@deftypefnx Constructor {} Array2<T> (const DiagArray<T> &@var{a})\n@end deftypefn\n\n@deftypeop Assignment Array2<T> Array2<T>& {operator =} (const Array2<T> &@var{a})\n@end deftypeop\n\n@deftypemethod Array2<T> int dim1 (void) const\n@deftypemethodx Array2<T> int rows (void) const\n@end deftypemethod\n\n@deftypemethod Array2<T> int dim2 (void) const\n@deftypemethodx Array2<T> int cols (void) const\n@deftypemethodx Array2<T> int columns (void) const\n@end deftypemethod\n\n@deftypemethod Array2<T> T& elem (int @var{i}, int @var{j})\n@deftypemethodx Array2<T> T& checkelem (int @var{i}, int @var{j})\n@end deftypemethod\n\n@deftypeop Indexing Array2<T> T& {operator ()} (int @var{i}, int @var{j})\n@end deftypeop\n\n@c This needs to be fixed.\n@c\n@c T& xelem (int i, int j)\n@c\n@c T elem (int i, int j) const\n@c T checkelem (int i, int j) const\n@c T operator () (int i, int j) const\n\n@deftypemethod Array2<T> void resize (int @var{n}, int @var{m})\n@deftypemethodx Array2<T> void resize (int @var{n}, int @var{m}, const T &@var{val})\n@end deftypemethod\n\n@deftypefn Constructor {} Array3<T> (void)\n@deftypefnx Constructor {} Array3<T> (int @var{n}, int @var{m}, int @var{k})\n@deftypefnx Constructor {} Array3<T> (int @var{n}, int @var{m}, int @var{k}, const T &@var{val})\n@deftypefnx Constructor {} Array3<T> (const Array3<T> &@var{a})\n@end deftypefn\n\n@deftypeop Assignment Array3<T> Array3<T>& {operator =} (const Array3<T> &@var{a})\n@end deftypeop\n\n@deftypemethod Array3<T> int dim1 (void) const\n@deftypemethodx Array3<T> int dim2 (void) const\n@deftypemethodx Array3<T> int dim3 (void) const\n@end deftypemethod\n\n@deftypemethod Array3<T> T& elem (int @var{i}, int @var{j}, int @var{k})\n@deftypemethodx Array3<T> T& checkelem (int @var{i}, int @var{j}, int @var{k})\n@end deftypemethod\n\n@deftypeop Indexing Array3<T> T& {operator ()} (int @var{i}, int @var{j}, int @var{k})\n@end deftypeop\n\n@c This needs to be fixed.\n@c\n@c T& xelem (int i, int j, int k)\n@c\n@c T elem (int i, int j, int k) const\n@c T checkelem (int i, int j, int k) const\n@c T operator () (int i, int j, int k) const\n\n@deftypemethod Array3<T> void resize (int @var{n}, int @var{m}, int @var{k})\n@deftypemethodx Array3<T> void resize (int @var{n}, int @var{m}, int @var{k}, const T &@var{val})\n@end deftypemethod\n\n@deftypefn Constructor {} DiagArray<T> (void)\n@deftypefnx Constructor {} DiagArray<T> (int @var{n})\n@deftypefnx Constructor {} DiagArray<T> (int @var{n}, const T &@var{val})\n@deftypefnx Constructor {} DiagArray<T> (int @var{r}, int @var{c})\n@deftypefnx Constructor {} DiagArray<T> (int @var{r}, int @var{c}, const T &@var{val})\n@deftypefnx Constructor {} DiagArray<T> (const Array<T> &@var{a})\n@deftypefnx Constructor {} DiagArray<T> (const DiagArray<T> &@var{a})\n@end deftypefn\n\n@deftypeop Assignment DiagArray<T>& {} {operator =} (const DiagArray<T> &@var{a})\n@end deftypeop\n\n@deftypemethod DiagArray<T> int dim1 (void) const\n@deftypemethodx DiagArray<T> int rows (void) const\n@end deftypemethod\n\n@deftypemethod DiagArray<T> int dim2 (void) const\n@deftypemethodx DiagArray<T> int cols (void) const\n@deftypemethodx DiagArray<T> int columns (void) const\n@end deftypemethod\n\n@deftypemethod DiagArray<T> T& elem (int @var{r}, int @var{c})\n@deftypemethodx DiagArray<T> T& checkelem (int @var{r}, int @var{c})\n@end deftypemethod\n\n@deftypeop Indexing DiagArray<T> T& {operator ()} (int @var{r}, int @var{c})\n@end deftypeop\n\n@c This needs to be fixed.\n@c\n@c T& xelem (int r, int c)\n@c\n@c T elem (int r, int c) const\n@c T checkelem (int r, int c) const\n@c T operator () (int r, int c) const\n\n@deftypemethod DiagArray<T> void resize (int @var{n}, int @var{m})\n@deftypemethodx DiagArray<T> void resize (int @var{n}, int @var{m}, const T &@var{val})\n@end deftypemethod\n"
  },
  {
    "path": "doc/liboctave/bugs.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Bugs\n@chapter Bugs\n@cindex bugs, known\n@cindex installation trouble\n@cindex known causes of trouble\n@cindex troubleshooting\n"
  },
  {
    "path": "doc/liboctave/cp-idx.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Concept Index\n@unnumbered Concept Index\n\n@printindex cp\n"
  },
  {
    "path": "doc/liboctave/dae.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Differential Algebraic Equations\n@chapter Differential Algebraic Equations\n@cindex DAE\n\n@deftypefn  {} {} DAE (void)\n@deftypefnx  {} {} DAE (int @var{n})\n@deftypefnx  {} {} DAE (const ColumnVector &@var{x}, double @var{time}, DAEFunc &@var{f})\n@deftypefnx  {} {} DAE (const ColumnVector &@var{x}, ColumnVector &@var{xdot}, double @var{time}, DAEFunc &@var{f})\n@end deftypefn\n\n@deftypefn {} ColumnVector deriv (void)\n@end deftypefn\n\n@deftypefn {} {virtual void} initialize (const ColumnVector &@var{x}, double @var{t})\n@deftypefnx {} {virtual void} initialize (const ColumnVector &@var{x}, ColumnVector &@var{xdot}, double @var{t})\n@end deftypefn\n\n@deftypefn {} ColumnVector integrate (double @var{t})\n@end deftypefn\n\n@deftypefn {} Matrix integrate (const ColumnVector &@var{tout}, Matrix &@var{xdot_out})\n@deftypefnx {} Matrix integrate (const ColumnVector &@var{tout}, Matrix &@var{xdot_out}, const ColumnVector &@var{tcrit})\n@end deftypefn\n"
  },
  {
    "path": "doc/liboctave/diffeq.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Ordinary Differential Equations\n@chapter Ordinary Differential Equations\n@cindex ODE\n\n@deftypefn  {} {} ODE_options (void)\n@deftypefnx  {} {} ODE_options (const ODE_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} ODE_options& {operator =} (const ODE_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} void init (void)\n@end deftypefn\n\n@deftypefn {} void copy (const ODE_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} void set_default_options (void)\n@end deftypefn\n\n@deftypefn {} void set_absolute_tolerance (double @var{val})\n@end deftypefn\n\n@deftypefn {} void set_initial_step_size (double @var{val})\n@end deftypefn\n\n@deftypefn {} void set_maximum_step_size (double @var{val})\n@end deftypefn\n\n@deftypefn {} void set_minimum_step_size (double @var{val})\n@end deftypefn\n\n@deftypefn {} void set_relative_tolerance (double @var{val})\n@end deftypefn\n\n@deftypefn {} double absolute_tolerance (void)\n@deftypefnx {} double initial_step_size (void)\n@deftypefnx {} double maximum_step_size (void)\n@deftypefnx {} double minimum_step_size (void)\n@deftypefnx {} double relative_tolerance (void)\n@end deftypefn\n\n@deftypefn  {} {} ODE (void)\n@deftypefnx  {} {} ODE (int @var{n})\n@deftypefnx  {} {} ODE (const ColumnVector &@var{state}, double @var{time}, const ODEFunc &@var{f})\n@end deftypefn\n\n@deftypefn {} {virtual int} size (void) const\n@end deftypefn\n\n@deftypefn {} {virtual ColumnVector} state (void) const\n@end deftypefn\n\n@deftypefn {} {virtual double} time (void) const\n@end deftypefn\n\n@deftypefn {} {virtual void} force_restart (void)\n@end deftypefn\n\n@deftypefn {} {virtual void} initialize (const ColumnVector &@var{x}, double @var{t})\n@end deftypefn\n\n@deftypefn {} {virtual void} set_stop_time (double @var{t})\n@end deftypefn\n\n@deftypefn {} {virtual void} clear_stop_time (void)\n@end deftypefn\n\n@deftypefn {} {virtual ColumnVector} integrate (double @var{t})\n@end deftypefn\n\n@deftypefn {} void integrate (int @var{nsteps}, double @var{tstep}, ostream &@var{s})\n@end deftypefn\n\n@deftypefn {} Matrix integrate (const ColumnVector &@var{tout})\n@deftypefnx {} Matrix integrate (const ColumnVector &@var{tout}, const ColumnVector &@var{tcrit})\n@end deftypefn\n"
  },
  {
    "path": "doc/liboctave/error.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Error Handling\n@chapter Error Handling\n"
  },
  {
    "path": "doc/liboctave/factor.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Matrix Factorizations\n@chapter Matrix Factorizations\n@cindex matrix factorizations\n@cindex factorizations\n\n@deftypefn  {} {} AEPBALANCE (void)\n@deftypefnx  {} {} AEPBALANCE (const Matrix &@var{a}, const char *@var{balance_job})\n@deftypefnx  {} {} AEPBALANCE (const AEPBALANCE &@var{a})\n@end deftypefn\n\n@deftypefn {} AEPBALANCE& {operator =} (const AEPBALANCE &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix balanced_matrix (void) const\n@deftypefnx {} Matrix balancing_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const AEPBALANCE &@var{a})\n@end deftypefn\n\n@deftypefn {} {} ComplexAEPBALANCE (void)\n@deftypefnx {} {} ComplexAEPBALANCE (const ComplexMatrix &@var{a}, const char *@var{balance_job})\n@deftypefnx {} {} ComplexAEPBALANCE (const ComplexAEPBALANCE &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexAEPBALANCE& {operator =} (const ComplexAEPBALANCE &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix balanced_matrix (void) const\n@deftypefnx {} ComplexMatrix balancing_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexAEPBALANCE &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} DET (void)\n@deftypefnx  {} {} DET (const DET &@var{a})\n@end deftypefn\n\n@deftypefn {} DET& {operator =} (const DET &@var{a})\n@end deftypefn\n\n@deftypefn {} int value_will_overflow (void) const\n@deftypefnx {} int value_will_underflow (void) const\n@end deftypefn\n\n@deftypefn {} double coefficient (void) const\n@deftypefnx {} int exponent (void) const\n@deftypefnx {} double value (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const DET &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexDET (void)\n@deftypefnx  {} {} ComplexDET (const ComplexDET &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexDET& {operator =} (const ComplexDET &@var{a})\n@end deftypefn\n\n@deftypefn {} int value_will_overflow (void) const\n@deftypefnx {} int value_will_underflow (void) const\n@end deftypefn\n\n@deftypefn {} Complex coefficient (void) const\n@deftypefnx {} int exponent (void) const\n@deftypefnx {} Complex value (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexDET &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} GEPBALANCE (void)\n@deftypefnx  {} {} GEPBALANCE (const Matrix &@var{a}, const Matrix &, const char *@var{balance_job})\n@deftypefnx  {} {} GEPBALANCE (const GEPBALANCE &@var{a})\n@end deftypefn\n\n@deftypefn {} GEPBALANCE& {operator =} (const GEPBALANCE &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix balanced_a_matrix (void) const\n@deftypefnx {} Matrix balanced_b_matrix (void) const\n@deftypefnx {} Matrix left_balancing_matrix (void) const\n@deftypefnx {} Matrix right_balancing_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const GEPBALANCE &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} CHOL (void)\n@deftypefnx  {} {} CHOL (const Matrix &@var{a})\n@deftypefnx  {} {} CHOL (const Matrix &@var{a}, int &@var{info})\n@deftypefnx  {} {} CHOL (const CHOL &@var{a})\n@end deftypefn\n\n@deftypefn {} CHOL& {operator =} (const CHOL &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix chol_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const CHOL &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexCHOL (void)\n@deftypefnx  {} {} ComplexCHOL (const ComplexMatrix &@var{a})\n@deftypefnx  {} {} ComplexCHOL (const ComplexMatrix &@var{a}, int &@var{info})\n@deftypefnx  {} {} ComplexCHOL (const ComplexCHOL &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexCHOL& {operator =} (const ComplexCHOL &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix chol_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexCHOL &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} HESS (void)\n@deftypefnx  {} {} HESS (const Matrix &@var{a})\n@deftypefnx  {} {} HESS (const Matrix&a, int &@var{info})\n@deftypefnx  {} {} HESS (const HESS &@var{a})\n@end deftypefn\n\n@deftypefn {} HESS& {operator =} (const HESS &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix hess_matrix (void) const\n@deftypefnx {} Matrix unitary_hess_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const HESS &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexHESS (void)\n@deftypefnx  {} {} ComplexHESS (const ComplexMatrix &@var{a})\n@deftypefnx  {} {} ComplexHESS (const ComplexMatrix &@var{a}, int &@var{info})\n@deftypefnx  {} {} ComplexHESS (const ComplexHESS &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexHESS& {operator =} (const ComplexHESS &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix hess_matrix (void) const\n@deftypefnx {} ComplexMatrix unitary_hess_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexHESS &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} SCHUR (void)\n@deftypefnx  {} {} SCHUR (const Matrix &@var{a}, const char *@var{ord})\n@deftypefnx  {} {} SCHUR (const Matrix &@var{a}, const char *@var{ord}, int &@var{info})\n@deftypefnx  {} {} SCHUR (const SCHUR &@var{a}, const char *@var{ord})\n@end deftypefn\n\n@deftypefn {} SCHUR& {operator =} (const SCHUR &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix schur_matrix (void) const\n@deftypefnx {} Matrix unitary_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const SCHUR &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexSCHUR (void)\n@deftypefnx  {} {} ComplexSCHUR (const ComplexMatrix &@var{a}, const char *@var{ord})\n@deftypefnx  {} {} ComplexSCHUR (const ComplexMatrix &@var{a}, const char *@var{ord}, int &@var{info})\n@deftypefnx  {} {} ComplexSCHUR (const ComplexSCHUR &@var{a}, const char *@var{ord})\n@end deftypefn\n\n@deftypefn {} ComplexSCHUR& {operator =} (const ComplexSCHUR &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix schur_matrix (void) const\n@deftypefnx {} ComplexMatrix unitary_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexSCHUR &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} SVD (void)\n@deftypefnx  {} {} SVD (const Matrix &@var{a})\n@deftypefnx  {} {} SVD (const Matrix &@var{a}, int &@var{info})\n@deftypefnx  {} {} SVD (const SVD &@var{a})\n@end deftypefn\n\n@deftypefn {} SVD& {operator =} (const SVD &@var{a})\n@end deftypefn\n\n@deftypefn {} DiagMatrix singular_values (void) const\n@deftypefnx {} Matrix left_singular_matrix (void) const\n@deftypefnx {} Matrix right_singular_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const SVD &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexSVD (void)\n@deftypefnx  {} {} ComplexSVD (const ComplexMatrix &@var{a})\n@deftypefnx  {} {} ComplexSVD (const ComplexMatrix &@var{a}, int &@var{info})\n@deftypefnx  {} {} ComplexSVD (const ComplexSVD &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexSVD& {operator =} (const ComplexSVD &@var{a})\n@end deftypefn\n\n@deftypefn {} DiagMatrix singular_values (void) const\n@deftypefnx {} ComplexMatrix left_singular_matrix (void) const\n@deftypefnx {} ComplexMatrix right_singular_matrix (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexSVD &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} EIG (void)\n@deftypefnx  {} {} EIG (const Matrix &@var{a})\n@deftypefnx  {} {} EIG (const Matrix &@var{a}, int &@var{info})\n@deftypefnx  {} {} EIG (const ComplexMatrix &@var{a})\n@deftypefnx  {} {} EIG (const ComplexMatrix &@var{a}, int &@var{info})\n@deftypefnx  {} {} EIG (const EIG &@var{a})\n@end deftypefn\n\n@deftypefn {} EIG& {operator =} (const EIG &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector eigenvalues (void) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix eigenvectors (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const EIG &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} LU (void)\n@deftypefnx  {} {} LU (const Matrix &@var{a})\n@deftypefnx  {} {} LU (const LU &@var{a})\n@end deftypefn\n\n@deftypefn {} LU& {operator =} (const LU &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix L (void) const\n@deftypefnx {} Matrix U (void) const\n@deftypefnx {} Matrix P (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const LU &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexLU (void)\n@deftypefnx  {} {} ComplexLU (const ComplexMatrix &@var{a})\n@deftypefnx  {} {} ComplexLU (const ComplexLU &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexLU& {operator =} (const ComplexLU &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix L (void) const\n@deftypefnx {} ComplexMatrix U (void) const\n@deftypefnx {} Matrix P (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexLU &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} QR (void)\n@deftypefnx  {} {} QR (const Matrix &@var{A})\n@deftypefnx  {} {} QR (const QR &@var{a})\n@end deftypefn\n\n@deftypefn {} QR& {operator =} (const QR &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix Q (void) const\n@deftypefnx {} Matrix R (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const QR &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexQR (void)\n@deftypefnx  {} {} ComplexQR (const ComplexMatrix &@var{A})\n@deftypefnx  {} {} ComplexQR (const ComplexQR &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexQR& {operator =} (const ComplexQR &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix Q (void) const\n@deftypefnx {} ComplexMatrix R (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexQR &@var{a})\n@end deftypefn\n"
  },
  {
    "path": "doc/liboctave/fn-idx.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Function Index\n@unnumbered Function Index\n\n@printindex fn\n"
  },
  {
    "path": "doc/liboctave/gpl.texi",
    "content": "@c Copyright (C) 2007 Free Software Foundation, Inc.\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@cindex warranty\n@cindex copyright\n@node Copying\n@unnumbered GNU GENERAL PUBLIC LICENSE\n@center Version 3, 29 June 2007\n\n@display\nCopyright @copyright{} 2007 Free Software Foundation, Inc. @url{https://fsf.org/}\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n@end display\n\n@heading Preamble\n\nThe GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\nThe licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom\nto share and change all versions of a program---to make sure it remains\nfree software for all its users.  We, the Free Software Foundation,\nuse the GNU General Public License for most of our software; it\napplies also to any other work released this way by its authors.  You\ncan apply it to your programs, too.\n\nWhen we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\nTo protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you\nhave certain responsibilities if you distribute copies of the\nsoftware, or if you modify it: responsibilities to respect the freedom\nof others.\n\nFor example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too,\nreceive or can get the source code.  And you must show them these\nterms so they know their rights.\n\nDevelopers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\nFor the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\nSome devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the\nmanufacturer can do so.  This is fundamentally incompatible with the\naim of protecting users' freedom to change the software.  The\nsystematic pattern of such abuse occurs in the area of products for\nindividuals to use, which is precisely where it is most unacceptable.\nTherefore, we have designed this version of the GPL to prohibit the\npractice for those products.  If such problems arise substantially in\nother domains, we stand ready to extend this provision to those\ndomains in future versions of the GPL, as needed to protect the\nfreedom of users.\n\nFinally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish\nto avoid the special danger that patents applied to a free program\ncould make it effectively proprietary.  To prevent this, the GPL\nassures that patents cannot be used to render the program non-free.\n\nThe precise terms and conditions for copying, distribution and\nmodification follow.\n\n@heading TERMS AND CONDITIONS\n\n@enumerate 0\n@item Definitions.\n\n``This License'' refers to version 3 of the GNU General Public License.\n\n``Copyright'' also means copyright-like laws that apply to other kinds\nof works, such as semiconductor masks.\n\n``The Program'' refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as ``you''.  ``Licensees'' and\n``recipients'' may be individuals or organizations.\n\nTo ``modify'' a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of\nan exact copy.  The resulting work is called a ``modified version'' of\nthe earlier work or a work ``based on'' the earlier work.\n\nA ``covered work'' means either the unmodified Program or a work based\non the Program.\n\nTo ``propagate'' a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\nTo ``convey'' a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user\nthrough a computer network, with no transfer of a copy, is not\nconveying.\n\nAn interactive user interface displays ``Appropriate Legal Notices'' to\nthe extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n@item Source Code.\n\nThe ``source code'' for a work means the preferred form of the work for\nmaking modifications to it.  ``Object code'' means any non-source form\nof a work.\n\nA ``Standard Interface'' means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\nThe ``System Libraries'' of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n``Major Component'', in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\nThe ``Corresponding Source'' for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users can\nregenerate automatically from other parts of the Corresponding Source.\n\nThe Corresponding Source for a work in source code form is that same\nwork.\n\n@item Basic Permissions.\n\nAll rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\nYou may make, run and propagate covered works that you do not convey,\nwithout conditions so long as your license otherwise remains in force.\nYou may convey covered works to others for the sole purpose of having\nthem make modifications exclusively for you, or provide you with\nfacilities for running those works, provided that you comply with the\nterms of this License in conveying all material for which you do not\ncontrol copyright.  Those thus making or running the covered works for\nyou must do so exclusively on your behalf, under your direction and\ncontrol, on terms that prohibit them from making any copies of your\ncopyrighted material outside their relationship with you.\n\nConveying under any other circumstances is permitted solely under the\nconditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n@item Protecting Users' Legal Rights From Anti-Circumvention Law.\n\nNo covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\nWhen you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such\ncircumvention is effected by exercising rights under this License with\nrespect to the covered work, and you disclaim any intention to limit\noperation or modification of the work as a means of enforcing, against\nthe work's users, your or third parties' legal rights to forbid\ncircumvention of technological measures.\n\n@item Conveying Verbatim Copies.\n\nYou may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\nYou may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n@item Conveying Modified Source Versions.\n\nYou may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these\nconditions:\n\n@enumerate a\n@item\nThe work must carry prominent notices stating that you modified it,\nand giving a relevant date.\n\n@item\nThe work must carry prominent notices stating that it is released\nunder this License and any conditions added under section 7.  This\nrequirement modifies the requirement in section 4 to ``keep intact all\nnotices''.\n\n@item\nYou must license the entire work, as a whole, under this License to\nanyone who comes into possession of a copy.  This License will\ntherefore apply, along with any applicable section 7 additional terms,\nto the whole of the work, and all its parts, regardless of how they\nare packaged.  This License gives no permission to license the work in\nany other way, but it does not invalidate such permission if you have\nseparately received it.\n\n@item\nIf the work has interactive user interfaces, each must display\nAppropriate Legal Notices; however, if the Program has interactive\ninterfaces that do not display Appropriate Legal Notices, your work\nneed not make them do so.\n@end enumerate\n\nA compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n``aggregate'' if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n@item  Conveying Non-Source Forms.\n\nYou may convey a covered work in object code form under the terms of\nsections 4 and 5, provided that you also convey the machine-readable\nCorresponding Source under the terms of this License, in one of these\nways:\n\n@enumerate a\n@item\nConvey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by the\nCorresponding Source fixed on a durable physical medium customarily\nused for software interchange.\n\n@item\nConvey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by a written\noffer, valid for at least three years and valid for as long as you\noffer spare parts or customer support for that product model, to give\nanyone who possesses the object code either (1) a copy of the\nCorresponding Source for all the software in the product that is\ncovered by this License, on a durable physical medium customarily used\nfor software interchange, for a price no more than your reasonable\ncost of physically performing this conveying of source, or (2) access\nto copy the Corresponding Source from a network server at no charge.\n\n@item\nConvey individual copies of the object code with a copy of the written\noffer to provide the Corresponding Source.  This alternative is\nallowed only occasionally and noncommercially, and only if you\nreceived the object code with such an offer, in accord with subsection\n6b.\n\n@item\nConvey the object code by offering access from a designated place\n(gratis or for a charge), and offer equivalent access to the\nCorresponding Source in the same way through the same place at no\nfurther charge.  You need not require recipients to copy the\nCorresponding Source along with the object code.  If the place to copy\nthe object code is a network server, the Corresponding Source may be\non a different server (operated by you or a third party) that supports\nequivalent copying facilities, provided you maintain clear directions\nnext to the object code saying where to find the Corresponding Source.\nRegardless of what server hosts the Corresponding Source, you remain\nobligated to ensure that it is available for as long as needed to\nsatisfy these requirements.\n\n@item\nConvey the object code using peer-to-peer transmission, provided you\ninform other peers where the object code and Corresponding Source of\nthe work are being offered to the general public at no charge under\nsubsection 6d.\n\n@end enumerate\n\nA separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\nA ``User Product'' is either (1) a ``consumer product'', which means any\ntangible personal property which is normally used for personal,\nfamily, or household purposes, or (2) anything designed or sold for\nincorporation into a dwelling.  In determining whether a product is a\nconsumer product, doubtful cases shall be resolved in favor of\ncoverage.  For a particular product received by a particular user,\n``normally used'' refers to a typical or common use of that class of\nproduct, regardless of the status of the particular user or of the way\nin which the particular user actually uses, or expects or is expected\nto use, the product.  A product is a consumer product regardless of\nwhether the product has substantial commercial, industrial or\nnon-consumer uses, unless such uses represent the only significant\nmode of use of the product.\n\n``Installation Information'' for a User Product means any methods,\nprocedures, authorization keys, or other information required to\ninstall and execute modified versions of a covered work in that User\nProduct from a modified version of its Corresponding Source.  The\ninformation must suffice to ensure that the continued functioning of\nthe modified object code is in no case prevented or interfered with\nsolely because modification has been made.\n\nIf you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\nThe requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or\nupdates for a work that has been modified or installed by the\nrecipient, or for the User Product in which it has been modified or\ninstalled.  Access to a network may be denied when the modification\nitself materially and adversely affects the operation of the network\nor violates the rules and protocols for communication across the\nnetwork.\n\nCorresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n@item Additional Terms.\n\n``Additional permissions'' are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\nWhen you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders\nof that material) supplement the terms of this License with terms:\n\n@enumerate a\n@item\nDisclaiming warranty or limiting liability differently from the terms\nof sections 15 and 16 of this License; or\n\n@item\nRequiring preservation of specified reasonable legal notices or author\nattributions in that material or in the Appropriate Legal Notices\ndisplayed by works containing it; or\n\n@item\nProhibiting misrepresentation of the origin of that material, or\nrequiring that modified versions of such material be marked in\nreasonable ways as different from the original version; or\n\n@item\nLimiting the use for publicity purposes of names of licensors or\nauthors of the material; or\n\n@item\nDeclining to grant rights under trademark law for use of some trade\nnames, trademarks, or service marks; or\n\n@item\nRequiring indemnification of licensors and authors of that material by\nanyone who conveys the material (or modified versions of it) with\ncontractual assumptions of liability to the recipient, for any\nliability that these contractual assumptions directly impose on those\nlicensors and authors.\n@end enumerate\n\nAll other non-permissive additional terms are considered ``further\nrestrictions'' within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions; the\nabove requirements apply either way.\n\n@item Termination.\n\nYou may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\nHowever, if you cease all violation of this License, then your license\nfrom a particular copyright holder is reinstated (a) provisionally,\nunless and until the copyright holder explicitly and finally\nterminates your license, and (b) permanently, if the copyright holder\nfails to notify you of the violation by some reasonable means prior to\n60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\nTermination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n@item Acceptance Not Required for Having Copies.\n\nYou are not required to accept this License in order to receive or run\na copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n@item Automatic Licensing of Downstream Recipients.\n\nEach time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\nAn ``entity transaction'' is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n@item Patents.\n\nA ``contributor'' is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's ``contributor version''.\n\nA contributor's ``essential patent claims'' are all patent claims owned\nor controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, ``control'' includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\nIn the following three paragraphs, a ``patent license'' is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To ``grant'' such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  ``Knowingly relying'' means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\nA patent license is ``discriminatory'' if it does not include within the\nscope of its coverage, prohibits the exercise of, or is conditioned on\nthe non-exercise of one or more of the rights that are specifically\ngranted under this License.  You may not convey a covered work if you\nare a party to an arrangement with a third party that is in the\nbusiness of distributing software, under which you make payment to the\nthird party based on the extent of your activity of conveying the\nwork, and under which the third party grants, to any of the parties\nwho would receive the covered work from you, a discriminatory patent\nlicense (a) in connection with copies of the covered work conveyed by\nyou (or copies made from those copies), or (b) primarily for and in\nconnection with specific products or compilations that contain the\ncovered work, unless you entered into that arrangement, or that patent\nlicense was granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n@item No Surrender of Others' Freedom.\n\nIf conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey\na covered work so as to satisfy simultaneously your obligations under\nthis License and any other pertinent obligations, then as a\nconsequence you may not convey it at all.  For example, if you agree\nto terms that obligate you to collect a royalty for further conveying\nfrom those to whom you convey the Program, the only way you could\nsatisfy both those terms and this License would be to refrain entirely\nfrom conveying the Program.\n\n@item Use with the GNU Affero General Public License.\n\nNotwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n@item Revised Versions of this License.\n\nThe Free Software Foundation may publish revised and/or new versions\nof the GNU General Public License from time to time.  Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies that a certain numbered version of the GNU General Public\nLicense ``or any later version'' applies to it, you have the option of\nfollowing the terms and conditions either of that numbered version or\nof any later version published by the Free Software Foundation.  If\nthe Program does not specify a version number of the GNU General\nPublic License, you may choose any version ever published by the Free\nSoftware Foundation.\n\nIf the Program specifies that a proxy can decide which future versions\nof the GNU General Public License can be used, that proxy's public\nstatement of acceptance of a version permanently authorizes you to\nchoose that version for the Program.\n\nLater license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n@item Disclaimer of Warranty.\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW@.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT\nWARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE@.  THE ENTIRE RISK AS TO THE QUALITY AND\nPERFORMANCE OF THE PROGRAM IS WITH YOU@.  SHOULD THE PROGRAM PROVE\nDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR\nCORRECTION.\n\n@item Limitation of Liability.\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR\nCONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES\nARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT\nNOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR\nLOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM\nTO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER\nPARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n@item Interpretation of Sections 15 and 16.\n\nIf the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n@end enumerate\n\n@heading END OF TERMS AND CONDITIONS\n\n@heading How to Apply These Terms to Your New Programs\n\nIf you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these\nterms.\n\nTo do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe ``copyright'' line and a pointer to where the full notice is found.\n\n@smallexample\n@var{one line to give the program's name and a brief idea of what it does.}\nCopyright (C) @var{year} @var{name of author}\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or (at\nyour option) any later version.\n\nThis program is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE@.  See the GNU\nGeneral Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see @url{https://www.gnu.org/licenses/}.\n@end smallexample\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n@smallexample\n@var{program} Copyright (C) @var{year} @var{name of author}\nThis program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}.\nThis is free software, and you are welcome to redistribute it\nunder certain conditions; type @samp{show c} for details.\n@end smallexample\n\nThe hypothetical commands @samp{show w} and @samp{show c} should show\nthe appropriate parts of the General Public License.  Of course, your\nprogram's commands might be different; for a GUI interface, you would\nuse an ``about box''.\n\nYou should also get your employer (if you work as a programmer) or school,\nif any, to sign a ``copyright disclaimer'' for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n@url{https://www.gnu.org/licenses/}.\n\nThe GNU General Public License does not permit incorporating your\nprogram into proprietary programs.  If your program is a subroutine\nlibrary, you may consider it more useful to permit linking proprietary\napplications with the library.  If this is what you want to do, use\nthe GNU Lesser General Public License instead of this License.  But\nfirst, please read @url{https://www.gnu.org/licenses/why-not-lgpl.html}.\n"
  },
  {
    "path": "doc/liboctave/install.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Installation\n@chapter Installation\n@cindex installation\n"
  },
  {
    "path": "doc/liboctave/intro.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Introduction\n@chapter A Brief Introduction to Octave\n@cindex introduction\n\nThis manual documents how to run, install and port Octave's C++ classes,\nand how to report bugs.\n"
  },
  {
    "path": "doc/liboctave/liboctave.texi",
    "content": "% Copyright (C) 1996-2026 The Octave Project Developers\n%\n% This file is part of Octave.\n%\n% Octave is free software: you can redistribute it and/or modify it\n% under the terms of the GNU General Public License as published by\n% the Free Software Foundation, either version 3 of the License, or\n% (at your option) any later version.\n%\n% Octave is distributed in the hope that it will be useful, but\n% WITHOUT ANY WARRANTY; without even the implied warranty of\n% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n% GNU General Public License for more details.\n%\n% You should have received a copy of the GNU General Public License\n% along with Octave; see the file COPYING.  If not, see\n% <https://www.gnu.org/licenses/>.\n\n\n\\input texinfo\n@setfilename liboctave.info\n\n@dircategory Math\n@direntry\n* liboctave: (liboctave).       Octave C++ Classes\n@end direntry\n\n@c @smallbook\n@c @setchapternewpage odd\n@c @cropmarks\n@c @finalout\n\n@c Smaller amounts of whitespace for the 8.5 by 11 inch format.\n@tex\n\\global\\chapheadingskip = 15pt plus 4pt minus 2pt\n\\global\\secheadingskip = 12pt plus 3pt minus 2pt\n\\global\\subsecheadingskip = 9pt plus 2pt minus 2pt\n\\global\\parskip 6pt plus 1pt\n@end tex\n\n@iftex\n@set DONTINCLUDEGPL\n@end iftex\n\n@defindex op\n\n@c The version.texi file doesn't include a chapter, so it must not be\n@c included if you want to run the Emacs function\n@c texinfo-multiple-files-update.\n@include version-liboctave.texi\n\n@settitle Octave C++ Classes\n\n@ifnottex\n\nCopyright (C) 1996-2026 The Octave Project Developers\n\nPermission is granted to make and distribute verbatim copies of\nthis manual provided the copyright notice and this permission notice\nare preserved on all copies.\n\n@ignore\nPermission is granted to process this file through Tex and print the\nresults, provided the printed document carries copying permission\nnotice identical to this one except for the removal of this paragraph\n(this paragraph not being relevant to the printed manual).\n\n@end ignore\nPermission is granted to copy and distribute modified versions of\nthis manual under the conditions for verbatim copying, provided that\nthe entire resulting derived work is distributed under the terms of\na permission notice identical to this one.\n\nPermission is granted to copy and distribute translations of this\nmanual into another language, under the above conditions for\nmodified versions.\n@end ifnottex\n\n@titlepage\n@title Octave C++ Classes\n@subtitle Edition 1.0 for Octave version @value{VERSION}\n@author The Octave Project Developers\n@page\n@vskip 0pt plus 1filll\nCopyright @copyright{} 1996-2026 The Octave Project Developers.\n\nThis is the first edition of the documentation for Octave's C++ classes,\nand is consistent with version @value{VERSION} of Octave.\n\nPermission is granted to make and distribute verbatim copies of\nthis manual provided the copyright notice and this permission notice\nare preserved on all copies.\n\nPermission is granted to copy and distribute modified versions of this\nmanual under the conditions for verbatim copying, provided that the entire\nresulting derived work is distributed under the terms of a permission\nnotice identical to this one.\n\nPermission is granted to copy and distribute translations of this manual\ninto another language, under the same conditions as for modified versions.\n@end titlepage\n\n@contents\n\n@ifnottex\n@node Top\n@top\n\nThis manual documents how to use, install and port Octave's C++ class\nlibrary, and how to report bugs.  It corresponds to Octave version\n@value{VERSION}.\n@end ifnottex\n\n@c ------------------------------------------------------------------------\n\n@menu\n* Acknowledgements::\n* Copying::\n* Introduction::\n* Arrays::\n* Matrix and Vector Operations::\n* Matrix Factorizations::\n* Ranges::\n* Nonlinear Functions::\n* Nonlinear Equations::\n* Optimization::\n* Quadrature::\n* Ordinary Differential Equations::\n* Differential Algebraic Equations::\n* Error Handling::\n* Installation::\n* Bugs::\n* Concept Index::\n* Function Index::\n\n@detailmenu\n --- The Detailed Node Listing ---\n\nAcknowledgements\n\n* Contributors::                People who contributed to developing Octave.\n\nArrays\n\n* Constructors and Assignment::\n\nOptimization\n\n* Objective Functions::\n* Bounds::\n* Linear Constraints::\n* Nonlinear Constraints::\n* Quadratic Programming::\n* Nonlinear Programming::\n\nQuadrature\n\n* Collocation Weights::\n@end detailmenu\n@end menu\n\n@c ------------------------------------------------------------------------\n@c Chapters of manual.\n\n@include preface.texi\n@include gpl.texi\n@include intro.texi\n@include array.texi\n@include matvec.texi\n@include factor.texi\n@include range.texi\n@include nlfunc.texi\n@include nleqn.texi\n@include optim.texi\n@include quad.texi\n@include diffeq.texi\n@include dae.texi\n@include error.texi\n@include install.texi\n@include bugs.texi\n\n@c ------------------------------------------------------------------------\n@c Indices start here.\n\n@include cp-idx.texi\n@include fn-idx.texi\n\n@bye\n"
  },
  {
    "path": "doc/liboctave/matvec.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\nThe real and complex @code{ColumnVector} and @code{RowVector} classes\nall have the following functions.  These will eventually be part of an\n@code{MArray<T>} class, derived from the @code{Array<T>} class.  Then\nthe @code{ColumnVector} and @code{RowVector} classes will be derived\nfrom the @code{MArray<T>} class.\n\nElement by element vector by scalar ops.\n\n@deftypefn {} {RowVector} {operator +} (const RowVector &@var{a}, const double &@var{s})\n@deftypefnx {} {RowVector} {operator -} (const RowVector &@var{a}, const double &@var{s})\n@deftypefnx {} {RowVector} {operator *} (const RowVector &@var{a}, const double &@var{s})\n@deftypefnx {} {RowVector} {operator /} (const RowVector &@var{a}, const double &@var{s})\n@end deftypefn\n\nElement by element scalar by vector ops.\n\n@deftypefn {} {RowVector} {operator +} (const double &@var{s}, const RowVector &@var{a})\n@deftypefnx {} {RowVector} {operator -} (const double &@var{s}, const RowVector &@var{a})\n@deftypefnx {} {RowVector} {operator *} (const double &@var{s}, const RowVector &@var{a})\n@deftypefnx {} {RowVector} {operator /} (const double &@var{s}, const RowVector &@var{a})\n@end deftypefn\n\nElement by element vector by vector ops.\n\n@deftypefn {} {RowVector} {operator +} (const RowVector &@var{a}, const RowVector &@var{b})\n@deftypefnx {} {RowVector} {operator -} (const RowVector &@var{a}, const RowVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {RowVector} product (const RowVector &@var{a}, const RowVector &@var{b})\n@deftypefnx {} {RowVector} quotient (const RowVector &@var{a}, const RowVector &@var{b})\n@end deftypefn\n\nUnary MArray ops.\n\n@deftypefn {} {RowVector} {operator -} (const RowVector &@var{a})\n@end deftypefn\n\n@c ------------------------------------------------------------------------\n\nThe @code{Matrix} classes share the following functions.  These will\neventually be part of an @code{MArray2<T>} class, derived from the\n@code{Array2<T>} class.  Then the @code{Matrix} class will be derived\nfrom the @code{MArray<T>} class.\n\nElement by element matrix by scalar ops.\n\n@deftypefn {} {Matrix} {operator +} (const Matrix &@var{a}, const double &@var{s})\n@deftypefnx {} {Matrix} {operator -} (const Matrix &@var{a}, const double &@var{s})\n@deftypefnx {} {Matrix} {operator *} (const Matrix &@var{a}, const double &@var{s})\n@deftypefnx {} {Matrix} {operator /} (const Matrix &@var{a}, const double &@var{s})\n@end deftypefn\n\nElement by element scalar by matrix ops.\n\n@deftypefn {} {Matrix} {operator +} (const double &@var{s}, const Matrix &@var{a})\n@deftypefnx {} {Matrix} {operator -} (const double &@var{s}, const Matrix &@var{a})\n@deftypefnx {} {Matrix} {operator *} (const double &@var{s}, const Matrix &@var{a})\n@deftypefnx {} {Matrix} {operator /} (const double &@var{s}, const Matrix &@var{a})\n@end deftypefn\n\nElement by element matrix by matrix ops.\n\n@deftypefn {} {Matrix} {operator +} (const Matrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {Matrix} {operator -} (const Matrix &@var{a}, const Matrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {Matrix} product (const Matrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {Matrix} quotient (const Matrix &@var{a}, const Matrix &@var{b})\n@end deftypefn\n\nUnary matrix ops.\n\n@deftypefn {} {Matrix} {operator -} (const Matrix &@var{a})\n@end deftypefn\n\n@c ------------------------------------------------------------------------\n\nThe @code{DiagMatrix} classes share the following functions.  These will\neventually be part of an @code{MDiagArray<T>} class, derived from the\n@code{DiagArray<T>} class.  Then the @code{DiagMatrix} class will be\nderived from the @code{MDiagArray<T>} class.\n\nElement by element MDiagArray by scalar ops.\n\n@deftypefn {} {DiagMatrix} {operator *} (const DiagMatrix &@var{a}, const double &@var{s})\n@deftypefnx {} {DiagMatrix} {operator /} (const DiagMatrix &@var{a}, const double &@var{s})\n@end deftypefn\n\nElement by element scalar by MDiagArray ops.\n\n@deftypefn {} {DiagMatrix} {operator *} (const double &@var{s}, const DiagMatrix &@var{a})\n@end deftypefn\n\nElement by element MDiagArray by MDiagArray ops.\n\n@deftypefn {} {DiagMatrix} {operator +} (const DiagMatrix &@var{a}, const DiagMatrix &@var{b})\n@deftypefnx {} {DiagMatrix} {operator -} (const DiagMatrix &@var{a}, const DiagMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {DiagMatrix} product (const DiagMatrix &@var{a}, const DiagMatrix &@var{b})\n@end deftypefn\n\nUnary MDiagArray ops.\n\n@deftypefn {} {DiagMatrix} {operator -} (const DiagMatrix &@var{a})\n@end deftypefn\n\n@c ------------------------------------------------------------------------\n\n@node Matrix and Vector Operations\n@chapter Matrix and Vector Operations\n@cindex matrix manipulations\n@cindex vector manipulations\n\n@deftypefn  {} {} Matrix (void)\n@deftypefnx  {} {} Matrix (int @var{r}, int @var{c})\n@deftypefnx  {} {} Matrix (int @var{r}, int @var{c}, double @var{val})\n@deftypefnx  {} {} Matrix (const Array2<double> &@var{a})\n@deftypefnx  {} {} Matrix (const Matrix &@var{a})\n@deftypefnx  {} {} Matrix (const DiagArray<double> &@var{a})\n@deftypefnx  {} {} Matrix (const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix& {operator =} (const Matrix &@var{a})\n@end deftypefn\n\n@deftypefn {} int {operator ==} (const Matrix &@var{a}) const\n@deftypefnx {} int {operator !=} (const Matrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} Matrix& insert (const Matrix &@var{a}, int @var{r}, int @var{c})\n@deftypefnx {} Matrix& insert (const RowVector &@var{a}, int @var{r}, int @var{c})\n@deftypefnx {} Matrix& insert (const ColumnVector &@var{a}, int @var{r}, int @var{c})\n@deftypefnx {} Matrix& insert (const DiagMatrix &@var{a}, int @var{r}, int @var{c})\n@end deftypefn\n\n@deftypefn {} Matrix& fill (double @var{val})\n@deftypefnx {} Matrix& fill (double @var{val}, int r1, int c1, int r2, int c2)\n@end deftypefn\n\n@deftypefn {} Matrix append (const Matrix &@var{a}) const\n@deftypefnx {} Matrix append (const RowVector &@var{a}) const\n@deftypefnx {} Matrix append (const ColumnVector &@var{a}) const\n@deftypefnx {} Matrix append (const DiagMatrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} Matrix stack (const Matrix &@var{a}) const\n@deftypefnx {} Matrix stack (const RowVector &@var{a}) const\n@deftypefnx {} Matrix stack (const ColumnVector &@var{a}) const\n@deftypefnx {} Matrix stack (const DiagMatrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} Matrix transpose (void) const\n@end deftypefn\n\n@deftypefn {} Matrix extract (int r1, int c1, int r2, int c2) const\n@end deftypefn\n\n@deftypefn {} RowVector row (int @var{i}) const\n@deftypefnx {} RowVector row (char *s) const\n@end deftypefn\n\n@deftypefn {} ColumnVector column (int @var{i}) const\n@deftypefnx {} ColumnVector column (char *s) const\n@end deftypefn\n\n@deftypefn {} Matrix inverse (void) const\n@deftypefnx {} Matrix inverse (int &@var{info}) const\n@deftypefnx {} Matrix inverse (int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix fourier (void) const\n@deftypefnx {} ComplexMatrix ifourier (void) const\n@end deftypefn\n\n@deftypefn {} DET determinant (void) const\n@deftypefnx {} DET determinant (int &@var{info}) const\n@deftypefnx {} DET determinant (int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} Matrix solve (const Matrix &@var{b}) const\n@deftypefnx {} Matrix solve (const Matrix &@var{b}, int &@var{info}) const\n@deftypefnx {} Matrix solve (const Matrix &@var{b}, int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix solve (const ComplexMatrix &@var{b}) const\n@deftypefnx {} ComplexMatrix solve (const ComplexMatrix &@var{b}, int &@var{info}) const\n@deftypefnx {} ComplexMatrix solve (const ComplexMatrix &@var{b}, int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} ColumnVector solve (const ColumnVector &@var{b}) const\n@deftypefnx {} ColumnVector solve (const ColumnVector &@var{b}, int &@var{info}) const\n@deftypefnx {} ColumnVector solve (const ColumnVector &@var{b}, int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector solve (const ComplexColumnVector &@var{b}) const\n@deftypefnx {} ComplexColumnVector solve (const ComplexColumnVector &@var{b}, int &@var{info}) const\n@deftypefnx {} ComplexColumnVector solve (const ComplexColumnVector &@var{b}, int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} Matrix lssolve (const Matrix &@var{b}) const\n@deftypefnx {} Matrix lssolve (const Matrix &@var{b}, int &@var{info}) const\n@deftypefnx {} Matrix lssolve (const Matrix &@var{b}, int &@var{info}, int &@var{rank}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix lssolve (const ComplexMatrix &@var{b}) const\n@deftypefnx {} ComplexMatrix lssolve (const ComplexMatrix &@var{b}, int &@var{info}) const\n@deftypefnx {} ComplexMatrix lssolve (const ComplexMatrix &@var{b}, int &@var{info}, int &@var{rank}) const\n@end deftypefn\n\n@deftypefn {} ColumnVector lssolve (const ColumnVector &@var{b}) const\n@deftypefnx {} ColumnVector lssolve (const ColumnVector &@var{b}, int &@var{info}) const\n@deftypefnx {} ColumnVector lssolve (const ColumnVector &@var{b}, int &@var{info}, int &@var{rank}) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector lssolve (const ComplexColumnVector &@var{b}) const\n@deftypefnx {} ComplexColumnVector lssolve (const ComplexColumnVector &@var{b}, int &@var{info}) const\n@deftypefnx {} ComplexColumnVector lssolve (const ComplexColumnVector &@var{b}, int &@var{info}, int &@var{rank}) const\n@end deftypefn\n\n@deftypefn {} Matrix& {operator +=} (const Matrix &@var{a})\n@deftypefnx {} Matrix& {operator -=} (const Matrix &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix& {operator +=} (const DiagMatrix &@var{a})\n@deftypefnx {} Matrix& {operator -=} (const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix {operator !} (void) const\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const Matrix &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexMatrix} {operator -} (const Matrix &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexMatrix} {operator *} (const Matrix &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexMatrix} {operator /} (const Matrix &@var{a}, const Complex &@var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const Complex &@var{s}, const Matrix &@var{a})\n@deftypefnx {} {ComplexMatrix} {operator -} (const Complex &@var{s}, const Matrix &@var{a})\n@deftypefnx {} {ComplexMatrix} {operator *} (const Complex &@var{s}, const Matrix &@var{a})\n@deftypefnx {} {ComplexMatrix} {operator /} (const Complex &@var{s}, const Matrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {ColumnVector} {operator *} (const Matrix &@var{a}, const ColumnVector &@var{b})\n@deftypefnx {} {ComplexColumnVector} {operator *} (const Matrix &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {Matrix} {operator +} (const Matrix &@var{a}, const DiagMatrix &@var{b})\n@deftypefnx {} {Matrix} {operator -} (const Matrix &@var{a}, const DiagMatrix &@var{b})\n@deftypefnx {} {Matrix} {operator *} (const Matrix &@var{a}, const DiagMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const Matrix &@var{a}, const ComplexDiagMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator -} (const Matrix &@var{a}, const ComplexDiagMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator *} (const Matrix &@var{a}, const ComplexDiagMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {Matrix} {operator *} (const Matrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator *} (const Matrix &@var{a}, const ComplexMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const Matrix &@var{a}, const ComplexMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator -} (const Matrix &@var{a}, const ComplexMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} product (const Matrix &@var{a}, const ComplexMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} quotient (const Matrix &@var{a}, const ComplexMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {Matrix} map (d_d_Mapper @var{f}, const Matrix &@var{a})\n@deftypefnx {} void map (d_d_Mapper @var{f})\n@end deftypefn\n\n@deftypefn {} Matrix all (void) const\n@deftypefnx {} Matrix any (void) const\n@end deftypefn\n\n@deftypefn {} Matrix cumprod (void) const\n@deftypefnx {} Matrix cumsum (void) const\n@deftypefnx {} Matrix prod (void) const\n@deftypefnx {} Matrix sum (void) const\n@deftypefnx {} Matrix sumsq (void) const\n@end deftypefn\n\n@deftypefn {} ColumnVector diag (void) const\n@deftypefnx {} ColumnVector diag (int @var{k}) const\n@end deftypefn\n\n@deftypefn {} ColumnVector row_min (void) const\n@deftypefnx {} ColumnVector row_min_loc (void) const\n@end deftypefn\n\n@deftypefn {} ColumnVector row_max (void) const\n@deftypefnx {} ColumnVector row_max_loc (void) const\n@end deftypefn\n\n@deftypefn {} RowVector column_min (void) const\n@deftypefnx {} RowVector column_min_loc (void) const\n@end deftypefn\n\n@deftypefn {} RowVector column_max (void) const\n@deftypefnx {} RowVector column_max_loc (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const Matrix &@var{a})\n@deftypefnx {} {istream&} {operator >>} (istream &@var{is}, Matrix &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ColumnVector (void)\n@deftypefnx  {} {} ColumnVector (int @var{n})\n@deftypefnx  {} {} ColumnVector (int @var{n}, double @var{val})\n@deftypefnx  {} {} ColumnVector (const Array<double> &@var{a})\n@deftypefnx  {} {} ColumnVector (const ColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} ColumnVector& {operator =} (const ColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} int {operator ==} (const ColumnVector &@var{a}) const\n@deftypefnx {} int {operator !=} (const ColumnVector &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ColumnVector& insert (const ColumnVector &@var{a}, int @var{r})\n@end deftypefn\n\n@deftypefn {} ColumnVector& fill (double @var{val})\n@deftypefnx {} ColumnVector& fill (double @var{val}, int r1, int r2)\n@end deftypefn\n\n@deftypefn {} ColumnVector stack (const ColumnVector &@var{a}) const\n@end deftypefn\n\n@deftypefn {} RowVector transpose (void) const\n@end deftypefn\n\n@deftypefn {} ColumnVector extract (int r1, int r2) const\n@end deftypefn\n\n@deftypefn {} ColumnVector& {operator +=} (const ColumnVector &@var{a})\n@deftypefnx {} ColumnVector& {operator -=} (const ColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator +} (const ColumnVector &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexColumnVector} {operator -} (const ColumnVector &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexColumnVector} {operator *} (const ColumnVector &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexColumnVector} {operator /} (const ColumnVector &@var{a}, const Complex &@var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator +} (const Complex &@var{s}, const ColumnVector &@var{a})\n@deftypefnx {} {ComplexColumnVector} {operator -} (const Complex &@var{s}, const ColumnVector &@var{a})\n@deftypefnx {} {ComplexColumnVector} {operator *} (const Complex &@var{s}, const ColumnVector &@var{a})\n@deftypefnx {} {ComplexColumnVector} {operator /} (const Complex &@var{s}, const ColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} {Matrix} {operator *} (const ColumnVector &@var{a}, const RowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator *} (const ColumnVector &@var{a}, const ComplexRowVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator +} (const ComplexColumnVector &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator -} (const ComplexColumnVector &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} product (const ComplexColumnVector &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} quotient (const ComplexColumnVector &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ColumnVector} map (d_d_Mapper @var{f}, const ColumnVector &@var{a})\n@deftypefnx {} void map (d_d_Mapper @var{f})\n@end deftypefn\n\n@deftypefn {} double min (void) const\n@deftypefnx {} double max (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} RowVector (void)\n@deftypefnx  {} {} RowVector (int @var{n})\n@deftypefnx  {} {} RowVector (int @var{n}, double @var{val})\n@deftypefnx  {} {} RowVector (const Array<double> &@var{a})\n@deftypefnx  {} {} RowVector (const RowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} RowVector& {operator =} (const RowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} int {operator ==} (const RowVector &@var{a}) const\n@deftypefnx {} int {operator !=} (const RowVector &@var{a}) const\n@end deftypefn\n\n@deftypefn {} RowVector& insert (const RowVector &@var{a}, int @var{c})\n@end deftypefn\n\n@deftypefn {} RowVector& fill (double @var{val})\n@deftypefnx {} RowVector& fill (double @var{val}, int c1, int c2)\n@end deftypefn\n\n@deftypefn {} RowVector append (const RowVector &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ColumnVector transpose (void) const\n@end deftypefn\n\n@deftypefn {} RowVector extract (int c1, int c2) const\n@end deftypefn\n\n@deftypefn {} RowVector& {operator +=} (const RowVector &@var{a})\n@deftypefnx {} RowVector& {operator -=} (const RowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} {operator +} (const RowVector &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexRowVector} {operator -} (const RowVector &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexRowVector} {operator *} (const RowVector &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexRowVector} {operator /} (const RowVector &@var{a}, const Complex &@var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} {operator +} (const Complex &@var{s}, const RowVector &@var{a})\n@deftypefnx {} {ComplexRowVector} {operator -} (const Complex &@var{s}, const RowVector &@var{a})\n@deftypefnx {} {ComplexRowVector} {operator *} (const Complex &@var{s}, const RowVector &@var{a})\n@deftypefnx {} {ComplexRowVector} {operator /} (const Complex &@var{s}, const RowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} {double} {operator *} (const RowVector &@var{a}, ColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {Complex} {operator *} (const RowVector &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {RowVector} {operator *} (const RowVector &@var{a}, const Matrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} {operator *} (const RowVector &@var{a}, const ComplexMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} {operator +} (const RowVector &@var{a}, const ComplexRowVector &@var{b})\n@deftypefnx {} {ComplexRowVector} {operator -} (const RowVector &@var{a}, const ComplexRowVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} product (const RowVector &@var{a}, const ComplexRowVector &@var{b})\n@deftypefnx {} {ComplexRowVector} quotient (const RowVector &@var{a}, const ComplexRowVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {RowVector} map (d_d_Mapper @var{f}, const RowVector &@var{a})\n@deftypefnx {} void map (d_d_Mapper @var{f})\n@end deftypefn\n\n@deftypefn {} double min (void) const\n@deftypefnx {} double max (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const RowVector &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} DiagMatrix (void)\n@deftypefnx  {} {} DiagMatrix (int @var{n})\n@deftypefnx  {} {} DiagMatrix (int @var{n}, double @var{val})\n@deftypefnx  {} {} DiagMatrix (int @var{r}, int @var{c})\n@deftypefnx  {} {} DiagMatrix (int @var{r}, int @var{c}, double @var{val})\n@deftypefnx  {} {} DiagMatrix (const RowVector &@var{a})\n@deftypefnx  {} {} DiagMatrix (const ColumnVector &@var{a})\n@deftypefnx  {} {} DiagMatrix (const DiagArray<double> &@var{a})\n@deftypefnx  {} {} DiagMatrix (const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} DiagMatrix& {operator =} (const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} int {operator ==} (const DiagMatrix &@var{a}) const\n@deftypefnx {} int {operator !=} (const DiagMatrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} DiagMatrix& fill (double @var{val})\n@deftypefnx {} DiagMatrix& fill (double @var{val}, int @var{beg}, int @var{end})\n@deftypefnx {} DiagMatrix& fill (const ColumnVector &@var{a})\n@deftypefnx {} DiagMatrix& fill (const RowVector &@var{a})\n@deftypefnx {} DiagMatrix& fill (const ColumnVector &@var{a}, int @var{beg})\n@deftypefnx {} DiagMatrix& fill (const RowVector &@var{a}, int @var{beg})\n@end deftypefn\n\n@deftypefn {} DiagMatrix transpose (void) const\n@end deftypefn\n\n@deftypefn {} Matrix extract (int r1, int c1, int r2, int c2) const\n@end deftypefn\n\n@deftypefn {} RowVector row (int @var{i}) const\n@deftypefnx {} RowVector row (char *s) const\n@end deftypefn\n\n@deftypefn {} ColumnVector column (int @var{i}) const\n@deftypefnx {} ColumnVector column (char *s) const\n@end deftypefn\n\n@deftypefn {} DiagMatrix inverse (void) const\n@deftypefnx {} DiagMatrix inverse (int &@var{info}) const\n@end deftypefn\n\n@deftypefn {} DiagMatrix& {operator +=} (const DiagMatrix &@var{a})\n@deftypefnx {} DiagMatrix& {operator -=} (const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {Matrix} {operator +} (const DiagMatrix &@var{a}, double @var{s})\n@deftypefnx {} {Matrix} {operator -} (const DiagMatrix &@var{a}, double @var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const DiagMatrix &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexMatrix} {operator -} (const DiagMatrix &@var{a}, const Complex &@var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexDiagMatrix} {operator *} (const DiagMatrix &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexDiagMatrix} {operator /} (const DiagMatrix &@var{a}, const Complex &@var{s})\n@end deftypefn\n\n@deftypefn {} {Matrix} {operator +} (double @var{s}, const DiagMatrix &@var{a})\n@deftypefnx {} {Matrix} {operator -} (double @var{s}, const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const Complex &@var{s}, const DiagMatrix &@var{a})\n@deftypefnx {} {ComplexMatrix} {operator -} (const Complex &@var{s}, const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexDiagMatrix} {operator *} (const Complex &@var{s}, const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {ColumnVector} {operator *} (const DiagMatrix &@var{a}, const ColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator *} (const DiagMatrix &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexDiagMatrix} {operator +} (const DiagMatrix &@var{a}, const ComplexDiagMatrix &@var{b})\n@deftypefnx {} {ComplexDiagMatrix} {operator -} (const DiagMatrix &@var{a}, const ComplexDiagMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexDiagMatrix} product (const DiagMatrix &@var{a}, const ComplexDiagMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {Matrix} {operator +} (const DiagMatrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {Matrix} {operator -} (const DiagMatrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {Matrix} {operator *} (const DiagMatrix &@var{a}, const Matrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const DiagMatrix &@var{a}, const ComplexMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator -} (const DiagMatrix &@var{a}, const ComplexMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator *} (const DiagMatrix &@var{a}, const ComplexMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} ColumnVector diag (void) const\n@deftypefnx {} ColumnVector diag (int @var{k}) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexMatrix (void)\n@deftypefnx  {} {} ComplexMatrix (int @var{r}, int @var{c})\n@deftypefnx  {} {} ComplexMatrix (int @var{r}, int @var{c}, const Complex &@var{val})\n@deftypefnx  {} {} ComplexMatrix (const Matrix &@var{a})\n@deftypefnx  {} {} ComplexMatrix (const Array2<Complex> &@var{a})\n@deftypefnx  {} {} ComplexMatrix (const ComplexMatrix &@var{a})\n@deftypefnx  {} {} ComplexMatrix (const DiagMatrix &@var{a})\n@deftypefnx  {} {} ComplexMatrix (const DiagArray<Complex> &@var{a})\n@deftypefnx  {} {} ComplexMatrix (const ComplexDiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix& {operator =} (const ComplexMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} int {operator ==} (const ComplexMatrix &@var{a}) const\n@deftypefnx {} int {operator !=} (const ComplexMatrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix& insert (const Matrix &@var{a}, int @var{r}, int @var{c})\n@deftypefnx {} ComplexMatrix& insert (const RowVector &@var{a}, int @var{r}, int @var{c})\n@deftypefnx {} ComplexMatrix& insert (const ColumnVector &@var{a}, int @var{r}, int @var{c})\n@deftypefnx {} ComplexMatrix& insert (const DiagMatrix &@var{a}, int @var{r}, int @var{c})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix& insert (const ComplexMatrix &@var{a}, int @var{r}, int @var{c})\n@deftypefnx {} ComplexMatrix& insert (const ComplexRowVector &@var{a}, int @var{r}, int @var{c})\n@deftypefnx {} ComplexMatrix& insert (const ComplexColumnVector &@var{a}, int @var{r}, int @var{c})\n@deftypefnx {} ComplexMatrix& insert (const ComplexDiagMatrix &@var{a}, int @var{r}, int @var{c})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix& fill (double @var{val})\n@deftypefnx {} ComplexMatrix& fill (const Complex &@var{val})\n@deftypefnx {} ComplexMatrix& fill (double @var{val}, int r1, int c1, int r2, int c2)\n@deftypefnx {} ComplexMatrix& fill (const Complex &@var{val}, int r1, int c1, int r2, int c2)\n@end deftypefn\n\n@deftypefn {} ComplexMatrix append (const Matrix &@var{a}) const\n@deftypefnx {} ComplexMatrix append (const RowVector &@var{a}) const\n@deftypefnx {} ComplexMatrix append (const ColumnVector &@var{a}) const\n@deftypefnx {} ComplexMatrix append (const DiagMatrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix append (const ComplexMatrix &@var{a}) const\n@deftypefnx {} ComplexMatrix append (const ComplexRowVector &@var{a}) const\n@deftypefnx {} ComplexMatrix append (const ComplexColumnVector &@var{a}) const\n@deftypefnx {} ComplexMatrix append (const ComplexDiagMatrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix stack (const Matrix &@var{a}) const\n@deftypefnx {} ComplexMatrix stack (const RowVector &@var{a}) const\n@deftypefnx {} ComplexMatrix stack (const ColumnVector &@var{a}) const\n@deftypefnx {} ComplexMatrix stack (const DiagMatrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix stack (const ComplexMatrix &@var{a}) const\n@deftypefnx {} ComplexMatrix stack (const ComplexRowVector &@var{a}) const\n@deftypefnx {} ComplexMatrix stack (const ComplexColumnVector &@var{a}) const\n@deftypefnx {} ComplexMatrix stack (const ComplexDiagMatrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix transpose (void) const\n@end deftypefn\n\n@deftypefn {} {Matrix} real (const ComplexMatrix &@var{a})\n@deftypefnx {} {Matrix} imag (const ComplexMatrix &@var{a})\n@deftypefnx {} {ComplexMatrix} conj (const ComplexMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix extract (int r1, int c1, int r2, int c2) const\n@end deftypefn\n\n@deftypefn {} ComplexRowVector row (int @var{i}) const\n@deftypefnx {} ComplexRowVector row (char *s) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector column (int @var{i}) const\n@deftypefnx {} ComplexColumnVector column (char *s) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix inverse (void) const\n@deftypefnx {} ComplexMatrix inverse (int &@var{info}) const\n@deftypefnx {} ComplexMatrix inverse (int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix fourier (void) const\n@deftypefnx {} ComplexMatrix ifourier (void) const\n@end deftypefn\n\n@deftypefn {} ComplexDET determinant (void) const\n@deftypefnx {} ComplexDET determinant (int &@var{info}) const\n@deftypefnx {} ComplexDET determinant (int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix solve (const Matrix &@var{b}) const\n@deftypefnx {} ComplexMatrix solve (const Matrix &@var{b}, int &@var{info}) const\n@deftypefnx {} ComplexMatrix solve (const Matrix &@var{b}, int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix solve (const ComplexMatrix &@var{b}) const\n@deftypefnx {} ComplexMatrix solve (const ComplexMatrix &@var{b}, int &@var{info}) const\n@deftypefnx {} ComplexMatrix solve (const ComplexMatrix &@var{b}, int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector solve (const ComplexColumnVector &@var{b}) const\n@deftypefnx {} ComplexColumnVector solve (const ComplexColumnVector &@var{b}, int &@var{info}) const\n@deftypefnx {} ComplexColumnVector solve (const ComplexColumnVector &@var{b}, int &@var{info}, double &@var{rcond}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix lssolve (const ComplexMatrix &@var{b}) const\n@deftypefnx {} ComplexMatrix lssolve (const ComplexMatrix &@var{b}, int &@var{info}) const\n@deftypefnx {} ComplexMatrix lssolve (const ComplexMatrix &@var{b}, int &@var{info}, int &@var{rank}) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector lssolve (const ComplexColumnVector &@var{b}) const\n@deftypefnx {} ComplexColumnVector lssolve (const ComplexColumnVector &@var{b}, int &@var{info}) const\n@deftypefnx {} ComplexColumnVector lssolve (const ComplexColumnVector &@var{b}, int &@var{info}, int &@var{rank}) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix& {operator +=} (const DiagMatrix &@var{a})\n@deftypefnx {} ComplexMatrix& {operator -=} (const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix& {operator +=} (const ComplexDiagMatrix &@var{a})\n@deftypefnx {} ComplexMatrix& {operator -=} (const ComplexDiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix& {operator +=} (const Matrix &@var{a})\n@deftypefnx {} ComplexMatrix& {operator -=} (const Matrix &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix& {operator +=} (const ComplexMatrix &@var{a})\n@deftypefnx {} ComplexMatrix& {operator -=} (const ComplexMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} Matrix {operator !} (void) const\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const ComplexMatrix &@var{a}, double @var{s})\n@deftypefnx {} {ComplexMatrix} {operator -} (const ComplexMatrix &@var{a}, double @var{s})\n@deftypefnx {} {ComplexMatrix} {operator *} (const ComplexMatrix &@var{a}, double @var{s})\n@deftypefnx {} {ComplexMatrix} {operator /} (const ComplexMatrix &@var{a}, double @var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (double @var{s}, const ComplexMatrix &@var{a})\n@deftypefnx {} {ComplexMatrix} {operator -} (double @var{s}, const ComplexMatrix &@var{a})\n@deftypefnx {} {ComplexMatrix} {operator *} (double @var{s}, const ComplexMatrix &@var{a})\n@deftypefnx {} {ComplexMatrix} {operator /} (double @var{s}, const ComplexMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator *} (const ComplexMatrix &@var{a}, const ColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator *} (const ComplexMatrix &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const ComplexMatrix &@var{a}, const DiagMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator -} (const ComplexMatrix &@var{a}, const DiagMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator *} (const ComplexMatrix &@var{a}, const DiagMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const ComplexMatrix &@var{a}, const ComplexDiagMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator -} (const ComplexMatrix &@var{a}, const ComplexDiagMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator *} (const ComplexMatrix &@var{a}, const ComplexDiagMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const ComplexMatrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator -} (const ComplexMatrix &@var{a}, const Matrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator *} (const ComplexMatrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator *} (const ComplexMatrix &@var{a}, const ComplexMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} product (const ComplexMatrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {ComplexMatrix} quotient (const ComplexMatrix &@var{a}, const Matrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} map (c_c_Mapper @var{f}, const ComplexMatrix &@var{a})\n@deftypefnx {} {Matrix} map (d_c_Mapper @var{f}, const ComplexMatrix &@var{a})\n@deftypefnx {} void map (c_c_Mapper @var{f})\n@end deftypefn\n\n@deftypefn {} Matrix all (void) const\n@deftypefnx {} Matrix any (void) const\n@end deftypefn\n\n@deftypefn {} ComplexMatrix cumprod (void) const\n@deftypefnx {} ComplexMatrix cumsum (void) const\n@deftypefnx {} ComplexMatrix prod (void) const\n@deftypefnx {} ComplexMatrix sum (void) const\n@deftypefnx {} ComplexMatrix sumsq (void) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector diag (void) const\n@deftypefnx {} ComplexColumnVector diag (int @var{k}) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector row_min (void) const\n@deftypefnx {} ComplexColumnVector row_min_loc (void) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector row_max (void) const\n@deftypefnx {} ComplexColumnVector row_max_loc (void) const\n@end deftypefn\n\n@deftypefn {} ComplexRowVector column_min (void) const\n@deftypefnx {} ComplexRowVector column_min_loc (void) const\n@end deftypefn\n\n@deftypefn {} ComplexRowVector column_max (void) const\n@deftypefnx {} ComplexRowVector column_max_loc (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexMatrix &@var{a})\n@deftypefnx {} {istream&} {operator >>} (istream &@var{is}, ComplexMatrix &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexColumnVector (void)\n@deftypefnx  {} {} ComplexColumnVector (int @var{n})\n@deftypefnx  {} {} ComplexColumnVector (int @var{n}, const Complex &@var{val})\n@deftypefnx  {} {} ComplexColumnVector (const ColumnVector &@var{a})\n@deftypefnx  {} {} ComplexColumnVector (const Array<Complex> &@var{a})\n@deftypefnx  {} {} ComplexColumnVector (const ComplexColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector& {operator =} (const ComplexColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} int {operator ==} (const ComplexColumnVector &@var{a}) const\n@deftypefnx {} int {operator !=} (const ComplexColumnVector &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector& insert (const ColumnVector &@var{a}, int @var{r})\n@deftypefnx {} ComplexColumnVector& insert (const ComplexColumnVector &@var{a}, int @var{r})\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector& fill (double @var{val})\n@deftypefnx {} ComplexColumnVector& fill (const Complex &@var{val})\n@deftypefnx {} ComplexColumnVector& fill (double @var{val}, int r1, int r2)\n@deftypefnx {} ComplexColumnVector& fill (const Complex &@var{val}, int r1, int r2)\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector stack (const ColumnVector &@var{a}) const\n@deftypefnx {} ComplexColumnVector stack (const ComplexColumnVector &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexRowVector transpose (void) const\n@end deftypefn\n\n@deftypefn {} {ColumnVector} real (const ComplexColumnVector &@var{a})\n@deftypefnx {} {ColumnVector} imag (const ComplexColumnVector &@var{a})\n@deftypefnx {} {ComplexColumnVector} conj (const ComplexColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector extract (int r1, int r2) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector& {operator +=} (const ColumnVector &@var{a})\n@deftypefnx {} ComplexColumnVector& {operator -=} (const ColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector& {operator +=} (const ComplexColumnVector &@var{a})\n@deftypefnx {} ComplexColumnVector& {operator -=} (const ComplexColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator +} (const ComplexColumnVector &@var{a}, double @var{s})\n@deftypefnx {} {ComplexColumnVector} {operator -} (const ComplexColumnVector &@var{a}, double @var{s})\n@deftypefnx {} {ComplexColumnVector} {operator *} (const ComplexColumnVector &@var{a}, double @var{s})\n@deftypefnx {} {ComplexColumnVector} {operator /} (const ComplexColumnVector &@var{a}, double @var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator +} (double @var{s}, const ComplexColumnVector &@var{a})\n@deftypefnx {} {ComplexColumnVector} {operator -} (double @var{s}, const ComplexColumnVector &@var{a})\n@deftypefnx {} {ComplexColumnVector} {operator *} (double @var{s}, const ComplexColumnVector &@var{a})\n@deftypefnx {} {ComplexColumnVector} {operator /} (double @var{s}, const ComplexColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator *} (const ComplexColumnVector &@var{a}, const ComplexRowVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator +} (const ComplexColumnVector &@var{a}, const ColumnVector &@var{b})\n@deftypefnx {} {ComplexColumnVector} {operator -} (const ComplexColumnVector &@var{a}, const ColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} product (const ComplexColumnVector &@var{a}, const ColumnVector &@var{b})\n@deftypefnx {} {ComplexColumnVector} quotient (const ComplexColumnVector &@var{a}, const ColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} map (c_c_Mapper @var{f}, const ComplexColumnVector &@var{a})\n@deftypefnx {} {ColumnVector} map (d_c_Mapper @var{f}, const ComplexColumnVector &@var{a})\n@deftypefnx {} void map (c_c_Mapper @var{f})\n@end deftypefn\n\n@deftypefn {} Complex min (void) const\n@deftypefnx {} Complex max (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexColumnVector &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexRowVector (void)\n@deftypefnx  {} {} ComplexRowVector (int @var{n})\n@deftypefnx  {} {} ComplexRowVector (int @var{n}, const Complex &@var{val})\n@deftypefnx  {} {} ComplexRowVector (const RowVector &@var{a})\n@deftypefnx  {} {} ComplexRowVector (const Array<Complex> &@var{a})\n@deftypefnx  {} {} ComplexRowVector (const ComplexRowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexRowVector& {operator =} (const ComplexRowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} int {operator ==} (const ComplexRowVector &@var{a}) const\n@deftypefnx {} int {operator !=} (const ComplexRowVector &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexRowVector& insert (const RowVector &@var{a}, int @var{c})\n@deftypefnx {} ComplexRowVector& insert (const ComplexRowVector &@var{a}, int @var{c})\n@end deftypefn\n\n@deftypefn {} ComplexRowVector& fill (double @var{val})\n@deftypefnx {} ComplexRowVector& fill (const Complex &@var{val})\n@deftypefnx {} ComplexRowVector& fill (double @var{val}, int c1, int c2)\n@deftypefnx {} ComplexRowVector& fill (const Complex &@var{val}, int c1, int c2)\n@end deftypefn\n\n@deftypefn {} ComplexRowVector append (const RowVector &@var{a}) const\n@deftypefnx {} ComplexRowVector append (const ComplexRowVector &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector transpose (void) const\n@end deftypefn\n\n@deftypefn {} {RowVector} real (const ComplexRowVector &@var{a})\n@deftypefnx {} {RowVector} imag (const ComplexRowVector &@var{a})\n@deftypefnx {} {ComplexRowVector} conj (const ComplexRowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexRowVector extract (int c1, int c2) const\n@end deftypefn\n\n@deftypefn {} ComplexRowVector& {operator +=} (const RowVector &@var{a})\n@deftypefnx {} ComplexRowVector& {operator -=} (const RowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexRowVector& {operator +=} (const ComplexRowVector &@var{a})\n@deftypefnx {} ComplexRowVector& {operator -=} (const ComplexRowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} {operator +} (const ComplexRowVector &@var{a}, double @var{s})\n@deftypefnx {} {ComplexRowVector} {operator -} (const ComplexRowVector &@var{a}, double @var{s})\n@deftypefnx {} {ComplexRowVector} {operator *} (const ComplexRowVector &@var{a}, double @var{s})\n@deftypefnx {} {ComplexRowVector} {operator /} (const ComplexRowVector &@var{a}, double @var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} {operator +} (double @var{s}, const ComplexRowVector &@var{a})\n@deftypefnx {} {ComplexRowVector} {operator -} (double @var{s}, const ComplexRowVector &@var{a})\n@deftypefnx {} {ComplexRowVector} {operator *} (double @var{s}, const ComplexRowVector &@var{a})\n@deftypefnx {} {ComplexRowVector} {operator /} (double @var{s}, const ComplexRowVector &@var{a})\n@end deftypefn\n\n@deftypefn {} {Complex} {operator *} (const ComplexRowVector &@var{a}, const ColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {Complex} {operator *} (const ComplexRowVector &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} {operator *} (const ComplexRowVector &@var{a}, const ComplexMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} {operator +} (const ComplexRowVector &@var{a}, const RowVector &@var{b})\n@deftypefnx {} {ComplexRowVector} {operator -} (const ComplexRowVector &@var{a}, const RowVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} product (const ComplexRowVector &@var{a}, const RowVector &@var{b})\n@deftypefnx {} {ComplexRowVector} quotient (const ComplexRowVector &@var{a}, const RowVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexRowVector} map (c_c_Mapper @var{f}, const ComplexRowVector &@var{a})\n@deftypefnx {} {RowVector} map (d_c_Mapper @var{f}, const ComplexRowVector &@var{a})\n@deftypefnx {} void map (c_c_Mapper @var{f})\n@end deftypefn\n\n@deftypefn {} Complex min (void) const\n@deftypefnx {} Complex max (void) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexRowVector &@var{a})\n@end deftypefn\n\n@deftypefn  {} {} ComplexDiagMatrix (void)\n@deftypefnx  {} {} ComplexDiagMatrix (int @var{n})\n@deftypefnx  {} {} ComplexDiagMatrix (int @var{n}, const Complex &@var{val})\n@deftypefnx  {} {} ComplexDiagMatrix (int @var{r}, int @var{c})\n@deftypefnx  {} {} ComplexDiagMatrix (int @var{r}, int @var{c}, const Complex &@var{val})\n@deftypefnx  {} {} ComplexDiagMatrix (const RowVector &@var{a})\n@deftypefnx  {} {} ComplexDiagMatrix (const ComplexRowVector &@var{a})\n@deftypefnx  {} {} ComplexDiagMatrix (const ColumnVector &@var{a})\n@deftypefnx  {} {} ComplexDiagMatrix (const ComplexColumnVector &@var{a})\n@deftypefnx  {} {} ComplexDiagMatrix (const DiagMatrix &@var{a})\n@deftypefnx  {} {} ComplexDiagMatrix (const DiagArray<Complex> &@var{a})\n@deftypefnx  {} {} ComplexDiagMatrix (const ComplexDiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexDiagMatrix& {operator =} (const ComplexDiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} int {operator ==} (const ComplexDiagMatrix &@var{a}) const\n@deftypefnx {} int {operator !=} (const ComplexDiagMatrix &@var{a}) const\n@end deftypefn\n\n@deftypefn {} ComplexDiagMatrix& fill (double @var{val})\n@deftypefnx {} ComplexDiagMatrix& fill (const Complex &@var{val})\n@deftypefnx {} ComplexDiagMatrix& fill (double @var{val}, int @var{beg}, int @var{end})\n@deftypefnx {} ComplexDiagMatrix& fill (const Complex &@var{val}, int @var{beg}, int @var{end})\n@deftypefnx {} ComplexDiagMatrix& fill (const ColumnVector &@var{a})\n@deftypefnx {} ComplexDiagMatrix& fill (const ComplexColumnVector &@var{a})\n@deftypefnx {} ComplexDiagMatrix& fill (const RowVector &@var{a})\n@deftypefnx {} ComplexDiagMatrix& fill (const ComplexRowVector &@var{a})\n@deftypefnx {} ComplexDiagMatrix& fill (const ColumnVector &@var{a}, int @var{beg})\n@deftypefnx {} ComplexDiagMatrix& fill (const ComplexColumnVector &@var{a}, int @var{beg})\n@deftypefnx {} ComplexDiagMatrix& fill (const RowVector &@var{a}, int @var{beg})\n@deftypefnx {} ComplexDiagMatrix& fill (const ComplexRowVector &@var{a}, int @var{beg})\n@end deftypefn\n\n@deftypefn {} ComplexDiagMatrix transpose (void) const\n@end deftypefn\n\n@deftypefn {} {DiagMatrix} real (const ComplexDiagMatrix &@var{a})\n@deftypefnx {} {DiagMatrix} imag (const ComplexDiagMatrix &@var{a})\n@deftypefnx {} {ComplexDiagMatrix} conj (const ComplexDiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexMatrix extract (int r1, int c1, int r2, int c2) const\n@end deftypefn\n\n@deftypefn {} ComplexRowVector row (int @var{i}) const\n@deftypefnx {} ComplexRowVector row (char *s) const\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector column (int @var{i}) const\n@deftypefnx {} ComplexColumnVector column (char *s) const\n@end deftypefn\n\n@deftypefn {} ComplexDiagMatrix inverse (int &@var{info}) const\n@deftypefnx {} ComplexDiagMatrix inverse (void) const\n@end deftypefn\n\n@deftypefn {} ComplexDiagMatrix& {operator +=} (const DiagMatrix &@var{a})\n@deftypefnx {} ComplexDiagMatrix& {operator -=} (const DiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} ComplexDiagMatrix& {operator +=} (const ComplexDiagMatrix &@var{a})\n@deftypefnx {} ComplexDiagMatrix& {operator -=} (const ComplexDiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const ComplexDiagMatrix &@var{a}, double @var{s})\n@deftypefnx {} {ComplexMatrix} {operator -} (const ComplexDiagMatrix &@var{a}, double @var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const ComplexDiagMatrix &@var{a}, const Complex &@var{s})\n@deftypefnx {} {ComplexMatrix} {operator -} (const ComplexDiagMatrix &@var{a}, const Complex &@var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexDiagMatrix} {operator *} (const ComplexDiagMatrix &@var{a}, double @var{s})\n@deftypefnx {} {ComplexDiagMatrix} {operator /} (const ComplexDiagMatrix &@var{a}, double @var{s})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (double @var{s}, const ComplexDiagMatrix &@var{a})\n@deftypefnx {} {ComplexMatrix} {operator -} (double @var{s}, const ComplexDiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const Complex &@var{s}, const ComplexDiagMatrix &@var{a})\n@deftypefnx {} {ComplexMatrix} {operator -} (const Complex &@var{s}, const ComplexDiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexDiagMatrix} {operator *} (double @var{s}, const ComplexDiagMatrix &@var{a})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator *} (const ComplexDiagMatrix &@var{a}, const ColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexColumnVector} {operator *} (const ComplexDiagMatrix &@var{a}, const ComplexColumnVector &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexDiagMatrix} {operator +} (const ComplexDiagMatrix &@var{a}, const DiagMatrix &@var{b})\n@deftypefnx {} {ComplexDiagMatrix} {operator -} (const ComplexDiagMatrix &@var{a}, const DiagMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexDiagMatrix} product (const ComplexDiagMatrix &@var{a}, const DiagMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const ComplexDiagMatrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator -} (const ComplexDiagMatrix &@var{a}, const Matrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator *} (const ComplexDiagMatrix &@var{a}, const Matrix &@var{b})\n@end deftypefn\n\n@deftypefn {} {ComplexMatrix} {operator +} (const ComplexDiagMatrix &@var{a}, const ComplexMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator -} (const ComplexDiagMatrix &@var{a}, const ComplexMatrix &@var{b})\n@deftypefnx {} {ComplexMatrix} {operator *} (const ComplexDiagMatrix &@var{a}, const ComplexMatrix &@var{b})\n@end deftypefn\n\n@deftypefn {} ComplexColumnVector diag (void) const\n@deftypefnx {} ComplexColumnVector diag (int @var{k}) const\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const ComplexDiagMatrix &@var{a})\n@end deftypefn\n"
  },
  {
    "path": "doc/liboctave/module.mk",
    "content": "if AMCOND_BUILD_DOCS\n\nliboctave_TEXINFOS = \\\n  %reldir%/array.texi \\\n  %reldir%/bugs.texi \\\n  %reldir%/cp-idx.texi \\\n  %reldir%/dae.texi \\\n  %reldir%/diffeq.texi \\\n  %reldir%/error.texi \\\n  %reldir%/factor.texi \\\n  %reldir%/fn-idx.texi \\\n  %reldir%/gpl.texi \\\n  %reldir%/install.texi \\\n  %reldir%/intro.texi \\\n  %reldir%/matvec.texi \\\n  %reldir%/nleqn.texi \\\n  %reldir%/nlfunc.texi \\\n  %reldir%/ode.texi \\\n  %reldir%/optim.texi \\\n  %reldir%/preface.texi \\\n  %reldir%/quad.texi \\\n  %reldir%/range.texi\n\ninfo_TEXINFOS += \\\n  %reldir%/liboctave.texi\n\nINFO_DEPS += %reldir%/liboctave.info\nDVIS += %reldir%/liboctave.dvi\nPDFS += %reldir%/liboctave.pdf\nPSS += %reldir%/liboctave.ps\nHTMLS += %reldir%/liboctave.html\n\n%reldir%/liboctave.dvi: %reldir%/liboctave.texi $(srcdir)/%reldir%/version-liboctave.texi | %reldir%/$(am__dirstamp)\n\t$(AM_V_TEXI2DVI)TEXINPUTS=\"$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS\" \\\n\tMAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc/liboctave -I $(srcdir)/doc/liboctave' \\\n\t$(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \\\n\t`test -f '%reldir%/liboctave.texi' || echo '$(srcdir)/'`%reldir%/liboctave.texi\n\n%reldir%/liboctave.pdf: %reldir%/liboctave.texi $(srcdir)/%reldir%/version-liboctave.texi | %reldir%/$(am__dirstamp)\n\t$(AM_V_TEXI2PDF)TEXINPUTS=\"$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS\" \\\n\tMAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc/liboctave -I $(srcdir)/doc/liboctave' \\\n\t$(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \\\n\t`test -f '%reldir%/liboctave.texi' || echo '$(srcdir)/'`%reldir%/liboctave.texi\n\n%reldir%/liboctave.html: %reldir%/liboctave.texi $(srcdir)/%reldir%/version-liboctave.texi | %reldir%/$(am__dirstamp)\n\t$(AM_V_MAKEINFO)rm -rf $(@:.html=.htp)\n\t$(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I doc/liboctave -I $(srcdir)/doc/liboctave \\\n\t -o $(@:.html=.htp) `test -f '%reldir%/liboctave.texi' || echo '$(srcdir)/'`%reldir%/liboctave.texi; \\\n\tthen \\\n\t  rm -rf $@ && mv $(@:.html=.htp) $@; \\\n\telse \\\n\t  rm -rf $(@:.html=.htp); exit 1; \\\n\tfi\n\nDOC_TARGETS += \\\n  %reldir%/liboctave.info \\\n  %reldir%/liboctave.ps \\\n  %reldir%/liboctave.pdf \\\n  %reldir%/liboctave.html\n\ndoc_EXTRA_DIST += \\\n  $(liboctave_TEXINFOS) \\\n  %reldir%/liboctave.info \\\n  %reldir%/liboctave.dvi \\\n  %reldir%/liboctave.ps \\\n  %reldir%/liboctave.pdf \\\n  %reldir%/liboctave.html\n\n## The TeX software suite is used to create both PDF and PS output formats.\n## In order to avoid race conditions between simultaneous TeX commands, the\n## PDF and PS builds are forced to run serially through the following rule.\n%reldir%/liboctave.pdf: %reldir%/liboctave.ps\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nendif\n\ndoc-liboctave-clean:\n\trm -rf %reldir%/liboctave.t2d\n\trm -rf %reldir%/liboctave.t2p\n"
  },
  {
    "path": "doc/liboctave/nleqn.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Nonlinear Equations\n@chapter Nonlinear Equations\n@cindex nonlinear equations\n\n@deftypefn  {} {} NLEqn_options (void)\n@deftypefnx  {} {} NLEqn_options (const NLEqn_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} NLEqn_options& {operator =} (const NLEqn_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} void init (void)\n@end deftypefn\n\n@deftypefn {} void copy (const NLEqn_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} void set_default_options (void)\n@end deftypefn\n\n@deftypefn {} void set_tolerance (double @var{val})\n@end deftypefn\n\n@deftypefn {} double tolerance (void)\n@end deftypefn\n\n@deftypefn  {} {} NLEqn (void)\n@deftypefnx  {} {} NLEqn (const ColumnVector&, const @var{NLFunc})\n@deftypefnx  {} {} NLEqn (const NLEqn &@var{a})\n@end deftypefn\n\n@deftypefn {} NLEqn& {operator =} (const NLEqn &@var{a})\n@end deftypefn\n\n@deftypefn {} void resize (int @var{n})\n@end deftypefn\n\n@deftypefn {} void set_states (const ColumnVector &@var{x})\n@end deftypefn\n\n@deftypefn {} ColumnVector states (void) const\n@end deftypefn\n\n@deftypefn {} int size (void) const\n@end deftypefn\n\n@deftypefn {} ColumnVector solve (void)\n@deftypefnx {} ColumnVector solve (const ColumnVector &@var{x})\n@end deftypefn\n\n@deftypefn {} ColumnVector solve (int &@var{info})\n@deftypefnx{} ColumnVector solve (const ColumnVector &@var{x}, int &@var{info})\n@end deftypefn\n"
  },
  {
    "path": "doc/liboctave/nlfunc.texi",
    "content": "@c Copyright (C) 1997-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Nonlinear Functions\n@chapter Nonlinear Functions\n@cindex nonlinear functions\n\n@deftypefn  {} {} NLFunc (void)\n@deftypefnx  {} {} NLFunc (const @var{nonlinear_fcn})\n@deftypefnx  {} {} NLFunc (const @var{nonlinear_fcn}, const @var{jacobian_fcn})\n@deftypefnx  {} {} NLFunc (const NLFunc &@var{a})\n@end deftypefn\n\n@deftypefn {} NLFunc& {operator =} (const NLFunc &@var{a})\n@end deftypefn\n\n@deftypefn {} nonlinear_fcn function (void) const;\n@end deftypefn\n\n@deftypefn {} NLFunc& set_function (const nonlinear_fcn @var{f})\n@end deftypefn\n\n@deftypefn {} jacobian_fcn jacobian_function (void) const;\n@end deftypefn\n\n@deftypefn {} NLFunc& set_jacobian_function (const jacobian_fcn @var{j})\n@end deftypefn\n"
  },
  {
    "path": "doc/liboctave/ode.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Ordinary Differential Equations\n@chapter Ordinary Differential Equations\n@cindex ODE\n\n@deftypefn  {} {}ODE_options (void)\n@deftypefnx  {} {}ODE_options (const ODE_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} ODE_options& {operator =} (const ODE_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} void init (void)\n@end deftypefn\n\n@deftypefn {} void copy (const ODE_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} void set_default_options (void)\n@end deftypefn\n\n@deftypefn {} void set_absolute_tolerance (double @var{val})\n@end deftypefn\n\n@deftypefn {} void set_initial_step_size (double @var{val})\n@end deftypefn\n\n@deftypefn {} void set_maximum_step_size (double @var{val})\n@end deftypefn\n\n@deftypefn {} void set_minimum_step_size (double @var{val})\n@end deftypefn\n\n@deftypefn {} void set_relative_tolerance (double @var{val})\n@end deftypefn\n\n@deftypefn {} double absolute_tolerance (void)\n@deftypefnx {} double initial_step_size (void)\n@deftypefnx {} double maximum_step_size (void)\n@deftypefnx {} double minimum_step_size (void)\n@deftypefnx {} double relative_tolerance (void)\n@end deftypefn\n\n@deftypefn  {} {}ODE (void)\n@deftypefnx  {} {}ODE (int @var{n})\n@deftypefnx  {} {}ODE (const ColumnVector &@var{state}, double @var{time}, const ODEFunc &@var{f})\n@end deftypefn\n\n@deftypefn {} {virtual int} size (void) const\n@end deftypefn\n\n@deftypefn {} {virtual ColumnVector} state (void) const\n@end deftypefn\n\n@deftypefn {} {virtual double} time (void) const\n@end deftypefn\n\n@deftypefn {} {virtual void} force_restart (void)\n@end deftypefn\n\n@deftypefn {} {virtual void} initialize (const ColumnVector &@var{x}, double @var{t})\n@end deftypefn\n\n@deftypefn {} {virtual void} set_stop_time (double @var{t})\n@end deftypefn\n\n@deftypefn {} {virtual void} clear_stop_time (void)\n@end deftypefn\n\n@deftypefn {} {virtual ColumnVector} integrate (double @var{t})\n@end deftypefn\n\n@deftypefn {} void integrate (int @var{nsteps}, double @var{tstep}, ostream &@var{s})\n@end deftypefn\n\n@deftypefn {} Matrix integrate (const ColumnVector &@var{tout})\n@deftypefnx {} Matrix integrate (const ColumnVector &@var{tout}, const ColumnVector &@var{tcrit})\n@end deftypefn\n"
  },
  {
    "path": "doc/liboctave/optim.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Optimization\n@chapter Optimization\n@cindex optimization\n\n@menu\n* Objective Functions::\n* Bounds::\n* Linear Constraints::\n* Nonlinear Constraints::\n* Quadratic Programming::\n* Nonlinear Programming::\n@end menu\n\n@node Objective Functions\n@section Objective Functions\n@cindex objective functions\n\n@deftypefn  {} {} Objective (void)\n@deftypefnx  {} {} Objective (const @var{objective_fcn})\n@deftypefnx  {} {} Objective (const @var{objective_fcn}, const @var{gradient_fcn})\n@deftypefnx  {} {} Objective (const Objective &@var{a})\n@end deftypefn\n\n@deftypefn {} Objective& {operator =} (const Objective &@var{a})\n@end deftypefn\n\n@deftypefn {} objective_fcn objective_function (void) const;\n@end deftypefn\n\n@deftypefn {} Objective& set_objective_function (const @var{objective_fcn})\n@end deftypefn\n\n@deftypefn {} gradient_fcn gradient_function (void) const;\n@end deftypefn\n\n@deftypefn {} Objective& set_gradient_function (const @var{gradient_fcn})\n@end deftypefn\n\n@c ------------------------------------------------------------------------\n\n@node Bounds\n@section Bounds\n@cindex bounds\n\n@deftypefn  {} {} Bounds (void)\n@deftypefnx  {} {} Bounds (int @var{n})\n@deftypefnx  {} {} Bounds (const ColumnVector @var{lb}, const ColumnVector @var{ub})\n@deftypefnx  {} {} Bounds (const Bounds &@var{a})\n@end deftypefn\n\n@deftypefn {} Bounds& {operator =} (const Bounds &@var{a})\n@end deftypefn\n\n@deftypefn {} Bounds& resize (int @var{n})\n@end deftypefn\n\n@deftypefn {} double lower_bound (int @var{index}) const;\n@deftypefnx {} double upper_bound (int @var{index}) const;\n@end deftypefn\n\n@deftypefn {} ColumnVector lower_bounds (void) const;\n@deftypefnx {} ColumnVector upper_bounds (void) const;\n@end deftypefn\n\n@deftypefn {} int size (void) const;\n@end deftypefn\n\n@deftypefn {} Bounds& set_bound (int @var{index}, double @var{low}, double @var{high})\n@end deftypefn\n\n@deftypefn {} Bounds& set_bounds (double @var{low}, double @var{high})\n@deftypefnx {} Bounds& set_bounds (const ColumnVector @var{lb}, const ColumnVector @var{ub})\n@end deftypefn\n\n@deftypefn {} Bounds& set_lower_bound (int @var{index}, double @var{low})\n@deftypefnx {} Bounds& set_upper_bound (int @var{index}, double @var{high})\n@end deftypefn\n\n@deftypefn {} Bounds& set_lower_bounds (double @var{low})\n@deftypefnx {} Bounds& set_upper_bounds (double @var{high})\n@end deftypefn\n\n@deftypefn {} Bounds& set_lower_bounds (const ColumnVector @var{lb})\n@deftypefnx {} Bounds& set_upper_bounds (const ColumnVector @var{ub})\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const Bounds &@var{b})\n@end deftypefn\n\n@c ------------------------------------------------------------------------\n\n@node Linear Constraints\n@section Linear Constraints\n@cindex linear Constraints\n\n@deftypefn  {} {} LinConst (void)\n@deftypefnx  {} {} LinConst (int @var{nclin}, int @var{nx})\n@deftypefnx  {} {} LinConst (int @var{nclin_eq}, int @var{nclin_ineq}, int @var{nx})\n@deftypefnx  {} {} LinConst (const ColumnVector &@var{lb}, const Matrix &@var{A}, const ColumnVector &@var{ub})\n@deftypefnx  {} {} LinConst (const Matrix &@var{A_eq}, const ColumnVector &@var{b_eq}, const Matrix &@var{A_ineq}, const ColumnVector &@var{b_ineq})\n@deftypefnx  {} {} LinConst (const LinConst &@var{a})\n@end deftypefn\n\n@deftypefn {} LinConst& {operator =} (const LinConst &@var{a})\n@end deftypefn\n\n@deftypefn {} LinConst& resize (int @var{nclin}, int @var{n})\n@end deftypefn\n\n@deftypefn {} Matrix constraint_matrix (void) const;\n@end deftypefn\n\n@deftypefn {} LinConst& set_constraint_matrix (const Matrix &@var{A})\n@end deftypefn\n\n@deftypefn {} Matrix eq_constraint_matrix (void) const;\n@deftypefnx {} Matrix ineq_constraint_matrix (void) const;\n@end deftypefn\n\n@deftypefn {} ColumnVector eq_constraint_vector (void) const;\n@deftypefnx {} ColumnVector ineq_constraint_vector (void) const;\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const LinConst &@var{b})\n@end deftypefn\n\n@c ------------------------------------------------------------------------\n\n@node Nonlinear Constraints\n@section Nonlinear Constraints\n@cindex nonlinear Constraints\n\n@deftypefn  {} {} NLConst (void)\n@deftypefnx  {} {} NLConst (int @var{n})\n@deftypefnx  {} {} NLConst (const ColumnVector @var{lb}, const NLFunc @var{f}, const ColumnVector @var{ub})\n@deftypefnx  {} {} NLConst (const NLConst &@var{a})\n@end deftypefn\n\n@deftypefn {} NLConst& {operator =} (const NLConst &@var{a})\n@end deftypefn\n\n@node Quadratic Programming\n@section Quadratic Programming\n@cindex QP\n@cindex quadratic programming\n\n@deftypefn  {} {} QP (void)\n@deftypefnx  {} {} QP (const ColumnVector &@var{x}, const Matrix &@var{H})\n@deftypefnx  {} {} QP (const ColumnVector &@var{x}, const Matrix &@var{H}, const ColumnVector &@var{c})\n@deftypefnx  {} {} QP (const ColumnVector &@var{x}, const Matrix &@var{H}, const Bounds &@var{b})\n@deftypefnx  {} {} QP (const ColumnVector &@var{x}, const Matrix &@var{H}, const LinConst &@var{lc})\n@deftypefnx  {} {} QP (const ColumnVector &@var{x}, const Matrix &@var{H}, const ColumnVector &@var{c}, const Bounds &@var{b})\n@deftypefnx  {} {} QP (const ColumnVector &@var{x}, const Matrix &@var{H}, const ColumnVector &@var{c}, const LinConst &@var{lc})\n@deftypefnx  {} {} QP (const ColumnVector &@var{x}, const Matrix &@var{H}, const Bounds &@var{b}, const LinConst &@var{lc})\n@deftypefnx  {} {} QP (const ColumnVector &@var{x}, const Matrix &@var{H}, const ColumnVector &@var{c}, const Bounds &@var{b}, const LinConst &@var{lc})\n@end deftypefn\n\n@deftypefn {} {virtual ColumnVector} minimize (void)\n@deftypefnx {} {virtual ColumnVector} minimize (double &@var{objf})\n@deftypefnx {} {virtual ColumnVector} minimize (double &@var{objf}, int &@var{inform})\n@deftypefnx {} {virtual ColumnVector} minimize (double &@var{objf}, int &@var{inform}, ColumnVector &@var{lambda}) = 0;\n@end deftypefn\n\n@deftypefn {} {virtual ColumnVector} minimize (const ColumnVector &@var{x})\n@deftypefnx {} {virtual ColumnVector} minimize (const ColumnVector &@var{x}, double &@var{objf})\n@deftypefnx {} {virtual ColumnVector} minimize (const ColumnVector &@var{x}, double &@var{objf}, int &@var{inform})\n@deftypefnx {} {virtual ColumnVector} minimize (const ColumnVector &@var{x}, double &@var{objf}, int &@var{inform}, ColumnVector &@var{lambda})\n@end deftypefn\n\n@deftypefn {} ColumnVector minimize (double &@var{objf}, int &@var{inform}, ColumnVector &@var{lambda})\n@end deftypefn\n\n@c ------------------------------------------------------------------------\n\n@node Nonlinear Programming\n@section Nonlinear Programming\n@cindex NLP\n@cindex nonlinear programming\n\n@deftypefn  {} {} NLP (void)\n@deftypefnx  {} {} NLP (const ColumnVector &@var{x}, const Objective &@var{phi})\n@deftypefnx  {} {} NLP (const ColumnVector &@var{x}, const Objective &@var{phi}, const Bounds &@var{b})\n@deftypefnx  {} {} NLP (const ColumnVector &@var{x}, const Objective &@var{phi}, const Bounds &@var{b}, const LinConst &@var{lc})\n@deftypefnx  {} {} NLP (const ColumnVector &@var{x}, const Objective &@var{phi}, const Bounds &@var{b}, const LinConst &@var{lc}, const NLConst &@var{nlc})\n@deftypefnx  {} {} NLP (const ColumnVector &@var{x}, const Objective &@var{phi}, const LinConst &@var{lc})\n@deftypefnx  {} {} NLP (const ColumnVector &@var{x}, const Objective &@var{phi}, const LinConst &@var{lc}, const NLConst &@var{nlc})\n@deftypefnx  {} {} NLP (const ColumnVector &@var{x}, const Objective &@var{phi}, const NLConst &@var{nlc})\n@deftypefnx  {} {} NLP (const ColumnVector &@var{x}, const Objective &@var{phi}, const Bounds &@var{b}, const NLConst &@var{nlc})\n@end deftypefn\n\n@deftypefn {} NLP& {operator =} (const NLP &@var{a})\n@end deftypefn\n\n@deftypefn {} int size (void) const\n@end deftypefn\n\n@deftypefn {} ColumnVector minimize (void)\n@deftypefnx {} ColumnVector minimize (double &@var{objf})\n@deftypefnx {} ColumnVector minimize (double &@var{objf}, int &@var{inform})\n@deftypefnx {} ColumnVector minimize (double &@var{objf}, int &@var{inform}, ColumnVector &@var{lambda})\n@end deftypefn\n\n@deftypefn {} ColumnVector minimize (const ColumnVector &@var{x})\n@deftypefnx {} ColumnVector minimize (const ColumnVector &@var{x}, double &@var{objf})\n@deftypefnx {} ColumnVector minimize (const ColumnVector &@var{x}, double &@var{objf}, int &@var{inform})\n@deftypefnx {} ColumnVector minimize (const ColumnVector &@var{x}, double &@var{objf}, int &@var{inform}, ColumnVector &@var{lambda})\n@end deftypefn\n"
  },
  {
    "path": "doc/liboctave/preface.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Acknowledgements\n@chapter Acknowledgements\n@cindex acknowledgements\n\n@menu\n* Contributors::                People who contributed to developing Octave.\n@end menu\n\n@node Contributors\n@unnumberedsec Contributors to Octave\n@cindex contributors\n\nIn addition to John W. Eaton, several people have written parts\nof liboctave.  (This has been removed because it is the same as what is\nin the Octave manual.)\n"
  },
  {
    "path": "doc/liboctave/quad.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Quadrature\n@chapter Quadrature\n@cindex quadrature\n@cindex numerical integration\n@cindex integration\n\n@deftypefn  {} {} Quad (integrand_fcn @var{fcn})\n@deftypefnx  {} {} Quad (integrand_fcn @var{fcn}, double @var{abs}, double @var{rel})\n@end deftypefn\n\n@deftypefn {} {virtual double} integrate (void)\n@deftypefnx {} {virtual double} integrate (int &@var{ier})\n@deftypefnx {} {virtual double} integrate (int &@var{ier}, int &@var{neval})\n@deftypefnx {} {virtual double} integrate (int &@var{ier}, int &@var{neval}, double &@var{abserr}) = 0\n@end deftypefn\n\n@deftypefn {} {} Quad_options (void)\n@deftypefnx {} {} Quad_options (const Quad_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} Quad_options& {operator =} (const Quad_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} void init (void)\n@end deftypefn\n\n@deftypefn {} void copy (const Quad_options &@var{opt})\n@end deftypefn\n\n@deftypefn {} void set_default_options (void)\n@end deftypefn\n\n@deftypefn {} void set_absolute_tolerance (double @var{val})\n@end deftypefn\n\n@deftypefn {} void set_relative_tolerance (double @var{val})\n@end deftypefn\n\n@deftypefn {} double absolute_tolerance (void)\n@deftypefnx {} double relative_tolerance (void)\n@end deftypefn\n\n@deftypefn  {} {} DefQuad (integrand_fcn @var{fcn})\n@deftypefnx  {} {} DefQuad (integrand_fcn @var{fcn}, double @var{ll}, double @var{ul})\n@deftypefnx  {} {} DefQuad (integrand_fcn @var{fcn}, double @var{ll}, double @var{ul}, double @var{abs}, double @var{rel})\n@deftypefnx  {} {} DefQuad (integrand_fcn @var{fcn}, double @var{ll}, double @var{ul}, const ColumnVector &@var{sing})\n@deftypefnx  {} {} DefQuad (integrand_fcn @var{fcn}, const ColumnVector &@var{sing}, double @var{abs}, double @var{rel})\n@deftypefnx  {} {} DefQuad (integrand_fcn @var{fcn}, const ColumnVector &@var{sing})\n@deftypefnx  {} {} DefQuad (integrand_fcn @var{fcn}, double @var{ll}, double @var{ul}, const ColumnVector &@var{sing}, double @var{abs}, double @var{rel})\n@end deftypefn\n\n@deftypefn  {} {} IndefQuad (integrand_fcn @var{fcn})\n@deftypefnx  {} {} IndefQuad (integrand_fcn @var{fcn}, double @var{b}, IntegralType @var{t})\n@deftypefnx  {} {} IndefQuad (integrand_fcn @var{fcn}, double @var{b}, IntegralType @var{t}, double @var{abs}, double @var{rel})\n@deftypefnx  {} {} IndefQuad (integrand_fcn @var{fcn}, double @var{abs}, double @var{rel})\n@end deftypefn\n\n@menu\n* Collocation Weights::\n@end menu\n\n@node Collocation Weights\n@section Collocation Weights\n@cindex orthogonal collocation\n@cindex collocation weights\n\n@deftypefn  {} {} CollocWt (void)\n@deftypefnx  {} {} CollocWt (int @var{n}, int @var{inc_l}, int @var{inc_r})\n@deftypefnx  {} {} CollocWt (int @var{n}, int @var{inc_l}, int @var{inc_r}, double @var{l}, double @var{r})\n@deftypefnx  {} {} CollocWt (int @var{n}, double @var{a}, double @var{b}, int @var{inc_l}, int @var{inc_r})\n@deftypefnx  {} {} CollocWt (int @var{n}, int @var{inc_l}, int @var{inc_r}, double @var{l}, double @var{r})\n@deftypefnx  {} {} CollocWt (const CollocWt&)\n@end deftypefn\n\n@deftypefn {} CollocWt& {operator =} (const CollocWt&)\n@end deftypefn\n\n@deftypefn {} CollocWt& resize (int @var{ncol})\n@end deftypefn\n\n@deftypefn {} CollocWt& add_left (void)\n@deftypefnx {} CollocWt& add_right (void)\n@end deftypefn\n\n@deftypefn {} CollocWt& delete_left (void)\n@deftypefnx {} CollocWt& delete_right (void)\n@end deftypefn\n\n@deftypefn {} CollocWt& set_left (double @var{val})\n@deftypefnx {} CollocWt& set_right (double @var{val})\n@end deftypefn\n\n@deftypefn {} CollocWt& set_alpha (double @var{val})\n@deftypefnx {} CollocWt& set_beta (double @var{val})\n@end deftypefn\n\n@deftypefn {} int ncol (void) const\n@end deftypefn\n\n@deftypefn {} int left_included (void) const\n@deftypefnx {} int right_included (void) const\n@end deftypefn\n\n@deftypefn {} double left (void) const\n@deftypefnx {} double right (void) const\n@deftypefnx {} double width (void) const\n@end deftypefn\n\n@deftypefn {} double alpha (void) const\n@deftypefnx {} double beta (void) const\n@end deftypefn\n\n@deftypefn {} ColumnVector roots (void)\n@deftypefnx {} ColumnVector quad (void)\n@deftypefnx {} ColumnVector quad_weights (void)\n@end deftypefn\n\n@deftypefn {} Matrix first (void)\n@deftypefnx {} Matrix second (void)\n@end deftypefn\n\n@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const CollocWt &@var{c})\n@end deftypefn\n"
  },
  {
    "path": "doc/liboctave/range.texi",
    "content": "@c Copyright (C) 1996-2026 The Octave Project Developers\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software: you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by\n@c the Free Software Foundation, either version 3 of the License, or\n@c (at your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but\n@c WITHOUT ANY WARRANTY; without even the implied warranty of\n@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n@c GNU General Public License for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <https://www.gnu.org/licenses/>.\n\n@node Ranges\n@chapter Ranges\n@cindex ranges\n\nFIXME: The @code{Range} class is obsolete.\n"
  },
  {
    "path": "doc/module.mk",
    "content": "%canon_reldir%_EXTRA_DIST =\n\n%canon_reldir%_CLEANFILES =\n%canon_reldir%_DISTCLEANFILES =\n%canon_reldir%_MAINTAINERCLEANFILES =\n\nTEXINPUTS := $(PATH_SEPARATOR)$(abs_top_srcdir)/%reldir%/interpreter$(PATH_SEPARATOR)$(PATH_SEPARATOR)$(abs_top_builddir)/%reldir%/interpreter$(PATH_SEPARATOR)$(abs_top_builddir)/%reldir%/.texmf-var//$(PATH_SEPARATOR)$(TEXINPUTS)$(PATH_SEPARATOR)\n\nTEXMFCNF := $(PATH_SEPARATOR)$(abs_top_srcdir)/doc$(PATH_SEPARATOR)$(abs_top_builddir)/doc$(PATH_SEPARATOR)$(TEXMFCNF)$(PATH_SEPARATOR)\n\nTEXMFVAR := $(abs_top_builddir)/%reldir%/.texmf-var\n\nexport TEXINPUTS\nexport TEXMFCNF\nexport TEXMFVAR\n\nDVIPS = dvips\nTEX = tex\nPDFTEX = pdftex\n\nAM_V_TEX = $(am__v_TEX_$(V))\nam__v_TEX_ = $(am__v_TEX_$(AM_DEFAULT_VERBOSITY))\nam__v_TEX_0 = @echo \"  TEX     \" $@;\nam__v_TEX_1 =\n\nAM_V_PDFTEX = $(am__v_PDFTEX_$(V))\nam__v_PDFTEX_ = $(am__v_PDFTEX_$(AM_DEFAULT_VERBOSITY))\nam__v_PDFTEX_0 = @echo \"  PDFTEX  \" $@;\nam__v_PDFTEX_1 =\n\n## Conditionally define the following variables so that --disable-docs\n## can work.  If we don't define them, Automake will always define them,\n## even when AMCOND_BUILD_DOCS is false.\n\nINFO_DEPS =\nDVIS =\nPDFS =\nPSS =\nHTMLS =\n\ninclude %reldir%/doxyhtml/module.mk\ninclude %reldir%/interpreter/module.mk\ninclude %reldir%/liboctave/module.mk\ninclude %reldir%/refcard/module.mk\n\nif AMCOND_BUILD_DOCS\n\n## Listing \"dvi\" explicitly here seems to cause two simultaneous\n## builds of the DVI files, presumably because the PS version\n## also depends on the DVI file and somehow the rules are invoked\n## twice.  Is that a bug in automake or make or what?\n\n%canon_reldir%_EXTRA_DIST += %reldir%/texmf.cnf\n\nendif\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n\nCLEANFILES += $(%canon_reldir%_CLEANFILES)\nDISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)\nMAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)\n\ndoc-clean: doc-interpreter-clean doc-liboctave-clean\n\trm -f $(%canon_reldir%_CLEANFILES)\n\trm -rf %reldir%/.texmf-var\n\ndoc-distclean: doc-clean\n\trm -f $(%canon_reldir%_DISTCLEANFILES)\n\ndoc-maintainer-clean: doc-distclean doxyhtml-maintainer-clean\n\trm -f $(%canon_reldir%_MAINTAINERCLEANFILES)\n\trm -rf $(DVIS) $(HTMLS) $(PDFS) $(PSS)\n"
  },
  {
    "path": "doc/refcard/module.mk",
    "content": "if AMCOND_BUILD_DOCS\n\nrefcard_TEX_SRC = \\\n  %reldir%/refcard.tex \\\n  %reldir%/refcard-a4.tex \\\n  %reldir%/refcard-legal.tex \\\n  %reldir%/refcard-letter.tex\n\nrefcard_DVI = \\\n  %reldir%/refcard-a4.dvi \\\n  %reldir%/refcard-legal.dvi \\\n  %reldir%/refcard-letter.dvi\n\nrefcard_PDF = \\\n  %reldir%/refcard-a4.pdf \\\n  %reldir%/refcard-legal.pdf \\\n  %reldir%/refcard-letter.pdf\n\nrefcard_PS = \\\n  %reldir%/refcard-letter.ps \\\n  %reldir%/refcard-a4.ps \\\n  %reldir%/refcard-legal.ps\n\nrefcard_FORMATTED = \\\n  $(refcard_DVI) \\\n  $(refcard_PDF) \\\n  $(refcard_PS)\n\nDOC_TARGETS += \\\n  $(refcard_FORMATTED)\n\n%reldir%/refcard-a4.pdf: %reldir%/refcard.tex\n%reldir%/refcard-a4.dvi: %reldir%/refcard.tex\n%reldir%/refcard-a4.ps: %reldir%/refcard-a4.dvi\n\t-$(AM_V_DVIPS)$(DVIPS) $(AM_V_texinfo) -T 297mm,210mm -o $@ $<\n\n%reldir%/refcard-legal.pdf: %reldir%/refcard.tex\n%reldir%/refcard-legal.dvi: %reldir%/refcard.tex\n%reldir%/refcard-legal.ps: %reldir%/refcard-legal.dvi\n\t-$(AM_V_DVIPS)$(DVIPS) $(AM_V_texinfo) -T 14in,8.5in -o $@ $<\n\n%reldir%/refcard-letter.pdf: %reldir%/refcard.tex\n%reldir%/refcard-letter.dvi: %reldir%/refcard.tex\n%reldir%/refcard-letter.ps: %reldir%/refcard-letter.dvi\n\t-$(AM_V_DVIPS)$(DVIPS) $(AM_V_texinfo) -T 11in,8.5in -o $@ $<\n\n$(refcard_DVI) : %.dvi : %.tex | %reldir%/$(octave_dirstamp)\n\t-$(AM_V_TEX)cd $(@D) && \\\n\tTEXINPUTS=\"$(abs_top_srcdir)/doc/refcard:$(TEXINPUTS):\" \\\n\t$(TEX) $(<F) $(AM_V_texidevnull)\n\n$(refcard_PDF) : %.pdf : %.tex | %reldir%/$(octave_dirstamp)\n\t-$(AM_V_PDFTEX)cd $(@D) && \\\n\tTEXINPUTS=\"$(abs_top_srcdir)/doc/refcard:$(TEXINPUTS):\" \\\n\t$(PDFTEX) $(<F) $(AM_V_texidevnull)\n\ndoc_EXTRA_DIST += \\\n  $(refcard_FORMATTED) \\\n  $(refcard_TEX_SRC)\n\ndoc_CLEANFILES += \\\n  %reldir%/refcard-a4.log \\\n  %reldir%/refcard-legal.log \\\n  %reldir%/refcard-letter.log\n\ndoc_MAINTAINERCLEANFILES += \\\n  $(refcard_FORMATTED)\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nendif\n"
  },
  {
    "path": "doc/refcard/refcard-a4.tex",
    "content": "% refcard-a4.tex\n%\n% Make a reference card that will fit on A4 paper.\n%\n% Copyright (C) 1996-2026 The Octave Project Developers\n%\n% See the file COPYRIGHT.md in the top-level directory of this\n% distribution or <https://octave.org/copyright/>.\n%\n% This file is part of Octave.\n%\n% Octave is free software: you can redistribute it and/or modify it\n% under the terms of the GNU General Public License as published by\n% the Free Software Foundation, either version 3 of the License, or\n% (at your option) any later version.\n%\n% Octave is distributed in the hope that it will be useful, but\n% WITHOUT ANY WARRANTY; without even the implied warranty of\n% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n% GNU General Public License for more details.\n%\n% You should have received a copy of the GNU General Public License\n% along with Octave; see the file COPYING.  If not, see\n% <https://www.gnu.org/licenses/>.\n\n\\def\\refcardsize{a4}\n\\input refcard.tex\n"
  },
  {
    "path": "doc/refcard/refcard-legal.tex",
    "content": "% refcard-legal.tex\n%\n% Make a reference card that will fit on US legal paper.\n%\n% Copyright (C) 1996-2026 The Octave Project Developers\n%\n% See the file COPYRIGHT.md in the top-level directory of this\n% distribution or <https://octave.org/copyright/>.\n%\n% This file is part of Octave.\n%\n% Octave is free software: you can redistribute it and/or modify it\n% under the terms of the GNU General Public License as published by\n% the Free Software Foundation, either version 3 of the License, or\n% (at your option) any later version.\n%\n% Octave is distributed in the hope that it will be useful, but\n% WITHOUT ANY WARRANTY; without even the implied warranty of\n% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n% GNU General Public License for more details.\n%\n% You should have received a copy of the GNU General Public License\n% along with Octave; see the file COPYING.  If not, see\n% <https://www.gnu.org/licenses/>.\n\n\\def\\refcardsize{legal}\n\\input refcard.tex\n"
  },
  {
    "path": "doc/refcard/refcard-letter.tex",
    "content": "% refcard-letter.tex\n%\n% Make a reference card that will fit on US letter paper\n% (8-1/2 by 11 inches).\n%\n% Copyright (C) 1996-2026 The Octave Project Developers\n%\n% See the file COPYRIGHT.md in the top-level directory of this\n% distribution or <https://octave.org/copyright/>.\n%\n% This file is part of Octave.\n%\n% Octave is free software: you can redistribute it and/or modify it\n% under the terms of the GNU General Public License as published by\n% the Free Software Foundation, either version 3 of the License, or\n% (at your option) any later version.\n%\n% Octave is distributed in the hope that it will be useful, but\n% WITHOUT ANY WARRANTY; without even the implied warranty of\n% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n% GNU General Public License for more details.\n%\n% You should have received a copy of the GNU General Public License\n% along with Octave; see the file COPYING.  If not, see\n% <https://www.gnu.org/licenses/>.\n\n\\def\\refcardsize{letter}\n\\input refcard.tex\n"
  },
  {
    "path": "doc/refcard/refcard.tex",
    "content": "% refcard.tex\n%\n% This file is TeX source for a reference card describing Octave.\n%\n% Copyright (C) 1996-2026 The Octave Project Developers\n%\n% See the file COPYRIGHT.md in the top-level directory of this\n% distribution or <https://octave.org/copyright/>.\n%\n% This file is part of Octave.\n%\n% Octave is free software: you can redistribute it and/or modify it\n% under the terms of the GNU General Public License as published by\n% the Free Software Foundation, either version 3 of the License, or\n% (at your option) any later version.\n%\n% Octave is distributed in the hope that it will be useful, but\n% WITHOUT ANY WARRANTY; without even the implied warranty of\n% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n% GNU General Public License for more details.\n%\n% You should have received a copy of the GNU General Public License\n% along with Octave; see the file COPYING.  If not, see\n% <https://www.gnu.org/licenses/>.\n%\n%\n% Heavily modified by jwe from the source for the gdb reference card,\n% which was originally written by Roland Pesch <pesch@cygnus.com>.\n%\n%   Copyright (C) 1991, 1992 Free Software Foundation, Inc.\n%   Permission is granted to make and distribute verbatim copies of\n%   this reference provided the copyright notices and permission notices\n%   are preserved on all copies.\n%\n%\n% TeX markup is a programming language; accordingly this file is source\n% for a program to generate a reference.\n%\n% You only have to set the total width and height of the paper, the\n% horizontal and vertical margin space measured from *paper edge*\n% and the interline and interspec spacing.\n% In order to support a new papersize, you have to fiddle with the\n% latter four dimensions.  Just try out a few values.\n% All other values will be computed at process time so it should be\n% quite easy to support different paper sizes - only four values to\n% guess :-)\n%\n% To find the configuration places, just search for the string\n% \"User configuration\".\n%\n%   -- Andreas Vogel (av@ssw.de)\n%\n% NOTE ON INTENTIONAL OMISSIONS: This reference card includes many\n% Octave commands, but due to space constraints there are some things\n% I chose to omit.  In general, not all synonyms for commands are\n% covered, nor all variations of a command.\n\n\\def\\octaveversion{8}\n\n% ------------------\n% multicolumn format\n% ------------------\n\n% Declarations (these must come first)\n\n\\newdimen\\totalwidth\n\\newdimen\\totalheight\n\\newdimen\\hmargin\n\\newdimen\\vmargin\n\\newdimen\\secskip\n\\newdimen\\lskip\n\\newdimen\\barwidth\n\\newdimen\\barheight\n\\newdimen\\intersecwidth\n\n\\newcount\\columnsperpage\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                     %\n% CONFIGURATION                                                       %\n%                                                                     %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% There are currently 8 total columns, so some of these options will\n% not create a single page reference card.\n\n% Choose a paper size.  Default is US letter size.\n\n\\def\\refcardafoursize{a4}      % 3 columns, A4 paper (1 in = 254 mm)\n\\def\\refcardlegalsize{legal}   % 4 columns, US legal paper (8.5 x 14in)\n\\def\\refcardlettersize{letter} % 3 columns, US letter paper (8.5 x 11in)\n\n\\ifx\\refcardsize\\refcardafoursize\n  \\columnsperpage=3     % total number of columns to typeset\n  \\totalwidth=297mm     % total width of paper\n  \\totalheight=210mm    % total height of paper\n  \\hmargin=9mm          % horizontal margin width\n  \\vmargin=7mm          % vertical margin width\n  \\secskip=3mm          % space between refcard secs\n  \\lskip=0.4mm          % extra skip between \\sec entries\n\\else\n  \\ifx\\refcardsize\\refcardlegalsize\n    \\columnsperpage=4   % total number of columns to typeset\n    \\totalwidth=14in    % total width of paper\n    \\totalheight=8.5in  % total height of paper\n    \\hmargin=0.20in     % horizontal margin width\n    \\vmargin=0.25in     % vertical margin width\n    \\secskip=0.75pc     % space between refcard secs\n    \\lskip=2pt          % extra skip between \\sec entries\n  \\else\n    \\columnsperpage=3   % total number of columns to typeset\n    \\totalwidth=11in    % total width of paper\n    \\totalheight=8.5in  % total height of paper\n    \\hmargin=0.25in     % horizontal margin width\n    \\vmargin=0.25in     % vertical margin width\n    \\secskip=0.75pc     % space between refcard secs\n    \\lskip=2pt          % extra skip between \\sec entries\n  \\fi\n\\fi\n\n\\ifx\\pdfoutput\\undefined\n\\else\n  \\pdfpageheight=\\totalheight\n  \\pdfpagewidth=\\totalwidth\n\\fi\n\n% Change according to personal taste, not papersize dependent.\n\n\\barwidth=.1pt       % width of the cropmark bar\n\\barheight=2pt       % height of the cropmark bar\n\\intersecwidth=0.5em % width between \\itmwid and \\dfnwid\n\n% Uncomment only one of the following definitions for folding guides.\n\n% No printed folding guide:\n\n\\def\\vdecor{\\hskip\\hmargin plus1fil\n  \\hskip\\barwidth plus1fil\n  \\hskip\\hmargin plus1fil}\n\n% Solid line folding guide:\n\n%\\def\\vdecor{\\hskip\\hmargin plus1fil%\n%  \\vrule width \\barwidth%\n%  \\hskip\\hmargin plus1fil}\n\n% For small marks near top and bottom as folding guide:\n\n%\\def\\vdecor{\\hskip\\hmargin plus1fil%\n%  \\vbox to \\vsize{\\hbox to \\barwidth{\\vrule height\\barheight width\\barwidth}%\n%  \\vfill\n%  \\hbox to \\barwidth{\\vrule height\\barheight width\\barwidth}}%\n%  \\hskip\\hmargin plus1fil}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                      %\n% END CONFIGURATION                                                    %\n%                                                                      %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% values to be computed based on above definitions.\n% nothing to configure\n\n\\newdimen\\fullhsize          % width of area without margins\n\\newdimen\\itmwid             % width of item column\n\\newdimen\\dfnwid             % width of definition column\n\\newdimen\\idnwid             % width of indented text\n\\newdimen\\temp               % only for temporary use\n\n% an alternate section format, used in some cases to make text fit better.\n\n\\newdimen\\altitmwid        % width of item column in altsec\n\\newdimen\\altdfnwid        % width of definition column in altsec\n\n% Subtract hmargin for left and right sides of paper from full width.\n%\n%   fullhsize = totalwidth - (2 * hmargin)\n\n\\fullhsize=\\totalwidth\n\\temp=\\hmargin\n\\multiply \\temp by 2\n\\advance \\fullhsize by -\\temp\n\n% intercolumn space is composed of hmargin barwidth hmargin so that we\n% get the same amount of space on either side of the (optional) rule\n% between columns.  For N columns, we need to subtract this amount of\n% space N-1 times.  Divide by the number of columns to get the final\n% value of \\hsize that we use to typeset columns.\n\n% hsize = (fullhsize - (ncols-1)*barwidth - 2*(ncols-1)*hmargin) / ncols\n\n\\newcount\\tmpcnt\n\\tmpcnt\\columnsperpage\n\\advance \\tmpcnt by -1\n\n\\hsize=\\fullhsize\n\n\\temp=\\barwidth\n\\multiply \\temp by \\tmpcnt\n\\advance \\hsize by -\\temp\n\n\\multiply \\tmpcnt by 2\n\n\\temp=\\hmargin\n\\multiply \\temp by \\tmpcnt\n\\advance \\hsize by -\\temp\n\n\\divide \\hsize by \\columnsperpage\n\n% Vertical size is easy -- same amount of space above and below.\n%\n%   vsize = totalheight - (2 * vmargin)\n\n\\vsize=\\totalheight\n\\temp=\\vmargin\n\\multiply \\temp by 2\n\\advance \\vsize by -\\temp\n\n% adjust the offsets so the margins are measured *from paper edge*\n\n\\hoffset=-1in \\advance \\hoffset by \\hmargin\n\\voffset=-1in \\advance \\voffset by \\vmargin\n\n% Width of items in a section.\n\n% itmwid = (hsize - intersecwidth) * 1/3\n% dfnwid = (hsize - intersecwidth) * 2/3\n\n% width of the item\n\n\\temp=\\hsize\n\\advance \\temp by -\\intersecwidth\n\\divide \\temp by 3\n\\itmwid=\\temp\n\n% width of the corresponding definition\n\n\\dfnwid=\\hsize\n\\advance \\dfnwid by -\\itmwid\n\n% indentation for sub items, etc.\n\n\\temp=\\hsize \\advance\\temp by -1em\n\\idnwid=\\temp\n\n% Width of items in an alt section.\n\n\\altitmwid=\\itmwid \\advance \\altitmwid by 0.35in\n\\altdfnwid=\\dfnwid \\advance \\altdfnwid by -0.35in\n\n% Output macros.\n%\n% Strategy:\n%\n%   * set each column in a box\n%   * append new columns in a global `holding' box, inserting\n%     intercolumn decorations as necessary.\n%   * when we fill a page, dump the saved box and the latest column,\n%     separated by the intercolumn decoration.\n\n\\newbox\\holdbox\n\\newcount\\colno\n\\colno=0\n\n\\output={\\relax\n  \\global\\advance\\colno by 1\n  \\ifnum\\colno=1\n    \\global\\setbox\\holdbox=\\columnbox\n  \\else\n    \\ifnum\\colno=\\columnsperpage\n      \\shipout\\hbox to \\fullhsize{\\box\\holdbox\\vdecor\\columnbox}\n      \\advancepageno\n      \\global\\colno=0\n    \\else\n      \\global\\setbox\\holdbox=\\vbox{\\hbox{\\box\\holdbox\\vdecor\\columnbox}}\n    \\fi\n  \\fi}\n\n\\def\\columnbox{\\leftline{\\pagebody}}\n\n\\def\\bye{\\par\\vfill\n  \\supereject\n  \\if R\\lcr \\null\\vfill\\eject \\fi\n  \\end}\n\n% -----\n% Fonts\n% -----\n\n\\font\\bbf=cmbx10\n\\font\\vbbf=cmbx12\n\\font\\smrm=cmr6\n\\font\\brm=cmr10\n\\font\\rm=cmr7\n\\font\\it=cmti7\n\\font\\tt=cmtt8\n\n% We can afford to allow some slop\n\n\\hfuzz=1pt\n\\vfuzz=1pt\n\\hyphenpenalty=5000\n\\tolerance=2000\n\\raggedright\n\\raggedbottom\n\\normalbaselineskip=9pt\n\\baselineskip=9pt\n\n\\parindent=0pt\n\\parskip=0pt\n\\footline={\\vbox to0pt{\\hss}}\n\n\\def\\ctl#1{{\\tt C-#1}}\n\\def\\opt#1{{\\brm[{\\rm #1}]}}\n\\def\\xtra#1{\\noalign{\\smallskip{\\tt#1}}}\n\n% A normal section\n\n\\long\\def\\sec#1;#2\\endsec{\\vskip \\secskip\n  \\halign{%\n%\n% column 1 (of halign):\n%\n    \\vtop{\\hsize=\\itmwid\\tt ##\\par\\vskip \\lskip }\\hfil\n%\n% column 2 (of halign):\n%\n    &\\vtop{%\n      \\hsize=\\dfnwid\n      \\hangafter=1\n      \\hangindent=\\intersecwidth\n      \\rm ##\\par\\vskip \\lskip}\\cr\n%\n% Tail of \\long\\def fills in halign body with \\sec args:\n%\n    \\noalign{{\\bbf #1}%\n      \\vskip \\lskip}\n    #2}}\n\n\\long\\def\\widesec#1;#2\\endsec{\\vskip \\secskip\n  \\halign{%\n%\n% column 1 (of halign):\n%\n    \\vbox{\\tt\n      ##\\par\\vskip \\lskip }\\cr\n%\n% Tail of \\long\\def fills in halign body with \\sec args:\n%\n      \\noalign{{\\bbf #1}\\vskip 3\\lskip}\n    #2}}\n\n% an alternate section format, used in some cases to make text fit better.\n\n\\long\\def\\altsec#1;#2\\endsec{\\vskip \\secskip\n  \\halign{%\n%\n% column 1 (of halign):\n%\n    \\vtop{\\hsize=\\altitmwid\\tt\n      ##\\par\\vskip \\lskip}\\hfil\n%\n% column 2 (of halign):\n%\n    &\\vtop{%\n      \\hsize=\\altdfnwid\n      \\hangafter=1\n      \\hangindent=\\intersecwidth\n      \\rm ##\\par\\vskip \\lskip}\\cr\n%\n% Tail of \\long\\def fills in halign body with \\sec args:\n%\n    \\noalign{{\\bbf #1}\\vskip \\lskip}\n    #2}}\n\n% -------------------------------------\n% The actual text of the reference card\n% -------------------------------------\n\n{\\vbbf Octave Quick Reference}\\hfil{\\smrm Octave \\octaveversion \\space or later}\\qquad\n{\\smrm Copyright\\thinspace\\copyright\\thinspace 1996-2026 The Octave Project Developers}\n\n\\altsec Starting and Stopping;\noctave \\opt{-\\hbox{}-gui}&start Octave CLI/GUI session\\cr\noctave {\\it file}&run Octave commands in {\\it file}\\cr\noctave --eval {\\it code}&evaluate {\\it code} using Octave\\cr\noctave --help&describe command line options\\cr\nquit {\\rm or} exit&exit Octave\\cr\nCtrl-C&terminate current command and return to top-level prompt\\cr\n\\endsec\n\n\\sec Getting Help;\nhelp {\\it command}&briefly describe {\\it command}\\cr\ndoc&browse Octave manual\\cr\ndoc {\\it command}&search for {\\it command} in Octave manual\\cr\nlookfor {\\it str}&search for {\\it command} based on {\\it str}\\cr\n\\endsec\n\n\\sec Command Completion and History;\nTAB&complete a command or variable name\\cr\nAlt-?&list possible completions\\cr\nCtrl-r Ctrl-s&search command history\\cr\n\\endsec\n\n\\sec Directory and Path Commands;\ncd {\\it dir}&change working directory to {\\it dir}\\cr\npwd&print working directory\\cr\nls \\opt{{\\it options}}&print directory listing\\cr\nwhat&list .m/.mat files in the current directory\\cr\npath&search path for Octave functions\\cr\npathdef&default search path\\cr\naddpath ({\\it dir})&add directory to search path\\cr\ngetenv ({\\it var})&value of environment variable\\cr\n\\endsec\n\n\\altsec Package Management;\n\\omit\\vbox{\\rm\\vskip0.25ex\n  Add-on packages are independent of core Octave, listed at\n  {https://packages.octave.org/} \\vskip0.75ex}\\span\\cr\npkg search {\\it foo}&search for packages online with keyword {\\it foo}\\cr\npkg install {\\it pkg}&download and install {\\it pkg}\\cr\npkg list&show installed packages\\cr\npkg load / pkg unload&load/unload installed package\\cr\nstatistics optim control signal image symbolic&various common\npackages\\cr\n\\endsec\n\n\\sec Matrices;\n\\omit\\vbox{\\rm\\vskip0.25ex\n  Square brackets delimit literal matrices.  Commas separate elements\n  on the same row.  Semicolons separate rows.  Commas may be replaced\n  by spaces, and semicolons may be replaced by newlines.\n  Elements of a matrix may be arbitrary expressions, assuming\n  all the dimensions agree.\\vskip0.75ex}\\span\\cr\n[ {\\it x}, {\\it y}, ... ]&enter a row vector\\cr\n[ {\\it x}; {\\it y}; ... ]&enter a column vector\\cr\n[ {\\it w}, {\\it x}; {\\it y}, {\\it z} ]&enter a 2$\\times$2 matrix\\cr\nrows columns&number of rows/columns of matrix\\cr\nzeros ones&create matrix of zeros/ones\\cr\neye diag&create identity/diagonal matrix\\cr\nrand randi randn&create matrix of random values\\cr\nsparse spalloc&create a sparse matrix\\cr\nall&true if all elements nonzero\\cr\nany&true if at least one element nonzero\\cr\nnnz&number of nonzero elements\\cr\n\\endsec\n\n\\sec Multi-dimensional Arrays;\nndims&number of dimensions\\cr\nreshape squeeze&change array shape\\cr\nresize&change array shape, lossy\\cr\ncat&join arrays along a given dimension\\cr\npermute ipermute shiftdim&like N-dimensional transpose\\cr\ncircshift&cyclically shift array elements\\cr\nmeshgrid&matrices useful for vectorization\\cr\n\\endsec\n\n\\sec Ranges;\n\\omit\\vbox{\\rm\\vskip0.25ex\n  Create sequences of real numbers as row vectors.\\vskip0.75ex}\\span\\cr\n{\\it base} : {\\it limit}\\cr\n{\\it base} : {\\it incr} : {\\it limit}\\cr\n\\omit\\hfill\\vbox{\\hsize=\\idnwid\\rm\\vskip0.75ex\n  {\\it incr} == 1 if not specified.  Negative ranges allowed.}\\span\\cr\n\\endsec\n\n\\altsec Numeric Types and Values;\n\\omit\\vbox{\\rm\\vskip0.5ex\n  Integers saturate in Octave.  They do not roll over.\n  \\vskip0.75ex}\\span\\cr\nint8 int16 int32 int64&signed integers\\cr\nuint8 uint16 uint32 uint64&unsigned integers\\cr\nsingle double&32-bit/64-bit IEEE floating point\\cr\nintmin intmax flintmax&integer limits of given type\\cr\nrealmin realmax&floating point limits of given type\\cr\ninf nan NA&IEEE infinity, NaN, missing value\\cr\neps&machine precision\\cr\npi e&3.14159..., 2.71828...\\cr\ni j&$\\sqrt{-1}$\\cr\n\\endsec\n\n\\sec Strings;\n\\omit\\vbox{\\rm\\vskip0.5ex\n  A {\\it string constant\\/} consists of a sequence of characters\n  enclosed in either double-quote or single-quote marks.  Strings\n  in double-quotes allow the use of the escape sequences below.\n  \\vskip0.75ex}\\span\\cr\n\\char'134\\char'134&a literal backslash\\cr\n\\char'134 \"&a literal double-quote character\\cr\n\\char'134 '&a literal single-quote character\\cr\n\\char'134 n&newline, ASCII code 10\\cr\n\\char'134 t&horizontal tab, ASCII code 9\\cr\nsprintf sscanf&formatted IO to/from string\\cr\nstrcmp&compare strings\\cr\nstrcat&join strings\\cr\nstrfind regexp&find matching patterns\\cr\nstrrep regexprep&find and replace patterns\\cr\n\\endsec\n\n\\sec Index Expressions;\n{\\it var}({\\it idx})&select elements of a vector\\cr\n{\\it var}({\\it idx1}, {\\it idx2})&select elements of a matrix\\cr\n{\\it var}({[1 3], :})&rows 1 and 3\\cr\n{\\it var}({:, [2 end]})&the second and last columns\\cr\n{\\it var}({1:2:end, 2:2:end})&get odd rows and even columns\\cr\n{\\it var1}({\\it var2} == 0)&elements of {\\it var1} corresponding to zero\nelements of {\\it var2}\\cr\n{\\it var}({:})&all elements as a column vector\\cr\n\\endsec\n\n\\sec Cells, Structures, and Classdefs;\n{\\it{var}}$\\{${\\it{idx}}$\\}$ = ...&set an element of a cell array\\cr\ncellfun ({\\it f}, {\\it c})&apply a function to elements of cell array\\cr\n{\\it{var}}.{\\it{field}} = ...&set a field of a structure\\cr\nfieldnames ({\\it s})&returns the fields of a structure\\cr\nstructfun ({\\it f}, {\\it s})&apply a function to fields of structure\\cr\nclassdef&define new classes for OOP\\cr\n\\endsec\n\n\\sec Assignment Expressions;\n{\\it var} = {\\it expr}&assign value to variable\\cr\n{\\it var}({\\it idx}) = {\\it expr}&only the indexed elements are changed\\cr\n{\\it var}({\\it idx}) = []&delete the indexed elements\\cr\n\\endsec\n\n\\sec Arithmetic Operators;\n%\n% FIXME These operators look ugly, but putting them in math mode causes\n% some of them to break even more.\n%\n\\omit \\vbox{\\rm\\vskip0.75ex\n  If two operands are of different sizes, scalars and singleton dimensions are\n  automatically expanded.  Non-singleton dimensions need to match.\n  \\vskip0.75ex}\\span\\cr\n{\\it x} + {\\it y}, {\\it x} - {\\it y}&addition, subtraction\\cr\n{\\it x} * {\\it y}&matrix multiplication\\cr\n{\\it x} .* {\\it y}&element-by-element multiplication\\cr\n{\\it x} / {\\it y}&right division, conceptually equivalent to\n  {\\tt (inverse~(y')~*~x')'}\\cr\n{\\it x} ./ {\\it y}&element-by-element right division\\cr\n{\\it x} \\char'134{} {\\it y}&left division, conceptually equivalent to\n  {\\tt inverse~(x)~*~y}\\cr\n{\\it x} .\\char'134{} {\\it y}&element-by-element left division\\cr\n{\\it x} \\char'136{} {\\it y}&power operator\\cr\n{\\it x} .\\char'136{} {\\it y}&element-by-element power operator\\cr\n+= -= *= .*= /= ./= \\char'134{}= .\\char'134{}= \\char'136{}= .\\char'136{}=&\nin-place equivalents of the above operators\\cr\n-{\\it x}&negation\\cr\n+{\\it x}&unary plus (a no-op)\\cr\n{\\it x}$'$&complex conjugate transpose\\cr\n{\\it x}.$'$&transpose\\cr\n++{\\it x} --{\\it x}&increment/decrement, return {\\it new\\/} value\\cr\n{\\it x}++ {\\it x}--&increment/decrement, return {\\it old\\/} value\\cr\n\\endsec\n\n\\sec Comparison and Boolean Operators;\n\\omit \\vbox{\\rm\\vskip0.75ex\n  These operators work on an element-by-element basis.  Both arguments\n  are always evaluated.\\vskip0.75ex}\\span\\cr\n< <= == >= >&relational operators\\cr\n!= \\char'176 =&not equal to\\cr\n\\& &logical AND\\cr\n|  &logical OR\\cr\n! \\char'176 &logical NOT\\cr\n\\endsec\n\n\\sec Short-circuit Boolean Operators;\n\\omit \\vbox{\\rm\\vskip0.75ex\n  Operators evaluate left-to-right.  Operands are only evaluated if\n  necessary, stopping once overall truth value can be determined.\n  Nonscalar operands are converted to scalars with\n  {\\tt all}.\\vskip0.75ex}\\span\\cr\n{\\it x} \\&\\& {\\it y}&logical AND\\cr\n{\\it x} || {\\it y}&logical OR\\cr\n\\endsec\n\n\\vfill\\eject\n\n\\sec Operator Precedence;\n\\omit \\vbox{\\rm\\vskip0.5ex\n  Table of Octave operators, in order of {\\tt decreasing}\n  precedence.\\vskip0.75ex}\\span\\cr\n() $\\{\\}$ . & array index, cell index, structure index\\cr\n'\\ \\ .'\\ \\ \\char'136\\ \\ .\\char'136&transpose and exponentiation\\cr\n+\\ \\ -\\ \\ ++\\ \\ --\\ \\ !&unary minus, increment, logical ``not''\\cr\n* / \\char'134\\ \\ .*\\ \\ ./\\ \\ .\\char'134&multiplication and division\\cr\n+\\ \\ -&addition and subtraction\\cr\n:&colon\\cr\n< <= == >= > !=&relational operators\\cr\n\\&\\ \\ |&element-wise ``and'' and ``or''\\cr\n\\&\\&\\ \\ ||&logical ``and'' and ``or''\\cr\n= += -= *= /=  etc.&assignment, groups left to right\\cr\n;\\ \\ ,&statement separators\\cr\n\\endsec\n\n\\altsec General programming;\n\\omit \\vbox{\\rm\\vskip0.5ex\n  endfor, endwhile, endif etc.\\ can all be replaced by end.\n  \\vskip0.75ex}\\span\\cr\nfor x = 1:10\n\nendfor & for loop\\cr\n\\cr\n\nwhile (x <= 10)\n\nendwhile & while loop\\cr\n\\cr\n\ndo\n\nuntil (x > 10) & do-until loop\\cr\n\\cr\n\nif (x < 5)\n\nelseif (x < 6)\n\nelse\n\nendif & if-then-else\\cr\n\\cr\n\nswitch (tf)\n\n\\quad case \"true\"\n\n\\quad case \"false\"\n\n\\quad otherwise\n\nendswitch & switch-case\\cr\n\\cr\n\nbreak & exit innermost loop\\cr\n\\cr\n\ncontinue & go to start of innermost loop\\cr\n\\cr\n\nreturn & jump back from function to caller\\cr\n\\cr\n\ntry\n\ncatch & cleanup only on exception\\cr\n\\cr\n\nunwind\\char'137 protect\n\nunwind\\char'137 protect\\char'137 cleanup& cleanup always \\cr\n\\endsec\n\n\\widesec Functions;\nfunction \\opt{{\\it ret-list} =} {\\it function-name}\n  \\opt{\\hskip0.2em({\\it arg-list})\\hskip0.2em}\\cr\n\\quad{\\it function-body}\\cr\nendfunction\\cr\\cr\n{\\rm {\\it ret-list\\/} may be a single identifier or a comma-separated\n  list of identifiers enclosed by square brackets.\\vskip0.75ex}\\cr\n{\\rm {\\it arg-list\\/} is a comma-separated list of identifiers and may\n  be empty.}\\cr\n\\endsec\n\n\\sec Function Handles and Evaluation;\n@{\\it{func}}&create a function handle to {\\it func}\\cr\n@({\\it vars}) {\\it expr}&define an anonymous function\\cr\nstr2func func2str&convert function to/from string\\cr\nfunctions ({\\it handle})&Return information about a function handle\\cr\n{\\it f} ({\\it args})&Evaluate a function handle {\\it f}\\cr\nfeval &Evaluate a function handle or string\\cr\neval ({\\it str})&evaluate {\\it str} as a command\\cr\nsystem ({\\it cmd})&execute arbitrary shell command string\\cr\n&\\cr\n\\omit\\vbox{\\rm\\vskip0.25ex\n  Anonymous function handles make a copy of the variables in the\n  current workspace at the time of creation.\\vskip0.75ex}\\span\\cr\n\\endsec\n\n\\altsec Global and Persistent Variables;\nglobal {\\it var} = ...&declare \\& initialize global variable\\cr\npersistent {\\it var} = ...&persistent/static variable\\cr\n\\omit\\hfill\\vbox{\\rm\\vskip0.25ex\n  Global variables may be accessed inside the body of a function\n  without having to be passed in the function parameter list provided\n  that they are declared global when used.}\\span\\cr\n\\endsec\n\n\\sec Common Functions;\ndisp&display value of variable\\cr\nprintf&formatted output to {\\tt stdout}\\cr\ninput scanf&input from {\\tt stdin}\\cr\nwho whos&list current variables\\cr\nclear {\\it pattern}&clear variables matching pattern\\cr\nexist&check existence of identifier\\cr\nfind&return indices of nonzero elements\\cr\nsort&return a sorted array\\cr\nunique&discard duplicate elements\\cr\nsortrows&sort whole rows in numerical or lexicographic order\\cr\nsum prod&sum or product\\cr\nmod rem&remainder functions\\cr\nmin max range mean median std&basic statistics\\cr\n\\endsec\n\n\\sec Error Handling, Debugging, Profiling;\nerror ({\\it message})&print message and return to top level\\cr\nwarning ({\\it message})&print a warning message\\cr\ndebug&guide to all debugging commands\\cr\nprofile&start/stop/clear/resume profiling\\cr\nprofshow profexplore&show the results of profiling\\cr\n\\endsec\n\n\\sec File I/O, Loading, Saving;\nsave load &save/load variables to/from file\\cr\nsave -binary &save in binary format (faster, smaller)\\cr\ndlmread dlmwrite&read/write delimited data\\cr\ncsvread csvwrite&read/write CSV files\\cr\nxlsread xlswrite&read/write XLS spreadsheets\\cr\n&\\cr\nfopen fclose & open/close files\\cr\nfprintf fscanf textscan&formatted file I/O\\cr\nfflush&flush pending output\\cr\n\\endsec\n\n\\sec Math Functions;\n\\omit \\vbox{\\rm\\vskip0.5ex\n  type {\\tt doc <function>} to find related functions.\n  \\vskip0.75ex}\\span\\cr\ncov corrcoef&covariance, correlation coefficient\\cr\ntan tanh atan2&trig and hyperbolic functions\\cr\ncross curl del2&vector algebra functions\\cr\n&\\cr\ndet inv& determinant, matrix inverse\\cr\neig &eigenvalues and eigenvectors\\cr\nnorm &vector or matrix norm\\cr\nrank &matrix rank\\cr\nqr &QR factorization\\cr\nchol &Cholesky factorization\\cr\nsvd &singular value decomposition\\cr\n&\\cr\nfsolve&solve nonlinear algebraic equations\\cr\nlsode ode45&integrate nonlinear ODEs\\cr\ndassl&integrate nonlinear DAEs\\cr\nintegral&integrate nonlinear functions\\cr\n&\\cr\nunion&set union\\cr\nintersection&set intersection\\cr\nsetdiff&set difference\\cr\n&\\cr\nroots &polynomial roots\\cr\npoly &matrix characteristic polynomial\\cr\npolyder polyint&polynomial derivative/integral\\cr\npolyfit polyval&polynomial fitting/evaluation\\cr\nresidue &partial fraction expansion\\cr\nlegendre bessel&special functions\\cr\n&\\cr\nconv conv2& convolution, polynomial multiplication\\cr\ndeconv& deconvolution, polynomial division\\cr\n&\\cr\nfft fft2 ifft&FFT / inverse FFT\\cr\nfreqz &FIR filter frequency response\\cr\nfilter &filter by transfer function\\cr\n\\endsec\n\n\\altsec Plotting and Graphics;\nplot plot3 &2-D / 3-D plot with linear axes\\cr\nline &2-D or 3-D line\\cr\npatch fill&2-D patch, optionally colored\\cr\nsemilogx semilogy loglog&logarithmic axes\\cr\nbar hist&bar chart, histogram\\cr\nstairs stem&stairsteps and stem plots\\cr\ncontour &contour plot\\cr\nmesh trimesh surf &plot 3-D surfaces\\cr\n&\\cr\nfigure&new figure\\cr\nhold on&add to existing figure\\cr\ntitle &set plot title\\cr\naxis &set axis range and aspect\\cr\nxlabel ylabel zlabel &set axis labels\\cr\ntext &add text to a plot\\cr\ngrid legend &draw grid or legend\\cr\n&\\cr\nimage imagesc spy&display matrix as image\\cr\nimwrite saveas print&save figure or image\\cr\nimread&load an image\\cr\ncolormap &get or set colormap\\cr\n\\endsec\n\n\\vskip 0pt plus 2fill\n\\hrule width \\hsize\n\\par\\vskip10pt\n{\\smrm\\parskip=6pt\nQuick reference for Octave \\octaveversion \\space or later.\nCopyright\\thinspace\\copyright\\thinspace 1996-2026 The Octave Project\nDevelopers.  The authors assume no responsibility for any errors on this card.\nThis card may be freely distributed under the terms of the GNU General Public\nLicense.\n\nOctave license and copyright: https://octave.org/copyright/\n\n\\TeX{} Macros for this card by Roland Pesch (pesch@cygnus.com),\noriginally for the GDB reference card\n}\n\n\\end\n\n% For AUCTeX:\n%\n% Local Variables:\n% mode: tex\n% TeX-master: t\n% End:\n"
  },
  {
    "path": "doc/texmf.cnf",
    "content": "% Increase save size to run @seealso macro for Octave documentation\nsave_size = 10000\n"
  },
  {
    "path": "etc/CHECKLIST.md",
    "content": "Things to do before making a release:\n\n  * Update the version number and release date in configure.ac.\n\n  * Update the OCTAVE_API_VERSION number in configure.ac.\n\n  * Update version number and release year in CITATION.\n\n  * Update the etc/NEWS.N.md file corresponding to the major release\n    number N.  Include release date in Summary header.\n\n  * Update the NEWS-<VERSION>.html, index.in, news.in, and download.in\n    files for the web site.\n\n  * Copy tarballs to ftp.gnu.org.\n\n  * Post a release announcement to the help@octave.org and\n    info-gnu@gnu.org lists.\n\n  * Update https://wiki.octave.org/Release_History page.\n"
  },
  {
    "path": "etc/HACKING.md",
    "content": "Hacking Octave\n==============\n\nThis file attempts to describe the rules to use when hacking the\nOctave sources cloned from the Savannah source code\n[repository](https://hg.savannah.gnu.org/hgweb/octave/).\n**DO NOT** put this file into the distribution.  These requirements\ndo not apply when building from a distribution tarball.\n\nQuick start\n-----------\n\n1. Install all the required dependencies.  Precisely how to do that\n   depends on what type of system you are using.  There are more\n   details below.\n\n2. Clone the Octave sources:\n\n        hg clone https://www.octave.org/hg/octave\n\n3. Change to the top-level directory of the Octave source tree and\n   run the `bootstrap` script:\n\n        cd octave\n        ./bootstrap\n\n4. Create a build directory, `cd` to it, then run `configure` and\n   `make`, or `make -jX` (to run `X` simultaneous jobs):\n\n        mkdir .build\n        cd .build\n        ../configure\n        make -j2\n\nRequirements\n------------\n\nWe've opted to keep only the highest-level sources in the repository.\nThis eases our maintenance burden (fewer merges, etc.), but imposes\nmore requirements on anyone wishing to build from the just-cloned\nsources.  For example, you have to use the latest stable versions of\nthe maintainer tools we depend upon.  These include:\n\n- [Autoconf](https://www.gnu.org/software/autoconf/)\n- [Automake](https://www.gnu.org/software/automake/)\n- [Bison](https://www.gnu.org/software/bison/)\n- [Flex](https://www.gnu.org/software/flex/)\n- [Gnulib](https://www.gnu.org/software/gnulib/)\n- [GNU Make](https://www.gnu.org/software/make/)\n- [gperf](https://www.gnu.org/software/gperf/)\n- [Gzip](https://www.gnu.org/software/gzip/)\n- [Libtool](https://www.gnu.org/software/libtool/)\n- [Mercurial](https://www.mercurial-scm.org/)\n- [Perl](https://www.cpan.org/)\n- [Rsync](https://samba.anu.edu.au/rsync/)\n- [Tar](https://www.gnu.org/software/tar/)\n\nIn addition to these maintainer tools, Octave makes use of many\nexternal libraries and packages.  See `doc/interpreter/install.txi`\nfor the complete list of required and optional dependencies.\n\nOnly building the initial full source tree will be a bit painful.\nLater, after synchronizing from the repository, a plain `make` should\nbe sufficient.\n\nFirst clone\n-----------\n\nIf you are reading these notes, you may have already managed to clone\nthis package from the repository.  For the record, you will find all\nthe relevant information on downloading sources at:\n\n  <https://www.octave.org/download.html>\n\nAfter cloning Octave, you will need to run the `bootstrap` script:\n\n    ./bootstrap\n\nThis script will examine the source tree and generate some `Makefile`\nfragments, then run autotools scripts to generate `Makefile.in` files\nfrom `Makefile.am` files and create the `configure` script.  The\n`bootstrap` script comes from gnulib, but is kept in the Octave\nsource archive.  It should be updated from the gnulib sources as\nnecessary.\n\nIf you have a copy of gnulib in some directory apart from the Octave\nsource tree, then pass the name of the directory containing\n`gnulib-tool` to the `bootstrap` script using the option:\n\n    --gnulib-srcdir=DIRNAME\n\nIf you have downloaded gnulib directly, `DIRNAME` will be the\ndirectory where gnulib was unpacked.  If you have installed gnulib\nusing a package manager, `DIRNAME` is likely to be `/usr/bin` or\n`/usr/local/bin` (where the gnulib-tool script resides).\n\nBy using an external gnulib directory, you can share a single gnulib\nsource tree among several projects.  From 2011 until 2020, the gnulib\nsources were a Mercurial subrepository of the Octave repository, so they\nwill be automatically updated to the corresponding Mercurial revision if\nyou update the working directory to a revision in that time period.\nIn 2020, the gnulib Mercurial subrepository was deleted.  Instead, the\n`bootstrap` script is used to fetch and update to a marked revision of\nthe gnulib git repository.  A working copy of the gnulib git repository\nwill be automatically updated to the matching revision (see the default\nvalue of `GNULIB_REVISION` in `bootstrap.conf`) when you run the\n`bootstrap` script after you updated the working directory to a revision\nafter that point in time.  A working `git` installation is necessary.\n\nAdditional options besides `--gnulib-srcdir` can be passed to\n`bootstrap` and they will be forwarded without modification to the\ngnulib `bootstrap` script.\n\nOnce the `bootstrap` script completes successfully, you may configure\nand build Octave.  We recommend that you build Octave in a separate\ndirectory tree from the sources.  For example, if you have just\nfinished running the `bootstrap` script in the top-level source\ndirectory, run the following commands to create a build tree,\nconfigure, and build Octave:\n\n    mkdir .build\n    cd .build\n    ../configure\n    make -j2\n    make check\n\nThe `-j2` after the first `make` call means, that two jobs run\nsimultaneously.  This number may be increased depending on your\nsystem.  At this point, there should be no difference between your\nworking tree and the currently visited hg revision:\n\n    hg diff\n\nshould output no difference.\n\nCoding style\n------------\n\nThe most important advice is to follow any conventions you detect\nin the file being edited.  In addition, Octave maintainers have\nwritten a lot on the subject.  See\n<https://wiki.octave.org/Contribution_guidelines>.\n\nProjects\n--------\n\nA list of proposed projects is maintained at\n<https://wiki.octave.org/Projects>.\n\nBugs and patches\n----------------\n\nSee the file `BUGS` in this directory for more guidance on reporting bugs\nand preparing patches.\n\nSource code directory layout\n----------------------------\n\nAn overview of the directory layout of Octave's source files:\n\n- `build-aux`\n     scripts which support the build process.\n\n- `doc`\n     Texinfo and Doxygen documentation for Octave.\n\n- `etc`\n     miscellaneous files, such as this `HACKING` howto.\n\n- `examples`\n     some example files (`mkoctfile` and mex samples, old class\n     programming interface).\n\n- `gnulib`\n     gnulib repository.  This is a working copy of the gnulib git\n     repository.  We usually don't want to update gnulib sources when\n     going from one stable point release to the next.\n\n- `libgnu`\n     gnulib sources that we use.  These files are copied here from the\n     gnulib directory by the `bootstrap` script.\n\n- `liboctave`\n    C++ interfaces to the numerical libraries, Fortran numerical\n    libraries, various OS facilities, and utility functions.\n  - `array`\n       the base `Array`, `NDArray`, `Matrix`, and `Sparse` classes.\n  - `external`\n       various numerical libraries (mostly Fortran).\n    - `amos`        bessel functions\n    - `blas-xtra`   wrappers for blas functions used in Octave\n    - `daspk`       large scale differential algebraic equation solver\n    - `dasrt`       differential algebraic equation solver with root finding\n    - `dassl`       differential-algebraic system solver\n    - `fftpack`     subroutines for fast fourier transforms\n    - `lapack-xtra` wrappers for lapack functions used in Octave\n    - `odepack`     ordinary differential equation solver\n    - `quadpack`    subroutines for numerical integration\n    - `ranlib`      random number generators\n    - `slatec-err`  slatec error handling library\n    - `slatec-fn`   various special function subroutines\n  - `numeric`\n       C++ numerical algorithms and interfaces to the Fortran\n       algorithms.\n  - `operators`\n       code for operators that act on base classes (such as `Array`).\n  - `system`\n       OS-related functions.\n  - `util`\n       utility and miscellaneous functions.\n  - `wrappers`\n       C++ wrappers for gnulib functions written in C.\n\n- `libinterp`\n     the interpreter itself plus lots of infrastructure around it.\n     Octave's extensive `octave_value` class hierarchy for\n     polymorphically handling all Octave types is defined here.\n     The built-in functions are also defined here.\n  - `octave-value`\n       the `octave_value` class hierarchy.  These are the container\n       classes that hold various Octave data types like struct\n       numerical arrays, structure arrays, and cell arrays.\n  - `parse-tree`\n       Classes that define the parse tree for the interpreter.\n  - `corefcn`\n       statically linked `DEFUN` functions (callable from the\n       scripting language) as well as internal C++ functions used by\n       the interpreter.\n  - `dldfcn`\n       dynamically linked `DEFUN_DLD` functions (callable from the\n       scripting language).  If you see `help foo` telling you that\n       `foo` is defined in `foo.oct`, then `foo.cc` will be found\n       here and contain the source code.\n  - `operators`\n       definitions and template instantiations for operators for all\n       possible Octave type combinations.\n  - `template-inst`\n       some C++ template instantiations.\n\n- `libgui`\n     the graphical user interface of GNU Octave.\n  - `graphics`\n       Qt graphics toolkit (OpenGL plotting).\n  - `kb-layouts`\n       various files need by the qterminal widget that has been\n       derived from Konsole.\n  - `languages`\n       translation files and list of translators.\n  - `qterminal`\n       Qt terminal widget.\n  - `src`\n       source files for the GUI\n    - `icons`\n         icon files that will be compiled into the executable via a\n         resource file.\n    - `m-editor`\n         source files for the m-file editor.\n\n- `m4` m4 scripts used by configure during the build process.\n\n- `scripts` functions written in the Octave language.\n  - `@ftp`             ftp object class\n  - `+containers`      container classes (Map)\n  - `+matlab`          various functions under Matlab namespace\n  - `audio`            play and record sound files (system dependent)\n  - `deprecated`       older deprecated functions\n  - `elfun`            elementary mathematical functions\n  - `general`          utility functions\n  - `geometry`         geometry algorithms\n  - `gui`              User-Interface (UI) functions\n  - `help`             help subsystem functions\n  - `image`            image processing\n  - `io`               input/output functions\n  - `java`             java/Octave interface\n  - `legacy`           functions not recommended for use, but not deprecated\n  - `linear-algebra`   linear algebra\n  - `miscellaneous`    stuff that doesn't fit anywhere else\n  - `ode`              Ordinary Differential Equations\n  - `optimization`     zero finders and minimizers\n  - `path`             functions for path manipulation\n  - `pkg`              the package manager\n  - `plot`             plotting functions\n  - `polynomial`       polynomial manipulation\n  - `prefs`            user-defined preferences\n  - `profiler`         code profiler for performance\n  - `set`              set manipulation\n  - `signal`           signal processing\n  - `sparse`           sparse matrix support\n  - `specfun`          special mathematical functions\n  - `special-matrix`   functions for generating special types of matrices\n  - `startup`          initialization functions\n  - `statistics`       statistical functions, distributions, and tests\n  - `strings`          character string manipulation\n  - `testfun`          unit testing\n  - `time`             time and date functions\n  - `web`              web-related functions\n\n- `src`\n     code for the actual executables that are created.  This includes\n     `octave`, `octave-cli`, `octave-gui`, as well as `mkoctfile`.\n\n- `test`\n     tests for the interpreter.\n  - `*.tst`\n       fixed tests for the interpreter.\n  - `fntests.m`\n       script to run function tests embedded in C++ and .m files.\n\nRelease Numbering\n-----------------\n\nSince version 5, Octave uses the following rules for release numbering:\n\n    Version Dev. Phase      When\n\n    5.0.0   (experimental)  active development of Octave 5 on default branch\n    5.0.1   (pre-release)   stabilization period of Octave 5 on stable branch\n    5.0.90  (pre-release)   first release candidate for 5.1.0\n    5.0.91  (pre-release)   continued stabilization of Octave 5 on stable branch\n    5.0.92  (pre-release)   second release candidate for 5.1.0\n    6.0.0   (experimental)  active development of Octave 6 on default branch\n    5.1.0   (release)       first release of Octave 5 from stable branch\n    5.1.1   (pre-release)   bug fixing on stable branch after 5.1.0 release\n    5.2.0   (release)       second release of Octave 5 from stable branch\n    5.2.1   (pre-release)   bug fixing on stable branch after 5.2.0 release\n    ...     ...             ...\n\nTo summarize, the first release of Octave 5 is Octave 5.1.0 while development\nsnapshots are Octave 5.0.0 and snapshots from the release branch are Octave\n5.n.1.\n\nWith this numbering scheme:\n\n  * Any version X.0.0 means \"this is an experimental development version\".\n\n  * Any version X.Y.Z with Z > 0 means, \"this is a pre-release version\n    meant for bug fixing and testing\".  In practice, Z will be either 1\n    (stabilization period after and before making release candidates), or\n    90, 92, etc. (release candidate snapshots leading up to release), or\n    91, 93, etc. (stabilization period on stable branch during the\n    process of making release candidates).\n\n  * Any version X.Y.0 with Y != 0 means \"this is a released version\".\n\nShared Library Versioning\n-------------------------\n\nVersion numbers for the liboctave, liboctinterp, liboctgui, and libmex shared\nlibraries are set in the `module.mk` files in the top-level directory for each\nlibrary using the variables\n\n    %canon_reldir%_%canon_reldir%_current\n    %canon_reldir%_%canon_reldir%_revision\n    %canon_reldir%_%canon_reldir%_age\n\nThe rules for updating these version numbers are:\n\n  * Start with the existing version information for each libtool library in\n    the form `CURRENT:REVISION:AGE`.\n\n  * Update the version information only immediately before a public release of\n    the software.  This should happen at the time the first release candidate\n    is made.  More frequent updates are unnecessary, and only guarantee that\n    the current interface number gets larger faster.\n\n  * If any interfaces have been added, removed, or changed since the last\n    update, then increment current and set revision to 0 (`c:r:a` becomes\n    `c+1:0:a`).\n\n  * If current was _not_ incremented in the previous step, but the library\n    source code has changed in any way since the last update, then increment\n    revision (`c:r:a` becomes `c:r+1:a`).\n\n  * If any interfaces have been added since the last public release, then\n    increment age (`c:r:a` becomes `c:r:a+1`).\n\n  * If any interfaces have been removed or changed since the last public\n    release, then set age to 0 (`c:r:a` becomes `c:r:0`).\n\nNever try to set the interface numbers so that they correspond to the Octave\nversion number.  This is an abuse that only fosters misunderstanding of the\npurpose of library versions.\n\nThe following explanation may help to understand the above rules a bit better:\nconsider that there are three possible kinds of reactions from users of your\nlibrary to changes in a shared library:\n\n  * Programs using the previous version may use the new version as drop-in\n    replacement, and programs using the new version can also work with the\n    previous one.  In other words, no recompiling nor relinking is needed.\n    In this case, bump revision only, don’t touch current nor age.\n\n  * Programs using the previous version may use the new version as drop-in\n    replacement, but programs using the new version may use APIs not present\n    in the previous one.  In other words, a program linking against the new\n    version may fail with unresolved symbols if linking against the old\n    version at runtime: set revision to 0, bump current and age.\n\n  * Programs may need to be changed, recompiled, and relinked in order to use\n    the new version.  Bump current, set revision and age to 0.\n\nThese guidelines also appear in the GNU libtool manual where they are stated in\na slightly different but equivalent way.  See\n<https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html>.\n\nMerging the default branch to stable before a release\n-----------------------------------------------------\n\nTo merge default to stable for a release with version == MAJOR:\n\nNOTE, I use two separate repos, one in `/path/to/octave-stable` that is\nupdated to the stable branch and one in `/path/to/octave-default` that\nis updated to the default branch.\n\n1. Update the repo in `/path/to/octave-stable` to the most recent change on\n   the stable branch.  Ensure that there are no pending changes (be careful\n   to avoid wiping out any changes you are currently working on!):\n\n        cd /path/to/octave-stable\n        hg update -C stable\n\n2. Merge default to stable (there should never be any conflicts here;\n   you are just making the stable branch be whatever is on the current\n   default branch):\n\n        hg merge default\n\n3. Commit the change (in the commit message replace VERSION with the correct\n   version; it should be of the form \"MAJOR.1\"):\n\n        hg commit -m \"maint: Merge default to stable to begin VERSION release process.\"\n\n4. Bump version numbers and release date in `configure.ac` for pre-release:\n\n  * Set version in `AC_INIT` to MAJOR.0.1\n  * `OCTAVE_MAJOR_VERSION` should already be correct.\n  * Set `OCTAVE_MINOR_VERSION` to 0.\n  * Set `OCTAVE_PATCH_VERSION` to 1.\n  * Set `OCTAVE_RELEASE_DATE` to the current date.\n  * Set the year in `OCTAVE_COPYRIGHT` to the current year.\n    The copyright dates in the source files should have already been updated\n    during the development cycle.  If not, that should be done in a separate\n    change before the merge.\n\n        hg commit  # Use commit message similar to the one in 8f8fab4c93ae\n\n5. Update the repo in `/path/to/octave-default` to the most recent change on\n   the default branch.  Ensure that there are no pending changes (be careful\n   to avoid wiping out any changes you are currently working on!):\n\n        cd /path/to/octave-default\n        hg update -C default\n\n6. Merge stable back to default (there should not be conflicts in this\n   merge):\n\n        hg merge stable\n        hg commit -m \"maint: Merge stable to default.\"\n\n7. Bump versions in `configure.ac` to begin active development of MAJOR+1:\n\n  * Set version in `AC_INIT` to MAJOR+1.0.0\n  * Set `OCTAVE_MAJOR_VERSION` to MAJOR+1\n  * Set `OCTAVE_MINOR_VERSION` to 0\n  * Set `OCTAVE_PATCH_VERSION` to 0\n\n        hg commit  # Use commit message similar to the one in dc1347cab668\n\n8. Remove functions and properties deprecated in MAJOR-1 (see ecf207896f76,\n   for example)\n\n9. Create new `etc/NEWS.VERSION+1.md` file by copying `etc/NEWS.VERSION.md` and\n   then removing text so that it is a template file with headings only (see\n   0ec5eaabaf2c, for example).\n\nCreating first release candidate for new MAJOR version\n------------------------------------------------------\n\nThis requires updating the VERSION for Octave; the shared library `SOVERSION`\nfor each of `liboctave`, `liboctinterp`, `liboctgui`, and `libmex`; and\nthe oct-file version `OCTAVE_API_VERSION`.\n\n1. Bump version numbers and release date in `configure.ac` for release\n   candidate:\n\n  * Set version in `AC_INIT` to MAJOR.0.90\n  * `OCTAVE_MAJOR_VERSION` should already be correct (MAJOR).\n  * `OCTAVE_MINOR_VERSION` should already be correct (0).\n  * Set `OCTAVE_PATCH_VERSION` to 90.\n  * Set `OCTAVE_RELEASE_DATE` to the current date.\n  * Set the final year in `OCTAVE_COPYRIGHT` to the current year.\n\n2. Update `SOVERSION` numbers for shared libraries.\n\n    The version numbers for the `liboctave`, `liboctinterp`, `liboctgui`, and\n    `libmex` shared libraries are set in the `module.mk` file in the top-level\n    directory for each library using the variables\n\n        %canon_reldir%_%canon_reldir%_current\n        %canon_reldir%_%canon_reldir%_revision\n        %canon_reldir%_%canon_reldir%_age\n\n    1. Determine whether any API interface has been added, removed, or changed\n       by reviewing differencs in header files.  Follow guidelines in Shared\n       Library Versioning to update `_current`, `_revision`, and `_age`\n       fields.\n\n        hg diff --from release-9-4-0 -I 'liboctave/**.h'\n\n    2. **Only** if current was _not_ incremented in the previous step, verify\n       whether any source code changes have been made (this would require\n       incrementing revision).\n\n        hg diff --from release-9-4-0 -I liboctave\n\n3. Bump Octave API version for oct-files in `configure.ac`\n\n  * Increment `OCTAVE_API_VERSION` if any shared library version numbers have\n    had their CURRENT version field changed.\n\n\nMake Windows binaries\n------------------------------------------------------\n\nFIXME: Instructions needed by someone who can document the MXE build process.\n\n\n\\################################################################################\n\nCopyright (C) 2009-2026 The Octave Project Developers\n\nSee the file COPYRIGHT.md in the top-level directory of this\ndistribution or <https://octave.org/copyright/>.\n\nThis file is part of Octave.\n\nOctave is free software: you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nOctave is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with Octave; see the file COPYING.  If not, see\n<https://www.gnu.org/licenses/>.\n\n\nThis file was adapted for Octave from the HACKING file that is part of\nGNU Bison, which contained the following Copyright notice:\n\n  Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009\n  Free Software Foundation, Inc.\n\n  This file is part of GNU Bison.\n\n  This program is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  This program is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with this program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "etc/NEWS.1",
    "content": "Summary of changes for version 1.1.1 (1995-02-23):\n-------------------------------------------------\n\n  * New built-in variables, default_return_value and\n    define_all_return_values.\n\n    If define_all_return_values is set to \"false\", Octave does not do\n    anything special for return values that are left undefined, and\n    you will get an error message if you try to use them.  For\n    example, if the function\n\n      function [x, y] = f ()\n        y = 1;\n      endfunction\n\n    is called as\n\n      octave:13> [a, b] = f ()\n\n    Octave will print an error message for the attempt to assign an\n    undefined value to `a'.\n\n    This is incompatible with Matlab, which will define the return\n    variable `x' to be the empty matrix.  To get the Matlab-like\n    behavior, you can set the variable define_all_return_values to\n    \"true\" (the default is \"false\") and default_return_value to `[]'\n    (the default).  Then, any return values that remain undefined when\n    the function returns will be initialized to `[]'.\n\n    If the function is called without explicitly asking for an output,\n    it will succeed.  This behavior is compatible and unchanged from\n    previous versions of Octave.\n\n  * New built-in variable suppress_verbose_help_message.  If set to\n    \"true\", Octave will not add additional help information to the end\n    of the output from the help command and usage messages for\n    built-in commands.  The default value is \"false\".\n\n  * New built-in variable PS4 is used as the prefix of echoed input\n    (enabled with the --echo-input (-x) option).\n\n  * The function size() now accepts an optional second argument.\n\n  * Output from `save - ...' now goes through the pager.\n\n  * The break statement may also be used to exit a function, for\n    compatibility with Matlab.\n\n  * The directory tree for installing Octave is now closer to\n    conforming with the current GNU standards.\n\n  * More bug fixes.\n\nSummary of changes for version 1.1.0 (1995-01-12):\n-------------------------------------------------\n\n  * Octave now requires g++ 2.6.3 or later.  This change is necessary\n    to make template instantiations cleaner, and to avoid having to\n    have special cases in the code for earlier versions of gcc.\n\n  * A new data structure type has been added.  The implementation uses\n    an associative array with indices limited to strings, but the\n    syntax is more like C-style structures.  here are some examples of\n    using it.\n\n    Elements of structures can be of any type, including structures:\n\n      octave:1> x.a = 1;\n      octave:2> x.b = [1, 2; 3, 4];\n      octave:3> x.c = \"string\";\n      octave:4> x\n      x =\n\n      <structure: a b c>\n\n      octave:5> x.a\n      x.a = 1\n      octave:6> x.b\n      x.b =\n\n        1  2\n        3  4\n\n      octave:7> x.c\n      x.c = string\n      octave:8> x.b.d = 3\n      x.b.d = 3\n      octave:9> x.b\n      x.b =\n\n      <structure: d>\n\n      octave:10> x.b.d\n      x.b.d = 3\n\n    Functions can return structures:\n\n      octave:1> a = rand (3) + rand (3) * I;\n      octave:2> function y = f (x)\n      > y.re = real (x);\n      > y.im = imag (x);\n      > endfunction\n      octave:3> f (a)\n      ans =\n\n      <structure: im re>\n\n      octave:4> ans.im\n      ans.im =\n\n        0.093411  0.229690  0.627585\n        0.415128  0.221706  0.850341\n        0.894990  0.343265  0.384018\n\n      octave:5> ans.re\n      ans.re =\n\n        0.56234  0.14797  0.26416\n        0.72120  0.62691  0.20910\n        0.89211  0.25175  0.21081\n\n    Return lists can include structure elements:\n\n      octave:1> [x.u, x.s, x.v] = svd ([1, 2; 3, 4])\n      x.u =\n\n        -0.40455  -0.91451\n        -0.91451   0.40455\n\n      x.s =\n\n        5.46499  0.00000\n        0.00000  0.36597\n\n      x.v =\n\n        -0.57605   0.81742\n        -0.81742  -0.57605\n\n      octave:8> x\n      x =\n\n      <structure: s u v>\n\n    This feature should be considered experimental, but it seems to\n    work OK.  Suggestions for ways to improve it are welcome.\n\n  * Octave now supports a limited form of exception handling modeled\n    after the unwind-protect form of Lisp:\n\n      unwind_protect\n        BODY\n      unwind_protect_cleanup\n        CLEANUP\n      end_unwind_protect\n\n    Where BODY and CLEANUP are both optional and may contain any\n    Octave expressions or commands.  The statements in CLEANUP are\n    guaranteed to be executed regardless of how control exits BODY.\n\n    This is useful to protect temporary changes to global variables\n    from possible errors.  For example, the following code will always\n    restore the original value of the built-in variable\n    do_fortran_indexing even if an error occurs while performing the\n    indexing operation.\n\n      save_do_fortran_indexing = do_fortran_indexing;\n      unwind_protect\n        do_fortran_indexing = \"true\";\n        elt = a (idx)\n      unwind_protect_cleanup\n        do_fortran_indexing = save_do_fortran_indexing;\n      end_unwind_protect\n\n    Without unwind_protect, the value of do_fortran_indexing would not\n    be restored if an error occurs while performing the indexing\n    operation because evaluation would stop at the point of the error\n    and the statement to restore the value would not be executed.\n\n  * Recursive directory searching has been implemented using Karl\n    Berry's kpathsea library.  Directories below path elements that\n    end in // are searched recursively for .m files.\n\n  * Octave now waits for additional input when a pair of parentheses\n    is `open' instead of giving an error.  This allows one to write\n    statements like this\n\n      if (big_long_variable_name == other_long_variable_name\n          || not_so_short_variable_name > 4\n          && y > x)\n        some (code, here);\n\n    without having to clutter up the if statement with continuation\n    characters.\n\n  * Continuation lines are now allowed in string constants and are\n    handled correctly inside matrix constants.\n\n  * Both `...{whitespace}\\n' and `\\{whitespace}\\n' can be used to\n    introduce continuation lines, where {whitespace} may include\n    spaces, tabs and comments.\n\n  * The script directory has been split up by topic.\n\n  * Dynamic linking mostly works with dld.  The following limitations\n    are known problems:\n\n    -- Clearing dynamically linked functions doesn't work.\n\n    -- Dynamic linking only works with dld, which has not been ported\n       to very many systems yet.\n\n    -- Configuring with --enable-lite-kernel seems to mostly work to\n       make nonessential built-in functions dynamically loaded, but\n       there also seem to be some problems.  For example, fsolve seems\n       to always return info == 3.  This is difficult to debug since\n       GDB doesn't appear to allow breakpoints to be set inside\n       dynamically loaded functions.\n\n    -- Octave uses a lot of memory if the dynamically linked functions\n       are compiled with -g.  This appears to be a limitation with\n       dld, and can be avoided by not using -g to compile functions\n       that will be linked dynamically.\n\n  * fft2 and ifft2 are now built-in functions.\n\n  * The `&&' and `||' logical operators are now evaluated in a\n    short-circuit fashion and work differently than the element by\n    element operators `&' and `|'.  See the Octave manual for more\n    details.\n\n  * Expressions like 1./m are now parsed as 1 ./ m, not 1. / m.\n\n  * The replot command now takes the same arguments as gplot or\n    gsplot (except ranges, which cannot be respecified with replot\n    (yet)) so you can add additional lines to existing plots.\n\n  * The hold command has been implemented.\n\n  * New function `clearplot' clears the plot window.  The name `clg'\n    is aliased to `clearplot' for compatibility with Matlab.\n\n  * The commands `gplot clear' and `gsplot clear' are equivalent to\n    `clearplot'.  (Previously, `gplot clear' would evaluate `clear' as\n    an ordinary expression and clear all the visible variables.)\n\n  * The Matlab-style plotting commands have been improved.  They now\n    accept line-style arguments, multiple x-y pairs, and other plot\n    option flags.  For example,\n\n      plot (x, y, \"@12\", x, y2, x, y3, \"4\", x, y4, \"+\")\n\n    results in a plot with\n\n      y  plotted with points of type 2 (\"+\") and color 1 (red).\n      y2 plotted with lines.\n      y3 plotted with lines of color 4.\n      y4 plotted with points which are \"+\"s.\n\n    the help message for `plot' and `plot_opt' provide full\n    descriptions of the options.\n\n  * NaN is now dropped from plot data, and Inf is converted to a\n    very large value before calling gnuplot.\n\n  * Improved load and save commands:\n\n    -- The save and load commands can now read and write a new binary\n       file format.  Conversion to and from IEEE big and little endian\n       formats is handled automatically.  Conversion for other formats\n       has not yet been implemented.\n\n    -- The load command can now read Matlab .mat files, though it is\n       not yet able to read sparse matrices or handle conversion for\n       all data formats.\n\n    -- The save command can write Matlab .mat files.\n\n    -- The load command automatically determines the save format\n       (binary, ascii, or Matlab binary).\n\n    -- The default format for the save command is taken from the\n       built-in variable `default_save_format'.\n\n    -- The save and load commands now both accept a list of globbing\n       patterns so you can easily load a list of variables from a\n       file.\n\n    -- The load command now accepts the option -list, for listing the\n       variable names without actually loading the data.  With\n       -verbose, it prints a long listing.\n\n    -- The load command now accepts the option -float-binary, for\n       saving floating point data in binary files in single precision.\n\n  * who and whos now accept a list of globbing patterns so you can\n    limit the lists of variables and functions to those that match a\n    given set of patterns.\n\n  * New functions for manipulating polynomials\n\n      compan     -- companion matrix corresponding to polynomial coefficients\n      conv       -- convolve two vectors\n      deconv     -- deconvolve two vectors\n      roots      -- find the roots of a polynomial\n      poly       -- characteristic polynomial of a matrix\n      polyderiv  -- differentiate a polynomial\n      polyinteg  -- integrate a polynomial\n      polyreduce -- reduce a polynomial to minimum number of terms\n      polyval    -- evaluate a polynomial at a point\n      polyvalm   -- evaluate a polynomial in the matrix sense\n      residue    -- partial fraction expansion corresponding to the ratio\n                    of two polynomials\n\n  * New functions for manipulating sets\n\n      create_set   -- create a set of unique values\n      complement   -- find the complement of two sets\n      intersection -- find the intersection of two sets\n      union        -- find the union of two sets\n\n  * New elementary functions:\n\n      acot   acoth   acsc   acsch\n      asec   asech   cot    coth\n      csc    csch    log2   sec\n      sech\n\n  * New special functions:\n\n      beta   -- beta function\n      betai  -- incomplete beta function\n      gammai -- incomplete gamma function\n\n  * New image processing functions:\n\n      colormap  -- set and return current colormap\n      gray      -- set a gray colormap\n      gray2ind  -- image format conversion\n      image     -- display an image\n      imagesc   -- scale and display an image\n      imshow    -- display images\n      ind2gray  -- image format conversion\n      ind2rgb   -- image format conversion\n      loadimage -- load an image from a file\n      ntsc2rgb  -- image format conversion\n      ocean     -- set a color colormap\n      rgb2ind   -- image format conversion\n      rgb2ntsc  -- image format conversion\n      saveimage -- save an image to a file\n\n  * New time and date functions:\n\n      tic          -- set wall-clock timer\n      toc          -- get elapsed wall-clock time, since timer last set\n      etime        -- another way to get elapsed wall-clock time\n      cputime      -- get CPU time used since Octave started\n      is_leap_year -- is the given year a leap year?\n\n  * Other new functions:\n\n      bug_report -- submit a bug report to the bug-octave mailing list\n\n      toascii -- convert a string to a matrix of ASCII character codes\n\n      octave_tmp_file -- generate a unique temporary file name\n\n      undo_string_escapes -- replace special characters in a string by\n                             their backslash forms\n\n      is_struct -- determine whether something is a structure data type\n\n      feof   -- check EOF condition for a specified file\n      ferror -- check error state for a specified file\n      fread  -- read binary data from a file\n      fwrite -- write binary data to a file\n\n      file_in_path -- check to see if named file exists in given path\n\n      kbhit  -- get a single character from the terminal\n\n      axis   -- change plot ranges\n      hist   -- plot histograms\n\n      diary  -- save commands and output to a file\n\n      type   -- show the definition of a function\n      which  -- print the type of an identifier or the location of a\n                function file\n\n      isieee  -- Returns 1 if host uses IEEE floating point\n      realmax -- Returns largest floating point number\n      realmin -- Returns smallest floating point number\n\n      gcd     -- greatest common divisor\n      lcm     -- least common multiple\n\n      null    -- orthonormal basis of the null space of a matrix\n      orth    -- orthonormal basis of the range space of a matrix\n\n      fft2    -- two-dimensional fast fourier transform\n      ifft2   -- two-dimensional inverse fast fourier transform\n      filter  -- digital filter\n      fftfilt -- filter using fft\n      fftconv -- convolve to vectors using fft\n      sinc    -- returns sin(pi*x)/(pi*x)\n      freqz   -- compute the frequency response of a filter\n\n  * The meaning of nargin (== args.length ()) in built-in functions\n    has been changed to match the meaning of nargin in user-defined\n    functions.\n\n  * Variable return lists.  Octave now has a real mechanism for\n    handling functions that return an unspecified number of values,\n    so it is no longer necessary to place an upper bound on the number\n    of outputs that a function can produce.\n\n    Here is an example of a function that uses the new syntax to\n    produce n values:\n\n      function [...] = foo (n)\n        for i = 1:n\n          vr_val (i * x);\n        endfor\n      endfunction\n\n  * New keyword, all_va_args, that allows the entire list of va_args\n    to be passed to another function.  For example, given the functions\n\n      function f (...)\n        while (nargin--)\n          disp (va_arg ())\n        endwhile\n      endfunction\n      function g (...)\n        f (\"begin\", all_va_args, \"end\")\n      endfunction\n\n    the statement\n\n      g (1, 2, 3)\n\n    prints\n\n      begin\n      1\n      2\n      3\n      end\n\n    all_va_args may be used more than once, but can only be used\n    within functions that take a variable number of arguments.\n\n  * If given a second argument, svd now returns an economy-sized\n    decomposition, eliminating the unnecessary rows or columns of U or\n    V.\n\n  * The max and min functions correctly handle complex matrices in\n    which some columns contain real values only.\n\n  * The find function now handles 2 and 3 output arguments.\n\n  * The qr function now allows computation of QR with pivoting.\n\n  * hilb() is much faster for large matrices.\n\n  * computer() is now a built-in function.\n\n  * pinv() is now a built-in function.\n\n  * The output from the history command now goes through the pager.\n\n  * If a function is called without assigning the result, nargout is\n    now correctly set to 0.\n\n  * It is now possible to write functions that only set some return\n    values.  For example, calling the function\n\n      function [x, y, z] = f () x = 1; z = 2; endfunction\n\n    as\n\n      [a, b, c] = f ()\n\n    produces:\n\n      a = 1\n\n      b = [](0x0)\n\n      c = 2\n\n  * The shell_cmd function has been renamed to system (the name\n    shell_cmd remains for compatibility).  It now returns [output, status].\n\n  * New built-in variable `OCTAVE_VERSION'.  Also a new function,\n    version, for compatibility with Matlab.\n\n  * New built-in variable `automatic_replot'.  If it is \"true\", Octave\n    will automatically send a replot command to gnuplot each time the\n    plot changes.  Since this is fairly inefficient, the default value\n    is \"false\".\n\n  * New built-in variable `whitespace_in_literal_matrix' allows some\n    control over how Octave decides to convert spaces to commas in\n    matrix expressions like `[m (1)]'.\n\n    If the value of `whitespace_in_literal_matrix' is \"ignore\", Octave\n    will never insert a comma or a semicolon in a literal matrix list.\n    For example, the expression `[1 2]' will result in an error\n    instead of being treated the same as `[1, 2]', and the expression\n\n      [ 1, 2,\n        3, 4 ]\n\n    will result in the vector [1 2 3 4] instead of a matrix.\n\n    If the value of `whitespace_in_literal_matrix' is \"traditional\",\n    Octave will convert spaces to a comma between identifiers and `('.\n    For example, given the matrix\n\n      m = [3 2]\n\n    the expression\n\n      [m (1)]\n\n    will be parsed as\n\n      [m, (1)]\n\n    and will result in\n\n      [3 2 1]\n\n    and the expression\n\n      [ 1, 2,\n        3, 4 ]\n\n    will result in a matrix because the newline character is converted\n    to a semicolon (row separator) even though there is a comma at the\n    end of the first line (trailing commas or semicolons are ignored).\n    This is apparently how Matlab behaves.\n\n    Any other value for `whitespace_in_literal_matrix' results in\n    behavior that is the same as traditional, except that Octave does\n    not convert spaces to a comma between identifiers and `('.\n    For example, the expression\n\n      [m (1)]\n\n    will produce 3.  This is the way Octave has always behaved.\n\n  * Line numbers in error messages for functions defined in files and\n    for script files now correspond to the file line number, not the\n    number of lines after the function keyword appeared.\n\n  * Octave now extracts help from script files.  The comments must\n    come before any other statements in the file.\n\n  * In function files, the first block of comments in the file will\n    now be interpreted as the help text if it doesn't look like the\n    Octave copyright notice.  Otherwise, Octave extracts the first set\n    of comments after the function keyword.\n\n  * The function clock is more accurate on systems that have the\n    gettimeofday() function.\n\n  * The standard output stream is now automatically flushed before\n    reading from stdin with any of the *scanf() functions.\n\n  * Expanded reference card.\n\n  * The Octave distribution now includes a frequently asked questions\n    file, with answers.  Better answers and more questions (with\n    answers!) are welcome.\n\n  * New option --verbose.  If Octave is invoked with --verbose and not\n    --silent, a message is printed if an octaverc file is read while\n    Octave is starting.\n\n  * An improved configure script generated by Autoconf 2.0.\n\n  * Lots of bug fixes.\n\nSummary of changes for version 1.0 (1994-02-17):\n-----------------------------------------------\n\n  * C-style I/O functions now handle files referenced by name or by\n    number more consistently.\n\nSummary of changes for version 0.83 (1994-02-13):\n------------------------------------------------\n\n  * Loading global symbols should work now.\n\n  * Clearing the screen doesn't reprint the prompt unnecessarily.\n\n  * The operations <complex scalar> OP <real matrix> for OP == +, -,\n    *, or ./ no longer crash Octave.\n\n  * More portability and configuration fixes.\n\nSummary of changes for version 0.82 (1994-02-08):\n------------------------------------------------\n\n  * Octave now comes with a reference card.\n\n  * The manual has been improved, but more work remains to be done.\n\n  * The atanh function now works for complex arguments.\n\n  * The asin, acos, acosh, and atanh functions now work properly when\n    given real-valued arguments that produce complex results.\n\n  * SEEK_SET, SEEK_CUR, and SEEK_END are now constants.\n\n  * The `using' qualifier now works with gplot and gsplot when the\n    data to plot is coming directly from a file.\n\n  * The strcmp function now works correctly for empty strings.\n\n  * Eliminated bogus parse error for M-files that don't end with `end'\n    or `endfunction'.\n\n  * For empty matrices with one nonzero dimension, the +, -, .*, and\n    ./ operators now correctly preserve the dimension.\n\n  * Octave no longer crashes if you type ^D at the beginning of a line\n    in the middle of defining a loop or if statement.\n\n  * On AIX systems, Back off on indexing DiagArray via Proxy class to\n    avoid gcc (or possibly AIX assembler?) bug.\n\n  * Various other bug and portability fixes.\n\nSummary of changes for version 0.81 (1994-01-28):\n------------------------------------------------\n\n  * Octave no longer dumps core if you try to define a function in\n    your .octaverc file.\n\n  * Fixed bug in Array class that resulted in bogus off-diagonal\n    elements when computing eigenvalue and singular value\n    decompositions.\n\n  * Fixed bug that prevented lsode from working on the SPARCstation,\n    at least with some versions of Sun's f77.  This bug was introduced\n    in 0.80, when I changed LSODE to allow the user to abort the\n    integration from within the RHS function.\n\n  * Fixed bug that prevented global attribute of variables from being\n    saved with save(), and another that prevented load() from working\n    at all.\n\nSummary of changes for version 0.80 (1994-01-18):\n------------------------------------------------\n\n  * I have started working on a manual for the C++ classes.  At this\n    point, it is little more than a list of function names.  If you\n    would like to volunteer to help work on this, please contact\n    maintainers@octave.org.\n\n  * The patterns accepted by the save and clear commands now work like\n    file name globbing patterns instead of regular expressions.  I\n    apologize for any inconvenience this change may cause, but file\n    name globbing seems like a more reasonable style of pattern\n    matching for this purpose.\n\n  * It is now possible to specify tolerances and other optional inputs\n    for dassl, fsolve, lsode, npsol, qpsol, and quad.  For each of\n    these functions, there is a corresponding function X_options,\n    which takes a keyword and value arguments.  If invoked without any\n    arguments, the X_options functions print a list of possible\n    keywords and current values.  For example,\n\n      npsol_options ()\n\n    prints a list of possible options with values, and\n\n      npsol_options (\"major print level\", 10)\n\n    sets the major print level to 10.\n\n    The keyword match is not case sensitive, and the keywords may be\n    abbreviated to the shortest unique match.  For example,\n\n      npsol_options (\"ma p\", 10)\n\n    is equivalent to the statement shown above.\n\n  * The new built-in variable save_precision can be used to set the\n    number of digits preserved by the ASCII save command.\n\n  * Assignment of [] now works in most cases to allow you to delete\n    rows or columns of matrices and vectors.  For example, given a\n    4x5 matrix A, the assignment\n\n      A (3, :) = []\n\n    deletes the third row of A, and the assignment\n\n      A (:, 1:2:5) = []\n\n    deletes the first, third, and fifth columns.\n\n  * Variable argument lists.  Octave now has a real mechanism for\n    handling functions that take an unspecified number of arguments,\n    so it is no longer necessary to place an upper bound on the number\n    of optional arguments that a function can accept.\n\n    Here is an example of a function that uses the new syntax to print\n    a header followed by an unspecified number of values:\n\n      function foo (heading, ...)\n        disp (heading);\n        va_start ();\n        while (--nargin)\n          disp (va_arg ());\n        endwhile\n      endfunction\n\n    Note that the argument list must contain at least one named\n    argument (this restriction may eventually be removed), and the\n    ellipsis must appear as the last element of the argument list.\n\n    Calling va_start() positions an internal pointer to the first\n    unnamed argument and allows you to cycle through the arguments\n    more than once.  It is not necessary to call va_start() if you\n    do not plan to cycle through the arguments more than once.\n\n  * Recursive functions should work now.\n\n  * The environment variable OCTAVE_PATH is now handled in the same\n    way as TeX handles TEXINPUTS.  If the path starts with `:', the\n    standard path is prepended to the value obtained from the\n    environment.  If it ends with `:' the standard path is appended to\n    the value obtained from the environment.\n\n  * New functions, from Kurt Hornik (hornik@neuro.tuwien.ac.at) and\n    the Department of Probability Theory and Statistics TU Wien,\n    Austria:\n\n     corrcoef    -- corrcoef (X, Y) is the correlation between the i-th\n                    variable in X and the j-th variable in Y\n                    corrcoef (X) is corrcoef (X, X)\n     cov         -- cov (X, Y) is the covariance between the i-th\n                    variable in X and the j-th variable in Y\n                    cov (X) is cov (X, X)\n     gls         -- generalized least squares estimation\n     kurtosis    -- kurtosis(x) = N^(-1) std(x)^(-4) SUM_i (x(i)-mean(x))^4 - 3\n                    If x is a matrix, return the row vector containing\n                    the kurtosis of each column\n     mahalanobis -- returns Mahalanobis' D-square distance between the\n                    multivariate samples X and Y, which must have the\n                    same number of components (columns), but may have\n                    a different number of observations (rows)\n     ols         -- ordinary least squares estimation\n     pinv        -- returns the pseudoinverse of X; singular values\n                    less than tol are ignored\n     skewness    -- skewness (x) = N^(-1) std(x)^(-3) SUM_i (x(i)-mean(x))^3\n                    if x is a matrix, return the row vector containing\n                    the skewness of each column\n\n  * Errors in user-supplied functions called from dassl, fsolve,\n    lsode, npsol, and quad are handled more gracefully.\n\n  * Programming errors in the use of the C++ classes within Octave\n    should no longer cause Octave to abort.  Instead, Octave's error\n    handler function is called and execution continues as best as is\n    possible.  This should result in eventually returning control to\n    the top-level Octave prompt.  (It would be nice to have a real\n    exception handling mechanism...)\n\n  * A number of memory leaks have been eliminated.  Thanks to\n    Fong Kin Fui <fui@ee.nus.sg> for reporting them.\n\n  * The C++ matrix classes are now derived from a generic\n    template-based array class.\n\n  * The readline function operate-and-get-next (from bash) is now\n    available and bound to C-O by default.\n\n  * Octave now uses the version of readline currently distributed with\n    bash-1.13.  On some systems, interactive invocations of Octave\n    will now blink the cursor to show matching parens.\n\n  * By default, include files are now installed in\n    $prefix/include/octave instead of $prefix/include.\n\n  * Octave now uses a config.h file instead of putting all defines on\n    the compiler command line.\n\nSummary of changes for version 0.79 (1993-11-08):\n------------------------------------------------\n\n  * New control systems functions:\n\n     dgram -- Returns the discrete controllability and observability gramian.\n     dlqr  -- Discrete linear quadratic regulator design.\n     dlqe  -- Discrete linear quadratic estimator (Kalman Filter) design.\n     c2d   -- Convert continuous system description to discrete time\n              description assuming zero-order hold and given sample time.\n\n  * The max (min) functions can now return the index of the max (min)\n    value as a second return value.\n\nSummary of changes for version 0.78 (1993-11-05):\n------------------------------------------------\n\n  * Octave's handling of global variables has been completely\n    rewritten.  To access global variables inside a function, you must\n    now declare them to be global within the function body.  Likewise,\n    if you do not declare a variable as global at the command line,\n    you will not have access to it within a function, even if it is\n    declared global there.  For example, given the function\n\n      function f ()\n        global x = 1;\n        y = 2;\n      endfunction\n\n    the global variable `x' is not visible at the top level until the\n    command\n\n      octave:13> global x\n\n    has been evaluated, and the variable `y' remains local to the\n    function f() even if it is declared global at the top level.\n\n    Clearing a global variable at the top level will remove its global\n    scope and leave it undefined.  For example,\n\n      octave:1> function f ()   # Define a function that accesses\n      >  global x;              #   the global variable `x'.\n      >  x\n      > endfunction\n      octave:2> global x = 1    # Give the variable `x' a value.\n      octave:3> f ()            # Evaluating the function accesses the\n      x = 1                     #   global `x'.\n      octave:4> clear x         # Remove `x' from global scope, clear value.\n      octave:5> x = 2           # Define new local `x' at the top level\n      x = 2\n      octave:6> f               # The global `x' is no longer defined.\n      error: `x' undefined near line 1 column 25\n      error: evaluating expression near line 1, column 25\n      error: called from `f'\n      octave:7> x               # But the local one is.\n      x = 2\n\n  * The new function, `is_global (string)' returns 1 if the variable\n    named by string is globally visible.  Otherwise, returns 0.\n\n  * The implementation of `who' has changed.  It now accepts the\n    following options:\n\n      -b -builtins   -- display info for built-in variables and functions\n      -f -functions  -- display info for currently compiled functions\n      -v -variables  -- display info for user variables\n      -l -long       -- display long info\n\n    The long output looks like this:\n\n      octave:5> who -l\n\n      *** currently compiled functions:\n\n      prot  type               rows   cols  name\n      ====  ====               ====   ====  ====\n       wd   user function         -      -  f\n\n      *** local user variables:\n\n      prot  type               rows   cols  name\n      ====  ====               ====   ====  ====\n       wd   real scalar           1      1  y\n\n      *** globally visible user variables:\n\n      prot  type               rows   cols  name\n      ====  ====               ====   ====  ====\n       wd   complex matrix       13     13  x\n\n    where the first character of the `protection' field is `w' if the\n    symbol can be redefined, and `-' if it has read-only access.  The\n    second character may be `d' if the symbol can be deleted, or `-'\n    if the symbol cannot be cleared.\n\n  * The new built-in variable ignore_function_time_stamp can be used\n    to prevent Octave from calling stat() each time it looks up\n    functions defined in M-files.  If set to \"system\", Octave will not\n    automatically recompile M-files in subdirectories of\n    $OCTAVE_HOME/lib/VERSION if they have changed since they were last\n    compiled, but will recompile other M-files in the LOADPATH if they\n    change.  If set to \"all\", Octave will not recompile any M-files\n    unless their definitions are removed with clear.  For any other\n    value of ignore_function_time_stamp, Octave will always check to\n    see if functions defined in M-files need to recompiled.  The\n    default value of ignore_function_time_stamp is \"system\".\n\n  * The new built-in variable EDITOR can be used to specify the editor\n    for the edit_history command.  It is set to the value of the\n    environment variable EDITOR, or `vi' if EDITOR is not set, or is\n    empty.\n\n  * There is a new built-in variable, INFO_FILE, which is used as the\n    location of the info file.  Its initial value is\n    $OCTAVE_HOME/info/octave.info, so `help -i' should now work\n    provided that OCTAVE_HOME is set correctly, even if Octave is\n    installed in a directory different from that specified at compile\n    time.\n\n  * There is a new command line option, --info-file FILE, that may be\n    used to set Octave's idea of the location of the info file.  It\n    will override any value of OCTAVE_INFO_FILE found in the\n    environment, but not any INFO_FILE=\"filename\" commands found in\n    the system or user startup files.\n\n  * Octave's Info reader will now recognize gzipped files that have\n    names ending in `.gz'.\n\n  * The save command now accepts regular expressions as arguments.\n    Note that these patterns are regular expressions, and do not work\n    like filename globbing.  For example, given the variables `a',\n    `aa', and `a1', the command `save a*' saves `a' and `aa' but not\n    `a1'.  To match all variables beginning with `a', you must use an\n    expression like `a.*' (match all sequences beginning with `a'\n    followed by zero or more characters).\n\n  * Line and column information is included in more error messages.\n\nSummary of changes for version 0.77 (1993-10-23):\n------------------------------------------------\n\n  * Improved help.  The command `help -i topic' now uses the GNU Info\n    browser to display help for the given topic directly from the\n    Texinfo documentation.\n\n  * New function: chol -- Cholesky factorization.\n\nSummary of changes for version 0.76 (1993-10-05):\n------------------------------------------------\n\n  * Better run-time error messages.  Many now include line and column\n    information indicating where the error occurred.  Octave will also\n    print a traceback for errors occurring inside functions. If you\n    find error messages that could use improvement, or errors that\n    Octave fails to catch, please send a bug report to\n    bug@octave.org.\n\n  * If gplot (or gsplot) is given a string to plot, and the string\n    does not name a file, Octave will pass the string along to gnuplot\n    directly.  This allows commands like\n\n      gplot \"sin (x)\" w l, data w p\n\n    to work (assuming that data is a variable containing a matrix of\n    values).\n\n  * Long options (--help, --version, etc.) are supported.\n\nSummary of changes for version 0.75 (1993-09-15):\n------------------------------------------------\n\n  * The documentation is much more complete, but still could use a lot\n    of work.\n\n  * The history function now prints line numbers by default.  The\n    command `history -q' will  omit them.\n\n  * The clear function now accepts regular expressions.\n\n  * If gplot (or gsplot) is given a string to plot, and the string\n    names a file, Octave attempts to plot the contents of the file.\n\n  * New functions:\n\n    history:\n\n      run_history  -- run commands from the history list.\n      edit_history -- edit commands from the history list with your\n                      favorite editor.\n\n    linear algebra:\n\n      balance         -- Balancing for algebraic and generalized\n                         eigenvalue problems.\n      givens          -- Givens rotation.\n      is_square       -- Check to see if a matrix is square.\n      qzhess          -- QZ decomposition of the matrix pencil (a - lambda b).\n      qzval           -- Generalized eigenvalues for real matrices.\n      syl             -- Sylvester equation solver.\n\n    control systems:\n\n      is_symmetric    -- Check to see if a matrix is symmetric.\n      abcddim         -- Check dimensions of linear dynamic system [A,B,C,D].\n      is_controllable -- Check to see if [A,B,C,D] is controllable.\n      is_observable   -- Check to see if [A,B,C,D] is observable.\n      are             -- Solve algebraic Ricatti equation.\n      dare            -- Solve discrete-time algebraic Ricatti equation.\n      lqe             -- Kalman filter design for continuous linear system.\n      lqr             -- Linear Quadratic Regulator design.\n      lyap            -- Solve Lyapunov equation.\n      dlyap           -- Solve discrete Lyapunov equation.\n      tzero           -- Compute the transmission zeros of [A,B,C,D].\n\nSummary of changes for version 0.74 (1993-07-20):\n------------------------------------------------\n\n  * Formal parameters to functions are now always considered to be\n    local variables, so things like\n\n      global x = 0\n      global y = 0\n      function y = f (x) x = 1; y = x; end\n      f (x)\n\n    result in the function returning 1, with the global values of x\n    and y unchanged.\n\n  * Multiple assignment expressions are now allowed to take indices,\n    so things like\n\n      octave:13> [a([1,2],[3,4]), b([5,6],[7,8])] = lu ([1,2;3,4])\n\n    will work correctly.\n\nSummary of changes for version 0.73 (1993-07-10):\n------------------------------------------------\n\n  * Saving and loading global variables works correctly now.\n\n  * The save command no longer saves built-in variables.\n\n  * Global variables are more reliable.\n\n  * Matrices may now have one or both dimensions zero, so that\n    operations on empty matrices are now handled more consistently.\n\n    By default, dimensions of the empty matrix are now printed along\n    with the empty matrix symbol, `[]'.  For example:\n\n      octave:13> zeros (3, 0)\n      ans =\n\n      [](3x0)\n\n    The new variable `print_empty_dimensions' controls this behavior.\n\n    See also Carl de Boor, An Empty Exercise, SIGNUM, Volume 25,\n    pages 2--6, 1990, or C. N. Nett and W. M. Haddad, A\n    System-Theoretic Appropriate Realization of the Empty Matrix\n    Concept, IEEE Transactions on Automatic Control, Volume 38,\n    Number 5, May 1993.\n\n  * The right and left division operators `/' and `\\' will now find a\n    minimum norm solution if the system is not square, or if the\n    coefficient matrix is singular.\n\n  * New functions:\n\n      hess   -- Hessenberg decomposition\n      schur  -- Ordered Schur factorization\n      perror -- print error messages corresponding to error codes\n                returned from the functions fsolve, npsol, and qpsol\n                (with others to possibly be added later).\n\n  * Octave now prints a warning if it finds anything other than\n    whitespace or comments after the final `end' or `endfunction'\n    statement.\n\n  * The bodies of functions, and the for, while, and if commands are\n    now allowed to be empty.\n\n  * Support for Gill and Murray's QPSOL has been added.  Like NPSOL,\n    QPSOL is not freely redistributable either, so you must obtain\n    your own copy to be able to use this feature.  More information\n    about where to find QPSOL and NPSOL are in the file README.NLP.\n\nSummary of changes for version 0.72 (1993-06-10):\n------------------------------------------------\n\n  * For numeric output, columns are now lined up on the decimal point.\n    (This requires libg++-2.3.1 or later to work correctly).\n\n  * If octave is running interactively and the output intended for the\n    screen is longer than one page and a pager is available, it is\n    sent to the pager through a pipe.  You may specify the program to\n    use as the pager by setting the variable PAGER.  PAGER may also\n    specify a command pipeline.\n\n  * Spaces are not always significant inside square brackets now, so\n    commands like\n\n      [ linspace (1, 2) ]\n\n    will work.  However, some possible sources of confusion remain\n    because Octave tries (possibly too hard) to determine exactly what\n    operation is intended from the context surrounding an operator.\n    For example:\n\n    -- In the command\n\n         [ 1 - 1 ]\n\n       the `-' is treated as a binary operator and the result is the\n       scalar 0, but in the command\n\n         [ 1 -1 ]\n\n       the `-' is treated as a unary operator and the result is the\n       vector [ 1 -1 ].\n\n    -- In the command\n\n         a = 1; [ 1 a' ]\n\n       the single quote character `'' is treated as a transpose operator\n       and the result is the vector [ 1 1 ], but in the command\n\n         a = 1; [ 1 a ' ]\n\n       an error message indicating an unterminated string constant is\n       printed.\n\n  * Assignments are just expressions now, so they are valid anywhere\n    other expressions are.  This means that things like\n\n      if (a = n < m) ... endif\n\n    are valid.  This is parsed as:  compare `n < m', assign the result\n    to the variable `a', and use it as the test expression in the if\n    statement.\n\n    To help avoid errors where `=' has been used but `==' was\n    intended, Octave issues a warning suggesting parenthesis around\n    assignments used as truth values.  You can suppress this warning\n    by adding parenthesis, or by setting the value of the new built-in\n    variable `warn_assign_as_truth_value' to 'false' (the default\n    value is 'true').\n\n    This is also true for multiple assignments, so expressions like\n\n      [a, b, c] = [u, s, v] = expression\n\n    are now possible.  If the expression is a function, nargout is set\n    to the number of arguments for the right-most assignment.  The\n    other assignments need not contain the same number of elements.\n    Extra left hand side variables in an assignment become undefined.\n\n  * The default line style for plots is now `lines' instead of\n    `points'.  To change it, use the `set data style STYLE' command.\n\n  * New file handling and I/O functions:\n\n      fopen    -- open a file for reading or writing\n      fclose   -- close a file\n      fflush   -- flush output to a file\n      fgets    -- read characters from a file\n      frewind  -- set file position to the beginning of a file\n      fseek    -- set file position\n      ftell    -- tell file position\n      freport  -- print a report for all open files\n      fscanf   -- read from a file\n      sscanf   -- read from a string\n      scanf    -- read from the standard input\n\n  * New built-in variables for file and I/O functions:\n\n      stdin    -- file number corresponding to the standard input stream.\n      stdout   -- file number corresponding to the standard output stream.\n      stderr   -- file number corresponding to the standard error stream.\n\n    The following may be used as the final (optional) argument for\n    fseek:\n\n      SEEK_SET -- set position relative to the beginning of the file.\n      SEEK_CUR -- set position relative to the current position.\n      SEEK_END -- set position relative to the end of the file.\n\n  * New function: setstr -- convert vectors or scalars to strings\n    (doesn't work for matrices yet).\n\n  * If possible, computer now prints the system type instead of\n    always printing `Hi Dave, I'm a HAL-9000'.\n\n  * Octave now properly saves and restores its internal state\n    correctly in more places.  Interrupting Octave while it is\n    executing a script file no longer causes it to exit.\n\n  * Octave now does tilde expansion on each element of the LOADPATH.\n\n  * A number of memory leaks have been plugged.\n\n  * Dependencies for C++ source files are now generated automatically\n    by g++.\n\n  * There is a new command line option, -p PATH, that may be used to\n    set Octave's loadpath from the command line.  It will override any\n    value of OCTAVE_PATH found in the environment, but not any\n    LOADPATH=\"path\" commands found in the system or user startup files.\n\n  * It is now possible to override Octave's default idea of the\n    location of the system-wide startup file (usually stored in\n    $(prefix)/lib/octave/octaverc) using the environment variable\n    OCTAVE_HOME.  If OCTAVE_HOME has a value, Octave will look for\n    octaverc and its M-files in the directory $OCTAVE_HOME/lib/octave.\n\n    This allows people who are using binary distributions (as is\n    common with systems like Linux) to install the real octave binary\n    in any directory (using a name like octave.bin) and then install\n    a simple script like this\n\n      #!/bin/sh\n      OCTAVE_HOME=/foo/bar/baz\n      export OCTAVE_HOME\n      exec octave.bin\n\n    to be invoked as octave.\n\n\nSummary of changes for version 0.71 (1993-04-15):\n------------------------------------------------\n\n  * Much improved plotting facility.  With this release, Octave does\n    not require a specially modified version of gnuplot, so gnuplot\n    sources are no longer distributed with Octave.  For a more\n    detailed description of the new plotting features, see the file\n    PLOTTING.\n\n  * New plotting commands:\n\n      plot            -- 2D plots\n      semilogx        -- 2D semilog plot with logscale on the x axis\n      semilogy        -- 2D semilog plot with logscale on the y axis\n      loglog          -- 2D log-log plot\n      mesh            -- 3D mesh plot\n      meshdom         -- create matrices for 3D plotting from two vectors\n      contour         -- contour plots of 3D data\n      bar             -- create bar graphs\n      stairs          -- create stairstep plots\n      polar           -- 2D plots from theta-R data\n      grid            -- turn plot grid lines on or off\n      xlabel, ylabel  -- place labels on the x and y axes of 2D plots\n      sombrero        -- demonstrate 3D plotting\n      gplot           -- 2D plot command with gnuplot-like syntax\n      gsplot          -- 3D plot command with gnuplot-like syntax\n      set             -- set plot options with gnuplot syntax\n      show            -- show plot options with gnuplot syntax\n      closeplot       -- close stream to gnuplot process\n      purge_tmp_files -- delete temporary files created by plot command\n\n  * Other new commands:\n\n      ls, dir         -- print a directory listing\n      shell_cmd       -- execute shell commands\n      keyboard        -- get input from keyboard, useful for debugging\n      menu            -- display a menu of options and ask for input\n      fft             -- fast fourier transform\n      ifft            -- inverse fast fourier transform\n\n  * Strings may be enclosed in either single or double quote\n    characters.  Double quote characters are not special within single\n    quote strings, and single quotes are not special within double\n    quote strings.\n\n  * Command name completion now works for M-file names too.\n\n  * Better help and usage messages for many functions.\n\n  * Help is now available for functions defined in M-files.  The first\n    block of comments is taken as the text of the help message.\n\n  * Numerous changes in preparation to support dynamic loading of\n    object files with dld.\n\n  * Bug fixes to make solving DAEs with dassl actually work.\n\n  * The command `save file' now saves all variables in the named file.\n\n  * If do_fortran_indexing is 'true', indexing a scalar with\n    [1,1,1,...] (n times) replicates its value n times.  The\n    orientation of the resulting vector depends on the value of\n    prefer_column_vectors.\n\n  * Things like [[1,2][3,4]] no longer cause core dumps, and invalid\n    input like [1,2;3,4,[5,6]] now produces a diagnostic message.\n\n  * The cd, save, and load commands now do tilde expansion.\n\n  * It's now possible to clear global variables and functions by name.\n\n  * Use of clear inside functions is now a parse error.\n\nSummary of changes for version 0.70 (1993-03-08):\n------------------------------------------------\n\n  * Better parse error diagnostics.  For interactive input, you get\n    messages like\n\n      octave:1> a = 3 + * 4;\n\n      parse error:\n\n          a = 3 + * 4;\n                  ^\n\n    and for script files, the message includes the file name and input\n    line number:\n\n      octave:1> foo\n\n      parse error near line 4 of file foo.m:\n\n          a = 3 + * 4;\n                  ^\n\n  * New built-in variable PS2 which is used as the secondary prompt.\n    The default value is '> '.\n\n  * New file, octave-mode.el, for editing Octave code with GNU Emacs.\n    This is a modified version of Matthew R. Wette's matlab-mode.el.\n\n  * Better support for missing math functions.\n\n  * User preferences are now cached in a global struct so we don't\n    have to do a symbol table lookup each time we need to know what\n    they are.  This should mean slightly improved performance for\n    evaluating expressions.\n\nSummary of changes for version 0.69 (1993-02-23):\n------------------------------------------------\n\n  * Multiple assignments are now possible, so statements like\n\n      a = b = c = 3;\n      a = b = c = [1,2;3,4];\n\n    or\n\n      c = (a = (b = 2) * 3 + 4) * 5\n\n    are legal, as are things that have even more bizarre effects, like\n\n      a(4:6,4:6) = b(2:3,2:3) = [1,2;3,4];\n\n    (try it).\n\n  * Improved parsing of strings (but they still don't work as matrix\n    elements).\n\n  * An M-file may now either define a function or be a list of\n    commands to execute.\n\n  * Better detection and conditional compilation of IEEE functions\n    isinf, finite, and isnan.\n\n  * Replacements for acosh, asinh, atanh, and gamma from the BSD math\n    library for those systems that don't have them.\n\nSummary of changes for version 0.68 (1993-02-16):\n------------------------------------------------\n\n  * New functions:\n\n      eval  -- evaluate a string as a sequence of Octave commands.\n      input -- print a prompt and get user input.\n\nSummary of changes for version 0.67 (1993-02-09):\n------------------------------------------------\n\n  * New functions:\n\n      find -- return the indices of nonzero elements.\n\n  * Zero-one style indexing now works.  For example,\n\n      a = [1,2,3,4];\n      b = a([1,0,0,1])\n\n    sets b to the first and fourth elements of a.\n\n    Zero-one style indexing also works for indexing the left hand side\n    of an assignment.  For example,\n\n      a = rand (1,2;3,4);\n      a([0,1],:) = [-1,-2]\n\n    sets the second row of a to [-1 -2]\n\n    The behavior for the ambiguous case\n\n      a = [1,2,3,4];\n      b = a([1,1,1,1]);\n\n    is controlled by the new global variable `prefer_zero_one_indexing'.\n    If this variable is equal to 'true', b will be set to [1 2 3 4].\n    If it is false, b will be set to [1 1 1 1].  The default value is\n    'false'.\n\n  * Using the new global variable `propagate_empty_matrices', it is\n    possible to have unary and binary operations on empty matrices\n    return an empty matrix.  The default value of this variable is\n    'warn', so that empty matrices are propagated but you get a\n    warning.  Some functions, like eig and svd have also been changed\n    to handle this.\n\n  * Empty matrices can be used in conditionals, but they always\n    evaluate to `false'.  With propagate_empty_matrices = 'true', both\n    of the following expressions print 0:\n\n      if  [], 1, else 0, end\n      if ~[], 1, else 0, end\n\n  * Octave no longer converts input like `3.2 i' or `3 I' to complex\n    constants directly because that causes problems inside square\n    brackets, where spaces are important.  This abbreviated notation\n    *does* work if there isn't a space between the number and the i,\n    I, j, or J.\n\nSummary of changes for version 0.66 (1993-01-28):\n------------------------------------------------\n\n  * Logical unary not operator (~ or !) now works for complex.\n\n  * Left division works.\n\n  * Right and left element by element division should work correctly\n    now.\n\n  * Numbers like .3e+2 are no longer errors.\n\n  * Indexing a matrix with a complex value doesn't cause a core dump.\n\n  * The min and max functions should work correctly for two arguments.\n\n  * Improved (I hope!) configuration checks.\n\n  * Octave is now installed as octave-M.N, where M and N are version\n    numbers, and octave is a link to that file.  This makes it\n    possible to have more than one version of the interpreter installed.\n\nSummary of changes for version 0.63 (1993-01-14):\n------------------------------------------------\n\n  * The reshape function works again.\n\n  * Octave now converts input like `3.2i' or `3 I' or `2.3e5 j' to be\n    complex constants directly, rather than requiring an expression\n    like `3.3 * i' to be evaluated.\n\nSummary of changes for version 0.61 (1993-01-10):\n------------------------------------------------\n\n  * Octave has been successfully compiled using gcc 2.3.3 and libg++ 2.3.\n    on a 486 system running Linux.\n\n  * The win_texas_lotto function is now called texas_lotto (it's a\n    script file, and win_texas_lotto.m is too long for some Linux and\n    System V systems).\n\nSummary of changes for version 0.57:\n------------------------------------\n\n  * The C-like formatted print functions printf, fprintf, and sprintf\n    finally work.\n\nSummary of changes for version 0.56:\n------------------------------------\n\n  * By default, octave prints a short disclaimer when it starts.\n    (You can suppress it by invoking octave with -q).\n\n  * You can keep octave from reading your ~/.octaverc and .octaverc\n    files by invoking it with -f.\n\n  * When returning two values, eig now returns [v, d] instead of\n    [lambda, v], where d is a diagonal matrix made from lambda.\n\n  * The win_texas_lotto function now produces a sorted list.\n\n  * New functions:\n\n      expm -- matrix exponential.\n      logm -- matrix logarithm.\n\nSummary of changes for version 0.55:\n------------------------------------\n\n  * The following (C-style) backslash escape sequences work in quoted\n    strings (useful(?) with printf()):\n\n      \\a  bell         \\r  carriage return\n      \\b  backspace    \\t  horizontal tab\n      \\f  formfeed     \\v  vertical tab\n      \\n  newline      \\\\  backslash\n\n  * Use of `...' at the end of a line will allow a statement to\n    continue over more than one line.\n\n  * The names `inf' and `nan' are now aliases for `Inf' and `NaN',\n    respectively.\n\n  * New functions:\n\n      casesen -- print a warning if the luser tries to turn off case\n                 sensitivity.\n      median  -- find median value.\n      norm    -- compute the norm of a matrix.\n      sort    -- sort columns.\n\n  * New variable, `silent_functions'.  If silent_functions == 'true',\n    the results of expressions are not printed even if they are not\n    followed by a semicolon.  The disp() and printf() functions still\n    result in output.  The default value for this variable is 'false'.\n\n  * New variable `return_last_value_computed'.  If it is 'true',\n    functions defined in script files return the last value computed\n    if a return value has not been explicitly declared.  The default\n    value for this variable is 'false'.\n\nSummary of changes for version 0.52:\n------------------------------------\n\n  * Name completion works for function and variable names currently in\n    the symbol tables.  Coming soon: completion for names of functions\n    defined in script files but not yet compiled.\n\n  * The initial value of do_fortran_indexing is now false, and the\n    initial value of prefer_column_vectors is now true.  Swap the\n    values of these variables if you want behavior that is more like\n    Matlab.\n\n  * All script files check the number of input arguments before doing\n    much real work.\n\n  * The identifiers `i' and `j' are now also names for sqrt(-1).\n    These symbols may be used for other purposes, but their original\n    definition will reappear if they are cleared.\n\n  * The symbol tables are now implemented with hash tables for faster\n    searching.\n\n  * A small amount of help is now available for most built-in\n    operators, keywords and functions.  Coming soon: help for script\n    files.\n\n  * Without any arguments, the help command now lists all known\n    built-in operators, keywords and functions.\n\n  * Generic parse errors are now signalled by `Eh, what's up doc?',\n    which is closer to what Bugs actually says.\n\n  * The who command now only prints variable names by default.\n    Use the -fcn (or -fcns, or -functions) switch to print the names of\n    built-in or currently compiled functions.\n\nSummary of changes for version 0.51:\n------------------------------------\n\n  * Major overhaul of array indexing.\n\n  * The colloc function actually works now.\n\nSummary of changes for version 0.50:\n------------------------------------\n\n  * The lsode and dassl functions now return the states only,\n    instead of the time and the states, so you must keep track of\n    the corresponding times (this is easy though, because you have\n    to specify a vector of desired output times anyway).\n\n  * Solution of NLPs with NPSOL now works on the SPARC.\n\n  * New keywords `endif', `endfor', `endfunction', `endif', and\n    `endwhile', which allow for better diagnostics.  The `end' keyword\n    is still recognized.  All script files have been changed to use\n    these new keywords in place of `end'.\n\n  * It is now possible to uninstall Octave by doing a `make uninstall'\n    in the top level directory.\n\n  * The Makefiles are much closer to conforming with GNU coding standards.\n\n  * New functions:\n\n      win_texas_lotto  -- produce six unique random numbers between 1 and 50.\n      quad             -- numerical integration.\n      lu               -- LU factorization\n      qr               -- QR factorization\n      dassl            -- Solution of DAEs using DASSL.\n\n  * New files:\n\n      THANKS -- A list of people and organizations who have supported\n                the development of Octave.\n\n      NEWS   -- This file, listing recent changes.\n\n  * Help is now available at the gnuplot prompt.\n"
  },
  {
    "path": "etc/NEWS.10.md",
    "content": "For (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\nSummary of bugs fixed for version 10.4.0 (tbd):\n-----------------------------------------------------\n\n### Improvements and fixes\n\n### GUI\n\n### Build system / Tests\n\n### Documentation\n\n\nSummary of bugs fixed for version 10.3.0 (2025-09-23):\n-----------------------------------------------------\n\n## Improvements and fixes\n\n- Correctly interpret command line option `--no-init-user` (bug #67187).\n- `image`: Avoid error if image data is empty (bug #65866).\n- Respect logarithmic scaling of axis when plotting scatter objects\n  (bug #67239).\n- Avoid segmentation fault with display with too low color depth (bug #65866).\n- Store save type in `binary-float` format also for empty matrices\n  (bug #67271).\n- Fix ASAN bug in liboctave `svd` code caused by use of\n  `std::vector::reserve ()` (bug #67248).\n- `mldivide`: Correctly apply permutation for sparse matrix with permuted lower\n  form.\n- Allow empty field names in `struct` and `cell2struct` functions (bug #67255).\n- `containers.Map`: Allow empty `char` arrays as keys (bug #67255).\n- Fix ASAN warnings in `__ilu__.cc` (bug #67249).\n- `rose.m`: Fix regression where output variables always returned (bug #48889).\n- `rose.m`: Overhaul function to resolve incorrect custom bin placement\n  (bug #67280).\n- Clarify the `\"Octave:language-extension\"` warning message for comparing\n  complex numbers that the compatibility difference is that Octave considers\n  the complex part of the number (bug #67257).\n- `delaunayn.m`: Check inputs for non-finite values to avoid segfault in QHull\n  (bug #67315).\n- Fix calculation of \"nearest integer\" function (bug #67339).\n- `struct2hdl.m`: Use a consistent output type for `valcomp` (bug #67217).\n- Avoid crash when Octave invoked with `-d` argument.\n- Skip saving too large arrays in `-binary` format (bug #67382).\n- Write and read large array in chunks for `-binary` file format (bug #67382).\n- Correctly parse `clear ?` (bug #67459).\n- `colorbar.m`: Don't emit error if \"position\" property given (bug #67537).\n\n### GUI\n\n- Fix `SIGABRT` on exit of GUI (bug #67230).\n- Fix focus when reopening editor file from MRU list (bug #67384).\n\n### Build system / Tests\n\n- Add tests for shadowed functions in core Octave (bug #46849).\n- Fix building Java on solaris2 platforms (bug #67442).\n- Include `ida.h` in configure tests from the locations at which it is looked\n  for.\n- Do not check for `nvector_serial.h` without folder in configure test.\n\n### Documentation\n\n- Expand on orthogonality properties of the cross product (bug #67186).\n- Remove newline before `@tex` invocation for better alignment.\n- Remove notes in documentation scheduled for deletion in version 9.1.\n- Clarify use of \"interpreter\" property when printing.\n- Improve TeX output for vector calculus functions.\n- Explain more clearly uses and pitfalls of `NA`.\n- Add documentation for hexadecimal and binary integer constants (bug #67645).\n- Use `IEEE@tie{}754` when referring to floating point standard.\n- `diary`: Clarify documentation.\n- `echo`: Clarify documentation.\n- Update manual for `--traditional` option to note that `PS4` is set.\n\n\nSummary of bugs fixed for version 10.2.0 (2025-05-29):\n-----------------------------------------------------\n\n## Improvements and fixes\n\n- `tensorprod`: Fix error for certain tensor/vector combinations (bug #66950).\n- `mkoctfile`: Skip compiling object file with soversion for `--mex -c -o`\n  (bug #66972).\n- Fix segmentation fault in `octave-svgconvert` when called with no inputs.\n- `mkoctfile`: Remove temporary C source files after compilation.\n- `unicode2native`: Fix conversion of short strings to UTF-16 or UTF-32.\n- Detect leading and trailing comments for all parse tree elements\n  (bug #67004).\n- `bar`: Avoid listener error when replacing an existing bar plot (bug #67006).\n- Fix sparse matrix assignment with reverse range indexing (bug #66516).\n- `ezplot`: Enable polar and 2-D plots of constant functions (bug #66563).\n- Check for any kind of file not just regular files (bug #67018).\n- `var`/`std`: Issue an error for non-floating point inputs. Previous versions\n  accepted integer type inputs but could produce erroneous outputs due to\n  integer arithmetic and under/overflow errors (bug #67016).\n- `annotation`: Change `\"verticalalignment\"` default value (bug #67033).\n- Previously, symbols that are not actually callable by a user might have been\n  added to the list of callable functions when loading .mex files.  Remove\n  these symbols from that list.  This fixes unloading .mex files with `clear`.\n- Remove break points only from user functions (defined in .m file).  This\n  fixes an infinite recursion issue when re-loading updated .oct or .mex files.\n- For improved Matlab compatibility the `strncmp` and `strncmpi` functions now\n  return `true` if the number of characters specified by `N` is equal to 0\n  (bug #57879).\n- Fix `nargout` in multi-output indexing expressions beginning with function\n  call (bug #67096).\n- `findobj`: Do not match empty tags with `[]` (bug #67048).\n- Check for undefined output when indexing function output (bug #67111).\n- `perms`: Fix buffer overflow and crash; minor code cleanup (bug #67115).\n- `mkoctfile`: Support spaces in output path of linker step.\n- `mkoctfile`: Support spaces in path to binary when stripping debug info.\n- `octave-svgconvert`: Speed up printing to PDF (bug #66959).\n- `error`: Fix segmentation fault on missing fields in `err.stack` structure\n  (bug #67143).\n- Avoid parse error for empty lines in debug mode (bug #67108).\n- Check if effective SOVERSION is exported from .mex file libraries\n  (bug #67163).\n\n### GUI\n\n- Fix build error without QScintilla installed (bug #66962).\n- Avoid potential integer overflow on Windows.\n- Make dialogs shown by `inputdlg`, `listdlg`, `questdlg`, `uigetdir`, or\n  `uigetfile` modal.\n\n### Build system / Tests\n\n- Add visibility attributes for the `octave::base_fcn_handle` class.\n- Add visibility attributes to parse tree symbols (bug #67056).\n- Add visibility attributes to `Array<T>` template class member functions.\n- Use correct preprocessor macro when instantiating `MArray` template class.\n- Disable visibility flags by default.\n- Support passing additional flags when linking `octave*` executables.\n- Single-quote path that might contain unescaped backslashes in the generation\n  of the doc cache.\n- Ignore deprecation warning for `std::wbuffer_convert` in header.\n- `error`: Add more built-in self-tests.\n\n### Documentation\n\n- Recommend use of string function name as first argument to `cellfun()`.\n- `cellfun`: Call out special accelerated functions.\n- Update documentation for `feval`, `eval`, `evalin`, `evalc`.\n- `axis`: Remove incorrect statement from documentation.\n- Do not put graphics object categories into Graphic Properties Index.\n- Adjust Perl regexp used to remove leading ':' in HTML.\n- `char`: Document calling form with no inputs.\n- Fix missing hyperlinks in Table of Contents of Octave manual.\n- Fix overfull hbox warnings in Texinfo log files.\n- Replace Texinfo `@dots` macro with `@enddots` macro where appropriate.\n- Do not print ugly black boxes for overfull hboxes in PDF output.\n- Fix accidental doc text inclusions after `@deftypefn`.\n- Remove reference to Octave Forge in `stats.txi`.\n- Document use of `:` keyword as a range operator.\n- Correct and expand documentation on ranges.\n- Remove outdated text on range arithmetic from manual.\n- Examples: Add missing namespace `octave` when calling built-in function in\n  `standalonebuiltin.cc`.\n- Document calling `error()` with structure input (bug #67143).\n\n\nSummary of important user-visible changes for version 10 (2025-03-28):\n---------------------------------------------------------------------\n\n### General improvements\n\n- Three short form aliases have been added for long form options when starting\n`octave`.\n  * `-e CODE` for `--eval CODE`\n  * `-g` for `--gui`\n  * `-G` for `--no-gui`\n\n- Three long form options have been introduced for clarity.\n  * `--no-init-user` : Don't read user configuration files `~/.octaverc` or\n    `.octaverc` files at startup.\n  * `--no-init-site` : Don't read site-wide configuration files at startup.\n  * `--no-init-all` : Don't read any configuration files at startup.\n\n- `nchoosek` algorithm is now ~2x faster and provides greater precision.\n\n- `nextpow2` algorithm is now more accurate for inputs very close to a power\n  of 2.  The output class now matches the input class for Matlab compatibility.\n  The function no longer accepts complex inputs and emits an error for these\n  inputs.\n\n- `jsonencode` now outputs integers and floating point integers without an\n  unnecessary \".0\" suffix.\n\n- `hist` now accepts N-dimensional array inputs for input `Y`, which is\n  processed in columns as if the array was flattened to a 2-dimensional array.\n\n- The third output for `unique` is now correct when the `stable` sort option is\n  used.\n\n- Support setting breakpoints in `set` or `get` methods of `classdef`\n  properties (bug #65610).\n\n- `.mex` files now link to the new library `liboctmex` (instead of to\n  `liboctinterp` and `liboctave`).  The `SOVERSION` of this new library is\n  expected to be stable across multiple major versions of Octave.  The benefit\n  is that `.mex` files will not necessarily require rebuilding for every\n  major version release of Octave.\n\n- `pkg describe` command now supports a new `Tracker` tag in the `DESCRIPTION`\n  file and returns package-provided repository and bug tracker URLs.  Package\n  maintainers are encouraged to utilize the new feature to redirect users to\n  package-specific bug trackers instead of Savannah.\n\n- `pkg install` now mentions package-provided URL and package-provided bug\n  tracker if they exist.\n\n### Graphical User Interface\n\n### Graphics backend\n\n- `polar` plots now include the center tick mark value, typically 0, in the\n  `'rtick'` parameter when the plot is created.  Subsequent modifications to\n  `'rtick'` by the function `rticks` will only include the center tick mark\n  value if it is specified.\n\n- `view` correctly interprets Cartesian viewpoints on main axes (bug #65641).\n\n- `plot3` now draws a single marker if only one data point is given.\n  Previously the plot was blank (`marker` = `\"none\"`) which was confusing.\n\n### Matlab compatibility\n\n- `height` and `width` are now aliases for the `rows` and `columns` functions.\n\n- All colormaps now default to a size of 256 colors. (The previous default size\n  was 64.)\n\n- The first argument to `colormap` may now be a figure or axes object.  Calling\n  `colormap` on a figure object will clear any `\"colormap\"` properties set at\n  the axes level.\n\n- `griddata` output size more consistently matches the input interpolation\n  points when the inputs are vectors.  If the inputs are vectors with the\n  same-orientation, then the outputs will be the same size as those vectors.\n  When either input is a row vector and the other is a column vector, the\n  interpolating points are processed through `meshgrid` and the output is a\n  matrix the same size as the meshgrid.\n\n- `iqr` now provides compatible output for empty inputs.\n\n- `cross` now produces row vector outputs when the inputs are a mix of row and\n  column vectors (bug #61295).\n\n- `rat` now accepts complex inputs.\n\n- The optional second input argument of `system`, denoting whether to return\n  the output as a variable, is now required to be a boolean value if used.\n\n- Octave functions whose Matlab equivalents give errors when passed non-integer\n  values as sizes or dimensions now also give similar errors.  For example,\n  `cell (e, pi)` now gives an error in Octave about requiring integer sizes for\n  the cell array, matching Matlab behavior.  Previously, Octave's conversion\n  from non-integers to integers was more lenient.\n\n- `issorted` now accepts the `MODE` option `\"monotonic\"`, which has the same\n  behavior as the option `\"either\"`.\n\n- `movfun` and `movslice`: Functions now accept `wlen` equal to 1 or [0,0],\n  non-integer values of `wlen`, and values of `wlen` that create window lengths\n  exceeding the size of the target array.  `movfun` also accepts values of\n  `dim` larger than the number of non-singleton dimensions in the target array.\n  The `SamplePoints` option has been implemented for both functions.\n  Non-numeric input array handling has been improved.  These changes affect all\n  moving window functions (`movmad`, `movmax`, `movmean`, `movmedian`,\n  `movmin`, `movprod`, `movstd`, `movsum`, and `movvar`) (bug #65928,\n  bug #66025).\n\n- `movfun`: The `nancond` property has been fully implemented and made\n  Matlab-compatible.  The `omitnan` option will ignore `NaN` and `NA` values\n  when calculating the function return, and, if all elements in a window slice\n  are `NaN` or `NA`, it will return the value contained in a new property\n  `nanval` (default `NaN`) for that element.  The `includenan` property (the\n  default) has been updated for compatibility such that any window containing\n  `NaN` or `NA` will return `NaN` rather than passing those values to the\n  calculating function.  `omitmissing` and `includemissing` are now accepted as\n  aliases for `omitnan` and `includenan`.  These changes affect all moving\n  window functions (`movmad`, `movmax`, `movmean`, `movmedian`, `movmin`,\n  `movprod`, `movstd`, `movsum`, and `movvar`) (bug #66156).\n\n- `movmin` and `movmax`: These functions now have their default behavior set to\n  `omitnan`.  `NaN` and `NA` values will be ignored unless a moving window\n  contains only `NaN` or `NA` values, in which case the function will return\n  `NaN` for that element (bug #66156).\n\n- `movsum`: When called with option `omitnan`, any windows containing only\n  `NaN` and `NA` values will return 0 (bug #66156).\n\n- `movprod`: When called with option `omitnan`, any windows containing only\n  `NaN` and `NA` values will return 1 (bug #66156).\n\n- `movmad`: The function now defaults to calculating median absolute deviation.\n  Before Octave 10, the function calculated mean absolute deviation.  A new\n  `method` property has been provided that takes values of either `\"mean\"` or\n  `\"median\"` to allow the user to select which option to use.  This property\n  should not be expected to function in code used outside of Octave.\n  (bug #66256).\n\n- `symbfact`: outputs `count`, `parent`, and `post` are now row vectors rather\n  than column vectors.\n\n### Alphabetical list of new functions added in Octave 10\n\n* `clim`\n* `rticklabels`\n* `thetaticklabels`\n\n### Deprecated functions, properties, and operators\n\nThe following functions and properties have been deprecated in Octave 10\nand will be removed from Octave 12 (or whatever version is the second\nmajor release after 10):\n\n- Functions\n\n        Function    | Replacement\n        ------------|------------\n        dsearch     | dsearchn\n\n- Core\n\n        Function                                     | Replacement\n        ---------------------------------------------|-----------------------------------\n        symbol_record_rep::mark_as_variable          | symbol_record_rep::mark_variable\n        symbol_record_rep::unmark_as_variable        | symbol_record_rep::unmark_variable\n        symbol_record::mark_as_variable              | symbol_record::mark_variable\n        symbol_record::unmark_as_variable            | symbol_record::unmark_variable\n        interpreter::verbose                         | interpreter::init_trace\n        cmdline_options::verbose                     | cmdline_options::init_trace\n        interpreter::read_init_files                 | interpreter::read_user_files\n        cmdline_options::read_init_files             | cmdline_options::read_user_files\n        __lo_ieee_isnan,    __lo_ieee_float_isnan    | std::isnan     or  isnan\n        __lo_ieee_isfinite, __lo_ieee_float_isfinite | std::isfinite  or  isfinite\n        __lo_ieee_isinf,    __lo_ieee_float_isinf    | std::isinf     or  isinf\n        __lo_ieee_signbit,  __lo_ieee_float_signbit  | std::signbit   or  signbit\n        octave_value (const Array<octave_value>& a)  | octave_value (const Cell&)\n\n  - The `octave_value (const Array<octave_value>& a)` constructor will already\n    be removed in Octave 11 (or whatever version is the next major release\n    after Octave 10).\n\n  - A new method `rwdata ()` provides direct read/write access (a pointer) to\n    the data in a liboctave `Array` object (or its derived classes such as\n    `Matrix`).  Historically, the method `fortran_vec ()` provided this access,\n    but the name is unclear, and it is recommended to use `rwdata ()` in any\n    new code.  There are no plans to deprecate `fortran_vec`.\n\n  - The `--verbose`,`-V` command-line option has been deprecated.  Use\n    `--init-trace` to print the configuration files executed during\n    initialization.\n\nThe following features were deprecated in Octave 8 and have been removed\nfrom Octave 10.\n\n- Functions\n\n        Function             | Replacement\n        ---------------------|---------------------\n        shift                | circshift\n        sparse_auto_mutate   | none (see NEWS.8.md)\n\n- `fminsearch` parameter passing: A legacy, undocumented, and only partially\n  supported syntax for passing parameters to the minimized function `fcn`\n  called by `fminsearch` by appending them to the input argument list was\n  partly implemented since Octave 4.4.0.  Due to conflicts with other input\n  methods, the documentation of this syntax was removed in Octave 5.1.0.  The\n  remaining functionality has been completely removed in Octave 10.  Attempts\n  to call `fminsearch` with that syntax will result in an error.  The preferred\n  method of passing parameters to any of the minimization functions (including\n  `fminsearch`, `fminbnd`, and `fminunc`) is through the use of anonymous\n  functions.  Specific examples of this can be found in the \"Minimizers\"\n  section of the Octave manual.\n\n- The unsupported and unnecessary `load` options of `-force` and `-import` have\n  been removed.  If legacy m-files are still invoking `load` with these options\n  update the code and remove them.\n\n### Build system\n\n- Octave now requires a C++ compiler that is compliant with C++17 (preferably\n  with GNU extensions).\n\n- The location of the list of packages installed site-wide for all users\n  (`pkg global_list`) has changed (bug #66831).  The file `octave_packages` is\n  now installed at `octave-config -p LOCALAPIPKGDIR`.  There will be no\n  disruption if you are upgrading to version 10.1 of Octave and then installing\n  packages.  If you want to use previously installed packages that you *know*\n  will run without re-compilation (because the package uses m-files only and no\n  oct-files or mex-files), then you can execute the command\n  `pkg global_list CURRENT_GLOBAL_LIST_FILE` (e.g., from within one of your\n  startup files) to point Octave to the existing list.  Alternatively, run\n  `pkg rebuild -global` once (potentially requires superuser rights), or copy\n  `CURRENT_GLOBAL_LIST_FILE` to the path and filename returned by\n  `pkg global_list`.\n\n\nSummary of bugs fixed for version 10.1.0 (2025-03-28):\n-----------------------------------------------------\n\n- bug #66753: `hist.m`: Test for equal bin spacing using a numeric tolerance.\n- bug #66753: `hist.m`: Fix regression in determining equal bin spacing.\n- bug #66753: Fix thinko in cset be1d0c816788\n- bug #66647: Silence unexpected `Octave:mixed-string-concat` warning in\n  `num2str.m`.\n- bug #66642: Code beautification for cset 2c2301104caf\n- bug #66642: Check for undefined outputs in `cellfun` and `arrayfun`.\n- bug #66642: Add `cellfun` BIST for function failing to return requested\n  output.\n- bug #66642: Add `arrayfun` BIST for function failing to return requested\n  output.\n- bug #66617: Avoid error for `struct2cell` with function without output\n  arguments.\n- bug #66617: Add self-tests for `structfun` with function without output\n  arguments.\n- bug #66558: Translate shortcuts and descriptions in settings dialog.\n- bug #66521: `symbfact`: Return row vectors for Matlab compatibility.\n- bug #66511: `sparseqr`: Support permutation output with CXSparse.\n- bug #66511: Emit error when `qr()` is called with permutation output and\n  CXSparse library is used.\n- bug #66488: `qr (sparse, 0)` isn't equal to `qr (sparse, 'econ', 'vector')`.\n- bug #66477: Avoid ASAN error with `path (_)` manipulations.\n- bug #66466: `legend` and `bar` cause ASAN to crash Octave.\n- bug #66451: Ctrl-C kills Octave 10.0.0.\n- bug #66448: File encoding conversion errors on macOS 14.\n- bug #66399: `fseek` and `ftell` functions don't always work correctly on\n  Windows with filesizes >2GB.\n- bug #66315: `menu()` throws an error when Qt dialogs are not available.\n- bug #66256: `movmad` uses 'mean absolute deviation' while Matlab uses 'median\n  absolute deviation'.\n- bug #66156: Implement `nanflag` option for moving window functions.\n- bug #66025: `movfun`: Implement `SamplePoints` option.\n- bug #66010: Function `glpk` produces incorrect output.\n- bug #65964: `nthargout` does not propagate error ID.\n- bug #65928: `movfun` dimension constraints: Shouldn't error for\n  `dim > ndims(x)`, or `wlen > size(x, dim)`, or `wlen=1`.\n- bug #65876: Error retrieving data from `struct` values in `containers.Map`.\n- bug #65768: Segmentation fault on default branch.\n- bug #65753: Strip leading/trailing whitespace from \"Function Index\" search\n  expression.\n- bug #65753: Documentation window: Function Index: Search box respects\n  trailing spaces.\n- bug #65730: Some remaining cases of silent conversion of fractional inputs.\n- bug #65683: `issorted`: enable `'monotonic'` and `'strict...'` sort modes.\n- bug #65674: `axes` `'colormap'` property being set over `figure` `'colormap'`\n  property.\n- bug #65665: Input validation for `system()`.\n- bug #65645: Execute FIXME of `perms.cc`: Use `constexpr` instead of template\n  specialisation.\n- bug #65641: `view` produces incorrect viewpoint when given a vector aligned\n  with the primary axes.\n- bug #65637: `short_disp` doesn't show ellipsis at end of long arrays.\n- bug #65617: <F9> clears editor setting 'Always show debug breakpoints and\n  pointers...'.\n- bug #65577: Feature request: Editor right-click to run test without needing\n  to clear `%!` first.\n- bug #65538: `xint_value` does not work the way it is intended.\n- bug #65531: `iqr` handling of empty inputs is not compatible.\n- bug #65499: Use separate GUI settings for Octave releases.\n- bug #65495: `nchoosek` error 'gcd: all values must be integers'\n- bug #65459: `uifigure ('visible', 'off')` temporarily creates a visible\n  figure window.\n- bug #65447: `jsonencode` does not accept integer values larger than 999999.\n- bug #65441: `nextpow2` incorrect for some inputs slightly larger than powers\n  of two.\n- bug #65238: Improve `nchoosek.m` algorithm to prevent numerical issues.\n- bug #65221: `movfun`: Create `inputParser` only once.\n- bug #65176: `unique.m`: Enable third output with option `'stable'`.\n- bug #65134: `griddata`: Output size inconsistent for vector input\n  interpolation points.\n- bug #65030: Column width in browser pane not retained between restarts of\n  Octave.\n- bug #65010: Compatibility: Colormaps now default to 256 colors in Matlab.\n- bug #64995: Implement `height` and `width` as aliases for `rows` and\n  `columns` for Matlab compatibility.\n- bug #64991: `polar` doesn't populate `'rtick'` with center tick value.\n- bug #62928: Error sourcing file message when script with embedded '.' in\n  filename has syntax error.\n- bug #61295: `cross()`: Dimensions inconsistent with Matlab when using\n  mismatched input vector dimensions.\n- bug #60797: `sqrtm`: Returns `NaN` for matrix of ones with rows and\n  columns >=4.\n- bug #60726: Fix `nargout` for `subsref` when returned value may be a cs-list.\n- bug #56690: Support displaying lazy index objects in variable editor.\n- bug #55961: `properties` function does not preserve order.\n- bug #55198: `rat()` should support complex numbers.\n- bug #41028: `lastwarn`: Save warning info for disabled warnings.\n- bug #41028: Modify built-in self-tests to pass with Matlab-compatible\n  `lastwarn()` behavior.\n\n### Old release news\n\n- [Octave 9.x](NEWS.9.md)\n- [Octave 8.x](NEWS.8.md)\n- [Octave 7.x](NEWS.7.md)\n- [Octave 6.x](NEWS.6.md)\n- [Octave 5.x](NEWS.5.md)\n- [Octave 4.x](NEWS.4)\n- [Octave 3.x](NEWS.3)\n- [Octave 2.x](NEWS.2)\n- [Octave 1.x](NEWS.1)\n"
  },
  {
    "path": "etc/NEWS.11.md",
    "content": "Summary of bugs fixed for version 11.2.0 (YYYY-MM-DD):\n-----------------------------------------------------\n\nFor (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\n### Improvements and fixes\n\n### GUI\n\n### Build system / Tests\n\n### Documentation\n\n\nSummary of important user-visible changes for version 11 (2026-02-18):\n---------------------------------------------------------------------\n\n### General improvements\n\n- The internal interface to Java has been updated to be more memory-efficient\n  (faster culling of unused objects).  Building Octave from source code with\n  Java support now requires JDK 1.9 or newer.  Distributed, precompiled\n  versions of Octave will run with any JVM.\n\n- The `pkg` command has these user-visible changes:\n  * The package installation command `pkg install foo` now automatically\n    determines whether `foo` is a local file, a URL, or an unqualified package\n    name in that order, and installs it as appropriate.  The `-forge` option is\n    no longer required.\n  * There is a new search command for packages: `pkg search foo bar baz`\n    searches the Octave Packages index for packages having all the listed\n    keywords in their description.  Search terms can also be specified as\n    regular expressions.\n  * The old command `pkg list -forge`, which returned a list of packages found\n    online, has been replaced by `pkg search -refresh -all`.\n  * Package metadata is now cached locally on the computer as a backup for\n    reliability.  It is updated automatically when an operation that needs the\n    current package index such as `install`, `update`, or `search` is run the\n    first time in an Octave session.  Metadata updates can also be done on\n    demand with the new option `-refresh` for those three actions.\n  * Package tarballs are now verified using SHA256 if they are downloaded\n    during `pkg install` or `pkg update`.\n\n- Convolution of short and wide arrays (especially row vectors) is now faster\n  by anywhere from 10% to 150X, depending on the array size and shape.\n  Previously, convolution of tall and skinny arrays (especially column vectors)\n  was much faster than convolving short and wide ones, requiring transposition\n  or permutation of the inputs for performance.  Now Octave automatically picks\n  the fastest calculation order irrespective of the input orientation.\n\n- The functions `sum`, `cumsum`, `sumsq` now have special code for logical\n  inputs resulting in performance improvements of up to 6X.\n\n- The function `sum` now fully supports increased precision through the\n  `\"extra\"` optional argument, which is also available for sparse arrays.\n\n- The function `norm` now uses Kahan summation resulting in more accurate\n  results (.02% for data of class `single`).\n\n- New function `_Exit` has been added which makes it possible to use\n  `fork`/`_Exit` sequence to perform work in parallel child processes for\n  potential performance gains.\n\n- The `fzero` function is now more accurate (1-2 eps when `TolX` is eps).\n\n- The `randi` function has been completely rewritten and is now 4.5X faster\n  while using some 3.5X less memory than before.\n\n- The `roots` function now accepts only inputs of type `double` or `single`.\n\n- The `mean` function no longer accepts character array inputs.  It does\n  continue to accept logical and integer types as input.  Convert any character\n  input to an accepted input type.\n\n- All core statistics functions (other than `mean` as described above) now\n  accept only inputs of type `double` or `single`.  Convert other input data\n  types to `double` or `single`.\n\n- On dot-indexing of `classdef` objects, `subsref` now tries to resolve the\n  symbol name to a property first, and if a property is not found then it will\n  look for a method.\n\n### Graphical User Interface\n\n- The File Browser now has two tabs: the first for browsing the file system as\n  usual, and the second for viewing and managing all open editor files.\n\n- The Find File dialog now offers most recently used lists for input fields and\n  the ability to search for/in several file patterns at the same time.\n\n- The GUI now uses scalable SVG icons for beautiful display at any size.\n\n- The GUI now uses the default Octave command prompt.  This prompt is\n  completely customizable by calling `PS1` in an initialization file such as\n  `.octaverc`.  To recover the former behavior of the GUI use\n  `PS1 ('>> '); PS2 ('')`.\n\n- The GUI has two new user preferences: one for showing a small splash screen\n  at startup, and one for using the directory of the currently focused editor\n  file instead of the current Octave directory as the initial folder for the\n  Open File dialog.\n\n- The text of the Octave GUI has been translated to a new language: Asturian.\n  It uses the ISO 639 language code ast_ES.\n\n### Graphics backend\n\n- `polar` plot background patch object has been moved to the Z=0 plane to\n  permit view changes that previously resulted in an obscured plot area\n  (bug #67574).\n\n- Octave no longer strips leading and trailing spaces from user-specified\n  ticklabels (bug #67302).  This makes it possible to use a monospaced font to\n  align labels as the user intends.  This change is Matlab-compatible.\n\n- The `XMinorTickValues`, `YMinorTickValues`, `ZMinorTickValues` axes\n  properties that were previously hidden have been made visible to allow users\n  to control the position of minor ticks (bug #67394).\n\n- Printing to PDF format is now ~25% faster.\n\n- Improvements to alpha blending with newer versions of OpenGL.\n\n### Matlab compatibility\n\n- The warning `\"Octave:language-extension\"` is no longer emitted for automatic\n  broadcasting which Matlab has supported since version 2016B.\n\n- Broadcasting now works on sparse matrix operations as well as mixed\n  operations between sparse and full matrices.\n\n- Broadcasting now works on diagonal matrix operations as well as mixed\n  operations between diagonal matrices and vectors.\n\n- All basic operations functions now properly handle empty inputs and return\n  correctly sized output arguments for both dense arrays and sparse matrices.\n\n- The functions `all` and `any` now accept the optional arguments `\"all\"` or\n  `vecdim`.\n\n- The functions `cumprod` and `cumsum` now accept the optional arguments\n  `\"all\"` or `vecdim`, `direction`, and `nanflag`.\n\n- The functions `min` and `max` now support the optional arguments `\"all\"` or\n  `vecdim`, `nanflag`, and the paired argument `\"ComparisonMethod\"` with options\n  `\"real\"`, `\"abs\"`, and `\"auto\"`.  The `\"linear\"` indexing flag is now also\n  supported, when a second output argument is requested.\n\n- The functions `cummin`, and `cummax` now support the optional arguments\n  `\"all\"` or `vecdim`, `nanflag`, `direction`, and the paired argument\n  `\"ComparisonMethod\"` with options `\"real\"`, `\"abs\"`, and `\"auto\"`.  The\n  `\"linear\"` indexing flag is now also supported, when a second output argument\n  is requested.\n\n- The functions `prod`, `sum`, and `sumsq` now accept the optional arguments\n `\"all\"` or `vecdim`, `nanflag`, and `\"default\"` in `outtype`.  `prod` and\n `sumsq` functions now retain the class of the input argument by default.\n 'sumsq' now also accepts an `outtype` argument.\n\n- The functions `bounds`, `center`, `meansq`, `range`, `statistics`, and\n  `zscore` now accept the optional arguments `\"all\"` or `vecdim`, and\n  `nanflag`.\n\n- The functions `kurtosis`, `mode`, `moment`, `prctile`, `quantile`, and\n  `skewness` now accept the optional arguments `\"all\"` or `vecdim`.\n\n- The function `mean` now accepts the optional paired argument `\"Weights\"`.\n\n- The function `iqr` now calculates an optional second output `q` which\n  contains the 25th and 75th quantiles used to calculate the interquartile\n  range.  It also now accepts the optional arguments `\"all\"` or `vecdim`.\n\n- The function `quantile` now also accepts a positive integer as the second\n  input argument specifying evenly spaced cumulative probabilities.\n\n- The functions `strncmp` and `strncmpi` now return true for `N=0` for Matlab\n  compatibility.\n\n- The function `gradient` with a numeric input now only accepts type `double`\n  or `single`.\n\n- The function `polyfit` now returns the highest powers possible and the\n  constant term when there is insufficient data to create all `N` terms of the\n  polynomial.  The output structure has a new field `rsquared` which is the\n  coefficient of determination describing how well the polynomial fits the\n  data.\n\n- The function `cellfun` now fails if the returned type does not match in the\n  invocations for each cell element.  In earlier versions, the elements were\n  converted to a compatible type if possible.\n\n- The function `speye` can now be called with zero arguments for compatibility\n  with the full-matrix function `eye` and Matlab-compatibility.\n\n- The function `containers.Map` now supports char N-D arrays as keys.\n\n- The function `qp` now has a new input option `\"AllowSemidefinite\"` for\n  problem instances where the Hessian matrix is positive semi-definite instead\n  of positive definite.  The default value is `false`.\n\n- The function `qr` for a dense matrix input `A` and a single output now\n  returns just the matrix `R`, rather than an augmented version from LAPACK\n  with additional information in the lower-triangular portion of the matrix.\n  This resolves the output incompatibility with the sparse calling syntax for\n  this function, as well as the incompatibility with Matlab.\n\n- The `weboptions` function has been re-written internally.  Support for\n  non-integer `Timeout` values, and the special value `Inf`, has been added.\n\n- The `urlread` and `urlwrite` functions now make use of various `weboptions`\n  such as timeouts and user credentials.  The old calling form of passing a\n  cell array is still supported for backward compatibility.\n\n- The functions `fill` and `fill3` now handle all input combinations of vector\n  and matrix vertex data and color data in a Matlab-compatible way.\n\n- The `image` function now validates that `x` and `y` inputs are vectors, and\n  accepts and processes 1-element vectors for compatibility.\n\n- The `ind2rgb` and `ind2gray` functions now clip exceptional values such as\n  `NaN` or `Inf` to the last value in the colormap for compatibility.\n\n- The function `colorbar` now requires the `location` input to be the first\n  argument rather than the last argument.  This may require updating existing\n  Octave scripts.  The graphics properties `AxisLocation`, `Direction`, and\n  `TickLabels` have been implemented.\n\n- The `newplot` function has been re-written to remove functionality that was\n  possibly never used in Octave, and has been removed from Matlab.  The\n  function is also more compatible, and does not change the current figure\n  unexpectedly.  However, any user plotting code that depends on this broken\n  behavior will need to be updated.\n\n- The `uitable` property `\"ColumnWidth\"` now supports the argument `\"fit\"`\n  which produces smaller column widths than `\"auto\"` (sized to width of data,\n  rather than possibly including `ColumnName` in width calculation).\n  Specifying small numeric widths down to 1-pixel now works correctly.\n\n- The `KeyEvent` structure passed as an input paramater to graphics callback\n  functions such as `KeyPressFcn` now returns fieldnames in the same order\n  as Matlab: `Character`, `Modifier`, `Key`.\n\n- The `KeyEvent` structure now includes the fields `Source` (graphics handle\n  of object returning `KeyEvent`) and `EventName` (e.g., `KeyPress` or\n  `KeyRelease`).\n\n### Alphabetical list of new functions added in Octave 11\n\n* `_Exit`\n* `assert_equal`\n* `corrcov`\n* `dither`\n* `funm`\n* `mape`\n* `rms`\n* `rmse`\n* `trexc`\n* `xline`\n* `yline`\n\n### Deprecated functions, properties, and operators\n\nThe following functions and properties have been deprecated in Octave 11\nand will be removed from Octave 13 (or whatever version is the second\nmajor release after 11):\n\n- Functions\n\n        Function               | Replacement\n        -----------------------|------------------\n        polyfit output s.X     | polyfit output s.V\n\n- Core\n\n        Function                  | Replacement\n        --------------------------|--------------------------\n        octave::math::x_nint      | octave::math::round\n        octave::math::isinteger   | octave::math::is_integer\n\n    The environment variable `OCTAVE_LATEX_DEBUG_FLAG` to enable debugging of\n    the latex interpreter has been renamed to `OCTAVE_LATEX_DEBUG`.\n\n    The environment variable `QTHANDLES_DEBUG` to enable debugging of the GUI\n    has been renamed to `OCTAVE_QTHANDLES_DEBUG`.\n\nThe following mapper function typedefs have been deprecated in Octave 11\nand will be removed from Octave 12 (or whatever version is the first\nmajor release after 11):\n\n- Function typedefs\n\n    * `b_d_Mapper`\n    * `b_c_Mapper`\n    * `d_d_Mapper`\n    * `d_c_Mapper`\n    * `c_c_Mapper`\n    * `b_f_Mapper`\n    * `b_fc_Mapper`\n    * `f_f_Mapper`\n    * `f_fc_Mapper`\n    * `fc_fc_Mapper`\n\nInput to the functions `any` and `all` that is non-numeric and non-logical has\nbeen deprecated in Octave 11 and will throw an error in Octave 12 (or whatever\nversion is the first major release after Octave 11).\n\nThe following features were deprecated in Octave 9 and have been removed\nfrom Octave 11.\n\n- Core\n\n        Function                                     | Replacement\n        ---------------------------------------------|-----------------------------------\n        octave::initialized                          | octave::is_initialized\n        octave::same_file                            | octave::sys::same_file\n        octave::interpreter_initialized              | octave::interpreter_is_initialized\n        all_ok (Array<octave::idx_vector>&)          |\n        idx_vector::bool ()                          |\n        octave_value (const Array<octave_value>& a)  | octave_value (const Cell&)\n\n  - The `octave_value (const Array<octave_value>& a)` constructor was\n    deprecated in Octave 10 and was removed after only one major version.\n\n### Old release news\n\n- [Octave 10.x](etc/NEWS.10.md)\n- [Octave 9.x](etc/NEWS.9.md)\n- [Octave 8.x](etc/NEWS.8.md)\n- [Octave 7.x](etc/NEWS.7.md)\n- [Octave 6.x](etc/NEWS.6.md)\n- [Octave 5.x](etc/NEWS.5.md)\n- [Octave 4.x](etc/NEWS.4)\n- [Octave 3.x](etc/NEWS.3)\n- [Octave 2.x](etc/NEWS.2)\n- [Octave 1.x](etc/NEWS.1)\n"
  },
  {
    "path": "etc/NEWS.12.md",
    "content": "Summary of important user-visible changes for version 12 (yyyy-mm-dd):\n---------------------------------------------------------------------\n\n### General improvements\n\n* The size of `classdef` objects is now reported by `who` (bug #55810).  A\n  value class' byte size is calculated by summing up the byte size of all its\n  properties.  A handle class' byte size is calculated by getting the size of\n  the machine word on the users computer (most likely 4 or 8 bytes).\n\n* The constructors of `classdef` classes now support returning more than one\n  output argument.  The first output argument must be the constructed object.\n\n\n### Graphical User Interface\n\n* When opening a file from the Find Files dialog, all occurrences of the search\n  text are highlighted in the editor.\n\n### Graphics backend\n\n\n### Matlab compatibility\n\n* Sparse matrices can only be 2-dimensional.  Octave now throws an error if the\n  input to `sparse` is an N-dimensional array.  An error is also thrown if an\n  N-dimensional indexing operation of a sparse matrix is attempted.  Both\n  behaviors are Matlab-compatible.\n\n* The function `ismember` now supports the `\"legacy\"` option for determining\n  which index position to return when there are multiple matches.  The default\n  behavior is now to return the first instance.  The legacy option returns\n  the location of the last instance instead, and was the default behavior in\n  previous Octave versions and in Matlab release R2012b and earlier.\n\n### Alphabetical list of new functions added in Octave 12\n\n\n### Deprecated functions, properties, and operators\n\nThe following functions and properties have been deprecated in Octave 12\nand will be removed from Octave 14 (or whatever version is the second\nmajor release after 12):\n\n- Functions\n\n        Function               | Replacement\n        -----------------------|--------------------------\n\n\n- Core\n\n        Function                            | Replacement\n        ------------------------------------|-------------------------------------------\n        string_vector::list_in_columns (os) | string_vector::list_in_columns (os, width)\n                                            |   width = command_editor::terminal_cols ()\n\nThe following features were deprecated in Octave 10 and have been removed\nfrom Octave 12.\n\n- Functions\n\n        Function    | Replacement\n        ------------|------------\n        dsearch     | dsearchn\n\n- Core\n\n        Function                                     | Replacement\n        ---------------------------------------------|-----------------------------------\n        symbol_record_rep::mark_as_variable          | symbol_record_rep::mark_variable\n        symbol_record_rep::unmark_as_variable        | symbol_record_rep::unmark_variable\n        symbol_record::mark_as_variable              | symbol_record::mark_variable\n        symbol_record::unmark_as_variable            | symbol_record::unmark_variable\n        interpreter::verbose                         | interpreter::init_trace\n        cmdline_options::verbose                     | cmdline_options::init_trace\n        interpreter::read_init_files                 | interpreter::read_user_files\n        cmdline_options::read_init_files             | cmdline_options::read_user_files\n        __lo_ieee_isnan,    __lo_ieee_float_isnan    | std::isnan     or  isnan\n        __lo_ieee_isfinite, __lo_ieee_float_isfinite | std::isfinite  or  isfinite\n        __lo_ieee_isinf,    __lo_ieee_float_isinf    | std::isinf     or  isinf\n        __lo_ieee_signbit,  __lo_ieee_float_signbit  | std::signbit   or  signbit\n\nThe following features were deprecated in Octave 11 and have been removed\nfrom Octave 12.\n\n- Function typedefs\n\n    * `b_d_Mapper`\n    * `b_c_Mapper`\n    * `d_d_Mapper`\n    * `d_c_Mapper`\n    * `c_c_Mapper`\n    * `b_f_Mapper`\n    * `b_fc_Mapper`\n    * `f_f_Mapper`\n    * `f_fc_Mapper`\n    * `fc_fc_Mapper`\n\n\n### Functions removed without the usual deprecation period\n\nThe following changes have been made without the usual deprecation period of two\nrelease cycles because we believe that they are unlikely to have been used in\ncode outside of core Octave.\n\nThe header `oct-atomic.h` has been removed.  Use the `std::atomic` object\ndefined in the standard C++ header `<atomic>` instead.\n\nThe following C++ functions have been removed from Octave 12:\n\n        Function                | Replacement\n        ------------------------|--------------------------------------------\n        octave_get_float_format | octave::mach_info::native_float_format\n        octave_is_big_endian    | octave::mach_info::words_big_endian\n                                | (or octave::mach_info::words_little_endian)\n        octave_atomic_increment | ++std::atomic<...>\n        octave_atomic_decrement | --std::atomic<...>\n\n### Function APIs changed without the usual deprecation period\n\nThe `Sparse` class for sparse matrices behaves similarly to the `Array` class\nfor full matrices.  The `Array` class provides a `data()` method which returns a\nread-only `const` pointer to the underlying data, and a `rwdata()` method which\nreturns a pointer that can be used to modify the underlying data.  The `Sparse`\nclass did not follow these conventions, but has been modified in Octave 12 to\nbehave identically to the `Array` class.\n\n        Old Function                | New Functions\n        ----------------------------|--------------------------------------\n        Sparse::data (write-access) | Sparse::rwdata\n                                    | Sparse::rwridx (write-access to ridx)\n                                    | Sparse::rwcidx (write-access to cidx)\n\nThe virtual functions `octave_base_value::all` and `octave_base_value::any`\nhave been changed to throw an error if the subclass type does not override `all`\nand `any`.  The `all` and `any` function only work on numeric or logical input.\nThey will error if passed any other input.  In previous versions of Octave,\n`all` and `any` returned 0 if the input type was neither numeric nor logical,\nwhich is not MATLAB compatible.\n\n### Old release news\n\n- [Octave 11.x](etc/NEWS.11.md)\n- [Octave 10.x](etc/NEWS.10.md)\n- [Octave 9.x](etc/NEWS.9.md)\n- [Octave 8.x](etc/NEWS.8.md)\n- [Octave 7.x](etc/NEWS.7.md)\n- [Octave 6.x](etc/NEWS.6.md)\n- [Octave 5.x](etc/NEWS.5.md)\n- [Octave 4.x](etc/NEWS.4)\n- [Octave 3.x](etc/NEWS.3)\n- [Octave 2.x](etc/NEWS.2)\n- [Octave 1.x](etc/NEWS.1)\n"
  },
  {
    "path": "etc/NEWS.2",
    "content": "Summary of changes for version 2.1.x (1997-06-05 -- 2006-03-20):\n---------------------------------------------------------------\n\n  * Given a matrix, X, and a boolean index, idx, of the same shape as\n    X, X(idx) and X(idx) = RHS now work no matter what the value of\n    do_fortran_indexing is.\n\n  * If you are using GNU Emacs 19.34 or earlier, you will need to add\n    the following code to your ~/.emacs file in order to use Emacs\n    Octave mode:\n\n      ;; Set up the custom library.\n      ;; taken from http://www.dina.kvl.dk/~abraham/custom/\n      (eval-and-compile\n        (condition-case ()\n            (require 'custom)\n          (error nil))\n        (if (and (featurep 'custom) (fboundp 'custom-declare-variable))\n            nil ;; We've got what we needed\n          ;; We have the old custom-library, hack around it!\n          (defmacro defgroup (&rest args)\n            nil)\n          (defmacro defcustom (var value doc &rest args)\n            (` (defvar (, var) (, value) (, doc))))))\n\n  * When `format +' is in effect, Octave uses the following symbols to\n    provide more information about the values in a matrix:\n\n      +      positive real\n      -      negative real\n      i      pure imaginary\n      c      complex\n      blank  zero\n\n  * The ++ and -- operators now work for indexed matrices, and the\n    following operators now work:\n\n      +=, -=, *=, /=, \\=, <<=, >>=, .*=, ./=, .\\=, &=, |=\n\n    These operators are currently implemented using a relatively\n    inefficient brute-force method but hey, they work.\n\n  * The built-in variable argv is now a list of strings instead of a\n    string vector.\n\n  * The value of LOADPATH set by the environment variable\n    OCTAVE_PATH, the -p or --path command line options, or on the\n    command line is no longer modified to include the default path.\n    Instead it is left as specified.  Its default value is now \":\",\n    which tells Octave to search the default path, and the new\n    built-in variable DEFAULT_LOADPATH contains the default list of\n    directories to search.\n\n  * The function file_in_path no longer does any special processing of\n    its PATH argument.  To search LOADPATH for files, it is now\n    generally better to use the new function file_in_loadpath.\n\n  * If fread is given a skip parameter, the skip is performed after\n    the read instead of before (for compatibility with Matlab).\n\n  * The new built-in variable `crash_dumps_octave_core' controls\n    whether Octave writes user variables to the file `octave-core'\n    when it crashes or is killed by a signal.  The default value is 1\n    (0 if you use --traditional).\n\n  * If LOADPATH contains a doubled colon, the default path is inserted\n    in its place.  This is similar to the substitution that also takes\n    place for leading or trailing colons in the LOADPATH.\n\n  * Loops of the form `for i = STRING ... endfor' are now allowed.\n\n  * It is now possible to set the iteration limit for lsode using\n    lsode_options (\"step limit\", N).\n\n  * New functions:\n\n      is_complex  -- tell whether a variable is complex\n      rehash      -- re-initialize the cache of directories in LOADPATH\n      graw        -- send a string to the gnuplot subprocess\n\n  * New functions from Kurt Hornik's Octave-ci package:\n\n    In finance (new directory):\n\n      fv    -- future value of an investment\n      fvl   -- future value of an initial lump sum investment\n      irr   -- internal rate of return of an investment\n      nper  -- number of payments needed for amortizing a loan\n      npv   -- net present value of a series of payments\n      pmt   -- amount of periodic payment needed to amortize a loan\n      pv    -- present value of an investment\n      pvl   -- present value of an investment that pays off at the end\n      rate  -- rate of return of an investment\n      vol   -- volatility of financial time series data\n\n    In linear-algebra:\n\n      dmult -- rescale the rows of a matrix\n\n    In signal:\n\n      arch_fit       -- fit an ARCH regression model\n      arch_rnd       -- simulate an ARCH process\n      arch_test      -- test for conditional heteroscedascity\n      arma_rnd       -- simulate an ARMA process\n      autocor        -- compute autocorrelations\n      autocov        -- compute autocovariances\n      autoreg_matrix -- design matrix for autoregressions\n      bartlett       -- coefficients of the Bartlett (triangular) window\n      blackman       -- coefficients of the Blackman window\n      diffpara       -- estimate the fractional differencing parameter\n      durbinlevinson -- perform one step of the Durbin-Levinson algorithm\n      fractdiff      -- compute fractional differences\n      hamming        -- coefficients of the Hamming window\n      hanning        -- coefficients of the Hanning window\n      hurst          -- estimate the Hurst parameter\n      periodogram    -- compute the periodogram\n      rectangle_lw   -- rectangular lag window\n      rectangle_sw   -- rectangular spectral window\n      sinetone       -- compute a sine tone\n      sinewave       -- compute a sine wave\n      spectral_adf   -- spectral density estimation\n      spectral_xdf   -- spectral density estimation\n      spencer        -- apply Spencer's 15-point MA filter\n      stft           -- short-term Fourier transform\n      synthesis      -- recover a signal from its short-term Fourier transform\n      triangle_lw    -- triangular lag window\n      triangle_sw    -- triangular spectral window\n      yulewalker     -- fit AR model by Yule-Walker method\n\n    In statistics/base (new directory):\n\n      center     -- center by subtracting means\n      cloglog    -- complementary log-log function\n      cor        -- compute correlations\n      cov        -- compute covariances\n      cut        -- cut data into intervals\n      iqr        -- interquartile range\n      kendall    -- kendall's rank correlation tau\n      logit      -- logit transformation\n      mean       -- compute arithmetic, geometric, and harmonic mean\n      meansq     -- compute mean square\n      moment     -- compute moments\n      ppplot     -- perform a PP-plot (probability plot)\n      probit     -- probit transformation\n      qqplot     -- perform a QQ-plot (quantile plot)\n      range      -- compute range\n      ranks      -- compute ranks\n      run_count  -- count upward runs\n      spearman   -- spearman's rank correlation rho\n      statistics -- compute basic statistics\n      studentize -- subtract mean and divide by standard deviation\n      table      -- cross tabulation\n      values     -- extract unique elements\n      var        -- compute variance\n\n    In statistics/distributions (new directory):\n\n      beta_cdf           -- CDF of the Beta distribution\n      beta_inv           -- Quantile function of the Beta distribution\n      beta_pdf           -- PDF of the Beta distribution\n      beta_rnd           -- Random deviates from the Beta distribution\n\n      binomial_cdf       -- CDF of the binomial distribution\n      binomial_inv       -- Quantile function of the binomial distribution\n      binomial_pdf       -- PDF of the binomial distribution\n      binomial_rnd       -- Random deviates from the binomial distribution\n\n      cauchy_cdf         -- CDF of the Cauchy distribution\n      cauchy_inv         -- Quantile function of the Cauchy distribution\n      cauchy_pdf         -- PDF of the Cauchy distribution\n      cauchy_rnd         -- Random deviates from the Cauchy distribution\n\n      chisquare_cdf      -- CDF of the chi-square distribution\n      chisquare_inv      -- Quantile function of the chi-square distribution\n      chisquare_pdf      -- PDF of the chi-square distribution\n      chisquare_rnd      -- Random deviates from the chi-square distribution\n\n      discrete_cdf       -- CDF of a discrete distribution\n      discrete_inv       -- Quantile function of a discrete distribution\n      discrete_pdf       -- PDF of a discrete distribution\n      discrete_rnd       -- Random deviates from a discrete distribution\n\n      empirical_cdf      -- CDF of the empirical distribution\n      empirical_inv      -- Quantile function of the empirical distribution\n      empirical_pdf      -- PDF of the empirical distribution\n      empirical_rnd      -- Bootstrap samples from the empirical distribution\n\n      exponential_cdf    -- CDF of the exponential distribution\n      exponential_inv    -- Quantile function of the exponential distribution\n      exponential_pdf    -- PDF of the exponential distribution\n      exponential_rnd    -- Random deviates from the exponential distribution\n\n      f_cdf              -- CDF of the F distribution\n      f_inv              -- Quantile function of the F distribution\n      f_pdf              -- PDF of the F distribution\n      f_rnd              -- Random deviates from the F distribution\n\n      gamma_cdf          -- CDF of the Gamma distribution\n      gamma_inv          -- Quantile function of the Gamma distribution\n      gamma_pdf          -- PDF of the Gamma distribution\n      gamma_rnd          -- Random deviates from the Gamma distribution\n\n      geometric_cdf      -- CDF of the geometric distribution\n      geometric_inv      -- Quantile function of the geometric distribution\n      geometric_pdf      -- PDF of the geometric distribution\n      geometric_rnd      -- Random deviates from the geometric distribution\n\n      hypergeometric_cdf -- CDF of the hypergeometric distribution\n      hypergeometric_inv -- Random deviates from hypergeometric distribution\n      hypergeometric_pdf -- PDF of the hypergeometric distribution\n      hypergeometric_rnd -- Random deviates from hypergeometric distribution\n\n      kolmogorov_smirnov_cdf -- CDF of the Kolmogorov-Smirnov distribution\n\n      laplace_cdf        -- CDF of the Laplace distribution\n      laplace_inv        -- Quantile function of the Laplace distribution\n      laplace_pdf        -- PDF of the Laplace distribution\n      laplace_rnd        -- Random deviates from the Laplace distribution\n\n      logistic_cdf       -- CDF of the logistic distribution\n      logistic_inv       -- Quantile function of the logistic distribution\n      logistic_pdf       -- PDF of the logistic distribution\n      logistic_rnd       -- Random deviates from the logistic distribution\n\n      lognormal_cdf      -- CDF of the log normal distribution\n      lognormal_inv      -- Quantile function of the log normal distribution\n      lognormal_pdf      -- PDF of the log normal distribution\n      lognormal_rnd      -- Random deviates from the log normal distribution\n\n      normal_cdf         -- CDF of the normal distribution\n      normal_inv         -- Quantile function of the normal distribution\n      normal_pdf         -- PDF of the normal distribution\n      normal_rnd         -- Random deviates from the normal distribution\n\n      pascal_cdf         -- CDF of the Pascal (negative binomial) distribution\n      pascal_inv         -- Quantile function of the Pascal distribution\n      pascal_pdf         -- PDF of the Pascal (negative binomial) distribution\n      pascal_rnd         -- Random deviates from the Pascal distribution\n\n      poisson_cdf        -- CDF of the Poisson distribution\n      poisson_inv        -- Quantile function of the Poisson distribution\n      poisson_pdf        -- PDF of the Poisson distribution\n      poisson_rnd        -- Random deviates from the Poisson distribution\n\n      stdnormal_cdf      -- CDF of the standard normal distribution\n      stdnormal_inv      -- Quantile function of standard normal distribution\n      stdnormal_pdf      -- PDF of the standard normal distribution\n      stdnormal_rnd      -- Random deviates from standard normal distribution\n\n      t_cdf              -- CDF of the t distribution\n      t_inv              -- Quantile function of the t distribution\n      t_pdf              -- PDF of the t distribution\n      t_rnd              -- Random deviates from the t distribution\n\n      uniform_cdf        -- CDF of the uniform distribution\n      uniform_inv        -- Quantile function of the uniform distribution\n      uniform_pdf        -- PDF of the uniform distribution\n      uniform_rnd        -- Random deviates from the uniform distribution\n\n      weibull_cdf        -- CDF of the Weibull distribution\n      weibull_inv        -- Quantile function of the Weibull distribution\n      weibull_pdf        -- PDF of the Weibull distribution\n      weibull_rnd        -- Random deviates from the Weibull distribution\n\n      wiener_rnd         -- Simulate a Wiener process\n\n    In statistics/models (new directory):\n\n      logistic_regression             -- ordinal logistic regression\n      logistic_regression_derivatives -- derivates of log-likelihood\n                                         in logistic regression\n      logistic_regression_likelihood  -- likelihood in logistic regression\n\n    In statistics/tests (new directory):\n\n      anova                       -- one-way analysis of variance\n      bartlett_test               -- bartlett test for homogeneity of variances\n      chisquare_test_homogeneity  -- chi-square test for homogeneity\n      chisquare_test_independence -- chi-square test for independence\n      cor_test                    -- test for zero correlation\n      f_test_regression           -- test linear hypotheses in linear\n                                     regression model\n      hotelling_test              -- test for mean of a multivariate normal\n      hotelling_test_2            -- compare means of two multivariate normals\n      kolmogorov_smirnov_test     -- one-sample Kolmogorov-Smirnov test\n      kolmogorov_smirnov_test_2   -- two-sample Kolmogorov-Smirnov test\n      kruskal_wallis_test         -- kruskal-Wallis test\n      manova                      -- one-way multivariate analysis of variance\n      mcnemar_test                -- mcnemar's test for symmetry\n      prop_test_2                 -- compare two proportions\n      run_test                    -- run test for independence\n      sign_test                   -- sign test\n      t_test                      -- student's one-sample t test\n      t_test_2                    -- student's two-sample t test\n      t_test_regression           -- test one linear hypothesis in linear\n                                     regression model\n      u_test                      -- mann-Whitney U-test\n      var_test                    -- f test to compare two variances\n      welch_test                  -- welch two-sample t test\n      wilcoxon_test               -- wilcoxon signed-rank test\n      z_test                      -- test for mean of a normal sample with\n                                     known variance\n      z_test_2                    -- compare means of two normal samples with\n                                     known variances\n\n  * The save command now accepts the option -append to save the\n    variables at the end of the file, leaving the existing contents.\n\n  * New command-line option --no-history (also available using the\n    single character option -H) inhibits saving command history.\n\n  * The mkoctfile script now accepts -DDEF options and passes them on\n    to the C and C++ compilers.\n\n  * Running `make check' should work now before you run `make install',\n    even if you build a copy of Octave that depends on shared versions\n    of the Octave libraries.\n\n  * For matrices, x(:) now works and returns a column vector no matter\n    what the value of do_fortran_indexing is.\n\n  * New keywords __FILE__ and __LINE__ expand to the name of the file\n    that is being read and the current input line number, respectively.\n\n  * Octave's expression parser is more general and consistent.  It is\n    now possible to access structure elements and index arbitrary\n    values.  For example, expressions like\n\n      my_home_dir = getpwuid (getuid ()) . dir;\n\n    and\n\n      svd (x) (1:5)\n\n    now work.\n\n  * New built-in variable `print_rhs_assign_val' controls what is\n    printed when an assignment expression is evaluated.  If it is\n    zero, the value of the variable on the left hand side (after the\n    assignment) is printed.  If it is nonzero, the value of the right\n    hand side (i.e., the result of the expression) is printed.  The\n    default value of is zero, so the behavior is the same as in\n    previous versions of Octave.\n\n  * tmpnam now takes two optional arguments, DIR, and PREFIX.  For\n    example, tmpnam (\"/foo\", \"bar-\") returns a file name like\n    \"/foo/bar-10773baa\".  If DIR is omitted or empty, the value of the\n    environment variable TMPDIR, or /tmp is used.  If PREFIX is\n    omitted, \"oct-\" is used.\n\n  * The built-in variable `PWD' has been removed.  If you need to get\n    the value of the current working directory, use the pwd() function\n    instead.\n\n  * New operators.  Octave's parser now recognizes the following\n    operators:  << >> += -= *= /= .+= .-= .*= ./= &= |= <<= >>=.  So\n    far, there are only a few operations defined that actually use\n    them (this should change before 2.1 is released).\n\n  * New built-in data types:\n\n    logical:\n\n      A true value is represented by 1, and false value by 0.\n      Comparison operations like <, <=, ==, >, >=, and != now return\n      logical values.  Indexing operations that use zero-one style\n      indexing must now use logical values.  You can use the new\n      function logical() to convert a numeric value to a logical\n      value.  This avoids the need for the built-in variable\n      `prefer_zero_one_indexing', so it has been removed.  Logical\n      values are automatically converted to numeric values where\n      appropriate.\n\n    file:\n\n      A file object represents an open Octave stream object.  The\n      fopen function now returns a file object instead of an integer.\n      File objects can be converted to integers automatically, and the\n      other functions that work with file ids still work with\n      integers, so this change should be backward compatible.\n\n      The binary left-shift operator `<<' has been defined to work as\n      in C++ for file objects and built-in types.  For example,\n\n        my_stream = fopen (\"foo\", \"w\");\n        my_stream << \"x = \" << pi << \" marks the spot\\n\";\n\n      writes `x = 3.1416 marks the spot' in the file foo.\n\n      The built-in variables stdin, stdout, and stderr are now also\n      file objects instead of integers.\n\n    list:\n\n      A list is an array of Octave objects.  It can be indexed using\n      the normal indexing operator.  For example,\n\n        x = list ([1,2;3,4], 1, \"foo\");\n        stdout << x(2) << \"\\n\"\n        1\n        stdout << x;\n        (\n         [1] =\n\n           1  2\n           3  4\n\n          [2] = 1\n          [3] = foo\n        )\n\n      There is currently no special syntax for creating lists; you\n      must use the list function.\n\n  * Commas in global statements are no longer special.  They are now\n    treated as command separators.  This removes a conflict in the\n    grammar and is consistent with the way Matlab behaves.  The\n    variable `warn_comma_in_global_decl' has been eliminated.\n\n  * It is now possible to declare static variables that retain their\n    values across function calls.  For example,\n\n      function ncall = f () static n = 0; ncall = ++n; endfunction\n\n    defines a function that returns the number of times that it has\n    been called.\n\n  * Within user-defined functions, the new automatic variable `argn'\n    contains the names of the arguments that were passed to the\n    function.  For example,\n\n      function f (...)\n        for i = 1:nargin\n          stdout << \"argn(\" << i << \") = `\" << deblank (argn(i,:)) \\\n                 << \"' and its value is \" << va_arg () << \"\\n\";\n        endfor\n      endfunction\n      f (1+2, \"foo\", sin (pi/2))\n\n    prints\n\n      argn(1) = `1 + 2' and its value is 3\n      argn(2) = `\"foo\"' and its value is foo\n      argn(3) = `sin (pi)' and its value is 1\n\n    on the standard output stream.  If nargin is zero, argn is not defined.\n  * Functions like quad, fsolve, and lsode can take either a function\n    name or a simple function body as a string.  For example,\n\n      quad (\"sqrt (x)\", 0, 1)\n\n    is equivalent to\n\n      function y = f (x) y = sqrt (x); endfunction\n      quad (\"f\", 0, 1)\n\n  * If the argument to eig() is symmetric, Octave uses the specialized\n    Lapack subroutine for symmetric matrices for a significant\n    increase in performance.\n\n  * If the argument to lsode that names the user-supplied function is\n    a 2-element string array, the second element is taken as the name\n    of the Jacobian function.  The named function should have the\n    following form:\n\n      JAC = f (X, T)\n\n    where JAC is the Jacobian matrix of partial derivatives of the\n    right-hand-side functions that define the set of differential\n    equations with respect to the state vector X.\n\n  * Global variables are now initialized to the empty matrix, for\n    compatibility with Matlab.\n\n  * Explicit initialization of global variables only happens once.\n    For example, after the following statements are evaluated, g still\n    has the value 1.\n\n      global g = 1\n      global g = 2\n\n    This is useful for initializing global variables that are used to\n    maintain state information that is shared among several functions.\n\n  * Structure elements completion on the command line actually works\n    now.\n\n  * The new built-in variable `fixed_point_format' controls whether\n    Octave uses a scaled fixed-point format for displaying matrices.\n    The default value is 0 unless you use --traditional.\n\n  * The function sumsq now computes sum (x .* conj (x)) for complex values.\n\n  * The new built-in variable max_recursion_depth allows you to\n    prevent Octave from attempting infinite recursion.  The default\n    value is 256.\n\n  * Octave now uses kpathsea 3.2.\n\n  * New configure option, --enable-readline.\n\n  * New configure option, --enable-static.\n\nSummary of changes for version 2.0.7 (1997-06-04):\n-------------------------------------------------\n\n  This is a bug-fixing release.  There are no new user-visible features.\n\nSummary of changes for version 2.0.6 (1997-05-27):\n-------------------------------------------------\n\n  This is primarily a bug-fixing release.  There are only a few new\n  user-visible features.\n\n  * The new built-in variable default_eval_print_flag controls whether\n    Octave prints the results of commands executed by eval() that do\n    not end with semicolons.  The default is 1.\n\n  * The new built-in constant OCTAVE_HOME specifies the top-level\n    directory where Octave is installed.\n\n  * Octave no longer includes functions to work with NPSOL or QPSOL,\n    because they are not free software.\n\n  * The new built-in variable called kluge_procbuf_delay specifies the\n    number of microseconds to delay in the parent process after\n    forking.  By default on gnu-win32 systems, it's set to 500000 (1/2\n    second).  On other systems, the default value is 0.  Delaying for\n    a short time in the parent after forking seems to avoid problems\n    in which communicating with subprocesses via pipes would sometimes\n    cause Octave to hang.  I doubt that the delay is really the right\n    solution.  If anyone has a better idea, I'd love to hear it.\n\nSummary of changes for version 2.0.5 (1997-03-01):\n-------------------------------------------------\n\n  * A `switch' statement is now available.  See the Statements chapter\n    in the manual for details.\n\n  * Commands like ls, save, and cd may now also be used as formal\n    parameters for functions.\n\n  * More tests.\n\nSummary of changes for version 2.0.4 (1997-02-20):\n-------------------------------------------------\n\n  * It is now possible to use commands like ls, save, and cd as simple\n    variable names.  They still cannot be used as formal parameters\n    for functions, or as the names of structure variables.  Failed\n    assignments leave them undefined (you can recover the original\n    function definition using clear).\n\n  * Is is now possible to invoke commands like ls, save, and cd as\n    normal functions (for example, load (\"foo\", \"x\", \"y\", \"z\")).\n\nSummary of changes for version 2.0.3 (1997-02-18):\n-------------------------------------------------\n\n  * The manual has been completely revised and now corresponds much\n    more closely to the features of the current version.\n\n  * The return value for assignment expressions is now the RHS since\n    that is more consistent with the way other programming languages\n    work.  However, Octave still prints the entire LHS value so that\n\n      x = zeros (1, 2);\n      x(2) = 1\n\n    still prints\n\n      x =\n\n        0  1\n\n    but an assignment like\n\n      z = x(2) = 1\n\n    sets z to 1 (not [ 0, 1 ] as in previous versions of Octave).\n\n  * It is now much easier to make binary distributions.  See the\n    Binary Distributions section of the manual for more details.\n\nSummary of changes for version 2.0.2 (1997-01-27):\n-------------------------------------------------\n\n  * Octave now stops executing commands from a script file if an error\n    is encountered.\n\n  * The return, and break commands now cause Octave to quit executing\n    commands from script files.  When used in invalid contexts, the\n    break, continue, and return commands are now simply ignored\n    instead of producing parse errors.\n\n  * size (\"\") is now [0, 0].\n\n  * New functions:\n\n      sleep   -- pause execution for a specified number of seconds\n      usleep  -- pause execution for a specified number of microseconds\n\nSummary of changes for version 2.0 (1996-12-10):\n-----------------------------------------------\n\n  * The set and show commands for setting and displaying gnuplot\n    parameters have been replaced by gset and gshow.  This change will\n    probably break lots of things, but it is necessary to allow for\n    compatibility with the Matlab graphics and GUI commands in a\n    future version of Octave.  (For now, the old set and show commands\n    do work, but they print an annoying warning message to try to get\n    people to switch to using gset.)\n\n  * Octave has been mostly ported to Windows NT and Windows 95 using\n    the beta 17 release of the Cygnus GNU-WIN32 tools.  Not everything\n    works, but it is usable.  See the file README.WINDOWS for more\n    information.\n\n  * Dynamic linking works on more systems using dlopen() and friends\n    (most modern Unix systems) or shl_load() and friends (HP/UX\n    systems).  A simple example is provided in examples/hello.cc.\n    For this feature to work, you must configure Octave with\n    --enable-shared.  You may also need to have a shared-library\n    version of libg++ and libstdc++.\n\n  * New data types can be added to Octave by writing a C++ class.  On\n    systems that support dynamic linking, new data types can be added\n    to an already running Octave binary.  A simple example appears in\n    the file examples/make_int.cc.  Other examples are the standard\n    Octave data types defined in the files src/ov*.{h,cc} and\n    src/op-*.cc.\n\n  * The configure option --enable-bounds-check turns on bounds\n    checking on element references for Octave's internal array and\n    matrix classes.  It's enabled by default.  To disable this\n    feature, configure Octave with --disable-bounds-check.\n\n  * The C-style I/O functions (fopen, fprintf, etc.) have been\n    rewritten to be more compatible with Matlab.  The fputs function\n    has also been added.  Usage of the *printf functions that was\n    allowed in previous versions of Octave should still work.\n    However, there is no way to make the new versions of the *scanf\n    functions compatible with Matlab *and* previous versions of\n    Octave.  An optional argument to the *scanf functions is now\n    available to make them behave in a way that is compatible with\n    previous versions of Octave.\n\n  * Octave can now read files that contain columns of numbers only,\n    with no header information.  The name of the loaded variable is\n    constructed from the file name.  Each line in the file must have\n    the same number of elements.\n\n  * The interface to the pager has changed.  The new built-in variable\n    `page_output_immediately' controls when Octave sends output to the\n    pager.  If it is nonzero, Octave sends output to the pager as soon\n    as it is available.  Otherwise, Octave buffers its output and\n    waits until just before the prompt is printed to flush it to the\n    pager.\n\n  * Expressions of the form\n\n      A(i,j) = x\n\n    where X is a scalar and the indices i and j define a matrix of\n    elements now work as you would expect rather than giving an error.\n    I am told that this is how Matlab 5.0 will behave when it is\n    released.\n\n  * Indexing of character strings now works.\n\n  * The echo command has been implemented.\n\n  * The document command is now a regular function.\n\n  * New method for handling errors:\n\n      try\n        BODY\n      catch\n        CLEANUP\n      end_try_catch\n\n    Where BODY and CLEANUP are both optional and may contain any\n    Octave expressions or commands.  The statements in CLEANUP are\n    only executed if an error occurs in BODY.\n\n    No warnings or error messages are printed while BODY is\n    executing.  If an error does occur during the execution of BODY,\n    CLEANUP can access the text of the message that would have been\n    printed in the builtin constant __error_text__.  This is the same\n    as eval (TRY, CATCH) (which may now also use __error_text__) but\n    it is more efficient since the commands do not need to be parsed\n    each time the TRY and CATCH statements are evaluated.\n\n  * Octave no longer parses the help command by grabbing everything\n    after the keyword `help' until a newline character is read.  To\n    get help for `;' or `,', now, you need to use the command\n    `help semicolon' or `help comma'.\n\n  * Octave's parser now does some simple constant folding.  This means\n    that expressions like 3*i are now evaluated only once, when a\n    function is compiled, and the right hand side of expressions like\n    a = [1,2;3,4] are treated as true matrix constants rather than\n    lists of elements which must be evaluated each time they are\n    needed.\n\n  * Built-in variables that can take values of \"true\" and \"false\" can\n    now also be set to any nonzero scalar value to indicate \"true\",\n    and 0 to indicate \"false\".\n\n  * New built-in variables `history_file', `history_size', and\n    `saving_history'.\n\n  * New built-in variable `string_fill_char' specifies the character\n    to fill with when creating arrays of strings.\n\n  * If the new built-in variable `gnuplot_has_frames' is nonzero,\n    Octave assumes that your copy of gnuplot includes support for\n    multiple plot windows when using X11.\n\n    If the new built-in variable `gnuplot_has_multiplot' is nonzero,\n    Octave assumes that your copy of gnuplot has the multiplot support\n    that is included in recent 3.6beta releases.\n\n    The initial values of these variables are determined by configure,\n    but can be changed in your startup script or at the command line\n    in case configure got it wrong, or if you upgrade your gnuplot\n    installation.\n\n  * The new plot function `figure' allows multiple plot windows when\n    using newer versions of gnuplot with X11.\n\n  * Octave now notices when the plotter has exited unexpectedly.\n\n  * New built-in variable `warn_missing_semicolon'.  If nonzero, Octave\n    will warn when statements in function definitions don't end in\n    semicolons.  The default value is 0.\n\n  * Octave now attempts to continue after floating point exceptions\n    or out-of-memory errors.\n\n  * If Octave crashes, it now attempts to save all user-defined\n    variables in a file named `octave-core' in the current directory\n    before exiting.\n\n  * It is now possible to get the values of individual option settings\n    for the dassl, fsolve, lsode, npsol, qpsol, and quad functions\n    using commands like\n\n      dassl_reltol = dassl_options (\"relative tolerance\");\n\n  * The svd() function no longer computes the left and right singular\n    matrices unnecessarily.  This can significantly improve\n    performance for large matrices if you are just looking for the\n    singular values.\n\n  * The filter() function is now a built-in function.\n\n  * New function randn() returns a pseudo-random number from a normal\n    distribution.  The rand() and randn() functions have separate\n    seeds and generators.\n\n  * Octave's command-line arguments are now available in the built-in\n    variable `argv'.  The program name is also available in the\n    variables `program_invocation_name' and `program_name'.  If\n    executing a script from the command line (e.g., octave foo.m) or\n    using the `#! /bin/octave' hack, the program name is set to the\n    name of the script.\n\n  * New built-in variable `completion_append_char' used as the\n    character to append to successful command-line completion\n    attempts.  The default is \" \" (a single space).\n\n  * Octave now uses a modified copy of the readline library from\n    version 1.14.5 of GNU bash.\n\n  * In prompt strings, `\\H' expands to the whole host name.\n\n  * New built-in variable `beep_on_error'.  If nonzero, Octave will try\n    to ring your terminal's bell before printing an error message.\n    The default value is 0.\n\n  * For functions defined from files, the type command now prints the\n    text of the file.  You can still get the text reconstructed from\n    the parse tree by using the new option -t (-transformed).\n\n  * New command-line argument --traditional sets the following\n    preference variables for compatibility with Matlab:\n\n      PS1                           = \">> \"\n      PS2                           = \"\"\n      beep_on_error                 = 1\n      default_save_format           = \"mat-binary\"\n      define_all_return_values      = 1\n      do_fortran_indexing           = 1\n      empty_list_elements_ok        = 1\n      implicit_str_to_num_ok        = 1\n      ok_to_lose_imaginary_part     = 1\n      page_screen_output            = 0\n      prefer_column_vectors         = 0\n      prefer_zero_one_indexing      = 1\n      print_empty_dimensions        = 0\n      treat_neg_dim_as_zero         = 1\n      warn_function_name_clash      = 0\n      whitespace_in_literal_matrix  = \"traditional\"\n\n  * New functions:\n\n      readdir  -- returns names of files in directory as array of strings\n      mkdir    -- create a directory\n      rmdir    -- remove a directory\n      rename   -- rename a file\n      unlink   -- delete a file\n      umask    -- set permission mask for file creation\n      stat     -- get information about a file\n      lstat    -- get information about a symbolic link\n      glob     -- perform filename globbing\n      fnmatch  -- match strings with filename globbing patterns\n      more     -- turn the pager on or off\n      gammaln  -- alias for lgamma\n\n  * New audio functions from Andreas Weingessel\n    <Andreas.Weingessel@ci.tuwien.ac.at>.\n\n      lin2mu     -- linear to mu-law encoding\n      loadaudio  -- load an audio file to a vector\n      mu2lin     -- mu-law to linear encoding\n      playaudio  -- play an audio file\n      record     -- record sound and store in vector\n      saveaudio  -- save a vector as an audio file\n      setaudio   -- executes mixer shell command\n\n  * New plotting functions from Vinayak Dutt.  Ones dealing with\n    multiple plots on one page require features from gnuplot 3.6beta\n    (or later).\n\n      bottom_title  -- put title at the bottom of the plot\n      mplot         -- multiplot version of plot\n      multiplot     -- switch multiple-plot mode on or off\n      oneplot       -- return to one plot per page\n      plot_border   -- put a border around plots\n      subplot       -- position multiple plots on a single page\n      subwindow     -- set subwindow position for next plot\n      top_title     -- put title at the top of the plot\n      zlabel        -- put a label on the z-axis\n\n  * New string functions\n\n      bin2dec  -- convert a string of ones and zeros to an integer\n      blanks   -- create a string of blanks\n      deblank  -- delete trailing blanks\n      dec2bin  -- convert an integer to a string of ones and zeros\n      dec2hex  -- convert an integer to a hexadecimal string\n      findstr  -- locate occurrences of one string in another\n      hex2dec  -- convert a hexadecimal string to an integer\n      index    -- return position of first occurrence a string in another\n      rindex   -- return position of last occurrence a string in another\n      split    -- divide one string into pieces separated by another\n      str2mat  -- create a string matrix from a list of strings\n      strrep   -- replace substrings in a string\n      substr   -- extract a substring\n\n    The following functions return a matrix of ones and zeros.\n    Elements that are nonzero indicate that the condition was true for\n    the corresponding character in the string array.\n\n      isalnum   -- letter or a digit\n      isalpha   -- letter\n      isascii   -- ascii\n      iscntrl   -- control character\n      isdigit   -- digit\n      isgraph   -- printable (but not space character)\n      islower   -- lower case\n      isprint   -- printable (including space character)\n      ispunct   -- punctuation\n      isspace   -- whitespace\n      isupper   -- upper case\n      isxdigit  -- hexadecimal digit\n\n    These functions return new strings.\n\n      tolower  -- convert to lower case\n      toupper  -- convert to upper case\n\n  * New function, fgetl.  Both fgetl and fgets accept an optional\n    second argument that specifies a maximum number of characters to\n    read, and the function fgets is now compatible with Matlab.\n\n  * Printing in hexadecimal format now works (format hex).  It is also\n    possible to print the internal bit representation of a value\n    (format bit).  Note that these formats are only implemented for\n    numeric values.\n\n  * Additional structure features:\n\n    -- Name completion now works for structures.\n\n    -- Values and names of structure elements are now printed by\n       default.  The new built-in variable `struct_levels_to_print'\n       controls the depth of nested structures to print.  The default\n       value is 2.\n\n    -- New functions:\n\n       struct_contains (S, NAME) -- returns 1 if S is a structure with\n                                    element NAME; otherwise returns 0.\n\n       struct_elements (S)       -- returns the names of all elements\n                                    of structure S in an array of strings.\n\n  * New io/subprocess functions:\n\n      fputs    -- write a string to a file with no formatting\n      popen2   -- start a subprocess with 2-way communication\n      mkfifo   -- create a FIFO special file\n      popen    -- open a pipe to a subprocess\n      pclose   -- close a pipe from a subprocess\n      waitpid  -- check the status of or wait for subprocesses\n\n  * New time functions:\n\n      asctime    -- format time structure according to local format\n      ctime      -- equivalent to `asctime (localtime (TMSTRUCT))'\n      gmtime     -- return time structure corresponding to UTC\n      localtime  -- return time structure corresponding to local time zone\n      strftime   -- print given time structure using specified format\n      time       -- return current time\n\n    The `clock' and `date' functions are now implemented in M-files\n    using these basic functions.\n\n  * Access to additional Unix system calls:\n\n      dup2     -- duplicate a file descriptor\n      exec     -- replace current process with a new process\n      fcntl    -- control open file descriptors\n      fork     -- create a copy of the current process\n      getpgrp  -- return the process group id of the current process\n      getpid   -- return the process id of the current process\n      getppid  -- return the process id of the parent process\n      getuid   -- return the real user id of the current process\n      getgid   -- return the real group id of the current process\n      geteuid  -- return the effective user id of the current process\n      getegid  -- return the effective group id of the current process\n      pipe     -- create an interprocess channel\n\n  * Other new functions:\n\n      commutation_matrix  -- compute special matrix form\n      duplication_matrix  -- compute special matrix form\n      common_size.m       -- bring arguments to a common size\n      completion_matches  -- perform command completion on string\n      tilde_expand        -- perform tilde expansion on string\n\n      meshgrid  -- compatible with Matlab's meshgrid function\n      tmpnam    -- replaces octave_tmp_file_name\n      atexit    -- register functions to be called when Octave exits\n      putenv    -- define an environment variable\n      bincoeff  -- compute binomial coefficients\n      nextpow2  -- compute the next power of 2 greater than a number\n      detrend   -- remove a best fit polynomial from data\n      erfinv    -- inverse error function\n      shift     -- perform a circular shift on the elements of a matrix\n      pow2      -- compute 2 .^ x\n      log2      -- compute base 2 logarithms\n      diff      -- compute differences of matrix elements\n      vech      -- stack columns of a matrix below the diagonal\n      vec       -- stack columns of a matrix to form a vector\n      xor       -- compute exclusive or\n\n  * Functions for getting info from the password database on Unix systems:\n\n      getpwent  -- read entry from password-file stream, opening if necessary\n      getpwuid  -- search for password entry with matching user ID\n      getpwnam  -- search for password entry with matching username\n      setpwent  -- rewind the password-file stream\n      endpwent  -- close the password-file stream\n\n  * Functions for getting info from the group database on Unix systems:\n\n      getgrent  -- read entry from group-file stream, opening if necessary\n      getgrgid  -- search for group entry with matching group ID\n      getgrnam  -- search for group entry with matching group name\n      setgrent  -- rewind the group-file stream\n      endgrent  -- close the group-file stream\n\n  * The New function octave_config_info returns a structure containing\n    information about how Octave was configured and compiled.\n\n  * New function getrusage returns a structure containing system\n    resource usage statistics.  The `cputime' function is now defined\n    in an M-file using getrusage.\n\n  * The info reader is now a separate binary that runs as a\n    subprocess.  You still need the info reader distributed with\n    Octave though, because there are some new command-line arguments\n    that are not yet available in the public release of Info.\n\n  * There is a new built-in variable, INFO_PROGRAM, which is used as\n    the name of the info program to run.  Its initial value is\n    $OCTAVE_HOME/lib/octave/VERSION/exec/ARCH/info, but that value can\n    be overridden by the environment variable OCTAVE_INFO_PROGRAM, or\n    the command line argument --info-program NAME, or by setting the\n    value of INFO_PROGRAM in a startup script.\n\n  * There is a new built-in variable, EXEC_PATH, which is used as\n    the list of directories to search when executing subprograms.  Its\n    initial value is taken from the environment variable\n    OCTAVE_EXEC_PATH (if it exists) or PATH, but that value can be\n    overridden by the command line argument --exec-path PATH, or\n    by setting the value of EXEC_PATH in a startup script.  If the\n    EXEC_PATH begins (ends) with a colon, the directories\n    $OCTAVE_HOME/lib/octave/VERSION/exec/ARCH and $OCTAVE_HOME/bin are\n    prepended (appended) to EXEC_PATH (if you don't specify a value\n    for EXEC_PATH explicitly, these special directories are prepended\n    to your PATH).\n\n  * If it is present, Octave will now use an `ls-R' database file to\n    speed up recursive path searching.  Octave looks for a file called\n    ls-R in the directory specified by the environment variable\n    OCTAVE_DB_DIR.  If that is not set but the environment variable\n    OCTAVE_HOME is set, Octave looks in $OCTAVE_HOME/lib/octave.\n    Otherwise, Octave looks in the directory $datadir/octave (normally\n    /usr/local/lib/octave).\n\n  * New examples directory.\n\n  * There is a new script, mkoctfile, that can be used to create .oct\n    files suitable for dynamic linking.\n\n  * Many more bug fixes.\n\n  * ChangeLogs are now kept in each subdirectory.\n\nSee NEWS.1 for old news.\n"
  },
  {
    "path": "etc/NEWS.3",
    "content": "Summary of important user-visible changes for version 3.8 (2013-12-27):\n----------------------------------------------------------------------\n\n  ** One of the biggest new features for Octave 3.8 is a graphical user\n     interface.  It is the one thing that users have requested most\n     often over the last few years and now it is almost ready.  But\n     because it is not quite as polished as we would like, we have\n     decided to wait until the 4.0.x release series before making the\n     GUI the default interface (until then, you can use the --force-gui\n     option to start the GUI).\n\n     Given the length of time and the number of bug fixes and\n     improvements since the last major release Octave, we also decided\n     against delaying the release of all these new improvements any\n     longer just to perfect the GUI.  So please enjoy the 3.8 release of\n     Octave and the preview of the new GUI.  We believe it is working\n     reasonably well, but we also know that there are some obvious rough\n     spots and many things that could be improved.\n\n     WE NEED YOUR HELP.  There are many ways that you can help us fix\n     the remaining problems, complete the GUI, and improve the overall\n     user experience for both novices and experts alike:\n\n       * If you are a skilled software developer, you can help by\n         contributing your time to help with Octave's development.  See\n         http://octave.org/get-involved.html for more information.\n\n       * If Octave does not work properly, you are encouraged\n         report the problems you find.  See http://octave.org/bugs.html\n         for more information about how to report problems.\n\n       * Whether you are a user or developer, you can help to fund the\n         project.  Octave development takes a lot of time and expertise.\n         Your contributions help to ensure that Octave will continue to\n         improve.  See http://octave.org/donate.html for more details.\n\n    We hope you find Octave to be useful.  Please help us make it even\n    better for the future!\n\n ** Octave now uses OpenGL graphics by default with FLTK widgets.  If\n    OpenGL libraries or FLTK widgets are not available when Octave is\n    built, gnuplot is used.  You may also choose to use gnuplot for\n    graphics by executing the command\n\n      graphics_toolkit (\"gnuplot\")\n\n    Adding this command to your ~/.octaverc file will set the default\n    for each session.\n\n ** Printing or saving figures with OpenGL graphics requires the\n    gl2ps library which is no longer distributed with Octave.  The\n    software is widely available in most package managers.  If a\n    pre-compiled package does not exist for your system, you can find\n    the current sources at http://www.geuz.org/gl2ps/.\n\n ** Octave now supports nested functions with scoping rules that are\n    compatible with Matlab.  A nested function is one declared and defined\n    within the body of another function.  The nested function is only\n    accessible from within the enclosing function which makes it one\n    method for making private functions whose names do not conflict with those\n    in the global namespace (See also subfunctions and private functions).\n    In addition, variables in the enclosing function are visible within the\n    nested function.  This makes it possible to have a pseudo-global variable\n    which can be seen by a group of functions, but which is not visible in\n    the global namespace.\n\n    Example:\n    function outerfunc (...)\n      ...\n      function nested1 (...)\n        ...\n        function nested2 (...)\n           ...\n        endfunction\n      endfunction\n\n      function nested3 (...)\n        ...\n      endfunction\n    endfunction\n\n ** Line continuations inside character strings have changed.\n\n    The sequence '...' is no longer recognized as a line continuation\n    inside a character string.  A backslash '\\' followed by a newline\n    character is no longer recognized as a line continuation inside\n    single-quoted character strings.  Inside double-quoted character\n    strings, a backslash followed by a newline character is still\n    recognized as a line continuation, but the backslash character must\n    be followed *immediately* by the newline character.  No whitespace or\n    end-of-line comment may appear between them.\n\n ** Backslash as a continuation marker outside of double-quoted strings\n    is now deprecated.\n\n    Using '\\' as a continuation marker outside of double quoted strings\n    is now deprecated and will be removed from a future version of\n    Octave.  When that is done, the behavior of\n\n      (a \\\n       b)\n\n    will be consistent with other binary operators.\n\n ** Redundant terminal comma accepted by parser\n\n    A redundant terminal comma is now accepted in matrix\n    definitions which allows writing code such as\n\n    [a,...\n     b,...\n     c,...\n    ] = deal (1,2,3)\n\n ** Octave now has limited support for named exceptions\n\n    The following syntax is now accepted:\n\n      try\n        statements\n      catch exception-id\n        statements\n      end\n\n    The exception-id is a structure with the fields \"message\" and\n    \"identifier\".  For example\n\n      try\n        error (\"Octave:error-id\", \"error message\");\n      catch myerr\n        printf (\"identifier: %s\\n\", myerr.identifier);\n        printf (\"message:    %s\\n\", myerr.message);\n      end_try_catch\n\n    When classdef-style classes are added to Octave, the exception-id\n    will become an MException object.\n\n ** Warning states may now be set temporarily, until the end of the\n    current function, using the syntax\n\n      warning STATE ID \"local\"\n\n    in which STATE may be \"on\", \"off\", or \"error\".  Changes to warning\n    states that are set locally affect the current function and all\n    functions called from the current scope.  The previous warning state\n    is restored on return from the current function.  The \"local\"\n    option is ignored if used in the top-level workspace.\n\n ** Warning IDs renamed:\n\n    Octave:array-as-scalar => Octave:array-to-scalar\n    Octave:array-as-vector => Octave:array-to-vector\n\n ** 'emptymatch', 'noemptymatch' options added to regular expressions.\n\n    With this addition Octave now accepts the entire set of Matlab options\n    for regular expressions.  'noemptymatch' is the default, but 'emptymatch'\n    has certain uses where you need to match an assertion rather than actual\n    characters.  For example,\n\n    regexprep ('World', '^', 'Hello ', 'emptymatch')\n      => Hello World\n\n    where the pattern is actually the assertion '^' or start-of-line.\n\n ** For compatibility with Matlab, the regexp, regexpi, and regexprep\n    functions now process backslash escape sequences in single-quoted pattern\n    strings.  In addition, the regexprep function now processes backslash\n    escapes in single-quoted replacement strings.  For example,\n\n    regexprep (str, '\\t', '\\n')\n\n    would search the variable str for a TAB character (escape sequence \\t)\n    and replace it with a NEWLINE (escape sequence \\n).  Previously the\n    expression would have searched for a literal '\\' followed by 't' and\n    replaced the two characters with the sequence '\\', 'n'.\n\n ** A TeX parser has been implemented for the FLTK toolkit and is the default\n    for any text object including titles and axis labels.  The TeX parser is\n    supported only for display on a monitor, not for printing.\n\n    A quick summary of features:\n\n    Code         Feature     Example             Comment\n    -----------------------------------------------------------------\n    _            subscript   H_2O                formula for water\n    ^            exponent    y=x^2               formula for parabola\n    \\char        symbol      \\beta               Greek symbol beta\n    \\fontname    font        \\fontname{Arial}    set Arial font\n    \\fontsize    fontsize    \\fontsize{16}       set fontsize 16\n    \\color[rgb]  fontcolor   \\color[rgb]{1 0 1}  set magenta color\n    \\bf          bold        \\bfBold Text        bold font\n    \\it          italic      \\itItalic Text      italic font\n    \\sl          slanted     \\slOblique Text     slanted font\n    \\rm          normal      \\bfBold\\rmNormal    normal font\n    {}           group       {\\bf Bold}Normal    group objects\n                             e^{i*\\pi} = -1      group objects\n\n ** The m-files in the plot directory have been overhauled.\n\n    The plot functions now produce output that is nearly visually compatible\n    with Matlab.  Plot performance has also increased, dramatically for some\n    functions such as comet and waitbar.  Finally, the documentation for most\n    functions has been updated so it should be clearer both how to use a\n    function and when a function is appropriate.\n\n ** The m-files in the image directory have been overhauled.\n\n    The principal benefit is that Octave will now no longer automatically\n    convert images stored with integers to doubles.  Storing images as uint8\n    or uint16 requires only 1/8 or 1/4 the memory of an image stored using\n    doubles.  For certain operations, such as fft2, the image must still be\n    converted to double in order to work.\n\n    Other changes include fixes to the way indexed images are read from a\n    colormap depending on the image class (integer images have a -1 offset to\n    the colormap row number).\n\n ** The imread and imwrite functions have been completely rewritten.\n\n    The main changes relate to the alpha channel, support for reading and\n    writing of floating point images, implemented writing of indexed images,\n    and appending images to multipage image files.\n\n    The issues that may arise due to backwards incompatibility are:\n\n      * imwrite no longer interprets a length of 2 or 4 in the third dimension\n        as grayscale or RGB with alpha channel (a length of 4 will be saved\n        as a CMYK image).  Alpha channel must be passed as separate argument.\n\n      * imread will always return the colormap indexes when reading an indexed\n        image, even if the colormap is not requested as output.\n\n      * transparency values are now inverted from previous Octave versions\n        (0 is for completely transparent instead of completely opaque).\n\n    In addition, the function imformats has been implemented to expand\n    reading and writing of images of different formats through imread\n    and imwrite.\n\n ** The colormap function now provides new options--\"list\", \"register\",\n    and \"unregister\"--to list all available colormap functions, and to\n    add or remove a function name from the list of known colormap\n    functions.  Packages that implement extra colormaps should use these\n    commands with PKG_ADD and PKG_DEL statements.\n\n ** strsplit has been modified to be compatible with Matlab.  There\n    are two instances where backward compatibility is broken.\n\n    (1) Delimiters are now string vectors, not scalars.\n\n    Octave's legacy behavior\n\n      strsplit (\"1 2, 3\", \", \")\n      ans =\n      {\n       [1,1] = 1\n       [1,2] = 2\n       [1,3] =\n       [1,4] = 3\n      }\n\n    Matlab compatible behavior\n\n      strsplit (\"1 2, 3\", \", \")\n      ans =\n      {\n       [1,1] = 1 2\n       [1,2] = 3\n      }\n\n    (2) By default, Matlab treats consecutive delimiters as a single\n    delimiter.  By default, Octave's legacy behavior was to return an\n    empty string for the part between the delmiters.\n\n    Where legacy behavior is desired, the call to strsplit() may be\n    replaced by ostrsplit(), which is Octave's original implementation of\n    strsplit().\n\n ** The datevec function has been extended for better Matlab compatibility.\n    It now accepts string inputs in the following numerical formats: 12, 21,\n    22, 26, 29, 31.  This is undocumented, but verifiable, Matlab behavior.\n    In addition, the default for formats which do not specify a date is\n    January 1st of the current year.  The previous default was the current day,\n    month, and year.  This may produce changes in existing scripts.\n\n ** The error function and its derivatives has been extended to accept complex\n    arguments.  The following functions now accept complex inputs:\n\n    erf  erfc  erfcx\n\n    In addition two new error functions erfi (imaginary error function) and\n    dawson (scaled imaginary error function) have been added.\n\n ** The glpk function has been modified to reflect changes in the GLPK\n    library.  The \"round\" and \"itcnt\" options have been removed.  The\n    \"relax\" option has been replaced by the \"rtest\" option.  The numeric\n    values of error codes and of some options have also changed.\n\n ** The kurtosis function has changed definition to be compatible with\n    Matlab.  It now returns the base kurtosis instead of the \"excess kurtosis\".\n    The old behavior can be had by changing scripts to normalize with -3.\n\n               \"excess kurtosis\" = kurtosis (x) - 3\n\n ** The moment function has changed definition to be compatible with\n    Matlab.  It now returns the central moment instead of the raw moment.\n    The old behavior can be had by passing the type argument \"r\" for raw.\n\n ** The default name of the Octave crash dump file is now\n    \"octave-workspace\" instead of \"octave-core\".  The exact name can\n    always be customized with the octave_core_file_name function.\n\n ** A citation command has been added to display information on how to\n    cite Octave and packages in publications.  The package system will\n    look for and install CITATION files from packages.\n\n ** The java package from Octave Forge is now part of core Octave.  The\n    following new functions are available for interacting with Java\n    directly from Octave:\n\n      debug_java     java_matrix_autoconversion\n      isjava         java_unsigned_autoconversion\n      java2mat       javaaddpath\n      javaArray      javaclasspath\n      javaMethod     javamem\n      javaObject     javarmpath\n                     usejava\n\n    In addition, the following functions that use the Java interface\n    are now available (provided that Octave is compiled with support for\n    Java enabled):\n\n      helpdlg    listdlg   questdlg\n      inputdlg   msgbox    warndlg\n\n ** Other new functions added in 3.8.0:\n\n      atan2d                     erfi             lines\n      base64_decode              expint           linsolve\n      base64_encode              findfigs         missing_component_hook\n      betaincinv                 flintmax         polyeig\n      built_in_docstrings_file   fminsearch       prefdir\n      cmpermute                  gallery          preferences\n      cmunique                   gco              readline_re_read_init_file\n      colorcube                  hdl2struct       readline_read_init_file\n      copyobj                    history_save     rgbplot\n      dawson                     imformats        save_default_options\n      dblist                     importdata       shrinkfaces\n      desktop                    isaxes           splinefit\n      doc_cache_create           iscolormap       stemleaf\n      ellipj                     isequaln         strjoin\n      ellipke                    jit_debug        struct2hdl\n      erfcinv                    jit_enable       tetramesh\n                                 jit_startcnt     waterfall\n\n ** Deprecated functions.\n\n    The following functions were deprecated in Octave 3.4 and have been\n    removed from Octave 3.8.\n\n      autocor    dispatch              is_global    setstr\n      autocov    fstat                 krylovb      strerror\n      betai      gammai                perror       values\n      cellidx    glpkmex               replot\n      cquad      is_duplicate_entry    saveimage\n\n    The following functions have been deprecated in Octave 3.8 and will\n    be removed from Octave 3.12 (or whatever version is the second major\n    release after 3.8):\n\n      default_save_options    java_new\n      gen_doc_cache           java_set\n      interp1q                java_unsigned_conversion\n      isequalwithequalnans    javafields\n      java_convert_matrix     javamethods\n      java_debug              re_read_readline_init_file\n      java_get                read_readline_init_file\n      java_invoke             saving_history\n\n\n    The following keywords have been deprecated in Octave 3.8 and will\n    be removed from Octave 3.12 (or whatever version is the second major\n    release after 3.8):\n\n      static\n\n    The following configuration variables have been deprecated in Octave\n    3.8 and will be removed from Octave 3.12 (or whatever version is the\n    second major release after 3.8):\n\n      CC_VERSION  (now GCC_VERSION)\n      CXX_VERSION (now GXX_VERSION)\n\n    The internal class <Octave_map> has been deprecated in Octave 3.8 and will\n    be removed from Octave 3.12 (or whatever version is the second major\n    release after 3.8).  Replacement classes are <octave_map> (struct array)\n    or <octave_scalar_map> for a single structure.\n\nSummary of important user-visible changes for version 3.6 (2012-01-15):\n----------------------------------------------------------------------\n\n ** The PCRE library is now required to build Octave.  If a pre-compiled\n    package does not exist for your system, you can find PCRE sources\n    at http://www.pcre.org\n\n ** The ARPACK library is no longer distributed with Octave.\n    If you need the eigs or svds functions you must provide an\n    external ARPACK through a package manager or by compiling it\n    yourself.  If a pre-compiled package does not exist for your system,\n    you can find the current ARPACK sources at\n    http://forge.scilab.org/index.php/p/arpack-ng\n\n ** Many of Octave's binary operators (.*, .^, +, -, ...) now perform\n    automatic broadcasting for array operations which allows you to use\n    operator notation instead of calling bsxfun or expanding arrays (and\n    unnecessarily wasting memory) with repmat or similar idioms.  For\n    example, to scale the columns of a matrix by the elements of a row\n    vector, you may now write\n\n      rv .* M\n\n    In this expression, the number of elements of rv must match the\n    number of columns of M.  The following operators are affected:\n\n      plus      +  .+\n      minus     -  .-\n      times     .*\n      rdivide   ./\n      ldivide   .\\\n      power     .^  .**\n      lt        <\n      le        <=\n      eq        ==\n      gt        >\n      ge        >=\n      ne        !=  ~=\n      and       &\n      or        |\n      atan2\n      hypot\n      max\n      min\n      mod\n      rem\n      xor\n\n    additionally, since the A op= B assignment operators are equivalent\n    to A = A op B, the following operators are also affected:\n\n      +=  -=  .+=  .-=  .*=  ./=  .\\=  .^=  .**=  &=  |=\n\n    See the \"Broadcasting\" section in the new \"Vectorization and Faster\n    Code Execution\" chapter of the manual for more details.\n\n ** Octave now features a profiler, thanks to the work of Daniel Kraft\n    under the Google Summer of Code mentorship program.  The manual has\n    been updated to reflect this addition.  The new user-visible\n    functions are profile, profshow, and profexplore.\n\n ** Overhaul of statistical distribution functions\n\n    Functions now return \"single\" outputs for inputs of class \"single\".\n\n    75% reduction in memory usage through use of logical indexing.\n\n    Random sample functions now use the same syntax as rand and accept\n    a comma separated list of dimensions or a dimension vector.\n\n    Functions have been made Matlab-compatible with regard to special\n    cases (probability on boundaries, probabilities for values outside\n    distribution, etc.).  This may cause subtle changes to existing\n    scripts.\n\n    negative binomial function has been extended to real, non-integer\n    inputs.  The discrete_inv function now returns v(1) for 0 instead of\n    NaN.  The nbincdf function has been recoded to use a closed form\n    solution with betainc.\n\n ** strread, textscan, and textread have been completely revamped.\n\n    They now support nearly all Matlab functionality including:\n\n      * Matlab-compatible whitespace and delimiter defaults\n\n      * Matlab-compatible options: 'whitespace', treatasempty', format\n        string repeat count, user-specified comment style, uneven-length\n        output arrays, %n and %u conversion specifiers (provisionally)\n\n ** All .m string functions have been modified for better performance or\n    greater Matlab compatibility.  Performance gains of 15X-30X have\n    been demonstrated.  Operations on cell array of strings no longer pay\n    quite as high a penalty as those on 2-D character arrays.\n\n      deblank:  Now requires character or cellstr input.\n\n      strtrim:  Now requires character or cellstr input.\n                No longer trims nulls (\"\\0\") from string for Matlab\n                compatibility.\n\n      strmatch: Follows documentation precisely and ignores trailing spaces\n                in pattern and in string.  Note that this is documented\n                Matlab behavior but the implementation apparently does\n                not always follow it.\n\n      substr:   Now possible to specify a negative LEN option which\n                extracts to within LEN of the end of the string.\n\n      strtok:   Now accepts cellstr input.\n\n      base2dec, bin2dec, hex2dec:\n                Now accept cellstr inputs.\n\n      dec2base, dec2bin, dec2hex:\n                Now accept cellstr inputs.\n\n      index, rindex:\n                Now accept 2-D character array input.\n\n      strsplit: Now accepts 2-D character array input.\n\n ** Geometry functions derived from Qhull (convhull, delaunay, voronoi)\n    have been revamped.  The options passed to the underlying qhull\n    command have been changed for better results or for Matlab\n    compatibility.\n\n      convhull: Default options are \"Qt\" for 2D, 3D, 4D inputs\n                Default options are \"Qt Qx\" for 5D and higher\n\n      delaunay: Default options are \"Qt Qbb Qc Qz\" for 2D and 3D inputs\n                Default options are \"Qt Qbb Qc Qx\" for 4D and higher\n\n      voronoi:  No default arguments\n\n ** Date/Time functions updated.  Millisecond support with FFF format\n    string now supported.\n\n    datestr: Numerical formats 21, 22, 29 changed to match Matlab.\n             Now accepts cellstr input.\n\n ** The following warning IDs have been removed:\n\n      Octave:associativity-change\n      Octave:complex-cmp-ops\n      Octave:empty-list-elements\n      Octave:fortran-indexing\n      Octave:precedence-change\n\n ** The warning ID Octave:string-concat has been renamed to\n    Octave:mixed-string-concat.\n\n ** Octave now includes the following Matlab-compatible preference\n    functions:\n\n      addpref  getpref  ispref  rmpref  setpref\n\n ** The following Matlab-compatible handle graphics functions have been\n    added:\n\n      guidata         uipanel        uitoolbar\n      guihandles      uipushtool     uiwait\n      uicontextmenu   uiresume       waitfor\n      uicontrol       uitoggletool\n\n    The uiXXX functions above are experimental.\n\n    Except for uiwait and uiresume, the uiXXX functions are not\n    supported with the FLTK+OpenGL graphics toolkit.\n\n    The gnuplot graphics toolkit does not support any of the uiXXX\n    functions nor the waitfor function.\n\n ** New keyword parfor (parallel for loop) is now recognized as a valid\n    keyword.  Implementation, however, is still mapped to an ordinary\n    for loop.\n\n ** Other new functions added in 3.6.0:\n\n      bicg                       nthargout                   usejava\n      is_dq_string               narginchk                   waitbar\n      is_sq_string               python                      zscore\n      is_function_handle         register_graphics_toolkit\n      loaded_graphics_toolkits   recycle\n\n ** Deprecated functions.\n\n    The following functions were deprecated in Octave 3.2 and have been\n    removed from Octave 3.6.\n\n      create_set          spcholinv    splu\n      dmult               spcumprod    spmax\n      iscommand           spcumsum     spmin\n      israwcommand        spdet        spprod\n      lchol               spdiag       spqr\n      loadimage           spfind       spsum\n      mark_as_command     sphcat       spsumsq\n      mark_as_rawcommand  spinv        spvcat\n      spatan2             spkron       str2mat\n      spchol              splchol      unmark_command\n      spchol2inv          split        unmark_rawcommand\n\n    The following functions have been deprecated in Octave 3.6 and will\n    be removed from Octave 3.10 (or whatever version is the second major\n    release after 3.6):\n\n      cut                polyderiv\n      cor                shell_cmd\n      corrcoef           studentize\n      __error_text__     sylvester_matrix\n      error_text\n\n ** The following functions have been modified for Matlab compatibility:\n\n      randperm\n\nSummary of important user-visible changes for version 3.4.3 (2011-10-10):\n------------------------------------------------------------------------\n\n ** Octave 3.4.3 is a bug fixing release.\n\nSummary of important user-visible changes for version 3.4.2 (2011-06-24):\n------------------------------------------------------------------------\n\n ** Octave 3.4.2 fixes some minor installation problems that affected\n    version 3.4.1.\n\nSummary of important user-visible changes for version 3.4.1 (2011-06-15):\n------------------------------------------------------------------------\n\n ** Octave 3.4.1 is primarily a bug fixing release.\n\n ** IMPORTANT note about binary incompatibility in this release:\n\n    Binary compatibility for all 3.4.x releases was originally planned,\n    but this is impossible for the 3.4.1 release due to a bug in the way\n    shared libraries were built in Octave 3.4.0.  Because of this bug,\n    .oct files built for Octave 3.4.0 must be recompiled before they\n    will work with Octave 3.4.1.\n\n    Given that there would be binary incompatibilities with shared\n    libraries going from Octave 3.4.0 to 3.4.1, the following\n    incompatible changes were also made in this release:\n\n      * The Perl Compatible Regular Expression (PCRE) library is now\n        required to build Octave.\n\n      * Octave's libraries and .oct files are now installed in\n        subdirectories of $libdir instead of $libexecdir.\n\n    Any future Octave 3.4.x release versions should remain binary\n    compatible with Octave 3.4.1 as proper library versioning is now\n    being used as recommended by the libtool manual.\n\n ** The following functions have been deprecated in Octave 3.4.1 and will\n    be removed from Octave 3.8 (or whatever version is the second major\n    release after 3.4):\n\n      cquad  is_duplicate_entry  perror  strerror\n\n ** The following functions are new in 3.4.1:\n\n      colstyle  gmres  iscolumn  isrow  mgorth  nproc  rectangle\n\n ** The get_forge_pkg function is now private.\n\n ** The rectangle_lw, rectangle_sw, triangle_lw, and triangle_sw\n    functions are now private.\n\n ** The logistic_regression_derivatives and logistic_regression_likelihood\n    functions are now private.\n\n ** ChangeLog files in the Octave sources are no longer maintained\n    by hand.  Instead, there is a single ChangeLog file generated from\n    the Mercurial version control commit messages.  Older ChangeLog\n    information can be found in the etc/OLD-ChangeLogs directory in the\n    source distribution.\n\nSummary of important user-visible changes for version 3.4 (2011-02-08):\n----------------------------------------------------------------------\n\n ** BLAS and LAPACK libraries are now required to build Octave.  The\n    subset of the reference BLAS and LAPACK libraries has been removed\n    from the Octave sources.\n\n ** The ARPACK library is now distributed with Octave so it no longer\n    needs to be available as an external dependency when building\n    Octave.\n\n ** The `lookup' function was extended to be more useful for\n    general-purpose binary searching.  Using this improvement, the\n    ismember function was rewritten for significantly better\n    performance.\n\n ** Real, integer and logical matrices, when used in indexing, will now\n    cache the internal index_vector value (zero-based indices) when\n    successfully used as indices, eliminating the conversion penalty for\n    subsequent indexing by the same matrix.  In particular, this means it\n    is no longer needed to avoid repeated indexing by logical arrays\n    using find for performance reasons.\n\n ** Logical matrices are now treated more efficiently when used as\n    indices.  Octave will keep the index as a logical mask unless the\n    ratio of true elements is small enough, using a specialized\n    code.  Previously, all logical matrices were always first converted\n    to index vectors.  This results in savings in both memory and\n    computing time.\n\n ** The `sub2ind' and `ind2sub' functions were reimplemented as compiled\n    functions for better performance.  These functions are now faster,\n    can deliver more economized results for ranges, and can reuse the\n    index cache mechanism described in previous paragraph.\n\n ** The built-in function equivalents to associative operators (`plus',\n    `times', `mtimes', `and', and `or') have been extended to accept\n    multiple arguments.  This is especially useful for summing\n    (multiplying, etc.) lists of objects (of possibly distinct types):\n\n      matrix_sum = plus (matrix_list{:});\n\n ** An FTP object type based on libcurl has been implemented.  These\n    objects allow ftp connections, downloads and uploads to be\n    managed.  For example,\n\n      fp = ftp (\"ftp.octave.org);\n      cd (fp, \"gnu/octave\");\n      mget (fp, \"octave-3.2.3.tar.bz2\");\n      close (fp);\n\n ** The default behavior of `assert (observed, expected)' has been\n    relaxed to employ less strict checking that does not require the\n    internals of the values to match.  This avoids previously valid\n    tests from breaking due to new internal classes introduced in future\n    Octave versions.\n\n    For instance, all of these assertions were true in Octave 3.0.x\n    but false in 3.2.x due to new optimizations and improvements:\n\n      assert (2*linspace (1, 5, 5), 2*(1:5))\n      assert (zeros (0, 0), [])\n      assert (2*ones (1, 5), (2) (ones (1,5)))\n\n ** The behavior of library functions `ismatrix', `issquare', and\n    `issymmetric' has been changed for better consistency.\n\n    * The `ismatrix' function now returns true for all numeric,\n      logical and character 2-D or N-D matrices.  Previously, `ismatrix'\n      returned false if the first or second dimension was zero.\n      Hence, `ismatrix ([])' was false,\n      while `ismatrix (zeros (1,2,0))' was true.\n\n    * The `issquare' function now returns a logical scalar, and is\n      equivalent to the expression\n\n        ismatrix (x) && ndims (x) == 2 && rows (x) == columns (x)\n\n      The dimension is no longer returned.  As a result, `issquare ([])'\n      now yields true.\n\n    * The `issymmetric' function now checks for symmetry instead of\n      Hermitianness.  For the latter, ishermitian was created.  Also,\n      logical scalar is returned rather than the dimension, so\n      `issymmetric ([])' is now true.\n\n ** Function handles are now aware of overloaded functions.  If a\n    function is overloaded, the handle determines at the time of its\n    reference which function to call.  A non-overloaded version does not\n    need to exist.\n\n ** Overloading functions for built-in classes (double, int8, cell,\n    etc.) is now compatible with Matlab.\n\n ** Function handles can now be compared with the == and != operators,\n    as well as the `isequal' function.\n\n ** Performance of concatenation (using []) and the functions `cat',\n    `horzcat', and `vertcat' has been improved for multidimensional\n    arrays.\n\n ** The operation-assignment operators +=, -=, *= and /= now behave more\n    efficiently in certain cases.  For instance, if M is a matrix and S a\n    scalar, then the statement\n\n      M += S;\n\n    will operate on M's data in-place if it is not shared by another\n    variable, usually increasing both time and memory efficiency.\n\n    Only selected common combinations are affected, namely:\n\n      matrix += matrix\n      matrix -= matrix\n      matrix .*= matrix\n      matrix ./= matrix\n\n      matrix += scalar\n      matrix -= scalar\n      matrix *= scalar\n      matrix /= scalar\n\n      logical matrix |= logical matrix\n      logical matrix &= logical matrix\n\n    where matrix and scalar belong to the same class.  The left-hand\n    side must be a simple variable reference.\n\n    Moreover, when unary operators occur in expressions, Octave will\n    also try to do the operation in-place if it's argument is a\n    temporary expression.\n\n ** The effect of comparison operators (<, >, <=, and >=) applied to\n    complex numbers has changed to be consistent with the strict\n    ordering defined by the `max', `min', and `sort' functions.  More\n    specifically, complex numbers are compared by lexicographical\n    comparison of the pairs `[abs(z), arg(z)]'.  Previously, only real\n    parts were compared; this can be trivially achieved by converting\n    the operands to real values with the `real' function.\n\n ** The automatic simplification of complex computation results has\n    changed.  Octave will now simplify any complex number with a zero\n    imaginary part or any complex matrix with all elements having zero\n    imaginary part to a real value.  Previously, this was done only for\n    positive zeros.  Note that the behavior of the complex function is\n    unchanged and it still produces a complex value even if the\n    imaginary part is zero.\n\n ** As a side effect of code refactoring in liboctave, the binary\n    logical operations are now more easily amenable to compiler\n    optimizations and are thus significantly faster.\n\n ** Octave now allows user-defined `subsasgn' methods to optimize out\n    redundant copies.  For more information, see the manual.\n\n ** More efficient matrix division handling.  Octave is now able to\n    handle the expressions\n\n      M' \\ V\n      M.' \\ V\n      V / M\n\n    (M is a matrix and V is a vector) more efficiently in certain cases.\n    In particular, if M is triangular, all three expressions will be\n    handled by a single call to xTRTRS (from LAPACK), with appropriate\n    flags.  Previously, all three expressions required a physical\n    transpose of M.\n\n ** More efficient handling of certain mixed real-complex matrix\n    operations.  For instance, if RM is a real matrix and CM a complex\n    matrix,\n\n      RM * CM\n\n    can now be evaluated either as\n\n      complex (RM * real (CM), RM * imag (CM))\n\n    or as\n\n      complex (RM) * CM,\n\n    depending on the dimensions.  The first form requires more\n    temporaries and copying, but halves the FLOP count, which normally\n    brings better performance if RM has enough rows.  Previously, the\n    second form was always used.\n\n    Matrix division is similarly affected.\n\n ** More efficient handling of triangular matrix factors returned from\n    factorizations.  The functions for computing QR, LU and Cholesky\n    factorizations will now automatically return the triangular matrix\n    factors with proper internal matrix_type set, so that it won't need\n    to be computed when the matrix is used for division.\n\n ** The built-in `sum' function now handles the non-native summation\n    (i.e., double precision sum of single or integer inputs) more\n    efficiently, avoiding a temporary conversion of the whole input\n    array to doubles.  Further, `sum' can now accept an extra option\n    argument, using a compensated summation algorithm rather than a\n    straightforward sum, which significantly improves precision if lots\n    of cancellation occurs in the summation.\n\n ** The built-in `bsxfun' function now uses optimized code for certain\n    cases where built-in operator handles are passed in.  Namely, the\n    optimizations concern the operators `plus', `minus', `times',\n    `ldivide', `rdivide', `power', `and', `or' (for logical arrays),\n    the relational operators `eq', `ne', `lt', `le', `gt', `ge', and the\n    functions `min' and `max'.  Optimizations only apply when both\n    operands are of the same built-in class.  Mixed real/complex and\n    single/double operations will first convert both operands to a\n    common type.\n\n ** The `strfind' and `strrep' functions now have compiled\n    implementations, facilitating significantly more efficient searching\n    and replacing in strings, especially with longer patterns.  The code\n    of `strcat' has been vectorized and is now much more efficient when\n    many strings are concatenated.  The `strcmpi' and `strncmpi'\n    functions are now built-in functions, providing better performance.\n\n ** 'str2double' now has a compiled implementation and the API conforms\n    to Matlab.  The additional Octave-specific features of returning a\n    boolean matrix indicating which elements were successfully converted\n    has been removed.\n\n ** Matlab-style ignoring input and output function arguments using\n    tilde (~) is now supported.  Ignored output arguments may be\n    detected from a function using the built-in function `isargout'.\n    For more details, consult the manual.\n\n ** The list datatype, deprecated since the introduction of cells, has\n    been removed.\n\n ** The accumarray function has been optimized and is now significantly\n    faster in certain important cases.\n\n ** The behavior of isreal and isnumeric functions was changed to be more\n    Matlab-compatible.\n\n ** The integer math & conversion warnings (Octave:int-convert-nan,\n    Octave:int-convert-non-int-val, Octave:int-convert-overflow,\n    Octave:int-math-overflow) have been removed.\n\n ** rem and mod are now built-in functions.  They also handle integer\n    types efficiently using integer arithmetic.\n\n ** Sparse indexing and indexed assignment has been mostly rewritten.\n    Since Octave uses compressed column storage for sparse matrices,\n    major attention is devoted to operations manipulating whole columns.\n    Such operations are now significantly faster, as well as some other\n    important cases.\n\n    Further, it is now possible to pre-allocate a sparse matrix and\n    subsequently fill it by assignments, provided they meet certain\n    conditions.  For more information, consult the `spalloc' function,\n    which is no longer a mere dummy.  Consequently, nzmax and nnz are no\n    longer always equal in Octave.  Octave may also produce a matrix\n    with nnz < nzmax as a result of other operations, so you should\n    consistently use nnz unless you really want to use nzmax (i.e., the\n    space allocated for nonzero elements).\n\n    Sparse concatenation is also affected, and concatenating sparse\n    matrices, especially larger collections, is now significantly more\n    efficient.  This applies to both the [] operator and the\n    cat/vertcat/horzcat functions.\n\n ** It is now possible to optionally employ the xGESDD LAPACK drivers\n    for computing the singular value decomposition using svd, instead\n    of the default xGESVD, using the configuration pseudo-variable\n    svd_driver.  The xGESDD driver can be up to 6x times faster when\n    singular vectors are requested, but is reported to be somewhat less\n    robust on highly ill-conditioned matrices.\n\n ** Configuration pseudo-variables, such as page_screen_output or\n    confirm_recursive_rmdir (or the above mentioned svd_driver), now\n    accept a \"local\" option as second argument, requesting the change\n    to be undone when the current function returns:\n\n    function [status, msg] = rm_rf (dir)\n      confirm_recursive_rmdir (false, \"local\");\n      [status, msg] = rmdir (dir, \"s\");\n      ...\n    endfunction\n\n    Upon return, confirm_recursive_rmdir will be restored to the value\n    it had on entry to the function, even if there were subsequent\n    changes to the variable in function rm_rf or any of the functions\n    it calls.\n\n ** pkg now accepts a -forge option for downloading and installing\n    packages from Octave Forge automatically.  For example,\n\n      pkg install -forge general\n\n    will automatically download the latest release of the general\n    package and attempt to install it.  No automatic resolving of\n    dependencies is provided.  Further,\n\n      pkg list -forge\n\n    can be used to list all available packages.\n\n ** The internal data representation of structs has been completely\n    rewritten to make certain optimizations feasible.  The field data\n    can now be shared between structs with equal keys but different\n    dimensions or values, making operations that preserve the fields\n    faster.  Economized storage is now used for scalar structs (just\n    like most other scalars), making their usage more\n    memory-efficient.  Certain array-like operations on structs\n    (concatenation, uniform cellfun, num2cell) have gained a\n    significant speed-up.  Additionally, the octave_scalar_map class\n    now provides a simpler interface to work with scalar structs within\n    a C++ DLD function.\n\n ** Two new formats are available for displaying numbers:\n\n      format short eng\n      format long eng\n\n    Both display numbers in engineering notation, i.e., mantissa +\n    exponent where the exponent is a multiple of 3.\n\n ** The following functions are new in Octave 3.4:\n      accumdim    erfcx        nfields      pqpnonneg  uigetdir\n      bitpack     fileread     nth_element  quadcc     uigetfile\n      bitunpack   fminbnd      onCleanup    randi      uiputfile\n      blkmm       fskipl       pbaspect     repelems   uimenu\n      cbrt        ifelse       pie3         reset      whitebg\n      curl        ishermitian  powerset     rsf2csf\n      chop        isindex      ppder        saveas\n      daspect     luupdate     ppint        strread\n      divergence  merge        ppjumps      textread\n\n ** Using the image function to view images with external programs such\n    as display, xv, and xloadimage is no longer supported.  The\n    image_viewer function has also been removed.\n\n ** The behavior of struct assignments to non-struct values has been\n    changed.  Previously, it was possible to overwrite an arbitrary\n    value:\n\n      a = 1;\n      a.x = 2;\n\n    This is no longer possible unless a is an empty matrix or cell\n    array.\n\n ** The dlmread function has been extended to allow specifying a custom\n    value for empty fields.\n\n ** The dlmread and dlmwrite functions have been modified to accept\n    file IDs (as returned by fopen) in addition to file names.\n\n ** Octave can now optimize away the interpreter overhead of an\n    anonymous function handle, if the function simply calls another\n    function or handle with some of its parameters bound to certain\n    values.  Example:\n\n      f = @(x) sum (x, 1);\n\n    When f is called, the call is forwarded to @sum with the constant 1\n    appended, and the anonymous function call does not occur on the\n    call stack.\n\n ** For compatibility with Matlab, mu2lin (x) is now equivalent to\n    mu2lin (x, 0).\n\n ** The new function `history_control' may be used to control the way\n    command lines are added to the history list when Octave is using\n    readline for command-line editing.  For example\n\n      history_control (\"ignoredups\")\n\n    tells Octave to avoid adding duplicate lines to the history list.\n\n ** Octave now uses the gnulib library for improved portability and to\n    avoid bugs in operating system functions.\n\n ** Deprecated functions.\n\n    The following functions were deprecated in Octave 3.0 and have been\n    removed from Octave 3.4.\n\n      beta_cdf         geometric_pdf        pascal_pdf\n      beta_inv         geometric_rnd        pascal_rnd\n      beta_pdf         hypergeometric_cdf   poisson_cdf\n      beta_rnd         hypergeometric_inv   poisson_inv\n      binomial_cdf     hypergeometric_pdf   poisson_pdf\n      binomial_inv     hypergeometric_rnd   poisson_rnd\n      binomial_pdf     intersection         polyinteg\n      binomial_rnd     is_bool              setstr\n      chisquare_cdf    is_complex           struct_contains\n      chisquare_inv    is_list              struct_elements\n      chisquare_pdf    is_matrix            t_cdf\n      chisquare_rnd    is_scalar            t_inv\n      clearplot        is_square            t_pdf\n      clg              is_stream            t_rnd\n      com2str          is_struct            uniform_cdf\n      exponential_cdf  is_symmetric         uniform_inv\n      exponential_inv  is_vector            uniform_pdf\n      exponential_pdf  isstr                uniform_rnd\n      exponential_rnd  lognormal_cdf        weibcdf\n      f_cdf            lognormal_inv        weibinv\n      f_inv            lognormal_pdf        weibpdf\n      f_pdf            lognormal_rnd        weibrnd\n      f_rnd            meshdom              weibull_cdf\n      gamma_cdf        normal_cdf           weibull_inv\n      gamma_inv        normal_inv           weibull_pdf\n      gamma_pdf        normal_pdf           weibull_rnd\n      gamma_rnd        normal_rnd           wiener_rnd\n      geometric_cdf    pascal_cdf\n      geometric_inv    pascal_inv\n\n    The following functions were deprecated in Octave 3.2 and will\n    be removed from Octave 3.6 (or whatever version is the second major\n    release after 3.2):\n\n      create_set          spcholinv    splu\n      dmult               spcumprod    spmax\n      iscommand           spcumsum     spmin\n      israwcommand        spdet        spprod\n      lchol               spdiag       spqr\n      loadimage           spfind       spsum\n      mark_as_command     sphcat       spsumsq\n      mark_as_rawcommand  spinv        spvcat\n      spatan2             spkron       str2mat\n      spchol              splchol      unmark_command\n      spchol2inv          split        unmark_rawcommand\n\n    The following functions have been deprecated in Octave 3.4 and will\n    be removed from Octave 3.8 (or whatever version is the second major\n    release after 3.4):\n\n      autocor  cellidx   gammai     is_global  replot     values\n      autocov  dispatch  glpkmex    krylovb    saveimage\n      betai    fstat     intwarning perror     strerror\n\nSummary of important user-visible changes for version 3.2 (2009-06-05):\n----------------------------------------------------------------------\n\n ** Compatibility with Matlab graphics has been improved.\n\n    The hggroup object and associated listener callback functions have\n    been added allowing the inclusion of group objects.  Data sources\n    have been added to these group objects such that\n\n           x = 0:0.1:10;\n           y = sin (x);\n           plot (x, y, \"ydatasource\", \"y\");\n           for i = 1 : 100\n             pause(0.1)\n             y = sin (x + 0.1 * i);\n             refreshdata ();\n           endfor\n\n    works as expected.  This capability has be used to introduce\n    stem-series, bar-series, etc., objects for better Matlab\n    compatibility.\n\n ** New graphics functions:\n\n      addlistener                  ezcontour   gcbo         refresh\n      addproperty                  ezcontourf  ginput       refreshdata\n      allchild                     ezmesh      gtext        specular\n      available_graphics_toolkits  ezmeshc     intwarning   surfl\n      graphics_toolkit             ezplot      ishghandle   trisurf\n      cla                          ezplot3     isocolors    waitforbuttonpress\n      clabel                       ezpolar     isonormals\n      comet                        ezsurf      isosurface\n      dellistener                  findall     linkprop\n      diffuse                      gcbf        plotmatrix\n\n ** New experimental OpenGL/FLTK based plotting system.\n\n    An experimental plotting system based on OpenGL and the FLTK\n    toolkit is now part of Octave.  This graphics toolkit is disabled by\n    default.  You can switch to using it with the command\n\n        graphics_toolkit (\"fltk\")\n\n    for all future figures or for a particular figure with the command\n\n        graphics_toolkit (h, \"fltk\")\n\n    where \"h\" is a valid figure handle.\n\n ** Functions providing direct access to gnuplot have been removed.\n\n    The functions __gnuplot_plot__, __gnuplot_set__, __gnuplot_raw__,\n     __gnuplot_show__, __gnuplot_replot__, __gnuplot_splot__,\n     __gnuplot_save_data__ and __gnuplot_send_inline_data__ have been\n     removed from Octave.  These function were incompatible with the\n     high level graphics handle code.\n\n ** The Control, Finance and Quaternion functions have been removed.\n\n    These functions are now available as separate packages from\n\n      http://octave.sourceforge.net/packages.html\n\n    and can be reinstalled using the Octave package manager (see\n    the pkg function).\n\n ** Specific sparse matrix functions removed.\n\n    The following functions, which handled only sparse matrices have\n    been removed.  Instead of calling these functions directly, you\n    should use the corresponding function without the \"sp\" prefix.\n\n      spatan2     spcumsum  spkron   spprod\n      spchol      spdet     splchol  spqr\n      spchol2inv  spdiag    splu     spsum\n      spcholinv   spfind    spmax    spsumsqk\n      spcumprod   spinv     spmin\n\n ** Improvements to the debugger.\n\n    The interactive debugging features have been improved.  Stopping\n    on statements with dbstop should work correctly now.  Stepping\n    into and over functions, and stepping one statement at a time\n    (with dbstep) now works.  Moving up and down the call stack with\n    dbup and dbdown now works.  The dbstack function is now available\n    to print the current function call stack.  The new dbquit function\n    is available to exit the debugging mode.\n\n ** Improved traceback error messages.\n\n    Traceback error messages are much more concise and easier to\n    understand.  They now display information about the function call\n    stack instead of the stack of all statements that were active at\n    the point of the error.\n\n ** Object Oriented Programming.\n\n    Octave now includes OOP features and the user can create their own\n    class objects and overloaded functions and operators.  For\n    example, all methods of a class called \"myclass\" will be found in\n    a directory \"@myclass\" on the users path.  The class specific\n    versions of functions and operators take precedence over the\n    generic versions of these functions.\n\n    New functions related to OOP include\n\n      class  inferiorto  isobject  loadobj  methods  superiorto\n\n    See the Octave manual for more details.\n\n ** Parsing of Command-style Functions.\n\n    Octave now parses command-style functions without needing to first\n    declare them with \"mark_as_command\".  The rules for recognizing a\n    command-style function calls are\n\n      * A command must appear as the first word in a statement,\n        followed by a space.\n\n      * The first character after the space must not be '=' or '('\n\n      * The next token after the space must not look like a binary\n        operator.\n\n    These rules should be mostly compatible with the way Matlab parses\n    command-style function calls and allow users to define commands in\n    .m files without having to mark them as commands.\n\n    Note that previous versions of Octave allowed expressions like\n\n      x = load -text foo.dat\n\n    but an expression like this will now generate a parse error.  In\n    order to assign the value returned by a function to a variable,\n    you must use the normal function call syntax:\n\n      x = load (\"-text\", \"foo.dat\");\n\n ** Block comments.\n\n    Commented code can be between matching \"#{\" and \"#}\" or \"%{\" and\n    \"%}\" markers, even if the commented code spans several line.  This\n    allows blocks code to be commented, without needing to comment\n    each line.  For example,\n\n    function [s, t] = func (x, y)\n      s = 2 * x;\n    #{\n      s *= y;\n      t = y + x;\n    #}\n    endfunction\n\n    the lines \"s *= y;\" and \"t = y + x\" will not be executed.\n\n ** If any subfunction in a file ends with \"end\" or \"endfunction\", then\n    they all must end that way.  Previously, Octave accepted\n\n      function main ()\n        ...\n      # no endfunction here.\n      function sub ()\n        ...\n      endfunction\n\n    but this is no longer allowed.\n\n ** Special treatment in the parser of expressions like \"a' * b\".\n\n    In these cases the transpose is no longer explicitly formed and\n    BLAS libraries are called with the transpose flagged,\n    significantly improving performance for these kinds of\n    operations.\n\n ** Single Precision data type.\n\n    Octave now includes a single precision data type.  Single\n    precision variables can be created with the \"single\" command, or\n    from functions like ones, eye, etc.  For example,\n\n      single (1)\n      ones (2, 2, \"single\")\n      zeros (2, 2, \"single\")\n      eye (2, 2, \"single\")\n      Inf (2, 2, \"single\")\n      NaN (2, 2, \"single\")\n      NA (2, 2, \"single\")\n\n    all create single precision variables.  For compatibility with\n    Matlab, mixed double/single precision operators and functions\n    return single precision types.\n\n    As a consequence of this addition to Octave the internal\n    representation of the double precision NA value has changed, and\n    so users that make use of data generated by Octave with R or\n    visa-versa are warned that compatibility might not be assured.\n\n ** Improved array indexing.\n\n    The underlying code used for indexing of arrays has been\n    completely rewritten and indexing is now significantly faster.\n\n ** Improved memory management.\n\n    Octave will now attempt to share data in some cases where previously\n    a copy would be made, such as certain array slicing operations or\n    conversions between cells, structs and cs-lists.  This usually reduces\n    both time and memory consumption.\n    Also, Octave will now attempt to detect and optimize usage of a vector\n    as a stack, when elements are being repeatedly inserted at/removed from\n    the end of the vector.\n\n ** Improved performance for reduction operations.\n\n    The performance of the sum, prod, sumsq, cumsum, cumprod, any, all,\n    max and min functions has been significantly improved.\n\n ** Sorting and searching.\n\n    The performance of sort has been improved, especially when sorting\n    indices are requested.  An efficient built-in issorted\n    implementation was added.  The sortrows function now uses a more\n    efficient algorithm, especially in the homogeneous case.  The lookup\n    function is now a built-in function performing a binary search,\n    optimized for long runs of close elements.  Lookup also works with\n    cell arrays of strings.\n\n ** Range arithmetics\n\n    For some operations on ranges, Octave will attempt to keep the\n    result as a range.  These include negation, adding a scalar,\n    subtracting a scalar, and multiplying by a scalar.  Ranges with zero\n    increment are allowed and can be constructed using the built-in\n    function `ones'.\n\n ** Various performance improvements.\n\n    Performance of a number of other built-in operations and functions\n    was improved, including:\n\n    * logical operations\n    * comparison operators\n    * element-wise power\n    * accumarray\n    * cellfun\n    * isnan\n    * isinf\n    * isfinite\n    * nchoosek\n    * repmat\n    * strcmp\n\n ** 64-bit integer arithmetic.\n\n    Arithmetic with 64-bit integers (int64 and uint64 types) is fully\n    supported, with saturation semantics like the other integer types.\n    Performance of most integer arithmetic operations has been\n    improved by using integer arithmetic directly.  Previously, Octave\n    performed integer math with saturation semantics by converting the\n    operands to double precision, performing the operation, and then\n    converting the result back to an integer value, truncating if\n    necessary.\n\n ** Diagonal and permutation matrices.\n\n    The interpreter can now treat diagonal and permutation matrices as\n    special objects that store only the non-zero elements, rather than\n    general full matrices.  Therefore, it is now possible to construct\n    and use these matrices in linear algebra without suffering a\n    performance penalty due to storing large numbers of zero elements.\n\n ** Improvements to fsolve.\n\n    The fsolve function now accepts an option structure argument (see\n    also the optimset function).  The INFO values returned from fsolve\n    have changed to be compatible with Matlab's fsolve function.\n    Additionally, fsolve is now able to solve overdetermined systems,\n    complex-differentiable complex systems, systems with a sparse\n    jacobian and can work in single precision if given single precision\n    inputs.  It can also be called recursively.\n\n ** Improvements to the norm function.\n\n    The norm function is now able to compute row or column norms of a\n    matrix in a single call, as well as general matrix p-norms.\n\n ** New functions for computing some eigenvalues or singular values.\n\n    The eigs and svds functions have been included in Octave.  These\n    functions require the ARPACK library (now distributed under a\n    GPL-compatible license).\n\n ** New QR and Cholesky factorization updating functions.\n\n      choldelete  cholshift   qrdelete  qrshift\n      cholinsert  cholupdate  qrinsert  qrupdate\n\n ** New quadrature functions.\n\n      dblquad  quadgk  quadv  triplequad\n\n ** New functions for reading and writing images.\n\n    The imwrite and imread functions have been included in Octave.\n    These functions require the GraphicsMagick library.  The new\n    function imfinfo provides information about an image file (size,\n    type, colors, etc.)\n\n ** The input_event_hook function has been replaced by the pair of\n    functions add_input_event_hook and remove_input_event_hook so that\n    more than one hook function may be installed at a time.\n\n ** Other miscellaneous new functions.\n\n      addtodate          hypot                       reallog\n      bicgstab           idivide                     realpow\n      cellslices         info                        realsqrt\n      cgs                interp1q                    rectint\n      command_line_path  isdebugmode                 regexptranslate\n      contrast           isfloat                     restoredefaultpath\n      convn              isstrprop                   roundb\n      cummin             log1p                       rundemos\n      cummax             lsqnonneg                   runlength\n      datetick           matlabroot                  saveobj\n      display            namelengthmax               spaugment\n      expm1              nargoutchk                  strchr\n      filemarker         pathdef                     strvcat\n      fstat              perl                        subspace\n      full               prctile                     symvar\n      fzero              quantile                    treelayout\n      genvarname         re_read_readline_init_file  validatestring\n      histc\n\n ** Changes to strcat.\n\n    The strcat function is now compatible with Matlab's strcat\n    function, which removes trailing whitespace when concatenating\n    character strings.  For example\n\n      strcat ('foo ', 'bar')\n      ==> 'foobar'\n\n    The new function cstrcat provides the previous behavior of\n    Octave's strcat.\n\n ** Improvements to the help functions.\n\n    The help system has been mostly re-implemented in .m files to make\n    it easier to modify.  Performance of the lookfor function has been\n    greatly improved by caching the help text from all functions that\n    are distributed with Octave.  The pkg function has been modified\n    to generate cache files for external packages when they are\n    installed.\n\n ** Deprecated functions.\n\n    The following functions were deprecated in Octave 3.0 and will be\n    removed from Octave 3.4 (or whatever version is the second major\n    release after 3.0):\n\n      beta_cdf         geometric_pdf       pascal_pdf\n      beta_inv         geometric_rnd       pascal_rnd\n      beta_pdf         hypergeometric_cdf  poisson_cdf\n      beta_rnd         hypergeometric_inv  poisson_inv\n      binomial_cdf     hypergeometric_pdf  poisson_pdf\n      binomial_inv     hypergeometric_rnd  poisson_rnd\n      binomial_pdf     intersection        polyinteg\n      binomial_rnd     is_bool             setstr\n      chisquare_cdf    is_complex          struct_contains\n      chisquare_inv    is_list             struct_elements\n      chisquare_pdf    is_matrix           t_cdf\n      chisquare_rnd    is_scalar           t_inv\n      clearplot        is_square           t_pdf\n      clg              is_stream           t_rnd\n      com2str          is_struct           uniform_cdf\n      exponential_cdf  is_symmetric        uniform_inv\n      exponential_inv  is_vector           uniform_pdf\n      exponential_pdf  isstr               uniform_rnd\n      exponential_rnd  lognormal_cdf       weibcdf\n      f_cdf            lognormal_inv       weibinv\n      f_inv            lognormal_pdf       weibpdf\n      f_pdf            lognormal_rnd       weibrnd\n      f_rnd            meshdom             weibull_cdf\n      gamma_cdf        normal_cdf          weibull_inv\n      gamma_inv        normal_inv          weibull_pdf\n      gamma_pdf        normal_pdf          weibull_rnd\n      gamma_rnd        normal_rnd          wiener_rnd\n      geometric_cdf    pascal_cdf\n      geometric_inv    pascal_inv\n\n    The following functions are now deprecated in Octave 3.2 and will\n    be removed from Octave 3.6 (or whatever version is the second major\n    release after 3.2):\n\n      create_set          spcholinv  spmax\n      dmult               spcumprod  spmin\n      iscommand           spcumsum   spprod\n      israwcommand        spdet      spqr\n      lchol               spdiag     spsum\n      loadimage           spfind     spsumsq\n      mark_as_command     spinv      str2mat\n      mark_as_rawcommand  spkron     unmark_command\n      spatan2             splchol    unmark_rawcommand\n      spchol              split\n      spchol2inv          splu\n\nSummary of important user-visible changes for version 3.0 (2007-12-21):\n----------------------------------------------------------------------\n\n ** Compatibility with Matlab graphics is much better now.  We now\n    have some graphics features that work like Matlab's Handle\n    Graphics (tm):\n\n    + You can make a subplot and then use the print function to\n      generate a file with the plot.\n\n    + RGB line colors are supported if you use gnuplot 4.2.  Octave\n      can still use gnuplot 4.0, but there is no way to set arbitrary\n      line colors with it when using the Matlab-style plot functions.\n      There never was any way to do this reliably with older versions\n      of gnuplot (whether run from Octave or not) since it only\n      provided a limited set to choose from, and they were terminal\n      dependent, so choosing color 1 with the X11 terminal would be\n      different from color 1 with the PostScript terminal.  Valid RGB\n      colors for gnuplot 4.0 are the eight possible combinations of 0\n      and 1 for the R, G and B values. Invalid values are all mapped\n      to the same color.\n\n      This also affects patch objects used in the bar, contour, meshc\n      and surfc functions, where the bars and contours will be\n      monochrome. A workaround for this is to type \"colormap gmap40\"\n      that loads a colormap that in many cases will be adequate for\n      simple bar and contour plots.\n\n    + You can control the width of lines using (for example):\n\n        line (x, y, \"linewidth\", 4, \"color\", [1, 0, 0.5]);\n\n      (this also shows the color feature).\n\n    + With gnuplot 4.2, image data is plotted with gnuplot and may be\n      combined with other 2-d plot data.\n\n    + Lines for contour plots are generated with an Octave function, so\n      contour plots are now 2-d plots instead of special 3-d plots, and\n      this allows you to plot additional 2-d data on top of a contour\n      plot.\n\n    + With the gnuplot \"extended\" terminals the TeX interpreter is\n    emulated. However, this means that the TeX interpreter is only\n    supported on the postscript terminals with gnuplot 4.0. Under\n    gnuplot 4.2 the terminals aqua, dumb, png, jpeg, gif, pm, windows,\n    wxt, svg and x11 are supported as well.\n\n    + The following plot commands are now considered obsolete and will\n      be removed from a future version of Octave:\n\n        __gnuplot_set__\n        __gnuplot_show__\n        __gnuplot_plot__\n        __gnuplot_splot__\n        __gnuplot_replot__\n\n      Additionally, these functions no longer have any effect on plots\n      created with the Matlab-style plot commands (plot, line, mesh,\n      semilogx, etc.).\n\n    + Plot property values are not extensively checked.  Specifying\n      invalid property values may produce unpredictable results.\n\n    + Octave now sends data over the same pipe that is used to send\n      commands to gnuplot.  While this avoids the problem of\n      cluttering /tmp with data files, it is no longer possible to use\n      the mouse to zoom in on plots.  This is a limitation of gnuplot,\n      which is unable to zoom when the data it plots is not stored in\n      a file.  Some work has been done to fix this problem in newer\n      versions of gnuplot (> 4.2.2).  See for example, this thread\n\n        http://www.nabble.com/zooming-of-inline-data-tf4357017.html#a12416496\n\n      on the gnuplot development list.\n\n\n ** The way Octave handles search paths has changed.  Instead of\n    setting the built-in variable LOADPATH, you must use addpath,\n    rmpath, or path to manipulate the function search path.  These\n    functions will maintain \".\" at the head of the path, for\n    compatibility with Matlab.\n\n    Leading, trailing or doubled colons are no longer special.\n    Now, all elements of the search path are explicitly included in\n    the path when Octave starts.  To display the path, use the path\n    function.\n\n    Path elements that end in // are no longer searched recursively.\n    Instead, you may use addpath and the genpath function to add an\n    entire directory tree to the path.  For example,\n\n      addpath (genpath (\"~/octave\"));\n\n    will add ~/octave and all directories below it to the head of the\n    path.\n\n\n ** Previous versions of Octave had a number of built-in variables to\n    control warnings (for example, warn_divide_by_zero).  These\n    variables have been replaced by warning identifiers that are used\n    with the warning function to control the state of warnings.\n\n    For example, instead of writing\n\n      warn_divide_by_zero = false;\n\n    to disable divide-by-zero warnings, you should write\n\n      warning (\"off\", \"Octave:divide-by-zero\");\n\n    You may use the same technique in your own code to control\n    warnings.  For example, you can use\n\n      warning (\"My-package:phase-of-the-moon\",\n               \"the phase of the moon could cause trouble today\");\n\n    to allow users to control this warning using the\n    \"My-package:phase-of-the-moon\" warning identifier.\n\n    You may also enable or disable all warnings, or turn them into\n    errors:\n\n      warning (\"on\", \"all\");\n      warning (\"off\", \"all\");\n      warning (\"error\", \"Octave:divide-by-zero\");\n      warning (\"error\", \"all\");\n\n    You can query the state of current warnings using\n\n      warning (\"query\", ID)\n      warning (\"query\")\n\n    (only those warning IDs which have been explicitly set are\n    returned).\n\n    A partial list and description of warning identifiers is available\n    using\n\n      help warning_ids\n\n\n ** All built-in variables have been converted to functions.  This\n    change simplifies the interpreter and allows a consistent\n    interface to internal variables for user-defined packages and the\n    core functions distributed with Octave.  In most cases, code that\n    simply accesses internal variables does not need to change.  Code\n    that sets internal variables will change.  For example, instead of\n    writing\n\n      PS1 = \">> \";\n\n    you will need to write\n\n      PS1 (\">> \");\n\n    If you need write code that will run in both old and new versions\n    of Octave, you can use something like\n\n      if (exist (\"OCTAVE_VERSION\") == 5)\n        ## New:\n        PS1 (\">> \");\n      else\n        ## Old:\n        PS1 = \">> \";\n      endif\n\n\n ** For compatibility with Matlab, the output order of Octave's\n    \"system\" function has changed from\n\n      [output, status] = system (cmd);\n\n    to\n\n      [status, output] = system (cmd);\n\n\n ** For compatibility with Matlab, the output of Octave's fsolve\n    function has been changed from\n\n      [x, info, msg] = fsolve (...);\n\n    to\n\n      [x, fval, info] = fsolve (...);\n\n\n ** For compatibility with Matlab, normcdf, norminv, normpdf, and\n    normrnd have been modified to compute distributions using the\n    standard deviation instead of the variance.\n\n\n ** For compatibility with Matlab, gamcdf, gaminv, gampdf, gamrnd,\n    expcdf, expinv, exppdf and exprnd have been modified to compute\n    the distributions using the standard scale factor rather than\n    one over the scale factor.\n\n---------------------------------------------------------\n\nSee NEWS.2 for old news.\n"
  },
  {
    "path": "etc/NEWS.4",
    "content": "Summary of bugs fixed for version 4.4.1 (2018-08-09):\n----------------------------------------------------\n\nUsing the bug numbers listed below, find bug reports on the web using\nthe URL https://savannah.gnu.org/bugs/?NNNNN\n\n ** disable compound binary operator optimization (bug #54465)\n\n ** Fix initial bracketing for fzero (bug #54445).\n\n ** Fix scrolling command window in Windows 10 (bug #52496).\n\n ** Produce a single backtrace for global declaration overriding local variable.\n\n ** revive setstr (bug #54417)\n\n ** ode15i.m: In tests, use unlikely symbol name instead of “foo”.\n\n ** run.m: In test, use a symbol name that is unlikely to be a function.\n\n ** avoid alignment warning on solaris systems (bug #54389)\n\n ** Improve error message if iconv is not available (bug #54384).\n\n ** avoid error in gnulib wrapper on systems that don’t have fpu control word\n\n ** avoid unused variable warning on some systems\n\n ** avoid fprintf format warning on some systems\n\n ** eliminate unnecessary sun-utils.h header file\n\n ** index.tst: Make tests case insensitive for NaN, NA, Inf values (bug #54385).\n\n ** positive value from uname can mean success (bug #54235)\n\n ** add some bug numbers to the test suite\n\n ** consider any non-zero return from uname to be failure (bug #54235)\n\n ** if freetype detection fails, unset FT2_* config variables (bug #54369)\n\n ** Produce same random number stream for \"state\" initialized to Inf (bug\n    #54342).\n\n ** avoid crash when loading classdef objects (bug #54319)\n\n ** hist.m: Don’t error out if called with identical Y values (bug #54326).\n\n ** Parse empty struct input correctly (bug #54318).\n\n ** Fix regression in 4.2.0 which disallowed printing with some Ghostscript\n    devices.\n\n ** transform libiconv.dll.a to -liconv for mkoctfile (bug #53920)\n\n ** trapz.m: Overhaul function to fix errors with different orientations of X\n    and Y (bug #54277).\n\n ** Write audio OGG files in smaller chunk sizes (bug #54280).\n\n ** Use LAPACK DTGSEN subrouting for ordered-qz computation (bug #53761)\n\n ** Fix blkmm to work with empty matrices (bug #54261).\n\n ** use octave bat file in pkg install configure/make when in windows (bug\n    #53938).\n\n ** repelem.m: Fix behavior when final repeat count is 0 (bug #54275).\n\n ** .hgsub: Use hg.octave.org instead of hg-new.octave.org\n\n ** move some fortran and dynamic linking configure checks to separate macros\n\n ** configure.ac: Reorder tests so that FPICFLAG is correctly set on Solaris\n    (bug #54235).\n\n ** eigs.m: Decrease opts.maxit in UnconvergedEigenvalues BIST (bug #54179).\n\n ** fix ambiguous overload build error on Solaris (bug #54217)\n\n ** pkg.m: Restore ability to use file glob patterns when specifying local pkg\n    files (bug #54224).\n\n ** Use %ld format code in xerbla printf (bug #54206).\n\n ** use int instead of size_t for xerbla string length (bug #54206)\n\n ** Pair fclose with all fopen and prevent file-io.cc test fails (bug #54180).\n\n ** fsolve.m: Return info=1 when initial guess x0 is correct (bug #53991).\n\n ** fsolve.m: Add BIST test for bug #53991.\n\n ** fsolve.m: exit with info=-2 when singularity reached (bug #53991).\n\n ** ensure that Make sees Octave exit status when running make check\n\n ** interpreter.cc (intialize_xerbla_error_handler, xerbla_abort): New\n    functions.\n\n ** improve warnings for global/local variable conflicts (bug #54052)\n\n ** maybe preserve local value when declaring variable global (bug #54052)\n\n ** fix regression in text (bug #54109)\n\n ** create valid tmp scope for who -file (bug #54030)\n\n ** polar.m: Correct axes limits when using negative rho values (bug #53999).\n\n ** text.m: Fix regression when ‘String’ property is specified (bug #54067).\n\n ** allow NULL mxArray* to be returned as undefined from fcn calls (bug #54096)\n\n ** treat NULL as [] for mxSetFieldByNumber and mxSetCell (bug #54096)\n\n ** Properly test Qt offscreen printing during manual figures generation.\n\n ** Avoid segfault with textscan (bug #53786).\n\n ** add Qt include needed to build against Qt 5.11 (bug #53978)\n\n ** make listing local functions for command completion work again (bug #53925)\n\n ** Stop segfault in debug mode with readline complete (bug #53925).\n\n ** Remove code to install default colors for qt toolkit from window theme (bug\n    #53805).\n\n ** back out changes attempting to automatically call handle class destructor\n\n ** residue.m: Use a pre-conditioner on final matrix division for numerical\n    stability (bug #53869)\n\n ** track multiple file types (oct|m|mex) for private functions (bug #53856)\n\n ** also preserve temporaries in indexing expressions (bug #53844)\n\n ** also update load-path info if private subdir time stamp changes (bug #53856)\n\n ** defer deletion of temporaries in argument lists (bug #53844)\n\n ** improve test for handle class destructor\n\n ** call delete method correctly for handle class objects (bug #53844)\n\n ** use size_t for f77 char arg length params with GCC 8 (bug #53872)\n\n ** Fix lrwork dimension in svd for complex cases (bug #53823).\n\n ** lines.m: Don’t open empty figure or axes if none already exist (bug #53648)\n\nDocumentation bugs fixed:\n\n ** doc: Add version number to top title of HTML manual for clarity.\n\n ** flip.m: Update docstring.\n\n ** setdiff.m: Fix typo in documentation (bug #54393).\n\n ** doc: Replace instances of realroot (non-existent) with realpow (bug #54336).\n\n ** HACKING.md: Update for recently removed files.\n\n ** remove unused qtinfo source files\n\n ** doc: Remove bad calling convention for warning with a mode struct (bug\n    #54288)\n\n ** Document work-around for disabling OpenGL software rendering (bug #53845).\n\n ** xpow.cc (err_nonsquare_matrix): Clarify error message (bug #54248).\n\n ** doc: Miscellaneous documentation fixes all over the manual (bug #54288).\n\n ** doc: small fixes to size and plot.txi (bug #54283).\n\n ** doc: Clarify description of Example 4 for size (bug #54283).\n\n ** doc: Fix malformed URL (bug #54225).\n\n ** Fix typo in error statement from containers.Map (bug #54103).\n\n ** doc: Use qcode macro to document fseek offsets (bug #51402).\n\n ** Use correct abbreviation UTC for Coordinated Universal Time (bug #53918).\n\n ** doc: Rewrite section on indexing for clarity (bug #53675).\n\n ** md5sum.m: Fix error in sample code (bug #53829).\n\nOther bugs fixed:\n\n ** gui: fix editor rendering on some displays, disable QScintilla buffered\n    drawing\n\n ** m4/octave_blas_f77_func.m4: Restore 64-bit integer BLAS detection (bug\n    #53853).\n\n ** build: include inplace_edit.pl in tarball (bug #54349).\n\n ** fix test for 8-byte integer BLAS lib on big-endian systems (bug #53853)\n\n ** OCTAVE_CHECK_LIB: avoid shell syntax error if not checking for lib\n\n ** build: avoid compiler warning about unused function abs (bug #54237)\n\n ** build: Work around bug in perl 5.28.0 (bug #54202).\n\n\nSummary of important user-visible changes for version 4.4 (2018-04-30):\n----------------------------------------------------------------------\n\n ** A graphical Variable Editor has been added to the GUI interface.\n    It uses a spreadsheet-like interface for quick, intuitive editing\n    of variables.  The Variable Editor is launched by double-clicking\n    on a variable name in the Workspace Window or by typing\n    \"openvar VARIABLE_NAME\" in the Command Window.\n\n ** On systems with 64-bit pointers, --enable-64 is now the default and\n    Octave always uses 64-bit indexing.  However, if the configure\n    script determines that the BLAS library uses 32-bit integers, then\n    operations using the following libraries are limited to arrays with\n    dimensions that are smaller than 2^31 elements:\n\n      BLAS  LAPACK  QRUPDATE  SuiteSparse  ARPACK\n\n    Additionally, the following libraries use \"int\" internally, so\n    maximum problem sizes are always limited:\n\n      glpk  Qhull\n\n ** The octave command no longer starts the GUI by default.  Most users\n    starting Octave from a shell were expecting the command line\n    interface, and desktop launchers already required the `--force-gui'\n    option.  With this change, desktop launchers should be modified to\n    use the new option `--gui'.  The previous `--force-gui' option will\n    continue to work, and maps to `--gui', but it will be removed in\n    Octave 6.\n\n ** A known bug in Qt (https://bugreports.qt.io/browse/QTBUG-55357) is\n    addressed by limiting GUI sub-panel relocation capabilities for Qt\n    versions in the range >= 5.6.1 and < 5.7.1.  However, this may not\n    thoroughly avoid issues on all platforms.\n\n ** A new container data type--containers.Map--is available.  Map is a\n    key/value storage container (a.k.a, a hash) that efficiently allows\n    storing and retrieving values by name, rather than by position which\n    is how arrays work.\n\n ** The bareword \"import\" is now recognized in scripts and functions.\n    However, the functionality to import functions and classes from\n    other namespaces into the local scope has not yet been implemented.\n    Attempting to use \"import\" will provoke an error message.\n\n ** hex2num and num2hex now work for integer and char types and num2hex\n    may optionally return a cell array of strings instead of a character\n    array.  If given a cell array of strings, hex2num now returns a\n    numeric array of the same size as the input cell array.  Previously,\n    hex2num would accept a cell array of strings of arbitrary dimension\n    but would always return a column vector.\n\n ** New special functions cosint, sinint, and gammaincinv have been added.\n\n ** Special functions in Octave have been rewritten for larger input\n    domains, better accuracy, and additional options.\n    * gammainc now accepts negative real values for X.\n    * improved accuracy for gammainc, betainc, betaincinv, expint.\n    * gammainc has new options \"scaledlower\" and \"scaledupper\".\n    * betainc, betaincinv have new option \"upper\".\n\n ** The \"names\" option used in regular expressions now returns a struct\n    array, rather than a struct with a cell array for each field.  This\n    change was made for Matlab compatibility.\n\n ** The quadcc function now uses both absolute tolerance and relative\n    tolerance to determine the stopping criteria for an integration.\n    To be compatible with other quadXXX functions, such as quadgk, the\n    calling syntax has changed to\n\n      quadcc (f, a, b, [AbsTol, [RelTol]])\n\n    To update existing code, change instances of RelTol to [0, RelTol].\n\n      quadcc (f, a, b, tol) => quadcc (f, a, b, [0, tol])\n\n    A warning that a single tolerance input is now interpreted as an\n    absolute tolerance will be issued in Octave versions 4.4 and 5,\n    after which it will be removed.  The warning has ID\n    \"Octave:quadcc:RelTol-conversion\" and can be disabled with\n\n      warning (\"off\", \"Octave:quadcc:RelTol-conversion\")\n\n ** The qr function now returns a standard factorization unless\n    explicitly instructed to perform an economy factorization by using a\n    final argument of 0.\n\n ** The Qt graphics toolkit now supports offscreen printing without osmesa\n    if Octave was built with Qt >= 5.1.\n\n ** The built-in pager for display of large data is now disabled by\n    default.  To re-enable it for every Octave session add the following\n    to your .octaverc file:\n\n      more on;\n\n ** The FLTK toolkit is no longer prioritized for development.  The\n    number of Octave Maintainers is too small to support three different\n    graphic toolkits.  New development will target the Qt toolkit.\n    While no longer prioritized, the FLTK toolkit is not deprecated and\n    there is no schedule for its removal.\n\n ** The graphic object property \"PickableParts\" has been implemented\n    which controls whether an object can accept mouse clicks.\n\n ** The graphic object property \"Interruptible\" has been fully\n    implemented which controls whether a running callback function can\n    be interrupted by another callback function.\n\n ** The graphic object property \"HitTest\" has been updated to be fully\n    compatible with Matlab.\n\n ** Text objects now implement the properties \"BackgroundColor\",\n    \"EdgeColor\", \"LineStyle\", \"LineWidth\", and \"Margin\".\n\n ** An initial implementation of alpha transparency has been made for\n    patch and surface objects.  Printing to svg and pdf is supported.\n\n ** ishandle now returns true for both graphics handle objects and\n    Java objects.  The latter change was made for Matlab compatibility.\n    Use ishghandle or isgraphics if it is important not to include Java\n    objects.\n\n ** The pkg command now accepts a URL as an argument, allowing a valid\n    Octave package to be installed from any remote host with one command,\n    for example\n\n      pkg install https://example.org/download/example-package.tar.gz\n\n ** The following statistical functions have been moved from core\n    Octave to the statistics package available from Octave Forge.\n\n    BASE\n      cloglog\n      logit\n      prctile\n      probit\n      qqplot\n      table  (renamed to crosstab)\n\n    DISTRIBUTIONS\n      betacdf\n      betainv\n      betapdf\n      betarnd\n      binocdf\n      binoinv\n      binopdf\n      binornd\n      cauchy_cdf\n      cauchy_inv\n      cauchy_pdf\n      cauchy_rnd\n      chi2cdf\n      chi2inv\n      chi2pdf\n      chi2rnd\n      expcdf\n      expinv\n      exppdf\n      exprnd\n      fcdf\n      finv\n      fpdf\n      frnd\n      gamcdf\n      gaminv\n      gampdf\n      gamrnd\n      geocdf\n      geoinv\n      geopdf\n      geornd\n      hygecdf\n      hygeinv\n      hygepdf\n      hygernd\n      kolmogorov_smirnov_cdf\n      laplace_cdf\n      laplace_inv\n      laplace_pdf\n      laplace_rnd\n      logistic_cdf\n      logistic_inv\n      logistic_pdf\n      logistic_rnd\n      logncdf\n      logninv\n      lognpdf\n      lognrnd\n      nbincdf\n      nbininv\n      nbinpdf\n      nbinrnd\n      normcdf\n      norminv\n      normpdf\n      normrnd\n      poisscdf\n      poissinv\n      poisspdf\n      poissrnd\n      stdnormal_cdf\n      stdnormal_inv\n      stdnormal_pdf\n      stdnormal_rnd\n      tcdf\n      tinv\n      tpdf\n      trnd\n      unidcdf\n      unidinv\n      unidpdf\n      unidrnd\n      unifcdf\n      unifinv\n      unifpdf\n      unifrnd\n      wblcdf\n      wblinv\n      wblpdf\n      wblrnd\n      wienrnd\n\n    MODELS\n      logistic_regression\n\n    TESTS\n      anova\n      bartlett_test\n      chisquare_test_homogeneity\n      chisquare_test_independence\n      cor_test\n      f_test_regression\n      hotelling_test\n      hotelling_test_2\n      kolmogorov_smirnov_test\n      kolmogorov_smirnov_test_2\n      kruskal_wallis_test\n      manova\n      mcnemar_test\n      prop_test_2\n      run_test\n      sign_test\n      t_test\n      t_test_2\n      t_test_regression\n      u_test\n      var_test\n      welch_test\n      wilcoxon_test\n      z_test\n      z_test_2\n\n ** The following image functions have been moved from core Octave to\n    the image package available from Octave Forge.\n\n      ntsc2rgb\n      rgb2ntsc\n\n ** Other new functions added in 4.4:\n\n      bounds\n      camlookat\n      camorbit\n      campos\n      camroll\n      camtarget\n      camup\n      camva\n      camzoom\n      corrcoef\n      cosint\n      decic\n      erase\n      gammaincinv\n      getframe\n      groot\n      gsvd\n      hgtransform\n      humps\n      integral\n      integral2\n      integral3\n      isgraphics\n      isstring\n      mad\n      ode15i\n      ode15s\n      openvar\n      quad2d\n      repelem\n      rgb2gray\n      rticks\n      sinint\n      tfqmr\n      thetaticks\n      vecnorm\n      winqueryreg\n      xticklabels\n      xticks\n      yticklabels\n      yticks\n      zticklabels\n      zticks\n\n ** Deprecated functions.\n\n    The following functions have been deprecated in Octave 4.4 and will\n    be removed from Octave 6 (or whatever version is the second major\n    release after 4.4):\n\n      Function             | Replacement\n      ---------------------|------------------\n      chop                 | sprintf for visual results\n      desktop              | isguirunning\n      tmpnam               | tempname\n      toascii              | double\n      java2mat             | __java2mat__\n\n\n ** The following functions were deprecated in Octave 4.0 and have been\n    removed from Octave 4.4.\n\n      allow_noninteger_range_as_index\n      bicubic\n      delaunay3\n      do_braindead_shortcircuit_evaluation\n      dump_prefs\n      find_dir_in_path\n      finite\n      fmod\n      fnmatch\n      gmap40\n      loadaudio\n      luinc\n      mouse_wheel_zoom\n      nfields\n      octave_tmp_file_name\n      playaudio\n      saveaudio\n      setaudio\n      syl\n      usage\n\n ** The \"Octave:undefined-return-values\" warning ID is obsolete.  Octave\n    now throws an error for any attempts to assign undefined values that\n    might be returned from functions.\n\n ** Deprecated graphics properties.\n\n    The following properties or allowed corresponding values have been\n    deprecated in Octave 4.4 and will be removed from Octave 6 (or whatever\n    version is the second major release after 4.4):\n\n      Object               | Property                | Value\n      ---------------------|-------------------------|-------------------\n      figure               | doublebuffer            |\n                           | mincolormap             |\n                           | wvisual                 |\n                           | wvisualmode             |\n                           | xdisplay                |\n                           | xvisual                 |\n                           | xvisualmode             |\n      axes                 | drawmode                |\n      annotation           | edgecolor (\"rectangle\") |\n      text                 | fontweight              | \"demi\" and \"light\"\n      uicontrol            | fontweight              | \"demi\" and \"light\"\n      uipanel              | fontweight              | \"demi\" and \"light\"\n      uibuttongroup        | fontweight              | \"demi\" and \"light\"\n\n ** The rectangle and ellipse annotation property \"edgecolor\" has been\n    deprecated and will be removed from Octave 6 (or whatever version\n    is the second major release after 4.4).  Use the property \"color\"\n    instead.\n\n ** The header file oct-alloc.h has been removed along with the macros\n    that it defined (DECLARE_OCTAVE_ALLOCATOR, DEFINE_OCTAVE_ALLOCATOR,\n    and DEFINE_OCTAVE_ALLOCATOR2).\n\n\nSummary of bugs fixed for version 4.2.2 (2018-03-13):\n----------------------------------------------------\n\nUsing the bug numbers listed below, find bug reports on the web using\nthe URL https://savannah.gnu.org/bugs/?NNNNN\n\n ** make leftdiv work for scalar \\ int-matrix (bug #51682)\n\n ** inputdlg.m: Avoid crash when prompt and defaults sizes differ (bug #53209)\n\n ** tie octave_classdef::numel method to \"numel\" user override method\n    (bug #46571)\n\n ** fix performance of Sparse fsolve for complex sparse matrices (bug #53140)\n\n ** fix performance of Sparse fsolve (bug #53140)\n\n ** octave.desktop.in: No repetition of Name in Comment field and start I10n\n    (bug #53078)\n\n ** don't create partially invalid graphic objects (bug #52904)\n\n ** test for incorrect regexprep on ARM platforms (bug #52810)\n\n ** fix incorrect regexprep on ARM platforms (bug #52810)\n\n ** correctly handle reading of characters >127 in scanf family (bug #52681)\n\n ** fix addpath for UNC paths on Windows (bug #51268)\n\n ** protect being-deleted objects on figure list from second deletion\n    (bug #52666)\n\n ** dlmwrite.m: Close fid if filename is only one char long (bug #52679)\n\n ** set gnuplot color data to half output range when autoscaling zero input\n    range (bug #52624)\n\n ** add polarplot() to the list of unimplemented functions (bug #52643)\n\n ** configure.ac: Fix test for Java version (bug #52617)\n\n ** for gnuplot toolkit, do not map TrueColor data to colormap size (bug #52599)\n\n ** make wheel scroll behave more consistently in pan mode (bug #52588)\n\n ** make gnuplot color have three components for interpolated edge color\n    (bug #52595)\n\n ** simplify gnuplot toolkit scripts for image/non-image data plots (bug #52589)\n\n ** fix concatenation of empty char matrices with other strings (bug #52542)\n\n ** build: Fix compiling OCTAVE_ARPACK_OK_2 Fortran code (bug #52425)\n\n ** trisurf.m, trimesh.m: Fix input validation (bug #48109)\n\n ** allow uncommenting in editor when line begins with whitespace (bug #52406)\n\n ** do not extend selection when indenting/commenting in editor (bug #45610)\n\n ** remove all delimiters from whitespace list in textscan function (bug #52479)\n\n ** calculate 1-norm of matrices to assess whether NaN or Inf are present\n    (bug #39000)\n\n ** prevent extra ampersand under KDE in cd-or-add-to-path dialog (bug #52423)\n\n ** plotyy.m: Fix error when using FUN2 argument (bug #48115)\n\n ** check ARPACK library for buggy behavior in configure (bug #52425)\n\n ** fix printing integer type images (bug #51558)\n\n ** fix segfault in delaunayn when Qhull memory is not properly cleared\n    (bug #52410)\n\n ** fix segfault with CHOLMOD library and empty matrices (bug #52365)\n\n ** tag global and persistent symbols as variables when parsing (bug #52363)\n\n ** properly restore the input stream pointer at end of textscan (bug #52116 et\n    al.)\n\n ** fix building with Qt4 for Windows (bug #52237)\n\n ** ensure numeric values are passed for the axes \"clim\" property (bug #52053)\n\n ** avoid abort on exit from GUI (bug #50664)\n\n ** correct auto limits on log axes with negative and zero values (bug #51861)\n\n ** fix warning in quadgk with zero size interval (bug #51867)\n\n ** sparse: correctly handle scalar column index (bug #51880)\n\n ** fix segfault in ichol under certain conditions (bug #51736)\n\n ** configure: ensure empty pkg-config results are actually empty (bug #51680)\n\n ** fix 'legend hide' for gnuplot (bug #50483)\n\n ** qqplot.m: Fix typo in input validation (bug #51458)\n\n ** add possible '\\r' to smartindent regex exprepression (Bug #51279)\n\n ** make strncmp case sensitive again (bug #51384)\n\n ** fix possible infinite loop in normest1.m (bug #51241)\n\n ** also run unwind protect cleanup code on interrupt exceptions (bug #51209)\n\n ** fix crash when inverting complex matrices with NaNs (bug #51198)\n\n ** improve accuracy of residue for inputs with very different magnitudes\n    (bug #51148)\n\n ** publish.m: Fix corruption of results for some code inputs (bug #51178)\n\n ** residue.m: Remove code that filters out small return values (bug #34266, bug\n    #49291)\n\n ** avoid possible double free at interpreter exit (bug #51088)\n\n ** show stack trace for errors in command line and startup files (bug #49346)\n\n ** interp1.m: Return NA for all columns which are out of bounds (bug #51030)\n\n ** use idx_type for dimensions instead of int (bug #50934)\n\n ** show stack trace for wrong type arg errors (bug #50894)\n\n ** let mouse selection of Qt figures update \"currentfigure\" (bug #50666)\n\n ** disable qscintilla editor drag and drop so parent will handle it (Bug\n    #50559)\n\n ** quadgk.m: Correct error messages which point to quadv (bug #50604)\n\n ** set version on AppUserModelId (Bug #50428)\n\n ** version-rcfile: Don't try to execute startup directory, only startup.m\n    (bug #50593)\n\n ** dlmread: Return empty matrix when requested range is outside data\n    (bug #50102)\n\n ** fix eigs for generalized nonsymmetric and shift-invert problems (bug #39573)\n\n ** fix eigs for the generalized eigenvalue problem (bug #50546)\n\n ** datetick.m: Fix uneven range bugs (bug #50493)\n\n ** datenum.m: Correct calculation for fractional leap years (bug #50508)\n\n ** datenum.m: Allow horizontal vectors of dates with fractional months\n    (bug #50508)\n\n ** datenum.m: Accept legal input of vectors with fractional months (bug #50508)\n\n ** fix the anchor position in the info text of the doc browser (bug #50422)\n\n ** fix order of legend labels with plotyy axes (bug #50497)\n\n ** correct hggroup plot legends for gnuplot toolkit, add legend demo 17 items\n    (bug #49341)\n\n ** for gnuplot graphics toolkit, show only one key entry for errorbars\n    (bug #49260)\n\n ** fix compilation of jit caused by cset d0562b3159c7 (bug #50398)\n\n ** remove inline keyword on file_stat destructor which breaks MacOS compilation\n    (bug #50234)\n\nDocumentation bugs fixed:\n\n ** playblocking.m: Correct documentation about start and limits inputs\n    (bug #51217)\n\n ** fix eig output argument description (bug #50524)\n\n ** remove backslashes before double quotes in m-file docstrings (bug #52870)\n\n ** tweaks to use single quotes instead of double quotes (bug #52870)\n\n ** correct fieldname of returned struct in ver (bug #52845)\n\n ** cleanup @code example in Appendix on test functions (bug #52852)\n\n ** fixes for signal, image, audio, and OOP chapters (bug #52844)\n\n ** fix issues in geometry, polynomial, and interpolation chapters (bug #52835)\n\n ** fix TeX documentation for qp and clarify size of inputs (bug #52829)\n\n ** correct errors in Diagonal matrix chapter of manual (bug #52814)\n\n ** replace @math{1e^{XXX}} sequences with raw 1eXXX (bug #52827)\n\n ** use '...' rather than deprecated '\\' for line continuation (bug #52828)\n\n ** make documentation Sec 26.1 more consistent and Sec 25.4 clearer\n    (bug #52685)\n\n ** documentation fixes for linspace, logspace, lookup (bug #52785)\n\n ** atan2d.m: Correct documentation to match atan docstring (bug #52786)\n\n ** small tweaks to fplot and surfnorm docstrings (bug #52761)\n\n ** rewrite documentation for Advanced Indexing (bug #52723)\n\n ** delete extra ']' in scanf docstring (bug #52742)\n\n ** fix mistaken use of space between function and '(' in documentation\n    (bug #52723)\n\n ** fix various inconsistencies in manual (bug #52712)\n\n ** fix typo in cset 8354b505ad6b (bug #52702)\n\n ** fix inconsistencies with char, strvcat, strread docstrings (bug #52702.\n\n ** explain Matlab compatibility of fopen modes (bug #52644)\n\n ** update documentation for keywords to include classdef statements\n    (bug #52591)\n\n ** fix documentation of third input to lsode() (bug #52664)\n\n ** clarify quiver/quiver3 documentation when a linestyle is given (bug #52608)\n\n ** new section about classdef classes with example (bug #44590)\n\n ** correct surface plot explanation of  meshgridded results of 1 input\n    (bug #52536)\n\n ** fix definition of Delaunay triangulation in docstrings (bug #52416)\n\n ** accumarray.m: Add '@' to function handles in docstring (bug #52418)\n\n ** update manual to explain \\deg and \\circ symbols (bug #52287)\n\n ** correct documentation for randg (bug #52118)\n\n ** add documentation about PCRE library regexp stack overflow (bug #51589)\n\n ** play.m: Correct documentation about start and limits inputs (bug #51217)\n\n ** redo docstring for qz (bug #50846)\n\n ** describe optional install dependencies PortAudio and SUNDIALS (bug #50513)\n\n ** update CITATION date, version, and permalink to manual (bug #47058)\n\n\nSummary of bugs fixed for version 4.2.1 (2017-02-22):\n----------------------------------------------------\n\nUsing the bug numbers listed below, find bug reports on the web using\nthe URL https://savannah.gnu.org/bugs/?NNNNN\n\n ** guarantee returning std::string from tilde_expand functions (bug #50234)\n\n ** workaround segfault in file_stat (bug #50234)\n\n ** genpropdoc.m: document more graphics properties (bug #50337)\n\n ** always fork and exec when starting the gui (bug #49609)\n\n ** print.m: fix regression with -append option (bug #50318)\n\n ** don't display legend, colorbar, and annotation axes coordinates\n    (bug #50272)\n\n ** qp.m: Fix regression with incorrect vector dimensions (bug #50067)\n\n ** prevent infinite loop in global documentation search (bug #50177)\n\n ** connect execute command signal in editor constructor (bug #50171)\n\n ** connect editors execute command signal to the required slot (bug #50171)\n\n ** check if input is class method before declaring it unimplemented\n    (patch #9238) (bug #49694)\n\n ** workaround segfault when an error occurs while printing (bug #49779)\n\n ** axis.m: Do not set plotboxaspectratio to 0 (bug #49755)\n\n ** don't rethrow exception in destructor (bug #49304)\n\n ** rethrow octave::exit_exception (bug #49304)\n\n ** update appdata.xml to follow conventions (bug #49952)\n\n ** mexproto.h (mxAssert, mxAssertS): ensure operator precedence (bug #50050)\n\n ** calculate error in solution for ode solvers correctly (bug #49950)\n\n ** use GetModuleFileName for getting octave path in windows (bug #48671)\n\n ** use C++ updaters for labels color (bug #49980)\n\n ** distinguish elements vs. bytes in fread (bug #49699)\n\n ** move frame2im and im2frame to image/ directory (bug #49939)\n\n ** fix undefined return argument for more than 2 outputs from ode solver\n    (bug #49890)\n\n ** fix inv for hermitian matrices (bug #49904)\n\n ** fix gzip for certain types of gzip files (bug #49760)\n\n ** fix typo in liboctave version info (bug #49860)\n\n ** initialize ODE Event function with start time (bug #49846)\n\n ** allow configure test to succeed without implicit fcn decls (bug #49782)\n\n ** allow external docstrings from .oct files to be found again (bug #49687)\n\n ** don't require semicolon between property list elements (bug #49819)\n\n ** display.m: Correctly display output for non-class objects\n    (bug #49753, #49794)\n\n ** don't run publish.tst unless OSMESA or gnuplot are available (bug #49767)\n\n ** find help for function aliases again (bug #49687)\n\n ** legend.m: backport cset 7184b4516a68 (bug #49675)\n\n ** preserve lasterror info on rethrow (bug #49642)\n\n ** norm: fix error in input argument validation leading to segfault\n    (bug #49634)\n\nDocumentation bugs fixed:\n\n ** overhaul Java interface description (bug #50299)\n\n ** add documentation for hex and binary prefix and _ separator\n    (bug #50305, #50334)\n\n ** fix build of docs broken in sub2ind (bug #50348)\n\n ** version.m: document that \"-release\" returns an empty string (bug #50294)\n\n ** remove trailing \"\\n\\\" from sleep and usleep docstrings (bug #50301)\n\n ** expand documentation for cast() (bug #50201)\n\n ** correct two entries in Table 34.1 (bug #50203)\n\n ** oop.txi: Improve table formatting (bug #50203)\n\n ** fix '##' in middle of docstring/comment lines (bug #50145)\n\n ** reword documentation about subplots in 15.2.4 (bug #50148)\n\n ** update unimplemented list of functions and where to find them\n    (bug #50098)\n\n ** compare_plot_demos: fix HTML syntax, simplify output, remove\n    external deps (bug #49709)\n\n ** add more depth to explanation of '~' function argument (bug #49444)\n\n ** correct documentation for javaclasspath file (bug #49873)\n\n ** small fixes to docstrings (bug #49733)\n\n ** change text describing demo plots to reflect new ColorOrder (bug #49288)\n\nOther bugs fixed:\n\n ** add missing classdef test files (bug #49819)\n\n\nSummary of important user-visible changes for version 4.2 (2016-11-13):\n----------------------------------------------------------------------\n\n ** The parser has been extended to accept, but ignore, underscore\n    characters in numbers.  This facilitates writing more legible code\n    by using '_' as a thousands separator or to group nibbles into bytes\n    in hex constants.\n\n    Examples: 1_000_000 == 1e6  or  0xDE_AD_BE_EF\n\n ** The parser has been extended to understand binary numbers which\n    begin with the prefix '0b' or '0B'.  The value returned is Octave's\n    default numeric class of double, not at unsigned integer class.\n    Therefore numbers greater than flintmax, i.e., 2^53, will lose some\n    precision.\n\n    Examples: 0b101 == 5  or  0B1100_0001 == 0xC1\n\n ** gnuplot 4.4 is now the minimum version supported by Octave.\n\n ** The default set of colors used to plot lines has been updated to be\n    compatible with Matlab's new default color scheme.  The line plot\n    color scheme can be set with the axes property \"ColorOrder\".\n\n ** The default colormap is now set to \"viridis\" which is also the\n    default colormap in matplotlib.  This new colormap fixes some of the\n    main issues with the old default colormap \"jet\" such as its bad\n    \"luminance profile\" and is also more similar to Matlab's new default\n    colormap \"parula\".\n\n ** The colormap function no longer supports the input argument \"list\"\n    to show built-in colormaps.  Use \"help colormap\" to find the\n    built-in colormaps.\n\n ** The graphics command \"hold on\" now ensures that each new plot added\n    to an existing plot has a different color or linestyle according to\n    the \"ColorOrder\" and/or \"LineStyleOrder\" properties.  This is\n    equivalent to the old command \"hold all\" and was made for Matlab\n    compatibility.  Existing code *may* produce differently colored\n    plots if it did not specify the color for a plot and relied on each\n    new plot having the default first color in the \"ColorOrder\"\n    property.\n\n ** When starting, Octave now looks in the function path for a file\n    startup.m and executes any commands found there.  This change was\n    made to accommodate Matlab users.  Octave has it's own configuration\n    system based on the file .octaverc which is preferred.\n\n ** Octal ('\\NNN') and hex ('\\xNN') escape sequences in single quoted\n    strings are now interpreted by the function do_string_escapes().\n    The *printf family of functions now supports octal and hex escape\n    sequences in single-quoted strings for Matlab compatibility.\n\n ** Special octal and hex escape sequences for the pattern and\n    replacement strings in regular expressions are now interpreted for\n    Matlab compatibility.\n\n    octal: '\\oNNN' or '\\o{NNN}'\n    hex  : '\\xNN'  or '\\x{NN}'\n\n ** Unknown escape sequences in the replacement string for regexprep are\n    now substituted with their unescaped version and no warning is\n    emitted.  This change was made for Matlab compatibility.\n\n    Example: regexprep ('a', 'a', 'x\\yz')\n             => 'xyz'\n\n ** mkfifo now interprets the MODE argument as an octal, not decimal,\n    integer.  This is consistent with the equivalent shell command.\n\n ** linspace now returns an empty matrix if the number of requested\n    points is 0 or a negative number.  This change was made to be\n    compatible with Matlab releases newer than 2011.  In addition,\n    Octave no longer supports matrix inputs for A or B.\n\n ** The cov function now returns the complex conjugate of the result\n    from previous versions of Octave.  This change was made for\n    compatibility with Matlab.\n\n ** condest now works with a normest1 compatible syntax.\n\n ** The griddata function no longer plots the interpolated mesh if no\n    output argument is requested, instead the vector or array of\n    interpolated values is always returned for Matlab compatibility.\n\n ** The new function \"light\" and the corresponding graphics object\n    provide light and shadow effects for patch and surface objects.\n\n ** The surfnorm function now returns unnormalized (magnitude != 1)\n    normal vectors for compatibility with Matlab.\n\n ** The normal vectors returned from isonormals have been reversed to\n    point towards smaller values for compatibility with Matlab.\n\n ** The quadl function now uses an absolute, rather than relative,\n    tolerance for Matlab compatibility.  The default tolerance is 1e-6\n    which may result in lower precision results than previous versions\n    of Octave which used eps as the relative tolerance.  The quadl\n    function has also been extended to return a second output with the\n    total number of function evaluations.\n\n ** The textscan function is now built-in and is much faster and much\n    more Matlab-compatible than the previous m-file version.\n\n ** Dialog boxes--errordlg, helpdlg, inputdlg, listdlg, msgbox,\n    questdlg, and warndlg--now exclusively use Qt for rendering.\n    Java based versions have been removed.\n\n ** The axes properties \"TitleFontSizeMultiplier\" and \"TitleFontWeight\"\n    are now implemented which control the default appearance of text\n    created with title().\n    The axes property \"LabelFontSizeMultiplier\" is now implemented\n    which controls the default appearance of text created with\n    xlabel(), ylabel(), or zlabel().\n\n ** The graphics property \"box\" for axes now defaults to \"off\".\n    To obtain equivalent plots to previous versions of Octave use\n      set (0, \"DefaultAxesBox\", \"on\");\n    in your .octaverc file.\n\n ** The graphics property \"boxstyle\" has been implemented.  The default\n    is \"back\" which draws only the back planes in a 3-D view.  If the\n    option is \"full\" then all planes are drawn.\n\n ** The graphics property \"erasemode\" has been hidden, and will\n    eventually be removed.  This property has also been removed\n    from Matlab, and was never implemented in Octave.\n\n ** The graphics property \"graphicssmoothing\" for figures now controls\n    whether anti-aliasing will be used for lines.  The default is \"on\".\n\n ** The value \"zero\" for the axes properties \"xaxislocation\" and\n    \"yaxislocation\" has been deprecated and will be removed from\n    Octave 5.  Use \"origin\" instead.\n\n ** The publish function allows easy publication of Octave script files\n    in HTML or other formats, including figures and output created by\n    this script.  It comes with its counterpart grabcode, which lets one\n    literally grab the HTML published code from a remote website, for\n    example.\n\n ** The value of the MEX variable TrapFlag now defaults to 0, which will\n    cause Octave to abort execution of a MEX file and return to the\n    prompt if an error is encountered in mexCallMATLAB.\n\n ** The MEX API now includes the function mexCallMATLABWithTrap.  This\n    function will not abort if an error occurs during mexCallMATLAB, but\n    instead will return execution to the MEX function for error\n    handling.\n\n ** The MEX API functions for input validation that begin with \"mxIs\"\n    (e.g., mxIsDouble, mxIsEmpty, etc.) now return type bool rather than\n    type int.\n\n ** The functions mxAssert and mxAssertS for checking assertions have\n    been added.  In order to avoid a performance penalty they are only\n    compiled in to debug versions of a MEX file, i.e., that are produced\n    when the '-g' option is given to mex or mkoctfile.\n\n ** Other new MEX API functions include mexEvalStringWithTrap,\n    mxIsScalar, mxCreateUninitNumericArray, mxCreateUninitNumericMatrix.\n\n ** Other new functions added in 4.2:\n\n      audioformats\n      camlight\n      condeig\n      deg2rad\n      dialog\n      evalc\n      hash\n      im2double\n      isocaps\n      lighting\n      localfunctions\n      material\n      normest1\n      ode23\n      ode45\n      odeget\n      odeplot\n      odeset\n      padecoef\n      profexport\n      psi\n      rad2deg\n      reducepatch\n      reducevolume\n      smooth3\n      uibuttongroup\n\n ** Deprecated functions.\n\n    The following functions have been deprecated in Octave 4.2 and will\n    be removed from Octave 5 (or whatever version is the second major\n    release after 4.2):\n\n      Function             | Replacement\n      ---------------------|------------------\n      bitmax               | flintmax\n      mahalanobis          | mahal in Octave Forge statistics pkg\n      md5sum               | hash\n      octave_config_info   | __octave_config_info__\n      onenormest           | normest1\n      sleep                | pause\n      usleep               | pause\n      wavread              | audioread\n      wavwrite             | audiowrite\n\n ** The following functions were deprecated in Octave 3.8 and have been\n    removed from Octave 4.2.\n\n      default_save_options    java_new\n      gen_doc_cache           java_unsigned_conversion\n      interp1q                javafields\n      isequalwithequalnans    javamethods\n      java_convert_matrix     re_read_readline_init_file\n      java_debug              read_readline_init_file\n      java_invoke             saving_history\n\n ** The global error_state variable in Octave's C++ API has been\n    deprecated and will be removed in a future version.  Now the error\n    and print_usage functions throw an exception\n    (octave::execution_exception) after displaying the error message.\n    This makes the error and print_usage functions in C++ work more like\n    the corresponding functions in the scripting language.\n\n ** The default error handlers in liboctave have been updated to use\n    exceptions.  After displaying an error message they no longer return\n    control to the calling program.  The error handler function can be\n    customized through the global variables\n    \"current_liboctave_error_handler\" and\n    \"current_liboctave_error_with_id_handler\".  If a programmer has\n    installed their own custom error handling routines when directly\n    linking with liboctave then these must be updated to throw an\n    exception and not return to the calling program.\n\n ** The system for common errors and warnings has been renamed from\n    gripe_XXX to either err_XXX if error is called or warn_XXX if\n    warning is called.  The gripe_XXX functions are deprecated and will\n    be removed in version 5.\n\n ** New configure option, --enable-address-sanitizer-flags, to build\n    Octave with memory allocator checks (similar to those in valgrind)\n    built in.\n\nSummary of important user-visible changes for version 4.0 (2015-05-23):\n----------------------------------------------------------------------\n\n ** A graphical user interface is now the default when running Octave\n    interactively.  The start-up option --no-gui will run the familiar\n    command line interface, and still allows use of the GUI dialogs and\n    qt plotting toolkit.  The option --no-gui-libs runs a minimalist\n    command line interface that does not link with the Qt libraries and\n    uses the fltk toolkit for plotting.\n\n ** Octave now uses OpenGL graphics with Qt widgets by default.  If\n    OpenGL libraries are not available when Octave is built, gnuplot is\n    used.  You may choose to use the fltk or gnuplot toolkit for\n    graphics by executing the command\n\n      graphics_toolkit (\"fltk\")\n        OR\n      graphics_toolkit (\"gnuplot\")\n\n    Adding such a command to your ~/.octaverc file will set the default\n    for each session.\n\n ** A new syntax for object oriented programming termed classdef has\n    been introduced.  See the manual for more extensive documentation of\n    the classdef interface.\n\n    New keywords:\n\n      classdef      endclassdef\n      enumeration   endenumeration\n      events        endevents\n      methods       endmethods\n      properties    endproperties\n\n ** New audio functions and classes:\n\n      audiodevinfo  audioread      sound\n      audioinfo     audiorecorder  soundsc\n      audioplayer   audiowrite\n\n ** Other new classes in Octave 4.0:\n\n      audioplayer    inputParser\n      audiorecorder\n\n ** Optional stricter Matlab compatibility for ranges, diagonal\n    matrices, and permutation matrices.\n\n    Octave has internal optimizations which use space-efficient storage\n    for the three data types above.  Three new functions have been added\n    which control whether the optimizations are used (default), or\n    whether the data types are stored as full matrices.\n\n    disable_range   disable_diagonal_matrix   disable_permutation_matrix\n\n    All three optimizations are disabled if Octave is started with the\n    --braindead command line option.\n\n ** The preference\n\n      do_braindead_shortcircuit_evaluation\n\n    is now enabled by default.\n\n ** The preference\n\n      allow_noninteger_range_as_index\n\n    is now enabled by default and the warning ID\n\n      Octave:noninteger-range-as-index\n\n    is now set to \"on\" by default instead of \"error\" by default and \"on\"\n    for --traditional.\n\n ** The \"backtrace\" warning option is now enabled by default.  This\n    change was made for Matlab compatibility.\n\n ** For compatibility with Matlab, the \"ismatrix (x)\" function now only\n    checks the dimension of \"x\".  The old behavior of \"ismatrix\" is\n    obtained by \"isnumeric (x) || islogical (x) || ischar (x)\".\n\n ** The nextpow2 function behavior has been changed for vector inputs.\n    Instead of computing `nextpow2 (length (x))', it will now compute\n    nextpow2 for each element of the input.  This change is Matlab\n    compatible, and also prevents bugs for \"vectors\" of length 1.\n\n ** polyeig now returns a row vector of eigenvalues rather than a matrix\n    with the eigenvalues on the diagonal.  This change was made for\n    Matlab compatibility.\n\n ** Interpolation function changes for Matlab compatibility\n\n    The interpolation method 'cubic' is now equivalent to 'pchip' for\n    interp1, interp2, and interp3.  Previously, 'cubic' was equivalent\n    to 'spline' for interp2.  This may produce different results as\n    'spline' has continuous 1st and 2nd derivatives while 'pchip' only\n    has a continuous 1st derivative.  The methods 'next' and 'previous'\n    have been added to interp1 for compatibility.\n\n ** The delaunay function has been extended to accept 3-D inputs for\n    Matlab compatibility.  The delaunay function no longer plots the\n    triangulation if no output argument is requested, instead, the\n    triangulation is always returned.  The delaunay3 function which\n    handles 3-D inputs has been deprecated in favor of delaunay.\n\n ** The trigonometric functions asin and acos return different phase\n    values from previous versions of Octave when the input is outside\n    the principal branch ([-1, 1]).  If the real portion of the input is\n    greater than 1 then the limit from below is taken.  If the real\n    portion is less than 1 then the limit from above is taken.  This\n    criteria is consistent with several other numerical analysis\n    software packages.\n\n ** The hyperbolic function acosh now returns values with a phase in the\n    range [-pi/2, +pi/2].  Previously Octave returned values in the\n    range [0, pi].  This is consistent with several other numerical\n    analysis software packages.\n\n ** strfind changes when using empty pattern (\"\") for Matlab\n    compatibility\n\n    strfind now returns an empty array when the pattern itself is empty.\n    In previous versions of Octave, strfind matched at every character\n    location when the pattern was empty.\n\n      NEW\n      strfind (\"abc\", \"\") => []\n      OLD\n      strfind (\"abc\", \"\") => [1, 2, 3, 4]\n\n ** Integer formats used in the printf family of functions now work for\n    64-bit integers and are more compatible with Matlab when printing\n    non-integer values.  Now instead of truncating, Octave will switch\n    the effective format to '%g' in the following circumstances:\n\n      * the value of an integer type (int8, uint32, etc.) value exceeds\n        the maximum for the format specifier.  For '%d', the limit is\n        intmax ('int64') and for '%u' it is intmax ('uint64').\n\n      * round(x) != x or the value is outside the range allowed by the\n        integer format specifier.\n\n    There is still one difference: Matlab switches to '%e' and Octave\n    switches to '%g'.\n\n ** The functions intersect, setdiff, setxor, and union now return a\n    column vector as output unless the input was a row vector.  This\n    change was made for Matlab compatibility.\n\n ** The inpolygon function now returns true for points that are within\n    the polygon OR on it's edge.  This change was made for Matlab\n    compatibility.\n\n ** The archive family of functions (bzip2, gzip, zip, tar) and their\n    unpacking routines (bunzip2, gunzip, unzip, untar, unpack) have been\n    recoded.  Excepting unpack, the default is now to place files in the\n    same directory as the archive (on unpack) or as the original files\n    (on archiving).\n\n ** Qt and FLTK graphics toolkits now support offscreen rendering on\n    Linux.  In other words, print will work even when the figure\n    visibility is \"off\".\n\n ** Z-order stacking issues with patches, grid lines, and line object\n    plot markers for on screen display and printing have all been\n    resolved.  For 2-D plots the axis grid lines can be placed on top of\n    the plot with set (gca, \"layer\", \"top\").\n\n ** The patch graphic object has been overhauled.  It now produces\n    visual results equivalent to Matlab even for esoteric combinations\n    of faces/vertices/cdata.\n\n ** The polar() plot function now draws a circular theta axis and radial\n    rho axis rather than using a rectangular x/y axis.\n\n ** linkprop has been completely re-coded for performance and Matlab\n    compatibility.  It now returns a linkprop object which must be\n    stored in a variable for as long as the graphic objects should\n    remain linked.  To unlink properties use 'clear hlink' where hlink\n    is the variable containing the linkprop object.\n\n ** isprime has been extended to operate on negative and complex inputs.\n\n ** xor has been extended to accept more than two arguments in which\n    case it performs cumulative XOR reduction.\n\n ** The following functions now support N-dimensional arrays:\n\n      fliplr   flipud   rot90   rectint\n\n ** The new warning ID \"Octave:data-file-in-path\" replaces the three\n    previous separate warning IDs \"Octave:fopen-file-in-path\",\n    \"Octave:load-file-in-path\", and \"Octave:md5sum-file-in-path\".\n\n ** The warning ID Octave:singular-matrix-div has been replaced by\n    Octave:nearly-singular-matrix and Octave:singular-matrix.\n\n ** The warning ID Octave:matlab-incompatible has been replaced by\n    Octave:language-extension to better reflect its meaning.\n\n ** The warning ID Octave:broadcast has been removed.  Instead automatic\n    broadcasting will throw an Octave:language-extension warning.  This\n    warning ID is used for broadcasting as well as other features not\n    available in Matlab.\n\n ** Other new functions added in 4.0:\n\n      annotation\n      bandwidth\n      cubehelix\n      dir_in_loadpath\n      flip\n      frame2im\n      get_home_directory\n      hgload\n      hgsave\n      ichol\n      ilu\n      im2frame\n      isbanded\n      isdiag\n      isstudent\n      istril\n      istriu\n      javachk\n      jit_failcnt\n      linkaxes\n      lscov\n      metaclass\n      numfields\n      open\n      ordschur\n      pan\n      qmr\n      rotate\n      rotate3d\n      sylvester\n      unsetenv\n      validateattributes\n      zoom\n\n ** inline() scheduled for eventual deprecation by Matlab\n\n    Functions created through the use of inline are scheduled for\n    deprecation by Matlab.  When this occurs Octave will continue to\n    support inline functions for an indeterminate amount of time before\n    also removing support.  All new code should use anonymous functions\n    in place of inline functions.\n\n ** Deprecated functions.\n\n    The following functions have been deprecated in Octave 4.0 and will\n    be removed from Octave 4.4 (or whatever version is the second major\n    release after 4.0):\n\n      Function             | Replacement\n      ---------------------|------------------\n      bicubic              | interp2\n      delaunay3            | delaunay\n      dump_prefs           | individual preference get/set routines\n      find_dir_in_path     | dir_in_loadpath\n      finite               | isfinite\n      fmod                 | rem\n      fnmatch              | glob or regexp\n      gmap40               | ----\n      loadaudio            | audioread\n      luinc                | ilu or ichol\n      mouse_wheel_zoom     | mousewheelzoom axes property\n      nfields              | numfields\n      octave_tmp_file_name | tempname\n      playaudio            | audioplayer\n      saveaudio            | audiowrite\n      syl                  | sylvester\n      usage                | print_usage\n\n      allow_noninteger_range_as_index\n      do_braindead_shortcircuit_evaluation\n      setaudio\n\n ** The following functions were deprecated in Octave 3.8 and will be\n    removed from Octave 4.2 (or whatever version is the second major\n    release after 3.8):\n\n      default_save_options    java_new\n      gen_doc_cache           java_unsigned_conversion\n      interp1q                javafields\n      isequalwithequalnans    javamethods\n      java_convert_matrix     re_read_readline_init_file\n      java_debug              read_readline_init_file\n      java_invoke             saving_history\n\n ** The following functions were deprecated in Octave 3.6 and have been\n    removed from Octave 4.0.\n\n      cut                polyderiv\n      cor                shell_cmd\n      corrcoef           studentize\n      __error_text__     sylvester_matrix\n      error_text\n\n ** The following keywords were deprecated in Octave 3.8 and have been\n    removed from Octave 4.0\n\n      static\n\n ** The following configuration variables were deprecated in Octave 3.8\n    and have been removed from Octave 4.0\n\n      CC_VERSION  (now GCC_VERSION)\n      CXX_VERSION (now GXX_VERSION)\n\n ** The internal function atan2 of the sparse matrix class has been\n    deprecated in Octave 4.0 and will be removed from Octave 4.4 (or\n    whatever version is the second major release after 4.0).  Use the\n    Fatan2 function with sparse inputs as a replacement.\n\n ** The internal class Octave_map was deprecated in Octave 3.8 and has\n    been removed from Octave 4.0.  Replacement classes are octave_map\n    (struct array) or octave_scalar_map for a single structure.\n\n ** Octave now has OpenMP enabled by default if the system provides a\n    working OpenMP implementation.  This allows oct-file modules to take\n    advantage of OpenMP if desired.  This can be disabled when building\n    Octave with the configure option --disable-openmp.\n\n ** Octave now automatically truncates intermediate calculations done\n    with floating point values to 64 bits.  Some hardware math\n    co-processors, such as the x87, maintain extra precision, but this\n    leads to disagreements in calculations when compared to reference\n    implementations in software using the IEEE standard for double\n    precision.  There was no measurable performance impact to this\n    change, but it may be disabled with the configure option\n    --disable-float-truncate.  MinGW and Cygwin platforms, as well as\n    GCC compilers >= 5.0 require this feature.  Non-x87 hardware, or\n    hardware using SSE options exclusively, can disable float truncation\n    if desired.\n\n---------------------------------------------------------\n\nSee NEWS.3 for old news.\n"
  },
  {
    "path": "etc/NEWS.5.md",
    "content": "Summary of bugs fixed for version 5.2.0 (2020-01-31):\n----------------------------------------------------\n\nSee: https://www.octave.org/news/release/2020/01/31/octave-5.2.0-released.html\n\nFor (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\n### Improvements\n\n- Lock amd and symbfact to avoid segmentation fault with SuiteSparse (bug #57435)\n- Fix segfault when calculating patch vertex normals (bug #57353)\n- Fix segfault in constructing patch normals for lighting (bug #57353)\n- `mat2str.m`: Fix for logical matrix (add `transpose`).\n- improve file equality check for MS Windows (bug #55161)\n- `ismember.m`: Fix second return argument when values are complex (bug #52437)\n- `findobj.m`: Fix typo and correctly handle numeric properties (bug #57030)\n- Correctly display integer types with format hex (bug #56966)\n- Cast `winqueryreg` `REG_DWORD` types to `DWORD` (bug #56703)\n- Fix numerous errors in `audiowrite` / `audioread` (bug #56889)\n- `print.m`: Pass quoted path to `octave-svgconvert` (bug #56768)\n- `dir.m`: Fix occasionally returning incorrect folder field (bug #55448)\n- Stop segfault when calling 3-input form of `diag` with cell arrays (bug #56711)\n- improve message for setting breakpoint in nonexistent function (bug #56157)\n- Use framebuffer object for printing invisible Qt figures on mac (bug #55268)\n- Escape backslash characters in EPS output (bug #56448)\n- Use replacement characters to display non UTF-8 strings in figures (bug #55974)\n- `inputrc`: Add warning about modification (bug #56079)\n- `documentation.cc` (global_search): just return if query string is empty (bug #56388)\n- Default (c)transpose for old style class arrays (bug #56323)\n- Always reserve at least 1 element of storage for sparse matrices (bug #56232)\n- Don't segfault at exit after reading malformed HDF5 file (bug #56149)\n- Fix `pause()` with no arguments called on Windows (bug #55943)\n- refactor minimum eigenvalue index search in `qp` (bug #56037)\n- qp: fix obscure corner case when calculating `qp` caused by a typo (bug #56037)\n- use `std::streampos` instead of `std::ios::streampos` (patch #9782).\n- fix `pause` and `kbhit` with glibc 2.28 end-of-file state behavior (bug #55029)\n- Fix return of left-handed vectors when inputs are complex (bug #56026)\n- `waitbar.m`: Fix hang when using `createcancelbtn` property (bug #55963)\n- `shading.m`: Fix unexpected error when multiple `hggroups` present (bug #55993)\n- `dec2base.m`: Correctly handle zero matrix input (bug #56005)\n- eliminate duplicate graphics callback object stack (bug #55908)\n- Improve performance when closing figures (bug #55908)\n- Reduce time to process `pkg -forge list` by 30X (bug #39479)\n- Feed `fig2dev` with PDF files converted from svg (bug #55906)\n- Improve error checking for `iconv_open`.\n- `poly.m`: fix the fix for input of complex conjugate pairs (bug #53897)\n- `mkoctfile`: use the `TMPDIR` environment variable if set (bug #55814)\n- `line.m`: Fix creation of unwanted axes (bug #55840)\n- Accept 4-input form for `quiver3` (bug #55570)\n- `pkg.m`: restore installing packages from zip archives (bug #55788)\n- `axis.m`: Fix issues with `equal` argument (bug #55619, bug #55614, bug #55574,\n  bug #55514, bug #54848, bug #53724, bug #53504, bug #53336, bug #51938, bug #50356).\n- `ordeig.m`: Do not fail on 1x1 matrices (bug #55779)\n\n### GUI\n\n- fix editors search and replace in selection (bug #56405)\n- undo a complete replace all action in the editor (bug #56405)\n- fix missing unlock of mutex when gui editor is not present (bug #56097)\n- prevent unnamed editor tab from being closed by `rmdir` (bug #55888)\n- prevent editor from closing files that are not affected by `rmdir` (bug #55823)\n- fix creating keyword files for editor autocompletion (bug #55835)\n- fix dock widget position when being dragged out of the main window (bug #55704)\n\n### Build system / Tests\n\n- configure: prevent overlinking when SUNDIALS is disabled (bug #55956)\n- use QtCore and Qt5Gui modules instead of Qt5OpenGL (bug #55735)\n- make building with Qt4 QGLWidget work again (bug #55735)\n- build: adapt `mk-qthelp.pl` to changes in Texinfo 6.7.\n- BIST should not rely on the current directory to be writable.\n- `bp-table.cc`: Fix test.\n- maint: Make old style class tests Matlab compatible.\n- Add BIST tests for `unlink` (bug #56097)\n\n### Documentation\n\n- fix many spelling errors (bug #57613)\n- help: improve documentation for the `startup.m` user script.\n- avoid conflict with `@seealso` macro in Texinfo 6.6 (bug #55952)\n- `mk-doc-cache.pk`: Also translate `@seealso` here. (bug #55952)\n- `__makeinfo__.m`: Also translate `@seealso` here (bug #55952)\n- `polar.m`: Document that input is expected to be in radians (bug #57052)\n- `gallery.m`: Fix typo in docstring for `poisson` (bug #56267)\n- Add 1024x1024 Octave logo icon (bug #55836)\n- add `.editorconfig` for default file encoding and indentation.\n- `octave.doap`: Copy localized (short) description over from appdata (bug #55279)\n- `org.octave.Octave.appdata.xml`: Add German and French description (bug #55279)\n- `languages/*.ts`: updated language files (bug #55772)\n- `quiver3.m`: Fix texinfo typo in docstring from cset f7b10bd40045.\n- doc: fix `.` Operator Index entry to build with Texinfo 6.7.\n- doc: improve example of using global variables from oct-files.\n- doc: Create en-dashes and em-dashes correctly in documentation.\n- doc: expand `page_output_immediately` doc string, mention `page_screen_output`.\n- doc: Clarify documentation of `history_file` (bug #57027)\n- doc: Improve documentation for `get_help_text`, `get_help_text_from_file`.\n- doc: Add documentation for `GNUTERM` variable used with gnuplot (bug #56906)\n- doc: Improve `contour` docstring example (bug #56849)\n- doc: Add example to show limitations of the given BLAS integer size.\n- doc: Improve documentation of sparse functions.\n- doc: Improve spelling of `bicgstab` (bug #56812)\n- doc: Remove `Map` functions `keys`, `values`, `remove` from unimplemented list (bug #56718)\n- doc: Add function index entry for alias `inverse` (bug #56629)\n- add content rating declaration to AppStream metadata (bug #56466)\n- doc: Remove stray semicolons from `pie`, `pie3` calling forms.\n- doc: Redo documentation for `rats` function.\n- doc: Specify `position` property for text objects is a three-element vector (bug #56303)\n- doc: state that Octave can only load HDF5 files created by itself (bug #56148)\n- doc: Fix names of options in `issorted` (bug #56087)\n- doc: Small fixes to `mat2cell` and `polyeig` docstrings (bug #55985)\n- doc: Improve example code for using `-pdflatexstandalone` (bug #55945)\n- doc: Refer to \"root object\" rather than \"root figure object\".\n- doc: Place cross-reference from list of graphics object properties back to object (bug #46076)\n- doc: document the newline character in warning messages (bug #49158)\n- doc: pkg versions can be more general than \"x.y.z\" (bug #55798)\n\n\nSummary of important user-visible changes for version 5 (2019-02-23):\n--------------------------------------------------------------------\n\nSee: https://www.octave.org/NEWS-5.1.html\n\n### General improvements\n\n- The Octave plotting system now supports high resolution screens,\n  i.e., those with greater than 96 DPI which are referred to as\n  HiDPI/Retina monitors.\n\n- Unicode character support for files and folders in Windows.\n\n- A new core function `movfun` will apply a function to a sliding\n  window of arbitrary size on a dataset and accumulate the results.\n  Many common cases have been implemented using the naming\n  scheme `movXXX` where `XXX` is the function that will be applied.\n  For example, the moving average over a dataset is `movmean`.\n  New moving window functions:\n\n  `movfun`  `movslice`\n  `movmad`  `movmax`   `movmean`  `movmedian`  `movmin`  `movprod`\n  `movstd`  `movsum`   `movvar`\n\n- The `fsolve` function has been tweaked to use larger step sizes when\n  calculating the Jacobian of a function with finite differences.\n  This leads to faster convergence.\n\n- The `ranks` function has been recoded for performance and is now 25X\n  faster.  In addition, it now supports a third argument that specifies\n  how to resolve the ranking of tie values.\n\n- The function `randi` has been recoded to produce an unbiased (all\n  results are equally likely) sample of integers.  This may produce\n  different results in existing code.  If it is necessary to reproduce\n  the exact random integer sequence as in previous versions use\n\n        ri = imin + floor ((imax - imin + 1) * rand ());\n\n- The function `isdefinite` now returns `true` or `false` rather than\n  `-1`, `0`, or `1`.  To test for a positive semi-definite matrix (old\n  output of `0`) check whether the following two conditions hold:\n\n    `isdefinite (A) => 0`  and  `isdefinite (A + 5*TOL, TOL) => 1`\n\n- The `intmax`, `intmin`, and `flintmax` functions now accept a variable\n  as input.  Existing code to query the range of an existing variable can\n  be simplified by removing the call to `class` that was previously\n  required.  For example defining the variable `x = int8 (3)` in the\n  workspace, calls like\n\n        range = [ intmin(class(x)), intmax(class(x)) ]\n\n  can in Octave 5 be simplified to `range = [ intmin(x), intmax(x) ]`.\n\n- The path handling functions no longer perform variable or brace\n  expansion on path elements and Octave's load-path is no longer\n  subject to these expansions.\n\n- A new printing device is available, `\"-ddumb\"`, which produces ASCII\n  art for plots.  This device is only available with the gnuplot toolkit.\n\n- The `msgbox` function has changed in two respects: the default `WindowStyle`\n  is now `\"non-modal\"`, and the default interpreter for the message is now\n  `\"tex\"`.  Both `WindowStyle` and `Interpreter` can be controlled by passing\n  an option struct argument.\n\n### Dependencies\n\n- The GUI requires Qt libraries.  The minimum Qt4 version supported is\n  Qt4.8.  Qt5 of any version is preferred.\n\n- The OSMesa library is no longer used.  To print invisible figures\n  when using OpenGL graphics, the Qt `QOFFSCREENSURFACE` feature must be\n  available and you must use the qt graphics toolkit.\n\n- The FFTW library is now required to perform FFT calculations.\n  The FFTPACK sources have been removed from Octave.\n\n\n### Matlab compatibility\n\n- The determination of an object's dimensions, size, and shape by the\n  functions `ndims`, `rows`, `columns`, `isscalar`, `isvector`,\n  `isrow`, `iscolumn`, `ismatrix`, and `issquare` now fully depends\n  on the function size.  Thus, any user-defined object can ensure correct\n  treatment by the aforementioned functions by properly overloading the\n  `size` function.\n\n- The functions `issymmetric` and `ishermitian` accept an option\n  `\"nonskew\"` or `\"skew\"` to calculate the symmetric or skew-symmetric\n  property of a matrix.  Performance has also been increased.\n\n- The `issorted` function now uses a direction option of `\"ascend\"`\n  or `\"descend\"`.  Change all uses of `\"ascending\"` and `\"descending\"`\n  in existing code to the new options.\n\n- The `strncmp` and `strncmpi` functions now return `true` if the two\n  input strings match, even though the number of characters specified\n  by `n` exceeds the string length.  For Example:\n\n    `strncmp (\"abc\", \"abc\", 100)`\n\n  returns `true` in Octave 5 and `false` in older versions of Octave.\n\n- The `str2func` function no longer accepts a second `\"global\"` argument.\n  This argument was typically used to allow functions that accept\n  function names as arguments to avoid conflicts with subfunctions or\n  nested functions.  Instead, it's best to avoid this situation\n  entirely and require users to pass function handles rather than\n  function names.\n\n- Using `clear` with no arguments now removes only local variables\n  from the current workspace.  Global variables will no longer be\n  visible, but they continue to exist in the global workspace and\n  possibly other workspaces such as the base workspace.\n\n\n#### Nonlinear Equations\n\nSeveral default solver options have been changed to be Matlab compatible.\nThis *may* result in existing code producing different results.\n\n- `fsolve`\n\n        Option         |   New Default    | Old Default\n        ---------------|------------------|-------------\n        FinDiffType    |    \"forward\"     |  \"central\"\n        MaxFunEvals    | 100*length(x0)   |    Inf\n        TolFun         |     1e-6         |    1e-7\n        TolX           |     1e-6         |    1e-7\n        Updating       |     \"off\"        |    \"on\"\n\n- `fminsearch`\n\n        Option   | New Default | Old Default\n        ---------|-------------|------------\n        TolFun   |   1e-7      |   1e-4\n\n- `fminbnd`\n\n        Option         | New Default | Old Default\n        ---------------|-------------|------------\n        MaxFunEvals    |     500     |   Inf\n        MaxIter        |     500     |   Inf\n        TolX           |    1e-4     |   1e-8\n\n- `fminunc`\n\n        Option         |   New Default    | Old Default\n        ---------------|------------------|------------\n        FinDiffType    |   \"forward\"      | \"central\"\n        MaxFunEvals    | 100*length(x0)   |   Inf\n        TolX           |     1e-6         |   1e-7\n        TolFun         |     1e-6         |   1e-7\n\n\n#### Graphic objects\n\n- Figure graphic objects have a new property `\"Number\"` which is\n  read-only and will return the handle (number) of the figure.\n  However, if the property `\"IntegerHandle\"` has been set to `\"off\"`\n  then the property will return an empty matrix `[]`.\n\n- Patch and surface graphic objects now use the `\"FaceNormals\"` property\n  for flat lighting.\n\n- `\"FaceNormals\"` and `\"VertexNormals\"` for patch and surface graphic\n  objects are now calculated only when necessary to improve graphics\n  performance.  In order for any normals to be calculated the\n  `\"FaceLighting\"` property must be set to `\"flat\"` (FaceNormals) or\n  `\"gouraud\"` (VertexNormals), **and** a light object must be present\n  in the axes.\n\n- The `\"Margin\"` property of `text`-objects has a new default of `3`\n  rather than `2`.\n\n- Printing to raster formats (bitmaps like PNG or JPEG) now uses an\n  OpenGL-based method by default.  The print options `\"-opengl\"`\n  (raster) and `\"-painters\"` (vector) have been added (\"qt\" toolkit\n  only).  The figure property `\"renderer\"` specifies which renderer to\n  use.  When the property `\"renderermode\"` is `\"auto\"` Octave will select\n  `\"-opengl\"` for a raster output format and `\"-painters\"` for a vector\n  output format.\n\n- A new print option `\"-RGBImage\"` has been added which captures the\n  pixels of a figure as an image.  This is similar to screen capture\n  tools, except that print formatting options can be used to, for\n  example, change the resolution or display the image in black and\n  white.\n\n- Two new print options for page-based formats (PDF, PostScript) have\n  been added.  The `\"-fillpage\"` option will stretch the plot to occupy\n  the entire page with 0.25 inch margins all around.  The `\"-bestfit\"`\n  option will expand the plot to take up as much room as possible on\n  the page without distorting the original aspect ratio of the plot.\n\n- Printing using the `\"-dtiff\"` output device will now create compressed\n  images using LZW compression.  To produce uncompressed images use the\n  `\"-dtiffn\"` device.\n\n\n### Legacy functions\n\nThe following functions have been declared legacy functions which\nmeans they are obsolete and should not be used in any new code.\nUnlike deprecated functions, however, their removal from Octave has\nnot yet been scheduled.\n\n        Function              | Replacement\n        ----------------------|------------------\n        findstr               | strfind\n        flipdim               | flip\n        isdir                 | isfolder or dir_in_loadpath\n        isequalwithequalnans  | isequaln\n        isstr                 | ischar\n        setstr                | char\n        strmatch              | strncmp or strcmp\n        strread               | textscan\n        textread              | textscan\n\n\n### Deprecated functions and properties\n\nThe following functions and graphics properties have been deprecated\nin Octave 5 and will be removed from Octave 7 (or whatever version\nis the second major release after 5):\n\n- Functions\n\n        Function                 | Replacement\n        -------------------------|-------------------\n        output_max_field_width   | output_precision\n        is_keyword               | iskeyword\n\n- Graphics properties\n\n        Object           | Property      | Value\n        -----------------|---------------|------------\n        text             | fontangle     | \"oblique\"\n        uibuttongroup    | fontangle     | \"oblique\"\n        uicontrol        | fontangle     | \"oblique\"\n        uipanel          | fontangle     | \"oblique\"\n        uitable          | fontangle     | \"oblique\"\n\n- Specifying `legend` position with a numeric argument is deprecated.\n  Use a string argument instead.\n\n- The environment variable used by `mkoctfile` for linker flags is now\n  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` is deprecated, and a warning\n  is emitted if is used, but it will continue to work.\n\n\n### Removed functions and properties\n\nThe following functions and properties were deprecated in Octave 4.2\nand have been removed from Octave 5.\n\n- Functions\n\n        Function             | Replacement\n        ---------------------|------------------\n        bitmax               | flintmax\n        mahalanobis          | mahal in Octave Forge statistics pkg\n        md5sum               | hash\n        octave_config_info   | __octave_config_info__\n        onenormest           | normest1\n        sleep                | pause\n        usleep               | pause\n        wavread              | audioread\n        wavwrite             | audiowrite\n\n- Properties\n\n        Object      | Property          | Value\n        ------------|-------------------|---------\n        axes        | xaxislocation     | \"zero\"\n                    | yaxislocation     | \"zero\"\n        hggroup     | erasemode         |\n        image       | erasemode         |\n        line        | erasemode         |\n        patch       | erasemode         |\n        patch       | normalmode        |\n        surface     | erasemode         |\n        surface     | normalmode        |\n        text        | erasemode         |\n\n### Alphabetical list of new functions added in 5\n\n- `clearvars`\n- `isfile`\n- `isfolder`\n- `matlab.lang.makeUniqueStrings`\n- `matlab.lang.makeValidName`\n- `movegui`\n- `movfun`\n- `movie`\n- `movmad`\n- `movmax`\n- `movmean`\n- `movmedian`\n- `movmin`\n- `movprod`\n- `movslice`\n- `movstd`\n- `movsum`\n- `movvar`\n- `openfig`\n- `ordeig`\n- `savefig`\n- `uitable`\n\n\n### Old release news\n\n- [Octave 4.4.x](NEWS.4)\n- [Octave 4.2.x](NEWS.4)\n- [Octave 4.0.x](NEWS.4)\n- [Octave 3.8.x](NEWS.3)\n- [Octave 3.6.x](NEWS.3)\n- [Octave 3.4.x](NEWS.3)\n- [Octave 3.2.x](NEWS.3)\n- [Octave 3.0.x](NEWS.3)\n- [Octave 2.x](NEWS.2)\n- [Octave 1.x](NEWS.1)\n"
  },
  {
    "path": "etc/NEWS.6.md",
    "content": "Summary of bugs fixed for version 6.4.0 (2021-10-30)\n----------------------------------------------------\n\nFor (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\n### Improvements and fixes\n\n- Reduce memory usage in BISTs for `copyobj`, `hgsave` (bug #57591).\n- `hgsave.m`, `copyobj.m`: Use `'qt'` graphics toolkit in BISTs.\n- `main.cc`: Use `getopt` to parse command line arguments (bug #60886).\n- `main.cc`: Remove invalid case (bug #60886).\n- Disable `getopt` error reporting in wrapper program (bug #60886).\n- `interp1.m`: Don't interpret later numeric input as `xi` (bug #60967).\n- `pkg`: Improve similar package name suggestion (bug #61067).\n- Store parent name in function object when caching parents in scope (bug #61105).\n- Avoid internal error and segfault with `eval` and scripts (bug #61191).\n- `rmpath`: Prevent removing the current directory from the load path (bug #61216).\n\n### GUI\n\n- Fix missing interpreter event in `octave-scintilla`.\n- Fix opening a file in a custom editor (bug #60990).\n\n### Documentation\n\n- Improve docstring for `disable_diagonal_matrix`, `disable_diagonal_matrix`,\n  and `disable_range` (patch #10089).\n- `cbrt`: Clarify that function errors for non-real input.\n- `dsearchn.m`: Added optional distance output description (bug #61156).\n- Add Hungarian translation for project description files.\n- Document `fsolve` output `\"info\"` -2 (bug #61310).\n\n### Build system\n\n- Correct error message for incompatible CXSparse (bug #61385).\n\n\nSummary of bugs fixed for version 6.3.0 (2021-07-11)\n----------------------------------------------------\n\nFor (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\n### Important notice\n\n- This bug fix release breaks ABI compatiblity with Octave 6.2.0. Re-build\n  binaries (like .oct or .mex files) when updating to this version.\n\n### Improvements and fixes\n\n- `ls-hdf5.cc`: Avoid throwing inside HDF5 function (bug #60081).\n- `ls-hdf5.cc`: Handle non-zero terminated type strings (bug #60081).\n- Fix occasional segfault in `symbfact` (bug #60101).\n- `fsolve.m`: Fix undefined output error when using `Output` function (bug #60144).\n- Fix compilation error with `iconv_t` on Solaris (bug #60162).\n- build: Check for `stropts.h` (bug #60163).\n- Avoid ambiguous call to `pow` (bug #60169).\n- Fix context link when creating handle to nested function.\n- `print.m`: Warn when figure is too large to be printed to output page (bug #60236).\n- Defer clearing function vars until stack frame is deleted (bug #60137).\n- Avoid memory leaks when returning handles to nested functions.\n- Hold references to closure frames in anon functions if needed (bug #60237).\n- `eigs`: Prevent possible segmentation fault at exit (bug #60311).\n- Issue warning when gnuplot graphics toolkit is initialized.\n- `mpoles.m`: Fix detection of pole multiplicity (bug #60384).\n- Perform shutdown actions in interpreter destructor (bug #60334).\n- build: Make relocation of dependencies with Octave optional (bug #60413).\n- `qz.cc`: Return correct number of eigenvalues (bug #60357).\n- `qz.cc`: Let test pass with LAPACK 3.9.1 and earlier versions (bug #60357).\n- `pkg.m`: Use default prefixes unless otherwise set previously (bug #60472).\n- `betaincinv.m`: Correctly handle small inputs (bug #60528).\n- `betaincinv.m`: Correctly handle inputs very close to 1.0 (bug #60528).\n- `unistd-wrappers.c`: Allocate sufficient memory for `new_argv` (bug #60535).\n- Mark system functions correctly if `OCTAVE_HOME` is non-canonical (bug #60554).\n- Mark compiled system functions correctly if `OCTAVE_HOME` is non-canonical (bug #60554).\n- Fix error if test suite is run before Octave is installed (bug #60554).\n- `lo-array-errwarn.cc`: Include `<limits>` (bug #60470).\n- Use `std::size_t` and `std::ptrdiff_t` in C++ code (bug #60471).\n- Use `std::size_t` in more instances (bug #60471).\n- Return proper number of stack frames for `dbstack (N)` call (bug #60531).\n- Avoid ambiguous match of overloaded function (bug #60531).\n- `lscov.m`: Relax BIST tolerance to pass with OpenBLAS (bug #60552).\n- `print`: Fix error when `\"px\"` word is present in a figure (bug #60641).\n- `logm.m`: Fix check for real negative values in complex vector (bug #60738).\n- build: Set necessary flags to allow execution on Windows Vista (bug #60746).\n- Declare base_parser destructor virtual.\n- `hist.m`: Improve handling and docstring for third parameter `\"norm\"` (bug #60783).\n- `logm.m`: Allow tolerance in check for real negative values in complex vector (bug #60738).\n- `expm.m`, `logm.m`: Use function `isdiag` to detect if input is a diagonal matrix (bug #60738).\n- tests: Relax tolerance for some tests on macOS.\n- `logspace.m`: Mark tests as known to fail on macOS (bug #55538).\n- `hist.m`: Use deterministic test (bug #60783).\n- `rgb2ind.m`: Reduce memory usage and eliminate randomness in test.\n- `logm.m`: Allow larger tolerance for test on macOS.\n- build: Use correct path to `octave` binary in build tree on macOS.\n- build: Fix typo in folder to libraries when building `.oct` or `.mex` files.\n- build: Set `DL_LDFLAGS` in the build rules for `.oct` or `.mex` files.\n- `rgb2ind.m`: Suppress output in test.\n- Improve documentation for `log2` function (bug #60817).\n- `ind2sub`: Fix typo in \"see also\" section of docstring (bug #60842).\n- `mrdivide`, `mldivide`: Document that functions might return minimum norm solutions (bug #60839).\n- Fix scoping issue for handles to sibling nested functions (bug #60845).\n- `ls-mat5.cc`: Avoid integer overflow in calculation of buffer size for zlib (bug #55427).\n- Move top-level REPL from interpreter to evaluator.\n- Avoid crash with `dbquit` when executing command in terminal from GUI (bug #60813).\n\n### GUI\n\n- Fix calling external editor (bug #60198).\n- Fix missing file suffix .m when saving a new script (bug #60214).\n- Do not run files that are not saved as Octave files (bug #60214).\n- Fix confirm overwrite for native editor file \"save as\" dialogs (bug #60214).\n- Fix crash when GUI tries to restore missing previous Octave dir (bug #60255).\n- Fix restoring the horizontal position of docked GUI widgets (bug #59426).\n- Prevent floating widgets from re-opening after restart (bug #60279).\n- Avoid crash in GUI for `rmdir(\"\")` (bug #60473).\n- Fix EOL mode when saving files under new names (bug #60585).\n- Fix auto indentation of switch-structure in GUI editor (bug #60649).\n- Avoid crash when closing GUI with open editor tabs (bug #60500).\n- `octave-qscintilla.cc` (`contextmenu_run`): Fix keyboard command handling.\n\n### Documentation\n\n- Improve Differential Equations chapter and example for `lsode` (bug #57508).\n- Clarify usage of `\"Depends\"` keyword in package `DESCRIPTION` file (bug #60053).\n- Add note that wildcard patterns for `save` are glob patterns (bug #60157).\n- Change example for Delaunay triangulation to match the generating code (bug #60216).\n- Document single precision issues with OpenGL graphics toolkits (bug #59418).\n- Minor changes to documentation of single precision issues with OpenGL (bug #59418).\n- Expand on documentation for command syntax (bug #60084).\n- `isprop.m`: Document that function only works on graphics objects in Octave 6.X (bug #60295).\n- Explain how to write dual-purpose executable scripts and Octave functions (bug #60291).\n- Update keyword docstrings (bug #60275).\n- Use Texinfo commands to improve `transpose()` docstring rendering.\n- `betainc.m`, `betaincinv.m`: Correct non-TeX definition of beta incomplete integral.\n- Grammarcheck documentation ahead of 6.3 release.\n- Spellcheck documentation ahead of 6.3 release.\n\n\nSummary of bugs fixed for version 6.2.0 (2021-02-19):\n----------------------------------------------------\n\nSee: https://www.octave.org/news/release/2021/02/20/octave-6.2.0-released.html\n\nFor (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\n### Improvements\n\n- `bicgstab.m`, `cgs.m`: Fix typo in `\"iter_min\"` variable name (bug #60071).\n- Compute with `NA` correctly on MIPS architecture (bug #59830).\n- Fix lookup of `\"caller\"` stack frame (bug #59847).\n- Also wait on `main_thread` after interpreter shuts down (bug #56952).\n- Fix symbol lookup issue with anonymous functions (bug #55989).\n- Line buffer input in `terminal_reader` class.\n- `qr`: Error for dense `A` and `B` with three output arguments (bug #58944).\n- `strmatch.m`: Always return column vector for Matlab compatibility (bug #59917)\n- Avoid crash when `evalin` global variables into existence in script (bug #59937)\n- Avoid crash on null statement list (bug #59938).\n- Fix ignored output from user function in left side of assignment (bug #59704).\n- Temporarily set lvalue list to null (bug #59704).\n- `fminbnd.m`: do not ignore `\"OutputFcn\"` (bug #59901).\n- `load-path.cc`: Reduce number of times `\"canonicalize_file_name\"` is called (bug #59711).\n- `interpn.m`: Use `size_equal` for 10X speedup in cset 067b663529bb (bug #59856).\n- `interpn.m`: Fix check for scattered point coordinates (bug #59856).\n- Avoid `YYUSE` in Octave parser files (see bug #59806).\n- `struct2hdl.m`: Set `\"units\"` property early.\n- `load-path.cc`: Avoid copying string for loop variable.\n- `pcg.m`: Return correct `FLAG` and correct `RELRES` output (bug #59776).\n- Use static keyword on regexp pattern in `file_stat` (bug #59706).\n- `stat`: Improve regular expression for UNC roots on Windows (bug #59706).\n- `stat`: Use `\"make_absolute\"` instead of `\"canonicalize_file_name\"` on Windows (bug #59706).\n- Improve `class_simple` function handle function lookup (bug #59661).\n- `hdl2struct.m`: store hidden text properties (bug #57241).\n- Mark script created with commands from history as modified.\n- `replem.m`: Fix operations with sparse matrices (bug #59705).\n- `ode_event_handler.m`: Fix mishandling of event edge types and multiple events (bug #59709).\n- Increase size of dynamic variable `new_argv` by 1 to avoid indexing out of array.\n- Fix incorrect results for set functions with `\"legacy\"` option (bug #59708).\n- `dir.m`: Return folder (not including file) in field `\"folder\"` (bug #59689).\n- Avoid memory leak with function handles (bug #59659).\n- Avoid dispatch error if method argument is a function handle (bug #59617).\n- Avoid crash due to accessing first element of empty list (bug #59656).\n- Don't propagate prevailing `isargout` info through `mexCallMATLAB` (bug #59597).\n- Show original error when failing to create a graphics object (bug #59620).\n- Fix regression with superclass lookup in classdef constructors (bug #59602).\n- Allow Octave class `execution_exception` to catch `std::exception` objects (bug #59592).\n\n### GUI\n\n- Fix restoring editor session after having closed all tabs (bug #60051).\n- Maybe convert TAB to SPC in GUI terminal pasted text (bug #59916).\n- Make bracketed paste mode work in GUI terminal.\n- Fix regression in variable editor when printing without selection.\n- Avoid gui when octave is launched in non-interactive mode (bug #59628).\n- `file-editor-tab.cc` (dtor): do not delete `m_edit_area` (bug #59628).\n- Fix error when restoring previous main window layout (bug #59426).\n- Improve default sizes of gui dock widgets.\n- Clean up constructing main window layout of the gui.\n- Fix focus command window after command execution (bug #59609).\n- Check object size before plotting from variable editor (bug #56685).\n- `documentation.cc`: Include missing header (bug #59553).\n\n### Build system / Tests\n\n- Add default value to `OCTAVE_MIPS_NAN` configure macro for cross-compiling (bug #59830).\n- tests: Function name should match file name (bug #59704).\n- Avoid build errors with Qt4 (bug #59813).\n- `eigs.m`: Make tests that depend on CHOLMOD conditional.\n- tests: Make tests that depend on CXSparse conditional.\n- build: Use `SPARSE_XCPPFLAGS` in `CPP_FLAGS` for `libcorefcn` (bug #59806).\n- Add test case for bug #59661.\n- `hgsave.m`: Allow test to run with qt or gnuplot graphics toolkits (bug #57241).\n\n### Documentation\n\n- `embedded.cc`: Fix syntax error interpreter shutdown.\n- Update Octave Project Developers copyright for the new year.\n- Use the same comment style for copyright headers in `.m` files and shell scripts.\n\n\nSummary of important user-visible changes for version 6.1.0 (2020-11-26):\n------------------------------------------------------------------------\n\n### General improvements\n\n- The `intersect`, `setdiff`, `setxor`, `union`, and `unique` functions\n  accept a new sorting option `\"stable\"` which will return output values\n  in the same order as the input, rather than in ascending order.\n\n- Complex RESTful web services can now be accessed by the `webread` and\n  `webwrite` functions alongside with the `weboptions` structure.  One\n  major feature is the support for cookies to enable RESTful\n  communication with the web service.\n\n  Additionally, the system web browser can be opened by the `web`\n  function.\n\n- The `linspace` function now produces symmetrical sequences when the\n  endpoints are symmetric.  This is more intuitive and also compatible\n  with recent changes made in Matlab R2019b.\n\n- The underlying algorithm of the `rand` function has been changed.\n  For single precision outputs, the algorithm has been fixed so that it\n  produces values strictly in the range (0, 1).  Previously, it could\n  occasionally generate the right endpoint value of 1 (See bug #41742).\n  In addition, the new implementation uses a uniform interval between\n  floating point values in the range (0, 1) rather than targeting a\n  uniform density (# of random integers / length along real number\n  line).\n\n- Numerical integration has been improved.  The `quadv` function has\n  been re-written so that it can compute integrands of periodic\n  functions.  At the same time, performance is better with ~3.5X fewer\n  function evaluations required.  A bug in `quadgk` that caused complex\n  path integrals specified with `\"Waypoints\"` to occasionally be\n  calculated in the opposite direction was fixed.\n\n- The `edit` function option `\"editinplace\"` now defaults to `true` and\n  the option `\"home\"` now defaults to the empty matrix `[]`.  Files will\n  no longer be copied to the user's `HOME` directory for editing.  The old\n  behavior can be restored by setting `\"editinplace\"` to `false` and\n  `\"home\"` to `\"~/octave\"`.\n\n- The `format` command supports two new options: `uppercase` and\n  `lowercase` (default).  With the default, print a lowercase `'e'` for\n  the exponent character in scientific notation and lowercase `'a-f'` for\n  the hex digits representing 10-15.  With `uppercase`, print `'E'` and\n  `'A-F'` instead.  The previous uppercase formats, `E` and `G`, no longer\n  control the case of the output.\n\n  Additionally, the `format` command can be called with multiple options\n  for controlling the format, spacing, and case in arbitrary order.\n  For example:\n\n        format long e uppercase loose\n\n  Note, in the case of multiple competing format options the rightmost\n  one is used, and, in case of an error, the previous format remains\n  unchanged.\n\n- L-value references (e.g., increment (`++`), decrement (`--`), and all\n  in-place assignment operators (`+=`, `-=`, `*=`, `/=`, etc.)) are no longer\n  allowed in anonymous functions.\n\n- New warnings have been added about questionable uses of the colon `':'`\n  range operator.  Each has a new warning ID so that it can be disabled\n  if desired.\n\n  >  `Octave:colon-complex-argument`   : when any arg is complex<br>\n  >  `Octave:colon-nonscalar-argument` : when any arg is non-scalar\n\n- The `regexp` and related functions now correctly handle and *require*\n  strings in UTF-8 encoding.  As with any other function that requires\n  strings to be encoded in Octave's native encoding, you can use\n  `native2unicode` to convert from your preferred locale.  For example,\n  the copyright symbol in UTF-8 is `native2unicode (169, \"latin1\")`.\n\n- The startup file `octaverc` can now be located in the platform\n  dependent location for user local configuration files (e.g.,\n  `${XDG_CONFIG_HOME}/octave/octaverc` on Unix-like operating systems or\n  `%APPDATA%\\octave\\octaverc` on Windows).\n\n- `pkg describe` now lists dependencies and inverse dependencies\n  (i.e., other installed packages that depend on the package in\n  question).\n\n- `pkg test` now tests all functions in a package.\n\n- When unloading a package, `pkg` now checks if any remaining loaded\n  packages depend on the one to be removed.  If this is the case `pkg`\n  aborts with an explanatory error message.  This behavior can be\n  overridden with the `-nodeps` option.\n\n- The command\n\n        dbstop in CLASS at METHOD\n\n  now works to set breakpoints in classdef constructors and methods.\n\n#### Graphics backend\n\n- The use of Qt4 for graphics and the GUI is deprecated in Octave\n  version 6 and no further bug fixes will be made.  Qt4 support will be\n  removed completely in Octave version 7.\n\n- The `legend` function has been entirely rewritten.  This fixes a\n  number of historical bugs, and also implements new properties such as\n  `\"AutoUpdate\"` and `\"NumColumns\"`.  The gnuplot toolkit---which is no\n  longer actively maintained---still uses the old legend function.\n\n- The `axis` function was updated which resolved 10 bugs affecting\n  axes to which `\"equal\"` had been applied.\n\n- Graphic primitives now accept a color property value of `\"none\"`\n  which is useful when a particular primitive needs to be hidden\n  (for example, the Y-axis of an axes object with `\"ycolor\" = \"none\"`)\n  without hiding the entire primitive `\"visibility\" = \"off\"`.\n\n- A new property `\"FontSmoothing\"` has been added to text and axes\n  objects that controls whether anti-aliasing is used during the\n  rendering of characters.  The default is `\"on\"` which produces smooth,\n  more visually appealing text.\n\n- The figure property `\"windowscrollwheelfcn\"`is now implemented.\n  This makes it possible to provide a callback function to be executed\n  when users manipulate the mouse wheel on a given figure.\n\n- The figure properties `\"pointer\"`, `\"pointershapecdata\"`, and\n  `\"pointershapehotspot\"` are now implemented.  This makes it possible\n  to change the shape of the cursor (pointer in Matlab-speak) displayed\n  in a plot window.\n\n- The figure property `\"paperpositionmode\"` now has the default `\"auto\"`\n  rather than `\"manual\"`.  This change is more intuitive and is\n  Matlab compatible.\n\n- The appearance of patterned lines `\"LineStyle\" = \":\"|\"--\"|\"-.\"` has\n  been improved for small widths (`\"LineWidth\"` less than 1.5 pixels)\n  which is a common scenario.\n\n- Printing to EPS files now uses a tight bounding box (`\"-tight\"`\n  argument to print) by default.  This makes more sense for EPS\n  files which are normally embedded within other documents, and is\n  Matlab compatible.  If necessary use the `\"-loose\"` option to\n  reproduce figures as they appeared in previous versions of Octave.\n\n- The following print devices are no longer officially supported: cdr,\n  corel, aifm, ill, cgm, hpgl, mf and dxf.  A warning will be thrown\n  when using those devices, and the code for supporting those formats\n  will eventually be removed from a future version of Octave.\n\n- The placement of text subscripts and superscripts has been\n  re-engineered and now produces visually attractive results similar to\n  Latex.\n\n### Matlab compatibility\n\n- The function `unique` now returns column index vectors for the second\n  and third outputs.  When duplicate values are present, the default\n  index to return is now the `\"first\"` occurrence.  The previous Octave\n  behavior, or Matlab behavior from releases prior to R2012b, can be\n  obtained by using the `\"legacy\"` flag.\n\n- The function `setdiff` with the `\"rows\"` argument now returns Matlab\n  compatible results.  The previous Octave behavior, or Matlab behavior\n  from releases prior to R2012b, can be obtained by using the `\"legacy\"`\n  flag.\n\n- The functions `intersect`, `setxor`, and `union` now accept a\n  `\"legacy\"` flag which changes the index values (second and third\n  outputs) as well as the orientation of all outputs to match Matlab\n  releases prior to R2012b.\n\n- The function `streamtube` is Matlab compatible and plots tubes along\n  streamlines which are scaled by the vector field divergence. The\n  Octave-only extension `ostreamtube` can be used to visualize the flow\n  expansion and contraction of the vector field due to the local\n  crossflow divergence.\n\n- The interpreter now supports handles to nested functions.\n\n- The graphics properties `\"LineWidth\"` and `\"MarkerSize\"` are now\n  measured in points, *not* pixels.  Compared to previous versions\n  of Octave, some lines and markers will appear 4/3 larger.\n\n- The meta.class property \"SuperClassList\" has been renamed\n  \"Superclasslist\" for Matlab compatibility.  The original name will\n  exist as an alias until Octave version 8.1.\n\n- Inline functions created by the function `inline` are now of type\n  `\"inline\"` when interrogated with the `class` function.  In previous\n  versions of Octave, the class returned was `\"function_handle\"`.  This\n  change is Matlab compatible.  Inline functions are deprecated in\n  both Matlab and Octave and support may eventually be removed.\n  Anonymous functions can be used to replace all instances of inline\n  functions.\n\n- The function `javaaddpath` now prepends new directories to the\n  existing dynamic classpath by default.  To append them instead, use\n  the new `\"-end\"` argument.  Multiple directories may now be specified\n  in a cell array of strings.\n\n- An undocumented function `gui_mainfcn` has been added, for compatibility\n  with figures created with Matlab's GUIDE.\n\n- Several validator functions of type `mustBe*` have been added.  See\n  the list of new functions below.\n\n### Alphabetical list of new functions added in Octave 6\n\n* `auto_repeat_debug_command`\n* `commandhistory`\n* `commandwindow`\n* `filebrowser`\n* `is_same_file`\n* `lightangle`\n* `mustBeFinite`\n* `mustBeGreaterThan`\n* `mustBeGreaterThanOrEqual`\n* `mustBeInteger`\n* `mustBeLessThan`\n* `mustBeLessThanOrEqual`\n* `mustBeMember`\n* `mustBeNegative`\n* `mustBeNonempty`\n* `mustBeNonNan`\n* `mustBeNonnegative`\n* `mustBeNonpositive`\n* `mustBeNonsparse`\n* `mustBeNonzero`\n* `mustBeNumeric`\n* `mustBeNumericOrLogical`\n* `mustBePositive`\n* `mustBeReal`\n* `namedargs2cell`\n* `newline`\n* `ode23s`\n* `ostreamtube`\n* `rescale`\n* `rotx`\n* `roty`\n* `rotz`\n* `stream2`\n* `stream3`\n* `streamline`\n* `streamtube`\n* `uisetfont`\n* `verLessThan`\n* `web`\n* `weboptions`\n* `webread`\n* `webwrite`\n* `workspace`\n\n\n### Deprecated functions and properties\n\nThe following functions and properties have been deprecated in Octave 6\nand will be removed from Octave 8 (or whatever version is the second\nmajor release after 6):\n\n- Functions\n\n        Function         | Replacement\n        -----------------|------------------\n        runtests         | oruntests\n\n- Properties\n\n        Object           | Property      | Value\n        -----------------|---------------|------------\n                         |               |\n\n- The environment variable used by `mkoctfile` for linker flags is now\n  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` is deprecated, and a warning\n  is emitted if it is used, but it will continue to work.\n\n\n### Removed functions and properties\n\nThe following functions and properties were deprecated in Octave 4.4\nand have been removed from Octave 6.\n\n- Functions\n\n        Function         | Replacement\n        -----------------|------------------\n        chop             | sprintf for visual results\n        desktop          | isguirunning\n        tmpnam           | tempname\n        toascii          | double\n        java2mat         | __java2mat__\n\n- Properties\n\n        Object           | Property                  | Value\n        -----------------|---------------------------|-----------------------\n        annotation       | edgecolor (\"rectangle\")   |\n        axes             | drawmode                  |\n        figure           | doublebuffer              |\n                         | mincolormap               |\n                         | wvisual                   |\n                         | wvisualmode               |\n                         | xdisplay                  |\n                         | xvisual                   |\n                         | xvisualmode               |\n        line             | interpreter               |\n        patch            | interpreter               |\n        surface          | interpreter               |\n        text             | fontweight                | \"demi\" and \"light\"\n        uibuttongroup    | fontweight                | \"demi\" and \"light\"\n        uicontrol        | fontweight                | \"demi\" and \"light\"\n        uipanel          | fontweight                | \"demi\" and \"light\"\n        uitable          | fontweight                | \"demi\" and \"light\"\n\n\n### Old release news\n\n- [Octave 5.x](NEWS.5.md)\n- [Octave 4.x](NEWS.4)\n- [Octave 3.x](NEWS.3)\n- [Octave 2.x](NEWS.2)\n- [Octave 1.x](NEWS.1)\n"
  },
  {
    "path": "etc/NEWS.7.md",
    "content": "Summary of bugs fixed for version 7.4.0 (tbd):\n----------------------------------------------------\n\nFor (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\n### Improvements and fixes\n\n### GUI\n\n### Build system / Tests\n\n### Documentation\n\nSummary of bugs fixed for version 7.3.0 (2022-11-02):\n----------------------------------------------------\n\n### Improvements and fixes\n\n- `scanf`: Don't set error when reaching end of stream (bug #62723).\n- Fix duplicate names displayed with mixed `@class`/`classdef` classes (bug #62802).\n- `canonicalize_file_name`: Handle symlinks to UNC network shares (bug #62847).\n- `canonicalize_file_name`: Generalize check for mapped network drive (bug #62847).\n- `fortran_vec`: Fix instances of method chaining that may cause dangling pointer.\n- Fix wrong color in PDF printout of some LaTeX strings (bug #62884).\n- `unpack.m`: Escape backslashes in paths on Windows (bug #62888).\n- `canonicalize_file_name`: Check root of potential mapped network drive (bug #62847).\n- `nextpow2.m`: Fix for input between 0.5 and 1 (bug #62947).\n- `quad2d`: Fix unintended complex conjugate return (bug #62972).\n- Make sure we don't pass short 8.3 path to `latex` on Windows (bug #62779).\n- `canonicalize_file_name`: Trim trailing file separators from root of mapped network drive (bug #62847).\n- `imformats.m`: Fix `isa` function in return value (bug #62974).\n- `pie3`: Fix \"Too many input\" args error.\n- Accept negative inputs to `-2^63` for `dec2bin` and `dec2hex` (bug #63089).\n- Fix incorrect `lambda` outputs for `lsqnonneg` and `pqpnonneg` (bug #63178).\n- `addtodate.m`: Fix wrong month returned when subtracting a month from some end-of-month dates (bug #60671).\n- `var.m`: Fix some `Inf` and `NaN` inputs returning `0` instead of `NaN` (bug #63203)\n- `var.m`: Fix automatic broadcasting error for sparse and diagonal matrix inputs with vector weighting (bug #63291).\n- `legend.m`: Fix error with `contour` plot containing `clabel`s (bug #63262).\n- `dec2bin.m`: Fix input validation (bug #63089).\n- `glpk.m`: Avoid using `isfinite` on potentially sparse input.\n- `var.m`: Use `bsxfun` rather than broadcasting with vector weighting (bug #63291).\n- Fix out of bound indexing in in-place broadcasting operations (bug #63303).\n\n### GUI\n- Respect confirmation when deleting files in file browser widget (bug #63198).\n\n### Build system / Tests\n\n- `io.tst`: Add test case for `scanf` (bug #62723).\n- `nextpow2.m`: Add bug number tag to regression tests (bug #62947).\n- `quad2d.m`: Add BIST to cset b0e90ca8e679 (bug #62972).\n- Add test for number of methods with `classdef` in `@folder` (bug #62802).\n- Use Autoconf macro to find `egrep` executable.\n\n### Documentation\n\n- `uitable.m`: Fix example code (bug #62824).\n- Clarify number of processors returned by `nproc` with hyperthreading.\n- Minor wording change to hashing documentation.\n- `lsqnonneg` and `pqpnonneg`: Document undocumented outputs.\n- `pqpnonneg.m`: Improve docstring readability.\n- `lsode`: Make TeX and non-TeX docstrings agree.\n- `curl`: Fix error in TeX docstring.\n- Update text on function argument checking.\n- `schur`: Update documentation.\n\n\nSummary of bugs fixed for version 7.2.0 (2022-07-28):\n----------------------------------------------------\n\nSee: https://octave.org/news/release/2022/07/28/octave-7.2.0-released.html\n\n### Improvements and fixes\n\n- Avoid out-of-bounds indexing when checking for broadcastable inplace operators (bug #38466).\n- `hdl2struct.m`: Fix saving of `uibuttongroups` (bug #62266).\n- Fix `ls` with glob patterns on Windows (bug #62282).\n- `pkg.m`: Create directory before saving file (bug #62303).\n- `nchoosek.m`: Fix freeze-up for certain integer inputs (bug #62319).\n- `nchoosek.m`: Restore fast path code for floating point inputs (bug #62319).\n- `betainc.m`: Use sophisticated technique for calculating exponents to avoid inaccuracies (bug #62329).\n- `ls.m`: Fix handling of `\\` on UNIX platforms (bug #62282).\n- `findobj.m`: Fix input validation of graphics handles (bug #62378).\n- `newplot.m`: Backed out changeset fdd58773ac02 (bug #61945).\n- `__print_parse_opts__.m`: Initialize variables in all cases for print warnings (bug #62287).\n- `__wglob__`: Correctly handle `.` and `..` in patterns on Windows (bug #62414).\n- `datenum.m`: Correctly handle arrays with leading singleton dimensions (bug #62407).\n- Stop incorrect error when `reset()` called on `uimenu` handle (bug #62425).\n- Emit more informative error message on empty input when setting axis limits (bug #62541).\n- `msgbox.m`: Allow \"custom\" `cdata` for icon (bug #62445).\n- Fix memory leak with nested functions and anonymous functions (bug #62459).\n- `__wglob__`: Retain trailing file separator on Windows (bug #62414).\n- `pkg`: Avoid error when unlinking non-existent files (bug #62436).\n- `mkoctfile.m`: Trim whitespace (newline) around system output.\n- `subplot.m`: Avoid error when mixing `rcn` and `\"position\"` calling form (bug #62526).\n- `plot`: Deprecate using numbers to select line colors (bug #62470).\n- Don't shut down interpreter immediately on `execute` (bug #62308).\n- `isprime.m` and `__isprimelarge__.cc`: Minor performance tweaks.\n- `__wglob__`: Handle patterns with UNC paths on Windows (bug #62576).\n- Change wording of error message when using a variable as function (bug #62552).\n- `inputParser.m`: Adapt for interpreter changes regarding number of output arguments (bug #62420).\n- Store token ID, not keyword ID when parsing keywords (bug #62587).\n- `canonicalize_file_name`: Do not translate mapped network drive to UNC path (bug #62576).\n- `inputParser`: Correctly handle cell default values for optional parameters (bug #62639).\n- `factor.m`: Performance tweak to avoid division in certain cases.\n- Fix regression with `\\color[rgb]` TeX pattern (bug #62668).\n- `regexp`: Check pattern length before accessing it (bug #62704).\n- `pkg.m`: Create `PREFIX` and `ARCHPREFIX` directories (bug #62681).\n- `pkg`: Replace `OCTAVE_HOME` in `PREFIX` and `ARCHPREFIX` independently (bug #62681).\n- `randmtzig.cc`: Add missing `#include <ctime>` (bug #62750).\n- `pkg`: Fix formatting of `copyfile` message (bug #62769).\n- `pkg`: Escape special characters in `OCTAVE_HOME` for `regexprep` (bug #62681).\n\n### GUI\n\n- Fix removing trailing spaces on closing a modified file (bug #62271).\n- Replace use of deprecated `QDesktopWidget` in GUI.\n- Fix display in Variable Editor when `fixed_point_format` is on (bug #62544).\n- Fix file length when saving shorter content in editor (bug #62588).\n\n### Build system / Tests\n\n- `addpref.m`: Recode test to work with multiple running instances of Octave.\n- Don't leak build directories in installed directories (bug #62295).\n- Import `hash-buffer` modules from gnulib (bug #62416).\n- Remove `.dirstamp` files from `test/` directory with `maintainer-clean` target.\n- Add tests for `__FILE__` and `__LINE__` (bug #52587).\n\n### Documentation\n\n- `datestr.m`: Fix minor typo.\n- `ls.m`: Improve wording in docstring (bug #62282).\n- `dir.m`: Clarify wildcard behavior on Windows in docstring (bug #62282).\n- `memory.m`: Redo documentation to be formatted correctly in Info output.\n- Document contracted `format` arguments (bug #62417).\n- `humps.m`: Fix mismatch between TeX docstring and non-TeX docstring.\n- `warning_ids.m`: Add new warning ID `\"Octave:deprecated-option\"`.\n- `primes.m`: Move code examples before math theory.\n- `primes.m`: Mark variables in docstring with `@var{}` macro.\n- Rewrite section on automatic type conversions (bug #62283).\n- `subsasgn`: Correct example code (bug #33221).\n\n\nSummary of important user-visible changes for version 7 (2022-04-06)\n--------------------------------------------------------------------\n\nSee: https://www.gnu.org/software/octave/news/release/2022/04/06/octave-7.1.0-released.html\n\n### General improvements\n\n- Many functions in Octave can be called in a command form---no\nparentheses for invocation and no return argument assignment---or in a\nfunctional form---parentheses and '=' for assignment of return values.\n\n    **Command Form Example**\n\n    `mkdir new_directory`\n\n    **Function Form Example**\n\n    `status = mkdir (\"new_directory\")`\n\n    Octave now handles errors that occur in a consistent manner.  If\n    called in command form and there is a failure, an error is thrown\n    and a message printed.  If called in functional form, no error or\n    message is printed and the failure is communicated to the programmer\n    via the output status variable.\n\n    The following list of functions have been modified.\n\n    * `copyfile`\n    * `fcntl`\n    * `fileattrib`\n    * `kill`\n    * `link`\n    * `mkfifo`\n    * `movefile`\n    * `rename`\n    * `rmdir`\n    * `symlink`\n    * `unlink`\n\n- Calling a user-defined function with too many inputs or outputs is now\nan error.  The interpreter makes this check automatically.  If a\nfunction uses `varargin` then the check is skipped for function inputs,\nand if a function uses `varargout` then the check is skipped for function\noutputs.  Input validation for functions typically begins with checking\nthat the number of inputs and outputs match expectations.  Existing code\ncan be simplified by removing these checks which are now done by the\ninterpreter.  Typically, code blocks like the following can simply be\ndeleted.\n\n        ## Checking number of inputs\n        if (nargin > 2)\n          print_usage ();\n        endif\n\n        ## Checking number of outputs\n        if (nargout > 1)\n          print_usage ();\n        endif\n\n- Binary and hexadecimal constants like `0b101` and `0xDEADBEEF` now\ncreate integers (unsigned by default) with sizes determined from the\nnumber of digits present.  For example, `0xff` creates a `uint8` value\nand `0xDEADBEEF` creates a `uint32` value.  You may also use a suffix of\nthe form `u8`, `u16`, `u32`, `u64`, `s8`, `s16`, `s32`, or `s64` to\nexplicitly specify the data type to use (`u` or `s` to indicate unsigned\nor signed and the number to indicate the integer size).\n\n    Binary constants are limited to 64 binary digits and hexadecimal\nconstants are limited to 16 hexadecimal digits with no automatic\nrounding or conversion to floating point values.  Note that this may\ncause problems in existing code.  For example, an expression like\n`[0x1; 0x100; 0x10000]` will be `uint8` (because of the rules of\nconcatenating integers of different sizes) with the larger values\ntruncated (because of the saturation semantics of integer values).  To\navoid these kinds of problems either: 1) declare the first integer to be\nof the desired size such as `[0x1u32; 0x100; 0x10000]`, or 2) pad\nconstants in array expressions with leading zeros so that they use the\nsame number of digits for each value such as\n`[0x00_00_01; 0x00_01_00; 0x01_00_00]`.\n\n- The colon operator now works for integer (`int8`, `int16`, ..., `uint64`)\nand single data types.  However, only `double` ranges use a\nmemory-efficient storage scheme internally.  Other data types are\nstored as ordinary arrays.\n\n- The increment and decrement operators `++` and `--` must \"hug\" their\ncorresponding variables.  In previous versions of Octave, whitespaces\nbetween these operators and the variable they affect were allowed.  That\nis no longer the case.\n\n- Parsing of command-style function calls has changed to improve\nconsistency of behavior and compatibility with Matlab.  This change\naffects statements that begin with binary operator expressions when the\nfirst operand is a plain symbol followed by a whitespace character and\nthe binary operator is not followed by a whitespace character.  For\nexample, the statement `cmd -option` is parsed as a command-style\nfunction call, not a binary subtraction operation.\n\n    This change affects all binary operators: `+`, `-`, `*`, `/`, `\\`,\n`^`, `.*`, `./`, `.\\`, `.^`, `|`, `&`, `||`, `&&`, `+=`, `-=`, `*=`,\n`/=`, `\\=`, `^=`, `.*=`, `./=`, `.\\=`, `.^=`, `|=`, and `&=`.\n\n    Previous versions of Octave would attempt to determine whether the\nfirst operand in an expression was a variable, and if so, parse\nexpressions like `var -val` as an expression.  However, this attempt to\n\"do the right thing\" could cause trouble (for example, if a variable is\nonly defined conditionally).\n\n    Now, parsing command-style function calls is purely based on syntax.\n\n    Command-style function call syntax is only allowed at the beginning\nof a statement.  Expressions in other contexts are not affected, so an\nexpression like `a + b +c` will not be parsed as a command-style function\ncall.\n\n    For compatibility with Matlab, a binary expression at the beginning\nof a statement that starts with one of the symbols `I`, `i`, `J`, `j`,\n`Inf`, `inf`, `NaN`, `nan`, or `pi` is never parsed as a command-style\nfunction call.  Octave also extends this behavior to `e`, which is not\npresent as a special numeric constant in Matlab.\n\n    Note that full compatibility with Matlab, which does not have the\nOP= operators, would require that even `a -= b` is parsed as a\ncommand-style function call.  As that would significantly hinder the use\nof these operators, Octave treats them as the other binary operators\ninstead of providing fully compatible behavior.\n\n- The `mldivide` function (i.e., the `\\` operator) now uses an LU\ndecomposition to solve nearly singular full square matrices.  This is\nMatlab-compatible and yields results which more nearly minimize `norm\n(A*x - b)`.  Previously, Octave computed a minimum-norm solution.\n\n- The `factor` function has been overhauled for speed.  For large\ninputs > 1e14, it can be up to 10,000 times faster.\n\n- The `isprime` function uses a new primality testing algorithm\nthat is up to 50,000 times faster for inputs > 1e14.\n\n- The `betainc` function now calculates an exact output for the\nimportant special cases where `a` or `b` are `1`.\n\n- The `whos` function now displays an additional attribute `'s'` when\nthe variable is a sparse type.\n\n- As part of GSoC 2020, Abdallah K. Elshamy implemented the\n`jsondecode` and `jsonencode` functions to read and write JSON data.\n\n- As part of GSoC 2021, Abdallah K. Elshamy implemented the\n`jupyter_notebook` classdef class.  This class supports running and\nfilling Jupyter Notebooks using the Octave language kernel from Octave\nitself.  Making the evaluation of long-running Jupyter Notebooks on a\ncomputing server without permanent browser connection possible.\n\n- By default, the history file is now located at `$DATA/octave/history`,\nwhere `$DATA` is a platform dependent location for (roaming) user data\nfiles (e.g., `${XDG_DATA_HOME}` or, if that is not set, `~/.local/share` on\nUnix-like operating systems or `%APPDATA%` on Windows).\n\n- For Octave on Windows OS, the minimum required version of the Windows\nAPI is now 6.1 (Windows 7 or newer).\n\n- The non-re-entrant version of the QHull library \"libqhull\" was\ndeprecated upstream.  Octave now (optionally) requires the re-entrant\nversion of that library \"libqhull_r\" instead.\n\n- Octave's build system no longer appends \"++\" to the end of the\n\"magick++\" library name (set with the `--with-magick=` configure flag).\nThe real name of the \"magick++\" library (including any potentially\ntrailing \"++\") needs to be set in that option now.\n\n- The `pkg update` command now accepts options that are passed to `pkg\ninstall` for each updated package.  Specifying `-local` or\n`-global` will restrict update checks to local or global\ninstalled packages, respectively.\n\n### Graphical User Interface\n\n- The graphical user interface is now available in Hungarian and\nTurkish.\n\n- In debug mode, symbol values are now shown in tooltips when hovering\nvariables in the editor panel.\n\n- The \"Disable global shortcuts when Command Window has focus\" GUI\npreference under the Shortcuts tab is now disabled by default.  This\noption disables keyboard shortcuts to avoid interference with readline\nkey strokes in the Command Window.  Unlike versions prior to Octave 7,\nthis preference now also affects the Ctrl-C/V shortcuts for copy/paste.\n\n- In command line mode, i.e. when Octave is started without the `--gui` option,\nthe doc command now opens the GUI documentation browser as a standalone widget,\nprovided that Octave was compiled with GUI support.\n\n### Graphics backend\n\n- Support for Qt4 for both graphics and the GUI has been removed.\n\n- If a working LaTeX tool chain is found on the path, including `latex`,\n`dvipng`, and `dvisvgm` binaries, then text strings can now be rendered\nproperly when using the `\"latex\"` value for the text objects'\n`\"interpreter\"` property and axes objects' `\"ticklabelinterpreter\"`.\nType `doc \"latex interpreter\"` for further info.\n\n- The `\"Marker\"` property for plot objects now accepts `|` which draws\na vertical line or `_` which draws a horizontal line.\n\n- The `FMT` format argument for plot commands now accepts long forms for\ncolor names which may be more understandable than the existing\none-letter codes.  For example, the RGB value `[0 0 0]` can now be\nspecified by `\"black\"` in addition to `\"k\"`.\n\n- The color graphics properties, for example `\"EdgeColor\"` or\n`\"FaceColor\"`, now accept HTML specifications.  An HTML specification is\na string that begins with the character '#' and is followed by either 3\nor 6 hexadecimal digits.  For example, magenta which is 100% red and\nblue values can specified by `\"#FF00FF\"` or `\"#F0F\"`.\n\n- The additional property `\"contextmenu\"` has been added to all graphics\nobjects.  It is equivalent to the previously used `\"uicontextmenu\"`\nproperty which is hidden now.\n\n- `uicontrol` objects now fully implement the `\"Off\"` and `\"Inactive\"`\nvalues of the `\"Enable\"` property.  When the value is `\"Off\"`, no\ninteraction with the object occurs and the `uicontrol` changes color\n(typically to gray) to indicate it is disabled.  When the value is\n`\"Inactive\"`, the object appears normally (no change in color), but it\nis not possible to change the value of the object (such as modifying\ntext in an `Edit` box or clicking on a `RadioButton`).\n\n- The `\"ListBoxTop\"` property for `uicontrol` objects has been\nimplemented for `set` commands.\n\n- The `Title` property for print formats such as PDF or SVG is now set\nto the title displayed on the figure window which contains the plot.\n\n- Additional properties have been added to the `axes` graphics object:\n\n    * `\"alphamap\"` (not yet implemented)\n    * `\"alphascale\"` (not yet implemented)\n    * `\"colorscale\"` (not yet implemented)\n    * `\"fontsizemode\"` (not yet implemented)\n    * `\"innerposition\"` (equivalent to `\"position\"`)\n    * `\"interactions\"` (not yet implemented)\n    * `\"layout\"` (not yet implemented)\n    * `\"legend\"` (not yet implemented)\n    * `\"nextseriesindex\"` (read-only, used by `scatter`\n      graphics objects)\n    * `\"positionconstraint\"` (replacement for `\"activepositionproperty\"`\n      which is now a hidden property.  No plans for removal.)\n    * `\"toolbar\"` (not yet implemented)\n    * `\"xaxis\"` (not yet implemented)\n    * `\"yaxis\"` (not yet implemented)\n    * `\"zaxis\"` (not yet implemented)\n\n### Matlab compatibility\n\n- The function `griddata` now implements the `\"v4\"` Biharmonic Spline\nInterpolation method.  In adddition, the function now accepts 3-D inputs\nby passing the data to `griddata3`.\n\n- Coordinate transformation functions `cart2sph`, `sph2cart`,\n`cart2pol`, and `pol2cart` now accept either row or column vectors for\ncoordinate inputs.  A single coordinate matrix with one variable per\ncolumn can still be used as function input, but a single output variable\nwill now contain just the first output coordinate, and will no longer\nreturn the full output coordinate matrix.  Output size matches the size\nof input vectors, or in the case of an input matrix will be column\nvectors with rows corresponding to the input coordinate matrix.\n\n- The function `dec2bin` and `dec2hex` now support negative numbers.\n\n- The function `factor` now supports `uint64` inputs larger than\n`flintmax`.\n\n- The function `primes` now supports char inputs.\n\n- The functions `quantile` and `prctile` now permit operating on\ndimensions greater than `ndims (x)`.\n\n- The function `iqr` now uses Matlab compatible interpolation for\nquantile values.  The dimension input now allows a vector, \"all\", and\ndimensions greater than `ndims (x)`.  The function also handles\n`Inf` and `NaN` input values in a Matlab-compatible manner.\n\n- The function `importdata` now produces more compatible results when\nthe file contains a 2-D text matrix.\n\n- The file functions `copyfile`, `mkdir`, `movefile`, `rmdir` now return\na logical value (true/false) rather than a numeric value (1/0).\n\n- `uimenu` now accepts property `\"Text\"` which is identical to\n`\"Label\"`.  Matlab recommends using `\"Text\"` in new code, although there\nis no announced date for deprecating `\"Label\"`.\n\n- The functions `scatter` and `scatter3` now return a handle to a\nscatter graphics object.  For compatibility, they return an `hggroup` of\npatch graphics objects when the `\"gnuplot\"` graphics toolkit is used.  In\nprevious versions of Octave, these functions returned an `hggroup` of\npatch graphics objects for all graphics toolkits.\n\n- The functions `bar` and `barh` now handle stacked negative bar values\nin a Matlab-compatible manner.  Negative values now stack below the zero\naxis independently of a positive value bars in the same stack.\nPreviously the negative bars could overlap positive bars depending on\ndrawing order.\n\n- The functions `bar` and `barh` now use colors from the `\"ColorOrder\"`\naxes property rather than the `\"Colormap\"` figure property unless one\nof the histogram options (@qcode{\"hist\"}, @qcode{\"histc\"} was specified.\n\n- The function `saveas` now defaults to saving in Octave figure format\n(.ofig) rather than PDF (.pdf).\n\n- A new warning ID (`\"Octave:unimplemented-matlab-functionality\"`) has\nbeen added which prints a warning when Octave's parser recognizes valid\nMatlab code, but for which Octave does not yet implement the\nfunctionality.  By default, this warning is enabled.\n\n- When Octave is started with the `--traditional` option for maximum\ncompatibility the `print_struct_array_contents` internal variable is set\nto true.\n\n- The function `repelem` now produces a row vector output when the input is\na scalar.\n\n- The functions `var` and `std` now accept a weight vector as input and\ncompute the weigthed variance.  Dimension input now allows a vector and\nthe keyword \"all\".\n\n### Alphabetical list of new functions added in Octave 7\n\n* `cospi`\n* `getpixelposition`\n* `endsWith`\n* `fill3`\n* `jsondecode`\n* `jsonencode`\n* `jupyter_notebook`\n* `listfonts`\n* `matlab.net.base64decode`\n* `matlab.net.base64encode`\n* `memory`\n* `ordqz`\n* `rng`\n* `sinpi`\n* `startsWith`\n* `streamribbon`\n* `turbo`\n* `uniquetol`\n* `xtickangle`\n* `ytickangle`\n* `ztickangle`\n\n### Deprecated functions and operators\n\nThe following functions and operators have been deprecated in Octave 7\nand will be removed from Octave 9 (or whatever version is the second\nmajor release after 7):\n\n- Functions\n\n        Function                     | Replacement\n        ---------------------------- |----------------------------\n        disable_diagonal_matrix      | optimize_diagonal_matrix\n        disable_permutation_matrix   | optimize_permutation_matrix\n        disable_range                | optimize_range\n\n  For plot functions, the use of numbers to select line colors in\n  shorthand formats was an undocumented feature that is deprecated in\n  Octave 7 and will be removed from Octave 9.\n\n- Operators\n\n        Operator | Replacement | Description\n        ---------|-------------|------------\n        **       | ^           | Matrix exponent\n        .**      | .^          | Element-by-element exponent\n        .+       | +           | Element-by-element addition\n        .-       | -           | Element-by-element subtraction\n\n- Interpreter\n\n    * The use of `'...'` for line continuations *inside* double-quoted\n    strings has been deprecated.  Use `'\\'` for line continuations\n    inside strings instead.\n\n    * The use of `'\\'` as a line continuation *outside* of double-quoted\n    strings has been deprecated.  Use `'...'` for line continuations\n    instead.\n\n    * Any trailing whitespace after a `'\\'` line continuation has been\n    deprecated.  Delete unnecessary trailing whitespace.\n\n\nThe following functions were deprecated in Octave 6 and will be removed\nfrom Octave 8 (or whatever version is the second major release after 6):\n\n- Functions\n\n        Function               | Replacement\n        -----------------------|------------------\n        runtests               | oruntests\n\n- The environment variable used by `mkoctfile` for linker flags is now\n  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` was deprecated in Octave 6,\n  and a warning is now emitted if it is used, but it will continue to\n  work.\n\n### Removed functions, properties, and features\n\nThe following functions and properties were deprecated in Octave 5\nand have been removed from Octave 7.\n\n- Functions\n\n        Function                 | Replacement\n        -------------------------|------------------\n        output_max_field_width   | output_precision\n        is_keyword               | iskeyword\n\n- Properties\n\n        Object           | Property      | Value\n        -----------------|---------------|------------\n        text             | fontangle     | \"oblique\"\n        uibuttongroup    | fontangle     | \"oblique\"\n        uicontrol        | fontangle     | \"oblique\"\n        uipanel          | fontangle     | \"oblique\"\n        uitable          | fontangle     | \"oblique\"\n\n- The prototype JIT compiler has been removed from Octave.  Since it was\nfirst added as part of a Google Summer of Code project in 2012, no one\nhas ever seriously taken on further development of it and it still does\nnothing significant.  It is out of date with the default interpreter\nthat walks the parse tree.  Even though we have fixed the configure\nscript to disable it by default, people still ask questions about how to\nbuild it, but it doesn’t seem that they are doing that to work on it but\nbecause they think it will make Octave code run faster (it never did,\nexcept for some extremely simple bits of code as examples for\ndemonstration purposes only).  The following functions related to the\nJIT compiler have also been removed: `debug_jit`, `jit_enable`,\n`jit_failcnt`, and `jit_startcnt`.\n\n### Old release news\n\n- [Octave 6.x](NEWS.6.md)\n- [Octave 5.x](NEWS.5.md)\n- [Octave 4.x](NEWS.4)\n- [Octave 3.x](NEWS.3)\n- [Octave 2.x](NEWS.2)\n- [Octave 1.x](NEWS.1)\n"
  },
  {
    "path": "etc/NEWS.8.md",
    "content": "Summary of bugs fixed for version 8.5.0 (tbd):\n----------------------------------------------------\n\nFor (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\n### Improvements and fixes\n\n### GUI\n\n### Build system / Tests\n\n### Documentation\n\n\nSummary of bugs fixed for version 8.4.0 (2023-11-05):\n----------------------------------------------------\n\nFor (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\n### Improvements and fixes\n\n- `mkoctfile`: Skip parsing for less flags (bug #64590).\n- Fix getting number of non-zero elements in SuiteSparse matrices.\n- `delaunayn.m`: Avoid erroneous simplex removal for integer inputs\n  (bug #64658).\n- `delaunayn`: Add precision loss warning for large int inputs (bug #64658).\n- `delaunayn`: Also warn for negative integers with large magnitude\n  (bug #64658).\n- Correctly load all-zero sparse matrices from text files (bug #64696).\n- Allocate correct storage for interleaved complex mxArray objects\n  (bug #64687).\n- `mkoctfile`: Prefer parsing over passing on argument after unknown argument\n  (bug #64725).\n- `fft`: Avoid segmentation fault with ND-arrays (bug #64729).\n- `fft`: Avoid overwriting input for inplace operations (bug #64733).\n- `intersect.m`: Correct third output with `\"stable\"` flag (bug #60347).\n- Avoid use-after-free issue in parser (bug #60882).\n- `betainc.m`: Improve integer input logic and validation (bug #64726).\n- `webread`: Apply timeout also for initial connection (bug #64826).\n\n### GUI\n\n### Build system / Tests\n\n- `mkpp.m`: Remove stray text causing error with demo code.\n- Ensure that new test for saving sparse matrices writes a text file.\n- Search for tests in and install octave-value template sources (bug #64696).\n\n### Documentation\n\n- Correct variable name typo in documentation of `slice()`.\n- Expand documentation for `gcd()` and `lcm()`.\n- `datevec`: Clarify that heuristics are used to detect the format of a date\n  string (bug #64563).\n- `datenum`: Add help text that inputs can be arrays, add examples\n  (bug #54679).\n- `datevec`: Add help text that inputs can be arrays (bug #54679).\n- Describe various pitfalls with floating point ranges (bug #64692).\n- Add range example and some copyedits.\n\n\nSummary of bugs fixed for version 8.3.0 (2022-08-08):\n----------------------------------------------------\n\n### Improvements and fixes\n\n- `undo_string_escapes`: Return `'\\0'` for `NUL` byte input (bug #64051).\n- Stop excessive memory usage for minor grid ticks (bug #64017).\n- Include needed headers in installed `.cc` files (bug #63922).\n- Fix floating point exception when sparse array reshaped to `0x0` (bug\n  #64080).\n- `unicode2native`: Fix conversion to UTF-16 (bug #64139).\n- `memory`: Fix execution on Cygwin.\n- `uniconv-wrappers`: Avoid freeing uninitialized pointer (bug #64182).\n- `lo-regexp.cc`: Only include PCRE2/PCRE headers if feature test succeeded\n  (bug #64172).\n- Fix segfault when `saveobj()` used with old-style class files (bug #64220).\n- Fix restoring breakpoints from `dbstatus` breakpoint structure (bug #64271).\n- `colorbar.m`: Fix undefined variable `d` (bug #64287).\n- Reset all axes properties except `'Units'` and `'Position'` with\n  `cla ('reset')`.\n- `unicode2native.m`: Restore support for one input parameter (bug #64331).\n- `native2unicode`, `unicode2native`: Support empty second argument (bug\n  #64331).\n- `fullfile.m`: Return empty cell for input with empty cell (bug #64377).\n- `audioplayer.m`: Emit error if input data `Y` is empty (bug #64379).\n- Remove obsolete callback constructor code for `@audioplayer` and\n  `@audiorecorder` (bug #64379).\n- Avoid false detection of \"non-real pivot\" in `ichol()` (bug #63785).\n- Fix building against SuiteSparse 7.1.0 when SPQR is disabled (bug #64446).\n- `ellipsoid.m`: Avoid returning geometry data unless it is explicitly\n  requested to avoid overwriting `ans`.\n- `subsasgn`: Avoid panic on invalid field names (bug #64213).\n- `lex.ll`: Remove `$` as a valid character for identifiers.\n- `fileparts.m`: Allow for relative path on different drive on Windows (bug\n  #64462).\n- `datevec.m`: Add some ISO 8601 conform formats (patch #9964).\n- `delaunayn.m`: Avoid erroneous simplex removal for integer inputs (bug\n  #64658).\n\n### Build system / Tests\n- `betaincinv.m`: Slightly increase test tolerance (for macOS 13).\n- `colorbar.m`: Add tests (bug #64287).\n- `sparse-qr.cc`: Fix compatibility with SuiteSparse 7.1.0 / CXSparse 4.0.4.\n- `pcg.m`: Use eps tolerance in test for `ishermitian` (bug #63787).\n- `fileparts.m`: Overhaul BISTs.\n\n### Documentation\n- Return documentation for `help properties` (bug #64067).\n- Add note to `isprime.m` on inputs over 2^64.\n\n\nSummary of bugs fixed for version 8.2.0 (2023-04-13):\n----------------------------------------------------\n\nFor (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\n### Improvements and fixes\n- `pr-output.cc`: Fix output for `format native-bit` (bug #63940).\n- Fix evaluation of `&` and `|` expressions in conditional contexts (bug\n  #63935).\n- Avoid clang warning about very unlikely buffer overflow.\n- `mpoles.m`: Overhaul function and use absolute tolerance for zero poles\n  (bug #63937).\n- `perms.m`: Change `\"unique\"` output order to reverse lexicographic to\n  match non-unique order (bug #63962).\n- Remove trailing `'\\r'` from curl dir list (bug #63851).\n- `fopen`: Use \"UTF-8\" as default encoding for `fopen` (bug #63930).\n- Don't use encoding facet when writing bytes to stream (bug #63931).\n- `fopen`, `unicode2native`: Fix converting the encoding of short char\n  arrays with invalid UTF-8 (bug #63930).\n- `fopen`: Try to gather complete UTF-8 surrogates when converting\n  encoding (bug #63930).\n- Fix display of scalar complex variables with mixed `Inf`/`NaN` and\n  floating point values (bug #63961).\n- `fopen`: Do not convert encoding for file streams with libc++\n  (bug #63930).\n\n### GUI\n- Speedup loading and saving preferences dialog (bug #63909).\n\n### Build system / Tests\n- `inpolygon.m`: Fix demo code (bug #63865).\n- `if.tst`: New test for bug #63935.\n- `acinclude.m4`: Correct typo in `#define PCRE2_CODE_UNIT_WIDTH`.\n- `lu`: Add self-test with complex valued input.\n- Disable visibility flags by default (bug #61855, bug #63916).\n- Check whether using STL from LLVM or Apple (bug #63930).\n\n### Documentation\n- Improve documentation for `linspace` and `logspace` functions.\n- Correct and improve documentation for `sparse()` function.\n\n\nSummary of important user-visible changes for version 8 (2023-03-07):\n--------------------------------------------------------------------\n\n### General improvements\n\n- Octave's libraries are now built using symbol visibility by default.\n  That means that fewer symbols are exported from these libraries.\n  Configure with `--disable-lib-visibility-flags` to export all symbols\n  (as in previous versions).\n\n- `filter` is now 5X faster, which also speeds up `deconv`, `fftfilt`\n  and `arma_rnd` by the same amount.\n\n- `integral` can now return a second argument containing the error\n  estimate from the underlying integrator.\n\n- `perms` now accepts a second argument \"unique\" to return only unique\n  permutations for inputs with repeated elements.  It is faster and\n  takes less memory to call `perms ('aaaabbbbcccc', \"unique\")` than to\n  call `unique (perms ('aaaabbbbcccc'), \"rows\")`.\n\n- `quadgk` can now accept the `ArrayValued` input parameter to handle\n  array-valued input functions.\n\n- `delaunayn` now has consistent trivial simplex checking and removal\n  for all input dimensions, simplex checking 3D inputs is now\n  vectorized, and >3D simplex checking performance has been improved.\n  Simplexes points are now ordered so they will all have positive\n  outward normal vectors.  Input type checking has also been added for\n  improved error handling.\n\n- `factor` now factorizes all 64-bit integers in roughly the same time.\n  Previously, the product of two large primes took much longer to factorize\n  than highly composite inputs.\n\n- `Refine` option is now implemented in functions `ode45`, `ode23`,\n  and `ode23s`.\n\n- Octave is now compatible with PCRE2 (UTF-8).  PCRE2 is preferred over PCRE\n  if both are installed.  Configure with `--without-pcre2` if you prefer Octave\n  to use PCRE in this case.\n\n- `mean` now internally processes data as type double to reduce likelihood of\nhitting overflow or precision limits with other types (bug #63848).\n\n### Graphical User Interface\n\n- The GUI has a dark style and several new icons in toolbars for better\n  visibility and higher contrast.\n\n- A new terminal widget has been added for the GUI.  It is still experimental\n  and is disabled by default.  It can be enabled with the command line\n  parameter `--experimental-terminal-widget`.\n\n- More fonts for the documentation browser are included.\n\n### Graphics backend\n\n- When printing, the option `-svgconvert` is now the default.  If you want to\nuse the more limited EPS-based tool chain (the former default)&mdash;e.g., if\nyou encounter inaccurate image rendering&mdash;you can pass the `-nosvgconvert`\noption to the `print` function.\n\n- Additional properties have been added to the `figure` graphics object:\n    * `\"innerposition\"` (equivalent to `\"position\"`)\n    * `\"windowstate\"` (not yet implemented)\n\n- Legend now features a new property `\"itemhitfcn\"`, allowing the\n  execution of a callback function when a legend item is clicked.\n\n### Matlab compatibility\n\n- `inline` functions now support all Matlab methods.  The performance\n  of `inline` functions has also been improved.\n\n- `sub2ind` now supports index values outside of the size specified by\n  the subscripts.\n\n- `cylinder` now accepts a scalar for the radius argument.\n\n- `clock` now has an optional second output `ISDST` which indicates if\n  Daylight Savings Time is in effect for the system's time zone.\n\n- `print` now accepts option `-image` to specify the \"opengl\" renderer\n  and `-vector` to specify the \"painters\" renderer.\n\n- `format` now accepts the option \"default\", which is equivalent to\n  calling `format` without any options to reset the default state.\n\n- `quadgk` now stops iterating when `error <= tolerance` while the previous\n  condition was `error < tolerance`.\n\n- `mean` now accepts vector dimensions and options to handle `NaN` values.\n  The option `\"a\"` (arithmetic mean), `\"g\"` (geometric mean), and `\"h\"`\n  (harmonic mean) are no longer accepted, only the arithmetic mean is computed.\n  For the geometric and harmonic mean, please use respective functions\n  `geomean` and `harmmean` from the Octave Statistics package.\n\n- `var` and `std` now optionally output a second argument containing the mean\n  or weighted mean.\n\n- `integral` can now accept the 'ArrayValued' option in combination with\n  'RelTol' and 'WayPoints'.\n\n- File system operations that remove files (e.g., `unlink` or `rmdir`) now also\n  remove files that have their read-only file attribute set on Windows.\n\n- The default state for certain graphics properties has been made\n  consistent with Matlab.\n\n        Object      | Property         | Default State\n        ------------|------------------|------------\n        figure      | \"dockcontrols\"   | \"on\"\n\n- `ode45`, `ode23`, and `ode23s` have improved results for options `Events`,\n  `OutputFcn`, and `Refine`, along with corrected orientation of struct\n  outputs.\n\n- *Early notice of future breaking changes*:  Due to many user requests that\n  Octave should have a Matlab-compatible string class, there is work under way\n  to implement a string class that will differ from a vector of characters.  In\n  Octave, single-quoted character arrays are currently compatible with Matlab,\n  but double-quoted forms are not.  Currently in Octave, both 'foo' and \"foo\"\n  are largely interchangeable, barring certain escape sequence interpretations\n  such as \"\\n\" (converted to a single newline character) as opposed to '\\n'\n  (two separate characters).  Matlab’s single-quoted character arrays and\n  double-quoted strings do not process backslash escape sequences, unlike many\n  other languages, and those escape sequences are instead processed by\n  individual functions such as `fprintf`.\n\n  Octave's behavior is likely to change in future as a consequence of\n  implementing Matlab-style string syntax.  For example, 'foo' will remain a\n  three-element character vector, but \"foo\" will become a single-element string\n  object.  Some backslash escape sequences are likely to differ from their\n  current Octave behavior, but will achieve greater Matlab compatibility.  The\n  exact implementation is a work in progress, and may or may not include\n  methods of preserving backward compatibility.\n\n  *What this means for user code*: If your code currently relies on\n  double-quoted strings (e.g., \"foo\") representing character vectors as\n  opposed to string objects, and if you intend to update to a future version of\n  Octave incorporating the above changes, then consider replacing all\n  double-quoted strings with single-quoted strings in your code over time\n  (e.g., replace \"foo\" with 'foo'). Single-quoted strings are expected to\n  retain current behavior.  Further, if your code relies on backslash escape\n  sequence interpretation in double-quoted strings (except for special cases\n  like the `printf` family), that code may need to change as well.\n\n\n### Alphabetical list of new functions added in Octave 8\n\n* `clearAllMemoizedCaches`\n* `matlab.lang.MemoizedFunction`\n* `memoize`\n* `normalize`\n* `pagectranspose`\n* `pagetranspose`\n* `uifigure`\n\n### Deprecated functions, properties, and operators\n\nThe following functions and properties have been deprecated in Octave 8\nand will be removed from Octave 10 (or whatever version is the second\nmajor release after 8):\n\n- Functions\n\n        Function               | Replacement\n        -----------------------|------------------\n        shift                  | circshift\n        sparse_auto_mutate     | none (see below)\n\n- The `sparse_auto_mutate` function no longer has any effect on Octave's\n  behavior.  Previously, after calling `sparse_auto_mutate (true)`,\n  Octave would automatically convert sparse matrices to full when a\n  sparse matrix required more memory than simply using full matrix\n  storage.  This setting was `false` by default for compatibility with\n  Matlab.  Now you must manually convert to full storage when desired.\n\n- Properties\n\n  The following property names are discouraged, but there is no fixed\n  date for their removal.\n\n        Object           | Property    | Replacement\n        -----------------|-------------|------------\n        uimenu           | label       | text\n        uimenu           | callback    | menuselectedfcn\n\nThe following functions were deprecated in Octave 6 and have been removed\nfrom Octave 8.\n\n- Functions\n\n        Function     | Replacement\n        -------------|------------\n        runtests     | oruntests\n\n- The environment variable used by `mkoctfile` for linker flags is now\n  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` was deprecated in Octave 6,\n  and will be removed in a future version of Octave.\n\nSummary of bugs fixed for version 8.1.0 (2023-01-22):\n----------------------------------------------------\n\n- Improved input validation and/or output handling for `poly`, `pinv`, `patch`,\n  `fill`, `fill3`, `qp`, `datevec`, `textscan`, `sub2ind`, `qr`, `airy`,\n  `regexp`, `dec2bin`, `dec2hex`, `mean`, and many others.\n- Improved performance for `complex`, `fftw`, `delaunayn`, `isfield`, `tsearch`,\n  sparse matrix exponentiation, other sparse operations, and many others.\n- Overhauled `@audiorecorder` and `@audioplayer` classes.\n\n### Old release news\n\n- [Octave 7.x](NEWS.7.md)\n- [Octave 6.x](NEWS.6.md)\n- [Octave 5.x](NEWS.5.md)\n- [Octave 4.x](NEWS.4)\n- [Octave 3.x](NEWS.3)\n- [Octave 2.x](NEWS.2)\n- [Octave 1.x](NEWS.1)\n"
  },
  {
    "path": "etc/NEWS.9.md",
    "content": "For (bug #XXXXX) see https://savannah.gnu.org/bugs/?XXXXX\n\nSummary of bugs fixed for version 9.5.0 (tbd):\n-----------------------------------------------------\n\n### Improvements and fixes\n\n### GUI\n\n### Build system / Tests\n\n### Documentation\n\n\nSummary of bugs fixed for version 9.4.0 (2025-02-05):\n-----------------------------------------------------\n\n### Improvements and fixes\n- Fix error in calculation of file timestamp on Windows (bug #31080).\n\n### GUI\n- Update Spanish translation file (bug #66616).\n- Update Brazilian Portuguese translation file (bug #66554).\n\n### Build system / Tests\n- `cellfun`: Add test for function failing to return requested output\n  (bug #66642).\n- `arrayfun`:  Add test for function failing to return requested output\n  (bug #66642).\n\n### Documentation\n- Clarify default editor difference between CLI and GUI (bug #66703).\n\n\nSummary of bugs fixed for version 9.3.0 (2024-12-12):\n-----------------------------------------------------\n\n### Improvements and fixes\n\n- `jupyter-notebook`: Avoid error if evaluated code closes an existing figure\n  window.  Use `unwind_protect` block to ensure figure and tempfile cleanup\n  actions occur (bug #65644).\n- `uitable`: Fix updating value with combo box selection (bug #65873).\n- `movfun`:  Correct output shape of n-D arrays when operating on dimensions\n  higher than 2.  This will affect all moving window functions (`movmad`,\n  `movmax`, `movmean`, `movmedian`, `movmin`, `movprod`, `movstd`, `movsum`,\n  and `movvar`) (bug #65927).\n- `movvar` and `movstd`: Use correct default value of 0 if an empty array is\n  specified for `opt` to maintain consistent behavior with `var` and `std`.\n  Improve input validation to ensure `opt` is one of 0, 1, or []. (bug #66021).\n- `fopen`: Convert identifier for locale charset to lower-case characters\n  (bug #65963).\n- `regexp`: Avoid integer underflow with unsigned integers.\n- `interp2`: Provide a meaningful error message if the input reference array\n  is a vector (bug #66086).\n- `struct2hdl.m`: Do not delete previously added axes children (bug #66221).\n- `print`: Fix regression in pdf fonts (bug #66306).\n- `legend` icons now inherit the \"facelalpha\" property to match appearance of\n  patch and surface graphics objects (bug #66314).\n- `barh` properties now better match equivalent `bar` plot.  Changing\n  `horizontal` property for a bar or barh plot now consistently updates\n  properties to match redrawn plot (bug #65671).\n- Tick mark labels are now correctly updated after changing x or y data for\n  `bar` and `barh` plots (bug #65734).\n- `hdl2struct.m`: Fix missing legend markers (bug #65904).\n- Enable FLTK graphics toolkit on macOS if not multi-threaded (bug #66482).\n- Do not execute PKG_ADD script in current directory (bug #66477).\n\n### GUI\n\n- Update Brazilian Portugese translation file (bug #66337).\n- Fix some missing white spaces in documentation viewer (bug #66459).\n\n### Build system / Tests\n\n- `jupyter-notebook` test no longer fails if a figure window is open\n  (bug #65644).\n- `movmad`, `movmax`, `movmean`, `movmedian`, `movmin`, `movprod`, `movslice`,\n  `movstd`, `movsum`, `movvar`: Add BISTs for general function operation.\n- `interp2`, `interp3`, `interpn`: Add more tests for non-numeric inputs\n  (bug #66086).\n- Update formatting of movXXX functions.\n\n### Documentation\n\n- `load`: Correct documentation of `-v7.3` and `-hdf5` options (bug #42530).\n- `interp2`, `interp3`, `interpn`: Specify that inputs need to be numeric\n  (bug #66086).\n- `error`: Document the `ID` argument (bug #66015).\n- `sqp`: Clarify size requirements of input arguments `lb` and `ub`\n  (bug #66421).\n- Eliminate double period at end of \"mode\" graphics property documentation.\n- Fix makeinfo errors for comment block keywords (bug #66428).\n\n\nSummary of bugs fixed for version 9.2.0 (2024-06-01):\n-----------------------------------------------------\n\n### Improvements and fixes\n\n- `hist.m`: Add input validation for `Y` restricting it to 2-D array\n  (bug #65478).  Avoid error when `Y` value range is very small (bug #65714).\n- `cross.m`: Add input validation for `dim` restricting it to a numeric\n  integer valued scalar (bug #65544, bug #65527).\n- `getframe.m`: Respect pixel ratio (high DPI) of screen with figure\n  (bug #65540).\n- `legend.m`: Fix error if root property `\"showhiddenhandles\"` is `\"on\"`\n  (bug #65442)\n- `savepath.m`: Correctly handle packages without binaries (bug #65559).\n- Correctly scale figure position on screen with DPI scaling (high DPI).\n- `profile ('on')` now clears any existing profile data as the documentation\n  states (bug #65595).\n- Fix segmentation fault when trying to set breakpoint in non-existent method\n  of `classdef` class (bug #65610).\n- Improve default display of `classdef` properties (bug #62432).\n- Avoid crash with Qt6 6.7.0 (bug #65605).\n- `bar.m`: Catch input number validation error.\n- Prevent OOM crash or segmentation fault in `sort ()` when `dim` equals `Inf`\n  (bug #65712).\n- `legend.m`: Avoid setting more colors than coordinates for `patch` objects\n  (bug #65632).\n- `inputParser.m`: Allow default classdef objects which overload `struct`\n  (bug #65667).\n- Preserve `\"position\"` property of figure when object is `reset()`\n  (bug #65750).\n- `hist.m`: Avoid error when `y` value range is very small (bug #65714).\n- `barh`: Add input validation check for `nargin < 1`.\n\n### GUI\n\n- Use first word for options in right-click menu of command window widget\n  (bug #65518).\n- Set `DontUseNativeDialog` flag as first property in `QFileDialog`.\n- Explicitly raise non-modal message boxes ensuring visibility.\n- Save and restore splitter state of documentation widget.\n- Allow executing new files from built-in editor with F5 (bug #65548).\n- Allow unbinding GUI shortcuts (bug #65580).\n- Fix restoring headers in file browser and workspace view (bug #65030).\n- File dialogs of the built-in editor are now modal.\n- Fix dragging editor from main window into floating state (bug #65725).\n\n### Build system / Tests\n\n- Avoid overriding `save_*` variables from outer scope (bug #65476).\n  This fixes an error that might have lead to overlinking of shared libraries\n  (e.g., `.oct` files). Consider rebuilding shared libraries that have been\n  built with Octave 9.1.0.\n- Add BIST for `is_valid_file_id.m` (bug #65543).\n- Update metainfo.xml with new fields for AppStream 1.0 (bug #65355).\n- Show result of check for `std::pmr::polymorphic_allocator` in configure\n  summary.\n- Run test program for polymorphic allocators if possible instead of a simple\n  build check.\n- Speed up BIST for the central part of `convn` with `'full'` shape.\n- Require Qt Widgets module when building the GUI (bug #65625).\n- `bug-53027.tst`: Delete temporary file after test is done (bug #53027).\n- Avoid build error with GCC 14 when targeting Windows.\n- Try to clean up after BIST also in case test failed (bug #53027).\n- `bar.m`, `barh.m`: Add plotting BISTs (bug #65671).\n- Check if C and Fortran compilers accept `-fexceptions` flag (bug #65767).\n  This affects building Octave itself from sources and also how .mex or .oct\n  files are built by `mex` and `mkoctfile`.\n\n### Documentation\n\n- Describe shape of outputs for `hist` (bug #65471).\n- Simplify programming notes for `patch` objects (bug #65421).\n- `vecnorm.m`: Add missing parenthesis to equation in docstring.\n- Add example to Minimizers section on using anonymous functions to pass\n  additional arguments to functions called by minimizer functions\n  (`fminsearch`, `fminbnd`, `fminunc`).\n- Add application notes in `fminsearch`, `fminbnd`, `fminunc` indicating the\n  preferred way to pass parameters is through anonymous functions.\n- Update remaining copyright statements to 2024.\n- Minor fix for `setappdata.m`.\n- Section \"Assignment Expressions\": Use `@emph` rather than `@i` macro for\n  better rendering in plaintext formats.\n- Section \"Running Octave\": Tell new users how to start Octave on their\n  computers.\n- `tsearch`: Add programming note about expected performance.\n\n### Deprecated functions, properties, and operators\n\n- `fminsearch` parameter passing:  A legacy, undocumented, and only partially\n  supported syntax for passing parameters to the minimized function `fcn`\n  called by `fminsearch` by appending them to the input argument list has\n  functioned intermittently since Octave 4.4.0.  Due to conflicts with other\n  compatibility-required input methods the documentation of this syntax was\n  removed in Octave 5.1.0, and the remaining functionality will be completely\n  removed in Octave 10.  The preferred method of passing parameters to any of\n  the minimization functions (including `fminsearch`, `fminbnd`, and `fminunc`)\n  is through the use of anonymous functions.  Specific examples of this can be\n  found in the \"Minimizers\" section of the GNU Octave manual.\n\n\nSummary of important user-visible changes for version 9 (2024-03-12):\n---------------------------------------------------------------------\n\n### General improvements\n\n- `dec2base`, `dec2bin`, and `dec2hex` have all been overhauled.  All three\n  functions now accommodate negative inputs and fractional inputs, and repeated\n  code between the functions has been reduced or eliminated.  Previously only\n  `dec2bin` and `dec2hex` accepted negative inputs but `dec2base` did not, and\n  none of the three accepted fractional inputs.  Now, `dec2base (100*pi, 16, 4,\n  6)`, for example, returns a base-16 string with four places for the integer\n  part and six places for the fractional part.  Omitting the number of decimal\n  places (the fourth input) retains old behavior for backward compatibility,\n  except that non-integer inputs will no longer produce errors.\n\n- `quiver` and `quiver3` now properly plot non-float numeric inputs by\n  internally casting them to 'double' (bug #59695).  Both functions now honor\n  a previously ignored scaling factor input when there is only a single arrow\n  (bug #39552), and `quiver3` no longer produces an error when a scaling factor\n  is given without x and y inputs.  Both functions now also accept a scale\n  factor of \"off\" which is equivalent to setting it to 0.  When a linestyle\n  with a base marker is set suppressing arrowhead display, subsequent\n  name-value property pairs in the `quiver`/`quiver3` function call will no\n  longer turn arrowhead display back on (bug #64143).  The linewidth property\n  now also affects the line width of the base marker.\n\n- Classdef files now support breakpoints inside them.\n\n- The `inputParser` function has been re-architected for a 60% performance\n  improvement.\n\n- The `perms` function has been made faster.\n\n- The `audiowrite` function now supports writing to MPEG audio\n  formats---including MP3---if the `sndfile` library supports it.\n\n- `oruntests`: The current directory now changes to the directory\n  containing the files with the tests for the duration of the test.  This\n  aligns the behavior of this function with Octave's test suite.  This also\n  means that the file encoding specified in the `.oct-config` file for the\n  respective directory is taken into account for the tests.\n\n### Graphical User Interface\n\n- The Graphical User Interface (GUI) of Octave is now compatible with Qt6.  Qt6\n  is selected by default if the necessary Qt modules are detected and the used\n  compiler is compatible.  Support for building with Qt5 is still available but\n  might be removed in a future version of Octave.  Qt5 is used if configuring\n  with `--with-qt=5` or as a fallback if Qt6 cannot be used.\n\n### Graphics backend\n\n- The FLTK backend is not maintained and its use is discouraged.  The\n  recommended backend is qt.  Enabling the fltk backend with `graphics_toolkit\n  fltk` now emits a warning.\n\n- The `set` function now accepts any combination of name/value pairs, cell\n  array of names / cell array of values, or property structures.  This change\n  is Matlab compatible.\n\n- When the `hold` function is used without arguments to toggle the current\n  state, the resulting value is now displayed in the Command Window for\n  informational purposes.\n\n- The axes graphics property `\"TickDir\"` now accepts the option `\"none\"`, which\n  will not draw tick marks but will still draw tick labels.\n\n- Stricter checks are performed for valid dimensions of the color data\n  properties `\"CData\"` and `\"FaceVertexCData\"` when rendering `patch` objects.\n\n### Matlab compatibility\n\n- The `inputParser` function now implements the `PartialMatching` property for\n  `Parameter` and `Switch` names.  For Matlab compatibility, `PartialMatching`\n  is now set to true by default which may change the behavior of existing code.\n\n- Overhauled `mean`, `median`, `var`, and `std` functions have been imported\n  from statistics package v1.5.4 to compatibly implement 'nanflag'\n  (bug #50571), 'all' (bug #58116), and 'vecdim' (bug #58089) options, preserve\n  output class, and match expected output behavior for empty (bug #50583) and\n  sparse inputs (bug #63291).  Both `median` and `mean` can handle large\n  integer values without overflow or precision concerns (bug #54567), and\n  `mean` avoids errors due to limits of single precision by processing as\n  doubles (bug #63848).  `median` has also adopted the 'outtype' option from\n  `mean`.\n\n- Code such as `A = ones (3, 3); A(:, :, 1) = []` is now Matlab compatible.\n\n- `mad` function now produces Matlab compatible output using improved `mean`\n  and `median` functions.  'vecdim' and 'all' options are now supported.  `mad`\n  ignores all NaN values (using 'omitnan' mean/median option) and produces\n  expected output behavior for empty inputs.\n\n- `mode` now produces Matlab compatible output for empty inputs (bug #50583).\n\n- `linspace` and `logspace` now handle `Inf` inputs in a Matlab compatible way.\n\n- `normalize` now produces Matlab compatible output for inputs containing NaN\n  values (bug #50571).\n\n- `cov` now processes the input form cov(x,y) with two separate data arrays x\n  and y, as cov(x(:),y(:)) to maintain Matlab compatibility.  It also accepts a\n  NANFLAG option to allow ignoring NaN entries in input data (bug #50571) and\n  produces Matlab compatible outputs for empty inputs (bug #50583).  `corr` and\n  `corrcoef` internal code has been adapted to the new `cov` behavior with no\n  change to user interface.  Packages using the octave core's `cov` that rely\n  on the previous calling form may need to make similar adaptations.  Calls for\n  cov(x) with a vector x expecting a scalar return can get the previous results\n  from `cov(x)(2)`, and calls to cov(x,y) with x and y matrices expecting\n  columnwise covariance calculation can obtain the previous results using\n  `cov([x,y])(1:nx, nx+1:end)`, where nx = columns(x).\n\n- `qz` now handles input and output arguments in a Matlab compatible way.  It\n  always computes the complex QZ decomposition if there are only two input\n  arguments, and it accepts an optional third input argument 'real' or\n  'complex' to select the type of decomposition.  The output arguments are\n  always in the same order independently of the input arguments, and the\n  generalized eigenvalues are no longer returned (one can use the `ordeig`\n  function for that purpose).  The optional reordering of the generalized\n  eigenvalues has been removed (one can use the `ordqz` function for that\n  purpose).\n\n- `pcolor` now sets the axes limits to be just large enough to display the\n  plotted data (equivalent of `axis tight`).\n\n- `xlim`, `ylim`, `zlim` functions can now query or set the limit calculation\n  method which is one of \"tickaligned\", \"tight\", or \"padded\".\n\n- `optimget` and `optimset` now produce an error on an ambiguous match of an\n  incomplete option name instead of emitting a warning.\n\n- `datevec` when provided a date format will match date string characters up to\n  the length of the format string.  A date vector will be returned as long as\n  the characters up to the format string length are a perfect match, and any\n  trailing characters in the date string will be ignored. (bug #42241)\n\n- `unwrap` now produces compatible output for inputs with non-finite elements\n  (Inf, NaN, NA).  Such elements will now retained in the output but skipped\n  over by the wrapping calculation.  The function also permits logical inputs\n  and specified operating dimensions larger than the number of dimensions in\n  the input array.\n\n- The default string length for the function `rats` has changed from 9 to 13.\n\n- *Continuing reminder of future breaking changes*:  There is ongoing work\n  to implement a Matlab compatible string class that will differ from a vector\n  of characters.  In Octave, single-quoted character arrays are currently\n  compatible with Matlab, but double-quoted forms are not, and are likely to\n  change in future as a consequence of implementing Matlab-style string syntax.\n  For example, 'foo' will remain a three-element character vector, but\n  \"foo\" will become a single-element string object.\n\n  *What this means for user code*: If your code currently relies on\n  double-quoted strings (e.g., \"foo\") representing character vectors as\n  opposed to string objects, then start replacing all double-quoted strings\n  with single-quoted strings in your code over time (e.g., replace \"foo\" with\n  'foo').  Single-quoted strings will retain their current behavior.  Further,\n  if your code relies on backslash escape sequence interpretation in\n  double-quoted strings (except in special cases like the `printf` family),\n  that code may need to change as well.\n\n### Alphabetical list of new functions added in Octave 9\n\n* `isenv`\n* `ismembertol`\n* `isuniform`\n* `tensorprod`\n\n### Deprecated functions, properties, and operators\n\nThe following functions and properties have been deprecated in Octave 9 and\nwill be removed from Octave 11 (or whatever version is the second major release\nafter 9):\n\n- Functions\n\n        Function                         | Replacement\n        ---------------------------------|-----------------------------------\n        interpreter::initialized         | octave::is_initialized\n        octave::same_file                | octave::sys::same_file\n        octave::interpreter_initialized  | octave::interpreter_is_initialized\n\n- Properties\n\n  The following property names are discouraged, but there is no fixed\n  date for their removal.\n\n        Object           | Property    | Replacement\n        -----------------|-------------|------------\n\n- Core\n\n    * The `idx_vector::bool()` function is obsolete and always returns true.\n      Any uses can simply be removed from existing code with no loss of\n      function.\n\n    * The `all_ok(const Array<octave::idx_vector>&)` function in `Array-util.h`\n      is obsolete and always returns true.  Any uses can simply be removed from\n      existing code with no loss of function.\n\n    * The member variable `octave_base_value::count` is deprecated and will be\n      removed from Octave 11.  Replace all instances with the new name\n      `m_count`.\n\nThe following features were deprecated in Octave 7 and have been removed from\nOctave 9.\n\n- Functions\n\n        Function                   | Replacement\n        ---------------------------|------------------\n        disable_diagonal_matrix    | optimize_diagonal_matrix\n        disable_permutation_matrix | optimize_permutation_matrix\n        disable_range              | optimize_range\n\n- Operators\n\n        Operator | Replacement\n        ---------|------------\n        .+       | +\n        .+=      | +=\n        .-       | -\n        .-=      | -=\n        **       | ^\n        **=      | ^=\n        .**      | .^\n        .**=     | .^=\n\n- Interpreter\n\n    * The use of `'...'` for line continuations *inside* double-quoted strings\n      has been removed.  Use `'\\'` for line continuations inside strings\n      instead.\n\n    * The use of `'\\'` as a line continuation *outside* of double-quoted\n      strings has been removed.  Use `'...'` for line continuations instead.\n\n    * Support for trailing whitespace after a `'\\'` line continuation has been\n      removed.  Delete unnecessary trailing whitespace.\n\n- For plot functions, the use of numbers to select line colors in shorthand\n  formats was an undocumented feature that was removed in Octave 9.\n\n- The environment variable used by `mkoctfile` for linker flags is now\n  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` was deprecated in Octave 6 and has\n  been removed.\n\nSummary of bugs fixed for version 9.1.0 (2024-03-12):\n----------------------------------------------------\n\n- Bugfixes to `whos -file`, `urlread`, `mat2cell`, `set`, `savepath`,\n  `loadpath`, `griddata`, and the general interpreter stack-handling.\n\n- Better input validation for `sparse`, `speye`.\n\n- Memory usage reduced for `movfun` and `movslice`.\n\n- Memory usage reduced when saving to file, preventing OOM and data loss.\n\n- Memory usage improved when plotting grid tick marks.\n\n- Memory management made more robust in the GUI code and with several GUI\n  components (variable editor, doc browser, etc).\n\n- Text encoding for non-UTF-8 generally made more robust.  File editor now\n  lists available encodings.\n\n- Octave on Windows now supports directory names and path names with non-ASCII\n  characters (other platforms had it already for years).  Windows paths now\n  also allow relative paths on different drives.\n\n- Several race conditions removed in signal handler.\n\n- Better compatibility when linking to `libc++`.\n\n- Performance and stability improvements: avoid unnecessary string\n  construction, use static casts instead of dynamic casts where possible,\n  eliminate various isolated crash conditions.\n\n### Old release news\n\n- [Octave 8.x](NEWS.8.md)\n- [Octave 7.x](NEWS.7.md)\n- [Octave 6.x](NEWS.6.md)\n- [Octave 5.x](NEWS.5.md)\n- [Octave 4.x](NEWS.4)\n- [Octave 3.x](NEWS.3)\n- [Octave 2.x](NEWS.2)\n- [Octave 1.x](NEWS.1)\n"
  },
  {
    "path": "etc/OLD-ChangeLogs/ChangeLog",
    "content": "2011-04-14  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Add colstyle to list of new functions for 3.4\n\n2011-04-08  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Deprecate studentize(), add new function zscore().\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Add perror, strerror to list of functions deprecated in 3.4\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Add cquad to list of functions deprecated in 3.4\n\n2011-03-24  Jarno Rajahalme  <jarno.rajahalme@gmail.com>\n\n\t* configure.ac: Try again with \"-ff2c\" if fortran compiler is\n\tfound incompatible. On OSX, try again with\n\tlibcruft/misc/blaswrap.c, if \"-ff2c\" also fails.\n\n2011-03-17  Iain Murray  <iain@iainmurray.net>\n\n\t* bootstrap.conf (gnulib_modules): Include nproc in the list.\n\n2011-03-08  Rik  <octave@nomad.inbox5.com>\n\n\t* mk-opts.pl: Recode using more modern Perl syntax.\n\tUse my, not local, for lexically-scoped variables.\n\tUse ALL_CAPITALS for global variable names.\n\tChange code to remove any warnings from Perl lint (-w).\n\tInline small subroutines for better readability.\n\tUse here documents and qq operator to avoid excessive backlashing of \".\n\tAdd more informative usage() information.\n\n2011-03-03  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Deprecate is_duplicate_entry.\n\n2011-03-01  Ben Abbott  <bpabbott@mac.com>\n\n\t* README.MacOS: Add Fink packages needed to support print output.\n\n2011-02-28  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Mention new functions isrow, iscolumn.\n\n2011-02-23  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* .hgignore: Cleanup and more files to be ignore that get added\n\tto the source during build time.\n\n2011-02-22  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: New explicit 'make check' target.\n\n2011-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Note that PCRE is now required to build Octave.\n\t* configure.ac: Improve check for PCRE, which is now required.\n\tDon't check for -lregex.\n\n2011-02-19  Rik  <octave@nomad.inbox5.com>\n\n\t* README.MacOS: Keep line length below 80, use 2 spaces to start\n\tsentences.\n\n2011-02-16  Richard Campbell  <rlcamp.pdx@gmail.com>\n\n\t* README.MacOS: Updated Readme.MacOS section 2.2.1 with results of test\n\tcompilation on vanilla machine.\n\n2011-02-15  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* configure.ac: Use AC_COMPILE_IFELSE to check for OpenGL\n\tsupport in FLTK.\n\n2011-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Update.\n\n2011-02-09  Ben Abbott  <bpabbott@mac.com>\n\n\t* README.MacOS: Spelling corrections.\n\n2011-02-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* README.MacOS: Fix FFTW CCFLAGS.\n\n2011-02-08  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Use indentation of 2 spaces rather than 3 in code examples.\n\n2011-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: New section for 3.6.  List deprecated functions that\n\thave been removed for 3.6.\n\n2011-02-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* README.MacOS: Add detail.\n\n2011-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Add note about subfunctions.\n\n2011-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* PROJECTS, README.devel: Use maintainers@octave.org instead of\n\toctave-maintainers@octave.org.\n\n2011-02-05  Rik  <octave@nomad.inbox5.com>\n\n\t* PROJECTS: Point to maintained list on Octave Wiki.\n\n2011-02-05  Rik  <octave@nomad.inbox5.com>\n\n\t* mkoctfile.in, octave-config.in: Update usage strings.\n\n2011-02-04  Rik  <octave@nomad.inbox5.com>\n\n\t* configure.ac: Add new doc/icons/Makefile to list of Makefiles to build\n\t* examples/Makefile.am: Move building of .desktop files and distribution\n\tof icons to doc/icons directory.\n\n2011-01-30  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Deprecate glpkmex function.\n\n2011-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* acinclude.m4 (OCTAVE_PROG_GHOSTSCRIPT): Update warning message.\n\n2011-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Remove code to print warning for missing ARPACK.\n\t* README.MacOS: Remove arpack from list of prerequisite software.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Deprecate saveimage function.\n\n2011-01-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* README.MacOS: Spelling corrections.\n\t* README.MacOS: Additional modifications for building Octave manually.\n\t* README.MacOS: Modify instructions for building Octave manually.\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for ARPACK.\n\t* common.mk (ARPACK_CPPFLAGS, ARPACK_LDFLAGS, ARPACK_LIBS):\n\tDelete variables.\n\t(do_subst_config_vals): Don't substitute them.\n\n2011-01-27  Ben Abbott  <bpabbott@mac.com>\n\n\t* README.MacOS: Modify instructions for MacPorts to \"deactivate\"\n\trather than \"uninstall\" octave.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* mk-opts.pl, mkoctfile.cc.in, mkoctfile.in: Untabify.\n\n\t* mkf77def.in, mk-opts.pl, mkoctfile.cc.in, structdemo.cc,\n\tunwinddemo.cc, fortdemo.cc, paramdemo.cc,\n\tcelldemo.cc,stringdemo.cc, hello.cc, embedded.cc, helloworld.cc:\n\tStrip trailing whitespace.\n\n2011-01-26  Ben Abbott  <bpabbott@mac.com>\n\n\t* README.MacOS: Modify organization, and update for MacPorts.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap: Update from gnulib sources.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (INSTALL_SCRIPT): Update commend about UGLY_DEFS.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* acinclude.m4 (OPENGL_LIBS): Don't add -L/usr/X11R6/LIB to\n\tLDFLAGS in test.  Bug #32160.\n\n2011-01-25  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Directly run makefile rules in doc/interpreter directory\n\tfor AUTHORS, BUGS, INSTALL.OCTAVE files.\n\n2011-01-25  John W. Eaton  <jwe@octave.org>\n\n\t* autogen.sh (AUTOMAKE): Add --foreign to the automake command.\n\tCheck for required GNU files here instead of having automake do it.\n\tExport AUTOMAKE so our options are actually used.\n\n2011-01-25  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (EXTRA_DIST): Remove ROADMAP from the list.\n\n2011-01-24  Rik  <octave@nomad.inbox5.com>\n\n\t* AUTHORS: Remove.  File now auto-generated from contributors.texi.\n\t* Makefile.am: Add rule for AUTHORS file.\n\n2011-01-24  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Note change in audio/mu2lin.\n\n2011-01-22  Tatsuro MATSUOKA  <tmacchant@yahoo.co.jp>\n\n\t* README.MinGW: Small corrections to documentation.\n\n2011-01-22  Rik  <octave@nomad.inbox5.com>\n\n\t* README.devel: Update for 3.4 release.\n\n2011-01-22  Rik  <octave@nomad.inbox5.com>\n\n\t* HACKING: Revise and incorporate all of file ROADMAP.\n\t* ROADMAP: Deleted.\n\n2011-01-22  Rik  <octave@nomad.inbox5.com>\n\n\t* README.Windows: Reference README.MinGW\n\t* README.MinGW: Replace placeholder with actual instructions\n\n2011-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.5.0+.\n\t(OCTAVE_API_VERSION_NUMBER): Now 44.\n\t(OCTAVE_RELEASE_DATE): Now 2011-01-22.\n\t(OCTAVE_COPYRIGHT): Update year.\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* README.Cygwin, README.MacOS, README.Windows, README.ftp: Update\n\tdocumentation files for 3.4 release.\n\n\t* README.MinGW: Create placeholder for new README file.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap: Update from gnulib sources.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac, NEWS: Update for backend -> graphics_toolkit change.\n\n2011-01-17  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Add quadcc to list of new functions added.\n\n2011-01-17  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.cc.in (main): Add + missing from previous change.\n\n2011-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.3.54.\n\t(OCTAVE_API_VERSION_NUMBER): Now 42.\n\t(OCTAVE_RELEASE_DATE): Now 2010-11-19.\n\n2011-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Add krylovb to deprecated function list.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Add replot to deprecated function list.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include filemode in the list.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* Update copyright notices for 2011.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap (gnulib_path): Set default gnulib path with ${x:=y},\n\tnot ${x=y}.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap, bootstrap.conf: Update from gnulib sources.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include mkstemp in the list.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_ARG_ENABLE(extra-warning-flags)):\n\tEliminate some code duplication.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_ARG_ENABLE(extra-warning-flags)): Check for\n\t-Wcast-qual and -Wcast-align and add them to WARN_CFLAGS and\n\tWARN_CXXFLAGS.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_ARG_ENABLE(extra-warning-flags)): Check for\n\t-Wpointer-arith, -Wmissing-prototypes, -Wstrict-prototypes, and\n\t-Wwrite-strings and add them to WARN_CFLAGS.  Check for\n\t-Wpointer-arith and add them to WARN_CXXFLAGS.\n\n2011-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* mk-opts.pl: Generate initialization lists and in-line code for\n\tcopying.\n\n2011-01-11  Rik  <octave@nomad.inbox5.com>\n\n\t* ROADMAP: Update guide to Octave directory structure.\n\n2011-01-11  Rik  <octave@nomad.inbox5.com>\n\n\t* README.mirrors: Update ftp links.\n\n2011-01-06  Rik  <octave@nomad.inbox5.com>\n\n\t* README: Update links and disk space requirements.\n\n2011-01-06  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* run-octave.in: Add a -gud option so that gdb can be called from\n\tEmacs's GUD mode and similar.\n\n2011-01-06  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in, mkoctfile.cc.in: Substitute and use LAPACK_LIBS.\n\tBug #32009.\n\n2011-01-04  Rik  <octave@nomad.inbox5.com>\n\n\t* README.MacOS: Update CFLAGS recommendation to use -O2.\n\n2011-01-04  Rik  <octave@nomad.inbox5.com>\n\n\t* README.gnuplot: Update recommendation to version 4.4.\n\n2011-01-04  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* README.Cygmin: Update build instructions before 3.4 release.\n\n2010-12-31  Kai Habel  <kai.habel@gmx.de>\n\n\t* NEWS: Add curl and divergence to new functions list.\n\n2010-12-20  Ben Abbott  <bpabbott@mac.com>\n\n\t* README.MacOS, Makefile.am: Update build insructions for MacOS and\n\tdistribute file in tarball.\n\n2010-12-20  Rik  <octave@nomad.inbox5.com>\n\n\t* README.Cray, SENDING-PATCHES, Makefile.am: Remove obsolete files.\n\n2010-12-18  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Deprecate sphcat and spvcat functions.\n\n2010-12-17  Rik  <octave@nomad.inbox5.com>\n\n\t* README.MacOS: New file documenting build instructions for Mac OSX.\n\n2010-12-09  Kai Habel  <kai.habel@gmx.de>\n\n\t* NEWS: Add pie3 to new functions list.\n\n2010-12-09  Marco Atzeri  <marcox_atzeri@yahoo.it>\n\n\t* configure.ac: Don't add -lwsock32 to LIBS on cygwin systems.\n\n2010-11-21  Kai Habel  <kai.habel@gmx.de>\n\n\t* NEWS: Add uigetdir, uigetfile, uiputfile.\n\n2010-11-19  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (bin_SCRIPTS): Remove run-octave from the list.\n\n2010-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.3.54+.\n\n2010-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.3.54.\n\t(OCTAVE_API_VERSION_NUMBER): Now 42.\n\t(OCTAVE_RELEASE_DATE): Now 2010-11-19.\n\n2010-11-15  Kai Habel  <kai.habel@gmx.de>\n\n\t* NEWS: Add saveas. Fix uimenu.\n\n2010-11-14  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* mkoctfile.cc.in: replace %OCTAVE_CONF_F77_INTEGER8_FLAG% with\n\t%OCTAVE_CONF_F77_INTEGER_8_FLAG%.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for nan.h.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AH_BOTTOM): Eliminate special case for __DECCXX:\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Eliminate special cases for nextstep.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Eliminate special checks for SCO systems.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Update deprecated function list with dispatch.\n\n2010-11-09  Rik  <octave@nomad.inbox5.com>\n\n\t* configure.ac: Fix typo where variable name was missing '$'\n\n2010-11-09  Rik  <octave@nomad.inbox5.com>\n\n\t* configure.ac: Properly m4 quote AS_HELP_STRING.\n\n2010-11-09  Rik  <octave@nomad.inbox5.com>\n\n\t* configure.ac: Remove redundant warning message when '--without-opengl'\n\toption used.\n\n2010-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for trunc, copysign, or _copysign.\n\n2010-11-08  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (--without-opengl): New configure option.\n\n2010-11-03  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include copysign in the list.\n\n2010-10-28  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Update deprecated function list with autocov and autocor.\n\n2010-10-25  Kai Habel  <kai.habel@gmx.de>\n\n\t* NEWS: Add uimenu.\n\n2010-10-24  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Update deprecated function list for version 3.4.\n\n2010-10-22  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (EXTRA_DIST): Include bootstrap and bootstrap.conf\n\tin the list.\n\n2010-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.3.53+.\n\n2010-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.3.53.\n\t(OCTAVE_API_VERSION_NUMBER): Now 41.\n\t(OCTAVE_RELEASE_DATE): Now 2010-10-19.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* examples/make_int.cc (Fmake_int): Don't pass arg to mlock.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* examples/structdemo.cc (Fstructdemo): Use octave_scalar_map\n\tinstead of Octave_map.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Style fixes.\n\n2010-09-29  John P. Swensen  <jpswensen@gmail.com>\n\n\t* configure.ac: Allow selection of GraphicsMagick or ImageMagick\n\tat configure time using \"--with-magick=\" option.\n\n2010-09-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* m4/ax_blas.m4: Update.\n\n2010-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* octave-bug.in, octave-bug.cc.in: Delete\n\t* Makefile.am (EXTRA_DIST): Remove them from the list.\n\t(bin_PROGRAMS): Remove octave-bug from the list.\n\t(octave_bug_SOURCES, nodist_octave_bug_SOURCES): Delete variables.\n\t(BUILT_SOURCES): Remove octave-bug.cc from the list.\n\t(bin_SCRIPTS): Remove octave-bug from the list.\n\t(octave-bug.cc, octave-bug): Delete rules.\n\n2010-09-20  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include mktime in the list.\n\n2010-09-18  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (BUILT_SOURCES): Include run-octave in the list.\n\n2010-09-16  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (SCRIPTS_EXE_SUFFIX) Delete variable and all uses.\n\t(BUILD_COMPILED_AUX_PROGRAMS): New variable.\n\t(AMCOND_BUILD_COMPILED_AUX_PROGRAMS): New Automake conditional.\n\t* Makefile.am (SCRIPTS_EXE_SUFFIX, BUILT_SHELL_FILES): Delete\n\tvariables and all uses.\n\t(bin_SCRIPTS, bin_PROGRAMS, mkoctfile_SOURCES,\n\tnodist_mkoctfile_SOURCES, octave_config_SOURCES,\n\tnodist_octave_config_SOURCES, octave_bug_SOURCES,\n\tnodist_octave_bug_SOURCES, BUILT_SOURCES): Define conditionally\n\tbased on AMCOND_BUILD_COMPILED_AUX_PROGRAMS.\n\t(noinst_SCRIPTS): New variable.\n\t(CLEANFILES): Include $(bin_PROGRAMS) $(bin_SCRIPTS)\n\t$(BUILT_SOURCES) in the list.\n\t(all-local): Also depend on $(bin_PROGRAMS) and $(noinst_SCRIPTS).\n\t(octave-bug.cc, octave-config.cc, mkoctfile.cc, octave-bug)\n\t(octave-config, mkoctfile): Make rules conditional on\n\tAMCOND_BUILD_COMPILED_AUX_PROGRAMS.\n\t(make-version-links, remove-version-links): Define different\n\trules conditional on AMCOND_BUILD_COMPILED_AUX_PROGRAMS.\n\n2010-09-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-09-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* m4/ax_blas_f77_func.m4: Update.\n\n2010-09-07  Ben Abbott  <bpabbott@mac.com>\n\n\t* acinclude.m4, configure.ac, m4/module.mk: Update acx_*.m4\n\tmacros to the newer ax_*.m4 versions.\n\t* ax_blas.m4, ax_lapack.m4, ax_blas_f77_func.m4,\n\tax_pthread.m4: Add files.\n\t* acx_blas.m4, acx_lapack.m4, acx_blas_f77_func.m4,\n\tacx_pthread.m4: Remove files.\n\n2010-09-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-08-21  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Add randi to list of new functions\n\n2010-08-09  John Swensen  <jpswensen@gmail.com>\n\n\t* mkoctfile.in: Add ability to pass -pthread through to linker.\n\n2010-08-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-08-09  Rik  <octave@nomad.inbox5.com>\n\n\t* examples/Makefile.am: Don't echo 'echo' command when building\n\toctave.desktop.\n\n2010-08-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-08-05  Rik  <octave@nomad.inbox5.com>\n\n\t* configure.ac: Change warning messages about freetype and fontconfig\n\tto reflect their requirement for native graphics.  Bug #30594.\n\n2010-08-05  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Remove distribution of emacs directory\n\n\t* emacs/info-emacs-info, emacs/info-emacs-octave-help, emacs/module.mk,\n\temacs/NEWS, emacs/octave-hlp.el, emacs/octave-inf.el,\n\temacs/octave-mod.el, emacs/octave-tags, emacs/octave-tags.1,\n\temacs/README, emacs/TODO: Remove from further hg checkouts.\n\n2010-08-05  Rik  <octave@nomad.inbox5.com>\n\n\t* ChangeLog: Correct date in version upgrade 3.3.52+ comment.\n\n2010-08-01  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.3.52+.\n\n2010-08-01  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.3.52.\n\t(OCTAVE_API_VERSION_NUMBER): Now 40.\n\t(OCTAVE_RELEASE_DATE): Now 2010-08-01.\n\n2010-07-30  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: add .gdbinit to the DISTCLEANFILES list\n\n2010-07-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Include list of new functions.\n\n2010-07-08  Rik  <octave@nomad.inbox5.com>\n\n\t* NEWS: Update with addition of engineering format.\n\n2010-07-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-06-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mkoctfile.in: F77_INTEGER_8_FLAG -> OCTAVE_CONF_F77_INTEGER_8_FLAG.\n\n2010-06-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.ac: Temporarily include F77_INTEGER_8_FLAG in FFLAGS for\n\tBLAS checking.\n\t* mkoctfile.in: Include F77_INTEGER_8_FLAG in ALL_FFLAGS.\n\t* mkoctfile.cc.in: Ditto.\n\n2010-05-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-05-11  Rik  <octave@nomad.inbox5.com>\n\n\t* configure.ac: Capitalize ARPACK in messages.\n\n2010-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* ROADMAP: Delete entry for villad.\n\n2010-04-26  Rik  <octave@nomad.inbox5.com>\n\n\t* configure.ac: fix bug with shell HERE document introduced in\n        previous change.\n\n2010-04-26  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* configure.ac: make all graphics related tests inter-dependent\n\n2010-04-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-04-16  David Bateman  <dbateman@free.fr>\n\n\t* PROJECTS: Update for new sparse functionality.\n\n2010-04-14  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* NEWS: Update.\n\n2010-04-08  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* Makefile.am (make-version-links, remove-version-links):\n\tUse SCRIPTS_EXE_SUFFIX for scripts, not EXEEXT.\n\n2010-04-07  John W. Eaton  <jwe@octave.org>\n\n\t* README.ftp, README.devel:\n\tUpdate from Judd Storrs <jstorrs@gmail.com>.\n\n2010-03-27  David Bateman  <dbateman@free.fr>\n\n\t* acinclude.m4 (OCTAVE_CHECK_OPENMP): Macro to check for OpenMP support\n\t* configure.ac: Use it here. Disable OpenMP support by default\n\n2010-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Sort the list.\n\n2010-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* bootstrap.conf: Include roundf, trunc, truncf.\n\n2010-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.3.51+.\n\n2010-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_INIT): Version is now 3.3.51.\n\t(OCTAVE_API_VERSION_NUMBER): Now 39.\n\t(OCTAVE_RELEASE_DATE): Now 2010-03-24.\n\n2010-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Style fixes.\n\n2010-03-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AH_BOTTOM): Define GNULIB_NAMESPACE.\n\n2010-03-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* acinclude.m4 (OCTAVE_CXX_COMPLEX_REFERENCE_ACCESSORS,\n\tOCTAVE_CXX_COMPLEX_SETTERS): New macros.\n\t* configure.ac: Use them.\n\n2010-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* gdbinit: New file.\n\t* Makefile.am (EXTRA_DIST): Add it to the list.\n\t(all-local): Depend on .gdbinit.\n\t(.gdbinit): New rule.\n\n2010-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* boostrap: Update from gnulib/build-aux/bootstrap.\n\n2010-02-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* configure.ac: Define NOMINMAX under MSVC.\n\n\t* configure.ac: Add pcre_config --cflags to XTRA_CXXFLAGS instead of\n\tCPPFLAGS.\n\n2010-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Add $COLAMD_LDFLAGS $COLAMD_LIBS $AMD_LDFLAGS,\n\tand $AMD_LIBS to LIBS when checking for cholmod library.\n\n2010-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* acinclude.m4 (OCTAVE_CHECK_FORTRAN_INTEGER_SIZE): Save and\n\trestore FFLAGS.  Temporarily add F77_INTEGER_8_FLAG to FFLAGS.\n\t* common.mk (F77_INTEGER_8_FLAG): New variable.\n\t(do_subst_config_vals): Substitute it.\n\t* configeure.ac: Don't add -fdefault-integer-8 to FFLAGS.\n\tSubstitute F77_INTEGER_8_FLAG.  Improve --enable-64 warning.\n\n2010-02-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include progname in the list.\n\n2010-02-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-02-04  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for gethostname.\n\t* bootstrap.conf (gnulib_modules): Include gethostname in the list.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for fcntl.h or fcntl.\n\t* bootstrap.conf (gnulib_modules): Include fcntl in the list.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* acinclude.m4 (OCTAVE_HAVE_C99_VSNPRINTF): Delete.\n\t* configure.ac: Don't call OCTAVE_HAVE_C99_VSNPRINTF.\n\tDon't check for snprintf, vfprintf, vsprintf, vsnprintf, or _snprintf.\n\t* bootstrap.conf (gnulib_modules): Include vsprintf in the list.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for strerror.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for raise or strdup.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for poll or usleep.\n\t* bootstrap.conf (gnulib_modules): Include nanosleep and sleep\n\tin the list.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for sigaction, sigpending,\n\tsigprocmask, or sigsuspend.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for getcwd.\n\t* bootstrap.conf (gnulib_modules): Include getcwd in the list.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Assume signal.h provides sigset_t and sig_atomic_t.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't call OCTAVE_SIGNAL_CHECK,\n\tOCTAVE_REINSTALL_SIGHANDLERS, AC_C_CONST, AC_HEADER_STDC, or\n\tAC_STRUCT_TM, AC_TYPE_SIGNAL.\n\tDon't define RETSIGTYPE_IS_VOID.\n\t* acinclude.m4 (OCTAVE_SIGNAL_CHECK, OCTAVE_REINSTALL_SIGHANDLERS):\n\tDon't call AC_TYPE_SIGNAL.  Assume sighandler return type is void.\n\t(OCTAVE_SIGNAL_CHECK, OCTAVE_REINSTALL_SIGHANDLERS): Delete macros.\n\t* bootstrap.conf (gnulib_modules): Include sigaction, signal,\n\tand sigprocmask in the list.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for stdint.h.\n\t(AH_BOTTOM): Unconditionally include stdint.h.\n\tDelete fallback integer type definitions.\n\t* bootstrap.conf (gnulib_modules): Include stdint in the list.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for atexit or on_exit.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for bcopy, bzero, or memmove.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include sys_time, sys_times,\n\tand time in the list.\n\t* configure.ac: Don't check for sys/time.h, sys/times.h,\n\tsys/stat.h, sys/utimes, or utimes.h.\n\tDon't call AC_HEADER_TIME.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* acinclue.m4 (OCTAVE_STRPTIME_BROKEN): Delete.\n\t* configure.ac: Don't call it.\n\n2010-02-01  John W. Eaton  <jwe@octave.org>\n\n\t* acinclude.m4 (OCTAVE_PROG_MAKEINFO): Delete macro.\n\t* configure.ac: Don't call it.  Don't issue warning about\n\tmakeinfo in summary.\n\n2010-01-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-01-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for standard C headers (by now, I\n\tthink we can safely assume they exist).  Don't check for\n\tvarargs.h.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include sys_stat in the list.\n\t* configure.ac: Don't check for sys/types.h or unistd.h.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include unistd in the list.\n\tKeep list sorted.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Delete checks for rename, link, readlink, rmdir,\n\tstrcasecmp, stricmp, strncasecmp, strnicmp, strptime, symlink,\n\tand unlink.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include pathmax and readlink\n\tin the list.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include symlink in the list.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include link in the list.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include unlink in the list.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include strptime in the list.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include rename in the list.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include rmdir in the list.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include c-strcase in the list.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include getopt-gnu in the list.\n\n2010-01-17  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* bootstrap.conf: Add round module.\n\t* configure.ac: Allow to use MSVC with *mingw* build host. Check for\n\topendir in -ldirent. Add -ladvapi32 to LIBS.\n\n2010-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Edit.\n\n2010-01-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2010-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Handle --enable-docs.  Print warning in summary\n\tif building documentation is disabled.\n\t* Makefile.am (SUBDIRS): Use @DOCDIR@ instead of doc.\n\t(dist-hook): New target, conditional on AMCOND_BUILD_DOCS.\n\n2010-01-09  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for nlink_t.\n\t(AH_BOTTOM): Don't define nlink_t here.\n\n2010-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for times.\n\t* bootstrap.conf (gnulib_modules): Include times in the list.\n\n2010-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Don't check for gettimeofday, or whether\n\tgettimeofday accepts one or two arguments.\n\t* bootstrap.conf (gnulib_modules): Include gettimeofday in the list.\n\n2010-01-05  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include mkfifo in the list.\n\n2010-01-05  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Remove nonexistent fstat module.\n\n2009-12-22  Rik  <octave@nomad.inbox5.com>\n\n\t* WWW/: remove web directory no longer used\n\n2010-01-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-12-27  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Use libtool cache variables to simplify checks\n\tfor dynamic linking api.\n\n2009-12-26  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include fstat, lstat, and\n\tstat in the list.\n\t* configure.ac: Don't check for fstat, lstat, or stat.\n\n2009-12-25  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include mkdir in the list.\n\t* configure.ac: Don't check for mkdir.\n\tDon't call OCTAVE_MKDIR_TAKES_ONE_ARG.\n\t* acinclude.m4 (OCTAVE_MKDIR_TAKES_ONE_ARG): Delete.\n\n2009-12-25  John W. Eaton  <jwe@octave.org>\n\n\t* bootstrap.conf (gnulib_modules): Include crypto/md5 in the list.\n\n2009-12-22  Rik  <octave@nomad.inbox5.com>\n\n\t* configure.ac: Remove second redundant test for nlink_t\n\n2009-12-21  Rik  <octave@nomad.inbox5.com>\n\n\t* dlfcn directory: Remove dlfcn directory with leftover code from 1996\n\n2009-12-20  Rik  <octave@nomad.inbox5.com>\n\n\t* acinclude.m4: use M4 quoting for arguments to autoconf macros\n\n2009-12-20  Rik  <octave@nomad.inbox5.com>\n\n\t* configure.ac, acinclude.m4: Better warnings when gnuplot is not\n\tinstalled but native graphics are available\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* emacs/module.mk, examples/Makefile.am, info-emacs-info,\n\tinfo-emacs-octave-help: Distribute emacs specific files from emacs\n\tdirectory rather than examples directory\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* m4/module.mk, Makefile.am: Redo previous patch with distribution\n\ttriggered by m4/module.mk.\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Distribute m4/gnulib-cache.m4 per recommendation\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am, examples/Makefile.am, common.mk, configure.ac: Eliminate\n\tTOPDIR variable in favor of built-in automake variables of top_builddir\n\tand top_srcdir.\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Use M4 quoting for arguments to autoconf macros containing\n\tvariables\n\n2009-12-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fsize_equal): Allow calling with zero arguments.\n\tvariables\n\n2009-12-15  John W. Eaton  <jwe@octave.org>\n\n\t* README.MSVC: Delete section about obtaining glob library.\n\t* bootstrap.conf (gnulib_modules): Add fnmatch and glob to the list.\n\t* common.mk (LIBGLOB): Delete variable.\n\t(do_subst_config_vals): Don't substitute it.\n\t* octave-bug.in, octave-bug.cc.in: Eliminate LIBGLOB variable.\n\t* configure.ac: Don't check for glob.h or the glob and fnmatch\n\tfunctions.  Eliminate LIBGLOB variable.\n\n2009-12-11  Rik  <octave@nomad.inbox5.com>\n\n\t* HACKING: Elaborate which DIRNAME to use for --gnulib-srcdir option.\n\n2009-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Add $PTHREAD_LIBS to $LIBS and $PTHREAD_CFLAGS\n\tto $CFLAGS for subsequent tests.\n\n2009-12-11  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: remove install-extras target and use automake syntax to\n\tdistribute NEWS file.\n\t* examples/Makefile.am: remove install-images target and use automake\n\tsyntax to distribute image data.\n\n2009-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* .dir-locals.el: Correctly set indent-tabs-mode for ChangeLogs,\n\tand Makefiles.\n\n\t* common.mk (cp_update_rule): New macro.\n\n2009-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in, mkoctfile.cc.in: If output file is specified and\n\tit does not end in output_ext, append output_ext.\n\n2009-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in, mkoctfile.cc.in: When compiling files in\n\tsubdirectories, place object files in current directory by\n\tdefault.\n\n2009-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.cc.in: Accept long options with single -.\n\n2009-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in: Accept long options with single -.\n\n2009-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* HACKING: Clarify gnulib checkout and use.\n\n2009-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Remove URL argument from AC_INIT.\n\tUse AC_CONFIG_AUX_DIR.  Move AM_INIT_AUTOMAKE after other\n\tAC_CONFIG setup macros.  Use gl_EARLY and gl_INIT for gnulib.\n\tAdd libgnu/Makefile to the list of AC_CONFIG_FILES.  Eliminate\n\tspecial case check for for strftime.\n\t* bootstrap: New file, from gnulib.\n\t* bootstrap.conf: New file, from gnulib.  Override bootstrap\n\tdefaults for checkout_only_file, gnulib_tool_option_extras,\n\tgnulib_name, and source_base.\n\t(gnulib_modules): Add strftime to the list.\n\t* autogen.sh: Simply generate makefile fragments and call\n\tbootstrap to do the rest of the initial setup.\n\t* Makefile.am (SUBDIRS): Add libgnu to the list.\n\t* libgnu/Makefile.am: New directory and file.\n\t* INSTALL: Remove our copy so version from gnulib will be\n\tdistributed.\n\t* HACKING: New file.\n\n2009-12-08  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: add BUGS and OCTAVE.INSTALL to DISTCLEANFILES\n\n2009-12-08  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Update gnuplot status message.\n\t* acinclude.m4 (OCTAVE_PROG_GNUPLOT): Likewise.\n\n2009-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* examples/make_int.cc: Delete Emacs local variables.\n\n\t* .dir-locals.el: New file.\n\n2009-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* examples/firstmexdemo.c, examples/fortdemo.cc,\n\texamples/funcdemo.cc, examples/hello.cc, examples/make_int.cc,\n\texamples/mycell.c, examples/myfeval.c, examples/myfunc.c,\n\texamples/mypow2.c, examples/mysparse.c, examples/mystring.c,\n\texamples/mystruct.c, examples/paramdemo.cc,\n\texamples/stringdemo.cc, examples/structdemo.cc,\n\texamples/unwinddemo.cc, examples/embedded.cc: Untabify.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (OCTAVE_API_VERSION_NUMBER): New variable.\n\t(OCTAVE_API_VERSION): Define using OCTAVE_API_VERSION_NUMBER.\n\t* common.mk (OCTAVE_API_VERSION_NUMBER): New variable.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Check $have_x = yes, not just $have_x.\n\tFrom Carmine Paolino <earcar@gmail.com>.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Require auotconf 2.62.\n\n2009-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* common.mk (OCTAVE_VERSION, OCTAVE_API_VERSION)\n\t(OCTAVE_RELEASE_DATE, OCTAVE_COPYRIGHT, OCTAVE_IDX_TYPE):\n\tNew substituted variables.\n\t(version): Define from $(OCTAVE_VERSION).\n\t(api_version): Define from $(OCTAVE_API_VERSION).\n\t(do_subst_texinfo_vals): Delete macro.\n\n\t* configure.ac (AC_CONFIG_HEADER): Quote arg.\n\t(AC_CONFIG_FILES): Remove mxarray.h and version.h from the list.\n\n\t* examples/Makefile.am (CLEANFILES): New variable.\n\n2009-11-30  Kacper Kowalik  <xarthisius.kk@gmail.com>\n\n\t* acinclude.m4 (OCTAVE_HDF5_HAS_ENFORCED_16_API): New macro that\n\ttests whether the HDF5 library has an enforced v1.6 API and detects\n\tv1.8 APIs.\n\t* configure.m4: Adapt test for HDF5 libraries to support v1.8\n\tHDF5 libraries.\n\n2009-11-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-11-27  David Bateman  <dbateman@free.fr>\n\n\t* configure.ac (HAVE_H5GGET_NUM_OBJS) Remove define.\n\n2009-11-27  David Bateman  <dbateman@free.fr>\n\n\t* NEWS: Document ftp objects.\n\t* configure.ac: Document that curl libraries impact ftp objects.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-11-25  Tatsuro MATSUOKA  <tmacchant@yahoo.co.jp>\n\n\t* acinclude.m4 (OCTAVE_PROG_GNUPLOT): Don't check for pgnuplot or\n\tpipe-gnuplot on Windows systems.  Set default to gnuplot for all\n\tsystems.\n\t(OCTAVE_PROG_GHOSTSCRIPT): Check for gswin32c first on Windows\n\tsystems, then gs.\n\n2009-11-25  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am examples/Makefile.am liboctave/Makefile.am\n\tscripts/Makefile.am src/Makefile.am test/Makefile.am:\n\tRemove unnecessary .PHONY targets for common targets which\n\tAutomake supplies already.  Examples are local-all, install-local-data\n\n2009-11-21  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_MSG_NOTICE): Report graphics (fltk) CFLAGS.\n\tReport fontconfig CFLAGS and LIBS.\n\tReport freetype2 CFLAGS and LIBS.\n\n2009-11-21  John W. Eaton  <jwe@octave.org>\n\n\t* common.mk: Substitute FT2_CFLAGS.\n\t* configure.ac: Remove spurious lines in check for freetype.  Add\n\t$FT2_CFLAGS to $XTRA_CXXFLAGS.\n\n2009-11-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-11-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-11-16  John W. Eaton  <jwe@octave.org>\n\n\t* common.mk (AM_CXXFLAGS): Don't include DLL_CXXDEFS in the list.\n\t(CONFIGURE_CFLAGS): New variable.\n\t(AM_CFLAGS): Define similar to AM_CXXFLAGS.\n\n2009-11-12  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac (AC_CONFIG_FILES): Also generate libcruft/mkf77def.\n\n2009-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* acinclude.m4 (OCTAVE_IEEE754_DATA_FORMAT): Fail if IEEE 754\n\tformat is not detected.\n\n2009-11-11  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* configure.ac: Remove tests for ftgl.\n\n2009-11-11  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* configure.ac: Remove -mwindows from FLTK_LDFLAGS.\n\n2009-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Fail if LT_INIT it is not defined.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Update.\n\n\t* configure.ac: Exit with error if BLAS or LAPACK libraries are\n\tnot found or if the BLAS library is found to be incompatible with\n\tthe Fortran compiler.  Eliminate warn_blas_f77_incompatible\n\tvariable.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Set octincludedir to\n\t$(includedir)/octave-$(version)/octave, not\n\t$(includedir)/octave-$(version).\n\t* mkoctfile.in: Set DEFAULT_INCFLAGS to -I$octincludedir/.. and\n\t-I$octincludedir instead of -I$octincludedir and\n\t-I$octincludedir/octave.\n\n\t* configure.ac: Pass args to AC_INIT.  Invoke AM_INIT_AUTOMAKE and\n\tAC_PROG_LIBTOOL.  Don't call AC_PROG_RANLIB.  Set version info here.\n\tCall AC_CONFIG_MACRO_DIR.  Give same warning for gcc 1.x and 2.x.\n\tUse AM_CONDITIONALS for FFTW, BLAS, and LAPACK.  Don't set\n\tvariables with calls to ACX_BLAS_WITH_F77_FUNC or ACX_LAPACK.\n\tDon't substitute BLAS_DIR or LAPACK_DIR.  Use LT_INIT.  Eliminate\n\t--enable-shared and --enable-static options (now provided by\n\tLT_INIT).  Set SHARED_LIBS and STATIC_LIBS variables based on\n\tLT_INIT variables.  Handle dlopen libraries with info from\n\tLT_INIT.  Substitute NO_UNDEFINED_FLAG (only set on Windows\n\tsytems).  Include $LAPACK_LIBS in $LIBS when checking for qrupdate\n\tand cholmod.  Handle --enable-dl consistently with other --enable\n\toptions.  Don't copy $srcdir/Makefile in AH_BOTTOM commands.\n\tSubstitute LEX_OUTPUT_ROOT.  Use AM_CONDITONAL for\n\tENABLE_DYNAMIC_LINKING.  Reindent configure summary.\n\t(AC_CONFIG_FILES): Don't list Makefiles in libcruft\n\tsubdirectories.  Generate Makefile and src/version.h.  Don't\n\tgenerate Makeconf, octMakefile, m4/Makefile, emacs/Makefile,\n\texamples/@polynomial/Makefile, or examples/@FIRfilter/Makefile.\n\n\t* run-octave.in Call libtool to execute src/octave.\n\t(ldpreloadsep, liboctinterp, liboctave, libcruft): Delete variables.\n\t(INFOFILE): Find it in $top_srcdir, not $builddir.\n\n\t* acinclude.m4: Rename from aclocal.m4.\n\t(OCTAVE_PROG_FLEX): Don't include -t in LFLAGS.\n\n\t* autogen.sh: Exit immediately on error.  Use libtoolize, aclocal,\n\tand automake.  Only run autoconf and autoheader in top-level and\n\tscripts directories.\n\tRun liboctave/config-ops.sh, doc/interpreter/config-images.sh, and\n\tsrc/DLD-FUNCTIONS/config-module.sh, to generate source lists for\n\tsubdirectories.\n\n\t* AUTHORS, Makefile.am, common.mk, m4/module.mk, emacs/module.mk,\n\texamples/@FIRfilter/module.mk, examples/@polynomial/module.mk,\n\texamples/Makefile.am: New files.\n\t* Makeconf.in, Makefile, octMakefile.in, m4/Makefile.in,\n\temacs/Makefile.in, install-sh, examples/Makefile.in,\n\texamples/@FIRfilter/Makefile.in, examples/@polynomial/Makefile.in:\n\tDelete.\n\n2009-11-09  David Grundberg  <davidg@cs.umu.se>\n\n\t* configure.ac: Use AMD_CPPFLAGS while checking for UMFPACK.\n\n2009-10-29  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* configure.in: Add support for dlopen on Mac systems.\n\n2009-10-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-10-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-10-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.ac: Define HAVE_QRUPDATE_LUU if qrupdate supports LU updates.\n\n2009-10-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.ac: Use the LANG argument to OCTAVE_CHECK_LIBRARY to avoid\n\tugly names.\n\n2009-09-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-09-18  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4: Consistently quote first arg to AC_DEFUN.\n\n2009-09-17  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Also AC_DEFINE OCTAAVE_IDX_TYPE.\n\t(AH_BOTTOM): Include contents of libcruft/misc/oct-dlldefs.h and\n\tliboctave/oct-types.h here.  Use C-style comments.\n\t(AC_CONFIG_FILES): Remove liboctave/oct-types.h from the list.\n\n2009-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* configure.ac: Rename from configure.in.\n\t(AC_CONFIG_FILES): Add m4/Makefile to the list.\n\t* acx_blas.m4, acx_lapack.m4, acx_blas_f77_func.m4,\n\tacx_pthread.m4: Move to m4 subdirectory.\n\t* m4/Makefile.in: New file.\n\t* octMakefile.in (M4_FILES): Adjust for new m4 subdirectory.\n\tRename all instances of configure.in to configure.ac.\n\t(CONF_DISTSUBDIRS, DISTSUBDIRS): Add m4 to the lists.\n\n\t* configure.in: Substitute ac_config_headers.\n\t* octMakefile.in (CONFIG_FILES): Include @ac_config_headers@ in\n\tthe list.  From Thorsten Meyer <thorsten.meyier@gmx.de>.\n\n2009-09-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (SPARSE_CPPFLAGS, SPARSE_LDFLAGS, FFTW_CPPFLAGS,\n\tFFTW_LDFLAGS): Don't sort lists.\n\n2009-09-02  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* Makeconf.in: Order SPARSE_LIBS so linking succeeds on Cygwin.\n\n2009-09-04  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t*  README.Cygwin: Update version info.\n\n2009-09-04  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (ldpreloadsep): New variable.  Set to ':' for Cygwin.\n\t* Makeconf.in (do-subst-script-vals): Substitute it.\n\t* run-octave.in: Use it to seprate elements in the LD_PRELOAD variable.\n\n2009-09-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AH_BOTTOM): If HAVE_Z is defined, define HAVE_ZLIB.\n\n2009-09-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-09-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.in (FLOAT_TRUNCATE): New config macro.\n\n2009-09-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* acx_blas_f77_func.m4 (ACX_BLAS_F77_FUNC): Check for correct INTEGER\n\tsize.\n\n2009-09-01  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_REQUIRE_64_BIT_FORTRAN_INTEGERS): New macro.\n\t* configure.in: Use it, if building with --enable-64.\n\tMove checks for Fortran compiler ahead of checks for libraries.\n\n2009-09-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-08-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-08-27  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Properly save and restore CPPFLAGS and LIBS when\n\tchecking for GraphicsMagick++.  Don't temporarily change LDFLAGS.\n\n2009-08-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* aclocal.m4 (m4_ifblank, m4_ifnblank): State FSF copyright and markup\n\tas FIXME.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Restore LIBS after checking for ARPACK.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Use OCTAVE_CHECK_LIBRARY to check for UMFPACK.\n\t* octave-bug.in, octave-bug.cc.in: Substitute UMFPACK_CPPFLAGS and\n\tUMFPACK_LDFLAGS.\n\t* Makeconf.in (UMFPACK_CPPFLAGS, UMFPACK_LDFLAGS): New variables.\n\t(do-subst-config-vals): Substitute them.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Use OCTAVE_CHECK_LIBRARY to check for qrupdate.\n\t* octave-bug.in, octave-bug.cc.in: Substitute QRUPDATE_CPPFLAGS and\n\tQRUPDATE_LDFLAGS.\n\t* Makeconf.in (QRUPDATE_CPPFLAGS, QRUPDATE_LDFLAGS): New variables.\n\t(do-subst-config-vals): Substitute them.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* octave-bug.in: Correct substitutions.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_CHECK_LIBRARY): Allow empty list of header files.\n\t* configure.in: Use OCTAVE_CHECK_LIBRARY to check for arpack.\n\t* octave-bug.in, octave-bug.cc.in: Substitute ARPACK_CPPFLAGS and\n\tARPACK_LDFLAGS.\n\t* Makeconf.in (ARPACK_CPPFLAGS, ARPACK_LDFLAGS): New variables.\n\t(do-subst-config-vals): Substitute them.\n\n2009-08-26  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* mkoctfile.cc.in: Fix typo.\n\t* octave-bug.cc.in: Correct substututions.\n\n2009-08-25  David Grundberg  <individ@acc.umu.se>\n\n\t* configure.in: Run PKG_PROG_PKG_CONFIG earlier. Use pkg-config\n\tinstead of GraphicsMagick++-config. Determine only -I, -L and -l\n\tflags and put them in MAGICK_CPPFLAGS, MAGICK_LDFLAGS and\n\tMAGICK_LIBS respectively. Substitute these variables.\n\tRemove variables MAGICK_CONFIG and MAGICK_INCFLAGS.\n\tTest linking against GraphicsMagick++.\n\t* Makeconf.in: Don't run $(MAGICK_CONFIG) here. Use substituted\n\tvalued from MAGICK_CPPFLAGS, MAGICK_LDFLAGS and MAGICK_LIBS.\n\tRemove variables MAGICK_CONFIG and MAGICK_INCFLAGS.\n\n2009-08-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* acx_blas_f77_func.m4: Fix typo.\n\n2009-08-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_HDF5_HAS_REQUIRED_API): If test fails, set\n\toctave_hdf5_ok to no instead of setting HAVE_HDF5 to false.\n\t* configure.in: Check octave_hdf5_ok instead of HAVE_HDF5.\n\tSet TEXINFO_HDF5 if HDF5 library is found.\n\n2009-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (ALL_CPPFLAGS): Add HDF5_CPPFLAGS to the list.\n\t* aclocal.m4 (OCTAVE_HDF5_HAS_REQUIRED_API):\n\tSet HAVE_HDF5 to false, not WITH_HDF5.\n\t* configure.in: Use OCTAVE_CHECK_LIBRARY to check for HDF5\n\tlibrary.  Print HDF5_CPPFLAGS and HDF5_LDFLAGS in the summary.\n\t* octave-bug.in, octave-bug.cc.in, Makeconf.in: Substitute\n\tHDF5_CPPFLAGS and HDF5_LDFLAGS.\n\n2009-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* acx_blas_f77_func.m4 (ACX_BLAS_F77_FUNC): Save and restore LIBS.\n\n2009-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_CHECK_LIBRARY): Use variables named\n\toctave_check_library_save_XXX instead of save_XXX.\n\t* configure.in: Add Z_LDFLAGS and Z_LIBS to LIBS, and Z_CPPFLAGS\n\tto CPPFLAGS in checks for curl and glpk libraries.\n\n2009-08-18  David Grundberg  <individ@acc.umu.se>\n\n\t* aclocal.m4 (OCTAVE_CHECK_LIBRARY): Clear QHULL_LIBS etc on\n\terrors. Interpret --without-qhull etc correctly.\n\n2009-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in, mkoctfile.cc.in (FFTW3_LDFLAGS, FFTW3_LIBS,\n\tFFTW3F_LDFLAGS, FFTW3F_LIBS): Substitute instead of FFTW_LIBS.\n\t(FFTW_LIBS): Define from FFTW3_LDFLAGS, FFTW3_LIBS,\n\tFFTW3F_LDFLAGS, and FFTW3F_LIBS variables.\n\n\t* octave-bug.cc.in, octave-bug.in (Z_CPPFLAGS, Z_LDFLAGS):\n\tSubstitute and display them.\n\t(Z_LIBS): Rename from ZLIB_LIBS.\n\t* configure.in: Use OCTAVE_CHECK_LIBRARY to check for ZLIB.\n\tPrint Z_CPPFLAGS and Z_LDFLAGS in the summary.\n\t* Makeconf.in (Z_CPPFLAGS, Z_LDFLAGS): New variables.\n\t(Z_LIBS): Rename from ZLIB_LIBS.\n\t(do-subst-config-vals): Substitute them.\n\n\t(ALL_CPPFLAGS): New variable.\n\t(%.o : %.c, %.o : %.cc, pic/%.o : %.c, pic/%.o : %.cc):\n\tUse $(ALL_CPPFLAGS) instead of $(CPPFLAGS) in command.\n\n2009-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* octave-bug.in, octave-bug.cc.in: Include AMD_CPPFLAGS,\n\tAMD_LDFLAGS, AMD_LIBS, ARPACK_LIBS, BLAS_LIBS, CAMD_CPPFLAGS,\n\tCAMD_LDFLAGS, CAMD_LIBS, CARBON_LIBS, CCOLAMD_CPPFLAGS,\n\tCCOLAMD_LDFLAGS, CCOLAMD_LIBS, CHOLMOD_CPPFLAGS, CHOLMOD_LDFLAGS,\n\tCHOLMOD_LIBS, COLAMD_CPPFLAGS, COLAMD_LDFLAGS, COLAMD_LIBS,\n\tCURL_CPPFLAGS, CURL_LDFLAGS, CURL_LIBS, CXSPARSE_CPPFLAGS,\n\tCXSPARSE_LDFLAGS, CXSPARSE_LIBS, DL_LIBS, FFTW3_CPPFLAGS,\n\tFFTW3_LDFLAGS, FFTW3_LIBS, FFTW3F_CPPFLAGS, FFTW3F_LDFLAGS,\n\tFFTW3F_LIBS, GRAPHICS_LIBS, GLPK_CPPFLAGS, GLPK_LDFLAGS,\n\tGLPK_LIBS, HDF5_LIBS, OPENGL_LIBS, PTHREAD_CFLAGS, PTHREAD_LIBS,\n\tQHULL_CPPFLAGS, QHULL_LDFLAGS, QHULL_LIBS, QRUPDATE_LIBS,\n\tREADLINE_LIBS, REGEX_LIBS, TERM_LIBS, UMFPACK_LIBS, X11_INCFLAGS,\n\tX11_LIBS, and ZLIB_LIBS in the summary of varibles.\n\n\t* configure.in: Include LEXLIB and LIBGLOB in the summary.\n\n2009-08-17  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* aclocal.m4 (OCTAVE_HDF5_DLL): Include HDF5_LIBS in LIBS before\n\tattempting link.\n\n2009-08-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* aclocal.m4: Define the autoconf 2.64+ m4sugar macros `m4_ifblank'\n\tand `m4_ifnblank' if on earlier autoconfs.\n\n2009-08-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (GLPK_CPPFLAGS, GLPK_LDFLAGS,\n\tAMD_CPPFLAGS, AMD_LDFLAGS, CAMD_CPPFLAGS, CAMD_LDFLAGS,\n\tCCOLAMD_CPPFLAGS, CCOLAMD_LDFLAGS, CHOLMOD_CPPFLAGS,\n\tCHOLMOD_LDFLAGS, COLAMD_CPPFLAGS, COLAMD_LDFLAGS,\n\tCXSPARSE_CPPFLAGS, CXSPARSE_LDFLAGS): New variables.\n\t(do-subst-config-vals): Substitute Them.\n\t(SPARSE_CPPFLAGS, SPARSE_LDFLAGS, SPARSE_LIBS, FFTW_CPPFLAGS,\n\tFFTW_LDFLAGS, FFTW_LIBS): New variables.\n\n\t* configure.in: Use OCTAVE_CHECK_LIBRARY to check for GLPK, AMD,\n\tCAMD, CCOLAMD, CHOLMOD, COLAMD, CXSPARSE, FFTW3, and FFTW3F\n\tlibraries.  Print GLPK_CPPFLAGS, GLPK_LDFLAGS, AMD_CPPFLAGS,\n\tAMD_LDFLAGS, CAMD_CPPFLAGS, CAMD_LDFLAGS, CCOLAMD_CPPFLAGS,\n\tCCOLAMD_LDFLAGS, CHOLMOD_CPPFLAGS, CHOLMOD_LDFLAGS,\n\tCOLAMD_CPPFLAGS, COLAMD_LDFLAGS, CXSPARSE_CPPFLAGS,\n\tCXSPARSE_LDFLAGS, FFTW3_CPPFLAGS, FFTW3_LDFLAGS, FFTW3_LIBS,\n\tFFTW3F_CPPFLAGS, FFTW3F_LDFLAGS, and FFTW3F_LIBS in the summary.\n\t(AH_BOTTOM): Define HAVE_FFTW if HAVE_FFTW3 and HAVE_FFTW3F are\n\tboth defined.\n\n\t* aclocal.m4 (OCTAVE_CHECK_LIBRARY): New optional arguments for\n\tlanguage and doc string.\n\n2009-08-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* aclocal.m4 (OCTAVE_CHECK_LIBRARY): Prepend to LIBS rather than\n\treplacing.\n\n2009-08-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (QHULL_CPPFLAGS, QHULL_LDFLAGS, CURL_CPPFLAGS,\n\tCURL_LDFLAGS): New variables.\n\t(do-subst-config-vals): Substitute QHULL_CPPFLAGS, QHULL_LDFLAGS,\n\tCURL_CPPFLAGS, and CURL_LDFLAGS\n\t* configure.in: Use OCTAVE_CHECK_LIBRARY to check for qhull and\n\tcurl libraries.  Print QHULL_CPPFLAGS, QHULL_LDFLAGS,\n\tCURL_CPPFLAGS, and CURL_LDFLAGS in the summary.  Print glpk\n\tlibrary warning at time of check.  Use AC_MSG_WARN, not\n\tAC_MSG_RESULT, to print fftw warning.\n\t* aclocal.m4 (OCTAVE_CHECK_LIBRARY): New macro.\n\t(AC_CHECK_QHULL_VERSION, AC_CHECK_QHULL_OK):\n\tImplement with modern autoconf macros.\n\n2009-08-11  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Define and substitute TERM_LIBS instead of\n\tTERMLIBS.  Don't add TERM_LIBS to LIBS.  Define DL_LIBS instead of\n\tadding them to LIBS.  Display TERM_LIBS and DL_LIBS in summary\n\treporrt.\n\t* aclocal.m4 (OCTAVE_ENABLE_READLINE): Define and substitute\n\tREADLINE_LIBS instead of LIBREADLINE.  Don't add readline library\n\tto LIBS.  Display READLINE_LIBS in summary report.  Temporarily\n\tadd TERM_LIBS to LIBS when checking for readline library.\n\t* Makeconf.in, mkoctfile.cc.in, mkoctfile.in:\n\tUse READLINE_LIBS instead of LIBREADLINE and TERM_LIBS instead of\n\tTERMLIBS.  Substitute DL_LIBS.\n\t(do-subst-config-vals): Substitute TERM_LIBS and DL_LIBS.\n\n2009-08-11  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Generate separate variables for HDF5_LIBS and\n\tZLIB_LIBS.  Don't add them to LIBS.  Add separate entries for them\n\tin the summary report.\n\t* Makeconf.in (HDF5_LIBS, ZLIB_LIBS): New variables.\n\t(do-subst-config-vals): Substitute AMD_LIBS, ARPACK_LIBS,\n\tCAMD_LIBS, CCOLAMD_LIBS, CHOLMOD_LIBS, COLAMD_LIBS, CXSPARSE_LIBS,\n\tFT2_LIBS, GRAPHICS_LIBS, HDF5_LIBS, OPENGL_LIBS, PTHREAD_CFLAGS,\n\tPTHREAD_LIBS, QHULL_LIBS, QRUPDATE_LIBS, REGEX_LIBS, UMFPACK_LIBS,\n\tZLIB_LIBS.\n\n2009-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* acx_pthread.m4: New file.\n\t* configure.in: Include it and invoke ACX_PTHREAD macro.  Print\n\tptrhead flags and libraries in summary output.\n\t* Makeconf.in (PTHREAD_CFLAGS, PTHREAD_LIBS): Substitute values.\n\t(ALL_CFLAGS, ALL_CXXFLAGS): Include $(PTHREAD_CFLAGS).\n\n2009-08-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-07-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-07-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-07-16  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (MAGICK_LIBS): Don't pass --ldflags to $(MAGICK_CONFIG).\n\n2009-07-09  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Don't use system strftime on MinGW systems.\n\n2009-06-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Correct info.\n\t* NEWS: Update.\n\n2009-06-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* aclocal.m4: Add pkg.m4 macros.\n\t* configure.in (HAVE_FREETYPE): New defined variable.\n\t* configure.in: Add configure tests for Fontconfig detection.\n\n2009-06-23  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* run-octave.in: Exclude @-files from path.  Remove CVS exclusions.\n\n2009-06-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-06-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Update.\n\n2009-06-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* examples/@polynomial/subsref.m: Handle ':' correctly.\n\t* examples/@polynomial/subsasgn.m: Ditto.\n\n2009-06-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* example/@polynomial/numel.m: New method.\n\t* example/@polynomial/Makefile.in: Include it.\n\n2009-05-22 Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* mkoctfile.cc.in: mask MSVC specific linker flags for mex output\n\n2009-06-02  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* examples/@polynomial: Fix end method for zero based indexing.\n\n2009-06-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* examples/@polynomial/subsref.m: Allow chained subscripts,\n\tfix behavior according to docs.\n\t* examples/@polynomial/subsasgn.m: Allow chained subscripts,\n\tfix behavior according to docs.\n\n2009-06-02  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* examples/@polynomial: Remove tabs from all functions so\n\tdocumentation looks right.  Fix a bunch of methods\n\tthat didn't work.  Add a method referred to in the docs\n\tthat didn't exist.\n\n2009-05-26  John W. Eaton  <jwe@octave.org>\n\n\t* src/dirfns.cc (Fpathsep): Allow path separator to be set.\n\n2009-03-17  Thomas Weber  <thomas.weber.mail at gmail.com>\n\n\t* configure.in: fix typo with regards to termios.h\n\n2009-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* examples/@FIRfilter/Makefile.in: New file.\n\t* examples/Makefile.in: Include it.\n\t* configure.in: Ditto.\n\n2009-05-24  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* configure.in: (SCRIPTS_EXE_SUFFIX) Define to \".exe\" for\n\tmingw32 compilation (similar to msvc)\n\n2009-05-24  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* examples/@FIRfilter: added FIRfilter class example.\n\n2009-05-22  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* src/sysdep.cc: Removed CYGWIN_init\n\n2009-05-21  Marco Atzeri  <marco_atzeri@yahoo.it>\n\t* configure.in: Correct my mistake in cygwin SHLBINPRE SHLBIN\n\n2008-05-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* aclocal.m4 (AC_CHECK_QHULL_OK): Do not use -lm under\n\tWindows systems.\n\t* configure.in: Add -luser32 to LIBS under Windows.\n\n\t* configure.in (SCRIPTS_EXE_SUFFIX): New substituted\n\tvariable. Define to \".exe\" for MSVC compilation.\n\t* octMakefile.in (SCRIPTS_EXE_SUFFIX): New variable.\n\t(DISTFILES): Add mkoctfile.cc.in, octave-config.cc.in and\n\toctave-bug.cc.in.\n\t(SHELL_SCRIPTS): Use SCRIPTS_EXE_SUFFIX.\n\t(mkoctfile.cc, mkoctfile$(EXEEXT)): New build rules.\n\t(octave-config.cc, octave-config$(EXEEXT)): Likewise.\n\t(octave-bug.cc, octave-bug$(EXEEXT)): Likewise.\n\t(install, install-strip, uninstall): Use SCRIPTS_EXE_SUFFIX.\n\t(maintainer-clean, distclean): Remove mkoctfile.[cc|o|exe],\n\toctave-config.[cc|o|exe] and octave-bug.[cc|o|exe].\n\t(clean): Remove mkoctfile$(EXEEXT), octave-config$(EXEEXT),\n\toctave-bug$(EXEEXT) and the corresponding object files.\n\n2009-05-07  Rik  <rdrider0-list@yahoo.com>\n\n\t* README.mirrors: Remove invalid mirror sites which no longer exist.\n\n2009-05-07  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in, mkoctfile.in, mkoctfile.cc.in, octave-bug.in,\n\toctave-bug.cc.in: Eliminate last remnants of f2c goop.\n\n2009-05-07  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* configure.in, Makeconf.in: (SHLPRE): Rename from SHLLIBPRE.\n\n2009-05-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.in: Include the whole 3.x g++ series as problematic.\n\t* Makefile: Don't mention that g++-3.x might work.\n\n2009-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Put -lftgl ahead of $FT2_LIBS, and $FT2_LIBS ahead\n\tof $OPENGL_LIBS.\n\n2009-05-04  Peter O'Gorman  <pogma@thewrittenword.com>\n\n\t* aclocal.m4 (OCTAVE_HAVE_C99_VSNPRINTF): New macro.\n\t* configure.in: Use it.\n\n\t* configure.in (rs6000-ibm-aix* | powerpc-ibm-aix*): Set\n\tlibrary_path_var to LIBPATH.\n\t(hppa*-hp-hpux*): Set library_path_var to SHLIB_PATH.\n\t(ia64*-hp-hpux*): New case for shared library variables.\n\n\t* configure.in: Provide decls for exp2, round, and tgamma if they\n\tare missing.\n\n2009-04-11  David Bateman  <dbateman@free.fr>\n\n\t* NEWS: Add new graphics functions.\n\n2009-04-05  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Use AC_USE_SYSTEM_EXTENSIONS instead of\n\tAC_GNU_SOURCE, AC_AIX, AC_MINIX, and AC_ISC_POSIX.\n\tRequire Autoconf 2.60.\n\n\t* configure.in: Add -Wformat to extra warning flags.  Add\n\t-Wconversion to strict warning flags.\n\n2009-04-02  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-script-install): Use $(INSTALL_DATA) instead of\n\tmv to install PKG_ADD file.\n\n2009-04-02  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* Makeconf.in (do-subst-script-vals): Use SHLLIBPRE instead of\n\tLIBPRE for names for shared libraries.\n\n2009-03-28  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* configure.in: For cygwin, set LIBPRE=lib and clear CPICFLAG,\n\tCXXPICFLAG, and FPICFLAG.\n\n2009-03-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* aclocal.m4 (OCTAVE_CMATH_FUNC): Add missing AC_LANG_POP.\n\t* configure.in: Enclose string in quotes.\n\n2009-03-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: More updates.\n\n2009-03-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* aclocal.m4 (OCTAVE_CMATH_FUNC): New macro.\n\t* configure.in: Use it.\n\n2009-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* run-octave.in: Use doc-cache instead of DOC for doc cache file.\n\t* configure.in: Likewise.\n\n\t* configure.in (--enable-extra-warning-flags): New option to\n\tcontrol extra compiler warning flags.\n\t(--enable-strict-warning-flags): Rename from --enable-picky-flags.\n\t(GXX_STRICT_FLAGS): Remove -Wenum-clash from the list.\n\n2009-03-08  Søren Hauberg  <hauberg@gmail.com>\n\n\t* NEWS: Mention 'histc'.\n\n2009-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* config.guess, config.sub: Update from FSF sources.\n\n2009-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (doc_cache_file): New default variable\n\t* Makeconf.in (@doc_cache_file, do-subst-default-vals): Substitute it.\n\n2009-02-24  John W. Eaton  <jwe@octave.org>\n\n\t* run-octave.in (DOCFILE): New variable.  Pass --doc-cache-file\n\toption to Octave.\n\n\t* configure.in: Copy Makefile to build directory if not building\n\tin srcdir.\n\n2009-02-24  Thorsten Meyer  <thorsten@hexe>\n\n\t* configure.in: AC_SUBST ac_config_files.\n\t* Makeconf.in (config_opts): Define CONFIG_SUBDIRS variable.\n\t* Makefile: Add make target for configuration files.\n\t* octMakefile.in: Add make targets for configuration files,\n\tconfig.status and configure.\n\n\t* Makefile.in: Rename to Makefile.\n\t* configure.in: Remove Makefile from list of autogenerated\n\tconfiguration files.\n\t* octMakefile.in: Remove references to Makefile.in, add Makefile\n\tto list of CONF_DISTFILES.\n\t* octMakefile.in (maintainer-clean distclean): Don't delete Makefile.\n\n2009-02-17  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* configure.in: Check for mkstemps on MinGW platform\n\t(HAVE_MKSTEMPS): Define if mkstsmps is avilable in libiberty.\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Mention cummin and cummax\n\n2009-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_PROG_GPERF): Don't run gperf.\n\n\t* Makeconf.in (do-subst-config-vals): Substitute CARBON_LIBS,\n\tX11_INCFLAGS, and X11_LIBS.\n\n2009-02-17  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* Makeconf.in: Substitute CARBON_LIBS.\n\t* configure.in: Use CARBON_LIBS instead of LIBS for framework Carbon.\n\n\t* configure.in: Fix test for X11 if \"--without-x\" is given.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Yet more updates.\n\n2009-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Mention command-style parsing changes.  More updates.\n\n2009-02-13  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: Update for release.\n\n2009-02-11 Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* aclocal.m4 (OCTAVE_GLUTESSCALLBACK_THREEDOTS): New macro.\n\t(OCTAVE_OPENGL): Use it in OpenGL check.\n\n2009-02-11 Ben Abbott  <bpabbott@mac.com>\n\n\t* configure.in: Include FTGLTextureFont.h when FTGL_UPPER_CASE is\n\tnot defined.\n\n2009-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (octetcdir): New default value.\n\t* Makeconf.in (octetcdir): New variable.\n\t(do-subst-default-vals): Substitute octetcdir.\n\t* octMakefile.in (install, uninstall): Use $(octetcdir) for NEWS.\n\t(DIRS_TO_MAKE): Add $(octetcdir) to the list.\n\n2009-02-10  Rafael Laboissiere  <rafael@debian.org>\n\n\t* examples/Makefile.in: Run some clean targets on sub-directory\n\t@polynomial.\n\n2009-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (dist): Create subdirs of examples, not scripts.\n\n\t* examples/@polynomial/Makefile.in (do-mkpkgadd):\n\tProvide special definition for this directory.\n\n\t* examples/Makefile.in (EXAMPLE_SOURCES): Delete unused variable.\n\t(SUBDIRS, DISTSUBDIRS): Don't reset to empty.\n\n2009-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* install-octave.in: Delete.\n\t* configure.in: Delete AC_CONFIG_COMMANDS macro that was used to\n\tmake install-octave executable.\n\n2009-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (all): Display $(prefix) in summary message.\n\n2009-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_HDF5_HAS_REQUIRED_API): New macro.\n\t* configure.in: Use it in HDF5 check.\n\n2009-02-04  Benjamin Lindner  <lindnerben@gmx.net>\n\n\t* configure.in: Use separate cases for *-*-mingw* and *-*-cygwin*\n\tto set variables related to creating shared libraries.\n\n2009-02-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* aclocal.m4 (AC_CHECK_QHULL_OK): New macro, based on suggestion by\n\tPetr Mikulik <mikulik@physics.muni.cz>.\n\t* configure.in: Call it.\n\n2009-02-01  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* autogen.sh: Remove printing of cvs motd.\n\n2009-01-30  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* configure.in (SHLLIBPRE, SHLBINPRE): Fix definitions for Cygwin.\n\t(SHLEXT, SHLLIB, SHLBIN, SONAME_FLAGS): Fix definitions for Cygwin\n\tand MinGW.\n\n2009-01-30  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* configure.in: Add -lgdi32 to LIBS on *-*-msdosmsvc* and\n\t*-*-mingw* systems.\n\n2009-01-29  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* aclocal.m4 (OCTAVE_HAVE_FRAMEWORK): Add support for\n\t--with-framework-<name> and replace \"$ac_safe\" by \"$1\".\n\t* configure.in: Change \"have_carbon\" with\n\t\"have_framework_carbon\".\n\n2009-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check to see that pcre library has pcre_compile\n\tfunction.\n\n \t* configure.in (SHLLIBPRE, SHLBINPRE): New variables.  AC_SUBST them.\n \t(*-*-cygwin*): Set LIBPRE and SHLBINPRE to cyg and SHLLIBPRE to lib.\n\tUse SHLLIBPRE and SHLLIB in definition of SONAME_FLAGS.\n\t(*-*-msdosmsvc): Make SHLBINPRE and SHLLIBPRE empty.\n \tAdjust definition of SONAME_FLAGS for SHLLIBPRE.\n\n\t* Makeconf.in (SHLLIBPRE, SHLBINPRE): Substitute new variables here.\n\tFrom Marco Atzeri <marco_atzeri@yahoo.it>.\n\n2009-01-27  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* configure.in: Add of -lregex to REGEX_LIBS.\n\n2009-01-26  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* aclocal.m4 (OCTAVE_HAVE_FRAMEWORK): New macro.\n\t* configure.in: Use it.\n\n2009-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AH_BOTTOM): Define OCTAVE_USE_OS_X_API if\n\t__APPLE__ and __MACH__ are defined.\n\n2009-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.in: Fix qrupdate warning message.\n\n2009-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in: Substitute X11_INCFLAGS and X11_LIBS.\n\t* configure.in: Use AC_PATH_X to check for X11 header files and\n\tlibraries.\n\n\t* THANKS, Announce: Remove obsolete files.\n\t* octMakefile.in (DISTFILES): Remove THANKS from the list.\n\n2009-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for fstat.\n\n2008-12-23  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Add configuration test for ARPACK.\n\t* Makeconf.in (ARPACK_LIBS): Add variable with location of ARPACK\n\tlibrary.\n\t* NEWS: Document that eigs and svds were moved to Octaave.\n\n2008-10-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.in: Remove the OCTAVE_LOCAL_BUFFER stuff (moved to\n\tliboctave).\n\n2008-12-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* NEWS: Document more new features.\n\n2008-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* config.guess, config.sub: Update from FSF sources.\n\n2008-11-18  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.cc.in, octave-bug.cc.in: Style fixes.\n\n2008-11-13  Ben Abbott  <bpabbott@mac.com>\n\n\t* src/graphics.h.in: Add props screensize & screenpixelsperinch.\n\n2008-11-08  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* Makeconf.in: export PERL variable for use in scripts/mkdoc\n\n2008-10-30  David Bateman  <dbateman@free.fr>\n\n\t* NEWS: Minor update to document improved indexing code.\n\n2008-10-23  Jason Riedy  <jason@acm.org>\n\n\t* configure.in: Take care to use FT2_CFLAGS when checking\n\tfor FTGL headers.\n\n2008-10-22  David Bateman  <dbateman@free.fr>\n\n\t* examples/@polynomial: Move examples/polynomial here.\n\t* examples/@polynomial/Makefile.in: Update for new location.\n\t* examples/Makefile.in: Ditto.\n\t* configure.in: Change locate of examples/@polynomial makefile\n\tin AC_CONFIG_FILES.\n\n2008-10-16  David Bateman  <dbateman@free.fr>\n\n\t* NEWS: Minor update.\n\n2008-10-15  David Bateman  <dbateman@free.fr>\n\n\t* examples/polynomial/display.m, examples/polynomial/double.m,\n\texamples/polynomial/end.m, examples/polynomial/get.m,\n\texamples/polynomial/mtimes.m, examples/polynomial/plot.m,\n\texamples/polynomial/polynomial.m,\n\texamples/polynomial/polynomial_superiorto.m,\n\texamples/polynomial/polyval.m, examples/polynomial/set.m,\n\texamples/polynomial/subsasgn.m, examples/polynomial/subsref.m:\n\tNew example files for a sample OOP class.\n\t* examples/polynomial/Makefile.in: Add a makefile for this new\n\tdirectory\n\t* examples/Makefile.in: Reference the new subdirectory here.\n\t* configure.in: Add the new makefile to AC_CONFIG_FILES.\n\n2008-10-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.in: Check for sizeof (long double) and randl.\n\n2008-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* aclocal.m4 (OCTAVE_FAST_INT_OPS): New macro.\n\t* configure.in: Call OCTAVE_FAST_INT_OPS\n\n2008-09-08  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.cc.in, octave-bug.cc.in, octave-config.cc.in: Style fixes.\n\n2008-09-08  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* mkoctfile.cc.in, octave-bug.cc.in, octave-config.cc.in: New files.\n\n2008-08-28  David Bateman  <dbateman@free.fr>\n\n\t* NEWS: Update for some of the graphics changes\n\n2008-08-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* acx_blas_f77_func.m4, acx_lapack.m4: Update macros from\n\t<http://autoconf-archive.cryp.to/>.\n\n2008-08-07  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_STRING_NPOS): Delete.\n\t* configure.in (OCTAVE_STRING_NPOS): Delete use.\n\n2008-08-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-subst-script-vals): Also substitute SED.\n\t* run-octave.in: Use sed to append : to path elements\n\tinstead of using the find expression \"-exec echo '{}':\".\n\tSubstitute SED here.\n\n\t* aclocal.m4: Fail if no usable version of sed is found.\n\n\t* Makefile.in (header-msg): Mention GNU Make requirement.\n\tUpdate GCC version info.\n\n2008-07-31  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (DISTFILES): Add \"missing\" to the list.\n\n2008-07-30  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (CXX_ABI, OCTAVE_CXX_PREPENDS_UNDERSCORE,\n\tOCTAVE_PROG_NM): Delete macros.\n\t* configure.in: Delete uses.\n\n2008-07-29  Tatsuro MATSUOKA  <tmacchant@yahoo.co.jp>\n\n\t* aclocal.m4 (OCTAVE_OPENGL): Handle MinGW the same as MSVC.\n\n2008-07-29  David Bateman  <dbateman@free.fr>\n\n\t* NEWS.3: Copy from NEWS.\n\t* NEWS: Initial update in preparation for a 3.2 release.\n\n2008-07-21  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: If FTGL.h is found, then also include\n\tFTGLTextureFont.h in test code.\n\n2008-07-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* configure.in: Remove GRAPHICS_OPENGL variable.\n\n2008-07-21  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_OPENGL): Fix shell syntax problems.\n\tHandle HAVE_GL_GL_H and HAVE_OPENGL_GL_H in link test.\n\n\t* configure.in: Don't define and substitute FLTK_BACKEND_SRC or\n\tGL_RENDER_SRC.\n\t(HAVE_FLTK): AC_DEFINE if FLTK is available.\n\t(HAVE_OPENGL): AC_DEFINE if OpenGL is available.\n\n2008-07-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.in: Extend FTGL test to test for both ftgl.h and FTGL.h.\n\tUse HAVE_FTGL_UPPERCASE to indicate the latter (version <= 2.1.2).\n\n2008-07-19 Rafael Laboissiere  <rafael@debia8n.org>\n\n\t* octMakefile.in (CONF_DISTFILES): Include acx_blas_f77_func.m4 in\n\tthe list.\n\n2008-07-18 Carlo de Falco  <carlo.defalco@gmail.com>\n\n\t* aclocal.m4: Search for gl.h and glu.h in OpenGL/ as well as in GL/.\n\n2008-07-18  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Fix FTGL test to handle either FTGL/ftgl.h or ftgl.h.\n\t(warn_freetype, warn_ftgl, warn_fltk_config, warn_fltk_opengl):\n\tNew variables.  Use these instead of overloading warn_graphics.\n\n2008-07-17  David Bateman  <dbateman@free.fr>\n\n\t* configure.in (HAVE_MAGICK): New define for presence of\n\tGraphicsMagick.\n\n2008-07-16  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* configure.in: Add check for pthread.h.\n\n2008-07-14  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (MAGICK_CONFIG): Substitute here.\n\t(MAGICK_INCFLAGS, MAGICK_LIBS): Define using GraphicsMagick++\n\tconfig script.\n\t(do-subst-config-vals): Include MAGICK_LIBS and MAGICK_INCFLAGS in\n\tlist of substitutions.\n\t* configure.in: Check for GraphicsMagick++ config script.\n\n2008-07-10  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (DIRS_TO_MAKE): Delete $(localfcnfilepath) and\n\t$(localoctfilepath) from the list.  Include $(datadir)\n\t$(localfcnfiledir) $(localapifcnfiledir) $(localverfcnfiledir)\n\t$(localoctfiledir) $(localapioctfiledir) $(localveroctfiledir)\n\t$(imagedir) and $(localapiarchlibdir) in the list.\n\n\t* configure.in: Look for FTGL/ftgl.h instead of FTGL/FTGL.h.  Also\n\tlook for ftgl.h.\n\n2008-07-10  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* configure.in: new substituted variables GL_RENDER_SRC and\n\tFLTK_BACKEND_SRC.\n\n2008-06-20  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Makeconf.in: Add GRAPHICS_CFLAGS substitution.\n\t* configure.in: Add checks for hypotf and _hypotf.\n\n2008-06-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.in: Move LIBS and CXXFLAGS restoration into\n\tthe proper block.\n\n2008-06-05  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Add FT2_CFLAGS to XTRA_CXXFLAGS, not CXXFLAGS.\n\tDon't add FT2_LIBS to LIBS.\n\tDon't generate src/graphics/Makefile, src/graphics/Makerules,\n\tsrc/graphics/opengl/Makefile, or src/graphics/fltk_backend/Makefile.\n\n\t* Makeconf.in (FT2_LIBS, GRAPHICS_LIBS): Substitute here.\n\n2008-06-04  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* configure.in: Use AC_TRY_LINK in FTGL test.\n\tInclude FT_CFLAGS in CXXFLAGS.\n\n\t* aclocal.m4 (OCTAVE_OPENGL): Note FIXME for apple.\n\n\t* configure.in: Check for FTGL library.\n\n\t* configure.in: Remove check for Fl/glu.h header.\n\n\t* aclocal.m4 (AC_CHECK_FT2): New macro to check for freetype2.\n\n\t* configure.in: Check for FLTK and corresponding compiler flags.\n\n2008-06-04  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* configure.in: Double-quote warn_graphics variable.\n\n\t* aclocal.m4 (OCTAVE_OPENGL): New function to detect OpenGL\n\theaders and libraries.\n\t* configure.in (OCTAVE_OPENGL): Use it.\n\t(OCTGRAPHICS_DLL_DEFS): New define to build\n\tgraphics-related DLL.\n\t(AC_CONFIG_FILES): Generate additional files for graphics\n\trelated libraries.\n\t* Makeconf.in (OPENGL_LIBS): New variable.\n\n\t* .hgignore: Also ignore build-.*, configure, and autom4te.cache.\n\n2008-05-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mk-opts.pl (emit_print_function, emit_set_function,\n\temit_show_function): Support float type.\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* configure.in (AC_CHECK_FUNCS): Add expm1, lgammaf, lgammaf_r,\n\tlog1pf and tgammaf. Also check for libfftw3f.\n\n2008-04-09  Rafael Laboissiere  <rafael@debian.org>\n\n\t* example/octave.desktop.in: Drop the Encoding key, which is\n\tdeprecated by the FreeDesktop standard.\n\n2008-04-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-check-m-sources): New macro.\n\n2008-04-03  Tatsuro MATSUOKA  <tmacchant@yahoo.co.jp>\n\n\t* README.Cygwin: Update.\n\n2008-04-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* acx_blas_f77_func.m4: New file.\n\t* configure.in: Call ACX_BLAS_WITH_F77_FUNC instead of ACX_BLAS.\n\tSupply a warning for incompatible Fortran/BLAS configuration.\n\n2008-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* configure.in: Check for expm1 and log1p functions.\n\n2008-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for trunc.\n\n2008-03-21  David Bateman  <dbateman@free.fr>\n\n\t* configure.in (HAVE_AMD): Complete test for presence of amd.\n\n2008-03-18  David Bateman  <dbateman@free.fr>\n\n\t* configure.in (AC_CHECK_FUNCS): Also check lgamma_r.\n\n2008-03-11  David Bateman  <dbateman@free.fr>\n\n\t* run-octave.in: Fix typo.\n\n2008-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (install install-strip): Ignore errors\n\tinstalling octave.desktop file.\n\n2008-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (*-*-freebsd*, *-*-openbsd*): Don't set SH_LD.\n\n2008-02-14  John W. Eaton  <jwe@octave.org>\n\n\t* examples/fortdemo.cc: Don't check f77_exception_encountered.\n\n2008-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (octave.desktop):\n\tUse mv instead of move-if-change.\n\n2008-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* dlfcn/Makefile.in: Unconditionally include $(MAKEDEPS).\n\tMark $(MAKEDEPS) as .PHONY targets if omit_deps is true.\n\n2008-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4: Call AC_SUBST instead of AC_DEFINE_UNQOTED for\n\tGNUPLOT_BINARY.\n\t* aclocal.m4, configure.in: Use GNUPLOT instead of GNUPLOT_BINARY\n\tas variable name.\n\t* Makeconf.in (GNUPLOT): Substitute.\n\t(do-subst-config-vals): Substitute GNUPLOT.\n\n2007-12-21  John W. Eaton  <jwe@octave.org>\n\n\tVersion 3.0.0 released.\n\n2007-12-13  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (octave-bug, octave-config, mkoctfile):\n\tAlso depend on $(top_srcdir)/src/version.h.\n\n2007-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* acx_blas.m4: Use -lsunperf, not -xlic_lib=sunperf.\n\tFrom Jim Langston <Jim.Langston@Sun.COM>.\n\n2007-12-06  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (*-*-darwin*): Only set CPICFLAG, CXXPICFLAG, and\n\tFPICFLAG to \"\" on powerpc systems.\n\n2007-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* octave-bug.in (LIBDLFCN): Delete variable and all uses.\n\t* Makeconf.in (LIBDLFCN, DLFCN_INCFLAGS): Likewise.\n\t* configure.in (DLFCN_DIR, LIBDLFCN, DLFCN_INCFLAGS): Likewise.\n\tDon't generate dlfcn/Makefile.\n\t* octMakefile.in (DISTSUBDIRS): Delete dlfcn from the list.\n\t(SUBDIRS): Don't substitute DLFCN_DIR here.\n\n2007-12-03  Moritz Borgmann  <octave@moriborg.de>\n\n\t* Makeconf.in, aclocal.m4, configure.in: Check for find program,\n\tpreferably gfind (on non-GNU systems).  Need a sane find for\n\trun-octave script.\n\t* run-octave.in: Use FIND and AWK as determined by configure.\n\n2007-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: If available, include <sys/types.h> in test for\n\tsigset_t and sig_atomic_t.\n\n2007-11-30  Moritz Borgmann  <octave@moriborg.de>\n\n\t* configure.in: Also check for sunmath.h.\n\n2007-11-26  David Bateman  <dbateman@free.fr>\n\n\t* PROJECTS: condest now implemented.\n\n\t* NEWS: Document the TeX interpreter mode and its limitations with\n\tgnuplot 4.0.\n\n\t* NEWS: Document the use of \"colormap gmap40\" to workaround some\n\tgnuplot 4.0 colormap issues.\n\n2007-11-14  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Don't create Makefrag.bsd.\n\n2007-11-14  Joseph P. Skudlarek  <Jskud@Jskud.com>\n\n\t* configure.in: Rework pcre.h tests to work with autoconf 2.59,\n\tand avoid explicit pcre/pcre.h check by using pcre-config.\n\n2007-11-13  Joseph P. Skudlarek  <Jskud@Jskud.com>\n\n\t* octave-bug.in: Try mailx, then Mail, then /usr/ucb/mail, then\n\t/bin/mail.\n\n2007-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Only define HAVE_PCRE_H if <pcre.h> has the\n\tdefinitions we need.  Likewise for <pcre/pcre.h>.\n\n2007-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Delete AC_SUBST_FILE(f77_rules_frag).\n\n2007-11-07  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Also check for pcre/pcre.h.\n\n2007-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Delete BLAS library calling convention\n\tcompatibility check.\n\n2007-10-31  John W. Eaton  <jwe@octave.org>\n\n\t* README.binary-dist: Delete.\n\n\t* README.MachTen: Delete.\n\t* octMakefile.in (DISTFILES): Remove it from the list.\n\n2007-10-30  David Bateman  <dbateman@free.fr>\n\n\t* examples/addtwomatrices.cc, examples/celldemo.cc,\n\texamples/firstmexdemo.c, examples/fortdemo.cc, examples/fortsub.f,\n\texamples/funcdemo.cc, examples/globaldemo.cc,\n\texamples/helloworld.cc, examples/mycell.c, examples/myfeval.c,\n\texamples/myfunc.c, examples/mypow2.c, examples/mysparse.c,\n\texamples/mystring.c, examples/mystruct.c, examples/paramdemo.cc,\n\texamples/stringdemo.cc, examples/structdemo.cc,\n\texamples/unwinddemo.cc: Doc fixes for small book format.\n\n2007-10-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Makeconf.in: Remove UNSETCOMSPEC trick.\n\n2007-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AH_BOTTOM): Define OCTAVE_EMPTY_CPP_ARG here.\n\n2007-10-24  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (maintainer-clean distclean): No need to delete\n\tMakefrag.f77 and Makerules.f77.\n\t* Makeconf.in: Include rules for making .o files from .f files\n\tinstead of substituting @f77_rules_frag@.\n\t* configure.in): Delete handling of --with-f2c and --with-f77\n\toptions.  No need to call OCTAVE_CHECK_EXCLUSIVE_WITH_OPTIONS.\n\tDelete all special cases for f2c.\n\t* aclocal.m4 (OCTAVE_CHECK_EXCLUSIVE_WITH_OPTIONS): Delete macro.\n\n\t* FLEX.patch: Delete obsolete file.\n\t* octMakefile.in (DISTFILES): Remove it from the list.\n\n\t* acx_blas.m4: Use \"-Wl,-framework -Wl,vecLib\" instead of\n\tjust \"-framework vecLib\" in test for Mac OS X test.\n\n\t* configure.in, aclocal.m4: Avoid AC_TRY_EVAL.\n\n\t* aclocal.m4 (OCTAVE_STRPTIME_BROKEN): New macro.\n\t* configure.in: Use it.\n\n2007-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: When checking for -lf2c, set F2CLIBS instad of\n\tFLIBS, then set FLIBS to $F2CLIBS just before printing the summary.\n\tCheck for BLAS library calling convention compatibility.\n\n2007-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Delete checks for METIS.\n\n2007-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* mk-opts.pl (parse_input): Allow comment lines beginning with #.\n\n\t* Change copyright notices in all files that are part of Octave to\n\tGPLv3 or any later version.\n\n\t* COPYING: Update to GPLv3.\n\n\t* run-octave.in: List args explicitly in exec command.\n\n2007-10-11  John W. Eaton  <jwe@octave.org>\n\n\t* config.guess, config.sub: Update from FSF sources.\n\n2007-10-10  Kim Hansen  <kimhanse@gmail.com>\n\n\t* run-octave.in: Use $args.  Eliminate \"if [ -n \"$args\" ]\" conditional.\n\n2007-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* gdbinit.in: Delete.\n\t* octMakefile.in (DISTFILES): Remove it from the list.\n\t(.gdbinit): Delete rule.\n\t(maintainer-clean, distclean): No need to delete .gdbinit.\n\n2007-10-09  Kim Hansen  <kimhanse@gmail.com>\n\n\t* run-octave.in: Use gdb with --args, not .gdbinit.\n\n2007-10-08  John W. Eaton  <jwe@octave.org>\n\n\t* emacs/octave-hlp.el, emacs/octave-inf.el, emacs/octave-mod.el:\n\tSync with GNU Emacs versions.\n\t* emacs/octave-mod.el: Delete last two args from calls to\n\tdefine-abbrev.\n\n2007-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for lgamma and tgamma.\n\n2007-10-04  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (UGLY_DEFS): Delete special case for darwin.\n\n2007-10-03  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_PROG_SED): Also check for \\(X\\|Y\\) style\n\tregular expression alternation.\n\n2007-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_CHECK_STRPTIME): Delete.\n\t* configure.in: Don't use OCTAVE_CHECK_STRPTIME, simply check for\n\tstrptime.\n\n2007-09-18  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* aclocal.m4 (OCTAVE_CHECK_STRPTIME): New macro.\n\t* configure.in: Use it.\n\n2007-09-06  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Avoid broken strptime function on Cygwin systems.\n\n2007-09-01  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: AC_SUBST and check the variable TEXINFO_QHULL.\n\t* Makeconf.in: Use it.\n\n2007-08-24  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Extra Qhull bits.\n\n2007-08-24  Kim Hansen  <kimhanse@gmail.com>\n\n\t* run-octave.in: Use `command` instead of $(command) to accomodate\n\tbrain-dead shells.\n\n2007-08-24  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Probe for the use of Qhull.\n\t* aclocal.m4 (AC_CHECK_QHULL_VERSION): Macro to check whether\n\tQhull needs a version number.\n\t* Makeconf.in: Add QHULL_LIBS.\n\n2007-08-23  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_PROG_SED): Don't clobber value from environment.\n\tFrom: Christian Cornelssen <ccorn@cs.tu-berlin.de>.\n\n2007-08-23  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* aclocal.m4 (OCTAVE_PROG_GNUPLOT): Drop check for multiple plot\n\twindows.\n\n2007-08-10  Søren Hauberg  <hauberg@gmail.com>\n\n\t* ROADMAP: Update for current sources.\n\n2007-07-26  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Also look for glpk/glpk.h.\n\n2007-07-25  David Bateman  <dbateman@free.fr>\n\n\t* octMakefile.in, dlfcn/Makefile.in, emacs/Makefile.in,\n\texamples/Makefile.in, test/Makefile.in: Adjust DISTFILES to allow\n\tout of tree \"make dist\" to work.\n\n2007-07-24  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* configure.in (*-*-msdosmsvc): Only add -g to DL_LDFLAGS and\n\tSH_LDFLAGS if either CFLAGS or CXXFLAGS contains -g.\n\n2007-07-24  Rafael Laboissiere  <rafael@debian.org>\n\n\t* Makeconf.in (RUNTEST): Delete variable substitution.\n\t(do-subst-config-vals): Don't substitute %OCTAVE_CONF_RUNTEST%.\n\n2007-07-20  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* mkoctfile.in: Fix typo.\n\n2007-06-25  John W. Eaton  <jwe@octave.org>\n\n\t* mk-opts.pl (emit_print_function): Make generated function print\n\tto ostream (passed as arg) instead of local buffer.  Don't call\n\tprint_usage in generated function.\n\t(emit_options_function): Fix call to print_${class_name} in\n\tgenerated to pass octave_stdout as arg.\n\n2007-06-18  John W. Eaton  <jwe@octave.org>\n\n\t* emacs/octave-inf.el (inferior-octave-prompt): Match \"octave.bin\"\n\tand \"octave.exe\" in addition to \"octave\".\n\n2007-06-15  John W. Eaton  <jwe@octave.org>\n\n\t* run-octave.in: Use simple string concatenation instead of\n\tsprintf in AWK program.\n\n2007-06-13  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* configure.in: Set NO_OCT_FILE_STRIP=true for msdosmsvc.\n\n\t* aclocal.m4 (OCTAVE_HDF5_DLL): Include return statements in\n\tfunction body used for test.\n\n\t* configure.in: Check for CXSparse with C++.\n\n\t* Makeconf.in (do-subst-config-vals): Also substitute ${libdir} as\n\tOCTAVE_CONF_LIBDIR.\n\t* mkoctfile.in: Set DEFAULT_LIBDIR and substitute OCTAVE_HOME.\n\tDefine LIBDIR.  Use LIBDIR to set DEFAULT_LFLAGS.\n\n2007-06-12  Benjamin Lindner  <lindnerben@gmx.net>\n\n\t* configure.in: For mingw, add -lws2_32 -lkernel32 to LIBS and set\n\t_USE_MATH_DEFINES same as for msvc.\n\n2007-06-06  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* configure.in: Check for utime.h and sys/utime.h headers.\n\tCheck for utime, _chmod, _utime, and _utime32 functions.\n\n2007-06-03  David Bateman  <dbateman@free.fr>\n\n\t* configure.in (AC_CONFIG_FILES): Add src/mxarray.h\n\t* examples/mycell.c, examples/mypow2.c, examples/mysparse.c,\n\texamples/mystring.c, examples/mystruct.c: Use mwSize and mwIndex,\n\trather than int for indexing to conform to new mex API.\n\n2007-06-01  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (*-*-darwin*): Fix quoting and construction of\n\tMKOCTFILE_DL_LDFLAGS.\n\t* mkoctfile.in (DEFAULT_BINDIR, EXEEXT): New substitutions.\n\t* Makeconf.in (MKOCTFILE_DL_LDFLAGS): Delete.\n\t(do-subst-config-vals): Do configure substitution of\n\tMKOCTFILE_DL_LDFLAGS directly here instead of using intermediate\n\tvariable.  Quote this sed substitution with ' instead of \".\n\n2007-05-29  Steven Mestdagh  <steven.mestdagh@esat.kuleuven.be>\n\n\t* configure.in: Delete spurious \"break\" in fftw3 check.\n\tUse separate case for SH_LD and SH_LDFLAGS on openbsd.\n\n2007-05-22  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-script-uninstall): Also remove directory.\n\n2007-05-22  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* NEWS.2, README.MSVC, WWW/NEWS-2.html: Fix typos.\n\n2007-05-16  David Bateman  <dbateman@free.fr>\n\n\t* PROJECTS: Update.\n\n2007-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (SOURCES): Add all example files to the list.\n\n\t* octave-config.in: Don't set PREFIX to OCTAVE_HOME if OCTAVE_HOME\n\tis empty.\n\n2007-04-27  David Bateman  <dbateman@free.fr>\n\n\t* examples/mycell.c, examples/mypow2.c, examples/mystring.c,\n\texamples/myprop.c: New example mex files.\n\n2007-04-26  Alex Zvoleff  <azvoleff@sbcglobal.net>\n\n\t* configure.in: Don't report ARPACK libraries in summary.\n\n2007-04-25  David Bateman  <dbateman@free.fr>\n\n\t* Makeconf.in (do-subst-texinfo-vals): Also substitute abs_top_srcdir.\n\n\t* examples/myfunc.c, exampples/paramdemo.cc: New files\n\t* examples/mystruct.c, examples/mysparse.c, fortdemo.cc: Fix a few\n\tformatting issues when included in texinfo files.\n\n2007-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-subst-texinfo-vals): Also substitute top_srcdir.\n\n\t* examples/addtwomatrices.cc, examples/celldemo.cc,\n\texamples/fortdemo.cc, examples/funcdemo.cc,\n\texamples/globaldemo.cc, examples/helloworld.cc,\n\texamples/stringdemo.cc, examples/structdemo.cc,\n\texamples/unwinddemo.cc, examples/fortsub.f,\n\texamples/firstmexdemo.c: New files.\n\t* examples/Makefile.in (SOURCES): Add them to the list.\n\n2007-04-20  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Don't check for ARPACK.\n\n2007-03-29  Rafael Laboissiere  <rafael@debian.org>\n\n \t* emacs/octave-mod.el: Drop LOADPATH, INFO_FILE, and\n \tINFO_PROGRAM from octave-variables.\n\n\t* examples/info-emacs-octave-help, examples/info-emacs-info:\n\tUse gnuclient, not gnudoit.\n\n2007-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (dist, conf-dist): Use ln, not $(LN_S).\n\t* emacs/Makefile.in (dist): Likewise.\n\t* examples/Makefile.in (dist): Likewise.\n\t* dlfcn/Makefile.in (conf-dist): Likewise.\n\n\t* config.guess, config.sub: Update from FSF sources.\n\n2007-03-23  John W. Eaton  <jwe@octave.org>\n\n\t* examples/make_int.cc (octave_integer::clone): Return type is\n\tpointer to octave_base_value, not octave_value.\n\t(Fdoit): Rep is reference to octave_base_value, not octave_value.\n\n2007-03-21  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* octMakefile.in (all): Print message after successful build.\n\n2007-03-05  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (GLPK_PRE_4_14): Rename from GLPK_PRE_4_15.\n\n2007-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-script-uninstall): Remove PKG_ADD.\n\t* examples/Makefile.in (uninstall): Don't remove files listed in\n\t$(SCRIPTS) from $(srcdir).\n\tRemove www.octave.org-octave.desktop, not octave.desktop.\n\n\t* run-octave.in (run-octave.in): Use --no-initial-path.\n\tRename to qargs to args.  Use $args not \"$args\" when invoking Octave.\n\tTry harder to get quoting right when passing args to Octave.\n\n2007-02-26  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (DISTDIRS): Eliminate variable.\n\n2007-02-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* octMakefile.in, dlfcn/Makefile.in, emacs/Makefile.in:\n\tUse $(LN_S) instead of ln or ln -s.\n\n\t* octMakefile.in (dist): Use -9 instead of --best with gzip/bzip2.\n\n2007-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Also warn about missing functionality for\n\t--without-glpk or --without-curl options.  Print curl library\n\twarning in summary.\n\n2007-02-20  Rafael Laboissiere  <rafael@debian.org>\n\n\t* configure.in: Check for versions of GLPK prior to 4.15 and set\n\tthe GLPK_PRE_4_15 macro accordingly.\n\n2007-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in: Use OCTAVE_PREFIX, not OCTAVE_CONF_PREFIX, in sed\n\tsubstitutions.\n\t* octave-conf.in: Define DATAROOTDIR, not DATADIR, from\n\tOCTAVE_DATAROOTDIR.\n\tFrom Michael Goffioul <michael.goffioul@swing.be>.\n\n2007-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* octave-config.in (DATAROOTDIR): Include in list of vars.\n\tSubstitute OCTAVE_HOME.\n\n\t* Makeconf.in (MKOCTFILE_INCFLAGS, MKOCTFILE_LFLAGS): Delete vars.\n\t(do-subst-config-vals): Don't substitute them.\n\tAlso substitute OCTAVE_CONF_INCLUDEDIR, OCTAVE_CONF_OCTINCLUDEDIR,\n\tOCTAVE_CONF_OCTLIBDIR, and OCTAVE_CONF_PREFIX here.\n\t* mkoctfile.in (OCTAVE_CONF_OCTINCLUDEDIR, OCTAVE_CONF_INCLUDEDIR,\n\tOCTAVE_CONF_OCTLIBDIR): Substitute values and perform OCTAVE_HOME\n\tsubstitution here.\n\t(DEFAULT_INCFLAGS, DEFAULT_LFLAGS): New variables.  Use them to\n\tset default values for INCFLAGS and LFLAGS.\n\n2007-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in: Handle .a files.\n\n2007-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (all): Depend on dist-info-files.\n\t(dist): Delete dist-info-files dependency.\n\n\t* configure.in: Rewrite if !( X ) ... fi as if X; true; else ... fi.\n\tAlso check for _glp_lpx_simplex.\n\n2007-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-script-install): Use $(FCN_FILES) for list of\n\tfiles instead of $(FCN_FILES_NO_DIR).  Use basename to get\n\tfilename with no directory part.\n\n2007-02-07  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* aclocal.m4 (OCTAVE_HDF5_DLL): New macro.\n\t* configure.in: Use it.\n\n2007-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for realpath function.\n\n\t* demo.m: Delete obsolete file.\n\n2007-01-29  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* configure.in (*-*-msdosmsvc): Set NO_OCT_FILE_STRIP to true.\n\n2007-01-24  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (install): Install NEWS file.\n\t(uninstall): Remove it.\n\n2007-01-08  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Replace sparsesuite with suitesparse to match\n\tupstream name.\n\n2006-12-06  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* acx_blas.m4, acx_lapack.m4: Handle f2c calling convention.\n\n2006-12-05  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Don't check for strptime on *-apple-darwin* systems.\n\n2006-11-28  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in: Construct default output file from basename of\n\tinput file name.\n\n2006-11-28  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Check for sparse header files in the sparsesuite\n\tsub-directory. In the cholmod tests, include the camd libraries, as\n\tthis might be a dependency for cholmod.\n\n2006-11-15  John W. Eaton  <jwe@octave.org>\n\n\t* run-octave.in: Don't forget LD_PRELOAD if there are args.\n\n2006-11-14  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: If warning message is printed, print additional\n\tfinal note about missing libraries.\n\n2006-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* run-octave.in: Substitute liboctinterp, liboctave, and libcruft.\n\tUse them to set LD_PRELOAD.\n\t* Makeconf.in (do-subst-script-vals): Also substitute\n\tliboctinterp, liboctave, and libcruft.\n\n2006-11-13  Rafael Laboissiere  <rafael@debian.org>\n\n\t* mkoctfile.in: Add -Wl,... options to ldflags, not pass_on_flags.\n\n2006-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (octave.desktop):\n\tUse $(simple-move-if-change-rule) here.\n\n\t* Makeconf.in (simple-move-if-change-rule,\n\t(builddir-move-if-change-rule): New macros.\n\n2006-11-11  Søren Hauberg  <hauberg@gmail.com>\n\n\t* examples/Makefile.in (uninstall): Add missing semicolon.\n\n2006-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (uninstall): New target.\n\n2006-11-09  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* configure.in (OCTAVE_LOCAL_BUFFER): Don't access first element\n\tif size is 0.\n\n2006-11-06  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* configure.in (CRUFT_DLL_DEFS, OCTAVE_DLL_DEFS, OCTINTERP_DLL_DEFS):\n\tAlso rename in AC_SUBST calls.\n\t* Makeconf.in (ALL_CFLAGS): Use DLL_CDEFS instead of XTRA_CDEFS.\n\t(ALL_CXXFLAGS): Use DLL_CDEFS instead of XTRA_CXXDEFS.\n\n2006-11-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (CRUFT_DLL_DEFS): Rename from XTRA_CRUFT_DEFS.\n\t(OCTAVE_DLL_DEFS): Rename from XTRA_OCTAVE_DEFS.\n\t(OCTINTERP_DLL_DEFS): Rename from XTRA_OCTINTERP_DEFS.\n\t(XTRA_CRUFT_LINK_FLAGS): Rename from XTRA_CRUFT_LINK_DEPS.\n\n2006-11-02  John W. Eaton  <jwe@octave.org>\n\n\t* README.Cygwin: Rename from README.Windows.\n\t* README.MSVC: New file.\n\t* README.Windows: Point to the README.Cygwin and README.MSVC files.\n\n2006-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for PCRE macros we use.  Warn if regex\n\tlibrary is not found.  Print hdf5, zlib, umfpack, colamd, ccolamd,\n\tcholmod, and cxsparse warnings when we detect the problems.\n\n\t* run-octave.in: Handle quoted args properly in exec call?\n\n2006-10-29  John W. Eaton  <jwe@octave.org>\n\n\t* run-octave.in: Handle spaces in directory names.\n\n2006-10-28  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* configure.in (AH_BOTTOM): If using MSVC, define __WIN32__ before\n\tother #ifdefs that use it.\n\n2006-10-27  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AH_BOTTOM): Move DLL defs to\n\tlibcruft/misc/oct-dlldefs.h and include it here.\n\n\t* aclocal.m4 (OCTAVE_PROG_TEXI2PDF): Require OCTAVE_PROG_TEXI2DVI.\n\tIf texi2pdf is not found but texi2dvi is available, set TEXI2PDF\n\tto \"$TEXI2DVI --pdf\".\n\t(OCTAVE_PROG_GHOSTSCRIPT): Also check for gswin32 on Windows systems.\n\n\t* Makeconf.in (UNSETCOMSPEC): Define if COMSPEC is defined.\n\tFrom Michael Goffioul <michael.goffioul@swing.be>.\n\n2006-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (OCTAVE_EXPORT, OCTAVE_IMPORT): New macros\n\t(CRUFT_API, OCTAVE_API, OCTINTERP_API): Define using OCTAVE_EXPORT\n\tand OCTAVE_IMPORT.\n\n2006-10-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* configure.in (*-*-msdosmsvc): Set library_path_var.\n\tCheck for _WIN32_WINNT >= 0x0403.  Define _USE_MATH_DEFINES if it\n\tis needed.\n\t(XTRA_CRUFT_LINK_DEPS): New variable.  Substitute it.\n\n\t* aclocal.m4 (OCTAVE_MKDIR_TAKES_ONE_ARG): Perform check with C++\n\tcompiler.\n\n2006-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_PROG_PAGER): Also check for more.com for\n\t*-*-mingw* and *-*-msdosmsvc systems.\n\n\t* configure.in (F77_TOLOWER, F77_APPEND_UNDERSCORE,\n\tF77_APPEND_EXTRA_UNDERSCORE): New variables.  Substitute them.\n\t* Makeconf.in (F77_TOLOWER, F77_APPEND_UNDERSCORE,\n\tF77_APPEND_EXTRA_UNDERSCORE): Substitute here.\n\t(do-subst-f77-mangling): New macro.\n\n\t* emacs/octave-inf.el (inferior-octave-has-built-in-variables):\n\tNew defvar.\n\t(inferior-octave-resync-dirs): Check to see whether Octave has\n\tbuilt-in variables and set inferior-octave-has-built-in-variables.\n\tCheck inferior-octave-has-built-in-variables to decide whether to\n\tsend commands that set built-in variables or call functions to\n\tchange Octave's behavior.\n\tSend \"disp (pwd ())\" to Octave instead of just \"pwd\".\n\t(inferior-octave-startup): Send \"more off\" to Octave instead of\n\t\"page_screen_output = 0\".\n\n2006-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (RETSIGTYPE_IS_VOID): Define if\n\t\"$ac_cv_type_signal\" = \"void\".\n\n\t* configure.in (*-*-msdosmsvc): Don't check for strftime.\n\n\t* configure.in (INCLUDE_DEPS): Set and substitute.\n\t(DEPEND_FLAGS, DEPEND_EXTRA_SED_PATTERN): Rearrange way these are set.\n\n\t* Makeconf.in (INCLUDE_DEPS): Substitute here, and use to set default\n\tvalue for omit_deps.\n\n2006-10-25  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makeconf.in (ALL_CFLAGS): Include $(XTRA_CDEFS) in the list.\n\t(ALL_CXXFLAGS): Include $(XTRA_CXXDEFS) in the list.\n\n\t* configure.in (XTRA_CRUFT_DEFS, XTRA_OCTAVE_DEFS,\n\tXTRA_OCTINTERP_DEFS): Define and substitute.\n\t(AH_BOTTOM) [_MSC_VER]: include definitions for CRUFT_API,\n\tOCTAVE_API, and OCTINTERP_API.\n\n\t* configure.in (*-*-msdosmsvc): Add \"-EHs -MD\" to CXXFLAGS.\n\tAdd \"-MD\" to CFLAGS.  Add \"-MD\" to CONFLIB_ARG when checking for\n\tlibf2c.\n\n\t* configure.in (*-*-msdosmsvc): Generate replacement unistd.h.\n\t* octMakefile.in (maintainer-clean, distclean): Also remove unistd.h.\n\n\t* configure.in (*-*-msdosmsvc): Default sepchar is ';'.\n\tDefine default LIBS (link against kernel32 and ws2_32).\n\tForce having LoadLibrary API.\n\n\t* configure.in (AH_BOTTOM) [_MSC_VER]: Define __WIN32__.\n\n2006-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in (OCTAVE_VERSION): No need to quote replacement here.\n\n2006-10-24  John W. Eaton  <jwe@octave.org>\n\n\t* run-octave.in: Only modify .gdbinit if -g option is given.\n\tUse $(/bin/pwd) instead of $(pwd).\n\n2006-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* emacs/Makefile.in (SOURCES, DISTFILES, install, install-strip,\n\tuninstall): Handle otags name change.\n\t* emacs/octave-tags, emacs/octave-tags.1: Rename from otags.\n\n2006-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for _isnan, _finite, and _copysign.\n\n2006-10-17  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* aclocal.m4 (OCTAVE_CXX_PREPENDS_UNDERSCORE, OCTAVE_CXX_ABI): Use\n\t$ac_objext instead of assuming .o.\n\t(OCTAVE_PROG_GNUPLOT): Handle *-*-msdos the same as *-*-cygwin*\n\tand *-*-mingw32*.\n\n2006-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for curl_easy_escap instead of\n\tcurl_global_init.\n\n2006-10-13  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* configure.in [_MSC_VER]: Disable some warnings.\n\t(*-*-msdos): New case for shared libraries.\n\t(LIBPRE): New variable.\n\t* Makeconf.in: Substitute it.\n\n2006-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AH_BOTTOM): Don't unconditionally #define\n\tOCTAVE_HAVE_POSIX_FILESYSTEM followed by a conditional #undef\n\tOCTAVE_HAVE_POSIX_FILESYSTEM since autoconf is commenting out the\n\t#undef.\n\n2006-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (CURL_LIBS, do-subst-config-vals):\n\tSubstitute CURL_LIBS.\n\n\t* configure.in: Check for libcurl.\n\n2006-10-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (library_path_var): Substitute value from configure.\n\t(do-subst-script-vals): Add library_path_var to the list.\n\t* run-octave.in: Substitute value here.\n\n2006-10-03  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Warn if PCRE library is not found.\n\n\t* configure.in: Include CAMD_LIBS, AMD_LIBS, and REGEX_LIBS in the\n\tsummary.\n\n2006-10-03  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Check for libcamd.\n\t* Makeconf.in (CAMD_LIBS): New variable.\n\n2006-09-27  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in [--mex]: Include -I. in incflags.\n\tFrom Søren Hauberg <hauberg@gmail.com>.\n\n2006-09-26  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AC_CONFIG_FILES):\n\tRemove doc/interpreter/images/Makefile from the list.\n\n2006-09-16  John W. Eaton  <jwe@octave.org>\n\n\t* octave-bug.in: Delete LIBPLPLOT variables.\n\n2006-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for locale.h and setlocale.\n\n2006-09-13  Christopher Hulbert  <cchgroupmail@gmail.com>\n\n\t* run-octave.in (LD_LIBRARY_PATH): Also append LD_LIBRARY_PATH\n\tfrom environment.\n\n2006-08-25  Alexander Barth  <abarth@marine.usf.edu>\n\n\t* mkoctfile.in: Accept .f90 and .F90 as Fortran files.\n\tPass $incflags and $defs to Fortran compiler.\n\n2006-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-subst-texinfo-vals): Don't substitute\n\t%CANONICAL_HOST_TYPE%.\n\n2006-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_PROG_GHOSTSCRIPT, OCTAVE_PROG_MAKEINFO,\n\tOCTAVE_PROG_TEXI2DVI, OCTAVE_PROG_TEXI2PDF): New macros.\n\t* configure.in: Use them.  Maybe print warnings in summary.\n\n2006-07-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (localapiarchlibdir): Substitute it here.\n\t(do-subst-default-vals): Include it in the sed command here.\n\t* configure.in (localapiarchlibdir): New variable.\n\t* octave-config.in: Don't quote %VAR% values.\n\t(LOCALAPIARCHLIBDIR): New variable.\n\n2006-07-27  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* octave-config.in (OCTAVE_FCNFILEPATH, OCTAVE_IMAGEPATH,\n\tOCTAVE_LOCALFCNFILEPATH, OCTAVE_LOCALOCTFILEPATH): Delete variables.\n\n2006-07-26  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in (Options): Accept -g.\n\n\t* configure.in: Check for exp2 and log2.\n\n2006-07-25  David Bateman  <dbateman@free.fr>\n\n\t* mysparse.c: New file.\n\n2006-06-27  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (maintainer-clean distclean): Remove\n\t$(SHELL_SCRIPTS) instead of naming files individually.\n\tAlso remove .gdbinit.\n\n2006-06-21  John W. Eaton  <jwe@octave.org>\n\n\t* examples/myfeval.c, examples/myfevalf.f, examples/myhello.c,\n\texamples/myset.c, examples/mystruct.c: New files.\n\n\t* mkoctfile.in: New option, --mex.\n\n2006-06-13  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (--enable-64): Include \"(EXPERIMENTAL)\" in help text.\n\tAlso set warn_64_bit if no suitable type for octave_idx_type is found.\n\tIf --enable-64 is specified, print warning in summary message.\n\n2006-06-12  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_CXX_BROKEN_REINTERPRET_CAST): New macro.\n\t* configure.in: Use it.\n\t* AH_BOTTOM: Conditionally define FCN_PTR_CAST here.\n\n2006-06-08  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-subst-default-vals): Also substitute\n\tOCTAVE_DATAROOTDIR.\n\n2006-06-06  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (datarootdir): New variable.\n\n\t* acx_lapack.m4 (acx_lapack_ok):\n\tUse AC_LINK_IFELSE+AC_LANG_PROGRAM instead of AC_TRY_LINK\n\n\t* aclocal.m4: Use AC_RUN_IFELSE+AC_LANG_SOURCE instead of AC_TRY_RUN.\n\n\t* acx_blas.m4, acx_lapack.m4, configure.in, aclocal.m4:\n\tUse AS_HELP_STRING instead of AC_HELP_STRING.\n\n\t* configure.in: Outside of other macros, use AC_MSG_NOTICE instad\n\tof AC_MSG_RESULT.  Check for sys_siglist using method from\n\tautoconf manual.\n\n\t* configure.in, Makeconf.in: octMakefile.in: Delete plplot cruft.\n\n\t* configure.in, aclocal.m4:\n\tUse AC_LINK_IFELSE+AC_LANG_PROGRAM instead of AC_TRY_LINK\n\tUse AC_COMPILE_IFELSE+AC_LANG_PROGRAM instead of AC_TRY_COMPILE.\n\tUse AS_HELP_STRING consistently with AC_ARG_WITH and AC_ARG_ENABLE.\n\n2006-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for inttypes.h and stdint.h.\n\n2006-05-19  John W. Eaton  <jwe@octave.org>\n\n\t* mk-opts.pl (emit_print_function, emit_options_function):\n\tGenerate print_usage calls with no args.\n\n2006-05-11  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (localfcnfilepath, localoctfilepath, fcnfilepath,\n\timagepath): Delete variables.\n\t* Makeconf.in (localfcnfilepath, localoctfilepath, fcnfilepath,\n\timagepath): Likewise.\n\t(do-subst-default-vals): Don't substitute them.\n\n\t* run-octave.in: Pass --image-path to octave.\n\tUse find to recursively add directories to loadpath.\n\tFixup set args command in .gdbinit here.\n\n2006-05-09  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (abs_top_srcdir): Substitute value here.\n\n2006-05-05  David Bateman  <dbateman@free.fr>\n\n\t    * Makeconf.in (do-subst-scripts-vals): Also replace\n\t    abs_top_srcdir.\n\t    * run-octave.in: Define top_srcdir as an absolute path.\n\n2006-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (SHELL_SCRIPTS): Include run-octave in the list.\n\n2006-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* NEWS: New contents for 3.0.\n\t* NEWS.2: Move contents of NEWS here.\n\n2006-04-29  John W. Eaton  <jwe@octave.org>\n\n\t* run-octave.in: Execute $builddir/src/octave, not src/octave.\n\n2006-04-26  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* configure.in: Fix apiversion vs. api_version typo.\n\n2006-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (TARGETS): Include run-octave and .gdbinit in the list.\n\t* Makeconf.in (subst-script-vals): New macro.\n\t* octMakefile.in (run-octave, .gdbinit): New rules.\n\t(DISTFILES): Include run-octave.in and gdbinit.in in the list.\n\n2006-04-17  John W. Eaton  <jwe@octave.org>\n\n\t* mk-opts.pl (emit_print_function): Emit code that uses\n\tstd::ostringstream directly.\n\n2006-04-13  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (CONST_CAST, DYNAMIC_CAST, REINTERPRET_CAST,\n\tSTATIC_CAST): Delete.\n\n2006-04-12  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: If using g++, also add -Wold-style-cast to CXXFLAGS.\n\n2006-03-28  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Don't check for MPI libraries.\n\n2006-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Downcase ac_cv_header_mach_o_dyld_h.\n\tFrom Martin Costabel <costabel@wanadoo.fr>.\n\n2006-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in: (TEXINFO_COLAMD, TEXINFO_CHOLMOD, TEXINFO_UMFPACK):\n\tSubstitute here.\n\t(do-subst-texinfo-vals): New macro definition.\n\n\t* configure.in: Don't substitute OCTAVE_VERSION, OCTAVE_HOSTTYPE,\n\tor OCTAVE_HOME.\n\t(AC_CONFIG_FILES): Remove doc/conf.texi from the list.\n\n2006-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Only print warnings for missing functionality in\n\tsummary message.\n\n2006-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* mk-opts.pl (emit_print_function): Buffer extra message here and\n\tpass to print_usage.\n\n2006-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-subst-default-vals): Also substitute OCTAVE_RELEASE.\n\n2006-03-08  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Update the test for CXSPARSE for new upstream release.\n\t(OCTAVE_VERSION, OCTAVE_HOSTTYPE, OCTAVE_HOME,TEXINFO_UMFPACK,\n\tTEXINFO_COLAMD, TEXINFO_CHOLMOD): New variables for texinfo\n\tdocumentation.\n\t(AC_CONFIG_FILES): Add doc/interpreter/images/Makefile and\n\tdoc/conf.texi.\n\n2006-03-02  Kurt Hornik  <Kurt.Hornik@wu-wien.ac.at>\n\n\t* emacs/octave-mod.el (octave-indent-for-comment): Make the code\n\tmatch the comments.\n\n2006-03-02  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (ALL_SUBDIRS): Delete.\n\t(SUBDIRS): Include src here.\n\t(SHELL_SCRIPTS): New variable.\n\t(all): Depend on $(SHELL_SCRIPTS) and $(SUBDIRS) with libcruft and\n\tliboctave filtered out.\n\t(src): Depend on liboctave.\n\t(liboctave): Depend on libcruft.\n\n2006-02-09  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Fix for probe of colamd, cccolamd and metis. New test\n\tfor the presence of cxsparse.\n\tMakeconf.in: Include CXSPARSE_LIBS.\n\n2006-01-19  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Use $WITH_PCRE instead of $HAVE_PCRE in shell test.\n\n2006-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for mach-o/dyld.h, not Mach-O/dyld.h.\n\tFrom Martin Costabel <costabel@wanadoo.fr>.\n\n2006-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-mkpkgadd): New macro.\n\n2005-12-14  David Bateman  <dbateman@free.fr>\n\n\t* Makeconf.in: Remove OCTAVE_PROG_RUNTEST.\n\t* alocal.m4: Remove OCTAVE_PROG_RUNTEST.\n\n\t* Makeconf.in: New tests of regex and pcre.\n\n2005-12-13  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (install install-strip): Fix typo.\n\tFrom William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>.\n\n2005-12-05  Kurt Hornik  <Kurt.Hornik@wu-wien.ac.at>\n\n\t* emacs/octave-inf.el (inferior-octave-startup):\n\tForce a non-empty string for secondary prompt PS2.\n\n2005-12-02  John W. Eaton  <jwe@octave.org>\n\n\t* emacs/octave-mod.el (octave-electric-space): Don't indent\n\tcomments or strings if octave-auto-indent is nil.\n\n2005-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (install install-strip): Install images and\n\tdesktop file.\n\n2005-11-29  Rafael Laboissiere  <rafael@debian.org>\n\n\t* emacs/octave-mod.el: Ensure that key bindings for\n\toctave-mark-defun and backward-kill-word work in both XEmacs and\n\tGNU Emacs.\n\n2005-11-28  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for uname.\n\n2005-11-21  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (DISTFILES): Don't include octave.desktop here.\n\t(distclean): Remove octave.desktop here.\n\t(maintainer-clean): Not here.\n\n2005-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (distclean, maintainer-clean):\n\tAlso remove octave.desktop.\n\tFrom Quentin Spencer <qspencer@ieee.org>.\n\n2005-11-01  Quentin Spencer  <qspencer@ieee.org>\n\n\t* octMakefile.in (CONF_DISTFILES): Delete acx_include_dirs.m4 from\n\tthe list.\n\n2005-10-28  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AC_ARG_WITH(cholmod, ...)): Fix typo.\n\tFrom Quentin Spencer <qspencer@ieee.org> and\n\tAndy Adler <adler@site.uOttawa.ca>.\n\n2005-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in, aclocal.m4: Don't quote \"yes\".\n\n\t* configure.in: Print warning messages for umfpack, colamd,\n\tccolamd, and cholmod as we are searching.  Avoid multiple\n\tdefinitions of message strings.\n\n\t* aclocal.m4 (OCTAVE_UMFPACK_SEPERATE_SPLIT):\n\tUse new method of finding umfpack.h.\n\t* configure.in: Use AC_CHECK_HEADERS instead of\n\tACX_CHECK_HEADER_IN_DIRS.\n\t(AC_CONFIG_FILES): Delete liboctave/oct-sparse.h from the list.\n\n\t* acx_include_dirs.m4: Delete.\n\n2005-10-26  Arno J. Klaassen  <arno@heho.snv.jussieu.fr>\n\n\t* configure.in [*-*-freebsd*] (SH_LDFLAGS): Properly quote.\n\t(RLD_FLAG): Set.\n\n2005-10-23  David Bateman  <dbateman@free.fr>\n\n\t* configure.in (OCTAVE_UMFPACK_SEPERATE_SPLIT): Check for metis\n\tseparately.\n\t* PROJECTS: Remove completed sparse matrix tasks.\n\n2005-10-17  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* octave.test/system/system.exp: rmdir no longer prints a\n\tmessage if the directory does not exist.\n\n\t* octave.test/system/mk-rm-dir-1.m: mkdir/rmdir return 1\n\ton success and 0 on failure.\n\n2005-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (F77_FFLOAT_STORE_FLAG):\n\tCheck for -ffloat-store option for Fortran compiler and set\n\tF77_FLOAT_STORE_FLAG if it works.\n\t* Makeconf.in: Substitute it here.\n\t(do-subst-config-vals): Substitute OCTAVE_CONF_F77_FLOAT_STORE_FLAG.\n\n2005-10-14  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_PROG_PYTHON): New macro.\n\t* configure.in: Use it.\n\t* Makeconf.in (PYTHON): Substitute it.\n\n2005-10-05  David Bateman  <dbateman@free.fr>\n\n\t mkoctfile.in: allow -idirafter argument.\n\n2005-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (install install-strip):\n\tConditionally install octave.desktop.\n\t(IMAGE_FILES, IMAGE_FILES_NO_DIR): New macros.\n\t(DISTFILES): Include IMAGE_FILES in list.\n\t(install install-strip): Install image file.\n\n\t* aclocal.m4 (OCTAVE_PROG_DESKTOP_FILE_INSTALL): New macro\n\t* configure.in: Use it.\n\t* Makeconf.in: Substitute DESKTOP_FILE_INSTALL.\n\n\t* octave.desktop.in: New file.  From Søren Hauberg <hauberg@gmail.com>.\n\t* examples/Makefile.in (SOURCES): Add it to the list.\n\t(octave.desktop): New target.\n\t(all): Depend on octave.desktop.\n\n2005-09-22  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_PROG_PERL): New macro.\n\t* configure.in: Use it.\n\t* Makeconf.in (PERL): Substitute it.\n\n\t* config.guess, config.sub: Update from FSF sources.\n\n2005-09-19  David Bateman  <dbateman@free.fr>\n\n\t* octMakefile.in (LN_S): Change to DESTDIR before LN_S to avoid\n\tlack of symlinks under mingw.\n\n2005-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sparse.h.in: Move to liboctave.\n\t* octMakefile.in (CONF_DISTFILES): Delete it from the list.\n\t(maintainer-clean, distclean, install, install-strip, uninstall):\n\tOmit rules for oct-sparse.h.\n\t* configure.in: Substitute liboctave/oct-sparse.h, not oct-sparse.h.\n\n2005-09-15  David Bateman  <dbateman@free.fr>\n\n\t* acx_include_dirs.m4 (AC_CHECK_HEADER_IN_DIRS): Define new macro.\n\t* oct-sparse.h.in: New AC_CONFIG_FILE.\n\t* configure.in: (AC_CHECK_HEADER_IN_DIRS): Use macro.\n\t(AMD_LIBS, COLAMD_LIBS, CCOLAMD_LIBS, CHOLMOD_LIBS): Probe for\n\tthese sparse library in addition to UMFPACK.\n\t(UMFPACK_INCLUDE, AMD_INCLUDE, COLAMD_INCLUDE, CCOLAMD_INCLUDE):\n\tAC_SUBST into oct-sparse.h.\n\t(LIBGLOB): Probe for external glob/fnmatch, define LIBGLOB.\n\t(sepchar): Define path seperation character in system dependent\n\tmanner. Use it with OCTAVE_SET_DEFAULT.\n\t(SEPCHAR, SEPCHAR_STR): Dpend on sepchar.\n\t(DL_LDFLAGS): Define for cygwin and mingw.\n\t(-lwsock32): Add to LIBS.\n\t(loadlibrary_api): Set for mingw/cygwin and autoconf test appears\n\tbroken.\n\t* Makeconf.in: Don't use \";\" as sed seperation to avoid confusion\n\twith sepchar.\n\t(LIBGLOB, AMD_LIBS, COLAMD_LIBS, CCOLAMD_LIBS, CHOLMOD_LIBS,\n\tsepchar): Substitute.\n\t* octMakefile.in: (CONF_DISTFILES): Add acx_include_dirs.m4 and\n\toct-sparse.h.in\n\t(oct-sparse.h): Include in install and clean directives\n\n2005-08-31  Pascal A. Dupuis  <Pascal.Dupuis@esat.kuleuven.be>\n\n\t* emacs/octave-inf.el (inferior-octave-startup): Call\n\tinferior-octave-resync-dirs here.\n\n2005-07-14  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (SH_LDFLAGS): Add -Wl,--enable-auto-image-base for\n\tCygwin and MinGW.\n\n2005-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AH_BOTTOM): Also define GCC_ATTR_DEPRECATED.\n\n2005-06-02  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (do-subst-default-vals): Substitute\n\t${localstartupfiledir}, not ${localstartupfile} (which is undefined).\n\n2005-05-16  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Change UMFPACK_LONG_IDX to IDX_TYPE_LONG.\n\n2005-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AC_CHECK_LIB($zlib_lib, ...)): Check for\n\tgzclearerr instead of deflate.\n\n2005-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AC_ARG_WITH(umfpack)): List -lumfpack ahead of -lamd.\n\tFrom Dmitri A. Sergatskov <dasergatskov@gmail.com>.\n\n2005-04-29  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Add UMFPACK_LONG_IDX\n\n2005-04-21  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AC_CONFIG_FILES): Remove install-octave from the list.\n\t(AH_BOTTOM): Define SIZEOF_OCTAVE_IDX_TYPE.\n\n2005-04-14  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in: Only perform link step if we have some object files.\n\tIf only -v or --version is supplied, print version info and exit.\n\n2005-04-08  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (maintainer-clean distclean):\n\tRemove install-octave from the list of files to remove.\n\t(install-octave.in): Delete file.\n\t(DISTFILES): Remove it from the list.\n\n\t* Initial merge of 64-bit changes from Clinton Chee:\n\n\t2005-04-07  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (--enable-64): Make default disabled.\n\n\t2005-04-06  John W. Eaton  <jwe@octave.org>\n\n\t* mk-opts.pl (emit_show_function, emit_set_functions,\n\temit_print_function): Also accept \"octave_idx_type\" and\n\t\"Array<octave_idx_type>\".\n\n\t2005-04-01  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (USE_64_BIT_IDX_T): Substitute value.\n\t(do-subst-config-vals): Add to list of substitutions.\n\n\t* configure.in (AC_CONFIG_FILES): Perform substitutions on\n\tliboctave/oct-types.h too.\n\tHandle --enable-64.\n\n2005-04-06  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Split the HDF5 and zlib detection code, so that zlib\n\tcan be used for compressed load/save in the absence of HDF5.\n\n\t* Makeconf.in: Define UMFPACK_LIBS.\n\n\t* Configure.in: Slightly alter the UMFPACK detection code so that it\n\tcorrectly detects cblas bindings or not.\n\n2005-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* Makeconf.in (GLPK_LIBS): Substitute value.\n\t(do-subst-config-vals): Add to list of substitutions.\n\n\t* configure.in: Check for glpk.\n\n\t* emacs/octave-mod.el (octave-abbrev-table): Omit fifth and sixth\n\targuments from define-abbrev for compatibility with some older\n\tversions of Emacs.\n\n2005-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* octave-bug.in: Try harder to find default pager (use code\n\tsimilar to that used for finding default editor).\n\n2005-03-17  Shan G. Smith  <shan@cybertrails.com>\n\n\t* configure.in: Move check for -lumfpack to after check for blas.\n\n2005-03-17  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: If first check for -lumfpack fails try again with\n\t-lcblas as an additional library.\n\n\t* configure.in: Change defaults to enable shared libraries and\n\tdynamic linking and disable static libraries.\n\n2005-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (DISTFILES): Remove texi2dvi from the list.\n\n\t* emacs/octave-inf.el, emacs/octave-mod.el, emacs/octave-hlp.el:\n\tImport changes from Emacs.\n\n2005-03-14  Rafael Laboissiere  <rafael@debian.org>\n\n\t* emacs/octave-mod.el (octave-end-keywords): Omit \"end\" from the list.\n\t(octave-reserved-words): Include \"end\" here.\n\t(octve-block-match-alist): Don't include \"end\" here.\n\n2005-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for umfpack/umfpack.h instead of just umfpack.h.\n\n2004-06-22  David Bateman  <dbateman@free.org>\n\n\t* configure.in: Check for UMFPACK library and header files.\n\n2005-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Also print a warning if HDF5 library is not found.\n\n2005-03-10  John W. Eaton  <jwe@octave.org>\n\n\t* mkoctfile.in: Accept -R DIR.\n\n2005-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* examples/Makefile.in (bin-dist): Delete target.\n\t(BINDISTFILES): Delete variable.\n\t* emacs/Makefile.in: Likewise.\n\n\t* octMakefile.in (VERSION, ARCH, binary-dist): Delete targets.\n\t(XBINDISTFILES, BINDISTFILES, BINDISTSUBDIRS): Delete variables.\n\n2005-03-04  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (GXX_PICKY_FLAGS): Don't include\n\t-Wmissing-prototypes or -Wstrict-prototypes.\n\n2005-03-02  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_CC_FLAG, OCTAVE_CXX_FLAG, OCTAVE_F77_FLAG):\n\tUse AC_LINK_IFELSE instead of AC_TRY_LINK.\n\n\t* configure.in (OCTAVE_LOCAL_BUFFER): Use < T > instead of <T>.\n\tFrom Clinton Chee <chee@parallel.hpc.unsw.edu.au>.\n\n2005-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AC_CONFIG_FILES): Remove libcruft/odessa/Makefile\n\tfrom the list.\n\n2005-03-01  Todd Neal  <tolchz@gmail.com>\n\n\t* examples/make_int.cc: DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA now\n\ttakes three arguments.\n\n\t* octMakefile.in (SUBDIRS, CLEANSUBDIRS):\n\tRemove @GLOB_DIR@ from the list.\n\n2005-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* octMakefile.in (DISTDIRS): Remove glob from the list.\n\t(dist): No need to clean up in glob subdirectory.\n\t* glob: Delete directory.\n\t* Makeconf.in (GLOB_INCFLAGS, LIBGLOB): Delete.\n\t(do-subst-config-vals): Don't substitute them.\n\t(INCFLAGS): Remove $(GLOB_INCFLAGS) from the list.\n\t* configure.in: Don't test for glob or fnmatch.\n\n2005-02-22  Shan G. Smith  <shan@cybertrails.com>\n\n\t* mkoctfile.in: If not linking, then use output file name\n\tspecified with -o.\n\n2005-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* texi2dvi: Delete our private version.\n\n\t* Makeconf.in (MAKEINFO): Define.\n\t(TEXI2DVI): Define as texi2dvi, not $(top_srcdir)/texi2dvi.\n\n2005-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for canonicalize_file_name and resolvepath.\n\n2005-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* config.guess, config.sub: Update from FSF sources.\n\n2005-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* octave-bug.in: Try harder to find default editor (stolen from\n\tbashbug).\n\n2004-12-17  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Use AC_GNU_SOURCE.\n\n2004-12-17  Orion Poplawski  <orion@cora.nwra.com>\n\n\t* configure.in: Also check for signbit decl.\n\n2004-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* aclocal.m4 (OCTAVE_PROG_GPERF): Check with -L C++, not -L ANSI_C.\n\t* Makefile.in (header-msg): Change recommended gperf version to\n\t3.0.1 or more recent.\n\n2004-11-12  John W. Eaton  <jwe@octave.org>\n\n\t* Back off on -ffloat-store until we decide whether it is really\n\tnecessary.\n\n2004-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* (OCTAVE_PROG_GNUPLOT): Don't set GNUPLOT_BINARY before calling\n\tAC_CHECK_PROGS(GNUPLOT_BINARY, ...).\n\n\t* configure.in: Use it to see if the C, C++, and Fortran compilers\n\taccept -ffloat-store.\n\t* aclocal.m4 (OCTAVE_F77_FLAG): New macro.\n\n2004-09-08  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (GXX_PICKY_FLAGS): Remove -fno-nonnull-objects.\n\t(GCC_PICKY_FLAGS): Remove -Wnested-externs -Wid-clash-31.\n\tFrom Quentin Spencer <qspencer@ieee.org>.\n\n\t* configure.in (GCC_PICKY_FLAGS): Remove -Winline.\n\n2004-09-07  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Check for round.\n\n2004-06-22  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Use -Wl,-Bsymbolic for MKOCTFILE_DL_LDFLAGS on\n\tGNU/Linux systems but not for SH_LDFLAGS.\n\n2004-04-22  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in: Add -Wl,-Bsymbolic to SH_LDFLAGS for GNU/Linux\n\tsystems.  From Fredrik Lingvall <Fredrik.Lingvall@signal.uu.se>.\n\n\t* mkoctfile.in: Allow -Wx,option style options to be passed to the\n\tcompiler.  From Al Niessner <Al.Niessner@jpl.nasa.gov>.\n\n2004-04-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Delete code for --with-ieee754.\n\tUse OCTAVE_IEEE754_DATA_FORMAT.\n\n\t* aclocal.m4 (OCTAVE_IEEE754_DATA_FORMAT): New macro, based on\n\tconfigure.in code for HAVE_IEEE754_COMPLIANCE.\n\n2004-04-06  David Bateman  <dbateman@free.fr>\n\n  \t* configure.in : add the option --with-ieee754 and use it to define\n\tHAVE_IEEE754_COMPLIANCE\n\n2004-04-02  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Warn about g++ 2.9x versions.\n\n2004-04-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (dist): Also make bz2 file and compute md5\n\tchecksums of both gz and bz2 files.\n\n2004-03-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: No longer accept --with-g77 (it is still possible\n\tto use --with-f77=g77).\n\n2004-03-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for -mieee instead of -mieee-with-inexact.\n\n2004-02-20  Per Persson  <persquare@mac.com>\n\n\t* mkoctfile.in (LINK_DEPS): Include $LDFLAGS in the list.\n\n2004-02-18  Per Persson  <persquare@mac.com>\n\n\t* configure.in (*-*-darwin*): Define SONAME_FLAGS.\n\n2004-02-16  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Test for the presence of FFTW 3.x and use it in\n\tpreference to FFTW 2.x.  Define HAVE_FFTW3\n\n2004-02-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in (LINK_DEPS): Include $LIBS and $RLD_FLAG.\n\tUse $OCTAVE_LIBS instead of listing libs individually.\n\n2004-02-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Delete INCLUDE_LINK_DEPS.  Fix help text.\n\tAlways define LINK_DEPS.\n\t(LINK_DEPS): Also include FLIBS in the list.\n\n\t* Makeconf.in (INCLUDE_LINK_DEPS): Don't substitute.\n\t(do-subst-config-vals): Delete INCLUDE_LINK_DEPS.\n\t* configure.in (INCLUDE_LINK_DEPS): Delete.\n\n\t* mkoctfile (SH_LD, SH_LDFLAGS): Delete.\n\t(DL_LD, DL_LDFLAGS): New variables.  Use them instead of SH_LD and\n\tSH_LDFLAGS for creating .oct files.\n\tFix help text.\n\n\t* configure.in (MKOCTFILE_SH_LDFLAGS): Delete.\n\t(MKOCTFILE_DL_LDFLAGS): New variable, default to DL_LDFLAGS.\n\n\t* Makeconf.in (do-subst-config-vals): Add DL_LD, DL_LDFLAGS, and\n\tMKOCTFILE_DL_LDFLAGS to the list of substitutions.\n\tDelete MKOCTFILE_SH_LDFLAGS.\n\n2004-02-14  Per Persson  <persquare@mac.com>\n\n\t* configure.in (DL_LD, DL_LDFLAGS): New variables, default to\n\tSH_LD and SH_LDFLAGS, respectively.\n\tDefine independently for SH_LD and SH_LDFLAGS for *-*-darwin* targets.\n\t* Makeconf.in (DL_LD, DL_LDFLAGS): Substitute them here.\n\n2004-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (header-msg): Required bison version now 1.31 or later.\n\n2004-01-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el: If line-end-position is not defined,\n\tprovide it as an alias for point-at-eol.\n\n2004-01-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el: If line-beginning-position is not defined,\n\tprovide it as an alias for point-at-bol.\n\n2004-01-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AH_BOTTOM):\n\tDefine OCTAVE_LOCAL_BUFFER using vector<T> instead of auto_ptr.\n\tSuggested by Paul Thomas <Paul.Thomas@jet.efda.org>\n\n2004-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (maintainer-clean, distclean):\n\tRemove Makefile and autom4te.cache.\n\n2004-01-14  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Test for the presence of the function\n\tH5Gget_num_objs\tin HDF5 library, and define HAVE_H5GGET_NUM_OBJS.\n\n2004-01-06  Per Persson  <persquare@mac.com>\n\n\t* aclocal.m4 (OCTAVE_CXX_PREPENDS_UNDERSCORE): Recognize\n\t*-*-darwin*, not *-*-darwin6*.\n\n2003-12-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* INSTALL: Update to newer version from autoconf.\n\n2003-11-26  Cyril Humbert  <Cyril.Humbert@univ-mlv.fr>\n\n\t* octave-config.in (--m-site-dir): Echo $LOCALVERFCNFILEDIR, not\n\t$OCTAVE_LOCALVERFCNFILEDIR.\n\t(--oct-site-dir): Echo $LOCALVEROCTFILEDIR, not\n\t$OCTAVE_LOCALVEROCTFILEDIR.\n\n2003-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Also maybe add -W to WARN_CFLAGS and WARN_CXXFLAGS.\n\n2003-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (SHLLIB_VER): Fix typo.\n\n\t* Makeconf.in (WARN_CFLAGS, WARN_CXXFLAGS): Substitute them.\n\t(ALL_CFLAGS, BUG_CFLAGS): Add $(WARN_CFLAGS).\n\t(ALL_CXXFLAGS, BUG_CXXFLAGS): Add $(WARN_CXXFLAGS).\n\t(UGLY_ALL_CXXFLAGS): Delete.\n\n\t* configure.in: Add -Wall and -Wshadow to WARN_CFLAGS and\n\tWARN_CXXFLAGS instead of CFLAGS and CXXFLAGS.\n\n2003-11-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: If we need alloca, then also include it in LIBGLOB.\n\n2003-11-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Preserve CFLAGS and CXXFLAGS before doing anything.\n\tMaybe add -Wshadow to CFLAGS and CXXFLAGS.\n\n2003-10-24  Stefan Monnier  <monnier@iro.umontreal.ca>\n\n\t* emacs/octave-mod.el (octave-comment-start): Simplify.\n\t(octave-point): Remove.\n\t(octave-in-comment-p, octave-in-string-p)\n\t(octave-not-in-string-or-comment-p, calculate-octave-indent)\n\t(octave-blink-matching-block-open, octave-auto-fill):\n\tUse line-(beginning|end)-position instead.\n\n2003-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-inf.el (inferior-octave-prompt): Don't bother\n\tmatching \"octave.bin\".\n\n2003-10-29  Lute Kamstra  <lute@gnu.org>\n\n\t* emacs/octave-inf.el (inferior-octave-prompt): Recognize\n\tversion number in prompt.\n\n2003-10-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-mode-syntax-table): Allow % to be a\n\tcomment character.\n\n2003-10-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (AWK): Substitute and export it.\n\t* configure.in: Also check for AWK.\n\n2003-10-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_PREREQ): Require 2.57.\n\n2003-09-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AH_BOTTOM): Don't define HEAVYWEIGHT_INDEXING here.\n\n2003-07-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-variables): Delete\n\tpropagate_empty_matrices from the list.\n\n\t* ck-oct-fcns.m: Delete.\n\n2003-07-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Warn if --enable-dl but not --enable-shared.\n\n2003-07-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-variables): Delete\n\tdefault_return_value and define_all_return_values from the list.\n\tAdd warn_undefined_return_values to the list.\n\n2003-07-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-variables):\n\tAdd warn_empty_list_elements and warn_resize_on_range_error to the\n\tlist.\n\tDelete empty_list_elements_ok and resize_on_range_error from the\n\tlist.\n\n2003-07-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-variables): Add warn_neg_dim_as_zero\n\tto the list.\n\tDelete treat_neg_dim_as_zero from the list.\n\n2003-07-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-variables): Include\n\tDEFAULT_EXEC_PATH, DEFAULT_LOAD_PATH, crash_dumps_octave_core,\n\tsighup_dumps_octave_core, sigterm_dumps_octave_core,\n\twarn_imag_to_real, warn_num_to_str, warn_str_to_num, and\n\twarn_fortran_indexing in the list.\n\tDelete ok_to_lose_imaginary_part, implicit_num_to_str_ok,\n\timplicit_str_to_num_ok, prefer_column_vectors,\n\tprefer_zero_one_indexing, and do_fortran_indexing from the list.\n\n2003-07-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-default-vals): Substitute OCTAVE_API_VERSION.\n\t* octave-config.in: Handle new variable OCTAVE_API_VERSION.\n\n\t* octMakefile.in (DIRS_TO_MAKE): Delete undefined vars\n\t$(localfcnfilepathdirs) and $(localoctfilepathdirs) from the list.\n\n\t* octave-config.in: Handle new variables OCTAVE_LOCALAPIFCNFILEDIR\n\tand OCTAVE_LOCALAPIOCTFILEDIR\n\n\t* configure.in (localapifcnfiledir): New variable.\n\t(localfcnfilepath): Add it to the list.\n\t(localapioctfiledir): New variable.\n\t(localoctfilepath): Add it to the list.\n\t* Makeconf.in (do-subst-default-vals): Substitute new varibles.\n\n\t* Makeconf.in (getapiversion, apiversion): New macros.\n\n\t* octMakefile.in (DIRS_TO_MAKE): Include $(localverarchlibdir) in\n\tthe list.\n\n2003-07-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in: Set and substitute values for startupfiledir and\n\tlocalstartupfiledir.\n\n\t* octave-config.in: Allow other configuration defaults to be\n\taccessed using --variable VAR option.\n\n2003-07-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (distclean): remove install-octave here.\n\n2003-06-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: If user doesn't specify --enable-rpath, then\n\tdefault is to enable it.\n\n2003-06-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (GNUPLOT_HAS_FRAMES): Eliminate variable.\n\n\t* emacs/octave-mod.el (octave-variables): Eliminate\n\tgnuplot_has_multiplot.\n\n2003-05-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: In check for f_open in libf2c, only use\n\t-L. -lconflib if we have created libconflib.a.\n\n2003-05-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_PROG_GPERF): Provide struct decl so -t option\n\tsucceeds with gperf 3.0.\n\n\t* Makeconf.in (NO_OCT_FILE_STRIP): Use -C arg for make.\n\n\t* octMakefile.in (DIRS_TO_MAKE): Use $(shell ...) instead of `...`.\n\n2003-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in, octMakefile.in, emacs/Makefile.in,\n\texamples/Makefile.in: Handle DESTDIR.\n\n2003-05-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (sbindir): New variable substitution.\n\n2003-04-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't define WITH_KPATHSEARCH.\n\n2003-04-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Look for wsock32 library on MinGW systems.\n\n2003-04-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (OCTAVE_LOCAL_BUFFER): Always allocate temporary\n\tbuffer using new.\n\n2003-04-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in octMakefile.in: Delete kpathsea targets.\n\n\t* kpathsea: Delete all files and directory.\n\n\t* configure.in: Don't run configure in kpathsea subdirectory.\n\n\t* README.kpathsea: New file.\n\t* octMakefile.in (DISTFILES): Include it in the list.\n\n\t* Makeconf.in (do-subst-config-vals): Don't substitute it.\n\n\t* configure.in: Also check for basename.\n\tDon't substitute LIBKPATHSEA.\n\n2003-04-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AH_BOTTOM): Don't assume that __WIN32__ will be\n\tdefined when __CYGWIN__ is defined.\n\n2003-03-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Only complain for g++ earlier than 2.95.\n\tTry harder to get version number only.\n\n2003-03-05  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* aclocal.m4 (OCTAVE_DYNAMIC_AUTO_ARRAYS): New macro.\n\t* configure.in: Use it.\n\t(AH_BOTTOM): Check HAVE_DYNAMIC_AUTO_ARRAYS instead of __GNUG__.\n\n2003-03-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Undo previous change.\n\t* Makeconf.in: Likewise.\n\n2003-03-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (KPATHSEA_INCFLAGS): New variable.\n\t* Makeconf.in (KPATHSEA_INCFLAGS): Substitute it.\n\t(do-subst-config-vals): Add it to the list.\n\t(INCFLAGS): Add $(KPATHSEA_INCFLAGS).\n\n2003-02-23  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* aclocal.m4 (OCTAVE_PLACEMENT_DELETE): New macro.\n\t* configure.in: Use it.\n\t(AH_BOTTOM): Don't define HAVE_PLACEMENT_DELETE here.\n\n2003-02-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Allow RLD_FLAG to be set using --enable-rpath arg.\n\n\t* configure.in: Fix default RLD_FLAG value for *-sgi-*.  From\n\tPaul Kienzle <pkienzle@users.sf.net>.\n\n\t* configure.in: Check for long long int and unsigned long long int.\n\n\t* configure.in (AH_BOTTOM): Define HAVE_PLACEMENT_DELETE for gcc\n\t3.2 and later.\n\n\t* configure.in: Check for copysign and signbit.\n\n2003-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/Makefile.in (DISTFILES): Add otags.1 to the list.\n\n2003-02-18  Dirk Eddelbuettel  <edd@debian.org>\n\n\t* emacs/otags.1: New file.\n\n2003-02-18  David Bateman  <dbateman@free.fr>\n\n\t* configure.in: Eliminate linpack\n\n2003-02-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for mkstemp too.\n\n2003-02-13  Arno Klaassen  <arno@scito.com>\n\n\t* configure.in: Fix SH_LD and SH_LDFLAGS for -*-*-freebsd*.\n\n2003-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Use '$(CXX)', '$(AR)', not \"$CXX\" and \"$AR\" when\n\tsetting variables for building shared libraries.\n\n2003-02-13  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* examples/make_int.cc: Support for ISO standard compilers.\n\n2003-01-22  Richard Stallman  <rms@gnu.org>\n\n\t* emacs/octave-mod.el (octave-mode-map): Avoid binding keys that\n\tare reserved for users.\n\n2003-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in: Fix typo in previous change.\n\n2003-01-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (MKOCTFILE_INCFLAGS): Skip -I$(includedir) if\n\t$(includedir) is /usr/include.\n\n2003-01-16  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* Makeconf.in (SED): Export to subshells.\n\n2003-01-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't bother with compiler flags for\n\texplicit/no-implicit template instantiation.\n\n2003-01-11  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* configure.in, Makeconf.in: Allow setting of BUILD_LDFLAGS.\n\n2003-01-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* autogen.sh: Use --force for autoconf and autoheader.\n\n2003-01-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (CONF_DISTFILES): Include acx_blas.m4 and\n\tacx_lapack.m4.\n\n\t* configure.in (BUILD_CC, BUILD_CFLAGS, BUILD_CXX,\n\tBUILD_CXXFLAGS): Kluge for Sun C/C++.\n\n2003-01-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Default value of BUILD_CXX is $CXX, not g++.\n\t(AH_BOTTOM): Define __USE_STD_IOSTREAM if using Compaq C++ compiler.\n\tFor compiler/linker options, use -Wl,OPT instead of -Xlinker OPT.\n\tCheck for -ieee option for the C and C++ compilers on alpha systems.\n\n2003-01-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Fail on all gcc 1.x and 2.x versions.\n\n2002-12-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (OCTAVE_LOCAL_BUFFER): New macro.\n\n2002-12-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Include $LIBOCTINTERP in the stand alone link command.\n\tDefine LIBOCTAVE, LIBOCTINTERP, LIBCRUFT, LIBREADLINE using -lLIB.\n\n2002-12-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-script-install, do-script-uninstall):\n\tNew macros, used in Makefiles in scripts subdirectory.\n\t(do-script-install): Use new scripts/mkpkgadd script to construct\n\tPKG_ADD files.\n\n2002-12-03  Nix  <nix@esperi.demon.co.uk>\n\n\t* configure.in: Use AC_CHECK_DECL in conjunction with\n\tAC_DECL_SYS_SIGLIST to ensure signal.h is searched.\n\n2002-12-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Dont't set SONAME_FLAGS for alpha alpha*-dec-osf*\n\tsystems.\n\n2002-11-29  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* mkoctfile.in: Include \"$incflags $def\" in commands to generate\n\tdependecies.\n\n2002-11-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (do-subst-config-vals): Substitute OCTAVE_BINDIR.\n\n\t* configure.in (MKOCTFILE_SH_LDFLAGS): New variable.\n\t* Makeconf.in (do-subst-config-vals): Substitute\n\tOCTAVE_CONF version of this variable.\n\n\t* mkoctfile.in: Set SH_LDFLAGS from MKOCTFILE_SH_LDFLAGS, not\n\tSH_LDFLAGS.\n\t(VERSION): Substitute value of OCTAVE_CONF_VERSION.\n\n\t* configure.in (NO_OCT_FILE_STRIP): New variable.\n\t* Makeconf.in (do-subst-config-vals): Substitute it.\n\t* mkoctfile.in (no_oct_file_strip_on_this_platform): New variable.\n\n2002-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (OCTAVE_CXX_PRAGMA_INTERFACE_IMPLEMENTATION):\n\tDelete use.\n\n\t* aclocal.m4 (OCTAVE_LANG_PROG_NO_CONFDEFS): Delete.\n\t(OCTAVE_CXX_PRAGMA_INTERFACE_IMPLEMENTATION): Delete.\n\n2002-11-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for dlopen last, to avoid broken\n\tcompatibility libraries.\n\tDefault value for SHLLIB is '$(SHLEXT)', not $SHLEXT.\n\n2002-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (USE_EXCEPTIONS_FOR_INTERRUPTS): No need to define.\n\n2002-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for sigsetjmp and siglongjmp.\n\t(AH_BOTTOM): If both are found, define OCTAVE_HAVE_SIG_JUMP.\n\tAlso check for sig_atomic_t, typedef it if not available.\n\n2002-11-10  Per Persson  <persquare@mac.com>\n\n\t* configure.in: Detect dyld API for dynamic linking on OS X.\n\n2002-11-09  Per Persson  <persquare@mac.com>\n\n\t* configure.in: Use $(TOPDIR)/src/octave, not $(bindir)/octave for\n\t-bundle-loader argument.\n\n\t* aclocal.m4 (OCTAVE_CXX_PREPENDS_UNDERSCORE): Force result for OS X.\n\n2002-11-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Set FPICFLAG, Also set CXXPICFLAG, CPICFLAG,\n\tFPICFLAG, and INCLUDE_LINK_DEPS for OS X.\n\n\t* acx_blas.m4 (LIBS): Also check for Apple vecLib framework.\n\n2002-11-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AH_BOTTOM): Define USE_EXCEPTIONS_FOR_INTERRUPTS.\n\n2002-11-04  Joseph P. Skudlarek  <jskud@jskud.com>\n\n\t* emacs/otags: handle declarations without arguments and/or return\n\tvalues.\n\n2002-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (SHLEXT_VER, SHLLIB_VER, SHLBIN_VER): Use\n\t$(version), not $(VERSION).\n\n2002-10-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (HAVE_DLOPEN_API, HAVE_SHL_LOAD_API,\n\tHAVE_LOADLIBRARY_API): Delete.\n\t(do-subst-config-vals): Don't substitute them here.\n\n2002-10-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (ENABLE_DYNAMIC_LINKING): Rename from\n\tWITH_DYNAMIC_LINKING.\n\t* Makeconf.in: Likewise.\n\t* examples/hello.cc: Likewise.  Improve comments.\n\n\t* configure.in: Revive --enable-dl to set default value for\n\tWITH_DYNAMIC_LINKING.\n\n\t* configure.in: Also set SHLEXT_VER, SHLLIB_VER, SHLBIN_VER.\n\t* Makeconf.in: Substitute them here.\n\tAlso substitute SHLLINKEXT.\n\n2002-10-25  Per Persson  <persquare@mac.com>\n\n\t* aclocal.m4 (OCTAVE_CXX_PRAGMA_INTERFACE_IMPLEMENTATION): Fix\n\tfirst test to properly fail on OS X.  Fix typo in final test to\n\tset result.\n\n2002-10-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mk-opts.pl (emit_opt_class_header): Make set_options another\n\tname for copy.\n\n2002-10-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-config-vals): Don't substitute\n\tOCTAVE_CONF_OCTAVE_LITE.\n\t(OCTAVE_LITE): Delete.\n\n\t* Makeconf.in: Use HAVE_DLOPEN_API, HAVE_LOADLIBRARY_API, and\n\tHAVE_SHL_LOAD_API instead of WITH_DL and WITH_SHL.\n\n\t* configure.in: Rewrite the way we handle dynamic linking.\n\tIf dynamic linking is used always do what was previously only\n\tenabled by --enable-lite-kernel.\n\n2002-10-17  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* configure.in: Define WITH_DYNAMIC_LINKING based on --enable-shared.\n\tAdd -lwsock32 to LIBS for MinGW.\n\n2002-10-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_LANG_PROG_NO_CONFDEFS): New macro.\n\t(OCTAVE_CXX_PRAGMA_INTERFACE_IMPLEMENTATION): Use it along with\n\tAC_LINK_IFELSE instead of AC_TRY_LINK.\n\tRequire both programs to compile for success.\n\n2002-10-16  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* aclocal.m4: Both Cygwin and MinGW don't prepend underscores.\n\t* configure.in: MinGW builds shared libraries the same as Cygwin.\n\tMinGW must link to winsock explicitly.\n\t* install-octave.in: MinGW and Cygwin both need OCTAVE_HOME.\n\n2002-10-15  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* configure.in (library_path_var): New variable.\n\n2002-10-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (SH_LDFLAGS): Additional options for Cygwin:\n\t-Wl,--export-all-symbols -Wl,--enable-auto-import.\n\n\t* Makeconf.in (TERMLIBS): Substitute here.\n\n\t* configure.in: Define OCTAVE_USE_WINDOWS_API if\n\tdefined (__WIN32__) && ! defined (__CYGWIN__), not if\n\tdefined (__WIN32__) || ! defined (__CYGWIN__).\n\tAlso call AC_SUBST for TERMLIBS.\n\n2002-10-14  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* configure.in: Use correct SHLEXT and PICFLAG for Cygwin.\n\t* configure.in: Cygwin must link against -loctave.dll, etc.\n\n\t* configure.in: Define INCLUDE_LINK_DEPS because Cygwin needs DLLs\n\tto be linked against their dependencies.\n\t* Makeconf.in: Ditto.\n\n\t* configure.in: Define SHLLIB and SHLBIN because Cygwin doesn't\n\tlink against shared libs but instead against -lxxx.dll.  LIB and\n\tBIN are the link and load forms respectively of the library.\n\t* Makeconf.in: Ditto, and define the corresponding XXX_VER.\n\n\t* configure.in: Remove LIBOCT_READLINE and LIBOCT_PATHSEARCH\n\tbecause they are merged into LIBOCTAVE to avoid circular\n\tdependencies.\n\t* Makeconf.in: Ditto.\n\t* mkoctfile.in: Ditto.\n\n\t* aclocal.m4 (OCTAVE_ENABLE_READLINE): Define LIBREADLINE because\n\tCygwin requires liboctave to be linked against -lreadline so\n\tincluding it in LIBS isn't sufficient.\n\t* mkoctfile.in: Substitute and use LIBREADLINE here.\n\n\t* aclocal.m4 (OCTAVE_CXX_PREPENDS_UNDERSCORE): Force no for cygwin.\n\n2002-10-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AH_BOTTOM): Maybe define OCTAVE_USE_WINDOWS_API\n\tand OCTAVE_HAVE_WINDOWS_FILESYSTEM.\n\n2002-10-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_PROG_GNUPLOT): AC_DEFINE GNUPLOT_BINARY\n\tDefault value on Windows systems is pgnuplot.\n\tIf not cross compiling and no gnuplot program is found, set\n\tdefault to gnuplot.  Set defaults for multiplot and frames.  Check\n\tfor pgnpuplot, pipe-gnuplot, and gnuplot on Windows systems.\n\n\t* configure.in (BUILD_EXEEXT): New variable.\n\t* Makeconf.in (BUILD_EXEEXT): Substitute it here.\n\n\t* aclocal.m4 (OCTAVE_CXX_PRAGMA_INTERFACE_IMPLEMENTATION):\n\tAdd second test for OS X.\n\n2002-10-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_CXX_PRAGMA_INTERFACE_IMPLEMENTATION): New macro.\n\t* configure.in: Use it.\n\n\t* configure.in (BUILD_CC, BUILD_CFLAGS, BUILD_CXX, BUILD_CXXFLAGS):\n\tSet default values if cross compiling.\n\n\t* aclocal.m4 (OCTAVE_PROG_NM): Do the right thing for cross compiling.\n\t(OCTAVE_CXX_PREPENDS_UNDERSCORE): Require OCTAVE_PROG_NM.\n\t(OCTAVE_CXX_ABI): Likewise.\n\n\t* Makeconf.in (BUILD_CC, BUILD_CFLAGS, BUILD_CXX, BUILD_CXXFLAGS):\n\tNew variables for cross compiling.\n\n2002-10-07  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* configure.in: Check for raise.\n\n2002-10-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_PROG_SED): New macro, adapted from autoconf\n\tpatches mailing list archive, written by Robert Boehne\n\t<rboehne@ricardo-us.com>.\n\t* configure.in: Use it.\n\t* Makeconf.in: Substitute SED, use $(SED), not sed.\n\t(do-subst-conffig-vals): Substitute it here too.\n\t* mkoctfile.in: And here.  Use $SED, not sed.\n\t* octave-bug.in: Likewise.\n\t* install-octave.in: Likewise.\n\n2002-09-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't define mkdir here.\n\n2002-09-25  Mumit Khan  <khan@nanotech.wisc.edu>\n\n \t* aclocal.m4 (OCTAVE_MKDIR_TAKES_ONE_ARG): New macro to determine if\n \thost mkdir accepts only one arg instead of the usual two.\n \t* configure.in: Use. Check for direct.h.\n \t(mkdir): Define.\n\n2002-09-26  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* configure.in: Check for conio.h.\n\tCheck for _kbhit.\n\n2002-09-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AH_BOTTOM): Don't define\n\tUSE_PRAGMA_INTERFACE_IMPLEMENTATION.\n\n2002-09-26  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* configure.in: Fix syntax errors in !HAVE_XXX_T.\n\tDon't require terminal control for build.\n\n2002-09-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Fix typedefs used in AH_BOTTOM.\n\n2002-09-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AH_BOTTOM): If using g++, define\n\tUSE_PRAGMA_INTERFACE_IMPLEMENTATION.\n\n2002-08-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for sstream.\n\n2002-08-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (%.d : %.cc): Add $*.df to LHS of dependency list.\n\n2002-08-15  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* mk-opts.pl: Add support for INCLUDE = \"...\".\n\n2002-08-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mk-opts.pl: Handle Array<int> too.\n\n2002-08-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mk-opts.pl (emit_options_function): Emit newline at EOF.\n\n2002-08-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in: Use $@-t instead of $@.tmp or $@.t.\n\n2002-07-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mk-opts.pl: New file.\n\t* Makefile.in (DISTFILES): Add it to the list.\n\n2002-07-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_CONFIG_FILES): Add libcruft/dasrt/Makefile to\n\tthe list.\n\n2002-07-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_CONFIG_FILES): Add libcruft/odessa/Makefile to\n\tthe list.\n\n2002-05-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Maybe add -fno-coalesce-templates to XTRA_CXXFLAGS\n\ton darwin systems.\n\t(SH_LDFLAGS): Set this on darwin systems.\n\t(UGLY_DEFS): Cope with broken sed or shell quoting on darwin systems.\n\n2002-05-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_CXX_ISO_COMPLIANT_LIBRARY): Omit cwctype.\n\n2002-05-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_AIX): Move before AC_MINIX and AC_ISC_POSIX.\n\t(AH_BOTTOM): Move contents of acconfig.h here.\n\t* acconfig.h: Delete.\n\t* octMakefile.in (CONF_DISTFILES): Delete acconfig.h from the list.\n\n2002-04-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_CONFIG_FILES): Add libcruft/daspk/Makefile to\n\tthe list.\n\n2002-04-24  Kurt Hornik  <hornik@ci.tuwien.ac.at>\n\n\t* aclocal.m4 (OCTAVE_CC_FLAG, OCTAVE_CXX_FLAG): Also handle flags\n\tthat contain : and =.\n\n2002-04-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.guess, config.sub: Update from FSF sources.\n\n2002-04-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Declare F2C and F2CFLAGS with AC_ARG_VAR.\n\tDelete AC_SUBST calls for F77, FFLAGS, FLIBS, F2C, F2CFLAGS (no\n\tneed to do this explicitly now).\n\n2002-04-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in: Set and substitute EXEEXT, not EXE.\n\n\t* configure.in (EXE): Delete check and substitution.\n\t* install-octave.in: Use EXEEXT instead of EXE.\n\n\t* configure.in: Use AC_CHECK_MEMBERS, not OCTAVE_STRUCT_GR_PASSWD.\n\tUse AC_CHECK_TYPES, not AC_CHECK_TYPE or OCTAVE_CHECK_TYPE.\n\t* aclocal.m4 (OCTAVE_STRUCT_GR_PASSWD, OCTAVE_CHECK_TYPE): Delete.\n\t* acconfig.h (dev_t, ino_t, nlink_t, sigset_t): Typedef if not found.\n\n2002-04-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4: Replace AC_LANG_SAVE, AC_LANG_C, AC_LANG_CPLUSPLUS,\n\tand AC_LANG_RESTORE with AC_LANG_PUSH and AC_LANG_POP.\n\tUse AS_MESSAGE_LOG_FD instead of AC_FD_CC.\n\t* configure.in: Delete second arg in AC_CHECK_SIZEOF calls.\n\n2002-04-03  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\t* configure.in: Correct usage of AC_ARG_WITH for --with-fftw.\n\n\t* configure.in: Update for autoconf 2.5x.\n\tMinor syntax changes to new recommended syntaxes and macros.\n\tApply changes from autoupdate plus eliminate some warning\n\tmessages, deprecated uses of changequote, etc.\n\tUse autoheader templates to generate config.h.in.\n\tReplace most of Octave's Fortran support macros with those in the\n\tnew autoconf.\n\tEliminate most uses of internal (undocumented) autoconf cache vars.\n\tReplace BLAS/LAPACK detection new macros ACX_BLAS/ACX_LAPACK from\n\tthe autoconf macro repository.\n\t* acx_blas.m4, acx_lapack.m4: New files.\n\t* acconfig.h: Delete lines that can be automatically generated\n\tfrom new info in configure.in and aclocal.m4.\n\tIf it is not already defined, define F77_FUNC for use with f2c.\n\t* aclocal.m4 (OCTAVE_PROG_G77, OCTAVE_FLIBS, OCTAVE_F77_MAIN_FLAG,\n\tOCTAVE_F77_UPPERCASE_NAMES, OCTAVE_F77_APPEND_UNDERSCORE,\n\tOCTAVE_F2C_F77_COMPAT): Delete definitions.\n\tUse autoheader templates to generate config.h.in.\n\t* Makeconf.in, mkoctfile.in (FORTRAN_MAIN_FLAG): Delete all uses.\n\n2001-11-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave-bug.in (BLAS_LIBS, FFTW_LIBS, LD_CXX): Substitute and\n\tprint values.\n\t* mkoctfile.in: Accept --compile as an alias for -c.\n\tNew option, --link-stand-alone.\n\tNew option, --no-pathsearch.\n\tNew option, --no-readline.\n\tSubstitute RLD_FLAG, FLIBS, LIBKPATHSEA, LIBOCTINTERP,\n\tLIBOCTAVE, LIBOCT_READLINE, LIBOCT_PATHSEARCH, LIBCRUFT,\n\tBLAS_LIBS, FFTW_LIBS, and LIBS.\n\t* Makeconf.in (MKOCTFILE_LFLAGS): New variable.\n\t(do-subst-config-vals): Substitute FFTW_LIBS, LD_CXX,\n\tLIBOCT_PATHSEARCH, LIBOCT_READLINE, MKOCTFILE_LFLAGS.\n\n2001-11-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (LIBOCT_READLINE, LIBOCT_PATHSEARCH): New variables.\n\t* Makeconf.in: Substitute them here.\n\n2001-11-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (dist): Omit long-gone info subdir.\n\tFix find command for removing Makefile in kpathsea and glob subdirs.\n\n2001-08-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Substitute F2C and F2CFLAGS. Make it possible to\n\tuse f2c and a C compile to compiling Fortran source files.  Print\n\twarnings and error message on stderr, not stdout.  Issue warnings\n\tif it is not possible to comiple Fortran, C, or C++ files.\n\n\t* configure.in (%.c : %.f): Don't use cat in F2C rule.\n\n2001-07-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-config-vals): Substitute DEPEND_FLAGS and\n\tDEPEND_EXTRA_SED_PATTERN.\n\t* mkoctfile.in: Handle --depend.\n\n2001-07-25  Rafael Laboissiere  <rafael@laboissiere.net>\n\n       * octave-config.in: New file.\n       * Makeconf.in (do-subst-default-vals): Substitute OCTAVE_VERSION.\n       * Makefile.in (TARGETS): Add octave-config to list.\n       * octMakefile.in (DISTFILES): Add octave-config.in to list.\n       (BINDISTFILES): Add octave-config to list.\n       (all): Add octave-config dependency.\n       (octave-config): New rule.\n       (install): Install octave-config.\n       (uninstall): Delete octave-config from bindir.\n       (maintainer-clean): Delete octave-config.\n       (binary-dist): Add octave-config dependency.\n\n2001-06-29  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_CXX_ABI): Use \"sun_v5\" instead of \"sun\".\n\n\t* aclocal.m4 (OCTAVE_CXX_ABI): New macro.\n\t(OCTAVE_CXX_PREPENDS_UNDERSCORE): Add missing return value.\n\t* configure.in: Use.\n\t* acconfig.h (CXX_ABI): New macro.\n\n2001-05-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Quote the call to AC_CHECK_FUNC inside the\n\tAC_CHECK_LIB macro when checking for lapack.  For autoconf 2.50\n\n\t* aclocal.m4: Changes for autoconf 2.50:\n\tConvert dnl comments inside AC_DEFUN to ###.\n\t(OCTAVE_FLIBS): Use [] quoting instead of changequote.\n\n2001-05-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in: Remove remaining references to readline.\n\t(CONF_DISTFILES): Add autogen.sh to the list.\n\n2001-05-02  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* configure.in: Support for --with-fftw.\n\t(FFT_DIR, FFTW_LIBS): New substitutions.\n\t* Makeconf.in (FFTW_LIBS): New variable.\n\t* acconfig.h (HAVE_FFTW): New macro.\n\n2001-04-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_ENABLE_READLINE): Require readline unless\n\t--disable-readline is specified.\n\n\t* configure.in: Don't define TERMLIBS.  Do add terminal lib(s) to LIBS.\n\t* octave-bug.in: Delete references to TERMLIBS.\n\t* Makeconf.in: Likewise.\n\n\t* Makeconf.in (LIBREADLINE): Delete substitution.\n\t(do-subst-config-vals): Likewise.\n\t* octMakefile.in (SUBDIRS): Delete @READLINE_DIR@ from the list.\n\t* configure.in (AC_CONFIG_SUBDIRS): Delete $READLINE_DIR from the list.\n\n\t* configure.in (VOID_SIGHANDLER): Don't check or substitute here.\n\n2001-04-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (install, install-strip): Don't use mk-includedir-link\n\n\t* Makeconf.in (mk-includedir-link, mk-libdir-link): Delete definitions.\n\n2001-04-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (mk-libdir-link): Undo previous change\n\n2001-04-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Only check for libz if checking for HDF5 libraries.\n\tAllow user to specify HDF5 library name on command line, same as\n\tfor BLAS libraries.  Include BLAS and HDF5 libs in summary output.\n\n2001-04-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (CONF_DISTFILES): Remove config.h.bot from the list.\n\n2001-04-19  David Livings  <david.livings@asa.co.uk>\n\n\t* Makeconf.in (mk-libdir-link): Omit check for $(octlibdir)/octave\n\texisting as a directory.\n\n2001-02-28  Albert Chin-A-Young  <china@thewrittenword.com>\n\n\t* configure.in: Check for getpwnam in libsun only after checking\n\tdefault libraries first.  Check for gethostname in libsocket only\n\tafter checking default libraries first.\n\n2001-02-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Allow for using f2c when setting functions to look\n\tfor in the BLAS and Lapack libraries.\n\tFrom Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at>.\n\n2001-02-10  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* test/octave.test/string/dec2hex-1.m: Don't assume hex format\n\tproduces lower case letters.\n\n2001-02-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* acconfig.h: Merge contents of config.h.bot.\n\t* config.h.bot: Delete.\n\n\t* autogen.sh: Allow running of autoconf or autoheader to be skipped.\n\n2001-02-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* readline: Update to new version (4.2-beta1).\n\n2001-02-05  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* configure.in (TEMPLATE_AR, TEMPLATE_ARFLAGS): New variables.\n\t* Makeconf.in (TEMPLATE_AR, TEMPLATE_ARFLAGS): Likewise.\n\n\t* configure.in (XTRA_CXXFLAGS): Use -fno-implicit templates for\n\tpre-gcc3 compilers. Remove -fno-rtti and -fno-exceptions.\n\t(DEPEND_FLAGS, DEPEND_EXTRA_SED_PATTERN): New macros.\n\t(BLAS_LIBS): Fix test for sunperf library on Sun Solaris.\n\t(CPICFLAG, CXXPICFLAG, FPICFLAG, SH_LDFLAGS, RLD_FLAG): Add Sun\n\tcompiler support.\n\t* Makefile.in (DEPEND_FLAGS, DEPEND_EXTRA_SED_PATTERN): New\n\tvariables.\n\t(%.d : %.cc): Use.\n\t(%.d : %.c): Likewise.\n\t* acconfig.h (CXX_ISO_COMPLIANT_LIBRARY): Add #undef.\n\n2001-01-31  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* Makeconf.in (%.d : %.cc): Strip the directory portion of the\n\ttarget.\n\t(%.d : %.c): Likewise.\n\n\t* aclocal.m4 (OCTAVE_CXX_ISO_COMPLIANT_LIBRARY): New macro.\n\t* configure.in: Use it.\n\n2001-01-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-config-vals): Substitute\n\tOCTAVE_CONF_CANONICAL_HOST_TYPE here too.\n\t* octave-bug.in: Substitute OCTAVE_CONF_CANONICAL_HOST_TYPE, not\n\tOCTAVE_CANONICAL_HOST_TYPE.\n\n2000-12-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4: Give gperf a keyword, to avoid complaints from newer\n\tversions.\n\n2000-11-27  Marcus.Brinkmann  <Marcus.Brinkmann@ruhr-uni-bochum.de>\n\n\t* configure.in: Handle *-*-gnu* the same as *-*-linux* for shared\n\tlibrary creation.\n\n2000-11-03  Andy Adler  <en254@freenet.carleton.ca>\n\n\t* mkoctfile.in: Handle -c to mean compile only.\n\n2000-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Handle --print.\n\n2000-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_PROG_GPERF): Check that gperf supports flags\n\twe use.\n\n\t* missing: New file, modified from the missing script provided by\n\tautomake (never create files, just exit with failure status).\n\t* aclocal.m4 (OCTAVE_PROG_BISON, OCTAVE_PROG_FLEX, OCTAVE_PROG_GPERF):\n\tUse $(top_srcdir)/missing as replacement script.\n\n\t* aclocal.m4 (OCTAVE_PROG_FLEX, OCTAVE_PROG_BISON): New macros.\n\t* configure.in: Use them.\n\n2000-10-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* autogen.sh: Don't run configure.\n\n\t* configure.in (SPECIAL_MATH_LIB): Delete code related to this var.\n\t* Makeconf.in: Ditto.\n\t(BLAS_LIBS, LIBS): Substitute here.\n\t(do-subst-config-vals): Put BLAS_LIBS in oct-conf.h.\n\n2000-07-20  Joao Cardoso  <jcardoso@inescn.pt>\n\n\t* configure.in: (LD_CXX): Define and substitute.\n\tFor sco3.2v5 systems, set SONAME_FLAGS and RLD_FLAG.\n\t* Makeconf.in (LD_CXX): Allow substitution.\n\n2000-07-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (DISTSUBDIRS): Define in terms of $(ALL_SUBDIRS).\n\n2000-07-17  Joao Cardoso  <jcardoso@inescn.pt>\n\n\t* configure.in (LIBGLOB): Set to be the two object files in the\n\tglob directory instead of libglob.a.\n\n2000-07-05  Steven G. Johnson  <stevenj@gil-galad.mit.edu>\n\n\t* Use BLAS_LIBS to save the names of BLAS libraries instead of\n\tadding them to LIBS, then substitute BLAS_LIBS.\n\n2000-06-30  Steven G. Johnson  <stevenj@gil-galad.mit.edu>\n\n\t* configure.in: Support for --with-fastblas (ATLAS).\n\n2000-06-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for long long data type.\n\n2000-06-29  Steven G. Johnson  <stevenj@gil-galad.mit.edu>\n\n\t* acconfig.h (HAVE_HDF5): Add undef.\n\t* configure.in: Handle --with-hdf5.\n\n2000-06-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave-bug.in: Substitute correct values for config_opts,\n\tMACHINE, and CXXFLAGS.\n\n2000-06-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (GPERF): Allow substitution.\n\n2000-06-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_PROG_GPERF): New macro.\n\t* configure.in: Use it.  Print warning at end if gperf is missing.\n\n2000-04-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Try moving output file first.  But comment these\n\tlines and let people who have trouble enable them.\n\n2000-04-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Remove output file before linking.\n\n\t* octMakefile.in (DIRS_TO_MAKE): Create $(octincludedir)/octave.\n\t(install install-strip): Install config.h in $(octincludedir)/octave,\n\tnot $(octincludedir).\n\n2000-03-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (DIRS_TO_MAKE): Double up on $ in awk command to\n\tget them past Make.\n\n2000-03-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (SUBDIRS): Omit src.\n\t(ALL_SUBDIRS): New variable.  Include src here.\n\t(all): Depend on src instead of $(SUBDIRS).\n\t(src): New target.  Depend on $(SUBDIRS).\n\n\t* Makefile.in (.NOTPARALLEL): New target, for GNU Make 3.79.\n\t* octMakefile.in (.NOTPARALLEL): Likewise.\n\n2000-03-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for vsnprintf.\n\n2000-03-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (liboctave.$(SHLEXT)): Delete target before rebuilding.\n\n2000-03-21  Ben Sapp  <bsapp@nua.lampf.lanl.gov>:\n\n\t* Makeconf.in (%.o : %.c): Pass -o to compile command.\n\t(%.o : %.cc): Ditto.\n\t* configure.in (%.o : %.f): Ditto.\n\n2000-03-08  Stephen Eglen  <stephen@gnu.org>\n\n\t* emacs/octave-mod.el (octave-font-lock-keywords): To font-lock\n\tthe builtin operators, use `font-lock-builtin-face' for Emacs\n\tand `font-lock-preprocessor-face' for XEmacs.\n\n2000-03-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: For building shared libaries, handle\n\ti386-pc-solaris2* the same as sparc-sun-solaris2*.\n\n2000-02-29  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* examples/make_int.cc (make_int): Handle new operator names.\n\n2000-02-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (maintainer-clean distclean): Don't delete Makefile.\n\t(dist): Delete stamp-auto.\n\n2000-02-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (octincludedir): Delete trailing /octave here.\n\t* Makeconf.in (mk-includedir-link): Append it here.\n\t(MKOCTFILE_INCFLAGS): Use both -I$(octincludedir) and\n\t-I$(octincludedir)/octave.\n\n\t* configure.in (localveroctfiledir, localverarchlibdir,\n\tlocalverfcnfiledir): New variables.\n\t(localfcnfilepath): Prepend localverfcnfiledir.\n\t(localoctfilepath): Prepend localveroctfiledir.\n\t* Makeconf.in: Substitute them here.\n\n\t* Makeconf.in (do-subst-default-vals): Substitute\n\tOCTAVE_LOCALVERARCHLIBDIR, OCTAVE_LOCALVERFCNFILEDIR,\n\tOCTAVE_LOCALVEROCTFILEDIR.\n\n2000-02-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.guess: Update to latest from subversions.gnu.org.\n\t* config.sub: Likewise.  Recognize sv1-cray as a basic_machine.\n\n\t* Makeconf.in (MKOCTFILE_INCFLAGS): New macro.\n\t(do-subst-conf-vals): Substitute it.\n\t* mkoctfile.in: Set INCFLAGS from OCTAVE_CONF_MKOCTFILE_INCFLAGS.\n\n\t* mkoctfile.in: Fix names in substititions.\n\t* octave-bug.in: Likewise.\n\n2000-02-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-default-vals, do-subst-config-vals):\n\tSubstitute more complete set of values.\n\n2000-02-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (octave_cv_string_npos): Add std:: qualifier.\n\n2000-01-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-begin-keywords): Add \"do\".\n\t(octave-end-keywords): Add \"until\".\n\t(octave-abbrev-table): Add \"u\" as abbrev for \"until ()\"\n\t(octave-block-match-alist): Add do-until.\n\n2000-01-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't look for the sunmath library.\n\tDon't check for infinity or quiet_nan.\n\n\t* emacs/octave-mod.el (octave-mode-syntax-table):\n\tUndo previous change, but add a comment explaining why.\n\n\t* install-octave.in: Exit on any error instead of continuing.\n\tInstall Octave binary last.\n\n2000-01-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-mode-syntax-table):\n\tMake `%' a comment start character too.\n\n2000-01-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for strptime and localtime_r.\n\n1999-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (XTRA_CXXFLAGS, XTRA_CFLAGS): Use -mminimal-toc on\n\tAIX systems.\n\n1999-10-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/README: New file.\n\t* emacs/Makefile.in (DISTFILES, BINDISTFILES): Add it to the lists.\n\n\t* emacs/Makefile.in: Don't distribute .elc files.\n\n1999-10-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for select and poll.  Also check for poll.h\n\tand sys/poll.h.\n\n1999-10-19  Geoff Jacobsen  <geoffj@casquet.inet.net.nz>\n\n\t* autogen.sh: New file.\n\n1999-10-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in: Use `$(MAKE) -C dir' instead of `cd dir; $(MAKE)'.\n\nMon Sep 20 11:02:29 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-inf.el, emacs/octave-mod.el: Update to match FSF\n\tsources plus code that will make it work if Emacs doesn't have the\n\tcustomize code.\n\nTue Sep 14 07:57:06 1999  Kurt Hornik  <hornik@ci.tuwien.ac.at>\n\n\t* emacs/octave-inf.el (inferior-octave-startup): Always pass \"-i\"\n\tand \"--no-line-editing\" to Octave subprocess.\n \t(inferior-octave-startup-args): Default to nil.\n\nMon Sep  6 10:50:10 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-inf.el (inferior-octave-startup-args):\n\tAdd --no-line-editing to the list.\n\nFri Jul  9 09:15:24 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Try to handle IEEE FP flags for g77 on Alphas.\n\nThu Jul  8 19:56:37 1999  Stephen Eglen  <stephen@gnu.org>\n\n\t* emacs/octave-inf.el (inferior-octave-directory-tracker):\n\tChange regexp so that it doesn't match commands beginning with `cd'.\n\nWed Jun 23 13:20:11 1999  Mumit Khan  <khan@xraylith.wisc.edu>\n\n\t* configure.in (HAVE_TERMIOS_H): Avoid autoheader lossage.\n\nSun Jun 20 23:05:18 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for sys/ioctl.h.\n\nMon May 10 09:06:47 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_PROG_G77): Also match \"FSF-g77\", for egcs.\n\nThu Apr  8 19:20:09 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* examples/hello.cc (Fhello): octave_value::print now requires a\n\tstream arg.\n\nWed Feb  3 01:02:37 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Use AC_OUTPUT_COMMANDS to chmod install-octave so\n\tthat the command will also executed in config.status.\n\nThu Jan 28 21:05:32 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-config-vals): Do substitution on\n\tCANONICAL_HOST_TYPE, not TARGET_HOST_TYPE.\n\t(do-subst-default-vals): Likewise.\n\nWed Jan 20 12:56:02 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't put -O in FFLAGS for powerpc-apple-machten*.\n\nWed Dec  9 14:02:45 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (RDYNAMIC_FLAG): Substitute RDYNAMIC_FLAG here.\n\t* configure.in: Check for G++ compiler flag -rdynamic if setting\n\tup to support dynamic linking, and substitute RDYNAMIC_FLAG if\n\t-rdynamic is accepted.\n\t* aclocal.m4 (OCTAVE_CC_FLAG, OCTAVE_CXX_FLAG): Clarify usage comment.\n\nMon Dec  7 19:49:26 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for -lm just after compiler tests.\n\tRemove -lm from other macro calls.  Don't check for -lm on NeXT\n\tsystems.  Eric Norum <eric@skatter.usask.ca> says /lib/libsys_s.a\n\thas all the routines that are traditionally in libc.a and libm.a\n\ton *NIX systems.  NeXT also supplies a libm.a, but it seems to be\n\thorribly buggy.\n\nSat Dec  5 10:48:40 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Correctly handle -?.\n\nFri Dec  4 18:05:51 1998  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* emacs/octave-mod.el (octave-abbrev-start): Use the correct name\n\tof the abbrev table, and provide support for XEmacs.\n\t(octave-xemacs-p): New variable.\n\nTue Nov 24 23:31:50 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for strftime too.\n\tAvoid checking for termios.h on NeXT systems.\n\nThu Nov 19 16:07:57 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_CXX_PREPENDS_UNDERSCORE): New macro.\n\t* configure.in: Use it.\n\t* acconfig.h: Add #undef for it.\n\nThu Nov 12 10:42:25 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/otags: New script from Mario Storti\n\t<mstorti@minerva.unl.edu.ar>.\n\t* emacs/Makefile.in: Add it to the list of files to distribute and\n\tinstall.\n\nWed Nov 11 17:26:26 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_OUTPUT): Add libcruft/amos/Makefile.\n\tDelete libcruft/specfun/Makefile.\n\nMon Nov  9 08:53:03 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (LIBGLOB): Add a place for substitution to occur.\n\t(GLOB_INCFLAGS): Define as @GLOB_INCFLAGS@, not @DLFCN_INCFLAGS@.\n\t(do-subst-config-vals): Don't forget LIBGLOB.\n\t* octave-bug.in (LIBGLOB): Substitute here too, and add it to the\n\tlist of configuration items to print.\n\nMon Nov  2 20:33:16 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Define __NO_MATH_INLINES.\n\t* acconfig.h: Add #undef for it.\n\n\t* configure.in (AC_OUTPUT): Escape newlinew in macro call with \\.\n\n\t* install-octave.in (SHLEXT): Substitute.\n\t(SHLEXT_VER): Define.\n\tUse them for installing shared libraries.\n\tUse subshells to avoid having to cd back to $distdir.\n\t(distdir): Delete variable.\n\nFri Oct  2 14:23:59 1998  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* octave-inf.el (inferior-octave-prompt):  Also match prompts of\n\tthe form `octave.bin:1>' which come from using precopiled binary\n\tversions.\n\nThu Sep 24 13:51:03 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_OUTPUT): Add libcruft/ordered-qz to the list.\n\tDelete libcruft/balgen and libcruft/eispack from the list.\n\nMon Aug 31 12:07:02 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.sub: Accept armv4 everywhere arm is allowed.\n\nTue Aug 18 17:02:25 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Allow -DDEF on command line.\n\nThu Jun 18 20:24:40 1998  Roman Hodek  <Roman.Hodek@informatik.uni-erlangen.de>\n\n\t* configure.in (RLD_FLAG): Set correctly for Linux on all\n\tarchitectures.  From\n\nThu May 28 10:17:45 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: When checking for glob stuff, make sure that the\n\tsystsem header file has all the definitions that we need.  If not,\n\tset up to use our replacement library.\n\nMon May 18 11:33:45 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Fix typos in case statement.\n\nFri May 15 00:34:54 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Make sure install-octave is executable.\n\n\t* install-octave.in (oct_files): Don't cd to src.\n\t(have_find): Delete variable (assume all systems have find).\n\nThu May 14 10:29:30 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_SET_DEFAULT): Allow values to come from the\n\tenvironment.\n\n\t* Makefile.in (binary-dist): Don't set LDFLAGS to -static.\n\tRun configure with --enable-shared and --enable-lite-kernel.\n\n\t* octMakefile.in (DISTFILES): Include README.MachTen in the list.\n\t(XBINDISTFILES): Include README.MachTen in the list.\n\tDelete README.NLP from the list\n\t* README.MachTen: New file.\n\n\t* configure.in: Add -mno-fp-in-toc on ibm-aix4 systems.\n\tFrom Philippe.Defert@cern.ch <Philippe.Defert@cern.ch>.\n\nTue May  5 14:43:36 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_PROG_G77): Compile trivial program instead of\n\tjust running ${f77-f77} -v on nothing.\n\tConvert all uses of $F77 to ${F77-f77}.\n\nMon May  4 12:08:36 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-mode): Make comment-multi-line local\n\tand set to nil.\n\nTue Apr 28 14:28:14 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Really do skip -lkernel32.\n\nThu Apr 23 23:26:19 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* kpathsea: Update to version 3.2.\n\nMon Apr 20 21:58:39 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (dlfcn.h): Add check.\n\nSat Apr 18 20:15:37 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (USE_GNU_INFO): Delete everything related to this.\n\t* acconfig.h (USE_GNU_INFO): Delete undef.\n\nTue Apr 14 15:33:20 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* install-octave.in: Improve error messages if version number or\n\thost architecture can't be found.\n\n\t* install-octave.in: Don't install info reader.\n\nFri Mar 27 02:54:59 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_F2C_F77_COMPAT): Use a Fortran subroutine\n\tinstead of a function.\n\nTue Mar 10 17:28:20 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (RLD_FLAG): Use $(octlibdir), not $(libdir).\n\nMon Mar  2 00:02:26 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* install-octave.in: Explicitly set permissions on ls-R files.\n\n\t* configure.in: Don't disable GNU Info on cygwin32 systems.\n\n\t* install-octave.in: New file.\n\t* configure.in: Create install-octave.\n\t* octMakefile.in (distclean, maintainer-clean): Delete install-octave.\n\t(DISTFILES): Distribute install-octave.in, not install-octave.\n\nSun Mar  1 23:15:04 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Fix typo in test for glob and fnmatch headers.\n\nFri Feb 27 15:43:14 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Fix support for dlopen on SCO systems.\n\nMon Feb 23 13:06:11 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (ieee_fp_flag): Use -mieee-with-inexact on Alphas.\n\tUse octave_cv_f77_is_g77, not just f77_is_g77.\n\nFri Feb 20 00:38:31 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in, Makeconf.in: Try to set things up to use the\n\tsystem glob and fnmatch headers and functions if they exist.\n\tBetter handling of include and lib flags.\n\nThu Feb 19 01:21:19 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't check for gamma or lgamma\n\t* acconfig.h: Delete undef for HAVE_GAMMA and HAVE_LGAMMA.\n\nWed Feb 18 15:05:54 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't check for vfork.\n\nWed Feb 11 19:41:22 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (mk-libdir-link): Don't create link if a directory\n\tnamed $(libdir)/octave already exists.\n\nMon Feb  9 14:47:42 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (INSTALL_SUBDIRS): Delete @INFO_DIR@.\n\nThu Feb  5 03:04:09 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for vfork.\n\n\t* config.h.bot (X_CAST): New macro.\n\nWed Feb  4 01:42:50 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): If ld_run_path is not absolute, kill it.\n\nTue Feb  3 00:24:01 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-vals): Substitute $(libexecdir) too.\n\nMon Feb  2 22:42:27 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Define octlibdir.\n\t* Makeconf.in: Substitute value.\n\t(do-subst-config-vals): Set LIBDIR to $(octlibdir).\n\t(do-subst-default-vals): Substitute OCTLIBDIR too.\n\nSat Jan 31 19:29:56 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* acconfig.h: Add #undefs for HAVE_GAMMA and HAVE_LGAMMA to avoid\n\tbug in autoconf, but #if 0 them out to avoid warning messages\n\tabout redefining them.\n\nMon Jan 26 13:26:09 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-config-vals): Substitute XTRA_CFLAGS and\n\tXTRA_CXXFLAGS.\n\t* mkoctfile.in: Substitute XTRA_CFLAGS and XTRA_CXXFLAGS, not\n\tGCC_IEEE_FP_FLAG, HOST_CXXFLAGS, and NO_IMPLICIT_TEMPLATES.\n\t(ALL_CFLAGS): Use XTRA_CFLAGS, not GCC_IEEE_FP_FLAG here.\n\t(ALL_CXXFLAGS): Use XTRA_CXXFLAGS, not GCC_IEEE_FP_FLAG,\n\tHOST_CXXFLAGS, and NO_IMPLICIT_TEMPLATES here.\n\nSun Jan 25 01:59:47 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: (GXX_PICKY_FLAGS): Add -Weffc++.\n\tUse OCTAVE_CC_FLAG and OCTAVE_CXX_FLAG to add -Wall and for adding\n\tpicky flags in AC_ARG_ENABLE(picky-flags ...) macro.\n\n\t* aclocal.m4 (OCTAVE_F2C_F77_COMPAT): Require OCTAVE_PROG_G77.\n\tHandle cross compiling with g77.\n\t(OCTAVE_REINSTALL_SIGHANDLERS): Provide defaults for cross compiling.\n\n\t* aclocal.m4 (OCTAVE_PROG_AR, OCTAVE_PROG_G77, OCTAVE_PROG_PAGER,\n\tOCTAVE_PROG_GNUPLOT, OCTAVE_PROG_RUNTEST, OCTAVE_F77_MAIN_FLAG):\n\tNew macros.\n\t* configure.in: Use them in place of in-line code.\n\nSat Jan 24 00:33:14 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_HOST_TYPE): Don't set target_host_type.\n\t* configure.in: Use canonical_host_type in place of target_host_type.\n\nFri Jan 23 02:47:57 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Also check for -fno-rtti.\n\nThu Jan 15 23:12:27 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.guess, config.sub: Update to new version from the FSF.\n\t* configure.in: Match alpha*-... instead of just alpha-... to cope\n\twith new strings like alphaev56-dec-osf4.0b returned from\n\tconfig.guess.\n\n\t* aclocal.m4 (OCTAVE_CC_FLAG, OCTAVE_CXX_FLAG): New macros.\n\t* configure.in: Use them to find out if the C and C++ compilers\n\tsupport -mieee-fp, -mieee, -fno-implicit-templates, and\n\t-fno-exceptions instead of relying on version information.  Add\n\tfound flags to XTRA_CFLAGS and XTRA_CXXFLAGS instead of using\n\tGCC_IEEE_FP_FLAG and NO_IMPLICIT_TEMPLATES.\n\tDelete unused variable HOST_CXXFLAGS.\n\t* Makeconf.in: Use XTRA_CFLAGS and XTRA_CXXFLAGS instead of\n\tGCC_IEEE_FP_FLAG and NO_IMPLICIT_TEMPLATES.\n\tDelete unused variable HOST_CXXFLAGS.\n\nThu Dec 11 09:43:56 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.h.bot: Define CONST_CAST and STATIC_CAST too.\n\n\t* configure.in (SH_LD): Set default to $CXX, not $CC.\n\nMon Dec  1 00:49:56 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_OUTPUT): Add libcruft/slatec-err/Makefile.\n\nSun Nov 30 18:19:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for gamma and lgamma too.\n\nFri Nov 28 23:21:17 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_OUTPUT): Include libcruft/specfun/Makefile.\n\nFri Nov 28 13:32:26 1997  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* octave-inf.el (inferior-octave-directory-tracker):  Anchor\n\tregexp match to beginning of command string.\n\nWed Nov 26 00:38:31 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (SPECIAL_MATH_LIB): If libdxml exists on DU\n\tsystems, define SPECIAL_MATH_LIB.\n\t* Makeconf.in (SPECIAL_MATH_LIB): Substitute it.\n\nWed Nov 19 01:54:11 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_CXX_NEW_FRIEND_TEMPLATE_DECL): Don't forget\n\tto call AC_LANG_RESTORE.\n\n\t* configure.in (CXX_VERSION): Require 2.7.2 or later.\n\nWed Nov 19 01:38:58 1997  Mumit Khan  <khan@dhaka.xraylith.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_CXX_NEW_FRIEND_TEMPLATE_DECL): New macro\n\tcheck for new friend template declaration syntax (guiding\n\tdeclarations in DWP).\n\t* configure.in: Use it.\n\t* config.h.in: Add undef for CXX_NEW_FRIEND_TEMPLATE_DECL.\n\n\t* configure.in (CC_VERSION, CXX_VERISON): Check for egcs snapshots.\n\nMon Oct 20 01:31:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Reprint important warning messages at the end of\n\tthe run.\n\nFri Oct 17 04:43:27 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Include the following change from RMS for octave-mode.el:\n\n\t1997-04-22  Richard Stallman  <rms@psilocin.gnu.ai.mit.edu>\n\n\t* octave-mod.el (inferior-octave-output-list): Declare here\n\tto avoid compiler warnings.\n\t(inferior-octave-output-string): Likewise.\n\t(inferior-octave-receive-in-progress): Likewise.\n\nTue Oct 14 10:48:28 1997  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* emacs/octave-mod.el (octave-block-match-alist):  Move\n\t`otherwise' to right after `case' to have octave-close-block()\n\tcorrectly close a `switch' block by `endswitch'.\n\nThu Oct  2 01:37:15 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Ignore -lc and -lgcc.\n\tFrom \"Ram'on Garc'ia Fern'andez\" <ramon@juguete.quim.ucm.es>\n\n\t* mkoctfile.in: Handle -IDIR option.\n\nThu Sep 25 11:47:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Really add link options to link command.\n\tAlso handle -LDIR options.\n\nFri Sep 19 09:35:59 1997  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* octave-inf.el (inferior-octave-startup-args):  Set to '(\"-i\") to\n\tforce interactive behavior.\n\nWed Sep 10 15:31:03 1997  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* emacs/octave-mod.el (octave-auto-indent):  New variable.\n\t(octave-electric-semi, octave-electric-space):  Use it.\n\n\t* emacs/octave-mod.el (octave-maybe-insert-continuation-string):  New\n\tfunction.\n\t(octave-auto-fill):  No longer calls do-auto-fill.  Should now\n\tavoid breaking lines after comment starts or before code line\n\tcontinuation expressions.\n\t(octave-fill-paragraph):  Move forward a line if octave-auto-fill\n\tgave up.\n\n\t* emacs/octave-mod.el (octave-before-magic-comment-p):  New function.\n\t(octave-comment-indent):  Handle magic comments correctly.\n\t(calculate-octave-indent):  Handle magic comments correctly.\n\n\t* emacs/octave-inf.el (inferior-octave-prompt):  Include the `debug'\n\tprompt issued by the Octave `keyboard' command.\n\n\t* emacs/octave-mod.el (octave-abbrev-table):  Added abbrevs for switch,\n\tcase, otherwise, and endswitch.\n\t(octave-begin-keywords):  Added switch.\n\t(octave-else-keywords):  Added case and otherwise.\n\t(octave-end-keywords):  Added endswitch.\n\t(octave-block-match-alist):  Added an entry for switch syntax.\n\t(calculate-octave-indent):  Added support for switch syntax.\n\t(octave-block-end-offset):  New function.\n\t(octave-comment-indent):  Fix a typo.\n\n\t* emacs/octave-hlp.el:  Provide octave-hlp.\n\n\t* emacs/octave-inf.el:  Provide octave-inf.\n\nSun Sep  7 23:16:33 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in Don't use OCTAVE_SET_DEFAULT to set values for\n\tbindir, datadir, exec_prefix, includedir, infodir, libdir,\n\tlibexecdir, mandir.\n\tDon't use AC_PREFIX_DEFAULT, since we don't want to override the\n\tdefault setting anyway.\n\nTue Aug 26 13:30:36 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave-bug.in: CC bug report to user if $USER or $LOGNAME is set.\n\nMon Aug 25 11:06:54 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave-bug.in: Avoid clobbering existing dead bug report files\n\tby numbering them.\n\nWed Aug 13 20:34:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-before-magic-comment-p): New function.\n\t(calculate-octave-indent, octave-comment-indent): Use it.\n\nSun Aug  3 15:33:18 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* info: Delete subdirectory.\n\t* Makefile.in (TARGETS, help): Delete info.\n\t* octMakefile.in (DISTSUBDIRS, BINDISTSUBDIRS): Delete info\n\t(binary-dist): Don't strip info/info.\n\t* install-octave: Don't install info.\n\t* configure.in: Don't run configure in info subdirectory.\n\nFri Jul 25 14:05:15 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Avoid adding -lcrt0.o to FLIBS.\n\nThu Jul 17 13:31:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Only accept an ld_run_path that is\n\tabsolute.\n\nWed Jul  9 19:27:38 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Also check for getwd.\n\nTue Jul  8 17:47:11 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Avoid grabbing an argument starting\n\twith a - as an option for another argument.\n\nWed Jul  2 21:34:15 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-auto-indent): New variable.\n\t(octave-electric-semi, octave-electric-space): Use it.\n\nThu Jun 26 22:16:59 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Only set GCC_IEEE_FP_FLAG to -mieee-fp on Intel\n\tsystems if it seems to work.\n\nMon Jun 23 09:16:56 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (BOUNDS_CHECKING): Fix comment, allow bounds\n\tchecking to be enabled.\n\nFri Jun 20 14:26:17 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Define SH_LD, SH_LDFLAGS, and RLD_FLAG for\n\tsparc-sun-sunos4*.\n\n\t* mkoctfile.in: Handle --strip.\n\nSun Jun 15 16:24:03 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (DISTSUBDIRS): Delete readline.\n\t(BINDISTSUBDIRS): Delete readline and kpathsea.\n\t(DISTDIRS): Add readline.\n\nWed Jun 11 16:28:36 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Allow more options, support for C and Fortran\n\tsource, existing object files, etc.  Based on patch from Guido\n\tDietz <guido@aia009.aia.RWTH-Aachen.De>.\n\nFri Jun  6 15:20:42 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Use eval to invoke compilation and linking\n\tcommands.\n\n\t* octMakefile.in (dist, binary-dist): Don't worry about npsol or qpsol.\n\t* configure.in: Don't create libcruft/fsqp/Makefile,\n\tlibcruft/npsol/Makefile, or libcruft/qpsol/Makefile.\n\n\t* octMakefile.in (DISTFILES): Don't distribute MAKEINFO.PATCH.\n\n\t* octMakefile.in (DISTFILES): Don't distribute README.NLP.\n\t* configure.in: Delete checks for FSQP, NPSOL, and QPSOL.\n\t* acconfig.h: Delete undefs for FSQP, NPSOL, and QPSOL.\n\n\t* readline: Update to new version (2.1).\n\nThu Jun  5 01:38:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (SONAME_FLAGS): Define for some systems.\n\t* Makeconf.in: Substitute value here.\n\n\t* Makeconf.in (STATIC_LIBS): New variable.\n\t* configure.in: Handle --enable-static.\n\n\t* Makeconf.in (LIBEXT, SHLEXT_VER): New macros.\n\t(octlibdir, mk-libdir-link): Delete.\n\nWed Jun  4 00:07:29 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (mk-includedir-link, mk-libdir-link): Make them work.\n\n\t* configure.in (OCTAVE_PROGRAM_INVOCATION_NAME): Delete check.\n\t* aclocal.m4 (OCTAVE_PROGRAM_INVOCATION_NAME): Delete macro.\n\nMon Jun  2 13:56:26 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Move checks for RANLIB, AR, and ARFLAGS before\n\tchecks for libf2c.\n\nFri May 30 14:59:59 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Fix typo in check for $with_f77.\n\nThu May 22 16:48:34 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_OUTPUT): Remove duplicate entry for emacs/Makefile.\n\n\t* octMakefile.in (INSTALL_SUBDIRS): New macro.\n\t(install): Use it.\n\n\t* kpathsea: Update to new version (3.0).\n\n\t* readline: Update to new version (2.1-beta2).\n\nWed May 21 16:33:33 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (install, install-strip): Append version\n\tinformation to octave-bug and mkoctfile.\n\t(install, install-strip): Remove octave-bug and mkoctfile first.\n\tEnsure link is made in include directory.\n\n\t* configure.in (octlibdir): New variable.\n\t* Makeconf.in: Substitute it here.\n\t(do-subst-config-vals): Add -I${octincludedir} to INCFLAGS.\n\tAdd -L${octlibdir} to LIBFLAGS.\n\n\t* Makeconf.in (mk-includedir-link, mk-libdir-link): New macros.\n\nMon May  5 00:58:00 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Make --enable-readline work again.\n\t* Makeconf.in: Ditto.\n\nTue Apr  8 12:38:18 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in: Do substitute SH_LD and SH_LDFLAGS.  Don't\n\tsubstitute or use LIBFLAGS, RLD_FLAG, OCTAVE_LIBS, FLIBS, LEXLIB,\n\tTERMLIBS, LIBS, LDFLAGS, LIBPLPLOT, or LIBDLFCN.  Use $SH_LD and\n\t$SH_LDFLAGS, not $CXX -shared.\n\n\t* Makeconf.in (do-subst-config-vals): Also substitute SH_LD and\n\tSH_LDFLAGS.\n\nFri Mar 28 16:53:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't add -fpe1 to FFLAGS on Alpha OSF/1 systems\n\tunless we are also using a version of gcc that appears to support\n\tIEEE floating point.\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Require OCTAVE_HOST_TYPE.\n\tSkip -lkernel32 on cygwin32 systems.\n\nWed Mar 26 17:04:11 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* COPYING: Update to latest version that includes correct address\n\tfor the FSF.\n\nTue Mar 25 21:46:49 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_CXXLIBS): Delete macro definition.\n\t* configure.in, mkoctfile.in, Makeconf.in, octave-bug.in:\n\tDelete use of OCTAVE_CXXIBS.\n\nThu Mar 13 11:44:46 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Move extra checks for Fortran compiler above\n\tchecks for dynamic linking and shared library stuff.\n\tHandle --with-f77.  Check for Fortran compiler compatibility, even\n\tif using g77.  Handle --enable-picky-flags.\n\n\t* configure.in: Don't set special PIC options on SGI systems,\n\tsince PIC is apparently the default.\n\n\t* aclocal.m4 (OCTAVE_CHECK_EXCLUSIVE_WITH_OPTIONS,\n\tOCTAVE_HOST_TYPE, OCTAVE_SET_DEFAULT): New macros.\n\t* configure.in: Use them.\n\n\t* octMakefile.in (distclean): Don't remove configure, config.h.in,\n\tBUGS, or INSTALL.OCTAVE.\n\nWed Mar 12 16:56:56 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-strip): Don't try to set INSTALL_PROGRAM here.\n\n\t* emacs/Makefile.in (install-strip): New target.\n\t* dlfcn/Makefile.in: Ditto.\n\t* examples/Makefile.in: Ditto.\n\nSun Mar  9 03:44:33 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.h.bot (STATIC_CAST): Delete definition.\n\nThu Mar  6 03:26:41 1997  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* emacs/octave-hlp.el: Provide octave-hlp.\n\t* emacs/octave-inf.el: Provide octave-inf.\n\n\t* examples/info-emacs-octave-help: Require octave-hlp instead of\n\tloading it.\n\nTue Mar  4 12:19:24 1997  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* emacs/octave-mod.el: Properly indent switch statement.\n\nMon Mar  3 15:44:42 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dlfcn/Makefile.in (DISTFILES): Add ftp-site.\n\nSat Mar  1 15:23:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Improve checks for gettimeofday.\n\n\t* Version 2.0.5 released.\n\nSat Mar  1 01:34:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (dist): Also delete CVS junk\n\n\t* config.h.bot: Unconditionally define WITH_KPATHSEARCH.\n\nFri Feb 28 01:56:52 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mod.el (octave-end-keywords): Add endswitch.\n\t(octave-end-keywords): Add otherwise and case.\n\t(octave-else-keywords): Add switch.\n\t(octave-abbrev-table): Add abbrevs for all of them.\n\n\t* configure.in (f77_rules_frag): Set default value to /dev/null\n\tand redfine as needed.\n\t(bsd_gcc_kluge_targets_frag): Likewise.\n\nWed Feb 26 12:17:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (maintainer-clean): Delete some more stuff.\n\nFri Feb 21 20:38:25 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-config-vals): Remove extra -L from\n\tRLD_FLAG substitution.\n\nThu Feb 20 02:58:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.4 released.\n\n\t* configure.in (SH_LDFLAGS): Add -fPIC for HP-UX.\n\nTue Feb 18 09:22:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (SH_LDFLAGS): Fix typo in last change.\n\t(RLD_FLAG): Don't forget to put -shared in SH_LDFLAGS for alpha\n\tsystems.\n\n\t* Version 2.0.3 released.\n\nTue Feb 18 00:33:36 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (binary-dist): Strip src/octave and info/info.\n\n\t* examples/oregonator.m, examples/oregonator.cc: New files.\n\t* examples/Makefile.in (SOURCES): Add them to the list.\n\nFri Feb 14 14:07:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* install-octave: Don't fail if LIBRARIES file is missing.\n\tDon't try to install .oct files if there aren't any.\n\n\t* octMakefile.in (bin-dist-type): Delete target.\n\t(binary-dist): Don't depend on bin-dist-type.\n\tDon't delete config.status or config.h here.\n\t(BINDISTFILES): Include config.status and config.h here.\n\t(dist): Don't delete Makefile here.\n\t(binary-dist): Avoid empty chmod command.\n\n\t* Makefile.in (config-check): New target.\n\t(all): Depend on config-check.\n\t(static-binary-distribution, dynamic-binary-distribution): Delete.\n\t(binary-distribution): If in source directory, run configure and\n\tmake with appropriate args.\n\n\t* octMakefile.in (maintainer-clean, distclean): Don't delete Makefile.\n\t(CONF_DISTFILES): Distribute Makefile too.\n\nThu Feb 13 16:25:09 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (SH_LD, SH_LDFLAGS): New variables.\n\t* Makeconf.in: Substitute them.\n\n\t* configure.in (SH_LIBS, SH_FLIBS, SH_TERMLIBS): Delete.\n\n\t* Makeconf.in (SH_LIBS, SH_FLIBS, SH_TERMLIBS): Delete.\n\n\t* octave-bug.in: Reinstate RLD_FLAG.\n\t* mkoctfile.in: Likewise.\n\t* Makeconf.in: Likewise.\n\n\t* configure.in: Reinstate RLD_FLAG, but make it optional.\n\nTue Feb  4 14:10:35 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (binary-dist): Use find and xargs instead of\n\trequiring chmod to support X.\n\nMon Feb  3 23:51:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* examples/info-emacs-octave-help: Update from Kurt Hornik.\n\nFri Jan 31 20:41:15 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dlfcn/Makefile.in (all): Make libdlfcn.a, not dlfcn.a.\n\nWed Jan 29 00:18:55 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in: Use -M instead of -MM to generate dependencies.\n\tDon't strip $(srcdir) from output.\n\n\t* examples/Makefile.in (install): Install info-emacs-info and\n\tinfo-emacs-octave-help in $(archlibdir).\n\n\t* configure.in (INSTALL_SCRIPT): Substitute this in Makefiles.\n\t* octMakefile.in (INSTALL_SCRIPT): New macro.\n\t(install): Use it.\n\t* Makefile.in (install-strip): New target.\n\nTue Jan 28 09:48:32 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Don't look for values-X*.o.  This is\n\tapparently added automatically now by gcc.  Don't put space\n\tbetween -L and directory name.\n\n\t* Makefile.in (help): New target.\n\t(header-msg): extract from all.\n\t(all, help): Depend on header-msg.\n\n\t* aclocal.m4 (ld_run_path): Fix typo in last fix.\n\nMon Jan 27 00:10:10 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.2 released.\n\n\t* configure.in: Add check for usleep().\n\t(bsd_gcc_kluge_targets_frag): New fragment.\n\n\t* Makefile.in: Delete `internal' targets.\n\t(static-binary-dist, dynamic-binary-dist): Special cases.\n\n\t* octMakefile.in (static-binary-dist, dynamic-binary-dist):\n\tNew targets.\n\t(binary-dist, bin-dist): Delete.\n\nSun Jan 26 19:39:51 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/Makefile.in: New file.\n\t* configure.in: create emacs/Makefile.\n\t* octMakefile.in: Move/add emacs dir to the appropriate lists.\n\nSat Jan 25 22:27:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_CHECK_TYPE): New macro, stolen from bash.\n\t* configure.in: Use it.\n\t* acconfig.h: Add #undef for sigset_t.\n\n\t* configure.in (RLD_FLAG): Delete.\n\t* mkoctfile.in (RLD_FLAG): Delete.\n\t* octave-bug.in (RLD_FLAG): Delete.\n\t* Makeconf.in (RLD_FLAG): Delete.\n\n\t* Makefile.in (bin-dist): New target.\n\n\t* install-octave: Rename from doinstall.sh.  Update for 2.x.\n\nWed Jan 22 11:14:07 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (ld_run_path): Anchor search at beginning of line to\n\tavoid GNU sed bug on HP-UX systems.  Use just one sed command.\n\n\t* emacs/octave-hlp.el, emacs/octave-inf.el, emacs/octave-mod.el:\n\tNew files from Kurt Hornik.\n\t* emacs/octave.el: Delete.\n\nMon Jan 20 11:16:21 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkoctfile.in (ALL_CXXFLAGS): Delete reference to -lg++.\n\n\t* configure.in (RLD_FLAG): For sparc-sun-sunos4*, remove space\n\tbetween -L and $(libdir).\n\t(FPICFLAG): If using g77, set it to -fPIC.\n\nSun Jan 19 15:57:20 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in, configure.in: Delete FUGLY.\n\nWed Jan  8 23:12:02 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (DEFAULT_PAGER): On cygwin32 systems, also look for\n\tmore.com.\n\nTue Jan  7 00:16:35 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.1 released.\n\nThu Dec 19 16:18:59 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Only add -Xlinker args if compiler is\n\tgcc.\n\nSat Dec 14 09:46:50 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* README.Linux: New file.\n\t* octMakefile.in: Distribute it.\n\nFri Dec 13 22:37:49 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (TERMLIBS): Look for termcap and terminfo after\n\tncurses and curses.\n\nThu Dec 12 02:27:08 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (ALL_LDFLAGS): Add CPICFLAG here since gcc needs it\n\ton some systems.\n\n\t* configure.in (FPICFLAGS): Set to -fPIC if using g77 on HP/UX.\n\n\t* Makefile.in, octMakefile.in: Delete all doc-dist, local-dist,\n\tand split-dist targets.  Likewise for all other Makefiles in the\n\tsubdirectories.\n\n\t* README.Windows: Renamed from README.WINDOWS.\n\nTue Dec 10 01:33:52 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0 released.\n\n\t* octMakefile.in (binary-dist): Print message instead of making a\n\tbinary distribution.\n\nMon Dec  9 11:28:27 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* README.WINDOWS: New file.\n\t* octMakefile.in: Distribute it.\n\n\t* configure.in: Substitute EXE.  On cygwin32 systems, set it to .exe.\n\t* Makeconf.in (EXE): Add definition.\n\n\t* configure.in: On cygwin32 systems, set default to disable GNU info.\n\n\t* aclocal.m4 (OCTAVE_STRING_NPOS): New macro.\n\t* configure.in: Call it.\n\n\t* acconfig.h: Add undef for NPOS.\n\t* config.h.bot: Remove kluge for deciding whether to define NPOS.\n\nThu Dec  5 11:05:02 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.sub: Update to current version from FSF.\n\n\t* Makeconf.in (ALL_LDFLAGS): Add $(FORTRAN_MAIN_FLAG).\n\t* configure.in (FORTRAN_MAIN_FLAG): Substitute it.\n\n\t* octave-bug.in: Prompt for abort, edit, list, or send.\n\tGet subject from message in case it has been edited.\n\n\t* configure.in: When looking for libf2c, provide definitions for\n\tMAIN_ and MAIN__.\n\nTue Dec  3 11:35:35 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.guess: Delete second copy of script in file.\n\nSun Nov 24 21:40:25 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Set GCC_IEEE_FP_FLAG to -mieee-fp on all x86\n\tsystems, not just those running Linux.\n\nFri Nov 22 15:10:34 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave.el: Update from Kurt Hornik to with fixes for\n\tfill-paragraph.\n\nWed Nov 20 00:33:03 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.93.\n\n\t* aclocal.m4 (OCTAVE_STRUCT_GR_PASSWD): New macro.\n\t* configure.in: Use it.\n\t* acconfig.h (HAVE_GR_PASSWD): Add undef.\n\nTue Nov 19 23:10:01 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (INCFLAGS): Add libcruft/misc directory.\n\nThu Nov 14 00:07:31 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave.el (octave-text-functions): Change set and show to\n\tgset and gshow.\n\n\t* Makeconf.in (TEXI2DVI): Define to be our own private version.\n\n\t* texi2dvi: New file.\n\t* octMakefile.in (DISTFILES): Add it to the list.\n\n\t* configure.in: Don't substitute values in src/mk-oct-links.in.\n\n\t* emacs/octave.el: Update to version 0.8.6, from Kurt Hornik.\n\n\t* configure.in (RLD_FLAG): Surround case pattern in changequote.\n\n\t* Version 1.92.\n\nWed Nov 13 11:04:26 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't set or substitute LIBINFO.\n\t(infofile): Set and substitute a default value.\n\n\t* Makeconf.in (do-subst-default-values): Substitute it here.\n\n\t* configure.in: If running on an SCO system, define SCO, and force\n\tHAVE_ISINF and HAVE_ISNAN to be defined.\n\tAlso check for ieeefp.h and nan.h.\n\t* acconfig.h (HAVE_ISINF, HAVE_ISNAN, SCO): Add undefs.\n\nTue Nov 12 21:50:49 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* MAKEINFO.PATCH: Update to use patch relative to texinfo-3.9.\n\n\t* INFO.PATCH: New file.\n\t* octMakefile.in (DISTFILES): Add it.\n\n\t* info: Update to current release from texinfo-3.9.\n\nMon Nov 11 23:56:58 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.h.bot: Only check value of __GNUC__ and __GNUC_MINOR__ if\n\t__GNUC__ is defined.\n\nFri Nov  8 11:15:07 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (version): Look in $(TOPDIR)/src then\n\t$(srcdir)/$(TOPDIR)/src for version.h.\n\n\t* configure.in (TERMLIBS): Print warning message if no term\n\tlibrary is found.\n\t(CXXLIB_LIST, CXXLIB_PATH, FLIB_LIST, FLIB_PATH): Delete.\n\t* Makeconf.in (CXXLIB_LIST, CXXLIB_PATH, FLIB_LIST, FLIB_PATH):\n\tDelete.\n\t(do-subst-default-vals): Delete CXXLIB_LIST, CXXLIB_PATH,\n\tFLIB_LIST, and FLIB_PATH from the list.\n\nThu Nov  7 12:43:36 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (bin-dist-tar): Delete references to octtopnm.\n\n\t* configure.in (RLD_FLAG): Define if x86-linux.\n\n\t* Version 1.91.\n\nWed Nov  6 16:26:39 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Add checks for group stuff.\n\nTue Nov  5 12:32:30 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Add checks for geteuid, getuid.\n\n\t* configure.in: Comment out code to handle --enable-readline since\n\tit doesn't work yet.\n\n\t* aclocal.m4 (OCTAVE_SIGNAL_CHECK, OCTAVE_REINSTALL_SIGHANDLERS):\n\tNew checks stolen from bash 2.0 config.\n\t* configure.in: Use them.\n\n\t* acconfig.h: Add #undefs for HAVE_BSD_SIGNALS, HAVE_POSIX_SIGNALS,\n\tHAVE_USG_SIGHOLD, and MUST_REINSTALL_SIGHANDLERS.\n\nMon Nov  4 11:31:22 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for gethostname in libsocket.  Apparently\n\tneeded for some SCO systems.\n\n\t* emacs/octave.el: Update to version 0.8.5 from Kurt Hornik.\n\nFri Nov  1 01:33:40 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (octave-bug, mkoctfile): After substituting\n\tvalues, chmod a+rx.\n\nThu Oct 31 13:50:06 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (DISTFILES): Add NEWS.[0-9].\n\t* NEWS.1: Old news.\n\t* NEWS: Just keep news since last major release.\n\nWed Oct 30 01:04:13 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.90.\n\n\t* configure.in: Default is now no internal bounds checking.\n\n\t* Makefile.in (all): Fix message to say 2.7.2, not 2.7.0.\n\n\t* config.h.bot (GCC_ATTR_NORETURN): Rename from NORETURN.\n\t(GCC_ATTR_UNUSED): Rename from GCC_ATTRIBUTE_UNUSED.\n\t(NPOS): Define if using gcc 2.8.x or later.\n\n\t* octMakefile.in (DIRS_TO_MAKE): Add localarchlibdir to list.\n\n\t* configure.in (localarchlibdir): New variable.\n\t* Makeconf.in (localarchlibdir): Substitute it.\n\t(do-subst-default-vals): Likewise.\n\nSun Oct 27 14:03:36 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (do-subst-config-vals): Split into two sed commands\n\tto try to avoid fixed limits in some seds and/or systems.\n\nFri Oct 25 01:13:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.h.bot: Add definition for GCC_ATTRIBUTE_UNUSED.\n\n\t* configure.in: Define RUSAGE_TIMES_ONLY if cygwin32.\n\t* acconfig.h: Add undef.\n\nThu Oct 24 21:17:53 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.guess: Update to version that understands what to do for\n\tcygwin32 systems.\n\nFri Oct 18 12:23:57 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't comment out substitutions for plplot stuff.\n\nWed Oct 16 12:01:37 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* examples/Makefile.in (install): New target.\n\nTue Oct 15 14:40:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Comment out plplot stuff.\n\tIn commands to get gxx_version and gcc_version, use simpler sed\n\tcommand to avoid confusing brain-dead vendor-supplied seds.\n\nMon Oct 14 11:09:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (maintainer-clean distclean): Remove mkoctfile too.\n\t(kpathsea.info): New target.\n\t(dist-info-files): New target.\n\t(links-for-dist, links-for-bin-dist, local-dist-tar):\n\tDepend on dist-info-files instead of individual files.\n\nSat Oct 12 00:17:06 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* examples/Makefile.in (clean, mostlyclean): New targets.\n\n\t* octMakefile.in (CLEANSUBDIRS): New macro.\n\tUse it for clean targets.\n\n\t* config.h.bot (STATIC_CAST, DYNAMIC_CAST, REINTERPRET_CAST):\n\tNew macros.\n\nWed Sep 25 12:24:20 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't look in /usr/ucb/include to find getrusage\n\ton Solaris systems since that just seems to cause trouble.\n\t* Makeconf.in (UCB_INCFLAGS): Delete.\n\nFri Aug 30 09:07:23 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (TERMLIBS): Add check for ncurses.\n\nTue Aug 20 21:40:26 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Always set FPICFLAG, CPICFLAG, CXXPICFLAG, SHLEXT,\n\tRLD_FLAG, DLFCN_DIR, even if SHARED_LIBS is false.\n\nThu Aug 15 14:39:07 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (gxx_version, gcc_version): Strip out cygnus- from\n\tthe version number.\n\nTue Jul 30 12:55:43 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Also check for -bI:FILE arg to ld,\n\tfor AIX systems.\n\nThu Jul 25 03:09:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: On AIX systems, add \"-ll -lld\" to LIBDLFCN.\n\nFri Jul 19 13:02:05 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: If using g77 on alpha, don't add -fpe1 to FFLAGS.\n\nMon Jul 15 14:26:48 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.sub: Update to new version from FSF (gcc sources).\n\nThu Jun 13 16:38:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Look for g77 before other fortran compilers.\n\nThu Jun  6 00:05:47 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Add check for multiple plot windows in gnuplot.\n\t* acconfig.h: Add #undef for GNUPLOT_HAS_FRAMES.\n\nWed May 22 15:05:40 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (UCB_INCFLAGS): Another kluge to try to find\n\tgetrusage on Solaris systems.\n\t* Makeconf.in Substitute it.\n\n\t* configure.in (SH_LIBS, SH_FLIBS, SH_TERMLIBS): Define.\n\t* Makeconf.in: Substitute.\n\nWed May 22 02:42:32 1996  Kurt Hornik  <Kurt.Hornik@tuwien.ac.at>\n\n\t* emacs/octave.el (octave-indent-new-line): Protect\n\toctave-indent-line with save-excursion.\n\t(octave-calc-indent-this-line): Attempt to handle end tokens that\n\tare not on separate lines.\n\t(octave-electric-semi): Make `;' self-insert if inside comment.\n\t(octave-previous-line): Don't try to go back past the beginning of\n\tthe buffer.\n\nTue May 21 23:11:46 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (F77): Also check for f90.\n\nMon May 20 12:22:54 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave.el (octave-indent-new-line): Make it do what the\n\tdocstring says it does.\n\n\t* octave-bug.in: Fix previous change so it also matches things\n\tlike 1.90, not just 1.1.90.\n\nFri May 17 09:58:49 1996  Kurt Hornik  <Kurt.Hornik@tuwien.ac.at>\n\n\t* emacs/octave.el (octave-electric-semi): Also call octave-indent-line\n\tto indent the current line after inserting a semicolon.\n\nFri May 17 02:53:49 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (DIRS_TO_MAKE): Add octincludedir.\n\t(all): Add mkoctfile.\n\n\t* configure.in: Don't set values for exec_prefix, bindir, datadir,\n\tlibdir, libexecdir, includedir, mandir, or infodir, so that they\n\tcan be set from the configure command line.\n\n\t* configure.in, Makeconf.in: Handle mandir, man1dir and man1ext.\n\tChange topincludedir to includedir.  Use octincludedir as the\n\tsubdirectory of includedir where we really install include files.\n\n\t* octave-bug.in (BUGADDR): Also set to octave-maintainers if this\n\tlooks like a pretest version number.\n\n\t* Makeconf.in (do-subst-config-vals): Use $< instead of\n\treferencing $(srcdir) directly.\n\t(do-subst-default-vals): Likewise.\n\n\t* octMakefile.in (octave-bug): Depend on octave-bug.in\n\t(mkoctfile): Likewise, depend on mkoctfile.in.\n\nThu May 16 11:49:46 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (DISTFILES): Add mkoctfile.in.\n\t(install): Install mkoctfile too.\n\n\t* aclocal.m4 (OCTAVE_F2C_F77_COMPAT): Fix typo in last change\n\nMon May 13 04:02:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (UGLY_DEFS): Quote \" with more \\'s.\n\n\t* Makeconf.in (do-subst-config-vals): Quote substitutions here.\n\t* octave-bug.in, mkoctfile: Not here.\n\n\t* octMakefile.in (octave-bug, mkoctfile): Depend on Makeconf,\n\toctMakefile.\n\n\t* Makeconf.in (do-subst-default-vals): New definition, from\n\tsrc/Makefile.in.\n\n\t* Makeconf.in (do-subst-config-vals): Define here.\n\t* octMakefile.in: Not here.\n\n\t* octave-bug.in: Handle more configuration stuff.\n\n\t* configure.in (config_opts): Set from ac_configure_args and subst.\n\t* Makeconf.in: Handle config_opts.\n\t* octMakefile.in (do-subst-config-vals): Substitute them.\n\nSun May 12 03:37:55 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (TERMLIBS): Substitute here.\n\n\t* configure.in (topincludedir): New variable.\n\t* Makeconf.in (libexecdir): Substitute it.\n\n\t* octMakefile.in (do-subst-config-vals): Define new command.\n\t(octave-bug): Use it.\n\t(mkoctfile): New target.\n\n\t* Makefile.in (TARGETS): Add mkoctfile.\n\n\t* examples: New subdirectory.\n\t* octMakefile.in: Add it to the appropriate lists.\n\t* configure.in: Create examples/Makefile.\n\n\t* octMakefile.in (DIRS_TO_MAKE): Add $(libdir) here.\n\t(install): Use INSTALL_PROGRAM to install octave-bug script.\n\tAlso install config.h.\n\n\t* aclocal.m4 (OCTAVE_F2C_F77_COMPAT): Provide a definition for\n\tMAIN__ on Linux systems.\n\nTue Apr 30 05:44:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Handle --enable-bounds-check.\n\t* acconfig.h: Add undef for BOUNDS_CHECKING\n\nMon Apr 29 01:42:38 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_FUNC_SETVBUF_REVERSED): Delete.  Octave doesn't\n\tneed this check (it was for info, which has its own configure now).\n\nSun Apr 28 05:41:26 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (DEFAULT_PAGER): Don't append -e to less here.\n\nSat Apr 27 22:23:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for pid_t and sys/types.h.\n\nTue Apr 23 17:44:18 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for fcntl.h, not sys/fcntl.h.\n\tAdd checks for various system calls.\n\nSun Apr  7 16:42:54 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for strdup.\n\n\t* Makefile.in (TARGETS): Add dlfcn.\n\t* octMakefile.in (DISTSUBDIRS): Add dlfcn.\n\t(SUBDIRS): Add @DLFCN_DIR@.\n\t* configure.in: On AIX systems: set DLFCN_DIR=dlfcn when doing\n\tshared libraries, bypass checks for dlopen, etc., set and\n\tsubstitute LIBDLFCN and DLFCN_INCFLAGS.  Create dlfcn/Makefile.\n\nSat Apr  6 21:45:40 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (%.d : %.cc, %.d : %.c): Add dependency for pic/%.o.\n\nFri Mar 29 13:38:40 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (maintainer-clean distclean): Delete mk-oct-links.\n\nWed Mar 27 09:05:01 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Fix typo in message.\n\nTue Mar 26 02:41:16 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (UGLY_DEFS): Undo previous change.\n\tWhen checking for various libraries, don't check for main(), but\n\tinstead look for functions that are actually supposed to be in\n\tthose libraries.\n\tRequire autoconf 2.9.\n\tIf using solaris2, don't add /usr/ucblib/libucb.a to LIBS until\n\tnear the very end, then check for for getrusage and times just\n\tafter that.\n\n\t* Makeconf.in (UGLY_DEFS): Ditto.\n\n\t* octave-bug.in: Don't send empty bug reports.\n\nSat Mar 23 04:55:46 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (DISTDIRS): Omit plplot for now.\n\t* Makefile.in (TARGETS): Likewise.\n\nFri Mar 22 06:15:44 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Add checks for sys/times.h and times().\n\t(GCC_IEEE_FP_FLAG): Define this if using gcc 2.8.x or later on\n\tAlpha/OSF systems.\n\nWed Mar 20 02:04:08 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (octave.info): cd to doc/interpreter, not doc.\n\nSun Mar  3 10:01:13 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.h.bot: Define HEAVYWEIGHT_INDEXING here.\n\n\t* Makefile.in (TARGETS): Remove dld.\n\t* octMakefile.in (DISTSUBDIRS): Ditto.\n\t* configure.in: Don't create dld/Makefile.\n\tDo create doc/fac/Makefile, doc/interpreter/Makefile,\n\tdoc/liboctave/Makefile, and doc/refcard/Makefile.\n\nThu Feb 29 08:55:25 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (%.o : %.c): Use pattern rule instead of suffix rule.\n\t(%.o : %.cc): Likewise.\n\t(pic/%.o : %.c, pic/%.o : %.cc): Use separate rules instead of\n\texpecting one rule to generate two output files.\n\t* configure.in (f77_rules_frag): Use separate rules here too.\n\nMon Feb 26 03:34:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: If --disable-dl or --disable-shl, don't check for\n\tdynamic linking functions.\n\t(includedir): Append version.\n\nWed Feb 14 12:20:57 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (snapshot-version): Don't quote version number.\n\n\t* aclocal.m4 (OCTAVE_FLIBS): Avoid setting FLIBS=\" \".\n\nSat Feb 10 12:59:22 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* glob/Makefile.in (install): New target.\n\nFri Feb  9 14:00:53 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Fix help text for --enable-shared option.\n\nThu Feb  8 10:17:55 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (CONF_DISTFILES): New variable.\n\t(DISTFILES): Use it instead of listing things twice.\n\t(CONF_DISTSUBDIRS): New variable.\n\t(conf-dist): New target.\n\n\t* Makefile.in (TARGETS): Add conf-dist.\n\n\t* configure.in (CXX_VERSION, CC_VERSION): Substitute them.\n\t* octMakefile.in (octave-bug): Substitute them here too.\n\t* octave-bug.in: Put them in the configuration message.\n\nSat Feb  3 08:53:56 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: RLD_FLAG should be empty by default, but give it a\n\tvalue for alpha-dec-osf* systems.\n\nFri Feb  2 23:03:40 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in: Actually do add substitutions for FPICFLAG,\n\tCPICFLAG, and CXXPICFLAG.\n\nThu Feb  1 14:58:16 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (%.c : %.f): Fix typo.\n\nWed Jan 24 14:47:58 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Also configure in glob subdirectory.\n\tMake pattern rule say how to make .o from .f, not .f from .o.  Duh.\n\n\t* octMakefile.in: Add glob stuff to the appropriate lists.\n\t* Makeconf.in: Likewise.\n\n\t* aclocal.m4: Add test for program_invocation_name.\n\t* configure.in: Use it here.\n\n\t* acconfig.h: Add #undef here.\n\nMon Jan 22 17:32:00 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Add checks for mode_t, off_t, size_t, uid_t,\n\tdev_t, ino_t, and nlink_t typedefs.\n\t* acconfig.h: Add undefs for dev_t, ino_t, and nlink_t.\n\nSat Jan 20 21:05:49 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: For Fortran rules, use pattern rules instead of\n\tsuffix rules.\n\nFri Jan 19 12:38:23 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: When checking for libf2c.a, add -lm and an extra lib.\n\nWed Jan 10 16:36:43 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.i: Add missing colon in .o.f pattern for f2c rules.\n\nMon Jan  8 23:18:39 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_PROG_LN_S): New check.\n\t* Makeconf.in (LN_S): Substitute it.\n\n\t* configure.in (libexecdir): New variable.\n\t(archlibdir, octfiledir, localoctfiledir): Use it instead of libdir.\n\t(datadir): Default to $(prefix)/share instead of $(prefix)/lib.\n\n\t* Makeconf.in (libexecdir): Substitute it.\n\n\t* configure.in (localoctfiledir): Use $(libdir), not $(datadir).\n\nSun Jan  7 18:40:00 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* aclocal.m4 (OCTAVE_SMART_PUTENV): New macro, extracted from\n\tthe kpathsearch library.\n\t* configure.in: Call it.\n\nFri Dec 29 22:07:52 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makeconf.in (subdir-for-command): New definition for\n\tSUBDIR_FOR_COMMAND using GNU Make `foreach' instead of shell `for'\n\tcommand.\n\t* libcruft/Makefile.in, scripts/Makefile.in, octMakefile.in:\n\tInvoke new definition with `@'.\n\nWed Dec 27 14:27:48 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (SUBDIRS): Delete DLD_DIR.\n\t(distclean): Delete Makerules.f77.\n\n\t* Makeconf.in (WITH_DLD): Delete variable.\n\n\t* configure.in: Delete support for dynamic linking with dld.\n\n\t* configure.in, Makeconf.in: Use consistent names for WITH_DL,\n\tWITH_SHL, OCTAVE_LITE, and SHARED_LIBS\n\n\t* config.h.bot: Undo previous change.\n\t* acconfig.h: Add #undef for WITH_DYNAMIC_LINKING.\n\t* Makeconf.in: Substitute it here too.\n\t* configure.in: Set it here.\n\nTue Dec 26 00:12:14 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_CONFIG_SUBDIRS): Delete libcruft.\n\t(AC_OUTPUT): List libcruft files here.\n\n\t* configure.in, Makeconf.in: Handle Fortran compilation rules\n\tusing an included fragment in Makeconf.\n\nMon Dec 25 22:14:21 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (CPICFLAG, CXXPICFLAG, FPICFLAG): New variables.\n\t* Makeconf.in: Substitute them.\n\n\t* configure.in: Handle --enable-shared option.\n\tHandle Fortran source files differently.\n\t* Makeconf.in (SHARED_LIBS): Substitute shared_libs.\n\t(SHLEXT, RLD_FLAG, fortran_rules_flag): Substitute these too.\n\t(.c.o, .cc.o): Handle creating position independent code for\n\tshared libraries.\n\nSun Dec 24 00:29:12 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.h.bot: Maybe define WITH_DYNAMIC_LINKING.\n\n\t* Makeconf.in (WITH_DL, WITH_SHL): Substitute values.\n\t* acconfig.h: Add undefs for WITH_DL and WITH_SHL.\n\t* configure.in: Handle --enable-dl and --enable-shl.\n\tCheck for -ldl and dlopen, dlsym, dlclose, and dlerror.\n\tCheck for -ldld and shl_load, shl_findsym.\n\t(have_fortran_compiler): Quit if no suitable Fortran compiler is\n\tfound.\n\nFri Nov  3 03:33:42 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* emacs/octave-mode.el: Rename from octave.el.\n\nWed Oct 11 19:22:12 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (GNUPLOT_BINARY): When checking for multiplot,\n\tissue a `set term unknown' command first.\n\nWed Oct  4 01:42:35 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.guess: Add entry for PowerPC Macs running Machten.\n\n\t* octMakefile.in (dist-z): Remove old .gz file before creating new one.\n\nMon Oct  2 19:17:22 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check to see if it looks like gnuplot supports\n\tmultiplot.\n\t* acconfig.h: Add undef for GNUPLOT_HAS_MULTIPLOT.\n\n\t* acconfig.h: #undefs for HAVE_FINITE, HAVE_ISNAN, HAVE_ISINF,\n\tHAVE_TERMIOS_H, HAVE_TERMIO_H, and HAVE_SGTTY_H removed.  This\n\tfile should only have things that autoheader can't figure out.\n\nSun Oct  1 17:08:37 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (clean-tar): Also omit directories called OLD and\n\tfiles beginning with =.\n\nFri Sep 29 01:04:31 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ROADMAP: New file.\n\t* (DISTFILES): Include it.\n\n\t* emacs: New subdirectory for Emacs-related stuff.\n\t* octMakefile.in (DISTDIRS, BINDISTSUBDIRS): Include emacs.\n\t(DISTFILES, BINDISTFILES): Don't include octave-mode.el.\n\nTue Sep 26 03:56:39 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't add -Wno-unused to CFLAGS or CXXFLAGS.\n\t* config.h.bot: Remove definition of UNUSED.\n\n\t* config.sub: Replace with current version from FSF.\n\t* config.guess: Likewise.\n\nThu Sep 21 20:29:00 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AR, ARFLAGS): Set defaults for these, but also\n\tallow them to come from the environment.\n\t* Makeconf.in (AR, ARFLAGS): New variables to substitute.\n\nWed Sep 20 00:51:24 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octMakefile.in (maintainer-clean): Also remove Makeconf,\n\tconfig.cache, config.h, and config.log.\n\nTue Sep 19 17:20:32 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.h [HAVE_SIGACTION && HAVE_SIGPROCMASK &&\n\tHAVE_SIGPENDING && HAVE_SIGSUSPEND]: #define HAVE_POSIX_SIGNALS.\n\n\t* configure.in: Check for sigaction(), sigprocmask(),\n\tsigpending(), and sigsuspend() functions.\n\tDon't do anything special about checking for termios.h, termio.h,\n\tand sgtty.h.\n\nMon Sep 18 22:39:33 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* config.h.bot [__GNUC__]: Define NORETURN.\n\nFri Sep 15 05:12:29 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_C_BIGENDIAN): Remove test.\n\nThu Sep 14 02:07:51 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (LIBPLPLOT): Disable plplot by default for now.\n\tCheck for mkdir, rmdir, rename, and umask.\n\n\t* All Makefile.in files: Convert from realclean to\n\tmaintainer-clean, for GNU coding standards.\n\n\t* configure.in: Call AC_FUNC_CLOSEDIR_VOID.\n\nWed Sep 13 03:25:37 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Do check for IEEE functions on the Alpha.\n\nMon Sep 11 19:08:47 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Call AC_STRUCT_ST_BLKSIZE, AC_STRUCT_ST_BLOCKS,\n\tand AC_STRUCT_ST_RDEV.\n\nTue Sep  5 02:02:35 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Check for sys/param.h and sys/stat.h\n\tUse AC_HEADER_TIME, not AC_TIME_WITH_SYS_TIME.\n\tUse AC_HEADER_SYS_WAIT.\n\nThu Aug 24 15:35:44 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Don't set or call AC_SUBST for CXXFLAGS or CFLAGS,\n\tand don't call AC_SUBST for LDFLAGS -- autoconf takes care of this.\n\tIf adding -Wall, add -Wno-unused too.\n\nTue Aug 22 01:37:02 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (all): Update message.\n\n\t* config.h.bot: New file.\n\t* octMakefile.in (DISTFILES): Add it to the list.\n\n\t* acconfig.h (USE_PLPLOT): Add #undef.\n\nMon Aug 21 19:33:33 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (NO_DEP_TARGETS): New variable, for targets that can\n\tbe made without updating dependency files.\n\nSun Jun 25 18:27:49 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in (FFLAGS): Add -fpe1 on alpha-dec-osf1 systems.\n\nThu May  4 22:26:34 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: export CC, CXX, and F77 before calling\n\tAC_CONFIG_SUBDIRS.\n\nMon May  1 14:17:07 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: Handle --with-plplot.\n\t(AC_CONFIG_SUBDIRS): Add plplot directory if --with-plplot.\n\t* plplot: New subdirectory.\n\t* Makefile.in (plplot): New target.\n\t* octMakefile.in (SUBDIRS): Add @PLPLOT_DIR@.\n\t(DISTDIRS): Add plplot.\n\n\t* acconfig.h: Add #undef for GETTIMEOFDAY_NO_TZ.\n\n\t* configure.in: Improve check for gettimeofday.\n\nMon May  1 12:50:03 1995  John Eaton  (jwe@bullwinkle.che.utexas.edu)\n\n\t* acconfig.h (OCTAVE_LITE): Fix comment.\n\nTue Apr 11 20:31:52 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in (INFO_DIR, READLINE_DIR): New variables.\n\tIf $USE_GNU_INFO, AC_DEFINE it, don't AC_SUBST it.\n\tLikewise, for USE_READLINE.\n\n\t* octMakefile.in (SUBDIRS): Substitute INFO_DIR and READLINE_DIR.\n\n\t* aclocal.m4 (OCTAVE_F77_UPPERCASE_NAMES): New macro.\n\t(OCTAVE_F77_APPEND_UNDERSCORES): Require it.\n\t* configure.in: Use it.\n\t(info_subdir): If $USE_GNU_INFO, then run configure in info\n\tsubdirectory too.\n\tDon't check for sys/ttold.h or sys/ptem.h.\n\nMon Apr 10 00:17:57 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in (UGLY_DEFS): Delete commands to create this.\n\t* Makeconf.in (UGLY_DEFS): Delete substitution.\n\t* Makeconf.in (UGLY_ALL_CFLAGS): Delete definition.\n\n\t* configure.in: Add scripts and libcruft to CONFIG_SUBDIRS.\n\tDon't edit scripts or libcruft Makefiles here.\n\tReorganize checking for the Fortran compiler.\n\n\t* octMakefile.in (DISTFILES): Delete f2c-compat.sh flibs.sh\n\tcxxlibs.sh from list.  Add aclocal.m4.\n\t* configure.in: Use new macros defined in aclocal.m4.  Don't use\n\texternal shell scripts.  Cache values.\n\n\t* aclocal.m4: New file.\n\nSun Apr  9 12:47:27 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: Print status message before exiting.\n\tCache CXXLIBS and FLIBS.\n\n\t* acconfig.h: Delete #undefs for floating point format.\n\t* octMakefile.in (DISTFILES): Delete float-type.c from list.\n\t* configure.in: Don't try to determine floating point format at\n\tconfiguration time.\n\nMon Apr  3 21:46:10 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: Create scripts/time/Makefile too.\n\n\t* configure.in (gxx_version): Handle new gcc version message.\n\t(gcc_version): Likewise.\n\nWed Mar 29 22:59:42 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in (AC_STRFTIME): Delete check.\n\t(AC_STRUCT_TIMEZONE): New check.\n\nWed Mar 22 08:31:21 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makeconf.in (ALL_FFLAGS, FUGLY): New variables.\n\n\t* configure.in: Use AC_ARG_ENABLE and AC_ARG_WITH consistently.\n\tHandle --with-g77.  Substitute new variable FUGLY.  If F77 is g77,\n\tset it to -fugly.  Substitute command for making .o from .f.\n\nTue Mar 21 14:24:32 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* cxxlibs.sh: Extract -R options like -L options.\n\t* configure.in (FLIB_PATH, FLIB_LIST): Extract -R options along\n\twith -L options.\n\nTue Mar 21 14:20:55 1995  Paul Eggert  <eggert@twinsun.com>\n\n\t* configure.in (CXX): Export; cxxlibs.sh needs this.\n\t(FLIB_LIST, CXXLIB_LIST): Extract -R options along with -L options.\n\n\t* flibs.sh: Treat `-L foo' like `-Lfoo'.  Extract -R options\n\tlike -L options.\n\nTue Mar 21 08:08:06 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* flibs.sh: Search for values-X*.o, not values-*.o.\n\nFri Mar 10 10:32:27 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makeconf.in (SUBDIR_FOR_COMMAND): New command definition.\n\t* octMakefile.in: Use it.\n\n\t* octMakefile.in (install, uninstall, tags, TAGS, clean,\n\tmostlyclean, distclean, realclean): Combine actions.\n\nTue Feb 28 21:24:35 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in (FC): Set to $F77 and substitute it.\n\t* Makeconf.in (FC): Add substitution line.\n\nSun Feb 26 00:20:19 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* dointsall.sh: Create ls-R database.\n\n\t* configure.in: Configure kpathsea using AC_CONFIG_SUBDIRS().\n\tRemove check for SMART_PUTENV.\n\tRemove kpathsea/c-auto.h from AC_CONFIG_HEADER().\n\n\t* make: New directory, for kpathsea configuration.\n\t* octMakefile.in (DISTDIRS): Add it\n\n\t* kpathsea: Update with 2.6 distribution.\n\n\t* Makefile.in (TARGETS): New variable.  Combine all identical targets.\n\n\t* configure.in (LIBINFO, LIBREADLINE): New variables to substitute.\n\nSat Feb 25 18:47:11 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* acconfig.h (USE_READLINE): Add #undef.\n\t* configure.in: Add support for --enable-readline.\n\n\t* acconfig.h (USE_GNU_INFO): Add #undef.\n\t* configure.in: Add support for --enable-info.\n\n\t* acconfig.h (RUN_IN_PLACE): Delete #undef.\n\nSee ChangeLog.1 for earlier changes.\n"
  },
  {
    "path": "etc/OLD-ChangeLogs/ChangeLog.1",
    "content": "Thu Feb 23 09:32:01 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Version 1.1.1 released.\n\n\t* src/idx-vector.cc (idx_vector (const Range&)): Always initialize\n\tdata to 0.\n\t(idx_vector (const Matrix&, int, const char *, int)): Likewise.\n\t(idx_vector (const idx_vector&): Likewise, do it first.\n\t* src/idx-vector.h (~idx_vector): Simply delete data.\n\n\t* octMakefile.in: Combine libcruft, liboctave,dld, info, readline,\n\tkpathsea, src, scripts, and doc targets into just one.\n\t(all): Depend on $(SUBDIRS).\n\t* libcruft/Makefile.in (make-objects): Change to $(SUBDIRS)\n\ttarget that doesn't use a loop.\n\t(all): Depend on $(SUBDIRS).\n\nWed Feb 22 07:27:18 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Don't leave @LIBDLD@ on a line by itself.\n\n\t* src/tc-rep-idx.cc (fortran_style_matrix_index): Handle zero-one\n\tindexing as a separate case.\n\t(fortran_style_matrix_index): Check for out-of-bounds index.\n\n\t* src/idx-vector.cc (init_state): Don't forget len, num_zeros, and\n\tthe one_zero flag for vectors of all zero elements.\n\t(convert_one_zero_to_idx): Set data to zero after deleting it.\n\n\t* src/data.cc (check_dimensions):\n\tHandle case of treat_neg_dim_as_zero = \"warn\".\n\nTue Feb 21 08:18:19 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tree-misc.cc (initialize_undefined_elements): Don't declare\n\targ const.\n\n\t* src/sysdepl.cc (octave_getcwd): Declare arg as char *, not\n\tconst char *.\n\n\t* src/input.cc (match_sans_spaces): Initialize ep from copy of\n\targ, not arg itself.\n\n\t* octMakefile.in (snapshot-version): Look for OCTAVE_VERSION,\n\tnot just VERSION.  Don't end #define with a semicolon.\n\nMon Feb 20 15:57:17 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/image/Makefile.in (clean): Delete octtopnm.o and octtopnm.\n\nFri Feb 17 08:12:09 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/variables.cc (maybe_add_default_load_path): New function,\n\textracted from default_path(), which no longer needs it.\n\t* src/user-prefs.cc (sv_loadpath): Call it here.\n\nWed Feb 15 15:13:22 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/octave.cc (verbose_usage): Format help message more like\n\tthe help messages of other GNU programs.\n\n\t* src/variables.cc (install_builtin_variables): New builtin\n\tvariable, suppress_verbose_help_message.\n\t* src/user-prefs.cc (user_prefs): New field,\n\tsuppress_verbose_help_message.\n\t* src/user-prefs.cc (suppress_verbose_help_message): New function.\n\t* src/help.cc (additional_help_message): Check\n\tuser_pref.suppress_verbose_help_message before printing message.\n\nTue Feb 14 15:36:01 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/sysdep.cc (octave_chdir): New function.\n\t* src/dirfns.cc (change_to_directory): Use it.\n\n\t* src/sysdep.cc (octave_getcwd): New function.\n\t* src/dirfns.cc (get_working_directory, Fpwd): Use it.\n\t* src/input.cc (decode_prompt_string): Likewise.\n\n\t* src/version.h (VERSION): New #define.\n\t(version_string): Use it.\n\t(OCTAVE_COPYRIGHT): New #define.\n\t(OCTAVE_NAME_AND_VERSION): New #define.\n\t(OCTAVE_NAME_VERSION_AND_COPYRIGHT): New #define.\n\t(OCTAVE_STARTUP_MESSAGE): New #define.\n\t* src/octave.cc (main): Use new macros from version.h\n\t(print_version_and_exit): Likewise.\n\t(verbose_usage): Likewise.\n\t(Fwarranty): Likewise.\n\n\t* Makeconf.in (version): Make work with new version.h.\n\t* octMakefile.in (snapshot-version): Likewise.\n\n\t* src/variables.cc (default_path): Use SEPCHAR instead of literal ':'.\n\t* src/utils.cc (pathstring_to_vector): Likewise.\n\t* src/octave.cc (initialize_globals): Likewise, use SEPCHAR_STR to\n\tconstruct format string instead of using literal `:'.\n\n\t* configure.in: Call AC_DEFINE for SEPCHAR and SEPCHAR_STR.\n\t* acconfig.h: Add #undefs for SEPCHAR and SEPCHAR_STR.\n\n\t* src/dynamic-ld.cc: Don't include dld.h unless WITH_DLD.\n\n\t* src/octave.cc (parse_and_execute): Close file.\n\nMon Feb 13 19:39:12 1995  John Eaton  (jwe@bullwinkle.che.utexas.edu)\n\n\t* scripts/general/linspace.m: Delete.\n\t* src/data.cc (Flinspace): New function.\n\t* liboctave/dRowVector.cc (linspace): New function.\n\t* liboctave/CRowVector.cc (linspace): New function.\n\nSun Feb 12 21:23:54 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/load-save.cc (read_mat_binary_data): Only convert to string\n\tif the number of rows is 1.\n\n\t* scripts/image/saveimage.m: Force ASCII save.\n\nThu Feb  9 08:46:09 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/elfun/sec.m: Returned variable is `w', not `y'.\n\t* scripts/elfun/sech.m: Likewise.\n\nWed Feb  8 10:51:33 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/f-find.cc (find_nonzero_elem_idx): Increment i, j indices by\n\t1 before stashing them.\n\nFri Feb  3 15:44:03 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tree-misc.cc\n\t(tree_parameter_list::initialize_undefined_elements): New function.\n\t* src/tree-expr.cc (tree_function::eval): Use it to define return\n\tvalues.\n\t(tree_simple_assignment_expression:eval): Complain if RHS is undefined.\n\t(tree_multi_assignment_expression:eval): Complain if any of the\n\tRHS values are undefined.\n\t* src/user-prefs.h (init_user_prefs): New structure element,\n\tdefine_all_return_values.\n\t* src/user-prefs.cc (define_all_return_values): New function.\n\t* src/variables.cc (install_builtin_variables): Add DEFVARs for\n\tdefault_return_value and define_all_return_values.\n\t(builtin_any_variable): New function.\n\nWed Feb  1 08:02:28 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/parse.y (parse_error): Call yyerror() here.\n\t(input): Not here.\n\n\t* src/lex.l (handle_string): Call have_continuation and\n\thave_ellipsis_continuation with 0 arg, to disallow comments after\n\tcontinuation characters inside strings.\n\t(have_continuation): New arg, trailing_comments_ok with default\n\tvalue of 1.  If !trailing_comments_ok, don't allow comments to\n\tfollow continuation token.\n\t(have_ellipsis_continuation): New arg, trailing_comments_ok, with\n\tdefault value of 1.  Pass it along to have_continuation.\n\n\t* src/parse.y (yyerror): Call parse_error with first arg == \"%s\",\n\tsince msg might contain format specifiers.\n\n\t* src/tree-expr.cc (tree_index_expression::eval (int)): Detect\n\tundefined elements in argument list and print error message.\n\t(tree_index_expression::eval (int, int, const Octave_object&)):\n\tLikewise.\n\n\t* configure.in: Only set CFLAGS, CXXFLAGS, LDFLAGS, FFLAGS, and\n\tF2CFLAGS if they are not already set in the environment.\n\n\t* doinstall.sh: Add -print to find commands.\n\nTue Jan 31 13:26:53 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l (<MATRIX>{S}*\\,{S}*): Eat any trailing continuation\n\there.  Use value returned from eat_continuation to decide whether\n\tto insert a row separator.\n\t(<MATRIX>{S}+): Likewise.\n\t(<MATRIX>{SNLCMT}*\\n{SNLCMT}*): Eat any trailing whitespace here.\n\n\t* lex.l (ATE_SPACE_OR_TAB, ATE_NEWLINE): New macros.\n\t(eat_whitespace): Use them to set return value.\n\nMon Jan 30 14:02:24 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/user-prefs.cc (set_output_precision): Don't pass NaN to NINT.\n\t(set_output_max_field_width): Likewise.\n\t(set_save_precision): Likewise.\n\t* src/file-io.cc (return_valid_file): Likewise.\n\t(fgets_internal): Likewise.\n\t(fseek_internal): Likewise.\n\t(process_printf_format): Likewise.\n\t(fread_internal): Likewise.\n\t* src/f-colloc.cc (Fcolloc): Likewise.\n\t* src/f-fft.cc (Ffft): Likewise.\n\t* src/f-fft2.cc (Ffft2): Likewise.\n\t* src/f-ifft.cc (Fifft): Likewise.\n\t* src/f-ifft2.cc (Fifft2): Likewise.\n\t* src/f-npsol.cc (do_npsol_option): Likewise.\n\t* src/f-qpsol.cc (do_qpsol_option): Likewise.\n\t* src/f-rand.cc (Frand): Likewise.\n\t* src/pr-output.cc (all_elements_are_ints): Likewise.\n\t* src/tree-plot.cc (subplot_using::eval): Likewise.\n\t(subplot_style::print): Likewise.\n\t* src/sysdep.cc (Fpause): Likewise.\n\t* src/tc-rep.cc (TC_REP::valid_as_scalar_index): Likewise.\n\t(TC_REP::valid_as_zero_index): Likewise.\n\t(TC_REP::convert_to_str): Likewise.\n\t* src/tc-rep-idx.cc (TC_REP::do_scalar_index): Likewise.\n\t(TC_REP::fortran_style_matrix_index): Likewise.\n\t* src/tc-rep-ass.cc (TC_REP::fortran_style_matrix_assignment):\n\tLikewise.\n\nSat Jan 28 13:09:44 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/general/tril.m: Allow the k == nc for k > 0 and\n\t-k == nr for k < 0.  Make faster by eliminating nested loops.\n\t* scripts/general/triu.m: Likewise.\n\nFri Jan 27 08:32:10 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* libcruft/lapack: Update with files from LAPACK 2.0.\n\n\t* src/lex.l (\\[{S}*): Don't call fixup_column_count() here.\n\tDon't use TOK_RETURN here, since we call eat_whitespace().\n\t(eat_whitespace): Decrement current_input_column when calling\n\tyyunput().\n\t(<MATRIX>{SNLCMT}*\\n{SNLCMT}): Always call fixup_column_count().\n\n\t* src/parse.y (rows): Don't accept repeated semicolons.\n\t(matrix_row): Likewise, for commas.\n\n\t* src/Makefile.in (LIBOBJS): Delete.\n\n\t* liboctave/f77-uscore.h: Don't use C++ style comments.\n\n\t* octMakefile.in (DISTDIRS): Don't include bsd-math.\n\t* src/Makefile.in (VPATH): Don't include bsd-math directory.\n\t(SOURCES): Include acosh.c, asinh.c, atanh.c, erf.c erfc.c, and\n\tlgamma.c.\n\t* configure.in: Create libcruft/slatec-fn/Makefile.\n\tUse AC_CHECK_FUNCS to look for acosh, asinh, atanh.\n\tDon't do anything special if they are missing.\n\t* src/acosh.c, src/asinh.c, src/atanh.c, src/erf.c, src/erfc.c,\n\tsrc/lgamma.c: New files.\n\t* acconfig.h: Delete #undefs for ACOSH_MISSING, ASINH_MISSING,\n\tand ATANH_MISSING.\n\t* libcruft/Makefile.in (CRUFT_DIRS): Add slatec-fn.\n\t* libcruft/slatec-fn: New directory.\n\n\t* configure.in: Don't try to use IEEE floating point on m68k HP\n\tsystems.\n\nThu Jan 26 12:57:05 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l (maybe_unput_comma):  New function, extracted from\n\thandle_identifier().  Correctly handle the dot in things like\n\t`a.b' inside matrix lists.\n\t(handle_identifier): Use it.  Don't allow things like [a .1] or\n\t[a.b .1] to fool us.\n\nWed Jan 25 08:04:16 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/Makefile.in (realclean): Don't depend on distclean.  Do\n\tdelete Makefile here.\n\n\t* flibs.sh: Also check for /*values-*.o, for Sun Fortran 2.x.\n\t* configure.in (FLIB_LIST, CXXLIB_LIST, FLIB_PATH, CXXLIB_PATH):\n\tDelete any .o files found here.\n\tWhen checking for -lm, also append -lc on Linux systems.\n\n\t* mkinstalldirs: Create directories with mode 0755, to avoid\n\tproblems because the installers umask is too restrictive.\n\n\t* octave-bug.in: Don't use rmail, it crashes on Ultrix systems if\n\tthe message file isn't just right.  Use nested if statements\n\tinstead of ||, for Ultrix /bin/sh.  Avoid Ultrix awk crash.\n\n\t* scripts/linear-algebra/trace.m: Handle row and column vectors as\n\ta special case.\n\t* scripts/linear-algebra/null.m: Likewise.\n\t* scripts/linear-algebra/orth.m: Likewise.\n\nTue Jan 24 08:11:51 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* octave-bug.in: Add F2C, F2CFLAGS, FLIBS, and LDFLAGS to report.\n\t* Makefile.in (octave-bug): Substitute them.\n\nMon Jan 23 20:42:55 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tree-misc.cc (tree_if_clause::is_else_clause): New function.\n\t(tree_if_command_list::print_code): Use it to decide whether to\n\tprint \"else\" or \"elseif\" here.\n\t(tree_if_clause::print_code): Don't print \"else\" here.\n\n\t* scripts/image/colormap.m: Fix logic for initializing default\n\tcolormap and handling subsequent calls with no arguments.\n\n\t* src/lex.h (TOK_PUSH_AND_RETURN): Correct last change.\n\nSun Jan 22 18:02:37 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l (handle_identifier): Handle incrementing\n\tcurrent_input_column here.\n\t({IDENT}{S}*): Not here.\n\n\t* src/lex.h (TOK_PUSH_AND_RETURN): New macro.\n\t* src/lex.l: Use it.\n\n\t* src/parse.y (yyerror): If printing input line, always print `^'\n\terror marker too.\n\n\t* src/parse.y (command [BREAK]): Allow break to occur in function\n\tbodies too.\n\t* src/tree-expr.cc (tree_function::eval): Also check to see if\n\tfunction exited because of a break statement.\n\nFri Jan 20 10:48:18 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* config.guess: Replace with current version from FSF.\n\t* config.sub: Likewise.\n\n\t* src/tempname.c: Include statdefs.h.\n\n\t* src/tree-expr.cc (eval): Improve error messages.\n\nThu Jan 19 08:33:50 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l (handle_string): Properly handle pending escapes.\n\tCall error() for unterminated string constants.\n\t* src/parse.y (input): For parse errors, call yyerror().\n\n\t* test/config/unix-octave.exp (octave_start): Correctly set OSPATH\n\tfrom $OCTAVE_SCRIPT_PATH, not to the string OCTAVE_SCRIPT_PATH.\n\n\t* test/Makefile.in (OCTAVE_SCRIPT_PATH): Delete surrounding quotes\n\tin definition.\n\n\t* doc/texinfo.tex: Move to version 2.140.\n\n\t* src/f-rand.cc (Frand): Use different method for generating\n\tinitial seed so that it varies more each time Octave starts.\n\n\t* src/file-io.cc (feof_internal): Use args(0), not args(1).\n\n\t* src/Makefile.in (SOURCES): Use tempnam.c, not tmpnam.c.\n\t* src/tempnam.c: New file, from the GNU C library.\n\nWed Jan 18 08:10:31 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/user-prefs.h (user_prefs): New field, read_only_constants.\n\t* src/user-prefs.cc (read_only_constants): New function.\n\t* src/variables.cc (install_builtin_variables): Add DEFVAR for\n\tread_only_constants, but leave it #if 0'd out since we're not\n\treally ready for it yet..\n\t* src/symtab.cc (symbol_record::read_only_error): Check\n\tuser_prefs.read_only_constants to see if it is ok to redefine\n\tconstants that are marked as read-only.\n\n\t* src/user-prefs.h (user_prefs): New field, ps4.\n\t* src/user-prefs.cc (sv_ps4): New function.\n\t* src/variables.cc (install_builtin_variables): Add DEFVAR for PS4.\n\t* src/input.cc (do_input_echo): New function.  Use PS4 variable as\n\tprefix of echoed input.  Send echoed input through the pager.\n\n\t* flibs.sh: Ignore -lang* options.\n\n\t* src/load-save.cc (Fsave): Send `save - ...' output through the\n\tpager.\n\n\t* doc/Makefile.in: Create and distribute refcards of various sizes.\n\tDelete rules for making refcard.tex from refcard.tex.in.\n\tDon't make or distribute refcard-local.\n\t* doc/refcard.tex: Handle setting paper size with \\refcardsize.\n\t* doc/refcard-a4.tex, doc/refcard-legal.tex, doc/refcard-letter.tex:\n\tNew files.\n\nMon Jan 16 13:19:29 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tc-rep-ass.cc (TC_REP::do_scalar_assignment): Handle\n\tassignments like a(0) = [].\n\t* src/tc-inlines.h (valid_zero_index): New function.\n\t* src/tc-rep.cc (valid_as_zero_index): New function.\n\t* src/tree-const.h (valid_as_zero_index): New function.\n\n\t* src/parse.y (func_def2): Check user_prefs before warning about\n\tfunction name and function file name conflict.\n\t* src/user-prefs.h (user_prefs): New field, warn_function_name_clash.\n\t* src/user-prefs.cc (warn_function_name_clash): New function.\n\t* src/variables.cc (install_builtin_variables): Add DEFVAR for\n\twarn_function_name_clash.\n\n\t* scripts/image/octtopnm.c: Include stdlib.h instead of malloc.h.\n\nSun Jan 15 15:08:04 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* readline/rldefs.h: Use new #defines for directory headers now\n\tthat we are using autoconf 2.\n\n\t* scripts/special-matrix/hankel.m: Use .', instead of '.\n\n\t* src/input.cc (match_sans_spaces): Use strcmp, not strncmp.\n\n\t* src/tc-rep-ass.cc (TC_REP::fortran_style_matrix_assignment):\n\tFor scalar index, don't do assignment if RHS and LHS are both empty.\n\n\t* src/data.cc (Fsize): Handle optional second arg.\n\n\t* src/tree-expr.cc (tree_function::eval (int)): Correctly set\n\tnargin and nargout to zero when evaluating function.\n\n\t* src/lex.l (handle_string): Correct handling of string escapes.\n\nThu Jan 12 15:25:34 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Version 1.1.0 released.\n\n\t* octMakefile.in (bin-dist-tar): Ignore errors on strip commands.\n\n\t* src/tree-expr.cc (tree_builtin::eval (int)): Set nargout to 0\n\twhen calling function.\n\n\t* doc/Makefile.in (FORMATTED): Add refcard.dvi and refcard.ps so\n\tthat they are distributed along with the other docs.\n\t* octMakefile.in (clean-doc-dist-tar): Delete target.\n\t(doc-dist): Depend on doc-dist-tar, not\tclean-doc-dist-tar.\n\nTue Jan 10 14:29:43 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/help.cc (print_usage): Print warning if symbol isn't found.\n\n\t* src/utils.cc (Fundo_string_escapes): Fix typo in call to\n\tprint_usage().\n\n\t* src/octave.cc (Fsystem): Correctly compute exit code.\n\n\t* scripts/miscellaneous/etime.m: Complain if args are not the\n\tright length, not if they are.  Reverse sense of test for years.\n\tDuh.\n\n\t* src/f-find.cc (find_to_fortran_idx): For the case of one output\n\targument, return a row vector if the original argument to find was\n\ta row vector.\n\nMon Jan  9 12:57:27 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l (grab_help_text): Always overwrite help_buf.\n\t({CCHAR}): Don't call grab_help_text() if there is already\n\tsomething in help_buf.\n\nSat Jan  7 12:28:35 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in (HOST_CXXFLAGS): New variable to substitute.\n\t* Makeconf.in (ALL_CXXFLAGS, UGLY_ALL_CXXFLAGS, BUG_CXXFLAGS):\n\tAdd $(HOST_CXXFLAGS).\n\nFri Jan  6 13:07:09 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/special-matrix/toeplitz.m: Use .' instead of '.\n\nTue Jan  3 18:14:33 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* test: Rewrite many tests to not run Octave interactively.  This\n\tmakes the log files much more readable.\n\n\t* octMakefile.in (clean-tar): Delete octave-test/npsol directory,\n\tnot just test/octave.test/npsol.exp.  Likewise, add a command for\n\tdeleting qpsol tests.\n\nMon Jan  2 20:02:10 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/octave.cc (main): Return 0 if error_state is not set.\n\n\t* src/error.cc (error_1): New function.\n\t(error): Use it.\n\t(parse_error): New function.\n\t* src/parse.y: Never call error and yyerror; just use yyerror.\n\t(yyerror): Improve logic.  Use new parse_error() function so that\n\terror_state is always set for a parse error.  Don't use\n\tostream::form().\n\t(ABORT_PARSE): Don't call reset parser here.\n\t(colon_expr): Don't call yyerror here.  An error message is\n\tprinted by tree_colon_expression::chain() if it fails.\n\nMon Dec 26 20:11:01 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tree-expr.cc (eval): Only call multi-arg form of eval for\n\tobject_to_eval if necessary.\n\nFri Dec 23 00:08:08 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l: Don't increment promptflag anywhere.\n\t(eat_continuation): New function.\n\t(eat_whitespace): Handle embedded continuations.  Return nonzero\n\tif whitespace consumed.\n\t(handle_close_brace): Don't pass yytext.  Do pass flag indicating\n\twhether whitespace follows brace.\n\t(handle_identifier): Check for next token being `=' here.  Pass\n\tflag indicating whether whitespace follows identifier.\n\t(<MATRIX>{SNLCMT}*;{SNLCMT}*): Call eat_whitespace() here.\n\t({IDENT}{S}*): Call eat_continuation() here.\n\t(do_comma_insert_check): And here, but put a space back if\n\twhitespace is gobbled.\n\t(have_continuation, have_ellipsis_continuation): Decrement\n\tpromptflag here.\n\nWed Dec 21 09:56:49 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tree-plot.cc (Fclearplot): Send \"set nolabel\" too.\n\nMon Dec 19 17:50:15 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tree-plot.h, src/tree-plot.cc (subplot): Rename using to\n\tusing_clause to avoid new C++ keyword.  Rename title and style to\n\tmatch.\n\nFri Dec 16 00:09:01 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: Don't check for fpsetmask.\n\t* src/sysdep.cc (sysdep_init): Don't check HAVE_FPSETMASK\n\nThu Dec 15 00:28:52 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/variables.cc (install_builtin_variables) [default_save_format]:\n\tFix doc string.\n\n\t* configure.in: Rework DEFAULT_DOT_O_FROM_DOT_F and\n\tDEFAULT_DOT_C_FROM_DOT_F to avoid embedded newlines.\n\t* Makeconf.in: Likewise.\n\n\t* src/pager.cc (flush_output_to_pager): Close stream before\n\tresetting signal handler.\n\n\t* src/help.cc (Fhelp): Call fcn_file_in_path here.  Delete it too.\n\tPrint file name before help message.\n\t* src/variables.cc (get_help_from_file): Don't call\n\tfcn_file_in_path here.\n\t(gobble_leading_white_space): Correctly grab only first set of\n\tcomments.\n\nWed Dec 14 11:42:13 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/parse.y (pager_buf): Don't make it a fixed-size array.\n\t* src/variables.cc (get_help_from_file): New function.\n\t(gobble_leading_white_space): Return first block of comments for\n\tlater use as help string.\n\t(looks_like_octave_copyright): New function.\n\t(parse_fcn_file): Stash help from gobble_leading_white_space in\n\tglobal help_buf.\n\t* src/lex.l (grab_help_text): Don't overwrite help found by\n\tgobble_leading_white_space.\n\t(reset_parser): Delete help_buf.\n\t* src/help.cc (Fhelp): Only try to get help from symbol records\n\tthat are defined.  If all else fails, try get_help_from_file.\n\n\t* src/pager.cc (flush_output_to_pager): Re-initialize pager_buf\n\timmediately after extracting message.  Delete message immediately\n\tafter sending it to the output stream.  Ignore interrupts while\n\trunning pager.\n\n\t* octMakefile.in (clean-tar): Delete npsol.exp and any .m files\n\tthat are in the test/octave.test directory.\n\t(install): Use $(INSTALL), not just install.\n\n\t* src/lex.l (reset_parser): Don't reset input column or line\n\tnumber if reading from a script file or a function file.\n\t(is_keyword): Don't set line number to 1 if reading function file\n\tor script file.\n\t* src/variables.cc (gobble_leading_whitespace): Count lines.\n\t* src/octave.cc (main): If reading file, set reading_script_file\n\tand curr_fcn_file_name before calling get_input_from_file().\n\n\t* src/tc-rep.cc (TC_REP::matrix_value): If implicit_str_to_num_ok,\n\tconvert empty string to empty matrix.\n\nTue Dec 13 20:25:34 1994  Frederick (Rick) A Niles <niles@axp745.gsfc.nasa.gov>\n\n\t* liboctave/dbleQR.cc, liboctave/dbleQRP.cc, liboctave/CmplxQR.cc,\n\tliboctave/CmplxQRP.cc: Get economy-sized dimensions correct.\n\n\t* libcruft/misc/i1mach.f, libcruft/misc/gen-d1mach.c,\n\tlibcruft/ranlib/ignuin.f: Prevent warnings about variable may be\n\tused before defined.\n\nTue Dec 13 11:07:34 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/variables.cc: Change commas_in_literal_matrix to\n\twhitespace_in_literal_matrix.\n\t* src/user-prefs.h (user_preferences): Likewise.\n\t* src/user-prefs.cc (init_user_prefs): Likewise.\n\t(whitespace_in_literal_matrix): Likewise, rename function.\n\t* src/lex.l: Likewise.\n\t(nesting_level): Rename from in_brace_or_paren.\n\t(<MATRIX>{SNLCMT}*\\n{SNLCMT}*): Make separate case from\n\t<MATRIX>{SNLCMT}*;{SNLCMT}.  Check nesting level to decide whether\n\tto convert newline to semicolon.\n\t({NL}, {CCHAR}): Check nesting level to decide whether to eat\n\tor return newline.\n\t(\"(\"): Decrement promptflag.\n\t(\")\"): Increment promptflag.\n\nMon Dec 12 00:02:51 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/Makefile.in, scripts/*/Makefile.in (install): Don't\n\tdepend on all.\n\n\t* octMakefile.in: Put doc dir last.\n\t* doc/Makefile.in (dir): New file.\n\t(DISTFILES): Distribute dir.\n\t(install): Install dir if it does not already exist in $(infodir).\n\tOtherwise, print message.\n\n\t* src/lex.l: Handle {IDENT}{S}*/= with yyinput() instead of\n\ttrailing context.\n\t(handle_close_brace): New function.\n\t(handle_number): New function.\n\t(have_continuation, handle_ellipsis_continuation, handle_string):\n\tNew functions for handling strings and continuation lines in\n\tstring constants.\n\t(eat_whitespace): New function eliminates need for NEW_MATRIX\n\tstart state.\n\nSun Dec 11 15:53:03 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l: Eliminate special case for eating whitespace when\n\tstart state is <TEXT_FCN>.\n\tMerge three cases for handling `]' for <MATRIX> start state.\n\nFri Dec  9 12:21:35 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l: Handle `\\' as a continuation character too.\n\tAllow comments and blanks to follow continuation characters.\n\tImprove handling of comments in matrices.  Create a few more\n\tdefinitions for patterns.  Restructure source.\n\n\t* configure.in: Check for bcopy too.\n\n\t* configure.in (gxx_version): Don't use -fno-implicit-templates on\n\tAIX systems with g++ 2.6.x.\n\n\t* octave-bug.in: Check for CC: lines too.  Use case-insensitive\n\tmatch for To: and Cc: lines.  Actually send file that has header\n\tseparator stripped.  Print list of CC: addresses too.\n\n\t* src/input.cc (get_user_input): If user enters empty string,\n\treturn empty matrix or empty string.\n\n\t* src/help.cc (Fhelp, Ftype, Fwhich): Don't allow lookup_by_name\n\tto execute script files.\n\nThu Dec  8 23:20:02 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tc-rep.cc (print): Don't check `print', which is not a\n\tvariable in this context.\n\nWed Dec  7 10:52:59 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/configure.in: Check for fpsetmask.\n\t* src/sysdep.cc (sysdep_init): Check HAVE_FPSETMASK.  Only call it\n\tif either __386BSD__ or __FreeBSD__ is defined.\n\tDon't check __386BSD__ as a condition for including\n\tfloatingpoint.h.\n\nMon Dec  5 12:29:07 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/utils.cc: Update directory header macro names for autoconf 2.\n\t* src/dirfns.cc: Likewise.\n\nSun Dec  4 22:00:40 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* octMakefile.in (DISTFILES): Don't distribute GCC.PATCH, since it\n\tis not needed with gcc 2.6.3.\n\n\t* configure.in: Really do disable IEEE floating point functions on\n\tthe Alpha.\n\nWed Nov 30 11:42:44 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* doc/FAQ.texi: New file.\n\t* doc/Makefile.in: Create info, dvi, and ps files and distribute\n\tthem.\n\n\t* Makefile.in (all): Expand initial message.\n\nSat Nov 26 21:47:05 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/octave.cc (Fcomputer): Always append ios::ends to ostrstream\n\tbefore returning.\n\nMon Nov 21 09:41:34 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l: When start state is TEXT_FCN, gobble blanks with\n\tpattern that matches only blanks before other patterns that can\n\talso match just blanks.  Always check whether in_brace_or_paren\n\tstack is empty before trying to use it.\n\n\t* src/parse.y (make_multi_val_ret): Call constructor for\n\ttree_simple_assignment_expression with correct number of args.\n\n\t* scripts/plot/shg.m: New function.\n\n\t* src/f-qpsol.cc (Fqpsol): Correct for changes in meaning of\n\tnargin and the way args is loaded.\n\t* src/f-npsol.cc (Fnpsol): Likewise.\n\n\t* scripts/polynomial/roots.m: Return empty matrix for scalar or\n\tempty matrix args.\n\n\t* src/tree-plot.cc (gnuplot_terminal_type): New static variable.\n\t(Fset): If this is a set term command, set gnuplot_terminal_type.\n\t(open_plot_stream): Use gnuplot_terminal_type if it is set.\n\n\t* src/idx-vector.cc (idx_vector::init): Don't check max value of\n\tindex vector against dimension here.  We may need to resize.\n\t* src/tc-rep-idx.cc (do_scalar_index): Do check idx-vector max\n\tvalue here.\n\n\t* src/lex.l (is_plot_keyword): Don't set past_plot_range here.\n\tDon't accept abbreviations for clear.\n\t(handle_identifier): Don't call is_plot_keyword unless plotting.\n\tSet past_plot_range here, before checking for plot option keywords.\n\nFri Nov 18 17:25:59 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/data.cc (Fis_struct): New function.\n\nThu Nov 17 18:13:56 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* octMakefile.in (DISTFILES): Distribute GCC.PATCH.  Don't\n\tdistribute LIBG++.PATCH.\n\n\t* src/tree-plot.cc (Fclearplot): Turn off grid and reset\n\tplot_line_count to zero.\n\n\t* configure.in: Check for sys/resource.h.\n\tCreate scripts/strings/Makefile too.\n\n\t* src/timefns.cc: Surround inclusion of sys/resource.h in extern \"C\".\n\tOnly include sys/resource.h if both HAVE_SYS_RESOURCE_H and\n\tHAVE_GETRUSAGE are defined.\n\nWed Nov 16 09:26:10 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/plot/plot_opt.m: New function.\n\t* scripts/plot/semilogx.m, scripts/plot/semilogx.m,\n\tscripts/plot/loglog.m, scripts/plot/plot.m: Handle additional\n\targs and format strings.\n\t* scripts/plot/polar.m: Handle format arg.\n\t* scripts/plot/polar_int_1.m, scripts/plot/polar_int_2.m: Extract\n\tfrom polar_int.m.\n\t* scripts/plot/plot_int_1.m, scripts/plot/plot_int_2.m: Extract\n\tfrom plot_int.m.\n\t* scripts/plot/plot_2_s_s.m, scripts/plot/plot_2_v_v.m,\n\tscripts/plot/plot_2_m_m.m, scripts/plot/plot_2_v_m.m,\n\tscripts/plot/plot_2_m_v.m: Handle format arg.\n\n\t* scripts/strings/strcmp.m: Move here.\n\t* scripts/general/strcmp.m: From here.\n\n\t* src/xdiv.cc (result_ok): Issue warning instead of error if warn\n\tis nonzero.\n\nTue Nov 15 15:54:19 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tree-plot.cc (Fcloseplot): Clear title and labels too.\n\n\t* src/help.cc (keywords): Add entries for all_va_args,\n\tunwind_protect, unwind_protect_cleanup, and end_unwind_protect.\n\n\t* liboctave/Makefile.in: Use -include for dependency files.\n\t* src/Makefile.in: Likewise.\n\nMon Nov 14 10:28:23 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tree-misc.cc (convert_to_const_vector): Resize vector before\n\treturning.\n\n\t* src/lex.l (plot_style_token): Also allow \"steps\", \"boxes\", and\n\t\"boxerrorbars\".\n\n\t* src/parse.y (UNWIND): Rename from UNWIND_PROTECT.\n\t(CLEANUP): Rename from UNWIND_PROTECT_CLEANUP.\n\t(command): Allow optsep after UNWIND and CLEANUP tokens.\n\t* src/lex.l (is_keyword): Use new token names\n\n\t* src/tree-const.h (tree_constant::all_va_args): New enum.\n\t(tree_constant (tree_constant::all_va_args t)): New constructor.\n\t(is_all_va_args): New function.\n\t(is_empty, is_zero_by_zero, make_numeric_or_magic,\n\tmake_numeric_or_range_or_magic): Handle\tall_va_args type.\n\t* src/tc-rep.h (constant_type::all_va_args): New enum element.\n\t(is_all_va_args): New function.\n\t* src/tc-rep.cc (TC_REP::tree_constant_rep (TC_REP::constant_type),\n\tTC_REP::print_code): Handle all_va_args.\n\t* src/tree-misc.cc (tree_argument_list::convert_to_const_vector):\n\tHandle all_va_args.\n\t* src/tree-expr.cc (tree_index_expression::eval): After call to\n\ttree_argument_list::convert_to_const_vector (), check error_state.\n\t(tree_simple_assignment_expression::eval): Likewise.\n\t(tree_function::octave_all_va_args): New function.\n\t* src/parse.y (ALL_VA_ARGS): New token.\n\t(arg_list): Handle ALL_VA_ARGS.\n\t* src/lex.l (is_keyword): Handle all_va_args.\n\n\t* src/tree-expr.cc (tree_identifier::bump_value): Check read-only\n\tstatus of sym before altering value.\n\t(tree_prefix_expression::eval): Check error_state after call to\n\ttree_identifier::bump_value ().\n\n\t* src/variables.cc (bind_nargin_and_nargout): Don't make nargin\n\tand nargout read only.\n\n\t* scripts/strings: New subdirectory for string functions.\n\t* scripts/Makefile.in (SUBDIRS): Add strings.\n\t* scripts/strings/strcat.m: New function.\n\nFri Nov 11 14:17:31 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/load-save.cc (extract_keyword): Allow trailing blanks on the\n\tinput line.\n\nThu Nov 10 09:53:35 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/general/reshape.m, scripts/image/ind2gray.m,\n\tscripts/image/ind2gray.m, scripts/image/ind2rgb.m,\n\tscripts/image/rgb2ind.m: unwind_protect do_fortran_indexing.\n\t* scripts/general/strcmp.m: unwind_protect implicit_str_to_num_ok.\n\t* scripts/miscellaneous/menu.m: unwind_protect page_screen_output.\n\n\t* src/parse.y (UNWIND_PROTECT, UNWIND_PROTECT_CLEANUP): New tokens.\n\t(command): Handle unwind-protect.\n\t* src/lex.l (is_keyword): Handle unwind_protect,\n\tunwind_protect_cleanup, and end_unwind_protect.\n\t* src/tree-cmd.cc (tree_unwind_protect_command): New class, to\n\thandle unwind-protect.\n\n\t* src/token.h (end_tok_type): New field, end_unwind_protect.\n\n\t* src/error.cc (verror): Flush pending output to pager here.\n\t(error): Not here.\n\n\t* src/tc-rep.cc (force_numeric): Don't jump to top level on error.\n\t* src/tc-rep.cc, src/tc-rep-ass.cc, src/tc-rep-idx.cc: Check\n\terror_state after calls to make_numeric* functions.\n\n\t* src/f-lpsolve.cc: Define Flp_solve and Flp_solve_options, not\n\tFlpsolve or Flpsolve_options.\n\n\t* src/utils.cc (Ffile_in_path): Define Ffile_in_path, not\n\tFfile_in_pat.\n\n\t* src/f-inv.cc: Add DEFUN for inverse.\n\nWed Nov  9 09:30:15 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/load-save.cc (read_mat_file_header): Check for mopt < 0 too.\n\tDon't fail if reading mopt fails.\n\t(save_mat_binary_data): Handle range data as a special case.\n\t(get_default_save_format): Also accept `mat-binary' and\n\t`mat_binary'.\n\t(Fsave): Add ios::trunc to flags for opening output file.\n\n\t* src/parse.y (func_def2): Stash function name before stashing\n\tfile name.\n\n\t* src/utils.cc (fcn_file_in_path): Don't append `.m' if the name\n\talready ends in `.m'.\n\t(oct_file_in_path): Likewise, for `.oct'.\n\n\t* src/error.cc (usage): Set error state to -1, so we get traceback\n\tinformation after a call to usage.\n\n\t* src/tree-expr.cc (stash_fcn_file_name): Store full name of the\n\tfile.\n\n\t* scripts/*/*.m: Change messages to say `invalid' instead of\n\t`illegal', since no laws are being broken by using these functions\n\tincorrectly.\n\n\t* src/timefns.cc (Fcputime): New function.\n\t* configure.in: Check for getrusage.\n\n\t* src/scripts/miscellaneous/tic.m: New function.\n\t* src/scripts/miscellaneous/toc.m: New function.\n\t* src/scripts/miscellaneous/etime.m: New function.\n\t* src/scripts/miscellaneous/is_leap_year.m: New function.\n\n\t* src/error.cc (Fwarning, Fusage): New functions.\n\t* scripts/*/*.m: Use them instead of printing warning and usage\n\tmessages directly with disp, printf, or fprintf.\n\n\t* src/file-io.cc (close_files): Check Pix before using.\n\t(file_count): Delete unnecessary variable.  Instead, use\n\tDLList::length to get the number of files in the list.\n\n\t* src/sighandlers.cc (install_signal_handlers): Explicitly ignore\n\tSIGPOLL and SIGIO.\n\nTue Nov  8 15:26:50 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/general/logspace.m: Lose fractional part of third arg.\n\tDon't round, for compatibility with Matlab.\n\t* scripts/general/linspace.m: Likewise.\n\n\t* liboctave/CMatrix.cc (row_min, row_max, row_min_loc, row_max_loc):\n\tHandle case of row containing only real elements.\n\t(column_min, column_max, column_min_loc, column_max_loc):\n\tLikewise, for columnwise operations.\n\t* src/f-minmax.cc (two-complex-arg min, max): Handle case of both\n\tcolumns containing only real elements.\n\n\t* src/variables.cc (Fclear): Pass 0 to symbol_table::list() for\n\tpats and npats.\n\nMon Nov  7 20:22:36 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* liboctave/dColVector.cc (operator +=): Don't return reference to\n\ttemporary.\n\t(operator -=): Likewise.\n\t* liboctave/CMatrix.cc (operator +=, operator -=): Likewise.\n\nSun Nov  6 23:15:24 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* octMakefile.in (DISTSUBDIRS): Don't use $(SUBDIRS) here.\n\n\t* src/load-save.cc (Fsave): Open output file with mode ==\n\tios::out, not ios::in.\n\nSat Nov  5 18:18:11 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in (HAVE_SYS_SIGLIST): Check for sys_siglist variable,\n\teven if it isn't declared in a system header.\n\t* acconfig.h (HAVE_SYS_SIGLIST): Add #undef.\n\t* src/sighandlers.cc (sys_siglist): Define our own if\n\tHAVE_SYS_SIGLIST is not defined, not if SYS_SIGLIST_DECLARED is\n\tnot defined.\n\n\t* src/tree-plot.cc (Fclearplot): New function.\n\t(clg): Alias for clearplot.\n\n\t* src/parse.y (CLEAR): New token.\n\t(statement): Handle PLOT CLEAR as a special case.\n\t* src/lex.l (is_plot_keyword): Handle CLEAR here too.\n\nFri Nov  4 08:44:57 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* All: Remove remaining #pragma interface/implementation statements.\n\n\t* src/tree-plot.cc (subplot): Move actual code here from .h file.\n\n\t* src/tree-expr.cc (tree_expression): Declare destructor virtual.\n\tDelete unnecessary destructors.\n\n\t* src/SLStack.h, src/SLStack.cc (operator =): Return reference to\n\tSLStack, not void.\n\n\t* src/f-qzval.cc (Fqzval): Rename from Fqzvalue.  Change Help\n\tand usage messages too.\n\n\t* scripts/plot/plot_int.m: Really figure out if there are any\n\timaginary parts.\n\n\t* scripts/control/are.m: Fix typo.\n\nThu Nov  3 18:44:11 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/load-save.cc (save_ascii_data): Handle new arg,\n\tstrip_nan_and_inf.  Change callers.\n\t(strip_infnan): New functions.\n\t(save_three_d): Strip inf and nan values here too.\n\n\t* src/tree-plot.h (subplot_using): New data have_values and val.\n\t* src/tree-plot.cc (subplot_using::eval, subplot_using::values):\n\tNew functions.\n\t(subplot_style::errorbars): New function.\n\t(subplot::extract_plot_data, subplot::handle_plot_data): New functions.\n\t(subplot::print): Improve handling of data.\n\nWed Nov  2 08:11:08 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/file-io.cc (do_scanf): If reading from stdin, flush stdout\n\tfirst.\n\n\t* configure.in: Leave some comments in the configure file.\n\tImprove checking for termios.h, termio.h, and sgtty.h.\n\n\t* src/variables.cc (install_builtin_variables): DEFVAR realmax and\n\trealmin here.\n\t* src/sysdep.cc: Instead of DEFUNing them here.\n\n\t* src/variables.cc (do_who): Accept globbing patterns as args.\n\t(maybe_list): Handle them here.\n\n\t* src/symtab.cc (matches_patterns): New function.\n\t(symbol_table::list, symbol_table::long_list): Accept list of\n\tpatterns, and use matches_patterns to see if the given string is a\n\tmatch.  Change all callers.\n\n\t* src/load-save.cc (read_binary_data): Don't fail if reading\n\tname_len fails.\n\t(do_load): Quit quietly if nothing is left to read.  Clean up doc\n\tand name in all cases.\n\nTue Nov  1 16:34:20 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/lex.l (\")\"): Set cant_be_identifier to 1 here too.\n\n\t* src/tree-plot.cc: Use abbreviations for gnpulot plot, splot,\n\treplot, with, using, and title commands.\n\nMon Oct 31 14:26:12 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/variables.cc (Fclear): Look in global symbol table for\n\tuser-defined function names.\n\n\t* src/load-save.cc (do_load): New function.\n\t(Fload): Use it to avoid assigning streams.\n\t(write_binary_header): New function.\n\t(save_vars): New function.\n\t(Fsave): Use it to avoid assigning streams.\n\n\t* libcruft/linpack/zgesl.f (zgesl): Comment out unused varialbes\n\tand statement functions.\n\n\t* src/sysdep.cc (Fisieee): New function.\n\t(Frealmax, Frealmin): Ditto.\n\n\t* scripts/miscellaneous/version.m: New file.\n\nFri Oct 28 14:52:08 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* octMakefile.in (distclean): Also delete config.cache and\n\tconfig.log.\n\n\t* Makeconf.in (CPPFLAGS): Allow substitution.\n\n\t* configure.in: Use AC_PREFIX_DEFAULT.\n\n\t* configure.in: Use AC_CANONICAL_HOST instead of doing this\n\tourselves.\n\n\t* install-sh: Rename from install.sh.\n\t* octMakefile.in (DISTFILES): Distribute install-sh, not install.sh.\n\nMon Oct 24 10:04:27 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* octave-bug.in: Print message if bug report appears to have been\n\tmailed successfully.  Otherwise, exit with error status.\n\nFri Oct 21 14:05:10 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tc-rep-ass.cc (TC_REP::do_vector_assign (rhs, idx-vector)):\n\tHandle all four cases of row/colum mixing.  Report an error if the\n\tRHS is a matrix.\n\n\t* src/tc-rep-idx.cc (TC_REP::do_index): Don't barf on indexing an\n\tempty matrix with colon(s).\n\t(TC_REP::do_scalar_index): Create index vector with  z_len = 1.\n\t(TC_REP::do_matrix_index (Range, tree_constant)): Correctly handle\n\tcase of colon as second arg.\n\n\t* octave-bug.in: Put mail commands in subshells so error message\n\treally do go away.\n\nThu Oct 20 11:05:36 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* octave-bug.in: If passing $SUBJECT on the command line to a\n\tmailer, quote it.  Don't assume /bin/mail takes any args other\n\tthan a recipient address.  Do the right thing if the To: line\n\tchanges.\n\n\t* src/tc-rep.cc (TC_REP::rows, TC_REP::columns): Return -1 for\n\tanything that doesn't really have rows or columns.\n\n\t* src/tc-rep-idx.cc (fortran_style_matrix_index): Check max and\n\tmin index values.\n\n\t* Makefile.in (FORCE): New phony target.  Used instead of .PHONY\n\tto be portable.\n\n\t* octave-bug.in: Try harder to mail the message.\n\n\t* src/dynamic-ld.cc: Undefine true, false, and boolean after\n\tincluding kpathse/pathsearch.h.\n\n\t* src/sysdep.cc: Include <float.h>.\n\nWed Oct 19 10:28:49 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in (CXXLIB_LIST, FLIB_LIST, CXXLIB_PATH, FLIB_PATH):\n\tBe careful not to match -l or -L in the middle of a word.\n\n\t* src/f-minmax.cc: Correctly handle mixed scalar/matrix args.\n\n\t* octMakefile.in: Rename from Makefile.in.\n\t* Makefile.in: New file.  For `all' target, print message and\n\texecute make again using octMakefile.  For other targets, just\n\texecute make again using octMakefile.\n\n\t* configure.in: Check for sys_siglist.\n\t* src/sighandlers.h [! HAVE_SYS_SIGLIST]: Provide an external\n\tdeclaration.\n\t* src/sighandlers.cc (generic_sig_handler): New function, replaces\n\tmost individual signal handler functions.\n\t(sigint_handler, sigpipe_handler): Restore signal handler before\n\tdoing anything else.\n\t[! HAVE_SYS_SIGLIST] (sys_siglist): Provide our own definition.\n\n\t* config.guess: Update from FSF sources.\n\nTue Oct 18 23:36:24 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* flibs.sh: Don't pass -Y P,path.  Instead, turn it into a series\n\tof -L dir args.\n\n\t* configure.in: Update for autoconf 2.0.\n\tDelete support for --enable-run-in-place (it is too hard to make\n\tthis work reliably...).\n\nMon Oct 17 11:40:49 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/user-prefs.cc (init_user_prefs): Declare to return void,\n\tnot int.\n\n\t* configure.in: Change quote characters around tr command.  Some\n\tsystems actually do need the []'s for ranges...\n\nSun Oct 16 12:22:14 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tempname.c, src/tmpnam.c: New files.\n\t* src/Makefile.in (SOURCES): Add them.\n\t* src/dirfns.cc: Delete functions extracted from glibc.\n\n\t* configure.in (localfcnfiledir, localoctfiledir, imagedir):\n\tNew variables.  Use them to define localfcnfilepath,\n\tlocaloctfilepath, and imagepath.\n\t* Makeconf.in: Substitute them here.\n\n\t* src/utils.cc (get_fcn_file_names) [WITH_DLD]: Also match .oct\n\tfiles.\n\n\t* dld/find_exec.c (dld_find_executable): Don't be fooled by\n\tdirectories or other special files in PATH.\n\t(ABSOLUTE_FILENAME_P): Also return true if the name includes a\n\t`/'.  This isn't necessarily an absolute path, but we will turn it\n\tinto one later.\n\t* src/dynamic-ld.cc (octave_dld_init): Call make_absolute() on\n\tvalue returned from dld_find_executable().\n\nSat Oct 15 08:35:13 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* flibs.sh: Undo previous change.  Only substitute spaces for\n\tcommas if it looks like we have output from xlf.  Handle -Y and\n\tLD_RUN_PATH using gcc's -Xlinker option.\n\n\t* Makefile.in (snapshot-version): Use move-if-change for version.h.\n\nFri Oct 14 09:18:08 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/image/Makefile.in (SOURCES): Don't forget octtopnm.c.\n\n\t* Makefile.in (BINDISTFILES): Distribute octave-bug too.\n\n\t* configure.in (imagepath): Install at same level as fcnfiledir,\n\tnot below it.\n\n\t* doinstall.sh: Correctly extract version numbers that are not all\n\tdigits.  Also install images too.  Also install octaverc.  Ask\n\toctave for the target host type.  Also create site/m and\n\tsite/oct directories.  Also install octave-bug.\n\n\t* scripts/image/Makefile.in (DISTFILES): Distribute demo image\n\tfiles too.\n\n\t* doinstall.sh: Update for new directory organization.\n\n\t* src/variables.cc (subst_octave_home): Make it work for multiple\n\tsubstitutions.\n\n\t* flibs.sh: Handle -Y P,path:of:lib:dirs output from f77 on Solaris.\n\n\t* src/strfns.cc (Ftoascii): New file, new function.\n\t(Fisstr, Fsetstr): Move here, fromd ata.cc.\n\n\t* src/Makefile.in (SOURCES): Include it.\n\nThu Oct 13 11:58:03 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/signal/filter.m: Postpad `b' before reshaping.\n\n\t* mkinstalldirs: New file.\n\t* Makefile.in: Distribute it, don't make mkpath.\n\t* All Makefile.in files: Use it instead of mkpath.\n\n\t* src/utils.cc (Foctave_tmp_file): New function.\n\n\t* src/utils.cc (undo_string_escape): Move here from tc-rep.cc,\n\trename from undo_string_escapes, and make extern.\n\t(undo_string_escapes): New function, for undoing a whole string.\n\t(Fundo_string_escapes): New function.\n\n\t* scripts/miscellaneous/dump_prefs.m,\n\tscripts/miscellaneous/dump_1_pref.m: New functions.\n\t* scripts/miscellaneous/bug_report.m: Record user preferences in a\n\tfile and pass the name of the file to octave-bug.  Use\n\toctave_tmp_file to generate tmp file name.\n\t* octave-bug.in: Accept a final file-name arg as a file that\n\tcontains a list of user-preferences.\n\nWed Oct 12 09:09:37 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: Redefine archlibdir and octfiledir so that oct\n\tand exec directories are at the same level as the m directory.\n\tRedefine localoctfilepath so that site/oct is a the same level as\n\tsite/m.\n\n\t* Makeconf.in (F77): Substitute it.\n\t(BUG_CFLAGS, BUG_CXXFLAGS): New vars.\n\t* configure.in:\n\t* scripts/bug_report.m: New file.\n\t* octave-bug.in: New file.\n\t* Makefile.in (DISTFILES): Distribute octave-bug.in.\n\t(dirs_to_make): Add $bindir.\n\t(all): Add octave-bug.\n\t(octave-bug): New target.\n\t(install): Install it.\n\t* src/defaults.h.in: Add defines for bindir.\n\t* src/Makefile.in (defaults.h): Substitute it.\n\t* src/variables.cc (octave_bin_dir): New function.\n\t* src/octave.cc (initialize_globals): Also add $bindir to path.\n\n\t* configure.in: Check for gettimeofday. Add AC_TIME_WITH_SYS_TIME.\n\t* src/systime.h: New file.\n\t* src/timefns.h: Use gettimeofday if available.\n\t* src/Makefile.in (INCLUDES): Add systime.h.\n\nMon Oct 10 14:34:56 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/octave.cc (verbose_flag): New global variable.\n\t(long_opts): Add \"verbose\".\n\t(usage_string): Update.\n\t(main): Set verbose_flag if given --verbose.\n\t(execute_startup_files): Don't print messages about reading\n\tstartup files if verbose_flag is not set.\n\n\t* src/tree-expr.cc (apply_mapper_fcn): Handle scalars as a special\n\tcase, but then just try to convert other arg types to a matrix.\n\n\t* src/f-det.cc (Fdet): Check if arg is complex type, but not\n\tnecessarily a complex matrix.\n\t* src/f-schur.cc (Fschur): Likewise, and also for real types.\n\t* src/f-lu.cc (Flu): Likewise.\n\t* src/f-minmax.cc (Fmin, Fmax): Likewise.\n\nSun Oct  9 21:04:17 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tc-rep-ass.cc (TC_REP::assign): If LHS is undefined, don't\n\ttry to force it to be a numeric type.\n\nFri Oct  7 09:05:10 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: Define LD_STATIC_FLAG for Alpha OSF/1 1.3 systems.\n\n\t* src/tc-rep-idx.cc (TC_REP::do_index): Only work for numeric\n\ttypes, but don't panic if conversion doesn't work.\n\t* src/tc-rep-ass.cc (TC_REP::assign): Likewise.\n\n\t* src/tc-rep.cc (TC_REP::gripe_wrong_type_arg): New function.\n\n\t* src/gripes.cc (gripe_wrong_type_arg): Define here.\n\t* src/tree-const.cc: Not here.\n\nWed Oct  5 16:24:38 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/file-io.cc (do_scanf): Don't panic if string is NULL.\n\n\t* src/gripes.cc (gripe_unrecognized_float_fmt): New function.\n\t(gripe_2_or_3_dim_plot): Ditto.\n\t(gripe_unrecognized_data_fmt): Ditto.\n\t(gripe_data_conversion): Ditto.  Use it in load-save.cc data\n\tconversion routines that aren't implemented yet.\n\n\t* src/load-save.cc (do_double_format_conversion): Don't panic on\n\tunrecognized floating point formats.\n\t(do_float_format_conversion): Likewise.\n\t(write_doubles): Don't panic if data format is unrecognized.\n\t(do_save): Likewise\n\t(install_loaded_variable): Don't panic for unknown symbol types.\n\t(read_binary_data): Also check error_state after calls to read_doubles.\n\n\t* src/symtab.cc (symbol_table::rename): Don't panic if symbol\n\tcan't be renamed.\n\t* src/parse.y (return_list): Abort parse if renaming results in an\n\terror.\n\n\t* src/tree-misc.cc (tree_if_command::eval): Don't panic if all\n\t(all (cond)) is not a scalar.\n\n\t* src/tree-expr.cc (tree_unary_expression::print_code): Don't\n\tpanic if expression type is unknown.\n\n\t* src/tree-plot.cc (tree_plot_command::eval): Don't panic if plot\n\tis not 2 or 3 dimensional.\n\t(tree_plot_command::print_code, subplot::print, save_in_tmp_file):\n\tLikewise.\n\n\t* src/variables.cc (alias_builtin): Panic with better message.\n\t(subst_octave_home): Don't panic if OCTAVE_HOME doesn't contain\n\tOCTAVE_PREFIX.\n\n\t* src/tc-inlines.h (REP_RHS_MATRIX): Use panic_impossible()\n\tinstead of abort().\n\t(REP_ELEM_ASSIGN, CRMATRIX): Likewise.\n\n\t* src/data.cc (Fdiag, make_diag): Do work here.\n\t* src/tc-rep.cc (TC_REP::diag, make_diag): Not here.\n\t* src/tc-rep.h (TC_REP::diag): Delete.\n\t* src/tree-const.h (tree_constant::diag): Delete.\n\nTue Oct  4 08:35:37 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/f-fft.cc (Ffft): Correctly set n_points for row vectors if\n\tnargin == 1.\n\t* src/f-ifft.cc (Fifft): Likewise.\n\n\t* src/load-save.cc (Fsave): Declare file and stream static.\n\nMon Oct  3 10:40:50 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tree-expr.cc (octave_va_arg): Correct arg count and index to\n\tmatch recent change to arg passing/nargin.\n\t(define_param_list): Always set num_named_args = param_list->length ().\n\n\t* readline/Makefile.in (install): Don't install libreadline.a by\n\tdefault.\n\t(uninstall): Now no need to delete it.\n\n\t* configure.in (localfcnfilepath, localoctfilepath): Change to\n\tmatch organization of system fcn and oct files, and enable\n\trecursive searching in both.  Enable recursive searching in\n\t$(octfiledir).\n\t(includedir): Change to $(prefix)/include/octave.\n\nSun Oct  2 10:14:18 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: For now, disable IEEE floating point functions on\n\tthe Alpha.  This is braindead, but at least prevents divide by\n\tzero crashes...\n\n\t* src/file-io.cc (fseek_internal): Use values for origin that\n\tmatch what we use to define SEEK_SET, SEEK_CUR, and SEEK_END in\n\tvariables.cc.\n\n\t* dld: Merge various changes for Linux from dld 3.2.4 that is\n\tbeing distributed with jacal.\n\n\t* src/file-io.cc (fwrite_internal): Correct indexing of args.\n\n\t* src/tree-expr.cc (apply_mapper_fcn): New function.\n\t(tree_builtin::eval): Use it instead of tree_constant::mapper().\n\t* src/tree-const.h (tree_constant::mapper): Delete.\n\t* src/tc-rep.cc, src/tc-rep.h (TC_REP::mapper): Delete.\n\n\t* src/data.cc (Fcumprod, Fcumsum, Fprod, Fsum, Fsumsq): Do work here.\n\t* src/tc-rep.cc (TC_REP::cumprod, TC_REP::cumsum, TC_REP::prod,\n\tTC_REP::sum, TC_REP::sumsq): Not here.  Delete.\n\t* src/tc-rep.h (TC_REP::cumprod, TC_REP::cumsum, TC_REP::prod,\n\tTC_REP::sum, TC_REP::sumsq): Delete\n\t* src/tree-const.h (tree_constant::cumprod, tree_constant::cumsum,\n\ttree_constant::prod, tree_constant::sum, tree_constant::sumsq):\n\tDelete.\n\n\t* tree-const.h: Don't check gcc minor version number.\n\t* tc-rep.h: Likewise.\n\n\t* src/file-io.h (class file_info): Declare here.\n\t* src/file-io.cc: Not here.\n\n\t* configure.in (LIBOCTDLD, LIBDLD): Remove ../ prefix.\n\t* Makefile.in (distclean, realclean): Don't remove *.a.\n\t* src/Makefile.in (OCTAVE_LIBS): Correct directory spec for libs.\n\tBuild, install, and clean liboctdld.a, not ../liboctdld.a.\n\t* dld/Makefile.in: Build, install, and clean libdld.a, not ../libdld.a.\n\t* info/Makefile.in: Likewise, for libinfo.a.\n\t* kpathsea/Makefile.in: Likewise, for libkpathsea.a.\n\t* libcruft/Makefile.in: Likewise, for libcruft.a.\n\t* liboctave/Makefile.in: Likewise, for liboctave.a.\n\t* readline/Makefile.in: Likewise, for libreadline.a.\n\n\t* configure.in (gxx_version): Require 2.6.x or later.  Don't\n\tdefine EXTERNAL_TEMPLATES.  Do define NO_IMPLICIT_TEMPLATES.\n\t* liboctave/Array-C.cc, liboctave/Array-d.cc, src/Array-tc.cc,\n\tsrc/DLList-fi.cc src/SLStack-tok.cc, src/SLStack-ue.cc,\n\tsrc/SLStack-tm.cc, src/SLStack-pc.cc, src/SLStack-i.cc,\n\tsrc/SLList-tc.cc, src/SLStack-sym.cc, src/SLStack-ui.cc,\n\tsrc/SLList-misc.cc, src/SLList-expr.cc, src/SLList-plot.cc,\n\tsrc/Map-tc.cc: New files.  Instantiate templates here.\n\t* libocave/Array.cc, src/Map.cc, src/Stack.cc, src/SLStack.cc:\n\tNot here.  Remove #pragma implementation hack.\n\t* liboctave/Array.h, src/Stack.h, src/Map.h, src/SLStack.h: Remove\n\t#pragma interface hack.\n\t* Makeconf.in: Substitute NO_IMPLICIT_TEMPLATES, not\n\tEXTERNAL_TEMPLATES.\n\t(ALL_CXX_FLAGS, UGLY_ALL_CXX_FLAGS): Use $(NO_IMPLICIT_TEMPLATES),\n\tnot $(EXTERNAL_TEMPLATES).\n\t* acconfig.h: Remove USE_EXTERNAL_TEMPLATES #undef.\n\t* src/Makefile.in (XALL_CXX_FLAGS): Delete -fno-implicit-templates.\n\t(TI_SRC, TI_OBJ): New variables.\n\t(libtinst.a): New target.\n\t* liboctave/Makefile.in (TI_SRC): New variable.\n\t(SOURCES): Add it to list.\n\nFri Sep 30 09:52:15 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/Makefile.in: Automatically generate more lists.\n\tUse := in more places.\n\t* src/Array-C.cc src/Array-d.cc src/Array-tc.cc src/Map-tc.cc\n\tsrc/Stack-i.cc src/SLStack-pc.cc src/SLStack-sym.cc\n\tsrc/SLStack-tok.cc src/SLStack-tm.cc src/SLStack-ue.cc:\n\tNew template instantiation files.\n\t* configure.in: If using gcc 2.6.x or later, use\n\t-fno-implicit-templates instead of -fexternal-templates.\n\n\t* src/tc-inlines.h: Rename from tc-inlines.cc.\n\n\t* src/parse.y (looking_at_indirect_ref): New global flag, for\n\tparser feedback.\n\t(tree_indirect_ref_type): New token type.\n\t(TEXT_ID): New token.\n\t(indirect_ref): New non-terminal.\n\t(make_index_expression): New function.\n\t(variable): Use it to build variable from indirect_ref, not just\n\tidentifier.\n\n\t* src/lex.l (handle_identifier): Handle identifiers differently if\n\tlooking at an indirect reference.  Add `.' to list of other ops.\n\n\t* src/tree-expr.cc (tree_identifier::do_lookup): Handle new\n\texec_script arg.\n\t(tree_identifier::assign): New functions for assignment to a\n\tstrucutre element.\n\t(print_constant): New function.\n\t(tree_identifier::eval, tree_indirect_ref::eval): Use it.\n\t(\n\n\t* src/tree-expr.h (tree_indirect_ref): New class for handling\n\tstructure references.\n\t(tree_expression::is_indirect_ref): New virtual function.\n\t(tree_fvc::lookup_map_element): New virtual function.\n\t(tree_index_expression, tree_simple_assignment_expression):\n\tAdd new constructors for handling indirect references.\n\n\t* src/oct-map.h: New file, for class managing Octave's\n\tstructure/map type.\n\n\t* src/tree-misc.cc (tree_global::eval): Don't allow individual\n\tstructure elements to be tagged global.\n\n\t* src/tc-rep.h (tree_constant_rep): Add new field, a_map, and a\n\tnew type_tag, map_constant.\n\t* src/tree-const.cc (tree_constant::is_map): New function.\n\t* src/tree-const.cc (tree_constant::map_value,\n\ttree_constant::assign_map_element, tree_constant::make_unique,\n\ttree_constant::lookup_map_element,\n\ttree_constant::make_unique_map_element): New functions.\n\n\t* src/Map.h (CHNode::CHNode): Copy key.\n\t(CHNode::~CHNode): Delete it.\n\t(CHMap::contents): Don't declare return value const.\n\n\t* src/tc-inlines.cc: Move some macros here from tc-rep.cc so they\n\tcan appear in one place and be shared by tc-rep-idx.cc,\n\ttc-rep-ass.cc, and tc-pre.cc.\n\n\t* src/tc-rep-idx.cc, src/tc-rep-ass.cc: New files, extracted from\n\ttc-rep.cc to make compilation of tc-rep stuff faster and require\n\tless memory.\n\n\t* src/variables.cc (Fwhos): Correctly insert \"-long\" into arg list\n\tfor Fwho.\n\nMon Sep 26 12:59:55 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* test/Makefile.in (OCTAVE_SCRIPT_PATH): Append `//' for recursive\n\tsearching.\n\nFri Sep 23 07:53:13 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/plot/bar.m: Don't return values if nargout == 0.\n\t* scripts/plot/hist.m: Likewise.\n\t* scripts/plot/stairs.m: Likewise.\n\n\t* src/tree-plot.cc (Fishold): New function.\n\t(plot_line_count, parametric_plot, clear_before_plotting):\n\tDeclare static.\n\n\t* src/f-fft.cc (Ffft): Handle row vector as a special case.\n\t* src/f-ifft.cc (Fifft): Ditto.\n\nThu Sep 22 13:20:53 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/help.cc (print_symbol_type): New function, extracted from Fwhich.\n\t(Fwhich): Use it.\n\t(Fhelp): Use it to print type info before help message.\n\n\t* src/dynamic-ld.cc: Hide all DLD-specific functions behind\n\t#ifdef WITH_DLD.\n\n\t* scripts/startup: New directory.\n\t* scripts/startup/Makefile.in: New file.\n\t* scripts/startup/octaverc: New file.  Don't overwrite existing\n\tfile when nstalling.\n\t* configure.in: Generate Makefile in scripts/startup.\n\t* scripts/Makefile.in (SUBDIRS): Add startup.\n\t* src/defaults.h.in (OCTAVE_STARTUPFILEDIR): New macro.\n\t* src/variables.cc (get_site_defaults): Look for octaverc in\n\tOCTAVE_STARTUPFILEDIR.\n\n\t* configure.in (fcnfiledir): Make it end in `//'.\n\n\t* src/error.cc (Ferror): Correct indexing error.\n\n\t* src/Map.h, src/Map.cc: New files implementing associative arrays.\n\t* src/Makefile.in: Include them in the list of files to distribute\n\tand compile.\n\nWed Sep 21 09:50:19 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makefile.in (DISTSUBDIRS): Add dld to the list.\n\n\t* scripts/plot/hist.m: New function file.\n\n\t* src/tc-rep.cc (TC_REP::do_matrix_index (tree_constant,\n\ttree_constant): For case of scalar as first arg, move call to\n\tindex check to the TC_REP::do_matrix_index (int, tree_constant)\n\tfunction.\n\t(TC_REP::do_matrix_index (int, tree_constant): Be compatible with\n\tMatlab for indexing of the form row_vector (0, :).\n\t(TC_REP::do_matrix_index (tree_constant, int): Likewise, for\n\tindexing of the form col_vector (:, 0).\n\t(TC_REP::do_matrix_assignment): Similar changes for assignment.\n\nTue Sep 20 17:48:39 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/parse.y (return_list, return_list1): New nonterminals.\n\tRename from func_def1a.  Handle variable number of return values.\n\t* src/tree-expr.h (tree_function::vr_list): New field.\n\t* src/tree-expr.cc (delete_vr_list): New function.\n\t(tree_function::octave_vr_val, tree_function::takes_var_return):\n\tNew functions, for variable return lists.\n\t(tree_function::define_ret_list, tree_function::eval): Handle vr_list.\n\t(Fvr_val): New function.\n\t* src/tree-misc.h (tree_va_return_list): New list class.\n\t* src/tree-misc.cc (tree_parameter_list::convert_to_const_vector):\n\tTake pointer to tree_va_return_list as arg, and append the values\n\tfound there.\n\n\t* src/arith-ops.cc (mx_stupid_bool_op): Correctly handle empty\n\tmatrices for == and != ops.\n\n\t* src/variables.cc (Fis_global): Check args(0), not args(1).\n\t(Fexist): Likewise.\n\t(install_builtin_mapper): Set nargin_max to 1, not 2.\n\n\t* src/dynamic-ld.cc (octave_dld_init): Make raw program name\n\tabsolute before calling dld_find_executable.\n\n\t* src/octave.cc (initialize_error_handlers): New function.\n\t(main): Call init_user_prefs and initialize_error_handlers.\n\tRearrange order of calls to initialization functions.\n\n\t* src/user-prefs.cc (init_user_prefs): New function.\n\n\t* src/data.cc (map): Correct condition for assert ().  Correct\n\thandling of empty args.\n\n\t* src/f-lsode.cc src/f-dassl.cc src/f-quad.cc src/f-npsol.cc\n\tsrc/f-fsolve.cc: Pass correct number of args to\n\ttakes_correct_nargs ().\n\t* src/variables.cc (takes_correct_nargs): Use %s, not %c in format\n\tstring.\n\n\t* src/f-ifft2.cc src/f-expm.cc src/f-det.cc src/f-svd.cc\n\tsrc/f-syl.cc src/f-schur.cc src/f-qzval.cc src/f-qr.cc\n\tsrc/f-pinv.cc src/f-lu.cc src/f-log.cc src/f-inv.cc src/f-hess.cc\n\tsrc/f-eig.cc src/f-chol.cc src/f-balance.cc src/f-lsode.cc\n\tsrc/f-dassl.cc src/f-quad.cc src/f-npsol.cc src/f-fsolve.cc:\n\tCorrectly handle return value from empty_arg ().\n\t* src/utils.cc (empty_arg): Clarify usage, correct return value if\n\targ is empty but no message is printed.\n\n\t* src/Makefile.in (dist): Delete builtins.cc too.\n\n\t* configure.in (DYNAMIC_LD_OBJ): Delete.\n\t* src/Makefile.in (OBJECTS): Don't substitute DYNAMIC_LD_OBJ.\n\tAlways include dynamic-ld.o.\n\n\t* configure.in: Generate Makefile in scripts/elfun and\n\tscripts/specfun.\n\n\t* Makeconf.in (version): Use `:=' and `$(shell )', not just `='\n\tand backticks, so we only extract the version number once.\n\nMon Sep 19 09:04:30 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/tc-rep.h (represent_strings_with_doubles): New field in\n\ttree_constant_rep class.\n\n\t* tree-misc.cc (tree_argument_list::convert_to_const_vector):\n\tDon't allocate extra arg for function name.\n\t* sysdep.cc, pr-output.cc, input.cc, file-io.cc, error.cc,\n\ttc-rep.cc, tree-expr.cc, f-svd.cc, f-sort.cc, f-schur.cc,\n\tf-rand.cc, f-qzval.cc, f-quad.cc, f-qr.cc, f-qpsol.cc, f-pinv.cc,\n\tf-npsol.cc, f-minmax.cc, f-lu.cc, f-lsode.cc, f-log.cc, f-inv.cc,\n\tf-ifft2.cc, f-ifft.cc, f-hess.cc, f-givens.cc, f-fsolve.cc,\n\tf-fft2.cc, f-fft.cc, f-expm.cc, f-eig.cc, f-det.cc, f-dassl.cc,\n\tf-colloc.cc, f-chol.cc, f-balance.cc, f-syl.cc, variables.cc,\n\ttree-misc.cc, data.cc, octave.cc, utils.cc, defun-int.h:\n\tChange meaning and usage of nargin and args.length() to cope with\n\tabove change.  This makes nargin mean the same thing in built-in\n\tfunctions as it does in M-files.\n\nSat Sep 17 09:29:08 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* scripts/general/nargchk.m: New function.\n\nFri Sep 16 08:48:13 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makeconf.in (FLIB_LIST, FLIB_PATH, CXXLIBS, CXXLIB_LIST,\n\tCXXLIB_PATH): Set these.\n\n\t* cxxlibs.sh: New file.\n\t* configure.in: Use it to determine extra C++ libraries to link\n\tto.  Use sed magic to extract list of libraries and directories\n\tfrom FLIBS and CXXLIBS.\n\t* Makefile.in: (DISTFILES): Include cxxlibs.sh.\n\n\t* configure.in: Change AC_VERBOSE messages to match\n\tautoconf-generated messages.\n\n\t* src/dynamic-ld.cc (dld_octave_resolve_reference): Search library\n\tpath for list of files to link.\n\n\t* src/utils.cc (pathstring_to_vector): Un-#if 0 it.\n\n\t* Makefile.in: Install liboctdld.a if not linking to it.\n\t(defaults.h): Substitute FLIB_LIST, FLIB_PATH, CXXLIB_LIST,\n\tCXXLIB_PATH.\n\nThu Sep 15 09:31:29 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makeconf.in (LD_STATIC_FLAG): Actually substitute LD_STATIC_FLAG.\n\t(ALL_LDFLAGS): Include it here.\n\n\t* configure.in: Check for signgam declaration in math.h\n\t* acconfig.h: Add #undef for SIGNGAM_DECLARED.\n\t* src/mappers.h: Provide our own declaration of signgam if\n\tHAVE_LGAMMA but not SIGNGAM_DECLARED.\n\nWed Sep 14 11:28:09 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/dynamic-ld.cc (mangled_octave_builtin_name,\n\tmangle_octave_oct_file_name, load_octave_builtin,\n\tload_octave_oct_file, init_dynamic_linker): New functions.\n\t[WITH_DLD] (octave_dld_init, dld_octave_resolve_reference,\n\tdld_octave_builtin, dld_octave_oct_file): New functions to handle\n\tdetails of dynamic linking using dld.\n\n\t* src/variables.cc (load_fcn_from_file) [WITH_DLD]: Handle looking\n\tfor .oct file to link at run time.\n\n\t* src/tree-expr.cc (tree_builtin::tree_builtin): Always init my_name.\n\t(tree_builtin::eval): If no definition, try to load one using\n\tload_octave_builtin().\n\n\t* src/octave.cc (main): Initialize dynamic linking here.\n\n\t* src/defun-int.h (DEFINE_FUN_STRUCT, DEFINE_FUN_STRUCT_FUN):\n\tNew macros.\n\t* src/defun-dld.h (DEFUN_DLD_BUILTIN): Rename from DEFUN_DLD and\n\thandle case of WITH_DLD && OCTAVE_LITE && MAKE_BUITLINS.\n\t(DEFUN_DLD): Use this for external user-supplied functions that\n\tare intended to be dynamically linked.\n\n\t* configure.in: Handle --enable-lite-kernel.  Call AC_SUBST for\n\tuse_dld and lite_kernel.  Define LIBOCTDLD unless doing dynamic\n\tlinking and small kernel requested.\n\t* acconfig.h: Add #undefs for OCTAVE_LITE and SMART_PUTENV.\n\t* Makeconf.in: Define WITH_DLD from @use_dld@ and OCTAVE_LITE from\n\t@lite_kernel@.\n\n\t* src/octave.cc (Fsystem): Rename from shell_cmd.\n\t(Fshell_cmd): Define as alias to Fsystem.\n\nMon Sep 12 20:19:20 1994  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* src/mappers.cc: Include error.h and math.h.\n\nSat Sep 10 11:49:11 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Makefile.in: Clean up rules for making distributions.\n\t(DISTDIRS): Distribute kpathsea\n\nFri Sep  9 08:46:03 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/dMatrix.cc (pseudo_inverse): New function.\n\t* liboctave/CMatrix.cc (pseudo_inverse): New function.\n\t* src/f-pinv.cc: New file, for pinv().\n\t* src/Makefile.in (DLD_SRC): Add f-pinv.cc.\n\t(DLD_OBJ): Add f-pinv.o.\n\t* scripts/linear-algebra/pinv.m: Delete.\n\n\t* configure.in: Define and substitute $imagepath.\n\t* src/Makefile.in: Substitute OCTAVE_IMAGEPATH.\n\t* src/defaults.h.in: Add OCTAVE_IMAGEPATH.\n\t* src/variables.cc (install_builtin_variables): Define IMAGEPATH.\n\t* src/user-prefs.cc (image_path): New function.\n\t* Makeconf.in (imagepath): substitute it.\n\n\t* src/octave.cc (initialize_globals): Ensure that $archlibdir is\n\tin the user's PATH.\n\n\t* utils.cc (search_path_for_file, Ffile_in_path): New functions.\n\n\t* configure.in: Append `//' to $fcnfiledir, for recursive\n\tsearching.\n\t(AC_OUTPUT): Edit makefiles in script subdirectories too.\n\n\t* scripts: Regroup function files in the following directories,\n\teach with its own Makefile.in:\n\n\t   image           plot        signal          control\n\t   linear-algebra  polynomial  special-matrix  general\n\t   miscellaneous   set         statistics\n\n\t* src/help.cc (simple_help): Use kpathsea functions to find files\n\tin path.\n\t* src/utils.cc (get_fcn_file_names): Likewise.\n\t(pathstring_to_vector): #if 0 out.\n\nThu Sep  8 16:59:42 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/Makefile.in (OCTAVE_LIBS): Include ../libkpathsea.a.\n\t* configure.in: Include configure stuff for kpathsea here too.\n\t* Makefile.in (kpathsea): New target.\n\t* src/utils.cc (file_in_path): Use kpathsea function instead of\n\tdoing our own searching.\n\t* kpathsea/Makefile.in (lib): Define as ../libkpathsea.a, not just\n\tkpathsea.a.\n\nWed Sep  7 09:39:20 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/user-prefs.cc (check_str_pref): Fix comment.\n\n\t* src/utils.cc (empty_arg): Check flag == 0, not is_empty > 0.\n\n\t* src/f-fft2.cc (Ffft2): New file and function.\n\t* src/f-ifft2.cc (Fifft2): Likewise.\n\t* src/fft2.m, src/ifft2.m: Delete.\n\n\t* src/f-fft.cc (Ffft): Handle second arg.  Depending on value of\n\tpropagate_empty_matrices, return empty matrix for empty arg.\n\t* src/f-ifft.cc (Fifft): Likewise.\n\n\t* liboctave/CMatrix.cc (fourier2d, ifourier2d): New functions.\n\t* liboctave/dMatrix.cc (fourier2d, ifourier2d): New functions.\n\n\t* src/tree-misc.cc (eval (int, int)): New function.\n\t* src/octave.cc (eval_string, Feval): Handle multiple output args.\n\n\t* src/error.cc (suppress_octave_error_messages): New global.\n\t(error): Check it to see if messages should be printed.\n\t* src/octave/cc (Feval): Set it if `catch' arg is supplied.\n\n\t* src/octave.cc (Feval): Handle second `catch' arg.\n\n\t* src/load-save.cc (read_mat_file_header): Init swap to zero.\n\n\t* doc/octave.1: New simple man page.\n\t* doc/Makefile.in: Distribute and install it.\n\n\t* src/variables.cc (Fclear): Handle -x option for exclusive clear.\n\nTue Sep  6 16:00:34 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/load-save.cc (save_mat_binary_data): New function.\n\t(do_save): Handle LS_MAT_BINARY.\n\t(Fsave): Handle -mat-binary.\n\t(Changes from G. Beyerle <gbeyerle@AWI-Potsdam.DE>.)\n\n\t* src/variables.cc (subs_octave_home, octave_arch_lib_dir):\n\tNew functions.\n\t(octave_home, octave_info_dir, octave_lib_dir, default_path):\n\tFix for new directory organization.\n\n\t* src/tree-expr.h (tree_multi_val_ret): New class to serve as a\n\tbase for objects that can produce more than one value when\n\tevaluated.\n\t(tree_fvc, tree_index_expression, tree_multi_assignment_expression):\n\tUse it as a base.\n\n\t* src/parse.y (make_multi_val_re): New function.\n\t(expression): Use it to construct multiple value assignments.\n\n\t* configure.in, Makefile.in, Makeconf.in, src/defaults.h.in:\n\tRevamp directory structure used for installed versions of Octave.\n\n\t* src/f-schur.cc (Fschur): Correct argument count in error message.\n\n\t* src/octave.cc (Fcomputer): New function.\n\t* scripts/computer.in: Delete.\n\t* scripts/Makefile.in: Don't edit or distribute computer.in.\n\nThu Sep  1 09:02:06 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/variables.cc (install_builtin_variables): New builtin\n\tvariable, OCTAVE_VERSION.\n\nTue Aug 30 17:18:14 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-expr.cc: Include string.h\n\t(tree_matrix::eval): Fix handling of strings to work as in 1.0.\n\nMon Aug 29 14:55:14 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/lex.l: Handle \".+\" and \".-\" too.\n\n\t* src/dirfns.cc (dir_acess, exists, gen_tempname, tempnam): New\n\tfunctions from glibc.\n\t* src/utils.cc (octave_tmp_file_name): Use tempnam.\n\t(choose_temp_base_try): Delete.\n\t* configure.in: Check for tempnam.\n\n\t* src/load-save.cc (Fsave): Only write floating point format if\n\tdoing binary save.\n\n\t* liboctave/Array.cc (operator =): Check to see if assignment is\n\tto same object.\n\nSun Aug 28 23:32:59 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/CollocWt.cc (CollocWt::init): Call delete [] on vectors.\n\t* liboctave/NPSOL.cc (NPSOL::minimize): Eliminate some memory leaks.\n\t* liboctave/QPSOL.cc (QPSOL::minimize): Likewise.\n\t* liboctave/NLEqn.cc (NLEqn::solve): Likewise.\n\nThu Aug 25 09:27:04 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* info/session.c (info_get_input_char): Don't exit immediately if\n\twe see EOF on the input stream.\n\n\t* scripts/kurtosis.m, scripts/skewness.m: Update from KH.\n\nWed Aug 24 00:19:49 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* dld/Makefile.in, scripts/Makefile.in, doc/Makefile.in,\n\treadline/Makefile.in, info/Makefile.in, libcruft/Makefile.in,\n\tliboctave/Makefile.in, src/Makefile.in (INSTALL, INSTALL_PROGRAM,\n\tINSTALL_DATA): Define here.\n\t* Makeconf.in: Not here.\n\n\t* src/tree-plot.cc (send_to_plot_stream): Handle\n\tuser_pref.automatic_replot.\n\t* src/variables.cc (install_builtin_variables):\n\tAdd DEFVAR for automatic_replot.\n\t* src/user-prefs.cc (automatic_replot): New function.\n\t* src/user-prefs.h (user_preferences): Add automatic_replot to the\n\tlist.\n\n\t* src/data.cc (Fatan2): Make work for mixed scalar and Matrix args.\n\t(map): New functions for two arg mappers (like atan2).\n\n\t* src/f-fsqp.cc: Don't surround everything in FSQP_MISSING, so\n\tthat trying to use fsqp will result in a message about fsqp not\n\tbeing freely redistributable.\n\t* src/f-npsol.cc: Likewise, for NPSOL_MISSING.\n\t* src/f-qpsol.cc: Likewise, for QPSOL_MISSING.\n\nTue Aug 23 12:56:47 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree-expr.cc (tree_identifier::eval): Don't call delete for\n\tans_id.  The destructor for tree_simple_assignment_expression does\n\tthis now.\n\n\t* src/Makefile.in (%.def : %.cc): Use sed, not awk.\n\t(realclean, distclean, local-dist, dist): Delete .d and .def files.\n\n\t* liboctave/Array.h (DiagArray::Proxy): Make compilation\n\tconditional on gcc version, not just _AIX.\n\n\t* src/utils.cc (octave_tmp_file_name, choose_temp_base_try): New\n\tfunctions, stolen from GCC.  If HAVE_MKTEMP is not defined, just\n\tcall tmpnam; otherwise, try harder to please.\n\t* src/tree-plot.cc (save_in_tmp_file): Use it, instead of calling\n\ttmpnam() directly.\n\t* src/file-io.cc (do_scanf): Likewise.\n\t* src/octave-hist.cc (mk_tmp_hist_file): Likewise.\n\t* configure.in: Check for mktemp.\n\n\t* src/tree-const.h (is_matrix_type, is_scalar_type): Make private.\n\t* src/tc-rep.h (is_matrix_type, is_scalar_type): Likewise.\n\n\t* src/tc-rep.h (force_numeric, make_numeric,\n\tmake_numeric_or_magic, make_numeric_or_range_or_magic): Make\n\tprivate.\n\t(make_numeric_or_range): #if 0 out.\n\n\t* src/utils.cc (empty_arg): Correctly set return value.\n\n\t* src/arith-ops.cc: Don't include setjmp.h.\n\t* src/utils.cc: Surround setjmp.h with extern \"C\".\n\t* src/octave.cc: Likewise.\n\n\t* src/sighandlers.cc (octave_new_handler): New function.\n\t(install_signal_handlers): Call it.\n\n\t* src/f-qzval.cc (Fqzvalue): Don't call make_numeric for args.\n\tCheck error state after attempting to extract values.  Simplify\n\twhere possible.\n\t* src/f-colloc.cc (Fcolloc): Likewise.\n\t* src/f-rand.cc (Frand): Likewise.\n\t* src/f-sort.cc (Fsort): Likewise.\n\t* src/f-find.cc (Ffind): Likewise.\n\t* src/f-minmax.cc (Fmin, Fmax): Likewise.\n\t* src/f-fft.cc (Ffft): Likewise.\n\t* src/f-ifft.cc (Fifft): Likewise.\n\t* src/f-svd.cc (Fsvd): Likewise.\n\t* src/f-inv.cc (Finv): Likewise.\n\t* src/f-det.cc (Fdet): Likewise.\n\t* src/f-eig.cc (Feig): Likewise.\n\t* src/f-lu.cc (Flu): Likewise.\n\t* src/f-hess.cc (Fhess): Likewise.\n\t* src/f-qr.cc (Fqr): Likewise.\n\t* src/f-givens.cc (Fgivens): Likewise.\n\t* src/f-syl.cc (Fsyl): Likewise.\n\t* src/f-log.cc (Flog): Likewise.\n\t* src/f-expm.cc (Fexpm): Likewise.\n\t* src/f-balance.cc (Fbalance): Likewise.\n\t* src/f-schur.cc (Fschur): Likewise.\n\t* src/f-chol.cc (Fchol): Likewise.\n\t* src/f-npsol.cc (Fnpsol, npsol_options): Likewise.\n\t* src/f-fsolve.cc (Ffsolve, fsolve_options): Likewise.\n\t* src/f-dassl.cc (Fdassl, dassl_options): Likewise.\n\t* src/f-lsode.cc (Flsode, lsode_options): Likewise.\n\t* src/f-quad.cc (Fquad, quad_options): Likewise.\n\t* src/tree-expr.cc (tree_matrix::eval): Likewise, while building\n\tmatrix.\n\t(tree_colon_expression::eval): Likewise, for elements of range.\n\t* src/variables.cc (is_valid_function, Fis_global, Fexist):\n\tLikewise.\n\t* src/sysdep.cc (Fgetenv, Fpause): Likewise.\n\t* src/octave.cc (eval_string, Fshell_cmd): Likewise.\n\t* src/input.cc (get_user_input): Likewise.\n\t* src/file-io.cc (return_valid_file, fopen_file_for_user,\n\tfgets_internal, fseek_internal, process_printf_format, do_printf,\n\tdo_scanf, fread_internal, fwrite_internal, feof_internal):\n\tLikewise.\n\n\t* src/tc-rep.cc (TC_REP::string_value): Call error() and return 0\n\tinstead of crashing if not string_constant.\n\n\t* src/file-io.cc (fopen_file_for_user): Take string as first arg,\n\tnot tree_constant.  Change callers.\n\t(fgets_internal, fseek_internal): Correct check for int arg.\n\t(process_scanf_format): Use isspace instead of checking directly\n\t(and incorrectly) for white space characters.\n\n\t* src/tree-expr.cc (tree_matrix::eval, tree_unary_expression::eval,\n\ttree_binary_expression::eval, tree_colon_expression::eval,\n\ttree_simple_assignment_expression::eval ): Eliminate uneccesary\n\tconversions to and from Octave_object/tree_constant.\n\nMon Aug 22 18:35:05 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/data.cc (Fatan2): New function.\n\n\t* src/data.cc (get_dimensions): Don't call make_numeric for args.\n\tCheck error state after attempting to extract values.\n\nFri Aug 19 08:28:24 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree-misc.h (tree_parameter_list::tree_parameter_list)):\n\tInitialize marked_for_varargs to zero.\n\n\t* src/load-save.cc: Add float variants of the conversion routines.\n\t(LS_DO_READ): Add swap parameter and only swap bytes if it is true.\n\t(read_doubles): Pass swap to LS_DO_READ.  Handle float data.\n\t(LS_DO_WRITE): Copy data to tmp buffer to avoid destroying data.\n\t(do_double_format_conversion): Rename from do_float_format_conversion.\n\t(do_float_format_conversion): New function to handle conversion\n\tfor float data.\n\t(read_mat_binary_data): Use read_doules for all cases.  Handle\n\tfloat data.\n\t(too_large_for_float): New function.\n\t(save_binary_data): Save data format for scalars and ranges too.\n\t(read_binary_data): Read data format for scalars and ranges too.\n\t(do_save, save_vars): New arg, save_as_floats.\n\t(Fsave): New option, -float-binary.\n\n\t* src/utils.cc (empty_arg): New function.\n\t* src/f-balance.cc (Fbalance): Use it to simplify handling of\n\tempty arguments.\n\t* src/f-chol.cc (Fchol): Likewise.\n\t* src/f-det.cc (Fdet): Likewise.\n\t* src/f-eig.cc (Feig): Likewise.\n\t* src/f-expm.cc (Fexpm): Likewise.\n\t* src/f-fft.cc (Ffft): Likewise.\n\t* src/f-hess.cc (Fhess): Likewise.\n\t* src/f-ifft.cc (Fifft): Likewise.\n\t* src/f-inv.cc (Finv): Likewise.\n\t* src/f-log.cc (Flogm, Fsqrtm): Likewise.\n\t* src/f-lu.cc (Flu): Likewise.\n\t* src/f-qr.cc (Fqr): Likewise.\n\t* src/f-schur.cc (Fschur): Likewise.\n\t* src/f-svd.cc (Fsvd): Likewise.\n\n\t* src/tc-rep.cc (tupe_as_string): Move here.\n\t* src/tree-const.cc: From here.\n\n\t* src/gripes.cc (gripe_invalid_conversion): New function.\n\nThu Aug 18 21:02:19 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/(print_empty_matrix): New function.\n\t* src/pr-output.cc (octave_print_internal): Use it to print empty\n\tmatrices.\n\t* src/tc-rep.cc (TC_REP::print_code, TC_REP::print): Rely on\n\toctave_print_internal() to handle printing empty matrices.\n\n\t* src/pr-output.cc (octave_print_internal (all variants)):\n\tNew arg, pr_as_read_syntax.  If nonzero, print the value in a form\n\tthat Octave can parse.\tDeclare os as ostream&, not ostrstream&.\n\t* src/tc-rep.cc (TC_REP::print_code): Handle all types, not just\n\treal and imaginary constants.\n\t* src/help.cc (Ftype): Also print values of variables.\n\nWed Aug 17 08:46:44 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/octave.cc (Fshell_cmd): Return output if nargout > 0 or\n\tnargin > 2, otherwise, just send output to the pager.\n\n\t* src/mappers.cc (xerf, xerfc, xgamma, xlgamma): New functions.\n\tPut preprocessor conditionals here.\n\t(install_mapper_functions): Not here.\n\nTue Aug 16 09:55:25 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Check for erf, erfc, and lgamma.\n\t* src/mappers.cc (erf, erfc, lgamma): New mappers.\n\t* src/mappers.h (Mapper_fcn): Add new field `name'.\n\t* src/variables.cc (install_builtin_mapper): Save the name.\n\t* src/tc-rep.cc (TC_REP::mapper): Don't crash if a mapper function\n\tis missing.\n\n\t* src/tc-rep-1.cc (warn_invalid_conversion): New function.\n\t* src/gripes.cc (gripe_invalid_conversion): New function.\n\n\t* src/parse.y (list1, parse_error): New non-terminals.\n\t(list): Use them.\n\t* src/lex.l: Return LEXICAL_ERROR instead of calling\n\tjump_to_top_level.\n\n\t* liboctave/Range.cc (matrix_value): New function.\n\t* src/tc-rep.cc (TC_REP::matrix_value): Use it.\n\n\t* src/tree-const.h (to_matrix, to_vector, to_scalar): Delete\n\tunecessary functions.\n\t* src/tc-rep.cc (TC_REP::to_matrix, TC_REP::to_vector,\n\tTC_REP::to_scalar): Likewise.  Change all callers to use\n\tmatrix_value, vector_value, and scalar_value instead.\n\n\t* src/tree-const.cc (TC_REP::matrix_value): If at all possible,\n\tproduce a matrix from the current constant.  Otherwise, print an\n\terror message.  Don't abort or jump to the top level.\n\t(TC_REP::scalar_value, TC_REP::complex_scalar_value,\n\tTC_REP::vector_value, TC_REP::complex_vector_value,\n\tTC_REP::complex_matrix_value): Likewise, for appropriate types.\n\n\t* src/utils.cc (empty_arg): New function.\n\t* src/f-svd.cc (Fsvd): Use it.\tDon't call make_numeric; rely on\n\tvalue functions to do conversion.\n\n\t* src/load-save.cc (Fload): Handle -list and -verbose.\n\nMon Aug 15 09:32:57 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tc-rep.cc (TC_REP): New define, so we don't have to write\n\ttree_constant::tree_constant_rep:: everywhere.\n\t* src/tree-const.h (class tree_constant): Nest tree_constant_rep\n\tclass inside tree_constant class by including tc-rep.h here.\n\t* src/tc-rep.h: Don't include any other files, delete forward\n\tclass declarations.\n\n\t* src/tc-rep.h (constant_type): Make private.\n\n\t* src/parse.y (arg_list): Use tree_constant::magic_colon in\n\tconstructor call, not tree_constant_rep::magic_colon.\n\t* src/tree-const.h (tree_constant::tree_constant\n\t(tree_constant::magic_colon)): Convert arg from\n\ttree_constant_rep::constant_type.\n\n\t* src/f-svd.cc (Fsvd): Simplify.\n\n\t* src/tree-expr.cc (any_arg_is_magic_colon): Don't use values from\n\ttree_constant_rep::constant_type enum.\n\t(tree_matrix::eval): Likewise.\n\t* src/tree-misc.cc (tree_parameter_list::define_from_arg_vector,\n\ttree_if_clause::eval):\tLikewise.\n\t* src/tree-cmd.cc (tree_while_command::eval,\n\ttree_for_command::eval): Likewise.\n\t* src/symtab.cc (symbol_record_info::symbol_record_info): Likewise.\n\t* src/f-colloc.cc (Fcolloc): Likewise.\n\t* src/f-npsol.cc (npsol_objective_function): Likewise.\n\t* src/f-chol.cc (Fchol): Likewise.\n\t* src/f-det.cc (Fdet): Likewise.\n\t* src/f-eig.cc (Feig): Likewise.\n\t* src/f-expm.cc (Fexpm): Likewise.\n\t* src/f-fft.cc (Ffft): Likewise.\n\t* src/f-find.cc (Ffind): Likewise.\n\t* src/f-hess.cc (Fhess): Likewise.\n\t* src/f-ifft.cc (Fifft): Likewise.\n\t* src/f-inv.cc (Finv): Likewise.\n\t* src/f-log.cc (Flog): Likewise.\n\t* src/f-lu.cc (Flu): Likewise.\n\t* src/f-minmax.cc (Fmin, Fmax): Likewise.\n\t* src/f-qr.cc (Fqr): Likewise.\n\t* src/f-rand.cc (rand): Likewise.\n\t* src/f-schur.cc (schur): Likewise.\n\t* src/f-sort.cc (Fsort): Likewise.\n\t* src/f-svd.cc (Fsvd): Likewise.\n\n\t* src/f-lu.cc (Flu): Handle case of nargout == 0 the same as\n\tnargout == 1.\n\n\t* src/tree-const.h (force_numeric): Don't return type info.\n\t* src/tc-rep.cc (tree_matrix::eval): Ditto.\n\t* src/tree-expr.cc (tree_matrix::eval): Don't use return value\n\tfrom tree_constant::force_numeric().\n\n\t* src/tree-const.h (is_magic_colon): New function.\n\t* src/tc-rep.h (is_magic_colon): New function.\n\n\t* src/load-save.cc (ascii_save_type): New function.\n\t(save_binary_data, save_ascii_data, save_three_d): Don't use\n\tvalues from tree_constant_rep::constant_type enum. Fail if write\n\tis unsuccessful.  Fail but don't panic if type is unrecognized.\n\t(save_vars): Check error state after call to do_save().\n\n\t* src/tc-rep.cc (isstr): Delete, since we have is_string.\n\t* src/tree-const.h (isstr): Ditto.\n\t* src/data.cc (Fisstr): Use is_string(), not isstr().\n\nSun Aug 14 16:12:10 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/load-save.cc (save_type): Add LS_U_INT, LS_CHAR and LS_FLOAT.\n\t(get_save_type): Handle them.\n\t(read_doubles, write_doubles): Likewise.\n\n\t* src/load-save.cc (get_floating_point_format): New function.\n\t(read_mat_binary_data, read_binary_file_header): Use it.\n\n\t* src/lex.l: Combine {D}+\\.{D}*{EXPON}?{Im} and {D}+{EXPON}?{Im}\n\tpatterns into the single pattern {D}+\\.?{D}*{EXPON}?{Im}\n\tLikewise, combine {D}+\\.{D}*{EXPON}? and {D}+{EXPON}? into the\n\tsingle pattern {D}+\\.?{D}*{EXPON}?\n\t({D}+/\\.[\\*/\\\\^']): New pattern to force expressions like `1./m'\n\tto be parsed the same as `1 ./ m'.\n\n\t* src/tree-expr.cc (do_lookup): Correctly set script_file_executed.\n\n\t* src/octave.cc (long_opts): Add --silent as an alias for --quiet,\n\tand --ignore-init-file as an alias for --norc.\n\n\t* src/octave.cc (verbose_usage): Exit successfully to conform to\n\tthe GNU coding standards.\n\nSat Aug 13 11:06:23 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/dirfns.cc (chdir): New alias for cd.\n\n\t* src/lex.l (\")\"): Set convert_spaces_to_comma.\n\n\t* src/*.cc: Use tree_constant::is_string(), not\n\ttree_constant::is_string_type().\n\n\t* src/f-balance.cc (Fbalance): Use is_string() rather than\n\tchecking const_type() against tree_constant_rep::string_constant.\n\n\t* src/tc-rep.h (tree_constant_rep::is_string_type): Delete.\n\t* src/tree-const.h (tree_constant::is_string_type): Delete.\n\n\t* src/Makefile.in (%.def : %.cc): Complain if generated file is\n\tempty.\n\n\t* configure.in (gcc_version): Set LDFLAGS to -g, not \"-g -O\".\n\n\t* src/lex.l (looks_like_bin_op): Also return true for things like\n\t[ 1+ 2 ].\n\n\t* src/data.cc (Feye, Fones): With no args, return 1.0.\n\t(Fzeros): With no args, return 0.0.\n\n\t* src/Makefile.in (XALL_CXXFLAGS): ALL_CXXFLAGS without\n\t-fextternal-templates.\n\t(%.def : %.cc): Use it instead of ALL_CXXFLAGS.\n\n\t* configure.in: Don't use -O for compiling float-type.c.\n\n\t* libcruft/misc/Makefile.in (XCC): Use patsubst to delete any -O#\n\tflags, not just -O.\n\nFri Aug 12 18:20:35 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\tChanges for binary load/save, and reading .mat files:\n\n\t* src/variables.cc (is_globally_visible): Declare extern, not\n\tstatic.\n\n\t* src/user-prefs.cc (sv_default_save_format): New function.\n\t* src/user-prefs.h (default_save_format): New field in\n\tuser_preferences struct.\n\tsrc/variables.cc (install_builtin_variables): Add DEFVAR for\n\tdefault_save_format.\n\n\t* src/tc-rep.h (tree_constant_rep::is_unknown,\n\ttree_constant_rep::is_scalar, tree_constant_rep::is_matrix,\n\ttree_constant_rep::is_complex_scalar,\n\ttree_constant_rep::is_complex_matrix,\n\ttree_constant_rep::is_string, tree_constant_rep::is_range):\n\tNew functions.\n\n\t* src/tree-const.h (tree_constant::is_unknown,\n\ttree_constant::is_scalar, tree_constant::is_matrix,\n\ttree_constant::is_complex_scalar, tree_constant::is_complex_matrix,\n\ttree_constant::is_string, tree_constant::is_range):\n\tNew functions.\n\n\t* src/tc-rep.cc (tree_constant_rep::save,\n\ttree_constant_rep::save_three_d): Move to load-save.cc and convert\n\tto nonmember functions.\n\n\t* src/tree-const.h (tree_constant::save,\n\ttree_constant::save_three_d): Delete functions.\n\n\t* src/tree-plot.cc (save_in_tmp_file): Call nonmember functions\n\tsave_ascii_file and save_three_d instead of tree_constant class\n\tmember functions.\n\n\t* src/symtab.cc (symbol_table::glob): New function.\n\t(symbol_table::save, symbol_record::save, symbol_def::save):\n\tDelete unneeded functions.\n\n\t* src/load-save.cc: New file, for load/save related functions\n\textracted from src/variables.cc and src/tc-rep.cc.\n\n\t* src/error.cc (verror): Don't print name if it is null.\n\nTue Aug  9 14:31:43 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/file-io.cc (process_printf_format): Use\n\ttree_constant::is_scalar_type() and is_string_type() functions\n\tinstead of comparing directly with elements of the\n\ttree_constant_rep::constant_type enum.\n\t* src/variables.cc (builtin_real_scalar_variable): Likewise.\n\t(install_loaded_variable): Likewise.\n\n\t* src/tree-plot.cc (open_plot_stream): New function.\n\t(send_to_plot_stream): Use it.  Do our own check for replot with\n\tnothing to plot.\n\t(tree_plot_command::eval): Open plot stream before doing anything.\n\n\t* src/data.cc (check_dimensions): When changing negative\n\tdimensions to zero, handle nr and nc separately.\n\nMon Aug  8 20:18:17 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* variables.cc (is_valid_fcn): Use lookup_by_name() instead of\n\tlooking in the global symbol table directly.\n\n\t* variables.cc (load_variable): Move code here.\n\t* src/tc-rep.cc (tree_constant_rep::load): From here.\n\t* src/tree-const.h (tree_constant::load): Delete.\n\n\t* src/tree-plot.cc: Derive classes from tree_print_code and\n\timplement print_code() member functions.\n\n\t* src/tree-plot.cc (subplot_list::print): New function.\n\t(tree_plot_command::print): Use it, and don't crash if plot_list\n\tis null.\n\n\t* scripts/axis.m: New function file.\n\nSun Aug  7 17:06:16 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Check for size of short, int, and long.\n\n\t* float-type.c: New file.\n\t* configure.in: Use it to determine the native floating point\n\tformat.\n\t* Makefile.in: Add it to the list of files to distribute.\n\t* acconfig.h (IEEE_BIG_ENDIAN, IEEE_LITTLE_ENDIAN, VAX_D_FLOAT,\n\tVAX_G_FLOAT): Add #undefs.\n\nSat Aug  6 18:23:47 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* config.guess: Update with new copy from gcc 2.6.0.\n\n\t* src/*.cc, src/*.h, src/*.l, src/*.y: Eliminate need for tree.h.\n\t* src/Makefile.in (INCLUDES): Delete it from the list.\n\n\t* src/token.cc (token::token (double)): Handle saving original\n\ttext of constants for later use by print_code() functions.\n\t(token::~token): Delete original text.\n\t(token::text_rep): New function.\n\t* src/lex.l: Save original text for NUM and IMAG_NUM tokens.\n\t* src/parse.y: Likewise.\n\n\t* src/parse.y (yyerror): Use the pager.\n\n\t* src/tree-base.h (tree_print_code): New base class for trees and\n\tlists of trees.\n\t(tree): Derive from tree_print_code.\n\t* src/tree-base.cc: New file, for tree_print_code functions, and\n\tfor initializing tree_print_code static members.\n\t* src/tree-const.cc, src/tc-rep.cc, src/tree-plot.cc,\n\tsrc/tree-expr.cc, src/tree-cmd.cc (all tree classes):\n\tProvide print_code() member function.\n\t* src/tree-misc.cc: Also derive list classes from tree-base.h and\n\tprovide print_code() member functions.\n\n\t* src/help.cc (Ftype, Fwhich): New functions.\n\n\t* src/octave-hist (do_history): Send history output through the\n\tpager.\n\n\t* src/variables.cc (do_who, Fwhos): New functions.\n\n\t* src/tree-expr.h (tree_expression::in_parens): Declare here.\n\t(tree_simple_assignment_expression::in_parens): Not here.\n\t* src/parse.y (maybe_warn_assign_as_truth_value): Eliminate cast.\n\n\t* src/variables.cc (load_fcn_from_file, lookup, lookup_by_name):\n\tNew functions, extracted from tree_identifier class.\n\t(gobble_leading_whitespace, is_function_file, parse_fcn_file):\n\tMove here from tree-expr.cc.\n\t* src/help.cc (Fhelp): Use lookup_by_name so that looking up\n\tsymbols is handled in a consistent way.\n\n\t* tree-expr.cc (tree_unary_expression::oper,\n\ttree_binary_expression::oper, tree_prefix_expression::oper,\n\ttree_postfix_expression::oper): New functions.\n\n\t* tc-rep.cc (valid_scalar_indices): Define here.\n\t* tc-inlines.cc: Not here.\n\n\t* src/tree-const.h (tree_constant::stash_original_text): New\n\tfunction.\n\t* src/tc-rep.cc (tree_constant_rep::stash_original_text): Ditto.\n\t(undo_string_escapes): Ditto.\n\n\t* src/tc-rep (tree_constant_rep::do_matrix_index): Don't just\n\treturn *this.\n\t* src/tree-const.h (tree_constant::tree_constant (tree_constant_re&)):\n\tDelete.\n\n\t* src/pager.cc (open_diary_file, close_diary_file,\n\tmaybe_write_to_diary_file, Fdiary): New functions.\n\t(flush_output_to_pager): Call maybe_write_to_diary_file before\n\tsending output to the screen.\n\t* src/input.cc (octave_gets): Call maybe_write_to_diary file to\n\tsave the prompt and the user input.\n\t* src/error.cc (verror): Use C++ streams, not C I/O functions.\n\tCall maybe_write_to_diary file to save error messges too.\n\t* src/octave.cc (clean_up_and_exit): Close diary file here.\n\n\t* src/octave.cc (main): Initialize pager first.\n\n\t* src/input.cc (get_user_input): Return empty matrix for no input.\n\n\t* src/tree-plot.cc: Include readline/tilde.h instead of declaring\n\ttilde_expand() directly.\n\t* src/utils.cc: Likewise.\n\n\t* src/tree-plot.cc (tree_plot_command::print_code): New function.\n\t* src/tree-const.h (tree_constant::print_code): Likewise.\n\n\t* src/tree-expr.h (tree_simple_assignment_expression::ans_ass):\n\tNew data member to flag assignments to ans.\n\t* src/tree-expr.cc (tree_identifier::eval): Set it when\n\tconstructing assignments to ans.\n\t* src/parse.y (maybe_convert_to_ans_assign): Likewise.\n\n\t* src/tree-expr.h (tree_simple_assignment_expression::preserve):\n\tNew data member to allow preserving left hand side args that\n\tshouldn't be deleted in some cases (ugh).\n\t* src/tree-expr.cc (tree_multi_assignment_expression::eval):\n\tCreate assignment with preserve flag set.\n\nWed Aug  3 14:27:25 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\tYet another massive reorganization of sources, once again\n\thopefully for the better.  A fair amount of work is not detailed\n\there, but these are the major points.  The grammar file and the\n\tderivation of the tree classes are somewhat cleaner now.\n\n\t* src/parse.y: Cope with changes to derivation scheme.\n\n\t* src/tree-misc.cc: New file.\n\t(tree_statement, tree_global): New classes.\n\t(tree_global_init_list): New class, derived from SLList for the\n\tlist of expressions in a global command.\n\t* src/tree-cmd.cc (tree_global_command): Use tree_global_init_list.\n\n\t* src/tree-misc.cc (tree_argument_list): Move here from\n\ttree-expr.cc, and derive from SLList instead of tree.\n\t(tree_parameter_list): Likewise.\n\t(tree_return_list): Likewise.\n\n\t* src/tree-cmd.cc (tree_command_list): Delete class.\n\t* src/tree-misc.cc (tree_statement_list): New class for keeping a\n\tlist of commands or expressions to evaluate.  Derive from SLList,\n\tnot tree.\n\n\t* src/tree-plot.cc (subplot_list, plot_limits, plot_range,\n\tsubplot_using, subplot_style): Rename from tree_*, and\n\tdon't derive from tree class.\n\n\t* src/tree-plot.cc: Eliminate eval member function for classes not\n\tderived from tree class.\n\n\t* src/tree-plot.cc, src/tree-cmd.cc: For classes derived from\n\ttree-command, the eval() member function is now void eval (void).\n\n\t* src/tree-base.h (tree::tree): New constructor, to initialize the\n\tline and column info.  For all classes that are derived from the\n\ttree class, use it instead of manipulating the data directly.\n\t(line_num, column_num): Make private.\n\n\t* src/tree-expr.cc (tree_simple_assignment_expression::preserve):\n\tNew data member, set in constructors and used by the destructor\n\twhen the left-hand side of the expression should not be deleted\n\t(as for some temporary assignments not constructed in the parser).\n\n\t* src/tree-expr.h (tree_expression::type) Rename and move here from\n\ttree-base.h.  Change all uses.\n\t(tree_matrix::dir): Likewise.  Change all uses.\n\n\t* src/utils.cc (make_argv): Stash function name in argv[0].\n\n\t* src/octave.cc (global_command): Declare as tree_statement_list,\n\tnot tree.\n\n\t* src/parse.y (make_binary_op, make_unary_op, make_prefix_op,\n\tmake_postfix_op): New functions.\n\n\t* src/parse.y (GLOBAL): Make it a tok_val type.\n\t* src/lex.l (is_keyword): Give GLOBAL a value.\n\nMon Aug  1 22:37:22 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/lex.l (grab_help_text): Unput the last character read.\n\nSun Jul 31 21:17:07 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/pr-output.cc (set_format (double, int&)): Avoid calling\n\tlog10 for Inf and NaN.\n\nFri Jul 29 16:08:32 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/octave.cc (reading_startup_message_printed): New flag.\n\t(parse_and_execute): New arg, verbose.  If true, print name of\n\tfile as it is read.\n\t(execute_startup_files): Don't print message if\n\tinhibit_startup_message is true.\n\t(main): Move startup message before reading init files.\n\nThu Jul 28 00:25:42 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/Makefile.in (MATRIX_INC): Delete CmplxColVec.h from list.\n\n\t* src/symtab.cc (symbol_table::rename): New function.\n\t* src/parse.y (func_def2): Use it instead of tree_identifier::rename.\n\t* src/tree-expr.cc (tree_identifier::rename): Delete unused function.\n\n\t* src/tree-expr.cc (tree_identifier::load_fcn_from_file): New function.\n\t(tree_identifier::do_lookup): Use it instead of parse_fcn_file.\n\t* src/variables.cc (is_valid_function): Ditto.\n\t* src/help.cc (Fhelp): Ditto.\n\n\t* src/utils.cc (oct_file_in_path): New function.\n\nWed Jul 27 08:59:32 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree-expr.cc (tree_identifier::parse_fcn_file): Combine\n\tthree functions into one.\n\n\t* src/utils.cc: Delete uneeded declaration of ioctl().\n\t* src/sysdep.cc: Likewise.\n\n\t* install.sh: New file, from autoconf distribution.\n\t* Makefile.in (DISTFILES): Distribute it.\n\nTue Jul 26 16:08:58 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/Makefile.in (DISTDIRS): New variable, for directories\n\tbelow scripts to distribute.\n\t(dist): Handle distributing whole directories named by $(DISTDIRS).\n\t(local-dist): Ditto.\n\nMon Jul 25 12:57:09 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/CmplxQRP.cc: Provide declaration for zungqr.\n\t* liboctave/dbleQRP.cc: Provide declaration for dorgqr.\n\n\t* src/Makefile.in (dist): Also remove y.output and defaults.h.\n\t(local-dist): Ditto.\n\t(realclean): Ditto.\n\n\t* src/oct-obj.h (Octave_object::Octave_object (int)): Make\n\tprivate, to avoid problems with different meanings of\n\tOctave_object (int) and Octave_object (double) constructors.\n\n\t* scripts/amr-image: New files for image processing from Tony\n\tRichardson.  These are not in the default octave LOADPATH yet.\n\tSee the README file in the amr-image directory for more info on\n\thow to use them.\n\n\t* src/octave.cc (Fshell_cmd): Restore accidentally deleted\n\tfunction.\n\n\t* scripts/conv-amr.m, scripts/deconv-amr.m, scripts/roots-amr.m,\n\tscripts/poly-amr.m, scripts/roots-tuwien.m, scripts/conv-tuwien.m,\n\tscripts/deconv-tuwien.m, scripts/poly-tuwien.m:\n\tNew files.\n\tFIXME -- For each of these functions, either one of the\n\tversions will need to be selected, or they will need to be merged\n\tbefore the next release.\n\n\t* scripts/null.m, scripts/orth.m, scripts/fft2.m, scripts/ifft2.m,\n\tscripts/filter.m, scripts/compan.m, scripts/polyderiv.m,\n\tscripts/polyinteg.m, scripts/polyreduce.m, scripts/polyval.m,\n\tscripts/polyvalm.m, scripts/postpad.m, scripts/prepad.m,\n\tscripts/residue.m, scripts/sinc.m, scripts/freqz.m,\n\tscripts/complement.m, scripts/intersection.m,\n\tscripts/create_set.m, scripts/union.m:\n\tNew files.\n\n\t* scripts/hilb.m: Eliminate inner loop, for speed.  From\n\tromolo@URSAMAJOR.ENG.UNIPR.IT (Romolo Manfredini).\n\nSun Jul 24 22:08:48 1994  Castor Fu (castor@drizzle.stanford.edu)\n\n\t* libcruft/ranlib/genf.f (genf): Use 1.2E-38 instead of 1.0E-38\n\twhen checking to see if generated numbers will cause overflow.\n\tThis helps DEC's f77 compiler on the Alpha, which refuses to\n\tgenerate denormalized constants.\n\t* libcruft/ranlib/gennf.f (gennf): Likewise.\n\nFri Jul 22 10:27:00 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/Makefile.in (DEF_FILES): Depend on defun header files too.\n\nThu Jul 21 14:40:30 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/NLFunc.h (nonlinear_fcn): Declare as pointer to\n\tfunction taking const ColumnVector arg.\n\t(jacobian_fcn): Ditto.\n\n\t* src/defun-int.h (DEFINE_ARGV): Declare and define save_argc and\n\tsave_argv for functions that mess with argc and argv directly.\n\t(DELETE_ARGV): Use save_argc and save_argv instead of argc and argv.\n\n\t* src/f-lsode.cc (ODE_OPTIONS): Add const qualifier for string elts.\n\t(print_lsode_option_list): Declare keyword as const char *.\n\t* src/f-npsol.cc, src/f-qpsol.cc, src/f-dassl.cc, src/f-quad.cc:\n\tLikewise, for corresponding structs and functions.\n\n\t* liboctave/dbleSVD.h (SVD::type): New enum, for choosing type of\n\tfactorization.\n\t* liboctave/CmplxSVD.cc (SVD::SVD): Add new optional arg for type.\n\t(init): Handle case of type == SVD::economy.\n\t* liboctave/dbleSVD.cc: Likewise.\n\n\tQR changes from R. Bruce Tenison (btenison@eng.auburn.edu) adapted\n\tfor new way of defining builtin functions:\n\n\t* doc/linalg.texi:  Changed QR description to include QRP\n\tfactorization\n\n\t* src/f-qr.cc (Fqr): Handle permuted and economy QR\n\tfactorizations.  Handle case of 1 output arg.\n\n\t* liboctave/Makefile.in (MATRIX_INC, MATRIX_SRC): Add new QRP files.\n\n\t* liboctave/dbleQRP.h, liboctave/dbleQRP.cc, liboctave/CmplxQRP.h,\n\tliboctave/CmplxQRP.h: New files, for QR with pivoting.\n\n\t* liboctave/dbleQR.h (QR::type): New enum, for choosing type of\n\tfactorization.\n\t* liboctave/CmplxQR.cc (QR): Add new optional arg for type.\n\tHandle case of type == SVD::economy and SVD::raw.\n\t* liboctave/dbleQR.cc (QR): Likewise.\n\n\t* libcruft/lapack/dgeqpf.f: New file.\n\t* libcruft/lapack/zgeqpf.f: Ditto.\n\nWed Jul 20 13:12:55 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/*.cc, liboctave/*.h: Various cleanups to remove use of\n\tNULL.  Only mention default argument values in function\n\tdeclarations, not in their definitions (required for gcc 2.6.x).\n\n\t* configure.in: If configuring for alpha-dec-osf, check for sgtty\n\tfirst. If not found, go ahead and check for Posix terminal driver.\n\nTue Jul 19 09:25:45 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/mx-defs.h (FILE): Don't declare as struct FILE just to\n\tavoid including stdio.h.\n\t* liboctave/dMatrix.cc: Do include stdio.h here.\n\n\t* liboctave matrix classes: Declare operator>> correctly, and\n\treturn istream object.  Get friend stuff right.\n\n\t* liboctave/DAE.cc (DAE::integrate): To see if the user provided a\n\tJacobian function, call DAEFunc::jacobian_function ().\n\n\t* liboctave/DAE.cc (user_fun, user_jac): Qualify with class name.\n\t* liboctave/ODE.cc (user_fun, user_jac): Ditto.\n\n\t* liboctave/DAFunc.h (DAEJac): Declare inside class.\n\t(DAERHSFunc, DAEJacFunc): Define types inside class.\n\t* liboctave/ODEFunc.h (ODERHSFunc, ODEJacFunc) Likewise.\n\n\tMassive reorganization of sources, hopefully for the better.\n\tA fair amount of work is not detailed here, but these are the\n\tmajor points...\n\n\t* src/symtab.h (symbol_def::TYPE) Add new elements for recording\n\twhether a symbol is a text function or mapper function.\n\t* src/symtab.cc (symbol_def::is_text_function,\n\tsymbol_record::is_text_function, symbol_def::is_mapper_function,\n\tsymbol_record::is_mapper_function): New functions.\n\tModify existing is_* functions to cope with these changes.\n\t(symbol_def::symbol_def (tree_builtin*, unsigned)): New 2nd arg.\n\t(symbol_def::symbol_def (tree_function*, unsigned)): Ditto\n\t(symbol_def::define (tree_builtin*, unsigned)): Ditto.\n\t(symbol_def::define (tree_function*, unsigned)): Ditto.\n\t* src/variables.cc (is_text_function_name): Use the new symbol\n\ttable functions, since we can no longer tell by looking in a\n\tsimple list.\n\n\t* tree-expr.cc (class tree_builtin): Text functions are no longer\n\thandled as a special case here.\n\n\t* src/sysdep.cc (octave_ieee_init): Special case Alpha for\n\tinitializing Inf and NaN.\n\n\t* src/tc-rep.cc: Use const in more places.\n\n\t* src/data.cc src/timefns.cc, src/dirfns.cc, src/dirfns.h: New\n\tfiles.\n\n\t* src/*.cc, src/*.y, src/*.l, src/*.h: Various cleanups to remove\n\tuse of NULL.  Only mention default argument values in function\n\tdeclarations, not in their definitions (required for gcc 2.6.x).\n\n\t* src/g-builtins.cc, src/g-builtins.h, src/t-builtins.cc\n\tsrc/t-builtins.h: Removed.  Functions moved to various other\n\tfiles, where they more logically belong.\n\t* src/utils.cc:  Likewise, various functions moved to other files,\n\twhere they more logically belong.\n\t* src/mappers.cc (install_mapper_functions): Declare all mapper\n\tfunctions here with the new DEFUN_MAPPER() macro.\n\t* src/variables.cc (install_builtin_variables): Declare all\n\tbuiltin variables here, with the new DEFVAR() macro.\n\n\t* src/f-*.h: Deleted.\n\t* src/f-*.cc: Delete #ifdef WITH_DLD code and use DEFUN_DLD()\n\tinstead to declare builtin functions that will be dynamically\n\tloaded.  Give all functions a uniform return type and argument\n\tlist.\n\n\t* src/mkdefs, src/mkbuiltins: New scripts.\n\t* src/Makefile.in: Use them to generate builtins.cc automatically\n\tfrom source files that use DEFUN.\n\n\t* src/defun.h, src/defun-dld.h, src/defun-int.h: New files, to\n\tdefine DEFUN() and DEFVAR() macros to make it possible to define\n\tfunctions together with their help strings in one place.  The code\n\tto install functions in the symbol table is now generated by\n\tmkbuiltins.\n\n\t* configure.in (LIBOCTDLD): New variable to define.\n\tOnly call AC_VERBOSE() for DYNAMIC_LD_OBJ, DLD_DIR, LIBDLD,\n\tLIBOCTDLD, and LD_STATIC_FLAG if they are set.\n\t* move-if-change: Move here, from src/move-if-change.\n\t* Makeconf.in (%.d: %.cc): Echo simple message instead of the\n\tcommands actually executed.\n\t(%.d: %.c): Likewise.\n\n\t* src/unwind-prot.h: Include stddef.h, for size_t.\n\nTue Jul 12 12:51:25 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/f-eval.cc, src/f-fill.cc, src/f-find.cc, src/f-input.cc,\n\tsrc/f-minmax.cc, src/f-log.cc, src/f-sort.cc, src/f-eval.h,\n\tsrc/f-fill.h, src/f-find.h, src/f-input.h, src/f-log.h,\n\tsrc/f-minmax.h, src/f-sort.h: New files, for functions extracted\n\tfrom tree-const.cc.\n\t* src/Makefile.in: Add them to the list of INCLUDES, SOURCES, and\n\tOBJECTS.\n\n\t* src/f-*.cc: Clean up things a bit by letting the compiler\n\tgenerate the tree_constant constructor calls.\n\n\t* src/unwind-prot.h: Include stddef.h, for size_t.\n\n\t* src/oct-obj.h (Octave_object (int, const tree_constant&)):\n\tNew constructor form.\n\t* src/tree-const.cc (find_nonzero_elem_idx): Rewrite to handle 2\n\tand 3 return values.\n\n\t* src/g-builtins.cc (builtin_find): Check nargout too.\n\t* src/builtins.cc (general_functions): Fix help message for find.\n\nMon Jul 11 13:36:15 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tc-rep.cc\t(tree_constant_rep::convert_to_row_or_column_vector):\n\tIf already have a row or column vector, return without doing\n\tanything.\n\nSat Jul  9 01:02:51 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/oct-obj.h (Octave_object): Make it a class, not just a\n\ttypedef.\n\n\t* src/tree-expr.h (tree_function::curr_va_arg_number): Rename from\n\tcurr_arg_number.\n\t(tree_function::varargs_ok): Delete unused member variable.\n\t* src/tree-expr.cc (tree_function::octave_va_arg): Increment\n\tcur_va_arg_number before indexing args_passed.\n\t(tree_function::octave_va_start): Set curr_va_arg_number to\n\tnum_args_passed, not num_args_passed + 1.\n\t(tree_function::takes_varargs): Call param_list::takes_varargs,\n\tdon't just return varargs_ok.\n\t(tree_function::define_param_list): If param_list is not NULL, set\n\tnum_named_args and curr_va_arg_number even if function doesn't\n\ttake varargs.\n\n\t* src/tree-expr.cc (tree_identifier::eval (int)): Only pass empty\n\targ list if evaluating a constant.\n\t(tree_function::eval (int)): Always pass least one arg.\n\n\t* Makeconf.in (TMP_IF_1): Add `-I../src'.\n\t(TMP_IF_2): Add `-I$(TOPDIR)/src' and `-I$(top_srcdir)/src'.\n\n\t* src/t-builtins.h, src/variables.h, src/file-io.h, src/f-syl.h,\n\tsrc/f-svd.h, src/f-schur.h, src/f-rand.h, src/f-qzval.h,\n\tsrc/f-quad.h, src/f-qpsol.h, src/f-npsol.h, src/f-lsode.h,\n\tsrc/f-lpsolve.h, src/f-hess.h, src/f-givens.h, src/f-fsqp.h,\n\tsrc/f-fsolve.h, src/f-eig.h, src/f-dassl.h, src/f-colloc.h,\n\tsrc/f-balance.h, src/dynamic-ld.h, src/builtins.cc,\n\tsrc/tree-const.cc, src/file-io.cc, src/f-syl.cc, src/f-svd.cc,\n\tsrc/f-schur.cc, src/f-rand.cc, src/f-qzval.cc, src/f-qr.cc,\n\tsrc/f-qpsol.cc, src/f-lu.cc, src/f-lpsolve.cc, src/f-inv.cc,\n\tsrc/f-ifft.cc, src/f-hess.cc, src/f-givens.cc, src/f-fsqp.cc,\n\tsrc/f-fft.cc, src/f-expm.cc, src/f-eig.cc, src/f-det.cc,\n\tsrc/f-colloc.cc, src/f-chol.cc, src/f-balance.cc,\n\tsrc/dynamic-ld.cc, src/f-dassl.cc, src/f-fsolve.cc,\n\tsrc/f-lsode.cc, src/f-npsol.cc, src/f-quad.cc, src/tree-expr.h,\n\tsrc/tc-rep.cc, src/tc-inlines.cc, src/tc-rep.h, src/tree-const.h,\n\tsrc/g-builtins.cc, src/g-builtins.h, src/tree-expr.cc,\n\tsrc/variables.cc: Delete nargin in favor of using args.length().\n\n\t* configure.in: Check for struct exception in math.h.\n\t* src/sysdep.cc (matherr): New function.\n\nFri Jul  8 15:31:53 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tc-rep.cc: Include arith-ops.h.\n\t(tree_constant_rep::do_scalar_index): Use `invalid', not `illegal'\n\tin messages.\n\n\t* src/oct-obj.h: Protect contents from multiple inclusion.\n\n\t* src/tree-const.h, src/tree-expr.h: Don't include Array.h.\n\n\t* src/parse.y (param_list): Allow ELLIPSIS by itself.\n\t* src/tree-expr.cc (tree_identifier::mark_varargs_only,\n\ttree_identifier::vararg_only): New functions.\n\t(tree_function::eval): Only call define_from_arg_vector if\n\tparam_list is non-null and not marked as varargs_only.\n\n\t* src/f-balance.h, src/f-chol.h, src/f-colloc.h, src/f-dassl.h,\n\tsrc/f-eig.h, src/f-fsolve.h, src/f-fsqp.h, src/f-givens.h,\n\tsrc/f-hess.h, src/f-lpsolve.h, src/f-lsode.h, src/f-lu.h,\n\tsrc/f-npsol.h, src/f-qpsol.h, src/f-qr.h, src/f-quad.h,\n\tsrc/f-qzval.h, src/f-rand.h, src/f-schur.h, src/f-svd.h,\n\tsrc/f-syl.h: Include oct-obj.h, not tree-const.h to get\n\tdeclaration of Octave_object.\n\n\t* src/f-givens.cc (givens): Handle case of nargout == 0.\n\tUse `invalid', not `illegal' in messages.\n\t* src/f-balance.cc (balance): Likewise.\n\n\t* src/f-balance.cc (balance): Print warning about two output\n\targuments for complex-valued case too.\n\n\t* src/tc-rep.cc: Include arith-ops.h.\n\nThu Jul  7 20:54:12 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/parse.y (identifier): Add missing semicolon.\n\t(param_list): Ditto.\n\n\t* src/f-svd.cc (svd): Handle nargout == 0 the same as nargout == 1.\n\t* src/f-schur.cc (schur): Likewise.\n\t* src/f-hess.cc (hess): Likewise.\n\t* src/f-eig.cc (eig): Likewise.\n\t* src/f-syl.cc (syl): Likewise.\n\t* src/f-qzval.cc (qzvalue): Likewise.\n\t* src/f-npsol.cc (npsol): Likewise.\n\t* src/f-qpsol.cc (qpsol): Likewise.\n\t* src/f-givens.cc (givens): Likewise.\n\t* src/f-fsolve.cc (fsolve): Likewise.\n\t* src/f-balance.cc (balance): Likewise.\n\t* src/file-io.cc (process_scanf_format): Likewise.\n\t* src/g-builtins.cc (builtin_balance, builtin_chol, builtin_dassl,\n\tbuiltin_eig, builtin_fsolve, builtin_fsqp, builtin_lsode,\n\tbuiltin_max, builtin_min, builtin_npsol, builtin_qpsol,\n\tbuiltin_quad, builtin_rand, builtin_size, builtin_sort,\n\tbuiltin_svd, builtin_schur, builtin_syl, builtin_givens,\n\tbuiltin_hess): Likewise.\n\t* src/tree-const.cc (vector_of_empties, column_max, column_min):\n\tLikewise.\n\n\t* src/variables.h, src/symtab.h: Include builtins.h for typedefs.\n\n\t* src/tree-expr.cc(tree_multi_assignment_expression::eval): Rework\n\thandling of undefined values returned from functions.\n\n\t* src/tree-expr.cc (tree_identifier::is_defined): New function.\n\t(tree_parameter_list::is_defined): New function.\n\t(tree_parameter_list::convert_to_const_vector): Use it to avoid\n\tevaluating undefined objects.\n\n\t* src/f-balance.cc, src/f-eig.h, src/f-hess.cc, src/f-lu.h,\n\tsrc/f-rand.cc, src/f-balance.h, src/f-expm.cc, src/f-hess.h,\n\tsrc/f-npsol.cc, src/f-rand.h, src/f-chol.cc, src/f-expm.h,\n\tsrc/f-ifft.cc, src/f-npsol.h, src/f-schur.cc, src/f-chol.h,\n\tsrc/f-fft.cc, src/f-ifft.h, src/f-qpsol.cc, src/f-schur.h,\n\tsrc/f-colloc.cc, src/f-fft.h, src/f-inv.cc, src/f-qpsol.h,\n\tsrc/f-svd.cc, src/f-colloc.h, src/f-fsolve.cc, src/f-inv.h,\n\tsrc/f-qr.cc, src/f-svd.h, src/f-dassl.cc, src/f-fsolve.h,\n\tsrc/f-lpsolve.cc, src/f-qr.h, src/f-syl.cc, src/f-dassl.h,\n\tsrc/f-fsqp.cc, src/f-lpsolve.h, src/f-quad.cc, src/f-syl.h,\n\tsrc/f-det.cc, src/f-fsqp.h, src/f-lsode.cc, src/f-quad.h,\n\tsrc/f-det.h, src/f-givens.cc, src/f-lsode.h, src/f-qzval.cc,\n\tsrc/f-eig.cc, src/f-givens.h, src/f-lu.cc, src/f-qzval.h,\n\tsrc/dynamic-ld.cc, src/dynamic-ld.h, src/file-io.cc,\n\tsrc/file-io.h, src/t-biultins.cc, src/t-builtins.h,\n\tsrc/tree-expr.cc, src/tree-expr.h, src/tree-const.cc,\n\tsrc/tree-const.h, src/tc-inlines.cc, src/tc-rep.cc, src/tc-rep.h,\n\tsrc/g-builtins.cc, src/g-builtins.h:\n\tCope with inital round of Octave_object changes.\n\n\t* src/oct-obj.h: New file for Octave_object typedef.\n\t* src/dynamic-ld.h, src/file-io.h, src/tree-const.h,\n\tsrc/tree-expr.h: Include it.\n\t* src/Makefile.in (INCLUDES): Add it to the list.\n\nWed Jul  6 09:28:28 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* libocsrc/tree-const.h:\n\n\t* src/parse.y (maybe_convert_to_ans_assign,\n\tmaybe_warn_assign_as_truth_value): Pass tree_expression*, not tree*.\n\t(ans_expression, expression, simple_expr, simple_expr1, title):\n\tDeclare as tree_expression_type, not tree_type.\n\t(opt_list): Add missing semicolon.\n\n\t* src/tc-rep.h, src/tc-rep.cc: New files, extracted from\n\ttree-const.h and tree-const.cc, for the tree_constant_rep class.\n\tLeave most friend functions behind, in tree-const.h.\n\tDon't declare do_binary_op or do_unary_op as friends.\n\n\t* src/lex.l: Include tree-plot.h and tree-const.h.\n\n\t* src/variables.cc (takes_correct_nargs): Pass tree_fvc* not tree*.\n\t* src/variables.cc (is_valid_function): Return tree_fvc* not tree*.\n\tChange all callers.\n\n\t* src/symtab.h, symtab.cc: Change declaration of symbol definition to\n\tbe tree_fvc* instead of tree*.  Change all callers.\n\n\t* src/f-dassl.cc (dassl_fcn): Declare as tree_fvc*, not tree*.\n\t* src/f-quad.cc (quad_fcn): Likewise.\n\t* src/f-lsode.cc (lsode_fcn): Likewise.\n\t* src/f-fsolve.cc (fsolve_fcn): Likewise.\n\t* src/f-npsol.cc (npsol_fcn, npsol_constraints): Likewise.\n\n\t* src/tree-plot.cc: All operations are now on tree_expression types,\n\tnot tree types.\n\n\t* src/tree-expr.h (tree_matrix): Derive from tree_expression, not tree.\n\n\t* src/tree-expr.h (tree_builtin, tree_function, tree_identifier):\n\tDerive from tree_fvc, not tree.\n\t* src/tree-const.h (class tree_constant): Likewise.\n\n\t* src/tree-expr.h (is_identifier, is_index_expression,\n\tis_assignment_expression, is_prefix_expression,\n\tmark_for_possible_ans_assign, eval (with args)): Declare in\n\ttree_expression class, not tree class.\n\n\t* src/tree-expr.h (tree_fvc): New class, derived from\n\ttree_expression, to provide a connection between functions,\n\tvariables, and constants.\n\t(is_constant, assign, name, bump_value, max_expected_args,\n\tfcn_file_name, time_parsed, is_system_fcn_file, save): Declare\n\tin tree_fvc class, not in tree class.\n\n\t* src/tree.h: Simply include tree-expr.h and tree-cmd.h.\n\t* src/tree-expr.h, tree-expr.cc: New files, extracted from tree.h\n\tand tree.cc for classes derived from tree_expression, plus some\n\thelper classes.\n\t* src/tree-cmd.h, tree-cmd.cc: Likewise, for classes derived from\n\ttree_command.\n\n\t* src/tree.cc (eval (int, int)): Merge with eval (int,\n\ttree_constant*, int, int) by rearranging order of args and using\n\tdefault arg values.  Change all callers.\n\nTue Jul  5 14:33:33 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* doc/Makefile.in (refcard.dvi): Run TeX on $(srcdir)/refcard.tex,\n\tnot just refcard.tex.\n\t(refcard-local.tex): Likewise, for the local version.\n\n\t* src/tree-const.cc (tree_constant_rep::do_index): Check for empty\n\tmatrix here.\n\t(tree_constant_rep::do_vector_index) Not here.\n\nThu Jun 30 09:41:03 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/g-builtins.cc (builtin_shell_command): Only take one\n\targument and return [status, output].\n\t* src/procstream.cc (procstreambase::close): Return process exit\n\tstatus.\n\n\t* src/tree.cc (tree_builtin::eval (int)): Handle new style of\n\tcalling text functions.\n\t(tree_builtin::eval (int, int): Likewise.\n\t(tree_builtin::eval (tree_constant*, int, int, int): Likewise.\n\t(tree_identifier::eval (tree_constant*, int, int, int)): Don't\n\tcount the output arguments that we create automatically (ans) when\n\tfiguring nargout.\n\t(tree_identifier::eval (int)): Likewise.\n\n\t* src/tree-const.cc: Delete text-style eval() functions.\n\t* src/tree.cc: Ditto.\n\n\t* src/tree-const.h: Change typedef of Text_fcn to return a pointer\n\tto a tree_constant, and to include the number of output arguments\n\tin the parameter list.\n\t* src/t-builtins.h: Change declarations of all builtin text-style\n\tfunctions to match.\n\t* src/t-builtins.cc: Change definitions too.\n\n\t* src/parse.y (word_list): Build an argument_list, not a word_list.\n\t(word_list_command): Create an index_expression, not a\n\tword_list_command.\n\t* src/tree.cc (tree_word_list): Delete unneeded class.\n\t(tree_word_list_command): Likewise.\n\n\t* src/tc-extras.cc (get_dimensions): For one-arg version, expect\n\t2-element vector or scalar specifying dimensions.  Don't simply\n\tuse the dimensions of a matrix arg.\n\nWed Jun 29 09:52:15 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/f-det.cc (determinant): Return 0 if matrix is singular to\n\tmachine precision.\n\n\t* liboctave/dMatrix.cc (Matrix::inverse): Declare rcond as\n\tvolatile to prevent optimization of the expression\n\t`rcond + 1.0 == 1.0'.\n\t(Matrix::determinant): Ditto.\n\t(Matrix::solve): Ditto.\n\t* liboctave/CMatrix.cc (ComplexMatrix::inverse): Ditto.\n\t(ComplexMatrix::determinant): Ditto.\n\t(ComplexMatrix::solve): Ditto.\n\nTue Jun 28 10:53:31 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/utils.cc (default_info_file): Add directory separator when\n\tappending \"octave.info\".\n\n\t* src/tree-plot.cc (plot_line_count): Make global.\n\t* src/utils.cc (send_to_plot_stream): If the plot stream is not\n\topen, set plot_line_count to zero.\n\t(close_plot_stream): Likewise, set it to zero when closing the\n\tstream.\n\n\t* src/parse.y (plot_command): Allow replot without args.\n\n\t* src/tree-plot.cc (clear_before_plotting): New global variable.\n\t(tree_plot_command::eval): Use it to handle hold on/off.\n\t* src/t-builtins.cc (builtin_hold): New function.\n\t* src/builtins.cc (text_functions): Add it to the list.\n\nFri Jun 24 11:08:36 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/token.h (plot_tok_type): Add new field, replot.\n\t* src/lex.l (is_keyword): Handle replot here.\n\t* src/parse.y (plot_command): And here.\n\t* src/g-builtins.cc (builtin_replot): Not here.\n\t* src/builtins.cc (general_functions): Or here.\n\nTue Jun 21 10:47:08 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/g-builtins.cc (builtin_kbhit): New function.\n\t* src/builtins.cc (general_functions): Add it to the list.\n\n\t* src/tree-const.cc (tree_constant_rep::rows (void)): For strings\n\tand ranges, only return 1 if the string or range is not empty.\n\nThu Jun  9 20:42:06 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree.cc (tree_builtin::eval (int)): Delete ancient code that\n\teval()'d the return value.\n\t(tree_builtin::eval (int, int)): Likewise.\n\t(tree_builtin::eval (int, char**, int)): Likewise.\n\t(tree_builtin::eval (tree_constant*, int, int, int)): Likewise.\n\t(tree_function::eval (tree_constant*, int, int, int)): Likewise.\n\t(tree_colon_expression::eval (int)): Likewise.\n\t(tree_unary_expression::eval (int)): Likewise.\n\t(tree_binary_expression::eval (int)): Likewise.\n\nMon Jun  6 03:48:32 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/file-io.cc (fread_internal): Make it work.\n\t(fwrite_internal): Likewise.\n\t(num_items_remaining): Renamed from get_whats_left().  Don't pass\n\tnr/nc as last arg, simply return the number of items of size that\n\tare left to read.\n\t(get_size_conv): Delete unnecessary function.\n\t* liboctave/dMatrix.cc (Matrix::read): Make it work.\n\t(Matrix::write): Likewise.\n\t* liboctave/dMatrix.h (conversion): Delete unecessary enum.\n\n\t* src/sysdep.cc: Include <math.h>.\n\t(octave_ieee_init): Cast return value of infinity() and\n\tquiet_nan() to double.\n\nSun Jun  5 14:35:32 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Makeconf.in (getversion): Get everything between the double\n\tquotes, not just numbers and periods.\n\n\t* src/tree-const.cc (tree_constant_rep::do_scalar_assignment): Correct\n\ttypo in last change.\n\n\t* src/parse.y: Include tree-plot.h and tree-const.h.\n\n\t* src/Makefile.in (SOURCES): Delete tc-assign.cc and tc-index.cc\n\t(INCLUDES): Add tree-plot.h.\n\n\t* src/tree-plot.h: New file.  Declare plotting classes here.\n\t* src/tree.h: Not here.\n\n\t* src/tc-index.cc, tc-assign.cc: Delete unnecessary files.\n\n\t* src/tc-extras.cc: Include EIG.h\n\n\t* src/tree-const.cc (tree_constant_rep::tree_constant_rep (RowVector&,\n\tint)): Provide default value for int arg.\n\t(tree_constant_rep::tree_constant_rep (ColumnwVector&, int)): Ditto\n\t(tree_constant_rep::tree_constant_rep (ComplexRowVector&, int)): Ditto\n\t(tree_constant_rep::tree_constant_rep (ComplexColumnwVector&, int)):\n\tDitto.\n\t(tree_constant_rep::tree_constant_rep (RowVector&)): Delete, now\n\thandled by corresponding two arg constructor.\n\t(tree_constant_rep::tree_constant_rep (ColumnwVector&)): Likewise.\n\t(tree_constant_rep::tree_constant_rep (ComplexRowVector&)): Likewise.\n\t(tree_constant_rep::tree_constant_rep (ComplexColumnwVector&)):\n\tLikewise.\n\n\t* src/tree-const.cc: Add pragma implementation.  Merge in contents of\n\ttc-index.cc and tc-assign.cc so that the pragma interface/pragma\n\timplementation hack will do some good.\n\t* src/tree-const.h: Include mx-base.h, not Matrix.h.  Add pragma\n\tinterface.  Delete unnecessary constructor declarations.\n\n\t* src/unwind-prot.h, src/unwind-prot.cc (unwind_elem_tag): Rename\n\tfrom _tag.\n\t(unwind_elem_fptr): Rename from _fptr.\n\t(unwind_elem_ptr): Rename from _ptr.\n\n\t* NLConst.cc (NLConst::NLConst): Pass vector args by reference.\n\n\t* src/procstream.h, src/procstream.cc, src/idx-vector.h,\n\tsrc/idx-vector.cc, src/token.h, src/token.cc, src/unwind-prot.h,\n\tsrc/unwind-prot.cc, src/symtab.h, src/symtab.cc, src/tree.h,\n\tsrc/tree.cc, liboctave/Range.h, liboctave/Range.cc,\n\tliboctave/QLD.h, liboctave/QLD.cc, liboctave/ODE.h,\n\tliboctave/ODE.cc, liboctave/Quad.h, liboctave/Quad.cc,\n\tliboctave/Objective.h, liboctave/Objective.cc, liboctave/NPSOL.h,\n\tliboctave/NPSOl.cc, liboctave/NLFunc.h, liboctave/NLFunc.cc,\n\tliboctave/Bounds.h, liboctave/Bounds.cc, liboctave/QP.h,\n\tliboctave/QP.cc, liboctave/NLConst.cc, liboctave/LinConst.cc,\n\tliboctave/LPsolve.cc, liboctave/LP.cc, liboctave/FSQP.cc,\n\tliboctave/FEGrid.cc, liboctave/QPSOL.cc, liboctave/CollocWt.cc,\n\tliboctave/DAEFunc.cc, liboctave/DAEFunc.h, liboctave/DAE.cc,\n\tliboctave/NLEqn.cc, liboctave/ODEFunc.cc, liboctave/QPSOL.h,\n\tliboctave/ODEFunc.h, liboctave/NLP.h, liboctave/NLEqn.h,\n\tliboctave/NLConst.h, liboctave/LinConst.h, liboctave/LPsolve.h,\n\tliboctave/LP.h, liboctave/FSQP.h, liboctave/FEGrid.h,\n\tliboctave/DAE.h, liboctave/CollocWt.h:\n\tAdd pragma interface/implementation.\n\n\t* src/f-svd.cc, src/f-schur.cc, src/f-qr.cc, src/f-lu.cc,\n\tsrc/f-hess.cc, src/f-det.cc, src/f-chol.cc, src/f-qzval.cc,\n\tsrc/f-inv.cc, src/f-ifft.cc, src/f-givens.cc, src/f-fft.cc,\n\tsrc/f-balance.cc, src/f-expm.cc, src/f-fsqp.cc, src/f-syl.cc,\n\tsrc/xdiv.cc, src/xpow.cc, src/idx-vector.cc, src/pr-output.cc,\n\tsrc/unwind-prot.cc, src/file-io.cc, liboctave/Bounds.h,\n\tliboctave/CollocWt.h, liboctave/DAE.h, liboctave/EIG.h,\n\tliboctave/FEGrid.h, liboctave/LP.h, liboctave/LPsolve.cc,\n\tliboctave/LinConst.h, liboctave/NLEqn.cc, liboctave/NLEqn.h,\n\tliboctave/NLP.h, liboctave/NPSOL.cc, liboctave/NPSOL.h,\n\tliboctave/ODE.h, liboctave/Objective.h, liboctave/QLD.cc,\n\tliboctave/QP.h, liboctave/QPSOL.h, liboctave/Quad.h:\n\tInstead of including Matrix.h, only include the individual\n\tmatrix/vector/etc. header files that are needed.\n\n\t* liboctave/QLD.cc, liboctave/ODE.cc, liboctave/NLFunc.cc,\n\tliboctave/DAEFunc.cc, liboctave/DAE.cc, liboctave/NLEqn.cc,\n\tliboctave/ODEFunc.cc:\n\tUse 0, not NULL.\n\n\t* liboctave/mx-inlines.cc: Include Complex.h.\n\n\t* liboctave/mx-kludge.h: Don't enclose contents in extern \"C++\".\n\n\t* liboctave/Matrix.h: Simply include mx-base.h and mx-ext.h.\n\n\t* liboctave/mx-base.h: New file, includes all basic matrix/vector\n\theader files.\n\t* liboctave/mx-ext.h: New file, includes all extra matrix/vector\n\trelated header files.\n\t* liboctave/mx-defs.h: New file, for matrix/vector related\n\tdefines.  Also provides forward declarations for all matrix/vector\n\tclasses.\n\n\t* liboctave/Makefile.in: Cope with new files.\n\n\t* liboctave/CmplxAEPBAL.cc, liboctave/CmplxDET.h,\n\tliboctave/CmplxQR.cc, liboctave/CmplxSVD.h, liboctave/dbleDET.cc,\n\tliboctave/dbleHESS.h, liboctave/dbleSCHUR.cc,\n\tliboctave/CmplxAEPBAL.h, liboctave/CmplxHESS.cc,\n\tliboctave/CmplxQR.h, liboctave/dbleAEPBAL.cc, liboctave/dbleDET.h,\n\tliboctave/dbleLU.cc, liboctave/dbleSCHUR.h,\n\tliboctave/CmplxCHOL.cc, liboctave/CmplxHESS.h,\n\tliboctave/CmplxSCHUR.cc, liboctave/dbleAEPBAL.h,\n\tliboctave/dbleGEPBAL.cc, liboctave/dbleLU.h, liboctave/dbleSVD.cc,\n\tliboctave/CmplxCHOL.h, liboctave/CmplxLU.cc,\n\tliboctave/CmplxSCHUR.h, liboctave/dbleCHOL.cc\n\tliboctave/dbleGEPBAL.h, liboctave/dbleQR.cc, liboctave/dbleSVD.h,\n\tliboctave/CmplxDET.cc, liboctave/CmplxLU.h, liboctave/CmplxSVD.cc,\n\tliboctave/dbleCHOL.h, liboctave/dbleHESS.cc, liboctave/dbleQR.h,\n\tliboctave/EIG.h, liboctave/EIG.cc:\n\tNew files, extracted from Matrix-ext.cc, in an attempt to allow\n\teffective use of pragma interface/implementation and make\n\tgenerated code somewhat smaller.\n\t* liboctave/dColVector.cc liboctave/CColVector.cc: Likewise, from\n\tColVector.{cc,h}.\n\t* liboctave/dRowVector.cc liboctave/CRowVector.cc: Likewise, from\n\tRowVector.{cc,h}.\n\t* liboctave/dMatrix.cc liboctave/CMatrix.cc: Likewise, from\n\tMatrix.{cc,h}.\n\t* liboctave/dDiagMatrix.cc liboctave/CDiagMatrix.cc: Likewise,\n\tfrom DiagMatrix.{cc,h}.\n\nFri Jun  3 15:32:53 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/Array.h: Include assert.h.\n\t(DiagArray<T>::operator T ()): [! _AIX] Only call get() if i is\n\talso equal to j.\n\n\t* scripts/rem.m: Allow mixing of scalar/matrix args, but complain\n\tif both args are matrices and the dimensions don't agree.\n\n\t* src/lex.l (grab_help_text): Correct previous change.\n\nThu Jun  2 12:08:18 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Matrix.h (conversion): New enum, for binary read/write\n\tfunctions.\n\t* Matrix.cc (read, write) New functions.\n\t* file-io.cc (feof_internal, ferror_internal, fread_internal,\n\tfwrite_internal, get_size_conv, get_whats_left): New functions.\n\t* g-builtins.cc (builtin_feof, builtin_ferror, builtin_fread,\n\tbuiltin_fwrite): New functions.\n\t* builtins.cc (general_functions): Add them to the list.\n\n\t* configure.in: Check for infinity() and quiet_nan().\n\t* sysdep.h (octave_Inf, octave_NaN): New global variables.\n\t* sysdep.cc (octave_ieee_init): New function.  Initialize\n\toctave_Inf and octave_NaN.\n\t(sysdep_init): Call it.\n\t* builtins.cc (initialize_builtins): Don't compute Inf and NaN\n\tvalues here.\n\nTue May 31 20:06:27 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/variables.cc (identifier_exists): Only return 1 for\n\tvariables if they are also defined.\n\nSun May 29 20:40:55 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/lex.l: Don't declare beginning_of_function as static.\n\t(COMMENT): Delete unnecessary exclusive start state.\n\t(\\#, \\%): Handle comments directly.  Try to be smart about not\n\treturning a newline character when reading a matrix list.\n\t(grab_help_text): Don't put a newline back on the input stream.\n\t* src/parse.y (list1): Set beginning_of_function to zero here.\n\nWed May 25 03:34:17 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/error.cc (error): If error_state is -2, don't do anything.\n\tIf the format string ends in a new line character, strip it, print\n\tthe error message, and set the error state to -2.\n\t* src/tree.cc (tree_function::traceback_error): Don't set the\n\terror_state if it is already negative.\n\n\t* src/tree-const.cc (convert_to_row_or_column_vector): New function.\n\t* src/idx-vector.cc (idx_vector::shorten): New function.\n\t* src/tc-assign.cc (fortran_style_matrix_assignment\n\t(tree_constant&, tree_constant&)): Handle deleting elements by\n\tassignment of `[]'.  Use convert_to_row_or_column_vector to handle\n\tconversion to a vector in the case of deleting some elements from\n\ta matrix.  Use idx_vector::shorten() to remove unnecessary index\n\tvector elements.\n\t(do_scalar_assignment (tree_constant&, tree_constant*, int)):\n\tHandle assignment of empty matrix.\n\tIf converting complex to real, delete old complex value.\n\t(delete_rows (idx_vector&)): If deleting all rows of a column\n\tvector, convert to empty matrix.\n\t(delete_rows (Range&)): Ditto.\n\t(delete_columns (idx_vector&)): If deleting all columns of a row\n\tvector, convert to empty matrix.\n\t(delete_columns (Range&)): Ditto.\n\n\t* src/tc-extras.cc (column_max (tree_constant*, int, int)):\n\tUse MAX, not MIN when trying to find the biggest scalar.\n\tLikewise, find the complex scalar with the largest, not the\n\tsmallest absolute value.\n\n\t* src/tc-assign.cc (do_matrix_assignment (tree_constant&,\n\ttree_constant_rep::constant_type, tree_constant&): For case of\n\tj_arg == matrix constant, don't negate return value of\n\tindexed_assign_conforms().\n\n\t* src/user-prefs.cc (commas_in_literal_matrix): New function.\n\tPut functions in alphabetical order.\n\t* src/user-prefs.h (commas_in_literal_matrix): New structure element.\n\tAlphabetize structure elements and lists of functions.\n\t* src/builtins.cc (string_variables): Add commas_in_literal_matrix\n\tto the list.\n\t* src/lex.l (<MATRIX>{SN}*\\]{S}*): Pay attention to the value of\n\tusre_pref.commas_in_literal_matrix when deciding whether to insert\n\ta comma after seeing a ']' character.\n\t(handle_identifier): Likewise.\n\t(<MATRIX>{S}+): If commas are required, just eat the spaces.\n\nTue May 24 19:49:51 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tc-assign.cc (tree_constant_rep::do_matrix_assignment\n\t  (tree_constant&, tree_constant*, int)): Handle empty arguments\n\tfor two index values.\n\t(tree_constant_rep::do_matrix_assignment\n\t  (tree_constant&, tree_constant&)):\n\tLikewise, for single index values.\n\nMon May 23 01:43:23 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Makefile.in (snapshot, snapshot-version): New targets.\n\n\t* configure.in: Handle --enable-run-in-place (was easier than\n\tdoing the work to parse --run-in-place like Emacs uses).\n\n\t* acconfig.h: Add #undef for RUN_IN_PLACE.\n\n\t* Makeconf.in (OCTAVE_HOME): New macro.\n\t* src/Makefile.in (defaults.h): Use it instead of ${prefix}.\n\n\t* Makeconf.in (OCTAVE_INFO_DIR, OCTAVE_LIB_DIR): New macros.\n\t* src/Makefile.in (defaults.h): Substitute them too.\n\n\t* src/defaults.h.in (OCTAVE_INFO_DIR): New macro, used if\n\tRUN_IN_PLACE is defined.\n\t(OCTAVE_LIB_DIR): Likewise.\n\n\t* src/utils.cc (octave_home): Handle RUN_IN_PLACE\n\t(octave_info_dir): Ditto.\n\t(octave_lib_dir): Ditto.\n\n\t* src/tree-const.cc (tree_constant_rep::diag (void)): For empty\n\tmatrix, return empty matrix.\n\t(tree_constant_rep::diag (tree_constant &)): Likewise, regardless\n\tof value of arg.\n\n\t* scripts/int2str.m: Format as integer, not float.\n\tDon't add trailing new line character.\n\nSun May 22 22:13:01 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/plot_int.m: When looking for imaginary arguments, check\n\tif any element has an imaginary component, not if all elements\n\thave imaginary components.\n\nThu May 19 19:46:23 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/parse.y (EXPR_AND_AND, EXPR_OR_OR): New tokens, for\n\tshort-circuit logical AND and OR operators.\n\t(simple_expression): Handle new tokens.\n\t* src/lex.l (&&) [SHORT_CIRCUIT_LOGICALS]: Return EXPR_AND_AND.\n\t(||) [SHORT_CIRCUIT_LOGICALS]: Return EXPR_OR_OR.\n\t* src/tree.cc (tree_binary_expression::eval): Handle short-circuit\n\tboolean operators.\n\t(tree_binary_expression::eval_error): Print different messages for\n\tor_or/or and and_and/and.\n\t* src/tree-base.h (tree_expression_type): Add new structure\n\telements and_and and or_or.\n\t* src/tree-const.cc (tree_constant_rep::is_true): New function.\n\nTue May 17 17:04:00 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/idx-vector.cc (idx_vector::sort_uniq ()): New function.\n\t* src/tc-assign.cc (tree_constant_rep::delete_rows ()): Use it.\n\t(tree_constant_rep::delete_columns ()): Likewise.\n\nMon May 16 13:31:33 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/linspace.m: Replace for loop with range operation.\n\t* scripts/logspace.m: Replace for loop with element by element\n\texponentiation.\n\nSun May  8 00:49:38 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/lqe.m: Correct comment.\n\tTranspose k before returning.\n\nFri May  6 00:47:24 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree.cc (quit_loop_now): New function.\n\t(tree_while_command::eval): Use it.\n\t(tree_for_command::eval): Ditto.\n\n\t* src/tree.cc (tree_for_command::do_for_loop_once): New function.\n\t(tree_for_command::eval): Use it.\n\nMon May  2 19:45:39 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree.cc (tree_for_command::eval): Handle returning,\n\tbreaking, and continuing for case of scalar expression in loop\n\tcontrol statement.\n\nWed Apr 20 00:38:26 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/lex.l (\\[{S}*): Don't return ',' for this\tmatch when\n\tconvert_spaces_to_comma is true, since that can never be the right\n\tthing to do.\n\n\t* All Makefile.in files: Set top_srcdir here.\n\t* Makeconf.in: Not here.\n\n\t* Makeconf.in: Use top_srcdir instead of root_srcdir\n\n\t* configure.in: Update for autoconf-1.8.  Use AC_VERBOSE for\n\tverbose messages.  Use AC_WARN and AC_ERROR instead of echo for\n\twarning and error messages.  Organize feature tests a bit better.\n\tUse new autoconf macros to check for C++ compiler.  Add copyright\n\tnotice.  Recognize --enable-dld instead of --with-dld since that\n\tseems to be more in line with the intent of the --enable/--with\n\toptions for configure scripts.  Use new autoconf macros\n\tAC_REVISION and AC_PREREQ.  Don't add -Wall to CFLAGS and CXXFLAGS\n\tuntil after all feature tests are done.  Etc.\n\nFri Apr 15 01:56:20 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* acconfig.h: Add #undefs for HAVE_FINITE, HAVE_ISINF, and\n\tHAVE_ISNAN.\n\t* configure.in: Check for floatingpoint.h.\n\t* src/sysdep.cc (sysdep_init): Disable trapping on common\n\texceptions for 386BSD systems that have floatingpoint.h.\n\n\t* src/utils.cc: Don't declare ioctl() with prototype.\n\nSat Apr  9 17:48:07 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tc-assign.cc (tree_constant_rep::fortran_style_matrix_assignment\n\t  (tree_constant&, tree_constant&)):\n\tHandle case of M (X) = scalar, where X is a zero-one vector with\n\tonly one nonzero element.\n\n\t* src/tc-assign.cc (tree_constant_rep::do_vector_assign\n\t  (tree_constant&, Range&):\n\tHandle case of right hand side being a scalar.\n\t(tree_constant_rep::do_vector_assign (tree_constant&, idx_vector&):\n\tDitto.\n\n\t* src/tc-assign.cc (tree_constant_rep::do_matrix_assignment\n\t  (int,tree_constant_rep::constant_type)):\n\tAllow assignment of complex scalar too.\n\t(tree_constant_rep::do_matrix_assignment\n\t  (tree_constant_rep::constant_type, int)):\n\tDitto.\n\n\t* src/tree-const.h (REP_RHS_MATRIX): Initialize nr and nc.\n\tAbort if rhs is not a real or complex matrix.\n\nWed Apr  6 13:59:37 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/Range.cc (Range::nelem_internal): Use an integer, not\n\ta double, for the number of intervals.\tAvoid possible problems\n\twith extended precision registers on some systems (e.g. x86/Linux).\n\nMon Mar 28 17:23:18 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/utils.cc (raw_mode): For OCRNL, ONOCR, and ONLRET, check to\n\tsee if they are defined before using them instead of checking to\n\tsee if NeXT is defined.\n\n\t* info/terminal.c (terminal_prep_terminal): Check to see if OCRNL\n\tis defined before using it instead of checking to see if NeXT is\n\tdefined.\n\nThu Mar 24 03:21:01 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree.cc (tree_parameter_list::define_from_arg_vector):\n\tNew function.\n\t(tree_parameter_list::convert_to_const_vector): Ditto.\n\t(tree_function::eval): Use them instead of trying to do this\n\tin-line.\n\n\t* src/symtab.h (symbol_record::global_link_context): New stack for\n\tsaving linked_to_global flag.\n\t* src/symtab.cc (symbol_record::push_context): Save\n\tlinked_to_global too.\n\t(symbol_record::pop_context): And restore it.\n\nWed Mar 23 16:18:19 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* doc/refcard.tex.in: New file.\n\t* doc/Makefile.in: Create refcard.* and refcard-local.* from\n\trefcard.tex.in.\n\nTue Mar 22 15:23:55 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.sh: exec $OCTAVE_HOME/bin/octave.bin, not just\n\toctave.bin.\n\nThu Mar 17 01:06:10 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/arith-ops.cc (do_binary_op (ComplexMatrix&, Matrix& b)):\n\tCorrectly handle element by element left division.\n\n\t* src/g-builtins.cc (builtin_error): Return without calling error\n\t(and setting error_state) if the message is empty.\n\n\t* src/help.cc (operators): Correct help message for `.^'.\n\n\t* src/tc-index.cc (tree_contant_rep::fortran_style_matrix_index):\n\tPreserve vector orientation when indexing with a zero-one vector.\n\n\t* src/tc-index.cc (tree_constant_rep::do_scalar_index): Handle\n\tindexing a scalar with `0'.\n\n\t* src/tc-index.cc (tree_constant_rep::do_scalar_index): Handle the\n\tindex `:' the same as the index `1'.\n\nTue Mar 15 17:22:00 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/Array.cc: Fix typo in comments about compiler flags.\n\nWed Mar  9 15:08:21 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 1.0.1.\n\n\t* src/*.h: Use the macro octave_FOO_h instead of _FOO_h to protect\n\tagainst multiple inclusion.\n\t* liboctave/*.h: Likewise.\n\n\t* liboctave/*.h: Surround contents of files in extern \"C++\" { }.\n\nTue Mar  8 18:06:54 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tc-index.cc (tree_constant_rep::do_vector_index (const\n\ttree_constant&) const): Don't crash if matrix is empty.\n\n\t* scripts/norm.m: Return empty matrix for empty argument.\n\nMon Mar  7 23:34:44 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* doinstall.sh: chmod new directories to 755.\n\nSat Mar  5 13:15:10 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* bsd-math/log1p.c: Declare finite as returning int, not double.\n\t* bsd-math/finite.c (finite): Add return type.\n\nThu Mar  3 14:42:00 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/DiagMatrix.cc (operator *): Provide definitions for\n\tDiagMatrix * DiagMatrix, ComplexDiagMatrix * ComplexDiagMatrix,\n\tComplexDiagMatrix * DiagMatrix, and DiagMatrix * ComplexDiagMatrix.\n\n\t* liboctave/ColVector.cc (operator >>): Provide definitions for\n\treal and complex column vectors.\n\n\t* liboctave/RowVector.cc (operator >>): Provide definitions for\n\treal and complex row vectors.\n\nWed Mar  2 18:00:47 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/Array.h (DiagArray::Proxy::operator & ()): Provide\n\tfunction body.\n\nTue Mar  1 13:18:35 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree-const.cc (tree_constant::load (istream&)): Don't skip\n\tpast first type keyword if not global.\n\t(tree_constant::load (istream&, tree_constant_rep::constant_type)):\n\tAllocate storage for reading complex scalar.\n\nSun Feb 20 14:17:47 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/menu.m: Don't fail on input that is empty or not a\n\tscalar.\n\n\t* Makefile.in (DISTFILES): Distribute ChangeLog.[0-9].\n\n\t* src/lex.l (reset_parser): Don't resynch line number to command\n\thistory number if reading a script file.\n\nThu Feb 17 01:36:19 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 1.0 released.\n\n\t* src/file-io.cc (fopen_file_for_user): Improve error message.\n\t(fopen_internal): Likewise.\n\nWed Feb 16 02:21:05 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Try harder to find finite, isnan, and isinf.\n\tUse m4 `dnl' comments, not shell `#' comments.\n\n\t* src/file-io.cc (file_io_get_file): New function.\n\t(fgets_internal): Use it instead of trying to do this in line.\n\t(frewind_internal, fseek_internal, ftell_internal, do_printf,\n\tdo_scanf): Likewise.\n\t* (do_scanf): Allow file name as string for fscanf.\n\t* (procss_scanf_format): Delete unused argument `args'.  Delete\n\tunused local variable `arg_type'.  Don't complain if we can't\n\tstore the result of a requested conversion.  Only return\n\tsuccessfully if a conversion actually occurs, even if we are not\n\tstoring the value.\n\nSun Feb 13 13:32:03 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.83 released.\n\n\t* Array.h (DiagArray): Move inline definitions of get() and set()\n\tbefore use by other inline functions.\n\nSat Feb 12 14:15:45 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Check for g77 last.  Even if it is ever actually\n\treleased, it probably won't be stable for quite a while.\n\n\t* MAKEINFO.PATCH: New file.\n\t* Makefile.in (DISTFILES): Distribute it.\n\n\t* liboctave/Matrix.cc (operator + (Complex, const Matrix&)):\n\tMake it work.\n\t(operator - (Complex, const Matrix&)): Ditto.\n\t(operator * (Complex, const Matrix&)): Ditto.\n\t(operator / (Complex, const Matrix&)): Ditto.\n\nFri Feb 11 00:03:39 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Check for strerror too.\n\n\t* configure.in: When saving CFLAGS as XCFLAGS and then restoring\n\tthe value, quote the RHS.\n\n\t* src/g-builtins.cc (builtin_clc): Do the dirty work to clear the\n\tscreen here instead of using rl_clear_screen to avoid printing\n\tprompt unnecessarily.\n\nThu Feb 10 00:26:32 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/utils.cc: Add all the cruft that the autoconf manual\n\tsuggests for including dirent.h.\n\n\t* info/terminal.c (terminal_prep_terminal): [HAVE_TERMIOS_H &&\n\tNeXT]: Don't use OCRNL, as someone says NeXT's termios.h doesn't\n\thave it.\n\n\t* configure.in (GCC_IEEE_FP_FLAG): Correct check for ix86 Linux.\n\tDon't try to check for CC == gcc.\n\tAdd GCC_IEEE_FP_FLAG to CFLAGS while checking for IEEE FP\n\tfunctions finite, isnan, and isinf.\n\n\t* readline/rldefs.h: Make definition of HAVE_POSIX_SIGNALS\n\tconditional on definition of _POSIX_VERSION, not HAVE_TERMIOS_H.\n\nWed Feb  9 02:41:32 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree.cc (tree_function::octave_va_start): Rename from\n\tva_start to avoid conflict with va_start macro.\n\t(tree_function::octave_var_arg): Likewise, rename from va_arg.\n\t* src/g-builtins.cc (builtin_va_arg): Call octave_va_arg for the\n\tcurrent function instead of va_arg.\n\t(builtin_va_start): Likewise, for octave_va_start.\n\n\t* Version 0.82.1.\n\n\t* doc/Makefile.in (clean): Also remove octave.in, octave.rd,\n\toctave.ins, and octave.rds.\n\n\t* src/t-builtins.cc (load_variable): Make it work for all\n\tcombinations of loading global or local variables when the\n\tvariable to be loaded is already a global variable, local\n\tvariable, a function, or even undefined.\n\nTue Feb  8 00:33:09 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.82 released.\n\n\t* liboctave/mx-kludge.cc (operator + (KL_MAT_TYPE, KL_MAT_TYPE)):\n\tFor an empty matrix with one nonzero dimension, be sure to return\n\ta result of the same size.\n\t(operator - (KL_MAT_TYPE, KL_MAT_TYPE)): Ditto.\n\t(product (KL_MAT_TYPE, KL_MAT_TYPE)): Ditto.\n\t(quotient (KL_MAT_TYPE, KL_MAT_TYPE)): Ditto.\n\nMon Feb  7 01:30:19 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/Array.h, liboctave/array.cc (DiagArray): Back off on\n\tindexing via Proxy class changes for AIX systems to avoid gcc (or\n\tpossibly AIX assembler?) bug.\n\n\t* src/tree-const.cc (tree_constant_rep::maybe_resize (int,\n\tforce_orient)): Don't abort for a max index of zero.\n\n\t* liboctave/Matrix.h (class RowVector, friend double operator *\n\t(const RowVector&, const ColumnVector&)): Add missing const in\n\tdeclaration.\n\n\t* liboctave/Matrix.cc (Matrix::fill (val, r1, c1, r2, c2)): Set nc\n\tto cols(), not rows().\n\t(ComplexMatrix::fill (double val, r1, c1, r2, c2)): Likewise.\n\t(ComplexMatrix::fill (Complex val, r1, c1, r2, c2)): Likewise.\n\n\t* All source files: To match the documenation, refer to function\n\tfiles, not M-files.  Rename functions and variables that refer to\n\t_m_file_,  mfile, or mf to refer to _fcn_file, ffile, or ff.\n\nSun Feb  6 19:08:26 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/parse.y (yyerror): Don't crash if a parse error happens and\n\tthe current input line is NULL.\n\nSat Feb  5 18:53:04 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/file-io.cc (initialize_file_io): Don't use variable names\n\tthat start with `_'.\n\t* src/file-io.cc (class file_info): Likewise.\n\nFri Feb  4 01:15:59 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/builtins.cc (general_functions): In usage message for fopen,\n\tuse `Valid' instead of `Legal'.\n\n\t* src/file-io.cc (do_printf): Use `invalid' instead of `illegal'\n\tin error message.\n\t(do_scanf): Likewise.\n\n\t* src/mappers.cc (atanh): Use correct formula.\n\nThu Feb  3 22:08:40 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* doc/refcard.tex: New file.\n\t* doc/Makefile.in (all): Make refcard.ps.\n\t(DISTFILES): Distribute refcard.tex, refcard.dvi, and refcard.ps.\n\n\t* src/tree-const.cc (any_element_is_negative): Delete function.\n\t(any_element_less_than): New function.\n\t(any_element_greater_than): Ditto.\n\t(tree_constant_rep::mapper): Use struct elements lower_limit,\n\tupper_limit, and can_return_complex_for_real_arg to properly\n\thandle functions like acos, asin, atanh, and acosh.\n\n\t* src/builins.h (struct Mapper_fcn): Rename neg_arg_complex to\n\tcan_return_complex_for_real_arg.  New elements, lower_limit and\n\tupper_limit.\n\t(struct builtin mappers functions): Rename neg_arg_complex to\n\tcan_return_complex_for_real_arg.  New elements, lower_limit and\n\tupper_limit.  Delete elements nargin_max and nargout_max.\n\t* src/variables.cc (install_builtin_mapper_function): Handle new\n\tstruct elements can_return_complex_for_real_arg, lower_limit, and\n\tupper_limit.  Don't use nargin_max and nargout_max -- they are\n\tthe same for all mapper functions.\n\nWed Feb  2 05:06:56 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/Matrix.h: Don't include values.h.\n\t* liboctave/Matrix-ext.cc: Include float.h\n\t(DET::value_will_overflow): Use DBL_MAX, not MAXDOUBLE.\n\t(ComplexDET::value_will_overflow): Likewise.\n\t(DET::value_will_underflow): Use DBL_MIN, not MINDOUBLE.\n\t(ComplexDET::value_will_underflow): Likewise.\n\t* src/tree.cc: Include limits.h, not values.h.\n\t(tree_builtin::max_expected_args): Use INT_MAX, not MAXINT.\n\n\t* configure.in: If compiling on an ix86, set GCC_IEEE_FP_FLAG to\n\t-mieee-fp.  We should no longer require the modified crt0 code on\n\tLinux systems in order to get IEEE functions.\n\t* Makeconf.in (GCC_IEEE_FP_FLAG): Substitute value.\n\t(ALL_CFLAGS, UGLY_ALL_CFLAGS, ALL_CXX_FLAGS, UGLY_ALL_CXX_FLAGS,\n\tALL_LDFLAGS): Use it.\n\nTue Feb  1 22:30:46 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/builtins.cc (install_builtins): Make SEEK_SET, SEEK_CUR, and\n\tSEEK_END constants.\n\n\t* src/tree-plot.cc (tree_subplot_using::print): Only check column\n\tnumber against max if max is greater than 0.\n\nMon Jan 31 15:59:31 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/strcmp.m: Correctly handle empty strings.\n\n\t* src/parse.y (input): Recognize lone simple_list and simple_list\n\tfollowed by error and '\\n'.\n\nFri Jan 28 00:20:30 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.81 released.\n\n\t* src/octave.cc (clean_up_and_exit): Call cleanup_tmp_files() here\n\ttoo.\n\n\t* configure.in: Check for atexit and on_exit.\n\t* src/octave.cc: Use HAVE_ATEXIT and HAVE_ON_EXIT (instead of\n\tjust checking to see if sun is defined) to decide whether to\n\tdefine atexit as on_exit.\n\t(main): Don't try to call atexit if it's missing and we don't have\n\ton_exit either.\n\nThu Jan 27 22:16:48 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Check for gethostname and sys/utsname.h.\n\t* utils.cc (gethostname): Steal replacement from bash.  Provide\n\tdefinition if it looks like it's missing and we have\n\tsys/utsname.h.\n\n\t* liboctave/Array.h (DiagArray): Define non-const indexing\n\tfunctions here.\n\t* liboctave/Array.cc (DiagArray): Not here.\n\n\t* liboctave/Array.h (DiagArray::Proxy): New class to handle\n\tnon-const reference indexing.  Allows different action if indexing\n\ton left side of assignment operator.\n\n\t* src/octave.cc (main): Call initialize_pager(),\n\tinitialize_readline(), and install_signal_handlers() before trying\n\tto read startup files.\n\n\t* src/octave.cc (input_from_startup_file): New global flag.\n\t(execute_startup_files): Set it to 1 before reading startup files.\n\t* src/parse.y (func_def_2): If input_from_startup_file, don't try\n\tto compare file name and function name.\n\nWed Jan 26 14:39:27 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* readline/rldefs.h: Make better use of autoconf defines.\n\nTue Jan 25 17:19:19 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/Matrix.cc (ComplexMatrix (DiagMatrix)): Make sure off\n\tdiagonal elements are zero.\n\t(ComplexMatrix (ComplexDiagMatrix): Likewise.\n\t(Matrix (DiagMatrix): Likewise.\n\nFri Jan 21 17:43:11 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* flibs.sh: Recognize libraries that match `/*.a'.\n\nThu Jan 20 18:12:01 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.80.1.\n\nWed Jan 19 14:48:27 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* libcruft/odepack/stode.f: Don't try to `RETURN 0'.  This causes\n\tlsode to fail, at least with Sun's f77.\n\n\t* src/tree-const.cc (tree_constant_rep::load): Delete string\n\treturned from extract_keyword.\n\t* src/t-builtins.cc (builtin_load): Likewise.\n\t* src/variables.cc (extract_keyword): Return new storage, not\n\tstatic buffer.\n\n\t* src/t-builtins.cc (builtin_save): If saving a named list of\n\tvariables, use is_globally_visible to decide whether to mark\n\tvariables in the current symbol table as global.\n\nTue Jan 18 11:57:03 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.80 released.\n\n\t* doc/Makefile.in (install): Delete commands for installing\n\tliboctave.info instead of trying to comment them out.\n\n\t* liboctave/Array.cc: Allow users to compile with\n\t-fexternal-stemplates and USE_EXTERNAL_TEMPLATES defined to\n\tgenerate their own .o files with new types.\n\n\t* Makeconf.in (includedir): Install include files in\n\t$prefix/include/octave by default.\n\n\t* liboctave/Makefile.in (TEMPLATE_SRC): New macro.\n\t(install): Install files listed in $(TEMPLATE_SRC) too.\n\n\t* info/search.h: Conditionally declare stricmp and strnicmp.\n\t* info/search.c: Conditionally define stricmp and strnicmp.\n\t* config.h.in: Add undefs for HAVE_STRICMP and HAVE_STRNICMP.\n\n\t* configure.in: Check for stricmp and strnicmp too.\n\n\t* doc/Makefile.in: For now, don't format or try to install the\n\tliboctave manual.\n\tDon't distribute formatted copies of liboctave manual.\n\nMon Jan 17 01:10:54 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* doc/Makefile.in (clean): Remove all index files.\n\n\t* src/Makefile.in (defaults.h): Depend on Makefile too.\n\t* doc/Makefile.in (conf.texi): New rule for making conf.texi from\n\tconf.texi.in.\n\n\t* doc/conf.texi.in: New file.\n\t* doc/octave.texi: Include conf.texi to get VERSION, OCTAVE_HOME,\n\tand other variables that need to be set depending on the\n\tconfiguration.\n\n\t* Makefile.in (DISTFILES): Don't distribute PLOTTING.  Current\n\tplotting info is in the Texinfo docs.\n\nSat Jan 15 15:43:34 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* config.sub: New file, from libg++-2.5.2.\n\t* Makefile.in: Distribute config.sub.\n\t* configure.in: Use config.sub to validate system types.  If it\n\tfails, continue with target_host_type and canonical_host_type set\n\tto unknown.  Leave target_host_type set to any alias given as the\n\tTARGET argument to configure.\n\n\t* readline/rldefs.h: If ultrix and HAVE_SGTTY_H, avoid Posix\n\tterminal driver.\n\t* configure.in: If configuring for ultrix, check for sgtty first.\n\tIf not found, go ahead and check for Posix terminal driver.\n\n\t* configure.in: Don't try to do anything special for readline on\n\tNeXT systems.\n\n\t* Makeconf.in: Define rules for making .d files here.\n\tliboctave/Makefile.in: Not here.\n\tsrc/Makefile.in: Or here.\n\n\t* liboctave/Matrix.h (all Matrix/Vector operator = functions):\n\tSimply call the base class operator =, then return *this.\n\t(class ColumnVector): Declare RowVector a friend class, so it can\n\taccess the private constructor for the transpose operator.\n\t(class RowVector): Likewise, for ColumnVector.\n\t(class ComplexColumnVector): Likewise, for CommplexRowVector.\n\t(class ComplexRowVector): Likewise, for ComplexColumnVector.\n\tNumerous formatting cleanups.\n\nThu Jan 13 13:17:47 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.79.90.\n\n\t* builtins.cc: Include missing-math.h.\n\n\t* src/missing-math.h: Provide declarations for acosh, asinh,\n\tatanh, and gamma whether they are actually missing or not, because\n\tthey are not part of the standard math.h, and the g++/libg++\n\tinstallation no longer provides declarations for them.\n\n\t* src/sighandlers.h (RETSIGTYPE): Define here.\n\t(BADSIG): Likewise.\n\t(sig_handler): Likewise.\n\n\t* src/g-builtins.cc: Include sighandlers.h\n\tDon't define RETSIGTYPE, BADSIG, or sig_handler here.\n\t* src/octave.cc: Or here.\n\nWed Jan 12 16:12:27 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/g-builtins.cc: Don't check nargin/nargout in *_options\n\tfunctions.\n\n\t* src/f-qpsol.cc, src/f-quad.cc, src/f-lsode.cc, src/f-fsolve.cc,\n\tsrc/f-dassl.cc, liboctave/QPSOL.cc, liboctave/Quad.cc,\n\tliboctave/ODE.cc, liboctave/NLEqn.cc, liboctave/DAE.cc:\n\tSimilar changes for these classes/functions as the following\n\tchanges for src/f-npsol.cc and liboctave/NPSOL.cc:\n\n\t* src/f-npsol.cc (npsol_opts): New static variable to hold Octave's\n\tcurrent idea of npsol options.\n\t(npsol): Call nlp.copy (npsol_opts) after creating NPSOL object.\n\t(npsol_option_table): New static list of options for npsol.\n\t(print_npsol_option_list): New function.\n\t(do_npsol_option): New function.\n\t(npsol_options): Make it work.\n\n\t* liboctave/NPSOL.cc (NPSOL_options): New class.\n\t* (NPSOL): Also derive from NPSOL_options.\n\t* (minimize): Call pass_options_to_npsol before calling npsol.\n\t* (NPSOL::option): No longer works.  Print error message instead.\n\t* (NPSOL::set_default_options): Now a member of NPSOL_options class.\n\n\t* src/utils.cc: If missing, declare strcasecmp, strncasecmp.\n\t* (almost_match): Add new argument to do case-insensitive matches.\n\t* (keyword_almost_match): New function to match a string against a\n\tlist of keywords.\n\n\t* liboctave/NLP.h (NLP): Add destructor and copy constructor.\n\n\t* configure.in: Check for strcasecmp and strncasecmp.\n\t* config.h.in: Add #undefs for HAVE_STRCASECMP and STRNCASECMP.\n\t* src/strcasecmp.c, src/strncase.c: New files, from glibc.\n\t* src/Makefile.in (SOURCES, OBJECTS): List them.\n\n\t* src/builtins.cc (general_functions): Improve usage message for\n\tthe *_options functions.\n\t(print_usage): New arg, just_usage with default value of 0.\n\tIf nonzero, don't print info about where to find additional help.\n\n\t* src/Makefile.in (INCLUDES): Add error.h.\n\t(SOURCES): Add error.h.\n\n\t* src/tree.cc (tree_identifier::parse_m_file): call reset_parser\n\tbefore calling yyparse ().\n\t* src/tc-extras.cc (eval_string): Likewise.\n\tDon't save previous symbol table.  That is handled by the\n\tunwind protect.\n\n\t* src/lex.l (reset_parser): Don't unconditionally call yyreset.\n\tAdd a couple of comments.\n\t(yywrap): Always return 1, not 0.\n\t(yy_flex_alloc, yy_flex_realloc, yy_flex_free): #if 0 out.\n\n\t* src/utils.cc (raw_mode): Only complain about stdin not being a\n\ttty if we are really interactive.\n\n\t* src/octave.cc (main): End startup message with endl to ensure\n\tflushing before other output.\n\t* Turn of readline's blink_matching_paren feature if not\n\tinteractive, or if reading from a file specified on the command\n\tline.\n\n\t* src/octave.cc (main): Set the symbol table context just before\n\tcalling reset_parser in the main loop.\n\t* src/lex.l (reset_parser): Not here.\n\n\t* src/input.cc (octave_gets): Declare static.\n\t(octave_read): Also handle echoing input if not using readline.\n\n\t* Makefile.in (DISTFILES): Add SENDING-PATCHES to the list.\n\nMon Jan 10 14:30:13 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/corrcoef.m, scripts/fortran_vec.m, scripts/kurtosis.m,\n\tscripts/ols.m, scripts/skewness.m, scripts/cov.m, scripts/gls.m,\n\tscripts/mahalanobis.m, scripts/pinv.m: New script files from Kurt\n\tHornik (hornik@neuro.tuwien.ac.at) and the Department of\n\tProbability Theory and Statistics TU Wien, Austria.\n\nSun Jan  9 01:11:05 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/g-builtins.cc (builtin_fsqp_options): If FSQP_MISSING is\n\tdefined, don't call fsqp_options; just print usage message.\n\t(builtin_npsol_options): Likewise, for npsol_options.\n\t(builtin_qpsol_options): Likewise, for qpsol_options.\n\t* src/builtins.cc (general_functions): Provide different usage\n\tmessage for fsqp_options depending on whether FSQP_MISSING is\n\tdefined.  Likewise for npsol_options and qpsol_options.\n\nSat Jan  8 16:45:57 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* libcruft/misc/dostop.c: Include config.h.\n\n\t* src/variables.cc (extract_keyword): Use ostrstream instead of\n\tfixed length buffer.  For keywords with string values, return\n\tvalue in static buffer.\n\t* src/t-builtins.cc (builtin_load): Handle new argument list for\n\textract_keyword.  Handle possiblity of load_variable setting\n\terror_state.\n\t* src/tree-const.cc (tree_constant_rep::load): Handle new argument\n\tlist for extract_keyword.\n\nFri Jan  7 13:20:47 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/f-eig.cc (builtin_eig_2): Rename from builtin_eig.\n\t* src/f-fsolve.cc (builtin_fsolve_2): Rename from builtin_fsolve.\n\t* src/f-inv.cc (builtin_inv_2): Rename from builtin_inv.\n\nThu Jan  6 12:29:41 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree-base.h (tree::save): Add optional argument `precision'.\n\t* src/tree-const.cc (tree_constant::save): Ditto.\n\t(tree_constant_rep::save): Ditto.\n\t* src/symtab.cc (symbol_def::save): Ditto.\n\t(symbol_record::save): Ditto.\n\t(symbol_table::save): Ditto.\n\n\t* src/t-builtins.cc (builtin_save): Pass user_pref.save_precision\n\tto symbol table save functions.\n\t* src/builtns.cc (string_variables): Add save precision to thelist.\n\t(install_builtins): Initialize it.\n\t* src/user-prefs.cc (set_save_precision): New function.\n\t* src/user-prefs.h (user_pref.save_precision): New data element.\n\n\t* liboctave/Matrix-ext.cc: Provide correct prototypes for dgeesx\n\tand zgeesx.\n\t* (SCHUR::init): Don't declare a dummy_select function pointer,\n\tjust pass `(void *) 0' instead, since the dummy argument is never\n\tsupposed to be used anyway.\n\n\t* src/input.cc (initialize_readline): Cast command_completer to\n\tCPPFunction, not Function, now that readline has more than one\n\tfunction typedef.\n\t* Add extern declaration for free_undo_list ().\n\n\t* Replace readline source from GDB with readline source from bash.\n\tThis allows paren matching.\n\nWed Jan  5 01:20:26 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Also check for sys/select.h.\n\n\t* liboctave/RowVector.cc (ComplexRowVector::operator *): Complete\n\tfunction body.  Put code in-line rather than making a call to the\n\tBLAS routine zdotu to avoid having to cope with the various ways\n\tthat Fortran compilers might translate this.\n\n\t* src/input.cc (operate_and_get_next): New function, from bash.\n\t(initialize_readline): Bind operate_and_get_next to C-O here.\n\n\t* src/input.cc (command_completer, command_generator):\n\tDeclare static here.\n\t* srs/input.h (command_completer, command_generator):\n\tNot extern here.\n\n\t* g-builtins.cc (builtin_warranty): Change copyright info.\n\t* octave.cc (verbose_usage): Likewise.\n\t(main): Likewise.\n\nMon Jan  3 15:49:41 1994  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/fnmatch.c, src/fnmatch.h: New files for pattern matching\n\tfrom the GNU C library.\n\t* src/Makefile.in: Add them to the appropriate lists.\n\t* src/t-builtins.cc (builtin_save): Use fnmatch to do pattern\n\tmatching instead of using regular expressions.\n\t(builtin_clear): Likewise.\n\t(glob_pattern_p): New function.\n\t(builtin_save): Print error message and return if only given one\n\targument that contains globbing characters.\n\n\t* src/symtab.cc (symbol_record::save): Don't attempt to save\n\tundefined variables.\n\nWed Dec 29 02:55:08 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/rank.m: Also need to compute SVD when nargin == 2.\n\tCorrect usage message.\n\nWed Dec 15 01:44:18 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/f-lpsolve.cc, src/f-fsqp.cc, src/f-npsol.cc, src/f-qpsol.cc,\n\tsrc/f-lsode.cc, src/f-dassl.cc, src/f-fsolve.cc, src/f-quad.cc:\n\tNew stub options functions, XXX_options, and XXX_options_2 (for\n\tfuture dld use), where XXX is lpsolve, fsqp, npsol, etc.\n\t* src/f-lpsolve.h, src/f-fsqp.h, src/f-npsol.h, src/f-qpsol.h,\n\tsrc/f-lsode.h, src/f-dassl.h, src/f-fsolve.h, src/f-quad.h:\n\tDeclare XXX_options functions.\n\t* src/builtins.cc (builtin_general_functions): Add new XXX_options\n\tfunctions to the list of builtin functions.\n\t* src/g-builtins.cc: Define builtin_XXX_options functions.\n\t* src/g-builtins.h: Declare them.\n\n\t* scripts/tzero.m: Add missing comma in fprintf call.\n\nTue Dec 14 00:24:35 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* libcruft/quadpack/*.f: Modify to handle user-requested\n\ttermination from inside the user-supplied function.\n\t* src/f-quad.cc (quad_user_function): Set quad_integration_error\n\tif an error is encountered in the user-supplied function.\n\t* liboctave/Quad.h (quad_integration_error): New global variable.\n\t* liboctave/Quad.cc (user_function): Handle\n\tquad_integration_error, and error flag for modified Quadpack\n\tfunctions.\n\n\t* src/tree.cc (tree_simple_assignment_expression::eval): Check\n\terror status after calling convert_to_const_vector () on the\n\targument list.\n\t(tree_index_expression::eval): Ditto.\n\n\t* src/tree.cc (tree_argument_list::convert_to_const_vector):\n\tIf an error is encountered while evaluating an element of the\n\tlist, print an error message including the element number.\n\n\t* liboctave/ODE.cc (integration_error): New private data member.\n\t(ODE constructors): Initialize it to zero.\n\t(ODE::integrate (double)): Reset it to zero before each\n\tintegration step.\n\t(lsode_f): Treat empty vector returned from user-supplied function\n\tas an error.\n\t* src/f-lsode.cc (lsode_user_function): Return empty vector if\n\terror is encountered in user-supplied function.  Don't jump to top\n\tlevel on error.\n\n\t* libcruft/odepack/lsode.f (lsode): Return with istate = -13 on\n\terror from user supplied subroutine.\n\t* libcruft/odepack/lsode.f (lsode): Handle extra argument returned\n\tfrom user-supplied function.\n\t* libcruft/odepack/stode.f (stode): Likewise.\n\t* libcruft/odepack/prepj.f (prepj): Likewise.\n\nWed Dec  8 01:30:57 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/DAE.cc (integration_error): New private data member.\n\t(DAE constructors): Initialize it to zero.\n\t(DAE::integrate (double)): Reset it to zero before each\n\tintegration step.\n\t(dassl_f): Treat empty vector returned from user-supplied function\n\tas an error.\n\t* src/f-dassl.cc (dassl_user_function): Return empty vector if\n\terror is encountered in user-supplied function.  Don't jump to top\n\tlevel on error.\n\n\t* liboctave/NPSOL.cc (npsol_objective_error): New global variable.\n\t(npsol_objfun): Set to zero before calling user-supplied function.\n\tCheck after calling user-supplied function.\n\tSet mode to -1 on error.\n\t(npsol_confun): Set mode to -1 on error.\n\t(npsol declaration): Declare args for user-supplied functions.\n\t* src/f-npsol.cc (npsol_objective_function): If an error is\n\tencountered in the calculation of the objective function, set\n\tnpsol_objective_error to 1.\n\t(npsol_constraint_function): Treat empty vector returned from\n\tuser-supplied function as an error.\n\n\t* liboctave/Array.cc (*::checkelem): Correct bounds checking.  On\n\terror, return uninitialized value of type T.  This avoids placing\n\tan extra requirement on the class that can be used as an array\n\telement.\n\t(*::operator ()): Likewise.\n\nMon Dec  6 07:24:49 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/NLEqn.cc (hybrd1 declaration): Declare args for\n\tuser-supplied fuction.\n\t(hybrj1): Likewise.\n\t(hybrd1_fcn): Treat return of empty vector from user supplied\n\tfunction as an error by setting iflag to -1.\n\t(hybrj1_fcn): Likewise.\n\t(solve): Handle case of info < 0 returned from hybrd1.\n\n\t* src/f-fsolve.cc (fsolve_user_function): Don't jump to top level\n\ton error in user-supplied function.  Treat empty vector returned\n\tfrom user-supplied function as error.\n\t(hybrd_info_to_fsolve_info): Translate -1 (failure in evaluation\n\tof user-supplied function) to -2.\n\t* scripts/perror.m (fsolve case): Handle -2.\n\n\t* info/error.c (program_name): Initialize to info, not NULL.\n\n\t* info/session.c (initialize_info_session): Don't exit if term is\n\ttoo dumb or too small to use info.  Return int status instead.\n\t* info/info.h (TERM_TOO_SMALL): New macro.\n\n\t* src/t-buitlins.cc (try_info): Check return value from\n\tinitialize_info_session ().\n\n\t* liboctave/Array.cc (DiagArray<T>::DiagArray (int n, const T& val)):\n\tSet number of rows and columns to n, not 0.\n\nSat Dec  4 14:01:41 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/lex.h (YY_INPUT): Undefine if defined, then always define\n\tthe way we want.\n\t(YY_FATAL_ERROR): Likewise.\n\n\t* src/lex.l (yywrap): Declare static.\n\t(yy_flex_alloc): New function, so we don't have to link with\n\tlibfl.a when using flex 2.4.x.\n\t(yy_flex_realloc): Ditto.\n\t(yy_flex_free): Ditto.\n\nThu Dec  2 19:23:43 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/*.m: Add copying notice to script files.\n\n\t* src/input.cc (command_generator): Return copy of matching string.\n\n\t* src/input.cc (command_generator): Correctly delete array of\n\tcharacter strings.\n\t* src/symtab.cc (symbol_table::save): Likewise.\n\t* src/utils.cc (pathstring_to_vector): Likewise.\n\n\t* src/utils.cc (get_m_file_names): When reallocating vector of\n\tstrings, delete original vector of pointers, but not the strings\n\tthey point to.\n\nTue Nov 30 12:36:41 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/RowVector.cc, liboctave/ColVector.cc,\n\tliboctave/DiagMatrix.cc, liboctave/Matrix.cc,\n\tliboctave/Matrix-ext.cc: Massive rewrite to cope with new\n\tderivation scheme.\n\n\t* liboctave/Matrix.h: Include Array.h, and derive Matrix,\n\tComplexMatrix, etc. from Array<double>.  Derive Complex\n\tversions from Array<Complex>.  Delete declarations of functions\n\tnow inherited from the Array classes.\n\t* Include mx-kludge.h with appropriate #defines in each class that\n\tneeds it.\n\t* liboctave/Matrix.cc: Include mx-kludge.cc with appropriate\n\t#defines in each class that needs it.\n\n\t* liboctave/Makefile.in (INCLUDES): Add Array.h, MArray.h, and\n\tmx-kludge.h.\n\t(SOURCES): Add Array.cc.\n\t(EXTRAS): Add MArray.cc and mx-kludge.cc.\n\n\t* liboctave/mx-kludge.h, liboctave/mx-kludge.cc: New files to\n\timplement the MArray functionality with macros until g++ can\n\thandle the MArray stuff.\n\n\t* liboctave/MArray.h, liboctave/MArray.cc: New files for generic\n\tarrays with simple math functions for like-types.  This won't\n\tquite work with g++ yet, so it's not used anywhere.\n\n\t* liboctave/Array.h, liboctave/Array.cc: New files for generic\n\tarrays.\n\n\t* liboctave/mx-inlines.cc: Add const for const arguments.\n\n\t* src/file-io.cc (file_info): Rename class from File_info.\n\t(file_info::operator =): Fix memory leak by deleting old name\n\tand mode before saving new.  Don't do copy if source and\n\tdestination are the same.\n\n\t* src/tree.cc (tree_matrix::eval): Plug memory leak.\n\n\t* src/tree.cc (tree_builtin::tree_builtin): Check to see that nm,\n\tnot my_name, is non-NULL before saving it.\n\n\t* src/tree.cc (tree_identifier::eval, tree_gobal_command::eval):\n\tAfter performing the assignment, delete the identifier created\n\tfor temporary asssignment since the destrucotr for\n\ttree_simple_assignment_expression doesn't do it for us.\n\n\t* src/tree.cc (tree_function::stash_m_file_name): Delete file_name\n\tbefore saving it.\n\t(tree_function::stash_function_name): Likewise, for fcn_name.\n\n\t* src/lex.l, src/lex.h: Make quote_is_transpose globally visible.\n\t* src/parse.y (param_list): Use it, and recognize empty parameter\n\tlists here.\n\n\t* src/parse.y (simple_expr1): Recognize empty matrices here.\n\t(matrix): Not here.\n\n\t* src/arith-ops.cc (do_binary_op): The matrix product and quotient\n\tfunctions aren't class member functions now.\n\n\t* src/tc-index.cc, src/tc-assign.cc, src/symtab.cc,\n\tsrc/tree-plot.cc, src/idx-vector.cc, src/tree-const.cc:\n\tCall ::error, not just error, since g++ now complains about not\n\tbeing able to find a non-hidden member function by that name.\n\n\t* src/tree-const.cc: Call ::real and ::imag, not just real and imag,\n\tsince g++ now complains about not being able to find non-hidden\n\tmember functions by those names.\n\n\t* src/tree-const.cc (tree_constant_rep::force_numeric): Handle case\n\tof zero-length strings.\n\n\t* src/tree-const.cc (tree_constant_rep::convert_to_str): Null\n\tterminate strings created from scalars.\n\n\t* src/tc-index.cc (tree_constant_rep::fortran_style_matrix_index): Use\n\tdata(), not fortran_vec().\n\t* src/idx-vector.cc (idx_vector::idx_vector): Likewise.\n\n\t* src/SLStack.cc: Move function definitions here.\n\t* src/SLStack.h: From here.  Include SLStack.cc if not using\n\texternal templates.\n\n\t* src/unwind-prot.h: Move class declaration here.\n\t* src/unwind-prot.cc: From here.\n\n\t* src/xdiv.h, src/xpow.h, src/variables.h, src/utils.h,\n\tsrc/user-prefs.h, src/t-builtins.h, src/sighandlers.h,\n\tsrc/pr-output.h, src/pager.h, src/octave-hist.h, src/mappers.h,\n\tsrc/input.h, src/help.h, src/gripes.h, src/g-builtins.h,\n\tsrc/f-syl.h, src/f-svd.h, src/f-schur.h, src/f-rand.h,\n\tsrc/f-qzval.h, src/f-quad.h, src/f-qr.h, src/f-qpsol.h,\n\tsrc/f-npsol.h, src/f-lu.h, src/f-lsode.h, src/f-lpsolve.h,\n\tsrc/f-inv.h, src/f-ifft.h, src/f-hess.h, src/f-givens.h,\n\tsrc/f-fsqp.h, src/f-fsolve.h, src/f-fft.h, src/f-expm.h,\n\tsrc/f-eig.h, src/f-det.h, src/f-dassl.h, src/f-colloc.h,\n\tsrc/f-chol.h, src/f-balance.h, src/error.h, src/dynamic-ld.h,\n\tsrc/builtins.h, src/arith-ops.h, src/tree-const.h, src/tree.h,\n\tsrc/token.h, src/symtab.h, src/procstream.h, src/idx-vector.h,\n\tsrc/file-io.h, src/tree-base.h, src/unwind-prot.h, src/Stack.h,\n\tliboctave/LinConst.h, liboctave/FEGrid.h, liboctave/NLEqn.h,\n\tliboctave/NLConst.h, liboctave/LPsolve.h, liboctave/LP.h,\n\tliboctave/FSQP.h, liboctave/DAEFunc.h, liboctave/DAE.h,\n\tliboctave/CollocWt.h, liboctave/Bounds.h, liboctave/Objective.h,\n\tliboctave/ODEFunc.h, liboctave/NLFunc.h, liboctave/Range.h,\n\tliboctave/Quad.h, liboctave/QP.h, liboctave/QPSOL.h,\n\tliboctave/QLD.h, liboctave/NPSOL.h, liboctave/NLP.h,\n\tliboctave/f77-uscore.h, liboctave/lo-error.h,\n\tliboctave/Matrix.h:\n\tDon't use #pragma interface.\n\n\t* src/tc-index.cc, src/tc-assign.cc, src/symtab.cc,\n\tsrc/procstream.cc, src/gripes.cc, src/f-syl.cc, src/f-svd.cc,\n\tsrc/f-schur.cc, src/f-rand.cc, src/f-quad.cc, src/f-qr.cc,\n\tsrc/f-qpsol.cc, src/f-npsol.cc, src/f-lu.cc, src/f-lsode.cc,\n\tsrc/f-lpsolve.cc, src/f-inv.cc, src/f-ifft.cc, src/f-hess.cc,\n\tsrc/f-givens.cc, src/f-fsqp.cc, src/f-fsolve.cc, src/f-fft.cc,\n\tsrc/f-eig.cc, src/f-det.cc, src/f-dassl.cc, src/f-colloc.cc,\n\tsrc/f-chol.cc, src/f-balance.cc, src/t-builtins.cc,\n\tsrc/octave-hist.cc, src/input.cc, src/g-builtins.cc,\n\tsrc/xdiv.cc, src/xpow.cc, src/user-prefs.cc, src/unwind-prot.cc,\n\tsrc/tree-plot.cc, src/token.cc, src/tc-extras.cc, src/sysdep.cc,\n\tsrc/sighandlers.cc, src/pr-output.cc, src/pager.cc,\n\tsrc/mappers.cc, src/idx-vector.cc, src/help.cc, src/f-qzval.cc,\n\tsrc/f-expm.cc, src/error.cc, src/dynamic-ld.cc, src/builtins.cc,\n\tsrc/arith-ops.cc, src/variables.cc, src/utils.cc,\n\tsrc/tree-const.cc, src/file-io.cc, src/tree.cc,\n\tliboctave/sun-utils.cc, liboctave/mx-inlines.cc,\n\tliboctave/RowVector.cc, liboctave/ColVector.cc,\n\tliboctave/DiagMatrix.cc, liboctave/Matrix.cc,\n\tliboctave/Matrix-ext.cc, liboctave/Quad.cc, liboctave/ODE.cc,\n\tliboctave/LPsolve.cc, liboctave/FSQP.cc, liboctave/DAE.cc,\n\tliboctave/DAEFunc.cc, liboctave/QP.cc, liboctave/Objective.cc,\n\tliboctave/ODEFunc.cc, liboctave/NLFunc.cc, liboctave/NLConst.cc,\n\tliboctave/LP.cc, liboctave/lo-error.cc, liboctave/Range.cc,\n\tliboctave/QPSOL.cc, liboctave/NPSOL.cc, liboctave/NLEqn.cc,\n\tliboctave/Matrix.cc, liboctave/Matrix-ext.cc,\n\tliboctave/LinConst.cc, liboctave/FEGrid.cc,\n\tliboctave/DiagMatrix.cc, liboctave/CollocWt.cc,\n\tliboctave/ColVector.cc, liboctave/Bounds.cc:\n\tDon't use #pragma implementation.\n\n\t* src/lex.l, src/parse.y, src/procstream.cc, src/gripes.cc,\n\tsrc/f-syl.cc, src/f-svd.cc, src/f-schur.cc, src/f-rand.cc,\n\tsrc/f-quad.cc, src/f-qr.cc, src/f-qpsol.cc, src/f-npsol.cc,\n\tsrc/f-lu.cc, src/f-lsode.cc, src/f-lpsolve.cc, src/f-inv.cc,\n\tsrc/f-ifft.cc, src/f-hess.cc, src/f-givens.cc, src/f-fsqp.cc,\n\tsrc/f-fsolve.cc, src/f-fft.cc, src/f-eig.cc, src/f-det.cc,\n\tsrc/f-dassl.cc, src/f-colloc.cc, src/f-chol.cc,\n\tsrc/f-balance.cc, src/t-builtins.cc, src/octave-hist.cc,\n\tsrc/input.cc, src/g-builtins.cc, src/xdiv.cc, src/xpow.cc,\n\tsrc/user-prefs.cc, src/unwind-prot.cc, src/tree-plot.cc,\n\tsrc/token.cc, src/tc-extras.cc, src/sysdep.cc,\n\tsrc/sighandlers.cc, src/pr-output.cc, src/pager.cc,\n\tsrc/mappers.cc, src/idx-vector.cc, src/help.cc, src/f-qzval.cc,\n\tsrc/f-expm.cc, src/error.cc, src/dynamic-ld.cc, src/builtins.cc,\n\tsrc/arith-ops.cc, src/variables.cc, src/utils.cc,\n\tsrc/tree-const.cc, src/file-io.cc, src/tree.cc: If HAVE_CONFIG_H\n\tis defined, include config.h.\n\n\t* config.h.in, acconfig.h: New files\n\t* Makefile.in (DISTFILES): Add them to the list.\n\n\t* Makeconf.in (root_srcdir): Define.\n\t(INCFLAGS): Clean up.\n\t(UGLY_ALL_CFLAGS): New macro.\n\t(UGLY_ALL_CXXFLAGS): Likewise.\n\t(UGLY_ALL_LDFLAGS): Likewise.\n\n\t* configure.in: Convert to generate config.h.\n\tSubstitute root_srcdir in Makefiles.\n\tUse AC_DEFINE(foo, 1) instead of DEFS=\"$DEFS -Dfoo=1\".\n\tIf using g++ 2.5 or later, define USE_EXTERNAL_TEMPLATES.\n\tUse UGLY_DEFS for what would have been substited in DEFS, for\n\tthose cases when we need DEFS instead of config.h.\n\nTue Nov 16 04:59:19 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/f-expm.cc, src/f-givens.cc, src/f-qzval.cc, src/f-syl.cc:\n\tInclude f77-uscore.h here.\n\n\t* liboctave/ColVector.cc, liboctave/Matrix.cc,\n\tliboctave/Matrix-ext.cc, liboctave/RowVector.cc: Move declarations\n\tfor Fortran functions here.\n\t* liboctave/Matrix.h: From here. Don't include f77-uscore.h here.\n\nMon Nov 15 04:03:34 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tc-extras.cc (min): For two-arg versions, use error(), not\n\tFAIL.\n\t(max): Likewise.\n\t* src/idx-vector.cc (checkelem): Likewise.\n\n\t* liboctave/Matrix.h, liboctave/Matrix.cc, liboctave/RowVector.cc,\n\tliboctave/ColVector.cc, liboctave/DiagMatrix.cc,\n\tliboctave/Matrix-ext.cc, liboctave/Bounds.cc, liboctave/DAE.cc,\n\tliboctave/CollocWt.cc, liboctave/FEGrid.cc, liboctave/LinConst.cc,\n\tliboctave/ODE.cc, liboctave/NLEqn.cc: Don't abort or exit on\n\terrors.  Instead print some message by calling the function\n\tpointed to by current_liboctave_error_handler and then return.\n\n\t* liboctave/lo-error.cc: New file, for liboctave error handling\n\tstuff.\n\nSun Nov 14 23:28:12 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/utils.cc (default_path): Handle OCTAVE_PATH from the\n\tenvironment like TeX handles TEXINPUTS.  If the path starts with\n\t`:', prepend the standard path.  If it ends with `:' append the\n\tstandard path.  If it begins and ends with `:', do both (which is\n\tuseless, but the luser asked for it...).\n\t(octave_lib_dir): Plug memory leak.\n\nSat Nov 13 02:41:24 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/symtab.h (symbol_record::context): New data member, to allow\n\trecursive functions to work.\n\t* src/symtab.cc (symbol_record::push_context): New function\n\t(symbol_record::pop_context): Ditto.\n\t(symbol_table::pop_context): Ditto.\n\t(symbol_table::push_context): Ditto.\n\n\t* src/tree.cc (tree_function::eval): If call_depth is > 1, push\n\tsymbol table context and add unwind protect to pop it on exit or\n\terror.\n\t(pop_symbol_table_context): New function for unwind protect.\n\n\t* configure.in: Use AC_HAVE_HEADERS(unistd.h) instead of\n\tAC_UNISTD_H.\n\n\t* src/lex.l, src/f-quad.cc, src/f-rand.cc, src/f-lpsolve.cc,\n\tsrc/f-fsqp.cc, src/f-fsolve.cc, src/f-det.cc, src/f-dassl.cc,\n\tsrc/f-colloc.cc, src/utils.cc, src/variables.cc, src/tree.cc,\n\tsrc/tree-const.cc, src/tc-extras.cc, src/sysdep.cc, src/symtab.cc,\n\tsrc/octave-hist.cc, src/pr-output.cc, src/input.cc,\n\tsrc/g-builtins.cc, src/f-det.cc, src/f-inv.cc, src/file-io.cc:\n\tConvert most calls to message() to calls to warning() or error()\n\tinstead.\n\n\t* src/f-npsol.cc (npsol): Don't try to create the linear\n\tconstraint object before checking array sizes.\n\nFri Nov 12 04:36:12 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tc-inlines.cc (is_one_zero): New function.\n\t* src/tc-assign.cc: Everywhere we check for is_zero_one, also\n\tcheck for is_one_zero.  Some people write ranges that go in\n\tdecreasing order...\n\t* src/tc-index.cc: Likewise.\n\n\t* src/tc-inlines (index_check (Range&, int&, char*)): Eliminate\n\tsecond arg -- there is no need to return the max value of the\n\trange.  Correctly compute and check the minimum value.\n\t* src/tc-index.cc: Change all callers, and check the max value\n\tthere.\n\t* src/tc-assign.cc: Likewise.\n\n\t* src/tc-assign.cc (do_vector_assign): Handle assignment of empty\n\tmatrix for int, idx_vector, and Range cases.\n\t(do_matrix_assign): Likewise, for cases when one of the indices is\n\ta colon and the other is an int, idx_vector, or Range.\n\n\t* liboctave/Range.h (Range): Rename private data members rng_foo\n\tinstead of just _foo.\n\t* liboctave/Range.cc: Change names where used.\n\n\t* liboctave/Range.cc (max): Return correct value even when the\n\telements in the range don't line up exactly with the limit.\n\t(min): Likewise.\n\t(sort): New function.\n\n\t* src/tc-assign.cc (delete_row (int)): New function.\n\t(delete_rows (idx_vector&)): Ditto.\n\t(delete_rows (Range&)): Ditto.\n\t(delete_column (int)): New function.\n\t(delete_columns (idx_vector&)): Ditto.\n\t(delete_columns (Range&)): Ditto.\n\n\t* src/tree-const.h (is_empty): Don't try checking rows and columns\n\tif type is magic_colon or unknown.  Return false instead.\n\t(is_zero_by_zero): New function.\n\n\t* src/idx-vector.cc (sort): New function.\n\t(intcmp): New static function, for sorting.\n\nThu Nov 11 02:31:13 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/menu.m: Update to use new va_start() and va_arg()\n\tfunctions.\n\n\t* src/g-builtins.cc (builtin_va_arg): Rename from\n\tbuiltin_get_next_arg.\n\t(builtin_va_start): New function.\n\t* src/builtins.cc (builtin_general_functions): Fix up list.\n\n\t* src/tree.cc (tree_function::va_arg): Rename from get_next_arg.\n\t(tree_function::va_start): New function.\n\n\t* src/tree.h (tree_function::num_named_args): New data member.\n\t* src/tree.cc (tree_function::define_param_list): Set it.\n\t(tree_function::eval): Unwind-protect it.\n\nWed Nov 10 03:37:44 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree.cc (tree_identifier::assign): Also check to make sure\n\tthat the symbol record is defined since symbol_record::is_variable\n\tmay return true even if the record is undefined.\n\t* src/variables.cc (link_to_global_variable): Don't try to copy a\n\tNULL_TREE_CONST.\n\n\t* src/tree-const.cc (tree_constant_rep::matrix_value): If the\n\tcurrent value is a scalar, return 1x1 matrix.\n\t* src/tc-assign.cc (tree_constant_rep::check_vector_assign):\n\tHandle case of zero size LHS.\n\tClean up formatting of some error messages.\n\n\t* src/lex.l ({EL}): Recognize ... when not at end of line.\n\t* src/octave.cc (curr_function): New global variable.\n\t* src/g-buitlins.cc (builtin_get_next_arg): New function.\n\t* src/builtins.cc (builtin_general_functions): Add it to the list.\n\t* src/parse.y (param_list1): Handle ... at end of parameter list.\n\tAbort parse on error.\n\t(ELLIPSIS): New token, for variable argument lists.\n\t* src/tree.h (tree_function): Add varargs_ok, args_passed,\n\tnum_args_passed, and curr_arg_number data members to handle\n\tvariable argument lists.\n\t(tree_parameter_list::marked_for_varargs): New data member.\n\t* src/tree.cc (tree_function::takes_varargs): New function.\n\t(tree_function::get_next_arg): New function.\n\t(tree_parameter_list::mark_varargs): New function.\n\t(tree_parameter_list::takes_varargs): New function.\n\t(tree_function::eval): Set curr_function, args_passed, and\n\tnum_args_passed for use by get_next_arg.\n\nMon Nov  8 14:22:34 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.79 released.\n\n\t* src/builtins.cc (builtin_text_functions):  Correct usage message\n\tfor who.\n\n\t* scripts/dgram.m: New function, from R. Bruce Tenison\n\t(btenison@eng.auburn.edu).\n\t* scripts/dlqe.m: Ditto.\n\t* scripts/dlqr.m: Ditto.\n\t* scripts/c2d.m: Ditto.\n\n\t* src/tree.cc (tree_identifier::name): Make it const.\n\t(tree_builtin::name): Ditto.\n\t(tree_parameter_list::name): Ditto.\n\t(tree_word_list::name): Ditto.\n\n\t* src/symtab.cc (symbol_table::save): Delete list of names after\n\tsaving.\n\n\t* src/symtab.h (symbol_table): Move #defines outside of class\n\tdeclaration.\n\nSun Nov  7 07:03:12 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Makeconf.in (CXX): Don't set from C++.  Do set from @CXX@, which\n\tis determined by configure.  Don't set C++FLAGS.\n\n\t* src/tree.cc: (tree_function::eval (int, int)): Simply call\n\teval (tree_constant *, int, int, int) with nargin = 1 and args =\n\tNULL_TREE_CONST instead of duplicating most of that function in place.\n\n\t* src/parse.y (func_def2): Reset id_name after renaming identifier.\n\tClear id_name from top level symbol table before defining identifier.\n\nSat Nov  6 04:38:57 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: When checking for g++, set CXX, not GXX.\n\n\tMerge min changes from Bruce Tenison (btenison@eng.auburn.edu) and\n\tmake the corresponding changes for max.\n\n\t* src/tc-extras.cc (min (ComplexMatrix&, ComplexMatrix&)): New\n\tfunction.\n\t(max (ComplexMatrix&, ComplexMatrix&)): Ditto.\n\t(column_min): Handle complex args and two return values.\n\t(column_max): Likewise.\n\n\t* liboctave/Matrix.cc (row_min_loc): New function.\n\t(row_max_loc): New function.\n\t(column_min_loc): Ditto.\n\t(column_max_loc): Ditto.\n\nFri Nov  5 03:12:55 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.78.\n\n\t* src/octave.h (clean_up_and_exit): Change form of declaration for\n\tGCC 2.5.x and beyond.\n\n\t* src/tree.cc (tree_identifier::eval): Correctly handle printing\n\tof identifier tags and conversion to assignment to `ans'.\n\t* src/parse.y (maybe_convert_to_ans_assign): Simplify.\n\tFor identifiers, defer decision about making an ans assignment\n\tuntil evaluation time since identifiers can be undefined at parse\n\ttime, and we can't tell what to do until we know what the def is.\n\t* src/tree.cc (tree_identifier::mark_for_possible_ans_assgin): New\n\tfunction.\n\t* src/tree.cc (tree_index_expression::mark_for_possible_ans_assign):\n\tNew function.\n\t* src/tree.h (tree_identifier): Add new private data,\n\tmaybe_do_ans_assign.\n\n\t* src/t-builtins.cc (builtin_who): Major overhaul.  Support long\n\tlistings.\n\t(print_symbol_info_line): New function.\n\t(print_long_listing): Ditto.\n\t(maybe_list): Ditto.\n\n\t* src/user-prefs.cc (sv_editor): New function for builtin variable\n\tEDITOR.\n\t* src/octave-hist.cc (do_edit_history): Use user_pref.editor, not\n\tjust the EDITOR environment variable.\n\n\t* src/user-prefs.cc (ignore_function_time_stamp): New function for\n\tnew builtin variable ignore_function_time_stamp.\n\t* src/variables.cc (symbol_out_of_date): Use value of new\n\tuser_pref.ignore_function_time_stamp to decide whether to check to\n\tsee if a file has changed.\n\t* src/tree.h (tree_function): Add new private data, system_m_file.\n\n\t* src/builtins.cc (string_variables): Add EDITOR and\n\tignore_function_time_stamp EDITOR to the list.\n\t(bultin_general_functions): Add is_global to the list.\n\n\t* src/t-builtins.cc (builtin_clear): Make it work with new\n\tvariable scoping rules.\n\t(builtin_document): Likewise, using new document_symbol()\n\tfunction.\n\t(builtin_save): Likewise.  Allow regular expression arguments.\n\tDon't save builtin variables that are read-only.\n\n\t* src/utils.cc (octave_home): Don't declare static.\n\t(octave_lib_dir): Likewise.\n\t(octave_info_dir): Likewise.\n\t(default_editor): New function.\n\n\t* src/tree.cc (tree_builtin::def): Delete function.\n\t(tree_identifier::def): Likewise.\n\t(tree_identifier::symrec): Likewise.\n\n\t* src/tree.h (tree_builtin): Store name of function, not pointer\n\tto symbol record.\n\n\t* src/user-prefs.cc (warn_assign_as_truth_value): Lookup\n\t\"warn_assign_as_truth_value\", not \"user_pref.warn...\".\n\n\t* src/tree-base.h (def): Delete unused virtual function.\n\t(is_prefix_expression): New virtual function.\n\t(mark_for_possible_ans_assign): Likewise.\n\t(is_system_m_file): Likewise.\n\t(stash_m_file_name): No longer needs to be virtual.\n\t(stash_m_file_time): Likewise.\n\n\t* src/octave.cc (octave_Complex_error_handler): Define, to keep\n\terrors in the Complex class from aborting Octave.  This is only a\n\ttemporary fix, I hope.\n\t(main): Install it.\n\t(initialize_globals): Get default editor.\n\t(main): Call initialize_symbol_tables to do that instead of\n\tcreating them directly in main.\n\n\t* src/variables.cc (document_symbol): New function.\n\t(initialize_symbol_tables): Likewise.\n\t(install_builtin_mapper_function): Likewise.\n\t(install_builtin_text_function): Likewise.\n\t(install_builtin_general_function): Likewise.\n\t(install_builtin_variable): Likewise.\n\t(install_builtin_variable_as_function): Likewise.\n\t(bind_nargin_and_nargout): Likewise.\n\t(bind_builtin_variable): Likewise.\n\t(link_to_global_variable): Likewise.\n\t(link_to_builtin_variable): Likewise.\n\t(link_to_builtin_or_function): Likewise.\n\t(force_link_to_function): Likewise.\n\t(is_globally_visible): Likewise.\n\t(is_builtin_variable): Likewise.\n\n\t* src/tree.cc (print_as_scalar): Avoid trying to print row vectors\n\ton one line.\n\n\t* src/builtins.cc (install_buitlins): Simplify installation of\n\tbuiltin functions using new install_builtin_*_function functions.\n\tDitto for using bind_builtin_variable for installing variables.\n\n\t* src/tree.h (tree_global_command): New class.\n\t* src/tree.cc (tree_global_command::*): Implement new class to\n\tmake global command executable.\n\t* src/parse.y (global_decl): Make global an executable statement.\n\n\t* src/parse.y (func_def2): Rework to match new way of handling\n\tglobal variables and function names in the symbol table.\n\tMark functions as `system' or not.\n\tDon't use id_to_define.\n\tIf m-file and function names disagree, rename function to match\n\tm-file name.\n\t* src/tree.cc (tree_identifier::rename): New function.\n\t* src/parse.cc, src/parse.h (id_to_define): Delete unused global\n\tvariable.\n\n\t* src/varables.cc (builtin_string_variable): Fix to match new\n\trules for global and builtin variables.\n\t(builtin_real_scalar_variable): Likewise.\n\n\t* src/tree.cc (tree_identifier::assign): Make it work with new\n\trules for global variables.\n\t(tree_identifier::parse_m_file): Likewise.\n\t(tree_identifier::do_lookup): Likewise.\n\n\t* src/tree.cc (mark_as_system_m_file): New function.\n\t(is_system_m_file): Ditto.\n\n\t* src/tree.cc (clear_symbol_table): New function, to be used in an\n\tunwined_protect element for clearing function symbol tables on\n\texit or error.\n\n\t* src/tree.cc (tree_function::eval): Simplify using\n\tbind_nargin_and_nargout.\n\tClear symbol table on exit or error with unwind_protect.\n\n\t* src/tree.cc (tree_prefix_expression::is_prefix_expression): New\n\tfunction.\n\n\t* src/g-builtins.cc (builtin_is_global): New function.\n\n\t* src/lex.l (lookup_identifier): Now that global variable binding\n\thas been fixed, only look for symbols in the current symbol table.\n\tReally.  I mean it this time.\n\n\t* src/symtab.cc: Complete overhaul, to make global variables work\n\ta bit more reasonably.\n\nMon Nov  1 15:03:39 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/Matrix.h (DiagMatrix::rows): Return nr, not len.\n\t(ComplexDiagMatrix::rows): Ditto.\n\t* src/Matrix.h (DiagMatrix::cols): Return nc, not len.\n\t(ComplexDiagMatrix::cols): Ditto.\n\t(DiagMatrix::columns): Ditto.\n\t(ComplexDiagMatrix::columns): Ditto.\n\n\t* liboctave/DiagMatrix.cc (DiagMatrix::row): Make it work for\n\tsquare case.\n\t(DiagMatrix::column): Likewise.\n\t(ComplexDiagMatrix::row): Likewise.\n\t(ComplexDiagMatrix::column): Likewise.\n\n\t* liboctave/DiagMatrix.cc (DiagMatrix::operator <<): Print spaces\n\tbetween elements.\n\t(ComplexDiagMatrix::operator <<): Likewise.\n\nFri Oct 29 15:32:12 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.77.1.\n\n\t* src/symtab.cc (symbol_record::alias): Don't copy formal_param or\n\tforced_global attribute.\n\n\t* src/symtabl.cc (symbol_table::bind_globals): Don't bind to\n\tglobal symbol unless it has forced_global attribute set.\n\n\t* src/tree.cc (print_as_scalar): New function.\n\t(tree_identifier::eval): Use it.\n\t(tree_simple_assignment_expression::eval): Likewise.\n\t(tree_multi_assignment_expression::eval): Likewise.\n\n\t* src/lex.l (is_keyword): Give better error message for attempts\n\tto define nested functions.\n\n\t* src/parse.y (global_decl): Return a command_list to execute\n\t(this makes assignments in global declarations executable).\n\n\t* src/tree.cc (tree_for_command): Handle line and column info in\n\tconstructors and for error messages.\n\t(tree_while_command): Ditto.\n\t(tree_if_command): Ditto.\n\t(tree_break_command): Ditto.\n\t(tree_continue_command): Ditto.\n\t(tree_return_command): Ditto.\n\t(*::eval_error): Only print messages if error_state > 0.\n\t(various): Only need to check that error_state is non-zero before\n\tcalling eval_error().\n\n\t* src/parse.y: Handle line and column information for FOR WHILE IF\n\tELSEIF ELSE BREAK CONTINUE and FUNC_RET tokens.\n\t* src/lex.l: Likewise.\n\n\t* src/octave.cc (parse_and_execute): Reset parser before starting\n\tnew parse.\n\n\t* src/tree-plot.cc (various): Check error_state in many more\n\tplaces, and issue more meaningful error messages.\n\n\t* src/tree-const.cc (maybe_resize): Don't call\n\tjump_to_top_level() on errors.\n\t(tree_constant_rep (Range)): Likewise.\n\n\t* src/g-builtins.cc (builtin_error): Use error(), not\n\tprint_if_string() to print error messages.\n\t* src/tree-const.cc (print_if_string): Delete unused function.\n\n\t* src/tc-assign.cc (various): Check error_state after calls to\n\tmaybe_resize().\n\n\t* src/tc-index.cc (various): Always check the state of idx_vectors\n\tafter trying to create them.\n\t* src/tc-assign.cc (various): Likewise.\n\n\t* src/idx-vector.cc: Use 0, not NULL.\n\tDon't include stdlib.h.\n\t(initialized): New data member, set nonzero if the idx_vector has\n\tbeen properly initialized.\n\tNever call jump_to_top_level () if initialization fails.\n\tAdd operator void *(), so we can test the state of an idx_vector\n\twith `if (vector)'.\n\n\t* src/pager.cc: Explicitly initialize pager_buf to NULL.\n\n\t* src/tree-base.h: Move includes ahead of other definitions.\n\n\t* liboctave/NLEqn.cc (NLEqn::NLEqn (const Vector&, const NLFunc)):\n\tInitialize n from xvec, not x.\n\nMon Oct 25 18:01:12 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/user-prefs.cc (sv_info_file): New function.\n\t* src/user-prefs.h (user_pref): Add info_file to the list.\n\t* src/t-builtins.cc (try_info): Use it instead of\n\tDEFAULT_INFO_FILE.\n\n\t* src/utils.cc (default_info_file): New function.\n\t(octave_info_dir): Likewise.\n\n\t* src/defaults.h.in (DEFAULT_INFO_FILE): Delete unnecessary\n\tdefinition since we figure out what it should be in utils.cc now.\n\t* src/Makefile.in (defaults.h): Don't substitute DEFAULT_INFO_FILE.\n\t* src/Makeconf.in (DEFAULT_INFO_FILE): Delete definition.\n\n\t* src/octave.cc (info_file): New global variable.\n\t(initialize_globals): Call default_info_file () to initialize it.\n\t(--info-file): New command line option.\n\n\t* src/builtins.cc (string_variables): Add INFO_FILE to the list.\n\t(install_builtins): Define it.\n\n\t* info/filesys.c (compress_suffixes): Choose gunzip for .gz files.\n\nSat Oct 23 17:46:09 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.77 released.\n\n\t* src/Makefile.in (INCFLAGS): Don't include info or dld\n\tdirectories.\n\t* dynamic-ld.cc: Include dld/dld.h, not just dld.h.\n\t* t-buitlins.cc: Include info/info.h, info/dribble.h, and\n\tinfo/terminal.h, not just info.h, dribble.h, and terminal.h.\n\n\t* src/t-builtins.cc (builtin_help): New option, -i, for invoking\n\tinfo browser.  If -i is not given, just do what we used to do, but\n\tpoint to help -i as a way to get additional information.\n\n\t* builtins.cc (print_usage): New function.\n\n\t* g-builtins.cc (all builtins): Call print_usage to get usage message.\n\t* t-builtins.cc (all builtins): Likewise.\n\nFri Oct 22 15:56:16 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Cholesky changes from R. Bruce Tenison (btenison@eng.auburn.edu):\n\n\t* src/f-chol.cc, src/f-chol.h: New files for the Cholesky\n\tFactorization.\n\t* src/Makefile.in (SOURCES, OBJECTS, DLD_OBJECTS): Add to lists.\n\t* src/g-builtins.cc (builtin_chol): New function.\n\t* src/g-builtins.h: Declare it.\n\n\t* liboctave/Matrix-ext.cc (CHOL, ComplexCHOL): New classes.\n\n\t* libcruft/lapack: dpotrf.f, zpotrf.f, dpotf2.f, zpotf2.f: New\n\tfiles.\n\n\t* libcruft/blas: dsyrk.f, zherk.f: New files.\n\nFri Oct 22 14:04:16 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/g-builtins.cc (builtin_schur): Fourth arg for DLD_BUILTIN is\n\tschur, not hess.\n\n\t* scripts/dare.m: Correct usage of fprintf.\n\n\t* src/utils.cc (raw_mode): Only complain about stdin not a tty if\n\tinteractive or forced interactive.\n\nThu Oct 21 17:00:57 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/builtins.cc (install_builtins): Try harder to make\n\tinitialization of NaN work.  Make note about possible fixes if it\n\tstill doesn't work.\n\n\t* src/utils.cc (raw_mode): [HAVE_TERMIOS_H] and [HAVE_TERMIO_H]\n\tDon't set TAB3 since it doesn't seem necessary and some systems\n\tdon't have it by this name.\n\t[HAVE_SGTTY_H] To be consistent, don't set XTABS here either.\n\n\t* src/error.c (error): Call flush_output_to_pager before printing\n\terror message.\n\t(panic): Likewise, before aborting.\n\n\t* src/symtab.cc (symbol_record::undefine): Delete unused function.\n\t(symbol_table::undefine): Likewise.\n\n\t* src/symtab.cc (clear): Never delete symbol records from the\n\ttable.  Only delete the definitions.  This makes clear and\n\tundefine equivalent, so we don't need them\n\t* src/tree.cc (tree_function::eval): Call symbol_table::clear, not\n\tsymbol_table::undefine.\n\n\t* src/t-builtins.cc (builtin_clear): Only clear global symbols if\n\twe are at the top level.\n\t* src/parse.y (CLEAR): Delete token.\n\t(word_list_command): Remove code to handle CLEAR as special case.\n\t(expect): Only 19 now.\n\t* src/lex.l (handle_identifier): Remove special code for clear.\n\tIt's ok to use it in a function body now.\n\n\t* src/t-builtins.cc: Include extern \"C\" declarations for Info stuff.\n\t(builtin_help): If given an argument, try to get help directly\n\tfrom info file first.  If that fails, do as before.\n\t(help_syms_list): New function:\n\t(simple_help): New function.\n\t(try_info): New function.\n\t(help_from_list): New function.\n\n\t* src/defaults.h.in (DEFAULT_INFO_FILE): Define new macro.\n\t* Makeconf.in: Set value of DEFAULT_INFO_FILE.\n\t* Makeconf.in (INSTALL_PROGRAM): Add definition.\n\t* Makefile.in (SUBDIRS): Add info directory.\n\t(info): New target.\n\t* configure.in: Add autoconf macros to handle info configuration.\n\n\t* info/Makefile.in: Major changes to make it work with Octave's\n\tMakeconf file, etc.  The default action is now to build a\n\tlibinfo.a file.\n\n\t* info/error.c: New file.  Move error functions here from info.c.\n\n\t* info/signals.c (clear_info_signal_handler): New function, useful\n\tif info is used directly in another program.\n\n\t* info/termdep.h: Handle termios too.\n\t* info/terminal.c (terminal_prep_terminal): Handle termios.\n\t* (terminal_unprep_terminal): Likewise\n\n\t* info/session.c (initialize_info_session): Add arg to make\n\tclearing the screen conditional.  Useful if we want to call\n\tindex_entry_exists() first before displaying anything.\n\tChange all callers.\n\n\t* info/session.c (finish_info_session): New function.\n\n\t* info/session.c (dispatch_error): Change message to include info\n\tabout how to get help and how to quit.\n\n\t* info/info.c (index_search_p): New flag.\n\t(--index-search): New option, like apropos, but search the indices\n\tand display the first node found.\n\n\t* info/indices.c (do_info_index_search): New function, modified\n\tfrom info_index_search to allow searching the index for a string\n\twithout prompting for it.\n\t(info_index_search): Just call do_info_index_search.\n\t(index_entry_exists): New function, to allow us to find out if\n\tthere is an index entry for a given string without actually\n\tdisplaying anything.\n\n\t* info: New directory, containing source for GNU info browser.\n\nTue Oct 19 00:14:33 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/octave-hist.cc (input_from_tmp_history_file): New global flag.\n\t(do_edit_history): Protect and set it.\n\t(do_run_history): Likewise.\n\t* src/parse.y (func_def2): Use it to see that input is coming from\n\ta temporary file.  This means that we shouldn't exit when we're\n\tdone reading it, and we should treat it just as if the input were\n\tcoming from the keyboard.\n\n\t* variables.cc (force_global): Force aliasing so it will happen\n\teven if the symbol record is undefined.\n\n\t* src/lex.l (lookup_identifier): Simplify\n\n\t* src/lex.l (reset_parser): Reset error_state here.\n\t* src/octave.cc (main): Not here.\n\nMon Oct 18 14:27:02 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree-const.cc: Delete constructor for tree_constant from\n\tString.\n\n\t* In src: tree.h, mappers.h, unwind-prot.h, parse.h, file-io.h,\n\tarith-ops.h, tree-base.h, tree-const.h, g-builtins.h,\n\tidx-vector.h, builtins.h, dynamic-ld.h, xdiv.h, xpow.h,\n\tpr-output.h, input.h, symtab.h, utils.h: Avoid including files\n\tunnecessarily.\n\n\t* In src: tc-inlines.cc, mappers.cc, variables.cc, arith-ops.cc,\n\ttree.cc, tree-const.cc, g-builtins.cc, file-io.cc, idx-vector.cc,\n\ttc-assign.cc, tc-index.cc, builtins.cc, dynamic-ld.cc, xdiv.cc,\n\txpow.cc, pr-output.cc, tc-extras.cc, input.cc, symtab.cc,\n\tutils.cc: Sprinkle liberally with const.\n\n\t* In src: f-syl.cc, f-svd.cc, f-schur.cc, f-rand.cc, f-qzval.cc,\n\tf-quad.cc, f-qr.cc, f-qpsol.cc, f-npsol.cc, f-lu.cc,\n\tf-lsode.cc, f-lpsolve.cc, f-inv.cc, f-ifft.cc, f-hess.cc,\n\tf-givens.cc, f-fsqp.cc, f-fsolve.cc, f-fft.cc, f-expm.cc,\n\tf-eig.cc, f-det.cc, f-dassl.cc, f-colloc.cc, f-balance.cc:\n\tAdd const qualifier to tree-constant arg.\n\nSat Oct 16 12:22:24 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree-const.h, src/tree-const.cc: Add const qualifier to\n\tconstructor arguments passed by reference.\n\tPass Complex arguments by const reference instead of by value.\n\n\t* liboctave/Matrix.h, liboctave/Matrix.cc, liboctave/ColVector.cc,\n\tliboctave/RowVector.cc liboctave/DiagMatrix.cc: Pass Complex\n\targuments by const reference instead of by value.\n\nWed Oct 13 14:13:29 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/utils.cc (decode_prompt_string): ctime returns time_t, which\n\tmight not be a long.\n\n\t* src/variables.cc (identifier_exists):\tOnly return non-zero if\n\tthe name has a definition.\n\n\t* src/f-npsol.cc (npsol): Call error(), not message(), to print\n\terror messages.\n\t(linear_constraints_ok): Likewise.\n\t(nonlinear_constraints_ok): Likewise.\n\n\t* src/f-qpsol.cc (qpsol): Don't try to create the linear\n\tconstraint object before checking array sizes.  Wouldn't exception\n\thandling be nice?\n\tCall error(), not message(), to print error messages.\n\tCheck to ensure that the bounds on linear constraints are\n\tvectors.\n\n\t* src/lex.l (lookup_identifier): Don't bind global variables\n\timmediately in loops or conditionals, even at the top level.\n\nSun Oct 10 8:48:00 1993  John Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* README.doc: New file.\n\t* Makefile.in (doc-dist): New target.\n\t* doc/Makefile.in (FORMATTED): New macro.\n\t(doc-dist): New target.\n\n\t* src/tree.cc (tree_identifier::eval): Don't print anything if an\n\terror is encountered.\n\t(tree_simple_assignment_expression::eval): Likewise.\n\n\t* src/tc-assign.cc (do_matrix_assignment): Handle resizing\n\tcorrectly when indices are (:,range), (:,matrix), (range,:), or\n\t(matrix,:) and the lhs is empty or undefined.\n\nTue Oct  5 04:02:37 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.76 released.\n\n\t* src/octave.cc (main):\tPrint usage message if we are given more\n\tthan one extra argument on the command line.\n\tDelay printing startup message until just before setting the toplevel\n\tjump context.\n\n\t* src/lex.h (DO_COMMA_INSERT_CHECK): Delete unused macro.\n\n\t* src/lex.l (handle_identifier): New function.\n\t({IDENT}/{S}*=, {IDENT}{S}*): Use it instead of duplicating code.\n\t(do_comma_insert_check): Use yyunput instad of returning original\n\tcharacter count.\n\tCall directly instead of using DO_COMMA_INSERT_CHECK macro.\n\nMon Oct  4 08:06:10 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.75.4.\n\n\t* src/tree-const.cc (tree_constant_rep::eval ()): Avoid calling\n\trows() and columns() for things like magic_colon.\n\nSun Oct  3 19:39:33 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\tChanges to add line and column info to run-time error messages:\n\n\t* src/tree.cc (tree_identifier, tree_prefix_expression,\n\ttree_postfix_expression, tree_simple_assignment_expression,\n\ttree_multi_assignment_expression, tree_colon_expression,\n\ttree_index_expression): Modify constructors to allow line and\n\tcolumn information to be stored.\n\t(abort_on_undefined): Delete (now) unnecessary static variable.\n\t(all eval() functions): If error_state, return immediately.\n\t(tree_matrix::eval ()): Call error and return tree_constant()\n\tinstead of jumping to top level on error.\n\t(tree_identifier::parse_m_file ()): When starting to read an\n\tM-file, initialize current_input_column to 1, not 0.\n\t(tree_identifier::eval_undefined_error ()): Improve error message\n\twith line and column info if it is available.  Don't abort to top\n\tlevel on errors.\n\t(tree_function::traceback_error ()): New function.\n\t(tree_function::eval ()): Don't jump to top level on errors.\n\tCall traceback_error if there is an error evaluating the command\n\tlist.\n\n\t* src/tree.cc (tree_prefix_expression::eval_error ()): New function.\n\t(tree_postfix_expression::eval_error ()): Ditto.\n\t(tree_unary_expression::eval_error ()): Ditto.\n\t(tree_binary_expression::eval_error ()): Ditto.\n\t(tree_simple_assignment_expression::eval_error ()): Ditto.\n\t(tree_multi_assignment_expression::eval_error ()): Ditto.\n\t(tree_colon_expression::eval_error ()): Ditto.\n\t(tree_index_expression::eval_error ()): Ditto.\n\n\t* src/tree.cc (tree_function::stash_function_name ()): New function.\n\t* src/parse.y (FCN): Use it.\n\n\t* src/lex.l: Return line and column info for many (but not all)\n\ttokens.\n\n\t* src/parse.y: Handle token values with the token class defined in\n\ttoken.cc.\n\t(check_end ()): New function.\n\t(end_error ()): Improve error messages by including line and\n\tcolumn info.\n\n\t* src/arith-ops.cc (lots of functions): Don't jump to top level on\n\terrors.\n\t* src/tree.cc (tree_unary_expression::eval ()),\n\ttree_binary_expression::eval ()): Handle error condition here.\n\n\t* src/gripes.cc (gripe_nonconformant): Add additional form of this\n\tfunction to allow message to include dimensions.  Change most\n\tcallers to use new form\n\n\t* src/octave.cc: Initialize column counter to 1, not 0.\n\t(main): Reset error_state before evaluating each top level\n\tcommand.\n\n\t* src/tree-plot.cc (tree_plot_command::eval ()): If error_state,\n\treturn immediately.\n\n\t* src/tree-const.cc (do_binary_op ()): Return tree_constant() instead\n\tof jumping to top level on errors.\n\t(do_unary_op): Likewise.\n\t(tree_constant_rep::eval ()): If error_state, return immediately.\n\tConvert 1x1 matrices to scalars.\n\n\t* src/tc-assign.cc (tree_constant_rep::do_scalar_assignment ()):\n\tDon't jump to top level on error.\n\tIf there is an error while attempting to convert an undefined\n\tvariable to a matrix, don't suddenly create an empty matrix.\n\t(tree_constant_rep::fortran_style_matrix_assignment ()): Check\n\treturn value of range_max_check() and don't jumpt to top level on\n\terrors.\n\t(tree_constant_rep::vector_assignment ()): Check return value of\n\tindex_check and don't jump to top level on errors.\n\t(tree_constant_rep::check_vector_assign ()): Don't jump to top\n\tlevel on errors.\n\t(tree_constant_rep::do_matrix_assignment ()): Check return value\n\tof index_check and don't jump to top level on errors.\n\n\t* src/tc-extras.cc (get_dimensions ()): Call error (sets error state)\n\tbut don't jump to top level on errors.\n\t(fill_matrix): Return tree_constant() on error.\n\t(identity_matrix): Likewise.\n\n\t* src/error.cc (error_state): New global variable, initialize to zero.\n\t(error): Set it to one.\n\n\t* src/tc-index.cc (tree_constant_rep::valid_as_scalar_index ()):\n\tDon't declare unused variable retval.\n\t(tree_constant_rep::do_scalar_index ()): Return tree_constant()\n\tinstead of jumping to top level on error.\n\t(tree_constant_rep::fortran_style_matrix_index): Don't jump to top\n\tlevel on indexing or range errors.\n\t(tree_constant_rep::do_vector_index ()): Likewise.\n\t(tree_constant_rep::do_matrix_index ()): Likewise.\n\n\t* src/tc-inlines (range_max_check): Return -1 instead of jumping\n\tto top level on error.\n\t(index_check): Likewise.\n\n\t* src/utils.cc (check_dimensions): Call error, not warning, and\n\tdon't jump to top level.\n\n\t* src/tree-base.h (line_num, column_num): New data members for all\n\ttree classes.\n\t(line (), column ()): New virtual functions to access line and\n\tcolumn info.\n\n\t* src/lex.l (enum end_tok_type, enum plot_tok_type): Delete\n\tdeclarations (now in token.h).\n\n\t* src/lex.h (YY_INPUT, YY_FATAL_ERROR, DO_COMMA_INSERT_CHECK,\n\tTOK_RETURN, BIN_OP_RETURN): Move macro definition here, from\n\tlex.l.  Rename RETURN TOK_RETURN.\n\n\t* src/token.cc, token.h: New files that define a class for tokens\n\tthat includes line and column information.\n\nWed Sep 29 11:15:12 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/octave.cc: Use GNU getopt to handle option parsing.\n\t* src/getopt.h src/getopt.c src/getopt1.c: New files for GNU\n\tgetopt.\n\t* src/Makefile.in: Add them to the appropriate lists.\n\n\t* src/utils.cc (raw_mode): Use the termios.h terminal driver\n\tinterface if it is available.\n\t* configure.in: Check for termios.h\n\n\t* src/tree-plot.cc (tree_subplot_list::print (int, ostrstream&)):\n\tIf the data to be plotted is a string but it doesn't name a file,\n\ttry sending it to gnuplot directly.\n\nTue Sep 28 16:06:42 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/QPSOL.cc (QPSOL::minimize (double&, int&, Vector&)):\n\tCorrect dimensions of work arrays, based on QPSOL source.\n\tPass ncon, which is max (1, nclin), not n, as the row dimension of\n\tclin.\n\n\t* src/f-npsol.cc (linear_constraints_ok): Improve warning for the\n\tcase of constraints with zero dimensions.\n\t(nonlinear_constraints_ok): Likewise.\n\nMon Sep 27 01:20:50 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.75.3.\n\n\t* Makefile.in (dist): Make file permissions for distribution rw.\n\t(binary-dist): Ditto.\n\t(local-dist): Ditto.\n\nSat Sep 25 15:29:20 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/pr-output.cc: Include stdio.h, for sprintf.\n\n\t* src/input.cc (octave_gets): Set octave_gets_line to NULL after\n\tfreeing it.\n\n\t* Version 0.75.2.\n\n\t* liboctave/Matrix.cc (Matrix::operator * (const ColumnVector&):\n\tCorrect dimension of return value.\n\t(ComplexMatrix::operator * (const ComplexColumnVector&)): Ditto.\n\nTue Sep 21 20:42:10 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree.cc (tree_identifier::assign (tree_constant&)):\n\tCorrectly handle case of hiding a function with a variable when\n\tthe variable has not been flagged as global.\n\ttree_identifier::assign (tree_constant&, tree_constant*, int)):\n\tLikewise.\n\n\t* src/variables.cc (force_global): When a variable is moved to the\n\tglobal symbol table, mark it as global.\n\n\t* src/symtab.cc (symbol_record::symbol_record ()): Initialize\n\tforced_global.\n\t(symbol_record::clear_visible ()): Reset forced_global to zero.\n\t(symbol_record::clear_all ()): Ditto.\n\t(symbol_record::mark_as_forced_global ()): New function.\n\t(symbol_record::is_forced_global ()): New function.\n\t(symbol_record::alias ()): Also copy forced_global attribute.\n\n\t* src/symtab.h (symbol_record::forced_global): New private data\n\tmember, used to record when a variable has been explicitly\n\tdeclared global.\n\n\t* src/lex.l (lookup_identifier): Look in current scope first.\n\nMon Sep 20 03:15:52 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/parse.y, src/tree.cc, src/tree.h: Allow `for' command to\n\tassign to an index expression, not just an identifier.\n\n\t* src/t-builtins.cc (builtin_clear (int, char **)): Don't delete\n\tg_names twice.\n\n\t* src/symtab.cc\t(symbol_table::list (int&)): Make sure count is\n\tinitialized to zero.\n\t(symbol_table::var_list (int&)): Ditto.\n\t(symbol_table::fcn_list (int&)): Ditto.\n\nSat Sep 18 04:06:42 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/lex.l, src/parse.y, src/parse.h: Use new global variable\n\tpast_plot_range to make gplot and gsplot smarter about\n\tdistinguishing plot ranges and literal matrices.\n\nFri Sep 17 01:06:30 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.75.1 released.\n\n\t* src/f-qzval.cc: Include <float.h> for DBL_EPSILON.\n\n\t* src/symtab.cc (symbol_record::save (ostream&, int)): Don't print\n\ta warning for ans being undefined.  Call warning to print the\n\tmessage, and change the text to make it clearer.\n\t(symbol_table::save (ostream&, int)): Don't crash if there aren't\n\tany symbols to save.\n\nThu Sep 16 00:21:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/t-builtins.cc (builtin_help): When trying harder to find\n\thelp for M-files, only insert the symbol into the global symbol\n\ttable if there really is an M-file of the given name in the path.\n\nWed Sep 15 02:08:27 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.75.\n\n\t* src/Makefile.in (INCLUDES): Distribute defaults.h\n\t(%.d: %.cc): Don't fail if we can't determine dependencies.\n\t(DISTFILES): Include move-if-change.\n\nTue Sep 14 21:23:20 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/perror.m: Use err, not info for fsolve section.\n\nMon Sep 13 19:29:26 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/utils.cc (get_m_file_names): Call closedir(), not free(), to\n\tdispose of directory structure.\n\nSun Sep 12 19:07:36 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree-const.cc (tree_constant_rep::double_value): Rearrange\n\tto avoid warning about reaching end of non-void function.\n\t(tree_constant_rep::matrix_value): Ditto.\n\n\t* src/error.cc (panic): Declare volatile.\n\t* src/utils.cc (jump_to_top_level): Declare as `void volatile',\n\tnot `volatile void'.\n\n\t* src/tree-const.cc (tree_constant_rep::complex_matrix_value):\n\tMake it work even if the internal representation is really a real\n\tor complex scalar or a real matrix.\n\t(tree_constant_rep::complex_scalar_value): Make it work even if\n\tthe internal representation is really a real scalar.\n\n\t* src/f-syl.cc (syl): Delete ComplexMatrixLoad().\n\tUse complex_matrix_value(), not ComplexMatrixLoad().\n\n\t* src/tree-const.cc (vector_of_empties): Renamed from empty_tree,\n\tmoved from f-syl.cc.\n\n\t* src/f-syl.cc (syl): Call vector_of_empties() instead of empty_tree().\n\t* src/f-qzval.cc (qzvalue): Ditto.\n\n\t* src/tree-const.h (tree_constant::is_empty): New inline function.\n\n\t* src/f-syl.cc (syl): Call is_empty instead of empty_arg.\n\t* src/f-qzval.cc (qzvalue): Ditto.\n\t* src/f-expm.cc (matrix_exp): Ditto.\n\nThu Sep  9 22:40:16 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/Matrix.cc (Matrix::transpose): Make it work for empty\n\tmatrices.\n\t(ComplexMatrix::transpose): Ditto.\n\nMon Sep  6 04:56:50 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/tree-plot.cc (tree_subplot_list::print): \tIf the plot data\n\tis a string and it names a file, plot the data in the file.\n\n\t* src/octave.cc (execute_startup_files): Try harder to avoid\n\texecuting $HOME/.octaverc twice.\n\n\t* liboctave/DAE.cc (DAE::integrate (Vector&, Matrix&, Vector&)):\n\tAdd missing parameter in call to integrate() if no critical points\n\tare specified.\n\nSat Sep  4 16:18:49 1993  John W. Eaton  (jwe@ward.che.utexas.edu)\n\n\t* src/octave.cc (execute_startup_files): Don't execute\n\t$HOME/.octaverc twice.\n\nMon Aug 30 11:25:12 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/t-builtins.cc (builtin_clear): Handle regular expressions.\n\nFri Aug 27 07:25:32 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/RowVector.cc:\n\t(RowVector::operator * (const ColumnVector& a) const): Fix brain-o.\n\nWed Aug 18 00:29:09 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* list_primes.m: New M-file.\n\n\t* src/tc-index.cc (do_scalar_index): Handle two vector args of all\n\tones.\n\nTue Aug 17 06:26:04 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/file-io.cc (process_printf_format): Use NINT for * modifier\n\targument.\n\nMon Aug 16 19:30:09 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/mappers.cc: (arg (double)): Return pi for negative real values.\n\nSun Aug 15 05:08:48 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/octave-hist.cc (mk_tmp_hist_file): New function, extracted\n\tfrom do_edit_history.\n\t(do_edit_history): Simplify using mk_tmp_hist_file.\n\t(do_run_history): New function.\n\t(edit_history_repl_hist): New function.\n\n\t* src/t-builtins.cc (builtin_run_history): New function.\n\n\t* src/builtins.cc (text_functions): Add run_history to the list.\n\nFri Aug 13 16:04:09 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tzero.m: New M-file.\n\t* abcdchk.m: New M-file.\n\t* is_symmetric.m: Use tol and norm (A) to decide if A' is close\n\tenough to A to be considered the same.\n\nWed Aug 11 15:50:59 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.74.1.\n\n\tMerge in expm changes from A. S. Hodel <scotte@eng.auburn.edu>:\n\n\t* f-expm.{h,cc}: New files.\n\t* src/Makefile.in: Include them in the usual places.\n\t* src/g-builtins.cc (builtin_expm): The new matrix_exp returns a\n\ttree_constant by value.\n\tInclude f-expm.h\n\t* src/tc-extras.cc (matrix_exp): Delete function.\n\nTue Aug 10 20:06:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\tMerge in qzval changes from A. S. Hodel <scotte@eng.auburn.edu>:\n\n\t* f-qzval.{h,cc}: New files.\n\t* src/Makefile.in: Include them in the usual places.\n\t* src/g-builtins.cc (builtin_qzval): New function.\n\tInclude f-qzval.h\n\t* src/g-builtins.h: Declare builtin_qzval.\n\t* src/builtins.cc (general_functions): Add qzval to the list.\n\n\t* libcruft/eispack: New directory.\n\t* libcruft/Makefile.in (SUBDIRS): Include it.\n\nTue Aug 10 20:06:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Add libcruft/balgen/Makefile and\n\tlibcruft/eispack/Makefile to the list of files to frob.\n\nTue Aug 10 20:06:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\tMerge in syl changes from A. S. Hodel <scotte@eng.auburn.edu>:\n\n\t* lyap.m: New M-file.\n\n\t* f-syl.{h,cc}: New files.\n\t* src/Makefile.in: Include them in the usual places.\n\t* src/g-builtins.cc (builtin_syl): New function.\n\tInclude f-syl.h\n\t* src/g-builtins.h: Declare builtin_syl.\n\t* src/builtins.cc (general_functions): Add syl to the list.\n\nTue Aug 10 20:06:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/g-builtins.cc (builtin_balance): Fix typo in doc string.\n\nTue Aug 10 20:06:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\tMerge in givens changes from A. S. Hodel <scotte@eng.auburn.edu>:\n\n\t* f-givens.{h,cc}: New files.\n\t* src/Makefile.in: Include them in the usual places.\n\t* src/g-builtins.cc (builtin_givens): New function.\n\tInclude f-givens.h\n\t* src/g-builtins.h: Declare builtin_givens.\n\t* src/builtins.cc (general_functions): Add givens to the list.\n\n\t* src/Makefile.in: (defaults.h) Quote substitutions.\n\tUse %foo%, not @foo@ to mark substitution.\n\t* src/defaults.h.in: Use %foo%, no @foo@ to do mark things to\n\tsubstitute.\n\n\t* qzhess.m: New M-file.\n\nTue Aug 10 20:06:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\tMerge in balance changes from A. S. Hodel <scotte@eng.auburn.edu>:\n\n\t* are, is_controllable.m, is_observable.m, is_square.m,\n\tis_symmetric.m:  New M-files.\n\n\t* Matrix.h (AEPBALANCE): New class.\n\t(ComplexAEPBALANCE): New class.\n\t(GEPBALANCE): New class.\n\t* Matrix-ext.cc: Add init functions for balancing classes.\n\n\t* src/f-balance.{h,cc}: New files.\n\t* src/Makefile.in: Include them in the usual places.\n\t* src/g-builtins.cc (builtin_balance): New function.\n\tInclude f-givens.h\n\t* src/g-builtins.h: Declare builtin_balance.\n\t* src/builtins.cc (general_functions): Add balance to the list.\n\n\t* libcruft/balgen: New directory.\n\t* libcruft/Makefile.in (SUBDIRS): Include it.\n\nTue Aug 10 20:06:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Use AC_HAVE_LIBRARY to check for -lm.\n\n\t* src/Makefile.in (defaults.h): Quote substitutions.\n\nMon Aug  9 13:30:07 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* README.NLP: New file.\n\t* Makefile.in (DISTFILES): Distribute it.\n\nSun Aug  8 19:05:48 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/move-if-change: New file.\n\t* src/Makefile.in (DISTFILES): Distribute it.\n\t(defaults.h): New rule.\n\t(utils.o): Delete rule, since extra defines are no longer needed.\n\t(INCLUDES): Distribute defaults.h.in.\n\t* src/utils.cc: Include defaults.h to get DEFAULT_PAGER and\n\tOCTAVE_HOME instead of depending on having them defined by the\n\tcompile command.\n\n\t* configure.in (DEFAULT_PAGER): Use AC_PROGRAMS_CHECK.\n\tIf we find less, add `-e' flag, so users won't have to type q to\n\tquit paging.\n\nSat Aug  7 13:34:06 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* f-*.cc: Renamed from tc-*.cc.  (Use f- as the file prefix\n\tbecause most of these functions are ultimately implemented in\n\tFortran, and, most importantly, it keeps them grouped together.)\n\t* f-*.h: New files, for external declarations of visible functions\n\tdefined in f-*.cc.\n\t* g-builtins.cc: Include them all.\n\t* tree-const.h: Don't declare these functions as friends.\n\t* Makefile.in: Cope with new names.\n\n\t* octave.cc (parse_and_execute (char *, int)): Don't declare static.\n\t* octave.h: Declare it extern here.\n\t* octave-hist.cc (do_edit_history): Use it here.\n\n\t* octave-hist.cc (do_edit_history): New function.\n\t* t-builtins.cc (builtin_edit_history): Use it.\n\n\t* t-builtins.cc, t-builtins.h, builtins.cc: Rename edit to\n\tedit_history.\n\n\t* octave-hist.cc (do_history): Print line numbers by default.\n\tAllow quieter output with -q option.\n\n\t* g-builtins.cc (builtin_hess): Use DLD_BUILTIN macro to call hess.\n\t* g-builtins.cc (builtin_schur): Likewise\n\n\t* tc-hess.cc (builtin_hess_2): Call hess with corrrect args.\n\t* tc-schur.cc (builtin_schur_2): Likewise, for schur dude :-).\n\n\t* tc-fsqp.cc (builtin_fsqp_2): Fix typo.\n\nThu Aug  5 23:14:01 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* input.cc (octave_read): Ensure that the last character in the\n\tbuffer is a new line.\n\nWed Aug  4 19:25:54 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* parse.y (func_def2): Also warn if we encounter a function\n\tdefinition with the same name as the script file we are reading.\n\n\t* tree.cc (tree_identifier::do_lookup): Always return NULL_TREE if\n\ta script file was executed.\n\nTue Aug  3 23:25:45 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* file-io.cc: Delete useless static keyword from File_info class\n\tdeclaration.\n\t* unwind-prot.cc: Likewise, for unwind_elem and saved_variable\n\tclasses.\n\t* tc-rand.cc: Likewise, for enum rand_dist declaration.\n\t* arith-ops.cc:  Likewise, for enum Matrix_bool_op declaration.\n\t* tree.cc: Likewise, for struct const_matrix_list declaration.\n\nFri Jul 23 01:40:38 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* sysdep.cc (malloc_handler): Add missing arg to call to message().\n\nTue Jul 20 04:09:32 1993  John W. Eaton  (jwe@june.che.utexas.edu)\n\n\t* Version 0.74 released.\n\n\t* doinstall.sh (version): Run `./octave -v' to get the version\n\tnumber instead of grabbing it from version.h.\n\t* Fail if we can't get a version number.\n\t* Install ./octave, not src/octave.\n\n\t* Makefile.in (binary-dist): Don't depend on all.\n\t* Link src/octave to ./octave.  (Now that there's no source in\n\tbinary distributions, why have a src directory?)\n\n\t* file-io.cc (process_scanf_format): Rename local variable `i' to\n\t`chars_from_fmt_str'.\n\t* (process_printf_format): Likewise.\n\n\t* sighandlers.cc (can_interrupt): New global variable.\n\t* (sigint_handler): Use it to decide whether to jump to top level.\n\t* octave.cc (main): Set it after calling setjmp.\n\n\t* octave.cc (main): Declare saved_sigint_handler to be volatile.\n\n\t* tree.cc, tree-plot.cc, t-builtins.cc, pager.cc, g-builtins.cc,\n\tfile-io.cc: Terminate strstream strings with ends instead of just\n\tusing '\\0'.\n\n\t* file-io.cc (process_scanf_format): Skip leading white space for\n\t%s conversions.\n\t* (fopen_file_for_user): Pass tree_constant arg by reference.\n\t* (do_scanf): If doing fprintf, don't fail if first arg is a\n\tstring.\n\nMon Jul 19 16:00:22 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* symtab.cc (pstrcmp): Declare to take char** args, not char*.\n\nSun Jul 18 13:02:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* file-io.cc (return_valid_file): Pass arg by reference.\n\n\t* file-io.cc (fclose_internal, fgets_internal, fseek_internal):\n\tEliminate unnecessary casts to double.\n\n\t* file-io.cc (return_valid_file, fgets_internal, fopen_internal,\n\tdo_printf, do_scanf): Use is_string_type instead of doing the\n\tcomparison ourselves.\n\t* g-builtins.cc (builtin_exist, builtin_getenv,\n\tbuiltin_shell_command): Ditto.\n\t* tc-colloc.cc (collocation_weights): Ditto.\n\t* tc-extras.cc (eval_string, get_user_input): Ditto.\n\t* tc-rand.cc (rand_internal): Ditto.\n\t* tree-plot.cc (tree_subplot_list::print): Ditto.\n\t* variables.cc (is_valid_function, octave_string_variable): Ditto.\n\nThu Jul 15 02:29:03 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* doc/Makefile.in (TEXINFO): Distribute texinfo.tex too.\n\n\t* t-builtins.cc (load_variable): Warn if replacing local symbol\n\twith global from file.\n\t* Warn if variable is not marked as global in a file, but already\n\texists as a global symbol, then go ahead and load it as a global.\n\nTue Jul 13 01:47:48 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (lookup_identifier): Never alias to global here.\n\t* tree.cc (do_lookup): Don't alias formal parameters to global.\n\t* variables.cc (force_global): Likewise.\n\t* symtab.cc (symbol_table::bind_globals): Likewise.\n\n\t* symtab.h (symbol_record::formal_param): New field.\n\t* symtab.cc (symbol_record::mark_as_global_parameter): New function.\n\t* (symbol_record::is_formal_parameter): Ditto.\n\t* tree.cc (tree_identifier::mark_as_formal_parameter): Ditto.\n\t* (tree_parameter_list::mark_as_formal_parameters): Ditto.\n\t* parse.y (param_list): Use it to tag formal parameters.\n\t* (func_def1): Ditto.\n\n\t* arith-ops.cc (DIVIDE_BY_ZERO_ERROR): On IEEE machines, allow\n\tdivide by zero errors to be suppressed.\n\t* user-prefs.h (warn_divide_by_zero): New user preference.\n\t* user-prefs.cc (warn_divide_by_zero): New function.\n\t* builtins.cc (builtin_string_variables): Install it with default\n\tvalue of true.\n\n\t* tree.cc (tree_multi_assignemnt_expression): Use tree_return_list\n\tinstead of tree_param_list.\n\t* (tree_multi_assignment_expression:eval): Make it work.\n\n\t* tree.cc (tree_return_list): New class.  Allow index expressions\n\tand identifiers in return lists.\n\t* (tree_matrix::to_return_list): Rename from to_param_list.\n\t* parse.y (expression): Use it.\n\n\t* parse.y: Increment and decrement maybe_screwed_again instead of\n\tjust setting it to zero or one.\n\nMon Jul 12 03:23:40 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tc-assign.cc (tree_constant_rep::do_matrix_assignment): Handle\n\tcase of lhs being of unknown type.\n\n\t* lex.l (check_for_garbage_after_fcn_def): Also ignore trailing\n\tcommas and semicolons.\n\nSun Jul 11 00:08:20 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.73.1 released.\n\n\t* symtab.cc (symbol_record::alias): Also copy pointer to sv_fcn.\n\nSat Jul 10 14:34:00 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_function::eval (int, char **, int): New function.\n\n\t* symtab.cc (symbol_table::bind_globals): New function.\n\t* tree.cc (tree_function::eval): Use it to associate local symbols\n\twith global data.\n\n\t* symtab.cc (alias): Add optional parameter `force'.\n\n\t* Version 0.73 released.\n\n\t* pr-output.cc: Use D_NINT instead of NINT in some cases to avoid\n\toverflow problems on systems that don't have IEEE Inf.\n\t* mappers.cc (round): Likewise.  Also avoids conversion of Inf to\n\tINT_MAX on systems that do have IEEE Inf.\n\n\t* builtins.h: Remove definition of NINT.\n\t* tree.h: Likewise.\n\t* tree-const.h: Likewise.\n\n\t* utils.cc (NINT): Move function here and improve handling of\n\textreme values.\n\t* (D_NINT): New function.\n\n\t* scripts/isempty.m: Don't require the number of rows and columns\n\tto both be zero.\n\nThu Jul  8 16:25:50 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.72.2.\n\n\t* configure.in: Do a better job of grabbing the last argument as\n\tthe target_host_type and avoiding setting it to things like\n\t--prefix=/foo/bar\n\n\t* tree-const.cc (tree_constant_rep::save): Add default case for\n\tmark_as_global switch to avoid warnings from gcc.\n\n\t* variables.cc (force_global): Cope with symbol table changes.\n\t* tree.cc: (tree_identifier::do_lookup): Likewise.\n\t* lex.l (lookup_identifier): Likewise.\n\t* builtins.cc (install_builtins): Likewise.\n\n\t* symtab.cc, symtab.h: Massive internal rewrite.\n\nWed Jul  7 02:18:01 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tc-assign.cc (tree_constant_rep::do_scalar_assignment): If rhs\n\tis a scalar type, also handle case of lhs being of unknown type.\n\t* Be sure to set the new type of the lhs.\n\n\t* tree-base.h: Don't include symtab.h.\n\t* tree-const.h: Ditto.\n\nTue Jul  6 22:47:28 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* parse.y (func_def2): Remove the function name from the top-level\n\tsymbol table if defining on command line (an M-file would never be\n\tparsed if there was already an entry with the same name in the top\n\tlevel symbol table).\n\n\t* parse.y (word_list_command): Allow clear without any arguments.\n\t* tree.cc (word_list_command::eval): Handle word list commands\n\twith no arguments.\n\nMon Jul  5 14:43:30 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.72.1.\n\n\t* help.cc (operators): Document the double quote character.\n\n\t* lex.l (getting_help): Delete unused variable.\n\t* (HELP_FCN): New exclusive start state.\n\t* ({IDENT}{S}*): Set start state to HELP_FCN instead of setting\n\tgetting_help.\n\t* ({IDENT}/{S}*=): Likewise.\n\n\t* symtab.cc (symbol_table::load): Delete unused function.\n\n\t* tree-const.cc (tree_constant::load): Return flag telling whether\n\tthe constant is global.\n\t* t-builtins.cc (builtin_load): Handle global variables.\n\t* (builtin_save): Likewise.\n\n\t* symtab.cc (symbol_record::save): Don't save builtin variables\n\t(variables marked as eternal are assumed to be builtin).\n\n\t* symtab.cc (symbol_record::mark_from_global): New function.\n\t* (symbol_def::undefine): Add optional argument to prevent\n\tdeleting symbol's definition.\n\t* (symbol_table::undefine): If this variable has been marked as\n\tdefined from a global, call symbol_def::undefine with arg = 1.\n\t* tree.cc (tree_identifier::do_lookup): If a local symbol is\n\tdefined from a global, mark it as such.\n\n\t* symtab.cc (symbol_record::define (symbol_record*)): Delete\n\tunused function.\n\n\t* tree.cc (tree_identifier::do_lookup (int&)): Use operator=\n\tinstead of symbol_record::define().\n\t* variables.cc (force_global (char*)): Likewise.\n\nSun Jul  4 01:27:44 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* symtab.cc (symbol_record): Define copy constructor and operator=.\n\n\t* builtins.cc (install_builtins): Make `i' and `j' read-only\n\tfunctions.\n\n\t* symtab.cc (symbol_record::define): Respect read-only status of\n\tvariables and functions.\n\nSat Jul  3 19:11:31 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* user-prefs.h (print_empty_dimensions): New user preference variable.\n\t* user-prefs.cc (print_empty_dimensions): New function.\n\t* builtins.cc (print_empty_dimesions): Make default value true.\n\t* tree-const.cc (tree_constant_rep::eval): Use value here.\n\n\t* cond.m: Handle empty matrices.\n\t* tc-det.m (determinant): Likewise.\n\t* tc-inv.m (inverse): Likewise.\n\n\t* tc-hess.cc (hess): Use gripe_square_matrix_required instead of\n\tcalling error.\n\t* tc-schur.cc (schur): Likewise.\n\n\t* builtins.cc (propagate_empty_matrices): Change default value to\n\ttrue.\n\n\t* tree-const.cc (tree_constant_rep::eval): If a matrix has zero\n\trows or columns, also print the dimension along with the `[]'\n\tsymbol.\n\n\t* tree-const.cc (do_binary_op): If ok to propagate empty matrices,\n\tgo ahead and do the binary operation so that the result will have\n\tconsistent dimensions.\n\t* (do_unary_op): Likewyse.\n\n\t* tc-extras.cc (get_dimensions): Don't force both nr and nc to\n\tzero if one is.\n\t* Matrix.cc, DiagMatrix.cc, ColVector.cc, RowVector.cc: Handle\n\tmatrices with zero dimensions in a more consistent fashion.\n\nThu Jul  1 00:27:01 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* perror.m: New M-file.\n\n\t* LP.h, LP.cc: New interface for linear programmming.\n\t* LPsolve.h LPsolve.cc: New files to implement linear programming\n\tusing lp_solve.\n\n\t* NPSOL.cc (minimize): Also return the vector of Lagrange\n\tmultipliers.\n\t* tc-npsol.cc (npsol): Optionally return them.\n\n\t* QPSOL.cc (minimize): Also return the vector of Lagrange\n\tmultipliers.\n\t* tc-qpsol.cc (qpsol): Optionally return them.\n\n\t* tc-qpsol.cc (qpsol): Make it work.\n\nWed Jun 30 02:19:00 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc (builtin_lpsolve): New function.\n\t* (builtin_qpsol): Ditto.\n\t* builtins.cc (general_functions): Add them to the list.\n\n\t* tc-lpsolve.cc: New file.\n\t* tc-qpsol.cc: Ditto.\n\t* src/Makefile.in: Add them to the list of SOURCES and DLD_OBJECTS.\n\nTue Jun 29 15:02:07 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/DAE.cc (integrate): If stop_time_set is false, reset\n\tdefault value for info[3].\n\t* liboctave/ODE.cc (integrate): Likewise, reset default values of\n\tiopt and itask.\n\n\tFrom Thorsten Ohl <ohl@physics.harvard.edu>:\n\t* config.guess: Add check for NeXT.\n\t* configure.in: Add check for NeXT so that readline is configured\n\tproperly (really need to improve readline's configuration scheme).\n\t* sysdep.cc (malloc_handler): New function for handling malloc\n\terrors on NeXT systems.\n\n\t* octave.cc (main): Call sysdep_init before anything else.\n\n\t* sysdep.cc: New file for system dependent things.\n\n\t* octave.cc (initialize_globals): Only pass argv[0] since that's\n\tthe only thing that's used.\n\nSat Jun 26 13:00:50 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_builtin::eval (int, char**, int)): Don't panic if\n\tcalled for something other than a text_fcn.\n\n\t* t-builtins.cc (builtin_cd): Rewrite to fix bogus memory\n\tproblems.\n\nFri Jun 25 15:23:03 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* t-builtins.cc (builtin_cd): Don't delete value returned by\n\tget_working_directory.\n\t* g-builtins.cc (builtin_pwd): Likewise, and simplify.\n\n\t* utils.cc (make_absolute): Always create a new copy to return.\n\t* utils.cc (change_to_directory): Don't delete pointer returned\n\tfrom get_working_directory().\n\t* (file_in_path): Likewise.\n\nThu Jun 24 16:48:38 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l ({IDENT}{S}*): Always insert a comma if the next token\n\tdoesn't look like some sort of operator, not just if\n\tconvert_spaces_to_comma is also true (it may have been turned off\n\tby BIN_OP_RETURN).\n\n\t* tree-const.h (matrix_ptr): Delete function.\n\t* tc-extras.cc (frobit): Delete function.\n\t* (get_dimensions): New function.\n\t* (identity_matrix): Completely rewrite.\n\t* (fill_matrix): Likewise.\n\nWed Jun 23 13:50:16 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Matrix-ext.cc (SCHUR::init): Also allow ord flag to be lowercase.\n\t* (ComplexSCHUR::init): Ditto.\n\t* tc-schur.cc (schur): Likewise.\n\n\t* Matrix-ext.cc (SCHUR::init): Declare sort as char, not char*,\n\tand pass its address to Lapack.\n\t* (ComplexSCHUR::init): Ditto.\n\n\t* Matrix-ext.cc (SCHUR::select_dig): Make static, and move ahead\n\tof first reference in file.\n\t* (SCHUR::select_ana): Likewise.\n\t* (ComplexSCHUR::select_complex_dig): Likewise.\n\t* (ComplexSCHUR::select_complex_ana): Likewise.\n\n\t* builtins.cc (install_builtins): Add `J' as an alias for `I'.\n\n\t* builtins.cc (install_builtins): Always create a new\n\ttree_constant for each variable, since the symbol table doesn't\n\tknow how to share them.\n\n\t* tc-schur.cc (schur): Use warning and error functions instead of\n\twriting directly to cerr.\n\t* tc-hess.cc (hess): Ditto.\n\n\t* src/Makefile.in (DLD_OBJECTS): Include tc-schur.o and tc-hess.o.\n\t* (SOURCES): Add tc-schur.cc tc-hess.cc.\n\n\t* Merge Schur and Hessenberg changes:\n\n\tFri Mar 19 11:01:19 1993  R. Bruce Tenison (btenison@eng.auburn.edu)\n\n\t* src/builtins.cc: Changed schur definition to include one more\n\tinput.  Also changed the help line description\n\t* src/g-builtins.cc: Changed builtin_schur to accept two inputs\n\tAlso changed the information to explain ordered schur operation.\n\t* src/tc-schur.cc Added extensions to the SCHUR and ComplexSCHUR\n\tcalls to pass extra paramater.  Also added check for proper param.\n\t* liboctave/Matrix.h: Modified declarations dgeesx and zgeesx to\n\taccept address of select function.  Modified class structures for\n\tSCHUR and ComplexSCHUR to accept extra ordered schur param.\n\t* liboctave/Matrix-ext.cc: Added extensions for the extra ordered\n\tschur paramater.\n\n\tWed Mar 17 15:23:14 1993  R. Bruce Tenison (btenison@eng.auburn.edu)\n\n\t* liboctave/Matrix-ext.cc (HESS and ComplexHESS): Added the\n\tHessenburg decomposition routines.\n\t* liboctave/Matrix.h Added fortran lapack functions definitions\n\tused in the Hessenburg procedure.\n\t* src/g-builtins.cc (builtin_hess): Hessenburg Decomposition routine\n\tadded\n\t* src/g-builtins.h (builtin_hess): Added extern definition.\n\t* liboctave/Matrix.h Added classed HESS and ComplexHESS\n\t* src/tree_const.h added defs for hess.\n\t* src/tc-hess.cc (hess): New file for hess function.\n\n\tTue Mar 16 10:46:32 1993  R. Bruce Tenison (btenison@eng.auburn.edu)\n\n\t* src/g-builtins.cc (builtin_schur): Schur Decomposition routine\n\tadded.\n\t* src/g-builtins.h (builtin_schur): Added extern definition.\n\t* liboctave/Matrix.h Added Classes SCHUR and Complex SCHUR, and\n\tadded defs for zgeesx and dgeesx (lapack schur decomp)\n\t* liboctave/Matrix-ext.cc (SCHUR and Complex SCHUR): Ditto.\n\t* src/tree-const.h added defs for schur.\n\t* src/tc-schur.cc (schur): New file for schur function.\n\nTue Jun 22 20:18:52 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (check_for_garbage_after_fcn_def): New function\n\t* parse.y (fcn_end_or_eof): If reading from an M-file, use it to\n\tprint warning about trailing garbage after the end of a function\n\thas been found.\n\nMon Jun 21 20:21:01 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tc-assign.cc (tree_constant_rep::assign): Handle case of\n\tassignment to unknown constant too.\n\t* (tree_constant_rep::do_scalar_assignment): Don't fail for\n\tunknown_constant type.\n\t* (tree_constant_rep::do_matrix_assignment): Likewise.\n\n\t* tree-const.cc (rows): Return 0 for unknown_constant type.\n\t* (columns): Likewise.\n\n\t* tree.cc (tree_identifier::assign): Defer defining symbol until\n\tassignment is successful.\n\t* When creating a new dummy tree_constant to assign a value to,\n\tleave it an unknown_constant type.\n\n\t* tc-assign.cc (do_scalar_assignment): If the right hand side\n\tisn't a scalar, maybe try to resize instead.\n\t* (do_matrix_assignment): For A(:,int) and A(int,:) cases, also\n\tresize if left hand side is a scalar.\n\n\t* norm.m: Allow \"fro\" to work for scalars and vectors too.\n\nSun Jun 20 01:17:03 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* NLConst.cc: New file.  Move inline function definitions here\n\tfrom NLConst.h.\n\n\t* Objective.cc: New file.  Move inline function definitions here\n\tfrom Objective.h\n\n\t* tree.cc (tree_word_list_command::eval): Call strsave for argv[0]\n\ttoo, and delete argv before returning.\n\t* (tree_builtin::eval): Likewise, for text functions with no\n\targuments.\n\nSat Jun 19 01:37:09 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (parse_and_execute): Delete calls to delete_buffer\n\tand switch_to_buffer, since that is taken care of by unwinding the\n\tframe.\n\nFri Jun 18 00:08:36 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_matrix::eval): Delete useless direct = ptr->direct\n\tand ptr = ptr->next statements from size-determining loop.\n\n\t* parse.y (opt_list): New rule.  Replace all occurrences of list\n\twith opt_list.\n\n\t* tree.cc: (tree_index_expression::eval (int, int)): Don't\n\tcomplain if the index expression has an empty argument list.\n\n\t* octave.cc (initialize_globals): Check return value of\n\tgetenv (\"HOME\") against NULL, not the global variable\n\thome_directory that we are trying to initialize.\n\n\t* tree.cc (tree_function::eval): Quick return if command list\n\tis empty.\n\t* parse.y (func_def3): Allow empty function bodies.\n\nThu Jun 17 02:08:02 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_while_command): Add constructor for case of\n\texpression only.\n\t* parse.y (statement): Allow empty command list for while commands.\n\n\t* parse.y (list): Allow empty commands in more places.  This ups\n\tthe shift/reduce error count by 6, to 19.\n\n\t* octave.cc (execute_startup_files): Don't delete sd.\n\n\t* octave.cc (initialize_globals): Make copies of all strings.\n\t* Store more humorous messages if things fail.\n\nTue Jun 15 11:03:39 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tc-extras.cc (get_user_input): Finish incomplete change to get\n\tinput using readline.\n\n\t* tc-extras.cc (match_sans_spaces): New function.\n\t* (get_user_input): Use it when checking to see if the user\n\tentered a `quit' command.\n\n\t* liboctave/Makefile.in: Don't distribute Makedeps.in or include\n\tMakedeps since we generate dependencies automatically now.\n\t* configure.in: Don't create liboctave/Makedeps.\n\nSun Jun 13 18:31:17 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/xdiv.cc (xdiv): Solve least-squares problem if system of\n\tequations is not square, or if it is singular.\n\t* (xleftdiv): Likewise.\n\n\t* liboctave/Matrix.h (Matrix::lssolve): New functions for\n\tleast-squares solutions of linear systems.\n\t* (ComplexMatrix::lssove): Ditto.\n\nSat Jun 12 19:07:07 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* libcruft/misc/xstopx.f (xstopx): Call dostop, not do_stop.\n\t* libcruft/misc/dostop.c: Rename from do_stop.c\n\t* (dostop): Likewise.\n\n\t* src/mappers.cc (xisnan (double)): Define even for systems that\n\tdon't have xisnan by always returning false.\n\t* (xisnan (const Complex&)): Likewise.\n\nFri Jun 11 19:54:58 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* doc/Makefile.in (install): Try harder to install info files.\n\n\t* libcruft/Makefile.in (install): Run ranlib on installed library.\n\t* liboctave/Makefile.in (install): Ditto.\n\t* readline/Makefile.in (install): Ditto.\n\nThu Jun 10 00:15:41 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.72 released.\n\n\t* libcruft/*/*.f: Don't call xstopx with '' since some Fortran\n\tcompilers object to zero-length strings.\n\t* libcruft/misc/xstopx.f (xstopx): Don't print empty strings or\n\tsingle blanks.\n\t* libcruft/misc/gen-d1mach.c (main): Likewise, for generated code.\n\n\t* test/Makefile.in (check): Set the Tcl variable OCTAVE_PATH.\n\t* test/config/unix-octave.exp: Pass OCTAVE_PATH to OCTAVE using\n\tthe new -p flag.\n\n\t* builtins.cc (install_builtins): Use load_path instead of calling\n\tdefault_path().\n\n\t* octave.cc (load_path): New global variable.\n\t* (initialize_globals): Initialize it here by calling default_path().\n\t* (main): Call initialize_globals() before getting command line\n\targuments.\n\t* Accept new argument, -p PATH.\n\n\t* octave.cc (clean_up_and_exit): Don't print a message when Octave\n\texits.\n\n\t* doinstall.sh: Install M-files in $(libsubdir), not $(libdir).\n\t* Use mkpath to create directories.\n\t* Extract version from version.h.\n\n\t* Makeconf.in (version): Compute version just once.\n\n\t* (libsubdir): New directory that includes version number, for\n\tinstalling M-files in (old versions of Octave may not be able to\n\tunderstand new M-files).\n\n\t* src/Makefile.in, libcruft/Makefile.in, liboctave/Makefile.in,\n\tdoc/Makefile.in, readline/Makefile.in, scripts/Makefile.in\n\t(install): Use mkpath to create directories.\n\t* scripts/Makefile.in (install): Install M-files in $(libsubdir),\n\tnot $(libdir).\n\n\t* mkpath.c: New file, from Emacs-19.\n\t* Makefile.in (mkpath): New rule.\n\t* (all): Depend on mkpath\n\t* (binary-dist): Distribute it.\n\n\t* config.guess: Update from bothner@cygnus.com.\n\n\t* lex.l (<STRING>{QSTR}*[\\n\\']): Set start state to 0 or MATRIX,\n\tdepending on value of braceflag.\n\t* (<DQSTRING>{DQSTR}*[\\n\\\"]): Ditto.\n\n\t* tree.cc (tree_matrix::eval): Make sure that strings are nul\n\tterminated.\n\nTue Jun  8 16:08:10 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (clean_up_and_exit): Print `bye-bye' here.\n\t* g-builtins.cc (builtin_quit): Not here.\n\n\t* pager.cc (terminal_columns): If screenwidth <= 0, return a\n\tdefault value of 80 columns.\n\t* (terminal_rows): Likewise for screenheight and a default of 24\n\trows.\n\n\t* octave.cc (parse_and_execute): Don't fiddle with interactive\n\tstates since that screws paging output.\n\t* tree.cc (parse_m_file): Likewise.\n\n\t* parse.y (input): For `simple_list error END_OF_INPUT' and\n\t`error END_OF_INPUT' use ABORT_PARSE.\n\t* Always accept `simple_list END_OF_INPUT'.\n\t* Always abort for `END_OF_INPUT'.\n\nMon Jun  8 13:55:41 1993  John C. Campbell  (jcc@schoch.che.utexas.edu)\n\n\t* file-io.h (fopen_file_for_user): New function declaration.\n\n\t* file-io.cc (fopen_file_for_user): New function.\n\t* (fgets_internal): If file doesn't exist open it for user,\n\talso return (double) -1 on EOF\n\t* (fseek_internal), (ftell_internal), (frewind_internal),\n\t(do_printf): Ditto.\n\t* (fopen_internal): Remove warn_on_not_open flag, limit warns.\n\nMon Jun  7 00:28:13 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* file-io.cc (do_scanf): Use `type' wherever possible instead of\n\thardcoding name in messages.\n\t* (do_printf): Ditto.\n\n\t* file-io.cc (fflush_internal): If flushing stdout, flush output\n\tto the pager instead of calling fflush on a stream.\n\t* (do_printf): Make fprintf (stdout, ...) exactly the same as\n\tprintf (...).\n\t* (do_scanf): Make fscanf (stdin, ...) exactly the same as\n\tscanf (...).\n\n\t* tc-extras.cc (get_user_input): Flush output to pager before\n\tprompting for input.\n\n\t* libcruft/Makefile.in (DISTFILES): Distribute STOP.patch to show\n\tthe changes made to the Fortran sources.\n\n\t* libcruft/*/*.f: Replace STOP statements with calls to xstopx, so\n\tthat Fortran programs won't just quit on us.\n\n\t* libcruft/misc/xstopx.f: New file.\n\t* libcruft/misc/do_stop.c: New file.\n\t* libcruft/misc/Makefile.in (SPECIAL): Add do_stop.c to the list.\n\t* (SPECIAL_DEPEND): Likewise, for do_stop.o.\n\t* libcruft/Makefile.in (CRUFT_OBJ): Ditto.\n\n\t* lex.l (\")\"): Don't pop the top of the in_brace_or_paren stack if\n\tit's empty.\n\nSun Jun  6 00:41:28 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* liboctave/CollocWt.cc (init): Always compute Gaussian quadrature\n\tweights instead of trying to compute Radau or Lobatto weights if\n\tthe endpoints are included.\n\t* Really do compute roots and derivative weights corresponding to\n\tLegendre polynomials if alpha and beta are zero, even if the\n\tendpoints are included.\n\nSat Jun  5 22:19:55 1993  John C. Campbell  (jcc@schoch.che.utexas.edu)\n\n\t* builtins.cc (builtin_general_functions): Correct max arg counts\n\tfor fscanf, scanf, and sscanf.\n\n\t* g-builtins.cc (builtin_fscanf): Correct argument checks.\n\t* (builtin_sscanf): Likewise.\n\n\t* file-io.cc (fopen_internal): Don't warn for opening new file.\n\n\t* file-io.cc (process_printf_format): Handle * for field width and\n\tprecision.\n\t* Pass array of arguments and nargin instead of just one arg.\n\t* (do_printf): Call process_printf_format() with new args.\n\n\t* file-io.cc (process_scanf_format): New function to handle scanf\n\tdirty work.\n\t* (do_scanf): New function.\n\nSat Jun  5 14:09:41 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (YY_FATAL_ERROR): Redefine here to keep from exiting on\n\tfatal scanner errors.\n\nFri Jun  4 16:35:25 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_multi_assignment_expression::eval (int)): Check to\n\tsee if result is NULL before trying to use it.\n\n\t* tc-extras.cc (get_user_input): Call gnu_readline() to get input.\n\nThu Jun  3 00:30:28 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/*.m: Convert single-quoted strings to use double quotes\n\tsince the manual says they are better.\n\n\t* Version 0.71.10.\n\n\t* doc/Makefile.in (DISTFILES): Distribute octave.info*.\n\n\t* Makefile.in (.fname): Delete target and move actions back to the\n\tindividual dist targets because this always needs to be done.\n\t* (binary-dist): Strip src/octave.\n\n\t* doinstall.sh: New file, for binary distributions.\n\nWed Jun  2 15:11:54 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Makefile.in (binary-dist): New target, just like dist, except\n\talso distribute libcruft.a, liboctave.a, libreadline.a and\n\tsrc/octave.\n\n\t* Makefile.in (.fname): New target.\n\t* (links-for-dist): New target.\n\t* (local-dist): Depend on .fname.\n\t* (dist): Depend on .fname and use links-for-dist.\n\n\t* octave.cc: Move code to print startup message to just after\n\toption processing so that any messages from startup files will\n\tappear after the normal startup message.\n\n\t* utils.cc (get_site_defaults): New function.\n\t* (OCTAVE_HOME): Provide default definition.\n\n\t* (SITE_DEFAULTS): Delete definition.\n\t* octave.cc (execute_startup_files): Use get_site_defaults instead.\n\n\t* src/Makefile.in (utils.o): Define OCTAVE_HOME to be $(prefix)\n\there.\n\n\t* Makeconf.in: Don't define SITE_DEFAULTS or OCTAVE_M_FILE_DIR.\n\n\t* lex.l (do_string_escapes): Recognize `\\\"'.\n\nTue Jun  1 01:28:20 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.71.9.\n\n\t* parse.y (maybe_convert_to_ans_assign): Greatly simplify.\n\n\t* file-io.cc (File_info): Convert from struct to proper class.\n\t* (valid_mode): New function.\n\n\t* parse.y, parse.h, lex.l, tree-extras.cc (convert_to_ans_assign):\n\tDelete unused variable.\n\n\t* builtins.cc (SEEK_CUR): Set to 1 to match (normal) system values.\n\t* (SEEK_END): Likewise, set to 2.\n\n\t* statdefs.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\t* octave-hist.cc: Include it.\n\t* variables.cc (identifier_exists): Likewise.\n\t* utils.cc (is_newer): Likewise.\n\n\t* builtins.cc (SEEK_SET): New builtin varible.\n\t* (SEEK_CUR): Ditto.\n\t* (SEEK_END): Ditto.\n\t* (stdin): Ditto.\n\t* (stdout): Ditto.\n\t* (stderr): Ditto.\n\n\t* lex.l (strip_trailing_whitespace): New function.\n\t* ({IDENT}{S}*): Use it.\n\t* (<TEXT_FCN>[^ \\t\\n\\;\\,]*): Fix to grab trailing spaces.\n\tUse strip_trailing_whitespce() to delete it before returning.\n\nMon May 31 21:00:00 1993  John C. Campbell  (jcc@june.che.utexas.edu)\n\n\t* file-io.cc, file-io.h: New files to implement C-style file\n\thandling and I/O functions.\n\t* (do_printf): Move here from tc-extras.cc.\n\t* (process_printf_format): Likewise.  Also renamed from\n\tprocess_format.\n\nMon May 31 00:52:55 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* (tree_function::eval): Now that we can restore values, enable\n\tcode to give error for attempts to call functions recursively.\n\n\t* octave.cc (parse_and_execute): Use unwind-protect functions to\n\tsave and restore state.\n\t* tree.cc (parse_m_file): Likewise.\n\t* (tree_function::eval): Likewise.\n\t* tc-extras (eval_string): Likewise.\n\n\t* unwind-prot.cc (saved_variable): New class to hold values of and\n\tpointers to variables we want to restore.\n\t* (restore_saved_variable): New function.\n\n\t* unwind-prot.cc (unwind_protect_int_internal): New function.\n\t* (unwind_protect_ptr_internal): Ditto.\n\t* (unwind_protect_var_internal): Ditto.\n\n\t* unwind-prot.h (unwind_prot_int): New macro.\n\t* unwind-prot.h (unwind_prot_ptr): Ditto.\n\t* unwind-prot.h (unwind_prot_var): Ditto.\n\n\t* variables.cc (symbol_out_of_date ()): Move here from tree.cc.\n\t* (is_valid_function): Fix logic for finding a function\n\tdefinition, including checking to see if the current symbol\n\tdefinition is out of date.\n\n\t* tree-const.h (is_numeric_or_range_type): New function.\n\t* tree-const.h (is_string_type): New function.\n\t* tree.cc (tree_matrix::eval): Use !is_string_type() instead of\n\tis_numeric_type() to decide that we've seen something other than\n\ta string.\n\n\t* parse.y (maybe_warn_assign_as_truth_value ()): New function.\n\t* user-prefs.h (warn_assign_as_truth_value): New preference.\n\t* user-prefs.cc (warn_assign_as_truth_value ()): New function.\n\t* builtins.cc (string_variables): Add it to the list.\n\n\t* tree.h (tree_simple_assignment_expression): Rename class from\n\ttree_assignment_expression.\n\t* (tree_assignment_expression): New class, derived from\n\ttree_expression.\n\t* (tree_simple_assignment_expression): Derive from new\n\ttree_assignment_expression class, not tree_expression class.\n\t* (tree_multi_assignment_expression): Ditto.\n\nSun May 30 22:40:58 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/Makefile.in (%.d: %.cc): First remove target file, then\n\tredirect into tmp file, and finally move tmp file to target file\n\tonly if creating tmp file was successful.\n\t* liboctave/Makefile.in (%.d: %.cc): Ditto.\n\nSat May 29 18:18:16 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_constant *tree_multi_assignment_expression\n\t::eval (int print, int nargout)): New function.\n\t* (tree_constant tree_multi_assignment_expression::eval (int print)):\n\tUse it to do the real work.\n\n\t* tree.cc (tree_matrix::to_param_list ()): Also allow index\n\texpressions as long as the argument list is missing.\n\n\t* parse.y (ans_expression): Now that assignments are just\n\texpressions, don't convert expressions to assignemnts to `ans' if\n\tthey already are assignments.\n\t* maybe_convert_to_ans_assign (tree *expr): New function to do the\n\treal work.\n\n\t* tree.cc (tree_multi_assignment_expression::\n\tis_assignement_expression ()): Return 1.\n\n\t* tree-base.h (tree::is_index_expression ()): New virtual\n\tfunction, returns 0.\n\t* tree.cc (tree_index_expression::is_index_expression ()): Return 1.\n\n\t* tree.cc (tree_assignment): Construct from tree_index_expression\n\tand a tree.\n\t* (tree_index_expression::ident ()): New function.\n\t* (tree_index_expression::arg_list ()): New function.\n\n\t* parse.y (variable): New rule, returns tree_index_expression.\n\n\t* parse.y: Rewrite assignment rules so that they are simply\n\texpressions, not special cases.\n\t* Rearrange fact and expression rules into expression (assignement\n\tor simple expression), simple_expr (binary and postfix expressions\n\tor secondary simple expression), and simple_expr1 (constants and\n\tprefix expressions) rules.\n\t* Delete fact rules.\n\n\t* parse.y: Make EXPR_EQ and EXPR_NE have the same precedence as\n\tthe other relational operators.\n\nFri May 28 10:14:01 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* unix-octave.exp: Delete use of OCTAVEFLAGS.\n\n\t* test/config: New directory.\n\t* test/config/Makefile.in: New file.\n\t* test/config/unix-octave.exp: Rename from test/octave-init.exp.\n\t* test/Makefile.in (SOURCES): Delete octave-init.exp from list.\n\t* configure.in: Add test/config/Makefile to the list of Makefiles\n\tto build.\n\n\t* utils.cc (send_to_plot_stream): Plot lines by default.\n\nThu May 27 08:03:31 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (\\]): Don't pop the top of the in_brace_or_paren stack if\n\tit's empty.\n\n\t* tree.cc (tree_matrix::eval): Make it work for single element\n\tstrings as well.\n\n\t* Version 0.71.8.\n\n\t* lex.l (next_token_is_postfix_unary_op): New function.\n\t* (<MATRIX>{SN}*\\]{S}*): Use it as well, to decide whether to\n\tinsert a comma.\n\t* (<MATRIX>{S}+): Likewise.\n\t* ({IDENT}{S}*): Likewise.\n\nWed May 26 15:37:27 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* pr-otput.cc (pr_any_float): Use form() now that iostream\n\tformatting bug has been fixed (libg++-2.3.1).\n\nMon May 24 15:36:22 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (any_arg_is_magic_colon): New function.\n\t* (tree_builtin::eval) Use it to avoid calling builtin functions\n\twith `:' arguments.\n\nSun May 23 14:07:19 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc (builtin_fprintf): Correct usage message.\n\nFri May 21 10:35:40 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.71.7.\n\n\t* octave.cc (main): Always reset_parser() before every call to\n\tyyparse(), not just on a longjmp return.\n\n\t* doc/Makefile.in (install): For now, don't try to install\n\tanything.\n\n\t* lex.l (<MATRIX>{S}+): Call next_token_is_bin_op() instead of\n\tmaking the check in line.\n\t* (<MATRIX>{SN}*\\]{S}*): Likewise.\n\t* (<MATRIX>{S}+): Likewise.\n\n\t* lex.l (looks_like_bin_op): New function.\n\t* (next_char_is_space): Ditto.\n\t* (next_token_is_bin_op): Ditto.\n\n\t* lex.l ({IDENT}{S}*): If we're in a brace context and the next\n\tcharacter is an open paren, set convert_spaces_to_comma to 0.\n\t* tree-const.cc (convert_to_str): New function.\n\t* g-builtins.cc (builtin_setstr): New function.\n\t* builtins.cc (builtin_general_functions): Add it to the list.\n\nThu May 20 17:56:15 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* doc/Makefile.in (SOURCES): Define to be all .texi files.\n\t* (octave.info): Depend on $(SOURCES).\n\t* (octave.dvi): New target.\n\t* Don't distribute the man page.\n\n\t* lex.l (<MATRIX>{S}+): If the next character is a plus or minus\n\tfollowed by a space or tab, don't insert a comma.  This makes\n\tinput like [1 + 1] == 2 and input like [1 +1] == [1 1].\n\t* (<MATRIX>{SN}*\\]{S}*): Likewise.\n\n\t* lex.l (<MATRIX>{S}+): Use in_brace_or_paren and\n\tconvert_spaces_to_comma to decide whether to convert spaces to a\n\tcomma.\n\n\t* lex.l ({IDENT}{S}*): If we're in a brace context and the next\n\tcharacter is an open paren, set convert_spaces_to_comma to 0.\n\n\t* lex.l (<MATRIX>{SN}*\\]{S}*): Even if we're still inside some braces,\n\tdon't always push a comma onto the input.\n\n\t* lex.l (<MATRIX>{SN}*\\]): Also grab trailing spaces.\n\t* ({IDENT}): Ditto.\n\n\t* lex.l (in_brace_or_paren): New stack to keep track of whether\n\tthe closest enclosing scope is a pair of braces or parens.  When\n\twe see a `[' or a `(', push a flag on the stack.  When we see a\n\t`]' or a `)', pop the top of the stack.\n\n\t* lex.l (convert_spaces_to_comma): New flag to control lexer behavior.\n\t* (RETURN): Reset it to 1.\n\t* (most other returns): Reset it to 1.\n\n\t* lex.l (BIN_OP_RETURN): New macro.  Set convert_spaces_to_comma to 0.\n\t* (most binary operators): Use it instead of RETURN.\n\n\t* lex.l (match_any): New function.\n\nWed May 19 12:51:54 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Range.cc (nelem_internal): Don't allow ranges with more than\n\tINT_MAX elements.  Return -1 to indicate failure.\n\t* tree-const.cc (tree_constant_rep::tree_constant_rep (double,\n\tdouble, double)): Check nelem() to see if the range is valid.\n\n\t* pr-output.cc (all_elements_are_ints (Range&)): We only need to\n\tcheck the base and the increment, not the limit too.\n\n\t* Range.cc (nelem_internal): Move function definition here from\n\tRange.h and do a better job of determining the number of elements\n\tin the range.\n\nTue May 18 09:06:20 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.71.6.\n\n\t* tc-extras.cc (find_nonzero_elem_idx): Declare inner loop\n\titeration variables that are used inside later nested loops\n\tin the outer enclosing scope to make this work for old and new\n\tlanguage definitions (see the ARM, chapter 19: \"ANSI/ISO\n\tResolutions\", 6.4/6.5: \"The statement or statements immediately\n\tcontrolled by the condition in a selection-statement, or an\n\titeration-statement introduce an implicit local scope\".\n\t* xpow.cc (elem_xpow (Matrix&, Matrix&)): Likewise.\n\n\t* tree.cc (tree_identifier::parse_m_file (char*, int)): Set\n\treading_script_file before calling parse_m_file and restore it\n\tafterward.\n\nMon May 17 20:04:54 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.h (prog_name): Declare extern.\n\t* (raw_prog_name): Ditto.\n\n\t* f2c-compat.sh (ctest.c): Also write a dummy MAIN_ since gcc 2.4\n\tdoesn't seem to create an executable now if there are unresolved\n\texternals, and the linker wants to see it on Suns.\n\nThu May 13 01:06:18 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Makefile.in (DISTFILES): Include Makeconf.in.\n\n\t* configure.in: Set defaults for CFLAGS, CXXFLAGS, LDFLAGS, and\n\tFFLAGS.\n\t* Don't substitute CDEBUG, COPTIMIZE, FOPTIMIZE, or CXXOPTIMIZE.\n\t* Use AC_PROGRAMS_CHECK instead of our own code for checking for a\n\tFortran compiler.\n\t* Add Makeconf to the list of files to create.\n\n\t* src/Makefile.in (octave): Use ALL_LDFLAGS instead of LDFLAGS.\n\n\t* Makeconf.in (ALL_CFLAGS, ALL_CXXFLAGS, ALL_LDFLAGS): New macros.\n\t* Allow the user to set CFLAGS, CXXFLAGS, and FFLAGS without\n\tscrewing things up.\n\t* (CDEBUG, COPTIMIZE, FOPTIMIZE, CXXOPTIMIZE): Delete.\n\t* Provide rules for making .o from .cc or .c files that use\n\tALL_CXXFLAGS and ALL_CFLAGS.\n\n\t* src/Makefile.in: Generate dependencies automatically using the\n\tmethod described in the GNU make manual.\n\t* liboctave/Makefile.in: Likewise.\n\n\t* All Makefile.in files: Set TOPDIR and include $(TOPDIR)/Makeconf.\n\t* Makeconf.in: New file, for most configuration options.\n\n\t* tc-rand.cc (rand_internal): Return an empty matrix for rand (0).\n\nWed May 12 01:32:36 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (clean_up_and_exit): Call close_plot_stream before\n\tquitting.\n\n\t* Version 0.71.4.\n\n\t* pr-output.cc (octave_print_internal (ostrstream&, Matrix&)):\n\tHandle wrapping columns neatly, respecting value of split_long_rows.\n\t* (octave_print_internal (ostrstream&, ComplexMatrix&)): Ditto.\n\t* (octave_print_internal (ostrstream&, Range&)): Ditto.\n\n\t* user-prefs.cc (split_long_rows): New preference variable and\n\tfunction.\n\t* builtins.cc (builtin_string_variables): Add to list with default\n\tvalue == true.\n\nTue May 11 02:20:43 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* pr-output.cc (pr_max_internal): Don't count Inf or NaN when\n\tlooking for max value.\n\t* (pr_min_internal): Likewise, for min values.\n\n\t* pr-output.cc (pr_any_float): Merge pr_float and pr_imag_float.\n\n\t* pr-output.cc (any_element_is_inf_or_nan (Matrix&)): New function.\n\t* (any_element_is_inf_or_nan (ComplexMatrix&)): New function.\n\t* (all set_format functions (except Range)): Consider Inf and NaN\n\twhen computing field width (we'll either print \"Inf\" (possibly\n\twith a sign) or \"NaN\").\n\n\t* pr-output.cc (pr_float): Handle Inf and NaN.\n\t* (pr_imag_float): Ditto.\n\n\t* pr-output.cc (set_format_style): Make format short set precision\n\tto 3 and max field width to 8.\n\n\t* pr-output.cc (pr_float): Don't print a sign for -0.0.\n\t* (pr_imag_float): Ditto.\n\n\t* pr-output.cc (all set_format functions): Return the actual field\n\twidth computed or 0 if free format.  For complex, return both real\n\tand imaginary field widths.\n\t* Include pager.h for terminal_rows() and terminal_columns().\n\n\t* pr-output.cc (pr_complex): If imaginary part is -0.0, print a\n\tminus sign but convert the value to 0.0 before printing.\n\n\t* octave.cc (parse_and_execute (FILE *, int)): Don't use readline\n\tto read commands from files.\n\t* (parse_and_execute (char *, int)): Set reading_script_file\n\tbefore calling get_input_from_file.\n\n\t* Version 0.71.3.\n\n\t* src/Makefile.in (deps): New target.\n\t* Update dependencies using the output from running `make deps'.\n\n\t* pr-output.cc (set_output_prec_and_fw): New function.\n\t* (set_format_style): Use it.\n\t* (set_format functions): Use user_pref variables for precision\n\tand field width.\n\n\t* variables.cc (octave_real_scalar_variable): New function.\n\t* buitlins.cc (builtin_string_variables): Add output_precision and\n\tmax_field_width to the list (really need a separate list for\n\tnumeric values...).\n\t* user-prefs.cc (set_output_max_field_width): New function to be\n\tcalled when output_max_field_width changes.\n\t* (output_precision): Likewise, for output_precision.\n\n\t* sighandlers.cc (pipe_handler_error_count): New global variable.\n\t* (sigpipe_handler): Use it to keep from printing more than one\n\tbroken pipe message between prompts.\n\t* (input.cc): Reset pipe_handler_error_count before printing the\n\tprompt.\n\nMon May 10 13:06:52 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* sighandlers.cc (sigpipe_handler): Issue warning and return\n\tinstead of aborting.\n\n\t* user-prefs.cc (all sv_* functions): Don't delete previous value\n\tof a preference string if the new value is bogus.\n\n\t* user-prefs.cc (all sv_* functions and all functions that handle\n\tuser preferences): Return 0 for success, -1 for failure.\n\t* symbtab.cc (symbol_record::define): Check return value of sv_fcn\n\tand restore previous value on failure.\n\t* symtab.h (sv_Function typedef): Change to return int, not void.\n\t* builtins.h (sv_Function typedef): Ditto.\n\nSun May  9 18:25:00 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* user-prefs.cc (all sv_* functions): Issue a warning if the user\n\tgives us something that's not a string.\n\nSat May  8 23:40:59 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* ColVector.cc (ColumnVector::min): Upper loop limit is len, not 0.\n\t* (ComplexColumnVector::min): Ditto.\n\t* RowVector.cc (RowVector::min): Ditto.\n\t* (ComplexRowVector::min): Ditto.\n\nFri May  7 18:41:29 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* pr-output.cc (set_format_style): New function, extracted from\n\tbuiltin_format().\n\t* t-builtins.cc (builtin_format): Call set_format_style to do real\n\twork.\n\n\t* pr-output.cc: New file for special formatted printing funcions.\n\t* tree-const.cc (tree_constant_rep::eval): Use new functions.\n\n\t* user-prefs.cc (sv_pager_binary): New function.\n\t* user-prefs.h (user_preferences) Add new field, pager_binary.\n\t* builtins.cc (builtin_string_variables): Add PAGER to the list.\n\t* utils.cc (default_pager): New function.\n\t* Makefile.in: Define DEFAULT_PAGER for utils.cc, not pager.cc.\n\t* pager.cc (get_pager): Delete function.\n\t* Use user_pref.pager_binary instead of calling get_pager().\n\nThu May  6 11:05:06 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* pager.cc (pager_buf): Declare as static pointer to ostrstream.\n\t* (initialze_pager): Delete old pager_buf and create new one for\n\teach batch of output.  This is needed because once str() is called\n\tfor pager buf, it will no longer grow.\n\n\t* pager.cc (maybe_page_output): Take care of deleting buffer after\n\tstr() is called.\n\t* (flush_output_to_pager): Likewise.\n\t* t-builtins.cc (builtin_ls): Likewise.\n\t* (builtin_set): Likewise.\n\t* (builtin_show): Likewise.\n\t* tc-extras.cc (process_format): Likewise.\n\t* (process_format): Likewise.\n\t* tree-plot.cc (tree_plot_command::eval): Likewise.\n\nWed May  5 10:45:39 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc (builtin_shell_command): Buffer characters with an\n\tostrstream and call maybe_page_output instead of writing directly\n\tto cout.\n\t* (builtin_warranty): Likewise.\n\t* tc-extras (do_printf): Likewise.\n\t* tree.cc (tree_identifier::eval): Likewise.\n\t* (tree_assignment_expression::eval): Likewise.\n\t* (tree_multi_assignment_expression::eval): Likewise.\n\t* tree-const.cc (tree_constant_rep::eval): Likewise.\n\t* t-builtins.cc (builtin_help): Likewise.\n\t* (builtin_ls): Likewise.\n\t* (builtin_who): Likewise.\n\n\t* user-prefs.h user-prefs.cc (page_screen_output): New preference.\n\t* builtins.cc (string_variables): Add to list with default value\n\tof true.\n\n\t* input.cc (octave_gets): If interactive, call flush_to_pager()\n\tbefore prompting.\n\n\t* utils.cc (terminal_rows): Move to pager.cc\n\t* (terminal_columns): Likewise.\n\t* (get_pager): Likewise.\n\n\t* pager.h, pager.cc: New file to handle pager stuff.\n\t* src/Makefile.in: Fix things to distribute and compile them.\n\n\t* libcruft/Makefile.in (CRUFT_OBJ): Strip $(srcdir)/ and convert\n\tfrom .f to .o in two steps since some versions of GNU make strip\n\tthe leading ./ from the output of $(wildcard), causing my pattern\n\tmatch to fail if compiling in the source tree.\n\nTue May  4 09:13:52 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* symtab.cc (symbol_record::define (symbol_record *)): Delete old\n\tname before saving new name.\n\t* (symbol_record::document): Likewise, for var.help and fcn.help.\n\n\t* parse.y (ABORT_PARSE): Renamed from DO_ABORT.\n\nMon May  3 01:00:04 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc: Define destructors for every class in tree.h.  It\n\tappears that it should always be ok to delete everything in a\n\tcommand tree once we're done executing it.  Function definitions\n\tare still ok because the parser doesn't set global_command to the\n\ttree_function we've built (that's saved somewhere in the symbol\n\ttable and shouldn't be deleted until we clear or redefine the\n\tfunction).\n\n\t* utils.cc (pathstring_to_vector): Do memory management here so\n\tcallers don't have to.\n\t* (default_path): Likewise.\n\n\t* utils.cc (make_absolute): Return current_path (not a copy) since\n\tit is static.\n\t* (get_working_directory): Return the_current_working_directory\n\t(not a copy) since it is global.\n\n\t* utils.cc (cleanup_tmp_files): Delete filename when done.\n\n\t* parse.y: Replace output to cerr with calls to error() or warning().\n\t* DO_ABORT: New macro.  Use it instead of YYERROR for errors that\n\twe detect, and call yyerror since bison doesn't.\n\t* (param_list1): Detect invalid parameter lists.\n\t* (yyerror): Don't print pointer if it is past the end of the line.\n\nSun May  2 13:03:09 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tc-extras.cc (process_format): Use ostrstream instead of a\n\tfixed-size character string to buffer the format.\n\n\t* utils.cc (terminal_rows): Get info from readline variable\n\tinstead of hardcoded constants.\n\t* (terminal_columns): Likewise.\n\n\t* utils.cc (maybe_page_output): New function.\n\t* t-builtins.cc (builtin_help): Use it.\n\t* (builtin_who): Ditto.\n\t* Don't include procstream.h anymore since we no longer need it.\n\n\t* utils.cc (jump_to_top_level): Call run_all_unwind_protects ()\n\tbefore jumping back to the top level.\n\nSat May  1 20:59:12 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* unwind-prot.cc unwind-prot.h: New files to implement memory\n\tcleanup stuff.\n\t* src/Makefile.in: Distribute them.\n\n\t* Version 0.71.2.\n\n\t* computer.m: Delete file.\n\t* scripts/Makefile.in (computer.m): Add $(srcdir)/ prefix to\n\tcomputer.in.\n\nFri Apr 30 17:03:04 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Matrix.h (<CLASS>::row (int i)): New function for extracting a\n\trow of a matrix where CLASS is one of Matrix, DiagMatrix,\n\tComplexMatrix, or ComplexDiagMatrix.\n\t* (<CLASS>:: column (int i)): Likewise for columns.\n\t* (<CLASS>::row (char *s)): Likewise, but selection is done with a\n\tcharacter string.  Currently we accept anything beginning with `F'\n\tor `f' to mean the first row and anything beginning with `l' or\n\t`L' to mean the last row.\n\nWed Apr 28 14:23:49 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* scripts/computer.in: New template file for computer.m.\n\t* scripts/Makefile.in (computer.m): Generate a custom computer.m\n\tfile using $target_host_type.\n\t* (clean): Delete computer.m.\n\n\t* configure.in: If last argument is not empty, use its value as\n\tthe TARGET.\n\t* If we aren't given a TARGET, use config.guess to find one.\n\t* Substitute target_host_type.\n\n\t* config.guess: New file, taken from gdb distribution.\n\t* Makefile.in: Distribute it.\n\n\t* tree-const.cc (force_numeric): New parameter, force_str_conv to\n\tallow us to ignore user preference on string to numeric\n\tconversion.\n\t* (make_numeric): Likewise.\n\n\t* tree.cc (tree_matrix::eval): Allow range constants in matrix\n\tlists by simply converting them to matrices.\n\t* Ditto for string constants.\n\nTue Apr 27 17:21:12 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* utils.cc (smells_like_X11): Delete unneeded function.\n\t* builtins.cc (install_builtins): Don't initialize\n\tgraphics_terminal since it's no longer needed.\n\n\t* utils.cc (pathstring_to_vector): Call tilde_expand on each\n\telement of the path.\n\n\t* mappers.cc: Include float.h for DBL_MAX.\n\nWed Apr 21 19:31:12 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* mappers.cc (xisnan (Complex&)): Rename from isnan.\n\t* builtins.cc (mapper_functions): Use xisnan instead of isnan.\n\t* (install_builtins): Special case for linux for geenerating\n\tinfinity and NaN.\n\nMon Apr 19 14:10:55 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.71.1 released.\n\n\t* symtab.cc (char **sorted_list (int& count)) New function.\n\t* (char **sorted_var_list (int& count)): Ditto.\n\t* (char **sorted_fcn_list (int& count)): Ditto.\n\t* t-builtins.cc (builtin_who): Check symbol count too.\n\n\t* utils.cc (send_to_plot_stream): Check is_open(), not just the\n\tstate of the stream.\n\t* (close_plot_stream): Likewise.\n\n\t* procstream.cc, procstream.h: Rewrite, taking a hint from the GNU\n\tfstream class.\n\nSun Apr 18 17:40:54 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* t-builtins.cc (builtin_help): Don't call list_in_columns if\n\tthere isn't anything to list.\n\nFri Apr 16 20:57:15 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Makefile.in (DISTDIRS): List dld here.\n\t* (DISTSUBDIRS): Not here.\n\nThu Apr 15 12:17:08 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.71 released.\n\n\t* scripts/*.m: Improve help messages for most files.\n\n\t* libcruft/Makefile.in: Make libcruft.a here.\n\t* libcruft/Makerules.in: Not here.\n\n\t* PLOTTING: New file.\n\t* Makefile.in: Add it to the list of files we distribute.\n\n\t* g-builtins.cc (builtin_shell_command): New function.\n\t* builtins.cc (general_functions): Add it to the list.\n\n\t* procstream.h, procstream.cc (iprocstream): New class.\n\n\t* lex.l (<MATRIX>{SN}*\\]): Maybe insert a comma after reading a `]'.\n\n\t* t-builtins.cc (builtin_load): Do tilde expansion for the file name.\n\t* (builtin_save): Ditto.\n\nWed Apr 14 10:40:44 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_function::eval): Until we have a proper call frame\n\tunwinding scheme, comment out previous change.\n\n\t* tree.cc (tree_matrix::eval): Brain Transplant.\n\t* (tree_matrix::length): New function.\n\n\t* tree-base.h (matrix_dir): Delete md_none, md_left, and md_up.\n\tThe only valid values are md_unknown, md_right, and md_down.\n\nTue Apr 13 20:07:25 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.h (tree_function::call_depth): New member variable.\n\t* tree.cc (tree_function::eval): Check it to make recursive\n\tfunction calls fail (waiting for proper symbol table handling).\n\n\t* utils.cc (pathstring_to_vector): Don't prepend `.' here.  We do\n\tthat already in default_path() if the user hasn't given us a\n\tloadpath.\n\n\t* t-builtins.cc (builtin_help): Get help for M-files even if they\n\thaven't been compiled yet.\n\t* List M-files we find in the loadpath.\n\n\t* utils.cc (get_m_file_names): Split into two functions, add\n\tparameter to specify whether .m suffix is deleted.\n\n\t* lex.l (grab_help_text): New function.\n\t* (beginning_of_function): New global variable.\n\t* (%|#): Call grab_help_text() if at beginning of a function.\n\t* tree.cc (tree_identifier::document): New function.\n\t* parse.y (func_def2): Use it.\n\t* (help_buf): New global buffer for help text.\n\nMon Apr 12 00:31:09 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* utils.cc (get_m_file_names): New function.\n\t* variables.cc (make_name_list): Use it.\n\n\t* t-builtins.cc (list_in_columns): Put output on an strstream\n\tinstead of in a String.\n\t* (builtin_help): Use an strstream instead of a String for buffering.\n\t* (builtin_who): Likewise.\n\n\t* g-builtins.cc (builtin_keyboard): New function.\n\t* builtins.cc (general_functions): Add to list.\n\n\t* tc-extras.cc (get_user_input): If the user enters `exit',\n\t`quit', or `return', return instead of eval'ing the string.\n\t* Don't abort on empty input.\n\t* Add additional argument to handle debugging via new `keyboard'\n\tfunction.  If doing debugging, keep reading until we see `exit',\n\t`quit', or `return'.\n\n\t* menu.m: New M-file.\n\n\t* New top level plotting functions:\n\n\t    plot.m    semilogx.m  semilogy.m  loglog.m   polar.m\n\t    title.m   xlabel.m    ylabel.m    grid.m     bar.m\n\t    stairs.m  mesh.m      meshdom.m   contour.m\n\n\t* New internal plotting functions:\n\n\t    plot_int.m    plot_2_s_s.m  plot_2_v_v.m  plot_2_v_m.m\n\t    plot_2_m_v.m  plot_2_m_m.m  polar_int.m\n\n\t* New utility functions:\n\n\t    is_scalar.m  is_vector.m  is_matrix.m\n\nSun Apr 11 11:10:29 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* t-buitlins.cc (builtin_ls): New function.\n\t* builtins.cc (text_functions): Add it to the list under the names\n\t`ls' and `dir'.\n\nSat Apr 10 15:13:05 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* procstream.cc (oprocstream::close): Set badbit for stream after\n\tit is closed.\n\n\t* utils.cc (close_plot_stream): New function.\n\t* g-buitlins.cc (closeplot): New builtin function.\n\t* builtins.cc (general_functions): Add to list.\n\n\t* lex.l (cant_be_identifier): New cruft to properly handle the\n\tplot command's `using', `title', and `with' keywords.\n\nFri Apr  9 09:38:25 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Warn if it looks like gnuplot isn't installed.\n\n\t* utils.cc (send_to_plot_stream): Check the user's preference for\n\tthe gnuplot binary.\n\n\t* user-prefs.cc (sv_graphics_terminal): Delete function.\n\t* user-prefs.h (graphics_terminal): Delete variable.\n\n\t* tree-plot.cc (tree_subplot_using::print): Add argument to allow\n\tchecking of columns given in using command and use it.\n\t* (tree_plot_command::eval): Change caller.\n\n\t* parse.y (title): Allow plot title to be any expression.\n\t* tree-plot.cc (subplot_list): Likewise.\n\n\t* tree-plot.cc (tree_plot_command::eval): Don't let lusers try to\n\tmake 2D parametric plots, since that seems to crash gnuplot.\n\n\t* tree.cc (tree_identifier::parse_m_file): Don't try to stash\n\tm-file name or time parsed if we were actually executing a script\n\tfile.\n\n\t* sombrero.m: New M-file to demonstrate 3D plotting.\n\n\t* parse.y (plot_options): Allow them to be specified in any order.\n\n\t* g-builtins.cc (builtin_purge_tmp_files): New function.\n\t* builtins.cc (general_functions): Add to list.\n\n\t* g-builtins.cc, g-builtins.h (builtin_plot): Delete.\n\t* builtins.cc (general_functions): Delete entry for builtin_plot.\n\n\t* t-builtins.cc (builtin_set): Check to see if the user is setting\n\tup parametric plotting.\n\t* tree-plot.cc (parametric_plot): New global variable.\n\t* tree_const.cc (save_three_d): New function.\n\t* tree-plot.cc (tree_subplot_list::print): Handle 3D plots.\n\n\t* Makefile.in: Delete everything having to do with distributing or\n\tmaking gnuplot.\n\t* configure.in: Likewise.\n\nThu Apr  8 10:02:52 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* utils.cc (send_to_plot_stream): New function.  Move declaration\n\tof plot_stream to utils.cc and make static.\n\n\t* t-builtins.cc (builtin_set): New function.\n\t* (builtin_show): Ditto.\n\n\t* lex.l: Handle set command.\n\t* (doing_set): Yet another global variable to control behavior of\n\tthe lexer.\n\n\t* tree-plot.cc (tree_subplot_using::print): Print warning if scanf\n\tformat string is given.\n\n\t* parse.y (ranges1): Allow lower and upper bounds to be optional.\n\t* tree-plot.cc (tree_plot_range::print): Make it work.\n\n\t* tree-plot.cc: New file, extracted from tree.cc.\n\n\t* sighandlers.cc (install_signals): New function.\n\t* (*_handler): New set of functions to handle signals that would\n\totherwise cause us to abort.\n\t* (my_friendly_exit): Call exit from most signal_handlers to clean\n\tup tmp files, etc.\n\n\t* lex.l (do_string_escapes): Correctly handle '' quotes.\n\t* Warn about unrecognized escape sequences but convert them to the\n\tescaped character anyway.\n\t* (EXPON): New definition.  Use it and ? qualifier to shorten the\n\texpressions for matching numbers.\n\t* (ECHAR): New definition.  Use it to correctly match\n\tbackslash-escaped characters in strings.\n\t* Definitions: Surround multi-character definitions in ()'s to\n\tavoid potential problems with things like {DEF}*.\n\t* (QQ): Rename from DQ.\n\t* (DQSTR): New definition for strings in double quotes.\n\t* (DQSTRING): New start state.  Recognizing a naked \" puts us here.\n\t* (\"\\n\"): Turn off quote_is_transpose at the beginning of each line.\n\t* Use error functions instead of writing messages directly.\n\t* Don't include iostream.h -- we don't need it now.\n\t* Do include error.h.\n\nWed Apr  7 13:12:17 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* sighandlers.h, sighandlers.cc: New files for signal handling\n\tfunctions.\n\t* Makefile.in: Include them in the usual places.\n\t* octave.cc (interrupt_handler): Move to sighandlers.cc and rename\n\tto sigint_handler.\n\n\t* utils.cc (mark_for_deletion): New function.\n\t* octave.cc (cleanup_tmp_files): New function.\n\t* octave.cc (main): Register cleanup_tmp_files with atexit\n\t(on_exit for sun).\n\n\t* Stack.h: Template based stack class converted from libg++\n\tgenclass files.\n\t* SLStack.h: Likewise.\n\t* (SLStack::pop): Avoid apparent bug in SLList::remove_front.\n\nTue Apr  6 10:01:52 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (almost_match): New function.\n\t* (plot_style_token): New function.\n\n\t* t-buitlins.cc: Include procstream.h instead of procbuf.h.\n\t* (builtin_help): Simplyfy opening of process output stream.\n\t* (builtin_who): Likewise.\n\nMon Apr  5 13:48:20 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tc-extras.cc (tree_constant_to_scalar): Move to tree-const.cc\n\tand make it a member function called to_scalar.\n\t* (tree_constant_to_vector): Likewise.\n\t* (tree_constant_to_matrix): Likewise.\n\n\t* procstream.h, procstream.cc: New files/classes that implement\n\tan ostream to a process.  Built on top of procbuf from libg++.\n\t* src/Makefile.in: Add them to the lists of files/objects.\n\nSat Apr  3 23:11:56 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Lots of clean-up changes to parse.y, tree.cc, tree.h, and\n\ttree-base.h.  Use more specific types than just <tree *> for\n\tnonterminals.  This allows us to have fewer virtual functions in\n\tthe base class.  Safer.  Cleaner.  Should have always been this\n\tway...\n\nFri Apr  2 10:04:32 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* parse.y, lex.l: Fix grammar to accept plot command very similar\n\tto the gnuplot plot command.\n\nWed Mar 31 13:11:56 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (eval_undefined_error): Until we can figure out how to\n\tclear names without causing problems later on, just remove the\n\tsymbol name.\n\n\t* tree.h (tree_plot_command): New class.\n\t* (tree_plot_limits): Ditto.\n\t* (tree_plot_range): Ditto.\n\t* (tree_subplot_list): Ditto.\n\t* (tree_subplot_using): Ditto.\n\t* (tree_subplot_style): Ditto.\n\n\t* tree-base.h (command_type): Add plot_command to list.\n\nMon Mar 29 09:53:50 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* find_exec.c (ABSOLUTE_FILENAME_P): Also return true if the\n\tgiven filename begins with `.'.\n\n\t* DAE.cc, DAE.h, DAEFunc.h, tc-dassl.cc: Make sure all calls to\n\tdassl and the user-supplied functions have consistent argument\n\tlists.\n\n\t* octave.cc (raw_program_name): New global variable to hold the\n\tunprocessed argv[0].  This is to help dld find the absolute path\n\tto the executing program.\n\t* (initialize_globals): Pass in argc and argv from main.\n\tInitialize raw_prog_name.\n\n\t* builtins.cc (general_functions): Correct help message for dassl.\n\t* g-builtins.cc (dassl_usage): Likewise.\n\n\t* src/Makefile.in: Lots of changes to make things work with or\n\twithout dld.\n\t* Makefile.in: Likewise.\n\t* configure.in: Likewise.\n\n\t* dld: New directory, containing our copy of the dld sources.\n\n\t* dynamic-ld.cc, dynamic-ld.h: New files to implement dynamic\n\tloading functions.\n\t* src/Makefile.in: Add them to the distribution, compile them if\n\tdoing dynamic loading.\n\nSun Mar 28 11:03:15 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: When looking for Fortran compilers, check for fc\n\tlast to avoid confusion with some vendor's /bin/sh fc builtin.\n\t* Handle new argument --with-dld.\n\n\t* g-builtins.cc (builtin_warranty): Add 1993 to list of copyright\n\tdates.\n\nSat Mar 27 17:58:23 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tc-extras.cc: Rename from tree-extras.cc.\n\t* tc-colloc.cc, tc-dassl.cc, tc-det.cc tc-eig.cc, tc-fft.cc,\n\ttc-fsolve.cc, tc-fsqp.cc, tc-ifft.cc, tc-inv.cc, tc-lsode.cc,\n\ttc-lu.cc, tc-npsol.cc, tc-qr.cc, tc-quad.cc, tc-rand.cc,\n\ttc-svd.cc: Split individual functions from tree-extras.cc.\n\n\t* g-builtins.cc (npsol_usage): Improve message.\n\t* (dassl_usage): Likewise.\n\t* (builtin_lsode): Likewise.\n\t* (builtin_fsolve): Likewise.\n\t* (builtin_quad): Likewise.\n\t* builtins.cc (general_functions): Improve corresponding messages.\n\n\t* libcruft/fftpack: New directory for fftpack functions.\n\t* libcrutf/fftpack/*.f: Add implicit double precision (a-h,o-z) at\n\tthe top of every subroutine.\n\n\t* tree-extras.cc (fft): Allow propagation of empty matrices.\n\t* (ifft): Ditto.\n\n\t* Matrix.cc (Matrix::fourier): New function.\n\t* (Matrix::ifourier): Ditto.\n\t* mx-inlines (make_complex): New function.\n\t* tree-extras.cc (fft): Use Matrix::fourier instead of doing real\n\tto complex conversion here and calling ComplexMatrix::fourier.\n\t* (ifft): Likewise, for ifourier.\n\nSat Mar 27 17:56:59 1993  Fook Fah Yap (ffy@eng.cam.ac.uk)\n\n\t* Matrix.cc (ComplexMatrix::fourier): New function for fft.\n\t* (ComplexMatrix::ifourier): New function for inverse fft.\n\n\t* builtins.cc (general_functions): Add fft and ifft to the list of\n\tbuiltin functions.\n\n\t* g-builtins.cc (fft): New function.\n\t* (ifft): Ditto.\n\n\t* tree-extras.cc (fft): New function.\n\t* (ifft): Ditto.\n\nSat Mar 27 13:53:39 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (usage_string): New file scope constant.\n\t* (getopt_option_string): Ditto.\n\n\t* error.cc: Declare all arguments const since we don't change them.\n\n\t* utils.cc (print_str_or_null): Delete unused function.\n\t* utils.h: Delete declaration.\n\n\t* tc-assign.cc, tc-index.cc, tc-inlines.cc, tree.cc,\n\ttree-const.cc: More error message cleanups.\n\n\t* tree-const.cc (print_if_string): Don't write to cerr\n\tunconditionally.\n\nFri Mar 26 22:00:18 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (min): Avoid function calls as arguments for MIN.\n\t* (column_min): Ditto.\n\t* (max): Likewise, for MAX.\n\t* (column_max): Ditto.\n\n\t* tree-const.h (NINT): Make it an inline function instead of a\n\tmacro.\n\n\t* tree-extras.cc (fill_matrix (tree_constant&, double, char*)):\n\tConvert to scalar type for complex values too.\n\n\t* error.h (panic_impossible): New macro to be used in place of\n\tassert (0) calls.\n\t* All .cc files: Replace calls to assert (0) and abort () with\n\tpanic_impossible ().\n\n\t* Many .cc files:: Replace many instances of `cerr << ...' with\n\tcalls to gripe() functions.\n\n\t* gripes.h, gripes.cc: New functions for reporting common errors.\n\t* Makefile.in: Include them in the usual places.\n\nThu Mar 25 18:42:49 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Many .cc files:: Replace many instances of `cerr << ...' with\n\tcalls to error() functions.\n\n\t* error.h, error.cc: New functions for reporting errors in a\n\tconsistent way.\n\t* Makefile.in: Include them in the usual places.\n\nWed Mar 17 17:29:44 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* symtab.cc (symbol_table::save): New functions.\n\t* t-buitlins.cc (builtin_save): Use new functions for saving\n\tsymbols.  Handle case of saving all variables.\n\n\t* g-builtins.cc (builtin_pause): If one argument is given, pause\n\tfor that many seconds before continuing.  Otherwise, wait for user\n\tinput.\n\n\t* symtab.cc (clear): Actually delete undefined symbol_records and\n\tremove their names from the list.\n\n\t* lex.l (lookup_identifier): New function.  Avoid putting global\n\tnames in the local symbol table.\n\t* ({IDENT}): Use it\n\t* ({IDENT}/{S}*=): Ditto.\n\n\t* tc-index.cc (do_scalar_index (tree_constant*, int)): Make\n\tindexing like a([1,1,1,1]) work for scalars.  GAG.\n\nTue Mar 16 20:08:23 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* t-buitlins.cc (builtin_cd): Call tilde_expand (from readline) on\n\tthe argument.\n\n\t* lex.l (discard_until): Delete unused function.\n\t* When reading numbers, abort if scanf fails to read a number that\n\twe think it should.\n\t* (IDENT): New macro to match identifiers.\n\t* ([_a-zA-Z][_a-zA-Z0-9]*): Use the / operator for trailing\n\tcontext and split into two cases instead of trying to do the\n\tlookahead ourselves.\n\n\t* lex.l (do_comma_insert_check): Return the value yyleng had\n\tbefore yyinput() is called.\n\t* (DO_COMMA_INSERT_CHECK): New macro.  This avoids the use of\n\tunput() in do_comma_insert_check() since there seems to be a bug\n\tin flex when calling unput() for '\\n'.\n\n\tNote that this change is necessary if we want to use yyless()\n\tsince we cant call yyless() from outside of yylex(), because\n\tFlex's yyless() is a macro that uses some variables local to\n\tyylex().\n\nMon Mar 15 11:03:43 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_matrix::eval): Undo part of previous change to\n\tmake a = [1,2;3,4]; [a,a;a,a] work again.\n\n\t* parse.y (input): Don't abort for simple_list followed by EOF.\n\nSun Mar 14 14:38:56 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* RowVector.cc (RowVector::operator << ()): Insert a space between\n\teach element.\n\t* (ComplexRowVector::operator << ()): Ditto.\n\n\t* g-buitlins.cc (plot): Don't declare plot_prog or plot_term as\n\tstatic, and don't delete them.\n\n\t* Matrix.h (all checkelem functions): Don't check for range errors\n\tif NO_RANGE_CHECK is defined.\n\nSat Mar 13 10:18:51 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Matrix.cc (ComplexMatrix::prod): Make it work.\n\nThu Mar 11 00:08:09 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Matrix.h (ellum): Delete function.\n\t* Declare and define new const elem, checkelem, and operator()\n\tfunctions.\n\n\t* ColVector.cc, DiagMatrix.cc, RowVector.cc, Matrix.cc, ODE.cc,\n\tLinConst.cc, FEGrid.cc, DAE.cc, Bounds.cc, FEGrid.h:\n\tChange all callers.\n\t* tree-const.cc, tree-extras.cc, xdiv.cc, xpow.cc: Ditto.\n\n\t* tree.cc (tree_matrix::eval): Improve row and column mismatch\n\tchecking -- [[1,2];[3,4]] works now, and [1,2;3,4,[5,6]] is\n\trejected.\n\t* Reformat error messages to include `error:' prefix.\n\nWed Mar 10 14:02:09 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (do_comma_insert): New global variable.\n\t* (reset_parser): Reset it.\n\t* lex.l (do_comma_insert_check): New function.  Call it wherever a\n\ttoken can be directly followed by '['.\n\t* (\\[{S}*): Check the value of do_comma_insert.\n\n\t* lex.l ([_a-zA-Z][_a-zA-Z0-9]*): Only look for names in the\n\tcurrent symbol table.\n\n\t* parse.y (word_list_cmd): Special case to disallow use of clear\n\tinside a fuction body.\n\n\t* parse.y (CLEAR): New %token.\n\t* lex.l ([_a-zA-Z][_a-zA-Z0-9]*): Return it if token is \"clear\".\n\n\t* t-builtins.cc (builtin_clear): Allow global symbols to be\n\tcleared.\n\n\t* symtab.cc (symbol_table::undefine): Clarify comment.\n\t* (symbol_table::clear): Don't actually remove names from the\n\ttable, just force them to be undefined.\n\n\t* tree.h (tree_function): Delete unused data member `id'.\n\t* tree.cc (tree_function constructors): Don't initialize id.\n\nMon Mar  8 15:50:28 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.70 released.\n\n\t* src/Makefile.in: Update dependencies.\n\n\t* tree.h: Include stdio.h, for FILE.\n\n\t* gnuplot-build: For now, always define -DNOGAMMA.\n\t* configure.in: Don't check for gamma().\n\n\t* libcruft/Makerules.in: Don't use lib.a(obj.o) style dependencies\n\tbecause it's too slow for large archives.\n\t* liboctave/Makefile.in: Ditto.\n\nSun Mar  7 16:33:39 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (parse_and_execute): Save and restore current column\n\tnumber.  Set input line and column number to zero.\n\t* tree.cc (parse_m_file): Likewise.\n\n\t* tree.cc (tree_identifier::parse_m_file (FILE*, int*)): New\n\tfunction.  If a parse error occurs, ensure that the symbol is\n\tcleared from the global symbol table.\n\t* (tree_identifier::parse_m_file (char*, int): Use it.\n\n\t* tree.cc (tree_identifier::do_lookup): New function.\n\t* (tree_identifier::eval): Use it.\n\n\t* utils.cc (decode_prompt_string): Really do use value of PWD.\n\n\t* user_prefs.cc (sv_loadpath, sv_ps1, sv_ps2, sv_pwd,\n\tsv_gnuplot_binary, sv_graphics_terminal): New functions.\n\t* (sv_graphics_terminal): Warn if terminal isn't valid, but set it\n\tanyway (it's too late to do anything by the time the function is\n\tcalled).\n\t* In functions that use these variables:  Use the value from the\n\tuser_pref structure instead of doing a symbol table lookup.\n\n\t* builtins.cc (builtin_string_variables): Add functions to call\n\tfor LOADPATH, PS1, PS2, PWD, gnuplot_binary, and graphics_terminal.\n\n\t* builtins.cc (PS2): New builtin_string_variables.  Set default\n\tvalue to \"> \".\n\t* input.cc (octave_gets): Use it instead of no prompt for\n\tcontinued input.\n\n\t* parse.y (yyerror): Use line, column, file name, and text of\n\tcurrent input line to print better parse error messages.\n\n\t* lex.l (NEW_MATRIX): New exclusive start state.  Need this to be\n\table to match \\[{SN}* _and_ get secondary prompting right.\n\n\t* input.cc (octave_read): Keep track of current input line.\n\t* tree.cc (parse_m_file): Save and restore current line number.\n\n\t* lex.l (all patterns): Keep track of current input column.\n\t* (fixup_column_count): New function to deal with patterns that\n\tmatch more than one line.\n\n\t* input.h, input.cc (current_input_line): Global pointer to\n\tthe text of the current input line.\n\n\t* parse.y, parse.h (input_line_number, current_input_column): New\n\tglobal variables.\n\n\t* Almost all source files: Finish (for now, at least) the\n\treorganization we started for global variables.\n\nWed Mar  3 14:49:59 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tc-assign.cc, tc-index.cc, tc-inlines.cc: New files, split out\n\tfrom tree-const.cc.\n\n\t* Almost all source files: reorganize so that all global data is\n\tdeclared in some include file or another.  It probably wouldn't\n\thurt to do some more reorganizing to try to eliminate the amount\n\tof global information...\n\nTue Mar  2 20:49:35 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* variables.h, variables.cc: New files for handling things that\n\tneed symbol table information.  Lots of files changed to include\n\tvariables.h, which now includes the extern declarations for the\n\tsymbol tables.  The declarations of the symbol tables are now in\n\tvariables.cc, but they are still initialized in octave.cc.\n\nMon Mar  1 11:35:03 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* builtins.h (builtin_string_variables): New field, sv_function,\n\tholds a pointer to the function to call when a variable changes.\n\t* builtins.cc (string_variables): Initialize sv_function field.\n\t* (install_builtins): While installing builtin string variables,\n\tstash sv_function and, if it isn't NULL, call it to initialize\n\tglobal variable user_pref.\n\n\t* symtab.h (symbol_record): New field, sv_fcn, holds a pointer to\n\tthe function to call when a variable changes.\n\t* symtab.cc (symbol_record::define): Call sv_fcn if it isn't NULL.\n\t* symtab.cc (symbol_record::set_sv_function): New function.\n\n\t* utils.cc, parse.y, tree.cc, tree-extras.cc, tree-const.cc,\n\tidx-vector.cc, builtins.cc, symtab.cc: Instead of calling\n\tfunctions like do_fortran_indexing(), get the user's preference\n\tfrom the global struct user_pref.\n\n\t* utils.h, utils.cc: Delete all functions like do_fortran_indexing()\n\tthat lookup user variables to find integer values.\n\t* user-prefs.h, user-prefs.cc: Move them here, but instead of\n\treturning values, set elements of the new global struct user_pref.\n\n\t* user-prefs.h, user-prefs.cc: New files for handling global\n\tvariables for user preferences.\n\t* Makefile.in: Add them to the SOURCES and INCLUDES macros.\n\n\t* bsd-math/{acosh,asinh,atanh,log1p}.c: Declare all external\n\tfunctions used in each file since they might not be in math.h.\n\t* bsd-math/{scalb,copysign,logb,finite,drem,sqrt}.c: New files\n\tfrom BSD's support.c.  Only using scalb, copysign, logb, and\n\tfinite for now.\n\n\t* configure.in: Move tests for f77 closer to the top.\n\t* Allow configuration to proceed even if we can't find a Fortran\n\tcompiler or f2c.\n\t* Use `here' documents instead of multiple echos for multi-line\n\tmessages.\n\t* Imrpoved checking for missing math functions.\n\nSun Feb 28 17:45:53 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* test/Makefile.in (check): Try to avoid errors from cp.\n\n\t* mappers.cc (xfinite): Put test for HAVE_FINITE first.\n\n\t* libcruft/Makerules.in (LIBCRUFT_DEPEND): Use `=' in assignment\n\tinstead of `:='.\n\n\t* liboctave/Makefile.in: Make an explicit list of sources instead\n\tof using $(wildcard).\n\nThu Feb 25 20:18:12 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* bsd-math/copysign.c: New file.  HP's don't have this?\n\t* configure.in (LIBOBJS): Also check for copysign, log1p, and\n\tlog__L.  For each missing user-level function, add -DFOO_MISSING=1\n\tto DEFS.\n\t* src/missing-math.h: For each function we declare, check the\n\tcorresponding XXX_MISSING macro.  Add declarations for copysign\n\tand log1p.\n\nWed Feb 24 20:39:32 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (<MATRIX>{SN}*\\]/{S}*==): Change scanning pattern to\n\t<MATRIX>{SN}*\\]{S}*/== in order to keep flex from generating any\n\tbacktracking code.\n\t* (<MATRIX>{SN}*\\]/{S}*=): Likewise.\n\nTue Feb 23 02:45:00 1993  John W. Eaton  (jwe@ward.che.utexas.edu)\n\n\t* Version 0.69 released.\n\n\t* mappers.cc [_AIX && __GNUG__] : Provide a definition for\n\tfinite(), since whatever version we get from the system when using\n\tg++ doesn't work (note that it does seem to work with gcc, xlc,\n\tand xlC).\n\n\t* bugs.texi: Note that the math.h file from libg++ declares\n\tfinite() incorrectly for some systems.\n\nMon Feb 22 02:04:16 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Look for runtest, but only believe that it exists\n\tif we can also find expect.\n\t* test/Makefile.in (check): Run tests in build directory, not\n\tsource directory.\n\n\t* tree.cc (reading_script_file): New global variable.\n\t* (parse_m_file): Use it, and properly save and restore state so\n\tthat nested script files will work.\n\n\t* octave.cc (parse_and_execute): Properly save and restore state\n\tso that nested script files will work.\n\t* Don't close input file here.\n\n\t* input.cc (get_input_from (FILE*)): Don't declare mf_instream\n\tstatic.  Set mf_instream if reading and M-file or a script file.\n\n\t* parse.y: Minor changes to accomodate new lexer.\n\n\t* lex.l: Major overhaul in an attempt to do better string\n\thandling.  Looks much simpler and even seems to work.\n\t* (do_string_escapes): New function.\n\nSat Feb 20 00:40:32 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc (builtin_npsol): If npsol is missing, return empty\n\tmatrices for x and phi, and -1 for inform.\n\n\t* num2str.m: Use %g, not %f.\n\n\t* tree.cc (parse_m_file): Save and restor curr_sym_tab, because\n\tyyparse may mess with it if it encounters a function definition.\n\t* tree-extras.cc (eval_string): Ditto\n\t* octave.cc (parse_and_execute): Ditto\n\n\t* Makefile.in (DISTDIRS): Add bsd-math to list.\n\n\t* src/Makefile.in (LIBOBJS): New macro, value set by configure.\n\t(vpath): Add @srcdir@/../bsd-math for LIBOBJS.\n\t(octave): Add $(LIBOBJS) to deps.\n\t* gnuplot-build/Makefile.in: Likewise, for notgnuplot.\n\n\t* configure.in: Use AC_REPLACE_FUNCS to Check for acosh, asinh,\n\tatanh, and gamma.\n\n\t* bsd-math: New directory for functions from the BSD math library\n\tto use as replacements for missing functions.\n\n\t* parse.y (semi_comma, comma_semi): New rules.\n\t(simple_list, simple_list1): Use them to allow empty statements.\n\t(list, list1): Likewise.  This allows empty commands as long as\n\tthe empty command doesn't contain any newlines.\n\n\t* parse.y (simple_assign): New rule, allows things like a = b = c.\n\t(multi_assign): Extracted from assignment.\n\t(assignment): Split into simple_assign and multi_assign.\n\t(expression): Allow '(' simple_assign ')' to be an expression.\n\n\t* tree-extras.cc (eval_string): Return result of last expression\n\tevaluated, to make things like `eval ('1+1;')*2' work.\n\nFri Feb 19 19:45:21 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc (builtin_pwd): Use getcwd, which is defined in\n\tunistd.h, instead of getwd, which seems to be a BSDISM.\n\t* utils.cc (decode_prompt_string): Ditto.\n\t* (get_working_directory): Ditto.\n\n\t* arith_ops.cc (DIVIDE_BY_ZERO_ERROR):  Don't rely on\n\tHAVE_IEEE_MATH, use HAVE_ISINF, HAVE_FINITE, and HAVE_ISNAN\n\tinstead.\n\t* configure.in: Don't define HAVE_IEEE_MATH.\n\n\t* tree-extras.cc: Include stdio.h for FILE.\n\nThu Feb 18 10:17:38 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (gobble_leading_white_space): New function.\n\t* (is_function_file): New function.\n\n\t* (parse_m_file): Handle case of .m file being just a file of\n\tcommands to execute.\n\t* Add optional argument to specify whether to execute a script\n\tfile.\n\t* Return whether a script file was executed.\n\t* (tree.cc, tree-extras.cc): Change callers.\n\n\t* octave.cc (parse_and_execute): new functions.\n\t* (execute_startup_files): Use them.\n\n\t* lex.l (<COMMENT>\\n): Don't gobble new line.\n\n\t* num2str.m: Don't print '\\n'.\n\nWed Feb 17 21:59:55 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* mappers.cc: Simplify and correct finite, isinf, isnan functions.\n\t* test/octave/t7.oct: New test for finite, isinf, and isnan\n\tfunctions.\n\n\t* configure.in: Define HAVE_IEEE_MATH if isnan and either finite\n\tor isinf is available.\n\n\t* builtins.cc (mapper_functions): Check HAVE_ISNAN instead of\n\tHAVE_IEEE_MATH to determine whether or not to define isnan().\n\n\t* mappers.cc: Don't check for HAVE_IEEE_MATH.  Just check for\n\tindividual functions directly.\n\n\t* g-builtins.cc (npsol_usage): Correct usage message.\n\n\t* g-builtins.cc: Don't include unistd.h unless HAVE_UNISTD_H is\n\tdefined.\n\t* t-builtins.cc: Ditto.\n\t* utils.cc: Ditto.\n\nTue Feb 16 00:35:44 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.68 released.\n\n\t* tree.cc (parse_m_file): Set reading_m_file before calling\n\tget_input_from_file.\n\t* Don't mess with current_infile.\n\n\t* input.cc (get_input_from_file): Set mf_instream if we are\n\treading an M-file.  Otherwise, set rl_instream, (even if we aren't\n\treally using readline -- this is just the `normal' input stream).\n\t* Don't use current_infile.\n\t* (octave_read): If not interactive, check reading_m_file to\n\tdetermine where to look for input.\n\n\t* octave.cc (main): Don't use readline if we aren't interactive.\n\n\t* libcruft/misc/Makefile.in (local-dist): Make sure we don't\n\tdistribute a bogus d1mach.f.\n\t(dist): Ditto.\n\n\t* tree-extras.cc (convert_to_ans_assign): New global variable.\n\t(eval_string): Conditionally turn off assignment to `ans', for\n\tget_user_input ().\n\t* parse.y (ans_expression): Use it.\n\t* lex.l (reset_parser): Reset it.\n\n\t* g-builtins.cc (builtin_input): New function.\n\t* builtins.cc (general_fucntions): Add it to the list.\n\t* tree-extras.cc (get_user_input): Do most of the real work.\n\nMon Feb 15 01:14:40 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* t-builtins.cc (load_variable): New function.\n\t(builtin_load): Use it.\n\n\t* Makefile.in (SUBDIRS): Add the test directory.\n\t(check): Don't depend on all.\n\nSat Feb 13 05:17:53 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (determinant, lu, matrix_exp, matrix_log,\n\tmatrix_sqrt): Handle empty matrix argument.\n\n\t* Matrix.h: Add constructors of the form Matrix (double a) and\n\tColumnVector (double a) to make it even easier to form single\n\telement vectors.\n\nFri Feb 12 03:27:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (main): Add -v option that will print the version\n\tstring and quit with a successful exit status.\n\nThu Feb 11 00:46:34 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (eig): If given an empty argument, return enough\n\tempty matrices to fill all possible LHS variables.\n\t(qr): Likewise.\n\t(svd): Likewise.\n\n\t* tree-const.cc (fortran_style_matrix_assignment): Do the right\n\tthing if LHS is an empty matrix.\n\n\t* tree-extras.cc (qr): Handle empty matrix argument.\n\n\t* Matrix-ext.cc (QR): Make it work (really!).\n\t(ComplexQR): Ditto.\n\nWed Feb 10 00:56:31 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* xdiv.cc (xdiv (ComplexMatrix& a, ComplexMatrix& b)): Do\n\tbtmp.solve (atmp), like the other three xdiv's.  Argh!\n\n\t* tree-extras.cc (eval_string): New function.  Mostly works but\n\tcould be very fragile.  We desperately need some sort of\n\t`unwind-protect' scheme to avoid disaster when octave is\n\tinterrupted.\n\n\t* g-builtins.cc (builtin_eval): Instead of just aborting, call\n\teval_string if given one argument.\n\n\t* input.cc (octave_read): If get_input_from_eval_string is\n\tnonzero, stuff current_eval_string into buf for flex to read.\n\n\t* tree-extras.cc (char *current_eval_string): New global variable\n\tfor eval().\n\t* (int get_input_from_eval_string): Ditto.\n\n\t* Update copyright notices to include 1993 (now that it's\n\tFebruary...).\n\nTue Feb  9 14:35:08 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.67 released.\n\n\t* tree-extras.cc, tree-const.cc: Check the value of the variable\n\t`propagate_empty_matrices' to decide what to do about empty\n\tmatrices in binary and unary operations and some function calls.\n\n\t* builtins.cc (builtin_string_variables): New global variable\n\t`propagate_empty_matrices' with initial value `warn'.\n\t* utils.cc (propagate_empty_matrices): New function.\n\nMon Feb  8 19:46:51 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-const.cc: Finish changes required to make zero-one indexing\n\twork for indexing and assignment.\n\nSat Feb  6 15:54:10 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* builtins.cc (builtin_string_variables): New global variable\n\t`prefer_zero_one_indexing' with initial value `false'.\n\t* utils.c (prefer_zero_one_indexing): New function.\n\nFri Feb  5 13:03:14 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* idx-vector.h, idx-vector.cc: Major overhaul to help with\n\tzero-one style indexing.\n\t* tree-const.cc (matrix_to_index_vector): Delete functions.\n\t* (functions that use idx_vectors): Update for new idx-vector\n\tstuff.\n\n\t* arith-ops.cc: Don't declare matrix_to_fortran_indices.\n\n\t* tree-const.cc (matrix_to_index_vector): Add new argument,\n\tallow_neg_one, with default value of false.\n\t* (matrix_to_fortran_indices): Add new argument, allow_zero, with\n\tdefault value of false.\n\n\t* g-builtins.cc (builtin_find): New function.\n\t* builtins.cc (general_fucntions): Add it to the list.\n\t* tree-extras.cc (find_nonzero_elem_idx (tree_constant)): Do\n\tmost of the real work.\n\t* tree-extras.cc (find_nonzero_elem_idx (const Matrix&): Do the rest.\n\t* (find_nonzero_elem_idx (const ComplexMatrix&): Ditto, for complex.\n\nWed Feb  3 00:54:01 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in (DEFAULT_DOT_O_FROM_DOT_F): If using f2c, quote\n\twith single quotes instead of double quotes to avoid problems on\n\tsystems (like the NeXT) that strip \\'s from double quoted strings.\n\n\t* utils.c (empty_list_elements_ok): New function.\n\t* tree.cc (matrix_list::eval): Use it.\n\t* builtins.cc (builtin_string_variables): New global variable\n\t`empty_list_elements_ok' with initial value `warn'.\n\n\t* utils.cc (check_str_pref): New function.\n\t* (resize_on_range_error, prefer_column_vectors,\n\twarn_comma_in_global_decl, do_fortran_indexing,\n\timplicit_str_to_num_ok, treat_neg_dim_as_zero,\n\tok_to_lose_imaginary_part, return_last_computed_value,\n\tsilent_functions, print_answer_id_name): Use it instead of\n\tneedlessly duplicating code.\n\nTue Feb  2 16:58:02 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (\"'\"): If it looks like we're defining a matrix, don't set\n\tthe start condition to be MAYBE_QSTRING.  GAK.  There has to be a\n\tbetter way...\n\n\t* lex.l: Increment and decrement promptflag instead of just\n\tsetting its value.  This should help get prompting right for\n\tthings like if [1,2;3,4] NL ...\n\t* input.cc (octave_gets): In order to issue a prompt, Require\n\tpropmtflag to be greater than zero, not just nonzero.\n\n\t* tree.cc (tree_if_command): Allow matrices as the expression to\n\ttest.  Unlike Matlab, a complex value is false only if both the\n\treal and imaginary parts are 0.\n\t* tree.cc (tree_while_command): Ditto.\n\n\t* tree.cc (tree_for_command): Allow matrices and complex values\n\tin the expression.  For matrices, assign each column in turn to\n\tthe dummy variable.\n\n\t* Matrix-ext.cc (qr): Make it work.  The LAPACK book gags me again!\n\n\t* xdiv.cc: When computing right division with complex matrices,\n\tuse hermitian() instead of transpose().\n\n\t* lex.l: Return IMAG_NUM for a numeric constant followed by\n\t[iIjJ], but don't allow spaces between the numeric constant and\n\tthe letter (it causes problems inside `[]' where spaces matter...\n\nMon Feb  1 17:15:19 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree_extras.cc (rand_internal): Make the random number generator\n\tgive us a different sequence every time we start octave unless we\n\tspecifically set the seed.\n\nThu Jan 28 00:10:24 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.66 released.\n\n\t* configure.in: Define PLOTLIB in addition to adding -DUNIXPLOT to\n\tDEFS if we find -lplot, and call AC_SUBST for PLOTLIB.\n\n\t* QP.cc: Define constructors here.\n\t* QP.h: Not here.\n\n\t* QP.cc (All constructors that are given H): Force H to be\n\tsymmetric.\n\t* (make_h_symmetric): New function.\n\nWed Jan 27 01:35:53 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* arith-ops.cc (do_unary_op): Do the right thing for complex\n\tlogical not operator.\n\t* Matrix.cc (ComplexMatrix::operator ! (void)): Return Matrix\n\tinstead of ComplexMatrix.\n\t* mx-inlines.cc (not (Complex *d, int len)): For each element of\n\td, return (d[i] == 0.0), not (d[i] != 0.0), and return it as a\n\tpointer to double, not Complex.\n\n\t* configure.in: Check for libcruft/qpsol/qpsol.f.\n\t* Create Makefile in libcruft/qpsol.\n\n\t* libcruft/qpsol: New directory.  Copy QPSOL sources here.\n\t* libcruft/qpsol/Makefile.in: New file.\n\t* libcruft/qpsol/README.MISSING: New file.\n\t* libcuft/Makefile.in: Include qpsol in list of directories to\n\tmake.\n\n\t* QPSOL.h, QPSOL.cc: New file for solving QPs with Gill and\n\tMurray's QPSOL.\n\n\t* QLD.h, QLD.cc: Delete all minimize functions except\n\tVector minimize (double&, int&).\n\n\t* QP.h: Declare minimize functions virtual.\n\t* (Vector minimize (double&, int&): Declare as a pure virtual\n\tfunction.\n\n\t* QP.cc: New file to implement generic minimize functions.\n\nTue Jan 26 00:27:13 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l: Recognize numbers of the form .{digits}E{digits} and\n\t.{digits}E[+-]{digits}\n\n\t* lex.l: Recognize .\\ as ELEFTDIV.\n\t* parse.y: Handle ELEFTDIV.\n\t* tree.cc (tree_binary_expression::eval): Handle el_leftdiv.\n\n\t* arith-ops.cc (do_binary_op): Handle element by element left\n\tdivision.  Fix some errors in element by element right division.\n\n\t* tree-base.h (enum expression_type): Add el_leftdiv.\n\n\t* Version 0.65 released.\n\n\t* tree-const.cc (tree_constant_rep::eval (tree_constant *args, int\n\tnargin, int nargout, int print)): Fix another brain-o in making\n\trecursive call.s\n\n\t* src/Makefile.in: Complete changes for CXX instead of C++ make\n\tvariables.\n\n\t* tree-const.cc: For assignment and indexing functions, treat\n\tcomplex scalars and matrices in the same branch of the switch as\n\treal scalars and matrices -- the double_value() and matrix_value()\n\tfunctions take care of checking to see if it's ok to lose the\n\timaginary part.\n\n\t* tree-const.h (tree_constant_rep::is_numeric_type): New function.\n\t* tree-const.h (tree_constant::make_numeric functions): Use it.\n\n\t* tree-const.h (tree_constant::make_numeric functions): Return\n\t*this for complex constants too.\n\nMon Jan 25 18:31:06 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (Matrix min (Matrix&, Matrix&)): Loop over nc and\n\tnr, not nr and nr.\n\t* (Matrix max (Matrix&, Matrix&)): Ditto.\n\n\t* tree-const.cc (tree_constant_rep::mapper): Fix brain-o in making\n\trecursive call.\n\nSun Jan 24 20:05:39 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: If using f2c, explicitly check for -lf2c.  If it's\n\tnot found, look for -lF77 and -lI77.  If a suitable combination\n\tisn't found, print a warning.\n\n\t* src/Makefile.in liboctave/Makefile.in: GNU Make 3.63 uses CXX\n\tand CXXFLAGS instead of C++ and C++FLAGS.  Fix things so that 3.63\n\twill work without sacrificing compatibility with earlier versions.\n\n\t* tree-const.cc (tree_constant_rep::diag (tree_constant&)): Fix\n\tbrain-o in forcing argument to be numeric.\n\nFri Jan 22 15:03:42 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (interrupt_handler): Declare to take int argument.\n\n\t* NPSOL.cc (npsol_objfun): Delete leftover debugging message.\n\nThu Jan 21 14:28:24 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Check version of gcc and issue a warning if it\n\tlooks like 1.something.\n\t* Check for g++.  Issue a warning if it is missing or if it is\n\tthere but it looks like verion 1.something.\n\n\t* flibs.sh, f2c-compat.sh: Change file permission to 755 to avoid\n\tproblems if the uid of the installer is different from the uid of\n\tthe owner of the files.\n\nWed Jan 20 04:18:49 1993  John W. Eaton  (jwe@june.che.utexas.edu)\n\n\t* libcruft/Makerules.in (@DOT_O_DOT_F_C[1234]@): Patterns deleted.\n\t* configure.in: Do multiple line sed substitutions the right way.\n\nTue Jan 19 14:50:50 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Use new AC_WITH to accept --with-f2c instead of\n\t--use-f2c.\n\t* Use new AC_HAVE_LIBRARY to find -lplot.\n\n\t* flibs.sh: Actually avoid including duplicate -lflags.\n\t* Use test, not `['.\n\nSun Jan 17 16:57:02 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Matrix.h: Declare operator+ and operator- functions for vectors.\n\t* RowVector.cc: Define half of them.\n\t* ColVector.cc: Define the other half.\n\nFri Jan 15 03:00:46 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/Makefile.in (install): Include version number in name of\n\tinstalled binary and make a link to $(bindir)/octave.\n\n\t* Version 0.64 released.\n\n\t* t-builtins.cc (builtin_clear): Don't allow the user to clear\n\tglobal symbols by name.  If he tries, issue a warning.\n\n\t* tree.cc (tree_identifier::eval_undefined_error):  Don't clear\n\tundefined symbols from the global or local (function) symbol\n\ttables.\n\nThu Jan 14 02:10:20 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_function::eval): Save old and set current symbol\n\ttable context, so eval_undefined_error() doesn't wipe out top\n\tlevel symbols.\n\n\t* Version 0.63 released.\n\nWed Jan 13 13:16:56 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Nearly every .h and .cc file: Add interface and implementation\n\t#pragmas for G++ in hopes of making smaller objects with -g.\n\n\t* tree-const: Properly handle assignments like A(:) = RHS when\n\tdo_fortran_indexing is true.\n\n\t* g-builtins.cc (builtin_eig): Correct usage message.\n\n\t* tree-const.cc (tree_constant_rep (ComplexDiagMatrix&)): Create\n\tand initialize a new complex_scalar.  Don't just try to copy the\n\tvalue...\n\n\t* Matrix.h: Declare new fill functions for diagonal matrices.\n\t* DiagMatrix.cc: Define them.\n\n\t* Matrix.h: Declare map functions for row and column vectors.\n\t* RowVector.cc: Define them.\n\t* ColumnVector.cc: Likewise.\n\n\t* CollocWt.h: Declare data protected instead of private.\n\t* CollocWt.cc (CollocWt::CollocWt (const CollocWt&)): Fix brain-o.\n\n\t* lex.l: Return IMAG_NUM for a numeric constant followed by\n\t[ \\t]*[iIjJ].\n\n\t* parse.y (IMAG_NUM): New token.\n\t* (fact): Recogize IMAG_NUM and convert its value to a complex\n\tconstant.\n\n\t* Version 0.62 released.\n\n\t* Makefile.in (local-dist): Include -local in tar.Z filename.\n\t* (split-local-dist): New target.\n\t* (dist): Don't depend on newversion.\n\t* (local-dist): Ditto.\n\n\t* tree-extras.cc (npsol): If the first argument isn't a vector,\n\tprint an error message and return.\n\n\t* tree.cc (tree_matrix::eval): Always set prev_row_total and\n\tprev_column_total when starting out.\n\n\t* octave.cc (main): Don't try to detect signal handler failures,\n\tbut do call signal() to set up the interrupt handler.\n\nTue Jan 12 19:59:33 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (npsol): Fix brain-o in checking length of bounds\n\tvectors.\n\nMon Jan 11 20:32:24 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (set_rand_seed): New function.\n\t(force_to_fit_range): New function.\n\t(current_seed): Really return current seed.\n\t(rand_internal): Allow the user to actually set the seed for the\n\trandom number generator.\n\nSun Jan 10 16:46:06 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.61 released.\n\n\t* builtins.h, builtins.cc: Rename from builtin-fcns.h,\n\tbuiltin-fcns.cc (too long for Linux/SysV).\n\n\t* mappers.cc (xisinf): For non-IEEE machines, consider DBL_MAX to\n\tbe infinite.\n\nFri Jan  8 09:15:57 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* gnuplot-build/Makefile.in (x11targets): Don't worry about\n\tchecking HAVE_X11_X_H.\n\n\t* configure.in: Check for gamma and lgamma for gnuplot.\n\n\t* gnuplot-build/Makefile.in (Makefile.X11): Only move Makefile to\n\t../Makefile.X11 if xmkmf succeeds.\n\n\t* gnuplot-build/Makefile.in (x11targets): Check to see that XMKMF\n\tis set *and* that Makefile.X11 exists.\n\t* If making notgnuplot_x11 with Makefile.X11 fails, try again with\n\tMakefile.\n\n\t* gnuplot-build/Makefile.in: Use @PLOTLIB@ in definintion of LIBS.\n\t* Don't define UNIXPLOT in TERMFLAGS.\n\t* Don't define LN_S; it isn't used anywhere, and configure doesn't\n\tgive it a value.\n\n\t* configure.in: Check for closepl().  If found, define UNIXPLOT,\n\tand substitute -lplot for @PLOTLIB@.\n\n\t* arith-ops.cc (DIVIDE_BY_ZERO_ERROR): New macro.  On systems that\n\thave IEEE math, give a warning but also go ahead and divide by\n\tzero.  On systems that don't have IEEE math, just give an error\n\tmessage and return an undefined tree_constant (it would probably\n\tbe possible to handle this so that it works the same everywhere,\n\tbut I'm not sure it's worth the effort...).\n\n\t* builtin-fcns.cc (install_builtins): On systems that don't have\n\tIEEE_MATH, define Inf to be MAX_DBL, but don't define NaN at all.\n\n\t* configure.in: Check for finite, isnan, and isinf.\n\t* Set HAVE_IEEE_MATH if we find finite and isnan.\n\n\t* builtin-fcns.cc (install_builtins): Use HAVE_IEEE_MATH instead\n\tof IEEE_MATH.\n\t* mappers.cc: Check HAVE_IEEE_MATH and HAVE_ISINF macros rather\n\tthan checking system type.\n\n\t* graph3d.c (hidden_line_plot): Declare dy and y as double, not\n\tfloat, since VERYLARGE can be DBL_MAX.\n\n\t* lsoda.f, lsodar.f, lsodes.f, lsodi.f, lsoibt.f, stoda.f,\n\tstodi.f, zrotg.f, sdot.f: Remove unused files.\n\n\t* texas_lotto.m: Renamed from win_texas_lotto.m to keep the\n\tfilename less than 14 characters.\n\nThu Jan  7 15:45:29 1993  John W. Eaton  (jwe@june.che.utexas.edu)\n\n\t* utils.cc: Declare ioctl extern \"C\".\n\n\t* tree.cc: Include stdio.h to be sure FILE is defined (apparently\n\tnot required by older versions of GNU iostream library).\n\t* t-builtins.cc: Likewise.\n\t* g-builtins.cc: Likewise, but for tmpnam.\n\n\t* tree-const.h (rand_internal): Rename from rand to avoid\n\tconflict with standard library rand (a macro in Linux).\n\t* tree-extras.cc (rand_internal): Fix function definition.\n\t* g-builtins.cc (builtin_rand): Call rand_internal instead of rand.\n\n\t* octave.cc (main): Don't try to detect signal handler failures.\n\tWhat's the proper way to do this if RETSIGTYPE is void?\n\nTue Jan  5 08:14:29 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_matrix::eval): When adding a matrix down or to the\n\tright, column or row dimension mismatches are always errors.\n\nMon Jan  4 04:58:55 1993  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.60 released.\n\n\t* xdiv.h, xdiv.cc: New files for Octave-specific matrix division\n\tstuff.\n\t* src/Makefile.in (INCLUDES, SOURCES, OBJECTS): Add xdiv stuff.\n\n\t* arith-ops.cc: Include xdiv.h.\n\nSun Jan  3 12:24:04 1993  John W. Eaton  (jwe@ward.che.utexas.edu)\n\n\t* gnuplot-build/Imakefile.in (notgnuplot_x11): In the compile\n\tcommand, put source file before\tlibraries.\n\n\t* libcruft/misc/Makefile.in: Don't use -O to compile gen-dimach.c.\n\nThu Dec 31 00:45:50 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (matrix_sqrt): Don't create D until it is really\n\tneeded.\n\t* (matrix_log): Ditto.\n\t* (matrix_exp): Ditto.\n\t[this should really be just one function instead of three...]\n\n\t* g-builtins.cc (builtin_sqrtm): New function.\n\t* builtin-fcns.cc (general_fucntions): Add it to the list.\n\t* tree-extras.cc (matrix_sqrt): Do the real work.\n\n\t* Makefile.in: Distribute INSTALL.OCTAVE and configure.in.\n\t* (INSTALL.info): Make ../INSTALL.OCTAVE, not ../INSTALL.\n\n\t* doc/Makefile.in: Make ../INSTALL.OCTAVE, not ../INSTALL.\n\n\t* INSTALL.OCTAVE: Rename from INSTALL.\n\tRefer to INSTALL for more info.\n\n\t* INSTALL: Copy from autoconf distribution.\n\tRefer to INSTALL.OCTAVE for more info.\n\n\t* octave.cc (main): Remove leading blank line from startup message.\n\t* Don't print it everytime the user types C-c...\n\n\t* xpow.cc: Finish off remaining cases.\n\n\t* tree-extras.cc (process_format): New function.\n\t(do_printf): Use it.\n\nWed Dec 30 00:43:14 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.56.\n\n\t* g-builtins.cc (builtin_logm): New function.\n\t* builtin-fcns.cc (general_fucntions): Add it to the list.\n\t* tree-extras.cc (matrix_log): Do the real work.\n\n\t* g-builtins.cc (builtin_expm): New function.\n\t* builtin-fcns.cc (general_fucntions): Add it to the list.\n\t* tree-extras.cc (matrix_exp): Do the real work.\n\n\t* Matrix-ext.cc (LU): Construct LU decomp. here, not in Matrix class.\n\t(ComplexLU): Likewise.\n\t* Matrix.cc (lu): Deleted.  Use LU constructor instead.\n\tChange all uses in octave sources.\n\n\t* Matrix-ext.cc (EIG): Construct EIG object here, not in Matrix class.\n\t* Matrix.cc (eig): Deleted.  Use EIG constructor instead.\n\tChange all uses in octave sources.\n\n\t* Matrix-ext.cc (SVD): Construct SVD here, not in Matrix class.\n\t(ComplexSVD): Likewise.\n\t* Matrix.cc (svd): Deleted.  Use SVD constructor instead.\n\tChange all uses in octave sources.\n\n\t* Makefile.in: Update for new Matrix file organization.\n\tDon't compile mx-inlines separately -- it's included where needed.\n\t* Matrix.h: Declare Fortran routines we call here, not in Matrix.cc.\n\tDon't declare every class to be a friend of every other class.\n\t* mx-inlines.cc: New file, included by all Matrix-related .cc files.\n\t* Matrix.cc: Split into several files.\n\t* ColVector.cc: New file, from Matrix.cc\n\t* RowVector.cc: Ditto.\n\t* DiagMatrix.cc: Ditto.\n\t* Matrix-ext.cc: Ditto.\n\n\t* tree-extras.cc (svd): Take advantage of new constructors and\n\tdiag functions.\n\n\t* Matrix.cc (DiagMatrix::diag) New function.\n\t(ComplexDiagMatrix::diag) Ditto.\n\n\t* tree-extras.cc (eig): Take advantage of new constructors.\n\n\t* tree-const.cc (tree_constant (DiagMatrix)): New constructor.\n\t(tree_constant (ComplexDiagMatrix)): Ditto.\n\n\t* Matrix.cc (Matrix (const DiagMatrix)): New constructor.\n\t(ComplexMatrix (const DiagMatrix)): Ditto.\n\t(ComplexMatrix (const ComplexDiagMatrix)): Ditto.\n\nTue Dec 29 01:14:49 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (main): Print message at startup by default.\n\tDon't print it until just before main loop.\n\t* New -q option (inhibit_startup_message) turns it off.\n\t* New -f option (read_init_files) inhibits reading of startup files.\n\t* Delete -v option.\n\t* (verbose_usage): Reflect changes in arguments, document -d.\n\n\t* win_texas_lotto.m: Sort picks before returning.\n\n\t* tree-extras.cc (eig): Return [v,d], not [l,v], where d is a\n\tdiagonal matrix made from l.\n\n\t* builtin-fcns.cc (mapper_functions): Fix last element of\n\tinitialization list to have correct number of elements.\n\n\t* Version 0.55.\n\n\t* Quad.h: Move all inline functions to Quad.cc to avoid apparent\n\tg++ bug on the RS/6000.\n\n\t* configure.in: If we find flex, don't define LEXLIB.\n\n\t* COPYING.LIB: Deleted -- we're not actually distributing anything\n\tunder these terms.\n\t* Makefile.in: Don't distribute COPYING.LIB.\n\nMon Dec 28 00:46:21 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* xpow.h, xpow.cc: New files for safer pow() interface for octave.\n\t* src/Makefile.in (INCLUDES, SOURCES, OBJECTS): Add xpow stuff.\n\n\t* arith-ops.cc: Include xpow.h.\n\t* Don't declare toplevel jmp_buf.\n\n\t* t-builtins.cc (builtin_save): Make file and stream static to\n\tavoid dumping core on return (is this a bug in libg++ or g++?).\n\t* (builtin_load): Ditto.\n\n\t* symtab.cc (load): Make it work again.  Yikes!  This hasn't\n\tworked since the big symbol table overhaul...\n\n\t* tree-const.cc (tree_constant_rep::save): Handle complex scalars\n\tand matrices.\n\n\t* (symbol_def::undefine): Delete previous symbol definition before\n\tdefining.  This should be ok now, after the parse_m_file fix of\n\t27 Dec.\n\n\t* getting_help: New global flag.\n\t* ([_a-zA-Z][_a-zA-Z0-9]*): Set it if looking at \"help\".\n\t* (reset_parser): Clear it.\n\t* lex.l (STRING): Use it to determine what to do with ' ; and , .\n\n\t* lex.l (QSTRING): Handle the following (C-style) backslash escape\n\tsequences correctly(?).\n\n\t  \\a  bell\t   \\r  carriage return\n\t  \\b  backspace    \\t  horizontal tab\n\t  \\f  formfeed     \\v  vertical tab\n\t  \\n  newline\t   \\\\  backslash\n\n\t* median.m: New M-file.\n\n\t* g-builtins.cc (builtin_sort): New function.\n\t* builtin-fcns.cc (general_fucntions): Add it to the list.\n\t* tree-extras.cc (sort): Do most of the real work.\n\t* tree-extras.cc (mx_sort): Do the rest.\n\nSun Dec 27 17:40:24 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* t-builtins.cc (builtin_casesen): New function.\n\t* builtin-fcns.cc (text_functions): Add it to the list.\n\n\t* strcmp.m: Temporarily allow string to numeric conversions.\n\tMaybe strcmp() should be built in to the interpreter?\n\n\t* norm.m: New M-file.\n\n\t* builtin-fcns.cc (install_builtins): Treat i and j as functions,\n\tnot variables.\n\t* Install inf as an alias for Inf.\n\t* Install nan as an alias for NaN.\n\n\t* tree.cc (tree_identifier::parse_m_file (char*)): Force new\n\tglobal symbol to be a function, not a variable.\n\nTue Dec 22 14:15:57 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_function::eval): Check with silent_functions()\n\tand return_last_value_computed() to determine proper behavoir.\n\n\t* builtin-fcns.cc (silent_functions): New builtin variable.\n\t* (return_last_value_computed) Ditto.\n\n\t* utils.cc (silent_functions): New function.\n\t* (return_last_value_computed) Ditto.\n\t[This scheme for determining preferences needs to be reworked...]\n\n\t* lex.l ([_a-zA-Z][_a-zA-Z0-9]*): Only force yytext[len] to be the\n\tend of the identifier if we gobbled some whitespace.\n\t* Always unput the last character read.\n\n\t* tree.cc (tree_function::eval) Always turn on printing for\n\tcommands inside functions.\n\nSat Dec 19 14:03:49 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.54.\n\nFri Dec 18 16:02:59 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* (symbol_def::undefine): Undo previous change.  Someone is\n\tcalling this function when they shouldn't be...\n\n\t* tree.cc (parse_m_file): If the script file is successfully\n\tparsed, Ensure that the new symbol is defined in the global\n\tsymbol table.\n\n\t* lex.l: Handle continuation lines with the pattern\n\t{EL}{S}*\\n { promptflag = 0; }  // Line continuation.\n\nThu Dec 17 01:47:14 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* symtab.cc (symbol_def::define): Delete previous symbol\n\tdefinition before defining.\n\t(symbol_def::undefine): Ditto, but new definition is always NULL.\n\n\t* readline/Makefile.in:  Don't compile emacs_keymap.c and\n\tvi_keymap.c since they are included by keymaps.c.\n\n\t* configure.in: If RETSIGTYPE isn't int, then define\n\tVOID_SIGHANDLER=\"-DVOID_SIGHANDLER=1\".\n\tSubstitute VOID_SIGHANDLER.\n\n\t* readline/Makefile.in (CFLAGS): Add -DVOID_SIGHANDLER if\n\tappropriate.\n\n\t* tilde.c: Declare xmalloc, not malloc.\n\n\t* lex.l ([_a-zA-Z][_a-zA-Z0-9]*): Only call unput if we've\n\tactually read something.\n\n\t* Version 0.53.\n\nWed Dec 16 01:35:48 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l ([_a-zA-Z][_a-zA-Z0-9]*): Look in the global symbol table\n\tfor names, but ignore functions.\n\n\t* tree.cc (tree_identifier::eval): Use symbol_out_of_date() to\n\tsimplify logic for re-parsing M-files.\n\tAlways look in global symbol table for functions in case the\n\tdefinition has changed (shouldn't the local symbols be undefined\n\tanyway??).\n\n\t* tree.cc (symbol_out_of_date): New function.\n\n\t* symtab.cc (symbol_table::undefine): Actually do something.\n\t* (symbol_table::remove_name): Ditto.\n\t* (symbol_table::clear): And so on.\n\n\t* Matrix.cc (ComplexMatrix::svd): Use complex conjugate transpose,\n\tnot simple transpose, for V.\n\n\t* Version  0.52.\n\n\t* gnuplot-build/Imakefile (notgnuplot_x11): In the compile\n\tcommand, put source file before\tlibraries.\n\n\t* parse.y (assignment): If trying to warn against assignment to a\n\tfunction, check is_function() instead of !is_variable().\n\n\t* src/Makefile.in: Distribute input.h.\n\nTue Dec 15 10:48:22 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (main): Call initialize_readline to set up completion\n\tfunctions.\n\n\t* input.cc (make_name_list, command_generator, command_completer,\n\tinitialize_readline): New functions.\n\n\t* input.h: New file.\n\t* lex.l: Include it instead of input.cc.\n\t* src/Makefile.in: Create input.o rather than including it\n\tdirectly in lex.l.\n\n\t* builtin-fcns.cc: do_fortran_indexing is now initially false.\n\tprefer_column_vectors is now initially true.\n\n\t* builtin-fcns.cc (install_builtins): Install i and j\n\t (== sqrt(-1)) as permanent global variables.\n\n\t* g-builtins.cc (MAXPATHLEN) Provide default definition here.\n\t* t-builtins.cc: Not here.\n\n\t* g-builtins.cc (quitting_gracefully, interactive,\n\tclean_up_and_exit, verbatim_pwd, getwd) Declare here.\n\t* t-builtins.cc: Not here.\n\n\t* g-builtins.cc: Also include readline.h and history.h.\n\n\t* g-builtins.cc: Include version.h and sys/param.h here.\n\t* t-builtins.cc: Not here.\n\n\t* g-builtins.cc: Move builtin_clc, builtin_clock, builtin_date,\n\tbuiltin_pause, builtin_quit, builtin_warranty here from\n\tt-builtins.cc.\n\n\t* builtin-fcns.cc (general_functions): Move builtin_clc,\n\tbuiltin_clock, builtin_date, builtin_pause, builtin_quit,\n\tbuiltin_warranty here from text_functions to limit the number of\n\treserved words.\n\n\t* scripts/*.m: Check for correct number of input arguments before\n\tproceeding.\n\n\t* configure.in (DEFAULT_PAGER): Look for less, more, page, and pg.\n\n\t* t-buitlins.cc (builtin_help): If no arguments are given, list\n\tall the known operators, keywords, functions, and variables.\n\n\t* t-builtins.cc (builtin_help) Pass the output through PAGER using\n\ta libg++ procbuf.\n\t(builtin_who): Ditto.\n\n\t* utils.cc (get_pager): New function.\n\n\t* help.h, help.cc: New files to manage lists of help info for\n\tkeywords and operators.\n\n\t* symtab.cc (symbol_record): Implement the Matlab-style semantics\n\tof functions using two symbol_def objects.\n\t* (symbol_table): Store identifier names in a hash table instead\n\tof a linear list.\n\t* symtab.cc (symbol_def): New class.\n\nSat Dec 12 00:00:00 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* parse.y (yyerror): Change error text to be more accurate.\n\n\t* lex.l ([_a-zA-Z][_a-zA-Z0-9]*): Only look in the current symbol\n\ttable for names.  Function names and other global symbols are now\n\tresolved at execution time.\n\n\t* symtab.cc (sorted_var_list): New function.\n\t* (sorted_fcn_list): Ditto.\n\t* (var_list): Ditto.\n\t* (fcn_list): Ditto.\n\tThese should probably not all be separate functions...\n\n\t* t-functions.cc (builtin_who): Call sorted_var_list for each\n\tsymbol table to print variable names only.\n\t* Accept -fcn, -fcns, or -functions to also list function names.\n\t* Make -all list function names, but under a separate heading from\n\tother symbols.\n\n\t* builtin-fcns.cc (is_text_function_name): New function.\n\t* lex.l ([_a-zA-Z][_a-zA-Z0-9]*): Use is_text_function_name to\n\tfind if a name is a text function name instead of relying on the\n\tsymbol tables.\n\n\t* lex.l (is_keyword): New function.\n\t([_a-zA-Z][_a-zA-Z0-9]*): Use is_keyword instead of having a\n\tspecial lex pattern for each keyword.\n\nThu Dec 10 12:25:12 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* t-builtins.cc: Declare top_level_sym_tab extern.\n\n\t* Version 0.51.\n\nWed Dec  9 02:00:38 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (all user_functions): If the return value from a\n\tuser's function is bogus, print an error message and abort to the\n\ttop level.\n\n\t* tree-const.cc (all do_matrix_index functions): Major overhaul to\n\tsimplify and apply range checking before doing the indexing.\n\n\t* tree-const.cc (fortran_row, fortran_column, valid_scalar_indices,\n\tmatrix_to_fortran_indices): Move here from arith-ops.cc and\n\tdeclare as `static inline'.  Delete declarations from arith-ops.h.\n\n\t* arith-ops.cc (gripe_nonconformant_assignment): Delete function.\n\n\t* tree-const.h (TREE_TO_MAT_IDX): Delete macro.\n\t* tree-const.cc (tree_to_mat_idx): Make it an inline function.\n\n\t* tree-const.cc (all do_matrix_assignment functions): Major\n\toverhaul to simplify resizing and range checking.\n\n\t* tree-const.cc (): Move here from arith-ops.cc.\n\tJump to top level on errors.\n\tReturn max value.\n\t(indexed_assign_conforms) New function.\n\t(index_check (int)): New function.\n\t(index_check (Range)): New function.\n\nTue Dec  8 21:07:23 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-const.cc (tree_constant_rep::tree_constant_rep (Range):\n\tDon't create range constants that have less than 2 elements.\n\n\t* utils.cc (jump_to_top_level): New function.\n\t* All: Replace calls to longjmp with calls to jump_to_top_level().\n\tDon't include <setjmp.h>, except in octave.cc, and utils.cc.\n\nMon Dec  7 01:57:30 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in: Create Imakefile in gnuplot-build directory.\n\tLook for xmkmf, then X11/X.h.\n\t* gnuplot-build/Makefile.in: Try harder to get notgnuplot_x11 to\n\tbuild correctly.\n\t* gnuplot-build/Imakefile.in: New file, for building\n\tnotgnuplot_x11 if xmkmf is available.\n\n\t* Version 0.50.\n\n\t* gnuplot-build/Makefile.in (SUBDIRS): Add docs.\n\n\t* tree-const.h (make_numeric_or_range_or_magic): New function.\n\t* tree-const.cc (do_matrix_index): Use it instead of make_numeric\n\tso that we actually take advantage of all the special cases we\n\thave for range types as matrix indices.\n\n\t* tree-const.cc (tree_constant_rep::do_matrix_index (int, Matrix)):\n\tFix typo.\n\n\t* DAE.cc (integrate): If returning a matrix of values, don't mix\n\ttime with the states.\n\t* ODE.cc (integrate): Likewise.\n\nSun Dec  6 16:58:41 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (dassl): New function.\n\t* g-builtins.cc (builtin_dassl): Make it work.\n\t* doc/octave.1: Document it.\n\n\t* DAEFunc.h, DAEFunc.cc, DAE.h, DAE.cc: New files.\n\n\t* tree-extras.cc (lsode): Clean up.  Use available functions\n\tinstead of doing everything in line.\n\n\t* tree.cc (tree_multi_assignment_expression::eval): Don't define\n\tconstants that are of unknown type.\n\tTry to be smarter about padding after last value.\n\n\t* tree-extras.cc (lu): Don't bother trying to return the LU\n\tfactorization in a single matrix since this isn't really useful\n\tand isn't compatible with Matlab anyway (they use Linpack, we use\n\tLapack).\n\n\t* tree.cc (tree_identifier::assign (rhs, args, nargs)): Only try\n\tto do assignment if rhs is defined.\n\nSat Dec  5 18:23:55 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (qr): New function.\n\t* g-builtins.cc (builtin_qr): New function.\n\t* builtins.cc: Add builtin_qr to list of builtin functions.\n\t* doc/octave.1: Document it.\n\n\t* Matrix.cc (Matrix::lu): Use dgesv from Lapack instead of dgefa\n\tsince it returns L and U, not some factors that need decoding.\n\t(ComplexMatrix:lu): Likewise.\n\nFri Dec  4 01:51:05 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* configure.in (INCDIRS): Don't include /usr/local/include.\n\t(LIBDIRS): Don't include /usr/local/lib.\n\n\t* tree-extras.cc (lu): New function.\n\t* g-builtins.cc (builtin_lu): New function.\n\t* builtins.cc: Add builtin_lu to list of builtin functions.\n\t* doc/octave.1: Document it.\n\n\t* Matrix.cc (Matrix:lu, ComplexMatrix:lu): New functions.\n\t* Matrix.h, Matrix.cc (LU, ComplexLU): New classes.\n\n\t* tree-extras.cc (do_quad): New function.\n\t* g-builtins.cc (builtin_quad): New function.\n\t* builtins.cc: Add builtin_quad to list of builtin functions.\n\t* doc/octave.1: Document it.\n\n\t* doc/Makefile.in (install): Edit the manpage to substitute\n\tcorrect values in the FILES section.\n\t(dist) Depend on octave.info.\n\t(local-dist): Ditto.\n\n\t* Quad.h, Quad.cc: New files to implement quadrature.\n\n\t* NPSOL.cc (npsol_objfun): If compiling with GCC on a Sun, assign\n\tto objf via assign_double().\n\n\t* sun-utils.h, sun-utils.cc: New files.\n\t* sun-utils.cc: Move declaration and definition of MAIN_ here from\n\tutils.cc.\n\t(access_double): New function, from GCC manual.\n\t(assign_double): New function, after access_double.\n\nThu Dec  3 03:16:03 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* NEWS: New file.\n\t* Makefile.in: Distribute it.\n\n\t* scripts/*.m: Change to use new end feature.\n\n\t* lex.l: Recognize `endif', `endfor', `endfunction', `endif', and\n\t`endwhile', in addtion to `end'.\n\t* parse.y: Check for command/end mismatches.\n\t(end_error): New function.\n\t* doc/octave.1: Document it.\n\nWed Dec  2 11:57:18 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* libcruft/villad: New directory.  Move and split villad.f here\n\tfrom libcruft/misc.\n\t* configure.in: Create Makefile in libcruft/villad.\n\t* libcruft/Makefile.in: Add libcruft/villad to list of dirs to make.\n\n\t* All Makefile.in (uninstall): New target.\n\t(distclean): Likewise.\n\t(check): Ditto.\n\t* Try to make clean targets conform with GNU coding standards.\n\n\t* utils.cc (smells_like_X11): New function.\n\t* builtin-fcns.cc (install_builtins): Don't set graphics terminal\n\tto x11 unless it looks like we're running X11.\n\n\t* win_texas_lotto.m: New M-file.\n\t* octave.1: Document it.\n\n\t* arith-ops.h: New file.\n\t* src/Makefile.in: Build arith-ops.o, distribute arith-ops.cc,\n\tarith-ops.h.  Maybe this will at least speed up recompiles.\n\n\t* THANKS: New file\n\t* Makefile.in: Distribute it.\n\n\t* configure.in: Create Makefile in gnuplot-build/docs.\n\t* gnuplot-build/docs/Makefile.in: New file.\n\t* Create and install notgnuplot.gih.\n\nTue Dec  1 00:15:48 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_identifier::eval (int)): Only pad after if printing.\n\t(tree_multi_assignment_expression::eval (int)): Ditto.\n\t(tree_assignment_expression::eval (int)): Ditto.\n\n\t* hankel.m: Use disp to print message.\n\t* toeplitz.m: Ditto.\n\n\t* lex.l (<MATRIX>{SN}*\\]/{S}*=): Check maybe_screwed_again to\n\tdecide whether to return SCREW_TWO or ']'.\n\n\t* doc/Makefile.in (install): Really install the manpage.\n\n\t* Version 0.49.\n\n\t* Matrix.cc (ComplexMatrix::operator !): New function.\n\t* arith-ops.cc (do_unar_op): Use it.\n\n\t* tree-extras.cc (inverse, svd, eig): Don't try to operate on\n\tempty matrices.\n\n\t* Matrix.h, Matrix.cc: (EIG): New class.\n\t(Matrix::eig): New functions.\n\t(ComplexMatrix::eig): Ditto.\n\t* tree-extras (eig): Use them.\n\t* g-builtins.cc (builtin_eig): New function.\n\t* builtin-fcns.cc (general_functions): Add eig to list.\n\t* dococtave.1: Document it.\n\n\t* Matrix.h, Matrix.cc: (ComplexDET): New class.\n\t* tree-extras (determinant): Use it.\n\nMon Nov 30 04:02:29 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Matrix.h, Matrix.cc (ComplexSVD): New class.\n\t* tree-extras (svd): Use it.\n\n\t* Matrix.cc (svd): Use lapack instead of linpack to compute SVD.\n\n\t* libcruft/Makefile.in: Replace eispack with lapack in\n\tsubdirectory list.\n\t* libcruft/eispack: Delete directory.\n\t* libcruft/lapack/Makefile.in: New file.\n\t* configure.in: Create Makefile in libcruft/lapack, not\n\tlibcruft/eispack.\n\n\t* libcruft/lapack: New directory.\n\t* Copy files for SVD and Eigenvalue computation here.\n\n\t* lex.l (<MATRIX>{SN}*\\]/{S}*=): Only return SCREW_TWO if not\n\tdefining a function.\n\n\t* arith-ops.cc (do_binary_op (double, double)): For pow operator,\n\tdon't create complex value if exponent is really an int.\n\n\t* configure.in: Check for f77 last.\n\t* Print warnings if bison or lex is not found.\n\t* Reformat fatal no f2c/f77 error message.\n\n\t* flib.sh: Make it work even if xlf is called f77.\n\nSun Nov 29 01:55:41 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc: Include f77-uscore.h.\n\t* Use F77_FCN macro when declaring or calling Fortran functions.\n\n\t* configure.in: After checking to see that it's not garbage, add\n\tthe output of f2c-compat.sh to DEFS.\n\n\t* f2c-compat.sh: Figure out whether or not we need to append an\n\tunderscore to Fortran function names.\n\n\t* flibs.sh: Handle xlf -v output as special case.\n\n\t* octave.cc: Only define BADSIG if it isn't already defined.\n\t* g-builtins.cc: Ditto.\n\n\t* configure.in: Don't create man/Makefile.\n\t* man: Directory deleted.\n\t* doc/Makefile.in: Distribute and install octave.1.\n\t* doc/octave.1: Renamed from man/octave.1.\n\nSat Nov 28 15:54:39 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* man/Makefile.in (install): Install manpage.\n\t* octave.1: rename from octave.man\n\t* octave.1: Document builtin variables and command line editing\n\t(stolen from bash man page).\n\n\t* tree-const.cc (eval (int print)): Convert complex values to real\n\tif imaginary part is zero.\n\n\t* octave.cc (log_usage): Deleted.\n\t(main): Don't call log_usage.\n\n\t* g-builtins.cc (builtin_sqrt): Delete.\n\t(builtin_log): Ditto.\n\t(builtin_log10): Ditto.\n\n\t* tree-const.h, tree-const.cc (sqrt_internal): Delete.\n\t(log_internal): Ditto.\n\t(log10_internal): Ditto.\n\n\t* tree-const.cc (mapper): Handle neg_arg_complex.\n\n\t* builtin-fcns.h (Mapper_fcn): New field neg_arg_complex.\n\t* builtin-fcns.cc: (mapper_functions[]): Initialize it for list of\n\tmapper functions.\n\t* builtin-fcns.cc: (mapper_functions[]): Move log, log10, and sqrt\n\tback here from general_functions[].\n\nFri Nov 27 17:05:21 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (tree_constant_to_vector): Handle complex scalars\n\tand matrices.\n\nWed Nov 25 17:32:42 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* man/octave.man: New file, very incomplete.\n\t* man/Makefile.in: Include octave.man in list of files to\n\tdistribute.\n\n\t* g-buitlins.cc (builtin_rand): Handle nargin == 1.\n\t* tree-extras.cc (rand): Likewise.\n\n\t* rem.m: New M-file.  Implemented as M-file because it's much\n\tsimpler!\n\n\t* configure.in (DEFAULT_DOT_C_FROM_DOT_F): Escape % characters in\n\trule to avoid problems with autoconf, which uses % for sed command\n\tdelimeters.\n\t(DEFAULT_DOT_O_FROM_DOT_F): Ditto.\n\nTue Nov 24 00:21:34 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (fill_matrix): Don't try to create matrices with\n\tnegative dimensions.\n\t(frobit): Likewise.\n\n\t* utils.cc (check_dimensions): New function.\n\n\t* utils.cc (treat_neg_dim_as_zero): New function.\n\t* builtin-fcns.cc (treat_neg_dim_as_zero): New builtin variable,\n\tdefault value is false.\n\n\t* tree-const.h (tree_constant::bump_value): Like, assign, check\n\treference count and possibly make a new copy before changing\n\tanything.\n\n\t* tree-base.h (is_builtin): New virtual function.\n\t* tree.cc (tree_builtin::is_builtin): New function.\n\n\t* parse.y (ans_expression): Also check to see if the lone\n\texpression is a builtin text-style function invoked without any\n\targuments.\n\n\t* octave.cc, t-builtins.cc: Print copyright and other normal\n\t(non-error) message on cout instead of cerr.\n\n\t* t-builtins.cc (builtin_warranty): Don't return message in\n\tretval.\n\t(builtin_history): Likewise.\n\t(builtin_help): Also.\n\t(builtin_who): Ditto.\n\n\t* Version 0.48.\n\n\t* tree-extras.cc: Fix most functions to handle complex arguments.\n\tStill need to finish SVD and DET (waiting for these functions in\n\tthe Matrix class).\n\n\t* tree.cc (tree_multi_assignment::eval): Optionally print names\n\tfor result variables.\n\n\t* tree-const.h (tree_constant::eval (int print, int nargout)):\n\tNew function.  Simply ignore nargout.\n\t* tree.cc (tree_matrix::eval (int print, int nargout)): Ditto.\n\n\t* tree.cc (tree_parameter_list::name): New function.\u0010\n\n\t* lex.l (<NEWMAT>): Delete rules, start condition because they are\n\tunecessary.\n\n\t* lex.l (<MATRIX>{SN}*\\]): Split into three rules.  Use trailing\n\tcontext instead of home-brew lookahead.\n\nMon Nov 23 00:51:51 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* utils.cc (ok_to_lose_imaginary_part): New function.\n\t* builtin-fcns.cc (ok_to_lose_imaginary_part): New builtin\n\tvariable, default value is warn.\n\n\t* tree-const.h (double_value): Maybe return real part if invoked\n\tfor complex tree_constant.\n\t* tree-const.h (matrix_value): Ditto.\n\n\t* Version 0.47.  This one wasn't tested, but there have been a lot\n\tof significant changes and I wanted a backup.\n\n\t* tree-const.cc (sqrt_internal): New function.  Sqrt isn't\n\timplemented as a mapper function since negative real arguments\n\tgive complex results.\n\t(log_internal): Ditto.\n\t(log10_internal): Ditto.\n\t* builtin-fcns.cc: Move sqrt, log, and log10 from mapper struct\n\tinitializer to general function struct initializer.\n\n\t* rot90.m: New M-file.  Still needs rem() to be complete.\n\n\t* tree-const.cc (mapper): Handle mapper functions for complex\n\tvariables.\n\n\t* mappers.h, mappers.cc: New file for mapper functions.\n\n\t* builtin-fcns.h, builtin-fcns.cc: Rename from builtins.h\n\tbuiltins.cc.\n\n\t* flipud.m: Don't do indexing on lhs.\n\t* fliplr.m: Likewise.\n\nSun Nov 22 17:09:36 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* arith-ops.cc (do_binary_op (double, double)): Handle a^b for\n\ta < 0.\n\n\t* builtins.cc: Make sqrt a general builtin function instead of a\n\tmapper function.\n\t* g-builtins.cc (builtin_sqrt): New function.\n\t* tree-const.cc (sqrt_internal): New function.\n\nSat Nov 21 16:41:02 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-const.h, tree-const.cc:  Complete most changes required to\n\thandle complex types.  There are lots of details, most will be\n\tomitted here.\n\n\t* tree-const.h (is_real_type) New function.\n\t(is_complex_type): Ditto.\n\t(is_scalar_type): Ditto.\n\t(is_matrix_type): Ditto.\n\n\t* tree-const.h (REP_RHS_MATRIX, REP_ELEM_ASSIGN, CRMATRIX,\n\tASSIGN_CRMATRIX_TO, CRMATRIX_ASSIGN_REP_ELEM,\n\tCRMATRIX_ASSIGN_ELEM): New macro for dealing with real and complex\n\tmatrices in the same tree_constant_rep function.\n\n\t* tree-const.cc: Include arith-ops.cc.\n\n\t* arith-op.cc: New file for functions that implement unary and\n\tbinary operations for the tree_constat classes.\n\t* Mark all operations that aren't implemented yet with a\n\tFIXME comment.  There are about 35-40 things left to fix\n\tin this file.\n\nThu Nov 19 00:25:16 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.46.\n\t[ This one wasn't tested, but there have been a lot of significant\n\tchanges and I wanted a backup. ]\n\n\t* tree-const.cc (tree_constant_rep::do_unary_op): Handle Complex.\n\t(do_unary_op (Complex&, tree::expression_type)): New function.\n\t(do_unary_op (ComplexMatrix&, tree_expression_type): Ditto.\n\n\t* tree-const.cc (tree_constant_rep::assign): Handle Complex\n\t(still needs updated support functions in order to work).\n\n\t* tree.cc (tree_matrix::eval): Handle Complex.\n\t(tree_identifier::eval): Ditto.\n\t(tree_for_command::eval): Ditto.\n\nWed Nov 18 23:33:13 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree_const.cc (tree_constant_rep::rows): Handle Complex.\n\t(tree_constant_rep::columns): Ditto.\n\t(tree_constant_rep::all): Ditto.\n\t(tree_constant_rep::any): Ditto.\n\t(tree_constant_rep::cumprod): Ditto.\n\t(tree_constant_rep::cumsum): Ditto.\n\t(tree_constant_rep::prod): Ditto.\n\t(tree_constant_rep::sum): Ditto.\n\t(tree_constant_rep::sumsq): Ditto.\n\n\t* tree_const.h, tree_const.cc (tree_constant::complex_value): New\n\tfunction.\n\t(tree_constant_rep::complex_value): Ditto\n\t(tree_constant::complex_matrix_value): New\n\t(tree_constant_rep::complex_matrix_value): New\n\n\t* tree_const.cc (tree_constant_rep::~tree_constant_rep): Handle\n\tcomplex scalars and matrices.\n\t(tree_constant_rep::force_numeric): Ditto.\n\t(tree_constant_rep::make_numeric): Ditto.\n\t(tree_constant_rep::eval): Ditto.\n\t(tree_constant_rep::bump_value): Ditto.  C++, for C == a\n\tcomplex value is C = C + 1.  Should I even do this?  Hmmm.\n\n\t* tree-const.h, tree-const.cc: Begin adding support for Compelex.\n\t* Add complex_scalar and complex_matrix to value union.\n\t* Add complex_scalar_constant and complex_matrix_constant to type\n\ttag enum.\n\t* New constructors.\n\n\t* Matrix.h, Matrix.cc: Major changes to add Complex support.\n\nTue Nov 17 14:40:45 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Matrix.cc (RowVector::operator (const Matrix&)): New function.\n\n\t* Matrix.cc (ColumnVector::transpose): New function.\n\tEliminate friend function that served the same purpose.\n\t(RowVector::transpose): Ditto.\n\nMon Nov 16 09:57:33 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (QSTRING): Fix to allow '' inside a string to represent a\n\tsingle quote.  Makes computer.m a little funnier.\n\nFri Nov 13 18:46:39 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.45.\n\n\t* computer.m: New M-file.\n\t* tril.m: Ditto.\n\t* triu.m: Ditto.\n\n\t* doc (*.texi): Can now produce BUGS, INSTALL, and octave.info\n\tfiles without generating errors, though the organization is\n\tprobably till very wrong.\n\n\t* Makefile.in (newversion): Add magic to handle major versions\n\tother than 0, and major/minor versions of any length.\n\nThu Nov 12 01:37:45 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.h, tree-const.h, builtins.cc, g-builtins.cc,\n\ttree-extras.cc: Conditionally compile code for NPSOL and FSQP\n\tbased on FSQP_MISSING and NPSOL_MISSING.\n\t* g-builtins.cc (builtin_npsol): If NPSOL is missing, always call\n\tnpsol_usage() to print out message indicating why NPSOL doesn't\n\twork.\n\t* g-builtins.cc (builtin_fsqp): Likewise for FSQP.\n\n\t* configure.in: Check for srcdir/libcruft/npsol/npsol.f and\n\tsrcdir/libcruft/fsqp/fsqp.f.  If missing, define NPSOL_MISSING or\n\tFSQP_MISSING and add them to DEFS.\n\n\t* libcruft/npsol/README.MISSING: New file.\n\t* libcruft/fsqp/README.MISSING: Ditto.\n\n\t* libcruft/npsol/Makefile.in (dist): Don't distribute sources\n\tbecause of license restriction.  Do distribute Makefile.in and\n\tREADME.MISSING.\n\t* libcruft/fsqp/Makefile.in (dist): Ditto.\n\n\t* All Makefile.in files (local-dist): New target, usually the same\n\tas dist.\n\n\t* parse.y (ans_expression): Check to see that the RHS isn't just\n\tan identifier.\n\t* tree.cc (tree_identifier::eval (int)): Maybe print id name.\n\t* tree.cc (tree_assignment::eval (int)): Ditto.\n\t* buitlins.cc (print_answer_id_name): New builtin variable.\n\t* utils.cc (print_answer_id_name): New function.\n\nTue Nov 10 10:58:36 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (log_usage): Surround with #if 0/#endif.\n\nMon Nov  9 13:42:54 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* symtab.cc (load): Only issue error mesasge if attempt to find\n\t_first_ name keyword fails.\n\n\t* tree-const.cc (make_numeric_or_magic): New function.  Like\n\tmake_numeric except also pass magic_colons.\n\t* tree-const.cc (all do_matrix_index functions): Matrix ndices can\n\tbe naked colons, so use make_numeric_or_magic on index arguments\n\tinstead of make_numeric.\n\n\t* liboctave/Makefie.in (install): Install .h files in $(includedir).\n\t(includedir): New macro, default value $(prefix)/include.\n\n\t* tree.cc (tree_function::eval (int print)): Force arguments to be\n\tundefined.\n\n\t* tree-const.h (tree_constant::assign (rhs, args, nargs)): Check\n\treference count before assigning.\n\t* tree.cc (tree_identifier::assign (rhs, args, nargs)): Don't eval\n\tlhs before doing assignment.\n\n\t* tree.cc (parse_m_file): Gobble leading white space, including\n\tcomments.\n\nFri Nov  6 16:52:59 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.44.\n\n\t* g-builtins.cc (builtin_getenv): New function.\n\n\t* isempty.m: New M-file.\n\n\t* g-builtins.cc (builtin_exist): New function.\n\t* utils.cc (identifier_exists): Handle the dirty details.\n\n\t* utils.cc (warn_comma_in_global_decl): New function.\n\t* builtins.cc (warn_comma_in_global_decl): New builtin variable.\n\tInitial value is true.\n\t* parse.y (global_decl): Handle global declarations here,\n\tincluding optional initialization.\n\t* t-builtins.cc (builtin_global): Deleted.\n\nThu Nov  5 23:59:39 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc (builtin_feval): New function.\n\t* tree-extras.cc (feval): Handle the dirty details.\n\n\t* g-builtins.cc (builtin_rand): New function.\n\t* tree-extras.cc (rand): Handle the dirty details.\n\nWed Nov  4 14:54:17 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* num2str.m: New M-file.\n\t* int2str.m: Ditto.\n\n\t* g-builtins.cc (builtin_disp): New function.\n\n\t* g-builtins.cc (builtin_fprintf, builtin_printf,\n\tbuiltin_sprintf):  New functions.\n\t* tree-extras.cc (do_printf): New function to handle the gory\n\tdetails.\n\n\t* g-builtins.cc (builtin_flops): Implement here because we may\n\tactually want to count operations at some point.\n\nTue Nov  3 17:06:40 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-const.cc (do_binary_op): Detect and give error message for\n\toptations on empty matrices.\n\t(do_unary_op): Likewise.\n\n\t* parse.y (matrix): Convert `[]' and `[;]' to empty matrices\n\tinstead of (tree_matrix *) NULL.\n\nMon Nov  2 11:23:40 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* src/Makefile.in: Update dependencies.\n\t* liboctave/Makefile.in: Ditto.\n\n\t* tree-const.cc (force_numeric): Consult matlab_strings()\n\tbefore doing string to number conversion.\n\t* builtins.cc (matlab_strings): New builtin variable.\n\t* utils.cc (matlab_strings): New function.\n\n\t* tree-extras.cc (linear_constraints_ok): New function.\n\t(linear_constraints_ok): Ditto.\n\t(npsol): Use them to avoid creating inconsistent sets of\n\tconstraints and crashing.  It would really be nice to have\n\texception handling.\n\n\t* symtab.cc (load): Issue error mesasges if attempt to find\n\tname keyword fails.\n\n\t* Version 0.43.\n\n\t* tree-extras.cc (npsol): Use new minimize (phi, inform).\n\tHandle nargout == 3.\n\n\t* g-builtins.cc (builtin_npsol): Allow nargout == 3.\n\n\t* NPSOL.cc (set_default_options): New function.\n\t(all constructors): Use it.\n\t(operator =): Use it and print warning message (setting default\n\toptions doesn't represent a true copy and it would be somewhat\n\tdifficult to fix this...).\n\n\t* npchkd.f (npchkd): Only write message if msglvl > 0.\n\nSun Nov  1 00:58:16 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* gnuplot-build/Makefile.in (LIBDIRS): Set correctly.\n\t(notgnuplot): Use it.\n\n\t* libcruft/misc/gen-d1mach.c: Generate d1mach.f at build time\n\tinstead of depending on the installer to get it right.\n\t* libcruft/Makefile.in (gen-d1mach): New target.\n\n\t* libcruft/Makerules.in (SPECIAL): New macro.\n\t(DISTFILES): Include it.\n\n\t* libcruft/Makerules.in (SPECIAL_DEPEND): Ditto.\n\t(../../libcruft.a): Use it.\n\nMon Oct 26 02:25:11 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (is_valid_function): Try harder to find M-files\n\tthat may not have been parsed yet.\n\n\t* symtab.cc (define (symbol_record*)): New function.  Make it\n\tsimple to copy all fields of a symbol_record if we already have\n\tone.\n\t* utils.cc (force_global): Use it.\n\n\t* utils.cc (valid_identifier): Allow underscores in names.\n\n\t* tree-extras.cc (npsol): Force column vector to be returned.\n\t(fsolve): Ditto.\n\n\t* Version 0.42.\n\n\t* tree-extras.cc (fsolve): New function for solving nonlinear\n\talgebraic equations.  This needs much more work if it is to\n\tprovide all the functionality of Matlab's fsolve.\n\n\t* tree-extras.cc (fsolve_user_function): New function.\n\n\t* libcruft/minpack: Import needed functions.\n\n\t* tree-extras.cc: (npsol (tree_constant*, int, int): Completely\n\trewrite to handle all of the follwing:\n\n\t  1. npsol (x, phi)\n\t  2. npsol (x, phi, lb, ub)\n\t  3. npsol (x, phi, lb, ub, llb, c, lub)\n\t  4. npsol (x, phi, lb, ub, llb, c, lub, nllb, g, nlub)\n\t  5. npsol (x, phi, lb, ub,              nllb, g, nlub)\n\t  6. npsol (x, phi,         llb, c, lub, nllb, g, nlub)\n\t  7. npsol (x, phi,         llb, c, lub)\n\t  8. npsol (x, phi,                      nllb, g, nlub)\n\n\t* tree-extras.cc (npsol_constraint_function): New function.\n\n\t* tree-extras.cc (tree_constant_to_vector): New function.\n\t(tree_constant_to_matrix): Ditto.\n\t(takes_correct_nargs): Ditto.\n\nFri Oct 23 10:19:51 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (is_valid_function): New function.\n\t(npsol): Use it.\n\n\t* utils.cc (s_plural): New function.\n\t(es_plural): Ditto.\n\n\t* tree-extras.cc (npsol): Improve checks for valid objective\n\tfunction.\n\n\t* tree.cc (tree_function::max_expected_args): New function.\n\nThu Oct 22 18:42:07 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc (builtin_lsode): Quick check of arguments, then\n\tcall lsode (tree_constant *, int, int).\n\t* Move rest of code for implementing builtin_lsode to\n\ttree-extras.cc.\n\n\t* g-builtins.cc (builtin_npsol: Quick check of arguments, then\n\tcall npsol (tree_constant *, int, int).\n\t* Move rest of code for implementing builtin_npsol to\n\ttree-extras.cc.\n\n\t* tree-const.cc: Simplify functions that require numeric arguments\n\tby always calling make_numeric for them instead of doing it\n\tconditionally.\n\t* tree.cc: Ditto.\n\t* tree-extras.cc: Ditto.\n\n\t* tree-const.h (tree_constant::make_numeric): Return *this if\n\talready a numeric type.\n\n\t* NLP.cc: In constructors, don't try to assign NULL to bounds\n\tobjects.\n\n\t* tree-const.cc (tree_constant_rep::valid_as_scalar_index (void)):\n\tNew function.\n\t* tree-const.cc (valid_scalar_indices (tree_constant*, int):\n\tNew function.\n\t* tree-const.cc (tree_constant_rep::do_scalar_index): Simplify by\n\tusing functions to determine if arguments are valid as indices.\n\t(tree_constant_rep::do_scalar_assignment): Likewise.\n\nWed Oct 21 14:11:58 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-extras.cc (determinant): Make it work again.\n\n\t* tree.cc (tree_identifier::eval (tree_constant*, int, int, int):\n\tSimplify logic.  Only have one ans->eval() call.\n\n\t* tree-const.cc (tree_constant_rep::eval (tree_constant*, int,\n\tint, int): Properly handle indexing of range constants.\n\n\t* tree-const.cc (stupid_fortran_style_matrix_index): Preserve row\n\tor column orientation for vectors.\n\n\t* toeplitz.m: New M-file.\n\t* invhilb.m: Ditto.\n\t* hankel.m: Ditto.\n\n\t* tree-extras.cc (max): Handle two arg case.\n\ttree-extras.cc (max): Likewise.\n\t(min (Matrix&, Matrix&): New function.\n\t(max (Matrix&, Matrix&): Ditto.\n\nTue Oct 20 15:13:57 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.41.\n\nMon Oct 19 16:46:35 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* rows.m: New M-file.\n\t* g-builtins.cc (builtin_rows): Delete function.\n\t* g-builtins.h (builtin_rows): Delete declaration.\n\t* builtins.cc (general_functions): Delete from initialization list.\n\n\t* columns.m: New M-file.\n\t* g-builtins.cc (builtin_columns): Delete function.\n\t* g-builtins.h (builtin_columns): Delete declaration.\n\t* builtins.cc (general_functions): Delete from initialization list.\n\n\t* length.m: New M-file.\n\t* g-builtins.cc (builtin_length): Delete function.\n\t* g-builtins.h (builtin_length): Delete declaration.\n\t* builtins.cc (general_functions): Delete from initialization list.\n\n\t* g-builtins.cc (builtin_size): If two values are expected to be\n\treturned, put nr and nc in separate registers.\n\nSun Oct 18 13:37:17 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree-base.h: Extract base tree class declarations from tree.h.\n\t* tree-const.cc, tree-const.h: Extract tree_constant class from\n\tfrom tree.cc, tree.h.\n\tChange all uses of tree.h to use either or both of tree-base.h and\n\ttree-const.h.\n\n\t* Matrix.cc (solve): Replaces LinEqn class.\n\ttree.cc (do_binary_op) Use it.\n\n\t* g-builtins.cc (builtin_max): New function.\n\ttree.cc (tree_constant::max): New friend.\n\n\t* g-builtins.cc (builtin_min): New function.\n\ttree.cc (tree_constant::min): New friend.\n\n\t* cond.m: New M-file.\n\n\t* rank.m: New M-file.\n\n\t* g-builtins.cc (builtin_svd): New function.\n\ttree.cc (tree_constant::svd): New friend function.\n\n\t* g-builtins.cc (builtin_svd): New function.\n\ttree.cc (tree_constant::svd): New friend function.\n\n\t* t-builtins.cc (builtin_format): New function.  Implement some of\n\tthe Matlab options (sort of).\n\n\t* Major changes to liboctave source.  A new Matrix.cc/Matrix.h\n\tcompletely replaces the old Matrix/Vec/AVec code.  All other\n\tclasses that use Matrix/Vector objects have been updated (or\n\tdeleted, if they are no longer needed).  All callers changed in\n\toctave sources.\n\nSun Oct 11 21:22:16 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_function::eval): Don't define more function\n\tparameters than are expected.  If fewer arguments than expected\n\tare actually supplied, force them to be undefined.\n\n\t* parse.y (fact): Give warning and abort for identifiers followed\n\tby '['.  This should catch most improper uses of [] instead of ()\n\tfor indexing operators.\n\n\t* tree.cc (do_binary_op (Matrix&, Matrix&, tree::expression_type):\n\tHandle element by element exponentiation.\n\nTue Sep 22 10:09:06 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.40.\n\nMon Sep 21 13:09:06 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l: Accept ** and .** as well as ^ and .^ as exponentiation\n\toperators.\n\nFri Sep 18 15:19:51 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.h tree.cc utils.cc g-builtins.cc: Elimitate need for\n\toverloaded operator-> in the tree_constant class.  Also eliminate\n\tuses of ->string, ->scalar, etc.  Instead, always call\n\t.string_value(), .double_value(), etc.\n\n\t* builtins.cc (install_builtins): Reserve `ans' as an\n\tuninitialized global variable (should it really be global?).\n\n\t* parse.y (ans_expression): Handle default assignemnt to builtin\n\tvariable ans.\n\t(command): Use it.\n\nTue Sep 15 14:06:12 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.39.\n\n\t* tree.cc (tree_identifier::bump_value): Don't try to increment\n\tundefined symbols or values.\n\t(tree_prefix_expression::eval): Don't call bump_value if id is a\n\tNULL_TREE.\n\t(tree_prefix_expression::eval): Likewise.\n\n\t* g-builtins.cc (lsode_builtin): Handle extra arguments.\n\tliboctave/ODE.cc (integ): Add template for handling bad returns\n\tfrom lsode.\n\n\t* tree.cc (class tree_return_command): Implementation is just like\n\tbreak and continue.  Something seems wrong about this...\n\tlex.l (return): Recognize return statement.\n\tparse.y (statement): Handle function returns.\n\ttree.cc (various eval functions): Check to see if we are returning\n\tfrom a function.\n\n\t* tree.cc (tree_for_command::eval): Set abort_on_undefined when\n\tevaluating the loop body.\n\t(tree_while_command::eval): Ditto.\n\n\t* tree.cc (class tree_idenfier): Improve searching/parsing M-files\n\twhen handling undefined names.\n\ttree.cc (tree_identifier::parse_m_file (char*)): New function.\n\t(tree_identifier::parse_m_file (void)): Use it.\n\n\t* utils.cc (force_global): New function.\n\t* symtab.cc (symbol_table::remove_name(char *)): New function.\n\n\t* tree.h, tree.cc (class tree_constant): Split into two classes,\n\ttree_constant (handle) and tree_constant_rep (body) to enable use\n\tof `smart pointers' and reference counted memory management.\n\t(Lots of things are different with this change.)\n\nSat Aug 22 11:58:27 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.38.\n\n\t* lex.l (COMMA_KLUDGE): Delete production, all uses.  This doesn't\n\tseem to be necessary anymore, and the mystery output lines\n\tdisappear without it.\n\n\t* builtins.cc (make_eternal (char *)): New function.\n\t(install_builtins): Make LOADPATH, eps, pi, Inf, and NaN eternal.\n\n\t* New M-files: mean.m, std.m, hadamard.m, vander.m, hilb.m,\n\tlinspace.m, logspace.m.\n\n\t* tree.cc (tree_function::eval): Don't check number of arguments\n\tsupplied against total number possible (previously thought to be\n\t`expected') so that user-defined functions can have variable\n\tnumbers of arguments.\n\n\t* tree.cc (tree_identifier::eval_undefined_error): New function.\n\t(tree_identifier::eval): Use it.\n\n\t* octave.cc (abort_on_undefined): New global symbol to control\n\twhether we should jump to top level after an undefined symbol has\n\tbeen encountered.\n\ttree.cc (tree_function::eval) Set it before evaluating function\n\tbody, restore to previous value after successful completion.\n\ttree.cc (tree_identifier::eval_undefined_error): Use it\n\nFri Aug 20 09:31:14 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc:  New mapper functions:\n\tisnan: Uses xisnan, which calls IEEE function isnan.\n\tisinf: Uses xisinf which calls IEEE functions finite and isnan,\n\tor isinf if available.\n\tfinite: Uses xfinite, which calls IEEE function finite.\n\tabs: Uses fabs.\n\n\t* g-builtins.cc\t(sumsq): New function.\n\t(diag): New function.\n\n\t* tree.cc (tree_constant::sumsq): New function\n\t(tree_constant::diag): New function\n\n\t* Matrix.cc (sumsq): New function.\n\t(diag): Ditto.\n\nThu Aug 20 00:36:44 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc (builtin_error): New function.\n\n\t* gnuplot-build/Makefile.in (dist): Actually create `term'\n\tsubdirectory.\n\n\t* Lots of changes to tree.cc tree_assignment_expression::eval and\n\ttree_index_expression::eval to make matrix indexing work like\n\tMatlab.\n\t(do_fortran_indexing): New user-level variable to control this\n\tbehavior.  If this variable is false, things like\n\n\t  a([1,2;3,4], [1,2;3,4]) = b\n\n\tbecome syntax errors.  Otherwise, Matlab braindamage prevails.\n\nTue Aug 18 13:15:46 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.37.\n\n\t* tree.cc (do_matrix_assignment): Conditionally allow single\n\tindices for Matrix assignments.\n\t(do_matrix_index): Ditto.\n\n\t* utils.cc (do_fortran_indexing): New function.\n\tutils.h: Declare it.\n\tbuiltins.cc (install_builtins): Default value for new\n\tdo_fortran_indexing variable.\n\n\t* builtins.cc (install_builtins): Bind eps to the value\n\tDBL_EPSILON from float.h.  Make it read only (will this cause\n\ttrouble)?\n\t* Bind Inf to 1/0 (will only work for IEEE machines.\n\t* Bind NaN to 0/0 (will only work for IEEE machines.\n\t* Add round, fix, floor, ceil, and sign to builtin mapper functions.\n\t(round): New function.\n\t(fix): Ditto.\n\t(signum): Ditto.\n\t* Add clc (clear screen function).\n\t* Add home (clear screen function).  To be just like Matlab, this\n\twouldn't clear the screen.\n\n\t* New M-files: fliplr.m, flipud.m, trace.m, reshape.m.\n\n\t* utils.cc (bind_variable): Revise bind_string_variable so that it\n\ttakes a tree_constant as an argument.\n\t(bind_protected_variable): Likewise for the function\n\tbind_protected_string_variable.\n\t(bind_string_variable): Delete.\n\t(bind_protected_string_variable): Ditto.\n\tutils.h: Fix declarations.\n\tbuiltins.cc t-builtins.cc: Fix callers.\n\n\t* builtins.cc (install_builtins): Bind LOADPATH here.\n\toctave.cc (initialize_globals): Not here.\n\n\t* Makefile.in (SOURCES): Add new scripts directory.\n\t(scripts): New target.\n\tlibcruft/Makefile.in (install): Don't depend on all.\n\n\t* utils.cc (m_file_in_path): Get path from LOADPATH variable.\n\ttree.cc (tree_identifier::parse_m_file): Modify caller.\n\n\t* src/Makefile.in (OCTAVE_M_FILE_DIR): New variable.\n\t(utils.o): Use it.\n\tutils.cc (default_path): Use it.\n\n\t* utils.cc (pathstring_to_vector): New function.\n\t(default_path): Return colon separated path instead of vector of\n\tpaths.\n\t* octave.cc (initialize_globals): Use pathstring_to_vector here.\n\tBind output of default_path to LOADPATH variable.\n\tEliminate octave_path global variable.\n\n\t* tree.cc (isstr): New function.\n\t(all): Ditto.\n\t(any): Ditto.\n\t(cumprod): Ditto.\n\t(cumsum): Ditto.\n\t(prod): Ditto.\n\t(sum): Ditto.\n\n\t* g-builtins.cc (builtin_isstr): New function.\n\t(builtin_all): Ditto.\n\t(builtin_any): Ditto.\n\t(builtin_cumprod): Ditto.\n\t(builtin_cumsum): Ditto.\n\t(builtin_prod): Ditto.\n\t(builtin_sum): Ditto.\n\n\t* Matrix.cc (all): New function.\n\t(any): Ditto.\n\t(cumprod): Ditto.\n\t(cumsum): Ditto.\n\t(prod): Ditto.\n\t(sum): Ditto.\n\n\t* scripts: New directory.\n\tscripts/strcmp.m: New file (first M-file function in distribution!).\n\tscripts/Makefile.in: New file.\n\tconfigure.in: Include scripts/Makefile in list of files to create.\n\nSat Aug 15 18:32:24 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.36.\n\nFri Aug 14 08:44:10 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (id_to_define): New global variable.\n\t(curr_m_file_name): Ditto.\n\t(current_infile): Ditto.\n\n\t* tree.h tree.cc (tree_identifier::parse_m_file): New function.\n\t(tree_identifier::eval): Handle M-files.\n\n\t* tree.h (stash_m_file_name): New virtual function.\n\t(stash_m_file_time): Ditto.\n\t(time_parsed): Ditto.\n\t(m_file_name): Ditto.\n\n\t* tree.h tree.cc (tree_function::stash_m_file_name) New function.\n\t(tree_function::stash_m_file_time): Ditto.\n\t(tree_function::time_parsed): Ditto.\n\t(tree_function::m_file_name): Ditto.\n\n\t* lex.l (reading_m_file): New global variable.\n\t(delete_buffer): New function.\n\t(yywrap): New function.  Always return 0 (is this a smart thing to\n\tdo?).\n\n\t* parse.y (func_def2): Handle input from m-files (sort of).\n\n\t* octave.cc (octave_path): New global variable.\n\t(using_readline): Ditto.\n\t(no_line_editing): Ditto.\n\n\t* octave.cc (main): Initialize current_command_number before\n\tcalling setjmp.\n\t* Increment it in main command loop, not in parse.y.\n\n\t* utils.h utils.cc (default_path): New function.\n\t(m_file_in_path): Ditto.\n\t(is_newer): Ditto.\n\n\t* octave.cc (main): Execute commands here.\n\t* parse.y (input): Not here.\n\n\t* octave.cc (tree *global_command): New global variable that\n\tpoints to the current command to be executed.\n\nThu Aug 13 07:08:11 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* parse.y: Make word_list_cmd a fact, not a command, so that\n\tthings like `y = who -all' can work.  You can't do that in Matlab.\n\n\t* t-builtins.cc (builtin_who): Print symbols in columns, sorted.\n\t(list_in_columns) New function, mostly stolen from GNU ls.\n\n\t* symtab.h symtab.cc (char **list (void)) New function.\n\t(char **sorted_list (void) New function.\n\n\t* tree.cc (various eval functions): Handle printing results of\n\ttext and general functions here.  Straighten out other printing\n\tstuff, maybe...\n\n\t* t-builtins.h t-builtins.cc: Make text functions return\n\ttree_constant* instead of int, delete print flag argument.\n\n\t* g-builtins.h g-builtins.cc: Delete print flag argument.\n\n\t* Version 0.35.\n\nWed Aug 12 15:12:23 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_builtin::eval): Call mapper function with\n\tprint = 0 to avoid getting two answers.\n\t(specific do_matrix_assignment functions): Handle resizing\n\tcorrectly for `:' indices.\n\t(tree_colon_expression::eval): Don't crash if the evaluation of\n\tan operand yields a NULL_TREE_CONST.\n\nMon Aug 10 07:31:37 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_identifier::define):  Return NULL_TREE_CONST if\n\tsymbol_record::define fails.\n\t(tree_identifier::assign): Likewise.\n\n\t* symtab.h (symbol_lifetime): New attribute for symbol_records.\n\tCan be either temporary or eternal.\n\t(symbol_class): Delete eternal attribute.\n\t* builtins.cc (install_builtins): Mark all builtins as eternal.\n\n\t* Version 0.34.\n\n\t* tree.h: Delete ttype, enum list of tree types.\n\n\t* g-builtins.h g-builtins.cc (builtin_colloc): New function.\n\n\t* liboctave (various): Add missing return values, etc. so that\n\tliboctave compiles cleanly.\n\n\t* tree.h tree.cc (tree_multi_assignment): New class to implement\n\tassignments to more than one variable.  Does it work?  Maybe...\n\n\t* tree.h (tree_constant **eval (int, int)): New virtual function.\n\t(is_identifier): Another one.\n\n\t* symtab.h (eternal): New class for symbol_records.\n\t* symtab.h symtab.cc (make_eternal): New function.\n\t* builtins.cc (install_builtins): Make builtin variables eternal.\n\n\t* tree.cc (list_to_vector): Surround by `#if 0/#endif' to avoid\n\tcompilation warning.\n\nSun Aug  9 03:18:38 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* t-builtins.h t-builtins.cc (builtin_cd): New function adapted\n\tfrom bash for changing the current working directory.\n\t(builtin_pwd): New function adapted from bash for printing the\n\tcurrent working directory.\n\n\t* utils.h utils.cc: New functions from bash for changing and\n\tprinting the current working directory:\n\n\t    pathname_backup        make_absolute\n\t    get_working_directory  change_to_directory\n\n\t* utils.h utils.cc (bind_string_variable): New function.\n\t(bind_protected_string_variable): Likewise.\n\n\t* octave.cc (initialze_globals): New function.\n\n\t* utils.h utils.cc: New functions from bash, mostly for fancy\n\tprompting:\n\n\t    polite_directory_format  absolute_pathname\n\t    absolute_program         base_pathname\n\t    read_octal               sub_append_string\n\t    decode_prompt_string\n\nThu Aug  6 02:39:31 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* octave.cc (initialize_history): Fix up to\n\t(octave_hist_file) New global variable.\n\t(octave_hist_size) Ditto.\n\t(history_lines_this_session) Ditto.\n\t(history_lines_in_file) Ditto.\n\n\t* input.cc (octave_gets): Keep track of number of lines read\n\tduring the current session.\n\n\t* utils.cc (default_history_file): New function.  Look for\n\tOCTAVE_HISTFILE environment variable and use its value if\n\tpossible.\n\t(default_history_size): New function.  Look for OCTAVE_HISTSIZE\n\tenvironment variable and use its value if possible.\n\n\t* t-builtins.cc (builtin_history): Steal from bash and modify to\n\twork with octave.\n\n\t* g-builtins.cc (builtin_det): New function.\n\n\t* tree.h tree.cc (determinant): New function\n\n\t* g-builtins.cc: Rewrite functions that use fill_matrix, inverse,\n\tand identity_matrix to use new versions implemented as friends of\n\ttree_constant.  This is being done in an attempt to get rid of all\n\tcalls to tree_constant::const_type() outside of tree.cc.\n\n\t* tree.cc (tree_constant): Implement new functions for filling\n\tand inverting tree constants as matrices, and for creating an\n\tidentity matrix from a tree_constant.\n\n\t* g-builtins.cc (builtin_inv): New function.\n\tbuiltins.cc: Allow builtin_inv to be called as either inv(A) or\n\tinverse(A).\n\n\t* tree.cc (do_binary_op (Matrix, Matrix)): Better handling of\n\tsolution of linear equations for square coefficient matrices.\n\n\t* LinEqn.cc (solve): Don't exit on singular matrices.  Implement\n\tnew variations of these functions that will allow status checking.\n\n\t* src/Makefile.in: Define GNUPLOT_BINARY and SITE_DEFAULTS.\n\tSpecific rules for octave.o and builtins.o to avoid defining\n\tGNUPLOT_BINARY and SITE_DEFAULTS for all .cc targets.\n\n\t* builtins.cc: Use macro GNUPLOT_BINARY.\n\n\t* octave.cc (execute_startup_files): Use macro SITE_DEFAULTS.\n\tExecute commands from SITE_DEFAULTS file.\n\n\t* t-buitlins.cc (builtin_pause): Make it work.\n\n\t* configure.in: Check for termio.h and/or sgtty.h.\n\n\t* octave.cc (clean_up): Reset terminal state to cooked mode.\n\t(main) Likewise, after return from SIGINT signal handler.\n\n\t* utils.h utils.cc (raw_mode): New function (mostly stolen from\n\tless(1)) toggle input processing for stdin to raw/cooked modes.\n\t(kbhit): New function to read one character from cin in raw mode\n\twithout echoing it.\n\n\t* builtins.cc: Fix expected number of arguments in lists of\n\tbuiltins.\n\n\t* tree.h tree.cc (max_args_expected (void)): New virtual function.\n\t(tree_builtins::) Provide a definition of it.\n\n\t* lex.l (identifier): Before gobbling up text function arguments,\n\tcheck to see that we expect some.\n\n\t* symtab.h symtab.cc (max_args_expected): Return max args expected\n\tby a symbol (currently only valid for tree_builtins).\n\nWed Aug  5 05:03:59 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* utils.h utils.cc (resize_on_range_error): Decide what to return\n\tbased on value of global variable of same name.\n\t(prefer_column_vectors): Likewise.\n\n\t* Version 0.33.\n\n\t* parse.y (func_def2): Call define (tree *, symbol_type), not\n\tdefine (tree *), so that the symbol type is set for user-defined\n\tfunctions.\n\t(assignment): Catch assignments to functions here.\n\n\t* tree.h tree.cc (tree_identifier::define (tree *, symbol_type):\n\tNew function (be careful out there...).\n\n\t* symtab.h (symbol_type): Add new `user_function' enum value.\n\n\t* tree.cc (do_matrix_assignment): Call prefer_column_vectors().\n\n\t* tree.h tree.cc (do_matrix_assignment (...)): New functions to\n\timplement assignment to indexed matrices.\n\t(do_scalar_assignment (...)): New function to implement assignment\n\tto an indexed scalar.\n\n\t* utils.h utils.cc (resize_on_range_error): New function.  Should\n\teventually decide what to return based on value of global variable\n\tof same name.\n\t(prefer_column_vectors): New function.\n\nTue Aug  4 05:37:47 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_constant::save): New function.\n\t(tree_constant::load): New function.\n\n\t* symtab.cc (symbol_record::save): New function.\n\t(symbol_table::load): New function.\n\n\t* t-builtins.cc (builtin_load): Start implementation.  Yikes, this\n\tis probably going to need a lot of work to be very robust...\n\n\t* t-builtins.cc (builtin_save): Implement by asking the\n\tsymbol_record to save itself.  Maybe this should really be done by\n\tasking the symbol table to save a symbol...\n\n\t* utils.cc (extract_keyword): New function.\n\t(valid_identifier): New function.\n\nFri Jul 31 04:16:24 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* parse.y (func_def3): Extra error cases for empty function\n\tbodies.\n\t(func_def1, func_def1a, func_def1b): Slighly straighten out some\n\ttruly twisted logic, eliminate func_def1a, rename func_def1b to\n\tfunc_def1a, and make statementss like function [x,y] = foo() end\n\twork properly (I think).\n\t(func_def*): Put function name in global symbol table, not top\n\tlevel symbold table.  This makes them accessible from other\n\tfunctions, eh?\n\n\t* t-builtins.cc (builtin_who): Accept -all, -local, -global, and\n\t-top flags.\n\nThu Jul 30 00:39:40 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* lex.l (current_buffer): New function to return current flex\n\tinput buffer.  Will need this to be able to switch file contexts.\n\n\t* Version 0.32.\n\n\t* lex.l (create_buffer, switch_to_buffer): New functions to handle\n\tinput from various streams.  This should be enough to allow us to\n\timplement Matlab-like M-files.\n\toctave.cc (main, execute_startup_files): Use them.\n\n\t* octave.cc (execute_startup_files): Execute commands from\n\t$HOME/.octaverc and ./.octaverc.\n\n\t* g-builtins.cc (builtin_plot): Delete temporary files.\n\tIgnore SIGINT while gnuplot is executing.\n\nWed Jul 29 20:16:25 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (all_args_defined): New function to check a\n\ttree_constant** vector to see if all elements are non-null.\n\t(tree_index_expression::eval (int)): Use it, and abort the\n\tevaluation if test fails.\n\n\t* terminals.h, terminals.cc: New files for doing things with\n\tgnuplot graphics terminal names.\n\tsrc/Makefile.in: Handle new files.\n\nTue Jul 28 00:25:24 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* g-builtins.cc (builtin_plot): Make it work, at least halfway.\n\n\t* g-builtins.cc (builtin_save): New function.\n\n\t* gnuplot-build/Makefile.in: Add -DREADLINE and remove readline.o\n\tfrom list of objects to actually enable the GNU command line\n\tediting.\n\n\t* configure.in: Use AC_PROG_CHECK macro to search for f2c and f77.\n\tCheck for several common Un*x Fortran compilers.\n\tAdd extra messages.\n\n\t* g-builtins.cc g-builtins.h: New files for builtin general\n\tfunctions extracted from builtins.cc.\n\n\t* t-builtins.cc t-builtins.h: New files for builtin text functions\n\textracted from builtins.cc.\n\n\t* Makefile.in (split-dist): New target.\n\n\t* Version 0.31.\n\nMon Jul 27 22:01:58 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_constant::do_matrix_index (tree_constant **, int):\n\tAllow single argument to work for matrices that are really row or\n\tcolumn vectors.\n\n\t* lex.l: Accept `<>' in addition to `!=' and `~=' as `not equal'\n\tcomparison operators.\n\n\t* libcruft/Makerules: Allow for compiling the Fortran routines\n\twith the native Fortran compiler instead of translating to C.\n\n\t* f2c-compat.sh, flibs.sh: New scripts which try to determine\n\twhether it will be possible for us to use the system's Fortran\n\tcompiler directly, and if so, what libraries to add to the loader\n\tcommand.  These scripts are known to work on SPARCstations running\n\tSunOS and DECstations running Ultrix.  Not tested elsewhere...\n\t* configure.in: Use them.\n\t* Makefile.in: Distribute them.\n\nWed Jul 22 00:04:48 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* builtins.cc: Begin implementation of NLP solver using NPSOL.\n\nTue Jul 21 13:44:13 1992  John W. Eaton  (jwe@june.che.utexas.edu)\n\n\t* octave.cc: If printing version information, also print pointer\n\tto warranty info.\n\n\t* builtins.cc: Implement the Matlab functions ones, zeros, eye,\n\tclock, date, size, length, and global.\n\tImplement warranty builtin.\n\t(builtin_clear): Fix to work with global variables.\n\n\t* symtab.cc (clear): Fix to work properly with global variables.\n\nMon Jul 20 11:58:23 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc (tree_constant::do_matrix_index (tree_constant**, int)):\n\tMake string indices work.\n\t(tree_constant::force_numeric): Don't special case\n\tsingle-character strings (this uncovers a flaw in the design of\n\tthe constructor for the magic colon operator...).\n\nFri Jul 17 16:33:00 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.30.\n\n\t* tree.cc: Delete undefined identifiers when trying to eval them.\n\n\t* builtins.cc: Add beginnings of builtin who and clear functions.\n\n\t* symtab.cc symtab.h (clear): New function.\n\n\t* tree.cc, tree.h, parse.y: Implement matrix indexing with colon\n\texpressions, implement the magic colon operator for column and row\n\tselection.\n\n\t* tree.cc tree.h: Completely rework colon expressions.\n\nThu Jul 16 09:27:48 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* gnuplot-dist: Rename from gnuplot-3.2 so we're not tied to a\n\tversion number.\n\nTue Jul 14 11:22:35 1992  John W. Eaton  (jwe@ward.che.utexas.edu)\n\n\t* tree.cc builtins.cc: Make argc/nargs/nargin work like C:\n\tthe argument count is the number of command line arguments plus\n\tthe function name.  This goes for `argument lists' for matrices as\n\twell as functions.  It seems a bit awkward but at it's consistent,\n\tand it's like C.  Hmm.  Maybe this is a bad choice...\n\n\t* utils.cc utils.h: New files for utility functions.\n\nMon Jul 13 00:29:50 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.29.\n\n\t* tree.cc tree_constant::tree_constant (matrix): Automatically\n\tconvert 1x1 matrices to scalars.\n\n\t* parse.y lex.l: Fix up a bunch of stupid stuff and reduce the\n\tnumber of shift/reduce conflicts to 16 (all but one because of the\n\toptional separator garbage).\n\n\t* parse.y lex.l: Allow for assignments to lists of identifiers to\n\tbe partially parsed.  This will still require some error checking\n\tin tree.cc to ensure that the list is made up of identifiers only,\n\tsince that's not enforced by the grammar (I don't see a way to do\n\tit, do you?)\n\nSun Jul 12 11:24:33 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* tree.cc tree.h parse.y lex.l: Implement logical AND (symbol &),\n\tOR (symbol |), and not (symbol ~).  Also provide the C-style\n\toperators &&, ||, and !).\n\n\t* Matrix.cc Matrix.h: Provide stupid element-wise logical\n\toperators for matrices.\n\n\t* Version 0.28.\n\n\t* parse.y lex.l tree.cc tree.h: Implement C-style prefix and\n\tpostfix increment and decrement operators (symbols ++ and --\n\trespectively).\n\n\t* parse.y lex.l tree.cc tree.h: Implement break and continue.\n\n\t* tree.cc tree.h: Assignment to matrix elements roughed out.\n\n\t* gnuplot/tree.cc: Solution of linear equations via the lift\n\tdivision operator partially implemented.  Singular coefficient\n\tmatrices aren't handled very well yet...\n\n\t* gnuplot-build/Makefile.in: Make this work to build gnuplot for\n\tgeneric X11/unix environments.\n\t* Remove -Wall from CFLAGS to avoid loads of warnings.\n\t* Use GNU readline instead of the one that comes with gnuplot.\n\n\t* gnuplot-build/*.diff: Various patches for various things.\n\nSat Jul 11 10:14:12 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.26\n\n\t* src/Makefile.in: Distribute lex.cc, parse.cc, y.tab.h.\n\t* src/Makefile.in (dist): Depend on lex.cc and parse.cc.\n\n\t* gnuplot-build: New directory for patching and building gnuplot.\n\tThis is apparenty required because the gnuplot license won't allow\n\tdistrubution of modified versions, but will allow patches to be\n\tdistributed.\n\t* gnuplot-build/Makefile.in: New file.\n\n\t* gnuplot-3.2: New directory.\n\n\t* readline: New directory from the bash-1.12 distribution, plus\n\ttilde.c from bash's lib/glob directory and xmalloc.c from bash's\n\tlib/malloc directory.\n\t* readline/Makefile.in, readline/doc/Makefile.in,\n\treadline/examples/Makefile.in: New files.\n\n\t* All Makefie.in files: Allow make to work from any directory, not\n\tjust the top level one.\n\nFri Jul 10 22:20:56 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* SERVICE: Remove, since it seems too specific to GNU products.\n\nThu Jul  9 07:48:33 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.20.\n\n\t* Solution of ODEs with LSODE partially implemented.  It's\n\tpossible to solve some simple equations.\n\n\t* tree.cc tree.h (tree_constant): Add string constants and make\n\tthem work more or less like string constants in Matlab (implicit\n\tconversion to ASCII numbers -- gag.  This isn't complete, and it\n\tit assumes that ASCII is the character set for the host\n\tmachine/compiler...).\n\nTue Jul  7 07:28:35 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.19.\n\n\t* User defined function definitions and calls to them mostly work.\n\tStill need to implement multiple return values correctly.\n\nMon Jul  6 04:23:37 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.18.\n\n\t* lex.l parse.y tree.cc tree.h: Begin implementation of\n\tuser-defined functions.\n\nSun Jul  5 19:27:08 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.17.\n\n\t* lex.l: Replace SAVE_STRING macro with a function.\n\n\t* builtins.cc (builtin_document): New builtin function.\n\t(builtin_help): Make it work.\n\n\t* lex.l: More rules for gathering text.  These are still not quite\n\tas they should be, but they will work in most cases.  I think the\n\tflex generated scanner is either going to have to be reworked or\n\treplaced with a handemade version at some point (probably soon)...\n\n\t* tree.cc tree.h: Add tree_word_list and tree_word_list_command\n\tclasses for text functions.\n\nFri Jul  3 05:13:15 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.16.\n\n\t* builtins.h builtins.cc: New files for builtin functions.\n\tImplement a few simple builtin functions.\n\n\t* tree.cc tree.h: Add tree_builtin type for builtin functions.\n\n\t* tree.cc tree.h: eval (args...) New virtual function.\n\nThu Jul  2 01:27:38 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.15.\n\n\t* symtab.h, symtab.cc: Allow variables and functions to be tagged\n\tas read-only or read-write.\n\nWed Jul  1 15:54:36 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* input.cc and octave.cc: allow input to come from a file.\n\n\t* lex.l: to accept `#' as a comment character (allows one to\n\tuse the `#!/bin/octave' style script hack).\n\n\t* doc: New directory containing skeleton stuff\n\t* SERVICE: New file from GCC.\n\t* BUGS: New file, now produced from doc/bugs.texi.\n\t* INSTALL: New file, now produced from doc/install.texi.\n\nSat Jun 27 15:52:37 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.14.\n\n\t* Fixed parser to eliminate reduce/reduce conflicts.\n\n\t* Fixed parser to recognize assignment to multiple identifiers\n\t(e.g., [E,V] = eig (A); ).\n\n\t* Quickie implementation of indexed array evaluation.  Works for\n\tscalar indices, but not range/array indices.\n\nFri Jun 26 04:23:12 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.12.\n\n\t* Hooks added for indexed array evaluation and assignment.\n\t* Colon expression implementation improved.\n\t* Implementation of for command eval() improved.\n\nThu Jun 25 00:28:12 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.11.\n\n\t* Colon expressions added.\n\t* For command added, but the implementation needs work.\n\nWed Jun 24 15:09:36 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.10.\n\n\t* Cheesy signal handler added to catch interrupts.\n\n\t* Matrix input works, even for nested matrices.  Some error\n\tchecking is done while the matrix is evaluated to ensure that\n\tthe number of rows and columns match up.\n\nMon Jun 22 00:21:49 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.9.\n\n\t* Command line matrix input partially implemented.  It's not yet\n\tpossible to enter nested matrices, but it is possible to enter\n\tsimple matrices (e.g. [1,2;a,b+c], where a, b, and c are scalars.\n\n\t* Version 0.8.\n\n\t* If commands added.\n\n\t* Version 0.7.\n\n\t* Command chains added.\n\t* Boolean operations added, tested for scalars.\n\t* While loop added, tested for simple commands.\n\nFri Jun 19 05:50:44 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.6.\n\n\tAt this early stage, while a lot of changes are being made very\n\tquickly, ChangeLog entries will probably just list features added.\n\n\t* Variable assignment works for scalars.\n\t* Simple scalar expressions work.\n\nThu Jun 18 06:44:24 1992  John W. Eaton  (jwe@schoch.che.utexas.edu)\n\n\t* Version 0.5.\n\n\t* src/version.h: For all the pre-alpha distributions, count\n\tversions as 0.1, etc. instead of 0.01.\n\n\t* Makefile: (dist) Automatically update version_string in\n\tsrc/version.h.\n\n\t* symtab.h, symbtab.cc: New files for symbol tables.\n\n\t* tree.h, tree.cc: New files for parse trees.\n\n\t* Lots of work unrecorded here.  Octave is now self-contained, the\n\ttree routines are being redesigned, etc.\n\nFri Mar 20 17:03:16 1992  John W. Eaton  (jwe@andy.che.utexas.edu)\n\n\t* Version 0.02.  Octave understands some simple matrix\n\texpressions, but it is not yet possible for matrix elements to\n\tbe constructed from expressions.\n\nThu Mar 19 06:13:39 1992  John W. Eaton  (jwe@andy.che.utexas.edu)\n\n\t* Version 0.01.  Octave understands simple scalar expressions.\n\tHey, Hey!  It is not yet self contained -- I'm still linking to\n\tthe old libraries in /usr/local/c++-classes, and this isn't likely\n\tto change for a while.  (Other things are much more important than\n\tmaking the distribution work on other machines.  Sorry...)\n\nFri Feb 21 05:06:38 1992  John W. Eaton  (jwe@andy.che.utexas.edu)\n\n\t* Version 0.00.  This includes the basic directory structure,\n\tmakefiles, and a lot of the old Fortran source, including a way to\n\tmake a libcruft.a.  Octave compiles and accepts input (with\n\thistory and editing) but doesn't do much else.\n\nWed Feb 19 06:20:44 1992  John W. Eaton  (jwe@andy.che.utexas.edu)\n\n\t* ChangeLog: New file.\n"
  },
  {
    "path": "etc/OLD-ChangeLogs/doc-ChangeLog",
    "content": "2011-04-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* interpreter/plot.txi: Clarify that inheritance of default property\n\tvalues only applies to the named object type.\n2011-04-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/plot.txi: Add colstyle function to documentation.\n\n2011-04-12  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/expr.txi: Correct use of it's -> its in documentation.\n\n2011-04-12  Ben Abbott  <bpabbott@mac.com>\n\n\t* interpreter/data.txi: Replace xref{Data Structures} with\n\txref{Structures}.\n\n2011-04-11  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/func.txi: Add discussion of isargout to Ignoring\n\tArguments section of documentation.\n\n2011-04-08  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/stats.txi: Deprecate studentize(), replace with\n\tzscore().\n\n2011-04-07  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Add spellcheck target to documentation\n\tMakefile.\n\n2011-04-06  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/numbers.txi, interpreter/strings.txi: Group commonly used\n\tisXXX functions together in documentation.\n\n2011-04-06  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/system.txi, interpreter/var.txi: Move pack() function to\n\tproper place in documentation.\n\n2011-04-06  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/diffeq.txi, interpreter/eval.txi, interpreter/plot.txi,\n\tinterpreter/var.txi: Clean up operator and function indices.\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/plot.txi: Add warning about single precision in FLTK.\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/aspell-octave.en.pws, interpreter/nonlin.txi,\n\tinterpreter/tips.txi: Spellcheck documentation for 3.4.1 release.\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/container.txi, interpreter/dynamic.txi,\n\tinterpreter/install.txi, interpreter/system.txi, interpreter/tips.txi:\n\tGrammarcheck files for 3.4.1 release.\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/grammar.txi: Remove reference to deprecated function\n\tperror().\n\n2011-04-03  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/grammar.txi, interpreter/octave.texi: Add new section\n\ton parsing to documentation.  Add functions add_input_event_hook,\n\tremove_input_event_hook, missing_function_hook to documentation.\n\n2011-04-03  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/linalg.txi: Add blkmm function to documentation.\n\n2011-04-02  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/stats.txi: Add quantile, prctile functions to\n\tdocumentation.\n\n2011-04-02  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/system.txi: Add isdeployed function to documentation.\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/io.txi: Add list_in_columns, terminal_size functions\n\tto documentation.\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/errors.txi, interpreter/octave.texi: Add onCleanup\n\tfunction to documentation.\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/contrib.txi: Add recommended format for commit messages\n\twhich reference the bug tracker.\n\n2011-03-28  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/expr.txi: Eliminate space between variable and\n\tparenthesis when using indexing.\n\t* interpreter/intro.txi, interpreter/io.txi: Fix typos in docstring.\n\t* interpreter/tips.txi: Add new recommendations for double spaces at\n\tstart of sentences and suggested variable names.\n\n2011-03-28  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/basics.txi: Add do_braindead_shortcircuit_evaluation to\n\tthe list of variables set by --traditional option.\n\n2011-03-27  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/expr.txi: Add allow_noninteger_range_as_index to\n\tdocumentation.\n\n2011-03-27  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/expr.txi: Add do_braindead_shortcircuit_evaluation to\n\tdocumentation.\n\n2011-03-26  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/mk_undocumented_list: Add error_text to list\n\tof functions not requiring a docstring.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/container.txi: Add cellindexmat function to documentation.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/oop.txi: Add optimize_subsasgn_calls function to\n\tdocumentation.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/stats.txi: Add runlength function to documentation.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/plot.txi: Add isocolors, isonormals, isosurface functions\n\tto documentation.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/basics.txi: Add dump_prefs to documentation.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave.texi, interpreter/plot.txi: Add daspect, pbaspect\n\tfunctions to documentation.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave.texi, interpreter/plot.txi: Add getappdata,\n\tsetappdata, isappdata, rmappdata functions to documentation.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/matrix.txi: Add nth_element function to documentation.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/aspell-octave.en.pws, interpreter/io.txi,\n\tinterpreter/octave.texi, interpreter/plot.txi: Add uimenu, uigetdir,\n\tuigetfile, and uiputfile to documentation.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/nonlin.txi, interpreter/octave.texi: Add fminbnd,\n\tfminunc functions to documentation.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/arith.txi, interpreter/linalg.txi: Add function chop\n\tto documentation.  Re-order Utility Functions and move function dot\n\tfrom linear algebra section to be with other utility functions.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/basics.txi: Add gen_doc_cache, get_help_text,\n\tget_help_text_from_file, get_first_help_sentence to documentation.\n\n2011-03-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/io.txi: Add fileread to documentation.\n\n2011-03-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/system.txi: Add gethostname to documentation\n\n2011-03-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/mk_undocumented_list: Add fmod,\n\toctave_tmp_file_name to list of exceptions which are already\n\tdocumented.\n\n2011-03-17  Iain Murray  <iain@iainmurray.net>\n\n\t* interpreter/system.txi: Remove nprocs and nprocs_conf functions\n\tfrom documentation and replace with nproc.\n\n2011-03-16  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/system.txi: Add nproc and nproc_conf functions to\n\tdocumentation.\n\n2011-03-03  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/matrix.txi: Deprecate is_duplicate_entry.\n\n2011-03-02  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/stats.txi: Correctly refer to discrete uniform\n\tdistribution in documentation.\n\n2011-03-01  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* interpreter/dynamic.txi: Make it clear that <octave/oct.h> is\n\ta C++ source file and refer to the section where other languages\n\tare discussed.\n\n\t* faq/OctaveFAQ.texi: Major update to FAQ. Whitespace changes.\n\tUpdate comments to version 3.4 of Octave. Summarise important\n\tpoints of the NEWS file. We no longer have\n\tstable/testing/unstable, only stable and development. Mention\n\tnewer versions of Windows. Update references to Matlab's latest\n\tversion. Mention that `!' can't be used for shell escapes.\n\tUpdate other numbers like number of pages in manual, version\n\tnumbers, dates when things happened, file sizes. Clean out dead\n\tlinks. Remove mentions of bugs@octave.org email address. Don't\n\tsay you can get Octave tapes from the FSF. Mention Ubuntu as\n\tanother distribution with Octave packages. Change package names\n\tin anticipation for the forthcoming 3.4 binary packages. Explain\n\tnested functions. Hint that classdef might happen in 3.5.\n\tMention 3D patches in the OpenGL backend. Clarify Matlab-style\n\tshort-circuiting. Specify that Octave also onCleanup.\n\n2011-02-28  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/numbers.txi: Add isrow, iscolumn functions to manual.\n\n2011-02-25  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* faq/OctaveFAQ.texi: Uniformise all mentions of Matlab to be\n\ttypeset in the @sc{Matlab} style. Also do some minor\n\tproofreading like removing trailing spaces and some minor\n\tspellchecking.\n\n2011-02-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/install.txi: Remove reference to POSIX regex library.\n\n2011-02-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/arith.txi, interpreter/io.txi, interpreter/oop.txi:\n\tRemove functions which have no DOCSTRING entries.\n\n2011-02-10 Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* interpreter/linalg.txi: Added gmres to the specialized solvers.\n\n\n2011-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/contributors.in: Add Fotios Kasolis to the list.\n\n2011-02-05  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/mk_undocumented_list: Add dbnext, alias for\n\tdbstep, to functions not requiring a docstring.\n\n2011-02-05  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/aspell-octave.en.pws: Add new spelling\n\texceptions to Octave private dictionary.\n\n2011-02-05  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave.texi: Update copyright on manual to 2011.\n\n2011-02-05  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/mkoctfile.1, interpreter/octave-config.1,\n\tinterpreter/octave.1: Overhaul man pages for release 3.4.\n\n2011-02-04  Rik  <octave@nomad.inbox5.com>\n\n\t* icons/octave-logo.ico: Add logo format left out of last changeset.\n\n2011-02-04  Rik  <octave@nomad.inbox5.com>\n\n\t* icons/: New directory for icons and .desktop files.\n\t* icons/octave-logo.png, icons/octave-logo.svg: Add new Octave O logo\n\tto Mercurial.\n\t* Makefile.am: New Makefile to build .desktop file and distribute logos.\n\t* octave.desktop.in, octave-sombrero.png: Moved from examples directory.\n\t* octave_branding_samples.svg: Original logos and branding material for\n\tOctave.  This file is not distributed.\n\n\t* interpreter/octave.texi: Use new O logo on title page.\n\t* interpreter/octave_logo.eps: O logo in eps form for Postscript output.\n\t* interpreter/octave_logo.pdf: O logo in pdf form for pdf output.\n\n2011-01-30  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Use pattern-style rules to make .texi files\n\trather than older suffix-style rules.\n\n2011-01-30  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave.texi: Add new section\n\t\"Customizing Toolkit Behavior\"\n\n\t* interpreter/plot.txi: Add functions gnuplot_binary, mouse_wheel_zoom,\n\tand gui_mode to new section.\n\n2011-01-30  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/optim.txi: Deprecate glpkmex function and remove\n\tfrom documentation.\n\n2011-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/install.txi (Compiling Octave with 64-bit\tIndexing):\n\tRemove info about ARPACK.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave.texi: Add new subsection on FLTK interaction.\n\t* interpreter/plot.txi: Add fltk_gui_mode, fltk_mouse_wheel_zoom\n\tfunctions to documentation.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/arith.txi: Add accumdim function to documentation.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/set.txi: Add powerset function to documentation.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/system.txi: Add S_ISSOCK function to documentation.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/system.txi: Add S_ISBLK and related functions to\n\tdocumentation.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/optim.txi: Add glpkmex function to documentation.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/system.txi: Add compare_versions function to\n\tdocumentation.\n\n2011-01-27  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/numbers.txi: Add sizemax function to documentation.\n\t* interpreter/doccheck/mk_undocumented_list: Add ifelse to functions\n\tnot requiring documentation.\n\n2011-01-27  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/image.txi: Add whitebg function to documentation.\n\t* interpreter/plot.txi: Add reset function to documentation.\n\n2011-01-27  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/linalg.txi: Add rsf2csf to documentation.\n\n2011-01-27  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/geometry.txi: Add trisurf to documentation.\n\n2011-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/arith.txi (Rational Approximations): Move here.\n\tUpdate menu.\n\t* interpreter/io.txi: From here.\n\tUpdate menu.\n\t* interpreter/octave.texi (Top): Update detailed menu.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/mk_doc_cache.m, interpreter/mkoctfile.1,\n\tinterpreter/munge-texi.cc, interpreter/doccheck/mk_undocumented_list:\n\tStrip trailing whitespace.\n\n2011-01-26  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/basics.txi: Use @code to eliminate extra single quotes\n\tin index.\n\t* interpreter/container.txi: Add @opindex citations for '.', '{' and\n\t'}'.\n\n2011-01-26  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave-bug.1: Delete obsolete man page\n\t* interpreter/Makefile.am: Stop distributing octave-bug.1 man page.\n\n2011-01-26  Olaf Till <olaf.till@uni-jena.de>\n\n\t* interpreter/package.txi: Document variables MKOCTFILE,\n\tOCTAVE_CONFIG, and OCTAVE exported by pkg for configure and make.\n\n2011-01-25  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Remove pass-through rules for AUTHORS, BUGS, and\n\tINSTALL.OCTAVE which are no longer required.\n\n2011-01-24  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am, interpreter/Makefile.am: Add rule to build AUTHORS file.\n\t* interpreter/preface.txi: Add @ifclear rule to build AUTHORS file.\n\n2011-01-23  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/install.txi: Redo build instructions for release 3.4.\n\t* interpreter/doccheck/aspell-octave.en.pws: Add new words to\n\tOctave private dictionary from install.txi\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* doc/interpreter/diagperm.txi, doc/interpreter/linalg.txi,\n\tdoc/interpreter/sparse.txi: Use non-breaking spaces between certain\n\tadjectives and their linked nouns in docstrings.\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* doc/interpreter/doccheck/README: Update documentation for\n\tdocumentation scripts.\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* doc/interpreter/doccheck/aspell-octave.en.pws,\n\tdoc/interpreter/plot.txi: Use @nospell macro on certain words in\n\tdocstring.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* faq/OctaveFAQ.texi, interpreter/doccheck/aspell-octave.en.pws,\n\tinterpreter/octave.texi, interpreter/plot.txi: Update for\n\tbackend -> graphics_toolkit change.\n\n\t* interpreter/interpimages.m, interpreter/geometryimages.m,\n\tinterpreter/sparseimages.m, interpreter/plotimages.m:\n\tCall graphics_toolkit, not backend.\n\n2011-01-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/aspell-octave.en.pws: Add new words to Octave\n\tprivate dictionary.\n\n2011-01-19  Rik  <octave@nomad.inbox5.com>\n\n\t* doc/interpreter/diagperm.txi, doc/interpreter/dynamic.txi,\n\tdoc/interpreter/func.txi, doc/interpreter/install.txi,\n\tdoc/interpreter/intro.txi, doc/interpreter/numbers.txi,\n\tdoc/interpreter/oop.txi, doc/interpreter/plot.txi,\n\tdoc/interpreter/sparse.txi, doc/interpreter/stats.txi: Grammarcheck\n\ttxi files for 3.4 release.\n\n2011-01-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/quad.txi: Add quadcc to documentation.\n\n2011-01-15  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/expr.txi: Add merge/ifelse function to documentation.\n\n2011-01-15  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/func.txi, interpreter/intro.txi: Eliminate\n\t@deffn macros.\n\n2011-01-15  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/mk_undocumented_list: Update list of exceptions\n\tnot requiring documentation.\n\n2011-01-15  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/stats.txi: Add stdnormal_xxx functions to documentation.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/matrix.txi: Add undocumented postpad to documentation.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave.texi, interpreter/poly.txi: Add undocumented\n\tpolyaffine to documentation.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/container.txi: Add undocumented nfields to documentation.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/poly.txi: Add undocumented ppder, ppint, ppjumps\n\tfunctions to documentation.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/system.txi: Add undocumented matlabroot to documentation.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/linalg.txi: Add undocumented svd_driver to documentation.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/arith.txi: Add undocumented cbrt to documentation.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/arith.txi: Add undocumented erfcx to documentation.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* Update copyright notices for 2011.\n\n2011-01-12  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/basics.txi: Add <BACKSPACE> to cursor movement section.\n\n2011-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/basics.txi (Commands For History):\n\tDocument history_control.\n\n2011-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/contributors.in: Add Konstantinos Poulios to the list.\n\n2011-01-10  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* interpreter/diagperm.txi: Remove Matlab euphemism.\n\t* interpreter/dynamic.txi: Ditto. Also use @file macro for a\n\tcouple of filenames.\n\n2011-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/container.txi (Basic Usage and Examples):\n\tDocument print_struct_array_contents.\n\n2011-01-05  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave.texi: Put statistics detailmenu in correct order.\n\n2011-01-05  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/numbers.txi, interpreter/obsolete.txi,\n\tinterpreter/oop.txi, interpreter/stats.txi: Use @headitem macro to\n\tcreate column heads for @multitable entries.\n\n2011-01-05  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/grammar.txi: Update list of keywords in grammar.\n\n2011-01-05  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/plot.txi (Introduction to Plotting): Formatting\n\tand style fixes.  Eliminate redundant example.\n\n2011-01-03  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave.texi: Add new menu item \"Correlation and\n\tRegression Analysis\"\n\t* interpreter/stats.txi: Update documentation chapter on\n\tbasic statistics.\n\n2010-12-31  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/expr.txi: Add isindex function to documentation\n\t* interpreter/func.txi: Add isargout function to documentation\n\t* interpreter/matrix.txi: Add isfinite function to documentation\n\t* interpreter/numbers.txi: Add ishermitian function to documentation\n\n2010-12-31  Kai Habel  <kai.habel@gmx.de>\n\n\t* interpreter/arith.txi: Add curl and divergence function.\n\n2010-12-22  Tatsuro Matsuoka  <tmacchant@yahoo.co.jp>\n\n\t* nonlin.txi: Correct docs for using Jacobian with fsolve.\n\n2010-12-22  Judd Storrs <jstorrs@gmail.com>\n\n\t* interpreter/expr.txi: Insert operator function docstrings.\n\t* interpreter/oop.txi: Remove conflicting anchors for operator\n\tfunctions. Add cindex entries for overloaded operators. Add\n\toverloads to opindex.\n\t* interpreter/numbers.txi: Fix colon opindex.\n\n2010-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/func.txi, interpreter/sparse.txi: Remove documentation\n\ton deprecated function dispatch.\n\n2010-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Update mk_undocumented_list target to use\n\t$(srcdir) for portability.\n\n2010-12-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/container.txi, interpreter/func.txi,\n\tinterpreter/linalg.txi, interpreter/numbers.txi,\n\tinterpreter/signal.txi, interpreter/sparse.txi, interpreter/stats.txi,\n\tinterpreter/system.txi: Remove deprecated functions from manual.\n\n2010-12-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/mk_undocumented_list: Update script to\n\tautomatically remove functions from the \"test/\" and \"doc/interpreter\"\n\tdirectories.\n\n2010-12-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Add undocumented_list target to create list\n\tof undocumented functions.\n\n2010-12-17  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/plot.txi (Two-Dimensional Plots): Document comet3.\n\n2010-12-17  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/plot.txi (Introduction to Graphics Structures):\n\tDcoument isprop.\n\n2010-12-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/oop.txi: Redo table rendered incorrectly in Info\n\tenvironment.\n\n2010-12-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/numbers.txi: Remove obsolete documentation about 64-bit\n\tinteger arithmetic.\n\n2010-12-16  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/mk_undocumented_list: Update list of exception\n\tfunctions not requiring documentation.\n\n2010-12-09  Doug Stewart <doug.dastew@gmail.com>\n\n\t* interpreter/plot.txi: changed origial to origin in Quiver section\n\n2010-12-09  Kai Habel  <kai.habel@gmx.de>\n\n\t* interpreter/plot.txi: Add pie3 function.\n\n2010-11-26  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/install.txi (Compiling Octave with 64-bit\n\tIndexing): New section.\n\n2010-11-23  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/install.txi: Delete obsolete statement about\n\tneeding a patch for makeinfo.\n\n2010-11-18  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/contributors.in: Add Christos Dimitrakakis to the list.\n\n2010-11-18  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/contributors.in: Add Daisuke Takago to the list.\n\n2010-11-15  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/bugs.txi, interpreter/emacs.txi, interpreter/func.txi,\n\tinterpreter/geometry.txi, interpreter/linalg.txi,\n\tinterpreter/octave.texi, interpreter/package.txi, interpreter/plot.txi,\n\tinterpreter/stmt.txi, interpreter/strings.txi, interpreter/system.txi:\n\tUpdate info-based documentation menus to include new nodes.\n\n2010-11-15  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/octave.texi, interpreter/plot.txi: Rename subsection\n\t\"Printing Plots\" to \"Printing and Saving Plots\".  Add reference to\n\tnew saveas function.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/munge-texi.cc: Eliminate special case for __DECCXX.\n\n2010-11-01  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* interpreter/numbers.txi: Explain that ranges in vectors do get\n\texpanded.\n\n2010-10-24  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/mk_undocumented_list: New verification\n\tscript produces a list of undocumented functions.\n\n2010-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/io.txi (Simple File I/O): Document textscan and\n\ttextread.\n\n2010-10-23  Ben Abbott  <bpabbott@mac.com>\n\n\t* interpreter/strings.txi: Add @DOCSTRING(strread).\n\n2010-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/io.txi (Opening and Closing Files):\n\tDocument is_valid_file_id.\n\n2010-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/contributors.in: Add Gunnar Farnebäck to the list.\n\n2010-10-18  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/image.txi (Displaying Images):\n\tDelete documentation for image_viewer.\n\n2010-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/strings.txi: Document untabify.\n\n2010-09-30  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/contributors.in: Add Jordi Gutiérrez Hermoso to\n\tthe list.  Fix spelling of Søren Hauberg.\n\n2010-09-28  Rik  <octave@nomad.inbox5.com>\n\n\t* doc/interpreter/Makefile.am, doc/interpreter/geometryimages.m,\n\tdoc/interpreter/images.awk, doc/interpreter/interpimages.m,\n\tdoc/interpreter/plotimages.m, doc/interpreter/sparseimages.m: Use\n\tOctave to create pdf versions of plots for documentation rather than\n\tGhostscript via Makefile.\n\n2010-09-28  Rik  <octave@nomad.inbox5.com>\n\n\t* doc/interpreter/geometryimages.m, doc/interpreter/interpimages.m,\n\tdoc/interpreter/plotimages.m, doc/interpreter/sparseimages.m: Untabify\n\tscripts.\n\n2010-09-27  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/mk_doc_cache.m: Use single quotes for regular expression\n\tpatterns where possible.\n\n2010-09-25  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/mk_doc_cache.m: Remove requirement for PCRE to build\n\tdoc cache.  Correctly parse first sentence from docstrings with\n\tmultiple @deftypefn lines.\n\n2010-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.am (EXTRA_DIST): Add images.awk to the list.\n\n2010-08-15  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/matrix.txi: Add documentation for randi function.\n\n2010-08-13  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Update @EXAMPLEFILE dependencies.\n\n2010-08-10  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Change dependency to $(srcdir)/images.mk.\n\n2010-08-08  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Add documentation dependency on images.mk.\n\t* interpreter/config-images.sh: Create images.mk in passed in srcdir,\n\trather than pwd.\n\n2010-08-08  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/images.awk: HTML images depend on octave.html/index.html.\n\n2010-08-01  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/basics.txi, interpreter/contrib.txi,\n\tinterpreter/diagperm.txi, interpreter/dynamic.txi, interpreter/eos.txi,\n\tinterpreter/expr.txi, interpreter/geometry.txi,\n\tinterpreter/install.txi, interpreter/matrix.txi,\n\tinterpreter/numbers.txi, interpreter/oop.txi, interpreter/plot.txi,\n\tinterpreter/sparse.txi, interpreter/stats.txi, interpreter/testfun.txi,\n\tinterpreter/tips.txi: Grammarcheck documentation.  Add @noindent lines\n\tand ensure line length is less than 80.\n\n2010-07-28  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/arith.txi, interpreter/audio.txi, interpreter/basics.txi,\n\tinterpreter/container.txi, interpreter/contrib.txi,\n\tinterpreter/debug.txi, interpreter/diagperm.txi,\n\tinterpreter/diffeq.txi, interpreter/dynamic.txi, interpreter/emacs.txi,\n\tinterpreter/errors.txi, interpreter/eval.txi, interpreter/expr.txi,\n\tinterpreter/func.txi, interpreter/image.txi, interpreter/install.txi,\n\tinterpreter/interp.txi, interpreter/intro.txi, interpreter/io.txi,\n\tinterpreter/linalg.txi, interpreter/matrix.txi, interpreter/nonlin.txi,\n\tinterpreter/numbers.txi, interpreter/optim.txi,\n\tinterpreter/package.txi, interpreter/plot.txi, interpreter/poly.txi,\n\tinterpreter/quad.txi, interpreter/sparse.txi, interpreter/stmt.txi,\n\tinterpreter/strings.txi, interpreter/testfun.txi, interpreter/tips.txi,\n\tinterpreter/var.txi: Grammarcheck .txi documentation files.\n\n2010-07-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/tips.txi: Update some tips.\n\n2010-07-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/mk_doc_cache.m: Use regexp rather than fussing with\n\tcharacter arrays.\n\n2010-07-19  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/matrix.txi: Add new function repelems to matrix chapter.\n\n2010-07-18  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/spellcheck,\n\tinterpreter/doccheck/spellcheck/add_to_aspell_dict:\n\tUse case insensitive sort in spellcheck scripts.\n\n2010-07-18  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck/aspell-octave.en.pws: Add Octave-specific words\n\tfrom stats.texi to private Aspell dictionary.\n\n2010-07-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/doccheck: New directory for spelling/grammar scripts.\n\t* interpreter/doccheck/README: Instructions for using scripts.\n\t* interpreter/doccheck/spellcheck: Script to spellcheck a Texinfo file.\n\t* interpreter/doccheck/aspell.conf: GNU Aspell configuration file for\n\tOctave documentation.\n\t* interpreter/doccheck/aspell-octave.en.pws: Private Aspell dictionary.\n\t* interpreter/doccheck/add_to_aspell_dict: Script to add new\n\tOctave-specific words to private Aspell dictionary.\n\t* interpreter/octave.texi: New @nospell macro which forces Aspell to\n\tignore the word marked by the macro.\n\t* interpreter/mk_doc_cache.m: Skip new @nospell macro when\n\tbuilding doc_cache.\n\t* interpreter/arith.txi, interpreter/audio.txi,\n\tinterpreter/bugs.txi, interpreter/contrib.txi,\n\tinterpreter/debug.txi, interpreter/diagperm.txi,\n\tinterpreter/dynamic.txi, interpreter/geometry.txi,\n\tinterpreter/matrix.txi, interpreter/numbers.txi,\n\tinterpreter/oop.txi, interpreter/package.txi,\n\tinterpreter/sparse.txi, interpreter/tips.txi:\n\tSpellcheck documentation.\n\n2010-07-01  Rik  <octave@nomad.inbox5.com>\n\n\t* refcard/refcard.tex: Fix italic macro typo for stem.\n\n2010-06-28  Rik  <octave@nomad.inbox5.com>\n\n\t* refcard/refcard.tex: Fix typos in refcard (bug #30260).\n\n2010-06-16  Rik  <octave@nomad.inbox5.com>\n\n\t* ChangeLog: Correctly break lines > 80 characters.\n\n2010-06-16  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/intro.txi: Clarify wording.  (bug #30165).\n\n2010-06-16  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/set.txi: Remove reference to deprecated function.\n\n2010-06-16  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/expr.txi, interpreter/func.txi, interpreter/install.txi,\n\tinterpreter/plot.txi, interpreter/sparse.txi: Periodic grammar check\n\tof documentation to ensure a common format.\n\n2010-05-27  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/arith.txi, interpreter/diffeq.txi, interpreter/intro.txi,\n\tinterpreter/nonlin.txi, interpreter/poly.txi, interpreter/sparse.txi:\n\tReplace @ifinfo with @ifnottex.\n\n2010-05-07  John W. Eaton  <jwe@octave.org>\n\n\t* basics.txi: Update list of internal variables for --traditional.\n\n2010-05-02  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/contrib.txi, interpreter/install.txi,\n\tinterpreter/plot.txi, interpreter/sparse.txi,\n\tinterpreter/octave.texi: Remove tabs causing problems with\n\tpdf formatting.\n\n2010-04-14  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* interpreter/plot.txi: Document keypress and mouse callback\n\tproperties\n\n2010-04-07  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/testfun.txi: Document runtests.\n\n2010-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/bugs.txi: Update for bug tracker.\n\n2010-02-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/expr.txi: Mention no ternary operator and the ifelse\n\tfucntion as a possible replacement.\n\n2010-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/tips.txi: More tips.\n\n2010-01-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/expr.txi (Assignment): Document return value of\n\tmulti-assignment with skipped values.\n\n2010-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/poly.txi (Derivatives and Integrals):\n\tDon't include docstring for polyinteg.\n\n\t* interpreter/obsolete.txi (Obsolete Functions):\n\tRemove weibcdf, weibinv, weibpdf, and weibrnd from the table.\n\n2010-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/obsolete.txi: New file.\n\t* interpreter/Makefile.am (MUNGED_TEXI_SRC): Add it to the list.\n\t* interpreter/octave.texi (Obsolete Functions): New menu item.\n\tInclude obsolete.texi.\n\n2010-01-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/expr.txi: Document using dummy outputs.\n\t* interpreter/func.txi: Document using dummy inputs.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/munge-texi.cc: Delete Emacs local-variable settings.\n\tUntabify.\n\n2010-01-17  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/container.txi (Creating Cell Arrays): Add\n\tdocstring for cellslices function.\n\n2010-01-09  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/munge-texi.cc: Avoid C-style casts.\n\t(main): Call usage if fewer than two arguments.\n\n2009-12-20  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/geometryimages.m: Correctly set postscript output when\n\tQHULL library does not exist and sombrero image is printed.\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am, faq/Makefile.am, interpreter/Makefile.am,\n\tliboctave/Makefile.am, refcard/Makefile.am, interpreter/images.awk:\n\tEliminate TOPDIR variable in favor of built-in automake variables of\n\ttop_builddir and top_srcdir.\n\n2009-12-17  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: use automake syntax to build munge-texi.\n\n2009-12-11  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: remove install-local target and use automake\n\tsyntax to install doc-cache file.\n\n2009-12-10  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Replace distdir-local with dist-hook rule as\n\tit is better supported by automake.\n\n2009-12-10  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: new distdir-local rule to check for presence\n\tof necessary libraries before packaging distribution\n\n2009-12-08  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Distribute all generated documentation\n\t(.pdf, .ps, .html, .dvi) to remove build requirement for TexInfo\n\n2009-12-07  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am, faq/Makefile.am, liboctave/Makefile.am:\n\tDocument use of NOTPARALLEL directive.\n\n2009-12-07  Rik  <octave@nomad.inbox5.com>\n\n\t* refcard/Makefile.am: Add CLEANFILES and MAINTAINERCLEANFILES objects\n\tto properly clean directory.\n\n2009-12-05  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Set dependency of *.texi files on\n\tmunge-texi source code rather than executable.\n\n2009-12-04  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/images.awk: Revert to using Ghostscript for documentation\n\tpdf image creation rather than Octave.\n\n2009-12-04  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am, interpreter/Makefile.am, liboctave/Makefile.am: remove\n\tlingering configuration support for conf.texi.\n\t* liboctave/Makefile.am: distribute .texi files.\n\n2009-12-04  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/geometryimages.m, interpreter/interpimages.m,\n\tinterpreter/sparseimages.m, interpreter/plotimages.m:\n\tSwitch to color output for PostScript documentation images.\n\n2009-12-04  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/geometryimages.m, interpreter/interpimages.m,\n\tinterpreter/sparseimages.m, interpreter/plotimages.m:\n\tSet default paperorientation to landscape to stop warning message.\n\n2009-12-04  Ben Abbott  <bpabbott@mac.com>\n\n\t* interpreter/geometryimages.m, interpreter/interpimages.m,\n\tinterpreter/sparseimages.m: Set default papersize to the desired\n\timagesize.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/images.awk: Emit rules to copy PNG files to\n\toctave.html directory once it is created.\n\t* interpreter/Makefile.am (all-local): Depend on $(HTMLDIR_IMAGES).\n\t(IMAGES): Include $(HTMLDIR_IMAGES) in the list.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/octave.texi: Include version.texi instead of conf.texi.\n\t* interpreter/Makefile.am (../conf.texi): Delete rule.\n\t(octave_TEXINFOS): Delete ../conf.texi from the list.\n\t($(srcdir)/octave.info octave.dvi octave.pdf octave.html):\n\tRemove duplicate $(octave_TEXINFOS) dependency.\n\tDepend on $(srcdir)/version.texi.\n\n\t* liboctave/liboctave.texi: Include version.texi instead of conf.texi.\n\t* liboctave/Makefile.am (../conf.texi): Delete rule.\n\t(dist_liboctave_TEXINFOS): Delete ../conf.texi from the list.\n\t(.NOTPARALLEL): Correct spelling of target.\n\t($(srcdir)/liboctave.info liboctave.dvi liboctave.html liboctave.pdf):\n\tDepend on $(srcdir)/version.texi\n\n\t* conf.texi.in: Delete.\n\t* Makefile.am: Delete rules for conf.texi.\n\t(.NOTPARALLEL): New target.\n\n2009-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* doc/Makefile.am (MUNGED_TEXI_SRC): Define as explicit list.\n\t(TXI_SRC): Define using substitution rule.\n\n\t* doc/Makefile.am (conf.texi): Only substitute OCTAVE_VERSION.\n\t* conf.texi: Likewise.\n\n\t* doc/interpreter/find-docstring-files.sh: New file.\n\t* doc/interpreter/Makefile.am (DOCSTRING_FILES): Use it.\n\t($(TOPDIR)/src/DOCSTRINGS, $(TOPDIR)/scripts/DOCSTRINGS):\n\tDelete rules.\n\t(.txi.texi): Pass $(top_srcdir) to munge-texi.\n\t(octave.info octave.dvi octave.pdf octave.html):\n\tDepend on $(octave_TEXINFOS), not $(nodist_octave_TEXINFOS).\n\t(nodist_octave_TEXINFOS): Delete variable.\n\t(octave_TEXINFOS): Include ../conf.texi in the list.\n\t(dist-hook): Delete target.\n\t(EXTRA_DIST): Add find-docstring-files.sh to the list.\n\n\t* doc/interpreter/basics.texi: Eliminate @value{OCTAVEHOME}\n\t* doc/interpreter/dynamic.txi: Delete examplefile and\n\tlongexamplefile macro definitions.  Replace uses with\n\t@EXAMPLEFILE, to be expanded by munge-texi.\n\t* doc/interpreter/geometry.txi: Eliminate @ifset HAVE_QHULL.\n\t* doc/interpreter/oop.txi: Delete classfile and polynomialfile\n\tmacro definitions.  Replace uses with @EXAMPLEFILE, to be expanded\n\tby munge-texi.\n\t* doc/interpreter/sparse.txi: Eliminate @ifset HAVE_CHOLMOD,\n\t@ifset HAVE_UMFPACK, and @ifset HAVE_COLAMD.\n\n\t* munge-texi.cc (top_srcdir): New global variable.\n\t(main): set top_srcdir from first arg.\n\t(usage): Include TOP-SRCDIR in the message.\n\t(recover_from_macro, process_example_file): New functions.\n\t(process_texi_input_file): Handle @EXAMPLEFILE tag.\n\n\t* doc/liboctave/Makefile.am (nodist_liboctave_TEXINFOS):\n\tDelete variable.\n\t(liboctave_TEXINFOS): Include ../conf.texi in the list.\n\n2009-12-02  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am: Correct Makefile.am to allow VPATH builds of\n\tdocumentation\n\n2009-12-01  Rik  <octave@nomad.inbox5.com>\n\n\t* faq/Makefile.am, doc/interpreter/bugs.txi,\n\tdoc/interpreter/install.txi: Eliminate false dependency on conf.texi.\n\n2009-11-30  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am:\n\tOverhaul Makefile to correctly generate *.texi files and to stop their\n\tdistribution when running 'make dist'\n\n2009-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/munge-texi.cc (process_texi_input_file): Double @ in\n\tsymbol_name used in @anchor.\n\t(extract_docstring): Double @ in function name used in @ref.\n\n\t* interpreter/mk_doc_cache.m (cmd): Transform @ in class names to\n\t@@ when processing DOCSTRINGS files.\n\n2009-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.a (nodist_octave_TEXINFOS): Add\n\tcontributors.texi and $(MUNGED_TEXI_SRC) to the list.\n\t(dist_octave_TEXINFOS): Delete.\n\t(DISTCLEANFILES, all_octave_TEXINFOS): New variables.\n\t($(srcdir)/octave.info, octave.dvi, octave.pdf,\toctave.html):\n\tDepend on $(all_octave_TEXINFOS), not $(octave_TEXINFOS).\n\t(octave.ps): Depend on .dvi file and EPS files, but not .texi\n\tsource files.\n\n2009-11-27  David Bateman  <dbateman@free.fr>\n\n\t* doc/interpreter/contributors.in: Add Kacper Kowalik.\n\n2009-11-27  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/install.txi: Document that curl libraries impact ftp\n\tobjects.\n\t* interpreter/system.txi: Document the ftp objects\n\n2009-11-25  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am:\n\tSimplify doc-cache handling in Makefile.am to use only\n\tinstall-data-local target\n\n2009-11-24  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.am:\n\tCorrect Makefile so that it halts on error when unable to build\n\tdoc-cache.\n\n2009-11-23  Rik  <octave@nomad.inbox5.com>\n\n\t* faq/Makefile.am, interpreter/Makefile.am, liboctave/Makefile.am:\n\tStop distribution of conf.texi by autotools.  conf.texi must be re-made\n\tfrom conf.texi.in during configure step\n\n2009-11-23  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Add . to SUBDIRS to force automake to compile this\n\tdirectory, and make conf.texi, before recursively compiling SUBDIRS\n\twhich depend on conf.texi\n\n2009-11-11  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Add DISTCLEANFILES macro so that generated conf.texi can\n\tbe cleaned by automake.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am, faq/Makefile.am, interpreter/Makefile.am,\n\tliboctave/Makefile.am, refcard/Makefile.am,\n\tinterpreter/config-images.sh, interpreter/images,\n\tinterpreter/images.awk: New files.\n\t* Makefile.in, faq/Makefile.in, interpreter/Makefile.in,\n\tliboctave/Makefile.in, refcard/Makefile.in: Delete.\n\t* interpreter/munge-texi.cc (main, usage): Eliminate unnecessary\n\t-d option.\n\t* liboctave/liboctave.texi: Surround @direntry in appropriate magic.\n\t* faq/OctaveFAQ.texi: Rename from faq/Octave-FAQ.texi.\n\n2009-10-23  Rik  <octave@nomad.inbox5.com>\n\n\t* various: Periodic grammar check of Octave documentation files to\n\tensure a standardized format.\n\n2009-10-20  Rik  <octave@nomad.inbox5.com>\n\n\t* interpreter/Makefile.in: Clean Makefile.in and remove a few\n\tnon-functional targets\n\n2009-10-13  Rik  <octave@nomad.inbox5.com>\n\n\t* various: Fix various incorrect usages of deffn and deftypefn macros\n\n2009-10-12  Rik  <octave@nomad.inbox5.com>\n\n\t* liboctave/Makefile.in: Simplify Makefile using GNU Make functions\n\t* liboctave/liboctave.texi: Stop header of file, which was meant to be\n\tcommented, from being transferred into the documentation.\n\n2009-10-12  Rik  <octave@nomad.inbox5.com>\n\n\t* faq/Makefile.in: Clean a few non-functional commands from Makefile\n\n2009-10-12  Rik  <octave@nomad.inbox5.com>\n\n\t* refcard/Makefile.in: Simplify Makefile using GNU Make functions\n\n2009-10-11  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.in: Include texmf.cnf in distributed files to fix texinfo\n\truntime error with stack overflow.\n\n2009-10-11  Rik  <octave@nomad.inbox5.com>\n\n\t* intepreter/Makefile.in: Fix broken command to create octave.dvi\n\n2009-10-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* intepreter/linalg.txi: Add reference to luupdate.\n\n2009-10-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/io.txi: Add reference to fskipl.\n\n2009-09-30  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/data.txi (Built-in Data Types):\n\tDocument bitpack and bitunpack.\n\t* interpreter/plot.txi: Delete spurious {}.  Update menus.  Fix\n\tcross-referencing.\n\t* interpreter/octave.texi: Update plotting sub-menus in detailed menu.\n\n2009-09-30  Michael D. Godfrey  <godfrey@isl.stanford.edu>\n\n\t* interpreter/plot.txi: Document graphics structures.\n\n2009-09-14  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/optim.txi: Document pqpnonneg.\n\n2009-08-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/expr.txi: Mention complex comparisons change.\n\n2009-08-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/tips.txi: Update.\n\n2009-07-20  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/contributors.in: Add Aleksej Saushev.\n\n2009-06-24  Rafael Laboissiere  <rafael@debian.org>\n\n\t* Makefile.in (dist): Drop conf.texi as prerequisite.\n\n2009-06-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/tips.txi: Update.\n\n2009-06-07  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/plot.txi: Update some of Advanced Plotting documentation.\n\tUpdated functions delete, allchild, backend, clf, hold, and refreshdata.\n\n2009-06-07  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/container.txi: Udate documentation of container types\n\n2009-06-03  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/plotimages.m: Correct errorbar plot for docs.  Make hist\n\tplot reprodroducible for docs.\n\t* interpreter/interpimages.m: Correct typo in legend of interpft plot\n\tfor docs.\n\n2009-06-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Makefile.in: Omit conf.texi in DISTFILES.\n\n2009-06-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/oop.txi: Update docs of polynomial class, mention\n\tchained indexing.\n\n2009-05-27  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/errors.txi: fix 'print_usage' output.\n\n2009-05-27  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/bugs.txi: fix call to 'page_screen_output'.\n\n2009-05-25  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/Makefile.in: Add texmf.cnf to list of distributed files\n\t(DIST_FILES) so that pdfs will build.\n\n2009-05-24  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* interpreter/oop.txi: Added inheritance documentatin\n\n2009-05-21  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/Makefile.in, texmf.cnf: Change texi2pdf call to include\n\tlocal TeX configuration file which increases save_history variable.\n\n2009-05-17  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/tips.txi: Change recommendation to use @tex rather than\n\t@iftex construction.\n\n2009-05-17  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/*.txi: Simplify TeXinfo files by eliminating redundant\n\t@iftex followed by @tex construction.  Also, spellchecked all .txi\n\tand .texi files.\n\n2009-05-14  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/arith.txi: Update section 17.8 (Mathematical Consants)\n\tof arith.txi.\n\n2009-05-01  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/arith.txi: Update section 17.7 (Coordinate\n\tTransformations) of arith.txi.\n\n2009-05-01  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/arith.txi: Simplify TeXinfo and eliminate use of\n\t@iftex in arith.txi.\n\n2009-05-01  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/arith.txi: Update section 17.5 (Utility Functions)\n\tof arith.txi.\n\n2009-04-30  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/arith.txi: Update section 17.4 (Sums and Products)\n\tof arith.txi.\n\n2009-04-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/numbers.txi: Update info on ranges.\n\t* interpreter/expr.txi: Update some info on indexing.\n\n2009-04-26  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/arith.txi: Update section 17.3 (Trigonometry) of\n\tarith.txi.\n\n2009-04-24  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/arith.txi: Update section 17.2 (Complex Arithmetic)\n\tof arith.txi.  Use Tex in more of the doc strings for pretty\n\tprinting in pdf format.\n\n2009-04-24  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/octave.pdf: Eliminate most overfull errors when\n\trunning texi2pdf for generating pdf documentation.  Use\n\t@smallexample when necessary to reduce font for long lines.\n\tReword variables or phrases so that Tex can break them at a better\n\tspot.\n\n2009-04-21  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/octave.pdf: Eliminate 'unbalanced parentheses in\n\t@def...' error during texi2pdf.  Fixed four .m files incorrectly\n\tusing @deftypefn macro.\n\n2009-04-19  Ansgar Burchardt  <ansgar@43-1.org>\n\n\t* interpreter/numbers.txi: Fix small mistake in example.\n\n2009-04-17  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/arith.txi: Update section 17.1 (Utility Functions)\n\tof arith.txi.  Split section into \"Exponents and Logarithms\" and\n\t\"Utility Functions\" Use Tex in many more of the doc strings for\n\tpretty printing in pdf format.\n\n2009-04-17  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/basics.txi: Update help text for sections 2.5, 2.6, 2.7\n\tof basics.txi\n\n2009-04-17  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/basics.txi: Update help text for sections 2.4 of\n\tbasics.txi.\n\n2009-04-17  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/basics.txi: Update help text for sections 2.2\n\tand 2.3 of basics.txi.\n\n2009-04-17  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/basics.txi: Update help strings for command line options.\n\n2009-04-11  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/contributors.in: Add Martin Helm.\n\n2009-04-06  John W. Eaton  <jwe@octave.org>\n\n\t* texinfo.tex: Prefer PDF image files if generating PDF output.\n\n2009-03-27  Rik  <rdrider0-list@yahoo.com>\n\n\t* interpreter/intro.txi: Add new sample section on elementary\n\tcalculations.  Add new example of solving systems of equations\n\n2009-03-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/diagperm.txi: Mention mixing with sparse matrices.\n\n2009-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/munge-texi.cc (process_texi_input_file):\n\tCopy leading comment with file name info to output.\n\n2009-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (DISTFILES): Use doc-cache instead of\n\tDOC for doc cache file.\n\n2009-03-08  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/stats.txi (Basic Statistical Functions):\n\tAdd the 'histc' function.\n\n2009-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/basics.txi (Command Line Options):\n\tDocument --doc-cache-file command-line option.\n\n2009-03-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/diagperm.txi: Various improvements.\n\n2009-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/set.txi (Sets): Don't document create_set.\n\n2009-02-26  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/strings.txi (Manipulating Strings):\n\tDocument strsplit, not split.\n\n2009-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (distclean): Remove tags and TAGS here\n\tinstead of in maintainer-clean target.\n\t(maintainer-clean): Depend on distclean, not clean.  Remove DOC.\n\t(DISTFILES): Add stmp-html to the list.\n\n\t* Makefile.in: Remove conf.texi in maintainer-clean target but not\n\tdistclean target.\n\n2009-02-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/diagperm.txi: Remove redundant url references.\n\n2009-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/diagperm.txi: Use TeX alternatives in some\n\tformulas, improve examples, delete superfluous defs.\n\n2009-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/diagperm.txi: New file.\n\t* interpreter/octave.texi: Reference it.\n\t* intepreter/Makefile.in: Include it.\n\t* interpreter/matrix.txi: Move @DOCSTRING(diag) to diagperm.txi.\n\n2009-02-19  John W. Eaton  <jwe@octave.org>\n\n\t* doc/interperter: Include @DOCSTRING commands for the following\n\tfunctions: bicgstab, cgs, choldelete, cholinsert, cholshift,\n\tclabel, comet, command_line_path, compass, contour3, ctranspose,\n\tcylinder, dellistener, diffuse, edit, ellipsoid, fclear, feather,\n\tfill, find_dir_in_path, finite, flag, info, is_absolute_filename,\n\tis_rooted_relative_filename, isdebugmode, ishghandle, isnull,\n\tissorted, make_absolute_filename, meshz, news,\n\toctave_tmp_file_name, optimget, pareto, plotmatrix, plotyy,\n\tqrshift, quiver3, re_read_readline_init_file, ribbon, rose,\n\trundemos, scatter, scatter3, slice, specular, sphere, spinmap,\n\tstem3, strchr, strtrim, surfl, surfnorm, times, transpose,\n\ttreelayout, uminus, uplus, warranty, what, xlim, yes_or_no.\n\n2009-02-17  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* interpreter/install.txi: Add documentation for configure options\n\t\"--without-framework-carbon\" and \"--without-framework-opengl\".\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/arith.txi: Add reference to \"cummin\" and \"cummax\".\n\n2009-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (uninstall): Use $(DESTDIR) here too.\n\tUninstall Info dir file.  Uninstall DOC file.\n\t(install): Install DOC file.  Add $(DESTDIR)$(octetcdir) to the\n\tlist of directories to make.\n\n2009-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (DOC): New target.\n\t(DISTFILES): Add DOC nad mk_doc_cache.m to the list.\n\t* mk_doc_cache.m: New file.\n\n2009-02-01  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/nonlin.txi: Remove reference to 'fsolve_options'.\n\n2009-02-01  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/system.txi: Remove reference to 'eomdate'.\n\n2009-01-24  Thorsten Meyer  <thorsten@hexe>\n\n\t* interpreter/container.txi (Data Structures): Update examples for\n\tstructure arrays.\n\n2009-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/io.txi (Terminal Output): Remove @DOCSTRING(ans).\n\n\t* vr-idx.txi: Delete.\n\t* interpreter/Makefile.in (SUB_SOURCE): Remove it from the list.\n\n2009-01-22  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/func.txi: Put varargin and varargout in concept index.\n\t* interpreter/var.txi: Put ans in concept index.\n\t* interpreter/octave.texi: Don't include vr-idx.texi.\n\n\t* interpreter/var.txi: Remove sections on built-in variables.\n\n2009-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/system.txi (Filesystem Utilities): @DOCSTRING for\n\tfstat.  Delete @DOCSTRING for lstat.  Add anchor for doc-lstat.\n\n2009-01-18  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/numbers.txi (Numeric Data Types): Trivial fixes.\n\n2009-01-14  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/matrix.txi: Add anchor for doc-postpad.\n\n2008-12-26  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/strings.txi: Add space to ischar example.\n\n2008-12-26  Francesco Potortì  <pot@gnu.org>\n\n\t* interpreter/matrix.txi (Rearranging Matrices): Add reference\n\tto resize function.\n\n\t* interpreter/plot.txi (Plot Annotations): Add cross reference to\n\tText Properties.\n\t(Two-Dimensional Plots): Update introduction to the axis function.\n\n       * interpreter/signal.txi (Signal Processing): Add explanation of\n       what wisdom is.\n\n2008-12-23  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Document the eigs and svds functions.\n\n2008-12-02  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/container.txi, interpreter/strings.txi:\n\tRemove reference to str2mat.m\n\n2008-11-15  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/strings.txi: Add text around docstrings, change\n\tstructure of the strings chapter.\n\n2008-10-31  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in ($(TEXINFO)): Depend directly on\n\t../../src/DOCSTRINGS and ../../scripts/DOCSTRINGS instead of phony\n\tsrc-DOCSTRINGS and scripts-DOCSTRINGS targets.\n\t(src-DOCSTRINGS, scripts-DOCSTRINGS): Delete.\n\t(DOCSTRING_FILES): New variable.\n\t($(SUB_TEXFINO)): Use it.  Display actual command.\n\t($(DOCSTRING_FILES)): New target.\n\t(%.spell : %.texi): Use -t suffix instead of .tmp.\n\t(constributors.texi, $(SUB_TEXINFO)): Use mv, instead of\n\t$(simple-move-if-change-rule).\n\n2008-10-30  David Bateman  <dbateman@free.fr>\n\n\t* faq/Octave-FAQ.texi: Document improved indexing and add an faq for\n\tthe compatibility of mldivide/mrdivide for singualr, under- and\n\tover-determined matrices.\n\n\t* interpreter/plot.txi: Document contour groups.\n\n2008-10-29  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/system.txi, interpreter/poly.txi,\n\tinterpreter/arith.txi, interpreter/poly.txi,\n\tinterpreter/optim.txi, interpreter/diffeq.txi,\n\tinterpreter/sparse.txi, interpreter/matrix.txi,\n\tinterpreter/plot.txi, interpreter/io.txi, interpreter/debug.txi,\n\tinterpreter/var.txi, interpreter/strings.txi:\n\tAdd missing @DOCSTRING commands.\n\n\t* interpreter/munge-texi.cc (extract_docstring): Expand arguments\n\tof @seealso{} into Texinfo references.\n\n2008-10-22  David Bateman  <dbateman@free.fr>\n\n\t* interprter/plot.txi: Add documentation for error bar series.\n\n\t* interprter/plot.txi: Update documentation for line series, Add\n\tdocumetation for scatter groups, stem series and surface groups.\n\n\t* texinfo.tex: Import new upstream version.\n\t* interpreter/Makefile.in (EXAMPLE_FILES_NODIR): Update for new OOP\n\tclass example location.\n\t* interpreter/oop.txi: Ditto.\n\n2008-10-15  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/oop.txi: New file.\n\t* interpreter/Makefile.in (SUB_SOURCES): Add it here.\n\t(POLYNOMIAL_FILES_NODIR): New variable for polynomial example class\n\tmethods.\n\t(EXAMPLE_FILES_NODIR): Add POLYNOMIAL_FILES_NODIR here.\n\t* interpreter/octave.texi: Reference new OOP chapter here.\n\t* interpreter/func.txi: Document private directories and function\n\tprecedence here.\n\n2008-10-16  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/contrib.txi: added recommendation of limited\n\tline width in code examples\n\n2008-10-03  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/contrib.txi: added example for mercurial queues\n\n08-10-03  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* interpreter/contrib.txi: correction of the mercurial example\n\t* interpreter/container.txi: minor correction of the text\n\n2008-09-25  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/image.txi: Update for imread and imwrite instead of\n\tloadimge and saveimage.\n\n2008-09-24  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/image.txi: Document imfinfo.\n\n2008-09-23  Francesco Potorti`  <Potorti@isti.cnr.it>.\n\n\t* interpreter/container.txi: Fix cross reference in struct docs.\n\n2008-09-23  Brian Gough  <bjg@network-theory.co.uk>\n\n\t* interpreter/matrix.txi: Update docs for random number generators.\n\n2008-09-22  David Bateman  <dbateman@free.fr>\n\n\t* faq/Octave-FAQ.texi: Update for Octave 3.1.51 and Matlab 2008a.\n\n2008-09-15  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Minor clarificiation\n\n2008-08-28  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/func.txi, interpreter/plot.txi: Doc fixes\n\tsuggested by Francesco Potorti` <Potorti@isti.cnr.it>.\n\n2008-08-28  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/plot.txi: Add description of data sources and line\n\tseries objects.\n\n2008-08-26  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/plot.txi: Document the group objects (bar, stem,\n\tstair, quiver and area series), and cllback functions.\n\n2008-08-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* interpreter/contrib.txi: New file.\n\t* interpreter/octave.texi: Include it here.\n\t* interpreter/Makefile.in (SUB_SOURCE): Add contrib.txi to the list.\n\n2008-08-21  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/plot.txi: Document ezplot.\n\n2008-08-19  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/numbers.txi: Document intwarning.\n\n2008-08-06  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/basics.txi, interpreter/errors.txi,\n\tinterpreter/expr.txi, interpreter/func.txi,\n\tinterpreter/numbers.txi: Update format of error messages in examples.\n\n2008-07-29  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/numbers.txi, interpreter/plot.txi,\n\tinterpreter/quad.txi: Miscellaneous documentation fixes.\n\n\t* control.txi, finance.txi, quaternion.txi: Delete.\n\t* octave.texi: Remove all references to the above.\n\t* Makefile.in: ditto.\n\n2008-07-28  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/arith.txi: Document reallog, realpow and realsqrt.\n\t* interpreter/dbug.txi: Document the means of setting a breakpoint\n\tin a sub-function\n\t* interpreter/func.txi: Document nargoutchk and symvar.\n\t* interpreter/geometry.txi: Document rectint.\n\t* interpreter/image.txi: Document contrast.\n\t* interpreter/interp.txi: Document interp1q.\n\t* interpreter/linalg.txi: Document planerot, rcond and subspace.\n\t* interpreter/numbers.txi: Document data type demotion and single\n\tprecision data type.\n\t* interpreter/plot.txi: Document ginput, gtext,\n\twaitforbuttonpress, ezcontour, ezcontourf, ezpolar, ezplot3,\n\tezmesh, ezmeshc, ezsurf, ezsurfc, allchild, findobj and findall\n\tfunctions.\n\t* interpreter/quad.txi: Document quadv, quadgk, dblquad and\n\ttriplequad functions.\n\t* interpreter/strings.txi: Document validstring, regexptranslate\n\tand isstrprop functions.\n\t* interpreter/system.txi: Document addtodate, filemarker and perl\n\tfunctions.\n\t* interpreter/var.txi: Document the genvarname and namelengthmax\n\tfunctions.\n\t* interpreter/octave.texi: Update table of contents for the above\n\tchanges.\n\n\t* interpreter/plot.txi: Document contourf.\n\n\t* interpreter/plot.txi: Clarify the description of OuterPosition\n\taxes property.\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/debug.txi: Uodate documentation for multiline\n\tinput. Add documentation for dbcont, dbquit, dbstep, dbstqck, dbup\n\tand dbdown functions.\n\t* interpreter/octave.texi: Upodate index for debugging functions.\n\n2008-05-03  Rafael Laboissiere  <rafael@debian.org>\n\n\t* interpreter/expr.txi, interpreter/tips.txi: Use ischar instead of\n\tdeprecated isstr.\n\n2008-04-02  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Document spaugment.\n\n2008-03-26  Rafael Laboissiere  <rafael@debian.org>\n\n\t* interpreter/mkoctfile.1: Remove spurious whitespace before macros\n\n2008-03-25  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/strings.txi: Document hex2num, num2hex.\n\n2008-03-21  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Document amd function.\n\n2008-03-19  Michael D. Godfrey  <godfrey@isl.stanford.edu>\n\n\t* interpreter/plot.txi: Reorder symbol character table.\n\n2008-03-18  Rafael Laboissiere  <rafael@debian.org>\n\n\t* interpreter/octave.1, interpreter/mkoctfile.1:\n\tEscape \"-\" signs that mean the \"minus\" character.\n\n2008-03-12  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/io.txi: Document dlmread, dlmwrite, csvread and\n\tcsvwrite.\n\n2008-02-25  Ben Abbott  <bpabbott@mac.com>\n\n\t* interpreter/geometryimages.m, interpreter/interpimages.m,\n\tinterpreter/plotimages.m, interpreter/sparseimages.m:\n\tUse cstrcat instead of strcat.\n\n2008-02-22  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Remove refernces to spdiag, spcumprod,\n\tspcumsum, spprod, spsum, spsumsq, spchol, spchol2inv, spcholinv,\n\tspinv and splu.\n\n2008-02-20  David Bateman  <dbateman@free.fr>\n\n \t* interpreter/sparse.txi: Remove references to spmin, spmax,\n \tspatan2, spfind, spqr and spdet.\n\n2008-02-19  Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* interpreter/package.txi: Improve INDEX file documentation.\n\n2008-01-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* interpreter/intro.txi: Replaced reference to deprecated\n\tfunction struct_elements with filenames.\n\n2008-02-08  Rafael Laboissiere  <rafael@debian.org>\n\n\t* interpreter/octave.1: Dropped unknown LO macro\n\t* interpreter/octave-bug.1: Likewise\n\n2008-02-07  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Remove references to spkron.\n\n2008-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (stmp-html, HTML): New targets.\n\t($(HTML_IMAGES_PNG)): Also depend on stmp-html.\n\tDon't create HTML directory here.\n\n2007-12-28  John W. Eaton  <jwe@octave.org>\n\n\tMerge changes from object branch:\n\n\t2007-06-20  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/var.txi, interpreter/io.txi:\n\tEliminate print_answer_id_name.\n\n2007-12-21  John W. Eaton  <jwe@octave.org>\n\n\tVersion 3.0.0 released.\n\n2007-12-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (conf.texi): Also depend on $(top_srcdir)/src/version.h.\n\n2007-12-05  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/geometryimages.m (image_as_txt): New function.\n\tUse it to generate \"figures\" for Info format.\n\t* interpreter/interpimages.m: Likewise.\n\t* interpreter/sparseimages.m: Likewise.\n\n2007-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/sparseimages.m, interpreter/plotimages.m,\n\tinterpreter/interpimages.m, interpreter/geometryimages.m:\n\tSet default text font to \"*\" for png images.\n\n\t* interpreter/Makefile.in (run-octave): Don't sleep.\n\n2007-12-04  Joseph P. Skudlarek  <Jskud@Jskud.com>\n\n\t* interpreter/plotimages.m: Generate text plots.\n\t* interpreter/sparseimages.m: Add initial blank line to text plots.\n\n\t* interpreter/Makefile.in (IMAGES_TXT): Include $(INTERPIMAGES_TXT)\n\t$(GEOMETRYIMAGES_TXT) and $(PLOTIMAGES_TXT) in the list.\n\t(INTERPIMAGES_TXT, GEOMETRYIMAGES_TXT, PLOTIMAGES_TXT): New variables.\n\n2007-11-26  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Document condest.\n\t* interpreter/plot.txi: Document the new text properties and the\n\tTeX interpreter mode of text objects.\n\t* interpreter/plotimages.m: Add an example for the TeX\n\tinterpreter.\n\t* interpreter/Makefile.in (PLOTIMAGES): Add the TeX example\n\n\t* interpreter/plot.txi: Document caxis.\n\t* interpreter/image.txi: Document gmap40.\n\n2007-11-12  Joseph P. Skudlarek  <Jskud@Jskud.com>\n\n\t* interpreter/gpl.txi: Move index commands after sectioning commands.\n\n2007-11-09  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/plot.txi: Document the new hidden and area functions.\n\n2007-11-07  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/plot.txi: Document new functions.\n\n2007-10-30  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/dynamic.txi, interpreter/install.txi,\n\tinterpreter/stats.txi, interpreter/strings.txi,\n\tinterpreter/testfun.txi, interpreter/tips.txi:\n\tDoc fixes for small book format.\n\n2007-10-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* interpreter/Makefile.in, faq/Makefile.in, liboctave/Makefile.in:\n\tUse temporary renamed files instead of Don't use --output option\n\targument for texi2[dvi|pdf].  Use $(sepchar) for path element\n\tseparation when building TEXINPUTS.  Remove use of UNSETCOMSPEC trick.\n\n2007-10-22  Kim Hansen  <kimhanse@gmail.com>\n\n\t* interpreter/munge-texi.cc: Include <cstdlib> and <cstring>.\n\n2007-10-19  David Bateman  <dbateman@free.fr>\n\n\t* refcard/refcard.tex: Update for 3.0.\n\n2007-10-15  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/preface.txi, interpreter/basics.txi,\n\tinterpreter/strings.txi, interpreter/container.txi,\n\tinterpreter/var.txi, interpreter/expr.txi, interpreter/errors.txi,\n\tinterpreter/io.txi, interpreter/func.txi, interpreter/package.txi:\n\tMake text fit on pages when using smallbook.\n\n2007-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* Change copyright notices in all files that are part of Octave to\n\tGPLv3 or any later version.\n\n2007-10-11  Brian Gough  <bjg@network-theory.co.uk>\n\n\t* interpreter/dynamic.txi, interpreter/geometry.txi,\n\tinterpreter/package.txi, interpreter/sparse.txi,\n\tinterpreter/system.txi: Spelling fixes.\n\n2007-10-10  Olli Saarela  <Olli.Saarela@kcl.fi>\n\n\t* interpreter/arith.txi, interpreter/basics.txi,\n\tinterpreter/container.txi, interpreter/dynamic.txi,\n\tinterpreter/eval.txi, interpreter/expr.txi, interpreter/func.txi,\n\tinterpreter/geometry.txi, interpreter/intro.txi,\n\tinterpreter/numbers.txi, interpreter/plot.txi,\n\tinterpreter/poly.txi, interpreter/set.txi, interpreter/sparse.txi,\n\tinterpreter/stmt.txi, interpreter/strings.txi,\n\tinterpreter/testfun.txi, interpreter/tips.txi: Spelling fixes.\n\n2007-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/octave.texi: Add David Bateman and Søren Hauberg as\n\tauthors.\n\n2006-09-28  Henry Mollet  mollet@pacbell.net\n\n\t* interpreter/func.txi: Correct results of a couple of examples.\n\n2007-09-14  John W. Eaton  <jwe@octave.org>\n\n\t* faq/Makefile.in: Create single Octave-FAQ.html file instead of a\n\tsplitting files into HTML directory.\n\n2007-09-05  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/system.m: Document gzip.\n\t* interpreter/container.txi: Document celldisp.\n\t* interpreter/matrix.txi: Document bsxfun.\n\t* interpreter/data.txi: Document typecast and swapbytes.\n\t* interpreter/container.txi: Document struct2cell.\n\t* interpreter/stats.txi: Document mode.\n\t* interpreter/eval.txi: Document run.\n\n2007-09-01  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/Makefile.in: Remove stray character from\n\tINTERIMAGES_PNG target.\n\t* conf.texi.in: Substitute for the variable TEXINFO_QHULL\n\t* interpreter/geometryimages.m: Check for the HAVE_QHULL build\n\tflag before creating certain figures.\n\t* interpreter/geometry.txi: Check whether TEXINFO_QHULL is set\n\tbefore including certain figures.\n\n2007-08-31  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/nonlin.txi: Extended the example.\n\n\t* interpreter/poly.txi: Sectioning and documentation.\n\t* interpreter/octave.texi: Adapt to changes in poly.txi.\n\n2007-08-30  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/geometryimages.m: Add inpolygon example\n\t* interpreter/Makefile.in (GEOMETRYIMAGES): Add inpolygon example.\n\t* interpret/geometry.txi: Document inpolygon.\n\n2007-08-27  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/struct.txi: Remove.\n\t* interpreter/containers.txi: Combine with this chapter. Add\n\texamples, and section on comma separated lists. Document the\n\tdifference between \"c(1,:) = []\" and c{1,:} = []\" for a cell\n\tarrays.\n\t* interpreter/octave.texi: Document new indexing of containers\n\tsection.\n\n2007-08-25  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/geometry.txi: Add examples and explanatory text.\n\t* interpreter/octave.texi: Update indexing of geometry functions.\n\t* interpreter/geometryimage.m: New script to create images for\n\tgeometry chapter.\n\t* interpreter/Makefile.in (SCRIPT_SORCES): add geometryimages.m\n\t(GEOMETRYIMAGES*): New variables.\n\t(IMAGES_EPS, IMAGES_PDF, IMAGES_PNG): Add the GEOMETRYIMAGES*.\n\n2007-08-24  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/geometry.txi: Document new functions.\n\t* interpreter/octave.texi: Update indexing of geometry items.\n\n2007-07-25  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (run-octave): Don't set DISPLAY.\n\n2007-07-25  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in, faq/Makefile.in, interpreter/Makwfile.in,\n\tliboctave/Makefile.in, refcard/Makefile.in:  Adjust DISTFILES\n\tto allow out of tree \"make dist\" to work.\n\n2007-07-23  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/Makefile.in (SUB_SOURCE): remove bit.txi.\n\t* interpreter/io.txi: Document rat and rats in new sub-section.\n\t* interpreter/plot.txi: New section for test functions. Document\n\tpeaks and meshc.\n\t* interpreter/octave.texi: Add test plotting section.\n\t* interpreter/image.txi: Document the functions autumn, bone,\n\tcool, copper, hot, hsv, jet, pink, prism, rainbow, spring,\n\tsummer, white and winter.\n\n2007-07-19  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/bit.xi: Remove.\n\t* interpreter/numbers.txi: Move here, and add examples.\n\t* interpreter/octave.texi: Remove \"Bit manipulation\" chapter and make\n\tit a sub-section of the \"Numeric Data Types\" chapter.\n\n2007-07-06  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/arith.txi: Add accumarray.\n\n2007-06-25  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/stats.txi: Reorganize sections and add introductory text.\n\n\t* interpreter/octave.texi: Update to reflect changes in stats.txi.\n\n2007-06-18  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/interpimages.m: Simpler images to demonstrate\n\tthe continuity of the second derivative of splines.\n\t* interpreter/interp.txi: Also change figures here.\n\t* interpreter/Makefile.in: and here.\n\n2007-06-18  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/optim.txi: Added some introductory text to each\n\tsection.\n\n\t* interpreter/set.txi: Added some introductory text.\n\t* interpreter/octave.texi: Updated to reflect changes in set.txi.\n\n2007-06-15  David Bateman  <dbateman@free.fr>\n\n\t* faq/Octave-FAQ.texi: Document the gnuplot 4.2 bug using pipes.\n\n2007-06-15  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* interpreter/testfun.txi: Provide a clue to using xtest for assert.\n\n2007-06-14  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* interpreter/testfun.txi: Document xtest block\n\n2007-06-14  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/Makefile.in (SCRIPT_SORCES): add interimages.m\n\t(INTERPIMAGES*): New variables. Add targets for them\n\t(IMAGES_EPS, IMAGES_PDF, IMAGES_PNG): Add the INTERPIMAGES.\n\t* interpreter/interpimages.m: New function\n\t* interpreter/interp.txi: Add text about second derivation of\n\tsplines\tand add figures.\n\n2007-06-12  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/numbers.txi: Document that 64-bit arithmetic is\n\tnot possible.\n\n2007-06-12  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/interp.txi: Split into two section and document\n\tinterp3 and the differences in the treatement of the dimensions\n\tbetween interpn and interp3.\n\t* hashing.txi: Remove.\n\t* system.txi: Move it here as a subsection. Include explanation\n\tand example.\n\t* interpreter/octave.texi: Add sections for the Interpolation\n\tchapter. Remove references to Hashing chapter and hashing.texi,\n\tand subsections for hashing to system utilities chapter.\n\n2007-06-12  2007-06-10  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/diffeq.txi: Note that x-dot is the derivative of x.\n\n2007-06-03  David Bateman  <dbatemna@free.fr>\n\n\t* interpreter/dynamic.txi: Use \"mwSize\" and \"mwIndex\" rather than\n\t\"int\" for indexing in mex-files and document them.\n\n2007-05-30  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (TEXI2DVICOMMAND, TEXI2PDFCOMMAND):\n\tNew macros.\n\t(octave-a4.pdf, octave-smallbook.pdf): New targets.\n\t(FORMATTED, all): Include octave-a4.pdf in list of dependencies.\n\tDelete octave.dvi and octave.ps from list.\n\t(FORMATTED, all): Use $(PDF_TARGETS).\n\t(maintainer-clean): Depend on clean.\n\n2007-05-30  G. D. McBain  <gdmcbain@freeshell.org>\n\n\t* interpreter/expr.txi (Assignment Ops): Doc fix.\n\n2007-05-29  Steven Mestdagh  <steven.mestdagh@esat.kuleuven.be>\n\n\t* interpreter/Makefile.in ($(HTML_IMAGES_PNG)): Use cp instead of\n\tINSTALL_DATA to copy files to the HTML directory.\n\n2007-05-28  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/errors.txi: Add new sections and some more detailed\n\tdescriptions on errors and warnings.\n\t* interpreter/octave.texi, interpreter/stmt.txi,\n\tinterpreter/var.txi: Add references to the new sections in\n\terrors.txi.\n\n2007-05-28  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/io.txi: Rearrange some sections, and add\n\ta few examples.\n\n2007-05-28  G. D. McBain  <geordie_mcbain@yahoo.com.au>\n\n\t* interpreter/struct.txi: Doc fix.\n\n2007-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* liboctave/Makefile.in (TEXINFO_SOURCE): New variable.\n\t(TEXINFO): Define using $(TEXINFO_SOURCE).\n\t(DISTFILES): Include $(TEXINFO_SOURCE) in the list, not $(TEXINFO).\n\n2007-05-22  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (TEXINFO_SOURCE): New variable.\n\t(TEXINFO): Define using $(TEXINFO_SOURCE).\n\t(DISTFILES): Include $(TEXINFO_SOURCE) in the list, not $(TEXINFO).\n\n2007-05-22  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* faq/Octave-FAQ.texi, interpreter/basics.txi,\n\trefcard/refcard.tex: Fix typos.\n\n2007-05-22  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (DISTFILES): Add mkcontrib.awk to the list.\n\n2007-05-21  David Bateman  <dbatemna@free.fr>\n\n\t* interpreter/debug.txi, io.txi, octave.txi: Doc fixes.\n\n2007-05-21  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/expr.txi: Describe +=, -=, *=, and /= operators.\n\tAdd new example.\n\n\t* interpreter/eval.txi: Partition the chapter into sections.\n\tDescribe evalin and assignin functions using text from Paul\n\tKienzle.  Change \"See See\" to \"See\".  Use @ref instead of @xref to\n\tavoid \"See\" to be written with a capital letter in the middle of a\n\tsentence.\n\n\t* interpreter/func.txi: New section describing load path.\n\tImprove 'inline' and 'command' sections.\n\n\t* interpreter/stmt.txi: Describe cell array cases for the switch\n\tstatement.  Minor layout changes.\n\n2007-05-19  David Bateman  <dbatemna@free.fr>\n\n\t* interpreter/func.txi: Additional documentation for function\n\tlocking, dispatch and autoloading.\n\n2007-05-16  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/expr.txi: Improve docs.\n\n2007-05-14  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/basics.txi, interpreter/data.txi,\n\tinterpreter/intro.txi, interpreter/numbers.txi,\n\tinterpreter/octave.texi, interpreter/preface.txi: Doc fixes.\n\n2007-04-18  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/package.texi: Document \"*\" flag for loaded packages.\n\n\t* interpreter.var.txi: Improve explanation of clear, exist, and who.\n\n\t* interpreter/intro.txi: Change @unnumberedsubsec to @subsection.\n\n\t* interpreter/container.txi: Doc fix.\n\n\t* interpreter/strings.txi: Improve explanation for creating\n\tcomparing, and converting strings.\n\t* interpreter/octave.texi: Update detailed menu.\n\n2007-05-09  David Bateman  <dbateman@free.fr>\n\n\t* faq/Octave-FAQ.texi: Update compatibility section.\n\n2007-04-27  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (EXAMPLE_FILES_NODIR): Add mycell.c, myfeval.c,\n\tmyfunc.c, mypow2.c, mysparse.c, mystring.c, mystruct.c and\n\tparamdemo.cc.\n\t* interpreter.txi/dynamic.txi: Complete all but the section on\n\tthe mex- and oct-file APIs.\n\n2007-04-26  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/stmt.txi: Document for loops over matrices, arrays\n\tand cell arrays.\n\n2007-04-25  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/dynamic.txi: Add additional copyrights. Add sections\n\tof input parameter checking, documentation and testing of\n\toct-files. Adds a section on calling other functions from\n\tmex-files, expands the basic information on mex-files, and add a\n\tfew new sections (to be completed) to the section about mex-files\n\n2007-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/dynamic.txi: Use abs_top_srcdir to find example files.\n\n2007-04-25  David Bateman  <dbateman@free.fr>\n\n\t* conf.texi.in: Also set abs_top_srcdir with substitution.\n\t* Makefile.in: Substitute abs_top_srcdir here.\n\n2007-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/dynamic.txi: Use @verbatiminclude for example code.\n\n\t* interpreter/Makefile.in (EXAMPLE_FILES_NODIR, EXAMPLE_FILES):\n\tNew variables.\n\t(octave.info, octave.dvi, octave.pdf, HTML/index.html):\n\tDepend on $(EXAMPLE_FILES).\n\n\t* conf.texi.in: Also set top_srcdir with substitution.\n\n\t* interpreter/tips.txi: Update with new text and examples.\n\tMove documentation section to the end.\n\n2007-04-24  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/octave.texi: Include dynamic.texi as appendix and\n\tupdate menus.\n\n\t* interpreter/plot.txi: Update menus.\n\n\t* interpreter/strings.txi: @result -> @result{}.\n\n\t* intrepreter/func.txi, intrepreter/sparse.txi:\n\tDelete .oct file section and update menus.\n\n\t* interpreter/addtwomatrices.cc, interpreter/celldemo.cc,\n\tinterpreter/fortdemo.cc, interpreter/funcdemo.cc,\n\tinterpreter/globaldemo.cc, interpreter/helloworld.cc,\n\tinterpreter/stringdemo.cc, interpreter/structdemo.cc,\n\tinterpreter/unwinddemo.cc, interpreter/fortsub.f,\n\tinterpreter/dynamic.txi: New files.\n\n\t* Makefile.in (SUB_SOURCE): Include dynamic.txi in the list.\n\n2007-04-18  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/package.texi: New file.\n\t* octave/texi: @include it, add it to the menus.\n\n2007-04-18  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/contributors.in: New file.\n\t* interpreter/Makefile.in (contributors.texi): New target.\n\t(clean): Also deleete contributors.texi\n\t(TEXINFO): Include contributors.texi in the list.\n\t(preface.texi): @include contributors.texi.\n\n2007-04-17  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/linalg.txi (Techniques used for Linear Algebra):\n\tNew node.\n\t* interpreter/octave.texi: Include it in menu.\n\t* interpreter/sparse.txi: Delete discusion of matrix_type.\n\n2007-04-16  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/stream.txi: Delete.\n\t* interpreter/Makefile.in (SUB_SOURCE): Remove it from the list.\n\n2007-04-16  Søren Hauberg  <hauberg@gmail.com>\n\n\t* intrepreter/stmt.txi: Improve documentation of switch statement.\n\n\t* interpreter/tips.txi: Update description of how copyright\n\tstatements are recognized.\n\n\t* interpreter/octave.texi: Don't include stream.texi.\n\tRemove menu entry for I/O streams.\n\n\t* interpreter/image.txi: Update docs.\n\n2007-04-11  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/container.txi: Document indexing with ().\n\n2007-04-11  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/container.txi: Improve cell array documentation.\n\n2007-04-09  Søren Hauberg  <hauberg@gmail.com>\n\n\t* interpreter/func.txi: Document varargin, varargout, and default\n\targument values.\n\n2007-04-03  Rafael Laboissiere  <rafael@debian.org>\n\n\t* interpreter/basics.txi: Clarified some limitations of the #!\n\tscript mechanism, in particular related to the parsing of the\n\targuments.\n\n2007-03-29  Rafael Laboissiere  <rafael@debian.org>\n\n\t* faq/Octave-FAQ.texi, interpreter/basics.txi,\n\tinterpreter/emacs.txi, interpreter/func.tx, interpreter/var.txi:\n\tMake it clear that the old built-in LOADPATH is an internal\n\tvariable, accessible through path ().\n\tDrop references to DEFAULT_LOADPATH.\n\tChang references to the old built-in variables INFO_FILE and\n\tINFO_PROGRAM to the respective fucntions info_file and\n\tinfo_program.\n\t* refcard/refcard.tex: Drop LOADPATH from list of built-in variables.\n\n2007-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in, interpreter/Makefile.in, faq/Makefile.in,\n\tliboctave/Makefile.in, refcard/Makefile.in (dist):\n\tUse ln instead of $(LN_S).\n\n2007-03-21  G. D. McBain  <geordie.mcbain@aeromech.usyd.edu.au>\n\n\t* interpreter/sparse.txi: Delete repeated word.\n\n2007-03-20  G. D. McBain  <geordie.mcbain@aeromech.usyd.edu.au>\n\n\t* interpreter/sparse.txi: Clarify sparse matrix creation example.\n\n2007-03-14  G. D. McBain  <geordie.mcbain@aeromech.usyd.edu.au>\n\n\t* interpreter/sparse.txi: Fix typo.\n\n2007-02-26  From Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in, interpreter/Makefile.in, faq/Makefile.in,\n\tliboctave/Makefile.in, refcard/Makefile.in:\n\tUse $(LN_S) instead of ln or ln -s.\n\n2007-02-21  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Add functions sprank and normest to\n\tdocumentation.\n\n2007-01-25  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/sparseimages.m: Don't call __gnuplot_x__ functions.\n\n2006-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/sparseimages.m: Fix call to __plt3__.\n\n2006-11-16  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/sparseimages.m (femimages): Use plot3.\n\n2006-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (%.texi : %.txi):\n\tUse $(simple-move-if-change-rule) here.\n\n2006-10-29  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (run-octave): Call it here.\n\t* interpreter/sparseimages.m (sparseimages): Don't call sleep here.\n\n2006-10-27  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (run-octave):\n\tUnset DISPLAY while running Octave.\n\tFrom Michael Goffioul <michael.goffioul@swing.be>.\n\n\t* interpreter/Makefile.in (octave.dvi, octave.pdf):\n\tUse $(UNSETCOMSPEC) in command.\n\t* faq/Makefile.in (Octave-FAQ.dvi, Octave-FAQ.pdf): Likewise.\n\t* liboctave/Makefile.in (liboctave.dvi, liboctave.pdf): Likewise.\n\n2006-10-09  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* interpreter/sparseimages.m: Plot sombrero images if sparse\n\tcapabilities are missing.\n\n2006-10-04  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (HTML_IMAGES_PNG): New variable.\n\t(HTML/index.html): Depend on $(HTML_IMAGES_PNG) instead of html-figs.\n\t($(HTML_IMAGES_PNG): HTML/%.png : %.png): New pattern rule.\n\t(html-dir): Delete target.\n\n2006-10-03  Rafael Laboissiere  <rafael@debian.org>\n\n\t* interpreter/mkoctfile.1: Fix indentation for --mex description.\n\n2006-09-26  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in (stamp-images): Delete.\n\t(octave.info): Depend on $(IMAGES_TXT), not stamp-images.\n\t(octave.dvi): Depend on $(IMAGES_EPS), not stamp-images.\n\t(octave.pdf): Depend on $(IMAGES_PDF), not stamp-images.\n\t(html-figs): Depend on $(IMAGES_PNG), not stamp-images.\n\t(SCRIPT_SOURCES, SPARSEIMAGES_1, SPARSEIMAGES_EPS,\n\tSPARSEIMAGES_PDF, SPARSEIMAGES_PNG, SPARSE_IMAGES_TXT, IMAGES_EPS,\n\tIMAGES_PDF, IMAGES_PNG, IMAGES_TXT, and IMAGES): New variables.\n\t(SOURCES): Include $(SCRIPT_SOURCES) in the list.\n\t(DISTFILES): Include $(IMAGES) in the list.\n\t(maintainer-clean): Delete $(IMAGES) here.\n\t(DISTSUBDIRS, SUBDIRS): Remove $(IMAGEDIR) from list.\n\t(octave.dvi, octave.info, octave.pdf, HTML/index.html):\n\tDon't include $(IMAGEDIR) in list of directories to search\n\t* sparseimages.m: Move here from images/sparseimages.m.\n\t* images/Makefile.in: Delete.\n\t* images: Delete directory.\n\n2006-08-24  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/images/Makefile.in (SPARSEIMAGES_PDF): New macro.\n\tKeep PDF images out of IMAGES list.\n\n2006-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* conf.texi.in: Eliminate TARGETHOSTTYPE variable.\n\n2006-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/images/Makefile.in (%.pdf : %eps):\n\tUse $(GHOSTSCRIPT) instead of gs.\n\n2006-08-14  Dmitri A. Sergatskov  <dasergatskov@gmail.com>\n\n\t* interpreter/images/sparseimages.m: Adapt to new automatic_replot\n\tdefinition.\n\n2006-06-27  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/Makefile.in: Elminate double-colon rules.\n\n2006-05-31  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/images/Makefile.in (run-octave):\n\tUse $(TOPDIR)/run-octave script to execute Octave.\n\t(OCTAVE_BINARY, OCTAVE_SCRIPT_PATH, OCTAVE_LD_LIBRARY_PATH,\n\tXLD_LIBRARY_PATH, SET_LD_LIBRARY_PATH): Delete variables.\n\n2006-04-06  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* interpreter/mkoctfile.1: Doc string fix.\n\n2006-04-03  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/matrix.txi: Add rande, randp, randg and update\n\tfor different random generator behavior.\n\n2006-03-28  John W. Eaton  <jwe@octave.org>\n\n\t* texinfo.tex: Update FSF address.\n\n2006-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/images/sparseimages.m: Fix missing endif.  Omit\n\tunnecessary call to axis.\n\n2006-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/images/sparseimages.m:\n\tAvoid some unnecessary calculations.\n\n2006-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/sparse.txi: Undo previous change.\n\tAlways use @image to include image files.\n\t* interpreter/Makefile.in: Eliminate stamp files.\n\t(clean, mostlyclean, distclean, maintainer-clean): Now\n\tdouble-colon targets.\n\t(stamp-images): New target.\n\t(octave.info, octave.dvi, octave.pdf, HTML/index.html): Depend on it.\n\t* interpreter/images/Makefile.in: Explicitly list images to be\n\tcreated and their dependencies.\n\t* interpreter/images/sparseimages.m (sparseimage): Delete dirc arg.\n\tSleep for 1 second before returning.\n\t(txtimages): Also create gplot.txt and grid.txt.\n\t(sparseimages): Don't redirect output here.\n\tNew arg, nm.  Only output a single figure at a time.\n\t(bury_output): New function.  Use it before plotting commands and\n\tafter every print function.\n\t* Makefile.in (conf.texi): New target.\n\t(DISTFILES): Include conf.texi in the list.\n\t(all, dist): Depend on conf.texi.\n\t* conf.texi.in: Values come from Makeconf, not configure.\n\n2006-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* liboctave/Makefile.in (FORMATTED): Omit .html files here.\n\t(DISTDIRS): New variable.\n\t(dist): Handle $(DISTDIRS) here.\n\n\t* faq/Makefile.in (FORMATTED): Omit .html files here.\n\t(DISTDIRS): New variable.\n\t(dist): Handle $(DISTDIRS) here.\n\n\t* interpreter/Makefile.in (FORMATTED): Omit .html files here.\n\t(DISTDIRS): New variable.\n\t(dist): Handle $(DISTDIRS) here.\n\n\t* interpreter/sparse.txi: Temporarily omit figures.\n\t* interpreter/Makefile.in: Temporarily omit actions for making figures.\n\t(DISTSUBDIRS): New macro.\n\t(dist): Recurse into $(DISTSUBDIRS) here.\n\n\t* interpreter/Makefile.in (real-pdf): Depend on stamp-eps\n\t(stamp-pdf): Depend on real-pdf.  Touch stamp-pdf here.\n\t(real-pdf): Not here.\n\n2006-03-16  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/images/sparseimages.m: set terminal type to dummy to\n\tdirect output to terminal rather than X11.\n\t* interpreter/sparse.txi: Update docs for new QR solvers.\n\n2006-03-09  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/Makefile.in: Change order of commands in HTML/index.html\n\ttarget. Respawn make for stamp-pdf target so that $(wildcard *.eps) is\n\treinterpreted.\n\t* interpreter/sparse.txi: Isolate conditionally built targets in\n\t\"@ifset ... @end ifset\".\n\n2006-03-08  David Bateman  <dbateman@free.fr>\n\n\t* conf.texi: Remove.\n\t* conf.texi.in: New file, for autoconf'ed version of conf.texi.\n\t* Makefile.in: replace conf.texi with conf.texi.in in DISTFILES\n\t* interpreter/Makefile.in: build in subdir IMAGEDIR, add stamps for\n\timage files. Copy png-files to HTML directory. Build pdf files from\n\teps files using epsffit, gs, grep, basename, head and awk.\n\t* octave.texi: Update sparse sub-sections.\n\t* sparse.txi: Updates for current state of sparse code.\n\t* interpreter/images/Makefile.in: New file.\n\t* interpreter/images/sparseimages.m: New file to build sparse images.\n\n2006-03-07  David Bateman  <dbateman@free.fr>\n\n\t* liboctave/dae.texi, liboctave/factor.texi, liboctave/nleqn.texi,\n\tliboctave/quad.texi, liboctave/matvec.texi, liboctave/nlfunc.texi,\n\tliboctave/diffeq.texi, liboctave/array.texi, liboctave/range.texi,\n\tliboctave/optim.texi: Fix some syntax problems for texinfo.tex 4.8.\n\n2006-03-06  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* interpreter/octave.texi (@seealso): Display args instead of\n\tdiscarding them.\n\n2006-03-02  John W. Eaton  <jwe@octave.org>\n\n\t* faq/Makefile.in (Octave-FAQ.ps): Depend on Octave-FAQ.dvi, not\n\t$(TEXINFO).\n\n\t* texinfo.tex: Update to 2004-11-25.16 version from Texinfo 4.8.\n\n2005-12-14  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/testfun.txi: New test/demo documentation.\n\t* interpreter/strings.txi: Include regexp/regexi docstrings.\n\t* interpreter/octave.texi: Include test/demo appendix.\n\t* interpreter/Makefile.in (SUB_SOURCE): Include test.txi.\n\n2005-12-13  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Add new gplot, etreeplot and treeplot\n\tfunctions.\n\n2005-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* liboctave/Makefile.in (maintainer-clean): Also remove liboctave.pdf\n\t* faq/Makefile.in (maintainer-clean): Also remove Octave-FAQ.pdf.\n\tFrom Quentin Spencer <qspencer@ieee.org>.\n\n2005-10-23  David Bateman  <dbateman@free.fr>\n\n\t* sparse.txi: Updates for new ufsparse licensing, new functions and\n\tvarious typos.\n\n2005-09-19  Rafael Laboissiere  <rafael@debian.org>\n\n\t* interpreter/octave-config.1: Use bold instead of italics to\n\tmarkup command name.\n\n2005-07-29  John W. Eaton  <jwe@octave.org>\n\n\t* faq/Makefile.in (HTML/index.html): Pass --ifinfo to makeinfo.\n\t* interpreter/Makefile.in (HTML/index.html): Likewise.\n\t* liboctave/Makefile.in (HTML/index.html): Likewise.\n\n2005-07-28  John W. Eaton  <jwe@octave.org>\n\n\t* faq/Makefile.in, interpreter/Makefile.in, liboctave/Makefile.in:\n\tUse makeinfo instead of texi2html to generate HTML.\n\n2005-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* interpreter/munge-texi.cc (skip_comments): New function.\n\t(process_doc_file): Use it to skip comments at beginning of file.\n\n2005-04-29  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Add matrix_type, spkron, and document\n\tchanges in solve code.\n\n2005-03-14  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: Add luinc function.\n\n2005-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (bin-dist): Delete target.\n\t(BINDISTSUBDIRS): Delete variable.\n\n\t* refcard/Makefile.in (bin-dist): Delete target.\n\t(BINDISTFILES): Delete variable.\n\t* liboctave/Makefile.in: Likewise.\n\t* interpreter/Makefile.in: Likewise.\n\t* faq/Makefile.in: Likewise.\n\n2005-02-25  John W. Eaton  <jwe@octave.org>\n\n\tSparse merge.\n\n\t2005-01-07  David Bateman  <dbateman@free.fr>\n\n\t* interpreter/sparse.txi: New file.\n\t* interpreter/Makefile.in: Add it to the build.\n\t* interpreter/octave.texi: Include it in the contents tables and the\n\ttop level document.\n\n2005-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* liboctave/Makefile.in (all): Also depend on Octave-FAQ.pdf.\n\tUse $(MAKEINFO) instead of makeinfo in rules.\n\n2005-02-25  Rafael Laboissiere  <rafael@debian.org>\n\n\t* liboctave/Makefile.in (Octave-FAQ.pdf): New target and rule.\n\t(FORMATTED): Add Octave-FAQ.pdf to the list.\n\n2005-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* liboctave/Makefile.in (liboctave.pdf): New target and rule.\n\t(FORMATTED): Add liboctave.pdf to the list.\n\t(all): Also depend on liboctave.pdf.\n\tUse $(MAKEINFO) instead of makeinfo in rules.\n\n\t* interpreter/Makefile.in (octave.pdf): New target and rule.\n\t(FORMATTED): Add octave.pdf to the list.\n\t(all): Also depend on octave.pdf.\n\tUse $(MAKEINFO) instead of makeinfo in rules.\n\n2005-02-08  Quentin Spencer  <qspencer@ieee.org>\n\n\t* interpreter/plot.txi: Emphasize compatible plotting functions\n\tover gplot and friends.\n\n2004-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* liboctave/Makefile.in (FORMATTED): Use liboctave*.html instead\n\tof liboctave_*.html.\n\n\t* faq/Makefile.in (FORMATTED): Use Octave-FAQ*.html instead of\n\tOctave-FAQ_*.html.\n\n2004-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* faq/Makefile.in (maintainer-clean): Remove Octave-FAQ*.html\n\tinstead of just Octave-FAQ_*.html.\n\n\t* liboctave/Makefile.in (maintainer-clean): Remove liboctave*.html\n\tinstead of just liboctave_*.html.\n\n\t* refcard/Makefile.in (maintainer-clean): Remove refcard-*.pdf.\n\n2003-12-09  Eric S. Raymond  <esr@thyrsus.com>\n\n\t* interpreter/mkoctfile.1: Use .I instead of .f for markup of \".oct\".\n\n2003-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/munge-texi.cc (process_texi_input_file):\n\tAvoid -Wshadow warnings.\n\n2003-08-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* refcard/Makefile.in (refcard-a4.pdf, refcard-legal.pdf,\n\trefcard-letter.pdf): New targets.\n\t(FORMATTED): Add them to the list.\n\t* refcard/refcard.tex: Optionally set pdf paper size parameters.\n\n2003-08-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (octave_toc.html): Add \"-I .\" to texinfo\n\tcommand line args.\n\n2003-07-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* faq/Makefile.in (FORMATTED): Include all Octave-FAQ_*.html files\n\there, not just the toc.\n\n2003-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in, liboctave/Makefile.in: Handle DESTDIR.\n\n2003-02-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (MAN_BASE): Add octave-config.1 to the list.\n\n2003-02-19  Dirk Eddelbuettel  <edd@debian.org>\n\n\t* octave-config.1: New file.\n\n2003-01-11  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* interpreter/Makefile.in (munge-texi$(BUILD_EXEEXT)): Pass\n\t$(BUILD_CXXFLAGS) and $(BUILD_LDFLAGS) to compiler.\n\t(%.o : %.cc): Delete pattern rule.\n\n2003-01-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/munge-texi.cc: Define __USE_STD_IOSTREAM if using\n\tCompaq C++.\n\n2002-12-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (%.o : %.c): No longer need\n\t-DNO_PRAGMA_INTERFACE_IMPLEMENTATION=1 compiler option.\n\t(munge-texi#(BUILD_EXEEXT)): Likewise.\n\tDon't link to Map-s.o.\n\n\t* interpreter/Map-s.cc: Delete.\n\t* interpreter/Makefile.in (DISTFILES): Delete it from the list.\n\t(mostlyclean, clean): Don't delete Map-s.o.\n\n\t* interpreter/munge-texi.cc: Require working STL.\n\n2002-11-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (maintainer-clean): Depend on\n\tclean-texi, don't remove $(TEXINFO).\n\n2002-11-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/munge-texi.cc: Use STL map class by default, but\n\tmake it easy to revert back to libg++-based Map class if that\n\tfails to work on some systems.\n\n2002-11-01  Dirk Eddelbuettel  <edd@debian.org>\n\n\t* interpreter/Makefile.in (MAN_BASE, MAN_SRC): New variables, use\n\tas appropriate.\n\n2002-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n \t* interpreter/mkoctfile.1: New file.\n\n2002-10-25  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* interpreter/Makefile.in (octave_toc.html): Use -expandinfo and\n\t-split_chapter instead of -expand info and -split chapter.\n\t* liboctave/Makefile.in (liboctave_toc.html): Likewisel\n\t* faq/Makefile.in (Octave-FAQ_toc.html): Likewise.\n\n2002-10-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (munge-texi$(BUILD_EXEEXT)): Always use\n\t-DNO_PRAGMA_INTERFACE_IMPLEMENTATION for compiling and linking.\n\n2002-10-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (%.texi : %.txi):\n\tUse $(top_srcdir)/move-if-change.\n\n2002-10-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in: Use $(BUILD_EXEEXT) as appropriate.\n\n2002-10-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (munge-texi, %.o : %.cc):\n\tUse $(BUILD_CXX), not $(CXX).\n\t(src-DOCSTRINGS, scripts-DOCSTRINGS): New targets.\n\t($(TEXIFNO)): Depend on them.\n\t(DOCSTRINGS): Delete variable.\n\n2002-10-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (%.spell): Use $(SED), not sed.\n\t* liboctave/Makefile.in (%.spell): Likewise.\n\t* faq/Makefile.in (%.spell): Likewise.\n\n2001-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (octave_toc.html): Use -expand info and\n\t-split chapter, to be consistent.\n\t* liboctave/Makefile.in (liboctave_toc.html): Likewise.\n\t* faq/Makefile.in (Octave-FAQ_toc.html): Likewise.\n\n2001-11-14  Christoph Spiel  <cspiel@hammersmith-consulting.com>\n\n\t* faq/Makefile.in (Octave-FAQ_toc.html): Use -expandinfo and\n\t-split_chapter, not -expand info and -split chapter.\n\t* liboctave/Makefile.in (liboctave_toc.html): Likewise.\n\n2001-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (MAIN_TEXINFO): Look in $(srcdir).\n\t(octave_toc.html): Use -expandinfo and -split_chapter, not\n\t-expand info and -split chapter.\n\n2001-03-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* liboctave/Makefile.in (liboctave_toc.html): Use -expand info and\n\t-split chapter instead of -expandinfo and -split_chapter options\n\tfor texi2html.\n\t* faq/Makefile.in (Octave-FAQ_toc.html): Likewise.\n\t* interpreter/Makefile.in (octave_toc.html): Likewise.\n\n2000-10-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* liboctave/Makefile.in (liboctave_toc.html): Add space after -I\n\tin texi2html command.\n\t* interpreter/Makefile.in (octave_toc.html): Ditto.\n\n2000-03-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/octave-bug.1: New file.\n\t* interpreter/Makefile.in (install install-strip): Install it.\n\t(DISTFILES, BINDISTFILES): Add it to the\n\n2000-02-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (clean): Also delete munge-texi,\n\tmunge-texi.o, and Map-s.o.\n\n2000-02-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/munge-texi.cc: Sprinkle with std:: qualifier.\n\n2000-01-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (clean-texi): Avoid removing octave.texi.\n\n2000-01-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in: Don't generate octave.texi from octave.txi.\n\t* interpreter/octave.texi: Rename from octave.txi.\n\n\t* interpreter/munge-texi.cc (process_texi_input_file): Undo\n\tprevious change, since % doesn't work as a comment character after\n\ttexinfo.tex is included.\n\n2000-01-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* texinfo.tex: Update to version from texinfo-4.0.\n\n\t* interpreter/munge-texi.cc (process_texi_input_file): For Texinfo\n\tdoc strings, automatically insert an @anchor{doc-SYMBOL} command\n\tjust before the docstring for SYMBOL.\n\n1999-12-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/munge-texi.cc (process_texi_input_file): Begin\n\ttransformed files with `% DO NOT EDIT' instead of `@c DO NOT EDIT'\n\tto prevent problems with TeX not knowing the definition of @c\n\tbefore it is used.\n\n1999-11-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (%.texi : %.txi): Suppress command echo.\n\n1999-10-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (dist): Remove .texi files first, so\n\tthey will have timestamps newer than the $(DOCSTRINGS) files.\n\t(%.texi : %.txi): Use mv instead of move-if-change.\n\n\t* interpreter/Map-s.cc: New file.\n\t* interpreter/munge-texi.cc: Use old libg++ Map class instead of\n\tSTL map, for the benefit of systems that have assemblers that\n\tcan't handle the long symbol names generated by g++ for\n\tmap<string,string>.\n\n1999-10-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/munge-texi.cc: Strip the \"-*- texinfo -*-\" marker\n\twhen including help text.\n\n\t* interpreter/Makefile.in ($(TEXINFO)): Depend on $(DOCSTRINGS).\n\t($(DOCSTRINGS)): New rule.\n\n\t* Makefile.in (dist, bin-dist): Use `$(MAKE) -C dir' instead of\n\t`cd dir; $(MAKE); cd ..'.\n\t(../BUGS, ../INSTALL.OCTAVE, $(SUBDIRS)) Likewise.\n\n\t* interpreter/*.txi: Rename from *.txi.\n\t* interpreter/munge-texi.cc: New file.\n\t* interpreter/Makefile.in: Use it to create .texi files from .txi\n\tfiles and DOCSTRING files.\n\nFri Jun 18 23:17:02 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (octave_toc.html): Add -expandinfo to\n\ttex12html options.\n\t* liboctave/Makefile.in (liboctave_toc.html): Likewise.\n\t* faq/Makefile.in (Octave-FAQ_toc.html): Likewise.\n\nFri Oct  9 00:27:33 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* faq/Makefile.in, interpreter/Makefile.in, liboctave/Makefile.in:\n\tNew rules for generating HTML files from Texinfo sources.\n\nThu May 14 21:04:40 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (../../BUGS, ../../INSTALL): Add\n\t--no-validate to makeinfo args.\n\nWed Jul  2 16:41:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* refcard/Makefile.in: Remove .tex files from binary distributions.\n\n\t* interpreter/Makefile.in: Add DVI and Postscript files to binary\n\tdistributions.\n\nFri Apr 18 02:51:00 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* faq/Octave-FAQ.texi: Rename from faq/FAQ.texi.\n\t* faq/Makefile.in: Fix names to match.\n\nWed Mar 12 17:01:02 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-strip): New target.\n\t* faq/Makefile.in: Ditto.\n\t* interpreter/Makefile.in: Ditto.\n\t* liboctave/Makefile.in: Ditto.\n\t* refcard/Makefile.in: Ditto.\n\nSat Mar  1 15:23:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.5 released.\n\nFri Feb 28 20:53:40 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* texinfo.tex: Update to latest version from Karl Berry, and apply\n\tprevious patch too.\n\nThu Feb 27 03:34:48 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* texinfo.tex (\\codeunder): Maybe make it work for @var{} inside\n\t@code{}.\n\nWed Feb 26 12:03:48 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* refcard/Makefile.in (mostlyclean clean): Delete log files.\n\n\t* liboctave/Makefile.in (mostlyclean clean): Delete more stuff.\n\n\t* faq/Makefile.in (mostlyclean clean): Delete some stuff.\n\nThu Feb 20 02:58:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.4 released.\n\nWed Feb 19 10:30:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DISTFILES): Distribute conf.texi, not conf.texi.in.\n\n\t* liboctave/Makefile.in: Don't make or distribute conf.texi.\n\t(liboctave.info, liboctave.dvi): Depend on ../conf.texi, not conf.texi.\n\n\t* interpreter/Makefile.in: Don't create or distribute conf.texi.\n\t(octave.info, octave.dvi): Depend on ../conf.texi, not conf.texi.\n\nTue Feb 18 09:22:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.3 released.\n\nWed Jan 29 11:49:25 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (../INSTALL.OCTAVE, ../BUGS): Declare these to be\n\t.PHONY so that we will always check the interpreter makefile to\n\tget the proper dependencies.\n\nMon Jan 27 15:52:33 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.2 released.\n\nSun Jan 26 22:07:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in: Make BUGS file directly from bugs.texi.\n\t* interpreter/bugs.texi: Incorporate bugs1.texi directly.\n\t* interpreter/bugs1.texi: Delete.\n\n\t* interpreter/Makefile.in: Make INSTALL file directly from\n\tinstall.texi.\n\t* interpreter/install.texi: Incorporate install1.texi directly.\n\t* interpreter/install1.texi: Delete.\n\nSat Jan 25 22:32:33 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in, interpreter/Makefile.in, liboctave/Makefile.in,\n\tfaq/Makefile.in, refcard/Makefile.in (bin-dist): New target.\n\nTue Jan  7 00:17:24 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.1 released.\n\nTue Dec 10 01:43:13 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0 released.\n\nFri Dec  6 15:23:52 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.94.\n\nWed Nov 20 01:00:50 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.93.\n\nThu Nov 14 00:07:25 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* faq/Makefile.in (FAQ.dvi): Use $(TEXI2DVI), not just texi2dvi.\n\t* interpreter/Makefile.in (octave.dvi): Likewise.\n\t* liboctave/Makefile.in (liboctave.dvi): Likewise.\n\n\t* Version 1.92.\n\nThu Nov  7 12:43:19 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.91.\n\n\t* texinfo.tex: Update to version from texinfo-3.9 distribution.\n\nWed Oct 30 17:20:28 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.90.\n\n\t* Makefile.in (DISTFILES): Add ChangeLog.\n\nSat Oct 12 13:38:49 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (maintainer-clean): Don't depend on distclean.\n\nSat Jun 15 23:01:33 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in (TEXINFO): Add audio.texi and emacs.texi.\n\nFri May 17 03:02:37 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* interpreter/Makefile.in: Use man1dir instead of mandir, and\n\tman1ext instead of manext.\n\nSat Mar 23 05:01:17 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* liboctave/Makefile.in (TEXINFO): Don't list conf.texi and\n\tgpl.texi here.\n\n\t* liboctave/Makefile.in (dist targets): Fix ln command.\n\t* refcard/Makefile.in (dist targets): Likewise.\n\t* interpreter/Makefile.in (dist targets): Likewise.\n\t* faq/Makefile.in (dist targets): Likewise.\n\nFri Mar 22 23:57:26 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* liboctave/Makefile.in (DISTFILES): Add gpl.texi.\n\t* interpreter/Makefile.in (DISTFILES): Add gpl.texi.\n\t* Makefile.in (DISTFILES): Delete gpl.texi.\n\nSun Mar  3 11:33:30 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Split docs into faq, interpreter, liboctave, and refcard\n\tsubdirectories.\n\nWed Sep 20 00:47:45 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkinstalldirs: New file.\n\t* Makefile.in (DISTFILES): Add it to the list.\n\n\t* Makefile.in (maintainer-clean): Delete .dvi, .ps, and .info\n\tfiles here.\n\t(clean): Not here.\n\t(mostlyclean): Make this the same as clean.\n\nTue Sep 19 03:18:35 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (../BUGS, ../INSTALL.OCTAVE): Specify output file to\n\tmakeinfo with --output option.\n\nThu Sep 14 20:31:47 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Don't fail if makeinfo, tex, or dvips fail.\n\nSee ChangeLog.1 in the top level directory for earlier changes.\n"
  },
  {
    "path": "etc/OLD-ChangeLogs/libcruft-ChangeLog",
    "content": "2011-03-24  Jarno Rajahalme  <jarno.rajahalme@gmail.com>\n\n\t* misc/blaswrap.c: New file.\n\t* misc/module.mk (EXTRA_DIST): Add it to the list.\n\n2011-01-31  Rik  <octave@nomad.inbox5.com>\n\n\t* arpack/src/dseupd.f, arpack/src/sseupd.f: Change GOTO target\n\tto eliminate warning about landing on end if.\n\n2011-01-31  John W. Eaton  <jwe@octave.org>\n\n\t* arpack/module.mk (EXTRA_DIST): Include arpack/module.mk in the\n\tlist.  Remove arpack/src/module.mk and arpacck/util/module.mk\n\tfrom the list.\n\n2011-01-31  John W. Eaton  <jwe@octave.org>\n\n\t* arpack/LICENSE: Update to current version from\n\thttp://www.caam.rice.edu/software/ARPACK.\n\t* arpack/ARPACK-license-question.email: Delete as it no longer\n\tapplies to the current license terms.\n\t* arpack/RiceBSD.txt: Delete.\n\t* arpack/module.mk: Update for license changes.\n\tAdd arpack/ prefix to doc files in list.\n\n2011-01-28  David Bateman  <dbateman@free.fr>\n\n\t* arpack/src/cneupd.f (cneupd): Restore value of nconv if ctrsen\n\treturns a smaller value.\n\t* arpack/src/dneupd.f (dneupd): Likewise, for dtrsen.\n\t* arpack/src/sneupd.f (sneupd): Likewise, for strsen.\n\t* arpack/src/zneupd.f (zneupd): Likewise, for ztrsen.\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* arpack/util/second.f (ARSCND): Declare ETIME INTRINSIC, not EXTERNAL.\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* arpack: New directory.\n\t* Makefile.am: Include arpack/module.mk.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* mkf77def.in: Strip trailing whitespace.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* misc/cquit.c, misc/f77-fcn.h, misc/quit.cc: Strip trailing\n\twhitespace.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* Update copyright notices for 2011.\n\n2010-09-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* blas-xtra/cconv2.f, blas-xtra/csconv2.f, blas-xtra/dconv2.f,\n\tblas-xtra/sconv2.f, blas-xtra/zconv2.f, blas-xtra/zdconv2.f:\n\tFix inner convolution formula.\n\n2010-07-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lapack-xtra/zrsf2csf.f, lapack-xtra/crsf2csf.f: New sources.\n\t* lapack-xtra/module.mk: Add them.\n\n2010-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* villad/dfopr.f, villad/dif.f, villad/intrp.f, villad/jcobi.f,\n\tvillad/radau.f, villad/vilerr.f, villad/module.mk: Delete.\n\t* Makefile.am: Don't include villad/module.mk.\n\n2010-04-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* blas-xtra/cmatm3.f, blas-xtra/zmatm3.f,\n\tblas-xtra/dmatm3.f, blas-xtra/xsdot.f: Fix typos. Add missing\n\tdecls.\n\n2010-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (libcruft_la_LIBADD): Include ../libgnu/libgnu.la\n\tin the list.  From Marco Atzeri <marco_atzeri@yahoo.it>.\n\n2010-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (libcruft_la_CPPFLAGS): Append $(AM_CPPFLAGS).\n\n2010-03-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* blas-xtra/cconv2.f, blas-xtra/csconv2.f, blas-xtra/dconv2.f,\n\tblas-xtra/sconv2.f, blas-xtra/zconv2.f, blas-xtra/zdconv2.f:\n\tNew sources.\n\t* blas-xtra/module.mk: Add them here.\n\n2010-03-02  John W. Eaton  <jwe@octave.org>\n\n\t* misc/cquit.c (octave_restore_signal_mask): Assume we have\n\tPOSIX signal handling.\n\n2010-02-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* misc/lo-error.c (liboctave_fatal_with_id,\n\tset_liboctave_error_with_id_handler): New functions.\n\t(current_liboctave_error_with_id_handler): New variable.\n\t* misc/lo-error.h: Declare them.\n\t(liboctave_error_with_id_handler): New typedef.\n\n2010-02-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* misc/quit.h: Define WIN32_LEAN_AND_MEAN and don't #undef min/max.\n\n\t* Makefile.am: Add -bindir option to libcruft_la_LDFLAGS.\n\n2010-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (libcruft_la_LIBADD): Include libranlib.la in the list.\n\t(noinst_LTLIBRARIES, libranlib_la_SOURCES, libranlib_la_DEPENDENCIES,\n\tlibcruft_la_FFLAGS): New variables.\n\t(ranlib.def): New target.\n\t(DISTCLEANFILES): Also remove ranlib.def.\n\t* ranlib/module.mk (libranlib_la_SOURCES): Rename from\n\tlibcruft_la_SOURCES.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* misc/quit.cc: Untabify.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (EXTRA_DIST): Remove STOP.patch from the list.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* misc/quit.h: Define inline-function variant of OCTAVE_QUIT in C++\n\tmode.\n\n2009-01-13  Rik  <octave@nomad.inbox5.com>\n\n\t* STOP.patch: Remove unmaintained patch for Fortran code\n\n2009-01-13  Rik  <octave@nomad.inbox5.com>\n\n\t* ranlib/advnst.f ranlib/genbet.f ranlib/genchi.f ranlib/genexp.f\n\tranlib/genf.f ranlib/gengam.f ranlib/genmul.f ranlib/gennch.f\n\tranlib/gennf.f ranlib/gennor.f ranlib/genunf.f ranlib/getcgn.f\n\tranlib/getsd.f ranlib/ignbin.f ranlib/ignnbn.f ranlib/ignpoi.f\n\tranlib/ignuin.f ranlib/initgn.f ranlib/mltmod.f ranlib/setant.f\n\tranlib/setgmn.f ranlib/setsd.f: call XSTOPX instead of STOP so Octave's\n\terror handler can intercept errors in Fortran code\n\n2010-01-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* misc/quit.cc (octave_rethrow_exception): Set octave_interrupt_state\n\tto -1 when throwing octave_interrupt_exception.\n\n2010-01-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (AM_CPPFLAGS): New variable.\n\n2009-12-31  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Reverse using simple_move_if_change_rule for cruft.def\n\twhich interferes with make timestamp algorithm.\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Eliminate TOPDIR variable in favor of built-in automake\n\tvariables of top_builddir and top_srcdir.\n\n2009-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Use simple_move_if_change_rule for cruft.def to eliminate\n\tunnecessary compilations.\n\n2009-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* misc/f77-fcn.h, misc/lo-error.h, misc/quit.h,\n\tmisc/f77-extern.cc, misc/quit.cc, misc/cquit.c, misc/f77-fcn.c,\n\tmisc/lo-error.c: Remove Emacs local variable list.\n\n2009-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* misc/cquit.c, misc/f77-fcn.h, misc/quit.h: Untabify.\n\n2009-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (DISTCLEANFILES): New variable.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* blas-xtra/sdot3.f: Use nested cache-aligned loop for general case.\n\t* blas-xtra/ddot3.f: Ditto.\n\t* blas-xtra/cdotc3.f: Ditto.\n\t* blas-xtra/zdotc3.f: Ditto.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* blas-xtra/sdot3.f: New source.\n\t* blas-xtra/ddot3.f: New source.\n\t* blas-xtra/cdotc3.f: New source.\n\t* blas-xtra/zdotc3.f: New source.\n\t* blas-xtra/smatm3.f: New source.\n\t* blas-xtra/dmatm3.f: New source.\n\t* blas-xtra/cmatm3.f: New source.\n\t* blas-xtra/zmatm3.f: New source.\n\t* blas-xtra/module.mk: Include them.\n\n2009-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* mkf77def.in: Only process files with names that match *.f.\n\n2009-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am: Restore rules for building cruft.def.\n\t(libcruft_la_LDFLAGS): Also append @XTRA_CRUFT_SH_LDFLAGS@.\n\t(libcruft_la_DEPENDENCIES): New variable.\n\t* mkf77def.in: Use @VAR@ instead of %VAR% substitutions.\n\tProcess\tsrcdir plus list of files instead of working as a filter.\n\n2009-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (libcruft_la_CPPFLAGS): Define.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* blas, lapack: Remove directories and all files.\n\t* Makefile.am: Don't include blas/module.mk or lapack/module.mk.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am, amos/module.mk, blas-xtra/module.mk,\n\tblas/module.mk, daspk/module.mk, dasrt/module.mk, dassl/module.mk,\n\tfftpack/module.mk, lapack-xtra/module.mk, lapack/module.mk,\n\tmisc/module.mk, odepack/module.mk, ordered-qz/module.mk,\n\tquadpack/module.mk, ranlib/module.mk, slatec-err/module.mk,\n\tslatec-fn/module.mk, villad/module.mk: New files.\n\n\t* Makefile.in, Makerules.in, amos/Makefile.in,\n\tblas-xtra/Makefile.in, blas/Makefile.in, daspk/Makefile.in,\n\tdasrt/Makefile.in, dassl/Makefile.in, fftpack/Makefile.in,\n\tlapack-xtra/Makefile.in, lapack/Makefile.in, misc/Makefile.in,\n\todepack/Makefile.in, ordered-qz/Makefile.in, quadpack/Makefile.in,\n\tranlib/Makefile.in, slatec-err/Makefile.in, slatec-fn/Makefile.in,\n\tvillad/Makefile.in: Delete.\n\n2009-09-17  John W. Eaton  <jwe@octave.org>\n\n\t* misc/oct-dlldefs.h: Delete.\n\t* misc/Makefile.in (INCLUDES): Remove oct-dlldefs.h from the list.\n\n2009-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LINK_DEPS): Omit $(FFTW_LIBS) from the list.\n\n2009-06-22  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (MISC_OBJ): Remove misc/machar.o and misc/smachar.o\n\tfrom the list.\n\n\t* misc/i1mach.f, misc/r1mach.f, misc/d1mach.f: Rewite in terms of\n\tLAPACK functions slamch and dlamch.\n\t* misc/machar.c: Delete.\n\t* misc/Makefile.in (CSRC): Remove machar.c from the list.\n\t(CEXTRA, XCC, XALL_CFLAGS): Delete variables.\n\t(machar.o, smachar.o, pic/machar.o, pic/smachar.o): Delete rules.\n\n2009-05-07  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* Makefile.in: (SHLPRE): Rename from SHLLIBPRE.\n\n2009-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* misc/quit.h (octave_rethrow_exception):\n\tDon't tag with GCC_ATTR_NORETURN.\n\n2009-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (maintainer-clean): Also remove libraries.\n\n\t* Makerules.in: Make maintainer-clean and distclean the same.\n\n2009-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* misc/quit.h (octave_signal_caught): Declare as volatile.\n\t* misc/cquit.cc (octave_signal_caught): Likewise.\n\n2009-02-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* blas/ssymm.f, blas/dsymm.f, blas/chemm.f, blas/zhemm.f: New sources.\n\t* blas/Makefile.in: Include them.\n\n2009-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LIBRARIES, install, uninstall): use SHLLIBPRE and\n\tSHLBINPRE library prefixes.\n\tFrom Marco Atzeri <marco_atzeri@yahoo.it>.\n\n2008-12-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lapack/chegs2.f lapack/chegst.f lapack/chegv.f lapack/dsygs2.f\n\tlapack/dsygst.f lapack/dsygv.f lapack/ssygs2.f lapack/ssygst.f\n\tlapack/ssygv.f lapack/zhegs2.f lapack/zhegst.f lapack/zhegv.f:\n\tNew sources.\n\t* lapack/Makefile.in: Include them.\n\n2008-12-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* blas/zsyrk.f: New source.\n\t* lapack/cggbak.f, lapack/cggev.f, lapack/cgghrd.f, lapack/chgeqz.f,\n\tlapack/ctgevc.f, lapack/dggev.f, lapack/sggev.f, lapack/zggbak.f,\n\tlapack/zggev.f, lapack/zgghrd.f, lapack/zhgeqz.f, lapack/ztgevc.f:\n\tNew sources.\n\t* lapack/Makefile.in: Include them.\n\n2008-08-12  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* blas/icamax.f, blas/isamax.f: New files.\n\t* blas/Makefile.in (FSRC): Add them to the list.\n\n\t* lapack/icmax1.f: New file.\n\t* lapack/Makefile.in (FSRC): Add it to the list.\n\n2008-06-16  David Bateman  <dbateman@free.fr>\n\n\t* slatec-fn/xacosh.f, slatec-fn/xasinh.f: Replace xsacosh with\n\txacosh, xdacosh with xacosh and xdasinh with xasinh.\n\n2008-06-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* misc/Makefile.in (MAKEDEPS): Remove CEXTRA.\n\n2008-06-04  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* misc/oct-dlldefs.h (OCTGRAPHICS_API): New macro for import/export\n\tin graphics related libraries.\n\n2008-06-02  David Bateman  <dbateman@free.fr>\n\n\t* slatec/xsgmainc.f: Replace DLGAMS with ALGAMS.\n\n2008-05-30  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* quadpack/qk15i.f: Delete extraneous semicolons.\n\n2008-05-21  David Bateman  <dbateman@free.fr>\n\n\t* odepack/slsode.f, odepack/sintdy.f: Replace the use of xerrwv\n\twith xerrwd and rumach with d1mach(4).\n\n\t* odepack/scfode.f, odepack/sewset.f, odepack/sintdy.f,\n\todepack/slsode.f, odepack/sprepj.f, odepack/ssolsy.f,\n\todepack/sstode.f, odepack/svnorm.f: New files.\n\t* odepack/Makefile.in (FSRC): Add them.\n\n\t* ordered-qz/sexchqz.f, ordered-qz/ssubsp.f: New files.\n\t* ordered-qz/Makefile.in (FSRC): Add them.\n\t* quadpack/qagi.f, quadpack/qagie.f, quadpack/qagp.f,\n\tquadpack/qagpe.f, quadpack/qelg.f, quadpack/qk15i.f,\n\tquadpack/qk21.f, quadpack/qpsrt.f: New files.\n\t* quadpack/Makefile.in (FSRC): Add them.\n\n2008-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* qrupdate/cch1dn.f, qrupdate/cchinx.f, qrupdate/cqhqr.f,\n\tqrupdate/cqrinc.f, qrupdate/cqrinr.f, qrupdate/cqrqhu.f,\n\tqrupdate/cqrqhv.f, qrupdate/sch1dn.f, qrupdate/schinx.f,\n\tqrupdate/sqhqr.f, qrupdate/sqrinc.f, qrupdate/sqrinr.f,\n\tqrupdate/sqrqhu.f: Convert DOUBLE PRECISION constants to REAL.\n\t* qrupdate/cqrinr.f, qrupdate/sqrinr.f: Correct EXTERNAL\n\tdeclarations.\n\t* qrupdate/sqrinr.f: Convert DOUBLE PRECISION calls to\n\tREAL counterparts.\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (MISC_OBJ): Add misc/smachar.o\n\t* Makerules.in (CRUFT_CSRC, CRUFT_CPICOBJ): Add CEXTRA, allowing\n\tobjects files with no corresponding source file in the\n\tdistribution.\n\n\t* amos/cacai.f, amos/cacon.f, amos/cbesh.f, amos/cbesi.f,\n\tamos/cbesj.f, amos/cbesk.f, amos/cbesy.f, amos/cbinu.f,\n\tamos/cbuni.f, amos/cbunk.f, amos/cunk1.f amos/cunk2.f,\n\tamos/crati.f, amos/cshch.f, amos/cuni1.f, amos/cuoik.f,\n\tamos/cairy.f, amos/cbiry.f, amos/ckscl.f, amos/cs1s2.f,\n\tamos/cuchk.f, amos/cuni2.f, amos/cwrsk.f, amos/casyi.f,\n\tamos/cbknu.f, amos/cmlri.f, amos/cseri.f, amos/cunhj.f,\n\tamos/cunik.f: New files.\n\t* amos/Makefile.in (FSRC): Add them.\n\n\t* blas-xtra/xsdot.f, blas-xtra/xsnrm2.f, blas-xtra/xscnrm2.f,\n\tblas-xtra/xcdotc.f, blas-xtra/xcdotu.f: New files\n\t* blas-xtra/Makefile.in (FSRC): Add them.\n\n\t* blas/sasum.f, blas/saxpy.f, blas/scabs1.f, blas/scopy.f,\n\tblas/sger.f, blas/smach.f, blas/snrm2.f, blas/srot.f,\n\tblas/sswap.f, blas/ssymv.f, blas/ssyr.f, blas/ssyr2.f,\n\tblas/ssyr2k.f, blas/stbsv.f, blas/strmm.f, blas/strmv.f,\n\tblas/strsv.f, blas/scasum.f, blas/scnrm2.f, blas/caxpy.f,\n\tblas/ccopy.f, blas/cdotc.f, blas/cdotu.f, blas/, blas/csrot.f,\n\tblas/csscal.f, blas/cgemm.f, blas/cgemv.f, blas/cgerc.f,\n\tblas/cgeru.f, blas/chemv.f, blas/cher.f, blas/cher2.f,\n\tblas/cher2k.f, blas/cherk.f, blas/cscal.f, blas/cswap.f,\n\tblas/ctbsv.f, blas/ctrmm.f, blas/ctrmv.f, blas/, blas/ctrsm.f,\n\tblas/ctrsv.f: New files\n\t* blas/Makefile.in (FSRC): Add them.\n\n\t* fftpack/zfftb.f, zfftb1.f, fftpack/zfftf.f, fftpack/zfftf1.f,\n\tfftpack/zffti.f, fftpack/zffti1.f, fftpack/zpassb.f,\n\tfftpack/zpassb2.f, fftpack/zpassb3.f, fftpack/zpassb4.f,\n\tfftpack/zpassb5.f, fftpack/zpassf.f, fftpack/zpassf2.f,\n\tfftpack/zpassf3.f, fftpack/zpassf4.f, fftpack/zpassf5.f: Rename\n\tfunction (c -> z | add z).\n\t* fftpack/cfftb.f, cfftb1.f, fftpack/cfftf.f, fftpack/cfftf1.f,\n\tfftpack/cffti.f, fftpack/cffti1.f, fftpack/passb.f,\n\tfftpack/passb2.f, fftpack/passb3.f, fftpack/passb4.f,\n\tfftpack/passb5.f, fftpack/passf.f, fftpack/passf2.f,\n\tfftpack/passf3.f, fftpack/passf4.f, fftpack/passf5.f: New files\n\tfor single precision.\n\t* fftpack/Makefile.in (FSRC): Add new files.\n\n\t* lapack-xtra/xclange.f, lapack-xtra/xslamch.f,\n\tlapack-xtra/xslange.f: New files.\n\t* lapack-xtra/Makefile.in (FSRC): Add them.\n\n\t* lapack/cbdsqr.f, lapack/csrscl.f, lapack/cgbcon.f,\n\tlapack/cgbtf2.f, lapack/cgbtrf.f, lapack/cgbtrs.f,\n\tlapack/cgebak.f, lapack/cgebal.f, lapack/cgebd2.f,\n\tlapack/cgebrd.f, lapack/cgecon.f, lapack/cgeesx.f, lapack/cgeev.f,\n\tlapack/cgehd2.f, lapack/cgehrd.f, lapack/cgelq2.f,\n\tlapack/cgelqf.f, lapack/cgelsd.f, lapack/cgelss.f,\n\tlapack/cgelsy.f, lapack/cgeqp3.f, lapack/cgeqpf.f,\n\tlapack/cgeqr2.f, lapack/cgeqrf.f, lapack/cgesv.f, lapack/cgesvd.f,\n\tlapack/cgetf2.f, lapack/cgetrf.f, lapack/cgetri.f,\n\tlapack/cgetrs.f, lapack/cggbal.f, lapack/cgtsv.f, lapack/cgttrf.f,\n\tlapack/cgttrs.f, lapack/cgtts2.f, lapack/cheev.f, lapack/chetd2.f,\n\tlapack/chetrd.f, lapack/chseqr.f, lapack/clabrd.f,\n\tlapack/clacgv.f, lapack/clacn2.f, lapack/clacon.f,\n\tlapack/clacpy.f, lapack/cladiv.f, lapack/clahqr.f,\n\tlapack/clahr2.f, lapack/clahrd.f, lapack/claic1.f,\n\tlapack/clals0.f, lapack/clalsa.f, lapack/clalsd.f,\n\tlapack/clange.f, lapack/clanhe.f, lapack/clanhs.f,\n\tlapack/clantr.f, lapack/claqp2.f, lapack/claqps.f,\n\tlapack/claqr0.f, lapack/claqr1.f, lapack/claqr2.f,\n\tlapack/claqr3.f, lapack/claqr4.f, lapack/claqr5.f, lapack/clarf.f,\n\tlapack/clarfb.f, lapack/clarfg.f, lapack/clarft.f,\n\tlapack/clarfx.f, lapack/clartg.f, lapack/clarz.f, lapack/clarzb.f,\n\tlapack/clarzt.f, lapack/clascl.f, lapack/claset.f, lapack/clasr.f,\n\tlapack/classq.f, lapack/claswp.f, lapack/clatbs.f,\n\tlapack/clatrd.f, lapack/clatrs.f, lapack/clatrz.f,\n\tlapack/clauu2.f, lapack/clauum.f, lapack/cpbcon.f,\n\tlapack/cpbtf2.f, lapack/cpbtrf.f, lapack/cpbtrs.f,\n\tlapack/cpocon.f, lapack/cpotf2.f, lapack/cpotrf.f,\n\tlapack/cpotri.f, lapack/cpotrs.f, lapack/cptsv.f, lapack/cpttrf.f,\n\tlapack/cpttrs.f, lapack/cptts2.f, lapack/crot.f, lapack/csteqr.f,\n\tlapack/ctrcon.f, lapack/ctrevc.f, lapack/ctrexc.f,\n\tlapack/ctrsen.f, lapack/ctrsyl.f, lapack/ctrti2.f,\n\tlapack/ctrtri.f, lapack/ctrtrs.f, lapack/ctzrzf.f,\n\tlapack/cung2l.f, lapack/cung2r.f, lapack/cungbr.f,\n\tlapack/cunghr.f, lapack/cungl2.f, lapack/cunglq.f,\n\tlapack/cungql.f, lapack/cungqr.f, lapack/cungtr.f,\n\tlapack/cunm2r.f, lapack/cunmbr.f, lapack/cunml2.f,\n\tlapack/cunmlq.f, lapack/cunmqr.f, lapack/cunmr3.f,\n\tlapack/cunmrz.f, lapack/sbdsqr.f, lapack/sgbcon.f,\n\tlapack/sgbtf2.f, lapack/sgbtrf.f, lapack/sgbtrs.f,\n\tlapack/sgebak.f, lapack/sgebal.f, lapack/sgebd2.f,\n\tlapack/sgebrd.f, lapack/sgecon.f, lapack/sgeesx.f, lapack/sgeev.f,\n\tlapack/sgehd2.f, lapack/sgehrd.f, lapack/sgelq2.f,\n\tlapack/sgelqf.f, lapack/sgelsd.f, lapack/sgelss.f,\n\tlapack/sgelsy.f, lapack/sgeqp3.f, lapack/sgeqpf.f,\n\tlapack/sgeqr2.f, lapack/sgeqrf.f, lapack/sgesv.f, lapack/sgesvd.f,\n\tlapack/sgetf2.f, lapack/sgetrf.f, lapack/sgetri.f,\n\tlapack/sgetrs.f, lapack/sggbak.f, lapack/sggbal.f,\n\tlapack/sgghrd.f, lapack/sgtsv.f, lapack/sgttrf.f, lapack/sgttrs.f,\n\tlapack/sgtts2.f, lapack/shgeqz.f, lapack/shseqr.f,\n\tlapack/slabad.f, lapack/slabrd.f, lapack/slacn2.f,\n\tlapack/slacon.f, lapack/slacpy.f, lapack/sladiv.f, lapack/slae2.f,\n\tlapack/slaed6.f, lapack/slaev2.f, lapack/slaexc.f, lapack/slag2.f,\n\tlapack/slahqr.f, lapack/slahr2.f, lapack/slahrd.f,\n\tlapack/slaic1.f, lapack/slaln2.f, lapack/slals0.f,\n\tlapack/slalsa.f, lapack/slalsd.f, lapack/slamc1.f,\n\tlapack/slamc2.f, lapack/slamc3.f, lapack/slamc4.f,\n\tlapack/slamc5.f, lapack/slamch.f, lapack/slamrg.f,\n\tlapack/slange.f, lapack/slanhs.f, lapack/slanst.f,\n\tlapack/slansy.f, lapack/slantr.f, lapack/slanv2.f,\n\tlapack/slapy2.f, lapack/slapy3.f, lapack/slaqp2.f,\n\tlapack/slaqps.f, lapack/slaqr0.f, lapack/slaqr1.f,\n\tlapack/slaqr2.f, lapack/slaqr3.f, lapack/slaqr4.f,\n\tlapack/slaqr5.f, lapack/slarf.f, lapack/slarfb.f, lapack/slarfg.f,\n\tlapack/slarft.f, lapack/slarfx.f, lapack/slartg.f, lapack/slarz.f,\n\tlapack/slarzb.f, lapack/slarzt.f, lapack/slas2.f, lapack/slascl.f,\n\tlapack/slasd0.f, lapack/slasd1.f, lapack/slasd2.f,\n\tlapack/slasd3.f, lapack/slasd4.f, lapack/slasd5.f,\n\tlapack/slasd6.f, lapack/slasd7.f, lapack/slasd8.f,\n\tlapack/slasda.f, lapack/slasdq.f, lapack/slasdt.f,\n\tlapack/slaset.f, lapack/slasq1.f, lapack/slasq2.f,\n\tlapack/slasq3.f, lapack/slasq4.f, lapack/slasq5.f,\n\tlapack/slasq6.f, lapack/slasr.f, lapack/slasrt.f, lapack/slassq.f,\n\tlapack/slasv2.f, lapack/slaswp.f, lapack/slasy2.f,\n\tlapack/slatbs.f, lapack/slatrd.f, lapack/slatrs.f,\n\tlapack/slatrz.f, lapack/slauu2.f, lapack/slauum.f,\n\tlapack/slazq3.f, lapack/slazq4.f, lapack/sorg2l.f,\n\tlapack/sorg2r.f, lapack/sorgbr.f, lapack/sorghr.f,\n\tlapack/sorgl2.f, lapack/sorglq.f, lapack/sorgql.f,\n\tlapack/sorgqr.f, lapack/sorgtr.f, lapack/sorm2r.f,\n\tlapack/sormbr.f, lapack/sorml2.f, lapack/sormlq.f,\n\tlapack/sormqr.f, lapack/sormr3.f, lapack/sormrz.f,\n\tlapack/spbcon.f, lapack/spbtf2.f, lapack/spbtrf.f,\n\tlapack/spbtrs.f, lapack/spocon.f, lapack/spotri.f,\n\tlapack/spotrs.f, lapack/sptsv.f, lapack/spttrf.f, lapack/spttrs.f,\n\tlapack/sptts2.f, lapack/srscl.f, lapack/ssteqr.f, lapack/ssterf.f,\n\tlapack/ssyev.f, lapack/ssytd2.f, lapack/ssytrd.f, lapack/stgevc.f,\n\tlapack/strcon.f, lapack/strevc.f, lapack/strexc.f,\n\tlapack/strsen.f, lapack/strsyl.f, lapack/strti2.f,\n\tlapack/strtri.f, lapack/strtrs.f, lapack/stzrzf.f,\n\tlapack/scsum1.f: New files\n\t* lapack/Makefile.in (FSRC): Add them.\n\n\t* misc/r1mach.f: New file\n\t* misc/machar.cc: Modify to allow to be build twice, once for\n\tdouble precision and once for single precision.\n\t* misc/Makefile.in (FSRC): Add it.\n\t(CEXTRA): Add smachar.c, and target for smachar.o\n\t(MAKEDEPS): Include CEXTRA.\n\n\t* qrupdate/sch1up.f, qrupdate/cch1up.f, qrupdate/sqrinc.f,\n\tqrupdate/cqrinc.f, qrupdate/sqrdec.f, qrupdate/cqrdec.f,\n\tqrupdate/sqrinr.f, qrupdate/cqrinr.f, qrupdate/sqrder.f,\n\tqrupdate/cqrder.f, qrupdate/sqrshc.f, qrupdate/cqrshc.f,\n\tqrupdate/sqr1up.f, qrupdate/cqr1up.f, qrupdate/sch1dn.f,\n\tqrupdate/cch1dn.f, qrupdate/schinx.f, qrupdate/cchinx.f,\n\tqrupdate/schdex.f, qrupdate/cchdex.f, qrupdate/sqrqhu.f,\n\tqrupdate/cqrqhu.f, qrupdate/sqrqhv.f, qrupdate/cqrqhv.f,\n\tqrupdate/sqhqr.f, qrupdate/cqhqr.f: New files.\n\t* qrupdate/Makefile.in (FSRC): Add them.\n\n\t* slatec-fn/acosh.f, slatec-fn/albeta.f, slatec-fn/algams.f,\n\tslatec-fn/alngam.f, slatec-fn/alnrel.f, slatec-fn/asinh.f,\n\tslatec-fn/atanh.f, slatec-fn/betai.f, slatec-fn/csevl.f,\n\tslatec-fn/erf.f, slatec-fn/erfc.f, slatec-fn/gami.f,\n\tslatec-fn/gamit.f, slatec-fn/gamlim.f, slatec-fn/gamma.f,\n\tslatec-fn/gamr.f, slatec-fn/inits.f, slatec-fn/pchim.f,\n\tslatec-fn/pchst.f, slatec-fn/r9gmit.f, slatec-fn/r9lgic.f,\n\tslatec-fn/r9lgit.f, slatec-fn/r9lgmc.f, slatec-fn/xacosh.f,\n\tslatec-fn/xasinh.f, slatec-fn/xatanh.f, slatec-fn/xbetai.f,\n\tslatec-fn/xerf.f, slatec-fn/xerfc.f, slatec-fn/xgamma.f,\n\tslatec-fn/xsgmainc.f: New files.\n\t* slatec-fn/Makefile.in (FSRC): Add them.\n\n2008-04-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* qrupdate/dch1dn.f, qrupdate/dchdex.f, qrupdate/dchinx.f,\n\tqrupdate/dqhqr.f, qrupdate/dqrdec.f, qrupdate/dqrinc.f,\n\tqrupdate/dqrqhu.f, qrupdate/dqrqhv.f, qrupdate/dqrshc.f,\n\tqrupdate/zch1dn.f, qrupdate/zchdex.f, qrupdate/zchinx.f,\n\tqrupdate/zqhqr.f, qrupdate/zqrdec.f, qrupdate/zqrder.f,\n\tqrupdate/zqrinc.f, qrupdate/zqrinr.f, qrupdate/zqrqhu.f,\n\tqrupdate/zqrqhv.f, qrupdate/zqrshc.f:\n\tFix external declarations, XERBLA calls, and docs.\n\n2008-04-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* qrupdate/dqrqhu.f, qrupdate/zqrqhu.f,\n\t* qrupdate/dqrshc.f, qrupdate/zqrshc.f,\n\t* qrupdate/dchinx.f, qrupdate/zchinx.f,\n\t* qrupdate/dchdex.f, qrupdate/zchdex.f: New files.\n\n2008-04-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* blas-xtra/xzdotu.f: Turn into simple wrapper for zdotu.\n\t* blas-xtra/xzdotc.f: Turn into simple wrapper for zdotc.\n\t* qrupdate/zqrqhv.f: Undo previous change.\n\n2008-03-22  David Bateman  <dbateman@free.fr>\n\n\t* qrupdate/dch1up.f: Remove unused external reference to dlartv.\n\n2008-03-18  John W. Eaton  <jwe@octave.org>\n\n\t* qrupdate/zqrqhv.f (zqrqhv): Call xzdotc instead of zdotc.\n\t* blas-xtra/xzdotu.f: Eliminate local zdotu variable.\n\t* blas-xtra/xzdotc.f: New file.\n\t* blas-xtra/Makefile.in (FSRC): Add it to the list.\n\n2008-03-10  John W. Eaton  <jwe@octave.org>\n\n\t* blas/zdrot.f, odepack/dlsode.f, odepack/ewset.f,\n\todepack/intdy.f, fftpack/cffti.f, fftpack/cfftb.f,\n\tfftpack/cfftf.f:\n\tUse (*) instead of (1) for assumed-size dimensions.\n\n2008-03-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* qrupdate/dqrinc.f: Declare DGEMV external.\n\t* qrupdate/zqrinc.f: Declare ZGEMV external.\n\tFix complex constant args in call to ZGEMV.\n\n2008-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* qrupdate/dch1dn.f, qrupdate/zch1dn.f: add \"quick return\" checks.\n\n2008-03-04 Jaroslav Hajek  <highegg@gmail.com>\n\n\t* qrupdate/dch1dn.f, qrupdate/dch1up.f,\n\tqrupdate/zch1dn.f, qrupdate/zch1up.f: New files.\n\t* qrupdate/Makefile.in (FSRC): Add them to the list.\n\n\t* qrupdate/Makefile.in, qrupdate/dqhqr.f, qrupdate/dqr1up.f,\n\tqrupdate/dqrdec.f, qrupdate/dqrder.f, qrupdate/dqrinc.f,\n\tqrupdate/dqrinr.f, qrupdate/dqrqhv.f, qrupdate/zqhqr.f,\n\tqrupdate/zqr1up.f, qrupdate/zqrdec.f, qrupdate/zqrder.f,\n\tqrupdate/zqrinc.f, qrupdate/zqrinr.f, qrupdate/zqrqhv.f:\n\tNew files.\n\t* Makefile.in (CRUFT_DIRS): Add qrupdate to the list.\n\n2008-02-14  John W. Eaton  <jwe@octave.org>\n\n\t* misc/f77-fcn.h (F77_XFCN): Call octave_rethrow_exception here\n\tinstead of checking octave_allocation_error.\n\t* misc/quit.cc (octave_execution_exception): New function.\n\t(octave_rethrow_exception): New function.\n\t(octave_handle_signal): Call octave_rethrow_exception instead of\n\toctave_throw_interrupt_exception.\n\t* misc/quit.h (octave_execution_error): New variable.\n\t(END_INTERRUPT_WITH_EXCEPTIONS): Catch octave_execution_exception.\n\t(octave_execution_exception): New class.\n\t(octave_exception): New enum.\n\t(octave_exception_state): Rename from octave_allocation_error.\n\tChange all uses.\n\n2008-02-12  John W. Eaton  <jwe@octave.org>\n\n\t* lapack-xtra/xilaenv.f: New wrapper for Fortran function ilaenv.\n\t* lapack-xtra/Makefile.in (FSRC): Add it to the list.\n\n2008-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* Makerules.in (%.def : %.f): Use mv instead of move-if-change.\n\n2008-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* misc/Makefile.in: Unconditionally include $(MAKEDEPS).\n\tMark $(MAKEDEPS) as .PHONY targets if omit_deps is true.\n\n2007-12-21  John W. Eaton  <jwe@octave.org>\n\n\tVersion 3.0.0 released.\n\n2007-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* lapack-xtra/xzlange.f: Include complete implementation of ZLANGE\n\tfunction here.\n\n\t* blas-xtra/xzdotu.f: Include complete implementation of ZDOTU\n\tfunction here.\n\n2007-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* lapack/dlals0.f: New file.\n\t* lapack/Makefile.in (FSRC): Add it to the list.\n\n2007-10-26  David Bateman  <dbateman@free.fr>\n\n\t* lapack/dgelsd.f, lapack/dlalsd.f, lapack/dlalsa.f,\n\tlapack/dlasda.f, lapack/dlasdt.f, lapack/dlasdq.f\n\tlapack/dlamrg.f, lapack/dlasd0.f, lapack/dlasd1.f,\n\tlapack/dlasd2.f, lapack/dlasd3.f, lapack/dlasd4.f,\n\tlapack/dlasd5.f, lapack/dlasd6.f, lapack/dlasd7.f,\n\tlapack/dlasd8.f, lapack/dlaed6.f, lapack/zgelsd.f,\n\tlapack/zlalsd.f , lapack/zlalsa.f, lapack/zlals0.f: New files.\n\t* lapack/Makefile.in (FSRC): Include them here.\n\n2007-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* lapack/dgtts2.f, lapack/zgtts2.f: New files.\n\t* lapack/Makefile.in (FSRC): Add them to the list.\n\n2007-10-16  John W. Eaton  <jwe@octave.org>\n\n\t* lapack/dlacn2.f, lapack/dlacn2.f, lapack/dlahr2.f,\n\tlapack/dlahr2.f, lapack/dlaqr0.f, lapack/dlazq3.f,\n\tlapack/dlazq3.f, lapack/dormr3.f, lapack/dormrz.f,\n\tlapack/iparmq.f, lapack/iparmq.f, lapack/zlacn2.f,\n\tlapack/zlahr2.f, lapack/zlaqr0.f: New files.\n\t* lapack/Makefile.in (FSRC): Add them to the list.\n\n\t* lapack: Update all files to current versions from Lapack 3.1.1.\n\n2007-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* Change copyright notices in all files that are part of Octave to\n\tGPLv3 or any later version.\n\n2007-10-03  John W. Eaton  <jwe@octave.org>\n\n\t* mkf77def.in: Combine sed expressions.\n\n2007-09-26  David Bateman  <dbateman@free.fr>\n\n\t* lapack/dgelsy.f,  lapack/dlatrz.f,  lapack/zlarz.f,\n\tlapack/dgeqp3.f,  lapack/dtzrzf.f,  lapack/zlarzt.f,\n\tlapack/dlaic1.f,  lapack/zgelsy.f,  lapack/zlatrz.f,\n\tlapack/dlaqp2.f,  lapack/zgeqp3.f,  lapack/ztzrzf.f,\n\tlapack/dlaqps.f,  lapack/zlaic1.f,  lapack/zunmr3.f,\n\tlapack/dlarzb.f,  lapack/zlaqp2.f,  lapack/zunmrz.f,\n\tlapack/dlarz.f,   lapack/zlaqps.f, lapack/dlarzt.f,\n\tlapack/zlarzb.f: New files\n\t* lapack/Makefile.in (FSRC): Add the new files.\n\n2007-07-25  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in, Makerules.in, fftpack/Makefile.in,\n\trandlib/Makefile.in: Adjust DISTFILES to allow out of tree \"make dist\"\n\tto work.\n\n2007-04-23  John W. Eaton  <jwe@octave.org>\n\n\t* ranlib/phrtsd.f (phrtsd): Store result of call to index\n\tinstrinsic in an INTEGER variable to ensure that the types of the\n\targuments passed to mod really are the same even on 64-bit systems.\n\n2007-04-18  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* blas-xtra/xdnrm2.f, blas-xtra/xdznrm2.f:\n\tDelete spurious semicolons.\n\n2007-04-06  John W. Eaton  <jwe@octave.org>\n\n\t* blas-xtra/xdnrm2.f, blas-xtra/xdznrm2.f: New functions.\n\t* blas-xtra/Makefile.in (FSRC): Add them to the list.\n\n\t* ranlib/phrtsd.f (phrtsd): Ensure that the types of the arguments\n\tpassed to mod are the same even on 64-bit systems.\n\n2007-04-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makefules.in: Handle Fortran, C, and C++ sources with separate\n\tvariables.\n\t* misc/Makefile.in: Use new variables for Fortran, C, and C++ files.\n\t* Makefile.in (clean mostlyclean distclean): No need to remove\n\t$(CRUFT_OBJ) here.\n\n2007-04-04  Rafael Laboissiere  <rafael@debian.org>\n\n\t* Makefile.in (clean): Remove mkf77def.\n\n2007-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makerules.in, Makefile.in (dist): Use ln instead of $(LN_S).\n\n2007-02-26  John W. Eaton  <jwe@octave.org>\n\n\t* misc/Makefile.in (CPICDEP): Also set if CPICFLAG is not defined.\n\t(CXXPICDEP): Also set if CXXPICFLAG is not defined.\n\n2007-02-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in, Makerules.in: Use $(LN_S) instead of ln or ln -s.\n\n2007-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* Makerules.in: Don't use wildcard function to generate source\n\tefile list.\n\t* amos/Makefile.in, blas-xtra/Makefile.in, blas/Makefile.in,\n\tdaspk/Makefile.in, dasrt/Makefile.in, dassl/Makefile.in,\n\tfftpack/Makefile.in, lapack-xtra/Makefile.in, lapack/Makefile.in,\n\tminpack/Makefile.in, misc/Makefile.in, odepack/Makefile.in,\n\tordered-qz/Makefile.in, quadpack/Makefile.in, ranlib/Makefile.in,\n\tslatec-err/Makefile.in, slatec-fn/Makefile.in, villad/Makefile.in:\n\tExplicitly list source files.\n\n2007-01-24  Alexander Barth  <abarth@marine.usf.edu>\n\n\t* misc/f77-fcn.h (F77_CSTRING): Call OCTAVE_LOCAL_BUFFER with cs,\n\tnot F77_CHAR_ARG_USE (s).\n\n2006-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makerules.in (%.def : %.f): Use $(simple-move-if-change-rule) here.\n\n2006-11-03  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DLL_CXXDEFS): Rename from XTRA_CXXDEFS.\n\t(DLL_CDEFS): Rename from XTRA_CDEFS.\n\tSubstitute CRUFT_DLL_DEFS, not XTRA_CRUFT_DEFS.\n\t(XTRA_CRUFT_SH_LDFLAGS): Rename from XTRA_CRUFT_LINK_DEPS.\n\tAdd $(XTRA_CRUFT_SH_LDFLAGS) to SH_LDFLAGS instead of to LINK_DEPS.\n\n2006-10-31  John W. Eaton  <jwe@octave.org>\n\n\t* misc/Makefile.in (INCLUDES): Add oct-dlldefs.h to the list.\n\n2006-10-29  John W. Eaton  <jwe@octave.org>\n\n\t* misc/Makefile.in (SPECIAL_INCLUDE): Add oct-dlldefs.h to the list.\n\n2006-10-28  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* misc/quit.h: Undefine min and max after including windows.h.\n\n2006-10-27  John W. Eaton  <jwe@octave.org>\n\n\t* misc/oct-dlldefs.h: New file.\n\n\t* mkf77def.in: Downcase all input to simplify matching.\n\tMatch only lines beginning with whitespace.\n\tMatch function return types.\n\tUse literal TAB characters instead of \\t in sed patterns.\n\tFrom Michael Goffioul <michael.goffioul@swing.be>.\n\n2006-10-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in (XTRA_CRUFT_LINK_DEPS): Substitute.\n\t(CRUFT_DEFS): New variable.\n\t(LINK_DEPS): Include $(XTRA_CRUFT_LINK_DEPS) in the list.\n\t(clean, mostlyclean, distclean): Delete cruft.def.\n\t(cruft.def): New target.\n\t(libraries): Depend on cruft.def.\n\n\t* misc/f77-fcn.h (f77_exception_encountered, xstopx):\n\tTag with CRUFT_API.\n\t* misc/lo-error.h (current_liboctave_error_handler,\n\tcurrent_liboctave_warning_handler,\n\tcurrent_liboctave_warning_with_id_handler,\n\tset_liboctave_error_handler, set_liboctave_warning_handler,\n\tset_liboctave_warning_with_id_handler): Likewise.\n\t* misc/quit.h (w32_sigint_init, w32_raise_final,\n\tw32_raise, w32_in_main_thread, current_context,\n\toctave_save_current_context, octave_restore_current_context,\n\toctave_jump_to_enclosing_context, octave_save_signal_mask,\n\toctave_restore_signal_mask, octave_interrupt_immediately,\n\toctave_interrupt_state, octave_allocation_error,\n\toctave_signal_caught, octave_handle_signal,\n\toctave_throw_interrupt_exception, octave_throw_bad_alloc,\n\toctave_signal_hook, octave_interrupt_hook, octave_bad_alloc_hook):\n\tLikewise.\n\n2006-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in ($(CRUFT_DEFS)): Depend on $(SUBDIRS).\n\t(cruft.def): Depend on $(CRUFT_DEFS).\n\t(libraries): Depend on cruft.def only.\n\n\t* mk77def.in: New script template\n\t* Makefile.in (DISTFILES): Include mk77def.in in the list.\n\t($(SUBDIRS)): Depend on mk77def.\n\t(mk77def): New target.\n\t(CRUFT_DEFS): New variable.\n\t* Makerules.in (CRUFT_FSRC, CRUFT_CSRC, CRUFT_CXXSRC): New variables.\n\t(CRUFT_SRC): Define using $(CRUFT_FSRC), $(CRUFT_CSRC), and\n\t$(CRUFT_CXXSRC).\n\t(CRUFT_DEFS): New variable.\n\t($(CRUFT_DEFS)): Depend on $(TOPDIR)/libcruft/mkf77def.\n\t(%.def : %.f): New pattern rule.  Use mkf77def script to do\n\tFortran name mangling.\n\t(clean, mostlyclean, distclean): Delete $(CRUFT_DEFS).\n\t(all): Depend on $(CRUFT_DEFS)\n\tPartially from Michael Goffioul  <michael.goffioul@swing.be>.\n\n2006-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* Makerules.in (XTRA_CDEFS, XTRA_CXXDEFS): Substitute here.\n\n2006-10-23  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* misc/f77-fcn.h (F77_CHAR_ARG_DEF, F77_CONST_CHAR_ARG_DEF,\n\tF77_CHAR_ARG_LEN_DEF, F77_CHAR_ARG_USE, F77_CHAR_ARG_LEN_USE,\n\tF77_CSTRING): New macros to handle passing C character strings to\n\tFortran.\n\n2006-10-17  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* lapack-xtra/xdlamch.f: Begin lines with spaces, not tabs.\n\n\t* misc/Makefile.in (machar.o, pic/machar.o): Specify output file\n\tname in compile command.\n\n2006-10-13  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in: Adapt rules to use $(LIBPRE).\n\n2006-09-11  John W. Eaton  <jwe@octave.org>\n\n\t* blas-xtra/xddot.f, blas-xtra/xzdotu.f: New files.\n\n2006-06-01  David Bateman  <dbateman@free.fr>\n\n\t* slatec-fn/dpchim.f, slatec-fn/dpchst.f: New files.\n\n2006-05-22  John W. Eaton  <jwe@octave.org>\n\n\t* lapack/dlantr.f, lapack/zlantr.f: New files.\n\n2006-05-03  David Bateman  <dbateman@free.fr>\n\n\t* lapack/dpocon.f, lapack/zpocon.f, lapack/dpotrs.f,\n\tlapack/zpotrs.f, lapack/dtrcon.f, lapack/ztrcon.f,\n\tlapack/dtrtrs.f, lapack/ztrtrs.f: New files.\n\n2006-04-29  John W. Eaton  <jwe@octave.org>\n\n\t* misc/lo-error.c (set_liboctave_warning_with_id_handler,\n\tliboctave_warning_with_id): New functions.\n\t(current_liboctave_warning_with_id_handler): New variable.\n\t* misc/lo-error.h (liboctave_warning_with_id_handler): New typedef.\n\t(current_liboctave_warning_with_id_handler, liboctave_warning_with_id\n\tset_liboctave_warning_with_id_handler): Provide decls.\n\n2006-04-18  John W. Eaton  <jwe@octave.org>\n\n\t* misc/f77-fcn.h (F77_XFCN): Move decls to beginning of blocks for C.\n\n2006-04-13  John W. Eaton  <jwe@octave.org>\n\n\t* misc/quit.h BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1,\n\tEND_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE): Omit unnecessary casts.\n\t* misc/f77-fcn.h (F77_XFCN, F77_CHAR_ARG_LEN): Likewise.\n\n2006-04-03  David Bateman  <dbateman@free.fr>\n\n\t* ranlib/wrap.f (dgenexp, dgengam, dignpoi): New functions.\n\n2006-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* misc/f77-fcn.h (F77_XFCN): Save octave_interrupt_immediately and\n\trestore it if an exception occurs that causes a longjmp.\n\n2005-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* ranlib/ignbin.f, ranlib/ignpoi.f: Avoid arithmetic IF statements.\n\n2005-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* lapack/Makefile.in (dlamc1.o pic/dlamc1.o):\n\tAdd $(F77_FLOAT_STORE_FLAG) to FFLAGS.\n\n2005-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* misc/machar.c: Restore test code.\n\n2005-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* misc/quit.h Rename all win32_ symbols to w32.  Change all uses.\n\n2005-09-15  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (LN_S): Change to DESTDIR before LN_S to avoid\n\tlack of symlinks under mingw.\n\t* misc/cquit.c (w32_thread_setjmp_mutex, win32_signal_context,\n\twin32_signal_to_raise, win32_main_thread_id, win32_main_thread,\n\twin32_restore_thread): New static variables.\n\t(win32_in_main_thread): Returns 1 if in main thread for win32.\n\t(win32_reset_context): Reset context (longjmp style) for win32.\n\t(win32_raise_in_main): Raise signal in main thread for win32.\n\t(win32_raise): Raise signal for win32.\n\t(win32_raise_final): Clean up win32 signalling.\n\t(win32_sigint_init): Initialize win32 signalling.\n\t* quit.h (win32_sigint_init, win32_raise_final, win32_raise,\n\twin32_in_main_thread): Declaration.\n\n2005-09-14  Daniel  <durbano@shbano.com>\n\n\t* lapack/zbdsqr.f: Fix typo in docs.\n\tFrom Jorge Barros de Abreu <ficmatin01@solar.com.br>.\n\n2005-05-06  John W. Eaton  <jwe@octave.org>\n\n\t* lapack/dpotri.f, lapack/dlauum.f, lapack/dlauu2.f,\n\tlapack/zpotri.f, lapack/zlauum.f, lapack/zlauu2.f: New files.\n\n2005-04-08  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in, Makerules.in (clean, distclean, maintainer-clean):\n\tAvoid duplication in rules.\n\n2005-03-17  Andy Adler  <adler@site.uottawa.ca>\n\n\t* Makerules.in (install-strip): Include double-colon target here too.\n\n2005-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (bin-dist): Delete target.\n\t(BINDISTLIBS, BINDISTFILES): Delete variables.\n\n2005-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (CRUFT_DIRS): Remove it from the list.\n\t* odessa: Delete directory.\n\n\t* misc/machar.c (rmachar): Declare local REAL variables volatile.\n\n2005-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* blas/zher.f: New file.\n\n\tSparse merge.\n\n\t2005-01-13 David Bateman  <dbateman@free.fr>\n\n\t* lapack/dgttrf.f lapack/dgttrs.f lapacl/zgttrf.f lapack/zgttrs.f:\n\tnew files\n\n\t2005-01-23  David Bateman  <dbateman@free.fr>\n\n\t* lapack/dgtsv.f lapack/dpbcon.f lapack/dpbtf2.f lapack/dpbtrf.f\n\tlapack/dpbtrs.f lapack/dptsv.f lapack/dpttrf.f lapack/dpttrs.f\n\tlapack/dptts2.f lapack/zgtsv.f lapack/zpbcon.f lapack/zpbtf2.f\n\tlapack/zpbtrf.f lapack/zpbtrs.f lapack/zptsv.f lapack/zpttrf.f\n\tlapack/zpttrs.f lapck/zptts2.f: New files.\n\n\t2004-12-29  John W. Eaton  <jwe@octave.org>\n\n\t* blas/zbtsv.f: New file.\n\t* lapack/dgbcon.f, lapack/dgbtrf.f, lapack/dgbtrs.f,\n\tlapack/dlatbs.f, lapack/zgbcon.f, lapack/zgbtf2.f,\n\tlapack/zgbtrf.f, lapack/zgbtrs.f, lapack/zlatbs.f: New files.\n\n2005-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* misc/cquit.c (octave_signal_caught): New global variable.\n\t* misc/quit.cc (occtave_handle_signal): New function.\n\t(octave_signal_hook): New global pointer.\n\t* misc/quit.h: Provide decls.\n\t(OCTAVE_QUIT): Check octave_signal_caught, not\n\toctave_interrupt_state, and call octave_handle_signal, not\n\toctave_throw_interrupt_exception.\n\n2005-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* misc/quit.h: Use C-style comments.\n\n2004-09-08  John W. Eaton  <jwe@octave.org>\n\n\t* misc/machar.c (rmachar): Use modern C declaration.\n\n2004-02-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/f77-fcn.c: Handle Cray, CVF, and f2c calling conventions.\n\n\t* misc/f77-fcn.h (xstopx): Use F77_CHAR_ARG_DECL and\n\tF77_CHAR_ARG_LEN_DECL in declaration.\n\n2004-02-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/quit.h (OCTAVE_QUIT): Set octave_interrupt_state to -1\n\twhile we are handling interrupts.\n\n2004-02-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (LINK_DEPS): Always define.\n\n2003-11-12  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/machar.c (machar) [CRAY]: Kluge to make it work.\n\n2003-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* odepack/dlsode.f: Rename from odepack/lsode.f.\n\t* odepack/dlsode.f (DLSODE): Rename from LSODE to avoid name\n\tconflict with LSODE class constructors on systems that upcase\n\tFortran names.\n\n\t* odessa/dodessa.f: Rename from odessa/odessa.f.\n\t* odessa/dodessa.f (DODESSA): Rename from ODESSA to avoid name\n\tconflict with ODESSA class constructors on systems that upcase\n\tFortran names.\n\n2003-10-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (MISC_OBJ): Add misc/cquit.o to the list.\n\n\t* misc/Makefile.in (SPECIAL_SRC): Add cquit.c to the list.\n\t* misc/cquit.c: New file.\n\t* misc/quit.cc: Move everything except octave_interrupt_hook,\n\toctave_bad_alloc_hook, octave_throw_interrupt_exception, and\n\toctave_throw_bad_alloc to cquit.c.\n\n2003-10-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/quit.h (octave_interrupt_hook, octave_bad_alloc_hook):\n\tMove declarations outside of extern \"C\" block.\n\n2003-10-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/f77-fcn.h: Only use inline if this is C++.\n\n\t* misc/f77-fcn.c (xstopx): Return type is now F77_RET_T.\n\tUse F77_RETURN.\n\t* misc/machar.c (machar): Likewise.\n\n\t* misc/f77-fcn.h (F77_CHAR_ARG, F77_CONST_CHAR_ARG, F77_CHAR_ARG2,\n\tF77_CONST_CHAR_ARG2, F77_CXX_STRING_ARG, F77_CHAR_ARG_LEN,\n\tF77_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL, F77_CHAR_ARG_LEN_DECL,\n\tF77_RET_T, F77_RETURN): New macros.\n\t[F77_USES_CRAY_CALLING_CONVENTION]: New data conversion functions.\n\n\t* misc/quit.h (octave_interrupt_hook, octave_bad_alloc_hook):\n\tMove function pointer declarations inside __cplusplus section.\n\n2003-07-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-lib): Use $(INSTALL), not\n\t$(INSTALL_PROGRAM) for $(SHLLIB) files.\n\n2003-07-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (CLEAN_SUBDIRS): New variable.\n\t(clean mostlyclean distclean maintainer-clean): Use it to ensure\n\tcleaning in all subdirs, not just those we build in.\n\n\t* Makerules.in (maintainer-clean, distclean): Don't use\n\tdependencies on double colon rules.\n\t(distclean): Also remove *.d, *.a, *.o, pic/*.o, pic, and stmp-pic.\n\t(maintainer-clean): Also remove *.d, *.a, *.o, pic/*.o, pic, and\n\tstmp-pic, and Makefile.\n\n\t* Makefile.in (maintainer-clean, distclean): Also remove *.$(SHLEXT).\n\n2003-06-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dasrt/ddasrt.f (DDASRT): Print correct message for invalid MXSTP.\n\n\t* dassl/ddassl.f (DDASSL): Handle MXSTP as in DASRT.\n\n\t* dassl/ddajac.f (DDAJAC): LIPVT is now 22.\n\t* dassl/ddassl.f (DDASSL): Likewise.\n\t* dassl/ddaslv.f (DDASLV): Likewise.\n\n\t* misc/quit.h (octave_interrupt_hook, octave_bad_alloc_hook):\n\tNew function pointers.\n\t* misc/quit.cc: Initialize them.\n\t(octave_throw_interrupt_exception): If octave_interrupt_hook is\n\tset, call it.\n\t(octave_throw_bad_alloc): Likewise, for octave_bad_alloc_hook.\n\n\t* dasrt/ddasrt.f (DDASRT): Set LMXSTP to 21 and LIPVT to 22 to\n\tavoid conflict with LLAST in DRCHECK.  Change docs for INFO(12)\n\tand LIW.\n\n2003-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in, misc/Makefile.in: Handle DESTDIR.\n\n2003-02-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* blas/sgemm.f, blas/strsm.f, blas/ssyrk.f, blas/sscal.f,\n\tblas/sgemv.f, blas/sdot.f: New files.\n\n2003-02-20  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* dassl/ddaslv.f: Fortran doesn't use ; in statements.\n\n2003-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* blas/dtbsv.f: New file.\n\t* lapack/dlatrs.f, lapack/dtrti2.f, lapack/dtrtri.f, lapack/ztrti2.f,\n\tlapack/ztrtri.f: New files.\n\n2003-02-04  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (CRUFT_DIRS): Remove linpack from list.\n\n\t* linpackdgbfa.f, linpackdgbsl.f, linpackdgeco.f, linpackdgedi.f,\n\tlinpackdgefa.f, linpackdgesl.f, linpackspofa.f, linpackzgeco.f,\n\tlinpackzgedi.f, linpackzgefa.f, linpackzgesl.f: Delete.\n\n\t* dassl/ddajac.f, dassl/ddaslv.f:  Use DGxTRF and\n\tDGxTRS instead of DGxFA and DGxSL.\n\t* daspk/ddaspk.f, daspk/dmatd.f, daspk/dslvd.f: Likewise.\n\t* odepack/lsode.f, odepack/prepj.f, odepack/solsy.f: Likewise.\n\t* odessa/odessa.f, odessa/odessa_prepj.f, odessa/odessa_solsy.f:\n\tLikewise.\n\t* libcrudt/ranlib/setgmn.f: Use SPOTRF instead of SPOFA.\n\n\t* lapack/dgbtf2.f, lapack/dgbtrf.f, lapack/dgbtrs.f,\n\tlapack/dgecon.f, lapack/dgetri.f, lapack/spotf2.f,\n\tlapack/spotrf.f, lapack/zgecon.f, lapack/zgetri.f: New files.\n\n2003-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/quit.h (BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1,\n\tBEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2): New macros.\n\n2003-01-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* odessa/odessa_rscom.f (ODESSA_RSCOM): Fix apparent typo (LODE2\n\tshould probably be LIODE2).\n\n\t* Makerules.in (clean, mostlyclean): Also remove *.d.\n\n\t* misc/quit.cc: Add std:: qualifiers to memcpy calls.\n\n2003-01-03  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* misc/quit.h: Move #include <new> outside extern \"C\" block.\n\t* misc/f77-fcn.h: Move #include \"quit.h\" outside extern \"C\" block.\n\n2002-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/quit.h (BEGIN_INTERRUPT_WITH_EXCEPTIONS,\n\tEND_INTERRUPT_WITH_EXCEPTIONS): Only define for C++ source.\n\tInclude <new> for C++ source.\n\n2002-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/quit.h, misc/quit.cc [! USE_EXCEPTIONS_FOR_INTERRUPTS]):\n\tAlways use exceptions for handling interrupts.\n\t(BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE):\n\n\t* misc/quit.h (OCTAVE_TRY_WITH_INTERRUPTS, OCTAVE_THROW_BAD_ALLOC,\n\tOCTAVE_CATCH_INTERRUPTS, SAVE_OCTAVE_INTERRUPT_IMMEDIATELY,\n\tINCREMENT_OCTAVE_INTERRUPT_IMMEDIATELY, OCTAVE_THROW_TO_TOP_LEVEL,\n\tDECREMENT_OCTAVE_INTERRUPT_IMMEDIATELY, OCTAVE_JUMP_TO_TOP_LEVEL,\n\tSET_OCTAVE_INTERRUPT_IMMEDIATELY): Replace all uses with\n\tdefinitions, delete macros.\n\n2002-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/quit.cc (octave_allocation_error): New variable.\n\t(octave_throw_bad_alloc): New function.\n\t* misc/quit.h: Provide decls.\n\t(OCTAVE_THROW_BAD_ALLOC): New macro.\n\t(END_INTERRUPT_WITH_EXCEPTIONS): Also catch bad_alloc.\n\t* misc/f77-fcn.h (F77_XFCN): Handle allocation errors.\n\n\t* misc/quit.h (octave_jmp_buf): New typedef.\n\t(current_context): Type is now octave_jmp_buf.\n\t(octave_set_current_context): Use sigsetjmp if we have it.\n\t(octave_interrupt_immediately, octave_interrupt_state): Type is\n\tnow sig_atomic_t.\n\t(BEGIN_INTERRUPT_WITH_EXCEPTIONS, END_INTERRUPT_WITH_EXCEPTIONS):\n\tNew macros.\n\n\t* misc/quit.cc (octave_jump_to_enclosing_context): Use siglongjmp\n\tif we have it.\n\t(octave_save_current_context, octave_restore_current_context): Use\n\toctave_jmp_buf type here.\n\n2002-11-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in: Handle automatic dependency generation for\n\tC/C++ source files.\n\n\t* misc/quit.h (INCREMENT_OCTAVE_INTERRUPT_IMMEDIATELY,\n\tDECREMENT_OCTAVE_INTERRUPT_IMMEDIATELY,\n\tSET_OCTAVE_INTERRUPT_IMMEDIATELY): New macros.\n\t(BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE,\n\tBEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE): Use them.\n\t* f77-fcn.h (F77_XFCN): Likewise.\n\n\t* misc/quit.cc: Include <cstring> for memcpy decl.\n\n2002-11-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/f77-fcn.h (F77_XFCN): Adapt to new signal/exception\n\thandling scheme.\n\t(f77_context): Delete decl.\n\t(copy_f77_context): Likewise.\n\t* misc/f77-fcn.cn (copy_f77_context): Delete.\n\t(Fxstopx): Set f77_exception_encountered.\n\tUse octave_jump_to_enclosing_context, not longjmp.\n\n\t* misc/f77-extern.cc (f77_context): Delete definition.\n\n\t* misc/quit.h, misc/quit.cc: New files.\n\t* misc/Makefile: Add them to the appropriate lists.\n\n\t* Makefile (MISC_OBJ): Add misc/quit.o\n\n2002-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* odessa/odessa.f (ODESSA): Second arg of xerrwd is string length.\n\t* odessa/odessa_intdy.f (ODESSA_INTDY): Likewise.\n\n2002-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dasrt/ddasrt.f (DDASRT): Fix computation of LENRW.\n\n2002-10-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install): Don't bother with versions for $(SHLBIN)\n\tfiles.\n\n\t* slatec-err/xerrwd.f (XERRWD): Print msg(1:nmes), not just msg.\n\n2002-10-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install): No need to use cd to create links.\n\n2002-10-14  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Makefile.in: Use link dependencies for shared libs if\n\tINCLUDE_LINK_DEPS.\n\t(LIBRARIES): If doing shared libs, include versioned library in\tlist.\n\t(libcruft.$(SHLEXT), libcruft.$(SHLEXT_VER)): Reverse actions --\n\tbuild unversioned library, symbolic link adds version info.\n\t(install, uninstall): Handle link and load forms of the library\n\tseparately.\n\n2002-09-30  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* slatec-fn/xdacosh.f: Mark external functions as external.\n\t* slatec-fn/xdasinh.f: Ditto.\n\t* slatec-fn/xdatanh.f: Ditto.\n\t* slatec-fn/xdbetai.f: Ditto.\n\t* slatec-fn/xderf.f: Ditto.\n\t* slatec-fn/xderfc.f: Ditto.\n\t* slatec-fn/xdgami.f: Ditto.\n\t* slatec-fn/xdgamit.f: Ditto.\n\t* slatec-fn/xdgamma.f: Ditto.\n\t* slatec-fn/xgmainc.f: Ditto.\n\n2002-08-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* odessa/odessa.f (ODESSA): Use XERRWD instead of XERR.\n\t* odessa/intdy.f (ODESSA_INTDY): Likewise.\n\t* odessa_rscom.f (ODESSA_RSCOM): Delete unused common block EH0001.\n\t* odessa_svcom.f (ODESSA_SVCOM): Likewise.\n\n\t* dasrt/xerrwv.f, odepack/xerrwv.f: Delete.\n\t* slatec-err/xerrwd.f (XERRWD): Call XSTOPX instead of using STOP.\n\n\t* quadpack/dqagi.f (DQAGI): Replace Hollerith constants with\n\tcharacter string constants.\n\t* quadpack/dqagp.f (DQAGP): Likewise.\n\t* odepack/lsode.f (LSODE): Likewise.\n\n\t* odepack/lsode.f (LSODE): Use XERRWD instead of XERRWV.\n\t* odepack/intdy.f (INTDY): Likewise.\n\t* dasrt/ddasrt.f (DDASRT): Likewise.\n\t* quadpack/xerror.f (XERROR): Likewise.\n\n2002-07-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* slatec-fn/xgmainc.f: New file.\n\n2002-07-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dasrt: New subdirectory.\n\t* Makefile.in (CRUFT_DIRS): Add it to the list.\n\n2002-07-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* odessa: New subdirectory.\n\t* Makefile.in (CRUFT_DIRS): Add it to the list.\n\n2002-06-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* slatec-err/xermsg.f (XERMSG): If MAXMES .LT. 0, messages may be\n\tprinted an unlimited number of times.\n\t* slatec-err/j4save.f (J4SAVE) Default for MAXMES is now -1.\n\n\t* misc/f77-fcn.c (xstopx): Pass args in proper order.\n\n2002-05-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ordered-qz/dsubsp.f (DSUBSP): Delete decl for unused variable J.\n\n\t* misc/f77-fcn.c (xstopx): Return type is void, not volatile void.\n\t* misc/f77-fcn.h (xstopx): Provide decl.  Add special gcc noreturn\n\tattribute here.\n\n2002-05-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/f77-fcn.h: Define F77_FCN for backward compatibility.\n\n2002-04-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* slatec-err/ixsav.f, slatec-err/xerrwd.f: New files.\n\n\t* daspk: New directory.\n\t* Makefile.in (CRUFT_DIRS): Add it to the list\n\n2002-04-03  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\t* misc/machar.c: Use F77_FUNC instead of checking\n\tF77_APPEND_UNDERSCORE.\n\t* misc/f77-fcn.h: Don't define F77_FCN.\n\t(xSTRINGIZE, STRINGIZE): New macros.\n\t(F77_XFCN_ERROR): Simplify by using STRINGIZE and F77_FUNC.\n\t(F77_XFCN): Use F77_FUNC instead of F77_FCN.\n\t* misc/f77-fcn.c: Use F77_FUNC instead of F77_FCN.\n\n2001-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DISTSUBDIRS): Add fftpack.\n\n2001-08-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lapack/dlasq3.f: Update from netlib.\n\t* lapack/dlasq5.f: Ditto.\n\n2001-05-02  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* Makefile.in (CRUFT_DIRS): Substitute @FFT_DIR@.\n\n2001-04-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install): Don't use mk-libdir-link.\n\n2001-04-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in (CPICDEP): Remove pic/dostop.o from the list.\n\n2001-03-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/xstopx.f: Delete.\n\t* misc/dostop.c: Delete.\n\t* misc/Makefile.in (SPECIAL, SPECIAL_DEPEND): Delete dostop.c and\n\tdostop.o from lists.\n\t* Makefile.in (MISC_OBJ): Delete misc/dostop.o from the list.\n\n\t* misc/dostop.c (dostop): Use F77_FCN macro for function definition.\n\tSpecify length in error format to avoid need for copying string.\n\tFrom Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>.\n\n2000-12-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lapack/dgelss.f (DGELSS): Use correct leading dimension for\n\tworkspace array passed to dgemm and dlacpy.\n\t(ZGELSS): Likewise, for calls to zgemm and zlacpy.\n\n2000-07-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DISTSUBDIRS): New macro.\n\t(dist): Use it instead of SUBDIRS.\n\n2000-06-30  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\t* blas-xtra, lapack-xtra: New directories.\n\t* Makefile.in (CRUFT_DIRS): Add them to the list.\n\tSubstitute @BLAS_DIR@ and @LAPACK_DIR@ here.\n\t* blas-xtra/xerbla.f: Move here from blas subdirectory.\n\t* blas-xtra/Makefile.in: New file.\n\t* lapack-xtra/xdlamch.f, lapack-xtra/xdlange.f,\n\tlapack-xtra/xzlange.f: Move here from lapack subdirectory.\n\t* lapack-xtra/Makefile.in: New file.\n\n2000-04-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in (install, uninstall): Include files go in\n\t$(octincludedir)/octave, not just $(octincludedir).\n\n2000-03-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (LIBRARIES): Conditionally define.\n\t(libraries): Depend on $(SUBDIRS) only.\n\tMake $(LIBRARIES) using a recursive invocation of make once\n\t$(SUBDIRS) are up to date.\n\t(.NOTPARALLEL): New target, for GNU Make 3.79.\n\n2000-03-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (libcruft.$(LIBEXT)): New target.\n\t(all): Depend on `libraries', not `$(SUBDIRS) shared-lib'.\n\tConditionally construct `libraries' target.\n\t(libcruft.$(SHLEXT_VER)): Delete target before rebuilding.\n\t* Makerules.in (LIBCRUFT): Delete variable.\n\t(LIBCRUFT_DEPEND): Conditionally define to $(LIBCRUFT_OBJS) only.\n\t(all): Print warning if anything is done.\n\t(stmp-pic): New target.\n\t($CRUFT_PICOBJ): Depend on stmp-pic.\n\t(clean, mostlyclean): Remove pic and stmp-pic.\n\n2000-02-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lapack/dbdsqr.f, lapack/dgeesv.f, lapack/dgelss.f,\n\tlapack/dgesvd.f, lapack/dlasq1.f, lapack/dlasq2.f,\n\tlapack/dlasq3.f, lapack/dlasq3.f, lapack/dlasq4.f,\n\tlapack/dlasq5.f, lapack/dlasq6.f, lapack/zbdsqr.f,\n\tlapack/zgelss.f, lapack/zgesvd.f, lapack/zhetd2.f:\n\tUpdate from netlib.\n\n1999-11-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Update to Lapack version 3.0.\n\t* lapack/ieeeck.f, lapack/dlasq2.f, lapack/dlasq3.f,\n\tlapack/dlasq5.f, lapack/dlasq6.f: New files.\n\n1999-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/lo-error.cc (current_liboctave_warning_handler): Define\there.\n\t(set_liboctave_warning_handler): New function.\n\t(liboctave_warning): Ditto.\n\t* misc/lo-error.h: Provide declararations for them here.\n\n1999-10-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (dist): Use `$(MAKE) -C dir' instead of `cd dir;\n\t$(MAKE); cd ..'.\n\n1999-10-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dassl/dpotrf.f, dassl/dpotf2.f: Move to lapack subdirectory.\n\nFri Mar 26 01:19:04 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makerules.in (all): Don't try to use a special rule for making\n\tthe archive.  The default rules may be slower, but they are also\n\tcorrect.\n\nWed Nov 11 17:27:35 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (CRUFT_DIRS): Add amos.  Delete specfun.\n\t* specfun: Delete directory.\n\t* amos: New directory\n\nThu Oct 15 00:43:13 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ranlib: Update to newer version of randlib.\n\t* ranlib/Makefile.in (SPECIAL): Update list.\n\nThu Sep 24 11:59:02 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* balgen, eispack: Delete directories and unnecesary files.\n\t* Makefile.in (CRUFT_DIRS): Delete eispack and balgen from the list.\n\n\t* lapack/xdlamch.f: New file.\n\n\t* ordered-qz: New directory.\n\t* Makefile.in (CRUFT_DIRS): Add it to the list.\n\n\t* lapack/dggbak.f, lapack/dtgevc.f, lapack/zggbal.f: New files.\n\nTue Jun  2 09:57:52 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/rybesl.f (rybesl): Don't access by(2) unless nb .gt. 1.\n\nMon May 11 12:33:42 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* fftpack/passb3.f, fftpack/passb5.f, fftpack/passf3.f,\n\tfftpack/passf5.f: Use double precision constants in data\n\tstatements.\n\nTue Apr 14 14:01:22 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* slatec-fn/xdgamit.f (xdgamit): New file.\n\nMon Apr  6 00:26:35 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* slatec-fn/xdgami.f (xdgami): Reorder args to match dgami.\n\nThu Feb 19 21:00:00 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/ribesl.f, specfun/rjbesl.f: Compute NSIG correctly.\n\tAdd missing comma in declaration statement.\n\nSun Feb  1 12:39:10 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install, uninstall): Use $(octlibdir), not $(libdir).\n\tUse $(mk-libdir-link).\n\n\t* quadpack/dqagi.f, quadpack/dqagie.f, quadpack/dqagp.f,\n\tquadpack/dqagpe.f, quadpack/dqk15i.f, quadpack/dqk21.f:\n\tMake user-supplied code a subroutine instead of a function.\n\nMon Jan 19 23:11:21 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lapack/xdlange.f, lapack/xzlange.f: New files.\n\nMon Dec  1 00:51:03 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dassl/xerhlt.f, dassl/xermsg.f, dassl/xerprn.f, dassl/xgetua.f,\n\tdassl/xsetua.f: Delete.\n\n\t* slatec-err: New directory.\n\t* Makefile.in: Add it to the list.\n\nSun Nov 30 17:55:20 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* slatec-fn/xdgami.f, slatec-fn/xdbetai.f, slatec-fn/xderfc.f,\n\tslatec-fn/xderf.f, slatec-fn/xdatanh.f, slatec-fn/xdasinh.f,\n\tslatec-fn/xdacosh.f: New files.\n\nSat Nov 29 13:02:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/ribesl.f (ribesl): Use d1mach to get machine parameters.\n\tSAVE static data between calls.  Use PARAMETERS where possible.\n\t* specfun/rjbesl.f (rjbesl): Likewise.\n\t* specfun/rkbesl.f (rkbesl): Likewise.\n\t* specfun/rybesl.f (rybesl): Likewise.\n\nFri Nov 28 14:05:12 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun: New subdirectory.\n\t* specfun/Makefile.in, specfun/ribesl.f, specfun/rjbesl.f,\n\tspecfun/rkbesl.f, specfun/rybesl.f: New files.\n\t* Makefile.in (CRUFT_DIRS): Add specfun.\n\nWed Nov 26 01:49:47 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* slatec-fn/d9gmit.f, slatec-fn/d9lgic.f, slatec-fn/d9lgit.f,\n\tslatec-fn/dbetai.f, slatec-fn/dgami.f, slatec-fn/dgamit.f,\n\tslatec-fn/dgamr.f, slatec-fn/dlbeta.f, slatec-fn/dlnrel.f:\n\tNew files for incomplete beta and incomplete gamma functions.\n\nThu Jul 17 13:18:57 1997  Klaus Gebhardt  <gebhardt@crunch.ikp.physik.th-darmstadt.de>\n\n\t* blas/xerbla.f (xerbla): Call XSTOPX instead of using STOP.\n\nFri Jun  6 16:49:22 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* slatec-fn/xdgamma.f: New file.\n\n\t* fsqp, npsol, qpsol: Delete directories.\n\t* Makefile.in (CRUFT_DIRS): Delete fsqp, npsol, and qpsol from list.\n\nThu Jun  5 01:40:36 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in, Makerules.in: Make building of static library optional.\n\t(liboctave.$(SHLEXT_VER)): Add $(SONAME_FLAGS) to command.\n\n\t* Makerules.in (stamp-picdir): Delete.\n\t(pic): New target.  Don't worry so much about creating pic\n\tdirectory only when it is really needed.\n\n\t* Makefile.in (stamp-shared): Delete.\n\t(shared-lib): New target.  Depend on shared libraries directly.\n\nWed May 21 16:29:42 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in (install): Ensure include directory link is made.\n\t(uninstall): Delete all installed files.\n\nThu Mar 13 22:31:35 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* blas, lapack: Add new files for symmetric eigenvalue\n\tcomputation.\n\nWed Mar 12 16:59:59 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in (install-strip): New target.\n\n\t* Makefile.in (install-strip): New target.\n\nMon Mar  3 15:38:39 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ranlib/Makefile.in (EXTERNAL_DISTFILES): Add Basegen.doc.\n\n\t* fftpack/Makefile.in (EXTERNAL_DISTFILES): Add fftpack.doc.\n\n\t* Makefile.in (DISTFILES): Add configure.in.\n\nSat Mar  1 15:23:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.5 released.\n\nWed Feb 26 12:08:39 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (maintainer-clean): Also remove configure.\n\nThu Feb 20 02:58:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.4 released.\n\nTue Feb 18 09:22:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.3 released.\n\nFri Feb 14 16:23:42 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (bin-dist): Don't write empty strings to LIBRARIES.\n\nThu Feb 13 17:33:41 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (stamp-shared): Use $(SH_LD) $(SH_LDFLAGS) instead\n\tof $(CXX) -shared.\n\n\t* Makerules.in (stamp-picdir): Silence noise about making pic.\n\nMon Jan 27 15:52:29 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.2 released.\n\nSat Jan 25 22:34:10 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in, balgen/Makefile.in, blas/Makefile.in,\n\tcfsqp/Makefile.in, dassl/Makefile.in, eispack/Makefile.in,\n\tfftpack/Makefile.in, fsqp/Makefile.in, lapack/Makefile.in,\n\tlinpack/Makefile.in, minpack/Makefile.in, misc/Makefile.in,\n\tnpsol/Makefile.in, odepack/Makefile.in, qpsol/Makefile.in,\n\tquadpack/Makefile.in, ranlib/Makefile.in, slatec-fn/Makefile.in,\n\tvillad/Makefile.in (bin-dist): New target.\n\nWed Jan 22 15:03:33 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in (pic/machar.o): Add $(CPICFLAG) for this target.\n\n\t* misc/d1mach.f (d1mach): Move SAVE statement ahead of DATA statment.\n\nWed Jan 15 21:04:29 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* blas/*.f: Update to latest version from Netlib.\n\nTue Jan  7 00:17:17 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.1 released.\n\nTue Dec 17 11:02:02 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/lo-error.c: Convert C++-style comments to C-style comments.\n\nWed Dec 11 01:50:31 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in (SPECIAL_DEPEND): Delete d1mach.o from the list.\n\nTue Dec 10 01:43:10 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0 released.\n\nFri Dec  6 15:23:50 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.94.\n\nWed Nov 20 01:00:43 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in (install): Also install lo-error.h.\n\n\t* Makefile.in (MISC_OBJ): Add misc/f77-fcn.o.\n\n\t* misc/lo-error.h: New file, moved here from liboctave.\n\t* misc/lo-error.c: Rename from lo-error.cc.  Make this a C-file\n\tinstead of C++.\n\n\t* Version 1.93.\n\nTue Nov 19 23:04:24 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in: Add variables for installing things.\n\n\t* Makerules.in (install, uninstall): Make these double colon rules.\n\n\t* f77-fcn.c, f77-fcn.h: New files, from liboctave.\n\n\t* misc/Makefile.in (SPECIAL_DEPEND): Add f77-fcn.o.\n\t(SPECIAL): Add f77-fcn.c and f77-fcn.h.\n\t(CPICDEP): Add pic/f77-fcn.o.\n\t(install): Install f77-fcn.h in $(octincludedir).\n\t(uninstall): Delete f77-fcn.h from $(octincludedir).\n\n\t* Makerules.in (CRUFT_CSRC): Delete unsed variable.\n\nThu Nov 14 00:07:00 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.92.\n\nFri Nov  8 09:55:40 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (libcruft.a): Delete target.\n\t* Makerules.in, Makefile.in: Use real archive rules to build\n\tlibcruft.a in parts.\n\n\t* Makefile.in (install): Use $(INSTALL_PROGRAM) for installing\n\tshared library.\n\nThu Nov  7 12:43:17 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Add -lm when building shared library.\n\n\t* Version 1.91.\n\nMon Nov  4 10:09:00 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lapack/dlag2.f, lapack/dggbal.f, lapack/dgghrd.f, lapack/dhgeqz.f:\n\tNew files.\n\n\t* Makefile.in (install): Use INSTALL_PROGRAM for shared version of\n\tlibcruft.\n\nSun Nov  3 19:37:37 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in (distclean): Delete target, since there is\n\tnothing special to do.\n\nWed Oct 30 17:20:14 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.90.\n\n\t* Makefile.in (DISTFILES): Add ChangeLog.\n\n\t* misc/Makefile.in: Make pic/machar.o using special rule.\n\tUse CPPFLAGS, not CPP_FLAGS.\n\nThu Oct 24 20:22:47 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (CRUFT_OBJ): No special treatment for d1mach.o.\n\n\t* misc/machar.c, misc/d1mach.f: New files\n\t* misc/Makefile.in: Fix to not generate d1mach.f.\n\nMon Oct 14 11:07:25 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (distclean): Remove stamp-shared too.\n\nSat Oct 12 00:20:41 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (maintainer-clean): Don't depend on distclean.\n\t* Makerules.in (maintainer-clean): Ditto.\n\nTue Aug 20 22:09:08 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makerules.in (stamp-picdir): Only create a pic subdirectory if\n\tSHARED_LIBS is true AND FPICFLAG is not empty.\n\nWed May 22 15:07:00 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (stamp-shared): Use CC, not CXX to create shared\n\tlibrary.  Also use SHARED_FLIBS here instead of FLIBS.\n\nSat Apr  6 21:28:47 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makerules.in (clean, mostlyclean): Also remove pic/*.o.\n\t(maintainer-clean, distclean): Also remove stamp-picdir and pic\n\tdirectory.\n\nWed Apr  3 01:01:31 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/Makefile.in: Set SPECIAL_PICDEPEND after including Makeconf\n\tand before including Makerules.\n\nFri Mar 29 13:45:06 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (distclean): Delete so_locations, which is created\n\ton DEC Alpha systems.\n\t(distclean, maintainer-clean): Don't depend on clean.\n\nWed Mar 27 05:59:02 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makerules.in: Add rules for making PIC code here.\n\t* Makefile.in (libcruft.a): Depend on $(CRUFT_PICOBJ)\n\t* misc/Makefile.in: Add rules for making PIC code from C and C++\n\tfiles.\n\nFri Feb  9 21:04:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/f77-extern.cc, misc/lo-error.cc: New files.\n\t* misc/Makefile.in (SPECIAL, SPECIAL_DEPEND): Add them to the lists.\n\t* Makefile.in (CRUFT_OBJ): Add it f77-extern.o and lo-error.o here\n\ttoo.\n\nSat Feb  3 07:57:39 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/dostop.c (dostop): Call error handler if we have a message.\n\tCall longjmp on f77_context, not jump_to_top_level().\n\t* misc/xstopx.f (xstopx): Pass non-blank strings on to dostop.\n\nMon Jan  8 22:55:26 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (clean): If $(SHARED_LIBS), remove shared libs.\n\t(mostlyclean): Ditto.\n\nFri Dec 29 21:43:24 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in, Makerules.in: Handle creating position independent\n\tcode and shared libraries for Octave.\n\nTue Dec 26 00:15:31 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makerules.in (stamp-picdir): New target.\n\t(all): Depend on it.\n\n\t* Makefile.in: Delete references to configure stuff.\n\t* configure.in, mkinstalldirs: Delete.\n\nSun Dec 24 02:42:29 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linpack/spofa.f: New file.\n\t* blas/level-1/sdot.f: New file.\n\t* blas/level-2/dsyr.f: New file.\n\nThu Dec 14 02:34:19 1995  Rick Niles  <niles@axp745.gsfc.nasa.gov>\n\n\t* fftpack/cfftb1.f, fftpack/cfftf1.f, fftpack/cffti1.f,\n\todepack/prepj.f, odepack/solsy.f, odepack/stode.f:\n\tAvoid warnings for nonstandard dimension statements of the form\n\t`real foo(1)' by using `real foo(*)' instead.\n\nMon Nov  6 07:24:03 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/dostop.c: Only call jump_to_top_level() if OCTAVE_SOURCE.\n\nFri Nov  3 11:08:31 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* misc/dostop.c: Just call jump_to_top_level() directly here.\n\nWed Sep 20 00:01:03 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkinstalldirs: New file.\n\t* Makefile.in (DISTFILES): Add it to the list.\n\n\t* Makerules.in: Fix cleaning rules.  Use double colon so we can\n\tadd things in the makefiles in the subdirectories.\n\n\t* Makefile.in (DISTFILES): Distribute configure.in and configure.\n\t(distclean): Also remove Makerules, config.log, and config.status.\n\t(maintainer-clean): Depend on distclean.\n\nMon Apr 10 09:55:13 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: New file.\n\nFri Mar 10 10:38:29 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makefile.in (install uninstall clean mostlyclean distclean\n\trealclean): Use SUBDIR_FOR_COMMAND.  Combine actions.\n\nSee ChangeLog.1 in the top level directory for earlier changes.\n"
  },
  {
    "path": "etc/OLD-ChangeLogs/liboctave-ChangeLog",
    "content": "2011-04-12  Rik  <octave@nomad.inbox5.com>\n\n\t* LSODE.cc: Add semicolon to error messages to prevent run-together text.\n\n2011-04-01  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* MatrixType (MatrixType::operator =): Plug memory leak due to\n\timproper handling of perm array (bug #32804).\n\n2011-03-29  Rik  <octave@nomad.inbox5.com>\n\n\t* Array.cc (diag): Treat empty vector (1x0 or 0x1) as valid input.\n\tImproves Matlab compatibility (bug #32901).\n\n2011-02-13  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-perm-op-defs.h (template <typename SM>\n\tSM octinternal_do_mul_colpm_sm (const octave_idx_type *,\n\tconst SM&)): Ensure that the row indices are sorted.\n\n2011-03-14  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::alloc) Change std::copy_backward to\n\tstd::copy, since the destination is at the back and not the\n\tfront. Bug #32747, cf. entry from 2010-11-25\n\n2011-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* oct-alloc.h: Include <cstddef>.\n\tFrom Orion Poplawski <orion@cora.nwra.com>.\n\n2011-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* PermMatrix.cc (operator*): Fix mixed row/column permutation\n\tcase.  Bug #32346.\n\n2011-02-04  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Undo accidental checkin\n\n2011-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-hist.cc (gnu_history::do_process_histcontrol):\n\tRename from command_history::do_process_histcontrol.\n\t(gnu_history::do_histcontrol): Rename from\n\tcommand_history::do_histcontrol.\n\t* cmd-hist.h (command_history::do_histcontrol): Provide dummy version.\n\t* cmd-hist.cc (command_history::do_process_histcontrol): Likewise.\n\tBug #32325.\n\n2011-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* Range.cc (Range::Range (double, double, octave_idx_type)):\n\tCorrectly compute limit from base, increment and number of\n\telements.  Bug #32321.\n\n2011-01-31  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (Sparse<T>::assign (const idx_vector&, const idx_vector&,\n\tconst Sparse<T>&)): Handle case of LHS originally empty, and\n\twith non-colon indices.  Fix typo in previous change.  Bug #32263.\n\n2011-01-30  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* lo-sysdep.cc (opendir): On error, free allocated DIR object\n\tbefore returning.\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* eigs-base.cc: Remove #endif corresponding to \"#ifdef HAVE_ARPACK\",\n\tnot the one that matched \"#if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL)\".\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* eigs-base.cc (EigsRealNonSymmetricFunc,\n\tEigsRealNonSymmetricMatrix, EigsRealNonSymmetricMatrixShift):\n\tInitialize eig_vec2 to 0 before calling dneupd.\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* eigs-base.cc: Assume we have ARPACK.\n\n2011-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (Sparse<T>::assign (const idx_vector&, const idx_vector&,\n\tconst Sparse<T>&)): Allow 0x0 LHS with colon dimensions to\n\tinherit dimensions from RHS.  Fix tests.  Bug #32263.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-refcount.h: Strip trailing whitespace.\n\n2011-01-24  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* SparseQR.h (class SparseQR::SparseQR_reps): Disallow copying.\n\t* Array.cc (class rec_permute_helper, class rec_index_helper,\n\tclass  rec_resize_helper): Likewise.\n\t* cmd-edit.cc (class default_command_editor): Likewise.\n\n2011-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-refcount.h: New source.\n\t* Makefile.am: Add it here.\n\n\t* Array.h: Use octave_refcount for refcounting.\n\t* Sparse.h: Ditto.\n\t* SparseCmplxQR.h: Ditto.\n\t* SparseQR.h: Ditto.\n\t* idx-vector.h: Ditto.\n\t* oct-shlib.h: Ditto.\n\t* sparse-base-chol.h: Ditto.\n\n2011-01-21  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* oct-fftw.h (class octave_fftw_planner): Disallow copying\n\t(class octave_float_fftw_planner): Likewise.\n\t* oct-sort.h (class octave_sort): Likewise.\n\t(struct oct_sort::MergeState): Likewise.\n\t* SparseCmplxQR.h (class SparseComplexQR::SparseComplexQR_rep):\n\tLikewise.\n\t* sparse-base-chol.h (class sparse_base_cho::sparse_base_chol_rep):\n\tLikewise.\n\n2011-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc (xgemm): Initialize output matrix for call to ZHERK.\n\t* fCMatrix.cc (xgemm): Initialize output matrix for call to CHERK.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* Array-b.cc, Array-d.cc, Array-f.cc, Array-util.cc,\n\tArray-util.h, Array.cc, Array.h, Array3.h, CColVector.cc,\n\tCColVector.h, CDiagMatrix.cc, CDiagMatrix.h, CMatrix.cc,\n\tCMatrix.h, CNDArray.cc, CNDArray.h, CSparse.cc, CSparse.h,\n\tCmplxAEPBAL.cc, CmplxAEPBAL.h, CmplxCHOL.cc, CmplxGEPBAL.cc,\n\tCmplxGEPBAL.h, CmplxHESS.cc, CmplxLU.h, CmplxQR.cc, CmplxQR.h,\n\tCmplxSCHUR.cc, CmplxSVD.h, CollocWt.cc, CollocWt.h, DASPK.cc,\n\tDASPK.h, DASRT.cc, DASRT.h, DASSL.cc, DASSL.h, DET.h,\n\tDiagArray2.h, EIG.cc, LSODE.cc, MArray.cc, MArray.h,\n\tMDiagArray2.cc, MDiagArray2.h, MSparse.cc, MSparse.h,\n\tMatrixType.cc, MatrixType.h, ODESFunc.h, PermMatrix.cc,\n\tPermMatrix.h, Quad.cc, Range.cc, Sparse.cc, Sparse.h,\n\tSparseCmplxCHOL.cc, SparseCmplxCHOL.h, SparseCmplxLU.cc,\n\tSparseCmplxLU.h, SparseCmplxQR.cc, SparseCmplxQR.h, SparseQR.cc,\n\tSparseQR.h, SparsedbleCHOL.cc, SparsedbleCHOL.h,\n\tSparsedbleLU.cc, SparsedbleLU.h, base-aepbal.h, base-de.h,\n\tbase-lu.cc, base-lu.h, boolNDArray.cc, boolNDArray.h,\n\tboolSparse.cc, boolSparse.h, bsxfun-defs.cc, chMatrix.cc,\n\tchNDArray.cc, chNDArray.h, cmd-edit.cc, cmd-edit.h, cmd-hist.cc,\n\tdColVector.h, dDiagMatrix.cc, dDiagMatrix.h, dMatrix.cc,\n\tdMatrix.h, dNDArray.cc, dNDArray.h, dSparse.cc, dSparse.h,\n\tdbleAEPBAL.h, dbleCHOL.cc, dbleCHOL.h, dbleGEPBAL.cc,\n\tdbleGEPBAL.h, dbleQR.cc, dbleQR.h, dbleSCHUR.h, dbleSVD.h,\n\tdim-vector.cc, dim-vector.h, dir-ops.cc, eigs-base.cc,\n\tf2c-main.c, fCColVector.cc, fCColVector.h, fCDiagMatrix.cc,\n\tfCDiagMatrix.h, fCMatrix.cc, fCMatrix.h, fCNDArray.cc,\n\tfCNDArray.h, fCRowVector.cc, fCRowVector.h, fCmplxAEPBAL.cc,\n\tfCmplxAEPBAL.h, fCmplxCHOL.cc, fCmplxGEPBAL.cc, fCmplxGEPBAL.h,\n\tfCmplxHESS.cc, fCmplxLU.h, fCmplxQR.cc, fCmplxQR.h,\n\tfCmplxQRP.cc, fCmplxSCHUR.cc, fCmplxSVD.h, fColVector.h,\n\tfDiagMatrix.cc, fDiagMatrix.h, fEIG.cc, fMatrix.cc, fMatrix.h,\n\tfNDArray.cc, fNDArray.h, file-ops.cc, file-stat.cc,\n\tfloatAEPBAL.cc, floatAEPBAL.h, floatCHOL.cc, floatCHOL.h,\n\tfloatGEPBAL.cc, floatGEPBAL.h, floatLU.h, floatQR.cc, floatQR.h,\n\tfloatQRP.cc, floatSCHUR.h, floatSVD.h, idx-vector.cc,\n\tidx-vector.h, intNDArray.cc, intNDArray.h, kpse.cc,\n\tlo-array-gripes.cc, lo-array-gripes.h, lo-cieee.c, lo-ieee.h,\n\tlo-mappers.cc, lo-mappers.h, lo-specfun.cc, mx-defs.h,\n\tmx-inlines.cc, oct-binmap.h, oct-convn.cc, oct-env.cc,\n\toct-fftw.cc, oct-fftw.h, oct-glob.cc, oct-group.h,\n\toct-inttypes.cc, oct-inttypes.h, oct-locbuf.cc, oct-locbuf.h,\n\toct-md5.cc, oct-mem.h, oct-norm.cc, oct-norm.h, oct-rand.cc,\n\toct-rand.h, oct-rl-hist.c, oct-shlib.cc, oct-shlib.h,\n\toct-sort.cc, oct-sort.h, oct-spparms.cc, oct-spparms.h,\n\toct-syscalls.cc, oct-time.cc, randgamma.c, randmtzig.c,\n\trandmtzig.h, randpoisson.c, regex-match.cc, regex-match.h,\n\tsparse-base-chol.cc, sparse-base-chol.h, sparse-base-lu.cc,\n\tsparse-base-lu.h, sparse-dmsolve.cc, sparse-sort.cc,\n\tsparse-sort.h, sparse-util.h, tempname.c:\n\tStrip trailing whitespace.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* Array.h, Array.cc\n\t(Array<T>::resize2 (octave_idx_type, octave_idx_type, const T&)):\n\tNew private function.\n\t(Array<T>::resize (octave_idx_type, octave_idx_type, const T&)):\n\tDeprecate.  Call resize2 to do the work.  Remove all uses from\n\tOctave.\n\n\t* CMatrix.h (ComplexMatrix::resize (octave_idx_type,\n\toctave_idx_type, const Complex&)): New function.\n\t* dMatrix.h (Matrix::resize (octave_idx_type,\n\toctave_idx_type, double)): New function.\n\t* fCMatrix.h (FloatComplexMatrix::resize (octave_idx_type,\n\toctave_idx_type, const FloatComplex&)): New function.\n\t* fMatrix.h (FloatMatrix::resize (octave_idx_type,\n\toctave_idx_type, const float)): New function.\n\n2011-01-20  David Bateman  <dbateman@free.fr>\n\n\t* Sparce.cc (template <class T> Sparse<T>::Sparse (const Array<T>&,\n\tconst idx_vector&, const idx_vector&, octave_idx_type,\n\toctave_idx_type, bool, octave_idx_type): Fix off by one error in the\n\tconstruction of sparse column vectors. Fix indexing issue in\n\tconstruction of sparse row vectors.\n\t* boolSparse.cc (SparseBoolMatrix SparseBoolMatrix::any (int) const):\n\tFully initialize cidx for any called on the first dimension.\n\n2011-01-19  John W. Eaton  <jwe@octave.org>\n\n\t* Array.h (explicit Array (octave_idx_type, const T&)):\n\tRestore constructor, but mark as deprecated.\n\t(explicit Array (octave_idx_type, octave_idx_type)): Delete.\n\t(Array (const Array<T>&, octave_idx_type, octave_idx_type)): Delete.\n\tFix all uses in Octave.\n\t* Array3.h: Deprecate header file.  Remove all uses from Octave.\n\n2011-01-19  John W. Eaton  <jwe@octave.org>\n\n\t* file-stat.cc (mode_as_string): Declare buffer as an array of\n\t12 characters, not 11.  Don't set buf[10] to '\\0'; strmode\n\tNUL-terminates the array.\n\n2011-01-14  David Grundberg  <individ@acc.umu.se>\n\n\t* SparseQR.cc (SparseQR_rep::SparseQR_rep) [HAVE_CXSPARSE]:\n\tMake initialization list depend on macro. Fixes compile error when\n\tmacro isn't defined.\n\t* SparseCmplxQR.cc (SparseComplexQR_rep::SparseComplexQR_rep)\n\t[HAVE_CXSPARSE]: Ditto.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.cc (xfloor): Move function body here from\n\tlo-mappers.h to avoid exposing gnulib:: in a header file.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* file-stat.cc (mode_as_string): Call strmode instead of mode_string.\n\n\t* filemode.h, filemode.c: Delete.\n\t* Makefile.am (INCS): Remove filemode.h from the list.\n\t(LIBOCTAVE_C_SOURCES): Remove filemode.c from the list.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* Update copyright notices for 2011.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* CColVector.cc, CMatrix.cc, CRowVector.cc, CSparse.cc,\n\tCmplxAEPBAL.cc, CmplxCHOL.cc, CmplxLU.cc, CmplxQR.cc,\n\tCmplxQRP.cc, EIG.cc, Quad.cc, dColVector.cc, dMatrix.cc,\n\tdRowVector.cc, dSparse.cc, dbleAEPBAL.cc, dbleCHOL.cc,\n\tdbleLU.cc, dbleQR.cc, dbleQRP.cc, eigs-base.cc, fCColVector.cc,\n\tfCMatrix.cc, fCNDArray.cc, fCRowVector.cc, fCmplxAEPBAL.cc,\n\tfCmplxCHOL.cc, fCmplxLU.cc, fCmplxQR.cc, fCmplxQRP.cc,\n\tfCmplxSVD.cc, fColVector.cc, fEIG.cc, fMatrix.cc, fNDArray.cc,\n\tfRowVector.cc, floatAEPBAL.cc, floatCHOL.cc, floatLU.cc,\n\tfloatQR.cc, floatQRP.cc, lo-specfun.cc, oct-convn.cc:\n\tStyle fixes.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc (get_blas_trans_arg): Return char, not char *.\n\tChange all uses.\n\t* dMatrix.cc (get_blas_trans_arg): Likewise.\n\t* fCMatrix.cc (get_blas_trans_arg): Likewise.\n\t* fMatrix.cc (get_blas_trans_arg): Likewise.\n\tSuggested by Pascal Dupuis <Pascal.Dupuis@worldonline.be>.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* filemode.c: Use prototypes for function definitions.  Reorder\n\tfunctions to eliminate need for forward declarations.\n\t* filemode.h: New file.\n\t* file-stat.cc: Include filemode.h instead of using local extern\n\tdeclarations.\n\t* Makefile.am (INCS): Add filemode.h to the list.\n\n\t* lo-cutils.h: New file.\n\t(octave_qsort, octave_strcasecmp, octave_strncasecmp,\n\toctave_w32_library_search, octave_waitpid): Move decls here from\n\tlo-utils.h.\n\t* Makefile.am (INCS): Add lo-cutils.h to the list.\n\t* lo-utils.h: Include cutils.h.\n\t* lo-cutils.c: Include cutils.h.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* SparseCmplxQR.cc\n\t(SparseComplexQR::SparseComplexQR_rep::SparseComplexQR_rep):\n\tCorrect order of member initialization.\n\t* SparseQR.cc (SparseQR::SparseQR_rep::SparseQR_rep): Likewise.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* oct-fftw.cc (octave_fftw_planner::octave_fftw_planner,\n\toctave_float_fftw_planner::octave_float_fftw_planner):\n\tAvoid duplicate initializations.  Correctly initialize RN to\n\tempty dim_vector.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (Sparse::Sparse): Initialize all data members in\n\tinitialization lists.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (rec_permute_helper::rec_permute_helper,\n\trec_index_helper::rec_index_helper,\n\trec_resize_helper::rec_resize_helper): Initialize all data\n\tmembers in initialization lists.\n\n\t* Array.h, Array.cc (Array::Array): Initialize slice_data and\n\tslice_len in memeber initialization lists.\n\t(Array::~Array): Now virtual.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* oct-locbuf.h (octave_chunk_buffer::~octave_chunk_buffer):\n\tNow virtual.\n\t(class octave_local_buffer, class octave_chunk_buffer):\n\tDon't allow copying or assignment.\n\n\t* file-stat.h (base_file_stat::~base_file_stat):\n\tNow protected and virtual.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* base-lu.h (base_lu::base_lu): Initialize all data members in\n\tinitialization lists.\n\t* base-qr.h (base_qr::base_qr): Likewise.\n\t* DET.h (base_det::base_det): Likewise.\n\t* sparse-base-lu.h (sparse_base_lu::sparse_base_lu): Likewise.\n\t* sparse-base-chol.h (sparse_base_chol::sparse_base_chol): Likewise.\n\n\t* base-lu.h (base_lu::~base_lu): Explicitly define virtual destrutor.\n\t* base-qr.h (base_qr::~base_qr): Likewise.\n\t* base-aepbal.h (base_aepbal::~base_aepval): Likewise.\n\t* sparse-base-lu.h (sparse_base_lu::~sparse_base_lu): Likewise.\n\t* sparse-base-chol.h (sparse_base_chol::~sparse_base_chol): Likewise.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* DAE.h (DAE::~DAE): Now virtual.\n\t* DAERT.h (DAERT::~DAERT): Likewise.\n\t* ODE.h (ODE::~ODE): Likewise.\n\t* DAEFunc.h (DAEFunc::~DAEFunc): Likewise.\n\t* DAERTFunc.h (DAEFunc::~DAEFunc): Likewise.\n\t* ODEFunc.h (ODE::~ODE): Likewise.\n\t* ODESFunc.h (ODESFunc::~ODESFunc): Likewise.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* idx-vector.h (idx_vector_rep::idx_vector_rep,\n\tidx_vector::idx_mask_rep::idx_mask_rep):\n\tInitialize all data members in initialization lists.\n\n\t* idx-vector.cc (idx_vector::idx_scalar_rep::idx_scalar_rep):\n\tInitialize data in member initialization list.\n\t(class idx_base_rep, class idx_colon_rep, class idx_range_rep,\n\tclass idx_scalar_rep, class idx_vector_rep, class idx_mask_rep):\n\tDon't allow assignment.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* LSODE.h (class LSODE): Delete pointer data members.\n\t(LSODE::LSODE): Initialize all data members in initialization lists.\n\t* LSODE.cc (LSODE::integrate): Extract pointers to data from\n\tarray data members at each call.\n\n\t* DASPK.h (class DASPK): Delete pointer data members.\n\t(DASPK::DASPK): Initialize all data members in initialization lists.\n\t* DASPK.cc (DASPK::integrate): Extract pointers to data from\n\tarray data members at each call.\n\n\t* DASSL.h (class DASSL): Delete pointer data members.\n\t(DASSL::DASSL): Initialize all data members in initialization lists.\n\t* DASSL.cc (DASSL::integrate): Extract pointers to data from\n\tarray data members at each call.\n\n\t* DASRT.h (class DASRT): Delete pointer data members.\n\t(DASRT::DASRT): Initialize all data members in initialization lists.\n\t* DASRT.cc (DASRT::integrate): Extract pointers to data from\n\tarray data members at each call.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* kpse.cc (struct str_llist_elt, struct cache_entry):\n\tExplicitly define constructor and destructor.\n\n\t* Quad.h (Quad::Quad, IndefQuad::IndefQuad,\n\tFloatIndefQuad::FloatIndefQuad): Initialize all data members in\n\tinitialization lists.\n\t* CollocWt.h (CollocWt::CollocWt): Likewise.\n\t* oct-time.h (octave_strptime::octave_strptime): Likewise.\n\t* oct-time.cc (octave_time::octave_time): Likewise.\n\t* pathsearch.h (dir_path::dir_path): Likewise.\n\t* regex-match.h (regex_match::regex_match): Likewise.\n\t* oct-sort.h (octave_sort::MergeState::MergeState): Likewise.\n\t* oct-shlib.h, oct-shlib.cc (octave_shlib::shlib_rep::shlib_rep,\n\toctave_shlib::octave_shlib): Likewise.\n\t* oct-mutex.h, oct-mutex.cc (octave_mutex::octave_mutex): Likewise.\n\t* MatrixType.cc (MatrixType::MatrixType): Likewise.\n\t* oct-fftw.cc (octave_fftw_planner::octave_fftw_planner,\n\toctave_float_fftw_planner::octave_float_fftw_planner): Likewise.\n\n\t* mach-info.h, mach-info.cc (oct_mach_info::oct_mach_info):\n\tInitialize all data members in initialization lists.\n\t(ten_little_endians): Rename from oct_mach_info::ten_little_endians.\n\tNow static instead of private member function\n\t(get_float_format): Rename from oct_mach_info::init_float_format.\n\tNow static instead of private member function.\n\n\t* dir-ops.h, dir-ops.cc (dir_entry::copy): Delete.\n\t(dir_entry::dir_entry): Initialize all data members in\n\tinitialization lists.\n\t(dir_entry::operator =): Copy elements directly here instead of\n\tcalling copy.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-hist.h, cmd-hist.cc: Sprinkle with const.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* CmplxCHOL.h (ComplexCHOL::ComplexCHOL): Initialize all data\n\tmembers in constructor initialization lists.\n\t* CmplxGEPBAL.h (ComplexGEPBALANCE::ComplexGEPBALANCE): Likewise.\n\t* CmplxHESS.h (ComplexHESS::ComplexHESS): Likewise.\n\t* CmplxSCHUR.h, CmplxSCHUR.cc (ComplexSCHUR::ComplexSCHUR): Likewise.\n\t* CmplxSVD.h (ComplexSVD::ComplexSVD): Likewise.\n\t* DET.h (base_det::base_det): Likewise.\n\t* EIG.h (EIG::EIG): Likewise.\n\t* SparseCmplxQR.cc\n\t(SparseComplexQR::SparseComplexQR_rep::SparseComplexQR_rep):\n\tLikewise.\n\t* SparseQR.cc (SparseQR::SparseQR_rep::SparseQR_rep): Likewise.\n\t* dbleCHOL.h (CHOL::CHOL): Likewise.\n\t* dbleGEPBAL.h (GEPBALANCE::GEPBALANCE): Likewise.\n\t* dbleHESS.h (HESS::HESS): Likewise.\n\t* dbleSCHUR.h, dbleSCHUR.cc (SCHUR::SCHUR): Likewise.\n\t* dbleSVD.h (SVD::SVD): Likewise.\n\t* fCmplxCHOL.h (FloatComplexCHOL::FloatComplexCHOL): Likewise.\n\t* fCmplxGEPBAL.h\n\t(FloatComplexGEPBALANCE::FloatComplexGEPBALANCE): Likewise.\n\t* fCmplxHESS.h (FloatComplexHESS::FloatComplexHESS): Likewise.\n\t* fCmplxSCHUR.h, fCmplxSCHUR.cc\n\t(FloatComplexSCHUR::FloatComplexSCHUR): Likewise.\n\t* fCmplxSVD.h (FloatComplexSVD::FloatComplexSVD):\n\tLikewise.\n\t* fEIG.h (FloatEIG::FloatEIG): Likewise.\n\t* floatCHOL.h (FloatCHOL::FloatCHOL): Likewise.\n\t* floatGEPBAL.h (FloatGEPBALANCE::FloatGEPBALANCE): Likewise.\n\t* floatHESS.h (FloatHESS::FloatHESS): Likewise.\n\t* floatSCHUR.h, floatSCHUR.cc (FloatSCHUR::FloatSCHUR): Likewise.\n\t* floatSVD.h (FloatSVD::FloatSVD): Likewise.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* LSODE.cc, DASSL.cc, DASRT.cc, DASPK.cc, CmplxSVD.cc,\n\tCmplxSCHUR.cc, CmplxHESS.cc, CmplxGEPBAL.cc, CmplxCHOL.cc,\n\tEIG.cc, dbleCHOL.cc, dbleGEPBAL.cc, dbleHESS.cc, dbleSCHUR.cc,\n\tdbleSVD.cc, fCmplxCHOL.cc, fCmplxGEPBAL.cc, fCmplxHESS.cc,\n\tfCmplxSCHUR.cc, fCmplxSVD.cc, fEIG.cc, floatCHOL.cc,\n\tfloatGEPBAL.cc, floatHESS.cc, floatSCHUR.cc, floatSVD.cc:\n\tStyle fixes.\n\n2011-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* oct-rl-hist.c (hc_erasedups): Avoid GCC warning.\n\n2011-01-12  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* oct-rl-hist.h: Replace macros with an enum\n\n2011-01-12  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\t    John W. Eaton  <jwe@octave.org>\n\n\t* cmd-hist.cc (command_history::process_histcontrol,\n\tcommand_history::hist_control, command_history::process_histcontrol,\n\tcommand_history::hist_control): New functions.\n\t(command_history::initialize, command_history::do_initialize):\n\tNew arg, control_arg.\n\t* cmd-hist.cc (gnu_history::do_add): Pass history_control to\n\toctave_add_history.\n\t* cmd-hist.h (command_history::process_histcontrol,\n\tcommand_history::hist_control, command_history::process_histcontrol,\n\tcommand_history::hist_control): Provide decls.\n\t(command_history::history_control): New data member.\n\n\t* oct-rl-hist.c (octave_add_history): New arg, history_control.\n\tReturn int, not void.\n\t(check_history_control, hc_erasedups): New static functions\n\tborrowed from Bash.\n\t* oct-rl-hist.h (octave_add_history): Fix decl.\n\t(HC_IGNSPACE, HC_IGNDUPS, HC_ERASEDUPS): New #defined constants.\n\n2011-01-06  John W. Eaton  <jwe@octave.org>\n\n\t* oct-md5.cc (oct_md5_file): Tag call to fclose with gnulib::.\n\t* Range.cc (tfloor): Tag calls to floor with gnulib::.\n\t* lo-mappers.h (xfloor): Tag call to floor with gnulib::\n\n2010-12-20  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.h (xrem, xmod): Declare temporary result from\n\tmultiplication volatile.\n\n2010-12-15  John W. Eaton  <jwe@octave.org>\n\n\tBug #31883.\n\n\t* cmd-hist.cc (command_history::do_clean_up_and_save,\n\tcommand_history::do_truncate_file,\n\tcommand_history::do_append, command_history::do_write,\n\tgnu_history::do_clean_up_and_save, gnu_history::do_truncate_file,\n\tgnu_history::do_append, gnu_history::do_write,\n\tgnu_history::do_read_range):\n\tDon't do anything if not initialized.\n\n\t* cmd-hist.cc, cmd-hist.h (command_history::initialize,\n\tcommand_history::is_initialized): New static functions.\n\t(command_history::do_initialize,\n\tcommand_history::do_is_initialized): New member functions.\n\n\t* cmd-hist.h (command_history::initialized): New data member.\n\t(comand_history::command_history): Initialize it.\n\n2010-12-14  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.h (xcopysign (double)): Call copysign, not copysignf.\n\t(xmod): Call X_NINT, not D_NINT.  Call xfloor, not floor.\n\tBug #31872.\n\n2010-12-13  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc (operator * (const Matrix& m, const ComplexMatrix&\ta)):\n\tFix cut and paste error.  Bug #31869.\n\n2010-12-09  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* lo-specfun.cc (xgamma): Also handle negative integer values as\n\tspecial cases when using tgamma.  Bug #31772.\n\n2010-11-25  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (Sparse<T>::assign): Use correct endpoint for\n\tdestination range when making room for new elements.\n\tBug #31734.\n\n2010-11-23  John W. Eaton  <jwe@octave.org>\n\n\t* oct-md5.cc (oct_md5_result_to_str): Avoid buffer overrun in\n\tcall to sprintf.  Replace loop with a single call to sprintf.\n\tBug #31689.\n\n2010-11-23  John W. Eaton  <jwe@octave.org>\n\n\t* oct-md5.cc (oct_md5_file): Close file after reading.\n\n2010-11-22  John W. Eaton  <jwe@octave.org>\n\n\t* boolSparse.cc (SparseBoolMatrix::sum, SparseBoolMatrix::any):\n\tCast integer idx_vector argument to octave_idx_type.\n\n2010-11-18  John W. Eaton  <jwe@octave.org>\n\n\t* chMatrix.cc (charMatrix::row_as_string): Never strip trailing\n\tnul characters.  Bug #31689.\n\n2010-11-12  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (LIBOCTAVE_SOURCES): Delete variable.\n\t(liboctave_la_SOURCES): Include $(LIBOCTAVE_CXX_SOURCES) and\n\t$(LIBOCTAVE_C_SOURCES) in this list instead of\n\t$(LIBOCTAVE_SOURCES).\n\t(nodist_liboctave_la_SOURCES): New variable.\n\t(octinclude_HEADERS): Don't include $(BUILT_INCS) in the list.\n\t(noinst_octinclude_HEADERS): New variable.\n\t(PRIVATE_INCS): Delete variable.\n\t(INCS): Include oct-glob.h in the list.\n\t(liboctave_la_SOURCES): Don't include $(PRIVATE_INCS) in the\n\tlist.\n\t(LIBOCT_PATHSEARCH_CXX_SOURCES, LIBOCT_PATHSEARCH_C_SOURCES,\n\tLIBOCT_PATHSEARCH_SOURCES): Delete variables.\n\t(LIBOCTAVE_CXX_SOURCES): Include pathsearch.cc in the list.\n\n2010-11-12  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::cat): Simplify previous change.\n\n2010-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::cat): New special case for concatenating\n\tempty matrices.  Bug #31615.\n\n2010-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.cc (xtrunc, xround): Move definitions here from\n\tlo-mappers.h.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* kpse-xfns.c: Delete.\n\t* kpse-xfns.h: Delete.  Move defintions to kpse.cc.\n\t* Makefile.am (INCS): Remove kpse-xfns.h from the list.\n\t(LIBOCT_PATHSEARCH_SOURCES): Define to pathsearch.cc.\n\t(LIBOCT_PATHSEARCH_CXX_SOURCES,\tLIBOCT_PATHSEARCH_C_SOURCES):\n\tDelete variables.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cieee.c Eliminate special cases for SCO.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* lo-ieee.cc (octave_ieee_init): Don't initialize octave_Inf,\n\toctave_NaN, and octave_NA to DBL_MAX.  Don't initialize\n\toctave_Float_Inf, octave_Float_NaN, and octave_Float_NA to FLT_MAX.\n\t(octave_ieee_init): Simplify using std::numeric_limits template.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* syswait.h: Delete special cases for NeXT systems.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* lo-sysdep.cc (octave_chdir): Delete special case for __EMX__.\n\t* oct-env.cc (octave_env::do_make_absolute): Likewise.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* lo-ieee.h: Eliminate special cases for SCO.\n\t* lo-ieee.cc (octave_ieee_init): Eliminate special cases for SCO.\n\n2010-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.h (xmod, xrem): Don't copy sign if result is zero.\n\n2010-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.cc, lo-mappers.h (xisnan, xisinf, xfinite, xmod,\n\txrem, floor, ceil, xround, xroundb, signum): Move definitions\n\tfrom lo-mappers.cc to lo-mappers.h and convert to templates.\n\t(xtrunc): Move definitions from lo-mappers.cc to lo-mappers.h.\n\t* lo-mappers.cc (fix): Use xtrunc.  Move definitions to\n\tlo-mappers.cc from lo-mappers.h.\n\t(real, imag, conj) Move definitions to lo-mappers.h and declare inline.\n\t(round): Move definitions to lo-mappers.h and declare inline.\n\tUse roundf for float version.\n\t(arg): Move definitions to lo-mappers.h and declare inline.\n\tUse atan2f for float version.\n\t* lo-mappers.h (xceil): New functions.\n\t(X_NINT): New template function.\n\t(D_NINT, F_NINT): Define in terms of X_NINT.\n\t* lo-utils.h, lo-utils.cc (D_NINT, F_NINT): Delete.\n\t* lo-mappers.h, lo-mappers.cc (NINTbig,\tNINT): Move from\n\tlo-utils.cc and lo-utils.h.\n\n2010-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::sort, Array<T>::is_sorted,\n\tArray<T>::is_sorted_rows): Use comparisons to sortmode values\n\tinstead of testing mode directly.\n\n2010-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.cc (xmod, xrem): New functions.\n\t(mod): Delete.\n\t* lo-mappers.h (xmod, xrem): Provide decls.\n\n2010-10-31  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* dim-vector.h (class dim_vector): tag with OCTAVE_API.\n\n2010-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (INCS): Include lo-array-gripes.h in the list.\n\t(LIBOCTAVE_CXX_SOURCES): Include lo-array-gripes.cc in the list.\n\n\t* lo-array-gripes.h: New file.  Move gripe function decls here\n\tfrom Array-util.h.\n\t* lo-array-gripes.c: New file.  Move gripe function definitions\n\there from Array-util.cc.\n\n\t* CMatrix.cc (ComplexMatrix::operator !): Gripe if any element is NaN.\n\t* CNDArray.cc (ComplexNDArray::operator !): Likewise.\n\t* CSparse.cc (SparseComplexMatrix::operator !): Likewise.\n\t* dMatrix.cc (Matrix::operator !): Likewise.\n\t* dNDArray.cc (NDArray::operator !): Likewise.\n\t* dSparse.cc (SparseMatrix::operator !): Likewise.\n\t* fCMatrix.cc (FloatComplexMatrix::operator !): Likewise.\n\t* fCNDArray.cc (FloatComplexNDArray::operator !): Likewise.\n\t* fMatrix.cc (FloatMatrix::operator !): Likewise.\n\t* fNDArray.cc (FloatNDArray::operator !): Likewise.\n\n2010-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* Array-util.cc (gripe_nan_to_character_conversion): New function.\n\t* Array-util.h: Provide decl.\n\n2010-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (INCS): Add caseless-str.h to the list.\n\n2010-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* caseless-str.h: New file, extracted from src/graphics.h.in.\n\n2010-09-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-utils.cc (xis_int_or_inf_or_nan): Fix typos.\n\n2010-09-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array::test, Array::test_all, Array::test_any): New\n\toverloaded template methods.\n\t* lo-mappers.h (xisinteger, xnegative_sign): New bool mappers.\n\t* dNDArray.cc (NDArray::any_element_is_negative,\n\tNDArray::all_integers): Simplify.\n\t* fNDArray.cc (FloatNDArray::any_element_is_negative,\n\tFloatNDArray::all_integers): Simplify.\n\n\t* lo-utils.cc (xis_int_or_inf_or_nan, xis_one_or_zero,\n\txis_zero, xtoo_large_for_float): New utility functions.\n\n\t* dNDArray.cc (NDArray::any_element_is_negative,\n\tNDArray::all_integers, NDArray::all_elements_are_zero,\n\tNDArray::all_elements_are_int_or_inf_or_nan,\n\tNDArray::any_element_not_one_or_zero,\n\tNDArray::too_large_for_float): Simplify.\n\n\t* fNDArray.cc (FloatNDArray::any_element_is_negative,\n\tFloatNDArray::all_integers, FloatNDArray::all_elements_are_zero,\n\tFloatNDArray::all_elements_are_int_or_inf_or_nan,\n\tFloatNDArray::any_element_not_one_or_zero,\n\tFloatNDArray::too_large_for_float): Simplify.\n\n2010-09-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dNDArray.cc (NDArray::any_element_is_negative,\n\tNDArray::any_element_is_nan,\n\tNDArray::any_element_is_inf_or_nan): Simplify.\n\t* fNDArray.cc (FloatNDArray::any_element_is_negative,\n\tFloatNDArray::any_element_is_nan,\n\tFloatNDArray::any_element_is_inf_or_nan): Simplify.\n\t* dMatrix.cc (Matrix::any_element_is_negative,\n\tMatrix::any_element_is_nan,\n\tMatrix::any_element_is_inf_or_nan): Simplify.\n\t* fMatrix.cc (FloatMatrix::any_element_is_negative,\n\tFloatMatrix::any_element_is_nan,\n\tFloatMatrix::any_element_is_inf_or_nan): Simplify.\n\t* CNDArray.cc (ComplexNDArray::any_element_is_negative,\n\tComplexNDArray::any_element_is_nan,\n\tComplexNDArray::any_element_is_inf_or_nan): Simplify.\n\t* fCNDArray.cc (FloatComplexNDArray::any_element_is_negative,\n\tFloatComplexNDArray::any_element_is_nan,\n\tFloatComplexNDArray::any_element_is_inf_or_nan): Simplify.\n\t* CMatrix.cc (ComplexMatrix::any_element_is_negative,\n\tComplexMatrix::any_element_is_nan,\n\tComplexMatrix::any_element_is_inf_or_nan): Simplify.\n\t* fCMatrix.cc (FloatComplexMatrix::any_element_is_negative,\n\tFloatComplexMatrix::any_element_is_nan,\n\tFloatComplexMatrix::any_element_is_inf_or_nan): Simplify.\n\n2010-09-21  John W. Eaton  <jwe@octave.org>\n\n\t* oct-env.cc (do_get_host_name): Call gnulib::gethostname\n\tinstead of octave_gethostname.\n\n\t* lo-utils.h, lo-cutils.c (octave_gethostname): Delete.\n\n2010-09-20  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc (octave_time::octave_time, octave_strptime::init):\n\tCall gnulib::mktime instead of mktime (may fix bug #31079).\n\n2010-09-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dSparse.h (SparseMatrix::SparseMatrix (const Sparse<double>&)):\n\tNew ctor.\n\t* CSparse.h (SparseComplexMatrix::SparseComplexMatrix\n\t(const Sparse<Complex>&)): New ctor.\n\t* boolSparse.cc (SparseBoolMatrix::sum): New method.\n\t* boolSparse.h: Declare it.\n\n2010-09-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* boolSparse.cc (SparseBoolMatrix::any): Optimize.\n\n2010-08-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-ch.cc: Inline basic sorts.\n\n2010-08-21  Rik  <octave@nomad.inbox5.com>\n\n\t* CmplxQRP.cc, CmplxQRP.h, dbleQRP.cc, dbleQRP.h, fCmplxQRP.cc,\n\tfCmplxQRP.h, floatQRP.cc, floatQRP.h: Declare Pvec as RowVector,\n\tnot ColumnVector.  Bug #30832.\n\n2010-08-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_all_finite): New check.\n\t* Sparse-op-defs.h (SPARSE_SMS_BIN_OP_1, SPARSE_SMS_BIN_OP_2,\n\tSPARSE_SSM_BIN_OP_1, SPARSE_SSM_BIN_OP_2): Use unchecked access where\n\tappropriate.\n\t(SPARSE_SMM_BIN_OP_1, SPARSE_MSM_BIN_OP_1): Simplify.\n\t(SPARSE_SMM_BIN_OP_2, SPARSE_MSM_BIN_OP_2): Use optimized code path\n\tif all values are finite.\n\t(SPARSE_MSM_BIN_OPS): Use SPARSE_MSM_BIN_OP_1 for division.\n\n2010-07-31  Rik  <octave@nomad.inbox5.com>\n\n\t* DASPK-opts.in, DASRT-opts.in, DASSL-opts.in, LSODE-opts.in,\n\tQuad-opts.in: Grammarcheck .cc files\n\n2010-07-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.cc (dim_vector::dim_max (void)): Turn it into a function.\n\t(dim_vector::safe_numel): Update usage.\n\t* dim-vector.h: Update declaration.\n\n2010-07-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleSCHUR.cc (SCHUR::SCHUR (const Matrix&, const Matrix&)):\n\tNew ctor.\n\t* dbleSCHUR.h: Declare it.\n\t* floatSCHUR.cc (FloatSCHUR::FloatSCHUR (const FloatMatrix&, const\n\tFloatMatrix&)): New ctor.\n\t* floatSCHUR.h: Declare it.\n\t* CmplxSCHUR.cc (ComplexSCHUR::ComplexSCHUR (const ComplexMatrix&,\n\tconst ComplexMatrix&),\n\tComplexSCHUR::ComplexSCHUR (const SCHUR&)): New ctors.\n\t* CmplxSCHUR.h: Declare them.\n\t* fCmplxSCHUR.cc (FloatComplexSCHUR::FloatComplexSCHUR\n\t(const FloatComplexMatrix&, const FloatComplexMatrix&),\n\tFloatComplexSCHUR::FloatComplexSCHUR (const FloatSCHUR&)): New ctors.\n\t* fCmplxSCHUR.h: Declare them.\n\n2010-07-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (Matrix::lssolve): Fix decision test for workaround.\n\t* fMatrix.cc (FloatMatrix::lssolve): Ditto.\n\t* CMatrix.cc (ComplexMatrix::lssolve): Ditto.\n\t* fCMatrix.cc (FloatComplexMatrix::lssolve): Ditto.\n\n2010-07-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.cc (dim_vector::dim_max): New static const member.\n\t* dim-vector.h: Declare it.\n\n2010-07-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (Matrix::extract, Matrix::extract_n): Reimplement using\n\tindex.\n\t* fMatrix.cc (FloatMatrix::extract, FloatMatrix::extract_n): Ditto.\n\t* CMatrix.cc (ComplexMatrix::extract, ComplexMatrix::extract_n): Ditto.\n\t* fCMatrix.cc (FloatComplexMatrix::extract, FloatComplexMatrix::extract_n): Ditto.\n\n2010-07-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* MSparse.h (MSparse<T>::index): Remove overloads.\n\t* dSparse.h (SparseMatrix::index): Likewise.\n\t* dSparse.cc (SparseMatrix::index): Likewise.\n\t* CSparse.h (SparseComplexMatrix::index): Likewise.\n\t* CSparse.cc (SparseComplexMatrix::index): Likewise.\n\n2010-07-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CMatrix.cc (ComplexMatrix::lssolve (const ComplexMatrix&)):\n\tUndo 10708:2786b7ae3f80, implement proper correction.\n\t* fCMatrix.cc (FloatComplexMatrix::lssolve (const FloatComplexMatrix&)):\n\tDitto.\n\n2010-06-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::scalar_1x1): New method.\n\t* lo-traits.h (equal_types): Fix.\n\n2010-06-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::cat): Implement the loose horzcat/vertcat rules\n\tunder dim=-1/-2.\n\t* Sparse.cc (Array<T>::cat): Implement the loose horzcat/vertcat rules\n\tunder dim=-1/-2.\n\t* Array.h, Sparse.h: Document it.\n\n2010-06-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.cc (dim_vector::hvcat): New method.\n\t* dim-vector.h (dim_vector::hvcat, dim_vector::cat): Update decls.\n\t(dim_vector::empty_2d): New method.\n\n2010-06-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* MatrixType.cc (matrix_real_probe): Use OCTAVE_LOCAL_BUFFER for\n\ttemporary array.\n\t(matrix_complex_probe): Parametrize by real type. Use\n\tOCTAVE_LOCAL_BUFFER for temporary array.\n\n2010-06-16  Rik  <octave@nomad.inbox5.com>\n\n\t* DASSL-opts.in: Periodic grammar check on documentation.\n\n2010-06-16  David Bateman  <dbateman@free.fr>\n\n\t* oct-rand.cc (void octave_rand:do_reset (void),\n\tvoid octave_rand:do_reset (const std::string&)): New functions\n\t* oct-rand.h (void octave_rand:do_reset (void),\n\tvoid octave_rand:do_reset (const std::string&)): Declare them\n\t(void octave_rand:reset (void),\n\tvoid octave_rand:reset (const std::string&)): New functions.\n\n2010-06-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CMatrix.cc (ComplexMatrix::lssolve (const ComplexMatrix&)):\n\tWorkaround LAPACK bug.\n\t* fCMatrix.cc (FloatComplexMatrix::lssolve (const FloatComplexMatrix&)):\n\tDitto.\n\n2010-06-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array::sort, Array::nth_element): Fix behavior when\n\ttrailing singleton dim is specified.\n\t* Sparse.cc (Sparse::sort): Ditto.\n\n2010-06-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::copy_data): Handle class_mask case.\n\t(idx_vector::increment): Fix class_colon and add class_mask.\n\n2010-06-06  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* mx-op-defs.h (MNANCHK): Add matrix element type argument and use it\n\tto specify template argument for mx_inline_any_nan.\n\t(MS_BOOL_OP, SM_BOOL_OP, MM_BOOL_OP, NDS_BOOL_OP, SND_BOOL_OP,\n\tNDND_BOOL_OP): Specify new MNANCHK argument.\n\n2010-06-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.cc: New source.\n\t* Makefile.am: Add it.\n\t* dim-vector.h (dim_vector::chop_all_singletons,\n\tdim_vector::str, dim_vector::num_ones, dim_vector::safe_numel,\n\tdim_vector::squeeze, dim_vector::concat, dim_vector::redim):\n\tMove bodies to dim_vector.cc.\n\t(dim_vector::concat): Rewrite.\n\t* Array.cc (Array::cat): Fix dim_vector concatenation. Don't use 0x0\n\tas neutral element, because it isn't with dim > 1.\n\n2010-06-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::optimize_dimensions): New method.\n\t* Array.h: Declare it.\n\n2010-06-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::maybe_delete_dims): Remove method (makes no\n\tlonger sense).\n\t* Array.h: Update decls.\n\n2010-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::compute_index (const octave_idx_type *,\n\tint)): New method overload.\n\t(dim_vector::compute_index, dim_vector::cum_compute_index,\n\tdim_vector::increment_index): Add missing const qualifiers.\n\n\t* Array-util.cc (compute_index (..., const dim_vector&)): Rewrite,\n\tadd new overloads. Move code from Array<T>::checkelem here.\n\t* Array-util.h: Update decls.\n\t* Array.h (Array<T>::compute_index): Forward to the above.\n\t(Array<T>::compute_index_unchecked): New method.\n\t(Array<T>::elem, Array<T>::xelem): Call it here.\n\n\t* Array.cc (Array<T>::checkelem): Use compute_index where suitable.\n\n2010-05-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_cumcount): Fix 2D version instantiation.\n\n2010-05-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::linearize): Remove.\n\t* Array.h (Array<T>::linearize): Remove decl.\n\n2010-05-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (Matrix::lssolve): Remove warnings about rank.\n\t* fMatrix.cc (FloatMatrix::lssolve): Ditto.\n\t* CMatrix.cc (ComplexMatrix::lssolve): Ditto.\n\t* fCMatrix.cc (FloatComplexMatrix::lssolve): Ditto.\n\n2010-05-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::unmask): Fix off-by-1 bug. Add tests.\n\n2010-05-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array::delete_elements (const idx_vector&)): Only call\n\tresize1 when deleting the last element of a vector.\n\n2010-05-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-norm.h: Fix include guard.\n\n2010-05-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleSCHUR.cc (SCHUR::init): Handle empty matrix case.\n\tUse clear rather than resize to realloc matrix.\n\t* floatSCHUR.cc (FloatSCHUR::init): Ditto.\n\t* CmplxSCHUR.cc (ComplexSCHUR::init): Ditto.\n\t* fCmplxSCHUR.cc (FloatComplexSCHUR::init): Ditto.\n\n2010-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* CollocWt.cc (diff, jcobi, dfopr): New functions, based on\n\tFortran functions in libcruft/villad.\n\t(jcobi): Handle iteration failure at large N.\n\t(CollocWt::init): Call them instead of Fortran code.\n\t* CollocWt.h (CollocWt::initialized): Declare as bool, not int.\n\tChange all uses.\n\tAddresses bug #29473.\n\n2010-05-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleSVD.h (SVD::driver): New enum.\n\t(SVD::SVD, SVD::init): Add driver option.\n\t* floatSVD.h (FloatSVD::FloatSVD, FloatSVD::init): Add driver option.\n\t* CmplxSVD.h (ComplexSVD::ComplexSVD, ComplexSVD::init):\n\tAdd driver option.\n\t* fCmplxSVD.h (FloatComplexSVD::FloatComplexSVD,\n\tFloatComplexSVD::init): Add driver option.\n\t* dbleSVD.cc (SVD::init): Optionally use xGESDD driver.\n\t* floatSVD.cc (FloatSVD::init): Ditto.\n\t* CmplxSVD.cc (ComplexSVD::init): Ditto.\n\t* fCmplxSVD.cc (FloatComplexSVD::init): Ditto.\n\n2010-04-28  John W. Eaton  <jwe@octave.org>\n\n\t* dim-vector.h (dim_vector (const octave_idx_type *, size_t)): Delete.\n\t* Sparse.cc (Sparse<T>::assign): Cast 0 to octave_idx_type in\n\tcall to Sparse<T> constructor.\n\tAddresses bug #29692.\n\n2010-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* intNDArray.cc (intNDArray<T>::abs, intNDArray<T>::signum):\n\tCreate new vector for return values.  Fixes bug #29685.\n\n2010-04-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::assign): Fix typos.\n\n2010-04-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.h (::assign, ::assign1): Remove declarations.\n\n2010-04-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::cat): Fast return for single array case.\n\t* Sparse.cc (Sparse<T>::cat): Ditto.\n\n2010-04-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::cat): Miscellaneous fixes.\n\t* Sparse.cc (Sparse<T>::cat): Ditto.\n\n2010-04-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::cat): New method.\n\t* Array.h: Declare it.\n\t* Sparse.cc (Sparse<T>::cat): New method.\n\t* Sparse.h: Declare it.\n\n2010-04-16  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (template <class T> Sparse<T>::Sparse (const Array<T>&,\n\tconst idx_vector&, const idx_vector&, octave_idx_type,\n\toctave_idx_type, bool, octave_idx_type)): Add argument defining the\n\tminimum storage to allocate for the sparse matrix.\n\t* Sparse.h (template <class T> Sparse (const Array<T>&,\n\tconst idx_vector&, const idx_vector&, octave_idx_type,\n\toctave_idx_type, bool, octave_idx_type)): ditto.\n\t* MSparse.h : ditto\n\t* CSparse.h : ditto\n\t* dSparse.h : ditto\n\t* boolSparse.h : ditto\n\n2010-04-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc: Update failing tests.\n\n2010-04-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::index): If S is a sparse column vector,\n\tforward S(I,1) and S(I,:) to 1D indexing. Handle permutation indexing\n\tin the 1D case.\n\t(Sparse<T>::assign): If S is a sparse column vector,\n\tforward S(I,1) = X and S(I,:) =X to 1D indexed assignment.\n\t* idx-vector.cc (idx_vector::inverse_permutation): Add missing break.\n\n2010-04-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-util.cc (gripe_invalid_assignment_size,\n\tgripe_assignment_dimension_mismatch): Move funcs here from Array.cc\n\t* Array-util.h: Declare them.\n\t* Array.cc: Remove them.\n\n\t* Sparse.cc (Sparse<T>::assign): New overloaded method.\n\t(Sparse<T>::operator =): Update.\n\t(Sparse<T>::resize1): Rewrite to match sparse assignment specifics.\n\t(Sparse<T>::set_index, Sparse<T>::clear_index, Sparse<T>::index_count,\n\tSparse<T>::value): Remove methods.\n\t(::assign1, ::assign): Remove funcs.\n\n\t(INSTANTIATE_SPARSE): Move here from Sparse.h.\n\n\t* Sparse.h (Sparse<T>::idx, Sparse<T>::idx_count): Remove member\n\tfields. Remove initializations from all ctors.\n\t(Sparse<T>::get_idx): Remove.\n\t(Sparse<T>::assign): Add decls.\n\t(INSTANTIATE_SPARSE_ASSIGN, INSTANTIATE_SPARSE_AND_ASSIGN): Remove.\n\t(INSTANTIATE_SPARSE): Move to Sparse.cc\n\n\t* Sparse-C.cc, Sparse-d.cc, Sparse-b.cc: Only call INSTANTIATE_SPARSE.\n\n\t* idx-vector.cc (idx_vector::inverse_permutation): New method.\n\t* idx-vector.h: Declare it.\n\n2010-04-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::Sparse (const Array<T>&, const idx_vector&,\n\tconst idx_vector&, ...)): Call maybe_compress after matrix is created.\n\n2010-04-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::diag): Change nzmax to nnz where appropriate.\n\t* MatrixType.cc (MatrixType::MatrixType): Ditto.\n\t* SparseQR.cc: Ditto.\n\t* SparseCmplxQR.cc: Ditto.\n\t* boolSparse.cc: Ditto.\n\n2010-04-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::resize (octave_idx_type, octave_idx_type)):\n\tRewrite. Be smarter esp. when resizing to more columns.\n\n2010-04-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::concat): Ignore zero_by_zero, but not\n\tall_zero arrays in concatenation (like Matlab).\n\n2010-04-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::index (const idx_vector&, bool)): Use shallow\n\tcopy when column is indexed by colon.\n\n2010-04-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (lblookup): Move in front of Sparse<T>::delete_elements.\n\n2010-04-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* str-vec.h (string_vector::string_vector (const Array<std::string>)):\n\tNew constructor.\n\n2010-04-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::complement): Rewrite.\n\n2010-04-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::maybe_delete_elements): Rename to\n\tdelete_elements. Use const reference arguments.\n\t(Sparse<T>::delete_elements (const idx_vector&, const idx_vector&)):\n\tRewrite.\n\t(Sparse<T>::maybe_delete_elements (int dim, const idx_vector&)): New\n\toverload.\n\t(Sparse<T>::maybe_delete_elements (Array<idx_vector>&)): Remove\n\toverload.\n\n2010-04-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc, Array-util.h, Array-util.cc: Reverse effects of\n\t4e64fbbd5c58.\n\n2010-04-02  John W. Eaton  <jwe@octave.org>\n\n\t* Array-util.cc, idx-vector.cc, idx-vector.h: Style fixes.\n\n2010-04-02  John W. Eaton  <jwe@octave.org>\n\n\t* idx-vector.cc (idx_vector::idx_vector (const Range&)):\n\tMove here from idx-vector.h.  Allow non-integer values in ranges,\n\tbut warn by default (for Matlab compatibility).\n\t* Array-util.h, Array-util.cc (gripe_invalid_index): New arg, ERR.\n\tIf ERR is false, generate warning instead of error.\n\n2010-04-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::maybe_delete_elements): Rewrite. Optimize for\n\tsparse column vectors.\n\n2010-04-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc: Declare all loops as throw (). Ditto for\n\tcorresponding applier arguments.\n\t(do_mx_check): New applier.\n\t(logical_value): Do not throw exceptions.\n\t* mx-op-defs.h (SNANCHK, MNANCHK): New helper macros.\n\t(MS_BOOL_OP, SM_BOOL_OP, MM_BOOL_OP, NDS_BOOL_OP, SND_BOOL_OP,\n\tNDND_BOOL_OP): Use them here.\n\n2010-03-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::Sparse (const Array<T>&,\n\tconst Array<octave_idx_type>&, ...), Sparse<T>::Sparse (const Array<T>&,\n\tconst Array<double>&, ...)):\n\tRemove old constructors.\n\t* Sparse.h: Ditto.\n\t* MSparse.h: Ditto.\n\t* dSparse.h: Ditto.\n\t* CSparse.h: Ditto.\n\t* boolSparse.h: Ditto.\n\n2010-03-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::idx_range_rep::as_array): Fix typo.\n\t(idx_vector::raw): Use unchecked constructor.\n\t* Sparse.cc (Sparse<T>::Sparse (const Array<T>&, const idx_vector&,\n\tconst idx_vector&, ...)): New ctor.\n\t* Sparse.h: Declare it.\n\n2010-03-30  John W. Eaton  <jwe@octave.org>\n\n\t* str-vec.cc (string_vector::string_vector (const char * const *)):\n\tCreate empty string_vector object if arg is NULL.\n\tFixes bug #29386.\n\n2010-03-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::raw): New method.\n\t* idx-vector.h: Declare it.\n\n2010-03-27  David Bateman  <dbateman@free.fr>\n\n\t* oct-openmp.h: New file.\n\t* Makefile.am (INCS): Add it here.\n\n2010-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::index (const idx_vector&, const\tidx_vector&,\n\tbool)): Specialize for contiguous row range, row permutation,\n\tand implement general case through double index-transpose.\n\n2010-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* eigs-base.cc (EigsComplexNonSymmetricFunc): Avoid warning\n\tabout deprecated Array constructor.\n\n2010-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-edit.cc, file-ops.cc, lo-math.h, lo-utils.cc, oct-env.cc,\n\tdir-ops.cc, file-stat.cc, cmd-hist.cc, oct-time.cc, oct-time.h,\n\toct-uname.cc: Revert changes from 2010-03-24 and 2010-03-25.\n\n2010-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-mappers.cc\t(fix (double)): Forward to gnulib::trunc.\n\t(fix (float)): Forward to gnulib::truncf.\n\t(xround (double)): Forward to gnulib::round.\n\t(xround (float)): Forward to gnulib::roundf.\n\t(xtrunc (double)): Forward to gnulib::trunc.\n\t(xtrunc (float)): Forward to gnulib::truncf.\n\n2010-03-25  David Grundberg  <davidg@cs.umu.se>\n\n\t* oct-time.h (octave_time): Revert ::modf to std::modf again now\n\tthat cmath is included again.\n\n2010-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-math.h: Include both \"math.h\" and \"cmath\".\n\n2010-03-24  David Grundberg  <davidg@cs.umu.se>\n\n\t* cmd-edit.cc: Include gnulib stdlib.h/string.h instead of C++\n\theaders.\n\t* file-ops.cc: Include gnulib stdlib.h/stdio.h/string.h instead of\n\tC++ headers.\n\t* lo-math.h: Include gnulib math.h instead of C++ headers.\n\t* lo-utils.cc: Include gnulib stdlib.h instead of C++ headers.\n\t* oct-env.cc, dir-ops.cc, file-stat.cc, cmd-hist.cc: Include\n\tgnulib string.h instead of C++ headers.\n\t* oct-time.cc: Include gnulib time.h instead of C++ headers.\n\t* oct-time.h (octave_time): Use default namespace ::modf instead\n\tof std::modf.\n\t* oct-uname.cc: Include gnulib string.h instead of C++ headers.\n\n2010-03-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (lblookup): New helper func.\n\t(Sparse<T>::index (const idx_vector&, bool)): Use it here for lookups.\n\t(Sparse<T>::index (const idx_vector&, const idx_vector&, bool)):\n\tSpecialize for scalar row index.\n\n2010-03-23  John W. Eaton  <jwe@octave.org>\n\n\t* config-ops.sh: Work properly for \"all\" cases.\n\n2010-03-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (octave_int_arith_base::rem, octave_int_base::mod):\n\tNew methods.\n\t(rem, mod): New template functions.\n\t* lo-mappers.cc (rem, mod): New overloaded functions.\n\t* lo-mappers.h: Declare them.\n\n2010-03-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-binmap.h: New source.\n\t* Makefile.am: Include it here.\n\n2010-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* config-ops.sh: Accept additional arguments.\n\t* Makefile.am ($(srcdir)/vx-op-inc.mk, $(srcdir)/mx-op-inc.mk\n\t$(srcdir)/smx-op-inc.mk, $(srcdir)/vx-op-src.mk, $(srcdir)/mx-op-src.mk\n\t$(srcdir)/smx-op-src.mk): Pass additional arguments to config-ops.sh.\n\n2010-03-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (Sparse<T>::index (const idx_vector&, const idx_vector&,\n\tbool)): Handle resize_ok in advance. Optimize colon as the first index.\n\t(Sparse<T>::index (const idx_vector&, bool)): Small fixes.\n\n2010-03-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dSparse.cc (SparseMatrix::matrix_value): Simplify.\n\t* CSparse.cc (SparseComplexMatrix::matrix_value): Simplify.\n\n2010-03-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-util.cc (gripe_invalid_resize): Move here from Array.cc.\n\t* Array-util.h: Declare it.\n\t* Array.cc: Use it.\n\n\t* idx-vector.cc (idx_vector::idx_mask_rep::unconvert): Fix non-owned\n\tcase.\n\t(idx_vector::idx_mask_rep::as_array): New method.\n\t* idx-vector.h: Declare it.\n\n\t* Sparse.cc (Sparse<T>::index (const idx_vector&, bool)): Rewrite.\n\t(Sparse<T>::array_value): New method.\n\t(Sparse<T>::resize1): New method.\n\t(Sparse<T>::resize): Move resize_no_fill bodies in here.\n\t(Sparse<T>::resize_no_fill): Remove.\n\t* Sparse.h: Update decls.\n\n2010-03-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.h (Sparse<T>::index): Use const references. Use bool for\n\tresize_ok. Remove Array<idx_vector> overload.\n\t* MSparse.h (MSparse<T>::index): Ditto.\n\t* dSparse.h, dSparse.cc (SparseMatrix::index): Ditto.\n\t* CSparse.h, CSparse.cc (SparseComplexMatrix::index): Ditto.\n\t* boolSparse.h, boolSparse.cc (SparseBoolMatrix::index): Ditto.\n\t* Sparse.cc (Sparse<T>::index): Ditto. Redim index to 2 dimensions.\n\tDon't use non-const methods. Use gripe_index_out_of_range.\n\n2010-03-17  John W. Eaton  <jwe@octave.org>\n\n\t* dim-vector.h (dim_vector): Also use DIM_VECTOR macro for 2 and\n\t3 dimensions.\n\n2010-03-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-macros.h: New source.\n\t* dim-vector.h: Use the macro magic to define constructors\n\tgenerically.\n\n2010-03-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h: Provide constructors up to order 7.\n\n2010-03-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-specfun.cc: Substitute cbrt and cbrtf if needed.\n\t* lo-specfun.h: Declare cbrt and cbrtf if needed.\n\t* configure.ac: Check for cbrt and cbrtf.\n\n2010-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* oct-glob.cc (octave_glob): Tag calls to glob and globfree with\n\tgnulib::.\n\n\t* kpse.cc (DEBUG_START, DEBUGF, FATAL_PERROR, FATAL, KPSE_DEBUG,\n\tlog_search, find_first_of): Tag calls to\n\tfputs with gnulib::.\n\t(DEBUGF1, DEBUGF2, DEBUGF3, DEBUGF4, log_search, find_first_of,\n\tkpse_element_dirs): Tag calls to fprintf with gnulib::.\n\t(hash_lookup, search, find_first_of, kpse_element_dirs):\n\tTag calls to putc with gnulib::.\n\t(do_subdir): Tag call to opendir with gnulib::.\n\t(xclosedir): Tag call to closedir with gnulib::.  Assume closedir\n\treturns int value.\n\n\t* cmd-hist.cc (gnu_history::do_append): Tag calls to open and\n\tclose with gnulib::.\n\t(command_history::error): Tag call to strerror with gnulib::.\n\n\t* cmd-edit.cc (gnu_readline::command_generator,\n\tgnu_readline::command_quoter, gnu_readline::command_dequoter):\n\tTag call to malloc with gnulib::.\n\t(default_command_editor::do_readline): Tag call to fputs with gnulib::.\n\t(command_editor::error): Tag call to strerror with gnulib::.\n\n\t* sparse-util.cc (SparseCholPrint): Tag call to vfprintf with gnulib::.\n\n\t* oct-uname.cc (octave_uname::init): Tag call to strerror with gnulib::.\n\n\t* oct-time.cc (octave_time::stamp): Tag call to gettimeofday\n\twith gnulib::.\n\t(octave_strptime::init): Tag call to strptime with gnulib::.\n\n\t* oct-syscalls.cc (octave_syscalls::dup2,\n\toctave_syscalls::execvp, octave_syscalls::fork,\n\toctave_syscalls::vfork, octave_syscalls::getpgrp,\n\toctave_syscalls::pipe, octave_syscalls::waitpid,\n\toctave_syscalls::kill, octave_fcntl):\n\tTag call to strerror with gnulib::.\n\t(octave_syscalls::dup2): Tag call to dup2 with gnulib::.\n\t(octave_syscalls::popen2): Tag calls to close with gnulib::.\n\t(octave_fcntl): Tag call to fcntl with gnulib::.\n\n\t* oct-env.cc (octave_env::error): Tag call to strerror with gnulib::.\n\n\t* lo-utils.cc (octave_putenv): Tag call to malloc with gnulib::.\n\t(octave_fgets): Tag calls to malloc and realloc with gnulib::.\n\n\t* lo-sysdep.cc (octave_getcwd): Tag call to getcwd with gnulib::.\n\n\t* lo-mappers.cc (xround): Tag call to round with gnulib::.\n\n\t* file-stat.cc (file_stat::update_internal): Tag calls to lstat\n\tand strerror with gnulib::.\n\t(file_fstat::update_internal): Tag calls to fstat and strerror\n\twith gnulib::.\n\n\t* file-ops.cc (octave_mkdir): Tag call to mkdir with gnulib::.\n\t(octave_mkfifo): Tag call to mkfifo with gnulib::.\n\t(octave_link): Tag call to link with gnulib::.\n\t(octave_symlink): Tag call to symlink with gnulib::.\n\t(octave_readlink): Tag call to readlink with gnulib::.\n\t(octave_rename): Tag call to rename with gnulib::.\n\t(octave_rmdir): Tag call to rmdir with gnulib::.\n\t(octave_unlink): Tag call to unlink with gnulib::.\n\t(octave_canonicalize_file_name): Tag call to\n\tcanonicalize_file_name with gnulib::.\n\t(octave_mkdir, octave_mkfifo, octave_link, octave_symlink,\n\toctave_readlink, octave_rename, octave_rmdir, octave_unlink,\n\toctave_tempnam, octave_canonicalize_file_name): Tag calls to\n\tstrerror with gnulib::.\n\n\t* dir-ops.cc (dir_entry::close): Tag closedir call with gnulib::.\n\t(dir_entry::open): Tag opendir and strerror calls with gnulib::.\n\n2010-03-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (octave_int_base::ftrunc, octave_int_base::fnon_int,\n\toctave_int_base::fnan, octave_int_base::get_trunc_flag,\n\toctave_int_base::get_nan_flag,\n\toctave_int_base::get_non_int_flag,\n\toctave_int_base::get_math_trunc_flag,\n\toctave_int_base::clear_conv_flags): Remove.\n\tRemove occurences of ftrunc, fnon_int and fnan eveywhere.\n\t* oct-inttypes.cc: Ditto last sentence. Remove warning tests.\n\n2010-03-07  Søren Hauberg  <hauberg@gmail.com>\n\n\t* dim-vector.h: New constructor accepting a C array of dimensions.\n\n2010-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* MArray.cc (MArray<T>::idx_add_nd): New method.\n\t* MArray.h: Declare it.\n\n2010-03-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-specfun.cc (erfcx, erfcx_impl): New functions.\n\t* lo-specfun.h: Declare erfcx.\n\n2010-03-03  John W. Eaton  <jwe@octave.org>\n\n\t* oct-convn.cc (convolve): Cast int constant to octave_idx_type in\n\tcall to std::max.\n\n2010-03-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-convn.cc (convolve_2d_axpy_kernel, convolve_2d_axpy): Remove.\n\t(convolve_2d): Forward to Fortran implementations, add inner flag.\n\t(convolve_nd): Handle inner-convolution case.\n\t(convolve): Ditto.\n\n2010-03-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-convn.h, oct-convn.cc: New sources.\n\t* Makefile.am: Include them.\n\n2010-03-01  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (Sparse<T>::maybe_delete_elements (idxx_vector&)):\n\tSpecial case the deletion of elements in sparse vectors.\n\t(Sparse<T>::index (idx_vector&, int) const): Special case indexing\n\tof sparse matrices with ranges with a step of 1.\n\t* Sparse.h: Include oct-mem.h for the copy_or_memcpy declaration.\n\n2010-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am ($(srcdir)/vx-op-inc.mk, $(srcdir)/mx-op-inc.mk,\n\t$(srcdir)/smx-op-inc.mk, $(srcdir)/vx-op-src.mk,\n\t$(srcdir)/mx-op-src.mk, $(srcdir)/smx-op-src.mk): New targets.\n\n\t* config-ops.sh: Accept top_srcdir argument.  Work from build\n\tdirectory too, not just source tree.\n\n2010-02-28  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Array-C.cc (DiagArray2<Complex>::Proxy): Remove explicit\n\tinstantiation under MSVC.\n\tArray-d.cc (DiagArray2<double>::Proxy): Ditto.\n\tArray-f.cc (DiagArray2<float>::Proxy): Ditto.\n\tArray-fC.cc (DiagArray2<FloatComplex::Proxy): Ditto.\n\n2010-02-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-util.cc (gripe_index_out_of_range): Throw errors with id.\n\t(gripe_nonconformant): Likewise.\n\t(error_id_index_out_of_bounds, error_id_invalid_index,\n\terror_id_nonconformant_args): New variables.\n\t(gripe_invalid_index): New function.\n\t* Array-util.h: Declare them.\n\t* Array.cc (Array<T>::checkelem): Throw invalid-index when negative\n\tindices are encountered.\n\n2010-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (Sparse<T>::diag): Handle case of diag (szv) when szv\n\tis a sparse vector with nnz = 0.\n\n2010-02-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-util.cc (gripe_index_out_of_range): New function.\n\t* Array.cc (Array<T>::range_error): Remove.\n\t(Array<T>::checkelem): Rewrite.\n\t(Array<T>::index, Array<T>::delete_elements): Simplify.\n\t* DiagArray2.cc (DiagArray2::checkelem): Use gripe_index_out_of_range.\n\t* Range.cc (Range::checkelem, Range::index): Ditto.\n\n2010-02-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (OP_DUP_FCN): Remove.\n\t(mx_inline_dup): Remove.\n\t(mx_inline_not): Remove.\n\t(mx_inline_make_complex): Remove.\n\t(mx_inline_change_sign): Remove.\n\t(mx_inline_fabs_dup): Remove.\n\t(mx_inline_cabs_dup): Remove.\n\t(mx_inline_imag_dup): Remove.\n\t(mx_inline_real_dup): Remove.\n\t(mx_inline_conj_dup): Remove.\n\t(mx_inline_change_sign): Remove.\n\n2010-02-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array<T>::ArrayRep): Simplify copy constructor. Add\n\tconversion constructor.\n\t(Array<T>): Remove pointer acquiring ctors.\n\t(Array<T>::maybe_economize): Update.\n\t(Array<T>::make_unique): Update.\n\t* Array.cc (Array<T>::fill): Update.\n\n\t* MArray.h (MArray<T>::MArray<T> (T *, ...)): Remove.\n\t* DiagArray2.h (DiagArray2<T>::DiagArray2<T> (T *, ...)): Remove.\n\t* MDiagArray2.h (MDiagArray2<T>::MDiagArray2<T> (T *, ...)): Remove.\n\t* Array3.h (Array3<T>::Array3<T> (T *, ...)): Remove.\n\n\t* dColVector.h (ColumnVector::ColumnVector (T *, ...)): Remove.\n\t* fColVector.h (FloatColumnVector::FloatColumnVector (T *, ...)): Remove.\n\t* CColVector.h (ComplexColumnVector::ComplexColumnVector (T *, ...)): Remove.\n\t* fCColVector.h (FloatComplexColumnVector::FloatComplexColumnVector (T *, ...)): Remove.\n\n\t* dRowVector.h (RowVector::RowVector (T *, ...)): Remove.\n\t* fRowVector.h (FloatRowVector::FloatRowVector (T *, ...)): Remove.\n\t* CRowVector.h (ComplexRowVector::ComplexRowVector (T *, ...)): Remove.\n\t* fCRowVector.h (FloatComplexRowVector::FloatComplexRowVector (T *, ...)): Remove.\n\n\t* dMatrix.h (Matrix::Matrix (T *, ...)): Remove.\n\t* fMatrix.h (FloatMatrix::FloatMatrix (T *, ...)): Remove.\n\t* CMatrix.h (ComplexMatrix::ComplexMatrix (T *, ...)): Remove.\n\t* fCMatrix.h (FloatComplexMatrix::FloatComplexMatrix (T *, ...)): Remove.\n\t* boolMatrix.h (boolMatrix::boolMatrix (T *, ...)): Remove.\n\t* chMatrix.h (charMatrix::charMatrix (T *, ...)): Remove.\n\n\t* dNDArray.h (NDArray::NDArray (T *, ...)): Remove.\n\t* fNDArray.h (FloatNDArray::FloatNDArray (T *, ...)): Remove.\n\t* CNDArray.h (ComplexNDArray::ComplexNDArray (T *, ...)): Remove.\n\t* fCNDArray.h (FloatComplexNDArray::FloatComplexNDArray (T *, ...)): Remove.\n\t* boolNDArray.h (boolNDArray::boolNDArray (T *, ...)): Remove.\n\t* chNDArray.h (charNDArray::charNDArray (T *, ...)): Remove.\n\n2010-02-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DiagArray2.h (DiagArray2): Clean up ctors. Remove Proxy class.\n\tRemove non-const two-index elem methods.\n\t* DiagArray2.cc: Update.\n\t* MDiagArray2.h: Update.\n\n\t* dDiagArray2.h: Update.\n\t* dDiagArray2.cc: Update.\n\t* fDiagArray2.h: Update.\n\t* fDiagArray2.cc: Update.\n\t* CDiagArray2.h: Update.\n\t* CDiagArray2.cc: Update.\n\t* fCDiagArray2.h: Update.\n\t* fCDiagArray2.cc: Update.\n\n\t* dMatrix.cc: Update.\n\t* fMatrix.cc: Update.\n\t* CMatrix.cc: Update.\n\t* fCMatrix.cc: Update.\n\n\t* dRowVector.cc: Update.\n\t* fRowVector.cc: Update.\n\t* CRowVector.cc: Update.\n\t* fCRowVector.cc: Update.\n\n\t* dColVector.cc: Update.\n\t* fColVector.cc: Update.\n\t* CColVector.cc: Update.\n\t* fCColVector.cc: Update.\n\n\t* dColVector.cc (ColumnVector::abs): New method.\n\t* dColVector.h: Declare it.\n\t* fColVector.cc (FloatColumnVector::abs): New method.\n\t* fColVector.h: Declare it.\n\t* CColVector.cc (ComplexColumnVector::abs): New method.\n\t* CColVector.h: Declare it.\n\t* fCColVector.cc (FloatComplexColumnVector::abs): New method.\n\t* fCColVector.h: Declare it.\n\n2010-02-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc: Parameterize all appliers by value types rather than\n\tArray types. Return & accept Array instances.\n\t* mx-op-defs.h: Update references.\n\t* CMatrix.cc: Ditto.\n\t* CNDArray.cc: Ditto.\n\t* DiagArray2.h: Ditto.\n\t* MArray.cc: Ditto.\n\t* boolMatrix.cc: Ditto.\n\t* boolNDArray.cc: Ditto.\n\t* bsxfun-defs.cc: Ditto.\n\t* chMatrix.cc: Ditto.\n\t* chNDArray.cc: Ditto.\n\t* dMatrix.cc: Ditto.\n\t* dNDArray.cc: Ditto.\n\t* fCMatrix.cc: Ditto.\n\t* fCNDArray.cc: Ditto.\n\t* fMatrix.cc: Ditto.\n\t* fNDArray.cc: Ditto.\n\t* intNDArray.cc: Ditto.\n\t* MDiagArray2.cc: Remove computed assignment operators, adapt\n\toperators to new mechanism.\n\t* MDiagArray2.h: Declare operators as friends.\n\t* MArray-decl.h (MDIAGARRAY2_OPS_FRIEND_DECLS): Don't expand\n\tMARRAY_OP_ASSIGN_FRIENDS here.\n\n2010-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* eigs-base.cc: Use octave_idx_type for Fortran LOGICAL values\n\tin function prototypes.\n\t(EigsRealSymmetricMatrix, EigsRealSymmetricMatrixShift,\n\tEigsRealSymmetricFunc, EigsRealNonSymmetricMatrix,\n\tEigsRealNonSymmetricMatrixShift, EigsRealNonSymmetricFunc,\n\tEigsComplexNonSymmetricMatrix, EigsComplexNonSymmetricMatrixShift,\n\tEigsComplexNonSymmetricFunc): Declare rvec argument as bool, not int.\n\tFix explicit instantiations to match.\n\n2010-02-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-mem.h (safe_size_comp): New helper func.\n\t(no_ctor_new): Call it here.\n\n2010-02-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-mem.h (copy_or_memcpy, fill_or_memset, no_ctor_new): Accept\n\tsize_t rather than octave_idx_type.\n\t* Array.h (Array<T>::byte_size): Correct calculation.\n\t* DiagArray2.h (DiagArray2<T>::byte_size): Call inherited byte_size.\n\t* PermMatrix.h (PermMatrix::byte_size): Ditto.\n\n2010-02-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* str-vec.h (string_vector::string_vector): Use (n, 1).\n\t(string_vector::resize): Ditto.\n\t* str-vec.cc (string_vector::string_vector): Ditto.\n\n2010-02-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array::Array (const Array&, octave_idx_type,\n\toctave_idx_type): New ctor.\n\t(Array::reshape (octave_idx_type, octave_idx_type): New method.\n\t* Array.h: Declare them.\n\t* Array2.h: Deprecate Array2, make it a #define for Array.\n\n\t* Array-C.cc: Remove Array2 instantiation.\n\t* Array-b.cc: Ditto.\n\t* Array-ch.cc: Ditto.\n\t* Array-d.cc: Ditto.\n\t* Array-f.cc: Ditto.\n\t* Array-fC.cc: Ditto.\n\t* Array-i.cc: Ditto.\n\t* Array-s.cc: Ditto.\n\t* Array-voidp.cc: Ditto.\n\n\t* CMatrix.cc: Use Array instead of Array2 everywhere.\n\t* CMatrix.h: Ditto.\n\t* CNDArray.cc: Ditto.\n\t* DiagArray2.cc: Ditto.\n\t* DiagArray2.h: Ditto.\n\t* MDiagArray2.h: Ditto.\n\t* Sparse.cc: Ditto.\n\t* Sparse.h: Ditto.\n\t* boolMatrix.h: Ditto.\n\t* boolNDArray.cc: Ditto.\n\t* chMatrix.h: Ditto.\n\t* chNDArray.cc: Ditto.\n\t* dMatrix.cc: Ditto.\n\t* dMatrix.h: Ditto.\n\t* dNDArray.cc: Ditto.\n\t* fCMatrix.cc: Ditto.\n\t* fCMatrix.h: Ditto.\n\t* fCNDArray.cc: Ditto.\n\t* fMatrix.cc: Ditto.\n\t* fMatrix.h: Ditto.\n\t* fNDArray.cc: Ditto.\n\t* lo-specfun.cc: Ditto.\n\t* lo-specfun.h: Ditto.\n\n2010-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* chMatrix.h (charMatrix): Base on Array<char>.\n\t* chMatrix.cc (charMatrix): Update.\n\t* boolMatrix.h (boolMatrix): Ditto.\n\t* boolMatrix.h (boolMatrix): Update.\n\n2010-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array): Define 2D constructors. Remove conflicting 1D\n\tinitialized constructor. Deprecate 1D constructor. Deprecate 1D resize.\n\tAdd 2D resize, resize1. Remove resize_fill. Make resize_fill_value\n\treturn a reference. Remove 1D clear.\n\n\t* MArray.h (MArray): Merge with MArrayN. Define 2D constructors, sync\n\twith Array changes.\n\n\t* MArrayN.h, MArray2.h: Deprecate headers, use compatibility #defines.\n\t* MArrayN.cc, MArray2.cc: Remove sources.\n\t* Makefile.am: Update.\n\n\t* fCMatrix.h (FloatComplexMatrix): Rebase on MArray.\n\t* fMatrix.h (FloatMatrix): Ditto.\n\t* dMatrix.h (Matrix): Ditto.\n\t* CMatrix.h (ComplexMatrix): Ditto.\n\t* fCNDArray.h (FloatComplexNDArray): Rebase on MArray.\n\t* fNDArray.h (FloatNDArray): Ditto.\n\t* dNDArray.h (NDArray): Ditto.\n\t* CNDArray.h (ComplexNDArray): Ditto.\n\n\t* Array-util.cc: Update.\n\t* Array.cc: Ditto.\n\t* Array2.h: Ditto.\n\t* Array3.h: Ditto.\n\t* CColVector.cc: Ditto.\n\t* CColVector.h: Ditto.\n\t* CMatrix.cc: Ditto.\n\t* CNDArray.cc: Ditto.\n\t* CRowVector.cc: Ditto.\n\t* CSparse.cc: Ditto.\n\t* ChangeLog: Ditto.\n\t* CmplxCHOL.cc: Ditto.\n\t* CmplxHESS.cc: Ditto.\n\t* CmplxLU.cc: Ditto.\n\t* CmplxQRP.cc: Ditto.\n\t* CmplxSCHUR.cc: Ditto.\n\t* CmplxSVD.cc: Ditto.\n\t* CollocWt.cc: Ditto.\n\t* DASPK-opts.in: Ditto.\n\t* DASPK.cc: Ditto.\n\t* DASRT-opts.in: Ditto.\n\t* DASRT.cc: Ditto.\n\t* DASSL-opts.in: Ditto.\n\t* DASSL.cc: Ditto.\n\t* DiagArray2.cc: Ditto.\n\t* DiagArray2.h: Ditto.\n\t* EIG.cc: Ditto.\n\t* LSODE-opts.in: Ditto.\n\t* LSODE.cc: Ditto.\n\t* MArray-C.cc: Ditto.\n\t* MArray-d.cc: Ditto.\n\t* MArray-defs.h: Ditto.\n\t* MArray-f.cc: Ditto.\n\t* MArray-fC.cc: Ditto.\n\t* MArray-i.cc: Ditto.\n\t* MArray-s.cc: Ditto.\n\t* MArray.cc: Ditto.\n\t* MDiagArray2.h: Ditto.\n\t* MSparse-defs.h: Ditto.\n\t* MSparse.cc: Ditto.\n\t* MSparse.h: Ditto.\n\t* Makefile.am: Ditto.\n\t* MatrixType.cc: Ditto.\n\t* PermMatrix.cc: Ditto.\n\t* Quad.cc: Ditto.\n\t* SparseCmplxLU.cc: Ditto.\n\t* SparseCmplxQR.cc: Ditto.\n\t* SparseCmplxQR.h: Ditto.\n\t* SparseQR.cc: Ditto.\n\t* SparseQR.h: Ditto.\n\t* SparsedbleLU.cc: Ditto.\n\t* base-lu.cc: Ditto.\n\t* dColVector.h: Ditto.\n\t* dMatrix.cc: Ditto.\n\t* dNDArray.cc: Ditto.\n\t* dRowVector.h: Ditto.\n\t* dSparse.cc: Ditto.\n\t* dbleCHOL.cc: Ditto.\n\t* dbleHESS.cc: Ditto.\n\t* dbleLU.cc: Ditto.\n\t* dbleQRP.cc: Ditto.\n\t* dbleSCHUR.cc: Ditto.\n\t* dbleSVD.cc: Ditto.\n\t* dim-vector.h: Ditto.\n\t* eigs-base.cc: Ditto.\n\t* fCColVector.cc: Ditto.\n\t* fCColVector.h: Ditto.\n\t* fCMatrix.cc: Ditto.\n\t* fCNDArray.cc: Ditto.\n\t* fCRowVector.cc: Ditto.\n\t* fCRowVector.h: Ditto.\n\t* fCmplxCHOL.cc: Ditto.\n\t* fCmplxHESS.cc: Ditto.\n\t* fCmplxLU.cc: Ditto.\n\t* fCmplxQRP.cc: Ditto.\n\t* fCmplxSCHUR.cc: Ditto.\n\t* fCmplxSVD.cc: Ditto.\n\t* fColVector.h: Ditto.\n\t* fEIG.cc: Ditto.\n\t* fMatrix.cc: Ditto.\n\t* fNDArray.cc: Ditto.\n\t* fRowVector.h: Ditto.\n\t* floatCHOL.cc: Ditto.\n\t* floatHESS.cc: Ditto.\n\t* floatLU.cc: Ditto.\n\t* floatQRP.cc: Ditto.\n\t* floatSCHUR.cc: Ditto.\n\t* floatSVD.cc: Ditto.\n\t* glob-match.h: Ditto.\n\t* int16NDArray.h: Ditto.\n\t* int32NDArray.h: Ditto.\n\t* int64NDArray.h: Ditto.\n\t* int8NDArray.h: Ditto.\n\t* intNDArray.cc: Ditto.\n\t* intNDArray.h: Ditto.\n\t* oct-fftw.cc: Ditto.\n\t* oct-norm.cc: Ditto.\n\t* oct-rand.cc: Ditto.\n\t* regex-match.cc: Ditto.\n\t* sparse-dmsolve.cc: Ditto.\n\t* str-vec.cc: Ditto.\n\t* str-vec.h: Ditto.\n\t* uint16NDArray.h: Ditto.\n\t* uint32NDArray.h: Ditto.\n\t* uint64NDArray.h: Ditto.\n\t* uint8NDArray.h: Ditto.\n\n2010-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* data-conv.cc, data-conv.h (read_floats, read_doubles,\n\tdo_float_format_conversion, do_double_format_conversion):\n\tDeclare len arg and loop counter as octave_idx_type, not int.\n\t(strip_spaces): Use size_t for string dimension and index, not int.\n\t(LS_DO_READ, LS_DO_WRITE): Declare loop counter as\n\toctave_idx_type, not int.\n\t(write_floats, write_doubles):\n\tDeclare len arg as octave_idx_type, not int.\n\t(IEEE_big_double_to_IEEE_little_double,\n\tVAX_D_double_to_IEEE_little_double,\n\tVAX_G_double_to_IEEE_little_double,\n\tCray_to_IEEE_little_double,\n\tIEEE_big_float_to_IEEE_little_float,\n\tVAX_D_float_to_IEEE_little_float,\n\tVAX_G_float_to_IEEE_little_float, Cray_to_IEEE_little_float,\n\tIEEE_little_double_to_IEEE_big_double,\n\tVAX_D_double_to_IEEE_big_double,\n\tVAX_G_double_to_IEEE_big_double, Cray_to_IEEE_big_double,\n\tIEEE_little_float_to_IEEE_big_float,\n\tVAX_D_float_to_IEEE_big_float, VAX_G_float_to_IEEE_big_float,\n\tCray_to_IEEE_big_float, IEEE_little_double_to_VAX_D_double,\n\tIEEE_big_double_to_VAX_D_double,\n\tVAX_G_double_to_VAX_D_double, Cray_to_VAX_D_double,\n\tIEEE_little_float_to_VAX_D_float,\n\tIEEE_big_float_to_VAX_D_float, VAX_G_float_to_VAX_D_float,\n\tCray_to_VAX_D_float, IEEE_little_double_to_VAX_G_double,\n\tIEEE_big_double_to_VAX_G_double,\n\tVAX_D_double_to_VAX_G_double, Cray_to_VAX_G_double,\n\tIEEE_little_float_to_VAX_G_float,\n\tIEEE_big_float_to_VAX_G_float, VAX_D_float_to_VAX_G_float,\n\tCray_to_VAX_G_float, read_doubles):\n\tDeclare len arg as octave_idx_type, not int.\n\n2010-02-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* lo-sysdep.cc, lo-utils.h, oct-shlib.h: Define WIN32_LEAN_AND_MEAN\n\tand don't #undef min/max.\n\t* oct-inttypes.h: Don't #undef min/max.\n\n\t* oct-glob.cc (octave_glob): Convert backslashes to forward slashes\n\tautomatically before calling glob, and convert back after the call\n\t(implementation from jwe).\n\n\t* Makefile.am: Add -bindir flag to liboctave_la_LDFLAGS.\n\n2010-02-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::as_array,\n\tidx_vector::idx_range_rep::as_array,\n\tidx_vector::idx_scalar_rep::as_array,\n\tidx_vector::idx_vector_rep::as_array): New methods.\n\t* idx-vector.h: Declare them.\n\n2010-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* oct-rand.cc: Include <sdint.h>.  Change declarations of ranlib\n\tfunctions to take int32_t instead of octave_idx_type values.\n\tChange all uses.\n\t(octave_rand::do_seed): Use int32_t in union, not octave_idx_type.\n\t(force_to_fit_range): Args are now int32_t, not octave_idx_type.\n\t(octave_rand::initialize_ranlib_generators): Use int32_t in seed\n\tcalculation.\n\n2010-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-op-defs.h (MINMAX_FCNS): Generalize.\n\t* mx-op-decl.h (MINMAX_DECLS): Likewise.\n\n\t* int16NDArray.h, int32NDArray.h, int64NDArray.h, int8NDArray.h,\n\tuint16NDArray.h, uint32NDArray.h, uint64NDArray.h, uint8NDArray.h:\n\tUpdate.\n\t* int16NDArray.cc, int32NDArray.cc, int64NDArray.cc, int8NDArray.cc,\n\tuint16NDArray.cc, uint32NDArray.cc, uint64NDArray.cc, uint8NDArray.cc:\n\tUpdate.\n\n\t* CNDArray.h, dNDArray.h, fCNDArray.h, fNDArray.h: Replace explicit\n\tdecls.\n\n\t* CNDArray.cc, dNDArray.cc, fCNDArray.cc, fNDArray.cc: Replace explicit\n\tdefinitions.\n\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* sparse-mk-ops.awk, mk-ops.awk, filemode.c, lo-cieee.c,\n\toct-rl-hist.c, randgamma.c, randmtzig.c, randpoisson.c,\n\ttempnam.c, tempname.c: Untabify.\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* Array-C.cc, Array-fC.cc, Array-util.cc, Array.cc,\n\tCColVector.cc, CDiagMatrix.cc, CMatrix.cc, CNDArray.cc,\n\tCRowVector.cc, CSparse.cc, CmplxAEPBAL.cc, CmplxCHOL.cc,\n\tCmplxGEPBAL.cc, CmplxHESS.cc, CmplxLU.cc, CmplxQR.cc,\n\tCmplxQRP.cc, CmplxSCHUR.cc, CmplxSVD.cc, CollocWt.cc, DASPK.cc,\n\tDASRT.cc, DASSL.cc, EIG.cc, LSODE.cc, MSparse.cc, MatrixType.cc,\n\tODES.cc, Quad.cc, Range.cc, Sparse-C.cc, Sparse.cc,\n\tSparseCmplxCHOL.cc, SparseCmplxLU.cc, SparseCmplxQR.cc,\n\tSparseQR.cc, SparsedbleCHOL.cc, SparsedbleLU.cc, boolNDArray.cc,\n\tboolSparse.cc, chMatrix.cc, chNDArray.cc, cmd-edit.cc,\n\tcmd-hist.cc, dColVector.cc, dDiagMatrix.cc, dMatrix.cc,\n\tdNDArray.cc, dRowVector.cc, dSparse.cc, data-conv.cc,\n\tdbleAEPBAL.cc, dbleCHOL.cc, dbleGEPBAL.cc, dbleHESS.cc,\n\tdbleLU.cc, dbleQR.cc, dbleQRP.cc, dbleSCHUR.cc, dbleSVD.cc,\n\tdir-ops.cc, eigs-base.cc, fCColVector.cc, fCDiagMatrix.cc,\n\tfCMatrix.cc, fCNDArray.cc, fCRowVector.cc, fCmplxAEPBAL.cc,\n\tfCmplxCHOL.cc, fCmplxGEPBAL.cc, fCmplxHESS.cc, fCmplxLU.cc,\n\tfCmplxQR.cc, fCmplxQRP.cc, fCmplxSCHUR.cc, fCmplxSVD.cc,\n\tfColVector.cc, fDiagMatrix.cc, fEIG.cc, fMatrix.cc, fNDArray.cc,\n\tfRowVector.cc, file-stat.cc, floatAEPBAL.cc, floatCHOL.cc,\n\tfloatGEPBAL.cc, floatHESS.cc, floatLU.cc, floatQR.cc,\n\tfloatQRP.cc, floatSCHUR.cc, floatSVD.cc, idx-vector.cc,\n\tintNDArray.cc, kpse.cc, lo-ieee.cc, lo-mappers.cc,\n\tlo-specfun.cc, lo-sysdep.cc, lo-utils.cc, mach-info.cc,\n\tmx-inlines.cc, oct-alloc.cc, oct-env.cc, oct-fftw.cc,\n\toct-glob.cc, oct-group.cc, oct-inttypes.cc, oct-md5.cc,\n\toct-rand.cc, oct-shlib.cc, oct-sort.cc, oct-spparms.cc,\n\toct-syscalls.cc, oct-time.cc, pathsearch.cc, regex-match.cc,\n\tsparse-base-chol.cc, sparse-base-lu.cc, sparse-dmsolve.cc,\n\tsparse-sort.cc, sparse-util.cc, str-vec.cc: Untabify.\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* Array-util.h, Array.h, Array2.h, Array3.h, CColVector.h,\n\tCMatrix.h, CNDArray.h, CRowVector.h, CSparse.h, CmplxCHOL.h,\n\tCmplxGEPBAL.h, CmplxHESS.h, CmplxLU.h, CmplxQRP.h, CmplxSCHUR.h,\n\tCmplxSVD.h, CollocWt.h, DAE.h, DAEFunc.h, DAERT.h, DAERTFunc.h,\n\tDASPK.h, DASRT.h, DASSL.h, DiagArray2.h, EIG.h, MArrayN.h,\n\tMDiagArray2.h, MSparse-defs.h, MSparse.h, MatrixType.h, ODE.h,\n\tODEFunc.h, ODES.h, ODESFunc.h, Quad.h, Range.h,\n\tSparse-diag-op-defs.h, Sparse-op-defs.h, Sparse-perm-op-defs.h,\n\tSparse.h, SparseCmplxCHOL.h, SparseCmplxLU.h, SparseCmplxQR.h,\n\tSparseQR.h, SparsedbleCHOL.h, SparsedbleLU.h, base-dae.h,\n\tbase-de.h, base-lu.h, base-min.h, base-qr.h, boolNDArray.h,\n\tboolSparse.h, chNDArray.h, cmd-hist.h, dMatrix.h, dNDArray.h,\n\tdSparse.h, data-conv.h, dbleCHOL.h, dbleGEPBAL.h, dbleHESS.h,\n\tdbleLU.h, dbleQRP.h, dbleSCHUR.h, dbleSVD.h, dir-ops.h,\n\tfCColVector.h, fCMatrix.h, fCNDArray.h, fCRowVector.h,\n\tfCmplxCHOL.h, fCmplxGEPBAL.h, fCmplxHESS.h, fCmplxLU.h,\n\tfCmplxQRP.h, fCmplxSCHUR.h, fCmplxSVD.h, fEIG.h, fMatrix.h,\n\tfNDArray.h, file-stat.h, floatCHOL.h, floatGEPBAL.h,\n\tfloatHESS.h, floatLU.h, floatQRP.h, floatSCHUR.h, floatSVD.h,\n\tglob-match.h, idx-vector.h, intNDArray.h, lo-ieee.h,\n\tlo-specfun.h, mx-op-decl.h, mx-op-defs.h, oct-env.h, oct-fftw.h,\n\toct-group.h, oct-inttypes.h, oct-mutex.h, oct-passwd.h,\n\toct-rand.h, oct-shlib.h, oct-sort.h, oct-spparms.h, oct-time.h,\n\toct-uname.h, pathsearch.h, sparse-base-chol.h, sparse-base-lu.h,\n\tsparse-sort.h, sparse-util.h, statdefs.h, str-vec.h: Untabify.\n\n2010-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.h (template <class U> Matrix (const Array<U>&)):\n\tNew constructor.\n\t* CMatrix.h (template <class U> ComplexMatrix (const Array<U>&)):\n\tNew constructor.\n\t* fMatrix.h (template <class U> FloatMatrix (const Array<U>&)):\n\tNew constructor.\n\t* fCMatrix.h (template <class U> FloatComplexMatrix (const Array<U>&)):\n\tNew constructor.\n\n2010-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::idx_vector_rep::idx_vector_rep (const\n\tArray<octave_idx_type>&, octave_idx_type, direct)): New constructor.\n\t* idx-vector.h: Declare it.\n\t(idx_vector::idx_vector (const Array<octave_idx_type>&,\n\toctave_idx_type)): New constructor.\n\n2010-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc: Include \"strftime.h\", not <strftime.h>.\n\t* file-ops.cc: Include \"pathmax.h\", not <pathmax.h>.\n\n2010-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* oct-env.cc (octave_env::prog_invocation_name): Rename from\n\tprogram_invocation_name.  Change all uses.\n\t(octave_env::prog_name): Rename from program_name.  Change all uses.\n\t(octave_env::do_set_program_name): Call ::set_program_name\n\tfunction from gnulib.\n\n2010-02-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.h (idx_vector::idx_base_rep::sort_idx): New pure virtual\n\tfunction.\n\t(idx_vector::idx_colon_rep::sort_idx,\n\tidx_vector::idx_range_rep::sort_idx,\n\tidx_vector::idx_scalar_rep::sort_idx,\n\tidx_vector::idx_vector_rep::sort_idx,\n\tidx_vector::idx_mask_rep::sort_idx): New override decls.\n\tidx_vector::sort (Array<octave_idx_type>&): New method.\n\t* idx-vector.cc (idx_vector::idx_range_rep::sort_idx,\n\tidx_vector::idx_vector_rep::sort_idx): New methods.\n\t(idx_vector::idx_vector_rep::sort_uniq_clone): Rewrite\n\tto use bucket sort under plausible circumstances.\n\n2010-02-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::permute): Fix result dimensions when inv=true.\n\n2010-02-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* MArrayN.cc (MArrayN::idx_min, MArrayN::idx_max): New methods.\n\t* MArrayN.h: Declare them.\n\t* lo-mappers.h (xmin, xmax): Define for general arguments.\n\n2010-02-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* chMatrix.h (charMatrix): Rebase directly on Array<char>.\n\t* chNDArray.h (charNDArray): Ditto.\n\t* chMatrix.cc: Update.\n\t* chNDArray.cc: Update.\n\t* MArray-ch.cc: Remove.\n\t* Makefile.am: Update.\n\n2010-02-04  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c (gethostname): Delete function.\n\t* lo-sysdep.h (gethostname): Delete declaration.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* oct-syscalls.h, oct-syscalls.cc (octave_fcntl): Assume fcntl exists.\n\tRename from octave_syscalls::fcntl.\n\t(octave_syscalls::popen2): Call octave_fcntl, not fcntl.\n\t* cmd-hist.cc, lo-sysdep.cc, oct-syscalls.cc:\n\tInclude <fcntl.h> unconditionally.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* dbleSVD.cc (SVD::init): Ensure args to std::max are the same type.\n\t* CmplxSVD.cc (ComplexSVD::init): Likewise.\n\t* floatSVD.cc (FloatSVD::init): Likewise.\n\t* fCmplxSVD.cc (FloatComplexSVD::init): Likewise.\n\t* idx-vector.cc (idx_range_rep): Likewise.\n\t* Array.cc (Array<T>::nth_element): Likewise.\n\n\t* lo-specfun.cc (null_dims): Delete unused static variable.\n\t(betainc): Call dim_vector (0, 0), not dim_vector (0).\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.h (octave_canonicalize_file_name): Rename from\n\tfile_ops::canonicalize_file_name.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc (canonicalize_file_name):\n\tDon't pass current directory to octave_env::make_absolute.\n\t* cmd-edit.cc (do_decode_prompt_string): Likewise.\n\n\t* oct-env.h (octave_env::get_current_directory):\n\tRename from octave_env::getcwd.\n\t(octave_env::make_absolute): Provide default value for second arg.\n\n\t* lo-sysdep.cc (octave_getcwd): Assume we are using gnulib\n\tgetcwd module.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.h: Include <ctime>, not \"systime.h\".\n\t* oct-time.cc: Include <strftime.h>, not \"strftime.h\".\n\tDon't include <windows.h>.\n\n\t* systime.h: Delete.\n\t* Makefile.am (INCS): Remove it from the list.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* lo-utils.h, lo-cutils.c (oct_strptime): Delete.\n\t* oct-time.cc (octave_strptime::init): Call strptime, not oct_strptime.\n\n2010-01-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (Matrix::determinant): Treat matrices marked as singular\n\tnormally.\n\t* fMatrix.cc (FloatMatrix::determinant): Ditto.\n\t* CMatrix.cc (ComplexMatrix::determinant): Ditto.\n\t* fCMatrix.cc (FloatComplexMatrix::determinant): Ditto.\n\n2010-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc: Don't tag functions with OCTAVE_API in source file.\n\n2010-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c, lo-utils.h (octave_link, octave_symlink,\n\toctave_readlink, octave_mkdir, octave_mkfifo, octave_rmdir,\n\toctave_rename, octave_tempnam, octave_umask, octave_unlink):\n\tDelete.\n\t* file-io.h, file-io.cc (octave_mkdir,  octave_mkfifo,\n\toctave_link, octave_symlink, octave_readlink, octave_rename,\n\toctave_rmdir, octave_recursive_rmdir, octave_umask,\n\toctave_unlink, octave_tempnam): Rename from file_ops::X to\n\toctave_X.  Change all uses.\n\t(file_ops::static_members): Incorporate directly into file_ops class.\n\n2010-01-23  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (LIBOCTAVE_C_SOURCES): Remove oct-getopt.c from the list.\n\t(LIBOCTAVE_CXX_SOURCES): Remove prog-args.c from the list.\n\t(INCS): Remove prog-args.h and oct-getopt.h from the list.\n\t* prog-args.cc, prog-args.h, oct-getopt.c, oct-getopt.h: Delete.\n\n2010-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* prog-args.h, prog-args.cc (prog_args::get_option,\n\tprog_args::option_argument, prog_args::option_index):\n\tDon't declare const.\n\n2010-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* prog-args.h, prog-args.cc (prog_args::get_option):\n\tRename from getopt. Now const.\n\t(prog_args::option_argument): Rename from optarg.  Now const.\n\t(prog_args::option_index): Rename from optind.  Now const.\n\n2010-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc: Don't include statdefs.h.\n\n2010-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleSVD.cc (SVD::init): Ensure LD* arguments >= 1.\n\t* floatSVD.cc (FloatSVD::init): Likewise.\n\t* CmplxSVD.cc (ComplexSVD::init): Likewise.\n\t* fCmplxSVD.cc (FloatComplexSVD::init): Likewise.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc, fCMatrix.cc, cmd-edit.cc, cmd-hist.cc,\n\tfile-ops.cc, file-ops.h, file-stat.cc, file-stat.h, filemode.c,\n\tkpse.cc, lo-cutils.c, lo-sysdep.cc, lo-utils.cc, oct-env.cc,\n\toct-group.cc, oct-group.h, oct-passwd.cc, oct-passwd.h,\n\toct-time.cc, oct-syscalls.cc, oct-syscalls.h, statdefs.h,\n\tsysdir.h, syswait.h, tempname.c, regex-match.h:\n\tAssume sys/types.h and unistd.h are present (gnulib provides them).\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.h, file-ops.cc, lo-utils.h, lo-cutils.c: Untabify.\n\n\t* file-ops.cc: Don't include unistd.h.\n\t(NOT_SUPPORTED): Delete unused macro.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c (octave_tempnam): New funtion.\n\t* lo-utils.h: Provide decl.\n\t* file-ops.cc (file_ops::tempnam): Call octave_tempnam.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c (octave_readlink): New funtion.\n\t* lo-utils.h: Provide decl.\n\t* file-ops.cc (file_ops::readlink): Call octave_readlink.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c (octave_symlink): New funtion.\n\t* lo-utils.h: Provide decl.\n\t* file-ops.cc (file_ops::symlink): Call octave_symlink.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c (octave_link): New funtion.\n\t* lo-utils.h: Provide decl.\n\t* file-ops.cc (file_ops::link): Call octave_link.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c (octave_unlink): New funtion.\n\t* lo-utils.h: Provide decl.\n\t* file-ops.cc (file_ops::unlink): Call octave_unlink.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c (octave_umask): New funtion.\n\t* lo-utils.h: Provide decl.\n\t* file-ops.cc (file_ops::umask): Call octave_umask.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.h (file_ops::mkdir): Move definitions to file-ops.cc.\n\t(file_ops::mkfifo): Move definitions to file-ops.cc.\n\t(file_ops::mkdir_internal, file_ops::mkfifo_internal): Delete decls.\n\t* file-ops.cc (file_ops::mkdir): Call octave_mkdir.\n\t(file_ops::mkfifo): Call octave_mkfifo.\n\t* lo-cutils.c (octave_mkdir, octave_mkfifo): New functions.\n\t* lo-utils.h: Provide decls.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (LIBOCTAVE_C_SOURCES): Remove strptime.c from the list.\n\t* strptime.c: Delete.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c (octave_rename): New funtion.\n\t* lo-utils.h: Provide decl.\n\t* file-ops.cc (file_ops::rename): Call octave_rename.\n\t* Makefile.am (LIBOCTAVE_C_SOURCES): Remove rename.c from the list.\n\t* rename.c: Delete.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cutils.c (octave_rmdir): New function.\n\t* lo-utils.h: Provide decl.\n\t* file-ops.cc (file_ops::rmdir): Call octave_rmdir.\n\t* Makefile.am (LIBOCTAVE_C_SOURCES): Remove rmdir.c from the list.\n\t* rmdir.c: Delete.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (LIBOCTAVE_C_SOURCES): Remove strcasecmp.c and\n\tstrncase.c from the list.\n\t* strcasecmp.c, strncase.c: Delete.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (INCS): Remove getopt.h from the list.\n\t(LIBOCTAVE_C_SOURCES): Remove getopt.c and getopt1.c from the list.\n\t* getopt.c, getopt1.c, getopt.h: Delete.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* Array-C.cc, Array-b.cc, Array-ch.cc, Array-d.cc, Array-f.cc,\n\tArray-fC.cc, Array-i.cc, Array-idx-vec.cc, Array-s.cc,\n\tArray-str.cc, Array-util.cc, Array-voidp.cc, Array.cc,\n\tCColVector.cc, CDiagMatrix.cc, CMatrix.cc, CNDArray.cc,\n\tCRowVector.cc, CSparse.cc, CmplxAEPBAL.cc, CmplxCHOL.cc,\n\tCmplxGEPBAL.cc, CmplxHESS.cc, CmplxLU.cc, CmplxQR.cc,\n\tCmplxQRP.cc, CmplxSCHUR.cc, CmplxSVD.cc, CollocWt.cc, DASPK.cc,\n\tDASRT.cc, DASSL.cc, DiagArray2.cc, EIG.cc, LSODE.cc,\n\tMArray-C.cc, MArray-ch.cc, MArray-d.cc, MArray-f.cc,\n\tMArray-fC.cc, MArray-i.cc, MArray-s.cc, MArray.cc, MArray2.cc,\n\tMArrayN.cc, MDiagArray2.cc, MSparse-C.cc, MSparse-d.cc,\n\tMSparse.cc, MatrixType.cc, ODES.cc, Quad.cc, Range.cc,\n\tSparse-C.cc, Sparse-b.cc, Sparse-d.cc, Sparse.cc,\n\tSparseCmplxCHOL.cc, SparseCmplxLU.cc, SparseCmplxQR.cc,\n\tSparseQR.cc, SparsedbleCHOL.cc, SparsedbleLU.cc, base-lu.cc,\n\tboolMatrix.cc, boolNDArray.cc, boolSparse.cc, chMatrix.cc,\n\tchNDArray.cc, cmd-edit.cc, cmd-hist.cc, dColVector.cc,\n\tdDiagMatrix.cc, dMatrix.cc, dNDArray.cc, dRowVector.cc,\n\tdSparse.cc, data-conv.cc, dbleAEPBAL.cc, dbleCHOL.cc,\n\tdbleGEPBAL.cc, dbleHESS.cc, dbleLU.cc, dbleQR.cc, dbleQRP.cc,\n\tdbleSCHUR.cc, dbleSVD.cc, dir-ops.cc, eigs-base.cc,\n\tfCColVector.cc, fCDiagMatrix.cc, fCMatrix.cc, fCNDArray.cc,\n\tfCRowVector.cc, fCmplxAEPBAL.cc, fCmplxCHOL.cc, fCmplxGEPBAL.cc,\n\tfCmplxHESS.cc, fCmplxLU.cc, fCmplxQR.cc, fCmplxQRP.cc,\n\tfCmplxSCHUR.cc, fCmplxSVD.cc, fColVector.cc, fDiagMatrix.cc,\n\tfEIG.cc, fMatrix.cc, fNDArray.cc, fRowVector.cc, file-ops.cc,\n\tfile-stat.cc, floatAEPBAL.cc, floatCHOL.cc, floatGEPBAL.cc,\n\tfloatHESS.cc, floatLU.cc, floatQR.cc, floatQRP.cc,\n\tfloatSCHUR.cc, floatSVD.cc, glob-match.cc, idx-vector.cc,\n\tint16NDArray.cc, int32NDArray.cc, int64NDArray.cc,\n\tint8NDArray.cc, intNDArray.cc, kpse.cc, lo-ieee.cc,\n\tlo-mappers.cc, lo-specfun.cc, lo-sysdep.cc, lo-utils.cc,\n\tmach-info.cc, mx-inlines.cc, oct-alloc.cc, oct-env.cc,\n\toct-fftw.cc, oct-group.cc, oct-inttypes.cc, oct-md5.cc,\n\toct-passwd.cc, oct-rand.cc, oct-shlib.cc, oct-sort.cc,\n\toct-spparms.cc, oct-syscalls.cc, oct-time.cc, oct-uname.cc,\n\tpathsearch.cc, prog-args.cc, regex-match.cc,\n\tsparse-base-chol.cc, sparse-base-lu.cc, sparse-dmsolve.cc,\n\tsparse-sort.cc, sparse-util.cc, str-vec.cc, uint16NDArray.cc,\n\tuint32NDArray.cc, uint64NDArray.cc, uint8NDArray.cc,\n\tf2c-main.c, lo-cieee.c, lo-cutils.c, oct-getopt.c,\n\toct-rl-edit.c, oct-rl-hist.c, randgamma.c, randmtzig.c,\n\trandpoisson.c, Array-util.h, Array.h, Array2.h, Array3.h,\n\tArrayN.h, CColVector.h, CDiagMatrix.h, CMatrix.h, CNDArray.h,\n\tCRowVector.h, CSparse.h, CmplxAEPBAL.h, CmplxCHOL.h,\n\tCmplxGEPBAL.h, CmplxHESS.h, CmplxLU.h, CmplxQR.h, CmplxQRP.h,\n\tCmplxSCHUR.h, CmplxSVD.h, CollocWt.h, DAE.h, DAEFunc.h, DAERT.h,\n\tDAERTFunc.h, DASPK.h, DASRT.h, DASSL.h, DiagArray2.h, EIG.h,\n\tLSODE.h, MArray.h, MArray2.h, MArrayN.h, MDiagArray2.h,\n\tMSparse-defs.h, MSparse.h, Matrix.h, MatrixType.h, ODE.h,\n\tODEFunc.h, ODES.h, ODESFunc.h, Quad.h, Range.h,\n\tSparse-op-defs.h, Sparse.h, SparseCmplxCHOL.h, SparseCmplxLU.h,\n\tSparseCmplxQR.h, SparseQR.h, SparsedbleCHOL.h, SparsedbleLU.h,\n\tbase-dae.h, base-de.h, base-lu.h, base-min.h, boolMatrix.h,\n\tboolNDArray.h, boolSparse.h, byte-swap.h, chMatrix.h,\n\tchNDArray.h, cmd-edit.h, cmd-hist.h, dColVector.h,\n\tdDiagMatrix.h, dMatrix.h, dNDArray.h, dRowVector.h, dSparse.h,\n\tdata-conv.h, dbleAEPBAL.h, dbleCHOL.h, dbleGEPBAL.h, dbleHESS.h,\n\tdbleLU.h, dbleQR.h, dbleQRP.h, dbleSCHUR.h, dbleSVD.h,\n\tdir-ops.h, fCColVector.h, fCDiagMatrix.h, fCMatrix.h,\n\tfCNDArray.h, fCRowVector.h, fCmplxAEPBAL.h, fCmplxCHOL.h,\n\tfCmplxGEPBAL.h, fCmplxHESS.h, fCmplxLU.h, fCmplxQR.h,\n\tfCmplxQRP.h, fCmplxSCHUR.h, fCmplxSVD.h, fColVector.h,\n\tfDiagMatrix.h, fEIG.h, fMatrix.h, fNDArray.h, fRowVector.h,\n\tfile-ops.h, file-stat.h, floatAEPBAL.h, floatCHOL.h,\n\tfloatGEPBAL.h, floatHESS.h, floatLU.h, floatQR.h, floatQRP.h,\n\tfloatSCHUR.h, floatSVD.h, functor.h, glob-match.h, idx-vector.h,\n\tint16NDArray.h, int32NDArray.h, int64NDArray.h, int8NDArray.h,\n\tintNDArray.h, kpse-xfns.h, lo-ieee.h, lo-mappers.h, lo-math.h,\n\tlo-specfun.h, lo-sysdep.h, lo-traits.h, lo-utils.h, mach-info.h,\n\tmx-base.h, mx-defs.h, mx-ext.h, mx-op-defs.h, oct-alloc.h,\n\toct-cmplx.h, oct-env.h, oct-fftw.h, oct-getopt.h, oct-group.h,\n\toct-inttypes.h, oct-md5.h, oct-passwd.h, oct-rand.h,\n\toct-rl-edit.h, oct-rl-hist.h, oct-shlib.h, oct-sort.h,\n\toct-spparms.h, oct-syscalls.h, oct-time.h, oct-uname.h,\n\tpathlen.h, pathsearch.h, prog-args.h, randgamma.h, randmtzig.h,\n\trandpoisson.h, regex-match.h, sparse-base-chol.h,\n\tsparse-base-lu.h, sparse-sort.h, sparse-util.h, statdefs.h,\n\tstr-vec.h, sun-utils.h, sysdir.h, systime.h, syswait.h,\n\tuint16NDArray.h, uint32NDArray.h, uint64NDArray.h,\n\tuint8NDArray.h: Remove Emacs local-variables settings.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* boolNDArray.cc (boolNDArray::cumsum): Sum directly in double to\n\tavoid a copy.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* dim-vector.h: Style fixes.  Remove Emacs local variables block.\n\tUntabify.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (PRIVATE_INCS): New variable.  List oct-glob.h\n\there instead of in INCS.\n\t(liboctave_la_SOURCES): Include $(PRIVATE_INCS) in the list.\n\n\t* glob-match.cc (glob_match::match, glob_match::glob): Now const.\n\tMove definitions here from glob-match.h.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_any_r, mx_inline_all_r): New helper\n\treductors.\n\t(mx_inline_any, mx_inline_all): Call the here in row-wise reduction\n\twith few enough columns.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-mappers.h (xmin (double, double), xmax (double, double),\n\txmin (float, float), xmax (float, float)): Inline definitions.\n\t* lo-mappers.cc (xmin (double, double), xmax (double, double),\n\txmin (float, float), xmax (float, float)): Remove from here.\n\t* mx-inlines.cc (mx_inline_xmin, mx_inline_xmax): Provide\n\tspecializations for real array-scalar and scalar-array cases.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-norm.cc (norm_accumulator_p::accum, norm_accumulator_mp::accum):\n\tCall octave_quit here.\n\t(higham_subp): Also here.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-op-defs.h (SND_MINMAX_FCN, NDS_MINMAX_FCN, NDND_MINMAX_FCN):\n\tSimplify using mx_inlines machinery.\n\t* dNDArray (min, max): Simplify.\n\t* fNDArray (min, max): Simplify.\n\t* CNDArray (min, max): Simplify.\n\t* fCNDArray (min, max): Simplify.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h: Substitute OCTAVE_QUIT -> octave_quit ().\n\t* CMatrix.cc: Ditto.\n\t* CNDArray.cc: Ditto.\n\t* CSparse.cc: Ditto.\n\t* CmplxGEPBAL.cc: Ditto.\n\t* MArrayN.cc: Ditto.\n\t* MSparse.cc: Ditto.\n\t* Sparse-diag-op-defs.h: Ditto.\n\t* Sparse-op-defs.h: Ditto.\n\t* Sparse-perm-op-defs.h: Ditto.\n\t* Sparse.cc: Ditto.\n\t* Sparse.h: Ditto.\n\t* SparseCmplxQR.cc: Ditto.\n\t* SparseQR.cc: Ditto.\n\t* boolSparse.cc: Ditto.\n\t* bsxfun-defs.cc: Ditto.\n\t* dMatrix.cc: Ditto.\n\t* dNDArray.cc: Ditto.\n\t* dSparse.cc: Ditto.\n\t* dbleGEPBAL.cc: Ditto.\n\t* fCMatrix.cc: Ditto.\n\t* fCNDArray.cc: Ditto.\n\t* fCmplxGEPBAL.cc: Ditto.\n\t* fMatrix.cc: Ditto.\n\t* fNDArray.cc: Ditto.\n\t* file-ops.cc: Ditto.\n\t* floatGEPBAL.cc: Ditto.\n\t* lo-utils.cc: Ditto.\n\t* mx-op-defs.h: Ditto.\n\t* oct-fftw.cc: Ditto.\n\t* oct-norm.cc: Ditto.\n\t* oct-rand.cc: Ditto.\n\t* sparse-dmsolve.cc: Ditto.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* bsxfun-defs.cc (BSXFUN_STDOP_DEFS_MXLOOP): Fix reversed min/max\n\tdefs.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* glob-match.h: Update copyright.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (INCS): Include oct-glob.h in the list.\n\t(LIBOCTAVE_CXX_SOURCES): Include oct-glob.cc in the list.\n\t* oct-glob.h, oct-glob.cc: New files.\n\t* glob-match.cc: (glob_match::match): Move internals to oct-glob.cc.\n\t(glob_match::glob_internal): Move internals to oct-glob.cc.\n\t(single_match_exists): Move to oct-glob.cc.\n\t(glob_match::opts_to_fnmatch_flags): New function.\n\t* glob-match.h Include oct-glob.h.\n\t(glob_match::glob): Call octave_glob to do the real work.\n\t(glob_match::glob_internal): Delete decl.\n\t(glob_match::match (const string_vector&)): Move here from\n\tglob-match.cc.\n\t(glob_match::match (const std::string&)): Call octave_fnmatch to\n\tdo the real work.\n\t(glob_match::fnmatch_flags): Rename from flags.\n\t(glob_match::opts_to_fnmatch_flags): New function.\n\t(glob_match::glob_match): Use it.\n\n2010-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CMatrix.cc (xgemm): Use octave_idx_type rather than int.\n\t* fCMatrix.cc (xgemm): Ditto.\n\n2010-01-16  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* oct-time.cc: Avoid to include nonneeded headers from Win32 API,\n\tespecially winsock.h. Include <sys/time.h> unconditionally, as it is\n\tnow provided by gnulib, in order to get gettimeofday defined.\n\n2010-01-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::insert): Rewrite using assign.\n\t(Array<T>::insert2, Array<T>::insertN): Remove.\n\t* Array.h: Update declarations. Add brief documentation.\n\n2010-01-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-b.cc: Inline ascending and descending sort.\n\t(do_bool_partition): New helper template function.\n\t(octave_sort<bool>::sort): Provide specializations.\n\n2010-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::insert (const Array<T>&, const\n\tArray<octave_idx_type>&): Allow less dimensions than indices.\n\n2010-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* chNDArray.h: Declare relational bsxfun ops.\n\t* chNDArray.cc: Define them.\n\n2010-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc: Fix prototype for zherk.\n\t* fCMatrix.cc: Fix prototype for cherk.\n\n2010-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* oct-rl-edit.c (octave_rl_set_name): Save arg before setting\n\trl_terminal_name.\n\n2010-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* idx-vector.cc (idx_vector::idx_scalar_rep::idx_scalar_rep (T x)):\n\tInitialize dummy variable.\n\n2010-01-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::compute_index): Generalize to the case of\n\tunequal lengths.\n\n2010-01-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::chop_trailing_singletons): Only uniquify\n\tif really needed.\n\t* Array.h (Array<T>::Array (T*, const dim_vector&)): Call\n\tchop_trailing_singletons.\n\t(Array<T>::Array (const Array<T>&, const dim_vector&,\n\toctave_idx_type...)): Ditto.\n\t(Array<T>::Array (const dim_vector&)): Ditto.\n\t(Array<T>::Array (const dim_vector&, const T&)): Ditto.\n\t(Array<T>::chop_trailing_singletons): Deprecate.\n\t* Array.cc (Array::Array(const Array&, const dim_vector&)): Ditto.\n\t(Array::index (const Array<idx_vector>&, ...)): Ditto.\n\t(Array<T>::permute): Don't call deprecate method here.\n\t(Array<T>::assign): Neither here.\n\n2010-01-11  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Remove unnecessary use of\n\tsimple_move_if_change_rule to allow Make to update timestamps.\n\n2010-01-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array<T>::crefT): New helper typedef.\n\t(Array<T>::elem const, Array<T>::xelem const,\n\tArray<T>::checkelem const, Array<T>::operator () const): Return crefT.\n\t(Array<T>::range_error const): Remove overloads.\n\t* Array.cc (Array<T>::range_error const): Remove overloads.\n\n2010-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc (octave_time::stamp): Assume gettimeofday is\n\tavailable and that it takes two arguments.\n\n2010-01-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-utils.cc (octave_fgets (FILE *, bool&)): Add OCTAVE_QUIT at the\n\tend.\n\n2010-01-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (AM_CPPFLAGS): Include @CPPFLAGS@ and -I../libgnu\n\tin the list.\n\n2009-12-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::maybe_reduce): Implement reduction rule\n\tfor subsequent ones () indices.\n\n2009-12-28  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc (fle_ops::mkdir_internal,\n\tfile_ops::mkfifo_internal): New private static functions.\n\t* file-ops.h (file_ops::mkdir, file_ops::mkdir): Move\n\tdefinitions here from file-ops.cc.  Forward to X_internal functions.\n\n2009-12-26  John W. Eaton  <jwe@octave.org>\n\n\t* file-stat.cc (lstat): Delete replacement function.\n\t(file_fstat::update_internal): Assume fstat is available.\n\n2009-12-25  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc (file_ops::mkdir): Assume we have an mkdir\n\tfunction that takes two arguments.\n\t* mkdir.c: Delete.\n\t* Makefile.am (LIBOCTAVE_C_SOURCES): Remove mkdir.c from the list.\n\n2009-12-25  John W. Eaton  <jwe@octave.org>\n\n\t* oct-md5.cc (oct_md5_result_to_str): New function.\n\t(oct_md5, oct_md5_file): Simplify using gnulib md5 functions and\n\toct_md5_result_to_str.\n\n\t* Makefile.am (INCS): Remove md5.h from the list.\n\t(LIBOCTAVE_C_SOURCES): Remove md5.c from the list.\n\t* md5.c, md5.h: Delete.\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Eliminate TOPDIR variable in favor of built-in\n\tautomake variables of top_builddir and top_srcdir.\n\n2009-12-17  John W. Eaton  <jwe@octave.org>\n\n\t* glob-match.h, glob-match.cc (glob_match::glob_internal):\n\tRename from glob_match::glob and make private.\n\t* glob-match.h (glob_match::glob): Forward to glob_internal.\n\n2009-12-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::index (const idx_vector&)): Fix determining of\n\tresult dimensions.\n\n2009-12-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Range.cc (Range::elem, Range::checkelem, Range::index):\n\tNew methods.\n\t* Range.h: Declare them.\n\n2009-12-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.h (idx_vector::loop, idx_vector::bloop): Fix behavior for\n\tmasks.\n\n2009-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Use DISTCLEANFILES rather than distclean-local rule.\n\tUse PERL variable defined by autoconf rather than direct call.\n\tUse simple_move_if_change rule to reduce useless compiles if\n\tOPTS_INC have not changed.\n\n2009-12-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-shlib.h: Remove stray declarations.\n\n2009-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* oct-shlib.cc (octave_dlopen_shlib::octave_dlopen_shlib):\n\tPrint filename along with message from dlerror.\n\tReverse sense of test.\n\n2009-12-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-shlib.h (octave_shlib): Rewrite.\n\t* oct-shlib.cc (octave_shlib): Rewrite.\n\n2009-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc (octave_base_tm::strftime): Call nstrftime instead\n\tof my_strftime.\n\n2009-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc: Include strftime.h.  Don't provide decl for strftime.\n\t(octave_base_tm::strftime): Call my_strftime instead of ::strftime.\n\t* Makefile.am (AM_CPPFLAGS): Add -I$(top_srcdir)/libgnu to the list.\n\t(LINK_DEPS): Add ../libgnu/libgnu.la to the list.\n\t(LIBOCTAVE_C_SOURCES): Remove strftime.c from the list.\n\t* strftime.c: Delete.\n\n2009-12-08  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Array-d.cc (Array<double>::is_sorted): Declare as OCTAVE_API.\n\t* Array-f.cc (Array<float>::is_sorted): Ditto.\n\t* lo-sysdep.cc: Undef min and max after including windows.h\n\n2009-12-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-d.cc (Array<double>::is_sorted): Optimized specialization.\n\t* Array-f.cc (Array<float>::is_sorted): Ditto.\n\n2009-12-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (lookup_binary): Remove.\n\t(octave_sort<T>::lookup (const T*, octave_idx_type, const T&, comp)):\n\tMove code here.\n\t(octave_sort<T>::lookup (const T*, octave_idx_type, const T*,\n\toctave_idx_type, octave_idx_type *, comp)): Remove offset parameter.\n\tUse a simple sequence of lookups.\n\t(octave_sort<T>::lookup (const T*, octave_idx_type, const T*,\n\toctave_idx_type, octave_idx_type *)): Update.\n\t(octave_sort<T>::lookupm, octave_sort<T>::lookupb): Remove.\n\t(octave_sort<T>::lookup_sorted): New overloaded method.\n\n\t* Array.cc (Array<T>::lookup (const Array<T>&, sortmode)): Remove\n\tlinf & rinf params. Rewrite using is_sorted to check for sortedness,\n\tcall octave_sort::lookup_sorted to do the sorted merge.\n\t(Array<T>::lookupm, Array<T>::lookupb): Remove.\n\t(NO_INSTANTIATE_ARRAY_SORT): Update.\n\n2009-12-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (sortrows_comparator): Rename to safe_comparator.\n\t(Array<T>::is_sorted): Use it here.\n\t* Array-d.cc: Update.\n\t* Array-f.cc: Update.\n\t* Array-C.cc: Update.\n\t* Array-fC.cc: Update.\n\n2009-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (BUILT_NODISTFILES): New variable.\n\n2009-12-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::idx_range_rep::unconvert,\n\tidx_vector::idx_scalar_rep::unconvert,\n\tidx_vector::idx_vector_rep::unconvert,\n\tidx_vector::idx_mask_rep::unconvert): New methods.\n\t(idx_vector::unconvert): Use them here. Add mask output.\n\t* idx-vector.h: Update decls.\n\n2009-11-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::zero_by_zero): New method.\n\t* idx-vector.h (idx_vector::idx_mask_rep::is_colon_equiv): Fix.\n\t* Array.cc (Array<T>::assign): Minor tweaks. Optimize\n\tA = []; A(1:m,1:n,1:k) = X for all cases. Use a shallow copy\n\tfor all colon-equivalent indices.\n\n2009-11-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.h (idx_vector::index_class): New member: class_mask.\n\t(idx_vector::idx_mask_rep): New class.\n\t(idx_vector::idx_vector (bool)): Construct idx_mask_rep.\n\t(idx_vector::unmask): New method decl.\n\t* idx-vector.cc (idx_vector::idx_vector (const boolNDArray&)):\n\tConstruct idx_mask_rep conditionally.\n\t(idx_vector::unmask): New method.\n\t(idx_vector::unconvert): Make non-const. unmask when called on a mask\n\tvector.\n\t(idx_vector::is_cont_range): Check also for idx_mask_rep.\n\n2009-11-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::nnz): New method.\n\t* Array.h: Declare it.\n\t* MArray.h (MArray<T>::nnz): Remove.\n\t* MArrayN.h (MArrayN<T>::nnz): Remove.\n\t* boolNDArray.h (boolNDArray::nnz): Remove.\n\n2009-11-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleCHOL.cc (CHOL::init): Output LAPACK's info. Resize matrix if\n\tnonzero. Use smarter copying.\n\t* floatCHOL.cc (FloatCHOL::init): Ditto.\n\t* CmplxCHOL.cc (ComplexCHOL::init): Ditto.\n\t* fCmplxCHOL.cc (FloatComplexCHOL::init): Ditto.\n\n2009-11-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* MArrayN.cc (MArrayN::idx_add): New methods.\n\t* MArrayN.h: Declare them.\n\t* MArray.cc, MArray.h: Remove from here.\n\n2009-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::safe_numel): New method.\n\t* Array.h (Array<T>::Array (const dim_vector&),\n\tArray<T>::Array (const dim_vector&, const T&),\n\tArray<T>::Array (T *, const dim_vector&)): Use it here.\n\t* Array.cc (Array<T>::clear (const dim_vector&)): Also here.\n\t(Array<T>::get_size): Remove.\n\t* Array2.h (Array2::get_size): Remove.\n\t* Array3.h (Array3::get_size): Remove.\n\n2009-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array::clear (const dim_vector&)): Use get_size.\n\n2009-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-mappers.cc (do_erfinv): New static function.\n\t(erfinv (double), erfinv (float)): New mappers.\n\t* lo-mappers.h: Declare them.\n\n2009-11-18  David Grundberg  <davidg@cs.umu.se>\n\n       * str-vec.cc (string_vector::list_in_columns): Avoid crash on\n       empty arguments from list_in_columns.\n\n2009-11-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.h (read_sparse_matrix): Fix order of tests and reads.\n\n2009-11-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_any_negative, mx_inline_pow): New loops.\n\t(DEFMXMAPPER2X): New macro.\n\t* bsxfun-decl.h (BSXFUN_OP2_DECL): New macro.\n\t* bsxfun-defs.cc (BSXFUN_OP2_DEF, BSXFUN_OP2_DEF_MXLOOP): New macros.\n\t(do_bsxfun_op): Use OCTAVE_QUIT.\n\t* dNDArray.cc (NDArray::all_integers (void)): New method.\n\t(NDArray::any_element_is_negative): Use mx_inline_any_negative.\n\t(bsxfun_pow (const NDArray&, const NDArray&),\n\tbsxfun_pow (const ComplexNDArray&, const NDArray&)): New functions.\n\t* dNDArray.h: Update.\n\t* fNDArray.cc (FloatNDArray::all_integers (void)): New method.\n\t(FloatNDArray::any_element_is_negative): Use mx_inline_any_negative.\n\t(bsxfun_pow (const FloatNDArray&, const FloatNDArray&),\n\tbsxfun_pow (const FloatComplexNDArray&, const FloatNDArray&)):\n\tNew functions.\n\t* fNDArray.h: Update.\n\t* CNDArray.cc (bsxfun_pow (const ComplexNDArray&, const\n\tComplexNDArray&)): New function.\n\t* CNDArray.h: Update.\n\t* fCNDArray.cc (bsxfun_pow (const FloatComplexNDArray&, const\n\tFloatComplexNDArray&)): New function.\n\t* fCNDArray.h: Update.\n\n2009-11-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CNDArray.cc (ComplexNDArray::all_elements_are_real):\n\tUse mx_inline_all_real.\n\t* CMatrix.cc (ComplexMatrix::all_elements_are_real): Ditto.\n\t* fCNDArray.cc (FloatComplexNDArray::all_elements_are_real):\n\tUse mx_inline_all_real.\n\t* fCMatrix.cc (FloatComplexMatrix::all_elements_are_real): Ditto.\n\t* CDiagMatrix.cc (ComplexDiagMatrix::all_elements_are_real): Ditto.\n\t* fCDiagMatrix.cc (FloatComplexDiagMatrix::all_elements_are_real):\n\tDitto.\n\t* CSparse.cc (SparseComplexMatrix::all_elements_are_real): Ditto.\n\n2009-11-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* base-aepbal.h (permuting_vector): Fix lower part swapping.\n\n2009-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (liboctave_la_CPPFLAGS): Add @OCTAVE_DLL_DEFS@ to\n\tthe list of flags.\n\n2009-11-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_any_nan): Rewrite.\n\t(mx_inline_all_real): New reduction loop.\n\n2009-11-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-mappers.cc ( rc_acos, rc_acos, rc_acosh, rc_acosh, rc_asin,\n\trc_asin, rc_atanh, rc_atanh, rc_log, rc_log, rc_xlog2, rc_log2,\n\trc_log10, rc_log10, rc_sqrt, rc_sqrt): New mappers.\n\t* lo-mappers.h: Declare them.\n\n\t* lo-specfun.cc (rc_lgamma, rc_lgamma, rc_log1p, rc_log1p): New\n\tmappers.\n\t* lo-specfun.h: Declare them.\n\t* Array.h (Array<T>::map): Unroll loop to reduce OCTAVE_QUIT checking.\n\tProvide function-reference overloads.\n\n\t* MArray.h (MArray<T>::map): Provide function-reference overloads.\n\t* Array2.h (Array2<T>::map): Ditto.\n\t* MArray2.h (MArray2<T>::map): Ditto.\n\n\t* Sparse.h (Sparse<T>::map): Ditto.\n\t* MSparse.h (MSparse<T>::map): Ditto.\n\n\t* dNDArray.h (NDArray::map): Remove.\n\t* dNDArray.cc (NDArray::map): Remove.\n\t* fNDArray.h (FloatNDArray::map): Remove.\n\t* fNDArray.cc (FloatNDArray::map): Remove.\n\t* CNDArray.h (ComplexNDArray::map): Remove.\n\t* CNDArray.cc (ComplexNDArray::map): Remove.\n\t* fCNDArray.h (FloatComplexNDArray::map): Remove.\n\t* fCNDArray.cc (FloatComplexNDArray::map): Remove.\n\n\t* dMatrix.h (Matrix::map): Remove.\n\t* dMatrix.cc (Matrix::map): Remove.\n\t* fMatrix.h (FloatMatrix::map): Remove.\n\t* fMatrix.cc (FloatMatrix::map): Remove.\n\t* CMatrix.h (ComplexMatrix::map): Remove.\n\t* CMatrix.cc (ComplexMatrix::map): Remove.\n\t* fCMatrix.h (FloatComplexMatrix::map): Remove.\n\t* fCMatrix.cc (FloatComplexMatrix::map): Remove.\n\n\t* dRowVector.h (RowVector::map): Remove.\n\t* dRowVector.cc (RowVector::map): Remove.\n\t* fRowVector.h (FloatRowVector::map): Remove.\n\t* fRowVector.cc (FloatRowVector::map): Remove.\n\t* CRowVector.h (ComplexRowVector::map): Remove.\n\t* CRowVector.cc (ComplexRowVector::map): Remove.\n\t* fCRowVector.h (FloatComplexRowVector::map): Remove.\n\t* fCRowVector.cc (FloatComplexRowVector::map): Remove.\n\n\t* dColVector.h (ColumnVector::map): Remove.\n\t* dColVector.cc (ColumnVector::map): Remove.\n\t* fColVector.h (FloatColumnVector::map): Remove.\n\t* fColVector.cc (FloatColumnVector::map): Remove.\n\t* CColVector.h (ComplexColumnVector::map): Remove.\n\t* CColVector.cc (ComplexColumnVector::map): Remove.\n\t* fCColVector.h (FloatComplexColumnVector::map): Remove.\n\t* fCColVector.cc (FloatComplexColumnVector::map): Remove.\n\n\t* dSparse.h (SparseMatrix::map): Remove.\n\t* dSparse.cc (SparseMatrix::map): Remove.\n\t* CSparse.h (SparseComplexMatrix::map): Remove.\n\t* CSparse.cc (SparseComplexMatrix::map): Remove.\n\n2009-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* lo-ieee.cc (octave_ieee_init): Improve comment about systems\n\twithout IEEE floating point format.\n\n2009-11-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_map): New template loop.\n\t(DEFMXMAPPER): New macro.\n\t(DEFMXMAPPER2): Rename from DEFMXMAPPER.\n\t(do_mx_unary_map): New applier.\n\t(mx_inline_real, mx_inline_complex): New loops.\n\t* dNDArray.cc (NDArray::abs, NDArray::isnan, NDArray::isinf,\n\tNDArray::isfinite, real, imag): Use new constructs.\n\t* fNDArray.cc (FloatNDArray::abs, FloatNDArray::isnan,\n\tFloatNDArray::isinf, FloatNDArray::isfinite, real, imag): Ditto.\n\t* CNDArray.cc (ComplexNDArray::abs, ComplexNDArray::isnan,\n\tComplexNDArray::isinf, ComplexNDArray::isfinite, conj): Use new\n\tconstructs.\n\t* fCNDArray.cc (FloatComplexNDArray::abs, FloatComplexNDArray::isnan,\n\tFloatComplexNDArray::isinf, FloatComplexNDArray::isfinite, conj): Use\n\tnew constructs.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* mx-ops, sparse-mx-ops, vx-ops, vx-ops:\n\tAdd comment about updating.\n\t* Makefile.am, config-ops.sh: New files.\n\t* Makefile.in: Delete.\n\n2009-11-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dSparse.h (Sparse::max): Use Array<octave_idx_type>.\n\t* dSparse.cc: Update.\n\t* CSparse.h (Sparse::max): Use Array<octave_idx_type>.\n\t* CSparse.cc: Update.\n\t* dNDArray.h (NDArray::max, NDArray::min, NDArray::cummax,\n\tNDArray::cummin, NDArray::diff): Use dim = -1 as default.\n\t* fNDArray.h (FloatNDArray::max, FloatNDArray::min, FloatNDArray::cummax,\n\tFloatNDArray::cummin, FloatNDArray::diff): Use dim = -1 as default.\n\t* CNDArray.h (ComplexNDArray::max, ComplexNDArray::min,\n\tComplexNDArray::cummax, ComplexNDArray::cummin, ComplexNDArray::diff):\n\tUse dim = -1 as default.\n\t* fCNDArray.h (FloatComplexNDArray::max, FloatComplexNDArray::min,\n\tFloatComplexNDArray::cummax, FloatComplexNDArray::cummin,\n\tFloatComplexNDArray::diff): Use dim = -1 as default.\n\t* intNDArray.h (intNDArray::max, intNDArray::min, intNDArray::cummax,\n\tintNDArray::cummin, intNDArray::diff): Use dim = -1 as default.\n\n2009-11-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-mem.h: Rename octave_ucopy -> copy_or_memcpy,\n\toctave_fill -> fill_or_memset, octave_new -> no_ctor_new,\n\toctave_delete -> no_ctor_delete.\n\t* Array.h: Update.\n\t* Array.cc: Update.\n\t* idx-vector.h: Update.\n\t* idx-vector.cc: Update.\n\n2009-11-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-mem.h: New source.\n\t* Makefile.in: Include it.\n\t* Array.h (Array<T>::ArrayRep::ArrayRep (...)): Use octave_new,\n\toctave_ucopy and octave_fill.\n\t(Array<T>::ArrayRep::~ArrayRep): Use octave_delete.\n\t(Array<T>::coerce): Use octave_new.\n\t* Array.cc (Array<T>::fill, rec_resize_helper::do_resize_fill,\n\tArray<T>::resize_fill, rec_permute_helper::do_permute,\n\tArray<T>::delete_elements): Use octave_ucopy and octave_fill.\n\t* idx-vector.h (index_vector::index, index_vector::assign): Use\n\toctave_ucopy.\n\t* idx-vector.cc (index_vector::copy_data): Ditto.\n\n2009-11-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::maybe_reduce): Implement (i:k:end, :)\n\tand (i:k:end, p:q) reductions.\n\n2009-11-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (twosum_accum): Remove FLOAT_TRUNCATE.\n\n2009-10-28  John W. Eaton  <jwe@octave.org>\n\n\t* PermMatrix.cc: Don't include error.h.\n\n2009-10-27  David Bateman  <dbateman@free.fr>\n\n\t* SparsedbleLU.cc (SparseLU::SparseLU (const SparseMatrix&,\n\tconst Matrix&, bool), SparseLU::SparseLU (const SparseMatrix&,\n\tconst ColumnVector&, const Matrix&, boo, bool, double, bool,\n\tbool)): Fix test for valid pivot tolerance.\n\t* SparseCmplxLU.cc (SparseComplexLU::SparseComplexLU\n\t(const SparseComplexMatrix&, const Matrix&, bool),\n\tSparseComplexLU::SparseComplexLU (const SparseComplexMatrix&,\n\tconst ColumnVector&, const Matrix&, boo, bool, double, bool,\n\tbool)): Ditto.\n\n2009-10-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::idx_range_rep::idx_range_rep\n\t(octave_idx_type, octave_idx_type, octave_idx_type)):\n\tImprove checking.\n\n2009-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.h \t(octave_time::octave_time (time_t t, int us)):\n\tNew constructor.\n\t(operator + (const octave_time&, const octave_time&)): New function.\n\n\t* file-stat.h (base_file_stat::time_resolution): New function.\n\n2009-10-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* bsxfun-decl.h, bsxfun-defs.cc: New sources.\n\t* Makefile.in: Add them.\n\t* dim-vector.h (dim_vector::compute_index,\n\tdim_vector::increment_index): Fix.\n\t* mx-inlines.cc (DEFMXMAPPER, DEFMXLOCALMAPPER): New macros.\n\t(mx_inline_xmin, mx_inline_xmax): New loops.\n\t(mx_inline_fun): Remove.\n\t* oct-inttypes.h (xmin (const octave_int<T>&, const octave_int<T>&),\n\txmax (const octave_int<T>&, const octave_int<T>&)):\n\tNew inline functions.\n\n\t* CNDArray.cc: Define bsxfun operations.\n\t* boolNDArray.cc: Ditto.\n\t* dNDArray.cc: Ditto.\n\t* fCNDArray.cc: Ditto.\n\t* fNDArray.cc: Ditto.\n\t* int16NDArray.cc: Ditto.\n\t* int32NDArray.cc: Ditto.\n\t* int64NDArray.cc: Ditto.\n\t* int8NDArray.cc: Ditto.\n\t* uint16NDArray.cc: Ditto.\n\t* uint32NDArray.cc: Ditto.\n\t* uint64NDArray.cc: Ditto.\n\t* uint8NDArray.cc: Ditto.\n\n\t* CNDArray.h: Declare bsxfun operations.\n\t* boolNDArray.h: Ditto.\n\t* dNDArray.h: Ditto.\n\t* fCNDArray.h: Ditto.\n\t* fNDArray.h: Ditto.\n\t* int16NDArray.h: Ditto.\n\t* int32NDArray.h: Ditto.\n\t* int64NDArray.h: Ditto.\n\t* int8NDArray.h: Ditto.\n\t* uint16NDArray.h: Ditto.\n\t* uint32NDArray.h: Ditto.\n\t* uint64NDArray.h: Ditto.\n\t* uint8NDArray.h: Ditto.\n\n2009-10-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::compute_index,\n\tdim_vector::increment_index, dim_vector::cumulative,\n\tdim_vector::cum_compute_index): New methods.\n\n2009-10-18  Carsten Clark  <tantumquantum+gnuoctave@gmail.com>\n\n\t* Makefile.in: Remove ArrayN.cc.\n\n2009-10-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Makefile.in: Include base-qr.h and base-qr.cc.\n\n2009-10-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleQR.cc: Initialize QR::raw, QR::economy and QR::std.\n\n2009-10-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ArrayN.h: Remove everything, just #define ArrayN Array.\n\tWarn if under gcc.\n\t* ArrayN.cc: Remove.\n\t* Array.cc (operator >>): New operator.\n\t* Array.h: Declare it.\n\n\t* Array-C.cc: Remove traces of ArrayN.\n\t* Array-b.cc: Ditto.\n\t* Array-ch.cc: Ditto.\n\t* Array-d.cc: Ditto.\n\t* Array-f.cc: Ditto.\n\t* Array-fC.cc: Ditto.\n\t* CNDArray.cc: Ditto.\n\t* CNDArray.h: Ditto.\n\t* MArrayN.h: Ditto.\n\t* boolNDArray.cc: Ditto.\n\t* boolNDArray.h: Ditto.\n\t* chNDArray.h: Ditto.\n\t* dNDArray.cc: Ditto.\n\t* dNDArray.h: Ditto.\n\t* fCNDArray.cc: Ditto.\n\t* fCNDArray.h: Ditto.\n\t* fNDArray.cc: Ditto.\n\t* fNDArray.h: Ditto.\n\t* intNDArray.cc: Ditto.\n\t* intNDArray.h: Ditto.\n\t* lo-specfun.cc: Ditto.\n\t* lo-specfun.h: Ditto.\n\n\t* mx-op-defs.h (DMS_BIN_OP, SDM_BIN_OP): Rewrite.\n\t(DMS_BIN_OPS, SDM_BIN_OPS): Define dm*s and dm/s rather than dm+s and\n\tdm-s which are rather useless.\n\t* mx-ops: Update.\n\n2009-10-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::column, Array<T>::page, Array<T>::linearize,\n\tArray<T>::linear_slice): New methods.\n\t* Array.h: Declare them\n\t* ArrayN.h: Forward them.\n\n2009-10-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (octave_sort<T>::nth_element): New overloaded method.\n\t* oct-sort.h: Declare it.\n\t* Array.cc (Array<T>::nth_element): New method.\n\t* Array.h: Declare it.\n\t(Array<T>::sort): Use int for dim argument.\n\t* ArrayN.h (ArrayN<T>::nth_element): Wrap.\n\t(ArrayN<T>::sort): Use int for dim argument.\n\n2009-10-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-traits.h (equal_types, is_instance, subst_template_param): New\n\ttraits classes.\n\t* mx-inlines.cc (op_dble_sum, twosum_accum): New helper funcs.\n\t(mx_inline_dsum, mx_inline_xsum): New reduction loops.\n\t* fNDArray.cc (FloatNDArray::dsum): New method.\n\t* fNDArray.h: Declare it.\n\t* fCNDArray.cc (FloatComplexNDArray::dsum): New method.\n\t* fCNDArray.h: Declare it.\n\t* dNDArray.cc (NDArray::xsum): New method.\n\t* dNDArray.h: Declare it.\n\t* CNDArray.cc (ComplexNDArray::xsum): New method.\n\t* CNDArray.h: Declare it.\n\t* intNDArray.cc (intNDArray::dsum): New method.\n\t* intNDArray.h: Declare it.\n\n2009-10-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* base-qr.cc (base_qr::regular): New method.\n\t* base-qr.h: Declare it.\n\t* base-lu.cc (base_lu::regular): New method.\n\t* base-lu.h: Declare it.\n\n2009-10-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* base-qr.h: New source.\n\t* base-qr.cc: New source.\n\t* dbleQR.h (QR): Rebase on base_qr<Matrix>.\n\t* dbleQR.cc: Ditto.\n\t* floatQR.h (QR): Rebase on base_qr<FloatMatrix>.\n\t* floatQR.cc: Ditto.\n\t* CmplxQR.h (QR): Rebase on base_qr<ComplexMatrix>.\n\t* CmplxQR.cc: Ditto.\n\t* fCmplxQR.h (QR): Rebase on base_qr<FloatComplexMatrix>.\n\t* fCmplxQR.cc: Ditto.\n\t* dbleQRP.h (QR): Update.\n\t* dbleQRP.cc: Ditto.\n\t* floatQRP.h (QR): Update.\n\t* floatQRP.cc: Ditto.\n\t* CmplxQRP.h (QR): Update.\n\t* CmplxQRP.cc: Ditto.\n\t* fCmplxQRP.h (QR): Update.\n\t* fCmplxQRP.cc: Ditto.\n\n2009-10-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* PermMatrix.cc (PermMatrix::eye): New method.\n\t* PermMatrix.h: Declare it.\n\t* dbleLU.cc (LU::update, LU::update_piv): New overloaded methods.\n\t* dbleLU.h: Declare them.\n\t* floatLU.cc (FloatLU::update, FloatLU::update_piv): New overloaded\n\tmethods.\n\t* floatLU.h: Declare them.\n\t* CmplxLU.cc (ComplexLU::update, ComplexLU::update_piv): New\n\toverloaded methods.\n\t* CmplxLU.h: Declare them.\n\t* fCmplxLU.cc (FloatComplexLU::update, FloatComplexLU::update_piv):\n\tNew overloaded methods.\n\t* fCmplxLU.h: Declare them.\n\n2009-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* mx-inlines.cc (mx_inline_diff): Avoid uninitialized variable warning.\n\n2009-10-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dDiagMatrix.cc (operator *(const DiagMatrix&, const DiagMatrix&)):\n\tRewrite.\n\t* fDiagMatrix.cc (operator *(const FloatDiagMatrix&, const FloatDiagMatrix&)):\n\tRewrite.\n\t* CDiagMatrix.cc (operator *(const ComplexDiagMatrix&, const ComplexDiagMatrix&)):\n\tRewrite.\n\t* fCDiagMatrix.cc (operator *(const FloatComplexDiagMatrix&, const\n\tFloatComplexDiagMatrix&)):\n\tRewrite.\n\t* DiagArray2.h (DiagArray2::diag_length): New method.\n\t* PermMatrix.h (PermMatrix::length): Make consistent with\n\tDiagArray2::length.\n\n2009-10-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* base-lu.cc (base_lu::unpack): Unpack getp as well.\n\n2009-10-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* PermMatrix.cc (PermMatrix::determinant): Implement a (hopefully)\n\tworking algorithm.\n\n2009-10-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (operator ==): Include fast case.\n\t* base-lu.cc (base_lu::packed, base_lu::unpack): New methods.\n\t(base_lu::L, base_lu::U, base_lu::Y, base_lu::getp): Distinguish\n\tpacked vs. unpacked case.\n\t* base-lu.h: Update decls.\n\t(base_lu::l_fact): New member field.\n\n2009-10-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-traits.h (strip_template_param): New trait class.\n\n2009-10-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::permute): Fast case identity permutation.\n\n2009-09-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-cmplx.h: Fix complex-real orderings.\n\n2009-09-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::redim): Rewrite.\n\t* Array-util.cc (sub2ind): Allow single index case.\n\n2009-09-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (xgemm): Use blas_trans_type to indicate transposes.\n\t(operator *(const Matrix&, const Matrix&)): Update.\n\t* fMatrix.cc (xgemm): Use blas_trans_type to indicate transposes.\n\t(operator *(const FloatMatrix&, const FloatMatrix&)): Update.\n\t* CMatrix.cc (xgemm): Use blas_trans_type to indicate transposes.\n\t(operator *(const ComplexMatrix&, const ComplexMatrix&)): Update.\n\t* fCMatrix.cc (xgemm): Use blas_trans_type to indicate transposes.\n\t(operator *(const FloatComplexMatrix&, const FloatComplexMatrix&)): Update.\n\t* dMatrix.h: Update decl.\n\t* fMatrix.h: Update decl.\n\t* CMatrix.h: Update decl.\n\t* fCMatrix.h: Update decl.\n\n2009-09-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CMatrix.cc (ComplexMatrix::ComplexMatrix (const Matrix&, const\n\tMatrix&)): New constructor.\n\t(operator * (Matrix, ComplexMatrix), operator * (ComplexMatrix,\n\tMatrix)): Optimize.\n\t* fCMatrix.cc (FloatComplexMatrix::FloatComplexMatrix (const FloatMatrix&, const\n\tFloatMatrix&)): New constructor.\n\t(operator * (FloatMatrix, FloatComplexMatrix), operator * (FloatComplexMatrix,\n\tFloatMatrix)): Optimize.\n\n2009-09-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (stack_complex_matrix, unstack_complex_matrix): New\n\tstatic funcs.\n\t(Matrix::solve (..., const ComplexMatrix&, ...)): Use the above funcs.\n\tImprove forwarding.\n\t* fMatrix.cc (stack_complex_matrix, unstack_complex_matrix): New\n\tstatic funcs.\n\t(FloatMatrix::solve (..., const FloatComplexMatrix&, ...)): Use the\n\tabove funcs.  Improve forwarding.\n\n2009-09-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-defs.h (blas_trans_type): New enum.\n\t(get_blas_char): New inline func.\n\t* dMatrix.cc (Matrix::utsolve, Matrix::ltsolve, Matrix::solve):\n\tSupport transt parameter.\n\t* fMatrix.cc (FloatMatrix::utsolve, FloatMatrix::ltsolve,\n\tFloatMatrix::solve): Ditto.\n\t* CMatrix.cc (ComplexMatrix::utsolve, ComplexMatrix::ltsolve,\n\tComplexMatrix::solve): Ditto.\n\t* fCMatrix.cc (FloatComplexMatrix::utsolve,\n\tFloatComplexMatrix::ltsolve, FloatComplexMatrix::solve): Ditto.\n\t* dMatrix.h, fMatrix.h, CMatrix.h, fCMatrix.h: Update.\n\n2009-09-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-op-defs.h (VS_BIN_OP, SV_BIN_OP, VV_BIN_OP): Simplify.\n\n2009-09-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dNDArray.h (NDArray::matrix_type): New typedef.\n\t* fNDArray.h (FloatNDArray::matrix_type): New typedef.\n\t* CNDArray.h (ComplexNDArray::matrix_type): New typedef.\n\t* fCNDArray.h (FloatComplexNDArray::matrix_type): New typedef.\n\t* boolNDArray.h (boolNDArray::matrix_type): New typedef.\n\t* charNDArray.h (charNDArray::matrix_type): New typedef.\n\n\t* dMatrix.h (Matrix::column_vector_type,\n\tMatrix::row_vector_type): New typedefs.\n\t* fMatrix.h (FloatMatrix::column_vector_type,\n\tFloatMatrix::row_vector_type): New typedefs.\n\t* CMatrix.h (ComplexMatrix::column_vector_type,\n\tComplexMatrix::row_vector_type): New typedefs.\n\t* fCMatrix.h (FloatComplexMatrix::column_vector_type,\n\tFloatComplexMatrix::row_vector_type): New typedefs.\n\n2009-09-18  John W. Eaton  <jwe@octave.org>\n\n\t* mach-info.cc: Don't include oct-types.h.\n\n2009-09-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (NoAlias): New template class.\n\t* dRowVector.cc (linspace): Rewrite.\n\t* fRowVector.cc (linspace): Rewrite.\n\t* CRowVector.cc (linspace): Rewrite.\n\t* fCRowVector.cc (linspace): Rewrite.\n\t* dMatrix.cc (linspace): New method.\n\t* dMatrix.h (linspace): Declare it.\n\t* fMatrix.cc (linspace): New method.\n\t* fMatrix.h (linspace): Declare it.\n\t* CMatrix.cc (linspace): New method.\n\t* CMatrix.h (linspace): Declare it.\n\t* fCMatrix.cc (linspace): New method.\n\t* fCMatrix.h (linspace): Declare it.\n\n2009-09-17  John W. Eaton  <jwe@octave.org>\n\n\t* oct-types.h.in: Delete.\n\t* Makefile.in (BUILT_INCLUDES, DISTFILES): Remove oct-types.h.in\n\tfrom the list.\n\t(distclean, maintainer-clean): Don't remove oct-types.h\n\t* DAEFunc.h, MatrixType.h, base-aepbal.h, dim-vector.h,\n\tlo-specfun.h, lo-utils.h, mx-op-decl.h, oct-inttypes.h,\n\trandgamma.h, randmtzig.h, randpoisson.h:\n\tDon't include oct-types.h.\n\n2009-09-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-rand.cc (octave_rand::do_matrix, do_nd_array, do_vector):\n\tUse Array::clear rather than Array::resize.\n\n2009-09-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dColVector.h (operator *(const Matrix&, const ColumnVector)):\n\tOptimize.\n\t* fColVector.h (operator *(const FloatMatrix&, const\n\tFloatColumnVector)): Optimize.\n\t* CColVector.h (operator *(const ComplexMatrix&, const\n\tComplexColumnVector)): Optimize.\n\t* fCColVector.h (operator *(const FloatComplexMatrix&, const\n\tFloatComplexColumnVector)): Optimize.\n\n2009-09-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::clear (const dim_vector&)): new method.\n\t* Array.h: Declare it.\n\t(Array<T>::clear (octave_idx_type)): New method.\n\t(Array<T>::clear (octave_idx_type, octave_idx_type)): New method.\n\n2009-09-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (DEFMXBOOLOPEQ): New macro.\n\t(mx_inline_and2, mx_inline_or2): New loops.\n\n\t* MArray.h (MArray<T>::MArray (const dim_vector&)): New constructor.\n\t(MArray<T>::MArray (const Array<T>&)): Ensure column vector.\n\t(MArray<T>::resize): New method.\n\t* DiagArray2.h (DiagArray2<T>::DiagArray2 (const dim_vector&)): New\n\tconstructor.\n\t* MDiagArray2.h (MDiagArray2<T>::MDiagArray2 (const dim_vector&)): New\n\tconstructor.\n\t* dColVector.h (ColumnVector::ColumnVector (const dim_vector&)): New\n\tconstructor.\n\t* fColVector.h (FloatColumnVector::FloatColumnVector (const\n\tdim_vector&)): New constructor.\n\t* CColVector.h (ComplexColumnVector::ComplexColumnVector (const\n\tdim_vector&)): New constructor.\n\t* fCColVector.h (FloatComplexColumnVector::FloatComplexColumnVector\n\t(const dim_vector&)): New constructor.\n\t* dRowVector.h (RowVector::RowVector (const dim_vector&)): New\n\tconstructor.\n\t* fRowVector.h (FloatRowVector::FloatRowVector (const dim_vector&)):\n\tNew constructor.\n\t* CRowVector.h (ComplexRowVector::ComplexRowVector (const\n\tdim_vector&)): New constructor.\n\t* fCRowVector.h (FloatComplexRowVector::FloatComplexRowVector (const\n\tdim_vector&)): New constructor.\n\n\t* CNDArray.cc (operator *= (const ComplexNDArray, double)): Simplify.\n\t* fCNDArray.cc (operator *= (const FloatComplexNDArray, float)): Simplify.\n\n\t* MArray.cc\n\t(operator += (MArray<T>&, const T&)): Simplify.\n\t(operator -= (MArray<T>&, const T&)): Simplify.\n\t(operator *= (MArray<T>&, const T&)): Simplify.\n\t(operator /= (MArray<T>&, const T&)): Simplify.\n\t(operator += (MArray<T>&, const MArray<T>&)): Simplify.\n\t(operator -= (MArray<T>&, const MArray<T>&)): Simplify.\n\t(product (MArray<T>&, const MArray<T>&)): Simplify.\n\t(quotient (MArray<T>&, const MArray<T>&)): Simplify.\n\t(MARRAY_AS_OP): Simplify.\n\t(MARRAY_SA_OP): Simplify.\n\t(MARRAY_AA_OP): Simplify.\n\t(operator - (const MArray<T>&)): Simplify.\n\n\t* MArray2.cc\n\t(operator += (MArray2<T>&, const T&)): Simplify.\n\t(operator -= (MArray2<T>&, const T&)): Simplify.\n\t(operator *= (MArray2<T>&, const T&)): Simplify.\n\t(operator /= (MArray2<T>&, const T&)): Simplify.\n\t(operator += (MArray2<T>&, const MArray<T>&)): Simplify.\n\t(operator -= (MArray2<T>&, const MArray<T>&)): Simplify.\n\t(product (MArray2<T>&, const MArray<T>&)): Simplify.\n\t(quotient (MArray2<T>&, const MArray<T>&)): Simplify.\n\t(MARRAY_A2S_OP): Simplify.\n\t(MARRAY_SA2_OP): Simplify.\n\t(MARRAY_A2A2_OP): Simplify.\n\t(operator - (const MArray2<T>&)): Simplify.\n\n\t* MArrayN.cc\n\t(operator += (MArrayN<T>&, const T&)): Simplify.\n\t(operator -= (MArrayN<T>&, const T&)): Simplify.\n\t(operator *= (MArrayN<T>&, const T&)): Simplify.\n\t(operator /= (MArrayN<T>&, const T&)): Simplify.\n\t(operator += (MArrayN<T>&, const MArray<T>&)): Simplify.\n\t(operator -= (MArrayN<T>&, const MArray<T>&)): Simplify.\n\t(product (MArrayN<T>&, const MArray<T>&)): Simplify.\n\t(quotient (MArrayN<T>&, const MArray<T>&)): Simplify.\n\t(MARRAY_NDS_OP): Simplify.\n\t(MARRAY_SND_OP): Simplify.\n\t(MARRAY_NDND_OP): Simplify.\n\t(operator - (const MArrayN<T>&)): Simplify.\n\n\t* MDiagArray2.cc\n\t(operator += (MDiagArray2<T>&, const MDiagArray2<T>&)): Simplify.\n\t(operator -= (MDiagArray2<T>&, const MDiagArray2<T>&)): Simplify.\n\t(operator *= (MDiagArray2<T>&, T)): Simplify.\n\t(operator /= (MDiagArray2<T>&, T)): Simplify.\n\t(MARRAY_DAS_OP, MARRAY_SDA_OP, MARRAY_DADA_OP): Simplify.\n\t* boolNDArray.cc (mx_el_and_assign, mx_el_or_assign): Simplify.\n\n\t* MArray-defs.h (DO_VS_OP, DO_SV_OP, DO_VV_OP,\n\tDO_VS_OP2, DO_VV_OP2, NEGV): Remove.\n\n2009-09-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (DEFMXUNOPEQ): New macro.\n\t(mx_inline_not2, mx_inline_uminus2): New loops.\n\t* boolNDArray.cc (boolNDArray::invert): New method.\n\t* boolNDArray.h: Declare it.\n\t* MArrayN.cc (MArrayN<T>::changesign): New method.\n\t* MArrayN.h: Declare it.\n\t* dNDArray.cc (NDArray::changesign): New method.\n\t* dNDArray.h: Declare it.\n\t* fNDArray.cc (FloatNDArray::changesign): New method.\n\t* fNDArray.h: Declare it.\n\t* CNDArray.cc (ComplexNDArray::changesign): New method.\n\t* CNDArray.h: Declare it.\n\t* fCNDArray.cc (FloatComplexNDArray::changesign): New method.\n\t* fCNDArray.h: Declare it.\n\t* intNDArray.cc (intNDArray::changesign): New method.\n\t* intNDArray.h: Declare it.\n\n2009-09-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-cmplx.h: Rewrite the comaprison ops. Use FLOAT_TRUNCATE.\n\n2009-09-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-cmplx.h: Correct strict operators in macros.\n\n2009-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* lo-ieee.cc (octave_ieee_init): Abort if floating point format\n\tis not recognized as IEEE.\n\n2009-08-27  John W. Eaton  <jwe@octave.org>\n\n\t* str-vec.cc, str-vec.h (string_vector::string_vector (const\n\tstd::set<std::string>&)): New constructor.\n\n2009-08-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (DEFCMPLXCMOP): Remove.\n\t* oct-cmplx.h (operator <, operator >): Remove definitions.\n\t(DEF_COMPLEXR_COMP): New macro. Instantiate for <, >, <=, >=.\n\t* mx-op-defs.h (MM_CMP_OP, MS_CMP_OP, SM_CMP_OP,\n\tNDND_CMP_OP, NDS_CMP_OP, SND_CMP_OP): Replace by one-liners. Remove\n\tunused parameters.\n\t(MM_CMP_OPS, MS_CMP_OPS, SM_CMP_OPS, NDND_CMP_OPS, NDS_CMP_OPS,\n\tSND_CMP_OPS): Update.\n\t(NDS_CMP_OP1, NDS_CMP_OPS1, NDS_CMP_OP2, NDS_CMP_OPS2,\n\tSND_CMP_OP1, SND_CMP_OPS1, SND_CMP_OP2, SND_CMP_OPS2): Remove.\n\t* mk-ops.awk: Simplify CMP_OPS branch.\n\t* Sparse-op-defs.h (SPARSE_SMSM_CMP_OPS, SPARSE_SMS_CMP_OPS,\n\tSPARSE_SSM_CMP_OPS, SPARSE_MSM_CMP_OPS, SPARSE_SMM_CMP_OPS):\n\tUpdate.\n\n\t* CNDArray.cc: Update syntax.\n\t* boolNDArray.cc: Ditto.\n\t* chNDArray.cc: Ditto.\n\t* dNDArray.cc: Ditto.\n\t* fCNDArray.cc: Ditto.\n\t* fNDArray.cc: Ditto.\n\n\t* int16NDArray.cc: Ditto.\n\t* int32NDArray.cc: Ditto.\n\t* int64NDArray.cc: Ditto.\n\t* int8NDArray.cc: Ditto.\n\t* uint16NDArray.cc: Ditto.\n\t* uint32NDArray.cc: Ditto.\n\t* uint64NDArray.cc: Ditto.\n\t* uint8NDArray.cc: Ditto.\n\n\t* CMatrix.cc: Ditto.\n\t* boolMatrix.cc: Ditto.\n\t* chMatrix.cc: Ditto.\n\t* dMatrix.cc: Ditto.\n\t* fCMatrix.cc: Ditto.\n\t* fMatrix.cc: Ditto.\n\n2009-08-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* MArray.cc (MArray<T>::product_eq, MArray<T>::quotient_eq): New\n\tmethods.\n\t* MArray2.cc (MArray2<T>::product_eq, MArray2<T>::quotient_eq): Ditto.\n\t* MArrayN.cc (MArrayN<T>::product_eq, MArrayN<T>::quotient_eq): Ditto.\n\t* MArray-decl.h (MARRAY_OP_ASSIGN_DECLX): New macro.\n\t(MARRAY_OP_ASSIGN_DECLS, MARRAY_OP_ASSIGN_FWD_DEFS): Include\n\tproduct_eq and quotient_eq.\n\t(MARRAY_FORWARD_DEFS): Use MARRAY_OP_ASSIGN_FWD_DEFS1.\n\t(MDIAGARRAY2_OPS_FORWARD_DECLS): Don't instantiate\n\tOP= operators for diag matrices.\n\t(MDIAGARRAY2_FORWARD_DEFS): Ditto.\n\t* MArray-defs.h (INSTANTIATE_MDIAGARRAY2_FRIENDS): Ditto.\n\n2009-08-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array::make_unique, Array::~Array, Array::operator =):\n\tMove here to allow inlining.\n\t* Array.cc: Remove from here.\n\n2009-08-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (logical_value): New overloaded template.\n\t(DEFMXBOOL_OP): Use it in definitions.\n\t(mx_inline_not): Also use logical_value.\n\t* mx-op-defs.h (ND_LOGICAL_NAN_CHECK, SC_LOGICAL_NAN_CHECK): Remove\n\t(also from all macros).\n\n\t* CMatrix.cc (operator !): Simply call mx_inline_not.\n\t* CNDArray.cc: Ditto.\n\t* dMatrix.cc: Ditto.\n\t* dNDArray.cc: Ditto.\n\t* fCMatrix.cc: Ditto.\n\t* fCNDArray.cc: Ditto.\n\t* fMatrix.cc: Ditto.\n\t* fNDArray.cc: Ditto.\n\n2009-08-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (Matrix::operator!): Simplify & check for NaNs.\n\t* fMatrix.cc (FloatMatrix::operator!): Ditto.\n\t* CMatrix.cc (ComplexMatrix::operator!): Ditto.\n\t* fCMatrix.cc (FloatComplexMatrix::operator!): Ditto.\n\t* dNDArray.cc (NDArray::operator!): Ditto.\n\t* fNDArray.cc (FloatNDArray::operator!): Ditto.\n\t* CNDArray.cc (ComplexNDArray::operator!): Ditto.\n\t* fCNDArray.cc (FloatComplexNDArray::operator!): Ditto.\n\n2009-08-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_add, mx_inline_sub, mx_inline_mul,\n\tmx_inline_div, mx_inline_uminus, mx_inline_not, mx_inline_add2,\n\tmx_inline_sub2, mx_inline_mul2, mx_inline_div2, mx_inline_iszero,\n\tmx_inline_notzero, mx_inline_and, mx_inline_or, mx_inline_not_and,\n\tmx_inline_not_or, mx_inline_and_not, mx_inline_or_not,\n\tmx_inline_lt, mx_inline_le, mx_inline_gt, mx_inline_ge,\n\tmx_inline_eq, mx_inline_ne): New templates.\n\t(do_mx_unary_op, do_mm_binary_op, do_sm_binary_op,\n\tdo_ms_binary_op, do_mm_inplace_op,do_ms_inplace_op):\n\tNew templates.\n\n\t* mx-op-defs.h (ND_LOGICAL_NAN_CHECK, SC_LOGICAL_NAN_CHECK):\n\tNew macros.\n\t(NDND_BIN_OP, NDS_BIN_OP, SND_BIN_OP): Simplify.\n\t(MM_BIN_OP, MS_BIN_OP, MM_BIN_OP): Simplify.\n\t(NDND_BOOL_OP, NDS_BOOL_OP, SND_BOOL_OP): Simplify.\n\t(MM_BOOL_OP, MS_BOOL_OP, MM_BOOL_OP): Simplify.\n\t(NDND_BOOL_OPS2, NDS_BOOL_OPS2, SND_BOOL_OPS2,\n\tMM_BOOL_OPS2, MS_BOOL_OPS2, SM_BOOL_OPS2): Remove.\n\t* mx-op-decl.h (NDND_BOOL_OPX_DECLS, NDS_BOOL_OPX_DECLS,\n\tSND_BOOL_OPX_DECLS): New macros.\n\t* mk-ops.awk: use _BOOL_OPS rather than _BOOL_OPS2.\n\n\t* boolMatrix.cc: Add missing bool op defs.\n\t* boolMatrix.h: Add missing bool op decls.\n\n\n\t* boolNDArray.cc: Remove unused arg to BOOL_OPS.\n\t* CMatrix.cc: Ditto.\n\t* CNDArray.cc: Ditto.\n\t* ChangeLog: Ditto.\n\t* chMatrix.cc: Ditto.\n\t* chNDArray.cc: Ditto.\n\t* dMatrix.cc: Ditto.\n\t* dNDArray.cc: Ditto.\n\t* fCMatrix.cc: Ditto.\n\t* fCNDArray.cc: Ditto.\n\t* fMatrix.cc: Ditto.\n\t* fNDArray.cc: Ditto.\n\t* int16NDArray.cc: Ditto.\n\t* int32NDArray.cc: Ditto.\n\t* int64NDArray.cc: Ditto.\n\t* int8NDArray.cc: Ditto.\n\t* uint16NDArray.cc: Ditto.\n\t* uint32NDArray.cc: Ditto.\n\t* uint64NDArray.cc: Ditto.\n\t* uint8NDArray.cc: Ditto.\n\n\t* CColVector.cc: Update syntax where needed.\n\t* CDiagMatrix.cc: Ditto.\n\t* CMatrix.cc: Ditto.\n\t* CRowVector.cc: Ditto.\n\t* chMatrix.cc: Ditto.\n\t* dColVector.cc: Ditto.\n\t* dDiagMatrix.cc: Ditto.\n\t* dMatrix.cc: Ditto.\n\t* dRowVector.cc: Ditto.\n\t* fCColVector.cc: Ditto.\n\t* fCDiagMatrix.cc: Ditto.\n\t* fCMatrix.cc: Ditto.\n\t* fCRowVector.cc: Ditto.\n\t* fColVector.cc: Ditto.\n\t* fDiagMatrix.cc: Ditto.\n\t* fMatrix.cc: Ditto.\n\t* fRowVector.cc: Ditto.\n\n2009-08-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-util.cc (zero_dims_inquire): Add matching ndims case.\n\n2009-08-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* MArrayN.cc (operator+=, operator-=): Test matching dimensions first.\n\t* boolNDArray.cc (mx_el_and_assign, mx_el_or_assign): New functions.\n\t* boolNDArray.h: Declare them.\n\n2009-08-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::clear): New method.\n\t* Array.h: Declare it.\n\t* MArray-decl.h (MARRAY_OP_ASSIGN_DECLS1, MARRAY_OP_ASSIGN_FWD_DECLS1,\n\tMARRAY_OP_ASSIGN_FRIENDS1, MARRAY_OP_ASSIGN_FWD_DEFS1): New macros.\n\t(MARRAY_OPS_FORWARD_DECLS, MARRAY_OPS_FRIEND_DECLS): Use them.\n\t* MArray-defs.h (MARRAY_OP_ASSIGN_DEFS1): New macro.\n\t(INSTANTIATE_MARRAY_FRIENDS): Use it.\n\t(INSTANTIATE_MARRAY2_FRIENDS): Use it.\n\t(INSTANTIATE_MARRAYN_FRIENDS): Use it.\n\t* MArray.cc (operator+=, operator-=):\n\tOperate out-of-place when this is shared copy.\n\t(operator*=, operator/=): New operator overloads.\n\t* MArray2.cc: Ditto.\n\t* MArrayN.cc: Ditto.\n\t* CNDArray.cc (operator *= (ComplexNDArray&, double),\n\toperator /= (ComplexNDArray&, double)): New operators.\n\t* CNDArray.h: Declare them.\n\t* fCNDArray.cc (operator *= (FloatComplexNDArray&, double),\n\toperator /= (FloatComplexNDArray&, double)): New operators.\n\t* fCNDArray.h: Declare them.\n\n2009-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LINK_DEPS): List LIBS last.\n\n2009-08-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc, fMatrix.cc, CMatrix.cc, fCMatrix.cc: Add more tests.\n\t* CMatrix.cc (xgemm): Fix vector * matrix case.\n\t* fCMatrix.cc (xgemm): Ditto.\n\n2009-08-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* fMatrix.cc, fCMatrix.cc: Make tests use single precision.\n\n2009-08-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CMatrix.cc (xgemm): Fix typo. Add test.\n\t* fCMatrix.cc (xgemm): Ditto.\n\n2009-08-14  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LINK_DEPS): Include BLAS_LIBS in the list.\n\n2009-08-13  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc, CNDArray.cc, dMatrix.cc, dNDArray.cc, fCMatrix.cc,\n\tfCNDArray.cc, fMatrix.cc, fNDARray.cc, oct-fftw.cc, oct-fftw.h:\n\tUpdate for new FFTW defines.\n\n\t* Makefile.in: Add library-specific CPPFLAGS and LDFLAGS variables\n\tto CPPFLAGS and LDFLAGS for files that use sparse matrices or fftw.\n\n2009-08-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Makefile.in: Include LDFLAGS when linking shared executable.\n\n2009-08-11  John W. Eaton  <jwe@octave.org>\n\n\t* oct-fftw.h, oct-fftw.cc (octave_fftw_planner): Convert to singleton.\n\t(octave_float_fft_planner): Likewise.\n\n2009-08-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LINK_DEPS): Use READLINE_LIBS instead of\n\tLIBREADLINE.  Also link with TERM_LIBS and DL_LIBS.\n\n2009-08-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_diff<T>): New overloaded template\n\tfunction.\n\t(get_extent_triplet): Use dim_vector::first_non_singleton.\n\t(do_mx_diff_op): New template function.\n\t* dNDArray.cc (NDArray::diff): New method.\n\t* dNDArray.h: Declare it.\n\t* fNDArray.cc (FloatNDArray::diff): New method.\n\t* fNDArray.h: Declare it.\n\t* CNDArray.cc (ComplexNDArray::diff): New method.\n\t* CNDArray.h: Declare it.\n\t* fCNDArray.cc (FloatComplexNDArray::diff): New method.\n\t* fCNDArray.h: Declare it.\n\t* intNDArray.cc (intNDArray<T>::diff): New method.\n\t* intNDArray.h: Declare it.\n\n2009-08-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::first_non_singleton): New method.\n\n2009-08-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector): Rewrite. Use single-alloc implementation\n\taka GCC's basic_string class.\n\t* Array.cc: Use dim_vector::alloc where fitting.\n\t* Array-util.cc: Ditto.\n\n2009-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* oct-shlib.cc (octave_shl_load_shlib::open): Pass BIND_IMMEDIATE,\n\tnot BIND_DEFERRED to shl_load.\n\t(octave_dlopen_shlib::open): Don't pass RTLD_GLOBAL to dlopen.\n\n2009-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LINK_DEPS): Omit $(BLAS_LIBS) from the list.\n\tInclude $(RLD_FLAG) in the list.\n\n2009-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LINK_DEPS): Include $(PTHREAD_LIBS) in the list.\n\n2009-08-04  Kristian Rumberg  <kristianrumberg@gmail.com>\n\n\t* cmd-edit.cc (gnu_readline::do_get_line_buffer,\n\tdefault_command_editor::do_get_line_buffer): New functions.\n\t(command_editor::get_line_buffer): New function.\n\t* cmd-edit.h (command_editor::get_line_buffer): Provide decls.\n\t(command_editor::do_get_line_buffer): New pure virtual function.\n\n2009-07-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.h (idx_vector::is_range): New method.\n\t(idx_vector::copy_data, idx_vector::unconvert): New method decls.\n\t* idx-vector.cc (idx_vector::copy_data, idx_vector::unconvert): New\n\tmethods.\n\t* Array-utils.cc (sub2ind, ind2sub): New functions.\n\n2009-07-29  John W. Eaton  <jwe@octave.org>\n\n\t* fMatrix.cc (operator >>): Use template function to read value.\n\t* fNDArray.cc (operator >>): Likeise.\n\t* fCMatrix.cc (operator >>): Use template function to read value.\n\t* fCNDArray.cc (operator >>): Likeise.\n\t* dMatrix.cc (operator >>): Use template function to read value.\n\t* dNDArray.cc (operator >>): Likeise.\n\t* CMatrix.cc (operator >>): Use template function to read value.\n\t* CNDArray.cc (operator >>): Likeise.\n\n\t* lo-utils.cc, lo-utils.h (octave_read_value): New template\n\t(octave_read_value<double>, octave_read_value<Complex>):\n\tProvide specializations.\n\t(octave_read_double, octave_read_complex, octave_read_float,\n\toctave_rread_float_complex): Define in terms of template functions.\n\t* Sparse.h (read_sparse_matrix): New template function.\n\t* dSparse.cc (operator >>): Call read_sparse_matrix.\n\t* CSparse.cc (operator >>): Likewise.\n\t* boolSparse.cc (operator >>): Likewise.\n\t* sparse-util.cc, sparse-util.h (sparse_indices_ok): New function.\n\t* Sparse.cc (Sparse<T>::indices_ok, Sparse<T>::SparseRep::indices_ok):\n\tNew member functions.\n\n2009-07-20  John W. Eaton  <jwe@octave.org>\n\n\t* lo-ieee.cc (octave_ieee_init) [__NetBSD__]: Call nan to\n\tinitialize Octave_NaN and nanf, to initialize Octave_Float_NaN.\n\n2009-07-11  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc (file_ops::symlink, file_ops::readlink):\n\tDon't use incorrectly sized OCTAVE_LOCAL_BUFFER.\n\n2009-07-08  John W. Eaton  <jwe@octave.org>\n\n\t* dim-vector.h (dim_vector::dim_vector_rep::dim_vector_rep\n\t(octave_idx_type, const dim_vector_rep *, int)):\n\tEnforce 2-d objects here.\n\t(dim_vector::dim_vector_rep::dim_vector_rep): Simply copy object.\n\t(dim_vector::resize): Allow N < 2.\n\n2009-07-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse-op-defs.h (SPARSE_ALL_OP): Fix typo.\n\t* dSparse.cc (SparseMatrix::prod): Ditto.\n\t* CSparse.cc (ComplexSparseMatrix::prod): Ditto.\n\n2009-07-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse-diag-op-defs.h (inner_do_add_sm_dm): Rewrite to ensure\n\tordering of row indices.\n\n2009-06-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (octave_sort<T>::lookupb<Comp>): Fix typo.\n\n2009-06-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (octave_sort<T>::lookup_merge): Delete.\n\t(octave_sort<T>::lookup<Comp>,\n\toctave_sort<T>::lookupm<Comp>,\n\toctave_sort<T>::lookupb<Comp>): Rewrite.\n\n2009-06-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* pathsearch.h (class dir_path::static_members): Decorate with\n\tOCTAVE_API.\n\n2009-06-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (octave_sort<T>::lookup_merge<Comp>): Slightly speed-up\n\tthe merge case.\n\n2009-06-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (octave_sort<T>::lookup_merge<Comp>): Fix lower-part\n\trecursion.\n\n2009-06-24  Alexander Barth  <barth.alexander@gmail.com>\n\n\t* eigs-base.cc (EigsRealSymmetricMatrix,\n\tEigsRealSymmetricMatrixShift, EigsRealSymmetricFunc,\n\tEigsRealNonSymmetricMatrix, EigsRealNonSymmetricMatrixShift,\n\tEigsRealNonSymmetricFunc, EigsComplexNonSymmetricMatrix,\n\tEigsComplexNonSymmetricMatrixShift, EigsComplexNonSymmetricFunc):\n\tUse octave_idx_type for parameters of type LOGICAL in ARPACK.\n\n2009-06-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* chMatrix.cc (charMatrix::charMatrix (const string_vector&)):\n\tOptimize w.r.t. COW of std::string.\n\n2009-06-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (lookup_impl<T, Comp>): New helper inline function.\n\t(octave_sort<T>::lookup_merge<Comp>): New private template method.\n\t(octave_sort<T>::lookup<Comp>): Rewrite.\n\t(octave_sort<T>::lookupm<Comp>): use lookup_impl.\n\t(octave_sort<T>::lookupb<Comp>): use lookup_impl.\n\t(out_of_range_pred, out_of_range): Remove.\n\n2009-06-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (xgemm): Replace resize() with uninitialized allocations\n\twhere appropriate.\n\t* fMatrix.cc (xgemm): Ditto.\n\t* CMatrix.cc (xgemm): Ditto.\n\t* fCMatrix.cc (xgemm): Ditto.\n\n2009-06-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (octave_sort::lookupm, octave_sort::lookupb): New\n\toverloaded methods.\n\t* oct-sort.h: Declare them.\n\t* Array.cc (Array<T>::lookupm, Array<T>::lookupb): New methods.\n\t* Array.h: Declare them.\n\n2009-06-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* cmd-edit.cc (command_editor::force_default_editor): New static\n\tmethod.\n\t* cmd-edit.h: Declare it.\n\n2009-06-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-mappers.cc (xlog2 (const Complex&, int&), xlog2 (const\n\tFloatComplex&, int&)): Use more robust expression.\n\n2009-06-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::find): Avoid allocating excessive memory. Fix\n\torder for backward searches.\n\n2009-06-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-C.cc (class DiagArray2<Complex>::Proxy): Only explicitly\n\tinstantiate DiagArray2<T>::Proxy on MSVC.\n\t* Array-d.cc (class DiagArray2<double>::Proxy): Ditto.\n\t* Array-f.cc (class DiagArray2<float>::Proxy): Ditto.\n\t* Array-fC.cc (class DiagArray2<FloatComplex>::Proxy): Ditto.\n\n2009-05-26  John W. Eaton  <jwe@octave.org>\n\n\t* pathsearch.h (dir_path::path_sep_char (char),\n\tdir_path::static_members::path_sep_char (char)): New functions.\n\n2009-05-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Array-C.cc (class DiagArray2<Complex>::Proxy): Tag with OCTAVE_API.\n\t* Array-d.cc (class DiagArray2<double>::Proxy): Ditto.\n\t* Array-f.cc (class DiagArray2<float>::Proxy): Ditto.\n\t* Array-fC.cc (class DiagArray2<FloatComplex>::Proxy): Ditto.\n\t* Array.cc (class octave_sort<T>): Ditto.\n\t* CColVector.h (conj, operator*, operator>>, operator<<): Ditto.\n\t* CDiagMatrix.h (class ComplexDiagMatrix, conj, operator*): Ditto.\n\t* CMatrix.h (conj): Ditto.\n\t* CNDArray.h (conj): Ditto.\n\t* PermMatrix.h (class PermMatrix, operator*): Ditto.\n\t* dDiagMatrix.h (class DiagMatrix): Ditto.\n\t* fCColVector.h (conj, operator*, operator>>, operator<<): Ditto.\n\t* fCDiagMatrix.h (class FloatComplexDiagMatrix, conj, operator*):\n\tDitto.\n\t* fCMatrix.h (conj): Ditto.\n\t* fCNDArray.h (conj): Ditto.\n\t* fDiagMatrix.h (operator*): Ditto.\n\t* oct-locbuf.h (octave_chunk_buffer::octave_chunk_buffer,\n\toctave_chunk_buffer::~octave_chunk_buffer): Ditto.\n\t* oct-inttypes.cc (octave_int_cmp_op::emulate_op): Ditto.\n\t* DET.h (class base_det<T>): Remove OCTAVE_API (cannot be applied on\n\ttemplates).\n\t* oct-inttypes.cc (octave_int_cmp_op::emulate_op<class xop>): Ditto.\n\n\t* CmplxQR.cc (ComplexQR::insert_col, ComplexQR::delete_col): Copy\n\tvolatile variable to avoid MSVC compilation error (cannot pass\n\tvolatile variable as const& argument).\n\t* dbleQR.cc (QR::insert_col, QR::delete_col): Ditto.\n\t* fCmplxQR.cc (FloatComplexQR::insert_col,\n\tFloatComplexQR::delete_col): Ditto.\n\t* floatQR.cc (FloatQR::insert_col, FloatQR::delete_col): Ditto.\n\n\t* oct-mutex.cc: Exclude pthread.h inclusion under Win32.\n\n\t* base-aepbal.h (base_aepbal::operator=): Add missing return\n\tstatement.\n\n2009-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* eigs-base.cc (\n\tEigsRealSymmetricMatrix,\n\tEigsRealSymmetricMatrixShift,\n\tEigsRealSymmetricFunc,\n\tEigsRealNonSymmetricMatrix,\n\tEigsRealNonSymmetricMatrixShift,\n\tEigsRealNonSymmetricFunc,\n\tEigsComplexNonSymmetricMatrix,\n\tEigsComplexNonSymmetricMatrixShift,\n\tEigsComplexNonSymmetricFunc): Update tests.\n\n2009-05-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CMatrix.cc\n\t(ComplexMatrix::all, ComplexMatrix::any, ComplexMatrix::cumprod,\n\tComplexMatrix::cumsum, ComplexMatrix::prod, ComplexMatrix::sum,\n\tComplexMatrix::sumsq): Use explicit template qualifications\n\tto workaround bugs in Intel C++ and MSVC++ compilers.\n\t* CNDArray.cc\n\t(ComplexNDArray::all, ComplexNDArray::any, ComplexNDArray::cumprod,\n\tComplexNDArray::cumsum, ComplexNDArray::prod, ComplexNDArray::sum,\n\tComplexNDArray::sumsq): Ditto.\n\t* boolMatrix.cc\n\t(boolMatrix::all, boolMatrix::any): Ditto.\n\t* boolNDArray.cc\n\t(boolNDArray::all, boolNDArray::any): Ditto.\n\t* chMatrix.cc\n\t(charMatrix::all, charMatrix::any): Ditto.\n\t* chNDArray.cc\n\t(charNDArray::all, charNDArray::any): Ditto.\n\t* dMatrix.cc\n\t(Matrix::all, Matrix::any, Matrix::cumprod,\n\tMatrix::cumsum, Matrix::prod, Matrix::sum,\n\tMatrix::sumsq): Ditto.\n\t* dNDArray.cc\n\t(NDArray::all, NDArray::any, NDArray::cumprod,\n\tNDArray::cumsum, NDArray::prod, NDArray::sum,\n\tNDArray::sumsq): Ditto.\n\t* fCMatrix.cc\n\t(FloatComplexMatrix::all, FloatComplexMatrix::any, FloatComplexMatrix::cumprod,\n\tFloatComplexMatrix::cumsum, FloatComplexMatrix::prod, FloatComplexMatrix::sum,\n\tFloatComplexMatrix::sumsq): Ditto.\n\t* fCNDArray.cc\n\t(FloatComplexNDArray::all, FloatComplexNDArray::any, FloatComplexNDArray::cumprod,\n\tFloatComplexNDArray::cumsum, FloatComplexNDArray::prod, FloatComplexNDArray::sum,\n\tFloatComplexNDArray::sumsq): Ditto.\n\t* fMatrix.cc\n\t(FloatMatrix::all, FloatMatrix::any, FloatMatrix::cumprod,\n\tFloatMatrix::cumsum, FloatMatrix::prod, FloatMatrix::sum,\n\tFloatMatrix::sumsq): Ditto.\n\t* fNDArray.cc\n\t(FloatNDArray::all, FloatNDArray::any, FloatNDArray::cumprod,\n\tFloatNDArray::cumsum, FloatNDArray::prod, FloatNDArray::sum,\n\tFloatNDArray::sumsq): Ditto.\n\t* intNDArray.cc\n\t(intNDArray<T>::all, intNDArray<T>::any,\n\tintNDArray<T>::cumsum, intNDArray<T>::sum): Ditto.\n\n2009-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Makefile.in: Remove reference to ArrayN-idx.h.\n\n2009-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-voidp.cc: New source.\n\t* Array.cc (NO_INSTANTIATE_ARRAY_SORT): const T& -> T const &\n\t* Makefile.in: Include it.\n\n2009-05-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::instantiation_guard): New function\n\t(INSTANTIATE_ARRAY): Always override it here.\n\t* Array.h: Declare it.\n\n2009-05-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ArrayN-idx.h: Remove file.\n\t* ArrayN.cc: Don't include it.\n\t* MArrayN.cc: Dtto.\n\n2009-05-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-util.cc (zero_dims_inquire): Move j++ out of branch.\n\n2009-05-07  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* Makefile.in: (SHLPRE): Rename from SHLLIBPRE.\n\n2009-05-05  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* file-ops.h (file_ops::tail) New function.\n\n2009-05-05  Carsten Clark  <tantumquantum+gnuoctave@gmail.com>\n\n\t* Quad.cc (user_function): Use access_double and assign_double on\n\tSPARC only, not on all Sun systems.\n\t* sun-utils.h: Likewise, define these functions on SPARC only.\n\n2009-05-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Sparse.cc (assign1): Fix an old indexing bug.\n\n2009-05-04  Carsten Clark  <tantumquantum+gnuoctave@gmail.com>\n\n\t* Quad.cc (float_user_function): Remove Sun/GCC special case.\n\n2009-04-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::idx_range_rep::idx_range_rep (const\n\tRange&)): Check for positive integer indices. Unify gripes.\n\n2009-04-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (rec_permute_helper::blk_trans): Declare as static.\n\t(Array<T>::transpose): Reuse it.\n\n2009-04-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::make_unique): Don't economize when unique.\n\t(Array<T>::resize_fill (octave_idx_type, const T&)): Optimize push &\n\tpop operations.\n\t(Array<T>::delete_elements (const idx_vector&)): Do pop operation\n\tusing resize.\n\n2009-03-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::assign): Remove redundant checks after invalid\n\tresize.\n\n2009-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::find): Reshape result for Matlab compatibility.\n\t* Array.h (Array<T>): Add friend template declaration.\n\n2009-03-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::idx_vector_rep::idx_vector_rep (const\n\tArray<bool>&): Use more M*b-compatible behaviour.\n\n2009-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dim-vector.h (dim_vector::numel): Add optional argument, simplify.\n\n2009-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array<T>::dims): Return a const reference.\n\t(Array<T>::is_vector): New method.\n\n2009-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::find): New method.\n\t* Array.h: Declare it.\n\n2009-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* EIG.cc (EIG::init (const Matrix&, bool),\n\tEIG::init (const Matrix&, const Matrix&, bool)):\n\tAvoid volatile declaration for tmp variable.\n\n\t* Makefile.in (MATRIX_INC): Add Sparse-diag-op-defs.h and\n\tSparse-perm-op-defs.h to the list.\n\n2009-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.cc (INT_DOUBLE_BINOP_DECL (*, uint64),\n\tINT_DOUBLE_BINOP_DECL (*, int64)): x -> y where appropriate.\n\n2009-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (rec_permute_helper::use_blk): New field.\n\t(rec_permute_helper::blk_trans): New method.\n\t(rec_permute_helper::rec_permute_helper): Use smart reductions,\n\tdetect possibility of using blocked transpose.\n\t(rec_permute_helper::do_permute): Use blocked transpose if possible.\n\n2009-03-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (convert_index(double,...)): Simplify.\n\n2009-03-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-d.cc: lo_ieee_isnan -> xisnan.\n\t* Array-f.cc: Ditto.\n\t* oct-inttypes.cc: Ditto.\n\t* oct-inttypes.h: Ditto.\n\t* CDiagMatrix.cc: Add missing include.\n\t* fCDiagMatrix.cc: Ditto.\n\n2009-03-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CColVector.cc, CMatrix.cc, CNDArray.cc, CRowVector.cc, CSparse.cc,\n\tboolSparse.cc, dColVector.cc, dMatrix.cc, dNDArray.cc, dRowVector.cc,\n\tdSparse.cc, fCColVector.cc, fCMatrix.cc, fCNDArray.cc, fCRowVector.cc,\n\tfColVector.cc, fMatrix.cc, fNDArray.cc, fRowVector.cc, intNDArray.cc:\n\tAllow empty arrays in stream input operators.\n\n2009-03-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array<T>::fastmap): New method.\n\t* dNDArray.cc (NDArray::isnan, NDArray::isinf, NDArray::isfinite):\n\tNew methods.\n\t* dNDArray.h: Declare them.\n\t* fNDArray.cc (FloatNDArray::isnan, FloatNDArray::isinf,\n\tFloatNDArray::isfinite): New methods.\n\t* fNDArray.h: Declare them.\n\t* CNDArray.cc (ComplexNDArray::isnan, ComplexNDArray::isinf,\n\tComplexNDArray::isfinite): New methods.\n\t* CNDArray.h: Declare them.\n\t* fCNDArray.cc (FloatComplexNDArray::isnan, FloatComplexNDArray::isinf,\n\tFloatComplexNDArray::isfinite): New methods.\n\t* fCNDArray.h: Declare them.\n\t* lo-mappers.h (xisnan, xisinf, xfinite): If possible, use definitions\n\tfrom <cmath>.\n\n2009-03-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-norm.cc (get_eps): Remove that hack.\n\t(higham): Use std::numeric_limits instead.\n\tInclude OCTAVE_QUIT.\n\n2009-03-16  Jason Riedy  <jason@acm.org>\n\n\t* Sparse.cc (transpose): Eliminate the workspace by computing in\n\tretval.xcidx.\n\t* CSparse.cc (hermitian): Eliminate the workspace by computing in\n\tretval.xcidx.\n\n2009-03-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-op-decl.h (NDS_BOOL_OP_DECLS, SND_BOOL_OP_DECLS, NDND_BOOL_OP_DECLS): Support compound binary ops.\n\t* mx-op-defs.h (NDS_BOOL_OPS, SND_BOOL_OPS, NDND_BOOL_OPS): Ditto. Optimize.\n\t* mx-op-defs.h (NDS_CMP_OP, SND_CMP_OP, NDND_CMP_OP): Optimize.\n\n2009-03-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* fNDArray.h (FloatMatrix::matrix_value): Fix return type.\n\t* dNDArray.cc (Matrix::matrix_value): Simplify.\n\t* fNDArray.cc (FloatMatrix::matrix_value): Simplify.\n\t* CNDArray.cc (ComplexMatrix::matrix_value): Simplify.\n\t* fCNDArray.cc (FloatComplexMatrix::matrix_value): Simplify.\n\n2009-03-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Range.h (Range::Range (double, double, octave_idx_type)): Remove\n\tconstructor body.\n\t* Range.cc: Move it here. Check for invalid range op results.\n\t(all operators): Validate cache for invalid range op results.\n\t* idx-vector.h (idx_vector::index): Optimize zero-step range case.\n\t* idx-vector.cc (idx_vector::maybe_reduce): Always reduce colon in\n\tsingleton dimension.\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* sparse-base-lu.cc (Pr_mat): New member function.  Return the row\n\tpermutation as a PermMatrix.\n\t(Pc_mat): New member function.  Return the col permutation as a\n\tPermMatrix.\n\n\t* sparse-base-lu.h (sparse_base_lu): Declare Pc_mat and Pr_mat\n\tmember functions.\n\n2009-03-09  Jason Riedy  <jason@acm.org>\n\n\t* Sparse-diag-op-defs.h (octave_impl::inner_do_add_sm_dm): New\n\ttemplate function.  Implementation for adding sparse and diagonal\n\tmatrices.  Takes two functional arguments, opa and opd, to\n\tgenerate both subtraction variants.\n\t(octave_impl::do_commutative_add_dm_sm): New template function.\n\tEnsure A+D and D+A use the same generated code.\n\t(octave_impl::do_add_dm_sm): New template function.  Check\n\targuments for diag + sparse and call inner routine.\n\t(octave_impl::do_sub_dm_sm): New template function.  Check\n\targuments for diag - sparse and call inner routine.\n\t(octave_impl::do_add_sm_dm): New template function.  Check\n\targuments for sparse + diag and call inner routine.\n\t(octave_impl::do_sub_sm_dm): New template function.  Check\n\targuments for sparse - diag and call inner routine.\n\n\t* dSparse.h (operator +): Declare overrides for real diag +\n\tsparse.\n\t(operator -): Declare overrides for real diag - sparse, sparse -\n\tdiag.\n\n\t* dSparse.cc (operator +): Define overrides for real diag +\n\tsparse.\n\t(operator -): Define overrides for real diag - sparse, sparse -\n\tdiag.\n\n\t* CSparse.h (operator +): Declare overrides for complex and real\n\tcombinations of diag + sparse.\n\t(operator -): Declare overrides for complex and real combinations\n\tof diag - sparse, sparse - diag.\n\n\t* CSparse.cc (operator +): Define overrides for complex and real\n\tcombinations of diag + sparse.\n\t(operator -): Define overrides for complex and real combinations\n\tof diag - sparse, sparse - diag.\n\n2009-03-08  Jason Riedy  <jason@acm.org>\n\n\t* Sparse-diag-op-defs.h (octave_impl::do_mul_dm_sm)\n\t(octave_impl::do_mul_sm_dm): New template\n\tfunctions. Implementations for sparse * diag and diag * sparse.\n\n\t* CSparse.h (operator *, trans_mul, herm_mul): Add overloads for\n\tDiagMatrix and ComplexDiagMatrix.\n\t* CSparse.cc (operator *, trans_mul, herm_mul): Implement\n\toperations by calling approprate functions in\n\tSparse-diag-op-defs.h.\n\t* dSparse.h (operator *, trans_mul): Add overloads for DiagMatrix.\n\t* dSparse.cc (operator *, trans_mul): Implement operations by\n\tcalling approprate functions in Sparse-diag-op-defs.h.\n\n2009-03-12  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (bitshift): Apply mask even if not shifting.\n\tFrom Seb Astien <se6astien2@googlemail.com>.\n\n2009-03-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* PermMatrix.cc (PermMatrix::power): New method.\n\t* PermMatrix.h: Declare it.\n\n2009-03-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dNDArray.cc (NDArray::NDArray (const charNDArray&)): New\n\tconstructor.\n\t* fNDArray.cc (FloatNDArray::FloatNDArray (const charNDArray&)):\n\tDitto.\n\t* CNDArray.cc (ComplexNDArray::ComplexNDArray (const charNDArray&)):\n\tDitto.\n\t* fCNDArray.cc (FloatComplexNDArray::FloatComplexNDArray\n\t(const charNDArray&)): Ditto.\n\n\t* dNDArray.h (NDArray::NDArray (const charNDArray&)): Declare.\n\t* fNDArray.h (FloatNDArray::FloatNDArray (const charNDArray&)):\n\tDitto.\n\t* CNDArray.h (ComplexNDArray::ComplexNDArray (const charNDArray&)):\n\tDitto.\n\t* fCNDArray.h (FloatComplexNDArray::FloatComplexNDArray\n\t(const charNDArray&)): Ditto.\n\n\t* dMatrix.cc (Matrix::Matrix (const charMatrix&)): Cast to unsigned\n\tchars.\n\t* fMatrix.cc (FloatMatrix::FloatMatrix (const charMatrix&)): Likewise.\n\t* CMatrix.cc (ComplexMatrix::ComplexMatrix (const charMatrix&)):\n\tLikewise.\n\t* fCMatrix.cc (FloatComplexMatrix::FloatComplexMatrix\n\t(const charMatrix&)): Likewise.\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* Sparse-perm-op-defs.h (octinternal_do_mul_colpm_sm): New\n\ttemplate function.  Logic for the column permutation * sparse\n\tmatrix operator.\n\t(octinternal_do_mul_pm_sm): New template function.  Logic for the\n\tpermutation matrix * sparse matrix operator.  Note that there is\n\tno special row perm * sparse routine; the permutation is inverted\n\tand the col perm routine is called.\n\t(octinternal_do_mul_sm_rowpm): New template function.  Logic for\n\tthe sparse matrix * row permutation operator.\n\t(octinternal_do_mul_sm_colpm): New template function.  Logic for\n\tthe sparse matrix * column permutation operator.\n\t(octinternal_do_mul_sm_pm): New template function.  Logic for the\n\tsparse matrix * permutation matrix operator.\n\n\t* dSparse.h (operator *): Declare sparse * permutation and\n\tpermutation * sparse.\n\t* dSparse.cc (operator *): Define sparse * permutation and\n\tpermutation * sparse.\n\n\t* CSparse.h (operator *): Declare sparse * permutation and\n\tpermutation * sparse.\n\t* CSparse.cc (operator *): Define sparse * permutation and\n\tpermutation * sparse.\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* sparse-base-lu.cc (Pc_vec): The column permutation should be\n\tUfact.cols ()-long, not Lfact.rows ()-long.\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* dSparse.cc (SparseMatrix::SparseMatrix (const PermMatrix&)):\n\tFix conversion to add values to the matrix as well as getting\n\tstructure correct.\n\n2009-03-10  John W. Eaton  <jwe@octave.org>\n\n\t* Array.h, ArrayN.h, Bounds.h, CmplxAEPBAL.h, CmplxCHOL.h,\n\tCmplxGEPBAL.h, CmplxHESS.h, CmplxQR.h, CmplxQRP.h, CmplxSCHUR.h,\n\tCmplxSVD.h, CollocWt.h, EIG.h, FEGrid.h, LinConst.h, Range.h,\n\tSparse.h, SparseCmplxQR.h, SparseQR.h, dbleAEPBAL.h, dbleCHOL.h,\n\tdbleGEPBAL.h, dbleHESS.h, dbleQR.h, dbleQRP.h, dbleSCHUR.h,\n\tdbleSVD.h, dim-vector.h, fCmplxAEPBAL.h, fCmplxCHOL.h,\n\tfCmplxGEPBAL.h, fCmplxHESS.h, fCmplxQR.h, fCmplxQRP.h,\n\tfCmplxSCHUR.h, fCmplxSVD.h, fEIG.h, floatAEPBAL.h, floatCHOL.h,\n\tfloatGEPBAL.h, floatHESS.h, floatQR.h, floatQRP.h, floatSCHUR.h,\n\tfloatSVD.h, idx-vector.h, lo-utils.h, oct-inttypes.h,\n\toct-spparms.h, str-vec.h: Include <iosfwd> instead of <iosstream>.\n\n2009-03-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (OP_CUMMINMAX_FCN2): r -> r0 where appropriate.\n\n2009-03-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.h (idx_vector::bloop): loop --> bloop.\n\t(idx_vector::loop): New method.\n\t* MArray.cc (MArray<T>::idx_add (cons idx_vector&, T))\n\t(MArray<T>::idx_add (cons idx_vector&, const MArray<T>&)): New methods.\n\t* MArray.h: Declare them.\n\n2009-03-05  Jason Riedy  <jason@acm.org>\n\n\t* Sparse.h (Sparse<T>::elt_type): Remove typedef, replace with:\n\t* Sparse.h (Sparse<T>::element_type): Add typedef to be consistent\n\twith Array.h\n\t* DiagArray2.h (DiagArray2<T>::elt_type): Likewise, removed.\n\t* DiagArray2.h (DiagArray2<T>::element_type): Define by using\n\tArray<T>::element_type.\n\t* intNDArray.h (intNDArray<T>::element_type): Remove, inherited\n\tfrom MArrayN<T>.\n\n2009-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dSparse.h (SparseMatrix::SparseMatrix(const PermMatrix&)): New\n\tconstructor.\n\t(SparseMatrix::SparseMatrix(const DiagMatrix&)): Fix implementation.\n\t* CSparse.h (SparseComplexMatrix::SparseComplexMatrix(const ComplexDiagMatrix&)):\n\tFix implementation.\n\n2009-03-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* PermMatrix.h (PermMatrix::elem): Fix comparisons.\n\n2009-03-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-mappers.cc (xmin (float, float), xmax (float, float)): Simplify.\n\n2009-03-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc: Add missing #include.\n\n2009-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in: Make maintainer-clean and distclean the same.\n\n2009-02-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.cc (pow (const octave_int<T>&, const octave_int<T>&)):\n\tSimplify.\n\n2009-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (octave_int_cmp_op::mop): Implement as simple\n\tforwarders when OCTAVE_INT_USE_LONG_DOUBLE is not defined.\n\t(octave_int_cmp_op::emulate_mop): New static overloaded template\n\tmember function.\n\t* oct-inttypes.cc: Turn the octave_int_cmp_op::mop definitions into\n\tdefs for octave_int_cmp_op::emulate_mop.\n\t(INSTANTIATE_INT64_DOUBLE_CMP_OP0): Instantiate\n\toctave_int_cmp_op::emulate_op instead.\n\n2009-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dDiagMatrix.cc (DiagMatrix::pseudo_inverse): New method.\n\t* dDiagMatrix.h: Declare it.\n\t* fDiagMatrix.cc (FloatDiagMatrix::pseudo_inverse): New method.\n\t* fDiagMatrix.h: Declare it.\n\t* CDiagMatrix.cc (ComplexDiagMatrix::pseudo_inverse): New method.\n\t* CDiagMatrix.h: Declare it.\n\t* fCDiagMatrix.cc (FloatComplexDiagMatrix::pseudo_inverse): New method.\n\t* fCDiagMatrix.h: Declare it.\n\n2009-02-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.h (octave_sort<T>::MergeState::MergeState): New\n\tconstructor.\n\t(octave_sort<T>::MergeState::~MergeState): New destructor.\n\t(octave_sort<T>::MergeState::reset,\n\toctave_sort<T>::MergeState::getmem,\n\toctave_sort<T>::MergeState::getmemi): New methods.\n\t(octave_sort<T>::sort,\n\toctave_sort<T>::merge_lo, octave_sort<T>::merge_hi\n\toctave_sort<T>::merge_at): Reflect change.\n\n2009-02-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-types.h (sortmode): Move enum here.\n\t* oct-sort.h (octave_sort<T>::ms): Declare as pointer.\n\t(octave_sort<T>::lookup): New overloaded method.\n\t* oct-sort.cc: Reflect change to ms.\n\t(octave_sort<T>::lookup): New overloaded method.\n\t(out_of_range_pred): New helper class.\n\t(out_of_range): New helper function.\n\t* oct-lookup.h: Remove file.\n\t* Array.cc (Array<T>::lookup): New overloaded method.\n\t* Array.h: Declare it.\n\n2009-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* dbleQR.cc (QR::init, QR::form): Cast int to octave_idx_type in\n\tcall to std::max.\n\t* floatQR.cc (FloatQR::init, FloatQR::form): Ditto.\n\t* CmplxQR.cc (ComplexQR::init, ComplexQR::form): Ditto.\n\t* fCmplxQR.cc (FloatComplexQR::init, FloatComplexQR::form): Ditto.\n\n\t* dbleQRP.cc (QRP::init): Cast int to octave_idx_type in call to\n\tstd::max and as operand to -= operator.\n\t* CmplxQRP.cc (ComplexQRP::init): Ditto.\n\t* floatQRP.cc (FloatQRP::init): Ditto.\n\t* fCmplxQRP.cc (FloatComplexQRP::init): Ditto.\n\n\t* CDiagMatrix.cc, CDiagMatrix.h (ComplexDiagMatrix::inverse):\n\tDeclare info as octave_idx_type, not int.\n\t* dDiagMatrix.cc, dDiagMatrix.h (DiagMatrix::inverse): Ditto.\n\t* fDiagMatrix.cc, fCDiagMatrix.h (FloatDiagMatrix::inverse): Ditto.\n\t* fCDiagMatrix.cc, fCDiagMatrix.h (FloatComplexDiagMatrix::inverse):\n\tDitto.\n\n\t* dMatrix.cc (Matrix::determinant):\n\tDeclare local variables volatile as needed to avoid \"maybe\n\tclobbered by vfork\" warning from GCC.\n\t* fMatrix.cc (FloatMatrix::determinant): Likewise.\n\t* CMatrix.cc (ComplexMatrix::determinant): Likewise.\n\t* fCMatrix.cc (FloatComplexMatrix::determinant): Likewise.\n\t* dbleQR.cc (QR::update, QR::insert_col, QR::delete_col): Likewise.\n\t* floatQR.cc (FloatQR::update, FloatQR::insert_col,\n\tFloatQR::delete_col): Likewise.\n\t* CmplxQR.cc (ComplexQR::update, ComplexQR::insert_col,\n\tComplexQR::delete_col): Likewise.\n\t* fCmplxQR.cc (FloatComplexQR::update, FloatComplexQR::insert_col,\n\tFloatComplexQR::delete_col): Likewise.\n\n\t* dMatrix.cc (padec, solve_singularity_warning): Delete unused\n\tstatic variable and function.\n\t* CMatrix.cc (padec, solve_singularity_warning): Ditto.\n\t* fMatrix.cc (padec, solve_singularity_warning): Ditto.\n\t* fCMatrix.cc (padec, solve_singularity_warning): Ditto.\n\n2009-02-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::resize (const dim_vector&)): Check for negative\n\tdimensions.\n\n2009-02-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.cc (pow (const octave_int<T>&, const octave_int<T>&)):\n\tUse octave_int comparisons to avoid warning for unsigned types.\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::resize (const dim_vector&)): Remove dead branch.\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (OP_CUM_FCN, OP_CUM_FCN2, OP_CUM_FCNN):\n\tAdd TSRC/TRES parameters.\n\t(mx_inline_cumcount): New function.\n\t* intNDArray.cc (intNDArray::cumsum): New method.\n\t* intNDArray.h: Declare it.\n\t* boolNDArray.cc (boolNDArray::cumsum): New method.\n\t* boolNDArray.h: Declare it.\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (OP_CUMMINMAX_FCN, OP_CUMMINMAX_FCN2,\n\tOP_CUMMINMAX_FCNN): New macros.\n\t(mx_inline_cummax, mx_inline_cummin, do_mx_cumminmax_op):\n\tNew overloaded template functions.\n\n\t* dNDArray.cc (NDArray::cummin, NDArray::cummax): New methods.\n\t* dNDArray.h: Declare them.\n\n\t* fNDArray.cc (FloatNDArray::cummin, FloatNDArray::cummax): New\n\tmethods.\n\t* fNDArray.h: Declare them.\n\n\t* CNDArray.cc (ComplexNDArray::cummin, ComplexNDArray::cummax): New\n\tmethods.\n\t* CNDArray.h: Declare them.\n\n\t* fCNDArray.cc (FloatComplexNDArray::cummin,\n\tFloatComplexNDArray::cummax): New methods.\n\t* fCNDArray.h: Declare them.\n\n\t* intNDArray.cc (intNDArray::cummin, intNDArray::cummax): New methods.\n\t* intNDArray.h: Declare them.\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (OP_MINMAX_FCN): Correct behaviour with NaNs.\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* MArray-defs.h: Move declarative part to MArray-decl.h\n\t* MArray-decl.h: New source.\n\n\t* mx-op-defs.h: Move declarative part to mx-op-decl.h.\n\t* mx-op-decl.h: New source.\n\n\t* Makefile.in: Include new sources in build.\n\t* mk-ops.awk: Include mx-op-decl.h in headers, mx-op-defs in .cc\n\tfiles.\n\n\t* CMatrix.cc, CMatrix.h, CNDArray.cc, CNDArray.h, MArray.h, MArray2.h,\n\tMArrayN.h, MDiagArray2.h, boolMatrix.cc, boolMatrix.h, boolNDArray.cc,\n\tboolNDArray.h, chMatrix.cc, chMatrix.h, chNDArray.cc, chNDArray.h,\n\tdMatrix.cc, dMatrix.h, dNDArray.cc, dNDArray.h, fCMatrix.cc,\n\tfCMatrix.h, fCNDArray.cc, fCNDArray.h, fMatrix.cc, fMatrix.h,\n\tfNDArray.cc, fNDArray.h, int16NDArray.cc, int16NDArray.h,\n\tint32NDArray.cc, int32NDArray.h, int64NDArray.cc, int64NDArray.h,\n\tint8NDArray.cc, int8NDArray.h, uint16NDArray.cc, uint16NDArray.h,\n\tuint32NDArray.cc, uint32NDArray.h, uint64NDArray.cc, uint64NDArray.h,\n\tuint8NDArray.cc, uint8NDArray.h: Ditto.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::assign (const idx_vector& i,\n\tconst idx_vector& j,...)): Fix invalid dimension inquiry.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (OP_ROW_SHORT_CIRCUIT): New macro.\n\t(mx_inline_any, mx_inline_all): Override row-reduction case.\n\t(MX_CUMULATIVE_OP, MX_BASE_REDUCTION_OP, MX_REDUCTION_OP,\n\tMX_ANY_OP, MX_ALL_OP, MX_ND_ANY_ALL, MX_ND_REDUCTION,\n\tMX_ND_COMPLEX_OP_REDUCTION, MX_ND_CUMULATIVE_OP,\n\tMX_ND_ANY_EVAL, MX_ND_ALL_EVAL, MX_ND_REAL_OP_REDUCTION):\n\tRemove unused macros.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (OP_RED_FCNN): Use explicit type qualification.\n\t(mx_inline_count): New overloaded template function.\n\t* boolNDArray.h (boolNDArray::sum): Return NDArray.\n\t* boolNDArray.cc (boolNDArray::sum): Return NDArray, use do_mx-red_op.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-C.cc, Array-fC.cc: Don't redefine complex comparison.\n\t* Sparse.cc (Sparse::sort): Don't use vec_index.\n\t* Sparse-C.cc, Sparse-d.cc, Sparse-b.cc: Don't reinstantiate\n\toctave_sort, reflect changes.\n\t* sparse-sort.cc: Explicitly instantiate octave_sort for requested\n\tpointer types.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-cmplx.h (operator <, operator >): New operators.\n\t* mx-inlines.cc (OP_MINMAX_FCN, OP_MINMAX_FCN2, OP_MINMAX_FCNN):\n\tNew macros.\n\t(mx_inline_min, mx_inline_max, do_mx_minmax_op): New overloaded\n\ttemplate functions.\n\t* dNDArray (NDArray::min, NDArray::max): Use do_mx_minmax_op.\n\t* fNDArray (FloatNDArray::min, FloatNDArray::max): Ditto.\n\t* CNDArray (ComplexNDArray::min, ComplexNDArray::max): Ditto.\n\t* fCNDArray (FloatComplexNDArray::min, FloatComplexNDArray::max):\n\tDitto.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* chMatrix.cc (charMatrix::all, charMatrix::any): Use do_mx_red_op.\n\t* chNDArray.cc (charNDArray::all, charNDArray::any): Ditto.\n\n2009-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-edit.cc (default_command_editor::do_readline):\n\tUse fputs instead of fprintf.\n\n2009-02-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (OP_RED_FCN, OP_RED_FCN2, OP_RED_FCNN, OP_CUM_FCN,\n\tOP_CUM_FCN2, OP_CUM_FCNN): Include TRET parameter.\n\t(OP_RED_ANYC, OP_RED_ANYR, OP_RED_ALLC, OP_RED_ALLR): New macros.\n\t(is_true, is_false): New template functions.\n\t(mx_inline_any, mx_inline_all): New template functions.\n\n\t* dMatrix.cc (Matrix::any, Matrix::all): Use do_mx_red_op and\n\tdo_mx_cum_op.\n\t* fMatrix.cc (FloatMatrix::any, FloatMatrix::all): Use do_mx_red_op\n\tand do_mx_cum_op.\n\t* CMatrix.cc (ComplexMatrix::any, ComplexMatrix::all): Use\n\tdo_mx_red_op and do_mx_cum_op.\n\t* fCMatrix.cc (FloatComplexMatrix::any, FloatComplexMatrix::all): Use\n\tdo_mx_red_op and do_mx_cum_op.\n\n\t* dNDArray.cc (NDArray::any, NDArray::all): Use do_mx_red_op and\n\tdo_mx_cum_op.\n\t* fNDArray.cc (FloatNDArray::any, FloatNDArray::all): Use do_mx_red_op\n\tand do_mx_cum_op.\n\t* CNDArray.cc (ComplexNDArray::any, ComplexNDArray::all): Use\n\tdo_mx_red_op and do_mx_cum_op.\n\t* fCNDArray.cc (FloatComplexNDArray::any, FloatComplexNDArray::all):\n\tUse do_mx_red_op and do_mx_cum_op.\n\n\t* intNDArray.cc (intNDArray::any, intNDArray::all): Use do_mx_red_op and\n\tdo_mx_cum_op.\n\n\t* boolNDArray.cc (boolNDArray::any, boolNDArray::all): Use do_mx_red_op and\n\tdo_mx_cum_op.\n\n\t* boolMatrix.cc (boolMatrix::any, boolMatrix::all): Use do_mx_red_op and\n\tdo_mx_cum_op.\n\n2009-02-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* intNDArray.cc: include mx-inlines.cc.\n\t(intNDArray::sum): Use mx_do_red_op (..., mx_inline_sum).\n\t* Range.cc (Range::is_sorted): Add missing return statement.\n\n2009-02-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (OP_RED_SUM, OP_RED_PROD, OP_RED_SUMSQ, OP_RED_SUMSQC,\n\tOP_RED_FCN, OP_RED_FCN2, OP_RED_FCNN, OP_CUM_FCN, OP_CUM_FCN2,\n\tOP_CUM_FCNN): New macros.\n\t(mx_inline_sum, mx_inline_prod, mx_inline_sumsq, mx_inline_cumsum,\n\tmx_inline_cumprod, get_extent_triplet, do_mx_red_op, do_mx_cum_op):\n\tNew template functions.\n\t* dMatrix.cc (Matrix::cumprod, Matrix::cumsum, Matrix::prod,\n\tMatrix::sum, Matrix::sumsq): Use do_mx_red_op and do_mx_cum_op.\n\t* fMatrix.cc (FloatMatrix::cumprod, FloatMatrix::cumsum,\n\tFloatMatrix::prod, FloatMatrix::sum, FloatMatrix::sumsq): Use\n\tdo_mx_red_op and do_mx_cum_op.\n\t* CMatrix.cc (ComplexMatrix::cumprod, ComplexMatrix::cumsum,\n\tComplexMatrix::prod, ComplexMatrix::sum, ComplexMatrix::sumsq): Use\n\tdo_mx_red_op and do_mx_cum_op.\n\t* fCMatrix.cc (FloatComplexMatrix::cumprod,\n\tFloatComplexMatrix::cumsum, FloatComplexMatrix::prod,\n\tFloatComplexMatrix::sum, FloatComplexMatrix::sumsq): Use do_mx_red_op\n\tand do_mx_cum_op.\n\n2009-02-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (if_else_type): Remove\n\t(octave_int_base::truncate_int): Use if_then_else.\n\n2009-02-12  John W. Eaton  <jwe@octave.org>\n\n\t* lo-traits.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\n\t* Array.h (compare_fcn_type): New typedef.\n\t* oct-sort.h (compare_fcn_type): Ditto.\n\n\t* oct-sort.h, oct-sort.cc (octave_sort<T>::octave_sort,\n\toctave_sort<T>::set_compare, octave_sort<T>::compare):\n\tUse typedef to simplify decl.\n\t(octave_sort<T>::ascending_compare,\n\toctave_sort<T>::descending_compare):\n\tUse ref_param<T>::type for parameter decl.\n\n\t* Array.cc (sort_isnan): Use ref_param<T>::type for parameter decl.\n\t(Array<T>::sort): Use explicit template parameter for sort_isnan calls.\n\n\t* Array.cc, Array-C.cc, Array-fC.cc, Array-d.cc, Array-f.cc\n\t(sortrows_comparator): Rename from _sortrows_comparator.  Change\n\tall uses.  Use typedef for return value to simplify decl.\n\t(sort_isnan): Rename from _sort_isnan.  Change all uses.\n\t(NO_INSTANTIATE_ARRAY_SORT): Use typedef to simplify instantiation\n\tof sortrows_comparator.\n\n\t* Array-C.cc, Array-fC.cc (sort_isnan, ascending_compare,\n\tdescending_compare, nan_ascending_compare,\n\tnan_descending_compare):\n\n2009-02-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (octave_sort<T>::is_sorted, octave_sort<T>::sort_rows,\n\toctave_sort<T>::is_sorted_rows): New methods.\n\t* oct-sort.h: Declare them.\n\n\t* Array.cc (Array<T>::is_sorted): New method.\n\t(INSTANTIATE_ARRAY_SORT, NO_INSTANTIATE_ARRAY_SORT,\n\tINSTANTIATE_ARRAY_AND_ASSIGN, INSTANTIATE_ARRAY): Move macros here.\n\t* Array.h: Reflect changes.\n\n\t* dim-vector.h (dim_vector::is_vector): New method.\n\t* Array-C.cc, Array-fC.cc: Override _sort_isnan, don't check for\n\tNaN in default comparators. Provide NaN-safe comparators, override\n\t_sortrows_comparator.\n\t* Array-d.cc, Array-f.cc: Provide NaN-safe comparators, override\n\t_sortrows_comparator.\n\t* Range.cc (Range::is_sorted): New method.\n\t* Range.h: Declare it.\n\n2009-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (octave_sort<T>): Rewrite for optimizations. Allow\n\tinlined comparison functor and by-the-way indexed sorting.\n\t* oct-sort.h (octave_sort<T>): Update interface.\n\t* Array.cc (Array<T>::sort): Reflect changes. Use copy & partition\n\tmechanism.\n\t* Array-d.cc, Array-f.cc, Array-C.cc, Array-fC.cc, Array-s.cc,\n\tArray-i.cc: Reflect changes.\n\n2009-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* file-stat.cc (base_file_stat::is_sock):\n\tUse EXISTS instead of OK in previous change.\n\n\t* file-stat.cc (base_file_stat::is_blk, base_file_stat::is_chr,\n\tbase_file_stat::is_dir, base_file_stat::is_fifo,\n\tbase_file_stat::is_lnk, base_file_stat::is_reg,\n\tbase_file_stat::is_sock): Return false if object is not initialized.\n\tFrom Rafael Laboissiere <rafael@debian.org>.\n\n2009-02-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.h (idx_vector::idx_colon_rep,\n\tidx_vector::idx_scalar_rep, idx_vector::idx_range_rep,\n\tidx_vector::idx_vector_rep): Declare allocators.\n\t* idx-vector.cc: Define them.\n\n2009-02-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* str-vec.h (string_vector::sort): Remove implementation.\n\t* str-vec.cc (string_vector::sort): Move here. Use in-place sorting.\n\t* Array-str.cc: Fix order of header files.\n\t* oct-sort.cc (octave_sort<T>::merge_hi): std::copy ->\n\tstd::copy_backward where appropriate.\n\n2009-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* Array-util.cc (zero_dims_inquire): Eliminate unused variable MATCH.\n\n\t* Sparse.cc (assign (Sparse<LT>& lhs, const Sparse<RT>& rhs)):\n\tEliminate unused variable N.\n\n\t* MArray-f.cc (MArray<float>::norm (float p) const,\n\tMArray<FloatComplex>::norm (float p) const): Pass P to xnorm.\n\n\t* eigs-base.cc (EigsRealNonSymmetricFunc, EigsRealSymmetricFunc)\n\t(EigsComplexNonSymmetricFunc): Avoid unused parameter warning.\n\t* idx-vector.cc (idx_vector::freeze): Likewise.\n\n2009-02-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-locbuf.h: Specialize OCTAVE_LOCAL_BUFFER to use chunked\n\tallocation for pointers and const pointers.\n\n2009-02-03  Benjamin Lindner  <lindnerben@gmx.net>\n\n\t* Makefile.in: Add missing library reference.\n\n2009-02-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::sort (octave_idx_type, sortmode)):\n\tCopy array on-the-fly.\n\t(Array<T>::sort (Array<octave_idx_type> &, octave_idx_type, sortmode)):\n\tCopy array on-the-fly, use bare pointers rather than vec_index.\n\n\t* Array-d.cc (Array<double>::sort (octave_idx_type, sortmode)):\n\tCopy array on-the-fly.\n\t(Array<double>::sort (Array<octave_idx_type> &, octave_idx_type, sortmode)):\n\tCopy array on-the-fly, use bare pointers rather than vec_index.\n\n\t* Array-f.cc (Array<float>::sort (octave_idx_type, sortmode)):\n\tCopy array on-the-fly.\n\t(Array<float>::sort (Array<octave_idx_type> &, octave_idx_type, sortmode)):\n\tCopy array on-the-fly, use bare pointers rather than vec_index.\n\n2009-02-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_fabs_dup, mx_inline_cabs_dup): New funcs.\n\n\t* dMatrix.cc (real, imag, Matrix::abs): Simplify.\n\t* fMatrix.cc (real, imag, FloatMatrix::abs): Simplify.\n\t* CMatrix.cc (ComplexMatrix::abs, ComplexMatrix::conj): Simplify.\n\t* fCMatrix.cc (FloatComplexMatrix::abs, FloatComplexMatrix::conj): Simplify.\n\n\t* CMatrix.h, fCMatrix.h (conj): Add missing decl.\n\n\t* dNDArray.cc (real, imag, NDArray::abs): Simplify.\n\t* fNDArray.cc (real, imag, FloatNDArray::abs): Simplify.\n\t* CNDArray.cc (ComplexNDArray::abs, ComplexNDArray::conj): Simplify.\n\t* fCNDArray.cc (FloatComplexNDArray::abs, FloatComplexNDArray::conj): Simplify.\n\n\t* CMatrix.h, fCMatrix.h (conj): New decl.\n\n2009-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* intNDArray.h (intNDArray<T>:any_element_is_nan): New function.\n\t* boolNDArrah.h (boolNDArray::any_element_is_nan): New function.\n\t* chNDArray.h (charNDArray::any_element_is_nan): New function.\n\n2009-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LIBRARIES, install, uninstall): Use SHLLIBPRE\n\tand SHLBINPRE library prefixes.\n\tFrom Marco Atzeri <marco_atzeri@yahoo.it>.\n\n2009-01-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (Matrix::Matrix (const RowVector&)): Use shallow copy.\n\t(Matrix::Matrix (const ColumnVector&)): Ditto.\n\t(Matrix::row): Ditto.\n\t(Matrix::column): Ditto.\n\n\t* fMatrix.cc (FloatMatrix::FloatMatrix (const FloatRowVector&)): Use\n\tshallow copy.\n\t(FloatMatrix::FloatMatrix (const FloatColumnVector&)): Ditto.\n\t(FloatMatrix::row): Ditto.\n\t(FloatMatrix::column): Ditto.\n\n\t* CMatrix.cc (ComplexMatrix::ComplexMatrix (const ComplexRowVector&)):\n\tUse shallow copy.\n\t(ComplexMatrix::ComplexMatrix (const ComplexColumnVector&)): Ditto.\n\t(ComplexMatrix::row): Ditto.\n\t(ComplexMatrix::column): Ditto.\n\n\t* fCMatrix.cc (FloatComplexMatrix::FloatComplexMatrix (const FloatComplexRowVector&)):\n\tUse shallow copy.\n\t(FloatComplexMatrix::FloatComplexMatrix (const FloatComplexColumnVector&)): Ditto.\n\t(FloatComplexMatrix::row): Ditto.\n\t(FloatComplexMatrix::column): Ditto.\n\n2009-01-27  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* Makefile.in (LINK_DEPS): Include ARPACK_LIBS and REGEX_LIBS in\n\tthe list.\n\n2009-01-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleQR.cc (QR::init): Use form. Use local buffers.\n\tQuery for optimal block size.\n\t(QR::form): New function.\n\t* dbleQR.h: Declare it.\n\t* dbleQRP.cc (QRP::init):Use form. Use local buffers.\n\tQuery for optimal block size.\n\n\t* floatQR.cc (FloatQR::init): Use form. Use local buffers.\n\tQuery for optimal block size.\n\t(FloatQR::form): New function.\n\t* floatQR.h: Declare it.\n\t* floatQRP.cc (FloatQRP::init):Use form. Use local buffers.\n\tQuery for optimal block size.\n\n\t* CmplxQR.cc (ComplexQR::init): Use form. Use local buffers.\n\tQuery for optimal block size.\n\t(ComplexQR::form): New function.\n\t* CmplxQR.h: Declare it.\n\t* CmplxQRP.cc (ComplexQRP::init):Use form. Use local buffers.\n\tQuery for optimal block size.\n\n\t* fCmplxQR.cc (FloatComplexQR::init): Use form. Use local buffers.\n\tQuery for optimal block size.\n\t(FloatComplexQR::form): New function.\n\t* fCmplxQR.h: Declare it.\n\t* fCmplxQRP.cc (FloatComplexQRP::init):Use form. Use local buffers.\n\tQuery for optimal block size.\n\n2009-01-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::assign (const idx_vector&, const Array<T>&)):\n\tOptimize assignment to an empty array.\n\t(Array<T>::assign (const idx_vector&, const idx_vector&, const Array<T>&)):\n\tOptimize assignment to an empty array.\n\n2009-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array2.h (Array2<T>::index): Declare resize_ok as bool.\n\t* ArrayN.h (ArrayN<T>::index): Ditto. Declare index vectors as const\n\trefs.\n\n2009-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Range.cc (sort_internal): Add missing test.\n\n2009-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::index (..., bool resize_ok)):\n\tOptimize the all-scalar-indices cases.\n\n2009-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleQR.h: Optionally declare warn_qrupdate_once.\n\t* dbleQR.cc: Define it.\n\t* (CmplxQR.h, dbleQR.h, fCmplxQR.h, floatQR.h): Declare replacement\n\tmethods unconditionally.\n\t* (CmplxQR.cc, dbleQR.cc, fCmplxQR.cc, floatQR.cc): Define\n\tupdating replacement methods.\n\t* (CmplxCHOL.h, dbleCHOL.h, fCmplxCHOL.h, floatCHOL.h): Declare\n\treplacement methods unconditionally.\n\t* (CmplxCHOL.cc, dbleCHOL.cc, fCmplxCHOL.cc, floatCHOL.cc): Define\n\tupdating replacement methods.\n\n2009-01-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Range.cc ( operator + (double x, const Range& r),\n\toperator + (const Range& r, double x),\n\toperator - (double x, const Range& r),\n\toperator - (const Range& r, double x),\n\toperator * (double x, const Range& r),\n\toperator * (const Range& r, double x)): New operators.\n\t* Range.h: Declare them.\n\n2009-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* file-stat.h, file-stat.cc (class base_file_stat): New base class.\n\t(class file_stat): Derive from base_file_stat.\n\t(class file_fstat): New class, derived from base_file_stat.\n\n2009-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* floatQR.h (FloatQR::update, FloatQR::insert_col,\n\tFloatQR::insert_row, FloatQR::delete_col, FloatQR::delete_row,\n\tFloatQR::shift_col): Update interfaces.\n\n\t* floatQR.cc: Update external decls for qrupdate routines.\n\t(FloatQR::update, FloatQR::insert_col, FloatQR::insert_row,\n\tFloatQR::delete_col, FloatQR::delete_row, FloatQR::shift_col): Reflect\n\tchanges in qrupdate interfaces, implement batch updates.\n\n\t* dbleQR.h (QR::update, QR::insert_col, QR::insert_row,\n\tQR::delete_col, QR::delete_row, QR::shift_col): Update interfaces.\n\n\t* dbleQR.cc: Update external decls for qrupdate routines.\n\t(QR::update, QR::insert_col, QR::insert_row, QR::delete_col,\n\tQR::delete_row, QR::shift_col): Reflect changes in qrupdate\n\tinterfaces, implement batch updates.\n\n\t* fCmplxQR.h (FloatComplexQR::update, FloatComplexQR::insert_col,\n\tFloatComplexQR::insert_row, FloatComplexQR::delete_col,\n\tFloatComplexQR::delete_row, FloatComplexQR::shift_col): Update\n\tinterfaces.\n\n\t* fCmplxQR.cc: Update external decls for qrupdate routines.\n\t(FloatComplexQR::update, FloatComplexQR::insert_col,\n\tFloatComplexQR::insert_row, FloatComplexQR::delete_col,\n\tFloatComplexQR::delete_row, FloatComplexQR::shift_col): Reflect\n\tchanges in qrupdate interfaces,\n\timplement batch updates.\n\n\t* CmplxQR.h (ComplexQR::update, ComplexQR::insert_col,\n\tComplexQR::insert_row, ComplexQR::delete_col, ComplexQR::delete_row,\n\tComplexQR::shift_col): Update interfaces.\n\n\t* CmplxQR.cc: Update external decls for qrupdate routines.\n\t(ComplexQR::update, ComplexQR::insert_col,\n\tComplexQR::insert_row, ComplexQR::delete_col, ComplexQR::delete_row,\n\tComplexQR::shift_col): Reflect changes in qrupdate interfaces,\n\timplement batch updates.\n\n\t* floatCHOL.h (FloatCHOL::update, FloatCHOL::downdate,\n\tFloatCHOL::insert_sym): Update interfaces.\n\t* floatCHOL.cc: Update external decls for qrupdate routines.\n\t(FloatCHOL::update, FloatCHOL::downdate, FloatCHOL::insert_sym,\n\tFloatCHOL::delete_sym, FloatCHOL::shift_sym): Reflect changes in\n\tqrupdate interfaces,\n\n\t* CHOL.h (CHOL::update, CHOL::downdate, CHOL::insert_sym): Update\n\tinterfaces.\n\t* CHOL.cc: Update external decls for qrupdate routines.\n\t(CHOL::update, CHOL::downdate, CHOL::insert_sym, CHOL::delete_sym,\n\tCHOL::shift_sym): Reflect changes in qrupdate interfaces,\n\n\t* fCmplxCHOL.h (FloatComplexCHOL::update, FloatComplexCHOL::downdate,\n\tFloatComplexCHOL::insert_sym): Update interfaces.\n\t* fCmplxCHOL.cc: Update external decls for qrupdate routines.\n\t(FloatComplexCHOL::update, FloatComplexCHOL::downdate,\n\tFloatComplexCHOL::insert_sym, FloatComplexCHOL::delete_sym,\n\tFloatComplexCHOL::shift_sym): Reflect changes in qrupdate interfaces,\n\n\t* CmplxCHOL.h (ComplexCHOL::update, ComplexCHOL::downdate,\n\tComplexCHOL::insert_sym): Update interfaces.\n\t* CmplxCHOL.cc: Update external decls for qrupdate routines.\n\t(ComplexCHOL::update, ComplexCHOL::downdate, ComplexCHOL::insert_sym,\n\tComplexCHOL::delete_sym, ComplexCHOL::shift_sym): Reflect changes in\n\tqrupdate interfaces,\n\n2009-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array<T>): Document internal use of slice_data and\n\tslice_len.\n\n2009-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (Sparse<T>::reshape): Include mismatched dimensions in\n\terror message.\n\t* Array.cc (Array<T>::reshape): Likewise.\n\tFrom Robert Millan <rmh@aybabtu.com>.\n\n2009-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array<T>::rep, Array<T>::dimensions): Make protected.\n\t* Array.cc (Array<T>::make_unique): Move implementation here.\n\t(Array<T>::fill): Ditto.\n\t* DiagArray2.h (DiagArray2<T>): Reimplement without abusing\n\tArray<T> internals.\n\t(DiagArray2<T>::operator Array2<T>): New method.\n\t* DiagArray2.cc (DiagArray2<T>): Update methods.\n\t* MDiagArray2.h (MDiagArray2<T>::operator Array2<T>): Simplify.\n\t* PermMatrix.h (PermMatrix): Reimplement without abusing\n\tArray<T> internals.\n\t* PermMatrix.cc (PermMatrix): Update methods.\n\n2009-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc, Array.h (all Array<T> constructors): Handle slice_data and\n\tslice_len.\n\t(Array<T>::Array<T> (const Array<T>&, const dim_vector&,\n\toctave_idx_type, octave_idx_type)): New constructor.\n\t(Array<T>::index): Use shallow copy when index reduces to a contiguous\n\trange.\n\t(Array<T>::make_unique): Rewrite.\n\t(Array<T>::ArrayRep): Delete redundant methods.\n\t(rec_index_helper::is_cont_range): New method.\n\t(Array<T>::maybe_economize): New method.\n\t* DiagArray2.cc (DiagArray2<T>::resize): Fix the mess.\n\n2008-01-15  Rafael Laboissiere  <rafael@debian.org>\n\n\t* oct-md5.cc: Include <cstdio>.\n\n2009-01-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array::ArrayRep::qsort): Remove.\n\t(Array::qsort): Remove.\n\t* glob-match.cc (glob_match::glob): qsort -> sort.\n\t* str-vec.cc (string_vector::compare): Remove.\n\t* str-vec.h (string_vector::compare): Remove decl.\n\t(string_vector::qsort): Rename to sort, call Array::sort.\n\n2008-12-23  David Bateman  <dbateman@free.fr>\n\n\t* eigs-base.cc: New file with template wrapper for ARPACK.\n\t* Makefile.in (TEMPLATE_SRC): Add it here.\n\n2008-12-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (rec_permute_helper): New class.\n\t(Array<T>::permute): Rewrite using the recursive algorithm.\n\n2008-12-12  David Bateman  <dbateman@free.fr>\n\n\t* sparse-base-chol.cc (inverse): Fix inversion based on cholesky\n\tfactorization.\n\n2008-12-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-locbuf.cc: New source.\n\t* oct-locbuf.h (octave_chunk_buffer): New class.\n\t(octave_local_buffer): Subclass from octave_chunk_buffer for selected\n\tPOD types.\n\n2008-12-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-op-defs.h (DMDM_BIN_OP): Fix invalid buffer length.\n\n2008-12-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.h, dMatrix.cc (Matrix::expm): Remove.\n\t* fMatrix.h, fMatrix.cc (FloatMatrix::expm): Remove.\n\t* CMatrix.h, CMatrix.cc (ComplexMatrix::expm): Remove.\n\t* fCMatrix.h, fCMatrix.cc (FloatComplexMatrix::expm): Remove.\n\n2008-12-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* base-aepbal.h: New source.\n\t* dbleAEPBAL.h, dbleAEPBAL.cc: Rebase AEPBAL on base_aepbal.\n\t* floatAEPBAL.h, floatAEPBAL.cc: Rebase FloatAEPBAL on base_aepbal.\n\t* CmplxAEPBAL.h, CmplxAEPBAL.cc: Rebase ComplexAEPBAL on base_aepbal.\n\t* fCmplxAEPBAL.h, fCmplxAEPBAL.cc: Rebase FloatComplexAEPBAL on base_aepbal.\n\n2008-12-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::idx_vector_rep::idx_vector_rep (const\n\tSparse<bool>&)): New constructor.\n\t* idx_vector.h: Declare it.\n\t(idx_vector::idx_vector (const Sparse<bool>&)): New constructor.\n\t* idx-vector.cc (idx_vector::idx_vector_rep::idx_vector_rep (const\n\tArray<bool>&)): Fix extent calculation.\n\n2008-12-09  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (INCLUDES): Add oct-locbuf.h\n\n2008-12-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mx-inlines.cc (mx_inline_fill_vs): New template function.\n\t* mx-op-defs.h (everywhere): Replace int by octave_idx_type.\n\t(MDM_MULTIPLY_OP): Use mx_inline_mul_vs and mx_inline_fill_vs.\n\t(DMM_MULTIPLY_OP): Ditto.\n\t* fDiagMatrix.cc (operator *): Remove redundant ifs.\n\t* fCDiagMatrix.cc (operator *): Remove redundant ifs.\n\n2008-12-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-locbuf.h (OCTAVE_LOCAL_BUFFER_INIT): New macro.\n\n2008-10-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-locbuf.h: New header file.\n\t* Array-d.cc, Array-f.cc, Array.cc, CMatrix.cc, CNDArray.cc,\n\tCSparse.cc, CmplxCHOL.cc, CmplxGEPBAL.cc, MatrixType.cc,\n\tSparse-op-defs.h, Sparse.cc, SparseCmplxLU.cc, SparseCmplxQR.cc,\n\tSparseQR.cc, SparsedbleLU.cc, dMatrix.cc, dNDArray.cc, dSparse.cc,\n\tdata-conv.cc, dbleCHOL.cc, dbleGEPBAL.cc, fCMatrix.cc, fCNDArray.cc,\n\tfCmplxCHOL.cc, fCmplxGEPBAL.cc, fMatrix.cc, fNDArray.cc, file-ops.cc,\n\tfloatCHOL.cc, floatGEPBAL.cc, lo-sysdep.cc, oct-fftw.cc, oct-md5.cc,\n\toct-rand.cc, regex-match.cc, sparse-dmsolve.cc: Include oct-locbuf.h.\n\n2008-12-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DiagArray2.h (DiagArray2<T>): Inherit Array<T> privately.\n\t(DiagArray2<T>::dim1, dim2, rows, columns, cols, length,\n\tnelem, numel, byte_size, dims): New methods.\n\t(DiagArray2<T>::diag): New method decl.\n\t* DiagArray2.cc (DiagArray2<T>::diag): New method.\n\t* MDiagArray2.h (MDiagArray2<T>::diag): New method.\n\t* dDiagMatrix.cc (DiagMatrix::diag): Remove.\n\t* fDiagMatrix.cc (FloatDiagMatrix::diag): Remove.\n\t* CDiagMatrix.cc (ComplexDiagMatrix::diag): Remove.\n\t* fCDiagMatrix.cc (FloatComplexDiagMatrix::diag): Remove.\n\n\t* PermMatrix.h (PermMatrix): Inherit Array<octave_idx_type> privately.\n\t(PermMatrix::dim1, dim2, rows, columns, cols, length,\n\tnelem, numel, byte_size, dims): New methods.\n\n\n2008-12-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dDiagMatrix.cc (DiagMatrix::determinant, DiagMatrix::rcond): New\n\tmethod.\n\t* dDiagMatrix.h: Declare them.\n\t* fDiagMatrix.cc (FloatDiagMatrix::determinant,\n\tFloatDiagMatrix::rcond): New methods.\n\t* fDiagMatrix.h: Declare them.\n\t* CDiagMatrix.cc (ComplexDiagMatrix::determinant,\n\tComplexDiagMatrix::rcond): New methods.\n\t* CDiagMatrix.h: Declare them.\n\t* fCDiagMatrix.cc (FloatComplexDiagMatrix::determinant,\n\tFloatComplexDiagMatrix::rcond): New methods.\n\t* fCDiagMatrix.h: Declare them.\n\n2008-12-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx-vector::complement): Add missing delete.\n\n2008-12-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleQRP.cc (QRP::QRP): Call DGEQP3 rather than DGEQPF.\n\t* floatQRP.cc (FloatQRP::FloatQRP): Call SGEQP3 rather than SGEQPF.\n\t* CmplxQRP.cc (ComplexQRP::ComplexQRP): Call ZGEQP3 rather than ZGEQPF.\n\t* fCmplxQRP.cc (FloatComplexQRP::FloatComplexQRP): Call CGEQP3 rather than CGEQPF.\n\n2008-12-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* PermMatrix.h, PermMatrix.cc: New sources.\n\t* MDiagArray2.cc (MDiagArray2<T>::is_multiple_of_identity): New method.\n\t* MDiagArray2.h (MDiagArray2<T>::is_multiple_of_identity): Declare it.\n\t* idx-vector.cc (idx_vector::is_permutation): New method.\n\t* idx-vector.h (idx_vector::is_permutation): Declare it.\n\t* base-lu.cc (base_lu::getp): New method.\n\t(base_lu::P): Call getp.\n\t(base_lu::Pvec): Call getp.\n\t* base-lu.h (base_lu): Delcare P as PermMatrix. Remove unused template\n\tparams.\n\t* dbleQRP.cc (dbleQRP::dbleQRP): Construct a permutation matrix.\n\t(dbleQRP::Pvec): New method.\n\t* dbleQRP.h: Declare new method. Declare P as PermMatrix.\n\t* CmplxQRP.cc (ComplexQRP): Likewise.\n\t* CmplxQRP.h (ComplexQRP): Likewise.\n\t* floatQRP.cc (FloatQRP): Likewise.\n\t* floatQRP.h (FloatQRP): Likewise.\n\t* fCmplxQRP.cc (FloatComplexQRP): Likewise.\n\t* fCmplxQRP.h (FloatComplexQRP): Likewise.\n\n2008-12-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DiagArray2.h (DiagArray2<T>::DiagArray2<T> (const DiagArray2<U>&)): New template\n\tconstructor.\n\t(DiagArray2<T>::elem, xelem, operator ()): Move to header file to\n\tenable inlining.\n\t* DiagArray2.cc (DiagArray2<T>::elem, xelem, operator ()): Remove\n\timplementations.\n\t* MDiagArray2.h (MDiagArray2<T>::MDiagArray2<T> (const DiagArray2<U>&)): New template\n\tconstructor.\n\t(MDiagArray2<T>::nnz): New method.\n\t* MDiagArray2.cc (MDiagArray2<T>::nnz): Implement it.\n\n\t* dDiagMatrix.h (DiagMatrix::DiagMatrix (const DiagArray2<U>&)): New template\n\tconstructor.\n\t(DiagMatrix::abs): New method decl.\n\t(real (const ComplexDiagMatrix&), imag (const ComplexDiagMatrix&)):\n\tNew decls.\n\t* dDiagMatrix.cc (DiagMatrix::abs): New method.\n\t(operator *(const DiagMatrix&, const DiagMatrix&)): Optimize.\n\t(real (const ComplexDiagMatrix&), imag (const ComplexDiagMatrix&)):\n\tNew functions.\n\n\t* fDiagMatrix.h (FloatDiagMatrix::FloatDiagMatrix (const DiagArray2<U>&)): New template\n\tconstructor.\n\t(FloatDiagMatrix::abs): New method decl.\n\t(real (const FloatComplexDiagMatrix&), imag (const FloatComplexDiagMatrix&)):\n\tNew decls.\n\t* fDiagMatrix.cc (FloatDiagMatrix::abs): New method.\n\t(operator *(const FloatDiagMatrix&, const FloatDiagMatrix&)): Optimize.\n\t(real (const FloatComplexDiagMatrix&), imag (const FloatComplexDiagMatrix&)):\n\tNew functions.\n\n\t* CDiagMatrix.h (ComplexDiagMatrix::ComplexDiagMatrix (const DiagArray2<U>&)): New template\n\tconstructor.\n\t(ComplexDiagMatrix::abs): New method decl.\n\t(conj (const ComplexDiagMatrix&)): Add missing decl.\n\t(ComplexDiagMatrix::all_elements_are_real): New method decl.\n\n\t* CDiagMatrix.cc (CDiagMatrix::abs): New method.\n\t(operator *(const DiagMatrix&, const ComplexDiagMatrix&)): Optimize.\n\t(operator *(const ComplexDiagMatrix&, const DiagMatrix&)): Optimize.\n\t(operator *(const ComplexDiagMatrix&, const ComplexDiagMatrix&)): Optimize.\n\t(ComplexDiagMatrix::all_elements_are_real): New method.\n\n\t* fCDiagMatrix.h (FloatComplexDiagMatrix::FloatComplexDiagMatrix (const DiagArray2<U>&)): New template\n\tconstructor.\n\t(FloatComplexDiagMatrix::abs): New method decl.\n\t(conj (const FloatComplexDiagMatrix&)): Add missing decl.\n\t(FloatComplexDiagMatrix::all_elements_are_real): New method decl.\n\n\t* fCDiagMatrix.cc (CDiagMatrix::abs): New method.\n\t(operator *(const FloatDiagMatrix&, const FloatComplexDiagMatrix&)): Optimize.\n\t(operator *(const FloatComplexDiagMatrix&, const FloatDiagMatrix&)): Optimize.\n\t(operator *(const ComplexDiagMatrix&, const ComplexDiagMatrix&)): Optimize.\n\t(FloatComplexDiagMatrix::all_elements_are_real): New method.\n\n\t* dSparse.cc (SparseMatrix::SparseMatrix (const DiagMatrix&)): New\n\tconstructor.\n\t* dSparse.h (SparseMatrix::SparseMatrix (const DiagMatrix&)): Declare\n\tit.\n\n\t* CSparse.cc (SparseComplexMatrix::SparseComplexMatrix (const ComplexDiagMatrix&)):\n\tNew constructor.\n\t* CSparse.h (SparseComplexMatrix::SparseComplexMatrix (const ComplexDiagMatrix&)):\n\tDeclare it.\n\t* mx-op-defs.h (DMM_MULTIPLY_OP, MDM_MULTIPLY_OP): Optimize.\n\n2008-11-21  Jarkko Kaleva  <d3roga@gmail.com>\n\n\t* EIG.h (EIG::EIG (const Matrix& a, const Matrix& b,\n\tbool calc_eigenvectors = true)): New constructor.\n\t(EIG::EIG (const Matrix& a, const Matrix& b, octave_idx_type& info,\n\tbool calc_eigenvectors = true)): New constructor.\n\t(EIG::EIG (const ComplexMatrix& a, const ComplexMatrix& b,\n\tbool calc_eigenvectors = true)): New constructor.\n\t(EIG::EIG (const ComplexMatrix& a, const ComplexMatrix& b,\n\toctave_idx_type& info, bool calc_eigenvectors = true)): New\n\tconstructor.\n\t* EIG.cc (EIG::init (const Matrix& a, const Matrix& b,\n\tbool calc_eigenvectors)): New function.\n\t(EIG::init (const ComplexMatrix& a, const ComplexMatrix& b,\n\tbool calc_eigenvectors)): New function.\n\t(EIG::symmetric_init (const Matrix& a, const Matrix& b,\n\tbool calc_eigenvectors)): New function.\n\t(EIG::hermitian_init (const ComplexMatrix& a, const ComplexMatrix& b,\n\tbool calc_eigenvectors)): New function.\n\t* fEIG.h (fEIG::fEIG (const FloatMatrix& a, const FloatMatrix& b,\n\tbool calc_eigenvectors = true)): New constructor.\n\t(fEIG::fEIG (const FloatMatrix& a, const FloatMatrix& b,\n\toctave_idx_type& info, bool calc_eigenvectors = true)): New\n\tconstructor.\n\t(fEIG::fEIG (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n\tbool calc_eigenvectors = true)): New constructor.\n\t(fEIG::fEIG (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n\toctave_idx_type& info, bool calc_eigenvectors = true)): New\n\tconstructor.\n\t(fEIG::init (const FloatMatrix& a, const FloatMatrix& b,\n\tbool calc_eigenvectors)): New function.\n\t(fEIG::init (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n\tbool calc_eigenvectors)): New function.\n\t(fEIG::symmetric_init (const FloatMatrix& a, const FloatMatrix& b,\n\tbool calc_eigenvectors)): New function.\n\t(fEIG::hermitian_init (const FloatComplexMatrix& a,\n\tconst FloatComplexMatrix& b, bool calc_eigenvectors)): New function.\n\n2008-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (Matrix::determinant),\n\tfMatrix.cc (FloatMatrix::determinant),\n\tCMatrix.cc (ComplexMatrix::determinant),\n\tfCMatrix.cc (FloatComplexMatrix::determinant):\n\tUse atmp(i,i) instead of elem(i,i).\n\n2008-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DET.h (base_det<T>::square): New member function.\n\t* dMatrix.cc (Matrix::determinant),\n\tfMatrix.cc (FloatMatrix::determinant),\n\tCMatrix.cc (ComplexMatrix::determinant),\n\tfCMatrix.cc (FloatComplexMatrix::determinant):\n\tAllow taking MatrixType argument.\n\t* dMatrix.h, fMatrix.h, CMatrix.h, fCMatrix.h: Update decls.\n\n2008-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DET.h: New source.\n\t* CmplxDET.cc, CmplxDET.h, dbleDET.cc, dbleDET.h, fCmplxDET.cc,\n\tfCmplxDET.h, floatDET.cc, floatDET.h: Remove.\n\t* Makefile.in: Reflect changes.\n\t* mx-defs.h: Remove DET decls.\n\t* mx-ext.h, dMatrix.h, fMatrix.h, CMatrix.h, fCMatrix.h,\n\tdSparse.h, CSparse.h: Include only DET.h.\n\t* dMatrix.cc (Matrix::determinant),\n\tfMatrix.cc (FloatMatrix::determinant),\n\tCMatrix.cc (ComplexMatrix::determinant),\n\tfCMatrix.cc (FloatComplexMatrix::determinant),\n\tdSparse.cc (SparseMatrix::determinant),\n\tCSparse.cc (SparseComplexMatrix::determinant): Use new class.\n\n2008-11-18  David Bateman  <dbateman@free.fr>\n\n\t* file-ops.cc (std::string file_ops::tilde_expand (const\n\tstd::string&)): Check if the string contains a tilde and fast\n\treturn if not.\n\n2008-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* dir-ops.cc (dir_entry::read): Use std::list<std::string> to\n\tcache names before converting to string_vector.\n\n2008-11-14  David Bateman  <dbateman@free.fr>\n\n\t* Array2.h (Array2<T> Array2<T>::index): Correct use of\n\tresize_fill_value.\n\n2008-11-12  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* MArray-C.cc, MArray-d.cc, MArray-f.cc, MArray-fC.cc: Declare\n\tMArray<T>::norm specialization before implicit MArray<T> implicit\n\tinstantiation.\n\t* idx-vector.h (class idx_vector::idx_base_rep, class\n\tidx_vector::idx_range_rep, class idx_vector::idx_colon_rep, class\n\tidx_vector::idx_scalar_rep, class idx_vector::idx_vector_rep): Add\n\tOCTAVE_API tag.\n\t* idx-vector.cc (idx_vector::idx_scalar_rep::idx_scalar_rep(T),\n\tidx_vector::idx_vector_rep::idx_vector_rep(const Array<T>&)): Ditto.\n\t* oct-inttypes.cc (octave_int<T>::type_name): Ditto.\n\t* oct-inttypes.cc (powf(const octave_int<T>&,const float&)): Cast 'b'\n\tto double.\n\t* oct-inttypes.h: Undefine min/max.\n\t* oct-norm.h (xnorm, xfrobnorm, xcolnorms, xrownorms): Add OCTAVE_API\n\ttag.\n\t* oct-norm.cc (xnorm, xfrobnorm, xcolnorms, xrownorms): Ditto.\n\n2008-11-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DiagArray2.h (DiagArray2<T>::maybe_delete_elements): Remove\n\tdeclaration.\n\n2008-11-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-norm.cc: Don't include Array.cc.\n\t(column_norms (const MArray2<T>&, ...)): Use std::vector instead of Array<T> for\n\taccumulator containers. Use empty constructor instead of\n\tArray<T>::resize.\n\t(row_norms (const MArray2<T>&, ...)): Ditto.\n\t(column_norms (const MSparse2<T>&, ...)): Ditto.\n\t(row_norms (const MSparse2<T>&, ...)): Ditto.\n\n2008-10-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-norm.h: New header file.\n\t* oct-norm.cc: New source.\n\t* CSparse.cc (SparseComplexMatrix::row, SparseComplexMatrix::column):\n\tNew member functions.\n\t* CSparse.h (SparseComplexMatrix): Declare them.\n\t* dSparse.cc (SparseMatrix::row, SparseMatrix::column):\n\tNew member functions.\n\t* dSparse.h (SparseMatrix): Declare them.\n\t* MArray-C.cc (MArray<Complex>::norm),\n\tMArray-d.cc (MArray<double>::norm),\n\tMArray-fC.cc (MArray<FloatComplex>::norm),\n\tMArray-f.cc (MArray<float>::norm): Wrap a call to xnorm.\n\n\t* MArray-defs.h (MARRAY_NORM_BODY): Remove.\n\n2008-11-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.cc (idx_vector::is_complement): Set resulting extent\n\tcorrectly.\n\t* Array.cc (Array<T>::delete_elements (int, const idx_vector&)):\n\tFix check for invalid dim.\n\n2008-10-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.h (idx_vector::idx_range_rep::extent): Don't change\n\textent when len is zero.\n\t* idx-vector.h (idx_vector::idx_range_rep::idx_range_rep (void)):\n\tCreate empty range by default.\n\n2008-10-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (octave_int_abs): New function.\n\t(octave_int_arith_base<T, true>::div): Use octave_int_abs instead of\n\tstd::abs.\n\t* oct-inttypes.cc (octave_int_arith_base<int64_t, true>): Ditto.\n\n2008-10-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-C.cc Array-d.cc Array-f.cc Array-fC.cc Array-i.cc Array-s.cc:\n\tDon't use semicolon after INSTANTIATE_ARRAY_ASSIGN.\n\t* Array-util.h (zero_dims_inquire): New declarations.\n\t(is_in, how_many_lgt, short_freeze): Remove declarations.\n\t* Array-util.cc (zero_dims_inquire): New functions.\n\t(is_in, how_many_lgt, short_freeze): Remove functions.\n\t* Array.cc (Array<T>::index, Array<T>::resize_fill, Array<T>::resize,\n\tArray<T>::assign, Array<T>::delete_elements):\n\tRewrite.\n\t* Array.h (Array<T>::index, Array<T>::resize_fill, Array<T>::resize,\n\tArray<T>::assign, Array<T>::delete_elements):\n\tRewrite interfaces.\n\t* Array2.h (Array2<T>::resize): Call Array<T>::resize_fill.\n\t* Array3.h (Array3<T>::resize): Call Array<T>::resize_fill.\n\t* ArrayN.h (ArrayN<T>::resize): Remove declarations.\n\t(ArrayN<T>::index): Fix call to resize_fill_value.\n\t* Sparse.cc (assign, assign1): Use zero-based indices.\n\t* chMatrix.h: Include mx-op-defs.h\n\t* dim-vector.h (dim_vector::any_neg, dim_vector::chop_all_singletons,\n\tdim_vector::redim): New member functions.\n\t* idx-vector.cc: Mostly rewrite.\n\t* idx-vector.h: Mostly rewrite.\n\n2008-10-29  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* lo-specfun.cc (cbesj, cbesy, cbesi, cbesk, cbesh1, cbesh2): Do not\n\tuse std::complex::real() and std::complex::imag() as l-value, this is\n\tnot supported under MSVC.\n\n2008-10-28  John W. Eaton  <jwe@octave.org>\n\n\t* lo-specfun.cc: Fix prototypes for the Fortran subroutines cbesh,\n\tcbesi, cbesj, cbesk, and cbesy.\n\t(cbesh, cbesi, cbesj, cbesk, cbesy): Fix calls to Fortran\n\tsubroutines.\n\n2008-10-28  Brian Gough  <bjg@gnu.org>\n\n\t* lo-specfun.cc (zbesi): Fix scaling factor for negative alpha.\n\t(cbesi): Likewise.\n\n2008-10-23  John Swensen  <jpswensen@comcast.net>\n\n\t* oct-shlib.cc (octave_dyld_shlib::open): Call NSLinkEditError to\n\tget better diagnostic if NSLinkModule fails.\n\n2008-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* oct-shlib.cc (octave_dlopen_shlib::open): Use RTLD_NOW instead\n\tof RTLD_LAZY.\n\n2008-10-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CSparse.cc (ComplexMatrix::expm): Improve inverse preconditioning\n\taccording to Marco Caliari.\n\t* dSparse.cc (Matrix::expm): Likewise.\n\t* fCSparse.cc (FloatComplexMatrix::expm): Likewise.\n\t* fSparse.cc (FloatMatrix::expm): Likewise.\n\n2008-10-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* sparse-util.h (SparseCholPrint): Change char * argument to const\n\tchar *.\n\t* sparse-util.cc (SparseCholPrint): Likewise.\n\n2008-10-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-sort.cc (octave_sort<T>::merge_getmem,\n\toctave_sort<T>::merge_freemem): Replace malloc -> new [], free ->\n\tdelete [].\n\t(octave_sort<T>::merge_lo, octave_sort<T>::merge_hi): Replace\n\tstd::memcpy and std::memmove with std::copy.\n\n2008-10-08  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse-op-defs.h (SPARSE_SMSM_BOOL_OPS): Duplicate code for scalar\n\tsparse arguments rather than rely on extern function.\n\n2008-10-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (octave_base_int<T>::compute_threshold): Return\n\texclusive bounds rather than inclusive, be resistant to compiler\n\toptimizations.\n\t(octave_base_int<T>::convert_real): Use exclusive bounds.\n\n2008-10-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (OCTAVE_INT_DOUBLE_BIN_OP): Change octave_int64 to\n\toctave_uint64 where appropriate.\n\n2008-10-06  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (SPARSE_SMSM_CMP_OPS): Duplicate code for scalar\n\tsparse arguments rather than rely on extern function.\n\n2008-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* Spasre-op-defs.h: Undo previous change.\n\n2008-10-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (octave_int<T>::one, octave_int<T>::zero): Declare\n\tconstants.\n\t* oct-inttypes.cc: Define them.\n\t* oct-inttypes.h: Define mixed operations via long double if possible.\n\t* oct-inttypes.cc: Define alternative implementations for 64-bit\n\tmultiplication and mixed operations.\n\t* mx-ops: Instantiate all 64-bit integer operations.\n\n2008-10-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-lookup.h: Mark functions inline. Add missing std:: qualifiers.\n\n2008-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.h (Sparse<T>::elt_type): New typedef.\n\t* Sparse-op-defs.h (SPARSE_SMSM_BOOL_OP, SPARSE_MSM_CMP_OP):\n\tUse it to call sparse-matrix/scalar operator instead of attempting\n\tto instantiate mixed-type sparse-matrix/scalar operators.\n\n2008-10-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array<T>::maybe_delete_elements): Remove rfv argument from\n\tdeclaration.\n\t* Array.cc (Array<T>::maybe_delete_elements): Remove all usages of\n\trfv.\n\n2008-10-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (assignN): Do not call maybe_delete_elements when\n\tfor empty matrix.\n\n2008-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h: Mostly rewrite.\n\t* oct-inttypes.cc: Modstly rewrite.\n\n2008-09-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (Array<T>::maybe_delete_elements_2(idx_vector&)): Return on\n\tempty index vector.\n\n2008-09-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (assign1, assign2, assignN): Do not call\n\tmaybe_delete_elements.\n\t(maybe_delete_elements (Array<idx_vector>&)): Call the 1D and 2D\n\tspecial handlers if possible.\n\t* Sparse.cc (assign1, assign2, assignN): Do not call\n\tmaybe_delete_elements.\n\n2008-09-22  Brian Gough  <bjg@gnu.org>\n\n\t* oct-rand.cc (initialize_mersenne_twister): Use separate\n\tinitializations for each generator to avoid correlation.\n\n2008-09-12  Jaroslav Hajek  <highegg@gmail.com>\n\n \t* oct-inttypes.h (pow (const octave_int<T>&, const octave_int<T>&)):\n\n2008-09-19  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assign1, assign2, assignN):\n\tClear lhs index before throwing error.\n\t(Array<T>::value): Clear index before throwing error.\n\n2008-09-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (maybe_delete_elements_2 (idx_vector&)): Fix tests to get\n\tbetter Matlab compatibility.\n\t(maybe_delete_elements (idx_vector&, idx_vector&)): Fix tests to get\n\tbetter Matlab compatibility, simplify, gripe on invalid 2-D deletion.\n\n2008-09-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.h (Array<T>::coerce): Use octave_idx_type instead of int.\n\n2008-09-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (pow (const octave_int<T>&, const octave_int<T>&)):\n\tHandle negative exponent correctly.\n\n2008-08-19  David Bateman  <dbateman@free.fr>\n\n\t* oct-inttypes.h (template <class T1, class T2> inline T2\n\toctave_int_fit_to_range (const T1&, const T2&, const T2&),\n\ttemplate <typename T> inline T octave_int_fit_to_range (const\n\tdouble&, const T&, const T&), template <> inline T2\n\toctave_int_fit_to_range<T1, T2> (const T1&, const T2&, const T2&),\n\tOCTAVE_S_US_FTR): Check and flag integer trunctation.\n\t(OCTAVE_INT_FIT_TO_RANGE, OCTAVE_INT_FIT_TO_RANGE2): Adapt for the\n\tabove change.\n\t(OCTAVE_INT_CONV_FIT_TO_RANGE): New macro for conversion to\n\tinteger types.\n\t(octave_int<T>::conv_error_type): New enum to flag conversion and\n\tmath warnings.\n\t(octave_int<T>::octave_int (U i), octave_int<T>::octave_int\n\t(double i), octave_int<>::octave_int (const octave_int<U>& i)):\n\tFlag conversion and math errors other than integer truncation.\n\t(octave_int<T> octave_int<T>::operator - (void)): Flag truncation\n\terror.\n\t(static bool get_trunc_flag (void), static bool clear_trunc_flag\n\t(void, static bool trunc_flag)): Delete.\n\t(static int get_conv_flag (void), static bool get_trunc_flag (void),\n\tstatic bool get_nan_flag (void), static bool get_non_int_flag (void),\n\tstatic bool get_math_trunc_flag (void), static void\n\tclear_conv_flag (void)): New functions to query and reset\n\tconversion and mathw arning state.\n\t(static int cov_flag): New parameter holding current conversion\n\tand math warning state. Set it to zero.\n\t(template <class T> octave_int<T> powf (float, const\n\toctave_int<T>&), template <class T> octave_int<T> powf (const\n\toctave_int<T>&, float)): New functions.\n\n2008-08-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-ieee.cc (octave_ieee_init): Try to ensure that octave_NaN is\n\tclassified as positive by lo_ieee_signbit.\n\n2008-08-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array.cc (no_op_fcn): New static function.\n\t(Array<T>::hermitian): If fcn is null, set to no_op_fcn.\n\n2008-08-07  John W. Eaton  <jwe@octave.org>\n\n\t* sprse-base-chol.h, oct-sparse.h: Don't include config.h.\n\n\t* cmd-edit.cc, file-ops.h, kpse.cc, oct-env.cc, pathsearch.cc:\n\tReplace all uses of NPOS with std::string::npos.\n\n\t* fCmplxLU.h, CmplxLU.h: Fix typo in definition of\n\tmultiple-inclusion guard macro.\n\n2008-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.h, file-ops.cc (file_ops::static_members):\n\tNew singleton class for static members of file_ops.\n\n\t* pathsearch.h, pathsearch.cc (class dir_path::static_members):\n\tNew singleton class for static members of dir_path.\n\n\t* pathsearch.cc (dir_path::init): Move octave_kpathsea_initialized\n\there from file scope.\n\n2008-08-04  John W. Eaton  <jwe@octave.org>\n\n\t* oct-env.cc (octave_env::do_set_program_name,\n\toctave_env::do_base_pathname): Fix usage of\n\tfile_ops::dir_sep_chars.\n\t(octave_env::do_make_absolute): Fix usage of\n\tfile_ops::dir_sep_chars and file_ops::dir_sep_str.\n\t(octave_env::do_get_home_directory): Fix usage of\n\tfile_ops::dir_sep_str.\n\n\t* file-ops.h (file_ops::do_is_dir_sep): New function.\n\t(file_ops_::is_dir_sep): Call it.\n\t* file-ops.cc (class file_ops): Make it a proper singleton object.\n\t(file_ops::file_ops): New constructor.\n\t(file_ops::instance_ok): New function.\n\t(file_ops::xdir_sep_char): Now private.  No longer static.  Rename\n\tfrom dir_sep_char.\n\t(file_ops::xdir_sep_str): Likewise, from dir_sep_str.\n\t(file_ops::xdir_sep_chars): Likewise, from dir_sep_chars.\n\t(file_ops::dir_sep_char, file_ops::dir_sep_str,\n\tfile_ops::dir_sep_chars): New functions.\n\t(file_ops::recursive_rmdir): Fix usage of file_ops::dir_sep_str.\n\t(file_ops::concat): Fix usage of file_ops::dir_sep_char.\n\n\t* oct-env.cc (octave_env::instance_ok): Fix typo in error message.\n\n2008-07-30  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h: Style fixes.\n\n2008-07-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-inttypes.h (octave_int<T>::trunc_flag): New member static field.\n\t(octave_int<T>::get_trunc_flag, octave_int<T>::clear_trunc_flag): New\n\tmember functions.\n\t(octave_int<T>::octave_int (const octave_int<U>&)): set trunc_flag\n\ton truncation.\n\t(SPECIALIZE_WIDENING_CONVERSION): New macro.\n\t(DECLARE_OCTAVE_INT_TYPENAME): New macro.\n\n2008-07-29  David Bateman  <dbateman@free.fr>\n\n\t* lo-ieee.h (LO_IEEE_NA_HW, LO_IEEE_NA_LW, LO_IEEE_NA_FLOAT):\n\tChange definition so cast from single to double and visa versa\n\tmaintains NA value.\n\t(LO_IEEE_NA_HW_OLD, LO_IEEE_NA_LW_OLD): Keep old values.\n\t(extern OCTAVE_API int __lo_ieee_is_old_NA (double)): Function to\n\tdetect old NA value.\n\t(extern OCTAVE_API double __lo_ieee_replace_old_NA (double)):\n\tFunction to replace old NA value with new new.\n\t* lo-cieee.c (int __lo_ieee_is_old_NA (double)): Function to\n\tdetect old NA value.\n\t(double __lo_ieee_replace_old_NA (double)): Function to replace\n\told NA value with new new.\n\t* data-conv.cc (void read_doubles(std::istream&, double *,\n\tsave_type, int, bool, octave_mach_info::float_format)): Test if\n\tloaded NA values is the old representation and replace it.\n\n2008-07-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-math.h: Ensure log2 is undefined from cmath in C++ mode.\n\n2008-07-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* oct-mutex.h (octave_base_mutex::octave_base_mutex): Initialize\n\tcount to 1, not -1.\n\n\t* oct-mutex.cc (octave_base_mutex::lock, octave_base_mutex::unlock):\n\tReplace error calls with (*current_liboctave_error_handler).\n\n2008-07-21  John W. Eaton  <jwe@octave.org>\n\n\t* regex-match.cc (regex_match::init): Initialize err to 0.\n\n2008-07-19  John W. Eaton  <jwe@octave.org>\n\n\t* oct-mutex.h (class octave_base_mutex): New class.\n\t(class octave_mutex): Don't use union for rep and count.\n\t(octave_mutex::rep): Declare as octave_base_mutex.\n\t(octave_mutex::count): Delete.\n\t(octave_mutex::lock, octave_mutex::unlock): No longer virtual.\n\t(octave_mutex::~octave_mutex): No need to check that rep is\n\tvalid or set rep to zero after deleting.\n\t(octave_mutex::operator =): No need to check that rep is valid.\n\t* oct-mutex.cc (octave_w32_mutex, octave_pthread_mutex): Derive\n\tfrom octave_base_mutex, not octave_mutex.\n\n2008-07-18  John W. Eaton  <jwe@octave.org>\n\n\t* oct-mutex.h (octave_mutex::octave_mutex (int)): Initialize rep\n\tto 0, not count.\n\t* oct-mutex.cc (octave_mutex::octave_mutex (void)): Set rep->count\n\tto 1 instead of incrementing it.\n\n2008-07-17  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* dNDArray.cc: Do not include ctor NDArray(Array<octave_idx_type>,\n\tbool, bool) into conditional HAVE_FFTW3 preprocessor statement.\n\n2008-07-16  John W. Eaton  <jwe@octave.org>\n\n\t* oct-mutex.h (octave_autolock::octave_autolock (void),\n\toctave_autolock (const octave_autolock&),\n\toctave_autolock::operator = (const octave_autolock&)):\n\tDelete definitions.\n\n2008-07-16  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* cmd-edit.cc (event_hook_lock): New static mutex variable.\n\t(command_editor::event_handler): Lock and copy event_hook_set before\n\texecuting handlers.\n\t(command_editor::add_event_hook, command_editor::remove_event_hook):\n\tAutolock event_hook_lock.\n\n2008-07-15  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* oct-mutex.h, oct-mutex.cc: New files.\n\t* Makefile.in: Add them to appropriate lists.\n\n2008-07-15  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sort.cc, oct-sort.h (octave_sort<T>::count_run): Declare\n\tdescending arg as bool&.\n\t(octave_sort<T>::sort): Pass bool to count_run for descending arg.\n\n2008-07-11  John W. Eaton  <jwe@octave.org>\n\n\t* dDiagMatrix.cc (DiagMatrix::diag): Return empty ColumnVector if\n\tnumber of rows or columns is 0.\n\t* fDiagMatrix.cc (FloatDiagMatrix::diag): Likewise.\n\n\t* Array-util.cc (is_vector): Avoid GCC warning.\n\t* Array-f.cc (Array<float>::sort): Likewise.\n\t* Array-d.cc (Array<double>::sort): Likewise.\n\t* dbleQR.cc (QR::QR (const Matrix&, const Matrix&)): Likewise.\n\t* CmplxQR.cc (ComplexQR::ComplexQR (const ComplexMatrix&, const\n\tComplexMatrix&)): Likewise.\n\t* floatQR.cc (FloatQR::FloatQR (const FloatMatrix&, const\n\tFloatMatrix&)): Likewise.\n\t* fCmplxQR.cc (FloatComplexQR::FloatComplexQR (const\n\tFloatComplexMatrix&, const FloatComplexMatrix&)): Likewise.\n\t* Quad.cc (IndefQuad::do_integrate (octave_idx_type&,\n\toctave_idx_type&, float&), FloatIndefQuad::do_integrate,\n\tDefQuad::do_integrate octave_idx_type&, octave_idx_type&, float&,\n\tFloatIndefQuad::do_integrate): Likewise.\n\n\t* mx-op-defs.h (MS_BOOL_OP, SM_BOOL_OP, MM_BOOL_OP, NDS_BOOL_OP,\n\tSND_BOOL_OP, NDND_BOOL_OP): Detect NaN values.\n\t* Array-util.cc (gripe_nan_to_logical_conversion): New function.\n\t* Array-util.h: Provide decl.\n\t* oct-inttypes.h (xisnan (octave_int<T>)): New function.\n\t* lo-mappers.h (xisnan (bool), xisnan (char)): New inline functions.\n\n\t* CMatrix.cc, CNDArray.cc, CSparse.cc, dMatrix.cc, dNDArray.cc,\n\tdSparse.cc, fCMatrix.cc, fCNDArray.cc, fMatrix.cc, fNDArray.cc:\n\tNew member function, any_element_is_nan.\n\t* CMatrix.h, CNDArray.h, CSparse.h, dMatrix.h, dNDArray.h,\n\tdSparse.h, fCMatrix.h, fCNDArray.h, fMatrix.h, fNDArray.h:\n\tProvide decl.\n\n2008-07-10  David Bateman  <dbateman@free.fr>\n\n\t* dNDArray.cc (NDArray::NDArray (const Array<octave_idx_type>&,\n\tbool, bool)): New constructor.\n\t* dNDArray.h: Provide decl.\n\n2008-07-10  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* lo-specfun.h: Fix typo in erff/erfcf declaration.\n\t* lo-specfun.cc: Ditto. Add atanhf implementation.\n\n2008-06-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* MatrixType.h: Add missing include statement.\n\n2008-06-13  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* lo-mappers.cc (arg): Remove ambiguity about atan2(float,float) usage.\n\t* fCmplxDET.cc (FloatComplexDET::initialize10): Likewise, for pow.\n\n2008-06-11  John W. Eaton  <jwe@octave.org>\n\n\t* so-array.h, so-array.cc, Array-so.cc: Delete.\n\t* Makefile.in: Remove them from the lists.\n\n2008-06-05  John W. Eaton  <jwe@octave.org>\n\n\t* oct-shlib.cc (octave_base_shlib::remove): Only dereference\n\tcounter if iterator is valid.\n\n2008-06-02  David Bateman  <dbateman@free.fr>\n\n\t* fCmplxDET.cc (FloatComplexDET::value_will_overflow,\n\tFloatComplexDET:value_will_underflow): Replace DBL_MIN and DBL_MAX\n\twith FLT_MIN and FLT_MAX.\n\t* floatDET.cc ((FloatDET::value_will_overflow,\n\tFloatDET:value_will_underflow): Ditto.\n\t* lo-cieee.c (__lo_ieee_float_is_NA): Check only a sngle word for\n\tfloat NA value.\n\t(lo_ieee_float_inf_value): Return correct float Infinity value.\n\t(lo_ieee_float_NA_value): Return correct float NA value.\n\t(lo_ieee_float_NaN_value): Return correct float NaN value.\n\t* lo-ieee.cc (octave_ieee_init): Set float NA value correctly.\n\t* lo-ieee.h (lo_ieee_float): value of union is of type float.\n\t(LO_IEEE_NA_FLOAT): Make NA value a valid float NaN.\n\t(LO_IEEE_NA_FLOAT_LW): Delete.\n\n2008-06-02  David Bateman  <dbateman@free.fr>\n\n\t* fCmplxLU.cc (class FloatComplexLU): Correct error in instantiation.\n\t* floatLU.cc (class FloatLU): ditto.\n\t* floatLU.h (class FloatLU): ditto.\n\n\t* floatAEPBAL.cc (octave_idx_type FloatAEPBALANCE::init (const\n\tFloatMatrix&, const std::string&)): Use FloatMatrix to initialize\n\tbalancing_mat.\n\n\t* Makefile.in (MATRIX_INC): Add fCmplxAEPBAL.h and floatAEPBAL.h.\n\t(MATRIX_SRC): Add fCmplxAEPBAL.cc and floatAEPBAL.cc.\n\n2008-05-21  David Bateman  <dbateman@free.fr>\n\n\t* Quad-opts.in: Handle single precision tolerances.\n\t* Quad.cc (float_user_fcn): New static variable.\n\t(quad_float_fcn_ptr): New typedef.\n\t(qagp, quagi): New QUADPACK decls.\n\t(float_user_function): New function.\n\t(DefQuad::do_integrate, IndefQuad::do_integrate): Float versions.\n\t(FloatDefQuad::do_integrate, FloatIndefQuad::do_integrate):\n\tNew functions.\n\t* Quad.h (class Quad): Handle float type.\n\t(class FloatDefQuad, class FloatIndefQuad): New classes.\n\n2008-05-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* fCMatrix.h (xgemm): Provide decl.\n\t(xcdotc, csyrk, cherk): New F77 decls.\n\t* fMatrix.cc (xgemm): New function.\n\t(operator * (const FloatMatrix&, const FloatMatrix&)): Simplify.\n\t(get_blas_trans_arg): New function.\n\t* fCMatrix.h (xgemm): Provide decl.\n\t(ssyrk): New F77 decl.\n\t* fCMatrix.cc (xgemm): New function.\n\t(operator * (const FloatComplexMatrix&, const\n\tFloatComplexMatrix&)): Simplify.\n\t(get_blas_trans_arg): New function.\n\n\t* dMatrix.cc, CMatrix.cc, Sparse-op-defs.h: Add missing copyright.\n\n\t* Sparse-op-defs.h (SPARSE_FULL_MUL): Simplify scalar*matrix case.\n\tCorrect indenting.\n\t(SPARSE_FULL_TRANS_MUL): New macro.\n\t(FULL_SPARSE_MUL): Simplify scalar*matrix case. Correct indenting.\n\tMove OCTAVE_QUIT one level up.\n\t(FULL_SPARSE_MUL_TRANS): New macro.\n\t* dSparse.h (mul_trans, trans_mul): Provide decl.\n\t* dSparse.cc (mul_trans, trans_mul): New functions.\n\t* CSparse.h (mul_trans, trans_mul, mul_herm, herm_mul): Provide decl.\n\t* CSparse.cc (mul_trans, trans_mul, mul_herm, herm_mul): New functions.\n\n\t* dMatrix.h (xgemm): Provide decl.\n\t* dMatrix.cc (xgemm): New function.\n\t(operator * (const Matrix&, const Matrix&)): Simplify.\n\t(get_blas_trans_arg): New function.\n\t* CMatrix.h (xgemm): Provide decl.\n\t* CMatrix.cc (xgemm): New function.\n\t(operator * (const ComplexMatrix&, const ComplexMatrix&)): Simplify.\n\t(get_blas_trans_arg): New function.\n\n\t* MatrixType.cc (matrix_real_probe, matrix_complex_probe):\n\tNew template functions.\n\t(MatrixType::MatrixType (const Matrix&),\n\tMatrixType::MatrixType (const FloatMatrix&)):\n\tjust call matrix_real_probe.\n\t(MatrixType::MatrixType (const ComplexMatrix&),\n\tMatrixType::MatrixType (const FloatComplexMatrix&)):\n\tjust call matrix_complex_probe.\n\n\t* MatrixType.cc (MatrixType::MatrixType (matrix_type, bool)):\n\tadd missing test for Unknown.\n\n2008-05-21  David Bateman  <dbateman@free.fr>\n\n\t* fCMatrix.cc (float rcond): Replace with float rcon everywhere\n\tto avoid shadowed variable warning\n\t(float ComplexMatrix::rcond (void) const): New method for\n\treciprocal condition number calculation.\n\t(float ComplexMatrix::rcond (MatrixType &mattype) const): ditto.\n\t* fCMatrix.h (float rcond):  Replace with float rcon everywhere\n\tto avoid shadowed variable warning\n\t(float ComplexMatrix::rcond (void) const): New method for\n\treciprocal condition number calculation.\n\t(float ComplexMatrix::rcond (MatrixType &mattype) const): ditto.\n\t* fMatrix.cc (float rcond): Replace with float rcon everywhere\n\tto avoid shadowed variable warning\n\t(float Matrix::rcond (void) const): New method for\n\treciprocal condition number calculation.\n\t(float Matrix::rcond (MatrixType &mattype) const): ditto.\n\t* fMatrix.h (float rcond):  Replace with float rcon everywhere\n\tto avoid shadowed variable warning\n\t(float Matrix::rcond (void) const): New method for\n\treciprocal condition number calculation.\n\t(float Matrix::rcond (MatrixType &mattype) const): ditto.\n\n\t* Array.cc: Fix transpose tests.\n\n\t* CmplxGEBAL.cc (ComplexGEPBALANCE), dbleGEPBAL.cc (GEPBALANCE),\n\tfCmplxGEPBAL.cc (FloatComplexGEPBALANCE), floatGEPBAL.cc\n\t(FloatGEPBALANCE): New class for generalized eigenvalue balancing.\n\t* CmplxGEBAL.h (ComplexGEPBALANCE), dbleGEPBAL.h (GEPBALANCE),\n\tfCmplxGEPBAL.h (FloatComplexGEPBALANCE), floatGEPBAL.h\n\t(FloatGEPBALANCE): Declare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* floatAEPBAL.cc (FloatAEPBALANCE), fCmplxAEPBAL.cc\n\t(FloatComplexAEPBALANCE): New classes for single precision\n\tAlgebraic eignvalue balancing.\n\t* floatAEPBAL.h (FloatAEPBALANCE), fCmplxAEPBAL.h\n\t(FloatComplexAEPBALANCE): Declare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* floatHESS.cc (FloatHESS), fCmplxHESS.cc (FloatComplexHESS):  New\n\tclasses for single precision Hessenberg decomposition.\n\t* floatHESS.h (FloatHESS), fCmplxHESS.h (FloatComplexHESS):\n\tDeclare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* floatQR.cc (FloatQR), fCmplxQR.cc (FloatComplexQR):  New\n\tclasses for single precision QR decomposition.\n\t* floatQR.h (FloatQR), fCmplxQR.h (FloatComplexQR):\n\tDeclare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* floatQRP.cc (FloatQRP), fCmplxQRP.cc (FloatComplexQRP):  New\n\tclasses for single precision permuted QR decomposition.\n\t* floatQRP.h (FloatQRP), fCmplxQRP.h (FloatComplexQRP):\n\tDeclare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* mx-defs (FloatAEPBALANCE, FloatComplexAEPBALANCE,\n\tComplexGEPBALANCE, FloatGEPBALANCE,FloatComplexGEPBALANCE,\n\tFloatHESS, FloatComplexHESS, FloatQR, FloatComplexQR, QRP,\n\tComplexQRP, FloatQRP, FloatComplexQRP):\tDeclare classes.\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc (Array<T> Array<T>::transpose () const): Modify for tiled\n\ttranspose to limit the number of cache misses.\n\t(Array<T> Array<T>::hermitian (T (*)(const&)) const): New method\n\tfor matrix conjugate transpose.\n\t* Array.h (Array<T> hermitian (T (*)(const&)) const): Declare it.\n\n\t* DiagArray2.cc (DiagArray2<T> DiagArray2<T>::transpose () const):\n\tSpecialization for diagonal arrays.\n\t(DiagArray2<T> DiagArray2<T>::transpose (T (*) (const&)) const):\n\tDitto.\n\n\t* MArray.h (MArray<T> hermitian <T (*) (const&)) const): New method.\n\t(MArray<T> transpose () const): Ditto.\n\t* MArray2.h (MArray2<T> hermitian <T (*) (const&)) const): Ditto.\n\t* Array2.h (Array2<T> hermitian <T (*) (const&)) const): Ditto.\n\t* ArrayN.h (ArrayN<T> hermitian <T (*) (const&)) const): Ditto.\n\t* MDiagArray2.h (MDiagArray2<T> transpose () const): Ditto.\n\t(MDiagArray<T> hermitian <T (*) (const&)) const): Ditto.\n\n\t* CColVector.cc (transpose, hermitian): Define in terms of base class.\n\t* CRowVector.cc (transpose, hermitian): Ditto.\n\t* dColVector.cc (transpose): Ditto.\n\t* dRowVector.cc (transpose): Ditto.\n\t* CDiagMatrix.h (transpose, hermitian): Ditto.\n\t* dDiagMatrix.h (transpose): Ditto.\n\n\t* fCColVector.cc (transpose, hermitian): Define in terms of base class.\n\t* fCRowVector.cc (transpose, hermitian): Ditto.\n\t* fColVector.cc (transpose): Ditto.\n\t* fRowVector.cc (transpose): Ditto.\n\t* fCDiagMatrix.h (transpose, hermitian): Ditto.\n\t* fDiagMatrix.h (transpose): Ditto.\n\n\t* CDiagMatrix.cc (ComplexDiagMatrix::transpose,\n\tComplexDiagMatrix::hermitian): Delete.\n\t* dDiagMatrix.cc (DiagMatrix::transpose): Ditto.\n\t* CMatrix.cc (ComplexMatrix::hermitian): Ditto.\n\n\t* fCDiagMatrix.cc (FloatComplexDiagMatrix::transpose,\n\tFloatComplexDiagMatrix::hermitian): Delete.\n\t* fDiagMatrix.cc (FloatDiagMatrix::transpose): Ditto.\n\t* fCMatrix.cc (FloatComplexMatrix::hermitian): Ditto.\n\n\t* lo-mappers.cc (FloatComplex xlog2(const FloatComplex&), float\n\txlog2 (flot, int&), FloatComplex xlog2(const FloatComplex&, int&)):\n\tNew mapper functions for single precion values.\n\t* lo-mappers.h (FloatComplex xlog2(const FloatComplex&), float\n\txlog2 (flot, int&), FloatComplex xlog2(const FloatComplex&, int&)):\n\tDeclare them.\n\n\t* CmplxGEBAL.cc (ComplexGEPBALANCE), dbleGEPBAL.cc (GEPBALANCE),\n\tfCmplxGEPBAL.cc (FloatComplexGEPBALANCE), floatGEPBAL.cc\n\t(FloatGEPBALANCE): New class for generalized eigenvalue balancing.\n\t* CmplxGEBAL.h (ComplexGEPBALANCE), dbleGEPBAL.h (GEPBALANCE),\n\tfCmplxGEPBAL.h (FloatComplexGEPBALANCE), floatGEPBAL.h\n\t(FloatGEPBALANCE): Declare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* floatAEPBAL.cc (FloatAEPBALANCE), fCmplxAEPBAL.cc\n\t(FloatComplexAEPBALANCE): New classes for single precision\n\tAlgebraic eignvalue balancing.\n\t* floatAEPBAL.h (FloatAEPBALANCE), fCmplxAEPBAL.h\n\t(FloatComplexAEPBALANCE): Declare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* floatHESS.cc (FloatHESS), fCmplxHESS.cc (FloatComplexHESS):  New\n\tclasses for single precision Hessenberg decomposition.\n\t* floatHESS.h (FloatHESS), fCmplxHESS.h (FloatComplexHESS):\n\tDeclare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* floatQR.cc (FloatQR), fCmplxQR.cc (FloatComplexQR):  New\n\tclasses for single precision QR decomposition.\n\t* floatQR.h (FloatQR), fCmplxQR.h (FloatComplexQR):\n\tDeclare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* floatQRP.cc (FloatQRP), fCmplxQRP.cc (FloatComplexQRP):  New\n\tclasses for single precision permuted QR decomposition.\n\t* floatQRP.h (FloatQRP), fCmplxQRP.h (FloatComplexQRP):\n\tDeclare them.\n\t* Makefile.in (MATRIX_INC): Include them here.\n\t(MATRIX_SRC): and here.\n\n\t* mx-defs (FloatAEPBALANCE, FloatComplexAEPBALANCE,\n\tComplexGEPBALANCE, FloatGEPBALANCE,FloatComplexGEPBALANCE,\n\tFloatHESS, FloatComplexHESS, FloatQR, FloatComplexQR, QRP,\n\tComplexQRP, FloatQRP, FloatComplexQRP):\tDeclare classes.\n\n\t* Array-f.cc, Array-fC.cc, MArray-f.cc, MArray-fC.cc,\n\tfCColVector.cc, fCColVector.h, fCDiagMatrix.cc, fCDiagMatrix.h,\n\tfCMatrix.cc, fCMatrix.h, fCNDArray.cc, fCNDArray.h,\n\tfCRowVector.cc, fCRowVector.h, fCmplxCHOL.cc, fCmplxCHOL.h,\n\tfCmplxDET.cc, fCmplxDET.h, fCmplxLU.cc, fCmplxLU.h,\n\tfCmplxSCHUR.cc, fCmplxSCHUR.h, fCmplxSVD.cc, fCmplxSVD.h,\n\tfColVector.cc, fColVector.h, fDiagMatrix.cc, fDiagMatrix.h,\n\tfEIG.cc, fEIG.h, fMatrix.cc, fMatrix.h, fNDArray.cc, fNDArray.h,\n\tfRowVector.cc, fRowVector.h, floatCHOL.cc, floatCHOL.h,\n\tfloatDET.cc, floatDET.h, floatLU.cc, floatLU.h, floatSCHUR.cc,\n\tfloatSCHUR.h, floatSVD.cc, floatSVD.h: New files.\n\t* Makefile.in (MATRIC_INC, TI_SRC, MATRIX_SRC): Add them.\n\n\t* CMatrix.cc, CMatrix.h, CNDArray.cc, CNDArray.h, CmplxDET.cc,\n\tMArray-C.cc, MArray-d.cc, MArray-defs.h, MArray.cc, MArray.h,\n\tMatrixType.cc, MatrixType.h, SparseCmplxQR.cc, SparseCmplxQR.h,\n\tSparseQR.cc, SparseQR.h, dMatrix.cc, dMatrix.h, dNDArray.cc,\n\tdNDArray.h, data-conv.cc, data-conv.h, dbleDET.cc, dbleSVD.cc,\n\tlo-cieee.c, lo-ieee.cc, lo-ieee.h, lo-mappers.cc, lo-mappers.h,\n\tlo-specfun.cc, lo-specfun.h, lo-utils.cc, lo-utils.h, mx-base.h,\n\tmx-defs.h, mx-ext.h, mx-inlines.cc, mx-op-defs.h, mx-ops,\n\toct-cmplx.h, oct-fftw.cc, oct-fftw.h, oct-inttypes.h, vx-ops:\n\tAllow single precision types.\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* CMatrix.cc (double rcond): Replace with double rcon everywhere\n\tto avoid shadowed variable warning\n\t(double ComplexMatrix::rcond (void) const): New method for\n\treciprocal condition number calculation.\n\t(double ComplexMatrix::rcond (MatrixType &mattype) const): ditto.\n\t* CMatrix.h (double rcond):  Replace with double rcon everywhere\n\tto avoid shadowed variable warning\n\t(double ComplexMatrix::rcond (void) const): New method for\n\treciprocal condition number calculation.\n\t(double ComplexMatrix::rcond (MatrixType &mattype) const): ditto.\n\t* dMatrix.cc (double rcond): Replace with double rcon everywhere\n\tto avoid shadowed variable warning\n\t(double Matrix::rcond (void) const): New method for\n\treciprocal condition number calculation.\n\t(double Matrix::rcond (MatrixType &mattype) const): ditto.\n\t* dMatrix.h (double rcond):  Replace with double rcon everywhere\n\tto avoid shadowed variable warning\n\t(double Matrix::rcond (void) const): New method for\n\treciprocal condition number calculation.\n\t(double Matrix::rcond (MatrixType &mattype) const): ditto.\n\n\t* regex-match.cc, regex-match.h: New class for simple regular\n\texpression matching\n\t* Makefile.in (INCLUDES): Add regex-match.h here, and\n\t(LIBOCTAVE_CXX_SOURCES): regex-match.cc here.\n\n2008-05-19  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc: Replace some DGBCON with GPBCON where they are\n\tincorrectly used.\n\n2008-05-13  David Bateman  <dbateman@free.fr>\n\n\t* idx-vector.cc (IDX_VEC_REP::idx_vector_rep (const boolNDArray&)):\n\tIf len is zero size the index vector in the same manner as if len\n\tis not zero.\n\n2008-05-05  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-edit.cc (command_editor::re_read_init_file,\n\tgnu_readline::do_re_read_init_file): New functions.\n\t* cmd-edit.h (command_editor::re_read_init_file): Provide decl.\n\t(command_editor::do_re_read_init_file): New function.\n\t* oct-rl-edit.c (octave_rl_re_read_init_file): New function.\n\t* oct-rl-edit.h: Provide decl.\n\n2008-05-05  Rafael Laboissiere  <rafael@debian.org>\n\n\t* oct-rl-edit.c (octave_read_init_file): Simply call rl_read_init_file.\n\n2008-05-01  John W. Eaton  <jwe@octave.org>\n\n\t* oct-shlib.h (octave_shlib::number_of_functions_loaded):\n\tReturn size_t instead of int value.\n\t* oct-shlib.cc (octave_base_shlib::number_of_functions_loaded):\n\tLikewise.\n\t(octave_base_shlib::fcn_names): Now a std::map object.\n\tAdjust all uses.\n\t(octave_base_shlib::fcn_names_iterator,\n\toctave_base_shlib::fcn_names_const_iterator): New typedefs.\n\t(octave_base_shlib::add_to_fcn_names, octave_base_shlib::remove):\n\tPerform reference counting for functions accessed.\n\n2008-04-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-mappers.cc (xlog2 (double)): Compute log (2), not log2 (2).\n\t(xlog2 (Complex), xlog2 (double, int&), xlog2 (Complex, int&)):\n\tNew functions.\n\t* lo-mappers.h: Provide decls.\n\n2008-04-25  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* oct-lookup.h (seq_lookup): Do not use output value of fill_n (MSVC\n\tdoes not support it).\n\n2008-04-24  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* lo-sysdep.cc (octave_popen2): Don't set PIPE_NOWAIT for parentWrite.\n\n2008-04-21  John W. Eaton  <jwe@octave.org>\n\n\t* idx-vector.cc (IDX_VEC_REP::idx_vector_rep (const boolNDArray&)):\n\tFix for-loop condition.\n\n2008-04-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* CmplxCHOL.cc, CmplxQR.cc, dbleCHOL.cc, dbleQR.cc: Fix calls to error()\n\n2008-04-16  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.h (Sparse<T>& operator = (Sparse<T>&)): Move definition\n\tof the operator for here\n\t* Sparse.cc (Sparse<T>& Sparse<T>::operator = (Sparse<T>&)): To\n\there. Also delete idx.\n\t* Array.h (Array<T>& operator = (Array<T>&)): Move definition\n\tof the operator for here\n\t* Array.cc (Array<T>& Array<T>::operator = (Array<T>&)): To\n\there. Also delete idx.\n\n2008-04-09  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* lo-mappers.cc (xround): Avoid floating-point overflow when input\n\tvalue is equal to bitmax implementation taken from gnulib).\n\n\t* file-stat.cc (file_stat::update_internal): Do not strip trailing\n\tfile separator when path length is equal to 1 (handle case '\\') under\n\t__WIN32__ platforms.\n\n2008-04-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleQR.h, dbleQR.cc (QR::shift_cols): New method.\n\t* CmplxQR.h, CmplxQR.cc (ComplexQR::shift_cols): New method.\n\t* dbleCHOL.h, dbleCHOL.cc (CHOL::insert_sym, CHOL::delete_sym,\n\tCHOL::shift_sym): New methods.\n\t* CmplxCHOL.h, CmplxCHOL.cc (ComplexCHOL::insert_sym,\n\tComplexCHOL::delete_sym, ComplexCHOL::shift_sym): New methods.\n\n2008-04-03  John W. Eaton  <jwe@octave.org>\n\n\t* lo-sysdep.cc [__WIN32__ && ! __CYGWIN__]: Include windows.h.\n\n2008-03-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-lookup.h: New file.\n\n2008-03-26  David Bateman  <dbateman@feee.fr>\n\n\t* Array.cc (assignN): Additional fix for vector assignments.\n\n2008-03-25  David Bateman  <dbateman@feee.fr>\n\n\t* Array.cc (assignN): refactor calculation of new dimensions when\n\toriginal matrix is empty.\n\t* Array-util.cc (bool is_vector (const dim_vector&)): New\n\tfunction.\n\t* Array-util.h (bool is_vector (const dim_vector&)): declare it.\n\n2008-03-25  David Bateman  <dbateman@free.fr>\n\n\t* sparse-base-chol.h (sparse_base_chol_rep::~sparse_base_chol_rep\n\t(void)): Only free the factorization if it was created\n\t* spase-base-chol.cc (sparse_base_chol_rep::init): Don't attempt\n\tto factorize a matrix that has been flagged as not being positive\n\tdefinite.\n\n2008-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.cc (xtrunc): New function.\n\t* lo-mappers.h: Provide decl.\n\n2008-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* lo-specfun.cc (expm1, log1p): New functions.\n\t* lo-specfun.h: Provide decls.\n\n\t* lo-mappers.cc (xroundb): New function.\n\t* lo-mappers.h: Provide decl.\n\n2008-03-23  David Bateman  <dbateman@free.fr>\n\n\t* mx-ops: Definite binary operators for mixed integer array +\n\tarray case, except for 64bit cases.\n\n2008-03-21  David Bateman  <dbateman@free.fr>\n\n\t* oct-sparse.h: Add headers for amd.h.\n\n2008-03-20  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc (Array<T> Array<T>::diag (octave_idx_type) const): New\n\tmethod for diag function.\n\t* Array.h  (Array<T> diag (octave_idx_type) const): Declare it.\n\t* Array2.h (Array2<T> diag (octave_idx_type) const): New method.\n\t* MArray2.h (MArray2<T> diag (octave_idx_type) const): ditto.\n\t* ArrayN.h (ArrayN<T> diag (octave_idx_type) const): ditto.\n\t* MArrayN.h (MArrayN<T> diag (octave_idx_type) const): ditto.\n\n\t* Sparse.cc (Sparse<T> Sparse<T>::diag (octave_idx_type) const):\n\tNew method for the diag function.\n\t* Sparse.h  (Sparse<T> diag (octave_idx_type) const): Declare it.\n\t* MSparse.h (MSparse<T> diag (octave_idx_type) const): New method.\n\n\t* Range.cc (Matrix Range::diag (octave_idx_type) const):\n\tNew method for the diag function.\n\t* Range.h  (Matrix diag (octave_idx_type) const): Declare it.\n\n\t* CDiagMatrix.cc (ComplexColumnVector ComplexDiagMatrix::diag\n\t(void) const): delete.\n\t* dDiagMatrix.cc (ColumnVector DiagMatrix::diag (void) const): delete.\n\t* dDiagMatrix.h (ColumnVector diag (void) const): ditto.\n\t* CMatrix.cc (ComplexColumnVector ComplexMatrix::diag (void) const):\n\tdelete.\n\t* CMatrix.h (ComplexColumnVector diag (void) const): ditto.\n\t* dMatrix.cc (ColumnVector Matrix::diag (void) const): ditto.\n\t* dMatrix.h (ColumnVector diag (void) const): ditto.\n\t* boolMatrix.cc (boolMatrix boolMatrix::diag (void) const): ditto.\n\t* boolMatrix.h (boolMatrix diag (void) const): ditto.\n\t* chMatrix.cc (charMatrix charMatrix::diag (void) const): ditto.\n\t* chMatrix.h (charMatrix diag (void) const): ditto.\n\t* intNDArray.cc (intNDArray<T> intNDArray<T>::diag (void) const): ditto.\n\t* intNDArray.h (intNDArray<T> diag (void) const): ditto.\n\n\t* CMatrix.cc (ComplexMatrix ComplexMatrix::diag (octave_idx_type)\n\tconst): Rewrite in terms of template classes function.\n\t* CMatrix.h (ComplexMatrix diag (octave_idx_type)const ): Change\n\treturn type.\n\t* dMatrix.cc (Matrix Matrix::diag (octave_idx_type) const): Rewrite in\n\tterms of template classes function.\n\t* dMatrix.h (Matrix diag (octave_idx_type) const): Change return type.\n\t* boolMatrix.cc (boolMatrix boolMatrix::diag (octave_idx_type) const):\n\tRewrite in terms of template classes function.\n\t* boolMatrix.h (boolMatrix diag (octave_idx_type) const): Change\n\treturn type.\n\t* chMatrix.cc (charMatrix charMatrix::diag (octave_idx_type)\n\tconst): Rewrite in terms of template classes function.\n\n\t* dSparse.cc (SparseMatrix SparseMatrix::diag (octave_idx_type) const):\n\tRewrite in terms of template classes function.\n\t* CSparse.cc (SparseComplexMatrix SparseComplexMatrix::diag\n\t(octave_idx_type) const): ditto.\n\t* boolSparse.cc (SparseBoolMatrix SparseBoolMatrix::diag\n\t(octave_idx_type) const): ditto.\n\t* intNDArray.cc (intNDArray<T> intNDArray<T>::diag\n\t(octave_idx_type) const): ditto.\n\n\t* CNDArray.cc (ComplexNDArray ComplexNDArray::diag\n\t(octave_idx_type) const): New method.\n\t* CNDArray.h (ComplexNDArray diag (octave_idx_type) const):\n\tDeclare it.\n\t* dNDArray.cc (NDArray NDArray::diag (octave_idx_type) const): New\n\tmethod.\n\t* dNDArray.h (NDArray diag (octave_idx_type) const): Declare it.\n\t* chNDArray.cc (charNDArray charNDArray::diag\n\t(octave_idx_type) const): New method.\n\t* chNDArray.h (charNDArray diag (octave_idx_type) const):\n\tDeclare it.\n\n\n2008-03-19  John W. Eaton  <jwe@octave.org>\n\n\t* oct-env.cc (octave_env::do_base_pathname): Also handle rooted\n\trelative filenames.\n\n2008-03-19  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc (assignN): If orig_empty allow assignment like\n\ta(1:10,1)=1:10\n\n\t* Sparse.h (template <class U, class F> Sparse<U> map (F fcn)\n\tconst): New template function.\n\t* MSparse.h (template <class U, class F> MSparse<U> map (F fcn)\n\tconst): ditto.\n\t* dSparse.cc (SparseMatrix SparseMatrix::map (dmapper) const,\n\tSparseComplexMatrix SparseMatrix::map (cmapper) const,\n\tSparseBoolMatrix SparseMatrix::map (bmapper) const): Rewrite in\n\tterms of the new template functor.\n\t* CSparse.cc (SparseMatrix SparseComplexMatrix::map (dmapper) const,\n\tSparseComplexMatrix SparseComplexMatrix::map (cmapper) const,\n\tSparseBoolMatrix SparseComplexMatrix::map (bmapper) const): ditto.\n\n2008-03-18  David Bateman  <dbateman@free.fr>\n\n\t* lo-specfun.cc (Complex xlgamma (const Complex&)): New function.\n\t* lo-specfun.h (Complex xlgamma (const Complex&)): Declare it.\n\t* randpoison.c (xlgamma): Use lgamma if HAVE_LGAMMA is defined.\n\n\t* dNDArray.cc (NDArray::min, NDArraymax): chop trailing singletons.\n\t* CNDarray.cc (ComplexNDArray::min, CompelxNDArray::max): ditto.\n\t* intNDarray.cc (intNDArray<T>::min, intNDArray<T>::max): ditto.\n\n\t* Array.cc (Array<T>::index): Don't short_freeze on index with\n\tfewer dimensions than the array only if the last dimension is empty.\n\n2008-03-18  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (octave_int_fit_to_range):\n\tUse partial specialization for double values.\n\n2008-03-08  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (Sparse<T>::index, assign): Likewise.\n\t* Array.cc (Array<T>::index1, Array<T>::index2, Array<T>::indexN,\n\tassign2): Eliminate use of idx_vector::is_one_zero method.\n\t* idx-vector.cc, idx-vector.h\n\t(idx_vector::maybe_convert_one_zero_to_idx,\n\tIDX_VEC_REP::maybe_convert_one_zero_to_idx): Delete unused function.\n\t(IDX_VEC_REP::one_zero): Delete data member.\n\t(IDX_VEC_REP::is_colon_equiv): Delete one_zero check.\n\t(idx_vector::is_one_zero, IDX_VEC_REP::is_one_zero): Delete function.\n\n2008-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* idx-vector.cc (IDX_VEC_REP::idx_vector_rep (bool),\n\tIDX_VEC_REP::idx_vector_rep (const boolNDArray&)):\n\tSimply perform the equivalent of \"find\" on the bool argument here,\n\tset one_zero to 0 and orig_dims to size of resulting index vector.\n\t(IDX_VEC_REP::freeze): Don't call maybe_convert_one_zero_to_idx here.\n\n2008-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleQR.cc (QR::insert_col, QR::insert_row,\n\tQR::delete_col, QR::delete_row): Use 0-based indexing.\n\t* CmplxQR.cc (ComplexQR::insert_col, ComplexQR::insert_row,\n\tComplexQR::delete_col, ComplexQR::delete_row): Likewise.\n\n\t* dbleCHOL.cc: Small doc and declaration fixes.\n\t* CmplxHOL.cc: Small doc and declaration fixes.\n\t* CmplxQR.cc (ComplexQR::ComplexQR): Adjust code to match dbleQR.cc.\n\t* dbleQR.cc (QR::delete_row): Fix incorrect test.\n\t* CmplxQR.cc (ComplexQR::delete_row): Fix incorrect test.\n\n2008-03-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dbleCHOL.cc (CHOL::set, CHOL::update, CHOL::downdate):\n\tNew functions.\n\t* dbleCHOL.h: Provide decls.\n\t* CmplxCHOL.cc (ComplexCHOL::set, ComplexCHOL::update,\n\tComplexCHOL::downdate): New functions.\n\t* CmplxCHOL.h: Provide decls.\n\n\t* dbleQR.cc (QR::update, QR::insert_col, QR::delete_col,\n\tQR::insert_row, QR::delete_row): New methods.\n\t(QR::QR (const Matrix&, const MAtrix&)): New constructor.\n\t* dbleQR.h: Provide decls.\n\t* CmplxQR.cc (ComplexQR::update, ComplexQR::insert_col,\n\tComplexQR::delete_col, ComplexQR::insert_row,\n\tComplexQR::delete_row): New methods.\n\t(ComplexQR::ComplexQR (const ComplexMatrix&, const ComplexMAtrix&)):\n\tNew constructor.\n\t* CmplxQR.h: Provide decls.\n\n2008-03-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Array-C.cc, Sparse-C.cc: Include oct-sort.cc after definitions\n\tof < and > operators.\n\n2008-03-03  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (assign1, assign1): Take care of repeated index\n\tvalues. Adapt the test code to check for these cases.\n\n2008-03-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dMatrix.cc (Matrix::lssolve): Also avoid dgelsd lwork query bug\n\tin lssolve method that accepts column vector argument.  Correct\n\tcalculation of nlvl.\n\t* CMatrix.cc (ComplexMatrix::lssolve): Likewise, for zgelsd.\n\n2008-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* oct-rand.cc (class octave_rand): Make it a proper singleton class.\n\n2008-02-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-rand.cc (get_dist_id): Fix typo.\n\t(get_dist_id, octave_rand::distribution, octave_rand::scalar,\n\tfill_rand): Improve error messages.\n\n\t* oct-rand.cc (unknown_dist): New dist type.\n\t(uniform_dist, normal_dist, expon_dist, poisson_dist, gamma_dist):\n\tUse static const int instead of #define.\n\t(get_dist_id): Default retval is unknown_dist.\n\n\t* oct-rand.cc (rand_states): New static variable.\n\t(initialize_rand_states, get_dist_id, get_internal_state,\n\tset_internal_state, switch_to_generator, save_state): New functions.\n\t(octave_rand::state): New arg to specify distribution.\n\tSave state in rand_states instead of setting internal state.\n\tReturn named state.  Use set_internal_state to generate proper\n\tstate vector from user supplied state.  Save and restore current\n\tstate if specified and current distributions are different.\n\t(octave_rand::distribution (void)): Use switch rather than if/else.\n\t(octave_rand::distribution (const std::string&)): Likewise.\n\t(octave_rand::uniform_distribution,\n\toctave_rand::normal_distribution,\n\toctave_rand::exponential_distribution,\n\toctave_rand::poisson_distribution,\n\toctave_rand::gamma_distribution): Call switch_to_generator.\n\t(octave_rand::state, maybe_initialize): For new_generators, just\n\tcall initialize_rand_states if not already initialized.\n\t(octave_rand::scalar, fill_rand): Save state after generating value.\n\n\t* dMatrix.cc (Matrix::lssolve): Avoid another dgelsd lwork query bug.\n\t* CMatrix.cc (ComplexMatrix::lssolve): Likewise, for zgelsd\n\n2008-02-24  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (octave_int_helper): New class.  Provide\n\tspecializations for signed and unsigned types.\n\t(octave_int<T>::operator >>=, octave_int<T>::abs,\n\toctave_int<T>::signum): Use static functions from\n\toctave_int_helper class.\n\n\t* oct-inttypes.h, oct-inttypes.cc (OCTAVE_US_TYPE1_CMP_OP,\n\tOCTAVE_US_TYPE2_CMP_OP): Tag function declarations and definitions\n\twith \"template <>\".\n\n2008-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* CSparse.cc, SparseCmplxLU.cc, SparsedbleLU.cc, dSparse.cc,\n\tfile-ops.cc, oct-group.cc, oct-shlib.cc, sparse-base-chol.h,\n\tsparse-dmsolve.cc: Use 0 instead of NULL.\n\n2008-02-22  David Bateman  <dbateman@free.fr>\n\n\t* boolSparse.cc (SparseBoolMatrix SparseBoolMatrix::diag\n\t(octave_idx_type) const): New method.\n\t* boolSparse.h (SparseBoolMatrix SparseBoolMatrix::diag\n\t(octave_idx_type) const): Declare it.\n\n\t* base-lu.h (lu_type Y (void) const): New method to return\n\tfactorization of xGETRF directly.\n\t* sparse-base-lu.cc (template <class lu_type, class lu_elt_type,\n\tclass p_type, class p_elt_type> lu_type sparse_base_lu <lu_type,\n\tlu_elt_type, p_type, p_elt_type> :: Y (void) const): New method\n\tto simulate the retirn of xGETRF.\n\t* sparse-base-lu.h (template <class lu_type, class lu_elt_type,\n\tclass p_type, class p_elt_type> lu_type sparse_base_lu <lu_type,\n\tlu_elt_type, p_type, p_elt_type> :: Y (void) const): Declare it\n\t(SparseMatrix R (void) const): Method to return scaling factors.\n\t* SparsedbleLU.cc: Allow two element pivot thresholding and\n\tscaling.\n\t* SparseCmplxLU.cc: ditto.\n\t* SparsedbleLU.h: Modify constructors to allow passing of two\n\telement pivoting thresholds and flag for scaling\n\t* SparseCmplxLU.h: ditto.\n\n\t* base-lu.cc (ColumnVector P_vec (void) const): New method to\n\treturn permutations as a vector.\n\t* base-lu.h (ColumnVector P_vec (void) const): Declare it.\n\t* sparse-base-lu.cc (ColumnVector Pr_vec (void) const): New method\n\treturn row permutations as a vector.\n\t(ColumnVector Pc_vec (void) const): New method return column\n\tpermutations as a vector.\n\t* sparse-base-lu.h (ColumnVector Pr_vec (void) const): Declare it.\n\t(ColumnVector Pc_vec (void) const): Declare it.\n\n\t* oct-spparms.cc: Add sym_tol field.\n\n2008-02-20  David Bateman  <dbateman@free.fr>\n\n\t* SparseComplexQR.cc (ComplexMatrix\n\tSparseComplexQR::SparseComplexQR_rep::Q\n\t(void) const): New method.\n\t* SparseComplexQR.h (ComplexMatrix\n\tSparseComplexQR::SparseComplexQR_rep::Q\n\t(void) const): Declare it.\n\t* SparseQR.cc (Matrix SparseQR::SparseQR_rep::Q\t(void) const): ditto.\n\t* SparseQR.h (Matrix SparseQR::SparseQR_rep::Q\t(void) const): ditto.\n\n2008-02-20  John W. Eaton  <jwe@octave.org>\n\n\t* boolNDArray.h (boolNDArray (const Array2<bool>&)): Delete.\n\n\t* Marray2.h (MArray2 (const Array2<U>&),\n\tMArray2 (const MArray2<U>&)): New templated constructors.\n\n\t* Array2.h (Array2 (const Array<U>&),\n\tArray2 (const Array<U>&, const dim_vector&)):\n\tNew templated constructors.\n\n\t* CColVector.cc (ComplexColumnVector::map): Forward to MArray::map.\n\t* dColVector.cc (ColumnVector::map): ditto.\n\t* CRowVector.cc (ComplexRowVector::map): ditto.\n\t* dRowVector.cc (RowVector::map): ditto.\n\t* CMatrix.cc (ComplexMatrix::map): Forward to MArray2::map.\n\t* dMatrix.cc (Matrix::map): ditto.\n\n\t* dNDArray.cc (NDArray::map): New functions.\n\t* dNDArray.h: Provide decls.\n\n\t* CNDArray.cc (ComplexNDArray::map): New functions.\n\t* CNDArray.h: Provide decls.\n\n\t* MArray2.h (MArray2<T>::map): New function.\n\t* Array2.h (Array2<T>::map): New function.\n\t* MArrayN.h (MArrayN<T>::map): New function.\n\t* ArrayN.h (ArrayN<T>::map): New function.\n\t* Array.h (Array<T>::map): New function.\n\n\t* functor.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\n2008-02-20  David Bateman  <dbateman@free.fr>\n\n\t* CColVector.h, CColVector.cc (ComplexColumnVector::apply): Remove.\n\t* dColVector.h, dColVector.cc (ColumnVector::apply): ditto.\n\t* CRowVector.h, CRowVector.cc (ComplexRowVector::apply): ditto.\n\t* dRowVector.h, dRowVector.cc (RowVector::apply): ditto.\n\t* CMatrix.h, CMatrix.cc (ComplexMatrix::apply): ditto.\n\t* dMatrix.h, dMatrix.cc (Matrix::apply): ditto.\n\n\t* CSparse.cc (apply): Remove.\n\t(map): Replace old mapper code with code taken from ov-mapepr.cc\n\t* CSparse.h (map): Reeclare them.\n\t(dmapper, cmapper, bmapper): typedefs for mapper functions.\n\t* dSparse.cc (apply): Remove.\n\t(map): Replace old mapper code with code taken from ov-mapepr.cc\n\t* dSparse.h (map): Reeclare them.\n\t(dmapper, cmapper, bmapper): typedefs for mapper functions.\n\n\t* intNDArray.cc (abs, signum): Two new mapper functions.\n\t* intNDArray.h (abs, signum): Declare them.\n\t* oct-inttypes.h (abs, signum): Mapper functions on scalar integer\n\tbase type.\n\n2008-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.cc (Matrix::lssolve): Check n > mnthr, not n > m when\n\tdeciding whether to calculate workspace size, with mnthr from ILAENV.\n\t* CMatrix.cc (ComplexMatrix::lssolve): Likewise.\n\n2008-02-14  John W. Eaton  <jwe@octave.org>\n\n\t* CColVector.cc, CMatrix.cc, CRowVector.cc, CSparse.cc,\n\tCmplxAEPBAL.cc, CmplxCHOL.cc, CmplxHESS.cc, CmplxLU.cc,\n\tCmplxQR.cc, CmplxQRP.cc, CmplxSCHUR.cc, CmplxSVD.cc, DASPK.cc,\n\tDASRT.cc, DASSL.cc, EIG.cc, LSODE.cc, NLEqn.cc, Quad.cc,\n\tdColVector.cc, dMatrix.cc, dRowVector.cc, dSparse.cc,\n\tdbleAEPBAL.cc, dbleCHOL.cc, dbleHESS.cc, dbleLU.cc, dbleQR.cc,\n\tdbleQRP.cc, dbleSCHUR.cc, dbleSVD.cc:\n\tDon't check f77_exception_encountered.\n\n2008-02-12  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc: Declare xilaenv instead of ilaenv.\n\t(ComplexMatrix::lssolve): Call xilaenv instead of ilaenv.\n\n2008-02-12  Jason Riedy  <ejr@cs.berkeley.edu>\n\n\t* Array.cc (ascending_compare, descending_compare): Remove\n\tnon-standard extern in the instantiations.\n\n\t* oct-sort.cc: Include <cstring> and sprinkle with std:: as needed.\n\n\t* dMatrix.cc (ILAENV): Declare LAPACK Fortran function.\n\t(Matrix::lssolve): Use ILAENV to query smlsiz.  And add an ugly\n\tworkaround for DGELSD's broken lwork query.  The formula is from\n\tLAPACK's dgelsd.f source and allocates enough workspace to use an\n\tefficient algorithm in the short-and-fat case (n > m).\n\t* CMatrix.cc (ILAENV): Declare LAPACK Fortran function.\n\t(ComplexMatrix::lssolve): Use ILAENV to query smlsiz.  And add an\n\tugly workaround for DGELSD's broken lwork query, as with double.\n\n2008-02-12  John W. Eaton  <jwe@octave.org>\n\n\t* sparse-sort.cc: Don't explicitly instantiate\n\tclass octave_sort<octave_idx_vector_sort *>,\n\tclass octave_sort<octave_idx_type>, or\n\tclass octave_sort<octave_sparse_sort_idxl *>.\n\n\t* Sparse.h (INSTANTIATE_SPARSE_SORT): Delete macro.\n\t* Sparse-C.cc, Sparse-b.cc, Sparse-d.cc: Don't use it.\n\n\t* Range.cc (Range::sort_internal): Avoid shadow warning from gcc.\n\n2008-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in ($(MAKEDEPS)): Skip dependencies if omit_deps is defined.\n\n2008-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sort.h (enum sortmode): Eliminate UNDEFINED.  Change all\n\tuses of UNDEFINED to ASCENDING.\n\n2008-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* Range.cc (Range::sort_internal): Rename from sort.  New arg,\n\tASCENDING, with default value of true.\n\t(Range::sort_internal (Array<octave_idx_type>&, bool)): New function.\n\t(Range::sort (octave_idx_type, sortmode) const): New function.\n\t(Range::sort (Array<octave_idx_type>&, octave_idx_type, sortmode)\n\tconst): New function.\n\t* Range.h: Fix/provide decls.\n\n\t* intNDArray.cc (intNDArray<T>::any (int)): Use != for comparison.\n\n2008-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in ($(OPTS_INC)): Use mv instead of move-if-change.\n\t(stamp-prereq): Eliminate.\n\t(clean): Don't remove stamp-prereq.\n\t(libraries): Don't depend on stamp-prereq.\n\t(PREREQ): New macro.\n\t($(MAKEDEPS)): Depend on $(PREREQ), not stamp-prereq.\n\t(distclean): Simplify with $(PREREQ).\n\t(OPT_BASE): New macro.\n\t(OPT_IN): Rename from OPTS_INC_DATA.  Define in terms of OPT_BASE.\n\t(OPT_INC): Rename from OPTS_INC.  Define in terms of OPT_BASE.\n\n2008-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in: Unconditionally include $(MAKEDEPS).\n\tMark $(MAKEDEPS) as .PHONY targets if omit_deps is true.\n\n2008-02-03  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Array.cc (ascending_compare, descending_compare,\n\tArray<T>::sort): Declare explicit specialization for T=double to\n\tavoid symbol duplication error at link time.\n\t* Array-d.cc (ascending_compare, descending_compare): Declare and\n\tdefine as nonmember functions, not member functions of Array<T>.\n\n2008-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* Array-i.cc: Also instantiate Arrays for long long type if it exists.\n\n2008-02-03  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Array.cc: Don't include Range.h.\n\n2008-01-31  David Bateman  <dbateman@free.fr>\n\n\t* oct-sort.cc: conversion of int to octave_idx_type where needed\n\tfor 64-bit builds.\n\t(IFLT): Allow IFLT macro to be overridden.\n\t* oct-sort.h: conversion of int to octave_idx_type where needed\n\tfor 64-bit builds.\n\t(enum sortmode): Type of sort to perform.\n\t(vec_index): Simple class to aid in indexed sorts.\n\n\t* Array.h ( Array<T> sort (octave_idx_type, sortmode) const,\n\tArray<T> sort (Array<octave_idx_type> &, octave_idx_type,\n\tsortmode) const): Array sorting methods.\n\t(INSTANTIATE_ARRAY_SORT, NO_INSTANTIATE_ARRAY_SORT): Macros to\n\tinstantiate the array sorting methods.\n\t* Array.cc (ascending_compare, descending_compare): New template\n\tfunctions for generic sort comparison.\n  \t( Array<T> Array<T>::sort (octave_idx_type, sortmode) const,\n\tArray<T> Array<T>::sort (Array<octave_idx_type> &, octave_idx_type,\n\tsortmode) const): Array sorting functions based of octave_sort\n\tclass.\n\t* Array-C.cc: Instantiate the complex array sort methods.\n\t(IFLT): New macro to override the one in the\n\toctave_sort class to avoid need for Complex < and > operators.\n\t(static double xabs (const Complex&)): Complex abs function\n\tavoiding std::abs(Inf) returning NaN with some compilers.\n\t(ascending_compare, descending compare): override template\n\tfunctions for complex comparison.\n\t* Array-d.cc: Instantiate the double array sort methods.\n\t(Array<double> Array<double>::sort (octave_idx_type,\n\tsortmode) const, Array<double> Array<double>::sort\n\t(Array<octave_idx_type> &, octave_idx_type, sortmode) const):\n\tArray sorting functions based of octave_sort using uint64 sorting\n\ton IEE754 doubles, for speed and correct sorting of Inf and NaN.\n\t(ascending_compare, descending compare): override template\n\tfunctions for double and uint64 comparison.\n\t* Array-b.cc, Array-ch.cc, Array-i.cc, Array-s.cc, Array-str.cc:\n\tInstantiate the array sort methods.\n\t* Array-idx-vec.cc: Null instantiation of array sort methods.\n\t* Array2.h, Array3.h, ArrayN.h (sort): 2, 3 and N-dimensional\n\tversions of the sort methods based on Array<T>::sort.\n\n\t* CSparse.cc, dSparse.cc: Remove inclusion of octa-sort.h.\n\t* Sparse.h ( Sparse<T> sort (octave_idx_type, sortmode) const,\n\tSparse<T> sort (Array<octave_idx_type> &, octave_idx_type,\n\tsortmode) const): Sparse sorting methods.\n\t(INSTANTIATE_ARRAY_SORT): Macro to instantiate the sparse sorting\n\tmethods.\n\t* Sparse.cc: replace sort with lsort throughout to avoid shadowing\n\tof new sort method.\n\t(sparse_ascending_compare, sparse_descending_compare): New template\n\tfunctions for generic sort comparison.\n  \t( Sparse<T> Sparse<T>::sort (octave_idx_type, sortmode) const,\n\tSparse<T> Sparse<T>::sort (Sparse<octave_idx_type> &, octave_idx_type,\n\tsortmode) const): Sparse sorting functions based of octave_sort\n\tclass.\n\t* Sparse-C.cc: Instantiate the complex sparse sort methods.\n\t(IFLT): New macro to override the one in the\n\toctave_sort class to avoid need for Complex < and > operators.\n\t(static double xabs (const Complex&)): Complex abs function\n\tavoiding std::abs(Inf) returning NaN with some compilers.\n\t(sparse_ascending_compare, sparse_descending compare): override\n\ttemplate functions for complex comparison.\n\t* Sparse-d.cc: Instantiate the cdouble sparse sort methods.\n\t(sparse_ascending_compare, sparse_descending compare): override\n\ttemplate functions for double comparison.\n\t* Array-b.cc: Instantiate the sparse sort methods.\n\n2008-01-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* idx-vector.h (idx_vector::idx_vector_rep::range_base,\n\tidx_vector::idx_vector_rep::range_step,\n\tidx_vector::idx_vector_rep::range_step): New data members.\n\t(idx_vector::idx_vector_rep::idx_vector_rep): Initialize them.\n\t* idx-vector.cc (IDX_VEC_REP::sort, IDX_VEC_REP::is_colon_equiv,\n\tIDX_VEC_REP::init_state, IDX_VEC_REP::operator =,\n\tIDX_VECTOR_REP::idx_vector_rep): Handle range.\n\n2008-01-18  Marco Caliari  <marco.caliari@univr.it>\n\n\t* dMatrix.cc (Matrix::expm): Correctly perform reverse permutation.\n\t* CMatrix.cc (ComplexMatrix::expm): Likewise.\n\n2008-01-22  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* oct-time.cc (octave_base_tim::init): Validate pointer argument;\n\tthis fixes the \"localtime(-1)\" crash under Windows.\n\n2008-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.cc (solve_singularity_warning): New function.\n\t(Matrix::expm): Pass pointer to solve_singularity_warning to\n\tMatrix::solve method.  Exit early if Matrix::solve fails.\n\tLimit sqpow value to avoid overflowing scale factor.\n\t* CMatrix.cc (solve_singularity_warning): New function.\n\t(ComplexMatrix::expm): Pass pointer to solve_singularity_warning to\n\tComplexMatrix::solve method.  Exit early if ComplexMatrix::solve fails.\n\tLimit sqpow value to avoid overflowing scale factor.\n\tFrom Marco Caliari <marco.caliari@univr.it>.\n\n2008-01-10  Kim Hansen  <kimhanse@gmail.com>\n\n\t* Sparse.cc: New tests for slicing of sparse matrices.\n\n2008-01-07  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (SPARSE_ANY_ALL_OP_ROW_CODE): Don't break from\n\tloop if this test succeeds.\n\n2008-01-03  David Bateman  <dbateman@free.fr>\n\n\t* MSparse.cc (SPARSE_A2A2_OP): If first arg is scalar zero, then\n\tneed unary operator on remaining argument\n\t* Sparse-op-defs.h (SPARSE_SMSM_BIN_OP_1): ditto.\n\n2007-12-21  John W. Eaton  <jwe@octave.org>\n\n\tVersion 3.0.0 released.\n\n2007-12-18  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (template <class T> Sparse<T> Sparse<T>::index\n\t(idx_vector&, int) const): Fix case indexing of non zero scalar\n\tstored as a sparse matrix.\n\t(template <class T> Sparse<T> Sparse<T>::index (idx_vector&,\n\tidx_vector&, int) const): For the non permutated indexing case,\n\tfix link list calculation and use.\n\n2007-12-17  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::indexN): Correctly handle scalar indexed by\n\tN-d array.\n\n2007-12-17  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (SPARSE_ANY_ALL_OP_ROW_CODE): Use ridx for row\n\tindex.\n\n2007-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (Sparse<T>::index (idx_vector&, int) const):\n\tIf indexing scalar with empty matrix, return empty array with same\n\tsize as index.\n\n2007-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* NLEqn.h (NLEqn::fval): New data member.  Adjust constructors\n\tand assignment operator.\n\t(NLEqn::function_value): New function.\n\t* NLEqn.cc (NLEqn::solve): If solution is successful, compute\n\tfunction value.\n\n\t* file-ops.cc (file_ops::concat): New function.\n\t* file-ops.h: Provide decl.\n\n2007-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc (octave_base_tm::init): Only assign t->tm_zone if it\n\tis not 0.\n\n2007-12-07  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (SPARSE_SMS_CMP_OP, SPARSE_SMS_BOOL_OP,\n\tSPARSE_SSM_CMP_OP, SPARSE_SSM_BOOL_OP, SPARSE_SMSM_CMP_OP,\n\tSPARSE_SMSM_BOOL_OP, SPARSE_BASE_REDUCTION_OP): Use sparse\n\tindexing where possible rather than the elem method.\n\t(SPARSE_REDUCTION_OP_ROW_EXPR, SPARSE_REDUCTION_OP_COL_EXPR,\n\tSPARSE_ANY_ALL_OP_ROW_CODE, SPARSE_ANY_ALL_OP_COL_CODE):\n\tReplace for new version of SPARSE_BASE_REDUCTION_OP.\n\t(SPARSE_ALL_OP): Specialize the initial value, and only treat dim\n\t= 0 directly.\n\t* CSparse.cc (SparseComplexMatrix SparseComplexMatrix::sumsq (int)\n\tconst): Replace ROW_EXPR and COL_EXPR functions for new version of\n\tSPARSE_BASE_REDUCTION_OP.\n\t(SparseComplexMatrix SparseComplexMatrix::prod (int) const):\n\tSpecialize the initial value, and only treat dim = 0 directly.\n\t* dSparse.cc (SparseMatrix SparseMatrix::sumsq (int) const):\n\tditto.\n\t(SparseMatrix SparseMatrix::prod (int) const): ditto.\n\n2007-12-06  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc (ComplexMatrix::expm): Update pointers to internal\n\tdata for npp and dpp after assignments.\n\t* dMatrix.cc (Matrix::expm): Use same method as ComplexMatrix::expm.\n\n2007-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (assign (Sparse<LT>&,  const Sparse<RT>&)):\n\tDo nothing if one index is empty.\n\n2007-12-04  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (assign (Sparse<LT>&,  const Sparse<RT>&)):\n\tResize matrix as well if one dimension of lhs is zero and the rhs\n\tindex exceeds the lhs index.\n\t* Sparse.cc (assign1 (Sparse<LT>&,  const Sparse<RT>&)):\n\tDon't resize to a smaller matrix for empty matrices with a max rhs\n\tindex smaller than the non zero lhs index.\n\n2007-12-04  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Array-util.h: Tag permute_vector_compare with OCTAVE_API.\n\n2007-12-03  Moritz Borgmann  <octave@moriborg.de>\n\n\t* Array-util.cc (permute_vector_compare): Move here from Array.cc.\n\t* Array-util.h (permute_vector, permute_vector_compare): Provide decls.\n\t* Array.cc (permute_vector, permute_vector_compare): Delete.\n\n2007-12-03  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (template <class LT, class RT> int assign\n\t(Sparse<LT>&,  const Sparse<RT>&)): Only set return matrix size to\n\trhs values if both no. rows and columns are zero.\n\n2007-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sort.cc, oct-sort.h: Style fixes.\n\n\t* lo-math.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\t* Array2.h, ArrayN.h, CmplxDET.cc, DASPK.cc, DASPK.h, DASRT.cc,\n\tDASRT.h, DASSL.cc, DASSL.h, LSODE.cc, LSODE.h, NLEqn.h, Quad.h,\n\tRange.cc, dbleDET.cc, lo-cieee.c, lo-ieee.cc, lo-mappers.cc,\n\toct-time.cc, oct-time.h, randgamma.c, randmtzig.c,\n\trandpoisson.c: Include lo-math.h instead of cmath or math.h.\n\t* lo-mappers.h: Don't include sunmath.h here.\n\n2007-11-26  John W. Eaton  <jwe@octave.org>\n\n\t* idx-vector.h (idx_vector::idx_vector_rep (const intNDArray<U>&)):\n\tEliminate unnecessary second arg from call to tree_to_mat_idx.\n\n\t* oct-inttypes.h (operator bool, operator char): Delete.\n\t(bool_value, char_value, double_value, float_value): New functions.\n\n2007-11-26  David Bateman  <dbateman@free.fr>\n\n\t* intNDArray.cc (template <class T> intNDArray<T>\n\tintNDArray<T>::max (int) const, template <class T> intNDArray<T>\n\tintNDArray<T>::max (ArrayN<octave_idx_type>&, int) const,\n\ttemplate <class T> intNDArray<T> intNDArray<T>::min (int) const,\n\ttemplate <class T> intNDArray<T> intNDArray<T>::min\n\t(ArrayN<octave_idx_type>&, int) const): New methods for integer\n\tclasses.\n\t* intNDArray.h (class intNDArray): Add min/max methods\n\t* mx-op-defs.h (MIXMAX_DECLS, MINMAX_FCNS, SND_MINMAX_FCN,\n\tNDS_MINMAX_FCN, NDND_MINMAX_FCN): New macro for instantiation of\n\tmin/max functions.\n\t* int8NDArray.h, int16NDArray.h, int32NDArray.h, int64NDArray.h,\n\tuint8NDArray.h, uint16NDArray.h, uint32NDArray.h, uint64NDArray.h\n\t(MINMAX_DECLS(T)): Declare the min/max functions for integer\n\ttypes.\n\t* int8NDArray.cc, int16NDArray.cc, int32NDArray.cc, int64NDArray.cc,\n\tuint8NDArray.cc, uint16NDArray.cc, uint32NDArray.cc, uint64NDArray.cc\n\t(MINMAX_FCNS(T)): Instantiate the min/max functions for integer\n\ttypes.\n\n\t* Arrayc.cc (Array<T>::index (idx_vector&, idx_vector&, int,\n\tconst T& rfv) const): If ndims != 2 call ND version of index.\n\n2007-11-14  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (opeator T (void) const): New conversion operator.\n\n\t* lo-specfun.cc (zbesi): When alpha is negative, don't limit\n\tcorrection to half-integer values.  From Eric Chassande-Mottin\n\t<echassandemottin@gmail.com>.\n\n2007-11-07  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* dMatrix.cc, CMatrix.cc: Help MSVC compiler to resolve\n\tambiguities related to math functions (in C++ mode).\n\n2007-11-06  David Bateman  <dbateman@free.fr>\n\n\t* intNDArray.cc (intNDArray<T> intNDArray<T>::sum (int) const):\n\tNew method.\n\t* intNDarray.h (intNDArray sum (int) const): Declare it.\n\t* boolNDArray.cc (boolNDArray boolNDArray::sum (int) const):\n\tNew method.\n\t* boolNDarray.cc (boolNDArray sum (int) const): Declare it.\n\t* MArray-def.h (MARRAY_NORM_BODY): Scale frobenius norm by infinity\n\tnorm to avoid issues of over- and underflow.  From Rolf Fabian\n\t<Rolf.Fabian@gmx.de>.\n\n2007-10-30  David Bateman  <dbateman@free.fr>\n\n\t* DASRT-opts.in, LSODE-opts.in: Doc fixes for small book format.\n\n2007-10-30  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc (lssolve): Compute size of rwork and iwork arrays.\n\t* dMatrix.cc (lssolve): Compute size of iwork array.\n\n2007-10-29  David Bateman  <dbateman@free.fr>\n\n\t* CMatrix.h (lssolve (const Matrix&, octave_idx_type&,\n\toctave_idx_type&, double&) const, lssolve (const ComplexMatrix&,\n\toctave_idx_type&, octave_idx_type&, double&) const, lssolve\n\t(const ColumnVector&, octave_idx_type&, octave_idx_type&,\n\tdouble& rcond) const, lssolve (const ComplexColumnVector&,\n\toctave_idx_type&, octave_idx_type&, double& rcond) const): New\n\tdeclarations.\n\t* CMatrix.cc (lssolve (const Matrix&, octave_idx_type&,\n\toctave_idx_type&, double&) const, lssolve (const ComplexMatrix&,\n\toctave_idx_type&, octave_idx_type&, double&) const, lssolve\n\t(const ColumnVector&, octave_idx_type&, octave_idx_type&,\n\tdouble& rcond) const, lssolve (const ComplexColumnVector&,\n\toctave_idx_type&, octave_idx_type&, double& rcond) const): New\n\tmethods.\n\t(lssolve (const Matrix&, octave_idx_type&, octave_idx_type&,\n\tdouble&) const, lssolve (const ComplexMatrix&, octave_idx_type&,\n\toctave_idx_type&, double&) const): Also return rcond from the\n\tsingular values returned by XGELSD.\n\t* dMatrix.h (lssolve (const Matrix&, octave_idx_type&,\n\toctave_idx_type&, double&) const, lssolve (const ComplexMatrix&,\n\toctave_idx_type&, octave_idx_type&, double&) const, lssolve\n\t(const ColumnVector&, octave_idx_type&, octave_idx_type&,\n\tdouble& rcond) const, lssolve (const ComplexColumnVector&,\n\toctave_idx_type&, octave_idx_type&, double& rcond) const): New\n\tdeclarations.\n\t* dMatrix.cc (lssolve (const Matrix&, octave_idx_type&,\n\toctave_idx_type&, double&) const, lssolve (const ComplexMatrix&,\n\toctave_idx_type&, octave_idx_type&, double&) const, lssolve\n\t(const ColumnVector&, octave_idx_type&, octave_idx_type&,\n\tdouble& rcond) const, lssolve (const ComplexColumnVector&,\n\toctave_idx_type&, octave_idx_type&, double& rcond) const): New\n\tmethods.\n\t(lssolve (const Matrix&, octave_idx_type&, octave_idx_type&,\n\tdouble&) const, lssolve (const ComplexMatrix&, octave_idx_type&,\n\toctave_idx_type&, double&) const): Also return rcond from the\n\tsingular values returned by XGELSD.\n\n2007-10-26  David Bateman  <dbateman@free.fr>\n\n\t* dMatrix.cc (Matrix::lssolve): Use xGELSD for rank deficient\n\tmatrices to avoid reliability issues with xGELSY.\n\t* CMatrix.cc (ComplexMatrix::lssolve): Likewise.\n\n2007-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc (octave_gmtime::init, octave_localtime::init):\n\tCall unix_time on arg instead of relying on conversion operator.\n\n\t* oct-time.h (octave_time::double_value): New function.\n\t(octave_time::operator double () const): Delete.\n\t(octave_time::operator time_t () const): Delete.\n\n2007-10-24  John W. Eaton  <jwe@octave.org>\n\n\t* strptime.c: Also compile if OCTAVE_HAVE_BROKEN_STRPTIME is defined.\n\n2007-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* CRowVector.cc (operator * const ComplexRowVector&, const\n\tComplexColumnVector&)): Delete spurious code left from patch.\n\n2007-10-22  Kim Hansen  <kimhanse@gmail.com>\n\n\t* chMatrix.cc, lo-utils.cc, oct-env.cc, oct-uname.cc,\n\tsparse-sort.cc: Include <cstring>.\n\n2007-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sparse.h: Don't include metis.h.\n\n\t* dSparse.cc (SparseMatrix::fsolve): Delete special code for METIS.\n\t* CSparse.cc (SparseComplexMatrix::fsolve): Likewise.\n\t* sparse-base-chol.cc (sparse_base_chol<chol_type, chol_elt,\n\tp_type>::sparse_base_chol_rep::init): Likewise.\n\n2007-10-16  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.cc (Matrix::inverse): Only check rcond == 0 if the\n\tmatrix is hermitian or calc_cond is true.\n\t* CMatrix.cc (ComplexMatrix::inverse): Likewise.\n\n2007-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* Change copyright notices in all files that are part of Octave to\n\tGPLv3 or any later version.\n\n2007-10-11  Brian Gough  <bjg@network-theory.co.uk>\n\n\t* DASSL-opts.in, LSODE-opts.in: Spelling fixes.\n\n2007-10-10  Olli Saarela  <Olli.Saarela@kcl.fi>\n\n\t* DASPK-opts.in, DASRT-opts.in, DASSL-opts.in: Spelling fixes.\n\n2007-10-10  John W. Eaton  <jwe@octave.org>\n\n\t* LPsolve.h, LPsolve.cc: Delete.\n\t* Makefile.in: Remove them from the INCLUDES and\n\tLIBOCTAVE_CXX_SOURCES lists.\n\n2007-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc (octave_strptime::init): Initialize t.tm_mon to -1\n\tand t.tm_year to INT_MIN before call to oct_strptime.  Adjust\n\tvalues to zero after call if they remain unchanged.\n\n\t* dSparse.cc (SparseMatrix::all_elements_are_zero): New function.\n\t* dNDArray.cc (NDArray::all_elements_are_zero): New function.\n\n2007-10-09  David Bateman  <dbateman@free.fr>\n\n\t* oct-time.cc (octave_strptime::init): Only call mktime if mday is\n\tvalud and mon and year are also filled in.\n\n\t* Array2.h (Array2<T>::Array2(const dim_vector&),\n\tArray2<T>::Array(const dim_vector&, const T&)): Check that\n\tdim_vector is 2 dimensional.\n\n\t* Sparse.cc (Sparse<T> Sparse<T>::index (idx_vector&, idx_vector&,\n\tint)): Remove a for loop in the random indexing case at the\n\texpense of maintaining a set of linked lists of indices that point\n\tto the same column in the original matrix.\n\t(int assign (Sparse<LT>&, Sparse<RT>)): Take a const copy of lhs\n\tand use it on the RHS of expressions to avoid unnecessary calls to\n\tmake_unique.\n\n2007-10-08  David Bateman  <dbateman@free.fr>\n\n\t* oct-rl-edit. (typedef rl_quoting_fcn_ptr, rl_dequoting_fcn_ptr,\n\trl_char_is_quoted_fcn_ptr, rl_command_fcn_ptr): New  typedefs\n\tfor readline compatible functions.\n\t(octave_rl_redisplay): Redisplay the current line of text.\n\t(octave_rl_newline):  Change interface to the same\n\tas used by the equivalent readline function itself.\n\t(octave_rl_filename_quoting_desired,\n\toctave_rl_set_filename_quote_characters,\n\toctave_rl_set_completer_quote_characters,\n\toctave_rl_qet_quoting_function, octave_rl_qet_dequoting_function,\n\toctave_rl_set_char_is_quoted_function): New functions to control\n\treadline filename quoting and line acceptace.\n\t* oct-rl-edit.c (octave_rl_newline): Change interface to the same\n\tas used by the equivalent readline function itself.\n\t(octave_rl_redisplay): Redisplay the current line of text.\n\t(octave_rl_filename_quoting_desired,\n\toctave_rl_set_filename_quote_characters,\n\toctave_rl_set_completer_quote_characters,\n\toctave_rl_qet_quoting_function, octave_rl_qet_dequoting_function,\n\toctave_rl_set_char_is_quoted_function): New functions to control\n\treadline filename quoting and line acceptace.\n\t* cmd-edit.h (typedef quoting_fcn, typedef dequoting_fcn,\n\ttypedef char_is_quoted_fcn, user_accept_line_fcn): New typedefs\n\tto map C++ function to readline compatible functions.\n\t(set_filename_quote_characters): New function to set the\n\tcharacters to if they appear in a filename that force the filename\n\tto be quoted.\n\t(set_completer_quote_characters): The characters that the readline\n\tcompletion function considers as quotation characters.\n\t(set_quoting_function, set_dequoting_function,\n\tset_char_is_quoted_function, set_user_accept_line_function):\n\tFunctions to set the Octave functions to perform quoting and the\n\tacceptance of a line of text by readline.\n\t(get_quoting_function, get_dequoting_function,\n\tget_char_is_quoted_function, get_user_accept_line_function):\n\tFunctions to get the above functions.\n\t(accept_line): New method for the command_editor to accept a line\n\tof text.\n\t(file_quoting_desired): Function to set whether readline should\n\tattempt to quote filenames.\n\t(do_set_filename_quoting_characters,\n\tdo_set_completer_quote_characters, do_set_quoting_function,\n\tdo_set_dequoting_function, do_set_char_is_quoted_function,\n\tdo_set_user_accept_line_function, do_get_quoting_function,\n\tdo_get_dequoting_function, do_get_char_is_quoted_function,\n\tdo_get_user_accept_line_function, do_filename_quoting_desired):\n\tVirtual functions to control the behavior of readline quoting and\n\tacceptance of lines.\n\t(do_accept_line): Virtual function for the accept line function.\n\t* cmd-edit.cc (class gnu_readline do_set_filename_quote_characters,\n\tdo_completer_quote_characters, do_set_quoting_function,\n\tdo_set_dequoting_function, do_set_char_is_quoted_function,\n\tdo_set_user_accept_line_function, do_get_quoting_function,\n\tdo_get_dequoting_function, do_get_user_accept_line_function,\n\tdo_accept_line, do_filename_quoting_desired, command_quoter,\n\tcommand_dequoter, command_char_is_quoted, command_accept_line):\n\tNew functions in gnu_readline class to control filename quoting\n\tand line acceptance.\n\t(quoting_function, dequoting_function, char_is_quoted_function,\n\tuser_accept_line_function): private variable to store functions\n\tsupplied for readline quoting and line acceptance.\n\t(gnu_readline::gnu_readline): Also set the new function pointers\n\tto zero.\n\t(gnu_readline::do_newline): Adapt to new octave_rl_newline\n\tinterface.\n\t(gnu_readeline::operate_and_get_next): Use new accept_line\n\tfunction rather than newline.\n\t(default_ommand_editor::do_accept_line): New method.\n\t(class command_editor set_filename_quote_characters,\n\tset_completer_quote_characters, set_quoting_function,\n\tset_dequoting_function, set_char_is_quoted_function,\n\tset_user_accept_line_function, get_quoting_function,\n\tget_dequoting_function, get_user_accept_line_function,\n\taccept_line, filename_quoting_desired): New functions checking\n\tinstance before calling virtual function.\n\n\t* CMatrix.h, dMatrix.h, boolMatrix.h, chMatrix.h, MArray2.h,\n\tArray2.h: Add dim_vector constructors.\n\t* charNDArray.h (charNDArray (const dim_vector&)): Add missing\n\tconst to dim_vector constructors.\n\t* boolMatrix.cc, chMatrix.cc, intNDArray.cc (diag (void), diag\n\t(octave_idx_type)): New methods to constructor diagonal matrices.\n\t* boolMatrix.h, chMatrix.h, intNDArray.h (diag (void), diag\n\t(octave_idx_type)): Declare them.\n\n2007-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* lo-specfun.cc: (zlgamma): Delete.\n\t(xgamma): Use C library gamma function if available.\n\t(xlgamma): Use C library lgamma function if available.\n\t(xlgamma) [! HAVE_LGAMMA]: Allow calculation for any value of X\n\tother than NaN or Inf.\n\n2007-10-05  John W. Eaton  <jwe@octave.org>\n\n\t* lo-specfun.cc (zlgamma): New function.\n\n2007-10-04  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sort.cc (octave_sort<T>::binarysort): Remove register\n\tqualifiers on local variables.\n\n2007-10-04  Marco Caliari  <mcaliari@math.unipd.it>\n\n\t* CMatrix.cc (ComplexMatrix::expm): Limit shift to values less\n\tthan log(realmax) to avoid issues with NaN.\n\n2007-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc (octave_strptime::init): Call mktime to propertly\n\tinitialize wday and yday.\n\tFrom Matthias Drochner <m.drochner@fz-juelich.de>.\n\n\t* cmd-edit.cc (command_editor::do_decode_prompt_string): Don't\n\tinsert extra '\\001' when decoding \\[ and \\].\n\n2007-09-26  David Bateman  <dbateman@free.fr>\n\n\t* dMatrix.cc (lssolve): Replace the use of xGELSS with xGELSY with\n\tis much faster and no less accurate.\n\t* CMatrix.cc (lssolve): ditto.\n\n2007-09-25  David Bateman  <dbateman@free.fr>\n\n\t* dMatrix.cc (utsolve, ltsolve, fsolve, lssolve): Allow\n\tzero dimensioned matrices.\n\t* CMatrix.cc (utsolve, ltsolve, fsolve, lssolve): ditto.\n\t* dSparse.cc (dsolve, utsolve, ltsolve, bsolve, trisolve, fsolve):\n\tditto.\n\t* CSparse.cc (dsolve, utsolve, ltsolve, bsolve, trisolve, fsolve):\n\tditto.\n\t* SparseQR.cc (SparseQR::SparseQR_rep::C, qrsolve): ditto.\n\t* SparseCmplxQR.cc (SparseComplexQR::SparseComplexQR_rep::C,\n\tqrsolve): ditto.\n\t* sparse-dmsolve.cc (dmsolve): ditto.\n\n2007-09-21  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assign1 (Array<LT>&, const Array<RT>&, const LT&)):\n\tAlso allow resizing empty LHS if it is 1x0 or 0xN.\n\n2007-09-19  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-edit.cc (command_editor::remove_startup_hook):\n\tFix cut-and-paste error.\n\t(gnu_readline::set_startup_hook): Only set hook function if new\n\tfunction is different from the current one.\n\n2007-09-18  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-edit.h, cmd-edit.cc (command_editor::startup_hook_set,\n\tcommand_editor::event_hook_set): New static data.\n\t(default_command_editor::set_startup_hook,\n\tgnu_readline::set_startup_hook,\n\tdefault_command_editor::restore_startup_hook,\n\tgnu_readline_restore_event_hook):\n\tRename from do_set_startup_hook and do_set_event_hook.\n\t(gnu_readline::operate_and_get_next): Call\n\tcommand_editor::add_startup_hook, not\n\tcommand_editor::set_startup_hook.\n\t(command_editor::startup_handler, command_editor::event_handler):\n\tNew functions.\n\t(command_editor::add_startup_hook, command_editor::add_event_hook,\n\tcommand_editor::remove_startup_hook,\n\tcommand_editor::remove_event_hook): Rename from set_startup_hook\n\tand restore_startup_hook.  Handle hook sets here.\n\t* cmd-edit.cc (gnu_history::do_goto_mark):\n\tCall remove_startup_hook instead of restore_startup_hook.\n\n2007-09-17  John W. Eaton  <jwe@octave.org>\n\n\t* lo-utils.cc (octave_read_complex, octave_read_double): Skip\n\tleading whitespace.\n\n2007-09-13  John W. Eaton  <jwe@octave.org>\n\n\t* lo-utils.cc (read_inf_nan_na, octave_read_double,\n\toctave_read_complex): Use istream::get instead of >> to read\n\tindividual characters.\n\n2007-09-10  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assign1): Don't call make_unique for invalid assignment.\n\n2007-09-10  David Bateman  <dbateman@free.fr>\n\n\t* Array.h (Array<T>::make_unique): Make public so that the\n\t::assign functions can access it directly.\n\t* Array.cc (Array<T>::maybe_delete_elements_1(idx_vector&),\n\tArray<T>::maybe_delete_elements_1(idx_vector&),\n\tArray<T>::maybe_delete_elements(idx_vector&, idx_vector&),\n\tArray<T>::maybe_delete_elements(Array<idx_vector>&, const T&)):\n\tUse xelem for non const RHS to avoid call to make_unique.\n\t(int assign1 (Array<LT>&, const Array<RT>&, const LT&)): Use\n\txelem for LHS and call lhs.make_unique() only once. Special case\n\tthe is_colon index case and use Array<T>::xelem(octave_idx_type)\n\trather than Array<T>::xelem(octave_idx_type,octave_idx_type) and\n\tbring the additional multiplication out of the inner loop.\n\t(int assign2 (Array<LT>&, const Array<RT>&, const LT&)): ditto.\n\t(int assignN (Array<LT>&, const Array<RT>&, const LT&)): ditto.\n\t* idx-vector.h (idx_vector::idx_vector_rep::idx_vector_rep\n\t(const Range& r)): Don't use init_state() method but special case\n\tas with a Range can avoid exhaustive search.\n\n2007-09-07  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::fortran_vec): Call make_unique instead of\n\tmanipulating rep directly.\n\n\t* Array.h (idx, idx_count): Declare mutable.\n\t(Array<T>::set_index, Array<T>::clear_index, Array<T>::value):\n\tNow const.\n\n2007-09-06  David Bateman  <dbateman@free.fr>\n\n\t* Array-util.cc (increment_index): dimensions can have singleton\n\ttrailing dimensions.\n\t* Array.h (range_error, xelem, checkelem, elem, operator ()):\n\tModify use of Array<int> to Array<octave_idx_type> and adjust\n\twhere necessary.\n\t* Array.cc (range_error): ditto.\n\t* MArrayN.h (permute, ipermute): ditto.\n\t* ArrayN.h (permute, ipermute): ditto.\n\t* so-array.cc (streamoff_array::compute_index): ditto.\n\t* so-array.h (compute_index): ditto.\n\t* CMattrix.cc (ComplexMatrix::exmpm): ditto.\n\n2007-08-29  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc (SparseMatrix SparseMatrix::inverse (MatrixType &,\n\toctave_idx_type&, double&, int, int)): Calculate with LU even for\n\tmatrices marked as singular.\n\t* CSparse.cc (SparseComplexMatrix SparseComplexMatrix::inverse (\n\tMatrixType &, octave_idx_type&, double&, int, int)): ditto.\n\t* dMatrix.cc (Matrix Matrix::inverse (MatrixType &, octave_idx_type&,\n\tdouble&, int, int)): ditto. If rcond==0 force matrix of infinities.\n\t* dMatrix.cc (ComplexMatrix ComplexMatrix::inverse (MatrixType &,\n\toctave_idx_type&, double&, int, int)): ditto.\n\n2007-08-27  John W. Eaton  <jwe@octave.org>\n\n\t* oct-env.cc (octave_env::rooted_relative_pathname,\n\toctave_env::do_rooted_relative_pathname): New functions.\n\t* oct-env.h: Provide decls.\n\n2007-08-24  David Bateman  <dbateman@free.fr>\n\n\t* MSparse.h (MSparse<T>& insert (const Sparse<T>&,\n\tconst Array<octave_idx_type>&)): New method.\n\t(MSparse (const dim_vector&, octave_idx_type)): Ditto.\n\t* dSparse.h (SparseMatrix& SparseMatrix::insert (const\n\tSparseMatrix&, const Array<octave_idx_type>&)): ditto.\n\t(SparseMatrix (const dim_vector&, octave_idx_type)): ditto.\n\t* dSparse.cc (SparseMatrix& SparseMatrix::insert (const\n\tSparseMatrix&, const Array<octave_idx_type>&)): ditto.\n\t* boolSparse.h (SparseBoolMatrix& SparseBoolMatrix::insert (const\n\tSparseBoolMatrix&, const Array<octave_idx_type>&)): ditto.\n\t* boolSparse.cc (SparseBoolMatrix& SparseBoolMatrix::insert (const\n\tSparseBoolMatrix&, const Array<octave_idx_type>&)): ditto.\n\t* CSparse.h (SparseComplexMatrix& SparseComplexMatrix::insert (const\n\tSparseMatrix&, const Array<octave_idx_type>&),\n\tSparseComplexMatrix& SparseComplexMatrix::insert (const\n\tSparseComplexMatrix&, const Array<octave_idx_type>&)): ditto.\n\t(SparseComplexMatrix (const dim_vector&, octave_idx_type)): ditto.\n\t* CSparse.cc (SparseComplexMatrix& SparseComplexMatrix::insert (const\n\tSparseMatrix&, const Array<octave_idx_type>&),\n\tSparseComplexMatrix& SparseComplexMatrix::insert (const\n\tSparseComplexMatrix&, const Array<octave_idx_type>&)): ditto.\n\n2007-08-19  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (Sparse<T>::permute): Avoid shadowing warning.\n\n2007-08-14  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (Sparse<T>::permute): permutation vector is zero based.\n\tSimplify.\n\t(Sparse<T>::reshape): Warn about reshaping to N-d array.\n\n2007-08-10  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* file-stat.cc (file_stat::update_internal) [__WIN32__]:\n\tRemove trailing dir separator when stat'ing directory except for\n\troot directory.\n\n2007-07-25  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in: \tAdjust DISTFILES to allow out of tree \"make dist\"\n\tto work.\n\n2007-06-04  David Bateman  <dbateman@free.fr>\n\n\t* oct-inttypes.h (octave_int<T>& operator <<= (const T2&),\n\toctave_int<T>& operator >>= (const T2&)): Make shift operators\n\tperform a twos complement arithmetic shift for both signed and\n\tunsigned integers regardless of compiler implementations.\n\n2007-06-13  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* SparseCmplxQR.cc (OCTAVE_C99_ZERO): For CXSparse 2.2 and greater\n\tuse cs_complex_t(0,0) for the complex zero.\n\n\t* MArray-ch.cc, MArray-d.cc, MArray-i.cc, MArray-s.cc:\n\tSprinkle class instantiations with OCTAVE_API as needed.\n\n\t* Array.h (INSTANTIATE_ARRAY_ASSIGN, INSTANTIATE_ARRAY,\n\tINSTANTIATE_ARRAY_AND_ASSIGN): New arg, API. Change all uses.\n\t* MArray-defs.h (MARRAY_OP_ASSIGN_DECL, MARRAY_OP_ASSIGN_DECLS,\n\tMARRAY_OP_ASSIGN_FWD_DECLS, MARRAY_OP_ASSIGN_FRIENDS,\n\tMARRAY_OP_ASSIGN_DEFS, MARRAY_UNOP, MARRAY_UNOP_DECLS,\n\tMARRAY_UNOP_FWD_DECLS, MARRAY_UNOP_FRIENDS, MARRAY_UNOP_DEFS,\n\tMARRAY_BINOP_DECL, MARRAY_BINOP_DECLS, MARRAY_AA_BINOP_DECLS,\n\tMDIAGARRAY2_DAS_BINOP_DECLS, MDIAGARRAY2_SDA_BINOP_DECLS,\n\tMDIAGARRAY2_DADA_BINOP_DECLS, MARRAY_BINOP_FWD_DECLS,\n\tMDIAGARRAY2_BINOP_FWD_DECLS, MARRAY_BINOP_FRIENDS,\n\tMDIAGARRAY2_BINOP_FRIENDS, MARRAY_BINOP_DEFS,\n\tMDIAGARRAY2_BINOP_DEFS, MARRAY_OPS_FORWARD_DECLS,\n\tMDIAGARRAY2_OPS_FORWARD_DECLS, MARRAY_OPS_FRIEND_DECLS,\n\tMDIAGARRAY2_OPS_FRIEND_DECLS, INSTANTIATE_MARRAY_FRIENDS,\n\tINSTANTIATE_MARRAY2_FRIENDS, INSTANTIATE_MARRAYN_FRIENDS,\n\tINSTANTIATE_MDIAGARRAY2_FRIENDS): Ditto.\n\t* MSparse-defs.h (SPARSE_OP_ASSIGN_DECL, SPARSE_OP_ASSIGN_DECLS,\n\tSPARSE_OP_ASSIGN_FWD_DECLS, SPARSE_OP_ASSIGN_FRIENDS,\n\tSPARSE_OP_ASSIGN_DEFS, SPARSE_UNOP, SPARSE_UNOP_DECLS,\n\tSPARSE_UNOP_FWD_DECLS, SPARSE_UNOP_FRIENDS, SPARSE_UNOP_DEFS,\n\tSPARSE_BINOP_DECL, SPARSE_BINOP_DECLS, SPARSE_AA_BINOP_DECLS,\n\tSPARSE_BINOP_FWD_DECLS, SPARSE_BINOP_FRIENDS, SPARSE_BINOP_DEFS,\n\tSPARSE_OPS_FORWARD_DECLS, SPARSE_OPS_FRIEND_DECLS,\n\tINSTANTIATE_SPARSE_FRIENDS): Ditto.\n\t* Sparse-op-defs.h (SPARSE_BIN_OP_DECL, SPARSE_CMP_OP_DECL,\n\tSPARSE_BOOL_OP_DECL, SPARSE_SMS_BIN_OP_DECLS,\n\tSPARSE_SMS_CMP_OP_DECLS, SPARSE_SMS_EQNE_OP_DECLS,\n\tSPARSE_SMS_BOOL_OP_DECLS, SPARSE_SSM_BIN_OP_DECLS,\n\tSPARSE_SMS_OP_DECLS, SPARSE_SSM_BIN_OP_DECLS,\n\tSPARSE_SSM_CMP_OP_DECLS, SPARSE_SSM_EQNE_OP_DECLS,\n\tSPARSE_SSM_BOOL_OP_DECLS, SPARSE_SSM_OP_DECLS,\n\tSPARSE_SMSM_BIN_OP_DECLS, SPARSE_SMSM_CMP_OP_DECLS,\n\tSPARSE_SMSM_EQNE_OP_DECLS, SPARSE_SMSM_BOOL_OP_DECLS,\n\tSPARSE_SMSM_OP_DECLS, SPARSE_MSM_BIN_OP_DECLS,\n\tSPARSE_MSM_CMP_OP_DECLS, SPARSE_MSM_EQNE_OP_DECLS,\n\tSPARSE_MSM_BOOL_OP_DECLS, SPARSE_MSM_OP_DECLS,\n\tSPARSE_SMM_BIN_OP_DECLS, SPARSE_SMM_CMP_OP_DECLS,\n\tSPARSE_SMM_EQNE_OP_DECLS, SPARSE_SMM_BOOL_OP_DECLS,\n\tSPARSE_SMM_OP_DECLS): Ditto.\n\t* Sparse.h (INSTANTIATE_SPARSE_ASSIGN, INSTANTIATE_SPARSE,\n\tINSTANTIATE_SPARSE_AND_ASSIGN): Ditto.\n\t* mx-op-defs.h (BIN_OP_DECL, CMP_OP_DECL, NDCMP_OP_DECL,\n\tBOOL_OP_DECL, NDBOOL_OP_DECL, VS_BIN_OP_DECLS, VS_OP_DECLS,\n\tSV_BIN_OP_DECLS, SV_OP_DECLS, VV_BIN_OP_DECLS, VV_OP_DECLS,\n\tMS_BIN_OP_DECLS, MS_CMP_OP_DECLS, MS_BOOL_OP_DECLS, MS_OP_DECLS,\n\tSM_BIN_OP_DECLS, SM_CMP_OP_DECLS, SM_BOOL_OP_DECLS, SM_OP_DECLS,\n\tMM_BIN_OP_DECLS, MM_CMP_OP_DECLS, MM_BOOL_OP_DECLS, MM_OP_DECLS,\n\tNDS_BIN_OP_DECLS, NDS_CMP_OP_DECLS, NDS_BOOL_OP_DECLS,\n\tNDS_OP_DECLS, SND_BIN_OP_DECLS, SND_CMP_OP_DECLS,\n\tSND_BOOL_OP_DECLS, SND_OP_DECLS, NDND_BIN_OP_DECLS,\n\tNDND_CMP_OP_DECLS, NDND_BOOL_OP_DECLS, NDND_OP_DECLS,\n\tSDM_BIN_OP_DECLS, SDM_OP_DECLS, DMS_BIN_OP_DECLS, DMS_OP_DECLS,\n\tMDM_BIN_OP_DECLS, MDM_OP_DECLS, DMM_BIN_OP_DECLS, DMM_OP_DECLS,\n\tDMDM_BIN_OP_DECLS, DMDM_OP_DECLS): Ditto.\n\n2007-06-12  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.cc (Matrix::expm): Special case for scalar arg.\n\t* CMatrix.cc (ComplexMatrix::expm): Likewise.\n\n2007-06-06  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* file-ops.cc (tilde_find_suffix, isolate_tilde_prefix,\n\ttilde_expand_word): Use file_ops::is_dir_sep instead of comparing\n\twith file_ops::dir_sep_char.\n\n\t* MArray-C.cc: Sprinkle with OCTINTERP_API as needed.\n\n2007-06-04  David Bateman  <dbateman@free.fr>\n\n\t* file-ops.cc: Typo.\n\n\t* Sparse.cc (Sparse<T> Sparse<T>::reshape): If length of new\n\tdimensions is greater than 2, collapse to 2-D.\n\n2007-06-02  David Bateman  <dbateman@free.fr>\n\n\t* SparseCmplxQR.cc: Changes to support CXSparse 2.2.0.\n\n2007-05-31  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array::get_size): Throw std::bad_alloc exception if\n\tthe computed size is too large for the size of Octave's index type.\n\n2007-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sparse.h: Don't surround included files with extern \"C\" { ... }.\n\n2007-05-16  David Bateman  <dbateman@free.fr>\n\n\t* dRowVector.cc (linspace): Return second argument if fewer than\n\ttwo values are requested.\n\t* CRowVector.cc (linspace): Likewise.\n\n2007-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.cc (signum (const Complex&)): Special case for (0, 0).\n\n2007-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* oct-fftw.h (octave_fftw): Tag with OCTAVE_API.\n\n2007-04-20  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assign1): For x(:) = RHS, require rhs_len == lhs_len,\n\tnot rhs_len == 1.\n\n2007-04-18  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* oct-md5.h (oct_md5, oct_md5_file): Tag decls with OCTAVE_API.\n\n2007-04-13  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::maybe_delete_elements_2): Don't return early\n\tfor empty matrix.  Only check for colon index equivalence if not empty.\n\n2007-04-10  John W. Eaton  <jwe@octave.org>\n\n\t* SparseCmplxQR.cc\n\t(SparseComplexQR::SparseComplexQR_rep::SparseComplexQR_rep):\n\tMove GCC_ATTR_UNUSED before the parameter decl.\n\tFrom Luis Ortiz  <lortiz@interactivesupercomputing.com>.\n\n2007-04-06  John W. Eaton  <jwe@octave.org>\n\n\t* MArray-defs.h (MARRAY_NORM_BODY): New macro.\n\t* MArray.h (MArray<T>::norm): New function.\n\t* MArray.cc: Provide decl.\n\t* MArray-d.cc (MArray<double>::norm): Define double specialization.\n\t* MArray-C.cc (MArray<Complex>::norm): Define Complex specialization.\n\n2007-04-04  John W. Eaton  <jwe@octave.org>\n\n\t* Range.cc (Range::nelem_internal): Likewise.\n\t* lo-utils.cc (NINT): Use numeric_limits<int> instead of INT_MAX.\n\t(NINTbig): Use numeric_limits<octave_idx_type> instead of INT_MAX.\n\tFrom Scott Pakin <pakin@lanl.gov>.\n\n2007-04-04  David Bateman  <dbateman@free.fr>\n\n\t* dMatrix.cc (Matrix::inverse): If calc_cond is true, calculate\n\tthe condition number for positive definite matrices.\n\t* CMatrix.cc (ComplexMatrix::inverse): Ditto.\n\t* dbleChol.h (CHOL(const Matrix&, bool)): New arg, calc_cond.\n\t(CHOL(const Matrix&, octave_idx_type&, bool): Ditto.\n\t(octave_idx_type init (const Matrix&, bool)): Ditto.\n\t(CHOL(const CHOL&)): Copy xrcond.\n\t(CHOL& operator = (const CHOL&)): Copy xrcond.\n\t(xrcond): New private data member.\n\t* CmplxCHOL.h (ComplexCHOL(const ComplexMatrix&, bool)): New arg,\n\tcalc_cond.\n\t(ComplexCHOL(const ComplexMatrix&, octave_idx_type&, bool): Ditto\n\t(octave_idx_type init (const ComplexMatrix&, bool)): Ditto.\n\t(ComplexCHOL(const ComplexCHOL&)): Copy xrcond.\n\t(ComplexCHOL& operator = (const ComplexCHOL&)): Copy xrcond.\n\t(xrcond): New private data member.\n\t* dbleCHOL.cc (CHOL::init(const Matrix&, bool)): If calc_cond is\n\ttrue, calculate the condition number with dpocon.\n\t* CmplxCHOL.cc (ComplexCHOL::init(const ComplexMatrix&, bool)): If\n\tcalc_cond is true, calculate the condition number with zpocon.\n\n2007-04-03  John W. Eaton  <jwe@octave.org>\n\n\t* intNDArray.cc (intNDArray): Delete spurious semicolon.\n\n\t* CMatrix.cc (ComplexMatrix::tinverse): Use Array<T> and\n\tfortran_vec method instead of OCTAVE_LOCAL_BUFFER to avoid\n\t\"maybe clobbered by vfork\" warning.\n\n\t* Sparse-op-defs.h (SPARSE_CUMSUM): Add braces to avoid ambiguous\n\tif/else.\n\n\t* oct-spparms.h (octave_sparse_params): Define copy constructor\n\tand destructor.\n\n\t* Array.cc (assignN): Don't resize dimension if corresponding\n\tindex is empty.\n\n2007-04-02  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.h (Matrix::inverse): Reinstate versions without\n\tMatrixType argument.\n\t* CMatrix.h (ComplexMatrix::inverse): Likewise.\n\n2007-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DISTDIRS): Delete variable.\n\t(dist): Delete action for DISTDIRS.  Use ln instead of $(LN_S).\n\n2007-03-26  David Bateman  <dbateman@free.fr>\n\n\t* MatrixType.cc: Replace all uses of the method\n\toctave_sparse_params::get_key (\"bandden\") with\n\toctave_sparse_params::get_bandden (void).\n\t(MatrixType::MatrixType (void)): Undo previous change but use\n\toctave_sparse_params::get_bandden (void).\n\t* oct-spparms.cc (get_bandden(void), do_get_bandden(void)): New\n\tmethods.\n\t* oct-spparms.h (get_bandden(void), do_get_bandden(void)):\n\tDeclare them.\n\n2007-03-26  Luis Ortiz  <lortiz@interactivesupercomputing.com>\n\t    David Bateman  <dbateman@free.fr>\n\n\t* idx-vector.h.cc (IDX_VEC_REP::idx_vector_rep (const Range&)):\n\tCheck that all elements are ints before doing anything.  Simplify\n\tcalculation of index values.\n\n2007-03-26  David Bateman  <dbateman@free.fr>\n\n\t* Range.cc (Range::all_elements_are_ints): Improve check.\n\n2007-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* chNDArray.cc, chMatrix.cc: Also generate comparison and bool ops.\n\t* chNDArray.h, chMatrix.h: Provide decls.\n\n2007-03-24  Luis Ortiz  <lortiz@interactivesupercomputing.com>\n\n\t* MatrixType.cc (MatrixType::MatrixType (void)): Initialize\n\tsp_bandden to zero for performance reasons as it's not used.\n\n2007-03-23  David Bateman  <dbateman@free.fr>\n\n\t* oct-rand.cc (octave_rand::seed): Seed differently for big and\n\tlittle endian.\n\n2007-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.cc (acos): Use formula similar to what we use for asin.\n\tFrom Alexander Barth <abarth@marine.usf.edu>.\n\n2007-03-12  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (octave_int::octave_int (double)):\n\tNew Specialization.  Round arg.\n\t(operator / (const octave_int<T1>&, const octave_int<T2>&)):\n\tRound result before converting type.\n\n2007-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assign1): Avoid resizing if there is an error.\n\n\t* dMatrix.cc, CMatrix.cc (operator *): Only check\n\tf77_exception_encountered immediately after calls that use F77_XFCN.\n\n\t* Array.cc (assign1 (Array<LT>&, const Array<RT>&, const LT&)):\n\tOnly allow resizing empty LHS if it is 0x0.\n\n\t* Array.cc (Array<T>::maybe_delete_elements (Array<idx_vector>&,\n\tconst T&)): Handle case of more indices than dimensions.\n\t(assign (Array<LT>&, const Array<RT>&, const LT&)): Allow more\n\tcases to be handled by assignN.\n\t(assignN (Array<LT>&, const Array<RT>&, const LT&)):\n\tSpecial cases for 2-d array assignments for speed.\n\tImprove handling of scalar RHS and empty indices.\n\n2007-03-05  David Bateman  <dbateman@free.fr>\n\n\t* oct-md5.c (oct_md5_file (const std::string&)): New function.\n\t* oct-md5.h (oct_md5_file (const std::string&)): Declare it.\n\n2007-03-02  John W. Eaton  <jwe@octave.org>\n\n\t* str-vec.h (string_vector::empty): Return bool, not int.\n\n2007-03-01  David Bateman  <dbateman@free.fr>\n\n\t* md5.h, md5.c: New files from libmd5-rfc sourceforge project for\n\tan independent implementation of RFC1321.\n\t* oct-md5.h, oct-md5: New files for treating std::string class\n\twith MD5.\n\t* Makefile.in (INCLUDES): Add md5.h and oct-md5.h\n\t(LIBOCTAVE_CXX_SOURCES): Add oct-md5.cc\n\t(LIBOCTAVE_C_SOURCES): Add md5.c\n\n2007-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (uninstall): Delete files listed in\n\t$(INCLUDES_FOR_INSTALL), instead of $(INCLUDES).\n\tFrom Thomas Treichl <Thomas.Treichl@gmx.net>.\n\n2007-02-27  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* file-ops.cc (file_ops::recursive_rmdir):\n\tClose dir_entry object before calling rmdir.\n\n2007-02-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in: Use $(LN_S) instead of ln or ln -s.\n\n\t* sparse-util.h (SparseCholPrint, SparseCholError):\n\tTag with OCTAVE_API.\n\n2007-02-18  David Bateman  <dbateman@free.fr>\n\n\t* oct-rand.cc (do_old_initialization()): call setcgn(1) prior to\n\tcalling setall and reset to the current generator after.\n\n2007-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* oct-shlib.h (octave_shlib::relative): New data member.\n\t(octave_shlib::mark_relative, octave_shlib::is_relative):\n\tNew functions.\n\n2007-02-16  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* lo-sysdep.cc (octave_popen2): New function to simulate popen2 on\n\twindows platform.\n\t* lo-sysdep.h (octave_popen2): Declare it.\n\t* oct-syscalls.cc (octave_syscalls::popen2): New function.\n\t* oct-syscalls.h (octave_syscalls::popen2): Declare it.\n\n2007-02-14  John W. Eaton  <jwe@octave.org>\n\n\t* kpse.cc (expand_elt): Omit special treatment for //.\n\n2007-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc (file_ops::canonicalize_file_name) [HAVE_REALPATH]:\n\tDon't delete value returned from realpath.\n\n2007-02-05  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* file-ops.cc (file_ops::canonicalize_file_name):\n\tProvide implementation if realpath function is available.\n\n2007-01-29  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* oct-fftw.h: Sprinkle with OCTAVE_API as needed.\n\n2007-01-17  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* lo-sysdep.cc (octave_chdir): Handle directory names like \"C:\" on\n\tWindows systems.\n\n2007-01-16  John W. Eaton  <jwe@octave.org>\n\n\t* dSparse.cc: Fix dgbtrf decl for --enable-64.\n\t(SparseMatrix::bsolve): Fix call to dgbtrf for --enable-64\n\n\t* oct-fftw.h (fftw_planner): Provide decl.\n\n2007-01-11  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in (LINK_DEPS): Include $(CAMD_LIBS) in the list.\n\n2007-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sparse.h: Use HAVE_CHOLMOD_CHOLMOD_H, not\n\tHAVE_UMFPACK_CHOLMOD_H for case of \"cholmod/cholmod.h\".\n\n2007-01-08  David Bateman  <dbateman@free.fr>\n\n\t* oct-sparse.h: Replace sparsesuite with suitesparse and\n\tSPARSESUITE with SUITESPARSE to match upstream name.\n\n2007-01-05  David Bateman  <dbateman@free.fr>\n\n\t* oct-fftw.cc: (octave_fftw_planner::method (void),\n\toctave_fftw_planner (FftwMethod)): New methods to interrogate and\n\tset the FFTW wisdom method used.\n\t(octave_fftw_planner::create_plan) Modify to allow different\n\tmethods to be used.\n\t(octave_fftw_planner): Move class definition from here.\n\t* oct-fftw.h (octave_fftw_planner): To here. Add method methods\n\tand FftwMethod enum.\n\n2007-01-03  David Bateman  <dbateman@free.fr>\n\n\t* MSparse.cc (SPARSE_A2A2_OP, SPARSE_A2A2_FCN_1,\n\tSPARSE_A2A2_FCN_1): Modify macros so that scalars stored as\n\tsparse matrices are special cased.\n\n\t* Sparse-op-defs.h: Include mx-ops.h to have access to mixed\n\tmatrix, sparse matrix operations.\n\t(SPARSE_SMSM_BIN_OP_1, SPARSE_SMSM_BIN_OP_2, SPARSE_SMSM_BIN_OP_3,\n\tSPARSE_SMSM_CMP_OP, SPARSE_SMSM_BOOL_OP, SPARSE_MSM_BIN_OP_1,\n\tSPARSE_MSM_BIN_OP_2, SPARSE_MSM_CMP_OP, SPARSE_MSM_BOOL_OP,\n\tSPARSE_SMM_BIN_OP_1, SPARSE_SMM_BIN_OP_2, SPARSE_SMM_CMP_OP,\n\tSPARSE_SMM_BOOL_OP, SPARSE_SPARSE_MUL, SPARSE_FULL_MUL,\n\tFULL_SPARSE_MUL): Modify macros so that scalars stored as\n\tsparse matrices are special cased.\n\n2006-12-22  David Bateman  <dbateman@free.fr>\n\n\t* boolSparse.cc (SparseBoolMatrix::operator !): Fix off-by-one error.\n\n2006-12-22  John W. Eaton  <jwe@octave.org>\n\n\t* dim-vector.h (dim_vector::dim_vector): Always start with at\n\tleast 2 dimensions.\n\t(dim_vector::resize): Don't allow resizing to fewer than 2 dimensions.\n\n2006-12-06  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* lo-sysdep.cc (opendir): Avoid passing \\\\* to FindFirstFile.\n\n\t* file-ops.cc (ops::canonicalize_file_name): Provide partial\n\timplementation for Windows.\n\n2006-12-06  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc (SparseMatrix::is_symmetric): Faster implementation.\n\t* CSparse.cc (SparseComplexMatrix::is_symmetric): Ditto.\n\n\t* dMatrrix.cc (finverse): Old inverse method renamed inverse.\n\t(tinverse): New method for triangular matrices.\n\t(inverse): New function with matrix type probing.\n\t* dMatrix.h (finverse, tinverse, inverse): New and modified\n\tdeclarations.\n\t* CMatrix.cc: Ditto.\n\t* CMatrix.h: Ditto.\n\n2006-12-06  John W. Eaton  <jwe@octave.org>\n\n\t* strptime.c (day_of_the_week): Use code from current glibc sources.\n\n2006-12-05  John W. Eaton  <jwe@octave.org>\n\n\t* lo-utils.cc (octave_read_double): If we see '+' or '-' but not\n\tfollowed by 'I' or 'i', try reading number after putting\n\tcharacters back on input stream.\n\n2006-12-05  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* randpoisson.c (oct_fill_randp): For lambda > 1e8, upper limit of\n\tloop is n, not L.\n\n2006-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* lo-utils.cc (octave_read_double, read_inf_nan_na):\n\tAlso recognize [+-][Ii]nf.\n\n2006-11-28  David Bateman  <dbateman@free.fr>\n\n\t* oct-sparse.h: Allow sparse headers to also be in a sparsesuite\n\tsub-directory.\n\n\t* dSparse.cc (SparseMatrix::inverse): Transpose the matrix type as\n\twell when calling tinverse for lower triangular matrices.\n\t* CSparse.cc (SparseComplexMatrix::inverse):\n\tDitto.\n\n2006-11-21  John W. Eaton  <jwe@octave.org>\n\n\t* oct-env.cc (do_absolute_pathname): Undo previous change.\n\n2006-11-20  John W. Eaton  <jwe@octave.org>\n\n\t* oct-env.cc (octave_env::do_absolute_pathname): Also return true\n\tfor \".\", and names beginning with \"./\" or \"../\".\n\n2006-11-14  Luis F. Ortiz  <lortiz@interactivesupercomputing.com>\n\n\t* CMatrix.cc, dMatrix.cc: New tests.\n\n2006-11-13  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Array-d.cc, dDiagMatrix.h: Sprinkle with OCTAVE_API as needed.\n\n2006-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in ($(OPTS_INC), mx-ops.h):\n\tUse $(simple-move-if-change-rule) here.\n\n2006-11-09  David Bateman  <dbateman@free.fr>\n\n\t* sparse-base-chol.cc (sparse_base_chol_rep::Q): Cast perms(i) to\n\toctave_idx_type, not int.\n\n2006-11-08  John W. Eaton  <jwe@octave.org>\n\n\t* dir-ops.cc (dir_entry::read): Avoid rewinddir.\n\n2006-11-06  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assignN): Exit early if invalid indices are found.\n\n2006-11-03  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* strftime.c [HAVE_TZNAME]: Tag tzname with OCTAVE_IMPORT.\n\n2006-11-03  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DLL_CXXDEFS): Rename from XTRA_CXXDEFS.\n\t(DLL_CDEFS): Rename from XTRA_CDEFS.\n\tSubstitute OCTAVE_DLL_DEFS, not XTRA_OCTAVE_DEFS.\n\n2006-10-28  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* oct-shlib.cc: Undefine min and max after including windows.h.\n\t* oct-syscalls.cc (syscalls::pipe (int *)): Avoid infinite recursion.\n\t* lo-sysdep.h: Move opendir, readdir, etc. decls here from\n\tlo-sysdep.cc.\n\n2006-10-27  John W. Eaton  <jwe@octave.org>\n\n\t* oct-time.cc [! HAVE_STRFTIME]: Declare strftime.\n\n2006-10-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* mx-op-defs.h (NDS_CMP_OP1, NDS_CMP_OPS1, NDS_CMP_OP2,\n\tNDS_CMP_OPS2): New macros.\n\n2006-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* mx-ops (core-type): New field for integer types.\n\t* mk-ops.awk: Handle core-type for integer comparison ops.\n\n\t* lo-cutils.c (octave_strcasecmp, octave-strncasecmp):\n\tMove here from src/cutils.c.\n\t* lo-utils.h: Provide decls.\n\t* strcasecmp.c: Move here from src/strcasecmp.c.\n\t* strncase.c: Move here from src/strncase.c.\n\t* Makefile.in (LIBOCTAVE_C_SOURCES): Add them to the list.\n\n2006-10-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* kpse.cc [! MSVC]: Don't include win32lib.h.\n\n\t* Array-C.cc, Array-b.cc, Array-ch.cc, Array-i.cc, Array-util.h,\n\tArray.h, CColVector.h, CMatrix.h, CNDArray.h, CRowVector.h,\n\tCSparse.h, CmplxAEPBAL.h, CmplxCHOL.h, CmplxDET.h, CmplxHESS.h,\n\tCmplxLU.h, CmplxQR.h, CmplxQRP.h, CmplxSCHUR.h, CmplxSVD.h,\n\tCollocWt.h, DAE.h, DASPK.h, DASRT.h, DASSL.h, EIG.h, LSODE.h,\n\tMArray-C.cc, MArray-defs.h, MSparse-C.cc, MSparse-d.cc,\n\tMSparse-defs.h, MatrixType.h, NLEqn.h, Quad.h, Range.h,\n\tSparse-op-defs.h, Sparse.h, SparseCmplxCHOL.h, SparseCmplxLU.h,\n\tSparseCmplxQR.h, SparseQR.h, SparsedbleCHOL.h, SparsedbleLU.h,\n\tboolMatrix.h, boolNDArray.h, boolSparse.h, chMatrix.h,\n\tchNDArray.h, cmd-edit.h, cmd-hist.h, dColVector.h, dDiagMatrix.h,\n\tdMatrix.h, dNDArray.h, dRowVector.h, dSparse.h, data-conv.h,\n\tdbleAEPBAL.h, dbleCHOL.h, dbleDET.h, dbleHESS.h, dbleLU.h,\n\tdbleQR.h, dbleQRP.h, dbleSCHUR.h, dbleSVD.h, dir-ops.h,\n\tfile-ops.h, file-stat.h, glob-match.h, idx-vector.h,\n\tint16NDArray.cc, int32NDArray.cc, int64NDArray.cc, int8NDArray.cc,\n\tlo-cutils.c, lo-ieee.h, lo-mappers.h, lo-specfun.h, lo-utils.h,\n\tmach-info.h, mx-op-defs.h, oct-alloc.h, oct-env.h, oct-group.h,\n\toct-inttypes.cc, oct-inttypes.h, oct-passwd.h, oct-rand.h,\n\toct-shlib.h, oct-spparms.h, oct-syscalls.h, oct-time.h,\n\toct-uname.h, pathsearch.h, prog-args.h, so-array.h, str-vec.h,\n\tuint16NDArray.cc, uint32NDArray.cc, uint64NDArray.cc,\n\tuint8NDArray.cc: Sprinkle with OCTAVE_API as needed.\n\n2006-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.cc (INSTANTIATE_INTTYPE_BIN_OP): Provide explicit\n\ttype qualification for OP.\n\n2006-10-26  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (Sparse<T>::resize_no_fill (octave_idx_type,\n\toctave_idx_type)): Be more careful with the size of the input\n\tmatrix, and therefore don't create or read non existent data.\n\n2006-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (assign): Clear lhs index after error.\n\n2006-10-25  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (assign (Sparse<LT>&, const Sparse<RT>&)):\n\tFix previous patch so it works.\n\n2006-10-25  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* glob-match.h (glob_match::glob_match (const std::string&,\n\tunsigned int)): Delete initializer for first arg.\n\n\t* lo-sysdep.cc (opendir, readdir, rewinddir, closedir):\n\tNew functions.\n\n\t* Makefile.in (XTRA_CDEFS, XTRA_CXXDEFS): Substitute here.\n\n\t* oct-env.cc (octave_env::do_get_home_directory) [_MSC_VER]: Use\n\tsame code as __MINGW32__.\n\t* syswait.h [_MSC_VER]: Define HAVE_WAITPID, WAITPID, and WNOHANG\n\tthe same as for __MINGW32__.\n\n\t* randpoisson.c: Undefine INFINITE before redefining.\n\n2006-10-24  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (assign (Sparse<LT>&, const Sparse<RT>&)): Resize the\n\tlhs at the point we know the assignment can succeed if the lhs is\n\tempty.\n\n2006-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assign2): Don't require vector assignments to be oriented.\n\n2006-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cieee.c: If isnan is not available but _isnan is, then define\n\tisnan to be _isnan, and define HAVE_ISNAN.  Likewise for _finite\n\tand _copysign.\n\n2006-10-17  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* oct-syscalls.cc (syscalls::waitpid): Always declare and define retval.\n\n\t* CMatrix.cc (ComplexMatrix::solve): Avoid infinite recursion.\n\t* CSparse.cc (SparseComplexMatrix::insert): Likewise.\n\n\t* oct-types.h.in: Include limits.h, for CHAR_BIT.\n\n2006-10-13  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in: Adapt rules to use $(LIBPRE).\n\n2006-10-03  David Bateman  <dbateman@free.fr>\n\n\t* MatrixType.cc (MatrixType::MatrixType): Avoid crash if np == 0\n\tor p == 0.\n\n2006-10-02  John W. Eaton  <jwe@octave.org>\n\n\t* dbleDET.cc (DET::initialize2): Ensure arg to log10 is double.\n\t* CmplxDET.cc (ComplexDET::initialize2): Likewise.\n\n2006-09-22  David Bateman  <dbateman@free.fr>\n\n\t* MatrixType.h (MatrixType::MatrixType(const SparseComplexMatrix&)):\n\tRemove spurious warning.\n\n2006-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::index (Array<idx_vector>&, int, const T&) const):\n\tHandle resizing.\n\n\t* intNDArray.h (intNDArray<T>:elt_type): New typedef.\n\n2006-09-11  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.cc (operator * (const Matrix&, const Matrix&))):\n\tHandle M*v and rv*cv special cases.\n\t* CMatrix.cc (operator * (const ComplexMatrix&, const\n\tComplexMatrix&))): Likewise.\n\tFrom Luis F. Ortiz <lortiz@interactivesupercomputing.com>.\n\n\t* dRowVector.cc (operator * (const RowVector&, const\n\tColumnVector&)): Call xddot here instead of using a Fortran\n\tfunction directly.\n\t* CRowVector.cc (operator * (const ComplexRowVector&, const\n\tComplexColumnVector&)): Call xzdotu here.\n\n2006-09-05  John W. Eaton  <jwe@octave.org>\n\n\t* chNDArray.cc (charNDArray::any, charNDArray::all): Compare\n\telements to '\\0', not ' '.\n\n2006-08-25  John W. Eaton  <jwe@octave.org>\n\n\t* mx-inlines.cc (MX_ND_REDUCTION): Special case for 0x0 arrays.\n\n2006-08-23  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.cc, dMatrix.h (Matrix::save_ascii): Delete function and decl.\n\t* CMatrix.cc, CMatrix.h (ComplexMatrix::save_ascii): Likewise.\n\n2006-08-22  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc (ComplexMatrix::save_ascii): New function.\n\t* dMatrix.cc (Matrix::save_ascii): New function.\n\n\t* mx-inlines.cc (MX_ND_CUMULATIVE_OP): Correctly detect empty arrays.\n\tIf array is empty, return value is same size as array.\n\t(MX_ND_REDUCTION): Correctly detect empty arrays.\n\tIf array is empty, produce correctly sized return value.\n\n2006-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.cc (Matrix::any_element_not_one_or_zero): New function.\n\t* dMatrix.h: Provide decl.\n\t* dNDArray.cc (NDArray::any_element_not_one_or_zero): New function.\n\t* dNDArray.h: Provide decl.\n\t* intNDArray.cc (intNDArray<T>::any_element_not_one_or_zero):\n\tNew function.\n\t* intNDArray.h: Provide decl.\n\n\t* Array.cc (Array<T>::permute): Only rearrange values if array is\n\tnot empty.\n\n2006-07-26  John W. Eaton  <jwe@octave.org>\n\n\t* dbleDET.cc (DET::initialize10, DET::value_will_underflow,\n\tDET::value_will_overflow): Use xlog2 instead of log2.\n\t(DET::initialize2, DET::initialize10): Use xround instead of round.\n\t(DET::initialize2, DET::value): Use xexp2 instead of exp2.\n\t* CmplxDET.cc (ComplexDET::initialize10,\n\tComplexDET::value_will_underflow,\n\tComplexDET::value_will_overflow): Use xlog2 instead of log2.\n\t(ComplexDET::initialize2, ComplexDET::initialize10):\n\tUse xround instead of round.\n\t(ComplexDET::initialize2, ComplexDET::value):\n\tUse xexp2 instead of exp2.\n\n\t* lo-mappers.cc (M_LOG10E): Delete unused macro.\n\t(xlog2, xexp2): New functions.\n\t* lo-mappers.h: Provide decls.\n\n2006-07-22  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.h (Sparse<T>::mex_get_data, Sparse<T>::mex_get_ir,\n\tSparse<T>::mex_get_jc): New functions.\n\n2006-07-21  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (octave_int<T>::mex_get_data): New function.\n\t* Array.h (Array<T>::mex_get_data): New function.\n\n2006-07-19  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (octave_int::operator bool (void)): New function.\n\n2006-07-16  John W. Eaton  <jwe@octave.org>\n\n\t* oct-spparms.h, oct-spparms.cc (class octave_sparse_params):\n\tRename from SparseParams.  Use same implementation method as other\n\tsingleton classes in Octave.  Change all uses of\n\tVoctave_sparse_controls to use static functions from\n\toctave_sparse_params class instead.\n\n\t* oct-spparms.h, oct-spparms.cc (SparseParams::set_key,\n\tSparseParams::get_key): Pass std::string arg by const reference,\n\tnot const value.\n\n2006-07-15  John W. Eaton  <jwe@octave.org>\n\n\t* data-conv.cc: Instantiante swap_bytes templates here.\n\n\t* MatrixType.cc (MatrixType::MatrixType):\n\tUse complete initializer lists in constructors.\n\n2006-07-06  John W. Eaton  <jwe@octave.org>\n\n\t* str-vec.cc (string_vector::string_vector (std::list<std::string>&)):\n\tNew constructor.\n\t* str-vec.h: Provide decl.\n\n2006-07-01  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc (tinverse): Check for rows with no elements and zero\n\telements on the diagonal. Allow both Upper and Lower triangular\n\tmatrices to be treated.\n\t* CSparse.cc (tinverse): ditto.\n\t* Sparse-op-defs.h (SPARSE_SPARSE_MUL): Take into account 64-bit\n\tconstant assignment.\n\n2006-06-30  John W. Eaton  <jwe@octave.org>\n\n\t* lo-sysdep.cc (octave_chdir): Perform tilde expansion here.\n\t* cmd-edit.cc (editor::read_init_file): Ditto.\n\t* dir-ops.cc (dir_entry::open): Ditto.\n\t* file-stat.cc (stat::update_internal): Ditto.\n\t* cmd-hist.cc (command_history::set_file): Ditto.\n\n\t* data-conv.cc (data_conv::string_to_data_type):\n\tCorrectly handle leading \"*\".\n\n2006-06-29  Atsushi Kajita  <a-kajita@mizar.freemail.ne.jp>\n\n\t* Sparse.cc (Sparse<T>::SparseRep::elem): Avoid out of bounds\n\tarray access.\n\n2006-06-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in: Finish renaming of OBJECTS -> LIBOCTAVE_OBJECTS.\n\n2006-06-21  John W. Eaton  <jwe@octave.org>\n\n\t* oct-shlib.cc (octave_dlopen_shlib::close,\n\toctave_shl_load_shlib::close, octave_w32_shlib::close):\n\tSkip do_close_hook if cl_hook is 0.\n\n2006-06-16  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sort.h: Don't include config.h, lo-mappers.h, or quit.h.\n\t* randmtzig.h: Don't inlcude config.h.\n\n2006-05-31  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc (assignN): Maybe reshape LHS before doing assignment.\n\n2006-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* oct-types.h.in: Include stdint.h or inttypes.h for integer\n\ttypedefs, or define them if those files are not available.\n\t* oct-inttypes.h (octave_int8_t, octave_int16_t, octave_int32_t,\n\toctave_int64_t, octave_uint8_t, octave_uint16_t, octave_uint32_t,\n\toctave_uint64_t): Delete typedefs.  Replace all uses of these\n\ttypes with int8_t, int16_t, etc.\n\t* data-conv.h (TWO_BYTE_INT, FOUR_BYTE_INT, EIGHT_BYTE_INT):\n\tDelete definitions.  Replace all uses of these macros with int8_t,\n\tint16_t, etc.\n\t* randmtzig.h: Delete integer typedefs.\n\n2006-05-18  John W. Eaton  <jwe@octave.org>\n\n\t* EIG.cc (EIG::init): Trap Inf and NaN values here.\n\tFrom Keith Goodman <kwgoodman@gmail.com>.\n\n2006-05-08  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (SPARSE_SPARSE_MUL): fix bug in previous\n\tmodification.\n\n2006-05-09  David Bateman  <dbateman@free.fr>\n\n\t* sparse-dmsolve.cc: Remove reference to ov-re-sparse.h,\n\tov-cx-sparse. and error_state.\n\t* SparseQR.cc, SparseCmplxQR.cc (qrsolve): Return info = -1 on error.\n\n2006-05-08  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (SPARSE_SPARSE_MUL): Set column pointers in\n\tfirst pass and use to determine which algorithm to use on a\n\tcolumn-by-column basis.\n\n2006-05-04  David Bateman  <dbateman@free.fr>\n\n\t* SparseQR.cc, SparseQR.h, SparseCmplxQR.cc, SparseCmplxQR.h,\n\tsparse-dmsolve.cc : Allow compilation with versions v2.0.0 of\n\tCXSparse or later\n\n2006-05-03  David Bateman  <dbateman@free.fr>\n\n\t* CMatrix.cc (zpotrf, zpocon, zpotrs, ztrcon, ztrtrs):\n\tExternal declaration of lapack triangular and Cholesky codes.\n\t(ComplexMatrix::utsolve, ComplexMatrix::ltsolve,\n\tComplexMatrix::fsolve): New private solver codes for\n\tupper, lower and LU/Cholesky solvers.\n\t(ComplexMatrix::solve): New versions for cached matrix\n\ttype. Adapt old versions to call new versions\n\t* CMatrix.h (utsolve, ltsolve, fsolve): Declaration of\n\tnew solvers.\n\t(solve): New versions for cached matrix type.\n\t* dMatrix.cc (dpotrf, dpocon, dpotrs, dtrcon, dtrtrs):\n\tExternal declaration of lapack triangular and Cholesky codes.\n\t(Matrix::utsolve, Matrix::ltsolve,\n\tMatrix::fsolve): New private solver codes for\n\tupper, lower and LU/Cholesky solvers.\n\t(Matrix::solve): New versions for cached matrix\n\ttype. Adapt old versions to call new versions\n\t* dMatrix.h (utsolve, ltsolve, fsolve): Declaration of\n\tnew solvers.\n\t(solve): New versions for cached matrix type.\n\t* CSparse.cc: Replace all uses of SparseType with MatrixType.\n\t* CSparse.h: ditto.\n\t* dSparse.cc: ditto.\n\t* dSparse.h: ditto.\n\t* SparseCmplxCHOL.cc: ditto.\n\t* SparsedbleCHOL.cc: ditto.\n\t* sparse-dmsolve.cc: ditto.\n\t* SparseType.cc, SparseType.h: delete.\n\t* MatrixType.cc: New file for class to cache matrix type, based on\n\told SparseType class but caching matrix and sparse types.\n\t* MatrixType.h: ditto.\n\t* Makefile.in (MATRIX_INC, MATRIX_SRC): Add MatrixType.h and\n\tMatrixType.cc respectively. Delete SparseType.h and SparseType.cc\n\trespectively.\n\t* mx-base.h: Include MatrixTye.h as header file.\n\n2006-05-01  John W. Eaton  <jwe@octave.org>\n\n\t* oct-shlib.h (octave_shlib::octave_shlib, octave_shlib::open):\n\tDelete WARN_FUTURE arg.  Change all uses.\n\t* oct-shlib.cc (octave_base_shlib::stamp_time): Delete arg.\n\tChange all uses.  Use current_liboctave_warning_with_id_handler.\n\t(octave_base_shlib::open): Delete arg.  Change all derived classes\n\tand uses.\n\n2006-04-29  John W. Eaton  <jwe@octave.org>\n\n\t* Array-flags.cc, Array-flags.h: Delete.\n\t* Makefile.in (MATRIX_SRC): Remove Array-flags.cc from the list.\n\t(MATRIX_INC): Remove Array-flags.h from the list.\n\n\t* idx-vector.cc (IDX_VEC_REP::freeze): Delete warn_resize arg.\n\tUse current_liboctave_warning_with_id_handler\n\twith warning ID Octave:resize-on-range-error.\n\t* idx-vector.h: Fix decl.\n\t* Array.cc, Sparse.cc: Change all callers.\n\n\t* Array.cc (Array<T>::maybe_delete_elements, Array<T>::index2,\n\tassign2, assignN): Use current_liboctave_warning_with_id_handler\n\twith warning ID Octave:fortran-indexing instead of\n\tliboctave_wfi_flag.\n\t* Sparse.cc (assign, Sparse<T>::index): Likewise.\n\n2006-04-26  John W. Eaton  <jwe@octave.org>\n\n\t* pathsearch.cc (dir_path::path_sep_char, dir_path::path_sep_str):\n\tNew static data.\n\t* pathsearch.h: Provide decls.\n\t(dir_path::is_path_sep): New function.\n\n2006-04-18  John W. Eaton  <jwe@octave.org>\n\n\t* randmtzig.c (randmt, randi53, randi54, randi64, randu32, randu53):\n\tOmit inline from decl.\n\n\t* Sparse.cc (Sparse<T>::index): Use std::vector<bool> to avoid\n\tlocal array with variable dimension.\n\n2006-04-16  John W. Eaton  <jwe@octave.org>\n\n\t* lo-sstream.h: Delete.\n\t* Makefile.in (INCLUDES): Remove it from the list.\n\n\t* dim-vector.h (dim_vector::str): Use std::ostringstream directly.\n\t* Sparse.cc (Sparse::range_error): Likewise.\n\t* DASSL.cc (DASSL::error_message): Likewise.\n\t* LSODE.cc (LSODE::error_message): Likewise.\n\t* DASRT.cc (DASRT::error_message): Likewise.\n\t* DASPK.cc (DASPK::error_message): Likewise.\n\t* Array.cc (Array::range_error): Likewise.\n\n\t* kpse.cc (kpse_hash): Rename from hash.\n\t(hash_lookup): Call kpse_hash instead of hash.\n\n\t* SparseType.cc (SparseType::SparseType): Use std::vector<bool>\n\tto avoid local array with variable dimension.\n\n2006-04-13  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (assign (Sparse<LT>&, const Sparse<RT>&)):\n\tOptimize assignment.\n\n2006-04-13  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.cc (assign (Sparse<LT>&, const Sparse<RT>&)):\n\tEliminate unnecessary casts.\n\t* SparsedbleLU.cc (SparseLU::SparseLU): Likewise.\n\n\t* kpse.cc (fopen): Use reinterpret_cast instead of C-style cast.\n\t(log_search, dir_links): Use static_cast instead of C-style cast.\n\n\t* prog-args.cc (args::getopt): Use reinterpret_cast instead of X_CAST.\n\t* oct-alloc.cc (allocator::grow): Likewise.\n\t* CSparse.cc (SparseComplexMatrix::determinant,\n\tSparseComplexMatrix::factorize, SparseComplexMatrix::fsolve):\n\tLikewise.\n\t* SparseCmplxLU.cc (SparseComplexLU::SparseComplexLU): Likewise.\n\n\t* oct-sort.cc (roundupsize, octave_sort<T>::merge_getmem):\n\tUse static_cast instead of C-style cast.\n\t* CSparse.cc (SparseComplexMatrix::fsolve): Likewise.\n\t* dSparse.cc (SparseMatrix::fsolve): Likewise.\n\n\t* data-conv.cc (LS_DO_WRITE): Use static_cast for value conversion.\n\tUse OCTAVE_LOCAL_BUFFER instead of new/delete.\n\t(LS_DO_READ): Allocate local buffer to avoid pointer tricks.\n\t(write_doubles, read_doubles, LS_DO_WRITE, LS_DO_READ):\n\tUse reinterpret_cast instead of X_CAST.\n\n\t* DiagArray2.h (DiagArray2::Proxy::operator&): No need to cast\n\treturn value here.\n\n2006-04-12  Rafael Laboissiere  <rafael@debian.org>\n\n\t* ArrayN.h (ArrayN::ArrayN): Qualify fill with Array<T> base class.\n\t* DiagArray2.h (DiagArray2::DiagArray2): Likewise.\n\n2006-04-03  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.cc (Sparse<T>::resize): Use xcidx rather than cdix, etc\n\tto avoid copy of original matrix.\n\n\t* Makefile.in (INCLUDES): Add randgamma.h, randpoisson.h and\n\trandmtzig.h to the list.\n\t(LIBOCTAVE_C_SOURCES): Add randgamma.c, randpoisson.c and\n\trandmtzig.c to the list.\n\t* oct-rand.cc (do_old_initialization): Rename from do_initialization.\n\t(use_old_generators): New variable.\n\t(old_initialized): Rename from initialized.\n\t(new_initialized): New variable.\n\t(oct_init_by_entropy): New function.\n\t(maybe_initialize): Initialize new or old generator depending on\n\tvalue of use_old_generators.\n\t(octave_rand::state): New functions.\n\t(octave_rand::distribution): Add gamma, exponential and poisson\n\tdistributions.\n\t(octave_rand::exponential_distribution,\n\toctave_rand::poisson_distribution,\n\toctave_rand::gamma_distribution): New methods to select\n\texponential, poisson or gamma distribution.\n\t(octave_rand::scalar, octave_rand::matrix, octave_rand::nd_array,\n\toctave_rand::vector): Add new distributions.\n\t* oct-rand.h: Provide decls for new functions.\n\t(octave_rand::matrix, octave_rand::scalar, octave_rand::\n\t(octave_rand::scalar, octave_rand::matrix, octave_rand::nd_array,\n\toctave_rand::vector): New arg A, for gamma and poisson distributions.\n\t* randpoisson.c, randpoisson.h, randgamma.c, randmtzig.c,\n\trandmtzig.h: New files.\n\n2006-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* dSparse.cc (SparseMatrix::bsolve): Integer work vector is\n\tArray<octave_idx_type>, so fortran_vec returns pointer to\n\toctave_idx_type, not pointer to int.\n\n\t* CMatrix.cc, CMatrix.h (ComplexMatrix::row (char*),\n\tComplexMatrix::column (char*)): Delete.\n\t* dMatrix.cc, dMatrix.h (Matrix::row (char*),\n\tMatrix::column (char*)): Delete.\n\n2006-03-21  David Bateman  <dbateman@free.fr>\n\n\t* SparseQR.h: Publish externally used friends.\n\t* SparseCmplxQR.h: ditto.\n\n2006-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* lo-specfun.cc (betainc): Use F77_XFCN instead of F77_FUNC for\n\tcall to xdbetai.\n\n2006-03-21  David Bateman  <dbateman@free.fr>\n\n\t* lo-specfun.cc (xlgamma, xgamma): Trap special values.\n\t(xlgamma): Use F77_XFCN instead of F77_FUNC for call to dlgams.\n\n\t* dSparse.cc (solve): Add argument singular_fallback, to allow\n\tfallback to QR solvers to be optional.\n\t* CSparse.cc (solve): Ditto.\n\t* dSparse.h (solve): update declaration for new argument.\n\t* CSparse.h (solve): Ditto.\n\t* sparse-dmsolve.cc (dmsolve): Use singular_fallback argument\n\tto bypass QR solvers when solving the well determined part of\n\tthe problem.\n\n2006-03-17  John W. Eaton  <jwe@octave.org>\n\n\t* str-vec.cc (vector::list_in_columns): New optional arg, width.\n\n2006-03-16  David Bateman  <dbateman@free.fr>\n\n\t* CSparse.cc: Change use of nzmax to nnz to allow automatic\n\treduction of matrix size, except for a couple of cases where nzmax\n\tis needed.\n\t(zpbcon): Correct declaration of lapack zpbcon function.\n\t(dsolve, utsolve, ltsolve, trisolve, bsolve, factorize, fsolve): Add\n\tan argument to allow the calculation of condition number to be\n\toptional.\n\t(bsolve): Add code for the calculation of the condition number\n\tusing zpbcon and zgbcon.\n\t(dsolve): Bug fix for rectangular matrices with sparse RHS.\n\t(utsolve, ltsolve, trisolve, bsolve, fsolve): Mark matrix type as\n\tsingular if singularity is detected.\n\t(solve): Use optional argument to disable calculation of\n\tcondition number for all but fsolve, for speed. Add code to\n\tallow rectnagular matrices or matrices identified as singular\n\tto be treated.\n\t(lssolve): delete.\n\t(operator *): Don't recast real matrices as complex, but\n\trather use the macro directly on the real data.\n\t* dSparse.cc: ditto.\n\t* CSparse.h (dsolve, utsolve, ltsolve, trisolve, bsolve,\n\tfsolve, factorize): Update declaration for new argument to\n\tcalculate the condition number.\n\t(lssolve): delete.\n\t* dSparse.h: ditto.\n\t* Msparse.h: Change use of nxmax to nnz to allow automatic\n\treduction of matrix size, except for a couple of cases where\n\tnzmax is needed.\n\t* Sparse.cc: Change use of nxmax to nnz to allow automatic\n\treduction of matrix size, except for a couple of cases where\n\tnzmax is needed.\n\t(Sparse<T>::index (idx_vector&, idx_vector&, int) const):\n\tSpecial case strict permutations for speed.\n\t* Sparse-op-defs.h: Change use of nxmax to nnz to allow automatic\n\treduction of matrix size, except for a couple of cases where\n\tnzmax is needed.\n\t(SPARSE_SPARSE_MUL, SPARSE_FULL_MUL, FULL_SPARSE_MUL): Update\n\tmacros to allow mixed complex/real arguments.\n\t* SparseCmplxQR.cc (OCTAVE_C99_ZERO): New macro for C99 zero\n\tvalue.\n\t(qrsolve): Use it to zero temporary buffers used bt CXSPARSE.\n\t* SparseType.cc (SparseType::SparseType ()): Correct detection\n\tof permutated triangular matrices to avoid seg-faults. Disable\n\tdetection of underdetermined lower and over-determined upper\n\tmatrix due to problems with non minimum norm solutions.\n\t* sparse-dmsolve.cc: New file for Dulmage-Mendelsohn solver.\n\t* Makefile.in: add sparse-dmsolve.cc to targets.\n\n2006-03-15  William Poetra Yoga Hadisoeseno  <williampoetra@gmail.com>\n\n\t* oct-time.cc (octave_strptime::init): Return useful character count.\n\n2006-03-08  David Bateman  <dbateman@free.fr>\n\n\t* SparseCmplxQR.cc: Updates for new upstream CXSPARSE release. Fix for\n\tg++ 4.x stl_vector.h issue with C99 double _Complex type.\n\t* SparseCmplxQR.h:  Updates for new upstream CXSPARSE release.\n\t* SparseQR.cc: ditto.\n\t* SparseQR.h: ditto.\n\t* oct-sparse.h: ditto.\n\t* sparse-base-chol.cc (sparse_base_chol<>::sparse_base_chol_rep::init):\n\tDeclare info variable as volatile.\n\n\t* Sparse.cc (Sparse<T>::transpose (void) const): Accelerate algorithm.\n\t* CSparse.cc (SparseComplexMatrix::transpose (void) const): ditto.\n\n2006-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc (ComplexMatrix::determinant):\n\tScale result by factors of 2, not 10.\n\t* dMatrix.cc (Matrix::determinant): Likewise.\n\n\t* dbleDET.h (DET::DET): Use initializer list.\n\t(DET::coefficient2, DET::coefficient10, DET::exponent2,\n\tDET::exponent10): New functions.\n\t(DET::det): Delete.\n\t(DET::c2, DET::c10, DET::e2, DET::e10, DET::base2): New data members.\n\tStore value internally with double and int instead of 2-element\n\tdouble vector.\n\t(DET::initialize2, DET::initialize10): Provide decls.\n\t* dbleDET.cc (DET::value_will_overflow,\tDET::value_will_underflow):\n\tReturn bool value, not int.\n\t(DET::initialize2, DET::initialize10): New functions.\n\n\t* CmplxDET.h (ComplexDET::ComplexDET): Use initializer list.\n\t(ComplexDET::coefficient2, ComplexDET::coefficient10,\n\tComplexDET::exponent2, ComplexDET::exponent10): New functions.\n\t(ComplexDET::det): Delete.\n\t(ComplexDET::c2, ComplexDET::c10, ComplexDET::e2, ComplexDET::e10,\n\tComplexDET::base2): New data members.\n\tStore value internally with Complex and int instead of 2-element\n\tComplex vector.\n\t(ComplexDET::initialize2, ComplexDET::initialize10): Provide decls.\n\t* dbleComplexDET.cc (ComplexDET::value_will_overflow,\n\tComplexDET::value_will_underflow): Return bool value, not int.\n\t(ComplexDET::initialize2, ComplexDET::initialize10): New functions.\n\n2006-02-24  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assignN): Clear index before reshaping.\n\n\t* Array.h (Array<T>::operator =): Don't set idx to 0 if copying self.\n\n2006-02-20  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc (dsolve, utsolve, ltsolve): Remove restriction that\n\tmatrix must be square in diagonal, permuted diagonal, triangular\n\tand permuted triangular back/forward substitution code. Change\n\tambiguous use of no. rows and columns.\n\t* CSParse.cc (dsolve, utsolve, ltsolve): ditto.\n\t* SparseType.cc (SparseType::SparseType(const SparseMatrix&),\n\tSparseType::SparseType(const SparseComplexMatrix&)): Recognize\n\trectangular diagonal, permuted diagonal, triangular and permuted\n\ttriangular matrices.\n\t* Sparse.cc (Sparse<T>::Sparse (octave_idx_type, octave_idx_type, T)):\n\tTreat case where third argument is zero.\n\n2006-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* kpse.cc: Do define ST_NLINK_TRICK for Cygwin systems.\n\t(do_subdir) [ST_NLINK_TRICK]: Check links != 2 instead of links > 2.\n\n\t* getopt.c: Use __CYGWIN__ instead of __CYGWIN32__.\n\n2006-02-13  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (LINK_DEPS): Add missing dependencies on colamd,\n\tccolamd and cxsparse\n\n2006-02-13  John W. Eaton  <jwe@octave.org>\n\n\t* kpse.cc (kpse_path_iterator::next): Reverse order of tests in\n\twhile loop condition.\n\t(kpse_path_iterator::operator =): Declare as private function but\n\tdon't define to prevent attempts to use assignment operator.\n\tDon't define ST_NLINK_TRICK for Cygwin systems.\n\n2006-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* mx-inlines.cc (MX_ND_REDUCTION): Store in cummulative\n\tproduct of all dimensions in CP_SZ.\n\n2006-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* mx-inlines.cc (MX_ND_CUMULATIVE_OP): Store in cummulative\n\tproduct of all dimensions in CP_SZ.\n\n2006-02-09  David Bateman  <dbateman@free.fr>\n\n\t* SparseQR.cc: new file for real sparse QR class.\n\t* SparseQR.h: declaration.\n\t* SparseCmplxQR.cc: new file for complex sparse QR class.\n\t* SparseCmplxQR.h: declaration.\n\t* dSparse.cc (dinverse,tinverse,inverse): Remove unused input args.\n\t(factorize, fsolve): Enable code code lssolve.\n\t(lssolve): disable unused args, write based in above sparse QR class.\n\t* CSparse.cc (dinverse,tinverse,inverse): Remove unused input args.\n\t(factorize, fsolve): Enable code code lssolve.\n\t(lssolve): disable unused args, write based in above sparse QR class.\n\t* oct-sparse.h: fix location of colamd, ccolamd and metis headers.\n\tInclude CXSparse headers.\n\t* Makefile.in (MATRIX_INC): Include SparseQR.h and SparseCmplxQR.h.\n\t(MATRIX_SRC): Include SparseQR.cc and SparseCmplxQR.cc.\n\n2006-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* Array-util.h (calc_permutated_idx): Delete.\n\t* Array.cc (permute_vector): New data structure.\n\t(permute_vector_compare): New function.\n\t(Array<T>::permute): Rewrite to avoid calc_permutated_index for\n\timproved performance.\n\n2006-02-04  David Bateman  <dbateman@free.fr>\n\n\t* COLAMD: Remove all files, as now unused.\n\n2006-01-31  John W. Eaton  <jwe@octave.org>\n\n\t* Sparse.h (Sparse<T>::nzmax): New function.\n\t(Sparse<T>::nnz): Rename from nonzero.\n\tChange all uses of old nnz function to be nzmax.  Change all uses\n\tof nonzero to be nnz.\n\t(Sparse<T>::nzmx): Rename from nnz (data member).  Change all uses.\n\n2006-01-21  David Bateman  <dbateman@free.fr>\n\n\t* sparse-sort.cc (bool octave_sparse_sidxl_comp): 64-bit fix.\n\t(bool octave_idx_vector_comp): New function.\n\t(template class octave_sort<octave_idx_vector_sort *>): Instantiate\n\tindexed idx_vector sorting function.\n\t* sparse-sort.h (class octave_sparse_sort_idxl): 64-bit fix.\n\t(class octave_idx_vector_sort): New class for indexed idx_vector\n\tsorting.\n\t(bool octave_idx_vector_comp): Declaration.\n\t* Sparse.cc (int assign1(Sparse<LT>&, Sparse<RT>&)): Treat cases of\n\tunordered LHS indexes in assignment using new octave_idx_vector_sort\n\tclass.\n\t(int assign(Sparse<LT>&, Sparse<RT>&)): ditto.\n\n2006-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* so-array.h (streamoff_array::nnz): New funtion.\n\t* boolNDArray.h (boolNDArray::nnz): New function.\n\t* MArrayN.h (MArrayN<T>::nnz): New function.\n\t* MArray.h (MArray<T>::nnz): New function.\n\n2006-01-04  David Bateman  <dbateman@free.fr>\n\n\t* Spars-op-defs.h (SPARSE_SPARSE_MUL): Previous change resulted in\n\telements not being sorted in return matrix. Sort them, and make\n\tsolver select between two algorithms to further improve the\n\tperformance.\n\t* dSparse.cc: include oct-sort.h.\n\t* CSparse.cc: ditto.\n\t* sparse-sort.cc: Instantiate octave_sort<octave_idx_type>.\n\n2005-12-28  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (SPARSE_SPARSE_MUL): Improved algorithm that is\n\tfaster in all cases, and significantly so for low density or small\n\torder problems.\n\n2005-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* LSODE.cc (LSODE::do_integrate (double)): Resize iwork and rwork\n\tbefore setting any values in either array.\n\n2005-11-29  John W. Eaton  <jwe@octave.org>\n\n\t* oct-uname.h, oct-uname.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n2005-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::indexN): Simplify.\n\n2005-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (octave_int::operator char (void) const):\n\tNew conversion op.\n\n2005-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (distclean): Also remove oct-types.h.\n\tFrom Quentin Spencer <qspencer@ieee.org>.\n\n2005-10-31  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc, CSparse.cc: Use C++ true/false instead of\n\tpreprocessor defined TRUE/FALSE.\n\n2005-10-30  John W. Eaton  <jwe@octave.org>\n\n\t* mx-inlines.cc (MX_ND_REDUCTION): Iterate in direction of DIM.\n\t(MX_ND_CUMULATIVE_OP): Likewise.\n\n2005-10-29  John W. Eaton  <jwe@octave.org>\n\n\t* mx-inlines.cc (MX_ND_REDUCTION): Avoid increment_index to speed\n\tthings up.  Simplify.\n\n\t* Array.cc (Array<T>::indexN): Simplify.  Delete separate special\n\tcase for \"vector_equivalent\".\n\n\t* Array-util.cc (vector_equivalent): Arg is now dim_vector.\n\n2005-10-28  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sparse.h: Fix typo in HAVE_UFSPARSE_UMFPACK_H.\n\tFrom Quentin Spencer <qspencer@ieee.org>.\n\n\t* sparse-base-chol.cc: Use C++ true/false instead of\n\tpreprocessor defined TRUE/FALSE.  Use 0 instead of NULL.\n\n2005-10-27  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assignN): Reshape to final size instead of resizing.\n\n2005-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sparse.h: New file.\n\t* oct-sparse.h.in: Delete.\n\n2005-10-26  David Bateman  <dbateman@free.fr>\n\n\t* sparse-base-chol.h: Include cholmod specific code in HAVE_CHOLMOD\n\t* sparse-base-chol.cc: ditto.\n\n2005-10-26  John W. Eaton  <jwe@octave.org>\n\n\tChanges for GCC 4.1, tip from Arno J. Klaassen\n\t<arno@heho.snv.jussieu.fr>:\n\n\t* dSparse.h (real (const SparseComplexMatrix&)):\n\tPublish externally used friend function.\n\t(imag (const SparseComplexMatrix&)): Likewise.\n\n\t* dColVector.h (real (const ComplexColumnVector&)):\n\tPublish externally used friend function.\n\t(imag (const ComplexColumnVector&)): Likewise.\n\n\t* dNDArray.h (real (const ComplexNDArray&)):\n\tPublish externally used friend function.\n\t(imag (const ComplexNDArray&)): Likewise.\n\n\t* dMatrix.h (operator * (const ComplexMatrix&)):\n\tMove decl outside class.  No need to be friend.\n\t(real (const ComplexMatrix&)): Publish externally used friend function.\n\t(imag (const ComplexMatrix&)): Likewise.\n\n\t* CMatrix.h: (operator * (const ColumnVector&, const\n\tComplexRowVector&)): Move decl outside class.  No need to be friend.\n\t(operator * (const ComplexColumnVector&, const RowVector&)): Likewise.\n\t(operator * (const ComplexColumnVector&, const ComplexRowVector& b)):\n\tLikewise.\n\n2005-10-23  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (SPARSE_SPARSE_MUL): Check whether trailing zero\n\telements need to be removed.\n\n\t* oct-sparse.h.in: Include metis headers and some macros for long/int\n\tversions of cholmod.\n\n\t* CSparse.cc (tinverse): New private function for the inversion of\n\tan upper triangular matrix.\n\t(dinverse): ditto for diagonal matrices.\n\t(inverse): Add SparseType as an argument. Implement matrix inverse\n\tusing tinverse and dinverse.\n\t(fsolve): Use cholmod to implement Cholesky solver.\n\t* CSparse.h (tinverse, dinverse): Declarations\n\t(inverse): Alter declaration to include SparseType.\n\n\t* dSparse.cc (tinverse, dinverse, inverse, fsolve): ditto.\n\t* dSparse.h (tinverse, dinverse, inverse): ditto.\n\n\t* SparseType.cc: Fix complex constructor for hermitian matrices.\n\n\t* sparse-util.cc: New file for sparse utility functions.\n\t* sparse-util.h: New file with declarations of sparse utility\n\tfunctions.\n\n\t* sparse-base-chol.cc: New file with sparse cholesky class based\n\ton cholmod.\n\t* sparse-base-chol.h: New file with declaration of sparse cholesky\n\tclass based on cholmod.\n\n\t* SparseCmplxCHOL.cc: Instantiate sparse cholesky class for Complex.\n\t* SparseCmplxCHOL.h: Declaration of sparse cholesky class.\n\n\t* SparsedbleCHOL.cc: ditto.\n\t* SparsedbleCHOL.h: ditto.\n\n\t* Makefile.in (MATRIX_INC): Include sparse-base-chol.h.\n\t(INCLUDES): Include sparse-util.h\n\t(TEMPLATE_SRC): Include sparse-base-chol.cc\n\t(MATRIX_SRC): Include SparseCmplxCHOL.cc and SparsedbleCHOL.cc\n\n2005-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* oct-env.cc (octave_env::have_x11_display): New function.\n\t* oct-env.h: Provide decl.\n\n2005-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* file-stat.h (file_stat::mode): New function.\n\n\t* file-stat.cc (file_stat::is_blk, file_stat::is_chr,\n\tfile_stat::is_dir, file_stat::is_fifo, file_stat::is_lnk,\n\tfile_stat::is_reg, file_stat::is_sock): New static functions.\n\t* file-stat.h: Provide decls.\n\n2005-09-28  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc (file_ops::recursive_rmdir): New function.\n\t* file-ops.h: Provide decl.\n\n2005-09-19  David Bateman  <dbateman@free.fr>\n\n\t* oct-env.cc (octave_env::do_get_home_directory):\n\tAlso check HOMEDRIVE under mingw.\n\n\t* Makefile.in (LINK_DEPS): Include UFsparse libraries.\n\n2005-09-16  John W. Eaton  <jwe@octave.org>\n\n\t* oct-syscalls.cc: Include lo-utils.h here.\n\t(octave_syscalls::waitpid): Call octave_waitpid here.\n\n\t* lo-cutils.c (octave_waitpid): New function.\n\t* lo-utils.h: Provide decl.  Include syswait.h here, not in\n\toct-syscalls.cc\n\n\n\t* syswait.h [__MINGW32__]: Define WAITPID here instead of defining\n\twaitpid in src/sysdep.h.  Make this header C-compatible.\n\n\t* oct-syscalls.cc (octave_syscalls::waitpid): New arg, status.\n\tChange all uses.\n\n2005-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (MAKEDEPS_2): Omit unnecessary variable.\n\n\t* oct-sparse.h.in: New file.\n\t* Makefile.in (DISTFILES): Include it in the list.\n\t(INCLUDES): Add oct-sparse.h to the list.\n\n2005-09-15  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc : Include oct-sparse.h for probed umfpack, colamd etc\n\theaders. Remove include of umfpack.h.\n\t* CSparse.cc : ditto.\n\t* SparsedbleLU.cc : ditto.\n\t* SparseCmplxLU.cc : ditto.\n\n\t* COLAMD : Remove colamd files from octave.\n\t* COLAMD.files : delete.\n\t* COLAMD.README : delete.\n\t* Makefile.in: Remove COLAMD. Add LIBGLOB.\n\t(LN_S): Change to DESTDIR before LN_S to avoid lack of symlinks\n\tunder mingw.\n\n\t* kpse.cc (ENV_SEP, ENV_SEP_STRING): Use SEPCHAR and SEPCHAR_STR\n\tin definition.\n\t* lo-cutils.c (octave_w32_library_search): Call GetProcAddress with\n\tchange of cast not allowed under g++ 3.x.\n\t* lo-utils.h (octave_w32_library_search): Declaration.\n\t* oct-env.cc (do_get_home_directory): Also check HOMEPATH under mingw.\n\t* oct-shlib.cc (octave_w32_shlib::search): Use octave_w32_library_search.\n\n2005-09-07  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-edit.cc (command_editor::do_decode_prompt_string):  Update\n\tbased on current code in Bash.  Handle a few more escape\n\tsequences.  Do a better job of decoding \\W.\n\n2005-09-04  David Bateman  <dbateman@free.fr>\n\n\t* COLAMD: Update version of colamd to v2.4.\n\t* COLAMD.files: Add colamd_global.c to COLAMD_SRC and second build of\n\tcolamd.c for long version.\n\n2005-08-25  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (FULL_SPARSE_MUL, SPARSE_FULL_MUL): Macro for\n\tmixed sparse/full multiply.\n\t* dSparse.cc (operator *), CSparse.cc (operator *): New operators for\n\tmixed sparse/full multiply.\n\t* dSparse.h (operator *), CSparse.h (operator *): Declaration of\n\tmixed sparse/full multiply operators.\n\n2005-07-25   Erik de Castro Lopo  <erikd@zip.com.au>\n\n\t* oct-inttypes.h (OCTAVE_S_US_FTR): Compare <= 0 instead of < 0 to\n\tavoid warnings for unsigned types.\n\n2005-07-07  John W. Eaton  <jwe@octave.org>\n\n\t* dSparse.cc (SparseMatrix::factorize): Initialize Numeric to 0.\n\t* CSparse.cc (SparseComplexMatrix::factorize:) Likewise.\n\n2005-06-15  John W. Eaton  <jwe@octave.org>\n\n\t* oct-rl-edit.c (flush_stdout): Rename from no_redisplay.\n\tFlush stdout here.\n\t(octave_rl_clear_screen): Set rl_redisplay_function to flush_stdout.\n\n\t* Array.h (Array::resize): Change int args to octave_idx_type.\n\n2005-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* CMatrix.cc, CNDArray.cc, CSparse.cc, dMatrix.cc, dNDArray.cc,\n\tdSparse.cc, lo-cieee.c, lo-mappers.cc: Change all uses of\n\toctave_is_NaN_or_NA to xisnan.\n\n\t* lo-mappers.h (octave_is_NaN_or_NA): Mark with GCC_ATTR_DEPRECATED.\n\t* lo-ieee.h (lo_ieee_is_NaN_or_NA): Likewise.\n\n\t* lo-cieee.c (lo_ieee_is_NaN_or_NA): Now just a wrapper for\n\tlo_ieee_isnan.\n\n\t* dMatrix.cc (Matrix::too_large_for_float): Only check if abs\n\tvalue is greater than FLT_MAX.\n\t* CMatrix.cc (ComplexMatrix::too_large_for_float): Ditto.\n\t* dNDArray.cc (NDArray::too_large_for_float): Ditto.\n\t* CNDArray.cc (ComplexNDArray::too_large_for_float): Ditto.\n\n\t* dMatrix.cc (Matrix::too_large_for_float): Special case Inf\n\tvalues too.\n\t* CMatrix.cc (ComplexMatrix::too_large_for_float): Ditto.\n\n\t* dNDArray.cc (NDArray::too_large_for_float): Likewise for NaN,\n\tNA, Inf values.\n\t* CNDArray.cc (ComplexNDArray::too_large_for_float): Ditto.\n\n2005-06-14  David Bateman  <dbateman@free.fr>\n\n\t* dMatrix.cc (Matrix::too_large_for_float): Special case NaN and\n\tNA values.\n\t* CMatrix.cc (ComplexMatrix::too_large_for_float): Ditto.\n\n2005-06-02  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assignN): Try harder to correctly resize previously\n\tempty LHS.\n\n2005-05-16  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.h: Change UMFPACK_LONG_IDX to IDX_TYPE_LONG.\n\t* CSparse.h: ditto.\n\n2005-05-10  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc (determinant): Free numeric factorization after\n\tsucessful calculation.\n\t* CSparse.cc (determinant): ditto.\n\n2005-05-06  John W. Eaton  <jwe@octave.org>\n\n\t* dbleCHOL.cc (CHOL::init): Use xelem instead of elem for indexing\n\tchol_mat.\n\t(chol2mat_internal, chol2mat, CHOL::inverse): New functions.\n\t* dbleCHOL.h (chol2mat_internal, chol2mat, CHOL::inverse):\n\tProvide decls.\n\n\t* CmplxChol.cc (ComplexCHOL::init): Use xelem instead of elem for\n\tindexing chol_mat.\n\t(chol2mat_internal, chol2mat, ComplexCHOL::inverse): New functions.\n\t* CmplxCHOL.h (chol2mat_internal, chol2mat, CmplxCHOL::inverse):\n\tProvide decls.\n\n2005-05-05  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::permute): Call chop_trailing_singletons on\n\tretval before return.\n\n2005-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-edit.cc (gnu_readline::do_readline): Extract const char*\n\tfrom prompt outside of INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE block.\n\n2005-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LINK_DEPS): List $(UMFPACK_LIBS) ahead of $(BLAS_LIBS).\n\tFrom Dmitri A. Sergatskov <dasergatskov@gmail.com>.\n\n2005-04-29  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc (trisolve): Diagonal passed to lapack zptsv is type\n\tdouble.  Correct indexing for upper diagonal elements for sparse\n\ttridiagonal.\n\t* CSparse.cc (trisolve): ditto.\n\n\t* CSparse.h (UMFPACK_ZNAME): Define macro to pick version of\n\tUMFPACK for 64-bit.\n\t* CSparse.cc (UMFPACK_ZNAME): Replace all umfpack_zi_* with\n\tUMFPACK_ZNAME(*).\n\t* SparseCmplxLU.cc (UMFPACK_ZNAME): ditto\n\n\t* dSparse.h (UMFPACK_DNAME): Define macro to pick version of\n\tUMFPACK for 64-bit.\n\t* dSparse.cc (UMFPACK_DNAME): Replace all umfpack_di_* with\n\tUMFPACK_DNAME(*).\n\t* SparsedbleLU.cc (UMFPACK_DNAME): ditto\n\n\t* dSparse.cc (ltsolve, utsolve): Correct permuted upper/lower\n\ttriangular back/forward substitution code.\n\t* CSparse.cc (ltsolve, utsolve): ditto.\n\n\t* dSparse.cc (solve): Use mattype.type (false) to force messaging\n\tfrom spparms(\"spumoni\",1).\n\t* CSparse.cc (solve): ditto\n\n\t* SparseType.cc (SparseType(void)): Print info for\n\tspparms(\"spumoni\",1).\n\t(SparseType(const matrix_type), SparseType(const matrix_type, const\n\toctave_idx_type, const octave_idx_type*), SparseType(const matrix_type,\n\tconst octave_idx_type, const octave_idx_type)): New constructors.\n\t(SparseType (const SparseMatrix&), SparseType (SparseComplexMatrix&)):\n\tDetect row permuted lower triangular and column permuted upper\n\ttriangular matrices. Remove one of the permutation vectors..\n\n\t* SparseType.h: Simplify the permutation code.\n\t(SparseType(const matrix_type), SparseType\n\t(const matrix_type, const octave_idx_type, const octave_idx_type*),\n\tSparseType(const matrix_type, const octave_idx_type,\n\tconst octave_idx_type)): Declarations.\n\n2005-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* str-vec.cc (string_vector::delete_c_str_vec): Correctly free\n\tarray and its contents.\n\n2005-04-22  John W. Eaton  <jwe@octave.org>\n\n\t* oct-rl-edit.c (octave_rl_set_terminal_name): Don't cast away\n\tconst here now that rl_terminal_name is declared const char*.\n\n2005-04-21  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DISTFILES): Include oct-types.h.in in the list.\n\n2005-04-19  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assignN): Don't crash if the index list is empty.\n\n2005-04-14  David Bateman  <dbateman@free.fr>\n\n\t* SparseCmplxLU.cc: Add flags for incomplete factorization.\n\t* SparsedbleLU.cc: Ditto.\n\t* SparseCmplxLU.h: Definition.\n\t* SparsedbleLU.h: ditto.\n\n\t* SparseType.cc (transpose): New function.\n\t* SparseType.h (transpose): Definition.\n\n2005-04-11  John W. Eaton  <jwe@octave.org>\n\n\t* lo-specfun.cc: Use F77_XFCN instead of F77_FUNC for calls to\n\tfortran code that could end up calling XSTOPX.\n\n2005-04-10  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in: include oct-types in INCLUDES so that it is\n\tinstalled\n\n2005-04-08  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (clean): Use exact filenames instead of *.xxx.\n\n\t* Initial merge of 64-bit changes from Clinton Chee:\n\n\t2005-04-07  John W. Eaton  <jwe@octave.org>\n\n\t* MArray-i.cc, Array-i.cc: Instantiate Array<long> and MArray<long>.\n\n\t* CSparse.cc, CSparse.h, MSparse.cc, MSparse.h, Sparse-op-defs.h,\n\tSparse.cc, Sparse.h, SparseCmplxLU.cc, SparseType.cc,\n\tSparseType.h, SparsedbleLU.cc, boolSparse.cc, boolSparse.h,\n\tdSparse.cc, dSparse.h, sparse-base-lu.cc:\n\tUse octave_idx_type instead of int where needed.\n\n\t2005-03-31  Clinton Chee  <chee@parallel.hpc.unsw.edu.au>\n\n\t* Array-util.cc, Array-util.h, Array.cc,Array.h, Array2.h,\n\tArray3.h, ArrayN.cc, ArrayN.h, Bounds.cc, Bounds.h, CColVector.cc,\n\tCColVector.h, CDiagMatrix.cc, CDiagMatrix.h, CMatrix.cc,\n\tCMatrix.h, CNDArray.cc, CNDArray.h, CRowVector.cc, CRowVector.h,\n\tCmplxAEPBAL.cc, CmplxAEPBAL.h, CmplxCHOL.cc, CmplxCHOL.h,\n\tCmplxHESS.cc, CmplxHESS.h, CmplxLU.cc, CmplxQR.cc, CmplxQRP.cc,\n\tCmplxSCHUR.cc, CmplxSCHUR.h, CmplxSVD.cc, CmplxSVD.h, CollocWt.cc,\n\tCollocWt.h, DAEFunc.h, DASPK-opts.in,DASPK.cc,DASPK.h,\n\tDASRT-opts.in, DASRT.cc, DASRT.h, DASSL-opts.in, DASSL.cc,\n\tDASSL.h, DiagArray2.cc, DiagArray2.h, EIG.cc, EIG.h, FEGrid.cc,\n\tFEGrid.h, LPsolve.cc, LPsolve.h, LSODE-opts.in, LSODE.cc, LSODE.h,\n\tMArray-defs.h, MArray.cc, MArray.h, MArray2.cc, MArray2.h,\n\tMArrayN.cc, MDiagArray2.cc, MDiagArray2.h, NLConst.h, NLEqn.cc,\n\tNLEqn.h, Quad.cc, Quad.h, Range.cc,Range.cc, Range.h, base-de.h,\n\tbase-lu.cc, base-lu.h, base-min.h, boolMatrix.cc, boolMatrix.h,\n\tboolNDArray.cc, boolNDArray.h, chMatrix.cc, chMatrix.h,\n\tchNDArray.cc, chNDArray.h, dColVector.cc, dColVector.h,\n\tdDiagMatrix.cc, dDiagMatrix.h, dMatrix.cc, dMatrix.h,\n\tdNDArray.cc,dNDArray.cc, dNDArray.h, dRowVector.cc, dRowVector.h,\n\tdbleAEPBAL.cc, dbleAEPBAL.h, dbleCHOL.cc, dbleCHOL.h, dbleHESS.cc,\n\tdbleHESS.h, dbleLU.cc, dbleQR.cc, dbleQRP.cc, dbleSCHUR.cc,\n\tdbleSCHUR.h, dbleSVD.cc, dbleSVD.h, dim-vector.h, idx-vector.cc,\n\tidx-vector.h, intNDArray.cc, intNDArray.h, lo-specfun.cc,\n\tlo-specfun.h, mach-info.cc, mx-inlines.cc, oct-fftw.cc,\n\toct-fftw.h, oct-rand.cc, oct-rand.h, so-array.cc, so-array.h,\n\tstr-vec.cc, str-vec.h:\n\tUse octave_idx_type instead of int where needed.\n\n\t2005-04-01  John W. Eaton  <jwe@octave.org>\n\n\t* dim-vector.h, lo-utils.h: Include oct-types.h.\n\n\t* oct-types.h.in: New file.\n\n\t2005-03-31  Clinton Chee  <chee@parallel.hpc.unsw.edu.au>\n\n\t* lo-utils.cc (NINTbig): New function.\n\t* lo-utils.h: Provide decl.\n\n2005-04-06  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in: Link to UMFPACK_LIBS.\n\n2005-04-05  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assignN): Avoid shadowed declaration in previous change.\n\n2005-04-01  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assignN): For A(IDX-LIST) = RHS with A previously\n\tundefined, correctly match colons in IDX-LIST with RHS dimensions\n\twhen resizing A.  When performing the assignment, just check that\n\tthe number of elements in RHS matches the number of elements\n\tindexed by IDX-LIST.\n\n2005-03-30  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.cc (log10, tan, tanh): Delete functions.\n\t* lo-mappers.h (log10, tan, tanh): Delete decls.\n\n\t* CColVector.cc, CNDArray.cc, CRowVector.cc, CSparse.cc,\n\tdSparse.cc: Use std:: for Complex functions instead of relying on\n\twrappers from oct-cmplx.h.\n\n\t* oct-cmplx.h: Provide typedef only.\n\n\t* DiagArray2.cc (xelem): Don't use initializer for static data.\n\t* DiagArray2.h (DiagArray<T>::Proxy::operator T ()):\n\tLikewise.\n\n2005-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* cmd-edit.cc (do_readline): Wrap call to ::octave_rl_readline\n\twith {BEGIN,END}_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE.\n\n2005-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (MATRIX_INC): Remove oct-spparms.h from the list.\n\n2005-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DISTFILES): Don't include $(UMFPACK_EXTRAS).\n\t(DISTDIRS): Don't include UMFPACK.\n\t(LIBOCTAVE_OBJECTS): Don't include $(UMFPACK_OBJ).\n\t(UMFPACK_SPECIAL_1, UMFPACK_SPECIAL): No need for special include\n\tflags for these files.\n\tDon't include include $(srcdir)/UMFPACK.files.\n\tDon't include include $(srcdir)/UMFPACK.rules.\n\n\t* UMFPACK.README, UMFPACK.files, UMFPACK.patch, UMFPACK.rules:\n\tDelete files.\n\t* UMFPACK: Delete directory tree.\n\n\t* dSparse.cc: Include <umfpack/umfpack.h> instead of just \"umfpack.h\".\n\t* CSparse.cc: Likewise.\n\t* SparsedbleLU.cc: Likewise.\n\t* SparseCmplxLU.cc: Likewise.\n\n2005-03-14  David Bateman  <dbateman@free.org>\n\n\t* CSParse.cc, SparseCmplxLU.cc, SparsedbleLU.cc, dSparse.cc:\n\tAllow compilation to succeed if UMFPACK is not available.\n\n2005-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (bin-dist): Delete target.\n\t(BINDISTLIBS, BINDISTFILES): Delete variables.\n\n2005-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* ODESSA.h, ODESSA.cc, ODESSA-opts.in: Delete.\n\t* Makefile.in: Remove them from the lists.\n\n2005-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (LINK_DEPS): Remove -lglob from the list.\n\n2005-02-27  David Bateman  <dbateman@free.org>\n\n\t* Sparse.cc (Sparse<T>::reshape): Set cidx for the N last elements\n\tin the sparse matrix.\n\n2005-02-25  John W. Eaton  <jwe@octave.org>\n\n\tSparse merge.\n\n\t2005-02-13  David Bateman  <dbateman@free.fr>\n\n\t* CSparse.cc (SparseComplexMatrix:dsolve, SparseComplexMatrix:utsolve,\n\tSparseComplexMatrix::ltsolve, SparseComplexMatrix::trisolve,\n\tSparseComplexMatrix::bsolve, SparseComplexMatrix:fsolve): Split sparse\n\tsolver into separate functions for the diagonal, upper, lower\n\ttriangular, tridiagonal, banded and full cases.\n\t(SparseComplexMatrix::solve): rewrite to call the above function. One\n\tversion that probes the matrix type and another that assumes the type\n\tis passed.\n\n\t* dSparse.cc (SparseMatrix:dsolve, SparseMatrix:utsolve,\n\tSparseMatrix::ltsolve, SparseMatrix::trisolve,\n\tSparseMatrix::bsolve, SparseMatrix:fsolve): Likewise\n\t(SparseMatrix::solve): Likewise\n\n\t* CSparse.h (dsolve, utsolve, ltsolve, trisolve, bsolve, fsolve):\n\tDeclaration of new functions\n\t* dSparse.h (dsolve, utsolve, ltsolve, trisolve, bsolve, fsolve):\n\tLikewise\n\n\t* CSparse.cc (operator !): Reverse the sense of the test.\n\t* dSpase.cc (operator !): Likewise\n\n\t* dSparse.h (type, band_size, is_dense, triangular_row_perm,\n\ttriangular_col_perm, sparse_info): Remove matrix type code\n\t* CSparse.h (type, band_size, is_dense, triangular_row_perm,\n\ttriangular_col_perm, sparse_info): Likewise\n\t* boolSparse.h (type, band_size, is_dense, triangular_row_perm,\n\ttriangular_col_perm, sparse_info): Likewise\n\t* MSparse.h (type, band_size, is_dense, triangular_row_perm,\n\ttriangular_col_perm, sparse_info): Likewise\n\t* Sparse.h (type, band_size, is_dense, triangular_row_perm,\n\ttriangular_col_perm, sparse_info, matrix_type): Likewise\n\n\t* Sparse.cc (type, sparse_info, band_size): Remove type code\n\n\t* SparseType.h: New class for the matrix type used in solvers\n\t* SparseType.cc: methods of sparse matrix type class\n\n\t* Makefile.in: Add SparseType.cc\n\n\t2005-02-01  David Bateman  <dbateman@free.fr>\n\n\t* UMFPACK: Update to version 4.4\n\t* UMFPACK.patch: Version 4.4 contains most of the previous patch. Only\n\tkeep octave specific test files\n\n\t2005-01-23  David Bateman  <dbateman@free.fr>\n\n\t* dSparse.cc (SparseMatrix::solve): Include tridiagonal, cholesky\n\ttridiagonal and banded cholesky solvers. Remove calculation of\n\tcondition number for banded solvers.\n\t* CSparse.cc (SparseComplexMatrix::solve): ditto.\n\n\t* Sparse.h (int type (int) const, bool is_dense (void) const):\n\tnew functions.\n\t* MSparse.h (int type (int) const, bool is_dense (void) const): ditto\n\t* dSparse.h (int type (int) const, bool is_dense (void) const): ditto\n\t* CSparse.h (int type (int) const, bool is_dense (void) const): ditto\n\t* boolSparse.h (int type (int) const, bool is_dense (void) const):\n\tditto\n\n\t* Sparse.cc (int Sparse<T>::type (int) const,\n\tbool Sparse<T>::is_dense (void) const): New functions definition\n\n\t* Sparse.h (matrix_type typ): Move caching of matrix type to SparseRep,\n\tso it actually is cached, but disable\n\n\t* oct-spparms.cc (SparseParams::init_keys): Change spmoni to spumoni\n\tfor compatiability\n\n\t2005-01-18  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc (Array<T>::insert (const Array<T>&, const Array<int>&)):\n\tModify calculation of number elements to skip between copied blocks.\n\n\t2005-01-07  David Bateman  <dbateman@free.fr>\n\n\t* Sparse.h : Reverse definitions of numel and nelem.\n\t* Sparse.cc (assign1): Use numel and not nelem\n\t* Sparse-op-def.h: Replace all uses of nelem with numel\n\n\t2005-01-07  David Bateman  <dbateman@free.fr>\n\n\t* dbleDET.h: Make SparseMatrix a friend of the class DET\n\t* CmplexDET.h: Make SparseComplexMatrix a friend of the class\n\tComplexDET\n\t* dSparse.cc (SparseMatrix::determinant): Replace use of SparseDET\n\tby DET\n\t* dSparse.h (determinant): ditto\n\t* CSparse.cc (SparseComplexMatrix::determinant): Replace use of\n\tSparseComplexDET by ComplexDET\n\t* CSparse.h (determinant): ditto\n\t* SparsedbleDET.h, SparsedbleDET.cc, SparseCmplxDET.h,\n\tSparseCmplxDET.cc: delete files\n\t* Makefile.in: Delete reference to SparsedbleDET.h, SparsedbleDET.cc,\n\tSparseCmplxDET.h andSparseCmplxDET.cc.\n\n\t* CSparse.cc (SparseComplexMatrix::solve): Store matrix type in\n\tlocal variable to avoid variable shadowing.\n\t* dSparse.cc (SparseMatrix::solve): ditto.\n\n\t* boolSparse.cc boolSparse.h CSparse.cc CSparse.h dSparse.cc\n\tdSparse.h MSparse.cc MSparse-C.cc MSparse-d.cc MSparse-defs.h\n   \tMSparse.h oct-spparms.cc oct-spparms.h Sparse-b.cc Sparse.cc\n\tSparse-C.cc SparseCmplxLU.cc SparseCmplxLU.h SparsedbleLU.cc\n\tSparsedbleLU.h Sparse-d.cc Sparse.h Sparse-op-defs.h sparse-sort.cc\n\tsparse-sort.h: Remove additional licensing clause with authors\n\tpermission.\n\n\t2004-12-30  John W. Eaton  <jwe@octave.org>\n\n\t* MSparse.cc (SPARSE_A2S_OP_2, SPARSE_SA2_OP_2):\n\tLoop counter is int, not size_t.\n\n\t* oct-spparms.cc (SparseParams::operator =): Return *this.\n\n\t* Sparse-op-defs.h (SPARSE_SPARSE_MUL): Delete unused variable tmpval.\n\n\t* dSparse.cc (operator << (ostream&, const SparseMatrix&), atan2):\n\tDelete unused variables.\n\t(SparseMatrix::solve): Avoid warnings about uninitialized\n\tvariables and variables that might be clobbered by longjmp.\n\n\t* CSparse.cc (operator << (ostream&, const SparseComplexMatrix&),\n\tmin, max): Delete unused variables.\n\t(SparseComplexMatrix::solve): Avoid warnings about uninitialized\n\tvariables and variables that might be clobbered by longjmp.\n\n\t* Makefile.in (UMFPACK_SPECIAL): Include .d files in the list.\n\n\t* Sparse-op-defs.h (SPARSE_SMS_BIN_OP_2, SPARSE_SSM_BIN_OP_2):\n\tLoop counter is int, not size_t.\n\n\t* CSparse.cc (SparseComplexMatrix::hermitian): Avoid shadow warnings.\n\t* Sparse.cc (Sparse<T>::Sparse, Sparse<T>::type, assign): Likewise.\n\n\t* Sparse.h (Sparse::SparseRep): Order data members and initializer\n\tlists consistently.\n\n\t* mx-base.h: Include boolSparse.h, dSparse.h, and CSparse.h.\n\n\t2004-12-29  John W. Eaton  <jwe@octave.org>\n\n\t* COLAMD.files (COLAMD_EXTRAS): New variable.\n\t* UMFPACK.files (UMFPACK_EXTRAS): New variable.\n\t* Makefile.in (DISTFILES): Add $(COLAMD_EXTRAS) and\n\t$(UMFPACK_EXTRAS) to the list.\n\t(DISTDIRS): New variable.\n\t(dist): Handle $(DISTDIRS).\n\n\tMerge of sparse code from David Bateman <dbateman@free.fr> and\n\tAndy Adler <adler@site.uottawa.ca>.\n\n\t* Makefile.in (VPATH): ADD @srcdir@/COLAMD to the list.\n\n\t* Makefile.in (MAKEDEPS): Include $(COLAMD_SRC) and $(UMFPACK_SRC)\n\twithout directory prefix.\n\n\t* Makefile.in (LIBOCTAVE_OBJECTS): Add $(COLAMD_OBJ) and\n\t$(UMFPACK_OBJ) to the list.\n\n\t* COLAMD: New directory.\n\t* COLAMD.files: New file.\n\t* Makefile.in: Include COLAMD.files.\n\t(SOURCES): Add $(COLAMD_SOURCES) to the list.\n\t(LIBOCTAVE_OBJECTS): Add $(COLAMD_OBJECTS) to the list.\n\t(INCLUDES): Add $(COLAMD_INCLUDES) to the list.\n\n\t* UMFPACK: New directory.\n\t* UMFPACK.patch, UMFPACK.README, UMFPACK.files, UMFPACK.rules:\n\tNew files.\n\t* Makefile.in: Include UMFPACK.files and UMFPACK.rules.\n\t(SOURCES): Add $(UMFPACK_SOURCES) to the list.\n\t(LIBOCTAVE_OBJECTS): Add $(UMFPACK_OBJECTS) to the list.\n\t(INCLUDES): Add $(UMFPACK_INCLUDES) to the list.\n\n\t* Makefile.in (SPARSE_MX_OP_INC): New variable.\n\t(INCLUDES): Add it to the list.\n\t(SPARSE_MX_OP_SRC): New variable.\n\t(LIBOCTAVE_CXX_SOURCES): Add it to the list.\n\t(distclean): Remove $(SPARSE_MX_OP_INC) and $(SPARSE_MX_OP_SRC).\n\t(stamp-prereq): Depend on $(SPARSE_MX_OP_INC) and $(SPARSE_MX_OP_SRC).\n\n\t* sparse-mk-ops.awk, sparse-mx-ops: New files.\n\t* Makefile.in (DISTFILES): Add them to the lists.\n\n\t* oct-spparms.h, sparse-sort.h: New files.\n\t* Makefile.in (INCLUDES): Add them to the list.\n\n\t* oct-spparms.cc, sparse-sort.cc: New files.\n\t* Makefile.in (LIBOCTAVE_CXX_SOURCES): Add them to the list.\n\n\t* sparse-base-lu.cc: New file.\n\t* Makefile.in (TEMPLATE_SRC): Add it to the list.\n\n\t* boolSparse.cc, CSparse.cc, dSparse.cc, MSparse.cc, Sparse.cc,\n\tSparseCmplxDET.cc, SparseCmplxLU.cc, SparsedbleDET.cc,\n\tSparsedbleLU.cc: New files.\n\t* Makefile.in (MATRIX_SRC): Add them to the list.\n\n\t* boolSparse.h, CSparse.h, dSparse.h, MSparse-defs.h, MSparse.h,\n\tSparse.h, oct-spparms.h, sparse-base-lu.h, SparseCmplxDET.h,\n\tSparseCmplxLU.h, SparsedbleDET.h, SparsedbleLU.h,\n\tSparse-op-defs.h: New files.\n\t* Makefile.in (MATRIX_INC): Add them to the appropriate lists.\n\n\t* MSparse-d.cc, MSparse-C.cc, Sparse-b.cc, Sparse-d.cc,\n\tSparse-C.cc: New files.\n\t* Makefile.in (TI_SRC): Add them to the list.\n\n2005-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc (file_ops::canonicalize_file_name) [HAVE_RESOLVEPATH]:\n\tPass current directory to octave_env::make_absolute.\n\tSave value returned from octave_env::make_absolute in local var.\n\tPass const char*, not std::string as first arg of resolvepath.\n\tProvide decl for resolved_len.\n\n2005-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::permute): Allow permutation vector longer\n\tthan number of dimenensions of permuted matrix.\n\n\t* Array.cc (Array<T>::permute): Use zero-based indexing for perm_vec.\n\t* Array-util.cc (calc_permutated_idx): Likewise.\n\n2005-02-10  David Bateman  <dbateman@free.fr>\n\n\t* CNDArray.cc (ComplexNDarray::operator !): Change sense of test.\n\t* CMatrix.cc (ComplexMatrix::operator !): Likewise.\n\n2005-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* file-ops.cc (file_ops::canonicalize_file_name): New functions.\n\t* file-ops.h: Provide decls.\n\n\t* kpse.cc (kpse_tilde_expand): Simply return NAME if it is empty.\n\n2005-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* Array-util.cc (freeze): Improve error message.\n\n2005-01-26  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc (Array<T>::insert): Handle generic case, not just\n\tspecial case for fast concatenation.\n\n2005-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* mx-inlines.cc (MX_ND_REDUCTION): Delete RET_ELT_TYPE arg.\n\tChange all uses.  Use VAL instead of RET_ELT_TYPE when resizing.\n\n\t* dNDArray.cc (NDArray::any): NaN does not count as a nonzero value.\n\t* CNDArray.cc (ComplexNDArray::any): Likewise.\n\n2005-01-18  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc (Array<T>::insert (const Array<T>&, const Array<int>&)):\n\tModify calculation of number elements to skip between copied blocks.\n\n2005-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* idx-vector.cc (IDX_VEC_REP::freeze): Call warning handler, not\n\terror handler, to warn about resizing.\n\n2004-12-27  Martin Dalecki  <martin@dalecki.de>\n\n\t* Array.cc, ArrayN.cc, base-lu.cc, boolMatrix.cc, boolNDArray.cc,\n\tBounds.cc, CColVector.cc, CDiagMatrix.cc, chMatrix.cc,\n\tchNDArray.cc, CMatrix.cc, CmplxAEPBAL.cc, CmplxCHOL.cc,\n\tCmplxDET.cc, CmplxHESS.cc, CmplxLU.cc, CmplxQR.cc, CmplxQRP.cc,\n\tCmplxSCHUR.cc, CmplxSVD.cc, CNDArray.cc, CollocWt.cc,\n\tCRowVector.cc, DASPK.cc, DASRT.cc, DASSL.cc, dbleAEPBAL.cc,\n\tdbleCHOL.cc, dbleDET.cc, dbleHESS.cc, dbleLU.cc, dbleQR.cc,\n\tdbleQRP.cc, dbleSCHUR.cc, dbleSVD.cc, dColVector.cc,\n\tdDiagMatrix.cc, DiagArray2.cc, dMatrix.cc, dNDArray.cc,\n\tdRowVector.cc, EIG.cc, FEGrid.cc, idx-vector.cc, int16NDArray.cc,\n\tint32NDArray.cc, int64NDArray.cc, int8NDArray.cc, intNDArray.cc,\n\tLinConst.cc, LPsolve.cc, LSODE.cc, MArray2.cc, MArray.cc,\n\tMArrayN.cc, MDiagArray2.cc, NLEqn.cc, oct-alloc.cc, ODES.cc,\n\tODESSA.cc, Quad.cc, Range.cc, so-array.cc, uint16NDArray.cc,\n\tuint32NDArray.cc, uint64NDArray.cc, uint8NDArray.cc:\n\tDelete #pragma implementation.\n\n\t* Array2.h, Array3.h, Array.h, ArrayN.h, base-lu.h, boolMatrix.h,\n\tboolNDArray.h, Bounds.h, CColVector.h, CDiagMatrix.h, chMatrix.h,\n\tchNDArray.h, CMatrix.h, CmplxAEPBAL.h, CmplxCHOL.h, CmplxDET.h,\n\tCmplxHESS.h, CmplxLU.h, CmplxQR.h, CmplxQRP.h, CmplxSCHUR.h,\n\tCmplxSVD.h, CNDArray.h, CollocWt.h, CRowVector.h, DASPK.h,\n\tDASRT.h, DASSL.h, dbleAEPBAL.h, dbleCHOL.h, dbleDET.h, dbleHESS.h,\n\tdbleLU.h, dbleQR.h, dbleQRP.h, dbleSCHUR.h, dbleSVD.h,\n\tdColVector.h, dDiagMatrix.h, DiagArray2.h, dim-vector.h,\n\tdMatrix.h, dNDArray.h, dRowVector.h, EIG.h, FEGrid.h,\n\tidx-vector.h, int16NDArray.h, int32NDArray.h, int64NDArray.h,\n\tint8NDArray.h, intNDArray.h, LinConst.h, LPsolve.h, LSODE.h,\n\tMArray2.h, MArray.h, MArrayN.h, MDiagArray2.h, NLConst.h, NLEqn.h,\n\tODES.h, ODESSA.h, Quad.h, Range.h, so-array.h, uint16NDArray.h,\n\tuint32NDArray.h, uint64NDArray.h, uint8NDArray.h:\n\tDelete #pragma interface.\n\n2004-12-17  John W. Eaton  <jwe@octave.org>\n\n\t* lo-cieee.c (lo_ieee_signbit): New function.\n\t* lo-ieee.h: Provide decl.\n\tDon't define lo_ieee_signbit as a macro here.\n\tFrom Orion Poplawski <orion@cora.nwra.com>.\n\n2004-11-18  John W. Eaton  <jwe@octave.org>\n\n\t* int32NDArray.cc (pow): Delete instantiation.\n\t* int16NDArray.cc (pow): Likewise.\n\t* int8NDArray.cc (pow): Likewise.\n\t* uint32NDArray.cc (pow): Likewise.\n\t* uint16NDArray.cc (pow): Likewise.\n\t* uint8NDArray.cc (pow): Likewise.\n\n2004-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* kpse.cc (str_llist_float, str_llist_add, kpse_var_expand):\n\tNow static.\n\t(DB_ENVS, DB_HASH_SIZE, DB_NAME, ALIAS_NAME, ALIAS_HASH_SIZE,\n\tDEFAULT_TEXMFDBS): Delete unused macros.\n\n\t* Array.cc (Array<T>::index): Call generic N-d indexing function\n\tif idx_arg is N-d.\n\n2004-11-09  David Bateman  <dbateman@free.fr>\n\n\t* dNDArray.cc (concat): Delete.\n\t(NDArray::concat): New methods.\n\t* dNDArray.h: Provide decls.\n\n\t* CNDArray.cc (concat): Delete.\n\t(ComplexNDArray::concat): New methods.\n\t* CNDArray.h: Provide decls.\n\n\t* boolNDArray.cc (concat): Delete.\n\t(boolNDArray::concat): New methods.\n\t* boolNDArray.h: Provide decls.\n\n\t* chNDArray.cc (concat): Delete.\n\t(charNDArray::concat): New methods.\n\t* chNDArray.h: Provide decls.\n\n\t* oct-inttypes.h (OCTAVE_INT_CONCAT_FN, OCTAVE_INT_CONCAT_DECL):\n\tDelete macros.\n\n\t* int8NDArray.h, int16NDArray.h, int32NDArray.h, int64NDArray.h,\n\tuint8NDArray.h, uint16NDArray.h, uint32NDArray.h, uint64NDArray.h\n\t(OCTAVE_INT_CONCAT_DECL): Delete use of macro.\n\n\t* int8NDArray.cc, int16NDArray.cc, int32NDArray.cc, int64NDArray.cc,\n\tuint8NDArray.cc, uint16NDArray.cc, uint32NDArray.cc, uint64NDArray.cc\n\t(OCTAVE_INT_CONCAT_FN): Delete use of macro.\n\n\t* intNDArray.cc (intNDArray<T>::concat): New method.\n\t* intNDArray.h: Provide decl.\n\n2004-11-08  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.cc: New file.\n\t* Makefile.in (TI_SRC): Add it to the list.\n\t* oct-inttypes.h (OCTAVE_US_TYPE1_CMP_OP, OCTAVE_US_TYPE1_CMP_OPS,\n\tOCTAVE_SU_TYPE1_CMP_OP, OCTAVE_SU_TYPE1_CMP_OPS,\n\tOCTAVE_TYPE1_CMP_OPS, OCTAVE_US_TYPE2_CMP_OP,\n\tOCTAVE_US_TYPE2_CMP_OPS, OCTAVE_SU_TYPE2_CMP_OP,\n\tOCTAVE_SU_TYPE2_CMP_OPS, OCTAVE_TYPE2_CMP_OPS):\n\tNew macros for comparison operations.  Avoid potential\n\tproblems with default conversions when comparing signed and\n\tunsigned values.\n\n2004-11-03  John W. Eaton  <jwe@octave.org>\n\n\t* dMatrix.cc (Matrix::inverse): Return info == -1 for any failure.\n\t* CMatrix.cc (ComplexMatrix::inverse): Likewise.\n\n2004-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assignN): Avoid resizing if assignment will fail.\n\n2004-10-18  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assign2): Save result of squeeze operation.\n\tSqueeze if ndims is > 2, not if length of RHS vector is > 2.\n\n2004-10-11  David Bateman  <dbateman@free.fr>\n\n\t* oct-fftw.cc (class octave_fftw_planner): Add inplace[2] to\n\tflag whether transform in- or out-of-place.\n\t(octave_fftw_planner::octave_fftw_planner): Initialize it.\n\t(octave_fftw_planner::create_plan): Use it.\n\n2004-09-24  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (assign2, assignN): If index is empty, allow RHS to be\n\tany empty matrix, not just [].\n\n2004-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* mx-ops: Include scalar zero value in type definitions.\n\tDelete zero information from ops section.\n\t* mk-ops.awk: Use type-specific zero info.\n\n\t* mx-op-defs.h (MS_BOOL_OP, SM_BOOL_OP, MM_BOOL_OP, NDS_BOOL_OP,\n\tSND_BOOL_OP, NDND_BOOL_OP): Args now include zero values for both\n\tLHS and RHS.\n\t(MS_BOOL_OPS2, SM_BOOL_OPS2, MM_BOOL_OPS2, NDS_BOOL_OPS2,\n\tSND_BOOL_OPS2, NDND_BOOL_OPS2): New macros.\n\t(MS_BOOL_OPS, SM_BOOL_OPS, MM_BOOL_OPS, NDS_BOOL_OPS,\n\tSND_BOOL_OPS, NDND_BOOL_OPS): Define in terms of 2-zero versions.\n\n\t* idx-vector.h (idx_vector::idx_vector_rep::idx_vector_rep (const\n\tintNDArray<U>&)): Use explicit as_double () conversion in call to\n\ttree_to_mat_idx.\n\n\t* oct-inttypes.h (octave_int<T>::operator float): New conversion.\n\t(pow): Instead of \"if (b_val)\", use \"if (b_val != zero)\".\n\tLikewise for the \"if (b_val & one)\" test.\n\t(operator <<, operator >>): Type of retval is octave_int<T1>, not T1.\n\n2004-09-23  David Bateman  <dbateman@free.fr>\n\n\t* oct-inttypes.h (OCTAVE_INT_DOUBLE_CMP_OP, OCTAVE_DOUBLE_INT_CMP_OP):\n\tNew macros.  Use them to define mixed intX-double and double-intX ops.\n\n2004-09-22  Federico Zenith  <zenith@chemeng.ntnu.no>\n\n\t* DASPK-opts.in, DASRT-opts.in, ODESSA-opts.in:\n\tFix doc string layout to avoid overfull hbox in printed output.\n\n2004-09-21  John W. Eaton  <jwe@octave.org>\n\n\t* mach-info.h (octave_mach_info::flt_fmt_native): Delete.\n\t* mach-info.cc (octave_mach_info::string_to_float_format):\n\tFor \"native\", set actual native format.\n\t(octave_mach_info::float_format_as_string): Delete flt_fmt_native case.\n\n2004-09-17  David Bateman  <dbateman@free.fr>\n\n\t* CmplxSCHUR.cc (CmplxSCHUR::init): New arg, calc_unitary to make the\n\tcalculation of the unitary matrix optional.\n\t* dbleSCHUR.cc (SCHUR::init): Ditto.\n\t* CmplxSCHUR.h, dbleSCHUR.h: Update decls.\n\n2004-09-15  David Bateman  <dbateman@free.fr>\n\n\t* oct-sort.h (octave_sort<T>::set_compare (bool (*comp) (T, T))):\n\tNew function to set the comparison function for the sort.\n\n2004-09-10  John W. Eaton  <jwe@octave.org>\n\n\t* lo-mappers.cc (xround): Fix typo.\n\n2004-09-08  John W. Eaton  <jwe@octave.org>\n\n\t* Array.h (Array::~Array): Declare virtual.\n\n\t* idx-vector.h (idx_vector::idx_vector): Initialize rep in member\n\tinitializaion list.  Don't set rep->count since the rep\n\tconstructor does that.\n\n2004-09-07  John W. Eaton  <jwe@octave.org>\n\n\t* data-conv.cc (oct_data_conv::string_to_data_type): Handle dt_logical.\n\t(oct_data_conv::data_type_as_string): Likewise.\n\n\t* data-conv.h (oct_data_conv::data_type): Add dt_logical to list.\n\n\t* Range.cc (round): Delete unused function.\n\n\t* lo-mappers.cc (xround): Rename from round.  Change all uses.\n\tIf HAVE_ROUND, call round, otherwise fake with floor and ceil.\n\n\t* oct-inttypes.h: Include <cmath> here.\n\n2004-09-03  David Bateman  <dbateman@free.fr>\n\n\t* boolNDArray.cc (boolNDArray::concat, boolNDArray::insert):\n\tNew functions for boolean matrix concatenation.\n\t* boolNDArray.h: Provide decls.\n\n2004-09-03  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttpes.h (OCTAVE_INT_CMP_OP): Convert operarands to double\n\tto avoid signed/unsigned int comparison problems.\n\n\t* mx-ops: Generate CMP and BOOL ops for mixed integer types and\n\tfor mixed integer and double types.\n\n\t* mk-ops.awk: Output BIN_OP_DECLS, CMP_OP_DECLS, and BOOL_OP_DECLS\n\tseparately, and only if needed.\n\n\t* oct-inttypes.h (octave_fit_to_range): Use constructor instead of\n\tstatic_cast for type conversion.\n\n2004-09-01  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (pow, operator +, operator -, operator *,\n\toperator /): Handle mixed integer/double ops.  If op generates a\n\tNaN, set result to 0.\n\t(octave_int::operator - (void)): Convert to double, then negate,\n\tthen fit to range.\n\n\t* mx-ops: Define integer types.  Include declarations for mixed\n\tinteger/double ops.\n\n2004-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (pow): Args now const reference.\n\t(octave_int<T>::operator *=, octave_int<T>::operator /=,\n\toctave_int<T>::operator <<=, octave_int<T>::operator >>=):\n\tNew member functions.\n\t(OCTAVE_INT_BITSHIFT_OP): Delete macro.\n\t(operator >> (const octave_int<T1>& x, const T2& y)):\n\tDefine in terms of >>=.\n\t(operator << (const octave_int<T1>& x, const T2& y)):\n\tDefine in terms of <<=.\n\t(bitshift): Operate on octave_int<T> objects, not the values, so\n\twe get proper saturation properties.\n\n2004-08-31  David Bateman  <dbateman@free.fr>\n\n\t* oct-inttypes.h (pow (constT, T)): New template.\n\n\t* int8NDArray.cc, int16NDArray.cc, int32NDArray.cc, uint8NDArray.cc,\n\tuint16NDArray.cc, uint32NDArray.cc: Instantiate power function.\n\n2004-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (octave_int::byte_size): New function.\n\n2004-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (EXTRAS): Add intNDArray.cc to the list.\n\n\t* data-conv.h (oct_data_conv::data_type): Include sized types.\n\tExplicitly number enum elements.\n\n\t* data-conv.cc (oct_data_conv::string_to_data_type (const\n\tstd::string&, int&, oct_data_conv::data_type&,\n\toct_data_conv::data_type&)): New function.\n\t(oct_data_conv::string_to_data_type (const std::string&, int&,\n\toct_data_conv::data_type&)): New function.\n\t(oct_data_conv::data_type_as_string): New function.\n\n\t* dMatrix.cc (read_int, do_read, Matrix::read): Delete.\n\t(write_int, do_write, Matrix::write): Delete.\n\t* dMatrix.h (Matrix::read, Matrix::write): Delete decls.\n\n\t* byte-swap.h: Use template functions and specialization.\n\tChange all uses.\n\t(swap_2_bytes, swap_4_bytes, swap_8_bytes): Delete.\n\n2004-08-30  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (octave_int_fit_to_range): Use template\n\tspecializations to avoid warnings about signed/unsigned comparisons.\n\n2004-08-28  John W. Eaton  <jwe@octave.org>\n\n\t* data-conv.cc (do_float_format_conversion (unsigned char *,\n\tsize_t, int, oct_mach_info::float_format)): New function.\n\t(GET_SIZED_INT_TYPE): New macro.\n\t(string_to_data_type): Use it to return sized types corresponding\n\tto Octave array data types.\n\t(strip_spaces): New function.\n\t(do_double_format_conversion, do_float_format_conversion): Pass\n\tfrom_fmt and to_fmt.  Don't always assume the to_fmt is the native\n\tfloat format.\n\t(do_double_format_conversion,\n\tIEEE_big_double_to_IEEE_little_double,\n\tVAX_D_double_to_IEEE_little_double,\n\tVAX_G_double_to_IEEE_little_double, Cray_to_IEEE_little_double,\n\tIEEE_little_double_to_IEEE_big_double,\n\tVAX_D_double_to_IEEE_big_double, VAX_G_double_to_IEEE_big_double,\n\tCray_to_IEEE_big_double, IEEE_little_double_to_VAX_D_double,\n\tIEEE_big_double_to_VAX_D_double, VAX_G_double_to_VAX_D_double,\n\tCray_to_VAX_D_double, IEEE_little_double_to_VAX_G_double,\n\tIEEE_big_double_to_VAX_G_double, VAX_D_double_to_VAX_G_double,\n\tCray_to_VAX_G_double):\n\tPass data as void*, not double*.\n\t(do_float_format_conversion, IEEE_big_float_to_IEEE_little_float,\n\tVAX_D_float_to_IEEE_little_float,\n\tVAX_G_float_to_IEEE_little_float, Cray_to_IEEE_little_float,\n\tIEEE_little_float_to_IEEE_big_float,\n\tVAX_D_float_to_IEEE_big_float, VAX_G_float_to_IEEE_big_float,\n\tCray_to_IEEE_big_float, IEEE_little_float_to_VAX_D_float,\n\tIEEE_big_float_to_VAX_D_float, VAX_G_float_to_VAX_D_float,\n\tCray_to_VAX_D_float, IEEE_little_float_to_VAX_G_float,\n\tIEEE_big_float_to_VAX_G_float, VAX_D_float_to_VAX_G_float,\n\tCray_to_VAX_G_float):\n\tPass data as void*, not float*.\n\n2004-08-27  John W. Eaton  <jwe@octave.org>\n\n\t* byte-swap.h (swap_bytes): New template versions, with\n\tspecializations.\n\t(swap_2_bytes, swap_4_bytes, swap_8_bytes): Delete.\n\tChange all uses.\n\n2004-08-24  David Bateman  <dbateman@free.fr>\n\n\t* chNDArray.cc (concat): Check whether matrix to be inserted is\n\tempty instead of checking final matrix.\n\t* dNDArray.cc (concat): Likewise.\n\t* CNDArray.cc (concat): Likewise.\n\n2004-08-23  David Bateman  <dbateman@free.fr>\n\n\t* dim-vector.h (dim_vector::concat): Correct incrementation for\n\tnon-existent dimensions.\n\n2004-08-09  John W. Eaton  <jwe@octave.org>\n\n\t* idx-vector.h (idx_vector::idx_vector_rep::tree_to_mat_idx\n\t(const octave_int<U>&)): New member function.\n\t(idx_vector::idx_vector_rep::tree_to_mat_idx (double, bool&),\n\tidx_vector::idx_vector_rep::tree_to_mat_idx (int)):\n\tNow member functions instead of static in idx-vector.cc.\n\t(idx_vector::idx_vector_rep::idx_vector_rep (const octave_int<U>&),\n\tidx_vector::idx_vector_rep::idx_vector_rep (const intNDArray<U>&)):\n\tNew template constructors.\n\n2004-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* EIG.cc (EIG::init): Add volatile qualifier to nvr decl.\n\n\t* intNDArray.cc (intNDArray<T>::operator !, intNDArray<T>::all,\n\tintNDArray<T>::any): Sprinkle with this-> as needed.\n\t* mx-inlines.cc (MX_ND_REDUCTION, MX_ND_CUMULATIVE_OP): Likewise.\n\n2004-08-03  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::squeeze): Do nothing for 2-d arrays.  For\n\tarrays with more than two dimensions and only one non-singleton\n\tdimension, return a column vector.\n\n2004-07-28  John W. Eaton  <jwe@octave.org>\n\n\t* oct-cmplx.h (pow (const Complex&, const double&):\n\tConvert second arg to complex to avoid libstdc++ bug.\n\n2004-07-27  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (bitshift): New arg, MASK.\n\t(OCTAVE_INT_BITSHIFT_OP): Bitshift does not saturate.\n\n2004-07-23  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc (Array<T>::reshape): Return *this if no change in size.\n\n2004-07-23  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc, Array.h (cat_ra): Delete.\n\t* Array.h, Array-C.cc, Array-d.cc, Array-ch.cc, Array-i.cc\n\t(INSTANTIATE_ARRAY_CAT): Delete.\n\n\t* dNDArray.cc, dNDArray.h, CNDArray.cc, CNDArray.h, chNDArray.cc,\n\tchNDArray.h, intNDArray.cc, intNDArray.h (cat): Delete.\n\n\t* Array.cc (Array<T>::insert): Copy data in NDArray version.\n\n\t* dNDArray.cc, dNDArray.h, CNDArray.cc, CNDArray.h, chNDArray.cc,\n\tchNDArray.h (concat): New function used for concatenation that does\n\tan indexed copy of one array into another.\n\n\t* dim-vector.h (concat): New function to concatenate dim_vectors.\n\n\t* dNDArray.cc, dNDArray.h, CNDArray.cc, CNDArray.h, chNDArray.cc,\n\tchNDArray.h, intNDArray.cc, intNDArray.h (insert): New function for\n\tinsertion of one NDArray into another.\n\n\t* oct-inttype.cc (OCTAVE_INT_CONCAT_FN, OCTAVE_INT_CONCAT_DECL): New\n\tmacros to define the int/uint concatenation functions.\n\n\t* uint8NDArray.cc, uint16NDArray.cc, uint32NDArray.cc, uint64NDArray.cc\n\tint8NDArray.cc, int16NDArray.cc, int32NDArray.cc, int64NDArray.cc\n\t(OCTAVE_INT_CONCAT_FN): Instantiate the concatenation function .\n\n\t* uint8NDArray.h, uint16NDArray.h, uint32NDArray.h, uint64NDArray.h\n\tint8NDArray.h, int16NDArray.h, int32NDArray.h, int64NDArray.h\n\t(OCTAVE_INT_CONCAT_DECL): Declare the int/uint concatentaion\n\tfunctions.\n\n2004-07-22  David Bateman  <dbateman@free.fr>\n\n\t* oct-sort.h: Don't include oct-obj.h.\n\n\t* lo-specfun.cc (is_integer_value): New function.\n\t(zbesj, zbesi, zbesy): Special case negative integer or half\n\tinteger orders that cause overflow for small arguments.\n\n2004-07-12  John W. Eaton  <jwe@octave.org>\n\n\t* oct-inttypes.h (octave_int<T>::nbits): New function.\n\t(bitshift (const octave_int<T>&, int)): New function.\n\n2004-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* mx-base.h: Include headers for new int types.\n\n\t* dNDArray.h, dNDArray.cc (NDArray::NDArray (const boolNDArray&),\n\tNDArray::NDArray (const charNDArray&)): Delete.\n\t(template <class U> explicit NDArray (const intNDArray<U>&)): New\n\tconstructor.\n\t(NDArray::squeze): Call MArrayN::squeeze, not ArrayN::squeeze.\n\n\t* chMatrix.h (CharMatrix::transpose): New forwarding functions for\n\treturn type conversion.\n\n\t* ComplexNDArray.h, ComplexNDArray.cc\n\t(ComplexNDArray::ComplexNDArray (const ArrayN<Complex>&),\n\t(ComplexNDArray::ComplexNDArray (const NDArray&),\n\t(ComplexNDArray::ComplexNDArray (const boolNDArray&),\n\t(ComplexNDArray::ComplexNDArray (const charNDArray&)): Delete.\n\n\t(ComplexNDArray::squeze): Call MArrayN::squeeze, not ArrayN::squeeze.\n\n\t* MArrayN.h:\n\t(template <class U> explicit MArrayN<T>::MArrayN (const Array2<U>&),\n\t(template <class U> MArrayN<T>::MArrayN (const ArrayN<U>&),\n\t(template <class U> explicit MArrayN<T>::MArrayN (const MArray<U>&)):\n\tNew constructors.\n\t(ArrayN<T>::reshape, ArrayN<T>::permute, ArrayN<T>::ipermute,\n\tArrayN<T>::squeeze):\n\tNew forwarding functions for return type conversion.\n\n\t* ArrayN.h:\n\t(template <class U> explicit ArrayN<T>::ArrayN (const Array2<U>&),\n\t(template <class U> explicit ArrayN<T>::ArrayN (const ArrayN<U>&),\n\t(template <class U> explicit ArrayN<T>::ArrayN (const Array<U>&),\n\t(template <class U> explicit ArrayN<T>::ArrayN (const Array<U>&,\n\tconst dim_vector&)): New constructors.\n\t(ArrayN<T>::reshape, ArrayN<T>::permute, ArrayN<T>::ipermute,\n\tArrayN<T>::transpose):\n\tNew forwarding functions for return type conversion.\n\n\t* Array.h (template <class U> Array<T>::Array (const Array<U>&)):\n\tNew constructor.\n\t(Array<T>::coerce, Array<T>::byte_size): New functions.\n\n\t* Array-i.cc, MArray-i.cc: Instantiate new integer types.\n\n\t* oct-inttypes.h, int16NDArray.h, int32NDArray.h, int64NDArray.h,\n\tint8NDArray.h , intNDArray.h, uint16NDArray.h, uint32NDArray.h,\n\tuint64NDArray.h, uint8NDArray.h, int16NDArray.cc, int32NDArray.cc,\n\tint64NDArray.cc, int8NDArray.cc, intNDArray.cc, uint16NDArray.cc,\n\tuint32NDArray.cc, uint64NDArray.cc, uint8NDArray.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n2004-06-04  John W. Eaton  <jwe@octave.org>\n\n\t* mx-inlines.cc (MX_ND_REDUCTION): New arg, RET_ELT_TYPE.  Use\n\t\"RET_ELT_TYPE ()\" rather than \"false\" as fill value for retval\n\tresize op.  Change all uses.\n\n2004-06-03  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc (assignN): Allow magic colon for dimensions lvalue\n\tgreater than the existing number of dimensions in lvalue.\n\n2004-04-30  David Bateman  <dbateman@free.fr>\n\n\t* dim_vector.h (dim_vector::dim_vector_rep::dim_vector_rep):\n\tNew arg, fill_value.\n\t(dim_vector::resize): Allow optional fill_value argument.\n\n\t* Array.cc (Array<T>::index (Array<idx_vector>&, int, const T&)):\n\tDon't chop trailing dimensions of Array<idx_vector> if there is\n\tmore than one element in idx_vector.  Resize the return value to\n\tthe size of Array<idx_vector>.\n\n\t* Array-util.cc (short_freeze): Better freeze of last dimension of\n\tidx_vector that is shorter than a dim_vector.\n\n2004-04-23  John W. Eaton  <jwe@octave.org>\n\n\t* oct-sort.cc: Don't include oct-obj.h.\n\n2004-04-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::index2, Array<T>::indexN):\n\tDon't set invalid dimensions on return value.\n\n2004-04-21  John W. Eaton  <jwe@octave.org>\n\n\t* mx-inlines.cc (MX_ND_REDUCTION): Chop trailing singletons.\n\n2004-04-06  David Bateman  <dbateman@free.fr>\n\n\t* Array.cc (Array<T>::resize_no_fill (const dim_vector& dv),\n\tArray<T>::resize_and_fill (const dim_vector& dv, const T& val)):\n\tMake their behavior equivalent except for filling vs. not filling.\n\n  \t* oct-sort.cc: New template class for arbitrary sorting.\n  \t* oct-sort.h: Declaration of sort class.\n  \t* Makefile: Add them to the appropriate lists.\n\n2004-04-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mx-inlines.cc (MX_ND_CUMULATIVE_OP): Fix off-by-one error.\n\n2004-04-02  David Bateman  <dbateman@free.fr>\n\n\t* lo-specfun.cc (besselj, bessely, besseli, besselk, besselh1,\n\tbesselh2, airy, biry, betainc, gammainc, do_bessel):\n\tNew N-d array versions.\n\t(SN_BESSEL, NS_BESSEL, NN_BESSEL): New macros.\n\t* lo-specfun.h (besselj, bessely, besseli, besselk, besselh1,\n\tbesselh2, airy, biry, betainc, gammainc): Provide decls.\n\n\t* dNDArray.cc (NDArray::min, NDArray::max, min, max):\n\tNew functions.\n\t* dNDArray.h (NDArray::min, NDArray::max, min, max): Provide decls.\n\n\t* CNDArray.cc (ComplexNDArray::min, ComplexNDArray::max, min, max):\n\tNew functions.\n\t* CNDArray.h (ComplexNDArray::min, ComplexNDArray::max, min, max):\n\tProvide decls.\n\n2004-03-17  David Hoover  <jazzdaq@yahoo.com>\n\n\t* DASPK.cc (DASPK::do_integrate): Always add n*n elements to the\n\twork vector, not just when using a numerical Jacobian.\n\n2004-03-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* so-array.cc (SND_CMP_OP, NDS_CMP_OP, NDND_CMP_OP):\n\tOmit empty result args.\n\n\t* Array.cc (Array<T>::Array (const Array<T>&, const dim_vector&)):\n\tMove here from Array.h, check that size of array arg is not\n\tsmaller than the size defined by the new dimensions.\n\n2004-03-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::index2): Allow result to be N-d if indexing\n\ta scalar or vector with an N-d array.\n\n2004-03-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::index2): If scalar or vector is indexed by\n\tmatrix, return object that is the same size as the index.\n\n\t* mx-op-defs.h (NDND_CMP_OP, MM_CMP_OP): Require dimensions to agree.\n\tEliminate MT_RESULT args.  Return value is always size of args.\n\t(MS_CMP_OP, SM_CMP_OP, NDS_CMP_OP, SND_CMP_OP):\n\tEliminate EMPTY_RESULT arg.\n\tReturn value is always size of matrix or N-d array arg.\n\t(TBM, FBM, NBM): Delete unused macros.\n\n2004-03-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::maybe_delete_elements): Return immediately\n\tif all LHS dimensions are zero.  For one index case, freeze and\n\tsort idx_vec before checking length, and do nothing if\n\tnum_to_delete is zero.\n\t(Array<T>::maybe_delete_elements_2): Omit Fortran-indexing warning.\n\n2004-03-04  David Bateman  <dbateman@free.fr>\n\n\t* dNDArray.cc (NDArray::ifourier): Arg is int, not const int.\n\t* CNDArray.cc (ComplexNDArray::ifourier): Likewise.\n\n2004-03-03  Hans Ekkehard Plesser  <hans.ekkehard.plesser@nlh.no>\n\n\t* base-lu.cc (base_lu<>::L): Check bounds before setting diagonal\n\telement.\n\n2004-03-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Range.h (Range::Range): Add cache to member initialization list.\n\t(Range::clear_cache): New private function.\n\n\t* Range.h (Range::set_base, Range::set_limit, Range::set_inc):\n\tUse clear cache.  Don't do anything if range does not change.\n\t* Range.cc (Range::sort): Likewise.\n\n2004-03-02  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Range.cc (Range::matrix_value): Cache result.\n\t(Range::sort): Clear cache.\n\t* Range.h (Range::cache): New data member.\n\t(Range::set_base, Range::set_limit, Range::set_inc): Clear cache.\n\t(Range::print_range): Delete.\n\n2004-03-02  David Bateman  <dbateman@free.fr>\n\n\t* oct-fftw.cc: Only two versions of plan, and avoid endless\n\tchanges between them.  Faster for small fft's.\n\t(octave_fftw_planner::simd_align, octave_fftw_planner::rsimd_align):\n\tNew member variables.\n\t(octave_fftw_planner::ialign, octave_fftw_planner::oalign,\n\toctave_fftw_planner::rialign, octave_fftw_planner::roalign): Delete.\n\tChange all uses.\n\t(CHECK_SIMD_ALIGNMENT): New macro.\n\t(octave_fftw_planner::create_plan): Use it.\n\n2004-03-01  Petter Risholm  <risholm@idi.ntnu.no>\n\n\t* Array.cc (Array<T>::insertN): Eliminate N-d indexing.\n\n\t* mx-inlines.cc (MX_ND_CAT): Delete macro.\n\n\t* dNDArray.h, chNDArray.h, CNDArray.h (cat): Change declaration.\n\t* dNDArray.cc (NDArray<T>::cat): Call new form of cat function.\n\t* chNDArray.cc (charNDArray<T>::cat): Ditto.\n\t* CNDArray.cc (ComplexNDArray<T>::cat): Ditto.\n\n\t* Array.h (cat_ra): Return int.  Accept idx and move args, not add_dim.\n\t* Array.cc (cat_ra): Speed up implementation by avoiding N-d indexing.\n\n2004-02-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-rl-edit.c (octave_rl_set_startup_hook,\n\toctave_rl_get_startup_hook, octave_rl_set_event_hook,\n\toctave_rl_get_event_hook): Omit casts.\n\t* oct-rl-edit.h (rl_startup_hook_fcn_ptr, rl_event_hook_fcn_ptr):\n\tReturn value for function pointer typedef is now int.\n\t* cmd-edit.h (command_editor::startup_hook_fcn,\n\tcommand_editor::event_hook_fcn): Likewise.\n\t* cmd-hist.cc, cmd-hist.h (command_history::goto_mark,\n\tcommand_history::do_goto_mark, gnu_history::do_goto_mark):\n\tReturn type is now int.  Return 0.\n\n\t* EIG.cc (EIG::init, EIG::symmetric_init):\n\tQuery Lapack for workspace size.\n\n2004-02-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::resize_and_fill (const dim_vector&, const T&)):\n\tFix thinko in extending dimensions.\n\n2004-02-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Range.cc (Range::matrix_value, Range::min, Range::max):\n\tDon't compute values beyond the limits of the range.\n\t(operator << (std::ostream&, const Range&)): Likewise.\n\n2004-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-fftw.cc (octave_fftw_planner::create_plan):\n\tCast IN and OUT\targs to ptrdiff_t instead of long before masking.\n\tFrom Paul Kienzle <pkienzle@users.sf.net>.\n\n\t* Array.cc (Array<T>::insertN (const Array<T>&, int, int)):\n\tRename from Array<T>::insert.\n\t(Array<T>::insert2 (const Array<T>&, int, int)):\n\tReinstate old Array<T>::insert function under this name.\n\t(Array<T>::insert (const Array<T>&, int, int)):\n\tNew function.  Dispatch to insert2 or insertN as appropriate.\n\n2004-02-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-fftw.cc (convert_packcomplex_1d, convert_packcomplex_Nd):\n\tSprinkle with OCTAVE_QUIT.\n\n2004-02-16  David Bateman  <dbateman@free.fr>\n\n\t* oct-fftw.cc (octave_fftw_planner::create_plan, octave_fftw::fftNd):\n\tAdd support for FFTW 3.x. Include the ability to\n\tuse the real to complex transform for fft's of real matrices\n\t(octave_fftw_planner::create_plan2d): Delete.\n\t(octave_fftw::fft2d): Delete.\n\t(convert_packcomplex_1d, convert_packcomplex_Nd):\n\tNew static functions.\n\t* oct-fftw.h: Update decls.\n\n\t* dMatrix.cc (Matrix::fourier, Matrix::ifourier,\n\tMatrix::fourier2d, Matrix::ifourier2d): FFT's use real to complex\n\ttransforms.  1D FFT of a matrix done as single call rather than\n\tloop.  Update for FFTW 3.x\n\t* CMatrix.cc (ComplexMatrix::fourier, ComplexMatrix::ifourier,\n\tComplexMatrix::fourier2d, ComplexMatrix::ifourier2d): 1D fft of a\n\tmatrix done as single call rather than loop.  Update for FFTW 3.x.\n\n\t* dNDArray.cc (NDArray::fourier, NDArray::ifourier,\n\tNDArray::fourierNd, NDArray::ifouriourNd): New fourier transform\n\tfunctions for Nd arrays.\n\t* dNArray.h Provide decls.\n\t* CNDArray.cc (ComplexNDArray::fourier, ComplexNDArray::ifourier,\n\tComplexNDArray::fourierNd, ComplexNDArray::ifouriourNd): New\n\tfourier transform functions for complex Nd arrays.\n\t* CNArray.h: Provide decls.\n\n2004-02-15  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* Array.cc (Array<T>::insert (const Array<T>&, int, int)):\n\tMake it work for N-d arrays.\n\n\t* ArrayN.h (ArrayN<T>::insert (const ArrayN<T>& a, int, int)):\n\tNew function.\n\n\t* CNDArray.cc (ComplexNDArray::insert (const NDArray&, int, int),\n\tComplexNDArray::insert (const ComplexNDArray&, int, int)):\n\tNew functions.\n\t* CNDArray.h: Provide decls.\n\n2004-02-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (LINK_DEPS): Always define.\n\n\t* Array.cc (Array<T>::squeeze): Always return an array with at\n\tleast two dimensions.\n\n2004-02-13  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* mx-inlines.cc (MX_ND_CAT): New macro.\n\t* dNDArray.cc (NDArray::cat): New function.\n\t* dNDArray.h: Provide decls.\n\t* CNDArray.cc (complexNDArray::cat): New function.\n\t* CNDArray.h: Provide decls.\n\t* chNDArray.cc (charNDArray::cat): New function.\n\t* chNDArray.h: Provide decls.\n\n2004-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (maybe_delete_elements_2): Allow X(n) = [] for 2-d X.\n\t(Array<T>assign2): Also call maybe_delete_elements for single\n\tindex when rows and columns or LHS are both greater than 1.\n\n2004-02-13  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* Array.cc (Array<T>::maybe_delete_elements):\n\tCheck for index out of bounds.\tHandle one index.\n\n\t* Array.cc (Array<T>::indexN): Use dim_vector (0, 0) instead of\n\tdim_vector (0) to create empty return vector.\n\n2004-02-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::assignN): Don't crash if trying to resize a\n\tnon-empty LHS when the number of lhs dimensions is less than the\n\tnumber of indices.  Detect error if attempting to resize non-empty\n\tLHS with colon indices.\n\n2004-02-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::resize_and_fill): Don't bother to assign any\n\tvalues unless the length of the new array is greater than 0.\n\t(Array<T>::resize_no_fill): Likewise.\n\n\t* Array-util.cc (index_in_bounds): Also return false if ra_idx(i)\n\tis equal to dimensions(i).\n\n\t* Array-util.h, Array-util.cc (equal_arrays, any_zero_len,\n\tget_zero_len_size, number_of_elements):\n\tDelete unused functions.\n\n\t* Array-util.cc (get_ra_idx): Use dim_vector::numel instead of\n\tnumber_of_elements function.\n\t* Array.cc (Array<T>::indexN): Likewise.\n\n\t* Array.cc (Array<T>::indexN): Use dim_vector::operator == instead\n\tof equal_arrays function.\n\t(Array<T>::index, Array<T>::indexN, Array<T>::assignN) Use\n\tdim_vector::any_zero instead of any_zero_len function.\n\n\t* Array.cc (Array<T>::assignN): Eliminate special case for empty index.\n\tDon't skip reshaping and resizing if RHS is empty.\n\n\t* Array.cc (Array<T>::assignN): Simplify loop for array\tassignment.\n\tMove body of MAYBE_RESIZE_ND_DIMS here since it is only used once.\n\tDelete unused variables is_colon and is_colon_equiv.\n\tCorrectly resize for expressions like x(:,:,2) = ones(3,3) when\n\tLHS is not yet defined.\n\tError for resizing if number of indices is less than number of LHS\n\tdimensions.\n\n\t* Array.cc (Array<T>::maybe_delete_elements): Maybe warn about\n\tFortran-style indexing.\n\n2004-02-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::assignN): Simplify.\n\tAllow assignments to succeed if number if indices is less than the\n\tnumber of RHS dimensions.\n\n2004-02-05  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* Array.cc (Array<T>::maybe_delete_elements): Reshape LHS\n\twhen number of indices is less than number of dimensions.\n\n\t* Array.cc (Array<T>::assignN, Array<T>::maybe_delete_elements):\n\tRemove unsued variable lhs_inc.\n\n\t* Array.cc (Array<T>::maybe_delete_elements): Declare idx_is_colon\n\tand idx_is_colon_equiv Array<int> instead of dim_vector.\n\n\t* Array.cc (Array<T>::assignN): Compute new dims in a cleaner way.\n\n\t* Array.cc (Array<T>::index): Check for frozen_lengths.length ()\n\t== n_dims before checking to see if all indices are colon_equiv.\n\n2004-02-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::assignN): Require RHS == 0x0 matrix for\n\tdeleting elements.\n\t(Array<T>::index): Remove trailing singletons in ra_idx, but leave\n\tat least ndims elements.\n\n2004-02-05  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* Array.cc (Array<T>::assignN): Accept assignment of a vector\n\toriented differently from the index.\n\n\t* dim-vector.h (dim_vector::squeeze): Return value always has at\n\tleast two dimensions.\n\n2004-02-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dim-vector.h (dim_vector::squeeze): New function.\n\t(Array<T>::assignN): Use it instead of chop_trailing_singltons for\n\tdeciding whether the assignment conforms.\n\n\t* Array.cc (Array<T>::assignN): Simplify dimension check by\n\tcomparing rhs_dims and frozen_len sans trailing singletons.\n\n2004-02-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.cc (tree_to_mat_idx): New arg, conversion_error.\n\tCall error handler and return conversion_error == true if arg is\n\tnot integer.\n\t(IDX_VEC_REP::idx_vector_rep): Exit early if conversion_error.\n\n2004-02-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* boolNDArray.h (boolNDArray::boolNDArray): Declare dim_vector\n\treference arg const.\n\n2004-01-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-flags.cc: Include Array-flags.h, not Array.h.  Doh.\n\n2004-01-30  Jakub Bogusz  <qboosh@pld-linux.org>\n\n\t* Array-flags.h (liboctave_wfi_flag, liboctave_wrore_flag):\n\tNow bool, to match definition in Array-flags.cc.\n\n2004-01-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc: Include <vector> instead of <memory> for new\n\tdefinition of OCTAVE_LOCAL_BUFFER.\n\n\t* EIG.cc, EIG.h (EIG::init, EIG::symmetric_init, EIG::hermitian_init):\n\tNew arg, calc_eigenvectors.\n\t* EIG.h (EIG:EIG): New optional arg, calc_eigenvectors.\n\tBased on patch from David Bateman <dbateman@free.fr>.\n\n2004-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::assign2, Array<T>::assignN):\n\tFor X(I) = RHS, don't restrict I to fewer elements than X.\n\n\t* Array.cc (Array<T>::assign2): Simplify indexing for X(I) = RHS case.\n\n2004-01-22  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* mx-inlines.cc\t(MX_ND_REDUCTION, MX_ND_CUMULATIVE_OP):\n\tSimplify calculation of number of elements in retval.\n\n\t* Array.cc (Array<T>::assignN): Eliminate unnecessray code for\n\tfilling when RHS is scalar and dimension lengths agree.\n\n2004-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (distclean): Remove mx-ops.h, $(MX_OP_INC),\n\t$(VX_OP_INC), $(MX_OP_SRC), $(VX_OP_SRC), and $(OPTS_INC).\n\n2004-01-22  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* Array.cc (Array<T>::resize_and_fill): Correctly copy old elements.\n\t(Array<T>::assign2): Check for RHS dimensions larger than 2.\n\n2004-01-21  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* Array.h (Array<T>::chop_trailing_singletons): New function.\n\t* Array.cc (Array<T>::assignN): Use it on LHS.\n\n\t* Array.cc (Array<T>::assignN): Fix incorrectly nested if statement.\n\tRetrieve scalar element by passin 0 instead of an index array.\n\tCheck for singleton dimensions where RHS is matrix or higher dimension.\n\tMake sure index is in bounds.\n\n2004-01-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc (octave_ieee_init): Ensure that octave_Inf,\n\toctave_NaN, and octav_NA values are always initialized.  Check\n\tfloating point format, not HAVE_ISINF, HAVE_FINITE, or HAVE_ISNAN\n\tto decide whether to do IEEE initialization.\n\n2004-01-06  David Bateman  <dbateman@free.fr>\n\n \t* CNDArray.cc (ComplexNDArray::any_element_is_inf_or_nan,\n \tComplexNDArray::all_elements_are_real, ComplexNDArray::all_integers,\n \tComplexNDArray::too_large_for_float): New functions\n\n \t* CNDArray.cc (operator <<, operator >>): New IO operators.\n \t* CNDArray.h: Provide decls.\n \t* dNDArray.cc (operator <<, operator >>): New IO operators.\n \t* dNDArray.h: Provide decls.\n\n2003-12-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mx-ops: Delete bnda x bnda, b x bnda, and bnda x b ops since\n\tthey are already defined in boolNDArray.cc.\n\n\t* Array-util.cc (get_zero_len_size): Delete.\n\t* Array.cc (Array<T>::index (Array<idx_vector>&, int, const T&)):\n\tHandle zero-length result dimensions the same as empty original\n\tindices.\n\n2003-12-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dim-vector.h (dim_vector::chop_trailing_singleton_dims,\n\tdim_vector::dim_vector_rep::chop_trailing_singleton_dims):\n\tNew functions.\n\t* Array.cc (ArrayN<T>::indexN): Use it.\n\t(ArrayN<T>::index (Array<idx_vector>&, int, const T&)): Likewise.\n\n2003-11-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* boolNDArray.cc: Define BOOL ops.  Define mixed CMP ops.\n\t* boolNDArray.h: Declare BOOL ops.  Declare mixed CMP ops.\n\n2003-11-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mk-ops.awk: Also emit #include \"Array-util.h\".\n\n\t* mx-ops: Add bool, boolMatrix, and boolNDarray types.\n\tAdd bnda x bnda, b x bnda, and bnda x b ops.\n\n\t* MArray-misc.cc: Delete.\n\t* Makefile.in (MATRIX_SRC): Remove it from the list.\n\n\t* Array-util.h, Array-util.cc (gripe_nonconformant): Move here from\n\tMArray.h, MArray2.h, MArrayN.h, and MArray-misc.cc.\n\n2003-11-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleQR.cc (QR::init): Use separate pwork pointers.\n\t* CmplxQR.cc (ComplexQR::init): Likewise.\n\n\t* oct-group.cc (octave_group::getgrnam): Pass correct args to\n\ttwo-arg getgrnam version.\n\n\t* Array.cc (assignN): Allow single indexing to work.\n\t(Array<T>::range_error (const char*, const Array<int>&)):\n\tReport index values.\n\n\t* Array.cc (Array<T>::index): Delete unused arg names.\n\t* ODESSA.cc (odessa_j): Likewise.\n\t* DASRT.cc (ddasrt_f, ddasrt_g): Likewise.\n\t* DASPK.cc (ddaspk_psol): Likewise.\n\t* lo-mappers.cc (imag): Likewise.\n\t* Array-util.cc (get_zero_len_size): Likewise.\n\t* kpse.cc (path_search, path_find_first_of): Likewise.\n\t* cmd-edit.cc (do_generate_filename_completions): Likewise.\n\n\t* dim-vector.h (dim_vector::all_ones): New function.\n\n2003-11-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.h (idx_vector::orig_empty): Check orig_dims for\n\tzeros, not orig_rows or orig_columns.\n\t(idx_vector::idx_vector_rep::orig_rows): Define using orig_dims.\n\t(idx_vector::idx_vector_rep::orig_columns): Likewise.\n\n\t* idx-vector.cc (idx_vector::idx_vector_rep::orig_nr,\n\t(idx_vector::idx_vector_rep::orig_nc): Delete.\n\n\t* idx-vector.cc (idx_vector::idx_vector_rep):\n\tUse initialization lists for constructors.\n\n\t* Array.cc (Array<T>::indexN): Correctly handle single colon index.\n\tOmit special case for ra_idx.capacity () == 1.\n\tAlways allow single index for matrix args with optional warning.\n\n\t* idx-vector.h, idx-vector.cc: Convert boolMatrix functions to use\n\tboolNDArray.  Likewise, convert Matrix functions to use\tNDArray.\n\n\t* Array-so.cc: New file.  Move instantiations here from so-array.h.\n\t* Makefile.in (TI_SRC): Add it to the list.\n\n\t* MArray-defs.h (DO_VS_OP2, DO_VV_OP2): Accept args for element\n\ttype and the names of the left and right operands.  Change all uses.\n\n\t* so-array.cc, so-array.h: New files.  Move streamoff_array here\n\tfrom src/ov-streamoff.h and src/ov-streamoff.cc.\n\n2003-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* MArrayN.cc (operator -=, operator +=): Check dimensions, not\n\tjust length.\n\n\t* Array2.h, Array3.h, DiagArray2.h, DiagArray2.cc, MDiagArray2.h,\n\tArrayN.h:  Add this-> or Base:: qualifiers for references to\n\tnon-dependent member functions and data as needed.\n\n\t* DiagArray2.h, DiagArray2.cc: Delete unused code.\n\n\t* Array2.h (Array2<T>::operator =): Don't copy dimensions here.\n\t* Array3.h (Array3<T>::operator =): Likewise.\n\t* DiagArray2.h (DiagArray2<T>::operator =): Likewise.\n\tInclude Array.h, not Array2.h.\n\n2003-11-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* str-vec.cc (list_in_columns): Fix previous change.\n\n\t* dim-vector.h (dim_vector::num_ones): New function.\n\t* Array.cc (maybe_delete_elements): Use it instead of\n\tnum_ones (const Array<int>&).\n\n\t* Array.cc (assignN): Omit dubious check of singleton dimensions.\n\n\t* dNDArray.cc (NDArray::all_elements_are_int_or_inf_or_nan,\n\tNDArray::any_element_is_inf_or_nan, NDArray::too_large_for_float):\n\tNew functions.\n\t* dNDArray.h: Provide decls.\n\n\t* dMatrix.h (Matrix::any_element_is_negative,\n\tMatrix::any_element_is_inf_or_nan, Matrix::too_large_for_float,\n\tMatrix::all_elements_are_int_or_inf_or_nan, Matrix::all_integers):\n\tSimplify.\n\n\t* dNDArray.cc (NDArray::abs): Make it work for N-d arrays.\n\t* CNDArray.cc (ComplexNDArray::abs): Likewise.\n\n\t* dNDArray.cc (real, imag): New functions.\n\t* dNDArray.h: Provide decls.\n\n2003-11-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (TEMPLATE_SRC): Move MArrayN.cc here from MATRIX_SRC.\n\n2003-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h (Array<T>::resize (int, const T&)): Reinstate.\n\t* MArray.h (resize): Delete.\n\t* MArray2.h (resize): Delete.\n\t* DASRT.cc (DASRT::integrate): Use resize, not resize_and_fill.\n\t* ODESSA (ODESSA::integrate): Likewise.\n\n2003-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (dist): Depend on stamp-prereq.\n\n2003-11-12  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mach-info.c (oct_mach_info::init_float_format) [CRAY]:\n\tKluge to make it work.\n\n\t* lo-ieee.cc (octave_ieee_init): Set octave_Inf, octave_NaN, and\n\toctave_NA to DBL_MAX if native float format is vaxd, vaxg, or cray.\n\n\t* cmd-edit.cc (gnu_readline::do_generate_filename_completions,\n\tdefault_command_editor::do_generate_filename_completions,\n\tcommand_editor::generate_filename_completions): New functions.\n\t* cmd-edit.h: Provide decls.\n\t* oct-rl-edit.c (octave_rl_filename_completion_function): New\n\tfunction.\n\t* oct-rl-edit.h: Provide decl.\n\n2003-11-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h (INSTANTIATE_ARRAY_ASSIGN, INSTANTIATE_ARRAY_AND_ASSIGN,\n\tINSTANTIATE_ARRAY): New macros.\n\t* Array-C.cc, Array-b.cc, Array-ch.cc, Array-d.cc, Array-i.cc,\n\tArray-idx-vec.cc, Array-s.cc, Array-str.cc, ODESSA.cc: Use them.\n\n\t* Array.h (Array<T>::ipermute): New function.\n\n2003-11-11  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* Array.cc (Array<T>::permute): New function.\n\t* Array.h: Provide decl.\n\n\t* Array-util.cc (calc_permutated_idx): New function.\n\t* Array-util.h: Provide decl.\n\n2003-11-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::index2): Return value has orientation of\n\tindexed value if indexing a vector with a bool matrix.\n\n\t* ArrayN.h (ArrayN<T>::get_size): Delete.\n\n\t* Array.cc, ArrayN.cc, dNDArray.cc, CNDArray.cc, boolNDArray.cc,\n\tchNDArray.cc: Include Array-util.h instead of ArrayN-inline.h.\n\n\t* ArrayN-inline.h: Delete.\n\t* Array-util.h, Array-util.cc: New files, from ArrayN-inline.h.\n\t* Makefile.in: Fix the appropriate lists.\n\n\t* Array.cc, Array.h, ArrayN.h, CMatrix.cc, CNDArray.h,\n\tCRowVector.cc, CmplxQR.cc, CollocWt.h, DASPK.h, DASRT.h, DASSL.h,\n\tFEGrid.cc, LP.h, LSODE.h, MArrayN.h, ODE.h, ODES.h, ODESSA.cc,\n\tboolNDArray.h, chNDArray.h, dMatrix.cc, dNDArray.h, dRowVector.cc,\n\tdbleQR.cc, kpse.cc, oct-rl-hist.c, str-vec.cc, str-vec.h:\n\tAvoid -Wshadow warnings.\n\n2003-11-08  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h (Array<T>::nil_rep): Qualify return type with typename.\n\n\t* mk-ops.awk: Delete elements of bool_headers array individually.\n\n2003-11-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (maybe_delete_elements): Rename arg idx to ra_idx.\n\n2003-10-31  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* mx-inlines.cc (MX_ND_CUMULATIVE_OP): New macro.\n\n\t* CNDArray.cc, CNDArray.h (ComplexNDArray::cumsum,\n\tComplexNDArray::cumprod): Return ComplexNDArray.  Handle N-d arrays.\n\t* dNDArray.cc, dNDArray.h (NDArray::cumsum, NDArray::cumprod):\n\tReturn NDArray.  Handle N-d arrays.\n\n2003-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* LSODE.cc (LSODE::do_integrate): Avoid name conflict on systems\n\tthat upcase Fortran names by calling dlsode instead of lsode.\n\n\t* ODESSA.cc (ODESSA::do_integrate): Avoid name conflict on systems\n\tthat upcase Fortran names by calling dodessa instead of odessa.\n\n\t* file-ops.cc (file_ops::symlink): Cope with systems that expect\n\tnon-const args for symlink system call.\n\t(file_ops::readlink): Likewise, for readlink.\n\n\t* DASRT.cc (DASRT::integrate): Fix typo in Fortran function name.\n\n2003-10-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mach-info.h (oct_mach_info): Prefix enum elements with flt_fmt_.\n\tChange all uses.\n\n2003-10-29  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* dNDArray.cc (NDArray::cumprod, NDArray::cumsum, NDArray::prod,\n\tNDArray::sum, NDArray::sumsq, NDArray::abs): New functions.\n\t* dNDArray.h: Provide decls.\n\t* CNDArray.cc (ComplexNDArray::cumprod, ComplexNDArray::cumsum,\n\tComplexNDArray::prod, ComplexNDArray::sum, ComplexNDArray::sumsq,\n\tComplexNDArray::abs): New functions.\n\t* CNDArray.h: Provide decls.\n\n\t* mx-inlines.cc (MX_ND_REDUCTION): Rename from MX_ND_ANY_ALL.\n\tGeneralize to handle other reduction operations.\n\t(MX_ND_REAL_OP_REDUCTION, MX_ND_COMPLEX_OP_REDUCTION,\n\tMX_ND_ALL_ANY_REDUCTION): New macros.\n\n2003-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::reshape): New function.\n\t* Array.h: Provide decl.\n\n\t* dim-vector.h (dim_vector::numel): New function.\n\n\t* dim-vector.h (dim_vector_rep::dim_vector_rep (int, const\n\tdim_vector&)): Correctly handle case of n < dv->ndims.\n\n2003-10-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dim-vector.h (dim_vector::any_zero): New function.\n\t(dim_vector::str): New default arg, sep.\n\n\t* Array.h (Array<T>::numel): New function.\n\n2003-10-27  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* mx-inlines.cc (MX_ND_ALL_EXPR, MX_ND_ANY_EXPR,\n\tMX_ND_ALL_EVAL, MX_ND_ANY_EVAL, MX_ND_ALL_ANY): New macros.\n\t* dNDArray.h (NDArray::all, NDArray::any): Return type now boolNDArray.\n\t* CNDArray.h (ComplexNDArray::all, ComplexNDArray::any): Likewise.\n\t* boolNDArray.h (boolNDArray::all, boolNDArray::any): Likewise.\n\t* chNDArray.h (charNDArray::all, charNDArray::any): Likewise.\n\t* dNDArray.cc (NDArray::all, NDArray::any): Make them work.\n\t* CNDArray.cc (ComplexNDArray::all, ComplexNDArray::any): Likewise.\n\t* boolNDArray.cc (boolNDArray::all, boolNDArray::any): Likewise.\n\t* chNDArray.cc (charNDArray::all, charNDArray::any): Likewise.\n\n2003-10-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::resize_and_fill): Allow number of dimensions\n\tto change.  From Petter Risholm  <risholm@stud.ntnu.no>.\n\n\t* oct-rand.cc, CColVector.cc, CMatrix.cc, CRowVector.cc,\n\tCmplxAEPBAL.cc CmplxCHOL.cc, CmplxHESS.cc, CmplxLU.cc, CmplxQR.cc,\n\tCmplxQRP.cc, CmplxSCHUR.cc, CmplxSVD.cc, CollocWt.cc, DASPK.cc,\n\tDASRT.cc, DASSL.cc, EIG.cc, LSODE.cc,  NLEqn.cc, ODESSA.cc,\n\tQuad.cc, dColVector.cc, dMatrix.cc, dRowVector.cc, dbleAEPBAL.cc,\n\tdbleCHOL.cc, dbleHESS.cc, dbleLU.cc, dbleQR.cc, dbleQRP.cc,\n\tdbleSCHUR.cc, dbleSVD.cc, lo-specfun.cc:\n\tUse new F77 arg macros in declarations of external Fortran\n\tsubroutines and for calling them.\n\n2003-10-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::resize_no_fill (const dim_vector&)):\n\tAllow number of dimensions to change.\n\t(Array<T>::resize_no_fill (int, int)): Require ndims to be 0 or 2.\n\t(Array<T>::resize_and_fill (int, int, const T&)): Likewise.\n\t(Array<T>::resize_no_fill (int, int, int)): Require ndims to be 0 or 3.\n\t(Array<T>::resize_and_fill (int, int, int, const T&)): Likewise.\n\t(Array<T>::transpose): Require ndims to be 2.\n\t(Array<T>::index2): Likewise.\n\t(Array<T>::index (idx_vector&, idx_vector&, int, const T&)): Likewise.\n\t(Array<T>::maybe_delete_elements_2): Likewise.\n\t(Array<T>::maybe_delete_elements (idx_vector&, idx_vector&)): Likewise.\n\t(Array<T>::index1): Use resize_and_fill.\n\t(MAYBE_RESIZE_ND_DIMS): Likewise.\n\n\t* ODESSA.cc (ODESSA::integrate): Use resize_and_fill for x_s_out.\n\n\t* MArray2.h (MArray2<T>::resize (int, int)): New function.\n\t(MArray2<T>::resize (int, int, const T&)): New function.\n\n\t* MArray.h (MArray<T>::resize (int)): New function.\n\t(MArray<T>::resize (int, const T&)): New function.\n\n\t* DASRT.cc (DASRT::integrate): Use resize_and_fill for jroot.\n\n\t* DASPK-opts.in: Use single-arg resize for initial condition\n\theuristics.\n\n\t* dim-vector.h (class dim_vector): Now reference counted.\n\t(dim_vector_rep::elem): Use assert to check that index is in bounds.\n\n2003-10-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::squeeze): Delete redundant retval decl.\n\n\t* mx-cdm-cm.cc, mx-cdm-cm.h, mx-cdm-cs.cc, mx-cdm-cs.h,\n\tmx-cdm-dm.cc, mx-cdm-dm.h, mx-cdm-m.cc, mx-cdm-m.h, mx-cdm-s.cc,\n\tmx-cdm-s.h, mx-cm-cdm.cc, mx-cm-cdm.h, mx-cm-dm.cc, mx-cm-dm.h,\n\tmx-cm-m.cc, mx-cm-m.h, mx-cm-s.cc, mx-cm-s.h, mx-cs-cdm.cc,\n\tmx-cs-cdm.h, mx-cs-dm.cc, mx-cs-dm.h, mx-cs-m.cc, mx-cs-m.h,\n\tmx-dm-cdm.cc, mx-dm-cdm.h, mx-dm-cm.cc, mx-dm-cm.h, mx-dm-cs.cc,\n\tmx-dm-cs.h, mx-dm-m.cc, mx-dm-m.h, mx-dm-s.cc, mx-dm-s.h,\n\tmx-m-cdm.cc, mx-m-cdm.h, mx-m-cm.cc, mx-m-cm.h, mx-m-cs.cc,\n\tmx-m-cs.h, mx-m-dm.cc, mx-m-dm.h, mx-ops.h, mx-s-cdm.cc,\n\tmx-s-cdm.h, mx-s-cm.cc, mx-s-cm.h, mx-s-dm.cc, mx-s-dm.h,\n\tvx-ccv-cv.cc, vx-ccv-cv.h, vx-ccv-s.cc, vx-ccv-s.h, vx-crv-rv.cc,\n\tvx-crv-rv.h, vx-crv-s.cc, vx-crv-s.h, vx-cs-cv.cc, vx-cs-cv.h,\n\tvx-cs-rv.cc, vx-cs-rv.h, vx-cv-ccv.cc, vx-cv-ccv.h, vx-cv-cs.cc,\n\tvx-cv-cs.h, vx-rv-crv.cc, vx-rv-crv.h, vx-rv-cs.cc, vx-rv-cs.h,\n\tvx-s-ccv.cc, vx-s-ccv.h, vx-s-crv.cc, vx-s-crv.h: Delete.  These\n\tfiles are now automatically generated.\n\n\t* Makefile.in ($(VX_OP_INC), $(VX_OP_SRC), $(MX_OP_INC),\n\t$(MX_OP_SRC)): Generate lists with new mk-ops.awk script.\n\tAdd rules to generate these files and mx-ops.h.\n\t(stamp-prereq): Depend on these files.\n\n\t* mx-ops, vx-ops, mk-ops.awk: New files.\n\t* Makefile.in (DISTFILES): Add them to the list.\n\n2003-10-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* NDArray.cc (NDArray::NDArray (const boolNDArray),\n\tNDArray::NDArray (const charNDArray)): New constructors.\n\t(NDArray::operator !): New function.\n\tProvide NDS_CMP_OPS, NDS_BOOL_OPS, SND_CMP_OPS, SND_BOOL_OPS,\n\tNDND_CMP_OPS, NDND_BOOL_OPS.\n\n\t* CNDArray.cc (ComplexNDArray::ComplexNDArray (const NDArray&),\n\tComplexNDArray::ComplexNDArray (const boolNDArray&),\n\tComplexNDArray::ComplexNDArray (const charNDArray&)):\n\tNew constructors.\n\t(ComplexNDArray::operator !): New function.\n\tProvide NDS_CMP_OPS, NDS_BOOL_OPS, SND_CMP_OPS, SND_BOOL_OPS,\n\tNDND_CMP_OPS, NDND_BOOL_OPS.\n\n\t* ArrayN.h (resize (const dim_vector&)): Fix typo.\n\n\t* boolNDArray.cc (boolNDArray::operator !): New function.\n\tProvide NDND_CMP_OPS.\n\n\t* MArrayN.cc (operator +=, operator -=): New functions.\n\tProvide product and quotient functions.\n\n\t* MArray-misc.cc (gripe_nonconformant (const char *, dim_vector&,\n\tdim_vector&)): New function.\n\n\t* dim-vector.h (dim_vector::str, dim_vector::all_zero,\n\toperator ==, operator !=): New functions.\n\t* ArrayN.cc (operator <<): Use dim_vector::str here.\n\n\t* Array.cc (Array<T>::resize_no_fill, Array<T>::resize_and_fill):\n\tNo need to save old dimensions.\n\n\t* oct-rand.cc (MAKE_RAND_ND_ARRAY): New macro.\n\t(octave_rand::nd_array): New function.\n\t* oct-rand.h (octave_rand::nd_array): Provide decl.\n\n\t* mx-op-defs.h (NDCMP_OP_DECL, NDBOOL_OP_DECL, NDS_BIN_OP_DECLS,\n\tNDS_BIN_OP, NDS_BIN_OPS, NDS_CMP_OP_DECLS, NDS_CMP_OP,\n\tNDS_CMP_OPS, NDS_BOOL_OP_DECLS, NDS_BOOL_OP, NDS_BOOL_OPS,\n\tNDS_OP_DECLS, SND_BIN_OP_DECLS, SND_BIN_OP, SND_BIN_OPS,\n\tSND_CMP_OP_DECLS, SND_CMP_OP, SND_CMP_OPS, SND_BOOL_OP_DECLS,\n\tSND_BOOL_OP, SND_BOOL_OPS, SND_OP_DECLS, NDND_BIN_OP_DECLS,\n\tNDND_BIN_OP, NDND_BIN_OPS, NDND_CMP_OP_DECLS, NDND_CMP_OP,\n\tNDND_CMP_OPS, NDND_BOOL_OP_DECLS, NDND_BOOL_OP, NDND_BOOL_OPS,\n\tNDND_OP_DECLS): New macros.\n\t* mx-cm-m.h, mx-cm-s.h, mx-cs-m.h, mx-m-cm.h, mx-m-cs.h,\n\tmx-s-cm.h, mx-cm-m.cc, mx-cm-s.cc, mx-cs-m.cc, mx-m-cm.cc,\n\tmx-m-cs.cc, mx-s-cm.cc: Use them.\n\n\t* mx-defs.h (class NDArray, class ComplexNDArray, class\n\tboolNDArray, class charNDArray): New forward decls.\n\n2003-10-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (assign2): No error (but don't do anything either) for\n\texpressions like x([],j) = scalar.\n\n2003-10-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (assignN): Allow lhs(:) = scalar.\n\n\t* CNDArray.cc (ComplexNDArray::increment_index): New function.\n\t* dNDArray.cc (NDArray::increment_index): Likewise.\n\t* boolNDArray.cc (boolNDArray::increment_index): Likewise.\n\t* chNDArray.cc (charNDArray::increment_index): Likewise.\n\n\t* dim-vector.h (rows, cols): Delete unused data members.\n\n\t* Array.cc (Array<T>::get_size): Fix thinko.\n\n2003-10-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::squeeze): New function.\n\t* CNDArray.h (ComplexNDArray::squeeze): Likewise.\n\t* dNDArray.h (NDArray::squeeze): Likewise.\n\t* boolNDArray.h (boolNDArray::squeeze): Likewise.\n\t* chNDArray.h (charNDArray::squeeze): Likewise.\n\n2003-10-06  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* Array.cc (ArrayN<T>::indexN): New definition.\n\t* Array.h (Array<T>::indexN): Provide decl.\n\t* Array.cc (ArrayN<T>::index (idx_vector&, int, const T&):\n\tCall indexN if more than 2 indices.\n\t(ArrayN<T>::index (Array<idx_vector>&, int, const T&)):\n\tMake it (mostly) work.\n\t* ArrayN-inline.h (number_of_elements, get_ra_idx, short_freeze):\n\tNew functions.\n\n2003-10-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.cc (do_readline): Pass eof to octave_fgetl.\n\t* lo-utils.cc (octave_fgets, octave_fgetl): New overloaded\n\tversions with eof arg.\n\n2003-09-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h (dimensions): Now public.\n\ttemplate <class LT, class RT>\n\t(assign (Array<LT>&, const Array<RT>&, const LT&),\n\tassign1 (Array<LT>&, const Array<RT>&, const LT&),\n\tassign2 (Array<LT>&, const Array<RT>&, const LT&),\n\tassignN (Array<LT>&, const Array<RT>&, const LT&),\n\tresize_no_fill (int),\n\tresize_no_fill (int, int),\n\tresize_no_fill (int, int, int),\n\tresize_no_fill (const dim_vector&),\n\tresize_and_fill (int, const T&),\n\tresize_and_fill (int, int, const T&),\n\tresize_and_fill (int, int, int, const T&),\n\tresize_and_fill (const dim_vector&, const T&)): Now public.\n\n\t* Array.cc: Include <climits>.\n\n2003-09-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc: Merge Array-idx.h.\n\t* Array-idx.h: Delete.\n\n\t* chNDArray.h, chNDArray.cc, boolNDArray.h, boolNDArray.cc: New files.\n\n\t* Array.h, Array-idx.h, Array.cc: Fold all N-d functionality here.\n\tTurn inheritance hierarchy upside down (2-d and 3-d arrays are now\n\tjust special cases of the general purpose N-d Array object).\n\n\t* dim-vector.h: New file.  Use dim_vector objects instead of\n\tints or Array<int> objects to represent the size of Array\n\tobjects.\n\n\t* MArray-defs.h (INSTANTIATE_MARRAYN_FRIENDS): New macro.\n\n\t* Array2-idx.h, Array3-idx.h, Array2.cc, Array3.cc: Delete.\n\n\t* mx-base.h: Include NDArray header files.\n\n\t* MArray-C.cc, MArray-d.cc: Also instantiate ArrayN objects.\n\n\t* Array-C.cc, Array-b.cc, Array-ch.cc, Array-d.cc, Array-i.cc,\n\tArray-s.cc: Also instantiate ArrayN objects.\n\tDon't instantiate assign funcitons for Array2 objects.\n\n\t* CDiagMatrix.cc (ComplexDiagMatrix::diag): Signal error with\n\tliboctave_error_handler, not cerr.\n\t* CMatrix.cc (ComplexMatrix::diag): Likewise.\n\t* dDiagMatrix.cc (DiagMatrix::diag): Likewise.\n\t* dMatrix.cc (Matrix::diag): Likewise.\n\n\t* Array-flags.cc, Array.cc, Array.h, Array2.h, Array3.h, ArrayN.h:\n\tOmit checks for HEAVYWEIGHT_INDEXING.\n\n2003-09-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mx-base.h: Include CNDarray.h.  Include dNDArray.h, not NDArray.h.\n\n\t* CNDARray.h, CNDArray.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* dNDArray.h: Rename from NDArray.h.\n\t* dNDArray.cc: Rename from NDArray.cc.\n\t* Makefile.in: Rename them here too.\n\n2003-09-10  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* mx-base.h: Include NDArray.h, not ArrayN.h.\n\n\t* MArrayN.cc, MArrayN.h, NDArray.h, NDArray.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n2003-09-09  David Bateman  <dbateman@free.fr>\n\n\t* lo-specfun.cc (zbesj, zbesy, zbesi, zbesk, zbesh1, zbesh2, airy,\n\tbiry): Always request scaled results from AMOS functions and\n\tperform reverse scaling on results if scaled result not requested\n\tby user.\n\n2003-09-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n \t* lo-specfun.cc (xlgamma): Require nonnegative argument.\n\n2003-09-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-d.cc: Instantiate assign functions.\n\n2003-09-09  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* ArrayN-idx.h (vector_equivalent, equal_arrays): New functions.\n\t(get_elt_idx): Index ra_idx correctly.\n\n\t* ArrayN-inline.h (index_in_bounds): Index is also condidered in\n\tbounds if it is exactly on the bound.\n\n\t* ArrayN.cc (ArrayN<T>::maybe_delete_dims): New function.\n\t* ArrayN.h: Provide decl.\n\n\t* ArrayN.h (ArrayN<T>::ArrayN<T> (const Matrix&)): New constructor.\n\n\t* idx-vector.h (idx_vector::orig_dims): New member variable.\n\t(idx_vector::idx_vector_rep::orig_dimensions): New function.\n\t(idx_vector::orig_dimensions): New function.\n\n2003-09-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-specfun.cc (xlgamma): Require nonnegative argument.\n\n2003-09-04  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* ArrayN-idx.h (maybe_delete_elements): Implement function.\n\t(is_in, how_many_lgt, all_ones): New functions.\n\n2003-09-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (MATRIX_INC): Add ArrayN-inlines.h to the list.\n\n2003-09-03  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* ArrayN-inline.h: New file.\n\t(index_in_bounds, increment_index): Move here.\n\t* ArrayN.cc: From here.\n\n\t* ArrayN.h (maybe_delete_elements): New arg, resize_fill_value.\n\t* ArrayN-idx.h (assign): New function.\n\n2003-08-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-specfun.cc (zbesj, zbesy, zbesi, zbesk, airy, biry):\n\tAlso zero imaginary part of result if real part of input value is\n\tzero.\n\n2003-07-30  Heine Kolltveit  <kolltvei@idi.ntnu.no>\n\n\t* mx-base.h: Include ArrayN.h.\n\n2003-30-07  Heine Kolltveit  <kolltvei@idi.ntnu.no>\n\n\t* ArrayN.cc (operator <<): Corrected output.\n\n2003-07-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ArrayN.cc (increment_index): New arg, start_dimension.\n\n2003-07-29  Heine Kolltveit  <kolltvei@idi.ntnu.no>\n\n\t* ArrayN.cc (operator <<): Improve output readability.\n\n2003-07-29  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* ArrayN.cc (ArrayN<T>::resize (const Array<int>&, const T&)):\n\t* ArrayN.cc (ArrayN<T>::resize (const Array<int>&)):\n\tInitialize old_len before changing size.\n\n2003-07-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-lib): Use $(INSTALL), not\n\t$(INSTALL_PROGRAM) for $(SHLLIB) files.\n\n2003-07-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc (xmin, xmax): Handle NaN in a Matlab-compatible\n\tway.  Handle NA in an R-compatible way.\n\n\t* lo-cieee.c (lo_ieee_is_NaN_or_NA): Also check for lo_ieee_is_NA.\n\t(lo_ieee_is_NA): Don't call isnan unless HAVE_ISNAN is defined.\n\n\t* lo-mappers.h (octave_is_NA (const Complex&)): Provide decl.\n\t(octave_is_NaN_or_NA (const Complex&)): Likewise.\n\n\t* dMatrix.cc (Matrix::row_min, Matrix::row_max,\n\tMatrix::column_min, Matrix::column_max): Ignore NaNs.\n\t* CMatrix.cc (ComplexMatrix::row_min, ComplexMatrix::row_max,\n\tComplexMatrix::column_min, ComplexMatrix::column_max): Likewise.\n\n2003-07-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (assign (Array2<LT>&, const Array2<RT>&, const LT&)):\n\tPass true for resize_ok arg to freeze.\n\t* Array-idx.h (assign (Array<LT>&, const Array<RT>&, const LT&)):\n\tLikewise.\n\n\t* idx-vector.cc (IDX_VEC_REP::freeze): New arg, warn_resize;\n\tresize_ok arg is now bool.\n\t* idx-vector.h (idx_vector::freeze): Likewise.\n\n\t* Array-flags.cc, Array-flags.h (liboctave_wrore_flag):\n\tRename from liboctave_rre_flag.  Now bool.\n\t(liboctave_wfi_flag): Now bool.\n\n\t* Array2-idx.h (MAYBE_RESIZE_LHS): Don't check liboctave_rre_flag.\n\n2003-07-11  Russell Standish  <R.Standish@unsw.edu.au>\n\n\t* Array.h (resize_fill_value): Now a top-level template function.\n\tAccept object as argument.  Change all uses.\n\n2003-07-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-flags.cc, Array-flags.h (liboctave_pcv_flag): Delete.\n\n\t* Array2-idx.h (Array2<T>::index): Use liboctave_wfi_flag, not\n\tliboctave_dfi_flag.\n\t(assign): Likewise.  For indexed assignments like X(I) = RHS with\n\tX undefined or empty, always create a row vector.\n\n\t* Array-flags.cc (liboctave_wfi_flag): Rename from liboctave_dfi_flag.\n\t* Array-flags.h (liboctave_wfi_flag): Ditto.\n\n2003-06-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::index (idx_vector&, int, const T&)):\n\tMagic colon indexing always produces an object with one column.\n\n2003-06-21  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* kpse-xfns.h (NAME_BEGINS_WITH_DEVICE): Arg is std::string, not char*.\n\n\t* lo-ieee.h (signbit): Eliminate redundant extern \"C\" decl.\n\n2003-06-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (any_element_is_negative): If new optional arg\n\tneg_zero is true, also return true for negative zero.\n\n2003-06-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASSL.cc (DASSL::do_integrate): Set liw to 21 + n, not 20 + n.\n\tHandle step limit.\n\t* DASSL-opts.in: New option for step limit.\n\n2003-06-16  Per Persson  <persquare@mac.com>\n\n\t* oct-shlib.cc: Include mach-o/dyld.h, not Mach-O/dyld.h.\n\n2003-06-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASRT.cc (DASRT::integrate): Set liw to 21 + n, not 20 + n.\n\tStore step limit in iwork(20), not iwork(18).\n\n2003-05-16  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* oct-rand.cc: Use liboctave's clock layer instead of the system clock.\n\n2003-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Handle DESTDIR.\n\n\t* kpse.cc (kpse_path_iterator::next): Skip consecutive colons here.\n\t(kpse_path_iterator::set_end): Don't miss last element when not\n\tfollowed by a colon.\n\n2003-05-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-idx.h (Array<T>::index): Fix off-by-one error.\n\n2003-05-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* kpse.cc (kpse_absolute_p): Fix typo in translation.\n\t(find_first_of): Also do an absolute search on each\n\tname before looking in the path.\n\n2003-05-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* kpse.cc (dir_list_add): Ensure that directory ends with a\n\tdirectory separator.\n\n2003-04-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.cc: Include kpse.cc here.\n\n\t* kpse.cc: All functions are now static.  Massive surgery to\n\tcondense kpathsearch library to a single file of just the\n\tessentials for Octave and convert to using C++ strings (no more\n\tcalls to malloc, very few calls to new, so there should be much\n\tless potential for introducing memory leaks now).\n\n\t* Makefile.in (EXTRAS): Move kpse.cc here from\n\tLIBOCT_PATHSEARCH_CXX_SOURCES.\n\n\t* kpse.h, kpse-config.h: Delete.\n\t* Makefile.in (INCLUDES): Delete them from the list.\n\n2003-04-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* str-vec.cc (string_vector::append (const std::string&),\n\tstring_vector::append (const string_vector&)): New methods.\n\n2003-04-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* kpse.cc, kpse.h: Replace fn_type with std::string.\n\n\t* lo-ieee.h (lo_ieee_signbit): Provide signbit decl for MinGW systems.\n\n\t* kpse.cc (xclosedir): Don't define or declare for Windows.\n\t(READABLE): Now a static function to avoid warnings from MinGW\n\tcompiler.\n\n2003-04-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* kpse.cc: Move most functions from kpse-xfns.c here and make\n\tstatic.  Include most of kpse-xfns.h directly, removing\n\tunnecessary bits.\n\n\t* dMatrix.cc (Matrix::pseudo_inverse): Now const.\n\t* CMatrix.cc (ComplexMatrix::pseudo_inverse): Likewise.\n\n2003-04-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* getopt.c, getopt1.c, getopt.h: Move here from kpathsea.\n\t* Makefile.in: Add them to the appropriates lists.\n\n\t* oct-getopt.c: Include \"getopt.h\", not <kpathsea/getopt.h>.\n\n\t* Makefile.in (liboctave.$(LIBEXT), liboctave.$(SHLEXT)): Adjust\n\tfor new locations of kpathsea objects.\n\tDelete kpathsea targets.\n\n\t* pathsearch.cc (dir_path::set_program_name): Delete.\n\n\t* kpse.cc: New file.\n\t* Makefile.in (LIBOCT_PATHSEARCH_CXX_SOURCES): Add it to the list.\n\n\t* kpse.c: New file.\n\t* Makefile.in (LIBOCT_PATHSEARCH_C_SOURCES): Add it to the list.\n\n\t* kpse.h, kpse-config.h, kpse-xfns.h: New files.\n\t* Makefile.in (INCLUDES): Add them to the list.\n\n\t* oct-kpse.h: Delete.\n\t* Makefile.in (INCLUDES): Delete it from the list.\n\n2003-04-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleSVD.h (SVD::SVD, SVD::operator =): Also copy type_computed.\n\t* CmplxSVD.h (ComplexSVD::ComplexSVD, ComplexSVD::operator =):\n\tLikewise.\n\tFrom Quentin H. Spencer <qspencer@ieee.org>.\n\n2003-03-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-getopt.c: Include <kpathsea/getopt.h>, not \"getopt.h\".\n\n2003-02-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-alloc.h (DECLARE_OCTAVE_ALLOCATOR): Handle systems with or\n\twithout placement delete.\n\n\t* CMatrix.cc (ComplexMatrix::all_elements_are_real): Don't lose -0\n\timaginary parts.\n\n\t* lo-ieee.h (lo_ieee_signbit): New macro.\n\n2003-02-18  David Bateman  <dbateman@free.fr>\n\n\t* dMatrix.cc (Matrix::inverse, Matrix::determinant, Matrix::solve):\n\tUse Lapack instead of Linpack.\n\t* CMatrix.cc (ComplexMatrix::inverse, ComplexMatrix::determinant,\n\tComplexMatrix::solve): Likewise.\n\n\t* dMatrix.cc (Matrix::determinant, Matrix::inverse): New arg,\n\tcalc_cond.  If 0, skip condition number calculation.\n\t* CMatrix.cc (ComplexMatrix::determinant, ComplexMatrix::inverse):\n\tLikewise.\n\n\t* CmplxLU.cc (ComplexLU::ComplexLU): Allow non-square matrices.\n\t* dbleLU.cc (LU::LU): Likewise.\n\t* base-lu.cc (base_lu::L), base_lu::U, base_lu::P): Likewise.\n\n2002-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n  \t* octave.test/arith/prod-4.m, octave.test/arith/sum-4.m:\n\n2003-02-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::index): Fix thinko.\n\tAdditional compatibility fix.\n\n2003-02-13  Arno Klaassen  <arno@scito.com>\n\n\t* Array2-idx.h, Array2.cc, Array2.h, Array3.cc, Array3.h,\n\tArrayN.cc, ArrayN.h, DiagArray2.cc, DiagArray2.h, MDiagArray2.h:\n\tSprinkle with Array<T>:: as necessary for gcc 3.4.\n\n2003-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::index (idx_vector&, int, const T&)):\n\tCompatibility fix.\n\n2003-02-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CColVector.cc (ComplexColumnVector::extract_n): New function.\n\t* CRowVector.cc (ComplexRowVector::extract_n): Likewise.\n\t* CMatrix.cc (ComplexMatrix::extract_n): Likewise.\n\t* dColVector.cc (ColumnVector::extract_n): Likewise.\n\t* dRowVector.cc (RowVector::extract_n): Likewise.\n\t* dMatrix.cc (Matrix::extract_n): Likewise.\n\n\t* CColVector.cc (ComplexColumnVector::insert): Improve efficiency\n\twith make_unique and xelem.\n\t* CRowVector.cc (ComplexRowVector::insert): Likewise.\n\t* CMatrix.cc (ComplexMatrix::insert, ComplexMatrix::fill,\n\tComplexMatrix::extract, ComplexMatrix::row,\n\tComplexMatrix::column): Likewise.\n\t* dColVector.cc (ColumnVector::insert): Likewise.\n\t* dRowVector.cc (RowVector::insert): Likewise.\n\t* dMatrix.cc (Matrix::insert, Matrix::fill, Matrix::extract,\n\tMatrix::row, Matrix::column): Likewise.\n\n2003-01-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc (imag (double)): Return 0.0 for all args, even NaN.\n\n2003-01-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.cc, dMatrix.cc: Move min and max functions here, from\n\tsrc/DLD-FUNCTIONS/minmax.cc, and make them extern.\n\t* CMatrix.h, dMatrix.h: Provide decls.\n\n2003-01-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-rand.h, oct-rand.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n2003-01-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::index): Fix off-by-one error.\n\n2003-01-16  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* oct-syscalls.cc: Include signal.h.\n\n2003-01-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-syscalls.cc (octave_syscalls::kill): New function.\n\t* oct-syscalls.h: Provide decl.\n\n\n2003-01-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::read): Set size and return immediately if\n\tthere is nothing to read.\n\n2003-01-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-cutils.c: Define _XOPEN_SOURCE.\n\n2003-01-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* getopt.h: Update to version from kpathsearch, so we will install\n\tthe version that we are using.\n\n\t* getopt.c, getopt1.c: Delete.\n\t(INCLUDES): Delete them from the list.  We'll get these files from\n\tkpathsearch.\n\n\t* Makefile.in (liboctave.$(LIBEXT)): Link directly to\n\t../kpathsea/STATIC/*.o.\n\t(liboctave.$(SHLEXT)): Link directly to\t../kpathsea/SHARED/*.o.\n\n2003-01-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (read_int, write_int): Avoid warnings about\n\tunreachable code.\n\n\t* oct-alloc.h (DECLARE_OCTAVE_ALLOCATOR): Define operator delete\n\tto correspond to placement new operator.\n\n\t* dbleDET.cc (DET::value_will_overflow): We want det[1], not det[2].\n\t(DET::value_will_underflow): Likewise.\n\t* CmplxDET.cc (ComplexDET::value_will_overflow): Likewise.\n\t(ComplexDET::value_will_underflow): Likewise.\n\n\t* Makefile.in (distclean): Also remove stamp-prereq.\n\n\t* Array2-idx.h (Array2<T>::assign): If assignment conforms but the\n\tRHS and index are empty matrices, don't do anything.\n\n2002-12-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.cc (make_retval, free_c_array, make_c_names,\n\tdelete_c_names): New helper functions.\n\t(dir_path::find_first_of): New function.\n\t(dir_path::find_all_first_of): Likewise.\n\t* pathsearch.h: Provide decls.\n\n\t* oct-kpse.c (octave_kpse_path_find_first_of): New function.\n\t(octave_kpse_all_path_find_first_of): Likewise.\n\t* oct-kpse.h: Provide decls.\n\n2002-12-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ODESSA.cc (ODESSA::integrate): Handle maxord.\n\t* ODESSA-opts.in: Likewise.\n\n\t* LSODE.cc (ODESSA::integrate): Handle maxord.\n\t* LSODE-opts.in: Likewise.\n\n2002-12-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ODESSA.cc (ODESSA::ODESSA): Initialize \"initialized\" data member\n\tin all constructors.\n\n\t* Makefile.in (liboctave.$(SHLEXT)): Include $(LIBKPATHSEA) here.\n\t(LINK_DEPS): Not here.\n\n2002-12-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* str-vec.cc (string_vector::compare): New static member function.\n\t* str-vec.h: Provide decl.\n\t(string_vector::sort): Use it.\n\t(str_vec_compare): Delete static function.\n\n\t* oct-alloc.h (DECLARE_OCTAVE_ALLOCATOR): Also declare and define\n\ta placement operator new.\n\n2002-12-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Matrix.h: Include mx-ops.h too.\n\t* mx-ops.h: New file.\n\n2002-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASRT.cc, DASRT.h, Array.cc, ArrayN.h, Array.h, Array2.cc,\n\tArray2.h, Array3.cc, Array3.h, Bounds.cc, Bounds.h, CRowVector.h,\n\tCDiagMatrix.cc, CDiagMatrix.h, CMatrix.cc, CMatrix.h,\n\tCRowVector.cc, CColVector.h, ChangeLog, CmplxAEPBAL.cc,\n\tCmplxAEPBAL.h, CmplxCHOL.cc, CmplxCHOL.h, CmplxDET.cc, CmplxDET.h,\n\tCmplxHESS.cc, CmplxHESS.h, CmplxLU.cc, CmplxLU.h, CmplxQR.cc,\n\tCmplxQR.h, CmplxQRP.cc, ArrayN.cc, CmplxQRP.h, CmplxSCHUR.cc,\n\tCmplxSCHUR.h, CmplxSVD.cc, CmplxSVD.h, CollocWt.cc, dMatrix.cc,\n\tCollocWt.h, EIG.h, DASSL.cc, FEGrid.h, DASSL.h, DiagArray2.cc,\n\tDiagArray2.h, EIG.cc, FEGrid.cc, LSODE.cc, LPsolve.cc, LPsolve.h,\n\tLSODE.h, LinConst.cc, LinConst.h, MArray.h, MArray.cc, MArray2.cc,\n\tMArray2.h, MDiagArray2.cc, MDiagArray2.h, Range.cc, NLConst.h,\n\tNLEqn.cc, Range.h, NLEqn.h, Quad.cc, dbleQR.h, Quad.h, base-lu.cc,\n\tbase-lu.h, boolMatrix.cc, boolMatrix.h, dColVector.cc,\n\tdColVector.h, dDiagMatrix.cc, dDiagMatrix.h, dMatrix.h,\n\tdRowVector.cc, dRowVector.h, dbleAEPBAL.cc, dbleAEPBAL.h,\n\tdbleCHOL.cc, dbleCHOL.h, dbleDET.cc, dbleDET.h, dbleHESS.cc,\n\tdbleHESS.h, dbleLU.cc, dbleLU.h, dbleQR.cc, dbleQRP.cc, dbleQRP.h,\n\tdbleSCHUR.cc, dbleSCHUR.h, dbleSVD.cc, dbleSVD.h, idx-vector.cc,\n\tidx-vector.h, oct-alloc.cc, CColVector.cc, DASPK.h, DASPK.cc,\n\tODESSA.h, ODES.h, ODESSA.cc, ODES.cc, chMatrix.h, chMatrix.cc:\n\tUse \"defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION)\" instead of\n\t\"! defined (NO_PRAGMA_INTERFACE_IMPLEMENTATION)\".\n\n2002-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-shlib.cc (octave_dlopen_shlib::open): Use RTLD_GLOBAL too.\n\tFrom Remy Bruno <remy.bruno@libertysurf.fr>\n\n2002-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-specfun.cc: Use F77_FUNC instead of F77_XFCN for calls to\n\tfortran code that should run fast enough that it is not worth all\n\tthe setup costs of F77_XFCN.\n\n\t* Quad.cc (user_function): Surround body of function with\n\tBEGIN_INTERRUPT_WITH_EXCEPTIONS, END_INTERRUPT_WITH_EXCEPTIONS.\n\t* ODESSA.cc (odessa_f, odessa_j, odessa_b): Likewise.\n\t* NLEqn.cc (hybrd1_fcn, hybrj1_fcn): Likewise.\n\t* LSODE.cc (lsode_f, lsode_j): Likewise.\n\t* DASSL.cc (ddassl_f, ddassl_j): Likewise.\n\t* DASRT.cc (ddasrt_f, ddasrt_j, ddasrt_g): Likewise.\n\t* DASPK.cc (ddaspk_f, ddaspk_psol, ddaspk_j): Likewise.\n\n2002-11-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc (octave_ieee_init): Check defined (__osf__) instead\n\tof ! defined (linux).\n\n2002-11-09  Per Persson  <persquare@mac.com>\n\n\t* oct-shlib.cc (octave_dyld_shlib): New class.\n\t(make_shlib): Instantiate octave_dyld_shlib.\n\n2002-11-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.cc, dMatrix.cc: Sprinkle with OCTAVE_QUIT.\n\n\t* ODESSA.cc (odessa_f, odessa_j, odessa_b): Abort on error.\n\n\t* Array.h: Include <cstddef> here.\n\n2002-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASPK.cc (DASPK::do_integrate): Resize rwork and iwork before\n\tusing them.  Accept inequality contraint option of 0.  Assign\n\tpabs_tol and prel_tol before calling DASPK.  Don't redeclare\n\tabs_tol and rel_tol.\n\n\t* cmd-edit.h (command_editor::filename_completion_desired): New\n\tstatic function.\n\t(command_editor::do_filename_completion_desired): New virtual function.\n\t* oct-rl-edit.c (octave_rl_filename_completion_desired): New function.\n\t* oct-rl-edit.h: Provide decl.\n\n\t* Array2.cc (Array2<T>::get_size): #define MALLOC_OVERHEAD to\n\tavoid OS X linker bug.\n\t* ArrayN.cc (ArrayN<T>::get_size): Likewise.\n\n2002-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ODESFunc.h (ODESFunc::ODES_fsub, ODESFunc::ODES_bsub,\n\tODESFunc::ODES_jsub): Reorder args for consistency with other\n\tsolvers.\n\t* ODESSA.cc: Fix all callers.\n\n\t* mx-inlines.cc (MX_BASE_REDUCTION_OP): Also return scalar\n\tMT_RESULT if nr == 1 && nc == 0 && dim == -1 (i.e.,\n\tsum(zeros(1,0)) returns 0, not [](1x0)).\n\n2002-10-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (LINK_DEPS): Include $(FLIBS) here too.\n\n2002-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASRT.cc (DASRT::integrate): Fix computation of lrw\n\t(ddasrt_f): Combine loops.\n\n\t* NLEqn.cc (NLEqn::solve): Return current estimate of solution\n\tinstead of empty vector if user termninates iteration.\n\n2002-10-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-utils.cc (read_inf_nan_na, octave_read_double,\n\toctave_read_complex, octave_write_double, octave_write_complex):\n\tNew functions.\n\t* CMatrix.cc (operator << (std::ostream&, const ComplexMatrix&)):\n\tUse octave_write_complex.\n\t(operator >> (std::istream&, const ComplexMatrix&)):\n\tUse octave_read_complex.\n\t* dMatrix.cc (operator << (std::ostream&, double)):\n\tUse octave_write_double.\n\t(operator >> (std::istream&, double)): Use octave_read_double.\n\n2002-10-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-kpse.c (octave_kpse_clear_dir_cache): Delete.\n\t* oct-kpse.h: Delete decl.\n\t* pathsearch.cc (dir_path::init): Delete unnecessary call to\n\t::octave_kpse_clear_dir_cache.\n\n2002-10-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-sstream.h: Undef HAVE_SSTREAM if using a version of g++\n\tearlier than 3.0.\n\n\t* Makefile.in (LINK_DEPS): Include $(LIBKPATHSEA) here.\n\t(liboctave.$(SHLEXT)): Not here.\n\n2002-10-17  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* oct-shlib.cc (octave_w32_shlib): New class to support Windows.\n\n2002-10-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-lib): Don't bother with versions for\n\t$(SHLBIN) files.\n\n2002-10-16  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Makefile.in (LIB_DEPS): Include $(LIBS).\n\n2002-10-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-cieee.c: Move everything but lo_ieee_init here.\n\t(lo_ieee_Inf_value, lo_ieee_NA_value, lo_ieee_NaN_value):\n\tNew functions.\n\n\t* Makefile.in (install): No need to use cd to create links.\n\t(LINK_DEPS): Include $(LIBOCTAVE_LFLAGS) before list of libraries.\n\n2002-10-14  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Makefile.in: Merge liboctave with liboct-readline and\n\tliboct-pathsearch.\n\tUse link dependencies for shared libs if INCLUDE_LINK_DEPS.\n\t(libraries): Depend on versioned library.\n\t(liboctave.$(SHLEXT), liboctave.$(SHLEXT_VER)): Reverse actions --\n\tbuild unversioned library, symbolic link adds version info.\n\t(install, uninstall): Handle link and load forms of the library\n\tseparately.\n\n2002-10-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-time.cc: Use OCTAVE_USE_WINDOWS_API instead of __WIN32__ and\n\t__CYGWIN__.\n\n\t* file-ops.cc (file_ops::dir_sep_char, file_ops::dir_sep_str,\n\tfile_ops::dir_sep_chars): New static functions to replace\n\tOCTAVE_DIR_SEP_CHAR, OCTAVE_DIR_SEP_STR, OCTAVE_DIR_SEP_CHARS.\n\n\t* oct-env.cc (octave_env::do_set_program_name):\n\tUse file_ops::dir_sep_chars instead of OCTAVE_DIR_SEP_CHARS.\n\t(octave_env::do_base_pathname): Likewise.\n\t(octave_env::do_make_absolute): Likewise.\n\n\t* oct-env.cc (octave_env::do_make_absolute):\n\tUse file_ops::dir_sep_str instead of OCTAVE_DIR_SEP_STR.\n\t(octave_env::do_get_home_directory): Likewise.\n\n\t* file-ops.cc (is_dir_sep): Use dir_sep_chars instead of embedding\n\tthat information here too.\n\t(tilde_find_suffix, isolate_tilde_prefix, tilde_expand_word):\n\tUse file_ops::dir_sep_char instead of OCTAVE_DIR_SEP_CHAR.\n\n\t* file-ops.h: Use OCTAVE_HAVE_WINDOWS_FILESYSTEM and\n\tOCTAVE_HAVE_POSIX_FILESYSTEM instead of __WIN32__ and __CYGWIN__.\n\n2002-10-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-env.h (octave_env::current_directory): Now mutable.\n\t(octave_env:do_getcwd): Now const.\n\n\t* file-ops.h, file-ops.cc (file_ops::is_dir_sep): New function.\n\t(OCTAVE_DIR_SEP_CHAR, OCTAVE_DIR_SEP_STR, OCTAVE_DIR_SEP_CHARS,\n\tOCTAVE_CURRENT_DIR_STR): New macros.\n\t* oct-env.cc (is_dir_sep): Delete.\n\t(octave_env::do_base_pathname): Look for OCTAVE_DIR_SEP_CHARS, not '/'.\n\t(octave_env::do_set_program_name): Likewise.\n\t(octave_env::do_polite_directory_format): Use file_ops::is_dir_sep\n\tinstead of checking for '/'.\n\t(octave_env::pathname_backup): Likewise.\n\t(octave_env::do_absolute_pathname): Likewise.\n\t(octave_env::do_make_absolute): Likewise.\n\tIf dot_path is empty, use getcwd to set current_dir.\n\t(octave_env::do_get_home_directory): Use OCTAVE_DIR_SEP_STR\n\tinstead of \"/\".\n\n2002-10-07  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* lo-cutils.c: On non-Posix Windows systems, include winsock.h.\n\n2002-10-07  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* oct-env.cc (octave_env::do_absolute_pathname): Recognize\n\tabsolute path names under MinGW as well.\n\n2002-10-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-env.cc: Include <cctype> too.\n\n2002-10-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-env.cc (octave_env::do_absolute_pathname): Handle Windows\n\tfilenames.\n\t(octave_env::do_make_absolute): Check for absolute name with\n\tdo_absolute_path.\n\t(octave_env::do_chdir): Likewise.\n\t(is_dir_sep): New function.\n\n2002-10-03  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* oct-time.cc (octave_time::stamp): Better resolution for Windows\n\tsystems.\n\n2002-10-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::read): Clean up error handling logic.\n\n2002-09-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc (file_ops::mkdir): Handle one-arg mkdir here.\n\n\t* lo-specfun.cc (acosh): Call xdacosh, not dacosh.\n\n2002-09-27  Per Persson  <persquare@mac.com>\n\n\t* oct-group.cc (octave_group::octave_group): Dont' forget to set\n\tgr_gid too.\n\n2002-09-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc (xisnan, xfinite, xisinf): Simply forward to\n\tlo_ieee_* functions.\n\t* Makefile.in (LIBOCTAVE_C_SOURCES): Add lo-cieee.c to the list.\n\t* lo-ieee.cc (lo_ieee_double): Rename from ieee_double.\n\t(LO_IEEE_NA_HW, LO_IEEE_NA_LW): Rename from NA_HW and NA_LW.\n\t* lo-cieee.c: New file.\n\t[SCO] (isinf, isnan): Move here from lo-ieee.cc.\n\t* lo-ieee.h: Now all extern \"C\".\n\t(lo_ieee_isnan, lo_ieee_finite, lo_ieee_isinf): Move here from\n\tlo-mappers.cc and rename from xisnan, xfinite, xisinf.\n\n\t* lo-ieee.cc (lo_ieee_hw, lo_ieee_low): Rename from hw and lw.\n\tNow extern.\n\n2002-09-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc, Array.h, Array2.cc, Array2.h, Array3.cc, Array3.h,\n\tArrayN.cc, ArrayN.h, Bounds.cc, Bounds.h, CColVector.cc,\n\tCColVector.h, CDiagMatrix.cc, CDiagMatrix.h, CMatrix.cc,\n\tCMatrix.h, CRowVector.cc, CRowVector.h, CmplxAEPBAL.cc,\n\tCmplxAEPBAL.h, CmplxCHOL.cc, CmplxCHOL.h, CmplxDET.cc, CmplxDET.h,\n\tCmplxHESS.cc, CmplxHESS.h, CmplxLU.cc, CmplxLU.h, CmplxQR.cc,\n\tCmplxQR.h, CmplxQRP.cc, CmplxQRP.h, CmplxSCHUR.cc, CmplxSCHUR.h,\n\tCmplxSVD.cc, CmplxSVD.h, CollocWt.cc, CollocWt.h, DAE.cc,\n\tDASPK.cc, DASPK.h, DASRT.cc, DASRT.h, DASSL.cc, DASSL.h,\n\tDiagArray2.cc, DiagArray2.h, EIG.cc, EIG.h, FEGrid.cc, FEGrid.h,\n\tLPsolve.cc, LPsolve.h, LSODE.cc, LSODE.h, LinConst.cc, LinConst.h,\n\tMArray.cc, MArray.h, MArray2.cc, MArray2.h, MDiagArray2.cc,\n\tMDiagArray2.h, NLConst.h, NLEqn.cc, NLEqn.h, ODES.cc, ODES.h,\n\tODESSA.cc, ODESSA.h, Quad.cc, Quad.h, Range.cc, Range.h,\n\tbase-lu.cc, base-lu.h, boolMatrix.cc, boolMatrix.h, chMatrix.cc,\n\tchMatrix.h, dColVector.cc, dColVector.h, dDiagMatrix.cc,\n\tdDiagMatrix.h, dMatrix.cc, dMatrix.h, dRowVector.cc, dRowVector.h,\n\tdbleAEPBAL.cc, dbleAEPBAL.h, dbleCHOL.cc, dbleCHOL.h, dbleDET.cc,\n\tdbleDET.h, dbleHESS.cc, dbleHESS.h, dbleLU.cc, dbleLU.h,\n\tdbleQR.cc, dbleQR.h, dbleQRP.cc, dbleQRP.h, dbleSCHUR.cc,\n\tdbleSCHUR.h, dbleSVD.cc, dbleSVD.h, idx-vector.cc, idx-vector.h,\n\toct-alloc.cc:\n\tIf __GNUG__, use pragma interface/implementation.  Allow this to\n\tbe turned off by defining NO_PRAGMA_INTERFACE_IMPLEMENTATION.\n\n2002-09-26  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* file-ops.cc (file_ops::readlink): Don't declare buffer if\n\tsystem readlink function is not available.\n\n\t* lo-mappers.cc (xerf, xerfc): Delete.\n\t* lo-mappers.h (xerf, xerfc): Delete decls.\n\n\t* lo-mappers.cc: Remove unused #define M_PI.\n\t* lo-specfun.cc: Add #define M_PI if needed.\n\n2002-09-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.cc (do_decode_prompt_string): Cope with possibility\n\tthat geteuid doesn't exist.\n\n\t* LP.h: Rename LP class to octave_LP.\n\tLPsolve.h: Change all uses.\n\n\t* file-ops.cc, oct-passwd.cc oct-syscalls.cc oct-group.cc: Remove\n\tincorrect token-pasting op.\n\n\t* statdefs.h [! S_ISLNK]: undef HAVE_LSTAT instead of trying to\n\tdefine lstat.\n\n2002-09-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc, Array.h, Array2.cc, Array2.h, Array3.cc, Array3.h,\n\tArrayN.cc, ArrayN.h, Bounds.cc, Bounds.h, CColVector.cc,\n\tCColVector.h, CDiagMatrix.cc, CDiagMatrix.h, CMatrix.cc,\n\tCMatrix.h, CRowVector.cc, CRowVector.h, CmplxAEPBAL.cc,\n\tCmplxAEPBAL.h, CmplxCHOL.cc, CmplxCHOL.h, CmplxDET.cc, CmplxDET.h,\n\tCmplxHESS.cc, CmplxHESS.h, CmplxLU.cc, CmplxLU.h, CmplxQR.cc,\n\tCmplxQR.h, CmplxQRP.cc, CmplxQRP.h, CmplxSCHUR.cc, CmplxSCHUR.h,\n\tCmplxSVD.cc, CmplxSVD.h, CollocWt.cc, CollocWt.h, DAE.cc,\n\tDASPK.cc, DASPK.h, DASRT.cc, DASRT.h, DASSL.cc, DASSL.h,\n\tDiagArray2.cc, DiagArray2.h, EIG.cc, EIG.h, FEGrid.cc, FEGrid.h,\n\tLPsolve.cc, LPsolve.h, LSODE.cc, LSODE.h, LinConst.cc, LinConst.h,\n\tMArray.cc, MArray.h, MArray2.cc, MArray2.h, MDiagArray2.cc,\n\tMDiagArray2.h, NLConst.h, NLEqn.cc, NLEqn.h, ODES.cc, ODES.h,\n\tODESSA.cc, ODESSA.h, Quad.cc, Quad.h, Range.cc, Range.h,\n\tbase-lu.cc, base-lu.h, boolMatrix.cc, boolMatrix.h, chMatrix.cc,\n\tchMatrix.h, dColVector.cc, dColVector.h, dDiagMatrix.cc,\n\tdDiagMatrix.h, dMatrix.cc, dMatrix.h, dRowVector.cc, dRowVector.h,\n\tdbleAEPBAL.cc, dbleAEPBAL.h, dbleCHOL.cc, dbleCHOL.h, dbleDET.cc,\n\tdbleDET.h, dbleHESS.cc, dbleHESS.h, dbleLU.cc, dbleLU.h,\n\tdbleQR.cc, dbleQR.h, dbleQRP.cc, dbleQRP.h, dbleSCHUR.cc,\n\tdbleSCHUR.h, dbleSVD.cc, dbleSVD.h, idx-vector.cc, idx-vector.h,\n\toct-alloc.cc:\n\tUse USE_PRAGMA_INTERFACE_IMPLEMENTATION instead of __GNUG__\n\tto decide whether to use the interface/implementation pragmas.\n\n2002-09-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (INCLUDES): Add lo-sstream.h to the list.\n\n2002-08-17  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* CmplxCHOL.h, CollocWt.h, cmd-edit.h, oct-shlib.h: Don't use\n\tqualified names.\n\n2002-08-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h, Array2-idx.h, DiagArray2.cc, Array2.cc, Array3.cc,\n\tArrayN.cc: Add typename where needed.\n\n\t* DASPK.cc: Include lo-sstream.h and use macros instead of using\n\tstrstream classes directly.\n\t* DASRT.cc: Likewise.\n\t* DASSL.cc: Likewise.\n\t* LSODE.cc: Likewise.\n\t* ODESSA.cc: Likewise.\n\n\t* cmd-hist.cc: Don't include <strstream>.\n\t* oct-shlib.cc: Likewise.\n\n\t* lo-sstream.h: New file.\n\n2002-08-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* LSODE.h (rel_tol, abs_tol, px, pabs_tol, piwork, prwork, itol):\n\tNew data members.\n\t(LSODE::sanity_checked): Delete unused data member.\n\n\t* DASPKL.h (initialized, abs_tol, rel_tol, px, pxdot, pabs_tol,\n\tprel_tol, pinfo, piwork, prwork): New data members.\n\t* DASSL.h (DASSL): Likewise.\n\n\t* DASRT.h (DASRT::sanity_checked): Delete unused data member.\n\n\t* DASRT.cc (DASRT::integrate (double)): Better handling of\n\tinitialization, changes in options, etc.\n\t* DASPK.cc (DASPK::do_integrate): Likewise.\n\t* DASSL.cc (DASSL::do_integrate): Likewise.\n\t* LSODE.cc (LSODE::do_integrate): Likewise.\n\n2002-08-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DAEFunc.h (DAEFunc::reset): New data member.\n\t* DAERTFunc.h (DAERTFunc::reset): Likewise.\n\n\t* base-de.h (base_diff_eqn::set_stop_time): Force restart here.\n\t(base_diff_eqn::clear_stop_time): Likewise.\n\n\t* DASSL.cc (DASSL::do_integrate (double)): Handle more optoins.\n\t* DASPK.cc (DASPK::do_integrate (double)): Likewise.\n\n2002-08-15  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* DASPK-opts.in, DASPK.h: Move include to .in file.\n\t* DASRT-opts.in, DASRT.h: Likewise.\n\t* DASSL-opts.in, DASSL.h: Likewise.\n\t* LSODE-opts.in, LSODE.h: Likewise.\n\t* NLEqn-opts.in, NLEqn.h: Likewise.\n\t* ODESSA-opts.in, ODESSA.h: Likewise.\n\n2002-08-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* LSODE.cc (LSODE::error_message): Also return current T on\n\tfailures when that makes sense.\n\t* DASSL.cc (DASSL::error_message): Likewise.\n\t* DASRT.cc (DASRT::error_message): Likewise.\n\t* DASPK.cc (DASPK::error_message): Likewise.\n\t* ODESSA.cc (ODESSA:error_message): Likewise.\n\n\t* Makefile.in (liboct-pathsearch.$(SHLEXT_VER)): Link to\n\t$(LIBKPATHSEA) here.\n\n2002-08-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc (lo_ieee_is_NA): New function.\n\t(lo_ieee_is_NaN_or_NA): New function.\n\t(octave_NA): New global value.\n\t(octave_ieee_init): Initialize it.\n\t* lo-mappers.cc (octave_is_NA): New function.\n\t(octave_is_NaN_or_NA): New function.\n\t(xisnan): Return false if NaN looks like a missing value.\n\t(xisnan (const Complex&)): Use xisnan here.\n\n2002-08-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.h (ComplexMatrix::all, ComplexMatrix::any,\n\tComplexMatrix::cumprod, ComplexMatrix::cumsum,\n\tComplexMatrix::prod, ComplexMatrix::sum, ComplexMatrix::sumsq):\n\tDefault value for dim is -1, not 0.\n\t* dMatrix.h (Matrix::all, Matrix::any, Matrix::cumprod,\n\tMatrix::cumsum, Matrix::prod, Matrix::sum, Matrix::sumsq): Likewise.\n\t* boolMatrix.h (boolMatrix:all, boolMatrix::any): Likewise.\n\t* chMatrix.h (charMatrix::all, charMatrix::any): Likewise.\n\n\t* mx-inlines.cc (MX_ANY_ALL_OP_ROW_CODE, MX_ANY_ALL_OP_COL_CODE):\n\tNew macros.\n\t(MX_ANY_ALL_OP): Define MX_ANY_ALL_OP using them and\n\tMX_BASE_REDUCTION_OP.\n\t(MX_CUMULATIVE_OP): Fix spelling.  Change all uses.\n\n2002-08-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* chMatrix.h, chMatrix.cc (charMatrix::any, charMatrix::all):\n\tReturn boolMatrix, not Matrix.\n\n\t* mx-inlines.cc (MX_ANY_ALL_OP, MX_ALL_OP, MX_ANY_OP): New macros.\n\t* dMatrix.cc (Matrix::any): Replace guts with MX_ANY_OP.\n\t(Matrix::all): Replace guts with MX_ALL_OP.\n\t* CMatrix.cc (ComplexMatrix::any): Replace guts with MX_ANY_OP.\n\t(ComplexMatrix::all): Replace guts with MX_ALL_OP.\n\t* boolMatrix.cc (boolMatrix::any): Replace guts with MX_ANY_OP.\n\t(boolMatrix::all): Replace guts with MX_ALL_OP.\n\t* chMatrix.cc (charMatrix::any): Replace guts with MX_ANY_OP.\n\t(charMatrix::all): Replace guts with MX_ALL_OP.\n\n\t* dMatrix.h (Matrix::any): New arg, dim.\n\t(Matrix::all): Likewise.\n\t* CMatrix.h (ComplexMatrix::any): Likewise.\n\t(ComplexMatrix::all): Likewise.\n\t* boolMatrix.h (boolMatrix::any): Likewise.\n\t(boolMatrix::all): Likewise.\n\t* chMatrix.h (charMatrix::any): Likewise.\n\t(charMatrix::all): Likewise.\n\n\t* Makefile.in: Use $@-t instead of $@.t.\n\n2002-07-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-specfun.cc (gammainc): New arg, err, for scalar version.\n\tUse it in matrix versions to avoid spewing multiple errors.\n\tCall xgammainc instead of dgamit.\n\n2002-07-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.cc (ComplexMatrix::ComplexMatrix (const boolMatrix&)):\n\tGet rows and columns right in loop.\n\t(ComplexMatrix::ComplexMatrix (const charMatrix&)): Likewise.\n\n2002-07-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASPK.cc (DASPK::do_integrate): Allow array tolerances.\n\t* DASRT.cc (DASRT::integrate): Likewise.\n\t* DASSL.cc (DASSL::do_integrate): Likewise.\n\n\t* Quad.cc: Don't pass tolerances in constructors.\n\n\t* DASPK-opts.in, DASRT-opts.in, DASSL-opts.in, LSODE-opts.in,\n\tNLeqn-opts.in, ODESSA-opts.in, Quad-opts.in: New files.\n\t* DASPK-opts.h, DASRT-opts.h, DASSL-opts.h, LSODE-opts.h,\n\tNLeqn-opts.h, ODESSA-opts.h, Quad-opts.h: Generate automatically\n\tfrom corresponding .in files.\n\t* LSODE.h, Quad.h: Replace options class definitions with included\n\tfile.\n\t* Makefile.in (OPTS_INC_SRC, OPTS_INC): New variables, new rule to\n\tcreate OPTS_INC files from OPTS_INC_SRC files.\n\t(stamp-prereq): New target.\n\t(libraries): Depend on stamp-prereq.\n\tInclude stamp-prereq along with $(MAKEDEPS).\n\n2002-07-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* base-de.h (base_diff_eqn::istate): New data member.\n\t(base_diff_eqn::integration_state): New member function.\n\t* LSODE.h, LSODE.cc, ODESSA.h, ODESSA.cc: Delete corresponding\n\tdata members and functions.\n\t* DASPK.h, DASRT.h, DASSL.h: Delete idid data member.\n\t* DASPK.cc, DASRT.cc, DASSL.cc: Use istate instead of idid.\n\n2002-07-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* base-de.h (base_diff_eqn::stop_time,\n\tbase_diff_eqn::stop_time_set, base_diff_eqn::restart,\n\tbase_diff_eqn::integration_error): New data members.\n\t(base_diff_eqn::set_stop_time, base_diff_eqn::clear_stop_time,\n\tbase_diff_eqn::force_restart, base_diff_eqn::integration_ok,\n\tbase_diff_eqn::error_message): New member functions.\n\t* LSODE.h, LSODE.cc, DASSL.h, DASSL.cc, DASPK.h, DASPK.cc,\n\tDASRT.h, DASRT.cc, ODESSA.h, ODESSA.cc: Delete corresponding data\n\tmembers and functions.\n\n\t* DASRT.h (DASRT::set_ng, DASRT::get_ng): Delete\n\t* DASRT.cc (DASRT::DASRT): Set ng here.\n\t(DASRT::integrate): Don't forget to set nn.\n\n\t* DAEFunc.h (DAEFunc): Jacobian function now follows format of DASSL.\n\t* DASSL.cc (ddassl_j): Make it work.\n\t* DASPK.cc (ddaspk_j): Likewise.\n\n\t* DAE.cc: Delete.\n\n\t* DAERT.h, DAERTFunc.h, DASRT.h, DASRT.cc: New files for DAE\n\tsolving with root finding.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* base-dae.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\t* DAE.h (DAE): Derive from base_diff_alg_eqn, not base_diff_eqn.\n\n2002-07-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ODE.h: Move integrate and do_integrate method declarations and\n\tdefinitions here.\n\t* base-de.h: From here.\n\n\t* ODES.h, ODES.cc, ODESFunc.h, ODESSA.h, ODESSA.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\t(LIBOCTAVE_CXX_SOURCES):\n\n2002-07-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* NLEqn.cc (NLEqn::error_message): New function.\n\t* NLEqn.h (NLEqn::solution_state, NLEqn::solution_ok): New functions.\n\n2002-07-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-utils.cc (octave_fgetl): New function.\n\t* cmd-edit.cc (do_readline): Use it instead of octave_fgets.\n\n2002-05-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* LSODE.cc (LSODE::error_message): New function.\n\t* LSODE.h: Provide decl.\n\t(LSODE::integration_state): New function.\n\t(LSODE::integration_ok): New function.\n\n2002-05-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* LSODE.cc (LSODE_options::x_integration_method): New data member.\n\t(LSODE_options::set_integration_method,\n\tLSODE_options::integration_method): New functions.\n\n\t* LSODE.h (LSODE_options::x_absolute_tolerance): Now Array<double>.\n\tChange all uses.\n\t(LSODE_OPTIONS::absolute_tolerance): Return Array<double>, not double.\n\t(LSODE_OPTIONS::set_absolute_tolerance (const Array<double>&)):\n\tNew function.\n\n\t* Array.h (Array::fortran_vec): New const version.\n\n2002-05-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.cc (gnu_readline::history_search_backward): New function.\n\t(gnu_readline::history_search_forward): Likewise.\n\t(gnu_readline::gnu_readline): Use them instead of passing pointers\n\tto extern \"C\" functions to octave_rl_ad_defun.\n\n2002-05-22  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* DASPK.cc (ddaspk_psol): Return value.\n\t* oct-rl-edit.c: Use /* ... */ to comment.\n\n2002-05-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASSL.h (DASSL_options::init): Undo previous change.\n\t(DASSL_options::set_absolute_tolerance): Likewise.\n\t* LSODE.h (LSODE_options::init): Likewise.\n\t(LSODE_options::set_absolute_tolerance): Likewise.\n\n\t* DASPK.h (DASPK_options::init): Use default absolute tolerance of\n\tsqrt(eps), not eps^2.\n\tDASPK_options::set_absolute_tolerance): Likewise.\n\n2002-05-17  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* Array.h (Array<T>::resize_fill_value): Return default initialized\n\tobject.\n\n2002-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-rl-edit.c (OCTAVE_RL_SAVE_STRING): New macro.\n\t(octave_rl_set_name, octave_rl_set_basic_quote_characters): Use it.\n\t(octave_rl_set_basic_word_break_characters,\n\toctave_rl_set_completer_word_break_characters): New functions.\n\t* oct-rl-edit.h: Provide decls.\n\t* cmd-edit.cc (gnu_readline::do_set_basic_word_break_characters,\n\tgnu_readline::do_set_completer_word_break_characters): New functions.\n\t(command_editor::set_basic_quote_characters,\n\tcommand_editor::set_completion_append_character): New static functions.\n\t* cmd-edit.h: Provide decls.\n\t(command_editor::do_set_basic_word_break_characters,\n\tcommand_editor::do_set_completer_word_break_characters):\n\tNew virtual functions.\n\n\t* CMatrix.h, boolMatrix.h, chMatrix.h, dMatrix.h\n\t(resize_fill_value): New static function.\n\n\t* Array-idx.h (Array<T>::index): New args, resize_ok and\n\tresize_fill_value.\n\t* Array2-idx.h (Array2<T>::index): Likewise.\n\t* ArrayN-idx.h (ArrayN<T>::index): Likewise.\n\n\t* Array2.cc (Array<T>::print_info): New function.\n\t* Array2.h: Provide decl.\n\n\t* Array.cc (Array<T>::print_info): New function.\n\t* Array.h: Provide decl.\n\n2002-05-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.h (idx_vector::idx_vector (int)): New function.\n\t(idx_vector_rep::idx_vector_rep (int)): New decl.\n\t* idx-vector.cc (idx_vector_rep::idx_vector_rep (int)): New function.\n\n\t* Array.h (Array<T>::resize_fill_value (void)): New static function.\n\t(assign (Array<LT>&, const Array<RT>&)): Use it.\n\t* Array2.h (assign (Array2<LT>&, const Array2<RT>&)): Use it.\n\t* ArrayN.h (assign (ArrayN<LT>&, const ArrayN<RT>&)): Use it.\n\n2002-05-02  Cai Jianming  <caijianming@yahoo.co.uk>\n\n\t* Array3.h (Array3<T>::checkelem): Improve error message.\n\t* ArrayN.h (ArrayN<T>::range_error): Likewise.\n\t* DiagArray2.cc (DiagArray2<T>::checkelem): Likewise.\n\t* DiagArray2.cc (DiagArray2<T>::operator ()): Likewise.\n\n2002-04-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASSL.h (DASSL_options::init): Undo previous change.\n\t(DASSL_options::set_absolute_tolerance): Likewise.\n\n2002-04-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASPK.h, DASPK.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n2002-04-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::index (idx_vector&, idx_vector&) const):\n\tSimplify indexing when one or both of the indices are empty.\n\n2002-04-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASSL.h (DASSL_options::init): Set absolute tolerance to eps ^ 2.\n\t(DASSL_options::set_absolute_tolerance): Likewise.\n\t* LSODE.h (LSODE_options::init): Likewise.\n\t(LSODE_options::set_absolute_tolerance): Likewise.\n\n2002-04-03  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\t* f2c-main.c (MAIN_, MAIN__): Delete.  Use F77_DUMMY_MAIN instead.\n\t* file-stat.cc (file_stat::update_internal, file_stat::copy):\n\tUse HAVE_STRUCT_STAT_ST_RDEV instead of HAVE_ST_RDEV.\n\tUse HAVE_STRUCT_STAT_ST_BLKSIZE instead of HAVE_ST_BLKSIZE.\n\tUse HAVE_STRUCT_STAT_ST_BLOCKS instead of HAVE_ST_BLOCKS.\n\t* file-stat.h: Likewise.\n\t* oct-time.cc (octave_time::octave_time, octave_base_tm::strftime,\n\toctave_base_tm::init, octave_strptime::init): Use HAVE_TM_ZONE\n\tinstead of HAVE_STRUCT_TM_TM_ZONE.\n\t* strftime.c: Likewise.\n\t* lo-specfun.cc, mach-info.cc, CColVector.cc, CMatrix.cc,\n\tCRowVector.cc, CmplxAEPBAL.cc, CmplxCHOL.cc, CmplxHESS.cc,\n\tCmplxLU.cc, CmplxQR.cc, CmplxQRP.cc, CmplxSCHUR.cc, CmplxSVD.cc,\n\tCollocWt.cc, DASSL.cc, EIG.cc, LSODE.cc, NLEqn.cc, Quad.cc,\n\tdColVector.cc, dMatrix.cc, dRowVector.cc, dbleAEPBAL.cc,\n\tdbleCHOL.cc, dbleHESS.cc, dbleLU.cc, dbleQR.cc, dbleQRP.cc,\n\tdbleSCHUR.cc, dbleSVD.cc: Use F77_FUNC instead of F77_FCN.\n\n2002-04-02  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* CmplxQR.cc (ComplexQR::init): Use economy QR decomposition\n\tinternally when the user requests it.\n\t* CmplxQRP.cc (ComplexQRP::init): Ditto.\n\t* dbleQR.cc (QR::init): Ditto.\n\t* dbleQRP.cc (QRP::init): Ditto.\n\n2002-02-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-fftw.cc (octave_fftw::fft2d): Avoid having to find a\n\tdefinition for NULL by passing 0 as the last arg to fftwnd_one.\n\t(octave_fftw::ifft2d): Likewise.\n\n2002-02-22  Paul Kienzle  <pkienzle@jazz.ncnr.nist.gov>\n\n\t* lo-mappers.cc (arg): Simply call atan2 (0.0, x).\n\n2001-12-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data-conv.cc (LS_DO_READ): Don't do anything unless len > 0.\n\t(LS_DO_WRITE): Likewise.\n\n2001-11-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mx-inlines.cc (MX_CUMMULATIVE_OP): New macro.\n\t* CMatrix.cc (ComplexMatrix::cumprod, ComplexMatrix::cumsum): Use it.\n\t* dMatrix.cc (Matrix::cumprod, Matrix::cumsum): Likewise.\n\n\t* mx-inlines.cc (MX_REDUCTION_OP, MX_REDUCTION_OP_COL_EXPR,\n\tMX_REDUCTION_OP_ROW_EXPR): New macros.\n\t* dMatrix.cc (Matrix::prod, Matrix::sum): Use MX_REDUCTION_OP.\n\t* CMatrix.cc (ComplexMatrix::prod, ComplexMatrix::sum): Likewise.\n\n\t* mx-inlines.cc (MX_BASE_REDUCTION_OP): New macro.\n\tDIM == -1 now means no orientation for vector sums.\n\t* dMatrix.cc (ComplexMatrix::sumsq): Use it.\n\t* CMatrix.cc (ComplexMatrix::sumsq): Likewise.\n\n2001-11-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Range.cc (Range::nelem_internal): Special case ranges that must\n\thave zero elements.\n\n2001-11-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Split out readline and pathsearch functionality\n\tinto separate liboct-readline and liboct-pathsearch libraries.\n\n\t* oct-rl-edit.c (octave_rl_clear_screen): Call rl_clear_screen,\n\tnot _rl_clear_screen.  Temporarily redefine rl_redisplay_function\n\tto do nothing for this call to rl_clear_screen.\n\n2001-10-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASSL.cc (ddassl_f): Handle IRES returned from user supplied\n\tfunction.\n\t* DAEFunc.h (DAERHSFunc): Add IRES to prototype.\n\n2001-06-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::inverse, Matrix::solve, Matrix::determinant,\n\tMatrix::inverse): Handle the case of rcond being a NaN the same as\n\ta signular matrix.  From \"Jianming\" <caijianming@yahoo.co.uk>.\n\t* CMatrix.cc (ComplexMatrix::inverse, ComplexMatrix::solve,\n\tComplexMatrix::determinant, ComplexMatrix::inverse): Likewise.\n\n2001-05-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* chMatrix.cc (charMatrix::row_as_string): New parameter, raw.\n\n\t* Array-i.cc, Array-s.cc, Array-d.cc, Array-ch.cc, Array-C.cc,\n\tArray-b.cc: Instantiate three arg assign functions.\n\n\t* ArrayN.cc (assign (ArrayN<LT>&, const ArrayN<RT>&, const LT&)):\n\tNew arg, resize_fill_value.\n\t* ArrayN.h: Provide declaration.\n\t(assign (ArrayN<LT>&, const ArrayN<RT>&): Define here by calling\n\tthree arg version.\n\n\t* Array3.cc (assign (Array3<LT>&, const Array3<RT>&, const LT&)):\n\tNew arg, resize_fill_value.\n\t* Array3.h: Provide declaration.\n\t(assign (Array3<LT>&, const Array3<RT>&): Define here by calling\n\tthree arg version.\n\n\t* Array2.cc (assign (Array2<LT>&, const Array2<RT>&, const LT&)):\n\tNew arg, resize_fill_value.\n\t* Array2.h: Provide declaration.\n\t(assign (Array2<LT>&, const Array2<RT>&): Define here by calling\n\tthree arg version.\n\n\t* Array.cc (assign (Array<LT>&, const Array<RT>&, const LT&)):\n\tNew arg, resize_fill_value.\n\t* Array.h: Provide declaration.\n\t(assign (Array<LT>&, const Array<RT>&): Define here by calling\n\tthree arg version.\n\n2001-05-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.cc (dir_path::set_program_name): Set the environment\n\tvariables SELFAUTOLOC, SELFAUTODIR, SELFAUTOPARENT, and TEXMFDBS\n\tto the empty string.\n\n2001-05-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2.h (Array2<T>::operator = (const Array2<T>&)):\n\tDon't check for rep != a.rep.\n\n2001-05-02  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* oct-fftw.h, oct-fftw.cc: New files.\n\t* Makefile.in (INCLUDES, SOURCES): Add new files.\n\t* CMatrix.cc (ComplexMatrix::{fourier, ifourier, fourier2d,\n\tifourier2d}): Use fftw if available.\n\t* dMatrix.cc (Matrix::{fourier, ifourier, fourier2d, ifourier2d}):\n\tLikewise.\n\n2001-04-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-lib): Don't use mk-libdir-link.\n\t(install-inc): Don't use mk-includedir-link.\n\n2001-02-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-cutils.c (octave_gethostname): New function.\n\t* lo-utils.h: Provide declaration.\n\t* oct-env.cc (octave_env::do_get_host_name):\n\tCall octave_gethostname, instead of gethostname.\n\n\t* lo-cutils.c (gethostname): Define here.\n\t* lo-sysdep.cc: Not here.\n\n2001-02-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-cutils.c: Don't declare strptime.\n\t(oct_strptime): Cast return type of strptime to char*.\n\n2001-02-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-rl-edit.c (octave_rl_newline): Call rl_newline with two args.\n\t(octave_rl_set_name): call rl_re_read_init_file with two args.\n\t(octave_rl_read_init_file): Ditto.\n\t(octave_rl_clear_undo_list): Call rl_free_undo_list, not\n\tfree_undo_list.\n\t(octave_rl_completion_matches): Call rl_completion_matches, not\n\tcompletion_matches.\n\t(octave_rl_enable_paren_matching): New function.\n\t(octave_rl_set_blink_matching_paren_flag): Delete.\n\t(octave_rl_get_blink_matching_paren_flag): Delete.\n\n\t* lo-mappers.h, lo-mappers.cc (log10 (const Complex&),\n\ttanh (const Complex&)): Declare and define if not\n\tCXX_ISO_COMPLIANT_LIBRARY.\n\n2001-02-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.h (tanh (const Complex&)): Only declare if not\n\tCXX_ISO_COMPLIANT_LIBRARY.\n\n2001-02-05  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* lo-mappers.cc (tanh (const Complex&)): Only define if not\n\tCXX_ISO_COMPLIANT_LIBRARY.\n\n\t* Makefile.in (TEMPLATE_AR, TEMPLATE_ARFLAGS): Use to create\n\tarchive libraries containing templates.\n\n\t* ArrayN-idx.h (freeze, all_ok, any_orig_empty, any_zero_len,\n\tget_zero_len_size, all_colon_equiv): Inline.\n\t(ArrayN<T>::index): Rename idx to arr_idx.\n\t* ArrayN.cc (ArrayN<T>::index, ArrayN<T>::compute_index,\n\tArrayN<T>::get_size, ArrayN<T>::range_error, ArrayN<T>::range_error,\n\tincrement_index, ArrayN<T>::resize, ArrayN<T>::insert): Likewise.\n\n2001-02-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.h, lo-mappers.cc (tan (const Complex&),\n\tlog10 (const Complex&)): Delete.\n\n\t* oct-cmplx.h: Define forwarding functions for real, imag, abs,\n\targ, norm, conj, polar, cos, cosh, exp, log, log10, pow, sin,\n\tsinh, sqrt, tan, and tanh.\n\n2001-01-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc, help.cc, load-save.cc, pr-output.cc, utils.cc:\n\tAdd std:: namespace qualifier as needed.\n\n\t* mx-inlines.cc: Rename all functions with mx_inline_ prefix.\n\tChange all uses to match.\n\n2001-01-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-cutils.c: Don't delcare strptime.\n\n2001-01-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.cc (operator * (const ComplexMatrix&, const ComplexMatrix&):\n\tReturn correct size result for empty matrix case.\n\n2000-12-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc (xmin (const Complex&, const Complex& y):\n\tIf args are equal in magnitude, return first arg instead of\n\tsecond.\n\n2000-12-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Range.cc (Range::nelem_internal): Call tfloor, not round, but\n\tthen try harder to compute correct number of elements.\n\n\t* dMatrix.cc (Matrix::lssolve): Ask DGELSS for size of work vector.\n\t* CMatrix.cc (ComplexMatrix::lssolve): Likewise, for ZGELSS.\n\n2000-12-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Range.cc (Range::nelem_internal): Call round here, not tfloor.\n\tRename n_intervals to be n_elt.\n\n\t* strptime.c: Surround everything after including config.h in\n\t#ifndef HAVE_STRPTIME ... #endif.\n\n2000-11-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-idx.h (assign): When resizing, cast fill value to LT.\n\t* Array2-idx.h (MAYBE_RESIZE_LHS): Likewise.\n\n2000-11-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* MArray-defs.h: Protect against multiple inclusion.\n\n2000-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data-conv.h (enum save_type): Move LS_U_LONG and LS_LONG to the\n\tend of the list, to be compatible with previous versions of Octave.\n\n2000-11-16  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* oct-time.cc (DEFINE_SET_INT_FIELD_FCN): Don't check limits here,\n\tsince mktime is supposed to `normalize' the results for us.\n\n2000-10-31  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* Array2.cc (Array2<T>::transpose): Avoid copy for empty matrices\n\tand vectors.  Use xelem for faster access to elements when copying.\n\n2000-10-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.cc (ComplexMatrix::cumsum, ComplexMatrix::cumprod):\n\tCorrect indexing for operation across rows.\n\t* dMatrix.cc (Matrix::cumsum, Matrix::cumprod): Likewise.\n\n2000-10-12  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* Array2-idx.h (Array2<T>::index (idx_vector&)): Avoid copying\n\telements if arg is a colon.\n\n2000-10-12  Cai Jianming  <caijianming@yahoo.co.uk>\n\n\t* dMatrix.cc (Matrix::cumprod (int) const): New arg, DIM.\n\t(Matrix::cumsum (int) const): Likewise.\n\t(Matrix::prod (int) const): Likewise.\n\t(Matrix::sum (int) const): Likewise.\n\t(Matrix::sumsq (int) const): Likewise.\n\t* CMatrix.cc (ComplexMatrix::cumprod (int dim) const): Likewise.\n\t(ComplexMatrix::cumsum (int) const): Likewise.\n\t(ComplexMatrix::prod (int) const): Likewise.\n\t(ComplexMatrix::sum (int) const): Likewise.\n\t(ComplexMatrix::sumsq (int) const): Likewise.\n\n2000-10-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::index (idx_vector&)): Correctly set\n\tsize if Array<T>::index returns an empty array.\n\n2000-08-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc (file_ops::link, file_ops::symlink,\n\tfile_ops::readlink): New functions.\n\n2000-08-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::index (idx_vector&)): If a scalar is\n\tindexed, always return an object the same size as the index arg.\n\n\t* oct-time.cc (octave_base_tm::strftime): Return empty string for\n\tempty format.\n\n2000-07-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-cutils.c (oct_strptime): New function.\n\t* oct-time.cc (octave_strptime::init): Call it instead of strptime.\n\tDon't declare strptime.  Don't define _XOPEN_SOURCE or _BSD_SOURCE.\n\n2000-07-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-time.cc: Comment out _BSD_SOURCE and _XOPEN_SOURCE definitions.\n\n\t* Makefile.in (MATRIX_INC): Add ArrayN-idx.h to the list.\n\n2000-06-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.h (read_int): Provide declaration.\n\n2000-06-29  James R. Van Zandt  <jrv@vanzandt.mv.com>\n\n\t* data-conv.cc (read_doubles): Handle EIGHT_BYTE_INT cases.\n\t(write_doubles): Ditto.\n\t* data-conv.h: Ditto.\n\t(enum save_type): New values, LS_U_LONG and LS_LONG.\n\n2000-06-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* boolMatrix.h: Declare MM_CMP_OPS here.\n\t* boolMatrix.cc: Define them here.\n\n2000-06-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (assign): Allow x(bool) = RHS to succeed if x is\n\tpreviously undefined and set size of x to size of bool index.\n\t* idx-vector.cc (IDX_VEC_REP::maybe_convert_one_zero_to_idx):\n\tAllow z_len to be zero.\n\t(IDX_VEC_REP::freeze): If z_len is zero, set frozen_at_z_len to len.\n\tIf frozen, don't assert that frozen_at_z_len == z_len.\n\n2000-05-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-rl-edit.c (octave_rl_clear_screen): Call _rl_clear_screen\n\tinstead of rl_clear_screen.\n\n2000-05-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-d.cc: Instantiate ArrayN<double> here too.\n\t* Array-idx-vec.cc, ArrayN-idx.h, ArrayN.cc, ArrayN.h: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n2000-04-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array<T>::operator =): Don't set max_indices to 1 here.\n\n2000-03-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-sysdep.h: octave_chdir returns int, not bool.\n\n2000-03-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (liboctave.$(SHLEXT)): Delete target\n\tbefore rebuilding.\n\n2000-03-21  Ben Sapp  <bsapp@nua.lampf.lanl.gov>:\n\n\t* Makefile.in (liboctave.$(LIBEXT)): New target.\n\t(libraries): Depend only on library targets, not archive members.\n\n2000-03-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: (objects): New target.\n\n\t* lo-cutils.c: New file.\n\t* Makefile.in (SOURCES): Add it to the list.\n\t* lo-utils.h: Declare octave_qsort here.\n\t* Array.h (Array::qsort): Use it here.\n\n2000-03-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-time.cc: Include <sys/types.h> and <unistd.h>, if available.\n\n2000-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-rl-hist.c (octave_history_list): Do something when not\n\tprinting line numbers.  Fix reallocation of retval.\n\n2000-02-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-inc): Install files in\n\t$(octincludedir)/octave.\n\t(uninstall): Remove them from the correct directory too.\n\n\t* oct-time.cc: Temporarily define _BSD_SOURCE and _XOPEN_SOURCE if\n\tthey are not already defined.\n\n2000-02-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CRowVector.cc, CRowVector.h, CColVector.cc, CColVector.h:\n\tDelete declarations and definitions of mixed-type vector-vector ops.\n\n2000-02-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.h, CMatrix.cc: Add lssolve methods for real-valued RHS\n\tmatrix and vector objects.\n\n\t* mx-op-defs.h (DMM_BIN_OP): Explicitly request conversion to\n\treturn type from second arg type.\n\t(MDM_BIN_OP): Likewise, for first arg type.\n\n\t* dMatrix.cc (Matrix::fourier, Matrix::ifourier,\n\tMatrix::fourier2d, Matrix::ifourier2d): Likewise.\n\n\t* EIG.cc (EIG::symmetric_init, EIG::hermitian_init): Explicitly\n\trequest ColumnVector to ComplexColumnVector, and Matrix to\n\tComplexMatrix conversions.\n\n\t* CmplxAEPBAL.cc (ComplexAEPBALANCE::init): Give balancing_mat its\n\tinitial value using ComplexMatrix constructor.\n\n\t* CColVector.cc (product, quotient,\n\toperator * (const DiagMatrix&, const ComplexColumnVetor&)):\n\tFix type of returned value.\n\t* CDiagMatrix.cc (ComplexDiagMatrix::row,\n\tComplexDiagMatrix::column, ComplexDiagMatrix::inverse): Likewise.\n\n\t* Array.h, CColVector.h, CDiagMatrix.h, CMatrix.h, CRowVector.h,\n\tMArray.h, MDiagArray2.h, dColVector.h, dDiagMatrix.h, dMatrix.h,\n\tdRowVector.h: Declare some constructors explicit, to disallow\n\tpotentially problematic automatic type conversions.\n\n2000-02-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* vx-rv-crv.h, vx-cv-ccv.h, vx-crv-rv.h, vx-ccv-cv.h,\n\tvx-rv-crv.cc, vx-cv-ccv.cc, vx-crv-rv.cc, vx-ccv-cv.cc:\n\tMore new files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* vx-ccv-s.h, vx-crv-s.h, vx-cs-cv.h, vx-cs-rv.h, vx-cv-cs.h,\n\tvx-rv-cs.h, vx-s-ccv.h, vx-s-crv.h, vx-ccv-s.cc, vx-crv-s.cc,\n\tvx-cs-cv.cc, vx-cs-rv.cc, vx-cv-cs.cc, vx-rv-cs.cc, vx-s-ccv.cc,\n\tvx-s-crv.cc:, New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* CRowVector.h, CRowVector.cc, CColVector.h, CColVector.cc:\n\tDelete scalar by vector and vector by scalar binary ops.\n\n\t* MArray-defs.h: More new macros to handle MDiagArray operators.\n\t* dDiagMatrix.h, CDiagMatrix.h: Use the op-forwarding macros.\n\n2000-02-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-rl-edit.c (octave_rl_set_event_hook): Take address of\n\trl_event_hook before casting to void **.\n\t(octave_rl_set_startup_hook): Likewise, for rl_startup_hook.\n\n\t* MArray-defs.h: Many new macros to make declaration and\n\tdefinition of operators more consistent.\n\n\t* MArray.h, MArray2.h, dColVector.h, dRowVector.h, CColVector.h,\n\tCRowVector.h, dMatrix.h, CMatrix.h: Use them.\n\n2000-02-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::ifourier): Cast divisor to double.\n\t(Matrix::ifourier2d): Likewise.\n\t* CMatrix.cc (ComplexMatrix::ifourier): Likewise.\n\t(ComplexMatrix::ifourier2d): Likewise.\n\n\t* Array.h (Array::ArrayRep::qsort): Cast len to size_t.\n\n2000-02-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-rl-edit.c, oct-rl-edit.h: New files for interface to GNU\n\treadline library.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* oct-rl-hist.c, oct-rl-hist.h: New files for interface to GNU\n\treadline history library.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* data-conv.cc (LS_DO_WRITE): Cast arg to ostream::write to char*.\n\t(LS_DO_READ): Likewise, for istream::read.\n\t(write_doubles): Likewise.\n\t(read_doubles): Likewise.\n\n\t* oct-env.cc (octave_env::do_polite_directory_format):\n\tUse operator== and substr method to do limited-length string\n\tcomparison.\n\n\t* Array2-idx.h, Array-idx.h: Avoid shadowing warnings for idx.\n\n\t* Quad.h: Use do_integrate as name of pure virtual function.\n\n\t* base-de.h: Use tt instead of t as arg names.\n\tAdd method with tcrit arg.\n\n\t* DAE.h, DAE.cc: Likewise, also xx for x.\n\n\t* DASSL.cc (dassl_fcn_ptr, dassl_jac_ptr): New typedefs.\n\t* LSODE.cc: lsode_fcn_ptr, lsode_jac_ptr): Ditto.\n\t* Quad.cc (quad_fcn_ptr): Ditto.\n\t* NLEqn.cc (hybrd1_fcn_ptr, hybrj1_fcn_ptr): Ditto.\n\n\t* oct-getopt.h, oct-getopt.c: New files for interface to getopt.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* oct-kpse.h, oct-kpse.c: New files for interface to kpathsearch.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* dMatrix.cc (write_int, read_int): No longer declared static.\n\n\t* CDiagMatrix.h: Delete decls for friend operators that are\n\thandled by MDiagArray2 class.  Move others outside class decl and\n\tstrip friend status.\n\t* dDiagMatrix.h: Likewise.\n\n\t* MArray.h: Delete decls for friend operators inside class decl.\n\t* MArray2.h: Ditto.\n\t* MDiagArray2.h: Ditto.\n\n\t* MArray-defs.h (DO_VS_OP,, DO_SV_OP, DO_VV_OP, NEGV): Pass all\n\tnecessary parameters.  Don't allocate memory in the macro.  Change\n\tall uses.\n\n\t* dMatrix.h (class Matrix): Delete `friend class' decls.\n\t* CMatrix.h (class ComplexMatrix): Ditto.\n\n\t* mx-op-defs (MS_BOOL_OP, MS_BOOL_OPS, SM_BOOL_OP, SM_BOOL_OPS,\n\tMM_BOOL_OP, MM_BOOL_OPS, MDM_MULTIPLY_OP, MDM_BIN_OPS,\n\tDMM_MULTIPLY_OP, DMM_BIN_OPS): Pass zero constant as final arg, to\n\tavoid type conflicts.  Change all uses.\n\n\t* strptime.c (__mon_yday): Fix size of array decl.\n\n\t* mx-inlines.cc: Use `xnot' instead of `not' for function name.\n\n\t* chMatrix.cc (charMatrix::row_as_string): Delete extraneous\n\tdefault value for second arg.\n\n\t* Array2.cc (Array2<T>::resize): Add Array<T>:: qulaifier to\n\treferences to ArrayRep.\n\n2000-01-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h (Array::ArrayRep): Now protected, not private.\n\n\t* All source files: Include iostream, fstream, strstream,\n\tetc. as needed instead of using forward declarations for these\n\tclasses.  Add std:: qualifier as needed.\n\n2000-01-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-time.cc: Declare strptime extern \"C\".\n\n2000-01-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-time.cc [! HAVE_STRPTIME]: Provide declaration.\n\n2000-01-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2.h (Array2<T>::get_size): Now protected instead of private.\n\t* Array3.h, Array3.cc: Use it in constructors and resize methods\n\tto get total size to be allocated.\n\n\t* DASSL.cc (DASSL::integrate): Declare do_restart and save_output\n\tas bool, not int.\n\n2000-01-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (assign (Array2<LT>& lhs, const Array2<RT>& rhs)):\n\tAllow A(idx) = RHS if idx is a boolean index with the same shape\n\tas A, even when do_fortran_indexing is not enabled.\n\t(Array2<T>::index (idx_vector& idx) const): Likewise, for A(idx).\n\n2000-01-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::solve (...)): Add new variant with\n\tfunction pointer as final arg.  Passed function (if any) will be\n\tcalled for singularity errors.\n\t* CMatrix.cc (ComplexMatrix::solve (...)): Likewise.\n\n\t* dMatrix.cc (Matrix::pseudo_inverse): Use economy SVD.\n\t* CMatrix.cc (ComplexMatrix::pseudo_inverse): Likewise.\n\n\t* lo-ieee.cc (octave_ieee_init): Don't include sunmath.h.\n\tNo longer bother with infinity or quiet_nan.\n\n\t* Array2.cc (Array2<T>::get_size): New function.\n\t(Array2<T>::Array2, Array2<T>::resize): Use it.\n\n2000-01-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::maybe_delete_elements (idx_vector&)):\n\tNew function.\n\t(assign (Array2<LT>& lhs, const Array2<RT>& rhs)):\n\tUse it when indexing with one arg instead of faking a second one.\n\t(Array2<T>::maybe_delete_elements (idx_vector&, idx_vector&)):\n\tReturn empty matrices with the correct dimensions for A(:,:) = []\n\tand also A(:,idx) = [], and A(idx,:) = [] when idx enumerates all\n\trows or columns.\n\n\t* idx-vector.cc (IDX_VEC_REP::is_colon_equiv): Recognize a bool\n\tvector that is all true values with a length equal to n as colon\n\tequivalent.\n\n2000-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strptime.c: Only include langinfo.h if _LIBC is defined.\n\n2000-01-21  A. Scottedward Hodel  <a.s.hodel@eng.auburn.edu>\n\n\t* CMatrix.cc (ComplexMatrix::expm): Apply permutation and scaling\n\toperations directly in step 2 and reverse step 2.\n\t* dMatrix.cc (Matrix::expm): Apply permutation and scaling\n\toperations directly in step 2 and reverse step 2.\n\n2000-01-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-time.h, oct-time.cc (octave_strptime): New class.\n\n\t* strptime.c: New file, from glibc 2.1.2.\n\t* Makefile.in (SOURCES): Add strptime.c to the list.\n\n2000-01-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* MArray.h (MArray <const Array<T>&)): New constructor.\n\n2000-01-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.cc (dir_path::all_directories): Avoid dereferencing\n\tNULL directory list returned from kpse_element_dirs\n\n1999-12-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleLU.cc (LU::LU): Call DGETRF directly instead of calling DGESV.\n\t* CmplxLU.cc (ComplexLU::ComplexLU): Likewise, call ZGETRF\n\tdirectly, instead of calling ZGESV.\n\n1999-11-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data-conv.cc (init_sized_type_lookup_table): New function.\n\t(string_to_data_type): Use it to improve lookup of data types.\n\n1999-11-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (is_symmetric): Move here from Array2.cc.\n\t* Array2.h (is_symmetric): Delete declaration.\n\n1999-11-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-env.cc (do_get_user_name): Reverse sense of test.\n\n1999-11-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-time.cc (Fstrftime): Undo previous change.\n\t(octave_time::octave_time (const octave_base_tm&)): Likewise.\n\n1999-11-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleSVD.cc (SVD::init): Let DGESVD determine work space requirement.\n\t* CmplxSVD.cc (ComplexSVD::init): Likewise, for complex version.\n\n\t* dbleSCHUR.cc (SCHUR::init): IWORK is always referenced by dgeesx.\n\tDon't forget to pass length of third string argument to dgeesx.\n\n\t* CmplxSCHUR.cc (ComplexSCHUR::init): Don't forget to pass length\n\tof third string argument to zgeesx.\n\n1999-11-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DiagArray2.cc (DiagArray2<T>::operator () (int, int)):\n\tOn errors, simply return `T ()'.\n\t(DiagArray2<T>::checkelem (int, int)): Likewise.\n\n1999-11-02  A. Scottedward Hodel  <a.s.hodel@eng.auburn.edu>\n\n\t* dMatrix.cc (Matrix::expm): Do balancing here instead of using\n\tAEPBALANCE class.\n\t* CMatrix.cc (ComplexMatrix::expm): Likewise.\n\n1999-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-shlib.cc, oct-shlib.h: New files.\n\t* Makefile.in (INCLUDES, SOURCES): Add them to the lists.\n\n1999-10-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CRowVector.cc (linspace): Allow npoints == 1 if x1 == x2.\n\t* dRowVector.cc (linspace): Ditto.\n\n\t* oct-time.cc (Fstrftime): Don't save or delete tm_zone.\n\t(octave_time::octave_time (const octave_base_tm&)): Likewise.\n\n1999-10-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASSL.cc (DASSL::do_integrate (double)): If we have a function\n\tto evaluate the Jacobian, set info(4), not iwork(4).\n\tSet rwork(1) to the maximum step size, not rwork(2).\n\n1999-10-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-time.cc: Include <climits>.\n\n1999-10-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.h (command_editor::do_resize_terminal): New function.\n\t* cmd-edit.cc (command_editor::resize_terminal): New function.\n\t(gnu_readline::do_resize_terminal): New function.\n\nFri Sep  3 12:39:17 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc: Include ieeefp.h and sunmath.h if we have them.\n\t* lo-ieee.c: Likewise.\n\tDelete extern \"C\" declarations for infinity and quiet_nan.\n\nFri Aug 20 07:58:00 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mx-inlines.cc (VS_OP, SV_OP, VV_OP): Delete `extern template' decls.\n\t(VS_OP_FCN, SV_OP_FCN, VV_OP_FCN): Declare template functions\n\t`inline', not `static inline'.\n\n\t* idx-vector.cc (intcmp): Declare args as const void *, not int *,\n\tthen cast to const int * to compare.\n\nFri Jul 16 11:23:51 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DAEFunc.h: Remove useless preprocessor conditional.\n\nThu Jul 15 14:10:33 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.cc (command_editor::do_decode_prompt_string):\n\tUse octave_time object instead of time_t.\n\n\t* file-stat.h (file_stat::fs_atime, file_stat::fs_mtime,\n\tfile_stat::fs_ctime): Now octave_time objects.\n\t(file_stat::atime, file_stat::mtime, file_stat::ctime):\n\tReturn octave_time objects.\n\t(file_stat::is_newer): Args are now octave_time objects instead of\n\ttime_t.\n\n\t* oct-time.h (octave_time::as_double): Delete.\n\t(octave_time::operator double ()): New function.\n\t(octave_time::operator time_t ()): New function.\n\t(octave_time::ctime): New function.\n\t(octave_base_tm::strftime): Renamed from format_as_string.\n\t(octave_base_tm::asctime): New function.\n\t(operator == (const octave_time&, const octave_time&),\n\toperator != (const octave_time&, const octave_time&),\n\toperator < (const octave_time&, const octave_time&),\n\toperator <= (const octave_time&, const octave_time&),\n\toperator > (const octave_time&, const octave_time&),\n\toperator >= (const octave_time&, const octave_time&)):\n\tNew comparison functions.\n\n\t* strftime.c: Move here from src directory.\n\t* Makefile.in (SOURCES): Add it to the list.\n\n\t* oct-time.h (octave_time::octave_time (time_t)): New constructor.\n\nWed Jul 14 17:38:07 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-time.h, oct-time.cc: New files.\n\t* Makefile.in (INCLUDES, SOURCES): Add them to the lists.\n\n\t* systime.h: Move here from src directory.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\nMon Jul 12 22:34:34 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mx-defs.h (b_d_Mapper, b_c_Mapper): New typedefs.\n\t* dMatrix.cc (Matrix::map (b_d_Mapper)): New function.\n\t* CMatrix.cc (ComplexMatrix::map (b_c_Mapper)): New function.\n\t* lo-mappers.cc (xisinf, xisnan, xfinite): Return bool, not double.\n\n\t* lo-mappers.cc (xmin, xmax): New functions to correctly handle NaNs.\n\nMon May 10 07:45:11 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* MArray-defs.h (DO_VV_OP2): Fix macro definition to use arg.\n\nWed May  5 20:06:10 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>index (idx_vector& idx)): Always return a\n\tcolumn vector for A(:), for compatibility with Matlab.\n\nFri Apr 23 11:52:23 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* LSODE.cc (LSODE::do_integrate (double)): Don't forget to set\n\tiopt when there are optional inputs in rwork or iwork.\n\nFri Mar 26 11:26:32 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (libraries): Use the libfoo.a(objects) method of\n\tcreating static libs.\n\nThu Mar  4 02:17:04 1999  James Macnicol  <jamesm@evans.ee.adfa.oz.au>\n\n\t* data-conv.cc (oct_data_conv::string_to_data_type): Handle uint16\n\tand uint32 data types.\n\nThu Mar  4 01:51:37 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc (octave_ieee_init): Don't use __alpha__-specific code\n\tfor Linux.  Remove old Linux-specific code.\n\nTue Jan 19 09:34:55 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (operator * (const ColumnVector& v, const RowVector& a)):\n\tDon't require lengths to be equal.\n\t* CMatrix.cc (operator * (const ComplexColumnVector& v, const\n\tComplexRowVector& a)): Likewise\n\nTue Nov 24 23:38:19 1998  Eric Norum  <eric@skatter.USask.Ca>\n\n\t* statdefs.h: Only define mode_t if not already defined.\n\nTue Nov 24 17:24:52 1998  john  <john@arrows.demon.co.uk>\n\n\t* lo-specfun.cc (airy, biry): Set imaginary part of result to zero\n\twhen appropriate.\n\nMon Nov 23 09:57:05 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.cc (gnu_readline::gnu_readline): Set terminal name\n\tbefore calling rl_initialize.\n\nTue Nov 17 23:47:24 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-specfun.cc (besselh, airy, biry): New functions.\n\tUpdate Bessel function support to use library by D. E. Amos.\n\nThu Nov 12 17:44:15 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.h (command_editor::readline): Add new variation that\n\tallows EOF information to be passed back to caller.\n\n\t* dMatrix.cc (Matrix::read): Do the right thing for EOF when\n\tamount of data to read is unspecified.\n\nTue Nov 10 07:53:15 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-alloc.h (DECLARE_OCTAVE_ALLOCATOR): New macro.\n\t(DEFINE_OCTAVE_ALLOCATOR): Ditto.\n\n\t* byte-swap.h (swap_bytes, swap_2_bytes, swap_4_bytes, swap_8_bytes):\n\tAdd volatile qualifier to void* arg.\n\tCast volatile void* arg to volatile char*.\n\nMon Nov  9 08:28:31 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.h (command_editor::do_set_event_hook): New function.\n\t(command_editor::do_restore_event_hook): Ditto.\n\t* cmd-edit.cc (command_editor::set_event_hook): Ditto.\n\t(command_editor::restore_event_hook): Ditto.\n\t(gnu_readline::do_set_event_hook): Ditto.\n\t(gnu_readline::do_restore_event_hook): Ditto.\n\t(gnu_readline::previous_event_hook): New data member.\n\t(gnu_readline::gnu_readline): Initialize previous_event_hook.\n\nMon Nov  2 13:36:04 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (BINDISTLIBS): Don't include .$(SHLEXT_VER) in name.\n\n\t* Makefile.in (stmp-pic): New target.\n\t($(PICOBJ)): Depend on stmp-pic, not pic.\n\t(clean): Remove stmp-pic\n\n\t* Makefile.in: Undo previous change to avoid optmization when\n\tcompiling lo-ieee.cc.\n\nSun Nov  1 10:10:40 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc (xfinite): Define in terms of xfinite for real and\n\timaginary parts.\n\t(xisinf): Define in terms of xisinf for real and imaginary parts.\n\nThu Oct 29 18:57:50 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* boolMatrix.cc (boolMatrix::operator !): New function.\n\nFri Oct 23 21:46:20 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.h (dir_path::default_path): New data member.\n\t* pathsearch.cc (dir_path::init): Use it.\n\n\t* Makefile.in: Avoid optmization when compiling lo-ieee.cc.\n\nFri Oct 16 01:08:30 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* chMatrix.cc (charMatrix::extract): New function.\n\t(charMatrix::charMatrix (char c)): New constructor.\n\nTue Oct 13 22:11:08 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.h: (command_editor::do_read_init_file): New function.\n\t* cmd-edit.cc (command_editor::read_init_file): New function.\n\t(gnu_readline::do_read_init_file): Likewise.\n\nFri Sep 25 14:26:44 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-env.cc (octave_env::do_get_home_directory):\n \tIf HOME can't be found, set it to \"/\".\n\t(octave_env::do_get_user_name)\n\tIf user name can't be found, set it to \"unknown\".\n\t(octave_env::do_get_host_name)\n\tIf host name can't be found, set it to \"unknown\".\n\n\t* pathsearch.h (dir_path::rehash): New function.\n\t* pathsearch.cc (dir_path::init): Clear kpathsea's internal\n\tdiretcory cache before doing initialization.\n\nThu Sep 24 13:23:25 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Qzval): Delete.\n\t(qzhes, qzit, qzval): Delete F77_FCN declarations.\n\t* dMatrix.h (Qzval): Delete declaration.\n\n\t* dbleGEPBAL.h, dbleGEPBAL.cc: Delete.\n\t* Makefile.in (MATRIX_INC, MATRIX_SRC): Delete them from the lists.\n\t* mx-ext.h: Don't include dbleGEPBAL.\n\n\t* lo-ieee.cc (octave_ieee_init): For now, use X_CAST instead of\n\tstatic_cast.\n\nFri Sep  4 10:58:22 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::read): Skip after reading, not before.\n\tFrom: Dr.-Ing. Torsten Finke <fi@igh-essen.com>.\n\nWed Sep  2 09:50:21 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc (octave_ieee_init): For Linux on arm, don't rely on\n\tHUGE_VAL and NAN.\n\nWed Aug 26 15:04:57 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (assign (Array2<LT>& lhs, const Array2<RT>& rhs)):\n\tHandle x(i) = scalar for do_fortran_indexing == 1.\n\nThu Jul 30 00:34:10 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.cc (ComplexMatrix::ComplexMatrix (const charMatrix&)):\n\tAlloctate space before attempting to use it.\n\t(ComplexMatrix::ComplexMatrix (const boolMatrix&)): Likewise.\n\nMon Jun 22 17:04:27 1998  Tomislav Goles  <tom@ait-tech.com>\n\n\t* EIG.cc (EIG::init): Move invariant code outside loop.\n\nThu Jun 18 11:08:23 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* MArray2.cc (MARRAY_A2A2_OP): If operands are empty, make result\n\thave the same size as the operands.\n\nThu May 28 10:41:04 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DASSL.cc (DASSL::do_integrate): If an exception occurs in the\n\tcall to ddassl, set integration_error to 1 before calling the\n\terror handler and returning.\n\t* LSODE.cc (LSODE::do_integrate): Likewise.\n\nWed May 27 13:46:30 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (assign): Allow A([],[]) = scalar and, if\n\tdo_fortran_indexing is set, A([]) = scalar.\n\t* Array-idx.h (assign): Allow A([]) = scalar.\n\nThu May 14 11:50:24 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mx-op-defs.h (MDM_MULTIPLY_OP): Compute result if dm_nc > 0, not\n\tif dm_nc == 0.\n\nThu Apr 23 16:15:37 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.h (dir_path::p_orig): New field.\n\t* pathsearch.cc (dir_path::init): Perform variable and tilde\n\texpansion on the original path here.\n\t(dir_path::find_all): Don't do anything if not initialized.\n\nTue Apr 14 14:41:30 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (index): Allow x(:) even when do_fortran_indexing\n\tis not set.\n\t(index): Allow x = zeros (2, 0); x(1,:) to work.\n\n\t* lo-specfun.cc (gammainc): Use dgamit to compute\n\t(\\int_0^x exp(-t) t^(a-1) dt)/gamma(a), not just\n\t\\int_0^x exp(-t) t^(a-1) dt.\n\nWed Apr  8 22:50:44 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-C.cc, Array-b.cc, Array-ch.cc, Array-i.cc, Array-d.cc,\n\tArray-s.cc: Change return types of all `assign' explicit\n\tinstantiations to be int, not void, to match the template decl in\n\tArray.h.\n\nMon Apr  6 00:27:06 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-specfun.cc (gammainc): Reorder args in call to xdgami.\n\nThu Feb 19 01:16:38 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-specfun.cc (xgamma, xlgamma): Define here.\n\t* lo-mappers.cc: Not here.\n\n\t* lo-specfun.h: Declare xgamma and xlgamma here.\n\t* lo-mappers.h: Not here.\n\n\t* lo-specfun.h: Never declare gamma or lgamma.\n\nTue Feb 10 16:14:36 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-idx.h (assign): Allow A([]) = X to succeed if X is an\n\tempty matrix of any dimension.\n\nThu Feb  5 02:12:38 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-syscalls.cc (octave_syscalls::vfork): New function.\n\n\t* lo-specfun.cc: Don't include dbleBessel.h.\n\n\t* Makefile.in (INCLUDES): Delete oct-math.h from the list.\n\n\t* dir-ops.h (dir_entry::operator bool ()): Return bool, not void*.\n\t* file-stat.h (file_stat::operator bool ()): Likewise.\n\t* idx-vector.h (idx_vector::operator bool ()): Likewise.\n\t* oct-group.h (octave_group::operator bool ()): Likewise.\n\t* oct-passwd.h (octave_passwd::operator bool ()): Likewise.\n\n\t* data-conv.cc (IEEE_little_double_to_IEEE_big_double):\n\tDon't cast arg in call to swap_8_bytes.\n\t(IEEE_big_double_to_IEEE_little_double): Ditto\n\t(IEEE_big_float_to_IEEE_little_float): Don't cast arg in call to\n\tswap_4_bytes.\n\t(IEEE_little_float_to_IEEE_big_float): Ditto\n\n\t* oct-alloc.cc (grow): Use X_CAST, not static_cast.\n\t* prog-args.cc (prog_args::getopt): Likewise.\n\t* dMatrix.cc (read_int, do_read, write_int, do_write): Likewise.\n\t* cmd-edit.cc (gnu_readline::do_set_completion_function): Likewise.\n\t* data-conv.cc (LS_DO_READ, LS_DO_WRITE, read_doubles, write_doubles):\n\tLikewise.\n\n\t* byte-swap.h (swap_bytes, swap_2_bytes, swap_4_bytes,\n\tswap_8_bytes): Declare ptr arg as void*, then use cast.\n\nMon Feb  2 01:42:56 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install, uninstall): Use $(octlibdir), not $(libdir).\n\tUse $(mk-libdir-link).\n\n\t* file-stat.cc (file_stat::update_internal): Use stat and lstat,\n\tnot SAFE_STAT and SAFE_LSTAT.\n\t(lstat): New function, defined if HAVE_LSTAT is not defined.\n\t* safe-xstat.hin, safe-xstat.cin: Delete.\n\t* Makefile.in: Delete rules for safe-stat.h, safe-stat.c,\n\tsafe-lstat.h, and safe-lstat.cc.\n\nFri Jan 30 23:48:43 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* chMatrix.cc (charMatrix::all, charMatrix::any): New functions.\n\nTue Jan 20 16:30:00 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::expm): Skip trace normalization step if the\n\ttrace is negative.\n\t* CMatrix.cc (ComplexMatrix::expm): Skip trace normalization if\n\tthe real part of the trace is negative.\n\nMon Jan 19 16:01:59 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::expm): Call xdlange instead of dlange.\n\t* CMatrix.cc (ComplexMatrix::expm): Call xzlange instead of zlange.\n\n\t* Array2-idx.h (assign): Allow operations like a = 1; a(2:3) = [1;2]\n\tto succeed.\n\nThu Dec 18 14:53:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.cc (IDX_VEC_REP::sort): Don't do anything unless len > 1.\n\t(make_uniq): Likewise.\n\nFri Dec 12 10:58:33 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc (octave_ieee_init): Check for linux before __alpha__.\n\nSun Nov 30 14:59:12 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc: Include cmath and lo-specfun.h, not oct-math.h.\n\n\t* lo-specfun.h, lo-specfun.cc: New files.\n\t* Makefile.in (INCLUDES, SOURCES): Add them to the lists.\n\n\t* acosh.c, asinh.c, atanh.c, erf.c, erfc.c, gamma.c, lgamma.c,\n\toct-math.h: Delete.\n\t* Makefile.in (SOURCES): Delete them from the list.\n\nWed Nov 26 20:02:13 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-sysdep.cc (octave_getcwd): Prefer getcwd over getwd.\n\nWed Nov 19 02:30:04 1997  Mumit Khan  <khan@dhaka.xraylith.wisc.edu>\n\n\tChanges to make support egcs snapshots that implement explicit\n\tspecification of template functions according to CD2.\n\n\t* MArray.h: If NEED_TEMPLATE_FCN_SPECS is defined, add explicit\n\ttemplate function specs for template friends.\n\t* MArray2.h: Likewise.\n\t* MDiagArray2.h: Likewise.\n\nThu Nov 13 21:57:16 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.cc (sumsq): Compute equivalent of sum (x .* conj (x))\n\nThu Oct  2 17:13:02 1997  Mumit Khan  <khan@dhaka.xraylith.wisc.edu>\n\n\t* CRowVector.cc (linspace): Removed attempt for implicit conversion\n\tto complex<double>(int) instead of complex<double>(double).\n\n\t* lo-mappers.cc (atanh): Ditto.\n\nThu Jul 31 22:13:54 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.cc (IDX_VEC_REP::sort): New function.\n\t* idx-vector.h (idx_vector::sort): Ditto.\n\t* Array2-idx.h (Array2<T>::maybe_delete_elements): Use it before\n\ttrying to delete elements specified by the index vectors.\n\nFri Jul 25 17:31:26 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::lssolve): Increase lwork by factor of 16.\n\t* CMatrix.cc (ComplexMatrix::lssolve): Ditto.\n\nThu Jul 24 14:32:48 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc (tilde_expand_word): Fix off-by-one error.\n\nWed Jul  9 19:40:23 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-sysdep.cc (octave_getcwd): If getwd is available, use it.\n\tCall error handler if we can't find the current directory.\n\nMon Jul  7 21:14:41 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc (xisnan (double)): Return only 1 or 0.\n\t(xfinite (double)): Ditto.\n\n\t* dbleQR.cc (QR::init): Don't forget to initialize Q when type is raw.\n\t* CmplxQR.cc (ComplexQR::init): Ditto.\n\nSun Jun 15 21:06:37 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc (acos (const Complex&)): Select branch that is\n\tcompatible with Matlab.\n\nTue Jun 10 10:58:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h: Correctly handle empty matrices indexed by a\n\tsingle colon.\n\nFri Jun  6 04:27:40 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc (xlgamma): Use F77_XFCN function to call dlgams.\n\t(xgamma): Likewise, for calling xdgamma.\n\n\t* FSQP.h, NPSOL.h, QPSOL.h, FSQP.cc, NPSOL.cc, QPSOL.cc: Delete\n\t* Makefile.in (INCLUDES, SOURCES): Remove them from the lists.\n\n\t* file-ops.cc (file_ops::tilde_expand): Steal more code from bash\n\tto do better job expanding tildes.\n\n\t* str-vec.cc (string_vector::string_vector (const char * const *):\n\tUse temporary variable to compute length.\n\nThu Jun  5 01:44:43 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Make building of static library optional.\n\t(liboctave.$(SHLEXT_VER)): Add $(SONAME_FLAGS) to command.\n\n\t* Makefile.in (stamp-picdir): Delete.\n\t(pic): New target.  Don't worry so much about creating pic\n\tdirectory only when it is really needed.\n\t(stamp-interp): Delete.\n\t(libraries): New target.  Depend on shared library directly.\n\nWed Jun  4 00:08:55 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.h, pathsearch.cc (dir_pat::set_program_name):\n\tNew static function.\n\nMon Jun  2 12:44:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-mappers.cc (fix): Use floor and ceil instead of casting to int.\n\nThu May 22 16:20:43 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.h, cmd-edit.cc: Rename set_paren_string_delimiters to\n\tset_basic_quote_characters, to match new version of readline.\n\n\t* cmd-edit.cc (do_restore_terminal_state): Call readline function\n\tfor restoring terminal state through rl_deprep_term_function, now\n\tdeclared in readline.h\n\t(rl_deprep_terminal): Delete declaration.\n\nWed May 21 16:30:25 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-in): Use new mk-includedir-link macro.\n\t(install-lib): Install in $octlibdir.  Use new mk-libdir-link macro.\n\nThu May 15 11:46:42 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-edit.cc (command_editor::increment_current_command_number):\n\tNew static function.\n\nMon May 12 02:14:13 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.cc (IDX_VEC_REP::is_colon_equiv): Make it work when\n\tthe vector is not sorted.\n\n\t* CMatrix.cc (ComplexMatrix::operator !): Return boolMatrix.\n\t* dMatrix.cc (Matrix::operator !): Likewise\n\nWed May  7 21:14:06 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-syscalls.h, oct-syscalls.cc: New files.\n\n\t* cmd-edit.h, cmd-edit.cc: Handle completion function.\n\n\t* str-vec.h, str-vec.cc (string_vector::uniq): New function.\n\nTue May  6 00:52:02 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (INCLUDES_FOR_INSTALL): New variable.\n\t(install-inc): Use it.\n\n\t* file-ops.h, file-ops.cc (tempnam): Add DIR and PREFIX args.\n\tHandle errors and missing functions consistently.\n\n\t* oct-group.h, oct-group.cc: New files.\n\n\t* oct-passwd.cc: Handle errors and missing functions consistently.\n\n\t* str-vec.h, str-vec.cc (c_str_vec, delete_c_str_vec): New functions.\n\nMon May  5 17:53:01 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc: (file_ops::tilde_expand): Use new octave_passwd class.\n\t* oct-env.cc (octave_env::do_get_user_name): Likewise.\n\n\t* oct-passwd.h, oct-passwd.cc: New files.\n\nSun May  4 22:17:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statdefs.h: Only include sys/types.h if HAVE_SYS_STAT_H is defined.\n\n\t* mach-info.h, mach-info.cc: Add missing const qualifiers.\n\t(instance_ok ()): New function.\n\n\t* glob-match.h, glob-match.cc: Rename from oct-glob.h, oct-glob.cc.\n\n\t* cmd-hist.h, cmd-hist.cc: Make it work without GNU readline.\n\n\t* lo-utils.h, lo-utils.cc (strsave, octave_putenv): Move here from\n\tsrc/utils.h and src/utils.cc.\n\t(octave_fgets): New function, extracted from src/input.cc.\n\n\t* cmd-edit.h, cmd-edit.cc: New files.  Provide wrapper class for\n\tGNU readline, and allow Octave to work without GNU readline.\n\n\t* lo-sysdep.h, lo-sysdep.cc: New files for miscellaneous\n\tsystem-dependent functions.\n\n\t* oct-env.h, oct-env.cc: New files for process environment stuff.\n\n\t* file-stat.h, file-stat.cc: New files.  Extract file_stat class\n\tfrom file-ops.h and file-ops.cc and move here.\n\n\t* file-ops.h, file-ops.cc: Wrap functions in struct.  Move\n\ttilde_expand functions here from src/dirfns.cc.\n\nFri May  2 19:50:12 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathlen.h: New file, from ../src.\n\nTue Apr 29 04:39:01 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::maybe_delete_elements): Prevent\n\tout-of-bounds indexing of the index array.\n\t* Array-idx.h (Array<T>::maybe_delete_elements): Likewise.\n\nFri Mar 28 15:37:09 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* LSODE.h (x_step_limit): New field.\n\t(LSODE_options::init): Initialize it.\n\t(LSODE_options::copy): Copy it.\n\t(LSODE_options::set_step_limit, LSODE_options::step_limit):\n\tNew functions.\n\t(LSODE::working_too_hard): Delete.\n\t* LSODE.cc (LSODE::do_integrate): Handle step limit.\n\nWed Mar 26 15:31:57 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* MArray-b.cc: Delete.\n\t* Makefile.in: Delete it from the lists.\n\n\t* boolMatrix.h (class bboolMatrix): Derive from Array2, not\n\tMArray2, since most of the numeric ops don't really make sense.\n\nTue Mar 25 17:37:25 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* boolMatrix.cc (boolMatrix::all, boolMatrix::any): New functions.\n\n\t* dMatrix.cc (Matrix::all, Matrix::any): Return boolMatrix.\n\t* CMatrix.cc (ComplexMatrix::all, ComplexMatrix::any): Likewise.\n\n\t* idx-vector.h (idx_vector::idx_vector_rep::freeze,\n\tidx_vector::freeze): Delete prefer_zero_one arg.\n\t* Array-idx.h, Array2-idx.h: Change all callers.\n\n\t* Array-flags.h, Array-flags.cc (liboctave_pzo_flag): Delete.\n\n\t* mx-op-defs.h: New file for operator definitions.\n\t* mx-cdm-cm.h, mx-cdm-cs.h, mx-cdm-dm.h, mx-cdm-m.h, mx-cdm-s.h,\n\tmx-cm-cdm.h, mx-cm-dm.h, mx-cm-m.h, mx-cm-s.h, mx-cs-cdm.h,\n\tmx-cs-dm.h, mx-cs-m.h, mx-dm-cdm.h, mx-dm-cm.h, mx-dm-cs.h,\n\tmx-dm-m.h, mx-dm-s.h, mx-m-cdm.h, mx-m-cm.h, mx-m-cs.h, mx-m-dm.h,\n\tmx-s-cdm.h, mx-s-cm.h, mx-s-dm.h, mx-cdm-cm.cc, mx-cdm-cs.cc,\n\tmx-cdm-dm.cc, mx-cdm-m.cc, mx-cdm-s.cc, mx-cm-cdm.cc, mx-cm-dm.cc,\n\tmx-cm-m.cc, mx-cm-s.cc, mx-cs-cdm.cc, mx-cs-dm.cc, mx-cs-m.cc,\n\tmx-dm-cdm.cc, mx-dm-cm.cc, mx-dm-cs.cc, mx-dm-m.cc, mx-dm-s.cc,\n\tmx-m-cdm.cc, mx-m-cm.cc, mx-m-cs.cc, mx-m-dm.cc, mx-s-cdm.cc,\n\tmx-s-cm.cc, mx-s-dm.cc:\n\tNew files for mixed-type operations.\n\t* Makefiles.in: Add them to the appropriate lists.\n\n\t* mx-inlines.cc: Add bool by bool EQ ops.\n\n\t* idx-vector.h, idx-vector.cc: Add constructors for bool and\n\tboolMatrix types.\n\t(idx_vector::maybe_convert_one_zero_to_idx,\n\tidx_vector::idx_vector_rep::maybe_convert_one_zero_to_idx):\n\tDelete second arg, prefer_zero_one.  Change all callers.\n\n\t* boolMatrix.h, boolMatrix.cc: New files.\n\t* mx-base.h: Include boolMatrix.h here.\n\t* mx-defs.h: Provide forward declaration for boolMatrix here.\n\n\t* chMatrix.h, chMatrix.cc: Delete unused junk.\n\n\t* dMatrix.h, CMatrix.h: Delete friend declarations for operator+,\n\toperator-, operator*, product, and quotient functions.\n\tAdd constructor for boolMatrix type.\n\t* dMatrix.cc, CMatrix.cc: Delete operator+, operator-, operator*,\n\tproduct, and quotient functions.\n\n\t* CDiagMatrix.h: Delete friend declarations for operator+,\n\toperator-, and product functions.\n\t* CDiagMatrix.h: Delete operator+, operator-, and product functions.\n\n\t* Array-b.cc: Also instantiate 2d and 2d diagonal arrays.\n\nFri Mar 14 00:29:46 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* EIG.cc (EIG::hermitian_init (const ComplexMatrix&)): New function.\n\t(EIG::init (const ComplexMatrix&)): Call it if arg is hermitian.\n\t(EIG::symmetric_init (const Matrix&)): New function.\n\t(EIG::init (const Matrix&)): Call it if arg is symmetric.\n\n\t* CMatrix.cc (ComplexMatrix::is_hermitian): New function.\n\nThu Mar 13 17:04:26 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2.cc (is_symmetric): New function.\n\t* Array2.h (is_square): New function.\n\nWed Mar 12 16:59:49 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-strip): New target.\n\nMon Mar 10 22:34:22 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CmplxCHOL.cc, CmplxHESS.cc, CmplxLU.cc, CmplxQR.cc,\n\tCmplxQRP.cc, CmplxSCHUR.cc, CmplxSVD.cc, EIG.cc, dbleCHOL.cc,\n\tdbleHESS.cc, dbleLU.cc, dbleQR.cc, dbleQRP.cc, dbleSCHUR.cc,\n\tdbleSVD.cc: Don't include mx-inlines.cc.\n\n\t* mx-inlines.cc: Abuse the preprocessor to eliminate lots of\n\tduplicate code.\n\nSun Mar  9 03:44:52 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleQR.h (QR): Delete extra comma at end of list.\n\n\t* prog-args.cc (prog_args::getopt): Add missing const in cast.\n\n\t* dbleSVD.h (SVD::type): Delete extra comma at end of list.\n\n\t* idx-vector.h (idx_vector): Delete unnecessary idx_vector:: and\n\tidx_vecotr_rep:: qualifiers.\n\n\t* Array.h (class Array): Delete unnecessary Array<T>:: qualifiers.\n\n\t* data-conv.h (save_type): Delete extra comma at end of list.\n\n\t* CMatrix.cc, FEGrid.cc, Range.cc, dMatrix.cc, data-conv.cc,\n\tdir-ops.cc, file-ops.h, idx-vector.cc, idx-vector.h, lo-ieee.cc,\n\tlo-mappers.cc, oct-alloc.cc: Use `static_cast<T> (val)' instead of\n\told C-style `(T) val' casts.\n\nThu Mar  6 20:20:01 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (operator >>): Return if an error occurs instead of\n\tjust breaking out of the innermost loop.\n\t* CMatrix.cc (operator >>): Likewise.\n\nSat Mar  1 15:23:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.5 released.\n\nFri Feb 28 20:11:23 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CmplxQR.cc (ComplexQR::init): New function.\n\t(ComplexQR::ComplexQR): Use it.  Use initializer list too.\n\t* CmplxQRP.cc (ComplexQRP::init): New function.\n\tGet sizes right in all cases.\n\t(ComplexQR::ComplexQRP): Use it.  Use initializer list too.\n\n\t* dbleQR.cc (QR::init): New function.\n\t(QR::QR): Use it.  Use initializer list too.\n\t* dbleQRP.cc (QRP::init): New function.\n\tGet sizes right in all cases.\n\t(QR::QRP): Use it.  Use initializer list too.\n\nWed Feb 26 15:46:28 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mach-info.cc (oct_mach_info::string_to_float_format):\n\tRecognize \"vaxg\", not \"vax_g\".\n\nFri Feb 21 16:07:56 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (Array2<T>::maybe_delete_elements): Use correct\n\tdimension in check for colon equivalent index.\n\t* idx-vector.cc (IDX_VEC_REP::is_colon_equiv): A single-element\n\tindex whose value is 0 is also colon eqivalent for n == 1.\n\n\t* lo-ieee.cc (octave_ieee_init): Reorder #ifdef stuff to put\n\tsystem-specific tests first.\n\nThu Feb 20 02:58:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.4 released.\n\nWed Feb 19 09:42:30 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc: D'oh, it's `extern \"C\"', not `#extern \"C\"'.\n\nTue Feb 18 09:22:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.3 released.\n\nFri Feb 14 16:23:47 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (bin-dist): Don't write empty strings to LIBRARIES.\n\nThu Feb 13 14:35:19 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (stamp-prereq): Depend on stamp-picdir.\n\t(all): Don't depend on stamp-prereq or stamp-picdir.\n\t(liboctave.a, stamp-shared): Do depend on stamp-prereq.\n\t(stamp-picdir): Silence noise about making pic.\n\t(stamp-shared): Use $(SH_LD) $(SH_LDFLAGS) instead of $(CXX) -shared.\n\n\t* Array2-idx.h (Array2<T>::index (idx_vector&, idx_vector&)):\n\tFix typo in last change.\n\n\t* CColVector.cc (ComplexColumnVector::map (d_c_mapper)):\n\tConvert from friend (moved from dColVector.cc).\n\t* CMatrix.cc (ComplexMatrix::map (d_c_mapper)):\n\tLikewise (moved\tfrom dMatrix.cc).\n\t* CRowVector.cc (ComplexRowVector::map (d_c_mapper)):\n\tLikewise (moved\tfrom dRowVector.cc).\n\n\t* dColVector.cc (ColumnVector::map (d_d_mapper)): Convert from friend.\n\t* dMatrix.cc (Matrix::map (d_d_mapper)): Likewise.\n\t* dRowVector.cc (RowVector::map (d_d_mapper)): Likewise.\n\t* CColVector.cc (ComplexColumnVector::map (c_c_mapper)): Likewise.\n\t* CMatrix.cc (ComplexMatrix::map (c_c_mapper)): Likewise.\n\t* CRowVector.cc (ComplexRowVector::map (c_c_mapper)): Likewise.\n\n\t* dColVector.cc (ColumnVector::apply): Rename from map, return *this.\n\t* dMatrix.cc (Matrix::apply): Likewise.\n\t* dRowVector.cc (RowVector::apply): Likewise.\n\t* CColVector.cc (ComplexColumnVector::apply): Likewise.\n\t* CMatrix.cc (ComplexMatrix::apply): Likewise.\n\t* CRowVector.cc (ComplexRowVector::apply): Likewise.\n\nTue Feb 11 19:44:28 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc: Declare quiet_nan() and infinity().\n\nMon Feb 10 01:17:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc (oct_unlink (const string&, string&)):\n\tNew two-arg version.\n\t(oct_rmdir (const string&, string&)): New two-arg version.\n\t(oct_mkdir (const string&, mode_t, string&)): New three-arg version.\n\t(oct_mkfifo (const string&, mode_t, string&)): New three-arg version.\n\t(oct_rename (const string&, const string&, string&)):\n\tNew three-arg version.\n\nFri Feb  7 13:15:55 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.h (idx_vector::orig_empty): New function.\n\n\t* Array2-idx.h (Array2<T>::index (idx_vector&, idx_vector&)):\n\tDon't always resize to [](0x0) if one of the indices is empty or\n\tzero.\n\nSun Feb  2 22:33:44 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-hist.cc (command_history::read): New arg, must_exist.\n\tSet line_in_file here too.\n\t(command_history::read_range): New arg, must_exist.\n\nFri Jan 31 09:21:57 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* f2c-main.c: Change C++-style comments to C-style comments.\n\nTue Jan 28 10:46:02 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-inc): Create a relative symbolic link.\n\nMon Jan 27 15:52:27 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.2 released.\n\nSat Jan 25 22:36:21 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (bin-dist): New target.\n\nWed Jan 22 16:18:53 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleSVD.cc (SVD::init): Work around apparent dgesvd() bug.\n\t* CmplxSVD.cc (ComplexSVD::init): Work around apparent zgesvd() bug.\n\nMon Jan 20 18:44:11 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* chMatrix.cc (charMatrix::charMatrix (const string&)):\n\tIf the number of columns is zero, also set the number of rows to zero.\n\t(charMatrix::charMatrix (const char *)): Likewise.\n\nTue Jan  7 00:16:57 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.1 released.\n\nSun Jan  5 12:07:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::read): Correctly compute the number of\n\tcolumns for resizing when the number of rows is specified but the\n\tnumber of columns is not.\n\nWed Dec 18 16:18:58 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Range.cc (operator -): New function.\n\n\t* lo-ieee.cc: Include <nan.h> on all systems that have it.\n\nFri Dec 13 02:01:32 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (assign): Delay resizing left hand side until we\n\tknow if the assignment conforms.\n\nTue Dec 10 01:43:09 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0 released.\n\nFri Dec  6 14:41:15 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (assign): If index is a colon, set number of\n\telements to the lhs dimension if the lhs dimension is greater than\n\tzero.  Otherwise, set it to the rhs dimension.\n\n\t* Version 1.94.\n\n\t* Array2-idx.h (assign): Test for rhs scalar case first.\n\tIf index is colon, set number of elements to lhs dimension, not\n\trhs dimension.\n\nThu Dec  5 13:05:18 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sun-utils.h: Don't declare MAIN_ or MAIN__ here.\n\t* sun-utils.cc: Delete.\n\t* f2c-main.c: New file\n\n\t* Makefile.in: Fix file name lists.\n\n\t* CMatrix.cc (lssolve): Don't redeclare retval, resize it.\n\nWed Dec  4 12:24:24 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Qzval): Don't try to use same memory three times.\n\tCreate result using Complex constructor, not multiplication.\n\tOrder elements as they are returned from Eispack.\n\nMon Dec  2 00:26:41 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc (octave_ieee_init): Kluge for octave_Inf on SCO.\n\tOnly include nan.h if SCO is defined.  Define _IEEE before\n\tincluding it and undefine it afterward.\n\t[SCO] (isnan): Don't mistake Inf as NaN.\n\n\t* Array-idx.h (assign): Only resize if assignment conforms.\n\nWed Nov 20 01:00:40 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (INCLUDES): Delete lo-error.h.\n\t* lo-error.h: Delete (moved to libcruft/misc).\n\n\t* Version 1.93.\n\nTue Nov 19 23:07:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-glob.cc (glob_match::match): Don't expect our flag values to\n\tbe the same as they are in fnmatch.h.\n\n\t* f77-fcn.c, f77-fcn.h: Move to libcruft/misc directory.\n\n\t* Makefile.in (INCLUDES): Delete f77-fcn.h.\n\t(SOURCES): Delete f77-fcn.c.\n\nFri Nov 15 13:47:34 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.h: [SCO]: Declare isinf and isnan.\n\nThu Nov 14 00:06:53 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.92.\n\nWed Nov 13 11:19:22 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-hist.cc (command_history::add): Ignore empty input lines, or\n\tlines that have only carriage return or newline.\n\n\t* lo-ieee.cc (isnan, isinf): Provide functions for SCO.\n\nTue Nov 12 11:11:21 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.cc (idx_is_inf_or_nan): New function.\n\t(IDX_VEC_REP::idx_vector_rep): Use it.\n\nSun Nov 10 17:09:24 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* str-vec.h, str-vec.cc: Add constructors to make string vectors\n\tfrom vectors of C strings.\n\n\t* oct-glob.h, oct-glob.cc (glob_match): Allow pat to be a string\n\tvector.\n\t(glob_match::match): Allow match string to be a string vector.\n\t(glob_match::glob): New function.\n\n\t* chMatrix.cc (charMatrix::row_as_string): New arg, strip_ws.\n\n\t* Array-b.cc: New file.\n\t* Makefile.in (TI_SRC): Add it to the list.\n\nFri Nov  8 18:09:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc: Change #include \"\" to #include <> for safe-lstat.h\n\tand safe-stat.h, to avoid getting them from $srcdir when we really\n\twant the version from the build directory.  (Maybe this should be\n\tdone for all the include files, not just those that are\n\tauto-generated?  Hmm.)\n\nThu Nov  7 10:45:11 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.91.\n\n\t* Array3.cc (Array3<T>::resize): Make it work.\n\nWed Nov  6 22:44:33 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-alloc.h, oct-alloc.cc: New files.\n\t* Makefile.in: Add them to the lists.\n\nMon Nov  4 21:49:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleQRP.cc (QRP::QRP): Don't pass tmp data to unsafe constructor.\n\t* CmplxQRP.cc (ComplexQRP::ComplexQRP): Ditto.\n\nSun Nov  3 15:45:37 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc (file_stat::is_blk, file_stat::is_chr,\n\tfile_stat::is_dir, file_stat::is_fifo, file_stat::is_lnk,\n\tfile_stat::is_reg, file_stat::is_sock): Just return false if the\n\tunderlying macro is not defined.\n\n\t* oct-math.h (lgamma, gamma): Delete declarations.\n\t(asinh, acosh, atanh, erf, erfc): Declare arg types too.\n\tProtect declarations with #ifdef HAVE_*.\n\nWed Oct 30 11:42:58 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.90.\n\n\t* Makefile.in (DISTFILES): Add ChangeLog.\n\n\t* cmd-hist.cc: Only include fcntl.h if HAVE_FCNTL_H.\n\n\t* Matrix-ext.cc: Include <cfloat>, not <float.h>.\n\n\t* CMatrix.cc, cmd-hist.cc, file-ops.cc, file-ops.h, filemode.c,\n\tmkdir.c, rename.c, rmdir.c, safe-xstat.cin, statdefs.h, sysdir.h,\n\ttempname.c, utils.cc: Only include sys/types.h if HAVE_SYS_TYPES_H.\n\n\t* Array3.h (T Array3<T>::checkelem): Return T() for bogus value,\n\tsince that is now accepatble syntax, even for built-in types.\n\t* Array2.h (T Array2<T>::checkelem): Likewise\n\nSat Oct 26 23:37:34 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.cc (mkfifo) [! HAVE_MKFIFO]: Just print an error\n\tmessage and return -1.\n\nFri Oct 25 01:24:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* str-vec.h (str_vec_compare): Declare args as const void *, then\n\tcast them to const string * in the body of the function.\n\n\t* file-ops.cc (file_stat::mode_as_string): Explicitly construct\n\tstring from buf.\n\n\t* Array3.h (Array3::checkelem): Tag bogus return value with\n\tGCC_ATTRIBUTE_UNUSED.\n\t* Array2.h (Array2::checkelem): Likewise.\n\nThu Oct 24 19:40:36 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Quad.h (Quad): Define virtual destructor.\n\nTue Oct 15 11:34:48 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.cc (ComplexMatrix::all_elements_are_real): new function.\n\nSun Oct 13 11:19:00 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sun-utils.h: Conditionally declare MAIN__ too.  Declare MAIN_\n\tand MAIN__ extern \"C\".\n\t* sun-utils.cc: Include sun-utils.h here.  Delete extern \"C\" stuff.\n\nSat Oct 12 12:40:00 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* MArray-misc.cc: New file.\n\t* Makefile.in (MATRIX_SRC): Add it to the list.\n\n\t* mx-inlines.cc (equal): Return bool, not int.\n\n\t* idx-vector.h (idx_vector (double)): New constructor.\n\n\t* chMatrix.h, chMatrix.cc, CMatrix.h, CMatrix.cc, dMatrix.h,\n\tdMatrix.cc, dDiagMatrix.h, dDiagMatrix.cc, dRowVector.h,\n\tdRowVector.cc, dColVector.h, dColVector.cc, CColVector.h,\n\tCColVector.cc, CDiagMatrix.h, CDiagMatrix.cc, CRowVector.h,\n\tCRowVector.cc: Logical operators return bool, not int.\n\n\t* CMatrix.h, CMatrix.cc (ComplexMatrix::any_element_is_inf_or_nan):\n\tNew function.\n\n\t* dMatrix.h, dMatrix.cc (Matrix::any_element_is_negative,\n\tMatrix::any_element_is_inf_or_nan, Matrix::abs,\n\tMatrix::all_elements_are_inf_or_nan): New functions.\n\n\t* Range.h, Range.cc (Range::all_elements_are_ints): New function.\n\n\t* MArray.cc, MArray2.cc, MDiagArray2.cc: Call gripe_nonconformant\n\tfor errors.  Simplify macros by converting FCN to string for error\n\tmessages.\n\n\t* Array-idx.h (Array<T>::index): New function.  Don't call\n\tclear_index() here.\n\t(Array<T>::value): Call it, do call clear_index() here.\n\t* Array2-idx.h (Array<T>::value, Array<T>::index): Likewise, for\n\tone and two arg index functions.\n\nTue Sep 17 21:21:16 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DAEFunc.h: Delete #pragma interface since there is no longer a\n\tseparate implementation file.\n\nTue Aug 20 17:38:46 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (stamp-picdir): Only create a pic subdirectory if\n\tSHARED_LIBS is true AND CPICFLAG or CXXPICFLAG is not empty.\n\n\t* idx-vector.cc (IDX_VEC_REP::is_colon_equiv): Rename arg sort to\n\tsort_uniq.  If sort_uniq is nonzero, sort the elements and make\n\tthem uniq.\n\n\t* CMatrix.cc (ComplexMatrix::row_max, ComplexMatrix::row_min,\n\tComplexMatrix::column_max, ComplexMatrix::column_min):\n\tRewrite.  Also return index as a reference arg.\n\t(ComplexMatrix::row_max_loc, ComplexMatrix::row_min_loc,\n\tComplexMatrix::column_max_loc, ComplexMatrix::column_min_loc):\n\tDelete.\n\n\t* dMatrix.cc (Matrix::row_max, Matrix::row_min,\n\tMatrix::column_max, Matrix::column_min):\n\tRewrite.  Also return index as a reference arg.\n\t(Matrix::row_max_loc, Matrix::row_min_loc,\n\tMatrix::column_max_loc, Matrix::column_min_loc): Delete.\n\nFri Aug  9 05:01:04 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::row_min, Matrix::row_min_loc,\n\tMatrix::row_max, Matrix::row_max_loc, Matrix::column_min,\n\tMatrix::column_min_loc, Matrix::column_max,\n\tMatrix::column_max_loc): Ignore leading NaNs.\n\t* CMatrix.cc (ComplexMatrix::row_min, ComplexMatrix::row_min_loc,\n\tComplexMatrix::row_max, ComplexMatrix::row_max_loc,\n\tComplexMatrix::column_min, ComplexMatrix::column_min_loc,\n\tComplexMatrix::column_max, ComplexMatrix::column_max_loc): Ignore\n\tleading NaNs.\n\nThu Aug  8 16:04:17 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* QPSOL.cc (QPSOL::do_minimize): Insert linear constraint bounds\n\tstarting at n, not 0.\n\nSat Jul 27 02:54:44 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::Matrix (const RowVector&),\n\tMatrix::Matrix (const ColumnVector&)): New constructors.\n\n\t* CMatrix.cc (ComplexMatrix::ComplexMatrix (const RowVector&),\n\tComplexMatrix::ComplexMatrix (const ColumnVector&),\n\tComplexMatrix::ComplexMatrix (const ComplexRowVector&),\n\tComplexMatrix::ComplexMatrix (const ComplexColumnVector&)):\n\tNew constructors.\n\n\t* chMatrix.cc (charMatrix::charMatrix (const string_vector&)):\n\tNew constructor.\n\nWed Jul 24 16:39:16 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* LSODE.cc (do_integrate): Check to make sure that the state and\n\tderivative vectors are the same size.\n\t* DASSL.cc (do_integrate): Likewise.\n\nSun Jul 14 17:30:37 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::read, Matrix::write): Convert to use\n\tiostreams and handler data format conversions.  Delete old methods\n\tthat used stdio.\n\n\t* data-conv.h, data-conv.cc (oct_data_conv): New class.\n\nFri Jul 12 13:52:44 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mach-info.h: Rename from float-fmt.h.\n\t* mach-info.cc: Rename from float-fmt.cc.\n\tHandle machine information using a singlton class.\n\t* Makefile.in: Update appropriate lists.\n\nTue Jul  9 11:49:10 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-flags.cc: Provide definitions for the flags even if\n\tOCTAVE_SOURCE is not defined.\n\n\t* Array.h, Array2.h, Array3.h: BOUNDS_CHECKING now affects\n\toperator(), not elem().\n\t* Array3.h: Move indexing methods here from Array3.cc.\n\nMon Jun 24 02:30:05 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array3.cc (checkelem): Fix typo in call to Array2<T>::elem().\n\n\t* Makefile.in (install-lib): Use INSTALL_PROGRAM instead of\n\tINSTALL_DATA for shared libs.\n\nThu Jun  6 09:59:06 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Quad.cc: Include lo-error.h here too.\n\nMon May 27 12:41:07 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-ops.h: Include sys/types.h here.\n\nWed May 22 00:20:24 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* chMatrix.cc (charMatrix::transpose): Provide definition.\n\n\t* Array-idx.h (maybe_delete_elements): Correctly compute number of\n\telements in result.\n\t* Array2-idx.h (maybe_delete_elements): Likewise for number of\n\trows and columns in result.\n\nTue May 21 23:46:09 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleQR.cc (QR::QR): Don't create result from to-be-deleted data.\n\t* CmplxQR.cc (ComplexQR::ComplexQR): Likewise.\n\nFri May 17 03:06:02 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-inc): Install in octincludedir, not includedir.\n\nSun May 12 03:40:01 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (uninstall): Also delete shared library.\n\tSplit install into install-libs and install-includes.\n\t(install-inc): If linkdir is a directory, leave it alone.\n\n\t* sun-utils.cc (MAIN__): Define for Linux/ELF systems.\n\nThu May  2 20:19:01 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-idx.h (assign): Handle A(:) = X for A undefined or empty.\n\t* Array2-idx.h (assign): Likewise.\n\nTue Apr 30 05:43:06 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2.cc (Array2<T>::range_error): New functions.\n\n\t* Array.h (class Array<T>): elem() and operator() are now\n\tequivalent, and do bounds checking by default.\n\t* Array2.cc (class Array2<T>): Likewise.\n\nSat Apr  6 21:26:11 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (maintainer-clean, distclean): Also delete\n\tstamp-picdir, stamp-shared, and pic directory.\n\t(stamp-prereq): New target.\n\nFri Mar 29 13:44:13 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* NPSOL.h (NPSOL_options::set_option (const char *, int)):\n\tNew function.\n\n\t* Array.h, Array.cc (Array<T>::range_error ()): New functions.\n\t* Array.h (Array<T>::checkelem): Use them.\n\n\t* base-lu.h, base-lu.cc: Parameterize based on types of matrix\n\telements too.\n\t* dbleLU.h, dbleLU.cc, CmplxLU.h, CmplxLU.cc: Change to match.\n\n\t* MDiagArray2.h (MDiagArray2 (const MArray<T>& a)): Delete.\n\n\t* Makefile.in (distclean): Delete so_locations, which is created\n\ton DEC Alpha systems.\n\nSat Mar 23 04:02:53 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h (HEAVYWEIGHT_INDEXING): Do define this here if it is not\n\talready defined.\n\nFri Mar 22 23:53:58 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.cc: Include config.h.\n\nWed Mar 20 04:54:03 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2-idx.h (assign (Array2<LT>&, const Array2<RT>&)): Don't\n\tallow M(I, J) = scalar if I or J is empty.\n\n\t* Array-idx.h: Delete Array2 and Array3 code (now in Array2-idx.h\n\tand Array3-idx.h).\n\nThu Mar  7 10:20:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-error.h: Make comments C friendly.\n\nSun Mar  3 14:04:32 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2.h (make_unique): Move all indexing functions here.\n\t* Array2.cc: From here.\n\n\t* Array.h, Array2.h (NO_BOUNDS_CHECKING): New macro to control\n\twhether operator() calls elem or checkelem.\n\n\t* Array.h (make_unique): New private function.\n\tMove all indexing functions here.\n\t* Array.cc: From here.\n\n\t* pathsearch.cc (dir_path::find_all): Index tmp, don't dereference\n\tit too.\n\n\t* Array-d.cc, Array-ch.cc, Array-C.cc, Array-s.cc, Array-str.cc,\n\tArray-i.cc, MArray-i.cc, MArray-s.cc, MArray-d.cc, MArray-ch.cc,\n\tMArray-C.cc: Include config.h.\n\n\t* Array.h, Array2.h, DiagArray2.h, Array3.h:\n\tDon't define HEAVYWEIGHT_INDEXING here.\n\nSat Mar  2 18:39:35 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* base-lu.h, base-lu.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\t* dbleLU.h, dbleLU.cc, CmplxLU.h, Cmplx.cc: Derive from base_lu.\n\nFri Mar  1 08:30:58 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array2.h, Array3.h, DiagArray2.h: New files, extracted from Array.h\n\t* Array2-idx.h, Array3-idx.h: New files, extracted from Array-idx.h\n \t* Array2.cc, Array3.cc, DiagArray2.cc: New files, from Array.cc.\n\t* MArray2.h, MDiagArray2.h: New files, extracted from MArray.h.\n\t* MArray2.cc, MDiagArray2.cc, MArray-defs.h: New files, from MArray.cc.\n\n\t* MArray.h (INSTANTIATE_MARRAY_FRIENDS): New macro.\n\t(INSTANTIATE_MARRAY2_FRIENDS): Likewise.\n\t(INSTANTIATE_MDIAGARRAY_FRIENDS): Likewise.\n\t* MArray-C.cc, MArray-ch.cc, MArray-c.cc, MArray-i.cc, MArray-s.cc:\n\tSimplify using new macros.\n\nMon Feb 26 03:04:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install): If $(includedir) ends in version string,\n\tmake link to name that does not include version info.\n\n\t* lo-ieee.cc: Include <cmath> here.\n\nFri Feb 16 20:52:34 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-ieee.cc, lo-ieee.h: New files.\n\t* lo-mappers.cc, lo-mappers.h: New files.\n\t* lo-utils.cc, lo-utils.h: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\nThu Feb 15 22:02:17 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (all_integers, too_large_for_float): New functions.\n\t* CMatrix.cc (all_integers, too_large_for_float): New functions.\n\n\t* byte-swap.h, data-conv.h, data-conv.cc, float-fmt.h,\n\tfloat-fmt.cc: New files.\n\t* Makefile.in: Include them in the appropriate lists.\n\nWed Feb 14 01:49:47 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Qzval): New function.\n\nTue Feb 13 12:41:54 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* NPSOL.cc (NPSOL_options::set_option): Arg key is now string, not\n\tchar*.\n\n\t* DASSL.h, DASSL.cc: Do better management of temporary workspace.\n\tUse F77_XFCN to call Fortran subroutine.\n\t* dColVector.cc, CColVector.cc: Likewise.\n\t* dRowVector.cc, CRowVector.cc: Likewise.\n\t* NPSOL.h, NPSOL.cc: Likewise.\n\t* CmplxCHOL.cc: Likewise.\n\t* dbleCHOL.cc: Likewise.\n\t* CMatrix.cc: Likewise.\n\t* dMatrix.cc: Likewise.\n\t* QPSOL.cc: Likewise.\n\t* LSODE.cc: Likewise.\n\nSun Feb 11 14:14:26 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleHESS.cc (HESS::init): Dimension of tau is n-1, not n+1.\n\n\t* dbleSCHUR.h, dbleSCHUR.cc: Do better management of temporary\n\tworkspace.  Use F77_XFCN to call Fortran subroutine.\n\t* CmplxAEPBAL.h, CmplxAEPBAL.cc: Likewise.\n\t* CmplxSCHUR.h, CmplxSCHUR.cc: Likewise.\n\t* dbleGEPBAL.h, dbleGEPBAL.cc: Likewise.\n\t* dbleAEPBAL.h, dbleAEPBAL.cc: Likewise.\n\t* CmplxHESS.h, CmplxHESS.cc: Likewise.\n\t* CmplxSVD.h, CmplxSVD.cc: Likewise.\n\t* dbleHESS.h, dbleHESS.cc: Likewise.\n\t* dbleSVD.h, dbleSVD.cc: Likewise.\n\t* EIG.h, EIG.cc; Likewise.\n\t* CollocWt.cc: Likewise.\n\t* NLEqn.cc: Likewise.\n\t* Quad.cc: Likewise.\n\nSat Feb 10 12:14:59 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleLU.h, dbleLU.cc: Do better management of temporary workspace.\n\tUse F77_XFCN to call Fortran subroutine.\n\t* CmplxLU.h, CmplxLU.cc: Ditto.\n\t* dbleQR.h, dbleQR.cc: Ditto.\n\t* CmplxQR.h, CmplxQR.cc: Ditto.\n\t* dbleQRP.h, dbleQRP.cc: Ditto.\n\t* CmplxQRP.h, CmplxQRP.cc: Ditto.\n\n\t* dir-ops.h (dir_entry::dir): Declare as void*, not DIR*.\n\t(struct DIR): delete forward declaration.\n\t(dir_entry::operator = (const dir_entry$)): Protect against\n\tcopying same object.\n\t* dir-ops.cc: Cast dir appropriately.\n\nFri Feb  9 16:12:44 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lo-error.cc: Moved to libcruft/misc.\n\t* Makefile.in: Delete it from the list.\n\n\t* f77-fcn.c (f77_context, f77_exception_encountered): Delete\n\tdefinitions (they have been moved to libcruft/misc/f77-extern.cc).\n\n\t* Array-flags.h: New file.\n\t* Array-idx.h: Include it here.\n\t* Makefile.in (MATRIX_INC): Add it to the list.\n\n\t* Array-flags.cc: Renamed from Array-ext.cc.\n\t(liboctave_dfi_flag): Renamed from dfi_flag.\n\t(liboctave_pcv_flag): Renamed from pcv_flag.\n\t(liboctave_pzo_flag): Renamed from pzo_flag.\n\t(liboctave_rre_flag): Renamed from rre_flag.\n\t* Array-idx.h: Change all uses of dfi_flag, etc.\n\t* Makefile.in (MATRIX_SRC): Change file name here too.\n\n\t* Makefile.in (LIBOCTAVE_LFLAGS, LIBOCTAVE_LIBS): New variables.\n\t(stamp-shared): Use them here.\n\nTue Feb  6 09:53:41 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-hist.cc (command_history::ignore_entries): Delete default\n\targument value.\n\nMon Feb  5 12:07:50 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CmplxAEPBAL.h, CmplxCHOL.h, CmplxDET.h, CmplxHESS.h, CmplxLU.h,\n\tCmplxQR.h, CmplxQRP.h, CmplxSCHUR.h, CmplxSVD.h, dbleAEPBAL.h,\n\tdbleCHOL.h, dbleDET.h, dbleGEPBAL.h, dbleHESS.h, dbleLU.h,\n\tdbleQR.h, dbleQRP.h, dbleSCHUR.h, dbleSVD.h:\n\tClean up constructors, assigment operator.\n\nSun Feb  4 03:12:04 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* NPSOL.cc (do_minimize): Use F77_XFCN to call npsol.\n\tCheck f77_exception_encountered on return.\n\n\t* f77-fcn.c (f77_exception_encountered): New variable.\n\t(F77_XFCN): Set it.\n\t* f77-fcn.h: Provide declaration.\n\n\t* QPSOL.h (QPSOL_options::set_options): Renamed from copy().\n\n\t* NPSOL.h (NPSOL_options::set_options): Renamed from copy().\n\n\t* NLEqn.h (NLEqn_options::set_options): New function.\n\t* Quad.h (Quad_options::set_options): Likewise.\n\n\t* LP.h (class LP): Add accessors for LP data.\n\n\t* NLEqn.h (NLEqn::n): Delete.\n\n\t* NLEqn.h (class NLEqn::n): Likewise.\n\n\t* NLP.h (class NLP): Add accessors for NLP data.\n\n\t* NPSOL.h (class NPSOL_options): Move constructors, set, and\n\taccess functions here.\n\t* NPSOL.cc.cc: From here.\n\n\t* QLD.h (class QLD): Add destructor definition.\n\t* Objective.h (class Objective): Likewise.\n\t* ODEFunc.h (class ODEFunc): Likewise.\n\t* NLFunc.h (class NLFunc): Likewise.\n\t* NLEqn.h (class NLEqn): Likewise.\n\t* NLConst.h (class NLConst): Likewise.\n\t* LinConst.h (class LinConst): Likewise.\n\t* LSODE.h (class LSODE_options): Likewise.\n\t* CollocWt.h (class CollocWt): Likewise.\n\t* Bounds.h (class Bounds): Likewise.\n\n\t* QLD.cc (QLD::set_default_options): Delete.\n\n\t* QP.h (QP): Add accessors for QP data.\n\tAdd copy constructor, operator =, and destructor definitions.\n\n\t* Range.h, Quad.h, QP.h, QLD.h, Objective.h, NLP.h, NLFunc.h,\n\tNLConst.h, LinConst.h, LSODE.h, LP.h, FEGrid.h, EIG.h, DASSL.h,\n\tDAEFunc.h, CollocWt.h, Bounds.h:\n\tClean up constructors, assigment operator.\n\n\t* dRowVector.cc (RowVector::transpose): Use magic of reference\n\tcounting to avoid duplicating the data immediately.\n\t* dColVector.cc (ColumnVector::transpose): Likewise.\n\t* CRowVector.cc (ComplexrowVector::transpose): Likewise.\n\t* CColVector.cc (ComplexColumnVector::transpose): Likewise.\n\nSat Feb  3 01:02:36 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* prog-args.h (prog_args::option_argument): New enum.\n\n\t* f77-fcn.h: Rename from f77-uscore.h.\n\t(F77_XFCN_ERROR, F77_XFCN): New macros.\n\t* f77-fcn.c: New file.\n\t* Makefile.in (SOURCES): Add it to the list.\n\n\t* ODEFunc.h: Clean up.\n\n\t* DASSL.cc, DASSL.h: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* LSODE.cc, LSODE.h: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* ODE.cc: Delete.\n\t* Makefile.in (SOURCES): Remove from list.\n\n\t* base-de.h, DAE.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\t* ODE.h: Only define interface for ODE classes.\n\t* DAE.h: Only define interface for ODE classes.\n\n\t* LPsolve.cc (do_minimize): Print sorry not implemented message.\n\t(LPsolve::set_default_options)): Delete\n\t* LPsolve.h (class LPsolve): Add operator =, copy constructor, and\n\tdestructor.\n\n\t* LP.h (class LP): Add operator =, copy constructor, and destructor.\n\n\t* QPSOL.h (QPSOL::QPSOL (const QPSOL&)): New constructor.\n\t(QPSOL::operator =): Call base class operator = instead of assuming\n\twe know what to copy.\n\n\t* base-min.h (size): New function.\n\n\t* NLP.h (NLP::size): Delete.\n\t(NLP::NLP (const NLP&)): New constructor.\n\t(NLP::operator =): Call base class operator = instead of assuming\n\twe know what to copy.\n\n\t* NPSOL.h, NPSOL.cc (NPSOL::option): Delete.\n\t(class NPSOL): Add operator = and destructor.\n\n\t* NPSOL.h: Add NPSOL_options() to list of constructor initalizers.\n\nFri Feb  2 22:52:55 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (liboctave.a): Depend on $(PICOBJ).\n\nWed Jan 31 05:29:25 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Givens, Sylvester, Matrix::expm): New functions.\n\t* CMatrix.cc (Givens, Sylvester, ComplexMatrix::expm): Ditto.\n\nMon Jan 29 00:00:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* prog-args.h, prog-args.cc: New files.\n\t* Makefile.in: Add them to lists.\n\n\t* getopt.h, getopt.c, getopt1.c: New files.\n\t* Makefile.in: Add them to the lists.\n\n\t* oct-term.h, oct-term.cc: New files.\n\t* Makefile.in: Add them to the lists.\n\n\t* str-vec.cc: New file.\n\t* Makefile.in (SOURCES): Add it to the list.\n\n\t* file-ops.cc (oct_tmpnam): Move here from src/utils.cc.\n\n\t* tempname.c, tempnam.c: Move here from src directory.\n\t* Makefile.in: Add to lists.\n\nSun Jan 28 23:06:19 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cmd-hist.h, cmd-hist.cc: New files.\n\t* Makefile.in: Add them to lists.\n\nThu Jan 25 20:36:05 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-glob.h, oct-glob.cc: New files.\n\t* Makefile.in: Add them to lists.\n\nWed Jan 24 01:55:08 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.h, pathsearch.cc: New files.\n\t* Makefile.in: Add them to lists.\n\n\t* dir-ops.h, dir-ops.cc: New files.\n\t* sysdir.h: Move here from src directory.\n\t* Makefile.in: Add them to lists.\n\n\t* Array.h (Array::qsort): Return *this, not void.\n\t* str-vec.h (string_vector::qsort): Likewise.\n\n\t* chMatrix.cc (row_as_string): Resize result to eliminate\n\tunnecessary NULs.\n\nTue Jan 23 00:40:58 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* safe-xstat.hin, safe-xstat.cin, statdefs.h, file-ops.h,\n\tfile-ops.cc, filemode.c, mkdir.c, rmdir.c, rename.c:\n\tFiles moved here from src directory.\n\t* Makefile.in: Add them to lists.  Include appropriate rules.\n\n\t* acosh.c, asinh.c, atanh.c, erf.c, erfc.c, gamma.c, lgamma.c:\n\tUse pointers, not references (this is C code!).\n\n\t* oct-math.h: New file.\n\t* acosh.c, asinh.c, atanh.c, erf.c, erfc.c, gamma.c, lgamma.c:\n\tFiles moved here from src directory.\n\t* Makefile.in: Add them to lists.\n\nSun Jan 21 22:53:37 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.cc (make_uniq): Fix major brain-o.\n\n\t* CmplxSCHUR.h, CmplxSCHUR.cc, dbleSCHUR.h, dbleSCHUR.cc:\n\tConvert\tto use string class instead of char*.\n\n\t* str-vec.h, Array-str.cc: New files.\n\n\t* Array.h (Array::qsort): New function.\n\nFri Jan 12 01:45:10 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h: Nest ArrayRep class inside Array class.\n\tRefer to ArrayRep, not ArrayRep<T>.\n\tMove all ArrayRep functions inline.\n\tDon't declare other Array classes as friends of ArrayRep.\n\t* Array.cc: Delete ArrayRep functions.\n\t* Array-idx.h: Refer to ArrayRep, not ArrayRep<T>.\n\n\t* Array-C.cc, Array-ch.cc, Array-d.cc, Array-i.cc, Array-s.cc:\n\tDon't instantiate ArrayRep objects.\n\nWed Jan 10 04:40:21 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* chMatrix.cc (charMatrix::charMatrix (const string&)):\n\tNew constructor.\n\nTue Jan  9 04:44:56 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleGEPBAL.cc (GEPBALANCE::init): Use string instead of char*\n\tfor balance_job arg.\n\t* dbleAEPBAL.cc (AEPBALANCE::init): Likewise.\n\t* CmplxAEPBAL.cc (ComplexAEPBALANCE::init): Likewise.\n\n\t* chMatrix.cc (row_as_string): Return string, not const char*.\n\nMon Jan  8 03:20:01 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (clean): If $(SHARED_LIBS), also remove shared libs.\n\n\t* chMatrix.cc (row_as_string): Undo previous change.\n\nSun Jan  7 19:50:16 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* chMatrix.cc (row_as_string): Do memory management here.  Caller\n\tis expected to save string if necessary.\n\nSat Jan  6 19:28:20 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h (class DiagArray): Enable nested Proxy class for all\n\tplatforms.\n\n\t* Array.cc (Array<T>::operator = (const Array<T>&)): If rep ==\n\ta.rep, don't mess with count.\n\t* Array.h (Array2<T>& operator = (const Array2<T>&)): Likewise,\n\tdon't do anything if reps are the same.\n\t(Array3<T>& operator = (const Array3<T>&)\n\n\t* Array.h (ArrayRep<T>::operator = (const ArrayRep<T>&)):\n\tDeclare private with no definition to prevent misuse.\n\n\t* Array.cc (Array2<T>::insert (const Array2<T>&, int, int)):\n\tGet range check right.\n\t* dMatrix.cc (Matrix::insert (const RowVector&, int, int)): Ditto.\n\t(Matrix::insert (const ColumnVector&, int, int)): Ditto.\n\t(Matrix::insert (const DiagMatrix&, int, int)): Ditto.\n\t* CMatrix.cc (ComplexMatrix::insert (const Matrix&, int, int)): Ditto.\n\t(ComplexMatrix::insert (const RowVector&, int, int)): Ditto.\n\t(ComplexMatrix::insert (const ColumnVector&, int, int)): Ditto.\n\t(ComplexMatrix::insert (const DiagMatrix&, int, int)): Ditto.\n\t(ComplexMatrix::insert (const ComplexRowVector&, int, int)): Ditto.\n\t(ComplexMatrix::insert (const ComplexColumnVector&, int, int)): Ditto.\n\t(ComplexMatrix::insert (const ComplexDiagMatrix&, int, int)): Ditto.\n\t* dRowVector.cc (RowVector::insert (const RowVector&, int)): Ditto.\n\t* dColVector.cc\n\t(ColumnVector::insert (const ColumnVector&, int)): Ditto.\n\t* CRowVector.cc\n\t(ComplexRowVector::insert (const RowVector&, int)): Ditto.\n\t(ComplexRowVector::insert (const ComplexRowVector&, int)): Ditto.\n\t* CColVector.cc\n\t(ComplexColumnVector::insert (const ColumnVector&, int)): Ditto.\n\t(ComplexColumnVector::insert (const ComplexColumnVector&, int)): Ditto.\n\n\t* dMatrix.cc (Matrix::insert (const DiagMatrix&, int, int)):\n\tAlso fill in zeros, not just the diagonal.\n\n\t* CDiagMatrix.cc (ComplexDiagMatrix::fill (double, int, int)):\n\tUse END parameter properly.\n\t(ComplexDiagMatrix::fill (const Complex&, int, int)): Ditto.\n\t* dDiagMatrix.cc (DiagMatrix::fill (double, int, int)): Ditto.\n\n\t* Array.h (ArrayRep<T>::ArrayRep (void)): Set count to 1 here.\n\t(ArrayRep<T>::ArrayRep (T *, int)): Likewise.\n\t* Array.cc (ArrayRep<T>::ArrayRep (const ArrayRep<T>&)):\n\tDon't copy count.  Set it to 1.\n\t(ArrayRep<T>::ArrayRep (int)): Set count to 1 here.\n\n\t* Array.h (Array<T>::Array (T *, int)): After constructing rep,\n\tdon't set rep->count to 1 here (now handled by ArrayRep\n\tconstructors).\n\t(Array<T>::Array (void)): Ditto.\n\t(Array<T>::Array (int)): Ditto.\n\t(Array<T>::T& elem (int)): Ditto.\n\t* Array-idx.h (Array<T>::maybe_delete_elements (idx_vector&)): Ditto.\n\t(Array2<T>::maybe_delete_elements (idx_vector&, idx_vector&)): Ditto.\n\t* Array.cc: (Array<T>::Array (int, const T&)): Ditto.\n\t(Array<T>::resize (int)): Ditto.\n\t(Array<T>::resize (int, const T&)) :Ditto.\n\t(Array<T>::fortran_vec (void)): Ditto.\n\t(Array2<T>::resize (int, int)): Ditto.\n\t(Array2<T>::resize (int, int, const T&)): Ditto.\n\t(DiagArray<T>::resize (int, int)): Ditto.\n\t(DiagArray<T>::resize (int, int, const T&)): Ditto.\n\nSun Dec 31 21:23:26 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-ch.cc: Rename from Array-c.cc.\n\t* MArray-ch.cc: Rename from MArray-c.cc.\n\t* chMatrix.cc: Rename from cMatrix.cc.\n\t* chMatrix.h: Rename from cMatrix.h.\n\t* Makefile.in (TI_SRC): Use new names here.\n\t* mx-base.h: Likewise.\n\nFri Dec 29 21:45:00 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Handle shared libraries.\n\nThu Dec 28 14:18:34 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CRowVector.cc (operator * (ComplexRowVector, ComplexMatrix)):\n\tCorrectly compute length of return value.  Correct rows and\n\tcolumns in zgemv call.\n\t* dRowVector.cc (operator * (RowVector, Matrix)): Likewise.\n\nTue Dec 26 00:37:57 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (stamp-picdir): New target.\n\t(all): Depend on it.\n\nSun Dec 24 03:10:41 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (INCLUDES): Remove QLD.h.\n\t(SOURCES): Remove QLD.cc.\n\nWed Dec 20 00:43:46 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc (Matrix::inverse): New arg, force.\n \tIf force is nonzero, invert even if matrix is singular.\n\t(ComplexMatrix::inverse): Likewise.\n\n\t* dRowVector.cc, mx-inlines.cc, dMatrix.cc, dDiagMatrix.cc,\n\tdColVector.cc,MArray-C.cc, CmplxDET.cc, CRowVector.cc, CMatrix.cc,\n\tCDiagMatrix.cc, CColVector.cc, Array-C.cc, CmplxDET.h, CMatrix.h:\n\tInclude \"oct-cmplx.h\" instead of <Complex.h>.\n\n\t* mx-defs.h: Include oct-cmplx.h in place of forward declaration\n\tfor class Complex.\n\n\t* oct-cmplx.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\n\t* idx-vector.cc (IDX_VEC_REP::idx_vector_rep): Don't redeclare len.\n\t(IDX_VEC_REP::maybe_convert_one_zero_to_idx): Don't redeclare count.\n\t(IDX_VEC_REP::freeze): Don't redeclare max_val and min_val.\n\t(intcmp, sort_data, make_uniq, copy_data, IDX_VEC_REP::print):\n\tAvoid g++ bugs.\n\nTue Nov 14 14:24:16 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-idx.h (maybe_delete_elements): Give useful error message.\n\n\t* dbleSCHUR.cc, dbleSVD.cc: Include iostream.h.\n\nMon Nov 13 08:35:07 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CDiagMatrix.cc (inverse): Return retval, not *this.\n\t* dDiagMatrix.cc (inverse): Use same method as for Complex case.\n\nSat Nov  4 05:06:12 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.h, Array.cc, Array-idx.h [HEAVYWEIGHT_INDEXING]: Keep\n\tindex vector object with Array, not ArrayRep.\n\nFri Nov  3 06:52:38 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-idx.h (assign (Array2<T>&, const Array2<T>&): Don't fail\n\tif index is a colon and resizing is maybe needed.\n\nTue Oct 31 17:40:01 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.cc (IDX_VEC_REP::is_colon_equiv): Don't return true\n\tif we have a vector of 1's.\n\n\t* Array-idx.h (assign (Array2<LT>&, Array2<RT>&): If lhs has no\n\tcurrent orientation, require index and rhs to conform unless\n\tdo_fortran_indexing flag is set.\n\nSun Oct 15 23:32:08 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array-d.cc, Array-C.cc, mx-base.h, mx-inlines.cc, dDiagMatrix.h,\n\tCDiagMatrix.h, CMatrix.cc, CMatrix.h, dMatrix.h, mx-defs.h,\n\tcMatrix.h, MArray.cc, MArray.h, MArray-i.cc, MArray-c.cc,\n\tMArray-s.cc, Array.h, Array.cc, Array-c.cc, Array-i.cc,\n\tArray-s.cc, cMatrix.cc, Array-idx.h, dMatrix.cc:\n\tMassive changes to support additional data types.  Only charMatrix\n\tis currently used in Octave.\n\nThu Oct 12 02:22:36 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Array.cc (Array2<T>::insert (Array2<T>&, int, int): New function.\n\t* CMatrix.cc (ComplexMatrix::insert (ComplexMatrix&, int, int):\n\tSimply call Array2<Complex> version.\n\t* dMatrix.cc (Matrix::insert (Matrix&, int, int): Similarly, just\n\tcall Array2<double> version.\n\n\t* Array-C.cc, Array-d.cc: Instantiate new assign functions too.\n\n\t* Array.h, Array.cc: Massive overhaul to support new way of\n\thandling indexing.\n\t* idx-vector.h, idx-vector.cc: Likewise.\n\t* Array-ext.cc, Array-idx.h: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\nWed Oct 11 00:49:58 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Range.cc (nelem_internal): Use tfloor here, not round.\n\nSun Oct  8 18:21:02 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.h, idx-vector.cc: New files, moved from ../src.\n\t* Makefile.in (SOURCES, INCLUDES): Include them in the lists.\n\nSat Oct  7 19:07:02 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* CMatrix.cc (pseudo_inverse): Avoid bogus g++ warning.\n\n\t* Array.h: Move simple member functions here.\n\t* Array.cc: From here.\n\nFri Oct  6 00:36:04 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Range.cc (tfloor, tceil, round): New static functions.\n\t(Range::nelem_internal): Rewrite to use better method.\n\n\t* dbleSVD.h (SVD::type): New item, sigma_only.\n\t(type_computed): New var.\n\t* dbleSVD.cc (left_singular_matrix, right_singular_matrix):\n\tHandle possible error condition.\n\t(init): Allow for SVD::sigma_only, save type computed.\n\t* CmplxSVD.cc (left_singular_matrix, right_singular_matrix):\n\tHandle possible error condition.\n\t(init): Allow for SVD::sigma_only, save type computed.\n\nWed Oct  4 15:33:35 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Nearly all non-matrix .h and .cc files:\n\tMove short function bodies into class declarations for inlining.\n\tGenerally clean up.\n\n\t* base-min.h: New file.\n\t* LP.h (class LP): Derive from base_minimizer.\n\t* QLP.h (class QLP): Derive from base_minimizer.\n\t* NLP.h (class NLP): Derive from base_minimizer.\n\t* Makefile.in (INCLUDES): Add base-min.h to the list.\n\n\t* Makefile.in (SOURCES): Delete DAEFunc.cc, LP.cc, NLConst.cc,\n\tNLFunc.cc, Objective.cc and QP.cc from list.\n\nTue Sep 26 04:14:23 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dbleSCHUR.cc (select_ana): Remove name of unused parameter.\n\t(SCHUR::SCHUR): Delete unused parameter ord.\n\t* CmplxSCHUR.h (ComplexSCHUR::CmplxSCHUR): Likewise.\n\n\t* CRowVector.cc\n \t(ComplexRowVector::operator+ (const Complex&, const RowVector&),\n\t(ComplexRowVector::operator- (const Complex&, const RowVector&),\n\t(ComplexRowVector::operator* (const Complex&, const RowVector&),\n\t(ComplexRowVector::operator/ (const Complex&, const RowVector&)):\n\tActually do something.\n\n\t* dMatrix.cc (Matrix::lssolve (ComplexMatrix&)): Use dummy vars.\n\t(Matrix::lssolve (ComplexMatrix&, int&)): Likewise.\n\t(Matrix::lssolve (ComplexMatrix&, int&, int&)): Likewise.\n\n\t* Quad.cc (Quad_options::Quad_options (double, double)): New function.\n\t* (Quad::Quad (integrand_fcn, double, double): Properly initialize\n\ttolerances.\n\n\t* DAE.cc (ddassl_f, ddassl_j): Remove names of unused parameters.\n\t* LPsolve.cc (LPsolve::minimize): Likewise.\n\t* NPSOL.cc (NPSOL::option, npsol_confun, npsol_objfun): Likewise.\n\t* ODE.cc (lsode_f, lsode_j): Likewise.\n\t* QPSOL.cc (qphess): Likewise.\n\nFri Sep 22 04:14:51 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dMatrix.cc: Include <cstring>.\n\n\t* Array.cc: Try harder to avoid warnings from gcc in functions\n\tthat return bogus values after calling the error handler.\n\nThu Sep 14 00:56:00 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Use `ifndef omit_deps', not `ifndef $(omit_deps)'.\n\n\t* Makefile.in (TEMPLATE_SRC): Add Array-i.cc to the list.\n\nTue Aug 22 00:41:06 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DAE.cc (dassl_f): Add UNUSED attribute for unused parameters.\n\t(dassl_j): Likewise.\n\n\t* DAE.cc, NLEqn.cc, NPSOL.cc, ODE.cc, CColVector.cc, CMatrix.cc,\n\tdColVector.cc, dMatrix.cc, CmplxLU.cc, dbleLU.cc, QPSOL.cc,\n\tArray.cc, CollocWt.cc, FEGrid.h, LinConst.h:\n\tUpdate for change in for loop variable scope for gcc 2.7.0.\n\nMon Aug 21 19:34:53 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Only include dependency files if $(omit_deps) is\n\tnot set.\n\nMon May  1 13:26:00 1995  John Eaton  (jwe@bullwinkle.che.utexas.edu)\n\n\t* dbleSCHUR.h dbleSVD.h dbleQRP.h dbleQR.h dbleHESS.h dbleLU.h\n\tdbleCHOL.h dbleGEPBAL.h dbleAEPBAL.h dbleDET.h dDiagMatrix.h\n\tdColVector.h dMatrix.h dRowVector.h Quad.h Range.h QPSOL.h QLD.h\n\tODEFunc.h QP.h Objective.h NPSOL.h ODE.h NLEqn.h NLFunc.h\n\tNLConst.h LinConst.h LPsolve.h LP.h FSQP.h FEGrid.h EIG.h\n\tDAEFunc.h CollocWt.h DAE.h CmplxSVD.h CmplxQRP.h CmplxSCHUR.h\n\tCmplxHESS.h CmplxDET.h CmplxLU.h CmplxQR.h CmplxCHOL.h\n\tCmplxAEPBAL.h CRowVector.h CDiagMatrix.h Bounds.h CColVector.h\n\tCMatrix.h dbleSCHUR.cc dbleSVD.cc dbleQRP.cc dbleQR.cc\n\tdbleGEPBAL.cc dbleLU.cc dbleHESS.cc dbleDET.cc dbleCHOL.cc\n\tdbleAEPBAL.cc dColVector.cc dRowVector.cc dMatrix.cc\n\tdDiagMatrix.cc QPSOL.cc Range.cc Quad.cc QP.cc ODEFunc.cc QLD.cc\n\tObjective.cc NLEqn.cc ODE.cc NPSOL.cc NLFunc.cc LPsolve.cc\n\tNLConst.cc LinConst.cc FSQP.cc FEGrid.cc LP.cc DAE.cc EIG.cc\n\tCollocWt.cc DAEFunc.cc CmplxSVD.cc CmplxSCHUR.cc CmplxQRP.cc\n\tCmplxLU.cc CmplxQR.cc CmplxHESS.cc CmplxDET.cc CmplxCHOL.cc\n\tCmplxAEPBAL.cc CRowVector.cc CColVector.cc CMatrix.cc\n\tCDiagMatrix.cc Bounds.cc MArray.h MArray.cc Array.cc Array.h\n\tNLP.h: Use pragma interface/implementation. Don't surround\n\tcontents in extern \"C++\".\n\t* lo-error.h sun-utils.h: Don't surround contents in extern \"C++\".\n\nTue Apr 11 10:59:24 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* f77-uscore.h (F77_FCN): Allow for possibility of uppercase\n\tidentifiers.\n\t* utils.cc dbleSVD.cc dbleSCHUR.cc dbleQRP.cc dbleQR.cc dbleLU.cc\n\tdbleHESS.cc dbleGEPBAL.cc dbleAEPBAL.cc dRowVector.cc\n\tdColVector.cc QLD.cc CmplxSVD.cc CmplxCHOL.cc CmplxHESS.cc\n\tCmplxQR.cc CmplxQRP.cc QPSOL.cc CmplxAEPBAL.cc CmplxLU.cc\n\tCmplxSCHUR.cc dMatrix.cc CColVector.cc CRowVector.cc dbleCHOL.cc\n\tCollocWt.cc NLEqn.cc EIG.cc DAE.cc ODE.cc CMatrix.cc NPSOL.cc\n\tQuad.cc: Change usage of F77_FCN to match new definition\n\n\t* utils.cc dbleSVD.cc dbleSCHUR.cc dbleQRP.cc dbleQR.cc dbleLU.cc\n\tdbleHESS.cc dbleGEPBAL.cc dbleAEPBAL.cc dRowVector.cc\n\tdColVector.cc QLD.cc CmplxSVD.cc CmplxCHOL.cc CmplxHESS.cc\n\tCmplxQR.cc CmplxQRP.cc QPSOL.cc CmplxAEPBAL.cc CmplxLU.cc\n\tCmplxSCHUR.cc dMatrix.cc CColVector.cc CRowVector.cc dbleCHOL.cc\n\tCollocWt.cc NLEqn.cc EIG.cc DAE.cc ODE.cc CMatrix.cc NPSOL.cc\n\tQuad.cc: Where appropriate, declare Fortran subroutines to take\n\targs by reference instead of pointer.  Change all callers.\n\nSun Apr  9 20:11:56 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* MArray.h (MArray2::~MArray2, MDiagArray::~MDiagArray): New\n\tfunctions.  Make += and -= operators friend functions.\n\n\t* Array.h (Array2::~Array2, Array3::~Array3,\n\tDiagArray::~DiagArray): New functions.\n\nWed Apr  5 21:21:13 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makefile.in (EXTRAS): Don't distribute mx-kludge.cc.\n\t(MATRIX_INC): Don't distribute mx-kludge.h.\n\n\t* CColVector.h CColVector.cc CDiagMatrix.h CDiagMatrix.cc\n\tCMatrix.h CMatrix.cc CRowVector.h CRowVector.cc dColVector.h\n\tdColVector.cc dDiagMatrix.h dDiagMatrix.cc dMatrix.h dMatrix.cc\n\tdRowVector.h dRowVector.cc:\n\tDerive classes from MArray, MArray2, and MDiagArray, not Array,\n\tArray2, and DiagArray2.\n\tDon't use functions defined in mx-kludge.cc for arithmetic\n\tlike-type operations on arrays.\n\n\t* MArray.cc: Use the classes defined here like-type mathematical\n\toperations on Array objects.  Abuse CPP more.\n\t* Makefile.in (TEMPLATE_SRC): Add it to the list.\n\t(EXTRAS): Delete it from this list.\n\n\t* MArray-C.cc, MArray-d.cc: New files.\n\t* Makefile.in (TI_SRC): Add them to the list.\n\nTue Apr  4 14:13:46 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* mx-kludge.cc: Abuse CPP even more.\n\nMon Apr  3 21:05:30 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Objective.h (objective_function): Add missing const.\n\t(gradient_function): Likewise.\n\n\t* CColVector.h CColVector.cc CDiagMatrix.h CDiagMatrix.cc\n\tCMatrix.h CMatrix.cc CRowVector.h CRowVector.cc dColVector.h\n\tdColVector.cc dDiagMatrix.h dDiagMatrix.cc dMatrix.h dMatrix.cc\n\tdRowVector.h dRowVector.cc:\n\tReorganize to declare and define friends where they should be,\n\tbased on the use of private constructors.\n\nFri Mar 31 10:09:40 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* CRowVector.h (linspace): Add declaration.\n\t* dRowVector.h (linspace): Likewise.\n\n\t* dMatrix.cc (Matrix::inverse, Matrix::determinant, Matrix::solve):\n\tForce result of rcond + 1.0 to be stored.\n\t* CMatrix.cc (ComplexMatrix::inverse, ComplexMatrix::determinant,\n\tComplexMatrix::solve): Likewise.\n\nSee ChangeLog.1 in the top level directory for earlier changes.\n"
  },
  {
    "path": "etc/OLD-ChangeLogs/scripts-ChangeLog",
    "content": "2011-04-18  Paul Boven  <p.boven@xs4all.nl>\n\n\t* image/image.m: Fixed naming of variables in texinfo\n\n2011-04-17  Patrick Häcker  <magicmuscleman>\n\n\t* strings/mat2str.m: Limit the number of digits to one less than\n\tavailable for double.\n\n2011-04-15  Kai Habel  <kai.habel@gmx.de>\n\n\t* general/interp1.m, polynomial/mkpp.m, polynomial/pchip.m,\n\tpolynomial/ppder.m, polynomial/ppint.m, polynomial/ppjumps.m,\n\tpolynomial/ppval.m, polynomial/spline.m, polynomial/unmkpp.m:\n\tMake functions more compatible with respect to handling of\n\tpicewise polynoms (pp). Rename pp-struct elements.\n\tHandle nD-arguments correctly. Tests added.\n\t(bugs #32040, #32045)\n\n2011-04-13  David Bateman  <dbateman@free.fr>\n\n\t* plot/colstyle.m : New function.\n\t* plot/module.mk plot_FCN_FILES) : Add it here.\n\n2011-04-13  Rik  <octave@nomad.inbox5.com>\n\n\t* help/__makeinfo__.m: Simplify function by using regular expressions.\n\tEliminate third input argument see_also function.\n\n2011-04-13  Rik  <octave@nomad.inbox5.com>\n\n\t* general/isdir.m, general/isequal.m, general/isequalwithequalnans.m,\n\tgeneral/isscalar.m, general/issquare.m, general/isvector.m: Refactor\n\tcode to put input validation first.\n\n\t* general/iscolumn.m, general/isrow.m : Remove useless initialization\n\tof output variable.\n\n\t* general/isa.m: Add additional tests for various classes.\n\n2011-04-13  Rik  <octave@nomad.inbox5.com>\n\n\t* ChangeLog: Remove results of bad merge in ChangeLog.\n\n2011-04-12  Ben Abbott  <bpabbott@mac.com>\n\n\t* miscellaneous/getappdata.m: If no property name is provided, return\n\ta structure representing the appdata.\n\n2011-04-12  Marco Caliari  <marco.caliari@univr.it>\n\n\t* general/quadgk.m: Fix problem with -Inf bound on integral (bug\n\t#33055).\n\n2011-04-11  Ben Abbott  <bpabbott@mac.com>\n\n\t* miscellaneous/getappdata.m: If appdata propery does not exist, return\n\tan empty matrix.\n\n2011-04-08  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/module.mk, statistics/base/center.m,\n\tstatistics/base/module.mk: Deprecate studentize(), replace with\n\tzscore().\n\n2011-04-08  Rik  <octave@nomad.inbox5.com>\n\n\t* linear-algebra/cond.m, linear-algebra/expm.m, linear-algebra/logm.m,\n\tlinear-algebra/null.m, linear-algebra/orth.m, linear-algebra/rank.m,\n\tlinear-algebra/rref.m: Improve docstrings.\n\n2011-04-08  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/base/mode.m, statistics/base/quantile.m: Return output\n\tof same class as input.\n\n2011-04-06  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/pack.m: Improve docstring.\n\n2011-04-06  Rik  <octave@nomad.inbox5.com>\n\n\t* signal/module.mk: Make spectral density helper functions private.\n\t(rectangle_sw, rectangle_lw, triangle_sw, triangle_lw)\n\n2011-04-06  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/fminunc.m, plot/isocolors.m, plot/isonormals.m:\n\tClean up operator and function indices.\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/symvar.m, miscellaneous/warning_ids.m,\n\toptimization/fminunc.m: Spellcheck documentation for 3.4.1 release.\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* @ftp/mget.m, audio/loadaudio.m, audio/playaudio.m, audio/record.m,\n\taudio/saveaudio.m, general/circshift.m, general/cumtrapz.m,\n\tgeneral/dblquad.m, general/quadgk.m, general/quadl.m,\n\tgeneral/shiftdim.m, general/triplequad.m, geometry/convhull.m,\n\tgeometry/delaunay3.m, geometry/dsearch.m, geometry/dsearchn.m,\n\tgeometry/tsearchn.m, geometry/voronoi.m, image/brighten.m,\n\tio/textscan.m, miscellaneous/getappdata.m,\n\tmiscellaneous/namelengthmax.m, miscellaneous/rmappdata.m,\n\tmiscellaneous/setappdata.m, miscellaneous/swapbytes.m,\n\tmiscellaneous/symvar.m, miscellaneous/warning_ids.m,\n\tpkg/private/get_forge_pkg.m, plot/clabel.m, plot/colorbar.m,\n\tplot/cylinder.m, plot/daspect.m, plot/linkprop.m, plot/pbaspect.m,\n\tplot/plotyy.m, plot/private/__add_default_menu__.m, plot/sphere.m,\n\tplot/subplot.m, plot/view.m, polynomial/polyreduce.m,\n\tpolynomial/ppder.m, polynomial/ppint.m, signal/periodogram.m,\n\tsparse/colperm.m, sparse/nonzeros.m, sparse/spaugment.m,\n\tsparse/speye.m, sparse/treelayout.m, sparse/treeplot.m,\n\tstatistics/base/kurtosis.m, statistics/base/mean.m,\n\tstatistics/base/meansq.m, statistics/base/median.m,\n\tstatistics/base/mode.m, statistics/base/moment.m,\n\tstatistics/base/ranks.m, statistics/base/skewness.m,\n\tstatistics/base/statistics.m, statistics/base/var.m, time/datenum.m,\n\ttime/datetick.m, time/now.m: Grammarcheck m-files for 3.4.1 release.\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/module.mk, general/module.mk: Deprecate perror, strerror\n\tfunctions.\n\n2011-04-02  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/base/prctile.m, statistics/base/quantile.m: Improve\n\tdocstrings.\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* pkg/module.mk, pkg/pkg.m, pkg/private/get_forge_pkg.m: Add\n\tdocumentation for '-forge' option (bug #32464).  Make get_forge_pkg\n\ta private function.\n\n2011-03-31  Marco Caliari  <marco.caliari@univr.it>\n\n\t* sparse/spdiags.m: Treat empty vector (1x0 or 0x1) the same as diag().\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/base/cor.m: Increase tolerance of %!tests using random\n\tdata to guarantee passage.\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/module.mk, deprecated/cquad.m: Add deprecated entry for\n\tcquad() pointing to quadcc().\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/base/cor.m: Fix operation with only single input\n\t(bug #32961)\n\n2011-03-29  John W. Eaton  <jwe@octave.org>\n\n\t* special-matrix/wilkinson.m: Update test for 'wilkinson(1)' to reflect\n\tchanges to diag().\n\n2011-03-29  Michael Creel  <michael.creel@uab.es>\n\n\t* statistics/base/ols.m: Fix erroneous degrees of freedom when\n\tcomputing the covariance estimator (closes: bug #32892).\n\n2011-03-28  Rik  <octave@nomad.inbox5.com>\n\n\t* linear-algebra/cross.m, plot/ishold.m, signal/fftfilt.m: Improve\n\tdocstrings.\n\n2011-03-26  Robert T. Short  <octave@phaselockedsystems.com.com>\n\n\t* signal/ifftshift.m: Add tests.\n\n2011-03-26  Robert T. Short  <octave@phaselockedsystems.com.com>\n\n\t* signal/fftshift.m: Add tests.\n\n2011-03-21  Rik  <octave@nomad.inbox5.com>\n\n\t* signal/ifftshift.m: Fix bug #32873, ifftshift fails.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* general/module.mk, statistics/base/module.mk: Move runlength.m\n\tto statistics/base directory.\n\t* statistics/base/runlength.m: Add input validation and tests.\n\tImprove docstring.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/models/logistic_regression.m: Do not split function\n\tdeclaration with line continuation.\n\t* statistics/models/private/logistic_regression_likelihood.m,\n\tstatistics/models/private/logistic_regression_derivatives.m: Make\n\thelper functions private.\n\t* statistics/models/module.mk: Make helper functions private.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/isocolors.m, plot/isonormals.m, plot/isosurface.m: Improve\n\tdocstrings.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/dump_prefs.m: Close @deftypefn macro left open.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/dump_prefs.m: Improve docstring.\n\n2011-03-19  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/daspect.m, plot/pbaspect.m: Use newline between @deftypefnx\n\tmacros to get correct appearance.\n\n2011-03-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/patch.m: Add demo.\n\t* geometry/trisurf.m: Set default edgecolor as Matlab does. Add demos.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/uigetdir.m, plot/uigetfile.m, plot/uimenu.m, plot/uiputfile.m:\n\tImprove docstrings.  Check for error conditions (missing FLTK, wrong\n\tnumber of arguments) at top of code.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* general/curl.m, general/divergence.m, linear-algebra/cross.m:\n\tUpdate seealso cross references.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* help/get_first_help_sentence.m: Improve docstring.  Add tests.\n\n2011-03-17  Rik  <octave@nomad.inbox5.com>\n\n\t* scripts/sparse/svds.m: Fix bug #32818, nonconformant arguments\n\tin svds.\n\n2011-03-17  Rik  <octave@nomad.inbox5.com>\n\n\t* io/fileread.m: Add seealso reference to sscanf.\n\n2011-03-05  Ben Abbott <bpabbott@mac.com>\n\n\t* plot/colorbar.m: Allow location to be specified as a property.\n\n2011-03-03  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/bunzip2.m, miscellaneous/bzip2.m,\n\tmiscellaneous/gunzip.m, miscellaneous/gzip.m, miscellaneous/unpack.m,\n\tmiscellaneous/untar.m, miscellaneous/unzip.m: Improve docstrings\n\n\t* miscellaneous/tar.m, miscellaneous/zip.m: Check for invalid arguments\n\tat the top, rather than bottom, of code.\n\n2011-03-03  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/gzip.m: Use same functional form as bzip, zip, etc.\n\t* miscellaneous/private/__xzip__.m: Allow use of character arrays of\n\tfilenames.\n\t* miscellaneous/unpack.m: Allow use of character arrays of filenames.\n\tAdd capability for gunzip to work recursively on a directory.\n\tFix bug where unzip returned the archive name in addition to the list\n\tof files unzipped.\n\n2011-03-03  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/module.mk, general/module.mk: Deprecate is_duplicate_entry.\n\n2011-03-03  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/movefile.m: Fix copy&paste bug affecting Windows\n\tplatform.  (bug #32443)\n\n2011-03-02  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/distributions/unidcdf.m,\n\tstatistics/distributions/unidinv.m, statistics/distributions/unidpdf.m,\n\tstatistics/distributions/unidrnd.m: Correctly refer to distribution as\n\tdiscrete uniform in docstring.\n\n2011-03-02  Konstantinos Poulios  <logari81@gmail.com>\n\n\t* plot/subplot.m: Remove redundant calls.\n\tFor gnuplot set \"activepositionproperty\" to \"position\" always.\n\n2011-03-01  Rik  <octave@nomad.inbox5.com>\n\n\t* general/isscalar.m, general/isvector.m: Use modern warning function\n\trather than deprecated built-in variable to set warning state.\n\n2011-02-28  Rik  <octave@nomad.inbox5.com>\n\n\t* general/iscolumn.m, general/isrow.m: Add 2 new utility functions\n\tto check for row or column vector.\n\n2011-02-28  Rik  <octave@nomad.inbox5.com>\n\n\t* sparse/treeplot.m: Use 'o' plot style as default for nodes\n\n2011-02-27  Rik  <octave@nomad.inbox5.com>\n\n\t* special-matrix/pascal.m: Fix incorrect statement in documentation\n\tfor pascal.m.  Bug #32523.\n\n2011-02-26  Andy Buckle  <andybuckle@gmail.com>\n\n\t* testfun/demo.m, testfun/example.m: Allow command forms of example\n\tand demo.\n\n2011-02-26  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* polynomial/polyval.m: Compute offset/normalization only when needed.\n\n2011-02-26  Robert T. Short <octave@phaselockedsystems.com>\n\n\t* polynomial/polyval.m: Minor simplification in polynomial evaluation.\n\n2011-02-22  Rik  <octave@nomad.inbox5.com>\n\n\t* general/bitcmp.m, general/bitget.m, general/bitset.m,\n\tmiscellaneous/license.m, special-matrix/pascal.m,\n\tstatistics/base/quantile.m, statistics/tests/cor_test.m,\n\tstrings/substr.m: Uppercase variables in error strings.\n\n2011-02-25  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* miscellaneous/warnings_ids.m: Add a warning description for\n\tMatlab-style short-circuiting\n\n2011-02-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/subplot.m: Document using INDEX as a vector.\n\n2011-02-24  Robert T. Short  <rtshort@ieee.org>\n\n\t* polynomial/polyval.m: Properly evaluate constant polynomials.\n\n2011-02-24  John W. Eaton  <jwe@octave.org>\n\n\t* strings/strchr.m: Avoid implicit string to number conversion.\n\tBug #32546.  From Kim Hansen <kim@i9.dk>.\n\n2011-02-22  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/subplot.m: Use new looseinset property introduced by changeset\n\t12467. Decrease spacing between subplots rows / columns. Clean up and\n\tadd comments.\n\n2011-02-22  Rik  <octave@nomad.inbox5.com>\n\n\t* io/strread.m, plot/whitebg.m, strings/regexptranslate.m,\n\ttestfun/runtests.m: Use single quotes around regexp patterns.\n\n2011-02-20  Karsten Trulsen  <karstent@math.uio.no>\n\n\t* signal/fftshift.m: Fix broken function.  Bug 32442.\n\n2011-02-21  Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* pkg/get_forge_pkg.m: Fix typo in new PCRE style regular expression.\n\n2011-02-20  Thomas Weber <tweber@debian.org>\n\n\t* miscellaneous/warning_ids.m: Document\n\tOctave::autoload-relative-file-name warning.\n\n2011-02-19  Rik  <octave@nomad.inbox5.com>\n\n\t* io/dlmwrite.m, pkg/get_forge_pkg.m, plot/__gnuplot_ginput__.m,\n\tplot/__go_draw_axes__.m, testfun/runtests.m: Use PCRE regular\n\texpressions to simplify scripts.\n\n2011-02-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__print_parse_opts__.m, plot/private/__ghostscript__.m: Improve\n\twarnings when shell utilties are missing.\n\n2011-02-19  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* general/interp1.m: Fix tests according to spline update of\n\tchangeset 07e102029d2a (see bug 31780)\n\n2011-02-17  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/private/__add_default_menu__.m: Rename fltk_gui_mode here\n\tas well.\n\n2011-02-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/subplot.m: Decrease spacing between subplots rows / columns.\n\tClean up and add comments.\n\n2011-02-16  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* statistics/base/mean.m: Fix tests according to changeset 0f21f258aa17.\n\n2011-02-15  Konstantinos Poulios  <logari81@gmail.com>\n\n\t* plot/__fltk_print__.m: Forward pipeline to drawnow instead of\n\tinvoking a process here.  Bug #32319.\n\n2011-02-14  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/semilogxerr.m, plot/semilogyerr.m, special-matrix/pascal.m,\n\tspecial-matrix/rosser.m, special-matrix/wilkinson.m: Add missing\n\tcommas in @seealso macro.\n\n2011-02-14  David Bateman  <dbateman@free.fr>\n\n\t* testfun/test.m: More explicit error message when source of a\n\tdynamically linked function is not found.  Bug #30341.\n\n2011-02-14  David Bateman  <dbateman@free.fr>\n\n\t* plot/private/__scatter__.m: Correctly set the facevertexcdata and\n\tfaces properties in the patch objects.  Bug #31801.\n\n2011-02-14  Marco Caliari <marco.caliari@univr.it>\n\n\t* polynomial/spline.m: Allow length(x) == 2 and unsorted x values.\n\n2011-02-13  Konstantinos Poulios  <logari81@gmail.com>\n\n\t* plot/legend.m: Ignore outerposition.\n\n2011-02-10  Ben Abbott <bpabbott@mac.com>\n\n\t* plot/legend.m, plot/plotyy.m, plot/sombrero.m, plot/shading.m,\n\tplot/text.m: Modify demo scripts to allow conventient conversion\n\tto Matlab compatible syntax.\n\n2011-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/base/mean.m: Also accept logical values.\n\n2011-02-10 Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* linear-algebra/gmres.m: New file implementing the GMRES\n\titerative method for solving linear systems.\n\n2011-02-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Properly set fontspec for legends.\n\n2011-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/complement.m, deprecated/create_set.m,\n\tdeprecated/dmult.m, deprecated/iscommand.m,\n\tdeprecated/israwcommand.m, deprecated/lchol.m,\n\tdeprecated/loadimage.m, deprecated/mark_as_command.m,\n\tdeprecated/mark_as_rawcommand.m, deprecated/spatan2.m,\n\tdeprecated/spchol2inv.m, deprecated/spcholinv.m,\n\tdeprecated/spchol.m, deprecated/spcumprod.m,\n\tdeprecated/spcumsum.m, deprecated/spdet.m, deprecated/spdiag.m,\n\tdeprecated/spfind.m, deprecated/spinv.m, deprecated/spkron.m,\n\tdeprecated/splchol.m, deprecated/split.m, deprecated/splu.m,\n\tdeprecated/spmax.m, deprecated/spmin.m, deprecated/spprod.m,\n\tdeprecated/spqr.m, deprecated/spsum.m, deprecated/spsumsq.m,\n\tdeprecated/str2mat.m, deprecated/unmark_command.m,\n\tdeprecated/unmark_rawcommand.m:\n\tRemove functions deprecated in version 3.2.\n\t* module.mk (deprecated_FCN_FILES): Remove them from the list.\n\n2011-02-05  David Bateman  <dbateman@free.fr>\n\n\t* plot/legend.m: Allow the location and orientation to be set\n\twithout modifiying the legend keys.\n\t* plot/legend.m: Add padding to legend positions. Fix for\n\touterposition for southeastoutside and southwestoutside.\n\tBug #32374.\n\n2011-02-06  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/legend.m: Align legends to plot box, add demo. Bug 32373.\n\t* plot/legend.m: \"legend off\" should delete the legend object.\n\n2011-02-06  David Bateman  <dbateman@free.fr>\n\n\t* plot/legend.m : Delete old legend before probing the position and\n\touterposition. Reshape lpos correct if the legend locqtion is\n\t\"southeast\".  Bug #32343.\n\n2011-02-06  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/legend.m: Add demo for replacing existing legend.\n\n2011-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* general/circshift.m: New tests.\n\n2011-02-05  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/version.m, path/matlabroot.m: Correct spelling.\n\n2011-02-05  Rik  <octave@nomad.inbox5.com>\n\n\t* help/help.m, linear-algebra/onenormest.m, plot/graphics_toolkit.m,\n\tplot/pie3.m, plot/view.m, signal/periodogram.m: Grammarcheck docstrings.\n\n2011-02-05  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/legend.m: Add demo for inline keys created by two plot commands.\n\n2011-02-05  David Bateman  <dbateman@free.fr>\n\n\tBug #32022 and #32343.\n\n\t* plot/legend.m (updatelegend): Don't flip plots when resetting the\n\tlegend. Use unwind_protect to ensure that the resursive flag is reset\n\tin case of an error.\n\t(getlegenddata): Remove this function and replace its use with the\n\tfunction __getlegenddata__.\n\t* plot/privata/__getlegenddata__.m: New function\n\t* plot/module.mk (plot_PRIVATE_FCN_FILES): Add it here.\n\t* plot/private/__plt__.m: Set initial values of hlgnd and tlgnd\n\tif a legend exists already.\n\n2011-02-02  Rik  <octave@nomad.inbox5.com>\n\n\t* sparse/svds.m: Use testif to only run some sparse tests when\n\tnecessary libraries are installed.\n\n2011-02-01  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__gnuplot_has_feature__.m: Don't throw an error if gnuplot\n\tisn't installed.\n\n2011-02-01  John W. Eaton  <jwe@octave.org>\n\n\t* plot/scatter3.m: Pass h to set, not ax.\n\n2011-01-31  John W. Eaton  <jwe@octave.org>\n\n\t* plot/private/__axis_label__.m: Don't call __fltk_redraw__.\n\n2011-01-31  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__fltk_ginput__.m: Remove line that should have been\n\tremoved in previous change.\n\n2011-01-31  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/private/__gnuplot_has_terminal__.m: Simplify regular expression\n\tto eliminate word-boundary assertion.\n\n2011-01-30  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/module.mk, optimization/module.mk: Deprecate glpkmex\n\tfunction.\n\n2011-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__gnuplot_drawnow__.m: Rename from gnuplot_drawnow.m\n\tUpdate doc string and error message with new name.\n\t* plot/module.mk (plot_FCN_FILES): Update list.\n\n2011-01-30  Petr Mikulik  <mikulik@physics.muni.cz>\n\n\t* plot/__fltk_ginput__.m (ginput_aggregator): New arg, button.\n\tChange all uses.\n\t(ginput_keypressfcn): Save keypress info.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/gnuplot_binary.in: Improve docstring\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* general/accumarray.m: Add seealso reference to accumdim.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* set/powerset.m: Improve docstring.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/copyfile.m, miscellaneous/movefile.m,\n\tmiscellaneous/tempname.m: Improve docstrings\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/module.mk, image/module.mk: Deprecate saveimage.m.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/glpkmex.m: Add seealso reference to glpk.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/compare_versions.m: Allow only \"==\" equality operator.\n\tAdd input validation tests.  Improve docstring.\n\n\t* miscellaneous/ver.m, miscellaneous/version.m, path/matlabroot.m:\n\tImprove docstring.\n\n2011-01-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* miscellaneous/edit.m: As most editors open their own window, change\n\tmode to \"async\".\n\n2011-01-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__fltk_print__.m, plot/print.m: Fix {eps,ps,pdf}latexstandalone\n\tprinting for fltk, bug 32262.\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* sparse/svds.m: Use \"test\" instead of \"testif HAVE_ARPACK\".\n\n2011-01-27  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/whitebg.m: Improve docstring.\n\n2011-01-27  Rik  <octave@nomad.inbox5.com>\n\n\t* geometry/trimesh.m, geometry/triplot.m, geometry/trisurf.m: Add\n\tundocumented function trisurf to documentation.  Update seealso\n\tstrings.\n\n2011-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* general/rat.m: Move @seealso inside @deftypefn in docstring.\n\n2011-01-27  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/uigetfile.m, plot/uiputfile.m, plot/uigetdir.m: Check\n\tfor __fltk_uigetfile__.\n\n2011-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (check-missing-semicolon): New rule.\n\n2011-01-26  Rik  <octave@nomad.inbox5.com>\n\n\t* scripts/general/interp1.m, scripts/general/interp2.m,\n\tscripts/general/interp3.m, scripts/general/interpn.m: Use em-dash\n\trather than en-dash.\n\t* scripts/miscellaneous/mkoctfile.m: Use @code to prevent option\n\tturning to en-dash.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* mkdoc: Untabify.\n\n\t* mkdoc, gethelp.cc: Strip trailing whitespace.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* general/curl.m: Simplify processing of outptut values.\n\n2011-01-26  Olaf Till  <olaf.till@uni-jena.de>\n\n\t* pkg/pkg.m: Export environment variables MKOCTFILE and\n\tOCTAVE_CONFIG for configure and make, to configure also OCTAVE.\n\n2011-01-24  John W. Eaton  <jwe@octave.org>\n\n\t* audio/lin2mu: Doc fix.\n\n\t* audio/mu2lin.m: Doc fix.\n\tFor compatibility with Matlab, change default for N to be 8.\n\n2011-01-22  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/info.m: Use reference to bug tracker rather than\n\toctave-dev mailing list.\n\n2011-01-22  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/meshc.m: Add note: gnuplot does not support filled 3D patches,\n\tor mixing non-filled contours with filled surfaces.\n\t* plot/subplot.m: Set \"box\" to \"on\" by default (same as Matlab).\n\t* plot/cylinder.m: Remove console output from demo.\n\n2011-01-22  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* plot/plotyy.m: Set box property to off to allow both y-axes colors\n\tto be visible for OpenGL backends.\n\n2011-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* plot/private/__scatter__.m: Don't accept \"filled\" as a color.\n\t* plot/scatter.m: Doc fix.\n\tBug #32204.\n\n2011-01-21  Konstantinos Poulios  <logari81@gmail.com>\n\n\t* plot/xlabel.m, plot/ylabel.m, plot/zlabel.m: Setting axis label\n\tcolor from axis color.\n\n2011-01-20  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* image/imshow.m: Fix handling of clim and display_range so that\n\timages are more faithfully reproduced.\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* scripts/image/imshow.m, scripts/image/saveimage.m,\n\tscripts/io/dlmwrite.m, scripts/io/strread.m,\n\tscripts/miscellaneous/license.m, scripts/optimization/glpk.m,\n\tscripts/plot/refreshdata.m, scripts/plot/shading.m,\n\tscripts/plot/slice.m, scripts/plot/surfl.m, scripts/plot/uimenu.m,\n\tscripts/statistics/base/mean.m, scripts/statistics/base/moment.m,\n\tscripts/strings/isstrprop.m: Prevent doubled quotes around @table\n\titems in Info.\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* mkdoc: Mark all scripts as coming from 'scripts/' directory\n\tin Texinfo '@c func location' comments.\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* scripts/linear-algebra/condest.m,\n\tscripts/linear-algebra/onenormest.m, scripts/linear-algebra/qzhess.m,\n\tscripts/polynomial/polyfit.m, scripts/special-matrix/pascal.m: Use\n\tnon-breaking spaces between certain adjectives and their linked nouns\n\tin docstrings\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* image/imread.m, image/imwrite.m, signal/periodogram.m,\n\tstrings/isstrprop.m: Use @nospell macro on certain words in docstring.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* @ftp/loadobj.m, @ftp/saveobj.m, audio/record.m,\n\tgeneral/accumarray.m, general/accumdim.m, general/arrayfun.m,\n\tgeneral/bicubic.m, general/curl.m, general/divergence.m,\n\tgeneral/gradient.m, general/interp2.m, general/rat.m,\n\timage/imagesc.m, io/strread.m, io/textscan.m,\n\tlinear-algebra/krylov.m, miscellaneous/getappdata.m,\n\tmiscellaneous/isappdata.m, miscellaneous/rmappdata.m,\n\tmiscellaneous/setappdata.m, miscellaneous/what.m,\n\toptimization/qp.m, path/savepath.m, pkg/pkg.m,\n\tplot/__fltk_print__.m, plot/__gnuplot_print__.m,\n\tplot/__go_draw_axes__.m, plot/__print_parse_opts__.m,\n\tplot/axis.m, plot/caxis.m, plot/cla.m, plot/clabel.m,\n\tplot/clf.m, plot/colorbar.m, plot/cylinder.m, plot/daspect.m,\n\tplot/gnuplot_drawnow.m, plot/meshc.m, plot/newplot.m,\n\tplot/orient.m, plot/pbaspect.m, plot/plotyy.m, plot/print.m,\n\tplot/private/__actual_axis_position__.m,\n\tplot/private/__axis_label__.m, plot/private/__bar__.m,\n\tplot/private/__clabel__.m, plot/private/__errplot__.m,\n\tplot/private/__ezplot__.m, plot/private/__ghostscript__.m,\n\tplot/private/__patch__.m, plot/private/__pie__.m,\n\tplot/private/__quiver__.m, plot/private/__scatter__.m,\n\tplot/private/__stem__.m, plot/private/__tight_eps_bbox__.m,\n\tplot/refresh.m, plot/spinmap.m, plot/subplot.m, plot/surfc.m,\n\tplot/uigetfile.m, polynomial/polyout.m, sparse/spaugment.m,\n\tsparse/svds.m, sparse/treeplot.m, statistics/base/histc.m,\n\tstatistics/distributions/hygecdf.m,\n\tstatistics/distributions/hygeinv.m, statistics/tests/manova.m,\n\tstrings/deblank.m, testfun/runtests.m: Add missing semicolons.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/cellidx.m, deprecated/dmult.m,\n\tdeprecated/intwarning.m, deprecated/str2mat.m, general/curl.m,\n\tgeneral/divergence.m, general/gradient.m, geometry/griddata.m,\n\thelp/gen_doc_cache.m, io/dlmwrite.m, miscellaneous/getappdata.m,\n\tmiscellaneous/isappdata.m, miscellaneous/rmappdata.m,\n\tmiscellaneous/setappdata.m, miscellaneous/unpack.m,\n\toptimization/lsqnonneg.m, optimization/pqpnonneg.m,\n\tpkg/get_forge_pkg.m, pkg/pkg.m, plot/__fltk_print__.m,\n\tplot/__gnuplot_get_var__.m, plot/__gnuplot_open_stream__.m,\n\tplot/__gnuplot_print__.m, plot/daspect.m,\n\tplot/gnuplot_drawnow.m, plot/pbaspect.m,\n\tplot/private/__errplot__.m, plot/private/__fltk_file_filter__.m,\n\tplot/private/__ghostscript__.m, plot/uigetfile.m,\n\tplot/uiputfile.m, polynomial/polyaffine.m, sparse/pcg.m:\n\tStyle fixes for error and warning messages.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* @ftp/dir.m, @ftp/mget.m, @ftp/mput.m, ChangeLog,\n\taudio/lin2mu.m, audio/setaudio.m, audio/wavread.m,\n\taudio/wavwrite.m, deprecated/autocor.m, deprecated/autocov.m,\n\tdeprecated/betai.m, deprecated/create_set.m,\n\tdeprecated/dispatch.m, deprecated/gammai.m,\n\tdeprecated/intwarning.m, deprecated/replot.m, elfun/cosd.m,\n\telfun/sind.m, elfun/tand.m, general/accumarray.m,\n\tgeneral/accumdim.m, general/arrayfun.m, general/bicubic.m,\n\tgeneral/bitcmp.m, general/bitget.m, general/bitset.m,\n\tgeneral/cart2pol.m, general/cart2sph.m, general/cell2mat.m,\n\tgeneral/celldisp.m, general/circshift.m, general/cplxpair.m,\n\tgeneral/cumtrapz.m, general/curl.m, general/dblquad.m,\n\tgeneral/deal.m, general/del2.m, general/divergence.m,\n\tgeneral/flipud.m, general/gradient.m, general/idivide.m,\n\tgeneral/int2str.m, general/interp1.m, general/interp2.m,\n\tgeneral/interp3.m, general/interpft.m, general/interpn.m,\n\tgeneral/isdir.m, general/loadobj.m, general/logspace.m,\n\tgeneral/num2str.m, general/pol2cart.m, general/polyarea.m,\n\tgeneral/quadgk.m, general/quadl.m, general/quadv.m,\n\tgeneral/randi.m, general/rat.m, general/repmat.m,\n\tgeneral/rot90.m, general/rotdim.m, general/saveobj.m,\n\tgeneral/shift.m, general/sortrows.m, general/sph2cart.m,\n\tgeneral/structfun.m, general/subsindex.m, general/trapz.m,\n\tgeneral/triplequad.m, geometry/convhull.m, geometry/delaunay.m,\n\tgeometry/delaunay3.m, geometry/delaunayn.m, geometry/dsearch.m,\n\tgeometry/dsearchn.m, geometry/griddata3.m, geometry/griddatan.m,\n\tgeometry/inpolygon.m, geometry/rectint.m, geometry/trimesh.m,\n\tgeometry/trisurf.m, geometry/tsearchn.m, geometry/voronoi.m,\n\thelp/__makeinfo__.m, help/__strip_html_tags__.m, help/doc.m,\n\thelp/gen_doc_cache.m, help/get_first_help_sentence.m,\n\thelp/help.m, help/lookfor.m, help/print_usage.m, help/type.m,\n\timage/autumn.m, image/bone.m, image/brighten.m, image/cool.m,\n\timage/copper.m, image/flag.m, image/gmap40.m, image/gray.m,\n\timage/hot.m, image/hsv.m, image/hsv2rgb.m, image/image.m,\n\timage/imread.m, image/imshow.m, image/imwrite.m,\n\timage/ind2rgb.m, image/jet.m, image/ntsc2rgb.m, image/ocean.m,\n\timage/pink.m, image/prism.m, image/rainbow.m, image/rgb2hsv.m,\n\timage/rgb2ind.m, image/rgb2ntsc.m, image/spring.m,\n\timage/summer.m, image/winter.m, io/dlmwrite.m, io/fileread.m,\n\tio/strread.m, io/textread.m, linear-algebra/cond.m,\n\tlinear-algebra/condest.m, linear-algebra/cross.m,\n\tlinear-algebra/expm.m, linear-algebra/isdefinite.m,\n\tlinear-algebra/krylov.m, linear-algebra/logm.m,\n\tlinear-algebra/normest.m, linear-algebra/onenormest.m,\n\tlinear-algebra/rref.m, linear-algebra/subspace.m,\n\tmiscellaneous/ans.m, miscellaneous/bincoeff.m,\n\tmiscellaneous/bunzip2.m, miscellaneous/bzip2.m,\n\tmiscellaneous/computer.m, miscellaneous/copyfile.m,\n\tmiscellaneous/debug.m, miscellaneous/edit.m,\n\tmiscellaneous/getappdata.m, miscellaneous/getfield.m,\n\tmiscellaneous/gunzip.m, miscellaneous/gzip.m,\n\tmiscellaneous/isappdata.m, miscellaneous/ls.m,\n\tmiscellaneous/mkoctfile.m, miscellaneous/movefile.m,\n\tmiscellaneous/namelengthmax.m, miscellaneous/orderfields.m,\n\tmiscellaneous/private/__xzip__.m, miscellaneous/rmappdata.m,\n\tmiscellaneous/setappdata.m, miscellaneous/substruct.m,\n\tmiscellaneous/swapbytes.m, miscellaneous/tar.m,\n\tmiscellaneous/unimplemented.m, miscellaneous/unpack.m,\n\tmiscellaneous/untar.m, miscellaneous/unzip.m,\n\tmiscellaneous/ver.m, miscellaneous/warning_ids.m,\n\tmiscellaneous/what.m, miscellaneous/zip.m,\n\toptimization/__all_opts__.m, optimization/fminbnd.m,\n\toptimization/fminunc.m, optimization/fsolve.m,\n\toptimization/fzero.m, optimization/glpk.m,\n\toptimization/lsqnonneg.m, optimization/optimget.m,\n\toptimization/pqpnonneg.m, optimization/qp.m, optimization/sqp.m,\n\tpath/pathdef.m, path/savepath.m, pkg/pkg.m,\n\tplot/__fltk_ginput__.m, plot/__gnuplot_ginput__.m,\n\tplot/__gnuplot_has_feature__.m, plot/__gnuplot_open_stream__.m,\n\tplot/__gnuplot_print__.m, plot/__go_draw_axes__.m,\n\tplot/__go_draw_figure__.m, plot/__marching_cube__.m,\n\tplot/__next_line_color__.m, plot/__next_line_style__.m,\n\tplot/__plt_get_axis_arg__.m, plot/__print_parse_opts__.m,\n\tplot/area.m, plot/axis.m, plot/bar.m, plot/barh.m, plot/caxis.m,\n\tplot/cla.m, plot/clabel.m, plot/colorbar.m, plot/comet.m,\n\tplot/comet3.m, plot/compass.m, plot/contour.m, plot/contour3.m,\n\tplot/contourc.m, plot/cylinder.m, plot/daspect.m,\n\tplot/diffuse.m, plot/ellipsoid.m, plot/errorbar.m,\n\tplot/ezcontour.m, plot/ezcontourf.m, plot/ezmesh.m,\n\tplot/ezmeshc.m, plot/ezplot.m, plot/ezplot3.m, plot/ezpolar.m,\n\tplot/ezsurf.m, plot/ezsurfc.m, plot/feather.m, plot/findobj.m,\n\tplot/fplot.m, plot/gnuplot_drawnow.m, plot/gtext.m, plot/hist.m,\n\tplot/hold.m, plot/ishghandle.m, plot/isocolors.m,\n\tplot/isonormals.m, plot/isosurface.m, plot/isprop.m,\n\tplot/legend.m, plot/loglog.m, plot/loglogerr.m, plot/meshc.m,\n\tplot/meshz.m, plot/ndgrid.m, plot/orient.m, plot/pareto.m,\n\tplot/patch.m, plot/pbaspect.m, plot/pcolor.m, plot/peaks.m,\n\tplot/pie.m, plot/pie3.m, plot/plot.m, plot/plot3.m,\n\tplot/plotmatrix.m, plot/plotyy.m, plot/polar.m, plot/print.m,\n\tplot/private/__actual_axis_position__.m,\n\tplot/private/__axis_label__.m, plot/private/__bar__.m,\n\tplot/private/__clabel__.m, plot/private/__contour__.m,\n\tplot/private/__errplot__.m, plot/private/__ezplot__.m,\n\tplot/private/__fltk_file_filter__.m,\n\tplot/private/__ghostscript__.m,\n\tplot/private/__gnuplot_has_terminal__.m,\n\tplot/private/__patch__.m, plot/private/__pie__.m,\n\tplot/private/__pltopt__.m, plot/private/__quiver__.m,\n\tplot/private/__scatter__.m, plot/private/__stem__.m,\n\tplot/private/__tight_eps_bbox__.m, plot/quiver.m,\n\tplot/quiver3.m, plot/refreshdata.m, plot/rose.m, plot/saveas.m,\n\tplot/scatter.m, plot/scatter3.m, plot/semilogx.m,\n\tplot/semilogxerr.m, plot/semilogy.m, plot/semilogyerr.m,\n\tplot/shading.m, plot/slice.m, plot/specular.m, plot/sphere.m,\n\tplot/stairs.m, plot/stem.m, plot/stem3.m, plot/subplot.m,\n\tplot/surface.m, plot/surfc.m, plot/surfl.m, plot/surfnorm.m,\n\tplot/uigetdir.m, plot/uigetfile.m, plot/uimenu.m,\n\tplot/uiputfile.m, plot/view.m, plot/waitforbuttonpress.m,\n\tplot/whitebg.m, plot/xlim.m, plot/ylim.m, plot/zlim.m,\n\tpolynomial/mkpp.m, polynomial/mpoles.m, polynomial/pchip.m,\n\tpolynomial/poly.m, polynomial/polyaffine.m,\n\tpolynomial/polyderiv.m, polynomial/polyfit.m,\n\tpolynomial/polyreduce.m, polynomial/polyval.m,\n\tpolynomial/ppder.m, polynomial/ppint.m, polynomial/ppjumps.m,\n\tpolynomial/ppval.m, polynomial/residue.m, polynomial/roots.m,\n\tpolynomial/spline.m, polynomial/unmkpp.m, set/ismember.m,\n\tset/private/validargs.m, set/setdiff.m, set/setxor.m,\n\tset/union.m, set/unique.m, signal/arma_rnd.m, signal/fftconv.m,\n\tsignal/fftshift.m, signal/filter2.m, signal/freqz.m,\n\tsignal/ifftshift.m, signal/unwrap.m, sparse/bicgstab.m,\n\tsparse/cgs.m, sparse/gplot.m, sparse/pcg.m, sparse/pcr.m,\n\tsparse/spaugment.m, sparse/spdiags.m, sparse/speye.m,\n\tsparse/spfun.m, sparse/sprand.m, sparse/sprandn.m,\n\tsparse/sprandsym.m, sparse/spstats.m, sparse/spy.m,\n\tsparse/svds.m, sparse/treelayout.m, sparse/treeplot.m,\n\tspecfun/bessel.m, specfun/betaln.m, specfun/factor.m,\n\tspecfun/legendre.m, specfun/nchoosek.m, specfun/nthroot.m,\n\tspecfun/primes.m, specfun/reallog.m, specfun/realpow.m,\n\tspecfun/realsqrt.m, special-matrix/hadamard.m,\n\tspecial-matrix/invhilb.m, special-matrix/magic.m,\n\tspecial-matrix/pascal.m, special-matrix/toeplitz.m,\n\tstartup/__finish__.m, statistics/base/cov.m,\n\tstatistics/base/histc.m, statistics/base/iqr.m,\n\tstatistics/base/kendall.m, statistics/base/kurtosis.m,\n\tstatistics/base/mean.m, statistics/base/meansq.m,\n\tstatistics/base/median.m, statistics/base/mode.m,\n\tstatistics/base/moment.m, statistics/base/ols.m,\n\tstatistics/base/prctile.m, statistics/base/qqplot.m,\n\tstatistics/base/quantile.m, statistics/base/ranks.m,\n\tstatistics/base/run_count.m, statistics/base/skewness.m,\n\tstatistics/base/statistics.m, statistics/base/std.m,\n\tstatistics/base/studentize.m, statistics/base/var.m,\n\tstatistics/distributions/betainv.m,\n\tstatistics/distributions/betapdf.m,\n\tstatistics/distributions/betarnd.m,\n\tstatistics/distributions/binoinv.m,\n\tstatistics/distributions/binornd.m,\n\tstatistics/distributions/cauchy_cdf.m,\n\tstatistics/distributions/cauchy_inv.m,\n\tstatistics/distributions/cauchy_pdf.m,\n\tstatistics/distributions/cauchy_rnd.m,\n\tstatistics/distributions/chi2rnd.m,\n\tstatistics/distributions/discrete_rnd.m,\n\tstatistics/distributions/exprnd.m,\n\tstatistics/distributions/fcdf.m,\n\tstatistics/distributions/frnd.m,\n\tstatistics/distributions/gamrnd.m,\n\tstatistics/distributions/lognrnd.m,\n\tstatistics/distributions/nbincdf.m,\n\tstatistics/distributions/nbininv.m,\n\tstatistics/distributions/nbinpdf.m,\n\tstatistics/distributions/nbinrnd.m,\n\tstatistics/distributions/normrnd.m,\n\tstatistics/distributions/poissrnd.m,\n\tstatistics/distributions/stdnormal_rnd.m,\n\tstatistics/distributions/tpdf.m,\n\tstatistics/distributions/trnd.m,\n\tstatistics/distributions/unifcdf.m,\n\tstatistics/distributions/unifrnd.m,\n\tstatistics/distributions/wblrnd.m,\n\tstatistics/tests/bartlett_test.m,\n\tstatistics/tests/kolmogorov_smirnov_test_2.m,\n\tstatistics/tests/kruskal_wallis_test.m,\n\tstatistics/tests/t_test_regression.m, strings/blanks.m,\n\tstrings/dec2base.m, strings/dec2hex.m, strings/findstr.m,\n\tstrings/index.m, strings/isstrprop.m, strings/mat2str.m,\n\tstrings/regexptranslate.m, strings/str2num.m, strings/strchr.m,\n\tstrings/strjust.m, strings/strmatch.m, strings/strsplit.m,\n\tstrings/strtok.m, strings/untabify.m, testfun/assert.m,\n\ttestfun/demo.m, testfun/example.m, testfun/fail.m,\n\ttestfun/speed.m, testfun/test.m, time/datenum.m, time/datestr.m,\n\ttime/datetick.m, time/datevec.m, time/etime.m:\n\tStrip trailing whitespace.\n\n\t* statistics/distributions/betapdf.m: Untabify.\n\n2011-01-20  Petr Mikulik  <mikulik@physics.muni.cz>\n\n\t* plot/uigetdir.m: Use correct variable name for argument check.\n\tRemove unneeded white spaces.\n\t* plot/uigetfile.m, plot/uiputfile.m: Remove unneeded white spaces.\n\tBug #32190.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* plot/ginput.m, plot/gnuplot_drawnow.m, plot/uiputfile.m,\n\tplot/subplot.m, plot/axis.m, plot/colorbar.m,\n\tplot/__print_parse_opts__.m, plot/uigetdir.m,\n\tplot/__fltk_print__.m, plot/print.m, plot/__gnuplot_print__.m,\n\tplot/uigetfile.m, plot/private/__actual_axis_position__.m:\n\tUpdate for backend -> graphics_toolkit change.\n\n\t* plot/graphics_toolkit.m: Rename from backend.m.\n\t* plot/module.mk (plot_FCN_FILES): Update list.\n\n2011-01-19  Rik  <octave@nomad.inbox5.com>\n\n\t* general/curl.m, general/divergence.m, io/strread.m,\n\tmiscellaneous/mkoctfile.m, plot/bar.m, plot/errorbar.m, plot/hist.m,\n\tplot/mesh.m, plot/surf.m, polynomial/polyaffine.m: Correct spelling\n\tin docstrings.\n\n2011-01-19  John W. Eaton  <jwe@octave.org>\n\n\t* help/help.m: New option --list.  Bug #31905.\n\n2011-01-19  John W. Eaton  <jwe@octave.org>\n\n\t* io/strread.m: Avoid PCRE-ism in regexp.  Bug #32066.\n\n2011-01-17  Rik  <octave@nomad.inbox5.com>\n\n\t* audio/wavread.m, deprecated/spqr.m, elfun/lcm.m, general/bitget.m,\n\tgeneral/curl.m, general/divergence.m, general/interp3.m,\n\tgeneral/quadv.m, geometry/delaunayn.m, geometry/griddata.m,\n\thelp/help.m, io/textread.m, io/textscan.m, linear-algebra/cond.m,\n\tmiscellaneous/mkoctfile.m, miscellaneous/orderfields.m,\n\tmiscellaneous/run.m, miscellaneous/setappdata.m, plot/axis.m,\n\tplot/caxis.m, plot/daspect.m, plot/ellipsoid.m, plot/errorbar.m,\n\tplot/gnuplot_binary.in, plot/hist.m, plot/hold.m, plot/ishold.m,\n\tplot/legend.m, plot/mesh.m, plot/pbaspect.m, plot/pie3.m, plot/print.m,\n\tplot/private/__add_default_menu__.m, plot/scatter.m, plot/scatter3.m,\n\tplot/shg.m, plot/slice.m, plot/surf.m, plot/surfl.m, plot/uigetdir.m,\n\tplot/uigetfile.m, plot/uimenu.m, plot/uiputfile.m, plot/view.m,\n\tset/unique.m, signal/periodogram.m, sparse/pcg.m, sparse/pcr.m,\n\tsparse/spfun.m, specfun/legendre.m,\n\tstatistics/distributions/poisspdf.m, statistics/distributions/wblpdf.m,\n\tstrings/strjust.m, strings/untabify.m, testfun/assert.m,\n\ttestfun/demo.m, testfun/example.m, testfun/fail.m, testfun/test.m:\n\tGrammarcheck m-files for 3.4 release.\n\n2011-01-17  Rik  <octave@nomad.inbox5.com>\n\n\t* general/dblquad.m, general/quadgk.m, general/quadl.m,\n\tgeneral/quadv.m, general/triplequad.m: Improve docstring with seealso\n\tlinks to quadcc.\n\n2011-01-17  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/isdeployed.m: New function.\n\t* miscellaneous/module.mk (miscellaneous_FCN_FILES): Add it to\n\tthe list.  Bug #32151.\n\n2011-01-17  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/inputname.m: Use __varval__ to lookup \".argn.\"\n\tinstead of \"argn\".\n\n2011-01-16  Ben Abbott <bpabbott@mac.com>\n\n\t* plot/print.m: For DOS, connect the pipe to ghostscript (bug 31967),\n\tand redirect to NUL instead of /dev/null.\n\n2011-01-16  John W. Eaton  <jwe@octave.org>\n\n\t* gethelp.cc (main): Write function name along with file name in\n\tcomment.\n\n2011-01-16  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Use \"{}\" as the default font.\n\n2011-01-15  Rik  <octave@nomad.inbox5.com>\n\n\t* scripts/help/doc.m, scripts/help/which.m,\n\tscripts/miscellaneous/comma.m, scripts/miscellaneous/ls.m,\n\tscripts/miscellaneous/paren.m, scripts/miscellaneous/semicolon.m,\n\tscripts/pkg/pkg.m: Eliminate @deffn macros.\n\n2011-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/krylovb: Move here from linear-algebra.\n\t* deprecated/module.mk (deprecated_FCN_FILES):\n\tInclude krylovb.m in the list.\n\t* linear-algebra/module.mk (linear_algebra_FCN_FILES):\n\tRemove krylovb.m from the list.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* general/postpad.m, general/prepad.m: Improve docstring.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* ploynomial/polyaffine.m: Improve docstring.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* general/interp1.m, general/interp2.m, polynomial/mkpp.m,\n\tpolynomial/pchip.m, polynomial/ppder.m, polynomial/ppint.m,\n\tpolynomial/ppjumps.m, polynomial/ppval.m, polynomial/spline.m,\n\tpolynomial/unmkpp.m: Improve docstrings\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/flops.m: Delete function which was unimplemented\n\tin Octave and has been removed from Matlab since version 5.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* specfun/nthroot.m: Add Seealso references to docstring.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/module.mk: Remove texas_lotto.m from build system.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/texas_lotto.m: Remove Easter Egg function.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* Update copyright notices for 2011.\n\n2011-01-13  Michael Godfrey  <godfrey@isl.stanford.edu>\n\n\t* plot/contourc.m: Correct one argument case.\n\n2011-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* strings/mat2str.m: Handle logical arguments.  New tests.\n\tBug #32102.\n\n2011-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* linear-algebra/expm.m: Validate nargin.  New tests.\n\n2011-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* linear-algebra/logm.m: Handle scalar and diagonal matrix\n\targuments specially.  Call logm_pade_pf only if m > 1.  New tests.\n\tSpecial case suggested by Marco Caliari <marco.caliari@univr.it>.\n\n2011-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* general/private/__isequal__.m: Use builtin (\"struct\", ...) to\n\tconvert objects to a structs to avoid possible overloading of\n\tthe struct function.  Bug #32071.\n\n2011-01-09  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/orient.m, statistics/tests/kolmogorov_smirnov_test.m,\n\tstrings/strtrunc.m: Correct failing tests due to change in\n\tcapitalization of error strings from previous changeset.\n\n2011-01-09  Rik  <octave@nomad.inbox5.com>\n\n\t* audio/lin2mu.m, audio/loadaudio.m, audio/mu2lin.m, audio/saveaudio.m,\n\taudio/wavwrite.m, deprecated/split.m, deprecated/values.m,\n\tgeneral/accumarray.m, general/bitcmp.m, general/cell2mat.m,\n\tgeneral/circshift.m, general/curl.m, general/divergence.m,\n\tgeneral/genvarname.m, general/interpft.m, general/interpn.m,\n\tgeneral/nextpow2.m, general/polyarea.m, general/repmat.m,\n\tgeneral/rot90.m, general/rotdim.m, general/shiftdim.m,\n\tgeneral/strerror.m, general/trapz.m, geometry/griddata.m,\n\tgeometry/griddata3.m, geometry/griddatan.m, geometry/rectint.m,\n\timage/brighten.m, image/colormap.m, image/contrast.m, image/imagesc.m,\n\timage/imfinfo.m, image/imread.m, linear-algebra/commutation_matrix.m,\n\tlinear-algebra/condest.m, linear-algebra/cross.m,\n\tlinear-algebra/duplication_matrix.m, linear-algebra/isdefinite.m,\n\tlinear-algebra/vech.m, miscellaneous/bincoeff.m, miscellaneous/cast.m,\n\tmiscellaneous/compare_versions.m, miscellaneous/fileparts.m,\n\tmiscellaneous/license.m, miscellaneous/private/__xzip__.m,\n\tmiscellaneous/substruct.m, miscellaneous/unpack.m, miscellaneous/xor.m,\n\toptimization/sqp.m, pkg/get_forge_pkg.m, plot/backend.m,\n\tplot/contourc.m, plot/cylinder.m, plot/hidden.m, plot/hold.m,\n\tplot/orient.m, plot/private/__interp_cube__.m, plot/refreshdata.m,\n\tplot/subplot.m, plot/surface.m, plot/surfnorm.m, plot/text.m,\n\tplot/uimenu.m, polynomial/mkpp.m, polynomial/pchip.m,\n\tpolynomial/polyfit.m, polynomial/ppval.m, signal/arch_fit.m,\n\tsignal/arch_rnd.m, signal/arch_test.m, signal/arma_rnd.m,\n\tsignal/autoreg_matrix.m, signal/bartlett.m, signal/blackman.m,\n\tsignal/diffpara.m, signal/durbinlevinson.m, signal/fftfilt.m,\n\tsignal/fractdiff.m, signal/hamming.m, signal/hanning.m, signal/hurst.m,\n\tsignal/sinetone.m, signal/synthesis.m, signal/unwrap.m,\n\tsparse/spaugment.m, specfun/factor.m, specfun/factorial.m,\n\tspecfun/legendre.m, specfun/nthroot.m, specfun/primes.m,\n\tspecial-matrix/hadamard.m, special-matrix/magic.m,\n\tstatistics/distributions/betacdf.m, statistics/distributions/betainv.m,\n\tstatistics/distributions/betapdf.m, statistics/distributions/betarnd.m,\n\tstatistics/distributions/binocdf.m, statistics/distributions/binoinv.m,\n\tstatistics/distributions/binopdf.m, statistics/distributions/binornd.m,\n\tstatistics/distributions/cauchy_cdf.m,\n\tstatistics/distributions/cauchy_inv.m,\n\tstatistics/distributions/cauchy_pdf.m,\n\tstatistics/distributions/cauchy_rnd.m,\n\tstatistics/distributions/chi2cdf.m, statistics/distributions/chi2inv.m,\n\tstatistics/distributions/chi2pdf.m, statistics/distributions/chi2rnd.m,\n\tstatistics/distributions/discrete_cdf.m,\n\tstatistics/distributions/discrete_inv.m,\n\tstatistics/distributions/discrete_pdf.m,\n\tstatistics/distributions/discrete_rnd.m,\n\tstatistics/distributions/empirical_cdf.m,\n\tstatistics/distributions/empirical_inv.m,\n\tstatistics/distributions/empirical_pdf.m,\n\tstatistics/distributions/empirical_rnd.m,\n\tstatistics/distributions/expcdf.m, statistics/distributions/expinv.m,\n\tstatistics/distributions/exppdf.m, statistics/distributions/exprnd.m,\n\tstatistics/distributions/fcdf.m, statistics/distributions/finv.m,\n\tstatistics/distributions/fpdf.m, statistics/distributions/frnd.m,\n\tstatistics/distributions/gamcdf.m, statistics/distributions/gaminv.m,\n\tstatistics/distributions/gampdf.m, statistics/distributions/gamrnd.m,\n\tstatistics/distributions/geocdf.m, statistics/distributions/geoinv.m,\n\tstatistics/distributions/geopdf.m, statistics/distributions/geornd.m,\n\tstatistics/distributions/hygecdf.m, statistics/distributions/hygeinv.m,\n\tstatistics/distributions/hygepdf.m, statistics/distributions/hygernd.m,\n\tstatistics/distributions/kolmogorov_smirnov_cdf.m,\n\tstatistics/distributions/laplace_rnd.m,\n\tstatistics/distributions/logistic_rnd.m,\n\tstatistics/distributions/logncdf.m, statistics/distributions/logninv.m,\n\tstatistics/distributions/lognpdf.m, statistics/distributions/lognrnd.m,\n\tstatistics/distributions/nbincdf.m, statistics/distributions/nbininv.m,\n\tstatistics/distributions/nbinpdf.m, statistics/distributions/nbinrnd.m,\n\tstatistics/distributions/normcdf.m, statistics/distributions/norminv.m,\n\tstatistics/distributions/normpdf.m, statistics/distributions/normrnd.m,\n\tstatistics/distributions/poisscdf.m,\n\tstatistics/distributions/poissinv.m,\n\tstatistics/distributions/poisspdf.m,\n\tstatistics/distributions/poissrnd.m,\n\tstatistics/distributions/stdnormal_cdf.m,\n\tstatistics/distributions/stdnormal_rnd.m,\n\tstatistics/distributions/tcdf.m, statistics/distributions/tinv.m,\n\tstatistics/distributions/tpdf.m, statistics/distributions/trnd.m,\n\tstatistics/distributions/unidrnd.m, statistics/distributions/unifcdf.m,\n\tstatistics/distributions/unifinv.m, statistics/distributions/unifpdf.m,\n\tstatistics/distributions/unifrnd.m, statistics/distributions/wblcdf.m,\n\tstatistics/distributions/wblinv.m, statistics/distributions/wblpdf.m,\n\tstatistics/distributions/wblrnd.m, statistics/distributions/wienrnd.m,\n\tstatistics/models/logistic_regression.m, statistics/tests/anova.m,\n\tstatistics/tests/chisquare_test_homogeneity.m,\n\tstatistics/tests/cor_test.m, statistics/tests/f_test_regression.m,\n\tstatistics/tests/hotelling_test.m, statistics/tests/hotelling_test_2.m,\n\tstatistics/tests/kolmogorov_smirnov_test.m,\n\tstatistics/tests/kolmogorov_smirnov_test_2.m,\n\tstatistics/tests/manova.m, statistics/tests/mcnemar_test.m,\n\tstatistics/tests/prop_test_2.m, statistics/tests/sign_test.m,\n\tstatistics/tests/t_test.m, statistics/tests/t_test_2.m,\n\tstatistics/tests/t_test_regression.m, statistics/tests/u_test.m,\n\tstatistics/tests/var_test.m, statistics/tests/welch_test.m,\n\tstatistics/tests/wilcoxon_test.m, statistics/tests/z_test.m,\n\tstatistics/tests/z_test_2.m, strings/blanks.m, strings/index.m,\n\tstrings/strtrunc.m, strings/validatestring.m, time/addtodate.m,\n\ttime/datenum.m, time/datetick.m, time/datevec.m: Use uppercase for\n\tvariable names in error() strings to match Info documentation.\n\n\t* general/interp2.m, image/imshow.m, image/ind2rgb.m,\n\timage/saveimage.m, io/dlmwrite.m, io/strread.m, io/textscan.m,\n\tlinear-algebra/expm.m, linear-algebra/krylov.m, linear-algebra/logm.m,\n\tmiscellaneous/delete.m, miscellaneous/run.m, plot/__marching_cube__.m,\n\tsparse/bicgstab.m, sparse/cgs.m, strings/strmatch.m,\n\ttestfun/rundemos.m, testfun/runtests.m: Rewrite error string\n\n\t* @ftp/ftp.m, help/gen_doc_cache.m, miscellaneous/unix.m,\n\tplot/__gnuplot_open_stream__.m, plot/private/__add_default_menu__.m,\n\tpolynomial/ppder.m, polynomial/ppint.m, polynomial/ppjumps.m,\n\tsignal/periodogram.m: Correct use of @deftypefn macro\n\n\t* miscellaneous/paren.m: Space @deffnx macro for readability\n\n2011-01-09  Rik  <octave@nomad.inbox5.com>\n\n\t* general/arrayfun.m, general/blkdiag.m, general/structfun.m,\n\timage/imagesc.m, linear-algebra/cond.m, linear-algebra/condest.m,\n\tlinear-algebra/expm.m, linear-algebra/logm.m,\n\tlinear-algebra/onenormest.m, linear-algebra/qzhess.m,\n\toptimization/glpk.m, optimization/glpkmex.m, polynomial/poly.m,\n\tsparse/gplot.m, sparse/pcg.m, sparse/pcr.m, sparse/spaugment.m,\n\tsparse/spdiags.m, sparse/svds.m: Use uppercase 'A' to refer to matrix\n\targument.\n\n\t* io/dlmwrite.m: Use uppercase 'M' to refer to matrix argument.\n\n\t* io/textscan.m: Use uppercase 'C' to refer to Cell Array output.\n\tImprove docstring.\n\n\t* signal/unwrap.m: Use 'x' instead of 'a' for vector input argument.\n\n2011-01-09  Rik  <octave@nomad.inbox5.com>\n\n\t* general/bicubic.m, general/nargchk.m, general/nargoutchk.m,\n\tlinear-algebra/krylov.m, linear-algebra/krylovb.m,\n\tlinear-algebra/normest.m, linear-algebra/null.m, linear-algebra/orth.m,\n\tlinear-algebra/rank.m: Use common names for variables in documentation\n\tand code.\n\n2011-01-09  Rik  <octave@nomad.inbox5.com>\n\n\t* audio/loadaudio.m, audio/mu2lin.m, audio/saveaudio.m,\n\tgeneral/accumdim.m, general/bitget.m, general/bitset.m, general/del2.m,\n\tgeneral/isequal.m, general/isequalwithequalnans.m, general/logspace.m,\n\tgeneral/repmat.m, general/strerror.m, general/structfun.m,\n\tgeometry/delaunayn.m, geometry/dsearchn.m, image/ind2gray.m,\n\timage/ind2rgb.m, image/rgb2ind.m, io/csvread.m, io/csvwrite.m,\n\tlinear-algebra/rref.m, linear-algebra/subspace.m,\n\tlinear-algebra/trace.m, miscellaneous/dir.m, miscellaneous/dos.m,\n\tmiscellaneous/menu.m, miscellaneous/perl.m, miscellaneous/unix.m,\n\tpath/savepath.m, plot/allchild.m, plot/diffuse.m, plot/fplot.m,\n\tplot/refreshdata.m, plot/specular.m, plot/subplot.m,\n\tpolynomial/polyreduce.m, set/ismember.m, signal/arch_fit.m,\n\tsignal/arch_rnd.m, signal/arch_test.m, signal/diffpara.m,\n\tsignal/fftfilt.m, signal/filter2.m, signal/sinetone.m,\n\tsignal/spectral_xdf.m, signal/stft.m, signal/synthesis.m,\n\tsparse/spfun.m, sparse/spones.m, sparse/spstats.m, sparse/treelayout.m,\n\tsparse/treeplot.m, specfun/isprime.m,\n\tstatistics/distributions/expcdf.m, statistics/distributions/expinv.m,\n\tstatistics/distributions/exppdf.m, statistics/distributions/exprnd.m,\n\tstatistics/distributions/poisscdf.m,\n\tstatistics/distributions/poissinv.m,\n\tstatistics/distributions/poisspdf.m,\n\tstatistics/distributions/poissrnd.m,\n\tstatistics/tests/chisquare_test_independence.m,\n\tstatistics/tests/cor_test.m, statistics/tests/f_test_regression.m,\n\tstatistics/tests/t_test_regression.m, strings/base2dec.m,\n\tstrings/dec2base.m, strings/regexptranslate.m, strings/strjust.m,\n\tstrings/strmatch.m, time/asctime.m, time/datenum.m:\n\tUse common names for variables in documentation and code.\n\n\t* @ftp/ascii.m, @ftp/binary.m, @ftp/cd.m, @ftp/close.m, @ftp/delete.m,\n\t@ftp/dir.m, @ftp/ftp.m, @ftp/mget.m, @ftp/mkdir.m, @ftp/mput.m,\n\t@ftp/rename.m, @ftp/rmdir.m, general/chop.m, geometry/dsearch.m,\n\tsignal/spencer.m, specfun/primes.m, time/etime.m: Use common names for\n\tvariables in documentation and code.  Improve docstring\n\n\t* elfun/acot.m, elfun/acoth.m, elfun/acsc.m, elfun/acsch.m,\n\telfun/asec.m, elfun/asech.m, elfun/cot.m, elfun/coth.m, elfun/csc.m,\n\telfun/csch.m, elfun/sec.m, elfun/sech.m: Use common names for variables\n\tin documentation and code.  Change output variable to 'y' rather than\n\t'w'.\n\n\t* miscellaneous/bunzip2.m, miscellaneous/gunzip.m,\n\tmiscellaneous/unpack.m, miscellaneous/untar.m, miscellaneous/unzip.m:\n\tUse common names for variables in documentation and code.  Use default\n\ton input argument to simplify input validation.\n\n\t* general/accumarray.m: Use common names for variables in\n\tdocumentation, code and tests.\n\n\t* geometry/inpolygon.m: Use common names for variables in\n\tdocumentation, code and tests.  Improve docstring.\n\n\t* general/bitcmp.m: Use common names for variables in documentation and\n\tcode.  Switch tests to %!test blocks rather than %!shared variables and\n\t%!asserts for clarity.\n\n\t* general/int2str.m: Switch to input variable name 'n' rather than 'x'.\n\n\t* general/isdir.m: Switch to input variable name 'f' rather than 'x'.\n\tSwitch output variable to 'retval' rather than 'y'.\n\n\t* general/perror.m: Switch to input variable name 'funcname' rather\n\tthan 'name'.  Use common names for variables in documentation and\n\tcode.\n\n\t* general/rot90.m: Switch to input variable name 'A' rather than 'x'.\n\tBreak very long %!assert line into multiple asserts for readability.\n\n\t* general/sortrows.m: Use common names for variables in documentation\n\tand code.  Break very long %!assert line into multiple asserts for\n\treadability.\n\n\t* geometry/voronoin.m: Switch to input variable name 'options' rather\n\tthan 'opt'.\n\n\t* help/lookfor.m: Switch to input variable name 'arg2' rather than\n\t'extra'.\n\n\t* image/brighten.m: Switch to input variable name 'arg1' rather than\n\t'm'.  Eliminate CamelCase in output variable 'Rmap'.\n\n\t* image/rgb2hsv.m: Switch to variable name 'hsv_map' rather than\n\t'hsval'.\n\n\t* image/saveimage.m: Switch to input variable name 'fname', rather than\n\t'file'.  Use common names for variables in documentation and code.\n\n\t* io/strread.m, io/textread.m, io/textscan.m: Switch to input variable\n\tname 'format' rather than 'formatstr'\n\n\t* miscellaneous/run.m: Switch to input variable 'script' rather than\n\t's'.\n\n\t* miscellaneous/ver.m: Switch to input variable 'package' rather than\n\t'pack'.  Use default on input argument to simplify input validation.\n\n\t* plot/saveas.m: Switch to input variable 'fmt' rather than 'ext'.\n\tImprove docstring.\n\n\t* plot/title.m: : Switch to input variable 'string' rather than 'title'.\n\n\t* plot/uigetdir.m: Improve docstring.  Re-order input validation.\n\tEliminate unnecessary use of cellfun to compare strings.\n\n\t* polynomial/polyder.m, polynomial/polyderiv.m: Switch ouput variable\n\tname 'r' to 'd'.  Improve docstring.\n\n\t* polynomial/polyint.m: Switch input variable name 'c' to 'p'.\n\n\t* signal/fftconv.m: Switch input variable names to 'x','y' instead of\n\t'a','b' for vectors.\n\n\t* signal/fftshift.m, signal/ifftshift.m: Switch input variable name to\n\t'x' instead of 'v'.\n\n\t* sparse/etreeplot.m: Switch input variable name to 'A' rather than\n\t'tree' for matrix.\n\n\t* specfun/factor.m: Use common names for variables in documentation and\n\tcode.  Uncomment and re-instate test code.\n\n\t* statistics/distributions/cauchy_cdf.m,\n\tstatistics/distributions/cauchy_inv.m,\n\tstatistics/distributions/cauchy_pdf.m,\n\tstatistics/distributions/cauchy_rnd.m: Switch to input variables\n\t'location','scale' rather than 'lambda','sigma'.\n\n\t* statistics/tests/manova.m: Switch to input variable 'x' rather than\n\t'y'.\n\n\t* strings/untabify.m: Switch to input variable 'dblank' rather than\n\t'db'.\n\n\t* time/datestr.m: Improve docstring\n\n\t* time/weekday.m: Switch to input variable name 'format' rather than\n\t'form'.  Improve docstring.\n\n2011-01-08  John Hunt  <huntj@gawab.com>\n\n\t* plot/legend.m, plot/private/__plt__.m: legend with more than two\n\tinline keys (bug 31991). Add/modifyy demos.\n\n2011-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* general/private/__isequal__.m: Compare objects as if they are\n\tstructures.  Bug #32071.\n\n2011-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* linear-algebra/logm.m: Style fixes.\n\n2011-01-06  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/optimset.m: Remove \"i\" option from call to\n\tlookup.  Bug #31392.\n\n2011-01-05  Rik  <octave@nomad.inbox5.com>\n\n\t* general/isa.m: Add tests against logical values.\n\n2011-01-04  Rik  <octave@nomad.inbox5.com>\n\n\t* testfun/demo.m: Add newline to error output for better formatting.\n\n2011-01-03  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/base/center.m, statistics/base/corrcoef.m,\n\tstatistics/base/kendall.m, statistics/base/mean.m,\n\tstatistics/base/meansq.m, statistics/base/skewness.m,\n\tstatistics/base/studentize.m, statistics/base/var.m,\n\tstatistics/base/run_count.m, statistics/base/ranks.m: Improve input\n\tvalidation.  Add function tests.  Improve docstring.\n\n\t* statistics/base/moment.m, statistics/base/prctile.m,\n\tstatistics/base/spearman.m, statistics/base/std.m : Improve input\n\tvalidation.  Add input validation tests.  Improve docstring.\n\n\t* statistics/base/cloglog.m: Add function tests.\n\n\t* statistics/base/cor.m: Replace with call to corrcoef, now only an\n\talias.\n\n\t* statistics/base/cov.m: Add normalization option.  Improve input\n\tvalidation.  Add function tests.  Improve docstring.\n\n\t* statistics/base/cut.m: Use lowercase variable names.  Improve\n\tdocstring.\n\n\t* statistics/base/histc.m, statistics/base/median.m: Use same variable\n\tname in documentation and in function.  Add input validation tests.\n\tImprove docstring.\n\n\t* statistics/base/iqr.m, statistics/base/mode.m: Add input validation\n\ttests.  Improve docstring.\n\n\t* statistics/base/kurtosis.m: Return same class as input variable.  Add\n\tinput validation tests.  Improve docstring.\n\n\n\t* statistics/base/logit.m, statistics/base/range.m: Add function tests.\n\tImprove docstring.\n\n\t* statistics/base/mahalanobis.m: Use lower case variable names.\n\tImprove input validation.  Add input validation tests.\n\n\t* statistics/base/ols.m, statistics/base/gls.m: Use isargout to only\n\tcalculate necessary outputs.  Use lowercase variable names.  Add\n\tfunctional tests.  Improve docstring.\n\n\t* statistics/base/ppplot.m: Add input validation tests.\n\n\t* statistics/base/qqplot.m: Add ability to call \"XXXinv\" or \"XXX_inv\"\n\tfunctions.  Improve input validation.  Improve docstring.\n\n\t* statistics/base/quantile.m: Use defaults for input arguments to\n\tsimplify code.  Improve input validation.  Add input validation tests.\n\tImprove docstring.\n\n\t* statistics/base/statistics.m: Use lowercase variable names.  Improve\n\tinput validation.  Add input validation tests.  Improve docstring.\n\n\t* statistics/base/table.m: Switch from deprecated function 'values' to\n\t'unique'.  Add input validation tests.  Improve docstring.\n\n2011-01-02  Ben Abbott <bpabbott@mac.com>\n\n\t* plot/legend.m: Only one legend per axes (bug 32022). Add / modify\n\tdemos to test addional features.\n\n2010-12-31  Rik  <octave@nomad.inbox5.com>\n\n\t* general/is_duplicate_entry.m , general/isdir.m, general/isscalar.m,\n\tgeneral/issquare.m, general/isvector.m, linear-algebra/isdefinite.m,\n\tlinear-algebra/ishermitian.m, linear-algebra/issymmetric.m,\n\tmiscellaneous/isappdata.m, miscellaneous/ismac.m, miscellaneous/ispc.m,\n\tmiscellaneous/isunix.m, plot/isfigure.m, plot/ishold.m, plot/isprop.m,\n\tset/ismember.m, specfun/isprime.m, strings/isletter.m,\n\ttime/is_leap_year.m : Improve docstring\n\t* general/isa.m: Improve docstring.  Change function variable name to\n\tmatch documentation variable name.\n\t* strings/isstrprop.m: Improve docstring.  Change function variable\n\tname to match documentation variable name.  Add new test cases.\n\n2010-12-31  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/module.mk: Add isprop.m to list of function files for Automake.\n\n2010-12-31  Kai Habel  <kai.habel@gmx.de>\n\n\t* general/curl.m, general/divergence.m: New functions.\n\t* general/module.mk: Add new file to list.\n\t* miscellaneous/unimplemented.m: Remove curl and divergence from list.\n\n2010-12-31  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/scatter3.m: Grid on by default for 3D plots.\n\n2010-12-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/contour3.m, plot/mesh.m, plot/meshc.m, plot/surfc.m: Grid on\n\tby default for 3D plots.\n\t* plot/surfc.m, plot/meshc.m: Place contour for meshc/surfc at\n\tzlim(1).\n\t* plot/__go_draw_axes__.m: Tweak vertical alignment of text objects\n\tfor gnuplot to favor eps/ps output.\n\n2010-12-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/text.m: New demo for 3D plot and text with verticalalignment.\n\t* plot/__go_draw_axes__.m: Enable vertical alignment of text objects\n\tfor gnuplot.\n\n2010-12-28  Ben Abbott <bpabbott@mac.com>\n\n\t* plot/private/__plt__.m: Fix to allow inline legend keys. Bug 31991.\n\n2010-12-28  Rik  <octave@nomad.inbox5.com>\n\n\t* image/autumn.m, image/bone.m, image/cool.m, image/copper.m,\n\timage/flag.m, image/gray.m, image/hot.m, image/hsv.m, image/jet.m,\n\timage/ocean.m, image/pink.m, image/prism.m, image/rainbow.m,\n\timage/spring.m, image/summer.m, image/white.m, image/winter.m: Use\n\tsame variable name for documentation and function call.  Change demo\n\tcode to explicitly use colormap size.  Update docstring.\n\n\t* image/gmap40.m: Use same variable name for documentation and function\n\tcall.  Change demo code to use colormap size of 6 rather than 64.\n\tUpdate docstring.\n\n2010-12-28  Ben Abbott <bpabbott@mac.com>\n\n\t* plot/legend.m: Add demo to legend for inline key.\n\n2010-12-27  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/text.m: Add demo for text rotation and alignment.\n\n2010-12-26  Michael Godfrey <godfrey@isl.stanford.edu>\n\n\t* specfun/legendre.m: Add @tex blocks to docstring.\n\n2010-12-24  Rik  <octave@nomad.inbox5.com>\n\n\t* testfun/test.m: Use 'Command' for deftype in docstring.\n\n2010-12-24  Rik  <octave@nomad.inbox5.com>\n\n\t* audio/setaudio.m: Re-write docstring.\n\n2010-12-23  Søren Hauberg  <hauberg@gmail.com>\n\n\t* signal/detrend.m: Also accept polynomial order as a string\n\t(\"constant\" or \"linear\") for compatibility with Matlab.\n\n2010-12-22  Konstantinos Poulios  <logari81@gmail.com>\n\n\t* plot/private/__axis_label__.m: Trigger fltk graphics redraw\n\timmediately after setting an axis label.\n\n2010-12-22  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/optimset.m, optimization/optimget.m,\n\toptimization/__all_opts__.m: Consistently use lower case for\n\tstoring and searching option names.\n\n2010-12-22  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/base/skewness.m: Make returned value have the same\n\tclass as the input.\n\n2010-12-21  John W. Eaton  <jwe@octave.org>\n\n\t* time/datevec.m: Style fixes.\n\n2010-12-20  Ben Abbott <bpabbott@mac.com>\n\n\t* plot/__fltk_print__.m: Update figure for FLTK printing.  Bug #31884.\n\n2010-12-19  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/run.m: Use source to execute script.\n\n2010-12-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/view.m: Return azimuth and elevation for nargin == 0.\n\n2010-10-28  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/module.mk, sparse/module.mk, deprecated/sphcat.m,\n\tdeprecated/spvcat.m: Deprecate sphcat and spvcat functions.\n\n2010-12-17  John W. Eaton  <jwe@octave.org>\n\n\t* plot/comet3.m: New function.\n\t* plot/module.mk: Add comet3.m to the list\n\t* miscellaneous/unimplemented.m: Remove comet3 from the list.\n\n2010-12-17  John W. Eaton  <jwe@octave.org>\n\n\t* plot/comet.m: Use __plt_get_axis_arg__ to extract axis\n\targument.  Only switch to specified axis temporarily.\n\n2010-12-16  Ben Abbott <bpabbott@mac.com>\n\n\t* miscellaneous/unimplemented.m: Remove isprop() from list of\n\tunimplemented functions.\n\t* plot/isprop.m: New function.\n\n2010-12-16  Olaf Till <olaf.till@uni-jena.de>\n\n\t* optimization/sqp.m: Fix indexing error in sqp bounds selection.\n\n2010-12-14  Doug Stewart <doug.dastew@gmail.com>\n\n\t* plot/bar.m: Improve the docstring.\n\n2010-12-14  John W. Eaton  <jwe@octave.org>\n\n\t* plot/private/__quiver__.m: Use high contrast color black for arrows\n\tin quiver3 plots.  Bug #31802.\n\n2010-12-14  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/compass.m, plot/errorbar.m, plot/legend.m, plot/rose.m,\n\tplot/scatter.m, plot/scatter3.m, plot/stairs.m: Assign data used in\n\tdemo plots for reproducibility between runs.\n\n2010-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/median.m: Add NaN test case from bug #29930.\n\n2010-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* general/isequalwithequalnans.m: Add test case from bug #31239.\n\n2010-12-13  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__print_parse_opts__.m: Fix indexing bug for varargin.\n\tBug #31862.\n\n2010-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/distributions/betapdf.m: Add test for large values of\n\talpha and beta.\n\n2010-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* strings/strmatch.m: Add test with null search pattern.\n\n2010-12-13 Doug Stewart  <doug.dastew@gmail.com>\n\n\t* plot/hist.m: Improved the help section.\n\n2010-12-13  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/private/__add_default_menu__.m: New function.\n\t* plot/figure.m: Call __add_default_menu__ function.\n\t* plot/module.mk: Add new file to list.\n\n2010-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/sqp.m: Change docstring to refer to x0 as the initial\n\tseed vector.\n\n2010-12-13  Olaf Till <olaf.till@uni-jena.de>\n\n\t* optimization/sqp.m: Remove never violated Inf bounds from\n\tcomputation in function for inequality constraints (bug\n\t#31742).  Remove non-functional check for inequality constraints\n\tbeing +Inf in each iteration.\n\n2010-12-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/optimget.m: Use explicit toupper conversion rather than\n\tlookup(..., \"i\").\n\t* optimization/optimset.m: Ditto.\n\t* miscellaneous/parseparams.m: Ditto.\n\n2010-12-12  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/view.m: Fix bugs with respect to number if inputs and argument\n\thandling.\n\n2010-12-12  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/view.m: Make view more compatible. Allow cartesian\n\tcoordinates and axes handle arguments.\n\n2010-12-10  Ben Abbott  <bpabbott@mac.com>\n\n\t* io/strread.m: Don't require space between format specifiers.\n\n2010-12-10  Rik  <octave@nomad.inbox5.com>\n\n\t* testfun/speed.m: Eliminate line continuation in function definition.\n\n2010-12-10  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/private/__pie__.m: Add missing slice option to pie and\n\tpie3 function.\n\t* plot/pie.m, plot/pie3.m: Add new demo.\n\n2010-12-10  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* statistics/tests/kolmogorov_smirnov_test.m: Add tests.\n\n2010-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* plot/private/__pie__.m: Provide diagnositc for invalid\n\toptional arguments.  Use caller name instead of __pie__ in error\n\tmessages.\n\n2010-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/tests/kolmogorov_smirnov_test.m: Try both DIST_cdf\n\tand DISTcdf functions.  Always use feval to call CDF function.\n\tBug #31838.\n\n2010-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Set major and grid linewidths from\n\taxis linewidth property.  Bug #31755.\n\n2010-12-09  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/__print_parse_opts__.m: Convert print resolution from char to\n\tdouble.  Fixes Bug #31834.\n\n2010-12-09  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/private/__pie__.m: Allow logical indices for 'explode' variable.\n\n2010-12-09  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/pie3.m, plot/private/__pie__.m: New functions.\n\t* plot/pie.m: Move __pie__ function to plot/private, in order to\n\tbe used by pie and pie3.\n\t* miscellaneous/unimplemented.m: Remove pie3.m from list of\n\tunimplemented functions.\n\n2010-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* time/datestr.m: Don't call localtime (mktime (tm)) to fill in\n\tmissing elements of time strcture.  Bug #31079.\n\n2010-12-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/fill.m: Fix bug that implies nextplot = \"add\".\n\t* image/imshow.m: Flip y-axis.\n\n2010-12-08  John W. Eaton  <jwe@octave.org>\n\n\t* strings/strmatch.m: Avoid passing length of zero to strncmp.\n\tBug #31774.\n\n2010-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* general/repmat.m: Handle special case of replicating scalar\n\tusing an index vector containing zeros.  Bug #31775.\n\n2010-12-06  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/plot.m: Eliminate present tense in first sentence of docstring.\n\n2010-12-06  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/xlabel.m, plot/ylabel.m, plot/zlabel.m: Add additional calling\n\tform to docstring which returns handle (h)\n\n2010-12-06  Rik  <octave@nomad.inbox5.com>\n\n\t* scripts/testfun/speed.m: Overhaul documentation string.\n\n2010-12-03  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__stem__.m: Create a baseline for each stem hggroup.\n\t* plot/__go_draw_axes__.m: If not set, then unset the gnuplot\n\t{tblr}margins. Needed when using subplots with differing\n\tactivepositionproperty.\n\n2010-12-03  Konstantinos Poulios <logari81@gmail.com>\n\n\t* plot/pbaspect.m, plot/daspect.m: Fix handling of input array of\n\tlength 2.\n\n2010-12-02  Ben Abbott  <bpabbott@mac.com>\n\n\t* image/image.m: Only flip y-axis if nextplot property equal\n\t\"replace\". Fixes bug 31745.\n\t* plot/contour3.m: Modify demo to avoid clipping mesh. Fixes bug\n\t31744.\n\t* plot/fill.m: Allow multiple filled polygons. Fixes bug 31750.\n\t* plot/subplot.m: Add suppport for \"align\" and \"replace\" options.\n\tPartial fix for bug 31610.\n\n2010-11-26  John W. Eaton  <jwe@octave.org>\n\n\t* pkg/pkg.m: Append directories to EXEC_PATH instead of\n\tprepending them.  Use pathsep instead of \":\".\n\n\t* miscellaneous/copyfile.m, miscellaneous/movefile.m,\n\tmiscellaneous/ls_command.m, plot/__print_parse_opts__.m:\n\tSearch PATH for programs, not EXEC_PATH.\n\n\t* plot/print.m: Refer to PATH, not EXEC_PATH in error messages.\n\t* plot/__print_parse_opts__.m: Likewise.\n\n2010-11-25  Kai Habel  <kai.habel@gmx.de>\n\n\t* (plot/uimenu.m): Simplify code, add further check.\n\t* (plot/uigetdir.m, plot/uigetfile.m, plot/uiputfile.m):\n\tFix error messages.\n\n2010-11-25  John W. Eaton  <jwe@octave.org>\n\n\t* time/datetick.m: Add missing semicolon.\n\n2010-11-21  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/sqp.m: Use correct stopping tolerance in documentation.\n\n2010-11-21  Kai Habel  <kai.habel@gmx.de>\n\n\t* (plot/uigetdir.m, plot/private/__fltk_file_filter__.m:): Check if\n\tfile argument is a valid path, don't use fileparts in this case.\n\n2010-11-21  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Fix plot titles so they are visible for\n\tgnuplot 4.4.x (31711).\n\t* general/cell2mat.m: Return empty matrix for empty cell.\n\n2010-11-21  Kai Habel  <kai.habel@gmx.de>\n\n\t* (plot/uigetfile.m, plot/uiputfile.m): Set default directory to pwd.\n\n2010-11-21  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/uigetdir.m, plot/uigetfile.m, plot/uiputfile.m,\n\tplot/private/__fltk_file_filter__.m: New files.\n\t* plot/module.mk: Add new files.\n\t* miscellaneous/unimplemented.m: Remove uigetdir.m, uigetfile.m,\n\tand uiputfile.m from list of unimplemented functions.\n\n2010-11-20  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/gnuplot_drawnow.m: Remove spurious line causing 'ans=1' to be\n\treturned when printing plots.\n\n2010-11-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__gnuplot_has_feature__.m: Since there is not gnuplot 4.3.x\n\trelease, replace reference to version 4.3 with 4.4.\n\n2010-11-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/text.m: Ensure text position property is set after units\n\tproperty.\n\t* plot/__go_draw_axes__.m: Fix bug setting zscale to yscale (31693).\n\n2010-11-18  Christos Dimitrakakis  <christos.dimitrakakis@gmail.com>\n\n\t* statistics/distributions/betapdf.m: Use lgamma to compute\n\tnormalising constant in log space in order to handle large\n\tparameters a and b.  Ensure correct values at x == 0 or x == 1.\n\n2010-11-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__print_parse_opts__.m: For tests, allow __print_parse_opts__\n\tto run with no inputs.\n\n2010-11-17  Ben Abbott  <bpabbott@mac.com>\n\n\t* general/subsindex.m: Fix typo in doc-string.\n\n2010-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* strings/strchr.m: Style fixes.\n\n2010-11-17  Kim Hansen  <kim@ange.dk>\n\n\t* strings/strchr.m: New tests.\n\n2010-11-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* miscellaneous/unimplemented.m: Update unimplemented functions list.\n\n2010-11-15  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/saveas.m: Add function name to error messages.  Use semicolons\n\tto prevent unnecessary output.  Use common terms 'ext' for extension\n\tand 'filename' for filename in docstring.\n\n2010-11-15  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/saveas.m: New file.\n\t* plot/module.mk: Add saveas.m\n\t* plot/__print_parse_opts__.m: Parse arguments correctly when first\n\targument is a figure handle.\n\t* plot/print.m: Add saveas to seealso entry.\n\n2010-11-14  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/print.m: Use \"del\" instead of \"delete\" in DOS shell, and\n\treplace\tforward slashes with backslashes.\n\t* plot/__gnuplot_print__.m: Likewise.\n\n2010-11-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/__all_opts__.m: Ensure that the array is always\n\tcase-insensitively sorted.\n\n2010-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* plot/gnuplot_drawnow.m (have_non_legend_axes): New function.\n\tUse it to avoid errors if there are no axes.\n\t* plot/legend.m: Avoid indexing beyond end of varargin array.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* gethelp.cc: Eliminate special case for __DECCXX.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* scripts/deprecated/dispatch.m: Don't set warning state in tests.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/dispatch.m: Deprecate dispatch function.\n\t* deprecated/module.mk (deprecated_FCN_FILES): Add it to the list.\n\n2010-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* help/help.m: Call missing_function_hook with output argument\n\tand print message here.\n\t* miscellaneous/unimplemented.m: Return message if nargout > 0.\n\tFixes bug #31597.\n\n2010-11-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Check for z/y/zdata before converting\n\tnegative values to NaNs. Bug fix for changeset 11201.\n\t* plot/daspect.m: Fix demo using both daspect and pbaspect.\n\n2010-11-08  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Remove foreground color earlier.\n\t* plot/__go_draw_figure__.m: Don't set the foreground color here.\n\n2010-11-08  Rik  <octave@nomad.inbox5.com>\n\n\t* sparse/sprand.m: Add input validation to function.\n\n2010-11-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__bar__.m: Permit bar() to be called with scalar inputs.\n\t* plot/__go_draw_axes__.m, plot/axis.m: Set proper tight axis limits\n\tfor log scale.\n\n2010-11-07  David Bateman  <dbateman@free.fr>\n\n\t* plot/legend.m: Remove call to drawnow.\n\n\t* plot/__go_draw_axes__.m: Pass the legend axes as a structure.\n\tTest whether the legend axis has any children before using it.\n\t* plot/__go_draw_figure.m: Setup a fake axis to handle multi-parent\n\tlegend axes and delete this fake axiss when we're done with it.\n\t* plot/gnuplot_drawnow.m: Don't cound legend axes when decidong if\n\tmultiplot should be used or not.\n\t* plot/legend.m: Handle correctly plotyy as a multi-parented axis.\n\tReuse existing legend axis if possible. Setup listeners to propagate\n\tchanges in the lines to the legend. Setup listeners that handle the\n\tproperties that need to legend to be recreated.\n\t* plot/plotyy.m: Cross-references the axes of the plotyy in the userdata\n\tof the axes.\n\n2010-11-07  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* plot/colorbar.m: Make colorbar function aware of dataaspect settings.\n\n2010-11-06  Marco Caliari <marco.caliari@univr.it>\n\n\t* polynomial/spline.m: Fit a parabola for input with 3\n\telements (bug #31098).\n\n2010-11-04  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/__fltk_ginput__.m: Use semicolons to prevent internal\n\tfunction evaluations being output to screen.\n\n2010-11-04  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/module.mk: Add __fltk_ginput__.m to list of scripts\n\n2010-11-04  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Update check-m-sources target to include generated\n\tfunction files.\n\n2010-11-04  Rik  <octave@nomad.inbox5.com>\n\n\t* general/accumarray.m, general/accumdim.m, general/blkdiag.m,\n\tgeneral/cell2mat.m, general/common_size.m,\n\tgeneral/private/__isequal__.m, general/private/__splinen__.m,\n\tgeometry/voronoi.m, io/textscan.m, miscellaneous/private/__xzip__.m,\n\tpkg/pkg.m, plot/axis.m, plot/pareto.m, plot/private/__patch__.m,\n\tstatistics/base/mode.m, strings/deblank.m, strings/strcat.m,\n\tstrings/strmatch.m, strings/strtrim.m, strings/untabify.m:\n\tReverse previous changeset.  Use all lower case for \"uniformoutput\"\n\toption.\n\n2010-11-03  Rik  <octave@nomad.inbox5.com>\n\n\t* general/accumdim.m, general/cell2mat.m, general/common_size.m,\n\tgeneral/structfun.m, pkg/pkg.m, strings/untabify.m: Use CamelCase\n\tfor 'UniformOutput' option to cellfun.\n\n2010-11-03  Rik  <octave@nomad.inbox5.com>\n\n\t* scripts/plot/plotyy.m, scripts/plot/xlim.m, scripts/plot/ylim.m,\n\tscripts/plot/zlim.m: Fix typos in docstring and demo string.\n\n2010-11-03  Rik  <octave@nomad.inbox5.com>\n\n\t* general/common_size.m, miscellaneous/private/__xzip__.m,\n\tmiscellaneous/what.m, plot/pareto.m, plot/private/__patch__.m:\n\tUse function handle as input to cellfun rather than quoted function\n\tname or anonymous function wrapper.\n\n2010-11-03  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* plot/axis.m: Making 'axis equal' equivalent to 'daspect([1,1,1])'.\n\n2010-11-03  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* plot/private/__actual_axis_position__.m: Remove temporary\n\tcalculation of plotboxratio for the gnuplot backend when\n\tdataaspectratiomode, xlimmode and ylimmode are all set to manual.\n\tNow this case is handled in src/graphics.cc .\n\n2010-11-03  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* plot/axis.m: Leave zlim unchanged during \"axis tight\" on 2D plots\n\n2010-11-03  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__patch__.m: Don't index an empty array; bug introduced\n\tby changeset 11175.\n\n2010-11-03  Ben Abbott  <bpabbott@mac.com>\n\n\t* miscellaneous/getappdata.m, miscellaneous/isappdata.m,\n\tmiscellaneous/rmappdata.m, miscellaneous/setappdata.m:\n\tAdd new appdata function.\n\n2010-11-01  David Bateman  <dbateman@free.fr>\n\n\t* plot/__private__/__contour__.m: Use __go_patch__ rather than patch\n\tto avoid the cost of the patch callback functions. Ensure that the\n\tproperties that are normally set by patch are correctly set in the\n\tcall to __go_patch__.\n\n2010-11-01  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/axis.m: Exclude hggroup {x,y,z}data properties when determing\n\ttight axis limits.\n\n2010-10-31  Rik  <octave@nomad.inbox5.com>\n\n\t* strings/base2dec.m, strings/bin2dec.m, strings/dec2base.m,\n\t  strings/dec2bin.m, strings/dec2hex.m, strings/hex2dec.m:\n\t  Improve docstrings, use more descriptive variable names,\n\t  add more tests for functions used to convert between bases.\n\n2010-10-31  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* plot/__go_draw_axes__.m: Removing deprecated code handling the case\n        of both plotboxaspectratiomode and dataaspectratiomode set to manual\n        for the gnuplot backend. Now this case is handled already in\n        src/graphics.cc where xlim, ylim, zlim are recalculated if necessary.\n\n2010-10-30  Gunnar Farnebäck <gunnar@lysator.liu.se>\n\n\t* strings/dec2base.m: Update algorithm to handle numbers up to 2^64-1.\n\n2010-10-28  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/module.mk, signal/module.mk, deprecated/autocov.m,\n\tdeprecated/autocor.m: Deprecate autocov and autocor functions.\n\n2010-10-27  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Don't attempt to plot patch outlines if\n\tthe marker property is set to none.\n\n2010-10-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/daspect.m, plot/pbaspect.m: Add demos setting both data and\n\tplotbox aspect ratios.\n\n2010-10-27  David Bateman  <dbateman@free.fr>\n\n\t* plot/private/__patch__.m (setdata, setvertexdata): If argments are\n\trepeated, take the last argument only into account. Set cdata and\n\tfacevertexcdata properties always.\n\n2010-10-26  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/uimenu.m: Add simple demo\n\n2010-10-25  David Bateman  <dbateman@free.fr>\n\n\t* statistics/distributions/discrete_pdf.m: Sort values before calling\n\tthe lookup function.\n\n2010-10-25  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/uimenu.m: New function\n\t* plot/__go_draw_figure__.m: Ignore uimenu objects for gnuplot\n\tbackend\n\t* plot/module.mk (plot_FCN_FILES): Add it to the list.\n\n2010-10-24  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/compare_versions.m, plot/ylabel.m, plot/ylim.m,\n\tplot/zlabel.m, plot/zlim.m: Docstring improvements.\n\n2010-10-24  Rik  <octave@nomad.inbox5.com>\n\n\t* specfun/module.mk, deprecated/module.mk, deprecated/betai.m,\n\tdeprecated/gammai.m, deprecated/is_global.m: Deprecate betai,\n\tgammai, and is_global functions.\n\n2010-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* strings/untabify.m, strings/strjust.m, io/strread.m:\n\tDocstring fixes.\n\n2010-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/distributions/nbinrnd.m: Use | instead of || in\n\targument to find.\n\n\t* deprecated/intwarning.m, general/bicubic.m, general/postpad.m,\n\tgeneral/prepad.m, general/private/__splinen__.m,\n\tgeneral/shift.m, miscellaneous/swapbytes.m, pkg/pkg.m,\n\tplot/clabel.m, plot/colorbar.m, plot/fill.m, plot/legend.m,\n\tplot/plotmatrix.m, plot/plotyy.m, plot/private/__clabel__.m,\n\tplot/private/__ezplot__.m, plot/private/__quiver__.m,\n\tplot/subplot.m, signal/unwrap.m, statistics/base/histc.m,\n\tstatistics/base/iqr.m, statistics/base/kurtosis.m,\n\tstatistics/base/mode.m, statistics/base/ranks.m,\n\tstatistics/base/run_count.m, statistics/base/skewness.m,\n\tstatistics/base/statistics.m, statistics/base/studentize.m,\n\tstatistics/distributions/exprnd.m,\n\tstatistics/distributions/frnd.m,\n\tstatistics/distributions/geornd.m,\n\tstatistics/distributions/lognrnd.m,\n\tstatistics/distributions/nbinrnd.m,\n\tstatistics/distributions/poissrnd.m,\n\tstatistics/distributions/trnd.m,\n\tstatistics/distributions/wblrnd.m, strings/strcat.m,\n\ttime/datestr.m, time/datetick.m: Break lines before && and ||,\n\tnot before.\n\n2010-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* io/strread.m: Docstring fixes.\n\n2010-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* io/is_valid_file_id.m: Ensure that FID is a scalar before\n\tcalling fopen to get info.  New tests.\n\n2010-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* io/is_valid_file_id.m: New function.\n\t* io/module.mk (io_FCN_FILES): Add it to the list.\n\n2010-10-23  Ben Abbott  <bpabbott@mac.com>\n\n\t* io/textscan.m, miscellaneous/unimplemented.m, io/module.mk:\n\tNew function.\n\n2010-10-22  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/legend.m: Trivial fix to allow legend handle to be returned.\n\n2010-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/base/quantile.m: Fix typo in previous change.\n\n2010-10-21  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/distributions/wblcdf.m, statistics/distributions/wblinv.m,\n\tstatistics/distributions/wblpdf.m, statistics/distributions/wblrnd.m:\n\tFix reversed documentation for shape and scale parameters.\n\n2010-10-21  Ben Abbott  <bpabbott@mac.com>\n\n\t* io/strread.m: Improve compatibility with Matlab.\n\n2010-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* general/private/__isequal__.m: Style fixes.\n\n2010-10-20  Iain Murray  <murray@cs.toronto.edu>\n\n\t* general/private/__isequal__.m: Fix bug #31239 where\n\tisequalwithequalnans is incorrect.\n\n2010-10-20  Rik  <octave@nomad.inbox5.com>\n\n\t* polynomial/conv.m: Remove redundant test.\n\t* signal/fftconv.m: Add tests used by conv.m code.\n\n2010-10-20  Olaf Till  <olaf.till@uni-jena.de>\n\n\t* optimization/optimset.m: Use cell2struct instead of struct to\n\thandle cell arrays as options.\n\n2010-10-20  John W. Eaton  <jwe@octave.org>\n\n\t* io/strread.m, optimization/sqp.m, plot/daspect.m,\n\tplot/pbaspect.m, plot/gnuplot_drawnow.m, plot/isocolors.m,\n\tplot/isonormals.m, plot/legend.m, plot/print.m,\n\tplot/private/__interp_cube__.m, plot/__fltk_print__.m,\n\tplot/__gnuplot_print__.m, plot/__print_parse_opts__.m,\n\tstatistics/base/quantile.m: Style fixes.\n\n2010-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* strings/module.mk (strings_FCN_FILES): Include\n\tstrings/untabify.m in the list.\n\t* strings/untabify.m: Escape { and } characters in docstring.\n\n2010-10-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* strings/strjust.m: Add \"untabify\" and \"strrep\" to @seealso{} in the\n\tdoc-string.\n\n2010-10-18  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* general/gradient.m, linear-algebra/normest.m,\n\tplot/__gnuplot_print__.m, plot/__print_parse_opts__.m,\n\tplot/daspect.m, plot/gnuplot_drawnow.m, plot/pbaspect.m,\n\tplot/print.m, signal/periodogram.m:\n\tStyle fix, replace end by endfor.\n\n2010-10-18  Marco Caliari  <marco.caliari@univr.it>\n\n\t* polynomial/polyval.m: Use Horner's method.\n\n2010-10-18  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Always use gnuplot to display images.\n\t* image/image.m: Delete references to image_viewer.\n\t* image/image_viewer.m: Delete obsolete function.\n\t* image/module.mk (image_FCN_FILES): Remove image/image_viewer.m\n\tfrom the list.\n\n2010-10-18  Gunnar Farneback  <gunnar@lysator.liu.se>\n\n\t* general/interp2.m: Fix input checks for cubic\n\tinterpolation (bug #31352, part 1).\n\n2010-10-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: Add examples to the docstring.\n\n2010-10-18  John W. Eaton  <jwe@octave.org>\n\n\t* plot/private/__errplot__.m: Remove debugging statement from\n\tprevious change.\n\n2010-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/edit.m: Use version 3 in GPL notice.\n\n\t* @ftp/ascii.m, @ftp/binary.m, @ftp/cd.m, @ftp/close.m,\n\t@ftp/delete.m, @ftp/dir.m, @ftp/display.m, @ftp/ftp.m,\n\t@ftp/loadobj.m, @ftp/mget.m, @ftp/mkdir.m, @ftp/mput.m,\n\t@ftp/rename.m, @ftp/rmdir.m, @ftp/saveobj.m,\n\thelp/__makeinfo__.m, help/__strip_html_tags__.m,\n\thelp/gen_doc_cache.m, help/get_first_help_sentence.m,\n\thelp/help.m, help/lookfor.m, help/print_usage.m,\n\thelp/private/__additional_help_message__.m, help/type.m,\n\thelp/which.m, io/fileread.m, io/strread.m, io/textread.m,\n\tpkg/get_forge_pkg.m, plot/__gnuplot_has_feature__.m,\n\tplot/__gnuplot_open_stream__.m, plot/__marching_cube__.m,\n\tplot/cla.m, plot/comet.m, plot/daspect.m, plot/isocolors.m,\n\tplot/isonormals.m, plot/isosurface.m, plot/pbaspect.m,\n\tplot/private/__interp_cube__.m, plot/private/__ghostscript__.m,\n\tplot/private/__tight_eps_bbox__.m,\n\tplot/private/__gnuplot_has_terminal__.m,\n\tpolynomial/polyaffine.m, sparse/svds.m, strings/strsplit.m:\n\tUse Octave copyright notice instead of generic \"This program is\n\tfree software\" notice.\n\n2010-10-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* strings/untabify.m: New function to untabify text.\n\n2010-10-17  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/mesh.m, plot/surf.m: Include the 4th input (color) in the\n\tdocstring.\n\n2010-10-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__errplot__.m, plot/errorbar.m: Allow line and marker\n\ttypes to be set.\n\n2010-10-14  John W. Eaton  <jwe@octave.org>\n\n\t* special-matrix/rosser.m: New tests.\n\t* special-matrix/wilkinson.m: Fix error message.  New tests.\n\t* special-matrix/pascal.m: Error if T is out of range.\n\tNew tests.\n\n2010-10-14  John W. Eaton  <jwe@octave.org>\n\n\t* set/unique.m: Remove check for issparse existence since it is\n\tnow a built-in function.\n\n2010-10-14  Ben Abbott  <bpabbott@mac.com>\n\n\t* strings/strjust.m: Clarify that justification  applies to spaces and\n\tnull characters.\n\n2010-10-09  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Enable linetypes for gnuplot.\n\n2010-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/distributions/geornd.m,\n\t* statistics/distributions/hygecdf.m,\n\t* statistics/distributions/hygeinv.m,\n\t* statistics/distributions/poissrnd.m,\n\t* statistics/distributions/wblrnd.m:\n\tUse || instead of | and && instead of & in IF conditions\n\tinvolving scalars.\n\n2010-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__fltk_ginput__.m: Use || instead of | in IF condition.\n\n2010-10-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* image/image.m, plot/__go_draw_axes__.m: Do not store flipped image\n\tproperty values when x/ydata descends.\n\n2010-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* signal/periodogram.m: Fix parse errors.\n\n2010-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* time/datevec.m: Use endfunction to mark end of primary\n\tfunction and subfunctions.\n\n2010-10-07  Rik  <octave@nomad.inbox5.com>\n\n\t* polynomial/conv.m: Improve docstring.\n\t* signal/fftconv.m: Improve docstring and error messages.\n\n2010-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/conv.m: Handle optional third argument.  New\n\ttests.  Update doc string.\n\n2010-10-06  Ben Abbott  <bpabbott@mac.com>\n\n\t* image/image.m: Allow x/ydata to imply a flip of the image.\n\tModify demos.\n\n2010-10-05  Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* general/quadv.m: Fix help string and add a test for vector\n\tvalued functions.\n\n2010-10-04  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* image/image.m (__img__): Use __image_pixel_size__ to calculate\n\tlimits\n\n2010-09-28  John P. Swensen  <jpswensen@gmail.com>\n\n\t* image/imwrite.m: Call __magick_format_list__ to get list of\n\taccepted formats.\n\n2010-09-28  Rik  <octave@nomad.inbox5.com>\n\n\t* linear-algebra/logm.m, plot/legend.m, signal/periodogram.m:\n\tUntabify scripts.\n\n2010-09-27  Rik  <octave@nomad.inbox5.com>\n\n\t* io/dlmwrite.m: Replace non-POSIX '\\d' regex pattern.\n\n\t* miscellaneous/edit.m, path/savepath.m,\n\tplot/__gnuplot_get_var__.m,\n\tplot/private/__gnuplot_has_terminal__.m, plot/refreshdata.m,\n\tplot/whitebg.m, testfun/runtests.m, time/datestr.m:\n\tUse single quotes for regular expression patterns when possible.\n\n\t* miscellaneous/ls.m, plot/__gnuplot_ginput__.m,\n\tplot/__go_draw_axes__.m, plot/private/__ezplot__.m,\n\ttestfun/test.m: Remove uses of shorthand character classes\n\twithin list operators which is unsupported by POSIX regex.\n\n\t* pkg/get_forge_pkg.m: Select desired output from regexp\n\trather than ignoring most outputs.\n\n2010-09-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__print_parse_opts__.m: Fix test.\n\n2010-09-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* elfun/lcm.m: Simplify.\n\n2010-09-27  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__print_parse_opts__.m: Properly crop eps image and fix tests.\n\n\t* plot/__go_draw_axes__.m, plot/private/__ezplot__.m,\n\ttestfun/test.m: Remove uses of shorthand character classes\n\twithin list operators which is unsupported by POSIX regex.\n\n\t* pkg/get_forge_pkg.m: Select desired output from regexp\n\trather than ignoring most outputs.\n\n2010-09-26  Rik  <octave@nomad.inbox5.com>\n\n\t* testfun/runtests.m (has_tests): Recode to remove requirement for PCRE.\n\tBug #31025.\n\n2010-09-25  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__print_parse_opts__.m: Recongize gs devices {eps/pdf/ps}write.\n\n2010-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/bug_report.m: Display information about how to\n\tsubmit bug reports instead of creating and mailing a bug report.\n\n2010-09-22  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__ghostscript__.m, plot/print.m: When appending, delete\n\ttemporay files at the end of the ghostscript pipeline.\n\n2010-09-21  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__fltk_print__.m, plot/private/__ghostscript__.m,\n\tplot/__gnuplot_print__.m, plot/__print_parse_opts__.m,\n\tplot/print.m: Print via a pipeline.\n\n2010-09-20  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/legend.m: Index location cellstr to obtain a string.\n\n2010-09-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/colorbar.m, plot/axis.m,\n\tplot/private/__actual_axis_position__.m, plot/__go_draw_axes__.m:\n\tSpecial treatment activepositionproperty = outerposition for the\n\tgnuplot backend. This allows the gnuplot key to be placed outside\n\tthe plotbox.\n\t* plot/private/__plt__.m: Trivial fix for recent legend changeset.\n\t* plot/legend.m: Treat line, patch, and surface objects differetly.\n\t* plot/__go_draw_axes__.m: Remove left over debug code.\n\t* miscellaneous/mkoctfile.m: Change help text to be consistent with\n\tthe shell version.\n\n2010-09-18  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Modify legend code to use data from legend\n\taxes.\n\t* plot/__go_draw_figure__.m: Draw draw figure axes, but pass their\n\tdata to the axis they are associated with.\n\t* plot/__get_plt_axes_arg__.m: Ignores axes tagged with \"legend\".\n\t* plot/legend.m: Rewrite to use line and text primitives in a seperate\n\taxis.\n\t* plot/plot3.m: Support old legend format (eg \"-;title'\") with new\n\tlegend code.\n\t* plot/private/__plt__.m: Ditto.\n\n2010-09-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Ensure text objects have units of \"data\".\n\n2010-09-16  John Swensen  <jpswensen@gmail.com>\n\n\t* imwrite.m: Accept more image formats.\n\n2010-09-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* signal/periodogram.m: Support additional inputs:\n\twin, nfft, Fs, range. Thanks to Alois Schlögl.\n\n2010-09-13  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Use new function __gnuplot_has_terminal__().\n\t* plot/private/__gnuplot_has_terminal__.m: New function.\n\n2010-09-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/common_size.m: Partially rewrite using cellindexmat.\n\n2010-09-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: Use @vec instead of @(x) x(:) for faster call.\n\n2010-09-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pkg/get_forge_pkg.m: Allow underscores in pkg names.\n\n2010-09-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__fltk_print__.m, plot/private/__ghostscript__.m,\n\tplot/__gnuplot_print__.m, plot/__print_parse_opts__.m,\n\tplot/print.m: Consolidate gs code into print.m.\n\t* plot/colorbar.m, plot/axis.m,\n\tplot/private/__actual_axis_position__.m, plot/__go_draw_axes__.m:\n\tRevert treatment of activepositionproperty from the gnuplot backend.\n\t* image/image.m: Fix axis limits for single dimension images, add\n\tdemo.\n\n2010-09-07  David Bateman  <dbateman@free.fr>\n\n\t* plot/plotyy.m: Don't add the __plotyy_axes__ property to the\n\taxes handles if iit already exists.\n\n2010-09-06  Petr Mikulik  <mikulik@physics.muni.cz>\n\n\t* geometry/griddata.m: Allow x, y to be vectors, and z a matrix.\n\n2010-09-03  David Bateman  <dbateman@free.fr>\n\n\t* geometry/delaunay.m: Allow the delaunay function to treat\n\tmatrices of the same size for compatibility.\n\n2010-09-03  Ben Abbott  <bpabbott@mac.com>\n\n\t* image/image.m: Matlab compatible axis limits, add demo.\n\n2010-09-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* io/dlmwrite.m: Don't fclose if file ID is supplied.\n\n2010-09-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* io/dlmwrite.m: Support file IDs.\n\n2010-07-07  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/what.m: Off by one error.\n\n\t* plot/__go_draw_axes__.m: Improve matlab compatibility for \".\"\n\tmarker.\n\n2010-08-31  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__actual_axis_position__.m, plot/__go_draw_axes__.m,\n\tplot/axis.m, plot/colorbar.m, plot/daspect.m, plot/plotyy.m,\n\tplot/subplot.m: Treatment of activepositionproperty for gnuplot.\n\t* plot/__go_draw_axes__.m: Missing part of last changeset.\n\t* plot/__go_draw_axes__.m: Fix specification of pointtype for patches\n\t(bug introduced in rev 2f9de135e7f9).\n\n2010-08-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Use gnuplot's pentagon for marker == 'p'.\n\n2010-08-27  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/colorbar.m, * plot/__go_draw_axes__.m,\n\tplot/private/__actual_axis_position__.m: Don't pass figure handle to\n\t__calc_dimensions__.\n\t* plot/private/__ghostscript__.m: Don't set anti-aliasing options for\n\tvector formats.\n\t* plot/__print_parse_opts__.m: Fix tests.\n\n2010-08-27  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* plot/__go_draw_axes__.m (__calc_dimensions__): Delete.\n\t* plot/__actual_axis_position__.m (__calc_dimensions__): Delete.\n\n2010-08-27  Pascal A. Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* plot/hold.m: If arg is axis handle, get corresponding figure\n\thandle from axis parent property.\n\n2010-08-27  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__gnuplot_print__.m: Properly restore fontsize after eps output.\n\t* plot/plotyy.m: Modified demo for changeset 10912 9abc67b4bd4f.\n\t* plot/__fltk_print__.m, plot/__go_draw_axes__.m,\n\tplot/__go_draw_figure__.m, plot/__gnuplot_print__.m,\n\tplot/gnuplot_drawnow.m, plot/print.m, plot/private/__ghostscript__.m,\n\tplot/private/__tight_eps_bbox__.m: Unify gnuplot printing with the\n\tthe fltk backend. Turn figure background color off when printing.\n\tImprove the axes font spacing for most gnuplot terminals.\n\n2010-08-26  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: For yaxislocation == 'right' associate text\n\tposition with 'second' coordinate system.\n\n2010-08-25  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Revert erroneous portion of changeset\n\t10910 40cf7cc4ea62.\n\n2010-08-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__actual_axis_position__.m, plot/__go_draw_axes__.m:\n\tProperly interpret plotboxaspectratio when 3D objects are viewed as 2D.\n\t* plot/colorbar.m: Add demo.\n\n2010-08-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/interp2.m: Don't use bicubic for consistency (can't handle\n\tnon-grid interpolation).\n\n2010-08-17  Rik  <octave@nomad.inbox5.com>\n\n\t* general/randi.m: Add IMAX check for class \"single\" numbers.\n\n2010-08-15  Rik  <octave@nomad.inbox5.com>\n\n\t* general/randi.m: Add new script for random integers.\n\t* general/module.mk: Add randi to build file list.\n\t* miscellaneous/unimplemented.m: Remove randi from unimplemented list.\n\n2010-08-15  Rik  <octave@nomad.inbox5.com>\n\n\t* image/imwrite.m: Allow writing of 1-bit (B&W) images.\n\tImprove documentation string.  Add input validation tests.\n\n2010-08-13  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__print_parse_opts__.m: Double quote paths with spaces.\n\n2010-08-11  Rik  <octave@nomad.inbox5.com>\n\n\t* set/unique.m: Handle corner case where sparse matrix is actually full.\n\n2010-08-10  Rik  <octave@nomad.inbox5.com>\n\n\t* set/unique.m: Check whether outputs are used before calculating.\n\n2010-08-10  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/base/module.mk, deprecated/module.mk,\n\tstatistics/base/values.m, deprecated/values.m: Deprecate values.m\n\n2010-08-08  Rik  <octave@nomad.inbox5.com>\n\n\t* miscellaneous/unimplemented.m: Add newlines to format output for\n\teasier reading.  Format all lines < 80 characters.  Remove\n\t'whitebg' function from unimplemented list.\n\n2010-08-08  Rik  <octave@nomad.inbox5.com>\n\n\t* @ftp/PKG_ADD: Remove temporary build file from hg version control.\n\n2010-08-09  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__print_parse_opts__.m: Default pstex suffix should be '.ps'.\n\n2010-08-08  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Create .DOCSTRINGS quietly and avoid screen clutter\n\tduring build.\n\n2010-08-08  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Run do_subst macro quietly without cluttering screen\n\tduring build.\n\n2010-08-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: Include 'colormap' when converting RGB to mono.\n\n2010-08-07  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__fltk_print__.m: When running pstoedit, crop eps file after it\n\tis created. Correctly check error status.\n\n2010-08-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/cell2mat.m: Allow cells of struct arrays.\n\n2010-08-05  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__print_parse_opts__.m, plot/__fltk_print__.m: Don't warn on\n\tabsence of fig2dev or pstoedit until they are needed.\n\t* plot/__print_parse_opts__.m, plot/__fltk_print__.m: Add epslatex,\n\tpslatex, and pdflatex output for fltk backend. Use the gs png16m device\n\tinstead of png256.\n\t* plot/print.m: Modify texinfo. Add unwind_protect block.\n\n2010-08-01 Marco Caliari  <marco.caliari@univr.it>\n\n\t* general/bicubic.m: Fix bug #30400 when bicubic called with small\n\tnumbers of arguments.\n\n2010-08-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/sortrows.m: Don't actually permute the rows if not\n\trequested.\n\n2010-08-04  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m, plot/__print_parse_opts__.m, plot/__gnuplot_print__.m,\n\tplot/private/__ghostscript__.m: plot/__fltk_print__.m: Add ps and pdf\n\toutput for fltk backend, improved use of ghostscript, and minor\n\timprovements.\n\n2010-08-01  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/intwarning.m, general/arrayfun.m, general/cplxpair.m,\n\tgeneral/interp1.m, general/interpn.m, general/quadgk.m,\n\tgeneral/structfun.m, image/image_viewer.m, io/strread.m,\n\tmiscellaneous/warning_ids.m, optimization/lsqnonneg.m, pkg/pkg.m,\n\tplot/__marching_cube__.m, plot/bar.m, plot/contourc.m, plot/errorbar.m,\n\tplot/ezplot.m, plot/isocolors.m, plot/isonormals.m, plot/isosurface.m,\n\tplot/stem.m, plot/stem3.m, polynomial/compan.m, polynomial/ppval.m,\n\tsignal/arch_rnd.m, sparse/pcg.m, sparse/svds.m,\n\tspecial-matrix/invhilb.m, statistics/distributions/wblcdf.m,\n\ttestfun/assert.m, testfun/demo.m, testfun/speed.m:\n\tGrammarcheck documentation.  Add @noindent lines and ensure line\n\tlength is less than 80.\n\n2010-08-01  Martin Helm  <martin@mhelm.de>\n\n\t* plot/isosurface.m: Swap rows and columns of matrix in call to\n\tmeshgrid.\n\n2010-08-01  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/print.m: Update documentation string.  Change to active voice.\n\n2010-07-30  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: add .DOCSTRINGS to the DISTCLEANFILES list\n\n2010-07-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m, plot/__print_parse_opts__.m, plot/__fltk_print__.m,\n\tplot/__gnuplot_print__.m: Improved printing for the fltk backend.\n\t* plot/private/__ghostscript__.m, plot/private/__tight_eps_bbox__.m:\n\tNew files to support printing.\n\n2010-07-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/expm.m: Special-case scalars and diagonal matrices.\n\tSuggested by M. Caliari.\n\n2010-07-26  Rik  <octave@nomad.inbox5.com>\n\n\t* linear-algebra/logm.m: Improve documentation string.  Add GPL header.\n\tAdd additional test block.\n\n2010-07-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/logm.m: Rewrite. Thanks to M. Caliari and R. T. Guy.\n\n2010-07-26  Rik  <octave@nomad.inbox5.com>\n\n\t* deprecated/complement.m, deprecated/intwarning.m, general/arrayfun.m,\n\tgeneral/circshift.m, general/colon.m, general/common_size.m,\n\tgeneral/del2.m, general/flipdim.m, general/fliplr.m, general/flipud.m,\n\tgeneral/idivide.m, general/interp1.m, general/interp2.m,\n\tgeneral/interp3.m, general/interpn.m, general/loadobj.m,\n\tgeneral/quadgk.m, general/rat.m, general/saveobj.m, general/shiftdim.m,\n\tgeometry/delaunayn.m, image/image_viewer.m, image/imfinfo.m,\n\tio/csvread.m, io/csvwrite.m, io/strread.m, linear-algebra/condest.m,\n\tlinear-algebra/housh.m, linear-algebra/onenormest.m,\n\tlinear-algebra/qzhess.m, miscellaneous/bincoeff.m,\n\tmiscellaneous/compare_versions.m, miscellaneous/computer.m,\n\tmiscellaneous/edit.m, miscellaneous/fileattrib.m,\n\tmiscellaneous/getfield.m, miscellaneous/license.m, miscellaneous/ls.m,\n\tmiscellaneous/parseparams.m, miscellaneous/swapbytes.m,\n\tmiscellaneous/ver.m, miscellaneous/warning_ids.m,\n\toptimization/fminbnd.m, optimization/fminunc.m, optimization/fsolve.m,\n\toptimization/fzero.m, optimization/glpk.m, optimization/lsqnonneg.m,\n\toptimization/pqpnonneg.m, optimization/qp.m, optimization/sqp.m,\n\tpath/pathdef.m, pkg/pkg.m, plot/__marching_cube__.m, plot/axis.m,\n\tplot/colorbar.m, plot/contourc.m, plot/contourf.m, plot/cylinder.m,\n\tplot/ezplot.m, plot/isocolors.m, plot/isonormals.m, plot/legend.m,\n\tplot/print.m, plot/refreshdata.m, plot/slice.m, plot/subplot.m,\n\tplot/surfl.m, polynomial/compan.m, polynomial/mpoles.m,\n\tpolynomial/poly.m, polynomial/polyaffine.m, polynomial/polyfit.m,\n\tpolynomial/polygcd.m, polynomial/polyout.m, polynomial/residue.m,\n\tpolynomial/roots.m, polynomial/unmkpp.m, set/union.m, signal/filter2.m,\n\tsignal/stft.m, sparse/spdiags.m, specfun/bessel.m, specfun/beta.m,\n\tspecfun/betaln.m, specfun/nchoosek.m, specfun/nthroot.m,\n\tspecfun/perms.m, special-matrix/hadamard.m, special-matrix/hankel.m,\n\tspecial-matrix/hilb.m, special-matrix/invhilb.m,\n\tspecial-matrix/toeplitz.m, special-matrix/vander.m,\n\tstatistics/base/cloglog.m, statistics/base/cor.m,\n\tstatistics/base/corrcoef.m, statistics/base/kendall.m,\n\tstatistics/base/kurtosis.m, statistics/base/logit.m,\n\tstatistics/base/mean.m, statistics/base/median.m,\n\tstatistics/base/quantile.m, statistics/base/skewness.m,\n\tstatistics/base/std.m, statistics/base/var.m,\n\tstatistics/distributions/kolmogorov_smirnov_cdf.m,\n\tstatistics/distributions/wblcdf.m, statistics/tests/cor_test.m,\n\tstatistics/tests/hotelling_test_2.m, strings/bin2dec.m,\n\tstrings/cstrcat.m, strings/dec2bin.m, strings/dec2hex.m,\n\tstrings/findstr.m, strings/hex2dec.m, strings/index.m,\n\tstrings/isstrprop.m, strings/regexptranslate.m, strings/rindex.m,\n\tstrings/strcat.m, strings/substr.m, testfun/demo.m, time/asctime.m,\n\ttime/clock.m, time/ctime.m, time/date.m, time/datenum.m,\n\ttime/is_leap_year.m: Grammarcheck documentation of m-files.\n\tAdd newlines between @items for readability.\n\n2010-07-26  Ben Abbott  <bpabbott@mac.com>\n\n\t* general/interp1.m: When absent set X equal to the inices of Y.\n\t* general/interpn.m: Convert interpolation vectors of non-equal\n\tlength to nd-arrays.\n\n2010-07-26  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/image.m: Replace parenthesis with curly bracket in Texinfo.\n\n2010-07-25  Rik  <octave@nomad.inbox5.com>\n\n\t* image/image.m: Always reverse 'ydir' property when displaying images.\n\n2010-07-19  Rik  <octave@nomad.inbox5.com>\n\n\t* help/__makeinfo__.m: Add support to process @nopsell macro.\n\tFix bug when more than one @seealso block exists.\n\n2010-07-19  Rik  <octave@nomad.inbox5.com>\n\n\t* general/repmat.m: Add seealso to new repelems function.\n\n2010-07-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* specfun/nchoosek.m: Optimize.\n\n2010-07-18  Rik  <octave@nomad.inbox5.com>\n\n\t* @ftp/ftp.m, @ftp/mget.m, audio/lin2mu.m, audio/loadaudio.m,\n\taudio/mu2lin.m, audio/playaudio.m, audio/saveaudio.m,\n\taudio/wavwrite.m, deprecated/create_set.m,\n\tdeprecated/intwarning.m, deprecated/lchol.m,\n\tdeprecated/spchol.m, deprecated/spdiag.m, deprecated/spfind.m,\n\tdeprecated/splchol.m, deprecated/splu.m, deprecated/spmax.m,\n\tdeprecated/spmin.m, deprecated/spqr.m, deprecated/weibcdf.m,\n\tdeprecated/weibrnd.m, general/accumarray.m, general/bitset.m,\n\tgeneral/colon.m, general/deal.m, general/del2.m,\n\tgeneral/genvarname.m, general/gradient.m, general/interp1.m,\n\tgeneral/interp2.m, general/interp3.m, general/interpft.m,\n\tgeneral/interpn.m, general/nargchk.m, general/nargoutchk.m,\n\tgeneral/nextpow2.m, general/num2str.m, general/pol2cart.m,\n\tgeneral/polyarea.m, general/prepad.m, general/quadgk.m,\n\tgeneral/quadl.m, general/quadv.m, general/rat.m,\n\tgeneral/repmat.m, general/shiftdim.m, general/structfun.m,\n\tgeneral/trapz.m, geometry/convhull.m, geometry/delaunay.m,\n\tgeometry/delaunay3.m, geometry/delaunayn.m, geometry/dsearch.m,\n\tgeometry/dsearchn.m, geometry/griddata.m, geometry/trimesh.m,\n\tgeometry/triplot.m, geometry/trisurf.m, geometry/voronoi.m,\n\tgeometry/voronoin.m, help/__makeinfo__.m, help/gen_doc_cache.m,\n\thelp/get_first_help_sentence.m, help/print_usage.m, help/type.m,\n\timage/brighten.m, image/colormap.m, image/image.m,\n\timage/imagesc.m, image/imfinfo.m, image/imshow.m,\n\timage/imwrite.m, image/ind2rgb.m, io/dlmwrite.m, io/fileread.m,\n\tio/strread.m, io/textread.m, linear-algebra/cond.m,\n\tlinear-algebra/condest.m, linear-algebra/ishermitian.m,\n\tlinear-algebra/onenormest.m, miscellaneous/bzip2.m,\n\tmiscellaneous/dir.m, miscellaneous/dos.m, miscellaneous/edit.m,\n\tmiscellaneous/gzip.m, miscellaneous/mkoctfile.m,\n\tmiscellaneous/orderfields.m, miscellaneous/parseparams.m,\n\tmiscellaneous/perl.m, miscellaneous/unix.m,\n\tmiscellaneous/unpack.m, miscellaneous/version.m,\n\tmiscellaneous/zip.m, optimization/fminbnd.m,\n\toptimization/fminunc.m, optimization/fsolve.m,\n\toptimization/glpk.m, optimization/glpkmex.m,\n\toptimization/lsqnonneg.m, optimization/optimget.m,\n\toptimization/optimset.m, optimization/pqpnonneg.m,\n\toptimization/private/__fdjac__.m, optimization/qp.m,\n\tpkg/get_forge_pkg.m, pkg/pkg.m, plot/__fltk_print__.m,\n\tplot/__gnuplot_print__.m, plot/ancestor.m, plot/area.m,\n\tplot/axes.m, plot/axis.m, plot/bar.m, plot/barh.m, plot/box.m,\n\tplot/caxis.m, plot/cla.m, plot/clabel.m, plot/close.m,\n\tplot/colorbar.m, plot/comet.m, plot/compass.m, plot/contour.m,\n\tplot/contour3.m, plot/contourc.m, plot/contourf.m,\n\tplot/cylinder.m, plot/ellipsoid.m, plot/ezcontour.m,\n\tplot/ezcontourf.m, plot/ezmesh.m, plot/ezmeshc.m, plot/ezplot.m,\n\tplot/ezplot3.m, plot/ezpolar.m, plot/ezsurf.m, plot/ezsurfc.m,\n\tplot/feather.m, plot/figure.m, plot/fill.m, plot/findall.m,\n\tplot/findobj.m, plot/fplot.m, plot/gcbo.m, plot/grid.m,\n\tplot/hggroup.m, plot/hidden.m, plot/line.m, plot/meshgrid.m,\n\tplot/ndgrid.m, plot/pareto.m, plot/patch.m, plot/pcolor.m,\n\tplot/peaks.m, plot/pie.m, plot/plotmatrix.m, plot/plotyy.m,\n\tplot/print.m, plot/private/__actual_axis_position__.m,\n\tplot/quiver.m, plot/quiver3.m, plot/refresh.m, plot/rose.m,\n\tplot/scatter.m, plot/scatter3.m, plot/shading.m, plot/slice.m,\n\tplot/specular.m, plot/sphere.m, plot/subplot.m, plot/surfl.m,\n\tplot/surfnorm.m, plot/text.m, plot/title.m, plot/view.m,\n\tplot/whitebg.m, plot/xlabel.m, plot/xlim.m, plot/ylabel.m,\n\tplot/ylim.m, plot/zlabel.m, plot/zlim.m, polynomial/compan.m,\n\tpolynomial/mkpp.m, polynomial/mpoles.m, polynomial/pchip.m,\n\tpolynomial/ppder.m, polynomial/ppint.m, polynomial/ppjumps.m,\n\tpolynomial/ppval.m, polynomial/spline.m, set/intersect.m,\n\tset/powerset.m, set/setdiff.m, set/setxor.m, set/union.m,\n\tset/unique.m, signal/fftshift.m, signal/filter2.m,\n\tsignal/ifftshift.m, sparse/bicgstab.m, sparse/cgs.m,\n\tsparse/etreeplot.m, sparse/gplot.m, sparse/pcg.m, sparse/pcr.m,\n\tsparse/spdiags.m, sparse/speye.m, sparse/sprand.m,\n\tsparse/sprandn.m, sparse/sprandsym.m, sparse/spstats.m,\n\tsparse/spy.m, sparse/treelayout.m, sparse/treeplot.m,\n\tspecfun/bessel.m, specfun/legendre.m, specfun/pow2.m,\n\tstatistics/base/center.m, statistics/base/histc.m,\n\tstatistics/base/kendall.m, statistics/base/meansq.m,\n\tstatistics/base/prctile.m, statistics/base/quantile.m,\n\tstatistics/base/range.m, statistics/base/std.m,\n\tstatistics/base/table.m, statistics/distributions/betacdf.m,\n\tstatistics/distributions/betarnd.m,\n\tstatistics/distributions/binornd.m,\n\tstatistics/distributions/cauchy_rnd.m,\n\tstatistics/distributions/chi2rnd.m,\n\tstatistics/distributions/discrete_rnd.m,\n\tstatistics/distributions/empirical_rnd.m,\n\tstatistics/distributions/exprnd.m,\n\tstatistics/distributions/fcdf.m,\n\tstatistics/distributions/frnd.m,\n\tstatistics/distributions/gamrnd.m,\n\tstatistics/distributions/geornd.m,\n\tstatistics/distributions/hygernd.m,\n\tstatistics/distributions/kolmogorov_smirnov_cdf.m,\n\tstatistics/distributions/laplace_rnd.m,\n\tstatistics/distributions/logistic_rnd.m,\n\tstatistics/distributions/lognrnd.m,\n\tstatistics/distributions/nbinrnd.m,\n\tstatistics/distributions/normrnd.m,\n\tstatistics/distributions/stdnormal_rnd.m,\n\tstatistics/distributions/tcdf.m,\n\tstatistics/distributions/trnd.m,\n\tstatistics/distributions/unidrnd.m,\n\tstatistics/distributions/unifcdf.m,\n\tstatistics/distributions/unifrnd.m,\n\tstatistics/distributions/wblcdf.m,\n\tstatistics/distributions/wblrnd.m,\n\tstatistics/tests/kolmogorov_smirnov_test.m,\n\tstatistics/tests/kolmogorov_smirnov_test_2.m,\n\tstatistics/tests/wilcoxon_test.m, strings/base2dec.m,\n\tstrings/index.m, strings/mat2str.m, strings/strchr.m,\n\tstrings/substr.m, strings/validatestring.m, testfun/assert.m,\n\ttestfun/example.m, testfun/fail.m, testfun/speed.m,\n\ttestfun/test.m, time/calendar.m, time/date.m, time/datenum.m,\n\ttime/datetick.m, time/datevec.m:\n\tGrammarcheck documentation of m-files.\n\n2010-07-17  Rik  <octave@nomad.inbox5.com>\n\n\t* audio/lin2mu.m, general/common_size.m, general/interp1.m,\n\tgeneral/interp2.m, general/interpn.m, general/quadl.m,\n\tgeometry/dsearchn.m, geometry/voronoi.m, geometry/voronoin.m,\n\timage/hsv2rgb.m, image/imread.m, image/rgb2hsv.m,\n\tlinear-algebra/commutation_matrix.m, linear-algebra/condest.m,\n\tlinear-algebra/expm.m, linear-algebra/krylov.m,\n\tlinear-algebra/onenormest.m, miscellaneous/perl.m,\n\tplot/linkprop.m, plot/plot.m, plot/print.m, plot/stem3.m,\n\tsignal/diffpara.m, signal/stft.m, sparse/pcg.m, sparse/pcr.m,\n\tspecfun/primes.m, special-matrix/hadamard.m, special-matrix/hankel.m,\n\tspecial-matrix/invhilb.m, special-matrix/pascal.m,\n\tspecial-matrix/rosser.m, special-matrix/toeplitz.m,\n\tspecial-matrix/vander.m, special-matrix/wilkinson.m,\n\ttestfun/speed.m: Spellcheck documentation.\n\n2010-07-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/flipdim.m: Suuport flipping about trailing singleton\n\tdimension.\n\n2010-07-14  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__gnuplot_print__.m: Fix broken options \"-orientation\",\n\t\"-special_flag\", \"-debug_file\", \"-tight_flag\", and \"-printer\".\n\n2010-07-14  Rik  <octave@nomad.inbox5.com>\n\n       * linear-algebra/normest.m: Improve documentation.  Add better input\n       validation.  Use same variable names in code as in documentation.\n\n2010-07-14  Marco Caliari  <marco.caliari@univr.it>\n\n       * linear-algebra/normest.m: Set the \"state\" of the random number\n       generator to trace(A).\n\n2010-07-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/cell2mat.m: Optimize so as to minimize the number of\n\tconcats.\n\n2010-07-12  John W. Eaton  <jwe@octave.org>\n\n\t* general/display.m: Print usage message if nargin != 1.\n\tBug #30421.\n\n2010-07-09  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* general/interp2.m: improve input argument handling and\n\tallow not equally spaced griddata (bug #29601)\n\n2010-07-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: Fix incorrect handling of nondefault fill\n\tvalues in min/max reductions of integers.\n\n2010-07-07  David Bateman  <dbateman@free.fr>\n\n\t* __next_line_color__.m: Allow conditional initialisation of the\n\tcolor_rotation variable.\n\t* __next_line_style__.m: Allow conditional initialisation of the\n\tstyle_rotation variable.\n\t* hold.m: Support \"hold all\".\n\t* newplot.m: Conditionally initialisation the line style and color\n\tbased on the __hold_all__ axes property.\n\n2010-07-04  Søren Hauberg  <hauberg@gmail.com>\n\n\t* polynomial/deconv.m: ensure that the orientation of the third\n\tinput to 'filter' matches the orientation of 'y'.\n\n2010-07-02  Rik  <octave@nomad.inbox5.com>\n\n\t* audio/wavread.m: Correctly handle non-word aligned data chunks.\n\t(bug #30309).\n\n2010-06-16  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/stairs.m: Add additional calling forms to documentation.\n\n2010-06-24  John W. Eaton  <jwe@octave.org>\n\n\t* plot/private/__plt__.m: Replace usage message with error.\n\t* plot/loglog.m, plot/plot.m, plot/polar.m, plot/semilogx.m,\n\tplot/semilogy.m: Call print_usage if no args are supplied.\n\tAdd additional calling forms to documentation.\n\n2010-06-24  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* plot/print.m: convert to wrapper for backend specific print functions\n\t* plot/__gnuplot_print__.m: New gnuplot specific print function,\n\tlargely based on the former print.m\n\t* plot/__fltk_print__.m: New fltk specific print function\n\t* plot/__print_parse_opts__.m: New option parser for print\n\tfunctions, largely based on the former print.m\n\t* plot/module.mk: Add new m-files here\n\n2010-06-23  David Bateman  <dbateman@free.fr>\n\n\t* whitebg.m: New function.\n\t* module.mk (plot_FCN_FILES): Add it here.\n\t* __go_draw_figure__.m: Set the border color to the inverse of the\n\tbackground color.\n\n2010-06-17  Brad Froehle  <brad.froehle@gmail.com>\n\n\t* sparse/spy.m: Fix typo.\n\n2010-06-16  Rik  <octave@nomad.inbox5.com>\n\n\t* set/union.m: Remove seealso reference to deprecated function.\n\n2010-06-16  Rik  <octave@nomad.inbox5.com>\n\n\t* @ftp/dir.m, @ftp/ftp.m, @ftp/mget.m, @ftp/mput.m, @ftp/rename.m,\n\tdeprecated/fstat.m, general/accumdim.m, general/interp1.m,\n\tlinear-algebra/ishermitian.m, linear-algebra/issymmetric.m,\n\tmiscellaneous/substruct.m, optimization/fminbnd.m,\n\toptimization/fsolve.m, plot/bar.m, plot/daspect.m, plot/pbaspect.m,\n\tplot/print.m, polynomial/mkpp.m, polynomial/ppval.m, set/union.m,\n\tsignal/unwrap.m, specfun/nthroot.m: Periodic grammar check of\n\tdocumentation to ensure a common format.\n\n2010-06-14  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/image.m: Flip data, rather than y-axis, for images.  (bug #30033)\n\n2010-06-12  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/scatter.m: New demo.\n\t* plot/private/__scatter__.m: Properly set default value markersize\n\tand marker type.\n\n2010-06-12  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/scatter.m: Add new calling forms of function to documentation.\n\n2010-06-10  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__scatter__.m, plot/scatter.m: Honor Matlab color\n\tsettings.\n\t* general/prepad.m: Fix typo 'dimm' -> 'dim'.\n\n2010-06-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/vec.m: Remove (make built-in).\n\t* linear-algebra/module.mk: Update.\n\n2010-06-09  Rik  <octave@nomad.inbox5.com>\n\n\t* general/flipdim.m, general/accumdim.m: Use > 1 test to find\n\tfirst non-singleton dimension rather than != 1.\n\n2010-06-08  Rik  <octave@nomad.inbox5.com>\n\n\t* general/cumtrapz.m, general/postpad.m, general/prepad.m,\n\tgeneral/shift.m, general/trapz.m, signal/unwrap.m: Use common\n\tmethod to find first non-singleton dimension.\n\n2010-06-08  Rik  <octave@nomad.inbox5.com>\n\n\t* general/rotdim.m: Modify function to use same variable names\n\tas documentation.\n\n2010-06-08  Rik  <octave@nomad.inbox5.com>\n\n\t* general/cart2pol.m, general/cart2sph.m, general/pol2cart.m,\n\tgeneral/sph2cart.m: Add option to operate on column matrix of\n\tcoordinates.\n\n2010-06-08  Rik  <octave@nomad.inbox5.com>\n\n\t* general/arrayfun.m, general/cart2pol.m, general/cart2sph.m,\n\tgeneral/idivide.m, general/logspace.m, general/sph2cart.m,\n\tgeneral/structfun.m, image/imagesc.m, io/csvread.m, io/csvwrite.m,\n\tlinear-algebra/cond.m, linear-algebra/condest.m,\n\tlinear-algebra/isdefinite.m, linear-algebra/null.m,\n\tlinear-algebra/orth.m, miscellaneous/list_primes.m,\n\toptimization/fminunc.m, optimization/fzero.m, path/matlabroot.m,\n\tplot/axis.m, plot/plot.m, plot/semilogx.m, plot/semilogxerr.m,\n\tplot/semilogy.m, plot/semilogyerr.m, plot/stem.m, polynomial/poly.m,\n\tpolynomial/polyder.m, polynomial/polyderiv.m, polynomial/polyfit.m,\n\tpolynomial/polyout.m, polynomial/polyval.m, set/ismember.m,\n\tsparse/spfun.m, specfun/betaln.m, statistics/base/mean.m,\n\tstatistics/base/median.m, statistics/base/mode.m, statistics/base/ols.m,\n\tstatistics/base/ranks.m,\n\tstatistics/distributions/kolmogorov_smirnov_cdf.m,\n\tstatistics/distributions/wblpdf.m: Improve documentation strings\n\n2010-06-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pkg/pkg.m: Support pkg list -forge.\n\n2010-06-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pkg/get_forge_pkg.m: New function.\n\t* pkg/module.mk: Add it here.\n\t* pkg/pkg.m: Support -forge switch for auto-downloading OctaveForge\n\tpackages.\n\n2010-06-03  Alois Schlögl\n\n\t* signal/arch_test.m, statistics/tests/bartlett_test.m,\n\tstatistics/tests/chisquare_test_homogeneity.m,\n\tstatistics/tests/chisquare_test_independence.m,\n\tstatistics/tests/manova.m, statistics/tests/mcnemar_test.m,\n\tstatistics/tests/run_test.m, statistics/distributions/chi2pdf.m:\n\tReplace calls to obsolete chisquare_cdf with chi2cdf.\n\n2010-06-03  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/private/__plt__.m: Add newline to usage message.\n\n2010-06-02  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/sqp.m: Overhaul sqp code.\n\tGuarantee equivalent results if sqp called with or wihout bounds\n\t(bug #29989).  Simplify input option handling and add %tests\n\tto check validation code.  Rewrite documentation string.\n\n2010-06-01  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/fminbnd.m: Remove unused persistent variable.\n\n2010-06-01  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/private/__contour__.m: Correctly size X and Y when only Z\n\tspecified (bug #30002).\n\n2010-05-31  Rik  <octave@nomad.inbox5.com>\n\n\t* specfun/legendre.m: Orient row vector correctly (bug #29997).\n\tAdd input validation for negative values and %tests to check\n\tvalidation routines.\n\n2010-05-30  Rik  <octave@nomad.inbox5.com>\n\n\t* sparse/svds.m: Overhaul code.\n\tReturn smallest singular values if sigma == 0 (Bug #29721).\n\tAvoid calculating U and V matrices unless requested.\n\tCorrectly handle zero matrix input.\n\tImprove documentation string.\n\n2010-05-26  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/base/histc.m, statistics/base/iqr.m,\n\tstatistics/base/kurtosis.m, statistics/base/mode.m,\n\tstatistics/base/ranks.m, statistics/base/run_count.m,\n\tstatistics/base/skewness.m, statistics/base/statistics.m,\n\tstatistics/base/studentize.m: Improve validation of input arguments.\n\n2010-05-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* specfun/isprime.m: Fix and further optimize.\n\n2010-05-26  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/legend.m: Improve documentation string.\n\n2010-05-26  Rik  <octave@nomad.inbox5.com>\n\n\t* sparse/svds.m: Check struct input arguments.  Overhaul documentation.\n\n2010-05-26  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/legend.m: Key labels for specified objects.\n\t* plot/ancestor.m: Support vectors of handles.\n\n2010-05-26  Rik  <octave@nomad.inbox5.com>\n\n\t* sparse/svds.m: Initialize ARPACK starting vector in svds test code.\n\tBug #29721.\n\n2010-05-25  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/spline.m: Ignore NaNs within input vectors.\n\n2010-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* specfun/primes.m: Use logical masks rather than numeric.\n\t* specfun/isprime.m: Rewrite using isprime.\n\n2010-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/unimplemented.m: Don't mention onCleanup (supported).\n\n2010-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/base/median.m: Ensure NaNs where needed. Simplify first\n\tnon-singleton dimension computation.\n\n2010-05-24  Rik  <octave@nomad.inbox5.com>\n\n\t* general/private/__isequal__.m, image/image.m,\n\tstatistics/base/ranks.m: Replace calls to deprecated functions.\n\n2010-05-23  Rik  <octave@nomad.inbox5.com>\n\n\t* image/imshow.m: Scale image point color according to colormap.\n\tBug #29926.\n\n2010-05-16  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/semilogx.m, plot/semilogy.m: Plot minor ticks for semilog plots.\n\n2010-05-16  Rik  <octave@nomad.inbox5.com>\n\n\t* audio/loadaudio.m, audio/playaudio.m, audio/saveaudio.m,\n\taudio/wavread.m, general/bicubic.m, general/bitcmp.m, general/bitget.m,\n\tgeneral/bitset.m, general/cplxpair.m, general/del2.m,\n\tgeneral/gradient.m, general/interp2.m, general/interp3.m,\n\tgeneral/interpn.m, general/postpad.m, general/prepad.m,\n\tgeneral/private/__splinen__.m, image/image_viewer.m, image/imagesc.m,\n\timage/saveimage.m, linear-algebra/expm.m, linear-algebra/krylov.m,\n\tmiscellaneous/edit.m, miscellaneous/private/__xzip__.m,\n\tmiscellaneous/what.m, optimization/glpk.m, optimization/optimset.m,\n\toptimization/pqpnonneg.m, path/pathdef.m, plot/__go_draw_axes__.m,\n\tplot/__marching_cube__.m, plot/gnuplot_drawnow.m, plot/ishold.m,\n\tplot/isocolors.m, plot/isonormals.m, plot/print.m,\n\tplot/private/__add_datasource__.m, plot/private/__color_str_rgb__.m,\n\tplot/private/__errplot__.m, plot/private/__interp_cube__.m,\n\tplot/shading.m, plot/specular.m, polynomial/deconv.m,\n\tpolynomial/polyint.m, polynomial/ppint.m, set/powerset.m,\n\tsignal/arch_fit.m, signal/arch_test.m, signal/durbinlevinson.m,\n\tspecial-matrix/hadamard.m, statistics/distributions/unidrnd.m,\n\tstatistics/distributions/unifinv.m,\n\tstatistics/models/logistic_regression.m, strings/strjust.m,\n\ttestfun/rundemos.m, testfun/runtests.m, testfun/test.m, time/datenum.m:\n\tPrint name of function in error() string messages.\n\n2010-05-16  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/contourc.m, plot/private/__contour__.m,\n\tplot/surface.m, plot/surfnorm.m: Check input\n\targuments for size and type (bug #29861).\n\n2010-05-13  John W. Eaton  <jwe@octave.org>\n\n\t* help/help.m: Avoid unnecessary use of varargout.\n\n2010-05-13   Qianqian Fang  <fangq>\n\n\t* miscellaneous/tempdir.m: Add filesep to end of tempdir (bug #29864).\n\n2010-05-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* io/textread.m: Fix typo.\n\n2010-05-08  David Gesswein  <djg@pdp8online.com>\n\n\t* io/dlmwrite.m: Correctly set output precision (#29870).\n\n2010-05-12  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* help/help.m: Allow docstring to be returned as output, and\n\tcorrect docstring.\n\n2010-05-08  Rik  <octave@nomad.inbox5.com>\n\n\t* testfun/test.m: Don't abort testing when skipping a testif block\n\n2010-05-05  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/tests/cor_test.m, statistics/tests/t_test.m,\n\tstatistics/tests/t_test_2.m, statistics/tests/t_test_regression.m,\n\tstatistics/tests/welch_test.m: Replace deprecated function calls.\n\tPatch provided by Alois Schlögl.\n\n2010-05-02  Rik  <octave@nomad.inbox5.com>\n\n\t* linear-algebra/cond.m: Add TeX equation to documentation\n\n2010-05-02  Peter van den Biggelaar  <peter@biglr.net>\n\n\t* plot/close.m: No error on \"close([])\".\n\n2010-05-01  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Remove gnuplot errorbar code.\n\n2010-04-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/loglogerr.m, plot/semilogxerr.m, plot/semilogyerr.m:\n\tAdd demos.\n\t* plot/private/__errplot__.m: Fix bug parsing errorbar style.\n\t* plot/private/__errplot__.m: Implement errorbars in the Matlab style.\n\n2010-04-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/errorbar.m: Modify demo.\n\t* plot/private/__errplot__.m: Fix bug for boxxy errorbar.\n\t* plot/errorbar.m: Add demos.\n\n2010-04-27  David Bateman  <dbateman@free.fr>\n\n\t* plot/private/__errplot__.m: Update the marker in a seperate\n\tlistener function.\n\n2010-04-27  Rik  <octave@nomad.inbox5.com>\n\n\t* plot/private/__go_draw_axes__.m: Use \".\" for marker when plotting\n\twith errorbars.  (bug #29057)\n\n2010-04-27  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__errplot__.m: Add missing semicolon line terminations.\n\n2010-04-27  David Bateman  <dbateman@free.fr>\n\n\t* plot/private/__default_plot_options_.m: New option errorstyle.\n\t* plot/private/__pltopt__.m: Use errorstyle here seperately from\n\tthe linestyle so that both can be set.\n\t* plot/private/__errcomm__.m: Allow for the fact that matrices\n\tto __errplot__ with return a vector of handles.\n\t* plot/private/__errplot__.m: Allow for default linestyles.\n\n\t* plot/private/__errplot__.m: Set the errorbar marker to \"none\".\n\n2010-04-26  David Bateman  <dbateman@free.fr>\n\n\t* plot/bar.m: Document the use of the colormap for the color of\n\tthe bars.\n\n\t* plot/private/__errplot__.m: Allow x, box and xy errorbars with\n\tdifferent syntax.\n\n\t* plot/private/__errplot__.m: Allow matlab style linestyles, and\n\tsupport setting the markers.\n\n2010-04-24  David Bateman  <dbateman@free.fr>\n\n\t* plot/private/__patch__.m: Correct order of calling setdata and\n\tsetvertexdata.\n\n2010-04-25  Ben Abbott  <bpabbot@mac.com>\n\n\t* plot/__go_draw_figure__.m: Hidden axes may have visible children.\n\n2010-04-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: Set figure color property to 'none' when printing.\n\n2010-04-24  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Correct fill of diamond markers\n\n2010-04-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Consistent placement of axes for ps vs\n\tother gnuplot terminals.\n\n2010-04-23  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/colorbar.m: Fix colorbar() bugs for manual plotboxaspectratio.\n\t* plot/axis.m: For 'axis normal' restore plotboxaspectratio.\n\n2010-04-23  John W. Eaton  <jwe@octave.org>\n\n\t* gethelp.cc (extract_help_text): Use C++ static_cast instead of\n\tC-style cast.\n\n2010-04-23  Rik  <octave@nomad.inbox5.com>\n\n\t* audio/loadaudio.m, audio/mu2lin.m, audio/playaudio.m,\n\taudio/saveaudio.m, audio/wavread.m, audio/wavwrite.m,\n\tdeprecated/cellidx.m, deprecated/intwarning.m,\n\tdeprecated/lchol.m, deprecated/spatan2.m, deprecated/spchol.m,\n\tdeprecated/spchol2inv.m, deprecated/spcholinv.m,\n\tdeprecated/spcumprod.m, deprecated/spcumsum.m,\n\tdeprecated/spdet.m, deprecated/spdiag.m, deprecated/spfind.m,\n\tdeprecated/spinv.m, deprecated/spkron.m, deprecated/splchol.m,\n\tdeprecated/split.m, deprecated/splu.m, deprecated/spmax.m,\n\tdeprecated/spmin.m, deprecated/spprod.m, deprecated/spqr.m,\n\tdeprecated/spsum.m, deprecated/spsumsq.m, elfun/lcm.m,\n\tgeneral/bicubic.m, general/cell2mat.m, general/circshift.m,\n\tgeneral/cplxpair.m, general/cumtrapz.m, general/dblquad.m,\n\tgeneral/del2.m, general/gradient.m, general/idivide.m,\n\tgeneral/int2str.m, general/interp1.m, general/interp2.m,\n\tgeneral/interp3.m, general/interpn.m, general/isa.m,\n\tgeneral/num2str.m, general/postpad.m, general/prepad.m,\n\tgeneral/private/__isequal__.m, general/quadgk.m,\n\tgeneral/quadl.m, general/quadv.m, general/rat.m,\n\tgeneral/rotdim.m, general/shift.m, general/sortrows.m,\n\tgeneral/structfun.m, general/trapz.m, geometry/griddata.m,\n\tgeometry/griddata3.m, geometry/inpolygon.m, geometry/rectint.m,\n\tgeometry/trimesh.m, geometry/triplot.m, geometry/trisurf.m,\n\tgeometry/voronoi.m, help/doc.m, help/help.m, help/which.m,\n\tio/dlmwrite.m, io/strread.m, linear-algebra/condest.m,\n\tlinear-algebra/cross.m, linear-algebra/krylov.m,\n\tlinear-algebra/null.m, linear-algebra/onenormest.m,\n\tlinear-algebra/orth.m, linear-algebra/rank.m,\n\tlinear-algebra/rref.m, miscellaneous/bincoeff.m,\n\tmiscellaneous/cast.m, miscellaneous/compare_versions.m,\n\tmiscellaneous/copyfile.m, miscellaneous/dir.m,\n\tmiscellaneous/dump_prefs.m, miscellaneous/edit.m,\n\tmiscellaneous/fileattrib.m, miscellaneous/fileparts.m,\n\tmiscellaneous/fullfile.m, miscellaneous/license.m,\n\tmiscellaneous/ls.m, miscellaneous/ls_command.m,\n\tmiscellaneous/mkoctfile.m, miscellaneous/movefile.m,\n\tmiscellaneous/orderfields.m, miscellaneous/perl.m,\n\tmiscellaneous/run.m, miscellaneous/substruct.m,\n\tmiscellaneous/swapbytes.m, miscellaneous/tar.m,\n\tmiscellaneous/unpack.m, miscellaneous/what.m,\n\tmiscellaneous/zip.m, optimization/fminunc.m,\n\toptimization/fsolve.m, optimization/glpk.m, optimization/qp.m,\n\toptimization/sqp.m, path/pathdef.m, path/savepath.m, pkg/pkg.m,\n\tplot/__gnuplot_get_var__.m, plot/__gnuplot_ginput__.m,\n\tplot/__go_draw_axes__.m, plot/__next_line_color__.m,\n\tplot/__next_line_style__.m, plot/__plt_get_axis_arg__.m,\n\tplot/ancestor.m, plot/area.m, plot/axes.m, plot/axis.m,\n\tplot/box.m, plot/cla.m, plot/clabel.m, plot/clf.m, plot/close.m,\n\tplot/colorbar.m, plot/comet.m, plot/compass.m, plot/contourf.m,\n\tplot/cylinder.m, plot/ellipsoid.m, plot/feather.m, plot/fill.m,\n\tplot/findobj.m, plot/fplot.m, plot/gnuplot_drawnow.m,\n\tplot/grid.m, plot/gtext.m, plot/hidden.m, plot/hist.m,\n\tplot/hold.m, plot/ishold.m, plot/isonormals.m,\n\tplot/isosurface.m, plot/legend.m, plot/linkprop.m, plot/meshz.m,\n\tplot/newplot.m, plot/pareto.m, plot/pie.m, plot/plot3.m,\n\tplot/plotmatrix.m, plot/plotyy.m, plot/polar.m,\n\tplot/private/__actual_axis_position__.m,\n\tplot/private/__add_datasource__.m,\n\tplot/private/__axes_limits__.m, plot/private/__axis_label__.m,\n\tplot/private/__bar__.m, plot/private/__clabel__.m,\n\tplot/private/__contour__.m, plot/private/__errcomm__.m,\n\tplot/private/__errplot__.m, plot/private/__ezplot__.m,\n\tplot/private/__patch__.m, plot/private/__plt__.m,\n\tplot/private/__pltopt__.m, plot/private/__quiver__.m,\n\tplot/private/__scatter__.m, plot/private/__stem__.m,\n\tplot/refreshdata.m, plot/ribbon.m, plot/rose.m, plot/slice.m,\n\tplot/sombrero.m, plot/sphere.m, plot/stairs.m, plot/subplot.m,\n\tplot/surf.m, plot/surface.m, plot/surfl.m, plot/surfnorm.m,\n\tplot/text.m, plot/view.m, polynomial/polyderiv.m,\n\tpolynomial/polygcd.m, polynomial/polyout.m, polynomial/spline.m,\n\tset/intersect.m, set/setdiff.m, set/setxor.m, signal/unwrap.m,\n\tsparse/pcg.m, sparse/pcr.m, sparse/spaugment.m,\n\tsparse/spconvert.m, sparse/sprand.m, sparse/sprandsym.m,\n\tsparse/svds.m, sparse/treelayout.m, sparse/treeplot.m,\n\tspecfun/nchoosek.m, specfun/primes.m, special-matrix/toeplitz.m,\n\tstatistics/base/iqr.m, statistics/base/kurtosis.m,\n\tstatistics/base/qqplot.m, statistics/base/quantile.m,\n\tstatistics/base/ranks.m, statistics/base/run_count.m,\n\tstatistics/base/skewness.m, statistics/base/statistics.m,\n\tstatistics/base/studentize.m, statistics/base/var.m,\n\tstatistics/distributions/betapdf.m,\n\tstatistics/distributions/betarnd.m,\n\tstatistics/distributions/binocdf.m,\n\tstatistics/distributions/binoinv.m,\n\tstatistics/distributions/binornd.m,\n\tstatistics/distributions/cauchy_pdf.m,\n\tstatistics/distributions/cauchy_rnd.m,\n\tstatistics/distributions/chi2rnd.m,\n\tstatistics/distributions/discrete_rnd.m,\n\tstatistics/distributions/exprnd.m,\n\tstatistics/distributions/fcdf.m,\n\tstatistics/distributions/finv.m,\n\tstatistics/distributions/fpdf.m,\n\tstatistics/distributions/frnd.m,\n\tstatistics/distributions/gampdf.m,\n\tstatistics/distributions/gamrnd.m,\n\tstatistics/distributions/geornd.m,\n\tstatistics/distributions/hygepdf.m,\n\tstatistics/distributions/laplace_inv.m,\n\tstatistics/distributions/lognrnd.m,\n\tstatistics/distributions/nbincdf.m,\n\tstatistics/distributions/nbininv.m,\n\tstatistics/distributions/nbinpdf.m,\n\tstatistics/distributions/nbinrnd.m,\n\tstatistics/distributions/normrnd.m,\n\tstatistics/distributions/poissinv.m,\n\tstatistics/distributions/poissrnd.m,\n\tstatistics/distributions/tinv.m,\n\tstatistics/distributions/tpdf.m,\n\tstatistics/distributions/trnd.m,\n\tstatistics/distributions/unidrnd.m,\n\tstatistics/distributions/unifrnd.m,\n\tstatistics/distributions/wblpdf.m,\n\tstatistics/distributions/wblrnd.m, strings/cstrcat.m,\n\tstrings/deblank.m, strings/findstr.m, strings/isstrprop.m,\n\tstrings/regexptranslate.m, strings/strtok.m, testfun/assert.m,\n\ttestfun/example.m, testfun/fail.m, testfun/rundemos.m,\n\ttestfun/runtests.m, testfun/speed.m, testfun/test.m,\n\ttime/datestr.m, time/weekday.m: Untabify.\n\n2010-04-23  Rik  <octave@nomad.inbox5.com>\n\n\t* geometry/griddata.m, geometry/griddatan.m, geometry/tsearchn.m:\n\tReplace nan with NaN for nice visual cue.\n\n2010-04-23  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/gplot.m: Eliminate parsing error for NaN inside\n\tof matrix declaration.\n\n2010-04-22  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/sqp.m: Return correct value (101) on succes.\n\tFixes bug #29577.\n\n2010-04-22  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/glpk.m: Eliminate repmat (Inf, x , y) and just\n\tuse Inf (x,y).\n\n2010-04-22  Rik  <octave@nomad.inbox5.com>\n\n\t* general/rat.m, sparse/gplot.m, strings/base2dec.m,\n\tgeometry/triplot.m, optimization/sqp.m, optimization/qp.m,\n\tstatistics/base/run_count.m, statistics/base/ranks.m:\n\tEliminate NaN*ones and Inf*ones constructs and just use Nan()\n\tand Inf().\n\n2010-04-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/colorbar.m: Allow 'peer' option to be specified.\n\t* plot/colorbar.m: Consistent treatment of plotboxaspectratio, and\n\tadd listener for plotboxaspectratiomode.\n\t* plot/axis.m: Consistent treatment of plotboxaspectratio.\n\t* plot/__go_draw_axes__.m: Consistently determine axes position.\n\n2010-04-17  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/private/__actual_axis_position__.m: Fix bug when restoring\n\tfigure position property to its original value.\n\n2010-04-16  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_figure__.m: Pass bg_is_set to __go_draw_axes__. Don't\n\tunset the background figure color.\n\t* plot/__go_draw_axes__.m: Unset the background figure color here.\n\n\t* statistics/distributions/*: Replace constructs like \"NaN * one()\"\n\twith \"NaN()\" and  \"Inf * ones ()\" with \"Inf()\".\n\n2010-04-15  David Bateman  <dbateman@free.fr>\n\n\t* statistics/distributions/discrete_pdf.m: Reimplement using lookup.\n\t* statistics/distributions/discrete_inv.m: Reimplement using lookup.\n\t* statistics/distributions/discrete_cdf.m: typo in last patch.\n\n2010-04-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/distributions/stdnormal_cdf.m: Calculate using erfc.\n\n2010-04-13  David Bateman  <dbateman@free.fr>\n\n\t* statistics/discrete_cdf.m: Reimplement using lookup.\n\n2010-04-13  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* plot/__fltk_ginput__.m: New functions, implement ginput for\n\tfltk backend.\n\n2010-04-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* sparse/spalloc.m: Remove.\n\t* sparse/module.mk: Update.\n\n2010-04-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/plotyy.m: Add listener for dataaspectratiomode.\n\n2010-04-12  Ben Abbott  <bpabbot@mac.com>\n\n\t* plot/loglog.m: Minor ticks on by default for loglog plots.\n\t* plot/__plt_get_axis_arg__.m, plot/newplot.m: Respect the nextplot\n\tproperty value of 'new' for axes and 'replacechildren' for axes and\n\tfigures.\n\n2010-04-10  Ben Abbott  <bpabbot@mac.com>\n\n\t* plot/__go_draw_figure__.m: Don't set background for non-visible axes.\n\n2010-04-07  John W. Eaton  <jwe@octave.org>\n\n\t* testfun/runtests.m: New function.\n\t* testfun/module.mk (testfun_FCN_FILES): Add it to the list.\n\n2010-02-19  Rik  <octave@nomad.inbox5.com>\n\n\t* statistics/cut.m: Modify cut to use the same decision criteria\n\tas histc when deciding whether a data point is inside or outside\n\tinterval.\n\n2010-04-02  Marc Vinyals  <mrc_timer@users.sourceforge.net>\n\n\t* signal/arma_rnd.m: fix typo in test.\n\n2010-04-02  Marc Vinyals  <mrc_timer@users.sourceforge.net>\n\n\t* signal/arma_rnd.m: fix typo in test.\n\n2010-03-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* specfun/factor.m: Use rem to check divisibility.\n\n2010-03-27  Ben Abbott  <bpabbot@mac.com>\n\n\t* plot/__go_draw_figure__.m: Untabify.\n\t* plot/print.m: Provide default suffixes & validate hardcopy format.\n\n2010-03-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fzero.m: Handle the breakdown if initial bracketing\n\tcontains an exact root. Improve docstring.\n\n2010-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/module.mk: Add unimplemented.m here.\n\n2010-03-25  Ben Abbott  <bpabbot@mac.com>\n\n\t* general/cell2mat.m: Add test for cells of cells.\n\n2010-03-24  Petr Mikulik  <mikulik@physics.muni.cz>\n\n\t* plot/__go_draw_axes__.m: Unset logscale also for unused gnuplot\n\taxis locations.\n\n2010-03-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* help/help.m: Maybe warn about unimplemented Matlab functions.\n\n2010-03-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/unimplemented.m: New function.\n\n2010-03-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/cell2mat.m: Support cells of cells.\n\n2010-03-23  John W. Eaton  <jwe@octave.org>\n\n\t* plot/refreshdata.m: Don't use cell2mat on cell array of cell arrays.\n\n2010-03-22  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/gmap40.m, image/hot.m, image/hsv2rgb.m, image/image.m,\n\timage/image_viewer.m, image/imfinfo.m, image/imread.m, image/imshow.m,\n\timage/saveimage: Detabify.\n\n2010-03-21  Søren Hauberg  <hauberg@gmail.com>\n\n\t* general/quadv.m: Replace 'quadl' with 'quadv' in help text.\n\n2010-03-20  Søren Hauberg  <hauberg@gmail.com>\n\n\t* general/interp2.m: For nearest neighbour interpolation ceil\n\t(instead of floor) at the center of the data intervals to be\n\tcompatible with Matlab.  Add test.\n\t* general/interpn.m: Ditto.\n\n2010-03-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strmatch.m (strtrimr): Rewrite for correct behavior.\n\tAdd test.\n\n2010-03-18  Petr Mikulik  <mikulik@physics.muni.cz>\n\n\t* plot/print.m: Add '-append' option.\n\n2010-03-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: print.m: Detabify.\n\n2010-03-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/nthroot.m: Remove.\n\t* general/module.mk: Update.\n\t* specfun/nthroot.m: New source.\n\t* specfun/module.mk: Update.\n\n2010-03-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/intwarning.m: Deprecate.\n\n2010-03-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/index.m: Make it a wrapper for strfind.\n\n2010-03-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strchr.m: Optimize.\n\n2010-03-05  Søren Hauberg  <hauberg@gmail.com>\n\n\t* pkg/pkg.m (write_index): include classes in autogenerated\n\tINDEX files.\n\n2010-03-05  Søren Hauberg  <hauberg@gmail.com>\n\n\t* plot/fplot.m: Ensure that 'limits' is a 2 or 4 vector, and\n\tthat 'fn' is a function.\n\n2010-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* testfun/test.m: Support catching warnings and errors by IDs.\n\n2010-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumdim.m: Optimize the summation case.\n\n2010-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumdim.m: New function.\n\n2010-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fzero.m: Avoid division by zero.\n\n2010-03-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fminbnd.m: Fix tests.\n\n2010-03-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fminbnd.m: Fix termination tolerances.\n\n2010-03-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* polynomial/convn.m: Remove.\n\t* polynomial/module.mk: Update.\n\n2010-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* set/unique.m: If the argument is sparse and we are not\n\toperating on rows and we don't need indices, convert nonzero\n\telements to a full matrix and work on that instead, converting\n\tback to sparse when done.\n\n2010-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* set/unique.m: Return 0x1 arrays for empty arrays with some\n\tnonzero dimensions.  Return object with the same class as the\n\targument.  New tests.\n\n2010-02-27  Liam Groener  <liamg@mac.com>\n\n\t* time/datetick.m: Fix 'keepticks' bug, and untabify.\n\n2010-02-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/str2double.m: Remove.\n\n2010-02-24  John W. Eaton  <jwe@octave.org>\n\n\t* plot/private/__contour__.m (get_lvl_eps): New function.\n\tHandle case of single level value.  Use sqrt (eps) instead of 1e-6.\n\t(update_text, add_patch_children): Use it.\n\n2010-02-19  Rik  <octave@nomad.inbox5.com>\n\n\t* optimization/fzero.m: Add test for discontinuity at the end.\n\n2010-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* image/imfinfo.m: Don't handle file time stamp here.\n\n2010-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/base/center.m: Convert integer inputs to doubles.\n\n2010-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/interp2: Slightly optimize linear interpolation.\n\n2010-02-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/interp2: Remove debug stub.\n\n2010-02-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/optimget.m: Simplify.\n\n2010-02-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/parseparams.m: Extend to allow direct parsing of\n\toptions.\n\n2010-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fminbnd.m: Undocument impossible info values.\n\t* optimization/fzero.m: Ditto.\n\n\t* optimization/fzero.m: Make default TolX consistent with fminbnd.\n2010-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fminbnd.m: New function.\n\t* optimization/module.mk: Add it here.\n\t* optimization/fzero.m: Make default TolX consistent with fminbnd.\n\n2010-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/private/__isequal__.m: Remove list-related stub.\n\n2010-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* image/imshow.m: Allow logical values for images.\n\n2010-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: Use != instead of diff to compare indices in\n\tdense case. Set explicit mode in sparse case to aid optimization.\n\n2010-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/menu.m: Use sscanf rather than eval.\n\n2010-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/substruct.m: Vectorize.\n\n2010-02-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: Document complexity.\n\n2010-02-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: Add new test that also forces index cache\n\tgeneration for faster sorting.\n\n2010-02-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: 1 more small fix.\n\n2010-02-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: Small fixes.\n\n2010-02-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: Rewrite. Split sparse and dense case. Treat\n\tcell-valued subs efficiently. Optimize dense case for @sum, @max and\n\t@min. Optimize the @(x){x} reduction. Add tests.\n\n2010-02-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/dir.m: Fix month passed to datenum.\n\n2010-02-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/private/__isequal__.m: Handle function handles.\n\n2010-02-01  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m (get_old_gnuplot_color): Remove as\n\tno longer used (for gnuplot 4.0).\n\n\t* plot/private/__scatter__.m: Treat \"flat\" colored patches as\n\ta single patch.\n\t* plot/__go_draw_axes__.m: If a patch object is flat, treat its\n\toutline with the gnuplot \"palette\".\n\n2010-01-30  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* statistics/tests/kruskal_wallis_test.m: Replace chisquare_cdf\n\tby chi2cdf.\n\n2010-01-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/axis.m, plot/__go_draw_axes__.m, plot/colorbar.m,\n\tplot/isocolors.m, plot/isonormals.m, plot/isosurface.m,\n\tplot/plotyy.m, plot/polar.m, plot/surfl.m,\n\tplot/private/__actual_axis_position.m:\n\tReplace dataaspectratio and dataaspectratiomode properties with\n\tplotboxaspectratio and plotboxaspectratio properties.\n\n2010-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/compan.m, polynomial/conv.m, polynomial/deconv.m,\n\tpolynomial/mpoles.m, polynomial/polyderiv.m,\n\tpolynomial/polygcd.m, polynomial/polyout.m,\n\tpolynomial/polyreduce.m, polynomial/polyval.m,\n\tpolynomial/polyvalm.m, polynomial/residue.m:\n\tPoint to polyint in @seealso, not polyinteg.\n\n\t* deprecated/module.mk (deprecated_FCN_FILES):\n\tRemove delete files from the list.\n\n\t* deprecated/beta_cdf.m, deprecated/beta_inv.m,\n\tdeprecated/beta_pdf.m, deprecated/beta_rnd.m,\n\tdeprecated/binomial_cdf.m, deprecated/binomial_inv.m,\n\tdeprecated/binomial_pdf.m, deprecated/binomial_rnd.m,\n\tdeprecated/chisquare_cdf.m, deprecated/chisquare_inv.m,\n\tdeprecated/chisquare_pdf.m, deprecated/chisquare_rnd.m,\n\tdeprecated/clearplot.m, deprecated/com2str.m,\n\tdeprecated/exponential_cdf.m, deprecated/exponential_inv.m,\n\tdeprecated/exponential_pdf.m, deprecated/exponential_rnd.m,\n\tdeprecated/f_cdf.m, deprecated/f_inv.m, deprecated/f_pdf.m,\n\tdeprecated/f_rnd.m, deprecated/gamma_cdf.m,\n\tdeprecated/gamma_inv.m, deprecated/gamma_pdf.m,\n\tdeprecated/gamma_rnd.m, deprecated/geometric_cdf.m,\n\tdeprecated/geometric_inv.m, deprecated/geometric_pdf.m,\n\tdeprecated/geometric_rnd.m, deprecated/hypergeometric_cdf.m,\n\tdeprecated/hypergeometric_inv.m,\n\tdeprecated/hypergeometric_pdf.m,\n\tdeprecated/hypergeometric_rnd.m, deprecated/intersection.m,\n\tdeprecated/is_bool.m, deprecated/is_complex.m,\n\tdeprecated/is_list.m, deprecated/is_matrix.m,\n\tdeprecated/is_scalar.m, deprecated/is_square.m,\n\tdeprecated/is_stream.m, deprecated/is_struct.m,\n\tdeprecated/is_symmetric.m, deprecated/is_vector.m,\n\tdeprecated/lognormal_cdf.m, deprecated/lognormal_inv.m,\n\tdeprecated/lognormal_pdf.m, deprecated/lognormal_rnd.m,\n\tdeprecated/meshdom.m, deprecated/normal_cdf.m,\n\tdeprecated/normal_inv.m, deprecated/normal_pdf.m,\n\tdeprecated/normal_rnd.m, deprecated/pascal_cdf.m,\n\tdeprecated/pascal_inv.m, deprecated/pascal_pdf.m,\n\tdeprecated/pascal_rnd.m, deprecated/poisson_cdf.m,\n\tdeprecated/poisson_inv.m, deprecated/poisson_pdf.m,\n\tdeprecated/poisson_rnd.m, deprecated/polyinteg.m,\n\tdeprecated/struct_contains.m, deprecated/struct_elements.m,\n\tdeprecated/t_cdf.m, deprecated/t_inv.m, deprecated/t_pdf.m,\n\tdeprecated/t_rnd.m, deprecated/uniform_cdf.m,\n\tdeprecated/uniform_inv.m, deprecated/uniform_pdf.m,\n\tdeprecated/uniform_rnd.m, deprecated/weibull_cdf.m,\n\tdeprecated/weibull_inv.m, deprecated/weibull_pdf.m,\n\tdeprecated/weibull_rnd.m, deprecated/wiener_rnd.m:\n\tDelete functions deprecated in version 3.0.0.\n\n\t* deprecated/weibcdf.m, deprecated/weibinv.m,\n\tdeprecated/weibpdf.m, deprecated/weibrnd.m:\n\tNote that Matlab still has these functions, so they probabl\n\tshould not be removed with other functions deprecated in 3.0.0.\n\n2010-01-28  Ben Abbott  <bpabbot@mac.com>\n\n\t* plot/daspect.m, plot/pbaspect.m: New functions.\n\n2010-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* general/Makefile.am (general_FCN_FILES): Add chop.m to the list.\n\n2010-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/isstr.m, deprecated/clg.m, deprecated/setstr.m:\n\tNote that Matlab still has these functions, so they probabl\n\tshould not be removed with other functions deprecated in 3.0.0.\n\n2010-01-27  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* plot/gnuplot_drawnow.m: Add \"emf\" to the list of enhanced\n\tterminals for the gnuplot backend.\n\n2010-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* general/chop.m: New function.\n\n2010-01-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Support TypicalX, autoscale only if\n\tAutoScaling is on, off by default. Fix default tolerances.\n\t* optimization/fminunc.m: Support TypicalX, autoscale only if\n\tAutoScaling is on, off by default Fix default tolerances..\n\t* optimization/private/__fdjac__.m: Accept typicalx as a parameter.\n\n2010-01-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/pqpnonneg.m: If Cholesky update failed, switch off\n\tupdating but continue.\n\n2010-01-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pkg/pkg.m: More complement -> setdiff changes.\n\n2010-01-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pkg/pkg.m: Use setdiff rather than complement.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* gethelp.cc: Untabfy.\n\n2010-01-20  Ben Abbott  <bpabbot@mac.com>\n\n\t* plot/__go_draw_figure__.m: Reverse order axes are drawn.\n\n2010-01-20  David Bateman  <dbateman@free.fr>\n\n\t* plot/private/__contour__.m: Set default linestyle if pltopt returns\n\tan empty style.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* time/datetick.m: Make form arg optional.\n\tFrom Philip Nienhuis  <pr.nienhuis@hccnet.nl>.\n\n2010-01-20  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Correct an error in drawing of patch\n\tobjects where unrequested markers were drawn.\n\n\t* plot/__go_draw_figure__.m: Also plot white foreground and\n\tbackground colors.\n\t* plot/plotyy.m: Set axes colors to \"none\".\n\n\t* plot/__go_draw_axes__.m (next_marker):  Remove and all uses of\n\tthis function.\n\tPartially respect the markeredgecolor and markerfacecolor properties.\n\t* plot/private/__color__str_rgb__.m: New function\n\t* plot/module.mk: Add it here.\n\t* plot/__next_line_style__.m: New function selected next line style\n\tusing the axes linestyleorder property.\n\t* plot/__next_line_color.m: Increment next line style here.\n\t* plot/newplot.m: Reset next line style here.\n\t* plot/module.mk: Add __next_line_style__.m here.\n\t* plot/plot3.m: Use __next_line_style__ here.\n\t* plot/private/plt.m: And here.\n\t* plot/private/stem.m: And here.\n\t* plot/private/scatter.m: And here. Correctly handle nargin == 3. Use\n\tmatlab compatible edgecolor, markeredgecolor and markerfacecolor\n\tproperty values.\n\t* plot/private/pltopt.m: Remove \"@\" marker as an option.\n\t* plot/private/__default_plot_options__.m: Default plot options\n\tare empty signalling that __next_line_color__ and\n\t__next_line_style should be used.\n\n2010-01-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/structfun.m: Error when invalid options are specified.\n\n2010-01-19  Jaroslav Hajek  <highegg@gmail.com>, Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* general/structfun.m: Correctly support multiple arguments with\n\tnon-uniform output. Correct test for non-uniform output.\n\n2010-01-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* help/print_usage.m: Try determining whether called from top level.\n\tIf not, don't print additional help and enable backtrace instead.\n\n2010-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* testfun/test.m: Undo previous change.\n\n2010-01-18  David Grundberg  <davidg@cs.umu.se>\n\n\t* testfun/test.m: Append endfunction to function test blocks.\n\n2010-01-17  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* general/celldisp.m: Add example, add demo.\n\n\t* general/structfun.m, miscellaneous/getfield.m,\n\tmiscellaneous/orderfields.m, miscellaneous/setfield.m,\n\tmiscellaneous/substruct.m: Update documentation string.\n\n2010-01-16  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m (next_marker):  New function to find a\n\tnew marker. Use it to support the \"@\" marker.\n\t* plot/private/__pltopt__.m: Don't convert \"@\" marker ro \"+\";\n\n2010-01-15  David Bateman  <dbateman@free.fr>\n\n\tplot/__go_draw_figure__.m: Respect the figure and axes color\n\tproperties.\n\n2010-01-14  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m:  Fix for markerfacecolor and\n\tmarkeredgecolor for unfillable points like '+'.\n\n2010-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* io/fileread.m: Add missing semicolon.\n\n2010-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strcmpi.m: Remove.\n\t* strings/strncmpi.m: Remove.\n\t* strings/module.mk: Update.\n\n2010-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/inputname.m: Use isvarname instead of regexp.\n\n2010-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/inputname.m: Return \"\" if argument name is not a\n\tvalid identifier.  Update docstring.\n\n2010-01-12  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes_.m:  Allow patch markerfacecolor and\n\tmarkeredgecolor properties to be used and set the marker colors\n\tappropriately.\n\n2010-01-12  Jaroslav Hajek  <highegg@gmail.com>\n\t    Ben Barrowes  <benjamin.e.barrowes@usace.army.mil>\n\n\t* set/private/validargs.m: New function.\n\t* set/module.mk: Add it here.\n\t* set/ismember.m: Use it here.\n\t* set/intersect.m: Ditto.\n\t* set/union.m: Ditto.\n\t* set/setdiff.m: Ditto.\n\t* set/setxor.m: Ditto.\n\n2010-01-11  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Update DOCSTRINGS rules to avoid\n\tsimple_move_if_change_rule and allow Make to update timestamps.\n\n2010-01-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* plot/private/__scatter__.m: Use patch objects instead of lines,\n\tswitch at 100 points.\n\n2010-01-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* plot/private/__scatter__.m: Fix typos.\n\n2010-01-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* io/fileread.m: New source.\n\n2010-01-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* plot/private/__scatter__.m: Use alternative strategy for larger\n\tpoint sets.\n\n2010-01-06  Ben Abbott  <bpabbott@mac.com>\n\n\t* optimization/qp.m: Add missing semicolon.\n\n2010-01-11  Ben Barrowes  <benjamin.e.barrowes@usace.army.mil>\n\n\t* set/: allow set scripts to handle cell inputs\n\n2010-01-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/qp.m: Supply default values on request and register\n\toptions.\n\n2010-01-05  John W. Eaton  <jwe@octave.org>\n\n\t* qp.m: Allow linear term and constraint arguments to be\n\toptional.\n\n2010-01-05  Joshua Redstone  <redstone@gmail.com>\n\n\t* qp.m: Handle optimset options struct argument.\n\n2010-01-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strmatch.m: Optimize.\n\n2010-01-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strrep.m: Remove.\n\t* strings/module.mk: Update.\n\n2010-01-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Support old style jacobian passing.\n\n2010-01-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* set/powerset.m: New function.\n\t* set/module.mk: Include it.\n\n2009-12-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/common_size.m: Use named function rather than a handle.\n\n2009-12-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* set/complement.m: Deprecate.\n\n2009-12-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strcat.m: Further simplify.\n\n2009-12-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/common_size.m: Optimize.\n\n2009-12-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strcat.m: Vectorize.\n\n2009-12-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/xor.m: Optimize.\n\n2009-12-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/issquare.m: Do not check type.\n\t* linear-algebra/issymmetric.m: Strengthen test.\n\t* linear-algebra/ishermitian.m: Strengthen test.\n\n2009-12-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strfind.m: Remove.\n\t* strings/module.mk: Update.\n\n2009-12-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strjust.m: Rewrite.\n\n2009-12-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strjust.m: Special-case string and empty argument.\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Eliminate TOPDIR variable in favor of built-in automake\n\tvariables of top_builddir and top_srcdir.\n\n2009-12-18  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Use Automake syntax to build helper program gethelp\n\n2009-12-17  Rik  <octave@nomad.inbox5.com>\n\n\t* testfun/test.m: Add newline to message output.\n\n2009-12-14  John W. Eaton  <jwe@octave.org>\n\n\t* specfun/isprime.m: Produce logical result.  Error if nargin > 1.\n\tNew tests.\n\n2009-12-14  John W. Eaton  <jwe@octave.org>\n\n\t* help/__makeinfo__.m: Use fullfile to concatenate file name\n\tcomponents.  Use hyphens instead of underscores in tmp file name.\n\n2009-12-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* help/__makeinfo__.m: Use P_tmpdir to create temporary file.\n\n2009-12-09  Rik  <octave@nomad.inbox5.com>\n\n\t* polynomial/module.mk: Correct typo and distribute newly\n\tcreated ppder.m.\n\n2009-12-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ppder.m: New function.\n\t* ppint.m: New function.\n\t* ppjumps.m: New function.\n\n2009-12-09  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: remove install-images target and use automake\n\tsyntax to distribute image data.\n\n2009-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (DOCSTRINGS): Use $(cp_update_rule) instead of\n\tcp -a --update.\n\n2009-12-09  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Copy DOCSTRINGS from srcdir to builddir if it does not\n\texist.  Enables VPATH builds.\n\n2009-12-08  Petr Mikulik  <mikulik@physics.muni.cz>\n\n\t* plot/gnuplot_drawnow.m: Prune prompt lines from dumb terminal output.\n\t* plot/__go_draw_figure__.m: Add missing 'unset multiplot' to restore\n\thotkey and mouse functionality for 2D plots.\n\n2009-12-09  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Distribute DOCSTRINGS in tar.gz file.\n\t* mkdoc: Pass current directory, \"./\", when running mkdoc on\n\tlocal files.\n\n2009-12-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/interp1q.m: Use more optimal code.\n\n2009-12-08  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (DOCSTRINGS): Depend on $(GEN_FCN_FILES) instead\n\tof $(FCN_FILES_IN).  Pass $(GEN_FCN_FILES) to mkdoc instead of\n\t$(FCN_FILES_IN).  Use mv instead of $(simple_move_if_change_rule).\n\t(EXTRA_DIST): Include  $(GEN_FCN_FILES) in the list.\n\n2009-12-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/interp1.m: Allow discontinuities (jumps) for the\n\t\"nearest\" and \"linear\" methods.  Document the feature and add a\n\tfew tests.\n\n2009-12-06  Rik  <rik@nomad.inbox5.com>\n\n\t* Makefile.am: Distribute DOCSTRINGS so that documentation will\n\tnot require rebuild after merely untarring a distribution.\n\t* mkdoc: Change output to refer to mfiles as \"scripts/...\" rather than\n\t\"$srcdir/...\".  Otherwise, distributed DOCSTRINGS file will not match\n\tDOCSTRINGS created under a VPATH build and documentation will be\n\tunnecessarily rebuilt.\n\n2009-12-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* set/ismember.m: Simplify.\n\n2009-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* audio/wavwrite.m: Delete generated a.wav file after each test.\n\n\t* Makefile.am (DIRSTAMP_FILES, DISTCLEANFILES): New variables.\n\t(DOCSTRINGS): Also depend on $(FCN_FILES_IN).  Pass\n\t$(FCN_FILES_IN) to mkdoc instead of $(GEN_FCN_FILES).  Tell mkdoc\n\tto look for $(FCN_FILES_IN) files in $(srcdir), not build\n\tdirectory.\n\t(DISTCLEANFILES): New variable.\n\tDon't silence dirstamp, DOCSTRINGS, $(GEN_FCN_FILES), and PKG_ADD\n\trules.\n\n\t* audio/module.mk, deprecated/module.mk, elfun/module.mk,\n\thelp/module.mk, general/module.mk, geometry/module.mk,\n\timage/module.mk, io/module.mk, linear-algebra/module.mk,\n\tmiscellaneous/module.mk, @ftp/module.mk, optimization/module.mk,\n\tpath/module.mk, pkg/module.mk, plot/module.mk,\n\tpolynomial/module.mk, set/module.mk, signal/module.mk,\n\tsparse/module.mk, specfun/module.mk, special-matrix/module.mk,\n\tstartup/module.mk, statistics/base/module.mk,\n\tstatistics/distributions/module.mk, statistics/models/module.mk,\n\tstatistics/tests/module.mk, strings/module.mk, testfun/module.mk,\n\ttime/module.mk: Append to DIRSTAMP_FILES.\n\n2009-12-02  Rik  <rik@nomad.inbox5.com>\n\n\t* image/imread.m: Run test case only if underlying GraphicMagick\n\tlibrary exists.\n\n2009-12-02  John W. Eaton  <jwe@octave.org>\n\n\t* help/module.mk: Fix typo in previous change.\n\n2009-12-01  John W. Eaton  <jwe@octave.org>\n\n\t* help/module.mk (help_PRIVATE_FCN_FILES): New list.\n\t(help_FCN_FILES): Remove new private functions from the list.\n\tInclude $(help_PRIVATE_FCN_FILES) in the list.\n\t* help/private/__additional_help_message__.m: Rename from\n\thelp/__additional_help_message__.m.\n\n\t* statistics/base/module.mk (statistics_base_FCN_FILES):\n\tRemove statistics/base/__quantile__.m from the list.\n\t* statistics/base/__quantile__.m: Now a subfunction of\n\tstatistics/base/quantile.m.\n\t* statistics/base/quantile.m: Remove redundant tests.\n\n\t* miscellaneous/__xzip__.m: Comment out tests until we have a way\n\tto test private functions directly.\n\n\t* general/isequal.m, general/isequalwithequalnans.m:\n\tConvert tests from __isequal__.\n\n\t* optimization/module.mk (optimization_PRIVATE_FCN_FILES): New list.\n\t(optimization_FCN_FILES): Remove new private functions and new\n\tsubfunctions from the list.  Include\n\t$(optimization_PRIVATE_FCN_FILES) in the list.\n\n\t* optimization/private/__fdjac__.m: Rename from\n\toptimization/__fdjac__.m.\n\n\t* optimization/__dogleg__.m: Now a subfunction of path/fsolve.m.\n\t* optimization/__doglegm__.m: Now a subfunction of path/fminunc.m.\n\n\t* general/module.mk (general_PRIVATE_FCN_FILES): New list.\n\t(general_FCN_FILES): Remove new private functions from the list.\n\tInclude $(general_PRIVATE_FCN_FILES) in the list.\n\n\t* general/private/__isequal__.m: Rename from general/__isequal__.m.\n\t* general/private/__splinen__.m: Rename from general/__splinen__.m.\n\n\t* image/module.mk (image_FCN_FILES): Remove image/__img__.m and\n\timage/__img_via_file__.m from the list.\n\n\t* image/__img__.m: Now a subfunction of image/image.m.\n\t* image/__img_via_file__.m: Now a subfunction of image_viewer.m.\n\n\t* path/module.mk (path_FCN_FILES): Remove path/__extractpath__.m\n\tfrom the list.\n\n\t* path/__extractpath__.m: Now a subfunction of path/pathdef.m.\n\n\t* miscellaneous/module.mk (miscellaneous_PRIVATE_FCN_FILES): New list.\n\t(miscellaneous_FCN_FILES): Remove __xzip__.m from the list.\n\tInclude $(miscellaneous_PRIVATE_FCN_FILES) in the list.\n\n\t* miscellaneous/private/__xzip__.m: Rename from\n\tmiscellaneous/__xzip__.m.\n\n2009-12-01  David Bateman  <dbateman@free.fr>\n\n\t* @ftp/ftp.m: Treat empty constructor and construction from\n\tanother FTP object.\n\t* @ftp/loadobj.m: Allow and remove the matlab specific fields\n\tof FTP objects allowing matlab FTP objects to be loaded in Octave.\n\t* @ftp/display.m: user -> username.\n\n2009-12-01  John W. Eaton  <jwe@octave.org>\n\n\t* plot/module.mk (plot_PRIVATE_FCN_FILES): New list.\n\t(plot_FCN_FILES): Include $(plot_PRIVATE_FCN_FILES) in the list.\n\tRemove new private functions and new subfunctions from the list.\n\n\t* plot/private/__actual_axis_position__.m: Rename from\n\tplot/__actual_axis_position__.m.\n\t* plot/private/__add_datasource__.m: Rename from\n\tplot/__add_datasource__.m.\n\t* plot/private/__axes_limits__.m: Rename from plot/__axes_limits__.m.\n\t* plot/private/__axis_label__.m: Rename from plot/__axis_label__.m.\n\t* plot/private/__bar__.m: Rename from plot/__bar__.m.\n\t* plot/private/__clabel__.m: Rename from plot/__clabel__.m.\n\t* plot/private/__contour__.m: Rename from plot/__contour__.m.\n\t* plot/private/__default_plot_options__.m: Rename from\n\tplot/__default_plot_options__.m.\n\t* plot/private/__errcomm__.m: Rename from plot/__errcomm__.m.\n\t* plot/private/__errplot__.m: Rename from plot/__errplot__.m.\n\t* plot/private/__ezplot__.m: Rename from plot/__ezplot__.m.\n\t* plot/private/__interp_cube__.m: Rename from plot/__interp_cube__.m.\n\t* plot/private/__line__.m: Rename from plot/__line__.m.\n\t* plot/private/__patch__.m: Rename from plot/__patch__.m.\n\t* plot/private/__plt__.m: Rename from plot/__plt__.m.\n\t* plot/private/__pltopt__.m: Rename from plot/__pltopt__.m.\n\t* plot/private/__quiver__.m: Rename from plot/__quiver__.m\n\t* plot/private/__scatter__.m: Rename from plot/__scatter__.m.\n\t* plot/private/__stem__.m: Rename from plot/__stem__.m.\n\n\t* plot/__pltopt1__.m: Now a subfunction of plot/__pltopt__.m.\n\n\t* plot/__bars__.m: Now a subfunction of plot/__bar__.m.\n\t* plot/__bar__.m (bars): Rename from __bars__.\n\t(__bar__): Call bars insteaad of __bars__.\n\n\t* plot/__area__.m: Now a subfunction of plot/area.m.\n\n\t* plot/__plr1__.m, plot/__plr2__.m: Now subfunctions of polar.m.\n\n\t* plot/__plt1__.m, plot/__plt2__.m, plot/__plt2mm__.m,\n\tplot/__plt2mv__.m, plot/__plt2ss__.m, plot/__plt2sv__.m,\n\tplot/__plt2vm__.m, plot/__plt2vs__.m, plot/__plt2vv__.m:\n\tNow subfunctions of __plt__.m.\n\n2009-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* mkdoc: Handle classes in function names.\n\n2009-11-27  David Bateman  <dbateman@free.fr>\n\n\t* @ftp/ascii.m, @ftp/binary.m, @ftp/cd.m, @ftp/close.m,\n\t@ftp/delete.m, @ftp/dir.m, @ftp/display.m, @ftp/ftp.m,\n\t@ftp/loadobj.m, @ftp/mget.m, @ftp/mkdir.m, @ftp/module.mk,\n\t@ftp/mput.m, @ftp/rename.m, @ftp/rmdir.m, @ftp/saveobj.m: New files\n\t* Makefile.am: Add the @ftp to the build.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/cross.m: Avoid doing indexing twice.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/normest.m: Randomize initial vector.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/dot.m: Remove.\n\t* linear-algebra/module.mk: Update.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/qp.m: Fix matrix tests.\n\t* optimization/condest.m: Ditto.\n\t* optimization/krylov.m: Ditto.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* sparse/normest.m: Move to linear-algebra.\n\t* linear-algebra/normest.m: Simplify. Don't form A'*A explicitly.\n\n2009-11-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/isdefinite.m: Use Cholesky factorization.\n\n2009-11-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/issymmetric.m: Move to linear-algebra.\n\t* general/isdefinite.m: Ditto.\n\t* linear-algebra/issymmetric.m: Use 0 as default tolerance. Optimize\n\tthis case. Check for symmetry, not hermitianness.\n\t* linear-algebra/ishermitian.m: New function.\n\t* linear-algebra/isdefinite.m: Use ishermitian instead of issymmetric.\n\n2009-11-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/cellidx.m: Deprecate.\n\n2009-11-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/issquare.m: Change to return consistent result for empty\n\tmatrices.\n\n2009-11-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/cell2mat.m: Check type of all elements. Slightly optimize.\n\tAdd tests.\n\n2009-11-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: Use num2cell instead of mat2cell. Use repmat.\n\n2009-11-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* script/miscellaneous/getfield: Deblank field names, gripe on invalid\n\tindex.\n\t* script/miscellaneous/setfield: Rewrite using subsasgn.\n\n2009-11-22  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/print.m: Properly set the default ghostscript_binary\n\tunder Windows. Modify the search for the ghostscript binary\n\tso that it works for Win32, mingw, Cygwin, and Unix systems.\n\n2009-11-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/dec2base.m: Fix division.\n\n2009-11-20  Lukas Reichlin  <lukas.reichlin@swissonline.ch>\n\n\t* linear-algebra/krylov.m: Add missing swap routine.\n\n2009-11-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/__isequal__.m: Check for isnumeric|islogical.\n\t* testfun/assert.m: Ditto.\n\n2009-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* specfun/perms.m: Avoid recursion. Simplify assignments. Allow empty\n\tvectors.\n\n2009-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* specfun/erfinv.m: Remove.\n\t* specfun/module.mk: Update.\n\n2009-11-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/orient.m: Flip papersize and paperposition when orientation\n\tchanges. Add support for 'tall' option. Add tests.\n\n2009-11-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* io/textread.m: strncmp->strcmpi.\n\n2009-11-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/expm.m: Fix typo.\n\n2009-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/intwarning.m: Doc fix.\n\n2009-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* plot/stairs.m (__stairs__): Correct nargin check.  New demos.\n\tFrom Jakub Kasse  <jakub.kasse@tul.cz>.\n\n2009-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* help/help.m (help): Return immediately after calling do_contents.\n\t(do_contents): Find all matching directories, not just the first.\n\tCall get_help_text_from_file to avoid looking in path.\n\tHandle printing here.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am, audio/module.mk, deprecated/module.mk,\n\telfun/module.mk, general/module.mk, geometry/module.mk,\n\thelp/module.mk, image/module.mk, io/module.mk,\n\tlinear-algebra/module.mk, miscellaneous/module.mk,\n\toptimization/module.mk, path/module.mk, pkg/module.mk,\n\tplot/module.mk, polynomial/module.mk, set/module.mk,\n\tsignal/module.mk, sparse/Makefile.in, specfun/Makefile.in,\n\tspecial-matrix/Makefile.in, startup/Makefile.in,\n\tstatistics/Makefile.in, statistics/base/module.mk,\n\tstatistics/distributions/module.mk, statistics/models/module.mk,\n\tstatistics/tests/module.mk, strings/module.mk, testfun/module.mk,\n\ttime/module.mk: New files.\n\t* Makefile.in, move-if-change, configure.ac, audio/Makefile.in,\n\tdeprecated/Makefile.in, elfun/Makefile.in, general/Makefile.in,\n\tgeometry/Makefile.in, help/Makefile.in, image/Makefile.in,\n\tio/Makefile.in, linear-algebra/Makefile.in,\n\tmiscellaneous/Makefile.in, optimization/Makefile.in,\n\tpath/Makefile.in, pkg/Makefile.in, plot/Makefile.in,\n\tpolynomial/Makefile.in, set/Makefile.in, signal/Makefile.in,\n\tskip-autoheader, sparse/module.mk, specfun/module.mk,\n\tspecial-matrix/module.mk, startup/module.mk,\n\tstatistics/base/Makefile.in, statistics/distributions/Makefile.in,\n\tstatistics/models/Makefile.in, statistics/tests/Makefile.in,\n\tstrings/Makefile.in, testfun/Makefile.in, time/Makefile.in:\n\tDelete.\n\t* mk-pkg-add: Rename from mkpkgadd.\n\t* mkdoc, mk-pkg-addd: Operate on explicit lists of files instead\n\tof directory names.\n\t* mkdoc: Skip files not ending in .m.\n\n2009-11-10  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: No 'with linestyle' when linestyle == 'none'.\n\n2009-11-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/arrayfun.m: Fix nargout=0 case.\n\n2009-11-08  Petr Mikulik  <mikulik@physics.muni.cz>\n\n\t* plot/gnuplot_drawnow.m: Support gnuplot's dumb terminal.\n\n2009-11-02  Stefan Hepp  <stefan@stefant.org>\n\n\t* plot/gnuplot_drawnow.m (gnuplot_default_term): Don't set term to\n\tx11 unless DISPLAY is set.\n\n2009-11-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/interp1.m: Simplify.\n\n2009-11-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* polynomial/mkpp.m: Improve Matlab compatibility.\n\t* polynomial/ppval.m: Ditto.\n\t* polynomial/unmkpp: Update.\n\t* polynomial/pchip.m: Update and optimize.\n\t* polynomial/spline.m: Update.\n\t* general/__splinen__.m: Update.\n\n2009-10-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/tril.m, general/triu.m: Remove sources.\n\t* general/Makefile.in: Update.\n\n2009-10-20  Søren Hauberg  <hauberg@gmail.com>\n\n\t* general/interp2.m: improved error checking and support for bicubic\n\tinterpolation when X and Y are meshgrid format.\n\n2009-10-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/interp1.m: Perform optimizations, improve code (use switch\n\tinstead of multiple ifs).\n\t* polynomial/pchip.m: Employ more optimized formulas (from SLATEC).\n\n2009-10-22  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/autumn.m, image/bone.m, image/cool.m, image/copper.m,\n\timage/flag.m, image/gmap40.m, image/gray.m, image/hot.m,\n\timage/hsv.m, image/jet.m, image/ocean.m, image/pink.m,\n\timage/prism.m, image/rainbow.m, image/spring.m, image/summer.m,\n\timage/white.m, image/winter.m: Add demos.\n\n2009-10-20  Søren Hauberg  <hauberg@gmail.com>\n\n \t* general/interp2.m: improved error checking and support for bicubic\n\n2009-10-19  Søren Hauberg  <hauberg@gmail.com>\n\n\t* io/strread.m, io/textread.m: New functions.\n\n2009-10-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/base/center.m: Rewrite using bsxfun.\n\n2009-10-15  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Allow line and surface markerfacecolor\n\tand markeredgecolor properties to be used and set the marker colors\n\tappropriately.\n\n2009-10-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/base/median.m: Rewrite using nth_element.\n\n2009-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* image/__img__.m: Adjust xlim and ylim correctly.\n\n2009-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (plot/gnuplot_binary.m): New rule.\n\t(DOCSTRINGS): Depend on plot/gnuplot_binary.m.\n\t(ALL_M_FILES): Define with =, not :=.\n\n2009-10-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* geometry/griddata.m: Fix handling vector xi, yi.\n\n2009-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/arrayfun.m: Simplify.\n\n2009-09-30  John W. Eaton  <jwe@octave.org>\n\n\t* mkdoc: Work on list of file names instead of a directory.\n\t* Makefile.in (ALL_M_FILES): Don't strip directories.\n\tAlso search build directory if it is different from $(srcdir).\n\tPass $(ALL_M_FILES) to mkdoc.\n\n2009-09-30  Michael D. Godfrey  <godfrey@isl.stanford.edu>\n\n\t* plot/clabel.m: Spelling fix.\n\t* plot/newplot.m: Update docstring.\n\n2009-09-28  John W. Eaton  <jwe@octave.org>\n\n\t* general/sortrows.m: Also use old algorithm for sparse matrices.\n\n2009-09-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* set/union.m: Fix docstring.\n\t* set/setxor.m: Fix docstring.\n\n2009-09-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/randperm.m: Remove.\n\t* general/Makefile.in: Update.\n\n2009-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* confiugre.ac: Rename from configure.in\n\t* Makefile.in: Rename all instances of configure.in to\n\tconfigure.ac.\n\n2009-09-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/Makefile.in: Include __doglegm__.m.\n\n2009-09-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fminunc.m: Simplify damped BFGS calculation.\n\n2009-09-09  Tatsuro Matsuoka  <tmacchant@yahoo.co.jp>\n\n\t* plot/gnuplot_drawnow.m: Avoid flickering windows by avoding\n\t'set multiplot' / 'unset multiplot' for gnuplot's windows and\n\twxt terminals.\n\n2009-09-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/__dogleg__.m: Revert to revision 22c8272af34b.\n\t* optimization/__doglegm__.m: New source.\n\t* optimization/fminunc.m: Use it.\n\n2009-09-08  John W. Eaton  <jwe@octave.org>\n\n\t* io/dlmwrite.m: Fix typo.\n\n2009-09-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Change initial TR step strategy.\n\t* optimization/fminunc.m: Change initial TR step strategy.\n\n2009-09-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fminunc.m: Correct extra output params handling.\n\n2009-09-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Update initial factor.\n\t* optimization/fminunc.m: Update initial factor.\n\n2009-09-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/arrayfun.m: Fix test.\n\n2009-09-05  John W. Eaton  <jwe@octave.org>\n\n\t* plot/hold.m: Correctly toggle hold state.  Set both figure and\n\taxes \"nextplot\" property when turning hold state on.\n\t* plot/ishold.m: Check figure and axes nextplot properties.\n\tAccept axes or figure handle argument.\n\n2009-09-01  Christophe Tournery  <christophe.tournery@illusonic.com>\n\n\t* audio/wavread.m: Rename data_size from obsolete ck_size.\n\n2009-08-31  David Bateman  <dbateman@free.fr>\n\n\t* general/quadgk.m: More care with the interval length and\n\tconvergence of contour integrals.\n\n2009-08-29  John W. Eaton  <jwe@octave.org>\n\n\t* time/datestr.m: Add missing semicolon.\n\n2009-08-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/int2str.m: Convert to double before calling log10.\n\n2009-08-26  E. Joshua Rigler  <relgire@gmail.com>\n\n\t* time/datestr.m: Set tm.isdst to -1 before calling mktime.\n\n2009-08-25  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__gnuplot_open_stream__.m: Save pid in __plot_stream__ property.\n\t* plot/gnuplot_drawnow.m: Wait for gnuplot subprocess when printing.\n\tFrom Ben Abbott <bpabbott@mac.com>, Rob Mahurin <rob@utk.edu>, and\n\tDmitri Sergatskov <dasergatskov@gmail.com>.\n\n2009-08-22  David Bateman  <dbateman@free.fr>\n\n\t* plot/__add_datasource__.m: Correct test for \"datasource\" argument\n\t* plot/__countour__.m: Add edgecolor properties and make it an alias\n\tfor linecolor with the value \"auto\" being \"flat\" for the edgecolor.\n\n2009-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* help/print_usage.m: Make it work again if an argument is given.\n\n2009-08-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* help/print_usage: Allow calling from methods.\n\n2009-08-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/diff.m: Remove.\n\t* general/Makefile.in: Update.\n\n2009-08-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/flipdim.m: Fix omitted check.\n\n2009-08-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/flipdim.m: Simplify.\n\n2009-08-07  Olli Saarela  <olli.saarela@gmail.com>\n\n\t* plot/__gnuplot_ginput__.m: If read fails to return data, sleep\n\tbefore trying again.\n\n2009-08-06  John W. Eaton  <jwe@octave.org>\n\n\t* plot/compass.m, plot/feather.m: Simplify argument processing.\n\n2009-08-06  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/base/std.m: Correctly work along singleton dimension.\n\tFrom Christoph Ellenberger <C.Ellenberger@gmx.net>.\n\n2009-08-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* geometry/griddata.m: Optimize.\n\n2009-08-06  Olaf Till  <olaf.till@uni-jena.de>\n\n\t* geometry/griddata.m: Linearize arrays.\n\n2009-08-04  Pieter Eendebak  <pieter.eendebak@gmail.com>\n\n\t* set/setxor.m: Added test for cell arrays of strings.\n\n2009-08-05  Olli Saarela  <olli.saarela@gmail.com>\n\n\t* plot/__gnuplot_get_var__.m: If read fails to return data, sleep\n\tbefore trying again.\n\n2009-08-04  Pieter Eendebak  <pieter.eendebak@gmail.com>\n\n\t* set/setxor.m: Support cell arrays of strings.\n\n2009-08-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/sub2ind.m: Remove source.\n\t* general/ind2sub.m: Remove source.\n\t* general/Makefile.in: Update.\n\n2009-08-02  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Avoid the flickering x11 window seen with\n\trapid replots by avoidng setting multiplot mode. This fix only\n\tfunctions for a single axes with no image objects.\n\t* plot/__go_draw_figure__.m: Move 'set multiplot' to gnuplot_drawnow.\n\n2009-07-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/common_size: Optimize.\n\n2009-07-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Fix ticklabels specified as 2D character\n\tarray.\n\t* plot/__go_draw_axes__.m: Ignore fontnames for the Lua-TikZ terminal.\n\t* plot/gnuplot_drawnow.m: Support the gnuplot terminal Lua-TikZ.\n\t* plot/print.m: Support the gnuplot terminal Lua-TikZ.\n\n2009-07-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* plot/gnuplot_binary.m: Fix typo.\n\n2009-07-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fzero.m: Use \"global\" parameter in str2func.\n\t* optimization/fsolve.m: Ditto.\n\t* optimization/fminunc.m: Ditto.\n\n2009-07-24  John W. Eaton  <jwe@octave.org>\n\n\t* plot/gnuplot_binary.in: Accept arguments in addition to program name.\n\t* plot/__gnuplot_open_stream__.m: Pass additional args to gnuplot.\n\n2009-07-23  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/legend.m: Add an hggroup demo using bar(). Include clf()\n\tin each demo.\n\n2009-07-23  John W. Eaton  <jwe@octave.org>\n\n\t* image/imread.m: Fix test.\n\n\t* plot/legend.m: Process arguments in order, child objects in\n\treverse.  Remove special case for single label.  New demos.\n\n2009-07-23  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* testfun/assert.m: Fix string comparison bug.\n\n2009-07-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* testfun/assert.m: Use less strict checking for exact matches.\n\n2009-07-17  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Use \"layer\" property to decide whether\n\tto send \"set border front\" or \"set border layerdefault\" to plot\n\tstream.  Don't send \"set border front\" to plot stream for image data.\n\n2009-07-15  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* polynomial/conv.m: Fix Matlab incompatibility.  New tests.\n\n2009-07-09  John W. Eaton  <jwe@octave.org>\n\n\t* plot/axis.m: Return 4-element vector for 2-d view.\n\tFrom David Woodburn <david.woodburn@gmail.com>.\n\n\t* sparse/nonzeros.m: Always return a column vector.  New tests.\n\n2009-06-25  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Apply feature 'wxt_has_size'.\n\t* plot/__gnuplot_has_feature__.m: Add feature 'wxt_has_size' for\n\tgnuplot >= 4.3.0.\n\n2009-06-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_figure__.m: Modify the implicit margin when gnuplot's\n\toutput is landscape.\n\t* plot/gnuplot_drawnow.m: Simplify handling of the figure's paper\n\tproperties, and rely upon listeners for units conversion. Minor code\n\timprovements.\n\t* plot/print.m: Reimplement -landscape and -portrait to modify the\n\tproperties papersize and paperposition. Produce compatible results\n\twhen paperpositionmode=='auto'. Simplfy units conversion and\n\trestoration of initial figure properties.\n\n2009-06-24  Marco Caliari  <marco.caliari@univr.it>\n\n\t* general/repmat.m: Call kron, not spkron.\n\n2009-06-24  Alexander Mamonov  <mamonov@gmail.com>\n\n\t* plot/plot3.m: Correctly compute offsets for property/value pairs.\n\n2009-06-23  Alexander Mamonov  <mamonov@gmail.com>\n\n\t* image/imread.m: New test.\n\n2009-06-22  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/grid.m: Add missing semi-colon. Allow grid to be toggled\n\ton/off for each axis independently. Gnuplot requires that minor\n\tticks accompany minor ticks. Add demo.\n\t* plot/__go_draw_axes__.m: For {x,y,z}scale == 'log' use 10 minor\n\tticks.\n\n2009-06-22  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/base/var.m: Return zero for scalar case.  Handle\n\tempty arguments in a Matlab compatible way.  New tests.\n\n2009-06-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* set/ismember.m: Properly handle NaNs. Fix test.\n\n2009-06-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Change the default x11 fontspec from '*,0'\n\tto ',0' to avoid delays searching the fontpath for a font named '*'.\n\n2009-06-18  Daniel Gualberto  <daniel@alacer.com.br>\n\n\t* polynomial/mpoles.m: Fix infinite loop for a multiplicity of\n\tpoles at zero. Test added.\n\n2009-06-17  Bertrand Roessli  <bertrand.roessli@psi.ch>\n\n\t* plot/axis.m: Fix bug for 'axis tight' with multiple surface plots,\n\tadd demo.\n\n2009-06-15  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/quiver.m: Add 'clf' to demos.\n\t* plot/plotyy.m: Consider dataaspectratiomode before changing\n\tdataaspectratio.\n\n2009-06-14  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/plotyy.m: Fix compatibility with subplot, add listeners for\n\tdataaspectratio, and add a demo.\n\n2009-06-14  Eric Chassande-Mottin  <echassandemottin@gmail.com>\n\n\t* plot/plotyy.m: Correct behavior when there is no currentfigure.\n\n2009-06-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* set/ismember.m: Reimplement using lookup & unique.\n\n2009-06-11  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: Fix logic associated with 'have_ghostscript'.\n\t* plot/gnuplot_drawnow.m: Add support for pdfcairo and pngcairo\n\tterminals. Minor code improvements.\n\t* plot/print.m: Associate '-mono' with devices ps, ps2, eps, & eps2.\n\tHave '-mono' render all objects in monochrome.\n\tFor pdf or png output, favor gnuplot's cairo terminals.\n\n2009-06-10  Marco Caliari  <marco.caliari@univr.it>\n\n\t* plot/hold.m: Add demo including a hggroup.\n\t* plot/__go_draw_axes__.m: Fix order when pushing group children onto\n\tthe axes kid list.\n\t* general/quadgk.m: Better waypoint transform.\n\n2009-06-09  David Bateman  <dbateman@free.fr>\n\n\t* general/quadgk.m: Add test case and fixed doubly infinite\n\twaypoint transform for x = 0 case.\n\n2009-06-09  Marco Caliari  <marco.caliari@univr.it>\n\n\t* general/quadgk.m: Fix doubly infinite transformation to the finite\n\tinterval.\n\n2009-06-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/axis.m: Fix bug for 'axis tight' with multiple lines, modify\n\tdemo.\n\n2009-06-07  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* testfun/assert.m: Fix texinfo bug.\n\n2009-06-04  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Change strncmpi(scale,'lo') to\n\tstrcmp(scale,'log').\n\t* plot/__go_draw_axes__.m: For log-scale axes use format '10^{%T}'.\n\n2009-06-03  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/colorbar.m: Colorbar 'handlevisibility' should be 'on'.\n\tAdd additional demos which illustrate problems with the present\n\timplementation.\n\t* plot/__gnuplot_has_feature__.m: Change version for\n\t\"x11_figure_position\" from \">=4.3.0\" to \">=4.2.5\".\n\t* plot/__scatter__.m: If the color spec is empty, set using\n\t__next_line_color__.\n\t* plot/scatter3.m: Add demos.\n\n2009-06-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* polynomial/polyfit.m: Fix test.\n\n2009-06-02  Rafael Laboissiere  <rafael@debian.org>\n\n\t* help/doc.m: In test, look also for the gzipped version of the\n\tinfo_file\n\n2009-05-29  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__gnuplot_get_var__.m: Insert missing semicolon.\n\n2009-05-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Set x2range when xaxislocation=='top'\n\tand set y2range when yaxislocation=='right'. Simplify support\n\tfor ticklabel separator '|'.\n\t* plot/__go_draw_figure__.m: Change 'autoscale fix' to\n\t'autoscale keepfix'.\n\t* plot/colorbar.m: Add demos.\n\n2009-05-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Add support for ticklabel separator '|'.\n\n2009-05-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* sparse/bicgstab.m: Improve preconditioning; avoid explicit inverse.\n\t* sparse/cgs.m: Improve preconditioning; avoid explicit inverse.\n\n2009-05-28  Radek Salac  <salac.r@gmail.com>\n\n\t* sparse/bicgstab.m: New output when calling without arguments.\n\tTime optimization - remove certain checks linked to\n\tpreconditioner which are unacceptably slow.\n\t* sparse/cgs.m: New output when calling without arguments.\n\tTime optimization - remove certain checks linked to\n\tpreconditioner which are unacceptably slow.  Rename internal\n\tvariable to match bicgstab.\n\n2009-05-27  Rik Wehbring  <rdrider0-list@yahoo.com>\n\n\t* plot/axis.m: Update documentation to reflect addition of\n\t\"tight\" option.\n\n2009-05-27  Rik Wehbring  <rdrider0-list@yahoo.com>\n\n\t* ismember.m: Update examples to remove incorrect reference to\n\tresidue function.\n\n2009-05-27  John W. Eaton  <jwe@octave.org>\n\n\t* image/imwrite.m: Convert indexed images to RGB before calling\n\t__magick_write__.\n\n\t* image/imshow.m: In demo, convert image to rgb before scaling\n\tcomponents.  Use imread instead of loadimage.\n\n2009-05-26  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Fix rendering of overlaping images and\n\tline objects.  Add demos as well.\n\n2009-05-27 Søren Hauberg  <hauberg@gmail.com>\n\n\t* geometry/delaunay.m: Support cellstr's as options.\n\n2009-05-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* plot/imshow.m: Fix handling of indexed images.\n\n2009-05-26 Søren Hauberg  <hauberg@gmail.com>\n\n\t* help/__makeinfo__.m: Support several @seealso's in one text.\n\n2009-05-26  John W. Eaton  <jwe@octave.org>\n\n\t* plot/colorbar.m: Downcase location argument.\n\n2009-05-26 Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* pkg/pkg.m: Add \"version\" field to the structure returned by \"pkg\n\tdescribe\".\n\n2009-05-25  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Properly render TeX symbols for x11, when\n\tusing the anonymous fontname=\"*\".\n\n2009-05-24 Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* plot/gnuplot_drawnow.m: single-quote output name to allow backslash\n\tcharacters as filesep under windows\n\t* plot/print.m: Support ps->pdf using ghostscript under windows, check\n\tfor %GSC% environment variable.\n\n2009-05-24 Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* plot/__gnuplot_version__.m: quote gnuplot_binary to allow spaces\n\tin file name\n\n2009-05-22  John W. Eaton  <jwe@octave.org>\n\n\t* general/interp3.m: Don't require interpolation grid to have same\n\tsize as data.  From Kris Thielemans <kris.thielemans@imperial.ac.uk>.\n\n2009-05-19 Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* pkg/pkg.m: Fix a bug when quering only one non installed package\n\twith \"pkg describe\".\n\n2009-05-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/__fdjac__.m: Support central differences.\n\t* optimization/fsolve.m: Support central differences. Add FinDiffType\n\toption.\n\t* optimization/fminunc.m: Ditto.\n\n2009-05-17  Rik Wehbring  <rdrider0-list@yahoo.com>\n\n\t* *.m: Simplify Texinfo documentation in .m scripts by removing\n\tredundant @iftex calls\n\n2009-05-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fminunc.m: Improve TR updating strategy.\n\t* optimization/fsolve.m: Ditto.\n\n2009-05-15  John W. Eaton  <jwe@octave.org>\n\nv\t* general/nargchk.m: Don't generate error if output is struct.\n\tUncomment some additional tests.\n\tFrom Alois Schloegl <alois.schloegl@tugraz.at>\n\n2009-05-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fminunc.m: Import the step adaptation strategy\n\timprovements from fsolve.\n\n2009-05-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__gnuplot_has_feature__.m: Add feature \"key_has_font_properties\".\n\t* plot/__go_draw_axes__.m: Have legend inherit the axis font-name/size.\n\n2009-05-04  Peter O'Gorman  <pogma@thewrittenword.com>\n\n\t* miscellaneous/tar.m, miscellaneous/unpack.m:\n\tPass \"xvf\" to tar instead of \"-x -v -f\".\n\n2009-04-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__gnuplot_has_feature__.m: Change version for\n\t\"x11_figure_position\", >4.2.4 to >=4.3.0.\n\n2009-04-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: For figure position, treat 'wxt' as 'x11'.\n\n2009-04-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/base/range.m: Fix behavior when dim is specified.\n\n2009-04-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: Fix typo: 'gswin23c' -> 'gswin32c'. Suppress stderr\n\twhen printing. New sub-function: fix_eps_bbox(). Add option, \"-tight\",\n\tto replace the gnuplot bbox with a tight bbox for eps-files.\n\n2009-04-23  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: Use Ghostscript rather than ImageMagick's 'convert'.\n\tSupport printing to non-postscript printers. Do not change the output\n\tfilename when using Ghostscript. When using lpr to print the output,\n\tsend it without filtering (unix), or as if it were binary (pc).\n\n2009-04-22  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* general/isa.m: Correctly report multiple layers of class hierarchy.\n\n2009-04-20  John W. Eaton  <jwe@octave.org>\n\n\t* special-matrix/vander.m: Update tests.\n\n2009-04-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* special-matrix/vander.m: Allow second argument.\n\t* special-matrix/polyfit.m: Simplify.\n\n2009-04-17  Rik  <rdrider0-list@yahoo.com>\n\n\t* plot/__marching_cube__.m: Correct help Texinfo so manual will compile\n\n2009-04-16  Marco Caliari  <marco.caliari@univr.it>\n\n\t* toeplitz.m: Treat separately the sparse case.\n\n2009-04-14  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* plot/__marching_cube__.m: Add help text.\n\t* plot/isonormals.m: Add help text and tests.\n\n2009-04-14  David Bateman  <dbateman@free.fr>\n\n\t* plot/__patch__.m: Set default facecolor to [0,1,0].\n\n2009-04-12  Aravindh Krishnamoorthy  <aravindh.k.dev@gmail.com>\n\n\t* special-matrix/hadamard.m: Fix a documentation mistake.\n\n2009-04-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* polynomial/polyaffine.m: New function.\n\t* polynomial/polyscale.m: Remove.\n\t* polynomial/polytrans.m: Remove.\n\n2009-04-12  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__gnuplot_open_stream__.m: New function.\n\t* plot/__gnuplot_get_var__.m: If not open, open the gnuplot plot stream.\n\t* plot/gnuplot_drawnow.m: Replace internal function open_gnuplot_stream\n\twith new __gnuplot_open_stream__.\n\n2009-04-11  David Bateman  <dbateman@free.fr>\n\n\t* geometry/trisurf.m: New file.\n\t* geometry/Makefile.in (SOURCES): Add it here.\n\t* geometry/trimesh.m: Convert to using 3D patches.\n\t* plot/__go_draw_axes__.m: Allow 3D filled triangular patches.\n\t* plot/__patch__.m: Rewrite to allow update of dependent variables\n\twith listener functions amongst themselves.\n\t* plot/patch.m: Add 3D demo. Update the documentation.\n\n2009-04-11  Martin Helm  <martinh@sirius.mhelm.de>\n\n\t* plot/__interp_cube__.m, plot/__marching_cube__.m, isocolors.m,\n\tisonnormals.m, isosurface.m: New files.\n\t* plot/Makefile.in (SOURCES): Add them here.\n\n2009-04-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* set/intersect.m: Add missing branch.\n\n2009-04-10  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: If no pdf support in gnuplot, then \"convert\" from\n\tpostscript to pdf. For gnuplot 4.2.x use \"convert\", if it is present,\n\tto produce pdf output. Only render a full page for ps/pdf output.\n\tRename variable, \"size\" to \"canvas_size\". Reformat help text to\n\teliminate unintended spaces. Minor improvements to the code.\n\t* plot/gnuplot_drawnow.m: Place canvas size at the end of the terminal\n\tspec, and remove trailing semicolon. Minor improvments to the code.\n\t* plot/__gnuplot_get_var__.m: If fifo fails to open, try 2nd time.\n\n2009-04-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* special-matrix/vander.m: Optimize.\n\n2009-04-07  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/Makefile.in: Remove __gnuplot_default_font__.m from SOURCES.\n\n2009-04-06  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__gnuplot_get_var__.m: Correct misleading error messages, and\n\tremove dangling/commented code.\n\t* plot/__gnuplot_default_font__.m: Remove file from archive.\n\t* plot/__go_draw_axes__.m, plot/__go_draw_figure__.m: Allow\n\tfontsize to be specified for all terminals with fontname == \"*\".\n\n2009-04-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* polynomial/polyscale.m: New function.\n\t* polynomial/polytrans.m: New function.\n\n2009-04-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* special-matrix/pascal.m: Fix, optimize & extend.\n\n2009-04-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/vech.m: Optimize.\n\n2009-04-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* special-matrix/toeplitz.m: Optimize.\n\n2008-04-03  David Bateman  <dbateman@free.fr>\n\n\t* plot/__scatter__.m: correct indexing of cdata.x\n\n2009-04-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fminunc.m: New function.\n\t* optimization/Makefile.in: Update.\n\t* optimization/__dogleg__: Allow general quadratics.\n\n2009-04-02  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Include gnuplot command termination when\n\tplotting image.\n\n2009-04-02  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Fix title placement for gnuplot 4.2.x.\n\n2009-04-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Fix test.\n\n2009-03-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: New subfunction create_fontspec(). Allow\n\tfontsize to be specified when the fontname is anonymous.\n\n2009-03-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__gnuplot_default_font__.m: New function: determine gnuplot's\n\tterminal dependent default font.\n\t* plot/__go_draw_figure__.m: Substitute gnuplot default font when\n\t\"fontname\" = \"*\".\n\n2009-03-29  John W. Eaton  <jwe@octave.org>\n\n\t* testfun/Makefile.in (SOURCES): Add rundemos.m to the list.\n\n2009-03-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: For eps output the bounding box should represent the\n\tfigure's position.\n\n2009-03-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Always set figure property \"__plot_stream__\"\n\tto the active gnuplot steam. Permits __gnuplot_get_var__ to return to\n\tproper result for all gnuplot streams.\n\n2009-03-27  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Properly position the title for 3D plots\n\twhen using the gnuplot (v4.3+) backend.\n\n2009-03-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/expm.m: Fix order of outputs from balance.\n\n2009-03-25  Kai Habel  <kai.habel@gmx.de>\n\n\t* general/gradient.m: Fix calculation for more than two\n\tdimensions.  Change interpretation of vector arguments from\n\tspacing to coordinates.  New tests.\n\n2009-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* mkdoc: Pass full file name to gethelp.\n\t* gethelp.cc (main): Handle second argument.  Write comment with\n\tfull file name to output.\n\n2009-03-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: When printing, pass scalar plot_stream\n\tto __gnuplot_draw_figure__, and close all plot streams when done.\n\n2009-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* general/isa.m: Handle parent classes.\n\n2009-03-23  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Check that gnuplot has internal variable\n\t\"GPVAL_TERMINALS\".\n\t* plot/__gnuplot_has_feature__.m: Add \"variable_GPVAL_TERMINALS\".\n\n2009-03-21  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Verify the gnuplot terminal is supported.\n\t* plot/__gnuplot_get_var__.m: Add function to get gnuplot variables.\n\t* plot/print.m: Restore the behavior for option -S<num>,<num>.\n\n2009-03-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m (guarded_eval): Simplify & fix missing\n\tsemicolon.\n\n2009-03-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/__fdjac__.m: Pass in fvec to save one evaluation.\n\t* optimization/fsolve.m: Avoid redundant reevaluation when using\n\tFD jacobians. Document how it can be done with user jacobians.  Make\n\tfirst iteration special and call outputfcn after it. Skip updates\n\tunless two successful iterations have occurred.\n\t* optimization/__dogleg__.m: Add missing alpha in the zero-gradient\n\tcase.\n\t* optimization/fsolve.m: Remove autodg (not used), simplify.\n\n2009-03-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/base/var.m: a -> x.\n\n2009-03-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/base/mean.m: Simplify.\n\t* statistics/base/meansq.m: Optimize.\n\t* statistics/base/center.m: Fix behvaior with vectors, simplify.\n\t* statistics/base/std.m: Simplify using `center'.\n\t* statistics/base/var.m: Ditto.\n\t* statistics/base/cov.m: Ditto.\n\n2009-03-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/repmat.m: Use subscript pairs rather than forming Kronecker\n\tproducts.\n\n2009-03-11  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Unset the {x,y,z}ticks when initializing\n\teach axis. Set ticklabels when the ticklabels are empty and when\n\tticklabelmode==\"manual\".\n\n2009-03-11  Marco Caliari  <marco.caliari@univr.it>\n\n\t* plot/axis.m: Implement \"square\" and \"equal\" options, conditional\n\ton how octave positions gnuplot axes. Place the \"title()\" and\n\t\"axis()\" commands after \"plot()\" in the demos.\n\n2009-03-09  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m (do_tics): Fix typo (xaxislocation ->\n\tyaxislocation).\n\n2009-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* help/lookfor.m (search_cache): Also match function names.\n\n\t* pkg/pkg.m, help/gen_doc_cache.m, help/lookfor.m:\n\tUse doc-cache instead of DOC for doc cache file.\n\n2009-03-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/accumarray.m: Reorder tests. Call either \"sparse\" or\n\t__accumarray_sum__ for the default summation case.\n\t* statistics/base/histc.m: Reimplement using lookup & accumarray.\n\n2009-03-08  Søren Hauberg  <hauberg@gmail.com>\n\n\t* statistics/base/histc.m: New function.\n\n2009-03-06  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Preserve the order of axes' children\n\twhen pruning the handles for the {x,y,z}labels and title.\n\t* plot/legend.m: Change demo to add colors to lines. This change\n\treveals the problem (above) with the ordering of the axes' children.\n\n2009-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/condest.m: Use lu rather than splu. Use relative tols\n\tfor tests.\n\n2009-03-05  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/spdiag.m: Ensure sparse result.\n\n2009-03-05  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Preserve column vector orientation for\n\tthe axes children while removing the axis label & title handles.\n\n2009-03-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* polynomial/polyval.m: Implement using Horner scheme.\n\n2009-03-03  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Fix unintended shift of plot image for\n\tthe gnuplot postscript+eps terminal.\n\n2009-03-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pkg/pkg.m (fix_depends): Fix & simplify splitting the string.\n\n2009-03-02  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* set/complement.m, set/union.m: Remove reference to deprecated\n\tfunction create_set.\n\n2009-03-01  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Do not render axis labels twice when\n\ttheir handles are visible, but do render objects with hidden\n\thandles.\n\n2009-03-01  Ben Abbott  <bpabbott@mac.com>\n\n\t* general/num2str.m: Trivial bug fix. Recent switch from split()\n\tto strsplit() produced cells rather than character data.\n\n2009-03-01  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/colorbar.m: Bug fix. Allow hidden colorbars to be deleted,\n\tand replace existing colorbar when a new one is created. Additional\n\tdemos are included to verify these behaviors.\n\n2009-02-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__actual_axis_position__.m: Include file missed in prior\n\tchangeset.\n\n2009-02-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m, plot/gnuplot_drawnow.m: Add compatible support for\n\tspecificying resolution of bitmap terminals, \"-r<num>\".\n\n\t* plot/gnuplot_drawnow.m: Check that canvas size is only specified\n\tone time.\n\n\t* plot/gnuplot_drawnow.m, plot/__go_draw_figure__.m: Support papersize,\n\tpaperposition properties. Accommodate gnuplot's implicit margins for\n\tpostscript terminals. Remove internal function get_canvassize().\n\n\t* plot/gnuplot_drawnow.m:\n\tTerminate gnuplot \"set term ...\" with semicolon.\n\tSpecify vector terminals sizes in floating point.\n\tRename internal function isbackend() to output_to_screen().\n\tRename internal function gnuplot_term() to gnuplot_default_term().\n\tRename internal function isbitmap() to term_units_are_pixels().\n\tMinor changes for coding conventions.\n\n\t* plot/__actual_axis_position__.m, Makefile.in: New function to\n\tdetermine position of rendered axes, including the effect of the\n\taspect ratio.\n\t* plot/__gnuplot_has_feature__.m: Add new feature\n\t\"screen_coordinates_for_{lrtb}margin\".\n\t* plot/__go_draw_axes__.m, plot/colorbar.m: Enable axes to be\n\tpositioned using {lrtb}margins.\n\t* plot/colorbar.m: Add to, and modify, demos.\n\n\t* plot/print.m: Remove non-functional/commented code.\n\t* plot/__go_draw_figure__.m: Remove non-functional code.\n\t* plot/__gnuplot_has_feature__.m: Remove non-functional code.\n\n\t* plot/quiver3.m: Add \"clf\" and \"colormap(jet(64))\" to demo.\n\n2009-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* set/complement.m: Call unique, not create_set.\n\t* set/unique.m: Style fix for docstring.\n\t* deprecated/create_set.m: Move here from set/create_set.m.\n\tAlways return a row vector, as documented.\n\n\t* set/Makefile.in (SOURCES): Remove create_set.m from the list.\n\t* deprecated/Makefile.in (SOURCES): Add create_set.m to the list.\n\n\t* general/num2str.m: Call strsplit instead of split.\n\n\t* strings/strsplit.m: Style fixes.\n\n2009-02-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strsplit.m: Check also nargin.\n\n2009-02-26  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/split.m: Add warning, not about version.\n\n2009-02-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strsplit.m: New function.\n\t* strings/split.m: Move to deprecated/.\n\t* strings/Makefile.in: Update.\n\t* deprecated/Makefile.in: Update.\n\n\t* general/int2str.m: Use strsplit instead of split.\n\t* general/num2str.m: Ditto.\n\t* help/__makeinfo__.m: Ditto.\n\t* help/lookfor.m: Ditto.\n\t* miscellaneous/compare_versions.m: Ditto.\n\t* miscellaneous/tar.m: Ditto.\n\t* miscellaneous/unpack.m: Ditto.\n\t* miscellaneous/what.m: Ditto.\n\t* miscellaneous/zip.m: Ditto.\n\t* pkg/pkg.m: Ditto.\n\t* strings/strtok.m: Ditto.\n\t* testfun/rundemos.m: Ditto.\n\n2009-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (distclean maintainer-clean): Remove tags and TAGS\n\tin distclean target.\n\n2009-02-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* help/lookfor.m: Vectorize the path splitting using mat2cell.\n\tExtract new path elements using setdiff.\n\n2009-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* plot/pie.m: Use numel to check sizes of X and LABELS instead of\n\tusing size_equal.  From Andy Buckle <andybuckle@gmail.com>.\n\n\t* help/lookfor.m: Split original path into cell array and compare\n\telements with strcmp.  Suppress warnings and errors when getting\n\thelp text from function files.\n\n2009-02-24  John W. Eaton  <jwe@octave.org>\n\n\t* help/gen_doc_cache.m: Don't compress output file.  By default,\n\twrite to DOC, not DOC.gz.  Don't save empty cache.\n\n\t* help/lookfor.m: Use doc_cache_file to get location of DOC file.\n\n2009-02-24  Jason Riedy  <jason@acm.org>\n\n\t* pkg/pkg.m (generate_lookfor_cache): Generate a DOC file for each\n\tdirectory.\n\n\t* help/gen_doc_cache.m: Call __makeinfo__, not makeinfo.\n\n2009-02-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Update niter after each iteration, not just\n\ta succesful one.\n\n2009-02-08  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* configure.in: AC_SUBST ac_config_files\n\n\t* Makefile.in:  Add make targets for configuration files\n\tand config.status.\n\n2009-02-23  John W. Eaton  <jwe@octave.org>\n\n\t* plot/fplot.m: Fix nargin check.\n\tFrom Joel Parker <Joel.Parker@radiancetech.com>.\n\n2009-02-20  Steffen Groot  <steffen.groot@technolution.eu>\n\n\t* plot/__patch__.m: Correct indexing of varargin.\n\n2009-02-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/dmult.m: Remove.\n\t* linear-algebra/Makefile.in: Update.\n\t* deprecated/dmult.m: Move here; revert to the 3.0.x version.\n\t* deprecated/Makefile.in: Update.\n\t* statistics/models/logistic_regression_derivatives.m: Replace dmult\n\tby diagonal matrices.\n\n2009-02-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Only send figure position info to gnuplot\n\twhen the plot stream is first opened. Revert usage of hidden axes\n\tto store prior figure \"position\" property.\n\n2009-02-19  John W. Eaton  <jwe@octave.org>\n\n\t* general/__isequal__.m, general/__splinen__.m, image/__img__.m,\n\timage/__img_via_file__.m, miscellaneous/__xzip__.m,\n\toptimization/__all_opts__.m, optimization/__dogleg__.m,\n\toptimization/__fdjac__.m, path/__extractpath__.m,\n\tplot/__add_datasource__.m, plot/__area__.m,\n\tplot/__axes_limits__.m, plot/__axis_label__.m, plot/__bar__.m,\n\tplot/__bars__.m, plot/__clabel__.m, plot/__contour__.m,\n\tplot/__default_plot_options__.m, plot/__errcomm__.m,\n\tplot/__errplot__.m, plot/__ezplot__.m,\n\tplot/__gnuplot_has_feature__.m, plot/__gnuplot_version__.m,\n\tplot/__go_close_all__.m, plot/__go_draw_axes__.m,\n\tplot/__go_draw_figure__.m, plot/__line__.m,\n\tplot/__next_line_color__.m, plot/__patch__.m, plot/__plr1__.m,\n\tplot/__plr2__.m, plot/__plt1__.m, plot/__plt2__.m,\n\tplot/__plt2mm__.m, plot/__plt2mv__.m, plot/__plt2ss__.m,\n\tplot/__plt2sv__.m, plot/__plt2vm__.m, plot/__plt2vs__.m,\n\tplot/__plt2vv__.m, plot/__plt__.m, plot/__plt_get_axis_arg__.m,\n\tplot/__pltopt1__.m, plot/__pltopt__.m, plot/__quiver__.m,\n\tplot/__scatter__.m, plot/__stem__.m, startup/__finish__.m,\n\tstatistics/base/__quantile__.m: Consistent doc strings for\n\tinternal fucntions.\n\n2009-02-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/subplot.m: Fix unintended deletion of axes.\n\n2009-02-18  Frederick Umminger  <Frederick_Umminger@playstation.sony.com>\n\n\t* audio/wavread.m: Improve search for data chunks.\n\n2009-02-18  Ivan Sutoris  <ivan.sutoris@gmail.com>\n\n\t* miscellaneous/edit.m: Expand documentation about editor mode.\n\n2009-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__gnuplot_version__.m: Don't use regexp to extract version\n\tnumber.\n\n2009-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* plot/gnuplot_drawnow.m (gnuplot_set_term):\n\tAdjust nargin checks for new signature.\n\n2009-02-17  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/contourc.m: Convert demo to test.\n\t* plot/surfnorm.m: Add another demo.\n\t* plot/surfnorm.m, plot/pareto.m: Add \"colormap(jet)\" to 1st demo.\n\t* plot/plotyy.m, plot/patch.m, plot/pareto.m, plot/legend.m,\n\tplot/fill.m, plot/comet.m, plot/colorbar.m, plot/clabel.m:\n\tReplace \"close all\" with \"clf\" in demo.\n\n2009-02-17  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Only close the gnuplot window and send\n\tposition/size info when the figure's position property has changed.\n\t(gnuplot_set_term): New arg, NEW_STREAM.  Change all uses.\n\t(open_gnuplot_stream): Delete unused output ENHANCED.\n\n2009-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* plot/plotyy.m: Handle case of existing figure with no axes.\n\n2009-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* help/__makeinfo__.m: Rename from help/makeinfo.m.  Delete tmp file.\n\t* help/Makefile.in (SOURCES): Add __makeinfo__.m, delete makeinfo.m.\n\t* help/get_first_help_sentence.m, help/help.m, help/lookfor.m,\n\thelp/print_usage.m: Call __makeinfo__ instead of makeinfo.\n\t* help/__strip_html_tags__.m, help/__additional_help_message__.m:\n\tDoc fix.\n\n2009-02-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/shading.m: No new figure windows for the demos.\n\t* plot/surfl.m: Clear figure before running demos.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/expm.m: Fix invalid unscaling.\n\t* help/which.m: Do not add \"function\" here.\n\t* optimization/fsolve.m: Update comments.\n\n2009-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* help/help.m: Shorten default help text.\n\n2009-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* help/doc.m, help/help.m, help/lookfor.m, help/type.m,\n\thelp/which.m, image/colormap.m, miscellaneous/delete.m,\n\tmiscellaneous/dir.m, miscellaneous/edit.m,\n\tmiscellaneous/intwarning.m, miscellaneous/ls.m,\n\tmiscellaneous/mex.m, miscellaneous/mkoctfile.m,\n\tmiscellaneous/run.m, miscellaneous/what.m, path/savepath.m,\n\tpkg/pkg.m, plot/axis.m, plot/box.m, plot/caxis.m, plot/cla.m,\n\tplot/close.m, plot/colorbar.m, plot/grid.m, plot/hidden.m,\n\tplot/hold.m, plot/legend.m, plot/orient.m, plot/print.m,\n\tplot/shading.m, plot/title.m, plot/xlabel.m, plot/ylabel.m,\n\tplot/zlabel.m, testfun/demo.m, testfun/example.m, testfun/fail.m,\n\ttestfun/rundemos.m, testfun/test.m:\n\tDelete \"PKG_ADD: mark_as_command\" directive.\n\n\t* edit.m: Avoid command-style function call syntax when\n\tassigning results in tests.\n\n\t* deprecated/mark_as_rawcommand.m, deprecated/unmark_rawcommand.m,\n\tdeprecated/israwcommand.m, deprecated/mark_as_command.m,\n\tdeprecated/unmark_command.m, deprecated/iscommand.m:\n\tNew functions.\n\t* deprecated/Makefile.in (SOURCES): Add them to the list.\n\n2009-02-15  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/subplot.m: Compatible placement of subplots.\n\n2009-02-13 Ben Abbott  <bpabott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Respect axes ticklength property.\n\n2009-02-12  John W. Eaton  <jwe@octave.org>\n\n\t* general/sortrows.m: Call __sort_rows_idx__, not __sortrows_idx__.\n\n2009-02-12  Søren Hauberg  <hauberg@gmail.com>\n\n\t* help/gen_doc_cache.m: Change API so we only handle one directory per\n\tcall to this function.\n\n2009-02-12  Søren Hauberg  <hauberg@gmail.com>\n\n\t* help/lookfor.m: Adapt to new cache scheme.\n\n2009-02-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/sortrows.m: Employ __sortrows_idx__ when applicable,\n\tgripe for sparse matrices.\n\n2009-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/news.m: Look in octetcdir for NEWS file.\n\n2009-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/interp2.m: Added support for pchip bicubic interpolation.\n\tAlso simplified code and added support for natural extrapolation via\n\t\"extrap\".\n\n2009-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/Makefile.in (SOURCES): Include __xzip__.m in the list.\n\n\t* testfun/rundemos.m: Error if fopen fails.\n\n2009-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (install install-strip): Don't install ls-R file.\n\t(uninstall): Don't uninstall ls-R file.\n\n2009-02-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Document support for complex holomorphic\n\tsystems. Improve guarded evaluation.\n\n2009-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/news.m: Use puts instead of printf.\n\n2009-02-05  Thomas D. Dean  <tomdean@speakeasy.org>\n\n\t* polynomial/polyout.m: Replace com2str with num2str, and minor\n\tstyle changes.\n\n2009-02-04  John W. Eaton  <jwe@octave.org>\n\n\t* help/which.m: Still print something sensible if type is empty.\n\n2009-02-04  Søren Hauberg  <hauberg@gmail.com>\n\t    Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* miscellaneous/Makefile.in (SOURCES): Add bzip2.m to the list.\n\n2009-02-04  Frederick Umminger  <Frederick_Umminger@playstation.sony.com>\n\n\t* signal/freqz.m: Ensure causal phase response.\n\tHandle long input correctly.\n\n2009-02-04  Petr Mikulik  <mikulik@physics.muni.cz>\n\n\t* plot/__go_draw_axes__.m: Pass \"interpolate 0, 0\" to gnuplot\n\tinstead of \"interpolate 4, 4\".\n\n2009-02-04  John W. Eaton  <jwe@octave.org>\n\n\t* audio/wavwrite.m, deprecated/splu.m, general/bitcmp.m,\n\tgeneral/fliplr.m, general/flipud.m, general/genvarname.m,\n\tgeneral/nargchk.m, general/nargoutchk.m, general/quadgk.m,\n\tgeneral/rot90.m, geometry/griddata.m, geometry/rectint.m,\n\tgeometry/voronoi.m, geometry/voronoin.m,\n\thelp/__strip_html_tags__.m, image/brighten.m, image/imfinfo.m,\n\timage/imread.m, linear-algebra/cond.m, linear-algebra/condest.m,\n\tlinear-algebra/dmult.m, linear-algebra/dot.m,\n\tlinear-algebra/expm.m, linear-algebra/housh.m,\n\tlinear-algebra/onenormest.m, linear-algebra/subspace.m,\n\tmiscellaneous/compare_versions.m, optimization/__all_opts__.m,\n\toptimization/optimget.m, pkg/pkg.m, plot/__bar__.m,\n\tplot/__plr2__.m, plot/ribbon.m, plot/slice.m, polynomial/pchip.m,\n\tpolynomial/roots.m, set/unique.m, signal/fractdiff.m,\n\tsignal/hurst.m, specfun/beta.m, specfun/legendre.m,\n\tstatistics/base/__quantile__.m, statistics/base/quantile.m,\n\tstatistics/tests/cor_test.m,\n\tstatistics/tests/kolmogorov_smirnov_test_2.m, strings/base2dec.m,\n\tstrings/dec2base.m, strings/strcat.m, strings/validatestring.m,\n\ttime/addtodate.m: Style fixes.\n\n2009-02-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: remove redundant line.\n\n2009-02-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/Makefile.in: Add missing source.\n\n2009-02-02  Rob Mahurin  <rob@utk.edu>\n\n\t* general/interpft.m: Increase tolerance in tests, for FFTPACK.\n\n2009-02-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/__all_opts__.m: Yield empty list in recursive calls.\n\tmlock to avoid unloading.\n\n2009-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/PKG_ADD: Delete.\n\t* optimization/fsolve.m, optimization/fzero.m,\n\toptimization/lsqnonneg.m: Use PKG_ADD: comment to call __all_opts__.\n\n2009-01-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/__all_opts__.m: New source.\n\t* optimization/optimset.m: Implement checking for registered options.\n\t* optimization/optimget.m: Ditto.\n\t* optimization/fsolve.m: Fix misspelled option.\n\t* optimization/PKG_ADD: New startup file.\n\n2009-01-30  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/__go_draw_axes__.m: Add support for transparent surfaces.\n\t* plot/__gnuplot_has_feature__.m: Add feature 'transparent_surface',\n\tRequire gnuplot 4.3 for transparent patches and surfaces.\n\n2009-01-30  Benjamin Lindner  <lindnerben@gmx.net>\n\n\t* time/datestr.m: Convert YYYY to %Y instead of %C%y.\n\tConvert [Dd][Dd] to %d instead of %e.\n\n2009-01-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/print.m: Use __gnuplot_has_feature__ instead of\n\tcompare_versions.\n\n\t* plot/gnuplot_drawnow.m: Respect x11 figure position property.\n\n2009-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/fileparts.m: Match all possible file separators.\n\n2009-01-29  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/__go_draw_axes__.m: Add support for transparent patches.\n\n2009-01-29  Søren Hauberg  <hauberg@gmail.com>\n\n\t* help/help.m, help/print_usage.m, help/get_first_help_sentence.m:\n\tprint sensible error message when function is found but not documented.\n\n\t* help/help.m: Allow displaying 'Contents.m' files.\n\n2009-01-29  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/Makefile.in (SOURCES): Include diffuse.m, specular.m, and\n\tsurfl.m in the list.\n\n2009-01-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Style fixes.\n\n\t* plot/__gnuplot_has_feature__.m: New file, checks for supported\n\tfeature.\n\n2009-01-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Don't use pivoting at all (for the time\n\tbeing).\n\n2009-01-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Use more adaptive rescaling.\n\tPut back the default tolerances based on machine eps respecting\n\tthe used precision. Partially reflect this in the default optimset\n\tvalues.\n\n2009-01-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/ordefields.m: Use indexed assignment instead of a\n\tloop. Fix for multidimensional cases.\n\n2009-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* general/arrayfun.m, image/imwrite.m, plot/axis.m, plot/clf.m,\n\tplot/ribbon.m, plot/gnuplot_drawnow.m, plot/cla.m, set/unique.m:\n\tUse endif or endfor instead of \"end\".\n\n\t* path/savepath.m: Call command_line_path instead of commandlinepath.\n\n2009-01-27  Jason Riedy  <jason@acm.org>\n\n\t* miscellaneous/orderfields.m: Really fix the indexing for struct\n\tarrays.\n\n2009-01-27  Carlo de Falco  <kingcrimson@tsicali.it>\n\n\t* polynomial/spline.m: Doc fix.\n\n2009-01-27  Søren Hauberg  <hauberg@gmail.com>\n\n\t* general/gradient.m: Handle computing the gradient of a function\n\thandle.\n\n2009-01-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/lsqnonneg.m: Reimplement using QR updating for\n\tsquare and overdetermined systems.\n\n2009-01-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Provide default values on request.\n\tAdjust some defaults.\n\t* optimization/fzero.m: Ditto.\n\t* optimization/optimset.m: Query optimal values via the M*b way.\n\n2009-01-26  Jason Riedy  <jason@acm.org>\n\n\t* miscellaneous/orderfields.m: Also avoid loop for non-empty structs.\n\n2009-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Disable Broyden updates for sparse jacobians.\n\n2009-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/__fsolve_defopts__.m: Remove.\n\t* optimization/Makefile.in: Reflect change.\n\n2009-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/__fdjac__.m: Fix setting up h.\n\t* optimization/fsolve.m: Allow underdetermined systems. Use QR for\n\tlarge enough square and overdetermined systems, with pivoting in the\n\tfirst step. Simplify options. Adjust defaults - make TR radius\n\ttolerance less stringent. Support DisplayFcn.\n\n2008-12-24 Ben Abbott  <bpabbott@mac.com>\n\n\t* path/savepath.m: Respect cmd-line and env paths.\n\n2009-01-24 Ben Abbott  <bpabbott@mac.com>\n\n\t* sparse/svds.m: svds.m: skip tests if ARPACK is missing.\n\n2009-01-23  Søren Hauberg  <hauberg@gmail.com>\n\n\t* help/type.m: Make 'type X' work, when X is the name of a variable.\n\n2009-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* help/which.m: New function.\n\t* help/Makefile.in (SOURCES): Add it to the list.\n\n\t* help/help.m: Also display location of the file before the help text.\n\t* help/print_usage: Also display additional help text.\n\t* help/__additional_help_message__.m: Return message instead of\n\tdisplaying it.\n\n2009-01-22  Søren Hauberg  <hauberg@gmail.com>\n\n\t* help: New directory.\n\t* configure.in (AC_CONFIG_FILES): Add help/Makefile to the list.\n\t* Makefile.in (SUBDIRS): Add it to the list.\n\t* help/__additional_help_message__.m, help/__strip_html_tags__.m,\n\thelp/gen_doc_cache.m, help/get_first_help_sentence.m, help/help.m,\n\thelp/lookfor.m, help/makeinfo.m, help/print_usage.m, help/type.m:\n\tNew functions.\n\t* help/Makefile.in (SOURCES): Add them to the list.\n\t* help/doc.m: Move here from miscellaneous/doc.m.\n\t* miscellaneous/Makefile.in (SOURCES): Remove doc.m from the list.\n\t* miscellaneous/pkg.m: Generate documentation cache during install.\n\n2009-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Undo the last change.\n\n2009-01-18  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* miscellaneous/doc.m: Add test for existence of info file.\n\n2009-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__axis_label__.m: Set properties in existing axis label\n\tobject instead of creating a new text object.\n\t* plot/ylabel.m: Don't set rotation property here.\n\t* plot/title.m: Don't set horizontalalignment property here.\n\n\t* plot/ylabel.m: Insert rotation property in varargin before\n\tpassing it on to __axis_label__.\n\t* plot/__axis_label__.m: Don't set rotation for ylabel here.\n\n\t* plot/title.m: Insert horizontalalignment property in varargin\n\tbefore passing it on to __axis_label__.\n\n2009-01-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strchr.m: New function.\n\t* strings/Makefile.in: Add it.\n\n2009-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Only use qrupdate if available.\n\n2009-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* general/postpad.m: Doc fix.\n\t* general/prepad.m: Doc fix.\n\t* image/pink.m: Spelling fix.\n\t* image/hsv.m: Doc fix.\n\tFrom Francesco Potorti` <Potorti@isti.cnr.it>.\n\n\t* testfun/assert.m: Use isfield instead of struct_contains.\n\n2009-01-17 Ben Abbott  <bpabbott@mac.com>\n\n\t* general/cart2sph.m, cart2pol.m, sph2cart.m pol2cart.m:\n\tPermit scalars when transforming coordinates.\n\n2009-01-17  Steven Verstoep  <isgoed@hotmail.com>\n\n\t* plot/__quiver__.m: __quiver__.m: Fix auto-size of (x,y) coord.\n\n2009-01-16  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/gnuplot_drawnow.m: Fix for handling options.\n\n2009-01-16  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/legend.m: Fix legend order for both horizontal and\n\tvertical string cell.\n\n2008-01-15  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/grid.m: Document handle argument.\n\n2009-01-15  Peter L. Søndergaard  <peter@sonderport.dk>\n\n\t* general/nargoutchk.m: Doc fix.\n\t* general/nargchk.m: Improve compatibility.  New tests.\n\n2008-01-15  Rafael Laboissiere  <rafael@debian.org>\n\n\t* gethelp.cc: Include <cstdio>.\n\n2009-01-14  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m (ticklabel_to_cell): New function.\n\tUse it to handle non-cell ticklabels.\n\n2009-01-14  Søren Hauberg  <hauberg@gmail.com>\n\n\t* general/diff.m, general/logspace.m, general/nextpow2.m,\n\tlinear-algebra/commutation_matrix.m,\n\tlinear-algebra/duplication_matrix.m, linear-algebra/expm.m,\n\tmiscellaneous/bincoeff.m, miscellaneous/list_primes.m,\n\toptimization/fsolve.m, plot/subplot.m, polynomial/pchip.m,\n\tpolynomial/polyout.m, polynomial/residue.m, polynomial/spline.m,\n\tsignal/freqz.m, signal/sinc.m, specfun/beta.m, specfun/betaln.m,\n\tspecfun/nchoosek.m, specfun/pow2.m, special-matrix/hankel.m,\n\tspecial-matrix/hilb.m, special-matrix/invhilb.m\n\tspecial-matrix/sylvester_matrix.m, special-matrix/toeplitz.m,\n\tspecial-matrix/vander.m, statistics/base/gls.m,\n\tstatistics/base/kendall.m, statistics/base/kurtosis.m,\n\tstatistics/base/mean.m, statistics/base/median.m,\n\tstatistics/base/ols.m, statistics/base/skewness.m,\n\tstatistics/distributions/kolmogorov_smirnov_cdf.m:\n\tUse ifnottex instead of ifinfo.\n\n2009-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* linear-algebra/expm.m:\n\n\t* optimization/fsolve.m: Doc fix.\n\n\t* plot/__go_draw_axes__.m: Scale markersize by 1/3, not 1/6.\n\n\t* io/dlmwrite.m: Use '%c' format for character data.\n\n2009-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* general/repmat.m: Handle negative row or column dimension.\n\n\t* elfun/lcm.m, general/accumarray.m, general/bicubic.m,\n\tgeneral/cellidx.m, general/cplxpair.m, general/dblquad.m,\n\tgeneral/gradient.m, general/interp1.m , general/pol2cart.m,\n\tgeneral/quadgk.m, general/quadv.m, general/repmat.m,\n\tgeneral/structfun.m, geometry/griddata.m, geometry/inpolygon.m,\n\timage/brighten.m, image/hsv2rgb.m, image/imread.m,\n\timage/imwrite.m, linear-algebra/dmult.m,\n\tlinear-algebra/onenormest.m, miscellaneous/getfield.m,\n\tmiscellaneous/setfield.m, miscellaneous/what.m,\n\toptimization/fsolve.m, optimization/fzero.m,\n\toptimization/lsqnonneg.m, optimization/qp.m, pkg/pkg.m,\n\tplot/__area__.m, plot/__clabel__.m, plot/__stem__.m, plot/axis.m,\n\tplot/colorbar.m, plot/contour3.m, plot/findall.m, plot/findobj.m,\n\tplot/fplot.m, plot/grid.m, plot/hist.m, polynomial/convn.m,\n\tpolynomial/polyreduce.m, set/intersect.m, set/setxor.m,\n\tset/union.m, signal/arch_fit.m, signal/durbinlevinson.m,\n\tsignal/fftshift.m, signal/freqz_plot.m, signal/ifftshift.m,\n\tsignal/spectral_adf.m, sparse/bicgstab.m, sparse/cgs.m,\n\tsparse/gplot.m, sparse/normest.m, sparse/pcg.m, sparse/pcr.m,\n\tsparse/spy.m, sparse/svds.m, sparse/treelayout.m,\n\tsparse/treeplot.m, specfun/primes.m, special-matrix/hadamard.m,\n\tstatistics/base/center.m, statistics/base/quantile.m,\n\tstatistics/base/ranks.m, statistics/base/std.m,\n\tstatistics/distributions/hygepdf.m,\n\tstatistics/tests/kruskal_wallis_test.m, strings/index.m,\n\tstrings/mat2str.m, strings/str2double.m, strings/strrep.m,\n\ttestfun/assert.m, testfun/example.m, testfun/fail.m,\n\ttestfun/speed.m, testfun/test.m: Style fixes.\n\n\t* audio/wavread.m, general/__splinen__.m, general/bicubic.m,\n\tgeneral/rat.m, linear-algebra/expm.m, linear-algebra/krylov.m,\n\tlinear-algebra/onenormest.m, miscellaneous/edit.m,\n\toptimization/__dogleg__.m, pkg/pkg.m, plot/__errplot__.m,\n\tplot/__go_draw_axes__.m, plot/__stem__.m, plot/findobj.m,\n\tset/ismember.m, signal/arma_rnd.m, signal/freqz.m, signal/stft.m,\n\tsparse/pcg.m, sparse/sprandsym.m, sparse/treelayout.m,\n\tspecfun/factor.m, specfun/nchoosek.m, specfun/primes.m,\n\tstatistics/base/quantile.m, statistics/base/values.m,\n\tstrings/findstr.m, strings/str2double.m, strings/strrep.m,\n\ttestfun/assert.m, testfun/fail.m, testfun/speed.m, testfun/test.m,\n\ttime/datestr.m, time/datevec.m: Comment style fixes.\n\n2009-01-13  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* set/unique.m: Fix for vertical array inputs.\n\n2009-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/fzero.m, optimization/fsolve.m: Style fixes.\n\tUse strcmpi to compare options.\n\n2009-01-12  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* strings/strvcat.m: Remove.\n\t* strings/Makefile.in (SOURCES): Remove strvcat.m.\n\n2009-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* plot/diffuse.m, plot/surfl.m, plot/specular.m: Style fixes.\n\n2009-01-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/sortrows.m: Fix invalid `{x:y} = z' assignment.\n\t* miscellaneous/orderfields.m: Ditto.\n\t* miscellaneous/what.m: Ditto.\n\t* pkg/pkg.m: Ditto.\n\t* plot/ndgrid.m: Ditto.\n\t* strings/strcat.m: Ditto.\n\n2009-01-09  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/surfl.m: New function\n\t* plot/diffuse.m: Ditto.\n\t* plot/specular.m: Ditto.\n\n2009-01-05  John W. Eaton  <jwe@octave.org>\n\n\t* mkdoc: Set defaults for FIND and PERL.  Check usage.\n\n2009-01-01  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* miscellaneous/__xzip__.m: Fix error messages, add tests.\n\n2008-12-26  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* general/int2str.m, general/num2str.m, strings/base2dec.m,\n\tstrings/blanks.m, strings/cstrcat.m, strings/findstr.m,\n\tstrings/isstrprop.m, strings/mat2str.m, strings/regexptranslate.m,\n\tstrings/split.m, strings/str2double.m, strings/str2num.m,\n\tstrings/strcat.m, strings/strcmpi.m, strings/strfind.m,\n\tstrings/strjust.m, strings/strmatch.m, strings/strncmpi.m,\n\tstrings/strrep.m, strings/strtok.m, strings/strtrim.m,\n\tstrings/strtrunc.m, strings/strvcat.m, strings/substr.m:\n\tFix documentation strings, add examples, references and tests.\n\t* general/int2str.m: Add missing semicolon.\n\t* strings/regexptranslate.m: add nargin check.\n\t* strings/str2double.m: fix nargin check.\n\n2008-12-29  David Bateman  <dbateman@free.fr>\n\n\t* goemetry/voronoi.m: Speed up and handle dense grids.\n\n2008-12-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* miscellaneous/delete.m: Allow filename globs. Display warnings if\n\toperation fails.\n\n2008-12-26  Francesco Potortì  <pot@gnu.org>\n\n\t* general/prepad.m: Add reference to postpad.\n\n\t* miscellaneous/bincoeff.m: Make reference to nchoosek.\n\n\t* general/postpad.m: Use @seealso.  Add reference to resize.\n\n\t* statistics/base/statistics.m: Correct help string.\n\n\t* plot/hist.m: Doc string now mentions matrix input argument.\n\tCorrect error message.\n\n2008-12-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__contour__.m: __contour__.m: correct order of patches\n\n2008-12-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__contour__.m: __contour__.m: correct order of patches\n\n2008-12-24  Doug Stewart  <dastew@sympatico.ca>\n\n\t* plot/grid.m: Handle \"minor\" option.\n\n2008-12-24  John W. Eaton  <jwe@octave.org>\n\n\t* testfun/test.m: Print \"has no tests\" message if there are demos\n\tbut no tests instead of printing PASSES 0 out of 0 tests.\n\n2008-12-23  David Bateman  <dbateman@free.fr>\n\n\t* sparse/svds.m: New function.\n\t* sparse/Makefile.in (SOURCES): Add it here.\n\n2008-11-21  Radek Salac  <salac.r@gmail.com>\n\n\t* sparse/bicgstab.m: New function.\n\t* sparse/Makefile.in (SOURCES): Add it here.\n\n2008-12-18  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* time/datevec.m (__date_vfmt2sfmt__): New helper function.\n\t(datevec): Avoid repeated parsing of the format string.\n\t* set/unique.m: Only check for options if nargin > 1.\n\n2008-12-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/lsqnonneg.m: Preprocess using QR for over-determined\n\tsystems. Simplify & fix indexing. Use left division for step problem.\n\tFix output args.\n\n2008-12-13  Francesco Potortì  <pot@gnu.org>\n\n\t* specfun/nchoosek.m: Check for input arguments, signal loss of\n\tprecision, correctly handle k==0 and k==n cases, add proper tests.\n\n2008-12-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fsolve.m: Optionally allow pivoted qr factorization.\n\n2008-12-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/expm.m: New source.\n\n2008-12-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* specfun/nchoosek.m: Use a recursionless approach.\n\n2008-12-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/repmat.m: Optimize & simplify the scalar & 2d matrix case.\n\n2008-12-07  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* strings/lower.m: Remove.\n\t* strings/upper.m: Remove.\n\t* strings/Makefile.in: Remove lower.m, upper.m.\n\n2008-12-02  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* strings/str2mat.m: Make it a simple wrapper around\n\tchar() and move it to deprecated/str2mat.m, remove\n\tobsolete tests, move remaining test to src/strfns.cc (Fchar).\n\t* strings/Makefile.in: Remove str2mat.m.\n\t* deprecated/Makefile.in: Add str2mat.m.\n\t* strings/strvcat.m: Remove reference to str2mat.\n\n2008-11-28  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Set two point clipping mode to be on.\n\n2008-11-26  Francesco Potortì  <pot@gnu.org>\n\n\t* specfun/nchoosek.m: Set max_recursion_depth and use a subfunction.\n\n2008-11-29  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* miscellaneous/gzip.m: Remove @seealso reference to __xzip__,\n\timprove tests.\n\t* miscellaneous/bzip2.m: Remove @seealso reference to __xzip__,\n\tfix handling of output argument, add test.\n\t* miscellaneous/__xzip__.m: Improve error messages, fix cleanup\n\tof temporary directories, remove tab characters\n\n2008-11-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/legend.m: Correct ording of legend labels.\n\n2008-11-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Correct order for rendering children.\n\n2008-11-21  Radek Salac  <salac.r@gmail.com>\n\n\t* sparse/cgs.m, sparse/treelayout.m: New functions.\n\t* sparse/Makefile.in (SOURCES): Add them here.\n\n2008-11-14  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m (do_tics_1): Support the minorick properties\n\tof the axis object.\n\n2008-11-14  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/gnuplot_drawnow.m: Add support of properites to gp backend.\n\n2008-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/distributions/chi2rnd.m: Fix another missing semicolon.\n\tFrom sven.mattisson@insatnet.nu.\n\n2008-11-12  David Bateman  <dbateman@free.fr>\n\n\t* plot/__quiver__.m: Only autoscale if more than one element to\n\tplot. Modify callbacks for change in order of children.\n\t* plot/__stem__.m: Modify callbacks for change in order of children.\n\n2008-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/spline.m: Delete debugging statements.  From\n\tSebastian Schöps <sebastian@schoeps.org>.\n\n2008-11-07  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* mkdoc: do not remove white space before @ within @example\n\tenvironment\n\n2008-11-05  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* plot/subplot.m: fix texi bug\n\n2008-11-04  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* miscellaneous/unpack.m: return directly after recursive handling\n\tof cell-strings\n\n2008-11-03  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: xticklabel should accept a numeric vector.\n\n2008-09-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/__fdjac__.m: New function file.\n\t* optimization/__dogleg__.m: New function file.\n\t* optimization/fsolve.m: New function file.\n\t* optimization/Makefile.in: Include the new sources.\n\n2008-09-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fzero.m: Replace tabs by spaces.\n\n2008-09-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fzero.m: Simplify exception handling.\n\n2008-10-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/fzero.m: New function file.\n\t* optimization/Makefile.in: Add it.\n\n2008-10-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/optimset.m: Don't include empty options in option\n\tstructure.\n\t* optimization/optimget.m: New function file.\n\t* optimization/Makefile.in: Add it.\n\t* optimization/lsqnonneg.m: Query options using optimget.\n\n2008-10-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/__norm__.m: Remove.\n\n2008-10-25  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* miscellaneous/bzip2.m, miscellaneous/__xzip__.m: new commands.\n\t* miscellaneous/gzip.m: change to use __xzip__ for actual compression,\n\tadd tests.\n\n2008-10-31  David Bateman  <dbateman@free.fr>\n\n\t* plot/__contour__.m: Exclude infinite values when calculating contour\n\tlevels.\n\t* plot/clabel.m: Close previous plots in demos to avoid pollution\n\tbetween other plot demos.\n\t* plot/plotyy.m: Ditto.\n\n2008-10-30  David Bateman  <dbateman@free.fr>\n\n\t* plot/legend.m: Add support for the \"left\" and \"right\" options.\n\t* plot/__go_draw_axes__.m: If the axes property keyreverse is set,\n\treverse the key and labelling text.\n\n\t* plot/__clabel__.m, plot/clabel.m: New functions.\n\t* plot/Makefile.in (SOURCES): Add them here.\n\t* plot/__contour__.m: Rewrite to use contour groups.\n\t* plot/contourf.m: Call __contour__ instead of using specific code.\n\t* plot/contour.m, plot/contour3.m: Minor modification to allow for\n\tnew interface to __contour__.\n\n2008-10-29  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* set/create_set.m, set/ismember.m, set/union.m, set/complement.m:\n\tFix @seealso references to deprecated function intersection.\n\t* polynomial/polyvalm.m, polynomial/polyout.m,\n\tpolynomial/polyint.m, polynomial/polygcd.m,\n\tdeprecated/polyinteg.m: Remove \"and\" from @seealso string.\n\t* specfun/betaln.m: Change @seealso reference from deprecated\n\tbetai to betainc.\n\t* plot/plot.m, plot/xlabel.m, plot/ylabel.m, plot/zlabel.m,\n\tplot/plot3.m: Fix @seealso references to ylabel and zlabel.\n\t* general/issymmetric.m, image/imagesc.m, specfun/realpow.m,\n\tpolynomial/polyfit.m, time/eomday.m: Remove @seealso references to\n\tnon-existent functions.\n\n2008-10-29  John W. Eaton  <jwe@octave.org>\n\n\t* plot/cla.m: In test, set visible off when creating figure.\n\n2008-10-28  Gabriele Pannocchia  <g.pannocchia@ing.unipi.it>\n\n\t* optimization/qp.m: Convert bounds of the form b <= x <= b and\n\tconstraints of the form b <= A*x <= b to equality constraints.\n\n2008-10-27  Søren Hauberg  <hauberg@gmail.com>\n\n\t* plot/ellipsoid.m: Check nargin == 6, not nargin == 5.\n\n2008-10-22  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/cla.m: Fix error when no children to clear.\n\n\t* plot/findobj.m: Allow handle to be empty.\n\n2008-10-22  John W. Eaton  <jwe@octave.org>\n\n\t* plot/allchild.m: Move call to get showhiddenhandles outside of\n\tunwind_protect block.\n\n2008-10-22  David Bateman  <dbateman@free.fr>\n\n\t* plot/refreshdata.m: Modify demo so that \"y\" is evaluated in the\n\t\"caller\" workspace.\n\n\t* plot/__errplot__.m: Add errorbar series objects.\n\t* plot/errbar.m: Add some demos.\n\n\t* plot/__add_line_series__.m: Remove\n\t* plot/Makefile.in (SOURCES): Remove it here too.\n\t* plot/__add_datasource__.m: Allow for more than one character in\n\tsource name.\n\t* plot/refreshdata.m: Ditto.\n\t* plot/__plt2mm__.m, plot/__plt2mv__.m, plot/__plt2ss__.m,\n\tplot/__plt2sv__.m, plot/__plt2vm__.m, plot/__plt2vv__.m,\n\tplot/__plt2vs__.m, plot3.m: Remove previous line series changes.\n\t* plot/__scatter__.m: Add scatter series objects and data sources.\n\t* plot/legend.m: Update type in loop and remove debugging messages.\n\n2008-10-21  Ben Abbott  <bpabbott@mac.com>\n\n\t* specfun/legendre.m: Warn once on under/overflow.\n\n\t* plot/clf.m: Improve Matlab compatibility.\n\n2008-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* plot/quiver3.m: Turn hold off after demo.\n\n\t* plot/newplot.m: Delete stray debugging code.\n\n\t* plot/gnuplot_drawnow.m: Pass handle to __go_draw_figure__, not\n\tstruct.  Use get instead of examining struct fields directly.\n\t* plot/__go_draw_figure__.m: First arg is now handle, not figure\n\tobject struct.  Use get instead of examining struct elements\n\tdirectly.  Use allhild instead of looking at children field of\n\tfigure object struct.\n\n2008-10-20  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/orient.m: Fix syntax error.\n\n2008-10-20  David Bateman  <dbateman@free.fr>\n\n\t* testfun/rundemos.m: Pause between files, as demo itself doesn't.\n\n\t* plot/fill.m, plot/quiver.m: Quiet the demos.\n\t* plot/stair.m: Treat a line style argument correctly.\n\n2008-10-20  John W. Eaton  <jwe@octave.org>\n\n\t* plot/surfnorm.m: Save and restore hold state.\n\tFrom Daniel J. Sebald <daniel.sebald@ieee.org> and\n\tBen Abbott <bpabbott@mac.com>.\n\n2008-10-20  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/closereq.m: Respect property tag.\n\n\t* plot/__stem__.m: Respect new ordering of children when setting\n\tbaseline.\n\n\t* plot/orient.m, plot/print.m: Properly validate figure handle.\n\n\t* plot/hold.m, plot/comet.m: Properly validate axes handle.\n\n\t* plot/__go_draw_axes__.m: Fix for binary xfer of suface plots.\n\n2008-10-20  David Bateman  <dbateman@free.fr>\n\n\t* plot/plotyy.m: Test that an axes handle actually is one before\n\tsetting it.\n\n2008-10-17  David Bateman  <dbateman@free.fr>\n\n\t* plot/__plt_get_axis_arg__.m: Exclude non-numeric and root figure\n\tfrom potential axis handles.\n\t* plot/colorbar.m: Remove debug output.\n\t* plot/comet.m: Close plot before demo\n\t* plot/contourc.m: No output if nargout == 0.\n\n2008-10-16  David Bateman  <dbateman@free.fr>\n\n\t* plot/subplot.m: Allow for column vector of children for figure.\n\n2008-10-16  John W. Eaton  <jwe@octave.org>\n\n\t* testfun/rundemos.m: New function.\n\n2008-10-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/contourf.m: Correct order of patch object handles.\n\n2008-10-16  David Bateman  <dbateman@free.fr>\n\n\t* plot/colorbar.m (colorbar:resetaxis): Uncomment the reseting of\n\tthe axes.\n\n\t* plot/newplot.m: Don't preserve axes properties here, but rather\n\tdo it in the graphics handle code so that the preservation can be\n\tdone after callbacks are executed.\n\n\t* plot/__go_draw_axes__.m: If current plot is an image, don't flag\n\tthe plot as binary, as the binary specification is already in the\n\t\"usingclause\".\n\n\t* plot/__go_draw_figure__.m: Always use multiplot and create an\n\tenclosing axis to ensure bounding box of postscript is correct.\n\n2008-10-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m (do_tics_1): New arg, interpreter.\n\t(do_tics): Pass interpreter to do_tics_1.\n\n2008-10-15  David Bateman  <dbateman@free.fr>\n\n\t* general/colon.m: Small typo.\n\t* general/loadobj.m: Ditto.\n\n2008-10-14  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m (do_tics_1): New args, fontname and fontsize.\n\tPass fontspec for tic marks to gnuplot.\n\t(do_tics): Pass axes fontname and fontsize to do_tics_1.\n\n\t* plot/newplot.m: Perserve fontangle, fontname, fontsize,\n\tfontunits, fontweight, position, outerposition, and\n\tactivepositionproperty axes properties when replacing plot.\n\n2008-10-15  Daniel J. Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/__go_draw_axes__.m: Make previous change work for surface\n\tplots.\n\n2008-10-14  Daniel J. Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/__go_draw_axes__.m: Send binary data to gnuplot.\n\n2008-10-13  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Fix concatenation of handles.\n\n2008-10-12  David Bateman  <dbateman@free.fr>\n\n\t* general/colon..m: New function.\n\t* general/Makefile.in (SOURCES): Add it here.\n\n2008-10-10  David Bateman  <dbateman@free.fr>\n\n\t* image/__img__.m: Manually set the limits of th eimage\n\t* plot/__go_draw_axes__.m: Base window position in the axis\n\tposition property and not the outerposition property. Remove\n\tcolorbar code based on the gnuplot colorbox. Allow images to be a\n\tvector to support image based colorbars. Also check labelmode for\n\tmanual tics.\n\t* plot/__go_draw_figure__.m: Remove gnuplot colorbox based\n\tcolorbar code.\n\t* plot/colorbar.m: Rewrite to use an image and callbacks to link\n\tit to the principal axis.\n\t* plot/legend.m: Support an axis handle as the first\n\targument. Support hggroups.\n\t* plot/pareto.m: Don't support an axis handle as the first\n\targument as the plotyy command in fact needs two axis handles.\n\t* plot/plotyy.m: Rewrite to use listeners and callbacks to\n\tsynchronize the two axes.\n\t* plot/subplot.m: Also skip axes that are tagged as being a\n\tcolorbar. Don't break in search of overlapping axes to delete. Set\n\tboth the position and the outerposition.\n\n2008-10-09  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__axis_label__.m: Inherit font properties from axes.\n\n2008-10-09  David Bateman  <dbateman@free.fr>\n\n\t* general/loadobj.m, general/saveobj.m, general/display: New functions\n\t* general/Makefile.in (SOURCES): Add then here.\n\n2008-10-08  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/fileparts.m: Handle \"/file\" properly.\n\tImprove compatibility.\n\n2008-10-07  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/cla.m: New function.\n\t* plot/Makefile.in (SOURCES): Add it to the list.\n\n2008-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/delete.m: Pass array of handles to __go_delete__.\n\n2008-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__add_datasource__.m, plot/__axes_limits__.m,\n\tplot/__bar__.m, plot/__bars__.m, plot/__contour__.m,\n\tplot/__go_draw_axes__.m, plot/__go_draw_figure__.m,\n\tplot/__patch__.m, plot/__quiver__.m, plot/__scatter__.m,\n\tplot/__stem__.m, plot/ancestor.m, plot/axis.m, plot/box.m,\n\tplot/caxis.m, plot/close.m, plot/colorbar.m, plot/fill.m,\n\tplot/findobj.m, plot/grid.m, plot/hidden.m, plot/hold.m,\n\tplot/ishold.m, plot/legend.m, plot/linkprop.m, plot/orient.m,\n\tplot/plotmatrix.m, plot/shading.m: Use case-insensitive comparison\n\tfor properties.  Misc style fixes.\n\n2008-10-06  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/orient.m: Figure handle must be scalar.\n\t* plot/hold.m: Axis handle must be scalar.\n\t* plot/axes.m: Axis handle must be scalar.\n\t* plot/__plt_get_axis_arg__.m: Handle must be scalar.\n\n\t* miscellaneous/delete.m: Permit a vector of handles to be deleted.\n\n2008-10-02  John W. Eaton  <jwe@octave.org>\n\n\t* pkg/pkg.m (configure_make): Handle filenames with spaces.\n\n2008-10-02  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* pkg.m (configure_make): Enclose building directory in quotes.\n\n2008-10-02  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Remove depdenence on gnuplot version.\n\n2008-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* string/split.m: New tests.\n\n2008-09-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/__go_draw_axes__.m: Fix interpolation of facecolors.\n\n\t* plot/shading.m: New demo.\n\n2008-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Eliminate have_newer_gnuplot variable.\n\n\t* plot/__gnuplot_version__.m: Also include patchlevel.\n\n2008-09-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/deconv.m: Fix row/col orientation & length of output.\n\n\t* polynomial/conv.m: Correct row/col orientation of output.\n\n2008-09-27  Ivan Sutoris  <ivan.sutoris@gmail.com>\n\n\t* optimization/sqp.m: Document additional parameters.\n\n2008-09-26  David Bateman  <dbateman@free.fr>\n\n\t* general/subsindex.m: Dummy subsindex function for help string\n\tand to throw error for use outside of a class\n\t* general/Makefile.in (SOURCES): Include it here.\n\n2008-09-26  John W. Eaton  <jwe@octave.org>\n\n\t* image/imfinfo.m: Delete temporary file.\n\n2008-09-25  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/imread.m, image/imwrite.m: Doc fix.\n\n2008-09-24  John W. Eaton  <jwe@octave.org>\n\n\t* plot/fplot.m: Call axis after calling plot.\n\n2008-09-24  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/imfinfo.m: New function.\n\t* image/Makefile.in (SOURCES): Add it to the list.\n\n2008-09-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* strings/strcat.m: Improve Matlab compatibility for non-character\n\tdata.\n\n2008-09-24  John W. Eaton  <jwe@octave.org>\n\n\t* general/interpft.m: Increase tolerance in tests.\n\n2008-09-23  Francesco Potorti`  <Potorti@isti.cnr.it>\n\n\t* plot/pcolor.m: Improve doc string.\n\n2008-09-22 Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/comet.m: New file.\n\t* plot/Makefile.in (SOURCES): Add it here.\n\n2008-09-22  David Bateman  <dbateman@free.fr>\n\n\t* plot/plotmatrix.m: New function.\n\t* plot/Makefile.in (SOURCES): Add it here.\n\n\t* general/quadgk.m: No function count in quadgk and so don't try and\n\tprint it when given trace argument.\n\n2008-09-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/blkdiag.m: Skip assignment if rhs is empty.\n\n2008-09-18  Kris Thielemans  <kris.thielemans@csc.mrc.ac.uk>\n\n\t* image/imshow.m: Fix for display_range.\n\n\t* general/interpn.m: Fixe for extrapval and documentation of\n\textrapval.\n\n2008-09-17  David Bateman  <dbateman@free.fr>\n\n\t* time/datetick.m: New function.\n\t* time/Makefile.in (SOURCES): Add it here.\n\t* time/datestr.m: More careful check for datevec format with 6\n\tcolumn arguments.\n\t* plot/__go_draw_axes__ (do_tics_1): Use %.15g format rather than\n\t%g format. Also use manual mode if xlabelmode is manual.\n\n\t* general/cell2mat.m: Backout previous change. Special case 2D\n\tcase for speed.\n\n2008-09-11  David Bateman  <dbateman@free.fr>\n\n\t* general/cell2mat.m: Improve the speed.\n\n2008-09-09  John W. Eaton  <jwe@octave.org>\n\n\t* time/datestr.m: Convert format and use strftime to do most of\n\tthe actual conversion.\n\n2008-09-08  Tatsuro MATSUOKA  <tmacchant@yahoo.co.jp>\n\n\t* plot/plot.m: Doc fix.\n\n2008-09-08  Mark van Rossum  <mvanross@inf.ed.ac.uk>\n\n\t* statistics/distributions/binornd.m: Handle zero values of n\n\tcorrectly.\n\n2008-09-08  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/contourf.m: Fix case for equal-sized matrices\n\tof X and Y.\n\n2008-09-02  David Bateman  <dbateman@free.fr>\n\n\t* plot/__add_datasource__.m: Fix indexing of varargin.\n\n\t* plot/__line__.m: Remove empty clause fof if/then/else test\n\t* plot/plot3.m: Correctly plot matrices.\n\n2008-08-31  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/__plt2mm__.m, plot/__plt2mv__.m, plot/__plt2ss__.m,\n\tplot/__plt2sv__.m, plot/__plt2vm__.m, plot/__plt2vs__.m,\n\tplot/__plt2vv__.m: Do not call \"set\" with empty arguments.\n\n2008-08-29  David Bateman  <dbateman@free.fr>\n\n\t* plot/__plt2mm__.m, plot/__plt2mv__.m, plot/__plt2ss__.m,\n\tplot/__plt2sv__.m, plot/__plt2vm__.m, plot/__plt2vs__.m,\n\tplot/__plt2vv__.m, plot/plot3.m, plot/__area__.m, plot/__bars__.m,\n\tplot/__quiver__.m, plot/__stem__.m, plot/stairs.m :\n\tPass additional prop/val pairs to hggroup rather than underlying\n\tobjects. If a baseline existings specifically associate it with\n\tthe parent of the created hggroup to allow things like \"stem(...,\n\t'parent', hg)\" to work correctly.\n\t* plot/hold.m: If currentaxes if figure doesn't exist, create it.\n\n\t* plot/plot3.m: Pass hline to __add_line_series__.\n\t* plot/__add_datasource__.m: Fix off by one error.\n\n2008-08-28  David Bateman  <dbateman@free.fr>\n\n\t* plot/__add_line_series__.m, plot/ishghandle.m, plot/linkprop.m,\n\tplot/refresh.m, plot/refreshdata.m: New functions\n\t* Makefile.in (SOURCES): Add them here.\n\n\t* plot/__area__.m, plot/__bars__.m, plot/__quiver__.m,\n\tplot/__stem__.m, plot/stairs.m, plot/stem.m: Add data sources.\n\n\t* plot/__plt2mm__.m, plot/__plt2mv__.m, plot/__plt2ss__.m,\n\tplot/__plt2sv__.m, plot/__plt2vm__.m, plot/__plt2vs__.m,\n\tplot/__plt2vv__.m, plot/plot3.m: Add line series and data sources.\n\n2008-08-28  Martin Weiser  <weiser2@natur.cuni.cz>\n\n\t* plot/scatter3.m: Doc fix.\n\n2008-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* plot/hold.m: If hold is applied to a figure, set state for all\n\tchild axes objects.\n\n2008-08-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/backend.m: New function to handle backend switch.\n\t* plot/Makefile.in: Add it.\n\n2008-08-26  David Bateman  <dbateman@free.fr>\n\n\t* plot/__area__.m: Use __next_line_color__ rather than fixed set\n\tof colors. Convert to use area series objects.\n\t* plot/area.m: Update documentation to correspond to\n\tthe area series usage.\n\t* plot/__bar.m: Pass the original rather than scaled width to\n\t__bars__.\n\t* plot/__bars__.m: Convert to use bar series objects.\n\t* plot/bar.m, plor/barh.m:  Update documentation to correspond to\n\tthe bar series usage.\n\t* plot/__quiver__.m: Convert to use quiver series objects. Change\n\tthe default scaling and arrowsize for compatibility.\n\t* plot/quiver.m:  Update documentation to correspond to\n\tthe quiver series usage.\n\t* plot/stairs.m: Convert to use stair series objects.\n\t* plot/stem.m: Don't include baseline in xlim calculation. Correct\n\ttest of whether baseline xdata needs updating in the update_xlim\n\tcallback.\n\n2008-08-25  Thomas L. Scofield  <scofield@calvin.edu>\n\n\t* image/imwrite.m: Add ras and tiff to the list of accepted formats.\n\tHandle parameter-value options.  Untabify.\n\n2008-08-25  David Bateman  <dbateman@free.fr>\n\n\t* plot/__stem__.m: Use property inheritance and don't explicitly\n\tcall drawnow.\n\n\t* plot/__go_draw_axes__.m: Respect the \"visible\" property of object and\n\tdon't draw them if the object is not visible.\n\n\t* plot/__stem__.m: Convert to use stem series object.\n\t* plot/stem.m, plot/stem3.m: Update documentation to correspond to\n\tthe stem series usage.\n\n2008-08-22  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/distributions/chi2rnd.m: Fix missing semicolon.\n\n2008-08-21  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Fix test for have_data.\n\t(__gnuplot_write_data__): Write \"Inf Inf\\n\" if all data pairs\n\tcontain NaN values.\n\n2008-08-21  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* optimization/sqp.m: Increase test script tolerance.\n\n2008-08-21  David Bateman  <dbateman@free.fr>\n\n\t* plot/ezplot.m : New function.\n\t* plot/Makefile.in (SOURCES): Add ezplot.m to the list.\n\t* plot/__ezplot__.m: Adapt to allow for use with the ezplot function.\n\n2008-08-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pkg/pkg.m (configure_make): Pass handle to is_architecture_dependent\n\tdirectly.\n\n2008-08-20  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Don't set pm3d implicit if the plot\n\tcontains a surface. Fixes things like meshc(peaks()).\n\n2008-08-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* optimization/glpk.m: Fix invalid call to zeros.\n\n2008-08-19  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/intwarning.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add it here.\n\n\t* statistics/base/ranks.m: Doc fix.\n\n2008-08-08  John W. Eaton  <jwe@octave.org>\n\n\t* general/Makefile.in (SOURCES): Add cellidx.m to the list.\n\n2008-08-07  John W. Eaton  <jwe@octave.org>\n\n\t* gethelp.cc: Delete definition of NPOS.\n\n2008-08-04  John W. Eaton  <jwe@octave.org>\n\n\t* strings/strtok.m: Include TAB, LF, VT, FF, and CR in default\n\tlist of delim characters.  Update tests.\n\n2008-07-29  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* general/arrayfun.m: Minor bug fixes, update help text and tests\n\n2008-07-29  John W. Eaton  <jwe@octave.org>\n\n\t* plot/axis.m (__get_tight_lims__): Use strcat instead of [].\n\tDon't fail if data is not a vector.\n\n2008-07-29  David Bateman  <dbateman@free.fr>\n\n\t* general/cellidx.m: reinclude from control toolbox, as used by\n\tprint command. Replace is_signal_list with iscellstr.\n\t* general/quadqk.m, linear-algebra/planeror.m,\n\tmiscellaneous/namelengthmax.m, specfun/realpow.m: Miscellaneous\n\tdocumentation fixes.\n\n\t* control, finance, quaternion: Remove directories and all of the\n\tfiles they contain.\n\t* Makefile.in: Remove all references to the above directories.\n\t* configure.in: ditto.\n\n2008-07-28  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/hold.m: Clarify help text.\n\n\t* specfun/reallog.m: Fix help string.\n\n2008-07-28  David Bateman  <dbateman@free.fr>\n\n\t* strings/regexptranslate.m: Add real documentation.\n\n\t* plot/contourf.m: Allow X,Y to be unequal vectors.\n\n\t* plot/shading.m: Clarify help string.\n\n\t* general/genvarname.m: Trivial documentation fix.\n\n2008-07-28  John W. Eaton  <jwe@octave.org>\n\n\t* image/imwrite.m: New function.\n\t* image/Makefile.in (SOURCES): Add it to the list.\n\n2008-07-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* time/datestr.m: New xtest.\n\n2008-07-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/closereq.m: Use first gcbf to get the handle of the figure to\n\tbe closed.\n\t* plot/close.m: Call __go_execute_callback__.\n\n2008-07-17  John W. Eaton  <jwe@octave.org>\n\n\t* general/fliplr.m: Fix usage test.\n\t* testfun/test.m: Fix usage tests.\n\n2008-07-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/base/cov.m: Fix test that should no longer work.\n\n2008-07-16  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/gcbo.m, plot/gcbf.m: New functions.\n\t* plot/Makefile.in (SOURCES): Add them to the list.\n\n2008-07-16  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/loadimage.m: New file.\n\t* deprecated/Makefile.in (SOURCES): Add it to the list.\n\t* image/loadimage.m: Delete.\n\t* image/Makefile.in (SOURCES): Remove it from the list.\n\t* image/imread.m: Incorporate loadimage functionality here.\n\tSimplify.\n\t* image/imshow.m: Call imread, not loadimage.\n\n\t* image/__img__.m: Set clim for true-color integer data.\n\n\t* image/imshow.m: Don't convert integer true-color data to double.\n\n\t* plot/__go_draw_axes__.m: Recognize 3-d cdata as a true-color image.\n\n2008-07-14  John W. Eaton  <jwe@octave.org>\n\n\t* image/Makefile.in (SOURCES): Add imread.m to the list.\n\n2008-07-14  Thomas L. Scofield  <scofield@calvin.edu>\n\n\t* image/imread.m: New file from Octave Forge.\n\n2008-07-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* set/unique.m: Implement 'first' and 'last', some simplifications.\n\t* set/union.m: Implement output indices.\n\t* set/intersect.m: Implement 'rows'.\n\t* set/setdiff.m: Implement output indices.\n\t* set/setxor.m: Implement 'rows' and output indices.\n\tAdd tests and adjust docs in all of the above.\n\n2008-06-11  John W. Eaton  <jwe@octave.org>\n\n\t* set/ismember.m: Fix fail tests.\n\n\t* general/rat.m: Properly initialize steps when all elements of\n\tinput array are integers.  Append spaces as necessary when\n\tbuilding  character array.\n\n2008-06-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* plot/__go_draw_axes__.m: Use fprintf for formatted output.\n\n2008-06-04  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/__go_draw_axes__.m: Support hggroup objects.\n\t* plot/hggroup.m: New file.\n\t* plot/Makefile.in: Handle it.\n\n2008-06-02  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/debug.m: New file..\n\t* Makefile.in (SOURCES): Add it to the list.\n\n\t* general/interp1q.m: Remove spaces between functions and args in\n\t[]. Fix test code to actually test interp1q.\n\n2008-06-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strings/strcat.m: Add tests.\n\n2008-06-02  Kim Hansen  <kimhanse@gmail.com>\n\n\t* strings/mat2str.m: Change is_complex to iscomplex, add tests, add\n\tmissing ;\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/single.m: Remove.\n\t* Makefile.in (SOURCES): Remove it here as well.\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* general/interp1q.m: New function.\n\t* general/Makefile.in (SOURCES): Add it here.\n\n2008-05-20  Bill Denney  <bill@denney.ws>\n\n\t* time/datenum.m: Allow mixed scalar and vector/matrix input.\n\tNew tests.\n\n2008-05-19  John W. Eaton  <jwe@octave.org>\n\n\t* general/isa.m: Fix tests.\n\n2008-05-13  Bill Denney  <bill@denney.ws>\n\n\t* general/isa.m: Use persistent cell arrays to hold class names\n\tinstead of multiple strcmp calls.\n\n2008-05-12  David Bateman  <dbateman@free.fr>\n\n\t* control/base/__stepimp__.m, control/base/bode_bounds.m,\n\tcontrol/base/damp.m, control/base/dlqr.m, control/base/lsim.m,\n\tcontrol/base/tzero.m, control/hinf/hinfsyn.m,\n\tcontrol/hinf/is_dgkf.m, control/system/d2c.m,\n\tcontrol/system/is_controllable.m, control/system/is_detectable.m,\n\tcontrol/system/is_stabilizable.m, control/system/is_stable.m,\n\tcontrol/system/sysconnect.m, general/bicubic.m,\n\tgeneral/cplxpair.m, general/isdefinite.m, general/issymmetric.m,\n\tgeneral/quadgk.m, general/quadl.m, general/quadv.m,\n\tgeometry/delaunayn.m, linear-algebra/krylov.m,\n\tlinear-algebra/null.m, linear-algebra/onenormest.m,\n\tlinear-algebra/orth.m, linear-algebra/rank.m,\n\tlinear-algebra/rref.m, optimization/qp.m, optimization/sqp.m,\n\tpolynomial/polygcd.m, polynomial/residue.m, sparse/normest.m,\n\tspecfun/erfinv.m, statistics/distributions/betainv.m,\n\tstatistics/distributions/gaminv.m,\n\tstatistics/distributions/kolmogorov_smirnov_cdf.m,\n\tstatistics/tests/manova.m: Modify calls to eps to allow for single\n\tprecision types.\n\n\t* general/isa.m: Also treat \"float: and \"numeric\" as the class\n\targument.\n\n\t* general/dblquad.m, general/quadgk.m, general/quadv.m,\n\tgeneral/triplequad.m: New functions.\n\n\t* testfun/assert.m: Allow assert(cond, errmsg, ...) and\n\tassert(cond, msgid, errmsg, ...) syntax for compatibility.\n\n2008-05-09  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* miscellaneous/news.m: Replace deprecated isstr call.\n\n2008-05-06  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/symvar.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add it to the list.\n\n2008-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/dbstack.m: Delete.\n\t* miscellaneous/Makefile.in (SOURCES): Remove it from the list.\n\n2008-05-03  Rafael Laboissiere  <rafael@debian.org>\n\n\t* linear-algebra/cond.m, miscellaneous/version.m,\n\tmiscellaneous/version.m, plot/feather.m, plot/__bar__.m,\n\tplot/compass.m, plot/__quiver__.m, plot/__scatter__.m: Use ischar\n\tinstead of deprecated isstr.\n\n2008-05-01  David Bateman  <dbateman@free.fr>\n\n\t* plot/plot.m: Remove documentation of 'L' option.\n\t* plot/stairs.m: Allow axis handles, properties and linespecs to\n\tbe passed.\n\n2008-04-30  John W. Eaton  <jwe@octave.org>\n\n\t* elfun/acot.m, elfun/acsc.m, elfun/acsch.m, elfun/asec.m,\n\telfun/asech.m, specfun/pow2.m: Fix tests.\n\n2008-04-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* specfun/log2.m: Delete.\n\t* specfun/Makefile.in (SOURCES): Delete it from the list.\n\n2008-04-29  David Bateman  <dbateman@free.fr>\n\n\tpkg/pkg.m: Also set archprefix with the -local and -global options.\n\n2008-04-29  Jonathan Stickel  <jjstickel@vcn.com>\n\n\t* statistics/distributions/tcdf.m, statistics/distributions/tinv.m:\n\tDoc fix.\n\n2008-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/dbstack.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add it to the list.\n\n2008-04-21  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m (gnuplot_position_colorbox): New arg, obj.\n\tChange caller.  Improve sizing and position of colorbox for subplots.\n\t* plot/colorbar.m: New demos.\n\n2008-04-16  Søren Hauberg  <hauberg@gmail.com>\n\n\t* plot/__gnuplot_version__.m: Display error if gnuplot is not found.\n\n2008-04-15  John W. Eaton  <jwe@octave.org>\n\n\t* plot/view.m: Get values from current axes if nargin == 0.\n\n2008-04-15  David Bateman  <dbateman@free.fr>\n\n\t* plot/__patch__.m: Fix for NaN values in faces of patches.\n\n2008-04-14  David Bateman  <dbateman@free.fr>\n\n\t* plot/rose.m: Add missing comment mark that causes issues with\n\toctave-forge function referencing.\n\t* deprecated/lchol.m, deprecated/splchol.m: Fix texinfo errors.\n\n2008-04-09  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/beta_cdf.m, deprecated/beta_inv.m,\n\tdeprecated/beta_pdf.m, deprecated/beta_rnd.m,\n\tdeprecated/binomial_cdf.m, deprecated/binomial_inv.m,\n\tdeprecated/binomial_pdf.m, deprecated/binomial_rnd.m,\n\tdeprecated/chisquare_cdf.m, deprecated/chisquare_inv.m,\n\tdeprecated/chisquare_pdf.m, deprecated/chisquare_rnd.m,\n\tdeprecated/clearplot.m, deprecated/clg.m, deprecated/com2str.m,\n\tdeprecated/exponential_cdf.m, deprecated/exponential_inv.m,\n\tdeprecated/exponential_pdf.m, deprecated/exponential_rnd.m,\n\tdeprecated/f_cdf.m, deprecated/f_inv.m, deprecated/f_pdf.m,\n\tdeprecated/f_rnd.m, deprecated/gamma_cdf.m,\n\tdeprecated/gamma_inv.m, deprecated/gamma_pdf.m,\n\tdeprecated/gamma_rnd.m, deprecated/geometric_cdf.m,\n\tdeprecated/geometric_inv.m, deprecated/geometric_pdf.m,\n\tdeprecated/geometric_rnd.m, deprecated/hypergeometric_cdf.m,\n\tdeprecated/hypergeometric_inv.m, deprecated/hypergeometric_pdf.m,\n\tdeprecated/hypergeometric_rnd.m, deprecated/intersection.m,\n\tdeprecated/is_bool.m, deprecated/is_complex.m,\n\tdeprecated/is_list.m, deprecated/is_matrix.m,\n\tdeprecated/is_scalar.m, deprecated/is_square.m,\n\tdeprecated/is_stream.m, deprecated/is_struct.m,\n\tdeprecated/is_symmetric.m, deprecated/is_vector.m,\n\tdeprecated/isstr.m, deprecated/lchol.m,\n\tdeprecated/lognormal_cdf.m, deprecated/lognormal_inv.m,\n\tdeprecated/lognormal_pdf.m, deprecated/lognormal_rnd.m,\n\tdeprecated/meshdom.m, deprecated/normal_cdf.m,\n\tdeprecated/normal_inv.m, deprecated/normal_pdf.m,\n\tdeprecated/normal_rnd.m, deprecated/pascal_cdf.m,\n\tdeprecated/pascal_inv.m, deprecated/pascal_pdf.m,\n\tdeprecated/pascal_rnd.m, deprecated/poisson_cdf.m,\n\tdeprecated/poisson_inv.m, deprecated/poisson_pdf.m,\n\tdeprecated/poisson_rnd.m, deprecated/polyinteg.m,\n\tdeprecated/setstr.m, deprecated/spatan2.m, deprecated/spchol.m,\n\tdeprecated/spchol2inv.m, deprecated/spcholinv.m,\n\tdeprecated/spcumprod.m, deprecated/spcumsum.m, deprecated/spdet.m,\n\tdeprecated/spdiag.m, deprecated/spfind.m, deprecated/spinv.m,\n\tdeprecated/spkron.m, deprecated/splchol.m, deprecated/splu.m,\n\tdeprecated/spmax.m, deprecated/spmin.m, deprecated/spprod.m,\n\tdeprecated/spqr.m, deprecated/spsum.m, deprecated/spsumsq.m,\n\tdeprecated/struct_contains.m, deprecated/struct_elements.m,\n\tdeprecated/t_cdf.m, deprecated/t_inv.m, deprecated/t_pdf.m,\n\tdeprecated/t_rnd.m, deprecated/uniform_cdf.m,\n\tdeprecated/uniform_inv.m, deprecated/uniform_pdf.m,\n\tdeprecated/uniform_rnd.m, deprecated/weibcdf.m,\n\tdeprecated/weibinv.m, deprecated/weibpdf.m, deprecated/weibrnd.m,\n\tdeprecated/weibull_cdf.m, deprecated/weibull_inv.m,\n\tdeprecated/weibull_pdf.m, deprecated/weibull_rnd.m,\n\tdeprecated/wiener_rnd.m: Don't embed newline in warning message.\n\n2008-04-09  David Bateman  <dbateman@free.fr>\n\n\t* testfun/assert.m: Don't allow cond and expected to be lists.\n\n2008-04-04  John W. Eaton  <jwe@octave.org>\n\n\t* strings/Makefile.in (SOURCES): Add isstrprop.m to the list.\n\n\t* Makefile.in, audio/Makefile.in, control/Makefile.in,\n\t* Makefile.incontrol/base/Makefile.in, control/hinf/Makefile.in,\n\t* Makefile.incontrol/obsolete/Makefile.in,\n\t* Makefile.incontrol/system/Makefile.in, control/util/Makefile.in,\n\t* Makefile.indeprecated/Makefile.in, elfun/Makefile.in,\n\t* Makefile.infinance/Makefile.in, general/Makefile.in,\n\t* Makefile.ingeometry/Makefile.in, image/Makefile.in,\n\t* Makefile.inio/Makefile.in, linear-algebra/Makefile.in,\n\t* Makefile.inmiscellaneous/Makefile.in, optimization/Makefile.in,\n\t* Makefile.inpath/Makefile.in, pkg/Makefile.in, plot/Makefile.in,\n\t* Makefile.inpolynomial/Makefile.in, quaternion/Makefile.in,\n\t* Makefile.inset/Makefile.in, signal/Makefile.in,\n\t* Makefile.insparse/Makefile.in, specfun/Makefile.in,\n\t* Makefile.inspecial-matrix/Makefile.in, startup/Makefile.in,\n\t* Makefile.instatistics/Makefile.in, statistics/base/Makefile.in,\n\t* Makefile.instatistics/distributions/Makefile.in,\n\t* Makefile.instatistics/models/Makefile.in,\n\t* Makefile.instatistics/tests/Makefile.in, strings/Makefile.in,\n\t* Makefile.intestfun/Makefile.in, time/Makefile.in\n\t* Makefile.in(check-m-sources): New target.\n\n2008-04-04  Bill Denney  <bill@denney.ws>\n\n\t* optimization/lsqnonneg.m: Use optimset, correctly index\n\tZ and P in main loop.\n\n2008-04-04  David Bateman  <dbateman@free.fr>\n\n\t* deprecated/beta_cdf.m deprecated/beta_inv.m\n\tdeprecated/beta_pdf.m deprecated/beta_rnd.m\n\tdeprecated/binomial_cdf.m deprecated/binomial_inv.m\n\tdeprecated/binomial_pdf.m deprecated/binomial_rnd.m\n\tdeprecated/chisquare_cdf.m deprecated/chisquare_inv.m\n\tdeprecated/chisquare_pdf.m deprecated/chisquare_rnd.m\n\tdeprecated/clearplot.m deprecated/clg.m deprecated/com2str.m\n\tdeprecated/exponential_cdf.m deprecated/exponential_inv.m\n\tdeprecated/exponential_pdf.m deprecated/exponential_rnd.m\n\tdeprecated/f_cdf.m deprecated/f_inv.m deprecated/f_pdf.m\n\tdeprecated/f_rnd.m deprecated/gamma_cdf.m deprecated/gamma_inv.m\n\tdeprecated/gamma_pdf.m deprecated/gamma_rnd.m\n\tdeprecated/geometric_cdf.m deprecated/geometric_inv.m\n\tdeprecated/geometric_pdf.m deprecated/geometric_rnd.m\n\tdeprecated/hypergeometric_cdf.m deprecated/hypergeometric_inv.m\n\tdeprecated/hypergeometric_pdf.m deprecated/hypergeometric_rnd.m\n\tdeprecated/intersection.m deprecated/is_bool.m\n\tdeprecated/is_complex.m deprecated/is_list.m\n\tdeprecated/is_matrix.m deprecated/is_scalar.m\n\tdeprecated/is_square.m deprecated/is_stream.m deprecated/isstr.m\n\tdeprecated/is_struct.m deprecated/is_symmetric.m\n\tdeprecated/is_vector.m deprecated/lognormal_cdf.m\n\tdeprecated/lognormal_inv.m deprecated/lognormal_pdf.m\n\tdeprecated/lognormal_rnd.m deprecated/meshdom.m\n\tdeprecated/normal_cdf.m deprecated/normal_inv.m\n\tdeprecated/normal_pdf.m deprecated/normal_rnd.m\n\tdeprecated/pascal_cdf.m deprecated/pascal_inv.m\n\tdeprecated/pascal_pdf.m deprecated/pascal_rnd.m\n\tdeprecated/poisson_cdf.m deprecated/poisson_inv.m\n\tdeprecated/poisson_pdf.m deprecated/poisson_rnd.m\n\tdeprecated/polyinteg.m deprecated/setstr.m\n\tdeprecated/struct_contains.m deprecated/struct_elements.m\n\tdeprecated/t_cdf.m deprecated/t_inv.m deprecated/t_pdf.m\n\tdeprecated/t_rnd.m deprecated/uniform_cdf.m\n\tdeprecated/uniform_inv.m deprecated/uniform_pdf.m\n\tdeprecated/uniform_rnd.m deprecated/weibcdf.m deprecated/weibinv.m\n\tdeprecated/weibpdf.m deprecated/weibrnd.m deprecated/weibull_cdf.m\n\tdeprecated/weibull_inv.m deprecated/weibull_pdf.m\n\tdeprecated/weibull_rnd.m deprecated/wiener_rnd.m: Add warning that\n\tfunction will be removed in a future version.\n\n2008-04-03  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/beta_cdf.m, deprecated/beta_inv.m,\n\tdeprecated/beta_pdf.m, deprecated/beta_rnd.m,\n\tdeprecated/binomial_cdf.m, deprecated/binomial_inv.m,\n\tdeprecated/binomial_pdf.m, deprecated/binomial_rnd.m,\n\tdeprecated/chisquare_cdf.m, deprecated/chisquare_inv.m,\n\tdeprecated/chisquare_pdf.m, deprecated/chisquare_rnd.m,\n\tdeprecated/clearplot.m, deprecated/clg.m, deprecated/com2str.m,\n\tdeprecated/exponential_cdf.m, deprecated/exponential_inv.m,\n\tdeprecated/exponential_pdf.m, deprecated/exponential_rnd.m,\n\tdeprecated/f_cdf.m, deprecated/f_inv.m, deprecated/f_pdf.m,\n\tdeprecated/f_rnd.m, deprecated/gamma_cdf.m,\n\tdeprecated/gamma_inv.m, deprecated/gamma_pdf.m,\n\tdeprecated/gamma_rnd.m, deprecated/geometric_cdf.m,\n\tdeprecated/geometric_inv.m, deprecated/geometric_pdf.m,\n\tdeprecated/geometric_rnd.m, deprecated/hypergeometric_cdf.m,\n\tdeprecated/hypergeometric_inv.m, deprecated/hypergeometric_pdf.m,\n\tdeprecated/hypergeometric_rnd.m, deprecated/intersection.m,\n\tdeprecated/is_bool.m, deprecated/is_complex.m,\n\tdeprecated/is_list.m, deprecated/is_matrix.m,\n\tdeprecated/is_scalar.m, deprecated/is_square.m,\n\tdeprecated/is_stream.m, deprecated/is_struct.m,\n\tdeprecated/is_symmetric.m, deprecated/is_vector.m,\n\tdeprecated/isstr.m, deprecated/lchol.m,\n\tdeprecated/lognormal_cdf.m, deprecated/lognormal_inv.m,\n\tdeprecated/lognormal_pdf.m, deprecated/lognormal_rnd.m,\n\tdeprecated/meshdom.m, deprecated/normal_cdf.m,\n\tdeprecated/normal_inv.m, deprecated/normal_pdf.m,\n\tdeprecated/normal_rnd.m, deprecated/pascal_cdf.m,\n\tdeprecated/pascal_inv.m, deprecated/pascal_pdf.m,\n\tdeprecated/pascal_rnd.m, deprecated/poisson_cdf.m,\n\tdeprecated/poisson_inv.m, deprecated/poisson_pdf.m,\n\tdeprecated/poisson_rnd.m, deprecated/polyinteg.m,\n\tdeprecated/setstr.m, deprecated/spatan2.m, deprecated/spchol.m,\n\tdeprecated/spchol2inv.m, deprecated/spcholinv.m,\n\tdeprecated/spcumprod.m, deprecated/spcumsum.m, deprecated/spdet.m,\n\tdeprecated/spdiag.m, deprecated/spfind.m, deprecated/spinv.m,\n\tdeprecated/spkron.m, deprecated/splchol.m, deprecated/splu.m,\n\tdeprecated/spmax.m, deprecated/spmin.m, deprecated/spprod.m,\n\tdeprecated/spqr.m, deprecated/spsum.m, deprecated/spsumsq.m,\n\tdeprecated/struct_contains.m, deprecated/struct_elements.m,\n\tdeprecated/t_cdf.m, deprecated/t_inv.m, deprecated/t_pdf.m,\n\tdeprecated/t_rnd.m, deprecated/uniform_cdf.m,\n\tdeprecated/uniform_inv.m, deprecated/uniform_pdf.m,\n\tdeprecated/uniform_rnd.m, deprecated/weibcdf.m,\n\tdeprecated/weibinv.m, deprecated/weibpdf.m, deprecated/weibrnd.m,\n\tdeprecated/weibull_cdf.m, deprecated/weibull_inv.m,\n\tdeprecated/weibull_pdf.m, deprecated/weibull_rnd.m,\n\tdeprecated/wiener_rnd.m:\n\tNote version when function was deprecated.\n\n2008-04-03  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Conditionally \"set pm3d implict\" for 2D\n\tplot or 3D plots with more than one line.\n\n\t* deprecated/splchol.m deprecated/lchol.m deprecated/spfind.m\n\tdeprecated/spchol.m deprecated/spmin.m deprecated/spmax.m\n\tdeprecated/spdet.m deprecated/splu.m deprecated/spqr.m\n\tdeprecated/spatan2.m deprecated/spchol2inv.m\n\tdeprecated/spcholinv.m deprecated/spcumprod.m deprecated/spdiag.m\n\tdeprecated/spinv.m deprecated/spcumsum.m deprecated/spprod.m\n\tdeprecated/spsum.m deprecated/spsumsq.m: New files\n\t* deprecated/Makefile.in (SOURCES): Add them here.\n\n2008-04-03  Ben Abbott  <bpabbott@mac.com>\n\n\t* sparse/spaugment.m: Increase test script tolerance.\n\n2008-04-02  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/Makefile.in (SOURCES): Add spkron.m to the list.\n\n\t* general/Makefile.in (SOURCES): Add runlength.m to the list.\n\n2008-04-02  Bill Denney  <bill@denney.ws>\n\n\t* optimization/lsqnonneg.m: New function.\n\t* optimization/Makefile.in (SOURCES): Add it to the list.\n\n2008-04-02  David Bateman  <dbateman@free.fr>\n\n\t* sparse/spaugment.m: New function\n\t* sparse/Makefile.in (SOURCES): Add it here.\n\n\t* plot/__gnuplot_ginput__.m: Use the gnuplot stream itself for\n\tcommunication rather than a chat file if mkfifo is not available.\n\t* plot/gnuplot_drawnow.m: Open stream with popen2 to allow two way\n\tcommunication with the gnuplot process.\n\n2008-04-01  Richard Bovey  <Richard.Bovey@baesystems.com>\n\n\t* general/sortrows.m: Handle negative column arguments.\n\n2008-04-01  Julian Schnidder  <j.schnidder@gmx.de>\n\n\t* miscellaneous/perl.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add it to the list.\n\n2008-03-31  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Set the tick direction in the main call\n\tthe set tics rather than separately to avoid issues with multiple\n\tticks in plotyy.\n\n\t* plot/gtext.m: New function to place text on a plot.\n\t* plot/waitforbuttonpress.m: New function.\n\t* plot/Makefile.in (SOURCES): Add them to the list.\n\t* plot/__gnuplot_ginput__.m: Bug fix for nargin==1. Workaround for\n\tmissing mkfifo under Windows.\n\t* plot/ginput.m: Eliminate setting of n.\n\n\t* plot/ginput.m: New function.\n\t* plot/__gnuplot_ginput__.m: New function based on a version of\n\tginput.m from Petr Mikulik <mikulik@physics.muni.cz>.\n\t* plot/Makefile.in (SOURCES): Add them to the list.\n\n2008-03-31  Dmitri A. Sergatskov  <dasergatskov@gmail.com>\n\n\t* miscellaneous/run.m: Fix check for existence of file.\n\n2008-03-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/lookup.m: Remove (lookup moved to DLD-FUNCTIONS).\n\t* general/Makefile.in (SOURCES): Delete lookup.m from the list.\n\t* general/interp1.m, general/interp2.m, general/interpn.m,\n\tpolynomial/ppval.m: Fix buggy lookup calls.\n\t* general/interp1.m: New test.\n\n2008-03-28  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* miscellaneous/tempdir.m: Use correct function name in texinfo\n\tdocumentation.\n\n2008-03-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* general/del2.m: Missing semicolon.\n\n2008-03-28  Julian Schnidder  <j.schnidder@gmx.de>\n\n\t* miscellaneous/info.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add it to the list.\n\n2008-03-27  Søren Hauberg  <hauberg@gmail.com>\n\n\t* plot/xlim.m, plot/ylim.m, plot/zlim.m, strings/strtrim.m:\n\tDoc fixes.\n\n2008-03-27  David Bateman  <dbateman@free.fr>\n\n\t* plot/__plt2__.m: Test if args are empty first so that\n\tplot(zeros(1,0),zeros(1,0)) works as expected.\n\n\t* plot/plotyy.m: The axis handle is a two element vector and\n\tso needs special treatment. Call newplot for the second axis.\n\n2008-03-27  Bill Denney  <bill@denney.ws>\n\n\t* time/datenum.m: Allow vector inputs in any orientation.\n\n\t* strings/validatestring.m: New function.\n\t* strings/Makefile.in (SOURCES): Add it to the list.\n\n\t* general/nargoutchk.m: New function.\n\t* general/Makefile.in (SOURCES): Add it to the list.\n\n\t* general/genvarname.m: New function.\n\t* general/Makefile.in (SOURCES): Add it to the list.\n\n\t* time/addtodate.m: New function.\n\t* time/Makefile.in (SOURCES): Add it to the list.\n\n\t* geometry/rectint.m: Vectorize and add more tests.\n\n2008-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__axis_label__.m: Use name of caller in error message.\n\n2008-03-27  David Bateman  <dbateman@free.fr>\n\n\t* linear-algebra/planerot.m: Givens rotation function.\n\n2008-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* set/ismember.m: Set size of idx output correctly for empty args.\n\tNew tests.\n\n\t* general/logical.m: Correctly handle empty args.  New tests.\n\n\t* control/hinf/h2syn.m, general/__splinen__.m, general/gradient.m,\n\tgeometry/inpolygon.m, geometry/trimesh.m, geometry/triplot.m,\n\timage/imagesc.m, io/csvread.m, io/csvwrite.m,\n\tmiscellaneous/edit.m, miscellaneous/tempname.m, plot/fill.m,\n\tplot/patch.m, plot/ribbon.m, plot/surface.m, polynomial/mkpp.m,\n\tpolynomial/pchip.m, polynomial/spline.m, set/unique.m:\n\tTexinfo fixes.\n\n2008-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/dmult.m: Handle scaling along arbitrary dimension.\n\n2008-03-26  Søren Hauberg  <hauberg@gmail.com>\n\n\t* polynomial/convn.m: New tests.\n\n2008-03-20  Ben Abbott  <bpabbott@mac.com>\n\n\t* statistics/base/statistics.m: Calculate median and quantiles in\n\ta manner consistent with method #7 used by GNU R.\n\t* statistics/base/__quantile__.m, statistics/base/quantile.m,\n\tstatistics/base/prctile.m: New functions.\n\t* statistics/base/Makefile.in (SOURCES): Add them to the list.\n\n2008-03-25  Søren Hauberg  <hauberg@gmail.com>\n\n\t* polynomial/convn.m: New function.\n\t* polynomial/Makefile.in (SOURCES): Add it to the list.\n\n2008-03-25  David Bateman  <dbateman@free.fr>\n\n\t* image/contrast.m: New function.\n\t* image/Makefile.in (SOURCES): Add it to the list.\n\n2008-03-24  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* pkg/pkg.m: Allow installation of already extracted packages.\n\n2008-03-24  David Bateman  <dbateman@free.fr>\n\n\t* general/idivide.m: New function.\n\t* general/Makefile.in (SOURCES): Add it to the list.\n\n\t* miscellaneous/namelengthmax.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add it to the list.\n\n\t* strings/regexptranslate.m: New function.\n\t* strings/Makefile.in (SOURCES): Add it to the list.\n\n2008-03-21  David Bateman  <dbateman@free.fr>\n\n\t* specfun/reallog.m, specfun/realpow.m, specfun/realsqrt.m:\n\tNew functions.\n\t* specfun/Makefile.in (SOURCES): Add them to the list.\n\n2008-03-20  David Bateman  <dbateman@free.fr>\n\n\t* general/tril.m, general/triu.m: Fail if input is a structure.\n\n\t* miscellaneous/cast.m: Also allow cast to \"char\".\n\n\t* general/rotdim.m: Ensure k is an integer scale.\n\n\t* general/circshift.m: If matrix is empty fast return.\n\n2008-03-20  Jaroslav Hajek  <highegg@localhost.localdomain>\n\n\t* linear-algebra/subspace.m: Check number of arguments, number\n\tof dimensions of arguments and matching dimensions.\n\n2008-03-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* linear-algebra/subspace.m: New function.\n\t* linear-algebra/subspace.m: New function.\n\n2008-03-19  Emil Lucretiu  <emil@la.mine.nu>\n\n\t* signal/sinetone.m: Ensure integral number of samples.\n\n2008-03-19  Michael D. Godfrey  <godfrey@isl.stanford.edu>\n\n\t* plot/__go_draw_axes__.m: Additional correction for symbol codes.\n\n2008-03-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* statistics/base/mode.m: Add NDArray tests.\n\n2008-03-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* statistics/distributions/exppdf.m,\n\tstatistics/distributions/expcdf.m,\n\tstatistics/distributions/expinv.m,\n\tstatistics/distributions/exprnd.m: Doc fix.\n\n2008-03-19  David Bateman  <dbateman@free.fr>\n\n\t* statistics/base/mode.m: Fix for row vectors.\n\n\t* plot/__scatter__.m: Modify for change of markersize in\n\t__go_draw_axes__.m and for compatibility.\n\t* plot/__go_draw_axes__.m: Don't divide the marker size by 6\n\ttwice.\n\t* plot/scatter3.m: Doc fix.\n\n2008-03-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* specfun/beta.m: Fix for negative inputs.\n\n2008-03-18  Michael D. Godfrey  <godfrey@isl.stanford.edu>\n\n\t* plot/__go_draw_axes__.m: Use correct symbol codes.\n\n2008-03-14  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/__go_draw_axes__.m: Expicitly set gnuplot user\n\tstyle to default to avoid wrong mesh color in some cases.\n\n2008-03-12  David Bateman  <dbateman@free.fr>\n\n\t* geometry/griddata3.m: Use griddatan and not griddata\n\tinternally. Return vi and not yi. Add test code.\n\n2008-03-11  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Use get to access hidden properties.\n\tUse strcmpi when comparing string properties.\n\n\t* io/csread.m, io/csvwrite.m, io/dlmwrite.m: Style fixes.\n\n2008-03-11  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/__go_draw_axes__.m: Plot surfaces in front of axes.\n\tAllow plotting of uniform colored mesh plots with and\n\tw/o hidden line removal.\n\n2008-03-11  David Bateman  <dbateman@free.fr>\n\n\t* io/dlmwrite.m, io/csvread.m, io/csvwrite.m: Files ported from\n\toctave-forge.\n\t* io/Makefile.in (SOURCES): Add them here.\n\n2008-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* plot/contourf.m: Set axes layer property to \"top\".\n\n\t* plot/__go_draw_axes__.m: Handle tickdir property.\n\n2008-03-06  John W. Eaton  <jwe@octave.org>\n\n\t* plot/hist.m: Avoid temporaries.\n\tAllow matrix arguments when number of bins > 30.\n\tFrom Robert S. Mahurin <rob@utk.edu>.\n\n\t* plot/ChangeLog: Handle axes linewidth property.\n\n\t* plot/__go_draw_axes__.m: Adjust markersize by a factor of 1/6.\n\n\t* general/interpn.m: New test.\n\n2008-03-05  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/roots.m: Catch Infs and/or NaNs.\n\n2008-03-05  Sebastien Loisel  <loisel@temple.edu>\n\n\t* polynomial/roots.m: Apply a scaling factor to the removal of the\n\tleading zeros.\n\n2008-03-04  John W. Eaton  <jwe@octave.org>\n\n\t* plot/print.m: Fix oops in applying last change.\n\n2008-03-04  Bill Denney  <bill@denney.ws>\n\n\t* plot/allchild.m, plot/findall.m: New functions.\n\t* plot/Makefile.in (SOURCES): Add them to the list.\n\n\t* geometry/rectint.m: New function.\n\t* geometry/Makefile.in (SOURCES): Add it to the list.\n\n2008-03-04  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* pkg/pkg.m (pkg:configure_make): Make it work with recent changes in\n\tisspace handling with cell arrays of strings.\n\n2008-03-04  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/polyfit.m: Modified tests to respect a relative tolerance.\n\n\t* plot/print.m: Accept a figure handle as an optional input.\n\n2008-02-29  John W. Eaton  <jwe@octave.org>\n\n\t* plot/print.m: Handle gif and jpg devices.\n\n2008-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m (get_old_gnuplot_color): New subfunction.\n\tUse it to replace repeated if/elseif blocks.\n\n2008-02-28  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/__go_draw_axes__.m: If facecolor property of a surface is\n\t\"none\", don't use pm3d mode and set linestyle correctly.\n\n2008-02-25  Ben Abbott  <bpabbott@mac.com>\n\n\t* control/system/zpout.m, finance/irr.m, general/int2str.m,\n\tgeneral/num2str.m, miscellaneous/bug_report.m,\n\tmiscellaneous/copyfile.m, miscellaneous/dir.m,\n\tmiscellaneous/edit.m, miscellaneous/fullfile.m,\n\tmiscellaneous/mkoctfile.m, miscellaneous/movefile.m,\n\tmiscellaneous/tempdir.m, miscellaneous/unpack.m,\n\tpath/__extractpath__.m, pkg/pkg.m, plot/__ezplot__.m,\n\tplot/__go_draw_axes__.m, plot/legend.m, plot/print.m,\n\tsignal/spectral_adf.m, signal/spectral_xdf.m,\n\tstatistics/tests/z_test.m, statistics/tests/z_test_2.m,\n\tstrings/Makefile.in, strings/strcat.m, strings/strvcat.m,\n\ttestfun/assert.m, testfun/demo.m, testfun/speed.m,\n\ttestfun/test.m: Use cstrcat instead of strcat.\n\n\t* strings/strcat.m: New compatible version.\n\n\t* strings/cstrcat.m: Rename from strings/strcat.m.\n\n2008-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* strings/isstrprop.m: New file.\n\n2008-02-25  Ryan Hinton  <rwh4s@virginia.edu>\n\n\t* miscellaneous/unpack.m: Use \"-f -\" args for tar.\n\n2008-02-24  John W. Eaton  <jwe@octave.org>\n\n\t* specfun/log2.m: Ensure returned value of F strictly less than 1.\n\tFrom Dave Hawthorne <davehawthorne@ieee.org>.\n\n2008-02-22  Ben Abbott  <bpabbott@mac.com>\n\n\t* specfun/legendre.m: Doc fix.\n\n2008-02-22  David Bateman  <dbateman@free.fr>\n\n\t* sparse/pcg.m, sparse/spdiags, spstats.m: Remove references to\n\tspdiag.\n\n2008-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/fullfile.m: Improve handling of empty args and\n\targs ending with filesep.\n\n\t* control/base/__stepimp__.m: Don't use subplot for just one plot.\n\n2008-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* image/imshow.m: Call axis (\"image\").\n\tFrom Michael G. Ross <mgross@MIT.EDU>.\n\n\t* plot/errorbar.m: If nargout > 0, return vector of handles to\n\tline objects.\n\t* plot/__go_draw_axes__.m: Improve handling of line style for\n\terrorbar plots.\n\n2008-02-20  Marco Caliari  <marco.caliari@univr.it>\n\n\t* specfun/legendre.m: Accept normalization options (\"sch\", \"norm\"),\n\tand improve stability for higher orders.\n\n2008-02-20  John W. Eaton  <jwe@octave.org>\n\n\t* strings/strcat.m: Detect cellstr args.\n\n2008-02-20  David Bateman  <dbateman@free.fr>\n\n\t* sparse/colperm.m, sparse/nonzero.m, sparse/spdiags.m,\n\tsparse/spfun.m, sparse/spones.m, sparse/sprand.m,\n\tsparse/sprandn.m, sparse/sprandsym.m, sparse/spy.m: Use generic\n\tversion of find rather than spfind.\n\n2008-02-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* miscellaneous/edit.m: New option EDITINPLACE.  Prefer file list\n\trather than path list.  Return option structure with \"get all\".\n\n\t* polynomial/polyfit.m: Use QR decomposition.  Handle\n\tnormalization option.\n\t* polynomial/polyval.m: Normalize dependent variable.  Optionally\n\tgenerate 50% prediction intervals.\n\n\t* miscellaneous/ver.m: Include package version information in\n\toutput.  Improve consistency with Matlab.\n\n2008-02-19  John W. Eaton  <jwe@octave.org>\n\n\t* pkg/pkg.m: Style fixes.\n\n2008-02-19  Carlo de Falco  <carlo.defalco@gmail.com>\n\n\t* pkg/pkg.m: Handle 'describe' command.\n\t(parse_pkg_idx, print_package_description): New subfunctions.\n\n2008-02-19  Bill Denney  <bill@denney.ws>\n\n\t* time/datestr.m: Avoid confusion for datenum vectors that are 6\n\telements wide.\n\n2008-02-18  David Bateman  <dbateman@free.fr>\n\n\t* general/rem.m, general/mod.m: Treat integer types correctly.\n\n2008-02-15  Timo Lindfors  <timo.lindfors@iki.fi>\n\n\t* statistics/tests/kruskal_wallis_test.m: Handle ties.\n\t* general/runlength.m: New function from Paul Kienzle.\n\n2008-02-15  Rolf Fabian  <r.fabian@jacobs-university.de>\n\n\t* linear-algebra/cond.m: New optional second argument to\n\tspecify 1-norm, inf-norm, or frobenius-norm.\n\n2008-02-12  Kostas Poulios  <poulios.konstantinos@googlemail.com>\n\n\t* plot/__quiver__.m: make arrow head be in z-plane of the arrow\n\tbody. Allow the linespec to specify the arrow color.\n\n2008-02-12  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/cast.m: Also treat the logical type.\n\n\t* plot/__go_draw_axes__.m: Set pm3d implict to fix colorbars on\n\tcontour plots.\n\n \t* plot/__go_draw_axes__.m: Use the cdatamapping property to set\n\tthe cbrange.\n\t* plot/__img__.m: Set cdatamapping to \"direct\".\n\t* plot/imagesc.m: Set cdatamapping to \"scaled\".\n\n2008-02-08  Julien Pommier  <pommier@pianoteq.com>\n\n\t* audio/wavread.m: Limit data read to end of data chunk.\n\n2008-02-08  David Bateman  <dbateman@free.fr>\n\n\t* plot/__contour__.m: Respect the graphic handle options that are\n\tpassed.\n\t* plot/__go_draw_axes__.m: Respect the linewidth for patch objects.\n\n2008-02-01  Dave Goel  <deego3@gmail.com>\n\n\t* signal/arch_rnd.m: Correctly index E and Y vectors.\n\n2008-02-01  Bill Denney  <bill@denney.ws>\n\n\t* time/weekday.m: Allow vector inputs and speed up.\n\t* time/eomday.m: Return column vector for column vector inputs.\n\n2008-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/edit.m: Use \"## Created: DATE\" instead of \"initial\n\trevision\".\n\n\t* plot/Makefile.in (SOURCES): Include __plt2sv__.m and\n\t__plt2vs__.m in the list.\n\n\t* miscellaneous/tempdir.m: Append filesep to name for\n\tcompatibility.  Warn if not a directory or directory does not\n\texist.\n\n\t* strings/deblank.m: Improve compatibility.\n\n2008-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* strings/str2double.m: Delete unused variable FLAG_OCTAVE.\n\n2008-01-28  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/xlabel.m, plot/ylabel.m, plot/zlabel.m:\n\tReturn the label handle, not the current axis handle.\n\n2008-01-25  Alexander Barth  <barth.alexander@gmail.com>\n\n\t* general/interpn.m: Compatibility fix. Don't ndgrid vector\n\tabscissa.\n\n2008-01-25  David Bateman  <dbateman@free.fr>\n\n\t* general/__splinen__.m: Treat mixed orientation vectors.\n\t* plot/__scatter__.m: Remove NaN values from data.\n\t* plot/__patch__.m: Vectorize treatment of trailing NaN values.\n\n2008-01-25  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* linear-algebra/trace.m: Test cases for non 2-d args.\n\n2008-01-25  James Packer  <james.packer@wadh.ox.ac.uk>\n\n\t* geometry/griddata3.m: Call griddata, not gridata.\n\n2008-01-24  Schloegl Alois  <alois.schloegl@tugraz.at>\n\n\t* linear-algebra/trace.m: Require 2-d args.  Handle vectors properly.\n\n2008-01-22  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* linear-algebra/cond.m, linear-algebra/trace.m:\n\tMove tests here from test/test_linalg.m.\n\n\t* general/diff.m, general/fliplr.m, general/flipud.m,\n\tgeneral/logspace.m, general/rot90.m, general/shift.m, general/tril.m,\n\tgeneral/triu.m, linear-algebra/vec.m, linear-algebra/vech.m,\n\tspecial-matrix/hankel.m, special-matrix/hilb.m,\n\tspecial-matrix/invhilb.m, special-matrix/sylvester_matrix.m,\n\tspecial-matrix/toeplitz.m, special-matrix/vander.m:\n\tMove tests here from test/test_matrix.m.\n\n\t* general/isscalar.m, general/issquare.m, general/isvector.m:\n\tMove tests here from test/test_number.m.\n\n\t* deprecated/polyinteg.m, polynomial/compan.m, polynomial/conv.m,\n\tpolynomial/deconv.m, polynomial/poly.m, polynomial/polyderiv.m,\n\tpolynomial/polyfit.m, polynomial/polyreduce.m, polynomial/polyval.m,\n\tpolynomial/polyvalm.m, polynomial/roots.m:\n\tMove tests here from test/test_poly.m.\n\n\t* signal/unwrap.m:\n\tMove tests here from test/test_signal.m.\n\n\t* statistics/base/corrcoef.m, statistics/base/cov.m,\n\tstatistics/base/kurtosis.m, statistics/base/mahalanobis.m,\n\tstatistics/base/mean.m, statistics/base/median.m,\n\tstatistics/base/skewness.m, statistics/base/std.m:\n\tMove tests here from test/test_stats.m.\n\n\t* general/int2str.m, general/num2str.m, strings/bin2dec.m,\n\tstrings/blanks.m, strings/deblank.m, strings/dec2bin.m,\n\tstrings/dec2hex.m, strings/findstr.m, strings/hex2dec.m,\n\tstrings/index.m, strings/rindex.m, strings/split.m, strings/str2mat.m,\n\tstrings/str2num.m, strings/strcat.m, strings/strrep.m,\n\tstrings/substr.m:\n\tMove tests here from test/test_string.m.\n\n\t* miscellaneous/computer.m, miscellaneous/ls.m,\n\tmiscellaneous/version.m, time/asctime.m, time/clock.m, time/ctime.m,\n\ttime/date.m, time/etime.m, time/is_leap_year.m:\n\tMove tests here from test/test_system.m.\n\n2008-01-22  Schloegl Alois  <alois.schloegl@tugraz.at>\n\n\t* specfun/erfinv.m: Replace z_old and z_new by a single variable z.\n\tSimplify initial checks on argument values.\n\n2008-01-22  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/gnuplot_drawnow.m: New function corresponding to the\n\timplementation of the gnuplot-based graphics backend (derived from\n\tdrawnow.m).\n\t* plot/drawnow.m: Deleted (converted to C++).\n\n2008-01-15  Rolf Fabian  <Rolf.Fabian@gmx.de>\n\n\t* linear-algebra/__norm__.m: Only scale if inf norm is finite.\n\tNew tests.\n\n2008-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/sqp.m: End each function with endfunction.\n\n2008-01-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/residue.m: For each group of pole multiplicity, set\n\tthe poles of the group to the value of the group's average.\n\n2008-01-17  Tetsuro KURITA  <tkurita@mac.com>\n\n\t* plot/print.m: Handle PDF output.\n\t* plot/drawnow.m: Add \"PDF\" in a list of enhanced_terminals.\n\n2008-01-17  John W. Eaton  <jwe@octave.org>\n\n\t* path/savepath.m: Print newline before initial comment line.\n\tDouble up single quote characters.\n\t* path/__extractpath__.m: Return just the path as a string.\n\tUndo single quote character doubling.\n\n\t* path/pathdef.m: Avoid eval.  Simplify.\n\n\t* path/pathdef.m: Use fullfile instead of concatenating with filesep.\n\t* path/__extractpath__.m, path/savepath.m: Use unwind_protect to\n\tavoid possible file descriptor leak.\n\n2008-01-17  Ben Abbott  <bpabbott@mac.com>\n\n\t* path/savepath.m: Warn if modified file is not explicitly specified.\n\t* startup/main-rcfile: Call atexit (\"__finish__\").\n\n2008-01-16  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m (__do_enhanced_option__): New subfunction.\n\tUse it to disable enhanced mode for individual labels and titles.\n\n\t* startup/Makefile.in (SOURCES): Add __finish__.m to the list.\n\t(install install-strip, uninstall): Handle function files.\n\n2008-01-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* startup/__finish__.m: New file.\n\t* path/__extractpath__.m, path/matlabroot.m,\n\tpath/pathdef.m: New files.\n\t* path/Makefile.in (SOURCES): Add them to the list.\n\n2008-01-15  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* special-matrix/vander.m: Vectorize.  New test.\n\n\t* elfun/acot.m, elfun/acoth.m, elfun/acsc.m, elfun/acsch.m,\n\telfun/asec.m, elfun/asech.m, elfun/cot.m, elfun/coth.m,\n\telfun/csc.m,elfun/csch.m, elfun/lcm.m, elfun/sec.m, elfun/sech.m,\n\tgeneral/rem.m, miscellaneous/bincoeff.m, miscellaneous/xor.m,\n\tspecfun/beta.m, specfun/log2.m, specfun/pow2.m:\n\tMove tests here from test/test_arith.m.\n\n2008-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* linear-algebra/__norm__.m: Use sum(abs(x),2), not sum(abs(x.')).\n\n2008-01-15  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/drawnow.m, plot/__go_draw_figure__.m, plot/__go_draw_axes__.m:\n\tCall __get__ instead of get.\n\n2008-01-15  Ben Abbott  <bpabbott@mac.com>\n\n\t* linear-algebra/__norm__.m: Avoid divide by zero error for\n\tFrobenius norm if matrix is all zeros.  Use transpose instead of\n\thermitian operator.\n\n2008-01-14  Bill Denney  <bill@denney.ws>\n\n\t* plot/axis.m: Correctly handle \"tight\" and \"image\" options.\n\n2008-01-14  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/hsv2rgb.m, image/ntsc2rgb.m, image/rgb2hsv.m,\n\timage/rgb2ntsc.m: Also accept images as input.\n\n\t* image/gray2ind.m: Handle image type other than double.\n\tImprove error checking and documentation.\n\n2008-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m (get_fontname_and_size): Use strcmpi\n\tinstead of calling tolower on first arg.  Default font name is\n\tHelvetica, not helvetica.  Don't downcase user-specified font name.\n\t(__maybe_munge_text__): Fix typo.\n\n\t* optimization/sqp.m: Fix function definitions in test code.\n\n2008-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* plot/gnuplot_binary.in: New file.\n\t* plot/gnuplot_binary.m: Delete.\n\t* plot/Makefile.in (SOURCES): Remove gnuplot_binary.m from the list.\n\t(SOURCES_IN, GEN_M): New macros.\n\t(DISTFILES): Include $(SOURCES_IN) in the list.\n\t(FCN_FILES): Include $(GEN_M) in the list.\n\t(all): Depend on $(GEN_M).\n\t($(GEN_M): %.m : $(TOPDIR)/Makeconf): New pattern rule.\n\t(distclean): Also remove $(GEN_M).\n\n2008-01-11  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/sqp.m: New test from example in doc string.\n\n2008-01-10  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/mpoles.m: Avoid cases where poles could be assigned\n\tto more than one multiplicity group.\n\n2008-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* plot/gnuplot_binary.m: New file.\n\t* plot/Makefile.in (SOURCES): Add it to the list.\n\n2008-01-09  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow.m: Fail if filename includes a directory part that\n\tdoes not exist.\n\n2008-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/copyfile.m, miscellaneous/movefile.m:\n\tError if glob call fails to match any files.\n\n2008-01-04  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* strings/strtrim.m: Doc fix.\n\n2008-01-04  Muthiah Annamalai  <muthuspost@gmail.com>\n\n\t* general/sub2ind.m, general/ind2sub.m: Doc fix.\n\n2008-01-04  Søren Hauberg   <hauberg@gmail.com>\n\n\t* set/create_set.m, set/union.m: Accept \"rows\" argument.\n\n2008-01-02  John W. Eaton  <jwe@octave.org>\n\n\t* plot/print.m: Correctly handle pbm terminal.\n\n2007-12-28  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/edit.m: Use strcat instead of fullfile to add file\n\textensions.\n\n2007-12-28  David Bateman  <dbateman@free.fr>\n\n\t* ezcontourf.m, ezcontour.m, ezmeshc.m, ezmesh.m, ezplot3.m,\n\t__ezplot__.m, ezpolar.m, ezsurfc.m, ezsurf.m: New functions.\n\t* Makefile.in (SOURCES): Add to the sources.\n\n2007-12-28  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/pcolor.m: Swap 1st and 2nd argument in call to meshgrid.\n\tRemove unnecessary call of size function.\n\n2007-12-21  John W. Eaton  <jwe@octave.org>\n\n\tVersion 3.0.0 released.\n\n2007-12-21  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/imshow.m: Accept empty value for display_range.\n\n2007-12-20  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* pkg/pkg.m: Add .lib as architecture-dependent suffix.\n\n2007-12-19  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/imshow.m: Store uint8 images as doubles.  Handle default\n\tdisplay ranges correctly.\n\n2007-12-19  Alexander Barth  <barth.alexander@gmail.com>\n\t    Peter A. Gustafson  <petegus@umich.edu>\n\n\t* plot/contourc.m: Allow usage of irregular spaced x, y data.\n\n2007-12-19  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/edit.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add it to the list.\n\n2007-12-19  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/__bar__.m: Handle \"basevalue\" option.\n\t* plot/__bars__.m: New arg, base_value.\n\n2007-12-17  David Bateman  <dbateman@free.fr>\n\n\t* plot/rose.m, plot/feather.m, plot/compass.m: New functions\n\t* plot/Makefiles (SOURCES): Add them to the sources\n\t* plot/polar.m: Set the x and y limits to the maximum polar\n\tradius. Set the axes to be square.\n\t* plot/__go_draw_axes__.m: Allow {x|y}axislocation to be \"zero\"\n\tand print axis at zero if this is used.\n\n\t* plot/__go_draw_axes__.m: Use \"set pm3d explicit\" so that\n\tcontours can overlay pcolor plots. Priveldge no hidden line\n\tremoval when there are multiple objects in the plot.\n\n2007-12-17  Peter A. Gustafson  <petegus@umich.edu>\n\n\t* plot/__go_draw_axes__.m:  Fix mirrored tics and borders for\n\tset (gca (), \"[xy]axislocation\", \"{right|top}\", \"box\", \"off\").\n\n2007-12-17  Ben Abbott  <bpabbott@mac.com>\n\n\t* miscellaneous/run.m: Replace script with f when looking for\n\tfile to run.\n\n2007-12-14  David Bateman  <dbateman@free.fr>\n\n\t* plot/contour3.m, plot/__contour__.m: Handle linespec.\n\t* plot/contour.m: Doc fix.\n\t* plot/__go_draw_axes__.m (case \"patch\"): Include \"lt\" in lt string.\n\tInclude linetype in withclause.\n\n\t* plot/__go_draw_axes__.m (__calc_dimensions__): New function.\n\tUse it to determine dimensions.  Consolidate all 3-d settings.\n\n2007-12-13  John W. Eaton  <jwe@octave.org>\n\n\t* image/imshow.m: Turn axis visibility off.\n\tDon't scale true color images.\n\t* image/image.m: Set axis layer property to \"top\".\n\n2007-12-12  John W. Eaton  <jwe@octave.org>\n\n\t* image/loadimage.m: Avoid calling eval.  Avoid calling exist.\n\n\t* plot/pie.m: Avoid calling \"exist\".\n\n\t* linear-algebra/condest.m: Use nargin instead of size(varargin,2).\n\tCondense argument processing logic.  Allow 6 arguments.\n\tUse issquare.  Avoid calling \"exist\".\n\n\t* plot/__go_draw_axes__.m: Handle the axes layer property.\n\n2007-12-12  David Bateman  <dbateman@free.fr>\n\n\t* plot/ellipsoid.m: Port from octave-forge, editing for style.\n\t* plot/Makefile.in (SOURCES): Add to the sources.\n\n2007-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* plot/surf.m: Set xgrid, ygrid, and zgrid on here.\n\t* plot/surface.m: Not here.\n\n\t* plot/__go_draw_axes__.m: Always use \"set grid front\".  Send a\n\tsubsequent \"unset grid\" if there is no grid.\n\n\t* plot/__go_draw_axes__.m: Include \"front\" in \"set label\" options.\n\n\t* plot/surface.m: Don't set facecolor property in call to\n\t__go_surface__.\n\n\t* plot/__plt2vs__.m, plot/__plt2sv__.m: New functions.\n\t* plot/__plt2__.m: Handle scalar-vector and vector-scalar cases.\n\n2007-12-11  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/__patch__.m: Fix typo. Improve argument checking, so that a\n\tcolor string is not taken as z value.\n\n\t* plot/slice.m: Remove unused variable, set xgrid, ygrid, and\n\tzgrid to \"on\" and box to \"off\" for used axes.\n\n\t* plot/__go_draw_axes__.m, plot/plot3.m, plot/ribbon.m,\n\tplot/slice.m: Use size_equal(var1,var2,...) when possible.\n\n2007-12-11  David Bateman  <dbateman@free.fr>\n\n\t* miscelleaneous/fullfile.m: Ignore empty arguments.\n\n\t* sparse/spstats.m: Drop argument to Fsparse to force mutation.\n\t* statistics/base/mode.m: Ditto.\n\n\t* plot/__plt_get_axis_arg__.m: Ignore integer valued handles as\n\tobject handles are all now non integer.\n\n2007-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* plot/sombrero.m, plot/peaks.m: Use surf instead of mesh.\n\n\t* general/issymmetric.m: Use ' instead of .' for compatibility\n\twith previous versions of Octave.\n\t* general/ishermitian.m: Delete.\n\t* general/Makefile.in (SOURCES): Remove ishermitian.m from the list.\n\n\t* plot/fplot.m: In N is not specified, increase initial number of\n\tpoints from 3 and 5 to 5 and 8.\n\n\t* signal/detrend.m: Move tests here from test/test_signal.m.\n\tLoosen tolerance on first test from 10*eps to 20*eps.\n\n\t* finance/rate.m: Don't request info from fsolve.\n\n2007-12-10  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/__line__.m: Pass initial property/value pairs to __go_line__.\n\t* plot/surface.m: Pass initial property/value pairs to __go_surface__.\n\n2007-12-10  David Bateman  <dbateman@free.fr>\n\n\t* image/image.m: Rewritten to allow trailing properties to be\n\tpassed to underlying image object.\n\t* image/__img__.m: Pass additional arguments to __go_image__.\n\t* plot/__patch__.m: Don't set clim, rely on autoscaling.\n\n2007-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: If we have a grid, send \"set grid\n\tfront\" to gnuplot.\n\n2007-12-10  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Issue \"set view map\" for pcolor, and \"set\n\tborder front\" from images.\n\t* plot/__go_draw_figure__.m: Issue \"set autoscale fix\" for gnuplot.\n\t* plot/pcolor.m: Set axis \"box\" property.\n\t* plot/title.m, plot/xlabel.m, plot/ylabel.m, plot/xlabel.m:\n\tMark as commands.\n\n2007-12-07  David Bateman  <dbateman@free.fr>\n\n\t* plot/surf.m: Don't set facecolor property.\n\n2007-12-06  John W. Eaton  <jwe@octave.org>\n\n\t* plot/print.m: Pass mono to drawnow.\n\t* plot/drawnow.m: New arg, mono.  Pass it to __go_draw_figure__.\n\t* plot/__go_draw_figure__.m: New arg, mono.  Pass it to __go_draw_axes.\n\t* plot/__go_draw_axes__.m: New arg, mono.  If mono is true,\n\tdisable color specifications.\n\n\t* general/issymmetric.m: Move tests here from test/test_number.m\n\n2007-12-06  Jason Riedy  <ejr@cs.berkeley.edu>\n\n\t* general/issymmetric.m: To keep its argument sparse and the\n\tfunction quick, use the infinity norm rather than the 2-norm.\n\tAlso measure the symmetric part rather than the Hermitian part.\n\t* general/ishermitian.m: New file.  Measure the Hermitian part.\n\t* general/Makefile.in: Add ishermitian.m to SOURCES.\n\n2007-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Omit \"font \\\"NAME,SIZE\\\"\" in gnuplot\n\ttext and label commands if font is \"*\".\n\n\t* linear-algebra/krylov.m: Doc fixes.\n\tFrom Marco Caliari <caliari@sci.univr.it>.\n\n2007-12-04  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/shading.m: Use __plt_get_axis_arg__ for optional axes argument.\n\tAdd \"## PKG_ADD: mark_as_command axis\" line.\n\n2007-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* contour.m, contour3.m, contourc.m, contourf.m, cylinder.m,\n\tfplot.m, plot3.m, plotyy.m, quiver3.m, scatter.m, scatter3.m,\n\tslice.m, sombrero.m, stairs.m, stem.m, stem3.m:\n\tGenerate demos from examples.\n\n2007-12-03  David Bateman  <dbateman@free.fr>\n\n\t* testfun/test.m: Disable \"testif\" test block to avoid spurious\n\tskipped test for \"make check\". Avoid printing variables for\n\tskipped tests.\n\n\t* testfun/test.m: Add \"testif\" type to allow for conditional tests.\n\n\t* plot/plotyy.m: Use activepositionproperty property of axes\n\tobject. Set second axis color to \"none\".\n\t* plot/__go_draw_axes__.m: Respect the activepositionproperty\n\tproperty of the axis objects.\n\n2007-12-03  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* linear-algebra/condest.m: Loosen tolerance in test.\n\n2007-12-02  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Remove unnecessary call to\n\tget_data_limits.\n\n2007-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Don't compute data or axis limits.\n\t(get_data_limits, get_axis_limits): Delete.\n\n2007-11-30  David Bateman  <dbateman@free.fr>\n\n\t* plot/__scatter__.m: Avoid out of bounds varargin element access.\n\n\t* plot/__go_draw_axes__.m (do_tics_1): regexprep the cell array of\n\ttick labels rather than one by one on the labels themselves.\n\t* plot/pareto.m: Bug in numerical labels fixed. Bug in search for\n\t95% crossing fixed.\n\n2007-11-29  David Bateman  <dbateman@free.fr>\n\n\t* plot/pareto.m: New file.\n\t* plot/Makefile.in (SOURCES): Add it to the sources.\n\t* plot/__go_draw_axes__.m (do_tics1): Replace \"%\" with \"%%\" in tic\n\tmarks to avoid gnuplot error about formating. More colorspec to\n\tafter the tics.\n\t* plot/plotyy.m: More generic check for appropriate axis color.\n\n\t* plot/__stem__.m: New file based on old stem.m expanded to treat\n\t2- and 3-D.\n\t* plot/stem3.m: New function.\n\t* plot/Makefile.in (SOURCES): Add them to the sources.\n\t* plot/stem.m: Adapt to use __stem__.\n\n2007-11-29  John W. Eaton  <jwe@octave.org>\n\n\t* plot/contour.m, plot/contour3.m, plot/fill.m, plot/patch.m,\n\tplot/surf.m, plot/surface.m: Don't return handle value unless\n\trequested.\n\n\t* plot/patch.m: Omit isnan check on handle returned from\n\t__plt_get_axis_arg__.\n\n\t* plot/__plt_get_axis_arg__.m: Don't fail if current figure exists\n\tbut has no axes.\n\n2007-11-28  David Bateman  <dbateman@free.fr>\n\n\t* __plt_get_axis_handle__.m: Also allow hggroup and return axes\n\tancestor. If leading argument is logical set variable nogca to see\n\tif gca() should be called if there is no active handle found.\n\t* __bar__.m, caxis.m, scatter.m, contourf.m, __axes_limits__.m,\n\tfill.m,  surf.m, meshz.m, axis.m, pie.m, contour.m,\n\tquiver.m, area.m, grid.m, cylinder.m, contour3.m, surface.m,\n\tpatch.m, scatter3.m, plot.m, sphere.m, quiver3.m, plotyy.m,\n\txlabel.m, ylabel.m, surfnorm.m, zlabel.m: Adapt to use\n\t__plt__get_axis_arg__ to find axis handle.\n\t* polar.m: Typo.\n\n2007-11-28  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m (get_data_limits): Delete unused arg TX.\n\n2007-11-28  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/drawnow.m: Fix typo.\n\n2007-11-27  David Bateman  <dbateman@free.fr>\n\n\t* plot/errorbar.m, plot/loglog.m, plot/loglogerr.m, plot/polar.m,\n\tplot/semilogx.m, plot/semilogxerr.m, plot/semilogy.m,\n\tplot/semilogyerr.m: Treat an axis handle as the first argument.\n\n\t* plot/meshz.m: New function.\n\t* plot/Makefile.in (SOURCES): Add it to the list.\n\t* plot/surface.m: Allow surface to accept an axis handle as the\n\tfirst argument.\n\t* plot/meshc.m: Extract z from the the surface object rather than\n\tvarargin so that we can rely on code in surface to treat leading\n\taxis handles.\n\n\t* plot/__go_draw_axes__.m: Add nomirror to \"set ytics\" and \"set\n\ty2tics\" in the case of a plotyy plot.\n\t* plot/plotyy.m: ensure the position property is set correct for\n\tthe second axis, by setting it after the plot itself. In the case\n\tof a plot that returns multiple handles, base the color selection\n\ton the first.\n\n2007-11-27  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/__go_draw_axes__.m: Set quadrilateral color according to\n\tz-value of vertex 'c3'.\n\n2007-11-27  John W. Eaton  <jwe@octave.org>\n\n\t* image/image.m: Allow nargin == 0 case to work again.\n\n2007-11-27  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_figure__.m: Force a multiplot mode with a\n\tcolorbar, to ensure that the colorbar is on the canvas for png and\n\tpostscipt outputs.\n\n2007-11-26  David Bateman  <dbateman@free.fr>\n\n\t* sparse/spstats.m, statistics/base/mode.m: More care with sparse\n\treturn values.\n\n\t* plot/plotyy.m: New function\n\t* plot/Makefile.in (SOURCES): Add it here.\n\t* plot/__go_draw_axes__.m: Force axis margins for plotyy. Set text\n\tcolor for {x|y|z}label and {x|y|z}tics. Also force the label of\n\t{x|y}label to respect the axis position.\n\t* plot/xlabel.m, plot/ylabel.m, plot/zlabel.m: Accept an axis\n\thandle as the first argument.\n\n\t* pkg/pkg.m (pkg:install): When loading the installed packages\n\tindex into installed_pkgs_lst and not descriptions..\n\n\t* plot/quiver3.m, plot/surfnorm.m, plot/__quiver__.m: New functions.\n\t* plot/Makefile.in (SOURCES): Add them to the sources.\n\t* plot/quiver.m: Modify to use __quiver__.m.\n\n\t* plot/hist.m: Avoid saturation when the x values are in an\n\tinetger type.\n\n2007-11-26  Jason Riedy  <ejr@cs.berkeley.edu>\n\n\t* linear-algebra/condest.m, linear-algebra/onenormest.m: New\n\tfunctions.\n\t* linear-algebra/Makefile.in (SOURCES): Add them to the sources.\n\n2007-11-26  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Prevent the cbrange from being of zero\n\textent.\n\n\t* plot/colorbar.m: New function.\n\t* plot/Makefile.in (SOURCES): Add it to the sources.\n\t* plot/__go_draw_axes__.m: Calculate the colorbar position,\n\tprecalculate the clim, set pm3d except for mesh.\n\t* plot/__contour__.m: Don't scale the contours to clim, but rather\n\tsave the real values so that colorbar corresponds to the contour\n\tlevels.\n\n\t* plot/stem.m: Set marker color the same as the line color. Draw\n\ta single discontinous line object for the stems.\n\n\t* plot/sphere.m: New function ported from JHandles.\n\t* plot/Makefile.in (SOURCES): Add it to the sources.\n\n\t* plot/__go_draw_axes__.m: Pass the have_newer_gnuplot arg to\n\t__maybe_munge_text__. Use it to reforce fontname for gnuplot 4.0\n\tto get enhanced mode to work correctly for the X11 terminal.\n\n\t* plot/imagesc.m, plot/image.m: Scale colormap to image and not\n\tthe reverse. Allow an axes handle to be passed and/or returned.\n\t* plot/__go_draw_axes__.m: Autoscale colormap for images.\n\n\t* plot/__go_draw_axes__.m: Add depthorder flag to \"set pm3d\" to\n\tsort surface patches by their depth and not the order they are\n\trendered in.\n\n\t* plot/__patch__.m: Set clim correctly.\n\t* plot__go_draw_axes__.m: Allow patch objects to have markers, and\n\tthe marker color is determined by the cmap.\n\t* plot/scatter.m: New function to 2D scatter plots.\n\t* plot/scatter3.m: New function to 3D scatter plots.\n\t* plot/__scatter__.m: Support function for scatter plots\n\t* Makefile.in (SOURCES): Ad dnew functions here.\n\n\t* plot/drawnow.m (open_gnuplot_stream, init_gnuplot_stream):\n\tReturn whether the terminal supports enhanced text or not.\n\t(drawnow:enhanced_term): New sub-function to determine if terminal\n\tsupports enhanced mode.\n\t* plot/__go_draw_figure__.m: Accept enhanced flag and pass to\n\t__go_draw_axes__.\n\t* plot/__go_draw_axes__.m: Accept enhanced flag and munge text if\n\tneeded to support the enhanced mode.\n\t* plot/print.m: Remove \"enhanced\" option as this is now treated in\n\tdrawnow.m.\n\n\t* plot/caxis.m: New function to control the color axis limits.\n\t* plot/Makefile.in (SOURCES): Include it.\n\t* plot/axis.m: Allow the first argument to be an axes handle.\n\t* plot/__go_draw_axes__.m: Move the setting of the caxis, also\n\tautoscale caxis for patches. If any(isinf(clim)) don't set the\n\tcaxis limits.\n\n\t* image/gmap40.m: New gnuplot 4.0 specific colormap fucntion.\n\t* image/Makefile.in (SOURCES): Include it.\n\t* plot/__bar__.h: Allow axis handles to be passed. Set the color\n\tof the bars for the colormap.\n\t* plot/bar.m, plot/barh.m: Document that axis handles can be\n\tpassed.\n\t* plot/__contour.m: Avoid possible divide by zero error.\n\t* plot/contour.m: Missing semicolon.\n\t* plot/surface.m: Don't attempt to set additional arguments if\n\tthere are none.\n\t* plot/Makefile.in (SOURCES): Include __bars__.m\n\n2007-11-19  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/__bar__.m: put bar creation code into separate function\n\tto allow easy hook up from other graphic backends\n\n\t* plot/__bars__.m: new function containing bar creation code\n\n2007-11-26  Alexander Barth  <barth.alexander@gmail.com>\n\n\t* general/accumarray.m: Correct dimension check.\n\n2007-11-26  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/residue.m: Prepad along second dimension.\n\tFrom Doug Stewart <dastew@sympatico.ca>.\n\n2007-11-26  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/cylinder.m, plot/slice.m: New functions.\n\t* plot/Makefile.in (SOURCES): Add them to the list.\n\n2007-11-14  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/patch.m: Handle arg may also be hggroup object.\n\tUse ancestor to find parent axes object.\n\n2007-11-14  David Bateman  <dbateman@free.fr>\n\n\t* plot/__contour__.m: Treat unclosed contours by adding NaN to\n\tflag to patch that it is not closed. Allow z to take string\n\targuments and use it to flag that the contours are placed at the\n\tz level of the contour itself.\n\t* plot/__go_draw_axes__.m: Treat hidden line removal in patch\n\tobjects as well. Let hidden removal take precedence in case of a\n\tconflict.\n\t* plot/surface.m: Allow surface to treat handles being passed or\n\treturned. Any additional arguments arr used to set the surface\n\thandle.\n\t* plot/contour3.m: New function\n\t* plot/Makefile.in (SOURCES): Add it to the sources.\n\n2007-11-14  John W. Eaton  <jwe@octave.org>\n\n\t* specfun/bessel.m: Update doc string from\n\tsrc/DLD-FUNCTIONS/besselj.cc.\n\n2007-11-12  David Bateman  <dbateman@free.fr>\n\n\t* plot/contour.m: Allow handles to be passed and returned. Split\n\tthe countour function itself into __contour__.m to be shared with\n\tsurfc and meshc.\n\t* plot/__contour__.m: New file\n\t* plot/Makefile.in (SOURCES): Add it to the sources.\n\t* plot/__go_draw_axes.m: For patch objects don't attempt to patch\n\tthe face or edge if the facecolor or edge color are marked as\n\t\"none\". Allow the edgecolor to be determined by the cdata in the\n\tsame manner as the facecolor. Fail if facecolor is not \"none\" and\n\ta 3-D plot is desired, rather than ignoring zdata. Make the\n\tstorage of 3D/4D data consistent between line, surface and patch\n\tobjects.\n\t* plot/meshc.m: Use new __contour__.m to plot the contours.\n\t* plot/surfc.m: Use new __contour__.m to plot the contours.\n\n\t* plot/__go_draw_axes__.m (get_fontname_and_size):\n\tHandle fontweight and fontangle properties.\n\n2007-11-12  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/spinmap.m, plot/ribbon.m: New functions.\n\t* plot/Makefile.in (SOURCES): Add them to the list.\n\n2007-11-12  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m (get_fontname_and_size): New subfunction.\n\tUse it to avoid duplicated code.\n\n2007-11-12  David Bateman  <dbateman@free.fr>\n\n\t* plot/title.m: Fix return value for nargout > 0.\n\n\t* plot/__go_draw_axes.m: Allow the font and fontsize to be\n\tspecified for the title, xlabel, ylabel and text objects.\n\n\t* plot/__go_draw_axes.m: Allow arbitrary colormaps with gnuplot\n\t4.0 and surface plots.\n\n2007-11-12  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/__patch__.m: Fix computation of faces when patch is defined\n\twith X/Y/Z data.\n\n2007-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Correct test for have_data.\n\tCorrect logic in setting palette data.\n\n\t* audio/wavread.m, control/base/__bodquist__.m,\n\tcontrol/base/dare.m, control/base/dlqr.m, control/hinf/h2norm.m,\n\tcontrol/system/c2d.m, control/system/is_detectable.m,\n\tcontrol/system/is_signal_list.m, control/system/is_stabilizable.m,\n\tcontrol/system/tfout.m, general/isdefinite.m,\n\tlinear-algebra/krylov.m, miscellaneous/compare_versions.m,\n\toptimization/glpk.m, path/savepath.m, plot/findobj.m,\n\tplot/shading.m, polynomial/mpoles.m, polynomial/polyint.m,\n\tsignal/freqz.m, signal/hurst.m, sparse/spfun.m, sparse/spones.m,\n\tsparse/spstats.m, testfun/assert.m, testfun/fail.m,\n\ttestfun/test.m: Use specific end keywords.\n\n\t* plot/surfc.m, plot/meshc.m: Don't change view if hold is on.\n\n2007-11-09  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/mesh.m, plot/pcolor.m, plot/surf.m, plot/surface.m:\n\tDon't change view if hold is on.\n\n2007-11-09  David Bateman  <dbateman@free.fr>\n\n\t* plot/hidden.m: New function.\n\t* plot/Makefile.in (SOURCES): Add it here.\n\t* plot/meshc.m, plot/mesh.m: Set facecolor to White for hidden\n\tline removal.\n\t* plot/__go_draw_axes__.m: If facecolor is white flag hidden line\n\tremoval and if it is \"none\" don't do hidden line removal.\n\n\t* plot/legend.m: Also allow labels for surface and patch types.\n\t* plot/__bar__.m: Split into separate patch pbjects to allow\n\tsetting of the legend.\n\t* plot/__go_draw_axes__.m: Set titlespec from keylabel for patch\n\tobjects as well.\n\n\t* plot/area.m, plot/__area__.m: New functions\n\t* plot/Makefile.in (SOURCES): Add them to the list of files.\n\n\t* plot/patch.m: Correctly handle case of axis handle as first arg.\n\n2007-11-09  Joseph P. Skudlarek  <Jskud@Jskud.com>\n\n\t* sparse/spdiags.m: Tweak documentation entries to match other uses.\n\n2007-11-08  John W. Eaton  <jwe@octave.org>\n\n\t* control/base/dcgain.m, control/base/dre.m,\n\tcontrol/base/impulse.m, control/base/step.m,\n\tcontrol/system/dmr2d.m, control/system/ord2.m,\n\tcontrol/system/sys2ss.m, control/system/sysdimensions.m,\n\tcontrol/system/sysgetsignals.m, control/system/sysout.m,\n\tcontrol/system/tfout.m, control/system/ugain.m,\n\tcontrol/system/zpout.m, control/util/strappend.m:\n\tDon't fail with usage message if nargout is too large.\n\n\t* control/hinf/h2syn.m, control/hinf/hinf_ctr.m,\n\tcontrol/hinf/hinfnorm.m, control/hinf/hinfsyn.m,\n\tcontrol/hinf/hinfsyn_chk.m, control/hinf/is_dgkf.m,\n\tcontrol/hinf/wgt1o.m, control/obsolete/dezero.m,\n\tcontrol/obsolete/dlqg.m, control/obsolete/minfo.m,\n\tcontrol/obsolete/packsys.m, control/obsolete/qzval.m,\n\tcontrol/obsolete/rotg.m, control/obsolete/series.m,\n\tcontrol/obsolete/swapcols.m, control/obsolete/swaprows.m,\n\tcontrol/obsolete/syschnames.m, control/obsolete/unpacksys.m,\n\tcontrol/system/__syschnamesl__.m,\n\tcontrol/system/__syscont_disc__.m,\n\tcontrol/system/__sysdefioname__.m, control/system/__sysgroupn__.m,\n\tcontrol/system/__tf2sysl__.m, control/system/__zp2ssg2__.m,\n\tcontrol/system/abcddim.m, control/system/buildssic.m,\n\tcontrol/system/c2d.m, control/system/cellidx.m,\n\tcontrol/system/d2c.m, control/system/dmr2d.m,\n\tcontrol/system/fir2sys.m, control/system/is_abcd.m,\n\tcontrol/system/is_controllable.m, control/system/is_detectable.m,\n\tcontrol/system/is_digital.m, control/system/is_observable.m,\n\tcontrol/system/is_stabilizable.m, control/system/is_stable.m,\n\tcontrol/system/jet707.m, control/system/listidx.m,\n\tcontrol/system/parallel.m, control/system/ss.m,\n\tcontrol/system/ss2sys.m, control/system/ss2zp.m,\n\tcontrol/system/starp.m, control/system/sys2ss.m,\n\tcontrol/system/sys2tf.m, control/system/sys2zp.m,\n\tcontrol/system/sysadd.m, control/system/sysappend.m,\n\tcontrol/system/sysconnect.m, control/system/syscont.m,\n\tcontrol/system/sysdimensions.m, control/system/sysdisc.m,\n\tcontrol/system/sysdup.m, control/system/sysgetsignals.m,\n\tcontrol/system/sysgroup.m, control/system/sysmin.m,\n\tcontrol/system/sysmult.m, control/system/sysout.m,\n\tcontrol/system/sysprune.m, control/system/sysreorder.m,\n\tcontrol/system/sysscale.m, control/system/syssetsignals.m,\n\tcontrol/system/syssub.m, control/system/sysupdate.m,\n\tcontrol/system/tf.m, control/system/tf2ss.m,\n\tcontrol/system/tf2sys.m, control/system/tfout.m,\n\tcontrol/system/zp.m, control/system/zp2ss.m,\n\tcontrol/system/zp2sys.m, control/system/zp2tf.m,\n\tcontrol/system/zpout.m, control/util/__outlist__.m,\n\tcontrol/util/__zgpbal__.m, control/util/axis2dlim.m,\n\tcontrol/util/prompt.m, control/util/sortcom.m,\n\tcontrol/util/zgfmul.m, control/util/zgfslv.m,\n\tcontrol/util/zginit.m, control/util/zgreduce.m,\n\tcontrol/util/zgrownorm.m, control/util/zgscal.m: Style fixes.\n\n2007-11-08  David Bateman  <dbateman@free.fr>\n\n\t* plot/quiver.m: Fix arrowheads.\n\n2007-11-07  Ben Abbott  <bpabbott@mac.com>\n\n\t* set/ismember.m: Call cell_ismember to handle cellstr args.\n\tHandle \"rows\" argument.  New tests.\n\t(cell_ismember): New function.\n\n2007-11-07  John W. Eaton  <jwe@octave.org>\n\n\t* control/base/__bodquist__.m, control/base/__freqresp__.m,\n\tcontrol/base/__stepimp__.m, control/base/are.m,\n\tcontrol/base/ctrb.m, control/base/damp.m, control/base/dare.m,\n\tcontrol/base/dcgain.m, control/base/dgram.m, control/base/dlqr.m,\n\tcontrol/base/dre.m, control/base/impulse.m, control/base/lqe.m,\n\tcontrol/base/lqg.m, control/base/lqr.m, control/base/lsim.m,\n\tcontrol/base/ltifr.m, control/base/nichols.m,\n\tcontrol/base/nyquist.m, control/base/obsv.m, control/base/place.m,\n\tcontrol/base/rlocus.m, control/base/step.m, control/base/tzero.m:\n\tStyle fixes.\n\n2007-11-07  Muthiah Annamalai  <muthuspost@gmail.com>\n\n\t* control/base/bode_bounds.m, control/base/dgram.m,\n\tcontrol/base/dlyap.m, control/base/freqchkw.m,\n\tcontrol/base/gram.m, control/base/place.m,\n\tcontrol/hinf/hinf_ctr.m, control/hinf/hinfsyn_chk.m,\n\tcontrol/hinf/hinfsyn_ric.m, control/system/is_sample.m,\n\tcontrol/system/is_signal_list.m, control/system/ss2tf.m,\n\tcontrol/system/sys2fir.m, control/system/sysgettsam.m,\n\tcontrol/system/sysgettype.m, control/system/sysreorder.m,\n\tcontrol/system/tf2sys.m, control/system/zp2tf.m,\n\tcontrol/util/axis2dlim.m, control/util/swap.m,\n\tcontrol/util/zgfmul.m, control/util/zgfslv.m,\n\tcontrol/util/zginit.m, control/util/zgreduce.m,\n\tcontrol/util/zgrownorm.m, control/util/zgscal.m,\n\tcontrol/util/zgsgiv.m, control/util/zgshsr.m, general/isa.m,\n\tgeometry/inpolygon.m, linear-algebra/housh.m,\n\tmiscellaneous/compare_versions.m, miscellaneous/inputname.m,\n\tmiscellaneous/run.m, quaternion/qconj.m,\n\tquaternion/qcoordinate_plot.m, quaternion/qderiv.m,\n\tquaternion/qderivmat.m, quaternion/qinv.m, quaternion/qmult.m,\n\tquaternion/qtrans.m, quaternion/qtransvmat.m, signal/fractdiff.m,\n\tsignal/freqz_plot.m, signal/periodogram.m, signal/rectangle_lw.m,\n\tsignal/rectangle_sw.m, signal/sinc.m, signal/triangle_lw.m,\n\tsignal/triangle_sw.m, signal/yulewalker.m, sparse/colperm.m,\n\tsparse/etreeplot.m, sparse/nonzeros.m, sparse/spalloc.m,\n\tsparse/spones.m, sparse/spy.m, specfun/isprime.m,\n\tstatistics/distributions/empirical_cdf.m,\n\tstatistics/distributions/empirical_inv.m,\n\tstatistics/distributions/empirical_pdf.m,\n\tstatistics/models/logistic_regression_derivatives.m,\n\tstatistics/models/logistic_regression_likelihood.m: Check nargin.\n\n2007-11-07  David Bateman  <dbateman@free.fr>\n\n\t* general/gradient.m: Correctly convert deltax and deltay scalar\n\tvalues are scalars to vectors.\n\n\t* plot/__go_draw_axes__.m: Fix surfaces for gnuplot 4.0 and for\n\tthe meshc.m function.\n\t* plot/meshc.m: Also use the surface function.\n\n\t* plot/meshc.m, plot/quiver.m, plot/surfc.m, : New files.\n\t* plot/Makefile.in (SOURCES): Add them to the list.\n\tAlso add pcolor.m, shading.m, surf.m, and surface.m to the list.\n\n2007-11-07  Michael Zeising  <michael@michaels-website.de>\n\n\t* audio/wavwrite.m, audio/wavwrite.m: Correct sample scaling.\n\n2007-11-07  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Also set have_data to false if any of\n\tthe data limits are infinite.\n\t(get_data_limits): Don't do anything if xdat or tx are empty.\n\t(get_axis_limits): Don't do anything if min_val or max_val are\n\tinfinite.\n\n2007-11-06  David Bateman  <dbateman@free.fr>\n\n\t* plot/hist.m: Pass any additional arguments to bar for\n\ttreatment. Create a default x value that is always a vector.\n\n2007-11-06  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* pkg/pkg.m.m: Check for environment variables CC, CXX, AR, RANLIB\n\twhen calling ./configure and add quotes to preserve spaces.\n\n2007-11-06  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/pcolor.m, plot/shading.m, plot/surf.m, plot/surface.m:\n\tNew files.\n\t* plot/mesh.m: Call surface to do the real work.\n\t* plot/__go_draw_axes__.m: Use pm3d mode to handle new surface\n\tproperties.\n\n\t* image/colormap.m: Also return current colormap if nargout and\n\tnargin are both 0.\n\n2007-11-05  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* startup/inputrc: Delete key bindings starting with \\340 code.\n\n2007-11-05  David Bateman  <dbateman@free.fr>\n\n\t* linear-algebra/__norm__.m: Scale frobenius norm by infinity norm\n\tto avoid issues of over- and underflow.  From Rolf Fabian\n\t<Rolf.Fabian@gmx.de>.\n\n2007-11-02  Olli Saarela  <Olli.Saarela@kcl.fi>\n\n\t* time/asctime.m, general/structfun.m: Fix broken @examples in\n\thelp texts.\n\n2007-11-02  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/bar.m, plot/barh.m: Doc fix.\n\n2007-10-31  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Call undo_string_escapes on obj.keylabel.\n\n2007-10-31  Michael goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/subplot.m: Ignore legend objects when parsing existing axes\n\tobjects and legend objects are implemented with a separate axes\n\tobject.\n\n2007-10-30  David Bateman  <dbateman@free.fr>\n\n\t* control/base/DEMOcontrol.m: Doc fixes for small book format.\n\n\t* plot/__go_draw_axes__.m (do_linestyle_command):\n\tUse point type 0 for \".\".\n\n2007-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* image/imshow.m: Improve compatibility.\n\t* image/image.m: Return handle if nargou > 0.\n\n\t* pkg/pkg.m: Delete PKG_ADD directive for autoloading packes.\n\n2007-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/compare_versions.m: Style fixes.\n\n2007-10-24  John W. Eaton  <jwe@octave.org>\n\n\t* image/saveimage.m: Use functional form of save instead of eval.\n\tUse -text instead of -ascii.\n\n\t* plot/__go_draw_axes__.m: Handle visible = \"off\" for axes objects.\n\n2007-10-23  Peter A. Gustafson  <petegus@umich.edu>\n\n\t* plot/legend.m: Also extract location string from varargin (lost\n\twhen 2007-10-08 patch was applied).\n\n2007-10-23  David Bateman  <dbateman@free.fr>\n\n\t* plot/xlim.m, plot/ylim.m, plot/zlim.m, plot/__axes_limits__.m,\n\tmiscellaneous/what.m: New functions\n\t* plot/Makefile.in, miscellaneous/Makefile.in (SOURCES): Add new\n\tfunctions.\n\n2007-10-22  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/cputime.m, time/tic.m, time/toc.m: Delete.\n\t* miscellaneous/Makefile.in (SOURCES): remove cputim.m\n\t* time/Makefile.in (SOURCES): Remov tic.m and toc.m\n\n2007-10-19  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/contourf.m: New function.\n\t* plot/Makefile.in (SOURCES): Add it to the list.\n\n2007-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* plot/subplot.m: Doc fix.\n\n2007-10-19  David Bateman  <dbateman@free.fr>\n\n\t* plot/__bar__.m, plot/fill.m: Call newplot as needed.\n\n2007-10-17  Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* plot/print.m: Handle -textspecial and -textnormal flags for fig\n\toutput.\n\n2007-10-15  Søren Hauberg  <hauberg@gmail.com>\n\n\t* general/rat.m, sparse/pcg.m, sparse/pcr.m, optimization/sqp.m,\n\tstatistics/models/logistic_regression.m, polynomial/polygcd.m,\n\tcontrol/system/ss.m, signal/arch_rnd.m, control/system/ss2sys.m,\n\tcontrol/system/syssetsignals.m, control/base/lqg.m,\n\tstrings/str2double.m, control/system/sysscale.m,\n\tcontrol/hinf/hinfdemo.m, general/cplxpair.m:\n\tMake help text fit on pages when using smallbook.\n\n2007-10-15  David Bateman  <dbateman@free.fr>\n\n\t* plot/print.m: Call drawnow before printing to ensure the plot is\n\ton the screen.\n\n\t* testfun/test.m: In error/warning blocks test for an error before\n\ta warning to avoid unexpected failures.\n\n2007-10-15  Kim Hansen  i<kimhanse@gmail.com>\n\n\t* testfun/assert.m: Correct documentation of absolution versus\n\trelative error tolerance and add tests.\n\n2007-10-14  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (pkg:configure_make): Treat case of no files to install in\n\tsrc directory.\n\t* plot/Makefile.in (SOURCES): Add fill.m.\n\n2007-10-13  David Bateman  <dbateman@free.fr>\n\n\t* plot/__patch__.m: Allow multiple patches to be defined and\n\treturn a single patch object. Allow Faces/Vertices form of\n\tpatch. Flag failure so the patch can call print_usage.\n\t* plot/patch.m: Update help string for Faces/Vertices\n\tcall. Respect the fail flag returned by __patch__. Add demo code\n\tthat tests the functionality of patch.\n\t* plot/__go_draw_axes__.m: Treat an array of patches in a single\n\tpatch object.\n\t* plot/fill.m: New function.\n\n2007-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* Change copyright notices in all files that are part of Octave to\n\tGPLv3 or any later version.\n\n2007-10-11  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m (get_axis_limits):\n\tReturn lim = [] if logscale and no positive values.\n\t(__go_draw_axes__): Skip plotting if computed axis limits are empty.\n\tSet initial min and min positive values to Inf, max values to -Inf.\n\t(get_data_limits): Correctly handle xminp when no positive values\n\tare found.\n\n2007-10-11  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/residue.m: New optional input for pole multiplicity.\n\tDoc fix.  Fix tests.\n\n2007-10-11  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* toplev.cc (Foctave_config_info): Add field \"mac\".\n\n\t* miscellaneous/ismac.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add it to the list.\n\t* miscellaneous/ispc.m, miscellaneous/isunix.m: Doc fix.\n\n2007-10-11  Arno Onken  <asnelt@asnelt.org>\n\n\t* statistics/distributions/hygernd.m: Allow size to be specified\n\tas a scalar.  Handle three argument case.  Allow T, M, and N to be\n\tscalars or matrices of a common size.\n\n2007-10-11  Brian Gough  <bjg@network-theory.co.uk>\n\n\t* control/csrefcard.lt, control/system/is_detectable.m,\n\tcontrol/system/sysgroup.m, geometry/voronoin.m,\n\tmiscellaneous/dir.m, sparse/pcg.m, sparse/treeplot.m,\n\tstatistics/base/mode.m, statistics/distributions/betarnd.m,\n\tstatistics/distributions/binornd.m,\n\tstatistics/distributions/cauchy_rnd.m,\n\tstatistics/distributions/chi2rnd.m,\n\tstatistics/distributions/discrete_rnd.m,\n\tstatistics/distributions/exprnd.m,\n\tstatistics/distributions/frnd.m,\n\tstatistics/distributions/gamrnd.m,\n\tstatistics/distributions/geornd.m,\n\tstatistics/distributions/laplace_rnd.m,\n\tstatistics/distributions/logistic_rnd.m,\n\tstatistics/distributions/lognrnd.m,\n\tstatistics/distributions/nbinrnd.m,\n\tstatistics/distributions/normrnd.m,\n\tstatistics/distributions/poissrnd.m,\n\tstatistics/distributions/stdnormal_rnd.m,\n\tstatistics/distributions/trnd.m,\n\tstatistics/distributions/unifrnd.m,\n\tstatistics/distributions/wblrnd.m: Spelling fixes.\n\n2007-10-10  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* time/tic.m: New optional output value.\n\n\t* general/int2str.m: Doc fix.\n\n2007-10-10  Arno Onken  <asnelt@asnelt.org>\n\n\t* statistics/distributions/hygecdf.m,\n\tstatistics/distributions/hygeinv.m,\n\tstatistics/distributions/hygepdf.m,\n\tstatistics/distributions/hygernd.m:\n\tSwap order of T and M args for compatibility.\n\n2007-10-10  Olli Saarela  <Olli.Saarela@kcl.fi>\n\n\t* control/hinf/hinfsyn.m, control/hinf/wgt1o.m,\n\tcontrol/system/buildssic.m, control/system/c2d.m,\n\tcontrol/system/d2c.m, control/system/ord2.m, control/system/ss.m,\n\tcontrol/system/ss2sys.m, control/system/ss2tf.m,\n\tcontrol/system/syscont.m, control/system/sysdimensions.m,\n\tcontrol/system/sysdisc.m, control/system/sysmult.m,\n\tcontrol/system/sysrepdemo.m, control/system/tf2ss.m, elfun/lcm.m,\n\tfinance/fv.m, general/cumtrapz.m, general/gradient.m,\n\tgeneral/interp1.m, general/interp2.m, general/interp3.m,\n\tgeneral/interpft.m, general/interpn.m, general/polyarea.m,\n\tgeneral/rat.m, general/structfun.m, general/trapz.m,\n\tgeometry/tsearchn.m, image/rgb2hsv.m, linear-algebra/krylov.m,\n\tmiscellaneous/ans.m, miscellaneous/gzip.m, optimization/glpk.m,\n\toptimization/sqp.m, plot/findobj.m, plot/legend.m, plot/peaks.m,\n\tplot/plot3.m, plot/stem.m, polynomial/deconv.m,\n\tpolynomial/pchip.m, polynomial/spline.m, polynomial/unmkpp.m,\n\tsparse/pcr.m, sparse/spalloc.m, sparse/spconvert.m,\n\tspecfun/factor.m, specfun/legendre.m, statistics/base/mean.m,\n\tstatistics/base/meansq.m, statistics/base/var.m,\n\tstatistics/tests/chisquare_test_independence.m,\n\tstatistics/tests/t_test.m, statistics/tests/u_test.m,\n\tstrings/dec2base.m, strings/mat2str.m, testfun/speed.m,\n\ttestfun/test.m: Spelling fixes.\n\n2007-10-10  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/mpoles.m: Return indx = ordr(indx), not indx(ordr).\n\n2007-10-10  John W. Eaton  <jwe@octave.org>\n\n\t* general/num2str.m: Always allow for sign for automatically\n\tcomputed format widths.\n\n2007-10-09  David Bateman  <dbateman@free.fr>\n\n\t* plot/patch.m: Accept a handle as the first argument.\n\n2007-10-09:  Kim Hansen  <kimhanse@gmail.com>\n\n\t* general/repmat.m: Handle sparse input.  Add tests.\n\n2007-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* audio/wavwrite.m: Accept arguments in compatible order.\n\n2007-10-08  David Bateman  <dbateman@free.fr>\n\n\t* general/interp2.m: Relax test for values outside the grid to\n\tallow monotonically decreasing abscissa as well.\n\n2007-10-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/residue.m: Doc fix.  Add tests.  Restore multiplicity\n\tas output parameter.\n\n2007-10-08  Peter A. Gustafson  <petegus@umich.edu>\n\n\t* plot/__go_draw_axes__.m, plot/legend.m:\n\tHandle compatible position specifiers as strings.\n\n2007-10-08  John Swensen  <jpswensen@comcast.net>\n\n\t* general/num2str.m: Eliminate extra whitespace in output.\n\t* strings/strtrim.m: New function.\n\t* strings/Makefile.in (SOURCES): Add it to the list.\n\n2007-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/residue.m: New test from test/test_poly.m.\n\n2007-10-06  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/saveimage.m: Handle saving color images without a colormap.\n\t* image/__img_via_file__.m: Add missing semicolon.\n\n2007-10-06  Bill Denney  <wsloand@gmail.com>\n\n\t* general/__splinen__.m, general/isscalar.m, general/rat.m,\n\tstrings/dec2base.m: Use numel(x) instead of prod(size(x)).\n\n2007-10-06  Francesco Potorti`  <Potorti@isti.cnr.it>\n\n\t* plot/print.m: Handle svg output type.  Accept new -S option to\n\tspecify size for PNG and SVG output types.\n\n2007-10-05  Ben Abbott  <bpabbott@mac.com>\n\n\t* polynomial/mpoles.m: New function.\n\t* polynomial/residue.m: Modified to behave in reciprocal\n\tmanner.  No longer compute 4th output, \"e\".  No longer accept\n\ttolerance input.  Explicitly set tolerance parameter to 0.001.\n\tRespect maximum relative difference in poles when determining\n\ttheir multiplicity.  Use mpoles to determine the multiplicity of\n\tpoles.\n\n2007-10-05  Peter A. Gustafson  <petegus@umich.edu>\n\n\t* plot/__go_draw_axes__.m: Add cbrange to the plot stream\n\tfor surface plots.\n\n2007-10-05  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__next_line_color__.m: Get color_rotation from axes\n\tcolororder property.\n\n2007-10-03  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/dir.m: Handle symbolic links in compatible way.\n\tUse S_ISDIR (st.mode) instead of checking st.modestr(1) == \"d\".\n\n\t* linear-algebra/Makefile.in (SOURCES): Rename norm.m to __norm__.m.\n\t* linear-algebra/__norm__.m: Rename from norm.m.  Eliminate\n\tspecial for __vnorm__.\n\n2007-10-03  Quentin Spencer  <qspencer@ieee.org>\n\n\t* linear-algebra/norm.m: Special case vector 1-norm and 2-norm.\n\n2007-10-03  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (is_architecture_dependent): New function to identify\n\tif a file is architecture dependent based on a list of file\n\textensions.\n\t(configure_make): Simplify the search for architecture dependent\n\tfiles based on this function.\n\t(load_pakages_and_dependencies): Also look for bin directory in\n\tthe architecture dependent directory.\n\n2007-10-03  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/dir.m: Create empty struct with field names.\n\tInclude datenum in struct.\n\n2007-10-02  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/ls.m: If nargout return string array of files\n\treturned by ls.\n\n2007-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Use %.15e instead of %.15g when setting\n\trange values.\n\n2007-10-01  David Bateman  <dbateman@free.fr>\n\n\t* linear-algebra/norm.m: Inline the isvector(x) calculation for\n\tspeed with small vectors.\n\t* pkg/pkg.m (archprefix): Set using octave_config_info(\"libexecdir\")\n\trather than OCTAVE_HOME().\n\n2007-09-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* plot/findobj.m: New function.\n\t* plot/Makefile.m (SOURCES): Add it to SOURCES.\n\n2007-09-26  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m: Add second argument to setting for prefix for\n\tarchitecture dependent files. Use throughout.\n\t(pkg:issuperuser): New function, use through to check for\n\troot user.\n\t(pkg:getarchprefix): function to give the archiecture dependent\n\tprefix for a package.\n\t(pkg:getarchdir): New function giving location of architetcure\n\tdependent directory. Use through out.\n\t(pkg:install): Treat architecture dependent directory separately\n\tas in might not be a sub-directory of the package directory.\n\t(pkg:uninstall): ditto.\n\t(pkg:create_pkgadddel): Check for global or local install for\n\tarchitecture dependent directory.\n\t(pkg:finish_installation): ditto.\n\t(pkg:write_INDEX): ditto.\n\t(pkg:load_packages_and_dependencies): ditto.\n\t(pkg:copy_files): ditto. Add step to copy architecture dependent\n\tfiles to a new location if user is root.\n\t(pkg:rm_rf): Check if file or directory exists before removing.\n\t(pkg:dirempty): Check if directory exists before checking.\n\n\t* plot/___patch__.m: Allow face colors to be passed as strings\n\n\t* plot/__plt_get_axis_arg__.m: Treat case of empty \"varargin\"\n\tneeded for calls to \"hold\" without an argument.\n\n2007-09-21  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/sqp.m: Fix typo.\n\n\t* plot/__go_draw_axes__.m (do_tics_1): Use %g, not %.15g here.\n\n2007-09-21  Luther Tychonievich  <lty@cs.byu.edu>\n\n\t* control/hinf/h2norm: Compute d*d', not d'*d.\n\n2007-09-21  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* statistics/distributions/Makefile.in (SOURCES): Add unidcdf.m,\n\tunidpdf.m and unidinv.m\n\n2007-09-18  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Use %.15g throughout.\n\t(do_tics_1): Set numeric axes formats to \"%.15g\".\n\n2007-09-18  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m (__gnuplot_write_data__): Use %e instead\n\tof %g when writing data.\n\n2007-09-17  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Omit linestyle clause for errorbar plots.\n\n2007-09-14  Ulrich Tipp  <ulrich.tipp@hsnr.de>\n\n\t* miscellaneous/bincoeff.m: Fix calculation of bincoeff (n, k) for\n\tnoninteger N with N-K < 1.\n\n2007-08-04  Jean-Francois Cardoso  <cardoso@tsi.enst.fr>\n\n\t* strings/index.m: Correct for strings differing after the third\n\tposition (bug reported by Maude Martin).\n\n2007-09-13  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__default_colormap__.m: Delete.\n\t* plot/Makefile (SOURCES): Remove from the list.\n\n2007-09-13  Christof Zeile  <cz-oct07@cvmx.com>\n\n\t* pol2cart.m: Make it work with mixed scalar/nonscalar arguments.\n\n2007-09-10  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Allow gnuplot 4.0 with patches, but\n\tlimit the selection of colors in the same way as for lines.\n\t* plot/__patch__.m: Allow matrix arguments with one patch per\n\tcolumn.\n\t* plot/__bar__.m: Adapt to use \"patch\".\n\n2007-09-06  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow.m (drawnow): New arg, debug_file.\n\t(init_plot_stream): Split from open_plot_stream.\n\t* plot/print.m: Accept -debug=FILE argument.\n\n2007-09-06  David Bateman  <dbateman@free.fr>\n\n\t* general/celldisp.m: New function.\n\t* general/Makefile.in (SOURCES): Add celldisp.m.\n\t* miscellaneous/swapbytes.m: New function.\n\t* miscellaneous/gzip.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add swapbytes.m and gzip.m.\n\n2007-09-05  David Bateman  <dbateman@free.fr>\n\n\t* general/structfun.m: New function.\n\t* general/Makefile.in (SOURCES): Add it to sources.\n\t* miscellaneous/run.m: New function.\n\t* miscellaneous/Makefile.in (SOURCES): Add it to sources.\n\t* statistics/base/mode.m: New function.\n\t* statistics/base//Makefile.in (SOURCES): Add it to sources.\n\n2007-09-05  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/orderfields.m: Use numel instead of length.\n\n2007-09-05  Michael goffioul  <michael.goffioul@gmail.com>\n\n\t* miscellaneous/orderfields.m: Handle empty structs.\n\n2007-09-05  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Consistently index PARAMETRIC with\n\tDATA_IDX.\n\n2007-09-04  David Bateman  <dbateman@free.fr>\n\n\t* general/isdir.m: Return a logical value.\n\n2007-09-04  David Bateman  <dbateman@free.fr>\n\n\t* statistics/distributions/chi2pdf.m,\n\tstatistics/distributions/chi2cdf.m,\n\tstatistics/distributions/chi2inv.m: Modifiy the call to the gamma\n\tdistribution functions to account for inverse of scale factor in\n\tgamma functions.\n\n2007-09-01  John W. Eaton  <jwe@octave.org>\n\n\t* plot/Makefile.in (SOURCES): Add ancestor.m to the list.\n\n2007-09-01  David Bateman  <dbateman@free.fr>\n\n\t* polynomial/polyint.m: New function like polyinteg but with\n\texplicit integration constant.\n\t* polynomial/polyinteg.m: Remove.\n\t* polynomial/Makefile.in (SOURCES): Add polyint.m and remove\n\tpolyinteg.m.\n\t* deprecated/polyinteg.m: Move version here.\n\t* deprecated/Makefile.in (SOURCES): Add polyinteg.m.\n\n\t* geometry/voronoi.m: Add large box around data to get a good\n\tapproximation of the rays to infinity.\n\n2007-08-31  Michael goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/axes.m: Allow parent to be specified when creating axes\n\tobjects.  Support non-figure parents.\n\n2007-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* plot/ancestor.m: New function, adapted from Octave Forge.\n\n2007-08-31  Søren Hauberg  <hauberg@gmail.com>\n\n\t* polynomial/polygcd.m: Better layout of example.\n\t* polynomial/compan.m: Remove unnecessary check.\n\t* polynomial/roots.m: Added example to help text.\n\t* polynomial/polyderiv.m: Change 'polyder' to 'polyderiv' in help text.\n\t* polynomial/poly.m: Added example to help text.\n\n2007-08-30  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/qp.m: Increase maxit to 200.\n\n2007-08-30  David Bateman  <dbateman@free.fr>\n\n\t* geometry/inpolygon.m: New file.\n\t* geometry/Makefile.in (SOURCES): Add inpolygon.m.\n\n2007-08-29  Peter A. Gustafson  <petegus@umich.edu>\n\n\t* plot/__go_draw_axes__.m: Disable linetype in do_linestyle_command.\n\n2007-08-24  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Treat text color property.\n\n2007-08-24  John W. Eaton  <jwe@octave.org>\n\n\t* plot/subplot.m, plot/plot.m, plot/grid.m:\n\tUse p = get (h, \"prop\") instead of obj = get (h); p = obj.prop.\n\n\t* miscellaneous/movefile.m: Separate second and third args and\n\tuse p1 and p2, not f1 and f2 when constructing arguments for\n\tcalls to system.  From Michael Goffioul <michael.goffioul@gmail.com>.\n\n2007-08-24  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* set/intersect.m: Make it work with cell arrays of strings.\n\n2007-08-24  David Bateman  <dbateman@free.fr>\n\n\t* geometry/convhull.m, geometry/delaunay.m, geometry/delaunay3.m,\n\tgeometry/griddata.m, geometry/voronoi.m, geometry/voronoin.m: New\n\tfunctions ported from octave-forge.\n\t* geometry/delaunayn.m, geometry/dsearch.m, geometry/dsearchn.m,\n\tgeometry/griddata3.m, geometry/griddatan.m, geometry/trimesh.m,\n\tgeometry/triplot.m, geometry/tsearchn.m:\n\tNew functions.\n\t* geometry/voronoi.m: Remove duplicate edges from Voronoi diagram.\n\t* geometry/Makefile.in (SOURCES): Add functions above.\n\t* configure.in (AC_CONFIG_FILES): Add new file geometry/Makefile.\n\n2007-08-23  John W. Eaton  <jwe@octave.org>\n\n\t* pkg/pkg.m: Avoid using installed_packages for both function and\n\tvariable name.\n\n2007-08-23  David Bateman  <dbateman@free.fr>\n\n\t* plot/plot.m: Allow first arg to be axes handle.\n\n2007-08-22  David Bateman  <dbateman@free.fr>\n\n\t* control/base/nichols.m: Correct for misnamed variable, and ensure\n\toutputs are returned only if requested.\n\n2007-08-22  Donald Parsons  <dparsons@brightdsl.net>\n\n\t* control/base/nichols.m: Fix typo.\n\n2007-08-13  John W. Eaton  <jwe@octave.org>\n\n\t* plot/meshgrid.m: Use repmat instead of multiplication.\n\n2007-08-10  Peter A. Gustafson  <petegus@umich.edu>\n\n\t* plot/__go_draw_axes__.m: Add axes position to the usingclause,\n\tuse axes position in each appropriate gnuplot set statement.\n\n2007-08-10  John W. Eaton  <jwe@octave.org>\n\n\t* image/Makefile.in (DISTFILES): Also include $(IMAGES) in the list.\n\t(install install-strip): Use $(IMAGES), not $(IMAGE_FILES_NO_DIR).\n\t(uninstall): Use $(IMAGES), not $(IMAGE_FILES_NO_DIR).\n\t(IMAGE_FILES, IMAGE_FILES_NO_DIR): Delete obsolete variables.\n\n2007-08-10  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/patch.m, plot/__patch__.m: New files.\n\t* plot/Makefile.in (SOURCES): Add them to the list.\n\n2007-08-07  John W. Eaton  <jwe@octave.org>\n\n\t* path/savepath.m: Use single quotes for argument to PATH command\n\tthat is inserted in file.\n\n2007-07-27  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow.m: Only set default value for term if GNUTERM is\n\tnot set in the environment.\n\n2007-07-25  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in, audio/Makefile.in, control/Makefile.in,\n\tcontrol/base/Makefile.in, control/hinf/Makefile.in,\n\tcontrol/obsolete/Makefile.in, control/system/Makefile.in,\n\tcontrol/util/Makefile.in, deprecated/Makefile.in,\n\telfun/Makefile.in, finance/Makefile.in, general/Makefile.in,\n\timage/Makefile.in, io/Makefile.in, linear-algebra/Makefile.in,\n\tmiscellaneous/Makefile.in, optimizaton/Makefile.in,\n\tpath/Makefile.in, pkg/Makefile.in, plot/Makefile.in,\n\tpolynomial/Makefile.in, quaternion/Makefile.in,\n\tset/Makefile.in, signal/Makefile.in, sparse/Makefile.in,\n\tspecfun/Makefile.in, special-matrix/Makefile.in,\n\tstartup/Makefile.in, statistics/Makefile.in,\n\tstatistics/base/Makefile.in, statistics/distributions/Makefile.in,\n\tstatistics/models/Makefile.in, statistics/tests/Makefile.in,\n\tstrings/Makefile.in, testfun/Makefile.in, time/Makefile.in:\n\tAdjust DISTFILES to allow out of tree \"make dist\" to work.\n\n2007-07-25  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__plt2__.m: Return [](0x1) if both X and Y are empty.\n\n2007-07-24  David Bateman  <dbateman@free.fr>\n\n\t* image/flag.m: New colormap function.\n\t* images/Makefile.in: Include it in SOURCES.\n\n\t* image/autumn.m image/bone.m image/cool.m image/copper.m\n\timage/hot.m image/hsv.m image/jet.m image/pink.m image/prism.m\n\timage/rainbow.m image/spring.m image/summer.m image/white.m\n\timage/winter.m, image/brighten.m: Use isscalar and not is_scalar.\n\t* image/gray.m, image/ocean.m: Use the same means of finding the\n\tnumber of colormap elements as the other colormap functions.\n\n2007-07-24  Kai Habel  <kai.habel@gmx.de>\n\n\t* plot/__go_draw_axes__.m: Handle patch.\n\n2007-07-23  David Bateman  <dbateman@free.fr>\n\n\t* general/rat.m: New function for ration approximation imported\n\tfrom octave-forge.\n\t* general/del2.m: New function for discrete laplacian operator.\n\t* general/Makefile.in: Include rat.m and del2.m  in SOURCES.\n\n\t* image/autumn.m image/bone.m image/cool.m image/copper.m\n\timage/hot.m image/hsv.m image/jet.m image/pink.m image/prism.m\n\timage/rainbow.m image/spring.m image/summer.m image/white.m\n\timage/winter.m, image/brighten.m: Port image functions from\n\toctave-forge.\n\t* image/Makefile.in: Add ported functions to SOURCES.\n\t* image/gray.m, image/ocean.m: Don't set the colormap for\n\tcompatibility with matlab.\n\n\t* plot/meshc.m, plot/peaks.m: Port plotting function from\n\toctave-forge\n\t* plot/Makefile.in: Add ported functions to SOURCES.\n\t* plot/__go_draw_axes__.m: Set the palette for the surfaces if\n\tusing gnuplot 4.2 or greater.\n\n2007-07-23  Claudio Belotti  <c.belotti@imperial.ac.uk>\n\n\t* general/cart2sph.m: Fix unbalanced paranthesis.\n\n2007-07-19  David Bateman  <dbateman@free.fr>\n\n\t* plot/fplot.m: More compatible version.\n\n2007-07-18  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/clf.m: Check for valid handle before deleting.\n\n\t* plot/figure.m: Pass \"figure\" property/value pairs directly to\n\t__go_figure__ instead of using regular \"set\" call.\n\n2007-07-18  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* plot/drawnow.m: Prefer GNUTERM to DISPLAY when choosing terminal\n\ttype for gnuplot.\n\n2007-07-18  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Unconditionally send \"unset label\" to\n\tgnuplot for each set of axes.\n\n2007-07-18  David Bateman  <dbateman@free.fr>\n\n\t* statistics/distributions/gamcdf.m, statistics/distributions/gaminv.m,\n\tstatistics/distributions/gampdf.m, statistics/distributions/gamrnd.m,\n\tstatistics/distributions/expcdf.m, statistics/distributions/expinv.m,\n\tstatistics/distributions/exppdf.m, statistics/distributions/exprnd.m:\n\tUse standard scale factor rather than one on the scale factor for\n\tcompatibility.\n\n\t* deprecated/gamma_cdf.m, deprecated/gamma_inv.m,\n\tdeprecated/gamma_pdf.m, deprecated/gamma_rnd.m,\n\tdeprecated/exponential_cdf.m, deprecated/exponential_inv.m,\n\tdeprecated/exponential_pdf.m, deprecated/exponential_rnd.m:\n\tPreserve backward compatibility.\n\n2007-07-17  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* pkg/pkg.m (pkg:installed_packages): Use findstr rather than regexp\n\tto avoid issues with regexp special characters in the path strings.\n\n2007-07-06  David Bateman  <dbateman@free.fr>\n\n\t* general/accumarray.m: New function to create an array by\n\taccumulating the elements.\n\n2007-06-29  Marcus W. Reble  <reble@wisc.edu>\n\n\t* optimization/sqp.m (sqp): New args, lb, ub, maxiter, and tolerance.\n\t(fdjac): Set nx outside of if block.\n\t(cf_ub_lb, cigrad_ub_lb): New subfunctons.\n\n2007-06-28  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* plot/subplot.m: Add 'ishandle' check when parsing the existing axes.\n\n\t* plot/axis.m: Also set \"visible\" property when setting axes to\n\ton/off.\n\n2007-06-27  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* image/colormap.m: Only return colormap if nargout > 0.\n\tMark as command.\n\n2007-06-25  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow.m, plot/__go_draw_axes__.m: Use strcmpi instead of\n\tstrcmp for selected property comparisons.\n\n2007-06-25  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/imshow.m: Fix check for colormap arguments.\n\n2007-06-25  Joel Keay  <keay@nhn.ou.edu>\n\n\t* plot/drawnow.m: Handle GNUTERM=aqua if DISPLAY is not set.\n\n2007-06-25  Søren Hauberg  <hauberg@gmail.com>\n\n\t* statistics/base/median.m: Update help text to mention 'dim'\n\targument, and note that the data should be sorted for the\n\tdefinition of the median to be correct.\n\n\t* statistics/base/std.m: Add missing square to definition of\n\tstandard deviation.\n\n\t* statistics/base/cov.m: Add definition of covariance to the help text.\n\n\t* statistics/base/kurtosis.m, statistics/base/skewness.m,\n\tstatistics/base/std.m:\n\tNote that \\bar{x} is the mean value of x in the help text.\n\n\t* specfun/nchoosek.m: Add alternative definition of the binomial\n\tcoefficient to the help text.\n\n\t* specfun/perms.m, statistics/base/values.m: Add example in help text.\n\n\t* statistics/base/var.m: Put N in @math in help text.\n\n\t* statistics/base/qqplot.m, statistics/base/ppplot.m,\n\tstatistics/tests/kolmogorov_smirnov_test.m:\n\tWrite about possible values of 'dist' in help text.\n\n\t* statistics/base/corrcoef.m, statistics/base/cor.m:\n\tAdd definition of correlation to the help text.\n\n\t* statistics/base/logit.m, statistics/base/kendall.m,\n\tstatistics/base/cloglog.m, statistics/tests/hotelling_test_2.m,\n\tstatistics/distributions/wblcdf.m, statistics/distributions/wblpdf.m:\n\tTeXification of help text.\n\n\t* statistics/tests/hotelling_test.m: Write T^2 in @math in help text.\n\n\t* statistics/tests/var_test.m, statistics/tests/welch_test.m:\n\tAdd missing @var's to help text.\n\n\t* statistics/models/logistic_regression.m: Fix typos in help text.\n\n\t* statistics/distributions/kolmogorov_smirnov_cdf.m: Fix TeX part\n\tof help text.\n\n\t* statistics/distributions/unidinv.m: Add a missing 'discrete' to\n\thelp text.\n\n\t* statistics/distributions/unidpdf.m,\n\tstatistics/distributions/discrete_pdf.m:\n\tReplace 'pDF' with 'PDF' in help text.\n\n2007-06-25  John W. Eaton  <jwe@octave.org>\n\n\t* strings/substr.m: Use offset consistently in code and doc string.\n\tFrom Rafael Laboissiere <rafael@debian.org>.\n\n2007-06-25  Pete Gustafson  <petegus@umich.edu>\n\n\t* plot/__go_draw_axes__.m: Handle units for text objects.\n\n2007-06-25  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Handle char arrays for tic labels.\n\tRecycle tic labels if necessary.  From Juhani Saastamoinen\n\t<juhani@cs.joensuu.fi>.\n\n2007-06-20  John W. Eaton  <jwe@octave.org>\n\n\t* strings/index.m: Allow strings to be empty.\n\tFrom Hartmut Wziontek <hwz@hwz.bv.TU-Berlin.DE>\n\n\t* plot/__go_draw_axes__.m (do_tics_1): Fix typo (xtic -> tics).\n\n2007-06-19  Vittoria Rezzonico  <vittoria.rezzonico@epfl.ch>\n\n\t* sparse/pcg.m: Allow the preconditioner to be passed as two\n\tseparate matrices.\n\n2007-06-19  David Bateman  <dbateman@free.fr>\n\n\t* plot/axis.m: Prefer to use legend rather than the older Octave\n\tonly \";;\" legend syntax.\n\t* polynomial/mkpp.m: ditto.\n\t* polynomial/pchip.m: ditto.\n\t* signal/freqz_plot.m: ditto.\n\t* sparse/gplot.m: ditto.\n\t* sparse/treeplot.m: ditto.\n\n2007-06-19  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m (do_tics, do_tics_1): New functions.\n\t(__go_draw_axes__): Call do_tics to handle tic marks.\n\n2007-06-18  Søren Hauberg  <hauberg@gmail.com>\n\n\t* general/interp1.m, general/interp2.m, general/interp3.m,\n\tgeneral/interpn.m: Replace, NaN with NA.  Use isna instead of ==\n\tto check for NA.\n\n2007-06-18  Søren Hauberg  <hauberg@gmail.com>\n\n\t* optimization/glpk.m: TeXified the help text.\n\t* optimization/qp.m: TeXified the help text.\n\t* optimization/sqp.m: TeXified the help text.\n\n2007-06-16  Søren Hauberg  <hauberg@gmail.com>\n\n\t* plot/legend.m: Replace 'vargin' with 'varargin'.\n\n2007-06-15  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Only attempt label rotation if\n\thave_newer_gnuplot is true.\n\n2007-06-15  Pete Gustafson  <petegus@umich.edu>\n\n\t* plot/__go_draw_axes__.m  Handle rotation arg for axis labels.\n\t* plot/__axis_label__.m  Assign ylabel default rotation property\n\tto 90, all others 0.\n\n\t* plot/__errplot__.m: Set ifmt from fmt.linestyle.\n\t* plot/__go_draw_axes__.m: Removed undefined tx from call to\n\tget_data_limits.\n\t* plot/__plotopt1__.m: Intercept and strip format string when\n\tcalled by __errplot__.\n\n2007-06-15  John W. Eaton  <jwe@octave.org>\n\n\t* testfun/test.m: Also return number of expected failures.\n\n2007-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* set/ismember.m: Mark two tests known to fail with xtest.\n\n\t* plot/__go_draw_axes__.m: Handle text rotation property.\n\n2007-06-14  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* testfun/test.m: Add xtest support for tests known to fail.\n\n2007-06-14  Sebastian Schubert  <sebastian-schubert@gmx.de>\n\n\t* plot/print.m: Handle pstex, pslatex, epslatex, and\n\tepslatexstandalone terminals.\n\n2007-06-14  David Bateman  <dbateman@free.fr>\n\n\t* general/__splinen__.m: Check also for ND vectors. Fix for N > 2,\n\tas permutation of results was incorrect.\n\t* general/interp1.m: Add demo on second derivative\n\t* general/interpn.m: Convert \"y\" to vectors for __splinen__\n\tcall. Add 3D demo. Fix typos\n\t* general/interp3.m: Fix typos. Correct permutation for use of\n\tinterpn.\n\t* polynomial/mkpp.m: Correction for matrices of 3 or more dimensions.\n\n2007-06-13  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/mkoctfile.m: Quote args too.\n\n2007-06-13  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* miscellaneous/mkoctfile.m: Quote script name for call to system.\n\n2007-06-12  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* plot/__pltopt1__.m: Set linestyle to \"none\" instead of \"\".\n\tSet have_linestyle to true if two character linestyle is found.\n\n2007-06-12  David Bateman  <dbateman@free.fr>\n\n\t* general/Makefile.in (SOURCES): Include __spline__.m, interp3.m\n\tand interpn.m.\n\n\t* pkg/pkg.m (pkg:load_package_dirs): Check for field \"loaded\" in\n\tstructure before using it.\n\n2007-06-12  David Bateman  <dbateman@free.fr>\n\n\t* general/interp1.m: Change examples to use new graphics interface.\n\t* general/__splinen__.m: New support function for N-dimensional\n\tspline interpolation.\n\t* general/bicubic.m: Allow definition of extrapolation\n\tvalue. Adapt tests to use new graphics interface\n\t* general/interp2.m: Call __splinen__ for 2-D spline\n\tinterpolation. Make the lookup table code only be called for\n\tlinear and nearest methods.\n\t* general/interpn.m: New function for N-dimensional, linear, nearest\n\tand spline interpolation.\n\t* general/interp3.m: New function for 3-dimensional, linear, nearest\n\tand spline interpolation.\n\t* polynomial/spline.m: Change examples to use new graphics interface.\n\n2007-06-12  Steve M. Robbins  <steve@sumost.ca>\n\n\t* statistics/tests/wilcoxon_test.m: Error if N <= 25.\n\n2007-06-12  Søren Hauberg  <soren@hauberg.org>\n\n\t* plot/fplot.m: If function is inline, vectorize it.\n\n2007-06-10  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (pkg:installed_packages): truncate start of package\n\tdirectory if need to, so that it fits on a line.\n\n2007-06-07  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (pkg): For rebuild target, force package order in\n\tsaved file so that dependent packages are loaded first, and if\n\tnargout==0 don't return any arguments.\n\t(pkg:install): Only load packages that are marked autoload after\n\tinstall. Various fixes. Save in order.\n\t(pkg:uninstall): Save in order\n\t(pkg:load_packages): Use load_package_and_dependencies to load\n\tpackages.\n\t(pkg:save_order): New function to sort package list with dependent\n\tpackages first.\n\t(pkg:load_packages_and_dependencies): New function to load both a\n\tlist of packages and their dependencies.\n\t(pkg:load_package_dirs): New function that returns a vector of the\n\tindexes into the installed package list indicating the packages to\n\tload and the order to load them in to respect the dependencies.\n\n2007-06-03  Søren Hauberg  <soren@hauberg.org>\n\n\t* plot/axes.m: Eliminate redundant else clause.\n\n2007-06-03  David Bateman  <dbateman@free.fr>\n\n\t* polynomial/spline.m: Add a small tolerance to spline tests.\n\t* pkg/pkg.m: Protect against multiple actions being define.\n\n2007-06-01  David Bateman  <dbateman@free.fr>\n\n\t* pkg.m (pkg:is_superuser): Remove function used in one place and\n\tincorporate into main pkg function.\n\t(pkg:install): Check for existence of files to install before\n\tglobbing and warn the user if they don't exist.\n\n2007-05-31  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/copyfile.m: Split copying of multiple files to a\n\tdirectory over several copy command to limit the line length.\n\t* miscellaneous/movefile.m: Ditto.\n\n\t* pkg.m: Add build option to allow binary Octave packages to be\n\tbuilt from source packages. Probe absolute path of prefix, global\n\tand local lists. Use strcat, rather that [] for strings.\n\t(pkg:build): New function to binary binary package.\n\t(pkg:absolute_pathname): Use fileattrib to probe absolute path.\n\t(pkg:repackage): Package binary Octave package from installation.\n\t(pkg:create_pkgadddel): Extract PKG_ADD and PKG_DEL directives\n\tfrom m-files into main installation directory.\n\t(pkg:shell): Suppress verbose messages from shell and only display\n\tthem with the verbose flag.\n\t(pkg:installed_packages): Also include the loaded flag in the\n\tlocal and global packages.\n\t(pkg:uninstall): On uninstall, only rmpath the package if it is\n\tflagged as loaded.\n\n2007-05-31  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* pkg.m (pkg:load_packages): Correctly load a mix of packages\n\twith and without architecture dependent directories.\n\t(pkg:installed_packages): Probe the global_list file even if it is\n\tthe same as the local_list.\n\n2007-05-29  John W. Eaton  <jwe@octave.org>\n\n\t* sparse/spy.m: Set axis to \"ij\" mode.\n\n2007-05-24  John W. Eaton  <jwe@octave.org>\n\n\t* set/ismember.m: Quote first arg of \"fail\" tests.\n\n2007-05-24  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (pkg:rebuild): Thinko in rebuild logic.\n\n2007-05-22  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m: Use rethrow(lasterror()) throughout rather than\n\terror(lasterr()(8:end)).\n\t(pkg:install): Warning for empty packages being removed. Suppress\n\tspurious output. Warning rather than error for uninstalling a\n\tpackage that is not installed to avoid RPM issue.\n\t(pkg:configure_make): Fix for parsing of src/FILES. Don't create\n\tinst or architecture dependent directory if it exists.\n\n2007-05-22  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* ChangeLog, control/system/is_stabilizable.m, general/bicubic.m,\n\timage/ind2gray.m, image/saveimage.m, plot/box.m, plot/grid.m,\n\tsignal/freqz.m: Fix typos.\n\n2007-05-21  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m: Add rebuild target, and -local, -global option to\n\tforce installation location.\n\t(rebuild): New subfunction to rebuild package database from\n\tinstalled packages. Also allows changing of autoload status\n\t(install): Warn use if attempting to install from non existent\n\tfile.\n\t(issuperuser): Use 'geteuid() == 0' instead of 'strcmp (getenv(\n\t\"USER\", \"root\"))' for root test.\n\n2007-05-21  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* miscellaneous/copyfile.m: check for cp.exe on Windows platforms\n\tand replace \"\\\" characters with \"/\".\n\t* pkg/pkg.m: Use shell rather than system throughout. Replace \"\\\"\n\tcharacters with \"/\" throughout.\n\t(shell): New subfunction that wraps system and is careful with the\n\tshell on windows platforms.\n\t(configure_make): Explictly pass complier etc to configure\n\tprocess.\n\t(issuperuser): Force default to global install for Windows machines.\n\n2007-05-19  Kristan Onu\n\n\t* plot/Makefile.in (SOURCES): Remove hbar.m and add barh.m.\n\n2007-05-18  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (install): More verbosity.\n\t(configure_make): Ditto.\n\t(create_pkgadddel): Install in architecture dependent directory if\n\tit exists to address issues with autoload/mfilename.\n\t(write_INDEX): Check in archiecture dependent directories as well.\n\n2007-05-17  David Bateman  <dbateman@free.fr>\n\n\t* plot/hbar.m: Remove.\n\t* plot/barh.m: and move it here.\n\n2007-05-16  Søren Hauberg  <soren@hauberg.org>\n\n\t* general/sub2ind.m, general/ind2sub.m: Doc fix.\n\n2007-05-16  John W. Eaton  <jwe@octave.org>\n\n\t* general/logspace.m: Return second arg if fewer than two values\n\tare requested.\n\n2007-05-14  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_figure__.m: Ensure that a reset commands starts\n\ton a new line.\n\n2007-05-14  Tarmigan Casebolt  <tarmigan+list@gmail.com>\n\n\t* statistics/distributions/norminv.m,\n\tstatistics/distributions/norminv.m,\n\tstatistics/distributions/normpdf.m,\n\tstatistics/distributions/normrnd.m:\n\tUse standard deviation, not variance.\n\t* statistics/distributions/lognpdf.m: Adapt to change in norminv.\n\t* statistics/distributions/logninv.m: Refer to norminv, not normal_inv.\n\t* deprecated/normal_cdf.m, deprecated/normal_inv.m,\n\tdeprecated/normal_pdf.m, deprecated/normal_rnd.m: Preserve\n\tbackward compatibility.\n\n2007-05-14  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m: Mark loaded packages with \"*\".\n\n2007-05-13  Søren Hauberg  <soren@hauberg.org>\n\n\t* miscellaneous/single.m: Doc fix.\n\tConvert to double instead of returning argument unchanged.\n\n\t* miscellaneous/doc.m: Doc fix.\n\n\t* miscellaneous/ver.m: Doc fix.\n\tDon't display information about Octave Forge.\n\n2007-05-12  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m: Add a \"-verbose\" option that allows all output of an\n\tinstall to be printed. An error in the on_uninstall script causes\n\ta failure to uninstall. Place oct- and mex-files in an\n\tarchitecture dependent directory.\n\n2007-05-09  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Break plot command over multiple lines.\n\n2007-05-09  G. D. McBain  <geordie.mcbain@aeromech.usyd.edu.au>\n\n\t* statistics/distributions/normcdf.m: Use standard deviation\n\tinstead of variance for compatibility.\n\n2007-05-08  John W. Eaton  <jwe@octave.org>\n\n\t* set/unique.m, set/ismember.m: Use numel(x) instead of prod(size(x)).\n\n\t* set/ismember.m: Always return logical values.\n\n\t* set/ismember.m: Return early if no matches are found.  New tests.\n\tFrom David Grohmann <grohmann@arlut.utexas.edu>.\n\n\t* general/__isequal__.m: Allow numeric values of different classes\n\tto compare equal.\n\n2007-05-07  David Bateman  <dbateman@free.fr>\n\n\t* sparse/spy.m: Reverse Y axis for new graphics code. Make more\n\tcompatiable, accepting LineSpec and markersize arguments.\n\n2007-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Convert NA to NaN before writing.\n\n2007-05-02  G. D. McBain  <geordie.mcbain@aeromech.usyd.edu.au>\n\n\t* contour.m: Rewrite help string.\n\n2007-04-28  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/unzip.m, miscellaneous/untar.m,\n\tmiscellaneous/bunzip2.m, miscellaneous/gunzip.m:\n\tSpecial case nargout == 0.\n\n2007-04-27  Kim Hansen  <kimhanse@gmail.com>\n\n\t* general/sub2ind.m: Handle empty input, add tests.\n\n2007-04-27  G. D. McBain  <geordie.mcbain@aeromech.usyd.edu.au>\n\n\t* plot/contourc.m: Doc fix.\n\n2007-04-26  David Bateman  <dbateman@free.fr>\n\n\t* plot/hist.m: Partially remove previous patch.\n\n2007-04-26  David Bateman  <dbateman@free.fr>\n\n\t* plot/hist.m: Support returning of handle\n\t* plot/__bar__.m: __pltopt__ should only be called on strings or\n\tcells.\n\n2007-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: For images, set titlespec{data_idx} to\n\t\"title \\\"\\\"\", not \"\".\n\n\t* plot/legend.m: Initialize WARNED to false.\n\n2007-04-24  John W. Eaton  <jwe@octave.org>\n\n\t* io/beep.m: Fix cut and paste error.\n\tFrom Søren Hauberg  <soren@hauberg.org>.\n\n2007-04-23  John W. Eaton  <jwe@octave.org>\n\n\t* plot/box.m: Delete extra endfunction keyword.\n\n2007-04-23  David Bateman  <dbateman@free.fr>\n\n\t* plot/plot3.m: Call newplot.\n\n2007-04-20  John W. Eaton  <jwe@octave.org>\n\n\t* plot/Makefile.in (SOURCES): Fix typo in adding __bar__.m to the list.\n\n2007-04-19  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/unpack.m: Use gzip -d and bzip2 -d instead of\n\tgunzip and bunzip.  From Michael Goffioul <michael.goffioul@swing.be>.\n\n2007-04-19  A. S. Hodel  <a.s.hodel@eng.auburn.edu>\n\n\t* control/util/axis2dlim.m: Delete extraneous line.\n\n2007-04-18  John W. Eaton  <jwe@octave.org>\n\n\t* specfun/factorial.m: Increase tolerance in large value test.\n\n2007-04-18  David Bateman  <dbateman@free.fr>\n\n\t* __bar__.m: New support function for bar/hbar to support graphic\n\thandles, and additional arguments.\n\t* bar.m: Convert to use __bar__.\n\t* hbar.m: New function\n\t* hist.m: Explicitly set the width of the bar plot.\n\n2007-04-17  John W. Eaton  <jwe@octave.org>\n\n\t* plot/stem.m (stem_line_spec): Pass false as third arg to __pltopt__.\n\n\t* set/ismember.m: New tests.\n\tFrom David Grohmann <grohmann@arlut.utexas.edu>\n\n2007-04-17  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* specfun/factorial.m: Use gamma function instead of cumprod.\n\tAdd tests.\n\n2007-04-16  John W. Eaton  <jwe@octave.org>\n\n\t* gethelp.cc (looks_like_octave_copyright): Use same logic as in\n\tlooks_like_copyright in src/help.cc.\n\tFrom Søren Hauberg <soren@hauberg.org>.\n\n\t* plot/__go_draw_axes__.m: For log plots, omit zero values too.\n\n2007-04-13  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/sqp.m: Initialize info to 0.\n\n\t* optimization/qp.m: Undo previous change.\n\n2007-04-13  Geordie McBain  <geordie.mcbain@aeromech.usyd.edu.au>\n\n\t* spdiags.m: Fixed the four-argument case to work for columns of\n\tlength one.\n\n2007-04-12  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/qp.m: Avoid Octave indexing bug.\n\n2007-04-12  Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* miscellaneous/menu.m, control/base/bddemo.m,\n\tcontrol/hinf/dgkfdemo.m, control/system/packedform.m,\n\tcontrol/system/sysrepdemo.m:\n\tAdapt to page_screen_output as a function.\n\n2007-04-11  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/not.m: Delete.\n\t* miscellaneous/Makefile.in (SOURCES): Delete it from the list.\n\n2007-04-11  A. S. Hodel  <a.s.hodel@eng.auburn.edu>\n\n\t* control/util/axis2dlim.m: Try harder to handle min and max vals\n\tthat are close but not exactly equal.\n\n2007-04-11  David Bateman  <dbateman@free.fr>\n\n\t* general/bitcmp.m: Make it work again.\n\n2007-04-10  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Try harder to handle min and max vals\n\tthat are close but not exactly equal.\n\n2007-04-09  Daniel J. Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/stem.m: Add back the baseline line and let it be not adjustable\n\tin response to a change in x limits for now.\n\n2007-04-09  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m (__gnuplot_write_data__): New function.\n\t(__go_draw_axes__): Use it to write data to plot stream.\n\n2007-04-09  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/stem.m: Fix typos in doc string.  Fix typo in call to\n\tzeros.  Set markerfacecolor property in call to plot.\n\n2007-04-06  John W. Eaton  <jwe@octave.org>\n\n\t* linear-algebra/norm.m: Use new __vnorm__ function for vector args.\n\n2007-04-06  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/stem.m: Use plot instead of a series of calls to line.\n\n2007-04-05  John W. Eaton  <jwe@octave.org>\n\n\t* sparse/nonzeros.m, sparse/normest.m, sparse/spconvert.m,\n\tsparse/spdiags.m, sparse/speye.m, sparse/spfun.m, sparse/spones.m,\n\tsparse/sprand.m, sparse/sprandn.m, sparse/sprandsym.m,\n\tsparse/spstats.m, sparse/treeplot.m: Style fixes.\n\n\t* pkg/pkg.m: Use \"strcat (...)\" instead of \"[...]\".\n\tUse strcmpi instead of strcmp+tolower.\n\tStyle fixes.\n\n\t* testfun/speed.m: Use \"strcat (...)\" instead of \"[...]\".\n\tPlotting fixes.  Style fixes.\n\n\t* testfun/test.m: Use \"strcat (...)\" instead of \"[...]\".\n\tStyle fixes.\n\n\t* testfun/fail.m: No need to check for evalin and lastwarn.\n\tStyle fixes.\n\n\t* testfun/demo.m, testfun/example.m: Style fixes.\n\tUse \"strcat (...)\" instead of \"[...]\".\n\tUse format specifiers in calls to warning.\n\n\t* testfun/assert.m: Use \"numel (x)\" instead of \"prod (size (x))\".\n\tUse \"strcat (...)\" instead of \"[...]\".\n\tUse \"x(end)\" instead of \"x(length (x))\".\n\tCheck NA before NaN.\n\tStyle fixes.\n\n2007-03-29  John W. Eaton  <jwe@octave.org>\n\n\t* plot/stem.m (stem, set_default_values): Use RGB triple for color.\n\n2007-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in, audio/Makefile.in, control/Makefile.in,\n\tcontrol/base/Makefile.in, control/hinf/Makefile.in,\n\tcontrol/obsolete/Makefile.in, control/system/Makefile.in,\n\tcontrol/util/Makefile.in, deprecated/Makefile.in,\n\telfun/Makefile.in, finance/Makefile.in, general/Makefile.in,\n\timage/Makefile.in, io/Makefile.in, linear-algebra/Makefile.in,\n\tmiscellaneous/Makefile.in, optimization/Makefile.in,\n\tpath/Makefile.in, pkg/Makefile.in, plot/Makefile.in,\n\tpolynomial/Makefile.in, quaternion/Makefile.in, set/Makefile.in,\n\tsignal/Makefile.in, sparse/Makefile.in, specfun/Makefile.in,\n\tspecial-matrix/Makefile.in, startup/Makefile.in,\n\tstatistics/Makefile.in, statistics/base/Makefile.in,\n\tstatistics/distributions/Makefile.in,\n\tstatistics/models/Makefile.in, statistics/tests/Makefile.in,\n\tstrings/Makefile.in, testfun/Makefile.in, time/Makefile.in:\n\tUse ln instead of $(LN_S) in dist target.\n\n2007-03-27  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Allow linewidth settings to work with\n\tgnuplot 4.0.\n\n2007-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Send image data to gnuplot via plot stream.\n\n2007-03-26  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/__go_draw_axes__.m: Always end palette data to gnuplot via\n\tplot stream and using binary data.\n\n2007-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__plt1__.m, plot/__plt2__.m, plot/__plt2mm__.m,\n\tlot/__plt2mv__.m, plot/__plt2ss__.m, plot/__plt2vm__.m,\n\tplot/__plt2vv__.m: Accept properties in addtition to options struct.\n\n2007-03-26  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Send \"set ticslevel 0\" to plot stream.\n\n\t* plot/plot3.m: Handle line properties.\n\t* plot/plot.m: Update docstring.\n\t* plot/__plotopt__.m, plot/__pltopt1__.m: New arg, err_on_invalid.\n\t* plot/__plt__.m: Also gather properties.\n\n2007-03-26  Kim Hansen  <kimhanse@gmail.com>\n\n\t* testfun/assert.m: Delete special check for empty objects.\n\tAdd test.\n\n2007-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow.m: Exit early if call is recursive.\n\n\t* plot/__go_draw_axes__.m (get_data_limits): New function.\n\tCheck for Inf too.\n\t(__go_draw_axes__): Use get_data_limits.\n\n2007-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow.m: If GNUTERM is set to wxt in the environment,\n\tsend terminal setting command with title option to plot stream.\n\n\t* plot/legend.m: Correctly increment index into list of children..\n\n2007-03-23  John W. Eaton  <jwe@octave.org>\n\n\t* general/interp2.m, general/bicubic.m, control/base/rldemo.m,\n\tcontrol/hinf/hinfdemo.m, control/hinf/dhinfdemo.m,\n\tcontrol/base/nyquist.m, control/base/nichols.m,\n\tcontrol/base/frdemo.m, signal/freqz_plot.m,\n\tcontrol/base/__stepimp__.m, control/base/bode.m,\n\tquaternion/demoquat.m, quaternion/qcoordinate_plot.m,\n\tstatistics/base/qqplot.m, statistics/base/ppplot.m, sparse/spy.m:\n\tUpdate plotting code.\n\n\t* control/base/bode.m: Unwrap phase angle.\n\n\t* miscellaneous/dump_prefs.m: Remove automatic_replot from the list.\n\n\t* plot/axis.m: Don't check automatic_replot, or call replot.\n\n\t* quaternion/demoquat.m: Delete comments with obsolete plotting\n\tcommands.\n\n\t* plot/__pltopt1__.m: Handle \"@\" marker same as \"+\".\n\tHandle numeric color specs.\n\t* plot/plot.m: Remove \"-@\" and \"@\" from docstring.\n\n\t* plot/orient.m: Fix tests to avoid creating a plot window.\n\n\t* elfun/acosd.m, elfun/acotd.m, elfun/acscd.m, elfun/asecd.m,\n\telfun/asind.m, elfun/atand.m, elfun/cosd.m, elfun/cotd.m,\n\telfun/cscd.m, elfun/secd.m, elfun/sind.m, elfun/tand.m,\n\tgeneral/arrayfun.m, miscellaneous/compare_versions.m,\n\tpath/savepath.m, pkg/pkg.m, plot/__gnuplot_version__.m,\n\tplot/contour.m, plot/contourc.m, plot/legend.m, plot/stem.m,\n\tpolynomial/pchip.m: Fix copyright notice, correct FSF address.\n\n\t* plot/__go_draw_figure__.m: Send reset to gnuplot before every\n\tplot, not just multiplots.\n\n\t* plot/__go_draw_axes__.m: Use %g for label coordinates, not %d.\n\n\t* plot/contour.m: Don't call drawnow.\n\n2007-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow.m: Check and optionally, set, the __modified__\n\tproperty of each figure.\n\n\t* plot/__go_draw_axes__.m: If no real data, plot a point at Inf,\n\tInf to show axes.  From Daniel J Sebald <daniel.sebald@ieee.org>.\n\n2007-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* linear-algebra/null.m: Set elements of retval with magnitudes\n\tless than eps to 0.\n\n2007-03-21  David Bateman  <dbateman@free.fr>\n\n\t* plot/__go_draw_axes__.m: Handle some colors with older gnuplot.\n\t* testfun/speed.m: Documentation and example fix.\n\n2007-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* plot/subplot.m: If we find an existing subplot region, set\n\tit to be the \"currentaxes\" property for the current figure.\n\tDelete old axes objects if the new axes object overlaps the old.\n\n2007-03-20  David Bateman  <dbateman@free.fr>\n\n\t* general/Makefile.in: Include arrayfun.m in SOURCES.\n\n2007-03-20  Bill Denney  <denney@seas.upenn.edu>\n\n\t* general/arrayfun.m: New function.\n\n2007-03-20  John W. Eaton  <jwe@octave.org>\n\n\t* plot/newplot.m: Call __request_drawnow__ after initializing axes.\n\t* plot/text.m: Call __request_drawnow__ after creating text objects.\n\n\t* plot/clf.m: Don't call drawnow.\n\n2007-03-20  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* image/__img__.m: Maybe set yaxis to reverse for images.\n\t* plot/__go_draw_axes__.m: Don't add flipy to gnuplot command for\n\timages.\n\n\t* plot/drawnow.m: Make __go_close_all_registered__ persistent\n\tinstead of global.  Only register __go_close_all__ with atexit if\n\tthe plot stream is successfully opened.\n\n2007-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__go_draw_axes__.m: Make have_newer_gnuplot persistent.\n\tFrom Daniel J Sebald <daniel.sebald@ieee.org>.\n\n2007-03-15  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/__go_draw_axes__.m (do_linestyle_command): Fix marker types.\n\tUse numeric line types.\n\n\t* control/base/rlocus.m: Add asymptotes to the plot.  Use wider\n\tlines and larger markers.  Remove key titles from line type\n\tproperties.\n\n2007-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__axis_label__.m: Accept additional property-value pairs\n\tand pass them to __go_text__.  Simply return the handle obtained\n\tfrom __go_text__ instead of calling get on the current axis.\n\t* plot/xlabel.m, plot/zlabel.m, plot/zlabel.m: Check args here.\n\tAllow for extra property value pairs to be passed along.\n\t* plot/title.m: Implement with __axis_label__ since it does all\n\tthat title needs to do.\n\n\t* plot/clf.m: Set currentaxes property for current figure to [].\n\n\t* plot/__axis_label__.m: Convert arg to text handle before calling set.\n\n\t* plot/__plt__.m: Return line handles from all calls to __plt1__\n\tand __plt2__, not just the last.\n\n\t* plot/Makefile.in (SOURCES): Rename from SOURCES_M.\n\t(SOURCES_IN, GEN_M): Delete.\n\t(FCN_FILES): Don't include $(GEN_M).\n\t(all): Don't depend on $(GEN_M).\n\t($(GEN_M) : %.m : %.in): Delete pattern rule.\n\n\t* plot/text.m: Use __go_text__ instead of __uiboject_text_ctor__.\n\n\t* plot/newplot.m: Call __go_axes_init__ instead of\n\t__uiobject_axes_init__.\n\n\t* plot/mesh.m: Use __go_surface__ instead of\n\t__uiobject_surface_ctor__.  Don't access object fields directly.\n\n\t* plot/line.m: Use __line__ to do actual work.\n\t* plot/__line__.m: New function.\n\n\t* plot/axes.m: Use __go_axes__ to create axes graphics handle.\n\tUse get and set instead of accessing object fields directly.\n\n\t* plot/figure.m: Use __go_figure__ to create figure graphics\n\thandle.\n\n\t* plot/drawnow.m: Register __go_close_all__ with atexit instead of\n\t__uiobject_close_all.  Call __go_draw_figure__ instead of\n\t__uiobject_draw_figure__.\n\n\t* plot/clf.m: Use get instead of accessing object fields\n\tdirectly.  Simply delete children.  Don't set currentaxes.\n\n\t* plot/close.m (close_all_figures): New subfunction.\n\tUse it instead of getting list of figures to close from\n\t__uiobject_figures__.\n\n\t* plot/closereq.m: Simply delete the current figure.  Don't set\n\tcurrentfigure.\n\n\t* plot/__errplot__.m: Call __line__ instead of\n\t__uiobject_line_ctor__.  Use set instead of accesing object fields\n\tdirectly.  Don't call __uiobject_adopt__.\n\n\t* plot/__uiobject_adopt__.m, plot/__uiobject_alloc__.in,\n\tplot/__uiobject_axes_ctor__.m, plot/__uiobject_axes_dtor__.m,\n\tplot/__uiobject_axes_init__.in, plot/__uiobject_axes_setr__.m,\n\tplot/__uiobject_delete__.m, plot/__uiobject_figure_ctor__.m,\n\tplot/__uiobject_figures__.in, plot/__uiobject_free__.in,\n\tplot/__uiobject_get_handle__.in, plot/__uiobject_globals__.m,\n\tplot/__uiobject_grow_list__.in, plot/__uiobject_handle2idx__.in,\n\tplot/__uiobject_image_ctor__.m, plot/__uiobject_init_figure__.in,\n\tplot/__uiobject_init_root_figure__.in,\n\tplot/__uiobject_line_ctor__.m, plot/__uiobject_make_handle__.in,\n\tplot/__uiobject_root_figure_ctor__.m,\n\tplot/__uiobject_surface_ctor__.m, plot/__uiobject_text_ctor__.m:\n\tplot/get.in, plot/include-globals.awk, plot/ishandle.m,\n\tplot/set.in: Delete.\n\t* plot/Makefile.in (SOURCES_M, SOURCES_IN): Remove from lists.\n\n\t* plot/__go_close_all__.m: Rename from __uiobject_close_all.m.\n\tPass \"hidden\" as second arg to close.\n\t* plot/__go_draw_axes__.m: Rename from __uiobject_draw_axes.m.\n\t* plot/__go_draw_figure__.m: Rename from __uiobject_draw_figure.m.\n\t* plot/Makefile.in (SOURCES_M): Rename in list.\n\n\t* image/__img__.m: Use __go_image__ to create image graphics\n\thandle.\n\n\t* miscellaneous/delete.m: Call __go_delete__, not\n\t__uiobject_delete__.  Check that arg is a graphics handle before\n\tcalling __go_delete__.\n\n2007-03-13  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/cast.m: Use feval and strcmp with cell to check\n\targ instead of switch statement.\n\tFrom Søren Hauberg <soren@hauberg.org>.\n\n2007-03-12  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/cast.m: New function.\n\n\t* miscellaneous/delete.m: Call __go_delete__, not __uiobject_delete__.\n\n2007-03-08  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/copyfile.m, miscellaneous/movefile.m: Perform\n\ttilde expansion on target filename before passing it to the shell.\n\n\t* statistics/base/Makefile.in (SOURCES): Remove unidrnd.m from list.\n\t* statistics/distributions/Makefile.in (SOURCES): Add it here.\n\n2007-03-08  David Bateman  <dbateman@free.fr>\n\n\t* statistics/base/unidrnd.m: Move to statistics/distributions\n\treplacing slower version based on dicrete_rnd.\n\n2007-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* control/base/rlocus.m: Update for current plotting functions.\n\n2007-03-07  A. S. Hodel  <a.s.hodel@eng.auburn.edu>\n\n\t* control/base/rlocus.m: Improve display.\n\n2007-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* plot/legend.m: Only handle positions -1:4.\n\t* plot/__pltopt1__.m: Don't set linestyle if only marker style is\n\tfound in option string\n\t* plot/__uiobject_draw_axes__.m: Handle key position.\n\n\t* plot/newplot.m: Always reset next line color.\n\n\t* testfun/assert.m: Check that number of dimensions match before\n\tchecking dimensions.\n\n2007-03-07  Muthiah Annamalai  <muthuspost@gmail.com>\n\n\t* specfun/perms.m, specfun/factorial.m: Check args.\n\n2007-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* plot/mesh.m: Call newplot before doing anything.\n\n\t* plot/__uiobject_draw_axes__.m: Send \"e\\n\" at end of data, not\n\tjust \"e\".  Only flush plot stream once.\n\tFrom Daniel J Sebald <daniel.sebald@ieee.org>.\n\n\t* strings/blanks.m: Omit first index in assignment.\n\n2007-03-07  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* set/setdiff.m: Some code cleanup and a fix for setdiff on rows.\n\n2007-03-06  David Bateman  <dbateman@free.fr>\n\t    John W. Eaton  <jwe@octave.org>\n\n\t* set/setdiff.m: Ignore \"rows\" for cell array args.\n\tHandle cellstr args.\n\n2007-03-05  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/sqp.m: Defer first call to obj_hess until after\n\tcalling obj_fun.\n\n2007-03-02  Bob Weigel  <rweigel@gmu.edu>\n\n\t* specfun/nchoosek.m: Fix nargin check.\n\n2007-03-01  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* image/__img__.m: Don't set xlim and ylim properties.\n\n2007-03-01  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* general/interp1.m: Fix *style cases for decreasing x.\n\n2007-03-01  Muthiah Annamalai  <muthuspost@gmail.com>\n\n\t* polynomial/roots.m: Check nargin before accessing arg.\n\n2007-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m: If looking at image data, Don't\n\tincrement data_idx unless using gnuplot for display.\n\n2007-02-28  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/__uiobject_draw_axes__.m: Improve calculation of limits for\n\tplots with images.\n\t* image/image.m, image/imagesc.m, image/imshow.m:\n\tDeprecate zoom argument.\n\n2007-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m: Use fullfile to generate\n\ttemporary file names.  Keep image and colormap file ids separate.\n\n\t* general/interp1.m: Correctly compute min and max values when\n\tvalues are decreasing and not evenly spaced.\n\tFrom Ricardo Marranita <ricardo.marranita@gmail.com>.\n\n2007-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* testfun/test.m (test): Handle possibility of file_in_loadpath\n\treturning an empty cell array.\n\n2007-02-27  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* pkg/pkg.m: Use fullfile to create filenames from parts.\n\n2007-02-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in, audio/Makefile.in, control/Makefile.in,\n\tcontrol/base/Makefile.in, control/hinf/Makefile.in,\n\tcontrol/obsolete/Makefile.in, control/system/Makefile.in,\n\tcontrol/util/Makefile.in, deprecated/Makefile.in,\n\telfun/Makefile.in, finance/Makefile.in, general/Makefile.in,\n\timage/Makefile.in, io/Makefile.in, linear-algebra/Makefile.in,\n\tmiscellaneous/Makefile.in, optimization/Makefile.in,\n\tpath/Makefile.in, pkg/Makefile.in, plot/Makefile.in,\n\tpolynomial/Makefile.in, quaternion/Makefile.in, set/Makefile.in,\n\tsignal/Makefile.in, sparse/Makefile.in, specfun/Makefile.in,\n\tspecial-matrix/Makefile.in, startup/Makefile.in,\n\tstatistics/Makefile.in, statistics/base/Makefile.in,\n\tstatistics/distributions/Makefile.in,\n\tstatistics/models/Makefile.in, statistics/tests/Makefile.in,\n\tstrings/Makefile.in, testfun/Makefile.in, time/Makefile.in:\n\tUse $(LN_S) instead of ln or ln -s.\n\n2007-02-24  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (configure_make): Ignore blank lines and trailing\n\t'\\n' in FILES file.\n\t(configure_make): Also install any mex files.\n\n2007-02-24  David Bateman  <dbateman@free.fr>\n\n\t* statistics/distributions (SOURCES): Add nbincdf.m,\n\tnbininv.m, nbinpdf.m and nbinrnd.m.\n\n2007-02-23  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/distributions/Makefile.in (SOURCES): Remove\n\tpascal_cdf.m pascal_inv.m pascal_pdf.m pascal_rnd.m from the list.\n\n\t* deprecated/Makefile.in (SOURCES): Add pascal_cdf.m,\n\tpascal_inv.m, pascal_pdf.m, and pascal_rnd.m to the list.\n\n2007-02-23  David Bateman  <dbateman@free.fr>\n\n\t* statistics/distributions/discrete_rnd.m,\n\tstatistics/distributions/geornd.m,\n\tstatistics/distributions/lognnd.m,\n\tstatistics/distributions/nbinrnd.m,\n\tstatistics/distributions/wblrnd.m:  Accelerate distributions.\n\n\t* statistics/distributions/unidcdf.m,\n\tstatistics/distributions/unidinv.m,\n\tstatistics/distributions/unidpdf.m,\n\tstatistics/distributions/unidrnd.m: New functions based on\n\tdiscrete_cdf, etc.\n\n\t* statistics/distributions/pascal_cdf.m,\n\tstatistics/distributions/pascal_inv.m,\n\tstatistics/distributions/pascal_pdf.m,\n\tstatistics/distributions/pascal_rnd.m: Remove.\n\t* statistics/distributions/nbincdf.m,\n\tstatistics/distributions/nbininv.m,\n\tstatistics/distributions/nbinpdf.m,\n\tstatistics/distributions/nbinrnd.m: Replace with matlab\n\tcompatible functions.\n\t* deprecated/pascal_cdf.m, deprecated/pascal_inv.m,\n\tdeprecated/pascal_pdf.m, deprecated/pascal_rnd.m: Use the new\n\tnbincdf, etc functions to implement these.\n\n2007-02-22  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/__uiobject_draw_axes__.m: Insert newline between plot\n\tcommand and data.\n\n2007-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/doc.m: If index search fails, try again without\n\tthe index search option.\n\n2007-02-22  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/doc.m: Find doc.info file correctly in user directories.\n\n\t* statistics/distributions/frnd.m, statistics/distributions/exprnd.m,\n\tstatistics/distributions/gamrnd.m, statistics/distributions/trnd.m,\n\tstatistics/distributions/poissrnd.m, statistics/distributions/chi2rnd.m,\n\tstatistics/distributions/betarnd.m: Convert to use randg, rande\n\tand randp to accelerate.\n\n\t* pkg/pkg.m (fix_depends): Support > and < operators as well.\n\n2007-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m: If not using gnuplot for images,\n\tcache data and display after xlim and ylim have been determined.\n\n2007-02-22  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/__uiobject_draw_axes__.m:\n\tAllow multiple images to be displayed with gnuplot.\n\n2007-02-20  Rafael Laboissiere  <rafael@debian.org>\n\n\t* optimization/glpk.m: Document the fact that extra.mem does not work\n\tfor versions of GLPK 4.15 and later.\n\n2007-02-19  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_alloc__.in: If next available element in\n\t__uiobject_list__ is 0, grow list before doing anything else.\n\t* plot/__uiobject_grow_list__.in: Only set __uiobject_head__ on\n\tfirst call when size of __uiobject_list__ is 0.\n\n2007-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/Makefile.in (SOURCES): Remove popen2.m from the list.\n\n2007-02-16  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* miscellaneous/popen2.m: Remove as replaced with builtin.\n\n2007-02-16  Muthiah Annamalai  <muthuspost@gmail.com>\n\n\t* specfun/nchoosek.m: Check nargin.\n\n2007-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* path/addpath.m, path/rmpath.m: Delete\n\t* path/Makefile.in (SOURCES): Remove them from the list.\n\n\t* plot/__uiobject_axes_init__.in, plot/__uiobject_axes_setr__.m:\n\tDelete title, xlabel, ylabel, and zlabel properties before\n\treassigning.\n\t* plot/__uiobject_axes_init__.in: New arg, mode.\n\tDon't init outerposition if \"mode\" is \"replace\".\n\t* plot/newplot.m: Check both figure and axes nextplot properties.\n\tIf axes nextplot property is replace, pass \"replace\" as mode arg\n\tto __uiobject_axes_init__.\n\n2007-02-15  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* image/imshow.m: Don't restore old colormap.\n\n\t* plot/__uiobject_image_ctor__.m: Set xdata and ydata properties.\n\t* image/__img__.m: New file containing common parts of image.m and\n\timshow.m.\n\t* image/Makefile.in (SOURCES): Add __img__.m to the list.\n\t* image/image.m, image/imshow.m: Call __img__.\n\t* plot/__uiobject_draw_axes__.m:\n\tHandle rgb imaged data stored in 3-d arrays.\n\n\t* plot/figure.m: Doc fix.\n\n2007-02-14  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* audio/wavread.m, audio/wavwrite.m: Use types with specific sizes\n\tfor reading and writing data.  New tests.  Improve rounding.\n\n2007-02-13  John W. Eaton  <jwe@octave.org>\n\n\t* plot/stem.m: New file, adapted from OctPlot.\n\t* plot/Makefile.in (SOURCES_M): Add it to the list.\n\n\t* plot/__errcomm__.m, plot/__plr1__.m, plot/__plr2__.m,\n\tplot/__plt1__.m, plot/__plt2__.m, plot/__plt2mm__.m,\n\tplot/__plt2mv__.m, plot/__plt2ss__.m, plot/__plt2vm__.m,\n\tplot/__plt2vv__.m, plot/__plt__.m, plot/loglog.m,\n\tplot/loglogerr.m, plot/plot.m, plot/plot3.m, plot/polar.m,\n\tplot/semilogx.m, plot/semilogxerr.m, plot/semilogy.m,\n\tplot/semilogyerr.m: Return handles to line objects.\n\n2007-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_close_all.m: New file.\n\t* plot/Makefile.in (SOURCES_M): Add it to the list.\n\n2007-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow.m: Arrange for plot streams to be close on exit.\n\t* plot/__uiobject_globals__.m: Don't call mlock.\n\n\t* plot/drawnow.m: Only check for DISPLAY if isunix returns true.\n\t* plot/__uiobject_delete__.m: Send quit command and flush stream\n\tbefore calling pclose.\n\n2007-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* plot/subplot.m: Delete spurious call to axes.\n\n\t* plot/figure.m: Call drawnow for current figure before creating\n\tor switching to a new figure.\n\t* plot/__uiobject_init_figure__.in: Handle empty arg the same as\n\tnargin == 0 case.\n\n\t* testfun/assert.m: Try to avoid problems when comparisons involve\n\tstrange values like Inf+NaNi.\n\n2007-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow.m: Use gnuplot_binary() instead of just \"gnuplot\"\n\tand check gnuplot_use_title_option instead of just assuming -title\n\tworks.  From Michael Goffioul <michael.goffioul@swing.be>.\n\n\t* Makefile.in (DISTFILES): Add move-if-change to the list.\n\n\t* audio/Makefile.in, control/base/Makefile.in,\n\tcontrol/hinf/Makefile.in, control/obsolete/Makefile.in,\n\tcontrol/system/Makefile.in, control/util/Makefile.in,\n\tdeprecated/Makefile.in, elfun/Makefile.in, finance/Makefile.in,\n\tgeneral/Makefile.in, image/Makefile.in, io/Makefile.in,\n\tlinear-algebra/Makefile.in, miscellaneous/Makefile.in,\n\toptimization/Makefile.in, plot/Makefile.in,\n\tpolynomial/Makefile.in, quaternion/Makefile.in, set/Makefile.in,\n\tsignal/Makefile.in, sparse/Makefile.in, specfun/Makefile.in,\n\tspecial-matrix/Makefile.in, startup/Makefile.in,\n\tstatistics/base/Makefile.in, statistics/distributions/Makefile.in,\n\tstatistics/models/Makefile.in, statistics/tests/Makefile.in,\n\tstrings/Makefile.in, testfun/Makefile.in, time/Makefile.in,\n\tpath/Makefile.in, pkg/Makefile.in: Explicitly list source files.\n\n\t* plot/figure.m: Don't call drawnow.  Correctly init figure when\n\tonly given property list.\n\n2007-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m: Handle xdir, ydir, and zdir axis\n\tproperties.\n\n\t* plot/sombrero.m: Call box (\"off\") after mesh.\n\n\t* plot/__uiobject_draw_axes__.m: Avoid rgb colors and \"set style\n\tline default\" commands with older versions of gnuplot.\n\n\t* plot/close.m: Use get (0, \"currentifgure\") instead of gcf.\n\n2007-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m: Set pt to 0 if marker is \".\".\n\t* sparse/gplot.m: Use line style - instead of 1.\n\n2007-02-05  Rafael Laboissiere  <rafael@debian.org>\n\n\t* plot/print.m: Avoid error message from cellidx.\n\n2007-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* plot/legend.m: Fix check for data.\n\n2007-02-05  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* plot/__uiobject_draw_axes__.m (do_linestyle_command):\n\tAlways set lt and pt.\n\n2007-02-05  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* plot/contourc.m: Correctly compute X and Y.\n\n2007-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m: Use title \"\" if no explicit title.\n\tWhen setting {x,y,z}lim, also set {x,y,z}limmode to \"auto.\n\n2007-02-01  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m:\n\tDon't try to set axis limits unless we have data.\n\n\t*  plot/__plt1__.m, plot/__plt2__.m, plot/__plt2mm__.m,\n\tplot/__plt2mv__.m, plot/__plt2ss__.m, plot/__plt2vm__.m,\n\tplot/__plt2vv__.m, plot/__plt__.m, plot/__pltopt1__.m,\n\tplot/__pltopt__.m, plot/plot3.m: Set and use options struct\n\tinstead of of key and fmt strings.\n\n\t* plot/__pltopt1__.m: Greatly simplify.\n\n\t* plot/__next_line_color__.m: New file.\n\t* plot/Makefile.in (SOURCES_M): Add it to the list.\n\t* plot/newplot.m: Call __next_line_color__ here to reset rotation.\n\n\t* plot/__default_plot_options__.m: New file.\n\t* plot/Makefile.in (SOURCES_M): Add it to the list.\n\n\t* plot/__plt3__.m: Delete.\n\t* plot/Makefile.in (SOURCES_M): Remove it from the list.\n\n2007-01-31  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m: Set defaults for color,\n\tlinestyle, linewidth, marker, and markersize properties.\n\t* plot/__uiobject_draw_axes__.m: Attempt to handle line and marker\n\tcolors and widths, and line styles.\n\n\t* plot/__plt__.m, image/image.m: Don't call drawnow.\n\n\t* plot/__gnuplot_version__.m: Restore from CVS Attic.\n\t* plot/Makefile.in (SOURCES_M): Add it to the list.\n\n\t* plot/__uiobject_draw_axes__.m: Delete useless call to\n\t__gnuplot_save_data__.\n\n\t* image/image.m: Accept 2 args, but ignore the second for now.\n\n2007-01-30  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (pkg, isautoload, install, load_packages): Add ability\n\tto flag a package as to be autoloaded. Add install flags -noauto,\n\t-auto to force autoload behavior.\n\t(installed_packages): Make list of installed packages unique.\n\n2007-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* Merge of changes from graphics-branch:\n\n\t2007-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* plot/subplot.m: Set nextplot property of current figure to \"add\".\n\n\t* plot/__uiobject_draw_axes__.m: Only handle outerposition\n\tproperty if it exists.\n\n\t2007-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m: Move initialization of max and\n\tmin values outside of loop over child objects.\n\n\t* plot/contour.m, plot/contourc.m: New files.\n\t* plot/Makefile.in (SOURCES_M): Add them to the list.\n\n\t* image/image_viewer.m: Set view_fcn to \"gnuplot_internal\" if we\n\tfind a gnuplot version newer than 4.0.\n\t* image/__img_gnuplot__.m: Delete.\n\t* image/image.m: Create image graphics object.\n\tCall newplot to setup and drawnow to finish.\n\tEliminate ZOOM arg.\n\n\t* plot/__uiobject_draw_axes__.m: Handle image data.\n\n\t* plot/legend.m: Eliminate useless variable \"warned\".\n\n\t* plot/__uiobject_image_ctor__.m: New file.\n\t* plot/Makefile.in (SOURCES_M): Add it to the list.\n\n\t* plot/gcf.m: Also create new figure if currentfigure is 0.\n\t* plot/drawnow.m: Use get (0, \"currentfigure\") instead of gcf.\n\n\t* plot/__uiobject_root_figure_ctor__.m: Set visible property.\n\n\t* plot/__default_colormap__.m: New file.\n\t* plot/Makefile.in (SOURCES_M): Add it to the list.\n\t* plot/__uiobject_figure_ctor__.m: Use it to set default colormap\n\tproperty.\n\t* image/colormap.m: Use colormap property of current figure\n\tto store colormap instead of using persistent variable.\n\tCall __default_colormap__ to get default map value.\n\t* image/ocean.m, image/gray.m: Set colormap for current figure.\n\n\t* plot/__uiobject_draw_axes__.m: Handle aspect ratio property.\n\tHandle some tick mark options.\n\n\t* plot/__uiobject_axes_setr__.m: If we see xtick, ytick, or ztick,\n\tset corresponding *mode to \"manual\".  If we set dataaspectratio,\n\tset dataaspectratiomode to \"manual\".\n\n\t* plot/__uiobject_axes_init__.m: Include *tick, *tickmode,\n\t*ticklabelmode, dataaspectratio, dataaspectratiomode properties.\n\n\t* plot/axis.m: New file.\n\t* plot/Makefile.in (SOURCES_M): Include it in the list.\n\n\t* plot/__uiobject_axes_setr__.m: If we see xlim, ylim, or zlim,\n\tset corresponding *limmode to \"manual\".\n\t* plot/__uiobject_draw_axes__.m\t(get_axis_limits): New subfunction.\n\tUse it to compute autosclaled limits.\n\tArg is now handle, not object.  Change all callers.\n\tCompute data limits.\n\n\t2007-01-25  John W. Eaton  <jwe@octave.org>\n\n\t* plot/drawnow: Fix visibility check for zero args.\n\n\t* plot/text.m: New file.\n\t* plot/Makefile.in (SOURCES_M): Add it to the list.\n\t* plot/__uiobject_draw_axes__.m: Handle text objects.\n\t* plot/__uiobject_text_ctor__.m: Include units, position, and\n\thorizontalalignment properties.\n\n\t* plot/figure.m: Set options for f we just constructed or were\n\tgiven as an argument, not gcf.  Only return handle if nargout > 0.\n\n\t* plot/drawnow.m: Handle visible field for figure here.\n\t* plot/__uiobject_figure_ctor__.m: Set default visible field.\n\n\t* plot/__uiobject_draw_axes__.m: Call undo_string_escapes on\n\ttitle and axis labels.\n\n\t* plot/plot3.m, plot/mesh.m: Set default 3-d view here.\n\t* plot/__uiobject_draw_axes__.m: Handle view for 3-d plots.\n\t* plot/__uiobject_axes_init__.in: Set default view field for object.\n\t* plot/view.m: New file.\n\t* plot/Makefile.in (SOURCES_M): Add it to the list.\n\n\t* plot/__uiobject_make_handle__.in, plot/set.m, plot/drawnow.m:\n\tCall __request_drawnow__.\n\n\t* plot/newplot.m: For \"replace\" action, call __uiobject_axes_init__.\n\n\t* plot/__uiobject_axes_ctor__.m, plot/__uiobject_text_ctor__.m:\n\tCall set to set properties.  Return handle instead of structure.\n\tChange all callers.\n\n\t* plot/__uiobject_axes_setr__.m: New file.\n\t* plot/set.in: Check for __setter__ field.\n\n\t* plot/__uiobject_axes_init__.in:\n\tRename from plot/__uiobject_axes_init__.m.\n\tInclude __uiobject_globals__.\n\tAccept handle as arg instead of structure\n\t* plot/Makefile.in (SOURCES_M): Remove __uiobject_axes_init__.m\n\tfrom the list.\n\t(SOURCES_IN): Add __uiobject_axes_init__.in to the list.\n\n\t2007-01-24  John W. Eaton  <jwe@octave.org>\n\n\t* plot/Makefile.in ($(GEN_M)): Depend on __uiobject_globals__.m.\n\n\t* plot/__uiobject_globals__.m: Call __lock_global__ when\n\tinitializing each global variable.\n\n\t2007-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_globals__.m (__uiobject_handles_free_list__,\n\t__uiobject_figure_handles_free_list__): New global variables.\n\t* plot/__uiobject_get_handle__.m, plot/__uiobject_free__.m:\n\tPlace unused handles on the free list.\n\n\t* plot/__uiobject_get_figure_handle__.in: Delete.\n\t* plot/Makefile.in: Delete it from the SOURCES_IN list.\n\n\t* plot/__uiobject_init_figure__.in: Perform allocation of figure\n\thandles here.  Return figure handle.\n\t* plot/figure.m: Call __uiobject_init_figure__ to allocate handle.\n\n\t2007-01-11  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__uiobject_draw_axes__.m: Use \"%g\", not \"%.4g\" when writing\n\tdata for gnuplot.\n\n\t* plot/Makefile.in (SOURCES_M, SOURCES_IN, GEN_M): New lists of\n\tfiles.\n\t(SOURCES): Include $(SOURCES_M) and $(SOURCES_M) in the list.\n\t(DISTFILES): Include include-globals.awk in the list.\n\t(FCN_FILES): Define using $(SOURCES_M) and $(GEN_M).\n\t($(GEN_M) : %.m : %.in): New rule.\n\n\t* include-globals.awk: New file.\n\n\t* plot/__uiobject_alloc__.in, plot/__uiobject_figures__.in,\n\tplot/__uiobject_free__.in, plot/__uiobject_get_figure_handle__.in,\n\tplot/__uiobject_get_handle__.in, plot/__uiobject_grow_list__.in,\n\tplot/__uiobject_handle2idx__.in, plot/__uiobject_init_figure__.in,\n\tplot/__uiobject_init_root_figure__.in,\n\tplot/__uiobject_make_handle__.in,  plot/get.in, plot/set.in:\n\tRename from corresponding .m files.\n\n\t* move-if-change: New file.\n\n\t* plot/__uiobject_delete__.m: New file.\n\t* plot/delete.m, plot/__uiobject_delete_children__.m,\n\tplot/__uiobject_delete_child__.m: Delete.\n\t* miscellaneous/delete.m: Forward to __uiobject_delete__ if arg is\n\tnot a character string.\n\t* plot/__plt2mm__.m, plot/__plt2mv__.m, plot/__plt2vm__.m:\n\tFix assignment to tmp key value in loop.\n\t* plot/__uiobject_axes_dtor__.m: No need to Call __uiobject_free__\n\tfor obj.title, obj.xlabel, obj.ylabel, obj.zlabel.\n\t* plot/__uiobject_axes_dtor__.m, plot/__uiobject_axis_init__.m:\n\tInline code to delete children.\n\t* plot/__uiobject_free__.m: Arg is now handle, not index into\n\t__uiobject_list__.\n\t* plot/clf.m, plot/closereq.m, plot/newplot.m: No need to remove\n\tand free child.\n\n\t2006-12-08  John W. Eaton  <jwe@octave.org>\n\n\t* plot/gcf.m: Check if the root figure object's currentfigure\n\thandle is empty, not 0.\n\t* plot/__uiobject_root_figure_ctor__.m:\n\tSet currentfigure to [], not 0.\n\n\t* plot/stairs.m: Handle matrix arguments.  Improve compatibility.\n\n\t2006-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__plt_get_axis_arg__.m, plot/__uiobject_adopt__.m,\n\tplot/__uiobject_alloc__.m, plot/__uiobject_axes_ctor__.m,\n\tplot/__uiobject_axes_dtor__.m, plot/__uiobject_axes_init__.m,\n\tplot/__uiobject_delete_children__.m,\n\tplot/__uiobject_draw_axes__.m, plot/__uiobject_draw_figure__.m,\n\tplot/__uiobject_figure_ctor__.m, plot/__uiobject_figures__.m,\n\tplot/__uiobject_free__.m, plot/__uiobject_get_figure_handle__.m,\n\tplot/__uiobject_get_handle__.m, plot/__uiobject_globals__.m,\n\tplot/__uiobject_grow_list__.m, plot/__uiobject_handle2idx__.m,\n\tplot/__uiobject_init_figure__.m,\n\tplot/__uiobject_init_root_figure__.m,\n\tplot/__uiobject_line_ctor__.m, plot/__uiobject_make_handle__.m,\n\tplot/__uiobject_remove_child__.m,\n\tplot/__uiobject_root_figure_ctor__.m,\n\tplot/__uiobject_surface_ctor__.m, plot/__uiobject_text_ctor__.m,\n\tplot/axes.m, plot/box.m, plot/closereq.m, plot/delete.m,\n\tplot/drawnow.m, plot/gca.m, plot/gcf.m, plot/get.m,\n\tplot/isfigure.m, plot/ishandle.m, plot/line.m, plot/newplot.m,\n\tplot/set.m: New files.\n\n\t* plot/__plt3__.m, plot/errorbar.m, plot/__axis_label__.m,\n\tplot/__plr1__.m, plot/__errcomm__.m, plot/print.m, plot/zlabel.m,\n\tplot/__plt1__.m, plot/__plt2__.m, plot/sombrero.m, plot/shg.m,\n\tplot/fplot.m, plot/ndgrid.m, plot/clf.m, plot/hold.m,\n\tplot/ishold.m, plot/meshdom.m, plot/ylabel.m, plot/__plt2ss__.m,\n\tplot/__plt2vv__.m, plot/__plr2__.m, plot/__plt2mm__.m,\n\tplot/__pltopt1__.m, plot/meshgrid.m, plot/__plt2mv__.m,\n\tplot/figure.m, plot/xlabel.m, plot/stairs.m, plot/__plt2vm__.m,\n\tplot/bar.m, plot/__errplot__.m, plot/semilogx.m, plot/semilogy.m,\n\tplot/loglog.m, plot/polar.m, plot/legend.m, plot/orient.m,\n\tplot/title.m, plot/__pltopt__.m, plot/grid.m, plot/hist.m,\n\tplot/subplot.m, plot/plot.m, plot/mesh.m, plot/__plt__.m,\n\tplot/close.m, plot/loglogerr.m, plot/plot3.m, plot/semilogxerr.m,\n\tplot/semilogyerr.m, plot/replot.m:\n\tAdapt to new graphics data structure.\n\n\t* plot/__do_legend__.m, plot/__gnuplot_version__.m,\n\tplot/__init_plot_vars__.m, plot/__make_using_clause__.m,\n\tplot/__plot_globals__.m, plot/__plr__.m, plot/__render_plot1__.m,\n\tplot/__render_plot__.m, plot/__setup_plot__.m, plot/axis.m,\n\tplot/contour.m, plot/mplot.m, plot/multiplot.m, plot/oneplot.m,\n\tplot/plot_border.m, plot/subwindow.m: Delete.\n\n2007-01-24  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m: Install ChangeLog file if it exists.\n\tDelete bare newline in string passed to write_INDEX.\n\n\t* sparse/sprandsym.m: Make work for even values of N.\n\n2007-01-24  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/news.m: New file.\n\n2007-01-23  Luis F. Ortiz  <lortiz@interactivesupercomputing.com>\n\n\t* strings/strncmpi.m: Use strncmp instead of calling strtrunc on args.\n\n\t* strings/strncmp.m: Delete (we now have a built-in version).\n\n2007-01-22  Bob Weigel  <rweigel@gmu.edu>\n\n\t* testfun/test.m: Check for all files in path, use first found.\n\n2007-01-22  David Bateman  <dbateman@free.fr>\n\n\t* polynomial/spline.m: Make DG a column instead of a row vector.\n\n2007-01-18  Søren Hauberg  <hauberg@gmail.com>\n\n\t* pkg/pkg.m (copy_files): Call write_INDEX with correct target\n\tfile name.\n\n\t* image/ind2rgb.m: Better input checking.  Return 3-d array if\n\tnargout is 1.  Handle colormaps that have too few colors.\n\n\t* pkg/pkg.m (create_pkgadddel): Call fullfile with nm, not \"nm\".\n\t(configure_make): Use fullfile instead of concatenating with \"/\".\n\n2007-01-10  Baylis Shanks  <bshanks3@hotmail.com>\n\n\t* set/ismember.m: Handle N-d arrays.\n\n2007-01-10  David Bateman  <dbateman@free.fr>\n\n\t* elfun/acosd.m, elfun/acotd.m, elfun/acscd.m, elfun/asecd.m,\n\telfun/asind.m, elfun/atand.m, elfun/cosd.m, elfun/cotd.m,\n\telfun/cscd.m, elfun/secd.m, elfun/sind.m, elfun/tand.m:\n\tNew files.\n\n2007-01-09  Søren Hauberg  <hauberg@gmail.com>\n\n\t* pkg/pkg.m: Allow filenames to contain glob patterns.\n\n2007-01-08  Søren Hauberg  <hauberg@gmail.com>\n\n\t* pkg/pkg.m: Use copyfile instead of calling system.  Use fullfile\n\tinstead of concatenating with \"/\".  Use mlock to ensure that\n\tpersistent variables are not clobbered if user types clear all.\n\n2007-01-08  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/copyfile.m, miscellaneous/movefile.m:\n\tImprove handling of file names containing globbing characters.\n\tFrom Søren Hauberg <hauberg@gmail.com>.\n\n2007-01-05  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/optimset.m, optimization/__fsolve_defopts__.m:\n\tNew files.\n\n2006-12-30  John W. Eaton  <jwe@octave.org>\n\n\t* sparse/spfun.m: Check for \"function_handle\" not \"function handle\".\n\t* plot/fplot.m: Likewise.  Use isa instead of strcmp + class.\n\n2006-12-27  Søren Hauberg  <hauberg@gmail.com>\n\n\t* image/imshow.m: Strip NaNs from image.\n\n2006-12-08  David Bateman  <dbateman@free.fr>\n\n\t* sparse/normest.m: New file.\n\n2006-12-06  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* miscellaneous/copyfile.m, miscellaneous/movefile.m:\n\tWork on Windows systems without cp or mv.\n\n\t* startup/inputrc: Include sequences for Windows.\n\n2006-12-06  Søren Hauberg  <hauberg@gmail.com>\n\n\t* pkg/pkg.m (unload_packages): New function.\n\t(pkg): Handle unload action.\n\n\t* __errplot__.m: Add missing semicolon.\n\n2006-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/mexext.m: New file.\n\n2006-11-29  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m: Add local_list and global_list options that allow the\n\tlocation of package lists to be probed and set.\n\n2006-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__render_plot1__.m: Reverse y axis for images.\n\n\t* plot/__render_plot__.m: New args, terminal and output.\n\t* plot/print.m: Don't set output and term here.  Instead, call\n\t__render_plot__ with terminal and output.\n\n2006-11-16  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__render_plot1__.m: New file.\n\t* plot/__render_plot__.m: Use it.  Loop over multiplots.\n\t* plot/print.m, plot/subplot.m: Don't send \"set multiplot\" to\n\tgnuplot.  Let __render_plot__ do that.\n\n2006-11-16  Francesco Potorti`  <Potorti@isti.cnr.it>\n\n\t* plot/plot.m: Fix doc string.\n\n2006-11-16  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__render_plot__.m: Check for mix of 2-d and 3-d plots\n\tbefore sending anything to the plotter.\n\n2006-11-15  John W. Eaton  <jwe@octave.org>\n\n\t* image/__img_gnuplot__.m: Store more info in global plot\n\tstructures and use __render_plot__ to build plot command to\n\tdisplay image.\n\n\t* plot/__plt3__.m: New arg, parametric.  Change all callers.\n\n\t* plot/__plot_globals__.m (__plot_line_offset__, __plot_command__,\n\t__plot_command_sep__): Delete.\n\t(__plot_data_type__, __plot_data_parametric__,\n\t__plot_image_colormap__, __plot_image_dims__, __plot_fmtstr__,\n\t__plot_usingstr__, __plot_withstr__): New variables.\n\t* plot/__init_plot_vars__.m: Initialize them.\n\n\t* plot/__init_plot_vars__.m, plot/__setup_plot__.m:\n\tDon't handle sep or cmd.\n\n\t* plot/__render_plot__.m: New function.\n\t* plot/__plt__.m, plot/__plt3__.m, plot/__errplot__.m:\n\tStore more info in global plot structures and use __render_plot__\n\tto build plot command.\n\t* plot/replot.m: Simply call __render_plot__.\n\n\t* plot/contour.m, plot/mesh.m, plot/plot3.m:\n\tSet __plot_data_parametric__ here.\n\n2006-11-14  John W. Eaton  <jwe@octave.org>\n\n\t* plot/bottom_title.m, plot/top_title.m: Delete.\n\n\t* image/image_viewer.m: Set default values here.\n\t* image/image.m: Not here.\n\n\t* image/image_viewer.m: Always return old values.  Check arguments.\n\t* image/__img_gnuplot__.m: Rename from __img__m.\n\n2006-11-14  Søren Hauberg  <soren@hauberg.org>\n\n\t* image/image_viewer.m: New function.\n\t* image/__img_via_file__.m: New function.\n\t* image/image.m: Use image_viewer to determine which program to\n\tuse for image viewing.\n\t* image/__img__.m: Silently accept more than 3 args.\n\n2006-11-14  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__do_legend__.m, plot/__errplot__.m,\n\tplot/__init_plot_vars__.m, plot/__plot_globals__.m,\n\tplot/__plt3__.m, plot/__plt__.m, plot/__setup_plot__.m,\n\tplot/legend.m, plot/mplot.m, plot/multiplot.m, plot/oneplot.m,\n\tplot/replot.m, plot/subplot.m, plot/subwindow.m:\n\tUse __plot_globals__ for multiplot variables.  Keep track of\n\tmultiplot info for each figure.  Eliminate __multiplot_xscale__.\n\n2006-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* plot/mesh.m: Use proper dimensions for y in call to repmat.\n\n\t* miscellaneous/substruct.m: New function.\n\n\t* testfun/assert.m: Force orientation to match when comparing\n\tstruct elements.\n\n\t* general/__isequal__.m: Avoid assignment of comma-separated lists\n\twhen comparing structs.\n\n2006-11-13  Søren Hauberg  <hauberg@gmail.com>\n\n\t* general/bicubic.m, general/cart2pol.m, general/cart2sph.m,\n\tplot/contour.m, linear-algebra/cross.m, general/cumtrapz.m,\n\tlinear-algebra/dot.m, image/imshow.m, general/interp2.m,\n\tgeneral/mod.m, plot/plot3.m, plot/__plr2__.m, plot/__plr__.m,\n\tgeneral/pol2cart.m, general/polyarea.m, polynomial/polyfit.m,\n\tgeneral/rem.m, image/rgb2ind.m, general/sph2cart.m,\n\tgeneral/trapz.m, miscellaneous/xor.m: Use size_equal.\n\n2006-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* plot/mesh.m: Use size_equal to compare dimensions.\n\n2006-11-13  Søren Hauberg  <soren@hauberg.org>\n\n\t* plot/mesh.m: Simplify.  Set hidden3d for the plot.\n\n2006-11-11  Søren Hauberg  <soren@hauberg.org>\n\n\t* miscellaneous/copyfile.m: Fix docs to match function.\n\n2006-11-08  John W. Eaton  <jwe@octave.org>\n\n\t* plot/legend.m: New function, adapted from Octave Forge.\n\n\t* plot/__do_legend__.m: New function.\n\t* plot/__errplot__.m, plot/__plt3__.m, plot/__plt__.m,\n\tplot/replot.m: Call it before plotting.\n\n\t* plot/plot3.m, plot/mesh.m, plot/contour.m: Don't send \"set\n\tnoparametric\" to gnuplot..\n\n\t* plot/__plotopt__.m, plot/__pltopt1__.m, plot/__plt1__.m,\n\tplot/__plt2__.m, plot/__plt2mm__.m, plot/__plt2mv__.m,\n\tplot/__plt2ss__.m, plot/__plt2vm__.m, plot/__plt2vv__.m: Accept\n\tand return key title separate from line format.  Accept format and\n\tkey as cellstr.  Always return data as cell array.  Return format\n\tand key title as cellstr.\n\t* plot/__errplot__.m, plot/__plt3__.m, plot/__plt__.m:\n\tHandle line format and key titles separately.\n\t* plot/__plt3__.m, plot/__plt__.m: Handle data as cell array only.\n\n\t* plot/__plot_globals__.m (__plot_line_offset__,\n\t__plot_key_labels__, __plot_key_properties__): New global\n\tvariables.  Initialize them.\n\t* plot/__init_plot_vars__.m (__plot_line_offset__,\n\t__plot_key_labels__, __plot_key_properties__): Initialize.\n\t* plot/__errplot__.m, plot/__plt3__.m, plot/__plt__.m\n\t(__plot_line_offset__, __plot_key_labels__,\n\t__plot_key_properties__): Store information about plot key titles.\n\n\t* plot/__errplot__.m, plot/__init_plot_vars__.m, plot/__plt3__.m,\n\tplot/__plt__.m: Use cf, mxi, and myi as shorthand for\n\t__current_figure__, __multiplot_xi__, and __multiplot_yi__,\n\trespectively.\n\n\t* plot/__errcomm__.m: Allow fmt to be cellstr.\n\n\t* strings/strcat.m: Disable Octave:empty-list-elements warning\n\twhle concatenating args.\n\n2006-11-07  John W. Eaton  <jwe@octave.org>\n\n\t* startup/main-rcfile: Conditionally set PAGER_FLAGS.\n\n2006-11-06  Søren Hauberg  <soren@hauberg.org>\n\n\t* pkg/pkg.m (extract_pkg): No need to pass \"dotexceptnewline\"\n\toption to regexp.\n\n\t* image/__img__.m: Send \"set size ratio -1\" before plotting.\n\n2006-11-03  Bill Denney  <denney@seas.upenn.edu>\n\n\t* strings/index.m: New arg, direction.  Simplify and speed up.\n\t* strings/rindex.m: Implement using index (..., \"last\");\n\n\t* blanks.m, strcat.m: Simplify.  Add tests.\n\n2006-11-01  Bill Denney  <denney@seas.upenn.edu>\n\n\t* general/__isequal__.m: Test size and class more consistently.\n\n2006-10-27  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/ls_command.m: Use /D instead of /w.\n\tFrom Michael Goffioul <michael.goffioul@swing.be>.\n\n\t* miscellaneous/ls.m, miscellaneous/ls_command.m: New files.\n\t* miscellaneous/dir.m: Mark as a command.\n\n2006-10-27  William Poetra Yoga Hadisoeseno  <williampoetra@gmail.com>\n\n\t* miscellaneous/unpack.m: Fix missing comma in strcat call.\n\n2006-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* image/image.m: Set x = y = [] when nargin == 0;\n\n2006-10-25  Quentin Spencer  <qspencer@ieee.org>\n\n\t* image/image.m: Call __img__ if gnuplot version is > 4.0.\n\t* image/__img__.m: New file, originally from\n\tDaniel J Sebald <daniel.sebald@ieee.org>.\n\n2006-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__gnuplot_version__.m: New function, originally from\n\tDaniel J Sebald <daniel.sebald@ieee.org> by way of\n\tQuentin Spencer <qspencer@ieee.org>.\n\n2006-10-25  Søren Hauberg  <soren@hauberg.org>\n\n\t* plot/__pltopt__.m: Update symbol marker id numbers for gnuplot 4.\n\n2006-10-24  Bill Denney  <denney@seas.upenn.edu>\n\n\t* miscellaneous/unpack.m, miscellaneous/bunzip2.m,\n\tmiscellaneous/gunzip.m: New files.\n\t* miscellaneous/untar.m, miscellaneous/unzip.m:\n\tCall unpack to do the real work.\n\n2006-10-24  John W. Eaton  <jwe@octave.org>\n\n\t* plot/plot3.m: If we have a format string, then also pass using\n\tstring to __plt3__.\n\n\t* plot/sombrero.m: Don't return anything if nargout == 0.\n\n\t* plot/__plt3__.m: Create using clause if none is supplied.\n\t* plot/mesh.m: Always pass empty using string to __plt3__.\n\n2006-10-20  Bill Denney  <denney@seas.upenn.edu>\n\n\t* movefile.m, copyfile.m: Handle cellstr lists of files.\n\tQuote filenames in shell commands.\n\n2006-10-17  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (uninstall): Allow the uninstall to proceed even if\n\tthe package directory is missing.\n\n2006-10-13  John W. Eaton  <jwe@octave.org>\n\n\t* plot/box.m: New function.\n\n2006-10-13  Etienne Grossmann  <etienne@tyzx.com>\n\n\t* general/ind2sub.m, general/sub2ind.m: Handle empty indices.\n\n2006-10-12  Quentin Spencer  <qspencer@ieee.org>\n\n\t* plot/sombrero.m: Only plot if nargout == 0.  Otherwise, return data.\n\n2006-10-10  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/copyfile.m, miscellaneous/movefile.m: New functions.\n\n2006-10-10  Bill Denney  <denney@seas.upenn.edu>\n\n\t* audio/lin2mu.m, audio/loadaudio.m, audio/mu2lin.m,\n\taudio/playaudio.m, audio/record.m, audio/saveaudio.m,\n\taudio/setaudio.m, audio/wavread.m, audio/wavwrite.m,\n\tcontrol/base/__bodquist__.m, control/base/__freqresp__.m,\n\tcontrol/base/are.m, control/base/bode.m, control/base/ctrb.m,\n\tcontrol/base/damp.m, control/base/dare.m, control/base/dcgain.m,\n\tcontrol/base/dre.m, control/base/impulse.m, control/base/lqg.m,\n\tcontrol/base/lsim.m, control/base/lyap.m, control/base/nichols.m,\n\tcontrol/base/nyquist.m, control/base/obsv.m, control/base/pzmap.m,\n\tcontrol/base/rlocus.m, control/base/step.m, control/base/tzero.m,\n\tcontrol/hinf/h2norm.m, control/hinf/h2syn.m,\n\tcontrol/hinf/hinfnorm.m, control/hinf/hinfsyn.m,\n\tcontrol/hinf/is_dgkf.m, control/hinf/wgt1o.m,\n\tcontrol/obsolete/dezero.m, control/system/__sysdefioname__.m,\n\tcontrol/system/buildssic.m, control/system/c2d.m,\n\tcontrol/system/cellidx.m, control/system/d2c.m,\n\tcontrol/system/dmr2d.m, control/system/fir2sys.m,\n\tcontrol/system/is_abcd.m, control/system/is_controllable.m,\n\tcontrol/system/is_detectable.m, control/system/is_digital.m,\n\tcontrol/system/is_observable.m, control/system/is_siso.m,\n\tcontrol/system/is_stabilizable.m, control/system/is_stable.m,\n\tcontrol/system/jet707.m, control/system/listidx.m,\n\tcontrol/system/ord2.m, control/system/parallel.m,\n\tcontrol/system/ss.m, control/system/ss2zp.m,\n\tcontrol/system/starp.m, control/system/sys2ss.m,\n\tcontrol/system/sys2tf.m, control/system/sys2zp.m,\n\tcontrol/system/sysadd.m, control/system/sysappend.m,\n\tcontrol/system/syschtsam.m, control/system/sysconnect.m,\n\tcontrol/system/syscont.m, control/system/sysdimensions.m,\n\tcontrol/system/sysdisc.m, control/system/sysdup.m,\n\tcontrol/system/sysgetsignals.m, control/system/sysgettsam.m,\n\tcontrol/system/sysgroup.m, control/system/sysidx.m,\n\tcontrol/system/sysmin.m, control/system/sysmult.m,\n\tcontrol/system/sysout.m, control/system/sysprune.m,\n\tcontrol/system/sysscale.m, control/system/syssetsignals.m,\n\tcontrol/system/syssub.m, control/system/sysupdate.m,\n\tcontrol/system/tf.m, control/system/tfout.m,\n\tcontrol/system/ugain.m, control/system/zp.m,\n\tcontrol/system/zpout.m, control/util/__outlist__.m,\n\tcontrol/util/__zgpbal__.m, control/util/prompt.m,\n\tcontrol/util/sortcom.m, control/util/strappend.m,\n\tdeprecated/com2str.m, elfun/acot.m, elfun/acoth.m, elfun/acsc.m,\n\telfun/acsch.m, elfun/asec.m, elfun/asech.m, elfun/cot.m,\n\telfun/coth.m, elfun/csc.m, elfun/csch.m, elfun/lcm.m, elfun/sec.m,\n\telfun/sech.m, finance/fv.m, finance/fvl.m, finance/irr.m,\n\tfinance/nper.m, finance/npv.m, finance/pmt.m, finance/pv.m,\n\tfinance/pvl.m, finance/rate.m, finance/vol.m,\n\tgeneral/__isequal__.m, general/bitcmp.m, general/bitget.m,\n\tgeneral/bitset.m, general/blkdiag.m, general/cart2sph.m,\n\tgeneral/cell2mat.m, general/circshift.m, general/cplxpair.m,\n\tgeneral/cumtrapz.m, general/deal.m, general/diff.m,\n\tgeneral/flipdim.m, general/fliplr.m, general/flipud.m,\n\tgeneral/ind2sub.m, general/int2str.m,\n\tgeneral/is_duplicate_entry.m, general/isdefinite.m,\n\tgeneral/isequal.m, general/isequalwithequalnans.m,\n\tgeneral/isscalar.m, general/issquare.m, general/issymmetric.m,\n\tgeneral/isvector.m, general/logical.m, general/logspace.m,\n\tgeneral/mod.m, general/nargchk.m, general/nextpow2.m,\n\tgeneral/perror.m, general/postpad.m, general/prepad.m,\n\tgeneral/randperm.m, general/rem.m, general/repmat.m,\n\tgeneral/rot90.m, general/rotdim.m, general/shift.m,\n\tgeneral/shiftdim.m, general/sph2cart.m, general/strerror.m,\n\tgeneral/sub2ind.m, general/trapz.m, general/tril.m,\n\tgeneral/triu.m, image/gray.m, image/gray2ind.m, image/hsv2rgb.m,\n\timage/image.m, image/imagesc.m, image/ind2gray.m, image/ind2rgb.m,\n\timage/loadimage.m, image/ntsc2rgb.m, image/ocean.m,\n\timage/rgb2hsv.m, image/rgb2ntsc.m, image/saveimage.m, io/beep.m,\n\tlinear-algebra/commutation_matrix.m, linear-algebra/cond.m,\n\tlinear-algebra/cross.m, linear-algebra/dmult.m,\n\tlinear-algebra/dot.m, linear-algebra/duplication_matrix.m,\n\tlinear-algebra/krylov.m, linear-algebra/krylovb.m,\n\tlinear-algebra/logm.m, linear-algebra/norm.m,\n\tlinear-algebra/null.m, linear-algebra/orth.m,\n\tlinear-algebra/qzhess.m, linear-algebra/rank.m,\n\tlinear-algebra/trace.m, linear-algebra/vec.m,\n\tlinear-algebra/vech.m, miscellaneous/bincoeff.m,\n\tmiscellaneous/delete.m, miscellaneous/dir.m, miscellaneous/dos.m,\n\tmiscellaneous/fileattrib.m, miscellaneous/fileparts.m,\n\tmiscellaneous/flops.m, miscellaneous/fullfile.m,\n\tmiscellaneous/ispc.m, miscellaneous/isunix.m,\n\tmiscellaneous/menu.m, miscellaneous/not.m, miscellaneous/popen2.m,\n\tmiscellaneous/single.m, miscellaneous/unix.m, miscellaneous/ver.m,\n\tmiscellaneous/xor.m, optimization/glpk.m, optimization/glpkmex.m,\n\toptimization/qp.m, optimization/sqp.m, plot/__axis_label__.m,\n\tplot/__errplot__.m, plot/__plr1__.m, plot/__plr2__.m,\n\tplot/__plr__.m, plot/__plt1__.m, plot/__plt2__.m,\n\tplot/__plt2mm__.m, plot/__plt2mv__.m, plot/__plt2ss__.m,\n\tplot/__plt2vm__.m, plot/__plt2vv__.m, plot/__pltopt1__.m,\n\tplot/__pltopt__.m, plot/bar.m, plot/bottom_title.m, plot/close.m,\n\tplot/contour.m, plot/errorbar.m, plot/figure.m, plot/fplot.m,\n\tplot/grid.m, plot/hist.m, plot/hold.m, plot/ishold.m,\n\tplot/loglogerr.m, plot/mesh.m, plot/meshdom.m, plot/meshgrid.m,\n\tplot/multiplot.m, plot/orient.m, plot/polar.m, plot/replot.m,\n\tplot/semilogxerr.m, plot/semilogyerr.m, plot/sombrero.m,\n\tplot/stairs.m, plot/subplot.m, plot/subwindow.m, plot/title.m,\n\tplot/top_title.m, polynomial/compan.m, polynomial/conv.m,\n\tpolynomial/deconv.m, polynomial/mkpp.m, polynomial/poly.m,\n\tpolynomial/polyder.m, polynomial/polyderiv.m,\n\tpolynomial/polyfit.m, polynomial/polygcd.m,\n\tpolynomial/polyinteg.m, polynomial/polyout.m,\n\tpolynomial/polyreduce.m, polynomial/polyval.m,\n\tpolynomial/polyvalm.m, polynomial/ppval.m, polynomial/residue.m,\n\tpolynomial/roots.m, polynomial/unmkpp.m, quaternion/quaternion.m,\n\tset/complement.m, set/create_set.m, set/intersect.m,\n\tset/ismember.m, set/setdiff.m, set/setxor.m, set/union.m,\n\tset/unique.m, signal/arch_fit.m, signal/arch_rnd.m,\n\tsignal/arma_rnd.m, signal/autocor.m, signal/autoreg_matrix.m,\n\tsignal/bartlett.m, signal/blackman.m, signal/detrend.m,\n\tsignal/diffpara.m, signal/durbinlevinson.m, signal/fftconv.m,\n\tsignal/fftfilt.m, signal/fftshift.m, signal/filter2.m,\n\tsignal/freqz.m, signal/hamming.m, signal/hanning.m,\n\tsignal/hurst.m, signal/ifftshift.m, signal/sinetone.m,\n\tsignal/sinewave.m, signal/spencer.m, signal/stft.m,\n\tsignal/synthesis.m, signal/unwrap.m, sparse/gplot.m,\n\tsparse/spfun.m, sparse/sprand.m, sparse/sprandn.m,\n\tsparse/sprandsym.m, sparse/spstats.m, specfun/beta.m,\n\tspecfun/betai.m, specfun/betaln.m, specfun/erfinv.m,\n\tspecfun/gammai.m, specfun/log2.m, specfun/pow2.m,\n\tspecial-matrix/hankel.m, special-matrix/hilb.m,\n\tspecial-matrix/invhilb.m, special-matrix/sylvester_matrix.m,\n\tspecial-matrix/toeplitz.m, special-matrix/vander.m,\n\tstatistics/base/center.m, statistics/base/cloglog.m,\n\tstatistics/base/cor.m, statistics/base/corrcoef.m,\n\tstatistics/base/cov.m, statistics/base/cut.m,\n\tstatistics/base/gls.m, statistics/base/iqr.m,\n\tstatistics/base/kendall.m, statistics/base/kurtosis.m,\n\tstatistics/base/logit.m, statistics/base/mahalanobis.m,\n\tstatistics/base/mean.m, statistics/base/meansq.m,\n\tstatistics/base/median.m, statistics/base/moment.m,\n\tstatistics/base/ols.m, statistics/base/ppplot.m,\n\tstatistics/base/probit.m, statistics/base/qqplot.m,\n\tstatistics/base/range.m, statistics/base/ranks.m,\n\tstatistics/base/run_count.m, statistics/base/skewness.m,\n\tstatistics/base/spearman.m, statistics/base/statistics.m,\n\tstatistics/base/std.m, statistics/base/studentize.m,\n\tstatistics/base/table.m, statistics/base/values.m,\n\tstatistics/base/var.m, statistics/distributions/betacdf.m,\n\tstatistics/distributions/betainv.m,\n\tstatistics/distributions/betapdf.m,\n\tstatistics/distributions/betarnd.m,\n\tstatistics/distributions/binocdf.m,\n\tstatistics/distributions/binoinv.m,\n\tstatistics/distributions/binopdf.m,\n\tstatistics/distributions/binornd.m,\n\tstatistics/distributions/cauchy_cdf.m,\n\tstatistics/distributions/cauchy_inv.m,\n\tstatistics/distributions/cauchy_pdf.m,\n\tstatistics/distributions/cauchy_rnd.m,\n\tstatistics/distributions/chi2cdf.m,\n\tstatistics/distributions/chi2inv.m,\n\tstatistics/distributions/chi2pdf.m,\n\tstatistics/distributions/chi2rnd.m,\n\tstatistics/distributions/discrete_cdf.m,\n\tstatistics/distributions/discrete_inv.m,\n\tstatistics/distributions/discrete_pdf.m,\n\tstatistics/distributions/discrete_rnd.m,\n\tstatistics/distributions/empirical_rnd.m,\n\tstatistics/distributions/expcdf.m,\n\tstatistics/distributions/expinv.m,\n\tstatistics/distributions/exppdf.m,\n\tstatistics/distributions/exprnd.m,\n\tstatistics/distributions/fcdf.m, statistics/distributions/finv.m,\n\tstatistics/distributions/fpdf.m, statistics/distributions/frnd.m,\n\tstatistics/distributions/gamcdf.m,\n\tstatistics/distributions/gaminv.m,\n\tstatistics/distributions/gampdf.m,\n\tstatistics/distributions/gamrnd.m,\n\tstatistics/distributions/geocdf.m,\n\tstatistics/distributions/geoinv.m,\n\tstatistics/distributions/geopdf.m,\n\tstatistics/distributions/geornd.m,\n\tstatistics/distributions/hygecdf.m,\n\tstatistics/distributions/hygeinv.m,\n\tstatistics/distributions/hygepdf.m,\n\tstatistics/distributions/hygernd.m,\n\tstatistics/distributions/kolmogorov_smirnov_cdf.m,\n\tstatistics/distributions/laplace_cdf.m,\n\tstatistics/distributions/laplace_inv.m,\n\tstatistics/distributions/laplace_pdf.m,\n\tstatistics/distributions/laplace_rnd.m,\n\tstatistics/distributions/logistic_cdf.m,\n\tstatistics/distributions/logistic_inv.m,\n\tstatistics/distributions/logistic_pdf.m,\n\tstatistics/distributions/logistic_rnd.m,\n\tstatistics/distributions/logncdf.m,\n\tstatistics/distributions/logninv.m,\n\tstatistics/distributions/lognpdf.m,\n\tstatistics/distributions/lognrnd.m,\n\tstatistics/distributions/normcdf.m,\n\tstatistics/distributions/norminv.m,\n\tstatistics/distributions/normpdf.m,\n\tstatistics/distributions/normrnd.m,\n\tstatistics/distributions/pascal_cdf.m,\n\tstatistics/distributions/pascal_inv.m,\n\tstatistics/distributions/pascal_pdf.m,\n\tstatistics/distributions/pascal_rnd.m,\n\tstatistics/distributions/poisscdf.m,\n\tstatistics/distributions/poissinv.m,\n\tstatistics/distributions/poisspdf.m,\n\tstatistics/distributions/poissrnd.m,\n\tstatistics/distributions/stdnormal_cdf.m,\n\tstatistics/distributions/stdnormal_inv.m,\n\tstatistics/distributions/stdnormal_pdf.m,\n\tstatistics/distributions/stdnormal_rnd.m,\n\tstatistics/distributions/tcdf.m, statistics/distributions/tinv.m,\n\tstatistics/distributions/tpdf.m, statistics/distributions/trnd.m,\n\tstatistics/distributions/unifcdf.m,\n\tstatistics/distributions/unifinv.m,\n\tstatistics/distributions/unifpdf.m,\n\tstatistics/distributions/unifrnd.m,\n\tstatistics/distributions/wblcdf.m,\n\tstatistics/distributions/wblinv.m,\n\tstatistics/distributions/wblpdf.m,\n\tstatistics/distributions/wblrnd.m,\n\tstatistics/distributions/wienrnd.m, statistics/tests/anova.m,\n\tstatistics/tests/bartlett_test.m,\n\tstatistics/tests/chisquare_test_homogeneity.m,\n\tstatistics/tests/chisquare_test_independence.m,\n\tstatistics/tests/cor_test.m, statistics/tests/f_test_regression.m,\n\tstatistics/tests/hotelling_test.m,\n\tstatistics/tests/hotelling_test_2.m,\n\tstatistics/tests/kolmogorov_smirnov_test.m,\n\tstatistics/tests/kolmogorov_smirnov_test_2.m,\n\tstatistics/tests/kruskal_wallis_test.m, statistics/tests/manova.m,\n\tstatistics/tests/mcnemar_test.m, statistics/tests/prop_test_2.m,\n\tstatistics/tests/run_test.m, statistics/tests/sign_test.m,\n\tstatistics/tests/t_test.m, statistics/tests/t_test_2.m,\n\tstatistics/tests/t_test_regression.m, statistics/tests/u_test.m,\n\tstatistics/tests/var_test.m, statistics/tests/welch_test.m,\n\tstatistics/tests/wilcoxon_test.m, statistics/tests/z_test.m,\n\tstatistics/tests/z_test_2.m, strings/base2dec.m, strings/blanks.m,\n\tstrings/deblank.m, strings/dec2base.m, strings/dec2bin.m,\n\tstrings/dec2hex.m, strings/findstr.m, strings/hex2dec.m,\n\tstrings/index.m, strings/isletter.m, strings/lower.m,\n\tstrings/rindex.m, strings/split.m, strings/str2mat.m,\n\tstrings/str2num.m, strings/strcat.m, strings/strcmpi.m,\n\tstrings/strfind.m, strings/strjust.m, strings/strmatch.m,\n\tstrings/strncmp.m, strings/strncmpi.m, strings/strrep.m,\n\tstrings/strtrunc.m, strings/strvcat.m, strings/substr.m,\n\tstrings/upper.m, testfun/assert.m, testfun/demo.m,\n\ttestfun/example.m, testfun/fail.m, testfun/speed.m,\n\ttestfun/test.m, time/asctime.m, time/calendar.m, time/ctime.m,\n\ttime/datenum.m, time/datestr.m, time/datevec.m, time/eomday.m,\n\ttime/etime.m, time/is_leap_year.m:\n\tUse print_usage instead of usage.\n\n2006-10-09  David Bateman  <dbateman@free.fr>\n\n\t* time/datevec.m: Add additional compatible default parsing strings.\n\n2006-10-09  Bill Denney  <denney@seas.upenn.edu>\n\n\t* pkg/pkg.m: Remove trailing \"\\n\" from error messages.\n\tRemove compare_versions subfunction.\n\n\t* miscellaneous/compare_versions.m: New function to compare\n\tversion numbers as strings with any boolean operators.\n\n\t* miscellaneous/untar.m: Check more rigorously to see if the tar\n\tfile exists.\n\n2006-10-04  John W. Eaton  <jwe@octave.org>\n\n\t* pkg/pkg.m: Use fullfile to concatenate directory and file names.\n\n2006-10-04  Søren Hauberg  <soren@hauberg.org>\n\n\t* pkg/pkg.m: Update docs.  Handle prefix option.\n\tHandle dependencies for load option.\n\n2006-10-04  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/clearplot.m, deprecated/clg.m: New functions.\n\n\t* plot/clg.m: Delete.\n\t* plot/__init_plot_vars__.m: New function.\n\t* plot/__setup_plot__.m: Use __init_plot_vars__.\n\n2006-10-03  Søren Hauberg  <soren@hauberg.org>\n\n\t* pkg/pkg.m: Avoid calling addpath with no args.\n\n2006-10-03  Bill Denney  <denney@seas.upenn.edu>\n\n \t* audio/loadaudio.m, control/base/nyquist.m,\n \tcontrol/system/__zp2ssg2__.m, linear-algebra/cross.m,\n \tlinear-algebra/krylov.m, statistics/base/center.m,\n \tstatistics/base/median.m, statistics/base/std.m,\n \tstatistics/base/var.m, testfun/test.m: \tUse the new find syntax to\n\tfind first or last element matching a condition.\n\n2006-10-02  Bill Denney  <denney@seas.upenn.edu>\n\n\t* strings/deblank.m, strings/upper.m, strings/lower.m,\n\tgeneral/__isequal__.m: Minimize looping using cellfun.\n\n2006-10-02  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (copy_files): always create installation directory.\n\n2006-10-02  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* miscellaneous/doc.m: Swap file and directory args to info.\n\n2006-10-01  Arno Onken  <whyly@gmx.net>\n\n\t* statistics/distributions/exprnd.m: Fix typo.\n\n2006-09-30  Benjamin Lindner  <lindnerben@gmx.net>\n\n\t* polynomial/ppval.m: Use .' instead of '.\n\t* polynomial/spline.m: Likewise.  New tests.\n\n2006-09-26  David Bateman  <dbateman@free.fr>\n\n\t* __plt3__.m: Using global variables __plot_data__,\n\t__plot_data_offset__ and __plot_command__ to store plots and\n\tcorrectly handle multiplots, and hold state. Only accept a single\n\tdata parameter plus, using, format and with strings. Remove\n\tsetting of gnuplot parameters.\n\t* __make_using_clause__.m: New function extracted from __plt__.m.\n\t* __setup_plot__.m: Convert to a function and pass the plotting\n\tcommand to use.\n\t* __plt__.m: Change call to __setup_plot__ and __make_using_clause__.\n\t* contour.m: Use unwind protect on the parametric state of plot\n\tand __plt3__ instead of calling __gnuplot_splot__ directly.\n\t* mesh.m: ditto.\n\t* plot3.m: Error checking, setting of parametric state and\n\tformation of matrix to plot moved from old __plt3__.\n\n2006-09-22  Michael Creel  <michael.creel@uab.es>\n\n\t* deprecated/chisquare_pdf.m: Typo in documentation.\n\n2006-09-22  Søren Hauberg  <soren@hauberg.org>\n\n\t* signal/filter2.m: Correct texinfo doc.\n\n2006-09-22  David Bateman  <dbateman@free.fr>\n\n\t* miscellaneous/parseparams.m: Correct texinfo doc.\n\n2006-09-15  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (prepare_installation): Don't create package\n\tinstallation directory here.\n\t(copy_files): Create it here instead, to avoid issues with\n\tupgrades. Also install the COPYING file in packinfo.\n\n2006-09-13  John W. Eaton  <jwe@octave.org>\n\n\t* general/blkdiag.m: Adjust to new cellfun rules.\n\n2006-08-30  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (install): Disallow bundles of packages. More verbose\n\terror message for archive name not matching package name.\n\t(installed_packages): Size header of printed results to\n\targuments. Sort the list of installed packages before printing\n\tthem.\n\n2006-09-11  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* signal/freqz.m: Update tests.\n\n2006-09-11  Ken Kouno  <kouno@mk.ecei.tohoku.ac.jp>\n\n\t* signal/freqz.m: Corretly postpad arrays.\n\tDon't call fliplr on a column vector.\n\n2006-09-11  Luis F. Ortiz  <lortiz@interactivesupercomputing.com>\n\n\t* general/shiftdim.m: Use permute instead of reshape.\n\n2006-09-05  Alexander Barth  <abarth93@users.sourceforge.net>\n\n\t* miscellaneous/parseparams.m: New function.\n\n2006-09-05  Rafael Laboissiere  <rafael@debian.org>\n\n\t* miscellaneous/doc.m: Swap order of --file and --directory\n\toptions for info program invocation.\n\n2006-08-30  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (create_pkgadddel): Resolve variable name-clash from\n\tprevious change.\n\n2006-08-26  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (install, uninstall, installed_packages): Allow for\n\tabsence of trailing \"/\" in OCTAVE_HOME.\n\n2006-08-25  Alexander Barth  <abarth@marine.usf.edu>\n\n\t* time/datenum.m: Allow arg to be character string.\n\n2006-08-25  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (install): Verify that package name correponds to the\n\tarchive name. Treat both PKG_ADD and PKG_DEL and remove them if\n\tthey are empty. If package directory is empty, remove it to fail\n\tgracefully for system specific packages.\n\t(extract_pkgadd, create_pkgadd): delete.\n\t(extract_pkg, create_pkg): Generalized versions of deleted functions\n\t(copy_files): Install both bin/ and doc/ directories, adding the\n\tbin/ to the EXEC_PATH when the package is loaded.\n\n2006-08-24  John W. Eaton  <jwe@octave.org>\n\n\t* image/saveimage.m: Use logical indexing instead of\n\tindices computed by calling find on the logical index.\n\n2006-08-24  Søren Hauberg  <soren@hauberg.org>\n\n\t* miscellaneous/bincoeff.m, specfun/factorial.m:\n\tUse logical indexing instead of indices computed by calling find\n\ton the logical index.\n\n\t* linear-algebra/krylov.m: Delete unused local var nzidx.\n\n2006-08-23  Quentin Spencer  <qspencer@ieee.org>\n\n\t* control/system/tf2zp.m: Simplify gain calculation.\n\n2006-08-23  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__plt__.m: Insert using clauses for all plots.\n\n2006-08-23  A S Hodel  <hodelas@auburn.edu>\n\n\t* control/system/sysscale.m: Call tf and zp with correct number of\n\targs.\n\n2006-08-22  David Bateman  <dbateman@free.fr>\n\n\t* pkg/pkg.m (extract_pkgadd, create_pkgadd): New functions to\n\tSearch inst/*.m and src/*.m files in the package for\n\tPKG_ADD directives and append user supplied PKG_ADD.\n\t(pkg): Call create_pkgadd after copying files.\n\n2006-08-21  Søren Hauberg  <soren@hauberg.org>\n\n\t* pkg/pkg.m: Handle multiple packages in a single file.\n\tInsert directory separator between OCTAVE_HOME and rest of package\n\tinstallation directory.\n\n2006-08-21  John W. Eaton  <jwe@octave.org>\n\n\t* general/num2str.m: Early return if arg is empty.\n\tFrom Thomas Treichl <Thomas.Treichl@gmx.net>.\n\n2006-08-21  David Bateman  <dbateman@free.fr>\n\n\t* strings/mat2str.m: Compute NC before using.\n\n2006-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* audio/wavread.m: Fix calculation of sample count.\n\n2006-08-14  Søren Hauberg  <soren@hauberg.org>\n\n\t* image/imshow.m: New Matlab-compatible version.\n\n2006-08-15  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/is_global.m: Delete.\n\n2006-08-14  John W. Eaton  <jwe@octave.org>\n\n\t* pkg/Makefile.in (script_sub_dir): Change from plot to pkg.\n\n2006-08-14  Dmitri A. Sergatskov  <dasergatskov@gmail.com>\n\n\t* sparse/spy.m, control/base/bode.m, control/base/__stepimp__.m,\n\tsignal/freqz_plot.m: Adapt to new automatic_replot definition.\n\n2006-08-14  Søren Hauberg  <soren@hauberg.org>\n\n\t* pkg/pkg.m: Don't pass function name to print_usage.\n\tUse addpath and rmpath instead of manipulating LOADPATH.\n\tHandle changes to system function.\n\t(rm_rf): New subfunction.  Use it to avoid confirmation dialog for\n\trecursive directory removal.\n\n\t* strings/bin2dec.m: Ignore spaces in input for compatibility.\n\n\t* colormap.m: Change global variable to persistent.\n\n\t* rgb2ind.m: Handle single 3-d array as rgb image.\n\n2006-08-14  John W. Eaton  <jwe@octave.org>\n\n\t* strings/str2double.m: Fix missing semicolon.\n\n2006-07-27  Jim Peterson  <jpeterson@annapmicro.com>\n\n\t* plot/plot3.m: Accept one complex or one real and one complex\n\targument and plot real and imaginary components for y and z.\n\n2006-07-27  John W. Eaton  <jwe@octave.org>\n\n\t* testfun/test.m: Call fflush after each block of calls to\n\tfprintf, fputs, or fdisp.\n\n2006-07-26  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/mex.m: New function.\n\n2006-07-22  John W. Eaton  <jwe@octave.org>\n\n\t* special-matrix/hadamard.m: Coerce bool matrix to double.\n\n2006-07-07  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/orderfields.m: New file.\n\n2006-06-30  John W. Eaton  <jwe@octave.org>\n\n\t* time/datevec.m: Make another attempt to account for precision of\n\tdatenum format.\n\n2006-06-29  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/dump_prefs.m: Remove obsolete symbols from the list.\n\tUse feval instead of \"type -q\" to get values now that all the\n\tsymbols are functions.\n\n2006-06-16  John W. Eaton  <jwe@octave.org>\n\n\t* time/datevec.m: Avoid computing log of non-positive values.\n\n2006-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* time/datevec.m: Attempt to account for precision of datenum format.\n\n2006-06-01  Quentin H. Spencer  <qspencer@ieee.org>\n\n\t* audio/wavread.m: Fix file range error and add read support for\n\t24-bit WAV files.\n\n2006-06-01  David Bateman  <dbateman@free.fr>\n\n\t* general/interpft.m, general/quadl.m, general/polyarea.m,\n\tgeneral/interp1.m, general/gradient.m, general/interp2.m,\n\tgeneral/bicubic.m, miscellaneous/inputname.m, plot/__plt3__.m,\n\tplot/ndgrid.m, plot/plot3.m, polynomial/pchip.m, sparse/pcg.m,\n\tsparse/pcr.m, strings/mat2str.m: New files from Octave Forge.\n\n2006-05-31  Bill Denney  <bill@givebillmoney.com>\n\n \t* miscellaneous/fileparts.m, miscellaneous/fullfile.m: Add seealso.\n \t* miscellaneous/texas_lotto.m: Fix warning message.\n\n2006-05-26  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/doc.m: Also handle nargin == 0.\n\n2006-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* plot/mesh.m: Use __gnupot_raw__ except where __gnuplot_set__ is\n\treally needed.\n\n2006-05-22  John W. Eaton  <jwe@octave.org>\n\n\t* general/lookup.m: New file from Octave Forge.\n\n2006-05-22  David Bateman  <dbateman@free.fr>\n\n\t* general/nthroot.m, linear-algebra/rref.m, specfun/isprime.m,\n\tspecfun/primes.m, specfun/factor.m, specfun/nchoosek.m,\n\tspecfun/legendre.m, specfun/perms.m, special-matrix/rosser.m,\n\tspecial-matrix/wilkinson.m, special-matrix/pascal.m,\n\tspecial-matrix/magic.m, special-matrix/hadamard.m,\n\tstrings/strtok.m: New files from Octave Forge.\n\n2006-05-19  David Bateman  <dbateman@free.fr>\n\n\t* polynomial/unmkpp.m, polynomial/mkpp.m, polynomial/spline.m,\n\tpolynomial/ppval.m, set/setxor.m: New files from Octave Forge.\n\n2006-05-17  John W. Eaton  <jwe@octave.org>\n\n\t* set/intersection.m: Delete\n\t* deprecated/intersection.m: New file.\n\n2006-05-17  David Bateman  <dbateman@free.fr>\n\n\t* general/cplxpair.m, general/trapz.m, general/cumtrapz.m,\n\tgeneral/isdir.m, miscellaneous/dos.m, miscellaneous/getfield.m,\n\tmiscellaneous/setfield.m, plot/fplot.m, set/intersect.m,\n\tsignal/ifftshift.m, signal/filter2.m, specfun/betaln.m,\n\tspecfun/factorial.m, strings/strvcat.m: New files from Octave\n\tForge.\n\n2006-05-11  John W. Eaton  <jwe@octave.org>\n\n\t* path/path.m: Delete (now a built-in function).\n\n\t* pkg/Makefile.in: New file.\n\t* configure.in (AC_CONFIG_FILES): Add pkg/Makefile to the list.\n\t* Makefile.in (SUBDIRS): Add pkg to the list.\n\n2006-05-10  John W. Eaton  <jwe@octave.org>\n\n\t* tar.m, untar.m, unzip.m: Adapt to Octave coding style.\n\t* tar.m, untar.m: Only tar; don't compress or uncompress.\n\n2006-05-10  Søren Hauberg  <hauberg@gmail.com>\n\n\t* tar.m, untar.m, unzip.m: New files.\n\n2006-05-10  John W. Eaton  <jwe@octave.org>\n\n\t* path/addpath.m, path/rmpath.m: Improve compatibility.\n\t* path/setpath.m: Delete.\n\n\t* pkg/pkg.m: New file.\n\n2006-05-09  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* plot/plot.m: Doc string fix.\n\n2006-05-09  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* testfun/speeed.m: Use new interface to unique and assert.\n\tImprove documentation.  Approximate time complexity from log-log\n\tplot.  Return time complexity and raw times if requested.  The\n\tmean ratio is no longer returned.  Provide complete control over\n\twhich n are computed.\n\n2006-05-09  John W. Eaton  <jwe@octave.org>\n\n\t* path/path.m: Move here from miscellaneous.\n\tAdapt to new LOADPATH definition.\n\n2006-05-03  David Bateman  <dbateman@free.fr>\n\n\t* path/rmpath.m, path/addpath.m, miscellaneous/path.m: Replace all\n\texplicit uses of a path seperation character with pathsep().\n\n2006-05-03  Bob Weigel  <rweigel@gmu.edu>\n\n\t* set/setdiff.m: New arg, byrows.  New tests.\n\n2006-04-29  John W. Eaton  <jwe@octave.org>\n\n\t* startup/main-rcfile: Disable some warnings.\n\n2006-04-14  Bill Denney  <denney@seas.upenn.edu>\n\n \t* strings/strcmpi.m: Return false instead of error if args are not\n\tchar or cellstr.\n\n2006-04-10  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/dir.m: Ensure that returned structure array is\n\tNx1, not 1xN.\n\n2006-04-06  Olli Saarela  <olli.saarela@kcl.fi>\n\n\t* plot/hist.m: Ignore NaN in inputs.\n\n2006-04-06  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* miscellaneous/mkoctfile.m: Doc string fix.\n\n2006-04-05  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__plt2__.m: Return data = [] and fmtstr = \"\" if x1 and x2\n\tare both empty.\n\t* plot/__plt__.m: Ignore empty data and format strings returned\n\tfrom __plt1__ or __plt2__.\n\n2006-04-04  Bob Weigel  <rweigel@gmu.edu>\n\n\t* set/unique.m: Properly handle single column input when\n\t\"rows\" is specified.\n\n2006-04-04  John W. Eaton  <jwe@octave.org>\n\n\t* path/setpath.m: New file.\n\t* path/savepath.m: Use setpath to set path instead of assigning\n\tdirectly to LOADPATH.\n\n\t* path/Makefile.in, path/addpath.m, path/rmpath.m, path/savepath.m:\n\tNew files, adapted from Octave Forge by Keith Goodman\n\t<kwgoodman@gmail.com>.\n\t* path: New directory.\n\t* Makefile.in (SUBDIRS): Add it to the list.\n\t* configure.in (AC_CONFIG_FILES): Include path/Makefile here.\n\n2006-04-02  David Bateman  <dbateman@free.fr>\n\n\t* general/tril.m, general.triu.m:\n\tUse resize (resize (x, 0), nr, nc) rather than zeros (nr, nc)\n\tto allow user types to work correctly.\n\t* special-matrix/hankel.m, special-matrix/toeplitz.m: Ditto.\n\n2006-04-03  David Bateman  <dbateman@free.fr>\n\n\t* plot/grid.m: Cache the state of the grid to allow toggling.\n\tAccept keyword \"minor\" for minor grid.\n\n2006-03-28  John W. Eaton  <jwe@octave.org>\n\n\t* general/isscalar.m: Only require that all dimensions are 1 for\n\tcompatiblity.\n\n2006-03-28  Bill Denney  <bill@givebillmoney.com>\n\n\t* general/isvector.m: Allow non-numeric objects to be vectors for\n\tcompatibility.\n\n2006-03-28  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* plot/__errplot__.m: Doc string fix.\n\n\t* miscellaneous/doc.m: Mark as command.\n\n\t* general/isequal.m, general/__isequal__.m, general/cell2mat.m,\n\tgeneral/isequalwithequalnans.m, general/blkdiag.m,\n\tstrings/strfind.m, miscellaneous/doc.m: Update FSF address.\n\n2006-03-27  Don Bindner  <dbindner@truman.edu>\n\n\t* plot/meshgrid.m: If nargout == 3 and vectors are supplied,\n\treturn 3d matrices.\n\n2006-03-27  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* time/toc.m: Don't print \"Elapsed time...\" if tic has not been set.\n\n2006-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* plot/print.m: Don't replot after popping terminal setting.\n\n2006-03-20  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/mkoctfile.m: Use version-specific name of\n\tmkoctfile.  Use fullfile to construct file name.\n\n2006-03-20  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* miscellaneous/mkoctfile.m: Make it possible to call mkoctfile\n\tshell script from Octave prompt.\n\n2006-03-17  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/weibcdf.m, deprecated/weibinv.m,\n\tdeprecated/weibpdf.m, deprecated/weibrnd.m: New functions.\n\n\t* deprecated/weibull_cdf.m, deprecated/weibull_inv.m,\n\tdeprecated/weibull_pdf.m, deprecated/weibull_rnd.m:\n\tCall new wbl functions to do the real work.\n\tSwap args and provide default values as necessary to preserve\n\tcompatibility with old version of Octave.\n\n\t* statistics/distributions/wblcdf.m: Rename from weibcdf.m.\n\tstatistics/distributions/wblinv.m: Rename from weibinv.m.\n\tstatistics/distributions/wblpdf.m: Rename from weibpdf.m.\n\tstatistics/distributions/wblrnd.m: Rename from weibrnd.m.\n\tSwap scale and shape args for compatibility.\n\n\t* deprecated/lognormal_cdf.m, deprecated/lognormal_inv.m,\n\tdeprecated/lognormal_pdf.m, deprecated/lognormal_rnd.m:\n\tPreserve compatibility with old versions of Octave given new\n\tdefinitions of logncdf, logninv, lognpdf, and lognrnd.\n\n\t* statistics/distributions/logncdf.m,\n\tstatistics/distributions/logninv.m,\n\tstatistics/distributions/lognpdf.m,\n\tstatistics/distributions/lognrnd.m: Compatibility fixes.\n\tFrom Ben Barrowes  <barrowes@alum.mit.edu>\n\n\t* deprecated/hypergeometric_rnd.m: Update interface to match\n\tcurrent 2.1.x version.\n\n\t* deprecated/t_rnd.m: Call trnd, not t_rnd.\n\n\t* miscellaneous/dir.m: Use readdir instead of glob.\n\tSpecial case for \".\" to avoid globbing.  Use list_in_columns.\n\tEliminate unused variables len and finfo.\n\n2006-03-16  Bill Denney  <bill@givebillmoney.com>\n\n\t* miscellaneous/dir.m: Improve compatibility.\n\n2006-03-15  William Poetra Yoga Hadisoeseno  <williampoetra@gmail.com>\n\n\t* time/calendar.m, time/datestr.m, time/datevec.m, time/eomday.m,\n\ttime/now.m, time/weekday.m: New functions from Octave Forge.\n\n2006-03-16  John W. Eaton  <jwe@octave.org>\n\n\t* control/base/bode_bounds.m: Check for iip and iiz empty instead\n\tof looking at sum of max dimensions.\n\n2006-03-16  David Bateman  <dbateman@free.fr>\n\n\t* testfun/test.m: Clear last warning before warning test to avoid\n\tissues with previously set warnings.\n\t* build_sparse_test.sh: Tests for multiple RHS for rectanguar\n\tsparse matrices. Force matrix type from spqr solution to be\n\tsingular to force QR solvers to be used for assert.\n\n2006-03-16  William Poetra Yoga Hadisoeseno  <williampoetra@gmail.com>\n\n\t* strings/strfind.m: New file.\n\n2006-03-16  John W. Eaton  <jwe@octave.org>\n\n\t* general/rows.m, general/columns.m: Delete.\n\n2006-03-15  William Poetra Yoga Hadisoeseno  <williampoetra@gmail.com>\n\n\t* strings/strcmpi.m: Simplify.\n\t* strings/strncmpi.m: Import from octave-forge, simplify.\n\t* strings/strtrunc.m: New file.\n\n\t* strings/lower.m, strings/upper.m: Handle cellstr arguments.\n\n2006-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/doc.m: New file.\n\tFrom Søren Hauberg <soren@hauberg.org>.\n\n2006-03-15  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* miscellaneous/mkoctfile.m: New file.\n\n2006-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/residue.m: Use & instead of && to generate arg for find.\n\n2006-03-14  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* strings/bin2dec.m: Doc fix.\n\n2006-03-10  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* time/etime.m: Use datenum to support times spanning year boundaries.\n\t* time/datenum.m: New function to compute day number from time.\n\n2006-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/unix.m, plot/print.m:\n\tSwap order of outputs from system.\n\n2006-03-06  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* audio/lin2mu.m, audio/loadaudio.m, audio/mu2lin.m,\n\taudio/playaudio.m, audio/record.m, audio/saveaudio.m,\n\taudio/wavread.m, audio/wavwrite.m, control/base/DEMOcontrol.m,\n\tcontrol/base/__stepimp__.m, control/base/are.m,\n\tcontrol/base/controldemo.m, control/base/damp.m,\n\tcontrol/base/dare.m, control/base/impulse.m, control/base/lqg.m,\n\tcontrol/base/step.m, control/system/abcddim.m,\n\tcontrol/system/is_abcd.m, control/system/is_controllable.m,\n\tcontrol/system/is_detectable.m, control/system/is_observable.m,\n\tcontrol/system/is_stabilizable.m, control/system/is_stable.m,\n\tcontrol/system/jet707.m, control/system/sys2fir.m,\n\tcontrol/system/sysdimensions.m, control/system/sysupdate.m,\n\tcontrol/system/tfout.m, control/system/ugain.m,\n\tcontrol/system/zpout.m, elfun/lcm.m, finance/irr.m,\n\tfinance/nper.m, finance/npv.m, finance/pmt.m, finance/pv.m,\n\tfinance/rate.m, general/__isequal__.m, general/bitcmp.m,\n\tgeneral/bitget.m, general/bitset.m, general/blkdiag.m,\n\tgeneral/cart2pol.m, general/cart2sph.m, general/cell2mat.m,\n\tgeneral/circshift.m, general/columns.m, general/flipdim.m,\n\tgeneral/fliplr.m, general/flipud.m, general/ind2sub.m,\n\tgeneral/int2str.m, general/isdefinite.m, general/isequal.m,\n\tgeneral/isequalwithequalnans.m, general/isscalar.m,\n\tgeneral/issquare.m, general/issymmetric.m, general/isvector.m,\n\tgeneral/logspace.m, general/mod.m, general/nextpow2.m,\n\tgeneral/num2str.m, general/perror.m, general/pol2cart.m,\n\tgeneral/rem.m, general/rot90.m, general/rotdim.m, general/rows.m,\n\tgeneral/shiftdim.m, general/sph2cart.m, general/sub2ind.m,\n\tgeneral/tril.m, image/hsv2rgb.m, image/image.m, image/imagesc.m,\n\timage/imshow.m, image/ind2gray.m, image/ind2rgb.m,\n\timage/loadimage.m, image/rgb2hsv.m, image/rgb2ind.m,\n\timage/saveimage.m, io/beep.m, linear-algebra/cond.m,\n\tlinear-algebra/norm.m, miscellaneous/comma.m, miscellaneous/dir.m,\n\tmiscellaneous/license.m, miscellaneous/menu.m,\n\tmiscellaneous/semicolon.m, miscellaneous/texas_lotto.m,\n\tmiscellaneous/unix.m, miscellaneous/ver.m, optimization/sqp.m,\n\tplot/__errcomm__.m, plot/__errplot__.m, plot/__pltopt1__.m,\n\tplot/__pltopt__.m, plot/bar.m, plot/contour.m, plot/errorbar.m,\n\tplot/grid.m, plot/hist.m, plot/loglog.m, plot/loglogerr.m,\n\tplot/mesh.m, plot/meshgrid.m, plot/plot.m, plot/polar.m,\n\tplot/semilogx.m, plot/semilogxerr.m, plot/semilogy.m,\n\tplot/semilogyerr.m, plot/shg.m, plot/stairs.m, plot/title.m,\n\tplot/xlabel.m, polynomial/compan.m, polynomial/conv.m,\n\tpolynomial/deconv.m, polynomial/polyderiv.m, polynomial/polygcd.m,\n\tpolynomial/polyinteg.m, polynomial/polyout.m,\n\tpolynomial/polyreduce.m, polynomial/polyval.m,\n\tpolynomial/polyvalm.m, polynomial/residue.m, set/complement.m,\n\tset/create_set.m, set/intersection.m, set/ismember.m,\n\tset/setdiff.m, set/union.m, set/unique.m, sparse/etreeplot.m,\n\tsparse/gplot.m, sparse/spalloc.m, sparse/sphcat.m,\n\tsparse/sprand.m, sparse/sprandn.m, sparse/sprandsym.m,\n\tsparse/spvcat.m, sparse/treeplot.m, specfun/erfinv.m,\n\tspecfun/log2.m, specfun/pow2.m, special-matrix/hankel.m,\n\tspecial-matrix/hilb.m, special-matrix/invhilb.m,\n\tspecial-matrix/sylvester_matrix.m, special-matrix/toeplitz.m,\n\tspecial-matrix/vander.m, statistics/base/median.m,\n\tstatistics/base/std.m, statistics/distributions/gamcdf.m,\n\tstatistics/distributions/gaminv.m,\n\tstatistics/distributions/gampdf.m,\n\tstatistics/distributions/gamrnd.m, strings/base2dec.m,\n\tstrings/bin2dec.m, strings/dec2base.m, strings/dec2bin.m,\n\tstrings/dec2hex.m, strings/hex2dec.m, strings/isletter.m,\n\tstrings/lower.m, strings/upper.m, testfun/assert.m,\n\ttestfun/demo.m, testfun/example.m, testfun/test.m, time/etime.m:\n\tMove @seealso inside @defXXX macro.  Remove \"and\" from @seealso.\n\n2006-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* time/tic.m: Move here from miscellaneous/tic.m.\n\t* time/toc.m: Move here from miscellaneous/toc.m.\n\n2006-02-26  Keith Goodman  <kwgoodman@gmail.com>\n\n \t* miscellaneous/toc.m: Display \"Elapsed time is X seconds\" if user\n\tdoes not assign output of toc to a variable.\n\n2006-02-16  Bill Denney  <denney@seas.upenn.edu>\n\n \t* axis.m: Catch limits that are the same and return an error.\n\n2006-02-15  Dmitri A. Sergatskov  <dasergatskov@gmail.com>\n\n\t* plot/print.m: Accept emf device option to support Enhanced\n\tMetafile format.\n\n2006-02-15  A S Hodel  <hodelas@auburn.edu>\n\n\t* control/base/lqe.m: Doc fix.\n\n2006-02-15  Keith Goodman  <kwgoodman@gmail.com>\n\n \t* statistics/distributions/gamcdf.m: Doc fix.\n \t* statistics/distributions/gaminv.m: Doc fix.\n \t* statistics/distributions/gampdf.m: Doc fix.\n \t* statistics/distributions/gamrnd.m: Doc fix.\n\n2006-02-09  David Bateman  <dbateman@free.fr>\n\n\t* general/triu.m: Minimum change to allow sparse matrix. More needed\n\tfor arbitrary user type.\n\t* general/tril.m: ditto.\n\t* sparse/sprand.m: Doc fix.\n\t* sparse/sprandn.m: Ditto.\n\t* sparse/sprandsym.m: New function.\n\t* audio/setaudio.m, general/cart2pol.m, general/cart2sph.m,\n\tgeneral/pol2cart.m, general/sph2cart.m, signal/freqz_plot.m:\n\tUpdate for syntax error for latest texinfo.tex file.\n\n2006-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* plot/grid.m: Append \";\\n\" to \"set grid\" command.\n\n2006-02-02  A S Hodel  <hodelas@auburn.edu>\n\n\t* control/base/rlocus.m: Don't atttempt to plot rlzer if it is empty.\n\n2006-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* audio/Makefile.in, control/base/Makefile.in,\n\tcontrol/hinf/Makefile.in, control/obsolete/Makefile.in,\n\tcontrol/system/Makefile.in, control/util/Makefile.in,\n\tdeprecated/Makefile.in, elfun/Makefile.in, finance/Makefile.in,\n\tgeneral/Makefile.in, image/Makefile.in, io/Makefile.in,\n\tlinear-algebra/Makefile.in, miscellaneous/Makefile.in,\n\toptimization/Makefile.in, plot/Makefile.in,\n\tpolynomial/Makefile.in, quaternion/Makefile.in, set/Makefile.in,\n\tsignal/Makefile.in, sparse/Makefile.in, specfun/Makefile.in,\n\tspecial-matrix/Makefile.in, startup/Makefile.in,\n\tstatistics/base/Makefile.in, statistics/distributions/Makefile.in,\n\tstatistics/models/Makefile.in, statistics/tests/Makefile.in,\n\tstrings/Makefile.in, time/Makefile.in, testfun/Makefile.in:\n\t(all): Depend on PKG_ADD.\n\t(PKG_ADD): New target.\n\n2006-01-13  Bill Denney  <bill@givebillmoney.com>\n\n \t* miscellaneous/dir.m: Add @seealso{} to docstring.\n\n2006-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* time/etime.m: Move here from miscellaneous/etime.m.\n\t* time/is_leap_year.m: Move here from miscellaneous/is_leap_year.m.\n\n2006-01-13  Bill Denney  <bill@givebillmoney.com>\n\n\t* miscellaneous/dir.m: Use filesep instead of \"/\" where needed.\n\t* miscellaneous/fullfile.m: Likewise.\n\n2006-01-12  David Bateman  <dbateman@free.fr>\n\n\t* general/blkdiag.m: Compatible behavior for empty matrices\n\t* statistics/base/unidrnd.m: Documentation buglet.\n\n2005-12-14  David Bateman  <dbateman@free.fr>\n\n\t* testfun/assert.m, testfun/fail.m, testfun/test.m, testfun/demo.m,\n\ttestfun/speed.m, testfun/example.m, Makefile.in: New files.\n\n\t* Makefile.in (SUBDIRS): Include testfun.\n\t* configure.in (AC_CONFIG_FILES): Include testfun/Makefile.\n\n\t* miscellaneous/dir.m: Transpose sub-assignment for cleanness.\n\n\t* general/__isequal__.m: Remove reference to getfield.\n\n\t* plot/hist.m: Update test code for row/column discrepencies.\n\t* signal/freqz.m: Alter output row/column for matlab compatibility.\n\tUpdate the test code for this.\n\t* sparse/spstats.m: Fix small bug in the dimension of output.\n\n2005-12-13  William Poetra Yoga Hadisoeseno  <williampoetra@gmail.com>\n\n\t* cell/cell2mat.m: New file, from octave-forge.\n\n2005-12-13  Ivana Varekova  <varekova@redhat.com>\n\n\t* sparse/treeplot.m, sparse/etreeplot.m, sparse/gplot.m:\n\tNew graph theory functions.\n\n2005-12-13  John W. Eaton  <jwe@octave.org>\n\n\t* general/blkdiag.m: Use \"isempty\" instead of @isempty.\n\n\t* control/system/ss.m: Doc fix.\n\tFrom Jorge Barros de Abreu <ficmatin01@solar.com.br>.\n\n2005-12-12  Michael Zeising  <michael@michaels-website.de>\n\n\t* audio/wavread.m, audio/wavwrite.m:\n\tCorrect scaling for 8-bit linear pcm samples.\n\tImprove scaling for all other linear pcm resolutions.\n\n2005-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/base/moment.m: Don't save and restore warn_str_to_num.\n\n\t* sparse/spdiags.m: Don't save and restore warn_fortran_indexing.\n\t* strings/strjust.m: Likewise.\n\n\t* general/shift.m: Don't save and restore warn_empty_list_elements.\n\t* signal/arma_rnd.m: Likewise.\n\t* strings/strcat.m: Likewise.\n\t* control/base/__freqresp__.m: Likewise.\n\t* control/base/place.m: Likewise.\n\t* control/base/pzmap.m: Likewise.\n\t* control/base/pzmap.m: Likewise.\n\t* control/system/sysappend.m: Likewise.\n\t* control/system/syscont.m: Likewise.\n\t* control/system/sysdisc.m: Likewise.\n\t* control/system/sysgroup.m: Likewise.\n\t* control/system/tfout.m: Likewise.\n\t* control/system/zpout.m: Likewise.\n\t* control/util/__outlist__.m: Likewise.\n\n2005-12-06  John W. Eaton  <jwe@octave.org>\n\n\t* audio/wavread.m, audio/wavwrite.m: Adapt to Octave coding style.\n\tAvoid for loop in interleave/deinterleave steps.\n\n2005-12-06  Michael Zeising  <michael@michaels-website.de>\n\n\t* audio/wavread.m, audio/wavwrite.m: New files.\n\n2005-12-06  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/dir.m: Return Nx1 instead of 1xN struct array.\n\n2005-12-05  John W. Eaton  <jwe@octave.org>\n\n\t* plot/axis.m: Add \"## PKG_ADD: mark_as_command axis\" line.\n\n2005-12-02  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/fileattrib.m: New function.\n\n2005-12-01  John W. Eaton  <jwe@octave.org>\n\n\t* general/columns.m: Use size (x, 2) instead of [nr, nc] = size (x).\n\t* general/rows.m: Use size (x, 1) instead of [nr, nc] = size (x).\n\tFrom William Poetra Yoga Hadisoeseno <williampoetra@yahoo.com>.\n\n2005-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* linear-algebra/krylov.m: Format doc string.\n\tFrom Jorge Barros de Abreu <ficmatin01@solar.com.br>.\n\n2005-11-23  William Poetra Yoga Hadisoeseno  <williampoetra@yahoo.com>\n\n\t* general/blkdiag.m: Import from octave-forge.\n\tIgnore empty matrices in the input.  Add tests.\n\n\t* general/isequal.m, general/isequalwithequalnans.m:\n\tNew wrapper scripts for general/__isequal__.m.\n\t* general/__isequal__.m: Rename from general/isequal.m.\n\tNew arg, nans_compare_equal.\n\n2005-11-29  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/ver.m: Use new uname built-in function instead of\n\tcalling system.  Only append octave_forge_string if\n\tOCTAVE_FORGE_VERSION exists.  Use puts instead of disp.\n\tCall license instead of hard-coding license info here.\n\n\t* miscellaneous/license.m: Use persistent instead of global for\n\t__octave_licenses__.  Use puts instead of disp.\n\tUse getuid and getpwuid instead of calling unix (\"id -un\").\n\tIf nargout = 1, return license info instead of printing usage message.\n\n2005-11-29  William Poetra Yoga Hadisoeseno  <williampoetra@gmail.com>\n\n\t* miscellaneous/ver.m: New file.\n\t* miscellaneous/license.m: New file.\n\n2005-11-22  John W. Eaton  <jwe@octave.org>\n\n\t* plot/axis.m: Use %.16g instead of just %g to format ranges for\n\tgnuplot set command.\n\n2005-11-15  John W. Eaton  <jwe@octave.org>\n\n\t* general/shiftdim.m: Doc fix.\n\n2005-11-07  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* set/unique.m: Doc string fix.\n\n2005-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (distclean, maintainer-clean):\n\tAlso remove autom4te.cache directory.\n\tFrom Quentin Spencer  <qspencer@ieee.org>.\n\n2005-10-28  John W. Eaton  <jwe@octave.org>\n\n\t* general/shiftdim.m: Compatibility fix for row vectors.\n\tCorrect check for non-scalar non-integer shift.  For positive\n\tN, shift is remainder of N and number of dims.  Always return NS.\n\tSimplify.\n\n2005-10-18  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* general/randperm.m: Improve compatibility by allowing input\n\tvalue of zero.\n\n2005-10-13  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__plt__.m, plot/__errplot__.m, plot/replot.m:\n\tIf in multiplot mode, clear plot before issuing new plot command.\n\n\t* plot/__setup_plot__.m: New function.\n\t* plot/__plt__.m, plot__errplot__.m: Use it.\n\tHandle multiplot data and offsets here.\n\n\t* plot/__plot_globals__.m: Also keep track of multiplot options.\n\tMove initialization to __setup_plot__.m.\n\n\t* plot/subplot.m: Multiplot globals now in __plot_globals__.m.\n\tDon't reset gnuplot_command_replot.\n\n\t* plot/replot.m: Handle multiplot data and offsets here.\n\t* plot__axis_label__.m, plot/axis.m, plot/grid.m,\n\tplot/plot_border.m, plot/plot.m, plot/plot_title.m,\n\tplot/top_title.m: Call replot, not __gnuplot_replot__.\n\n2005-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* plot/figure.m: Handle __current_figure__, not gnuplot details.\n\n2005-10-04  Rafael Laboissiere  <rafael@debian.org>\n\n\t* binoinv.m, chi2pdf.m, frnd.m, poissinv.m, tinv.m, trnd.m,\n\tweibrnd.m: Removed calls and references to deprecated _pdf and\n\t_inv functions.\n\t* chi2pdf.m: Fixed typos in the documentation.\n\n2005-09-28  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/single.m: New function.\n\n\t* statistics/base/unidrnd.m: New function.\n\n2005-09-27  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/dir.m: Filename never includes directory part.\n\n2005-09-22  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/residue.m: Use logical indexing instead of find..\n\n2005-09-22  Julius Smith  <jos@ccrma.stanford.edu>\n\n\t* polynomial/residue.m: Avoid division by zero for pure imaginary\n\tand zero poles.\n\n2005-09-22  Bill Denney  <denney@seas.upenn.edu>\n\n\t* strings/deblank.m: Handle cell arrays.\n\t* strings/split.m: New argument, N, to limit number of splits.\n\n2005-09-22  Miroslaw Kwasniak  <mirek@zind.ikem.pwr.wroc.pl>\n\n\t* plot/__pltopt1__.m: Handle plot colors \"w\" and \"k\" separately.\n\n2005-09-20  \"Orestes Mas\"  <orestes@tsc.upc.edu>\n\n\t* control/base/rlocus.m: Doc fix.\n\n2005-09-20  John W. Eaton  <jwe@octave.org>\n\n\t* general/isvector.m: Improve compatibility.\n\n\t* general/postpad.m: Allow first argument to be a scalar.\n\tAllow padding to extend dimensionality.\n\t* general/prepad.m: Likewise.\n\n2005-09-14  Daniel  <durbano@shbano.com>\n\n\t* statistics/tests/bartlett_test.m, linear-algebra/cross.m,\n\tstatistics/distributions/discrete_cdf.m, general/fliplr.m,\n\t/control/base/dgram.m: Doc string fixes.\n\tFrom Jorge Barros de Abreu <ficmatin01@solar.com.br>.\n\n2005-09-12  Stefan van der Walt  <stefan@sun.ac.za>\n\n\t* saveimage.m: Do not ignore most significant bit when writing\n\tblack and white images to file.\n\n2005-09-07  Bill Denney  <denney@seas.upenn.edu>\n\n\t* audio/playaudio.m, control/base/__bodquist__.m,\n\tcontrol/base/lqg.m, control/obsolete/dezero.m,\n\tcontrol/system/__syschnamesl__.m, control/system/__sysconcat__.m,\n\tcontrol/system/c2d.m, control/system/cellidx.m,\n\tcontrol/system/d2c.m, control/system/dmr2d.m,\n\tcontrol/system/is_signal_list.m, control/system/listidx.m,\n\tcontrol/system/ss.m, control/system/sysappend.m,\n\tcontrol/system/sysconnect.m, control/system/sysdup.m,\n\tcontrol/system/sysgetsignals.m, control/system/sysidx.m,\n\tcontrol/system/sysprune.m, control/system/syssetsignals.m,\n\tcontrol/system/tfout.m, control/system/zpout.m,\n\tcontrol/util/prompt.m, control/util/sortcom.m,\n\tcontrol/util/strappend.m, finance/fv.m, finance/nper.m,\n\tfinance/pmt.m, finance/pv.m, finance/rate.m, general/diff.m,\n\tgeneral/num2str.m, general/repmat.m, general/sortrows.m,\n\tgeneral/strerror.m, image/colormap.m, image/imshow.m,\n\timage/loadimage.m, image/saveimage.m, linear-algebra/norm.m,\n\tmiscellaneous/fileparts.m, miscellaneous/popen2.m,\n\tplot/__axis_label__.m, plot/__errcomm__.m, plot/__plt1__.m,\n\tplot/__plt2__.m, plot/__plt__.m, plot/__pltopt1__.m,\n\tplot/__pltopt__.m, plot/axis.m, plot/bottom_title.m, plot/close.m,\n\tplot/grid.m, plot/hist.m, plot/plot_border.m, plot/polar.m,\n\tplot/print.m, plot/title.m, plot/top_title.m,\n\tpolynomial/polyout.m, set/unique.m, signal/freqz.m, signal/stft.m,\n\tstatistics/base/mean.m, statistics/base/moment.m,\n\tstatistics/tests/cor_test.m,\n\tstatistics/tests/kolmogorov_smirnov_test.m,\n\tstatistics/tests/kolmogorov_smirnov_test_2.m,\n\tstatistics/tests/prop_test_2.m, statistics/tests/sign_test.m,\n\tstatistics/tests/t_test.m, statistics/tests/t_test_2.m,\n\tstatistics/tests/t_test_regression.m, statistics/tests/u_test.m,\n\tstatistics/tests/var_test.m, statistics/tests/welch_test.m,\n\tstatistics/tests/wilcoxon_test.m, statistics/tests/z_test.m,\n\tstatistics/tests/z_test_2.m, strings/base2dec.m, strings/blanks.m,\n\tstrings/deblank.m, strings/dec2base.m, strings/index.m,\n\tstrings/rindex.m, strings/split.m, strings/str2mat.m,\n\tstrings/str2num.m, strings/strcat.m, strings/strcmpi.m,\n\tstrings/strncmp.m, strings/strrep.m, strings/substr.m:\n\tAvoid deprecated functions.  Use ischar instead of isstr.  Use\n\tisvector instead of is_vector.  Use isstruct instead of\n\tis_struct.  Use char instead of setstr.\n\n2005-08-31  Daniel  <durbano@shbano.com>\n\n\t* special-matrix/invhilb.m, statistics/base/iqr.m,\n\tcontrol/system/is_controllable.m, set/ismember.m: Doc fixes.\n\tFrom Jorge Barros de Abreu <ficmatin01@solar.com.br>.\n\n2005-08-29  Bill Denney  <denney@seas.upenn.edu>\n\n\t* image/saveimage.m: Open output file in binary mode.\n\n\t* miscellaneous/bug_report.m: Open prefs file in text mode.\n\n2005-08-16  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/computer.m: Handle optional maxsize and endian\n\toutputs.\n\n2005-08-15  John W. Eaton  <jwe@octave.org>\n\n\t* strings/strcat.m: Allow single argument.\n\n2005-07-18  John W. Eaton  <jwe@octave.org>\n\n\t* strings/strcmp.m: Delete.\n\n2005-07-13  John W. Eaton  <jwe@octave.org>\n\n\t* deprecated/hypergeometric_rnd.m: Preserve compatibility with old\n\tversions of Octave.\n\n2005-07-13  Ben Barrowes  <barrowes@alum.mit.edu>\n\n\t* statistics/distributions/betacdf.m: Rename from beta_cdf.m.\n\t* statistics/distributions/betainv.m: Rename from beta_inv.m.\n\t* statistics/distributions/betapdf.m: Rename from beta_pdf.m.\n\t* statistics/distributions/betarnd.m: Rename from beta_rnd.m.\n\t* statistics/distributions/binocdf.m: Rename from binomial_cdf.m.\n\t* statistics/distributions/binoinv.m: Rename from binomial_inv.m.\n\t* statistics/distributions/binopdf.m: Rename from binomial_pdf.m.\n\t* statistics/distributions/binornd.m: Rename from binomial_rnd.m.\n\t* statistics/distributions/chi2cdf.m: Rename from chisquare_cdf.m.\n\t* statistics/distributions/chi2inv.m: Rename from chisquare_inv.m.\n\t* statistics/distributions/chi2pdf.m: Rename from chisquare_pdf.m.\n\t* statistics/distributions/chi2rnd.m: Rename from chisquare_rnd.m.\n\t* statistics/distributions/expcdf.m: Rename from exponential_cdf.m.\n\t* statistics/distributions/expinv.m: Rename from exponential_inv.m.\n\t* statistics/distributions/exppdf.m: Rename from exponential_pdf.m.\n\t* statistics/distributions/exprnd.m: Rename from exponential_rnd.m.\n\t* statistics/distributions/fcdf.m: Rename from f_cdf.m.\n\t* statistics/distributions/finv.m: Rename from f_inv.m.\n\t* statistics/distributions/fpdf.m: Rename from f_pdf.m.\n\t* statistics/distributions/frnd.m: Rename from f_rnd.m.\n\t* statistics/distributions/gamcdf.m: Rename from gamma_cdf.m.\n\t* statistics/distributions/gaminv.m: Rename from gamma_inv.m.\n\t* statistics/distributions/gampdf.m: Rename from gamma_pdf.m.\n\t* statistics/distributions/gamrnd.m: Rename from gamma_rnd.m.\n\t* statistics/distributions/geocdf.m: Rename from geometric_cdf.m.\n\t* statistics/distributions/geoinv.m: Rename from geometric_inv.m.\n\t* statistics/distributions/geopdf.m: Rename from geometric_pdf.m.\n\t* statistics/distributions/geornd.m: Rename from geometric_rnd.m.\n\t* statistics/distributions/hygecdf.m: Rename from hypergeometric_cdf.m.\n\t* statistics/distributions/hygeinv.m: Rename from hypergeometric_inv.m.\n\t* statistics/distributions/hygepdf.m: Rename from hypergeometric_pdf.m.\n\t* statistics/distributions/hygernd.m: Rename from hypergeometric_rnd.m.\n\t* statistics/distributions/logncdf.m: Rename from lognormal_cdf.m.\n\t* statistics/distributions/logninv.m: Rename from lognormal_inv.m.\n\t* statistics/distributions/lognpdf.m: Rename from lognormal_pdf.m.\n\t* statistics/distributions/lognrnd.m: Rename from lognormal_rnd.m.\n\t* statistics/distributions/normcdf.m: Rename from normal_cdf.m.\n\t* statistics/distributions/norminv.m: Rename from normal_inv.m.\n\t* statistics/distributions/normpdf.m: Rename from normal_pdf.m.\n\t* statistics/distributions/normrnd.m: Rename from normal_rnd.m.\n\t* statistics/distributions/poisscdf.m: Rename from poisson_cdf.m.\n\t* statistics/distributions/poissinv.m: Rename from poisson_inv.m.\n\t* statistics/distributions/poisspdf.m: Rename from poisson_pdf.m.\n\t* statistics/distributions/poissrnd.m: Rename from poisson_rnd.m.\n\t* statistics/distributions/tcdf.m: Rename from t_cdf.m.\n\t* statistics/distributions/tinv.m: Rename from t_inv.m.\n\t* statistics/distributions/tpdf.m: Rename from t_pdf.m.\n\t* statistics/distributions/trnd.m: Rename from t_rnd.m.\n\t* statistics/distributions/unifcdf.m: Rename from unifoxorm_cdf.m.\n\t* statistics/distributions/unifinv.m: Rename from uniform_inv.m.\n\t* statistics/distributions/unifpdf.m: Rename from uniform_pdf.m.\n\t* statistics/distributions/unifrnd.m: Rename from uniform_rnd.m.\n\t* statistics/distributions/weibcdf.m: Rename from weibull_cdf.m.\n\t* statistics/distributions/weibinv.m: Rename from weibull_inv.m.\n\t* statistics/distributions/weibpdf.m: Rename from weibull_pdf.m.\n\t* statistics/distributions/wienrnd.m: Rename from wiener_rnd.m.\n\n\t* deprecated/beta_cdf.m, deprecated/beta_inv.m,\n\tdeprecated/beta_pdf.m, deprecated/beta_rnd.m,\n\tdeprecated/binomial_cdf.m, deprecated/binomial_inv.m,\n\tdeprecated/binomial_pdf.m, deprecated/binomial_rnd.m,\n\tdeprecated/chisquare_cdf.m, deprecated/chisquare_inv.m,\n\tdeprecated/chisquare_pdf.m, deprecated/chisquare_rnd.m,\n\tdeprecated/exponential_cdf.m, deprecated/exponential_inv.m,\n\tdeprecated/exponential_pdf.m, deprecated/exponential_rnd.m,\n\tdeprecated/f_cdf.m, deprecated/f_inv.m, deprecated/f_pdf.m,\n\tdeprecated/f_rnd.m, deprecated/gamma_cdf.m,\n\tdeprecated/gamma_inv.m, deprecated/gamma_pdf.m,\n\tdeprecated/gamma_rnd.m, deprecated/geometric_cdf.m,\n\tdeprecated/geometric_inv.m, deprecated/geometric_pdf.m,\n\tdeprecated/geometric_rnd.m, deprecated/hypergeometric_cdf.m,\n\tdeprecated/hypergeometric_inv.m, deprecated/hypergeometric_pdf.m,\n\tdeprecated/hypergeometric_rnd.m, deprecated/lognormal_cdf.m,\n\tdeprecated/lognormal_inv.m, deprecated/lognormal_pdf.m,\n\tdeprecated/lognormal_rnd.m, deprecated/normal_cdf.m,\n\tdeprecated/normal_inv.m, deprecated/normal_pdf.m,\n\tdeprecated/normal_rnd.m, deprecated/poisson_cdf.m,\n\tdeprecated/poisson_inv.m, deprecated/poisson_pdf.m,\n\tdeprecated/poisson_rnd.m, deprecated/t_cdf.m, deprecated/t_inv.m,\n\tdeprecated/t_pdf.m, deprecated/t_rnd.m, deprecated/uniform_cdf.m,\n\tdeprecated/uniform_inv.m, deprecated/uniform_pdf.m,\n\tdeprecated/uniform_rnd.m, deprecated/weibull_cdf.m,\n\tdeprecated/weibull_inv.m, deprecated/weibull_pdf.m,\n\tdeprecated/wiener_rnd.m: New files.\n\n2005-07-08  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/distributions/weibrnd.m: Rename from weibull_rnd.m.\n\t* deprecated/weibull_rnd.m: New file.\n\n2005-07-08  cctsim  <cctsim@yahoo.co.uk>\n\n\t* strings/dec2base.m: Allow matrix arguments.\n\n2005-07-08  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__errplot__.m: Use __plot_globals__.\n\t* plot/__plt__.m: Likewise.\n\t* plot/figure.m: Likewise.\n\n\t* plot/hold.m: New file.\n\t* plot/ishold.m: New file.\n\t* plot/__plot_globals__.m: New file.\n\n2005-07-05  cctsim  <cctsim@yahoo.co.uk>\n\n\t* strings/dec2base.m: Don't remove all leading zeros if result is zero.\n\n2005-07-05  John W. Eaton  <jwe@octave.org>\n\n\t* strings/findstr.m: Return [] for no matches.\n\n2005-06-17  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* miscellaneous/tic.m: Fix doc string.\n\n2005-06-15  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/polyfit.m: Force return value to be a row vector.\n\n2005-06-15  Tom Holroyd  <tomh@kurage.nimh.nih.gov>\n\n\t* general/isequal.m: Correct nargin check.\n\n2005-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* general/isvector.m: Handle N-d arrays.\n\tFrom Bill Denney <denney@seas.upenn.edu>.\n\n2005-06-02  Ben Barrowes  <barrowes@alum.mit.edu>\n\n\t* plot/meshgrid.m: Handle 3 input arguments.\n\n2005-06-02  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* signal/freqz.m: Use correct calculations when given a vector of\n\tfrequencies.  Improve accuracy of returned frequency vector.\n\tImprove speed for medium length filters (at a slight cost for slow\n\tfilters).  Add test cases.\n\n2005-05-27  \"Dmitri A. Sergatskov\"  <dasergatskov@gmail.com>\n\n\t* plot/loglog.m: Fix set commands.\n\n2005-05-25  John W. Eaton  <jwe@octave.org>\n\n\t* plot/sombrero.m: Default n to 41 if nargin == 0.\n\n2005-05-24  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/tests/anova.m: Use mean (y(:)) to compute total_mean.\n\n\t* strings/strncmp.m: New file, from Tom Holroyd\n\t<tomh@kurage.nimh.nih.gov>.\n\n\t* strings/strcmp.m: Return logical values in all cases.\n\n2005-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* plot/orient.m: New file.  Adapt to Octave coding style.\n\tTexinfoize doc string.\n\n\t* plot/print.m: New file.  Adapt to Octave coding style. Include\n\tPKG_ADD command.  Use set terminal consistently\tthroughout.  Use\n\tset terminal push/pop and unconditionally set output to screen\n\twhen done to avoid requiring gget.  Use a cell array for dev_list\n\tand cellidx to search for items in the list.  Delete local\n\tvariable endl.  Don't set and restore automatic_replot.  Use {}\n\tinstead of nth to index varargin.  Delete local variable\n\tva_arg_cnt.\n\n2005-05-18  John W. Eaton  <jwe@octave.org>\n\n\t* general/num2str.m: Return early if X is a character string.\n\n2005-05-11  John W. Eaton  <jwe@octave.org>\n\n\t* strings/findstr.m: Allow non-string arguments for compatiblity.\n\tFrom Tom Holroyd <tomh@kurage.nimh.nih.gov>.\n\n\t* plot/polar.m: Don't call __pltopt__ here.\n\n2005-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* mkdoc: Print header message.\n\n2005-04-28  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AC_CONFIG_SRCDIR): Look for startup/inputrc, not\n\tstartup/octaverc.\n\n2005-04-28  Stefan van der Walt  <stefan@sun.ac.za>\n\n\t* image/imshow.m: Handle various image depths and 3d RGB images.\n\t(__im_numeric_limits__): New internal function.\n\n2005-04-28  toni saarela  <toni.saarela@helsinki.fi>\n\n\t* statistics/tests/anova.m: Compute total_mean as mean of all\n\tdata, not mean of group_mean.\n\n2005-04-28  John W. Eaton  <jwe@octave.org>\n\n\t* startup/local-rcfile: New file.\n\t* startup/main-rcfile: Rename from startup/octaverc.\n\t* startup/Makefile.in (SOURCES): Add inputrc to the list.\n\t(install install-strip): Install main-rcfile in $(fcnfiledir)/startup.\n\tInstall local-rcfile in $(localfcnfiledir)/startup.\n\n2005-04-28  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* startup/inputrc: New file.\n\t* startup/octaverc: Configure readline using inputrc from\n\tstartupfiledir.\n\t* startup/Makefile.in (install, install-strip): Install octaverc\n\tin $(fcnfiledir)/startup.\n\n2005-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/qp.m: Define n_in after removing -Inf bounds from Ain.\n\n2005-04-21  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/glpk.m: Handle SENSE argument.\n\n\t* optimization/qp.m, optimization/sqp.m: New files.\n\n2005-04-08  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (clean, distclean, maintainer-clean):\n\tAvoid duplication in rules.\n\n2005-03-28  John W. Eaton  <jwe@octave.org>\n\n\t* plot/contour.m, plot/mesh.m: Continue to use __gnuplot_raw__ for\n\tsetting {no,}parametric.\n\t* plot/figure.m: Likewise, for setting terminal type.\n\n\t*  __axis_label__.m:, plot/axis.m, plot/bottom_title.m,\n\tplot/contour.m, plot/figure.m, plot/multiplot.m, plot/mplot.m,\n\tplot/plot_border.m, plot/subplot.m, plot/subwindow.m,\n\tplot/title.m, plot/top_title.m: Avoid eval.\n\n2005-03-28  Dmitri A. Sergatskov  <dasergatskov@gmail.com>\n\n\t* plot/__axis_label__.m, plot/axis.m, plot/grid.m,\n\tplot/plot_border.m, plot/replot.m, plot/title.m, plot/top_title.m:\n\tUse __gnuplot_replot__ instead of replot.\n\n\t* plot/__axis_label__.m, plot/axis.m, plot/bottom_title.m,\n\tplot/contour.m, plot/errorbar.m, plot/figure.m, plot/grid.m,\n\tplot/loglogerr.m, plot/loglog.m, plot/mesh.m, plot/mplot.m,\n\tplot/multiplot.m, plot/oneplot.m, plot/plot_border.m, plot/plot.m,\n\tplot/polar.m, plot/semilogxerr.m, plot/semilogx.m,\n\tplot/semilogyerr.m, plot/semilogy.m, plot/shg.m, plot/subplot.m,\n\tplot/subwindow.m, plot/title.m, plot/top_title.m:\n\tUse __gnuplot_raw__ instead of __gnuplot_set__.\n\n\t* plot/replot.m: Use __gnuplot_replot__, not __greplot__.\n\n2005-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* optimization/glpkmex.m: Texinfoize Doc string.\n\t* optimization/glpk.m: Likewise.\n\tAllow VARTYPE and CTYPE to be row or column vectors of characters\n\t(row vectors are orginary character strings).\n\t* optimization/glpkparam.m: Delete.\n\n2005-03-24  Quentin Spencer  <qspencer@ieee.org>\n\n\t* statistics/base/mean.m: Allow DIMS arg greater than the number\n\tof dimensions of X.\n\n2005-03-23  John W. Eaton  <jwe@octave.org>\n\n\t* general/tril.m, general/triu.m: Return value of same class as\n\targument.\n\n\t* optimization/glpk.m: Simplify interface.  By default, solve\n\tstandard LP min C'*x s.t. A*x = b, x >= 0.\n\t* optimization/glpkmex.m: New file.\n\n2005-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* configure.in (AC_CONFIG_FILES): Add optimization/Makefile to the\n\tlist.\n\n\t* optimization/glpk.m: Adapt to Octave coding style.\n\tNo need for varargout or varargin.\n\tPrint usage message if nargin > 11.\n\tAllow any value of nargout.\n\tUse repmat (C, nr, nc) instead of char (C * ones (nr, nc)).\n\tAvoid looping when checking character classes.\n\n\t* optimization: New directory.\n\t* Makefile.in (SUBDIRS): Add it to the list.\n\t* optimization/Makefile.in: New file.\n\t* optimization/glpk.m, optimization/glpkparams.m,\n\toptimization/glpktest1, optimization/glpktest2: New files.\n\n2005-03-16  Søren Hauberg  <soren@hauberg.org>\n\n\t* strings/split.m: Quick return for empty second arg.\n\tImprove warning for multi-line strings.\n\tSpeed up by avoiding sprintf in loop and eval.\n\n2005-03-16  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* polynomial/polyderiv.m : Accept a*b, a/b.  Auto-reduce common terms.\n\t* polynomial/polyder.m: Ditto.\n\t* polynomial/polygcd.m: New function.\n\n2005-03-16  John W. Eaton  <jwe@octave.org>\n\n\t* control/base/__stepimp__.m, control/base/bode.m,\n\tcontrol/base/frdemo.m, control/base/nichols.m,\n\tcontrol/base/nyquist.m, control/base/pzmap.m,\n\tcontrol/base/rldemo.m, control/base/rlocus.m,\n\tcontrol/hinf/dhinfdemo.m, control/hinf/hinfdemo.m,\n\tplot/__axis_label__.m, plot/__errplot__.m, plot/__plt__.m,\n\tplot/axis.m, plot/bar.m, plot/bottom_title.m, plot/contour.m,\n\tplot/errorbar.m, plot/figure.m, plot/grid.m, plot/loglog.m,\n\tplot/loglogerr.m, plot/mesh.m, plot/meshgrid.m, plot/mplot.m,\n\tplot/multiplot.m, plot/oneplot.m, plot/plot.m, plot/plot_border.m,\n\tplot/polar.m, plot/semilogx.m, plot/semilogxerr.m,\n\tplot/semilogy.m, plot/semilogyerr.m, plot/shg.m, plot/stairs.m,\n\tplot/subplot.m, plot/subwindow.m, plot/title.m, plot/top_title.m,\n\tplot/xlabel.m, quaternion/demoquat.m,\n\tquaternion/qcoordinate_plot.m, signal/freqz_plot.m, sparse/spy.m,\n\tstatistics/base/ppplot.m, statistics/base/qqplot.m:\n\tUse __gnuplot_plot__ instead of gplot, __gnuplot_splot__ instead\n\tof gsplot, and __gnuplot_set__ instead of gset. Remove gplot,\n\tgsplot from @seealso docs.\n\n\t* plot/replot.m: New file.\n\n2005-03-15  David Bateman  <dbateman@free.fr>\n\n\t* set/unique.m, set/ismember.m: Handle cell arrays.\n\n2005-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/Makefile.in (bin-dist): Delete target.\n\t(BINDISTSUBDIRS): Delete variable.\n\t* control/Makefile.in: Likewise.\n\n\t* audio/Makefile.in (bin-dist): Delete target.\n\t(BINDISTFILES): Delete variable.\n\t* control/base/Makefile.in: Likewise.\n\t* control/hinf/Makefile.in: Likewise.\n\t* control/obsolete/Makefile.in: Likewise.\n\t* control/system/Makefile.in: Likewise.\n\t* control/util/Makefile.in: Likewise.\n\t* deprecated/Makefile.in: Likewise.\n\t* elfun/Makefile.in: Likewise.\n\t* finance/Makefile.in: Likewise.\n\t* general/Makefile.in: Likewise.\n\t* image/Makefile.in: Likewise.\n\t* sparse/Makefile.in: Likewise.\n\t* io/Makefile.in: Likewise.\n\t* plot/Makefile.in: Likewise.\n\t* Makefile.in: Likewise.\n\t* miscellaneous/Makefile.in: Likewise.\n\t* linear-algebra/Makefile.in: Likewise.\n\t* polynomial/Makefile.in: Likewise.\n\t* quaternion/Makefile.in: Likewise.\n\t* set/Makefile.in: Likewise.\n\t* signal/Makefile.in: Likewise.\n\t* specfun/Makefile.in: Likewise.\n\t* special-matrix/Makefile.in: Likewise.\n\t* startup/Makefile.in: Likewise.\n\t* statistics/base/Makefile.in: Likewise.\n\t* statistics/distributions/Makefile.in: Likewise.\n\t* statistics/models/Makefile.in: Likewise.\n\t* statistics/tests/Makefile.in: Likewise.\n\t* strings/Makefile.in: Likewise.\n\t* time/Makefile.in: Likewise.\n\n2005-03-08  John W. Eaton  <jwe@octave.org>\n\n\t* general/repmat.m: Correctly diagnose 3-argument non-scalar\n\tdimensions case.  From Matthew A Swabey <mas01r@ecs.soton.ac.uk>.\n\n2005-03-04  John W. Eaton  <jwe@octave.org>\n\n\t* plot/clg.m: New file.\n\n2005-03-03  John W. Eaton  <jwe@octave.org>\n\n\t* general/isequal.m, general/sortrows.m, set/ismember.m,\n\tset/setdiff.m, strings/str2double.m, strings/strmatch.m,\n\tstrings/strcmpi.m:\n\tNew files from Octave-forge.  Adapt to Octave coding standards.\n\n2005-03-03  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* statistics/distributions/binomial_pdf.m: Extend the feasible\n\tcomputation range.\n\n2005-02-25  John W. Eaton  <jwe@octave.org>\n\n\tSparse merge.\n\n\t2005-01-23  David Bateman  <dbateman@free.fr>\n\n\t* sparse/randperm.m: Delete duplicate randperm.m.\n\n\t2005-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* sparse/Makefile.in: New file.\n\t* configure.in (AC_CONFIG_FILES): Add sparse/Makefile to the list.\n\n\t2005-01-07  David Bateman  <dbateman@free.fr>\n\n\t* set/unique.m: import file from octave-forge.\n\n\t2005-01-05  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in: include sparse directory in SUBDIRS.\n\n\t2004-12-30  John W. Eaton  <jwe@octave.org>\n\n\t* sparse/nzmax.m: Delete (there is an nzmax function in\n\tsrc/DLD-FUNCTIONS/sparse.cc).\n\n\t2004-12-28  John W. Eaton  <jwe@octave.org>\n\n\tMerge of sparse code from David Bateman <dbateman@free.fr> and\n\tAndy Adler <adler@site.uottawa.ca>.\n\n\t* sparse/colperm.m, sparse/nonzeros.m, sparse/nzmax.m,\n\tsparse/randperm.m, sparse/spalloc.m, sparse/spconvert.m,\n\tsparse/spdiags.m, sparse/speye.m, sparse/spfun.m, sparse/sphcat.m,\n\tsparse/spones.m, sparse/sprand.m, sparse/sprandn.m,\n\tsparse/spstats.m, sparse/spvcat.m, sparse/spy.m: New files.\n\n\t* sparse: New directory.\n\n2005-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/residue.m: Force prepad to always create row vectors.\n\n\t* polynomial/poly.m: Quick return if m is 0.\n\tFrom Carmen Navarrete <carmen.navarrete@uam.es>.\n\n2005-02-21  David Bateman  <dbateman@free.fr>\n\n\t* statistics/distributions/poisson_rnd.m: fix for lambda of zero.\n\tFrom Mark van Rossum <mvanross@inf.ed.ac.uk>.\n\tFix for row vectors with at least one element of lambda not in\n\t(0, Inf).\n\n2005-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/base/qqplot.m: Use feval instead of eval.\n\n\t* plot/grid.m, plot/plot_border.m, plot/title.m, plot/top_title.m,\n\tplot/__axis_label__.m: Issue replot command.\n\n2005-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* polynomial/polyderiv.m: Force P to be a row vector.\n\n2005-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* strings/dec2base.m: Don't delete leading zero if third arg is\n\tprovided and len <= computed max_len.\n\n2005-01-27  David Bateman  <dbateman@free.fr>\n\n\t* strings/dec2base.m: Be even more careful about handling all digits.\n\n2005-01-27  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* strings/dec2base.m: Use integer arithmetic to count number of digits.\n\n2005-01-27  Benjamin Hall  <benjamin.hall@pw.utc.com>\n\n\t* statistics/base/median.m: Make it work for the scalar case too.\n\n2005-01-25  Daniel J Sebald  <daniel.sebald@ieee.org>\n\n\t* plot/__plt__.m: Initialize fmt and sep outside of loop.\n\tSimplify logic for decoding args.\n\n2005-01-24  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__plr__.m, plot/__plr2__.m: Pass name of caller to __plt__.\n\n\t* plot/__plt__.m: No need to save and reset hold state now.\n\t(first_plot): Delete unused variable.\n\n\t* plot/__plr2__.m, plot/__plt2__.m: Improve diagnostics.\n\n\t* plot/__plr__.m: Use __plt__, not specific __pltXX__ functions.\n\t* plot/__plt1__.m, plot/__plt2__.m, plot/__plt2mm__.m,\n\tplot/__plt2mv__.m, plot/__plt2ss__.m, plot/__plt2vm__.m,\n\tplot/__plt2vv__.m:\n\tReturn data and gnuplot commands instead of evaluating them.\n\t* plot/__plt__.m: Handle evaluation of all gnuplot commands here.\n\tBased on changes from Daniel J Sebald <daniel.sebald@ieee.org>.\n\n2005-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* linear-algebra/cross.m: Allocate idx1 before use.\n\n2004-12-08  Heikki Junes  <Heikki.Junes@hut.fi>\n\n\t* statistics/base/range.m: Fix varargin usage.\n\n2004-12-02  Pascal A. Dupuis  <Pascal.Dupuis@esat.kuleuven.ac.be>\n\n\t* strings/deblank.m: Remove all trailing whitespace (check with\n\tisspace), not just SPC.\n\n2004-12-02  Balint Reczey  <balint_reczey@yahoo.com>\n\n\t* statistics/base/moment.m: Fix argument parsing for N-d arrays.\n\n2004-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* miscellaneous/fileparts.m: Allow filenames with no extension.\n\tFrom Julius Smith <jos@ccrma.stanford.edu>.\n\n2004-11-08  John W. Eaton  <jwe@octave.org>\n\n\t* plot/__plt2vm__.m: Delete debugging statement.\n\tFrom Dmitri A. Sergatskov <dmitri@unm.edu>.\n\n2004-11-04  John W. Eaton  <jwe@octave.org>\n\n\t* plot/hist.m: Always return row vectors for vector args.\n\n2004-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* strings/strcmp.m: If args are not strings or cell arrays of\n\tstrings, return zero instead of reporting an error.\n\n2004-09-22  Federico Zenith  <zenith@chemeng.ntnu.no>\n\n\t* control/base/analdemo.m, control/base/are.m, control/base/bddemo.m,\n\tcontrol/base/controldemo.m, control/base/damp.m, control/base/dare.m,\n\tcontrol/base/dcgain.m, control/base/dgram.m, control/base/dlyap.m,\n\tcontrol/base/dre.m, control/base/frdemo.m, control/base/gram.m,\n\tcontrol/base/impulse.m, control/base/lqp.m, control/base/obsv.m,\n\tcontrol/base/pzmap.m, control/base/rldemo.m, control/hinf/h2norm.m,\n\tcontrol/hinf/hinfsyn.m, control/hinf/hinfsyn_ric.m,\n\tcontrol/hinf/is_dgkf.m, control/system/c2d.m,\n\tcontrol/system/is_detectable.m, control/system/is_sample.m,\n\tcontrol/system/is_siso.m, control/system/is_stable.m,\n\tcontrol/system/ss2sys.m, control/system/ss.m, control/system/sys2ss.m,\n\tcontrol/system/sys2tf.m, control/system/sys2zp.m,\n\tcontrol/system/sysappend.m, control/system/sysconnect.m,\n\tcontrol/system/sysdisc.m, control/system/sysdup.m,\n\tcontrol/system/sysgetsignals.m, control/system/sysmult.m,\n\tcontrol/system/syssetsignals.m, control/system/syssub.m,\n\tcontrol/system/tf2sys.m, control/system/ugain.m,\n\tcontrol/system/zp2ss.m, control/system/zp2sys.m,\n\tcontrol/system/zp2tf.m, control/util/axis2dlim.m, polynomial/roots.m,\n\tspecial-matrix/toeplitz.m: Fix typos in doc strings.\n\n\t* control/base/are.m, control/base/dare.m, control/base/lsim.m,\n\tcontrol/base/ltifr.m, control/base/place.m,control/base/tzero2.m,\n\tcontrol/base/tzero.m, control/hinf/hinf_ctr.m, control/hinf/wgt1o.m,\n\tontrol/system/is_abcd.m, control/system/parallel.m,\n\tcontrol/system/ss2tf.m, control/system/ss2zp.m, control/system/ss.m,\n\tcontrol/system/sysappend.m, control/system/sysconnect.m,\n\tcontrol/system/sysdup.m, control/system/sysgroup.m,\n\tcontrol/system/sysprune.m, control/system/sysreorder.m,\n\tcontrol/system/sysscale.m, control/system/syssub.m,\n\tcontrol/system/tf2ss.m, control/system/tf2zp.m, control/util/zgfmul.m,\n\tcontrol/util/zginit.m, control/util/zgscal.m, elfun/acoth.m,\n\tpolynomial/polyout.m, specfun/log2.m:\n\tAdd output arguments in doc strings.\n\n\t* control/base/are.m, control/base/bode_bounds, control/base/bode.m,\n\tcontrol/base/__bodquist__.m, control/base/ctrb.m, control/base/dare.m,\n\tcontrol/base/DEMOcontrol.m, control/base/dlyap.m, control/base/dre.m,\n\tcontrol/base/freqchkw.m, control/base/__freqresp__.m,\n\tcontrol/base/__freqresp__.m, control/base/lqp.m, control/base/lqr.m,\n\tcontol/base/lsim.m, control/base/lyap.m, control/base/nyquist.m,\n\tcontrol/base/obsv.m, control/base/place.m, control/base/pzmap.m,\n\tcontrol/base/__stepimp__.m, control/base/step.m, control/base/tzero2.m\n\tcontrol/base/tzero.m, control/hinf/dhinfdemo.m, control/hinf/h2norm.m,\n\tcontrol/hinf/h2syn.m, control/hinf/hinfdemo.m,\n\tcontrol/hinf/hinfnorm.m, control/hinf/hinfsyn_chk.m,\n\tcontrol/hinf/hinfsyn.m, control/hinf/is_dgkf.m,\n\tcontrol/obsolete/syschnames.m, control/obsolete/syschnames.m,\n\tcontrol/system/c2d.m, control/system/is_abcd.m,\n\tcontrol/system/is_controllable.m, control/system/is_detectable.m,\n\tcontrol/system/is_observable.m, control/system/is_stable.m,\n\tcontrol/system/jet707.m, control/system/ord2.m,\n\tcontrol/system/starp.m, control/system/sys2fir.m,\n\tcontrol/system/sys2ss.m, control/system/sys2tf.m,\n\tcontrol/system/sys2zp.m, control/system/syscont.m,\n\tcontrol/system/sysdisc.m, control/system/sysdup.m,\n\tcontrol/system/sysgettype.m, control/system/sysgroup.m,\n\tcontrol/system/sysmult.m, control/system/sysprune.m,\n\tcontrol/system/sysreorder.m, control/system/sysscale.m,\n\tcontrol/system/syssetsignals.m, control/system/sysupdate.m,\n\tcontrol/system/tf2ss.m, control/system/tf2sys.m,\n\tcontrol/system/zp2ss.m, control/system/zp2sys.m,\n\tcontrol/util/axis2dlim.m, control/util/prompt.m,\n\tcontrol/util/zgfmul.m, control/util/zginit.m,\n\tcontrol/util/__zgpbal__.m, control/util/zgscal.m:\n\tUse @var, @strong, @command, @math, @acronym, @table and @cite\n\tin doc strings.\n\n\t* control/base/bode_bounds.m, control/base/ctrb.m, control/base/dre.m,\n\tcontrol/base/dgram.m, control/base/dlyap.m, control/base/ltifr.m,\n\tcontrol/base/nyquist.m, control/base/obsv.m, control/base/tzero.m,\n\tcontrol/hinf/dgkfdemo.m, control/hinf/dhinfdemo.m,\n\tcontrol/hinf/h2norm.m, control/hinf/h2syn.m, control/hinf/hinf_ctr.m,\n\tcontrol/hinf/hinfdemo.m, control/hinf/hinfnorm.m,\n\tcontrol/hinf/hinfsyn_chk.m, control/hinf/hinfsyn.m,\n\tcontrol/hinf/wgt1o.m, control/obsolete/syschnames.m,\n\tcontrol/system/c2d.m, control/system/fir2sys.m,\n\tcontrol/system/is_stabilizable.m, control/system/jet707.m,\n\tcontrol/system/ord2.m, control/system/ss2tf.m, control/system/tf2ss.m,\n\tcontrol/util/zgshsr.m, polynomial/polyout.m:\n\tNew @tex section(s) in doc strings for better formating of printed\n\toutput.\n\n\t* control/base/__freqresp__.m, control/base/nyquist.m,\n\tcontrol/base/__stepimp__.m, control/hinf/hinfdemo.m,\n\tcontrol/obsolete/syschnames.m, control/system/sysprune.m:\n \tUse proper double quote marks for TeX.\n\n\t* control/base/DEMOcontrol.m: Add missing ;\n\n\t* control/base/nichols.m, control/base/rlocus.m,\n\tcontrol/obsolete/minfo.m, control/system/is_digital.m,\n\tcontrol/system/ss2zp.m, control/system/sysmin.m,\n\tcontrol/system/tf2zp.m, control/util/sortcom.m:\n\tConvert documentation to use or more completely use Texinfo.\n\n\t* control/base/rlocus.m, control/hinf/dhinfdemo.m,\n\tcontrol/hinf/hinfdemo.m, control/system/ord2.m,\n\tcontrol/system/parallel.m, control/system/ss2tf.m,\n\tcontrol/system/starp.m: Use \"@group ... @end group\" to avoid ascii\n\tart splitting over a page boundary.\n\n\t* control/hinf/dgkfdemo.m, control/hinf/dhinfdemo.m,\n\tcontrol/hinf/h2norm.m, control/hinf/h2syn.m, control/hinf/hinf_ctr.m,\n\tcontrol/hinf/hinfdemo.m, control/hinf/hinfnorm.m,\n\tcontrol/hinf/hinfsyn_chk.m, control/hinf/hinfsyn.m,\n\tcontrol/hinf/wgt1o.m, control/system/buildssic.m:\n\tUse {\\cal H}_\\infty for H-infinity and likewise for H-2 to\n\tthe TeX documentation.\n\n\t* control/system/is_stabilizable.m:\n\tAdd Copyright so that help is displayed correctly.\n\n\t* special-matrix/vander.m: Octave indexes start at 1.\n\n2004-09-21  David Bateman  <dbateman@free.fr>\n\n\t* general/rotdim.m: New function for rotation of an N-d array in an\n\tarbitrary plane.\n\n\t* general/flipdim.m: New function to flip an N-d array about an\n\tarbitrary axis.\n\n2004-09-15  David Bateman  <dbateman@free.fr>\n\n\t* general/bitget.m: Replace Bmax, which is undefined with bitmax\n\n2004-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* strings/strcmp.m: Fix typo in cell/string array case.\n\tUse iscellstr to check for cells rather than iscell.\n\tImprove diagnostics for invalid args.\n\n2004-09-10  David Bateman  <dbateman@free.fr>\n\n\t* statistics/distributions/binomial_rnd.m: Fix error for scalar n\n\tand p with n > 1, and fix for matrix n and p with n == 1.\n\n\t* statistics/distributions/poisson_rnd.m: Fix for matrix length,\n\tdue to row vs. column vector operations.\n\n2004-09-03  David Bateman  <dbateman@free.fr>\n\n\t* general/repmat.m: Fix to allow logical classes.\n\n2004-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* general/isa.m: New function, from Octave-forge.\n\n2004-08-31  David Bateman  <dbateman@free.fr>\n\n\t* general/bitcmp.m, general/bitget.m, general/bitset.m: Remove\n\tlimitation on the use of int64 and uint64 types, and the use\n\tof the eval.\n\n\t* general/bitset.m: Remove superfluous cast to return type, as bug\n\tin .^ with integer types is fixed.\n\n\t* general/repmat.m: Adapt to allow integer types.\n\n2004-08-31  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* plot/axis.m: Don't reset axes when querying them.\n\n2004-08-27  David Bateman  <dbateman@free.fr>\n\n\t* statistics/base/ranks.m: Handle non-consecutive ties.\n\tEliminate loop.\n\n2004-07-27  David Bateman  <dbateman@free.fr>\n\n\t* general/num2str.m: Also insert spaces in output when precision\n\targument is supplied.\n\n2004-07-23  David Bateman  <dbateman@free.fr>\n\n\t* general/bitcmp.m, general/bitget.m, general/bitset.m: New functions.\n\n2004-07-22  Etienne Grossmann  <etienne@cs.uky.edu>\n\n\t* general/sub2ind.m: Make reshaping index list unnecessary.\n\n2004-07-22  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* miscellaneous/unix.m: Fix doc string.\n\n2004-07-22  Stefan van der Walt  <stefan@sun.ac.za>\n\n\t* plot/figure.m: Clarification of documentation.\n\n\t* image/imshow.m: Warn for complex images.\n\tOnly estimate colourmap for images in [0, 65536].\n\n2004-07-22  David Bateman  <dbateman@free.fr>\n\n\t* general/num2str.m: Fix the case of an all zero input.\n\n2004-06-22  Etienne Grossmann  <etienne@cs.uky.edu>\n\n\t* general/ind2sub.m: Doc fix.\n\n2004-06-08  John W. Eaton  <jwe@octave.org>\n\n\t* statistics/tests/kolmogorov_smirnov_test.m: Use func2str to\n\tconvert function handle to string for eval.\n\n2004-06-04  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* plot/errorbar.m: Remove debugging output.\n\n2004-06-03  Stefan van der Walt  <stefan@sun.ac.za>\n\n\t* plot/__pltopt__.m: Properly escape @ symbols in doc string.\n\n2004-06-03  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* deprecated/com2str.m: Include 'i' suffix for pure imaginary numbers.\n\n\t* polynomial/polyout.m: Use parenthesis if necessary around\n\tcomplex polynomial coefficient.\n\n\t* plot/__errcomm__.m, plot/__errplot__.m: Simplify code and fix\n\tthe bug which causes __errplot__ to ignore the last argument.\n\n2004-06-03  David Bateman  <dbateman@free.fr>\n\n\t* general/shiftdim.m: New function based on JWE code snippet.\n\n\t* general/circdim.m: New function.\n\n2004-05-06  David Bateman  <dbateman@free.fr>\n\n\t* general/issquare.m: Fail if ndim(x) > 2.\n\n\t* linear-algebra/norm.m, linear-algebra/norm.m: Fail if ndim(x) > 2.\n\n\t* linear-alegbra/cross.m, linear-algebra/dot.m: Allow matrix and\n\tN-d array arguments.  Add optional dim argument to define\n\tdimension along which to operate.\n\n\t* linear-algebra/dmult.m: Allow N-d arrays.\n\n\t* linear-algebra/vec.m: Use v(:) and not reshape.\n\n2004-04-29  David Bateman  <dbateman@free.fr>\n\n\t* statistics/base/ranks.m, statistics/base/run_count.m,\n\tstatistics/base/studentize.m, statistics/base/kurtosis.m\n\tstatistics/base/statistics.m, statistics/base/skewness.m\n\tstatistics/base/iqr.m:\n\tMake N-d array aware.  Allow optional argument to define the\n\tdimension along which to operate.  Update the documentation.\n\n\t* statistics/base/ranks.m: Change algorithm to use sort,\n\tand adjust for the ties after.\n\n\t* statistics/base/run_counts.m: Change algorithm to use\n\tthe a combination of diff and find, rather than a for-loop.\n\n2004-04-23  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* plot/hist.m: Correctly determine cutoffs.  New tests.\n\n2004-04-23  David Bateman  <dbateman@free.fr>\n\n\t* general/int2str.m: Treat only real part of argument, and treat\n\tNDArrays by stacking the slices through the matrix vertically.\n\n\t* general/num2str.m: Improve format of integer matrices, and the\n\tconversion of complex matrices added. Treat NDArrays by stacking\n\tthe slices through the matrix vertically.\n\n\t* deprecated/com2str.m: Moved here from general subdirectory.\n\n2004-04-22  John W. Eaton  <jwe@octave.org>\n\n\t* quaternion/qtransvmat.m: Use continuation characters to make\n\tsure result is a matrix instead of a vector.  From <aklark@atdot.it>.\n\n2004-04-21  David Bateman  <dbateman@free.fr>\n\n\t* elfun/lcm.m: Make N-d aware.\n\n\t* general/diff.m: Make the code N-d array aware.  Allow an\n\toptional argument to define the dimension along which to perform\n\tthe differences and allow the order of the differences to be larger\n\tthan the dimension itself.\n\n\t* general/rot90.m, general/fliplr.m, general/flipud.m: Limit the\n\tuse of these functions to 1- and 2-d arrays.\n\n2004-04-16  John W. Eaton  <jwe@octave.org>\n\n\t* elfun/gcd.m: Delete.\n\n2004-04-15  David Bateman  <dbateman@free.fr>\n\n\t* set/create_set.m, general/is_duplicate_entry.m: Make N-d array aware.\n\n\t* general/shift.m, general/prepad.m, general/postpad.m: Make N-d\n\tarray aware and and optional argument for the dimension along\n\twhich to operate.\n\n\t* signal/unwrap.m: Make N-d array aware and fix optional\n\targument for the dimension to be consistent with other N-d array\n\tfunctions.\n\n2004-04-08  David Bateman  <dbateman@free.fr>\n\n\t* statistics/distributions/discrete_cdf.m,\n\tstatistics/distributions/discrete_inv.m,\n\tstatistics/distributions/discrete_pdf.m,\n\tstatistics/distributions/discrete_rnd.m,\n\tstatistics/distributions/exponential_cdf.m,\n\tstatistics/distributions/exponential_inv.m,\n\tstatistics/distributions/exponential_pdf.m,\n\tstatistics/distributions/exponential_rnd.m,\n\tstatistics/distributions/f_cdf.m,\n\tstatistics/distributions/f_inv.m,\n\tstatistics/distributions/f_pdf.m,\n\tstatistics/distributions/f_rnd.m,\n\tstatistics/distributions/geometric_cdf.m,\n\tstatistics/distributions/geometric_inv.m,\n\tstatistics/distributions/geometric_pdf.m,\n\tstatistics/distributions/geometric_rnd.m,\n\tstatistics/distributions/hypergeometric_rnd.m,\n\tstatistics/distributions/kolmogorov_smirnov_cdf.m,\n\tstatistics/distributions/laplace_cdf.m,\n\tstatistics/distributions/laplace_inv.m,\n\tstatistics/distributions/laplace_pdf.m,\n\tstatistics/distributions/laplace_rnd.m,\n\tstatistics/distributions/logistic_inv.m,\n\tstatistics/distributions/logistic_rnd.m,\n\tstatistics/distributions/lognormal_cdf.m,\n\tstatistics/distributions/lognormal_inv.m,\n\tstatistics/distributions/lognormal_pdf.m,\n\tstatistics/distributions/lognormal_rnd.m,\n\tstatistics/distributions/pascal_cdf.m,\n\tstatistics/distributions/pascal_inv.m,\n\tstatistics/distributions/pascal_pdf.m,\n\tstatistics/distributions/pascal_rnd.m,\n\tstatistics/distributions/poisson_cdf.m,\n\tstatistics/distributions/poisson_inv.m,\n\tstatistics/distributions/poisson_pdf.m,\n\tstatistics/distributions/poisson_rnd.m,\n\tstatistics/distributions/t_cdf.m,\n\tstatistics/distributions/t_inv.m,\n\tstatistics/distributions/t_pdf.m,\n\tstatistics/distributions/t_rnd.m,\n\tstatistics/distributions/weibull_cdf.m,\n\tstatistics/distributions/weibull_inv.m,\n\tstatistics/distributions/weibull_pdf.m,\n\tstatistics/distributions/weibull_rnd.m:\n\tAllow N-d arrays.\n\n\t* statistics/distributions/discrete_inv.m: Fix bug in indexing,\n\tthat results in NaN in places where it should not have had.\n\n\t* statistics/distributions/discrete_rnd.m: New argument formats to\n\tallow creating arbitrary matrices, compatiable with the other\n\t*_rnd.m functions. Maintain compatibility with previous format.\n\n\t* statistics/distributions/empirical_rnd.m: New argument formats\n\tto allow creating arbitrary matrices, compatiable with the other\n\t*_rnd.m functions. Maintain compatibility with previous\n\tformat.  Allow N-d arrays.\n\n\t* statistics/distributions/hypergeometric_cdf.m,\n\tstatistics/distributions/hypergeometric_inv.m,\n\tstatistics/distributions/hypergeometric_pdf.m,\n\tstatistics/distributions/wiener_rnd.m:\n\tError for non-scalar arguments.\n\n\t* statistics/distributions/pascal_rnd.m:\n\tCorrect for n = 1 bug, where all elements were equal.\n\n2004-04-06  David Bateman  <dbateman@free.fr>\n\n\t* general/common_size.m, miscellaneous/bincoeff.m,\n\tstatistics/distributions/beta_cdf.m,\n\tstatistics/distributions/beta_inv.m,\n\tstatistics/distributions/beta_pdf.m,\n\tstatistics/distributions/beta_rnd.m,\n\tstatistics/distributions/binomial_cdf.m,\n\tstatistics/distributions/binomial_inv.m,\n\tstatistics/distributions/binomial_pdf.m,\n\tstatistics/distributions/binomial_rnd.m,\n\tstatistics/distributions/cauchy_cdf.m,\n\tstatistics/distributions/cauchy_inv.m,\n\tstatistics/distributions/cauchy_pdf.m,\n\tstatistics/distributions/cauchy_rnd.m,\n\tstatistics/distributions/chisquare_cdf.m,\n\tstatistics/distributions/chisquare_inv.m,\n\tstatistics/distributions/chisquare_pdf.m,\n\tstatistics/distributions/chisquare_rnd.m,\n\tstatistics/distributions/gamma_cdf.m,\n\tstatistics/distributions/gamma_inv.m,\n\tstatistics/distributions/gamma_pdf.m,\n\tstatistics/distributions/gamma_rnd.m,\n\tstatistics/distributions/normal_cdf.m,\n\tstatistics/distributions/normal_inv.m,\n\tstatistics/distributions/normal_pdf.m,\n\tstatistics/distributions/normal_rnd.m,\n\tstatistics/distributions/stdnormal_cdf.m,\n\tstatistics/distributions/stdnormal_pdf.m,\n\tstatistics/distributions/stdnormal_rnd.m,\n\tstatistics/distributions/uniform_cdf.m,\n\tstatistics/distributions/uniform_inv.m,\n\tstatistics/distributions/uniform_pdf.m,\n\tstatistics/distributions/uniform_rnd.m:\n\tAllow the inputs to be N-d arrays.\n\n\t* statistics/base/var.m: Update for N-d arrays.  Allow dimension arg.\n\t* statistics/base/median.m: Likewise.\n\n2004-04-02  David Bateman  <dbateman@free.fr>\n\n\t* statistics/base/std.m: Allow optional args for type and dim.\n\t* statistics/base/center.m, statistics/base/meansq.m,\n\tstatistics/base/moment.m, statistics/base/range.m:\n\tUpdate for N-d arrays.\n\t* signal/fftshift.m: Fix dimensioning error.\n\n\t* statistics/base/std.m: Use repmat not ones(nr,1)*mean to allow\n\tN-d arrays.\n\n\t* general/mod.m, general/mod.m: Allow N-d arrays with one scalar arg.\n\n\t* signal/fftshift.m: Update for N-d arrays, allow optional dim arg.\n\n\t* specfun/erfinv.m, general/repmat.m: Update for N-d arrays.\n\n\t* control/base/bode.m, control/base/lqg.m, control/system/ss2sys.m,\n\tcontrol/system/cellidx.m, control/system/dmr2d.m control/system/ss.m,\n\tcontrol/system/sysprune.m: Doc update for usage of cell arrays.\n\n\t* control/system/sysidx.m: Use cellidx and not listidx.\n\n2004-03-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__pltopt1__.m: Always add title clause to plot command with\n\tdefault of \"\" (so it is off unless explicitly set by the user).\n\n2004-03-12  Stefan van der Walt  <stefan@sun.ac.za>\n\n\t* image/imshow.m: Accept \"truesize\" argument.\n\tIgnore current colormap.  New tests and demos.\n\n2004-03-10  Volker Kuhlmann  <VolkerKuhlmann@gmx.de>\n\n\t* signal/sinewave.m: Allow N to default to M.\n\n2004-03-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* signal/unwrap.m: Use \"isempty (tol)\" instead of \"tol == []\".\n\n2004-03-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/deal.m: New function.\n\tAdd tests from Paul Kienzle.\n\n2004-03-03  Stefan van der Walt  <stefan@sun.ac.za>\n\n\t* plot/hist.m: Compute histogram correctly for n>=30.\n\n2004-03-02  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* signal/sinc.m: Use i(:) instead of i when checking for any nonzeros.\n\n2004-03-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/horzcat.m: Delete.\n\t* miscellaneous/vertcat.m: Delete.\n\n2004-02-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/figure.m: Also look for GNUTERM in the environment and use\n\tthat if it is set (for OS X).  From Per Persson <persquare@mac.com>.\n\n2004-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/base/__stepimp__.m: Only call clearplot if we will be\n\tdoing multiple plots in the same gnuplot frame.\n\n2004-02-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/system/__sysconcat__.m, control/system/__tfl__.m,\n\tcontrol/system/cellidx.m, control/system/ss.m,\n\tcontrol/system/tf.m, control/system/zp.m: New functions.\n\n2004-02-16  Glenn Golden  <gdg@zplane.com>\n\n\t* statistics/distributions/discrete_inv.m:\n\tReduce memory requirements.\n\n2004-02-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__errcomm__.m: Fix thinko in previous change.\n\tFrom Teemu Ikonen  <tpikonen@pcu.helsinki.fi>.\n\n2004-02-16  A S Hodel  <a.s.hodel@Eng.Auburn.EDU>\n\n\t* control/base/__bodquist__.m, control/base/__stepimp__.m,\n\tcontrol/base/analdemo.m, control/base/bddemo.m,\n\tcontrol/base/bode.m, control/base/dre.m, control/base/frdemo.m,\n\tcontrol/base/lqg.m, control/base/nyquist.m, control/base/place.m,\n\tcontrol/base/rldemo.m, control/base/rlocus.m,\n\tcontrol/base/tzero.m, control/hinf/dgkfdemo.m,\n\tcontrol/hinf/dhinfdemo.m, control/hinf/h2syn.m,\n\tcontrol/hinf/hinf_ctr.m, control/hinf/hinfsyn.m,\n\tcontrol/hinf/wgt1o.m, control/obsolete/dlqg.m,\n\tcontrol/obsolete/packsys.m, control/obsolete/series.m,\n\tcontrol/system/__sysdefioname__.m,\n\tcontrol/system/__sysdefstname__.m, control/system/__sysgroupn__.m,\n\tcontrol/system/__tf2sysl__.m, control/system/buildssic.m,\n\tcontrol/system/c2d.m, control/system/d2c.m,\n\tcontrol/system/dmr2d.m, control/system/fir2sys.m,\n\tcontrol/system/is_signal_list.m, control/system/is_siso.m,\n\tcontrol/system/jet707.m, control/system/listidx.m,\n\tcontrol/system/moddemo.m, control/system/ord2.m,\n\tcontrol/system/packedform.m, control/system/parallel.m,\n\tcontrol/system/ss2sys.m, control/system/sys2tf.m,\n\tcontrol/system/sys2zp.m, control/system/sysadd.m,\n\tcontrol/system/sysappend.m, control/system/sysconnect.m,\n\tcontrol/system/syscont.m, control/system/sysdimensions.m,\n\tcontrol/system/sysdisc.m, control/system/sysdup.m,\n\tcontrol/system/sysgetsignals.m, control/system/sysgettype.m,\n\tcontrol/system/sysgroup.m, control/system/sysmin.m,\n\tcontrol/system/sysmult.m, control/system/sysprune.m,\n\tcontrol/system/sysrepdemo.m, control/system/sysscale.m,\n\tcontrol/system/syssetsignals.m, control/system/syssub.m,\n\tcontrol/system/sysupdate.m, control/system/tf2sys.m,\n\tcontrol/system/ugain.m, control/system/zp2ss.m,\n\tcontrol/system/zp2sys.m, control/util/__outlist__.m,\n\tcontrol/util/__zgpbal__.m, control/util/strappend.m:\n\tUse cell arrays instead of lists.\n\n2004-01-23  Stefan van der Walt  <stefan@sun.ac.za>\n\n\t* plot/bar.m: Increase size of cutoff vector from xlen-1 to xlen\n\tso that bar (1, 1) will work.\n\n2004-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__errcomm__.m: Cope with nargin now being a function.\n\t* plot/__errplot__.m: Likewise.\n\t* plot/__plt__.m: Likewise.\n\t* plot/plot_border.m: Likewise.\n\n\t* Makefile.in (distclean, maintainer-clean): Remove DOCSTRINGS,\n\tnot $(DOCSTRINGS).\n\n2004-01-21  Quentin Spencer  <qspencer@ieee.org>\n\n\t* linear-algebra/rank.m: Allow rank ([]) to return 0, same as\n\trank ([], tol).\n\n2004-01-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* elfun/acot.m: Return atan (1./z).\n\tFrom Gregory Vanuxem <g.vanuxem@wanadoo.fr>.\n\n\t* miscellaneous/dir.m: New file.\n\n\t* general/num2str.m: Use \"%d\" as format if values are ints with\n\tmagnitude less than 1e10.\n\n2004-01-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/num2str.m: If single arg is string, return it.\n\n\t* miscellaneous/not.m: New file.\n\n\t* miscellaneous/unix.m: New file.\n\n\t* miscellaneous/isunix.m: New file.\n\t* miscellaneous/ispc.m: New file.\n\n\t* miscellaneous/computer.m: New file.\n\n\t* miscellaneous/delete.m: New file.\n\n2004-01-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/tests/kolmogorov_smirnov_test_2.m: Fix test for ties.\n\n2004-01-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/path.m: Handle DEFAULT_LOADPATH substitution.\n\tAlways return substituted version of LOADPATH if nargout != 0.\n\n2003-12-21  Schloegl Alois  <alois.schloegl@tugraz.at>\n\n\t* miscellaneous/fullfile.m: If filename is empty, set it to \".\"\n\tbefore continuing.\n\n\t* miscellaneous/fileparts.m: Allow name to start with \".\".\n\n2003-12-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/ind2sub.m: New file.\n\t* general/sub2ind.m: New file.\n\n2003-12-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/system/zp2ss.m: Don't save and restore\n\twarn_empty_list_elements.\n\n2003-12-15  Gabriele Pannocchia  <g.pannocchia@ing.unipi.it>\n\n\t* control/system/zp2ss.m: Correct definition of pure gain system.\n\n2003-12-10  Quentin Spencer  <qspencer@ieee.org>\n\n\t* statistics/base/mean.m: Remove special case for row vectors.\n\n2003-11-19  Quentin Spencer  <qspencer@ieee.org>\n\n\t* signal/freqz_plot.m: Save and restore automatic_replot too.\n\n2003-11-18  Danilo Piazzalunga  <danilopiazza@libero.it>\n\n\t* statistics/base/iqr.m: Handle matrices.\n\n2003-11-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/issymmetric.m: Don't fail if norm (x) == 0.\n\n2003-11-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/path.m: Fix thinko in previous change.\n\n2003-11-14  Gabriele Pannocchia  <g.pannocchia@ing.unipi.it>\n\n\t* control/base/dare.m: Check positive (semi)definiteness and\n\tdimensions of r (and q).\n\t* control/base/dlqr.m: Check stabilizability of (A,B),\n\tdetectability of (A,Q), and whether (A,Q) has non minimal modes\n\tnear unit circle.\n\n\t* control/system/is_detectable.m: Use Hautus Lemma.\n\tCorrect the behavior for discrete-time systems.\n\t* control/system/is_stabilizable.m: Likewise.\n\n\t* linear-algebra/krylov.m: Return H = [] in Vnrm == 0 case.\n\n\t* linear-algebra/krylovb.m: Fix typo in usage message.\n\n\t* general/isdefinite.m: New function.\n\n2003-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/reshape: Delete.\n\n2003-10-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/numel.m: Delete.\n\n2003-10-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/horzcat.m, miscellaneous/vartcat.m: New files.\n\n\t* deprecated/isstr.m: New file.\n\n2003-10-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__axis_label__.m, plot/xlabel.m, plot/ylabel.m,\n\tplot/zlabel.m, plot/title.m: Return a value if nargout > 0.\n\n2003-10-02  Quentin Spencer  <qspencer@ieee.org>\n\n\t* statistics/base/mean.m: Fix missing semicolon problem.\n\n2003-09-08  Al Niessner  <Al.Niessner@jpl.nasa.gov>\n\n\t* plot/subplot.m: New global variable, __multiplot_scale__.\n\n2003-08-29  David Castelow  <DCastelow@Airspan.com>\n\n\t* strings/dec2base.m, strings/dec2bin.m, strings/dec2hex.m:\n\tAllow optional length argument.\n\n2003-08-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* polynomial/polyfit.m: Avoid calling flipud.\n\tFrom Pascal A. Dupuis <Pascal.Dupuis@esat.kuleuven.ac.be>.\n\tReturn structure as second output value for improved Matlab\n\tcompatibility.\n\n2003-07-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/cond.m: Behave as though old built-in variable\n\tpropagate_empty_matrices is always 1.  Also handle empty matrices\n\twith one non-zero dimension.\n\n\t* miscellaneous/dump_prefs.m: Add warn_separator_insert and\n\twarn_single_quote_string to the list.\n\tDelete whitespace_in_literal_matrix and propagate_empty_matrices\n\tfrom the list.\n\n2003-07-25  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* signal/autocov.m: Transpose result of conj because diag returns\n\ta column vector, not a row vector.\n\n\t* audio/playaudio.m, audio/record.m, image/image.m,\n\tmiscellaneous/bug_report.m: Protect spaces in filenames\n\twith quotes.\n\n2003-07-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* io/printf.m, io/puts.m: Delete.\n\n\t* miscellaneous/dump_prefs.m: Delete define_all_return_values and\n\tdefault_return_value from the list.\n\tAdd warn_undefined_return_values to the list.\n\n\n2003-07-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/dump_prefs.m: Delete default_global_variable_value\n\tand initialize_global_variables from the list.\n\n2003-07-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/colormap.m: Don't save and restore default_eval_print_flag.\n\n\t* miscellaneous/dump_prefs.m: Delete default_eval_print_flag.\n\n\t* control/util/zgshsr.m: Use x OP= y instead of x = x OP y.\n\t* control/system/sys2fir.m: Likewise.\n\n\t* control/system/is_siso.m: Use && instead of & where appropriate.\n\t* control/system/__tf2sysl__.m: Likewise.\n\n\t* control/system/__tf2sysl__.m: Use end instead of length(X).\n\n\t* control/freqchkw.m: Use %-escapes for error instead of num2str\n\tand [] concatenation.\n\t* control/system/sys2fir.m: Likewise.\n\n\t* control/base/dgram.m, control/base/freqchkw.m,\n\tcontrol/base/gram.m, control/system/__abcddims__.m,\n\tcontrol/system/__sysdefstname__.m, control/system/__tf2sysl__.m,\n\tcontrol/system/is_sample.m, control/system/is_signal_list.m,\n\tcontrol/system/is_siso.m, control/system/sys2fir.m,\n\tcontrol/system/syschtsam.m, control/system/sysgettsam.m,\n\tcontrol/system/sysgettype.m, control/system/tf2zp.m,\n\tcontrol/system/ugain.m, control/util/prompt.m,\n\tcontrol/util/run_cmd.m, control/util/zgrownorm.m,\n\tcontrol/util/zgshsr.m:\n\tImprove conformance to Octave coding style.\n\n\t* miscellaneous/dump_prefs.m: Add warn_resize_on_reange_error to\n\tthe list.\n\tDelete resize_on_range_error from the list.\n\n\t* control/base/pzmap.m, control/base/place.m,\n\tcontrol/base/__freqresp__.m, control/system/sysappend.m,\n\tcontrol/system/syscont.m, control/system/sysdisc.m,\n\tcontrol/system/sysgroup.m, control/system/tfout.m,\n\tcontrol/system/zp2ss.m, control/system/zpout.m,\n\tcontrol/util/__outlist__.m, signal/arma_rnd.m, general/shift.m,\n\tstrings/strcat.m: Save and restore warn_empty_list_elements, not\n\tempty_list_elements_ok.\n\n\t* miscellaneous/dump_prefs.m: Add warn_empty_list_elements to the list.\n\tDelete empty_list_elements_ok from the list.\n\n2003-07-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/dump_prefs.m: Include warn_neg_dim_as_zero in the\n\tlist.\n\tDelete treat_neg_dim_as_zero from the list.\n\n\t* strings/blanks.m: Don't check treat_neg_dim_as_zero.\n\n2003-07-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/reshape.m: Omit do_fortran_indexing from doc string (it\n\twas not used in the code in any case).\n\n\t* strings/strjust.m: Temporarily set warn_fortran_indexing, not\n\tdo_fortran_indexing.\n\n\t* statistics/base/moment.m: Temporarily set warn_str_to_num, not\n\timplict_str_to_num_ok.  Use unwind_protect block to do it.\n\n\t* miscellaneous/dump_prefs.m: Include DEFAULT_EXEC_PATH,\n\tDEFAULT_LOAD_PATH, crash_dumps_octave_core,\n\tsighup_dumps_octave_core, sigterm_dumps_octave_core,\n\twarn_imag_to_real, warn_num_to_str, warn_str_to_num, and\n\twarn_fortran_indexing in the list.\n\tDelete ok_to_lose_imaginary_part, implicit_num_to_str_ok,\n\timplicit_str_to_num_ok, do_fortran_indexing, and\n\tprefer_column_vectors from list.\n\n2003-07-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (distclean, maintainer-clean): Also remove\n\tgethelp$(BUILD_EXEEXT), $(DOCSTRINGS), and autom4te.cache\n\tdirectory.\n\n2003-06-17  Aaron A. King  <king@quercus.tiem.utk.edu>\n\n\t* plot/hist.m: Don't forget to define n if x is a vector.\n\n2003-06-13  Alois Schloegl  <alois.schloegl@tugraz.at>\n\n\t* miscellaneous/fileparts.m: For compatibility with Matlab,\n\treturn \".\" with extension.\n\n2003-06-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/base/__stepimp__.m, control/base/nichols.m,\n\tcontrol/base/nyquist.m, miscellaneous/dump_prefs.m,\n\tplot/bottom_title.m, plot/mplot.m, plot/multiplot.m,\n\tplot/oneplot.m, plot/plot_border.m, plot/subplot.m,\n\tplot/subwindow.m, plot/top_title.m, signal/freqz_plot.m:\n\tEliminate gnuplot_has_multiplot (assume it is always true).\n\n2003-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in, image/Makefile.in, startup/Makefile.in: Handle DESTDIR.\n\n2003-05-05  Andy Adler  <adler@site.uottawa.ca>\n\n\t* plot/hist.m: Improve performance by using different algorithms\n\tdepending on number of bins.\n\n2003-05-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/system/sysadd.m: If systems are not \"tf\", convert before\n\tadding.\n\n2003-05-01  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* image/imagesc.m: Accept data limits parameter for colormap.\n\n2003-04-11  Doug Stewart  <dastew@sympatico.ca>\n\n\t* control/base/__stepimp__.m: If digital impulse, reduce gain of\n\tthe impulse by t_step.\n\n2003-04-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/base/__bodquist__.m: Don't convert pdbig and fdbig to\n\tcolumn vectors.\n\n2003-03-24  Quentin Spencer  <qspencer@ieee.org>\n\n\t* linear-algebra/null.m: Handle empty matrix arg.\n\n2003-03-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/shift.m: Force empty_list_elements_ok to 1.\n\n2003-02-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* deprecated/struct_contains.m, deprecated/struct_elements.m:\n\tNew files.\n\n2003-02-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/tests/kolmogorov_smirnov_test.m: Use str2func to make\n\tfunction handle to pass to feval.\n\t* statistics/base/qqplot.m: Likewise.\n\t* statistics/base/ppplot.m: Likewise.\n\t* signal/spectral_xdf.m: Likewise.\n\t* signal/spectral_adf.m: Likewise.\n\n2003-02-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/axis.m: Avoid whitespace in literal matrix problem.\n\n2003-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/logm.m: New file.\n\n2003-02-18  David Bateman  <dbateman@free.fr>\n\n \t* mkpkgadd: Scan C++ files as well\n\n2003-02-13  Alois Schloegl  <alois.schloegl@tugraz.at>\n\n\t* strings/findstr.m: Return empty set for zero-length target.\n\n2003-02-11  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* set/union.m: Preserve the orientation of inputs.\n\n2003-01-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/int2str.m: Eliminate leading spaces.\n\n2003-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/int2str.m: Do a better job with 0, Inf, and NaN,\n\n2003-01-11  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Makefile.in (gethelp$(BUILD_EXEEXT)): Pass $(BUILD_CXXFLAGS) and\n\t$(BUILD_LDFLAGS) to compiler.\n\n2003-01-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/num2str.m: Don't specify field width for scalars.\n\n2003-01-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DISTFILES): Don't forget mkpkgadd.\n\n2003-01-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* gethelp.cc: Define __USE_STD_IOSTREAM if using Compaq C++.\n\n\t* miscellaneous/tempname.m: New file.\n\n\t* miscellaneous/tempdir.m: New file.\n\n\t* miscellaneous/fullfile.m: New file.\n\n2003-01-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/fileparts.m: New file.\n\n\t* io/beep.m: New file.\n\n\t* plot/__pltopt1__.m: Call undo_string_escapes for title part of\n\tformat only.\n\n2003-01-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/strcmp.m: Handle cell arrays of strings.\n\n2002-12-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/int2str.m: Handle matrices.\n\t* general/num2str.m: Likewise.\n\tAlso handle optional precision, and format args.\n\n2002-12-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* audio/Makefile.in, control/base/Makefile.in,\n\tcontrol/hinf/Makefile.in, control/obsolete/Makefile.in,\n\tcontrol/system/Makefile.in, elfun/Makefile.in,\n\tfinance/Makefile.in, general/Makefile.in, image/Makefile.in,\n\tio/Makefile.in, linear-algebra/Makefile.in,\n\tmiscellaneous/Makefile.in, polynomial/Makefile.in,\n\tquaternion/Makefile.in, set/Makefile.in, signal/Makefile.in,\n\tspecfun/Makefile.in, special-matrix/Makefile.in,\n\tstatistics/base/Makefile.in, statistics/distributions/Makefile.in,\n\tstatistics/models/Makefile.in, statistics/tests/Makefile.in,\n\tstrings/Makefile.in, time/Makefile.in, plot/Makefile.in,\n\tdeprecated/Makefile.in: Use new do-script-install and\n\tdo-script-uninstall macros.\n\n\t* mkpkgadd: New script.\n\n\t* plot/close.m: New file.\n\n2002-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/image.m: Use -raw option for xv.\n\tFrom Remy Bruno <remy.bruno@libertysurf.fr>\n\n2002-11-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/base/lsim.m: Use approximate test for step size change.\n\n\t* signal/bartlett.m: Avoid row/column mismatch error.\n\n2002-11-12  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* statistics/base/var.m: Use better formula for improved accuracy.\n\n2002-11-04  Nicholas Piper  <nick-octave@nickpiper.co.uk>\n\n\t* control/base/lsim.m: Correct doc string.\n\n2002-11-04  A S Hodel  <a.s.hodel@Eng.Auburn.EDU>\n\n\t* control/system/syssub.m: Call tf2sys with Gnum-Hnum, not Gnum+Hnum.\n\n2002-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/contour.m: Handle x and y as matrices too.\n\n2002-11-01  Joseph P. Skudlarek  <jskud@jskud.com>\n\n\t* plot/contour.m: Fix error and usage messages.\n\n2002-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/contour.m: Correct orientation of plot.\n\n2002-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/base/analdemo.m: Fix typo.\n\n2002-10-31  Francesco Potorti`  <pot@gnu.org>\n\n\t* statistics/distributions/discrete_pdf.m: Fix typo.\n\n2002-10-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkdoc: Exit immediately on errors.\n\tExit with error if gethelp does not exist.\n\n\t* Makefile.in: Use $(BUILD_EXEEXT) as appropriate.\n\n2002-10-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (gethelp): Use $(BUILD_CXX), not $(CXX).\n\n2002-09-27  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* statistics/distributions/normal_cdf.m: Handle variance == 0.\n\t* statistics/distributions/normal_pdf.m: Likewise.\n\t* statistics/distributions/normal_inv.m: Likewise.\n\n2002-09-27  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* specfun/erfinv.m: Return NaN for NaN inputs.\n\n2002-09-26  Jeff Cunningham  <jeffrey@cunningham.net>\n\n\t* statistics/base/var.m: Handle complex values.\n\n2002-08-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_CONFIG_FILES): Add deprecated/Makefile to the\n\tlist.\n\t* deprecated/Makefile.in: New file.\n\n2002-08-09  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* statistics/distributions/beta_cdf.m: Replace betai with betainc.\n\t* statistics/distributions/binomial_cdf.m: Likewise.\n\t* statistics/distributions/f_cdf.m: Likewise.\n\t* statistics/distributions/t_cdf.m: Likewise.\n\n\t* miscellaneous/bincoeff.m: Replace lgamma with gammaln.\n\t* specfun/beta.m: Likewise.\n\t* special-matrix/invhilb.m: Likewise (but it is only in a comment).\n\t* statistics/distributions/gamma_pdf.m: Likewise.\n\t* statistics/distributions/poisson_pdf.m: Likewise.\n\n\t* statistics/distributions/gamma_cdf.m: replace gammai with gammainc\n\t* statistics/distributions/poisson_cdf.m: Likewise.\n\n2002-08-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* deprecated/is_bool.m: New file.\n\t* deprecated/is_complex.m: New file.\n\t* deprecated/is_global.m: New file.\n\t* deprecated/is_list.m: New file.\n\t* deprecated/is_matrix.m: New file.\n\t* deprecated/is_scalar.m: New file.\n\t* deprecated/is_square.m: New file.\n\t* deprecated/is_stream.m: New file.\n\t* deprecated/is_struct.m: New file.\n\t* deprecated/is_symmetric.m: New file.\n\t* deprecated/is_vector.m: New file.\n\t* Change all callers of these functions to use the new names.\n\n\t* deprecated: New directory.\n\t* Makefile.in (SUBDIRS): Add it to the list.\n\n\t* general/isscalar.m: Rename from is_scalar.m.\n\t* general/issquare.m: Rename from is_square.m.\n\t* general/issymmetric.m: Rename from is_symmetric.m.\n\t* general/isvector.m: Rename from is_vector.m.\n\n2002-08-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/base/mean.m: Allow empty matrices.\n\tHandle DIM arg.\n\n2002-08-05  Teemu Ikonen  <tpikonen@pcu.helsinki.fi>\n\n\t* plot/__errcomm__.m: If format is not specified, default to error\n\tbar format.\n\n2002-08-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/popen2.m: Use F_SETFL and O_NONBLOCK, not\n\t__F_SETFL__ and __O_NONBLOCK__.\n\n\t* image/saveimage.m: Use OCTAVE_VERSION, not __OCTAVE_VERSION__.\n\t* miscellaneous/bug_report.m: Likewise.\n\n2002-07-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/mod.m: Use isreal (x), not any (any (imag (x))).\n\t* general/rem.m: Likewise.\n\n\t* plot/loglogerr.m: Use varargin instead of old style varargs.\n\t* plot/semilogxerr.m: Likewise.\n\t* plot/semilogyerr.m: Likewise.\n\n2002-07-25  Teemu Ikonen  <tpikonen@pcu.helsinki.fi>\n\n\t* plot/__errcomm__.m: New file.  Common functionality for error plots.\n\t* plot/loglogerr.m: New file.  Double logarithm plots with errorbars.\n\t* plot/semilogxerr.m: New file.  Semilogarithm plots with errorbars.\n\t* plot/semilogyerr.m: New file.  Semilogarithm plots with errorbars\n\n\t* plot/errorbar.m: Use __errcomm__.m.\n\t* plot/__errplot__.m: Minor cleanups.\n\t* plot/__pltopt__.m: Handle boxxyerrorbars plot style.\n\t* plot/__pltopt1__.m: Likewise.\n\n2002-07-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/rem.m: Delete redundant call to usage.\n\n\t* general/mod.m: Additional error checks, Texinfoize doc string.\n\n2002-04-29  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* general/mod.m: New function.\n\n2002-07-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/system/sysmult.m: Use varargin instead of old style varargs.\n\t* control/system/sysadd.m: Likewise.\n\t* control/system/sysgroup.m: Likewise.\n\t* control/system/syssub.m: Likewise.\n\t* elfun/gcd.m: Likewise.\n\t* elfun/lcm.m: Likewise.\n\t* general/common_size.m: Likewise.\n\t* io/printf.m: Likewise.\n\t* miscellaneous/menu.m: Likewise.\n\t* miscellaneous/path.m: Likewise.\n\t* plot/__errplot__.m: Likewise.\n\t* plot/__plt__.m: Likewise.\n\t* plot/axis.m: Likewise.\n\t* plot/errorbar.m: Likewise.\n\t* plot/mplot.m: Likewise.\n\t* plot/loglog.m: Likewise.\n\t* plot/plot.m: Likewise.\n\t* plot/plot_border.m: Likewise.\n\t* plot/semilogx.m: Likewise.\n\t* plot/semilogy.m: Likewise.\n\t* plot/xlabel.m: Likewise.\n\t* plot/ylabel.m: Likewise.\n\t* plot/zlabel.m: Likewise.\n\t* statistics/base/ppplot.m: Likewise.\n\t* statistics/base/qqplot.m: Likewise.\n\t* statistics/tests/bartlett_test.m: Likewise.\n\t* statistics/tests/kolmogorov_smirnov_test.m: Likewise.\n\t* statistics/tests/kruskal_wallis_test.m: Likewise.\n\t* strings/str2mat.m: Likewise.\n\t* strings/strcat.m: Likewise.\n\n2002-06-27  Paul Kienzle  <pkienzle@jazz.ncnr.nist.gov>\n\n\t* statistics/distributions/gamma_pdf.m: Avoid overflow in more cases.\n\n2002-05-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* skip-autoheader: New file, for autogen.sh.\n\t* Makefile.in (DISTFILES): Add it to the list.\n\n2002-04-29  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* general/repmat.m: New function.\n\n2002-04-25  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* audio/lin2mu.m: Accept matrices and [-1,1] normalized audio.\n\tUse optional parameter to specify the number of bits in the input.\n\t* audio/mu2lin.m: Accept matrices, return n-bit integers or\n\tfloats in the range [-1,1], 2x speedup.\n\n\t* strings/index.m, strings/rindex.m: Vectorize for speed.\n\n2002-04-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/kron.m: Delete.\n\n2002-04-24  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* signal/freqz.m: If nargout is zero, plot results instead of\n\treturning them.\n\t* signal/freqz_plot.m: New file.\n\n2002-04-24  Bill Lash  <lash@tellabs.com>\n\n\t* signal/unwrap.m: New file.\n\n2002-04-23  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* image/rgb2hsv.m: Faster, more accurate, remove the\n\tdivide by zero warning.\n\n2002-04-09  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* strings/deblank.m: Trim \\0 as well as blank.\n\n\t* freqz.m: Evaluate a specific range of frequencies\n\texpressed in radians or Hz relative to a supplied sample rate.\n\n2002-04-04  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* signal/fftfilt.m: Filter columns if called with a matrix.\n\n\t* strings/findstr.m: Vectorize as much as possible.\n\n2002-04-04  Dirk Laurie  <dirk@calvyn.puk.ac.za>\n\n\t* special-matrix/invhilb.m: New version that is faster and more\n\taccurate.\n\n2002-04-03  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\t* configure.in: Update for autoconf 2.5x.\n\n2002-04-03  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* special-matrix/vander.m: Code tidy and vectorize.\n\n2002-04-02  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* linear-algebra/cross.m: Accept nx3 and 3xn matrices, in addition\n\tto vectors.  Issue a warning in the case x matches y' but return a\n\tcolumn vector as Octave currently does.\n\n\t* plot/contour.m: Set default number of levels for contour(x,y,z).\n\n\t* control/system/starp.m: Leave more of the documentation\n\tprocessing to texinfo and less to the @format block.\n\n\t* image/imagesc.m: Only display image if no output is requested.\n\tCode tidying.\n\n2002-03-07  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n \t* statistics/base/center.m: Accept and return empty matrix.\n\n2002-02-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/erfinv.m: Fix usage message.\n\n2002-02-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* elfun/coth.m: Use 1 ./ tanh(z) instead of cosh(z) ./ sinh(z).\n\tFrom \"Michael O'Brien\" <mobrien@kento.unm.edu>.\n\n2001-06-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/distributions/discrete_cdf.m: Downcase incorrectly\n\tcapitalized variable names.\n\n2001-05-30  Jean-Francois Cardoso  <cardoso@tsi.enst.fr>\n\n\t* m/image/saveimage.m: fix saving an image to Postscript format.\n\n2001-04-18  A. Scottedward Hodel  <a.s.hodel@eng.auburn.edu>\n\n\t* control/system/is_stabilizable.m: Pass a to sys2ss, not sys.\n\n2001-02-28  Kai Habel  <kai.habel@gmx.de>\n\n\t* general/cart2pol.m: New file.\n\t* general/pol2cart.m: New file.\n\t* general/cart2sph.m: New file.\n\t* general/sph2cart.m: New file.\n\t* image/rgb2hsv.m: New file.\n\t* image/hsv2rgb.m: New file.\n\n2001-02-26  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* plot/meshgrid.m: Avoid for loops.\n\t* plot/meshdom.m: Likewise.\n\n2001-02-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/norm.m: Use sqrt instead of ^0.5.\n\n2001-02-22  Heinz Bauschke  <bauschke@cecm.sfu.ca>\n\n\t* linear-algebra/norm.m: Use more efficient method for Frobenius\n\tnorm.\n\n2001-02-09  David Livings  <david.livings@asa.co.uk>\n\n\t* statistics/tests/welch_test.m: Fix typo.\n\n\t* statistics/distributions/chisquare_cdf.m:\n\tDon't restrict inputs to be only positive integers.\n\t* statistics/distributions/chisquare_inv.m: Likewise.\n\t* statistics/distributions/chisquare_pdf.m: Likewise.\n\t* statistics/distributions/chisquare_rnd.m: Likewise.\n\t* statistics/distributions/f_cdf.m: Likewise.\n\t* statistics/distributions/f_inv.m: Likewise.\n\t* statistics/distributions/f_pdf.m: Likewise.\n\t* statistics/distributions/f_rnd.m: Likewise.\n\t* statistics/distributions/t_cdf.m: Likewise.\n\t* statistics/distributions/t_inv.m: Likewise.\n\t* statistics/distributions/t_pdf.m: Likewise.\n\t* statistics/distributions/t_rnd.m: Likewise.\n\n2001-02-08  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* strings/dec2base.m: New file.\n\t* strings/base2dec.m: New file.\n\t* strings/strjust.m: New file.\n\t* strings/dec2hex.m: Replace with version that just calls 2dec2base.\n\t* strings/dec2bin.m: Likewise.\n\t* strings/hex2dec.m: Replace with version that just calls base2dec.\n\t* strings/bin2dec.m: Likewise.\n\n2001-02-07  David Livings  <david.livings@asa.co.uk>\n\n\t* statistics/base/ppplot.m: Use gset, not set.\n\t* statistics/base/qqplot.m: Likewise.\n\n2001-02-05  Ondrej Popp  <ondrej@geocities.com>\n\n\t* control/system/c2d.m: Add missing endif.\n\n2000-12-15  Teemu Ikonen  <tpikonen@pcu.helsinki.fi>\n\n\t* strings/index.m: Return 0 if either string is empty.\n\n2000-12-15  Ben Sapp  <bsapp@lanl.gov>\n\n\t* control/system/c2d.m: Allow option of matched pole/zero\n\tequivalent for conversion.\n\n2000-12-15  Matthew W. Roberts  <matt@lehi.tamu.edu>\n\n\t* strings/findstr.m: Return empty matrix if search string is empty.\n\n2000-12-15  Kai Habel  <kai.habel@gmx.de>\n\n\t* saveimage.m: Do create rawbit image for black and white images,\n\tbut do it correctly.\n\n2000-12-13   Teemu Ikonen  <tpikonen@pcu.helsinki.fi>\n\n\t* polynomial/deconv.m: For compatibility with Matlab, don't reduce\n\tresult polynomials.\n\n2000-12-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/saveimage.m: Don't try to create rawbit image.\n\n2000-11-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (bin-dist): Pass -C to $(MAKE), not -c.\n\n2000-11-16  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* plot/contour.m: Reorder args for Matlab compatibility.\n\n2000-10-27  Mats Jansson  <mats.e.jansson@home.se>\n\n\t* set/create_set.m: Avoid empty matrix in matrix list warning.\n\n2000-09-08  Teemu Ikonen  <tpikonen@pcu.helsinki.fi>\n\n\t* plot/errorbar.m, plot/__errplot__.m: New functions.\n\n\t* plot/mesh.m: Also set nologscale before plotting.\n\t* plot/__pltopt1__.m: Handle xerrorbars, yerrorbars, and\n\txyerrorbars instead of just errorbars.\n\n2000-08-25  Thomas Walter  <walter@pctc.chemie.uni-erlangen.de>\n\n\t* image/image.m: Try display (from ImageMagick) first.\n\n2000-08-01  Rolf Fabian  <fabian@tu-cottbus.de>\n\n\t* plot/meshgrid.m: Use transpose to reorient vectors, not complex\n\tconjugate transpose.\n\n2000-07-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/str2mat.m: Apply setstr to each argument.\n\n2000-07-17  Gabriele Pannocchia  <pannocchia@ing.unipi.it>\n\n\t* control/base/dkalman.m: New file.\n\t* control/base/dlqe.m: Handle singular A matrix.\n\t* control/base/dlqr.m: Likewise.\n\n2000-07-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/strcmp.m: Return 0 instead of an error if row and column\n\tdimensions don't match.\n\n2000-06-30  Kai Habel  <kahacjde@calvados.zrz.TU-Berlin.DE>\n\n\t* plot/hist.m: Allow 3 argument form to work.\n\n2000-06-27  Matthew W. Roberts  <matt@lehi.tamu.edu>\n\n\t* plot/plot.m: Add examples in doc string.\n\n2000-06-08  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* control/base/__stepimp__.m: Reset multiplot state when done.\n\tDo the right thing even if automatic_replot is not zero.\n\tAvoid failure if system has pure imaginary poles.\n\n2000-06-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/logical.m: Return arg if it is empty.  Better error\n\tmessage for non-numeric types.\n\n2000-05-31  A. Scottedward Hodel  <a.s.hodel@eng.auburn.edu>\n\n\t* control/base/dlqe.m: Update documentation.  Fix typo.  Warn\n\tabout difference with Matlab dlqe function.\n\n\t* control/system/sysmult.m: Fix typo in argument dimensions checking.\n\n2000-05-24  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* strings/strrep.m: Fix typo.\n\n2000-05-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/strrep.m: Don't transpose result for case of jump > 0.\n\n2000-05-13  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* strings/strrep.m: Avoid for loop for speed.\n\t* plot/axis.m: Handle string options for Matlab compatibility.\n\n2000-04-04  John Smith  <john@arrows.demon.co.uk>\n\n\t* statistics/distributions/beta_inv.m: Provide better(?) initial\n\tguess for iteration.\n\n2000-03-31   Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* image/image.m: Allow image (A) or image (x, y, A).\n\t* image/imagesc.m: Likewise.\n\n\t* image/image.m: If zoom is not supplied, or if it is an empty\n\tmatrix, autoscale the image.\n\n2000-03-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/title.m, plot/bottom_title.m, plot/top_title.m:\n\tUndo string escapes in text twice(!) before sending to gnuplot.\n\n\t* image/saveimage.m: Add comment to file saying who created it and\n\twhen it was created.  Suggested by Stephen Eglen\n\t<stephen@cogsci.ed.ac.uk>.\n\n2000-03-21  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* polynomial/polyreduce.m: Simplify by looking for the first\n\tnon-zero element rather than the last of the first set of zero\n\telements.\n\n\t* plot/__pltopt1__.m: Accept \"--\", \"-.\", and \":\" line styles.\n\n2000-03-21  Kai Habel  <kahacjde@calvados.zrz.TU-Berlin.DE>\n\n\t* image/saveimage.m: Swap black and white colormaps so zero is\n\tdisplayed as black and 1 is displayed as white.\n\tFix indexing bug in ppm case.\n\n2000-03-06  Stephen Eglen  <stephen@anc.ed.ac.uk>\n\n\t* statistics/tests/kolmogorov_smirnov_test_2.m: Account for ties\n\tbetween the two distributions (took same approach as ks.test() in R.)\n\n2000-02-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/base/bode.m: Temporarily disable automatic_replot.\n\n2000-02-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (clean): Also remove gethelp.\n\n\t* specfun/erfinv.m: Use z_new in convergence test, not z_old.\n\n2000-02-11  Georg Thimm  <mgeorg@SGraphicsWS1.mpe.ntu.edu.sg>\n\n\t* set/create_set.m: Use find to avoid while loop.\n\n2000-02-11  Stephen Eglen  <stephen@cogsci.ed.ac.uk>\n\n\t* plot/hist.m: New optional third argument.\n\n2000-02-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/bug_report.m: Use octave-bug script with version\n\tnumber appended.\n\n2000-02-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* gethelp.cc: Sprinkle with std:: qualifier.\n\n2000-01-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/saveimage.m: Delete some debugging code.\n\n2000-01-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* signal/sinc.m: Avoid reshaping.\n\n\t* image/rgb2ind.m: No longer needs to reset do_fortran_indexing.\n\t* image/ind2rgb.m: Ditto.\n\t* image/ind2gray.m: Ditto.\n\t* general/reshape.m: Ditto.  Also no longer needs to reset\n\timplicit_str_to_num_ok.\n\n2000-01-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/popen2.m: Deal with the fact that pipe now returns\n\ta list of file structures, not a vector of numeric file ids.\n\n2000-01-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__axis_label__.m: New function.\n\tUndo string escapes in text twice(!) before sending to gnuplot.\n\t* plot/xlabel.m: Use it.\n\t* plot/ylabel.m: Ditto.\n\t* plot/zlabel.m: Ditto.\n\n\t* plot/mesh.m: Fix error message to reflect reality.\n\n2000-01-24  Cyril Humbert  <humbert@phobos.univ-mlv.fr>\n\n\t* statistics/distributions/weibull_pdf.m: Use correct formula.\n\n2000-01-22  Michael Reifenberger  <mike@Plaut.de>\n\n\t* audio/saveaudio.m: Also accept files with .ul extension.\n\t* audio/loadaudio.m: Ditto.\n\t* audio/playaudio.m: Ditto.\n\n2000-01-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/distributions/beta_cdf.m: Texinfoize doc string.\n\t* statistics/distributions/beta_inv.m: Ditto.\n\t* statistics/distributions/beta_pdf.m: Ditto.\n\t* statistics/distributions/beta_rnd.m: Ditto.\n\t* statistics/distributions/binomial_cdf.m: Ditto.\n\t* statistics/distributions/binomial_inv.m: Ditto.\n\t* statistics/distributions/binomial_pdf.m: Ditto.\n\t* statistics/distributions/binomial_rnd.m: Ditto.\n\t* statistics/distributions/cauchy_cdf.m: Ditto.\n\t* statistics/distributions/cauchy_inv.m: Ditto.\n\t* statistics/distributions/cauchy_pdf.m: Ditto.\n\t* statistics/distributions/cauchy_rnd.m: Ditto.\n\t* statistics/distributions/chisquare_cdf.m: Ditto.\n\t* statistics/distributions/chisquare_inv.m: Ditto.\n\t* statistics/distributions/chisquare_pdf.m: Ditto.\n\t* statistics/distributions/chisquare_rnd.m: Ditto.\n\t* statistics/distributions/discrete_cdf.m: Ditto.\n\t* statistics/distributions/discrete_inv.m: Ditto.\n\t* statistics/distributions/discrete_pdf.m: Ditto.\n\t* statistics/distributions/discrete_rnd.m: Ditto.\n\t* statistics/distributions/empirical_cdf.m: Ditto.\n\t* statistics/distributions/empirical_inv.m: Ditto.\n\t* statistics/distributions/empirical_pdf.m: Ditto.\n\t* statistics/distributions/empirical_rnd.m: Ditto.\n\t* statistics/distributions/exponential_cdf.m: Ditto.\n\t* statistics/distributions/exponential_inv.m: Ditto.\n\t* statistics/distributions/exponential_pdf.m: Ditto.\n\t* statistics/distributions/exponential_rnd.m: Ditto.\n\t* statistics/distributions/f_cdf.m: Ditto.\n\t* statistics/distributions/f_inv.m: Ditto.\n\t* statistics/distributions/f_pdf.m: Ditto.\n\t* statistics/distributions/f_rnd.m: Ditto.\n\t* statistics/distributions/gamma_cdf.m: Ditto.\n\t* statistics/distributions/gamma_inv.m: Ditto.\n\t* statistics/distributions/gamma_pdf.m: Ditto.\n\t* statistics/distributions/gamma_rnd.m: Ditto.\n\t* statistics/distributions/geometric_cdf.m: Ditto.\n\t* statistics/distributions/geometric_inv.m: Ditto.\n\t* statistics/distributions/geometric_pdf.m: Ditto.\n\t* statistics/distributions/geometric_rnd.m: Ditto.\n\t* statistics/distributions/hypergeometric_cdf.m: Ditto.\n\t* statistics/distributions/hypergeometric_inv.m: Ditto.\n\t* statistics/distributions/hypergeometric_pdf.m: Ditto.\n\t* statistics/distributions/hypergeometric_rnd.m: Ditto.\n\t* statistics/distributions/kolmogorov_smirnov_cdf.m: Ditto.\n\t* statistics/distributions/laplace_cdf.m: Ditto.\n\t* statistics/distributions/laplace_inv.m: Ditto.\n\t* statistics/distributions/laplace_pdf.m: Ditto.\n\t* statistics/distributions/laplace_rnd.m: Ditto.\n\t* statistics/distributions/logistic_cdf.m: Ditto.\n\t* statistics/distributions/logistic_inv.m: Ditto.\n\t* statistics/distributions/logistic_pdf.m: Ditto.\n\t* statistics/distributions/logistic_rnd.m: Ditto.\n\t* statistics/distributions/lognormal_cdf.m: Ditto.\n\t* statistics/distributions/lognormal_inv.m: Ditto.\n\t* statistics/distributions/lognormal_pdf.m: Ditto.\n\t* statistics/distributions/lognormal_rnd.m: Ditto.\n\t* statistics/distributions/normal_cdf.m: Ditto.\n\t* statistics/distributions/normal_inv.m: Ditto.\n\t* statistics/distributions/normal_pdf.m: Ditto.\n\t* statistics/distributions/normal_rnd.m: Ditto.\n\t* statistics/distributions/pascal_cdf.m: Ditto.\n\t* statistics/distributions/pascal_inv.m: Ditto.\n\t* statistics/distributions/pascal_pdf.m: Ditto.\n\t* statistics/distributions/pascal_rnd.m: Ditto.\n\t* statistics/distributions/poisson_cdf.m: Ditto.\n\t* statistics/distributions/poisson_inv.m: Ditto.\n\t* statistics/distributions/poisson_pdf.m: Ditto.\n\t* statistics/distributions/poisson_rnd.m: Ditto.\n\t* statistics/distributions/stdnormal_cdf.m: Ditto.\n\t* statistics/distributions/stdnormal_inv.m: Ditto.\n\t* statistics/distributions/stdnormal_pdf.m: Ditto.\n\t* statistics/distributions/stdnormal_rnd.m: Ditto.\n\t* statistics/distributions/t_cdf.m: Ditto.\n\t* statistics/distributions/t_inv.m: Ditto.\n\t* statistics/distributions/t_pdf.m: Ditto.\n\t* statistics/distributions/t_rnd.m: Ditto.\n\t* statistics/distributions/uniform_cdf.m: Ditto.\n\t* statistics/distributions/uniform_inv.m: Ditto.\n\t* statistics/distributions/uniform_pdf.m: Ditto.\n\t* statistics/distributions/uniform_rnd.m: Ditto.\n\t* statistics/distributions/weibull_cdf.m: Ditto.\n\t* statistics/distributions/weibull_inv.m: Ditto.\n\t* statistics/distributions/weibull_pdf.m: Ditto.\n\t* statistics/distributions/weibull_rnd.m: Ditto.\n\t* statistics/distributions/wiener_rnd.m: Ditto.\n\n2000-01-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/base/values.m: Texinfoize doc string.\n\t* statistics/base/var.m: Ditto.\n\t* statistics/base/table.m: Ditto.\n\t* statistics/base/studentize.m: Ditto.\n\t* statistics/base/statistics.m: Ditto.\n\t* statistics/base/spearman.m: Ditto.\n\t* statistics/base/run_count.m: Ditto.\n\t* statistics/base/ranks.m: Ditto.\n\t* statistics/base/range.m: Ditto.\n\t* statistics/base/qqplot.m: Ditto.\n\t* statistics/base/probit.m: Ditto.\n\t* statistics/base/ppplot.m: Ditto.\n\t* statistics/base/moment.m: Ditto.\n\t* statistics/base/meansq.m: Ditto.\n\t* statistics/base/logit.m: Ditto.\n\t* statistics/base/kendall.m: Ditto.\n\t* statistics/base/iqr.m: Ditto.\n\t* statistics/base/cut.m: Ditto.\n\t* statistics/base/cor.m: Ditto.\n\t* statistics/base/cloglog.m: Ditto.\n\t* statistics/base/center.m: Ditto.\n\t* statistics/models/logistic_regression.m: Ditto.\n\t* statistics/models/logistic_regression_derivative.m: Ditto.\n\t* statistics/models/logistic_regression_likelihood.m: Ditto.\n\t* statistics/tests/anova.m: Ditto.\n\t* statistics/tests/bartlett_test.m: Ditto.\n\t* statistics/tests/chisquare_test_homogeneity.m: Ditto.\n\t* statistics/tests/chisquare_test_independence.m: Ditto.\n\t* statistics/tests/cor_test.m: Ditto.\n\t* statistics/tests/f_test_regression.m: Ditto.\n\t* statistics/tests/hotelling_test.m: Ditto.\n\t* statistics/tests/hotelling_test_2.m: Ditto.\n\t* statistics/tests/kolmogorov_smirnov_test.m: Ditto.\n\t* statistics/tests/kolmogorov_smirnov_test_2.m: Ditto.\n\t* statistics/tests/kruskal_wallis_test.m: Ditto.\n\t* statistics/tests/manova.m: Ditto.\n\t* statistics/tests/mcnemar_test.m: Ditto.\n\t* statistics/tests/prop_test_2.m: Ditto.\n\t* statistics/tests/run_test.m: Ditto.\n\t* statistics/tests/sign_test.m: Ditto.\n\t* statistics/tests/t_test.m: Ditto.\n\t* statistics/tests/t_test_2.m: Ditto.\n\t* statistics/tests/t_test_regression.m: Ditto.\n\t* statistics/tests/u_test.m: Ditto.\n\t* statistics/tests/var_test.m: Ditto.\n\t* statistics/tests/welch_test.m: Ditto.\n\t* statistics/tests/wilcoxon_test.m: Ditto.\n\t* statistics/tests/z_test.m: Ditto.\n\t* statistics/tests/z_test_2.m: Ditto.\n\n2000-01-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/bin2dec.m: Texinfoize doc string.\n\t* plot/__plr1__.m: Ditto.\n\t* plot/__pltopt__.m: Ditto.\n\t* plot/__plt__.m: Ditto.\n\t* plot/__plt2vv__.m: Ditto.\n\t* plot/__plr2__.m: Ditto.\n\t* plot/__plr__.m: Ditto.\n\t* plot/__plt1__.m: Ditto.\n\t* plot/__plt2__.m: Ditto.\n\t* plot/__plt2mm__.m: Ditto.\n\t* plot/__plt2mv__.m: Ditto.\n\t* plot/__plt2ss__.m: Ditto.\n\t* miscellaneous/paren.m: Ditto.\n\t* miscellaneous/comma.m: Ditto.\n\t* miscellaneous/semicolon.m: Ditto.\n\t* miscellaneous/path.m: Ditto.\n\t* miscellaneous/list_primes.m: Ditto.\n\t* miscellaneous/flops.m: Ditto.\n\t* miscellaneous/dump_prefs.m: Ditto.\n\t* miscellaneous/bug_report.m: Ditto.\n\t* linear-algebra/dot.m: Ditto\n\t* linear-algebra/dmult.m: Ditto.\n\t* general/randperm.m: Ditto.\n\t* general/logical.m: Ditto.\n\t* general/is_duplicate_entry.m: Ditto.\n\t* signal/arch_fit.m: Ditto.\n\t* signal/arch_rnd.m: Ditto.\n\t* signal/arch_test.m: Ditto.\n\t* signal/arma_rnd.m: Ditto.\n\t* signal/autocor.m: Ditto.\n\t* signal/autocov.m: Ditto.\n\t* signal/autoreg_matrix.m: Ditto.\n\t* signal/bartlett.m: Ditto.\n\t* signal/blackman.m: Ditto.\n\t* signal/detrend.m: Ditto.\n\t* signal/diffpara.m: Ditto.\n\t* signal/durbinlevinson.m: Ditto.\n\t* signal/fftconv.m: Ditto.\n\t* signal/fftfilt.m: Ditto.\n\t* signal/fftshift.m: Ditto.\n\t* signal/fractdiff.m: Ditto.\n\t* signal/freqz.m: Ditto.\n\t* signal/hamming.m: Ditto.\n\t* signal/hanning.m: Ditto.\n\t* signal/hurst.m: Ditto.\n\t* signal/periodogram.m: Ditto.\n\t* signal/rectangle_lw.m: Ditto.\n\t* signal/rectangle_sw.m: Ditto.\n\t* signal/sinc.m: Ditto.\n\t* signal/sinetone.m: Ditto.\n\t* signal/sinewave.m: Ditto.\n\t* signal/spectral_adf.m: Ditto.\n\t* signal/spectral_xdf.m: Ditto.\n\t* signal/spencer.m: Ditto.\n\t* signal/stft.m: Ditto.\n\t* signal/synthesis.m: Ditto.\n\t* signal/triangle_lw.m: Ditto.\n\t* signal/triangle_sw.m: Ditto.\n\t* signal/yulewalker.m: Ditto.\n\t* control/util/strappend.m: Ditto.\n\t* control/base/nichols.m: Ditto.\n\t* control/system/is_signal_list.m: Ditto.\n\t* control/system/listidx.m: Ditto.\n\t* control/system/sysgettsam.m: Ditto.\n\t* control/system/sysidx.m: Ditto.\n\n2000-01-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/system/__abcddims__.m: Rename from\n\tcontrol/system/abcddims.m, change all callers.\n\t* control/base/__bodquist__.m: Likewise.\n\t* control/base/__freqresp__.m: Likewise.\n\t* control/util/__outlist__.m: Likewise.\n\t* control/base/__stepimp__.m: Likewise.\n\t* control/system/__syschnamesl__.m: Likewise.\n\t* control/system/__syscont_disc__.m: Likewise.\n\t* control/system/__sysdefioname__.m: Likewise.\n\t* control/system/__sysdefstname__.m: Likewise.\n\t* control/system/__sysgroupn__.m: Likewise.\n\t* control/system/__tf2sysl__.m: Likewise.\n\t* control/util/__zgpbal__.m: Likewise.\n\t* control/system/__zp2ssg2__.m: Likewise.\n\n\t* quaternion/demoquat.m: Add copyright notice, Texinfoize doc string.\n\t* quaternion/qconj.m: Ditto.\n\t* quaternion/qcoordinate_plot.m: Ditto.\n\t* quaternion/qderiv.m: Ditto.\n\t* quaternion/qderivmat.m: Ditto.\n\t* quaternion/qinv.m: Ditto.\n\t* quaternion/qmult.m: Ditto.\n\t* quaternion/qtrans.m: Ditto.\n\t* quaternion/qtransv.m: Ditto.\n\t* quaternion/qtransvmat.m: Ditto.\n\t* quaternion/quaternion.m: Ditto.\n\n2000-01-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/base/Makefile.in: Ditto.\n\t* control/hinf/Makefile.in: New file.\n\t* control/marsyas/Makefile.in: Ditto.\n\t* control/obsolete/Makefile.in: Ditto.\n\t* control/system/Makefile.in: Ditto.\n\t* control/util/Makefile.in: Ditto.\n\n\t* strings/com2str.m: Move here from control directory.\n\n\t* control/base: New directory.\n\t* control/base/DEMOcontrol.m: Move here from control directory.\n\t* control/base/analdemo.m: Ditto.\n\t* control/base/are.m: Ditto.\n\t* control/base/bddemo.m: Ditto.\n\t* control/base/bode.m: Ditto.\n\t* control/base/bode_bounds.m: Ditto.\n\t* control/base/bodquist.m: Ditto.\n\t* control/base/controldemo.m: Ditto.\n\t* control/base/ctrb.m: Ditto.\n\t* control/base/damp.m: Ditto.\n\t* control/base/dare.m: Ditto.\n\t* control/base/dcgain.m: Ditto.\n\t* control/base/dgram.m: Ditto.\n\t* control/base/dlqe.m: Ditto.\n\t* control/base/dlqr.m: Ditto.\n\t* control/base/dlyap.m: Ditto.\n\t* control/base/dre.m: Ditto.\n\t* control/base/frdemo.m: Ditto.\n\t* control/base/freqchkw.m: Ditto.\n\t* control/base/freqresp.m: Ditto.\n\t* control/base/gram.m: Ditto.\n\t* control/base/impulse.m: Ditto.\n\t* control/base/lqe.m: Ditto.\n\t* control/base/lqg.m: Ditto.\n\t* control/base/lqr.m: Ditto.\n\t* control/base/lsim.m: Ditto.\n\t* control/base/ltifr.m: Ditto.\n\t* control/base/lyap.m: Ditto.\n\t* control/base/nichols.m: Ditto.\n\t* control/base/nyquist.m: Ditto.\n\t* control/base/obsv.m: Ditto.\n\t* control/base/place.m: Ditto.\n\t* control/base/pzmap.m: Ditto.\n\t* control/base/rldemo.m: Ditto.\n\t* control/base/rlocus.m: Ditto.\n\t* control/base/step.m: Ditto.\n\t* control/base/stepimp.m: Ditto.\n\t* control/base/tzero.m: Ditto.\n\t* control/base/tzero2.m: Ditto.\n\n\t* control/hinf: New directory.\n\t* control/hinf/dhinfdemo.m: Move here from control directory.\n\t* control/hinf/h2norm.m: Ditto.\n\t* control/hinf/h2syn.m: Ditto.\n\t* control/hinf/hinf_ctr.m: Ditto.\n\t* control/hinf/hinfdemo.m: Ditto.\n\t* control/hinf/hinfnorm.m: Ditto.\n\t* control/hinf/hinfsyn.m: Ditto.\n\t* control/hinf/hinfsyn_chk.m: Ditto.\n\t* control/hinf/hinfsyn_ric.m: Ditto.\n\t* control/hinf/wgt1o.m: Ditto.\n\t* control/hinf/dgkfdemo.m: Ditto.\n\t* control/hinf/is_dgkf.m: Ditto.\n\n\t* control/marsyas: New directory.\n\t* control/marsyas/demomarsyas.m: Move here from control directory.\n\t* control/marsyas/susball.m: Ditto.\n\n\t* control/obsolete/dezero.m: Move here from control directory.\n\t* control/obsolete/rotg.m: Ditto.\n\n\t* control/system: New directory.\n\t* control/system/abcddim.m: Move here from control directory.\n\t* control/system/abcddims.m: Ditto.\n\t* control/system/buildssic.m: Ditto.\n\t* control/system/c2d.m: Ditto.\n\t* control/system/d2c.m: Ditto.\n\t* control/system/dmr2d.m: Ditto.\n\t* control/system/fir2sys.m: Ditto.\n\t* control/system/is_abcd.m: Ditto.\n\t* control/system/is_digital.m: Ditto.\n\t* control/system/is_sample.m: Ditto.\n\t* control/system/is_signal_list.m: Ditto.\n\t* control/system/is_siso.m: Ditto.\n\t* control/system/is_controllable.m: Ditto.\n\t* control/system/is_detectable.m: Ditto.\n\t* control/system/is_observable.m: Ditto.\n\t* control/system/is_stabilizable.m: Ditto.\n\t* control/system/is_stable.m: Ditto.\n\t* control/system/jet707.m: Ditto.\n\t* control/system/listidx.m: Ditto.\n\t* control/system/moddemo.m: Ditto.\n\t* control/system/ord2.m: Ditto.\n\t* control/system/packedform.m: Ditto.\n\t* control/system/parallel.m: Ditto.\n\t* control/system/ss2sys.m: Ditto.\n\t* control/system/ss2tf.m: Ditto.\n\t* control/system/ss2zp.m: Ditto.\n\t* control/system/starp.m: Ditto.\n\t* control/system/sys2fir.m: Ditto.\n\t* control/system/sys2ss.m: Ditto.\n\t* control/system/sys2tf.m: Ditto.\n\t* control/system/sys2zp.m: Ditto.\n\t* control/system/sysadd.m: Ditto.\n\t* control/system/sysappend.m: Ditto.\n\t* control/system/syschnamesl.m: Ditto.\n\t* control/system/syschtsam.m: Ditto.\n\t* control/system/sysconnect.m: Ditto.\n\t* control/system/syscont.m: Ditto.\n\t* control/system/syscont_disc.m: Ditto.\n\t* control/system/sysdefioname.m: Ditto.\n\t* control/system/sysdefstname.m: Ditto.\n\t* control/system/sysdimensions.m: Ditto.\n\t* control/system/sysdisc.m: Ditto.\n\t* control/system/sysdup.m: Ditto.\n\t* control/system/sysgetsignals.m: Ditto.\n\t* control/system/sysgettsam.m: Ditto.\n\t* control/system/sysgettype.m: Ditto.\n\t* control/system/sysgroup.m: Ditto.\n\t* control/system/sysgroupn.m: Ditto.\n\t* control/system/sysidx.m: Ditto.\n\t* control/system/sysmin.m: Ditto.\n\t* control/system/sysmult.m: Ditto.\n\t* control/system/sysout.m: Ditto.\n\t* control/system/sysprune.m: Ditto.\n\t* control/system/sysreorder.m: Ditto.\n\t* control/system/sysrepdemo.m: Ditto.\n\t* control/system/sysscale.m: Ditto.\n\t* control/system/syssetsignals.m: Ditto.\n\t* control/system/syssub.m: Ditto.\n\t* control/system/sysupdate.m: Ditto.\n\t* control/system/tf2ss.m: Ditto.\n\t* control/system/tf2sys.m: Ditto.\n\t* control/system/tf2sysl.m: Ditto.\n\t* control/system/tf2zp.m: Ditto.\n\t* control/system/tfout.m: Ditto.\n\t* control/system/ugain.m: Ditto.\n\t* control/system/zp2ss.m: Ditto.\n\t* control/system/zp2ssg2.m: Ditto.\n\t* control/system/zp2sys.m: Ditto.\n\t* control/system/zp2tf.m: Ditto.\n\t* control/system/zpout.m: Ditto.\n\n\t* control/util: New directory.\n\t* control/util/axis2dlim.m: Move here from control directory.\n\t* control/util/outlist.m: Ditto.\n\t* control/util/prompt.m: Ditto.\n\t* control/util/run_cmd.m: Ditto.\n\t* control/util/sortcom.m: Ditto.\n\t* control/util/strappend.m: Ditto.\n\t* control/util/swap.m: Ditto.\n\t* control/util/zgfmul.m: Ditto.\n\t* control/util/zgfslv.m: Ditto.\n\t* control/util/zginit.m: Ditto.\n\t* control/util/zgpbal.m: Ditto.\n\t* control/util/zgreduce.m: Ditto.\n\t* control/util/zgrownorm.m: Ditto.\n\t* control/util/zgscal.m: Ditto.\n\t* control/util/zgsgiv.m: Ditto.\n\t* control/util/zgshsr.m: Ditto.\n\n2000-01-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* gethelp.cc (extract_help_text): Discard first space character\n\tafter consecutive comment characters.\n\nThu Jan 13 00:56:57 2000  John W. Eaton  <jwe@bahaha.che.wisc.edu>\n\n\t* control/obsolete: New directory\n\t* control/obsolete/swaprows.m: Move here from control directory.\n\t* control/obsolete/swapcols.m: Ditto.\n\t* control/obsolete/dlqg.m: Ditto.\n\t* control/obsolete/minfo.m: Ditto.\n\t* control/obsolete/packsys.m: Ditto.\n\t* control/obsolete/qzval.m: Ditto.\n\t* control/obsolete/unpacksys.m: Ditto.\n\t* control/obsolete/series.m: Ditto.\n\t* control/obsolete/syschnames.m: Ditto.\n\t* polynomial/polyout.m: Ditto.\n\n2000-01-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/fliplr.m: Eliminate useless copy of arg.\n\t* general/flipud.m: Ditto.\n\n2000-01-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/cross.m: Only return a row vector if both args\n\tare row vectors.\n\t* polynomial/polyfit.m: Likewise.\n\n\t* signal/autocov.m: Don't reset prefer_column_vectors.\n\n\t* statistics/distributions/discrete_rnd.m:\n\tAlways generate a row vector.\n\t* statistics/distributions/hypergeometric_rnd.m: Likewise.\n\n2000-01-11  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* strings/upper.m: Add missing `-*- texinfo -*-' tag to doc string.\n\n\t* audio/setaudio.m: Texinfoize doc string.\n\t* control/com2str.m: Likewise.\n\t* control/controldemo.m: Likewise.\n\t* control/DEMOcontrol.m: Likewise.\n\t* control/dezero.m: Likewise.\n\t* control/dre.m: Likewise.\n\t* control/hinfsyn_ric.m: Likewise.\n\n2000-01-05  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* io/printf.m: Add @seealso{...} to doc string.\n\t* io/puts.m: Likewise.\n\t* plot/semilogx.m: Likewise.\n\t* plot/semilogy.m: Likewise.\n\t* plot/__pltopt__.m: Likewise.\n\t* plot/bar.m: Likewise.\n\t* plot/xlabel.m: Likewise.\n\t* plot/grid.m: Likewise.\n\t* plot/shg.m: Likewise.\n\t* plot/title.m: Likewise.\n\t* plot/mesh.m: Likewise.\n\t* plot/__pltopt1__.m: Likewise.\n\t* plot/contour.m: Likewise.\n\t* plot/hist.m: Likewise.\n\t* plot/stairs.m: Likewise.\n\t* plot/meshgrid.m: Likewise.\n\t* plot/polar.m: Likewise.\n\t* plot/loglog.m: Likewise.\n\t* plot/plot.m: Likewise.\n\t* miscellaneous/semicolon.m: Likewise.\n\t* miscellaneous/menu.m: Likewise.\n\t* miscellaneous/etime.m: Likewise.\n\t* miscellaneous/texas_lotto.m: Likewise.\n\t* miscellaneous/comma.m: Likewise.\n\t* audio/lin2mu.m: Likewise.\n\t* audio/playaudio.m: Likewise.\n\t* audio/loadaudio.m: Likewise.\n\t* audio/saveaudio.m: Likewise.\n\t* audio/mu2lin.m: Likewise.\n\t* audio/record.m: Likewise.\n\t* strings/isletter.m: Likewise.\n\t* strings/lower.m: Likewise.\n\t* strings/lower.m: Likewise.\n\t* strings/upper.m: Likewise.\n\t* specfun/erfinv.m: Likewise.\n\t* specfun/gammai.m: Likewise.\n\t* specfun/log2.m: Likewise.\n\t* specfun/pow2.m: Likewise.\n\t* elfun/gcd.m: Likewise.\n\t* elfun/lcm.m: Likewise.\n\t* special-matrix/vander.m: Likewise.\n\t* special-matrix/sylvester_matrix.m: Likewise.\n\t* special-matrix/hilb.m: Likewise.\n\t* special-matrix/hankel.m: Likewise.\n\t* special-matrix/toeplitz.m: Likewise.\n\t* special-matrix/invhilb.m: Likewise.\n\t* statistics/base/std.m: Likewise.\n\t* statistics/base/median.m: Likewise.\n\t* linear-algebra/cond.m: Likewise.\n\t* linear-algebra/norm.m: Likewise.\n\t* finance/nper.m: Likewise.\n\t* finance/pmt.m: Likewise.\n\t* finance/pv.m: Likewise.\n\t* finance/rate.m: Likewise.\n\t* finance/npv.m: Likewise.\n\t* general/fliplr.m: Likewise.\n\t* general/flipud.m: Likewise.\n\t* general/is_scalar.m: Likewise.\n\t* general/rem.m: Likewise.\n\t* general/perror.m: Likewise.\n\t* general/tril.m: Likewise.\n\t* general/rot90.m: Likewise.\n\t* general/num2str.m: Likewise.\n\t* general/int2str.m: Likewise.\n\t* general/reshape.m: Likewise.\n\t* general/logspace.m: Likewise.\n\t* general/is_symmetric.m: Likewise.\n\t* general/is_vector.m: Likewise.\n\t* general/nextpow2.m: Likewise.\n\t* general/columns.m: Likewise.\n\t* general/is_square.m: Likewise.\n\t* general/rows.m: Likewise.\n\t* control/ugain.m: Likewise.\n\t* control/damp.m: Likewise.\n\t* control/dare.m: Likewise.\n\t* control/are.m: Likewise.\n\t* control/sys2fir.m: Likewise.\n\t* control/abcddim.m: Likewise.\n\t* control/is_abcd.m: Likewise.\n\t* control/step.m: Likewise.\n\t* control/is_observable.m: Likewise.\n\t* control/is_controllable.m: Likewise.\n\t* control/jet707.m: Likewise.\n\t* control/polyout.m: Likewise.\n\t* control/impulse.m: Likewise.\n\t* control/lqg.m: Likewise.\n\t* control/is_detectable.m: Likewise.\n\t* control/sysdimensions.m: Likewise.\n\t* control/sysupdate.m: Likewise.\n\t* control/stepimp.m: Likewise.\n\t* control/is_stable.m: Likewise.\n\t* control/tfout.m: Likewise.\n\t* control/zpout.m: Likewise.\n\n2000-01-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* set/complement.m: Add @seealso{} stuff.\n\t* set/create_set.m: Likewise.\n\t* set/intersection.m: Likewise.\n\t* set/union.m: Likewise.\n\n1999-12-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/d2c.m: Use double quotes instead of single quotes for\n\tstring constants.\n\t* control/dgkfdemo.m: Likewise.\n\t* control/fir2sys.m: Likewise.\n\t* control/frdemo.m: Likewise.\n\t* control/moddemo.m: Likewise.\n\t* control/minfo.m: Likewise.\n\t* control/is_stabilizable.m: Likewise.\n\t* control/is_dgkf.m: Likewise.\n\t* control/polyout.m: Likewise.\n\t* control/sysconnect.m: Likewise.\n\t* control/sysrepdemo.m: Likewise.\n\t* control/tf2sys.m: Likewise.\n\t* control/tfout.m: Likewise.\n\t* control/zp2sys.m: Likewise.\n\t* control/zpout.m: Likewise.\n\t* control/tzero.m: Likewise.\n\n\t* control/DEMOcontrol.m: Handle moddemo case too.\n\n\t* image/loadimage.m: Use double quotes instead of single quotes\n\tfor string constants.  Use sprintf instead of square brackets to\n\tconstruct string.\n\n\t* control/DEMOcontrol.m: Formatting tweaks.\n\t* control/fir2sys.m: Likewise.\n\n1999-12-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkdoc: Only delete spaces before @ characters at the beginning\n\tof a line.\n\n1999-12-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/bddemo.m: Make it more likely to work with any value of\n\twhitespace_in_literal_matrix.\n\t* control/analdemo.m: Ditto.\n\t* control/dgkfdemo.m: Ditto.\n\t* control/frdemo.m: Ditto.\n\t* control/sysrepdemo.m: Ditto.\n\t* control/moddemo.m: Ditto.\n\t* control/zp2ss.m: Ditto.\n\t* control/zp2tf.m: Ditto.\n\t* control/syssub.m: Ditto.\n\t* finance/npv.m: Ditto.\n\t* statistics/base/studentize.m: Ditto.\n\t* statistics/base/values.m: Ditto.\n\t* statistics/distributions/exponential_cdf.m: Ditto.\n\t* statistics/distributions/poisson_cdf.m: Ditto.\n\n\t* control/dezero.m: Use toascii to convert string to ASCII value\n\tinstead of multiplying it by 1.\n\n\t* control/zp2sys.m: Don't save and restore implicit_str_to_num_ok.\n\t* control/zpout.m: Ditto.\n\t* control/tfout.m: Ditto.\n\t* control/tf2sys.m: Ditto.\n\t* control/syssub.m: Ditto.\n\t* control/syssetsignals.m: Ditto.\n\t* control/sysout.m: Ditto.\n\t* control/sysmult.m: Ditto.\n\t* control/sysgroup.m: Ditto.\n\t* control/sysdup.m: Ditto.\n\t* control/sysdisc.m: Ditto.\n\t* control/syscont.m: Ditto.\n\t* control/sysconnect.m: Ditto.\n\t* control/sysappend.m: Ditto.\n\t* control/sysadd.m: Ditto.\n\t* control/ss2sys.m: Ditto.\n\t* control/nyquist.m: Ditto.\n\t* control/lqg.m: Ditto.\n\t* control/fir2sys.m: Ditto.\n\t* control/dmr2d.m: Ditto.\n\t* control/dezero.m: Ditto.\n\t* control/d2c.m: Ditto.\n\t* control/c2d.m: Ditto.\n\t* control/bddemo.m: Ditto.\n\t* control/pzmap.m: Ditto.\n\n1999-12-08  Daniel Calvelo  <dcalvelo@pharion.univ-lille2.fr>\n\n\t* signal/spectral_adf.m: Fix typo.\n\n1999-11-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/cond.m: Texinfoize doc string.\n\t* linear-algebra/kron.m: Ditto.\n\t* linear-algebra/norm.m: Ditto.\n\t* linear-algebra/null.m: Ditto.\n\t* linear-algebra/orth.m: Ditto.\n\t* linear-algebra/rank.m: Ditto.\n\t* linear-algebra/trace.m: Ditto.\n\t* linear-algebra/qzhess.m: Ditto.\n\t* miscellaneous/menu.m: Ditto.\n\t* general/perror.m: Ditto.\n\t* general/strerror.m: Ditto.\n\t* general/columns.m: Ditto.\n\t* general/rows.m: Ditto.\n\t* image/colormap.m: Ditto.\n\t* image/gray.m: Ditto.\n\t* image/gray2ind.m: Ditto.\n\t* image/image.m: Ditto.\n\t* image/imagesc.m: Ditto.\n\t* image/imshow.m: Ditto.\n\t* image/ind2gray.m: Ditto.\n\t* image/ind2rgb.m: Ditto.\n\t* image/loadimage.m: Ditto.\n\t* image/rgb2ntsc.m: Ditto.\n\t* image/ntsc2rgb.m: Ditto.\n\t* image/ocean.m: Ditto.\n\t* image/rgb2ind.m: Ditto.\n\t* image/saveimage.m: Ditto.\n\t* io/printf.m: Ditto.\n\t* io/puts.m: Ditto.\n\n1999-11-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* special-matrix/hankel.m: Texinfoize doc string.\n\t* special-matrix/hilb.m: Ditto.\n\t* special-matrix/invhilb.m: Ditto.\n\t* special-matrix/sylvester_matrix.m: Ditto.\n\t* special-matrix/toeplitz.m: Ditto.\n\t* special-matrix/vander.m: Ditto.\n\t* linear-algebra/vec.m: Ditto.\n\t* linear-algebra/vech.m: Ditto.\n\t* general/common_size.m: Ditto.\n\t* general/diff.m: Ditto.\n\t* general/fliplr.m: Ditto.\n\t* general/flipud.m: Ditto.\n\t* general/rot90.m: Ditto.\n\t* general/reshape.m: Ditto.\n\t* general/shift.m: Ditto.\n\t* general/tril.m: Ditto.\n\t* general/triu.m: Ditto.\n\t* general/logspace.m: Ditto.\n\t* general/nargchk.m: Ditto.\n\n1999-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/base/mean: Texinfoize doc string.\n\t* statistics/base/median: Ditto.\n\t* statistics/base/std: Ditto.\n\t* statistics/base/cov: Ditto.\n\t* statistics/base/corrcoef: Ditto.\n\t* statistics/base/kurtosis: Ditto.\n\t* statistics/base/mahalanobis: Ditto.\n\t* statistics/base/skewness: Ditto.\n\t* statistics/base/gls.m: Ditto.\n\t* statistics/base/ols.m: Ditto.\n\t* signal/detrend.m: Ditto.\n\t* signal/freqz.m: Ditto.\n\t* signal/sinc.m: Ditto.\n\t* signal/fftconv.m: Ditto.\n\t* signal/fftfilt.m: Ditto.\n\t* set/create_set.m: Ditto.\n\t* set/union.m: Ditto.\n\t* set/intersection.m: Ditto.\n\t* set/complement.m: Ditto.\n\t* poly/compan.m: Ditto.\n\t* poly/conv: Ditto.\n\t* poly/deconv: Ditto.\n\t* poly/poly: Ditto.\n\t* poly/polyderiv: Ditto.\n\t* poly/polyfit: Ditto.\n\t* poly/polyinteg: Ditto.\n\t* poly/polyreduce: Ditto.\n\t* poly/polyval: Ditto.\n\t* poly/polyvalm: Ditto.\n\t* poly/residue: Ditto.\n\t* poly/roots: Ditto.\n\t* plot/top_title.m: Ditto\n\t* plot/subwindow.m: Ditto\n\t* plot/subplot.m: Ditto\n\t* plot/plot_border.m: Ditto\n\t* plot/oneplot.m: Ditto\n\t* plot/multiplot.m: Ditto\n\t* plot/mplot.m: Ditto\n\t* plot/xlabel.m: Ditto\n\t* plot/figure.m: Ditto\n\t* plot/meshdom.m: Ditto\n\t* plot/mesh.m: Ditto\n\t* plot/stairs.m: Ditto\n\t* plot/polar.m: Ditto\n\t* plot/loglog.m: Ditto\n\t* plot/hist.m: Ditto\n\t* plot/contour.m: Ditto\n\t* plot/bar.m: Ditto\n\t* plot/axis.m: Ditto\n\t* plot/plot.m: Ditto.\n\n1999-11-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/pinv.m: Delete.\n\n\t* Makefile.in (DOCSTRINGS): Don't echo $(ALL_M_FILES).\n\n\t* strings/blanks.m: Texinfoize doc string.\n\t* strings/strcat.m: Ditto.\n\t* strings/str2mat.m: Ditto.\n\t* strings/deblank.m: Ditto.\n\t* strings/findstr.m: Ditto.\n\t* strings/index.m: Ditto.\n\t* strings/rindex.m: Ditto.\n\t* strings/split.m: Ditto.\n\t* strings/strcmp.m: Ditto.\n\t* strings/strrep.m: Ditto.\n\t* strings/substr.m: Ditto.\n\t* general/int2str.m: Ditto.\n\t* general/num2str.m: Ditto.\n\t* strings/dec2bin.m: Ditto.\n\t* strings/bin2dec: Ditto.\n\t* strings/dec2bin: Ditto.\n\t* strings/dec2hex: Ditto.\n\t* strings/hex2dec: Ditto.\n\t* strings/str2num: Ditto.\n\n1999-11-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DISTFILES): Include DOCSTRINGS.\n\n1999-11-09  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* control/DEMOcontrol.m: Texinfoize doc string.\n\t* control/abcddim.m: Ditto.\n\t* control/abcddims.m: Ditto.\n\t* control/analdemo.m: Ditto.\n\t* control/are.m: Ditto.\n\t* control/axis2dlim.m: Ditto.\n\t* control/bddemo.m: Ditto.\n\t* control/bode.m: Ditto.\n\t* control/bode_bounds.m: Ditto.\n\t* control/bodquist.m: Ditto.\n\t* control/buildssic.m: Ditto.\n\t* control/c2d.m: Ditto.\n\t* control/ctrb.m: Ditto.\n\t* control/d2c.m: Ditto.\n\t* control/damp.m: Ditto.\n\t* control/dare.m: Ditto.\n\t* control/dcgain.m: Ditto.\n\t* control/dgkfdemo.m: Ditto.\n\t* control/dgram.m: Ditto.\n\t* control/dlqe.m: Ditto.\n\t* control/dlqr.m: Ditto.\n\t* control/dlyap.m: Ditto.\n\t* control/dmr2d.m: Ditto.\n\t* control/fir2sys.m: Ditto.\n\t* control/frdemo.m: Ditto.\n\t* control/freqchkw.m: Ditto.\n\t* control/freqresp.m: Ditto.\n\t* control/gram.m: Ditto.\n\t* control/h2norm.m: Ditto.\n\t* control/h2syn.m: Ditto.\n\t* control/hinf_ctr.m: Ditto.\n\t* control/hinfdemo.m: Ditto.\n\t* control/hinfnorm.m: Ditto.\n\t* control/hinfsyn.m: Ditto.\n\t* control/hinfsyn_chk.m: Ditto.\n\t* control/impulse.m: Ditto.\n\t* control/is_abcd.m: Ditto.\n\t* control/is_controllable.m: Ditto.\n\t* control/is_detectable.m: Ditto.\n\t* control/is_dgkf.m: Ditto.\n\t* control/is_digital.m: Ditto.\n\t* control/is_observable.m: Ditto.\n\t* control/is_sample.m: Ditto.\n\t* control/is_signal_list.m: Ditto.\n\t* control/is_siso.m: Ditto.\n\t* control/is_stabilizable.m: Ditto.\n\t* control/is_stable.m: Ditto.\n\t* control/jet707.m: Ditto.\n\t* control/lqe.m: Ditto.\n\t* control/lqg.m: Ditto.\n\t* control/lqr.m: Ditto.\n\t* control/lsim.m: Ditto.\n\t* control/ltifr.m: Ditto.\n\t* control/lyap.m: Ditto.\n\t* control/moddemo.m: Ditto.\n\t* control/nyquist.m: Ditto.\n\t* control/obsv.m: Ditto.\n\t* control/ord2.m: Ditto.\n\t* control/outlist.m: Ditto.\n\t* control/pinv.m: Ditto.\n\t* control/place.m: Ditto.\n\t* control/polyout.m: Ditto.\n\t* control/prompt.m: Ditto.\n\t* control/pzmap.m: Ditto.\n\t* control/qzval.m: Ditto.\n\t* control/rldemo.m: Ditto.\n\t* control/rlocus.m: Ditto.\n\t* control/sortcom.m: Ditto.\n\t* control/ss2sys.m: Ditto.\n\t* control/ss2tf.m: Ditto.\n\t* control/ss2zp.m: Ditto.\n\t* control/starp.m: Ditto.\n\t* control/step.m: Ditto.\n\t* control/stepimp.m: Ditto.\n\t* control/susball.m: Ditto.\n\t* control/sys2fir.m: Ditto.\n\t* control/sys2ss.m: Ditto.\n\t* control/sys2tf.m: Ditto.\n\t* control/sys2zp.m: Ditto.\n\t* control/sysadd.m: Ditto.\n\t* control/sysappend.m: Ditto.\n\t* control/syschnames.m: Ditto.\n\t* control/syschnamesl.m: Ditto.\n\t* control/syschtsam.m: Ditto.\n\t* control/sysconnect.m: Ditto.\n\t* control/syscont.m: Ditto.\n\t* control/syscont_disc.m: Ditto.\n\t* control/sysdefioname.m: Ditto.\n\t* control/sysdefstname.m: Ditto.\n\t* control/sysdimensions.m: Ditto.\n\t* control/sysdisc.m: Ditto.\n\t* control/sysdup.m: Ditto.\n\t* control/sysgetsignals.m: Ditto.\n\t* control/sysgettype.m: Ditto.\n\t* control/sysgroup.m: Ditto.\n\t* control/sysgroupn.m: Ditto.\n\t* control/sysmult.m: Ditto.\n\t* control/sysout.m: Ditto.\n\t* control/sysprune.m: Ditto.\n\t* control/sysreorder.m: Ditto.\n\t* control/sysrepdemo.m: Ditto.\n\t* control/sysscale.m: Ditto.\n\t* control/syssetsignals.m: Ditto.\n\t* control/syssub.m: Ditto.\n\t* control/sysupdate.m: Ditto.\n\t* control/tf2ss.m: Ditto.\n\t* control/tf2sys.m: Ditto.\n\t* control/tf2sysl.m: Ditto.\n\t* control/tf2zp.m: Ditto.\n\t* control/tfout.m: Ditto.\n\t* control/tzero.m: Ditto.\n\t* control/tzero2.m: Ditto.\n\t* control/ugain.m: Ditto.\n\t* control/wgt1o.m: Ditto.\n\t* control/zgfmul.m: Ditto.\n\t* control/zgfslv.m: Ditto.\n\t* control/zginit.m: Ditto.\n\t* control/zgpbal.m: Ditto.\n\t* control/zgreduce.m: Ditto.\n\t* control/zgrownorm.m: Ditto.\n\t* control/zgscal.m: Ditto.\n\t* control/zgsgiv.m: Ditto.\n\t* control/zgshsr.m: Ditto.\n\t* control/zp2ss.m: Ditto.\n\t* control/zp2ssg2.m: Ditto.\n\t* control/zp2sys.m: Ditto.\n\t* control/zp2tf.m: Ditto.\n\t* control/zpout.m: Ditto.\n\n1999-11-02  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* audio/lin2mu.m: Texinfoize doc string.\n\t* audio/loadaudio.m: Ditto.\n\t* audio/mu2lin.m: Ditto.\n\t* audio/playaudio.m: Ditto.\n\t* audio/record.m: Ditto.\n\t* audio/saveaudio.m: Ditto.\n\n1999-10-26  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* elfun/acot.m: Texinfoize doc string.\n\t* elfun/acsc.m: Ditto.\n\t* elfun/acsch.m: Ditto.\n\t* elfun/asec.m: Ditto.\n\t* elfun/asech.m: Ditto.\n\t* elfun/cot.m: Ditto.\n\t* elfun/coth.m: Ditto.\n\t* elfun/csc.m: Ditto.\n\t* elfun/csch.m: Ditto.\n\t* elfun/gcd.m: Ditto.\n\t* elfun/lcm.m: Ditto.\n\t* elfun/sec.m: Ditto.\n\t* elfun/sech.m: Ditto.\n\t* general/nextpow2.m: Ditto.\n\t* general/rem.m: Ditto.\n\t* linear-algebra/commutation_matrix.m: Ditto.\n\t* linear-algebra/cross.m: Ditto.\n\t* linear-algebra/duplication_matrix.m: Ditto.\n\t* miscellaneous/bincoeff.m: Ditto.\n\t* miscellaneous/xor.m: Ditto.\n\t* specfun/bessel.m: Ditto.\n\t* specfun/beta.m: Ditto.\n\t* specfun/betai.m: Ditto.\n\t* specfun/erfinv.m: Ditto.\n\t* specfun/gammai.m: Ditto.\n\t* specfun/log2.m: Ditto.\n\t* specfun/pow2.m: Ditto.\n\n1999-10-23  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* general/is_scalar.m: Texinfoize help text.\n\t* general/is_square.m: Ditto.\n\t* general/is_symmetric.m: Ditto.\n\n1999-10-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/split.m: If the string to be split is empty, just return\n\tan empty string.\n\n1999-10-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (ALL_M_FILES): New macro.\n\t(DOCSTRINGS): No longer .PHONY; depend on $(ALL_M_FILES).\n\n1999-10-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/bode.m: Don't return anything if nargout == 0.\n\n1999-10-20  James B. Rawlings  <jbraw@bevo.che.wisc.edu>\n\n\t* control/bode.m: Don't do axis scaling for magnitude plots.\n\n1999-10-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DISTFILES): Add move-if-change, mkdoc, and\n\tgethelp.cc to the list.\n\n1999-10-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* time/asctime.m: Texinfoize help text.\n\t* time/clock.m: Ditto.\n\t* time/date.m: Ditto.\n\t* miscellaneous/cputime.m: Ditto.\n\t* miscellaneous/etime.m: Ditto.\n\t* miscellaneous/is_leap_year.m: Ditto.\n\t* miscellaneous/popen2.m: Ditto.\n\t* miscellaneous/version.m: Ditto.\n\t* miscellaneous/tic.m: Ditto.\n\t* miscellaneous/toc.m: Just refer to tic.m.\n\n\t* Makefile.in (dist, bin-dist): Use `$(MAKE) -C dir' instead of\n\t`cd dir; $(MAKE); cd ..'.\n\t($(SUBDIRS)): Likewise.\n\n\t* statistics/Makefile.in ($(SUBDIRS)): Likewise.\n\n\t* statistics/Makefile.in (bin-dist): Use `$(MAKE) -C dir' instead\n\tof `cd dir; $(MAKE)'.\n\n\t* gethelp.cc, mkdoc: New files.\n\t* Makefile.in: Use them to create DOCSTRINGS file from .m file\n\tsources.\n\n1999-10-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/kron.m: Fix typo in previous change\n\n1999-10-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/bode.m: Allow optional 5th arg to specify plot style.\n\nWed Sep 22 22:12:03 1999 A. Scottedward Hodel  <a.s.hodel@eng.auburn.edu>\n\n\t* linear-algebra/krylov.m: Correctly handle case of V having full\n\trank when V has more columns than rows.\n\nMon Sep 20 23:04:57 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/linspace.m, linear-algebra/pinv.m: Delete.\n\n\t* statistics/tests/manova.m: Avoid problems if\n\twhitespace_in_literal_matrix is set to \"traditional\".\n\t* statistics/tests/t_test_regression.m: Likewise.\n\t* statistics/tests/u_test.m: Likewise.\n\t* statistics/tests/chisquare_test_homogeneity.m: Likewise.\n\t* statistics/tests/anova.m: Likewise.\n\t* statistics/tests/kruskal_wallis_test.m: Likewise.\n\t* statistics/base/statistics.m: Likewise.\n\t* image/saveimage.m: Likewise.\n\t* signal/arch_fit.m: Likewise.\n\t* signal/autoreg_matrix.m: Likewise.\n\t* signal/triangle_lw.m: Likewise.\n\t* strings/dec2hex.m: Likewise.\n\nThu Sep  9 19:31:58 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/saveimage.m: Initialize scale.\n\nSun Sep  5 22:13:47 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/reshape.m: Allow reshape (a, size (b)).\n\nFri Sep  3 00:01:38 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/erfinv.m: Improve stopping criterion.\n\tAdd iteration count as second return value.\n\nMon Aug 30 12:07:00 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/base/mean.m: Use .', not ' to reorient row vectors.\n\nTue Aug 17 11:11:27 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/pack.m: New function.\n\nMon Aug 16 07:46:57 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/figure.m: Always return figure number.  With no args,\n \tfigure now creates a new figure window and returns its number.\n\tAccept figure (property, value) syntax, but do nothing.\n\nThu Aug 12 09:28:01 PDT 1999  Tom Poage  <tfpoage@ucdavis.edu>\n\n\t* general/shift.m: Avoid printing temporary value for backward shift.\n\nMon Aug  2 16:39:04 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/bar.m: Compute bar widths correctly when x-values are not\n\tevenly spaced.\n\nMon Jul 12 22:48:34 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/cond.m: Avoid returning NaN for matrices that\n\tcontain only zeros.\n\nSun Jun 20 22:24:27 1999  Eduardo Gallestey  <eduardo@faceng.anu.edu.au>\n\n\t* linear-algebra/kron.m: Create result matrix and insert blocks\n\tinstead of appending them.\n\nSat Jun 19 01:52:18 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/bodquist.m, control/buildssic.m, control/is_digital.m,\n\tcontrol/stepimp.m, control/sysmin.m, control/syssetsignals.m:\n\tUpdate from A. S. Hodel.\n\nFri Jun 18 12:19:22 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* polynomial/polyfit.m: Correct previous change.\n\nWed Apr  7 13:57:26 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/qrhouse.m, linear-algebra/krygetq.m: Delete.\n\nWed Apr  7 13:22:43 1999  A. S. Hodel  <a.s.hodel@eng.auburn.edu>\n\n\t* control/is_controllable.m, control/zgscal.m: Accomodate new\n\tversion of krylov and krylovb.\n\n\t* control/outlist.m, control/sysout.m: Fix typos.\n\n\t* control/sysdimensions.m: Add option for total number of states.\n\n\t* linear-algebra/krylov.m: Improve robustness by row-pivoting.\n\t* linear-algebra/krylovb.m: Just call krylov with appropriate\n\targuments.\n\nTue Mar 30 00:43:09 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/index.m: Fail with meaningful error message if either\n\targ is a string array.\n\nWed Mar 24 20:34:48 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/norm.m: Do the right thing for 1- and\n\tinfinity-norms of complex matrices.  From Sven Khatri\n\t<khatri@saturn.vocalpoint.com>.\n\nTue Mar 16 13:36:36 1999  A. Scottedward Hodel\"  <scotte@eng.auburn.edu>\n\n\t* linear-algebra/qrhouse.m: Handle default args correctly.\n\nThu Mar 11 12:52:34 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/split.m: Avoid problems when splitting strings that have\n\t\\ in them.\n\nThu Mar 11 12:36:13 1999  Massimo Lorenzin  <maxlorenzin@tin.it>\n\n\t* image/colormap.m: Do better arg checking, handle string args\n\tthat name the colormap function to call (e.g., colormap (\"ocean\")).\n\nMon Mar  8 22:23:24 1999  Rolf Fabian  <fabian@TU-Cottbus.De>\n\n\t* polynomial/polyfit.m: Use .' transpose operator, not '.\n\t* linear-algebra/dot.m: Likewise.\n\t* linear-algebra/cross.m: Likewise.\n\t* general/rot90.m: Likewise.\n\nSat Mar  6 01:45:00 1999  A Scott Hodel  <hodel@edalf1.msfc.nasa.gov>\n\n\t* linear-algebra/qrhouse.m: Permute columns at each iteration so\n\tthat the leading column is not all zeros.\n\nFri Mar  5 00:37:47 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/shift.m: Fix potential problems with\n\twhitespace_in_literal_matrix.\n\t* signal/arch_rnd.m: Ditto.\n\t* signal/autocov.m: Ditto.\n\t* signal/diffpara.m: Ditto.\n\t* signal/hurst.m: Ditto.\n\t* signal/periodogram.m: Ditto.\n\t* signal/spectral_adf.m: Ditto.\n\t* signal/spectral_xdf.m: Ditto.\n\t* signal/spencer.m: Ditto.\n\t* signal/synthesis.m: Ditto.\n\t* statistics/distributions/wiener_rnd.m: Ditto.\n\t* statistics/models/logistic_regression_likelihood.m: Ditto.\n\t* statistics/models/logistic_regression.m: Ditto.\n\t* statistics/models/logistic_regression_derivatives.m: Ditto.\n\t* statistics/tests/run_test.m: Ditto.\n\t* statistics/tests/chisquare_test_independence.m: Ditto.\n\nWed Mar  3 02:25:00 1999  Joao Cardoso  <jcardoso@inescn.pt>\n\n\t* plot/__plr2__.m: Fix typo.\n\nTue Jan 12 10:31:15 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__pltopt1__.m: Accept \"k\" to mean black.\n\nFri Dec 11 10:43:19 1998  A Scott Hodel  <hodel@edalf1.msfc.nasa.gov>\n\n\t* linear-algebra/krylov.m: Force empty_list_elements_ok for this\n\tfunction.\n\nThu Dec 10 11:07:00 1998  A Scott Hodel  <hodel@edalf1.msfc.nasa.gov>\n\n\t* control/ss2sys.m: Fix typo.\n\nWed Dec  9 12:42:19 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/subplot.m, plot/oneplot.m: Don't call clearplot.\n\n\t* control: Update from A. S. Hodel <a.s.hodel@eng.auburn.edu> for\n\tsignal names as lists of strings instead of string arrays.\n\nFri Dec  4 16:08:42 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* quaternion: New directory of functions from A. S. Hodel\n\t<a.s.hodel@eng.auburn.edu>.\n\t* Makefile.in (SUBDIRS): Add it to the list.\n\t* quaternion/Makefile.in: New file.\n\t* configure.in (AC_OUTPUT): Add quaternion/Makefile.\n\nTue Nov 24 21:41:31 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/saveimage.m: Make it work again for black and white colormaps.\n\n\t* image/imagesc.m: Use rows (colormap), not length (colormap),\n\tsince there can be fewer rows than columns.  Round values to\n\tnearest position in colormap instead of truncating. Correct usage\n\tmessage.\n\nTue Nov 24 14:50:52 1998  A Scott Hodel  <hodel@edalf1.msfc.nasa.gov>\n\n\t* linear-algebra/krylov.m: New arg pflg.  If nonzero, avoid using\n\tzero rows of [A,v] as householder pivots; this avoids spurious\n\tnon-zero entries in returned orthogonal matrix U, but destroys the\n\tHouseholder matrix structure of H.\n\nFri Nov 20 12:46:46 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/logical.m: Just copy input to output if argument is\n\talready a logical object.\n\nFri Nov  6 10:17:00 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* New files from OCST, in control subdiretory:\n\n\t    DEMOcontrol.m      is_siso.m          syschnames.m\n\t    abcddim.m          is_stabilizable.m  syschnamesl.m\n\t    abcddims.m         is_stable.m        syschtsam.m\n\t    analdemo.m         jet707.m           sysconnect.m\n\t    are.m              lqe.m              syscont.m\n\t    axis2dlim.m        lqg.m              syscont_disc.m\n\t    bddemo.m           lqr.m              sysdefioname.m\n\t    bode.m             lsim.m             sysdefstname.m\n\t    bode_bounds.m      ltifr.m            sysdimensions.m\n\t    bodquist.m         lyap.m             sysdisc.m\n\t    buildssic.m        mb.m               sysdup.m\n\t    c2d.m              minfo.m            sysgetsignals.m\n\t    com2str.m          moddemo.m          sysgettsam.m\n\t    controldemo.m      nichols.m          sysgettype.m\n\t    ctrb.m             nyquist.m          sysgroup.m\n\t    d2c.m              obsv.m             sysgroupn.m\n\t    damp.m             ord2.m             sysmult.m\n\t    dare.m             outlist.m          sysout.m\n\t    dcgain.m           packedform.m       sysprune.m\n\t    demomarsyas.m      packsys.m          sysreorder.m\n\t    dezero.m;          parallel.m         sysrepdemo.m\n\t    dgkfdemo.m         place.m            sysscale.m\n\t    dgram.m            polyout.m          syssub.m\n\t    dhinfdemo.m        prompt.m           sysupdate.m\n\t    dlqe.m             pzmap.m            tf2ss.m\n\t    dlqg.m             qzval.m            tf2sys.m\n\t    dlqr.m             rldemo.m           tf2sysl.m\n\t    dlyap.m            rlocus.m           tf2zp.m\n\t    dmr2d.m            rotg.m             tfout.m\n\t    fir2sys.m          run_cmd.m;         tzero.m\n\t    frdemo.m           series.m           tzero2.m\n\t    freqchkw.m         sortcom.m          ugain.m\n\t    freqresp.m         ss2sys.m           unpacksys.m\n\t    gram.m             ss2tf.m            wgt1o.m\n\t    h2norm.m           ss2zp.m            zgfmul.m\n\t    h2syn.m            starp.m            zgfslv.m\n\t    hinf_ctr.m         step.m             zginit.m\n\t    hinfdemo.m         stepimp.m          zgpbal.m\n\t    hinfnorm.m         strappend.m;       zgreduce.m\n\t    hinfsyn.m          susball.m          zgrownorm.m\n\t    hinfsyn_chk.m      swap.m             zgscal.m\n\t    impulse.m          swapcols.m         zgsgiv.m\n\t    is_abcd.m          swaprows.m         zgshsr.m\n\t    is_controllable.m  sys2fir.m          zp2ss.m\n\t    is_detectable.m    sys2ss.m           zp2ssg2.m\n\t    is_dgkf.m          sys2tf.m           zp2sys.m\n\t    is_digital.m       sys2zp.m           zp2tf.m\n\t    is_observable.m    sysadd.m           zpout.m\n\t    is_sample.m        sysappend.m\n\nThu Nov  5 13:28:40 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_OUTPUT): Escape newlinew in macro call with \\.\n\n\t* strings/deblank.m: Make it work for string arrays too.\n\nWed Nov  4 21:51:13 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/housh.m: New file from the OCST.\n\t* linear-algebra/krygetq.m: Ditto.\n\t* linear-algebra/krylov.m: Ditto.\n\t* linear-algebra/krylovb.m: Ditto.\n\t* linear-algebra/qrhouse.m: Ditto.\n\t* general/is_duplicate_entry.m: Ditto.\n\n\t* general/is_symmetric.m: Call is_square instead of doing that\n\tcheck in line.\n\nWed Oct 28 11:51:14 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/is_square.m:\n\n\t* general/isempty.m, general/is_matrix.m: Delete.\n\n\t* general/is_symmetric: Delete special case for strings.  Whether\n\tthe conversion is valid should depend on implicit_str_to_num_ok.\n\n\t* general/is_square.m: If arg is not a matrix, don't check size,\n\tjust return 0.\n\t* general/is_symmetric: Likewise.\n\t* general/is_vector.m: Likewise.\n\t* general/is_scalar.m: Likewise.\n\n\t* general/length.m: Delete.\n\nFri Oct 23 00:21:55 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in: Add finance/Makefile, statistics/base/Makefile,\n\tstatistics/distributions/Makefile, statistics/models/Makefile,\n\tand statistics/tests/Makefile to the list of files to create.\n\n\t* finance/Makefile.in, statistics/base/Makefile.in,\n\tstatistics/distributions/Makefile.in, statistics/models/Makefile.in,\n  \tstatistics/tests/Makefile.in: New files.\n\t* statistics/Makefile.in: Delete file lists.  Now only handle\n\tsubdirectories.\n\t* Makefile.in (SUBDIRS): Add finance.\n\n\t* Move the following files from statistics to statistics/base:\n\n\t    corrcoef.m\n\t    kurtosis.m\n\t    mahalanobis.m\n\t    median.m\n\t    ols.m\n\t    skewness.m\n\t    std.m\n\n\tNew files, from Kurt Hornik's octave-ci package:\n\n\t* finance (new directory):\n\n\t    fv.m\n\t    fvl.m\n\t    irr.m\n\t    nper.m\n\t    npv.m\n\t    pmt.m\n\t    pv.m\n\t    pvl.m\n\t    rate.m\n\t    vol.m\n\n\t* linear-algebra/dmult.m\n\n\t* signal:\n\n\t    arch_fit.m\n\t    arch_rnd.m\n\t    arch_test.m\n\t    arma_rnd.m\n\t    autocor.m\n\t    autocov.m\n\t    autoreg_matrix.m\n\t    bartlett.m\n\t    blackman.m\n\t    diffpara.m\n\t    durbinlevinson.m\n\t    fractdiff.m\n\t    hamming.m\n\t    hanning.m\n\t    hurst.m\n\t    periodogram.m\n\t    rectangle_lw.m\n\t    rectangle_sw.m\n\t    sinetone.m\n\t    sinewave.m\n\t    spectral_adf.m\n\t    spectral_xdf.m\n\t    spencer.m\n\t    stft.m\n\t    synthesis.m\n\t    triangle_lw.m\n\t    triangle_sw.m\n\t    yulewalker.m\n\n\t* statistics/base (new directory):\n\n\t    center.m\n\t    cloglog.m\n\t    cor.m\n\t    cov.m\n\t    cut.m\n\t    iqr.m\n\t    kendall.m\n\t    logit.m\n\t    mean.m\n\t    meansq.m\n\t    moment.m\n\t    ppplot.m\n\t    probit.m\n\t    qqplot.m\n\t    range.m\n\t    ranks.m\n\t    run_count.m\n\t    spearman.m\n\t    statistics.m\n\t    studentize.m\n\t    table.m\n\t    values.m\n\t    var.m\n\n\t(Replaces cov.m and mean.m with new versions.)\n\n\t* statistics/distributions (new directory):\n\n\t    beta_cdf.m\n\t    beta_inv.m\n\t    beta_pdf.m\n\t    beta_rnd.m\n\t    binomial_cdf.m\n\t    binomial_inv.m\n\t    binomial_pdf.m\n\t    binomial_rnd.m\n\t    cauchy_cdf.m\n\t    cauchy_inv.m\n\t    cauchy_pdf.m\n\t    cauchy_rnd.m\n\t    chisquare_cdf.m\n\t    chisquare_inv.m\n\t    chisquare_pdf.m\n\t    chisquare_rnd.m\n\t    discrete_cdf.m\n\t    discrete_inv.m\n\t    discrete_pdf.m\n\t    discrete_rnd.m\n\t    empirical_cdf.m\n\t    empirical_inv.m\n\t    empirical_pdf.m\n\t    empirical_rnd.m\n\t    exponential_cdf.m\n\t    exponential_inv.m\n\t    exponential_pdf.m\n\t    exponential_rnd.m\n\t    f_cdf.m\n\t    f_inv.m\n\t    f_pdf.m\n\t    f_rnd.m\n\t    gamma_cdf.m\n\t    gamma_inv.m\n\t    gamma_pdf.m\n\t    gamma_rnd.m\n\t    geometric_cdf.m\n\t    geometric_inv.m\n\t    geometric_pdf.m\n\t    geometric_rnd.m\n\t    hypergeometric_cdf.m\n\t    hypergeometric_inv.m\n\t    hypergeometric_pdf.m\n\t    hypergeometric_rnd.m\n\t    kolmogorov_smirnov_cdf.m\n\t    laplace_cdf.m\n\t    laplace_inv.m\n\t    laplace_pdf.m\n\t    laplace_rnd.m\n\t    logistic_cdf.m\n\t    logistic_inv.m\n\t    logistic_pdf.m\n\t    logistic_rnd.m\n\t    lognormal_cdf.m\n\t    lognormal_inv.m\n\t    lognormal_pdf.m\n\t    lognormal_rnd.m\n\t    normal_cdf.m\n\t    normal_inv.m\n\t    normal_pdf.m\n\t    normal_rnd.m\n\t    pascal_cdf.m\n\t    pascal_inv.m\n\t    pascal_pdf.m\n\t    pascal_rnd.m\n\t    poisson_cdf.m\n\t    poisson_inv.m\n\t    poisson_pdf.m\n\t    poisson_rnd.m\n\t    stdnormal_cdf.m\n\t    stdnormal_inv.m\n\t    stdnormal_pdf.m\n\t    stdnormal_rnd.m\n\t    t_cdf.m\n\t    t_inv.m\n\t    t_pdf.m\n\t    t_rnd.m\n\t    uniform_cdf.m\n\t    uniform_inv.m\n\t    uniform_pdf.m\n\t    uniform_rnd.m\n\t    weibull_cdf.m\n\t    weibull_inv.m\n\t    weibull_pdf.m\n\t    weibull_rnd.m\n\t    wiener_rnd.m\n\n\t* statistics/models (new directory):\n\n\t    logistic_regression.m\n\t    logistic_regression_derivatives.m\n\t    logistic_regression_likelihood.m\n\n\t* statistics/tests (new directory):\n\n\t    anova.m\n\t    bartlett_test.m\n\t    chisquare_test_homogeneity.m\n\t    chisquare_test_independence.m\n\t    cor_test.m\n\t    f_test_regression.m\n\t    hotelling_test.m\n\t    hotelling_test_2.m\n\t    kolmogorov_smirnov_test.m\n\t    kolmogorov_smirnov_test_2.m\n\t    kruskal_wallis_test.m\n\t    manova.m\n\t    mcnemar_test.m\n\t    prop_test_2.m\n\t    run_test.m\n\t    sign_test.m\n\t    t_test.m\n\t    t_test_2.m\n\t    t_test_regression.m\n\t    u_test.m\n\t    var_test.m\n\t    welch_test.m\n\t    wilcoxon_test.m\n\t    z_test.m\n\t    z_test_2.m\n\nThu Oct 22 12:25:55 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* time/date.m: Use %Y, not %y in format string, for Matlab 5\n\tcompatibility and to avoid Y2K problems.\n\nMon Oct 19 17:26:35 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* polynomial/polyfit.m: Just use the \\ operator to handle the\n\tleast-squares solution.\n\nThu Sep  3 12:40:47 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/str2num.m: If eval returns a string, return an empty matrix.\n\n\t* strings/strrep.m: Don't convert args to numeric values.\n\tPrevent warnings for empty string args.\n\tFrom Georg Thimm <thimm@idiap.ch>.\n\n\t* strings/strcat.m: Prevent warnings for empty string args.\n\nWed Sep  2 17:20:24 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/menu.m: Remove special case for empty string\n\treturned from input().  Add second arg to eval() to catch errors.\n\nThu Jun 18 16:32:15 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__plt__.m: Don't call usleep.\n\nMon May 18 11:42:36 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/dot.m: New function.\n\n\t* strings/lower.m, strings/upper.m: New functions, for Matlab\n\tcompatibility.\n\nFri May 15 01:16:53 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/hist.m: Also allow just one output argument.\n\nSun May 10 23:00:45 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/deblank.m: Make it work if the string is only blanks.\n\nTue May  5 00:53:36 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__plt2mv__.m: Delete calls to keyboard.\n\nMon May  4 11:43:31 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/oneplot.m: Fix typo.\n\nWed Apr 22 12:11:27 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/flops.m: Allow a single argument too.\n\nTue Apr 21 10:18:20 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/str2mat.m: Also handle case when there are no empty\n\tstrings correctly.\n\nMon Apr 20 22:14:15 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/isletter.m: New function, for Matlab compatibility.\n\nFri Apr 17 10:53:39 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/str2mat.m: Handle string matrices too.\n\nWed Apr 15 11:16:01 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* audio/loadaudio.m: Accept \"pcm\" as another file extension for\n\tlinear encoding.\n\n\t* audio/saveaudio.m, audio/loadaudio.m, audio/playaudio.m,\n\taudio/record.m: Open files in binary mode.\n\nFri Apr 10 10:46:21 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/dump_prefs.m: Use string array for list of values.\n\tMove functionality of dump_1_pref here, but use built-in function\n\ttype to extract value, and put it inside try/catch block.\n\t* miscellaneous/dump_1_pref.m: Delete unused function.\n\nWed Apr  8 13:17:58 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__pltopt1.m__: New file.\n\t* plot/__pltopt.m__: Handle opt as a string array by calling\n\t__pltopt1__ multiple times and returning a string array with rows\n\tcorresponding to the rows of opt.\n\t* plot/__plt2ss__.m, plot/__plt2vv__.m, plot/__plt2vm__.m,\n\tplot/__plt2mv__.m, plot/__plt2mm__.m: Handle fmt as a string\n\tarray.\n\nFri Mar 27 03:00:40 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/mplot.m: Fix misspellings of global variables.\n\tDon't call clearplot.\n\nTue Mar 17 17:45:25 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/subplot.m, plot/multiplot.m: Set gnuplot_command_replot to\n\t\"cle;rep\" when going in ot multiplot mode.\n\t* plot/oneplot.m: Reset gnuplot_command_replot to \"rep\" when\n\tswitching out of multiplot mode.\n\nFri Feb 20 01:31:32 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/mplot.m, plot/subplot.m, plot/oneplot.m, plot/multiplot.m,\n\tplot/subwindow.m: Call clearplot after setting up multiplot mode.\n\nTue Feb  3 00:18:40 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* special-matrix/sylvester_matrix.m: Rename from hadamard.m\n\n\t* miscellaneous/bug_report.m: Don't try to get smart with\n\tOCTAVE_HOME.  Assume octave-bug can be found in EXEC_PATH.\n\n\t* Makefile.in (install): Create separate ls-R files for\n\t$(datadir) and $(libexecdir).\n\t(uninstall): Remove both ls-R files.\n\nSat Jan 31 01:09:32 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* signal/fftshift.m: New file.\n\n\t* plot/contour.m: Fix for non-square case.\n\n\t* general/randperm.m: New file.\n\nFri Jan 30 15:20:39 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/betai.m: Restore file for compatibility with previous\n\tversions.  Call betainc with reordered args.\n\t* specfun/gammai.m: Likewise, call gammainc with reordered args.\n\nWed Jan 28 22:44:59 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/contour.m: Handle discrete contour levels.\n\nTue Jan 27 04:31:22 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/lyap.m: For compatibility with Matlab, solve\n \tA*X + X*A' + C = 0 instead of A'*X + X*A + C = 0.\n\nWed Dec 10 00:14:29 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/bessel.m: New file.\n\n\t* specfun/betai.m, specfun/betainc.m, specfun/gammai.m,\n\tspecfun/gammainc.m: Delete.\n\nWed Nov 19 00:19:18 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/colormap.m: Initialize __current_color_map__ in global\n\tstatement.\n\t* miscellaneous/toc.m: Initialize __tic_toc_timestamp__ in global\n\tstatement.\n\t* plot/axis.m: Initialize __current_axis__ in global statement.\n\t* plot/mplot.m, plot/multiplot.m, plot/oneplot.m, plot/subplot.m,\n\tplot/subwindow.m: Initialize __multiplot_mode__ in global statement.\n\nTue Nov 18 01:35:50 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* time/tic.m: Rename _time_tic_called to __tic_toc_timestamp__.\n\t* time/toc.m: Likewise.\n\n\t* image/colormap.m: Rename CURRENT_COLOR_MAP to __current_color_map__.\n\n\t* plot/mplot.m, plot/multiplot.m, plot/subplot.m: Don't do\n\tanything special for automatic_replot when in multiplot mode --\n\trecent 3.6beta releases handle this correctly.\n\n\t* plot/figure.m: Ensure that we are not in multiplot mode before\n\tsetting the terminal type.\n\n\t* plot/mplot.m, plot/multiplot.m, plot/oneplot.m, plot/subplot.m,\n \tplot/subwindow.m: Use leading and trailing underscores for\n \t`private' globals.\n\n\t* plot/oneplot.m: Don't do anything if gnuplot_has_multiplot is false.\n\nFri Nov 14 10:53:11 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__pltopt__.m: Use sprintf instead of strcat when adding TITLE.\n\nFri Oct 10 11:18:10 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/gammai.m: Avoid problems with whitespace when\n\tconstructing matrices.\n\n\t* polynomial/polyfit.m: Compute yf correctly.  From Seung Lee\n\t<SJL@nrc.gov>.  Also return yf in the same orientation as the\n\toriginal y vector.\n\nFri Sep 19 17:04:40 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/cross.m: Use direct formula instead of calling\n\tdet three times in a loop.  If both args are column (row) vectors,\n\treturn a column (row) vector.  If they don't match, pay attention\n\tto the value of prefer_column_vectors.\n\nThu Aug 28 15:31:20 1997  Rolf Fabian  <fabian@olymp.Umwelt.TU-Cottbus.de>\n\n\t* polynomial/polyvalm.m: Don't assume orthogonal eigenvectors for\n\tnonsymmetric matrices.\n\n\t* general/tril.m: Fix usage message.\n\n\t* polynomial/polyvalm.m: Fix error messages.\n\t* polynomial/polyderiv.m: Likewise.\n\t* polynomial/polyval.m: Likewise.\n\nWed Aug 13 14:14:16 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/blanks.m: Allow blanks(0) to return empty string.\n\tAllow negative arguments if treat_neg_dim_as_zero is true.\n\nWed Jun 25 21:26:24 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/mesh.m: Set noparametric plot mode after plotting.\n\nWed Jun 25 21:06:10 1997  Rick Niles  <niles@axp745.gsfc.nasa.gov>\n\n\t* plot/__pltopt__.m: Handle key/legend names.\n\tCorrectly set colors, line styles, and point styles.\n\nWed Jun 25 13:34:06 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* polynomial/polyfit.m: Return fit y values as second output.\n\tDon't use QR factorization to solve least squares problem.\n\nWed Jun 18 10:24:00 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/dlqr.m: Use ao, not a, to compute k.\n\nTue Jun  3 12:16:00 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/path.m: New file.\n\nWed May 21 11:45:31 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/bug_report.m: Pass file id to dump_prefs, not file\n\tname.\n\nMon May 12 02:04:01 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/erfinv.m: Add missing semicolon.\n\nWed Apr  2 22:04:03 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/xor.m: Make type of return value logical.\n\nFri Mar 28 16:19:53 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/dump_prefs.m: Delete call to dump_1_pref for\n\twarn_comma_in_global_decl.\n\nTue Mar 25 22:00:49 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/bug_report.m: Use __OCTAVE_HOME__ to find\n\toctave-bug script.\n\nMon Mar 24 16:49:47 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/dump_prefs.m: Delete call to dump_1_pref for\n\tprefer_zero_one_indexing.\n\n\t* general/logical.m: New file.\n\nSat Mar 15 15:07:30 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/nextpow2.m: Correctly handle new meaning of is_scalar()\n\tand is_vector().\n\nThu Mar 13 16:36:35 1997  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* specfun/erfinv.m: Scale update by sqrt (pi) / 2.\n\tUse tolerance of 2 * eps.\n\nWed Mar 12 16:57:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-strip): New target.\n\t* audio/Makefile.in: Ditto.\n\t* control/Makefile.in: Ditto.\n\t* elfun/Makefile.in: Ditto.\n\t* general/Makefile.in: Ditto.\n\t* image/Makefile.in: Ditto.\n\t* io/Makefile.in: Ditto.\n\t* linear-algebra/Makefile.in: Ditto.\n\t* miscellaneous/Makefile.in: Ditto.\n\t* plot/Makefile.in: Ditto.\n\t* polynomial/Makefile.in: Ditto.\n\t* set/Makefile.in: Ditto.\n\t* signal/Makefile.in: Ditto.\n\t* specfun/Makefile.in: Ditto.\n\t* special-matrix/Makefile.in: Ditto.\n\t* startup/Makefile.in: Ditto.\n\t* statistics/Makefile.in: Ditto.\n\t* strings/Makefile.in: Ditto.\n\nTue Mar 11 10:14:26 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* elfun/coth.m: Write as cosh(x) ./ sinh(x) instead of 1 ./ tanh(x).\n\nFri Mar  7 23:06:48 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/corrcoef.m: Make it actually work.\n\nThu Mar  6 12:36:30 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/corrcoef.m: Don't fail if single argument is a matrix.\n\nSat Mar  1 15:23:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.5 released.\n\nWed Feb 26 01:48:28 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (maintainer-clean): Also remove configure.\n\n\t* signal/fftconv.m: Check inputs with is_vector(), not is_matrix().\n\n\t* general/is_matrix.m: Return zero for empty matrices.\n\nTue Feb 25 15:16:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/vech.m: Size result just once.\n\nSun Feb 23 00:15:57 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/is_square.m: Handle empty matrices correctly.\n\t* general/is_symmetric.m: Handle empty matrices and strings.\n\nSat Feb 22 01:06:22 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* polynomial/conv.m: Check inputs with is_vector(), not is_matrix().\n\t* polynomial/deconv.m: Likewise.\n\t* polynomial/polyderiv.m: Likewise.\n\t* polynomial/polyinteg.m: Likewise.\n\t* polynomial/polyreduce.m: Likewise.\n\t* polynomial/polyval.m: Likewise.\n\t* polynomial/polyvalm.m: Likewise.\n\t* general/postpad.m: Likewise.\n\t* general/prepad.m: Likewise.\n\n\t* polynomial/compan.m: Check input with is_vector(), not\n\tis_matrix().  Handle scalar case.\n\nFri Feb 21 13:36:58 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/contour.m: Order data so that it is consistent with\n\tmeshgrid and mesh.\n\n\t* plot/meshdom.m, plot/meshgrid.m: Change help message.\n\t* plot/sombrero.m: Use meshgrid, not meshdom.\n\nThu Feb 20 02:58:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.4 released.\n\nWed Feb 19 10:30:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/paren.m: New file.\n\nTue Feb 18 09:22:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.3 released.\n\nThu Feb 13 19:06:42 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/saveimage.m: Only clip image data that is actually out of\n\trange.\n\nSun Feb  9 19:52:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/is_matrix.m: Scalars, vectors, and empty matrices may\n\talso be considered to be matrices.\n\n\t* general/is_vector.m: Scalars may also be considered to be vectors.\n\n\t* general/isempty.m: Use size(), not rows() and columns().\n\n\t* plot/contour.m: Convert set to gset.\n\tSet view to 0, 0, 1, 1, not 0, 0, 1.9, 1.\n\nFri Feb  7 12:55:55 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/erfinv.m: Fix typo in last change.\n\nFri Jan 31 09:30:16 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/loadimage.m: Make it possible to load files with image\n\tdata named X or img.\n\n\t* image/default.img: Change name of image from X to img to match\n\twhat saveimage does now.\n\n\t* image/loadimage.m: Rename X to be img, to match what saveimage\n\tdoes now.\n\nMon Jan 27 13:48:31 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.2 released.\n\n\t* plot/__plt__.m: Use usleep() instead of replot to try to avoid\n\tweird missing-lines bug without creating extra plots unecessarily.\n\nSat Jan 25 22:37:07 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in, audio/Makefile.in, control/Makefile.in,\n\telfun/Makefile.in, general/Makefile.in, image/Makefile.in,\n\tio/Makefile.in, linear-algebra/Makefile.in,\n\tmiscellaneous/Makefile.in, plot/Makefile.in,\n\tpolynomial/Makefile.in, set/Makefile.in, signal/Makefile.in,\n\tspecfun/Makefile.in, special-matrix/Makefile.in,\n\tstartup/Makefile.in, statistics/Makefile.in, strings/Makefile.in,\n\ttime/Makefile.in (bin-dist): New target.\n\nWed Jan 22 11:28:30 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/erfinv.m: Avoid A([]) = X, X != [] error.\n\nTue Jan 21 11:16:40 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/xor.m: Make it work.\n\nMon Jan 20 12:28:34 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/sombrero.m: Doc fix.\n\nTue Jan  7 00:16:52 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.1 released.\n\nThu Dec 19 22:16:46 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* elfun/lcm.m: Replace missing if statement.\n\n\t* elfun/gcd.m: Report error if no input args.\n\t* elfun/lcm.m: Likewise.\n\nMon Dec 16 15:23:04 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install): Use ls -LR to create ls-R database.\n\tAlso list contents of $libexecdir/octave in ls-R database.\n\nTue Dec 10 01:43:07 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0 released.\n\nFri Dec  6 15:23:46 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.94.\n\nSun Dec  1 20:55:34 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/str2num.m: New file.\n\nWed Nov 20 01:00:24 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.93.\n\nTue Nov 19 15:13:35 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* linear-algebra/commutation_matrix.m, linear-algebra/cross.m,\n\tlinear-algebra/duplication_matrix.m, linear-algebra/vec.m,\n\tlinear-algebra/vech.m: New files from Kurt Hornik.\n\n\t* general/nextpow2.m, general/shift.m, general/diff.m,\n\tgeneral/common_size.m: New files from Kurt Hornik.\n\n\t* miscellaneous/bincoeff.m, miscellaneous/xor.m:\n\tNew files from Kurt Hornik.\n\n\t* signal/detrend.m: New file from Kurt Hornik.\n\n\t* specfun/betai.m, specfun/gammai.m, specfun/erfinv.m,\n\tspecfun/pow2.m, specfun/log2.m:\n\tNew files and updates from Kurt Hornik.\n\nFri Nov 15 18:13:00 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/__plt__.m: Add explicit replot after last command is\n\tissued, to force all lines to be displayed.  Hmm.\n\nThu Nov 14 00:06:34 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/axis.m, plot/bottom_title.m, plot/contour.m,\n\tplot/figure.m, plot/grid.m, plot/loglog.m, plot/mesh.m,\n\tplot/mplot.m, plot/multiplot.m, plot/oneplot.m, plot/plot.m,\n\tplot/plot_border.m, plot/polar.m, plot/semilogx.m,\n\tplot/semilogy.m, plot/subplot.m, plot/subwindow.m, plot/title.m,\n\tplot/top_title.m, plot/xlabel.m, plot/ylabel.m, plot/zlabel.m:\n\tUset gset, not set.\n\n\t* Version 1.92.\n\nThu Nov  7 12:43:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/saveimage.m: When writing PostScript, name Octave as the\n\talmighty Creator.  Use single call to fprintf instead of looping.\n\n\t* image/Makefile.in: Delete references to octtopnm.\n\n\t* general/logspace.m: Doc fix.\n\n\t* Version 1.91.\n\nSat Nov  2 21:06:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/image.m: Use tmpnam() instead of home-brew scheme.\n\n\t* audio/record.m, audio/playaudio.m: Use tmpnam() instead of\n\toctave_tmp_file_name().  Use unwind_protect to ensure tmp file is\n\tdeleted.\n\t* miscellaneous/bug_report.m: Likewise.  Also use unlink() instead\n\tof a system() command to delete the tmp file.\n\nWed Oct 30 17:19:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.90.\n\n\t* Makefile.in (DISTFILES): Add ChangeLog.\n\nThu Oct 10 17:31:01 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/subplot.m, plot/multiplot.m, plot/mplot.m:\n\tDon't check for string value of automatic_replot.\n\n\t* image/ind2ind.m, image/ind2rgb.m, image/ind2gray.m:\n\tTemporarily set do_fortran_indexing to 1, not \"true\".\n\n\t* miscellaneous/menu.m: Temporarily set page_screen_output to 0,\n\tnot \"false\".\n\n\t* linear-algebra/cond.m: Don't compare propagate_empty_matrices to\n\t\"false\".\n\nTue Aug 20 18:27:36 1996  Kurt Hornik  <Kurt.Hornik@ci.tuwien.ac.at>\n\n\t* strings/substr.m: Allow negative OFFSET.  LEN is now optional.\n\nMon Jul 15 16:15:22 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/bug_report.m: Don't redirect output to /dev/tty in\n\tsystem command.\n\nFri Jul 12 12:24:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* __plr1__.m: Renamed from polar_int_1.m.\n\t* __plr2__.m: Renamed from polar_int_2.m.\n\t* __plr__.m: Renamed from polar_int.m.\n\t* __plt1__.m: Renamed from plot_int_1.m.\n\t* __plt2__.m: Renamed from plot_int_2.m.\n\t* __plt2mm__.m: Renamed from plot_2_m_m_.m.\n\t* __plt2mv__.m: Renamed from plot_2_m_v_.m.\n\t* __plt2ss__.m: Renamed from plot_2_s_s_.m.\n\t* __plt2vm__.m: Renamed from plot_2_v_m_.m.\n\t* __plt2vv__.m: Renamed from plot_2_v_v_.m.\n\t* __plt__.m: Renamed from plot_int.m.\n\t* __pltopt__.m: Renamed from plot_opt.m.\n\tChange all callers.\n\nThu Jul 11 17:24:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* All .m files: Add regular Author:, Created:, and Adapted-By:\n\tcomments like those found in Emacs lisp files.\n\nMon Jun 24 04:16:41 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* All .m files: Change comment style.\n\nFri Jun 14 01:42:21 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* bottom_title.m, mplot.m, multiplot.m, oneplot.m, plot_border.m,\n\tsubplot.m, subwindow.m, top_title.m:\n\tPrint error message if gnuplot_has_multiplot is not true.\n\nThu Jun  6 00:18:54 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/figure.m: New function.\n\nWed Jun  5 18:19:00 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/strrep.m: New function.\n\nThu May 23 15:04:22 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strings/bin2dec.m, strings/blanks.m, strings/deblank.m,\n\tstrings/dec2bin.m, strings/dec2hex.m, strings/findstr.m,\n\tstrings/hex2dec.m, strings/index.m, strings/rindex.m,\n\tstrings/split.m, strings/str2mat.m, strings/substr.m:\n\tNew functions from Kurt Hornik, heavily modified by jwe.\n\n\t* general/reshape.m: Allow strings to be reshaped too.\n\n\t* strings/strcmp.m: No longer need to set implicit_str_to_num_ok.\n\tAlways return a scalar.\n\nWed May 22 19:52:11 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* polynomial/polyfit.m: Make orientation of result compatible with\n\tMatlab.\n\nSat May 18 17:32:15 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* polynomial/polyfit.m: Add missing close paren.\n\nThu May 16 10:23:11 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/plot_opt.m: Set compatibility arg in call to sscanf.\n\n\t* io/scanf.m: Delete.\n\nMon May 13 09:37:38 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/median.m: Fix typo in usage message.\n\nWed Apr 24 02:45:52 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/popen2.m: New file.\n\nWed Apr 17 18:34:04 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_OUTPUT): Add io/Makefile.\n\n\t* io: New directory.\n\t* Makefile.in (SUBDIRS): Add it to the list.\n\n\t* miscellaneous/flops.m: New file.\n\nFri Mar 22 04:40:48 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/cputime.m: Return three arguments instead of a\n\tvector, for compatibility with previous versions and with Matlab\n\t(which only returns one scalar value).\n\nWed Mar 20 05:09:48 1996  Kurt Hornik  <Kurt.Hornik@tuwien.ac.at>\n\n\t* general/triu.m: Compute lower bound on loop index correctly.\n\t* general/tril.m: Likewise, for upper bound.\n\nTue Feb  6 09:29:43 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/saveimage.m: For color images, make sure indices into\n\ttemporary colormap and result matrix have proper orientation.\n\tSet grey flag correctly.\n\nTue Jan  9 00:12:14 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* statistics/std.m: Use better formula (from Jim Van Zandt\n\tjrv@vanzandt.mv.com).\n\nSun Jan  7 20:12:14 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* meshgrid.m: New file (from Jim Van Zandt jrv@vanzandt.mv.com).\n\t* mesh.m: Transpose Z if only one arg.\n \tHandle case of all three args being matrices (from Jim Van Zandt\n\tjrv@vanzandt.mv.com).\n\t* meshdom.m: Undo previous change.\n\nWed Dec 20 13:48:12 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* configure.in (AC_OUTPUT): Add audio/Makefile\n\nThu Nov 16 13:07:07 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* audio: New directory of files from Kurt Hornik and Andreas\n\tWeingessel.\n\t* audio/Makefile.in: New file.\n\t* Makefile.in (SUBDIRS): Add audio to the list.\n\nMon Nov  6 07:29:35 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* polynomial/polyfit.m: Use `economy-stle' QR factorization.\n\nFri Nov  3 00:38:46 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/mesh.m: Require, length (y) == rows (z) and length (x) ==\n\tcolumns (z), not the other way around.\n\t* plot/meshdom.m: Don't reverse order of elements in y.\n\nThu Nov  2 23:56:53 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/axis.m: Return current axis if nargin == 0.\n\nTue Oct 31 04:11:28 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* polynomial/roots.m: Updates from Kurt Hornik.\n\n\t* polynomial/polyder.m: New file.\n\n\t* polynomial/polyderiv.m: Give return value and arg different names.\n\nMon Oct 30 23:27:02 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* specfun/betainc.m: New file.\n\t* specfun/gammainc.m: New file.\n\nWed Oct 18 23:45:52 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* general/strerror.m: New file.\n\t* general/perror.m: Implement using strerror().\n\nThu Oct  5 03:21:36 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/bottom_title.m plot/mplot.m plot/multiplot.m plot/oneplot.m\n\tplot/plot_border.m plot/subplot.m plot/subwindow.m\n\tplot/top_title.m plot/zlabel.m: New files, from Vinayak Dutt.\n\n\t* image/saveimage.m: Round img values first.\n\nTue Oct  3 03:55:18 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/abcddim.m control/are.m general/tril.m general/triu.m\n\timage/saveimage.m linear-algebra/kron.m linear-algebra/norm.m\n\tlinear-algebra/null.m miscellaneous/etime.m plot/contour.m\n\tplot/mesh.m plot/plot_int.m plot/polar_int.m\n\tspecial-matrix/hankel.m special-matrix/toeplitz.m\n\ttuwien/strfun/split.m: Add missing semicolons.\n\n\t* plot/polar_int.m: Use .', not ' to make vectors conform.\n\n\t* image/Makefile.in: Don't build or install octtoppm.\n\n\t* image/saveimage.m: Rewrite to avoid using octoppm and pbm\n\troutines so that people who don't have the pbm stuff installed\n\tcan still use this function.\n\nMon Oct  2 05:10:44 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* image/saveimage.m: Better error checking, clean up a bit.\n\nTue Sep 26 00:04:56 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* plot/plot_opt.m: Change more to more_opts as a temporary fix to\n\tavoid conflict with new built-in text-style function more.\n\n\t* linear-algebra/norm.m: Also allow 2nd arg == \"inf\".\n\n\t* startup/Makefile.in (install): Also install octaverc in\n\t$localfcnfiledir/startup/octavrc.\n\nWed Sep 20 00:01:30 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkinstalldirs: New file.\n\t* Makefile.in (DISTFILES): Add it to the list.\n\n\t* Makefile.in (DISTFILES): Distribute configure.in and configure.\n\nThu Sep 14 03:56:19 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* special-matrix/hankel.m: Compatibility fix.  Complain if\n\tr(1) != c(nr), not if r(1) != c(1).\n\n\t* signal/filter.m: Doc fix.\n\nWed Sep 13 03:19:05 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* miscellaneous/cputime.m: Use new resource structure names (no\n\tru_ or tv_ prefixes).\n\nTue Sep 12 02:20:44 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* time/ctime.m: Fix doc string and usage message.\n\nMon Sep 11 18:43:46 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* time/clock.m: Use new time structure names (no tm_ prefix).\n\nThu Aug 24 20:53:08 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* control/c2d.m: Make function work for any value of\n\twhitespace_in_literal_matrix.\n\t* control/dare.m: Likewise.\n\t* control/tzero.m: Likewise.\n\t* elfun/gcd.m: Likewise.\n\t* elfun/lcm.m: Likewise.\n\t* general/postpad.m: Likewise.\n\t* general/prepad.m: Likewise.\n\t* linear-algebra/kron.m: Likewise.\n\t* miscellaneous/etime.m: Likewise.\n\t* polynomial/conv.m: Likewise.\n\t* polynomial/deconv.m: Likewise.\n\t* polynomial/poly.m: Likewise.\n\t* polynomial/roots.m: Likewise.\n\t* signal/filter.m: Likewise.\n\t* signal/freqz.m: Likewise.\n\t* signal/fftfilt.m: Likewise.\n\nTue Jun  6 22:34:04 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* miscellaneous/is_leap_year.m: Make work for vector args.\n\nTue May  2 16:18:33 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* plot/polar_int_2.m: Add missing semicolons.\n\tSet theta = theta', not rho'.\n\nSun Apr 30 11:19:11 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* polynomial/roots.m: Make it work for any value of\n\twhitespace_in_literal_matrix.\n\nMon Apr 10 09:37:17 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* configure.in: New file.\n\nThu Mar 30 13:29:35 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* control/lyap.m: Add missing semicolon.\n\n\t* miscellaneous/cputime.m: New function file.\n\nWed Mar 29 22:50:49 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* time: New directory.\n\t* time/asctime.m, time/clock.m, time/ctime.m, time/date.m:\n\tNew function files.\n\t* time/Makefile.in: New file.\n\t* Makefile.in (SUBDIRS): Add time.\n\nThu Mar 23 15:42:26 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* polynomial/polyreduce.m: Make sure initial index is not empty.\n\nTue Mar 14 23:38:24 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* plot/plot_int_1.m: Transpose data with .', not '.\n\nFri Mar 10 10:40:13 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makefile.in (install uninstall clean mostlyclean distclean\n\trealclean): Use SUBDIR_FOR_COMMAND.  Combine actions.\n\nSun Feb 26 22:18:22 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makefile.in (install): Create ls-R database file.\n\t(uninstall): Delete it.\n\nFri Feb 24 10:36:01 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* image/saveimage.m: Fix typo.\n\nSee ChangeLog.1 in the top level directory for earlier changes.\n"
  },
  {
    "path": "etc/OLD-ChangeLogs/src-ChangeLog",
    "content": "2011-04-19  Kai Habel  <kai.habel@gmx.de>\n\n\t* src/DLD-FUNCTIONS/__init_fltk__.cc(plot_window::plot_window):\n\tInstantiate canvas before uimenu.\n\n2011-04-13  Rik  <octave@nomad.inbox5.com>\n\n\t* help.cc: Add spaces after commas in @seealso blocks.\n\n2011-04-12  Rik  <octave@nomad.inbox5.com>\n\n\t* load-path.cc (restoredefaultpath): Correct use of it's -> its in\n\tdocumentation.\n\n2011-04-10  John Eaton  <jwe@octave.org>\n\n\t* graphics.cc (Fishandle) Accept vector of handles (bug #33025).\n\n2011-04-08  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/eig.cc,\n\tDLD-FUNCTIONS/hess.cc, DLD-FUNCTIONS/pinv.cc, DLD-FUNCTIONS/schur.cc,\n\tDLD-FUNCTIONS/sqrtm.cc, DLD-FUNCTIONS/svd.cc, data.cc: Improve\n\tdocstrings.\n\n2011-04-06  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/dmperm.cc, data.cc: Clean up operator and function\n\tindices.\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/nproc.cc: Spellcheck documentation for 3.4.1 release.\n\n2011-04-04  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/colamd.cc, data.cc, file-io.cc: Grammarcheck files\n\tfor 3.4.1 release.\n\n2011-04-03  Rik  <octave@nomad.inbox5.com>\n\n\t* input.cc (add_input_event_hook, remove_input_event_hook): Improve\n\tdocstring.\n\t* utils.cc (isvarname): Add seealso link to iskeyword().\n\t* variables.cc (missing_function_hook): Improve docstring.\n\n2011-04-03  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/dot.cc (blkmm): Improve docstring.\n\n2011-04-03  Rik  <octave@nomad.inbox5.com>\n\n\t* data.cc (diag): Add documentation for 3-input form of diag.  Add new\n\ttests.\n\n2011-04-03  Rik  <octave@nomad.inbox5.com>\n\n\t* data.cc (diag): Reverse previous changeset.  Return 3-input form\n\tof diag().\n\n2011-04-01  Rik  <octave@nomad.inbox5.com>\n\n\t* data.cc (diag): Remove archaic 3-input argument form of function.\n\tAdd all calling forms of function to docstring.\n\n2011-04-01  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/filter.cc: Fix orientation of initial conditions vector\n\t(bug #32741).  Revamp test vectors.\n\n2011-04-01  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/__fltk_uigetfile__.cc, DLD-FUNCTIONS/__init_fltk__.cc:\n\tCorrect typo in #include path (bug #32972).\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/onCleanup.cc: Remove non-existent @seealso link in\n\tdocstring.\n\n2011-03-31  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/quadcc.cc: Add reference to original paper in docstring.\n\n2011-03-30  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* file-io.cc: Document the \"all\" parameter to fclose.\n\n2011-03-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.cc: Prevent ticks from being cropped by round-off errors\n\twhen limmode == auto (bug #32701).\n\n2011-03-28  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/inv.cc (inv, inverse), DLD-FUNCTIONS/tril.cc (tril),\n\tdata.cc (cumsum, szie), file-io.cc (fgets), ov-typeinfo.cc (typeinfo),\n\tov-usr-fcn.cc (nargout), utils.cc (make_absolute_filename),\n\tvariables.cc (who): Improve docstrings\n\n2011-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (Fmkstemp): Use gnulib::mkstemp.\n\t* DLD-FUNCTIONS/__init_fltk__.cc (f): Use gnulib::floor.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* dot.cc: Improve seealso cross references in docstring.\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* help.cc (get_help_text, get_help_text_from_file): Improve docstrings.\n\n2011-03-17  John W. Eaton  <jwe@octave.org>\n\n\t* ov-float.cc (octave_float_scalar::do_index_op): Widen to float\n\tmatrix, not double.\n\n2011-03-17  Rik  <octave@nomad.inbox5.com>\n\n\t* syscalls.cc (gethostname): Redo documentation string.\n\n2011-03-17  Iain Murray  <iain@iainmurray.net>\n\n\t* DLD-FUNCTIONS/nprocs.cc: Delete file.\n\t* DLD-FUNCTIONS/nproc.cc: New file.  New function nproc provided by\n\tgnulib.\n\t* DLD-FUNCTIONS/module-files: Add nproc.cc.\n\n2011-03-16  Iain Murray  <iain@iainmurray.net>\n\n\t* DLD-FUNCTIONS/nprocs.cc: New file.\n\t* DLD-FUNCTIONS/module-files: Add nprocs.cc.\n\tExpose nprocs and nprocs_conf from gnulib.\n\n2011-03-15  Marco Caliari  <marco.caliari@univr.it>\n\n\t* graphics.cc: Simplify calculation of number of tick labels.  Fixes\n\tbug #32692.\n\n2011-03-13  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc (plot_window::plot_window):\n\tRevert changes from 2011-02-26.\n\n2011-03-10  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in: Add PERSISTENT mode to listener_mode.\n\t(base_property::delete_listener): Take into account persistent\n\tmode of a listener.\n\t* graphics.cc (addlistener, dellistener): Accept a new optional\n\targument for persistent listeners.\n\n2011-03-07  Konstantinos Poulios  <logari81@googlemail.com>\n\n\tBug #32482.\n\n\t* graphics.h.in (axes::properties::update_yaxislocation,\n\taxes::properties::update_yaxislocation):\n\tHook update_ylabel_position and update_xlabel_position\n\trespectively.\n\n2011-03-06  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.cc (axes::properties::update_xlabel_position,\n\taxes::properties::update_ylabel_position,\n\taxes::properties::update_zlabel_position,\n\taxes::properties::update_title_position):\n\tDetermine position also for empty axes labels/titles in order\n\tto improve the tightinset calculation.\n\t(axes::properties::get_extent): Take position of empty strings\n\tinto account for the calculation of axes extents.\n\n2011-03-03  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in (axes::properties::get_extent): Add new optional\n\targument for ignoring the length of text objects.\n\t* graphics.cc (axes::properties::get_extent): Add the possibility\n\tof ignoring the length of text objects.\n\t(axes::properties::calc_tightbox): Take only text height into\n\taccount for the calculation of the tight box.\n\n2011-02-26  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc (plot_window::plot_window):\n\tMove canvas allocation after the configuration of the menubar.\n\t(plot_window::show_menubar, plot_window::hide_menubar):\n\tSimplify source code.\n\n2011-02-26  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/besselj.cc, DLD-FUNCTIONS/cellfun.cc,\n\tDLD-FUNCTIONS/filter.cc, DLD-FUNCTIONS/matrix_type.cc,\n\tDLD-FUNCTIONS/strfind.cc, DLD-FUNCTIONS/sub2ind.cc, bitfcns.cc,\n\tdata.cc, error.cc, file-io.cc, graphics.cc, help.cc, input.cc,\n\tload-path.cc, load-save.cc, oct-parse.yy, ov-base.cc, ov-cell.cc,\n\tov-class.cc, ov-fcn-handle.cc, ov-fcn-inline.cc, ov-flt-re-mat.cc,\n\tov-struct.cc, ov-usr-fcn.cc, pr-output.cc, pt-mat.cc, sparse.cc,\n\tstrfns.cc, syscalls.cc, sysdep.cc, toplev.cc, utils.cc, variables.cc:\n\tRewrite error strings to use variables named in documentation.\n\n2011-02-23  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_base::dup): Return retval.\n\n2011-02-22  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in (class axes::properties): New hidden property\n\tlooseinset.\n\t(axes::properties::update_looseinset): New function.\n\t* graphics.cc (axes::properties::init): Initialize looseinset.\n\t(axes::properties::sync_positions): Take looseinset into account\n\tinstead of default_axes_position.\n\t(axes::properties::set_defaults): Default values for looseinset.\n\n2011-02-21  Kai Habel  <kai.habel@gmx.de>\n\n\t* src/DLD-FUNCTIONS/__fltk_uigetfile__cc:\n\tUse forward slash as file seperator for fltk file path processing only.\n\n2011-02-21  Kai Habel  <kai.habel@gmx.de>\n\n\t* src/DLD-FUNCTIONS/__init_fltk__.cc(plot_window::plot_window):\n\tCall size_range early to allow window resizing for MacOS and MinGW.\n\n2011-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/regexp.cc: Assume we have PCRE.\n\n2011-02-19  Rik  <octave@nomad.inbox5.com>\n\n\t* src/DLD-FUNCTIONS/regexp.cc: Use PCRE regular expressions everywhere\n\tnow that Octave requires library for building.  Remove testif PCRE\n\ton testing blocks and adjust all documentation.\n\t\n2011-02-18  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.cc (axes::properties::sync_positions): Fix a small\n\tbug introduced with changes from 2011-02-14.\n\n2011-02-15  Konstantinos Poulios  <logari81@googlemail.com>\n\n\tBug #32319.\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc: Include sysdep.h.\n\t(class OpenGL_fltk): Replace integer print_fid member with\n\tboolean print_mode. New class member print_cmd of type string.\n\t(OpenGL_fltk::print): Accept command string argument instead of\n\tfile id.\n\t(OpenGL_fltk::draw): Invoke and terminate an octave process for\n\tthe printing job.\n\t(plot_window::print, figure_manager::print,\n\tfigure_manager::do_print): Replace file id with command string.\n\t(fltk_graphics_toolkit::print_figure): Remove parsing of file id.\n\t* graphics.cc (drawnow): Recognize strings beginning with \"|\" as\n\tpipelines instead of filenames.\n\n2011-02-14  David Bateman  <dbateman@free.fr>\n\n\t* gl-render.cc (void opengl_renderer::draw_patch (\n\tconst patch::properties &)): Obtain the marker color directly\n\tfrom the cdata rather that the facecolor, as the facecolor might\n\tnot have been set.  Bug #31801.\n\n2011-02-14  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.cc (axes::properties::sync_positions): Calculation of\n\ttightinset property.\n\n2011-02-13  Konstantinos Poulios  <logari81@googlemail.com>\n\n\tBugs #31800, #32211.\n\n\t* gl-render.cc (opengl_renderer::draw_axes_boxes): Draw only one\n\ty-axis line when plotyy tag is present.\n\t(opengl_renderer::draw_text): Remove superfluous calls of set_font\n\tand set_color.\n\t* graphics.h.in (class text::properties): Tag color with \"u\"\n\tqualifier.\n\t(text::properties::update_color): New function.\n\n2011-02-13  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in (axes::properties::update_boundingbox,\n\taxes::properties::update_dataaspectratio,\n\taxes::properties::update_dataaspectratiomode,\n\taxes::properties::update_plotboxaspectratio,\n\taxes::properties::update_plotboxaspectratiomode):\n\tReplace update_transform hooks with sync_positions.\n\n2011-02-13  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in (axes::properties::get_extent,\n\taxes::properties::calc_tightbox): New functions prototypes.\n\t(axes::properties::update_view): Hook sync_positions.\n\t(axes::properties::update_outerposition,\n\taxes::properties::update_position): Set activepositionproperty\n\tappropriately.\n\t(text::properties::update_string): Call\tupdate_text_extent after\n\trequest_autopos.\n\t* graphics.cc (axes::properties::sync_positions): Enable\n\tsynchronization of position and outer position. Take label and\n\ttitle extents in the calculation of outerposition into account.\n\tDo iterative calculation of position when activepositionproperty\n\tis set to outerposition.\n\t(axes::properties::update_title_position): Use new function\n\tget_extent.\n\t(axes::properties::update_autopos): Handle new tag \"sync\".\n\t(axes::properties::get_extent): New function calculating the\n\ttight box which contains all axes labels and axes title.\n\t(axes::properties::calc_tightbox): New function calculating axes\n\ttight box.\n\t(axes::properties::update_units): Don't call any hooks and listeners\n\tfor position, outerposition and tightset.\n\t(text::properties::update_text_extent): Request axes positions\n\tsynchronization when axes labels or title extents change.\n\n2011-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (strip_trailing_separators): Declare K as size_t\n\trather than octave_idx_type.\n\n2011-02-10 Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* DLD-FUNCTIONS/mgorth.cc: New file implementing modified\n\tGram-Schmidt orthogonalization.\n\n2011-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp_list): Avoid deprecated\n\tArray<T>::resize function.\n\n2011-02-09  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.cc (axes::properties::update_xlabel_position,\n\taxes::properties::update_ylabel_position,\n\taxes::properties::update_zlabel_position,\n\taxes::properties::update_title_position): Use get_transform only\n\twhen it is required.\n\t(text::properties::request_autopos): Remove redundant temporary\n\tsettting of autopos_tag to none.\n\n2011-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (INSTANTIATE_ABS): Omit inline keyword from\n\ttemplate instantiation.  From Orion Poplawski <orion@cora.nwra.com>.\n\n2011-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/chol.cc: Delete obsolete test of spcholinv.\n\n2011-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy (parse_fcn_file): Don't warn about coercing\n\tnested functions to subfunctions if yyparse failed.\n\n2011-02-06  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in (class axes::properties): Tag positionmode,\n\trotationmode, horizontalalignmentmode, verticalalignmentmode\n\twith \"u\" qualifier. New hidden property autopos_tag.\n\t(axes::properties::request_autopos,\n\taxes::properties::update_positionmode,\n\taxes::properties::update_rotationmode,\n\taxes::properties::update_horizontalalignmentmode,\n\taxes::properties::update_verticalalignmentmode): New functions\n\t(base_properties::update_autopos): New virtual function.\n\t(axes::properties::update_xlabel_position,\n\taxes::properties::update_ylabel_position,\n\taxes::properties::update_zlabel_position,\n\taxes::properties::update_title_position): Made public.\n\t* graphics.cc (base_properties::update_autopos,\n\taxes::properties::update_autopos,\n\ttext::properties::request_autopos): New functions.\n\t(axes::properties::init, axes::properties::set_defaults,\n\taxes::properties::set_xlabel, axes::properties::set_ylabel,\n\taxes::properties::set_zlabel, axes::properties::set_title):\n\tSet autopos_tag for {x,y,z}label and title.\n\t(axes::properties::update_xlabel_position,\n\taxes::properties::update_ylabel_position,\n\taxes::properties::update_zlabel_position,\n\taxes::properties::update_title_position): Run only for non-empty\n\tstrings. Set autopos_tag temporarily to none in order to prevent\n\trace conditions.\n\n2011-02-06  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.cc: Untabify and improve indentation.\n\n2011-02-06  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.cc (updating_axes_layout): New file-scope variable.\n\t(axes::properties::update_axes_layout):\tReturn immediately if\n\tupdating_axes_layout is true.\n\n2011-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc: Include <sys/types.h> and <unistd.h> for isatty.\n\tBug #32336.\n\n2011-02-03  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* gl-render.h: (opengl_renderer::draw_axes_titles): Remove prototype.\n\t* gl-render.cc: (opengl_renderer::draw_axes_titles): Remove function.\n\t(opengl_renderer::draw_axes_x_grid,\n\topengl_renderer::draw_axes_y_grid,\n\topengl_renderer::draw_axes_z_grid): Remove calculation of axis label\n\tpositions.\n\t* graphics.cc: (axes::properties::update_xlabel_position,\n\taxes::properties::update_ylabel_position\n\taxes::properties::update_zlabel_position\n\taxes::properties::update_title_position): New functions calculating\n\tlabel and title positions.\n\t(axes::properties::get_ticklabel_extents): New function.\n\t* graphics.h.in: Provide functions prototypes.\n\t* txt-eng-ft.cc (ft_render::get_extent): New function version.\n\t* txt-eng-ft.h (ft_render::get_extent): Provide function prototype.\n\n2011-02-03  Kai Habel  <kai.habel@gmx.de>\n\n\t* src/gl-render.cc(text_to_pixels): Use text_renderer object only\n\twhen freetype is available\n\n2011-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base.cc (octave_base_value::as_mxArray): Return 0 silently.\n\t* mex.cc (mxArray_octave_value::dup): If value can't be\n\tconverted to mxArray object, then simply create a clone of the\n\tmxArray_octave_value container.\n\n2011-02-02  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/eigs.cc, DLD-FUNCTIONS/qr.cc: Use testif to only run\n\tsome sparse tests when necessary libraries are installed.\n\n2011-02-03  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.cc (axes::properties::update_axes_layout):\n\tNew function calculating axes layout.\n\t(axes::properties::update_ticklengths): New function calculating\n\ttick lengths and offsets.\n\t* graphics.h.in (class axes::properties):: New private data\n\tdescribing axes layout and corresponding \"get\" methods. Provide\n\tdeclaration and call dependencies for \"update_axes_layout\".\n\tTag layer, yaxislocation, xaxislocation, tickdir, tickdirmode,\n\twith \"u\" qualifier.\n\t(axes::properties::update_layer,\n\taxes::properties::update_yaxislocation,\n\taxes::properties::update_xaxislocation,\n\taxes::properties::update_ticklengths,\n\taxes::properties::update_tickdir,\n\taxes::properties::update_tickdirmode): New functions\n\t* gl-render.cc:\t(opengl_renderer::draw_axes_planes,\n\topengl_renderer::draw_axes_boxes,\n\topengl_renderer::draw_axes_x_grid,\n\topengl_renderer::draw_axes_y_grid,\n\topengl_renderer::draw_axes_z_grid,\n\topengl_renderer::draw_axes_title): Simplify arguments list.\n\t(opengl_renderer::draw_axes): Remove calculation of axes layout.\n\t(opengl_renderer::setup_opengl_transformation): Disable antializing.\n\t* gl-render.h: Adapt functions prototypes.\n\n2011-02-01  John W. Eaton  <jwe@octave.org>\n\n\t* gl-render.h (opengl_renderer::draw (const Matrix& hlist)):\n\tUse get_object instead of lookup.\n\t* DLD-FUNCTIONS/__init_fltk__.cc (Fl_Gl_Window::draw): Likewise.\n\t* graphics.h.in (gh_manager::get_object (double)): New function.\n\t* gl-renderer.h (opengl_renderer::draw (const graphics_handle&)):\n\tDelete.\n\t* gl2ps-renderer.h (glps_renderer::draw (const graphics_handle&)):\n\tDelete.\n\n2011-02-01  John W. Eaton  <jwe@octave.org>\n\n\t* gl2ps-renderer.h: Remove virtual tag for derived virtual functions.\n\t(opengl_renderer (const graphics_handle&)): New function.\n\t* DLD-FUNCTIONS/__init_fltk__.cc (OpenGL_fltk::Fl_Gl_Window):\n\tDon't use new to create temporary glps_renderer object.\n\n2011-02-01  Michael Godfrey  <godfrey@isl.stanford.edu>\n\n\t* gl2ps-renderer.cc (glps_renderer::draw):\n\tReturn immediately if fdopen fails.\n\n2011-02-01  John W. Eaton  <jwe@octave.org>\n\n\t* gl-render.cc:\t(opengl_renderer::setup_opengl_transformation,\n\topengl_renderer::draw_axes_planes,\n\topengl_renderer::draw_axes_boxes,\n\topengl_renderer::draw_axes_x_grid,\n\topengl_renderer::draw_axes_y_grid,\n\topengl_renderer::draw_axes_z_grid,\n\topengl_renderer::draw_axes_title,\n\topengl_renderer::draw_axes_children):\n\tNew private functions, extracted from opengl_renderer::draw_axes.\n\t(opengl_renderer::draw_axes): Call subfunctions to do most of\n\tthe work.\n\t* gl-render.h: Provide decls.\n\n2011-01-31  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc (get_P_tmpdir): New function.\n\t* file-io.cc (FP_tmpdir): Use it.\n\tBug #32158.\n\n2011-01-30  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc (mouse_wheel_zoom, gui_mode): Rename\n\tfunctions and strip \"fltk_\" prefix.  Improve docstrings.\n\n2011-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* txt-eng-ft.cc (ft_manager::ft_manager): Omit fc_init_done from\n\tinitialization list if fontconfig is missing.\n\n2011-01-30  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* oct-parse.yy (class stdio_stream_reader): Disallow copying.\n\n2011-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (gnuplot_toolkit::redraw): Call __gnuplot_drawnow__,\n\tnot gnuplot_drawnow.\n\t(gnuplot_toolkit::print_figure): Likewise.\n\n2011-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (OCTAVE_LIBS): Remove $(ARPACK_LDFLAGS) and\n\t$(ARPACK_LIBS) from the list.\n\t(DLD-FUNCTIONS/eigs.df): Don't add $(ARPACK_CPPFLAGS) to CPPFLAGS.\n\t(DLD_FUNCTIONS_eigs_la_CPPFLAGS): Remove $(ARPACK_CPPFLAGS) from\n\tthe list.\n\t(DLD_FUNCTIONS_eigs_la_LIBADD): Remove $(ARPACK_LDFLAGS) and\n\t$(ARPACK_LIBS) from the list.\n\n2011-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc (Fload): Doc fix.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc (fltk_gui_mode, fltk_mouse_wheel_zoom):\n\tImprove docstrings.\n\n\t* graphics.cc (available_graphics_toolkits): Fix typo in docstring.\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* syscalls.cc (S_ISSOCK, S_ISCHR): Improve docstrings\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* dirfns.cc (readdir, filesep, pathsep): Improve docstrings\n\t* file-io.cc (tmpnam): Improve docstring\n\t* input.cc (filemarker): Improve docstring\n\t* syscalls.cc (stat, lstat): Improve docstring\n\n2011-01-29  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/getrusage.cc, toplev.cc: Improve docstring\n\n2011-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__fltk_uigetfile__.cc (__fltk_uigetfile__):\n\tDon't allocate Fl_File_Chooser object with new.  Delete unused\n\tvariable fargs.  Allocate default retval values in initial\n\tdeclaration.\n\n2011-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc: Undefine Complex after\n\tincluding FLTK headers.\n\t* DLD-FUNCTIONS/__fltk_uigetfile__.cc: Likewise.\n\n2011-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (__fltk_uigetfile__): Use the same compiler flags\n\tas for __init_fltk__.\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/eigs.cc (Feigs): Assume we have ARPACK.\n\tUse \"test\" instead of \"testif HAVE_ARPACK\".\n\t* toplev.cc (octave_config_info): Remove ARPACK_CPPFLAGS,\n\tARPACK_LDFLAGS, ARPACK_LIBS from the struct.\n\t* oct-conf.h.in (OCTAVE_CONF_ARPACK_CPPFLAGS,\n\tOCTAVE_CONF_ARPACK_LDFLAGS, OCTAVE_CONF_ARPACK_LIBS):\n\tDelete #defines.\n\n2011-01-28  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/__fltk_uigetfile__.cc: File filter value is\n\t1-based now.\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (Foutput_max_field_width): Set internal variable\n\toutput_max_field_width, not output_precision.\n\n2011-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (Fformat, Ffixed_point_format, Foutput_precision,\n\tFoutput_max_field_width, Fsplit_long_rows, Fprint_empty_dimensions):\n\tUpdate @seealso lists.\n\n2011-01-27  Rik  <octave@nomad.inbox5.com>\n\n\t* graphics.cc: Improve reset docstring.\n\n2011-01-27  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc (__fltk_uigetfile__): Remove here.\n\t* DLD-FUNCTIONS/__fltk_uigetfile__.cc: New file.\n\t* DLD-FUNCTIONS/module-files: Add __fltk_uigetfile__.cc.\n\tBug #32190.\n\n2011-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/dlmread.cc (Fdlmread): Skip leading whitespace\n\ton each line.\n\n2011-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (octave_struct::subsasgn,\n\toctave_scalar_struct::subsasgn): Call undef_subsasgn on object\n\treturned by octave_value::empty_conv if LHS is initially undefined.\n\tBug #32242.\n\n2011-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (input_event_hook): Fix incorrect use of iterator.\n\tReported by Pascal Dupuis <Pascal.Dupuis@worldonline.be>.\n\n2011-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (octave_class::reconstruct_exemplar):\n\tCall constructor with do_multi_index_op instead of feval.\n\tVerify that symbol_table::find_method did return a class\n\tconstructor for the correct type.  Bug #32242.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* lex.ll, graphics.cc, gl-render.cc, ov-mex-fcn.h, graphics.h.in:\n\tDelete trailing whitespace.\n\n2011-01-26  John W. Eaton  <jwe@octave.org>\n\n\tBug #32242.\n\n\t* ov.h, ov.cc (octave_value::undef_subsasgn): New function.\n\t* ov-class.h, ov-class.cc (octave_class::undef_subsasgn,\n\toctave_class::subsasgn_common): New functions.\n\t* ov-base.h, ov-base.cc (octave_base_value::subsasgn): If\n\tundefined, call undef_subsasgn on object returned by\n\toctave_value::empty_conv.\n\t(octave_base_value::undef_subsasgn): New virtual function.\n\t(octave_base_value::subsasgn): Only handle case of undefined\n\tvalues here.\n\n2011-01-26  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\t    John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (scaler::scaler (const std::string&)): New constructor.\n\t(graphics_handle::operator++, graphics_hanlde::operator--):\n\tImplement as recommended by Effective C++.\n\n\t* graphics.h.in (class base_property, class array_property,\n\tclass children_property, class property, class graphics_xform,\n\tclass graphics_event): Explicitelly iniatialize\n\tall data members in constructor initialisation list.\n\t* gl-render.cc (class patch_tesselator): Likewise\n\t* graphics.cc (class radio_values, class gh_manager),\n\t(class callback_event, class set_event): Likewise.\n\n\t* graphics.h.in (class base_graphics_property): Disallow copying.\n\t* graphics.cc (class function_event): Likewise.\n\t(function_event::function_event (void)): Delete implementation.\n\n2011-01-25  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/config-module.awk: Use automake variable for\n\tportability.\n\t* Makefile.am (uninstall-oct): Use GNU Make features for portability\n\n2011-01-25  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/fft.cc, DLD-FUNCTIONS/fft2.cc, DLD-FUNCTIONS/fftn.cc,\n\tload-save.cc: Make docstrings static by removing documentation\n\tdepending on #ifdef configuration variables.\n\n2011-01-25  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (OCT_STAMP_FILES): New variable.\n\t(DISTCLEANFILES): Add $(OCT_STAMP_FILES) to the list.\n\t(all-local): Depend on $(OCT_STAMP_FILES) instead of $(OCT_FILES).\n\n\t* DLD-FUNCTIONS/config-module.awk: Create stamp files when\n\tcreating .oct file links.\n\n2011-01-25  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* src/graphics.cc (text::properties::update_text_extent):\n\tDisable warning about missing freetype library.\n\n2011-01-25  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* src/graphics.cc (axes::properties::calc_ticks_and_lims):\n\tFixing wrong dimensions of minor ticks vector.\n\n2011-01-25  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.h (octave_map::octave_map (const string_vector&)):\n\tInitialize xvals elements to 1x1 Cells.  Bug #32222.\n\n2011-01-24  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* ov-base-mat.h (class octave_base_matrix): Disallow assignment.\n\t* ov-range.h (class octave_range): Likewise.\n\n2011-01-23  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (octave_scalar_struct::print_raw):\n\tAvoid unnecessary conversion of map value to Cell.\n\n2011-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h (symbol_table::parent_classes):\n\tAlso add parents of parents to the list.  Bug #32210.\n\n2011-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-class.cc (octave_class::subsasgn): Find appropriate unique base\n\tbefore trying any indexed assignment.  Bug #32182.\n\n2011-01-22  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in, graphics.cc (xmtick, ymtick, zmtick):\n\tNew properties holding minor ticks positions.\n\t(axes::properties::calc_ticks_and_lims): Calculation of minor ticks\n\tpositions.\n\t* gl-render.h, gl-render.cc\n\t(opengl_renderer::render_grid,\topengl_renderer::render_tickmarks,\n\topengl_renderer::render_ticktexts): New functions.\n\t(opengl_renderer::draw_axes): Make use of new rendering functions\n\tand minor ticks positions.\n\tCorrect axis label positioning for x axis at top and y axis at right\n\tposition. Bug #31800.\n\tChange axis positioning policy for 3D plots, keeping x and y axis\n\talways at bottom.\n\n2011-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* gl-render.cc: Use octave_refcount for refcounting.\n\t* oct-map.h: Ditto.\n\t* ov-base.h: Ditto.\n\t* pt-mat.cc: Ditto.\n\n2011-01-22  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* ov-mex-fcn.h, txt-eng-ft.cc, mex.cc:\n\tInitialize all data members in initialization list.\n\n2011-01-22  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc (fltk_uimenu): Disallow copying.\n\t(class plot_window): Likewise.\n\t* c-file-ptr-stream.h (class c_file_ptr_buf): Likewise.\n\t(class c_file_ptr_stream): Likewise.\n\t(class c_zfile_ptr_buf): Likewise.\n\t* gl-render.cc (class opengl_tesselator): Likewise.\n\t(class patch_tesselator): Likewise.\n\t* lex.ll (class flex_stream_reader): Likewise.\n\t* mex.cc (class mex): Likewise.\n\t* oct-procbuf.h (class octave_procbuf): Likewise.\n\t* pt-cbinop.h (class tree_compound_binary_expression): Likewise.\n\t* symtab.h (class scope_id_cache): Likewise.\n\t(class symbol_table): Likewise.\n\t* txt-eng-ft.h (class ft_manager): Likewise.\n\t(class ft_render): Likewise.\n\t* unwind-prot.h (class unwind_protect::elem): Likewise.\n\t(class unwind_protect::fcn_arg_elem): Likewise.\n\t(class unwind_protect::method_elem): Likewise.\n\t(class unwind_protect::restore_var_elem): Likewise.\n\t(class unwind_protect::delete_ptr_elem): Likewise.\n\t(class unwind_protect): Likewise.\n\t* zfstream.h (class gzfilebuf): Likewise.\n\n\t* mex.cc (class mxArray_octave_value): Disallow assignment.\n\t(class mxArray_matlab): Likewise.\n\t(class mxArray_number): Likewise.\n\t(class mxArray_sparse): Likewise.\n\t(class mxArray_struct): Likewise.\n\t(class mxArray_cell): Likewise.\n\n\t* unwind-prot.h (unwind_protect::elem::elem):\n\tProvide default constructor.\n\n2011-01-21  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* src/graphics.cc (axes::properties::set_xlabel,\n\taxes::properties::set_ylabel, axes::properties::set_zlabel):\n\tSetting axis label color from axis color.\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* src/file-io.cc, src/variables.cc: Prevent doubled quotes around @table\n\titems in Info.\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* src/DLD-FUNCTIONS/chol.cc, src/DLD-FUNCTIONS/luinc.cc,\n\tsrc/DLD-FUNCTIONS/qz.cc: Use non-breaking spaces between certain\n\tadjectives and their linked nouns in docstrings\n\n2011-01-20  Rik  <octave@nomad.inbox5.com>\n\n\t* src/DLD-FUNCTIONS/str2double.cc, src/data.cc, src/mappers.cc,\n\tsrc/variables.cc: Use @nospell macro on certain words in docstring.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__delaunayn__.cc,\n\tDLD-FUNCTIONS/__init_fltk__.cc,\n\tDLD-FUNCTIONS/__magick_read__.cc, DLD-FUNCTIONS/cellfun.cc,\n\tDLD-FUNCTIONS/quadcc.cc, DLD-FUNCTIONS/regexp.cc, data.cc,\n\tgripes.cc, ls-mat5.cc, toplev.cc, variables.cc:\n\tStyle fixes for error and warning messages.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* Array.cc, Sparse.cc, base-lu.cc, idx-vector.cc,\n\tlo-array-gripes.cc: Style fixes for error and warning messages.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__contourc__.cc, DLD-FUNCTIONS/__delaunayn__.cc,\n\tDLD-FUNCTIONS/__dsearchn__.cc, DLD-FUNCTIONS/__glpk__.cc,\n\tDLD-FUNCTIONS/__init_fltk__.cc,\n\tDLD-FUNCTIONS/__lin_interpn__.cc,\n\tDLD-FUNCTIONS/__magick_read__.cc,\n\tDLD-FUNCTIONS/__pchip_deriv__.cc, DLD-FUNCTIONS/__qp__.cc,\n\tDLD-FUNCTIONS/__voronoi__.cc, DLD-FUNCTIONS/amd.cc,\n\tDLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/besselj.cc,\n\tDLD-FUNCTIONS/bsxfun.cc, DLD-FUNCTIONS/ccolamd.cc,\n\tDLD-FUNCTIONS/cellfun.cc, DLD-FUNCTIONS/chol.cc,\n\tDLD-FUNCTIONS/colamd.cc, DLD-FUNCTIONS/colloc.cc,\n\tDLD-FUNCTIONS/convhulln.cc, DLD-FUNCTIONS/daspk.cc,\n\tDLD-FUNCTIONS/dasrt.cc, DLD-FUNCTIONS/dassl.cc,\n\tDLD-FUNCTIONS/det.cc, DLD-FUNCTIONS/dlmread.cc,\n\tDLD-FUNCTIONS/dmperm.cc, DLD-FUNCTIONS/dot.cc,\n\tDLD-FUNCTIONS/eig.cc, DLD-FUNCTIONS/eigs.cc,\n\tDLD-FUNCTIONS/fft.cc, DLD-FUNCTIONS/fft2.cc,\n\tDLD-FUNCTIONS/fftn.cc, DLD-FUNCTIONS/fftw.cc,\n\tDLD-FUNCTIONS/filter.cc, DLD-FUNCTIONS/find.cc,\n\tDLD-FUNCTIONS/gammainc.cc, DLD-FUNCTIONS/givens.cc,\n\tDLD-FUNCTIONS/hex2num.cc, DLD-FUNCTIONS/inv.cc,\n\tDLD-FUNCTIONS/kron.cc, DLD-FUNCTIONS/lookup.cc,\n\tDLD-FUNCTIONS/lsode.cc, DLD-FUNCTIONS/lu.cc,\n\tDLD-FUNCTIONS/luinc.cc, DLD-FUNCTIONS/matrix_type.cc,\n\tDLD-FUNCTIONS/max.cc, DLD-FUNCTIONS/md5sum.cc,\n\tDLD-FUNCTIONS/onCleanup.cc, DLD-FUNCTIONS/qr.cc,\n\tDLD-FUNCTIONS/quad.cc, DLD-FUNCTIONS/quadcc.cc,\n\tDLD-FUNCTIONS/qz.cc, DLD-FUNCTIONS/rand.cc,\n\tDLD-FUNCTIONS/regexp.cc, DLD-FUNCTIONS/schur.cc,\n\tDLD-FUNCTIONS/spparms.cc, DLD-FUNCTIONS/sqrtm.cc,\n\tDLD-FUNCTIONS/str2double.cc, DLD-FUNCTIONS/strfind.cc,\n\tDLD-FUNCTIONS/sub2ind.cc, DLD-FUNCTIONS/svd.cc,\n\tDLD-FUNCTIONS/syl.cc, DLD-FUNCTIONS/symbfact.cc,\n\tDLD-FUNCTIONS/symrcm.cc, DLD-FUNCTIONS/tril.cc,\n\tDLD-FUNCTIONS/tsearch.cc, DLD-FUNCTIONS/typecast.cc,\n\tDLD-FUNCTIONS/urlwrite.cc, OPERATORS/op-b-sbm.cc,\n\tOPERATORS/op-bm-sbm.cc, OPERATORS/op-cdm-cdm.cc,\n\tOPERATORS/op-chm.cc, OPERATORS/op-cm-cm.cc,\n\tOPERATORS/op-cm-m.cc, OPERATORS/op-cm-scm.cc,\n\tOPERATORS/op-cm-sm.cc, OPERATORS/op-cs-cs.cc,\n\tOPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc,\n\tOPERATORS/op-dm-dm.cc, OPERATORS/op-dms-template.cc,\n\tOPERATORS/op-fcdm-fcdm.cc, OPERATORS/op-fcm-fcm.cc,\n\tOPERATORS/op-fcm-fcs.cc, OPERATORS/op-fcm-fm.cc,\n\tOPERATORS/op-fcm-fs.cc, OPERATORS/op-fcs-fcm.cc,\n\tOPERATORS/op-fcs-fcs.cc, OPERATORS/op-fcs-fm.cc,\n\tOPERATORS/op-fcs-fs.cc, OPERATORS/op-fdm-fdm.cc,\n\tOPERATORS/op-fm-fcm.cc, OPERATORS/op-fm-fcs.cc,\n\tOPERATORS/op-fm-fm.cc, OPERATORS/op-fm-fs.cc,\n\tOPERATORS/op-fs-fcm.cc, OPERATORS/op-fs-fcs.cc,\n\tOPERATORS/op-fs-fm.cc, OPERATORS/op-int-concat.cc,\n\tOPERATORS/op-m-cm.cc, OPERATORS/op-m-m.cc,\n\tOPERATORS/op-m-scm.cc, OPERATORS/op-m-sm.cc,\n\tOPERATORS/op-pm-pm.cc, OPERATORS/op-pm-scm.cc,\n\tOPERATORS/op-pm-sm.cc, OPERATORS/op-pm-template.cc,\n\tOPERATORS/op-range.cc, OPERATORS/op-s-scm.cc,\n\tOPERATORS/op-sbm-b.cc, OPERATORS/op-sbm-bm.cc,\n\tOPERATORS/op-sbm-sbm.cc, OPERATORS/op-scm-cm.cc,\n\tOPERATORS/op-scm-cs.cc, OPERATORS/op-scm-m.cc,\n\tOPERATORS/op-scm-s.cc, OPERATORS/op-scm-scm.cc,\n\tOPERATORS/op-scm-sm.cc, OPERATORS/op-sm-cm.cc,\n\tOPERATORS/op-sm-cs.cc, OPERATORS/op-sm-m.cc,\n\tOPERATORS/op-sm-s.cc, OPERATORS/op-sm-scm.cc,\n\tOPERATORS/op-sm-sm.cc, OPERATORS/op-str-str.cc,\n\tOPERATORS/op-ui64-ui64.cc, bitfcns.cc, c-file-ptr-stream.cc,\n\tc-file-ptr-stream.h, comment-list.h, data.cc, debug.cc, debug.h,\n\tdefun-int.h, defun.cc, dynamic-ld.cc, error.cc, file-io.cc,\n\tgl-render.cc, gl-render.h, gl2ps-renderer.cc, gl2ps-renderer.h,\n\tgl2ps.c, gl2ps.h, graphics.cc, graphics.h.in, help.cc, input.cc,\n\tlex.h, lex.ll, load-path.cc, load-path.h, load-save.cc,\n\tload-save.h, ls-ascii-helper.cc, ls-hdf5.cc, ls-hdf5.h,\n\tls-mat-ascii.cc, ls-mat4.cc, ls-mat4.h, ls-mat5.cc,\n\tls-oct-ascii.cc, ls-oct-ascii.h, ls-oct-binary.cc, mappers.cc,\n\tmex.cc, mex.h, mexproto.h, mxarray.h.in, oct-hist.cc,\n\toct-lvalue.cc, oct-lvalue.h, oct-map.cc, oct-map.h, oct-obj.cc,\n\toct-obj.h, oct-parse.yy, oct-procbuf.cc, oct-stream.cc,\n\toct-stream.h, octave.cc, ov-base-diag.cc, ov-base-diag.h,\n\tov-base-int.cc, ov-base-int.h, ov-base-mat.cc, ov-base-mat.h,\n\tov-base-scalar.cc, ov-base-scalar.h, ov-base-sparse.cc,\n\tov-base-sparse.h, ov-base.cc, ov-base.h, ov-bool-mat.cc,\n\tov-bool-mat.h, ov-bool-sparse.cc, ov-bool-sparse.h, ov-bool.cc,\n\tov-bool.h, ov-builtin.h, ov-cell.cc, ov-cell.h, ov-ch-mat.cc,\n\tov-class.cc, ov-class.h, ov-complex.cc, ov-complex.h,\n\tov-cx-diag.cc, ov-cx-diag.h, ov-cx-mat.cc, ov-cx-mat.h,\n\tov-cx-sparse.cc, ov-cx-sparse.h, ov-dld-fcn.h, ov-fcn-handle.cc,\n\tov-fcn-handle.h, ov-fcn-inline.cc, ov-fcn-inline.h, ov-fcn.h,\n\tov-float.cc, ov-float.h, ov-flt-complex.cc, ov-flt-complex.h,\n\tov-flt-cx-diag.cc, ov-flt-cx-diag.h, ov-flt-cx-mat.cc,\n\tov-flt-cx-mat.h, ov-flt-re-diag.cc, ov-flt-re-diag.h,\n\tov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-lazy-idx.cc,\n\tov-lazy-idx.h, ov-null-mat.cc, ov-null-mat.h, ov-perm.cc,\n\tov-perm.h, ov-range.cc, ov-range.h, ov-re-diag.cc, ov-re-diag.h,\n\tov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-re-sparse.h,\n\tov-scalar.cc, ov-scalar.h, ov-str-mat.cc, ov-str-mat.h,\n\tov-struct.cc, ov-struct.h, ov-type-conv.h, ov-typeinfo.cc,\n\tov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, pager.cc,\n\tpr-output.cc, procstream.h, pt-arg-list.cc, pt-assign.h,\n\tpt-binop.cc, pt-bp.cc, pt-bp.h, pt-cbinop.cc, pt-cell.cc,\n\tpt-colon.cc, pt-const.cc, pt-decl.cc, pt-eval.cc,\n\tpt-fcn-handle.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-mat.cc,\n\tpt-mat.h, pt-pr-code.cc, pt-select.cc, pt-select.h, pt-stmt.cc,\n\tpt-unop.cc, pt-unop.h, sighandlers.cc, sighandlers.h,\n\tsparse-xdiv.cc, sparse-xdiv.h, sparse-xpow.cc, sparse-xpow.h,\n\tsparse.cc, strfns.cc, symtab.cc, symtab.h, syscalls.cc,\n\tsysdep.cc, toplev.cc, toplev.h, txt-eng-ft.cc, txt-eng-ft.h,\n\ttxt-eng.h, unwind-prot.h, utils.cc, utils.h, variables.cc,\n\tvariables.h, xdiv.cc, xdiv.h, xnorm.cc, xpow.cc, zfstream.cc,\n\tzfstream.h: Strip trailing whitespace.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* gl-render.cc, DLD-FUNCTIONS/__init_fltk__.cc,\n\tDLD-FUNCTIONS/__magick_read__.cc: Untabify.\n\n2011-01-20  Pascal Dupuis <Pascal.Dupuis@worldonline.be>.\n\n\t* debug.h, dynamic-ld.cc, gl-render.cc, gl-render.h,\n\tgl2ps-renderer.h, lex.h, ls-hdf5.h, oct-stream.h, oct-strstrm.h,\n\tov-base-diag.h, ov-base-mat.h, ov-base-scalar.h, ov-base-sparse.h,\n\tov-cell.h, ov-class.h, ov-dld-fcn.h, ov-fcn-handle.h,\n\tov-lazy-idx.h, ov-perm.h, ov-range.h, ov-struct.h, procstream.h,\n\tpt-assign.h, symtab.h, unwind-prot.h: Initialize\n\tall data members in initialization list.\n\n2011-01-20  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc (__fltk_uigetfile__): Append file\n\tseperator to 2nd return value (file path).\n\tBug #32190.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* oct-obj.h (octave_value_list::octave_value_list): Initialize\n\tall data members in initialization list.  From Pascal Dupuis\n\t<Pascal.Dupuis@worldonline.be>.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (read_mat5_binary_element):\n\tImprove diagnositc if uncompress fails.\n\n\t* load-path.cc (strip_trailing_separators): New static function.\n\t(load_path::do_add, load_path::do_remove): Call it on directory arg.\n\n2011-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* gl-render.h, graphics.cc, gl-render.cc, graphics.h.in:\n\tUpdate for backend -> graphics_toolkit change.\n\n\t* DLD-FUNCTIONS/__init_fltk__.cc: Rename from fltk_backend.cc\n\tUpdate for backend -> graphics_toolkit change.\n\t* DLD-FUNCTIONS/module-files, Makefile.am: Update for renamed file.\n\n2011-01-19  Rik  <octave@nomad.inbox5.com>\n\n\t* src/data.cc, src/input.cc, src/utils.cc: spellcheck docstrings.\n\n2011-01-19  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/dlmread.cc, DLD-FUNCTIONS/filter.cc,\n\tDLD-FUNCTIONS/inv.cc, DLD-FUNCTIONS/lu.cc, DLD-FUNCTIONS/quad.cc,\n\tDLD-FUNCTIONS/quadcc.cc, DLD-FUNCTIONS/rcond.cc,\n\tDLD-FUNCTIONS/regexp.cc, DLD-FUNCTIONS/strfind.cc,\n\tDLD-FUNCTIONS/typecast.cc, data.cc, dirfns.cc, error.cc, file-io.cc,\n\tgraphics.cc, help.cc, input.cc, load-path.cc, load-save.cc, mappers.cc,\n\toct-hist.cc, oct-parse.yy, pager.cc, pr-output.cc, pt-binop.cc,\n\tsparse.cc, strfns.cc, syscalls.cc, sysdep.cc, utils.cc: grammarcheck\n\tfiles in src directory.\t\n\n2011-01-19  John W. Eaton  <jwe@octave.org>\n\n\t* oct-obj.cc (octave_value_list::all_scalars): Check for scalar\n\tvalues, not strings.  Bug #32172.\n\n2011-01-17  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/module-files: Add quadcc.cc to list of files.\n\t* DLD-FUNCTIONS/quad.cc: Add Seealso links to quadcc.\n\n2011-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTION/lookup.cc (Flookup): Validate option string.\n\n2011-01-17  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr-fcn.cc (octave_user_function::bind_automatic_vars):\n\tSave argument names in hidden variable .argn..\n\n\t* variables.cc (F__varval__): New function.\n\n2011-01-17  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr-fcn.cc (bind_automatic_vars): Mark variables created\n\there as automatic.\n\n\t* symtab.h (symbol_table::mark_automatic): New function.\n\t(symbol_table::do_mark_automatic): New function.\n\n2011-01-17  Michael Godfrey <godfrey@isl.stanford.edu>\n\n\t* variables.cc (Fwhos): Describe a and f attributes in help text.\n\n2011-01-17  John W. Eaton  <jwe@octave.org>\n\n\t* sighandlers.cc (octave_signal_handler): Wait for children here.\n\t(sigchld_handler): Not here.\n\n2011-01-16  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/__delaunayn__.cc, DLD-FUNCTIONS/__dispatch__.cc,\n\tDLD-FUNCTIONS/__dsearchn__.cc, DLD-FUNCTIONS/__glpk__.cc,\n\tDLD-FUNCTIONS/__magick_read__.cc, DLD-FUNCTIONS/__pchip_deriv__.cc,\n\tDLD-FUNCTIONS/__voronoi__.cc, DLD-FUNCTIONS/amd.cc,\n\tDLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/besselj.cc,\n\tDLD-FUNCTIONS/bsxfun.cc, DLD-FUNCTIONS/ccolamd.cc,\n\tDLD-FUNCTIONS/cellfun.cc, DLD-FUNCTIONS/chol.cc,\n\tDLD-FUNCTIONS/colamd.cc, DLD-FUNCTIONS/colloc.cc,\n\tDLD-FUNCTIONS/conv2.cc, DLD-FUNCTIONS/convhulln.cc,\n\tDLD-FUNCTIONS/cquad.cc, DLD-FUNCTIONS/dasrt.cc, DLD-FUNCTIONS/det.cc,\n\tDLD-FUNCTIONS/dlmread.cc, DLD-FUNCTIONS/dmperm.cc,\n\tDLD-FUNCTIONS/dot.cc, DLD-FUNCTIONS/eig.cc, DLD-FUNCTIONS/eigs.cc,\n\tDLD-FUNCTIONS/fft.cc, DLD-FUNCTIONS/fft2.cc, DLD-FUNCTIONS/fftn.cc,\n\tDLD-FUNCTIONS/fftw.cc, DLD-FUNCTIONS/filter.cc, DLD-FUNCTIONS/find.cc,\n\tDLD-FUNCTIONS/fltk_backend.cc, DLD-FUNCTIONS/gammainc.cc,\n\tDLD-FUNCTIONS/gcd.cc, DLD-FUNCTIONS/getgrent.cc,\n\tDLD-FUNCTIONS/getpwent.cc, DLD-FUNCTIONS/hess.cc,\n\tDLD-FUNCTIONS/hex2num.cc, DLD-FUNCTIONS/inv.cc, DLD-FUNCTIONS/kron.cc,\n\tDLD-FUNCTIONS/lookup.cc, DLD-FUNCTIONS/lsode.cc, DLD-FUNCTIONS/lu.cc,\n\tDLD-FUNCTIONS/luinc.cc, DLD-FUNCTIONS/matrix_type.cc,\n\tDLD-FUNCTIONS/max.cc, DLD-FUNCTIONS/md5sum.cc,\n\tDLD-FUNCTIONS/onCleanup.cc, DLD-FUNCTIONS/pinv.cc, DLD-FUNCTIONS/qr.cc,\n\tDLD-FUNCTIONS/quad.cc, DLD-FUNCTIONS/qz.cc, DLD-FUNCTIONS/rand.cc,\n\tDLD-FUNCTIONS/rcond.cc, DLD-FUNCTIONS/regexp.cc,\n\tDLD-FUNCTIONS/schur.cc, DLD-FUNCTIONS/spparms.cc,\n\tDLD-FUNCTIONS/sqrtm.cc, DLD-FUNCTIONS/str2double.cc,\n\tDLD-FUNCTIONS/strfind.cc, DLD-FUNCTIONS/sub2ind.cc,\n\tDLD-FUNCTIONS/svd.cc, DLD-FUNCTIONS/syl.cc, DLD-FUNCTIONS/symbfact.cc,\n\tDLD-FUNCTIONS/symrcm.cc, DLD-FUNCTIONS/time.cc, DLD-FUNCTIONS/tril.cc,\n\tDLD-FUNCTIONS/tsearch.cc, DLD-FUNCTIONS/typecast.cc,\n\tDLD-FUNCTIONS/urlwrite.cc: Improve docstrings.  Use same variable names\n\tin error() strings and docstrings.\n\n2011-01-16  John W. Eaton  <jwe@octave.org>\n\n\t* mkgendoc: Write function name along with file name in comment.\n\n2011-01-15  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* symtab.h (do_clear_global_pattern): Reword so as to not\n\tinvalidate iterators when calling std::map::erase().\n\t* DLD-FUNCTIONS/urwlwrite.cc (~curl_handles): Ditto.\n\n2011-01-15  Rik  <octave@nomad.inbox5.com>\n\n\t* src/dirfns.cc, src/help.cc, src/input.cc, src/load-save.cc,\n\tsrc/oct-hist.cc, src/pager.cc, src/pr-output.cc, src/variables.cc:\n\tEliminate @deffn macros.\n\n2011-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* syscalls.cc (FWEXITSTATUS, FWIFEXITED): Missing semicolon.\n\n2011-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-handle.cc: Use version instead of flops in test.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/svd.cc: Add Seealso references to svd.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* src/mappers.cc: Add Seealso links between sqrt, cbrt, nthroot\n\tfunctions.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* dirfns.cc (Ffnmatch): Use DEFUNX until gnulib's fnmatch is C++\n\tfriendly.\n\n2011-01-14  Rik  <octave@nomad.inbox5.com>\n\n\t* src/mappers.cc: Add Seealso links between erf variants to docstring.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* sighandlers.cc (BADSIG, BLOCK_SIGNAL, SIGCHLD, BLOCK_CHILD,\n\tUNBLOCK_CHILD): Move macro definitions here from sighandlers.h.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* Update copyright notices for 2011.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (mkstemp): Delete.\n\tDelete decl for mkstemps.\n\t(Fmkstemp): Assume we have mkstemp from gnulib.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__pchip_deriv__.cc, DLD-FUNCTIONS/dot.cc,\n\toctave.cc: Style fixes.\n\n2011-01-13  David Bateman  <dbateman@free.fr>\n\n\tls-mat5.cc (int save_mat5_element_length (const octave_value&,\n\tconst std::string&, bool, bool)): For sparse matrices use nnz rather\n\tthan nzmax.\n\t(bool save_mat5_binary_element (std::ostream&, const octave_value&,\n\tconst std::string&, bool, bool, bool, bool)): ditto.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* base-list.h (class octave_base_list): Provide explicit\n\tdefault and copy construtors, assignment operator, and destructor.\n\t* load-path.h (load_path::dir_info::class_info): Likewise.\n\n\t* load-path.h (load_path::dir_info::dir_info): Initialize all\n\tmembers in initializaition list.\n\t* lex.h (lexical_feedback::lexical_feedback): Likewise.\n\n2011-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* cutils.h: New file.\n\t(octave_sleep, octave_usleep, octave_raw_vsnprintf): Move decls\n\there from utils.h.\n\t* Makefile.am (octinclude_HEADERS): Add cutils.h to the list.\n\t* utils.h: Include cutils.h.\n\t* cutils.c: Include cutils.h.\n\n2011-01-12  David Grundberg  <individ@acc.umu.se>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (__magick_read__) [!HAVE_MAGICK]:\n\tWrite more verbose error message that blames on imread, not\n\t__magick_read__.\n\n2011-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/rand.cc (reset_rand_generator): Delete unused\n\tstatic function.\n\n2011-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (graphics_object::get_ancestor): Avoid GCC warning.\n\n2011-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gcd.cc (extended_gcd): Tag call to floor with gnulib::.\n\n2011-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* oct-hist.cc (Fhistory_control): New function.\n\n2011-01-12  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* oct-hist.cc (default_history_control): New function.\n\t(initialize_history): Pass Vhistory control to\n\tcommand_history::initialize.\n\n2011-01-11  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* gl-render.cc (opengl_renderer::draw_axes): Improve positioning\n\tof titles.\n\n2011-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* ov-cell.cc (octave_cell::print_as_scalar): Always return true.\n\t(octave_cell::print_raw): Handle extra newlines here.\n\t* ov-struct.cc (Fstruct_levels_to_print): Move here from pr-output.cc\n\t(Vstruct_levels_to_print): Move here from pr-output.cc.  Now static.\n\t(Vprint_struct_array_contents): New static variable.\n\t(Fprint_struct_array_contents): New function.\n\t(octave_struct::print_raw): Use Vprint_struct_array_contents.\n\tSimplify and improve output.\n\t(octave_scalar_struct::print_raw): Simplify and improve output.\n\t* pr-output.h (Vstruct_levels_to_print): Delete decl.\n\t* ov-class.cc (octave_class::print_raw): Don't unwind_protect\n\tVstruct_levels_to_print.\n\n2011-01-09  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat5.cc (save_mat5_array_length (const float*, octave_idx_type,\n\tbool)): Take in to account the short tags for single data elements.\n\t(int save_mat5_element_length (const octave_value&, const std::string&,\n\tbool, bool)): Declare sparse matrices const to avoid a copy on read.\n\t* ls-utils.cc (save_type get_save_type (float, float)): New function.\n\t* ls-utils.h  (save_type get_save_type (float, float)): Declare it.\n\n2011-01-09  John W. Eaton  <jwe@octave.org>\n\n\t* token.h, token.cc (token::plot_tok_typ): Delete unused enum.\n\t(token::token_type): Delete pttype_token from the list.\n\t(token::token (plot_tok_type, int, int)): Delete unused constructor.\n\t(token::pttype): Delete unused function.\n\t(token::anonymous union): Delete PT element.\n\n2011-01-09  John W. Eaton  <jwe@octave.org>\n\n\t* lex.ll (display_token): Display token value for NUM, IMAG_NUM,\n\tSTRUCT_ELT, NAME, DQ_STRING, and SQ_STRING tokens.\n\n2011-01-09  John W. Eaton  <jwe@octave.org>\n\n\t* lex.h, lex.ll, oct-parse.yy (lexer_flags::parsed_function_name):\n\tDeclare to be std::stack<bool> instead of bool.  Change all uses.\n\tBug #32083.\n\n2011-01-08  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* gl-render.cc (opengl_renderer::draw_axes): Revert positionmode\n\tto auto after automatic positioning of titles. Bug #32074.\n\n2011-01-08  David Grundberg  <individ@acc.umu.se>\n\n\t* ov-fcn.h (is_subfunction): Rename from is_nested_function.\n\tChange all uses and nearby comments.\n\t* ov-usr-fcn.h (is_subfunction, mark_as_subfunction): Rename from\n\tis_nested_function, mark_as_nested_function.  Change all uses.\n\n2011-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): For uniformoutput case\n\twith nargout > 0, initialize elements of retval to NDArray\n\tobjects of the same size as the input.  Bug #32067.\n\n2011-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (Fget): Return empty matrix if no values are found.\n\tBug #32067.\n\n2011-01-06  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* txt-eng-ft.h, txt-eng-ft.cc: Remove dependency on graphics.h.\n\t(ft_render::set_font): New arguments list.\n\t(ft_render::text_to_pixels): New method.\n\t* graphics.cc (text::properties::update_text_extent): Adapt the call\n\tto ft_render::set_font.\n\t(text::properties::get_extent_matrix): New function.\n\t(text::properties::update_text_extent): Function rewrite.\n\t* gl-render.cc (opengl_renderer::set_font): Likewise.\n\t(opengl_renderer::text_to_pixels):\n\tMake use of ft_render::text_to_pixels.\n\t(opengl_renderer::render_text): Simplify.\n\t(opengl_renderer::draw_text): Make text drawing aware of the text\n\textent property.\n\t* gl-render.h (opengl_renderer::text_to_pixels): Arguments reordering.\n\t(opengl_renderer::get_transform): New function.\n\t* gl2ps-renderer.cc (glps_renderer::render_text): Adapt the call to\n\ttext_to_pixels.\n\t(glps_renderer::alignment_to_mode): New function.\n\t(glps_renderer::draw_text): Overload inherited function.\n\t* gl2ps-renderer.h (glps_renderer::alignment_to_mode): New function.\n\t* graphics.h.in: Add dependency on txt-eng-ft.h.\n\t(class text::properties): Tag horizontalalignment and verticalalignment\n\twith \"u\" qualifier.\n\t(text::properties::get_extent_matrix, get_pixels,\n\tupdate_horizontalalignment, update_verticalalignment): New functions.\n\t(text::properties::renderer): New class member of type ft_render.\n\t(text::properties::pixels): New class member of type uint8NDArray.\n\n2011-01-06  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/rand.cc (Frandperm): Tag call to floor with gnulib::.\n\t* DLD-FUNCTIONS/gcd.cc (divide): Tag calls to floor with gnulib::.\n\t* ov-scalar.cc (octave_scalar::map): Tag floor with gnulib::.\n\t* ov-cell.cc (octave_cell::save_hdf5): Tag call to floor with gnulib::.\n\t* pr-output.cc (engineering_exponent, num_digits,\n\toctave_print_internal_template): Tag call to floor with gnulib::.\n\t* graphics.cc: Consistently use std::ceil.\n\t(axes::properties::get_axis_limits): Tag calls to floor with gnulib::.\n\t(axes::properties::calc_ticks_and_lims): Likewise.\n\n2011-01-05  John W. Eaton  <jwe@octave.org>\n\n\tBug #32060.\n\n\t* ov-fcn.h (octave_function::mark_as_private_function): Now virtual.\n\t* ov-usr-fcn.h (octave_function::mark_as_private_fucntion):\n\tNew function.  Mark subfunctions as private also.\n\t* symtab.cc, symtab.h\n\t(symbol_table::mark_subfunctions_in_scope_as_private,\n\tsymbol_table::fcn_info::mark_subfunction_in_scope_as_private,\n\tsymbol_table::fcn_info::fcn_info_rep::mark_subfunction_in_scope_as_private):\n\tNew functions.\n\n2011-01-04  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-sparse.cc (octave_base_sparse<T>::print_raw): Improve\n\tdisplay of percentage full.  Bug #32011.\n\n2011-01-04  John W. Eaton  <jwe@octave.org>\n\n\t* ov-typeinfo.cc (Ftypeinfo): Return cell array of character\n\tstrings, not character array.  Bug #32050.\n\n2011-01-03  Rik  <octave@nomad.inbox5.com>\n\n\t* data.cc (islogical, isnumeric): Add tests to check sparse forms of\n\tlogical matrices.\n\n2011-01-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-bool-sparse.h (octave_sparse_bool_matrix::is_numeric_type): New\n\tvirtual method override.\n\n2010-12-31  Rik  <octave@nomad.inbox5.com>\n\n\t* toplev.cc (system): Add additional calling form \"shell_cmd\" to\n\tdocumentation.\n\n2010-12-31  Rik  <octave@nomad.inbox5.com>\n\n\t* data.cc (islogical, isinteger, iscomplex, isfloat, isempty,\n\tisnumeric, ismatrix, issorted): Improve docstring\n\t* graphics.cc (ishandle): Improve docstring\n\t* lex.ll (iskeyword): Improve docstring\n\t* mappers.cc (isalnum, isalpha, isascii, iscntrl, isdigit, isinf,\n\tisgraph, islower, isna, isnan, isprint, ispunct, isspace, isupper,\n\tisxdigit): Improve docstring\n\t(finite/isfinite): Make finite an alias for isfinite rather than the\n\treverse.  Improve docstring.\n\t* ov-cell.cc (iscell, iscellstr): Improve docstring\n\t* ov-class.cc (isobject, ismethod): Improve docstring\n\t* ov-null-mat.cc (isnull): Improve docstring\n\t* ov-struct.cc (isstruct, isfield): Improve docstring\n\t* ov-usr-fcn.cc (isargout): Improve docstring\n\t* sparse.cc (issparse): Improve docstring\n\t* strfns.cc (ischar): Improve docstring\n\t* sysdep.cc (isieee): Improve docstring\n\t* utils.cc (isvarname, is_absolute_filename,\n\tis_rooted_relative_filename, isindex): Improve docstring\n\t* variables.cc (isglobal): Improve docstring\n\n2010-12-28  Rik  <octave@nomad.inbox5.com>\n\n\t* data.cc (and, ctranspose, eq, ge, gt, ldivide, le, lt, minus,\n\tmldivide, mpower, mrdivide, mtimes, ne, not, or, plus, power, rdivide,\n\ttimes, transpose, uminus, uplus): Improve docstrings for functions\n\twhich emulate operators.  Add Seealso cross-referencing.\n\n2010-12-28  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat5.cc (save_mat5_array_length (const float*, octave_idx_type,\n\tbool)): Take in to account the 4 bytes of padding for an odd number\n\tof elements in single precision arrays.\n\n2010-12-27  Rik  <octave@nomad.inbox5.com>\n\n\t* syscalls.cc (stat): Add additional calling form using file descriptor\n\tfid to docstring.\n\n2010-12-26  Michael Godfrey <godfrey@isl.stanford.edu>\n\n\t* gammainc.cc: Add @tex blocks to docstring.\n\n2010-12-25  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/str2double.cc: Fix bug in converting \"numberi\" strings\n\tsuch as \"2i\".  Add ability to process special value \"NA\".  Rewrite\n\tdocstring.\n\n2010-12-25  Rik  <octave@nomad.inbox5.com>\n\n\t* input.cc (PS1): Correct use of xref macro to remove Tex warning.\n\n2010-12-22  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* input.cc (PS1): Give an example of how PS1 can use ANSI escape\n\tcodes for getting a colourised prompt.\n\t* oct-hist.cc (history): Correct documentation about how\n\thistory(\"-r\") appends to history, doesn't replace it.\n\n2010-12-22  Judd Storrs  <jstorrs@gmail.com>\n\n\t* data.cc (Fvec): New optional second argument to set dimension\n\tof result.\n\n2010-12-18  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in (class axes::properties): Tag xtickmode, ytickmode\n\tand ztickmode with \"u\" qualifier.\n\t(axes::properties::update_xtickmode, axes::properties::update_ytickmode\n\taxes::properties::update_ztickmode): New functions.\n\n2010-12-18  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/dlmread.cc (Fdlmread): Simplify file name/id logic.\n\tBug #31910.\n\n2010-12-17  Rik  <octave@nomad.inbox5.com>\n\n\t* oct-parse.yy (builtin): Remove seealso reference to deprecated\n\tfunction dispatch.\n\n2010-12-17  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in (class text::properties): New properties positionmode,\n\trotationmode, horizontalalignmentmode, verticalalignmentmode.\n\t* graphics.cc (axes::properties::init, axes::properties::set_defaults):\n\tSet mode to auto for all initialized positioning properties.\n\t(axes::properties::set_xlabel,set_ylabel,set_zlabel,set_title):\n\tRevert to auto-positioning mode and turn clipping off when title or\n\tlabels are set.\n\t* gl-render.cc (opengl_renderer::draw_axes): Disable auto-positioning\n\tof manually positioned title and axes labels.\n\n2010-12-17  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.h.in (class axes::properties): Change default value for\n\tfontsize from 12 to 10.\n\t* graphics.cc (axes::properties::set_defaults): Likewise.\n\n2010-12-15  John W. Eaton  <jwe@octave.org>\n\n\tBug #31883.\n\n\t* oct-hist.cc (initialize_history): Call command_history::initialize.\n\n\t* octave.cc (gripe_safe_source_exception): New function.\n\t(safe_source_file): New function.\n\t(execute_startup_files): Call safe_source_file instead of source_file.\n\t(execute_command_line_file): Likewise.  Don't handle exceptions here.\n\t(execute_eval_option_code): Also catch octave_execution\texception.\n\n2010-12-15  John W. Eaton  <jwe@octave.org>\n\n\tBug #31861.  Also bug #31286.\n\n\t* lex.h (lexical_feedback::defining_func): Now int instead of bool.\n\tlex.ll (is_keyword_token): Increment lexer_flags.defining_func\n\tinstead of setting it to true.\n\t(lexical_feedback::init): Set defining_func to 0 instead of false.\n\t* oct-parse.yy (recover_from_parsing_function): Decrement\n\tlexer_flags.defining_func here.\n\t* input.cc (input_event_hook): Don't do anything if we are\n\tlexer_flags.defining_func is nonzero.\n\n2010-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* ov-struct.cc (isfield): Additional test for cellstring of field names.\n\n2010-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* data.cc (mod): Additional tests for mod with non-integer real values.\n\n2010-12-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Drop support for the \"i\" option.\n\n2010-12-09  Marco Atzeri   <marco_atzeri@yahoo.it>\n\n\t* mappers.cc: In test for gamma, expect Inf for gamma(-1), not NaN.\n\tBug #31772.\n\n2010-12-08  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (base_property::do_set): Don't reverse order of\n\tchildren.  Bug #31822.\n\n2010-12-08  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::find_user_function):\n\tReturn if an error occurs in out_of_date_check.\n\n2010-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::find): If an\n\terror occurred during the first call to xfind, don't try again.\n\n2010-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy (case_list): Also accept default_case by itself.\n\tBug #31793.\n\n2010-12-01  John W. Eaton  <jwe@octave.org>\n\n\t* pt-pr-code.cc\t(tree_print_code::visit_octave_user_function_trailer):\n\tDon't indent or print \"endfunction\" here.\n\t* ov-usr-fcn.cc (ov_user_script::do_multi_index_op): Save and\n\tset tree_evaluator::statement_context, not\n\ttree_evaluator::in_fcn_or_script_body.\n\t(ov_user_function::do_multi_index_op): Likewise.\n\t* pt-eval.cc: Initialize tree_evaluator::statement_context, not\n\ttree_evaluator::in_fcn_or_script_body.\n\t(tree_evaluator::visit_break_command): Check statement_context,\n\tnot in_fcn_or_script_body.\n\t(tree_evaluator::visit_continue_command): Likewise.\n\t(tree_evaluator::visit_return_command): Likewise.\n\t(visit_statement): Also echo commands in scripts if\n\tVecho_executing_commands & ECHO_SCRIPTS is true.\n\t* pt-eval.h (tree_evaluator::in_fcn_body,\n\ttree_evaluator::in_script_body): New static variables.\n\t(tree_evaluator::): Now an enum.\n\t(tree_evaluator::in_function_or_script_body): Now an enum.\n\tRename from in_fcn_or_script_body.\n\n2010-12-01  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (fltk_gui_mode): Fix gui mode\n\tproblems when set to none.\n\n2010-11-26  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (find_uimenu_children,\n\t__fltk_redraw__): Consider hidden handles here.\n\n2010-11-26  John W. Eaton  <jwe@octave.org>\n\n\t* defaults.cc (FEXEC_PATH): Only call set_exec_path if nargin is\n\tgreater than zero.\n\n2010-11-25  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (fltk_gui_mode): New\n\tfunction to set GUI mode.\n\t(__fltk_uigetfile__): Remove nargout from argument list.\n\t(plot_window): Remove gui_mode enum here.\n\n2010-11-25  John W. Eaton  <jwe@octave.org>\n\n\t* defaults.cc (set_exec_path): Append EXEC_PATH to PATH.  Store\n\tonly extra directories in EXEC_PATH.\n\t(FEXEC_PATH): Update doc string.\n\tBug #31695.\n\n2010-11-22  John W. Eaton  <jwe@octave.org>\n\n\t* defun.cc (defun_isargout): Cast nout to octave_idx_type in call\n\tto std::min.\n\n2010-11-21  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/fltk-backend.cc (__fltk_uigetfile__): New function\n\tfor GUI file dialogs.\n\t* graphics.cc (property_list::set): Indentation\tfix.\n\n2010-11-20  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.h.in: Change intended for 11272.\n\n2010-11-19  John W. Eaton  <jwe@octave.org>\n\n\tBug #31706.\n\n\t* mex.h, mex.cc (mxArray::dup): Rename from clone.  Change all\n\tuses and derived classes.\n\t(mxArray_octave_value::dup): Convert to mxArray object here.\n\n2010-11-19  John W. Eaton  <jwe@octave.org>\n\n\tBug #31707.\n\n\t* mex.cc (mex::free): Don't warn about skipping memory not\n\tallocated by mxMalloc, mxCalloc, or mxRealloc.\n\n2010-11-18  Daisuke TAKAGO  <takago@neptune.kanazawa-it.ac.jp>\n\n\t* gl-render.cc (opengl_renderer::draw_line):\n\tLayer markers in 2D plots.\n\n2010-11-18  John W. Eaton  <jwe@octave.org>\n\n\tBug # 31689.\n\n\t* ov-str-mat.cc (octave_char_matrix_str::save_ascii):\n\tAdapt to change in charMatrix::row_as_string function.\n\t* DLD-FUNCTIONS/md5sum.cc: New tests.\n\n2010-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* pt-fcn-handle.cc (tree_anon_fcn_handle::rvalue1): Also stash\n\tthe directory name of the parent function in the newly created\n\tanonymous function.  Bug #31484.\n\n2010-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy (parse_fcn_file): Protect and set global_command\n\tto 0 before calling yyparse.\n\t* toplev.cc (main_loop): Likewise.\n\n\t* oct-parse.yy (eval_string): Set global_command to 0 after\n\tprotecting it and before calling yyparse.\n\t* input.cc (get_debug_input): Likewise.\n\n2010-11-14  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (graphics_object::get_ancestor): New method.\n\t* graphics.cc (graphics_object::get_ancestor): Likewise.\n\t(convert_text_position, convert_cdata): Use it.\n\t(xget_ancestor): Remove obsolete function.\n\t* DLD_FUNCTIONS/fltk_backend.cc (plot_window::uimenu_update,\n\tfltk_backend::update): Replace xget_ancestor with\n\tgraphics_objects::get_ancestor.\n\n2010-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (figure::properties::filename): Make writable.\n\tBug #31450.\n\n2010-11-12  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (nodist_liboctinterp_la_SOURCES): Remove\n\t$(OPT_HANDLERS) from  the  list.  Bug #31623.\n\n2010-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc: New tests for cat.  Enable 4 asserts that were disabled.\n\n2010-11-11  Kai Habel  <kai.habel@gmx.de>\n\n\t* fltk-backend.cc (plot_window::uimenu_update,\n\tfltk_backend::update): Add prefix 'ID_' to property ids to avoid\n\tname clash on windows systems.\n\t* graphics.cc (gnuplot_backend::update): Ditto.\n\t* genprops.awk (emit_declarations, emit_source): Ditto.\n\n2010-11-11  John W. Eaton  <jwe@octave.org>\n\n\tBug #31165.\n\n\t* symtab.h (symbol_table::parent_classes): New static function.\n\t* symtab.cc (out_of_date_check): Also look for methods defined\n\tin parent classes of dispatch_type.\n\t(symbol_table::fcn_info::fcn_info_rep::load_class_method): Call\n\tparent_classes instead of accessing parent_map directly.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (octave_main): Call octave_ieee_init here.\n\t* sysdep.cc (sysdep_init): Not here.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc: Eliminate special case for __DECCXX.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc (sysdep_init): Eliminate special case for NeXT systems.\n\t(malloc_handler, NeXT_init): Delete.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* sighandlers.cc (MAYBE_ACK_SIGNAL): Delete macro and all uses.\n\t(sigchld_handler): Delete special case for __EMX__.\n\t* sysdep.cc (sysdep_init): Eliminate special case for __EMX__.\n\t(OS2_init, Fextproc): Delete.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc (sysdep_init): Eliminate special case for SCO.\n\t(SCO_init): Delete.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__dispatch__.cc: Rename from dispatch.cc.\n\tMove tests to scripts/deprecated/dispatch.m.\n\t(F__dispatch__): Rename from Fdispatch.\n\n\t* DLD-FUNCTIONS/module-files: Add __dispatch__.cc to the list.\n\tRemove dispatch.cc from the list.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy (Fbuiltin): Move here from DLD-FUNCTIONS/dispatch.cc.\n\n2010-11-10  Kai Habel  <kai.habel@gmx.de>\n\n\t* fltk-backend.cc (fltk_uimenu::update_accelerator\n\tfltk_uimenu::update_callback, fltk_uimenu::update_enable,\n\tfltk_uimenu::update_foregroundcolor fltk_uimenu::update_visible):\n\tCheck if find_item was succesful.\n\t(fltk_uimenu::update_seperator): Make sure we don't write beyond\n\tlimits of menubar structure.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\tBug #31491.\n\n\t* pt-pr-code.cc, pt-pr-code.h (tree_print_code::print_fcn_handle_body):\n\tNew function.\n\t* ov-fcn-handle (octave_fcn_handle::print_raw): Use it.\n\t* pt-pr-code.cc (tree_print_code::visit_anon_fcn_handle): Likewise.\n\t* pt-pr-code.h (tree_print_code::suppress_newline): Rename from\n\tprinting_newlines.  Now int.  Change all uses.\n\t* pt-pr-code.cc (tree_print_code::newline): Only set\n\tbeginning_of_line if newline is printed.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\tBug #31567.\n\n\t* ov-fcn.h (octave_base_value::is_class_constructor)\n\toctave_base_value::is_class_method): New optional character\n\tstring argument.\n\t* ov-usr-fcn.h (octave_usr_fcn::is_class_constructor)\n\toctave_usr_fcn::is_class_method): New optional arg. If this\n\targument is not empty, also check it against the name of the\n\tdispatch class.\n\t* ov-class.cc (Fclass): Allow class function to be called inside\n\ta class method.  Require that the to-be-constructed object is of\n\tthe same class as the class constructor or method.\n\n2010-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* lex.ll (handle_number): Set lexer_flags.looking_for_object_index\n\tto false here.  Fixes bug #31608.\n\n2010-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* gl-render.cc (make_marker_list): Call fmod instead of mod.\n\n\t* data.cc (Frem): Use xrem instead of fmod and fmodf.\n\t(Fmod): Use xmod instead of mod.\n\n2010-11-08  Kai Habel  <kai.habel@gmx.de>\n\n\t* fltk-backend.cc (fltk_uimenu::do_find_uimenu_children):\n\tSimplify.  Remove unused code.\n\t(fltk_uimenu::update_submenu): Remove unused function.\n\t(fltk_uimenu::add_to_menu, fltk_uimenu::remove_from_menu):\n\tSimplify.  Get properties for valid objects only.\n\n2010-11-03  Ben Abbott  <bpabbott@mac.com>\n\n\t* gl-render.cc: Do not give rendering error for uimenus.\n\n2010-11-03  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/cquad.cc: If we don't have copysign but we do\n\thave _copysign, define copysign to be _copysign.\n\n2010-11-02  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/cquad.cc (Fcquad): Use octave_Inf, not INFINITY.\n\n2010-11-02  David Bateman  <dbateman@free.fr>\n\n\t* ls-hdf5.cc (bool hdf5_get_scalar_attr (hid_t, hid_t,\n\tconst char *, void *), herr_t hdf5_add_scalar_attr\n\t(hid_t, hid_t, const char *, void *)): New functions.\n\t(herr_t hdf5_add_scalar_attr (hid_t, const char *)): Remove static\n\tdefinition to make this function visible externally.\n\t* ls-hdf5.h (extern OCTINTERP_API bool hdf5_check_attr (hid_t,\n\tconst char *), extern OCTINTERP_API bool hdf5_get_scalar_attr\n\t(hid_t, hid_t, const char *, void *buf), extern OCTINTERP_API herr_t\n\thdf5_add_attr (hid_t, const char *), extern OCTINTERP_API herr_t\n\thdf5_add_scalar_attr (hid_t, hid_t, const char *, void *)): Function\n\tdeclarations.\n\t* ov-range.cc (bool octave_range::save_hdf5 (hid_t, const char *,\n\tbool)): Save the number of elements in the range as an HDF5 attribute.\n\t(bool octave_range::load_hdf5 (hid_t, const char *)): If an HDF5\n\tattribute containing the number of elements exists use it to ensure\n\tthe correct number of elements in the range.\n\n2010-11-01  David Bateman  <dbateman@free.fr>\n\n\t* gl-render.cc (void opengl_renderer::draw_patch (const\n\tpatch::properties &)): Draw clipped contours of patches.\n\t* graphics.cc (template<class T> static void get_array_limits\n\t(const Array<T>&, double&, double&, double&)): Don't need to test\n\tfor NaN as comparison is always false.\n\t(Matrix children_property::do_get_children (bool) const): New method of\n\tnew children_property class.\n\t(void children_property::do_delete_children (bool)): Ditto.\n\t(void base_properties::remove_child (const graphics_handle&)): Delete.\n\t(void base_properties::set_children (const octave_value&)): Delete.\n\t(void base_properties::delete_children (void)): Delete.\n\t(base_properties::update_axis_limits (const std::string&,\n\tconst graphics_handle&) const): New method.\n\t(void base_graphics_object::update_axis_limits (const std::string&,\n\tconst graphics_handle&)): New Method.\n\t(Matrix base_properties::get_children_internal (bool) const): Delete.\n\t(Matrix base_properties::get_children (void) const): Delete.\n\t(Matrix base_properties::get_hidden_children (void) const): Delete.\n\t(void axes::update_axis_limits (const std::string&,\n\tconst graphics_handle&): New Method.\n\t(void hggroup::properties::update_limits (void) const): New method.\n\t(void hggroup::properties::update_limits (const graphics_handle&)\n\tconst): New method.\n\t(void hggroup::update_axis_limits (const std::string&,\n\tconst graphics_handle&)): New method.\n\t* graphics.h.in (class children_property): New class.\n\t(class base_properties): Use it.\n\t(base_graphics_object::update_axis_limits(const std::string&,\n\tconst graphics_handle&)): New method.\n\t(graphics_object::update_axis_limits(const std::string&,\n\tconst graphics_handle&)): New method.\n\t(axes::update_axis_limits(const std::string&,\n\tconst graphics_handle&)): New method.\n\t(hggroup::adopt (const graphics_handle&)): Use it\n\t(void hggroup::properties::update_limits (void) const): Remove inline\n\tdefinition of the methid.\n\t(void hggroup::properties::update_limits (const graphics_handle&)\n\tconst): New method.\n\t(void hggroup::update_axis_limits (const std::string&,\n\tconst graphics_handle&)): New method.\n\n2010-10-31  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* xnorm.h (xnorm, xcolnorms, xrownorms, xfrobnorm): tag with\n\tOCTINTERP_API.\n\n2010-10-31  Kai Habel  <kai.habel@gmx.de>\n\n\t* fltk-backend.cc (find_uimenu_children): Remove template argument.\n\t(do_find_uimenu_children): New function.\n\n2010-10-29  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (octave_value patch::properties::get_color_data\n\t(void) const): Don't call convert_data is the facevertexcdata\n\tproperty is undefined or empty.\n\t* gl-render.cc (void opengl_renderer::draw_patch\n\t(const patch::properties &)): Set ec_mode to 0 if edgecolor is \"none\".\n\tSet fc_mode to 0 if facecolor is \"none\".\n\n2010-10-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* gl-render.cc: Crop ticks, ticklabels, and gridlines for OpenGL\n\tbackend.\n\n2010-10-28  Konstantinos Poulios  <logari81@googlemail.com>\n\n\t* graphics.cc (normalized_aspectratios, max_axes_scale):\n\tNew file-scope static function\n\t(updating_aspectratios): New file-scope variable.\n\t(axes::properties::update_aspectratios, axes::update_axis_limits):\n\tReturn immediately if updating_aspecratios is true.\n\t(axes::properties::update_aspectratios):\n\tIf dataaspectratiomode is set to manual this function will try to\n\trespect it even after changes in xlim, ylim, zlim.\n\tIf both dataaspectratiomode and plotboxaspectratiomode is set to\n\tmanual this function will try to recalulate xlim, ylim, zlim\n\tdepending on the status of xlimmode, ylimmode, zlimmode. If\n\taltering xlim, ylim, zlim is not possible, plotboxaspectratio will\n\tbe overriden.\n\t* graphics.h.in (class axes::properties): Tag dataaspectratio,\n\tdataaspectratiomode, plotboxaspectratio, and\n\tplotboxaspectratiomode with \"u\" qualifier.\n\t(axes::update_dataaspectratio,\n\taxes::update_dataaspectratiomode,\n\taxes::update_plotboxaspectratio,\n\taxes::update_plotboxaspectratiomode): New functions.\n\n2010-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (octave_main): Use F77_CHAR_ARC_LEN macro to pass\n\tcharacter string length in call to xerbla.\n\n2010-10-25  Kai Habel  <kai.habel@gmx.de>\n\n\t* gl-render.cc (opengl_renderer::draw): Ignore uimenu objects here.\n\t* graphics.h.in (class OCTINTERP_API uimenu): New graphics object.\n\t* graphics.cc (lookup_object_name): Add uimenu here.\n\t(make_graphics_object_from_type): Likewise.\n\t(property_list::set): Likewise.\n\t(property_list::lookup): Likewise.\n\t(root_figure::init_factory_properties): Likewise.\n\t(__go_uimenu__): New function.\n\t* DLD-Functions/fltk-backend.cc (OpenGL_fltk::resize): Make public.\n\t(script_cb): New function.\n\t(fltk_uimenu): New class.\n\t(plot_window::plot_window): Initialize fltk_uimenu object.\n\t(plot_window::~plot_window): Delete fltk_uimenu object.\n\t(plot_window::show_menubar): New function.\n\t(plot_window::hide_menubar): New function.\n\t(plot_window::uimenu_update): New function.\n\t(plot_window::handle): Do not evaluate FLTK events when figure\n\tis deleted.\n\t(figure_manager::uimenu_update): New function.\n\t(figure_manager::toggle_menubar_visibility): New functions.\n\t(figure_manager::do_toggle_menubar_visibility): New function.\n\t(figure_manager::do_uimenu_update): New function.\n\t(fltk_backend::uimenu_set_fltk_label): New function.\n\t(fltk_backend::update): Add figure and uimenu updates.\n\n2010-10-24  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/tril.cc, syscalls.cc: Docstring improvements.\n\n2010-10-24  Rik  <octave@nomad.inbox5.com>\n\n\t* variables.cc: Deprecate is_global function\n\n2010-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (Ffopen): Only handle fopen (\"all\") case if nargout\n\tis 0 or 1.\n\n2010-10-22  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (usage): Put whitespace before and after usage message.\n\t(octave_main): If getopt_long returns '?', it means an\n\tunrecognized option was encountered.\n\tPanic if default case in option switch statement is reached.\n \t(verbose_usage, short_opts, usage_string): Remove '?' as an\n\talias for 'h' in the list of possible options.\n\tFixes bug #31423.\n\n2010-10-22  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy (load_fcn_from_file): Also strip directory when\n\tcomputing function name from filename.  Bug #31395.\n\n2010-10-21  Gunnar Farnebäck  <gunnar@lysator.liu.se>\n\n\t* mex.cc (mxArray_number::as_octave_value): Convert single\n\tmatlab array to single octave array instead of to double octave\n\tarray.\n\n2010-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* gripes.h: Include lo-array-gripes.h.\n\n2010-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* ov-float.cc, ov-flt-re-mat.cc, ov-re-mat.cc, ov-re-sparse.cc,\n\tov-scalar.cc: Use gripe_nan_to_character_conversion.\n\n\t* ops.h, ov-base-mat.cc, ov-base-scalar.cc, ov-complex.h,\n\tov-cx-mat.cc, ov-cx-sparse.cc, ov-float.h, ov-flt-complex.h,\n\tov-flt-cx-mat.cc, ov-flt-re-mat.cc, ov-range.cc, ov-re-mat.cc,\n\tov-re-sparse.cc, ov-scalar.h: Use gripe_nan_to_logical_conversion.\n\n2010-10-20  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (Fsystem): Allow optional RETURN_OUTPUT and TYPE\n\targuments to be specified independently.  Update doc string.\n\n2010-10-18  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::do_find_first_of,\n\tload_path::do_find_all_first_of): Also search path for relative\n\tfilenames.\n\n2010-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/tril.cc: Use Octave copyright notice instead of\n\tgeneric \"This program is free software\" notice.\n\n\t* toplev.cc (Fwarranty): Say \"GNU Octave\" instead of \"This program\".\n\n2010-10-16  John W. Eaton  <jwe@octave.org>\n\n\t* mxarray.h.in (mxArray::is_function_handle): New virtual function.\n\t* mex.cc (mxArray_base::is_function_handle): New pure virtual function.\n\t(mxArray_octave_value::is_function_handle): New function.\n\t(mxArray_matlab::is_function_handle): New function.\n\t(mxIsFunctionHandle): New function.\n\t* mexproto.h (mxIsFunctionHandle): Provide decl.\n\n2010-10-14  John W. Eaton  <jwe@octave.org>\n\n\t* sparse.cc: Rename from DLD-FUNCTIONS/sparse.cc.  Include\n\tdefun.h, not defun-dld.h.\n\t(Fissparse, Fsparse, Fspalloc): Use DEFUN, not DEFUN_DLD.\n\t* Makefile.am (DIST_SRC): Add sparse.cc to the list.\n\t* DLD-FUNCTIONS/module-files: Remove sparse.cc from the list of files.\n\n2010-10-09  Ben Abbott  <bpabbott@mac.com>\n\n\t* gl-render.cc: Treat images with scalar unique(x/ydata) like Matlab.\n\n2010-10-08  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (maximum_braindamage):\n\tSet do_braindead_shortcircuit_evaluation to true.\n\tDisable Octave:possible-matlab-short-circuit-operator warning.\n\t* oct-parse.yy (if_cmd_list1, elseif_clause, loop_command):\n\tMark conditions in IF and WHILE statements for braindead\n\tshort-circuit behavior.\n\t* pt-binop.cc (Vdo_braindead_shortcircuit_evaluation): New\n\tstatic variable.\n\t(Fdo_braindead_shortcircuit_evaluation): New function.\n\t(tree_binary_expression::rvalue1): Perform short-circuit\n\tevaluation of | and & expressions that are conditions of WHILE\n\tand IF statements if Vdo_braindead_shortcircuit_evaluation is true.\n\t* pt-binop.h\n\t(tree_binary_expression::eligible_for_braindead_shortcircuit):\n\tNew data member.  Initialize it in class constructors.\n\t(tree_binary_expression::mark_braindead_shortcircuit): New function.\n\t* pt-exp.h (tree_expression::mark_braindead_shortcircuit):\n\tNew virtual function.\n\n2010-10-08  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.h.in: Properly set image pixel size when unique(x/ydata)\n\tis scalar.\n\n2010-10-07  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/conv2.cc (convn): Update docstring.  Add 1 new test.\n\n2010-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/conv2.cc (convn): Style fixes.  Edit docstring.\n\n2010-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (do_stream_open): Use fileno instead of ::fileno to\n\tavoid problems if fileno is a macro.\n\n2010-10-05  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stdstrm.h (octave_stdiostream::octave_stdiostream): Use\n\tfileno instead of ::fileno to avoid problems if fileno is a macro.\n\n2010-10-04  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h.in (axis::properties::pixel_size): New function.\n\t(axis::properties::pixel_xsize,axis::properties::pixel_ysize):\n\tNew functions, use axis::properties::pixel_size\n\t(axis::properties::update_ydata,axis::properties::update_xdata):\n\tUse axis::properties::pixel_size functions\n\n\t* graphics.cc (__image_pixel_size__): New function uses\n\taxis::properties::pixel_size functions\n\n2010-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (class caseless_str): Move to\n\tliboctave/caseless-string.h.\n\n2010-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (base_properties::get_dynamic): Create and return\n\toctave_scalar_map object instead of Octave_map.\n\t(base_graphics_object::remove_all_listeners): Use octave_map\n\tinstead of Octave_map.\n\t(base_graphics_object::values_as_string): Likewise.\n\n\t* graphics.h.in, graphics.cc (property_list::as_struct):\n\tReturn octave_scalar_map instead of Octave_map.\n\t(base_graphics_object::values_as_struct): Likewise.\n\t(graphics_object:values_as_struct): Likewise.\n\t(graphics_object::set): Accept octave_map instead of Octave_map.\n\n\t* genprops.awk: Use octave_map instead of Octave_map in\n\tgenerated code.  Convert second arg to octave_value in call to\n\toctave_map::assign.\n\n2010-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_struct::as_octave_value): Use octave_map\n\tinstead of Octave_map.\n\n2010-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base.h: Delete forward decl for Octave_map class.\n\n2010-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.h (octave_struct (const Octave_map&)): Delete constructor.\n\n2010-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-inline.cc (octave_fcn_inline::map_value):  Use\n\toctave_scalar_map and octave_map instead of Octave_map.\n\n2010-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (symbol_info_list::map_value): Use\n\toctave_scalar_map and octave_map instead of Octave_map.\n\n2010-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.h (octave_fields::nil_rep): Make a static function.\n\t(octave_fields::octave_fields (void)): Use it here.\n\n2010-09-30  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (octave_config_info): Use Octave_scalar_map instead\n\tof Octave_map.\n\t* sighandlers.cc (make_sig_struct, FSIG): Likewise.\n\n\t* utils.cc (decode_subscripts): Use octave_map instead of Octave_map.\n\t* octave.cc (F__version_info__): Likewise.\n\t* pt-eval.cc (visit_complex_for_command): Likewise.\n\t* pt-idx.cc (tree_index_expression::lvalue): Likewise.\n\n2010-09-30  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gcd.cc: Style fixes.\n\n2010-09-30  John W. Eaton  <jwe@octave.org>\n\n\t* oct-errno.cc.in (octave_errno::do_list, octave_errno::list):\n\tUse octave_scalar_map instead of Octave_map.\n\n2010-09-30  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* DLD-FUNCTIONS/gcd.cc (divide): New function, complex integer\n\tdivision with remainder.\n\t(simple_gcd): Overload for complex values.\n\t(extended_gcd): Ditto.\n\t(do_simple_gcd): Dispatch for complex gcd.\n\t(do_extended_gcd): Ditto.\n\t(Fgcd): Mention that complex gcd is now also possible.\n\n2010-09-30  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* DLD-FUNCTIONS/gcd.cc (extended_gcd): Fix bug that didn't\n\tdistinguish the two output coefficients.\n\t(Fgcd): Fix off-by-one bug and typo from copy-pasted code.\n\n2010-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-parse.yy (Fautoload): Replace Octave_map by octave_map.\n\t* ov-fcn-handle.cc (Ffunctions): Replace Octave_map by\n\toctave_scalar_map.\n\n2010-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* help.cc (F__which__): Use octave_map instead of Octave_map.\n\t* load-save.cc (do_load, save_fields, save_vars): Use\n\toctave_scalar_map instead of Octave_map.\n\n2010-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* debug.cc (Fdbstatus, Fdbstack): Use octave_map instead of\n\tOctave_map.\n\t* error.cc (warning_options, initialize_warning_options,\n\tpr_where, Frethrow, Ferror, Fwarning, Flasterror): Use\n\toctave_scalar_map or octave_map instead of Octave_map.\n\n2010-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-errno.cc (octave_errno::list, octave_errno::do_list): Use\n\toctave_scalar_map instead of Octave_map.\n\t* oct-errno.h: Update decls.\n\n2010-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-idx.cc (tree_index_expression::make_arg_struct): Use octave_map\n\tinstead of Octave_map.\n\t* pt-idx.h: Update decl.\n\n2010-09-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.cc (octave_map::contents): Fix off-by-1 error.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc (OCTAVE_GLPK_GET_REAL_PARAM,\n\tOCTAVE_GLPK_GET_INT_PARAM): Use GETFIELD to access map fields,\n\tnot CONTENTS.\n\t* DLD-FUNCTIONS/amd.cc (Famd): Likewise.\n\t* DLD-FUNCTIONS/luinc.cc (Fluinc): Likewise.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (F__ftp_dir__): Use octave_scalar_map\n\tinstead of Octave_map.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/luinc.cc (Fluinc): Use octave_scalar_map\n\tinstead of Octave_map.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Use octave_scalar_map\n\tinstead of Octave_map.  Use scalar values where appropriate in\n\tcall to glpk.\n\t(OCTAVE_GLPK_GET_REAL_PARAM, OCTAVE_GLPK_GET_INT_PARAM):\n\tUpdate for octave_scalar_map.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/amd.cc (Famd): Use octave_scalar_map instead of\n\tOctave_map.\n\t* DLD-FUNCTIONS/cellfun.cc (get_output_list): Likewise.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/dispatch.cc (Fdispatch): Use octave_scalar_map\n\tinstead of Octave_map.\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::handle): Likewise.\n\t* DLD-FUNCTIONS/regexp.cc (octregexp): Likewise.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/eigs.cc (Feigs): Use octave_scalar_map instead\n\tof Octave_map.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/getpwent.cc (mk_pw_map): Use octave_scalar_map\n\tinstead of Octave_map.\n\t* DLD-FUNCTIONS/getgrent.cc (mk_gr_map): Likewise.\n\t* DLD-FUNCTIONS/getrusage.cc (Fgetrusage): Likewise.\n\n2010-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/time.cc (intfield, stringfield): New functions.\n\t(mk_tm_map, extract_tm): Arg is now octave_scalar_map instead of\n\tOctave_map.\n\t(extract_tm): Use local intfield and setfield functions.\n\t(Fmktime, Fstrftime): Use octave_scalar_map instead of Octave_map.\n\n2010-09-28  John W. Eaton  <jwe@octave.org>\n\n\t* Cell.h, Cell.cc (Cell::Cell (const std::list<std::string>&)):\n\tNew constructor.\n\n2010-09-28  John P. Swensen  <jpswensen@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (maybe_initialize_magick):\n\tWarn on initialization of *Magick if QuantumDepth is less than 32.\n\n2010-09-28  John P. Swensen  <jpswensen@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (F__magick_format_list__):\n\tNew function.\n\n2010-09-28  John P. Swensen  <jpswensen@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (encode_uint_image)\n\t(encode_bool_image): Ensure bit depth encoding is correct for\n\tlogical, uint8, and uint16 images.\n\n2010-09-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc (xpow (double, const Matrix&)): Ensure real result for\n\tpositive base.\n\t(xpow (double, const Matrix&)): Likewise.\n\n2010-09-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* error.cc (interpreter_try): New function.\n\t* error.h: Declare it.\n\t* ov-fcn-handle.cc (octave_fcn_binder::maybe_binder): Use it here.\n\t* variables.cc (safe_symbol_lookup): Also here.\n\n2010-09-27  John W. Eaton  <jwe@octave.org>\n\n\t* gl-render.cc (opengl_renderer::draw_axes): Reverse order in\n\twhich child objects are processed.\n\n2010-09-26  Rik  <octave@nomad.inbox5.com>\n\n\t* load-path.cc: Use single quotes for regex when possible.\n\t* DLD-FUNCTIONS/regexp.cc (regexp): Update docstring to highlight\n\tdifferences between POSIX and PCRE regex.\n\n2010-09-26  Rik  <octave@nomad.inbox5.com>\n\n\t* load-path.cc: Use single quotes for regular expression patterns when\n\tpossible.\n\n2010-09-26  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/regexp.cc (regexp, regexprep, regexpi): Update\n\tdocstrings to more fully explain PCRE.  Modify advanced tests to run\n\tonly run when PCRE is present.\n\n2010-09-25  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (Fquit): Allow any number of output parameters.\n\n2010-09-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/gcd.cc (Fgcd): Rewrite. Use more efficient code.\n\tSpecialize for simple/extended Euclid. Handle integer arguments.\n\n2010-09-24  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/regexp.cc (regexp, regexprep): Update docstring to\n\tdiscuss limits when not compiled with PCRE.\n\n2010-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (ALL_DEF_FILES): New variable.\n\t(DEF_FILES): Don't include $(DLD_DYNAMIC_DEF_FILES) in the list.\n\t(DEF_FILES DLD_DYNAMIC_DEF_FILES): Fix dependency info.\n\t(doc-files): Depend on $(ALL_DEF_FILES), not $(DEF_FILES).\n\n2010-09-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc (elem_xpow (float, const NDArray&),\n\telem_xpow (float, const FloatNDArray&)): Use simpler tests.\n\n2010-09-21  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.h (octave_base_stream::file_number): Return 0, 1,\n\tand 2 for named stdin, stdout, and stderr streams; -1 otherwise.\n\n2010-09-21  John W. Eaton  <jwe@octave.org>\n\n\t* syscalls.cc (Fgethostname): New function.\n\n2010-09-20  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/time.cc (Fmktime): New tests (bug #31079).\n\n2010-09-20  John W. Eaton  <jwe@octave.org>\n\n\tBug #31085:\n\n\t* file-io.cc (do_stream_open): Use fopen, fileno, and gzdopen\n\tinstead of gzopen.  Pass integer file id to\n\toctave_zstdiostream::create.\n\n\t* oct-stdstrm.h (class octave_base_tstdiostream): Rename from\n\toctave_tstdiostream.\n\t(octave_tstdiostream::fnum): New data member.\n\t(octave_tstdiostream::file_number): New member function.\n\t(octave_tstdiostream::octave_tstdiostream): New arg, FID.\n\t(octave_tstdiostream::create): Delete.\n\t(class octave_stdiostream, class octave_zstdiostream): New\n\tnon-template classes derived from octave_tstdiostream to replace\n\ttypedefs.\n\n\t* oct-stream.h (octave_base_stream::file_number): Now virtual\n\tand const.  Return -1 in defaault implementation.\n\n2010-09-20  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp_list) [HAVE_PCRE]:\n\tBreak from search loop if idx is at or beyond end of buffer\n\t(bug #31056).\n\n2010-09-19  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.h.in: Add displayname property to patch and surface objects.\n\n2010-09-18  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in: Remove properties for dead legend code.\n\n2010-09-18  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.cc: Replace pagetype property value custom with <custom>.\n\n2010-09-16  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (static Matrix screen_size_pixels (void), static Matrix\n\tpapersize_from_type (const caseless_str, const caseless_str))): New\n\tfunctions.\n\t(void figure::properties::set_paperunits (const octave_value&),\n\tvoid figure::properties::set_papertype (const octave_value&),\n\tvoid figure::properties::update_paperunits (const caseless_str&))\n\tvoid figure::properties::update_papertype (void),\n\tvoid figure::properties::update_papersize (void),\n\tvoid figure::properties::update_units (const caseless_str&)): New\n\tmethods of the figure class.\n\t(void axes::properties::set_units (const octave_value&),\n\tvoid axes::properties::update_units (const caseless_str&),\n\tvoid axes::properties::set_fontunits (const octave_value&),\n\tvoid axes::properties::update_fontunits (const caseless_str&)):\n\tNew methods of the axes class.\n\t* graphics.h.in (void figure::properties::update_paperunits\n\t(const caseless_str&), void figure::properties::update_units\n\t(const caseless_str&)): Declaration of new figure methods.\n\t(void figure::properties::update_paperunits (const caseless_str&),\n\tvoid figure::properties::update_units (const caseless_str&)):\n\tDeclaration of new axes methods.\n\n2010-09-16  John P. Swensen  <jpswensen@gmail.com>\n\n\t* DLD-FUNCTIONS/))magick_read__.cc (write_image): Remove\n\tunnecessary for loop to set image format.\n\n2010-09-16  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/svd.cc (Fsvd): Delete assert to avoid\n\t\"comparison is always false due to limited range of data type\"\n\twarning from GCC.\n\n\t* utils.cc (octave_vsnprintf): Declare nchars volatile to avoid\n\tGCC warning.\n\n\t* pr-output.cc (octave_print_internal): Avoid uninitialized\n\tvariable warning from GCC.\n\n2010-09-16  John Swensen  <jpswensen@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (write_image): Allow\n\tarbitrary extensions with format specifier.\n\n2010-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (Faddpath, Frmpath): Document path arguments.\n\n2010-09-15  John Swensen  <jpswensen@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (write_image): Allow writing\n\tarbitrary image types to filenames without an extension (bug #30784).\n\n2010-09-14  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (symbol_exist): If looking for any type of file\n\tor \"file\", return 7 for directories and 2 for all other types of\n\tfiles.\n\n2010-09-14  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (base_graphics_backend::initialize): Rename\n\tfrom base_graphics_backend::object_created.  Change all uses.\n\t(base_graphics_backend::finalize): Rename from\n\tbase_graphics_backend::object_destoyed.  Change all uses.\n\t(base_graphics_backend::update): Rename from\n\tbase_graphics_backend::property_changed.  Change all uses.\n\n2010-09-14  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (fltk_backend::object_destroyed):\n\tDon't attempt to delete window if __plot_stream__ is empty.\n\n2010-09-14  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* load-path.cc (genpath): Pass SKIP in recursive call.\n\t(Fgenpath): Accept list of directories to skip.\n\n2010-09-14  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (BEGIN_CHAR_CLASS_CONVERSION): If we hit EOF but\n\thave found a match, clear the stream state (bug # 30997).\n\n2010-09-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Remove subsref optimization.\n\n2010-09-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellindexmat): New DEFUN.\n\n2010-09-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-fcn-handle.cc (octave_fcn_binder::maybe_binder): Stash name tags\n\tin the template.\n\t(octave_fcn_binder::do_multi_index_op): Don't use xelem to ensure\n\tproper unsharing. Make a shallow copy prior to call to ensure\n\tconsistency throughout recursive calls.\n\n2010-09-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-fcn-handle.h (octave_fcn_binder): New subclass.\n\t* ov-fcn-handle.cc: Define methods.\n\t* pt-fcn-handle.cc (tree_anon_fcn_handle::rvalue1): Call\n\toctave_fcn_binder::maybe_binder.\n\n2010-09-11  John W. Eaton  <jwe@octave.org>\n\n\t* pt-misc.cc (tree_parameter_list::initialize_undefined_elements):\n\tAvoid GCC shadow variable warning.\n\n2010-09-11  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (Faddpath): Adjust value of nargin if numeric\n\toption is found (bug #31001).\n\n2010-09-09  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* gl2ps-renderer.cc: Renders to a previously opened fid.\n\t* gl2ps-renderer.h: Ditto.\n\t* DLD-FUNCTIONS/fltk_backend.cc: print now accepts fid instead\n\tof filename to use with above change\n\n2010-09-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (maybe_initialize_magick): New\n\thelper function. Move initialization code & static variable here.\n\t(F__magick_read__, F__magick_write__, F__magick_finfo__): Call it\n\there.\n\n2010-09-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cquad.cc: New source, courtesy by Pedro Gonnet.\n\t* DLD-FUNCTIONS/module-files: Update.\n\n2010-09-01  Marco Caliari  <marco.caliari@univr.it>\n\n\t* graphics.cc: Fix axes limits underflow to zero for logscale.\n\n2010-09-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-mat.cc (single_type_concat (Array<T>&, ...)): Optimize all\n\tscalars case.\n\n2010-09-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.cc (octave_map::cat): Search first for an index with\n\tnonzero nfields and use it for comparisons.\n\t(permute_to_correct_order1): New overloaded helper func.\n\t(permute_to_correct_order): use it here. Pass the index here.\n\t* pt-mat.cc (single_type_concat): Don't subst 0x0 for all empty\n\tarrays. Use the respective cat() capability instead.\n\n2010-09-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/dlmread.cc (Fdlmread): Support \"emptyvalue\" option.\n\tFix condition for terminating read.\n\n2010-08-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/dlmread.cc (Fdlmread): Support reading from a file ID.\n\n2010-08-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-class.cc (get_current_method_class): Make it an octave_class\n\tmethod. Return class_name as default.\n\t(octave_class::dotref): Error on zero return value.\n\n2010-08-30  Ben Abbott  <bpabbott@mac.com>\n\n\t* gl-render.cc: Matlab compatible markers for the OpenGL.\n\n2010-08-30  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (convert_cdata_1, convert_cdata_2): New functions.\n\t(convert_cdata): Use them to avoid converting all elements of\n\tcdata to double at once.\n\t* graphics.h.in (surface::properties::init): Constrain cdata and\n\talphadata to be single, double, or uint8.\n\n2010-08-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* graphics.cc (convert_cdata): Avoid extracting pointer to temporary\n\tcopy.\n\n2010-08-30  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (convert_cdata): Allow cdata to be any type that\n\tcan be converted to double.\n\t* graphics.h.in (surface::properties::init): Remove constraints\n\ton cdata and alphadata.\n\n2010-08-27  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>\n\n\t* graphics.cc (axes::properties::rotate_view): Don't rotate past\n\tthe top and bottom.\n\t(axes::properties::update_camera): Fix the view when rotating to\n\tthe bottom.\n\t(calc_dimensions): New static function.\n\t(F__calc_dimensions__) New defun to replace m-script function.\n\t* graphics.h.in (calc_dimension): Provide decl.\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::plot_window):\n\tUse calc_dimensions to decide whether the current figure should\n\tbe rotated.\n\t(plot_window::mark_modified) Recompute the number of dimensions.\n\tDeactivate rotation if necessary.\n\t(plot_window::ndim) New data member.\n\t(plot_window::button_press, plot_window::handle): Only turn on\n\trotation if ndim == 3.\n\n2010-08-24  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat5.cc (static void read_mat5_binary_data (std::istream&,\n\tfloat *, octave_idx_type, bool, mat5_data_type,\n\toct_mach_info::float_format)) : New function\n\t(std::string read_mat5_binary_element (std::istream&,\n\tconst std::string&, bool, bool&, octave_value&)): Treat\n\tMAT_FILE_SINGLE_CLASS as single precision rather than convert to\n\tdouble precision.\n\t(static void write_mat5_array (std::ostream&, const FloatNDArray&,\n\tbool), int save_mat5_array_length (const float*, octave_idx_type,\n\tbool), int save_mat5_array_length (const FloatComplex*,\n\toctave_idx_type, bool)): New functions.\n\t(int save_mat5_element_length (const octave_value&,\n\tconst std::string&, bool save_as_floats, bool), bool\n\tsave_mat5_binary_element (std::ostream&, const octave_value&,\n\tconst std::string&, bool, bool, bool, bool)):  Treat\n\tMAT_FILE_SINGLE_CLASS as single precision rather than convert to\n\tdouble precision.\n\n2010-08-23  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::dir_info::initialize): Clear\n\tmethod_file_map before updating file list.\n\t* load-path.cc (load_path::load_path): Explicitly initialize\n\tprivate_fcn_map.\n\n2010-08-17  Rik  <octave@nomad.inbox5.com>\n\n\t* mappers.cc (gamma,lgamma): Add %!tests for negative integer\n\tinput arguments.\n\n2010-08-17  Rik  <octave@nomad.inbox5.com>\n\n\t* bitfcns.cc (bitmax): Add additional calling argument, class, and\n\tadditional return value for bitmax(\"single\").\n\n2010-08-17  Rik  <octave@nomad.inbox5.com>\n\n\t* bitfcns.cc (sizemax): Improve documentation string.\n\n2010-08-16  Ben Abbott  <bpabbott@mac.com>\n\n\t* gl2ps.c: Use upstream version gl2ps-1.3.5-svn-20100816.\n\n2010-08-13  Rik  <octave@nomad.inbox5.com>\n\n\t* toplev.c (do_goto_frame_relative): Remove unused variable c.\n\n2010-08-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-builtin.cc\n\t(octave_builtin::subsref (..., const std::list<octave_lvalue> *)\n\toctave_builtin::do_multi_index_op (..., const std::list<octave_lvalue> *)):\n\tNew methods. Move code here. Set curr_lvalue_list.\n\t(octave_builtin::curr_lvalue_list): New static member.\n\t* ov-fcn-handle.h: Declare them.\n\t* defun.cc (defun_isargout): New overloaded function.\n\t* defun-int.h: Declare it.\n\n2010-08-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-lazy-idx.h (octave_lazy_index::subsasgn): Remove override. Leave\n\tit to the defualt numeric conversion mechanism.\n\n2010-08-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fdiff): Allow logical type.\n\n2010-08-09  Rik  <octave@nomad.inbox5.com>\n\n\t* oct-parse.yy (parse_fcn_file): Restore parsing of help text\n\taccidentally lost in previous changeset.\n\n2010-08-09  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy (parse_fcn_file): Handle empty script files\n\t(bug #30588).\n\n2010-08-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::assign (assign_op, const std::string&,\n\tconst std::list<octave_value_list>&, const octave_value&):\n\tDon't attempt to fix struct assignment to non-struct values here.\n\tCheck for successful assignment before overwriting this.\n\n\t* ov-cell.cc (octave_cell::subsasgn): Allow dot assignment into empty\n\tcell.\n\n2010-08-08  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/config-module.awk: Add newlines to divide blocks\n\tin generated modules.mk and improve readability.\n\n2010-08-08  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Create .DOCSTRINGS quietly and avoid screen clutter\n\tduring build.\n\n2010-08-08  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Run do_subst macro quietly without cluttering screen\n\tduring build.\n\n2010-08-08  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc\n\t(base_graphics_backend::print_figure): Add a redraw to get the\n\tthing going.\n\n2010-08-05  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* gl2ps-renderer.cc (draw): Add support for more terminal types.\n\t* DLD-FUNCTIONS/fltk_backend.cc: Likewise.\n\n2010-08-04  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_number (const char *)): Create empty string if\n\tgiven NULL arg  (bug #30639).  Create 0x0 string array if given\n\tan empty string argument, not 1x0.\n\n2010-08-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-str-str.cc: Fix assignment operator.\n\t* OPERATORS/op-str-s.cc: Likewise.\n\t* OPERATORS/op-str-m.cc: Likewise.\n\n2010-08-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-fcn-handle.cc\n\t(octave_value::subsref (..., const std::list<octave_lvalue> *)\n\toctave_value::do_multi_index_op (..., const std::list<octave_lvalue> *)):\n\tNew methods. Move code here.\n\t* ov-fcn-handle.h: Declare them.\n\n2010-08-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-usr-fcn.cc (Fis_ignored_output): Rename to Fisargout. Change the\n\tbehavior to indicate not ignored outputs.\n\n2010-08-01  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/amd.cc, DLD-FUNCTIONS/balance.cc,\n\tDLD-FUNCTIONS/besselj.cc, DLD-FUNCTIONS/betainc.cc,\n\tDLD-FUNCTIONS/ccolamd.cc, DLD-FUNCTIONS/cellfun.cc,\n \tDLD-FUNCTIONS/chol.cc, DLD-FUNCTIONS/colamd.cc, DLD-FUNCTIONS/daspk.cc,\n\tDLD-FUNCTIONS/dasrt.cc, DLD-FUNCTIONS/dot.cc, DLD-FUNCTIONS/eigs.cc,\n\tDLD-FUNCTIONS/fftw.cc, DLD-FUNCTIONS/filter.cc,\n\tDLD-FUNCTIONS/lookup.cc, DLD-FUNCTIONS/lsode.cc, DLD-FUNCTIONS/lu.cc,\n\tDLD-FUNCTIONS/matrix_type.cc, DLD-FUNCTIONS/onCleanup.cc,\n\tDLD-FUNCTIONS/qr.cc, DLD-FUNCTIONS/rand.cc, DLD-FUNCTIONS/regexp.cc,\n\tDLD-FUNCTIONS/sparse.cc, DLD-FUNCTIONS/str2double.cc,\n\tDLD-FUNCTIONS/tril.cc, DLD-FUNCTIONS/typecast.cc, data.cc, graphics.cc,\n\tload-save.cc, ov-null-mat.cc, ov-struct.cc, ov-usr-fcn.cc,\n\tpr-output.cc, strfns.cc, variables.cc: Grammarcheck documentation.\n\tAdd @noindent lines and ensure line length is less than 80.\n\n2010-07-31  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc, DLD-FUNCTIONS/__voronoi__.cc,\n\tDLD-FUNCTIONS/amd.cc, DLD-FUNCTIONS/balance.cc,\n\tDLD-FUNCTIONS/besselj.cc, DLD-FUNCTIONS/betainc.cc,\n\tDLD-FUNCTIONS/ccolamd.cc, DLD-FUNCTIONS/cellfun.cc,\n\tDLD-FUNCTIONS/chol.cc, DLD-FUNCTIONS/colamd.cc, DLD-FUNCTIONS/conv2.cc,\n\tDLD-FUNCTIONS/convhulln.cc, DLD-FUNCTIONS/daspk.cc,\n\tDLD-FUNCTIONS/dasrt.cc, DLD-FUNCTIONS/dassl.cc,\n\tDLD-FUNCTIONS/dmperm.cc, DLD-FUNCTIONS/dot.cc, DLD-FUNCTIONS/eigs.cc,\n\tDLD-FUNCTIONS/fftn.cc, DLD-FUNCTIONS/fftw.cc, DLD-FUNCTIONS/filter.cc,\n\tDLD-FUNCTIONS/find.cc, DLD-FUNCTIONS/gammainc.cc, DLD-FUNCTIONS/gcd.cc,\n\tDLD-FUNCTIONS/getrusage.cc, DLD-FUNCTIONS/givens.cc,\n\tDLD-FUNCTIONS/hess.cc, DLD-FUNCTIONS/hex2num.cc, DLD-FUNCTIONS/inv.cc,\n\tDLD-FUNCTIONS/kron.cc, DLD-FUNCTIONS/lookup.cc, DLD-FUNCTIONS/lsode.cc,\n\tDLD-FUNCTIONS/lu.cc, DLD-FUNCTIONS/luinc.cc,\n\tDLD-FUNCTIONS/matrix_type.cc, DLD-FUNCTIONS/max.cc,\n\tDLD-FUNCTIONS/md5sum.cc, DLD-FUNCTIONS/onCleanup.cc,\n\tDLD-FUNCTIONS/qr.cc, DLD-FUNCTIONS/quad.cc, DLD-FUNCTIONS/qz.cc,\n\tDLD-FUNCTIONS/rand.cc, DLD-FUNCTIONS/regexp.cc, DLD-FUNCTIONS/schur.cc,\n\tDLD-FUNCTIONS/sparse.cc, DLD-FUNCTIONS/spparms.cc,\n\tDLD-FUNCTIONS/str2double.cc, DLD-FUNCTIONS/strfind.cc,\n\tDLD-FUNCTIONS/sub2ind.cc, DLD-FUNCTIONS/svd.cc, DLD-FUNCTIONS/syl.cc,\n\tDLD-FUNCTIONS/symbfact.cc, DLD-FUNCTIONS/time.cc,\n\tDLD-FUNCTIONS/tril.cc, DLD-FUNCTIONS/typecast.cc,\n\tDLD-FUNCTIONS/urlwrite.cc, bitfcns.cc, data.cc, debug.cc, defaults.cc,\n\tdirfns.cc, error.cc, file-io.cc, graphics.cc, help.cc, input.cc,\n\tload-path.cc, load-save.cc, ls-oct-ascii.cc, mappers.cc, oct-hist.cc,\n\toctave.cc, ov-base.cc, ov-cell.cc, ov-class.cc, ov-fcn-handle.cc,\n\tov-fcn-inline.cc, ov-null-mat.cc, ov-range.cc, ov-struct.cc,\n\tov-usr-fcn.cc, pager.cc, pr-output.cc, pt-eval.cc, pt-mat.cc,\n\tsighandlers.cc, strfns.cc, symtab.cc, syscalls.cc, sysdep.cc,\n\ttoplev.cc, utils.cc, variables.cc: Grammarcheck .cc files\n\n2010-07-30  John W. Eaton  <jwe@octave.org>\n\n\t* debug.cc (Fdbstack): Improve display.\n\n\t* toplev.cc (octave_call_stack::do_goto_frame_relative):\n\tImprove message.  Don't display column number.\n\n\t* debug.cc (get_file_line): Don't allow eol to be less than bol.\n\t(Fdbwhere): Improve message.  Don't display column number.\n\t(Fdbstack): Omit column number from display.\n\n\t* pt-eval.cc (tree_evaluator::visit_statement): Don't call\n\toctave_call_stack::set_statement for commands issued while\n\tdebugging.\n\n2010-07-30  John W. Eaton  <jwe@octave.org>\n\n\t* pt-bp.cc (tree_breakpoint::take_action): Only call\n\tdelete_breakpoint if is_breakpoint returns true.\n\t(tree_breakpoint::visit_statement): If statement is command,\n\taccept it, otherwise, maybe take action on the statement.\n\t(tree_breakpoint::visit_no_op_command): Handle breakpoints at\n\tend of function.\n\tAddresses more problems found with bug #30490.\n\n2010-07-30  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: add .DOCSTRINGS to the DISTCLEANFILES list\n\n2010-07-30  John W. Eaton  <jwe@octave.org>\n\n\t* pt-eval.cc (tree_evaluator::visit_if_command,\n\ttree_evaluator::visit_switch_command): Also process breakpoints\n\tfor the command (bug #30490).\n\n2010-07-29  Ben Abbott  <bpabbott@mac.com>\n\n\t* gl-render.cc: Transpose markers '^' and 'v'.\n\n2010-07-29  John W. Eaton  <jwe@octave.org>\n\n\t* pt-bp.cc (tree_breakpoint::visit_if_command): Also allow\n\tbreakpoint to be set on command, same as for switch, while, or\n\tdo-until statments.\n\t* pt-select.h, pt-select.cc (tree_if_command::set_breakpoint,\n\ttree_if_command::delete_breakpoint, tree_switch_command::set_breakpoint,\n\ttree_switch_command::delete_breakpoint): Delete functions and decls.\n\t(bug #30490).\n\n2010-07-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::subsref (..., const std::list<octave_lvalue> *)\n\toctave_value::do_multi_index_op (..., const std::list<octave_lvalue> *)):\n\tNew methods.\n\t* ov.h: Declare them.\n\t* ov-base.cc (octave_base_value::subsref (..., const std::list<octave_lvalue> *)\n\toctave_base_value::do_multi_index_op (..., const std::list<octave_lvalue> *)):\n\tNew methods.\n\t* ov-base.h: Declare them.\n\t* ov-usr-fcn.cc (octave_user_function::subsref (..., const std::list<octave_lvalue> *)\n\toctave_user_function::do_multi_index_op (..., const std::list<octave_lvalue> *)):\n\tNew virtual method overrides. Move code here.\n\t(octave_user_function::bind_automatic_vars): Add lvalue_list\n\tparameter. Bind automatic variable \".ignored.\".\n\t(Fis_ignored_output): New defun.\n\t* ov-usr-fcn.h: Update decls.\n\t* pt-misc.cc (tree_parameter_list::initialize_undefined_elements):\n\tSkip warning if outputs are ignored.\n\t* pt-exp.cc (tree_expression::rvalue (..., const\n\tstd::list<octave_lvalue> *)): New method overload.\n\t* pt-exp.h: Declare it.\n\t* pt-idx.cc (tree_index_expression::rvalue (..., const\n\tstd::list<octave_lvalue> *)): New method override. Move code here.\n\t* pt-idx.h: Declare it.\n\t* pt-assign.cc (tree_multi_assignment::rvalue): Pass in the pointer to\n\tlvalue_list.\n\n2010-07-28  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/find.cc (Ffind): Reorder cases to check for\n\tcharacter strings before numeric arrays.\n\tDelete explicit instantiations of find_nonzero_elem_idx templates.\n\tNew test for char array argument.\n\n2010-07-27  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/schur.cc (rsf2csf): Change first documentation line to\n\tactive voice.\n\n2010-07-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/schur.cc (Frsf2csf): New DEFUN.\n\n2010-07-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-scalar.cc (octave_base_scalar::diag): Implement here. Fix.\n\t* ov-base-scalar.h: Only declare here.\n\n2010-07-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-diag.cc (octave_diag_matrix::try_narrowing_conversion): Remove\n\tredundant cast.\n\t* ov-flt-re-diag.cc\n\t(octave_float_diag_matrix::try_narrowing_conversion): Ditto.\n\t* ov-cx-diag.cc\n\t(octave_complex_diag_matrix::try_narrowing_conversion): Ditto.\n\t* ov-flt-cx-diag.cc\n\t(octave_float_complex_diag_matrix::try_narrowing_conversion): Ditto.\n\n2010-07-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-mat.cc (do_single_type_concat_no_mutate): Remove.\n\t(tree_matrix::rvalue1): Use do_single_type_concat instead.\n\n2010-07-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* bitfcns.cc (Fsizemax): New DEFUN.\n\n2010-07-20  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::plot_window):\n\tAdded a bottom Fl_Box (copied from gmsh) and tooltips\n\n2010-07-20  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/typecast.cc (typecast): Combine two @seealso macro\n\tuses to one.\n\n2010-07-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/dlmread.cc (Fdlmread): Use octave_idx_type instead of\n\tunsigned long. Over-allocate by a factor 2 to reduce copying.\n\tAttempt to estimate number of columns from first line.\n\tHoist tmp_stream out of the loop and reset it for each substring.\n\n2010-07-17  Rik  <octave@nomad.inbox5.com>\n\n\t* data.cc (repelems): Add more documentation about new function.\n\n2010-07-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (do_repelems): New helper func.\n\t(Frepelems): New DEFUN.\n\n2010-07-19  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::gui_mode):\n\tUse enum instead of int.  Change all uses.\n\n2010-07-18  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc: Add mode for mouse rotation.\n\t(view2status): new function\n\t* graphics.cc: Remove limitations for zooming and translation.\n\t(axes::properties::rotate_view): new function\n\n2010-07-17  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/ccolamd.cc,\n\t  DLD-FUNCTIONS/cellfun.cc, DLD-FUNCTIONS/dasrt.cc,\n\t  DLD-FUNCTIONS/dmperm.cc, DLD-FUNCTIONS/eigs.cc, DLD-FUNCTIONS/qz.cc,\n\t  DLD-FUNCTIONS/rand.cc, DLD-FUNCTIONS/sparse.cc,\n\t  DLD-FUNCTIONS/sqrtm.cc, DLD-FUNCTIONS/symrcm.cc, dirfns.cc,\n\t  file-io.cc, syscalls.cc: Spellcheck documentation\n\n2010-07-08  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD_FUNCTIONS/rand.cc: Correct typo in rande documentation.\n\t(bug #30446).\n\n2010-07-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (mat2cell_mismatch, prepare_idx,\n\tdo_mat2cell_2d, do_mat2cell_nd, do_mat2cell): New helper funcs.\n\t(Fmat2cell): Use them here.\n\n2010-07-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (do_sparse_diff): Use typecasts where needed.\n\n2010-07-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/rand.cc (do_rand): Pass the distribution name as an\n\targument. Ensure restoration using unwind_protect.\n\t(Frand, Frandn, Frandg, Frandp, Frande): Update.\n\n2010-07-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* unwind-prot.h (unwind_protect::fcn_crefarg_elem): New class.\n\t(unwind_protect::add_fcn (void (*) (const T&), T)): New method\n\toverload.\n\n2010-07-08  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/__magick_read__,cc (F__magick_read__): Add the syntax\n\t__magick_read__ (\"file\", \"frames\", \"all\").\n\n2010-07-08  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD_FUNCTIONS/eigs.cc: Initialize random number generator in test\n\tblocks to get reproducible results.\n\n2010-07-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cell.cc (Fstruct2cell): Use octave_map. Optimize.\n\n2010-07-07  Rik  <octave@nomad.inbox5.com>\n\n\t* pr-output.cc (calc_scale_exp): Avoid use of % operator on negative\n\toperands for portability between C++ compilers.\n\t(engineering_exponent): Avoid use of % operator.  Keep calculation of\n\texponent within pr_engineering_float class.  (encapsulation).\n\t(num_digits): Rename from calc_digits.  Return true number of digits =\n\t1 + calc_digits.\n\t(calc_scale_exp): Rename from maybe_mod3 for readability.\n\t(operator << (... pr_engineering_float pef): Use pef abbreviation for\n\tpr_engineering_float.\n\n2010-07-07  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (axes): Add hidden property __hold_all.\n\n2010-07-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-class.h (octave_class::map): Turn to octave_map.\n\t* ov-class.cc (octave_class): Update methods.\n\t* ov-base.h, ov-base.cc (octave_base_value::old_map_value) : Remove.\n\t* ov.h, ov.cc (octave_value::old_map_value) : Remove.\n\n2010-07-06  David Bateman  <dbateman@free.fr>\n\n\t* pr-output.cc (static bool print_eng): Flag engineering format,\n\t(float_format::float_format (int, int, int, int)): New constructor.\n\t(int float_format::ex): New field in the class.\n\t(static int maybe_mod3 (const int&), static int\n\tengineering_exponent (const double&),\n\tstatic int calc_digits (const double&)): New functions\n\t(class pr_engineering_float): New class\n\t(std::ostream& operator << (std::ostream&,\n\tconst pr_formatted_float&)): New operator. Make it a friend of the\n\tfloat_format class.\n\t(static void set_real_format(...),\n\tstatic void set_real_matrix_format (...),\n\tstatic void set_complex_format(...),\n\tstatic void set_complex_matrix_format (...),\n\tstatic void set_range_format (...)): Set width for engineering format.\n\t(static void set_format (...)): Call calc_digits to find the number\n\tof digits in a value.\n\t(static void pr_any_float (const float_format *, std::ostream&,\n\tdouble, int)): Print engineering formats.\n\t(static void init_format_state (void)): Set default state of print_eng.\n\t(static void set_format_style (int, const string_vector&)): Parse\n\tthe \"eng\" argument.\n\t(Fformat): Document the new engineering format.\n\n2010-07-04  Søren Hauberg  <hauberg@gmail.com>\n\n\t* DLD_FUNCTIONS/__magick_read__.cc: restore locale after\n\tGraphicsMagick initialisation.\n\n2010-07-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* toplev.cc (octave_call_stack::do_backtrace): Use static\n\toctave_fields struct.\n\t(octave_call_stack::empty_backtrace): New static method.\n\t* toplev.h: Declare it.\n\t* error.cc (Vlast_error_stack, initialize_last_error_stack,\n\tFrethrow): Use octave_map or octave_scalar_map where applicable.\n\n2010-07-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-mat.cc (tm_row_const::tm_row_const_rep::all_1x1,\n\ttm_cont::all_1x1): New member fields.\n\t(tm_row_const::tm_row_const_rep::init, tm_const::init):\n\tHandle them here.\n\t(tm_row_const::all_1x1_p, tm_const::all_1x1_p): New methods.\n\t(single_type_concat<MAP> (octave_map&, ...)): New template\n\toverload.\n\t(do_single_type_concat<octave_map>): New template specialization.\n\t(tree_matrix::rvalue1): Specialize for cell and struct classes.\n\t* oct-map.cc (octave_map::do_cat (..., const octave_map *, ...)):\n\tAssign result dimensions.\n\n2010-07-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.cc (octave_map::cat (..., const octave_scalar_map *)):\n\tHandle special dims (-1, -2).\n\t* data.cc (do_single_type_concat_map): Don't handle them here.\n\n2010-07-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* syscalls.cc (mk_stat_map, Funame): Use octave_scalar_map.\n\n2010-07-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.h (octave_scalar_map::assign (const std::string&, const\n\toctave_value&), octave_map::assign (const std::string&, const Cell&)):\n\tBackward-compatible aliases for setfield.\n\n2010-07-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.cc (octave_fields::equal_up_to_order (const octave_fields&,\n\toctave_idx_type *)): New overload.\n\t(octave_fields::equal_up_to_order (const octave_fields&,\n\tArray<octave_idx_type>&)): Use it here.\n\t(octave_map::fast_elem_insert,\n\toctave_map::fast_elem_extract): New methods.\n\t* oct-map.h: Update decls.\n\t* ov-struct.cc (octave_struct::fast_elem_extract,\n\toctave_struct::fast_elem_insert,\n\toctave_scalar_struct::fast_elem_insert_self): New methods.\n\t* ov-struct.h: Update decls.\n\n2010-06-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (single_type_concat): Optimize all scalars case where\n\tapplicable.\n\t(single_type_concat_map, do_single_type_concat_map): New funcs.\n\t* pt-mat.cc (get_concat_class): Handle cell and struct concats.\n\n\n2010-06-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fnum2cell, do_num2cell): Optimize cells\n\tand structs.\n\n2010-06-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-struct.h (octave_scalar_struct::resize, octave_struct::resize):\n\tDon't ignore fill argument.\n\n2010-06-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.h (octave_map::octave_map (const dim_vector&, const\n\toctave_fields&)): New internal ctor.\n\n\t* oct-map.cc (octave_map::assign): Handle no fields case.\n\n2010-06-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-struct.cc (Fcell2struct): Rewrite.\n\n2010-06-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-range.cc (octave_range::save_ascii): Save length rather than\n\tlimit when inc is zero. Adjust comment.\n\t(octave_range::save_binary, octave_range::save_hdf5): Ditto.\n\t(octave_range::load_ascii): Assume limit is length when increment is\n\tzero.\n\t(octave_range::load_binary, octave_range::load_hdf5): Ditto.\n\n\n2010-06-25  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (reset_default_properties): New static function.\n\t(root_figure::reset_default_properties,\n\tfigure::reset_default_properties, axes::reset_default_properties):\n\tUse it to avoid duplicated code.\n\n2010-06-24  Rik  <octave@nomad.inbox5.com>\n\n\t* octave.cc: Add [FILE] to octave usage string (bug #30258).\n\n2010-06-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.h (octave_map, octave_scalar_map): New classes.\n\t* oct-map.cc (octave_map, octave_scalar_map): Implement them.\n\t(Octave_map::Octave_map (const octave_map&)): New ctor.\n\t* ov-struct.h (octave_struct): Use octave_map for storage.\n\t(octave_scalar_struct): New class.\n\t* ov-struct.cc: Update implementations.\n\t* ov-base.h (octave_base_value::old_map_value): New method.\n\t(octave_base_value::map_value): Return octave_map.\n\t(octave_base_value::scalar_map_value): New method.\n\t* ov-base.cc (octave_base_value::old_map_value,\n\toctave_base_value::map_value, octave_base_value::scalar_map_value):\n\tAdd default implementations.\n\t* ov-class.h (octave_class::old_map_value): New override.\n\t* ov-class.cc: Use old_map_value for efficiency.\n\n2010-06-23  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (void root_figure::reset_default_properties (void),\n\tvoid figure::reset_default_properties (void),\n\tvoid figure::reset_default_properties (void),\n\tFreset): New functions.\n\t* graphics.h.in (void graphics_object:reset_default_properies (void),\n\tvirtual void base_graphics_object:reset_default_properies (void)):\n\tNew functions.\n\t(void root_figure::reset_default_properties (void),\n\tvoid figure::reset_default_properties (void),\n\tvoid figure::reset_default_properties (void)): Declarations.\n\t(std::string color_property::values_as_string (void) const,\n\tCell color_property::values_as_cell (void) const): New functions.\n\n2010-06-21  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/dlmread.cc: Fix spreadsheet style range option.\n\t(bug #30183).\n\n2010-06-21  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (std::string radio_values:values_as_string (void)\n\tconst, Cell radio_values:values_as_cell (void) const): New functions.\n\t(void graphics_object::set (const octave_value_list&)): Throw error\n\twith no arguments.\n\t(std::string base_graphics_object::values_as_string (void),\n\tOctave_map base_graphics_object::values_as_struct (void)): New\n\tfunctions.\n\t(Fset): Allow single handle as an argument and return the radio\n\tvalues.\n\t* graphics.h.in (virtual bool base_property::is_radio (void) const,\n\tvirtual std::string base_property::values_as_string (void) const,\n\tvirtual Cell base_property::values_as_cell (void) const):\n\tNew function.\n\t(std::string radio_values::values_as_string (void) const,\n\tCell radio_values::values_as_cell (void) const): Declaration.\n\t(octave_idx_type radio_values::nelem (void) const): New function.\n\t(std::string radio_property::values_as_string (void) const,\n\tCell radio_property::values_as_cell (void) const,\n\tbool radio_property::is_radio (void) const): New functions.\n\t(bool property::is_radio (void) const,\n\tstd::string raproperty::values_as_string (void) const,\n\tCell property::values_as_cell (void) const): New functions.\n\t(std::string base_graphics_object::values_as_string (void),\n\tOctave_map base_graphics_object::values_as_struct (void)): Declaration.\n\t(std::string graphics_object::values_as_string (void),\n\tOctave_map graphics_object::values_as_struct (void)): New functions.\n\n2010-06-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (single_type_concat): Assume matrix arguments start from\n\tindex zero.\n\t(do_cat): Make dim a separate argument. Special-case support for dim =\n\t-1 and dim = -2\n\n2010-06-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-mat.cc (tm_row_const::eval_error): Make a static func.\n\t(tm_row_const::do_init_element): Simplify using dim_vector::hvcat.\n\t(tm_const::init): Ditto.\n\t(single_type_concat): Special-case empty results. Skip or use 0x0 for\n\tempty arrays otherwise.\n\t(tree_matrix::rvalue1): Skip empty arrays in the fallback branch.\n\n2010-06-16  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc, DLD-FUNCTIONS/dot.cc,\n\tDLD-FUNCTIONS/gammainc.cc, DLD-FUNCTIONS/lookup.cc,\n\tDLD-FUNCTIONS/lu.cc, DLD-FUNCTIONS/luinc.cc, DLD-FUNCTIONS/onCleanup.cc,\n\tDLD-FUNCTIONS/sparse.cc, DLD-FUNCTIONS/spparms.cc, DLD-FUNCTIONS/svd.cc,\n\tdata.cc, dirfns.cc, graphics.cc, mappers.cc, ov-cell.cc, ov-range.cc:\n\tPeriodic grammar check of documentation to ensure a common format.\n\n2010-06-11  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/rand.cc : Add \"reset\" flag to reset the random\n\tgenerators from the entropy pool.\n\n\t* genprops.awk : Don't special case the color_property in the\n\tfactory default methods.\n\n2010-06-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fsort): Fix invalid tests.\n\n2010-06-15  Rik  <octave@nomad.inbox5.com>\n\n\t* pr-output.cc: Second try at removing extra newlines from NDArrays\n\n2010-06-14  Rik  <octave@nomad.inbox5.com>\n\n\t* pr-output.cc: Remove extra newlines when displaying multi-dimensional\n\tarrays (bug #30029).\n\n2010-06-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fsort, Fnth_element): Fix behavior when trailing singleton\n\tdim is specified.\n\n2010-06-12  Ben Abbott  <bpabbott@mac.com>\n\n\t* DLD-FUNCTIONS/gammainc.cc: Fix doc-string typo.\n\n2010-06-11  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/gammainc.cc: Implement complementary incomplete\n\tgamma function.\n\n2010-06-10  Ben Abbott  <bpabbott@mac.com>\n\n\t* data.cc: Fix test for concatentating empty nd-arrays.\n\n2010-06-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fvec): New DEFUN.\n\n2010-06-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Freshape): Use octave_idx_type rather than int.\n\tDon't use intermediate Array when sizes are given as separate\n\targuments. Simplify computing unknown dimension.\n\n2010-06-09  David Grundberg  <individ@acc.umu.se>\n\n\t* ov-struct.cc (Fisfield): Accept cell array as name argument.\n\n2010-06-08  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/bsxfun.cc, DLD-FUNCTIONS/cellfun.cc,\n\tDLD-FUNCTIONS/det.cc, DLD-FUNCTIONS/lookup.cc, DLD-FUNCTIONS/lu.cc,\n\tDLD-FUNCTIONS/rand.cc, DLD-FUNCTIONS/svd.cc, DLD-FUNCTIONS/tril.cc,\n\tdata.cc, ov.cc: Improve documentation string.\n\n2010-06-06  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* data.cc (Frem, Fmod): Specify template arguments of binmap\n\texplicitely.\n\n2010-06-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/strfind.cc (Fqs_replace): Allow overlapped matches.\n\t(Fstrrep): Support \"overlaps\" option.\n\t(Fstrfind): Ditto.\n\n2010-05-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::fast_elem_extract,\n\toctave_value::fast_elem_insert): New methods.\n\t* ov-base.cc (octave_base_value::fast_elem_extract,\n\toctave_base_value::fast_elem_insert,\n\toctave_base_value::fast_elem_insert_self): New methods.\n\t* ov-base.h: Declare them.\n\t* ov-base-mat.cc (octave_base_matrix::fast_elem_extract,\n\toctave_base_matrix::fast_elem_insert): New overrides.\n\t* ov-base-mat.h: Declare them.\n\t* ov-base-scalar.cc (octave_base_scalar::fast_elem_extract,\n\toctave_base_scalar::fast_elem_insert_self): New overrides.\n\t* ov-base-scalar.h: Declare them.\n\t(octave_base_scalar::scalar_ref): New method.\n\t* ov-scalar.cc (octave_scalar::fast_elem_insert_self): New override.\n\t* ov-scalar.h: Declare it.\n\t* ov-float.cc (octave_float_scalar::fast_elem_insert_self): New override.\n\t* ov-float.h: Declare it.\n\t* ov-cell.cc (octave_base_matrix<Cell>::fast_elem_extract,\n\toctave_base_matrix<Cell>::fast_elem_insert): New specializations.\n\t* DLD-FUNCTIONS/cellfun.cc (scalar_col_helper, scalar_col_helper_def,\n\tscalar_col_helper_nda, make_col_helper, can_extract): Remove.\n\t(Fcellfun): Use the new fast_elem_insert method.\n\n2010-05-10  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/eigs.cc: Improve documentation string.\n\tUse ~ notation instead of dummy variables for unused return arguments.\n\n2010-05-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-mat.h (octave_base_matrix::matrix_ref (void) const): New\n\toverload.\n\n2010-05-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-obj.h (octave_value_list::slice): Optionally include tags in\n\tslicing.\n\t* oct-parse.yy (get_feval_args): Simplify.\n\t* pt-idx.cc (make_value_list): Use octave_idx_type instead of int.\n\n2010-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::length): Simplify.\n\n2010-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-mat.h (octave_base_matrix::ndims): New override.\n\t* ov-base-scalar.h (octave_base_scalar::numel,\n\toctave_base_scalar::ndims): New overrides.\n\n2010-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.cc (octave_base_value::ndims): Remove fallback\n\timplementation (makes no sense).\n\t* ov-base.h (octave_base_value::ndims): Use a simplistic fallback\n\there.\n\n2010-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (octave_base_value::rows, octave_base_value::columns):\n\tUse const where appropriate, don't test for impossible condition.\n\n2010-05-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Cell.h (Cell::index, Cell::assign, Cell::delete_elements):\n\tMake signatures consistent with inherited overloads. Import inherited\n\toverloads to class's scope.\n\t* oct-map.cc (Octave_map::maybe_delete_elements): Simplify.\n\n2010-05-20  John W. Eaton  <jwe@octave.org>\n\n\t* utils.cc (Ffile_in_path, Ffile_in_loadpath): If no file is\n\tfound, return empty character string instead of empty matrix.\n\n2010-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/onCleanup.cc (octave_oncleanup::load_ascii,\n\toctave_oncleanup::load_binary, octave_oncleanup::load_hdf5,\n\toctave_oncleanup::save_ascii, octave_oncleanup::save_binary,\n\toctave_oncleanup::save_hdf5): Comment out unused params.\n\n2010-05-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* defun-int.h (octave_auto_shlib): Make members public.\n\t* DLD-FUNCTIONS/onCleanup.cc: New source.\n\t* DLD-FUNCTIONS/module-files: Add it here.\n\n2010-05-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* variables.cc (set_internal_variable (int&, ..., const char **)):\n\tDrop nchoices argument. Instead determine nchoices by trailing NULL.\n\t* variables.h (SET_INTERNAL_VARIABLE_CHOICES): Update.\n\t* DLD-FUNCTIONS/svd.cc (Fsvd_driver): Update.\n\n2010-05-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* variables.cc (set_internal_variable (int&, ..., const char **, int)):\n\tNew overload.\n\t* variables.h: Declare it.\n\t(SET_INTERNAL_VARIABLE_CHOICES): New macro.\n\t* DLD-FUNCTIONS/svd.cc (Fsvd_driver): Use it here.\n\n2010-05-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-usr-fcn.h (octave_user_function::curr_unwind_protect_frame): New\n\tfield.\n\t(octave_user_function::local_protect): New template method.\n\t* ov-usr-fcn.cc (octave_user_function::octave_user_function):\n\tInitialize it here.\n\t(octave_user_function::do_multi_index_op): Set and restore it here.\n\t* variables.cc (wants_local_change, try_local_protect): New helper\n\tfuncs.\n\t(set_internal_variable): Call them in all overloads.\n\n2010-05-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.cc (symtab::do_mark_global, symtab::do_mark_hidden): Force\n\tnon-existing symbol to be created.\n\n2010-05-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xdiv.cc (solve_singularity_warning): Use ID for the warning.\n\n2010-05-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/sqrtm.cc (sqrtm_utri_inplace): Use an ID for the\n\twarning.\n\n2010-05-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* load-save.cc (install_loaded_variable): Pre-extract symbol record\n\treference to do all operations.\n\n2010-05-11  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat5.cc (save_mat5_element_length): Correct element length for\n\tsparse elements with NZMAX=1 or NC=0.\n\t(save_mat5_binary_element): Save the NZMAX elements of the RIDX\n\tsparse index.\n\n2010-05-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-lazy-idx.cc (octave_lazy_index::save_binary): Fix arguments to\n\tsave_binary_data.\n\n2010-05-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/sqrtm.cc (do_sqrtm): Mark the result as triangular\n\twhere applicable.\n\n2010-05-10  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/qr.cc: Split qrdelete test into high precision test\n\twhen QRUPDATE is present and low precision when it is not.\n\n2010-05-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/schur.cc (Fschur): Mark triangular matrices on output.\n\n2010-05-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-range.cc (octave_range::index_vector): Optimize order of\n\tconditions.\n\n2010-05-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::do_non_const_unary_op): Always return *this as\n\toctave_value&. Remove unused overload.\n\t* oct-lvalue.cc (octave_lvalue::do_unary_op): Simplify.\n\t* pt-unop.cc (tree_prefix_expression::rvalue1,\n\ttree_postfix_expression::rvalue1): Remove dummy rvalue1 calls.\n\n2010-05-07  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* ov-base.h (Vsparse_auto_mutate): Add OCTINTERP_API tag.\n\n2010-05-07  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (maximum_braindamage): Set value of internal\n\tvariable Vallow_noninteger_range_as_index to true instead of\n\tsetting Octave:allow-noninteger-ranges-as-indices warning state.\n\t* ov-range.cc (Fallow_noninteger_range_as_index): New function.\n\t(Vallow_noninteger_range_as_index): New variable.\n\t(octave_range::index_vector): Only allow non-integer range as\n\tindex if Vallow_noninteger_range_as_index is true.\n\t(octave_range::bool_array_value): Move definition here from ov-range.h.\n\t* ov-range.h (Vallow_noninteger_range_as_index): Provide decl.\n\t* utils.cc (reset_warning_state): Delete.\n\t(Fisindex): Temporarily set Vallow_noninteger_range_as_index\n\tinstead of changing warning state for\n\tOctave:allow-noninteger-ranges-as-indices to \"error\".\n\n2010-05-06  John W. Eaton  <jwe@octave.org>\n\n\t* xgl2ps.c: Don't compile gl2ps.c unless we have OpenGL.\n\tFrom Petr Mikulik <mikulik>.\n\n2010-05-06  John W. Eaton  <jwe@octave.org>\n\n\t* ov-range.cc (octave_range::index_vector):\n\tImprove warning/error message.\n\n2010-05-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/sqrtm.cc (sqrtm_utri_inplace, do_sqrtm): New helper\n\tfunctions.\n\t(Fsqrtm): Rewrite.\n\n2010-05-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/schur.cc (Fschur): Recognize \"complex\" option for\n\tMatlab compatibility. Simplify argument handling and improve error\n\tmessages.\n\n2010-05-05  John W. Eaton  <jwe@octave.org>\n\n\t* utils.cc (reset_warning_state): New function.\n\t(Fisindex): Temporarily set warning state for\n\tOctave:allow-noninteger-ranges-as-indices to \"error\".\n\t* error.cc (set_warning_state): New function.\n\t(initialize_default_warning_state): Set default warning state\n\tfor Octave:allow-noninteger-ranges-as-indices to \"error\".\n\t* error.h (set_warning_state): Provide decl.\n\t* octave.cc (maximum_braindamage): Set warning state for\n\tOctave:allow-noninteger-ranges-as-indices to \"on\".\n\t* ov-range.cc (octave_range::index_vector): Warn if range\n\tcontains non-integer values.\n\n2010-05-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/svd.cc (driver): New static var.\n\t(Fsvd): Use it to select a driver.\n\t(Fsvd_driver): New DEFUN.\n\n2010-05-02  Rik  <octave@nomad.inbox5.com>\n\n\t* ov-cell.cc: Wrap documentation line to prevent overfull hbox\n\tLaTex warning\n\n2010-05-01  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.cc, graphics.h.in: Remove line object properties ldata,\n\tudata, xldata, xudata.\n\n2010-04-30  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::set_axes_currentpoint):\n\tcheck for valid object before manipulating it\n\n2010-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (string_array_property::string_array_property):\n\tIndex string_vector with [], not ().\n\t(string_array_property::string_value): Likewise.\n\t(string_array_property::do_set): Likewise.\n\tAvoid indexing past last element of string_vector object.\n\tFixes bug #29695.\n\n2010-04-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cs-list.cc (octave_cs_list::subsref): New methods. Just gripe.\n\t* ov-cs-list.h: Declare them.\n\n2010-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr-fcn.cc (octave_user_script::do_multi_index_op):\n\tCorrect spelling of max_recursion_depth in error message.\n\t(octave_usr_fcn::do_multi_index_op): Ditto.\n\t* pt-eval.h, pt-eval.cc (Vmax_recursion_depth): Move definition\n\there from ov-usr-fcn.cc.  Now extern.\n\t(Fmax_recursion_depth): Move definition here from ov-usr-fcn.cc.\n\t* oct-parse.yy (source_file): Limit recursive calls on a\n\tper-file basis.\n\tAddresses bug #29491.\n\n2010-04-25  David Bateman  <dbateman@free.fr>\n\n\t* oct-parse.yy (octave_function * load_fcn_from_file\n\t(const std::string&, const std::string&, const std::string&)\n\t(const std::string&, bool)): When loading a mex-file attempt\n\tto load the m-file first to get the help string.\n\n2010-04-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.h.in: Have figure color property support a radio value,\n\t'none'.\n\n2010-04-24  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (void axes::properties::set_defaults\n\t(base_graphics_object&, const std::string&)): Make the default\n\taxes color \"none\".\n\n2010-04-24  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* Makefile.am: change GRAPHICS_CPPFLAGS to GRAPHICS_CFLAGS since\n\tthe former does not exist and the latter serves the same purpose\n\n2010-04-23  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Clarify compilation note about defaults.h\n\n2010-04-23  Rik  <octave@nomad.inbox5.com>\n\n\t* symtab.h: Clear global variables when 'clear -all' called\n\n2010-04-23  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc\t(OpenGL_fltk::OpenGL_fltk):\n\tExplicitly initizlize all data members in the order they are declared.\n\n2010-04-23  John W. Eaton  <jwe@octave.org>\n\n\t* txt-eng-ft.cc (ft_render::visit): Declare loop counter size_t,\n\tnot int.\n\n\t* graphics.h.in (graphics_xform::untransform):  Likewise.\n\t* graphics.cc (text::properties::update_text_extent): Likewise.\n\t* DLD-FUNCTIONS/fltk_backend.cc\t(plot_window::set_axes_currentpoint):\n\tAvoid GCC shadow variable warning.\n\n\t* DLD-FUNCTIONS (plot_window::plot_window): Explicitly\n\tinitialize all data members in the order they are declared.\n\n2010-04-23  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gcd.cc (Fgcd): Use two-argument dim_vector constructor.\n\n\t* ov-str-mat.cc (octave_char_matrix_str::do_index_op_internal):\n\tExplicitly create idx_vec with column orientation.\n\n\t* oct-obj.cc (octave_value_list::octave_value_list):\n\tExplicitly resize data to be row vector.\n\n2010-04-23  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/regexp.cc.: Eliminate compile warning.\n\twarning: suggest explicit braces to avoid ambiguous 'else'.\n\n2010-04-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-scalar.h (octave_base_scalar::reshape,\n\toctave_base_scalar::permute): Remove implementations.\n\t* ov-base-scalar.cc (octave_base_scalar::reshape,\n\toctave_base_scalar::permute): Provide correct implementations here.\n\n2010-04-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-bool.h (octave_bool::empty_clone): Correctly return an empty\n\tmatrix.\n\t* ov-float.h (octave_float::empty_clone): Ditto.\n\t* ov-base-mat.h (octave_base_matrix::clone,\n\toctave_base_matrix::empty_clone): Remove.\n\t* ov-base-scalar.h (octave_base_scalar::clone,\n\toctave_base_scalar::empty_clone): Remove.\n\t* ov-base-sparse.h (octave_base_sparse::clone,\n\toctave_base_sparse::empty_clone): Remove.\n\t* ov-base.h (octave_base_value::empty_clone): Remove implementation.\n\t* ov-base.cc (octave_base_value::empty_clone): Implement here.\n\tFall back to resize() for empty_clone().\n\t* ov.cc (octave_value::assign): Correct behavior in the indexed\n\tOP= case.  Use better error messages. Always return non-const\n\treference, like any assignment.\n\t* ov.h: Update decls.\n\t* oct-lvalue.cc (octave_lvalue::assign): Simplify.\n\n2010-04-22  Rik  <octave@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/hess.cc.: return correct Hessenberg matrix when\n\tcalled with only one output argument.\n\n2010-04-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (do_hypot): New helper function. Move bulk code from Fhypot\n\there.\n\t(Fhypot): Account for >2 args by folding do_hypot several times.\n\n2010-04-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-mat.cc (single_type_concat): New overloads. Make TYPE an explicit\n\ttemplate parameter. Try to forward some cases to Array<T>::cat and\n\tSparse<T>::cat.\n\t(do_single_type_concat, do_single_type_concat_no_mutate): Don't\n\tallocate the array here, let single_type_concat do it.\n\n2010-04-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (single_type_concat, do_single_type_concat): Rewrite using\n\tnew liboctave facilities.\n\t(do_cat): Don't compute result dims if the case can be forwarded to\n\tliboctave.\n\n2010-04-13  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (void text::properties::update_text_extent (void)):\n\tDon't call text_renderer.set_font if HAVE_FONTCONFIG is not set.\n\n2010-04-13  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp_list): Handle repeated matches\n\tin the list of matches returned by pcre.\n\n2010-04-13  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::set_currentpoint,\n\t(plot_window::set_axes_currentpoint, plot_window::key2shift,\n\t(plot_window::key2ascii, plot_window::modifier2cell): New helper\n\tfunctions for keypress and mousebutton callbacks.\n\t(plot_window::handle): implement keypress and mousebutton callbacks.\n\n\t* graphics.h.in (callback_property::is_defined): New conveniance\n\tfunction.  Rename figure.current_point to figure.currentpoint.\n\n2010-04-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/sparse.cc (Fspalloc): New DEFUN.\n\t* ov-base.cc (octave_base_value::nzmax): Return numel by default.\n\n2010-04-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-sparse.cc (octave_base_sparse::assign): Rewrite.\n\t* ov-cx-sparse.cc (octave_sparse_complex_matrix::assign\n\t(const octave_value_list& idx, const SparseMatrix& rhs)): Remove.\n\t* ov-cx-sparse.h: Remove decl.\n\n2010-04-10  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.h.in: Fix nextplot property values. Add \"new\" to\n\tlist for axes nextplot values. Change \"replace_children\" to\n\t\"replacechildren\" for both axes and figures.\n\n2010-04-09  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp_list): Properly ignore\n\tzero-length matches in named tokens.\n\n2010-04-09  John W. Eaton  <jwe@octave.org>\n\n\t* ov-ch-mat.h (octave_char_matrix::mex_get_data): New function.\n\tAddresses bug #29475.\n\n2010-04-09  Judd Storrs  <jstorrs@gmail.com>\n\n\t* utils.cc (isvarname): Keywords are not valid variable names.\n\n2010-04-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* help.cc (make_name_list): Don't insert global and top-level scope\n\tvariables. Always insert current scope.\n\n2010-04-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (SINGLE_TYPE_CONCAT, DO_SINGLE_TYPE_CONCAT): Replace by\n\ttemplates.\n\t(single_type_concat, do_single_type_concat): New static temvplate\n\tfuncs. Correctly skip 0x0 matrices.\n\t(Fcat): Call them here. Add tests.\n\n2010-04-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-parse.yy (feval): Use do_multi_index_op on handles.\n\t(get_feval_args): Use array slicing functions rather than loops.\n\n2010-04-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-sparse.cc (octave_base_sparse::delete_elements): Rewrite.\n\n2010-04-02  Judd Storrs  <jstorrs@gmail.com>\n\n\t* octave.cc (intern_argv): Truncate argv when script files are\n\trun without command line parameters. Resolves bug #29423.\n\n2010-03-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/sparse.cc (Fsparse): Rewrite.\n\n2010-03-28  David Grundberg  <davidg@cs.umu.se>\n\n\t* DLD-FUNCTIONS/convhulln.cc [HAVE_QHULL]: Neither include\n\tqhull/qhull_a.h nor run tests if unless we HAVE_QHULL.\n\n2010-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* variables.cc (maybe_missing_function_hook): Temporarily clear before\n\texecuting the hook to avoid recursive calls.\n\n2010-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* gl2ps-renderer.cc (glps_renderer::draw): Tag call to fclose\n\twith gnulib::.\n\n2010-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy, oct-fstrm.cc, mex.cc, input.cc,\n\tc-file-ptr-stream.cc: Revert changes from 2010-03-24.\n\n2010-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* kron.cc (Fkron): Completely rewrite.\n\n2010-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* version.h.in (OCTAVE_BUGS_STATEMENT): Point to\n\thttp://www.octave.org/bugs.html, not the mailing list.\n\n2010-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/config-module.awk: Emit additions to EXTRA_DIST.\n\n2010-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am ($(srcdir)/DLD-FUNCTIONS/module.mk):\n\tRemove doubled // from file name in rule.\n\n2010-03-24  David Grundberg  <davidg@cs.umu.se>\n\n\t* oct-parse.yy: Include gnulib stdlib.h/stdio.h instead of C++\n\theaders.\n\t* oct-fstrm.cc: Include gnulib stdlib.h/string.h instead of C++\n\theaders.\n\t* mex.cc: Include gnulib stdlib.h instead of C++ headers.\n\t* input.cc: Include gnulib stdio.h instead of C++ headers.\n\t* c-file-ptr-stream.cc: Include gnulib stdio.h.\n\n2010-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::add_to_fcn_map): Style fixes.\n\n2010-03-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* variables.cc (maybe_missing_function_hook): Don't call hook if\n\terrors are being handled.\n\n2010-03-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* variables.cc (Fmissing_function_hook): New pseudo-variable.\n\t(Vmissing_function_hook): New static var.\n\t(maybe_missing_function_hook): New function.\n\t* variables.h: Declare it.\n\t* pt-id.cc (tree_identifier::eval_undefined_error): Call it here.\n\t* oct-parse.yy (feval (const std::string&, ...)): Also here.\n\n2010-03-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Frem, Fmod): New DEFUNs.\n\t(Ffmod): Remove. Make an alias of Frem.\n\n2010-03-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (map_d_m, map_m_d, map_m_m, map_f_fm, map_fm_f, map_fm_fm,\n\tmap_d_s, map_s_d, map_s_s): Remove.\n\t(Fatan2, Fhypot, Ffmod): Rewrite using binmap.\n\n2010-03-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Fix the parsing of string\n\tfunction arguments.\n\n2010-03-20  John W. Eaton  <jwe@octave.org>\n\n\t* lex.ll: Don't undefine GNULIB_NAMESPACE.  Define fprintf,\n\tfwrite, malloc, and realloc and GNULIB_NAMESPACE::fprintf, ...\n\t* oct-parse.yy: Likewise.  Always include cstdlib.\n\n2010-03-16  John W. Eaton  <jwe@octave.org>\n\n\t* ls-oct-ascii.cc (save_ascii_data): Insert extra newline after\n\tdata is written to file.  From Brett Stewart <btstewart@wisc.edu>.\n\n2010-03-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (unary_mapper_t::umap_cbrt): New enum member.\n\t* ov.h (octave_value::cbrt): New forwarder method.\n\t* ov-scalar.cc (octave_scalar::map): Handle cbrt.\n\t* ov-float.cc (octave_float_scalar::map): Ditto.\n\t* ov-re-mat.cc (octave_matrix::map): Ditto.\n\t* ov-flt-re-mat.cc (octave_float_matrix::map): Ditto.\n\t* ov-re-sparse.cc (octave_sparse_matrix::map): Ditto.\n\n2010-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy, lex.ll: Undefine GNULIB_NAMESPACE immediately\n\tafter including <config.h>.\n\n\t* toplev.cc (wait_for_input): Tag call to select with gnulib::.\n\n\t* sighandlers.h (BLOCK_SIGNAL): Tag calls to sigemptyset,\n\tsigaddset, and sigprocmask with gnulib::.\n\t(UNBLOCK_CHILD): Tag call to sigprocmask with gnulib::.\n\t* sighandlers.cc (octave_set_signal_handler): Tag calls to\n\tsigemptyset with gnulib::.\n\t(octave_set_signal_handler): Tag call to sigaction with gnulib::.\n\n\t* oct-procbuf.cc (octave_procbuf::open): Tag calls to close, dup2,\n\tand fclose with gnulib::.\n\t(octave_procbuf::close): Tag call to fclose with gnulib::.\n\n\t* oct-hist.cc (unlink_cleanup): Tag call to unlink with gnulib::.\n\n\t* oct-fstrm.cc (octave_fstream::octave_fstream): Tag call to\n\tstrerror with gnulib::.\n\n\t* mex.cc (mex::malloc_unmarked, mex::realloc, mxArray::malloc,\n\tmxMalloc, mxRealloc): Tag call to malloc with gnulib::.\n\n\t* input.cc (gnu_readline): Tag call to fputs with gnulib::.\n\n\t* file-io.cc (cleanup_tmp_files): Tag call to unlink with gnulib::.\n\t(do_stream_open, Ftmpfile, Fmkstemp): Tag call to strerror with\n\tgnulib::.\n\n\t* dirfns.cc (octave_change_to_directory): Tag call to strerror\n\twith gnulib::.\n\n\t* c-file-ptr-stream.cc (c_file_ptr_buf::overflow): Tag calls to\n\tfputc with gnulib::.\n\t(c_file_ptr_buf::xsputn): Tag call to fwrite with gnulib::.\n\t(c_file_ptr_buf::file_close): Move here from\n\tc-file-ptr-stream.h.  Tag call to fclose with gnulib::.\n\n2010-03-12  Ben Abbott  <bpabbott@mac.com>\n\n\t* /DLD-FUNCTIONS/chol.cc: Increase tolerance for single precision test.\n\n2010-03-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Fix deprecated array constructor.\n\n2010-03-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-intx.h\n\t(OCTAVE_INT_NDARRAY_T::convert_gripe): Remove method.\n\t(OCTAVE_INT_NDARRAY_T): Remove all uses.\n\t(OCTAVE_INT_T::convert_gripe): Remove method.\n\t(OCTAVE_INT_T): Remove all uses.\n\t* ov.cc (convert_to_int_array, convert_to_octave_idx_type_array):\n\tRemove int conversion warnings.\n\t* data.cc (NATIVE_REDUCTION_1): Ditto.\n\n\t* OPERATORS/op-intx.h: Remove integer warning stubs.\n\t* OPERATORS/opt-int-conv.cc: Ditto.\n\n\t* gripes.cc (gripe_truncated_conversion,\n\tgripe_binop_integer_math_truncated,\n\tgripe_native_integer_math_truncated,\n\tgripe_unop_integer_math_truncated, gripe_non_integer_conversion,\n\tgripe_nan_conversion): Remove.\n\t* gripes.h: Remove decls.\n\t* error.cc (initialize_default_warning_state): Don't initialize\n\tremoved warnings.\n\n2010-03-07  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* gl-render.cc (draw_figure): disable depth test on the 3rd pass.\n\t(draw_text): use get_data_position to get text position.\n\t* graphics.h.in (graphics_xform): New zlim field.\n\t(graphics_xform::untransform(double,double,bool)): New method.\n\t(axes::properties::get_transform): Provide zlim data to graphics_xform\n\tconstructor.\n\t(text::properties::string, text::properties::units,\n\ttext::properties::rotation, text::properties::fontname,\n\ttext::properties::fontangle, text::properties::fontsize,\n\ttext::properties::fontweight, text::properties::interpreter): Add 'u'\n\tmodified.\n\t(text::properties::extent): New property.\n\t(text::properties::get_data_position): New method.\n\t(text::properties::update_position): Use it.\n\t(text::properties::update_text_extent,\n\ttext::properties::update_string, text::properties::update_rotation,\n\ttext::properties::update_fontname, text::properties::update_fontsize,\n\ttext::properties::update_fontangle,\n\ttext::properties::update_fontweight,\n\ttext::properties::update_interpreter, text::properties::update_units):\n\tNew updaters.\n\t* graphics.cc (convert_position): Support single point.\n\t(convert_text_position): New helper function.\n\t(text::properties::get_data_position, text::properties::get_extent,\n\ttext::properties::update_text_extent, text::properties::update_units):\n\tNew methods.\n\t* txt-eng-ft.h (ft_render::get_extent, ft_render::rotation_to_mode):\n\tNew methods.\n\t* txt-eng-ft.cc (ft_render::get_extent, ft_render::rotation_to_mode):\n\tDitto.\n\n2010-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (do_accumdim_sum): New helper function.\n\t(F__accumdim_sum__): New DEFUN.\n\n2010-03-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (unary_mapper_t::umap_erfcx): New enum member.\n\t* ov.h (octave_value::erfcx): New forwarder method.\n\t* ov-scalar.cc (octave_scalar::map): Handle erfcx.\n\t* ov-float.cc (octave_float_scalar::map): Ditto.\n\t* ov-re-mat.cc (octave_matrix::map): Ditto.\n\t* ov-flt-re-mat.cc (octave_float_matrix::map): Ditto.\n\n2010-03-03  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (F__magick_read__):\n\tCall Magick::InitializeMagick.\n\n2010-03-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/__convn__.cc: Remove.\n\t* DLD-FUNCTIONS/module-files: Update.\n\n2010-03-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/conv.cc (Fconv2): Rewrite using convn from liboctave.\n\t(Fconvn): New DEFUN.\n\n2010-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* (str2double1): Pass argument as const reference and make\n\texplicit copy instead of passing by value.\n\n2010-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/str2double.cc (set_component): Use autoconf\n\tmacros instead of checking predefined compiler macros.\n\t(str2double1): Pass val to set_component, not c.\n\n2010-03-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/str2double.cc (set_component): New helper func.\n\t(str2double1): Use it here.\n\n2010-03-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/str2double.cc (str2double1): Use ISO-conformant code\n\tfor setting the real and imaginary part.\n\n2010-02-28  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (curl_handle::init): Don't set\n\tCURLOPT_USERPWD if userpwd is empty.\n\n2010-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am ($(srcdir)/DLD-FUNCTIONS/module.mk): New target.\n\n\t* DLD-FUNCTIONS/config-module.sh: Accept top_srcdir argument.\n\tWork from build directory too, not just source tree.\n\n2010-02-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-typeinfo.h (octave_value_typeinfo::octave_value_typeinfo):\n\tAdd missing initializers.\n\n2010-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/conv2.cc (conv2 (const MArray<T>&, const MArray<T>&,\n\tShape)): Args are now const.  Move invariant expressions outside\n\tof loops.  Use pointers instead of Array class indexing methods.\n\t(conv2 (const MArray<T>&, const MArray<T>&, const MArray<T>&, Shape)):\n\tDitto.\n\n2010-02-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-mat.cc (do_index_op): Use checkelem for scalar indices.\n\tSimplify.\n\n2010-02-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc: Update.\n\t* ov-base-diag.cc: Update.\n\n2010-02-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/str2double.cc (single_number): New helper func.\n\t(extract_number): Call it instead of >> to get Inf's and NaN's\n\tcorrectly.\n\n2010-02-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/str2double.cc: New source.\n\n2010-02-19  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/qr.cc: Increase tolerance for test.\n\n2010-02-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* TEMPLATE-INST/Array-tc.cc: Remove Array2 instantiation.\n\t* DLD-FUNCTIONS/besselj.cc: Use Array instead of Array2.\n\t* DLD-FUNCTIONS/tril.cc: Ditto.\n\t* data.cc: Ditto.\n\t* ov-typeinfo.cc: Ditto.\n\t* ov-typeinfo.h: Ditto.\n\t* pr-output.cc: Ditto.\n\n2010-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-bool-mat.h (octave_bool_matrix::octave_bool_matrix (const\n\tArray<bool>&)): New ctor.\n\t* ov-ch-mat.h (octave_char_matrix::octave_char_matrix (const\n\tArray<char>&)): New ctor.\n\t* ov-str-mat.h (octave_char_matrix_str::octave_char_matrix_str (const\n\tArray<char>&)): New ctor.\n\t(octave_char_matrix_sq_str::octave_char_matrix_sq_str (const\n\tArray<char>&)): New ctor.\n\n2010-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Cell.cc: Reflect Array API changes.\n\t* DLD-FUNCTIONS/__convn__.cc: Ditto.\n\t* DLD-FUNCTIONS/__glpk__.cc: Ditto.\n\t* DLD-FUNCTIONS/__magick_read__.cc: Ditto.\n\t* DLD-FUNCTIONS/bsxfun.cc: Ditto.\n\t* DLD-FUNCTIONS/cellfun.cc: Ditto.\n\t* DLD-FUNCTIONS/conv2.cc: Ditto.\n\t* DLD-FUNCTIONS/dlmread.cc: Ditto.\n\t* DLD-FUNCTIONS/filter.cc: Ditto.\n\t* DLD-FUNCTIONS/kron.cc: Ditto.\n\t* DLD-FUNCTIONS/qz.cc: Ditto.\n\t* DLD-FUNCTIONS/regexp.cc: Ditto.\n\t* DLD-FUNCTIONS/sub2ind.cc: Ditto.\n\t* data.cc: Ditto.\n\t* file-io.cc: Ditto.\n\t* gl-render.cc: Ditto.\n\t* ls-mat5.cc: Ditto.\n\t* oct-map.cc: Ditto.\n\t* oct-obj.h: Ditto.\n\t* oct-parse.yy: Ditto.\n\t* oct-stream.cc: Ditto.\n\t* ov-base-mat.cc: Ditto.\n\t* ov-base-sparse.cc: Ditto.\n\t* ov-perm.cc: Ditto.\n\t* ov-struct.cc: Ditto.\n\t* ov-typeinfo.cc: Ditto.\n\t* ov-typeinfo.h: Ditto.\n\t* ov.cc: Ditto.\n\t* pr-output.cc: Ditto.\n\t* pt-mat.cc: Ditto.\n\t* strfns.cc: Ditto.\n\t* txt-eng-ft.cc: Ditto.\n\t* variables.cc: Ditto.\n\n2010-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc: Use numel instead of nelem consistently and where\n\tappropriate in all functions.\n\t(read_mat5_binary_element): Declare ridx and cidx as pointer to\n\toctave_idx_type, not int.\n\t(read_mat5_integer_data): Declare count as octave_idx_type, not int.\n\t(READ_INTEGER_DATA): Loop counter is octave_idx_type, not int.\n\t(OCTAVE_MAT5_INTEGER_READ): Declare n and loop counter as\n\toctave_idx_type, not int.\n\t(read_mat5_binary_element): Rows and columns of sparse matrix\n\tare octave_idx_type, not int.  Declare nzmax and nnz as\n\toctave_idx_type.  Read nzmax as 32-bit int, and assign.  Move\n\tdecls closer to first use.\n\t(read_mat5_binary_data): Declare count as octave_idx_type, not int.\n\t(read_mat5_binary_element, write_mat5_array):\n\tUse octave_idx_type instead of int for numel and loop counters.\n\t(write_mat5_array): Declare len and nel as octave_idx_type.\n\tMove declarations closer to first use.\n\t(write_mat5_tag): Declare bytes arg as octave_idx_type, not int.\n\t(write_mat5_integer_data): Declare nel as octave_idx_type, not int.\n\t(write_mat5_cell_array): Declare nel and loop counter as\n\toctave_idx_type, not int.\n\t(save_mat5_array_length): Declare nel nad loop counters as\n\toctave_idx_type, not int.\n\t(save_mat5_binary_element): Declare dims and counters as\n\toctave_idx_type, not int. Delete unused streampos variables.\n\tCall write_mat5_sparse_index_vector to write ridx and cidx.\n\tDon't write element if dimension is too large to save.\n\t(gripe_dim_too_large, write_mat5_sparse_index_vector): New functions.\n\n2010-02-22  Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* dirfns.cc (Fglob): Make glob function test more robust.\n\n2010-02-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* gl-render.h: Define WIN32_LEAN_AND_MEAN and don't #undef min/max.\n\t* DLD-FUNCTIONS/fltk_backend.cc: Don't #undef min/max.\n\n\t* sighandlers.cc (octave_set_signal_handler): Don't use SIGALRM\n\tunconditionally.\n\n\t* ov-bool.h (class octave_bool): Add OCTINTERP_API.\n\t* unwind-prot.h (class unwind_protect_safe): Ditto.\n\n\t* Makefile.am: Add -bindir flag to liboctinterp_la_LDFLAGS. Remove\n\ttemporary libtool module file after copying oct file.\n\n2010-02-19  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/qr.cc: Increase tolerance for test.\n\n2010-02-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-lazy-idx.cc (octave_lazy_index::reshape,\n\toctave_lazy_index::squeeze, octave_lazy_index::permute,\n\toctave_lazy_index::sort, octave_lazy_index::is_sorted,\n\toctave_lazy_index::sort_rows_idx, octave_lazy_index::is_sorted_rows):\n\tNew method overrides.\n\t* ov-lazy-idx.h: Declare them.\n\t* ov-re-mat.cc (octave_matrix::reshape, octave_matrix::squeeze,\n\toctave_matrix::sort, octave_matrix::is_sorted,\n\toctave_matrix::sort_rows_idx, octave_matrix::is_sorted_rows): New\n\tmethod overrides.\n\t* ov-re-mat.h: Declare them.\n\n2010-02-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/find.cc (Ffind): Avoid unsafe conversion from Inf to\n\tinteger.\n\n2010-02-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* syscalls.cc (mk_stat_result): New helper function.\n\t(Flstat): Call it here.\n\t(Fstat): Also here. Handle also the fstat case here.\n\n2010-02-18  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* dirfns.cc (Fglob): Document globbing patterns, add test.\n\n2010-02-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* load-path.cc (in_path_list): New helper function.\n\t(add_to_fcn_map): Use it here.\n\n2010-02-18  Søren Hauberg  <hauberg@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (__magick_finfo__):\n\tHandle multiple frames in a single image file.\n\n2010-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.h (Octave_map::Octave_map): Allow dimension to also be\n\tspecified in string_vector constructor.\n\n2010-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (OCTAVE_LIBS, OCTINTERP_LINK_DEPS):\n\tInclude ../libcruft/libranlib.la in the list.\n\t* oct-conf.h.in (OCTAVE_CONF_F77_INTEGER_8_FLAG): New macro.\n\t* toplev.cc (octave_config_info): Include F77_INTEGER_8_FLAG in\n\tthe struct.\n\n2010-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (do_numeric_lookup): Return an idx_vector\n\twhen left_inf is in effect, to enable lazy index optimization.\n\n2010-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-lazy-idx.h: New source.\n\t* ov-lazy-idx.cc: New source.\n\t* ov.cc (install_types): Register lazy_index here.\n\t(octave_value::octave_value (const idx_vector&)): Use lazy\n\tconstruction if possible, under control of an optional flag.\n\t(octave_value::clone): Implement.\n\t* ls-hdf5.cc (save_hdf5): Avoid saving lazy indices.\n\n2010-02-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-fcn-handle.h (octave_fcn_handle::print_as_scalar): New method\n\toverride.\n\n2010-02-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::is_equal_to): New method.\n\t* ov-fcn-handle.h: Declare it.\n\t* OPERATORS/op-fcn.cc (eq, ne): Call it here. Register new handler.\n\n2010-02-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* load-path.cc (load_path::do_any_class_method): Rename to\n\tdo_overloads. Return a list of classes.\n\t* load-path.h (load_path::any_class_method): Likewise.\n\t* symtab.cc (get_dispatch_type): Rewrite.\n\t* symtab.h (get_dispatch_type): Update decl.\n\t* ov-fcn-handle.h (octave_fcn_handle): Partially rewrite.\n\t(octave_fcn_handle::builtin_overloads, octave_fcn_handle::overloads,\n\toctave_fcn_handle::has_overloads): New members.\n\t* ov-fcn-handle.cc (octave_fcn_handle::do_multi_index_op): Rewrite.\n\t(make_fcn_handle): Partially rewrite.\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/config-module.awk, genprops.awk, graphics.h.in,\n\tmkgendoc, mk-pkg-add, mxarray.h.in, zfstream.cc, zfstream.h:\n\tUntabify.\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* strfns.cc (Fstrcmpi, Fstrncmpi): Use DEFUNX instead of DEFUN.\n\t(Fstrncmpi): Report strncmpi in error message, not strncmp.\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* Cell.cc, bitfcns.cc, c-file-ptr-stream.cc, comment-list.cc,\n\tdata.cc, debug.cc, defaults.cc, defun.cc, dirfns.cc, display.cc,\n\tdynamic-ld.cc, error.cc, file-io.cc, gl-render.cc,\n\tgl2ps-renderer.cc, graphics.cc, gripes.cc, help.cc, input.cc,\n\tload-path.cc, load-save.cc, ls-ascii-helper.cc, ls-hdf5.cc,\n\tls-mat-ascii.cc, ls-mat4.cc, ls-mat5.cc, ls-oct-ascii.cc,\n\tls-oct-binary.cc, mex.cc, oct-fstrm.cc, oct-hist.cc,\n\toct-lvalue.cc, oct-map.cc, oct-obj.cc, oct-prcstrm.cc,\n\toct-procbuf.cc, oct-stream.cc, oct-strstrm.cc, octave.cc,\n\tov-base-diag.cc, ov-base-int.cc, ov-base-mat.cc,\n\tov-base-scalar.cc, ov-base-sparse.cc, ov-base.cc,\n\tov-bool-mat.cc, ov-bool-sparse.cc, ov-bool.cc, ov-builtin.cc,\n\tov-cell.cc, ov-ch-mat.cc, ov-class.cc, ov-colon.cc,\n\tov-complex.cc, ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc,\n\tov-dld-fcn.cc, ov-fcn-handle.cc, ov-fcn-inline.cc, ov-float.cc,\n\tov-flt-complex.cc, ov-flt-cx-diag.cc, ov-flt-cx-mat.cc,\n\tov-flt-re-diag.cc, ov-flt-re-mat.cc, ov-int16.cc, ov-int32.cc,\n\tov-int64.cc, ov-int8.cc, ov-mex-fcn.cc, ov-perm.cc, ov-range.cc,\n\tov-re-diag.cc, ov-re-mat.cc, ov-re-sparse.cc, ov-scalar.cc,\n\tov-str-mat.cc, ov-struct.cc, ov-typeinfo.cc, ov-uint16.cc,\n\tov-uint32.cc, ov-uint64.cc, ov-uint8.cc, ov-usr-fcn.cc, ov.cc,\n\tpager.cc, pr-output.cc, procstream.cc, pt-arg-list.cc,\n\tpt-assign.cc, pt-binop.cc, pt-bp.cc, pt-cbinop.cc, pt-cell.cc,\n\tpt-check.cc, pt-cmd.cc, pt-colon.cc, pt-const.cc, pt-decl.cc,\n\tpt-eval.cc, pt-except.cc, pt-exp.cc, pt-fcn-handle.cc, pt-id.cc,\n\tpt-idx.cc, pt-jump.cc, pt-loop.cc, pt-mat.cc, pt-misc.cc,\n\tpt-pr-code.cc, pt-select.cc, pt-stmt.cc, pt-unop.cc,\n\tsighandlers.cc, sparse-xdiv.cc, sparse-xpow.cc, strfns.cc,\n\tsymtab.cc, syscalls.cc, sysdep.cc, toplev.cc, txt-eng-ft.cc,\n\tutils.cc, variables.cc, xdiv.cc, xpow.cc, oct-parse.yy, lex.ll:\n\tUntabify.\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* Cell.h, base-list.h, c-file-ptr-stream.h, comment-list.h,\n\tdebug.h, defun-int.h, dynamic-ld.h, error.h, gl-render.h,\n\tgl2ps-renderer.h, gripes.h, load-path.h, load-save.h, ls-hdf5.h,\n\tls-mat-ascii.h, ls-mat4.h, ls-mat5.h, ls-oct-ascii.h,\n\tls-oct-binary.h, oct-fstrm.h, oct-iostrm.h, oct-lvalue.h,\n\toct-map.h, oct-obj.h, oct-prcstrm.h, oct-stdstrm.h,\n\toct-stream.h, oct-strstrm.h, octave.h, ops.h, ov-base-diag.h,\n\tov-base-int.h, ov-base-mat.h, ov-base-scalar.h,\n\tov-base-sparse.h, ov-base.h, ov-bool-mat.h, ov-bool-sparse.h,\n\tov-bool.h, ov-builtin.h, ov-cell.h, ov-class.h, ov-complex.h,\n\tov-cx-diag.h, ov-cx-mat.h, ov-cx-sparse.h, ov-dld-fcn.h,\n\tov-fcn-handle.h, ov-fcn-inline.h, ov-fcn.h, ov-float.h,\n\tov-flt-complex.h, ov-flt-cx-diag.h, ov-flt-cx-mat.h,\n\tov-flt-re-diag.h, ov-flt-re-mat.h, ov-intx.h, ov-mex-fcn.h,\n\tov-perm.h, ov-range.h, ov-re-diag.h, ov-re-mat.h,\n\tov-re-sparse.h, ov-scalar.h, ov-str-mat.h, ov-struct.h,\n\tov-type-conv.h, ov-typeinfo.h, ov-usr-fcn.h, ov.h, parse.h,\n\tpr-output.h, pt-arg-list.h, pt-assign.h, pt-binop.h, pt-cell.h,\n\tpt-cmd.h, pt-colon.h, pt-const.h, pt-decl.h, pt-eval.h,\n\tpt-except.h, pt-exp.h, pt-fcn-handle.h, pt-id.h, pt-idx.h,\n\tpt-jump.h, pt-loop.h, pt-mat.h, pt-misc.h, pt-pr-code.h,\n\tpt-select.h, pt-stmt.h, pt-unop.h, sighandlers.h, sparse-xdiv.h,\n\tsparse-xpow.h, symtab.h, token.h, toplev.h, txt-eng-ft.h,\n\ttxt-eng.h, utils.h, variables.h, xdiv.h: Untabify.\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/qz.cc: Untabify.\n\t(Fqz): Declare complex_case volatile to avoid GCC warning.\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/qz.cc: Style fixes.\n\n2010-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc: If gnulib defines open, undefine it.  Move\n\t#undefs before including zfstream.h.\n\n2010-01-30  Jyh-Miin Lin  <jyhmiin@gmail.com>\n\n\t* DLD-FUNCTIONS/qz.cc (Fqz): Handle complex case without reordering.\n\tReturn Q' for Matlab compatibility.\n\n2010-02-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.cc: Reverse the effect of 2ceae0b40515.\n\t(get_dispatch_type): If btyp_unknown occurs, read the class dispatch\n\ttype.\n\n2010-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc: If gnulib defines close, undefine it.\n\n2010-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-perm.h (octave_perm_matrix::builtin_type): New function.\n\t* symtab.cc (build_sup_table): Build the matrix with extra column\n\tand row to avoid segfault when undefined value leaks in.\n\t(get_dispatch_type): Update. Gripe if invalid result is detected.\n\n2010-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc: Ensure that CLOCKS_PER_SEC is defined instead of HZ.\n\t(Fcputime): Use CLOCKS_PER_SEC instead of HZ.\n\n2010-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc: Include <sys/times.h>.  Define HZ if it is not defined.\n\n2010-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (base_properties::set_children): Ensure that new\n\tchildren are stored as a column vector.\n\n\t* syscalls.cc (Fdup2, Fexec, Fpopen2, Ffork, Fgetpgrp, Fgetpid,\n\tFgetppid, Fgetegid, Fgetgid, Fgeteuid, Fkill, Ffstat, Flstat,\n\tFpipe, Fstat, Fwaitpid): Use DEFUNX instead of DEFUN.\n\n2010-02-10  David Grundberg  <davidg@cs.umu.se>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (read_images): Reimplement\n\tcopying with direct fortran_vec manipulation, avoiding indexing\n\toperations.  Replace scale_quantum_to_depth calls with simple\n\tarithmetics.\n\t(scale_quantum_to_depth): Remove function.\n\n2010-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/bsxfun.cc (Fbsxfun): Remove redundant test. Add\n\texplanation.\n\n2010-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (octave_base_value::is_list): Remove.\n\t* ov.h (octave_value::is_list): Remove.\n\t* data.cc (Fislist): Remove.\n\t* oct-stream.cc (printf_value_cache::printf_value_cache): Don't call\n\tis_list.\n\n2010-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-str-mat.h (octave_char_matrix_str::is_real_type): Delete\n\toverload.\n\t* data.cc (Fisreal): Improve docs.\n\n2010-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fisnumeric): Improve documentation.\n\t(Fismatrix): Ditto.\n\n2010-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc, graphics.h.in\n\t(base_properties::get_hidden_children): New function.\n\t(base_properties::get_children_internal): New function.\n\t(base_properties::get_children): Call get_children_internal to\n\tdo the work.\n\t(base_properties::set_children): Incorporate maybe_set_children\n\tfunction here.  Account for hidden children.\n\t(maybe_set_children): Delete.\n\n\t* c-file-ptr-stream.h (c_file_ptr_buf::buf_close): Rename from close.\n\t(c_file_ptr_buf::file_close): Rename from fclose.\n\t(c_file_ptr_stream::stream_close): Rename from close.\n\t(c_zfile_ptr_buf:buf_close): Rename from close.\n\tChange all callers.\n\n2010-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* dynamic-ld.cc (clear): Only warn if reloading a dynamically\n\tlinked file that defines multiple functions.\n\n2010-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/find.cc (find_nonzero_elem_idx (const Array<T>&, ...)):\n\tOptimize creation of result indices.\n\t* data.cc (Fsort): Ditto.\n\n2010-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/colamd.cc (Fcolamd, Fsymamd, Fetree): Fix improper arg\n\tchecks.\n\t* DLD-FUNCTIONS/ccolamd.cc (Fccolamd, Fcsymamd): Likewise.\n\n2010-02-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-mat.cc (octave_matrix::sort): Special-case sorting a known\n\tindex vector.\n\n2010-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (Fclass): If more than 1 argument, check that\n\tcall is inside class constructor first, then check for valid\n\targuments.\n\n2010-02-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (F__accumarray_sum__): Allow bool and char inputs.\n\t(do_accumarray_minmax, do_accumarray_minmax_fun): New helper funcs.\n\t(F__accumarray_min__, F__accumarray_max__): New defuns.\n\n2010-02-04  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc: Don't include <sys/utsname.h>.\n\n2010-02-04  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (gh_manager::lookup (const octave_value&)):\n\tNew function.\n\t* graphics.cc (axes::properties::set_text_child): Validate value.\n\tAllow value to be character string or handle of text object.\n\n2010-02-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (OCTAVE_LIBS): Include all liboctave library\n\tdependencies here.\n\n2010-02-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-fcn-handle.h (octave_fcn_handle::anonymous): New static field.\n\t* ov-fcn-handle.cc (octave_fcn_handle::anonymous): Initialize it.\n\tUse everywhere instead of hardwired string.\n\t(octave_fcn_handle::print_raw): Print named function handle with\n\tstarting @.\n\t* pt-fcn-handle.cc: Use octave_fcn_handle::anonymous rather than\n\thardcoded string.\n\n2010-02-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-fcn.cc: New source.\n\t* OPERATORS/module.mk: Include it.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc: Assume we have fcntl.h and sys/stat.h.\n\n\t* syscalls.cc: Assume we have fcntl.h and fcntl.\n\t(Ffcntl): Use DEFUNX, not DEFUN.  Call octave_fcntl, not\n\toctave_syscalls::fcntl.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/sub2ind.cc (get_dim_vector):\n\tEliminate unnecessary cast.\n\n\t* DLD-FUNCTIONS/qr.cc (Fqrinsert, Fqrdelete):\n\tAvoid type mismatch errors with octave_idx_type.\n\n\t* oct-stream.cc (scanf_format_list::add_elt_to_list):\n\tNUM_ELTS arg is octave_idx_type, not int.\n\n\t* ov-struct.cc (octave_struct::load_ascii): Ensure args to\n\tstd::max are the same type.\n\t* DLD-FUNCTIONS/lookup.cc (do_numeric_lookup): Likewise.\n\t* DLD-FUNCTIONS/sub2ind.cc (get_dim_vector): Likewise.\n\t* DLD-FUNCTIONS/strfind.cc (qs_search): Likewise, for std::min.\n\t* DLD-FUNCTIONS/tril.cc (do_tril, do_triu): Likewise.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* utils.cc (octave_vsnprintf): Assume we have vsnprintf with\n\tsemantics that match the version provided by gnulib.\n\n\t* DLD-FUNCTIONS/convhulln.cc (Fconvhulln):\n\tUse std::sstream instead of fixed-length buffer and snprintf.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* cutils.c (octave_usleep): Implement using nanosleep.\n\t(octave_sleep): Assume sleep exists.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* syscalls.cc (Fcanonicalize_file_name):\n\tCall octave_canonicalize_file_name instead of\n\tfile_ops::canonicalize_file_name.\n\n2010-02-03  John W. Eaton  <jwe@octave.org>\n\n\t* dirfns.cc (Fpwd): Call octave_env::get_current_directory, not\n\toctave_env::getcwd.\n\n\t* utils.cc (search_path_for_file, search_path_for_all_files,\n\tmake_absolute, Ffile_in_loadpath, Ffile_in_path, file_in_path,\n\tcontents_file_in_path, Fmake_absolute_filename):\n\tDon't pass current directory to octave_env::make_absolute.\n\t* ov-fcn-handle.cc (octave_fcn_handle::set_fcn): Likewise.\n\t* octave.cc (execute_startup_files): Likewise.\n\t* ls-mat5.cc (read_mat5_binary_element): Likewise.\n\t* load-save.cc (find_file_to_load): Likewise.\n\t* load-path.cc (load_path::dir_info::update,\n\tload_path::dir_info::initialize, load_path::do_find_dir,\n\tload_path::do_find_matching_dirs): Likewise.\n\t* file-io.cc (do_stream_open): Likewise.\n\t* oct-parse.yy (load_fcn_from_file, Fautoload): Likewise.\n\t* DLD-FUNCTIONS/md5sum.cc (Fmd5sum): Likewise.\n\t* DLD-FUNCTIONS/urlwrite.cc (Furlwrite): Likewise.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* syscalls.cc (Fcanonicalize_file_name): Use DEFUNX instead of DEFUN.\n\n2010-02-02  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* DLD-FUNCTIONS/filter.cc: New tests.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (octave_main): Assume we have atexit.\n\t* sighandlers.h, sighandlers.cc: Delete conditional definition\n\tof RETSIGTYPE.  Replace all uses of RETSIGTYPE with void.\n\t(MAYBE_REINSTALL_SIGHANDLER, SIGHANDLER_RETURN):\n\tDelete macros and all uses.\n\n2010-02-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* load-path.cc (load_path::add_to_fcn_map): Warn when core library or\n\tbuilt-in functions are being shadowed.\n\t(load_path::do_add): Pass at_end to add_to_fcn_map, add_to_method_map.\n\tDon't abort when \".\" not yet included.\n\t(load_path::do_clear): Don't append \".\" here.\n\t(load_path::do_set): Always prepend \".\" here.\n\t(load_path::initialize): Don't explicitly include \".\" here.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/filter.cc (filter (MArray<T>&, MArray<T>&,\n\tMArrayN<T>&, MArrayN<T>&, int)): Return early if X is empty.\n\n2010-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* cutils.c: Include <sys/times.h>, not \"systime.h\".\n\t* data.cc (Fcputime): Assume we have times.\n\n\t* DLD-FUNCTIONS/getrusage.cc (Fgetrusage): Assume we have times.\n\tInclude <times.h> and <sys/times.h> unconditionally.\n\tDon't include <windows.h>\n\n2010-02-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strfns.cc (Fstrncmpi): Fix typo in docstring.\n\n2010-01-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-list.h, ov-list.cc, OPERATORS/op-list.cc: Remove.\n\n\t* Makefile.am, OPERATORS/module.mk: Update.\n\t* debug.cc: Remove #include.\n\t* ov-base.cc: Ditto.\n\t* ov-cs-list.h: Ditto.\n\t* ov-struct.cc: Ditto.\n\t* pt-bp.cc: Ditto.\n\t* ov.cc (octave_value::octave_value (const octave_value_list&)):\n\tSimplify.\n\t(install_types): Omit octave_list.\n\n2010-01-30  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* DLD-FUNCTIONS/time.cc: Replace struct_contains by isfield.\n\n2010-01-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-assign.h (tree_multi_assignment::etype): Remove.\n\t(tree_multi_assignment::tree_multi_assignment): Update.\n\t(tree_multi_assignment::op_type): Update.\n\t* pt-assign.cc (tree_multi_assignment::tree_multi_assignment): Update.\n\t(tree_multi_assignment::rvalue): Update.\n\t(tree_multi_assignment::dup): Update.\n\t* oct=parse.yy (make_assign_op): Don't allow computed multiple\n\tassignments.\n\n2010-01-30  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (__fltk_redraw__): call\n\tFl::check twice to ensure all pending draws are shown on screen\n\n2010-01-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-lvalue.h (octave_lvalue::black_hole): Remove field.\n\t(octave_lvalue::(all methods)): Update.\n\t* oct-lvalue.cc: Ditto.\n\n2010-01-29  David Grundberg  <davidg@cs.umu.se>\n\n\t* mex.cc (mex::realloc): Allocate new memory if the argument is\n\tNULL.\n\n2010-01-29  Ryan Rusaw  <rrusaw@gmail.com>\n\n\t* pt-eval.h, pt-eval.cc (tree_evaluator::do_keyboard):\n\tNew virtual function.\n\n2010-01-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* toplev.cc (run_command_and_return_output): Fix testing of failed\n\tprocess creation, simplify.\n\t(cleanup_iprocstream): Remove.\n\n2010-01-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-eval.cc (do_unwind_protect_cleanup_code): Save\n\tcurrent_statement and restore it after cleanup block.\n\n2010-01-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-parse.yy (validate_matrix_row): New static helper func.\n\t(cell_or_matrix_row): Call it here.\n\n2010-01-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-lvalue.h (octave_lvalue::is_black_hole): New method.\n\t(octave_lvalue::black_hole): New field.\n\t(octave_lvalue::is_defined, octave_lvalue::is_undefined,\n\toctave_lvalue::is_map): Make const.\n\t(octave_lvalue::index_set): Remove field.\n\t(octave_lvalue::octave_lvalue, octave_lvalue::operator =): Correctly\n\thandle black holes. Update.\n\t(dummy_value): Remove.\n\t* pt-id.h (tree_identifier::is_black_hole): New method.\n\t(tree_identifier::is_variable): Make virtual.\n\t(tree_black_hole): New class.\n\t* oct-parse.yy (magic_tilde): New terminal.\n\t(param_list): Allow magic_tilde.\n\t(arg_list): Allow magic_tilde.\n\t* pt-misc.cc (tree_parameter_list::validate): Handle black holes.\n\t* pt-idx.cc (tree_index_expression::append): Gripe if arguments\n\tcontain magic tilde.\n\t* pt-arg-list.h (tree_argument_list::has_magic_tilde): New method\n\tdecl.\n\t(tree_argument_list::list_includes_magic_tilde): New field.\n\t(tree_argument_list::tree_argument_list): Initialize it in ctors.\n\t* pt-arg-list.cc (tree_argument_list::has_magic_tilde): New method.\n\t(tree_argument_list::append): Update list_includes_magic_tilde.\n\n2010-01-27  Judd Storrs  <jstorrs@gmail.com>\n\n\t* ov-class.cc (octave_class::print_with_name) Add default case for\n\tclasses that don't define a display method.\n\n2010-01-26  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* gl-render.cc (draw_text): scale position.\n\n2010-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* dirfns.cc (Fmkdir, Frmdir, Flink, Fsymlink, Freadlink,\n\tFrename, Ftmpnam, Fumask): Use DEFUNX instead of DEFUN.\n\t* syscall.scc (Fmkfifo, Funlink): Ditto.\n\t* DLD-FUNCTIONS/urlwrite.cc (cleanup_urlwrite, reset_path,\n\tdelete_file): Now static.\n\n2010-01-23  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (octave_main): Use getopt directly instead of using\n\tthe (mostly useless) prog_args wrapper class.\n\tInclude <getopt.h>, not \"prog-args.h\".\n\n2010-01-23  John W. Eaton  <jwe@octave.org>\n\n\t* sighandlers.cc (user_abort): Also set debug_mode if Vdebugging.\n\t* debug.cc (bp_table::do_add_breakpoint, do_remove_all_breakpoints,\n\tbp_table::do_remove_breakpoint,\tdo_remove_all_breakpoints_in_file):\n\tAlso set debug_mode if Vdebugging.\n\t* pt-eval.cc (visit_return_command): Actually call reset_debug_state.\n\t(reset_debug_state): Also set debug_mode if Vdebugging.\n\n2010-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (octave_main): Use new names for prog_args member\n\tfunctions.\n\n2010-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc: Don't include sys/types.h, unistd.h, or fstream.\n\n2010-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy (make_break_command, make_continue_command,\n\tmake_return_command): Don't examine evaluator state here.\n\t* pt-eval.cc (tree_evaluator::visit_break_command): Don't set\n\ttree_break_command::breaking unless inside function or script\n\tbody, or inside a looping command.\n\t(tree_evaluator::visit_continue_command): Likewise, for\n\ttree_continue_command::continuing.\n\t(tree_evaluator::visit_return_command): Likewise, for\n\ttree_return_command::returning.  Act like dbcont if debugging\n\tand in the top-level debugging stack frame.\n\n2010-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_base_stream::do_scanf): Don't skip\n\twhitespace, literal text, and %% elements at the end of the\n\tformat spec.  Correctly process formats containing only literal text.\n\t(scanf_format_list::finish_conversion): Don't increment nconv\n\tfor literal % characters.\n\t(scanf_format_list::length, scanf_format_list::num_conversions):\n\tReturn octave_idx_type, not int.\n\t(scanf_format_list::nconv, scanf_format_list::curr_idx):\n\tNow octave_idx_type, not int.  Change all uses.\n\t(printf_format_list::length): Return octave_idx_type, not int.\n\t(scanf_format_list::nconv, scanf_format_list::curr_idx):\n\tNow octave_idx_type, not int.  Change all uses.\n\t(scanf_format_list::add_elt_to_list,\n\tscanf_format_list::process_conversion,\n\tscanf_format_list::finish_conversion,\n\tprintf_format_list::add_elt_to_list,\n\tprintf_format_list::process_conversion,\n\tprintf_format_list::finish_conversion):\n\tUse size_t instead of int as appropriate.\n\t* oct-stream.h: Update decls.\n\n2010-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* debug.cc (Fdbcont, Fdbquit): Call reset_debug_state.\n\t(Fdbquit): Set Vdebugging to false.\n\t* input.cc (Fkeyboard): Set tree_evaluator::debug_state to true.\n\tSet tree_evaluator::current_frame to the initial stack frame\n\tthat is active for debugging commands.\n\t* pt-eval.cc (tree_evaluator::reset_debug_state): New function.\n\t* pt-eval.h (tree_evaluator::reset_debug_state): Provide decl.\n\t* toplev.cc (main_loop): Call tree_evaluator::reset_debug_state\n\tif at top level.\n\n2010-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fnorm): Don't special-case empty matrix.\n\t* DLD-FUNCTIONS/svd.cc (Fsvd): Fix empty matrix case. Add tests.\n\n2010-01-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op): Partially undo\n\tprevious change.\n\t* ov-type-conv.h (octave_type_conv_body): Undo previous change.\n\t* ov-dld-fcn.cc (octave_dld_function::do_multi_index_op): Ditto.\n\n2010-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/getrusage.cc, DLD-FUNCTIONS/getgrent.cc,\n\tDLD-FUNCTIONS/getpwent.cc, DLD-FUNCTIONS/regexp.cc, lex.ll,\n\tcutils.c, data.cc, defaults.cc, dirfns.cc, file-io.cc, help.cc,\n\tinput.cc, oct-hist.cc, oct-procbuf.cc, oct-procbuf.h, octave.cc,\n\tpager.h, procstream.h, sighandlers.cc, toplev.cc, syscalls.cc,\n\tsysdep.cc, utils.cc: Assume sys/types.h and unistd.h are present\n\t(gnulib provides them).\n\n2010-01-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (octave_base_value::dim_vector): Return 0x0 by default.\n\t* oct-obj.h (octave_value_list::xelem, octave_value_list::clear): New\n\tmethods.\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op): Don't call\n\tmake_storable_values. Chop a potential single undefined value.\n\t* ov-type-conv.h (octave_type_conv_body): Ensure storable value.\n\t* ov-dld-fcn.cc (octave_dld_function::do_multi_index_op): New method.\n\t* DLD-FUNCTIONS/cellfun.cc (get_output_list): New helper function.\n\t(Fcellfun): Call it here. Optimize.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* defaults.h.in, graphics.h.in, oct-conf.h.in, oct-errno.cc.in,\n\tversion.h.in: Delete Emacs local-variable settings.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* cutils.c, main.c, matherr.c, siglist.c, Cell.cc, bitfcns.cc,\n\tc-file-ptr-stream.cc, comment-list.cc, data.cc, debug.cc,\n\tdefaults.cc, defun.cc, dirfns.cc, display.cc, dynamic-ld.cc,\n\terror.cc, file-io.cc, gl-render.cc, gl2ps-renderer.cc,\n\tgraphics.cc, gripes.cc, help.cc, input.cc, load-path.cc,\n\tload-save.cc, ls-ascii-helper.cc, ls-hdf5.cc, ls-mat-ascii.cc,\n\tls-mat4.cc, ls-mat5.cc, ls-oct-ascii.cc, ls-oct-binary.cc,\n\tls-utils.cc, mappers.cc, oct-fstrm.cc, oct-hist.cc,\n\toct-iostrm.cc, oct-lvalue.cc, oct-map.cc, oct-obj.cc,\n\toct-prcstrm.cc, oct-procbuf.cc, oct-stream.cc, oct-strstrm.cc,\n\toctave.cc, ov-base-int.cc, ov-base-mat.cc, ov-base-scalar.cc,\n\tov-base-sparse.cc, ov-base.cc, ov-bool-mat.cc,\n\tov-bool-sparse.cc, ov-bool.cc, ov-builtin.cc, ov-cell.cc,\n\tov-ch-mat.cc, ov-class.cc, ov-colon.cc, ov-complex.cc,\n\tov-cs-list.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-dld-fcn.cc,\n\tov-fcn-handle.cc, ov-fcn-inline.cc, ov-fcn.cc, ov-float.cc,\n\tov-flt-complex.cc, ov-flt-cx-mat.cc, ov-flt-re-mat.cc,\n\tov-int16.cc, ov-int32.cc, ov-int64.cc, ov-int8.cc, ov-list.cc,\n\tov-mex-fcn.cc, ov-range.cc, ov-re-mat.cc, ov-re-sparse.cc,\n\tov-scalar.cc, ov-str-mat.cc, ov-struct.cc, ov-typeinfo.cc,\n\tov-uint16.cc, ov-uint32.cc, ov-uint64.cc, ov-uint8.cc,\n\tov-usr-fcn.cc, ov.cc, pager.cc, pr-output.cc, procstream.cc,\n\tpt-arg-list.cc, pt-assign.cc, pt-binop.cc, pt-bp.cc, pt-cell.cc,\n\tpt-check.cc, pt-cmd.cc, pt-colon.cc, pt-const.cc, pt-decl.cc,\n\tpt-eval.cc, pt-except.cc, pt-exp.cc, pt-fcn-handle.cc, pt-id.cc,\n\tpt-idx.cc, pt-jump.cc, pt-loop.cc, pt-mat.cc, pt-misc.cc,\n\tpt-pr-code.cc, pt-select.cc, pt-stmt.cc, pt-unop.cc, pt.cc,\n\tsighandlers.cc, sparse-xdiv.cc, sparse-xpow.cc, strfns.cc,\n\tsymtab.cc, syscalls.cc, sysdep.cc, token.cc, toplev.cc,\n\tunwind-prot.cc, utils.cc, variables.cc, xdiv.cc, xpow.cc,\n\tzfstream.cc, Cell.h, base-list.h, builtins.h,\n\tc-file-ptr-stream.h, comment-list.h, debug.h, defun-dld.h,\n\tdefun-int.h, defun.h, dirfns.h, display.h, dynamic-ld.h,\n\terror.h, file-io.h, gl2ps-renderer.h, gripes.h, help.h, input.h,\n\tlex.h, load-path.h, load-save.h, ls-ascii-helper.h, ls-hdf5.h,\n\tls-mat-ascii.h, ls-mat4.h, ls-mat5.h, ls-oct-ascii.h,\n\tls-oct-binary.h, ls-utils.h, mex.h, mexproto.h, oct-errno.h,\n\toct-fstrm.h, oct-hdf5.h, oct-hist.h, oct-iostrm.h, oct-lvalue.h,\n\toct-map.h, oct-obj.h, oct-prcstrm.h, oct-procbuf.h,\n\toct-stdstrm.h, oct-stream.h, oct-strstrm.h, oct.h, octave.h,\n\tops.h, ov-base-int.h, ov-base-mat.h, ov-base-scalar.h,\n\tov-base-sparse.h, ov-base.h, ov-bool-mat.h, ov-bool-sparse.h,\n\tov-bool.h, ov-builtin.h, ov-cell.h, ov-ch-mat.h, ov-class.h,\n\tov-colon.h, ov-complex.h, ov-cs-list.h, ov-cx-mat.h,\n\tov-cx-sparse.h, ov-dld-fcn.h, ov-fcn-handle.h, ov-fcn-inline.h,\n\tov-fcn.h, ov-float.h, ov-flt-complex.h, ov-flt-cx-diag.h,\n\tov-flt-cx-mat.h, ov-flt-re-mat.h, ov-int-traits.h, ov-int16.h,\n\tov-int32.h, ov-int64.h, ov-int8.h, ov-intx.h, ov-list.h,\n\tov-mex-fcn.h, ov-range.h, ov-re-mat.h, ov-re-sparse.h,\n\tov-scalar.h, ov-str-mat.h, ov-struct.h, ov-type-conv.h,\n\tov-typeinfo.h, ov-uint16.h, ov-uint32.h, ov-uint64.h,\n\tov-uint8.h, ov-usr-fcn.h, ov.h, pager.h, parse.h, pr-output.h,\n\tprocstream.h, pt-all.h, pt-arg-list.h, pt-assign.h, pt-binop.h,\n\tpt-bp.h, pt-cbinop.h, pt-cell.h, pt-check.h, pt-cmd.h,\n\tpt-colon.h, pt-const.h, pt-decl.h, pt-eval.h, pt-except.h,\n\tpt-exp.h, pt-fcn-handle.h, pt-id.h, pt-idx.h, pt-jump.h,\n\tpt-loop.h, pt-mat.h, pt-misc.h, pt-pr-code.h, pt-select.h,\n\tpt-stmt.h, pt-unop.h, pt-walk.h, pt.h, sighandlers.h, siglist.h,\n\tsparse-xdiv.h, sparse-xpow.h, symtab.h, sysdep.h, token.h,\n\ttoplev.h, unwind-prot.h, utils.h, variables.h, xdiv.h, xpow.h,\n\tzfstream.h, oct-parse.yy, lex.ll: Delete EMacs local-variable settings.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc, DLD-FUNCTIONS/balance.cc,\n\tDLD-FUNCTIONS/besselj.cc, DLD-FUNCTIONS/betainc.cc,\n\tDLD-FUNCTIONS/ccolamd.cc, DLD-FUNCTIONS/cellfun.cc,\n\tDLD-FUNCTIONS/chol.cc, DLD-FUNCTIONS/colamd.cc,\n\tDLD-FUNCTIONS/colloc.cc, DLD-FUNCTIONS/conv2.cc,\n\tDLD-FUNCTIONS/daspk.cc, DLD-FUNCTIONS/dasrt.cc,\n\tDLD-FUNCTIONS/dassl.cc, DLD-FUNCTIONS/det.cc,\n\tDLD-FUNCTIONS/dmperm.cc, DLD-FUNCTIONS/dot.cc,\n\tDLD-FUNCTIONS/eig.cc, DLD-FUNCTIONS/eigs.cc,\n\tDLD-FUNCTIONS/fft.cc, DLD-FUNCTIONS/fft2.cc,\n\tDLD-FUNCTIONS/fftn.cc, DLD-FUNCTIONS/filter.cc,\n\tDLD-FUNCTIONS/find.cc, DLD-FUNCTIONS/fltk_backend.cc,\n\tDLD-FUNCTIONS/gammainc.cc, DLD-FUNCTIONS/gcd.cc,\n\tDLD-FUNCTIONS/getgrent.cc, DLD-FUNCTIONS/getpwent.cc,\n\tDLD-FUNCTIONS/getrusage.cc, DLD-FUNCTIONS/givens.cc,\n\tDLD-FUNCTIONS/hess.cc, DLD-FUNCTIONS/inv.cc,\n\tDLD-FUNCTIONS/lookup.cc, DLD-FUNCTIONS/lsode.cc,\n\tDLD-FUNCTIONS/lu.cc, DLD-FUNCTIONS/luinc.cc,\n\tDLD-FUNCTIONS/matrix_type.cc, DLD-FUNCTIONS/max.cc,\n\tDLD-FUNCTIONS/pinv.cc, DLD-FUNCTIONS/qr.cc,\n\tDLD-FUNCTIONS/quad.cc, DLD-FUNCTIONS/qz.cc,\n\tDLD-FUNCTIONS/rand.cc, DLD-FUNCTIONS/regexp.cc,\n\tDLD-FUNCTIONS/schur.cc, DLD-FUNCTIONS/sparse.cc,\n\tDLD-FUNCTIONS/spparms.cc, DLD-FUNCTIONS/sqrtm.cc,\n\tDLD-FUNCTIONS/svd.cc, DLD-FUNCTIONS/syl.cc,\n\tDLD-FUNCTIONS/symbfact.cc, DLD-FUNCTIONS/time.cc,\n\tDLD-FUNCTIONS/tril.cc: Delete Emacs local-variable settings.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__contourc__.cc, DLD-FUNCTIONS/__convn__.cc,\n\tDLD-FUNCTIONS/__delaunayn__.cc, DLD-FUNCTIONS/__dsearchn__.cc,\n\tDLD-FUNCTIONS/__glpk__.cc, DLD-FUNCTIONS/__lin_interpn__.cc,\n\tDLD-FUNCTIONS/__magick_read__.cc,\n\tDLD-FUNCTIONS/__pchip_deriv__.cc, DLD-FUNCTIONS/__qp__.cc,\n\tDLD-FUNCTIONS/__voronoi__.cc, DLD-FUNCTIONS/amd.cc,\n\tDLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/besselj.cc,\n\tDLD-FUNCTIONS/betainc.cc, DLD-FUNCTIONS/bsxfun.cc,\n\tDLD-FUNCTIONS/ccolamd.cc, DLD-FUNCTIONS/cellfun.cc,\n\tDLD-FUNCTIONS/chol.cc, DLD-FUNCTIONS/colamd.cc,\n\tDLD-FUNCTIONS/colloc.cc, DLD-FUNCTIONS/conv2.cc,\n\tDLD-FUNCTIONS/convhulln.cc, DLD-FUNCTIONS/daspk.cc,\n\tDLD-FUNCTIONS/dasrt.cc, DLD-FUNCTIONS/dassl.cc,\n\tDLD-FUNCTIONS/det.cc, DLD-FUNCTIONS/dispatch.cc,\n\tDLD-FUNCTIONS/dlmread.cc, DLD-FUNCTIONS/dmperm.cc,\n\tDLD-FUNCTIONS/eig.cc, DLD-FUNCTIONS/eigs.cc,\n\tDLD-FUNCTIONS/fft.cc, DLD-FUNCTIONS/fft2.cc,\n\tDLD-FUNCTIONS/fftn.cc, DLD-FUNCTIONS/fftw.cc,\n\tDLD-FUNCTIONS/filter.cc, DLD-FUNCTIONS/find.cc,\n\tDLD-FUNCTIONS/fltk_backend.cc, DLD-FUNCTIONS/gammainc.cc,\n\tDLD-FUNCTIONS/gcd.cc, DLD-FUNCTIONS/getgrent.cc,\n\tDLD-FUNCTIONS/getpwent.cc, DLD-FUNCTIONS/givens.cc,\n\tDLD-FUNCTIONS/hess.cc, DLD-FUNCTIONS/hex2num.cc,\n\tDLD-FUNCTIONS/inv.cc, DLD-FUNCTIONS/kron.cc,\n\tDLD-FUNCTIONS/lookup.cc, DLD-FUNCTIONS/lsode.cc,\n\tDLD-FUNCTIONS/lu.cc, DLD-FUNCTIONS/luinc.cc,\n\tDLD-FUNCTIONS/matrix_type.cc, DLD-FUNCTIONS/md5sum.cc,\n\tDLD-FUNCTIONS/pinv.cc, DLD-FUNCTIONS/qr.cc,\n\tDLD-FUNCTIONS/quad.cc, DLD-FUNCTIONS/qz.cc,\n\tDLD-FUNCTIONS/rand.cc, DLD-FUNCTIONS/rcond.cc,\n\tDLD-FUNCTIONS/regexp.cc, DLD-FUNCTIONS/schur.cc,\n\tDLD-FUNCTIONS/sparse.cc, DLD-FUNCTIONS/spparms.cc,\n\tDLD-FUNCTIONS/sqrtm.cc, DLD-FUNCTIONS/svd.cc,\n\tDLD-FUNCTIONS/syl.cc, DLD-FUNCTIONS/symbfact.cc,\n\tDLD-FUNCTIONS/symrcm.cc, DLD-FUNCTIONS/time.cc,\n\tDLD-FUNCTIONS/tril.cc, DLD-FUNCTIONS/tsearch.cc,\n\tDLD-FUNCTIONS/urlwrite.cc: Untabify.\n\n2010-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* TEMPLATE-INST/Array-os.cc, TEMPLATE-INST/Array-tc.cc,\n\tTEMPLATE-INST/Array-sym.cc: Delete Emacs local-variable settings.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc (xpow, elem_xpow): Don't do redundant real->complex\n\tconversions.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc: Substitute OCTAVE_QUIT -> octave_quit ().\n\t* input.cc: Ditto.\n\t* ls-mat-ascii.cc: Ditto.\n\t* oct-stream.cc: Ditto.\n\t* ov-base-int.cc: Ditto.\n\t* ov-base-sparse.cc: Ditto.\n\t* ov-bool-sparse.cc: Ditto.\n\t* ov-cell.cc: Ditto.\n\t* ov-cx-sparse.cc: Ditto.\n\t* ov-flt-re-mat.cc: Ditto.\n\t* ov-re-mat.cc: Ditto.\n\t* ov-re-sparse.cc: Ditto.\n\t* pr-output.cc: Ditto.\n\t* pt-eval.cc: Ditto.\n\t* pt-mat.cc: Ditto.\n\t* sighandlers.cc: Ditto.\n\t* sparse-xdiv.cc: Ditto.\n\t* sparse-xpow.cc: Ditto.\n\t* toplev.cc: Ditto.\n\t* utils.cc: Ditto.\n\t* xdiv.cc: Ditto.\n\t* xpow.cc: Ditto.\n\n2010-01-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/bsxfun.cc: New tests.\n\n2010-01-20  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (string_array_property): New property.\n\t(axes::properties): Use it here for the linestyleorder property.\n\tRemove the markerorder property.\n\t* genprops.awk: Emit string_array_property\n\n2010-01-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/strfind.cc: Optimize searching for 1 or 2 characters.\n\n2010-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* oct-parse.yy (fcn_end): Allow EOF as end of function if\n\treading from eval string.\n\t(eval_string): Protect and set reading_fcn_file,\n\treading_script_file, and reading_classdef_file.\n\n2010-01-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc (xpow (const NDArray&, double), xpow (const FloatNDArray&,\n\tfloat)): Optimize also the x.^3 case.\n\n2010-01-18  David Grundberg  <davidg@cs.umu.se>\n\n\t* mex.cc (mexPrintf): Change signature.\n\t* mexproto.h (mexPrintf): Ditto.\n\n2010-01-18  David Grundberg  <davidg@cs.umu.se>\n\n\t* mexproto.h (mxSetDimensions): Change signature.\n\t* mex.cc (mxSetDimensions): Ditto.\n\n2010-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellslices): Support dim argument, make\n\tconsistent with rest of functions.\n\n2010-01-17  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* ov-cell.cc (Fstruct2cell): Add example, add test.\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun, Fnum2cell), ov-struct.cc\n\t(Fisstruct): Fix docstring.\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellslices, Fisfield, Ffieldnames,\n\tFrmfield): Add test.\n\t* ov-struct.cc (Fcell2struct): Fix docstring, add test.\n\n2010-01-16  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (line::properties, surface::properties,\n\tpatch::properties): Allow the use of a \"@\" marker.\n\t(axes::properties): Add markerorder properties to set the\n\torder of the marker styles for the \"@\" marker.\n\n2010-01-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-mat.cc (SINGLE_TYPE_CONCAT, DO_SINGLE_TYPE_CONCAT,\n\tDO_SINGLE_TYPE_CONCAT_NO_MUTATE): Remove macros.\n\t(single_type_concat, do_single_type_concat,\n\tdo_single_type_concat_no_mutate): New template funcs.\n\t(tree_matrix::rvalue1): Call them here.\n\n2010-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* strfns.cc (do_strcmp_fun,\n\tstrcmp_array_op, strcmp_str_op,\n\tstrcmpi_array_op, strcmpi_str_op,\n\tstrncmp_array_op, strncmp_str_op,\n\tstrncmpi_array_op, strncmpi_str_op): New functions.\n\t(Fstrcmp, Fstrncmp): Reimplement using do_strcmp_fun.\n\t(Fstrcmpi, Fstrncmpi): New defuns.\n\n2010-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/bsxfun.cc (maybe_fill_table): register relational\n\thandlers for char arrays.\n\n2010-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-class.cc (octave_class::numel (const octave_value_list&)): Don't\n\tattempt to query overloaded size.\n\n2010-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn.h (octave_function (const std::string&, const std::string&)):\n\tExplicitly initialize all data members.\n\n\t* ov-builtin.h (octave_builtin::octave_builtin):\n\tExplicitly initialize base class object and data member.\n\n2010-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (read_indexed_images):\n\tNo need to explicitly call chop_trailing_singletons now.\n\n2010-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* oct-obj.cc (octave_value_list::any_cell): Avoid assignment in\n\tcondition of if statement.\n\n2010-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/lu.cc: Avoid test failures if HAVE_QRUPDATE_LUU is\n\tnot defined.\n\n2010-01-12  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (patch::properties): Add \"flat\" value to\n\tmarkeredgecolor and  markerfacecolor properties.\n\n2010-01-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (builtin_type_t): New enum constants: btyp_cell,\n\tbtyp_struct and btyp_func_handle.\n\t(btyp_isinteger, btyp_isfloat, btyp_isarray): New funcs.\n\t(btyp_class_name): New array.\n\t(get_builtin_classes): New func.\n\t* ov-cell.h (octave_cell::builtin_type): New virtual override.\n\t* ov-struct.h (octave_struct::builtin_type): New virtual override.\n\t* ov-fcn-handle.h (octave_fcn_handle::builtin_type): New virtual override.\n\t* symtab.cc (get_dispatch_type): Rewrite. Add overload.\n\t* symtab.h: Update decls.\n\t* ov-fcn-handle.cc (octave_fcn_handle::do_multi_index_op): Rewrite.\n\t(get_builtin_classes): Remove.\n\n2010-01-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-obj.cc (octave_value_list::any_cell): New method.\n\t* oct-obj.h: Declare it.\n\t* utils.cc (do_simple_cellfun): New overloaded function.\n\t* utils.h: Declare it.\n\t* DLD-FUNCTIONS/strfind.cc (Fstrfind): Call it here.\n\t(Fstrrep): Also here.\n\n2010-01-11  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Update DOCSTRINGS rules to avoid\n\tsimple_move_if_change_rule and allow Make to update timestamps.\n\n2010-01-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (curl_handle::lasterror):\n\tAvoid using errno as a local variable name.\n\n2010-01-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lu.cc (Fluupdate): Add tests for LU updating.\n\n2010-01-11  Tatsuro MATSUOKA  <tmacchant@yahoo.co.jp>\n\n\t* Makefile.am (OCTINTERP_LINK_DEPS): Include FT2_LDFLAGS and\n\tFT2_LIBS in the list.\n\n2010-01-09  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/lookup.cc (stri_comp_lt, stri_comp_gt):\n\tComment out unused functions.\n\n\t* oct-stream.cc (BEGIN_S_CONVERSION): Don't declare local tmp\n\tvariable twice.\n\n\t* gl-render.cc (opengl_renderer::draw_image): Avoid shadow\n\tdeclaration warning from GCC.\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (base_graphics_backend):\n\tAvoid unused parameter warning from GCC.\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_mex): Likewise.\n\n\t* data.cc (get_sort_mode_option): Avoid uninitialized variable\n\twarning from GCC.\n\n2010-01-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-obj.h (octave_value_list::operator () const,\n\toctave_value_list::elem const): Return const octave_value&.\n\t* ov.cc (octave_value::function_value,\n\toctave_value::user_function_value, octave_value::user_script_value,\n\toctave_value::user_code_value, octave_value::fcn_handle_value,\n\toctave_value::fcn_inline_value): Declare as const.\n\t* ov.h: Likewise.\n\t* ov-base.h (octave_value::function_value const): Remove overload.\n\t* ov-usr-fcn.h (octave_user_function::function_value const): Likewise.\n\t* ov-builtin.h (octave_builtin::function_value const): Likewise.\n\t* ov-builtin.h (octave_builtin::function_value const): Likewise.\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Take a non-const copy prior to\n\tcalling non-const functions.\n\n\n2010-01-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/strfind.cc (qs_replace): New function.\n\t(Fstrrep): Use it here. Allow S to be a cellstr.\n\n2010-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (cputime): Eliminate Windows-specific code.\n\n2010-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (get_global_value): Fix function name in error message.\n\t(get_top_level_value, set_top_level_value): New functions.\n\t* variables.h (get_top_level_value, set_top_level_value):\n\tProvide decls.\n\n\t* symtab.h (symbol_table::top_level_varref,\n\tsymbol_table::top_level_varval): New static functions.\n\n2010-01-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* utils.cc (octave_sleep (double)): Add OCTAVE_QUIT.\n\n2010-01-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* unwind_protect.h, unwind_protect.cc (unwind_protect): Rewrite.\n\tRemove obsolete macros. Use a simple linked list.\n\n\t* debug.cc (Fdbwhere): Update to new unwind_protect style.\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_oct,\n\t  octave_dynamic_loader::do_load_mex): Ditto.\n\t* error.cc (Flasterror, Flasterr, error_2, warning_1): Ditto.\n\t* graphics.cc (base_graphics_object::remove_all_listeners,\n\t  axes::update_axis_limits, gh_manager::do_execute_callback,\n\t  Fdrawnow): Ditto.\n\t* help.cc (raw_help_from_file): Ditto.\n\t* input.cc (do_keyboard, Fkeyboard, get_debug_input): Ditto.\n\t* load-path.cc (load_path::do_set, execute_pkg_add_or_del,\n\t* ls-mat4.cc (save_mat_binary_data): Ditto.\n\t* ls-mat5.cc (read_mat5_binary_element): Ditto.\n\t* mex.cc (call_mex, mexGetVariable): Ditto.\n\t* oct-hist.cc (do_edit_history, do_run_history): Ditto.\n\t* octave.cc (execute_startup_files, execute_eval_option_code,\n\t  execute_command_line_file): Ditto.\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op): Ditto.\n\t* ov-class.cc (octave_class::subsasgn, octave_class::print_raw):\n\tDitto.\n\t* ov-fcn-handle.cc (octave_fcn_handle::load_ascii,\n\toctave_fcn_handle::load_binary, octave_fcn_handle::load_hdf5): Ditto.\n\t* ov-list.cc (octave_list::print_raw): Ditto.\n\t* ov-mex-fcn.cc (octave_mex_function::do_multi_index_op): Ditto.\n\t* ov-struct.cc (octave_struct::print_raw): Ditto.\n\t* ov-usr-fcn.cc (octave_user_script::do_multi_index_op,\n\t  octave_user_function::do_multi_index_op): Ditto.\n\t* pager.cc (flush_octave_stdout): Ditto.\n\t* pr-output.cc (Frats): Ditto.\n\t* pt-arg-list.cc (tree_argument_list::convert_to_const_vector): Ditto.\n\n\t* pt-eval.cc (tree_evaluator::visit_simple_for_command,\n\ttree_evaluator::visit_complex_for_command,\n\ttree_evaluator::visit_while_command,\n\ttree_evaluator::visit_do_until_command): Update to new unwind_protect\n\tstyle.\n\t(do_catch_code): Remove.\n\t(tree_evaluator::visit_try_catch_command): Simplify. Don't register\n\tcatch code for unwind_protect.\n\t(tree_evaluator::do_unwind_protect_cleanup_code): Make a\n\ttree_evaluator method. Update to new unwind_protect style.\n\t(tree_evaluator::visit_unwind_protect_command): Use explicit try/catch\n\thandling rather than inserting unsafe code into unwind_protect.\n\n\t* pt-eval.h (tree_evaluator::do_unwind_protect_cleanup_code): New decl.\n\t* toplev.cc (main_loop): Update to new unwind_protect style.\n\t  (run_command_and_return_output): Ditto.\n\t* utils.cc (Fisindex): Ditto.\n\t* variables.cc (generate_struct_completions, safe_symbol_lookup,\n\tdo_who): Ditto.\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Ditto.\n\t* DLD-FUNCTIONS/daspk.cc (Fdaspk): Ditto.\n\t* DLD-FUNCTIONS/dasrt.cc (Fdasrt): Ditto.\n\t* DLD-FUNCTIONS/dassl.cc (Fdassl): Ditto.\n\t* DLD-FUNCTIONS/eigs.cc (Feigs): Ditto.\n\t* DLD-FUNCTIONS/lsode.cc (Flsode): Ditto.\n\t* DLD-FUNCTIONS/quad.cc (Fquad): Ditto.\n\t* DLD-FUNCTIONS/rand.cc (Frandn, Frande, Frandg, Frandp): Ditto.\n\t* DLD-FUNCTIONS/typecast.cc (get_data_and_bytesize, Ftypecast): Ditto.\n\t* DLD-FUNCTIONS/urlwrite.cc (Furlwrite, mput_directory,\n\tgetallfiles, F__ftp_mget__): Ditto.\n\n2010-01-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Cell.cc (Cell::cellstr_value): New method.\n\t* Cell.h (Cell::cellstr_value): Declare it.\n\n\t* ov-cell.h (octave_cell::cellstr_cache): Declare as autopointer.\n\t(octave_cell::clear_cellstr_cache): Move here.\n\t* ov-cell.cc (octave_cell::is_cellstr): Only allocate the pointer, but\n\tdon't actually create strings.\n\t(octave_cell::cellstr_value): Use cached test, call\n\tCell::cellstr_value.\n\t(octave_cell::make_cellstr_cache): Remove.\n\n2010-01-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (AM_CPPFLAGS): Include -I../libgnu in the list.\n\n2010-01-04  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* graphics.cc (graphics_object::set (const Octave_map&)): New function.\n\t(graphics_object::set (const Array<std::string>&, const Cell&,\n\toctave_idx_type)):  New function.\n\t(graphics_object::set_value_or_default (const caseless_str&,\n\tconst octave_value&)): New function.\n\t(graphics_object::set (const octave_value_list&)):\n\tCall set_value_or_default to set property values.\n\t(Fset): Handle struct and cell array arguments.\n\tNew tests.\n\t* graphics.h.in (graphics_objects::set): Provide decls.\n\n2010-01-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/strfind.cc (qs_search): Optionally discard overlaps.\n\tReturn result as Array<octave_idx_type>.\n\t(Fstrfind): Use octave_value (Array<octave_idx_type>) constructor.\n\t(Fstrrep): New function.\n\n2010-01-04  John W. Eaton  <jwe@octave.org>\n\n\t* lex.ll (can_be_command): New function.\n\t(handle_identifier): Use it.\n\n2010-01-04  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* Makefile.am (install-oct): Write $(DESTDIR)$(...), not\n\t$(DESTDIR).$(...).\n\n2010-01-02  Ben Abbott  <bpabbott@mac.com>\n\n\t* mappers.cc: Change test tolerance from 1e-16 to eps.\n\n2009-12-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (scalar_query_helper): Remove.\n\t(can_extract): New overloaded helper function.\n\t(scalar_col_helper_nda): Rewrite using can_extract and\n\toctave_value_extract. Instantiate for integer types.\n\t(make_col_helper): Support integer types.\n\n\n2009-12-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Fix tests.\n\n2009-12-28  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* DLD-FUNCTIONS/md5sum.cc, DLD-FUNCTIONS/lookup.cc: Include\n\tconfig.h before another header file.\n\n2009-12-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (xgl2ps.c): New file.\n\t(EXTRA_DIST): Include gl2ps.c in the list.\n\t(DIST_SRC): Include xgl2ps.c in the list instead of gl2ps.c.\n\n2009-12-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (decode_subscripts): Move to utils.cc.\n\t* utils.cc (decode_subscripts): New func.\n\t* utils.h: Declare it.\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Optimize the\n\t`cellfun (@subsref, args, {subs}, \"uniformoutput\", true)' case.\n\n2009-12-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* gripes.cc (gripe_nonbraced_cs_list_assignment): New function.\n\t* gripes.h: Declare it.\n\t* ov-cell.cc (octave_cell::subsasgn): Use it here.\n\t* ov-struct.cc (octave_struct::subsasgn): Also here.\n\t* pt-idx.cc (tree_simple_assignment::rvalue1): And here. Check for\n\tsingle lhs value.\n\n2009-12-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-str-mat.h (octave_char_matrix_str::is_matrix_type): Remove\n\toverride.\n\t* data.cc (Fismatrix): Update test.\n\n2009-12-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/strfind.cc: New source.\n\t* DLD-FUNCTIONS/module-files: Add it here.\n\n2009-12-23  John W. Eaton  <jwe@octave.org>\n\n\t* lex.ll: Use %top block to include config.h.\n\n2009-12-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/max.cc (do_cumminmax_body): Support also btyp_bool.\n\n2009-12-22  Rob Mahurin  <octave@tertiarysource.net>\n\n\t* find-defun-files.sh: Use SED and EGREP as returned by configure.\n\n2009-12-20  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_sindow::set_name): New method.\n\t(figure_manager::set_name, figure_manage::do_set_name): New methods.\n\t(fltk_backend::property_changed): Handle change of figure title string.\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Eliminate TOPDIR variable in favor of built-in automake\n\tvariables of top_builddir and top_srcdir.\n\n2009-12-18  David Grundberg  <davidg@cs.umu.se>\n\n\t* ov-usr-fcn.cc (octave_user_script::do_multi_index_op):\n\tPrint script filename in script indexing errors.\n\t(octave_user_script::subsref): Ditto.\n\n2009-12-18  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (get_debug_input): Don't attempt to get user input\n\tunless stdin is a tty.  Force interactive input mode when\n\treading debugging input.\n\t(octave_gets): Bypass readline if get_input_from_eval_string is true.\n\n\t* input.cc, input.h (stdin_is_tty): New variable.\n\t* octave.cc (octave_main): Set it to true if stdin is not a tty.\n\n2009-12-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/max.cc (do_minmax_red_op<boolNDArray>): New\n\tspecialization.\n\t(do_minmax_body): Handle btyp_bool.\n\n2009-12-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.cc (symbol_table::cleanup): Call clear_variables rather than\n\tclear_all on the top and global scopes.\n\n2009-12-16  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (F__init_fltk__):\n\tAdd __remove_fltk__ to the list of atexit functions.\n\t(F__remove_fltk__): Wait fltk_maxtime instead of 10 seconds.\n\n2009-12-15  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (do_goto_frame_relative): Stop searching at top\n\tstack frame even though it is not a function.\n\n2009-12-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Preserve original nargout. Call\n\tfunctions with this value. Use nargout1 to possibly accumulate extra\n\toutputs, as long as they are defined.\n\n2009-12-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-range.cc (octave_range::do_index_op): Defer single subscript to\n\tnew Range methods.\n\n2009-12-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.cc (symbol_table::cleanup): New static method.\n\t* symtab.h: Declare it.\n\t* toplev.cc (clean_up_and_exit): Call it here.\n\n2009-12-12  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::toggle_grid,\n\tplot_window::axis_auto): Modify the axes of the correct figure.\n\n2009-12-12  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::plot_window):\n\tHandle case where window is created but not visible. Cache\n\twindow label.\n\t(figure_manager::toggle_window_visibility,\n\t(figure_manager::do_toggle_window_visibility): New methods.\n\t(fltk_backend::property_change): Handle figure visibility change.\n\n2009-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (base_properties::all_dynamic_properties):\n\tNo longer static.\n\t(base_properties::set (const caseless_str&, const octave_value&)):\n\tOnly provide decl, not definition.\n\t(base_properties::set (const caseless_str&, const std::string&,\n\tconst octave_value&)): Delete.\n\t(base_properties::dynamic_properties): Rename from\n\tall_dynamic_properties.  No longer static.  Now protected.\n\t(base_properties::has_dynamic_property,\n\tbase_properties::dynamic_property_names,\n\tbase_properties::set_dynamic): Omit class name argument.\n\t* graphics.cc (base_properties::all_dynamic_properties):\n\tDelete obsolete definition.\n\t(base_properties::dynamic_property_names): Now const.\n\tOmit class name argument.  Simply return dynamic_properties set.\n\t(base_properties::has_dynamic_property): Omit class name argument.\n\tSimply return dynamic_properties set.  Don't pass class name to\n\tdynamic_property_names function.\n\t(base_properties::set_dynamic): Omit class name argument.\n\tDynamic_properties is no longer a map.\n\n\t* genprops.awk: Omit class name from arguments of generated\n\tbase_properties::all_property_names and base_properties::set\n\tfunctions.  Don't pass class name to base_properties::set in\n\tgenerated derived class set functions.\n\n2009-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (DOCSTRINGS): Use $(cp_update_rule) instead of\n\tcp -a --update.\n\n2009-12-10  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: distclean symbolic links for OCT_FILES\n\n2009-12-10  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Copy DOCSTRINGS from srcdir to builddir if it does not\n\texist.  Enables VPATH builds.\n\n2009-12-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-dld-fcn.h (octave_dld_function::get_shlib): New method.\n\t* ov-mex-fcn.h (octave_mex_function::get_shlib): New method.\n\t* defun.cc (get_current_shlib): New function.\n\t* defun-int.h: Declare it.\n\t(octave_auto_shlib): New class.\n\n2009-12-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.cc (out_of_date_check): Try also autoloads.\n\n2009-12-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.h (symbol_table::fcn_info::clear_autoload_function):\n\tNew method.\n\t(symbol_table::clear_dld_function): New method.\n\t* dynamic-ld.cc (octave_shlib_list::do_remove): Switch order of stmts.\n\t(octave_mex_file_list::do_remove): Likewise.\n\t(do_clear_function): Call symbol_table::clear_dld_function.\n\t(octave_dynamic_loader::do_load_oct): Don't use\n\toctave_shlib::mark_relative.\n\t(octave_dynamic_loader::do_load_mex): Ditto.\n\n2009-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (fopen_mode_to_ios_mode): Allow \"+\" at the end of\n\tmodestrings like \"rb+\".\n\n2009-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (BEGIN_C_CONVERSION, BEGIN_S_CONVERSION):\n\tStore characters directly in appropriately sized std::string object.\n\t(FINISH_CHARACTER_CONVERSION): Do store ASCII NUL values.\n\n2009-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc: Style fixes.\n\n2009-12-09  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::print): Print immediatly.\n\n2009-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* gl2ps-renderer.cc (draw_pixels): New template function.\n\t(opengl_renderer::draw_pixels): Use it.\n\n2009-12-09  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* gl2ps.c, gl2ps.h: Use upstream version gl2ps-1.3.5-svn-20091202.\n\n\t* gl-render.cc (opengl_renderer::draw_pixels): New function.\n\t(opengl_renderer::draw_image): Correctly handle images with width\n\tor height of 1.  Use draw_pixels.\n\t* gl-render.h (opengl_renderer::draw_pixels): Provide decl.\n\n\t* gl2ps-renderer.cc (glps_renderer::draw_pixels): New function.\n\t* gl2ps-renderer.h (glps_renderer::draw_pixels): Provide decl.\n\n2009-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc: Call nstrftime instead of my_strftime.\n\n2009-12-09  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc: Include strftime.h.\n\t(write_header): Call my_strftime instead of strftime.\n\n\t* Makefile.am (AM_CPPFLAGS): Add -I$(top_srcdir)/libgnu to the list.\n\t(OCTAVE_LIBS, OCTINTERP_LINK_DEPS, OCT_LINK_DEPS):\n\tAdd ../libgnu/libgnu.la to the list.\n\n2009-12-09  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Distribute DOCSTRINGS in tar.gz file\n\n2009-12-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dirfns.cc (Ffnmatch): Simplify.\n\n2009-12-08  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* ov-ch-mat.cc: Add missing #include.\n\t* oct-stream.cc (do_read): Simplify.\n\t* gl-render.h: Undef min and max after #including windows.h.\n\n2009-12-08  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (gendoc.cc): Don't pass $(srcdidr) to mkgendoc.\n\n2009-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-b-b.cc, OPERATORS/op-b-bm.cc,\n\tOPERATORS/op-b-sbm.cc, OPERATORS/op-bm-b.cc,\n\tOPERATORS/op-bm-bm.cc, OPERATORS/op-bm-sbm.cc,\n\tOPERATORS/op-cdm-cdm.cc, OPERATORS/op-cdm-cm.cc,\n\tOPERATORS/op-cdm-cs.cc, OPERATORS/op-cdm-dm.cc,\n\tOPERATORS/op-cdm-m.cc, OPERATORS/op-cdm-s.cc,\n\tOPERATORS/op-cell.cc, OPERATORS/op-chm.cc,\n\tOPERATORS/op-class.cc, OPERATORS/op-cm-cdm.cc,\n\tOPERATORS/op-cm-cm.cc, OPERATORS/op-cm-cs.cc,\n\tOPERATORS/op-cm-dm.cc, OPERATORS/op-cm-m.cc,\n\tOPERATORS/op-cm-pm.cc, OPERATORS/op-cm-s.cc,\n\tOPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc,\n\tOPERATORS/op-cs-cm.cc, OPERATORS/op-cs-cs.cc,\n\tOPERATORS/op-cs-m.cc, OPERATORS/op-cs-s.cc,\n\tOPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc,\n\tOPERATORS/op-dm-cdm.cc, OPERATORS/op-dm-cm.cc,\n\tOPERATORS/op-dm-cs.cc, OPERATORS/op-dm-dm.cc,\n\tOPERATORS/op-dm-m.cc, OPERATORS/op-dm-s.cc,\n\tOPERATORS/op-dm-scm.cc, OPERATORS/op-dm-sm.cc,\n\tOPERATORS/op-dm-template.cc, OPERATORS/op-dms-template.cc,\n\tOPERATORS/op-double-conv.cc, OPERATORS/op-fcdm-fcdm.cc,\n\tOPERATORS/op-fcdm-fcm.cc, OPERATORS/op-fcdm-fcs.cc,\n\tOPERATORS/op-fcdm-fdm.cc, OPERATORS/op-fcdm-fm.cc,\n\tOPERATORS/op-fcdm-fs.cc, OPERATORS/op-fcm-fcdm.cc,\n\tOPERATORS/op-fcm-fcm.cc, OPERATORS/op-fcm-fcs.cc,\n\tOPERATORS/op-fcm-fdm.cc, OPERATORS/op-fcm-fm.cc,\n\tOPERATORS/op-fcm-fs.cc, OPERATORS/op-fcm-pm.cc,\n\tOPERATORS/op-fcs-fcm.cc, OPERATORS/op-fcs-fcs.cc,\n\tOPERATORS/op-fcs-fm.cc, OPERATORS/op-fcs-fs.cc,\n\tOPERATORS/op-fdm-fcdm.cc, OPERATORS/op-fdm-fcm.cc,\n\tOPERATORS/op-fdm-fcs.cc, OPERATORS/op-fdm-fdm.cc,\n\tOPERATORS/op-fdm-fm.cc, OPERATORS/op-fdm-fs.cc,\n\tOPERATORS/op-float-conv.cc, OPERATORS/op-fm-fcdm.cc,\n\tOPERATORS/op-fm-fcm.cc, OPERATORS/op-fm-fcs.cc,\n\tOPERATORS/op-fm-fdm.cc, OPERATORS/op-fm-fm.cc,\n\tOPERATORS/op-fm-fs.cc, OPERATORS/op-fm-pm.cc,\n\tOPERATORS/op-fs-fcm.cc, OPERATORS/op-fs-fcs.cc,\n\tOPERATORS/op-fs-fm.cc, OPERATORS/op-fs-fs.cc,\n\tOPERATORS/op-i16-i16.cc, OPERATORS/op-i32-i32.cc,\n\tOPERATORS/op-i64-i64.cc, OPERATORS/op-i8-i8.cc,\n\tOPERATORS/op-int-concat.cc, OPERATORS/op-int-conv.cc,\n\tOPERATORS/op-list.cc, OPERATORS/op-m-cdm.cc,\n\tOPERATORS/op-m-cm.cc, OPERATORS/op-m-cs.cc,\n\tOPERATORS/op-m-dm.cc, OPERATORS/op-m-m.cc, OPERATORS/op-m-pm.cc,\n\tOPERATORS/op-m-s.cc, OPERATORS/op-m-scm.cc,\n\tOPERATORS/op-m-sm.cc, OPERATORS/op-pm-cm.cc,\n\tOPERATORS/op-pm-fcm.cc, OPERATORS/op-pm-fm.cc,\n\tOPERATORS/op-pm-m.cc, OPERATORS/op-pm-pm.cc,\n\tOPERATORS/op-pm-scm.cc, OPERATORS/op-pm-sm.cc,\n\tOPERATORS/op-pm-template.cc, OPERATORS/op-range.cc,\n\tOPERATORS/op-s-cm.cc, OPERATORS/op-s-cs.cc, OPERATORS/op-s-m.cc,\n\tOPERATORS/op-s-s.cc, OPERATORS/op-s-scm.cc,\n\tOPERATORS/op-s-sm.cc, OPERATORS/op-sbm-b.cc,\n\tOPERATORS/op-sbm-bm.cc, OPERATORS/op-sbm-sbm.cc,\n\tOPERATORS/op-scm-cm.cc, OPERATORS/op-scm-cs.cc,\n\tOPERATORS/op-scm-m.cc, OPERATORS/op-scm-s.cc,\n\tOPERATORS/op-scm-scm.cc, OPERATORS/op-scm-sm.cc,\n\tOPERATORS/op-sm-cm.cc, OPERATORS/op-sm-cs.cc,\n\tOPERATORS/op-sm-m.cc, OPERATORS/op-sm-s.cc,\n\tOPERATORS/op-sm-scm.cc, OPERATORS/op-sm-sm.cc,\n\tOPERATORS/op-str-m.cc, OPERATORS/op-str-s.cc,\n\tOPERATORS/op-str-str.cc, OPERATORS/op-struct.cc,\n\tOPERATORS/op-ui16-ui16.cc, OPERATORS/op-ui32-ui32.cc,\n\tOPERATORS/op-ui64-ui64.cc, OPERATORS/op-ui8-ui8.cc:\n\tDelete Emacs local-variable settings.\n\n2009-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-pm-sm.cc, OPERATORS/op-pm-scm.cc,\n\tOPERATORS/op-dm-sm.cc, OPERATORS/op-dm-scm.cc,\n\tOPERATORS/op-fs-fm.cc, OPERATORS/op-fs-fcm.cc,\n\tOPERATORS/op-fs-fcs.cc, OPERATORS/op-fm-fm.cc,\n\tOPERATORS/op-fm-fcs.cc, OPERATORS/op-fm-fcm.cc,\n\tOPERATORS/op-fcs-fs.cc, OPERATORS/op-fcs-fm.cc,\n\tOPERATORS/op-fcs-fcm.cc, OPERATORS/op-fcm-fs.cc,\n\tOPERATORS/op-fcm-fm.cc, OPERATORS/op-fm-fs.cc,\n\tOPERATORS/op-fcm-fcm.cc, OPERATORS/op-class.cc,\n\tOPERATORS/op-fcm-fcs.cc, OPERATORS/op-str-str.cc,\n\tOPERATORS/op-str-s.cc, OPERATORS/op-str-m.cc,\n\tOPERATORS/op-struct.cc, OPERATORS/op-sm-scm.cc,\n\tOPERATORS/op-sm-s.cc, OPERATORS/op-sm-sm.cc,\n\tOPERATORS/op-sm-cs.cc, OPERATORS/op-sm-cm.cc,\n\tOPERATORS/op-scm-sm.cc, OPERATORS/op-scm-scm.cc,\n\tOPERATORS/op-scm-s.cc, OPERATORS/op-scm-m.cc,\n\tOPERATORS/op-scm-cs.cc, OPERATORS/op-sm-m.cc,\n\tOPERATORS/op-sbm-sbm.cc, OPERATORS/op-scm-cm.cc,\n\tOPERATORS/op-sbm-bm.cc, OPERATORS/op-s-sm.cc,\n\tOPERATORS/op-s-scm.cc, OPERATORS/op-sbm-b.cc,\n\tOPERATORS/op-m-scm.cc, OPERATORS/op-m-sm.cc,\n\tOPERATORS/op-m-cm.cc, OPERATORS/op-int.h,\n\tOPERATORS/op-int-conv.cc, OPERATORS/op-int-concat.cc,\n\tOPERATORS/op-cs-sm.cc, OPERATORS/op-cs-scm.cc,\n\tOPERATORS/op-cm-sm.cc, OPERATORS/op-cs-cs.cc,\n\tOPERATORS/op-cm-m.cc, OPERATORS/op-cm-scm.cc,\n\tOPERATORS/op-cm-cm.cc, OPERATORS/op-chm.cc,\n\tOPERATORS/op-cell.cc, OPERATORS/op-bm-sbm.cc,\n\tOPERATORS/op-bm-bm.cc, OPERATORS/op-bm-b.cc,\n\tOPERATORS/op-b-sbm.cc, OPERATORS/op-fcs-fcs.cc:\n\tUntabify.\n\n2009-12-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Makefile.am: Build OPT_HANDLERS before DEF_FILES.\n\n2009-12-06  Rik  <rik@nomad.inbox5.com>\n\n\t* Makefile.am: Distribute DOCSTRINGS so that documentation will\n\tnot require rebuild after merely untarring a distribution.\n\n2009-12-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Document complexity.\n\n2009-12-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (do_numeric_lookup): Rewrite.\n\t(Flookup): Simplify string part. Use Array<std::string>::lookup.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (curl_handle::init): Always use\n\tCURLOPT_USERPWD instead of CURLOPT_USER and CURLOPT_PASSWD.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* version.h.in (OCTAVE_API_VERSION_NUMBER): New macro.\n\t* Makefile.am (version.h): Substitute OCTAVE_API_VERSION_NUMBER.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (mkdefs): New arguments, srcdir and file.\n\tGenerate output here.  (.cc.df): Not here.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (BUILT_SOURCES): Include graphics-props.cc in the\n\tlist.\n\n2009-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (liboctinterp_la_SOURCES): Remove $(OPT_HANDLERS)\n\tfrom the list.\n\n2009-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (CLEANFILES): Include DLD-FUNCTIONS/PKG_ADD,\n\tdoc-files, gendoc.cc, gendoc$(BUILD_EXEEXT), graphics-props.cc,\n\toct-parse.output, $(BUILT_NODISTFILES) in the list.  Remove\n\t$(BUILT_SOURCES) from the list.  (MAINTAINERCLEANFILES): New\n\tvariable.  (BUILT_DISTFILES): Remove oct-parse.cc and lex.cc\n\tfrom the list.  (BUILT_NODISTFILES): Include defaults.h,\n\tgraphics.h, oct-conf.h, oct-errno.cc, ops.cc, mxarray.h, and\n\tversion.h in the list.  Remove $(OPT_INC) from the list.\n\t(BUILT_SOURCES): Include mxarray.h and version.h in the list.\n\t(EXTRA_DIST): Include version.h.in in the list.  (.cc.df): Don't\n\tsilence rules.  Omit $(srcdir) from XDEFUN_FILE_NAME.\n\t($(DEF_FILES)): Depend on mkdefs and Makefile.  (mxarray.h,\n\tversion.h): New rules.  (DLD-FUNCTIONS/PKG_ADD): Don't silence\n\trules.  (builtins.cc, DOCSTRINGS, gendoc.cc, ops.cc,\n\t$(OPT_HANDLERS)) oct-errno.cc, oct-gperf.h): Don't silence\n\trules.  (doc-files, defaults.h, oct-conf.h): Don't silence\n\trules.\n\n\t* mxarray.h.in, version.h.in: Use % to delimit substitutions,\n\tnot @.\n\n\t* mkbuiltins: Operate on a list of files passed as arguments.\n\n\t* genprops.awk: Write either graphics.h or graphics-props.cc to\n\tstdout instead of graphics.h simultaneously with\n\tgraphics-props.cc ot a file.  * Makefile.am (graphics.h,\n\tgraphics-props.cc): Split into two separate rules.\n\n\t* find-defun-files.sh: Omit directory part from .df file names.\n\tOperate on .ll and .yy files instead of generated .cc files.\n\n2009-12-02  Rik  <rik@nomad.inbox5.com>\n\n\t* DLD-FUNCTIONS/urlwrite.cc: Correctly compile code even when\n\tlibcurl is not present according to configure.\n\n2009-12-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-bool-mat.h (octave_bool_matrix::octave_bool_matrix (const\n\tboolNDArray&, const idx_vector&)): New constructor.\n\t* ov-re-mat.h (octave_bool_matrix::octave_bool_matrix (const\n\tNDArray&, const idx_vector&)): Simplify.\n\t* ov.cc (octave_value::octave_value (const idx_vector&)): Allow\n\tthe mask case.\n\t* DLD-FUNCTIONS/find.cc (Ffind): Explicitly call unmask.\n\n2009-11-30  Kacper Kowalik  <xarthisius.kk@gmail.com>\n\n\t* oct-hdf5.h: Drop force the use of the v1.6 API * ls-hdf5.cc,\n\tov-base-int.cc, ov-bool-mat.cc, ov-bool-sparse.cc, ov-bool.cc,\n\tov-cell.cc, ov-class.cc, ov-complex.cc, ov-cx-mat.cc,\n\tov-cx-sparse.cc, ov-fcn-handle.cc, ov-fcn-inline.cc,\n\tov-float.cc, ov-flt-complex.cc, ov-flt-cx-mat.cc,\n\tov-flt-re-mat.cc, ov-list.cc, ov-range.cc, ov-re-mat.cc,\n\tov-re-sparse.cc, ov-scalar.cc, ov-str-mat.cc, ov-struct.cc:\n\tAllow v1.8 API versions of hdf5 functions.\n\n2009-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fft2.cc (Fifft2): Docstring fix.\n\n2009-11-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-unop.cc (tree_prefix_expression::rvalue1): Try to use\n\toctave_value::do_non_const_unary_op.\n\n2009-11-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (curl_handle::init): Use\n\tCURLOPT_USERPWD if libcurl ver < 7.19.0.\n\n2009-11-28  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* gl-render.cc (opengl_renderer::draw_image): Handle indexed\n\timages.\n\n2009-11-28  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* gl-render.h (opengl_renderer::draw): Draw children from end of\n\tlist to preserve correct stacking order (first child should be\n\ton top).\n\n\t* graphics.cc (maybe_set_children): Store sorted child lists.\n\n2009-11-27  Kacper Kowalik  <xarthisius.kk@gmail.com>\n\n\t* ls-hdf5.cc (have_h5giterate_bug): Drop this group iteration\n\tflag for buggy pre 1.2.2 versions of hdf5.  * ov-base-int.cc\n\t(octave_base_int_matrix<T>::load_hdf5)\n\toctave_base_int_scalar<T>::load_hdf5), ov-base-int.h\n\t(octave_base_int_matrix<T>::load_hdf5,\n\toctave_base_int_scalar<T>::load_hdf5), ov-base.cc\n\t(octave_base_value::load_hdf5), ov-base.h\n\t(octave_base_value::load_hdf5), ov-bool-mat.cc\n\t(octave_bool_matrix::load_hdf5), ov-bool-mat.h\n\t(octave_bool_matrix::load_hdf5), ov-bool-sparse.cc\n\t(octave_sparse_bool_matrix::load_hdf5), ov-bool-sparse.h\n\t(octave_sparse_bool_matrix::load_hdf5), ov-bool.cc\n\t(octave_bool::load_hdf5), ov-bool.h (octave_bool::load_hdf5),\n\tov-cell.cc (octave_cell::load_hdf5), ov-cell.h\n\t(octave_cell::load_hdf5), ov-class.cc (octave_class::load_hdf5),\n\tov-class.h (octave_class::load_hdf5), ov-complex.cc\n\t(octave_complex::load_hdf5), ov-complex.h\n\t(octave_complex::load_hdf5), ov-cx-mat.cc\n\t(octave_complex_matrix::load_hdf5), ov-cx-mat.h\n\t(octave_complex_matrix::load_hdf5), ov-cx-sparse.cc\n\t(octave_sparse_complex_matrix::load_hdf5), ov-cx-sparse.h\n\t(octave_sparse_complex_matrix::load_hdf5), ov-fcn-handle.cc\n\t(octave_fcn_handle::load_hdf5), ov-fcn-handle.h\n\t(octave_fcn_handle::load_hdf5), ov-fcn-inline.cc\n\t(octave_fcn_inline::load_hdf5), ov-fcn-inline.h\n\t(octave_fcn_inline::load_hdf5), ov-float.cc\n\t(octave_float_scalar::load_hdf5), ov-float.h\n\t(octave_float_scalar::load_hdf5), ov-flt-complex.cc\n\t(octave_float_complex::load_hdf5), ov-flt-complex.h\n\t(octave_float_complex::load_hdf5), ov-flt-cx-mat.cc\n\t(octave_float_complex_matrix::load_hdf5), ov-flt-cx-mat.h\n\t(octave_float_complex_matrix::load_hdf5), ov-flt-re-mat.cc\n\t(octave_float_matrix::load_hdf5), ov-flt-re-mat.h\n\t(octave_float_matrix::load_hdf5), ov-list.cc\n\t(octave_list::load_hdf5), ov-list.h (octave_list::load_hdf5),\n\tov-range.cc (octave_range::load_hdf5), ov-range.h\n\t(octave_range::load_hdf5), ov-re-mat.cc\n\t(octave_matrix::load_hdf5), ov-re-mat.h\n\t(octave_matrix::load_hdf5), ov-re-sparse.cc\n\t(octave_sparse_matrix::load_hdf5), ov-re-sparse.h\n\t(octave_sparse_matrix::load_hdf5), ov-scalar.cc\n\t(octave_scalar::load_hdf5), ov-scalar.h\n\t(octave_scalar::load_hdf5), ov-str-mat.cc\n\t(octave_char_matrix_str::load_hdf5), ov-str-mat.h\n\t(octave_char_matrix_str::load_hdf5), ov-struct.cc\n\t(octave_struct::load_hdf5), ov-struct.h\n\t(octave_struct::load_hdf5), ov.h (octave_value::load_hdf5):\n\tRemove have_hg5iterate_bug from the call to load_hdf5.\n\t* ov-cell.cc (octave_bool::load_hdf5), ov-class.cc\n\t(octave_class::load_hdf5), ov-fcn-handle.cc\n\t(octave_fcn_handle::load_hdf5), ov-list.cc\n\t(octave_list::load_hdf5), ov-struct.cc\n\t(octave_struct::load_hdf5): Remove HAVE_H5GGET_NUM_OBJS cruft\n\tfor old hdf5 versions.\n\n2009-11-27  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (curl_handle, curl_handles): Add\n\tclasses to manage the open curl connections.  (F__ftp__,\n\tF__ftp_pwd__, F__ftp_cwd__, F__ftp_dir__, F__ftp_ascii__,\n\tF__ftp_binary__, F__ftp_close__, F__ftp_mode__, F__ftp_delete__,\n\tF__ftp_rmdir__, F__ftp_mkdir__, F__ftp_rename__, F__ftp_mput__,\n\tF__ftp_mget__): New functions.\n\n2009-11-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::octave_value (const index_vector&)): Take\n\ta copy if idx to allow mutation.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/dot.cc (Fdot): Update docs.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/dot.cc: New source.\n\t* DLD-FUNCTIONS/module-files: Include it.\n\n2009-11-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fismatrix): Return true for empty matrices as well.\n\n2009-11-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/chol.cc (get_chol_l): New helper function.\n\t(Fchol): Use it to set MatrixType for lower triangular factors\n\tas well. Use default octave_idx_type->octave_value conversion.\n\n2009-11-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (do_accumarray_sum): Simplify.\n\n2009-11-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-struct.cc (octave_struct::save_binary): Save dimensions for\n\tstructs.  (octave_struct::load_binary): Load dimensions if\n\tpresent, use 1x1 otherwise.\n\n2009-11-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fmerge): Add missing parentheses.\n\n2009-11-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-complex.h (octave_complex::bool_value,\n\toctave_complex::bool_array_value): New methods.\n\t* ov-flt-complex.h (octave_float_complex::bool_value,\n\toctave_float_complex::bool_array_value): New methods.\n\t* ov-cx-mat.cc (octave_complex_matrix::bool_array_value): New\n\tmethod.  * ov-cx-mat.h: Declare it.\n\t* ov-flt-cx-mat.cc (octave_float_complex_matrix::bool_array_value):\n\tNew method.\n\t* ov-flt-cx-mat.h: Declare it.\n\n2009-11-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-struct.cc (octave_struct::save_ascii): Save dimensions for\n\tstructs.  (octave_struct::load_ascii): Load dimensions if\n\tpresent, use 1x1 otherwise.\n\n2009-11-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fmerge): Correct query for logical masks.\n\n2009-11-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* utils.cc (dims_to_numel): Fallback to index_vector query for\n\tnon-numeric types.\n\n2009-11-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-bool.h (octave_bool::is_numeric_type): New overload.\n\t* ov-bool-mat.h (octave_bool-matrix::is_numeric_type): New overload.\n\n2009-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (unary_mapper_t): New member: umap_erfinv.\n\t* ov-base.c (octave_base_value::get_umap_name): Add \"erfinv\" here.\n\t* ov.h (octave_value::erfinv): New method.\n\t* ov-scalar.cc (octave_scalar::map): Handle umap_erfinv.\n\t* ov-float.cc (octave_float::map): Ditto.\n\t* ov-re-mat.cc (octave_matrix::map): Ditto.\n\t* ov-flt-re-mat.cc (octave_float_matrix::map): Ditto.\n\t* ov-re-sparse.cc (octave_sparse_matrix::map): Ditto.\n\t* mappers.cc (Ferfinv): New DEFUN.\n\n2009-11-14  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* gl-render.cc (opengl_renderer::text_to_pixels): New function\n\tfrom code in render_text to produce the pixels and compute\n\tbounding box.  (opengl_renderer::render_text): Call\n\ttext_to_pixels to compute rotation mode and bounding box.\n\t* gl-renger.h (opengl_renderer::text_to_pixels): Provide decl.\n\t* gl2ps-renderer.cc (glps_renderer::render_text): Call\n\ttext_to_pixels to compute bounding box.\n\t(glps_renderer::set_font): Call opengl_renderer::set_font.\n\n2009-11-18  Michael Godfrey  <godfrey@isl.stanford.edu>\n\n\t* txt-eng-ft.cc: Relax font match test.\n\n2009-11-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/bsxfun.cc (bsxfun_builtin_op): New member:\n\tbsxfun_builtin_power.  (bsxfun_builtin_names): Include \"power\".\n\t(do_bsxfun_real_pow): New static function.  (maybe_fill_table):\n\tRegister power handlers.\n\n2009-11-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-complex.cc (octave_complex::try_narrowing_conversion):\n\tDon't check signbit.\n\t* ov-flt-complex.cc\n\t(octave_float_complex::try_narrowing_conversion): Ditto.\n\t* ov-cx-mat.cc (octave_complex_matrix::try_narrowing_conversion):\n\tSimplify.  Don't check signbit.\n\t* ov-flt-cx-mat.cc\n\t(octave_float_complex_matrix::try_narrowing_conversion): Ditto.\n\n2009-11-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-mat.cc (do_rc_map): New static function.\n\t(octave_matrix::map): Use it here.\n\t* ov-flt-re-mat.cc (do_rc_map): New static function.\n\t(octave_float_matrix::map): Use it here.\n\n2009-11-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/balance.cc: Fix docs.\n\n2009-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (liboctinterp_la_CPPFLAGS): Define.\n\n2009-11-13  Joel Keay  <keay@ou.edu>\n\n\t* graphics.h.in (image::properties::init): Also allow single,\n\tint16, and uint16 data types.\n\n2009-11-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (unary_mapper_t): Move to octave_base_value.\n\t* ov.h: Partially revert to c657c056240d.\n\t(FORWARD_MAPPER): Update to use octave_base_value::map.\n\t(octave_value::map): Ditto.\n\t* mappers.cc: Revert to c657c056240d.\n\t* data.cc: Ditto.\n\t* Cell.h, Cell.cc: Ditto.\n\t* ov-cell.cc (octave_cell::map): Rewrite.\n\t* ov-base-sparse.cc (octave_base_sparse::map): New method.\n\t* ov-base-sparse.h: Declare it.\n\t* ov-re-sparse.cc (octave_sparse_matrix::map): Use it as a fallback.\n\t* ov-cx-sparse.cc (octave_sparse_complexmatrix::map): Ditto.\n\n2009-11-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (unary_mapper_t): New enum.\n\t(octave_base_value::map (unary_mapper_t)): New method.\n\t(octave_base_value::abs, octave_base_value::acos,\n\toctave_base_value::acosh, octave_base_value::angle,\n\toctave_base_value::arg, octave_base_value::asin,\n\toctave_base_value::asinh, octave_base_value::atan,\n\toctave_base_value::atanh, octave_base_value::ceil,\n\toctave_base_value::conj, octave_base_value::cos,\n\toctave_base_value::cosh, octave_base_value::erf,\n\toctave_base_value::erfc, octave_base_value::exp,\n\toctave_base_value::expm1, octave_base_value::finite,\n\toctave_base_value::fix, octave_base_value::floor,\n\toctave_base_value::gamma, octave_base_value::imag,\n\toctave_base_value::isinf, octave_base_value::isna,\n\toctave_base_value::isnan, octave_base_value::lgamma,\n\toctave_base_value::log, octave_base_value::log2,\n\toctave_base_value::log10, octave_base_value::log1p,\n\toctave_base_value::real, octave_base_value::round,\n\toctave_base_value::roundb, octave_base_value::signum,\n\toctave_base_value::sin, octave_base_value::sinh,\n\toctave_base_value::sqrt, octave_base_value::tan,\n\toctave_base_value::tanh): Remove.\n\n\t* ov.h (octave_value::map (unary_mapper_t)): New method.\n\t(octave_value::abs, octave_value::acos, octave_value::acosh,\n\toctave_value::angle, octave_value::arg, octave_value::asin,\n\toctave_value::asinh, octave_value::atan, octave_value::atanh,\n\toctave_value::ceil, octave_value::conj, octave_value::cos,\n\toctave_value::cosh, octave_value::erf, octave_value::erfc,\n\toctave_value::exp, octave_value::expm1, octave_value::finite,\n\toctave_value::fix, octave_value::floor, octave_value::gamma,\n\toctave_value::imag, octave_value::isinf, octave_value::isna,\n\toctave_value::isnan, octave_value::lgamma, octave_value::log,\n\toctave_value::log2, octave_value::log10, octave_value::log1p,\n\toctave_value::real, octave_value::round, octave_value::roundb,\n\toctave_value::signum, octave_value::sin, octave_value::sinh,\n\toctave_value::sqrt, octave_value::tan, octave_value::tanh): Remove.\n\n\t* ov-scalar.h, ov-scalar.cc (octave_scalar): Update.\n\t* ov-float.h, ov-float.cc (octave_float): Update.\n\n\t* ov-complex.h, ov-complex.cc (octave_complex): Update.\n\t* ov-flt-complex.h, ov-flt-complex.cc (octave_float_complex):\n\tUpdate.\n\n\t* ov-re-matrix.h, ov-re-matrix.cc (octave_matrix): Update.\n\t* ov-flt-re-matrix.h, ov-flt-re-matrix.cc (octave_float_matrix): Update.\n\t* ov-cx-matrix.h, ov-cx-matrix.cc (octave_complex_matrix): Update.\n\t* ov-flt-cx-matrix.h, ov-flt-cx-matrix.cc\n\t(octave_float_complex_matrix): Update.\n\n\t* ov-re-sparse.h, ov-re-sparse.cc (octave_sparse_matrix): Update.\n\t* ov-cx-sparse.h, ov-cx-sparse.cc (octave_sparse_complex_matrix):\n\tUpdate.\n\n\t* ov-re-diag.h, ov-re-diag.cc (octave_diag_matrix): Update.\n\t* ov-flt-re-diag.h, ov-flt-re-diag.cc (octave_float_diag_matrix):\n\tUpdate.\n\t* ov-cx-diag.h ov-cx-diag.cc (octave_complex_diag_matrix): Update.\n\t* ov-flt-cx-diag.h, ov-flt-cx-diag.cc\n\t(octave_float_complex_diag_matrix): Update.\n\n\t* ov-range.h (octave_range): Update.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T): Update.\n\t(OCTAVE_VALUE_INT_SCALAR_T): Update.\n\n\t* ov-perm.h (octave_perm_matrix): Update.\n\t* ov-bool.h (octave_bool): Update.\n\t* ov-bool-mat.h (octave_bool_matrix): Update.\n\t* ov-ch-mat.h (octave_char_matrix): Update.\n\n\t* mappers.cc (Fabs, Facos, Facosh, Fangle, Farg, Fasin, Fasinh,\n\tFatan, Fatanh, Fceil, Fconj, Fcos, Fcosh, Ferf, Ferfc, Fexp,\n\tFexpm1, Ffinite, Ffix, Ffloor, Fgamma, Fimag, Fisinf, Fisna,\n\tFisnan, Flgamma, Flog, Flog2, Flog10, Flog1p, Freal, Fround,\n\tFroundb, Fsignum, Fsin, Fsinh, Fsqrt, Ftan, Ftanh, Fisalnum,\n\tFisalpha, Fisascii, Fiscntrl, Fisdigit, Fisgraph, Fislower,\n\tFisprint, Fispunct, Fisspace, Fisupper, Fisxdigit, Ftoascii,\n\tFtolower, Ftoupper): Update.\n\n2009-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::do_find_all_first_of): Take advantage\n\tof string_vector (std::list<std:string>) constructor.\n\n2009-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (do_get_help_text_from_file,\n\tFget_help_text_from_file): New functions.\n\t(do_get_help_text): Pass NAME by const reference.\n\t* utils.cc (find_dir_in_path): New optional argument \"all\".\n\t* load-path.cc (load_path::do_find_matching_dirs): New function.\n\t(load_path::do_find_dir): Perform match on absolute directory\n\tnames, but return name as it appears in dir_info_list.  Adjust\n\tdname_len after stripping directory separator.\n\t* load-path.h (load_path::do_find_matching_dirs): Provide decl.\n\t(load_path::find_matching_dirs): New function.\n\n2009-11-11  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (Fl_Gl_Window::draw):\n\tIf zooming, call overlay.\n\t(Fl_Gl_Window::overlay): Rename from draw_overlay.  Don't return\n\tearly if zooming.  Don't call valid and conditionally call\n\tsetup_veiwport.  Set overlay color and draw line around zoom box.\n\t(Fl_Gl_Window::zoom_box_vertex): New function.\n\t(Fl_Gl_Window::pixel2status): Call canvas->redraw, not\n\tcanvas->redraw_overlay.\n\n2009-11-10  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* gl2ps-renderer.cc, gl2ps-renderer.h, gl2ps.c, gl2ps.h: New\n\tfiles.  PostScript backend based on opengl_renderer and gl2ps.\n\t* Makefile.am (octinclude_HEADERS): Add gl2ps.h to the list.\n\t(DIST_SRC): Add gl2ps.c to the list.\n\t* gl-render.cc (opengl_renderer::render_text): Rename from\n\topengl_renderer::draw_text.\n\t(opengl_renderer::draw_figure, opengl_renderer::draw_axes,\n\topengl_renderer::draw_line, opengl_renderer::draw_surface,\n\topengl_renderer::draw_patch, opengl_renderer::draw_hggroup,\n\topengl_renderer::draw_text, opengl_renderer::draw_image):\n\tRename from overloaded opengl_renderer::draw.\n\t* gl-render.h: Fix decls.\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (OpenGL_fltk::print): New function.\n\t(OpenGL_fltk::print_filename): New data member.\n\t(OpenGL_fltk::draw): Add support for printing.\n\t(fltk_backend::print_figure): Call figure_manager::print.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (Fferror): Update doc string.\n\n2009-11-10  David Grundberg  <davidg@cs.umu.se>\n\n\t* oct-strstrm.h (octave_base_strstream::tell): Declare virtual.\n\t(octave_istrstream::tell): New method.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am, OPERATORS/module.mk, TEMPLATE-INST/module.mk,\n\tfind-defun-files.sh, version.h.in,\n\tDLD-FUNCTIONS/config-module.awk, DLD-FUNCTIONS/config-module.sh,\n\tDLD-FUNCTIONS/module-files: New files.\n\t* Makefile.in, version.h: Delete.\n\t* lex.ll: Rename from lex.l.  Include oct-parse.h instead of y.tab.h.\n\t* parse.yy: Rename from parse.y\n\t* mkbuiltins, mkgendoc: Don't require filenames to start with a\n\t\".\" at beginning of line.\n\n\t* oct-conf.h.in (OCTAVE_CONF_LAPACK_LIBS): Delete macro.\n\t* toplev.cc (octave_config_info): Don't include LAPACK_LIBS in the\n\tstruct.\n\n2009-11-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-class.cc (octave_class::numel): Use base version if called\n\tfrom built-in assignment.\n\t(octave_class::size): Ditto.\n\n2009-11-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/max.cc (Fcummin, Fcummax): Simplify examples in\n\tdocs.\n\n2009-11-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.cc (btyp_mixed_numeric): New function.\n\t* ov-base.h: Declare it.\n\t(btyp_isnumeric): New inline function.\n\t* DLD_FUNCTIONS/max.cc (do_minmax_red_op, do_minmax_bin_op,\n\tdo_minmax_body, do_cumminmax_red_op): New functions.\n\t(MINMAX_DOUBLE_SBODY, MINMAX_DOUBLE_BODY, MINMAX_SINGLE_SBODY,\n\tMINMAX_SINGLE_BODY, MINMAX_SPARSE_BODY, MINMAX_INT_SBODY,\n\tMINMAX_INT_BODY, MINMAX_BODY, CUMMINMAX_BODY): Remove.\n\t(Fmin, Fmax, Fcummin, Fcummax): Update.\n\n2009-11-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h: Add sparse matrix extractors.\n\n2009-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__delaunayn__.cc, DLD-FUNCTIONS/__dsearchn__.cc,\n\tDLD-FUNCTIONS/__voronoi__.cc, DLD-FUNCTIONS/convhulln.cc,\n\tDLD-FUNCTIONS/qz.cc, DLD-FUNCTIONS/tsearch.cc: Correctly include\n\tconfig.h, don't include oct.h, etc.\n\n2009-11-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/bsxfun.cc: Add missing copyright.  (fill_table):\n\tMark table as initialized.\n\n2009-11-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-assign.cc (tree_multi_assignment::rvalue): Don't skip\n\tzero-length lvalue cs-lists.\n\n2009-11-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cell.cc (octave_cell::print_raw): Indent properly. Use\n\tnewline rather than '\\n'.\n\n2009-11-03  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (root_figure): Add commandwindowsize, diary,\n\tdiaryfile, echo, format, language, monitorpositions,\n\tpointerlocation, pointerwindow, and recursionlimit properties.\n\n2009-11-03  David Grundberg  <davidg@cs.umu.se>\n\n\t* graphics.h.in (root_figure): Add FormatSpacing property.\n\n2009-11-03  David Grundberg  <davidg@cs.umu.se>\n\n\t* ov-class.cc (octave_class::size): Allow and ignore extra\n\toutargs from user-defined size methods.\n\n2009-11-03  David Grundberg  <davidg@cs.umu.se>\n\n\t* ov-class.cc (make_idx_args): Call user-defined\n\tsubsref/subsasgn with 1xN structs instead of Nx1.\n\n2009-11-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-class.cc (octave_class::unique_parent_class): New method.\n\t(octave_class::subsasgn): Use it here.\n\t* ov-class.h: Declare it.\n\n2009-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (get_sort_mode_option): New function.\n\t(Fissorted): Handle ascending or descending option.\n\n2009-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::dir_info::update): Always initialize\n\trelative directories that are not yet included in abs_dir_cache.\n\n2009-10-29  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (finish_function): Return function object unless\n\tparsing function file.\n\n2009-10-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/tril.cc: New source.  * Makefile.in: Include it.\n\n2009-10-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* error.cc (verror (bool, std::ostream&, ..., bool)): Add\n\toptional with_cfn flag. If specified, prepend current function\n\tname (unless already there).\n\t(error_1): Accept with_cfn flag and pass it on.\n\t(error_2): Ditto.\n\t(verror_with_cfn, error_with_cfn, error_with_id_cfn,\n\tverror_with_id_cfn): New functions.\n\t* error.h: Declare them.\n\t* octave.cc (lo_error_handler): Call verror_with_cfn.\n\t* ov-base.cc (INT_CONV_METHOD): Call error_with_cfn.\n\t* ov.cc (octave_value::int_vector_value, octave_idx_type_vector_value):\n\tCall error_with_cfn.\n\n2009-10-21  Rik  <octave@nomad.inbox5.com>\n\n\t* variables.cc: Correct use of deftypefnx for who and whos.\n\n2009-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.h (load_path::dir_path::dir_time_last_checked): New\n\tfield.  (load_path::dir_path::dir_path,\n\tload_path::dir_path::operator=): Initialize and copy\n\tdir_time_last_checked.\n\t* load-path.cc (load_path::dir_info::initialize): Store time of\n\tlast update.\n\t(load_path::dir_info::update): Check directory modification time\n\tagainst time of last update, within resolution of filesystem\n\ttime stamps.  Suggested by Judd Storrs <storrsjm@email.uc.edu>.\n\n2009-10-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (builtin_type_t): Declare also btyp_num_types.\n\t* DLD-FUNCTIONS/bsxfun.cc (bsxfun_builtin_op): New enum.\n\t(bsxfun_handler): New typedef.\n\t(bsxfun_builtin_names, bsxfun_handler_table): New variables.\n\t(bsxfun_builtin_lookup, maybe_fill_table, maybe_optimized_builtin):\n\tNew static funcs.\n\t(bsxfun_forward_op, bsxfun_forward_rel): New static template funcs.\n\t(Fbsxfun): Try to optimize some built-in operations.\n\n2009-10-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellslices): Allow non-positive\n\tindices as bounds.\n\n2009-10-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fnth_element): Clarify docstring.\n\n2009-10-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Cell.cc, Cell.h, DLD-FUNCTIONS/besselj.cc,\n\tDLD-FUNCTIONS/find.cc, DLD-FUNCTIONS/lookup.cc,\n\tDLD-FUNCTIONS/max.cc, TEMPLATE-INST/Array-tc.cc, data.cc,\n\toct-map.cc, ov-cx-mat.h, ov-flt-cx-mat.cc, ov-flt-cx-mat.h,\n\tov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-re-mat.h,\n\tov.cc, ov.h, pr-output.cc, pr-output.h, variables.cc:\n\tRemove traces of ArrayN.\n\n\t* OPERATORS/op-dm-scm.cc: Avoid using dm + s, dm - s operators.\n\t* OPERATORS/op-dm-sm.cc: Ditto.\n\t* OPERATORS/op-dms-template.cc: Ditto.\n\n2009-10-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fnum2cell): Use Array<T>::column here.\n\n2009-10-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Update docstring.\n\n2009-10-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::octave_value (octave_base_value *, bool)):\n\tNew constructor.\n\t(octave_value::octave_value (octave_base_value *, int)): Deprecate.\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Allow the obsolete func\n\tbody syntax.\n\n2009-10-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* variables.cc (extract_function): Pass 0 to eval_string to avoid\n\terror.\n\n2009-10-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::octave_value (const Array<std::string>&)): New\n\tconstructor.\n\t* ov.h: Declare it.\n\t* data.cc (Fnth_element): New DEFUN.\n\n2009-10-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fcumsum, Fcumprod, Fprod, Fsum, Fsumsq): Correct help\n\tstring.\n\n2009-10-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fsum): Rewrite.\n\t(Fcumsum): Rewrite.\n\t(NATIVE_REDUCTION, NATIVE_REDUCTION_1): Remove.\n\n2009-10-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-binop.cc, pt-unop.cc: Revert the effect of 1be3c73ed7b5.\n\n2009-10-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lu.cc (maybe_set_triangular): Remove.\n\t(get_lu_l, get_lu_u): New helper funcs.\n\t(Flu, Fluupdate): Use them to auto-set MatrixType of results.\n\t* DLD-FUNCTIONS/qr.cc (maybe_set_triangular): Remove.\n\t(get_qr_r): New helper func.\n\t(Fqr, Fqrupdate, Fqrinsert, Fqrdelete,\n\tFqrshift): Use it to auto-set MatrixType of results.\n\t* DLD-FUNCTIONS/chol.cc (get_chol_r): New helper func.\n\t(Fchol, Fcholupdate, Fcholinsert, Fcholdelete, Fcholshift): Use it\n\tto auto-set MatrixType of result.\n\n2009-10-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): Support 'nocompute'\n\toption.\n\n2009-10-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lu.cc (Fluupdate): New DEFUN_DLD.\n\t(check_lu_dims): New helper func.\n\n2009-10-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Flength): Simplify.\n\t(Fndims): Simplify.\n\t(Fsize): Rewrite, use dim_vector::redim to simplify.\n\t(Fsize_equal): Don't chop trailing singletons (should be already\n\tchopped).\n\n2009-10-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* utils.cc (dims_to_numel): New function.\n\t* utils.h: Declare it.\n\t* ov-base.cc (octave_base_value::numel (const octave_value_list&)):\n\tUse it here.\n\t* data.cc (Fnumel): Also here.\n\n2009-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (get_dims_str): New function.\n\t(symbol_info_list::display_line,\n\tsymbol_info_list::parse_whos_line_format): Use it to get dims string.\n\n2009-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h (octave_value::get_count): Return octave_idx_type, not int.\n\n2009-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* pt-arg-list.cc (tree_argument_list::convert_to_const_vector):\n\tAvoid uninitialized variable warning.\n\t* pt-cbinop.cc (simplify_ldiv_op): Avoid unused parameter warning.\n\t* ov-flt-re-mat.cc (convert_to_str_internal):\n\tUpdate for octave_value constructor changes.\n\n2009-10-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-stream.cc (octave_base_stream::skipl,\n\toctave_stream::skipl (long, ...), octave_stream::skipl (const\n\toctave_value&, ...)): New methods.\n\t* oct-stream.h: Declare them.\n\t* file-io.cc (Ffskipl): New DEFUN.\n\n2009-10-07  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-str-str.cc (DEFUNOP (transpose, char_matrix_str)):\n\tUpdate for octave_value constructor changes.\n\n2009-10-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::assign): Do not gripe \"assignment failed\" if\n\talready griped about the binary operation.\n\n2009-10-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-idx.cc (tree_index_expression::rvalue): When evaluating index\n\tchain, split on chaining ()() and (){}.\n\n2009-10-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-misc.cc (tree_argument_list::convert_to_const_vector):\n\tReturn more than nargout arguments only unless undefined elements\n\toccur.\n\t* ov-class.cc (octave_class::subsref): Pack return list from\n\toverloaded method into first value.\n\n2009-10-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-ch-mat.h (octave_char_matrix): Don't declare allocator and\n\ttypeid.\n\t* ov-ch-mat.cc: Don't define them.\n\t* ov.cc (install_types): Don't register octave_char_matrix.\n\n2009-10-05  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h (octave_value (const charMatrix&, char, bool),\n\toctave_value (const charNDArray&, char, bool),\n\toctave_value (const ArrayN<char>&, char, bool)):\n\tNew constructor decls.\n\t(octave_value (const charMatrix&, bool, char),\n\toctave_value (const charNDArray&, bool, char),\n\toctave_value (const ArrayN<char>&, bool, char)): Mark with\n\tGCC_ATTR_DEPRECATED.  Single-quoted strings are now default string\n\ttype.\n\t(octave_value::convert_to_str): Default is single-quoted strings.\n\t* ov.cc (octave_value (const charMatrix&, char, bool),\n\toctave_value (const charNDArray&, char, bool),\n\toctave_value (const ArrayN<char>&, char, bool)): New constructors.\n\t(octave_value (const charMatrix&, bool, char),\n\toctave_value (const charNDArray&, bool, char),\n\toctave_value (const ArrayN<char>&, bool, char)):\n\tAssume is_string argument is always true.\n\n\t* ov-re-mat.cc (octave_sparse_matrix::convert_to_str_internal):\n\tUpdate for octave_value constructor changes.\n\t* ov-ch-mat.h (octave_char_matrix::convert_to_str_internal): Likewise.\n\t* ov-re-sparse.cc (octave_sparse_matrix::convert_to_str_internal):\n\tLikewise.\n\t* ov-str-mat.h (octave_char_matrix_str::squeeze,\n\toctave_char_matrix_str::reshape, octave_char_matrix_str::permute,\n\toctave_char_matrix_str::diag, octave_char_matrix_str::sort,\n\toctave_char_matrix_sq_str::squeeze,\n\toctave_char_matrix_sq_str::reshape,\n\toctave_char_matrix_sq_str::permute,\n\toctave_char_matrix_sq_str::diag, octave_char_matrix_sq_str::sort):\n\tLikewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::do_index_op_internal):\n\tLikewise.\n\t(octave_char_matrix_str::resize): Likewise.\n\t* data.cc (do_cat, Fmerge): Likewise.\n\t* ops.h (DEFNDCHARCATOP_FN): Likewise.\n\t* ov-base-int.cc (octave_base_int_matrix<T>::convert_to_str_internal):\n\tLikewise.\n\t* pt-mat.cc (tree_matrix::rvalue1): Likewise.\n\n\t* ov-ch-mat.h (octave_char_matrix::octave_char_matrix): Delete\n\tunused bool arg.  Declare constructors protected.\n\n\t(xisalnum, xisalpha, xisascii, xiscntrl, xisdigit, xisgraph,\n\txislower, xisprint, xispunct, xisspace, xisupper, xisxdigit,\n\txtoascii, xtolower, xtoupper): Move decls here from ov-str-mat.h.\n\t(MAT_MAPPER, BOOL_MAT_MAPPER): Move macro definitions and uses\n\there from ov-str-mat.h.\n\n\t* ov-ch-mat.cc (MACRO_WRAPPER, STRING_MAPPER, TOSTRING_MAPPER):\n\tMove macro definitions and uses here.\n\t* ov-str-mat.cc: From here.\n\n\t* DLD-FUNCTIONS/typecast (Ftypecast): Update for octave_value\n\tconstructor changes.  Create sq_string unless casting from string,\n\tthen preserve exact type.\n\t(Fbitpack): Update for octave_value constructor changes.  Create\n\tsq_string.\n\t* DLD-FUNCTIONS/hex2num.cc (Fnum2hex): Update for octave_value\n\tconstructor changes.  Create sq_string.\n\t* ls-oct-ascii.cc (read_ascii_data): Likewise.\n\t* mex.cc (mxArray_number::as_octave_value): Likewise.\n\t* oct-stream.cc (octave_stream::read): Likewise.\n\t* ov-base.cc (STRING_MAPPER): Likewise.\n\n2009-10-04  John W. Eaton  <jwe@octave.org>\n\n\t* ov-str-mat.h (octave_char_matrix_str::squeeze,\n\toctave_char_matrix_sq_str::squeeze, octave_char_matrix_str::diag,\n\toctave_char_matrix_sq_str::diag): New functions.\n\n2009-10-03  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h.in (image::update_xdata): Add a half-pixel to each limit.\n\t(image::update_ydata): Ditto.\n\t* gl-render.cc (opengl_renderer::draw): Clip image to axis and fix\n\tunpack alignment.\n\n2009-10-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-scalar.h (octave_base_scalar::matrix_type): Always\n\treturn MatrixType::Diagonal.\n\t(octave_base_scalar::typ): Remove.\n\n2009-10-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h: Define also diag matrix extractors.\n\t(octave_type_traits, octave_array_type_traits): Remove.\n\t(octave_value::builtin_type): New method.\n\t* oct-stream.cc (do_read): Update.\n\t* data.cc (identity_matrix): Update.\n\t* ov-base.h (builtin_type_t): New enum.\n\t(octave_base_value::builtin_type): New method.\n\t* ov-re-mat.h (octave_matrix::builtin_type): New method.\n\t* ov-flt-re-mat.h (octave_float_matrix::builtin_type): New method.\n\t* ov-cx-mat.h (octave_complex_matrix::builtin_type): New method.\n\t* ov-flt-cx-mat.h (octave_float_complex_matrix::builtin_type):\n\tNew method.\n\t* ov-bool-mat.h (octave_bool_matrix::builtin_type): New method.\n\t* ov-ch-mat.h (octave_char_matrix::builtin_type): New method.\n\t* ov-scalar.h (octave_scalar::builtin_type): New method.\n\t* ov-float.h (octave_float::builtin_type): New method.\n\t* ov-complex.h (octave_complex::builtin_type): New method.\n\t* ov-bool.h (octave_bool::builtin_type): New method.\n\t* ov-flt-complex.h (octave_float_complex::builtin_type): New method.\n\t* ov-re-diag.h (octave_diag_matrix::builtin_type): New method.\n\t* ov-flt-re-diag.h (octave_float_diag_matrix::builtin_type): New method.\n\t* ov-cx-diag.h (octave_complex_diag_matrix::builtin_type): New method.\n\t* ov-flt-cx-diag.h\n\t(octave_float_complex_diag_matrix::builtin_type):\n\tNew method.\n\t* ov-re-sparse.h (octave_sparse_matrix::builtin_type): New method.\n\t* ov-cx-sparse.h (octave_sparse_complex_matrix::builtin_type):\n\tNew method.\n\t* ov-bool-sparse.h (octave_sparse_bool_matrix::builtin_type):\n\tNew method.\n\t* ov-intx.h (octave_int_matrix::builtin_type,\n\toctave_int_scalar::builtin_type): New methods.\n\t* ov-int8.h: Define OCTAVE_INT_BTYP.\n\t* ov-int16.h: Define OCTAVE_INT_BTYP.\n\t* ov-int32.h: Define OCTAVE_INT_BTYP.\n\t* ov-int64.h: Define OCTAVE_INT_BTYP.\n\t* ov-uint8.h: Define OCTAVE_INT_BTYP.\n\t* ov-uint16.h: Define OCTAVE_INT_BTYP.\n\t* ov-uint32.h: Define OCTAVE_INT_BTYP.\n\t* ov-uint64.h: Define OCTAVE_INT_BTYP.\n\n2009-10-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Fix initialization, add missing\n\tbreak.\n\n2009-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* gl-render.cc (opengl_renderer::draw (const image::properties&)):\n\tAdjust origin for glRasterPos3d.\n\n2009-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* gl-render.cc: Style fixes.\n\n2009-10-01  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.cc (image::properties::get_color_data): New function.\n\t* gl-render.cc (opengl_renderer::draw): Handle RGB images.\n\n2009-10-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc\n\t(do_num2cell_helper, do_num2cell): New funcs.\n\t(Fnum2cell): Rewrite.\n\t(do_cellslices_nda): Do not leave trailing dims.\n\n2009-09-30  John W. Eaton  <jwe@octave.org>\n\n\t* error.cc (error_1, pr_where_2, handle_message):\n\tDon't do anything if fmt is empty.\n\t(Ferror): Call print_usage if nargin == 0.\n\n2009-09-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/typecast.cc (Ftypecast): Rewrite.\n\t(Fbitpack, Fbitunpack): New DEFUNs.\n\n2009-09-28  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::handle): Redraw the\n\toverlay when zoom box changes size.\n\t* DLD-FUNCTIONS/fltk_backend.cc (fltk_mouse_wheel_zoom): New\n\tfunction to set mouse wheel zoom factor.\n\n2009-09-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/sub2ind.cc (get_dimensions): Allow singleton array.\n\t(Fsub2ind): Allow single index.\n\n2009-09-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-m-m.cc (trans_mul, mul_trans): Update.\n\t* OPERATORS/op-fm-fm.cc (trans_mul, mul_trans): Update.\n\t* OPERATORS/op-cm-cm.cc (trans_mul, mul_trans, herm_mul, mul_herm):\n\tUpdate.\n\t* OPERATORS/op-fcm-fcm.cc (trans_mul, mul_trans, herm_mul, mul_herm):\n\tUpdate.\n\t* OPERATORS/op-m-cm.cc (trans_mul): Update.\n\t* OPERATORS/op-cm-m.cc (mul_trans): Update.\n\t* OPERATORS/op-fm-fcm.cc (trans_mul): Update.\n\t* OPERATORS/op-fcm-fm.cc (mul_trans): Update.\n\n2009-09-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-m-cm.cc: Declare and install trans_mul operator.\n\t* OPERATORS/op-fm-fcm.cc: Ditto.\n\t* OPERATORS/op-cm-m.cc: Declare and install mul_trans operator.\n\t* OPERATORS/op-fcm-fm.cc: Ditto.\n\n2009-09-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-m-cm.cc: Declare and install trans_ldiv operator.\n\t* OPERATORS/op-fm-fcm.cc: Ditto.\n\n2009-09-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::op_trans_ldiv, op_herm_ldiv): New enum constants.\n\t* ov.cc (decompose_binary_op, binary_op_fcn_name): Support them.\n\t* xdiv.h: Include mx-defs.h, delete forward decls.\n\t* xdiv.cc (xleftdiv): Support transt parameter.\n\t(xdiv): Optimize.\n\t* pt-cbinop.cc (simplify_ldiv_op): New static func.\n\t(maybe_compound_binary_expression): Try it.\n\t* OPERATORS/op-m-m.cc: Define and install trans_ldiv handler.\n\t* OPERATORS/op-fm-fm.cc: Ditto.\n\t* OPERATORS/op-cm-cm.cc: Define and install trans_ldiv and herm_ldiv\n\thandlers.\n\t* OPERATORS/op-fcm-fcm.cc: Ditto.\n\n2009-09-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value_extract): New template function.\n\t* data.cc (do_linspace): New static template function.\n\t(Flinspace): Rewrite.\n\n2009-09-18  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (fltk_backend::redraw_figure):\n\tCall __fltk_redraw__ after marking figure as modified.\n\n2009-09-18  John W. Eaton  <jwe@octave.org>\n\n\t* mexproto.h: Define OCTINTERP_API if it is not already defined.\n\tUse C-style comments.\n\n2009-09-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/rand.cc (Frandperm): New function.\n\n2009-09-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-misc.cc (tree_parameter_list::convert_to_const_vector): Pass\n\tin nargout. Don't return excess elements. Optimize varargout-only case\n\tto possibly use a shallow copy.\n\t* pt-misc.h: Update decl.\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op): Update call\n\tto tree_parameter_list::convert_to_const_vector.\n\n2009-09-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pr-output.cc (Fdisp, Ffdisp): Declare retval as octave_value_list.\n\n2009-09-14  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::pixel2status,\n\tplot_window::pixel2pos): New argument AXES, which the\n\tcoordinates are relative to.\n\t(plot_window::handle): Pass axes to pixel2status and pixel2pos.\n\n2009-09-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.h (symbol_table::curr_fcn): New member field.\n\t(symbol_table::get_curr_fcn, symbol_table::set_curr_fcn): New member\n\tfuncs.\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::xfind): Use\n\tsymbol_table::get_curr_fcn.\n\t(symbol_table::fcn_info::fcn_info_rep::x_builtin_find): Ditto.\n\t* ov-usr-fcn.cc (octave_user_function::octave_user_function): Call\n\tsymbol_table::set_curr_fcn.\n\n2009-09-12  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 3.3.50+.\n\t(OCTAVE_API_VERSION): Now api-v38+.\n\n2009-09-12  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 3.3.50.\n\t(OCTAVE_API_VERSION): Now api-v38.\n\t(OCTAVE_RELEASE_DATE): Now 2009-09-12.\n\n2009-09-08  Rafael Laboissiere  <rafael@debian.org>\n\n\t* pr-output.cc: New test.\n\n2009-09-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Makefile.in: Add LDFLAGS to OCT_LINK_DEPS.\n\n2009-09-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc: Fix test.\n\n2009-09-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-s-cs.cc: Use DEFCMPLXCMPOP_OP.\n\t* OPERATORS/op-cs-s.cc: Ditto.\n\t* OPERATORS/op-fs-fcs.cc: Ditto.\n\t* OPERATORS/op-fcs-fs.cc: Ditto.\n\n2009-09-05  John W. Eaton  <jwe@octave.org>\n\n\t* genprops.awk: Fix formatting of generated output.\n\t* graphics.h.in (graphics_object::get (const std::string&) const,\n\tgraphics_object::get (const char *) const): New functions.\n\n2009-09-05  John W. Eaton  <jwe@octave.org>\n\n\t* txt-eng-ft.cc (ft_manager::do_get_font): Remove spurious\n\tassignment usd for debugging.\n\n2009-09-04  John W. Eaton  <jwe@octave.org>\n\n\t* txt-eng-ft.cc (ft_manager::do_get_font, ft_render::set_font,\n\tft_render::set_mode, ft_render::visit, ft_render::set_color):\n\tIssue warnings instead of errors for non-fatal problems.\n\t(ft_render::visit): If face is null, then return without warning.\n\t* genprops.awk: Also generate const std::string& and const char*\n\tversions of the get member functions.\n\t* gl-render.cc (opengl_renderer::draw): Omit caseless_str\n\tconstructor in call to get method.\n\t* ft_render::set_font (): Likewise.\n\n2009-09-03  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (set_format (const Complex&, int&, int&)):\n\tAvoid passing NaN or Inf to log10.\n\n2009-09-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::assign (assign_op, const octave_value&)):\n\tCall maybe_mutate after in-place operation.\n\n2009-09-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::do_non_const_unary_op): Split to\n\tgenuine/non-genuine case.\n\t(octave_value::binary_op_to_assign_op): New method.\n\t* ov.h: Declare it.\n\t* ov-re-mat.h (octave_matrix::changesign): New method.\n\t* ov-flt-re-mat.h (octave_float_matrix::changesign): New method.\n\t* ov-cx-mat.h (octave_complex_matrix::changesign): New method.\n\t* ov-flt-cx-mat.h (octave_float_complex_matrix::changesign): New\n\tmethod.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::changesign): New method.\n\t* ov-bool-mat.h (octave_bool_matrix::invert): New method.\n\t* pt-unop.cc (tree_prefix_expression::rvalue1): Use\n\tdo_non_const_unary_op.\n\t* pt-binop.cc (tree_binary_expression::rvalue1): If possible,\n\tconvert to computed assignment.\n\n\t* OPERATORS/op-m-m.cc: Define & install in-place minus operation.\n\t* OPERATORS/op-fm-fm.cc: Ditto.\n\t* OPERATORS/op-cm-cm.cc: Ditto.\n\t* OPERATORS/op-fcm-fcm.cc: Ditto.\n\t* OPERATORS/op-int.h: Ditto.\n\t* OPERATORS/op-bm-bm.cc: Define & install in-place not operation.\n\n2009-09-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-mat.h (octave_matrix::increment, octave_matrix::decrement):\n\tUse matrix_ref.\n\t* ov-flt-re-mat.h (octave_float_matrix::increment,\n\toctave_float_matrix::decrement): Use matrix_ref.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::increment,\n\tOCTAVE_VALUE_INT_MATRIX_T::decrement):\n\tUse matrix_ref.\n\n2009-09-02  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (axes::properties::calc_ticklabels):\n\tAvoid unused parameter warning from gcc.\n\n\t* ov-perm.cc (octave_perm_matrix::save_binary,\n\toctave_perm_matrix::load_binary): Avoid shadow warning from gcc.\n\n2009-09-01  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/eig.cc (Feigs): Correct nesting error in option\n\tparsing that prevented the use of a function for generalized\n\teigenvalue problems.\n\n2009-08-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ops.h (DEFCMPLXCMPOP_OP, DEFNDCMPLXCMPOP_FN): New macros.\n\t* gripes.cc (gripe_warn_complex_cmp): New function.\n\t* gripes.h: declare it.\n\n\t* OPERATORS/op-cm-cm.cc: Call the new macros.\n\t* OPERATORS/op-cm-cs.cc: Ditto.\n\t* OPERATORS/op-cm-m.cc: Ditto.\n\t* OPERATORS/op-cm-s.cc: Ditto.\n\t* OPERATORS/op-cs-cm.cc: Ditto.\n\t* OPERATORS/op-cs-cs.cc: Ditto.\n\t* OPERATORS/op-cs-m.cc: Ditto.\n\t* OPERATORS/op-fcm-fcm.cc: Ditto.\n\t* OPERATORS/op-fcm-fcs.cc: Ditto.\n\t* OPERATORS/op-fcm-fm.cc: Ditto.\n\t* OPERATORS/op-fcm-fs.cc: Ditto.\n\t* OPERATORS/op-fcs-fcm.cc: Ditto.\n\t* OPERATORS/op-fcs-fcs.cc: Ditto.\n\t* OPERATORS/op-fcs-fm.cc: Ditto.\n\t* OPERATORS/op-fm-fcm.cc: Ditto.\n\t* OPERATORS/op-fm-fcs.cc: Ditto.\n\t* OPERATORS/op-fs-fcm.cc: Ditto.\n\t* OPERATORS/op-m-cm.cc: Ditto.\n\t* OPERATORS/op-m-cs.cc: Ditto.\n\t* OPERATORS/op-s-cm.cc: Ditto.\n\n\n2009-08-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ops.h (BOOL_OP1, BOOL_OP2, BOOL_OP3, SC_MX_BOOL_OP, MX_SC_BOOL_OP,\n\tMX_MX_BOOL_OP): Remove.\n\n2009-08-28  John W. Eaton  <jwe@octave.org>\n\n\t* genprops.awk: Generate static member functions has_core_property\n\tand core_property_names.  Make has_property and all_property_names\n\tnon-static const member functions.  Pass object type to\n\tvalidate_property_name.\n\t* graphics.cc (validate_property_name): New arg, WHAT.\n\tImprove warning and error messages.\n\t(property_list::set): Use has_core_property instead of has_property.\n\t(base_properties::has_property): Delete definition.\n\t(base_graphics_object::remove_all_listeners): Move unwind protect\n\tblock here, from old base_properties::has_property function.\n\t* graphics.h.in (base_properties::has_property): Now virtual.\n\tUnconditionally call panic_impossible.\n\n2009-08-28  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (validate_property_name): Return full name of\n\tmatched property value.  Issue warning if given property name is\n\tabbreviated.\n\t* genprops.awk: Use name returned by validate_property_name for\n\tsubsequent matching.\n\t* octave.cc (maximum_braindamage):\n\tDisable Octave:abbreviated-property-match warning.\n\n2009-08-27  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (validate_property_name): New static function.\n\t(base_properties::dynamic_property_names): New function.\n\t* graphicffs.h.in (base_properties::dynamic_property_names):\n\tProvide decl.\n\t* genprops.awk: Generate all_property_names functions.  Use\n\tall_property_names as needed to avoid duplication elsewhere.\n\tCall validate_property_name in set/get functions.\n\n2009-08-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-class.cc (get_current_method_class): Simplify.\n\t(octave_class::in_class_method): Don't rely on multiple copies of\n\tmethods. Don't declare as const.\n\t(octave_class::octave_class (const Octave_map&, const std::string&,\n\tconst octave_value_list&)):\n\tCall symbol_table::add_to_parent_map instead.\n\t* ov-class.h (octave_class::in_class_method): Don't declare as const.\n\t* symtab.h (symbol_table::parent_map): New field.\n\t(symbol_table::add_to_parent_map): New method.\n\t(symbol_table::load_class_method): Search also parent classes.\n\t* load-path.h (load_path::parent_map, load_path::add_to_parent_map,\n\tload_path::do_add_to_parent_map): Remove.\n\t* load-path.cc (load_path::do_find_method): Don't search parent\n\tclasses.\n\n2009-08-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-cs-cs.cc: Simplify comparison operators.\n\t* OPERATORS/op-fcs-fcs.cc: Ditto.\n\n2009-08-25  David Grundberg  <individ@acc.umu.se>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc [HAVE_MAGICK]: Include\n\tMagick++.h instead of GraphicsMagick/Magic++.h.\n\t* Makefile.in: Replace MAGICK_LIBS with MAGICK_LDFLAGS and\n\tMAGICK_LIBS. Replace MAGICK_INCFLAGS with MAGICK_CPPFLAGS.\n\t* oct-conf.h.in: Ditto.\n\t* toplev.cc (octave_config_info): Ditto.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-conf.h.in: New defines for UMFPACK_CPPFLAGS and UMFPACK_LDFLAGS.\n\t* toplev.cc (octave_config_info): Include them in the list.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-conf.h.in: New defines for QRUPDATE_CPPFLAGS and QRUPDATE_LDFLAGS.\n\t* toplev.cc (octave_config_info): Include them in the list.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-conf.h.in: New defines for ARPACK_CPPFLAGS and ARPACK_LDFLAGS.\n\t* toplev.cc (octave_config_info): Include them in the list.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (OCTAVE_LIBS, OCTINTERP_LINK_DEPS):\n\tInclude BLAS_LIBS in the list.\n\n2009-08-26  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (OCTAVE_LIBS): Include FLIBS in the list.\n\t(OCTINTERP_LINK_DEPS): Include TERM_LIBS, LIBGLOB, and FLIBS in\n\tthe list.\n\n2009-08-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Ffmod): Reverse order of args.\n\n2009-08-26  Rob Mahurin  <rob@utk.edu>\n\n\t* syscalls.cc: Recommend waitpid() in popen2() documentation.\n\n2009-08-25  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (gnuplot_backend::send_quit): Wait for gnuplot process.\n\n2009-08-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-m-m.cc: Install .*= and ./= operators.\n\t* OPERATORS/op-fm-fm.cc: Ditto.\n\t* OPERATORS/op-cm-cm.cc: Ditto.\n\t* OPERATORS/op-fcm-fcm.cc: Ditto.\n\t* OPERATORS/op-int.h: Ditto.\n\n2009-08-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (UNARY_OP_DEFUN_BODY,\n\tBINARY_OP_DEFUN_BODY, BINARY_ASSOC_OP_DEFUN_BODY): Remove.\n\t(unary_op_defun_body, binary_op_defun_body,\n\tbinary_assoc_op_defun_body): New functions.\n\t(Fnot, Fuplus, Fuminus, Ftranspose, Fctranspose): Use\n\tunary_op_defun_body.\n\t(Fminus, Fmrdivide, Fmpower, Fmldivide, Flt, Fle, Feq, Fge, Fgt, Fne,\n\tFrdivide, Fpower, Fldivide): Use binary_op_defun_body.\n\t(Fplus, Ftimes, Fmtimes, Fand, For): Use binary_assoc_op_defun_body.\n\n2009-08-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-s-s.cc: Check for NaN in ! operator.\n\t* OPERATORS/op-fs-fs.cc: Ditto.\n\t* OPERATORS/op-cs-cs.cc: Ditto.\n\t* OPERATORS/op-fcs-fcs.cc: Ditto.\n\n2009-08-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ops.h (DEFNDASSIGNOP_FNOP): New macro.\n\t* OPERATORS/op-bm-bm.cc: Define and install &= and |= operators.\n\n2009-08-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-m-m.cc: Define and install += and -= operators.\n\t* OPERATORS/op-fm-fm.cc: Ditto.\n\t* OPERATORS/op-cm-cm.cc: Ditto.\n\t* OPERATORS/op-fcm-fcm.cc: Ditto.\n\t* OPERATORS/op-m-s.cc: Define and install +=,-=,*=,/= operators.\n\t* OPERATORS/op-fm-fs.cc: Ditto.\n\t* OPERATORS/op-cm-cs.cc: Ditto.\n\t* OPERATORS/op-fcm-fcs.cc: Ditto.\n\t* OPERATORS/op-cm-s.cc: Define and install *=,/= operators.\n\t* OPERATORS/op-fcm-fs.cc: Ditto.\n\t* ops.h (DEFNDASSIGNOP_OP): New macro.\n\t* ov.cc (octave_value::assign (assign_op, const octave_value&)):\n\tTry looking up specialized handlers if the value is not shared.\n\t* ov-base-mat.h (octave_base_matrix::matrix_ref): New method.\n\n2009-08-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-obj.h (octave_value_list::octave_value_list (octave_idx_type)):\n\tAllow this constructor.\n\n2009-08-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/find.cc (Ffind): Reuse cached index vector when\n\tconverting boolean mask to indices.\n\n2009-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* oct-conf.h.in: New #defines for HDF5_LDFLAGS and HDF5LDFLAGS.\n\t* Makefile.in (OCTAVE_LIBS, OCTINTERP_LINK_DEPS):\n\tInclude them in the lists.\n\t* toplev.cc (octave_config_info): Include them in the list.\n\n2009-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* oct-conf.h.in: New #defines for ZLIB_CPPFLAGS and ZLIB_LDFLAGS.\n\t* toplev.cc (octave_config_info): Include them in the list.\n\n2009-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (OCTINTERP_LINK_DEPS): Include FFTW_LDFLAGS,\n\tFFTW_LIBS and READLINE_LIBS in the list.\n\t(OCTAVE_LIBS): Attempt to include all necessary dependencies for\n\tstatic linking.\n\n2009-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (eigs.oct, chol.oct, qr.oct): Add library-specific\n\tCPPFLAGS and LDFLAGS variables to CPPFLAGS and LDFLAGS.\n\tFrom Benjamin Lindner <lindnerb@users.sourceforge.net>.\n\n2009-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (OCTINTERP_LINK_DEPS): List $(LIBS) last.\n\n2009-08-17  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Makefile.in (OCTINTERP_LINK_DEPS): Include $(LIBCRUFT) and\n\t$(LIBS) in the list.\n\t(OCT_LINK_DEPS): Include $(LIBOCTAVE) and $(LIBCRUFT) in the list.\n\t(eigs.oct, qz.oct): Add $(BLAS_LIBS) to LDFLAGS.\n\t(ccolamd.oct, symbfact.oct): Add library-specific CPPFLAGS and\n\tLDFLAGS variables to CPPFLAGS and LDFLAGS.\n\n2009-08-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-struct.h, ov-struct.cc: Revert to e08d72bb988e.\n\t* ov-class.h, ov-class.cc: Partially revert to e08d72bb988e.\n\t(octave_class::subsasgn): Cut&paste code from octave_struct::subsasgn\n\tfor the nested dot indexing.\n\t* ov-usr-fcn.cc (Voptimize_subasgn_calls): Default to true.\n\n2009-08-13  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fft.cc, DLD-FUNCTIONS/fft2.cc,\n\tDLD-FUNCTIONS/fftn.cc, DLD-FUNCTIONS/fftw.cc: Update for new FFTW\n\tdefines.\n\n\t* Makefile.in (amd.oct, colamd.oct, dmperm.oct, symcrm.oct,\n\tqr.oct, fft.oct, fft2.oct, fftn.oct, fftw.oct): Add\n\tlibrary-specific CPPFLAGS and LDFLAGS variables to CPPFLAGS\n\tand LDFLAGS.\n\t* oct-conf.h.in: New #defines for GLPK_CPPFLAGS, GLPK_LDFLAGS,\n\tAMD_CPPFLAGS, AMD_LDFLAGS, CAMD_CPPFLAGS, CAMD_LDFLAGS,\n\tCCOLAMD_CPPFLAGS, CCOLAMD_LDFLAGS, CHOLMOD_CPPFLAGS,\n\tCHOLMOD_LDFLAGS, COLAMD_CPPFLAGS, COLAMD_LDFLAGS,\n\tCXSPARSE_CPPFLAGS, CXSPARSE_LDFLAGS, FFTW3_CPPFLAGS,\n\tFFTW3_LDFLAGS, FFTW3_LIBS, FFTW3F_CPPFLAGS, FFTW3F_LDFLAGS, and\n\tFFTW3F_LIBS.\n\t* toplev.cc (octave_config_info): Include them in the list.\n\n2009-08-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-class.h (octave_class): Derive from octave_struct.\n\t(octave_class::octave_class): Update all constructors.\n\t(octave_class::numeric_conv, octave_class::byte_size, octave_class::numel, octave_class::nfields,\n\toctave_class::reshape, octave_class::resize, octave_class::is_defined,\n\toctave_class::map_value): Remove methods (inherit).\n\t* ov-class.h (octave_class::obsolete_copies): New field.\n\tInit to 0 in all constructors.\n\t(octave_class::unique_clone): New decl.\n\t* ov-class.cc (octave_class::unique_clone): Fake clone if all\n\tremaining copies are obsolete.\n\t(octave_class::subsref): Share code with octave_struct::subsref.\n\t(octave_class::subsref (..., bool auto_add)): New method.\n\t(octave_class::subsasgn): If plausible, attempt to\n\toptimize the method call by marking appropriate number of copies\n\tobsolete. Share code with octave_struct::subsasgn.\n\t(octave_class::dotasgn): New method override.\n\t* ov-struct.h (octave_struct::dotref): New virtual overload.\n\t(octave_struct::dotasgn): New virtual method decl.\n\t* ov-struct.cc (octave_struct::dotasgn): New virtual method.\n\t* ov-usr-fcn.h (octave_user_function::num_args_passed,\n\toctave_user_function::saved_args): Remove fields. Wipe from all\n\tconstructor lists.\n\t(octave_user_function::save_args_passed,\n\toctave_user_function::restore_args_passed): Remove methods.\n\t(octave_user_function::all_va_args): Update decl.\n\t(octave_user_function::subsasgn_optimization_ok): New method decl.\n\t* ov-usr-fcn.cc (octave_user_function::all_va_args): Rename from\n\toctave_all_va_args, take args as a parameter.\n\t(octave_user_function::subsasgn_optimization_ok): New method.\n\t(octave_user_function::do_multi_index_op): Simplify.\n\n2009-08-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (octave_base_value::count): Declare as octave_idx_type.\n\t(octave_base_value::octave_base_value (const octave_base_value&)):\n\tInitialize count to 1.\n\t(octave_base_value::unique_clone ()): New method.\n\t(octave_base_value::print_with_name): Declare as non-const.\n\t* ov-base.cc (octave_base_value::print_with_name): Update.\n\t* ov.h (octave_value::make_unique (void)): Don't set rep->count.\n\tCall unique_clone.\n\t(octave_value::make_unique (int)): Don't set rep->count.\n\tCall unique_clone.\n\t(octave_value::octave_value (const octave_base_value *)): Declare\n\tas private.\n\t* ov-class.cc (octave_class::print_with_name): Avoid using clone ().\n\t* ov-class.h (octave_class::print_with_name): Declare as non-const.\n\n2009-08-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in: Consistently add library-specific CPPFLAGS and\n\tLDFLAGS variables to CPPFLAGS and LDFLAGS for .oct files that need\n\tthem.  Also add X11_FLAGS to CPPFLAGS for display.d display.df and\n\tpic/display.o.\n\n\t* oct-conf.h.in: New #defines for QHULL_CPPFLAGS, QHULL_LDFLAGS,\n\tCURL_CPPFLAGS, and CURL_LDFLAGS.\n\t* toplev.cc (octave_config_info): Include them in the list.\n\n2009-08-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Makefile.in: Include LDFLAGS when linking shared executable.\n\n2009-08-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fissorted, F__sort_rows_idx__, Fnorm): Mark as Built-in\n\tFunctions in the inline help.\n\n2009-08-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fftw.cc (Ffftw): Update for octave_fftw_planner\n\tand octave_float_fftw_planner as singleton objects.\n\n2009-08-11  John W. Eaton  <jwe@octave.org>\n\n\t* oct-conf.h.in: Use READLINE_LIBS instead of LIBREADLINE.\n\tNew #defines for TERM_LIBS and DL_LIBS.\n\t* toplev.cc (octave_config_info): Add TERM_LIBS and DL_LIBS to the\n\tstruct.  Use READLINE_LIBS instead of LIBREADLINE.\n\n2009-08-11  John W. Eaton  <jwe@octave.org>\n\n\t* oct-conf.h.in: New #defines for AMD_LIBS, ARPACK_LIBS,\n\tCAMD_LIBS, CCOLAMD_LIBS, CHOLMOD_LIBS, COLAMD_LIBS, CXSPARSE_LIBS,\n\tFT2_LIBS, GRAPHICS_LIBS, HDF5_LIBS, OPENGL_LIBS, PTHREAD_CFLAGS,\n\tPTHREAD_LIBS, QHULL_LIBS, QRUPDATE_LIBS, REGEX_LIBS, UMFPACK_LIBS,\n\tZLIB_LIBS.\n\n\t* toplev.cc (octave_config_info): Include them in the struct.\n\n2009-08-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fdiff): New built-in function.\n\t(do_diff): New assistant function.\n\n2009-08-10  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/dlmread.cc (Fdlmread): Perform tilde expansion on\n\tfilename argument.\n\n2009-08-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.cc (out_of_date_check): Remove overloads. Add check_relative\n\tparameter.\n\t(out_of_date_check_internal): Remove.\n\t* symtab.h: Update.\n\t* ov-fcn-handle.cc (octave_fcn_handle::do_index_op): Call\n\tout_of_date_check with check_relative = false.\n\n2009-08-09  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (Fevalin): Also return output from CATCH expression.\n\n2009-08-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fifelse): Rename to Fmerge, alias to Fifelse.\n\n2009-08-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-dm-template.cc, OPERATORS/op-pm-template.cc:\n\tAlso define conversions for null string and null sq_string.\n\n2009-08-06  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-cdm-m.cc, OPERATORS/op-dm-m.cc, OPERATORS/op-pm-m.cc:\n\tDefine LDMATRIX and DEFINENULLASSIGNCONV.\n\t* OPERATORS/op-dm-template.cc, OPERATORS/op-pm-template.cc:\n\tInclude ov-null-mat.h and define assignment conversion for null\n\tmatrices if DEFINENULLASSIGNCONV is defined.  Define OCTAVE_LDMATRIX.\n\n2009-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* pt-eval.cc (tree_evaluator::visit_complex_for_command):\n\tUse key_list order for iterating through map.\n\n\t* Makefile.in (OCT_LINK_DEPS): Also include $(RLD_FLAG) in the list.\n\n2009-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (octave$(EXEEXT)): Clean up link flags and library list.\n\t(OCTINTERP_LINK_DEPS): Omit -L../libcruft $(LIBCRUFT) $(LIBS)\n\t$(FLIBS) from the list.  Include $(RLD_FLAG) in the list.\n\t(OCT_LINK_DEPS): Only include -L. $(LIBOCTINTERP) in the list.\n\n2009-08-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* utils.cc (Fisindex): New DEFUN.\n\n2009-08-04  Kristian Rumberg  <kristianrumberg@gmail.com>\n\n\t* input.cc (is_completing_dirfns): New function.\n\t(generate_completion): Use it to selectively complete file names.\n\n2009-08-04  John W. Eaton  <jwe@octave.org>\n\n\t* debug.cc (Fdbwhere): Call octave_call_stack::goto_frame_relative\n\tto move to user code frame.  Get line and column information from\n\tcall stack.\n\t* input.cc (Fkeyboard): Don't pass verbose flag to\n\toctave_call_stack::goto_frame_relative.\n\t(get_debug_input): Get line and column information from call stack.\n\n\t* pt-eval.h, pt-eval.cc (tree_evaluator::debug_line,\n\ttree_evaluator::debug_column, tree_evaluator::db_line,\n\ttree_evaluator::db_column): Delete.\n\t* pt-eval.cc (tree_evaluator::do_breakpoint): Don't print function\n\tname and location info here.  Delete line and column number args.\n\tChange all callers.\n\n\t* toplev.h (octave_call_stack::do_current,\n\toctave_call_stack::do_current_statement): New functions.\n\t(octave_call_stack::current): Call do_current, not top.\n\t(octave_call_stack::current_statement): Call do_current_statement,\n\tnot top_statement.\n\t(octave_call_stack::top, octave_call_stack::top_statement,\n\toctave_call_stack::do_top, octave_call_stack::do_top_statement):\n\tDelete.\n\n2009-08-04  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (octave_call_stack::do_goto_frame_relative): Allow\n\tNSKIP to be 0.  Set current scope and context.\n\t* input.cc (Fkeyboard): Use octave_call_stack::goto_frame_relative\n\tto set scope in user code that called the keyboard function.\n\n2009-08-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* input.cc (Fkeyboard): Only call do_keyboard, don't fiddle with\n\tstack.\n\n2009-08-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/sub2ind.cc: New source.\n\t* Makefile.in: Include it.\n\t* ov-range.h (octave_range::octave_range (const Range&, const\n\tidx_vector&)): New constructor.\n\t* ov-re-mat.h (octave_matrix::octave_matrix (const NDArray&, const\n\tidx_vector&)): New constructor.\n\t* ov.cc (octave_value::octave_value (const idx_vector&)): New\n\tconstructor.\n\t* ov.h: Declare it.\n\n2009-07-30  Ryan Rusaw  <rrusaw@gmail.com>\n\n\t* input.cc (reading_classdef_file): New file-scope variable.\n\t(gnu_readline): Also set curr_stream if reading_classdef_file.\n\t(octave_gets, get_input_from_file):\n\tHandle classdef files like other input files.\n\t* input.h (reading_classdef_file): Provide decl.\n\n\t* octave.gperf (classdef, endclassdef, endevents, endmethods,\n\tendproperties, events, get, methods, properties, set): New keywords.\n\n\t* lex.l: Handle classdef filees like other input files.\n\tRecognize superclass method identifiers and metaclass query constructs.\n\t(is_keyword_token): Recognize endclassdef, endevents, endmethods,\n\tendproperties, get, set, properties, methods, and events keywords.\n\t(maybe_classdef_get_set_method, parsing_classdef): New variables.\n\t(handle_superclass_identifier, handle_meta_identifier):\n\tNew static functions.\n\t(lexical_feedback::init): Initialize parsing_classdef and\n\tmaybe_classdef_get_set_method.\n\t(display_token): Handle SUPERCLASSREF, METAQUERY, GET, SET,\n\tPROPERTIES, METHODS, EVENTS, and  CLASSDEF tokens.\n\t* lex.h (maybe_classdef_get_set_method, parsing_classdef):\n\tProvide decls.\n\t* parse.y (%union): New placeholder type, dummy_type.\n\t(SUPERCLASSREF, METAQUERY, GET, SET, PROPERTIES, METHODS, EVENTS,\n\tCLASSDEF): New tokens.\n\t(superclass_identifier, meta_identifier, classdef_beg,\n\tclassdef_end, classdef1, classdef, opt_attr_list, attr_list, attr,\n\topt_superclasses, superclasses, class_body, properties_beg,\n\tproperties_block, properties_list, class_property, methods_beg,\n\tmethods_block, methods_list, events_beg, events_block,\n\tevents_list, class_event): New non-terminals.\n\t(primary_expr): Include superclass_identifier and meta_identifier\n\tas possible primary_exprs.\n\t(function_beg): If parsing classdef file, set\n\tlexer_flags.maybe_classdef_get_set_method to true.\n\tbe recognized.\n\t(fcn_name): Accept GET '.' identifier or SET '.' identifier.\n\t(end_error): Handle endclassdef.\n\t(looking_at_classdef_keyword): New function.\n\t(gobble_leading_whitespace): Handle classdef.\n\t* token.h, token.cc (sc, mc):\n\tNew union fields for symbol classdef symbol_record info.\n\t(token::token (symbol_table::symbol_record *,\n\tsymbol_table::symbol_record *, int, int),\n\ttoken::token (symbol_table::symbol_record *,\n\tsymbol_table::symbol_record *, symbol_table::symbol_record *, int,\n\tint)): New constructors.\n\t(token::method_rec, token::class_rec, token::package_rec,\n\ttoken::meta_class_rec, token::meta_package_rec): New methods.\n\t(token_type): New enum values: scls_rec_token, meta_rec_token.\n\t(end_tok_type): New enum values: classdef_end, events_end,\n\tmethods_end, properties_end.\n\n2009-07-30  David Grundberg  <individ@acc.umu.se>\n\n\t* symtab.h (symbol_table::parent_scope): Remove.\n\t(symbol_table::set_parent_scope): Remove.\n\t(symbol_table::reset_parent_scope): Remove.\n\t(symbol_table::install_subfunction): Require scope parameter\n\tinstead of xparent_scope default.\n\t* symtab.cc: Remove symbol_table::xparent_scope\n\t* lex.h (lexical_feedback::parsing_nested_function): Remove.\n\t* lex.l\t(is_keyword_token): Don't ignore endfunctions.\n\t(prep_lexer_for_script_file): Renamed from prep_lexer_for_script.\n\t(prep_lexer_for_function_file): New function.\n\t(display_token): Display SCRIPT_FILE and FUNCTION_FILE.\n\t(display_state): Display FUNCTION_FILE_BEGIN\n\t(FUNCTION_FILE_BEGIN): New state.\n\t(NESTED_FUNCTION_END, NESTED_FUNCTION_BEGIN): Remove states.\n\t(prep_for_function, prep_for_nested_function): Remove functions.\n\t* parse.h: Remove extern declaration parent_function_name,\n\tend_tokens_expected.\n\t* parse.y: Add variables current_function_depth,\n\tmax_function_depth, parsing_subfunctions, seen_endfunction. Remove\n\tparent_function_name. Rename curr_fcn_ptr to primary_fcn_ptr. Add\n\ttoken FUNCTION_FILE. Rename token SCRIPT to SCRIPT_FILE.\n\t(function_file): New rule.\n\t(input): Accept function_file.\n\t(script_file): Rule renamed from script.\n\t(function_file): New rule.\n\t(function_list): New rule.\n\t(push_fcn_symtab): Parse nested functions.\n\t(fcn_name): Remove parent_function_name.\n\t(function_end): Use seen_endfunction. New error messages.\n\t(make_script): Use primary_fcn_ptr.\n\t(frob_function): Simplify control structures. Don't use\n\tsymbol_table::parent_scope.\n\t(push_fcn_symtab, function_end, frob_function, finish_function):\n\tUse current_function_depth instead of\n\tlexical_feedback::parsing_nested_function.\n\t(make_return_command): Use current_function_depth instead of\n\tlexical_feedback::defining_func.\n\t(make_break_command, make_decl_command, maybe_warn_missing_semi):\n\tDitto\n\t(parse_fcn_file): Warn when nested functions have been\n\tdeclared. Remove superfluous local variables. Parse function files\n\tusing function_file rule.\n\n2009-07-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fmerge): Rename to Fifelse.\n\n2009-07-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fmerge): New DEFUN.\n\t(do_merge): New helper function.\n\n2009-07-29  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (param_list_end): Also set\n\tlexer_flags.looking_for_object_index to false.\n\n\t* ov-float.cc, ov-flt-re-mat.cc, ov-re-mat.cc, ov-re-sparse.cc,\n\tov-scalar.cc: Use complex function for acos mapper if arg is out\n\tof range [-1, 1].\n\n\t* ov-bool.cc (octave_bool::load_ascii): Call template function to\n\tread value.\n\t* ov-scalar.cc (octave_scalar::load_ascii): Likewise.\n\t* ov-complex.cc (octave_complex::load_ascii): Likewise.\n\t* ov-float.cc (octave_float_scalar::load_ascii): Likewise.\n\t* ov-flt-complex.cc (octave_float_complex::load_ascii): Likewise.\n\t* ls-mat-ascii.cc (read_mat_ascii_data): Likewise.\n\n\t* ov-re-sparse.cc (octave_sparse_matrix::load_binary,\n\toctave_sparse_matrix::load_hdf5): Perform sanity check on indices.\n\t* ov-cx-sparse.cc (octave_sparse_complex_matrix::load_binary,\n\toctave_sparse_complex_matrix::load_hdf5): Likewise.\n\t* ov-bool-sparse.cc (octave_sparse_bool_matrix::load_binary,\n\toctave_sparse_bool_matrix::load_hdf5): Likewise.\n\n2009-07-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::do_multi_index_op):\n\tCache lookups also for classes.\n\n2009-07-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Support auto-expanding scalar\n\tcells.\n\n2009-07-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::xfind,\n\tsymbol_table::fcn_info::fcn_info_rep::find,\n\tsymbol_table::fcn_info::fcn_info_rep::find_function,\n\tsymbol_table::fcn_info::find,\n\tsymbol_table::fcn_info::find_function,\n\tsymbol_table::find, symbol_table::do_find,\n\tsymbol_table::find_function):\n\tAdd local_funcs parameter.\n\t* symtab.h: Update decls.\n\t* ov-fcn-handle.cc (make_fcn_handle): Add local_funcs parameter.\n\t* ov-fcn-handle.h: Update decls.\n\n2009-07-24  John W. Eaton  <jwe@octave.org>\n\n\t* pt-mat.cc (DO_SINGLE_TYPE_CONCAT_NO_MUTATE): New macro.\n\t(tree_matrix::rvalue1): Use it to avoid complex -> real conversion.\n\n2009-07-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCIONS/cellfun.cc (Fcellfun): Avoid double error messages.\n\n2009-07-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* load-path.cc (load_path::do_any_class_method): New method.\n\t* load-path.h (load_path::do_any_class_method): New method decl.\n\t(load_path::any_class_method): New method.\n\t* ov-fcn-handle.cc (octave_fcn_handle::do_multi_index_op): Support\n\tcalls without non-overloaded base function.\n\t(make_fcn_handle): Support creation without non-overloaded base\n\tfunction.\n\n2009-07-23  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::pixel2axes_or_ca):\n\tReplace plot_window::pixel2axes and use algorithm from octavede.\n\t(plot_window::handle): Zooming now works on the axes below the\n\tmouse pointer instead of the current axes. Combine old and new\n\tzooming methods.\n\t(help_text): Update to reflect new mouse/key bindings.\n\n2009-07-23  Søren Hauberg  <hauberg@gmail.com>\n\n\t* graphics.cc (axes::properties::zoom_about_point,\n\taxes::properties::translate_view): New functions.\n\t(axes::properties::zoom): make zoom_stack usage optional.\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::handle): Use new\n\tzoom API.\n\n2009-07-23  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (safe_symbol_lookup): New function.\n\t(symbol_exist): Use it.\n\n2009-07-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/chol.cc (Fcholupdate,\n\tFcholinsert, Fcholdelete, Fcholshift): Replace is_matrix_type ->\n\tis_numeric_type.\n\n2009-07-23  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (IGNORE_EXCEPTION, SAFE_CALL): New macros.\n\t(clean_up_and_exit, do_octave_atexit): Use SAFE_CALL to handle\n\texceptions while preparing to exit.\n\n2009-07-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.cc (get_dispatch_type): Omit first-arg dispatch, export.\n\t* symtab.h (get_dispatch_type): Provide decl.\n\t* ov-fcn-handle.h (octave_fcn_handle::warn_reload): Delete.\n\t(octave_fcn_handle::disp): New field.\n\t(octave_fcn_handle::str_ov_map): New typedef.\n\t(octave_fcn_handle::octave_fcn_handle (..., str_ov_map *)): New\n\tconstructor.\n\t(octave_fcn_handle::do_multi_index_op): New method decl.\n\t(octave_fcn_handle::is_overloaded): New method.\n\t* ov-fcn-handle.cc\n\t(octave_fcn_handle::do_multi_index_op): New method.\n\t(octave_fcn_handle::subsref): Rewrite using do_multi_index_op.\n\t(octave_fcn_handle::make_fcn_handle): Construct overloaded handles if\n\tappropriate.\n\t(Ffunctions): Indicate (statically) overloaded handles.\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Update & modernize.\n\t* DLD-FUNCTIONS/bsxfun.cc (Fbsxfun): Ditto.\n\n2009-07-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.cc (symbol_table::find,\n\tsymbol_table::find_function,\n\tsymbol_table::symbol_record::find,\n\tsymbol_table::fcn_info::find,\n\tsymbol_table::fcn_info::fcn_info_rep::find,\n\tsymbol_table::fcn_info::fcn_info_rep::xfind): Simplify argument lists.\n\t* symtab.h: Update declarations.\n\t* pt-id.cc (tree_identifier::rvalue): Simplify.\n\t* pt-id.h (tree_identifier::do_lookup): Simplify.\n\t* pt-idx.cc (tree_index_expression::rvalue): Update.\n\t* variables.cc (symbol_exist): Update.\n\n2009-07-21  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_table::builtin_find,\n\tsymbol_table::do_builtin_find,\n\tsymbol_table::fcn_info::builtin_find,\n\tsymbol_table::fcn_info::fcn_info_rep::builtin_find,\n\tsymbol_table::fcn_info::fcn_info_rep::x_builtin_find): New functions.\n\t* symtab.h: Provide decls.\n\t* DLD-FUNCTIONS/dispatch.cc (Fbuiltin): Call\n\tsymbol_table::builtin_find instead of symbol_table::find_function.\n\n2009-07-20  Aleksej Saushev  <asau@inbox.ru>\n\n\t* sysdep.cc: Also define BSD_init if __NetBSD__ is defined.\n\t(sysdep_init): Also call BSD_init if __NetBSD__ is defined.\n\n2009-07-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* bitfcns.cc (DO_UBITSHIFT): Avoid overflow.\n\t(DO_SBITSHIFT): Fix mask calculation.\n\n2009-07-17  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (F__magick_read__):\n\tDetermine correct number of bits required when reading images.\n\n2009-07-16  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (get_array_limits): Require min_pos value to be\n\tgreater than zero.\n\n2009-07-15  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* DLD-FUNCTIONS/filter.cc: New tests.\n\n2009-07-09  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (Fones, Fzeros, Ftrue, Ffalse): Update docstrings.\n\n2009-07-08  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (convert_cdata): Return NaN for NaN values in cdata.\n\n\t* pt-assign.cc (maybe_warn_former_built_in_variable): Improve message.\n\n2009-07-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-eval.cc (do_unwind_protect_cleanup_code): Add missing\n\tunwind_protect::run.\n\n2009-07-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* help.cc (do_which): Also look for files.\n\n2009-07-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Cell.cc (Cell::index): Use proper resize_fill_value.\n\n2009-07-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.h (symbol_table::get_fcn_info): New private static method.\n\t(symbol_record_rep::finfo): New field.\n\t* symtab.cc (symbol_record::find): Use cached finfo if possible,\n\tcache on successful queries.\n\n2008-07-01  David Bateman  <dbateman@free.fr>\n\n\t* pr-output.cc (static inline std::string rational_approx (double,\n\tint)): Test for underflow of fractional part of rational approximation\n\tearlier in the loop.\n\n2009-07-01  Joe Rothweiler  <octaveuser@sensicomm.com>\n\n\t* input.cc (raw_mode): Use TCSADRAIN if no wait.\n\n2009-06-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.h (force_variable): Remove assertion.\n\n2009-06-28  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Makefile.in (INCLUDES): Install txt-eng.h and txt-eng-ft.h.\n\t* gl-render.cc (opengl_renderer::draw_text): Fix bitmap offset\n\tcomputation for 90x rotated text.\n\t* txt-eng-ft.cc (ft_render::render): Compute bitmap pixels correctly\n\tfor 90x rotated text.\n\n\t* gl-render.cc (opengl_renderer::draw(text::properties)): Don't do\n\tanything if the bitmap data is empty. Issue a warning instead of\n\tan error if Freetype library is not available.\n\t* txt-eng-ft.cc (ft_manager::do_get_font): Small change in error\n\tstring (add prefix).\n\t(ft_render::render): Don't do anything if the bitmap data is empty.\n\n2009-06-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.h (erase_scope (void *)): Remove overload.\n\n2009-06-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* txt-eng.h: New file for simple text engine.\n\t* txt-eng.h, txt-eng.cc: Freetype based text render engine.\n\t* Makefile.in: Add txt-eng-ft.cc to list of source files.\n\t* gl-render.h (opengl_renderer::draw_text, opengl_renderer::set_font,\n\topengl_renderer::draw(text::properties)): New method to support text\n\trendering using the Freetype renderer.\n\t(opengl_renderer::text_renderer): New field for text rendering.\n\t* gl-render.cc (opengl_renderer::draw(graphics_object)): Support text\n\tobject.\n\t(opengl_renderer::draw(figure::properties)): Setup alpha test.\n\t(opengl_renderer::draw(axes::properties)): Render tick labels, hide\n\tlabels for depth axes and fix a problem in calling\n\tgraphics_object::get(char*).\n\t(opengl_renderer::draw(text::properties)): Basic text rendering using\n\tFreetype engine.\n\t(opengl_renderer::draw_text): Ditto.\n\t(opengl_renderer::set_color): Propagate the color to the text\n\trenderer.\n\t(opengl_renderer::set_font): New utility method.\n\t* graphics.cc (axes::properties::init, axes::properties::set_defauls):\n\t(Re)initialize tick labels, labels and title property.\n\n2009-06-26  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (Faddpath): Preserve order of prepended elements.\n\n2009-06-25  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (gh_manager::restore_gcbo):\n\tArg is now void, not void*.\n\n2009-06-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* unwind-prot.h (unwind_protect::fcn_elem): New class.\n\t(unwind_protect::fcn_arg_elem): New class.\n\t(unwind_protect::method_elem): New class.\n\t(unwind_protect::add_action_var): Rename to add_fcn.\n\t(unwind_protect::add_fcn): New static method.\n\t(unwind_protect::add_method): New static method.\n\n\t* symtab.h: Split clear_variables into two overloads.\n\t* toplev.h (octave_call_stack::restore_frame): New static method.\n\n\t* graphics.cc: Update unwind_protect usage.\n\t* input.cc: Ditto.\n\t* lex.h: Ditto.\n\t* ls-mat5.cc: Ditto.\n\t* mex.cc: Ditto.\n\t* ov-builtin.cc: Ditto.\n\t* ov-fcn-handle.cc: Ditto.\n\t* ov-mex-fcn.cc: Ditto.\n\t* ov-usr-fcn.cc: Ditto.\n\t* parse.y: Ditto.\n\t* pt-eval.cc: Ditto.\n\t* toplev.cc: Ditto.\n\t* variables.cc: Ditto.\n\n2009-06-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* input.cc: Use unwind_protect::add_action_var where appropriate.\n\t* ls-mat5.cc: Ditto.\n\t* ov-fcn-handle.cc: Ditto.\n\t* parse.y: Ditto.\n\t* toplev.cc: Ditto.\n\t* variables.cc: Ditto.\n\n2009-06-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* unwind-prot.h (unwind_protect::elem): New polymorphic class.\n\t(unwind_protect::restore_var): Remove.\n\t(unwind_protect::restore_mem): Remove.\n\t(unwind_protect::elt_list): Update.\n\t(unwind_protect::add (elem *)): New method.\n\t(unwind_protect::add (void (*)(void *), void *)): Reimplement.\n\t(unwind_protect::run (void)): Rewrite.\n\t(unwind_protect::discard (void)): Rewrite.\n\t(unwind_protect::protect_var): Rewrite.\n\t(unwind_protect::protect_mem): Rewrite.\n\t(unwind_protect::add_action_var): New method.\n\t* unwind-prot.cc (unwind_protect::restore_mem): Remove.\n\n2009-06-24  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* oct-map.cc (Octave_map::squeeze, Octave_map::permute,\n\tOctave_map::transpose, Octave_map::reshape, Octave_map::concat,\n\tOctave_map::index): Add tests for preservation of key order in\n\tstruct arrays.\n\n2009-06-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-mat.cc (get_concat_class): Use empty string as zero value.\n\t(tm_row_const_rep::tm_row_const_rep): Initialize class_nm to empty\n\tstring.\n\t(tm_const::tm_const): Ditto.\n\n2009-06-24  John W. Eaton  <jwe@octave.org>\n\n\t* pt-assign.cc (former_built_in_variables): Remove \"ans\" from the list.\n\n2009-06-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* unwind-prot.h (restore_var, restore_mem): Hide also copy\n\tconstructors.\n\n2009-06-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* quit.h (octave_quit_exception): Delete.\n\t(exit_status, quitting_gracefully): New globals.\n\t* quit.cc: Initialize them.\n\t(Fquit): Set the globals, simulate interrupt.\n\t(main_loop): Handle exit properly.\n\t* octave.cc (execute_eval_option_code): Ditto.\n\t(execute_command_line_file): Ditto.\n\t* pt-eval.cc (do_unwind_protect_cleanup_code):\n\tFix order of unwind_protect calls.\n\n2009-06-23  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.cc (Octave_map::squeeze, Octave_map::permute,\n\tOctave_map::transpose, Octave_map::reshape, Octave_map::concat):\n\tPreserve key order.\n\n2009-06-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-eval.cc (tree_evaluator::visit_try_catch_command): Simplify.\n\n2009-06-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc: Modernize unwind_protect usage.\n\t* DLD-FUNCTIONS/daspk.cc: Ditto.\n\t* DLD-FUNCTIONS/dasrt.cc: Ditto.\n\t* DLD-FUNCTIONS/dassl.cc: Ditto.\n\t* DLD-FUNCTIONS/eigs.cc: Ditto.\n\t* DLD-FUNCTIONS/lsode.cc: Ditto.\n\t* DLD-FUNCTIONS/quad.cc: Ditto.\n\t* DLD-FUNCTIONS/rand.cc: Ditto.\n\t* debug.cc: Ditto.\n\t* dynamic-ld.cc: Ditto.\n\t* error.cc: Ditto.\n\t* graphics.cc: Ditto.\n\t* help.cc: Ditto.\n\t* input.cc: Ditto.\n\t* load-path.cc: Ditto.\n\t* ls-mat4.cc: Ditto.\n\t* ls-mat5.cc: Ditto.\n\t* mex.cc: Ditto.\n\t* oct-hist.cc: Ditto.\n\t* octave.cc: Ditto.\n\t* ov-builtin.cc: Ditto.\n\t* ov-class.cc: Ditto.\n\t* ov-fcn-handle.cc: Ditto.\n\t* ov-list.cc: Ditto.\n\t* ov-mex-fcn.cc: Ditto.\n\t* ov-struct.cc: Ditto.\n\t* ov-usr-fcn.cc: Ditto.\n\t* pager.cc: Ditto.\n\t* pr-output.cc: Ditto.\n\t* pt-arg-list.cc: Ditto.\n\t* pt-eval.cc: Ditto.\n\t* toplev.cc: Ditto.\n\t* variables.cc: Ditto.\n\n2009-06-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* unwind-prot.h (unwind_protect): Rewrite.\n\t(unwind_protect::protect_var): New class.\n\t(unwind_protect::protect_mem): New class.\n\t* unwind-prot.cc (unwind_protect): Rewrite.\n\t* pt-eval.cc (tree_evaluator::visit_try_catch_command): Delete frame\n\tproperly.\n\n2009-06-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cell.cc (octave_cell::all_strings): Avoid duplicate conversions.\n\n2009-06-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (Fsubsasgn): Uniquify shared value before assigning to it.\n\n2009-06-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc: Update docs.\n\n2009-06-17  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_octave_value::get_data):\n\tIf octave_value::mex_get_data returns a valid pointer, mark it as\n\tforeign and return it instead of enumerating the types that can be\n\thandled directly.\n\n\t* ov-re-mat.h (octave_matrix::mex_get_data): New function.\n\t* ov-bool-mat.h (octave_bool_matrix::mex_get_data): Ditto.\n\t* ov-flt-re-mat.h (octave_float_matrix::mex_get_data): Ditto.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::mex_get_data): Ditto.\n\t* ov-base-mat.h (octave_base_matrix::mex_get_data): Delete.\n\n2009-06-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.h (symbol_table::set_scope_and_context): Avoid checking\n\terror_state for setting context.\n\n2009-06-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-mat.h (octave_matrix::octave_matrix (const Array<octave_idx_type>&,\n\tbool)): New constructor.\n\t* ov.cc (octave_value::octave_value (const Array<octave_idx_type>&,\n\tbool)): New constructor.\n\t* ov.h: Declare it.\n\n\t* data.cc (Fsort, F__sort_rows_idx__): Use the new constructor.\n\t* DLD-FUNCTIONS/find.cc (Ffind): Ditto.\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Ditto.\n\t* DLD-FUNCTIONS/max.cc (Fmax, Fmin, Fcummax, Fcummin): Ditto.\n\n2009-06-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-mat.h (octave_base_matrix::idx_cache): New member field.\n\t(octave_base_matrix::typ): Turn to MatrixType *.\n\t(octave_base_matrix::octave_base_matrix (...)): Update constructors.\n\t(octave_base_matrix::clear_cached_info,\n\toctave_base_matrix::set_idx_cache): New member functions.\n\t* ov-base-mat.cc (octave_base_matrix::assign,\n\toctave_base_matrix::delete_elements): Call clear_cached_info here.\n\t* ov-re-mat.h (octave_matrix::index_vector): Use idx_cache.\n\t* ov-flt-re-mat.h (octave_float_matrix::index_vector): Ditto.\n\t* ov-bool-mat.h (octave_bool_matrix::index_vector): Ditto.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::index_vector): Ditto.\n\t* ov-range.h (octave_range::idx_cache): New member field.\n\t(octave_range::octave_range (...)): Update constructors.\n\t(octave_range::clear_cached_info,\n\toctave_base_matrix::set_idx_cache): New member functions.\n\t(octave_range::idx_vector): Use idx_cache.\n\n2009-06-14  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (axes::properties::xtick, axes::properties::ytick,\n\taxes::properties::ztick, axes::properties::xticklabelmode,\n\taxes::properties::yticklabelmode, axes::properties::zticklabelmode):\n\tAdd 'u' modifier to enable updaters.\n\t(axes::properties::calc_ticklabels): New function to update tick\n\tlabels.\n\t(axes::properties::update_xtick, axes::properties::update_ytick,\n\taxes::properties::update_ztick,\n\taxes::properties::update_xticklabelmode,\n\taxes::properties::update_yticklabelmode,\n\taxes::properties::update_zticklabelmode): Add updaters to update tick\n\tlabels correctly.\n\t(axes::properties::update_xlim, axes::properties::update_ylim,\n\taxes::properties::update_zlim): Update tick labels.\n\t* graphics.cc (axes::properties::calc_ticklabels): New function to\n\tupdate tick labels.\n\n2009-06-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Support character array lookup.\n\n2009-06-12  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-handle.cc (make_fcn_handle): Accept operators which have\n\tcorresponding functions and make function handles using the names.\n\tNew test.\n\n2009-06-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (do_numeric_lookup): New template function.\n\t(Flookup): Extend to support b and m options, improve diagnostic.\n\tRefactor.\n\n2009-06-12  Kai NODA  <nodakai@gmail.com>\n\n\t* ls-mat4.h: Fix include guard\n\t* ov-type-conv.h: Add missing include guard.\n\n2009-06-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (BINARY_ASSOC_OP_DEFUN_BODY): New helper macro.\n\t(Fplus, Fmtimes, Ftimes, Fand, For): Allow >= 1 arguments.\n\n2009-06-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cell.cc (octave_cell::sort (Array<octave_idx_type>&)): Simplify.\n\n2009-06-11  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc: Keep long options alphabetized.\n\n\t* display.h (display_info::no_window_system): New static function.\n\t(display_info::display_info, display_info::init,\n\tdisplay_info::instance_ok): New argument, QUERY.\n\t(display_info::init): Skip query if QUERY is false.\n\n\t* octave.cc (long_opts, octave_main): Handle --no-window-system option.\n\t(NO_WINDOW_SYSTEM_OPTION): New defined value.\n\t(usage_string, verbose_usage): Mention --no-window-system option.\n\n2009-06-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-class.cc (octave_class::subsref): Set up proper nargout for call to subsref\n\tmethod.\n\t* ov-class.cc (octave_class::subsref): Unpack cs-list and setup nargin\n\tfor call to subsasgn.\n\n2009-06-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.cc (octave_base_value::numel (const octave_value_list&),\n\toctave_base_value::size): New virtual methods.\n\t* ov-base.h: Declare them.\n\t* ov.h (octave_value::numel (const octave_value_list&)): New method.\n\t(octave_value::size): Forward to octave_base_value.\n\t* ov-class.cc (octave_class::numel (const octave_value_list&),\n\toctave_base_value::size): New method overrides.\n\t* ov-class.h: Declare them.\n\t* pt-idx.cc (tree_index_expression::lvalue): Rewrite.\n\t* data.cc (Fnumel): Allow indexed query.\n\n2009-06-10  John W. Eaton  <jwe@octave.org>\n\n\t* pt-fcn-handle.cc (tree_anon_fcn_handle::dup): Don't convert to\n\ttree_constant object here.  Do inherit from current symbol table\n\tscope and context.  New test.\n\n\t* lex.l\t(handle_identifier): Set lexer_flags.looking_for_object_index\n\tfalse if identifier is a keyword.\n\t({IDENT}{S}*): Don't set lexer_flags.looking_for_object_index here.\n\n2009-06-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* octave.cc (octave_main): Call initialize_command_input\n\tconditionally. Move line_editing update in front of it.\n\tCall command_editor::force_default_editor if not line_editing.\n\n2009-06-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Flog2): Fix tests.\n\n2009-06-08  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (symbol_exist): Returnn 1 for function handles and\n\tinline function objects.\n\n2009-06-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* symtab.h (symbol_table::do_clear_global,\n\tsymbol_table::do_clear_global_pattern): Properly erase from both local\n\tand global table.\n\n2009-06-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* variables.cc (Fclear): Clear also globals when called without\n\targuments.\n\n2009-06-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* graphics.cc (color_property::do_set): Allow a wider range of types.\n\n2009-06-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/find.cc (Ffind): Fix docs. Improve second argument\n\thandling. Add regression tests.\n\n2009-06-06  Rik  <rdrider0-list@yahoo.com>\n\n\t* data.cc: Update documentation for 'complex' function\n\n2009-06-06  Rik  <rdrider0-list@yahoo.com>\n\n\t* load-save.cc: Update documentation for NA and isna functions\n\n2009-06-06  Rik  <rdrider0-list@yahoo.com>\n\n\t* load-save.cc: Update documentation for load and save\n\n2009-06-06  Rik  <rdrider0-list@yahoo.com>\n\n\t* pr-output.cc: Update documentation for 'format'\n\n2009-06-05  Rik  <rdrider0-list@yahoo.com>\n\n\t* variables.cc: Update documentation for 'who' family of functions\n\n2009-06-03  Rik  <rdrider0-list@yahoo.com>\n\n\t* input.cc: Correct documentation for keyboard function\n\n2009-06-02  Rob Mahurin  <rob@utk.edu>\n\n\t* Makefile.in: Add CARBON_LIBS to OCTINTERP_LINK_DEPS.\n\tFrom Bernard Desgraups <bdesgraupes@orange.fr>.\n\n2009-06-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.cc (octave_base_value::numeric_assign): Gripe when no index\n\tgiven.\n\t* ov-cell.cc (octave_cell::subsasgn): Ditto.\n\t* ov-struct.cc (octave_struct::subsasgn): Ditto.\n\t* ov-list.cc (octave_list::subsasgn): Ditto.\n\n2009-05-28  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::do_files): Avoid shadow warning from GCC.\n\n2009-05-27  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (write_image):\n\tBail out if given indexed image.\n\n2009-05-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (encode_map): Fix RGB color\n\tconstruction.\n\n2009-05-26  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.h, load-path.cc (load_path::files, load_path::do_files):\n\tNew arg, OMIT_EXTS.\n\t* help.cc (F__list_functions__): Call load_path::files with\n\tomit_exts set to true.\n\n\t* symtab.h\n\t(symbol_table::symbol_record::symbol_record_rep::is_variable):\n\tUse \"! is_local ()\" instead of storage_class != local.\n\t(symbol_table::do_variable_names): Only add variables to the list.\n\t(symbol_table::unmark_forced_variables): New static function\n\t* variables.cc (do_who): Use is_variable instead of is_defined.\n\tAlso limit output to variables when using regexp pattern.\n\t* octave.cc (unmark_forced_vars): Delete.\n\t(execute_eval_option_code): Don't add unmark_forced_vars to\n\tunwind_protect stack here.\n\t* toplev.cc (main_loop): Add symbol_table::unmark_forced_variables\n\tto the unwind_protect stack here.\n\t* input.cc (get_debug_input): Likewise.\n\t* parse.y (parse_fcn_file, eval_string): Likewise.\n\n2009-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* toplev.h (quit_allowed): New global variable.\n\t* toplev.cc (quit_allowed): Declare it.\n\t(Fquit): Raise error if quitting is not allowed.\n\t* octave.cc (octave_main): if running as embedded, disable quit by\n\tdefault.\n\n2009-05-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* variables.cc (do_who): Only output symbols with a defined value.\n\n2009-05-22  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* toplev.h (main_loop): Tag with OCTINTERP_API.\n\t* input.h (octave_read, get_input_from_file, get_input_from_stdin):\n\tDitto.\n\t* lex.h (create_buffer, current_buffer, switch_to_buffer,\n\tdelete_buffer, restore_input_buffer, delete_input_buffer): Ditto.\n\n2009-05-22  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* ov-class.h, ov-class.cc (octave_class::clear_exemplar_map):\n\tNew function.\n\t* symtab.h (symbol_record::clear_objects,\n\tsymbol_record::do_clear_objects): New functions.\n\t* variables.cc (do_matlab_compatible_clear, clear):\n\tHandle -classes option.\n\n2009-05-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::assign (const\n\toctave_value_list, typename MT::element_type)): Avoid out of bounds\n\tassignments.\n\n2009-05-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.cc (figure::properties::get_boundingbox,\n\tfigure::properties::set_boundingbox): Get screen size from root\n\tobject.\n\t(convert_position): Get screen resolution from root object and remove\n\tunneeded \"backend\" argument.\n\t(axes::properties::get_boundingbox,\n\tfigure::properties::get_boundingbox,\n\tfigure::properties::set_boundingbox): Remove unneeded backend argument\n\tto convert_position call.\n\n\t* debug.h (class bp_table): Tag with OCTINTERP_API.\n\t* input.h (Vdebugging): Ditto.\n\t* pt-eval.h (class tree_evaluator): Ditto.\n\t* toplev.h (class octave_call_stack): Ditto.\n\n\t* file-io.cc (mkstemp): Add mktemp-based implementation of mkstemp on\n\tplatforms that do not have it (mkstemp is required by the new help\n\tsystem).\n\n\t* TEMPLATE-INST/Array-os.cc: Add \"extern template\" declaration for\n\tArray<octave_idx_type> to avoid implicit instantiation (and duplicate\n\tsymbols at link-time) [Win32]\n\n2009-05-20  John W. Eaton  <jwe@octave.org>\n\n\t* pt-assign.cc (maybe_warn_former_built_in_variable):\n\tSet initialized to true when done initializing vars set.\n\tFrom Michael Goffioul  <michael.goffioul@gmail.com>.\n\n2009-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-typeinfo.h\n\t(octave_value_typeinfo::unary_class_ops,\n\toctave_value_typeinfo::unary_ops,\n\toctave_value_typeinfo::non_const_unary_ops,\n\toctave_value_typeinfo::binary_class_ops,\n\toctave_value_typeinfo::binary_ops,\n\toctave_value_typeinfo::compound_binary_class_ops,\n\toctave_value_typeinfo::compound_binary_ops,\n\toctave_value_typeinfo::cat_ops,\n\toctave_value_typeinfo::assign_ops,\n\toctave_value_typeinfo::assignany_ops,\n\toctave_value_typeinfo::pref_assign_conv,\n\toctave_value_typeinfo::type_conv_ops,\n\toctave_value_typeinfo::widening_ops): Declare as Array<void *>.\n\t* ov-typeinfo.cc: Reflect changes.\n\n2009-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* toplev.h (octave_exit_func): New typedef.\n\t(octave_exit): Change to octave_exit_func.\n\n2009-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-typeinfo.cc: Don't include oct-obj.h.\n\n2009-05-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* toplev.h (octave_quit_exception): New class.\n\t(octave_exit): New global variable.\n\t* toplev.cc (octave_exit): Initialize to ::exit.\n\t(clean_up_and_exit): Call octave_exit if set.\n\t(Fquit): Raise octave_quit_exception to quit.\n\t(main_loop): Catch octave_quit_exception.\n\t* octave.cc (execute_command_line_file): Ditto.\n\t(execute_eval_option_code): Ditto.\n\n2009-05-19  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (F__fltk_redraw__): New function.\n\t(F__init_fltk__): Call add_input_event_hook with feval to add\n\t__fltk_redraw__ to the list of even hook functions to call.\n\tCall mlock when initializing.\n\t(F__remove_fltk__): Call remove_input_event_hook with feval to\n\tremove __fltk_redraw__ from the list of event hook functions.\n\tUnlock __init_fltk__ when shutting down.\n\n\t* input.cc (Finput_event_hook): Delete.\n\t(input_event_hook): Handle set of functions instead of just one.\n\t(Fadd_input_event_hook, Fremove_input_event_hook): New functions.\n\n2009-05-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Makefile.in: Add X11_LIBS to OCTINTERP_LINK_DEPS.\n\n2009-05-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* TEMPLATE-INST/Array-tc.cc: Change #include.\n\n2009-05-15  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* ov-class.cc (octave_class::exemplar_info): Fix typo in error message.\n\t* ov-class.cc (Fmethods): Methods returns cell array.\n\t* ls-mat5.cc (read_mat5_binary_element):\n\tConstruct exemplar array and ensure inheritance is correct.\n\n2009-05-15  John W. Eaton  <jwe@octave.org>\n\n\t* error.cc (Ferror): Handle error struct argument.\n\n\t* ls-mat5.cc (save_mat5_binary_element): Avoid multiple calls to\n\tcontents method.  From David Bateman <dbateman@free.fr>.\n\t(save_mat5_element_length): Use const Cell to avoid making copies\n\twhen indexing.\n\n2009-05-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-stream.cc: Don't instantiate Array2<read_fptr>.\n\t(octave_stream::read): Make read_fptr_table a static 2d array.\n\t(FILL_TABLE_ROW): Update.\n\n2009-05-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (F__accumarray_sum__): Optimize the constant range case.\n\n2009-05-11  John W. Eaton  <jwe@octave.org>\n\n\t* sparse-xdiv.cc (do_rightdiv_sm_dm, do_leftdiv_dm_sm):\n\tAvoid apparent MSVC bug with typedef.\n\n\t* Makefile.in (install-lib): Remove\n\t$(DESTDIR)$(octlibdir)/$(SHLLIBPRE)octinterp.$(SHLLIB_VER), not\n\t$(DESTDIR)$(octlibdir)/$(SHLPRE)octinterp.$(SHLEXT_VER).\n\n2009-05-08  Carsten Clark  <tantumquantum+gnuoctave@gmail.com>\n\n\t* data.cc (Fissorted): Fix typo in documentation entry.\n\n2009-05-07  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* ov-class.h, ov-class.cc (octave_class::reconstruct_exemplar):\n\tNew function.\n\t* ov-class.cc (octave_class::load_binary, octave_class::load_hdf5,\n\toctave_class::load_ascii): Construct exemplar table and ensure\n\tinheritance is correct.\n\t* ov-struct.cc (struct): Return struct from object.\n\n2009-05-07  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (base_graphics_object::set): Undo previous change.\n\t(base_properties::set (const caseless_str&, const octave_value&):\n\tNew virtual function.\n\t(base_properties::set (const caseless_str&, const std::string&,\n\tconst octave_value&)): No longer virtual.\n\n\t* toplev.cc (octave_config_info): Remove F2C and F2CFLAGS from the\n\tconfig infor struct.\n\t* oct-conf.h.in (OCTAVE_CONF_F2CFLAGS, OCTAVE_CONF_F2C):\n\tDelete definitions.\n\n2009-05-07  Marco Atzeri  <marco_atzeri@yahoo.it>\n\n\t* Makefile.in: (SHLPRE): Rename from SHLLIBPRE.\n\n2009-05-07  John W. Eaton  <jwe@octave.org>\n\n\t* genprops.awk (emit_declarations): Emit decls for static\n\thas_property functions.\n\t(emit_source): Add class name argument to base_properties::set\n\tfunction.  Pass class name to set_dynamic and\n\tbase_properties::set.  Emit definitions for has_property\n\tfunctions.\n\t* graphics.h.in, graphics.cc\n\t(base_properties::set, base_properties::set_dynamic):\n\tNew argument CNAME.\n\t(base_properties::all_dynamic_properties): New static data member.\n\t(base_properties::has_dynamic_property): New static function.\n\t(base_graphics_object::set): Pass class name to\n\tbase_properties::set function.\n\t(property_list::set): Check for invalid property names.\n\n2009-05-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-mat.cc (Fdouble): Fix order of branches.\n\n2009-05-05  John Swensen  <jpswensen@comcast.net>\n\n\t* debug.h, debug.cc (breakpoints): Rename from bp_map, use a\n\tstd::set instead of a std::map object.  Change all uses.\n\t(bp_table::do_get_breakpoint_list): Simplify.\n\n2009-05-05  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* ov-class.h, ov-class.cc (octave_class::reconstruct_parents):\n\tNew function.\n\t* ov-class.cc (octave_class::load_binary, octave_class::load_hdf5):\n\tContstruct parent list.\n\t(get_current_method_class): Clean up method class extraction.\n\n2009-05-05  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (array_property::validate): Require object to be any\n\tnumeric type, not necessarily a double precision value.\n\n\t* variables.cc (set_internal_variable): Pass NM in call to error.\n\n2009-05-04  Peter O'Gorman  <pogma@thewrittenword.com>\n\n\t* utils.cc: Don't define HAVE_C99_VSNPRINTF here.\n\n2009-05-01  John W. Eaton  <jwe@octave.org>\n\n\t* error.cc (Vlast_error_file, Vlast_error_name, Vlast_error_line,\n\tVlast_error_column): Delete.\n\t(Vlast_error_stack): New static variable.\n\t(initialize_last_error_stack): New static function.\n\t(verror, Frethrow, Flasterror): Set or use Vlast_error_stack, not\n\tVlast_error_file, etc.\n\n2009-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (octave_class::dotref): Handle empty parent class.\n\t(octave_class::get_current_method_class): Allow result to be empty.\n\t(called_from_builtin): New static function.\n\t(octave_class::subsref, octave_class::subsasgn): Use it.\n\n2009-04-23  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (Fclass): Check newly constructed classes against\n\tthe first constructed object of the class.\n\n\t* ov-class.h, ov-class.cc (octave_class::exmplar_info): New class.\n\t(exemplar_map): New static data member.\n\t(exemplar_iterator, exemplar_const_iterator): New typedefs.\n\n\t* ov-class.h (octave_class::nparents,\n\toctave_class::parent_class_name_list): New functions.\n\t* ov.h (octave_base_value::nparents,\n\toctave_base_value::parent_class_name_list): New functions.\n\t* ov-base.h, ov-base.cc (octave_base_value::nparents,\n\toctave_base_value::parent_class_name_list): New functions.\n\t(parent_class_names): Error if called for wrong type argument.\n\n\t* symtab.cc (load_out_of_date_fcn): New arg, dispatch_type.\n\t(out_of_date_check_internal): Pass dispatch type to\n\tload_out_of_date_fcn.\n\n2009-04-22  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-int.cc (octave_base_int_helper<T, false,\n\tfalse>::char_value_out_of_range): Correct result for specialization.\n\n\t* ov-class.cc (octave_class::dotref, octave_class::subsasgn):\n\tProtect against possibly invalid octave_value -> string conversions.\n\n2009-04-22  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* variables.cc (symbol_exist): Also return 1 for objects.\n\t* ov-base.h (octave_base_value::assign): New virtual function.\n\t* ov-class.h (octave_class::assign): New function.\n\t* ov-class.cc (octave_class::find_parent_class): Simplify.\n\t(octave_class::octave_class): Don't allow duplicate parent classes.\n\t(octave_class::subsasgn): Allow cls = method (cls, value) to work\n\tproperly when method is a parent-class method.\n\t(get_method_class): New static function.\n\t(octave_class:subsasgn, octave_class::dotref): Use it.\n\t(F__isa_parent__): New function.\n\n2009-04-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-range.cc (octave_range::char_array_value): New virtual function\n\toverride.\n\t* ov-range.h: Declare it.\n\n2009-04-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-mat.cc (tm_row_const::tm_row_const_rep::do_init_element):\n\tUpdate class name even for all-zeros elements.\n\t(get_concat_class): Update the default value if possible.\n\n2009-04-21  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (Fassignin): Add missing unwind_protect frame.\n\n\t* toplev.h (push (symbol_table::scope_id, symbol_table::context_id)):\n\tNew function.\n\n\t* toplev.cc (main_loop): Don't call symbol_table::reset_scope.\n\n\t* mex.cc (mexGetVariable, mexPutVariable): Use unwind_protect to\n\trestore call stack and scope.\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tDon't use symbol_table::push_scope.\n\t* variablees.cc (do_who): Likewise.  Use octave_call_stack and\n\tunwind_protect to manage change in scope.\n\t* ov-fcn-handle.cc (octave_fcn_handle::load_ascii,\n\toctave_fcn_handle::load_binary, octave_fcn_handle::load_hdf5):\n\tLikewise.\n\t* ls-mat5.cc (read_mat5_binary_element): Likewise.\n\n\t* symtab.h (erase_scope (void*)): New function, for unwind_protect.\n\t(symbol_table::push_scope, symbol_table::pop_scope,\n\tsymbol_table::reset_scope): Delete.\n\t(symbol_table::scope_stack): Delete static member.\n\t* symtab.cc (symbol_table::scope_stack): Delete definition.\n\n2009-04-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.h (Octave_map::contents (const_iterator) const,\n\tOctave_map::contents (iterator)): Simplify.\n\n2009-04-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.cc (Octave_map::assign (const octave_value_list&, const\n\tstd::string&, const Cell&)): Fix & simplify.\n\t(common_size): Remove.\n\n2009-04-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-idx.cc (make_value_list): Gripe on magic end query for undefined\n\tvariables.\n\n2009-04-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc (same_sign): New helper function.\n\t(elem_xpow (double, const Range&), elem_xpow (const Complex&, const Range&)):\n\tOnly optimize monotonic-magnitude integer ranges, start always from\n\tthe smaller end.\n\n2008-04-11  David Bateman  <dbateman@free.fr>\n\n\t* ov-cell.cc (Fstruct2cell): Treat possible trailing singleton for\n\tcreation of cell array from column structure vector.\n\n2009-04-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cell.cc (octave_cell::subsasgn): Fix reference counting\n\toptimization.\n\n2009-04-08  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (rehash_internal): New function.\n\t(Frehash): Use it.\n\t(Fpath, Faddpath, Frmpath): Call rehash_internal if path is modified.\n\n2009-04-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc (elem_xpow (double, const Range&),\n\telem_xpow (const Complex&, const Range&)): New functions.\n\t* xpow.h: Declare them.\n\t* OPERATORS/op-range.cc: Define scalar .^ range and complex .^ range &\n\tinstall them.\n\n2009-04-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-struct.cc (octave_struct::subsasgn): Fix reference counting\n\toptimization.\n\n2008-04-03  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/max.cc (MINMAX_SPARSE_BODY): Allow sparse boolean\n\tvalues.\n\n2009-04-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-str-mat.cc (default_numeric_conversion_function):\n\tCreate an octave_scalar if possible.\n\n2009-03-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (plot_window::button_press):\n\tDon't pass arbitrary input to fl_message as a format string.\n\n2009-03-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-eval.cc (do_unwind_protect_cleanup_code): Protect also\n\toctave_interrupt_state.\n\n2009-03-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellslices): Index n-d arrays along the\n\tlast dimension.\n\n2009-03-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/balance.cc (Fbalance): Fix order of output args.\n\n2009-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/find.cc\n\t(find_nonzero_elem_idx (const Array<T>&, ...)): Move dimensions\n\tfixup to liboctave.\n\n2009-03-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/find.cc\n\t(find_nonzero_elem_idx (const Array<T>&, ...)): Simplify.\n\tInstantiate for bool and octave_int types.\n\t(find_nonzero_elem_idx (const Sparse<T>&, ...)):\n\tInstantiate for bool.\n\t(Ffind): Handle bool and octave_int cases.\n\n2009-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.55+.\n\t(OCTAVE_API_VERSION): Now api-v37+.\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.55.\n\t(OCTAVE_API_VERSION): Now api-v37.\n\t(OCTAVE_RELEASE_DATE): Now 2009-03-25.\n\n\t* DLD-FUNCTIONS/find.cc (find_nonzero_elem_idx): Also return\n\t[](0x0) if the array has 0 rows and it is not a column vector.\n\n\t* oct-stream.cc (octave_stream::write (const Array<T>&,\n\toctave_idx_type, oct_data_conv::data_type, octave_idx_type,\n\toct_mach_info::float_format)): Seek to skip if still inside bounds\n\tof existing file.  Otherwise, write NUL to skip.\n\n\t* Makefile.in (%.df : %.cc): Write source file name to output,\n\twrapped in XDEFUN_FILE_NAME macro.\n\t* mkbuiltins: Provide definition for XDEFUN_FILE_NAME.\n\t* mkgendoc: Likeiwse.\n\t(XDEFUN_DLD_INTERNAL, XDEFUNX_DLD_INTERNAL, XDEFUN_INTERNAL,\n\tXDEFCONSTFUN_INTERNAL, XDEFUNX_INTERNAL, XDEFVAR_INTERNAL,\n\tXDEFCONST_INTERNAL): Pass file_name to print_doc_string.\n\t(print_doc_string): New arg, FILE_NAME.  Print file name as\n\tcomment.\n\n2009-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (F__parent_classes__): New function.\n\n2009-03-24  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* ov-class.h, ov-class.cc (octave_class::octave_class (const\n\tOctave_map&, const std::string&, const octave_value_list&)):\n\tNew constructor.\n\t(octave_class::find_parent_class, octave_class::parent_classes):\n\tNew functions.\n\t(octave_class::dotref): Also look in parent class.\n\t(Fclass): Handle parent class arguments.\n\n\t* ov-base.h (octave_base_value::get_parent_list,\n\toctave_base_value::parent_classes): New virtual functions.\n\n\t* load-path.h, load-path.cc (load_path::parent_map): New data member.\n\t(load_path::add_to_parent_map): New static function.\n\t(load_path::do_add_to_parent_map): New member function.\n\t(load_path::do_find_method): Also look in parent classes for methods.\n\t(load_path::parent_map_type, load_path::const_parent_map_iterator,\n\tload_path::parent_map_iterator): New typedefs.\n\n2009-03-23  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h\n\t(symbol_table::symbol_record::symobl_recoord_rep::is_variable):\n\tAlso return true if symbol is tagged as a variable.\n\t(symbol_table::symbol_record::symobl_recoord_rep::force_variable):\n\tDon't set variable value.\n\t(symbol_table::symbol_record::symobl_recoord_rep::clear_forced,\n\tsymbol_table::symbol_record::clear_forced): Delete.\n\t(symbol_table::unmark_forced_variables): Rename from\n\tsymbol_table::clear_forced_variables.\n\t(symbol_table::do_unmark_forced_variables): Rename from\n\tsymbol_table::do_clear_forced_variables.\n\t* parse.y (make_script, finish_function): Call\n\tsymbol_table::unmark_forced_variables instead of\n\tsymbol_table::clear_forced_variables.\n\t* octave.cc (unmark_forced_vars): New function.\n\t(execute_eval_option_code): Add it to the unwind-protect stack.\n\n2009-03-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-eval.cc (tree_evaluator::visit_simple_for_command):\n\tRemove struct branch, handle structs by the generic code.\n\t(tree_evaluator::visit_complex_for_command):\n\tAdd missing const qualifiers.\n\n2009-03-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-diag.cc: Add missing include.\n\t* sparse-xdiv.cc: Ditto.\n\t* DLD-FUNCTIONS/__glpk__.cc: Ditto.\n\t* DLD-FUNCTIONS/__lin_interpn__.cc: Ditto.\n\t* DLD-FUNCTIONS/__voronoi__.cc: Ditto.\n\n2009-03-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-mat.cc (octave_matrix::load_ascii): Simplify.\n\t* ov-flt-re-mat.cc (octave_float_matrix::load_ascii): Simplify.\n\t* ov-cx-mat.cc (octave_complex_matrix::load_ascii): Simplify.\n\t* ov-flt-cx-mat.cc (octave_float_complex_matrix::load_ascii): Simplify.\n\n2009-03-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-mat.cc (octave_matrix::isnan, octave_matrix::isinf,\n\toctave_matrix::finite): Simplify.\n\t* ov-flt-re-mat.cc (octave_float_matrix::isnan,\n\toctave_float_matrix::isinf, octave_float_matrix::finite): Simplify.\n\t* ov-cx-mat.cc (octave_complex_matrix::isnan,\n\toctave_complex_matrix::isinf, octave_complex_matrix::finite):\n\tSimplify.\n\t* ov-flt-cx-mat.cc (octave_float_complex_matrix::isnan,\n\toctave_float_complex_matrix::isinf,\n\toctave_float_complex_matrix::finite): Simplify.\n\n2009-03-19  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* ls-oct-ascii.cc (extract_keyword): Replace loop with call to\n\tread_until_newline to avoid leaving stray '\\r' in stream when\n\treading files with CRLF line endings.\n\n2009-03-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc\n\t(scalar_col_helper, scalar_col_helper_def, scalar_col_helper_nda,\n\tscalar_query_helper): New classes.\n\t(make_col_helper): New function.\n\t(Fcellfun): Use col_helper classes for UniformOutput. Avoid copying by\n\tusing const variables.\n\n2009-03-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-b-bm.cc: Add missing INSTALL_BINOPs.\n\t* OPERATORS/op-bm-b.cc: Ditto.\n\t* OPERATORS/op-fm-fm.cc: Ditto.\n\t* OPERATORS/op-m-m.cc: Ditto.\n\n2009-03-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::octave_value): Move to ov.h\n\t* ov.h (octave_value::octave_value): Implement fast inline constructor\n\tusing a static rep.\n\n2009-03-15  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellslices): New DLD function.\n\n2009-03-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::compound_binary_op): Support bool compound ops.\n\t* ov.cc (do_binary_op, decompose_binary_op, binary_op_fcn_name):\n\tDitto.\n\t* pt-cbinop.cc (strip_not, simplify_and_or_op): New funcs.\n\t(maybe_compound_binary_expression): Support bool compound ops.\n\t* OPERATORS/op-int.h: Support bool compound ops.\n\t* OPERATORS/op-b-bm.cc: Ditto.\n\t* OPERATORS/op-bm-b.cc: Ditto.\n\t* OPERATORS/op-bm-bm.cc: Ditto.\n\t* OPERATORS/op-fm-fm.cc: Ditto.\n\t* OPERATORS/op-m-m.cc: Ditto.\n\n2009-03-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc (xpow (const NDArray&, double), xpow (const ComplexNDArray&, double),\n\txpow (const FloatNDArray&, float), xpow (const FloatComplexNDArray&,\n\tfloat)): Use xisint for testing ints. Optimize w.r.t int exponents.\n\n2009-03-13  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (maybe_warn_assign_as_truth_value, make_binary_op,\n\tmaybe_warn_variable_switch_label, maybe_warn_associativity_change):\n\tPrint file and line number info if available.\n\t* lex.l (gripe_matlab_incompatible): Likewise.\n\n\t* error.cc (pr_where): Use octave_call_stack::backtrace to print\n\tcomplete stack trace at once.  Don't attempt to print code.\n\t(error_2): Set error_state to 0 before calling pr_where.\n\t(warning_1): Switch sense of test on symbol_table::at_top_level.\n\tCall pr_where after printing primary warning message.\n\n2009-03-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-range.h (octave_range::octave_range (const Range&)): Allow\n\tconstructing from invalid range op result.\n\t* ov-range.cc (octave_range::try_narrowing_conversion): Validate\n\tinvalid range op results.\n\t* data.cc (fill_matrix): Return packed form (zero-step range) if\n\tpossible.\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* DLD-FUNCTIONS/lu.cc (lu): Call fact.Pr_mat () and fact.Pc_mat ()\n\tto return permutation matrices in the sparse case.\n\n2009-03-12  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat-ascii.cc (get_mat_data_input_line): If we are looking at\n\t'\\r' or '\\n', skip current line ending instead of skipping until\n\tthe next.\n\n2009-03-12  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.cc: Fix default \"papersize\" property value.\n\n2009-03-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-flt-perm.h, ov-flt-perm.cc: Remove sources.\n\t* ov.h, ov.cc (octave_value::octave_value (const PermMatrix&)): Remove\n\tuse \"single\" argument.\n\t* ov.cc (install_types): Update.\n\t* xpow.cc, xpow.h (xpow (PermMatrix, float)): Remove.\n\t* ov-base-diag.cc (octave_base_diag::do_index_op): Remove permutation\n\tcreating block.\n\t* ov-re-diag.cc (octave_diag_matrix::do_index_op): Move it here.\n\t* ov-re-diag.h (octave_diag_matrix::do_index_op): New decl.\n\n\t* DLD-FUNCTIONS/det.cc (Fdet): Update.\n\t* DLD-FUNCTIONS/inv.cc (Finv): Update.\n\t* DLD-FUNCTIONS/pinv.cc (Fpinv): Update.\n\n\t* OPERATORS/op-fcm-pm.cc <-- OPERATORS/op-fcm-fpm.cc\n\t* OPERATORS/op-fcm-pm.cc: Update.\n\t* OPERATORS/op-fm-pm.cc <-- OPERATORS/op-fm-fpm.cc\n\t* OPERATORS/op-fm-pm.cc: Update.\n\t* OPERATORS/op-pm-fcm.cc <-- OPERATORS/op-fpm-fcm.cc\n\t* OPERATORS/op-pm-fcm.cc: Update.\n\t* OPERATORS/op-pm-fm.cc <-- OPERATORS/op-fpm-fm.cc\n\t* OPERATORS/op-pm-fm.cc: Update.\n\t* OPERATORS/op-pm-pm.cc: Update.\n\t* OPERATORS/op-pm-template.cc: Update.\n\n2009-03-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc (xpow (const PermMatrix&, double), xpow (const PermMatrix&,\n\tfloat)): New functions.\n\t* xpow.h: Declare them.\n\t* DLD-FUNCTIONS/op-pm-pm.cc: Support permutation matrix ^ scalar.\n\t* DLD-FUNCTIONS/op-fpm-fpm.cc: Ditto.\n\n2009-03-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-ch-mat.cc (octave_char_matrix::double_value,\n\toctave_char_matrix::float_value, octave_char_matrix::complex_value,\n\toctave_char_matrix::float_complex_value): Cast to unsigned char.\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* OPERATORS/op-pm-sm.cc (mul_pm_sm): New Octave binding for\n\tperm * sparse.\n\t(ldiv_pm_sm): New Octave binding for perm \\ sparse.\n\t(mul_sm_pm): New Octave binding for sparse * perm.\n\t(div_sm_pm): New Octave binding for sparse / perm.\n\t(install_pm_sm_ops): Install the above bindings.\n\n\t* OPERATORS/op-pm-scm.cc (mul_pm_scm): New Octave binding for\n\tperm * sparse complex.\n\t(ldiv_pm_scm): New Octave binding for perm \\ sparse complex.\n\t(mul_scm_pm): New Octave binding for sparse complex * perm.\n\t(div_scm_pm): New Octave binding for sparse complex / perm.\n\t(install_pm_scm_ops): Install the above bindings.\n\n\t* Makefile.in (PERM_OP_XSRC): Add op-pm-sm.cc and op-pm-scm.cc for\n\toperations between permutations and sparse matrices.\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* DLD-FUNCTIONS/find.cc (find_nonzero_elem_idx): New override\n\tfor find on PermMatrix.\n\t(find): Add a branch testing arg.is_perm_matrix () and calling the\n\tabove override.\n\n2009-03-10  John W. Eaton  <jwe@octave.org>\n\n\t* c-file-ptr-stream.cc, dynamic-ld.cc, error.cc, lex.l, pager.cc,\n\tzfstream.cc: Include <iostream>.\n\t* zfstream.h: Include <iosfwd> instead of <istream> and <ostream>.\n\t* c-file-ptr-stream.h, help.h, load-path.h, load-save.h,\n\tls-ascii-helper.h, oct-iostrm.h, oct-stream.h, ov-base-diag.h,\n\tov-base-int.h, ov-base-mat.h, ov-base-scalar.h, ov-base-sparse.h,\n\tov-base.h, ov-bool-mat.h, ov-bool-sparse.h, ov-bool.h, ov-cell.h,\n\tov-ch-mat.h, ov-class.h, ov-colon.h, ov-complex.h, ov-cs-list.h,\n\tov-cx-mat.h, ov-cx-sparse.h, ov-fcn-handle.h, ov-fcn-inline.h,\n\tov-float.h, ov-flt-complex.h, ov-flt-cx-mat.h, ov-flt-re-mat.h,\n\tov-intx.h, ov-list.h, ov-range.h, ov-re-mat.h, ov-re-sparse.h,\n\tov-scalar.h, ov-str-mat.h, ov-struct.h, ov.h, pager.h,\n\tpr-output.h, procstream.h, pt-assign.h, pt-cell.h, pt-const.h,\n\tpt-fcn-handle.h, pt-id.h, pt-mat.h, pt.h, utils.h:\n\tInclude <iosfwd> instead of <iosstream>.\n\n2009-03-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fsize_equal): Allow single argument call.\n\t* DLD-FUNCTIONS/max.cc (Fcummin, Fcummax): Update docs.\n\n2009-03-09  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* ls-ascii-helper.h, ls-ascii-helper.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\t* load-save.cc (Fload): Open all files in binary mode.\n\t* ov-range.cc (load_ascii): Explicitly handle CR and CRLF line endings.\n\t* ov-fcn-handle.cc (load_ascii): Likewise.\n\t* ov-fcn-inline.cc (load_ascii): Likewise.\n\t* ov-str-mat.cc (load_ascii): Likewise.\n\t* ls-mat-ascii.cc (get_mat_data_input_line): Likewise.\n\t* ls-oct-ascii.cc (extract_keyword, read_ascii_data): Likewise.\n\t* ls-oct-ascii.h (extract_keyword): Likewise.\n\n2009-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (OCTAVE_DEFAULT_FONTNAME): New macro, defaults to \"*\".\n\t(axes::properties, text::properties): Use it to set default fontname.\n\t* graphics.cc (axes::properties::set_defaults): Likewise.\n\n2009-03-09  Rafael Laboissiere  <rafael@debian.org>\n\n\t* Makefile.in (maintainer-clean): Remove y.tab.h here.\n\t(distclean): Not here.\n\n2009-03-09  Jason Riedy  <jason@acm.org>\n\n\t* OPERATORS/op-dm-sm.cc (add_dm_sm): Octave binding for diag + sparse.\n\t(sub_dm_sm): Octave binding for diag - sparse.\n\t(add_sm_dm): Octave binding for diag + sparse.\n\t(sub_sm_dm): Octave binding for diag - sparse.\n\t(install_dm_sm_ops): Install above bindings.\n\n\t* OPERATORS/op-dm-scm.cc (add_cdm_sm): Octave binding for diag + sparse.\n\t(add_dm_scm): Octave binding for diag + sparse.\n\t(add_cdm_scm): Octave binding for diag + sparse.\n\t(sub_cdm_sm): Octave binding for diag - sparse.\n\t(sub_dm_scm): Octave binding for diag - sparse.\n\t(sub_cdm_csm): Octave binding for diag - sparse.\n\t(add_sm_cdm): Octave binding for diag + sparse.\n\t(add_scm_dm): Octave binding for diag + sparse.\n\t(add_scm_cdm): Octave binding for diag + sparse.\n\t(sub_sm_cdm): Octave binding for diag - sparse.\n\t(sub_scm_dm): Octave binding for diag - sparse.\n\t(sub_scm_cdm): Octave binding for diag - sparse.\n\t(install_dm_scm_ops): Install above bindings.\n\n2009-03-08  Jason Riedy  <jason@acm.org>\n\n\t* sparse-xdiv.h (xleftdiv): Declare overrides for\n\txleftdiv (diagonal, sparse), both real and complex.\n\t(xdiv): Declare overrides for xdiv (sparse, diagonal), both real\n\tand complex.\n\n\t* sparse-xdiv.cc (do_rightdiv_sm_dm): New template function.\n\tImplementation for xdiv (sparse, diagonal).\n\t(xdiv): Call do_rightdiv_sm_dm to implement overrides, real and\n\tcomplex.\n\t(do_leftdiv_dm_sm): New template function.  Implementation for\n\txleftdiv (diagonal, sparse).\n\t(xleftdiv): Call do_leftdiv_dm_sm to implement overrides, real and\n\tcomplex.\n\n\t* OPERATORS/op-dm-sm.cc (ldiv_dm_sm): Octave binding for real left\n\tdivision, diagonal into sparse.\n\t(div_sm_dm): Octave binding for real right division, sparse by\n\tdiagonal.\n\t(install_dm_sm_ops): Install above bindings.\n\n\t* OPERATORS/op-dm-scm.cc (ldiv_dm_scm): Octave binding for real\n\tdiagonal \\ complex sparse.\n\t(ldiv_cdm_sm): Octave binding for complex diagonal \\ real sparse.\n\t(ldiv_cdm_scm): Octave binding for complex diagonal \\ complex sparse.\n\t(div_scm_dm): Octave binding for complex sparse / real diagonal.\n\t(div_sm_cdm): Octave binding for real sparse / complex diagonal.\n\t(div_scm_cdm): Octave binding for complex sparse / complex diagonal.\n\t(install_dm_scm_ops): Install above bindings.\n\n2009-03-08  Jason Riedy  <jason@acm.org>\n\n\t* OPERATORS/op-dm-scm.cc: New file.  Implement multiplication\n\tbetween diagonal matrices (both real and complex) and complex\n\tsparse matrices.\n\t* OPERATORS/op-dm-sm.cc: New file.  Implement multiplication\n\tbetween diagonal matrices and sparse matrices, all real.\n\t* Makefile.in (DIAG_OP_XSRC): Add op-dm-sm.cc and op-dm-scm.cc.\n\n2009-03-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (F__accumarray_sum__): New function.\n\t(do_accumarray_sum): New helper template function.\n\n2009-03-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xdiv.cc (mdm_div_impl, dmm_lelftdiv_impl, dmdm_div_impl,\n\tdmdm_leftdiv_impl): Optimize.\n\n2009-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (octave_print_internal (std::ostream&,\n\tconst PermMatrix&, bool, int)): Delete unused variable SCALE.\n\n\t* utils.cc (octave_vsnprintf): Avoid uninitialized variable\n\twarning from GCC.\n\n\t* DLD-FUNCTIONS/qz.cc (Fqz): Avoid \"maybe clobbered by vfork\"\n\twarning from GCC.\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.54.\n\t(OCTAVE_API_VERSION): Now api-v36.\n\t(OCTAVE_RELEASE_DATE): Now 2009-03-07.\n\n\t* octave.cc (verbose_usage): Include --doc-cache-file in option list.\n\n2009-03-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::diag_matrix_value,\n\toctave_value::complex_diag_matrix_value,\n\toctave_value::float_diag_matrix_value,\n\toctave_value::float_complex_diag_matrix_value,\n\toctave_value::perm_matrix_value): New methods.\n\n\t* ov-base.cc (octave_base_value::diag_matrix_value,\n\toctave_base_value::complex_diag_matrix_value,\n\toctave_base_value::float_diag_matrix_value,\n\toctave_base_value::float_complex_diag_matrix_value,\n\toctave_base_value::perm_matrix_value): New virtual methods.\n\n\t* ov-base.h: Declare them.\n\n\t* ov-base-diag.h (octave_base_diag::diag_matrix_value,\n\toctave_base_diag::complex_diag_matrix_value,\n\toctave_base_diag::float_diag_matrix_value,\n\toctave_base_diag::float_complex_diag_matrix_value,\n\toctave_base_diag::perm_matrix_value): Remove declarations.\n\n\t* DLD-FUNCTIONS/inv.cc (Finv): Simplify handling diag & perm matrices.\n\t* DLD-FUNCTIONS/pinv.cc (Fpinv): Ditto.\n\t* DLD-FUNCTIONS/det.cc (Fdet): Ditto.\n\n2009-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ls-hdf5.cc (add_hdf5_data): Handle diag & perm matrices.\n\n2009-03-05  John W. Eaton  <jwe@octave.org>\n\n\t* pt-cell.cc, pt-cell.h (tree_cell::dup): Now const.\n\t* comment-list.cc, comment-list.h (octave_comment_list::dup): Ditto.\n\t* pt-arg-list.cc, pt-arg-list.h (tree_argument_list::dup): Ditto.\n\t* pt-assign.cc, pt-assign.h (tree_simple_assignment::dup,\n\ttree_multi_assignment::dup): Ditto.\n\t* pt-binop.cc, pt-binop.h (tree_binary_expression::dup,\n\ttree_boolean_expression::dup): Ditto.\n\t* pt-cmd.cc, pt-cmd.h (tree_no_op_command::dup,\n\ttree_function_def::dup): Ditto.\n\t* pt-colon.cc, pt-colon.h (tree_colon_expression::dup): Ditto.\n\t* pt-const.cc, pt-const.h (tree_constant::dup): Ditto.\n\t* pt-decl.cc, pt-decl.h (tree_decl_elt::dup, tree_decl_init_list::dup,\n\ttree_global_command::dup, tree_static_command::dup): Ditto.\n\t* pt-except.cc, pt-except.h (tree_try_catch_command::dup,\n\ttree_unwind_protect_command::dup): Ditto.\n\t* pt-fcn-handle.cc, pt-fcn-handle.h (tree_fcn_handle::dup,\n\ttree_anon_fcn_handle::dup): Ditto.\n\t* pt-id.cc, pt-id.h (tree_identifier::dup): Ditto.\n\t* pt-idx.cc, pt-idx.h (tree_index_expression::dup): Ditto.\n\t* pt-jump.cc, pt-jump.h (tree_break_command::dup,\n\ttree_continue_command::dup, tree_return_command::dup): Ditto.\n\t* pt-loop.cc, pt-loop.h (tree_while_command::dup,\n\ttree_do_until_command::dup, tree_simple_for_command::dup,\n\ttree_complex_for_command::dup): Ditto.\n\t* pt-mat.cc, pt-mat.h (tree_matrix::dup): Ditto.\n\t* pt-misc.cc, pt-misc.h (tree_parameter_list::dup,\n\ttree_return_list::dup): Ditto.\n\t* pt-select.cc, pt-select.h (tree_if_clause::dup,\n\ttree_if_command_list::dup, tree_if_command::dup,\n\ttree_switch_case::dup, tree_switch_case_list::dup,\n\ttree_switch_command::dup): Ditto.\n\t* pt-stmt.cc, pt-stmt.h (tree_statement::dup,\n\ttree_statement_list::dup): Ditto.\n\t* pt-unop.cc, pt-unop.h (tree_prefix_expression::dup,\n\ttree_postfix_expression::dup): Ditto.\n\t* pt-fcn-handle.h (tree_anon_fcn_handle::parameter_list,\n\ttree_anon_fcn_handle::return_list, tree_anon_fcn_handle::body,\n\ttree_anon_fcn_handle::scope): Ditto.\n\n2009-03-05  Jason Riedy  <jason@acm.org>\n\n\t* ov-base-int.cc (convert_to_str_internal): Replace elt_type with\n\telement_type throughout.\n\n2009-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/sparse.cc (Fsparse): Handle diagonal and permutation\n\tmatrices.\n\n2009-03-03  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (octave_struct::save_ascii,\n\toctave_struct::save_binary, octave_struct::save_hdf5):\n\tPreserve order of structure fields.\n\t* ls-mat5.cc (save_mat5_binary_element): Likewise.\n\n\t* symtab.h (symbol_table::do_inherit): Only inherit values for\n\tsymbols from the donor_scope that already exist in the table.\n\t(symbol_table::symbol_record::symbol_record_rep::dup): Now const.\n\t(symbol_table::symbol_record::operator=): Decrement rep->count and\n\tmaybe delete rep.\n\t(symbol_table::fcn_info::operator=): Likewise.\n\n\t* pt-fcn-handle.cc: (tree_anon_fcn_handle::dup): Transform\n\ttree_anon_fcn_handle objects to tree_constant objects containing\n\toctave_fcn_handle objects.  New tests.\n\n\t* pt-assign.cc (tree_simple_assignment::rvalue1): Assign result of\n\tcall to rhs->rvalue1() to an octave_value object, not an\n\toctave_value_list object.\n\n2009-03-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-stream.h (octave_stream_list::lookup_cache): New member field.\n\t(octave_stream_list::octave_stream_list): Initialize it.\n\t(octave_stream_list::do_lookup): Use it.\n\t(octave_stream_list::clear): Make flush optional. Do physically erase\n\tentries from the map. Close files.\n\t(octave_stream_list::do_remove): Call clear on \"all\". Do erase deleted\n\tentry from the map.\n\n2009-03-02  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (Fget, F__get__): Return a column vector of property\n\tvalues, not a row vector.\n\n2009-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-fcm-fcm.cc (DEFNDASSIGNOP_FN (dbl_assign)):\n\tLHS type is float_complex_matrix, not complex_matrix.  RHS value\n\tfunction is float_complex_array, not complex_array.\n\n2009-03-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-perm.cc (octave_perm_matrix::print_raw): Call\n\toctave_print_internal.\n\t(octave_perm_matrix::print_raw): Call print_raw.\n\t* pr-output.cc (octave_print_internal (...,const DiagMatrix&,...)):\n\tIndicate diagonal matrix.\n\t(octave_print_internal (...,const ComplexDiagMatrix&,...)): Ditto.\n\t(octave_print_internal (...,const PermMatrix&,...)): New function.\n\t* pr-output.h: Declare it.\n\n2009-02-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-dms-template.cc (gripe_if_zero): New template static\n\tfunction.\n\t(dmsdiv, sdmldiv): Call it.\n\n2009-02-26  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h (symbol_table::symbol_record::symbol_record_rep::forced):\n\tNew static constant.\n\t(symbol_table::symbol_record::symbol_record_rep::force_variable,\n\tsymbol_table::symbol_record::force_variable): New functions.\n\t(symbol_table::symbol_record::symbol_record_rep::is_forced,\n\tsymbol_table::symbol_record::symbol_record_rep::mark_forced,\n\tsymbol_table::symbol_record::symbol_record_rep::unmark_forced,\n\tsymbol_table::symbol_record::symbol_record_rep::clear_forced,\n\tsymbol_table::symbol_record::is_forced,\n\tsymbol_table::symbol_record::mark_forced,\n\tsymbol_table::symbol_record::clear_forced,\n\tsymbol_table::symbol_record::unmark_forced): New fucntions.\n\t* lex.h, lex.l (force_local_variable): Delete.\n\t(handle_identifier): Call symbol_table::force_variable instead of\n\tforce_local_variable.\n\t* parse.y (make_script): Call symbol_table:clear_forced_variables\n\tafter defining script.\n\t(finish_function): Call symbol_table::clear_forced_variables\n\tinstead of symbol_table::clear_variables.\n\n\t* DLD-FUNCTIONS/chol.cc: Correct spelling of CHOLMOD in tests.\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.53+.\n\t(OCTAVE_API_VERSION): Now api-v35+.\n\n2009-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.53.\n\t(OCTAVE_API_VERSION): Now api-v35.\n\t(OCTAVE_RELEASE_DATE): Now 2009-02-25.\n\t(OCTAVE_COPYRIGHT): Update year.\n\n\t* Makefile.in (distclean): Remove tags TAGS y.tab.h y.output\n\tyy.lex.c here, not in maintainer-clean target.  Also remove\n\tparse.output.\n\n\t* DLD-FUNCTIONS/rand.cc: Note that the tests for the old random\n\tnumber generator will fail if using 64-bit indexing.\n\n2009-02-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lu.cc (maybe_set_triangular): New function.\n\t(Flu): Use it.\n\t* DLD-FUNCTIONS/qr.cc (maybe_set_triangular): New function.\n\t(Fqr): Use it.\n\n2009-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/chol.cc: Fix tests for missing cholmod.\n\n\t* input.cc (get_debug_input): Write debugging location info\n\tdirectly to std::cerr instead of calling message.\n\t* pt-eval.cc (tree_evaluator::do_breakpoint): Write debugging\n\tlocation info directly to std::cerr, not octave_stdout.\n\n\t* defaults.h.in (OCTAVE_DOC_CACHE_FILE): New macro.\n\t* defaults.cc (set_default_doc_cache_file): New function.\n\t(install_defaults): Call it.\n\n\t* help.cc (__list_functions__): Simplify\n\n\t* input.cc (get_debug_input): Don't pass arbitrary input to\n\tmessage as a format string.\n\n2009-02-24  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc, help.h (Vdoc_cache_file): New global variable.\n\t(Fdoc_cache_file): New function.\n\t* octave.cc (DOC_CACHE_FILE_OPTION): New option tag.\n\t(long_opts): Include doc-cache-file in the list.\n\t(octave_main): Handle DOC_CACHE_FILE_OPTION.\n\n2009-02-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-scalar.h\n\t(octave_scalar::int8_scalar_value): New method.\n\t(octave_scalar::int16_scalar_value): New method.\n\t(octave_scalar::int32_scalar_value): New method.\n\t(octave_scalar::int64_scalar_value): New method.\n\t(octave_scalar::uint8_scalar_value): New method.\n\t(octave_scalar::uint16_scalar_value): New method.\n\t(octave_scalar::uint32_scalar_value): New method.\n\t(octave_scalar::uint64_scalar_value): New method.\n\n\t* ov-float.h\n\t(octave_float_scalar::int8_scalar_value): New method.\n\t(octave_float_scalar::int16_scalar_value): New method.\n\t(octave_float_scalar::int32_scalar_value): New method.\n\t(octave_float_scalar::int64_scalar_value): New method.\n\t(octave_float_scalar::uint8_scalar_value): New method.\n\t(octave_float_scalar::uint16_scalar_value): New method.\n\t(octave_float_scalar::uint32_scalar_value): New method.\n\t(octave_float_scalar::uint64_scalar_value): New method.\n\n\t* OPERATORS/op-s-s.cc (scalar_to_float): Remove duplicate conversion.\n\t* OPERATORS/op-range.cc (range_to_float_matrix): Ditto.\n\n2009-02-24  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-float-conv.cc: New file.\n\t* Makefile.in (FLOAT_OP_XSRC): Add it to the list.\n\t(DOUBLE_OP_XSRC): Move op-double-conv.cc here from INTTYPE_OP_XSRC.\n\t* ops.h (DEFFLTCONVFN, DEFSTRFLTCONVFN): New macros.\n\n2009-02-23  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-sparse.cc (octave_base_sparse<T>::print_raw):\n\tRemove extra \")\" from output.\n\n\t* DLD-FUNCTIONS/eigs.cc (Feigs): If sigma argument is not a\n\tstring, try extraction as complex value and check for error\n\tinstead of inquiring about type first.\n\n\t* pt-eval.cc (tree_evaluator::visit_break_command,\n\ttree_evaluator::visit_return_command,\n\ttree_evaluator::visit_global_command,\n\ttree_evaluator::visit_static_command): Handle breakpoint.\n\t(tree_evaluator::visit_simple_for_command,\n\ttree_evaluator::visit_complex_for_command): Handle breakpoint once\n\tat beginning of loop.\n\t(tree_evaluator::visit_if_command_list): Don't call do_breakpoint\n\tfor else clauses.\n\t(tree_evaluator::visit_no_op_command): Handle breakpoint if no-op\n\tcommand is end of function or script.\n\t(tree_evaluator::visit_statement): Handle breakpoint for\n\texpressions but not commands.\n\t(tree_evaluator::visit_while_command,\n\ttree_evaluator::visit_do_until_command):\n\tCheck for breakpoint set on cmd, not expr.\n\t(tree_evaluator::visit_do_until_command): Handle breakpoint\n\tbetween check for breaking out of loop and loop control\n\texpression.\n\n\t* pt-cmd.h (tree_no_op_command::eof): New data member\n\t(tree_no_op_command::tree_no_op_command): Initialize it.\n\t(tree_no_op_command::is_end_of_fcn_or_script): New function.\n\t* pt-stmt.cc (tree_statement::is_end_of_fcn_or_script):\n\tCall is_end_of_fcn_or_script instead of looking at original text\n\tof no-op command.\n\n\t* pt-select.h, pt-select.cc (tree_if_command::set_breakpoint,\n\ttree_if_command::delete_breakpoint): New functions.\n\t(tree_switch_command::set_breakpoint,\n\ttree_switch_command::delete_breakpoint): New functions.\n\t* pt-stmt.h, pt-stmt.cc (tree_statement::set_breakpoint,\n\ttree_statement::delete_breakpoint, tree_statement::is_breakpoint):\n\tDelegate real work to cmd or expr.\n\t(tree_statement::bp): Delete data member.\n\t(tree_statement::tree_statement): Don't initialize bp.\n\t(tree_statement::dup): Don't copy bp.\n\n\t* pt.h (tree::line (int), tree:column (int)): New functions.\n\t(tree:set_breakpoint, tree::delete_breakpoint): Now virtual.\n\n\t* parse.y (finish_if_command): Also store line and column info for\n\tif statement in first element of list.\n\t(finish_switch_command): Likewise, for switch.\n\n\t* input.cc (last_debugging_command): New static variable.\n\t(octave_gets): Set it here.  Don't insert repeated debugging\n\tcommands in the history list.\n\n2009-02-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/pinv.cc: Support diagonal and permutation matrices.\n\n2008-02-21  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc, OPERATORS/op-s-scm.cc,\n\tOPERATORS/op-s-sm.cc, OPERATORS/op-scm-cs.cc, OPERATORS/op-scm-s.cc,\n\tOPERATORS/op-sm-cs.cc, OPERATORS/op-sm-s.cc: Don't perform any\n\tnarrowing to full matrices.\n\n2009-02-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-diag.h (octave_base_diag::sqrt): Remove.\n\t* ov-re-diag.cc (octave_diag_matrix::sqrt): New method.\n\t* ov-re-diag.h: Declare it.\n\t* ov-flt-re-diag.cc (octave_float_diag_matrix::sqrt): New method.\n\t* ov-flt-re-diag.h: Declare it.\n\t* ov-cx-diag.cc (octave_complex_diag_matrix::sqrt): New method.\n\t* ov-cx-diag.h: Declare it.\n\t* ov-flt-cx-diag.cc (octave_float_complex_diag_matrix::sqrt): New method.\n\t* ov-flt-cx-diag.h: Declare it.\n\n2009-02-20  John W. Eaton  <jwe@octave.org>\n\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_mex): Clear and\n\treload mex file if it is out of date.  Don't check path for file.\n\n\t* pt-bp.cc (tree_breakpoint::visit_octave_user_script,\n\ttree_breakpoint::visit_octave_user_function):\n\tDon't panic.  Call accept on command list if it exists.\n\n2009-02-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::do_index_op):\n\tCorrectly compute all-scalar index.\n\t* ov-cell.cc (octave_cell::is_sorted, octave_cell::is_sorted_rows):\n\tNew methods.\n\t(octave_cell::octave_cell (const Array<std::string>&)): New\n\tconstructor.\n\t* ov-cell.h: Declare them.\n\t* ov-cell.cc (octave_cell::sort): Create result already with\n\tcellstr_cache.\n\t* strfns.cc (Fstrcmp): Use special code when dealing with\n\tcellstr arrays.\n\n2009-02-20  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::assign):\n\tCorrectly compute all-scalar index.\n\n\t* symbtab.cc (symbol_table::stash_dir_name_for_subfunctions):\n\tNew function.\n\t* symtab.h: Provide decl.\n\t* parse.y (load_fcn_from_file): Call it after parsing a function.\n\n2009-02-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cell.h (octave_cell::cellstr_cache): New field.\n\t(octave_cell::clear_cellstr_cache, octave_cell::make_cellstr_cache,\n\toctave_cell::assign, octave_cell::delete_elements,\n\toctave_cell::mex_get_data): New methods.\n\t(octave_cell::is_cellstr): Reuse cellstr cache if possible, create if\n\tsuccessful.\n\t(octave_cell::cellstr_value): Reuse cellstr cache if possible.\n\t(octave_cell::subsasgn): Clear cellstr cache.\n\n2009-02-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Use Array<T>::lookup if possible.\n\tDo not compare octave_values directly. Properly check for iscellstr.\n\n2009-02-19  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc, graphics.cc, help.cc, lex.l, load-path.cc, parse.y:\n\tConsistent doc strings for internal functions.\n\n2009-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* ov.cc (convert_to_octave_idx_type_array): New static function.\n\t(octave_value::octave_idx_type_vector_value): New function.\n\t* ov.h (octave_value::octave_idx_type_vector_value): Provide decl.\n\t* DLD-FUNCTIONS/qr.cc (Fqrdelete, Fqrinsert): Use it to convert\n\toctave_value object to array of octave_idx_type values.\n\n\t* DLD-FUNCTIONS/find.cc (find_nonzero_elem_idx): Likewise.\n\t* DLD-FUNCTIONS/time.cc (strptime): Likewise.\n\t* DLD-FUNCTIONS/quad.cc (Fquad): Eliminate unnecessary cast.\n\t* toplev.cc (run_command_and_return_output): Likewise.\n\n\t* strfns.cc (Fstrvcat): Use octave_idx_type and size_t instead of\n\tint as needed.\n\t(Fstrcmp, Fstrncmp): Use octave_idx_type instead of int as needed.\n\n\t* DLD-FUNCTIONS/hex2num.cc (Fhex2num, Fnum2hex):\n\tUse union to avoid reinterpret_cast and GCC warning.\n\n\t* mex.cc (call_mex): Declare local nargout variable volatile to\n\tavoid \"maybe clobbered by vfork\" warning from GCC.\n\n\t* ov-cx-mat.cc (xabs): Comment out unused static function.\n\t* ov-flt-cx-mat.cc (xabs): Ditto.\n\n\t* c-file-ptr-stream.cc (c_file_ptr_buf::seekoff,\n\tc_file_ptr_buf::seepos, c_zfile_ptr_buf::seekoff,\n\tc_zfile_ptr_buf::seepos): Avoid unused paramter warnings.\n\n2009-02-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (Fresize): Allow arbitrary number of parameters. Improve\n\tdocumentation.\n\n2009-02-17  Benjamin Lindner  <lindnerb@users.sourceforge.net>\n\n\t* file-io.cc: (Fmkstemp): Use mkstemps if it is available and\n\tmkstemp is missing.\n\n2009-02-17  Olaf Till  <olaf.till@uni-jena.de>\n\n\t* DLD-FUNCTIONS/lsode.cc, DLD-FUNCTIONS/daspk.cc,\n\tDLD-FUNCTIONS/dassl.cc, DLD-FUNCTIONS/dasrt.cc: Documentation fixes.\n\n2009-02-17  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/convhulln.cc (Fconvhulln): Compute convex hull\n\tvolume and return it as second output.  New tests.\n\n2009-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn.h (octave_function::octave_function): Initialize data members.\n\t(octave_function::dispatch_class): No longer virtual.\n\tReplace with version from ov-usr-fcn.h.\n\t(octave_function::xdispatch_class,\n\toctave_function::stash_dispatch_class): Move here from ov-usr-fcn.h.\n\t(octave_function::mark_as_private_function,\n\toctave_function::is_private_function,\n\toctave_function::is_private_function_of_class): New functions.\n\t(octave_function::private_function): New data member.\n\t* ov-usr-fcn.h (octave_user_function::xdispatch_class,\n\toctave_user_function::stash_dispatch_class,\n\toctave_user_function::dispatch_class): Delete.\n\t* ov-usr-fcn.cc (octave_user_function::octave_user_function):\n\tDon't initialize xdispatch_type.\n\n\t* symtab.cc\n\t(symbol_table::fcn_info::fcn_info_rep::load_private_function):\n\tIf private directory is subdirectory of class directory, qmark\n\tfunction as a private directory of the class.\n\n\t* ov-class.cc (octave_class::in_class_method): Also return true\n\tfor functions that are private to a class.\n\t(octave_class::subsasgn): If not in class method, look for\n\tsubsasgn method.  If not found, or if not in a class method,\n\tperform default struct-style subscripted indexing.\n\n\t* ov-class.h (octave_class::empty_clone):\n\tPreserve fields and class name.\n\t* oct-map.h (Octave_map::Octave_map (const string_vector&):\n\tNew constructor.\n\n\t* ov-class.cc (octave_class::subsref): If indexing directly and\n\tresult is map, return class object, not simple struct.\n\n\t* symtab.cc\n\t(symbol_table::fcn_info::fcn_info_rep::load_private_function):\n\tPass dir_name to load_fcn_from_file.\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/data.cc (NATIVE_REDUCTION): Add BOOL_FCN argument.\n\t(NATIVE_REDUCTION_1): Check integer overflow flags and possibly gripe.\n\t(Fsum): Reflect change.\n\t(Fcumsum): USE NATIVE_REDUCTION.\n\t* gripes.cc (gripe_native_integer_math_truncated): New function.\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/max.cc (Fcummin, Fcummax): Improve inline docs.\n\n2009-02-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/max.cc (MINMAX_DOUBLE_SBODY): New macro.\n\t(MINMAX_DOUBLE_BODY): Move part of code to MINMAX_DOUBLE_SBODY.\n\t(MINMAX_SINGLE_SBODY): New macro.\n\t(MINMAX_SINGLE_BODY): Move part of code to MINMAX_DOUBLE_SBODY.\n\t(MINMAX_INT_SBODY): New macro.\n\t(MINMAX_INT_BODY): Move part of code to MINMAX_DOUBLE_SBODY.\n\t(CUMMINMAX_BODY): New macro.\n\t(Fcummin, Fcummax): New DLD functions.\n\n2009-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* octave.gperf: Eliminate whitespace to allow gperf 2.7.2 to work.\n\n\t* file-io.cc (Ffscanf, Fsscanf): Check error_state after call to\n\toctave_stream::scanf.\n\t(Ffgetl): Check error state after call to octave_stream::getl.\n\t(Ffgets): Check error state after call to octave_stream::gets.\n\n\t* oct-stream.cc (octave_base_stream::do_gets,\n\toctave_base_stream::do_scanf):\n\tDisallow reading from stdin when running interactively.\n\n\t* toplev.cc (octave_config_info): Add CARBON_LIBS, X11_INCFLAGS,\n\tand X11_LIBS to the struct.\n\t* oct-conf.h.in (OCTAVE_CONF_CARBON_LIBS,\n\tOCTAVE_CONF_X11_INCFLAGS, OCTAVE_CONF_X11_LIBS): New macros.\n\n2009-02-17  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* Makefile.in (octave$(EXEEXT)): Link with CARBON_LIBS.\n\n2009-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (next_token_can_follow_bin_op):\n\tPush all characters read on to buffer stack.\n\n\t* genprops.awk (emit_source): Don't use + to concatenate strings.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* data.cc (NATIVE_REDUCTION): Use boolNDArray::any for native bool\n\tsummation, boolNDArray::sum for double-valued.\n\n2009-02-16  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::assign (const octave_value_list&,\n\ttypename MT::element_type): Fix invalid index.\n\t* ov-re-mat.cc (default_numeric_demotion_function): Use\n\tfloat_array_value instead of float_matrix_value.\n\n2009-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (gnu_readline): Use fputs instead of fprintf.\n\n2009-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* defun.cc, defun-int.h, defun-dld.h (DEFUN_INTERNAL,\n\tDEFCONSTFUN_INTERNAL, DEFUNX_INTERNAL, DEFUN_DLD_INTERNAL,\n\tDEFUNX_DLD_INTERNAL, install_builtin_function,\n\tinstall_dld_function, install_mex_function):\n\tDelete IS_TEXT_FCN arg.  Fix all uses.\n\t(DEFMD, DEFUN_TEXT): Delete.\n\t* mkbuiltins, mkgendoc: Adapt to DEFUN macro changes.\n\n\t* lex.h, lex.l (lexer_flags::at_beginning_of_statement):\n\tNew data member.  Set it as needed in rules.\n\t(is_keyword_token):\n\tHandle lexer_flags::at_beginning_of_statement.\n\t(next_token_can_follow_bin_op, looks_like_command_arg): New functions.\n\t(handle_identifier): Use them to determine\n\tDon't check is_command_name or is_rawcommand_name.\n\t* parse.y (statement): Recognize word_list_cmd here.\n\t(expression): Not here.\n\n\t* lex.l (handle_string): Delete arg TEXT_STYLE.\n\t(BIN_OP_RETURN, XBIN_OP_RETURN): New arg, BOS. Change all uses.\n\n\t* lex.h, lex.l (lexer_flags::doing_raw_command): Delete data\n\tmember and all uses.\n\n\t* debug.cc, dirfns.cc, error.cc, input.cc, lex.l, load-path.cc,\n\tload-save.cc, oct-hist.cc, ov-class.cc, pager.cc, parse.y,\n\tpr-output.cc, sysdep.cc, utils.cc, variables.cc:\n\tReplace all uses of DEFCMD with DEFUN.\n\n\t* variables.cc (command_set, rawcommand_set): Delete static variables.\n\t(mark_as_command, unmark_command, is_command_name,\n\tmark_as_rawcommand, unmark_raw_command, is_rawcommand_name): Delete.\n\t(Fmark_as_command, Funmark_command, Fiscommand,\n\tFmark_as_rawcommand, Funmark_rawcommand, Fisrawcommand):\n\tConvert to .m files and move to scripts/deprecated.\n\t* variables.h (mark_as_command, is_command_name,\n\tis_marked_as_rawcommand, mark_as_rawcommand, unmark_rawcommand,\n\tis_rawcommand_name): Delete decls.\n\n\t* lex.h, lex.l (lexer_flags.looking_at_object_index): Now a\n\tstd::list<bool> object instead of an int.\n\tPush TRUE to list at start of object index.  Push FALSE at\n\tbeginning of matrix list.  Pop value at end of object index or\n\tmatrix list.\n\t(lexer_flags.looking_for_object_index): New data member.\n\tSet it as needed in rules.\n\t(inside_any_object_index): New function.\n\t* parse.y (begin_obj_idx, cancel_obj_idx): Delete non-terminals\n\tand all uses.\n\n2009-02-13 Ben Abbott  <bpabott@mac.com>\n\n\t* graphics.h.in (class axes::properties): Initialize ticklength.\n\t* graphics.cc (default_axes_ticklength): New function.\n\n2009-02-13  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_base_stream::do_gets): Handle CRLF and CR.\n\n\t* toplev.cc (do_octave_atexit): Only save history if\n\tVsaving_history is true.\n\n2009-02-12  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc, ov-base-diag.h, ov-base-mat.h, ov-base-scalar.h,\n\tov-base-sparse.h, ov-base.cc, ov-base.h, ov-perm.h, ov-range.h,\n\tov.h: Rename internal issorted and issorted_rows functions to\n\tis_sorted and is_sorted_rows.\n\n\t* ov-base-diag.h, ov-base-mat.h, ov-base-scalar.h, ov-base.h,\n\tov-cell.h, ov-perm.h, ov-range.h, ov.h, data.cc, ov-base.cc,\n\tov-cell.cc: Rename all uses of sortrows_idx to sort_rows_idx.\n\n\t* TEMPLATE-INST/Array-tc.cc: Don't instantiate sort functions for\n\tArrays of octave_value objects.\n\t(octave_sort<octave_value>::ascending_compare,\n\toctave_sort<octave_value>::descending_compare): Delete.\n\n\t* ov.h (octave_value::cellstr_value): New function.\n\t* ov-base.cc, ov-base.h (octave_base_value::cellstr_value):\n\tNew function.\n\t* ov-cell.h (octave_cell::cellstr_value, octave_cell::sort,\n\toctave_cell::sortrows_idx): New functions\n\t* Cell.h, Cell.cc (Cell::Cell (Array<std::string>)): New constructor.\n\n\t* TEMPLATE-INST/Array-tc.cc: Undo previous change.\n\t(octave_sort<octave_value>::ascending_compare,\n\toctave_sort<octave_value>::descending_compare):\n\tPass args by const reference instead of value.\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.52+.\n\t(OCTAVE_API_VERSION): Now api-v34+.\n\n\t* TEMPLATE-INST/Array-tc.cc\n\t(octave_sort<octave_value>::ascending_compare,\n\toctave_sort<octave_value>::descending_compare):\n\tDelete unused template specializations.\n\tUse NO_INSTANTIATE_ARRAY_SORT instead of INSTANTIATE_ARRAY_SORT\n\tfor octave_values.\n\n2009-02-11  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* gl-render.h: Use HAVE_FRAMEWORK_OPENGL.\n\t* gl-render.cc (opengl_tesselator, opengl_renderer::draw,\n\topengl_renderer::init_marker): Use HAVE_FRAMEWORK_OPENGL.\n\n2009-02-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::issorted, octave_value::sortrows_idx,\n\toctave_value::issorted_rows): New methods.\n\t* ov.cc (octave_base_value::issorted, octave_base_value::sortrows_idx,\n\toctave_base_value::issorted_rows): New methods.\n\t* ov.cc: Declare them.\n\n\t* ov-base-mat.h (octave_base_matrix::issorted, octave_base_matrix::sortrows_idx,\n\toctave_base_matrix::issorted_rows): New methods.\n\n\t* ov-base-diag.h (octave_base_diag::issorted, octave_base_diag::sortrows_idx,\n\toctave_base_diag::issorted_rows): New methods.\n\n\t* ov-perm.h (octave_perm_matrix::issorted, octave_perm_matrix::sortrows_idx,\n\toctave_perm_matrix::issorted_rows): New methods.\n\n\t* ov-range.h (octave_range::issorted, octave_range::sortrows_idx,\n\toctave_range::issorted_rows): New methods.\n\n\t* data.cc (F__sortrows_idx__, Fissorted): New defuns.\n\n2009-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (octave_config_info): Add octetcdir to the struct.\n\t* defaults.h.in (OCTAVE_OCTETCDIR): New macro.\n\n2009-02-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/__pchip_deriv__.cc (F__pchip_deriv__):\n\tAdd support for computing pchip derivatives along rows of matrix.\n\tEliminate redundant copying by using const args where appropriate.\n\n2009-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.52.\n\t(OCTAVE_RELEASE_DATE): Now 2009-02-09.\n\t(OCTAVE_COPYRIGHT): Update year.\n\n\t* load-path.cc (dir_info::update, dir_info::initialize):\n\tLikewise, to allow some functionality if getcwd fails.\n\n\t* toplev.cc (main_loop): Also catch octave_execution_exception.\n\n\t* DLD-FUNCTIONS/dispatch.cc: Comment out troublesome tests.\n\n\t* DLD-FUNCTIONS/eigs.cc: Increase tolerance to 1e-11 on all tests.\n\n\t* lex.l (lexical_feedback::looking_at_decl_list): New data member.\n\t* lex.l (lexical_feedback::init): Initialize it.\n\t(handle_identifier): Also force local variable if looking_at_decl_list.\n\t* parse.y (parsing_decl_list): New non-terminal.\n\t(declaration): Use it.  Set lexer_flags.looking_at_decl_list to\n\tfalse after parsing the declaration.\n\n2009-02-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* TEMPLATE-INST/Array-tc.cc: Reflect changes in octave_sort.\n\n2009-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (initialize_pathsearch): Delete.\n\t(octave_main): Don't call initialize_pathsearch.\n\n2009-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (eval_string): Use the one true evaluator.\n\n2009-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (INCLUDES): Include oct-hdf5.h in the list.\n\n\t* Makefile.in (oct-gperf.h): Don't use pipeline to process gperf\n\toutput.\n\n2009-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_table::fcn_info::cn_info_rep::xfind):\n\tNew function.\n\t(symbol_table::fcn_info::cn_info_rep::find):\n\tUse it to avoid recursive call.\n\n\t* graphics.cc (Fdrawnow): Return after errors.  Don't strip\n\ttrailing directory separator from name used in call to file_stat.\n\n\t* DLD-FUNCTIONS/eigs.cc (Feigs): Avoid warnings about ambiguous\n\telse.  Style fixes.  Return after errors.\n\n2009-02-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-map.cc (Octave_map::index): Optimize.\n\n2009-02-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-cm-cs.cc: Use scalar_value in scalar-to-matrix\n\tindexed assignments.\n\t* OPERATORS/op-fcm-fcs.cc: Ditto.\n\t* OPERATORS/op-fm-fs.cc: Ditto.\n\t* OPERATORS/op-m-s.cc: Ditto.\n\t* OPERATORS/op-int.h (OCTAVE_MS_INT_ASSIGN_OPS): Use homogeneous\n\tinteger scalar-to-matrix assignment.\n\t(OCTAVE_MM_INT_ASSIGN_OPS): Use homogeneous integer matrix-to-matrix\n\tassignment.\n\n\t* Cell.h (Cell::index): Remove direct idx_vector overloads.\n\t(Cell::assign): Remove direct idx_vector overloads.\n\t(Cell::delete_elements): Remove direct idx_vector overloads.\n\t* Cell.cc (Cell::index (const octave_value_list&)): Call\n\tArrayN<octave_value>::index.\n\n\t* oct-map.h (Octave_map::index): Remove direct idx_vector overloads.\n\t* oct-map.cc (Octave_map::index): Ditto.\n\t* ov-base-mat.cc (octave_base_mat::do_index_op): Optimize scalar\n\tindexing case.\n\t(octave_base_mat::assign (const octave_value_list&, const MT&)):\n\tSpecialize variable argument number.\n\t(octave_base_mat::assign (const octave_value_list&, const\n\ttypename MT::element_type&)):\n\tNew method overload with optimized scalar indexing case.\n\n\t* ov-cell.cc (octave_base_matrix<Cell>::do_index_op,\n\toctave_base_matrix<Cell>::assign,\n\toctave_base_matrix<Cell>::delete_elements): Specialize.\n\t(octave_cell::assign (const_octave_value_list, const octave_value&):\n\tDelete method.\n\t* ov-cell.h: Reflect change.\n\n\t* ov-cx-mat.cc (octave_complex_matrix::assign): Delete overloads.\n\t* ov-cx-mat.h: Reflect changes.\n\t* ov-flt-cx-mat.cc (octave_float_complex_matrix::assign): Delete overloads.\n\t* ov-flt-cx-mat.h: Reflect changes.\n\t* ov-list.cc (octave_list::do_index_op): Simplify.\n\t* ov-struct.cc (octave_struct::do_index_op): Simplify.\n\t* pt-eval.cc (tree_evaluator::visit_simple_for_command): Optimize\n\ttraversing a row vector.\n\n2009-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (Vignore_function_time_stamp):\n\tEliminate unused static variable.\n\n\t* debug.cc (get_file_line): Override default precedence in logical\n\texpression.\n\n\t* ov-null-mat.cc (default_null_str_numeric_conversion_function,\n\tdefault_null_sq_str_numeric_conversion_function,\n\tdefault_null_matrix_numeric_conversion_function):\n\tAvoid unused variable warning.\n\n\t* ov-flt-re-diag.cc (octave_float_diag_matrix::save_binary):\n\tAvoid unused parameter warning.\n\t* pt-eval.cc (tree_evaluator::visit_if_clause): Likewise.\n\t* ov-typeinfo.cc (octave_value_typeinfo::do_register_type): Likewise.\n\t* ov-base.cc (octave_base_value::subsref (const std::string&,\n\tconst std::list<octave_value_list>&, bool): Likewise.\n\t* ov-flt-cx-diag.cc (octave_float_complex_diag_matrix::save_binary):\n\tLikewise.\n\n\t* oct-hdf5.h: New file.\n\t* ls-hdf5.cc, ov-base.h, ov.h: Include oct-hdf5.h instead of hdf5.h.\n\t* ls-hdf5.h: Include oct-hdf5.h.\n\t* load-save.cc: Include ls-hdf5.h instead of hdf5.h.\n\t* ov-base-sparse.cc, load-save.cc:\n\tDon't protect #include \"ls-hdf5.h\" with #ifdef.\n\n2009-02-04  Kai Habel  <kai.habel@gmx.de>\n\n\t* gl-render.cc (opengl_renderer::draw (surface::properties)):\n\tNormalize surface normals. Correct calculation of diffuse lighting.\n\t* gl-render.cc (opengl_renderer::draw (patch::properties)):\n\tCorrect calculation of diffuse lighting.\n\n2009-02-04  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (do_which): If NAME is not in the symbol table, look for\n\ta function file in the load path.\n\t(raw_help_from_file): Unwind-protect and set reading_script_file.\n\n\t* pt-loop.h, pt-loop.cc (evaluating_looping_command):\n\tDelete global variable and all uses.\n\t* parse.y, parse.h (evaluating_function_body): Delete global\n\tvariable and all uses.\n\t(make_break_command, make_continue_command, make_return_command):\n\tUse tree_evaluator::in_fcn_or_script_body and\n\ttree_evaluator::in_loop_command instead of\n\tevaluating_function_body and evaluating_looping_command.\n\n\t* pt-eval.h (tree_evaluator::in_function_or_script_body):\n\tDelete \tmember variable and all uses.\n\t(tree_evaluator::reset): Delete function and all uses.\n\n\t* pt-eval.cc, pt-eval.h (tree_evaluator::in_fcn_or_script_body,\n\ttree_evaluator::in_loop_command): New static variables.\n\t(tree_evaluator::visit_simple_for_command,\n\ttree_evaluator::visit_complex_for_command,\n\ttree_evaluator::visit_while_command,\n\ttree_evaluator::visit_do_until_command): Unwind-protect and set\n\ttree_evaluator::in_loop_command instead of\n\tevaluating_looping_command.\n\t(tree_evaluator::visit_statement): Only call echo_code if\n\tevaluating function or script and (Vecho_executing_commands &\n\tECHO_FUNCTIONS).  Use tree_evaluator::in_fcn_or_script_body\n\tinstead of evaluating_function_body.\n\n\t* ov-usr-fcn.cc (octave_user_script::do_multi_index_op):\n\toctave_user_function::do_multi_index_op): Unwind-protect and set\n\ttree_evaluator::in_fcn_or_script_body.\n\n\t* pt-stmt.cc, pt-stmt.h (tree_statement::echo_code):\n\tRename from maybe_echo_code.  Simplify.\n\n2009-02-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-loop.h (tree_simple_for_command::do_for_loop_once,\n\ttree_complex_for_command::do_for_loop_once): Remove obsolete decls.\n\t* pt-loop.cc (quit_loop_now): Remove obsolete method.\n\t* pt-eval.cc (DO_ND_LOOP): Delete macro.\n\t(tree_evaluator::visit_simple_for_command): Use the generic\n\tdo_index_op for iterating matrices.\n\n2009-02-04  John W. Eaton  <jwe@octave.org>\n\n\tNew evaluator and debugger derived from tree-walker class.\n\n\t* pt-eval.h, pt-eval.cc: New files.  Parse tree evaluator code\n\tadapted from eval member functions in classes derived from\n\ttree_command.\n\t* Makefile.in (PT_INCLUDES, PT_SRC): Add them to the lists\n\n\t* pt-cmd.cc (tree_function_def::eval): Delete.\n\t* pt-cmd.h: Delete decl.\n\t(tree_command::eval): Delete pure virtual function.\n\t(tree_no_op_command::eval): Delete.\n\t(tree_function_def::function): Return octave_value, instead of\n\tpointer to octave_function.  Change all uses.\n\n\t* pt-except.cc (do_catch_code, tree_try_catch_command::eval,\n\tdo_unwind_protect_cleanup_code,\n\ttree_unwind_protect_command::eval): Delete.\n\t* pt-except.h: Delete decls.\n\n\t* pt-jump.cc (tree_break_command::eval, tree_return_command::eval,\n\ttree_continue_command::eval): Delete.\n\t* pt-jump.h: Delete decls.\n\n\t* pt-loop.cc (DO_ND_LOOP): Delete macro.\n\t(tree_while_command::eval, tree_do_until_command::eval,\n\ttree_simple_for_command::do_for_loop_once,\n\ttree_simple_for_command::eval,\n\ttree_complex_for_command::do_for_loop_once,\n\ttree_complex_for_command::eval):\n\t* pt-loop.h: Delete decls.\n\n\t* pt-select.cc (tree_if_clause::eval, tree_if_command_list::eval,\n\ttree_if_command::eval, tree_switch_case::eval,\n\ttree_switch_case_list::eval, tree_switch_command::eval): Delete.\n\t* pt-select.h: Delete decls.\n\t(class tree_if_clause, class tree_switch_case): Derive from tree.\n\tHandle line and column in constructors.\n\n\t* pt-stmt.cc (tree_statement::eval): Delete\n\t* pt-stmt.h: Delete decl.\n\n\t* pt-stmt.cc, pt-stmt.h (tree_statement::is_command,\n\ttree_statement::is_expression, tree_statement::line,\n\ttree_statement::column): Now const.\n\n\t* pt-stmt.cc (tree_statement::set_print_flag,\n\ttree_statement::is_end_of_fcn_or_script): New functions.\n\t* pt-stmt.h: Provide decl.\n\t(set_breakpoint, delete_breakpoint, is_breakpoint): New function.\n\t(bp): New member variable.\n\t(print_result): Delete member variable.\n\t(tree_statement_list::anon_function_body): New member variable.\n\t(tree_statement_list::mark_as_anon_function_body,\n\ttree_statement_list::is_anon_function_body,\n\ttree_statement_list::is_script_body): New functions.\n\n\t* pt-decl.cc (tree_decl_init_list::eval,\n\ttree_decl_command::accept, tree_global_command::do_init,\n\ttree_global_command::eval, tree_static_command::do_init,\n\ttree_static_command::eval): Delete.\n\t* pt-decl.h: Delete decls.\n\t(tree_decl_elt::eval_fcn): Delete typedef.\n\n\t* pt-decl.cc (tree_global_command::accept,\n\ttree_static_command::accept): New functions.\n\n\t* pt-stmt.cc (tree_statement::print_result): Move here from\n\tpt-stmt.h.  Return true if expr is printable.\n\n\t* ov-base.cc (Vsilent_functions): Delete.\n\t(octave_base_value::print_with_name): Don't check\n\tevaluating_function_body && Vsilent_functions here.\n\t* ov-class.cc (octave_class::print_with_name): Likewise.\n\t* ov-base.h (Vsilent_functions): Delete decl.\n\t* pt-eval.cc (Fsilent_functions): Move here from ov-base.cc.\n\t(Vsilent_functions): New static variable.\n\n\t* sighandlers.cc (user_abort): Set tree_evaluator::debug_mode here.\n\n\t* pt.h (tree::bp): Rename from tree::break_point.\n\t(tree::set_breakpoint, tree::delete_breakpoint, tree::is_breakpoint):\n\tNo longer virtual.\n\n\t* input.cc (get_debug_input): Use current_evaluator and\n\ttree-walker to evaluate command.\n\t* ov-usr-fcn.cc (octave_user_script::do_multi_index_op): Likewise.\n\t* toplev.cc (main_loop): Likewise.\n\t* parse.y (eval_string):\n\n\t* input.h, input.cc (Vdebugging_current_line): Delete.\n\t(get_debug_input): Use tree_evaluator::debug_line instead of\n\tVdebugging_current_line.\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tHandle inline functions and anonymous functions as single\n\texpressions.\n\t* parse.y (eval_string): Likewise.\n\n\t* parse.y (make_do_until_command): Rename first argument from\n\tdo_tok to until_tok.\n\t(loop_command): Pass UNTIL token instead of DO token to\n\tmake_do_until_command.\n\t(make_elseif_clause): New arg, elseif_tok.  Pass line and column\n\tinfo to tree_if_clause constructor.\n\t(elseif_clause): Pass ELSEIF token to make_elseif_clause.\n\t(make_switch_case): New arg, case_tok.  Pass line and column info\n\tto tree_switch_case constructor.\n\t(switch_case): Pass CASE token to make_switch_case.\n\t(make_script): New arg end_script.  Append it to cmds.\n\t(script): Create no-op command for end of script and pass it to\n\tmake_script.\n\t(start_function): New arg, end_function. Append it to body.\n\t(function2): Pass end_function to start_function.\n\t(make_end): New function.\n\t(function_end): Declare as tree_statement_type.\n\tCreate no-op command for end of script.\n\t(make_anon_fcn_handle): Mark body as anonymous function.\n\t(set_stmt_print_flag): Set print flag for all separator types\n\n\t* parse.y (fold (tree_binary_expression*),\n\tfold (tree_unary_expression *),\tfinish_colon_expression,\n\tfinish_matrix): Call rvalue1 instead of rvalue.\n\tStash line number in new tree_constant object.\n\n\t* debug.h (bp_table::have_breakpoints): New static function.\n\t(bp_table::do_have_breakpoints): New member function.\n\t* debug.cc (bp_table::do_add_breakpoint,\n\tbp_table::do_remove_breakpoint,\n\tbp_table::do_remove_all_breakpoints_in_file,\n\tbp_table::do_remove_all_breakpoints): Call\n\tbp_table::have_breakpoints to set tree_evaluator::debug_mode.\n\t(Fdbnext): Delete function.  Alias to dbstep.\n\t(Fdbquit, Fdbcont): Set tree_evaluator::dbstep_flag to zero.\n\t(Fdbstep): Rewrite to use tree_evaluator::dbstep_flag instead of\n\ttree::break_next, tree::last_line, tree::break_function, and\n\ttree::last_break_function.\n\t(Fdbwhere): Use tree_evaluator::debug_line and\n\ttree_evaluator::debug_column to get current line and column info.\n\tDon't print column if it is less than zero.\n\t* pt.cc, pt.h (tree::break_next, tree::last_line,\n\ttree::last_break_function, tree::break_function,\n\ttree::break_statement): Delete.\n\n\t* pt-bp.cc (tree_breakpoint::visit_global_command,\n\ttree_breakpoint::visit_static_command,\n\ttree_breakpoint::take_action (tree_statement&)): New functions.\n\t* pt-bp.h: Provide decls.\n\n\t* pt-bp.h (tree_walker::visit_global_command,\n\ttree_walker::visit_static_command): New pure virtual functions.\n\t(tree_walker::visit_decl_command): Delete.\n\n\t* pt-bp.cc (tree_breakpoint::visit_decl_command): Delete.\n\t* pt-bp.h: Delete decl.\n\t(MAYBE_DO_BREAKPOINT): Delete macro and all uses.\n\n\t* pt-bp.cc (tree_breakpoint::visit_no_op_command): Do nothing.\n\t(tree_breakpoint::visit_argument_list,\n\ttree_breakpoint::visit_binary_expression,\n\ttree_breakpoint::visit_colon_expression,\n\ttree_breakpoint::visit_decl_elt,\n\ttree_breakpoint::visit_decl_init_list,\n\ttree_breakpoint::visit_octave_user_script,\n\ttree_breakpoint::visit_octave_user_function,\n\ttree_breakpoint::visit_octave_user_function_header,\n\ttree_breakpoint::visit_octave_user_function_trailer,\n\ttree_breakpoint::visit_identifier,\n\ttree_breakpoint::visit_index_expression,\n\ttree_breakpoint::visit_matrix, tree_breakpoint::visit_cell,\n\ttree_breakpoint::visit_multi_assignment,\n\ttree_breakpoint::visit_anon_fcn_handle,\n\ttree_breakpoint::visit_constant,\n\ttree_breakpoint::visit_fcn_handle,\n\ttree_breakpoint::visit_parameter_list,\n\ttree_breakpoint::visit_postfix_expression,\n\ttree_breakpoint::visit_prefix_expression,\n\ttree_breakpoint::visit_return_list,\n\ttree_breakpoint::visit_simple_assignment): Call panic_impossible\n\tsince breakpoints aren't set on expressions.\n\t(tree_breakpoint::visit_if_clause): Fold into visit_if_command_list.\n\t(tree_breakpoint::visit_switch_case): Fold into visit_switch_case_list.\n\t(tree_breakpoint::visit_try_catch_command,\n\ttree_breakpoint::visit_unwind_protect_command):\n\tDon't set breakpoint on command itself, the the statements it\n\tcontains.\n\t(tree_breakpoint::visit_global_command,\n\ttree_breakpoint::visit_static_command): Call do_decl_command to do\n\tactual work.\n\t(tree_breakpoint::visit_while_command,\n\ttree_breakpoint::visit_do_until_command,\n\ttree_breakpoint::visit_simple_for_command,\n\ttree_breakpoint::visit_complex_for_command,\n\ttree_breakpoint::visit_statement,\n\ttree_breakpoint::visit_statement_list,\n\ttree_breakpoint::visit_switch_case_list): Set breakpoints at\n\tappropriate places.\n\n\t* pt-pr-code.h, pt-pr-code.cc (tree_print_code::visit_global_command,\n\ttree_print_code::visit_static_command,\n\ttree_print_code::do_decl_command): New functions.\n\t(tree_print_code::visit_decl_command): Delete.\n\n\t* pt-check.h, pt-check.cc (tree_checker::visit_global_command,\n\ttree_checker::visit_static_command, tree_checker::do_decl_command):\n\tNew functions.\n\t(tree_checker::visit_decl_command): Delete.\n\n\t* pt-select.cc (tree_switch_case::label_matches): Call rvalue1\n\tinstead of rvalue.\n\n\t* pt-exp.h, pt-exp.cc (tree_expression::rvalue1): New function.\n\t(tree_expression::rvalue (void)): Delete.\n\t(tree_expression::is_logically_true): Call rvalue1 instead of rvalue.\n\n\t* pt-fcn-handle.h, pt-fcn-handle.cc (tree_fcn_handle::rvalue1,\n\ttree_anon_fcn_handle::rvalue1): New functions.\n\t(tree_fcn_handle:rvalue (void),\n\ttree_anon_fcn_handle::rvalue1 (void)): Delete.\n\t(tree_fcn_handle::rvalue (int), tree_anon_fcn_handle_rvalue (int)):\n\tCall rvalue1 instead of rvalue.\n\n\t* pt-idx.h, pt-idx.cc (tree_index_expression::rvalue1): New function.\n\t(tree_index_expression::rvalue (void)): Delete.\n\t(tree_index_expression::get_struct_index,\n\ttree_index_expression::rvalue (int)): Call rvalue1 instead of rvalue.\n\n\t* pt-mat.h, pt-mat.cc (tree_matrix::rvalue1): New function.\n\t(tree_matrix::rvalue (void)): Delete.\n\t(tm_row_const::tm_row_const_rep::init,\n\ttree_matrix::rvalue (int)): Call rvalue1 instead of rvalue.\n\n\t* pt-misc.cc (tree_parameter_list::convert_to_const_vector):\n\tCall rvalue1 instead of rvalue.\n\t* pt-arg-list.cc (tree_argument_list::convert_to_const_vector):\n\tLikewise.\n\n\t* pt-unop.h, pt-unop.cc (tree_prefix_expression::rvalue1,\n\ttree_postfix_expression::rvalue1): New functions.\n\t(tree_prefix_expression::rvalue (void),\n\ttree_postfix_expression::rvalue (void)): Delete.\n\t(tree_prefix_expression::rvalue (int),\n\ttree_postfix_expression::rvalue (int)):\n\tCall rvalue1 instead of rvalue.\n\n\t* pt-id.h, pt-id.cc (tree_identifier::rvalue1): New function.\n\t(tree_identifier::rvalue (void)): Delete.\n\n\t* pt-assign.h, pt-assign.cc (tree_simple_assignment::rvalue1,\n\ttree_multi_assignment::rvalue1): New functions.\n\t(tree_simple_assignment::rvalue (void),\n\ttree_multi_assignment::rvalue (void): Delete.\n\t(tree_simple_assignment::rvalue (int)):\n\tCall rvalue1 instead of rvalue.\n\n\t* pt-binop.h, pt-binop.cc (tree_binary_expression::rvalue1,\n\ttree_boolean_expression::rvalue1): New functions.\n\t(tree_binary_expression::rvalue (void),\n\ttree_boolean_expression::rvalue (void)): Delete.\n\t(tree_binary_expression::rvalue (int),\n\ttree_boolean_expression::rvalue (int)):\n\tCall rvalue1 instead of rvalue.\n\n\t* pt-cbinop.h, pt-cbinop.cc\n\t(tree_compound_binary_expression::rvalue1): New function.\n\t(tree_compound_binary_expression::rvalue (void)): Delete.\n\n\t* pt-cell.h, pt-cell.cc (tree_cell::rvalue1): New function.\n\t(tree_cell::rvalue (void)): Delete.\n\t(tree_cell::rvalue (int)): Call rvalue1 instead of rvalue.\n\n\t* pt-colon.h, pt-colon.cc (tree_colon_expression::rvalue1):\n\tNew function.\n\t(tree_colon_expression::rvalue (void)): Delete.\n\t(tree_colon_expression::rvalue (int)):\n\tCall rvalue1 instead of rvalue.\n\n\t* pt-const.h, pt-const.cc (tree_constant::rvalue1): New function.\n\t(tree_constant::rvalue (void)): Delete.\n\t(tree_constant::rvalue (int)): Call rvalue1 instead of rvalue.\n\n\t* pt-decl.h, pt-decl.cc (tree_decl_elt::ravlue1): New function.\n\t(tree_decl_elt::ravlue (void)): Delete.\n\t(tree_decl_elt::eval): Call rvalue1 instead of rvalue.\n\n2009-02-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* TEMPLATE-INST/Array-tc.cc: Replace vec_index by pointers.\n\n2009-02-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-mat.cc (octave_matrix::abs, octave_matrix::real,\n\toctave_matrix::imag, octave_matrix::conj): Use special code.\n\t* ov-flt-re-mat.cc (octave_float_matrix::abs, octave_float_matrix::real,\n\toctave_float_matrix::imag, octave_float_matrix::conj): Use special code.\n\t* ov-cx-mat.cc (octave_complex_matrix::abs, octave_complex_matrix::real,\n\toctave_complex_matrix::imag, octave_complex_matrix::conj): Use special code.\n\t* ov-flt-cx-mat.cc (octave_float_complex_matrix::abs, octave_float_complex_matrix::real,\n\toctave_float_complex_matrix::imag, octave_float_complex_matrix::conj): Use special code.\n\n2009-01-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Add missing check.\n\n2009-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* pt-stmt.cc (tree_statement::eval): Check\n\tin_function_or_script_body instead of symbol_table::at_top_level ()\n\tto decide whether to call octave_call_stack::set_statement.\n\n\t* graphics.cc (properties::set_defaults): Also set\n\thorizontalalignment, verticalalignmnt, and rotation properties for\n\tnew label objects here.\n\n\t* ov-base-scalar.cc (octave_base_scalar<ST>::is_true (void) const):\n\tError if scalar is NaN.\n\t* ov-base-mat.cc (octave_base_matrix<MT>::is_true (void) const):\n\tLikewise, if any element of matrix is NaN.\n\t* ov-cell.cc (octave_cell::is_true): New function.\n\t* Cell.h (Cell::any_element_is_nan): New function.\n\n2009-01-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pr-output.cc:\n\t(void octave_print_internal (..., const DiagMatrix& m,...),\n\t(void octave_print_internal (..., const ComplexDiagMatrix& m,...),\n\t(void octave_print_internal (..., const FloatDiagMatrix& m,...),\n\t(void octave_print_internal (..., const FloatComplexDiagMatrix& m,...)):\n\tNew functions.\n\t* pr-output.h: Declare them.\n\t* ov-base-diag.cc (octave_base_diag::print_raw): Call\n\toctave_print_internal.\n\n2009-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (install, uninstall): Handle SHLLIBPRE and SHLBINPRE\n\tlibrary prefixes.  From Marco Atzeri <marco_atzeri@yahoo.it>.\n\n2008-01-28  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp_list): Don't break for zero\n\tlength match, but rather advance the index by one character and\n\ttry again.\n\n2009-01-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Fix doc string.\n\n2009-01-27  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (Fcommand_line_path): Rename from Fcommandlinepath.\n\n2009-01-27 Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.cc (convert_position): Handle character units.\n\t(default_axes_tick, default_figure_papersize,\n\tdefault_figure_paperposition): New functions.\n\t* graphics.h.in (class figure::properties): Use them to\n\tinitialize papersize, paperposition, xtick, ytick, and ztick\n\tproperties.\n\n2009-01-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/qr.cc (Fqr): Treat empty matrices correctly.\n\n2009-01-26  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* display.cc (display_info::init): Use double instead of CGFloat.\n\tUse HAVE_FRAMEWORK_CARBON instead of OCTAVE_USE_OS_X_API.\n\n2009-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::do_find_fcn): Handle @foo/bar.\n\n2009-01-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-cell.cc (tree_cell::rvalue): Optimize the single row case.\n\n2009-01-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-struct.cc (octave_struct::subsasgn): Reshape cs-list on rhs\n\taccording to the index expression.\n\t* ov-cell.cc (octave_cell::subsasgn): Ditto.\n\n2008-12-25 Ben Abbott  <bpabbott@mac.com>\n\n\t* load-path.cc (Fcommandlinepath): New function.\n\t* load-path.h (load_path::get_command_line_path,\n\tload_path::do_get_command_line_path): New functions.\n\n2009-01-24 Ben Abbott  <bpabbott@mac.com>\n\n\t* DLD-FUNCTIONS/eigs.cc: eigs.cc: skip tests if ARPACK is missing.\n\n2009-01-25  Søren Hauberg  <hauberg@gmail.com>\n\n\t* help.cc (do_get_help_text, raw_help_from_symbol_table): new output to\n\tflag the a function is found but not documented.\n\n2009-01-25  Søren Hauberg  <hauberg@gmail.com>\n\n\t* help.cc (raw_help_from_file): No longer search for files called\n\t'Contents.m', as this is moved to 'script/help.m'.\n\n\n2009-01-23  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (octave_call_stack::do_goto_caller_frame):\n\tAlso allow caller frame to be base frame, not just user code.\n\n2009-01-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* gripes.cc (gripe_indexed_cs_list, gripe_invalid_inquiry_subscript):\n\tNew functions.\n\t* gripes.h: Declare them.\n\t* pt-idx.cc: Remove definitions of the above funcs.\n\t* ov-cell.cc (octave_cell::subsref): Declare constants as const.\n\t(octave_cell::subsasgn): Remove dead branch, declare constants as const.\n\t(octave_cell::list_value): Optimize.\n\t* ov-struct.cc\n\t(octave_struct::subsref): Declare constants as const.\n\t(octave_struct::subsasgn): Remove dead branch, declare constants as const.\n\t* ov-cs-list.cc (octave_cs_list::octave_cs_list (const Cell&)):\n\tOptimize.\n\t* oct-obj.cc (octave_value_list::octave_value_list (const\n\tstd::list<octave_value_list>&)): New constructor.\n\t* oct-obj.h: Declare it.\n\t* pt-arg-list.cc (convert_to_const_vector): Optimize.\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::find): Use const\n\treference to avoid redundant copy.\n\t* ov-usr-fcn.cc (octave_user_function::bind_automatic_vars): Optimize.\n\t(octave_user_function::octave_all_va_args): Optimize.\n\n2009-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Cell.h (Cell::Cell (octave_value_list)): Only declare.\n\t(Cell::index (*)): Change resize_ok type to bool.\n\t* Cell.cc (Cell::Cell (octave_value_list)): Redefine.\n\t* oct-obj.h, oct-obj.cc: Change octave_value_list::data to\n\tCell variable, reflect changes.\n\n2009-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (do_which (std::ostream&, const std::string&), Fwhich):\n\tDelete.\n\t(do_which (const std::string&, std::string&), F__which__):\n\tNew functions.\n\t* do_which (const std::string&):\n\tCall do_which (const std::string&, std::string&) to do the work.\n\n2009-01-22  Søren Hauberg  <hauberg@gmail.com>\n\n\t* defun-int.h (print_usage): No longer mark as deprecated.\n\t* defun.cc (print_usage): Simply call feval to execute print_usage.m.\n\t* help.cc (additional_help_message, display_names_from_help_list,\n\tdisplay_symtab_names, simple_help, try_info, help_from_info,\n\tdisplay_help_text, display_usage_text, raw_help_from_list,\n\thelp_from_list, help_from_symbol_table, help_from_file,\n\tbuiltin_help, Fhelp, display_file, do_type, Ftype,\n\tfirst_help_sentence, print_lookfor, Flookfor): Delete.\n\t(looks_like_html, raw_help_from_map, raw_help, do_get_help_text,\n\tF__operators__, F__keywords__, F__builtins__,\n\tfile_is_in_dir, F__list_functions__): New functions.\n\t(pair_type, map_iter): New typedefs.\n\t(operators, keywords): Use pair_type for elements of list.\n\t(names): Use map for (keyword, doc) lists.\n\t(make_name_list): Sprinkle with const.\n\t* help.h (display_help_text, display_usage_text,\n\tadditional_help_message): Delete decls.\n\n2009-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (octave_config_info): Check OCTAVEUSE_OS_X_API instead\n\tof __APPLE__ && __MACH__.\n\n\t* display.cc (display_info::init): Get info for Windows and OS X\n\tsystems.\n\n2009-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-idx.cc (tree_index_expression::lvalue): Correct tmpi when seeing\n\ta plain struct component.\n\t* ov-struct.cc (octave_struct::subsasgn): Use proper type substr in\n\tempty_conv.\n\n2009-01-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/qr.cc: Remove HAVE_QRUPDATE check.\n\t* DLD-FUNCTIONS/chol.cc: Ditto.\n\n2009-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (display.o): Add X11_INCFLAGS to CPPFLAGS.\n\t(octave$(EXEEXT)): Link with X11_LIBS.\n\n\t* display.h, display.cc: New files.\n\t* graphics.cc (default_screendepth, default_screensize,\n\tdefault_screenpixelsperinch): New functions.\n\t* graphics.h.in (class root_figure::properties): New property,\n\tscreendepth.  Use default_screensize to initialize screensize\n\tproperty.  Use default_screenpixelsperinch to initialize\n\tscreenpixelsperinch property.\n\n\t* graphics.cc (properties::init): Set default xlabel, ylabel,\n\tzlabel, and title properties that differ from default text\n\tproperties.\n\n2009-01-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-range.cc: Define & register range-scalar ops.\n\n2009-01-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::subsref (..., bool auto_add)): New method.\n\t(octave_value::next_subsref (bool auto_add, ...)): New method.\n\t* ov.cc (octave_value::next_subsref (bool auto_add, ...)): New method.\n\t* ov-base.h (octave_base_value::subsref (..., bool auto_add)): New\n\tvirtual method.\n\t* ov-base.cc (octave_base_value::subsref (..., bool auto_add)): New\n\tvirtual method.\n\t* ov-cell.cc (octave_cell::subsref (..., bool auto_add)): New virtual\n\tmethod.\n\t* ov-cell.h (octave_cell::subsref (..., bool auto_add)): Declare it.\n\t* ov-struct.cc (octave_struct::subsref (..., bool auto_add)): New\n\tvirtual method.\n\t(octave_struct::subsref (const std::string& type, const\n\tstd::list<octave_value_list>& idx)): Do not allow resizing.\n\t* ov-struct.h (octave_struct::subsref (..., bool auto_add)): Declare\n\tit.\n\t* ov-struct.cc (octave_struct::dotref (..., bool auto_add)): New\n\tvirtual method.\n\t* ov-struct.h (octave_struct::dotref (..., bool auto_add)): Declare it.\n\t* pt-idx.cc (tree_index_expression::rvalue): Do not reevaluate already\n\tevaluated part of the index chain.\n\t(tree_index_expression::rvalue): Do not reevaluate already evaluated\n\tpart of the index chain. Do not actually perform trailing indexing.\n\tDo not allow indexing cs-lists.\n\n2009-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (Ffstat): New function.\n\n2009-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/qr.cc (Fqrupdate, Fqrinsert, Fqrdelete, Fqrshift):\n\tReflect changes in liboctave.\n\t* DLD-FUNCTIONS/chol.cc (Fcholupdate, Fcholinsert):\n\tReflect changes in liboctave.\n\n2009-01-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::make_unique (int)): New method.\n\t* oct-obj.h (octave_value_list::octave_value_list (const Cell&)): New\n\tconstructor.\n\t* ov-cell.cc (octave_cell::subsasgn): Allow composed {} indexing\n\tin multi-assignments. Optimize.\n\t* ov-struct.cc (octave_struct::subsasgn): Correct composed {} indexing\n\tin multi-assignments. Optimize & fix bugs.\n\t* pt-idx.cc (tree_index_expression::lvalue): Rewrite to allow\n\tspecifying cs-list anywhere in index chain, be more robust.\n\n2009-01-19  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (grab_comment_block): If not reading input from a file,\n\tbail out at first newline inside a comment.\n\n\t* lex.l (lexer_debug_flag): New static variable.\n\t(F__lexer_debug_flag__): New function.\n\t(LEXER_DEBUG): New macro.  Use it in all patterns.\n\t(DISPLAY_TOK_AND_RETURN): Also display token if lexer_debug_flag\n\tis set.\n\t(process_comment): Display comment if lexer_debug_flag is set.\n\t(display_character, display_state, lexer_debug): New static functions.\n\t(xunput): Display character if lexer_debug_flag is set.\n\n2009-01-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h: Describe usage of storable_value and make_storable_value.\n\t* ov.cc: Remove FIXME comment.\n\n2009-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (Freshape): Include mismatched dimensions in error message.\n\tFrom Robert Millan <rmh@aybabtu.com>.\n\n2009-01-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.cc (octave_value::maybe_economize): New method.\n\t(octave_value::non_null_value): rename to storable_value.\n\t(octave_value::make_non_null_value): rename to make_storable_value.\n\t* ov-base.h (octave_base_value::maybe_economize): New method.\n\t* ov-base-mat.h (octave_base_mat::maybe_economize): New override.\n\t* oct-obj.cc (octave_value_list::normalize_null_values):\n\tRename to make_storable_values, use make_storable_value.\n\t* oct-obj.h: Ditto.\n\t* ov-builtin.cc: non_null_value -> storable_value.\n\t* ov-cell.cc: Ditto.\n\t* ov-struct.cc: Ditto.\n\t* pt-decl.h: Ditto.\n\n2009-01-15  Søren Hauberg  <hauberg@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (encode_uint_image):\n\tInitialize bitdepth.\n\n2009-01-14  Søren Hauberg  <hauberg@gmail.com>\n\n\t* DLD-FUNCTIONS/betainc.cc, DLD-FUNCTIONS/chol.cc,\n\tDLD-FUNCTIONS/daspk.cc, DLD-FUNCTIONS/dasrt.cc,\n\tDLD-FUNCTIONS/dassl.cc, DLD-FUNCTIONS/filter.cc,\n\tDLD-FUNCTIONS/gammainc.cc, DLD-FUNCTIONS/gcd.cc,\n\tDLD-FUNCTIONS/givens.cc, DLD-FUNCTIONS/hess.cc,\n\tDLD-FUNCTIONS/lsode.cc, DLD-FUNCTIONS/qr.cc, DLD-FUNCTIONS/qz.cc,\n\tDLD-FUNCTIONS/schur.cc, DLD-FUNCTIONS/svd.cc,\n\tDLD-FUNCTIONS/syl.cc, data.cc, mappers.cc:\n\tUse ifnottex instead of ifinfo.\n\n2009-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::do_set): Call do_clear after disabling\n\tadd_hook.\n\n2009-01-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* dirfns.cc (Freadddir): qsort -> sort.\n\t* graphics.cc (maybe_set_children): Ditto.\n\t* help.cc (simple_help): Ditto.\n\t* input.cc (generate_possible_completions): Ditto.\n\t* oct_map.cc (keys_ok): Ditto.\n\t* ov-fcn-inline.cc (Finline): Ditto.\n\t* variables.cc (Fisrawcommand): Ditto.\n\n2009-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (maximum_braindamage): Set confirm_recursive_rmdir to\n\tfalse.\n\n\t* strfns.cc (Fstrcmp, Fstrncmp): Simplify by initializing all\n\telements of output to false with constructor argument.\n\n2009-01-12  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* strfns.cc (Fstrncmp): New test.\n\n2009-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* pt-stmt.h (tree_statement::is_null_statement): New function.\n\t* parse.y (set_stmt_print_flag): Return list.  Remove trailing\n\tnull statements from list.\n\t(list, simple_list): Simplify action.\n\t(make_statement, make_statement_list, append_statement_list):\n\tAlways create statements and them to the list.\n\n\t* base-list.h (octave_base_list::push_front,\n\toctave_base_list::push_back, octave_base_list::pop_front,\n\toctave_base_list::pop_back): New functions.\n\n\t* DLD-FUNCTIONS/qr.cc (Fqrupdate, Fqrinsert, Fqrdelete, Fqrshift):\n\tRequire args to be numeric, not necessarily matrix objects.\n\n2009-01-12  Ben Abbott  <bpabbott@mac.com>\n\n\t* graphics.h.in (text::properties::fontunits): Fix typo in list of\n\tpossible values.\n\n2009-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* strfns.cc (Fstrvcat, Fchar): Use queue to avoid duplicate calls\n\tto all_strings.\n\n2009-01-12  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* strfns.cc (Fstrvcap): New function.\n\n2008-11-29  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* strfns.cc (Fchar, Fischar, Fstrncmp, Flist_in_columns):\n\tImprove documentation strings.  Add examples and tests.\n\n2009-01-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-perm.cc (octave_perm_matrix::do_index_op): Return shallow copy\n\twhen indexed by (:,:).\n\t* ov-base-mat.cc (octave_base_diag::do_index_op): Return shallow copy\n\twhen indexed by (:,:). Optimize indexing equivalent to resizing.\n\t* data.cc: Fix tests.\n\t* mappers.cc: Fix tests.\n\n2009-01-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-diag.h, ov-base-mat.h, ov-base-scalar.h, ov-base-sparse.h,\n\tov-base.cc, ov-base.h, ov-perm.h, ov-range.h, ov.h: Add full_value\n\tmethods to octave_value, octave_base_value and its relevant\n\tsubclasses.\n\t* data.cc (Ffull): New DEFUN.\n\t* DLD-FUNCTIONS/sparse.cc (Ffull): move to data.cc.\n2009-01-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::is_copy_of): New method.\n\t* ov-struct.cc (numeric_conv): Add output parameter orig.\n\t(octave_struct::subsasgn): Temporarily erase duplicate lhs value prior\n\tto assignment.\n\n2009-01-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-obj.cc (octave_value_list::all_scalars): New method.\n\t* oct-obj.h: Declare it.\n\t* ov-cell.cc (octave_cell::subsasgn): Disable assigning\n\tto non-scalar {}-indexed cell, unless in a multi-assignment.\n\n2009-01-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/sparse.cc (Ffull): Convert diagonal & permutation\n\tmatrices, leave other classes untouched.\n\n2009-01-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-cdm-cdm.cc: Install missing widening op.\n\t* OPERATORS/op-dm-dm.cc: Ditto.\n\t* OPERATORS/op-fcdm-fcdm.cc: Ditto.\n\t* OPERATORS/op-fdm-fdm.cc: Ditto.\n\t* OPERATORS/op-pm-pm.cc: Ditto.\n\t* OPERATORS/op-fpm-fpm.cc: Ditto.\n\n2009-01-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cell.cc (octave_cell::subsasgn): Put erased copy back after\n\tmake_unique has been called.\n\n2009-01-09  Kai Habel  <kai.habel@gmx.de>\n\n\t* graphics.cc: Calculate normals for surface boundaries, use\n\tmore neighboring points to calculate interior normals\n\n2009-01-09  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (get_user_input (void)): Don't increment input_line_number.\n\t* lex.l (xunput): New function.  Use it in place of yyunput\n\tanywhere a newline character may be put back on the input stream.\n\tIncrement input_line_number in all rules that consume newlines\n\tcharacters.\n\t(text_yyinput): Increment input_line_number\n\t(fixup_column_count): Increment input_line_number.\n\t(prep_for_function): Set input_line_number to 1, not 0.\n\t(reset_parser): Set input_line_number to current_command_number,\n\tnot current_command_number-1.\n\t(flex_stream_reader::ungetc): Call xunput, not yyunput.\n\t* parse.y (input_line_number): Initialize to 1, not 0.\n\t(text_getc): Increment input_line_number correctly.\n\t(stdio_stream_reader::ungetc): Decrement input_line_number if\n\tputting back a newline character.\n\t(parse_fcn_file): Set input_line_number to 1, not 0.\n\t(eval_string): Unwind-protect input_line_number and\n\tcurrent_input_column.\n\n\t* parse.y (make_statement): New function.\n\t(statement): Use it.\n\t(make_statement_list, append_statement_list): New functions.\n\t(simple_list1, list1): Use them.\n\n2009-01-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cell.cc (octave_cell::subsasgn): Erase duplicate lhs value\n\tprior to assignment to avoid a redundant copy.\n\n2008-12-26  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* mappers.cc (Ftoascii), mappers.cc (Ftolower), mappers.cc\n\t(Ftoupper), DLD-FUNCTIONS/regexp.cc (Fregexp),\n\tDLD-FUNCTIONS/regexp.cc\t(Fregexpi), DLD-FUNCTIONS/regexp.cc\n\t(Fregexprep): Add references.\n\n2008-12-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-obj.h, oct-obj.cc (octave_value_list::valid_scalar_indices): Remove.\n\t* ov-base-diag.cc, ov-base-diag.h, ov-base-scalar.cc, ov-base.h,\n\tov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc, ov-bool-sparse.h,\n\tov-bool.cc, ov-bool.h, ov-ch-mat.cc, ov-ch-mat.h, ov-colon.h,\n\tov-complex.cc, ov-complex.h, ov-cx-mat.cc, ov-cx-mat.h,\n\tov-cx-sparse.cc, ov-cx-sparse.h, ov-float.cc, ov-float.h,\n\tov-flt-complex.cc, ov-flt-complex.h, ov-flt-cx-mat.cc,\n\tov-flt-cx-mat.h, ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h,\n\tov-perm.cc, ov-perm.h, ov-range.h, ov-re-mat.cc, ov-re-mat.h,\n\tov-re-sparse.cc, ov-re-sparse.h, ov-scalar.cc, ov-scalar.h,\n\tov-str-mat.cc, ov-str-mat.h, ov.h:\n\tRemove valid_as_scalar_index and valid_as_zero_index methods\n\tfrom octave_value, octave_base_value and all of its subclasses.\n\n2008-12-26  Francesco Potortì  <pot@gnu.org>\n\n\t* data.cc (resize): Add cross reference to postpad.\n\n2008-12-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* load-save.h (load_save_format_type, load_save_format_options): New\n\tenums.\n\t(load_save_format): Convert to a class.\n\t* load-save.cc (do_save(..., const octave_value&,...)): Use fmt.type\n\tin switch. Use options of LS_MAT_ASCII.\n\t(do_load, write_header): Use format.type in switch.\n\t* ls-mat-ascii.h (save_mat_ascii_data): Add tabs option.\n\t* ls-mat-ascii.cc (save_mat_ascii_data): Implement it.\n\n2008-12-24  Ben Abbott  <bpabbott@mac.com>\n\n\t* DLD-FUNCTIONS/chol.cc: Compare results to 0 in tests.\n\tDelete spurious function calls in test block.\n\n2008-12-24  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/eigs.cc: Use \"testif HAVE_ARPACK\" to skip tests if\n\tARPACK is not available.\n\n\t* Makefile.in (DLD_XSRC): Add eigs.cc to the list.\n\n\t* load-save.cc (parse_save_options): Handle -double.\n\n2008-12-23  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/eigs.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add it here.\n\n2008-12-22  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/__voronoi__.cc (F__voronoi__): Resize AtInf array\n\tbefore returning it.\n\n2008-12-12  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/chol.cc (Fcholinv): Add test.\n\n2008-12-12  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ls-hdf5.cc (add_hdf5_data): Check for diagonal & permutation\n\tmatrices and convert them to full prior to saving.\n\n2008-12-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-mat.cc (Fdouble): Handle diagonal & perm matrices.\n\t* ov-flt-re-mat.cc (Fsingle): Handle diagonal & perm matrices.\n\n2008-12-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-diag.cc (octave_base_diag<DMT,MT>::subsasgn): New method.\n\t* ov-base-diag.h (octave_base_diag<DMT,MT>::subsasgn): Declare it.\n\t(octave_base_diag<DMT,MT>::chk_valid_scalar): New method decl.\n\n\t* ov-re-diag.cc (octave_diag_matrix::chk_valid_scalar): New method\n\toverride.\n\t* ov-re-diag.h: Declare it.\n\t* ov-flt-re-diag.cc (octave_float_diag_matrix::chk_valid_scalar): New\n\tmethod override.\n\t* ov-flt-re-diag.h: Declare it.\n\t* ov-cx-diag.cc (octave_complex_diag_matrix::chk_valid_scalar): New\n\tmethod override.\n\t* ov-cx-diag.h: Declare it.\n\t* ov-flt-cx-diag.cc (octave_float_complex_diag_matrix::chk_valid_scalar):\n\tNew method override.\n\t* ov-flt-cx-diag.h: Declare it.\n\n2008-12-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/expm.cc: Remove.\n\t* Makefile.in: Update.\n\n2008-12-10  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_SCALAR_T::empty_clone): Construct an\n\tempty matrix instead of zero.\n\n2008-12-07  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* mappers.cc (Ftolower): Make lower alias of tolower, add tests\n\t* mappers.cc (Ftoupper): Make upper alias of toupper, add tests\n\n2008-12-09  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/balance.cc (Fbalance): Exploit the new AEPBAL functionality.\n\n2008-12-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xpow.cc ( xpow (const DiagMatrix& a, double b),\n\txpow (const DiagMatrix& a, const Complex& b),\n\txpow (const ComplexDiagMatrix& a, double b),\n\txpow (const ComplexDiagMatrix& a, const Complex& b),\n\txpow (const FloatDiagMatrix& a, float b),\n\txpow (const FloatDiagMatrix& a, const FloatComplex& b),\n\txpow (const FloatComplexDiagMatrix& a, float b),\n\txpow (const FloatComplexDiagMatrix& a, const FloatComplex& b)):\n\tNew methods.\n\t* xpow.h: Declare them.\n\t* OPERATORS/op-dms-template.cc: Support diagonal matrix ^ scalar.\n\n2008-12-08  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-re-diag.cc (octave_diag_matrix::save_binary,\n\toctave_diag_matrix::load_binary): New methods.\n\t* ov-re-diag.h: Declare them.\n\t* ov-flt-re-diag.cc (octave_float_diag_matrix::save_binary,\n\toctave_float_diag_matrix::load_binary): New methods.\n\t* ov-flt-re-diag.h: Declare them.\n\t* ov-cx-diag.cc (octave_complex_diag_matrix::save_binary,\n\toctave_complex_diag_matrix::load_binary): New methods.\n\t* ov-cx-diag.h: Declare them.\n\t* ov-flt-cx-diag.cc (octave_float_complex_diag_matrix::save_binary,\n\toctave_float_complex_diag_matrix::load_binary): New methods.\n\t* ov-flt-cx-diag.h: Declare them.\n\t* ov-perm.cc (octave_perm_matrix::save_binary,\n\toctave_perm_matrix::load_binary): New methods.\n\t* ov-perm.h: Declare them.\n\n2008-12-06  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::load_binary): Call istream::get\n\trather than istream::read to supply null terminating character.\n\n2008-10-29  Jaroslav Hajek  <highegg@gmail.com>\n\t* file-io.cc, gl-render.cc, load-save.cc, ls-hdf5.cc, ls-mat4.cc,\n\tls-mat5.cc, ls-oct-binary.cc, mex.cc, oct.h, ov-base-int.cc,\n\tov-bool-mat.cc, ov-bool-sparse.cc, ov-cell.cc, ov-class.cc,\n\tov-cx-mat.cc, ov-cx-sparse.cc, ov-fcn-handle.cc, ov-fcn-inline.cc,\n\tov-flt-cx-mat.cc, ov-flt-re-mat.cc, ov-re-mat.cc, ov-re-sparse.cc,\n\tov-str-mat.cc, ov-struct.cc, toplev.cc,\n\tDLD-FUNCTIONS/__lin_interpn__.cc, DLD-FUNCTIONS/amd.cc,\n\tDLD-FUNCTIONS/ccolamd.cc, DLD-FUNCTIONS/cellfun.cc,\n\tDLD-FUNCTIONS/colamd.cc, DLD-FUNCTIONS/gcd.cc,\n\tDLD-FUNCTIONS/matrix_type.cc, DLD-FUNCTIONS/regexp.cc,\n\tDLD-FUNCTIONS/symbfact.cc, DLD-FUNCTIONS/symrcm.cc:\n\tInclude oct-locbuf.h.\n\n2008-12-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base-diag.cc (save_ascii, load_ascii): Save natively.\n\t* ov-base-diag.h (load_ascii): Declare.\n\t* ov-perm.cc (save_ascii, load_ascii): Save natively.\n\t* ov-perm.h (load_ascii): Declare.\n\n2008-12-04  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* strfns.cc (Fchar): Add test from str2mat.m\n\n2008-12-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov.h (octave_value::is_perm_matrix): New method.\n\t* ov-base.h (octave_base_value::is_perm_matrix): New method.\n\t* ov-perm.h (octave_perm_matrix::is_perm_matrix): New method.\n\t* DLD-FUNCTIONS/inv.cc (Finv): Handle permutation matrices specially,\n\tcompute rcond for diagonal matrices.\n\t* DLD-FUNCTIONS/det.cc (Fdet): Handle permutation & diagonal matrices\n\tspecially.\n\n2008-12-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-perm.h: New source.\n\t* ov-perm.cc: New source.\n\t* ov-flt-perm.h: New source.\n\t* ov-flt-perm.cc: New source.\n\t* ov-base-diag.cc (octave_base_diag<DMT, MT>::do_index_op):\n\tIf subscripting an identity matrix by permutation(s), return a\n\tpermutation matrix object.\n\t* ov.cc (octave_value::octave_value (const PermMatrix&)): New\n\tconstructor.\n\t* ov.cc (octave_value::octave_value (const PermMatrix&)): Declare it.\n\t* op-cm-pm.cc: New source.\n\t* op-fcm-fpm.cc: New source.\n\t* op-fm-fpm.cc: New source.\n\t* op-fpm-fcm.cc: New source.\n\t* op-fpm-fm.cc: New source.\n\t* op-fpm-fpm.cc: New source.\n\t* op-m-pm.cc: New source.\n\t* op-pm-cm.cc: New source.\n\t* op-pm-m.cc: New source.\n\t* op-pm-pm.cc: New source.\n\t* op-pm-template.cc: New source.\n\t* Makefile.in: Include new sources.\n\t* DLD-FUNCTIONS/qr.cc (Fqr): Reflect interface changes of QR classes.\n\n2008-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* debug.cc (bp_table::do_get_breakpoint_list): Style fixes.\n\n2008-12-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (octave_base_value::is_diag_matrix): New virtual method.\n\t* ops.h (CONCAT2, CONCAT3): New macros. Use CONCAT macros instead of\n\tdirect token pasting to avoid disabling argument prescan.\n\t* xdiv.cc, xdiv.h: Implement xdiv and xleftdiv overloads for diagonal\n\tand mixed dense-diagonal operands.\n\n\t* ov-re-diag.h: New source.\n\t* ov-re-diag.cc: New source.\n\t* ov-flt-re-diag.h: New source.\n\t* ov-flt-re-diag.cc: New source.\n\t* ov-base-diag.h: New source.\n\t* ov-base-diag.cc: New source.\n\t* OPERATORS/op-m-dm.cc: New source.\n\t* OPERATORS/op-m-cdm.cc: New source.\n\t* OPERATORS/op-fm-fdm.cc: New source.\n\t* OPERATORS/op-fm-fcdm.cc: New source.\n\t* OPERATORS/op-fdm-fs.cc: New source.\n\t* OPERATORS/op-fdm-fm.cc: New source.\n\t* OPERATORS/op-fdm-fdm.cc: New source.\n\t* OPERATORS/op-fdm-fcs.cc: New source.\n\t* OPERATORS/op-fdm-fcm.cc: New source.\n\t* OPERATORS/op-fdm-fcdm.cc: New source.\n\t* OPERATORS/op-fcm-fdm.cc: New source.\n\t* OPERATORS/op-fcm-fcdm.cc: New source.\n\t* OPERATORS/op-fcdm-fs.cc: New source.\n\t* OPERATORS/op-fcdm-fm.cc: New source.\n\t* OPERATORS/op-fcdm-fdm.cc: New source.\n\t* OPERATORS/op-fcdm-fcs.cc: New source.\n\t* OPERATORS/op-fcdm-fcm.cc: New source.\n\t* OPERATORS/op-fcdm-fcdm.cc: New source.\n\t* OPERATORS/op-dms-template.cc: New source.\n\t* OPERATORS/op-dm-template.cc: New source.\n\t* OPERATORS/op-dm-s.cc: New source.\n\t* OPERATORS/op-dm-m.cc: New source.\n\t* OPERATORS/op-dm-dm.cc: New source.\n\t* OPERATORS/op-dm-cs.cc: New source.\n\t* OPERATORS/op-dm-cm.cc: New source.\n\t* OPERATORS/op-dm-cdm.cc: New source.\n\t* OPERATORS/op-cm-dm.cc: New source.\n\t* OPERATORS/op-cm-cdm.cc: New source.\n\t* OPERATORS/op-cdm-s.cc: New source.\n\t* OPERATORS/op-cdm-m.cc: New source.\n\t* OPERATORS/op-cdm-dm.cc: New source.\n\t* OPERATORS/op-cdm-cs.cc: New source.\n\t* OPERATORS/op-cdm-cm.cc: New source.\n\t* OPERATORS/op-cdm-cdm.cc: New source.\n\t* Makefile.in: Include them.\n\n\t* ov-re-mat.cc (octave_matrix::diag): New method override.\n\t* ov-re-mat.h: Declare it.\n\t* ov-cx-mat.cc: Likewise with octave_complex_matrix.\n\t* ov-cx-mat.h: Likewise with octave_complex_matrix.\n\t* ov-flt-re-mat.cc: Likewise with octave_float_matrix.\n\t* ov-flt-re-mat.h: Likewise with octave_float_matrix.\n\t* ov-flt-cx-mat.cc: Likewise with octave_float_complex_matrix.\n\t* ov-flt-cx-mat.h: Likewise with octave_float_complex_matrix.\n\t* ov.cc (octave_value::octave_value (const DiagMatrix&))\n\t(octave_value::octave_value (const FloatDiagMatrix&))\n\t(octave_value::octave_value (const ComplexDiagMatrix&))\n\t(octave_value::octave_value (const FloatComplexDiagMatrix&)):\n\tConstruct a diagonal matrix object.\n\t* data.cc (Fdiag): Support explicit dimensions. Fix tests.\n\t(Feye): Return diagonal matrix objects if possible. Fix tests.\n\t* mappers.cc (Freal, Fimag): Fix tests.\n\t* DLD-FUNCTIONS/inv.cc (Finv): Handle diagonal matrix objects.\n\t* ov-range.h (octave_range::diag): Declare only.\n\t* ov-range.cc (octave_range::diag): Return DiagMatrix if possible.\n\n2008-11-25  Jaroslav Hajek  <highegg@gmail.com>\n\t* ov.cc (octave_value::is_equal): New member function.\n\t* ov.h: Declare it.\n\t* pt-select.cc (tree_switch_case::label_matches): Call\n\toctave_value::is_equal.\n\n2008-12-04  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* DLD-FUNCTIONS/cellfun.cc: Added more tests for cellfun.\n\n2008-11-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.h (octave_base_value::type_conv_info): New class.\n\t* ov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc,\n\tov-bool-sparse.h, ov-bool.cc, ov-bool.h, ov-complex.cc, ov-complex.h,\n\tov-cx-mat.cc, ov-cx-mat.h, ov-null-mat.cc, ov-null-mat.h,\n\tov-range.cc, ov-range.h, ov-re-mat.cc, ov-re-mat.h, ov-scalar.cc,\n\tov-scalar.h, ov-str-mat.cc, ov-str-mat.h, ov.h:\n\tReturn type_conv_info instead of type_conv_fcn from\n\tnumeric_conversion_function and numeric_demotion_function\n\tmethods.\n\t* ov-base.cc (octave_base_value::numeric_assign): Try biased conversion\n\tfirst if possible.\n\t* ov.cc (do_binary_op): Likewise. Also, search recursively.\n\t* ov.cc (do_cat_op): Likewise.\n\n2008-11-24  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (F__go_delete__): Check validity of handles before\n\tdeleting them to avoid issues with callback function also deleting\n\tthe handles.\n\n2008-11-21  John Swensen  <jpswensen@comcast.net>\n\n\t* debug.cc (bp_table::do_get_breakpoint_list): Avoid modifying\n\tbp_map while iterating over it.\n\n2008-11-21  Jarkko Kaleva  <d3roga@gmail.com>\n\n\t* DLD-FUNCTIONS/eig.cc (Feig): Handle generalized eigenvalues and\n\teigenvectors.\n\n2008-11-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD_FUNCTIONS/det.cc: Include only DET.h. Retrieve & matrix type &\n\tstore it after calculation if possible.\n\n2008-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::dir_info::update): Simplify previous\n\tchange.\n\n\t* load-path.h (load_path::dir_info::abs_dir_name): New data member.\n\t(load_path::dir_info::dir_info, load_path::dir_info::operator =):\n\tCopy abs_dir_name.\n\t(load_path::abs_dir_cache_type, load_path::dir_cache_iterator,\n\tload_path::const_dir_cache_iterator): New typedefs.\n\t(load_path::abs_dir_cache): New static data member.\n\t(load_path::dir_info:dir_info): New constructor.\n\t* load-path.cc (load_path::abs_dir_cache): Define new static data\n\tmember.\n\t(load_path::dir_info::update): Look in abs_dir_cache for relative\n\tdirectory names.\n\t(load_path::dir_info::initialize): Update abs_dir_cache here.\n\n2008-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* ov-int8.h, ov-int16.h, ov-int32.h, ov-int64.h, ov-uint8.h,\n\tov-uint16.h, ov-uint32.h, ov-uint64.h: Don't define\n\tOCTAVE_INT_NDARRAY_T.\n\t* ov-intx.h (class OCTAVE_VALUE_INT_MATRIX_T,\n\tclass OCTAVE_VALUE_INT_SCALAR_T): Use intNDArray<OCTAVE_INT_T>\n\tinstead of OCTAVE_INT_NDARRAY_T.\n\t(OCTAVE_VALUE_INT_MATRIX_T::increment,\n\tOCTAVE_VALUE_INT_MATRIX_T::decrement,\n\tOCTAVE_VALUE_INT_SCALAR_T::increment,\n\tOCTAVE_VALUE_INT_SCALAR_T::decrement): Convert 1 to OCTAVE_INT_T.\n\n2008-11-15  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* strfns.cc (Fchar): adapt to conserve empty strings, add tests\n\n2008-11-12  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* dirfcn.cc (Ffilesep): Make it return all file separators when 'all'\n\tis given as argument.\n\n\t* DLD-FUNCTIONS/getrusage.cc: Undefine min/max.\n\t* TEMPLATE-INST/Array-os.cc: Declare Array<bool> as extern template.\n\n2008-11-12  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-cell.cc (op_catop_matrix_cell): Cast args in the correct\n\torder.\n\t* OPERATORS/op-struct.cc (op_catop_matrix_struct): Ditto.\n\n2008-11-11  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-assign.cc: Fix handling of empty cs-lists in assignment LHS.\n\n2008-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (<MATRIX_START>{S}+): Don't insert separator if next token\n\tis a separator.\n\n\t* parse.y (F__parser_debug_flag__): New function.\n\n2008-10-31  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* xnorm.cc: New source.\n\t* xnorm.h: New header file.\n\t* Makefile.in: Include xnorm.cc in the build process.\n\t* data.cc (Fnorm): Call xnorm, xcolnorms, xrownorms or xfrobnorm\n\tto do the actual work.\n\n2008-10-31  David Bateman  <dbateman@free.fr>\n\n\t* ov-base-scalar.h (octave_value octave_base_scalar::reshape\n\t(const dim_vector&) const): New method.\n\n2008-10-30  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.cc (Octave_map::index): Copy key_list.\n\n2008-10-31  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (void image::init (void)): Add a constraint for\n\tlogical cdata.\n\n\t* graphics.h.in (base_property::delete_listener): New method.\n\t(property::delete_listener): New method.\n\t(base_graphics_object::delete_listener): New method.\n\t(base_graphics_object::delete_property_listener): New method.\n\t(base_graphics_object::remove_all_listeners): New method.\n\t(graphics_object::delete_property_listener): New method.\n\t(axes::set_defaults): Call remove_all_listeners.\n\t* graphics.cc (void base_properties::delete_listener): New method\n\t(void base_graphics_object::remove_all_listeners (void)): New method\n\t(Fdellistener): New command to remove listener functions associated\n\twith a property.\n\n2008-10-30  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (axes::properties): Add keyreverse property.\n\t* graphics.cc (axes::properties::set_defaults): Initialize\n\tkeyreverse property.\n\n2008-10-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Cell.h (Cell::assign (const Array<idx_vector>&, ...),\n\tCell::delete_elements (const Array<idx_vector>&, ...)):\n\tNew member functions.\n\t* Cell.cc (Cell::assign (const octave_value_list&, ...),\n\tCell::delete_elements (const octave_value_list&, ...)):\n\tCall Array<T>::assign.\n\t* DLD-FUNCTIONS/dlmread.cc: Call Array<T>::resize_fill.\n\t* ov-base-mat.cc (octave_base_matrix::assign): Call Array<T>::assign.\n\t(octave_base_matrix::delete_elements):: Call Array<T>::delete_elements.\n\t* ov-cell.cc (Fcell): Call Array<T>::chop_trailing_singletons,\n\tsimplify.\n\t* ov-cx-mat.cc (octave_complex_matrix::assign): Call Array<T>::assign.\n\t* ov-flt-cx-mat.cc (octave_float_complex_matrix::assign): Call\n\tArray<T>::assign.\n\t* ov-list.cc (octave_list::subsasgn): Call Array<T>::assign.\n\t* pr-output.cc (PRINT_ND_ARRAY): Use zero-based indices.\n\n2008-10-29  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* data.cc (Fcolumns): Remove \"and\" from @seealso string.\n\t* mappers.cc (Fgamma, Flgamma): Replace @seealso reference to\n\tdeprecated gammai by gammainc.\n\t* DLD-FUNCTIONS/sqrtm.cc (Fsqrtm): Remove reference to Octave\n\tForge function funm.\n\t* DLD-FUNCTIONS/qz.cc (Fqz): removed @seealso reference to Octave\n\tForge function dare.\n\t* DLD-FUNCTIONS/rcond.cc (Frcond): removed @seealso reference to\n\tmldivide.\n\t* debug.cc (Fdbstop): Fix @seealso references and function name in\n\tdocstring of dbnext.\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Remove @seealso reference\n\tto isclass.\n\t* syscalls.cc (Fwaitpid): Replace WCONTINUED by WCONTINUE.\n\t* oct-hist.cc (Fhistory_size, Fsaving_history): Fix @seealso\n\treferences to history_timestamp_format_string.\n\t* DLD-FUNCTIONS/luinc.cc (Fluinc): Remove reference to missing\n\tfunction cholinc.\n\n2008-10-29  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/qr.cc (Fcholinsert, Fcholdelete, Fcholshift): Fix\n\tinline docs.\n\n2008-10-28  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (finish_function): Clear local variables in function scope.\n\t* symtab.h (symbol_table::clear_variables): New argument, scope.\n\n2008-10-28  Brian Gough  <bjg@gnu.org>\n\n\t* DLD-FUNCTIONS/besselj.cc: Added tests.\n\n2008-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* oct-hist.c (initialize_history): New arg, read_history_file)\n\t* oct-hist.h: Fix decl.\n\t* octave.cc (octave_main): Set read_history_file to false if\n\t--no-history option is specified.  Pass read_history_file to\n\tinitialize_history.\n\n\t* DLD-FUNCTIONS/fltk_backend.cc: Update initialization comment.\n\n2008-10-22  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (figure_manager::do_close_all):\n\tRename from close_all.  Now private.\n\t(figure_manager::do_new_window): Rename from new_window.\n\tNow private.\n\t(figure_manager::do_delete_window): Rename from delete_window.\n\tNow private.\n\t(figure_manager::do_mark_modified): Rename from mark_modified.\n\tNow private.\n\t(figure_manager::do_get_size): Rename from get_size.  Now private.\n\t(figure_manager::close_all, figure_manager::do_new_window,\n\tfigure_manager::do_delete_window,\n\tfigure_manager::do_mark_modified, figure_manager::do_get_size):\n\tNew static functions.\n\t(figure_manager::instance_ok): New function.\n\t(figure_manager::Instance): Delete.  Eliminate all uses in favor\n\tof static methods that call instance_ok and forward to private\n\tmember functions.\n\t(figure_manager::instance): New static data member.\n\t(figure_manager::hnd2idx, figure_manager::figprops2idx,\n\tfigure_manager::figprops2idx, figure_manager::str2idx): Now static.\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (figure_manager::default_size):\n\tIncrease default window size.\n\n\t* graphics.cc (figure::properties::remove_child): New function.\n\t* graphics.h.in: Provide decl.\n\n\t* gl-render.cc (opengl_renderer::draw): Get all children.\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (__fltk_redraw__):\n\tCheck for \"root\" object, not \"root_figure\".\n\n\t* graphics.h.in (base_properties::get_all_children): New function.\n\n2008-10-22  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (line::properties, surface::properties): Add data\n\tsource properties.\n\n2008-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (axes::properties::delete_children): Delete decl.\n\n\t* graphics.h.in (gh_manager::is_handle_visible): New function.\n\t(axes::properites): Move title property after label properties.\n\t(graphics_object::is_handle_visible): New function.\n\t(base_properties::is_handle_visible): New function.\n\t(base_properties): Mark children property with G.\n\t* graphics.cc (axes::properties::set_text_child): New function.\n\t(axes::properties::set_title, axes::properties::set_xlabel,\n\taxes::properties::set_ylabel, axes::properties::set_zlabel): Use it.\n\t(base_property::get_children): New function.  Only\n\treturn handles that are visible.\n\t(axes::properties::delete_text_child): Set handlevisibility to\n\t\"off\" for newly created object and add it to the list of children.\n\tCall base_properties::remove_child on previous handle value.\n\t(axes::properties::set_defaults): Don't explicitly delete xlabel,\n\tylabel, zlabel, and title handles.  Reinitialize them after\n\tdeleting children.\n\t(axes::properties::remove_child): Don't explicitly delete xlabel,\n\tylabel, zlabel, and title handles.\n\t(axes::properties::init): Move here from graphics.h.in.  Set\n\thandlevisibility to \"off\" for xlabel, ylabel, zlabel, and title\n\tand add them to the list of children.\n\t(axes::properties::delete_children): Delete.\n\n\t* genprops.awk: Allow whitespace between BEGIN_PROPERTIES and\n\topening paren.  Accept optional second argument for graphics\n\tobject name.\n\t* graphics.h.in (root_figure properties): Pass \"root\" as second\n\targ to BEGIN_PROPERTIES.\n\n2008-10-16  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (make_handle_fraction): New static function.\n\t(gh_manager::get_handle): Use it.\n\t(gh_manager::do_free): Call make_handle_fraction to replace\n\tfractional part of non-figure handles.\n\n\t* graphics.cc (base_properties::remove_child): Handle children as\n\ta column vector instead of a row vector.\n\n\t* utils.cc (Fis_absolute_filename, Fis_rooted_relative_filename,\n\tFmake_absolute_filename, Ffind_dir_in_path): New functions.\n\n2008-10-16  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (void axes::properties::set_defaults\n\t(base_graphics_object&,\tconst std::string&)): Preserve font\n\tand position properties if the axis is \"replaced\".\n\n2008-10-16  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (class axes::properties): New property: interpreter.\n\n2008-10-15  David Bateman  <dbateman@free.fr>\n\n\t* ov-class.c (Fsuperiorto, Finferiorto): Allow more than one class\n\tto be defined at a time.\n\n2008-10-12  David Bateman  <dbateman@free.fr>\n\n\t* pt-colon.cc (octave_value tree_colon_expression::make_range\n\t(const octave_value&, const octave_value&, const octave_value&)):\n\tTreating class overloading of colon operator.\n\t(octave_value tree_colon_expression::rvalue (void)): Ditto.\n\n2008-10-10  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (base_properties::adopt): Place new child at front\n\tof list, not end.  Make list of children a column vector instead\n\tof a row vector.\n\n\t* graphics.cc (gh_manager::do_free): Set the beingdeleted\n\tproperty, then delete the children, then execute the deletefcn.\n\t(axes::properties::set_defaults, axes::properties::remove_child,\n\taxes::properites::delete_children): Call delete_text_child to\n\tmanage the title, xlabel, ylabel, and zlabel properties.\n\t(axes::properties::get_title, axes::properties::get_xlabel,\n\taxes::properties::get_ylabel, axes::properties::get_zlabel): Delete.\n\n\t* graphics.h.in (axes::properites::title,\n\taxes::properites::xlabel, axes::properites::ylabel,\n\taxes::properites::zlabel): No longer mutable.  Don't generate\n\tfactory default values or custom get functions for these\n\tproperties.\n\n\t* graphics.cc (axes::properties::delete_text_child): New function.\n\t* graphics.h.in: Provide decl.\n\n\t* graphics.h.in (graphics_object::type): New function.\n\n2008-10-10  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (radio_property axes::properties::__colorbar__):\n\tDelete.\n\t* graphics.cc (void axes::properties::sync_positions (void)):\n\tDisable code synchronizing outerposiiton and position.\n\t(void axes::properties::set_defaults (base_graphics_object&,\n\tconst std::string&): Remove __colorbar__.\n\t(F__go_delete__): Don't delete if already being deleting to avoid\n\trecursion in callback functions.\n\t(F__go_axes_init__): Flag error if handle is deleted during\n\tinitialization due.\n\n2008-10-09  David Bateman  <dbateman@free.fr>\n\n\t* ov-class.cc (Octave_map octave_class::map_value (void) const):\n\tRemove.\n\t(bool octave_class::save_ascii (std::ostream&),\n\tbool octave_class::load_ascii (std::istream&),\n\tbool octave_class::save_binary (std::ostream&, bool&),\n\tbool octave_class::save_binary (std::ostream&, bool&),\n\tbool octave_class::save_hdf5 (hid_t, const char *, bool),\n\tbool octave_class::load_hdf5 (hid_t, const char *, bool)):\n\tAllow saving and reloading of classes.\n\t* ov-class. (Octave_map octave_class::map_value (void) const):\n\tRemove.\n\t* ls-mat.cc (std::string read_mat5_binary_element (std::istream&,\n\tconst std::string&, bool, bool&, octave_value&),\n\tint save_mat5_element_length (const octave_value&, const std::string&,\n\tbool, bool)): Allow saving and loading of classes.\n\t* ls-oct-ascii.h (template <class T> bool extract_keyword\n\t(std::istream&, const char *, T&, const bool)): Initialize value with\n\tnull constructor rather than 0.\n\n2008-10-07  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (F__go_delete__): Allow arrays of graphic handles.\n\n2008-10-01  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-i64-i64.cc: Instantiate all 64-bit operations.\n\t* OPERATORS/op-ui64-ui64.cc: Instantiate all unsigned 64-bit operations.\n\n2008-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* ov-type-conv.h (octave_type_conv_body): Avoid shadow warning\n\tfrom GCC.\n\n2008-10-06  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (static bool is_handle (const octave_value&)): Delete.\n\t(static octave_value is_handle (const octave_value&)): New function.\n\n2008-10-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Cell.cc (Cell::delete_elements): Don't pass second arg to\n\tArray<T>::maybe_delete_elements.\n\t* ov-base-mat.cc (octave_base_matrix<MT>::delete_elements): Ditto.\n\n2008-10-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Cell.h (Cell::delete_elements): Declare new member function.\n\t* Cell.h (Cell::delete_elements): Define it.\n\t* oct-map.cc (Octave_map::maybe_delete_elements): Call delete_elements\n\tinstead of assign with empty Cell.\n\n2008-10-02  John W. Eaton  <jwe@octave.org>\n\n\t* pt-arg-list.cc (tree_argument_list::convert_to_const_vector):\n\tDon't insert undefined elements in return list.\n\n2008-09-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-str-mat.h (octave-char-matrix-str::assign): Remove declaration.\n\t* ov-str-mat.cc (octave-char-matrix-str::assign): Remove definition.\n\n2008-09-30  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc: Only define\n\tmagick_to_octave_value if HAVE_MAGICK is defined.\n\n2008-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::load_class_method):\n\tCall load_class_constructor if name and dispatch_type are the same.\n\n2008-09-29  David Bateman  <dbateman@free.fr>\n\n\t* symtab.cc (octave_value symbol_table::find_function\n\t(const std::string&, tree_argument_list *, const string_vector&,\n\toctave_value_list&, bool&)): If first character of function name\n\tis \"@\" then look for class specific method.\n\n2008-09-26  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (out_of_date_check_internal):\n\tFix order of arguments in call to load_path::find_method.\n\n2008-09-26  David Bateman  <dbateman@free.fr>\n\n\t* ov-class.h (idx_vector index_vector (void) const): Declare new\n\tmaethod.\n\t* ov-class.cc (idx_vector index_vector (void) const): Define new\n\tmethod.\n\t* (Fismethod): New function.\n\n2008-09-26  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (urlwrite_cleanup_file) New function.\n\t(urlwrite_delete_file, urlwrite_filename): New static variables.\n\t(Furlwrite): Only return filename if urlget succeeds.  Use\n\tunwind_protect to delete files we create if download fails.\n\n2008-09-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-null-mat.h: New header file.\n\t* ov-null-mat.cc: New source.\n\t* ov.h (octave_value::is_null_value, octave_value::non_null_value,\n\toctave_value::make_non_null_value):\n\tDeclare new member functions.\n\t* ov.cc (octave_value:non_null_value, octave_value::make_non_null_value):\n\tDefine them.\n\t(octave_value::assign (assign_op op, const octave_value& rhs)):\n\t(register_types): Register null types.\n\tCall non_null_value ().\n\t* oct-obj.cc (octave_value_list::normalize_null_values): New member\n\tfunction.\n\t* oct-obj.h (octave_value_list::normalize_null_values): Declare it.\n\t* ov-base.h (is_null_value): New virtual member function.\n\t* ops.h (NULLASSIGNOPDECL, DEFNULLASSIGNOP_FN): New macros.\n\t* ov-base-mat.cc (octave_base_mat<MT>::delete_elements): New member func.\n\t* ov-base-mat.h: Declare it.\n\t* ov-base-sparse.cc (octave_base_sparse<MT>::delete_elements): New member func.\n\t* ov-base-sparse.h: Declare it.\n\t* ov-cell.cc (octave_cell:subsasgn): Handle null values.\n\t* ov-struct.cc (octave_cell:subsasgn): Handle null values.\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op): Normalize return\n\tvalues.\n\t* pt-misc.cc (tree_parameter_list::define_from_arg_vector): Call\n\toctave_lvalue::define instead of octave_lvalue::assign.\n\t* pt-decl.h (tree_decl_elt::rvalue): Call non_null_value ().\n\t* OPERATORS/op-int.h (OCTAVE_INT_NULL_ASSIGN_OPS,\n\tOCTAVE_INSTALL_INT_NULL_ASSIGN_OPS): New macros.\n\t* OPERATORS/op-m-m.cc: Install & define assignment & conversion operators.\n\t* OPERATORS/op-bm-bm.cc: Ditto.\n\t* OPERATORS/op-cell.cc: Ditto.\n\t* OPERATORS/op-cm-cm.cc: Ditto.\n\t* OPERATORS/op-cs-cs.cc: Ditto.\n\t* OPERATORS/op-fcm-fcm.cc: Ditto.\n\t* OPERATORS/op-fcs-fcs.cc: Ditto.\n\t* OPERATORS/op-fm-fm.cc: Ditto.\n\t* OPERATORS/op-fs-fs.cc: Ditto.\n\t* OPERATORS/op-int.h: Ditto.\n\t* OPERATORS/op-m-m.cc: Ditto.\n\t* OPERATORS/op-range.cc: Ditto.\n\t* OPERATORS/op-s-s.cc: Ditto.\n\t* OPERATORS/op-scm-scm.cc: Ditto.\n\t* OPERATORS/op-sm-sm.cc: Ditto.\n\t* OPERATORS/op-str-str.cc: Ditto.\n\t* OPERATORS/op-i16-i16.cc: Ditto.\n\t* OPERATORS/op-i32-i32.cc: Ditto.\n\t* OPERATORS/op-i64-i64.cc: Ditto.\n\t* OPERATORS/op-i8-i8.cc: Ditto.\n\t* OPERATORS/op-ui16-ui16.cc: Ditto.\n\t* OPERATORS/op-ui32-ui32.cc: Ditto.\n\t* OPERATORS/op-ui64-ui64.cc: Ditto.\n\t* OPERATORS/op-ui8-ui8.cc: Ditto.\n\n2008-09-25  David Bateman  <dbateman@free.fr>\n\n\t* pt-mat.cc (class tm_row_const): Add any_class test\n\t(class tm_const): Ditto.\n\t(octave_value tree_matrix::rvalue (void)): If any object to\n\tconcatenate is a class object, dispatch to the appropriate\n\tvertcat/horzcat function.\n\n2008-09-25  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_table::do_find): Don't set evaluated_args and\n\targs_evaluated here, prior to call to symbol_table::fcn_info::find.\n\n2008-09-24  Søren Hauberg  <hauberg@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (magick_to_octave_value): New\n\ttemplate function with specializations for various\n\tGraphicsMagick++ types.\n\t(F__magick_finfo__): New function.\n\n2008-09-24  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tAdd symbol_table::clear_variables cleanup function to the\n\tunwind_protect stack after the parameter list cleanup functions.\n\n\t* load-path.cc (load_path::do_initialize): Check for OCTAVE_PATH\n\tin the environment, not OCTAVE_LOADPATH.\n\n2008-09-24  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp_list): Retry if match limit\n\tis exceeded.\n\n2008-09-24  John W. Eaton  <jwe@octave.org>\n\n\t* genprops.awk (emit_declarations): Emit call to set_mode before\n\tupdaters.\n\n2008-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* pt-arg-list.cc (F__end__): Dispatch to user-defined end\n\tfunction for classes if one is defined.\n\t* lex.l (is_keyword_token): Allow \"end\" as a functon name.\n\n2008-09-23  David Bateman  <dbateman@free.fr>\n\n\t* variables.cc (static octave_value do_who (int, const string_vector&,\n\tbool, bool, std::string): Add final message argument and simple\n\ttreatment of the \"-file\" option.\n\n2008-09-22  David Bateman  <dbateman@free.fr>\n\n\t* debug.cc (static octave_user_code * get_user_code\n\t(const std::string&)): Only check user code as break points can't\n\tbe set in builtins or oct-files.\n\t(bp_table::intmap bp_table::do_remove_all_breakpoints_in_file\n\t(const std::string&, bool)): Add flag to silence the error message\n\tfrom this function if a user code with breakpoints is not found.\n\t(bp_table::fname_line_map bp_table::do_get_breakpoint_list (const\n\toctave_value_list&)): Do an ourt of date check on the function\n\tbefore checking the breakpoints.\n\t* debug.h (do_remove_all_breakpoints_in_file,\n\tremove_all_breakpoints_in_file): Add flag to silence error\n\tmessage.\n\t* symtab.cc (out_of_date_check_internal): Clear breakpoints in\n\tfunction if out_of_date. split into two versions taking the\n\toctave_function pointer seperately or not.\n\t* symtab.h (bool out_of_date_check (octave_function*)): New function.\n\n2008-09-18  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/fftw.cc (Ffftw): Clarify the documentation.\n\n2008-09-17  Krzesimir Nowak  <qdlacz@gmail.com>\n\n\t* debug.cc (Fisdebugmode): New function.\n\n2008-09-17  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (do_cat): Chopping trailing singleton dimensions.\n\n\t* data.cc (SINGLE_TYPE_CONCAT, DO_SINGLE_TYPE_CONCAT): New macros\n\t(do_cat): Special case single type concatenations for speed.\n\t* pt.mat.cc (std::string get_concat_class (const std::string&,\n\tconst std::string&), void maybe_warn_string_concat (bool, bool)):\n\tRemove static declaration.\n\t* pt-mat.h (std::string get_concat_class (const std::string&,\n\tconst std::string&), void maybe_warn_string_concat (bool, bool)):\n\tDefine extern here.\n\n\t* DLD-FUNCTIONS/sparse.cc (Fsparse): Clarify the help string.\n\n2008-09-10  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (octave_main): Make all command-line arguments\n\tavailable to startup scripts and PKG_ADD files.\n\n2008-09-09  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp_list): Distinguish between\n\tmatlab named tokens and perl lookbehind expressions. For\n\tlookbehind expression replace \"*\" and \"+\" with a limited number of\n\tfixed length expressions to simulate arbitrary length look behind.\n\n2008-09-08  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (encode_uint_image): Resolve \"pow\"\n\tambiguity.\n\n\t* graphics.cc (base_properties::get_dynamic,\n\tbase_properties::set_dynamic, base_propertyes::get_property_dynamic):\n\tAdd the 3rd template parameter to std::map, corresponding to all_props\n\tfield.\n\n2008-09-08  John W. Eaton  <jwe@octave.org>\n\n\t* ls-oct-ascii.cc (std::string extract_keyword (std::istream&,\n\tconst char *, const bool)): Also accept \\r as line ending character.\n\t* ls-oct-ascii.h (template <class T> bool extract_keyword\n\t(std::istream&, const char *, T&, const bool)): Likewise.\n\t(template <class T> bool extract_keyword (std::istream&, const\n\tstring_vector&, std::string&, T&, const bool)): Likewise.\n\n2008-09-03  Ben Abbott  <bpabott@mac.com>\n\n\t* mappers.cc: Use eps(single) as tolerance for single precesion test.\n\n2008-09-03  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (mlock): Lock current function on the call stack.\n\t(Fmlock): Lock caller.\n\n\t* symtab.cc (out_of_date_check_internal): If dispatch type is set,\n\tcheck for method.  If that fails, check for regular function.\n\n2008-09-02  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.cc (hggroup::update_axis_limits): Also reacts on\n\t[xyzac]liminclude changes.\n\n2008-08-31  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* DLD-FUNCTIONS/fltk_backend.cc (fltk_backend::redraw_figure,\n\tfltk_backend::print_figure): Change graphics_handle argument to\n\tgraphics_object.\n\n2008-08-29  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc: Replace int by octave_idx_type in multiple\n\tplaces.\n\t(array_property::is_equal): In macro CHECK_ARRAY_EQUAL, special\n\tcase scalar case and keep copy of array value to avoid early\n\tdestruction of converted array values.\n\n2008-08-28  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (root_figure::properties::showhiddenhandles):\n\tNew property.\n\n2008-08-27  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Initialize output vectors\n\tby NA value.\n\n2008-08-26 Ben Abbott  <bpabott@mac.com>\n\n\t* mappers.cc: Adjust tolerance for single precesion tests.\n\n\t* DLD-FUNCTIONS/chol.cc: Double tolerance.\n\n2008-08-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* parse.y (Fassignin): Use default  scope when calling varref.\n\n2008-08-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* genprops.awk (emit_declarations): Call updaters/listeners only when\n\t'set' method returned true.\n\t* graphics.h.in (base_property::set, base_property::do_set):\n\tReturn bool value.\n\t(property::set): Likewise.\n\t(string_property::do_set): Check value change and return bool value.\n\t(radio_property::do_set, double_property::do_set,\n\tarray_property::do_set): Likewise.\n\t(color_property::do_set, double_radio_property::do_set,\n\trow_vector_property::do_set, bool_property::do_set,\n\thandle_property::do_set): Return bool value.\n\t(any_property::do_set, callback_property::do_set): Return always true.\n\t(color_values::operator==, color_values::operator!=): Add.\n\t(array_property::is_equal): Add.\n\t* graphics.cc (base_property::set): Executes listeners/notifiers only\n\twhen do_set returns true. Return bool value.\n\t(color_property::do_set, double_radio_property::do_set): Check value\n\tchange and return bool value.\n\t(array_property::is_equal): Add.\n\n\t* genprops.awk (emit_declarations, emit_source): Change code emission\n\twhen emitting base_properties code (base is 1).\n\t(BEGIN): Initialize pcount to 0.\n\t(BEGIN_PROPERTIES): Initialize base to 0.\n\t(BEGIN_BASE_PROPERTIES): New statement.\n\t(main): Add support for 'f' modifier. Add support for non xxx_property\n\ttyped properties.\n\t* graphics.h.in (base_properties::base_properties): Remove\n\timplementation.\n\t(base_properties::get_tag, base_properties::get_parent,\n\tbase_properties::get_type, base_properties::get___myhandle__,\n\tbase_properties::get_busyaction, base_properties::get_buttondownfcn,\n\tbase_properties::is_clipping, base_properties::get_clipping,\n\tbase_properties::execute_createfcn, base_properties::get_createfcn,\n\tbase_properties::execute_deletefcn, base_properties::get_deletefcn,\n\tbase_properties::get_handlevisibility, base_properties::is_hittest,\n\tbase_properties::get_hittest, base_properties::is_interruptible,\n\tbase_properties::get_interruptible, base_properties::is_selected,\n\tbase_properties::get_selected, base_properties::is_selectionhighlight,\n\tbase_properties::get_selectionhighlight,\n\tbase_properties::get_uicontextmenu, base_properties::get_userdata,\n\tbase_properties::is_visible, base_properties::get_visible,\n\tbase_properties::is_beingdeleted, base_properties::get_beingdeleted,\n\tbase_properties::set_busyaction, base_properties::set_buttondownfcn,\n\tbase_properties::set_clipping, base_properties::set_createfcn,\n\tbase_properties::set_deletefcn, base_properties::set_handlevisibility,\n\tbase_properties::set_hittest, base_properties::set_interruptible,\n\tbase_properties::set_selected,\n\tbase_properties::set_selectionhighlight,\n\tbase_properties::set_uicontextmenu, base_properties::set_userdata,\n\tbase_properties::set_visible, base_properties::set_beingdeleted,\n\tbase_properties::get_children): Remove (now auto-generated).\n\t(base_properties::enum): Likewise.\n\t(base_properties::is_modified): Call is___modified__.\n\t(base_properties::set_modified): Call set___modified__.\n\t(base_properties::set_children): Add.\n\t(base_properties::set_dynamic, base_properties::get_dynamic,\n\tbase_properties::get_property_dynamic): New methods.\n\t(class base_properties): Surround properties declaration with\n\tBEGIN_BASE_PROPERTIES/END_PROPERTIES pair.\n\t* graphics.cc (base_properties::get, base_properties::set,\n\tbase_properties::get_property): Remove (now auto-generated).\n\t(base_properties::set_dynamic, base_properties::get_dynamic,\n\tbase_properties::get_property_dynamic): New methods.\n\t(base_properties::set_children): Likewise.\n\n\t* DLD_FUNCTIONS/fltk_backend.cc (F__fltk_redraw__): Make static.\n\t(F__init_fltk__): Protect from mutliple invocations.\n\t(F__remove_fltk__): Likewise.\n\t(F__init_fltk__): Register input event hook.\n\t(F__remove_fltk__): Unregister input event hook.\n\n\t* DLD_FUNCTIONS/fltk_backend.cc (fltk_backend::close_figure): Remove.\n\t(fltk_backend::object_destroyed, fltk_backend::property_changed): New\n\tmethods.\n\t* genprops.awk (emit_declarations): Generate \"enum\" property fields.\n\t(emit_sources): Emit set_id calls.\n\t* graphics.h.in (base_property::id): New field.\n\t(base_property::base_property): Initialize it.\n\t(base_property::get_id, base_property::set_id): Add accessors.\n\t(property::get_id, property::set_id): Likewise.\n\t(base_graphics_backend::close_figure, graphics_backend::close_figure):\n\tRemove methods.\n\t(base_graphics_backend::redraw_figure,\n\tbase_graphics_backend::print_figure, graphics_backend::redraw_figure,\n\tgraphics_backend::print_figure): Change graphics_handle argument into\n\tgraphics_object.\n\t(base_graphics_backend::property_changed,\n\tbase_graphics_backend::object_created,\n\tbase_graphics_backend::object_destroyed,\n\tgraphics_backend::property_changed, graphics_backend::object_created,\n\tgraphics_backend::object_destroyed): New signature with\n\tgraphics_object argument.\n\t(base_properties::base_properties): Add set_id calls.\n\t(class base_properties): Add \"enum\" property fields.\n\t(root_figure::properties::remove_child): Add overloaded method.\n\t(figure::properties::close): Remove.\n\t(figure::properties::set_backend): Call object_destroyed instead of\n\tclose.\n\t(figure::~figure): Remove close call.\n\t(figure::properties::get_title): New method.\n\t* graphics.cc (base_property::set): Call property_changed only for\n\tvalid id (>=0); Use graphics_object argument.\n\t(gh_manager::do_free): Call object_destroyed with graphics_object\n\targument.\n\t(base_graphics_backend::property_changed,\n\tbase_graphics_backend::object_created,\n\tbase_graphics_object::object_destroyed): Implement wrappers for\n\tgraphics_handle argument case.\n\t(gnuplot_backend::close_figure): Remove.\n\t(gnuplot_backend::object_destroyed,\n\tgnuplot_backend::property_changed): New methods.\n\t(gnuplot_backend::redraw_figure, gnuplot_backend::print_figure):\n\tChange graphics_handle argument to graphics_object.\n\t(root_figure::properties::remove_child): Add.\n\t(figure::properties::close): Remove.\n\t(figure::properties::set_position): Do not call set_figure_position.\n\t(figure::properties::get_title): New method.\n\t(gh_manager::do_make_graphics_handle): Call object_created with\n\ta graphics_object argument.\n\t(gh_manager::do_make_figure_handle): Likewise.\n\t(Fdrawnow): Call redraw_figure and print_figure with a graphics_object\n\targument.\n\n2008-08-26  Maciek Gajewski  <maciej.gajewski0@gmail.com>\n\n\t* graphics.h.in (base_property::set): Remove inline implementation.\n\t(base_graphics_backend::property_changed,\n\tbase_graphics_backend::object_created,\n\tbase_graphics_backend::object_destroyed): New method.\n\t(graphics_backend::property_changed, graphics_backend::object_created,\n\tgraphics_backend::object_destroyed): Likewise.\n\t* graphics.cc (base_property::set): Moved from header file.\n\t(gh_manager::do_free): Add backend notification.\n\t(gh_manager::do_make_graphics_handle): Likewise.\n\t(gh_manager::do_make_figure_handle): Likewise.\n\n2008-08-25  Thomas L. Scofield  <scofield@calvin.edu>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc: Untabify.\n\t(jpg_settings, encode_bool_image, encode_uint_image, encode_map):\n\tNew functions.\n\t(write_image): Use them to handle various image types.\n\n2008-08-25  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (void gh_manager::do_execute_callback\n\t(const graphics_handle&, const octave_value&, const\n\toctave_value&)): Don't pass the function handle as first arg of\n\tproperty listener functions\n\n\t* graphics.h.in (class base_properties): Add functor for caseless\n\tstring comparison. Use it in the property map, so that user added\n\tproperties are found in a case insensitive fashion.\n\n2008-08-22  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h (symbol_table::inherit): Pass reference to symbol table\n\tto do_inherit instead of scope.\n\t(symbol_table::do_inherit): First arg is now reference to\n\tsymbol_table, not scope id.  Insert all variables from donor scope.\n\n2008-08-21  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* mappers.cc: Increase test script tolerance.\n\n2008-08-20  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (builtin_help): Go to next symbol name on error.\n\t(do_type, do_which): Omit separate path search for files.\n\t(help_from_symbol_table): Only insert Texinfo markup if it looks\n\tlike the help message is already in Texinfo.\n\n2008-08-19  David Bateman  <dbateman@free.fr>\n\n\t* load-path.cc (load-path::do_find_dir (const std:string&) const)):\n\tMethod to find a directory on the load-path corresponding to the\n\targument.\n\t* load-path.h (load-path::do_find_dir (const std:string&) const),\n\tload-path::find_dir (const std::string&) const): New methods.\n\t* utils.cc (std::string contents_file_in_path (const std::string&)):\n\tNew function.\n\t* utils.h  (std::string contents_file_in_path (const std::string&)):\n\tDeclare it.\n\t* help.cc (static bool raw_help_from_file (const std::string&,\n\tstd::string&, std::string&, bool&)): Also check is requested\n\targument is a directory and contains the file Contents.m.\n\n\t* OPERATORS/op-int-conv.cc (DEFINTCONVFN): New macro that warn\n\tfor integer conversion issues. Use it to replace DEFCONVFN.\n\t* OPERATORS/op-int.h (DEFINTBINOP_OP, DEFINTNDBINOP_OP,\n\tDEFINTBINOP_FN, DEFINTNDBINOP_FN): New macros that warn for\n\tinteger truncation issues. Use them to replace the corresponding\n\tmacros in the integer arithmetic macros. Update other integer\n\tarithmetic functions that don't use these macros individually.\n\t* error.cc (initialize_default_warning_state (void)): Initialize\n\tthe default warning state for the integer warnings to be off.\n\t* gripes.cc (void gripe_binop_integer_math_truncated (const char *,\n\tconst char *, const char *), void gripe_unop_integer_math_truncated\n\t(const char *, const char *), void gripe_non_integer_conversion\n\t(const char *, const char *), void gripe_nan_conversion (const char *,\n\tconst char *)): Warning functions for integer conversion and math\n\tissues.\n\t* gripes.h (void gripe_binop_integer_math_truncated (const char *,\n\tconst char *, const char *), void gripe_unop_integer_math_truncated\n\t(const char *, const char *), void gripe_non_integer_conversion\n\t(const char *, const char *), void gripe_nan_conversion (const char *,\n\tconst char *)): Declare them.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::convert_gripe,\n\tOCTAVE_VALUE_INT_SCALAR_T::convert_gripe): Adapt for new means of\n\tflagging integer truncation.\n\t(OCTAVE_VALUE_INT_MATRIX_T::decrement,\n\tOCTAVE_VALUE_INT_MATRIX_T::increment,\n\tOCTAVE_VALUE_INT_SCALAR_T::decrement,\n\tOCTAVE_VALUE_INT_SCALAR_T::increment): Check for integer\n\ttruncation.\n\t* ov.cc (convert_to_int_array): Adapt for new means of\n\tflagging integer truncation.\n\n2008-08-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* pt-assign.h (tree_simple_assignment::first_execution): New\n\tmember field.\n\t(tree_simple_assignment::first_execution): Ditto.\n\t* pt-assign.cc (tree_simple_assignment::tree_simple_assignment):\n\tInitialize first_execution.\n\t(tree_multi_assignment::tree_multi_assignment): Ditto.\n\t(tree_simple_assignment::rvalue): Check for obsolete built-in\n\tvariables only at first execution.\n\t(tree_multi_assignment::rvalue): Ditto.\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Checks whether LB and UB are\n\tof proper size.\n\n\t* oct-obj.cc, oct-obj.h (octave_value_list::make_argv):\n\tAllow calling without fcn_name.\n\t* load-save.cc (parse_save_options (const string_vector&, ...)):\n\tReturn string_vector with parsed arguments removed instead.\n\t(parse_save_options (const std::string&, ...)):\tDitto.\n\t(Fsave): Fix calls to parse_save_options.\n\n2008-08-19  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (Feval): Return value produced by evaluating CATCH string.\n\n2008-08-12  John W. Eaton  <jwe@octave.org>\n\n\t* pt-fcn-handle.cc (tree_anon_fcn_handle::rvalue):\n\tCall stash_parent_function_scope for user function.\n\t* ov-fcn-inline.cc (octave_fcn_inline::octave_fcn_inline):\n\tLikewise.\n\n\t* ov-struct.cc (octave_struct::subsref): Don't allow resizing for\n\tsimple x(idx) case.\n\n2008-08-07  John W. Eaton  <jwe@octave.org>\n\n\t* ov.cc (octave_value::idx_type_value): Don't include default\n\targument values in definition.\n\n\t* glrender.h, zfstream.h: Don't include config.h.\n\n\t* oct-errno.h: Include <cerrno>.\n\n\t* Cell.cc, DLD-FUNCTIONS/regexp.cc, DLD-FUNCTIONS/dlmread.cc,\n\tdebug.cc, error.cc, file-io.cc, graphics.cc, help.cc, input.cc,\n\tlex.l, load-path.cc, load-save.cc, ls-mat-ascii.cc,\n\tls-oct-ascii.cc, oct-stream.cc, octave.cc, variables.cc,\n\tov-fcn-handle.cc, parse.y, pr-output.cc, symtab.cc, sysdep.cc,\n\tutils.cc, graphics.h.in: Replace all uses of NPOS with\n\tstd::string::npos.\n\n\t* ov.cc (octave_value::idx_type_value): Move definition here.\n\t* ov.h: From here.\n\n\t* DLD-FUNCTIONS/fsolve.cc (override_options): Don't fail if\n\toptions_map does not contain an expected keyword.\n\tFix typo in warning identifier.\n\t(make_unimplemented_options): Use CamelCase names here.\n\n2008-08-06  Søren Hauberg  <hauberg@gmail.com>\n\n\t* error.cc (Ferror): Update format of error messages in exmple.\n\t* parse.y: (Feval): Likewise.\n\n2008-08-06  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fsolve.cc (hybrd_info_to_fsolve_info):\n\tUpdate INFO values to be compatible with Matlab's current fsolve.\n\t(make_unimplemented_options, override_options): New functions.\n\t(Ffsolve): Handle optimset options.  Update doc string.\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op,\n\toctave_user_script::do_multi_index_op):\n\tCall octave_call_stack::backtrace_error_message.\n\t* toplev.h (octave_call_stack::do_pop): Don't call\n\tbacktrace_error_message here.\n\t* toplev.cc, toplev.h (octave_call_stack::do_backtrace_error_message):\n\tRename from octave_call_stack::backtrace_error_message.\n\t* toplev.h (octave_call_stack::backtrace_error_message):\n\tNew public static function.\n\n2008-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* gripes.cc (gripe_truncated_conversion,\n\tgripe_logical_conversion): Don't declare as extern here.\n\t* utils.cc (octave_format, octave_vformat): Likewise.\n\t* pr-output.cc (octave_print_internal (std::ostream&, const Cell&,\n\tbool, int, bool)): Likewise.\n\n\t* toplev.cc (octave_call_stack::backtrace_error_message): New\n\tfunction.\n\t* toplev.h: Provide decl.\n\t(octave_call_stack::do_pop): Call backtrace_error_message if\n\terror_state is nonzero.\n\n\t* pt-unop.cc (tree_prefix_expression::eval_error,\n\ttree_postfix_expression::eval_error): Delete.  Eliminate all uses.\n\t* pt-unop.h: Delete decls.\n\n\t* pt-select.cc (tree_switch_case::eval_error,\n\ttree_switch_command::eval_error): Delete.  Eliminate all uses.\n\t(tree_if_command::eval): Omit \"evaluating if command\" message.\n\t* pt-select.h: Delete decls.\n\n\t* pt-loop.cc (tree_while_command::eval_error,\n\ttree_complex_for_command::eval_error,\n\ttree_simple_for_command::eval_error,\n\ttree_do_until_command::eval_error): Delete.  Eliminate all uses.\n\t* pt-loop.h: Delete decls.\n\n\t* pt-exp.cc (tree_expression::is_logically_true): Omit \"evaluating\n\tconditional expression\" error message.\n\n\t* pt-decl.cc (tree_global_command::eval): Omit \"evaluating global\n\tcommand\" error message.\n\t(tree_static_command::eval): Omit \"evaluating static command\"\n\terror message.\n\n\t* pt-colon.cc (tree_colon_expression::eval_error): Omit\n\t\"evaluating colon expression\" error message.\n\t* pt-colon.h (tree_colon_expression::eval_error): Eliminate\n\tdefault argument value.\n\n\t* pt-idx.cc (tree_index_expression::eval_error): Delete.\n\tEliminate all uses.\n\t* pt-idx.h: Delete decl.\n\n\t* pt-binop.cc (tree_binary_expression::eval_error): Delete.\n\t* pt-binop.cc, pt-cbinop.cc: Eliminate all uses of eval_error.\n\t* pt-binop.h: Delete decl.\n\n\t* pt-assign.cc (tree_simple_assignment::eval_error,\n\ttree_multi_assignment::eval_error): Delete.  Eliminate all uses.\n\t* pt-assign.h: Delete decls.\n\n\t* ov-usr-fcn.cc (octave_user_script::traceback_error,\n\toctave_user_function::traceback_error): Delete.  Eliminate all uses.\n\t* ov-usr-fcn.h: Delete decls.\n\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op): Call\n\tgripe_library_exectuion_error on octave_execution_exception.\n\t* ov-mex-fcn.cc (octave_mex_function::do_multi_index_op): Likewise.\n\t* ov.cc (do_binary_op, do_cat_op, do_unary_op,\n\tdo_non_const_unary_op): Likewise.\n\t* pt-stmt.cc (tree_statement::eval): Likewise.\n\n\t* gripes.cc (gripe_library_execution_error): New function.\n\t* gripes.h: Provide decl.\n\n\t* dirfns.cc (Fpathsep): Fix usage of dir_path::path_sep_str.\n\t* defaults.cc (set_exec_path, set_image_path): Likewise.\n\t* load-path.h (load_path::set_command_line_path): Likewise.\n\t* load-path.cc (maybe_add_path_elts, load_path::do_initialize,\n\tload_path::do_path, genpath, Fpath): Likewise.\n\t(split_path): Fix usage of dir_path::path_sep_char.\n\n2008-08-04  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::find_autoload):\n\tFix usage of file_ops::dir_sep_chars.\n\t* variables.cc (looks_like_struct):\n\tLikewise.\n\t* ov-fcn-handle.cc (octave_fcn_handle::set_fcn): Likewise.\n\t* octave.cc (execute_command_line_file): Likewise.\n\t* ls-mat5.cc (read_mat5_binary_element): Likewise.\n\t* load-save.cc (find_file_to_load): Likewise.\n\t* load-path.cc (load_path::do_find_file): Likewise.\n\t* graphics.cc (drawnow): Likewise.\n\t* parse.y (frob_function): Likewise.\n\n\t* octave.cc (initialize_pathsearch): Fix usage of\n\tfile_ops::dir_sep_str.\n\t* help.cc (Flookfor): Likewise.\n\t* dirfns.cc (Ffilesep): Likewise.\n\t(Fautoload): Likewise.\n\n\t* defaults.cc (subst_octave_home): Fix usage of\n\tfile_ops::dir_sep_char.\n\t(Fmfilename): Likewise.\n\n2008-07-31  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (assign_lhs): Call force_local_variable on all elements\n\tof lexer_flags.pending_local_variables here, then clear the set.\n\t(matrix): Clear lexer_flags.pending_local_variable here.\n\t* lex.l (lexical_feedback::init): Clear it.\n\t(force_local_variable): No longer static.\n\t(is_variable): Also return true for names in the\n\tlexer_flags.pending_local_variables.\n\t(handle_identifier): If we are parsing a matrix list, mark\n\tidentifiers as pending local variables rather than forcing them to\n\tbe local variables immediately.\n\t* lex.h (lexical_feedback::pending_local_variables): New data member.\n\t(force_local_variable): Provide decl.\n\n2008-07-30  John W. Eaton  <jwe@octave.org>\n\n\t* ov-intx.h, ov.cc: Style fixes.\n\n\t* gripes.cc (gripe_truncated_conversion): Use the warning ID\n\tOctave:int-convert-overflow.\n\n2008-07-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* gripes.cc (gripe_truncated_conversion): New function.\n\t* gripes.h (gripe_truncated_conversion): Declare it.\n\t* ops.h (DEFCONVFNX2): New macro.\n\t(DEFCONVFN, DEFCONVFN2): Call DEFCONVFNX2 instead of DEFCONVFNX.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::convert_gripe): New member\n\tfunction.\n\t(OCTAVE_VALUE_INT_MATRIX_T::int*_array_value): Call convert_gripe.\n\t(OCTAVE_VALUE_INT_SCALAR_T::convert_gripe): New member function.\n\t(OCTAVE_VALUE_INT_SCALAR_T::int*_scalar_value): Call convert_gripe.\n\t(OCTAVE_VALUE_INT_SCALAR_T::int*_array_value): Call int*_scalar_value.\n\t* ov.cc (convert_to_int_array): New function.\n\t(int_vector_value): Call convert_to_int_array.\n\n2008-07-30  John W. Eaton  <jwe@octave.org>\n\n\t* defun-dld.h (DEFUNX_DLD): Eliminate fsname arg.\n\t* defun-int.h (DEFINE_FUN_INSTALLER_FUN2,\n\tDEFINE_FUN_INSTALLER_FUN3, DEFINE_FUNX_INSTALLER_FUN2): Delete.\n\t(DEFINE_FUNX_INSTALLER_FUN): Rename from DEFINE_FUNX_INSTALLER_FUN3.\n\tDon't emit fsname function.  Don't append cxx_abi to gname.\n\t(DEFINE_FUN_INSTALLER_FUN): Define in terms of\n\tDEFINE_FUNX_INSTALLER_FUN, not DEFINE_FUN_INSTALLER_FUN2.\n\t* dynamic-ld.cc (octave_dynamic_loader::name_mangler,\n\toctave_dynamic_loader::name_uscore_mangler): New functions.\n\t(octave_dynamic_loader::mangle_name,\n\toctave_dynamic_loader::xmangle_name): Delete.\n\t(octave_dynamic_loader::do_load_oct): Search for function with\n\tname_mangler then name_uscore_mangler.\n\n\t* oct-stream.cc (do_read): New arg, do_NA_conv.\n\tPerform NA translation if do_NA_conv is true.\n\t(DO_READ_VAL_TEMPLATE, read_fptr): Include the new arg for do_read\n\tin decl.\n\t(octave_stream::read): Pass do_NA_conv to do_read.\n\n2008-07-29  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (FNA): Add tests for conversion of single to double NA\n\tvalues.\n\n\t* ov-flt-re-mat.cc (Fsingle): Documentation fix.\n\n2008-07-28  David Bateman  <dbateman@free.fr>\n\n\t* error.cc (last_error_id, last_error_message, last_warning_id,\n\tlast_warning_message): New functions to return the error/warning\n\tmessage and id without exposing the internal values.\n\t* error.h  (last_error_id, last_error_message, last_warning_id,\n\tlast_warning_message): Declare them.\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Use them to pass the error\n\tto the ErrorHandler function.\n\n2008-07-28  John W. Eaton  <jwe@octave.org>\n\n\t* error.cc (Flasterror, Flasterr): Unwind-protect error_state.\n\n\t* DLD-FUNCTIONS/__magick_read__.cc (F__magick_write__, write_image):\n\tNew functions.\n\n2008-07-25  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/det.cc (Fdet): Return calculated determinant for\n\tnumerically singular matrices, not 0.\n\n\t* symtab.cc (get_dispatch_type): New function.\n\t(symbol_table::fcn_info::fcn_info_rep::find): Use it.\n\n\t* ov-class.cc (set_class_relationship): Delete static function.\n\t(Fsuperiorto, Finferiorto): Warn about precedence conflicts.\n\tCall symbol_table::set_class_relationship instead of local static\n\tfunction.\n\t* symtab.h (symbol_table::class_precedence_table): New data member.\n\t(symbol_table::set_class_relationship, symbol_table::is_superiorto):\n\tNew static functions.\n\n2008-07-24  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.h (load_path::dir_info::class_info): New struct.\n\t(load_path::dir_info::method_file_map_type): Now a map from\n\tclass name to a to a class_info object.  Change all uses.\n\t* load-path.cc (load_path::dir_info::get_method_file_map):\n\tAlso look for private functions in the class directory.\n\t(load_path::add_to_method_map): Also add private functions from\n\tclass directories to private_fcn_map.\n\n\t* dirfns.cc (Fmkdir): If directory already exists, return status =\n\ttrue, but also set error message.\n\n2008-07-23  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr_fcn.cc (octave_user_function::do_multi_index_op):\n\tDon't unwind_protect and set curr_parent_function here.\n\t* toplev.cc (curr_parent_function): Delete definition.\n\t* toplev.h: (curr_parent_function): Delete declaration.\n\n\t* ov-usr-fcn.h (octave_user_function::parent_scope): New data member.\n\t(octave_user_function::parent_fcn_scope,\n\toctave_user_function::stash_parent_fcn_scope): New functions.\n\t* ov-usr_fcn.cc (octave_user_function::octave_user_function):\n\tInitialize parent_scope.\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::find):\n\tCheck parent of current function by looking at call stack, not\n\tglobal curr_parent_function variable.\n\t* parse.y (frob_function): If parsing nested function, stash\n\tcurrent parent function scope.\n\t* ov-fcn.h (octave_function::parent_fcn_scope): New virtual function.\n\n2008-07-22  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.cc (F__go_execute_callback__): New function.\n\n\t* DLD-FUNCTIONS/fltk_backend.cc: Undefine min/max after FLTK headers\n\tinclusion.\n\n\t* graphics.h.in (class base_graphics_event, class graphics_event): New\n\tclasses (replace gh_manager::event_data).\n\t(class gh_manager::event_data): Remove.\n\t(gh_manager::post_function, gh_manager::do_post_function): Use\n\tgraphics_event::event_fcn type.\n\t(gh_manager::event_queue, gh_manager::do_post_event): Use\n\tgraphics_event type.\n\t* graphics.cc (class callback_event, class function_event, class\n\tset_event): Renamed from xxx_data classes.\n\t(graphics_event::create_callback_event,\n\tgraphics_event::create_function_event,\n\tgraphics_event::create_set_event): Renamed from gh_manager::xxx\n\tequivalent methods, removed reference count increment.\n\t(gh_manager::do_post_event): Likewise.\n\t(gh_manager::do_post_event): Use graphics_event type.\n\t(gh_manager::do_post_function): Use graphics_event::event_fcn type.\n\n2008-07-22  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.51+.\n\n2008-07-21  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.51.\n\t(OCTAVE_RELEASE_DATE): Now 2008-07-21.\n\n\t* ov-class.cc (octave_class::subsasgn): Only do internal magic if\n\trhs is not an octave_class object.\n\n\t* OPERATORS/op-struct.cc: Define concatenation operators for\n\tstruct/matrix concatenation (valid if matrix is empty).\n\t* OPERATORS/op-cell.cc (install_cell_ops): Likewise, for cells.\n\n\t* DLD-FUNCTIONS/fltk_backend.cc: Don't include oct.h.\n\tMake compilation of entire file conditional on HAVE_FLTK.\n\n\t* gl-render.cc: Make compilation of entire file conditional on\n\tHAVE_OPENGL.\n\n\t* Makefile.in (GL_RENDER_SRC, FLTK_BACKEND_SRC): Delete variables.\n\t(DLD_XSRC): Always include fltk_backend.cc in the list.\n\t(DIST_SRC): Always include gl-render.cc in the list.\n\n2008-07-19  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.50+.\n\t(OCTAVE_API_VERSION): Now api-v33+.\n\n2008-07-18  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 3.1.50.\n\t(OCTAVE_API_VERSION): Now api-v33.\n\t(OCTAVE_RELEASE_DATE): Now 2008-07-18.\n\t(OCTAVE_COPYRIGHT): Update date to 2008.\n\n2008-07-18  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (__magick_read__.df): New rule.\n\tAppend MAGICK_INCFLAGS to CPPFLAGS.\n\n\t* Makefile.in (EXTRAS): Add graphics-props.cc to the list.\n\tList graphics-props.cc as a target generated by genprops.awk.\n\n2008-07-18 Carlo de Falco  <carlo.defalco@gmail.com>\n\n\t* gl-render.h: Conditionally include GL/gl.h or OpenGL/gl.h\n\tand GL/glu.h or OpenGL/glu.h\n\n2008-07-17  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (out_of_date_check_internal): New arg, dispatch_type.\n\tUse it to handle class methods.\n\n\t* toplev.h (octave_call_stack::do_caller): New function.\n\t(octave_call_stack::caller): Use it.\n\n2008-07-17  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* Makefile.in (convhulln.oct, __delaunayn__.oct, __voronoi__.oct,\n\tregexp.oct, urlwrite.oct, __glpk__.oct, fltk_backend.oct):\n\tUse OCT_LINK_DEPS instead of DL_LDFLAGS for target-specific\n\tdependencies.\n\n2008-07-17  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTION/__magick_read__.cc (F__magick_read__): Allow build\n\twithout GraphicsMagick++ installed.\n\n2008-07-16  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (gh_manager::autolock): Delete copy constructor\n\tand assignment definitions.\n\n2008-07-16  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (callback_property::execute): Remove static version.\n\t(base_properties::is_hittest, base_properties::is_interruptible,\n\tbase_properties::is_selected, base_properties::is_selectionhighlight):\n\tNew convenience property accessors.\n\t(base_graphics_object::get_handle, graphics_object::get_handle): Idem.\n\t(gh_manager::graphics_lock): New global mutex\n\t(gh_manager::lock, gh_manager::unlock, gh_manager::do_lock,\n\tgh_manager::do_unlock): Add accessors for it.\n\t(gh_manager::autolock): New class for easy locking of the graphics\n\tsystem.\n\t(gh_manager::event_data): New class for event management.\n\t(gh_manager::event_queue): New object to hold pending events.\n\t(gh_manager::callback_objects): New stack of callback objects.\n\t(gh_manager::execute_callback, gh_manager:post_callback,\n\tgh_manager::post_function, gh_manager::post_set,\n\tgh_manager::process_events, gh_manager::flush_events,\n\tgh_manager::restore_gcbo): New static methods for event management.\n\t(gh_manager::do_execute_callback, gh_manager::do_post_callback,\n\tgh_manager::do_post_function, gh_manager::do_post_set,\n\tgh_manager::do_process_events, gh_manager::do_post_event,\n\tgh_manager::do_restore_gcbo): New non-static versions.\n\t* graphics.cc (xreset_gcbo): Remove.\n\t(execute_callback): Likewise.\n\t(base_property::run_listeners, callback_property::execute): Use\n\tgh_manager::execute_callback.\n\t(class callback_event_data, class function_event_data, class\n\tset_event_data): New classes to implement various types of events.\n\t(gh_manager::event_data::create_callback_event,\n\tgh_manager::event_data::create_function_event,\n\tgh_manager::event_data::create_set_event): Implement event factory\n\tmethods.\n\t(gh_manager::do_restore_gcbo, gh_manager::do_execute_callback,\n\tgh_manager::do_post_event, gh_manager::do_post_callback,\n\tgh_manager::do_post_function, gh_manager::do_post_set,\n\tgh_manager::do_process_events): New methods for event management.\n\t(Fishandle, Fset, Fget, F__get__, F__go_figure__, F__go_delete__,\n\tF__go_axes_init__, F__go_handles__, F__go_figure_handles__,\n\tFavailable_backends, Fdrawnow, Faddlistener, Faddproperty,\n\tget_property_from_handle, set_property_in_handle): Lock graphics\n\tsystem.\n\t(GO_BODY): Likewise.\n\t(Fdrawnow): Support single \"expose\" argument.\n\n2008-07-15  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__convn__.cc (convn): Cast second arg to\n\toctave_idx_type in call to std::max.\n\n2008-07-14  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (convhulln.oct, __delaunayn__.oct, __voronoi__.oct,\n\tregexp.oct, urlwrite.oct, __glpk__.oct, fltk_backend.oct):\n\tSimplify with target-specific settings for DL_LDFLAGS.\n\n\t* DLD-FUNCTIONS/__magick_read__.cc: Delete \"using namespace std\"\n\tand \"using namespace Magick\" directives.  Style fixes.\n\n\t* oct-conf.h.in (OCTAVE_CONF_MAGICK_INCFLAGS,\n\tOCTAVE_CONF_MAGICK_LIBS): Substitute here.\n\t* toplev.cc (octave_config_info): Include MAGICK_INCFLAGS and\n\tMAGICK_LIBS in the struct.\n\t* Makefile.in (DLD_XSRC): Add __magick_read__.cc to the list.\n\t(OCTAVE_LIBS): Add $(MAGICK_LIBS) to the list for static linking case.\n\t(__magick_read__.d, __magick_read__.o, pic/__magick_read__.o):\n\tAppend MAGICK_INCFLAGS to CPPFLAGS.\n\t(__magick_read__.oct): Append MAGICK_LIBS to LDFLAGS.\n\n2008-07-14  Thomas L. Scofield  <scofield@calvin.edu>\n\n\t* DLD-FUNCTIONS/__magick_read__.cc: New file from Octave Forge.\n\n2008-07-11  John W. Eaton  <jwe@octave.org>\n\n\t* syscalls.cc (const_value): Delete arg NM.  Change all uses.\n\n\t* DLD-FUNCTIONS/fft.cc (do_fft): Avoid GCC warning.\n\t* DLD-FUNCTIONS/fft2.cc (do_fft2): Likewise.\n\t* DLD-FUNCTIONS/fftn.cc (do_fftn): Likewise.\n\t* DLD-FUNCTIONS/qr.cc (Fqrshift): Likewise.\n\t* DLD-FUNCTIONS/lookup.cc (Flookup): Likewise.\n\t* gl-render.cc (opengl_renderer::draw): Likewise.\n\t* graphics.cc (axes::update_axis_limits,\n\thggroup::update_axis_limits, Favailable_backends):\n\tLikewise.\n\t* pt-cmd.cc (tree_no_op_command::dup, tree_function_def::dup):\n\tLikewise.\n\t* pt-const.cc (tree_constant::dup): Likewise.\n\t* pt-id.cc (tree_identifier::dup): Likewise.\n\t* pt-jump.cc (tree_break_command::dup, tree_continue_command::dup,\n\ttree_return_command::dup): Likewise.\n\n\t* DLD-FUNCTIONS/colamd.cc: Style fixes.\n\t(tree_postorder): Rename from TreePostorder.\n\t(tree_postorder, coletree): Avoid GCC warnings.\n\n\t* DLD-FUNCTIONS/chol.cc (Fchol): Avoid GCC warnings.\n\t(Fcholdelete, Fcholshift): Delete unused arg nargout.\n\n\t* toplev.cc, toplev.h (octave_call_stack::caller_user_function,\n\toctave_call_stack::caller_user_script,\n\toctave_call_stack::do_caller_user_function,\n\toctave_call_stack::do_caller_user_script):\n\tDelete functions and decls.\n\n\t* defun.cc (print_usage): Call octave_call_stack::caller_user_code,\n\tnot octave_call_stack::caller_user_function.\n\t* debug.cc (get_user_code): Likewise.\n\n\t* toplev.h (octave_call_stack::difference_type): Delete typedef.\n\t* toplev.cc, toplev.h (octave_call_stack::caller_user_code_line,\n\toctave_call_stack::do_caller_user_code_line,\n\toctave_call_stack::caller_user_code_column,\n\toctave_call_stack::do_caller_user_code_column,\n\toctave_call_stack::caller_script,\n\toctave_call_stack::do_caller_script,\n\toctave_call_stack::caller_user_function,\n\toctave_call_stack::do_caller_user_function,\n\toctave_call_stack::caller_user_code,\n\toctave_call_stack::do_caller_user_code):\n\tDelete unused difference_type arg.\n\n\t* ov-float.h, ov-flt-re-mat.cc, ov-range.h, ov-re-mat.h,\n\tov-re-sparse.cc, ov-scalar.h: Check for NaN in bool_value and\n\tbool_array_value member functions to bool.\n\n\t* ops.h (DEFSCALARBOOLOP_OP): New macro.\n\t* OPERATORS/op-s-s.cc, OPERATORS/op-fs-fs.cc: Use it to define\n\tel_and and el_or ops.\n\n2008-07-10  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/lookup.cc (assign): Delete.\n\t(Flookup): Use new NDArray constructors rather than assign.\n\t* data.cc (Fsort): Use new NDArray constructors rather than\n\tdirectly assigning.\n\t* besselj.cc (int_array2_to_matrix, int_arrayn_to_array,\n\tint_array2_to_float_matrix, int_arrayn_to_float_array): Delete.\n\t(do-bessel): Use new NDArray constructors.\n\t* max.cc (MINMAX_SPARSE_BODY, MINMAX_INT_BODY, MINMAX_SINGLE_BODY,\n\tMINMAX_DOUBLE_BODY): Use new NDArray constructors.\n\t* ov-bool.h (array_value, float_array_value): Explictly cast\n\tboolean scalar to double before the assignment to avoid ambiguity.\n\n2008-07-10  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat4.cc (read_mat_binary_data, save_mat_binary_data): Add\n\tloading and saving of sparse matrices.\n\n2008-07-10  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Makefile.in: Add OPENGL_LIBS to liboctinterp link command. Add\n\tGRAPHICS_CFLAGS to fltk_backend.cc compilation command.\n\t* data.cc: Define hypotf to _hypotf when not present.\n\t* gl-render.h: Replace OCTGRAPHICS_API with OCTINTERP_API.\n\t* gl-render.cc: Get rid of Array2<vertex_data>.\n\t* OPERATORS/op-int.h: Use powf instead of pow when invoked\n\twith float arguments.\n\n2008-07-09  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (get_debug_input): Don't delete global_command here.\n\t* toplev.cc (main_loop): Undo previous change.\n\n\t* toplev.h (octave_call_stack::instance_ok): Push top scope when\n\tcreating instance.\n\n\t* DLD-FUNCTIONS/inv.cc (Finv): Avoid GCC warning.\n\n\t* DLD-FUNCTIONS/expm.cc (Fexpm): Avoid GCC warning.\n\n\t* ov-fcn-inline.cc (octave_fcn_inline::load_ascii): Avoid GCC warning.\n\n2008-07-09  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* gl-render.cc (opengl_renderer::draw(figure)): Enable line smoothing\n\taccording to __enhanced__ property.\n\t(opengl_renderer::draw_marker): Only draw markers with valid call\n\tlists ID.\n\t(opengl_renderer::make_marker_list): Do not produce filled marker call\n\tlist for non-fillable markers.\n\t(opengl_renderer::draw(axes)): Do not antialias axes system.\n\n\t* gl-render.cc (opengl_renderer::set_polygon_offset): Also enable\n\tpolygon offseting in GL_LINE mode.\n\t(opengl_renderer::draw_marker): Offset markers foward instead of\n\tbackward (to draw them above lines).\n\n\t* Makefile.in: new substituted variables GL_RENDER_SRC and\n\tFLTK_BACKEND_SRC.\n\n\t* gl-render.cc (vertex_data::vertex_data_rep::vertex_data(void),\n\tvertex_data::vertex_data(void), vertex_data::vertex_data(...)):\n\tinitialize reference counting correctly.\n\n2008-07-09  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (main_loop): Unwind-protect global_command.\n\t* input.cc (get_debug_input): Likewise.\n\n2008-07-09  David Bateman  <dbateman@free.fr>\n\n\t* pt-id.cc (octave_value_list tree_identifier::rvalue (int),\n\toctave_lvalue tree_identifier::lvalue (void)): Remove\n\tMAYBE_DO_BREAKPOINT.\n\n2008-07-08  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (axes::properties::keypos): Declare as\n\tany_property instead of double_property.\n\n2008-06-28  John W. Eaton  <jwe@octave.org>\n\n\t* debug.cc (push_dummy_call_stack_elt): Delete.\n\t(Fdbstack): Don't push dummy stack elt.  Use nskip instead of\n\tnframes, and curr_frame instead of idx.  Pass curr_frame to\n\toctave_call_stack::backtrace.\n\n\t* ls-mat5.cc (read_mat5_binary_element): Explicitly pass 0 for\n\tcurrent_context in call to symbol_table::varref.\n\t* ov-fcn-handle.cc (octave_fcn_handle::load_ascii): Likewise.\n\tFix test.\n\n\t* mex.cc (mexGetVariable, mexPutVariable): Use octave_call_stack\n\tmethods to manipulate scope and context.\n\t* parse.y (source_file, Fassignin, Fevalin): Likewise.\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tCall octave_call_stack::push after call to symbol_table::push_scope.\n\tCall unwind_protect::add with octave_call_stack::unwind_pop\n\timmediately after call to octave_call_stack::push.\n\n\t* symtab.cc (symbol_table::xcurrent_caller_scope): Delete definition.\n\t* symtab.h (symbol_table::xcurrent_caller_scope): Delete decl.\n\tDelete all uses.\n\t(xcurrent_context_this_table): Delete.  Delete all uses.\n\t(symbol_table::current_caller_scope): Delete.\n\n\t* toplev.cc (octave_call_stack::do_num_user_code_frames):\n\tNew function.\n\t(octave_call_stack::do_backtrace): New arg, curr_user_frame.\n\tRename nframes arg to nskip.  Correctly handle curr_frame not at\n\tend of stack.\n\t(octave_call_stack::do_goto_frame_relative): Rename n arg to nskip.\n\tCorrectly handle curr_frame not at end of stack.\n\t(octave_call_stack::do_goto_caller_frame): New function.\n\t(octave_call_stack::do_goto_base_frame): New function.\n\t* toplev.h: Provide decls for new functions.\n\t(octave_call_stack::call_stack_elt::prev): New data member.\n\tInitialize it in constructor.\n\t(octave_call_stack::const_reverse_iterator,\n\toctave_call_stack::reverse_iterator): New typedefs.\n\t(octave_call_stack::symbol_table::scope_id current_scope,\n\toctave_call_stack::symbol_table::context_id current_context,\n\toctave_call_stack::num_user_code_frames,\n\toctave_call_stack::goto_caller_frame,\n\toctave_call_stack::goto_base_frame,\n\toctave_call_stack::do_num_user_code_frames,\n\toctave_call_stack::do_current_scope,\n\toctave_call_stack::do_current_context): New functions.\n\n\t(octave_call_stack::push): Default value for context arg is\n\tsymbol_table::current_context, not 0.\n\t(octave_call_stack::do_push): Save previous frame.  Always push\n\tnew frame on back of stack.  Call symbol_table::set_scope_and_context.\n\t(octave_call_stack::do_pop): Restore previous frame.  Always pop\n\tframe from back of stack.  Call symbol_table::set_scope_and_context.\n\n2008-06-26  John W. Eaton  <jwe@octave.org>\n\n\t* token.h: Omit \"class symbol_table::symbol_record\" decl;\n\n\t* lex.l (grab_block_comment): Use parens around || expression\n\twithin && expression.\n\n2008-06-23  John W. Eaton  <jwe@octave.org>\n\n\t* debug.cc (Fdbstack): Avoid shadowed variable warning.\n\n2008-06-23  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* genprops.awk (emit_source): Avoid gensub for portability.\n\t(BEGIN): Ditto.\n\n2008-06-20  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp_list): Make \"once\" an output\n\targument.\n\t(octregexp): Do not use cell arrays when \"once\" is requested.\n\n\t* ov.cc (make_vector_dims): New function.\n\t(vector_value, complex_vector_value, float_vector_value,\n\tfloat_complex_vector_value): Query N-d array values and simplify,\n\tavoid copying.\n\t(column_vector_value, complex_column_vector_value,\n\tfloat_column_vector_value, float_complex_column_vector_value,\n\trow_vector_value, complex_row_vector_value,\n\tfloat_row_vector_value, float_complex_row_vector_value):\n\tSimplify to trivial wrappers.\n\t(int_vector_value): Avoid conversions if integer type, query N-d array\n\tvalue, simplify.\n\n2008-06-17  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.h, toplev.cc (class octave_call_stack):\n\tPush elements on and pop from back of queue.\n\t(octave_call_stack::do_push, octave_call_stack::do_pop):\n\tAlways adjust curr_frame.\n\t(octave_call_stack::size, octave_call_stack::do_size): New functions.\n\t* pt-stmt.cc (tree_statement::eval):\n\tAlso call octave_call_stack::set_statement when debugging.\n\t* debug.cc (push_dummy_call_stack_elt): New function.\n\t(Fdbstack): Omit dbstack from call stack by popping element rather\n\tthan adjusting frame number.  Correctly handle arg.\n\n2008-06-12  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/qr.cc (Fqrupdate, Fqrinsert, Fqrshift, Fqrdelete):\n\tAllow single precision arguments, add tests for single precision.\n\n2008-06-11  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base.cc (octave_base_value::streamoff_value,\n\toctave_base_value::streamoff_array_value): Delete.\n\t* ov-base.h: Delete decls.\n\t(octave_base_value::is_streamoff): Delete.\n\t* ov-float.cc (octave_float_scalar::streamoff_value,\n\toctave_float_scalar::streamoff_array_value): Delete.\n\t* ov-float.h: Delete decls.\n\t* ov-flt-re-mat.cc (octave_float_matrix::streamoff_array_value): Delete.\n\t* ov-flt-re-mat.h: Delete decl.\n\t* ov-re-mat.cc (octave_matrix::streamoff_array_value): Delete.\n\t* ov-re-mat.h: Delete decl.\n\t* ov-re-sparse.cc (octave_sparse_matrix::streamoff_array_value): Delete.\n\t* ov-re-sparse.h: Delete decl.\n\t* ov-scalar.cc (octave_scalar::streamoff_value,\n\toctave_scalar::streamoff_array_value): Delete.\n\t* ov-scalar.h: Delete decls.\n\t* ov.cc (octave_value::octave_value (const streamoff_array&),\n\toctave_value::octave_value (const ArrayN<std::streamoff>&),\n\toctave_value::streamoff_value (void) const,\n\toctave_value::streamoff_array_value (void) const): Delete.\n\t* ov.h: Delete decls.\n\t(octave_value::is_streamoff): Delete.\n\t* ov.cc (install_types): Don't register streamoff type.\n\t* ov-streamoff.h, ov-streamoff.cc, OPERATORS/op-streamoff.cc: Delete.\n\t* Makefile.in: Delete them from the lists.\n\n\t* error.cc (verror): Restore newline in msg_string.  Stripping\n\t\"error: \" prefix when buffering error messages is no longer neeed.\n\n2008-06-25  David Bateman  <dbateman@free.fr>\n\n\t* pr-output.cc (Frats): Print usage if nargin == 0.\n\n2008-06-10  John W. Eaton  <jwe@octave.org>\n\n\t* mexproto.h (mxCreateLogicalScalar): Declar arg as mxLogical, not int.\n\n2008-06-09  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (execute_callback): Pass CB by const reference and\n\texplicitly make a copy.\n\t(xget_ancestor): Pass GO by const reference and explicitly make a copy.\n\n\t* error.cc (verror): Omit \"name: \" and \"\\a\" from Vlast_error_msg.\n\tSave line and column information from user code.\n\t* toplev.cc (octave_call_stack::do_caller_user_code_line,\n\toctave_call_stack::do_caller_user_code_column): New functions.\n\t* toplev.h: Provide decls.\n\t(octave_call_stack::caller_user_code_line,\n\toctave_call_stack::caller_user_code_column): New functions.\n\t(octave_call_stack::current_line, octave_call_stack::current_column):\n\tDefault return value is -1, not 0.\n\n2008-06-06  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h (octave_value::erase_subfunctions):\n\tNew function.\n\t* ov-base.h (octave_base_value::erase_subfunctions):\n\tNew virtual function.\n\t* ov-usr-fcn.h (octave_user_function::erase_subfunctions):\n\tNew function.\n\t* symtab.h (symbol_table::fcn_info::::erase_subfunction,\n\tsymbol_table::fcn_info::fcn_info_rep::erase_subfunction,\n\tsymbol_table::erase_subfunctions_in_scope):\n\tNew functions.\n\t(symbol_table::fcn_info::fcn_info_rep::clear_user_function):\n\tErase subfunctions here.\n\n\t* variables.cc (Fmlock): Doc fix.\n\n2008-06-05  John W. Eaton  <jwe@octave.org>\n\n\t* gl-render.cc (opengl_renderer::draw): Correctly avoid shadow\n\twarnings from gcc for xmin, xmax, ymin, ymax, zmin, and zmax.\n\n\t* graphics/ChangeLog, graphics/Makefile.in, graphics/Makerules.in,\n\tgraphics/fltk_backend/Makefile.in, graphics/opengl/Makefile.in:\n\tDelete.\n\n\t* gl-render.cc, gl-render.h: Move here from graphics/opengl.\n\t* Makefile.in: Add them to the appropriate lists.\n\t(octave$(EXEEXT)): Also link with $(OPENGL_LIBS)\n\n\t* fltk_backend.cc: Move here from graphics/fltk_backend.\n\t* Makefile.in (DLD_XSRC): Add it to the list\n\t(fltk_backend.oct): Include special rules for linking with\n\t$(GRAPHICS_LIBS) and $(FT2_LIBS).\n\n\t* dynamic-ld.cc (octave_dynamic_loader::mex_mangler,\n\toctave_dynamic_loader::mex_uscore_mangler,\n\toctave_dynamic_loader::mex_f77_mangler): New functions.\n\t(octave_dynamic_loader::do_load_mex): Use them.\n\t(octave_dynamic_loader::do_remove_oct): Rename from\n\toctave_dynamic_loader::do_remove.\n\t(octave_dynamic_loader::do_remove_mex): New function.\n\t* dynamic-ld.h: Provide/fix decls.\n\n\t* graphics.cc (properties::update_normals): Style fixes.\n\t* graphics.h.in: Style fixes.\n\n\tChangeLog entries for gl-render.h, gl-render.cc, and\n\tfltk_backend.cc before the move:\n\n\t2008-06-05  John W. Eaton  <jwe@octave.org>\n\n\t* opengl/gl-render.cc (xmin): New static function.\n\n\t* opengl/gl-render.h (opengl_renderer): Style fixes.\n\t* fltk_backend/fltk_backend.cc: Style fixes.\n\n\t2008-04-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.h (opengl_renderer::draw(hggroup)): New method.\n\t* opengl/gl-render.cc (opengl_renderer::draw(hggroup)): Likewise.\n\t(opengl_renderer::draw(graphics_object)): Call it.\n\n\t2008-03-17  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* fltk_backend/fltk_backend.cc (plot_window::resize,\n\tplot_window::draw): make canvas the size of figure.position\n\n\t2008-03-09  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* fltk_backend/fltk_backend.cc (plot_window::handle): add zoom\n\tstack\n\n\t2008-03-06  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* fltk_backend/fltk_backend.cc (plot_window::handle): Add handling\n\tof the 'a' and 'g' keys\n\t(plot_window: toggle_grid): New helper function\n\t(plot_window): Add new togglegrid button\n\n\t2008-03-01  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* fltk_backend/fltk_backend.cc (OpenGL_fltk::draw_overlay,\n\tOpenGL_fltk::zoom, OpenGL_fltk::set_zoom_box): Added to support\n\tzoom box\n\t(plot_window::handle): Added zoom box code, B-3 now does autoscale\n\t(plot_window::axis_auto): New utility function to call axis(\"auto\")\n\t(plot_window::button_press): \"A\" button now does autoscale\n\n\t* opengl/gl-render.cc (make_marker_list): Add the \"+x*.^v><\"\n\tmarkers\n\n\t2008-02-27  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.cc (opengl_renderer::draw(patch),\n\topengl_renderer::draw(surface)): Adapt to type change of facealpha and\n\tedgealpha, using double_radio_property class.\n\n\t2008-02-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.h: Make sure windows.h is included before OpenGL\n\theaders.\n\t* fltk_backend/Makefile.in (FLTK_EXTRA_CXXFLAGS): Use $(srcdir) for\n\tincludesion of OpenGL renderer headers.\n\t(Makeconf): Move inclusion of Makeconf later on, to avoid freezing\n\tMinGW make.\n\n\t* fltk_backend/Makefile.in (GRAPHICS_CFLAGS): New substituted\n\tvariable.\n\n\t2008-02-25  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* fltk_backend/fltk_backend.cc (class plot_window): Many changes\n\tto use figure::properties instead of figure handle to reference\n\tthe figure\n\t(class figure_manager): ditto\n\t(__fltk_redraw__): moved most of functionality into the\n\tfigure_manager class\n\t(plot_window::pixel2pos): Modified to use axes::pixel2coord\n\t(plot_window::pixel2staus): Modified to use pixel2pos\n\t(plot_window::handle): Added zoom with mouse\n\n\t2008-02-24  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* fltk_backend/fltk_backend.cc (OpenGL_fltk::Draw): removed double\n\tbuffer switch\n\t(OpenGL_fltk::setup_viewport): removed call to glOrtho --\n\tgl-render takes care of all the transformations\n\n\t2008-02-23  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* fltk_backend/fltk_backend.cc (plot_window::mark_modifed): mark\n\tthe whole window as damaged (otherwise changing figure.postion\n\tdoes not have immediate effect)\n\t(plot_window::draw): New function, checks for window size\n\t(__fltk_maxtime__): New DEFUN to allow tweaking of fltk timeout\n\t(__fltk_redraw__): Use fltk_maxtime as timeout\n\n\t2008-02-21  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.cc (opengl_renderer::patch_tesselator::combine):\n\tProtect against NULL vertex data.\n\n\t* opengl/gl-render.cc (opengl_renderer::draw(patch)): Add marker\n\trendering of patch objects.\n\n\t2008-02-21  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* opengl/gl-render.cc: remove OpenGL includes\n\t* opengl/gl-render.h: add OpenGL includes\n\t* fltk_backend/fltk_backend.cc: remove OpenGL includes\n\t(__fltk_redraw__): put figure handle into the figure's\n\t__plot_stream__ property for later\n\t(fltk_backend::close_figure): use argument as figure handle to\n\tclose\n\n\t2008-02-20  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* fltk_backend/Makefile.in: initial import\n\n\t* fltk_backend/fltk_backend.cc: initial import\n\n\n\t2008-02-20  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.h (opengl_renderer::draw(patch)): New method to\n\trender patch objects.\n\t(class opengl_renderer::patch_tesselator): Forward declaration.\n\t* opengl/gl-render.cc (opengl_texture::create): Use RGB data format\n\tinstead of RGBA.\n\t(class opengl_tesselator): New classes to abstract GLU tessellation\n\tprocess.\n\t(class opengl_renderer::patch_tesselator): New class to render opaque\n\tpatch objects.\n\t(class vertex_data): New class to hold vertex data during tessellation\n\tof patch objects.\n\t(opengl_renderer::draw(patch)): New method to render patch objects (no\n\ttransparency, no border, no marker yet).\n\t(opengl_renderer::draw(graphics_object)): Dispatch to it.\n\n\t* opengl/gl-render.cc (opengl_renderer::draw(patch)): Use patch color\n\tdata and support face/vertex single color specification.\n\n\t* opengl/gl-render.cc (opengl_tesselator::begin_polygon): Set\n\ttessellation property also for non-filled polygons.\n\t(opengl_renderer::patch_tesselator::vertex): Protect against empty\n\tcolor matrices.\n\t(opengl_renderer::draw(patch)): Render patch border (no transparency\n\tyet).\n\n\t2008-02-19  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.cc (opengl_texture::texture_rep::tex_coord,\n\topengl_texture::tex_coord): New wrapper around glTexCoord2d.\n\t(opengl_renderer::draw(surface)): Use it for texturemap\n\timplementation.\n\t(opengl_renderer::draw(surface)): Fix indexing bug when creating clip\n\tmatrix.\n\t(opengl_texture::operator=): Add assignment operator.\n\t(opengl_texture::create): New static opengl_texture creator.\n\t(opengl_texture::is_valid): New accessor.\n\n\t2008-02-18  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.cc (class opengl_texture): New class to wrap\n\ttexture operations in OpenGL.\n\n\t2008-02-17  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.cc (opengl_renderer::draw(surface)): Set material\n\tcolor when rendering surface facets.\n\n\t* opengl/gl-render.cc (opengl_renderer::draw(surface)): Add rendering\n\tof mesh and markers.\n\n\t2008-02-16  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.cc (opengl_renderer::draw(figure)): Initialize the\n\tOpenGL context correctly.\n\t(opengl_renderer::draw(surface)): Add missing glEnd call.\n\n\t2008-02-14  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* opengl/gl-render.h opengl/gl-render.cc: Add rendering\n\tinterface for surface objects (actual implement still\n\tmissing).\n\n\t2008-02-14  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Makefile.in Makerules.in: Initial import\n\t* opengl/Makefile.in: Likewise.\n\t* opengl/gl-render.h opengl/gl-render.cc: Likewise.\n\n2008-06-04  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.cc (axes::properties::set_defaults): Preserve position\n\tif mode is replace.\n\t(axes::properties::sync_positions): Use default_axes_postion for\n\tconsistency.\n\n\t* graphics.h.in (axes::properties::sync_positions,\n\taxes::properties::update_position,\n\taxes::properties::update_outerposition): New functions to sync\n\touterposition and position.\n\n\t* graphics.h.in (axes::properties::update_xlim,\n\taxes::properties::update_ylim, axes::properties::update_zlim):\n\tpass is_logscale flag to axes::properties::calc_ticks_and_lims\n\t* graphics.cc (axes::properties::calc_ticks_and_lims): Added\n\tsupport for log scale\n\n\t* graphics.h.in (axes::properities::fix_limits) : New method.\n\t(axes::properties::update_xlim, axes::properties::update_ylim,\n\taxes::properties::update_zlim): Use fix_limits.\n\n\t* graphics.cc (axes::properties::calc_ticks_and_lims): Make sure\n\tthat lo <= hi.\n\n\t* graphics.h.in (axes::pixel2coord, axes::coord2pixel): New functions.\n\n\t* graphics.cc (convert_position): No longer static.\n\t* graphics.h.in: Provide decl.\n\n \t* graphics.cc (Favailable_backends): New function.\n  \t* graphics.h.in (base_graphics_backend::available_backends_list):\n\tNew function.\n\n\t* graphics.cc (axes::properties::calc_ticks_and_lims): Refactor.\n\tAdjust axes limits & tics together so that the result is consistent.\n\t(axes::properties::calc_tick_sep): Ditto.\n\t(axes::properties::get_axis_limits): Ditto.  Now a member of\n\taxes::properties\n\t(magform): Now file-scope static function instead of\n\taxes::properties member function.\n\n\t* graphics.h.in (axes::properties::update_xlim): call the new\n\taxes::properties::calc_ticks_and_lims method\n\t(axes::properties::update_ylim): ditto\n\t(axes::properties::update_zlim): ditto\n\n2008-06-04  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* ov-fcn-inline.h (class octave_fcn_inline): Mark with OCTINTERP_API.\n\t* ov-fcn-handle.h (class Octave_fcn_handle): Likewise.\n\t* ls-oct-binary.h (save_binary_data, read_binary_data): Likewise.\n\n\t* genprops.awk (emit_source): Fix if-then-else statement generation\n\twhen the first property is hidden.\n\t* graphics.h.in (base_properties::adopt): Call mark_modified.\n\t(class hggroup): New graphics object class.\n\t* graphics.cc (lookup_object_name, make_graphics_object_from_type,\n\tproperty_list::lookup, property_list::set,\n\troot_figure::init_factory_properties): Support hggroup as possible\n\tobject type.\n\t(hggroup::update_axis_limits): New graphics object class.\n\t(make_graphics_object): Look for \"parent\" property in the arguments\n\tand use it as actual parent for the created object.\n\t(F__go_hggroup__): New function.\n\t(F__go_delete__): Set Vdrawnow_requested to true.\n\n\t* graphics.h.in (base_property::clone, string_property::clone,\n\tradio_property::clone, color_property::clone, double_property::clone,\n\tdouble_radio_property::clone, array_property::clone,\n\trow_vector_property::clone, bool_property::clone,\n\thandle_property::clone, callback_property::clone, any_property::clone,\n\tproperty::clone): New virtual method.\n\t(property::create): New static method to create dynamic properties.\n\t(base_properties::has_property): New method to check the existence of\n\ta property.\n\t(any_property::any_property, row_vector_property::row_vector_property,\n\tdouble_radio_property::double_radio_property): New copy constructors.\n\t* graphics.cc (lookup_object_name): New static utility function.\n\t(make_graphics_object_from_type): Likewise.\n\t(gh_manager::do_make_graphics_handle): Use it.\n\t(dprop_obj_map): New static map used for chaching purpose in dynamic\n\tproperty creation.\n\t(property::create): New static method to create dynamic properties.\n\t(base_properties::has_property): New method to check the existence of\n\ta property.\n\t(base_properties::override_defaults): Check parent validity.\n\t(Faddlistener): Documentation fix.\n\t(Faddproperty): New function to create dynamic properties.\n\n\t* genprops.awk (emit_get_array): Don't produce get_xxx_property\n\taccessors.\n\t* graphics.h.in (array_property::get_limits): New method to return the\n\tarray limits.\n\t(base_properties::get_xdata_property,\n\tbase_properties::get_ydata_property,\n\tbase_properties::get_zdata_property,\n\tbase_properties::get_ldata_property,\n\tbase_properties::get_udata_property,\n\tbase_properties::get_xldata_property,\n\tbase_properties::get_xudata_property,\n\tbase_properties::get_cdata_property): Remove methods, replaced with\n\tlimit-based equivalent.\n\t(base_graphics_object::get_xdata_property,\n\tbase_graphics_object::get_ydata_property,\n\tbase_graphics_object::get_zdata_property,\n\tbase_graphics_object::get_ldata_property,\n\tbase_graphics_object::get_udata_property,\n\tbase_graphics_object::get_xldata_property,\n\tbase_graphics_object::get_xudata_property,\n\tbase_graphics_object::get_cdata_property): Likewise.\n\t(graphics_object::get_xdata_property,\n\tgraphics_object::get_ydata_property,\n\tgraphics_object::get_zdata_property,\n\tgraphics_object::get_ldata_property,\n\tgraphics_object::get_udata_property,\n\tgraphics_object::get_xldata_property,\n\tgraphics_object::get_xudata_property,\n\tgraphics_object::get_cdata_property): Likewise.\n\t(base_properties::get_xlim, base_properties::get_ylim,\n\tbase_properties::get_zlim, base_properties::get_clim,\n\tbase_properties::get_alim, base_properties::is_xliminclude,\n\tbase_properties::is_yliminclude, base_properties::is_zliminclude,\n\tbase_properties::is_climinclude, base_properties::is_aliminclude):\n\tNew methods.\n\t(base_graphics_object::get_xlim, base_graphics_object::get_ylim,\n\tbase_graphics_object::get_zlim, base_graphics_object::get_clim,\n\tbase_graphics_object::get_alim, base_graphics_object::is_xliminclude,\n\tbase_graphics_object::is_yliminclude,\n\tbase_graphics_object::is_zliminclude,\n\tbase_graphics_object::is_climinclude,\n\tbase_graphics_object::is_aliminclude): Likewise.\n\t(graphics_object::get_xlim, graphics_object::get_ylim,\n\tgraphics_object::get_zlim, graphics_object::get_clim,\n\tgraphics_object::get_alim, graphics_object::is_xliminclude,\n\tgraphics_object::is_yliminclude, graphics_object::is_zliminclude,\n\tgraphics_object::is_climinclude, graphics_object::is_aliminclude):\n\tLikewise.\n\t(base_graphics_object::update_axis_limits): Provide default behavior\n\tby passing the call to the parent object.\n\t(line::properties::xdata, line::properties::ydata,\n\tline::properties::zdata, line::properties::ldata,\n\tline::properties::udata, line::properties::xldata,\n\tline::properties::xudata): Replace 'l' modifier with 'u'.\n\t(line::properties::xlim, line::properties::ylim,\n\tline::properties::zlim, line::properties::xliminclude,\n\tline::properties::yliminclude, line::properties::zliminclude): New\n\thidden properties.\n\t(line::properties::update_xdata, line::properties::update_ydata,\n\tline::properties::update_zdata, line::properties::update_xldata,\n\tline::properties::update_xudata, line::properties::update_ldata,\n\tline::properties::update_udata): New updaters that update limit\n\tproperties.\n\t(line::properties::compute_xlim, line::properties::compute_ylim): New\n\tmethod to compute actual limits taking into account x/y data and\n\tupper/lower bounds.\n\t(text::properties::position): Add 'u' modifier.\n\t(text::properties::xlim, text::properties::ylim,\n\ttext::properties::zlim, text::properties::xliminclude,\n\ttext::properties::yliminclude, text::properties::zliminclude): New\n\thidden properties.\n\t(text::properties::update_position): New updater that updates limit\n\tproperties.\n\t(image::properties::xdata, image::properties::ydata,\n\timage::properties::cdata): Replace 'l' modifier with 'u'.\n\t(image::properties::cdatamapping): Add 'l' modifier.\n\t(image::properties::xlim, image::properties::ylim,\n\timage::properties::clim, image::properties::xliminclude,\n\timage::properties::yliminclude, image::properties::climinclude): New\n\thidden properties.\n\t(image::properties::get_climinclude,\n\timage::properties::is_climinclude): Provide specialized inline\n\taccessors.\n\t(image::properties::update_xdata, image::properties::update_ydata,\n\timage::properties::update_cdata): New updaters that update limit\n\tproperties.\n\t(patch::properties::xdata, patch::properties::ydata,\n\tpatch::properties::zdata, patch::properties::cdata): Replace 'l'\n\tmodifier with 'u'.\n\t(patch::properties::cdatamapping): Add 'l' modifier.\n\t(patch::properties::alphadatamapping): New property.\n\t(patch::properties::xlim, patch::properties::ylim,\n\tpatch::properties::zlim, patch::properties::clim,\n\tpatch::properties::alim, patch::properties::xliminclude,\n\tpatch::properties::yliminclude, patch::properties::zliminclude,\n\tpatch::properties::climinclude, patch::properties::aliminclude: New\n\thidden properties.\n\t(patch::properties::get_climinclude,\n\tpatch::properties::is_climinclude, patch::properties::get_aliminclude,\n\tpatch::properties::is_aliminclude): Provide specialized inline\n\taccessors.\n\t(patch::properties::update_xdata, patch::properties::update_ydata,\n\tpatch::properties::update_zdata, patch::properties::update_cdata): New\n\tupdaters that update limit properties.\n\t(surface::properties::xdata, surface::properties::ydata,\n\tsurface::properties::zdata, surface::properties::cdata,\n\tsurface::properties::alphadata): Replace 'l' modifier with 'u'.\n\t(surface::properties::cdatamapping,\n\tsurface::properties::alphadatamapping): Add 'l' modifier.\n\t(surface::properties::xlim, surface::properties::ylim,\n\tsurface::properties::zlim, surface::properties::clim,\n\tsurface::properties::alim, surface::properties::xliminclude,\n\tsurface::properties::yliminclude, surface::properties::zliminclude,\n\tsurface::properties::climinclude, surface::properties::aliminclude: New\n\thidden properties.\n\t(surface::properties::get_climinclude,\n\tsurface::properties::is_climinclude,\n\tsurface::properties::get_aliminclude,\n\tsurface::properties::is_aliminclude): Provide specialized inline\n\taccessors.\n\t(surface::properties::update_xdata, surface::properties::update_ydata,\n\tsurface::properties::update_zdata): Update limit properties.\n\t(surface::properties::update_cdata,\n\tsurface::properties::update_alphadata): New updaters that update limit\n\tproperties.\n\t* graphics.cc (base_properties::update_axis_limits): Simply call\n\tupdate_axis_limits in owning graphics_object.\n\t(base_graphics_object::update_axis_limits): Provide default behavior\n\tby passing the call to the parent object.\n\t(check_limits_vals(double&,double&,double&,const octave_value&)): New\n\tstatic method to work with new limit properties in graphics objects.\n\t(get_children_limits): New static method to compute the raw limits of\n\ta set of children, based on the new limit properties.\n\t(axes::update_axis_limits): Simplify and call get_children_limits. Add\n\thandling of alpha limits.\n\t(line::properties::compute_xlim, line::properties::compute_ylim): New\n\tmethods to compute line limits taking into account upper/lower bounds.\n\n\t* graphics.cc (axes::properties::sync_positions): Update\n\ttransformation data.\n\n\t* graphics.cc (Faddlistener): Rename from Fadd_listener.\n\n\t* graphics.h.in (axes::properties::pixel2coord): Center Z coordinate\n\ton x_zlim instead of 0.\n\t(axes::properties::zoom, axes::properties::unzoom,\n\taxes::properties::clear_zoom_stack): New methods to handle zoom stack.\n\t(axes::properties::zoom_stack): New field to hold zoom stack.\n\t(axes::properties::update_xlim, axes::properites::update_ylim):\n\tAdditional do_clr_zoom argument to control whether the zoom stack will\n\tbe cleared.\n\t(axes::properties::update_zlim): Clear zoom stack.\n\t* graphics.cc (axes::properties::zoom, axes::properties::unzoom,\n\taxes::properties::clear_zoom_stack): New methods to handle zoom stack.\n\n\t* genprops.awk (emit_source): Use all properties in factory defaults.\n\n\t* graphics.h.in (base_property::base_property): Set internal counter\n\tto 1 by default.\n\t(property::property): Adapt constructors to default counter value in\n\tbase_property.\n\n\t* graphics.h.in (base_properties::get_property): Make virtual and\n\tremove const modifier.\n\t* graphics.cc (base_properties::get_property): Can return built-in\n\tproperties. Generate an error if the property does not exist.\n\t(base_properties::add_listener): Use get_property.\n\t(Fadd_listener): Add documentation.\n\t* genprops.awk (emit_common_declarations, emit_source): Emit code for\n\toverloaded get_property method.\n\n\t* genprops.awk (emit_declarations): Run listeners in the property\n\tsetter methods.\n\t* graphics.h.in (enum listener_mode): New enum type for listeners.\n\t(base_property::set): Make non-virtual and handle listeners execution.\n\t(base_property::listeners): New field holding a map of listeners.\n\t(base_property::add_listener, base_property::run_listeners,\n\tbase_property::do_set): New methods to handle listeners.\n\t(property::add_listener, property::run_listeners): Likewise.\n\t(base_properties::add_listener): Likewise.\n\t(base_graphics_object::add_property_listener,\n\tgraphics_object::add_property_listener): Likewise.\n\t(all property classes): Rename set to do_set and make it protected.\n\t* graphics.cc (base_property::run_listeners): New method to execute\n\tlisteners.\n\t(color_property::set, double_radio_property::set,\n\thandle_property::set): Rename to do_set.\n\t(base_properties::add_listener): New method to handle listener\n\tadditio. Only handle dynamic properties.\n\t(Fadd_listener): New octave interface to add property listeners to\n\tgraphics object.\n\n\t* genprops.awk (emit_get_data): Remove.\n\t(emit_declarations): Treat row_vector_property as array_property and\n\tremove data_property references.\n\t* graphics.h.in (array_property::array_property(array_property)): Add\n\tcopy constructor.\n\t(class data_property): Remove (replaced by array_property).\n\t(class base_graphics_backend, class graphics_backend): Replace\n\tdata_property references with array_property.\n\t(line::properties::xdata, line::properties::ydata,\n\tline::properties::zdata, line::properties::ldata,\n\tline::properties::udata, line::properties::xldata,\n\tline::properties::xudata): Turn into row_vector_property.\n\t(image::properties::xdata, image::properties::ydata): Likewise.\n\t(image::properties::init): Add length constraints for xdata and ydata.\n\t(patch::properties::xdata, patch::properties::ydata,\n\tpatch::properties::zdata, patch::properties::facevertexalphadata):\n\tTurn into array_property.\n\t(surface::properties::xdata, surface::properties::ydata,\n\tsurface::properties::zdata): Likewise.\n\t(patch::properties::init): Add size constraints for xdata, ydata,\n\tzdata and facevertexalphadata.\n\t(surface::properties::init): Add size constraints for xdata, ydata and\n\tzdata.\n\t* graphics.cc (check_limit_vals): Remove override with data_property.\n\t(axes::update_axis_limits): Replace data_property references with\n\tarray_property.\n\n\t* graphics.h.in (root_figure::get_default): Use factory defaults when\n\tno explicit default value exists.\n\t(figure::properties::set___backend__): Reset __plot_stream__ to empty\n\tvalue.\n\t* graphics.cc (gh_manager::gh_manager): Call\n\tgraphics_backend::default_backend to make sure the default backend is\n\tinitialized.\n\n\t* graphics.h.in (patch::properties::edgealpha,\n\tsurface::properties::facealpha, surface::properties::edgealpha): Fix\n\ttypos in property names.\n\n\t* graphics.h.in (class double_radio_property): New property class for\n\tholding face/edge alpha values.\n\t(patch::properties::facealpha, patch::properties::edgealpha,\n\tsurface::properties::facealpha, surface::properties::edgealpha): Use\n\tdouble_radio_property class.\n\t* graphics.cc (double_radio_property::set): Implement new property\n\tclass.\n\t* genprops.awk (emit_get_double_radio): New function to emit code for\n\tdouble_radio_property.\n\t(emit_declarations): Use it.\n\n\t* graphics.h.in (array_property::array_property(void)): New default\n\tconstructor.\n\t(array_property::xmin, array_property:xmax, array_property::xminp,\n\tarray_property::min_val, array_property::max_val,\n\tarray_property::min_pos): New fields and accessors to hold min/max\n\tvalues of the array data.\n\t(array_property::get_data_limits): New method to compute min/max\n\tvalues of the array data.\n\t(base_properties::get_cdata_property,\n\tgraphics_object::get_cdata_property): Return array_property.\n\t(image::properties::cdata, surface::properties::cdata,\n\tpatch::properties::cdata, patch::properties::facevertexcdata): Turn\n\tinto array_property type.\n\t(image::properties::init, surface::properties::init,\n\tpatch::properties::init): Add constraint initialization for cdata and\n\tfacevertexcdata (patch only).\n\t* genprops.awk (emit_get_array): New function to emit accessor for\n\tarray_property.\n\t(emit_declarations): Use it.\n\t* graphics.cc (get_array_limits): New template function to compute\n\tmin/max values of an Array<T> object.\n\t(array_property::get_data_limits): New method to compute min/max\n\tvalues of the array data, using get_array_limits.\n\t(check_limit_vals): Overridden function with array_property.\n\t(axes::update_axis_limits): Turn cdata property into array_property.\n\n\t* graphics.h.in (patch::properties::get_color_data): New utility\n\tfunction to retrieve actual color data.\n\t* graphics.cc (patch::properties::get_color_data): Likewise.\n\n\t* graphics.h.in (base_scaler::is_linear, lin_scaler::is_linear,\n\tscaler::is_linear): New method to detect linear scales.\n\t(graphics_xform::scale(Matrix)): New method to scale 2D/3D coordinates\n\tdirectly.\n\t(patch::properties::facelighting): Set default value to \"none\".\n\n\t* graphics.h.in (axes::axes): Be sure to initialize transformation\n\tdata correctly.\n\n\t* graphics.cc (xget_ancestor): Pass graphics_object argument by value\n\tinstead of by reference.\n\n\t* graphics.h.in (surface::properties::xdata,\n\tsurface::properties::ydata, surface::properties::zdata,\n\tsurface::properties::normalmode, surface::properties::vertexnormals):\n\tAdd 'u' modifier.\n\t(surface::properties::update_normals): New method to compute normals\n\tautomatically.\n\t(surface::properties::update_xdata, surface::properties::update_ydata,\n\tsurface::properties::update_zdata,\n\tsurface::properties::update_normalmode,\n\tsurface::properties::update_vertexnormals): New updaters to update\n\tnormals automatically.\n\t* graphics.cc (surface::properties::update_normals): Likewise.\n\t(cross_product): New inlined utility function for cross product\n\tcomputation adn accumulation.\n\n\t* graphics.h.in (class base_scaler, class lin_scaler, class\n\tlog_scaler, class scaler): Add scale method for NDArray.\n\t(log_scaler::do_scale): Factorize scaling code.\n\n\t* graphics.h.in (figure::properties::update_position): Re-remove.\n\t(figure::properties::facecolor): Re-add 'texturemap' value.\n\t(surface::properties::get_color_data): New method to compute actual\n\tsurface color data from cdata.\n\t* graphics.cc (surface::properties::get_color_data): Likewise.\n\t(xget_ancestor): New utility function to retrieve an ancestor of a\n\tgiven type.\n\t(convert_cdata): New utility function to convert cdata property into\n\tactual color data.\n\n\t* graphics.h.in (surface::properties::facecolor): Add \"texturemap\"\n\tas possible value.\n\t(class surface::properties): New properties alphadata,\n\talphadatmapping, ambientstrength, backfacelighting, diffusestrength,\n\tedgealpha, edgelighting, erasemode, facelighting, meshstyle,\n\tnormalmode, specularcolorreflectance, specularexponent,\n\tspecularstrength, vertexnormals.\n\t(surface::properties::init): Add constraints for alphadata,\n\tvertexnormals and cdata (the latter are commented until cdata\n\thas changed type).\n\n\t* graphics.h.in (base_properties::update_boundingbox): New method\n\tto handle object resize.\n\t(figure::properties::set_boundingbox): New method to set figure\n\tposition from backend.\n\t(figure::properties::update_position): Remove method.\n\t(figure::properties::position): Remove 'u' modifier and add 'S'\n\tmodifier.\n\t(axes::properties::update_boundingbox): Overload to recompute\n\ttransformation when axes size changed.\n\t* graphics.cc (base_properties::update_boundingbox): New method.\n\t(figure::properties::set_boundingbox,\n\tfigure::properties::set_position): Likewise.\n\n\t* genprops.awk: Add 'U' modifier to support extern updaters.\n\t* graphics.h.in (base_graphics_backend::gripe_invalid): New method\n\tto simplify error reporting.\n\t(class base_graphics_backend): Use it.\n\t(base_graphics_backend::set_figure_position): New backend method.\n\t(graphics_backend::set_figure_position): Likewise.\n\t(figure::properties::position): Mark property with updater.\n\t(figure::properties::update_position): New updater.\n\n\t* graphics.h.in (root_figure::properties::callbackobject):\n\tNew root property.\n\t(root_figure::properties::cbo_stack): New field.\n\t* graphics.cc (xset_gcbo, xreset_gcbo): New utility functions.\n\t(execute_callback): Set callbackobject property in root object\n\tbefore executing a callback.\n\t(root_figure::properties::set_callbackobject): Implement accessor.\n\n\t* graphics.h.in (root_figure::properties::callbackobject):\n\tNew root property.\n\t(root_figure::properties::cbo_stack): New field.\n\t* graphics.cc (xset_gcbo, xreset_gcbo): New utility functions.\n\t(execute_callback): Set callbackobject property in root object\n\tbefore executing a callback.\n\t(root_figure::properties::set_callbackobject): Implement accessor.\n\n\t* graphics.h.in (class root_figure::properties,\n\tclass line::properties, class text::properties,\n\tclass image::properties, class patch::properties,\n\tclass surface::properties): Export classes with\n\tOCTINTERP_API.\n\n\t* graphics.cc (axes::properties::set_defaults): Use correct\n\tdefault values for gridlinestyle and minorgridlinestyle.\n\n2008-06-03  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* load-save.cc (Fload): Fix \"-7\" option.\n\n2008-06-02  David Bateman  <dbateman@free.fr>\n\n\t* pt.cc (tree:last_break_function): Next pointer to last function\n\twith a breakpoint.\n\t* pt.h (tree:last_break_function): ditto.\n\t* debug.cc (Fdbstep): Use tree::break_function value of zero to\n\tsignal to step into the next function. Set tree::last_break_function\n\tto indicate position of last breakpoint.\n\t(Fdbnext):  Set tree::last_break_function to indicate position of\n\tlast breakpoint.\n\t* pt-bp.h (MAYBE_DO_BREAKPOINT): Check tree::break_function value\n\tof zero as well. Only check tree::last_line if we are in teh same\n\tfunction as the last breakpoint.\n\t* input.cc (char Vfilemarker): New global variable.\n\t(Ffilemarker): New function to query and set Vfilemarker.\n\t* input.h (extern char Vfilemarker): Make Vfilemarker available.\n\t* util.cc (fcn_file_in_path): If the input argument contains\n\tVfilemarker, strip the trailing part of string from this point\n\twhen looking for function file.\n\t* toplev.cc (octave_call_stack::fo_backtrace): Mark subfunctions\n\twith the name of the parent function and Vfilemarker.\n\t* symtab.cc (symbol_table::find_function (const std::string&,\n\ttree_argument_list *, const string_vector&, octave_value_list*,\n\tbool&): If function name contains Vfilemarker, check in scope of\n\tspecified parent function.\n\n\t* DLD-FUNCTIONS/betainc.cc: Move test code here. Add test code for\n\tsingle precision type.\n\t* DLD-FUNCTIONS/gammainc.cc: Ditto.\n\t* DLD-FUNCTIONS/gcd.cc (Fgcd): Support single precision. Move test\n\tcode here. Add test code for single precision type.\n\t* data.cc: Move test code here and add tests for single precision\n\ttype. Add tests for Fislogical.\n\t(NATIVE_REDUCTION): Support the 'double' argument.\n\t* mapper.cc: Move test code here and add tests for single precision\n\ttype.\n\t* ov-float.cc (CD_SCALAR_MAPPER): Replace Complex with\n\tFloatComplex.\n\t(erf, erfc, abs, acos, asin, asinh, atan, atanh, ceil, cos, cosh,\n\texp, expm1, floor, log10, log1p, sin, sinh, sqrt, tan, tanh): Use\n\tfloat version of base functions (ie. ::sinf and not ::sin)\n\t(lgamma, acosh, log, log2, log10, log1p): Use single precision\n\tinfinity value.\n\t* ov-flt-complex.cc (erf, erfc, expm1, log1p): Use the float\n\tversion of base functions.\n\t* ov-flt-cx-mat.cc (DARRY_MAPPER): Replace NDArray with FloatNDArray.\n\t(erf, erdc, gamma): Use FloatNDArray::dmapper and not\n\tNDArray::dmapper.\n\t* ov-flt-cx-mat.h (is_double_type): Delete.\n\t(is_single_type): New method.\n\t* ov-flt-re-mat.cc (lgamma,  acosh, log, log2, log10, log1p,\n\tsqrt): Use single precision infinity value.\n\n\t* chol.cc (Fcholinv, Fchol2inv, Fcholupdate, Fcholinsert,\n\tFcholdelete, Fcholshift): Allow single precision arguments.\n\t(Fchol): Move test code here. Add test code for single precision.\n\t(Fcholupdate, Fcholinsert, Fcholdelete, Fcholshift): Add test code\n\tfor single precision.\n\t* conv2.cc (Fconv2): Add single precision test code.\n\t* det.cc (Fdet): For single values or empty matrices, return\n\tsingle precision arg for single precion input. Move test code\n\there. Add single precision test code.\n\t* fft.cc (do_fft): For empty single precision arguments return a\n\tsingle precision value. Add single precision test code. Remove\n\tfft2 test code.\n\t* fft2.cc (do_fft2): For empty single precision arguments return a\n\tsingle precision value. Add single precision test code. Move fft2\n\ttest code here.\n\t* fftn.cc (do_fftn): For empty single precision arguments return a\n\tsingle precision value.\n\t* eig.cc (Feig):  Move test code here. Add single precision test\n\tcode.\n\t* expm.cc (Fexpm): Ditto.\n\t* find.cc (Ffind): Ditto.\n\t* hess.cc (Fhess): Ditto.\n\t* inv.cc (Finc): Ditto.\n\t* lu.cc (Flu): Ditto.\n\t* qr.cc (Fqr): Ditto.\n\t* schur.cc (Fschur): Ditto.\n\t* svd.cc (Fsvd): Ditto.\n\t* syl.cc (Fsyl): Ditto.\n\n\t* op-fcm-fcm.cc, op-fcm-fcs.cc, op-fcm-fm.cc, op-fcm-fs.cc,\n\top-fcs-fcm.cc, op-fcs-fcs.cc, op-fcs-fm.cc, op-fcs-fs.cc,\n\top-fm-fcm.cc, op-fm-fcs.cc, op-fm-fm.cc, op-fm-fs.cc,\n\top-fs-fcm.cc, op-fs-fcs.cc, op-fs-fm.cc, op-fs-fs.cc: Add mixed\n\tdouble, single precision concatenation operators.\n\n\t* data.cc (Fall, Fany, Fdiag, Fcat, Fismatrix, Fones, Fzeros,\n\tFinf, FNaN, FNA, Feye, Flinspace, Freshape, Ftranspose,\n\tFctranspose, Fsort). Move tests here. Add single precision tests.\n\t* mappers.cc (Ffinite, Fisinf, Fisna, Fisnan): Ditto.\n\t* ov-float.cc (octave_float_scalar:resize): single precision\n\treturn value.\n\t* ov.cc (octave_value::octave_value (const\n\tFloatComplexDiagMatrix&)): Ditto.\n\t* data.cc (Fnorm): Add single precision.\n\t(do_cat): Disable fast return and skipping empty matrices, as they\n\tplay a part in determining the return type.\n\t* ov.cc (octave_value do_cat_op (const octave_value&, const\n\toctave_value&, const Array<octave_idx_type>&)): ditto.\n\n2008-06-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-cell.cc (Fcellstr): For compatibility with Matlab, return {''}\n\twhen given ''.\n\n2008-05-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/fsolve.cc (fsolve_user_function,\n\tfsolve_user_jacobian): Reshape argument to original dims before\n\tpassing.\n\t(Ffsolve): Save original dimensions of the starting guess and reshape\n\ton return. Fix tests.\n\n2008-05-21  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/quad.cc (quad_float_user_function): New function.\n\t(Fquad): Handle float type.\n\tNew tests.\n\n2008-05-21  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* OPERATORS/op-fcm-fcm.cc (trans_mul, mul_trans, herm_mul, mul_herm):\n\tNew functions.\n\t(install_fcm_fcm_ops): Install them.\n\t* OPERATORS/op-fm-fm.cc (trans_mul, mul_trans): New functions.\n\t(install_fm_fm_ops): Install them.\n\n\t* OPERATORS/op-sm-m.cc (trans_mul): New function.\n\t(install_sm_m_ops): Register it.\n\t* OPERATORS/op-m-sm.cc (mul_trans): New function.\n\t(install_m_sm_ops): Register it.\n\t* OPERATORS/op-scm-cm.cc (trans_mul, herm_mul): New function.\n\t(install_scm_cm_ops): Register it.\n\t* OPERATORS/op-cm-scm.cc (mul_trans, mul_herm): New function.\n\t(install_cm_scm_ops): Register it.\n\n\t* dMatrix.cc: Declare DSYRK.\n\t(xgemm): Call DSYRK if symmetric case detected.\n\t* CMatrix.cc: Declare ZSYRK, ZHERK.\n\t(xgemm): Call ZSYRK/ZHERK if symmetric/hermitian case detected.\n\n\t* ov.h (octave_value::compound_binary_op): New enum.\n\t(do_binary_op (octave_value::compound_binary_op, ...),\n\toctave_value::binary_op_fcn_name (compound_binary_op),\n\toctave_value::do_binary_op (compound_binary_op, ...)):\n\tNew declarations.\n\t(OV_COMP_BINOP_FN): New macro (+ several expansions).\n\t* ov.cc (octave_value::binary_op_fcn_name (compound_binary_op),\n\tdecompose_binary_op, do_binary_op (compound_binary_op, ...)):\n\tNew functions.\n\t* ov-typeinfo.h (octave_value_typeinfo::register_binary_class_op\n\t(octave_value::compound_binary_op, ...),\n\toctave_value_typeinfo::register_binary_op\n\t(octave_value::compound_binary_op, ...),\n\toctave_value_typeinfo::do_register_binary_class_op\n\t(octave_value::compound_binary_op, ...),\n\toctave_value_typeinfo::do_register_binary_op\n\t(octave_value::compound_binary_op, ...),\n\toctave_value_typeinfo::do_lookup_binary_class_op\n\t(octave_value::compound_binary_op),\n\toctave_value_typeinfo::do_lookup_binary_op\n\t(octave_value::compound_binary_op, ...)):\n\tNew declarations.\n\t(octave_value_typeinfo::lookup_binary_class_op\n\t(octave_value::compound_binary_op),\n\t(octave_value_typeinfo::lookup_binary_op\n\t(octave_value::compound_binary_op, ...)):\n\tNew functions.\n\t(octave_value_typeinfo::compound_binary_class_ops,\n\toctave_value_typeinfo::compound_binary_ops):\n\tNew fields.\n\t* ov-typeinfo.cc (octave_value_typeinfo::register_binary_class_op\n\t(octave_value::compound_binary_op, ...),\n\toctave_value_typeinfo::register_binary_op\n\t(octave_value::compound_binary_op, ...),\n\toctave_value_typeinfo::do_register_binary_class_op\n\t(octave_value::compound_binary_op, ...),\n\toctave_value_typeinfo::do_register_binary_op\n\t(octave_value::compound_binary_op, ...),\n\toctave_value_typeinfo::do_lookup_binary_class_op\n\t(octave_value::compound_binary_op),\n\toctave_value_typeinfo::do_lookup_binary_op\n\t(octave_value::compound_binary_op, ...)):\n\tNew functions.\n\t(octave_value::do_register_type): Resize also compound_binary_ops\n\tfield.\n\t* pt-exp.h (tree_expression::is_unary_expression): New virtual\n\tfunction.\n\t* pt-unop.h (tree_unary_expression::is_unary_expression): New virtual\n\toverride.\n\t* pt-cbinop.h, pt-cbinop.cc: New files (implement\n\ttree_compound_binary_expression class).\n\t* pt-all.h: Include pt-cbinop.h.\n\t* Makefile.in (PT_INCLUDES, PT_SRC): Include them in the lists.\n\t* parse.y (make_binary_op): Call maybe_compound_binary_expression.\n\t* OPERATORS/op-m-m.cc (trans_mul, mul_trans): New operator handlers.\n\t(install_m_m_ops): Register them.\n\t* OPERATORS/op-cm-cm.cc (trans_mul, mul_trans, herm_mul, mul_herm):\n\tNew operator handlers.\n\t(install_cm_cm_ops): Register them.\n\n\t* DLD-FUNCTIONS/matrix_type.cc: Fix tests relying on the\n\tolder more optimistic hermitian check.\n\n2008-05-21  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/rcond.cc (Frcond): Add support for single precision.\n\n\t* DLD-FUNCTIONS/sqrt.m: Replace DBL_* with FLT_* for single\n\tprecision types.\n\t* data.cc (static octave_value fill_matrix (const\n\toctave_value_list&, double, float, const char *)): Add function\n\twith additional argument to allow for different valid for double\n\tand single precision.\n\t(Finf, FNaN, FNA, Frealmax, Frealmin): Use it here.\n\t(Feps): Modify behavior for a single numerical argument to give\n\tdifference to next largest value in the class of the type passed.\n\n2008-05-21  John W. Eaton  <jwe@octave.org>\n\n\t* pt-idx.h (tree_index_expression::tree_index_expression (int, int)):\n\tDelete default argument values.\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (Flog2): Handle single precision.\n\t* ov-float.h, ov.float.cc, ov-flt-complex.h, ov-flt-complex.cc,\n\tov-flt-re-mat.h, ov-flt-re-mat.cc, ov-flt-cx-mat.h,\n\tov-flt-cx-mat.cc: Provide single precision version of log2 mapper\n\tfunction.\n\n\t* DLD-FUNCTIONS/__convn__.cc, DLD-FUNCTIONS/__pchip_deriv__.cc,\n\tDLD-FUNCTIONS/besselj.cc, DLD-FUNCTIONS/betainc.cc,\n\tDLD-FUNCTIONS/conv2.cc, DLD-FUNCTIONS/gammainc.cc,\n\tDLD-FUNCTIONS/givens.cc, DLD-FUNCTIONS/kron.cc,\n\tDLD-FUNCTIONS/lookup.cc, DLD-FUNCTIONS/syl.cc, data.cc:\n\tPrefer demotion to single precision rather than promotion to double.\n\n\t* ov-float.cc, ov-float.h, ov-flt-complex.cc, ov-flt-complex.h,\n\tov-flt-cx-mat.cc, ov-flt-cx-mat.h, ov-flt-re-mat.cc,\n\tov-flt-re-mat.h (numeric_conversion_function (void) const):\n\tRemove method.\n\n\t* ov-complex.cc, ov-complex.h, ov-cx-mat.cc, ov-cx-mat.h,\n\tov-re-mat.cc, ov-re-mat.h, ov-scalar.cc, ov-scalar.h\n\t(numeric_conversion_function (void) const): Add method for\n\tconversion to single precision.\n\n\t* DLD-FUNCTIONS/conv2.cc (Fconv2): Don't access third arg if we\n\tdon't have one.\n\n\t* DLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/expm.cc,\n\tDLD-FUNCTIONS/find.cc, DLD-FUNCTIONS/hess.cc,\n\tDLD-FUNCTIONS/qr.cc: COnvert for use with single precision.\n\n\t* OPERATORS/op-int.h, OPERATORS/op-int-conv.cc,\n\tOPERATORS/op-int-concat.cc: Adapt for single precision.\n\n\t* OPERATORS/op-i8-i8.cc, OPERATORS/op-i16-i16.cc,\n\tOPERATORS/op-i32-i32.cc, OPERATORS/op-i64-i64.cc,\n\tOPERATORS/op-ui8-ui8.cc, OPERATORS/op-ui16-ui16.cc,\n\tOPERATORS/op-ui32-ui32.cc, OPERATORS/op-ui64-ui64.cc:\n\tAdd includes for single precision types.\n\n\t* OPERATORS/op-b-b.cc, OPERATORS/op-b-bm.cc, OPERATORS/op-bm-b.cc,\n\tOPERATORS/op-fcm-fs.cc, OPERATORS/op-fcs-fs.cc,\n\tOPERATORS/op-fm-fs.cc, OPERATORS/op-fs-fcm.cc,\n\tOPERATORS/op-fs-fcs.cc, OPERATORS/op-fs-fm.cc,\n\tOPERATORS/op-fs-fs.cc, OPERATORS/op-int.h, ov.cc, ov-scalar.cc,\n\tov-float.h, ov-flt-complex.cc, ov-float.cc, ov-flt-re-mat.cc,\n\tov-flt-cx-mat.cc: Replace octave_float with octave_scalar_float\n\n\t* OPERATORS/op-fm-fm.cc, OPERATORS/op-fm-fs.cc,\n\tOPERATORS/op-fm-fcm.cc, OPERATORS/op-fm-fcs.cc,\n\tOPERATORS/op-fs-fm.cc, OPERATORS/op-fs-fs.cc,\n\tOPERATORS/op-fs-fcm.cc, OPERATORS/op-fs-fcs.cc,\n\tOPERATORS/op-fcm-fm.cc, OPERATORS/op-fcm-fs.cc,\n\tOPERATORS/op-fcm-fcm.cc, OPERATORS/op-fcm-fcs.cc,\n\tOPERATORS/op-fcs-fm.cc, OPERATORS/op-fcs-fs.cc,\n\tOPERATORS/op-fcs-fcm.cc, OPERATORS/op-fcs-fcs.cc,\n\tOPERATORS/op-m-m.cc, OPERATORS/op-m-s.cc,\n\tOPERATORS/op-m-cm.cc, OPERATORS/op-m-cs.cc,\n\tOPERATORS/op-s-m.cc, OPERATORS/op-s-s.cc,\n\tOPERATORS/op-s-cm.cc, OPERATORS/op-s-cs.cc,\n\tOPERATORS/op-cm-m.cc, OPERATORS/op-cm-s.cc,\n\tOPERATORS/op-cm-cm.cc, OPERATORS/op-cm-cs.cc,\n\tOPERATORS/op-cs-m.cc, OPERATORS/op-cs-s.cc,\n\tOPERATORS/op-cs-cm.cc, OPERATORS/op-cs-cs.cc:\n\tAdd mixed single/double assign operators.\n\n\t* ov.h (numeric_demotion_function): New method for double to\n\tsingle demotion.\n\t* ov-base.h (numeric_demotion_function): Declare virtual version.\n\n\t* ov-complex.cc, ov-complex.h, ov-cx-mat.cc, ov-cx-mat.h,\n\tov-re-mat.cc, ov-re-mat.h, ov-scalar.cc, ov-scalar.h\n\t(numeric_cdemote_function (void) const): Add method for\n\tconversion to single precision renamed from the method\n\tnumeric_conversion_function\n\n\t* ov.cc (do_binary_op): Use demotion function seperately than the\n\tnumeric conversion function so as to avoid isses like\n\ta=zeros(2,2);a(1,:)=1:2.\n\n\t* OPERATORS/op-fcm-fcm.cc, OPERATORS/op-fcm-fcs.cc,\n\tOPERATORS/op-fcm-fm.cc, OPERATORS/op-fcm-fs.cc,\n\tOPERATORS/op-fcs-fcm.cc, OPERATORS/op-fcs-fcs.cc,\n\tOPERATORS/op-fcs-fm.cc, OPERATORS/op-fcs-fs.cc,\n\tOPERATORS/op-fm-fcm.cc, OPERATORS/op-fm-fcs.cc,\n\tOPERATORS/op-fm-fm.cc, OPERATORS/op-fm-fs.cc,\n\tOPERATORS/op-fs-fcm.cc, OPERATORS/op-fs-fcs.cc,\n\tOPERATORS/op-fs-fm.cc, OPERATORS/op-fs-fs.cc, ov-float.cc,\n\tov-float.h, ov-flt-complex.cc, ov-flt-complex.h, ov-flt-cx-mat.cc,\n\tov-flt-cx-mat.h, ov-flt-re-mat.cc, ov-flt-re-mat.h: New files.\n\t* Makefile.in (OV_INCLUDES, OV_SRC, OP_XSRC. FLOAT_OP_XSRC,\n\tDOUBLE_OP_XSRC): Add them here.\n\n\t* DLD-FUNCTIONS/__convn__.cc, DLD-FUNCTIONS/__lin_interpn__.cc,\n\tDLD-FUNCTIONS/__pchip_deriv__.cc, DLD-FUNCTIONS/besselj.cc,\n\tDLD-FUNCTIONS/betainc.cc, DLD-FUNCTIONS/bsxfun.cc,\n\tDLD-FUNCTIONS/chol.cc, DLD-FUNCTIONS/conv2.cc,\n\tDLD-FUNCTIONS/det.cc, DLD-FUNCTIONS/eig.cc, DLD-FUNCTIONS/fft.cc,\n\tDLD-FUNCTIONS/fft2.cc, DLD-FUNCTIONS/fftn.cc,\n\tDLD-FUNCTIONS/fftw.cc, DLD-FUNCTIONS/filter.cc,\n\tDLD-FUNCTIONS/gammainc.cc, DLD-FUNCTIONS/givens.cc,\n\tDLD-FUNCTIONS/inv.cc, DLD-FUNCTIONS/kron.cc,\n\tDLD-FUNCTIONS/lookup.cc, DLD-FUNCTIONS/lu.cc,\n\tDLD-FUNCTIONS/matrix_type.cc, DLD-FUNCTIONS/max.cc,\n\tDLD-FUNCTIONS/pinv.cc, DLD-FUNCTIONS/schur.cc,\n\tDLD-FUNCTIONS/sqrtm.cc, DLD-FUNCTIONS/svd.cc,\n\tDLD-FUNCTIONS/syl.cc, DLD-FUNCTIONS/symbfact.cc,\n\tDLD-FUNCTIONS/typecast.cc, OPERATORS/op-b-b.cc,\n\tOPERATORS/op-b-bm.cc, OPERATORS/op-bm-b.cc, OPERATORS/op-bm-bm.cc,\n\tOPERATORS/op-cm-cm.cc, OPERATORS/op-cs-cs.cc, OPERATORS/op-m-m.cc,\n\tOPERATORS/op-range.cc, OPERATORS/op-s-s.cc, bitfcns.cc, data.cc,\n\toct-stream.cc, ov-base.cc, ov-base.h, ov-bool-mat.cc,\n\tov-bool-mat.h, ov-bool.h, ov-ch-mat.cc, ov-ch-mat.h,\n\tov-complex.cc, ov-complex.h, ov-cx-mat.cc, ov-cx-mat.h, ov-intx.h,\n\tov-range.cc, ov-range.h, ov-re-mat.cc, ov-re-mat.h, ov-scalar.h,\n\tov.cc, ov.h, pr-output.cc, pr-output.h, pt-mat.cc, utils.cc,\n\tutils.h, xdiv.cc, xdiv.h, xpow.cc, xpow.h:\n\tAllow single precision types.\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/rcond.cc: New function.\n\t* Makefile.in (DLD_XSRC): Add it here.\n\n\t* debug.cc (Fdbstop): If no line specified assume line 1.\n\t(Fdbstep, Fdbcont, Fdbnext): Move debugging functions\n\tto normal commands.\n\t(Fdbquit): New command to quit debugging mode and return to the\n\tprompt.\n\t(Fdbstep): Modify the dbstep command for compatibility.\n\t* input.cc (Vdebugging_current_line): Store current line being\n\tdebugged for use in DEFCMD versions of debug commands.\n\t(match_sans_spaces_semi): Delete.\n\t(static void get_debug_input (const std;string&)): New function to\n\tparse input in debug mode using standard Octave parser.\n\t(static octave_value_list get_user_input (const\n\toctave_value_list&, int)): Remove debugging specialization.\n\t* input.h (Vdebugging_current_line): Store current line being\n\tdebugged for use in DEFCMD versions of debug commands.\n\t* parse.y (make_return_command): Special handling in debug mode.\n\t* pt-bp.h (MAYBE_DO_BREAKPOINT): Support break in n lines needed\n\tto support \"dbstep N\".\n\t* pt.cc (tree::break_next): Convert to a down counter to support\n\tbreak in N lines. Breakpoint occure when tree::break_next is zero.\n\t* toplev.cc (octave_user_script *\n\toctave_call_stack::do_caller_user_script (difference_type) const):\n\tSupport skipping the first N functions to support \"dbstep out\".\n\t(octave_user_function * octave_call_stack::do_caller_user_function\n\t(difference_type) const): Ditto.\n\t(octave_user_code * octave_call_stack::do_caller_user_code\n\t(difference_type) const): Ditto.\n\t* toplev.h (octave_user_script *\n\toctave_call_stack::do_caller_user_script (difference_type) const):\n\tAdd difference_type argument.\n\t(octave_user_function * octave_call_stack::do_caller_user_function\n\t(difference_type) const): Ditto.\n\t(octave_user_code * octave_call_stack::do_caller_user_code\n\t(difference_type) const): Ditto.\n\t(static octave_user_script *caller_script (difference_type)):\n\tDitto.\n\t(static octave_user_function *caller_user_function\n\t(difference_type q)): Ditto.\n\t(static octave_user_code *caller_user_code (difference_type q)):\n\tDitto.\n\n2008-05-20  Kim Hansen  <kimhanse@gmail.com>\n\n\t* load-path.cc (load_path::do_initialize):\n\tInclude separator when appending sys_path.\n\n2008-05-20  Bill Denney  <bill@denney.ws>\n\n\t* file-io.cc (Ffgets, Fgets, Ffputs, Ffscanf): Doc fix (seealso).\n\n2008-05-20  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* DLD-FUNCTIONS/rand.cc (Frandn): Doc fix.\n\n2008-05-20  David Bateman  <dbateman@free.fr>\n\n\t* load-save.cc (do_load): Treat non verbose list_only output in\n\tthe same manner as Fwho.\n\t* symtab.h (static void clear_variable_regexp (const\n\tstd::string&): New method.\n\t(static std::list<symbol_record> regexp (const std::string&)): Ditto.\n\t(static std::list<symbol_record> regexp_variables (const\n\tstd::string&)): Ditto.\n\t(static std::list<symbol_record> regexp_global_variables (const\n\tstd::string&)): Ditto,\n\t(static std::list<symbol_record> regexp_variables (const\n\tstring_vector&)): Ditto.\n\t(void do_clear_variable_regexp (const std::string&)): Ditto.\n\t(std::list<symbol_record> do_regexp (const std::string&, bool)\n\tconst): Ditto.\n\t(do_who): Accept the \"-regexp\" option. Use regexp versions of\n\tsymbol table functions.\n\t(static inline bool name_match_any_pattern (const string_vector&,\n\tint, int, bool): Add regexp argument, and use regexp matching if\n\ttrue.\n\t(do_clear_variables): Add regexp option and pass to\n\tname_match_any_pattern.\n\t(Fclear): Accept the -regexp option.\n\n2008-05-07  John W. Eaton  <jwe@octave.org>\n\n\t* pt-arg-list.cc, pt-arg-list.h (tree_argument_list::dup):\n\tNew arg, context.\n\t* pt-assign.cc, pt-assign.h (tree_simple_assignment::dup,\n\ttree_multi_assignment::dup): Likewise.\n\t* pt-binop.cc, pt-binop.h (tree_binary_expression::dup,\n\ttree_boolean_expression::dup): Likewise.\n\t* pt-cell.cc, pt-cell.h (tree_cell::dup): Likewise.\n\t* pt-cmd.cc, pt-cmd.h (tree_no_op_command::dup,\n\ttree_function_def::dup): Likewise.\n\t* pt-colon.cc, pt-colon.h (tree_colon_expression::dup): Likewise.\n\t* pt-const.cc, pt-const.h (tree_constant::dup): Likewise.\n\t* pt-decl.cc, pt-decl.h (tree_decl_elt::dup, tree_decl_init_list::dup,\n\ttree_global_command::dup, tree_static_command::dup): Likewise.\n\t* pt-except.cc, pt-except.h (tree_try_catch_command::dup,\n\ttree_unwind_protect_command::dup): Likewise.\n\t* pt-exp.h (tree_expression:dup): Likewise.\n\t* pt-fcn-handle.cc, pt-exp.h (tree_expression:dup): Likewise.\n\t* pt-fcn-handle.h (tree_fcn_handle::dup,\n\ttree_anon_fcn_handle::dup): Likewise.\n\t* pt-id.cc, pt-id.h (tree_identifier::dup): Likewise.\n\t* pt-idx.cc, pt-idx.h (tree_index_expression::dup): Likewise.\n\t* pt-jump.cc, pt-jump.h (tree_break_command::dup,\n\ttree_continue_command::dup, tree_return_command::dup): Likewise.\n\t* pt-loop.cc, pt-loop.h (tree_while_command::dup,\n\ttree_do_until_command::dup, tree_simple_for_command::dup,\n\ttree_complex_for_command::dup): Likewise.\n\t* pt-mat.cc, pt-mat.h (tree_matrix::dup): Likewise.\n\t* pt-misc.cc, pt-misc.h (tree_parameter_list::dup,\n\ttree_return_list::dup): Likewise.\n\t* pt-select.cc, pt-select.h (tree_if_clause::dup,\n\ttree_if_command_list::dup, tree_if_command::dup,\n\ttree_switch_case::dup, tree_switch_case_list::dup,\n\ttree_switch_command::dup, tree_statement::dup,\n\ttree_statement_list::dup, tree_prefix_expression::dup,\n\ttree_postfix_expression::dup): Likewise.\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::save_ascii,\n\toctave_fcn_handle::save_binary, octave_fcn_handle::save_hdf5):\n \tPass context to symbol_table::all_variables.\n\t* load-save.cc (dump_octave_core): Likewise.\n\t* ov-fcn-handle.cc (Ffunctions): Don't skip anonymous functions\n\twith the name set to the text of the function body.\n \tPass context to symbol_table::all_variables and\n\tsymbol_table::symbol_record::varval.\n\n\t* symtab.h (symbol_table::varref, symbol_table::do_varref,\n\tsymbol_table::varval, symbol_table::do_varval,\n\tsymbol_table::all_variables, symbol_table::do_all_variables,\n\tsymbol_table::symbol_record::varref,\n\tsymbol_table::symbol_record::varval,\n\tsymbol_table::symbol_record::is_defined,\n\tsymbol_table::symbol_record::is_variable,\n\tsymbol_table::symbol_record::symbol_record_rep::varref,\n\tsymbol_table::symbol_record::symbol_record_rep::varval,\n\tsymbol_table::symbol_record::symbol_record_rep::is_defined,\n\tsymbol_table::symbol_record::symbol_record_rep::is_variable,\n\t):\n\t* symtab.h (symbol_table::do_inherit): New arg, donor_context.\n\tLook for value in donor_contxt.  Set value in base context.\n\t* symtab.cc (symbol_table::symbol_record::symbol_record_rep::dump):\n\tPass xcurrent_context to varval.\n\n2008-05-06  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-inline.cc (Finline): Also ignore NaN, Inf, pi, NA and eps.\n\n\t* bitfcns.cc (BITOP): Treat octave_bool types and octave_scalar.\n\n2008-05-06  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h (symbol_table::scope_id_cache): New class.  Use it to\n\treplace scope_ids_in_use and scope_ids_free_list.\n\t(symbol_table::erase_scope): Call free_scope.\n\t(symbol_table::free_scope): Call scope_id_cache::free.\n\n\t* ov-fcn.h (octave_function::lock_subfunctions,\n\toctave_function::unlock_subfunctions): New virtual functions.\n\t(octave_function::lock_subfunctions): Call lock_subfunctions here.\n\t(octave_function::unlock_subfunctions): Call unlock_subfunctions here.\n\t* ov-usr-fcn.h (octave_user_function::lock_subfunctions,\n\toctave_user_function::unlock_subfunctions): New functions.\n\n\t* symtab.h (symbol_table::lock_subfunctions,\n\tsymbol_table::lock_subfunctions,\n\tsymbol_table::fcn_info::lock_subfunction,\n\tsymbol_table::fcn_info::unlock_subfunction,\n\tsymbol_table::fcn_info::fcn_info_rep::lock_subfunction,\n\tsymbol_table::fcn_info::fcn_info_rep::unlock_subfunction):\n\tNew functions.\n\n\t* symtab.h (symbol_table::set_scope, symbol_table::get_instance):\n\tDon't set instance unless allocation succeeds.\n\t(symbol_table::print_scope, symbol_table::do_print_scope): Delete.\n\t(symbol_table::free_scope): Avoid using invalid iterator.\n\t(symbol_table::erase_scope): Call free_scope here.\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::load_ascii,\n\toctave_fcn_handle::load_binary, octave_fcn_handle::load_hdf5):\n\tCache anonymous name here.\n\t(octave_fcn_handle::octave_fcn_handle): Move here from\n\tov-fcn-handle.h.  Cache name if function is user-defined.\n\n\t* pt-id.cc (tree_identifier::dup): Avoid shadow warning.\n\n\t* symtab.h (symbol_table::cache_name, symbol_table::do_cache_name):\n\tNew functions.\n\t(symbol_table::get_instance): Cache top-level name here.\n\t* parse.y (finish_function): Call symbol_table::cache_name here.\n\n\t* symtab.cc (F__dump_symtab_info__): New function.\n\n\t* symtab.cc (symbol_table::dump, symbol_table::dump_global,\n\tsymbol_table::dump_functions, symbol_table::do_dump,\n\tsymbol_table::symbol_record::symbol_record_rep::dump,\n\tsymobl_table::fcn_info::fcn_info_rep::dump): New functions.\n\t* symtab.h: Provide decls.\n\t(symtab::scopes, symbol_table::symbol_record::dump,\n\tsymbol_table::fcn_info::dump): New functions.\n\t(symtab::get_instance): New arg, create; if false throw error if\n\tinstance for given scope is not found.\n\n\t* ov-base.cc (octave_base_value::dump): New virtual function.\n\t* ov-base.h: Proivde decl.\n\t* ov.h (octave_value::dump): New function.\n\n\t* ov.h, ov.c (octave_value::function_value): New const version.\n\t* ov-base.h, ov-base.cc (octave_base_value::function_value): Likewise.\n\t* ov-builtin.h (octave_builtin::function_value): Likewise.\n\t* ov-fcn-handle.h (octave_fcn_handle::function_value): Likewise.\n\t* ov-mex-fcn.h (octave_mex_function::function_value): Likewise.\n\t* ov-usr-fcn.h (octave_user_script::function_value,\n\toctave_user_function): Likewise.\n\n\t* symtab.h, symtab.cc: Use consistent naming scheme for iterator\n\ttypedefs.  Change all uses.\n\n\t* variables.cc (F__print_symtab_info__, F__print_symbol_info__):\n\tDelete.\n\n\t* ov-cell.cc (Fstruct2cell): Handle structure arrays properly.\n\n2008-05-05  David Bateman  <dbateman@free.fr>\n\n\t* sysdep.cc (Fputenv): Allow single arg. Alias to setenv.\n\n2008-05-05  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (Fre_read_readline_init_file): New function.\n\n2008-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-handle.cc (Ffunctions): Pass octave_value object instead\n\tof Cell in structure field assignment.\n\n\t* parse.y (frob_function): Don't install subfunctions here.\n\t(finish_function): Handle subfunctions here.\n\tConditionally define tree_function_def object here.\n\n\t* symtab.h (symbol_table::fcn_info::fcn_info_rep::find_function):\n\tInitialize args_evaluated.\n\t* pt-id.cc (tree_identifier::rvalue): Likewise.\n\t* variables.cc (symbol_exist): Likewise.\n\n\t* pt-id.h (tree_identifier::tree_identifer): Delete useless statement.\n\n\t* variables.cc (get_global_value): Use symbol_table::global_varval\n\tinstead of passing scope to symbol_table::varval.\n\t(set_global_value): Use symbol_table::global_varref\n\tinstead of passing scope to symbol_table::varref.\n\t(do_who): Use symbol_table::glob_global_variables\n\tinstead of passing scope to symbol_table::glob_variables.\n\t(do_clear_globals):\n\tUse symbol_table::global_variable_names and\n\tsymbol_table::clear_global instead of passing scope to\n\tsymbol_table::clear_variables.\n\tUse symbol_table::global_variable_names instead of passing scope\n\tto symbol_table::variable_names.\n\n\t* unwind-prot.cc (unwind_protect::save_size_t): New function.\n\t(saved_variable::restore_value): Handle size_t values.\n\t(saved_variable::saved_variable): New size_t constructor.\n\t(saved_variable::size_type): New var_type enum value.\n\t(saved_variable::ptr_to_size_t, saved_variable::size_t_value):\n\tNew union elements.\n\t* unwind-prot.h (unwind_protect::save_size_t): Provide decl\n\t(unwind_protect_size_t): New macro.\n\n\t* toplev.cc (octave_call_stack::do_goto_frame,\n\toctave_call_stack::do_goto_frame_relative): New functions.\n\t(octave_call_stack::do_backtrace): Also return scope and context ids.\n\t* toplev.h \t(octave_call_stack::do_goto_frame,\n\toctave_call_stack::do_goto_frame_relative): Provide decls.\n\t(octave_call_stack::curr_frame): New data member.\n\t(octave_call_stack::octave_call_stack): Initialize it.\n\t(octave_call_stack::call_stack_elt::scope,\n\t(octave_call_stack::call_stack_elt::context): New data members.,\n\t(octave_call_stack::current_frame,\n\t(octave_call_stack::do_current_frame\n\toctave_call_stack::do_goto_frame,\n\toctave_call_stack::do_goto_frame_relative): New functions.\n\t(octave_call_stack::push, octave_call_stack::do_push):\n\tNew args, scope and context.\n\t(octave_call_stack::do_push, octave_call_stack::do_pop): Update\n\tcurr_frame if debugging.\n\n\t* symtab.cc (symbol_table::global_table): New map for global values.\n\t(symbol_table::xcurrent_context): New variable for context info.\n\t* symtab.h: Provide decls.\n\t(symbol_table::global_varref, symbol_table::global_varval,\n\tsymbol_table::current_context,\n\tsymbol_table::set_scope_and_context,\n\tsymbol_table::glob_global_variables,\n\tsymbol_table::global_variable_names,\n\tsymbol_table::top_leve_variable_names):\n\tNew functions.\n\t(symbol_table::context_id, const_global_table_iterator,\n\tglobal_table_iterator): New typedefs.\n\t(symbol_table::xcurrent_context_this_table): New variable.\n\t(symbol_table::symbol_table): Initialize it.\n\t(symbol_table::set_scope): Use it.\n\t(symbol_table::symbol_record::find, symbol_table::do_find):\n\tUse symbol_table::global_varref instead of passing scope to\n\tsymbol_table::varref.\n\t(symbol_table::symbol_record::symbol_record_rep::value_stack):\n\tNow a std::deque instead of a std::stack.\n\t(symbol_table::symbol_record::symbol_record_rep::push_context,\n\tsymbol_table::symbol_record::symbol_record_rep::pop_context):\n\tDon't push or pop persistent of global variables.\n\t(symbol_table::symbol_record::symbol_record_rep::varval,\n\tHandle context here.  Call symbol_table::global_varval instead of\n\tpassing scope to symbol_table::varval.\n\t(symbol_table::symbol_record::symbol_record_rep::varref):\n\tHandle context here.  Call symbol_table::global_varref instead of\n\tpassing scope to symbol_table::varref.\n\t(symbol_table::symbol_record::varref,\n\tsymbol_table::symbol_record::varval): No need to handle global\n\tvalues specially here.\n\t(symbol_table::symbol_record::push_context\n\tsymbol_table::symbol_record::pop_context: No need to handle global\n\tor persistent values specially here.\n\t(symbol_table::get_instance): Don't return global scope.\n\t(symbol_table::do_push_context, symbol_table::do_pop_context):\n\tIncrement/decrement xcurrent_context.\n\t(symbol_table::do_clear_global, symbol_table::do_clear_global_pattern):\n\tUse global_table instead of separate scope.\n\n\t* symtab.h, symtab.cc (symbol_table::fcn_info::fcn_info_rep::find,\n\tsymbol_table::fcn_info::fcn_info_rep::find_function,\n\tsymbol_table::fcn_info::find, symbol_table::fcn_info::find_function,\n\tsymbol_table::find, symbol_table::find_function,\n\tsymbol_table::do_find, symbol_table::insert, symbol_table::varref,\n\tsymbol_table::varval, symbol_table::persistent_varref,\n\tsymbol_table::persistent_varval, symbol_table::erase_persistent,\n\tsymbol_table::is_variable, symbol_table::clear,\n\tsymbol_table::clear_variables, symbol_table::clear_global,\n\tsymbol_table::clear_variable, symbol_table::clear_global_pattern,\n\tsymbol_table::clear_variable_pattern, symbol_table::push_context,\n\tsymbol_table::pop_context, symbol_table::mark_hidden,\n\tsymbol_table::mark_global, symbol_table::glob,\n\tsymbol_table::glob_variables, symbol_table::variable_names,\n\tsymbol_table::is_local_variable, symbol_table::is_global):\n\tEliminate scope arg.  Change all uses.\n\t(symbol_table::erase_scope, symbol_table::dup_scope):\n\tRequire scope arg.\n\n\t* pt-stmt.cc (tree_statement::eval): Don't update statement info\n\tin octave_call_stack if debugging.\n\n\t* pt-id.h (tree_identifier::xsym): New function.\n\t(tree_identifier::rvalue, tree_identifier::lvalue,\n\ttree_identifier::dup, tree_identifier::is_defined,\n\ttree_identifier::is_variable, tree_identifier::mark_global,\n\ttree_identifier::mark_as_static, tree_identifier::do_lookup,\n\ttree_identifier::mark_as_formal_parameter):\n\tUse xsym to access symbol.\n\t(tree_identifier::scope): New data member.\n\t(tree_identifier::tree_identifier): Initialize it.\n\n\t* ov-usr-fcn.cc (octave_user_script::octave_user_script,\n\toctave_user_function::octave_user_function):\n\tInitialize call_depth to -1.\n\t(octave_user_script::do_multi_index_op): Fix comparison of\n\tcall_depth with Vmax_recursion_depth.\n\t(octave_user_function::do_multi_index_op):\n\tCompare call depth > 0, instead of > 1.\n\t* ov-usr-fcn.h (octave_user_function::save_args_passed):\n\tCompare call depth > 0, instead of > 1.\n\n\t* input.cc (Vdebugging): New variable.\n\t(get_user_input): Eliminate DEBUG argument.  Use global Vdebugging\n\tvariable instead.  Change all callers.\n\t(saved_frame): New static variable.\n\t(restore_frame): New function.\n\t(do_keyboard): Unwind-protect Vdebugging here and set it to TRUE.\n\tSave current frame.  Use unwind_protect to restore it.\n\t(Fkeyboard): Save current frame.  Use unwind_protect to restore it.\n\tMove up the call stack one frame before calling do_keyboard.\n\t* input.h (Vdebugging): Provide decl.\n\n\t* mex.cc (mexGetVariable): Handle global vars with get_global_value.\n\t(mexPutVariable): Likewise, with set_global_value.\n\n\t* octave.cc (intern_argv): Assert that we are at the top level.\n\tDon't pass scope to symbol_table::varref or symbol_table::mark_hidden.\n\n\t* load-save.cc (install_loaded_variable): Use\n\tsymbol_table::global_varref instead of passing global scope to\n\tsymbol_table::varref.\n\n\t* help.cc (make_name_list): Call symbol_table::global_variable_names\n\tand symbol_table::top_level_variable_names instead of passing\n\tscope to symbol_table::variable_names.\n\n\t* debug.cc (do_dbupdown, Fdbup, Fdbdown): New functions.\n\t(current_stack_frame): Delete static variable.\n\t(Fdbstack): Rename from F__dbstack__.  Implement all of dbstack\n\there instead of partially in dbstack.m.\n\n2008-05-03  John W. Eaton  <jwe@octave.org>\n\n\t* pt-arg-list.cc (F__end__): If there are more dimensions than\n\tindices, smash extra dimensions first.\n\t(num_indices): New static variable.\n\t(tree_argument_list::convert_to_const_vector): Save and set it.\n\n\t* parse.y (parse_fcn_file): Also temporarily set parser_end_of_input\n\tand get_input_from_eval_string to false while reading script files.\n\n2008-05-01  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (load_fcn_from_file): Expect\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_oct):\n\tSearch currently loaded .oct files by file name.  Don't search\n\tcurrently loaded files for functions.\n\t(octave_shlib_list::find_file, octave_shlib_list::do_find_file):\n\tNew functions.\n\t(octave_shlib_list::search, octave_shlib_list::do_search): Delete.\n\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_oct): No need to\n\tdo load_path lookups here.\n\t(octave_shlib_list::iterator, octave_shlib_list::const_iterator):\n\tNew typedefs.\n\t(octave_shlib_list::do_remove, octave_shlib_list::do_search,\n\toctave_shlib_list::do_display): Use them.\n\t(octave_mex_file_list::iterator, octave_mex_file_list::const_iterator):\n\tNew typedefs.\n\t(octave_mex_file_list::do_remove): Use them.\n\n2008-05-03  Rafael Laboissiere  <rafael@debian.org>\n\n\t* DLD-FUNCTIONS/time.cc, file_io.cc: Use ischar instead of\n\tdeprecated isstr.\n\n2008-04-30  John W. Eaton  <jwe@octave.org>\n\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_oct):\n\tIf function already exists, reload it anyway.  Clear existing\n\toct_file only if reloading a function from the same file.\n\t(octave_shlib_list::display): New static function.\n\t(octave_shlib_list::do_display): New function.\n\n\t* symtab.cc (out_of_date_check_internal): Better handling for\n\tfunctions found in files by relative file names.\n\t(load_out_of_date_fcn): New function.\n\n\t* ls-oct-ascii.cc (extract_keyword): Return early if first char is\n\tnot a comment character.\n\t(read_ascii_data): Accept .nargin. and .nargout. as valid identifiers.\n\n\t* ov-fcn-handle.cc: Combine tests.  Test saving and loading\n\thandles for built-in, .oct, and .m functions.\n\t(octave_fcn_handle::save_ascii, octave_fcn_handle::save_binary,\n\toctave_fcn_handle::save_hdf5, octave_fcn_handle::print):\n\tAvoid dereferencing invalid pointer.\n\n\t* data.cc: Fix tests.  Use \"%!assert\", not \"%! assert\" for\n\tindividual assert tests.\n\n2008-04-30  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-base.cc, ov-base.h, ov-bool-mat.h, ov-bool-sparse.h,\n\tov-bool.h, ov-complex.cc, ov-complex.h, ov-cx-mat.cc, ov-cx-mat.h,\n\tov-cx-sparse.cc, ov-cx-sparse.h, ov-intx.h, ov-range.h,\n\tov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-re-sparse.h,\n\tov-scalar.cc, ov-scalar.h, ov.h:\n \tProvide log2 mapper function.\n\t* data.cc (Flog2): New function.\n\n2008-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* pt-stmt.h (tree_statement_list::function_body): New data member.\n\t(tree_statement_list::tree_statement_list): Initialize it.\n\t(tree_statement_list::mark_as_script_body): New function.\n\t(tree_statement::maybe_echo_code, tree_statement::eval):\n\tRename in_function_body argument to in_function_or_script_body.\n\t* pt-stmt.cc (tree_statement::eval): Only set statement in call\n\tstack if in_function_or_script_body is true.\n\n\t* pt-stmt.cc (tree_statement_list::eval): Call elt->eval with\n\tfunction_body || script_body.\n\t* ov-usr-fcn.cc (octave_user_script::octave_user_script):\n\tcommand list as script body here.\n\t(octave_user_function::octave_user_function):\n\tMark command list as function body here.\n\t* parse.y (start_function, make_anon_fcn_handle): Not here.\n\n\t* toplev.h, toplev.cc (octave_call_stack::backtrace,\n\toctave_call_stack::do_backtrace): New arg, N.  Skip innermost N\n\tstack frames.\n\n\t* debug.cc (F__dbstack__): New function.\n\t(current_stack_frame): New static variable.\n\n\t* error.cc (verror, pr_where): Use octave_call_stack instead of\n\ttree_statement stack to get line and column information.\n\t(pr_where): Use octave_call_stack instead of tree_statement stack\n\tto get current statement.\n\t* input.cc (get_user_input): Extract current line number from\n\toctave_call_stack instead of tree_statement_stack.\n\t* pt-stmt.cc (tree_statement::eval): Put current statement on\n\toctave_call_stack instead of tree_statement_stack.\n\t* pt-stmt.h, pt-stmt.cc (class tree_statement_stack): Delete.\n\n\t* toplev.h, toplev.cc (octave_call_stack::call_stack_elt):\n\tNew nested struct.\n\t(octave_call_stack::cs): Now a deque of call_stack_elts.\n\tChange all uses.\n\t(octave_call_stack::current_statement,\n\toctave_call_stack::current_line,\n\toctave_call_stack::current_column,\n\toctave_call_stack::top_statement,\n\toctave_call_stack::set_statement, octave_call_stack::backtrace):\n\tNew static functions.\n\t(octave_call_stack::do_current_line,\n\toctave_call_stack::do_current_column,\n\toctave_call_stack::do_top_statement,\n\toctave_call_stack::do_set_statement,\n\toctave_call_stack::do_backtrace): New member functions.\n\n2008-04-24  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.h, toplev.cc (octave_call_stack::unwind_pop_script):\n\tDelete unused function.\n\n\t* ov-usr-fcn.cc: Move constructor definitions here, from ov-usr-fcn.h.\n\t* ov-usr-fcn.h (octave_user_script::octave_user_script):\n\tAlso Initialize t_parsed and t_checked.\n\n2008-04-24  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* ov-usr-fcn.h (octave_user_script::octave_user_script):\n\tInitialize call_depth.\n\n2008-04-24  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (do_stream_open): Return -1 for directories.\n\n2008-04-23  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__qp__.cc (qp): Avoid bounds error when removing\n\tconstraint from active set.\n\n\t* lex.l (text_yyinput): New function.  Use it in place of yyinput.\n\t(next_token_is_sep_op, scan_for_comments, eat_whitespace,\n\thave_continuation): No need to check for CR or CRLF.\n\t* parse.y (text_getc): Also return NL for single CR.\n\n2008-04-32  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* input.cc (get_input_from_file): Open file in binary mode.\n\n2008-04-20  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_stream::read): Allow single data type\n\tspecification but return double.\n\n2008-04-18  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l, lex.h (process_comment): New arg, start_in_block.  Call\n\tgrab_block_comment if start_in_block is true.  Change all uses.\n\t* lex.l (grab_block_comment): New function.\n\t(grab_comment_block): New arg, at_bol.  Change all uses.\n\tCall grab_block_comment if we find the start of a block comment.\n\t(block_comment_nesting_level): New static variable.\n\t(^{S}*{CCHAR}\\{{S}*{NL}): New rule.\n\t(<<EOF>>): Warn about open block comments.\n\t(reset_parser): Set block_comment_nesting_level to zero.\n\t* parse.y (parse_fcn_file): Stash help text from\n\tgobble_leading_white_space after calling reset_parser.\n\t(text_getc): Keep track of input_line_number here.\n\t(skip_white_sapce): Don't increment input_line_number here.\n\t* lex.l (grab_comment_block): Or here.\n\n\t* lex.l (Vdisplay_tokens): New static variable.\n\t(F__display_tokens__): New function.\n\t(display_token): New function.\n\t(DISPLAY_TOK_AND_RETURN): New macro.\n\t(COUNT_TOK_AND_RETURN): Use DISPLAY_TOK_AND_RETURN.\n\t(<COMMAND_START>[\\\"\\'], \"'\", \\\"): Move handle_string outside of\n\tCOUNT_TOK_AND_RETURN macro parameter list.\n\t(handle_identifier): Don't use macros to return token values here.\n\t(<MATRIX_START>{S}*{COMMENT}{SNLCMT}*|<MATRIX_START>{S}*{NL}{SNLCMT}*):\n\tRecognize block comments here.\n\n\t* pr-output.cc (Fdisp): If nargout > 0, produce an sq-string\n\tunless arg is a dq-string.\n\n2008-04-17  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (looks_like_copyright): Handle leading whitespace.\n\t(class stdio_stream_reader): New class.\n\t(skip_white_space): New function.\n\t(gobble_leading_white_space): New arg, EOF.  Change all uses.\n\tUse skip_white_space and grab_comment_block to process comments.\n\t(process_leading_comments): Delete.\n\t(parse_fcn_file): Call gobble_leading_white_space instead of\n\tprocess_leading_comments.\n\tSkip parsing if gobble_leading_white_space detects EOF.\n\t* lex.l (process_comment): Delete CCHAR arg.  Change all uses.\n\t({CCHAR}): Unput comment character before calling process_comment.\n\t(grab_comment_block): Rename from grab_help_text.  Don't discard\n\tspaces from comment text.  Update input_line_number and\n\tcurrent_input_column as characters are read.  Warn only once about\n\tincompatible comment characters in a given block of comments.\n\tUse stream_reader class instead of accessing yyinput and yyunput\n\tdirectly.\n\t(class flex_stream_reader): New class.\n\t(process_comment): Use grab_comment_block to handle all comments.\n\tDon't call maybe_gripe_matlab_incompatible_comment.\n\tAlways store comment text returned by grab_comment_block.\n\t* lex.h (grab_comment_block): Provide decl.\n\t(class stream_reader): New class.\n\n2008-04-16  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (Fautoload, Fmfilename): Call\n\toctave_call_stack::caller_user_code, not\n\toctave_call_stack::caller_user_script_or_function.\n\t* toplev.cc, toplev.h (octave_call_stack::caller_user_code):\n\tRename from octave_call_stack::caller_user_script_or_function.\n\t(octave_call_stack::do_caller_user_code): Rename from\n\toctave_call_stack::do_caller_user_script_or_function.\n\t* ov-usr-fcn.h (class octave_user_code): New class, derived from\n\toctave_fucntion.\n\t(class octave_user_function, class octave_user_script): Derive\n\tfrom octave_user_code, not octave_function.\n\t(octave_user_script::user_code_value,\n\toctave_user_function::user_code_value): New functions.\n\t* ov.cc (octave_value::user_script_value,\n\toctave_value::user_code_value): New functions.\n\t* ov.h: Provide decls.\n\t(octave_value::is_user_code, octave_value::is_user_script):\n\tNew functions.\n\t* ov-base.cc (octave_base_value::user_script_value,\n\toctave_base_value::user_code_value): New virutal functions.\n\t* ov-base.h: Provide decls.\n\t(octave_base_value::is_user_script, octave_base_value::is_user_code):\n\tNew virtual functions.\n\t* error.cc (verror, pr_where, error_2, warning_1):\n\tCall octave_call_stack::caller_user_code instead of\n\toctave_call_stack::caller_user_script_or_function\n\t* input.cc (get_user_input): Likewise.\n\t* debug.h (bp_table::breakpoint_map): Use pointer to\n\toctave_user_code instead of octave_user_function.\n\t* debug.cc (get_user_code): Rename from get_user_function.\n\tReturn pointer to octave_user_code instead of octave_user_function.\n\tChange all uses.\n\t(bp_table::do_add_breakpoint, bp_table::do_remove_breakpoint,\n\tbp_table::do_remove_all_breakpoints_in_file,\n\tbp_table::do_get_breakpoint_list):\n\tAvoid dereferencing invalid pointers.\n\t(parse_dbfunction_params): Call\n\toctave_call_stack::caller_user_code, not\n\toctave_call_stack::caller_user_script_or_function.\n\n\t* load-save.cc (Fsave): Fix continuation character in doc string.\n\n\t* pt-walk.h (tree_walker::visit_function_def): New function.\n\t* pt-pr-code.cc (tree_print_code::visit_function_def): New function.\n\t* pt-pr-code.h: Provide decl.\n\t* pt-bp.cc (tree_breakpoint::visit_function_def): New function.\n\t* pt-bp.h: Provide decl.\n\t* pt-check.cc (tree_checker::visit_function_def): New function.\n\t* pt-check.h: Provide decl.\n\n\t* parse.y (finish_function): Return ptr to tree_function_def object\n\tif curr_fcn_ptr is not defined.  Avoid dereferencing invalid pointers.\n\t(frob_function): Set curr_fcn_ptr only when reading a function file.\n\t(function): Call finish function in both cases to generate value\n\tof production.\n\n\t* pt-cmd.h, pt-cmd.cc (tree_function_def): New class.\n\n\t* parse.y (parse_and_execute): Delete.\n\t* parse.h: Delete decl.\n\n\t* pt-pb.cc (tree_breakpoint::visit_octave_user_script): New function.\n\t* pt-pb.h: Provide decl.\n\t* pt-check.cc (tree_checker::visit_octave_user_script): New function.\n\t* pt-check.h: Provide decl.\n\t* pt-pr-code.cc (tree_print_code::visit_octave_user_script):\n\tNew function.\n\t* pt-pr-code.h: Provide decl.\n\t* pt-walk.h (visit_octave_user_script): New pure virtual function.\n\n\t* parse.y (make_script, process_leading_comments,\n\tlooking_at_function_keyword): New static functions.\n\t(SCRIPT): New token.\n\t(script): New non-terminal.\n\t(command): Handle script here.\n\t(parse_fcn_file): Eliminate EXEC_SCRIPT argument.  Change all\n\tcallers.  Parse scripts and return an octave_user_script rather\n\tthan executing them here.\n\t(load_fcn_from_file): Handle script and function files the same.\n\t(source_file): Call d_multi_index_op on object returned by\n\tparse_fcn_file.\n\t(is_function_file): Delete.\n\t(gobble_leading_white_space): Don't recurse.  Simplify.  Eliminate\n\tSKIP_CODE, IN_PARTS, and SAVE_COPYRIGHT arguments.  Change all\n\tcallers.\n\t(octave_function_ptr): Delete unused typedef.\n\t(get_help_from_file): If help text isn't found by\n\tgobble_leading_whitespace, parse file to find it.\n\n\t* lex.l (SCRIPT_FILE_BEGIN): New exclusive start state.\n\t(prep_lexer_for_script): New function.\n\t(grab_help_text): New arg, EOF.\n\t(process_comment): New function.\n\t({CCHAR}): Use it.\n\t* lex.h (prep_lexer_for_script): Provide decl.\n\n\t* lex.h, lex.cc, parse.y (lexical_feedback::beginning_of_function):\n\tDelete data member and all uses.\n\n\t* ov-usr-fcn.cc (octave_user_script::~octave_user_script):\n\tMove destructor here from ov-usr-fcn.h.  Delete cmd_list.\n\t(octave_user_script::subsref, octave_user_script::accept,\n\toctave_user_script::traceback_error): New functions.\n\t(octave_user_script::do_multi_index_op):\n\tExecute cmd_list instead of calling source_file.\n\t* ov-usr-fcn.h (octave_usr_script::cmd_list,\n\toctave_usr_script::t_parsed, octave_usr_script::t_checked,\n\toctave_usr_script::call_depth): New data members.\n\t(octave_usr_script::octave_usr_script): Initialize all data members.\n\t(octave_usr_script::octave_usr_script (const std::string&, const\n\tstd::string&, tree_statement_list *, const std::string&)):\n\tNew constructor.\n\t(octave_usr_script::function_value,\n\toctave_usr_script::user_script_value, mark_fcn_file_up_to_date,\n\toctave_usr_script::stash_fcn_file_time,\n\toctave_usr_script::time_parsed, octave_usr_script::time_checked,\n\toctave_usr_script::subsref, octave_usr_script::body): New functions.\n\t(octave_user_script::subsref, octave_user_script::accept,\n\toctave_user_script::traceback_error): Provide decls.\n\n2008-04-14  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* oct-stream.cc (octave_scan_1): Ensure digit following X is hex\n\tdigit before reading number as hex.\n\n2008-04-14  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (Ffread): Allow SKIP arg to be omitted.\n\t(Ffwrite): Likewise.  Handle args in a way consistent with Ffread.\n\n2008-04-09  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* DLD-FUNCTIONS/dispatch.cc: Replace system(\"echo '...'>...\") calls\n\twith real file writing.\n\n2008-04-07  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/qr.cc (Fqrshift): New function.\n\t* DLD-FUNCTIONS/chol.cc (Fcholinsert, Fcholdelete, Fcholshift):\n\tNew functions.\n\n2008-04-04  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (make_constant): Handle escape sequences in dq-strings.\n\n2008-04-03  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (make_constant): Also stash original text for strings.\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::subsref):\n\tDon't call next_subsref here.\n\n2008-04-01  John W. Eaton  <jwe@octave.org>\n\n\t* pt-id.h (do_lookup (bool&, bool)): Delete.\n\t(do_lookup (tree_argument_list *, const string_vector&,\n\toctave_value_list&, bool&)): Call MAYBE_DO_BREAKPOINT here.\n\n2008-04-02  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (void gnuplot_backend::close_figure (const\n\toctave_value&) const): Allow for an input and output stream.\n\n2008-03-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/lookup.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n2008-03-28  David Bateman  <dbateman@free.fr>\n\n\t* ov-complex.cc (SCALAR_MAPPER, CD_SCALAR_MAPPER): New macro for\n\tcomplex values with zero imaginary part.\n\t(erf, erfc, gamma, lgamma): Use the new mappers to define these\n\tmapper functions.\n\t* ov-complex.h (erf, erfc, gamma, lgamma): Declare them.\n\t* ov-cx-mat.cc (any_element_less_than, any_element_greater_than):\n\tNew static functions\n\t(DARRAY_MAPPER, CD_ARRAY_MAPPER): New macro for complex values\n\twith zero imaginary part.\n\t(erf, erfc, gamma, lgamma): Use the new mappers to define these\n\tmapper functions.\n\t* ov-cx-mat.h (erf, erfc, gamma, lgamma): Declare them.\n\t* ov-cx-sparse.cc (any_element_less_than, any_element_greater_than):\n\tNew static functions\n\t(DSPARSE_MAPPER, CD_SPARSE_MAPPER): New macro for complex values\n\twith zero imaginary part.\n\t(erf, erfc, gamma, lgamma): Use the new mappers to define these\n\tmapper functions.\n\t* ov-cx-sparse.h (erf, erfc, gamma, lgamma): Declare them.\n\t* ov-re-sparse.cc (CD_SPARSE_MAPPER): Use correct mapper functors.\n\t* mapper.cc: Add tests for the above cases.\n\n2008-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/max.cc: Rename from minmax.cc.\n\t* Makefile.in (DLD_XSRC): Rename minmax.cc to max.cc.\n\n\t* DLD-FUNCTIONS/__convn__.cc (convn): Use traits class and\n\ttypedefs to allow all types to be deduced from argument types.\n\n2008-03-27  Søren Hauberg  <hauberg@gmail.com>\n\n\t* DLD-FUNCTIONS/__convn__.cc (Fconvn): Allow convolving real data with\n\tcomplex data.\n\n2008-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* ov-range.h (octave_range::subsref (const std::string&,\n\tconst std::list<octave_value_list>&, int)):\n\tForward to simple subsref.\n\t* ov-base-sparse.h (octave_base_sparse<T>::subsref (const std::string&,\n\tconst std::list<octave_value_list>&, int)): Likewise.\n\t* ov-base-scalar.h (octave_base_sparse<T>::subsref (const std::string&,\n\tconst std::list<octave_value_list>&, int)): Likewise.\n\t* ov-base-matrix.h (octave_base_matrix<T>::subsref (const std::string&,\n\tconst std::list<octave_value_list>&, int)): Likewise.\n\n\t* ov-struct.cc, ov-cell.h (octave_cell::subsref (const\n\tstd::string&, const std::list<octave_value_list>&, int)):\n\tDefine nargout version of subsref instead of simple version.\n\t* ov-struct.cc, ov-struct.h (octave_struct::subsref (const\n\tstd::string&, const std::list<octave_value_list>&, int)):\n\tDefine nargout version of subsref instead of simple version.\n\n\t* ov-builtin.h (octave_builtin::subsref (const std::string&,\n\tconst std::list<octave_value_list>&): Forward to nargout subsref.\n\t* ov-cell.h (octave_cell::subsref (const std::string&,\n\tconst std::list<octave_value_list>&)):\n\t* ov-class.h (octave_class::subsref (const std::string&,\n\tconst std::list<octave_value_list>&): Likewise.\n\t* ov-fcn-handle.h (octave_fcn_handle::subsref (const std::string&,\n\tconst std::list<octave_value_list>&): Likewise.\n\t* ov-list.h (octave_list::subsref (const std::string&,\n\tconst std::list<octave_value_list>&): Likewise.\n\t* ov-mex-fcn.h (octave_mex_function::subsref (const std::string&,\n\tconst std::list<octave_value_list>&): Likewise.\n\t* ov-struct.h (octave_struct::subsref (const std::string&,\n\tconst std::list<octave_value_list>&)):\n\t* ov-usr-fcn.h (octave_user_function::subsref (const std::string&,\n\tconst std::list<octave_value_list>&): Likewise.\n\n\t* ov.cc (octave_value::subsref): Use value of nargout instead of\n\tis_constant method to decide which type of subsref method to call.\n\t(octave_value::assign): Always call simple subref method here.\n\n\t* DLD-FUNCTIONS/chol.cc, DLD-FUNCTIONS/det.cc,\n\tDLD-FUNCTIONS/getpwent.cc, DLD-FUNCTIONS/inv.cc,\n\tDLD-FUNCTIONS/qr.cc, DLD-FUNCTIONS/symrcm.cc, file-io.cc):\n\tTexinfo fixes.\n\n2008-03-26  Søren Hauberg  <hauberg@gmail.com>\n\n\t* DLD-FUNCTIONS/__convn__.cc (Fconvn):\n\tCall complex_array_value to extract N-d array.\n\n2008-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-sparse.cc (octave_base_sparse<T>::print_raw):\n\tAlso display percentage of elements that are nonzero.\n\n2008-03-25  Søren Hauberg  <hauberg@gmail.com>\n\n\t* DLD-FUNCTIONS/__convn__.cc: New file.\n\t* Makefile.in: Add __convn__.cc\n\n2008-03-25  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/hex2num.cc: New function\n\t* Makefile.in (DLD_XSRC): Add hex2num.cc.\n\n2008-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* mappers.cc (Fexpm1, Flog1p): New functions.\n\t* ov-base.cc, ov-base.h, ov-bool-mat.h, ov-bool-sparse.h,\n\tov-bool.h, ov-complex.cc, ov-complex.h, ov-cx-mat.cc, ov-cx-mat.h,\n\tov-cx-sparse.cc, ov-cx-sparse.h, ov-range.h, ov-re-mat.cc,\n\tov-re-mat.h, ov-re-sparse.cc, ov-re-sparse.h, ov-scalar.cc,\n\tov-scalar.h, ov.h:\n\tProvide expm1 and log1p functions.\n\n\t* mappers.cc (Froundb): New functions\n\t* ov-base.cc, ov-base.h, ov-bool-mat.h, ov-bool-sparse.h,\n\tov-bool.h, ov-complex.cc, ov-complex.h, ov-cx-mat.cc, ov-cx-mat.h,\n\tov-cx-sparse.cc, ov-cx-sparse.h, ov-intx.h, ov-range.h,\n\tov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-re-sparse.h,\n\tov-scalar.cc, ov-scalar.h, ov.h:\n \tProvide roundb mapper function.\n\n2008-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* load-save.cc (save_vars): Handle -struct modifier.\n\t(save_fields): New function.\n\t(Fsave): Document new feature.\n\n2008-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* lex.h (lexical_feedback::looking_at_initializer_expression):\n\tNew data member.\n\t* lex.l (lexical_feedback::init): Initialize it.\n\t(handle_identifier): Don't unconditionally force identifiers to be\n\tvariables in the current scope.  Don't call force_local_variable\n\tfor symbols that appear in parameter initializer expressions.\n\t* parse.y (decl_param_init): New parser \"subroutine\".\n\t(decl2): Use it.  Set lexer_flags.looking_at_initializer_expression\n\tto false after parsing initializer.\n\n2008-03-24  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (map_s_s): Fix for sparse/sparse mappers that resulted\n\tin an empty sparse matrix being returned.\n\t(Fhypot): New function based on the libm hypot function.\n\n2008-03-24  Primozz Peterlin  <primozz.peterlin@gmail.com>\n\n\t* variables.cc (Fexist): Doc fix.\n\n2008-03-23  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-int.h: Add el_div and el_ldiv operators to the\n\tbinops that were missing them. Added elem_pow functions for mixed\n\tinteger floating point cases. Initialize the mixed integer\n\tfloating point cases.\n\n2008-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* ov-cell.h (octave_cell::is_constant): Return true.\n\t* ov-cell.h, ov-cell.cc (octave_cell::subsref (const std::string&,\n\tconst std::list<octave_value_list>&)): Define.\n\t(octave_cell::subsref (const std::string&,\n\tconst std::list<octave_value_list>&, int)): Call panic_impossible.\n\n\t* ov-struct.h (octave_struct::is_constant): New function.\n\t* ov-struct.h, ov-struct.cc (octave_struct::subsref (const std::string&,\n\tconst std::list<octave_value_list>&)): Define.\n\t(octave_struct::subsref (const std::string&,\n\tconst std::list<octave_value_list>&, int)): Call panic_impossible.\n\n2008-03-21  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/amd.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add amd.cc.\n\n2008-03-20  David Bateman  <dbateman@free.fr>\n\n\t* Cell.cc (Cell Cell::diag (void) const): delete.\n\t(Cell Cell::diag (octave__idx_type) const):Rewrite in terms of\n\ttemplate classes function.\n\t* Cell.h (Cell diag (void) const): delete.\n\n\t* ov.h (octave_value diag (octave_idx_type) const): New method.\n\t* ov-base.h (virtual octave_value diag (octave_idx_type) const):\n\tNew virtual method.\n\t* ov-base.cc (octave_value octave_base_value::diag\n\t(octave_idx_type) const): New default method.\n\n\t* ov-base-mat.h (octave_value diag (octave_idx_type) const): New\n\tmethod.\n\t* ov-base-sparse.h (octave_value diag (octave_idx_type) const): New\n\tmethod.\n\t* ov-base-scalar.h (octave_value diag (octave_idx_type) const): New\n\tmethod.\n\t* ov-range.h (octave_value diag (octave_idx_type) const): New\n\tmethod.\n\n\t* data.cc (make_diag, make_spdiag): Delete.\n\t(Fdiag): Rewrite in terms of octave_value diag function.\n\n\t* data.cc (static octave_value make_diag (const Cell&,\n\toctave_idx_type)): New instantiation of template function.\n\t(static octave_value make_diag (const octave_value&,\n\toctave_idx_type)): Allow cell arrays.\n\n\t* Cell.cc (Cell Cell::diag (void) const, Cell Cell::diag\n\t(octave__idx_type)): New methods for diagonal matrices.\n\t* Cell.h (Cell Cell::diag (void) const, Cell Cell::diag\n\t(octave__idx_type)): Declare them.\n\n2008-03-18  David Bateman  <dbateman@free.fr>\n\n\t* ov-re-mat.cc (lgamma): Convert to a allow negative arguments.\n\t* ov-re-sparse.cc (lgamma): ditto.\n\t* ov-scalar.cc (lgamma): ditto.\n\n\t* DLD-FUNCTIONS/minmax.cc: 64-bit indexing fix.\n\n2008-03-13  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr-fcn.cc (octave_user_function::octave_user_function):\n\tHandle num_named_args in initialization list instead of functinon body.\n\n\t* octave.gperf: Eliminate varargin and varargout keywords.\n\t* lex.l (is_keyword_token): Eliminate varargin_kw and varargout_kw\n\tfrom switch statement.\n\t* parse.y (return_list): Eliminate special cases for VARARGOUT.\n\tCall validate on tree_parameter_list object.\n\t(param_list1): Likewise, for VARARGIN.\n\t* pt-misc.cc (tree_parameter_list::validate): New function.\n\t(tree_parameter_list::mark_varargs_only): Now private.\n\t(tree_parameter_list::mark_varargs): Now private.\n\t* pt-misc.h (tree_parameter_list::validate): Provide decl.\n\n2008-03-12  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (Vwhos_line_format): Omit print_dims parameter.\n\tFix doc string in Vwhos_line_format DEVAR.\n\t(symbol_record_name_compare): Delete unused function.\n\t(whos_parameter::dimensions): Delete struct field.\n\t(symbol_info_list): New class.\n\t(dimensions_string_req_first_space, make_dimensions_string,\n\tdimensions_string_req_total_space): Delete.\n\t(parse_whos_line_format): Move functionality to new\n\tsymbol_info_list class.\n\t(print_symbol_info_line): Move functionality to new\n\tsymbol_info_list::struct symbol_info::displaly_line method.\n\t(do_who): Simplify with new symbol_info_list class.\n\tHandle index expressions in addition to symbol names.\n\n\t* DLD-FUNCTIONS/dlmread.cc (Fdlmread): Fix separator detection.\n\n2008-03-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/eig.cc (Feig): Handle possible error from EIG.\n\t* DLD-FUNCTIONS/qp.cc (qp, Fqp): Likewise.\n\t* xpow.cc (xpow): Likewise.\n\n2008-03-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/dlmread.cc: Style fixes.\n\n2008-03-11  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/dlmread.cc: Function ported from octave forge. Add\n\tspreadsheet style ranges.\n\t* Makefile.in (DLD_XSRC): Add dlmread.cc.\n\n2008-03-10  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxCreateLogicalScalar): Argument is now mxLogical.\n\n\t* data.cc (Fisfloat): New function.\n\t* ov.h (octave_value::is_float_type): Ditto.\n\t* ov-base.h (octave_base_value::is_float_type): Ditto.\n\t* ov-complex.h (octave_complex): Ditto.\n\t* ov-cx-mat.h (octave_complex_matrix): Ditto.\n\t* ov-cx-sparse.h (octave_sparse_complex_matrix): Ditto.\n\t* ov-range.h (octave_range): Ditto.\n\t* ov-re-mat.h (octave_matrix): Ditto.\n\t* ov-re-sparse.h (octave_sparse_matrix): Ditto.\n\t* ov-scalar.h (octave_scalar): Ditto.\n\n\t* mxarray.h.in (mxLogical): Use unsigned char instead of int.\n\tFrom Antwerpen, G. (Gert) van <gert.vanantwerpen@tno.nl>.\n\n2008-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (octave_struct::print_raw): Don't print contents fo\n\tstruct arrays that have more than one element.\n\n2008-03-06  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): Document that\n\tthe initial interpretation of a positive definite return from\n\tmatrix_type is that the matrix is \"probably\" positive definite and\n\tnot certainly so.\n\n2008-03-06  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y: Move tests here from test/test_eval.m.\n\t* DLD-FUNCTIONS/fft.cc: Move tests here from test/test_signal.m.\n\t* DLD-FUNCTIONS/dassl.cc: Move tests here from test/test_diffeq.m.\n\t* DLD-FUNCTIONS/lsode.cc: Move tests here from test/test_diffeq.m.\n\t* DLD-FUNCTIONS/quad.cc: Move tests here from test/test_quad.m.\n\t* DLD-FUNCTIONS/time.cc: Move tests here from test/test_system.m.\n\n2008-03-06  Alexander Barth  <barth.alexander@gmail.com>\n\n\t* DLD-FUNCTIONS/__lin_interpn__.cc (lookup):\n\tHandle decreasing coordinate values.\n\n2008-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/chol.cc (Fcholupdate): Adjust code to meet\n\tOctave's coding guidelines.\n\n\t* DLD-FUNCTIONS/qr.cc (Fqrupdate, Fqrinsert, Fqrdelete): Adjust\n\tcode to meet Octave's coding guidelines.\n\t* DLD-FUNCTIONS/qr.cc (Fqrdelete): Fix incorrect test.\n\n\t* DLD-FUNCTIONS/qr.cc (Fqrinsert, Fqrdelete): Modify to use\n\t0-based indexing in liboctave's QR classes.\n\n2008-03-04  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/chol.cc (Fcholupdate): New function.\n\n\t* DLD-FUNCTIONS/qr.cc (Fqrupdate, Fqrinsert, Fqrdelete):\n\tNew functions.\n\n2008-03-04  Ryan Rusaw  <rrusaw@gmail.com>\n\n\t* toplev.h (octave_call_stack::element): New static function.\n\t(octave_call_stack::cs): Now std::deque instead of std::list.\n\n\t* pt-stmt.cc (curr_statement, curr_caller_statement): Delete.\n\t* pt-stmt.h: Delete decls.\n\n\t* pt-stmt.h, pt-stmt.cc (tree_statement_stack): New class.\n\n\t* pt-stmt.cc (tree_statement::eval): Use tree_statement_stack\n\tinstead of curr_statement variable.\n\n\t* ov-usr-func.cc (octave_user_function::do_multi_index_op):\n\tDon't set curr_caller_statement.\n\n\t* error.cc (verror, pr_where): Call tree_statement_stack::current_line\n\tand tree_statement_stack::current_column instead of\n\tinstead of curr_statement->line and curr_statement->column.\n\t* input.cc (get_user_input): Likewise.\n\n2008-02-27  John P. Swensen  <jpswensen@gmail.com>\n\n\t* debug.cc (get_user_function): Call symtab::find_function instead\n\tof symtab::find_user_function.\n\n2008-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (do_read): Stop reading if seek fails.\n\n2008-02-26  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-int.cc (octave_base_int_helper,\n\toctave_base_int_helper_traits): New templates and specializations.\n\t(octave_base_int_matrix<T>::convert_to_str_internal,\n\toctave_base_int_matrix<T>::convert_to_str_internal): Use them.\n\n\t* DLD-FUNCTIONS/rand.cc (do_rand): Pass name of calling function\n\tto octave_rand::state.\n\n\t* variables.cc (bind_ans): Handle cs-lists recursively.\n\n\t* ov-cs-list.h, ov-cs-list.cc (octave_cs_list::print,\n\toctave_cs_list::print_raw): Delete.\n\n2008-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* Cell.cc (Cell::map): New function.\n\t* Cell.h (Cell::map): Declare.\n\t(xisalnum, xisalpha, xisascii, xiscntrl, xisdigit,\n\txisgraph, xislower, xisprint, xispunct, xisspace, xisupper,\n\txisxdigit, xtoascii, xtolower, xtoupper): New mapper functions.\n\t(ctype_mapper): New private typedef.\n\n\t* ov-cell.h (xisalnum, xisalpha, xisascii, xiscntrl, xisdigit,\n\txisgraph, xislower, xisprint, xispunct, xisspace, xisupper,\n\txisxdigit, xtoascii, xtolower, xtoupper): New mapper functions.\n\n2008-02-25  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* ov-scalar.cc (octave_scalar::round): Use xround instead of ::round\n\tin mapper implementation.\n\n2008-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base.cc (UNDEFINED_MAPPER, STRING_MAPPER): New macros.  Use\n\tthem to define mapper functions.\n\n\t* mappers.cc (Fisalnum, Fisalpha, Fisascii, Fiscntrl, Fisdigit,\n\tFisgraph, Fislower, Fisprint, Fispunct, Fisspace, Fisupper,\n\tFisxdigit, Ftoascii, Ftolower, Ftoupper):\n\tUse DEFUNX to define ctype mapper functions.\n\tUse new function names.\n\n\t* ov-base.h, ov-base.cc, ov-str-mat.h, ov-str-mat.cc:\n\tPrepend x to ctype mapper function names.\n\n\t* graphics.h.in (row_vector_property::row_vector_property):\n\tSet default constraints here.\n\t(row_vector_property::add_constraint): New function.\n\t(row_vector_property::validate): Delete decl.\n\t(axes::properties::init): Use single-arg add_constraint function\n\tfor xlim, ylim, zlim, clim, and alim properties.\n\n\t* graphics.cc (row_vector_property::validate): Delete.\n\n\t* graphics.cc (axes::properties::update_camera,\n\taxes::properties::update_aspectratios):\n\tAvoid shadow warnings from GCC.\n\n\t* graphics.h.in (base_properties::get_bounding_box):\n\tAvoid unused argument warning from GCC.\n\n\t* graphics.h.in (array_property::add_constraint): Arg is now const\n\treference, not value.\n\n\t* graphics.h.in, graphics.cc (class row_vector_property): New class.\n\t(axes::properties): xlim, ylim, zlim, clim, alim, xtick, ytick,\n\tztick properties are now row_vector_property objects instead of\n\tarray_property objects.\n\n\t* genprops.awk: Special case row_vector_property in the same way\n\tas array_property.\n\n2008-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/ccolamd.cc, DLD-FUNCTIONS/colamd.cc,\n\tDLD-FUNCTIONS/convhulln.cc, DLD-FUNCTIONS/dmperm.cc,\n\tDLD-FUNCTIONS/qz.cc, DLD-FUNCTIONS/regexp.cc,\n\tDLD-FUNCTIONS/symbfact.cc, zfstream.h, zfstream.cc:\n\tUse 0 instead of NULL.\n\n2008-02-22  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/chol.c (Fchol, Fcholinv, Fchol2iinv): Treat\n\tsparse matrices. Add the \"lower\" and \"vector\" flags.\n\t* DLD-FUNCTIONS/inv.c (Finv): Treat sparse matrices.\n\t* DLD-FUNCTION/sparse.cc (static bool is_sparse (const\n\toctave_value&)): Remove and use arg.is_sparse_type () instead.\n\t(Fspcumprod, Fspcumsum, Fspprod, spsum, spsumsq, spdiag): Remove.\n\t* DLD-FUNCTIONS/splu.cc: Remove.\n\t* DLD-FUNCTIONS/lu.cc: Treat sparse matrices, Add \"vector\" flag.\n\t* DLD-FUNCTIONS/spchol.cc: Move to symbfact.cc\n\t* DLD-FUNCTIONS/symbfact.cc: Remove cholesky functions Fspchol,\n\tFspcholinv, Fspchol2inv.\n\t* DLD-FUNCTIONS/luinc.cc: Modify for new sparse LU\n\tconstructors. Ass the 'vector' flag.\n\t* DLD-FUNCTIONS/spparms.cc: Add the sum_tol flag.\n\n\t* Makifile.in (DLD_XSRC): Remove spchol.cc, splu.cc and add\n\tsymbfact.cc\n\t* data.cc (NATIVE_REDUCTION): Treat sparse matrices\n\t(DATA_REDUCTION): Ditto.\n\t(template <class T> static octave_value make_spdiag (const T&,\n\toctave_idx_type)): New template function for sparse diag\n\tfunction. Instantiate it.\n\t(static octave_value make_diag (const octave_value&,\n\toctave_idx_type): Use make_spdiag for sparse matrice.\n\t(Fatan2): Compatibility fixes for mixed full/sparse matrices.\n\n2008-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fsolve.cc (fsolve_user_jacobian):\n\tCheck dimensions of user-supplied Jacobian matrix.\n\t(fsolve_user_function): Check for non-square systems.\n\n2008-02-20  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (map_d_m, map_m_d, map_m_m, Fatan2, Ffmod):\n\tHandle N-d arrays.\n\n\t* ov-bool-mat.h (octave_bool_matrix (const Array2<bool>&)): Delete.\n\n2008-02-20  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/det.cc, DLD-FUNCTIONS/find.cc,\n\t* DLD-FUNCTIONS/minmax.cc, DLD-FUNCTIONS/qr.cc:\n\tTreat sparse matrices.\n\n\t* DLD-FUNCTIONS/sparse.cc (Fspmin, Fspmax, Fatan2): Remove functions.\n\n\t* DLD-FUNCTIONS/dmperm.cc: Rename from spqr.cc.\n\t(Fspqr): Delete function.\n\n\t* DLD-FUNCTIONS/spqr.cc, DLD-FUNCTIONS/spdet.cc,\n\tDLD-FUNCTIONS/spfind.cc: Remove.\n\n\t* Makefile.in (DLD_XSRC): Add dmperm.cc to the list.\n\tDelete det.cc, find.cc, minmax.cc, and qr.cc from the list.\n\n\t* Makefile.in (OV_SRC): Remove ov-mapper.cc.\n\t(OV_INCLUDES): Remove ov-mapper.h.\n\t(DEFUN_PATTERN): No longer accept DEFUN_MAPPER as valid.\n\t* ov-mapper.cc, ov-mapepr.h: Delete, remove all includes of\n\tov-mapper.h from all files.\n\n\t* op-b-sbm.cc, op-bm-sbm.cc, op-smb-b.cc, op-sbm-bm.cc: Include\n\tov-bool-sparse.h.\n\n\t* defun-int.h (DEFUN_MAPPER_INTERNAL, install_builtin_mapper):\n\tRemove.\n\t* defun.cc (install_builtin_mapper): Ditto.\n\t* defun.h (DEFUN_MAPPER): Remove.\n\n\t* mappers.cc: Rewrite all mapper function using DEFUN and newly\n\tintroduced octave_value mapper functions.\n\t(dummyp, xabs, xisalnum, xisascii, xiscntrl, xisdigit,\n\txisgraph, xislower, xisprint, xispunct, xisspace, xisupper,\n\txtoascii, xtolower, xtoupper, xconj, ximag, xreal): Remove\n\tstatic wrapper functions.\n\n\t* mkbuiltins (XDEFUN_MAPPER_INTERNAL, install_builtin_functions):\n\tRemove.\n\t* mkgendoc (XDEFUN_MAPPER_INTERNAL): Remove.\n\n\t* ov.cc (octave_mapper::register_type): Remove.\n\n\t* ov.h (abs, acos, acosh, angle, arg, asin, asinh, atan, atanh,\n\tceil, conj, cos, cosh, erf, erfc, exp, finite, fix, floor, gamma,\n\timag, isinf, isna, isnan, lgamma, log, log10, real, round, signum,\n\tsin, sinh, sqrt, tan, tanh, isalnum, isalpha, isascii, iscntrl,\n\tisdigit, isgraph, islower, isprint, ispunct, isspace, isupper,\n\tisxdigit, toascii, tolower, toupper):\n\tNew octave_value mapper\tfunctions.\n\n\t* ov-base.h (abs, acos, acosh, angle, arg, asin, asinh, atan,\n\tatanh, ceil, conj, cos, cosh, erf, erfc, exp, finite, fix, floor,\n\tgamma, imag, isinf, isna, isnan, lgamma, log, log10, real, round,\n\tsignum, sin, sinh, sqrt, tan, tanh, isalnum, isalpha, isascii,\n\tiscntrl, isdigit, isgraph, slower, isprint, ispunct, isspace,\n\tisupper, isxdigit, toascii, tolower, toupper):\n\tNew virtual mapper functions.\n\t* ov-base.cc (abs, acos, acosh, angle, arg, asin, asinh, atan,\n\tatanh, ceil, conj, cos, cosh, erf, erfc, exp, finite, fix, floor,\n\tgamma, imag, isinf, isna, isnan, lgamma, log, log10, real, round,\n\tsignum, sin, sinh, sqrt, tan, tanh, isalnum, isalpha, isascii,\n\tiscntrl, isdigit, isgraph, slower, isprint, ispunct, isspace,\n\tisupper, isxdigit, toascii, tolower, toupper):\n\tBase versions of mapper functions.\n\n\t* ov-bool-mat.h (abs, acos, acosh, angle, arg, asin, asinh, atan,\n\tatanh, ceil, conj, cos, cosh, erf, erfc, exp, finite, fix, floor,\n\tgamma, imag, isinf, isna, isnan, lgamma, log, log10, real, round,\n\tsignum, sin, sinh, sqrt, tan, tanh):\n\tMapper function recast boolen matrix as double.\n\t* ov-bool.h (abs, acos, acosh, angle, arg, asin, asinh, atan,\n\tatanh, ceil, conj, cos, cosh, erf, erfc, exp, finite, fix, floor,\n\tgamma, imag, isinf, isna, isnan, lgamma, log, log10, real, round,\n\tsignum, sin, sinh, sqrt, tan, tanh): Ditto.\n\t* ov-bool-sparse.h (abs, acos, acosh, angle, arg, asin, asinh,\n\tatan, atanh, ceil, conj, cos, cosh, erf, erfc, exp, finite, fix,\n\tfloor, gamma, imag, isinf, isna, isnan, lgamma, log, log10, real,\n\tround, signum, sin, sinh, sqrt, tan, tanh): Ditto.\n\t(char_array_value): New method to convert to charNDArray.\n\t* ov-bool-sparse.cc (char_array_value): New method to convert to\n\tcharNDArray.\n\t* ov-complex.cc (char_array_value): ditto.\n\t(xabs, ximag, xreal): Static wrapper functions.\n\t(abs, acos, acosh, angle, arg, asin, asinh, atan, atanh, ceil,\n\tconj, cos, cosh, exp, finite, fix, floor, imag, isinf, isna,\n\tisnan, log, log10, real, round, signum, sin, sinh, sqrt, tan,\n\ttanh): New mapper methods.\n\t* ov-complex.h: Provide decls.\n\n\t* ov-cx-mat.cc (char_array_value): New method to convert to\n\tcharNDArray.\n\t(xabs, ximag, xreal): Static wrapper functions.\n\t(abs, acos, acosh, angle, arg, asin, asinh, atan, atanh, ceil,\n\tconj, cos, cosh, exp, finite, fix, floor, imag, isinf, isna,\n\tisnan, log, log10, real, round, signum, sin, sinh, sqrt, tan,\n\ttanh): New mapper methods.\n\t* ov-cx-mat.h: Provide decls.\n\n\t* ov-cx-sparse.cc (char_array_value): New method to convert to\n\tcharNDArray.\n\t(xabs, ximag, xreal): Static wrapper functions.\n\t(abs, acos, acosh, angle, arg, asin, asinh, atan, atanh, ceil,\n\tconj, cos, cosh, exp, finite, fix, floor, imag, isinf, isna,\n\tisnan, log, log10, real, round, signum, sin, sinh, sqrt, tan,\n\ttanh): New mapper methods.\n\t* ov-cx-sparse.h: Provide decls.\n\n\t* ov-intx.h (abs, signum, imag, ceil, conj, fix, floor, real,\n\tround, finite, isinf, isna, isnan): Define for both matrix and\n\tscalar classes.\n\n\t* ov-range.h (abs, acos, acosh, angle, arg, asin, asinh, atan,\n\tatanh, ceil, conj, cos, cosh, erf, erfc, exp, finite, fix, floor,\n\tgamma, imag, isinf, isna, isnan, lgamma, log, log10, real, round,\n\tsignum, sin, sinh, sqrt, tan, tanh): New mapper functions.\n\n\t* ov-re-mat.cc (any_element_less_than): Static function to check if\n\tany elemet was less than a value,\n\t(any_element_greater_than): Ditto with greater than.\n\t(abs, acos, acosh, angle, arg, asin, asinh, atan, atanh, ceil,\n\tconj, cos, cosh, erf, erfc, exp, finite, fix, floor, gamma, imag,\n\tisinf, isna, isnan, lgamma, log, log10, real, round, signum, sin,\n\tsinh, sqrt, tan, tanh): New mapper functions.\n\t* ov-re-mat.h: Provide decls.\n\n\t* ov-scalar.cc (any_element_less_than): Static function to check if\n\tany elemet was less than a value,\n\t(any_element_greater_than): ditto with greater than.\n\t(abs acos acosh angle arg asin asinh atan atanh\n\tceil conj cos cosh erf erfc exp finite fix floor gamma imag\n\tisinf isna isnan lgamma log log10 real round signum sin sinh\n\tsqrt tan tanh): New mapper functions.\n\t* ov-scalar.h: Provide decls.\n\n\t* ov-str-mat.cc (xisalnum, xisascii, xiscntrl, xisdigit,\n\txisgraph, xislower, xisprint, xispunct, xisspace, xisupper,\n\txtoascii, xtolower, xtoupper): New static wrapper functions.\n\t(isalnum, isalpha, isascii, iscntrl, isdigit, isgraph, islower,\n\tisprint, ispunct, isspace, isupper, isxdigit, toascii, tolower,\n\ttoupper): New mapper methods.\n\t* ov-str-mat.h: Provide decls.\n\n2008-02-18  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (Fatan2): Reject arguments that are integer types.\n\n2008-02-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* DLD-FUNCTIONS/qr.cc: Doc fix.\n\n2008-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h\n\t(symbol_table::fcn_info::fcn_info_rep::clear_unlocked_functions):\n\tsymbol_table::fcn_info::fcn_info_rep::clear_cmdline_function,\n\tsymbol_table::fcn_info::fcn_info_rep::clear_autoload_function):\n\tNew functions.\n\t(symbol_table::fcn_info::fcn_info_rep::clear_user_function):\n\tDon't clear locked functions.\n\t(symbol_table::fcn_info::fcn_info_rep::clear_mex_function):\n\tCall clear_user_function instead of setting function_on_path directly.\n\t(symbol_table::fcn_info::fcn_info_rep::clear):\n\tUse new functions to do the real work.\n\n\t* ov.h (octave_value::lock, octave_value::unlock,\n\toctave_value::islocked): New functions.\n\t* ov-base.cc (octave_base_value::lock, octave_base_value::unlock):\n\tNew functions.\n\t* ov-base.h Provide decls.\n\t(octave_base_value::islocked): New function.\n\t* ov-fcn.h (octave_function::islocked): Now const.\n\n2008-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op):\n\tCatch possible octave_execution_exception.\n\t* ov-mex-fcn.cc (octave_mex_function::do_multi_index_op): Likewise.\n\t* ov.cc (do_binary_op, do_cat_op, do_unary_op,\n\toctave_value::do_non_const_unary_op): Likewise.\n\n2008-02-14  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/qz.cc:\n\tDon't check f77_exception_encountered.\n\n\t* sighandlers.cc (user_abort): If interrupting immediately, set\n\toctave_interrupt_state if it is not already set.\n\n\t* pt-stmt.cc (tree_statement::eval): Catch execution exceptions.\n\n\t* octave.cc (lo_error_handler): New static function.\n\t(initialize_error_handlers): Set liboctave_error_handler to\n\tlo_error_handler, not error.\n\n\t* DLD-FUNCTIONS/urlwrite.cc (urlget): Call octave_rethrow_exception\n\tinstead of octave_throw_interrupt_exception.\n\t* utils.cc (BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF):\n\tLikewise.\n\n2008-02-12  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in: Implement the cdatamapping property in patch and\n\timage objects.\n\n2008-02-12  John W. Eaton  <jwe@octave.org>\n\n\t* pt-loop.cc (tree_simple_for_command::eval): Compute range\n\telement with multiplication.\n\n2008-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in ($(MAKEDEPS)): Skip dependencies if omit_deps is defined.\n\n2008-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (set_range_format): Eliminate sign arg.\n\tChange all callers.\n\n2008-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (octave_struct::subsref): Allow Cell::index to resize.\n\n\t* input.cc (interactive_input): Eliminate debug arg.  Change All uses.\n\t(get_user_input): Don't process input_buf if there is an error.\n\tCall reset_error_handler instead of setting error_state to 0.\n\n2008-02-08  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (callback_property::execute): New static\n\thelper method (useful to execute callbacks by name).\n\t* graphics.cc (callback_property::execute): Likewise.\n\t(execute_callback): Avoid undefined argument when executing\n\tcallback. Do not use arguments when the callback is a string.\n\n2008-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* ov-range.h (octave_range::sort): New functions.\n\n2008-02-07  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (DLD_XSRC): Delete spkron.cc.\n\t* DLD-FUNCTIONS/spkron.cc: Delete.\n\t* DLD-FUNCTIONS/kron.cc: Include here and dispatch to the sparse\n\tversion if either argument is sparse.\n\n2008-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (parse.cc): Also use --defines option for bison.\n\n2008-02-06  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.cc (axes::properties::set_defaults): Set default axes\n\tcolor to white.\n\n2008-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (parse.cc): Use \"-o $@\" instead of renaming y.tab.c.\n\t(maintainer-clean): Don't remove y.tab.c.\n\n\t* Makefile.in (parse.cc : parse.y): Use mv instead of move-if-change.\n\t(stamp-prereq, stamp-liboctave-prereq): Eliminate.\n\t(clean): Don't remove stamp-prereq and stamp-liboctave-prereq.\n\t(OPT_BASE, OPT_IN, OPT_INC): New macros.\n\t(OPT_HANDLERS): Define in terms of OPT_BASE.\n\t($(OPT_INC) : %.h : %.in): New pattern rule.\n\t(PREREQ): New macro.\n\t($(MAKEDEPS)): Simplify with $(PREREQ).\n\n2008-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in: Unconditionally include $(MAKEDEPS).\n\tMark $(MAKEDEPS) as .PHONY targets if omit_deps is true.\n\n2008-02-05  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (base_properties::get_boundingbox): New method.\n\t(figure::properties::get_boundingbox): Overload method.\n\t(axes::properties::get_boundingbox): Likewise.\n\t* graphics.cc (figure::properties::get_boundingbox): Return a\n\tleft-to-right/top-to-bottom bounding box rectangle.\n\t(axes::properties::get_boundingbox): Likewise.\n\t(axes::properties::update_camera): Remove backend access and\n\tuse the new axes bounding box.\n\n2008-02-04  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h.in (axes::properties::update_xlim,\n\taxes::properties::update_ylim, axes::properties::update_zlim):\n\tNew update methods.\n\n\t* graphics.cc (axes::properties::calc_ticks): New function.\n\t(axes::properties::magform): New function.\n\t(axes::update_axis_limits): Call update_{x,y,z}lims if\n\tappropriate.\n\n2008-02-04  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (base_graphics_backend::get_screen_size,\n\tgraphics_backend::get_screen_size): New methods.\n\t(graphics_backend::available_backends): Export symbol.\n\t(class figure::properties, class axes::properties): Export classes.\n\t(figure::properties::get_boundingbox): New utility method.\n\t(figure::properties::position): Use valid default position.\n\t(axes::properties::gridlinestyle,\n\taxes::properties::minorgridlinestyle):\n\tUse dotted line style as default.\n\t* graphics.cc (default_figure_position): New static function.\n\t(gnuplot_backend::get_screen_size): New method.\n\t(figure::properties::get_boundingbox): New utility method.\n\n2008-02-02  Shai Ayal  <shaiay@users.sourceforge.org>\n\n\t* graphics.h.in (base_scaler::~base_scalar): New virtual destructor.\n\t* graphics.cc (axes::properties::update_camera): Tag abs with std.\n\n\t* graphics.h.in (graphics_backend::find_backend): New function.\n\t(class figure): Add __backend__ property and set method.\n\n2008-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (do_type): Don't print dyamically loaded function files.\n\n\t* ov-fcn.h (octave_function::is_dynamically_loaded_function): Delete.\n\n2008-02-01  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (Fset_variable, Fvariable_value):\n\tNew functions, but commented out for now.\n\n2008-01-30  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (axes::properties::get_transform_matrix,\n\taxes::properties::get_inverse_transform_matrix,\n\taxes::properties::get_opengl_matrix_1,\n\taxes::properties::get_opengl_matrix_2,\n\taxes::properties::get_transform_zlim): New accessors.\n\t(base_properties::is_clipping): New accessor.\n\t(class graphics_xform): New class encapsulating axes transformation.\n\t(axes::properties::get_transform): New method returning a\n\tgraphics_xform object.\n\t* graphics.cc (class graphics_xform): New class.\n\n2008-01-31  David Bateman  <dbateman@free.fr>\n\n\t* ov.cc (octave_value::octave_value (const ArrayN<bool>&),\n\toctave_value::octave_value (const Sparse<bool>&, const MatrixType &),\n\toctave_value::octave_value (const ArrayN<std::streamoff>&)): New\n\tconstructors.\n\t* ov.h: (octave_value (const ArrayN<bool>&),\n\toctave_value (const Sparse<bool>&, const MatrixType &),\n\toctave_value (const ArrayN<std::streamoff>&)): Declare them.\n\t(octave_value sort (octave_idx_type, sortmode) const, octave_value\n\tsort (Array<octave_idx_type> &, octave_idx_type, sortmode) const):\n\toctave_value sort method.\n\n\n\t* ov-base.cc (sort): Base versions of teh octave_value sort methods.\n\t* ov-base.h (sort): Declare the octave_value sort methods\n\t* ov-base-scalar.h (sort): Simple sort methods for scalars.\n\t* ov-base-mat.h, ov-base-sparse.h (sort): Sort methods calling\n\tunderlying array or sparse sort methods.\n\t* ov-str-mat.h (sort): String specific sort methods.\n\n\t* TEMPLATE-INST/Array-tc.cc: Instantiate the array sort methods.\n\t* ov-streamoff.h (sort): Sort versions returning and error.\n\t* oct-stream.cc, ov-typeinfo.cc, Array-os.cc: Null instantiation\n\tof array sort methods.\n\n\t* Makefile.in (DLD_XSRC): Remove sort.cc\n\t* DLD-FUNCTIONS/sort.cc: Remove\n\t* data.cc (Fsort): New function using octave_value sort methods\n\tfor the sorting. Add tests.\n\n2008-01-30  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* pager.cc (Fmore): Doc fix.\n\n2008-01-28  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* genprops.awk: Add update ('u') modifier and document the\n\treadonly ('r') modifier.\n\t* graphics.h.in (class base_scaler, class lin_scaler, class\n\tlog_scaler, class scaler): New classes to make abstraction of the\n\taxis scale.\n\t(base_graphics_backend::get_screen_resolution,\n\tgraphics_backend::get_screen_resolution): New methods.\n\t(axes::properties::sx, axes::properties::sy,\n\taxes::properties::sz): New scaler fields.\n\t(axes::properties::get_x_scaler, axes::properties::get_y_scaler,\n\taxes::properties::get_z_scaler): New accessors.\n\t(axes::properties::x_render, axes::properties::x_render_inv,\n\taxes::properties::x_gl_mat1, axes::properties::x_gl_mat2,\n\taxes::properties::x_zlim): New utility Matrix fields.\n\t(axes::properties::get_boundingbox,\n\taxes::properties::update_camera,\n\taxes::properites::update_aspectratios,\n\taxes::properties::update_transform,\n\taxes::properties::update_xscale, axes::properties::update_yscale,\n\taxes::properties::update_zscale, axes::properties::update_view,\n\taxes::properties::update_xdir, axes::properties::update_ydir,\n\taxes::properties::update_zdir): New updater methods.\n\t(axes::properties::init): Initialize sx, sy, sz and x_zlim correctly.\n\t(axes::properties::position): Use valid default position value.\n\t(axes::properties::xscale, axes::properties::yscale,\n\taxes::properties::zscale, axes::properties::xdir,\n\taxes::properties::ydir, axes::properties::zdir,\n\taxes::properties::view): Add updater ('u') property modifier.\n\t* graphics.cc (default_axes_position, default_axes_outerposition):\n\tNew initializers.\n\t(convert_position): New utility function to convert position\n\taccording to specified units.\n\t(gnuplot_backend::get_screen_resolution): New method.\n\t(axes::properties::set_defaults): Initilize recently added properties.\n\t(xform_matrix, xform_vector, transform, xform_scale,\n\txform_translate, scale, translate, xform, normalize, dot, cross,\n\tunit_cube, cam2xform, xform2cam): New inline transformation\n\tutility functions.\n\t(axes::properties::update_camera,\n\taxes::properties::update_aspectratios,\n\taxes::properties::get_boundingbox): New updater methods for\n\tcomputing transformation matrices.\n\t(axes::update_axis_limits): Update transformation data.\n\n2008-01-28  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (BEGIN_CHAR_CLASS_CONVERSION): Handle width properly.\n\t(OCTAVE_SCAN) [__GNUG__ && ! CXX_ISO_COMPLIANT_LIBRARY]:\n\tDelete special case.\n\n2008-01-25  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/rand.cc (Frandp): Relax relative error on randp\n\ttests.\n\n2008-01-25  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (base_properties::get_backend,\n\tbase_graphics_object::get_backend, graphics_backend::get_backend):\n\tNew methods for convenient access to the backend.\n\t(figure::get_backend, figure::set_backend): Remove.\n\t* graphics.cc (base_properties::get_backend): New method.\n\t(Fdrawnow): Use graphics_object::get_backend to simplify code.\n\n2008-01-24  Pascal Dupuis  <Pascal.Dupuis@worldonline.be>\n\n\t* mxarray.h.in: Include <cstring>.\n\n2008-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (clear_drawnow_request): New function.\n\t(Fdrawnow): Add it to the unwind_protect stack.\n\n\t* input.cc (Vdrawnow_requested): No longer static.\n\t* input.h: Provide decl.\n\t* graphics.cc (Fdrawnow, Fset, make_graphics_object):\n\tUse Vdrawnow_requested directly.\n\n\t* toplev.cc (octave_add_atexit_function,\n\toctave_remove_atexit_function): New functions.\n\t(Fatexit): Use them.\n\t* graphics.cc (Fdrawnow): Call octave_add_atexit_function instead\n\tof using eval.\n\t* toplev.h (octave_add_atexit_function,\n\toctave_remove_atexit_function): Provide decls.\n\n2008-01-22  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (base_properties::is_visible,\n\tbase_properties::set_modified): New accessors.\n\t(class base_graphics_backend, class graphics_backend): New classes\n\tfor handling octave/backend interaction.\n\t(figure::properties::close): Add \"pop\" argument controlling\n\twhether the figure should be popped from the list of existing figures.\n\t(class figure::properties): New backend field and accessors, holding\n\tthe graphics backend associated with the figure.\n\t* graphics.cc (class gnuplot_backend): New class for the default\n\tgnuplot backend.\n\t(figure::properties::close): Add \"pop\" argument and transfer the\n\tfigure closing to the associated backend.\n\t(Fdrawnow): New builtin function, converted from drawnow.m.\n\n2008-01-19  John W. Eaton  <jwe@octave.org>\n\n\t* genprops.awk (emit_source): Use \"pname\" for property name argument.\n\n2008-01-19  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h.in (class figure::properties): New properties:\n\talphamap, currentcharacter, currentobject, current_point,\n\tdockcontrols, doublebuffer, filename, integerhandle,\n\tinverthardcopy, keypressfcn, keyreleasefcn, menubar, mincolormap,\n\tname, numbertitle, paperunits, paperposition, paperpositionmode,\n\tpapersize, papertype, pointer, pointershapecdata,\n\tpointershapehotspot, position, renderer, renderermode, resize,\n\tresizefcn, selectiontype, toolbar, units, windowbuttondownfcn,\n\twindowbuttonmotionfcn, windowbuttonupfcn, windowbuttonwheelfcn,\n\twindowstyle, wvisual, wvisualmode, xdisplay, xvisual, xvisualmode,\n\tbuttondownfcn.\n\n2008-01-19  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (base_properties::beingdeleted,\n\tbase_properties::is_beingdeleted,\n\tbase_properties::get_beingdeleted,\n\tbase_properties::set_beingdeleted):\n\tAdd beingdeleted property and accessors.\n\t* graphics.cc (base_properties::get): Likewise.\n\t(gh_manager::free): Set beingdeleted to \"on\" when freeing an object.\n\t* genprops.awk: Skip C++-style comments in property declaration.\n\n\t* graphics.h.in (class axes::properties): New properties: alim,\n\talimmode, xminortick, yminortick, zminortick, ambientlightcolor,\n\tcameraposition, cameratarget, cameraupvector, cameraviewangle,\n\tcamerapositionmode, cameratargetmode, cameraupvectormode,\n\tcameraviewanglemode, currentpoint, drawmode, fontangle, fontname,\n\tfontsize, fontweight, fontunits, gridlinestyle,\n\tminorgridlinestyle, linestyleorder, linewidth, plotboxaspectratio,\n\tplotboxaspectratiomode, projection, tickdir, tickdirmode,\n\tticklength, tightinset, units, x_viewtransform,\n\tx_projectiontransform, x_viewporttransform, x_normrendertransform,\n\tx_rendertransform.\n\t* genprops.awk: Handle new readonly modifier 'r'.\n\n2008-01-18  Juhani Saastamoinen  <juhani@cs.joensuu.fi>\n\n\t* genprops.awk: Avoid using \"default\" as a variable name.\n\n2008-01-17  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (data_property::get_data_limits): Reset min/max values.\n\n2008-01-17  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-inline.cc: Add tests for Finline.\n\n2008-01-17  Ben Abbott  <bpabbott@mac.com>\n\n\t* load-path.cc (F__pathorig__): Rename from Fpathdef.\n\t(Frestoredefaultpath): New function.\n\n2008-01-16  John W. Eaton  <jwe@octave.org>\n\n\t* pt-assign.cc (tree_simple_assignment::rvalue,\n\ttree_multi_assignment::rvalue): Handle assignment of\n\tcomma-separated lists.\n\n2008-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* mappers.cc (install_mapper_functions): Move test for asin here\n\tfrom test/test_arith.m.\n\n\t* graphics.h.in (class line::properties, class text::properties):\n\tRename erase_mode property to erasemode.\n\n2008-01-15  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (base_properties::remove_child,\n\tbase_properties::adopt, base_properties::update_axis_limits):\n\tMake virtual.\n\t(base_graphics_object::mark_modified,\n\tbase_graphics_object::override-defaults,\n\tbase_graphics_object::set_from_list, base_graphics_object::set,\n\tbase_graphics_object::get, base_graphics_object::get_parent,\n\tbase_graphics_object::remove_child, base_graphics_object::adopt,\n\tbase_graphics_object::reparent, base_graphics_object::defaults,\n\tbase_graphics_object::type): Add default implementation.\n\t(class root_figure, class figure, class axes, class line,\n\tclass text, class image, class patch, class surface):\n\tRemove overloaded virtual methods whose implementation is\n\tidentical to the default one.\n\n\t* genprops.awk: Handle 'h' modifier for hidden properties.\n\tReplace \"get(void)\" method with \"get(bool all = false)\" to allow\n\taccess to hidden properties.\n\n\t* graphics.h.in (base_properties::get, base_graphics_object::get,\n\tgraphics_object::get, root_figure::get, figure::get, axes::get,\n\tline::get, text::get, patch::get, surface::get, image::get):\n\tNew arg, ALL, to access hidden properties.\n\t(gh_manager::do_get_object): Do not look for invalid handles.\n\t(figure::properties::__plot_stream__,\n\tfigure::properties::__enhanced__, axes::properties::__colorbar__):\n\tMake properties hidden.\n\t(axes::properties, line::properties, text::properties,\n\tpatch::properties, surface::properties): Remove obsolete 'a'\n\tproperty modifier.\n\t* graphics.cc (base_properties::get): New arg ALL, to access\n\thidden properties.\n\t(base_properties::mark_modified): Call mark_modified only on valid\n\tparent object.\n\t(__get__): New internal function returning all properties,\n\tincluding the hidden ones.\n\n2008-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (properties::set_currentfigure,\n\tproperties::set_currentaxes): Don't convert arg to double\n\tbefore passing to graphics_handle constructor.\n\t(base_properties::remove_child): Call mark_modified if list of\n\tchildren changes.\n\n2008-01-15  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h.in (class line::properties): New properties:\n\tdisplayname, erasemode.\n\t(class text::properties) New properties: backgroundcolor,\n\tdisplayname, edgecolor, erase_mode, editing, fontunits, linestyle,\n\tlinewidth, margin, verticalalignment.\n\n2008-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::do_initialize): Start with sys_path empty.\n\t(maybe_add_path_elts): Omit path_sep_str if path is empty.\n\n\t* symtab.h (symbol_table::do_pop_context): Remove symbol_records\n\twhich have no more context.\n\t(symbol_table::symbol_record::pop_context,\n\t(symbol_table::symbol_record::symbol_record_rep::pop_context):\n\tReturn size of value_stack, or 1 if variable is persistent or global.\n\n2008-01-14  Kai Habel  <kai.habel@gmx.de>\n\n\t* graphics.h.in (class patch::properties): New properties:\n\tcdatamapping, facevertexalphadata, facevertexcdata, vertexnormals,\n\tnormalmode, facelighting, edgealpha, edgelighting,\n\tbackfacelighting, ambientstrength, diffusestrength,\n\tspecularstrength, specularexponent, specularcolorreflectance,\n\terasemode.\n\n2008-01-14  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in (gh_manager::do_make_graphics_handle,\n\tgh_manager::make_graphics_handle): New boolean parameter\n\tdo_createfcn.\n\t* graphics.cc (xcreatefcn): New static function.\n\t(gh_manager::do_make_graphics_handle): New boolean parameter\n\tdo_createfcn.  Execute createfcn callback accordingly.\n\t(make_graphics_object, F__go_figure__): Use do_createfcn\n\tparameter and call xcreatefcn\n\n\t* genprops.awk (emit_get_callback): Pass user data to execute method.\n\t* graphics.cc (execute_callback): New static function.\n\t(callback_property::validate): Make it work.\n\t(callback_property::execute): Make it work.\n\t(gh_manager::do_free): Execute delete function here.\n\t* graphics.h.in (callback_property::execute): Fix decl.\n\t(base_properties::buttondownfcn, base_properties::createfcn,\n\tbase_properties::deletefcn, base_properties::userdata): Default\n\tvalue is empty Matrix, not undefined octave_value object.\n\t(base_properties::execute_createfcn): New function.\n\t(base_properties::execute_deletefcn): New function.\n\n2007-12-13  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h.in, graphics.cc (class base_properties): New\n\tproperties: busyaction, buttondownfcn, clipping, createfcn,\n\tdeletefcn, handlevisibility, hittest, interruptible, selected,\n\tselectionhighlight, uicontextmenu, userdata, visible.\n\t(class figure): Delete visible property.\n\n2008-01-13  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* graphics.h.in: Sprinkle with OCTINTERP_API as needed.\n\t(axes::properties::xaxislocation): Allow value of zero.\n\t(axes::properties::yaxislocation): Likewise.\n\n2008-01-12  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* Makefile.in (distclean): Delete graphics-props.cc.\n\n\t* genprops.awk: Handle new graphics property classes.\n\n\t* graphics.h.in, graphics.cc: Adapt for new specific property types.\n\n2008-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (octave_config_info): Add GNUPLOT to the struct.\n\t* oct-conf.h.in (OCTAVE_CONF_GNUPLOT): New macro.\n\n2008-01-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__qp__.cc (qp): Undo part of change from\n\t2007-09-04 (compute Y at each iteration).\n\n2008-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fsolve.cc (Ffsolve): Doc fix.\n\t(hybrd_info_to_fsolve_info): Swap return values for -1 and -2 inputs.\n\n\t* DLD_FUNCTIONS/__gnuplot_raw__.l: Delete.\n\t* Makefile.in (DLD_XSRC): Remove it from the list.\n\t(BUILT_DISTFILES): Remove __gnuplot_raw__.cc from the list.\n\t(stamp-prereq): Don't depend on __gnuplot_raw__.cc.\n\t(maintainer-clean): Don't remove __gnuplot_raw__.cc.\n\t(__gnuplot_raw__.cc): Delete target.\n\t(__gnuplot_raw__.o, pic/__gnuplot_raw__.o): Delete targets.\n\n\t* mex.cc (calc_single_subscript_internal): New static function.\n\t(mxArray_octave_value::calc_single_subscript): Use it.\n\t(mxArray_matlab::calc_single_subscript): Use it.\n\n2008-01-07  John W. Eaton  <jwe@octave.org>\n\n\t* pt-except.cc (tree_try_catch_command::eval):\n\tSet Vdebug_on_error and Vdebug_on_warning to false while executing\n\ttry block.\n\n\t* error.cc (Vdebug_on_error, Vdebug_on_warning): No longer static.\n\t* error.h: Provide decls.\n\n\t* gripes.cc (gripe_wrong_type_arg (const std::string&, const\n\toctave_value&, bool)): New function.\n\t* gripes.h: Provide decl.\n\n\t* oct-stream.cc (printf_value_cache::printf_value_cache):\n\tReject structs, cells, objects, and lists.\n\t(octave_base_stream::do_printf): Quit early if printf_value_cache\n\tconstructor fails.\n\n\t* parse.y (make_anon_fcn_handle): Don't attempt to convert\n\texpression to assignment to __retval__.\n\n2008-01-07  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* ov-builtin.h (octave_builtin): Tag with OCTINTERP_API.\n\t* ov-dld-fcn.h (octave_dld_function): Likewise.\n\n\t* ov-dld-fcn.cc (octave_dld_function::create): New function.\n\t* ov-dld-fcn.h: Provide decl.\n\t* defun.h (DEFINE_FUNX_INSTALLER_FUN3): Call it instead of\n\tcreating a new octave_dld_function object directly.\n\n2008-01-04  John Swensen  <jpswensen@comcast.net>\n\n\t* debug.cc (bp_table::do_remove_all_breakpoints_in_file):\n\tAvoid calling erase on invalid bp_map iterators.\n\t(bp_table::do_remove_breakpoint): Only try to delete breakpoints\n\tif some exist.  Avoid calling erase on invalid bp_map iterators.\n\t(parse_dbfunction_params): Return early if ARGS is empty.\n\tNew arg, WHO.  Change all uses.\n\tAccept but do nothing with struct args.\n\n2008-01-04  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* variables.cc (Fclear): Doc fix.\n\n2008-01-04  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h (symbol_table:pop_scope): Avoid accessing beyond end of\n\tscope_stack.\n\n2008-01-04  David Bateman  <dbateman@free.fr>\n\n\t* ov-mapper.cc (SPARSE_MAPPER_LOOP_2): Use data method instead of\n\telem in the case where F(0) is non-zero.\n\n2007-12-28  John W. Eaton  <jwe@octave.org>\n\n\tMerge changes from object branch:\n\n\t2007-12-12  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::dir_info::get_file_list,\n\tload_path::move_method_map, load_path::remove_method_map,\n\tload_path::do_find_fcn, load_path::do_find_private_fcn,\n\tload_path::do_find_method, load_path::do_find_file,\n\tload_path::do_find_first_of, load_path::do_find_all_first_of,\n\tload_path::do_display, load_path::add_to_method_map, genpath,\n\texecute_pkg_add_or_del): Use file_ops::concat.\n\n\t2007-08-24  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (Fmislocked): return value for nargin == 0 case.\n\n\t2007-07-27  John W. Eaton  <jwe@octave.org>\n\n\t* pt-idx.cc (tree_index_expression::rvalue):\n\tPass substring of type to subsref when doing partial evaluation.\n\t(tree_index_expression::lvalue): Likewise.\n\n\t2007-06-29  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (is_built_in_class, set_class_relationship,\n\tFsuperiorto, Finferiorto): New functions.\n\t(octave_class::in_class_method): New function.\n\t(octave_class::subsref, octave_class:subsasgn): Use it.\n\n\t2007-06-28  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (sanitize): New function.\n\t(make_idx_args): Use it.\n\n\t2007-06-28  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (octave_class::subsasgn): Expect and use only\n\tone return value from feval of subsasgn method.\n\n\t* ov.cc (octave_value::assign): Don't convert to struct if\n\tindexing a class object with \".\".\n\n\t* pt-idx.cc (tree_index_expression::make_arg_struct):\n\tUse Cell instead of octave_value_list for subscripts.\n\n\t* ov-class.cc (make_idx_args): For \".\" index, subs field is\n\tstring, not cell.\n\n\t2007-06-27  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::save_ascii,\n\toctave_fcn_handle::load_ascii, octave_fcn_handle::save_binary,\n\toctave_fcn_handle::load_binary, octave_fcn_handle::save_hdf5,\n\toctave_fcn_handle::load_hdf5): Adapt to new symbol table objects.\n\n\t* symtab.h (symbol_table::all_variables,\n\tsymbol_table::do_all_variables): New arg, defined_only.\n\n\t2007-06-26  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (read_mat5_binary_element): Adapt to new symbol table\n\tobjects.\n\n\t* variables.cc (Vwhos_line_format): New static variable.\n\t(Fwhos_line_format): New function.\n\t(symbol_record_name_compare): Delete function.\n\t(symbol_record_name_compare, whos_parameter): New structs.\n\t(print_descriptor, dimensions_string_req_first_space,\n\tdimensions_string_req_total_space, make_dimensions_string,\n\tparse_whos_line_format, print_symbol_info_line): New static\n\tfunctions, adapted from old symbol table class.\n\t(do_who): Adapt to new symbol table objects.\n\n\t* symtab.h (symbol_table::glob_variables): New functions.\n\t(symbol_table::do_glob): New argument, vars_only.  Change all uses.\n\n\t2007-06-22  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::help_for_dispatch):\n\tNew function.\n\t* symtab.h: Provide decl.\n\t(symbol_table::fcn_info::help_for_dispatch,\n\tsymbol_table::help_for_dispatch): New functions.\n\n\t* help.cc (help_from_symbol_table): Call\n\tsymbol_table::help_for_dispatch instead of\n\textract_help_from_dispatch.\n\n\t* help.cc (extract_help_from_dispatch): Delete.\n\t* help.h: Delete decl.\n\n\t2007-06-21  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/dispatch.cc (class octave_dispatch): Delete class.\n\t(builtin, any_arg_is_magic_colon, dispatch_record): Delete functions.\n\t(Fbuiltin, Fdispatch): Adapt to new symbol table objects.\n\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::print_dispatch):\n\tNew function.\n\t* symtab.h: Provide decl.\n\t(symbol_table::fcn_info::print_dispatch, symbol_table::print_dispatch):\n\tNew functions.\n\n\t* symtab.h (symbol_table::fcn_info::fcn_info_rep::clear_dispatch,\n\tsymbol_table::fcn_info::clear_dispatch, symbol_table::clear_dispatch):\n\tNew functions.\n\n\t* symtab.h (symbol_table::fcn_info::fcn_info_rep::get_dispatch,\n\tsymbol_table::fcn_info::get_dispatch, symbol_table::get_dispatch):\n\tNew functions.\n\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::find):\n\tUse leftmost class argument as dispatch type, or first argument if\n\tthere are no class arguments.\n\n\t2007-06-20  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base.cc (Vprint_answer_id_name, Fprint_answer_id_name): Delete.\n\t(octave_base_value::print_with_name): Always print name.\n\n\t* ov-base.cc (Vsilent_functions): No longer static.\n\t* ov-base.h: Provide decl.\n\n\t* ov-class.cc (Fmethods): Define as command.\n\n\t* ov-class.cc (octave_class::print): Simply call print_raw.\n\n\t* ov-class.cc (octave_class::print_with_name): New function.\n\t* ov-class.h: Provide decl.\n\n\t2007-06-19  John W. Eaton  <jwe@octave.org>\n\n\t* ov.cc (octave_value::do_unary_op, octave_value::do_binary_op):\n\tHandle class methods.\n\n\t* ov.cc (octave_value::unary_op_fcn_name,\n\toctave_value::binary_op_fcn_name): New functions.\n\t* ov.h: Provide decls.\n\n\t* ov-typeinfo.cc (octave_value_typeinfo::register_unary_class_op,\n\toctave_value_typeinfo::register_binary_class_op,\n\toctave_value_typeinfo::do_register_unary_class_op,\n\toctave_value_typeinfo::do_register_binary_class_op,\n\toctave_value_typeinfo::do_lookup_unary_class_op,\n\toctave_value_typeinfo::do_lookup_binary_class_op): New functions.\n\t* ov-typeinfo.h: Provide decls.\n\n\t* ov-typeinfo.h (octave_value_typeinfo::unary_class_op_fcn,\n\toctave_value_typeinfo::binary_class_op_fcn): New typedefs.\n\t(octave_value_typeinfo::unary_class_ops,\n\toctave_value_typeinfo::binary_class_ops): New data members.\n\t(octave_value_typeinfo::octave_value_typeinfo): Initialize them.\n\t(octave_value_typeinfo::lookup_unary_class_op,\n\toctave_value_typeinfo::lookup_binary_class_op): New functions.\n\n\t* OPERATORS/op-class.cc: New file.\n\t* Makefile.in (OP_XSRC): Add it to the list.\n\n\t* ov.cc (install_types): Call octave_class::register_type here.\n\n\t* ov-class.h (octave_class): Implement by containing a map object\n\tinstead of deriving from octave_struct.\n\t* ov-class.cc (octave_class::subsref, octave_class::subsasgn):\n\tDon't use octave_class implementation as default action.\n\n\t* ov.h, ov.cc (octave_value::octave_value (const Octave_map&, const\n\tstd::string&)): New constructor.\n\n\t2007-06-18  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (octave_class::subsref, octave_class::subsasgn):\n\tHandle dispatch to user-defined methods.\n\n\t* parse.y (load_fcn_from_file): New arg, dispatch_type.\n\tChange all uses.\n\n\t* ov-fcn.h (octave_function::is_class_constructor,\n\toctave_function::is_class_method, octave_function::dispatch_class):\n\tNew virtual functions.\n\n\t* ov-usr-fcn.h (octave_user_function::dispatch_class,\n\toctave_usr_function::stash_dispatch_class): New functions.\n\t(octave_usr_fucntion::xdispatch_class): New data member.\n\t* parse.y (frob_function): Call stash_dispatch_class here.\n\n\t* ov-struct.cc (Ffieldnames): Also handle objects.\n\n\t* ov-class.cc (Fmethods): New function.\n\t* load-path.cc (load_path::do_methods): New function.\n\t* load-path.h (load_path::methods): New function.\n\n\t* ov.h (octave_value::is_object): New function.\n\t* ov-base.h (octave_base_value::is_object): New virtual function.\n\t* ov-class.h (octave_class::is_object): New function.\n\t* ov-class.cc (Fisobject): New function.\n\n\t2007-06-15  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (octave_class::print): Call display method if found.\n\n\t* symtab.h (symbol_table::fcn_info::find_method): New function.\n\t(symbol_table::find_method): New function.\n\t(symbol_table::fcn_info::fcn_info_rep::find_method): Provide decl.\n\t* symtab.cc (symbol_table::fcn_info::fcn_info_rep::find_method):\n\tNew function.\n\t(symbol_table::fcn_info::fcn_info_rep::find): Use it.\n\n\t2007-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h (symbol_table::clear_mex_functions): Make it work.\n\t(symbol_table::fcn_info::fcn_info_rep::clear_mex_function,\n\tsymbol_table::fcn_info::clear_mex_function): New functions.\n\n\t2007-06-08  John W. Eaton  <jwe@octave.org>\n\n\t* defun.cc (Falias): Delete.\n\n\t* variables.cc (load_fcn_try_ctor): New function.\n\t(lookup): call load_fcn_try_ctor instead of load_fcn_from_file.\n\n\t* variables.cc, variables.h (at_top_level, lookup_by_name, lookup,\n\tinitialize_symbol_tables, fcn_out_of_date, symbol_out_of_date,\n\tlookup_function, lookup_user_function, link_to_global_variable,\n\tlink_to_builtin_or_function, force_link_to_function, Fdocument,\n\tis_local_variable, do_clear_all, do_clear_functions,\n\tdo_clear_globals, do_clear_variables, do_clear_function,\n\tdo_clear_global, do_clear_variable, do_clear_symbol,\n\tdo_clear_function_pattern, do_clear_global_pattern,\n\tdo_clear_variable_pattern, do_clear_symbol_pattern,\n\tclear_function, clear_variable, clear_symbol):\n\tDelete (some functionality moved to the new symtab.cc and some is\n\tno longer needed).\n\t(Fignore_function_time_stamp): Move to symtab.cc.\n\n\t* lex.l (lookup_identifier): Delete.\n\n\t* parse.y (is_function_file): New function.\n\t(load_fcn_from_file): Return pointer to octave_function, not bool.\n\n\t* ov-usr-fcn.h, ov-usr-fcn.cc (octave_user_function::argn_sr,\n\toctave_user_function::nargin_sr, octave_user_function::nargout_sr,\n\toctave_user_function::varargin_sr): Delete data members.\n\t(octave_user_function::install_automatic_vars): Delete.\n\t(octave_user_script::do_multi_index_op): New function.\n\n\t* ov-fcn.h (octave_function::locked, octave_function::my_dir_name):\n\tNew data members.\n\t(octave_function::dir_name, octave_function::stash_dir_name,\n\toctave_function::lock, octave_function::unlock,\n\toctave_function::islocked): New functions.\n\n\t* of-fcn-handle.h, ov-fcn-handle.cc (octave_fcn_handle::subsref):\n\tCall out_of_date_check here to simplify time stamp checking.\n\t(octave_fcn_handle::reload_warning): Delete.\n\n\t* ov.h (octave_value::is_user_script, octave_value::is_user_function):\n\tNew functions.\n\t* ov-base.h (octave_base_value::is_user_script,\n\toctave_base_value::is_user_function): New pure virtual functions.\n\t* ov-fcn.h (octave_function::is_user_script,\n\toctave_function::is_user_function): Delete.\n\n\t* load-save.cc (install_loaded_variable): Greatly simplify.\n\n\t* load-path.h, load-path.cc: Change private_fcn_file to private_file.\n\t(load_path::private_fcn_map): New data member.\n\t(load_path::do_add, load_path::do_remove, load_path::do_update):\n\tAlso manage private_file_map here.\n\t(load_path::add_to_private_fcn_map): New function.\n\t(load_path::remove_private_fcn_map): New function.\n\t(load_path::do_find_private_fcn): Make it work.\n\t(get_file_list): New function.\n\t(load_path::do_display): Use it.  Display private map.\n\t(load_path::find_method, load_path::find_fcn): Handle directory name.\n\n\t* token.cc, token.h, toplev.cc, debug.cc, defun.cc, defun-dld.h,\n\tdefun-int.h, error.cc, help.cc, load-save.h, load-save.cc, mex.cc,\n\toctave.cc, ov-fcn-handle.cc, ov-usr-fcn.cc, parse.h, parse.y,\n\tlex.l, variables.cc: Adapt to new symbol table objects (my\n\tapologies for the lack of detail).\n\n\t* unwind-prot.h (unwind_protect::add): Set default value for ptr arg.\n\n\t* pt-stmt.cc (tree_statement::eval): Rework method for deciding\n\twhether to assign value to ans.\n\n\t* pt-idx.cc (tree_index_expression::rvalue):\n\tLooking up symbol may evaluaate first args now.\n\n\t* pt-id.h, pt-id.cc (tree_identifier::document,\n\ttree_identifier::is_defined, tree_identifier::define,\n\ttree_identifier::is_function, tree_identifier::lookup,\n\ttree_identifier::link_to_global): Delete.\n\t(tree_identifier::do_lookup): Simplify.\n\t(tree_identifier::rvalue): Looking up symbol can't execute script now.\n\n\t* pt-misc.cc (tree_parameter_list::initialize_undefined,\n\ttree_parameter_list::is_defined): Call is_variable for elt, not\n\tis_defined.\n\n\t* pt-fcn-handle.h (tree_anon_fcn_handle::fcn): Now pointer to\n\toctave_user_function, not value.  Change all uses.\n\n\t* pt-decl.h (tree_decl_command::initialized): Delete data member.\n\t(tree_decl_elt::is_variable): New function.\n\t* pt-decl.cc: Fix all uses of tree_decl_command::initialized.\n\n\t* ls-hdf5.cc, ls-mat-ascii.cc, ls-mat4.cc, ls-mat5.cc,\n\tls-oct-ascii.cc, ls-oct-binary.cc, input.cc: Don't include symtab.h.\n\n\t* dynamic-ld.h, dynamic-ld.cc (octave_dynamic_loader::load_oct,\n\toctave_dynamic_loader::load_mex, octave_dynamic_loader::do_load_oct,\n\toctave_dynamic_loader::do_load_mex): Adapt to new symbol table\n\tobjects.  Return pointer octave_function instead of bool.\n\n\t* DLD-FUNCTIONS/dispatch.cc (Fbuiltin): Disable for now.\n\tDisable code that works with old symbol tables.\n\t(Fbuiltin): Simply call symbol_table::add_dispatch.\n\n\t* pt-arg-list.cc, pt-arg-list.h, pt-assign.cc, pt-assign.h,\n\tpt-binop.cc, pt-binop.h, pt-bp.h, pt-cell.cc, pt-cell.h,\n\tpt-cmd.cc, pt-cmd.h, pt-colon.cc, pt-colon.h, pt-const.cc,\n\tpt-const.h, pt-decl.cc, pt-decl.h, pt-except.cc, pt-except.h,\n\tpt-exp.h, pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h,\n\tpt-idx.cc, pt-idx.h, pt-jump.cc, pt-jump.h, pt-loop.cc, pt-loop.h,\n\tpt-mat.cc, pt-mat.h, pt-misc.cc, pt-misc.h, pt-select.cc,\n\tpt-select.h, pt-stmt.cc, pt-stmt.h, pt-unop.cc, pt-unop.h:\n\tAdapt dup functions to use scope instead of symbol_table objects.\n\n\t* TEMPLATE-INST/Array-sym.cc: Delete.\n\t* Makefile.in (TI_XSRC): Remove it from the list.\n\n\t* symtab.h, symtab.cc: Replace with new versions.\n\n\t2007-05-16  John W. Eaton  <jwe@octave.org>\n\n\t* oct-lvalue.cc, oct-lvalue.h (octave_lvalue::chg_fcn): Delete.\n\tFix all uses.\n\n\t2007-05-15  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::do_find_private_function): New function.\n\t* load-path.h (load_path::do_find_private_function): Provide decl.\n\t(load_path::find_private_function): New function.\n\n\t2007-05-08  John W. Eaton  <jwe@octave.org>\n\n\t* pt-idx.cc (tree_index_expression::rvalue): Handle dispatch here.\n\n\t* pt-id.cc (tree_identifier::is_variable, tree_identifier::lookup):\n\tNew functions.\n\t* pt-id.cc: Provide decls.\n\n\t* parse.y (current_class_name): New global variable.\n\t* parse.h: Provide decl.\n\n\t* parse.y (load_fcn_from_file, parse_fcn_file):\n\tNew arg, dispatch_type.\n\t(parse_fcn_file): Protect current_class_name and set it to\n\tdispatch_type before parsing function.\n\t(load_fcn_from_file): If dispatch_type is not empty, call\n\tload_path::find_method instead of load_path::find_fcn.\n\t* parse.h: Fix decls for extern functions.\n\n\t* lex.h (lexical_feedback::parsing_class_method): New data member.\n\t* lex.l (lexical_feedback::init): Initialize it.\n\t(lookup_identifier): Check it and set sym_name accordingly.\n\n\t* ov-usr-fcn.h (octave_user_function::mark_as_class_constructor,\n\toctave_user_function::is_class_constructor,\n\toctave_user_function::mark_as_class_method,\n\toctave_user_function::is_class_method): New functions.\n\t(octave_user_function::class_constructor,\n\toctave_user_function::class_method): New data members.\n\t* ov-usr-fcn.cc (octave_user_function::octave_user_function):\n\tInitialize them.\n\n\t* load-path.h, load-path.cc: Use typedefs to simplify template decls.\n\tUse fcn consistently instead of function.\n\n\t2007-05-03  John W. Eaton  <jwe@octave.org>\n\n\t* ov-class.cc (Fclass): Move here.\n\t* ov-typeinfo.cc: From here.\n\n\t* input.cc (octave_gets): Call load_path::update if user input\n\tcontains something other than one of the characters \" \\t\\n\\r\".\n\n\t* ov-class.cc, ov-class.h: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* load-path.cc (genpath): Skip directories beginning with \"@\".\n\t(load_path::dir_info::get_file_list):  Don't return anything.\n\tCall get_private_function_map here.\n\t(load_path::dir_info::initialize): Not here.\n\t(load_path::dir_info_::get_method_file_map): New function.\n\t(load_path::method_map): New data member.\n\t(load_path::do_clear): Also clear method_map.\n\t(load_path::do_add): Also call add_to_method_map.\n\t(load_path::do_update): Also clear method_map and call\n\t(load_path::do_find_method): New function.\n\t(load_path::do_add_to_method_map): New function.\n\t(load_path::move_fcn_map, load_path::move_method_map): New functions.\n\t(load_path::move): Use them.\n\t(load_path::remove_fcn_map, load_path::remove_method_map):\n\tNew functions.\n\t(load_path::remove): Use them.\n\t* load-path.h: Provide/fix decls.\n\t(load_path::find_method): New static function.\n\n\t* Makefile.in (%.df : %.cc): Use mv instead of\n\t$(simple-move-if-change-rule).\n\n2007-12-21  John W. Eaton  <jwe@octave.org>\n\n\tVersion 3.0.0 released.\n\n\t* version.h (OCTAVE_VERSION): Now 3.0.0.\n\t(OCTAVE_API_VERSION): Now api-v32.\n\t(OCTAVE_RELEASE_DATE): Now 2007-12-21.\n\n2007-12-19  Thomas Kasper  <ThomasKasper@gmx.net>\n\n\t* OPERATORS/op-scm-cs.cc (DEFBINOP (pow)): Extract complex value\n\tfrom second arg.\n\n2007-12-12  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/sparse.cc (Fsparse): Check for scalar arguments\n\tfor 2 argument version.\n\n2007-12-12  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (class axes) Add the layer property.\n\t* graphics.cc (class axes) Ditto.\n\n\t* graphics.cc (gh_manager::get_handle): Use ceil instead of trunc.\n\n2007-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.19+.\n\n2007-12-11  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.19.\n\t(OCTAVE_API_VERSION): Now api-v31.\n\t(OCTAVE_RELEASE_DATE): Now 2007-12-11.\n\n\t* graphics.cc (make_graphics_object):\n\tIf successful, call __request_drawnow__.\n\n\t* input.cc (Vgud_mode): New static variable.\n\t(F__gud_mode__): New function.\n\t(get_user_input): If debug and Vgud_mode, print location info in\n\tformat for Emacs GUD mode.\n\n2007-12-11  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-bm-sbm.cc, OPERATORS/op-b-sbm.cc,\n\tOPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc,\n\tOPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc,\n\tOPERATORS/op-m-scm.cc, OPERATORS/op-m-sm.cc,\n\tOPERATORS/op-s-scm.cc, OPERATORS/op-s-sm.cc: Privilege\n\tconversion to dense matrices for compatibility.\n\n\t* DLD-FUNCTIONS/sparse.cc (FSparse): Remove the mutate flag, as\n\tdefault bahavior is now to keep matrix sparse always.\n\n\t* graphics.cc (axes::properties::properties):\n\tInitialize xcolor, ycolor, and zcolor to (0, 0, 0).\n\n\t* graphics.h.in (gh_manager::next_handle): Now double.\n\t* graphics.cc (gh_manager::get_handle, gh_manager::gh_manager):\n\tSet fractional part of next_handle to a random value.\n\n2007-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* ov-cell.cc (octave_cell::all_strings): Handle empty elements.\n\tHandle N-d cell arrays.\n\n\t* DLD-FUNCTIONS/fsolve.cc (Ffsolve):\n\tFor compatibility, return [x, fval, info] instead of [x, info, msg].\n \tMove tests here from test/test_nonlin.m.\n\n\t* OPERATORS/op-cm-s.cc: Define function for el_mul with\n\tDEFNDBINOP_OP, not DEFBINOP_OP.\n\n\t* OPERATORS/op-s-cm.cc: Define functions for el_and and el_or\n\toperators with DEFNDBINOP_FN.\n\n\t* oct-hist.cc (default_history_file): Use file_ops::concat.\n\t* load-path.cc (dir_info::initialize, dir_info::get_file_list,\n\tload_path::do_find_fcn, load_path::do_find_file, genpath,\n\texecute_pkg_add_or_del, load_path::do_find_first_of,\n\tload_path::do_find_all_first_of): Likewise.\n\n\t* help.cc (Flookfor): Avoid doubling directory separator.\n\t* dirfns.cc (Fmkdir): Likewise.\n\n\t* pt-mat.cc (tree_matrix::rvalue): Produce sq_string if any\n\tstrings are sq_string objects.\n\n2007-12-10  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (data_property::data): Declare as NDArray instead\n\tof Matrix.  Change all uses.\n\n2007-12-10  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h.in (class figure) Add the color property.\n\t* graphics.cc (class figure) Ditto.\n\n2007-12-07  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (Fnorm): Don't return a scalar stored as a sparse\n\tmatrix. Convert it to a scalar.\n\n\t* graphics.cc (check_limit_val): Delete.\n\t(check_limit_vals): Simplify and no longer use check_limit_val.\n\n2007-12-05  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.18+.\n\n2007-12-05  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.18.\n\t(OCTAVE_API_VERSION): Now api-v30.\n\t(OCTAVE_RELEASE_DATE): Now 2007-12-05.\n\n2007-12-04  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (INCLUDES): Add builtins.h to the list.\n\n\t* oct-hist.cc (default_history_file): Use += instead of\n\tpush_back to append character to std::string object.\n\n\t* Makefile.in (LIBDLFCN): Delete all uses.\n\n\t* toplev.cc (octave_config_info): Remove LIBDLFCN and\n\tDLFCN_INCFLAGS from the list.\n\t* oct-conf.h.in (OCTAVE_CONF_DLFCN_INCFLAGS, OCTAVE_CONF_LIBDLFCN):\n\tDelete.\n\n\t* error.cc (Ferror): Handle error id.\n\n\t* load-save.cc (Fsave, Fload): Doc fixes.\n\tFrom Marco Caliari <caliari@sci.univr.it>.\n\n2007-12-04  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h.in (base_properties::get_type\n\tbase_properties::get___modified__,\n\tbase_properties::get___myhandle__): New functions.\n\n2007-12-04  Christoph Mayer  <Christoph.Mayer@dlr.de>.\n\n\t* toplev.h (clean_up_and_exit, recover_from_exception,\n\tdo_octave_atexit, global_command, curr_parent_function):\n\tTag with OCTINTERP_API.\n\n2007-12-03  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/luinc.cc: Make tests conditional on HAVE_UMFPACK.\n\t* DLD-FUNCTIONS/spqr.cc: Make tests conditional on HAVE_CXSPARSE.\n\n\t* DLD-FUNCTIONS/regexp.cc: Use \"%!testif\" blocks for conditional\n\ttests on PCRE.\n\n\t* graphics.cc (class axes): Add color and activepositionproperty\n\tproperties to axis objects.\n\t* graphics.h.in (class axes): ditto.\n\n\t* DLD-FUNCTIONS/regexp.cc: Also include sys/types.h for regexp.\n\n2007-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/sort.cc (operator < (const Complex&, const Complex&),\n\toperator > (const Complex&, const Complex&)):\n\tPass args by const reference, not value.\n\n\t* data.cc, matherr.c, pr-output.cc, sysdep.cc,\n\tDLD-FUNCTIONS/__dsearchn__.cc, DLD-FUNCTIONS/minmax.cc,\n\tDLD-FUNCTIONS/qz.cc, DLD-FUNCTIONS/sort.cc,\n\tDLD-FUNCTIONS/tsearch.cc: Include lo-math.h instead of cmath\n\tor math.h.\n\n2007-11-30  Moritz Borgmann  <octave@moriborg.de>\n\n\t* ls-mat5.h (mat5_data_type): Delete trailing comma in enum decl.\n\t* oct-stream.cc (octave_base_stream::do_printf): Use\n\tOCTAVE_EMPTY_CPP_ARG to avoid annoying Sun compiler warning.\n\t* OPERATORS/op-sbm-sbm.cc (DEFDBLCONVFN): Delete useless macro\n\tinvocation.\n\n\t* DLD-FUNCTIONS/typecast.cc (typecast): No longer static.\n\n2007-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (updating_axis_limits): New static variable.\n\t(check_limit_val, check_limit_vals, get_axis_limits): New functions.\n\t(axes::update_axis_limits): Make it work.\n\t* graphics.h.in (base_properties::get_children): New function.\n\t(base_properties::get_xdata, base_properties::get_ydata,\n\tbase_properties::get_zdata, base_properties::get_ldata,\n\tbase_properties::get_udata, base_properties::get_xldata,\n\tbase_properties::get_xudata, base_properties::get_cdata,\n\tbase_properties::get_properties (void) const):\n\tNew virtual functions.\n\t(graphics_object::get_xdata, graphics_object::get_ydata,\n\tgraphics_object::get_zdata, graphics_object::get_ldata,\n\tgraphics_object::get_udata, graphics_object::get_xldata,\n\tgraphics_object::get_xudata, graphics_object::get_cdata,\n\tgraphics_object::get_properties (void) const,\n\troot_figure::get_properties (void) const,\n\tfigure::get_properties (void) const,\n\taxes::get_properties (void) const,\n\tline::get_properties (void) const,\n\ttext::get_properties (void) const,\n\timage::get_properties (void) const,\n\tpatch::get_properties (void) const,\n\tsurface::get_properties (void) const)): New functions.\n\t(radio_property::radio_property (const radio_values&)):\n\tProvide\tdefault value for argument.\n\t(radio_property::radio_property (const radio_values&, const\n\tstd::string&)): Delete.\n\t(axes::xlimmode, axes::ylimmode, axes::zlimmode, axes::climmode,\n\taxes::xscale, axes::yscale, axes::zscale): Declare as\n\tradio_property instead of octave_value values.  Adjust all uses.\n\n2007-11-29  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (octave_print_internal_template (std::ostream&,\n\tconst octave_int<T>&, bool)): Rename from octave_print_internal.\n\t(PRINT_INT_SCALAR_INTERNAL): New macro.  Use it to define\n\tnon-template functions for printing scalar octave_int values.\n\t(octave_print_internal_template (std::ostream&, const intNDArray<T>&,\n\tbool, int)): Rename from octave_print_internal.\n\t(PRINT_INT_ARRAY_INTERNAL): New macro.  Use it to define\n\tnon-template functions for printing scalar octave_int values.\n\t* pr-output.h: Declare non-template functions for printing\n\toctave_int scalar and array values.\n\tDelete declarations of template funtions for printing octave_int\n\tscalar and array values.\n\n2007-11-28  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (base_properties::update_axis_limits,\n\taxes::update_axis_limits): New functions.\n\t* graphics.h.in (class data_property): New class.\n\t(graphics_object::update_axis_limits): New function.\n\t(base_graphics_object::update_axis_limits): New virtual function.\n\t(base_properties::update_axis_limits, axes::update_axis_limits):\n\tProvide decls.\n\t(class line, class image, class patch, class surface): Use it\n\tinstead of octave_value for data properties.  Tag data properties\n\twith \"l\" modifier.\n\t(class axes): Tag scale properties with \"l\" modifier.\n\t* genprops.awk: Handle \"l\" modifier.\n\n\t* mkbuiltins: Emit #include \"builtins.h\" for the builtins.cc file.\n\tFrom Christoph Mayer <Christoph.Mayer@dlr.de>.\n\n\t* TEMPLATE-INST/Array-tc.cc (resize_fill_value<octave_value>):\n\tDelete.\n\n\t* Cell.cc (Cell::Cell (const dim_vector&, const string_vector&, bool)):\n\tInitialize undefined values to resize_fill_value ().\n\n2007-11-27  John W. Eaton  <jwe@octave.org>\n\n\t* TEMPLATE-INST/Array-tc.cc (resize_fill_value<octave_value>):\n\tTag inline.  From Moritz Borgmann <octave@moriborg.de>.\n\n\t* pt-bp.cc (tree_breakpoint::visit_decl_command): Also check line\n\tnumber of cmd.\n\t* pt-decl.cc (tree_global_command::eval, tree_static_command::eval):\n\tInsert MAYBE_DO_BREAKPOINT here.\n\n\t* error.cc (Fwarning): If setting state \"all\" to \"error\", leave\n\tOctave:matlab-incompatible and Octave:single-quote-string warning\n\tstates unchanged.\n\t(warning_enabled): Allow individual warning states to override\n\t\"warning error all\".\n\n\t* octave.cc (execute_eval_option_code, execute_command_line_file):\n\tHandle interrupts.\n\t* toplev.cc (recover_from_exception): Now extern.\n\t* toplev.h (recover_from_exception): Provide decl.\n\n\t* pt-idx.cc (tree_index_expression::lvalue): Treat object == []\n\tthe same as undefined.\n\n2007-11-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (DO_DOUBLE_CONV): Always use long.\n\n\t* oct-stream.cc (do_write): Call float_value and double_value on\n\toctave_int<T> objects instead of relying on conversion operators.\n\n\t* ls-mat5.cc (read_mat5_binary_element, OCTAVE_MAT5_INTEGER_READ):\n\tCall double_value on octave_int<T> objects\n\tinstead of relying on conversion operator.\n\t(read_mat5_binary_file_header):\n\tCall char_value on octave_int<T> objects\n\tinstead of relying on conversion operator.\n\t(read_mat5_binary_element):\n\tCall bool_value on octave_int<T> objects\n\tinstead of relying on conversion operator.\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::double_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::scalar_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::matrix_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::complex_matrix_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::array_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::complex_array_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::double_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::scalar_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::matrix_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::complex_matrix_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::array_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::complex_array_value,\n\tCall double_value on octave_int<T> objects\n\tinstead of relying on conversion operator.\n\t(OCTAVE_VALUE_INT_MATRIX_T::bool_array_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::bool_array_value):\n\tCall bool_value on octave_int<T> objects\n\tinstead of relying on conversion operator.\n\t(OCTAVE_VALUE_INT_MATRIX_T::char_array_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::char_array_value):\n\tCall char_value on octave_int<T> objects\n\tinstead of relying on conversion operator.\n\n2007-11-26  David Bateman  <dbateman@free.fr>\n\n\t* Sparse-op-defs.h (SPARSE_BASE_REDUCTION_OP): Check that the fill\n\tvalue is not zero before creating the matrices.\n\n\t* graphics.cc (class axes): Add the {x|y|z}color color property.\n\t* graphics.h.in (class axes): ditto.\n\n\t* ov-base.cc (Vsparse_auto_mutate, Fsparse_auto_mutate): New\n\tinternal variable and built-in function to set it.\n\t* ov-base.h (extern bool Vsparse_auto_mutate): Export internal\n\tvariable to other functions.\n\t* ov-re-sparse.cc (octave_sparse_matrix::try_narrowing_conversion\n\t(void)), ov-cx-sparse.cc\n\t(octave_sparse_complex_matrix::try_narrowing_conversion (void)),\n\tov-bool-sparse.cc\n\t(octave_sparse_bool_matrix::try_narrowing_conversion (void)):\n\tUse Vsparse_auto_mutate flag to determine whether to convert\n\tsparse matrices to full matrices if that saves space.\n\n\t* DLD-FUNCTIONS/minmax.cc (MINMAX_DOUBLE_BODY): New version of\n\tMINMAX_BODY macro without the initialization.\n\t(MINMAX_INT_BODY): Macro for min/max for the integer types\n\t(MINMAX_BODY): New macro that calls the appropriate instantiation\n\tof the other two macros.\n\n\t* graphics.cc (class axes): Add __colorbar__ property.\n\t* graphics.h.in (class axes): ditto.\n\n\t* data.cc (Fnorm): Document the \"inf\" string argument for matrice\n\tand vectors and the \"fro\" argument for vectors.\n\n\t* graphics.h.in (class figure): Add __enhanced__ property to cache\n\twhether the terminal supports enhanced mode. Add interpreter\n\tproperty to all text classes, to determine the renderer for the\n\ttext.\n\t* graphics.cc (class figure): ditto.\n\n2007-11-26  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.cc (string_properties): delete class\n\t(property_name): rename class to caseless_str.\n\t(radio_values::possible_vals): change type to caseless_str.\n\n2007-11-26  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* builtins.h (install_builtins): Tag with OCTINTERP_API.\n\t* toplev.h (octave_interpreter_ready, octave_initialized): Likewise.\n\n2007-11-14  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mex::foreign_memlist): New data member.\n\t(mex::mark_foreign, mex::unmark_foreign): New functions.\n\t(mex::free): Don't warn about pointers found in foreign_memlist.\n\t(maybe_mark_foreign): New function.\n\t(mxArray_octave_value::get_data, mxArray_octave_value::get_ir,\n\tmxArray_octave_value::get_jc):\n\tCall maybe_mark_foreign on returned pointer.\n\n2007-11-14  David Bateman  <dbateman@free.fr>\n\n\t* mex.cc (mxArray_sparse::mxArray_sparse (const mxArray_sparse&)):\n\tAlso ensure that pr and pi are correctly copied.\n\n2007-11-14  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (@bsd_gcc_kluge_targets_frag@): Delete line for\n\tMakefrag.bsd substitution.\n\n\t* graphics.h.in (base_properties::tag): New property.\n\t(base_properties::get_tag, base_properties::set_tag): New functions.\n\t(root_figure::set, root_figure::get, figure::set, figure::get,\n\taxes::set, axes::get, line::set, line::get, text::set, text::get,\n\tpatch::set, patch::get, surface::set, surface::get): Handle tag.\n\n2007-11-14  Joseph P. Skudlarek  <Jskud@Jskud.com>\n\n\t* DLD-FUNCTIONS/regexp.cc: Undo previous change.\n\n2007-11-14  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mex::mark, mex::unmark): Now public.\n\t(mex::persistent): Delete.\n\t(mexMakeArrayPersistent): Call maybe_unmark_array instead of\n\tmex::persistent.\n\t(mexMakeMemoryPersistent): Call maybe_unmark instead of\n\tmex::persistent.\n\t(maybe_unmark (void *)): New function.\n\t(mxSetDimensions, mxSetPr, mxSetPi, mxSetData, mxSetImagData,\n\tmxSetIr, mxSetJc): Use it.  From David Bateman.\n\n2007-11-13  Joseph P. Skudlarek  <Jskud@Jskud.com>\n\n\t* DLD-FUNCTIONS/rand.cc (Frand): Update URL reference in doc string.\n\n2007-11-12  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in, graphics.cc (class text): Add the fontangle and\n\tfontweight properties. Add string_property class to handle the\n\tstring radio values.\n\n2007-11-12  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.17+.\n\n2007-11-12  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in, graphics.cc (class text): Add the fontname and\n\tfontsize properties.\n\n2007-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.17.\n\t(OCTAVE_API_VERSION): Now api-v29.\n\t(OCTAVE_RELEASE_DATE): Now 2007-11-10.\n\n2007-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l: Don't add atexit (\"closeplot\")\n\tto PKG_ADD file.\n\n2007-11-09  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc, graphics.h.in (class patch): Add the field \"keylabel\".\n\n\t* data.cc (Fcputime) [__WIN32__]: Correct scaling of sys and usr times.\n\n\t* graphics.cc (is_handle): Handle must be a real scalar.\n\n2007-11-09  Joseph P. Skudlarek  <Jskud@Jskud.com>\n\n\t* data.cc (Fislogical): Fix typo in documentation entry.\n\n2007-11-08  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l (F__gnuplot_save_data__):\n\tNote obsolescence in doc string.\n\t(WARN_OBSOLETE): New macro\n\t(F__gnuplot_save_data__, Fgnuplot_command_plot,\n\tFgnuplot_command_replot, Fgnuplot_command_splot,\n\tFgnuplot_command_using, Fgnuplot_command_with,\n\tFgnuplot_command_axes, Fgnuplot_command_title,\n\tFgnuplot_command_end, Fgnuplot_use_title_option,\n\tF__clear_plot_window__, Fcloseplot, Fpurge_tmp_files,\n\tF__gnuplot_raw__, F__gnuplot_send_inline_data__, F__gnuplot_set__,\n\tF__gnuplot_show__, F__gnuplot_plot__, F__gnuplot_splot__,\n\tF__gnuplot_replot__): Use WARN_OBSOLETE.\n\n2007-11-07  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/regexp.cc: Handle HAVE_PCRE_PCRE_H.  Check\n\tHAVE_PCRE_H instead of HAVE_PCRE to decide whether to include pcre.h.\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l (Fgnuplot_command_plot,\n\tFgnuplot_command_replot, Fgnuplot_command_splot,\n\tFgnuplot_command_using, Fgnuplot_command_with,\n\tFgnuplot_command_axes, Fgnuplot_command_title,\n\tFgnuplot_command_end, Fgnuplot_use_title_option,\n\tF__clear_plot_window__, Fcloseplot, Fpurge_tmp_files,\n\tF__gnuplot_raw__, F__gnuplot_send_inline_data__, F__gnuplot_set__,\n\tF__gnuplot_show__, F__gnuplot_plot__, F__gnuplot_splot__,\n\tF__gnuplot_replot__): Note obsolescence in doc string.\n\n2007-11-06  Kai Habel  <kai.habel@gmx.de>\n\n\t* graphics.h.in (class surface::properties): New properties,\n\tcdata, facecolor, facealpha, edgecolor, linestyle,\n\tlinewidth, marker, markeredgecolor, markerfacecolor, markersize.\n\t* graphics.cc (surface::properties::properties,\n\tsurface::properties::set, surface::properties::get,\n\tsurface::properties::factory_defaults): Handle new properities.\n\n2007-11-06  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (DATA_REDUCTION): Handle the 'native' and 'double'\n\targuments of the Fsum function.\n\t* OPERATORS/op-bm-bm.cc (matrix_to_bool_matrix,\n\tscalar_to_bool_matrix): New type conversion functions.\n\t(install_bm_bm_ops): Install new type conversions functions.\n\n2007-11-06  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* toplev.cc (Fsystem) [__WIN32__ && ! __CYGWIN__]:\n\tQuote the complete command.\n\n2007-11-06  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (Fnorm): New tests.\n\n\t* defun-int.h (DEFINE_FUNX_INSTALLER_FUN3): Don't install function\n\tif check_version produces an error.\n\n2007-11-05  John W. Eaton  <jwe@octave.org>\n\n\t* pt-idx.cc (tree_index_expression::lvalue): Try to do a better\n\tjob of computing the number of elements in lvalue expressions when\n\tthe last indexing element is \".\".\n\n2007-11-02  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (fopen_mode_to_ios_mode): Use std::ios::app instead\n\tof std::ios::ate.\n\n2007-11-02  Olli Saarela  <Olli.Saarela@kcl.fi>\n\n\t* input.cc, pr-output.cc, bitfcns.cc, DLD-FUNCTIONS/time.cc:\n\tFix broken @examples in help texts.\n\n2007-10-31  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (Fnorm): Avoid warning about p_val possibly being used\n\tuninitialized.\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.16+.\n\n2007-10-31  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.16.\n\t(OCTAVE_API_VERSION): Now api-v28.\n\t(OCTAVE_RELEASE_DATE): Now 2007-10-31.\n\n2007-10-31  Muthiah Annamalai  <muthuspost@gmail.com>\n\n\t* pt-assign.h (tree_simple_assignment::op_type,\n\ttree_multi_assignment::op_type): New functions.\n\t* pt-unop.h (tree_unary_expression::op_type): New function.\n\n2007-10-31  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (line::properties::get): Fix property name\n\t(markerface -> markerfacecolor).\n\n\t* Makefile.in (INCLUDES): Add debug.h to the list.\n\n2007-10-30  John Swensen  <jpswensen@comcast.net>\n\n\t* debug.h: New file.\n\t* debug.cc (parse_dbfunction_params, do_find_bkpt_list,\n\tintmap_to_ov): New functions.\n\t(Fdbstop, Fdbclear): Use parse_dbfunction_params.\n\tImprove compatibility.\n\t(Fdbstatus): Improve compatibility.\n\n\t* help.cc (do_which): No longer static.\n\t* help.h: Provide decl.\n\n2007-10-30  David Bateman  <dbateman@free.fr>\n\n\t* symtab.cc: Doc fixes for small book format.\n\n2007-10-30  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (fopen_mode_to_ios_mode): Handle 'W' as 'w' and 'R'\n\tas 'r', but warn about them.\n\n2007-10-29  Thomas Treichl  <Thomas.Treichl@gmx.net>\n\n\t* data.cc: Include sytime.h, sys/types.h, and sys/resource.h.\n\n2007-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (figure::properties::set_currentaxes):\n\tAllow currentfigure to be NaN.\n\n2007-10-25  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* DLD-FUNCTIONS/__contourc__.cc: Use unsigned int instead of uint.\n\t(drawcn): Use 1 << k instead of pow (2, k).\n\n2007-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h (symbol_record::TYPE): Delete trailing comma in enum decl.\n\n\t* ov-base.h (DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA): Use\n\tOCTAVE_EMPTY_CPP_ARG to avoid annoying Sun compiler warning.\n\n\t* Makefile.in (graphics.h): Use $(AWK) instead of awk.\n\n\t* DLD-FUNCTIONS/time.cc (Ftime, Fmktime): Avoid unnecessary cast.\n\n\t* data.cc (Ftic, Ftoc): Call double_value on octave_time objects\n\tinstead of relying on conversion operator.\n\t* ov.cc (octave_value::octave_value (octave_time)): Likewise.\n\n\t* variables.cc (symbol_out_of_date): Use explicit conversion to\n\ttime_t instead of relying on conversion operator.\n\t* ov-fcn-handle.cc (octave_fcn_handle::subsref): Likewise.\n\n\t* data.cc (tic_toc_timestamp): Rename from __tic_toc_timestamp__.\n\tChange all uses.\n\n2007-10-24  David Bateman  <dbateman@free.fr>\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::OCTAVE_VALUE_INT_MATRIX_T\n\t(const ArrayN<OCTAVE_INT_T>&)): New constructor.\n\t* ov.cc (octave_value::octave_value(const ArrayN<T>) with T being\n\toctave_int8, octave_uint8, octave_int16, octave_uint16,\n\toctave_int32, octave_uint32, octave_int64, octave_uint64): New\n\tconstructors.\n\t* ov.h (octave_value::octave_value(const ArrayN<T>) with T being\n\toctave_int8, octave_uint8, octave_int16, octave_uint16,\n\toctave_int32, octave_uint32, octave_int64, octave_uint64):\n\tDeclare them.\n\t* DLD-FUNCTIONS/sort.cc (template class octave_sort<T>,\n\ttemplate class vec_index<T>, template class\n\toctave_sort<vec_index<T> *>,  with T being\n\toctave_int8, octave_uint8, octave_int16, octave_uint16,\n\toctave_int32, octave_uint32, octave_int64, octave_uint64): New\n\tinstantiations of sort template classes.\n\t(Fsort): Use them.\n\n2007-10-24  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (root_figure::properties::set_currentfigure):\n\tAllow currentfigure to be NaN.\n\n\t* pt-idx.cc (tree_index_expression::lvalue): Correctly compute\n\tnumber of elements in lvalue expression when last indexing\n\telement is \".\".\n\n2007-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (is_handle (const graphics_handle&)): New function.\n\t(gh_manager::do_free, reparent, base_properties::set_parent,\n\tproperties::get_title, properties::get_xlabel,\n\tproperties::get_ylabel, properties::get_zlabel,\n\tproperties::remove_child, make_graphics_object, F__go_figure__,\n\tF__go_delete__, __go_axes_init__): Call OK on graphics handle\n\tobject instead of relying on implicit conversion operator.\n\t* graphics.h.in (graphics_handle::operator double ()): Delete.\n\t(graphics_handle::operator bool ()): Delete.\n\t(gh_manager::do_handle_list, gh_manager::do_figure_handle_list,\n\tbase_properties::adopt): Call VALUE on graphics handle object\n\tinstead of relying on implicit conversion operator.\n\n\t* ov-base.h (DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA): Call\n\tDECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 with \"( )\" as arg list\n\tinstead of \"()\".\n\n\t* mxarray.h.in (mxClassID): Delete trailing comma in enum decl.\n\n\t* symtab.h (symbol_table::symbol_table): Reduce default table size\n\tto 64.\n\n2007-10-22  Kim Hansen  <kimhanse@gmail.com>\n\n\t* unwind-prot.cc: Include <cstring>.\n\n2007-10-22  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (Ftic, Ftoc, Fcputime): New builtin versions of the\n\tbenchmarking functions for speed.\n\t* oct-map.cc (Octave_map::squeeze, Octave_map::permute): New methods.\n\t(Octave_map::index (const octave_value_list&, bool)): Add resize_ok\n\targument, define as const and use const_iterator internally.\n\t(Octave_map::index (idx_vector&, ...), Octave_map::index (Array\n\t<idx_vector>&, ...)): New forms of the index function.\n\t* oct-map.h (squeeze, permute, indx (const octave_value_list&, bool),\n\tindex (idx_vector&, ...), index (Array <idx_vector>&, ...)): Add\n\tor update declaration.\n\t* ov-struct.cc (octave_struct::do_index_op (const octave_value_list&,\n\tbool)): New method.\n\t* ov-struct.h (do_index_op (const octave_value_list&, bool)): Declare\n\tit.\n\t(squeeze (void), permute (const Arra<int>&, bool): New methods.\n\n2007-10-19  Kai Habel  <kai.habel@gmx.de>\n\n\t* DLD-FUNCTIONS/__contourc__.cc (add_point): Rename from\n\tcl_add_point.  Change all uses.\n\t(end_contour): Rename from cl_end_contour.  Change all uses.\n\t(start_contour): Rename from cl_start_contour.  Change all uses.\n\t(drawcn): Rename from cl_drawcn.  New algorithm for locating contours.\n\t(mark_facets): New function.\n\t(cntr): Rename from cl_cntr.  Change all uses.  New algorithm for\n\tlocating contours.\n\n2007-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* ov-cell.cc (octave_cell::subsasgn): If RHS is cs-list, don't\n\tfail if shape of LHS is different.\n\t* ov-struct.cc (octave_struct::subsasgn): Likewise.\n\n2007-10-19  Olli Saarela  <Olli.Saarela@kcl.fi>\n\n\t* help.cc (Flookfor): Call print_usage instead of usage.\n\t* DLD-FUNCTIONS/cellfun.cc (Fmat2cell): Likewise.\n\n2007-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/spchol.cc (Fsymbfact): Delete special code for METIS.\n\n2007-10-17  Gabriele Pannocchia  <g.pannocchia@ing.unipi.it>\n\n\t* DLD-FUNCTIONS/__qp__.cc (qp): Fix check for Wact(j).\n\n2007-10-15  Søren Hauberg  <hauberg@gmail.com>\n\n\t* error.cc (Ferror): Make text fit on pages when using smallbook.\n\t* load-save.cc (Fsave_header_format_string): Ditto.\n\t* ov-struct.cc (Fcell2struct): Ditto.\n\t* DLD-FUNCTIONS/besselj.cc (Fairy): Ditto.\n\t* DLD-FUNCTIONS/urlwrite.cc (Furlwrite, Furlread): Ditto.\n\n2007-10-15  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (axes::properties::get): Fix typo.\n\n2007-10-13  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.15+.\n\n2007-10-13  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.15.\n\t(OCTAVE_API_VERSION): Now api-v27.\n\t(OCTAVE_RELEASE_DATE): Now 2007-10-13.\n\n2007-10-13  David Bateman  <dbateman@free.fr>\n\n\t* graphics.h.in (class patch): Add the faces and vertices properties.\n\t* graphics.cc (patch::properties::properties): Initialize faces\n\tand vertices.\n\t(patch::properties::get): Also fetch faces and vertices.\n\t(patch::properties::factory_defaults): Set faces and vertices.\n\n2007-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* Change copyright notices in all files that are part of Octave to\n\tGPLv3 or any later version.\n\n2007-10-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (urlget): Disable use of EPSV mode.\n\n2007-10-11  Brian Gough  <bjg@network-theory.co.uk>\n\n\t* DLD-FUNCTIONS/fftn.cc, DLD-FUNCTIONS/regexp.cc, dirfns.cc,\n\tinput.cc: Spelling fixes.\n\n2007-10-10  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-sbm-sbm.cc (bool_matrix_to_double_matrix):\n\tNew conversion function.\n\t(install_sbm_sbm_ops): Install it.\n\n\t* ov-re-mat.cc (double): Handle sparse as a special case.\n\n2007-10-10  Olli Saarela  <Olli.Saarela@kcl.fi>\n\n\t* data.cc, debug.cc, dirfns.cc, error.cc, file-io.cc, help.cc,\n\tload-save.cc, ov-fcn-inline.cc, parse.y, pr-output.cc, symtab.cc,\n\tsyscalls.cc, toplev.cc, variables.cc, DLD-FUNCTIONS/bsxfun.cc,\n\tDLD-FUNCTIONS/cellfun.cc, DLD-FUNCTIONS/fft.cc,\n\tDLD-FUNCTIONS/fft2.cc, DLD-FUNCTIONS/fftw.cc,\n\tDLD-FUNCTIONS/gcd.cc, DLD-FUNCTIONS/lsode.cc,\n\tDLD-FUNCTIONS/luinc.cc, DLD-FUNCTIONS/matrix_type.cc,\n\tDLD-FUNCTIONS/rand.cc, DLD-FUNCTIONS/regexp.cc,\n\tDLD-FUNCTIONS/sparse.cc, DLD-FUNCTIONS/spchol.cc,\n\tDLD-FUNCTIONS/splu.cc, DLD-FUNCTIONS/spparms.cc: Spelling fixes.\n\n2007-10-10  Kim Hansen  <kimhanse@gmail.com>\n\n\t* DLD-FUNCTIONS/lpsolve.cc: Delete.\n\t* Makefile.in (DLD_XSRC): Remove it from the list.\n\n\t* data.cc (Fsqueeze): Document 2d behaviour.\n\t* ov-range.h (octave_range::squeeze): New function.\n\n2007-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (urlget_cleanup): New function.\n\t(urlget): Protect call to curl_easy_perform with\n\tBEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE and\n\tEND_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE.\n\n2007-10-09  David Bateman  <dbateman@free.fr>\n\n\t* input.cc (accept_line): Drop this function and remove automatic\n\tinsertion of closing quotes as the transpose operator confuses it.\n\t(initialize_command_input): Remove accept_line from here as well.\n\n2007-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* ov-mapper.cc (octave_mapper::apply): If possible, use\n\td_d_map_fcn to handle complex values which have imag(z) == 0.\n\n\t* DLD-FUNCTIONS/urlwrite.cc (Furlwrite, Furlread) [! HAVE_CURL]:\n\tThrow error instead of returning empty string hiding error message\n\tin third return value.\n\t(progress_func): Delete.\n\t(Furlread): Don't set progress callback for curl.\n\t(write_data, form_query_string, urlget): Now static.\n\n2007-10-08  David Bateman  <dbateman@free.fr>\n\n\t*  input.cc (quoting_filename): Function to add a leading quote to\n\ta string if needed.\n\t(accept_line): Function to check if a string needs a closing quote\n\tbefore calling the rl_newline function.\n\t(initialize_command_input): Initialize completer_quote_characters,\n\tfilename_quote_characters, quoting_function,\n\tuser_accept_line_function.\n\n\t* data.cc (template <class T> static make_diag (...)): New\n\ttemplate class version of make_diag. Make other make_diag\n\tfunctions depend on it.\n\t( static octave_value make_diag (const octave_value&,\n\toctave_idx_type)): Treat all possible internal Octave types.\n\n2007-10-08  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc \t(save_vars, dump_octave_core):\n\tDon't pass INFNAN_WARNED to do_save.\n\t(do_save): Delete unused arg, INFNAN_WARNED.\n\tDon't pass INFNAN_WARNED to save_ascii_data.\n\t* ls-oct-ascii.cc (save_ascii_data_for_plotting):\n\tDon't pass INFNAN_WARNED to save_ascii.\n\t(save_ascii_data): Delete unused arg, INFNAN_WARNED.\n\n\t* ov.h (octave_value::save_ascii): Delete unused arg, INFNAN_WARNED.\n\t* ov-base-int.cc (octave_base_int_matrix<T>::save_ascii,\n\toctave_base_int_scalar<T>::save_ascii): Likewise.\n\t* ov-base-sparse.cc (octave_base_sparse<T>::save_ascii): Likewise.\n\t* ov-base.cc (octave_base_value::save_ascii): Likewise.\n\t* ov-bool-mat.cc (octave_bool_matrix::save_ascii): Likewise.\n\t* ov-bool.cc (octave_bool::save_ascii): Likewise.\n\t* ov-cell.cc (octave_cell::save_ascii): Likewise.\n\t* ov-fcn-handle.cc (octave_fcn_handle::save_ascii): Likewise.\n\t* ov-fcn-inline.cc (octave_fcn_inline::save_ascii): Likewise.\n\t* ov-list.cc (octave_list::save_ascii): Likewise.\n\t* ov-struct.cc (octave_struct::save_ascii): Likewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::save_ascii): Likewise.\n\t* ov-range.cc (octave_range::save_ascii): Likewise.\n\n\t* ov-scalar.cc (octave_scalar::save_ascii): Remove warning about\n\treloading inf/nan values.  Delete unused arg, INFNAN_WARNED.\n\t* ov-complex.cc (octave_complex::save_ascii): Likewise.\n\t* ov-re-mat.cc (octave_matrix::save_ascii): Likewise.\n\t* ov-cx-mat.cc (octave_complex_matrix::save_ascii): Likewise.\n\n\t* ov-fcn-inline.cc (Finline): Use DEFUNX instead of DEFUN.\n\n2007-10-08  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* sighandlers.h (can_interrupt): Tag with OCTINERP_API.\n\t* sysdep.h (raw_mode, octave_popen, octave_pclose,\n\tsame_file_internal): Likewise.\n\n2007-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_base_stream::do_scanf):\n\tAlways allow MVAL to re resized if NR > 0.\n\t(FINISH_CHARACTER_CONVERSION): Likewise.\n\n\t* mappers.cc (install_mapper_functions): Undo previous change.\n\tFix doc string for lgamma.\n\t(xzlgamma): Delete.\n\n2007-10-05  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h.in (axes::properties): New property, colororder.\n\t* graphics.cc (default_colororder): New function.\n\t(axes::properties::properties, axes::properties::get,\n\taxes::properties::set_defaults,\n\taxes::properties::factory_defaults, ): Handle colororder.\n\n\t* mappers.cc (xzlgamma): New static function.\n\t(install_mapper_functions): Pass xzlgamma for c_c_map for lgamma\n\tmapper.  Pass 1 for can_ret_cmplx_for_real and set hi to\n\toctave_Inf.\n\n2007-10-04  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/symrcm.cc: Move static functions to top of file to\n\tavoid forward decls.\n\t(Q_enq): Delete unused arg QH.  Change all uses.\n\t(Q_deq): Delete unused arg QT.  Change all uses.\n\t(find_starting_node): Delete unused local variable J.\n\t(H_heapify_min, H_insert, find_starting_node, Fsymrcm):\n\tMove local variable decls to point of first use.\n\n\t* OPERATORS/op-streamoff.cc (STREAMOFF_COMP_OP):\n\tAvoid control-reaches-end-of-non-void-function warning.\n\n\t* pt-const.cc (tree_constant::dup): Avoid unused parameter warning.\n\n\t* pr-output.cc (set_real_format, set_real_matrix_format,\n\tset_complex_format, set_complex_matrix_format):\n\tDelete unused arg, SIGN.  Change uses.\n\n\t* oct-map.cc (Octave_map::Octave_map): Avoid shadow warning.\n\n\t* load-save.cc (write_header): Use reinterpret_cast to avoid\n\told-style cast warning.\n\n\t* data.cc (do_permute): Delete unused arg, FNAME.  Change all uses.\n\n\t* sysdep.cc (w32_set_octave_home, w32_set_quiet_shutdown,\n\tMINGW_signal_cleanup):\n\tOnly define if defined (__WIN32__) && !\tdefined (_POSIX_VERSION).\n\n2007-10-04  Jason Riedy  <jason@acm.org>\n\n\t* ls-mat5.cc (read_mat5_binary_data): Map miUTF16 to miUINT16,\n\tmiUTF32 to miUINT32.  The matfile format currently states that\n\twide UTF formats are in the same byte order as the integers.\n\t(read_mat5_binary_element): Replace all UTF16 and UTF32\n\tcharacters with the high bit set (value >127) by '?' and warn\n\tthat we've done so.\n\n2007-10-04  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* sysdep.cc (w32_set_octave_home): Base OCTAVE_HOME location on\n\toctinterp, not the main exe.\n\n2007-10-03  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (Fnorm): New function.\n\t(F__vnorm__): Delete.\n\n2007-10-03  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* DLD-FUNCTIONS/typecast.cc: Include <algorithm>.\n\n2007-10-03  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.cc (Octave_map::Octave_map (const dim_vector&,\n\tconst string_vector&)): Delete.\n\t(Octave_map::Octave_map (const dim_vector&, const Cell&)):\n\tNew function.\n\t* ov-struct.cc (Fstruct): Allow creation of empty struct arrays\n\twith field names.\n\n2007-10-01  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.cc ((color_property::color_property (const\n\toctave_value& val)): Undo change from 2007-09-26\n\t(patch::properties::properties): use the \"a\" modifier to\n\tface_color & edge_color properties\n\t(patch::properties::set): Undo change from 2007-09-26\n\t* graphics.h.in\t(color_property::color_property\n\t(const octave_value& val)): Undo change from 2007-09-26\n\n2007-10-01  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* octave.cc (octave_main): Add \"--line-editing\" option to force\n\treadline line editing.\n\n2007-09-28  David Bateman  <dbateman@free.fr>\n\n\t* ov-range.h (int8_array_value, int16_array_value, int32_array_value,\n\tint64_array_value, uint8_array_value, uint16_array_value,\n\tint32_array_value, uint64_array_value): New methods\n\n2007-09-28  Kai Habel  <kai.habel@gmx.de>\n\n\t* graphics.h.in (color_property::colormap_property (const Matrix&)):\n\tUse floating point math in calculation of colormap.\n\n2007-09-26  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (color_values::str2rgb): accept upper, lower and\n\tmixed-case versions of the string representing the color. Allow\n\tblack defined as \"k\" and white as \"w\".\n\t(color_property::color_property (const octave_value& val,\n\tconst radio_values &v)): Modify the constructor to also take a\n\tradio_values argument. Use it.\n\t(patch::properties::set): Change set_facecolor calls to initialize\n\tthe color_property argument with the available radio_values.\n\t* graphics.h.in (color_property::color_property\n\t(const octave_value& val, const radio_values &v)): Also pass a\n\tradio_values argument.\n\n\t* ov-range.h (sparse_matrix_value, sparse_complex_matrix_value):\n\tNew methods.\n\n\t* mk-pkg-add: Simplfy the autoload commands.\n\t* parse.y (Fautoload): Allow bare filename if file is in the same\n\tdirectory as the script from where the autoload command is run.\n\n2007-09-25  Matthias Drochner  <m.drochner@fz-juelich.de>\n\n\t* syscalls.cc (Fpopen2): Doc fix.\n\tUse \"sort -r\" instead of \"sort -nr\" in test.\n\n2007-09-18  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (input_event_hook, Finput_event_hook): Call\n\tcommand_editor::add_event_hook and\n\tcommand_editor::remove_event_hook intstead of\n\tcommand_editor::set_event_hook and\n\tcommand_editor::restore_event_hook.\n\n2007-09-17  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.14+.\n\n2007-09-17  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.14.\n\t(OCTAVE_API_VERSION): Now api-v26.\n\t(OCTAVE_RELEASE_DATE): Now 2007-09-17.\n\n\t* Makefile.in (DISTFILES): Add genprops.awk to the list.\n\n\t* ov-typeinfo.h (cat_op_fcn): Third arg in function pointer\n\ttypedef is now Array<octave_idx_type> instead of Array<int>.\n\n\t* file-io.cc (do_stream_open): Use binary mode by default.\n\n2007-09-14  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* genprop.awk: Handle \"a\" modifier.\n\n2007-09-14  Kai Habel  <kai.habel@gmx.de>\n\n\t* graphics.h.in (radio_values::contains): New function.\n\t(radio_values::validate): Use it.\n\t* graphics.cc (color_property::operator =): Call it instead of\n\tvalidate here.\n\n2007-09-13  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc (glpk): Pass LPX_FX, not LB_DB, to\n\tlpx_set_col_bnds when lb[i] == ub[i].\n\tFrom: Zhi Wang <zcwang@umich.edu>.\n\n\t* graphics.h.in (colormap_property::colormap_property):\n\tUse jet colormap as default.\n\n2007-09-12  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (text::properties::properties): Default color is\n\tblack, not white.\n\t* graphics.h (text::properties::color): Declare as color_property,\n\tnot octave_value.\n\n\t* graphics.h.in (root_figure::defaults, figure::defaults,\n\taxes::defaults, line::defaults, text::defaults, image::defaults,\n\tpatch::defaults, surface::defaults): New functions.\n\t* gripes.cc (gripe_not_implemented): New function.\n\t* gripes.h: Provide decl.\n\n2007-09-10  John W. Eaton  <jwe@octave.org>\n\n\t* genprops.awk: Add missing newline character at end of file.\n\tFrom Alexander Klimov <alserkli@inbox.ru>.\n\n2007-09-10  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (do_cat): Avoid invalid indexing into ra_idx vector.\n\n2007-09-06  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/__delaunay__.cc, DLD-FUNCRIONS/__voronoi__.cc,\n\tDLD-FUNCTIONS/convhulln.cc: Avoid variables in global scope\n\n2007-09-06  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (stamp-prereq): Add graphics.h to the dependency list.\n\n2007-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (INCLUDES): Remove graphics.h from the list.\n\t(DISTFILES): Include graphics.h.in in the list.\n\t(genprops.awk): New file.\n\t(graphics.h): New rule.\n\t(distclean): Remove graphics.h.\n\t* graphics.h.in: New file, from graphics.h.\n\t(graphics_handle): Now a class instead of typedef.  Adapt all uses.\n\t(OCTAVE_GRAPHICS_PROPERTY_INTERNAL, OCTAVE_GRAPHICS_PROPERTY,\n\tOCTAVE_GRAPHICS_MUTABLE_PROPERTY): Delete macros.\n\t(class root_figure, class figure, class axes, class line, class\n\ttext, class image, class patch, class surface): Use genprops.awk\n\tto generate property declarations and set/get functions.\n\t* graphics.h: Delete.\n\t* graphics.cc (nan_to_empty, empty_to_nan): Delete.\n\t(root_figure::properties::set, figure::properties::set,\n\taxes::properties::set, line::properties::set,\n\ttext::properties::set, image::properties::set,\n\tpatch::properties::set, surface::properties::set): Call\n\ttype-specific set functions to set properties.\n\t(root_figure::properties::set_currentfigure,\n\tfigure::properties::set_currentaxes, figure::properties::set_visible,\n\taxes::properties::get_title, axes::properties::get_xlabel,\n\taxes::properties::get_ylabel,  axes::properties::get_zlabel,\n\taxes::properties::set_title, axes::properties::set_xlabel,\n\taxes::properties::set_ylabel,  axes::properties::set_zlabel):\n\tDefine custom versions.\n\n2007-09-06  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/bsxfun.cc: New function.\n\t* DLD-FUNCTIONS/typecast.cc: New function.\n\t* Makefile.in (DLD_XSRC): Add bsxfun.cc and typecast.cc.\n\t* ov.cc (do_cat_op): Modify use of Array<int> to\n\tArray<octave_idx_type> and adjust where necessary.\n\t* ov.h (do_cat_op): ditto.\n\t* data.cc (do_cat): ditto.\n\t* pt-mat.cc (tree_matrix::rvalue): ditto.\n\n2007-09-05  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* oct-stream.cc (octave_base_stream::do_printf): Ignore precision\n\tportion of format string if printing Inf, NaN, or NA values.\n\n2007-09-05  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/sort.cc (mx_sort_sparse, mx_sort_sparse_indexed):\n\tNew template classes for sparse sort functions.\n\t(Fsort): Use them.\n\t* ov.h (octave_value (const Sparse<double>&, const MatrixType&),\n\toctave_value (const Sparse<Complex>&, const MatrixType&)): New\n\tconstructors.\n\t* ov.cc (octave_value::octave_value (const Sparse<double>&,\n\tconst MatrixType&), octave_value::octave_value (const\n\tSparse<Complex>&, const MatrixType&)): Define them.\n\t* ov-re-sparse.h (octave_sparse_matrix (const MSparse<double>&,\n\tconst MatrixType&), octave_sparse_matrix (const Sparse<double>&),\n\toctave_sparse_matrix (const Sparse<double>&, const MatrixType&)):\n\tNew constructors.\n\t* ov-cx-sparse.h (octave_sparse_complex_matrix (const MSparse<double>&,\n\tconst MatrixType&), octave_sparse_complex_matrix (const\n\tSparse<double>&), octave_sparse_complex_matrix (const\n\tSparse<double>&, const MatrixType&)): ditto.\n\n2007-09-04  Gabriele Pannocchia  <g.pannocchia@ing.unipi.it>\n\n\t* DLD-FUNCTIONS/__qp__.cc (qp): Use Wact(j) == i - n_eq when\n\tchecking for blocking constraint.  Don't resize lambda_tmp.  Only\n\tcompute Y = Aact.pseudo_inverse () if it is needed.\n\n2007-08-31  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* ls-mat-ascii.cc (get_lines_and_columns): Check beg variable for\n\tNPOS to avoid segmentation fault.\n\n\t* load-path.cc (load_path::do_find_file): Do not assume paths\n\tuse forward slashes.\n\n2007-08-30  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc (Fpause): Doc fix.\n\n2007-08-30  Gabriele Pannocchia  <g.pannocchia@ing.unipi.it>\n\n\t* DLD-FUNCTIONS/__qp__.cc (qp): Resize Wact to n_act-neq, not n_act.\n\n2007-08-29  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (class root_figure::properties):\n\tRename from root_figure::root_figure_properties.\n\t(class figure::properties): Rename from figure::figure_properties.\n\t(class axes::properties): Rename from axes::axes_properties.\n\t(class line::properties): Rename from line::line_properties.\n\t(class text::properties): Rename from text::text_properties.\n\t(class image::properties): Rename from image::image_properties.\n\t(class patch::properties): Rename from patch::patch_properties.\n\t(class surface::properties): Rename from surface::surface_properties.\n\n\t* base-list.h (octave_base_list::remove): Implement our own\n\tremove_if function here.\n\n2007-08-28  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.h (base_properties): Move class definition before\n\tdefinition of base_graphics_object class.  Provide forward\n\tdeclaration of base_graphics_object prior to definition of\n\tbase_properties.\n \t(base_graphics_object::get_properties): New virtual function.\n\t(graphics_object::get_properties, root_figure::get_properties,\n\tfigure::get_properties, axes::get_properties,\n\tline::get_properties, text::get_properties, image::get_properties,\n\tpatch::get_properties, surface::get_properties): New functions.\n\t(root_figure::properties, figure::properties, axes::properties,\n\tline::properties, text::properties, image::properties,\n\tpatch::properties, surface::properties): Data member now private.\n\n2007-08-27  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::do_find_file): Also files with non\n\trooted relative names.\n\t* load-save.cc (find_file_to_load): Likewise.  Also handle\n\tappending .mat to files with relative names.\n\n\t* graphics.cc (base_properties::mark_modified,\n\tbase_properties::override_defaults,\n\tbase_properties::delete_children, figure::get_default,\n\taxes::get_default): Move definitions here, from graphics.h.\n\t* graphics.h (class gh_manager): Move decl to end of file.\n\n\t* Cell.h (Cell::Cell (const octave_value_list&)): Create row\n\tvector instead of column vector.\n\n\t* pt-idx.cc (tree_index_expression::lvalue): Handle [x.a] =\n\t... style assignments.\n\t* ov-struct.cc (octave_struct::subsasgn): Handle case of RHS as\n\tcomma-separated list.\n\n\t* ov-cell.cc (gripe_failed_assignment): New function.\n\t(octave_cell::subsasgn): Call gripe_failed_assignment if assign\n\tmethods fail.\n\n2007-08-24  David Bateman  <dbateman@free.fr>\n\n\t* symtab.cc (void symbol_table::clear (void)): If the record in\n\tthe symbol table to clear is a user function that is a sub\n\tfunction with a static parent or if the parent is the current\n\tparent function, don't delete the record.\n\t(void symbol_table::clear_functions (void)): ditto.\n\t(void symbol_table::clear (const std::string&)): ditto.\n\t(void symbol_table::clear_function (const std::string&)): ditto.\n\n\t* graphics.h (class text): Add property color.\n\t* graphics.cc (text::text_properties::text_properties) ditto.\n\t(text::text_properties::set): ditto.\n\t(text::text_properties::get): ditto.\n\t(text::text_properties::factory_defaults): ditto.\n\n2007-08-24  John W. Eaton  <jwe@octave.org>\n\n\t* mappers.cc (dummyp): New function.\n\t(install_mapper_functions): Use it to handle character data in\n\tfinite, isinf, isna, and isnan functions.\n\n\t* load-path.cc (load_path::do_remove): Call remove_hook function\n\tbefore removing directory from list.\n\n2007-08-24  David Bateman  <dbateman@free.fr>\n\n\t* ov-bool-sparse.cc (DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA): Class\n\tis now logical.\n\t* ov-re-sparse.cc, ov-cx-sparse.cc\n\t(DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA): Class is now double.\n\t* ov-mapper.cc (octave_mapper::apply): Use is_sparse_type method\n\trather than comparing class name.\n\t* ls-mat5.cc (save_mat5_element_length, save_mat5_binary_element):\n\tditto.\n\t* pt-mat.cc (tree_matrix:rvalue): sparse matrices are now of class\n\t\"double\" or \"logical\", create new single type concat clause for\n\tthem.\n\t* mex.cc (get_class_id): No longer need to special case sparse\n\tmatrices.\n\n\t* DLD-FUNCTIONS/__delaunayn__.cc, DLD-FUNCTIONS/convhulln.cc,\n\tDLD-FUNCTIONS/tsearch.cc, DLD-FUNCTIONS/__voronoi__.cc: New\n\tfunctions ported from octave-forge.\n\t* DLD-FUCTIONS/__dsearchn__.cc: New file.\n\t* DLD-FUNCTIONS/__voronoi__.cc: Return point at infinity and\n\tinclude it in the polygrons of the Voronoi diagram for\n\tcompatibility.\n\t* Makefile.in: Add specific build targets for __delanayn__.cc,\n\tconvhulln.cc and __voronoi__.cc to link to Qhull.\n\t(DLD_SRC): Add new functions.\n\t(OCTAVE_LIBS): Add QHULL_LIBS\n\n2007-08-22  David Bateman  <dbateman@free.fr>\n\n\t* variables.cc (Fmunlock): Call munlock and not mlock.\n\t* symtab.cc (symbol_record::mark_as_formal_parameter): Typo.\n\n2007-08-10  John W. Eaton  <jwe@octave.org>\n\n\t* pt-idx.cc (tree_index_expression::get_struct_index): Improve\n\terror message.\n\t* ov-struct.cc (Fstruct, Fcell2struct): Trap invalid field names here.\n\n2007-08-10  Peter A. Gustafson  <petegus@umich.edu>\n\n\t* graphics.h, graphics.cc (axes::axes_properties): New properties,\n\txaxislocation and yaxislocation.\n\n2007-08-10  Kai Habel  <kai.habel@gmx.de>\n\n\t* graphics.cc, graphics.h (patch): New class.\n\t(axes::axes_properties): New properties, clim and climmode.\n\t(surface::surface_properties::surface_properties): Handle patch.\n\t(F__go_patch__): New function.\n\n2007-07-30  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_number::mxArray_number (int, const char **)):\n\tFirst arg is now mwSize.\n\t(max_str_len): Return mwSize value, not int.\n\t* mxarray.h.in (mxArray::mxArray (int, const char **)):\n\tFirst arg is now mwSize.\n\t(mxArray::mxArray (mxClassID, mwSize, mwSize, int, mxComplexity)):\n\tThird arg is now mwSize.\n\t(mxArray::get_string (char *, int)): Second arg is now mwSize.\n\n2007-07-26  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc: Include glpk/glpk.h if\n\tHAVE_GLPK_GLPK_H is defined.\n\n2007-07-26  David Bateman  <dbateman@free.fr>\n\n\t* pr-output.cc (Frats): Return character array with same number of\n\trows as original value.\n\n2007-07-26  John W. Eaton  <jwe@octave.org>\n\n\t* pt-bp.h (MAYBE_DO_BREAKPOINT): Rename cur_fcn to xfcn.\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.13+.\n\n2007-07-25  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.13\n\t(OCTAVE_API_VERSION): Now api-v25.\n\t(OCTAVE_RELEASE_DATE): Now 2007-07-25.\n\n\t* pt-bp.h (MAYBE_DO_BREAKPOINT): Rename fcn to curr_fcn.\n\n2007-07-25  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in: \tAdjust DISTFILES to allow out of tree \"make dist\"\n\tto work.\n\n2007-07-24  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.cc (color_property::operator = (const octave_value&)):\n\tNew method.\n\t* graphics.h: Provide decl.\n\n2007-07-24  Rafael Laboissiere  <rafael@debian.org>\n\n\t* oct-conf.h.in (OCTAVE_CONF_RUNTEST): Delete definition.\n\t* toplevel.cc (Foctave_config_info): Remove RUNTEST from struct.\n\n2007-07-23  David Bateman  <dbateman@free.fr>\n\n\t* pr-output.cc (rat_format, rat_string_len): Global variable\n\tcontrolling behavior of rational approximation. Use throughout.\n\t(class pr_rational_float): New class for rational approximation of\n\tfloats, specifically with the << operator defined.\n\t(std::ostream& operator << (std::ostream&, const\n\tpr_rational_float&)): Operator to print rational approximations of\n\tdouble values.\n\t(std::string rational_approx (double, int)): Function to convert a\n\tdouble value to a string of maximum length giving the rational\n\tapproximation.\n\t(pr_any_float): Include the output of rational approximations.\n\t(Fformat): Add the \"rat\" format as an option.\n\t(Frats): New function.\n\n2007-07-23  Aquil H. Abdullah  <aquil.abdullah@gmail.com>\n\n\t* mex.cc (mxCreateStructArray): Declare second arg as const.\n\t* mexproto.h (mxCreateStructArray): Ditto.\n\n2007-07-20  David Bateman  <dbateman@free.fr>\n\n\t* zfstream.cc (BUFSIZE): Increase default buffer size to 256kB\n\t(gzfilebuf::underflow): Stash the last 16 characters read, so as\n\tto avoid calling pbackfail as much as possible.\n\n2007-07-18  David Bateman  <dbateman@free.fr>\n\n\t * zfstream.cc (int_type gzfilebuf::pbackfail (int_type)): New\n\t method to putback a character when the putback position in the\n\t internal buffer doesn't exist.\n\t * zfstream.h (int_type pbackfail (int_type)): Declaration it.\n\n2007-07-14  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* ov-bool-sparse.cc (octave_sparse_bool_matrix:load_hdf5):\n\tUse OCTAVE_LOCAL_BUFFER for temporary boolean value.\n\n2007-06-27  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/sparse.cc (Fspdiag): Ensure spdiag(zeros(1,0)) returns\n\t0x0 matrix. Doc update.\n\t* data.cc (Fdiag): Doc update.\n\n2007-06-28  John W. Eaton  <jwe@octave.org>\n\n\t* ov-cell.cc (octave_cell::subsasgn): Given x = {}, convert to\n\tstruct for assignments like x(1).f = val;\n\n\t* oct-stream.cc (octave_scan_1): New function\n\t(octave_scan): Use it.  Handle fmt.width.\n\n\t* graphics.h (axes::axes_properties::visible): New data member.\n\t* graphics.cc (axes::axes_properties::axes_properties,\n\taxes::axes_properties::set, axes::axes_properties::get,\n\taxes::axes_properties::factory_defaults): Handle visible property.\n\n2007-06-27  Kai Habel  <kai.habel@gmx.de>\n\n\t* graphics.h (color_values::color_values): Arg is now std:string\n\tinstead of char.  Call str2rgb, not c2rgb.\n\t* graphics.h, graphics.cc: (color_values::str2rgb): Rename from\n\tc2rgb.  Handle long color names, not just single char abbreviations.\n\n2007-06-27  David Bateman  <dbateman@free.fr>\n\n\t* load-save.cc (Fsave): Ensure header is written for non\n\texistent file with \"-append\".\n\t* ls-hdf5.h: First steps towards having append work for hdf5.\n\n2007-06-26  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc (Fsave): Open files correctly for -append.\n\tDon't write file headers if appending.  Error for -append -hdf5.\n\n2007-06-25  Olaf Till  <i7tiol@t-online.de>\n\n\t* oct-stream.h (octave_stream_list::list): Use std::map.\n\t(octave_stream_list::curr_len): Delete data member.\n\t(octave_stream_list::octave_stream_list): Fix initializations.\n\n\t* oct-stream.cc (octave_steam_list::do_insert,\n\toctave_steam_list::do_lookup, octave_steam_list::do_remove,\n\toctave_steam_list::do_clear, octave_steam_list::do_list_open_files,\n\toctave_steam_list::do_open_file_numbers,\n\toctave_steam_list::do_get_file_number):\n \tUse new octave_stream_list::list type.\n\t(octave_stream_list::do_insert): Insert octave_stream with key\n\tcorresponding to file-descriptor.\n\t(octave_stream_list::do_insert, octave_steam_list::insert):\n\tRemove const qualifier of argument.\n\n2007-06-18  Søren Hauberg  <hauberg@gmail.com>\n\n\t* DLD-FUNCTIONS/__lin_interpn__.cc: Replace octave_NaN with octave_NA.\n\n2007-06-15  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h (OCTAVE_GRAPHICS_PROPERTY_INTERNAL,\n\tOCTAVE_GRAPHICS_PROPERTY, OCTAVE_GRAPHICS_MUTABLE_PROPERTY):\n\tNew macros. Use them to declare individual properties and define\n\taccessor methods for each property in the property classes.\n\n2007-06-15  Kai Habel  <kai.habel@gmx.de>\n\n\t* graphics.cc (Fget, Fset): Handle vectors of handles.\n\n2007-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc (octave_popen, octave_pclose): New functions.\n\t* sysdep.h: Provide decls.\n\n\t* oct-procbuf.cc (procbuf::open): Use octave_popen.\n\t(procbuf::close): Use octave_pclose.\n\t* oct-prcstrm.cc (octave_oprocstream::octave_oprocstream,\n\toctave_iprocstream::ictave_oprocstream): Likewise.\n\n\t* graphics.h (text::text_properties::rotation): New data member.\n\t* graphics.cc (text::text_properties::text_properties,\n\ttext::text_properties::set, text::text_properties::get,\n\ttext::text_properties::factory_defaults): Handle rotation property.\n\n2007-06-14  Kai Habel  <kai.habel@gmx.de>\n\n\t* graphics.cc (color_values::c2rgb): Also accept 'k' for black.\n\n2007-06-14  David Bateman  <dbateman@free.fr>\n\n\t* ov-ch-mat.h (idx_vector index_vector (void) const): Remove\n\tdefinition.\n\t* ov-ch-mat.cc (idx_vector index_vector (void) const): Move it\n\there. Special case \":\" case for compatibility.\n\n2007-06-13  John W. Eaton  <jwe@octave.org>\n\n\t* ov-re-mat.cc (octave_matrix::load_ascii):\n\tDo a better job of handling read errors and empty matrices.\n\t* ov-cx-mat.cc (octave_complex_matrix::load_ascii): Likewise.\n\t* ov-bool-mat.cc (octave_bool_matrix::load_ascii): Likewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::load_ascii): Likewise.\n\n2007-06-13  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/minmax.cc (MINMAX_BODY): Don't treat as single\n\targument if arg2 is empty and nargin=2.\n\n2007-06-13  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.h, graphics.cc: Move class declarations to graphics.h.\n\tMove larger functions outside of class declarations in graphics.cc.\n\n2007-06-12  Benjamin Lindner  <lindnerben@gmx.net>\n\n\t* DLD-FUNCTIONS/cellfun.cc: Use fullfile to generate filenames\n\tinstead of assuming / will work as directory separator.\n\n2007-06-12  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/interpn.cc: Remove it.\n\t* DLD-FUNCTIONS/__lin_interpn__.cc: Move it. This is now a support\n\tfunction of interpn.m.\n\t* Makefile.in (DLD_XSRC): Remove interpn.cc and add __lin_interpn__.cc.\n\n2007-06-07  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-handles.cc (octave_fcn_handle::save_hdf5): More care that\n\tall open HDF5 descriptors are closed.\n\t(octave_fcn_handle::load_hdf5): Ditto.\n\n2007-06-06  Benjamin Lindner  <lindnerben@gmx.net>\n\n\t* utils.cc [__MINGW32__]: Don't define HAVE_C99_VSNPRINTF.\n\n2007-06-06  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* defaults.h.in, ls-hdf5.h, ov-complex.h, ov-cx-mat.h, ov-intx.h,\n\tsysdep.h: Sprinkle with OCTINTERP_API as needed.\n\n2007-06-05  John W. Eaton  <jwe@octave.org>\n\n\t* help.h (raw_help): Tag with OCTINTERP_API.\n\n\t* Makefile.in (INCLUDES): Remove mxarray.h from the list so that\n\tit is not distributed.\n\t(EXTRAS): Add mxarray.h to the list so that it is installed.\n\n\t* sysdep.cc (same_file_internal) [OCTAVE_USE_WINDOWS_API]:\n\tAvoid leaking file handles.\n\n2007-05-08 Michael Weitzel  <michael.weitzel@uni-siegen.de>\n\n\t* DLD-FUNCTIONS/symrcm.cc: Fix for queuing error that might cause\n\tan infinite loop.\n\n2007-06-04  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (Fislogical): Rename from Fisbool.\n\tMake isbool an alias for islogical.\n\n2007-06-03  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (DISTFILES): Add mxarray.h.in\n\t(install-inc): Modify target so that mxarray.h is installed\n\tcorrectly.\n\t(distclean): Remove mxarray.h on distclean.\n\t* mex.cc: Use mwSize for dimensions and mwIndex for indexing\n\tthroughout, with the exception of struct key indexes.\n\t* mexproto.h: ditto.\n\t* mxarray.h: remove.\n\t* mxarray.h.in: Copy here and define mwSize, mwIndex, and use\n\tthroughout.\n\t* ov-bool-mat.cc (octave_bool_matrix::as_mxArray): Use mwSize and\n\tmwIndex.\n\t* ov-bool-sparse (octave_sparse_bool_matrix::as_mxArray): ditto.\n\t* ov-cell.cc (octave_cell:as_mxArray): ditto.\n\t* ov-ch-mat.cc (octave_char_matrix:as_mxArray): ditto.\n\t* ov-cx-mat.cc (octave_complex_matrix::as_mxArray): ditto.\n\t* ov-cx-sparse.cc (octave_sparse_complex_matrix::as_mxArray): ditto.\n\t* ov-int.h (as_mxArray): ditto.\n\t* ov-range.cc (octave_range:as_mxArray): ditto.\n\t* ov-re-mat.cc (octave_matrix:as_mxArray): ditto.\n\t* ov-re-sparse.cc (octave_sparse_matrix::as_mxArray): ditto.\n\t* ov-struct.cc (octave_struct::as_mxArray): ditto.\n\n2007-06-02  David Bateman  <dbateman@free.fr>\n\n\t* graphics.cc (color_property class): g++ doesn't like anonymous\n\tenums. Give type to color_type enum.\n\n2007-05-31  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.cc (radio_values, radio_property, color_values):\n\tNew classes.\n\t(color_property class): Handle both color and radio values.\n\n2007-05-31  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (main_loop): Improve bad_alloc error message.\n\n\t* octave.cc (execute_command_line_file, execute_eval_option_code):\n\tLikewise.\n\n2007-05-31  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* toplev.cc (octave_atexit_functions):\n\tNow std::list instead of std::stack.\n\t(do_octave_atexit): Adapte to octave_atexit_functions as list.\n\t(Fatexit): Allow second arg of false to remove element from list.\n\n\t* DLD-FUNCTIONS/symrcm.cc: Use ! instead of \"not\".\n\n\t* sysdep.cc (same_file_internal) [OCTAVE_USE_WINDOWS_API]:\n\tUse INVALID_HANDLE_VALUE, not INVALID_FILE_HANDLE.\n\n2007-05-28  G. D. McBain  <geordie_mcbain@yahoo.com.au>\n\n\t* ov-list.cc (append): Doc fix.\n\n2007-05-28  John W. Eaton  <jwe@octave.org>\n\n\t* pt-loop.cc (DO_ND_LOOP): Avoid parser problem with obsolete g++.\n\n2007-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.12+.\n\n2007-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.12.\n\t(OCTAVE_RELEASE_DATE): Now 2007-05-23.\n\n\t* parse.y (make_anon_fcn_handle): Don't build assignment expression.\n\t* ov-fcn-handle.cc (octave_fcn_handle::print_raw):\n\tDon't split assignment expression.\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tSpecial case for inline function body evaluation.\n\n2007-05-22  John W. Eaton  <jwe@octave.org>\n\n\t* pt-fcn-handle.cc (tree_anon_fcn_handle::rvalue):\n\tSet current function as parent of anonymous function handle.\n\n\t* Makefile.in (uninstall): Also remove\n\t$(DESTDIR)$(octincludedir)/octave, $(DESTDIR)$(octincludedir),\n\t$(DESTDIR)$(octlibdir), and $(DESTDIR)$(octfiledir).\n\n2007-05-22  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* debug.cc, error.cc, load-save.cc, oct-hist.cc, sighandlers.cc,\n\tsymtab.cc: Fix typos.\n\n2007-05-22  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.11+.\n\n2007-05-22  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.11.\n\t(OCTAVE_API_VERSION): Now api-v24.\n\t(OCTAVE_RELEASE_DATE): Now 2007-05-22.\n\n2007-05-21  David Bateman  <dbateman@free.fr>\n\n\t* debug.cc (Fdbstop): handle integer, vector and multiple line\n\targuments.\n\t(Fdbclar): ditto. Eliminate extraneous debugging messages.\n\n2007-05-21  Søren Hauberg  <hauberg@gmail.com>\n\n\t* load-path.cc (Fpath, Frehash): Replace \"LOADPATH\" with \"load\n\tpath\" in doc strings.\n\n\t* parse.y (Feval): Add example.\n\n2007-05-21  David Bateman  <dbateman@free.fr>\n\n\t* error.cc (rethrow_error): Use NULL name so that \"error:\" is not\n\tadded to the message\n\t(Frethrow): Correctly treat empty stack.\n\n2007-05-21  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.h (Octave_map::numel): Return number of array elements,\n\tnot number of map elements.\n\t(Octave_map::nfields): Rename from length.\n\t(Octave_map::empty): Delete.\n\tChange all uses of empty to check nfields () == 0 instead.\n\n2007-05-21  Søren Hauberg  <soren@hauberg.org>\n\n\t* help.cc (Fautoload): Doc fix.\n\t* variables.cc (Fiscommand): Doc fix.\n\n2007-05-19  David Bateman  <dbatemna@free.fr>\n\n\t* ov-fcn-inline.cc (Fvectorize): Doc fix.\n\n2007-05-16  Søren Hauberg  <soren@hauberg.org>\n\n\t* ov.cc (Fsubsref, Fsubsasgn): Doc fix.\n\n2007-05-16  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.h (load_path::sys_path): New static data member.\n\t(load_path::system_path): New static function.\n\t(load_path::do_system_path): New function.\n\t* load-path.cc (Vsystem_path): Delete.\n\t(load_path::do_initialize): Use sys_path, not Vsystem_path.\n\t(Fpathdef): Call load_path::system_path instead of using Vsystem_path.\n\t* ls-mat5.cc (read_mat5_binary_element): Likewise.\n\t* ov-fcn-handle.cc (octave_fcn_handle::set_fcn): Likewise.\n\n2007-05-16  David Bateman  <dbateman@free.fr>\n\n\t* load_pathc.cc (std::string octave_system_path (void)): New\n\tfunction.\n\t* load-path.h (std::string octave_system_path (void)): Declare it.\n\n\t* load-save.cc (static load_save_format get_file_format\n\t(std::istream&, const std::string&)): Add filename argument, and\n\tpass it to read_mat5_binary_header. Use new format throughout file.\n\t(Fload): Don't allow gzip of matlab v7 files as the files\n\tthemselves include compression.\n\n\t* ls-mat5.cc (arrayclsstype:MAT_FILE_WORKSPACE_CLASS): New class\n\ttype.\n\t(read_mat5_binary_element): Workspaces, don't have dimensions, so\n\tdon't read them. Implement read of matlab objects, but only use\n\tthem for inline functions. Implement reading of function and\n\tworkspace classes.\n\t(read_mat5_binary_header): Add filename argument. Read sub-system\n\tspecific data block given as an offset in bytes 117 to 124.\n\t(save_mat5_binary_element): Include saving of inline functions.\n\n\t* ls-mat5.h (read_mat5_binary_header): Include filename.\n\n\t* ov-fcn-handle.cc (octave_fcn_handle_save_ascii,\n\toctave_fcn_handle::load_ascii, octave_fcn_handle::save_binary,\n\toctave_fcn_handle::load_binary, octave_fcn_handle::save_hdf5,\n\toctave_fcn_handle::load_hdf5): Save and reload the local symbol\n\ttable of the user function associated with anonymous function\n\thandles. Save and load the absolute path and the exec_prefix for\n\tnormal function handles and use then to find equivalent functions\n\tbetween different installations of Octave. Attempt to maintain\n\tbackward and forward compatibility.\n\t(Ffunctions): Additional outputs, including the workspace of\n\tanonymous functions, and more compatiable outputs.\n\n\t* ov-fcn-handle.h (user_function_value): Expose the user function\n\tvalue of a function handle.\n\n\t* ov-fcn-inline.cc (Octave_map octave_fcn_inline::map_value\n\t(void) const): Return a structure compatiable with matlab's class\n\timplementation of inline functions.\n\n\t* ov-fcn-inline.h (map_value): Declare it.\n\n2007-05-14  Bob Weigel  <rweigel@gmu.edu>\n\n\t* DLD-FUNCTIONS/svd.cc: Doc fix.\n\n2007-05-14  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* DLD-FUNCTIONS/fft.cc (do_fft): Handle empty matrices.  New tests.\n\n2007-05-14  Søren Hauberg  <soren@hauberg.org>\n\n\t* toplev.cc (Fatexit): Simplify example in doc string.\n\t* help.cc (Flookfor): Doc fix.\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun):\n\tReformat to avoid long lines in doc string example.\n\n2007-05-13  Søren Hauberg  <soren@hauberg.org>\n\n\t* toplev.cc (Fquit): Doc fix.\n\t* help.cc (Fhelp): Doc fix.\n\t* oct-hist.cc (Fsaving_history): Doc fix.\n\n2007-05-11  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (symbol_out_of_date):\n\tAlways check for files that have gone missing.\n\n2007-05-08 Michael Weitzel  <michael.weitzel@uni-siegen.de>\n\n\t* DLD-FUNCTIONS/symrcm.cc: New function for Reverse Cuthill-McKee\n\tpermutation.\n\n2007-05-07  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.cc (Octave_map::resize): Handle case of no keys.\n\t(keys_ok): Rename from equiv_keys.  Return value is now status.\n\tPass key names as string_vector reference arg.\n\t(Octave_map::assign (const octave_value_list&, const Octave_map&)):\n\tCall keys_ok, not equiv_keys.  Handle case of no keys.\n\n2007-04-30  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (%.df : %.cc): Use mv instead of\n\t$(simple-move-if-change-rule).\n\n2007-04-30  David Bateman  <dbateman@free.fr>\n\n\t* pt-loop.cc (DO_ND_LOOP): New args, CONV and ARG.\n\tUse octave_idx_type instead of int for loop counters.\n\tRemove redundant assignments to variable \"quit\" as it is\n\talways defined in quit_loop_now.\n\tSpecial case rows = 0 and 1 cases in loops over arrays.\n\tInclude some of the code that was separate from the macro\n\tDO_ND_LOOP in the macro itself\n\t(tree_simple_for_command::eval): USE DO_ND_LOOP for all loops.\n\t(DO_LOOP): Delete.\n\n2007-04-30  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mex::cleanup): Don't call unmark for elements of the set\n\tinside the loop.  From Laurent Mazet <laurent.mazet@motorola.com>.\n\n2007-04-30  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-int-conv.cc: Define sq and dq string conversion\n\toperators.  Delete old char_matrix_str conversions.\n\t* OPERATORS/op-int-conv.cc (install_int_conv_ops): Install them.\n\n2007-04-27  Benjamin Lindner  <lindnerb@users.sourceforge.net>.\n\n\t* octave.cc (execute_startup_files): Call same_file to check for\n\talready executed init files.\n\n2007-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc (same_file_internal): New function.  POSIX code\n\tfrom same_file in utils.cc.  Windows code from\n\tBenjamin Lindner  <lindnerb@users.sourceforge.net>.\n\tDon't canonicalize file names.\n\tAlso return false if stat calls fail.\n\t* sysdep.h: Provide decl.\n\t* utils.cc (same_file): Use same_file_internal.\n\n2007-04-27  David Bateman  <dbateman@free.fr>\n\n\t* graphic.cc (get_property_form_handle, set_property_in_handle):\n\tNew functions.\n\t* grahics.h: New file.\n\t* mex.cc (mexGet, mexSet): use the above to implement mexGet\n\tand mexSet.\n\t* Makefile.in (INCLUDES): Add graphics.h\n\n2007-04-26  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tOnly deal with varargout if ret_list->takes_varargs () is true.\n\n2007-04-26  Søren Hauberg  <soren@hauberg.org>\n\n\t* DLD-FUNCTIONS/urlwrite.cc: Doc fix.\n\n2007-04-26  David Bateman  <dbateman@free.fr>\n\n\t* pt-loop.cc (tree_simple_for_command::eval (void)): Correct\n\treshaping of dim_vector in for loop for multi-dimensional array.\n\n2007-04-26  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc (find_file_to_load): Only consider regular files.\n\n2007-04-24  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.cc (color_property): Eliminate alpha channel from RGB\n\tcolor spec.\n\n2007-04-23  Shai Ayal  <shaiay@users.sourceforge.net>\n\n\t* graphics.cc (color_property::color_property):\n\tNew arg A for alpha channel.  Set rgba instead of red, green, blue.\n\t(color_property::color_property (char)): New constructor.\n\t(color_propery::rgba): New data member.\n\t(color_property::red, color_property::green, color_property::blue):\n\tDelete.\n\t(color_property::validate): Use rgba.\n\t(color_property::c2rgba): New function.\n\n2007-04-23  Søren Hauberg  <soren@hauberg.org>\n\n\t* data.cc (Fsize_equal): Allow more than two arguments.\n\n2007-04-20  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l (deftypefn):\n\t(Vautomatic_replot): Delete static variable.\n\t(Fautomatic_replot): Delete function.\n\n\t* toplev.cc (Fcasesen): Delete obsolete function.\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l (gnuplot::makeplot): Check\n\twhether caller is \"splot\", not \"gsplot\".\n\n2007-04-19  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (is_keyword_token): Delete all_va_args_kw switch case.\n\t* octave.gperf: Remove all_va_args_kw from the list.\n\n2007-04-19  Daniel J. Sebald  <daniel.sebald@ieee.org>\n\n\t* syscalls.cc: Fix popen2 test to stop trying after 100 times\n\tthrought the loop.\n\n2007-04-16  Geordie McBain  <geordie.mcbain@aeromech.usyd.edu.au>\n\n\t* ov-fcn-inline.cc (Fargnames): Doc fix.\n\n2007-04-13  Geordie McBain  <geordie.mcbain@aeromech.usyd.edu.au>\n\n\t* DLD-FUNCTIONS/find.cc (Ffind): Doc fix.\n\n2007-04-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DOCSTRINGS): Don't echo commands.\n\t(doc-files): Use mv, not $(simple-move-if-change-rule).\n\n\t* data.cc (Fnot, Fuplus, Fuminus, Ftranspose, Fctranspose, Fplus,\n\tFminus, Fmtimes, Fmrdivide, Fmpower, Fmldivide, Flt, Fle, Feq,\n\tFge, Fgt, Fne, Ftimes, Frdivide, Fpower, Fldivide, Fand, For):\n\tNew functions.\n\n2007-04-09  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (line::line_properties::markeredgecolor,\n\tline::line_properties::markerfacecolor): New properties.\n\n2007-04-06  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (F__vnorm__): New function.\n\n\t* pt-fcn-handle.cc (tree_anon_fcn_handle::param_list,\n\ttree_anon_fcn_handle::cmd_list,\ttree_anon_fcn_handle::ret_list,\n\ttree_anon_fcn_handle::sym_tab): Delete.  Remove all uses.\n\t(tree_anon_fcn_handle::fcn): New data member.\n\t(tree_anon_fcn_handle::tree_anon_fcn_handle): Initialize it.\n\t(tree_anon_fcn_handle::rvalue, tree_anon_fcn_handle::dup):\n\tExtract parameter list, return list, function body, and symbol\n\ttable from fcn.\n\t(tree_anon_fcn_handle::parameter_list, tree_anon_fcn_handle::body):\n\tForward request to fcn.\n\n\t* ov-usr-fcn.h (octave_user_function::local_sym_tab): Rename from\n\tsym_tab.  Change all uses.\n\t(octave_user_function::sym_tab): New function.\n\n\t* octave.cc (execute_command_line_file):\n\n2007-04-05  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/regexp.cc (Fregexprep): Correct iteration over\n\tcell arrays so that the source and pattern are iterated seperately\n\tin the same manner as matlab.\n\n2007-04-05  Laurent Mazet  <laurent.mazet@motorola.com>\n\n\t* mex.cc (mxArray_octave_value::get_string): Copy nel elements,\n\tnot buflen elements.\n\n2007-04-05  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (DO_DOUBLE_CONV): New macro.\n\t(do_printf): Use it.\n\n2007-04-04  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (octave_yes_or_no): Force interactive_input to use readline.\n\n\t* octave.cc (execute_eval_option_code): Catch bad::alloc here.\n\n2007-04-03  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/urlwrite.cc (Furlwrite, Furlread):\n\tUse && for logical, not &.\n\n\t* DLD-FUNCTIONS/qr.cc (Fqr): Clarify nargin check.\n\n\t* error.cc (Frethrow): Add braces to avoid ambiguous if/else.\n\t* oct-stream.cc (octave_scan<>): Likewise.\n\t* DLD-FUNCTIONS/colamd.cc (Fetree): Likewise.\n\t* DLD-FUNCTIONS/sort.cc (mx_sort, mx_sort_indexed): Likewise.\n\n\t* ov-fcn-handle.cc (make_fcn_handle): Pass ultimate parent\n\tfunction name to lookup_function.\n\n2007-03-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/filter.cc (filter): Fix typo in doc string.\n\tFrom Utkarsh Upadhyay <musically.ut@gmail.com>.\n\n2007-03-28  Rafael Laboissiere  <rafael@debian.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc: Fix #ifdef logic around GLPK_PRE_4_14.\n\n2007-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.10+\n\n2007-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.10.\n\t(OCTAVE_API_VERSION): Now api-v23.\n\t(OCTAVE_RELEASE_DATE): Now 2007-03-27.\n\n\t* version.h (OCTAVE_COPYRIGHT): Update for 2007.  Add \"and others\".\n\t(X_OCTAVE_WARRANTY_STATEMENT): Rename from OCTAVE_WARRANTY_STATEMENT.\n\tAccept arg.\n\t(OCTAVE_WARRANTY_STATEMENT): Define using X_OCTAVE_WARRANTY_STATEMENT.\n\t(OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY): Define using\n\tX_OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY.\n\t(X_OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY): Rename\n\tfrom OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY.\n\tAccept arg and pass to X_OCTAVE_WARRANTY_STATEMENT.\n\t(OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY): Pass empty\n\targ to X_OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_WARRANTY_AND_BUGS.\n\t(OCTAVE_STARTUP_MESSAGE): Put info about news last.\n\n2007-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (dist, conf-dist): Use ln, not $(LN_S).\n\n2007-03-26  Juhani Saastamoinen  <juhani@cs.joensuu.fi>\n\n\t* file-io.cc (do_stream_open) [! HAVE_ZLIB]:\n\tCall fopen with mode, not tmode.\n\n2007-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-str-str.cc (DEFCHARNDBINOP): New macro.  Use it to\n\tdefine functions for eq and ne ops.  Also define lt, le, ge, and\n\tgt ops.\n\n2007-03-23  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/rand.cc: Make more statistical tests optional.\n\n2007-03-23  John W. Eaton  <jwe@octave.org>\n\n\t* bitfcns.cc (Fbitshift): Error if third argument is not a scalar.\n\n2007-03-23  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/rand.cc: Make statistical tests optional and\n\tadd tests for fixed sequences.\n\n2007-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc (base_graphics_object::mark_modified):\n\tNew virtual function.\n\t(base_properties::__modified__): New data member.\n\t(base_properties::base_properties): Initialize it.\n\t(graphics_object::mark_modified, base_properties::mark_modified,\n\troot_figure::mark_modified, figure::mark_modified,\n\taxes::mark_modified, line::mark_modified, text::mark_modified,\n\timage::mark_modified, surface::mark_modified,\n\troot_figure::root_figure_properties::mark_modified,\n\tfigure::figure_properties::mark_modified,\n\taxes::axes_properties::mark_modified,\n\tline::line_properties::mark_modified,\n\ttext::text_properties::mark_modified,\n\timage::image_properties::mark_modified,\n\tsurface::surface_properties::mark_modified): New functions.\n\t(figure::figure_properties::set, figure::figure_properties::get,\n\taxes::axes_properties::set, axes::axes_properties::get,\n\tline::line_properties::set, line::line_properties::get,\n\ttext::text_properties::set, text::text_properties::get,\n\timage::image_properties::set, image::image_properties::get,\n\tsurface::surface_properties::set, surface::surface_properties::get):\n\tHandle __modified__ property.\n\n\t* parse.y (Fautoload): Use warning_with_id.\n\n2007-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__qp__.cc (ABS): Delete.  Use std::abs instead.\n\t(null): Set elements of retval with magnitudes less than eps to 0.\n\n\t* error.cc (Fwarning): Allow setting options with struct.\n\tIf setting options, return previous state.\n\n\t* graphics.cc (axes::axes_properties::set_defaults): Reverse sense\n\tof mode test for setting outerposition property.\n\t(figure::figure_properties::set): If setting visible property,\n\tmake this figure the current figure.\n\t(gh_manager::figure_handle_list, gh_manager::do_figure_handle_list):\n\tNew functions.\n\t(F__go_figure_handles__): New function.\n\n\t* sysdep.cc (Fpause): Also call drawnow if nargin == 0.\n\t(Fkbhit, Fsleep, Fusleep): Also call drawnow here.\n\n2007-03-20  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Correct for shape of return\n\tmatrix for the case of UniformOutput being true.\n\n2007-03-20  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc (Fpause): Call drawnow.\n\n2007-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (F__lock_global__): Delete.\n\n2007-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* graphics.cc: New file.\n\t* Makefile.in (DIST_SRC): Add it to the list.\n\n2007-03-13  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (do_stream_open): Use binary mode if 't' is not\n\tspecified in mode, but don't add 'b' if it is already present.\n\n2007-03-09  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (do_cat):  Also treat case of all empty matrices.\n\n2007-03-08  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_octave_value::set_dimensions,\n\tmxArray_octave_value::set_m, mxArray_octave_value::set_n,\n\tmxArray_octave_value::set_class_name,\n\tmxArray_octave_value::set_ir, mxArray_octave_value::set_jc,\n\tmxArray_octave_value::remove_field,\n\tmxArray_octave_value::set_field_by_number):\n\tDon't panic; request mutation instead.\n\t(class mxArray_octave_value):\n\n\t* mxarray.h (mxArray::set_m, mxArray::set_n,\n\tmxArray::set_dimensions): Wrap method call call with\n\tDO_VOID_MUTABLE_METHOD.\n\n2007-03-08  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (do_cat): Ignore leading empty matrices.\n\n2007-03-07  Bob Weigel  <rweigel@gmu.edu>\n\n\t* urlwrite.cc (urlget): Allow URL redirects.\n\n2007-03-05  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/md5sum.cc (Fmd5sum): Treat both files and strings.\n\n2007-03-05  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Check GLPK_PRE_4_14, not\n\tGLPK_PRE_4_15.\n\n2007-03-02  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (Fautoload): Undo previous change.\n\tWarn if FILE is not an absolute file name.\n\n\t* utils.cc (make_absolute): Make copy of arg before\n\n2007-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-mat.h\t(octave_base_matrix::octave_base_matrix (const MT&),\n\t(octave_base_matrix::octave_base_matrix (const MT&, const MatrixType&)):\n\tUse common definition with default argument value.\n\t* ov-base-scalar.h (octave_base_scalar<T>::typ): New data member.\n\tInitialize in constructors.\n\t(octave_base_scalar<T>::matrix_type): New funtions.\n\n2007-03-01  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/md5sum.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add md5sum.cc\n\n2007-03-01  Olli Saarela  <Olli.Saarela@kcl.fi>\n\n\t* input.cc (FPS1): Fix @seealso.\n\n2007-03-01  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): Special case scalar\n\ttypes and always return \"Full\" matrix type.\n\n2007-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (interactive_input): Also call flush_octave_stdout\n\tafter calling drawnow.\n\n2007-02-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (uninstall): Also remove octave-$(version)$(EXEEXT),\n\toct-gperf.h, and all .oct files.  Remove PKG_ADD.\n\tFrom Thomas Treichl <Thomas.Treichl@gmx.net>.\n\n\t* load-path.h, (load_path::initialize, load_path::do_initialize):\n\tNew arg, set_initial_path.\n\t* load-path.cc (load_path::do_initialize): Don't add system\n\tdirectories to apth if set_initial_path is false.\n\t* octave.cc (set_initial_path): New static variable.\n\t(NO_INITIAL_PATH_OPTION): New define.\n\t(usage_string): Include --no-initial-path in message.\n\t(long_opts): Include no-initial-path/NO_INITIAL_PATH_OPTION here.\n\t(octave_main): Handle NO_INITIAL_PATH_OPTION.\n\tPass set_initial_path to load_path::initialize.\n\n\t* parse.y (Fautoload): Warn about duplicate entries.  Only insert\n\tthe first found.\n\n2007-02-27  David Bateman  <dbateman@free.fr>\n\n\t* error.cc (Vlast_error_file, Vlast_erro_name, Vlast_error_row,\n\tVlast_error_column): New static variables.\n\t(verror): Use them to store the location of last error.\n\t(rethrow_error, Frethrow, Flasterror): New functions.\n\n\t* DLD-FUNCTIONS/regexp.cc (octcellregexp): Wrapper to octregexp\n\tfunction for cases when string or pattern are cell arrays\n\t(Fregexp, Fregexpi): Use them.\n\t(octregexprep): New function with functionality of old Fregexprep.\n\t(Fregexprep): Treat cell arguments.\n\n2007-02-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in: Use $(LN_S) instead of ln or ln -s.\n\n\t* DLD-FUNCTIONS/getrusage.cc: Undef min after including windows.h.\n\n2007-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/interpn.cc: Include dNDArray.h, not dMatrix.cc.\n\n\t* error.h: Include cstdarg.\n\tFrom Juhani Saastamoinen <juhani@cs.joensuu.fi>.\n\n2007-02-23  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (lookup_function): Don't dereference NULL\n\tcurr_parent_fucntion pointer.\n\t* ov-fcn-handle.cc (make_fcn_handle): Call lookup_function with\n\tparent set to empty string if call_stack is empty.\n\n\t* DLD-FUNCTIONS/dispatch.cc (Fbuiltin): Also adjust argument list\n\tin calls to functions that are not overloaded.  Call\n\tlookup_by_name to find function instead of searching fbi_symtab\n\tdirectly.\n\n\t* help.cc (do_which): Return empty string if file not found.\n\n2007-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_cell::mxArray_cell (const mxArray_cell&),\n\tmxArray_struct::mxArray_struct (const mxArray_struct&)):\n\tAvoid calling clone on 0 elements.\n\n\t* variables.cc (symbol_out_of_date): If checking nested function,\n\tlook for file using parent function name.  Delete unused\n\tvariable NAMES.\n\n\t* oct-stream.cc (octave_stream::do_gets): If no limit or not\n\tat limit, read ahead one character at end of line for compatibility.\n\t(octave_stream::gets, octave_stream::getl): Set max_len to -1 if\n\ttc_max_len is not defined.\n\t* file-io.cc (Ffgets, Ffgetl): If no limit specified, pass\n\tundefined octave_value object as max_len in call to\n\toctave_stream::gets.\n\n2007-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mexErrMsgIdAndTxt, mexWarnMsgIdAndTxt): Handle second\n\targ as format and accept variable number of arguments.\n\t* mexproto.h: Fix decls.\n\n\t* error.h, error.cc (vmessage, vusage, vwarning, verror,\n\tvparse_error, vmessage_with_id, vusage_with_id, vwarning_with_id,\n\tverror_with_id, vparse_error_with_id): Provide va_list versions of\n\tvariadic error, warning, and message functions.\n\t(message, usage, warning, error, parse_error, message_with_id,\n\tusage_with_id, warning_with_id, error_with_id,\n\tparse_error_with_id): Call va_list versions.\n\n\t* DLD-FUNCTIONS/urlwrite.cc (Furlwrite, Furlread): Return error\n\tcode and message instead of throwing error if functionality is\n\tmissing.\n\n\t* oct-obj.h (octave_value_list::splice): Set default for\n\treplacement list argument.\n\n2007-02-20  Rafael Laboissiere  <rafael@laboissiere.net>\n\n\t* DLD-FUNCTIONS/__glpk__.cc: Adapt code for changes in the GLPK\n\tAPI for version 4.15 or later.\n\n2007-02-20  John W. Eaton  <jwe@octave.org>\n\n\t* mxarray.h (mxArray::get_scalar): New function.\n\t* mex.cc (mxArray_base::get_scalar): New pure virtual function.\n\t(mxArray_octave_value::get_scalar, mxArray_matlab::get_scalar,\n\tmxArray_number::get_scalar): New functions.\n\t(mxGetScalar): Call get_scalar here.\n\n\t* mex.cc (mxArray_octave_value::get_dimensions): Cache ndims here.\n\t(mxArray_octave_value::get_number_of_dimensions):\n\tCall get_dimensions here to cache both ndims and dims.\n\n2007-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (symbol_out_of_date): Don't exit early if looking\n\tat nested function.\n\n2007-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_oct): Clear\n\tfunction if original was loaded from relative path and the name\n\tcan no longer be found in path.  Mark files found from relative\n\tpath as relative.\n\t(clear): Only warn if there is more than one function to clear.\n\n\t* variables.cc (symbol_out_of_date): Don't ignore return value in\n\tcall to octave_env::make_absolute.\n\t(symbol_out_of_date): Clear symbol if original was loaded from\n\trelative path and name can no longer be found in path.\n\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_oct):\n\tAlso check whether new file is same as the old file.\n\n\t* utils.cc (same_file): Move here from variables.cc.\n\t* utils.h: (same_file): Provide decl.\n\n\t* parse.y (frob_function): Stash parent function name if parsing\n\tnested function.\n\n\t* ov-fcn-handle.cc (make_fcn_handle): Pass current function name\n\tas parent in call to lookup_function.\n\n\t* ov-fcn.h (octave_function::parent_fcn_name): New virtual function.\n\n\t* ov-usr-fcn.h (octave_user_function::parent_name): New data member.\n\t(octave_user_function::stash_parent_function_name,\n\toctave_user_function::parent_function_name): New methods.\n\t* ov-usr-fcn.cc (octave_user_function::octave_user_function):\n\tInitialize parent_name.\n\n\t* variables.h, variables.cc (lookup_function): New arg, parent.\n\tIf not empty, try this first for lookup.\n\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_mex): If doing\n\tpath lookup, check relative status. Pass relative to oct_file_in_path.\n\t(octave_dynamic_loader::do_load_mex): Likewise, for mex_file_in_path\n\n\t* defun-int.h, defun.cc (install_mex_function): New arg, relative.\n\t(install_dld_function): Likewise.\n\t(octave_dld_fcn_installer): Likewise.\n\t(DEFINE_FUNX_INSTALLER_FUN3): Pass relative to install_dld_function.\n\n\t* dynamic-ld.h (octave_dynamic_loader::load_oct,\n\toctave_dynamic_loader::load_mex,\n\toctave_dynamic_loader::do_load_oct\n\toctave_dynamic_loader::do_load_mex): New arg, relative.\n\n\t* dirfns.h (Vcurrent_directory): Delete unused variable.\n\n\t* variables.cc (symbol_out_of_date): Also compare function time\n\tstamp to Vlast_chdir_time if function is from relative lookup.\n\n\t* dirfns.cc (Vlast_chdir_time): New variable.\n\t(octave_change_to_directory): Update it if chdir succeeds.\n\t* dirfns.h (Vlast_chdir_time): Provide decl.\n\n\t* ov-fcn.h (octave_function::relative): New data member.\n\t(octave_function::mark_relative, octave_function::is_relative):\n\tNew functions.\n\n\t* parse.y (fcn_file_from_relative_lookup): New static variable.\n\t(load_fcn_from_file): Note whether function file was found from\n\trelative path element.\n\t(frob_function): Maybe mark function as relative.\n\n\t* parse.y (lookup_autoload): Don't call octave_env::make_absolute\n\ton return value.\n\t* variables.cc (symbol_out_of_date): Make name absolute after call\n\tto lookup_autoload.\n\n\t* input.cc (interactive_input): New arg, DEBUG.  Don't call\n\tdrawnow if debugging.\n\t(get_user_input): Pass DEBUG to interactive_input.\n\n2007-02-16  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* syscalls.cc (Fpopen2): New function.\n\t(pipe): Modify to return input and output file descriptor\n\tseperately rather than in a list.\n\n2007-02-16  Muthiah Annamalai  <muthuspost@gmail.com>\n\n\t* debug.cc (Fdbtype): Improve compatibility.\n\n2007-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (wait_for_input): New function.\n\t(run_command_and_return_output): Use it instead of napping.\n\n\t* oct-procbuf.h (octave_procbuf::pid): Now const.\n\t* procstream.h (procstreambase::pid): Now const.\n\t(procstreambase::file_number): New function.\n\n2007-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* mxarray.h (mxChar): Use char instead of unsigned short.\n\n\t* toplev.cc (Foctave_config_info): Remove\n\tOCTAVE_CONF_MKOCTFILE_INCFLAGS and OCTAVE_CONF_MKOCTFILE_LFLAGS\n\tfrom the list.\n\t* oct-conf.h.in (OCTAVE_CONF_MKOCTFILE_INCFLAGS,\n\tOCTAVE_CONF_MKOCTFILE_LFLAGS): Don't define.\n\t(OCTAVE_CONF_INCLUDEDIR, OCTAVE_CONF_OCTINCLUDEDIR,\n\tOCTAVE_CONF_OCTLIBDIR, OCTAVE_CONF_PREFIX): New definitions.\n\n2007-02-14  Alexander Barth  <abarth@marine.usf.edu>\n\n\t* DLD-FUNCTIONS/interpn.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n2007-02-14  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (interactive_input): Check error_state after call to feval.\n\n2007-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_stream::rewind): Call seek (0, SEEK_SET)\n\tinstead of rep->rewind.\n\t(octave_base_stream::rewind): Delete Function.\n\t* oct-stream.h (octave_base_stream::rewind): Delete decl.\n\n2007-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (PAD): Adjust to change in write_mat5_tag.\n\t(TAGLENGTH): Delete unused macro.\n\n\t* ov-struct.cc (octave_struct::load_ascii,\n\toctave_struct::load_binary, octave_struct::load_hdf5):\n\tDelete obsolete attempt at backward compatibility.\n\n\t* ls-mat5.cc (read_mat5_binary_element): Don't attempt to read\n\tfieldnames if there are no fields.\n\t(write_mat5_tag): Don't use small data element format if bytes == 0.\n\n\t* ls-mat5.cc (read_mat5_binary_element): Always create a structure\n\tthat is at least 1x1.\n\t* ov-struct.cc (octave_struct::load_ascii,\n\toctave_struct::load_binary, octave_struct::load_hdf5): Likewise.\n\n2007-02-08  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* DLD-FUNCTIONS/__glpk__.cc: Include glplib.h if glpk.h does not.\n\tProvide definitions for lib_set_fault_hook and lib_set_print_hook\n\tif they are not defined.\n\n2007-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* defaults.cc (subst_octave_home):\n\tOnly substitute at beginning of string.\n\n\t* ls-hdf5.cc (save_hdf5_empty): Use OCTAVE_LOCAL_BUFFER.\n\t* ov-bool-mat.cc (octave_bool_matrix::save_hdf5,\n\toctave_bool_matrix::load_hdf5): Likewise.\n\t* ov-bool-sparse.cc (octave_sparse_bool_matrix::save_hdf5,\n\toctave_sparse_bool_matrix::load_hdf5): Likewise.\n\n2007-02-07  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* ov-cell.cc (octave_cell::save_hdf5): Correct test for H5Dwrite\n\treturn value.\n\n2007-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* zfstream.cc (gzfilebuf::open_mode): Always append \"b\" to c_mode.\n\n\t* toplev.cc (Foctave_config_info): Use struct for conf_info.\n\tCall subst_octave_home on selected values when initializing map.\n\t* defaults.cc (subst_octave_home): Now extern.\n\t* defaults.h.in: Provide decl.\n\n2007-02-05  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_number::as_octave_value): Fake mxSINGLE_CLASS\n\tby returning double-precision values.\n\t(mxArray_sparse::as_octave_value): Clarify error message.\n\n\t* ov-complex.h (octave_complex): Use std instead of OCTAVE_STD\n\tsince the latter was unconditionally defined to be std anyway.\n\n2007-02-05  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* ov-complex.h: Tag octave_complex class with OCTINTERP_API.\n\n2007-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* Merge of changes from graphics-branch:\n\n\t2007-01-26  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__contourc__.cc: New function.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n\t2007-01-25  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (Vdrawnow_requested): New static variable.\n\t(F__request_drawnow__): New function.\n\t(interactive_input): New function.  Update Vlast_prompt_time here.\n\t(octave_gets, get_user_input, octave_yes_or_no):\n\tCall interactive_input instead of gnu_readline.\n\n\t* symtab.h (symbol_record::eternal): New data member.\n\t(symbol_record::symbol_record): Initialize it.\n\t(symbol_record::make_eternal, symbol_record::is_eternal):\n\tDon't forward to symbol_def functions.\n\t(symbol_record::symbol_def::make_eternal,\n\tsymbol_record::symbol_def::is_eternal): Delete.\n\t(symbol_record::symbol_def::eternal): Delete data member.\n\t(symbol_record::symbol_def::symbol_def): Delete initialization.\n\n\t* pt-id.cc (tree_identifier::link_to_global): Include variable\n\tname in warning message.\n\n\t* variables.cc (F__lock_global__): New function.\n\n\t2007-01-11  John W. Eaton  <jwe@octave.org>\n\n\t* ls-oct-ascii.cc (save_ascii_data_for_plotting, save_three_d):\n\tSet precision to 6 instead of 4.\n\n2007-01-29  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/find.cc (find_nonzero_elem_idx): Don't panic if\n\tnargout is greater than 3.\n\n2007-01-24  John W. Eaton  <jwe@octave.org>\n\n\t* pt-assgn.cc (former_built_in_variables): New static data.\n\t(maybe_warn_former_built_in_variable): New static function.\n\t(tree_simple_assignment::tree_simple_assignment,\n\ttree_multi_assignment::tree_multi_assignment):\n\tMove definition here from pt-assign.h\n\tMaybe warn about assignment to obsolete built-in variables.\n\n\t* version.h (OCTAVE_STARTUP_MESSAGE): Mention \"news\" function.\n\n\t* pt-stmt.cc (tree_statement::eval): Use dynamic_cast, not\n\tstatic_cast.\n\n\t* help.cc (help_from_file): Show .oct or .mex file name if one\n\texists in the same directory as the .m file.\n\n2007-01-23  Luis F. Ortiz  <lortiz@interactivesupercomputing.com>\n\n\t* strfns.cc (Fstrncmp): New function.\n\n2007-01-17  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (help_from_file, help_from_symbol_table, help_from_list):\n\tRewrite using raw_ versions.\n\n2007-01-17  David Bateman  <dbateman@free.fr>\n\n\t* help.cc (raw_help, raw_help_from_file,\n\traw_help_from_symbol_table, raw_help_from_list): New functions.\n\t* help.h (raw_help): Provide decl.\n\n2007-01-16  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__pchip_deriv__.cc: Fix dpchim decl for --enable-64.\n\t(F__pchip_deriv__): Fix call to dpchim for --enable-64.\n\n\t* DLD-FUNCTIONS/fftw.cc: Delete decl for fftw_planner.\n\n2007-01-11  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* load-path.h (class load_path): Tag with OCTINTERP_API.\n\n\t* ls-oct-binary.cc (read_binary_data): Use unsigned char, not\n\tchar, for reading flags and data types.\n\n2007-01-10  Luis F. Ortiz  <lortiz@interactivesupercomputing.com>\n\n\t* parse.y (load_fcn_from_file): Delete unused variable NAMES.\n\tIf NM is absolute, strip directory and extension parts.\n\n2007-01-10  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* DLD-FUNCTIONS/getrusage.cc: Use #ifdef __WIN32__, not __MINGW32__.\n\n2007-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (load_fcn_from_file): Only compare last two characters\n\twhen looking for \".m\".\n\n2007-01-06  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_CONFIG_STATEMENT): New macro\n\t(OCTAVE_NAME_AND_VERSION): Remove config info.\n\t(OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY):\n\tUse OCTAVE_CONFIG_STATEMENT here.\n\n2007-01-05  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (DLD_XSRC): Add fftw.cc and remove fftw_wisdom.cc\n\t* DLD-FUNCTIONS/fftw.cc: New file.\n\t* DLD-FUNCTIONS/fftw_wisdom.cc: Delete.\n\t* defaults.cc (Vfftw_wisdom_program): Delete variable.\n\t(set_default_fftw_wisdom_prog): Delete function that sets it.\n\t(install_defaults): Delete set_default_fftw_prog from defaults.\n\t(Ffftw_wisdom_program): Delete.\n\n2007-01-04  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::load_ascii,\n\toctave_fcn_handle::load_binary):\n\tThrow error if handle can't be created.\n\n2007-01-04  Luis F. Ortiz  <lortiz@interactivesupercomputing.com>\n\n\t* mex.cc (mxArray_number::mxArray_number (int, const char **)):\n\tCorrectly index LHS in assignment.\n\n2007-01-03  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (Fisinteger): New function.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::is_integer_type,\n\tOCTAVE_VALUE_INT_SCALAR_T::is_integer_type): New function.\n\t* ov.h (octave_value::is_integer_type): New function.\n\t* ov-base.h (octave_base_value::is_integer_type): New virtual function.\n\n2007-01-03  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* toplev.cc (Fsystem): Handle async calls on Windows systems.\n\n2007-01-03  David Bateman  <dbateman@free.fr>\n\n\t* (OPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc,\n\tOPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc,\n\tOPERATORS/op-m-scm.cc, OPERATORS/op-m-sm.cc,\n\tOPERATORS/op-scm-cm.cc, OPERATORS/op-scm-cs.cc,\n\tOPERATORS/op-scm-m.cc, OPERATORS/op-scm-s.cc,\n\tOPERATORS/op-scm-scm.cc, OPERATORS/op-scm-sm.cc,\n\tOPERATORS/op-sm-cm.cc, OPERATORS/op-sm-cs.cc,\n\tOPERATORS/op-sm-m.cc, OPERATORS/op-sm-s.cc,\n\tOPERATORS/op-sm-scm.cc, OPERATORS/op-sm-sm.cc,\n\tOPERATORS/op-s-scm.cc, OPERATORS/op-s-sm.cc):\n\tModify div and ldiv functions so that scalars stored as sparse\n\tmatrices are special cased.\n\n\t* ov-re-sparse.cc (double_value, complex_value): Scalar can be\n\tstored as a sparse matrix and so don't warn on implicit conversion\n\tto a scalar.\n\t* ov-cx-sparse.cc (double_value, complex_value): ditto.\n\t* ov-bool-sparse.cc (double_value, complex_value): ditto.\n\n2007-01-03  John W. Eaton  <jwe@octave.org>\n\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load_mex): Also check\n\tfor _mexFunction.\n\n2006-12-30  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-inline.cc: For compatibility, class id is\n\t\"function_handle\", not \"inline function\".\n\n2006-12-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (%.df : %.cc): Insert a \"do not edit\" notice in the\n\t.df files.\n\n\t* mex.cc (mxArray_matlab::get_class_name,\n\tmxArray_octave_value::get_class_id): Use \"function_handle\", not\n\t\"function handle\".\n\n2006-12-14  John W. Eaton  <jwe@octave.org>\n\n\t* pt-decl.cc (tree_decl_elt::eval): New function.\n\t* pt-decl.h (tree_decl_elt::eval): Provide decl.\n\t(tree_decl_elt::is_defined, tree_decl_elt::lvalue_ok,\n\ttree_decl_elt::mark_as_formal_parameter, tree_decl_elt::rvalue,\n\ttree_decl_elt::lvalue): New functions.\n\n\t* pt-misc.h (class tree_parameter_list): Derive from\n\toctave_base_list<tree_decl_elt *> instead of\n\toctave_base_list<tree_identifier *>.\n\t(tree_parameter_list::tree_parameter_list (tree_identifier *)): Delete.\n\t(tree_parameter_list::tree_parameter_list (tree_decl_elt *)):\n\tNew function.\n\t* pt-misc.cc (tree_parameter_list::mark_as_formal_parameters,\n\ttree_parameter_list::initialize_undefined_elements,\n\ttree_parameter_list::undefine, tree_parameter_list::dup,\n\ttree_parameter_list::convert_to_const_vector,\n\ttree_parameter_list::is_defined): Handle argument list elements\n\tas tree_decl_list objects instead of tree_identifier objects.\n\t(tree_parameter_list::define_from_arg_vector): Likewise.\n\tAlways process entire list, setting default values if possible.\n\tAccept \":\" to mean \"use default argument\".\n\n\t* parse.y (param_list2): Use decl2 to recognize\n\t\"identifier '=' expression\" in addition to \"identifier\".\n\n\t* parse.y (return_list1, make_anon_fcn_handle, finish_function):\n\tAdapt to new definition of tree_parameter_list.\n\t* pt-bp.cc (tree_breakpoint::visit_parameter_list): Likewise.\n\t* pt-check.cc (tree_checker::visit_parameter_list): Likewise.\n\t* pt-pr-code.cc (tree_print_code::visit_parameter_list): Likewise.\n\n2006-12-08  John W. Eaton  <jwe@octave.org>\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::array_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::complex_array_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::bool_array_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::char_array_value):\n\tUse fortran_vec to avoid expensive indexing operator.\n\n2006-12-08  David Bateman  <dbateman@free.fr>\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_SCALAR_T::matrix_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::complex_matrix_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::matrix_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::comlex_matrix_value): New functions.\n\t(OCTAVE_VALUE_INT_MATRIX_T::array_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::comlex_array_value):\n\tUse octave_idx_type instead of int for indexing.\n\n2006-12-04  David Bateman  <dbateman@free.fr>\n\n\t* xpow.cc (xpow (const Matrix&, double)): Add matrix type probing\n\tto matrix inverse.\n\t(xpow (const ComplexMatrix&, double)): ditto.\n\t* DLD-FUNCTIONS/inv.cc (Finv): Add matrix type probing.\n\n2006-12-06  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc: Include \"Cell.h\" here.\n\t* input.h: Include \"oct-obj.h\", not \"ov-list.h\".\n\n2006-12-06  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* mappers.cc (install_mapper_functions): Undefine isascii before\n\tthe DEFUN_MAPPER for it.\n\n\t* input.cc (get_user_input): Prevent out of bounds array access\n\twhen checking for EOL.\n\n2006-12-05  John W. Eaton  <jwe@octave.org>\n\n\t* ls-oct-ascii.cc (extract_keyword): If no match and looking for\n\tmore, skip to end of line before trying another match.\n\n\t* pt-mat.cc (tm_row_const::empty): New function.\n\t(tm_const::init): Don't append anything if tmp tm_row_const object\n\tis empty.\n\t(tree_matrix::rvalue): Default return value is Matrix().\n\tDon't do anything if tmp tm_const object is empty.\n\n\t* dirfns.cc (Fmkdir): Fix thinko in previous change.\n\n2006-12-05  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* DLD-FUNCTIONS/rand.cc: Test for Poisson generator with lambda > 1e8.\n\n2006-12-04  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (Fdata): If ndims is greater than nargout and\n\tnargout is greater than 1, then collect size of trailing\n\tdimensions into retval(end).\n\n\t* load-path.cc (load_path::do_find_fcn): Return empty string if\n\ttests fail.\n\n\t* ov-base-mat.cc (void octave_base_matrix<MT>::assign (const\n\toctave_value_list&, const MT&)): Invalidate matrix type on\n\tassignment.\n\n2006-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fftw_wisdom.cc (Ffftw_wisdom):\n\tAccept \"r\" or \"w\" for second argument.\n\n2006-11-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/fftw_wisdom.cc (Ffftw_wisdom): Look in load-path\n\tif reading wisdom file, but not if writing.\n\n2006-11-28  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_struct::get_field_by_number):\n\tReturn 0 if key_num is out of range.\n\t(mxArray_struct::set_field_by_number):\n\tDo nothing if key_num is out of range.\n\t(mxArray_cell::get_cell, mxArray_cell::set_cell):\n\tAvoid out-of-bounds indexing\n\n2006-11-28  Luis F. Ortiz  <lortiz@interactivesupercomputing.com>\n\n\t* mex.cc (mxArray_matlab::get_n, mxArray_octave_value::get_n):\n\tReturn product of last N-1 dims.\n\n2006-11-28  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (eat_whitespace): Also handle CRLF as EOL.\n\n\t* dirfns.cc (Fmkdir): Handle \"mkdir (parent, dir)\".\n\n2006-11-21  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (load_path::do_find_file,\n\tload_path::do_find_first_of, load_path::do_find_all_first_of):\n\tCall rooted_pathname instead of absolute_pathname.\n\t* utils.cc (fcn_file_in_path, oct_file_in_path, mex_file_in_path):\n\tLikewise.\n\n2006-11-16  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* oct-hist.cc (default_history_file): Instead of appending\n\t\"/.octave_hist\", append directory separator (but only if\n\tnecessary), then \".octave_hist\".\n\n2006-11-16  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (Fresize): Fix doc string.\n\n2006-11-15  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l (write_data, write_inline_data):\n\tNew functions.\n\t(save_in_tmp_file): Use write_data.\n\t(gnuplot::send_inline_data, gnuplot_do_send_inline_data):\n\tNew functions.\n\t(F__gnuplot_send_inline_data__, F__gnuplot_save_data__):\n\tNew functions.\n\n\t* ls-oct-ascii.cc (save_ascii_data_for_plotting):\n\tCall save_ascii_data with precision = 4.\n\t(save_three_d): Temporarily set precision to 4 for output stream.\n\n2006-11-15  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Cell.h (Cell): Tag class with OCTINTERP_API.\n\n2006-11-13  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (maximum_braindamage): Disable\n\tOctave:fopen-file-in-path and Octave:load-file-in-path warnings.\n\n\t* load-save.cc (find_file_to_load): New function.\n\t(Fload): Call find_file_to_load to search load path for file.\n\n\t* file-io.cc (Ffopen): Search load path for file.\n\n\t* load-path.cc (path::do_find_first_of, path::do_find_file):\n\tBreak out of all loops once file is found, not just innermost one.\n\n\t* data.cc (Fsize_equal): New function.\n\n2006-11-13  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* ov.cc (check_subsref_elements, Fsubsref, Fsubsasgn):\n\tNew functions.\n\n\t* ov-re-mat.h, ov-scalar.h, pr-output.h:\n\tSprinkle with OCTINTERP_API as needed.\n\n2006-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (parse.cc): Avoid creating empty files.\n\t(%.df : %cc, builtins.cc, mkbuiltins, PKG_ADD, DOCSTRINGS,\n\tdoc-files, gendoc.cc, ops.cc, $(OPT_HANDLERS), oct-errno.cc,\n\toct-gperf.h): Use $(simple-move-if-change-rule) here.\n\t(lex.cc, __gnuplot_raw__.cc):\n\tUse $(destdir-move-if-change-rule) here.\n\t(ifndef omit_deps): Don't include stamp-prereq here.\n\t($(DEF_FILES), $(MAKEDEPS)): Also depend on stamp-prereq.\n\n2006-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* ov-str-mat.cc (octave_char_matrix_str::load_ascii,\n\toctave_char_matrix_str::load_binary):\n\tUse chMatrix as buffer instead of C string.\n\n2006-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr-fcn.h (octave_user_function::inline_function):\n\t New data member.\n\t(octave_user_function::mark_as_inline_function): Set it.\n\t(octave_user_function::is_inline_function): Check it.\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tAlso skip setting curr_parent_fucntion if evaluating an inline\n\tfunction.\n\t(octave_user_function::octave_user_function):\n\t Initialize inline_function.\n\t* pt-fcn-handle.cc (tree_anon_fcn_handle::rvalue):\n\tMark user function as inline here.\n\n2006-11-09  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* load-path.cc (load_path::move): Don't use reference to file_info\n\tobject that will be erased.\n\n2006-11-07  John W. Eaton  <jwe@octave.org>\n\n\t* utils.cc (file_in_path): Don't unconditionally return \"\".\n\n\t* pager.cc (default_pager): Don't append options here.\n\t(pager_command): New function.\n\t(do_sync): Use it.\n\t(VPAGER_FLAGS): New variable.\n\t(FPAGER_FLAGS): New function.\n\n2006-11-06  John W. Eaton  <jwe@octave.org>\n\n\t* oct-hist.cc (default_history_file): If env_file is not empty,\n\tjust accept it rather than checking to see if it exists.\n\n2006-11-03  Bill Denney  <denney@seas.upenn.edu>\n\n\t* help.cc (keywords): Document try and unwind_protect.\n\n2006-11-03  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DLL_CXXDEFS): Rename from XTRA_CXXDEFS.\n\t(DLL_CDEFS): Rename from XTRA_CDEFS.\n\tSubstitute OCTINTERP_DLL_DEFS, not XTRA_OCTINTERP_DEFS.\n\n2006-11-02  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* sysdep.cc (MSVC_init): Also cal w32_sigint_init and\n\tw32_set_quiet_shutdown.\n\n2006-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h (octave_value::idx_type_value): New function.\n\t* data.cc (fill_matrix, Flinspace, Freshape): Use idx_type_value\n\tinstead of int_value to extract size args.\n\n2006-10-31  John W. Eaton  <jwe@octave.org>\n\n\t* ov-range.h (octave_range::empty_clone): Return octave_matrix\n\tobject instead of octave_range.\n\n2006-10-29  Juhani Saastamoinen  <juhani@cs.joensuu.fi>\n\n\t* ls-mat5.cc (read_mat5_tag): Declare bytes as int32_t, not just int.\n\n2006-10-28  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (Fatexit): Push function names on the stack even if we\n\tdon't have atexit or on_exit.\n\n2006-10-28  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* mappers.cc (install_mapper_functions): Undefine toascii before\n\tthe DEFUN_MAPPER for it.\n\n2006-10-27  John W. Eaton  <jwe@octave.org>\n\n\t* mexproto.h: Include oct-dlldefs.h.\n\n\t* pr-output.cc (SPECIALIZE_UABS): New macro.\n\tUse it to generate specializations of abs for unsigned int types.\n\tInstantiate abs for signed int types.\n\n\t* load-path.cc (load_path::do_initialize):\n\tUse dir_path::path_sep_str instead of \":\".\n\tDon't append \":::\" to xpath when calling do_set.\n\n\t* dirfns.cc (Fls, cleanup_iprocstream): Delete.\n\n\t* sysdep.cc (Ftilde_expand): If arg is cellstr, return cellstr.\n\n\t* ov.h (octave_value::is_cellstr): New function.\n\t* ov-base.h (octave_base_value::is_cellstr): New function.\n\t* ov-cell.h (octave_cell::is_cellstr): New function.\n\t* ov-cell.cc (Fiscellstr): Implement with is_cellstr.\n\t* Cell.cc (Cell::Cell (const dim_vector&, const string_vector&, bool)):\n\tNew constructor.\n\t(Cell::is_cellstr): New function.\n\t* Cell.h: Provide decls.\n\n\t* defaults.cc (subst_octave_home): If dir_sep_char is not '/',\n\treplace before returning.\n\tFrom Michael Goffioul <michael.goffioul@swing.be>.\n\n2006-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* cutils.c (octave_strcasecmp, octave-strncasecmp):\n\tMove to liboctave/lo-cutils.c.\n\t* utils.h: Delete decls.\n\t* strcasecmp.c: Move to liboctave/strcasecmp.c.\n\t* strncase.c: Move to liboctave/strncase.c.\n\t* Makefile.in (DIST_SRC): Delete them from the list.\n\n\t* bitfcns.cc (bitshift): If A < 0, return -bitshift (-A, N, MASK).\n\n2006-10-26  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* help.cc (display_help_text): Quote sed patterns with \".\n\n\t* file-io.cc: Include file-io.h.\n\n\t* TEMPLATE-INST/Array-os.cc, TEMPLATE-INST/Array-sym.cc,\n\tTEMPLATE-INST/Array-tc.cc, defun-int.h, error.h, file-io.h,\n\tgripes.h, ls-oct-ascii.h, mexproto.h, oct-map.h, oct-obj.h,\n\toct-stream.cc, oct-stream.h, octave.h, ov-base.h,\n\tov-bool-sparse.cc, ov-bool-sparse.h, ov-cx-sparse.cc,\n\tov-cx-sparse.h, ov-fcn.h, ov-re-sparse.cc, ov-re-sparse.h,\n\tov-str-mat.h, ov-typeinfo.cc, ov-typeinfo.h, ov.h, pager.h,\n\tparse.h, pr-output.cc, pr-output.h, procstream.h, sighandlers.h,\n\tsymtab.h, unwind-prot.h, utils.h, variables.h:\n\tSprinkle with OCTINTERP_API as needed.\n\n2006-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* ov-bool.h (octave_bool::sparse_matrix_value,\n\toctave_bool::sparse_complex_matrix_value\n\toctave_bool::sparse_bool_matrix_value): New functions.\n\n2006-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* sighandlers.cc: Check defined (RETSIGTYPE_IS_VOID) instead of\n\tRETSIGTYPE == void.\n\n\t* oct-procbuf.cc (BUFSIZ): Define if not already defined.\n\t(octave_procbuf::open): Pass BUFSIZ as size argument to setvbuf.\n\n2006-10-25  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in (XTRA_CDEFS, XTRA_CXXDEFS): Substitute here.\n\n\t* oct-procbuf.cc [_MSC_VER]: Define W32POPEN and W32PCLOSE the\n\tsame as for __MINGW32__.\n\t(octave_procbuf::open, octave_procbuf::close) [_MSC_VER]:\n\tUse the same code as for __MINGW32__ and __CYGWIN__.\n\n\t* oct-prcstrm.cc [_MSC_VER]: Define popen and pclose.\n\n2006-10-25  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc (w32_set_octave_home): Correctly initialize bin_dir.\n\tFill it with '\\0' instead of ' '.\n\n2006-10-24  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in: Filter out $(XTRA_CXXDEFS) from $(ALL_CXXFLAGS) for\n\t$(DLD_PICOBJ).\n\n2006-10-24  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.cc (MSC_init): New function.\n\t(sysdep_init): Call it.\n\t(w32_set_octave_home): New function, based on code from Michael\n\tGoffioul <michael.goffioul@swing.be>.\n\t(MINGW_init): Call w32_set_octave_home here too.\n\n2006-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_table::clear_mex_functions): New function.\n\t* symtab.h: Provide decl.\n\t* vriables.cc (clear_mex_functions): New function.\n\t* variables.h Provide decl.\n\t* toplev.cc: Call clear_mex_functions instead of delete_symbol_tables.\n\n\t* variables.cc (delete_symbol_tables): Delete.\n\t* variables.h: Delete decl.\n\n\t* mex.cc (mex::unmark_array): New function.\n\t(mex::persistent): Define with unmark_array.\n\t(maybe_unmark_array): New function.\n\t(mxArray_struct::set_field_by_number, mxArray_cell::set_cell):\n\tCall maybe_unmark_array on val to avoid freeing val twice on exit\n\tfrom mex function.\n\t(mxFree): Call xfree, not free.\n\n2006-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* ov-intx.h\n\t(OCTAVE_VALUE_INT_MATRIX_T::OCTAVE_TYPE_PREDICATE_FUNCTION,\n\t(OCTAVE_VALUE_INT_SCALAR_T::OCTAVE_TYPE_PREDICATE_FUNCTION):\n\tFunction is now const, so it properly overloads method in base\n\tclass.\n\n\t* mex.cc (mxArray_octave_value::is_uint32):\n\tCall val.is_uint32_type, not val.is_int32_type.\n\t(mxArray_octave_value::is_uint64):\n\tCall val.is_uint64_type, not val.is_int64_type.\n\t(mxArray_octave_value::is_uint8):\n\tCall val.is_uint8_type, not val.is_int8_type.\n\n2006-10-20  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* ov-mex-fcn.h (octave_mex_function::atexit): New function.\n\t(octave_mex_function::exit_fcn_ptr): New data member.\n\t* ov-mex-fcn.cc (octave_mex_function::exit_fcn_ptr): New data member.\n\t(octave_mex_function::octave_mex_function): Initialize it.\n\t(octave_mex_function::~octave_mex_function):\n\tIf we have an exit function, call it.\n\n2006-10-20  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (delete_symbol_tables): New function.\n\t* variables.h: Provide decl.\n\t* toplev.cc (do_octave_atexit): Call it.\n\n\t* mex.cc (mex::mex): New arg, a pointer to the current mex function.\n\t(mex::curr_mex_fcn): New data member.\n\t(mex::current_mex_function): New function.\n\t(mexAtExit): Set exit function pointer in current mex file object.\n\n2006-10-20  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* mex.cc (enum callstyle): Delete enum definition.\n\t(Fortran_mex, C_mex): Delete functions.\n\t(call_mex): First arg is now bool.\n\t* ov-mex-fcn.cc (call_mex): Fix decl to match new definition.\n\t(Fortran_mex, C_mex): Delete decls.\n\t(octave_mex_function::do_multi_index_op): Simplify call to call_mex.\n\n2006-10-20  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (handle_identifier): If a command name is found, skip\n\tstarting command mode if parsing an object index.\n\n2006-10-20  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTION/spqr.cc (dmperm_internal): New function with core\n\tof Fdmperm.\n\t(Fdmperm): Call dmperm_internal rather then calculating loally.\n\t(Fsprank): New function to calculate the strutural rank also using\n\tdmperm_internal.\n\n2006-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (octave_struct::as_mxArrary):\n\tUse OCTAVE_LOCAL_BUFFER to allocate tempoarary array of field names.\n\n\t* mxarray.h (mxArray::persistent): Delete var and all uses.\n\t(mxArray::mark_persistent, mxArray::unmark_persistent,\n\tmxArray::is_persistent): Delete functions.\n\t* mex.cc (mex::function_name): Use mxArray::strsave, not strsave.\n\t(mex::mark_array): New function.\n\t(mex::make_value): Use it.\n\t(mex::free_value): Return true if we found ptr in arraylist.\n\t(mex::persistent (mxArray *)): Remove ptr from arraylist instead\n\tof marking it as persistent.\n\t(mxArray::malloc): Call ::malloc instead of malloc.\n\t(mxArray::calloc): Call ::calloc instead of calloc.\n\t(maybe_mark_array): New function.\n\t(mxCreateCellArray, mxCreateCellMatrix, mxCreateCharArray,\n\tmxCreateCharMatrixFromStrings, mxCreateDoubleMatrix,\n\tmxCreateDoubleScalar, mxCreateLogicalArray, mxCreateLogicalMatrix,\n\tmxCreateLogicalScalar, mxCreateNumericArray,\n\tmxCreateNumericMatrix, mxCreateSparse,\n\tmxCreateSparseLogicalMatrix, mxCreateString, mxCreateStructArray,\n\tmxCreateStructMatrix, mxDuplicateArray): Use it.\n\t(mxDestroyArray): No need to check persistence now.\n\tAlso delete ptr if mex_context->free_value does not.\n\t(call_mex): No need to delete elements of argout now.\n\n2006-10-18  John W. Eaton  <jwe@octave.org>\n\n\t* dynamic-ld.cc (octave_shlib_list::remove,\n\toctave_shlib_list::do_remove, octave_mex_file_list::remove,\n\toctave_mex_file_list::do_remove): New arg, cl_hook.\n\t(octave_shlib_list::do_remove): Pass cl_hook to octave_shlib close\n\tfunction.\n\t(octave_dynamic_loader::do_load_oct): Don't call close on shl\n\tdirectly.  Pass do_clear_function to octave_shlib_list::remove.\n\n\t* mex.cc (mexUnlock): Don't warn if unlocking a function that is\n\tnot locked.\n\n\t* pt-fcn-handle.cc (tree_anon_fcn_handle::dup):\n\tCorrectly duplicate symbol table info.\n\n2006-10-17  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* oct-map.h: Include <algorithm>.\n\n2006-10-16  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_stream_list::do_remove): Handle \"all\" as a\n\tspecial case.\n\n2006-10-13  Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in: Adapt rules to use $(LIBPRE).\n\n2006-10-11  John W. Eaton  <jwe@octave.org>\n\n\t* mex.h (UINT64_T, uint64_T, INT64_T, int64_T, UINT32_T, uint32_T,\n\tINT32_T, int32_T, UINT16_T, uint16_T, INT16_T, int16_T, UINT8_T,\n\tuint8_T, INT8_T, int8_T): Conditionally define.\n\tFrom Andy Adler <adler@site.uottawa.ca>.\n\n2006-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* oct-conf.h.in (OCTAVE_CONF_CURL_LIBS): Substitute.\n\t* toplev.cc (octave_config_info): Add CURL_LIBS to the list.\n\n2006-10-09  Alexander Barth  <abarth@marine.usf.edu>\n\n\t* DLD-FUNCTIONS/urlwrite.cc: New file providing urlwrite and urlread.\n\n2006-10-09  John W. Eaton  <jwe@octave.org>\n\n\t* pt-mat.cc (tree_matrix::dup): Append new elements to new matrix.\n\t* pt-cell.cc (tree_cell::dup): Append new elements to new cell array.\n\n2006-10-04  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.9+.\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l (F__clear_plot_window__):\n\tRename from Fclearplot.  Only clear plot window.\n\n2006-10-03  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/luinc.cc (Fluinc): Avoid crash if SparseLU or\n\tSparseComplexLU constructor fails.\n\n\t* DLD-FUNCTIONS/find.cc (find_nonzero_elem_idx):\n\tDelete unused variable.\n\n2006-10-03  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (OCT_LINK_DEPS) Include $(CAMD_LIBS) in the list.\n\t(octave$(EXEEXT)): Include $(CAMD_LIBS) in link command.\n\n2006-10-02  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.9.\n\t(OCTAVE_API_VERSION): Now api-v22.\n\t(OCTAVE_RELEASE_DATE): Now 2006-10-02.\n\n\t* pr-output.cc (pr_plus_format): Use \"inline\" instead of \"static\n\tinline\" for template functions to avoid problems when not\n\tcompiling with \tg++.\n\n\t* mex.cc (call_mex): Delete elements of argout.\n\tFrom Kai Labusch <labusch@inb.uni-luebeck.de>.\n\n2006-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/spfind.cc (sparse_find_non_zero_elem_idx):\n\tLeading dimension is NR, not NC.\n\n\t* Makefile.in (DEP_5): Include oct-errno.cc in the list.\n\n2006-09-27  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (abs): New template function.  Instantiate for\n\tunsigned types.\n\n2006-09-27  David Bateman  <dbateman@free.fr>\n\n\t* file-io.cc (Fsprintf): If fmt is an sq_string, return an sq_string.\n\n\t* DLD-FUNCTIONS/sparse.cc (spfind, sparse_find): Delete.\n\t* DLD-FUNCTIONS/spfind.cc: New file implementating compatible\n\tsparse find function.\n\t* Makefile.in (DLD_XSRC): Add spfind.cc.\n\n2006-09-26  Bill Denney  <bill@givebillmoney.com>\n\n\t* DLD-FUNCTIONS/find.cc (find_nonzero_elem_idx, Ffind):\n\tHandle direction and limit on number of elements to find.\n\n2006-09-26  John W. Eaton  <jwe@octave.org>\n\n\t* error.cc (warning_1): Call error_2, not error.\n\n2006-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* ops.h (DEFSTRDBLCONVFN): New arg, TFROM.\n\t* OPERATORS/op-double-conv.cc: Declare and install sq_string\n\tconversions too.\n\n\t* ov-base-int.cc (octave_base_int_scalar<T>::convert_to_str_internal,\n\toctave_base_int_matrix<T>::convert_to_str_internal):\n\tNew functions.\n\t* ov-base-int.h: Provide decls.\n\n2006-09-15  Søren Hauberg  <soren@hauberg.org>.\n\n\t* data.cc (Fsize): If nargout > ndims, fill with 1.\n\n2006-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc: Fix xerbla decl.\n\n2006-09-13  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/cellfun.cc: Improve error message for uniform\n\toutput case when results are not scalars.  Avoid shadow decls.\n\n2006-09-13  David Bateman  <dbateman@free.fr>\n\n\t* ov-scalar.h (octave_scalar::sparse_matrix_value,\n\toctave_scalar::sparse_complex_matrix_value): New extractor functions.\n\t* ov-complex.h (octave_complex::sparse_matrix_value,\n\toctave_complex::sparse_complex_matrix_value): Ditto.\n\t* DLD-FUNCTIONS/spkron.cc (Fspkron): Change example in help.\n\n2006-09-12  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Allow matlab compatiable\n\t'UniformOutput' and 'ErrorHandler' options.  Change output when\n\tcalled with function handler or inline function to by default have\n\t'UniformOutput' set to true.  Allow functions with multiple inputs\n\tand outputs. Add test code.  Replace some int with octave_idx_type.\n\t(Fnum2cell): Replace some int with octave_idx_type.  Add test code.\n\n2006-09-11  Yozo Hida  <yozo@cs.berkeley.edu>\n\n\t* DLD-FUNCTIONS/gcd.cc (Fgcd): Extend range by using std::floor\n\tinstead of converting to int.\n\n2006-09-05  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_sparse::as_octave_value): Cast nzmax to\n\toctave_idx_type for sparse matrix constructors.\n\n2006-09-01  John W. Eaton  <jwe@octave.org>\n\n\t* dirfns.cc: Don't handle nargout == 0 as a special case.\n\t(octave_change_to_directory): Perform tilde expansion on directory\n\tname here.\n\n2006-08-30  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc (get_file_format): Fix misplaced #endif.\n\n2006-08-29  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (execute_pkg_add_or_del):\n\tSource PKG_ADD or PKG_DEL in base workspace.\n\t* parse.y (source_file): New optional arg, context.\n\t* parse.h (source_file): Fix decl.\n\n2006-08-25  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.8+.\n\n2006-08-24  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.8.\n\t(OCTAVE_API_VERSION): Now api-v21.\n\t(OCTAVE_RELEASE_DATE): Now 2006-08-24.\n\n2006-08-23  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h (octave_value::save_ascii): Delete strip_nan_and_inf arg.\n\t* ov-base.h, ov-base.cc (octave_base_value::save_ascii): Likewise.\n\t* ov-base-int.h, ov-base-int.cc\t(octave_base_int_matrix<T>::save_ascii,\n\toctave_base_int_scalar<T>::save_ascii, ): Likewise.\n\t* ov-base-sparse.cc, ov-base-sparse.h\n\t(octave_base_sparse<T>::save_ascii): Likewise.\n\t* ov-bool-mat.cc, ov-bool-mat.h (octave_bool_matrix::save_ascii):\n\tLikewise.\n\t* ov-bool.cc, ov-bool.h (octave_bool::save_ascii): Likewise.\n\t* ov-cell.cc, ov-cell.h (octave_cell::save_ascii): Likewise.\n\t* ov-complex.cc, ov-complex.h (octave_complex::save_ascii): Likewise.\n\t* ov-fcn-handle.cc, ov-fcn-handle.h (octave_fcn_handle::save_ascii):\n\tLikewise.\n\t* ov-fcn-inline.cc, ov-fcn-inline.h (octave_fcn_inline::save_ascii):\n\tLikewise.\n\t* ov-list.cc, ov-list.h (octave_list::save_ascii): Likewise.\n\t* ov-range.cc, ov-range.h (octave_range::save_ascii): Likewise.\n\t* ov-scalar.cc, ov-scalar.h (octave_scalar::save_ascii): Likewise.\n\t* ov-str-mat.cc, ov-str-mat.h (octave_char_matrix_str::save_ascii):\n\tLikewise.\n\t* ov-struct.cc, ov-struct.h (octave_struct::save_ascii): Likewise.\n\t* ov-re-mat.cc, ov-re-mat.cc (octave_matrix::save_ascii): Likewise.\n\t* ov-cx-mat.cc, ov-cx-mat.cc (octave_complex_matrix::save_ascii):\n\tLikewise.\n\t* ov-cx-mat.cc, ov-cx-mat.cc (octave_complex_matrix::save_ascii):\n\tLikewise.\n\t* ov-re-mat.cc, ov-re-mat.cc (octave_matrix::save_ascii): Likewise.\n\n\t* ls-oct-ascii.cc, ls-oct-ascii.h (save_ascii_data):\n\tDelete strip_nan_and_inf arg.\n\t(save_ascii_data_for_plotting): Delete strip_nan_and_inf arg from\n\tcall to save_ascii_data.\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l (handle_using): Accept \"(EXPR)\"\n\tas components of using clauses.\n\t(enum _toktype): New element DOLLAR.\n\tAccept \"$\" in lexer.\n\n\t* ls-oct-ascii.cc (save_ascii_data): Delete arg strip_nan_and_inf.\n\tChange all uses.\n\n\t* ls-oct-ascii.h (save_three_d): Provide decl.\n\t* load-save.h (save_ascii_data_for_plotting, save_three_d):\n\tDelete decls.\n\n2006-08-22  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h (octave_value::save_ascii): strip_nan_and_inf is now int,\n\tnot bool.\n\t* ov-base.h, ov-base.cc (octave_base_value::save_ascii): Likewise.\n\t* ov-base-int.h, ov-base-int.cc\t(octave_base_int_matrix<T>::save_ascii,\n\toctave_base_int_scalar<T>::save_ascii, ): Likewise.\n\t* ov-base-sparse.cc, ov-base-sparse.h\n\t(octave_base_sparse<T>::save_ascii): Likewise.\n\t* ov-bool-mat.cc, ov-bool-mat.h (octave_bool_matrix::save_ascii):\n\tLikewise.\n\t* ov-bool.cc, ov-bool.h (octave_bool::save_ascii): Likewise.\n\t* ov-cell.cc, ov-cell.h (octave_cell::save_ascii): Likewise.\n\t* ov-complex.cc, ov-complex.h (octave_complex::save_ascii): Likewise.\n\t* ov-fcn-handle.cc, ov-fcn-handle.h (octave_fcn_handle::save_ascii):\n\tLikewise.\n\t* ov-fcn-inline.cc, ov-fcn-inline.h (octave_fcn_inline::save_ascii):\n\tLikewise.\n\t* ov-list.cc, ov-list.h (octave_list::save_ascii): Likewise.\n\t* ov-range.cc, ov-range.h (octave_range::save_ascii): Likewise.\n\t* ov-scalar.cc, ov-scalar.h (octave_scalar::save_ascii): Likewise.\n\t* ov-str-mat.cc, ov-str-mat.h (octave_char_matrix_str::save_ascii):\n\tLikewise.\n\t* ov-struct.cc, ov-struct.h (octave_struct::save_ascii): Likewise.\n\t* ov-re-mat.cc, ov-re-mat.cc (octave_matrix::save_ascii): Likewise.\n\t* ov-cx-mat.cc, ov-cx-mat.cc (octave_complex_matrix::save_ascii):\n\tLikewise.\n\n\t* ov-cx-mat.cc, ov-cx-mat.cc (octave_complex_matrix::save_ascii):\n\tDon't strip Inf and NaN here.  Call ComplexMatrix::save_ascii to\n\tdo the real work.\n\t* ov-re-mat.cc, ov-re-mat.cc (octave_matrix::save_ascii):\n\tDon't strip Inf and NaN here.  Call Matrix::save_ascii to do the\n\treal work.\n\n\t* ov-re-mat.cc, ov-cx-mat.cc (strip_infnan): Delete.\n\t* ls-oct-ascii.cc, ls-oct-ascii.h (save_ascii_data):\n\tstrip_nan_and_inf is now int, not bool.\n\t(strip_infnan): Delete.\n\t(save_ascii_data_for_plotting): Call save_ascii_data with\n\tstrip_nan_and_inf = 2.\n\n\t* Makefile.in (INCLUDES): Remove matrix.h from the list.\n\n2006-08-22  David Bateman  <dbateman@free.fr>\n\n\t* sparse-xpow.cc: Replace all uses of pow by std::pow.\n\t(elem_pow): Simplify for two sparse matrices arguments.\n\n2006-08-22  John W. Eaton  <jwe@octave.org>\n\n\t* ls-oct-ascii.cc: Increase default value of save_precision to 16.\n\n\t* ls-mat-ascii.cc (save_mat5_ascii_data): Use scientific format.\n\n2006-08-21  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (read_mat5_binary_data, read_mat5_integer_data,\n\twrite_mat5_array): Unconditionally enable code for 64-bit int types.\n\n\t* ov-fcn-handle.cc (DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA):\n\tFor compatibility, set class to function_handle.\n\n2006-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (set_real_matrix_format): Also always include space\n\tfor sign if values are int, inf, or nan.\n\t(set_complex_format, set_complex_matrix_format): Always include\n\tspace for sign in real format, but never in imaginary format.\n\n\t* gripes.cc (gripe_logical_conversion): New function.\n\t* gripes.h: Provide decl.\n\t* ov.h (octave_value::bool_value, octave_value::bool_matrix_value,\n\toctave_value::bool_array_value): New arg, warn.\n\t* ov-base.cc, ov-base.h (octave_base_value::bool_value,\n\toctave_base_value::bool_matrix_value,\n\toctave_base_value::bool_array_value): Likewise.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::bool_array_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::bool_array_value): Likewise.\n\t* ov-range.h (octave_range::bool_array_value): Likewise.\n\t* ov-re-mat.cc, ov-re-mat.h (octave_matrix::bool_array_value):\n\tLikewise.\n\t* ov-re-sparse.cc, ov-re-sparse.h\n\t(octave_sparse_matrix::bool_array_value): Likewise.\n\t* ov-scalar.h (octave_scalar::bool_value,\n\toctave_scalar::bool_array_value): Likewise.\n\t* OPERATORS/op-bm-b.cc (oct_assignop_conv_and_assign):\n\tAsk for warning from bool_array_value.\n\t* OPERATORS/op-bm-bm.cc (oct_assignop_conv_and_assign): Likewise.\n\t* ov-bool.h (octave_bool::bool_value,\n\toctave_bool::bool_matrix_value, octave_bool::bool_array_value):\n\tLikewise.\n\t* ov-bool-mat.h (octave_bool_matrix::bool_matrix_value,\n\toctave_bool_matrix::bool_array_value): Likewise.\n\t* ov-bool-sparse.cc, ov-bool-sparse.h\n\t(octave_sparse_bool_matrix::bool_matrix_value,\n\toctave_sparse_bool_matrix::bool_array_value): Likewise.\n\n2006-08-18  Benjamin Lindner  <lindnerben@gmx.net>\n\n\t* ls-mat5.cc (read_mat5_tag): Declare type as int32_t, not int.\n\t(read_mat5_binary_element): Likewise, for len and element_length.\n\n2006-08-18  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.h (enum load_save_format): New element, LS_MAT_ASCII_LONG.\n\t* load-save.cc (Fload, Fsave): Make -ascii Matlab compatible.\n\t(do_save): Handle LS_MAT_ASCII.\n\t* ls-mat-ascii.cc (save_mat_ascii_data): New function.\n\t* ls-mat-ascii.h: Provide decl.\n\n2006-08-17  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (save_mat5_element_length): Correctly compute element\n\tlength for character data.  Handle N-d character data\n\t(save_mat5_binary_element): Handle N-d character data.\n\n2006-08-16  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (gobble_leading_white_space): New arg, SKIP_CODE.\n\tChange all uses.\n\n2006-08-15  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (help_from_file): Call get_help_from_file with new file\n\targ.  Print file info here.\n\n\t* parse.y (get_help_from_file): Delete include_file_info arg.\n\tProvide two versions, one that returns the file found in a\n\treference arg and one that does not.\n\n\t* variables.cc (do_isglobal): New function.\n\t(Fisglobal): Use it.\n\t(Fis_global): New function.\n\n2006-08-14  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (symbol_record_name_compare): Fix casts.\n\n\t* ov-cell.cc (octave_cell::subsasgn): Call empty_conv for 0x0\n\tobjects, not just empty objects.\n\n\t* oct-map.h (Octave_map::clear): Also clear key_list.\n\n\t* load-path.cc (load_path::find_dir_info, load_path::do_add,\n\tload_path::do_remove): Perform tilde expansion on directory here.\n\n2006-07-29  John W. Eaton  <jwe@octave.org>\n\n\t* matrix.h: Delete to avoid conflict with liboctave/Matrix.h on\n\tcase-insensitive filesystems.\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.7+.\n\n2006-07-28  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.7.\n\t(OCTAVE_API_VERSION): Now api-v20.\n\t(OCTAVE_RELEASE_DATE): Now 2006-07-28.\n\n\t* load-path.cc (path::do_add): Warn for trailing \"//\".\n\n\t* strfns.cc: Comment out some tests for snapshot.\n\n2006-07-27  John W. Eaton  <jwe@octave.org>\n\n\t* defaults.cc (Vlocal_api_arch_lib_dir): New variable.\n\t(set_default_local_api_arch_lib_dir): New function.\n\t(install_defaults): Call it.\n\t(set_exec_path): Put Vlocal_api_arch_lib_dir in the list.\n\t* toplev.cc (localapiarchlibdir): Include it in the list.\n\t* defaults.h.in (OCTAVE_LOCALAPIARCHLIBDIR): Substitute here.\n\n2006-07-26  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray::as_octave_value (mxArray *)): New static function.\n\t(call_mex, mexPutVariable, mexCallMATLAB,\n\tmxArray_cell::as_octave_value, mxArray_struct::as_octave_value):\n\tUse static version of as_octave_value here.\n\t(mxArray_sparse::mxArray_sparse (const mxArray_sparse&)):\n\tCheck pr, ir, and jc before calling memcpy.\n\t(mxArray_number::mxArray_number): Check pr before calling memcpy\n\n\t* mxarray.h (mxArray::as_octave_value (mxArray *)): Provide decl.\n\t(mxArray::as_octave_value): Now protected.\n\n\t* file-io.cc (Ffeof, Fferror): Use DEFUNX instead of DEFUN.\n\n\t* mex.cc (xfree): New function.\n\t(mex::free): Use it.\n\t(mxArray_struct::~mxArray_struct, mxArray_cell::~mxArray_cell):\n\tDelete elements with delete, not mxDestroyArray.\n\t(mex::cleanup): Don't call mex::free or mex::free_value.\n\t(mex::free_value): Add debug warning.\n\t(mex::mark, mex::unmark): Fix debug warning.\n\t(call_mex): Use unwind_protect frame.\n\t(mexUnlock): Use iterator to remove item from mex_lock_count.\n\n\t* octave.cc (maximum_braindamage): Use disable_warning instead of\n\tbind_internal_variable to disable function-name-clash warning.\n\t* error.cc (disable_warning): No longer static.\n\t* error.h: Provide decl.\n\n2006-07-25  David Bateman  <dbateman@free.fr>\n\n\t* mex.cc (mxArray_octave_value::get_class_id): Handle sparse.\n\t(class mxArray_sparse): Derive from mxArray_matlab, not\n\tmxArray_number.\n\t(mxArray_sparse::as_octave_value): Implement function.\n\t* ov-bool-sparse.cc (octave_sparse_bool_matrix::as_mxArray):\n\tImplement function.\n\t* ov-cx-sparse.cc (octave_sparse_complex_matrix::as_mxArray):\n\tImplement function.\n\t* ov-re-sparse.cc (octave_sparse_matrix::as_mxArray):\n\tImplement function.\n\n2006-07-25  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mxArray_struct::as_octave_value, call_mex,\n\tmexCallMATLAB, mxArray_cell::as_octave_value):\n\tConvert NULL mxArray* pointers to empty matrix values.\n\t(mxArray_octave_value:get_ir): Fix typo.\n\n2006-07-22  John W. Eaton  <jwe@octave.org>\n\n\t* mxarray.h: New file.\n\t* mex.h, mexproto.h, mex.cc: New implementation of mxArray and MEX\n\tinterface.\n\n\t* ov.h (octave_value::mex_get_ir, octave_value::mex_get_jc):\n\tNew functions.\n\t* ov-base.h (octave_base_value::mex_get_ir,\n\toctave_base_value::mex_get_jc): New virtual functions.\n\t* ov-base-sparse.h (octave_base_sparse<T>::mex_get_ir,\n\toctave_base_sparse<T>::mex_get_jc): New functions.\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_SCALAR_T::as_mxArray,\n\tOCTAVE_VALUE_INT_MATRIX_T::as_mxArray): New functions.\n\t* ov-int8.h, ov-int16.h, ov-int32.h, ov-int64.h, ov-uint8.h,\n\tov-uint16.h, ov-uint32.h, ov-uint64.h: Define OCTAVE_INT_MX_CLASS\n\tbefore including ov-intx.h.  Undef it after.\n\t* ov-range.cc (octave_range::as_mxArray): New function.\n\t* ov-range.h: Provide decl.\n\t* ov-scalar.cc (octave_scalar::as_mxArray): New function.\n\t* ov-scalar.h: Provide decl.\n\t* ov-complex.cc (octave_complex::as_mxArray): New function.\n\t* ov-complex.h: Provide decl.\n\t* ov-re-mat.cc (octave_matrix::as_mxArray): New function.\n\t* ov-re-mat.h: Provide decl.\n\t* ov-cx-mat.cc (octave_complex_matrix::as_mxArray): New function.\n\t* ov-cx-mat.h: Provide decl.\n\t* ov-ch-mat.cc (octave_char_matrix::as_mxArray): New function.\n\t* ov-ch-mat.h: Provide decl.\n\t* ov-bool-mat.cc (octave_bool_matrix::as_mxArray): New function.\n\t* ov-bool-mat.h: Provide decl.\n\t* ov-bool.cc (octave_bool::as_mxArray): New function.\n\t* ov-bool.h: Provide decl.\n\n\t* ov-struct.h (octave_struct::numel): New function.\n\n\t* ls-mat5.cc (arrayclasstype): Use \"MAT_FILE_\" instead of \"mx\" as\n\tprefix for element names.\n\n\t* ov.h (octave_value::as_mxArray): New function.\n\t* ov-base.cc (octave_base_value::as_mxArray): New function.\n\t* ov-base.h: Provide decl.\n\n\t* ov.h (octave_value::mex_get_data): New function.\n\t* ov-base.h (octave_base_value::mex_get_data): New function.\n\t* ov-base-scalar.h (octave_base_scalar<ST>::mex_get_data): New function.\n\t* ov-base-matrix.h (octave_base_matrix<MT>::mex_get_data): New function.\n\t* ov-intx.h (OCTAVE_VALUE_INT_SCALAR_T::mex_get_data): New function.\n\n\t* ov.h (octave_value::nfields): New function.\n\t* ov-base.cc (octave_base_value::nfields): New virtual function.\n\t* ov-base.h: Provide decl.\n\t* ov-struct.h (octave_struct::nfields): New function.\n\n2006-07-19  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-bm-bm.cc (oct_assignop_conv_and_assign): New function.\n\t(install_bm_bm_ops): Install it for various types.\n\t* OPERATORS/op-bm-b.cc (oct_assignop_conv_and_assign): New function.\n\t(install_bm_b_ops): Install it for various types.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::bool_array_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::bool_array_value): New functions.\n\t* ov-range.h (octave_range::bool_array_value): New function.\n\t* ov-re-sparse.cc (octave_sparse_matrix::bool_array_value):\n\tNew function.\n\t* ov-re-sparse.h: Provide decl.\n\t* ov-re-mat.cc (octave_matrix::bool_array_value): New function.\n\t* ov-re-mat.h: Provide decl.\n\n\t* ov-base.cc (octave_base_value::numeric_assign):\n\tAvoid memory leak when converting LHS.\n\n2006-07-18  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h (octave_value::is_int8_type, octave_value::is_int16_type,\n\toctave_value::is_int32_type, octave_value::is_int64_type,\n\toctave_value::is_uint8_type, octave_value::is_uint16_type,\n\toctave_value::is_uint32_type, octave_value::is_uint64_type):\n\tNew functions.\n\t* ov-base.h (octave_base_value::is_int8_type,\n\toctave_base_value::is_int16_type,\n\toctave_base_value::is_int32_type,\n\toctave_base_value::is_int64_type,\n\toctave_base_value::is_uint8_type,\n\toctave_base_value::is_uint16_type,\n\toctave_base_value::is_uint32_type,\n\toctave_base_value::is_uint64_type): New functions.\n\t* ov-int8.h, ov-int16.h, ov-int32.h, ov-int16.h, ov-uint8.h,\n\tov-uint16.h, ov-uint32.h, ov-uint16.h: Define OCTAVE_BASE_INT_T.\n\t* ov-intx.h: Use OCTAVE_BASE_INT_T to define type-specific predicate.\n\n\t* ov.h (octave_value::is_double_type, octave_value::is_single_type):\n\tNew functions.\n\t* ov-base.h (octave_base_value::is_double_type,\n\toctave_base_value::is_single_type): New functions.\n\t* ov-re-mat.h (octave_matrix::is_double_type): New function.\n\t* ov-cx-mat.h (octave_matrix::is_double_type): New function.\n\t* ov-scalar.h (octave_scalar::is_double_type): New function.\n\t* ov-complex.h (octave_complex::is_double_type): New function.\n\t* ov-range.h (octave_range::is_double_type): New function.\n\t* ov-re-sparse.h (octave_sparse_matrix::is_double_type): New function.\n\t* ov-cx-sparse.h (octave_sparse_complex_matrix::is_double_type):\n\tNew function.\n\n2006-07-15  John W. Eaton  <jwe@octave.org>\n\n\t* ov-typeinfo.cc: Also instantiate arrays of assignany_ops.\n\n\t* oct-errno.cc.in (octave_errno::octave_errno): VALUE field in\n\terrno_struct no longer const.\n\n\t* DLD-FUNCTIONS/dispatch.cc (octave_dispatch::do_index_op):\n\tDeclare\tresize_ok arg as bool, not int.\n\tProvide default value for resize_ok.\n\n2006-07-14  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (do_write): Include explicit instantiations.\n\n\t* ov-str-mat.h (octave_char_matrix_sq_str::resize):\n\tInclude fill arg to match base class.\n\t* ov-struct.h (octave_struct::resize): Likewise.\n\n\t* ov-base-mat.cc, ov-base-mat.h, ov-base-sparse.cc,\n\tov-base-sparse.h, ov-base.cc, ov-base.h, ov-bool.cc,\n\tov-bool.h, ov-complex.cc, ov-complex.h, ov-intx.h, ov-list.cc,\n\tov-list.h, ov-range.cc, ov-range.h, ov-scalar.cc, ov-scalar.h,\n\tov-str-mat.cc, ov-str-mat.h, ov.h (do_index_op):\n\tDeclare\tresize_ok arg as bool, not int.\n\tProvide default value for resize_ok.\n\n\t* c-file-ptr-stream.h (c_file_ptr_stream::c_file_ptr_stream):\n\tQualify init.\n\n2006-07-13  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.h (Octave_map::del): Add missing std:: qualifier to use\n\tof find template.\n\n2006-07-07  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h (octave_value::is_bool_scalar): New function.\n\t* ov-base.h (octave_base_value::is_bool_scalar): New function.\n\t* ov-bool.h (octave_bool::is_bool_scalar): New function.\n\n\t* oct-map.cc (Octave_map::keys): Use assert.\n\t(Octave_map::assign): Avoid inserting new key in map unless\n\tassignment to cell succeeds.\n\n\t* oct-map.h (Octave_map::del): Only touch key_list if map contains key.\n\tAssert that key_list contains key.\n\n\t* oct-map.h (Octave_map::maybe_add_to_key_list): For efficiency,\n\tcheck map, not key_list.  From Paul Kienzle  <pkienzle@users.sf.net>.\n\n2006-07-06  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Declare mrowsc volatile.\n\n\t* ov-struct.cc (octave_struct::print_raw): Print keys in key_list\n\torder.\n\n\t* oct-map.h (Octave_map::key_list): New data member.\n\t(Octave_map::maybe_add_to_key_list): New function.\n\t(Octave_map::key_list_iterator, Octave_map::const_key_list_iterator):\n\tNew typedefs.\n\t(Octave_map::del): Also delete key from key_list.\n\t* oct-map.cc (Octave_map::keys): Compute return value from\n\tkey_list instead of map.\n\t(Octave_map::assign, Octave_map::contents): Call maybe_add_to_key_list.\n\t* oct-map.h, oct-map.cc (Octave_map::Octave_map):\n\tInsert keys in key_list.\n\n\t* oct-map.h (Octave_map::Octave_map (const dim_vector&,\n\tconst string_vector&)): New arg, key_list_arg.\n\t* oct-map.cc: Move definition here.\n\n2006-07-05  John W. Eaton  <jwe@octave.org>\n\n\t* mex.cc (mexGetVariable): Rename from mexGetArray, swap arguments.\n\t(mexGetVariablePtr): Rename from mexGetArrayPtr, swap arguments.\n\t(mexErrMsgIdAndTxt, mexWarnMsgIdAndTxt): New functions.\n\t* mexproto.h: Provide decls.\n\tInclude decls for as yet unsupported functions.\n\t* mex.h: Add enum for class ids.\n\t(mexGetArray): Define using mexGetVariable.\n\t(mexGetArrayPtr): Define using mexGetVariablePtr.\n\n2006-07-02  John W. Eaton  <jwe@octave.org>\n\n\t* ov-str-mat.cc (CHAR_MATRIX_CONV): Omit \"warn-\" from label.\n\t* parse.y (maybe_warn_variable_switch_label): Likewise.\n\n2006-07-01  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (finish_cell): Use finish_matrix to do constant folding.\n\n2006-06-30  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base.cc (octave_base_value::numeric_assign):\n\tAvoid memory leak when converting LHS.\n\n\t* oct-hist.cc (do_history, initialize_history, Fhistory_file):\n\tDon't perform tilde expansion on history file name.\n\n\t* syscalls.cc (Flstat, Fstat): Don't perform tilde expansion on arg.\n\t* input.cc (Fread_readline_init_file): Likewise.\n\t* dirfns.cc (Fcd, Freaddir): Likewise.\n\n\t* load-path.cc (genpath): Don't perform tilde expansion on name.\n\t(load_path::do_add): Don't warn about moving \".\" to front of list.\n\n2006-06-28  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (Faddpath): Don't treat \".\" specially here.\n\tDon't check directory status here.\n\t(Fpath): Handle all args.  Don't treat \".\" specially here.\n\t(Faddpath, Frmpath): Delete unused variable xpath.\n\t(load_path::do_add): New function.\n\t(load_path::do_prepend, load_path::do_append): Use it.\n\t(load_path::do_remove): Really prevent removal of \".\".\n\t(load_path::do_clear): Clearing doesn't remove \".\".\n\t(load_path::append, load_path::prepend, load_path::do_append,\n\tload_path::do_prepend): New arg, warn.\n\n\t* load-path.h: Fix decls.\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp_list):\n\tAvoid bug in older versions of g++.\n\n2006-06-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (clean): Also remove $(DLD_OBJ).\n\n\t* sighandlers.cc (install_signal_handlers): Don't handle SIGPROF.\n\tFrom Geoffrey Knauth <geoff@knauth.org>.\n\n2006-06-25  John W. Eaton  <jwe@octave.org>\n\n\t* mk-pkg-add: Avoid apparently non-portable sed patterns.\n\n2006-06-21  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (do_who): Handle mex.\n\n\t* symtab.cc (SYMBOL_DEF::type_as_string, SYMBOL_DEF::which,\n\tsymbol_table::clear_functions, table::clear_function,\n\tsymbol_table::clear_function_pattern):\n\tHandle mex.\n\t* symtab.h (symbol_record::is_mex_function,\n\tsymbol_record::symbol_def::is_mex_function): New functions.\n\t(symbol_record::TYPE): New value, MEX_FUNCTION.\n\t(symbol_record::is_function, symbol_table::user_function_name_list,\n\tSYMTAB_ALL_TYPES): Handle MEX_FUNCTION.\n\n\t* ov-fcn.h (octave_function::octave_function):\n\tProvide default for doc string arg.\n\n\t* defun.cc (install_mex_function): New function.\n\t* defun-int.h: Provide decl.\n\n\t* ov-builtin.cc (any_arg_is_magic_colon): Delete.\n\t(octave_builtin::do_multi_index_op): Call has_magic_colon method\n\tfor args instead of any_arg_is_magic_colon.\n\n\t* ov-base.h (octave_base_value::is_mex_function): New function.\n\t* ov.h (octave_value::is_mex_function): New function.\n\n\t* ov-mex-fcn.h, ov-mex-fcn.cc: New files.\n\n\t* parse.y (load_fcn_from_file): Also handle .mex files.\n\n\t* dynamic-ld.cc (octave_dynamic_loader::load_oct): Rename from load.\n\t(octave_dynamic_loader::do_load_oct): Rename from do_load.\n\t* dynamic-ld.h: Fix decls.\n\n\t* utils.cc (mex_file_in_path): New function.\n\t* utils.h: Provide decl.\n\n\t* variables.cc (symbol_out_of_date): Also handle mex files.\n\n\t* load-path.cc (load_path::dir_info::get_file_list,\n\tload_path::dir_info::get_private_function_map,\n\tload_path::do_find_fcn, load_path::add_to_fcn_map,\n\tload_path::do_display): Also handle mex files.\n\t* load-path.h (load_path::find_mex_file): New static function.\n\t(load_path::MEX_FILE): New static data member.\n\t(load_path::do_find_fcn): By default, also look for mex files.\n\n\t* matrix.h, mex.h, mex.cc: New files from Octave Forge\n\t* mexproto.h: New file, extracted from mex.h.\n\t* Makefile.in: Add them to the appropriate lists.\n\n2006-06-20  John W. Eaton  <jwe@octave.org>\n\n\t* ov-re-mat.cc (octave_matrix::convert_to_str_internal):\n\tDon't lose empty dimensions on conversion to char.\n\n\t* strfns.cc (Fstrcmp): Handle comparison of cellstr and empty string.\n\n2006-06-16  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (%union): New type, anon_fcn_handle_type.\n\t(anon_fcn_handle): Now anon_fcn_handle_type, not tree_constant_type.\n\t(make_anon_fcn_handle):\tReturn tree_anon_fcn_handle, not tree_constant.\n\n\t* comment-list.cc (octave_comment_list::dup): New function.\n\t* comment-list.h: Provide decl.\n\n\t* pt-cmd.cc (tree_no_op_command::dup): New function.\n\t* pt-cmd.h: Provide decl.\n\t(tree_command::dup): New pure virtual function.\n\n\t* pt-loop.cc (tree_while_command::dup, tree_do_until_command::dup,\n\ttree_simple_for_command::dup, tree_complex_for_command::dup):\n\tNew functions.\n\t* pt-loop.h: Provide decls.\n\n\t* pt-jump.cc (tree_break_command::dup, tree_continue_command::dup,\n\ttree_return_command::dup): New functions.\n\t* pt-jump.h: Provide decls.\n\n\t* pt-except.cc (tree_try_catch_command::dup,\n\ttree_unwind_protect_command::dup): New functions.\n\t* pt-except.h: Provide decls.\n\n\t* pt-select.cc (tree_if_clause::dup, tree_if_command_list::dup,\n\ttree_if_command::dup, tree_switch_case::dup,\n\ttree_switch_case_list::dup, tree_switch_command::dup):\n\tNew functions.\n\t* pt-select.h: Provide decls.\n\n\t* pt-decl.cc (tree_decl_elt::dup, tree_decl_init_list::dup,\n\ttree_global_command::dup, tree_static_command::dup): New functions.\n\t* pt-decl.h: Provide decls.\n\n\t* pt-exp.h (tree_expression::copy_base): New function.\n\t(tree_expression::dup): New pure virtual function.\n\n\t* pt-fcn-handle.cc, pt-fcn-handle.h (tree_anon_fcn_handle): New class.\n\n\t* pt-fcn-handle.cc (tree_function_handle::dup): New function.\n\t* pt-fcn-handle.h: Provide decl.\n\n\t* pt-colon.cc (tree_colon_expression::dup): New function.\n\t* pt-colon.h: Provide decl.\n\t(tree_colon_expression::tree_colon_expression (tree_expression *,\n\ttree_expression *, tree_expression *, int, int)): New constructor.\n\n\t* pt-const.cc (tree_constant::dup): New function.\n\t(tree_constant::tree_constant (const octave_value&, const\n\tstd::string&, int, int)): New constructor.\n\t* pt-const.h: Provide decls.\n\n\t* pt-idx.cc (tree_index_expression::dup): New functoin.\n\t(tree_index_expression::tree_index_expression (int, int)):\n\tNew constructor.\n\t* pt-idx.h: Provide decls.\n\n\t* pt-arg-list.cc (tree_argument_list::dup): New function.\n\t* pt-arg-list.h: Provide decl.\n\n\t* pt-id.cc (tree_identifier::dup): New function.\n\t* pt-id.h: Provide decl.\n\n\t* pt-cell.cc (tree_cell::dup): New function.\n\t* pt-cell.h: Provide decl.\n\n\t* pt-mat.cc (tree_matrix::dup): New function.\n\t* pt-mat.h: Provide decl.\n\n\t* pt-assign.cc (tree_simple_assignment::dup,\n\ttree_multi_assignment::dup): New functions.\n\t* pt-assign.h: Provide decls.\n\n\t* pt-binop.cc (tree_binary_expression::dup,\n\ttree_boolean_expression::dup): New functions.\n\t* pt-binop.h: Provide decls.\n\n\t* pt-unop.cc (tree_prefix_expression::dup,\n\ttree_postfix_expression::dup): New functions.\n\t* pt-unop.h: Provide decls.\n\n\t* pt-stmt.cc (tree_statement::dup, tree_statement_list::dup):\n\tNew functions.\n\t* pt-stmt.h: Provide decls.\n\n\t* pt-misc.cc (tree_parameter_list::dup,\n\ttree_return_list::dup): New functions.\n\t* pt-misc.h: Provide decls.\n\n\t* symtab.cc (symbol_table::dup, symbol_table::inherit,\n\tsymbol_record:is_automatic_variable): New functions.\n\t* symtab.h: Provide decls.\n\t(symbol_record::automatic_variable): New data member.\n\t(symbol_record::symbol_record): Initialize it.\n\t(symbol_record::mark_as_automatic_variable): New function.\n\n\t* pt-walk.h (tree_walker::visit_anon_fcn_handle):\n\tNew pure virtual function.\n\t* pt-pr-code.cc (tree_print_code::visit_anon_fcn_handle): New function.\n\t* pt-pr-code.h: Provide decl.\n\t* pt-bp.cc (tree_breakpoint::visit_anon_fcn_handle): New function.\n\t* pt-bp.h: Provide decl.\n\t* pt-check.cc (tree_checker::visit_anon_fcn_handle): New function.\n\t* pt-check.h: Provide decl.\n\n2006-06-13  John W. Eaton  <jwe@octave.org>\n\n\t* pt-stmt.cc (tree_statement_list::eval): Revise previous change\n\tto preserve return-last-value-computed semantics.\n\n\t* DLD-FUNCTIONS/fsolve.cc (hybrd_info_to_fsolve_info):\n\tWarn about invalid values of INFO from MINPACK instead of calling\n\tpanic_impossible.\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tDon't assign values returned by evaluation of cmd_list to\n\ttemporary variable.  Delete unused variable last_computed_value.\n\n\t* pt-stmt.cc (tree_statement_list::eval):\n\tClear retval before each statement is evaluated.\n\n2006-06-12  John W. Eaton  <jwe@octave.org>\n\n\t* unwind-prot.h (unwind_protect_fptr): New macro.\n\t* load-path.cc (load_path::do_set): Use it instead of\n\tunwind_protect_ptr when protecting add_hook function pointer.\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load): Use FCN_PTR_CAST\n\there instead of reinterpret_cast.\n\n2006-06-09  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.6+.\n\n2006-06-09  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.6.\n\t(OCTAVE_API_VERSION): Now api-v19.\n\t(OCTAVE_RELEASE_DATE): Now 2006-06-09.\n\n\t* ov-cell.cc (cell::save_hdf5): Use leading zeros to keep elements\n\tcorrectly sorted in the HDF file.\n\tFrom Stephen Fegan <sfegan@astro.ucla.edu>.\n\n2006-06-08  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr-fcn.cc (function::do_multi_index_op): Append contents of\n\tvarargout to ret_list before calling convert_to_const_vector.\n\n\t* pt-arg-list.cc (tree_argument_list::convert_to_const_vector):\n\tNo need to handle all_va_args here.\n\n\t* ov-va-args.h, ov-va-args.cc: Delete files.\n\t* Makefile.in (OV_INCLUDES, OV_SRC): Delete from the lists.\n\n\t* ov.cc (install_types): Don't register octave_all_va_args type.\n\t* ov.h, ov.cc (octave_value::octave_value (octave_value::all_va_args)):\n\tDelete.\n\t* ov.h (octave_value::is_all_va_args): Delete.\n\t(octave_value::enum all_va_args): Delete.\n\n\t* pt-pr-code.cc\t(tree_print_code::visit_octave_user_function_header):\n\tPrint \"varargout\" and \"varargin\" instead of \"...\".\n\n\t* pt-misc.h, pt-misc.cc\t(tree_parameter_list::convert_to_const_vector):\n\tArg is now const Cell& instead of tree_va_return_list*.\n\n\t* ov-usr-fcn.h, ov-usr-fcn.cc (octave_user_function::vr_list,\n\toctave_user_function::curr_va_arg_number):\n\tDelete variables and all uses.\n\t(octave_function::octave_va_start, octave_function::octave_va_arg,\n\toctave_function::octave_vr_val,\toctave_function::has_varargout):\n\tDelete functions and all uses.\n\n\t* ov-fcn.h (octave_function::octave_va_start,\n\toctave_function::octave_va_arg, octave_function::octave_vr_val,\n\toctave_function::has_varargout): Delete.\n\n\t* ov-usr-fcn.cc (Fva_arg, Fva_start, Fvr_val): Delete.\n\n\t* lex.l ({EL}): Don't handle \"...\" as varargin or varargout.\n\t* octave.gperf (all_va_args, ALL_VA_ARGS, all_va_args_kw): Delete.\n\t* parse.y (ALL_VA_ARGS): Delete token and all uses.\n\n\t* defaults.h.in (OCTAVE_DATAROOTDIR): Substitute here.\n\t* toplev.cc (octave_config_info): Add datarootdir to the struct.\n\n2006-06-07  John W. Eaton  <jwe@octave.org>\n\n\t* ov-cell.cc (octave_cell::subsasgn): Handle c-s list object on\n\tRHS if last index is '{'.\n\t* pt-assign.cc (tree_multi_assignment::rvalue): Compute all LHS\n\tlvalues before evaluating RHS.  If LHS lvalue expects more than\n\tone output, pass octave_cs_list object to assign method.\n\t* pt-idx.cc (tree_index_expression::lvalue): Compute expected\n\tnumber of values if '{' index appears last.\n\t* pt-arg-list.cc (tree_argument_list::lvalue_list): New function.\n\t* pt-arg-list.h (tree_argument_list::lvalue_list): Provide decl.\n\t* oct-lvalue.h (octave_lvalue::nel): New data member.\n\t(octave_lvalue::numel): New functions\n\t* oct-obj.cc (octave_value_list::has_magic_colon): New function.\n\t* oct-obj.h (octave_value_list::has_magic_colon): Provide decl.\n\t* pt-arg-list.cc (tree_argument_list::nargout_count): Delete function.\n\t* pt-arg-list.h (tree_argument_list::nargout_count): Delete decl.\n\n2006-06-06  John W. Eaton  <jwe@octave.org>\n\n\t* sighandlers.cc (generic_sig_handler, sigint_handler):\n\tUse strsignal instead of accessing sys_siglist directly.\n\t* siglist.h: Use HAVE_DECL_SYS_SIGLIST instead of SYS_SIGLIST_DECLARED.\n\t* siglist.c: Update sys_siglist.\n\t(init_signals, strsignal): New functions.\n\t* octave.cc (octave_main): Call init_signals here.\n\n\t* toplev.cc (Foctave_config_info): Delete LIBPLPLOT from struct.\n\n2006-06-05  John W. Eaton  <jwe@octave.org>\n\n\t* pt-assign.cc (Vprint_rhs_assign_val): Delete variable.\n\t(Fprint_rhs_assign_val): Delete function.\n\ttree_simple_assignment::rvalue, tree_multi_assignment::rvalue):\n\tNo special case for Vprint_rhs_assign_val.\n\n2006-06-02  John W. Eaton  <jwe@octave.org>\n\n\t* pt-arg-list.h (tree_argument_list::mark_as_simple_assign_lhs,\n\ttree_argument_list::is_simple_assign_lhs): New functions.\n\t(tree_argument_list::simple_assign_lhs): New data member.\n\t* parse.y (assign_lhs): Classify LHS here.\n\t(make_assign_op): Create simple or multi assign op based on\n\tclassification of LHS, not its length.\n\n2006-06-01  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DLD_XSRC): Add __pchip_deriv__.cc to the list.\n\n2006-06-01  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/__pchip_deriv__.cc: New file.\n\n2006-05-31  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.h (load_path::set_command_line_path): Make it\n\tadditive.\n\n2006-05-26  John W. Eaton  <jwe@octave.org>\n\n\t* load-path.cc (genpath, maybe_add_path_elts, Fgenpath, Frehash,\n\tFpath, Fpathdef): Move here from defaults.cc.\n\t* load-path.cc, load-path.h: New files.\n\t* Makefile.in (INCLUDES, DIST_SRC): Add them to the lists.\n\t* help.cc (make_name_list, simple_help): Use load_path instead of\n\toctave_fcn_file_name_cache.\n\t(Flookfor): Use load_path instead of Vload_path_dir_path.\n\t* octave.cc (octave_main):  Likewise.\n\t* parse.y (load_fcn_from_file): Likewise.\n\t* utils.cc (Ffile_in_loadpath, file_in_path, fcn_file_in_path,\n\toct_file_in_path): Likewise.\n\t* variables.cc (symbol_exist, symbol_out_of_date): Likewise.\n\t* DLD-FUNCTIONS/fftw_wisdom.cc (Ffftw_wisdom): Likewise.\n\t* utils.cc (Ffind_first_of_in_loadpath): Delete.\n\t* input.cc (octave_gets): Call load_path::update here.\n\t* dirfns.cc (octave_change_to_directory): Likewise.\n\t* defaults.cc (VLOADPATH, VDEFAULT_LOADPATH, Vload_path_dir_path,\n\tmaybe_add_or_del_packages, update_load_path_dir_path,\n\texecute_default_pkg_add_files, set_load_path): Delete.\n\t* defaults.h.in (Vload_path_dir_path,\n\texecute_default_pkg_add_files, maybe_add_default_load_path,\n\tset_load_path): Delete decls.\n\n\t* fn-cache.h, fn-cache.cc: Delete.\n\t* Makefile.in (INCLUDES, DIST_SRC): Remove them from the lists.\n\n\t* input.cc (octave_gets): Only update Vlast_prompt_time if we are\n\tinteractive and actually printing a prompt.  Don't print prompt if\n\treading startup files or command line files.  Initialize\n\tVlast_prompt_time to 0.\n\n\t* pr-output.cc (set_format): Always include space for sign.\n\n2006-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc (Fsave): Use tellp instead of pubseekoff to\n\tdetermine whether we are at beginning of file.\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_SCALAR_T::increment,\n\tOCTAVE_VALUE_INT_SCALAR_T::decrement,\n\tOCTAVE_VALUE_INT_MATRIX_T::increment,\n\tOCTAVE_VALUE_INT_MATRIX_T::decrement): New functions.\n\t* OPERATORS/op-int.h (OCTAVE_INSTALL_M_INT_UNOPS,\n\tOCTAVE_INSTALL_S_INT_UNOPS, OCTAVE_M_INT_UNOPS,\n\tOCTAVE_S_INT_UNOPS): Uncomment increment and decrement ops.\n\n2006-05-19  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (SYMBOL_DEF::document): If definition is a function,\n\talso pass doc string to function object.\n\t* ov-fcn.h (octave_function::document): New function.\n\t* defun.cc (print_usage (octave_function *)): New function.\n\t(print_usage (void)): New function.\n\t(print_usage (const std::string&)): Provide for backward\n\tcompatibility.  Ignore arg.\n\t(Fprint_usage): Don't accept arg.\n\t* defun-int.h (print_usage (void)): Provide decl.\n\t(print_usage (const std::string&)): Tag with GCC_ATTR_DEPRECATED.\n\n2006-05-04  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/conv2.cc: New file from Octave Forge.\n\t* Makefile.in (DLD_XSRC): Add it to the list\n\n2006-05-17  Bill Denney  <bill@givebillmoney.com>\n\n\t* help.cc (keywords): Improve and Texinfoize.\n\n2006-05-17  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (Vwhos_line_format): Show class instead of type.\n\t(symbol_table::parse_whos_line_format):\n\tUse 't' for \"Type\" and 'c' for \"Class\".\n\t(symbol_record::print_symbol_info_line): Likewise.\n\t(maybe_list_cmp_fcn): Fix casts.\n\n2006-05-11  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (IMAGE_PATH_OPTION): New macro.\n\t(usage_string, verbose_usage): Include --image-path option.\n\t(long_opts): Include --image-path.\n\t(octave_main): Handle IMAGE_PATH_OPTION.\n\n\t* toplev.cc (Foctave_config_info): Delete fcnfilepath, imagepath,\n\tlocalfcnfilepath, and localoctfilepath from the struct.\n\t* defaults.h.in (OCTAVE_FCNFILEPATH, OCTAVE_IMAGEPATH,\n\tOCTAVE_LOCALFCNFILEPATH, OCTAVE_LOCALOCTFILEPATH): Delete variables.\n\n\t* octave.cc (octave_main): Call set_exec_path and set_load_path\n\tinstead of bind_internal_variable.\n\n\t* defaults.cc (Fpathdef): Rename from FDEFAULT_LOADPATH.\n\tDon't allow default path to be set.\n\t(Fpath): Rename from FLOADPATH.  Make Matlab-compatible.\n\t(update_load_path_dir_path): No need to pass VDEFAULT_LOADPATH to\n\tdir_path constructor now.\n\t(update_exec_path, FDEFAULT_EXEC_PATH,\n\tset_default_default_exec_path, set_default_exec_path,\n\tmaybe_add_default_load_path): Delete functions.\n\t(VDEFAULT_EXEC_PATH): Delete variable.\n\t(FEXEC_PATH): Leading and trailing colons no longer special.\n\t(set_exec_path, set_load_path, set_image_path,\n\tmaybe_add_path_elts): New functions.\n\t(install_defaults): Call set_exec_path and set_load_path instead\n\tof set_default_exec_path and set_default_path.  Don't call\n\tset_default_default_exec_path.  Do call set_image_path.\n\t* defaults.cc (genpath, Fgenpath): New functions.\n\t(Vlocal_ver_oct_file_dir, Vlocal_api_oct_file_dir,\n\tVlocal_oct_file_dir, Vlocal_ver_fcn_file_dir,\n\tVlocal_api_fcn_file_dir, Vlocal_fcn_file_dir, Vimage_dir):\n\tNew variables.\n\t(set_default_local_ver_oct_file_dir,\n\tset_default_local_api_oct_file_dir,\n\tset_default_local_oct_file_dir,\n\tset_default_local_ver_fcn_file_dir,\n\tset_default_local_api_fcn_file_dir,\n\tset_default_local_fcn_file_dir, set_default_image_dir):\n\tNew functions.\n\t(install_defaults): Call them.\n\t* defaults.h.in (set_exec_path, set_load_path, set_image_path,\n\tVlocal_ver_oct_file_dir, Vlocal_api_oct_file_dir,\n\tVlocal_oct_file_dir, Vlocal_ver_fcn_file_dir,\n\tVlocal_api_fcn_file_dir, Vlocal_fcn_file_dir,\n\tVlocal_fcn_file_dir, Vimage_dir): Provide decls.\n\n2006-05-10  John W. Eaton  <jwe@octave.org>\n\n\t* ov-cell.cc (Fcellstr): Trim trailing blanks.\n\t* Cell.h (Cell::Cell (const string_vector&)): New arg, TRIM.\n\n\t* oct-hist.cc (initialize_history, Fhistory_size):\n\tAlso call command_history::set_size here.\n\n\t* defun.cc (Fprint_usage): New function.\n\t* help.cc (display_usage_text): New function.\n\n2006-05-09  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* DLD-FUNCTIONS/rand.cc: Doc string fix.\n\n2006-05-09  Jorge Barros de Abreu  <ficmatin01@solar.com.br>\n\n\t* data.cc (FInf, FNaN): Fix typo in doc string.\n\n2006-05-08  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DEFUN_PATTERN): Match DEFUNX_DLD.\n\t* mkbuiltins: Handle XDEFUNX_DLD_INTERNAL.\n\t* mkgendoc: Likewise.\n\t* mk-pkg-add: Likewise.  Do all the matching with sed.\n\t* defun-int.h \t(DEFINE_FUNX_INSTALLER_FUN, DEFINE_FUNX_INSTALLER_FUN2,\n\tDEFINE_FUNX_INSTALLER_FUN3): New macros.\n\t(DEFINE_FUN_INSTALLER_FUN3): Define using DEFINE_FUNX_INSTALLER_FUN3.\n\t(DEFUNX_DLD_INTERNAL): New macro.\n\t* defun-dld.h (DEFUNX_DLD): New macro.\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l: Mark __gnuplot_set__ as a\n\tcommand, not a rawcommand.\n\n\t* load-save.cc: No need to handle built-in variables.\n\t* help.cc (simple_help): No need to handle built-in variables.\n\n\t* variables.cc (is_builtin_variable, builtin_string_variable,\n\tbuiltin_real_scalar_variable, builtin_any_variable):\n\tDelete functions.\n\t(Fexist, Fdocument, do_who, Fwho, link_to_builtin_or_function):\n\tNo need to handle built-in variables.\n\t* variables.h (is_builtin_variable, builtin_string_variable,\n\tbuiltin_real_scalar_variable, builtin_any_variable): Delete decls.\n\n\t* symtab.h (symbol_record::symbol_def::is_builtin_variable,\n\tsymbol_record::is_builtin_variable): Delete.\n\t(symbol_record::TYPE): Remove BUILTIN_VARIABLE from enum.\n\t(symbol_record::symbol_def::is_variable, SYMTAB_ALL_TYPES,\n\tSYMTAB_VARIABLES): No need to handle built-in variables now.\n\t(symbol_record::define_builtin_variable,\n\tsymbol_record::link_to_builtin_variable): Delete decls.\n\t* symtab.cc (record::define, SYMBOL_DEF::type,\n\tSYMBOL_DEF::type_as_string): No need to handle built-in variables.\n\t(symbol_record::define_builtin_variable): Delete.\n\t(symbol_record::variable_reference): No need to attemp to link to\n\tbuilt-in variable.\n\n\t* utils.cc (check_preference, warn_old_style_preference): Delete.\n\t* utils.h (check_preference): Delete decl.\n\n\t* defun-int.h: Delete all DEFVAR macros.\n\n\t* Makefile.in, mkbuiltins: No need for VAR_FILES.\n\n\t* parse.y (current_script_file_name): Delete all uses.\n\t(clear_current_script_file_name): Delete function.\n\n\t* variables.cc (symbols_of_variables): Delete DEFVAR and function.\n\t(bind_ans): Lookup ans in curr_sym_tab, not fbi_sym_tab.\n\tSR is no longer static, so we insert value in local scope.\n\n\t* defun.cc (bind_builtin_variable): Delete function.\n\t* defun-int.h: Delete decl.\n\n\t* defaults.cc (fftw_wisdom_program): Rename from fftw_wisdom_prog.\n\tChange all uses.\n\t(VDEFAULT_LOADPATH): Rename from Vdefault_load_path.  Change all uses.\n\t(VLOADPATH): Rename from Vload_path.  Change all uses.\n\t(VDEFAULT_EXECPATH): Rename from Vdefault_exec_path.  Change all uses.\n\t(VEXECPATH): Rename from Vexec_path.  Change all uses.\n\t(VEDITOR): Rename from Veditor.  Change all uses.\n\t(Ffftw_wisdom_program, FDEFAULT_LOADPATH, FLOADPATH,\n\tFDEFAULT_EXEC_PATH, FEXEC_PATH, FEDITOR, FIMAGEPATH): New functions.\n\t(fftw_wisdom_program, default_load_path, loadpath,\n\tdefault_exec_path, exec_path, editor, image_path): Delete functions.\n\t(symbols_of_defaults): Delete DEFVARs and function.\n\n\t* pr-output.cc (set_output_prec_and_fw): Set Voutput_precision and\n\tVoutput_max_field_width directly instead of calling\n\tbind_builtin_variable.\n\n\t* octave.cc (octave_main, maximum_braindamage):\n\tCall bind_internal_variable instead of bind_builtin_variable.\n\n\t* pager.cc (Fmore): Set Vpage_screen_output directly instead of\n\tcalling bind_builtin_variable.\n\n\t* error.cc (Fwarning): Set Vdebug_on_warning directly instead of\n\tcalling bind_builtin_variable.\n\n\t* error.cc (initialize_warning_options): Now static.\n\t(disable_warning, initialize_default_warning_state): New functions.\n\n\t* error.h (initialize_warning_options): Delete decl.\n\t(initialize_default_warning_state): Provide decl.\n\t* octave.cc (octave_main): Call initialize_default_warning_state\n\tinstead initialize_warning_options.\n\n\t* lex.l (warn_matlab_incompatible, warn_separator_insert,\n\twarn_single_quote_string): Delete functions.\n\t(symbols_of_lex): Delete DEFVARS.\n\t(Vwarn_matlab_incompatible, Vwarn_separator_insert,\n\tVwarn_single_quote_string): Delete variables.\n\t(maybe_warn_separator_insert, gripe_single_quote_string,\n\tgripe_matlab_incompatible): Call warning_with_id instead of warning.\n\n\t* variables.h (SET_NONEMPTY_INTERNAL_STRING_VARIABLE,\n\tSET_INTERNAL_VARIABLE_WITH_LIMITS): New macros.\n\n\t* ls-oct-ascii.cc (Fsave_precision): New function.\n\t(save_precision): Delete function.\n\t(symbols_of_ls_oct_ascii): Delete DEFVAR and function.\n\n\t* oct-hist.cc (initialize_history): New function.\n\t* oct-hist.h: Provide decl.\n\t* octave.cc (octave_main): Call initialize_history instead of\n\tcommand_history::read.\n\n\t* oct-hist.cc (Fhistory_size, Fhistory_file,\n\tFhistory_timestamp_format_string, Fsaving_history): New functions.\n\t(history_size, history_file, history_timestamp_format_string,\n\tsaving_history): Delete functions.\n\t(symbols_of_oct_hist): Delete DEFVARs and function.\n\n\t* pt-mat.cc (Fstring_fill_char): New function.\n\t(string_fill_char): Delete function.\n\t(symbols_of_pt_mat): Delete DEFVAR and function.\n\n\t* variables.cc (Fignore_function_time_stamp, ans): New functions.\n\t(ignore_function_time_stamp): Delete function.\n\t(symbols_of_variables): Delete DEFVARs and function.\n\n\t* oct-procbuf.cc: (Vkluge_procbuf_delay): Delete variable.\n\t(octave_procbuf::open): Never delay after fork.\n\t(kluge_procbuf_delay): Delete function.\n\t(symbols_of_oct_procbuf): Delete DEFVAR and function.\n\n\t* dirfns.cc (Fconfirm_recursive_rmdir): New function.\n\t(confirm_recursive_rmdir): Delete function.\n\t(symbols_of_dirfns): Delete DEFVAR and function.\n\n\t* error.cc (initialize_warning_options): Now extern.\n\tRename from init_warning_options.\n\t* error.h: Provide decl.\n\t* octave.cc (octave_main): Call it here.\n\n\t* error.cc (Fbeep_on_error, Fdebug_on_error, Fdebug_on_warning):\n\tNew functions.\n\t(beep_on_error, debug_on_error, debug_on_warning): Delete Functions.\n\t(symbols_of_error): Delete DEFVARs and function.\n\n\t* help.cc (Finfo_file, Finfo_program, Fmakeinfo_program,\n\tFsuppress_verbose_help_message): New function.\n\t(info_file, info_program, makeinfo_program,\n\tsuppress_verbose_help_message): Delete function.\n\t(symbols_of_help): Delete DEFVARs and function.\n\t(Vinfo_program): Rename from Vinfo_prog.  Change all uses.\n\n\t* input.cc (FPS1, FPS2, FPS4, Fcompletion_append_char,\n\tFecho_executing_commands): New functions.\n\t(ps1, ps2, ps4, completion_append_char, echo_executing_commands):\n\tDelete functions.\n\t(symbols_of_input): Delete DEFVARs and function.\n\t(VPS1, VPS2, VPS4): Rename from Vps1, Vps2, Vps4.  Change all uses.\n\t(Fecho): Set Vecho_executing_commands directly.\n\n\t* load-save.cc (crash_dumps_octave_core, Fdefault_save_options,\n\tFoctave_core_file_limit, Foctave_core_file_name,\n\tFoctave_core_file_options, Fsave_header_format_string):\n\tNew functions.\n\t(crash_dumps_octave_core, default_save_options,\n\toctave_core_file_limit, octave_core_file_name,\n\toctave_core_file_options, save_header_format_string):\n\tDelete functions.\n\t(symbols_of_load_save): Delete DEFVARs and function.\n\n\t* ov-base.cc (Fprint_answer_id_name, Fsilent_functions): New functions.\n\t(print_answer_id_name, silent_functions): Delete functions.\n\t(symbols_of_ov_base): Delete DEFVARs and function.\n\n\t* ov-usr-fcn.cc (Fmax_recursion_depth): New function.\n\t(max_recursion_depth): Delete function.\n\t(symbols_of_ov_usr_fcn): Delete DEFVAR for max_recursion_depth.\n\tDelete function.\n\n\t* pager.cc (Fpage_output_immediately, Fpage_screen_output, FPAGER):\n\tNew functions.\n\t(page_output_immediately, page_screen_output, pager_binary):\n\tDelete functions.\n\t(symbols_of_pager): Delete DEFVARs and function.\n\t(VPAGER): Rename from Vpager_binary.  Change all uses.\n\n\t* pr-output.cc (Ffixed_point_format, Fprint_empty_dimensions,\n\tFsplit_long_rows, Foutput_max_field_width, Foutput_precision,\n\tFstruct_levels_to_print): New functions.\n\t(fixed_point_format, print_empty_dimensions, split_long_rows,\n\toutput_max_field_width, output_precision, struct_levels_to_print):\n\tDelete functions.\n\t(symbols_of_pr_output): Delete DEFVARs and function.\n\n\t* pt-assign.cc (Fprint_rhs_assign_val): New function.\n\t(print_rhs_assign_val): Delete function.\n\t(symbols_of_pt_assign): Delete DEFVAR.  Delete function.\n\n\t* sighandlers.cc (Fdebug_on_interrupt, Fsighup_dumps_octave_core,\n\tFsigterm_dumps_octave_core): New functions.\n\t(debug_on_interrupt, sighup_dumps_octave_core,\n\tsigterm_dumps_octave_core): Delete functions.\n\t(symbols_of_sighanlders): Delete DEFVARs.  Delete function.\n\n\t* symtab.cc (Vdebug_symtab_lookups): Now bool.\n\t(Fdebug_symtab_lookups, Fwhos_line_format,\n\tFvariables_can_hide_functions): New functions.\n\t(debug_symtab_lookups, whos_line_format,\n\tvariables_can_hide_functions): Delete functions.\n\t(symbols_of_symtab): Delete DEFVARs and function.\n\n2006-05-04  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/sqqr (Fdmperm): Allow compilation with versions\n\tv2.0.0 of CXSparse or later.\n\n2006-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (set_internal_variable): Move here from\n\tDLD-FUNCTIONS/__gnuplot_raw__.l.\n\t* variables.h (SET_INTERNAL_VARIABLE): Likewise.\n\t(set_internal_variable): Provide decls.\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l: Convert all DEFVARs to DEFUN_DLDs.\n\t(gnuplot::init): Delete.\n\t(gnuplot::gnuplot): Don't call init here.\n\t(set_internal_variable): New functions.\n\t(SET_INTERNAL_VARIABLE): New macro.\n\n\t* Makefile.in: Undo changes of 2006-03-16.\n\t* DLD-FUNCTINS/__gnuplot_raw__.l: Move here from __gnuplot_raw__.l.\n\tUndo changes of 2006-03-16.\n\n2006-05-03  David Bateman  <dbateman@free.fr>\n\n\t* ov-base-mat.h: Add caching of matrix type, and code to supply\n\tand copy matrix type.\n\t* ov-bool-mat.h: Add caching to constructor.\n\t* ov-re-mat.h: ditto.\n\t* ov-cx-mat.h: ditto.\n\t* ov.cc: Add to the BoolMatrix, Matrix and the ComplexMatrix\n\toctave_value constructors, the ability to specify the matrix type.\n\t* ov.h: Adapt declaration of above constructors.\n\t(MatrixType matrix_type(void) const, MatrixType matrix_type (const\n\tMatrixType&)): New functions for probing and setting matrix type.\n\t* ov-base.cc (virtual MatrixType matrix_type(void) const, virtual\n\tMatrixType matrix_type (const MatrixType&)): New default functions\n\tfor probing and setting matrix type.\n\t* ov-base.h  (virtual MatrixType matrix_type(void) const, virtual\n\tMatrixType matrix_type (const MatrixType&)): Declarations.\n\t* ov-base-sparse.h: Replace all uses of SparseType with\n\tMatrixType. Replace sparse_type function with matrix_type function.\n\t* ov-bool-sparse.h: Replace all uses of SparseType with MatrixType.\n\t* ov-cx-sparse.h: ditto.\n\t* ov-re-sparse.h: ditto.\n\t* sparse-xdiv.cc: ditto.\n\t* sparse-xdiv.h: ditto.\n\t* sparse-xpow.cc: ditto.\n\t* DLD-FUNCTIONS/luinc.cc: ditto.\n\t* DLD-FUNCTIONS/splu.cc: ditto.\n\t* xdiv.cc (xdiv, xleftdiv): Pass the matrix type, simplfy since\n\tthe matrix solve function now calls lssolve if singular.\n\t* xdiv.h (xdvi, xleftdiv): Update the declarations\n\t* OPERATORS/op-cm-cm.cc, OPERATORS/op-cm-cs.cc,\n\tOPERATORS/op-cm-m.cc, OPERATORS/op-cm-s.cc,\n\tOPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc,\n\tOPERATORS/op-cs-cm.cc, OPERATORS/op-cs-m.cc,\n\tOPERATORS/op-m-cm.cc, OPERATORS/op-m-cs.cc,\n\tOPERATORS/op-m-m.cc, OPERATORS/op-m-s.cc,\n\tOPERATORS/op-m-scm.cc, OPERATORS/op-m-sm.cc,\n\tOPERATORS/op-s-cm.cc, OPERATORS/op-s-m.cc,\n\tOPERATORS/op-scm-cm.cc, OPERATORS/op-scm-m.cc,\n\tOPERATORS/op-sm-cm.cc, OPERATORS/op-sm-m.cc: Update use of\n\txdiv and xleftdiv functions to allow matrix type caching.\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): Update to allow typing\n\t of Matrix, and ComplexMatrix types. Add new test code for this.\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fmat2cell): new function.\n\n\t* DLD-FUNCTIONS/regexp.cc (class regexp_elem): New class to store\n\tmatched element in a std::list.\n\t(octregexp_list): Take algorithm from octregexp and construct a\n\tlist of matches.\n\t(octregexp): Rewrite to use linked list of matches.\n\t(Fregexprep): New function, working directly in linked list of\n\tmatches.\n\n2006-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l ({CCHAR}): Exit rawcommand mode if returning '\\n' token.\n\n2006-05-02  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/rand.cc (do_rand): Require real scalar for seed.\n\n2006-05-01  John W. Eaton  <jwe@octave.org>\n\n\t* error.h (Vwarning_option): Delete.\n\t* variables.cc (looks_like_struct): Remove use from commented code.\n\n\t* gripes.cc, gripes.h (gripe_implicit_conversion): New arg, ID.\n\tChange all uses.\n\n\t* defaults.cc (set_local_site_defaults_file, set_site_defaults_file):\n\tAllow filenames to be set from the environment.\n\n\t* oct-map.cc (octave_map::resize): No longer const.\n\t* ov-struct.h (octave_struct::resize): Deal with it.\n\n\t* octave.cc (initialize_error_handlers): Also call\n\tset_liboctave_warning_with_id_handler.\n\t(execute_startup_files): Check that home_rc is not an empty string.\n\t(F__version_info__): Resize vinfo before assigining elements.\n\n\t* ov-base.cc (warn_num_to_str, warn_resize_on_range_error):\n\tDelete functions.\n\t(symbols_of_ov_base): Delete DEFVARS.\n\t(Vwarn_num_to_str, Vwarn_resize_on_range_error): Delete variables.\n\t(value::convert_to_str): Check state of warning ID\n\tOctave:num-to-str instead of using Vwarn_num_to_str.\n\t* OPERATORS/op-chm.cc: Likewise.\n\t* ov-base.h (Vwarn_num_to_str, Vwarn_resize_on_range_error):\n\tDelete decls.\n\n\t* ov-list.cc (octave_list::assign): Call warning_with_id instead\n\tof warning.\n\n\t* parse.y (warn_assign_as_truth_value, warn_associativity_change,\n\twarn_function_name_clash, warn_future_time_stamp,\n\twarn_missing_semicolon, warn_precedence_change,\n\twarn_variable_switch_label, symbols_of_parse):\n\tDelete DEFVARs and functions.\n\t(Vwarn_assign_as_truth_value, Vwarn_associativity_change,\n\tVwarn_function_name_clash, Vwarn_future_time_stamp,\n\tVwarn_missing_semicolon, Vwarn_precedence_change,\n\tVwarn_variable_switch_label): Delete variables.\n\t* parse.h (Vwarn_future_time_stamp): Delete decl.\n\t* parse.y (fold): Check state of warning ID\n\tOctave:associativity-change and Octave:precedence-change instead\n\tof using Vwarn_associativity_change and Vwarn_precedence_change.\n\t(maybe_warn_associativity_change, maybe_warn_missing_semi,\n\tmaybe_warn_assign_as_truth_value, make_binary_op, make_boolean_op,\n\tfrob_function): Call warning_with_id instead of warning.\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load): Likewise.\n\n\t* ov.cc (warn_fortran_indexing, warn_imag_to_real, symbols_of_ov):\n\tDelete DEFVARs and functions.\n\t(Vwarn_fortran_indexing, Vwarn_imag_to_real): Delete variables.\n\n\t* ov.cc (octave_value::vector_value, octave_value::int_vector_value,\n\toctave_value::complex_vector_value): Check state of warning ID\n\tOctave:fortran-indexing instead of using Vwarn_fortran_indexing.\n\t* ov-cx-sparse.cc (octave_sparse_complex_matrix::double_value,\n\toctave_sparse_complex_matrix::complex_value): Likewise.\n\t* ov-cx-mat.cc (octave_complex_matrix::matrix_value,\n\toctave_complex_matrix::complex_value): Likewise.\n\t* ov-re-mat.cc (octave_matrix::complex_value,\n\toctave_matrix::double_value): Likewise.\n\t* ov-streamoff.cc (octave_streamoff::streamoff_value): Likewise.\n\t* ov-re-sparse.cc (octave_sparse_matrix::complex_value,\n\toctave_sparse_matrix::double_value): Likewise.\n\t* ov-range.cc (octave_range::complex_value,\n\toctave_range::double_value): Likewise.\n\t* ov-ch-mat.cc (octave_char_matrix::complex_value,\n\toctave_char_matrix::double_value): Likewise.\n\t* ov-bool-sparse.cc (octave_sparse_bool_matrix::complex_value,\n\toctave_sparse_bool_matrix::double_value): Likewise.\n\t* ov-bool-mat.cc (octave_bool_matrix::complex_value,\n\toctave_bool_matrix::double_value): Likewise.\n\n\t* ov-cx-sparse.cc (octave_sparse_complex_matrix::double_value,\n\toctave_sparse_complex_matrix::matrix_value,\n\toctave_sparse_complex_matrix::sparse_matrix_value): Check state of\n\twarning ID Octave:imag-to-real instead of using Vwarn_imag_to_real.\n\t* ov-cx-mat.cc (octave_complex_matrix::double_value,\n\toctave_complex_matrix::matrix_value,\n\toctave_complex_matrix::complex_value,\n\toctave_complex_matrix::sparse_matrix_value): Likewise.\n\t* ov-complex.cc (octave_complex::double_value,\n\toctave_complex::matrix_value, octave_complex::array_value): Likewise.\n\n\t* ov.h (Vwarn_fortran_indexing, Vwarn_imag_to_real): Delete decls.\n\n\t* pt-mat.cc (warn_empty_list_elements, warn_string_concat):\n\tDelete functions.\n\t(symbols_of_pt_mat): Delete DEFVARs.\n\t(Vwarn_empty_list_elements, Vwarn_string_concat): Delete variables.\n\t(tm_row_const::tm_row_const_rep::eval_warning, tm_const::init,\n\tmaybe_warn_string_concat): Call warning_with_id instead of warning.\n\n\t* ov-str-mat.cc (warn_str_to_num, symbols_of_ov_str_mat):\n\tDelete DEFVAR and functions.\n\t(Vwarn_str_to_num): Delete variable.\n\t(CHAR_MATRIX_CONV): Call warning_with_id instead of warning.\n\n\t* utils.cc (warn_neg_dim_as_zero, symbols_of_utils):\n\tDelete DEFVAR and functions.\n\t(Vwarn_neg_dim_as_zero): Delete variable.\n\t(check_dimensions): Call warning_with_id instead of warning.\n\n\t* pt-misc.cc (warn_undefined_return_values, symbols_of_pt_misc):\n\tDelete DEFVAR and functions.\n\t(Vwarn_undefined_return_values): Delete variable.\n\t(tree_parameter_list::initialize_undefined_elements):\n\tCall warning_with_id instead of warning.\n\n\t* dynamic-ld.cc\t(warn_reload_forces_clear, symbols_of_dynamic_ld):\n\tDelete DEFVAR and functions.\n\t(Vwarn_reload_forces_clear): Delete variable.\n\t(do_clear_function, octave_dynamic_loader::do_load):\n\tCall warning_with_id instead of warning.\n\t* error.cc (warning_enabled): Now extern.\n\t(Fwarning): If specific id is not found, return state of \"all\".\n\n\t* error.h: Provide decl.\n\n\t* gripes.cc (warn_divide_by_zero, symbols_of_gripes):\n\tDelete DEFVAR and functions.\n\t(gripe_divide_by_zero): Check whether warning is enabled, then\n\tcall warning_with_id instead of warning.\n\t(Vwarn_divide_by_zero): Delete variable.\n\n2006-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (Fexist): Fix doc string.\n\n\t* help.cc (simple_help): No need to handle built-in constants now.\n\t* variables.cc (do_who): Likewise.\n\t(symbol_exist): Likewise.\n\t(link_to_builtin_or_function): Likewise.\n\t* symtab.cc (SYMBOL_DEF::type_as_string): Likewise.\n\t(record::read_only_error): Likewise.\n\t(SYMBOL_DEF::type): Likewise.\n\t(record::variable_reference): Likewise.\n\t(symbol_record::define_builtin_const): Delete function.\n\n\t* symtab.h (symbol_record::define_builtin_const): Delete decl.\n\t(symbol_record::symbol_def::is_constant): Delete function.\n\t(symbol_record::symbol_def::is_builtin_constant): Delete function.\n\t(symbol_record::symbol_def::is_constant): Delete function.\n\t(symbol_record::is_builtin_constant): Delete function.\n\t(SYMTAB_ALL_TYPES): No need to handle builtin-constants now.\n\t(symbol_record::TYPE): Remove BUILTIN_CONSTANT from enum.\n\n\t* defun.cc (install_builtin_constant): Delete function.\n\t* defun-int.h (install_builtin_constant): Delete decl.\n\n\t* variables.cc (bind_builtin_constant): Delete function.\n\t* variables.h (bind_builtin_constant): Delete decl.\n\n\t* defun-int.h (DEFCONST, DEFCONSTX, DEFCONST_INTERNAL,\n\tDEFCONSTX_INTERNAL): Delete definitions.\n\n\t* sighandlers.cc (FSIG): New function to replace DEFCONST in\n\tsymbols_of_sighandlers.\n\n\t* octave.cc (intern_argv): Set octave_argv instead of calling\n\tbind_builtin_variable here.\n\t(Fargv, Fprogram_invocation_name, Fprogram_name): New functions to\n\treplace DEFCONSTs in symbols_of_toplvev in toplev.cc.\n\t(octave_program_invocation_name, octave_program_name):\n\tNew static variables.\n\t(execute_command_line_file): Use unwind_protect_str to protect\n\toctave_program_invocation_name, octave_program_name instead of\n\tusing a restore function.\n\t(restore_program_name): Delete.\n\n\t* defaults.cc (FOCTAVE_HOME): New function to replace DEFCONST in\n\tsymbols_of_defaults.\n\n2006-04-27  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp): Fix for infinite loop in\n\tregexp. Include news regexp arguments, and associated tests.\n\n2006-04-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc: Also instantiate do_read functions for boolNDArray.\n\n2006-04-26  Bill Denney  <denney@seas.upenn.edu>\n\n \t* pager.cc (Fterminal_size): Add list_in_columns to @seealso.\n\n2006-04-26  John W. Eaton  <jwe@octave.org>\n\n\t* dirfns.cc (Ffilesep): New function to replace DEFCONST in\n\tsymbols_of_dirfns.\n\t(Fpathsep): New function.\n\n\t* defaults.cc (set_default_default_exec_path): Use\n\tdir_path::path_sep_str instead of std::string (SEPCHAR_STR).\n\t(set_default_exec_path): Likewise.\n\t(set_default_path): Likewise.\n\t(maybe_add_default_load_path): Likewise.  Use dir_path::is_path_sep.\n\n2006-04-18  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/regexp.cc: Include <algorithm>, for transform decl.\n\n\t* DLD-FUNCTIONS/ccolamd.cc (Fccolamd, Fcsymamd):\n\tAlways return something.\n\n\t* sighandlers.cc (octave_set_signal_handler,\n\toctave_set_interrupt_handler): New arg, restart_syscalls, with\n\tdefault value true.\n\t* sighandlers.h: Fix decls to match.\n\t* sysdep.cc (octave_kbhit): Disable restarting of system calls.\n\n\t* help.cc (Flookfor): Add std qualifier to transform function.\n\tInclude <algorithm>, for transform decl.\n\n2006-04-16  John W. Eaton  <jwe@octave.org>\n\n\t* pager.h (octave_diary_buf, octave_pager_buf): Use std:stringbuf\n\tdirectly.\n\n\t* ls-mat-ascii.cc (read_mat_ascii_data): Use std::istringstream\n\tdirectly.\n\t* load-save.cc (parse_save_options): Likewise.\n\t* ls-mat5.cc (read_mat5_binary_element): Likewise.\n\t* oct-strstrm.h (octave_istrstream::is): Likewise.\n\n\t* __gnuplot_raw__.l (printrange, handle_using, gnuplot::do_open,\n\tgnuplot::do_set, gnuplot::do_show, gnuplot::makeplot,\n\tgnuplot::handle_title): Use std::ostringstream directly.\n\t* toplev.cc (run_command_and_return_output): Likewise.\n\t* symtab.h (symbol_table::symbol_table): Likewise.\n\t* strfns.cc (Flist_in_columns): Likewise.\n\t* pt.cc (tree::str_print_code): Likewise.\n\t* parse.y (yyerror, fold, finish_matrix): Likewise.\n\t* pr-output.cc (PRINT_ND_ARRAY, octave_print_internal, Fdisp):\n\tLikewise.\n\t* symtab.cc (symbol_table::print_descriptor): Likewise.\n\t* ov-list.cc (octave_list::print_raw, octave_list::save_ascii,\n\toctave_list::save_binary, octave_list::save_hdf5): Likewise.\n\t* ov-fcn-inline.cc (octave_fcn_inline::octave_fcn_inline,\n\toctave_fcn_inline::load_ascii, octave_fcn_inline::print_raw,\n\tFinline): Likewise.\n\t* ov-fcn-handle.cc (octave_fcn_handle::load_ascii,\n\toctave_fcn_handle::save_binary, octave_fcn_handle::save_hdf5):\n\tLikewise.\n\t* ov-cs-list.cc (octave_cs_list::print_raw): Likewise.\n\t* ov-cell.cc (octave_cell::print_raw, octave_cell::save_hdf5):\n\tLikewise.\n\t* oct-strstrm.h (octave_ostrstream::os, octave_ostrstream::str):\n\tLikewise.\n\t* oct-stream.h (scanf_format_list::buf, printf_format_list::buf):\n\tLikewise.\n\t* oct-stream.cc (scanf_format_list::scanf_format_list,\n\tprintf_format_list::printf_format_list,\n\toctave_base_stream::do_gets, BEGIN_CHAR_CLASS_CONVERSION,\n\toctave_stream_list::do_list_open_files): Likewise.\n\t* ls-oct-ascii.h (extract_keyword): Likewise.\n\t* load-save.cc (do_load): Likewise.\n\t* lex.l (have_continuation, handle_string): Likewise.\n\t* input.cc (get_user_input): Likewise.\n\t* dirfns.cc (Fls): Likewise.\n\t* error.cc (error_message_buffer, vwarning, verror, pr_where):\n\tLikewise.\n\t* defun.cc (print_usage): Likewise.\n\t* help.cc (display_help_text, Ftype, first_help_sentence):\n\tLikewise.\n\t* ls-mat5.cc (save_mat5_binary_element): Likewise.\n\t* DLD-FUNCTIONS/regexp.cc (octregexp): Likewise.\n\t* DLD-FUNCTIONS/fftw_wisdom.cc (Ffftw_wisdom): Likewise.\n\n2006-04-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (lex.o parse.o __gnuplot_raw__.o, pic/parse.o\n\tpic/__gnuplot_raw__.o):\tOmit -Wold-style-cast from CXXFLAGS.\n\n\t* ls-mat5.cc (READ_INTEGER_DATA): Allocate local buffer to avoid\n\tpointer tricks.\n\n\t* DLD-FUNCTIONS/regexp.cc (octregexp): Use OCTAVE_LOCAL_BUFFER\n\tinstead of allocting memory with malloc.\n\n\t* DLD-FUNCTIONS/sparse.cc (Fsparse): Use octave_value extractors\n\tinstead of using get_rep.\n\n\t* DLD-FUNCTIONS/dispatch.cc (dispatch_record): Use dynamic_cast,\n\tnot reinterpret_cast.\n\n\t* DLD-FUNCTIONS/besselj.cc (Fairy): Use int_value instead of\n\tdouble_value and cast to extract kind arg.\n\t(int_arrayN_to_array): Arg is ArrayN<octave_idx_type>, not ArrayN<int>.\n\n\t* OPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc,\n\tOPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc,\n\tOPERATORS/op-m-scm.cc, OPERATORS/op-m-sm.cc,\n\tOPERATORS/op-s-scm.cc, OPERATORS/op-s-sm.cc,\n\tOPERATORS/op-scm-cm.cc, OPERATORS/op-scm-cs.cc,\n\tOPERATORS/op-scm-m.cc, OPERATORS/op-scm-s.cc,\n\tOPERATORS/op-scm-scm.cc, OPERATORS/op-scm-sm.cc,\n\tOPERATORS/op-sm-cm.cc, OPERATORS/op-sm-cs.cc,\n\tOPERATORS/op-sm-m.cc, OPERATORS/op-sm-s.cc,\n\tOPERATORS/op-sm-scm.cc, OPERATORS/op-sm-sm.cc: No need to cast\n\taway const just to cache sparse type.\n\t* ov-base-sparse.h (octave_base_sparse::typ): Now mutable.\n\t(octave_base_sparse::sparse_type): Now const.\n\n\t* OPERATORS/op-cm-scm.cc (DEFBINOP(div)): Explicitly cast args\n\there instead of using CAST_BINOP_ARGS.\n\n\t* OPERATORS/op-streamoff.cc (STREAMOFF_COMP_OP): Second arg to\n\tCAST_BINOP_ARGS is also const.\n\n\t* DLD-FUNCTIONS/chol.cc (Fcholinv, Fchol2inv): Eliminate nargout\n\targ to avoid unused variable warnings.\n\n\t* unwind-prot.h, unwind-prot.cc (unwind_protect::save_bool,\n\tunwind_protect::save_int, unwind_protect::save_str,\n\tunwind_protect::save_ptr, unwind_protect::save_var):\n\tPointer args now const.\n\t(unwind_protect_const_ptr): New macro.\n\n\t* symtab.cc (maybe_list_cmp_fcn): Use static_cast instead of X_CAST.\n\t* variables.cc (symbol_record_name_compare): Likewise.\n\t* ls-mat5.cc (MAT5_DO_WRITE, save_mat5_binary_element): Likewise.\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::save_hdf5,\n\toctave_fcn_handle::load_hdf5): Eliminate unnecessary casts.\n\t* ov-fcn-inline.cc (octave_fcn_inline::save_hdf5,\n\toctave_fcn_inline::load_hdf5): Likewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::save_hdf5,\n\toctave_char_matrix_str::load_hdf5): Likewise.\n\t* ov-bool-sparse.cc (octave_sparse_bool_matrix::save_hdf5,\n\toctave_sparse_bool_matrix::load_hdf5): Likewise.\n\t* ov-cx-sparse.cc (octave_sparse_complex_matrix::save_hdf5,\n\toctave_sparse_complex_matrix::load_hdf5): Likewise.\n\t* ov-re-sparse.cc (octave_sparse_matrix::save_hdf5,\n\toctave_sparse_matrix::load_hdf5): Likewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::save_ascii,\n\toctave_char_matrix_str::load_ascii): Likewise.\n\t* mappers.cc (xtoascii): Likewise.\n\t* load-save.cc (read_binary_file_header, write_header): Likewise.\n\t* parse.y (get_help_from_file, parse_fcn_file): Likewise.\n\t* DLD-FUNCTIONS/rand.cc (do_rand): Likewise.\n\t* ls-hdf5.cc (read_hdf5_data, hdf5_add_attr, save_hdf5_empty,\n\tload_hdf5_empty add_hdf5_data): Likewise.\n\t* ls-mat4.cc (read_mat_binary_data): Likewise.\n\t* ls-mat5.cc (read_mat5_binary_element): Likewise.\n\n\t* oct-stream.cc (expand_char_class, octave_base_stream::do_gets):\n\tUse static_cast instead of C-style cast.\n\t* oct-procbuf.cc (kluge_procbuf_delay): Likewise.\n\t* parse.y (gobble_leading_white_space,: Likewise.\n\t* DLD-FUNCTIONS/besselj.cc (int_array2_to_matrix,\n\tint_arrayN_to_array): Likewise.\n\t* DLD-FUNCTIONS/colamd.cc (Fcolamd, Fsymamd): Likewise.\n\t* DLD-FUNCTIONS/ccolamd.cc (Fcsymamd): Likewise.\n\t* pt-pr-code.cc (tree_print_code::print_comment_elt): Likewise.\n\t* DLD-FUNCTIONS/besselj.cc (do_bessel): Likewise.\n\t* DLD-FUNCTIONS/spchol.cc (Fsymfact): Likewise.\n\t* DLD-FUNCTIONS/sparse.cc (sparse_find): Likewise.\n\t* DLD-FUNCTIONS/sort.cc (FloatFlip): Likewise.\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): Likewise.\n\t* ls-mat5.cc (read_mat5_binary_element, OCTAVE_MAT5_INTEGER_READ,\n\tread_mat5_binary_element, save_mat5_binary_element): Likewise.\n\n\t* DLD-FUNCTIONS/splu.cc (Fspinv): Use dynamic_cast instead of\n\tC-style cast.\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): Likewise.\n\n\t* DLD-FUNCTIONS/sort.cc (mx_sort): Use reinterpret_cast instead of\n\tC-style cast.\n\t* ls-mat5.cc (write_mat5_tag): Likewise.\n\n\t* ov-typeinfo.h (octave_value_typeinfo::octave_value_typeinfo):\n\tEliminate unnecessary casts in constructor initializers.\n\n\t* ops.h (CAST_CONV_ARG, CAST_UNOP_ARG, CAST_BINOP_ARGS,\n\tDEFASSIGNANYOP_FN): Use C++ dynamic_cast instead of DYNAMIC_CAST macro.\n\n\t* unwind-prot.h (unwind_protect_ptr): Use combination of\n\treinterpret_cast and const_cast instead of X_CAST.\n\n\t* dynamic-ld.cc (loader::do_load): Use reinterpret_cast instead of\n\tX_CAST.\n\t* ov-base-int.cc (octave_base_int_matrix<T>::save_binary,\n\toctave_base_int_matrix<T>::load_binary,\n\toctave_base_int_scalar<T>::save_binary,\n\toctave_base_int_scalar<T>::load_binary): Likewise.\n\t* ov-bool-mat.cc (octave_bool_matrix::save_binary,\n\toctave_bool_matrix::load_binary): Likewise.\n\t* ov-bool-sparse.cc (octave_sparse_bool_matrix::save_binary,\n\toctave_sparse_bool_matrix::load_binary): Likewise.\n\t* ov-bool.cc (octave_bool::save_binary, octave_bool::load_binary):\n\tLikewise.\n\t* ov-cell.cc (octave_cell::save_binary, octave_cell::load_binary):\n\tLikewise.\n\t* ov-complex.cc (octave_complex::save_binary,\n\toctave_complex::load_binary): Likewise.\n\t* ov-cx-mat.cc (octave_matrix::save_binary,\n\toctave_matrix::load_binary): Likewise.\n\t* ov-cx-sparse.cc (octave_sparse_complex_matrix::save_binary,\n\toctave_sparse_complex_matrix::load_binary): Likewise.\n\t* ov-fcn-handle.cc (octave_fcn_handle::save_binary,\n\toctave_fcn_handle::load_binary): Likewise.\n\t* ov-fcn-inline.cc (octave_fcn_inline::save_binary,\n\toctave_fcn_inline::load_binary): Likewise.\n\t* ov-list.cc (octave_list::save_binary, octave_list::load_binary):\n\tLikewise.\n\t* ov-range.cc (octave_range::save_binary, octave_range::load_binary):\n\tLikewise.\n\t* ov-re-mat.cc (octave_matrix::save_binary,\n\toctave_matrix::load_binary): Likewise.\n\t* ov-re-sparse.cc (octave_sparse_matrix::save_binary,\n\toctave_sparse_matrix::load_binary): Likewise.\n\t* ov-scalar.cc (octave_scalar::save_binary,\n\toctave_scalar::load_binary): Likewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::save_binary,\n\t(octave_char_matrix_str::load_binary): Likewise.\n\t* ov-struct.cc (octave_struct::save_binary,\n\toctave_struct::load_binary): Likewise.\n\t* ls-oct-binary.cc (save_binary_data, read_binary_data): Likewise.\n\t* ls-mat4.cc (read_mat_file_header, save_mat_binary_data): Likewise.\n\t* ls-mat5.cc (read_mat5_tag, read_mat5_binary_element,\n\tread_mat5_binary_element, read_mat5_binary_file_header,\n\tMAT5_DO_WRITE, write_mat5_array, write_mat5_integer_data,\n\tsave_mat5_binary_element, READ_INTEGER_DATA): Likewise.\n\n2006-04-12  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h (OV_REP_TYPE): New macro.\n\n\t* DLD-FUNCTIONS/sparse.cc (MINMAX_BODY): No need to cast arg1 to\n\tconst octave_sparse_matrix&.\n\n\t* ov-base.cc (print_answer_id_name, warn_resize_on_range_error,\n\twarn_num_to_str, silent_functions): Move here, from ov.cc.\n\t(Vwarn_resize_on_range_error, Vsilent_functions): Likewise.\n\t(Vprint_answer_id_name): Likewise.  Now static.\n\t(symbols_of_ov_base): New function.  Move DEFVARs for\n\tprint_answer_id_name, warn_resize_on_range_error, warn_num_to_str,\n\tand silent_functions here from symbols_of_ov in ov.cc.\n\t* ov.h (Vprint_answer_id_name): Delete decl.\n\t* ov-base.h (Vwarn_resize_on_range_error, Vwarn_num_to_str):\n\tMove decls here from ov.h.\n\n\t* ov-str-mat.cc (warn_str_to_num): Move here, from ov.cc.\n\t(Vwarn_str_to_num): Likewise.  Now static.\n\t(symbols_of_ov_str_mat): New function.  Move DEFVAR for\n\twarn_str_to_num here from symbols_of_ov in ov.cc.\n\t* ov.h (Vwarn_str_to_num): Delete decl.\n\n\t* ov-struct.cc (octave_struct::load_ascii): Pass loop counter, not\n\tcount, to read_ascii.\n\t* ov-list.cc (octave_list::load_ascii): Likewise.\n\n\t* ov-list.cc (octave_list::do_index_op): Allow index to extract\n\tmultiple items.  Result is always a list.\n\n\t* pr-output.cc (struct_levels_to_print): Move here from ov.cc.\n\t(Vstruct-levels_to_print): Likewise.\n\t(symbols_of_pr_output): Move DEFVAR for struct_levels_to_print here\n\tfrom symbols_of_ov in ov.cc.\n\t* pr-output.h (Vstruct_levels_to_print): Nove decl here from ov.h.\n\n\t* gripes.cc (warn_divide_by_zero): Move here from ov.cc.\n\t(Vwarn_divide_by_zero): Likewise.  Now static.\n\t(symbols_of_gripes): New function.  Move DEFVAR for\n\twarn_divide_by_zero here from symbols_of_ov in ov.cc.\n\t* ov.h (Vwarn_divide_by_zero): Delete decl.\n\n\t* load-save.cc (do_load): Declare count octave_idx_type, not int.\n\t* ls-oct-ascii.cc, ls-oct-ascii.h (read_ascii_data): Likewise.\n\n\tRearrange octave_value class hierarchy so that rep is a pointer\n\tan octave_base_value object and the octave_base_value class\n\tstores the reference count.  Virtualness now goes with the\n\toctave_base_value class, not the octave_value class.\n\n\t* ops.h, ov-base-int.cc, ov-base-int.h, ov-base-mat.h,\n\tov-base-scalar.h, ov-base-sparse.h, ov-base.cc, ov-base.h,\n\tov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc,\n\tov-bool-sparse.h, ov-bool.cc, ov-bool.h, ov-cell.cc, ov-cell.h,\n\tov-ch-mat.h, ov-colon.h, ov-complex.cc, ov-complex.h,\n\tov-cs-list.h, ov-cx-mat.cc, ov-cx-mat.h, ov-cx-sparse.cc,\n\tov-cx-sparse.h, ov-fcn-handle.h, ov-fcn-inline.h, ov-fcn.cc,\n\tov-fcn.h, ov-intx.h, ov-list.cc, ov-list.h, ov-range.cc,\n\tov-range.h, ov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc,\n\tov-re-sparse.h, ov-scalar.h, ov-str-mat.cc, ov-str-mat.h,\n\tov-streamoff.h, ov-struct.cc, ov-struct.h, ov-type-conv.h,\n\tov-typeinfo.cc, ov-typeinfo.h, ov-va-args.h, ov.cc, ov.h,\n\tvariables.cc, DLD-FUNCTIONS/matrix_type.cc, DLD-FUNCTIONS/splu.cc,\n\tOPERATORS/op-chm.cc: Cope with octave_value hierarchy changes\n\t(apologies for the lack of detail).\n\n\t* ov.cc (octave_value::nil_rep): Delete.\n\t* ov.h (octave_value::nil_rep): Delete decl.\n\n\t* ov-base.h (DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA,\n\tDECLARE_OV_BASE_TYPEID_FUNCTIONS_AND_DATA,\n\tDECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2,\n\tDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA):\n\tMove macro definitions here from ov.h.\n\t(struct_indent, increment_struct_indent, decrement_struct_indent,\n\tlist_indent, increment_list_indent, decrement_list_indent):\n\tDelete decls.\n\n\t* ov-base.cc. ov-base.h (do_index_op, ndims, all, any,\n\tconvert_to_str, print_with_name, numeric_assign,\n\treset_indent_level, increment_indent_level,\n\tdecrement_indent_level, current_print_indent_level, newline,\n\tindent, reset): Move member functions here from octave_value class.\n\t(count, curr_print_indent_level, beginning_of_line):\n\tMove data members here from octave_value class.\n\t(gripe_indexed_assignment, gripe_assign_conversion_failed,\n\tgripe_no_conversion): Move here from ov.cc.\n\n\t* ov.h (class octave_xvalue): Delete.\n\t(octave_value::octave_value (const octave_xvalue&)): Delete.\n\t(anonymous union): Delete.\n\t(octave_value::rep): Now a pointer to octave_base_value instead of\n\toctave_value.\n\n\t(octave_value::internal_rep): Return pointer to octave_base_value,\n\tnot octave_value.\n\n2006-04-11  John W. Eaton  <jwe@octave.org>\n\n\t* pt-assign.cc (tree_simple_assignment::rvalue,\n\ttree_multi_assignment::rvalue):\n\tError if RHS is a comma-separated list.\n\n2006-04-07  John W. Eaton  <jwe@octave.org>\n\n\t* defaults.cc (FOCTAVE_VERSION): New function to replace\n\tcorresponding DEFCONSTX macro in symbols_of_defaults.\n\n\t* file-io.cc (FP_tmpdir, FSEEK_SET, FSEEK_CUR, FSEEK_END, Fstdin,\n\tFstdout, Fstderr): New functions to replace DEFCONSTX macros in\n\tsymbols_of_file_io.\n\t(const_value): New static function.\n\t(symbols_of_file_io): Delete.\n\n\t* syscalls.cc (FF_DUPFD, FF_GETFD, FF_GETFL, FF_SETFD, FF_SETFL,\n\tFO_APPEND, FO_ASYNC, FO_CREAT, FO_EXCL, FO_NONBLOCK, FO_RDONLY,\n\tFO_RDWR, FO_SYNC, FO_TRUNC, FO_WRONLY, FWNOHANG, FWUNTRACED,\n\tFWCONTINUE): New functions to replace DEFCONSTX macros in\n\tsymbols_of_syscalls.\n\t(const_value): New static function.\n\t(symbols_of_syscalls): Delete.\n\n\t* pr-output.cc (pr_max_internal, pr_min_internal):\n\tReturn 0 if all values are Inf or NaN.\n\tAlways leave space for sign when printing Inf or NaN values.\n\n\t* parse.y (Fmfilename): Don't let filenames like ../foo fake us out.\n\n\t* data.cc (fill_matrix): Create separate versions for int, bool,\n\tand double, and Complex values.\n\t(FInf, FNaN, Fe, Feps, Fpi, Frealmax, Frealmin, FI, FNA, Ffalse,\n\tFtrue): New functions to replace DEFCONST and DEFCONSTX macros in\n\tsymbols_of_data.  Provide i, J, and j aliases for I.\n\tProvide nan alias for NaN.  Provide inf alias for Inf.\n\t(symbols_of_data): Delete.\n\n2006-04-06  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (parse_and_execute, parse_fcn_file):\n\tCreate octave_script_function object and push it on the call stack.\n\n\t* parse.y (Fmfilename): Check for script or user function file on\n\tcall stack.\n\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op):\n\tUse octave_call_stack instead of curr_function to save pointer to\n\tcurrent function.\n\t* ov-mapper.cc (octave_mapper::do_multi_index_op): Likewise.\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op): Likewise.\n\n\t* pt-bp.h (MAYBE_DO_BREAKPOINT): Use octave_call_stack instead of\n\tcurr_function to get pointer to current function.\n\t* pt-arg-list.cc (list::convert_to_const_vector): Likewise.\n\t* variables.cc (Fmlock, Fmunlock, Fmislocked): Likewise.\n\t* input.cc (get_user_input): Likewise.\n\t* error.cc (warning_1, error_2): Likewise.  Only enter debug mode\n\tif there is a scripting language caller.\n\t* ov-usr-fcn.cc (Fva_arg, Fva_start, Fvr_val): Likewise.  Check\n\tscripting language caller, not current function.\n\n\t* toplev.cc (curr_caller_function, curr_function): Delete.\n\t* toplev.h: Delete decls.\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tDon't protect and set curr_caller_function.\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op): Likewise.\n\t* ov-mapper.cc (octave_mapper::do_multi_index_op): Likewise.\n\n\t* variables.cc (do_who): Use octave_call_stack instead of\n\tcurr_caller_function to get pointer to calling function.\n\t* input.cc (get_user_input): Likewise.\n\t* error.cc (pr_where): Likewise.  No need for curr_function now.\n\t* parse.y (Fmfilename): Likewise.  Check for scripting language\n\tcaller, not any calling function.\n\n\t* ov-usr-fcn.h (octave_user_script): New class.\n\t* ov-fcn.h (octave_function::is_user_script): New virtual function.\n\n\t* toplev.h, toplev.cc (octave_call_stack): New class.\n\n\t* debug.cc (Fdbwhere): Use get_user_function here.\n\n2006-04-05  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (mk-pkg-add): Use mfilename to simplify.\n\t(PKG_ADD): Don't pass --prefix arg to mk-pkg-add.\n\t(PKG_ADD.inst): Delete target.\n\t(clean): Don't remove PKG_ADD.inst.\n\t(install-oct): Don't depend on PKG_ADD.inst.  Install PKG_ADD, not\n\tPKG_ADD.inst.\n\n\t* parse.y (Fmfilename): New function.\n\n2006-04-04  David Bateman  <dbateman@free.fr>\n\n\t* help.cc (Flookfor): Skip overloaded functions.  Lookup help text\n\tof autoloaded function, not parent that contains the autoload.\n\n2006-04-03  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (Fresize): New function.\n\t* oct-map.cc, ov-base-mat.cc, ov-base-sparse.cc, ov-base.cc,\n\tov-bool.cc, ov-complex.cc, ov-range.cc, ov-scalar.cc,\n\tov-str-mat.cc (resize): Add boolean fill argument.\n\t* oct-map.h, ov-base-mat.h, ov-base-sparse.h, ov-base.h,\n\tov-bool.h, ov-complex.h, ov-intx.h, ov-range.h, ov-scalar.h,\n\tov-str-mat.h, ov.h (resize): Ditto.\n\n\t* DLD-FUNCTIONS/rand.cc (do_rand): Additional argument for\n\tgamma and poisson distributions.  Change \"state\" and \"seed\"\n\targuments so that they choose between generators.\n\tAdd, poisson, gamma and exponential generators.\n\t(Frand, Frandn): Update docs for new generators, add tests.\n\t(Frande, Frandp, Frandg): New generators, with test code.\n\n\t* DLD-FUNCTIONS/daspk.cc (Fdaspk): Allow functions to be passed\n\tusing function handles, inline functions, and cell arrays of\n\tstrings, inline and function handles.\n\t* DLD-FUNCTIONS/dasrtk.cc (Fdasrt): Likewise.\n\t* DLD-FUNCTIONS/dassl.cc (Fdassl): Likewise.\n\t* DLD-FUNCTIONS/fsolve.cc (Ffsolve): Likewise.\n\t* DLD-FUNCTIONS/lsode.cc (Flsode):  Likewise.\n\n\t* ls-hdf5.h (hdf5_fstreambase::open): Remove unused arg prot.\n\n2006-03-30  Bill Denney  <denney@seas.upenn.edu>\n\n \t* data.cc: Include numel in @seealso.\n\n2006-03-30  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/fftw_wisdom.cc: Don't attempt to save wisdom to\n\tan empty filename or invalid filename.\n\n2006-03-28  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/matrix_type.cc: Update copyright notice and FSF\n\taddress.\n\n2006-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/spchol.cc (Fsymbfact): Use CHOLMOD_NAME to select\n\tproper version of row_subtree function.\n\n\t* ov-cell.cc (octave_cell::save_hdf5): Use OSSTREAM instead of\n\tfixed character buffer and sprintf.\n\t* ov-list.cc (octave_list::save_hdf5, octave_list::save_ascii,\n\toctave_list::save_binary): Likewise.\n\n\t* ov-cell.h (octave_cell::convert_to_str_internal):\n\tUndo previous change for pad arg.\n\t* ov-cell.cc (octave_cell::all_strings): Reinstate pad arg, pass\n\tit on to all_strings.\n\t* ov.h (octave_value::all_strings): Reinstate pad arg.\n\t* ov-base.cc (octave_base_value::all_strings): Likewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::all_strings): Likewise.\n\t* ov.h, ov-base.h, ov-cell.h, ov-str-mat.h: Fix all_strings decls.\n\n2005-10-25  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (do_cat): With 1 arg, return [](0x0) for compatibility.\n\n2006-03-23  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.5+.\n\n2006-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.5.\n\t(OCTAVE_API_VERSION): Now api-v18.\n\t(OCTAVE_RELEASE_DATE): Now 2006-03-22.\n\n2006-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* ov-cell.h (octave_cell::convert_to_str_internal):\n\tIgnore pad and force args.\n\t* ov-cell.cc (octave_cell::all_strings): Delete args.  Never pad.\n\t* ov-base.cc (octave_base_value::all_strings): Delete args.\n\tAlways force string conversion, never pad.\n\t* ov-str-mat.cc (octave_char_matrix_str::all_strings):\n\tDelete args.  Don't strip whitespace.\n\t* ov.h, ov-base.h, ov-cell.h, ov-str-mat.h: Fix all_strings decls.\n\t* strfns.cc (Fchar): No args for all_strings.\n\n2006-03-21  David bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/getrusage.cc (Fgetrusage): Use GetProcessTimes for\n\tMinGW to obtain user and system times.\n\n2006-03-17  John W. Eaton  <jwe@octave.org>\n\n\t* strfns.cc (F__list_in_columns__): New function.\n\n2006-03-16  Bill Denney  <bill@givebillmoney.com>\n\n\t* DLD-FUNCTIONS/time.cc: Improve @seealso entries in doc strings.\n\n2006-03-16  John W. Eaton  <jwe@octave.org>\n\n\t* __gnuplot_raw__.l (F__gnuplot_show__): Temporarily use DEFCMD\n\tinstead of DEFUN.\n\t(symbols_of___gnuplot_raw__): Temporarily mark __gnuplot_plot__,\n\t__gnuplot_set__, __gnuplot_splot__, and __gnuplot_replot__ as raw\n\tcommands.\n\n\t* variables.cc (is_marked_as_rawcommand, unmark_rawcommand,\n\tmark_as_rawcommand): Temporarily not static.\n\t* variables.h: Temporarily Provide decls.\n\n2006-03-16  David Bateman  <dbateman@free.fr>\n\n\t* sparse-xdiv.cc (result_ok): delete.\n\t(xdiv, xleftdiv): Simplify to use version of SpareMatrix::solve\n\tand SparseComplexMatrix::solve which internally treats rectangular\n\tand singular matrices.\n\t* DLD-FUNCTIONS/luinc.cc: Remove error test for singular matrix as\n\tQR solver now implemented.\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): Paranoid check on\n\terror_state. Disable tests for the detection of underdetermined\n\tlower and over-determined upper matrix due to problems with\n\tnon minimum norm solutions.\n\t* DLD-FUNCTIONS/spqr.cc: Warning for issue of use of Fspqr for\n\tunder-determined problems.\n\n2006-03-16  John W. Eaton  <jwe@octave.org>\n\n\t* __gnuplot_raw__.l: Move here from DLD-FUNCTIONS/__gnuplot_raw__.l.\n\tUse DEFUN, not DEFUN_DLD.  Include defun.h, not defun-dld.h.\n\t(gnuplot::do_init):Move guts to symbols_of___gnuplot_raw__.\n\t(symbols_of___gnuplot_raw__): New function.\n\n\t* Makefile.in (DLD_XSRC): Delete __gnuplot_raw__.l from the list.\n\t(DIST_SRC): Include __gnuplot_raw__.l in the list.\n\t(__gnuplot_raw__.cc): Depend on __gnuplot_raw__.l, not\n\tDLD-FUNCTIONS/__gnuplot_raw__.l\n\n\t* ls-oct-ascii.h (extract_keyword): Use std::string compare method\n\tinstead of strncmp.\n\t* ls-oct-ascii.cc (extract_keyword): Likewise.\n\n2006-03-15  William Poetra Yoga Hadisoeseno  <williampoetra@gmail.com>\n\n\t* data.cc (Frows, Fcolumns): New functions.\n\n\t* DLD-FUNCTIONS/time.cc (Fstrptime, Fstrftime): Fix docstring.\n\n\t* strfns.cc (Fstrcmp): Fixed docstring.\n\n2006-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* pager.cc (Fterminal_size): New function.\n\n\t* help.cc (help_from_info): Simplify.\n\t(try_info): Use feval to call doc instead of executing info program.\n\t(additional_help_message): Point users to doc instead of help -i.\n\tFrom Søren Hauberg <soren@hauberg.org>.\n\n\t* toplev.cc (Fsystem): Return output if nargout > 1, not 0.\n\n2006-03-14  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* help.cc (Fhelp, Fwhich, Flookfor): Doc string fix.\n\n2006-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* defun.cc (print_usage): New arg, extra_msg.\n\n\t* xpow.cc: Omit tests for now.\n\n\t* parse.y (QUOTE, TRANSPOSE): For compatibility, now have same\n\tprecedence as POW and EPOW.\n\n2006-03-14  Bill Denney  <bill@givebillmoney.com>\n\n\t * load-save.cc (Fload, Fsave): Update docstring for functional form.\n\n2006-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* xpow.cc (elem_xpow): Undo previous change.\n\n2006-03-14  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* xpow.cc: New tests.\n\n2006-03-13  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (fcn_out_of_date): No longer static.\n\t* ov-fcn-handle.cc (warn_reload): New function.\n\t(octave_fcn_handle::subsref): Implement basic logic for updating\n\twhen pointed-to function changes.\n\n2006-03-10  John W. Eaton  <jwe@octave.org>\n\n\t* xpow.cc (elem_xpow): Only use complex pow if really necessary.\n\n\t* symtab.cc (symbol_table::glob, symbol_table::symbol_list,\n\tsymbol_table::subsymbol_list): Force result to be a column\n\tvector.\n\n\t* oct-stream.h (octave_stream::stream_ok): Undo previous change.\n\tEliminate who parameter.  Change all callers.\n\n\t* variables.cc (do_who): Return more info in structure array for\n\tverbose output.\n\t* symtab.h (symbol_record::size, symbol_record::class_name,\n\tsymbol_record::is_sparse_type, symbol_record::is_complex_type,\n\tsymbol_record::size, symbol_record::symbol_def::class_name,\n\tsymbol_record::symbol_def::is_sparse_type,\n\tsymbol_record::symbol_def::is_complex_type): New functions.\n\t* ov.h (octave_value::size): New function.\n\n2006-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (run_command_and_return_output): Swap output and\n\tstatus for compatibility.\n\n\t* Makefile.in (defaults.h, oct-conf.h): Force updates.\n\n\t* defaults.h.in (OCTAVE_RELEASE): New macro.\n\n\t* octave.cc (F__version_info__): New arg, release.\n\t(initialize_version_info): Pass release arg to F__version_info__.\n\n\t* toplev.cc: Include api_version in the list.\n\n\t* Makefile.in (DIST_SRC): Include octave.cc here.\n\t(DISTFILES, DEP_5): Not here.\n\n\t* octave.cc (F__version_info__): New function.\n\t(initialize_version_info): New function.\n\t(octave_main): Call initialize_version_info just before reading\n\tinit files.\n\n\t* version.h (OCTAVE_RELEASE_DATE): New macro.\n\n\t* ov-fcn-handle.h (octave_fcn_handle::dims): New function.\n\n2006-03-08  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_stream::stream_ok): Move definition here,\n\tfrom oct-stream.h.  New arg, warn.  If warn is true and stream is\n\tinvalid, print warning.\n\t(octave_stream::error): Always avoid warning message from\n\tstream_ok.  Return \"invalid stream object\" if stream is not ok.\n\n2006-03-08  David Bateman  <dbateman@free.fr>\n\n\t* ov-mapper.cc (SPARSE_MAPPER_LOOP_2): Change nnz to nz to remove\n\tshadowed variable warning.\n\t* DLD-FUNCTIONS/spqr.cc: Update for new upstream CXSPARSE release.\n\n2006-03-06  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (display_help_text): Force linebreak with @sp.\n\n2006-03-06  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* bitfcns.cc, data.cc, debug.cc, file-io.cc, help.cc,\n\tload-save.cc, mappers.cc, ov-cell.cc, ov-fcn-inline.cc,\n\tov-struct.cc, ov-usr-fcn.cc, ov.cc, pr-output.cc, utils.cc,\n\tvariables.cc, DLD-FUNCTIONS/ccolamd.cc, DLD-FUNCTIONS/cellfun.cc,\n\tDLD-FUNCTIONS/colamd.cc, DLD-FUNCTIONS/daspk.cc,\n\tDLD-FUNCTIONS/dasrt.cc, DLD-FUNCTIONS/dassl.cc,\n\tDLD-FUNCTIONS/fft.cc, DLD-FUNCTIONS/fft2.cc,\n\tDLD-FUNCTIONS/fftn.cc, DLD-FUNCTIONS/fftw_wisdom.cc,\n\tDLD-FUNCTIONS/gammainc.cc, DLD-FUNCTIONS/gcd.cc,\n\tDLD-FUNCTIONS/luinc.cc,\tDLD-FUNCTIONS/sparse.cc,\n\tDLD-FUNCTIONS/spchol.cc, DLD-FUNCTIONS/splu.cc,\n\tDLD-FUNCTIONS/spqr.cc, DLD-FUNCTIONS/sqrtm.cc:\n\tMove @seealso inside @defXXX macro.  Remove \"and\" from @seealso.\n\n2006-03-04  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (additional_help_message): Don't print \"\\n\" before message.\n\t(help_from_symbol_table): If Vsuppress_verbose_help_message is\n\ttrue, don't print which info.\n\n2006-03-03  John W. Eaton  <jwe@octave.org>\n\n\t* dirfns.cc (Vconfirm_recursive_rmdir): New static variable.\n\t(symbols_of_dirfns): DEFVAR it.\n\t(confirm_recursive_rmdir): New function.\n\t(Frmdir): Maybe ask for confirmation for recursive removal.\n\tRequire second arg to be \"s\".\n\n\t* input.cc (octave_yes_or_no): New function.\n\t(Fyes_or_no): New function.\n\t* input.h (octave_yes_or_no): Provide decl.\n\n2006-03-02  John W. Eaton  <jwe@octave.org>\n\n\t* dirfns.cc (Fmkdir, Frmdir): Now commands.\n\n2006-02-20  David Bateman  <dbateman@free.fr>\n\n\t* ov.h (virtual bool is_sparse_type (bool)): New virtual function\n\t* ov-base.h (bool is_sparse_type (bool)): New function\n\t* ov-base-sparse.h (bool is_sparse_type (bool)): New function\n\t* DLD-FUNCTIONS/ccolamd.cc, DLD-FUNCTION/colamd.cc,\n\tDLD-FUNCTIONS/__glpk__.cc, DLD-FUNCTIONS/splu.cc,\n\tDLD-FUNCTIONS/sparse.cc, DLD-FUNCTIONS/matrix_type.cc, pt-mat.cc:\n\tReplace us of 'arg.class_name () == \"sparse\"' with\n\t'arg.is_sparse_type ()'\n\n2006-02-20  David Bateman  <dbateman@free.fr>\n\n\t* pt-mat.cc (class tm_row_const): Add any_sparse bool variable.\n\t(tm_row_const::tm_row_const_rep::do_init_element): Initialize\n\tany_sparse variable if any matrice is sparse.\n\t(class tm_const): Add any_sparse bool variable.\n\t(tm_const::init): Initialize any_sparse variable.\n\t(tree_matrix::rvalue): If any matrix is sparse use sparse matrix\n\tas initial matrix for concatenation\n\t* DLD-FUNCTIONS/matrix_type.cc: Add tests for new rectangular\n\tdiagonal, permuted diagonal, triangular and permuted triangular\n\tmatrices\n\n2006-02-20  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (__builtin_delete, __builtin_new): Use std::cerr for\n\tmessages instead of std::cout.\n\t(main_loop, do_octave_atexit): Use octave_stdout, not std::cout.\n\n2006-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (Fautoload): Return struct array of autoload info if\n\tnargin == 0.\n\n2006-02-15  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* help.cc (keywords): Doc string fix.\n\n2006-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* oct-procbuf.cc (close): Use __CYGWIN__ instead of __CYGWIN32__.\n\n2006-02-13  David Bateman  <dbateman@free.fr>\n\n\t* DLD_FUNCTIONS/regexp.cc (octregexp): Add matlab compatiable\n\tnamed tokens. Update the tests\n\n2006-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (\\[{S}*): Maybe set lexer_flags.looking_at_return_list or\n\tlexer_flags.looking_at_matrix_or_assign_lhs here.\n\t* parse.y\n\t(return_list_beg): Don't use in_return_list here.\n\t(assign_lhs, matrix): Don't use in_matrix_or_assign_lhs here.\n\t(in_matrix_or_assign_lhs, in_return_list): Delete unused macros.\n\t(matrix): Clear lexer_flags.looking_at_matrix_or_assign_lhs in all\n\tcases.\n\n2006-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* utils.cc (oct_file_in_path): Check len > 4, not len > 2.\n\tFrom Larrie Carr <larrie@telus.net>.\n\n2006-02-09  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/spqr.cc: New file for sparse QR and dmperm based on\n\tCSparse.\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): dintinguish between\n\trectangular and singular matrices. Add tests.\n\t* DLD-FUNCTIONS/luinc.cc: Add tests.\n\t* DLD-FUNCTIONS/spkron.cc: Ditto.\n\t* Makefile.in (DLD_XSRC): Add spqr.cc.\n\t(OCT_LINK_DEPS): Add CSSPARSE_LIBS.\n\t* sparse-xdiv.h: Remove conditio of lssolve.\n\n2006-02-08  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (frob_function): Clear ID_NAME from top_level symbol\n\ttable if we are defining a function at the top-level and a\n\tfunction with the same name is already in the top-level symbol\n\ttable.\n\n2006-01-31  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-sparse.h (octave_base_sparse<T>::nzmax): New function.\n\t* ov.h (octave_value::nzmax): New function.\n\t* ov-base.cc (octave_base_value::nzmax): New function.\n\t* ov-base.h: Provide decl.\n\t* data.cc (Fnzmax): New function.\n\t* DLD-FUNCTIONS/sparse.cc (Fnzmax): Delete.\n\n2006-01-31  Kim Hansen  <kim@i9.dk>\n\n\t* __glpk__.cc (F__glpk__): Fix for sparse matrices.\n\n2006-01-30  John W. Eaton  <jwe@octave.org>\n\n\t* gripes.cc (gripe_wrong_type_arg (const char*, const char*, bool)):\n\tNew function.\n\t(gripe_wrong_type_arg (const char*, const std::string&, bool)):\n\tDefine using const char*, const char*, bool version.\n\t(gripe_wrong_type_arg (const char*, const octave_value&, bool)):\n\tDefine using const char*, const std::string&, bool version.\n\n\t* ov.h (octave_value::nnz): New function.\n\t* ov-base.cc (octave_base_value::nnz): New function.\n\t* ov-base.h: Provide decl.\n\t* ov-base-mat.h (octave_base_matrix<MT>::nnz): New function.\n\t* ov-base-scalar.h (octave_base_scalar<MT>::nnz): New function.\n\t* Cell.cc (Cell::nnz): New function.\n\t* Cell.h: Provide decl.\n\t* data.cc (Fnnz): New function.\n\t* DLD-FUNCTIONS/sparse.cc (Fnnz): Delete.\n\n2006-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (octave_struct::print_raw): Correctly print scalar\n\tstructs and empty struct arrays.\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l (Fclearplot): For compatibility,\n\talso turn off hold state for current figure.\n\n2006-01-13  Bill Denney  <bill@givebillmoney.com>\n\n \t* dirfns.cc: Add @seealso{} to docstrings.\n\n2006-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (display_help_text): Use warning() to print raw Texinfo\n\tsource.  Don't redirect error output for makeinfo process.\n\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l (F__gnuplot_init__): Delete\n\tfunction and PKG_ADD directive.\n\t(gnuplot::gnuplot): Call do_init here.\n\t(gnuplot::init): Delete static function.\n\t(gnuplot::close_all): New static function.\n\t(class gnuplot_X): New class.\n\t(gnpulot_X::X): New static instance.\n\n2006-01-12  David Bateman  <dbateman@free.fr>\n\n\t* help.cc (make_name_list): Add autoload functions to list of\n\tavailable completions.\n\t(simple_help): Add autoloaded functions to functions listed\n\t(first_help_sentence): Avoid issue with single line help string\n\tthat is not terminated in \\n.\n\t(Flookfor): Check for string match in the keyword/function, etc\n\tname. Also look for string match in help of autoloaded functions.\n\tLoad oct-files to be able to access their help string.\n\t* parse.y (string_vector autoloaded_functions (void)): New\n\tfunction to list all autloaded functions.\n\t(string_vector reverse_lookup_autoload (const std::string& nm)):\n\tReverse lookup function to match file to autoloaded functions.\n\t* parse.h (autoloaded_functions, reverse_lookup_autoload):\n\tDeclaration.\n\n\t* oct-map.cc (maybe_delete_elements): New function.\n\t* oct-map.h (maybe_delete_elements): Declare it.\n\t* ov-struct.cc (octave_struct::subsref): Handle indexing empty\n\tstructure.\n\t(octave_struct::subsasgn): If rhs is [], delete elements.\n\t(octave_struct::print_raw): Handle printing empty structure.\n\n\t* ls-mat5.cc (read_mat5_binary_element): Allow reading of sparse\n\telements when nnz doesn't equal nzmax.\n\n2006-01-10  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/sparse.cc (sparse_find): Use Sparse<T>::nonzero()\n\trather than Sparse<T>::nnz(), due to possibility of overallocation\n\tof memory.\n\n2006-01-06  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.cc (Octave_map::transpose): Avoid GCC 3.3.x parse error.\n\n2005-12-14  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_stream::invalid_stream_error): Delete.\n\t* oct-stream.h (octave_stream::stream_ok): Don't fail with error.\n\n2005-12-14  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/regexp.cc: New file.\n\n\t* DLD-FUNCTIONS/dispatch.cc: Update tests for string/sq_string\n\tdifferences.\n\n\t* error.cc (Vquiet_warning): New variable.\n\t(vwarning): Use Vquiet_warning to prevent warning output.\n\t(Fwarning): Include \"quiet\" option to Fwarning function.\n\tAssign retval when using \"query\".  Typo in error message.\n\t(Flastwarn): Clear warning_state when using Flastwarn to probe warning\n\tmessage.\n\n\t* ov-struct.cc: Update Fstruct tests for change in error output.\n\n\t* Makefile.in: Include regexp when needed with appropriate libraries.\n\n2005-12-13  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in: Change references to gplot.l to __gnuplot_raw__.l.\n\t* DLD-FUNCTIONS/__gnuplot_raw__.l: Rename from DLD-FUNCTIONS/gplot.l.\n\tRemove all references to deprecated gplot, gsplot, graw, gset and\n\tgshow functions.\n\t* help.cc (static help_list keywords[]): Remove gsplot and gplot.\n\n\t* ls-oct-ascii.cc (save_three_d):  Don't strip Inf or NaN.\n\t(save_ascii_data_for_plotting): Ditto.\n\n2005-12-13  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_stream_list::do_insert): Check open state\n\tof stream in list instead of whether stream state is OK.\n\n2005-12-12  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-struct.cc (transpose): New function.\n\t(install_struct_ops): Install it.\n\n\t* oct-map.cc (Octave_map::transpose): New function.\n\t* oct-map.h: Provide decl.\n\n2005-12-08  John W. Eaton  <jwe@octave.org>\n\n\t* Cell.cc (Cell::column): New function.\n\t* pt-loop.cc (DO_ND_LOOP): Simplify.\n\t(simple_for_loop_command::eval): Correctly handle N-d numeric and\n\tcell arrays when only the first dimension is 0.\n\n2005-12-07  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (NL): Also accept '\\r'.\n\n\t* error.cc (Vbacktrace_on_warning, warning_options,\n\tVlast_warning_id, Vlast_error_id): New file-scope variables.\n\t(Vwarning_frequency, Vwarning_option): Delete unused variables.\n\t(set_warning_option): Delete unused function.\n\t(Fwarning): Update for compatibility.  Use DEFCMD, not DEFUN.\n\t(warning_enabled, check_state): New functions.\n\t(warning (const char *fmt, ...)): Use it.\n\t(init_warning_options): New function.\n\t(symbols_of_error): Call it.\n\t(vwarning, Flastwarn): Handle Vlast_warning_id.  Improve compatibility.\n\t(handle_message): New arg, ID.  Change all callers.\n\t(vwarning, verror, error_1): New arg, ID.  Change all callers.\n\t(verror, Flasterr): Handle Vlast_error_id.  Improve compatibility.\n\n\t* error.cc (message_with_id, usage_with_id, warning_with_id,\n\terror_with_id, parse_error_with_id): New functions.\n\t(error_2, warning_1, usage_1): New functions.\n\t* error.h (message_with_id, usage_with_id, warning_with_id,\n\terror_with_id, parse_error_with_id): Provide decls.\n\n2005-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/schur.cc (Fschur): Doc string fix.\n\tFrom Jorge Barros de Abreu <ficmatin01@solar.com.br>.\n\n2005-11-28  John W. Eaton  <jwe@octave.org>\n\n\t* syscalls.cc (Funame): New function.\n\n2005-11-21  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (pr_int): Fix thinko in byte-swapping for bit format.\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun):\n\tUse C++ static_cast instead of C-style casts.\n\n2005-11-21  William Poetra Yoga H <williampoetra@yahoo.com>\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fcellfun):\n\tDocstring and error message fixes.\n\n2005-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/minmax.cc (MINMAX_BODY): Don't cast arg1 to\n\tconst octave_complex_matrix&.\n\n2005-11-16  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (PKG_ADD.inst): New target.\n\t(install-oct): Depend on it.\n\t(clean): Remove it.\n\n\t* mk-pkg-add: New option --install.  Don't use --prefix option.\n\tDelete obsolete comments.\n\n\t* Cell.cc (Cell::index): Indexing with () is a no-op, not an error.\n\t* oct-map.cc (Octave_map::index): Likewise.\n\t* ov-base-mat.cc (octave_base_matrix<MT>::do_index_op): Likewise.\n\t* ov-base-sparse.cc (octave_base_sparse<T>::do_index_op): Likewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::do_index_op_internal):\n\tLikewise.\n\n2005-11-11  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (install-oct): Fix thinko in previous change.\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.4\n\t(OCTAVE_API_VERSION): Now api-v17.\n\n\t* variables.cc (symbol_out_of_date): Check for autoloads here too.\n\n\t* Makefile.in (PKG_ADD): Depend on $(DLD_DEF_FILES), not $(DLD_SRC).\n\t(%.df : %.cc): Also insert PKG_ADD commands in .df files.\n\t(install-oct): Generate PKG_ADD file for install directory here.\n\tDon't depend on PKG-ADD. No need to make .oct file links.\n\t(clean): No need to delete links.\n\t(stamp-oct-links): Delete target.\n\t(distclean): No need to remove stamp-oct-links.\n\t(all): Depend on $(OCT_FILES), not stamp-oct-links.\n\n\t* mk-pkg-add: New file.\n\t* Makefile.in (DISTFILES): Add it to the list.\n\n\t* mk-oct-links: Delete.\n\t* Makefile.in (DISTFILES): Remove it from the list.\n\n2005-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* ov-str-mat.h (octave_char_matrix_str::permute,\n\toctave_char_matrix_str::resize): New functions.\n\t(octave_char_matrix_sq_str::reshape,\n\toctave_char_matrix_sq_str::permute,\n\toctave_char_matrix_sq_str::resize): New functions.\n\n\t* OPERATORS/op-str-str.cc, OPERATORS/op-str-s.cc,\n\tOPERATORS/op-str-m.cc: Use DEFNDCHARCATOP_FN.\n\n\t* data.cc (do_cat): No need to handle character arrays specially here.\n\n\t* ops.h (DEFNDCHARCATOP_FN): New macro.\n\t* OPERATORS/op-int.h (OCTAVE_INT_CHAR_CONCAT_FN,\n\tOCTAVE_CHAR_INT_CONCAT_FN, OCTAVE_INSTALL_INT_CHAR_CONCAT_FN,\n\tOCTAVE_INSTALL_CHAR_INT_CONCAT_FN): New macros.\n\t* OPERATORS/op-int-concat.cc: Use them do define char/int op functions.\n\t(install_int_concat_ops): Install char/int concat ops.\n\n\t* ov-scalar.h (class octave_scalar): Provide extractors\n\tfor all int array types and char array type.\n\n2005-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* ov-bool-mat.h (class octave_bool_matrix): Provide extractors\n\tfor all int array types and char array type.\n\t* ov-bool.h (class octave_bool): Likewise.\n\n\t* ov-intx.h (class OCTAVE_VALUE_INT_MATRIX_T): Provide extractors\n\tfor all int array types and char array type.\n\t(class OCTAVE_VALUE_INT_SCALAR_T): Provide extractors for all int\n\tscalar and array types and char array type.\n\n\t* pt-mat.cc (tm_const::class_nm): New data member.\n\t(tm_const::tm_const): Initialize it.\n\t(tm_const::class_name): New function.\n\t(tm_row_const::tm_row_const_rep::class_nm): New data member.\n\t(tm_row_const::tm_row_const_rep::tm_row_const_rep): Initialize it.\n\t(tm_row_const::class_name): New function.\n\t(get_concat_class): New function.\n\t(tm_row_const::tm_row_const_rep::do_init_element): Use it.\n\t(tm_const::init): Use it.\n\n2005-11-07  John W. Eaton  <jwe@octave.org>\n\n\t* strfns.cc (Fstrcmp): If args are not strings or cell arrays of\n\tstrings, return false.\n\n2005-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (oct-gperf.h): Avoid extra temporary file.\n\t(distclean): Delete oct-errno.cc here.\n\tFrom Quentin Spencer  <qspencer@ieee.org>.\n\n2005-11-01  Quentin Spencer  <qspencer@ieee.org>\n\n\t* DLD-FUNCTIONS/spchol.cc: Use C++ true/false instead of\n\tpreprocessor defined TRUE/FALSE.\n\t* Makefile.in (DISTFILES): Add mk-errno-list to the list.\n\n2005-10-30  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gplot.l (gnuplot::set_gnuplot_exe,\n\tgnuplot::do_set_gnuplot_exe): New functions.\n\t(gnuplot_binary): Call gnuplot::set_gnuplot_exe here.\n\n\t* DLD-FUNCTIONS/gplot.l (gnuplot::set_gnuplot_use_title_option,\n\tgnuplot::do_set_gnuplot_use_title_option): New functions.\n\t(gnuplot_use_title_option):\n\tCall gnuplot::set_gnuplot_use_title_option here.\n\n2005-10-27  James R. Van Zandt  <jrvz@comcast.net>\n\n\t* mappers.cc: Doc fix for lgamma.\n\t* DLD-FUNCTIONS/gammainc.cc (Fgammainc): Doc fix.\n\n2005-10-27  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Declare mrowsA volatile.\n\n\t* pt-mat.cc (tm_row_const::tm_row_const_rep::tm_row_const_rep):\n\tEnsure that we always have at least two dimensions here.\n\t(tm_const::tm_const): Likewise.\n\t(tm_const::rows, tm_const::columns): Simplify.\n\t(tm_row_const::rows, tm_row_const::columns)): Simplify.\n\n2005-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* oct-procbuf.cc (octave_procbuf::open): Cast 0 to void * to avoid\n\tnew g++ warning.\n\t* toplev.cc (Fsystem): Likewise.\n\n\tChanges for GCC 4.1, tip from Arno J. Klaassen\n\t<arno@heho.snv.jussieu.fr>:\n\n\t* ov.h (do_unary_op (octave_value::unary_op, const octave_value&)):\n\tPublish externally used friend function.\n\t(do_unary_op (octave_value::unary_op, const octave_value&,\n\tconst octave_value&)): Likewise.\n\n2005-10-25  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (do_cat): called with 2 args, should return args(1)\n\tfor compatibility.\n\n2005-10-23  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (DLD_XSRC): Add spchol.cc.\n\t* sparse-xpow.cc (xpow): Change call to sparse inverse to include\n\tSparseType.\n\t* DLD-FUNCTIONS/colamd.c (Fsymbfact): Remove.\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): 64-bit fixes and fix\n\tfor permutation of upper/lower triangular matrices.\n\t* DLD-FUNCTIONS/splu.cc (Fspinv): Implemtation of sparse inverse\n\tfunction.\n\t* DLD-FUNCTIONS/spchol.cc (sparse_chol): Static function for core of\n\tthe sparse cholesky factorization.\n\t(Fspchol): New function for sparse cholesky factorization R'R.\n\t(Fsplchol): New function for sparse cholesky factorization LL'.\n\t(Fspcholinv): New cholesky inverse function.\n\t(Fspchol2inv): New cholesky inverse function.\n\t(Fsymbfact): Implementation of symbolic factorization using cholmod.\n\n2005-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gplot.l (read_until): Special case STRING.\n\t(handle_string): Restore function.\n\t(\"'\", \"\\\"\"): Call handle string when matching these tokens..\n\n2005-10-20  John W. Eaton  <jwe@octave.org>\n\n\t* pt-mat.cc (tm_row_const::all_real): New data member.\n\t(tm_row_const::all_real_p): New function.\n\t(tm_row_const::tm_row_const_rep::all_real): New data member.\n\t(tm_row_const::tm_row_const_rep::all_real_p): New function.\n\t(tm_row_const::tm_row_const_rep::init): Set all_real and all_cmplx\n\tto true here.\n\t(tm_row_const::all_cmplx): Rename from is_cmplx.\n\t(tm_row_const::all_complex_p): Rename from complex_p.\n\t(tm_row_const::tm_row_const_rep::all_cmplx): Rename from is_cmplx.\n\t(tm_row_const::tm_row_const_rep::all_complex_p): Rename from complex_p.\n\t(tm_row_const::tm_row_const_rep::init): Set all_real and all_cmplx\n\tto true here.\n\t(SINGLE_TYPE_CONCAT): New macro.\n\t(tree_matrix::rvalue): Use it for single type cases.\n\n\t* pt-mat.cc: Sprinkle with OCTAVE_QUIT.\n\n2005-10-18  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (octave_main): If not embedded, call clean_up_and_exit\n\tinstead of return to exit function.\n\n2005-10-18  Arno J. Klaassen  <arno@heho.snv.jussieu.fr>\n\n\t* DLD-FUNCTIONS/gplot.l (gnuplot::handle_title):\n\tOmit class name from declaration.\n\n2005-10-17  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* DLD-FUNCTIONS/sort.cc: Doc string fix.\n\n2005-10-17  John W. Eaton  <jwe@octave.org>\n\n\t* oct-conf.h.in (OCTAVE_CONF_F77_FLOAT_STORE_FLAG): Substitute\n\tOCTAVE_CONF_F77_FLOAT_STORE_FLAG here.\n\n2005-10-14  John W. Eaton  <jwe@octave.org>\n\n\t* mk-errno-list: New script.\n\t* Makefile.in (oct-errno.cc): Use it.\n\n2005-10-13  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gplot.l (F__gnuplot_raw__):\n\tCall print_usage with correct function name.\n\n2005-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gplot.l: Major cleanup.\n\tBuilt-in variable gnuplot_has_frames no longer necessary.\n\t(gnuplot): New class to manage multiple gnuplot processes.\n\t(handle_string): Delete.  It was only used for the case of\n\t__gnuplot_plot__ \"file\", which is no longer allowed.\n\n2005-10-05  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (symbol_exist): Chekck for autoloaded functions.\n\n\t* parse.y (Fautoload): New function.\n\t(autoloading, autoload_map): New static variables.\n\t(load_fcn_from_file, frob_function): Handle autoloading.\n\t(lookup_autoload): New function.\n\t(get_help_from_file): New args, symbol_found and include_file_info.\n\tChange all callers.\n\n2005-10-05  David Bateman  <dbateman@free.fr>\n\n\t* help.cc (try_info): format in command string for mingw.\n\n2005-09-30  John W. Eaton  <jwe@octave.org>\n\n\t* ov.cc (octave_value::~octave_value): No need to set rep to zero\n\tafter deleting.\n\n2005-09-29  John W. Eaton  <jwe@octave.org>\n\n\t* syscalls.cc (mk_stat_map): Store mode too.\n\t(FS_ISREG, FS_ISDIR, FS_ISCHR, FS_ISBLK, FS_ISFIFO, FS_ISLNK,\n\tFS_ISSOCK): New functions.\n\t(Fstat): Fix docstring.\n\n2005-09-28  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (printf_value_cache::double_value): Force\n\tcharacter strings to be converted to ASCII equivalents.\n\n\t* data.cc (Fcomplex): New function.\n\n\t* ov-type-conv.h (OCTAVE_TYPE_CONV_BODY3): Return arg unchanged if\n\tclass name is same as name of conversion.\n\n\t* dirfns.cc (Frmdir, Fmkdir): For compatibility, return true for\n\tsuccess and false for failure.  Return third value, msgid.\n\t(Frmdir): Handle second arg for recursive behavior.\n\n2005-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (load_fcn_from_file): Don't look in path if file is\n\tabsolute and has .oct or .m extension.\n\n\t* utils.cc (Ferrno_list): New function.\n\n\t* oct-errno.h, oct-errno.cc.in: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\t(oct-errno.cc): New rule.\n\t($(OPT_HANDLERS)): Use $(PERL) instead of just perl.\n\n\t* utils.cc: Include oct-errno.h.\n\t(Ferrno): Rename from FERRNO.  Allow errno to be set.  Allow\n\tlookups of errno codes by name and access to structure containing\n\tall errno names and codes.\n\n2005-09-19  John W. Eaton  <jwe@octave.org>\n\n\t* pt-bp.cc (tree_breakpoint::visit_index_expression):\n\tAvoid dereferencing invalid pointer.\n\n2005-09-19  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (OCT_LINK_DEPS): Include UFsparse libraries.\n\n\t* DLD_FUNCTIONS/__glpk__.cc (F__glpk__): Replace isinf with\n\txisinf. Allow sparse matrices as second argument.\n\n\t* syscalls.cc: Typos.\n\t* sysdep.cc: Typos.\n\n2005-09-16  John W. Eaton  <jwe@octave.org>\n\n\t* syscalls.cc (Fwaitpid): Doc fix.  Expect WNOHANG, WUNTRACED,\n\tWCONTINUED as args instad of int values.\n\tReturn values are now [pid, status, msg] instad of [pid, msg].\n\t(WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP,\n\tWIFSTOPPED, WSTOPSIG, WIFCONTINUED): New functions.\n\t(symbols_of_syscalls): DEFCONST WNOHANG, WUNTRACED, and WCONTINUE.\n\n\t* oct-procbuf.cc (octave_procbuf::close): Call octave_syscalls::waitpid\n\there instead of calling waitpid directly.\n\t* sighandlers.cc (OCL_REP::wait): Likewise.\n\n\t* sysdep.h [__MINGW32__]: Don't define waitpid here.\n\n2005-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* sysdep.h [__MINGW32__]: Move to definition of waitpid sysdep.h.\n\n\t* sysdep.cc, sighandlers.cc: Rename all win32_ symbols to w32.\n\n\t* sysdep.cc (w32_set_quiet_shutdown): New function.\n\t* sysdep.h: Provide decl.\n\t* sysdep.cc (MINGW_signal_cleanup): Use it.\n\t* sighandlers.cc (octave_catch_interrupts): Use it.\n\n\t* sysdep.h: Provide decl.\n\t(MINGW_SIGNAL_CLEANUP): New macro.\n\t(USE_W32_SIGINT): Move definition here.\n\t* sighandlers.cc: From here.\n\n\t* DLD-FUNCTIONS/cellfun.cc (Fnum2cell): Use print_usage, not usage.\n\t* DLD-FUNCTIONS/colamd.cc (Fcolamd, Fsymamd, Fetree): Likewise.\n\t(Fcolamd, Fsymamd) [! HAVE_COLAMD]: Return empty octave_value_list\n\tobject.\n\n\t* sysdep.cc (sysdep_cleanup): New function.\n\tMove w32 clean up code here.\n\t* toplev.cc (clean_up_and_exit): From here.\n\tCall sysdep_cleanup here.\n\n2005-09-15  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in (DLD_XSRC): Add ccolamd.cc\n\t(OCTAVE_LIBS): Add LIBGLOB.\n\t(OCT_LINK_DEPST, octave): Add AMD, COLAMD, CCOLAMD and CHOLMOD\n\tlibraries.\n\t* default.cc (set_default_exec_path, set_default_path,\n\tmaybe_add_default_load_path, LOADPATH): Use SEPCHAR_STR and SEPCHAR.\n\t* help.cc (display_help_text): Exclude /dev/null on mingw.\n\t* oct-procbuf.cc (W32POPEN, W32PCLOSE): Macros for cygwin/mingw.\n\t(octave_procbuf::open, octave_probuf::close): Use them.\n\t* sighandler.cc (user_abort): New function with core of old\n\tsigint_handler.\n\t(sigint_handler): Simplify and specialize for w32.\n\t(w32_sigint_handler): W32 version of sigint handler.\n\t(octave_catch_interrupts): Initialize w32 siginit handler.\n\t* sysdep.cc (MINGW_init): New function.\n\t(sysdep_init): Use it.\n\t* toplev.cc (clean_up_and_exit): Clean w32 signalling shutdown.\n\t* DLD-FUNCTIONS/cellfun.cc (Fnum2cell): New function.\n\t* DLD-FUNCTIONS/colamd.cc (Fcolamd, Fsymamd): Allow conditional build.\n\tInclude oct-sparse.h rather than colamd.h.\n\t* DLD-FUNCTIONS/ccolamd.cc: New file with Fccolamd a Fcsymamd.\n\n2005-09-14  John W. Eaton  <jwe@octave.org>\n\n\t* ov-complex.cc (octave_complex::try_narrowing_conversion):\n\tDon't drop -0i.\n\t* ov-cx-mat.cc (octave_complex_matrix::try_narrowing_conversion):\n\tLikewise.\n\n2005-09-14  Daniel  <durbano@shbano.com>\n\n\t* DLD-FUNCTIONS/besselj.cc, DLD-FUNCTIONS/chol.cc,\n\tDLD-FUNCTIONS/fft.cc, DLD-FUNCTIONS/fftw_wisdom.cc, utils.cc:\n\tDoc string fixes.\n\tFrom Jorge Barros de Abreu <ficmatin01@solar.com.br>.\n\n2005-09-14  David Bateman  <dbateman@free.fr>\n\n\t* help.cc (Flookfor, print_lookfor, first_help_sentence):\n\tNew functions.\n\n2005-09-07  Bill Denney  <denney@seas.upenn.edu>\n\n\t* dirfns.cc (Fglob): Doc fix.\n\n2005-09-07  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (Fstruct): Allow struct (zeros (0, N)) to create a\n\t0xN struct array.\n\n2005-09-04  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/colamd.c (COLAMD_NAME, SYMAMD_NAME): New macros\n\t(symetree, make_set, link, finf, etdfs, TreePostorder, coletree,\n\tFcolamd, Fsymamd, Fetree): Update for 64-bit indexing and colamd\n\tversin 2.4.\n\n2005-09-01  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (symbol_out_of_date): Don't check nested functions.\n\n2005-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.cc (Octave_map::index): Don't crash if index list is empty.\n\t* ov-str-mat.cc (octave_char_matrix_str::do_index_op_internal):\n\tLikewise.\n\n\t* oct-map.h (Octave_map::ndims): New function.\n\n2005-08-30  John W. Eaton  <jwe@octave.org>\n\n\t* ov-range.h (octave_range::permute): New function.\n\n\t* ov-struct.cc (octave_struct::load_ascii,\n\toctave_struct::load_binary, octave_struct::load_hdf5): Try harder\n\tto read old-style files correctly.\n\n2005-08-25  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-sm-m.cc, OPERATORS/op-sm-cm.cc, OPERATORS/op-scm-m.cc,\n\tOPERATORS/op-scm-cm.cc, OPERATORS/op-m-sm.cc, OPERATORS/op-m-scm.cc,\n\tOPERATORS/op-cm-sm.cc, OPERATORS/op-cm-scm.cc: Use mixed matrix/sparse\n\tmultiply operator rather than casting sparse to matrix.\n\n2005-07-18  John W. Eaton  <jwe@octave.org>\n\n\t* strfns.cc (Fstrcmp): New function from Søren Hauberg\n\t<soren@hauberg.org> and Tom Holroyd <tomh@kurage.nimh.nih.gov>.\n\tAdapt to Octave conventions.\n\n2005-07-11  David Bateman  <dbateman@free.fr>\n\n\t* ov-fc-inline.cc (Fvectorize): Allow string arguments\n\n2005-07-08  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gplot.l (Fhold, Fishold): Delete.\n\t(clear_before_plotting): Delete static variable.\n\tDelete PKG_ADD line for hold.\n\n2005-07-07  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (pr_plus_format): Delete \"static\" from template decl.\n\n\t* oct-stream.cc (octave_scan): Delete explicit instantiation of\n\toctave_scan<double> since a specialization is provided.\n\n\t* DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): Include\n\t<algorithm>, for std::transform decl.  Use std qualifier for\n\ttransform and tolower.\n\n2005-07-05  Antoine Moreau  <antoine.moreau@univ-bpclermont.fr>\n\n\t* DLD-FUNCTIONS/betainc.cc (Fbetainc): Fix doc string to match\n\tfunction definition..\n\n2005-07-05  Mats Jansson  <mats.e.jansson@home.se>\n\n\t * file-io.cc (Fmkstemp): Check if second argument is true\n\t before marking file for deletion.\n\n2005-07-05  John W. Eaton  <jwe@octave.org>\n\n\t* ov-str-mat.cc (octave_char_matrix_str::do_index_op_internal):\n\tRename from char_matrix_str::do_index_op.  New arg, type.\n\tov-str-mat.h (octave_char_matrix_str::do_index_op): Define using\n\tdo_index_op_internal.\n\t(octave_char_matrix_sq_str::do_index_op): New function.\n\n2005-07-01  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (end_error): Also handle end_try_catch case.\n\n2005-06-17  John W. Eaton  <jwe@octave.org>\n\n\t* help.cc (help_from_list, help_from_symbol_table,\n\thelp_from_file): New arg, symbol_found.\n\t(builtin_help): Use symbol_found arg to determine whether help\n\ttext is empty or symbol is not available.\n\n\t* symtab.cc (symbol_record::print_info): Print more info.\n\n\t* DLD-FUNCTIONS/dispatch.cc (Fdispatch_help): Delete.\n\t(dispatch_record): Don't prepend \"<>\" to help text.\n\t(Fdispatch): Don't setup dispatched help.\n\n\t* help.cc (extract_help_from_dispatch): New function.\n\t(help_from_symbol_table): Use it.\n\t* defun.cc (print_usage): Use it.\n\n\t* toplev.cc (octave_config_info): Include localapifcnfiledir and\n\tlocalapioctfiledir in the list.\n\n\t* symtab.h (symbol_record::alias): New arg, mark_to_clear.\n\t(symbol_record::aliases_to_clear): New data member.\n\t(symbol_record::push_alias_to_clear): New function.\n\t* symtab.cc (symbol_record::alias): If mark_to_clear is true, push\n\tthis pointer on aliases_to_clear stack for s.\n\t(symbol_record::clear): Also clear aliases_to_clear_stack.\n\n\t* defun.cc (install_dld_function): Create full file name alias in\n\tfbi_sym_tab and hide it from view.\n\tDon't call protect or make_eternal on sym_rec.\n\n\t* variables.cc (fcn_out_of_date): New function.\n\t(symbol_out_of_date): Also check for symbol using full function\n\tfile name.\n\n\t* symtab.h (symbol_record::visible): New data member.\n\t(symbol_record::hide, symbol_record::show, symbol_record::is_visible):\n\tNew functions.\n\n\t* symtab.h (symbol_record::maybe_delete_def): New private function.\n\t* symtab.cc (symbol_record::clear, symbol_record::alias,\n\tsymbol_record::pop_context,\n\tsymbol_record::define (octave_function *, unsigned int)): Use it.\n\t(symbol_table::symbol_list): Only include visible symbols in list.\n\n\t* parse.y (frob_function): Hide nested function names.\n\n\t* parse.y (frob_function): Create full file name alias in\n\tfbi_sym_tab and hide it from view.\n\t* defun.cc (install_dld_function): Likewise.\n\n2005-06-16  John W. Eaton  <jwe@octave.org>\n\n\t* ov-dld-fcn.cc (octave_dld_function): Check Voct_file_dir to see\n\tif function is system file, Vfcn_file_dir.\n\t* defaults.cc (set_default_oct_file_dir): New function.\n\t(install_defaults): Call it.\n\t(Voct_file_dir): New global variable.\n\t* defaults.h.in (Voct_file_dir): Provide decl.\n\n\t* variables.cc (function_out_of_date_internal): Use\n\tVignore_function_time_stamp only to avoid calling stat.\n\t(symbol_out_of_date): Don't check Vignore_function_time_stamp here.\n\t(function_out_of_date): Rename from function_out_of_date_internal.\n\n\t* defaults.cc (loadpath): Don't do anything if value is unchanged.\n\tIf loadpath changes, also update Vlast_prompt_time.\n\n2005-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* pt-mat.cc (Vwarn_string_concat): Default value now false.\n\t(symbols_of_pt_mat): Change initial value here as well.\n\n\t* ls-mat5.cc, mappers.cc, oct-stream.cc, pr-output.cc: Change all\n\tuses of octave_is_NaN_or_NA to xisnan.\n\n2005-06-14  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* input.cc (get_user_input): Renamed debug commands to dbnext,\n\tdbstep, and dbcont.\n\t* pt.cc: Renamed dbg_next to dbnext in comment string.\n\t* pt.h: Renamed dbg_next to dbnext in comment string.\n\n2005-06-14  David Bateman  <dbateman@free.fr>\n\n\t* pt-arg-list.cc (F__end__): Return 1 for dimensions larger than ndim.\n\n2005-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (save_mat5_array_length): Special case for NaN, NA,\n\tand Inf values.  Only check if abs value is greater than FLT_MAX.\n\n2005-06-09  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat5.cc (save_mat5_element_length): 1 element strings will be\n\tsaved in a compressed format, so calculate the length accordingly.\n\n2005-05-30  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat5.cc (read_mat5_binary_element): Don't convert to string\n\tif matrix is not of type mxCHAR_CLASS.\n\n2005-05-23  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (Ffopen): Don't fail with internal error message if\n\twe fail to create a valid stream object.\n\t(do_stream_open (const std::string&, const std::string&,\n\tconst std::string&, int&): Always create octave_stream object,\n\teven if file pointer returne from fopen is 0.\n\n\t* load-save.cc (gripe_file_open): New function.\n\t(get_file_format, Fload, Fsave): Use it.\n\n\t* DLD-FUNCTIONS/sort.cc (mx_sort, mx_sort_indexed): Return\n\tappropriately sized empty values for empty args.\n\n\t* debug.cc (Fdbwhere, get_user_function): Look at\n\tcurr_caller_function, not curr_function, since function is now set\n\tinside mapper, built-in (and therefore dld) functions too.\n\n2005-05-21  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc, pr-output.h (Vprint_empty_dimensions): Now extern.\n\t* ov-cell.cc (octave_cell::print_raw): Conditionally print\n\tdimensions of empty 2-d cell arrays.\n\n\t* DLD-FUNCTIONS/sort.cc (mx_sort, mx_sort_indexed): Return empty\n\tvalues for empty args.\n\n\t* lex.l (handle_string): If single-quote string, \\ and . have no\n\tspecial meaning.\n\n2005-05-18  John W. Eaton  <jwe@octave.org>\n\n\t* pt-colon.cc (tree_colon_expression::make_range): Don't require\n\tscalars values as range components.\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.3\n\t(OCTAVE_API_VERSION): Now api-v16.\n\n\t* ov-base-sparse.cc (octave_base_sparse<T>::print_raw):\n\tMake spacing of output consistent with other parts of Octave.\n\n\t* DLD-FUNCTIONS/rand.cc (do_rand): Chop trailing singelton\n\tdimensions before generating array.\n\n2005-05-17  John W. Eaton  <jwe@octave.org>\n\n\t* ov.cc (install_types): Don't call octave_stream::register_type.\n\t* ov.h, ov.cc (octave_value::octave_value (const octave_stream&,\n\tint): Delete constructor.\n\t(octave_value::is_stream, octave_value::stream_value,\n\toctave_value::stream_number): Delete functions.\n\t* ov-base.h (octave_base_value::is_stream): Delete function.\n\t* ov-base.h, ov-base.cc (octave_base_value::stream_value,\n\toctave_base_value::stream_number): Delete functions.\n\t* file-io.cc (Fisstream): Delete function.\n\t* op-file.h, op-file.cc, OPERATORS/op-fil-sbm.cc,\n\tOPERATORS/op-fil-scm.cc, OPERATORS/op-fil-sm.cc,\n\t* OPERATORS/op-fil-b.cc, OPERATORS/op-fil-bm.cc,\n\tOPERATORS/op-fil-cm.cc, OPERATORS/op-fil-cs.cc,\n\tOPERATORS/op-fil-m.cc, OPERATORS/op-fil-s.cc,\n\tOPERATORS/op-fil-lis.cc, OPERATORS/op-fil-rec.cc,\n\tOPERATORS/op-fil-str.cc: Delete files.\n\t* Makefile.in (OP_XSRC, SPARSE_OP_XSRC): Delete op-fil-*.cc from\n\tthe lists.\n\t(OV_INCLUDES): Delete op-file.h from the list.\n\t(OV_SRC): Delete op-file.cc from the list.\n\t* oct-stream.cc, oct-stream.h (octave_stream_list::insert,\n\toctave_stream_list::do_insert): Return stream number instead of\n\toctave_value.\n\n2005-05-16  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat.cc (save_mat5_binary_element): Increase size of\n\tcompression buffer.\n\t(load_mat5_binary_element): Allow ASCII encoded as UTF8,\n\tand give error messages for multi-byte UTF8 and UTF16 and UTF32\n\tencodings.\n\n\t* ls-hdf5.h (H5T_NATIVE_IDX): New macro defining native indexing\n\ttype for HDF5 files\n\n\t* ls-hdf5.cc (save_hdf5_empty, load_hdf5_empty): Use\n\tH5T_NATIVE_IDX to allow 64-bit indexing.\n\t* ov-bool-sparse.cc (save_hdf5, load_hdf5): ditto.\n\t* ov-re-sparse.cc (save_hdf5, load_hdf5): ditto.\n\t* ov-cx-sparse.cc (save_hdf5, load_hdf5): ditto.\n\t* ov-cell.cc (save_hdf5, load_hdf5): ditto.\n\n\t* load-save.cc (parse_save_options): Remove -nozip option.\n\t(Fsave): If user defines file format, ignore completely the default\n\tfile format options.\n\n2005-05-12  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (oct-gperf.h): Try harder to cause Make to exit here\n\tif gperf is missing or fails to create a valid file.\n\n2005-05-10  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (<MATRIX_START>{SNLCMT}*\\]{S}*): If whitespace was gobbled,\n\tunput SPC before returning the token.\n\t(<MATRIX_START>{SNLCMT}*\\}{S}*): Likewise.\n\n2005-05-09  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (except_command): Make catch clause optional in try\n\tstatements.\n\t* pt-except.cc (tree_try_catch_command::eval):\n\tAlways buffer error messages.\n\n2005-05-06  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (octave_struct::save_ascii,\n\toctave_struct::save_binary, octave_sruct::save_hdf5):\n\tAlways save cell array.\n\t(octave_struct::load_ascii, octave_struct::load_binary,\n\toctave_sruct::load_hdf5): Try to read old-style files correctly.\n\n\t* DLD-FUNCTIONS/__qp__.cc (qp): Use chol2inv to compute inverse\n\tfrom Cholesky factors.\n\t(cholinv): Delete.\n\n\t* DLD-FUNCTIONS/chol.cc (Fcholinv): New function.\n\t(Fchol2inv): New function.\n\n2005-05-05  Keith Goodman  <kwgoodman@gmail.com>\n\n\t* ov-usr-fcn.cc\t(Fnargout, Fnargin): Update doc strings.\n\t* help.cc (keywords): Update doc strings for varargin, varargout.\n\n2005-05-05  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (BEGIN_S_CONVERSION): Correctly handle width\n\tspecifiers.\n\n2005-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (read_mat5_binary_element): Implement reading of N-d\n\tstructure arrays.\n\n\t* ov-struct.cc (octave_struct::load_hdf5,\n\toctave_struct::load_binary, octave_struct::load_ascii): Assign\n\tcell_value to map slot, not octave_value containing the cell.\n\n2005-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* error.cc (Flasterr): Don't access argv if an error occurs when\n\tcreating it.\n\n\t* mkgendoc (main): Print header message.\n\n2005-05-02  Bill Denney  <denney@seas.upenn.edu>\n\n\t* data.cc, defaults.cc, DLD-FUNCTIONS/qz.cc, file-io.cc,\n\tsighandlers.cc, syscalls.cc: Docstring fixes.\n\n2005-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (octave_print_internal (std::ostream&,\n\tconst Range&, bool, int)): Don't print newline at end of broken\n\trows (that is handled by pr_col_num_header).\n\tFrom Keith Goodman <kwgoodman@gmail.com>.\n\n\t* Makefile.in (octave$(EXEEXT)): List $(UMFPACK_LIBS) ahead of\n\t$(BLAS_LIBS).\n\t(OCTAVE_LIBS): Include $(GLPK_LIBS) in the list if dynamic linking\n\tis not enabled.\n\tFrom Dmitri A. Sergatskov <dasergatskov@gmail.com>.\n\n2005-05-02  John W. Eaton  <jwe@octave.org>\n\n\t* oct-map.h, oct-map.cc (Octave_map::seek, Octave_map::contents):\n\tNew non-const versions.\n\t(Octave_map::assign (const octave_value_list&,\n\tconst std::string&, const Cell&)): Allow both tmp RHS and LHS to\n\tbe resized.  For clarity, always resize to new_dims.\n\n2005-05-02  David Bateman  <dbateman@free.fr>\n\n\t* ov-re-sparse.cc, ov-cx-sparse.cc (load_binary): read save_type into\n\tone byte variable.\n\n2005-04-29  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (DO_LITERAL_CONVERSION): Cast fmt[i] to unsigned\n\tchar for comparison.\n\n\t* c-file-ptr-stream.h (c_file_ptr_stream): New template class,\n\tconverted from i_c_file_ptr_stream.\n\t(i_c_file_ptr_stream, o_c_file_ptr_stream, io_c_file_ptr_stream):\n\tNow typedefs.\n\t(i_c_zfile_ptr_stream, o_c_zfile_ptr_stream, io_c_zfile_ptr_stream):\n\tNew typedefs.\n\t* c-file-ptr-stream.h, c-file-ptr-stream.cc (c_zfile_ptr_buf):\n\tNew class.\n\n\t* oct-stdstrm.h (class octave_tstdiostream): New template class,\n\tconverted from octave_stdiostream.\n\t(octave_stdiostream): Now a typedef.\n\t[HAVE_ZLIB] (octave_zstdiostream): New a typedef.\n\t* oct-stdstrm.cc: Delete.\n\t* Makefile.in (DIST_SRC): Remove it from the list.\n\n2005-04-29  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in: Add matrix_type.cc and spkron.cc to DLD_XSRC.\n\n\t* ls.mat.cc (read_mat5_binary_element): Allow for endian change\n\tfor compressed data elements.\n\n\t* ov-base-sparse.cc (assign): Invalidate matrix type.\n\n\t* ov-base-sparse.cc (SparseType sparse_type (void),\n\tSparseType sparse_type (const SparseType&):\n\tFunctions to read and set sparse matrix type.\n\n\t* ov-bool-sparse.cc (load_binary): Remove third argument.\n\t(load_hdf5): Cast hsize_t comparisions with int to avoid warning.\n\t* ov-cx-sparse.cc (load_hdf5): Ditto.\n\t* ov-re-sparse.cc (load_hdf5): Ditto.\n\n\t* ov-re-sparse.cc (convert_to_str_internal): Add third argument\n\tfor string type.\n\t* ov-re-sparse.h (convert_to_str_internal): Adject declaration.\n\n\t* sparse-xdiv.cc (xdiv, xleftdiv): Pass SparseType as third\n\targument, use it and return it to allow caching of type.\n\t* sparse-xdiv.h (xdiv, xleftdiv): Change declarations for third\n\targument of type SparseType.\n\n\t* DLD-FUNCTIONS/luinc.cc (Fluinc): Use type_name and not\n\tclass_name to test for real/complex sparse matrices.\n\tSet matrix type.\n\n\t* DLD-FUNCTIONS/splu.cc (Fsplu): Set matrix type.\n\n\t* OPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc,\n\tOPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc,\n\tOPERATORS/op-m-scm.cc, OPERATORS/op-m-sm.cc,\n\tOPERATORS/op-s-scm.cc, OPERATORS/op-s-sm.cc,\n\tOPERATORS/op-scm-cm.cc, OPERATORS/op-scm-cs.cc,\n\tOPERATORS/op-scm-m.cc, OPERATORS/op-scm-s.cc,\n\tOPERATORS/op-scm-scm.cc, OPERATORS/op-scm-sm.cc,\n\tOPERATORS/op-sm-cm.cc, OPERATORS/op-sm-cs.cc,\n\tOPERATORS/op-sm-m.cc, OPERATORS/op-sm-s.cc,\n\tOPERATORS/op-sm-scm.cc, OPERATORS/op-sm-sm.cc (div, ldiv):\n\tPass and recache SparseType wirh xdiv/xleftdiv.\n\n2005-04-29  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (maybe_warn_interface_change): Delete function.\n\t(fopen_mode_to_ios_mode): Don't call it.\n\n2005-04-27  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::subsref):\n\tCheck whether function referenced by handle is out of date.\n\t(Ffunctions): Tag nameless user function as \"command-line\".\n\n\t* variables.cc (symbol_out_of_date (octave_fucntion *)): New function.\n\t(function_out_of_date): New function.\n\t* parse.y (load_fcn_from_file (const std::string&, bool)):\n\tNew function.\n\n\t* DLD-FUNCTIONS/gplot.l (gnuplot_init): New function to handle\n\tinitialization.  If builtin variables have already been installed,\n\tsimply update our cached values.\n\t(F__gnuplot_init__): Call gnuplot_init to do all the real work.\n\t(Fclearplot, Fcloseplot, Fhold, Fishold, Fpurge_tmp_files,\n\tF__gnuplot_raw__, F__gnuplot_set__, F__gnuplot_plot__,\n\tF__gnuplot_splot__, F__gnuplot_replot__, Fgplot, Fgsplot, Fgraw,\n\tFgset, Fgshow): Call gnuplot_init before doing anything.\n\n\t* parse.y: (safe_fclose): Delete comment list to avoid memory leak.\n\t(parse_and_execute (FILE *)): Also save and restore global_command.\n\n2005-04-26  John W. Eaton  <jwe@octave.org>\n\n\t* mkbuiltins (VAR_FILES): Expect $(VAR_FILES) to have .df suffix.\n\n\t* Makefile.in (clean): Also remove $(DLD_PICOBJ).\n\tUse mk-oct-links --delete to remove links to .oct files.\n\tRemove $(DOC_FILES) not $(DEF_FILES) and $(VAR_FILES).\n\n\t* mk-oct-links (mk-oct-links): Handle --delete option.\n\tRename -p option to be --print.  Skip nonexistent .df files.\n\n2005-04-25  John W. Eaton  <jwe@octave.org>\n\n\t* oct-hist.cc (default_history_file, default_history_size): Now static.\n\t* oct-hist.h: Delete decls.\n\n\t* oct-hist.cc (default_history_timestamp_format,\n\tdefault_history_timestamp_format): New functions.\n\t(Vdefault_history_timestamp_format): New variable.\n\t(symbols_of_oct_hist): DEFVAR it.\n\t(octave_history_write_timestamp): New function.\n\t* oct-hist.h (octave_history_write_timestamp): Provide decl.\n\t* toplev.cc (): call octave_history_write_timestamp here.\n\t* octave.cc (maximum_braindamage):\n\tBind history_timestamp_format_string here.\n\n2005-04-22  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.9.2.\n\t(OCTAVE_API_VERSION): Now api-v15.\n\n\t* pager.cc (default_pager): Also append -X.\n\n\t* DLD-FUNCTIONS/dispatch.cc (Fdispatch): Dispatch help on \"string\"\n\tand \"sq_string\" types.\n\t(dispatch_record): Add extra space to force new paragraph after\n\teach dispatched function name if we are formatting with Texinfo.\n\tForce noindent of preceding \"Overloaded function:\" tag.\n\n2005-04-21  John W Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (read_mat5_binary_element): Only read sparse matrix\n\tvalues if sizeof (int) == sizeof (octave_idx_type).\n\n\t* DLD-FUNCTIONS/colamd.cc: These functions only work if\n\tsizeof (int) == sizeof (octave_idx_type).\n\n\t* Makefile.in (parse.cc): Expect 14 shift/reduce conflicts.\n\n\t* parse.y (USING TITLE WITH AXES COLON OPEN_BRACE CLEAR):\n\tDelete unused tokens.\n\n\t* DLD-FUNCTIONS/__qp__.cc (qp): Use octave_idx_type where needed.\n\n\t* DLD-FUNCTIONS/__qp__.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n2005-04-20  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (IDENT): Allow $ in identifiers.\n\t* utils.cc (valid_identifier): Likewise.\n\n2005-04-19  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (Fsystem): Move enum exec_type declaration to file\n\tscope and rename system_exec_type.  Change all uses.\n\n2005-04-14  David Bateman  <dbateman@free.fr>\n\n\t* load-save.cc (Vdefault_save_format, Voctave_core_file_format):\n\tDelete variables.\n\t(Vdefault_save_options, Voctave_core_file_options): New variables.\n\t(get_save_format): Delete function.\n\t(parse_save_options (const string_vector&, ...),\n\tparse_save_options (const std::string&, ...)): New functions.\n\t(dump_octave_core): Allow save_as_floats to be used.\n\t(dump_octave_core): Parse save options.\n\t(Fsave): Split parsing of options, and default formats.\n\t(default_save_format): Delete function and DEFVAR.\n\t(default_save_options): New function.  DEFVAR it.\n\t(octave_core_file_format): Delete function and DEFVAR.\n\t(octave_core_file_options): New function.  DEFVAR it.\n\n\t* octave.cc (default_save_format): Delete binding\n\t(default_save_options): New bindings\n\n\t* Makefile.in: Add luinc.cc to DLD_XSRC.\n\t* DLD-FUNCTIONS/luinc.cc: New file for incomplete LU factorization.\n\n\t* ov-bool-sparse.h (index_vector): New function.\n\t* ov-re-sparse.cc (index_vector): Ditto.\n\t* ov-re-sparse.h (index_vector): Definition.\n\n\t* ov-mapper.cc (any_element_less_than, any_element_greater_than):\n\tNew versions for SparseMatrix\n\t(SPARSE_MAPPER_LOOP_2, SPARSE_MAPPER_LOOP_1, SPARSE_MAPPER_LOOP):\n\tNew macros.\n\t(octave_mapper::apply): Add special cases for sparse arguments to\n\tthe mapper functions\n\n\t* ov-re-sparse.cc (streamoff_array_value): Use octave_idx_type.\n\t(convert_to_str_internal): New function.\n\t* ov-re-sparse.h (convert_to_str_internal): Definition.\n\n\t* DLD-FUNCTIONS/sparse.cc (Fsparse): More care for nargin=2 case.\n\n\t* DLD-FUNCTIONS/splu.cc (Fsplu): Use octave_idx_type.\n\n2005-04-14  John W. Eaton  <jwe@octave.org>\n\n\t* strfns.cc (Fchar): If arg is a dq string, return a dq string.\n\n\t* pt-mat.cc (Vwarn_string_concat): New static variable.\n\t(symbols_of_pt_mat): DEFVAR it.\n\t(warn_string_concat): New function.\n\t(maybe_warn_string_concat): New function.\n\t(tree_matrix::rvalue): If all args are single quoted strings,\n\tcreate a single quoted string object.  If all args are strings\n\t(any type), create a double quoted string object.  If a mixture of\n\tstring types, maybe warn.\n\t(class tm_row_const, class tm_row_const_rep, class tm_const):\n\tNote whether all values are double or single quoted strings.\n\n\t* ov.h (octave_value::is_dq_string): New function.\n\n2005-04-13  John W. Eaton  <jwe@octave.org>\n\n\t* strfns.cc (Fchar): Create sq_string objects here.\n\n2005-04-12  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (Ffprintf, Fprintf, Fsprintf):\n\tPass octave_value to octave_stream::printf for FMT.\n\t(Fscanf, Fsscanf): Likewise, for octave_stream::scanf and\n\toctave_stream::oscanf.\n\n\t* oct-stream.cc, oct-stream.h (octave_stream::printf,\n\toctave_stream::scanf, octave_stream::oscanf): New versions that\n\taccept an octave_value for FMT.\n\t(octave_stream::puts): New version that accepts octave_value for\n\tvalue to print.\n\t(octave_base_stream::do_scanf): If all_char_conv, force\n\tconversion to string to avoid warning.\n\n\t* ov-str-mat.h, ov-str-mat.cc (octave_char_matrix_sq_str): New class.\n\t(octave_char_matrix_dq_str): New typedef.\n\n\t* ov.h, ov.cc: All string constructors now take type argument.\n\n\t* ov.cc (install_types): Register octave_char_matrix_sq_str.\n\n\t* ov.h (octave_value::convert_to_str): New arg, type.\n\t(octave_value::convert_to_str_internal): Likewise.\n\tChange all derived classes.\n\n\t* ov.h (octave_value::is_sq_string): New predicate.\n\n\t* octave.gperf (__FILE__): Now a DQ_STRING.\n\n\t* ls-mat4.cc (read_mat_binary_data): Force sq strings here.\n\t* ls-mat5.cc (read_mat5_binary_element): And here.\n\n\t* lex.l (<COMMAND_START>[\\;\\,]): Return SQ_STRING, not STRING.\n\t(<COMMAND_START>[^#% \\t\\r\\n\\;\\,\\\"\\'][^ \\t\\r\\n\\;\\,]*{S}*): Likewise.\n\t(handle_string): Type of string to return depends on delimeter.\n\n\t* parse.y (DQ_STRING, SQ_STRING): New token types.\n\t(STRING): Delete token type.\n\t(string): New non-terminal.\n\t(constant): Recognize string here instead of STRING.\n\t(word_list): Likewise.\n\t(opt_sep): Handle DQ_STRING and SQ_STRING.\n\n\t* OPERATORS/op-str-m.cc, OPERATORS/op-str-s.cc,\n\tOPERATORS/op-str-str.cc: Define operators for both sq and dq\n\tstrings.\n\n2005-04-08  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (clean): Use exact filenames instead of *.xxx.\n\tAlso remove PKG_ADD.\n\t(DISTFILES): Add gplot.cc to the list.\n\t(maintainer-clean): Remove gplot.cc here.\n\n\t* Initial merge of 64-bit changes from Clinton Chee:\n\n\t2005-04-07  John W. Eaton  <jwe@octave.org>\n\n\t* ls-oct-ascii.h, ls-oct-ascii.cc (extract_keyword): Now template\n\tfunctions defined in the header file.\n\n\t* ls-mat5.cc, ov-base-sparse.h, ov-base.h, ov-bool-sparse.cc\n\tov-cx-sparse.cc, ov-re-sparse.cc, ov.cc, pt-loop.cc,\n\tsparse-xdiv.cc, sparse-xpow.cc, DLD-FUNCTIONS/sparse.cc,\n\tDLD-FUNCTIONS/spdet.cc:\n\tUse octave_idx_type instead of int where needed.\n\n\t2005-03-31  Clinton Chee  <chee@parallel.hpc.unsw.edu.au>\n\n\t* Cell.cc, Cell.h, data.cc, defaults.cc, dirfns.cc, file-io.cc,\n\tgripes.cc, gripes.h, ls-mat-ascii.cc, ls-mat4.cc, ls-oct-ascii.cc,\n\toct-map.cc, oct-map.h, oct-obj.cc, oct-obj.h, oct-stream.cc,\n\toct-stream.h, octave.cc, ops.h, ov-base-mat.cc, ov-base.h,\n\tov-bool-mat.cc, ov-cell.cc, ov-cs-list.cc, ov-cx-mat.cc,\n\tov-intx.h, ov-list.cc, ov-mapper.cc, ov-range.cc, ov-range.h,\n\tov-re-mat.cc, ov-scalar.h, ov-str-mat.cc, ov-struct.cc, ov.cc,\n\tov.h, pr-output.cc, pt-arg-list.cc, pt-cell.cc, pt-loop.cc,\n\tpt-mat.cc, pt-select.cc, symtab.h, utils.cc, utils.h, xdiv.cc,\n\txpow.cc:\n\tUse octave_idx_type instead of int where needed.\n\n\t2005-04-01  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (octave_config_info): Add USE_64_BIT_IDX_T to the list.\n\t* oct-conf.h.in (OCTAVE_CONF_USE_64_BIT_IDX_T): Substitute here.\n\n\t2005-03-31  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/sort.cc: Don't use unsigned int for index into\n\tdim_vector, or cast dim to unsigned int.\n\t(Fsort): No need to cast arg before asking for dims.\n\n\t* DLD-FUNCTIONS/gcd.cc (Fgcd): Use OCTAVE_LOCAL_BUFFER to allocate\n\tlocal array of NDArray objects.\n\n\t2005-03-31  Clinton Chee  <chee@parallel.hpc.unsw.edu.au>\n\n\t* DLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/besselj.cc,\n\tDLD-FUNCTIONS/chol.cc, DLD-FUNCTIONS/colloc.cc,\n\tDLD-FUNCTIONS/daspk.cc, DLD-FUNCTIONS/dasrt.cc,\n\tDLD-FUNCTIONS/dassl.cc, DLD-FUNCTIONS/det.cc,\n\tDLD-FUNCTIONS/eig.cc, DLD-FUNCTIONS/expm.cc, DLD-FUNCTIONS/fft.cc,\n\tDLD-FUNCTIONS/fft2.cc, DLD-FUNCTIONS/fftn.cc,\n\tDLD-FUNCTIONS/fftw_wisdom.cc, DLD-FUNCTIONS/filter.cc,\n\tDLD-FUNCTIONS/find.cc, DLD-FUNCTIONS/fsolve.cc,\n\tDLD-FUNCTIONS/gcd.cc, DLD-FUNCTIONS/hess.cc, DLD-FUNCTIONS/inv.cc,\n\tDLD-FUNCTIONS/kron.cc, DLD-FUNCTIONS/lu.cc,\n\tDLD-FUNCTIONS/minmax.cc, DLD-FUNCTIONS/quad.cc,\n\tDLD-FUNCTIONS/qz.cc, DLD-FUNCTIONS/rand.cc,\n\tDLD-FUNCTIONS/schur.cc, DLD-FUNCTIONS/sort.cc,\n\tDLD-FUNCTIONS/sqrtm.cc, DLD-FUNCTIONS/svd.cc,\n\tDLD-FUNCTIONS/syl.cc:\n\tUse octave_idx_type instead of int where needed.\n\n2005-04-06  David Bateman  <dbateman@free.fr>\n\n\t* Makefile.in: Link to UMFPACK_LIBS. Add zfstream.{cc,h} to build and\n\tdist files.\n\n\t* zfstream.cc: New file for C++ binding for fstream like class for\n\tzlib.\n\n\t* zfstream.h: Definition for fstream like C++ bindings to zlib.\n\n\t* load-save.cc (static bool check_gzip_magic (const std::string&)):\n\tNew function to look for GZIP magic\n\t(static load_save_format get_file_format (const istream &file)): New\n\tfunction split from old get_file_format but passed istream to allow\n\tuse with zlib istream.\n\t(static load_save_format get_file_format (const std::string&,\n\tconst std::string&, bool)): Modify the test uncompressed file first,\n\tthen compressed version\n\t(Fload) Allow -v6, -6, -v7 and -7 options. Split load code to allow\n\tuse of zlib.\n\t(Fsave) Allow -zip, -z, -v6, -6, -v7 and -7 options. Split save code\n\tto allow use of zlib.\n\n\t* load-save.h: add LS_MAT7_BINARY to load_save_format enum\n\n\t* ls-mat5.cc (read_mat5_binary_element): Test for miCOMPRESSED flag for\n\tmatlab v7 files, and decompress data in memory. Allow reading of matlab\n\tlogical variables either in mxDOUBLE_CLASS or mxUINT8_CLASS.\n\t(int save_mat5_array_length(const double*, ...): New function to\n\tcalculate number of bytes used to save NDArray.\n\t(int save_mat5_array_length(const Complex*, ...): New function to\n\tcalculate number of bytes used to save ComplexNDArray.\n\t(int save_mat5_element_length): New function to find number of bytes\n\tneeded to save data element.\n\t(save_mat5_binary_element): New input arguments, mat7_format and\n\tcompressing, that define if we are in a matlab v7 format and where we\n\tare currently compressing the data element. If mat7_format use\n\tmiCOMPRESSED flag for matlab v7 files, and compress data in memory.\n\tAdd capability to save logical variables as mxUINT8_CLASS. If v7\n\tformat maximum variable length is 63 characters and not 31. Use the\n\tsave_mat5_element_length function to pre-calculate the number of bytes\n\ttaken by a variable rather than use a negative seek to correct after\n\twriting (zlib can't do negative seeking)\n\n\t* ls-mat5.h: Add to miCOMPRESSED, miUTF8, miUTF16 and miUTF32 flags to\n\tthe enum mat5_data_type.\n\t(save_mat5_binary_element): Add args mat7_format and compressing to the\n\tdefinition.\n\n2005-04-06  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-scm-scm.cc: Delete #pragma implementation.\n\n2005-04-05  John W. Eaton  <jwe@octave.org>\n\n\t* ov-ch-mat.h (octave_char_matrix::index_vector): New function.\n\n\t* oct-stream.cc (BEGIN_C_CONVERSION): Clear stream state if\n\twe hit EOF after we read something.\n\n\t* pt-assign.cc (tree_multi_assignment::rvalue):\n\tAllow assignments of the form [a,b,c] = x{:}.\n\n2005-03-30  John W. Eaton  <jwe@octave.org>\n\n\t* mappers.cc (install_mapper_functions): Use std:: as needed.\n\t* defun-int.h (DEFUN_MAPPER_INTERNAL): Don't use X_CAST on\n\tfunction pointer args.\n\n\t* ov-complex.cc, ov-cx-mat.cc, xpow.cc, ls-mat5.cc: Use std:: for\n\tComplex functions instead of relying on wrappers from oct-cmplx.h.\n\n\t* oct-stream.cc (octave_scan): Initialize c1 to EOF.\n\n2005-03-29  John W. Eaton  <jwe@octave.org>\n\n\t* utils.cc (get_dimensions): Produce error instead of warning if\n\tgiven a matrix argument.\n\n\t* load-save.cc (Fload, Fsave): Also accept -V4 option.\n\n\t* ls-hdf5.h (hdf5_fstreambase::hdf5_fstreambase,\n\thdf5_fstreambase::open): Use & instead of == to test whether mode\n\tis std::ios::in or std::ios::out.\n\t(hd5_ifstream::istream, hd5_ifstream::open, hd5_ofstream::istream,\n\thd5_ofstream::open): Default mode now includes binary flag.\n\n2005-03-28  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_stream::write): For compatibility, Write\n\tzeros instead of seeking if SKIP is nonzero.\n\n\t* DLD-FUNCTIONS/gplot.l (Fgraw): Recommend __gnuplot_raw__, not\n\t__gnuplot__raw__.\n\t(Fgshow): Recommend __gnuplot_show__, not __gnuplot__show__.\n\tDon't add \"mark_as_rawcommand (\"replot\")\" to PKG_ADD file.\n\n2005-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (gnu_readline): Don't wrap call to command_editor::readline\n\twith {BEGIN,END}_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE.\n\n2005-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (main_loop): Don't use octave_set_current_context here.\n\n\t* pt-loop.cc (simple_for_loop::eval): In for i = matrix ... end,\n\tskip loop if matrix is empty.  Likewise for cell arrays.\n\n2005-03-24  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Texinfoize doc string.\n\n\t* Makefile.in (install-oct): Always create $(octfiledir) and\n\tinstall PKG_ADD file there.\n\n\t* octave.cc (octave_main): Fix logic in test for exit after\n\tevaluating --eval option code.\n\n2005-03-23  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Require 9 arguments.\n\tPrint error messages and return early if value extractions fail.\n\tDefault for message level now 0.\n\tRename local variable error to be errnum.\n\t(glpk_fault_hook): Call message instead of writing to octave_stderr.\n\t(glpk_fault_hook): Call error instead of writing to octave_stderr.\n\t(glpk): Likewise.\n\tDeclare mark static.  Delete declaration of fperr.\n\t(glpk): Delete unnecessary casts.\n\n\t* DLD-FUNCTIONS/__glpk__.cc (OCTAVE_GLPK_GET_REAL_PARAM,\n\tOCTAVE_GLPK_GET_INT_PARAM): New macros.\n\t(F__glpk__): Use them.\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Accept lpsolver and\n\tsave_pb in param arg instead of as separate args.\n\tArg list now matches new interface for glpk.m.\n\tDon't return lambda and redcosts fields in extra if isMIP.\n\n\t* toplev.cc (do_octave_atexit): Call reset_error_handler before\n\teach call to feval.\n\n2005-03-22  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in: Add special rule for __glpk__.oct.\n\n\t* toplev.cc (octave_config_info): Add GLPK_LIBS to the list.\n\t* oct-conf.h.in (OCTAVE_CONF_GLPK_LIBS): Substitute here.\n\n\t* DLD-FUNCTIONS/__glpk__.cc (F__glpk__, glpk):\n\tAdapt to Octave coding style.\n\t(glpk): Move decls closer to first use.\n\t(F__glpk__): Eliminate unnecessary loop seting inf values.\n\tEnsure that isMIP is initialized.\n\tDeclare sense, nz, and isMIP volatile to avoid GCC warnings that\n\tthese variables might be might be clobbered by `longjmp' or `vfork'\n\n\t* DLD-FUNCTIONS/__glpk__.cc: New file.\n\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n2005-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (maximum_braindamage):\n\tDon't set warn_matlab_incompatible to true.\n\n2005-03-17  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (class bracket_brace_paren_nesting_level): Use static\n\tconst int members instead of anonymous enum.\n\n2005-03-16  John W. Eaton  <jwe@octave.org>\n\n\t* ov-struct.cc (octave_struct::save_ascii): Don't convert Cell\n\tobject to cs-list.\n\t(octave_struct::save_binary): Likewise\n\t(octave_struct::save_hdf5): Likewise.\n\n\t* DLD-FUNCTIONS/gplot.l (Fset, Fshow): Delete.\n\t(F__gnuplot_plot__): Rename from Fgplot.\n\t(F__gnuplot_splot__): Rename from Fgsplot.\n\t(F__gnuplot_raw__): Rename from Fgraw.\n\t(F__gnuplot_set__): Rename from Fgset.\n\t(F__gnuplot_show__): Rename from Fgshow.\n\t(F__gnuplot_replot__): Rename from Freplot.\n\t(WARN_DEPRECATED, DEPRECATED_BODY): New macros.\n\t(Fgplot, Fgsplot, Fgraw, Fgset, Fgshow): New functions.\n\n2005-03-15  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (<COMMAND_START>{NL}): Reset lexer_flags.doing_rawcommand\n\tstate here.\n\n\t* version.h (OCTAVE_API_VERSION): Now 2.9.0.\n\t(OCTAVE_API_VERSION): Now api-v14.\n\n\t* Makefile.in (INCLUDES): Delete sparse-ops.h from the list.\n\n\t* cellfun.cc: New function from Octave-forge.  Adapt to Octave\n\tcoding standards.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n2005-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/dispatch.cc (Fbuiltin):\tAvoid crash if symbol\n\tlookup fails.\n\n2005-03-10  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (Foctave_config_info): Print error instead of crashing\n\tif struct does not contain field we are looking for.\n\n2005-03-09  John W. Eaton  <jwe@octave.org>\n\n\t* load-save.cc (Fload, Fsave): Accept -text as an alias for -ascii.\n\tIssue warning for future change in meaning of -ascii.\n\n\t* Makefile.in (bin-dist): Delete target.\n\t(BINDISTFILES, BINDISTLIBS): Delete variables.\n\n2005-03-04  John W. Eaton  <jwe@octave.org>\n\n\t* octave.cc (octave_main): Concatenate all --eval arguments.\n\n2005-03-03  John W. Eaton  <jwe@octave.org>\n\n\t* input.cc (input_from_command_line_file): Move definition here.\n\t* parse.y: From here.\n\t* input.h (input_from_command_line_file): Move decl here.\n\t* parse.h: From here.\n\n\t* input.cc (octave_gets):\n\tDon't save history if input is from command line file.\n\n\t* parse.y (parse_and_execute, parse_fcn_file, eval_string):\n\tDon't alter value of input_from_command_line_file here.\n\t(input_from_command_line_file): Default value is false.\n\t(eval_string): Turn off line editing here.\n\n\t* toplev.cc, toplev.h (main_loop): Delete fun_to_call arg and all uses.\n\n\t* octave.cc (fun_to_call): Delete static variable.\n\t(persist, code_to_eval): New static variables.\n\t(long_opts): Delete --funcall, add --eval and --persist.\n\t(usage_string, verbose_usage, octave_main): Likewise.\n\t(FUNCALL_OPTION): Delete.\n\t(EVAL_OPTION, PERSIST_OPTION): New macros.\n\t(maximum_braindamage): Set persist to true.\n\t(execute_eval_option_code): New function.\n\t(restore_program_name): New function.\n\t(execute_command_line_file): New function.\n\t(octave_main): Call execute_eval_option code and\n\texecute_command_line file.  If persist, go interactive even after\n\tevaluating --eval code and/or command-line file.\n\n\t* ov-bool-sparse.h, ov-bool-sparse.cc\n\t(octave_sparse_bool_matrix::sparse_matrix_value,\n\toctave_sparse_bool_matrix::sparse_complex_matrix_value):\n\tAccept bool arg.\n\n\t* parse.y (looks_like_copyright): Check first 9 characters, not 14.\n\n2005-03-02  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_scan (std::istream&, const\n\tscanf_format_elt&, double*)): New specialization to handle Inf,\n\tNaN, and NA.\n\n\t* parse.y (looks_like_copyright):\n\tRename from looks_like_octave_copyright.  Change all uses.\n\tSimply match \"Copyright\".\n\n2005-03-01  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/odessa.cc: Delete.\n\t* Makefile.in (DLD_XSRC): Remove it from the list.\n\t(OPT_HANDLERS): Remove ODESSA-opts.cc from the list.\n\n2005-02-28  John W. Eaton  <jwe@octave.org>\n\n\t* toplev.cc (octave_config_info): Remove LIBGLOB and GLOB_INCFLAGS\n\tfrom the list.\n\t* oct-conf.h.in (OCTAVE_CONF_LIBGLOB, OCTAVE_CONF_GLOB_INCFLAGS):\n\tDelete.\n\t* Makefile.in (OCTAVE_LIBS): Remove $(LIBGLOB) from the list.\n\n2005-02-25  John W. Eaton  <jwe@octave.org>\n\n\tSparse merge.\n\n\t2005-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-SRC/rand.cc (Frand): Accept \"state\" as an alias for \"seed\".\n\n\t* DLD-SRC/dispatch.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n\t2005-02-13  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-inline.h, DLD-FUNCTIONS/spparms.cc, DLD-FUNCTIONS/gcd.cc:\n\tRemove additional licensing clause, with authors permission\n\n\t* ov-base-sparse.h: New constructor to cache SparseType, not yet\n\tused\n\t* ov-re-sparse.h: likewise\n\t* ov-cx-sparse.h: likewise\n\t* ov.h: Likewise\n\n\t* sparse-xdiv.cc: Remove spparms umfpack flag\n\n\t* DLD-FUNCTIONS/spparms.cc: Warning that umfpack flag is ignored.\n\n\t2005-01-16  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat5.cc (read_mat5_integer_data): Change \"T &m\" to \"T *m\" and\n\tinstantiate with values like octave_int8 rather than int8NDArray.\n\tModify function to fit\n\t(read_mat5_binary_element): Use new form of read_mat_integer_data\n\tto read data directly into sparse matrix\n\t(write_mat5_integer_data): Change \"const T &m\" to \"T *m\", etc. New\n\tinstantiation with int.\n\t(save_mat5_binary_element): Modify to save sparse data\n\n\t2005-01-15  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (do_cat): Use first non-empty matrix as base for\n\tconcatenation.\n\t* pt-mat.cc (tree_matrix::rvalue): ditto.\n\n\t2005-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* ov.cc (do_cat_op): When checking for empty args, use\n\tall_zero_dims, not numel.\n\t* ov.h (octave_value::all_zero_dims): New function.\n\n\t* ov-bool-sparse.cc (try_narrowing_conversion): Convert to\n\tbool_matrix, not matrix.\n\n\t2005-01-13  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (make_diag): Use numel not capacity to remove ambiguity.\n\t* ov.h (octave_value::capacity): New virtual funtion.\n\t* ov-base.h (octave_base_value::capacity): New function calls numel.\n\t* data.cc (Freshape): Use arg.numel() rather than arg.dims().numel()\n\tsince sparse numel now consistent.\n\t* symtab.h (symbol_record::symbol_def::capacity,\n\tsymbol_record::capacity): New methods.\n\t* symtab.cc (symbol_record::print_symbol_info_line,\n\tsymbol_table::parse_whos_line_format, symbol_table::maybe_list):\n\tused capacity() and not numel() to properly assess size of\n\tsparse objects.\n\t* ov-base-sparse.h (octave_base_sparse::capacity): New function,\n\t(octave_base_sparse::numel): Delete.\n\t* ov-re-sparse.cc (octave_sparse_matrix::streamoff_array_value):\n\tOnly fill from non-zero elements of sparse array.\n\t* DLD-FUNCTIONS/splu.cc (Fsplu): Change use of nelem to numel.\n\t* ov.cc (do_cat_op): Early return for concatenation with empty\n\tobjects.\n\n\t2005-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/find.cc (Ffind): Make it work for character strings.\n\n\t2005-01-11  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-double-conv.cc: New conversions for sparse_matrix\n\tand sparse_bool_matrix to matrix.\n\n\t2005-01-11  David Bateman  <dbateman@free.fr>\n\n\t* ov-base-sparse.h (octave_base_sparse::any,\n\toctave_base_sparse::all): Use new constructors, etc as pointed out\n\tby JWE.\n\n\t2005-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/sparse.cc (MINMAX_BODY, Fspatan2, make_spdiag):\n\tWrite retval(0) = result instead of retval(0) = octave_value (result).\n\t* DLD-FUNCTIONS/splu.cc (Fsplu): Likewise.\n\n\t2005-01-08  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat5.cc (read_mat5_integer_data): Instantiate for Array<int>\n\t(read_mat5_binary_element): Add code to read sparse matrices\n\tsaved in matlab v5 format\n\n\t2005-01-07  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-bm-sbm.cc, OPERATORS/op-b-sbm.cc,\n\tOPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc,\n\tOPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc,\n\tOPERATORS/op-m-scm.cc, OPERATORS/op-m-sm.cc,\n\tOPERATORS/op-sbm-b.cc, OPERATORS/op-sbm-bm.cc,\n\tOPERATORS/op-sbm-sbm.cc, OPERATORS/op-scm-cm.cc,\n\tOPERATORS/op-scm-cs.cc, OPERATORS/op-scm-m.cc,\n\tOPERATORS/op-scm-s.cc, OPERATORS/op-scm-scm.cc,\n\tOPERATORS/op-scm-sm.cc, OPERATORS/op-sm-cm.cc,\n\tOPERATORS/op-sm-cs.cc, OPERATORS/op-sm-m.cc,\n\tOPERATORS/op-sm-s.cc, OPERATORS/op-sm-scm.cc,\n\tOPERATORS/op-sm-sm.cc, OPERATORS/op-s-scm.cc,\n\tOPERATORS/op-s-sm.cc: New octave_value constructors allow\n\tmacros from ops.h to be used rather than sparse-ops.h. Remove\n\tother explicit uses of maybe_mutate.\n\n\t* sparse-ops.h: delete file.\n\n\t* colamd.cc (Fcolamd, Fsymamd, Fetree): Remove no longer needed\n\tuse of get_rep() and use the sparse matrix conversion functions\n\tdirectly.\n\n\t* data.cc (Freshape): Use arg.dims().numel() rather than\n\targ.numel() due to definition of numel for sparse matrices.\n\n\t* sparse.cc (Ffull, Fspfind, SPARSE_DIM_ARG_BODY, MINMAX_BODY,\n\tFspatan2, make_spdiag): Convert to use new octave_value sparse\n\tconstructors, sparse matrix conversion functions and remove\n\tmaybe_mutate calls.\n\t(Fspreshape): Delete\n\n\t* splu.cc (Fsplu): Remove remaining explicit octave_value\n\tconstruction.\n\n\t* ov-base-sparse.h (do_index_op, resize, reshape, permute, squeeze):\n\tMove these methods from the derived classes.\n\t* ov-base-spase.cc (do_index_op): Move this method from the derived\n\tclasses.\n\t* ov-bool-sparse.h (do_index_op, resize, reshape, permute, squeeze):\n\tdelete.\n\t* ov-re-spase.cc (do_index_op): delete.\n\t* ov-cx-sparse.h (do_index_op, resize, reshape, permute, squeeze):\n\tdelete.\n\t* ov-cx-spase.cc (do_index_op): delete.\n\t* ov-bool-spase.cc (do_index_op): delete.\n\t* ov-re-sparse.h (do_index_op, resize, reshape, permute, squeeze):\n\tdelete.\n\n\t* DLD-FUNCTIONS/spdet.cc (Fspdet): Remove use of SparseDet and\n\tSparseComplexDET classes and use DET and ComplexDET classes.\n\n \t* DLD-FUNCTIONS/colamd.cc op-bm-sbm.cc OPERATORS/op-b-sbm.cc\n\tOPERATORS/op-cm-scm.cc OPERATORS/op-cm-sm.cc OPERATORS/op-cs-scm.cc\n\tOPERATORS/op-cs-sm.cc OPERATORS/op-fil-sbm.cc OPERATORS/op-fil-scm.cc\n\tOPERATORS/op-fil-sm.cc OPERATORS/op-m-scm.cc OPERATORS/op-m-sm.cc\n\tOPERATORS/op-sbm-b.cc OPERATORS/op-sbm-bm.cc OPERATORS/op-sbm-sbm.cc\n\tOPERATORS/op-scm-cm.cc OPERATORS/op-scm-cs.cc OPERATORS/op-scm-m.cc\n\tOPERATORS/op-scm-s.cc OPERATORS/op-scm-scm.cc OPERATORS/op-scm-sm.cc\n\tOPERATORS/op-sm-cm.cc OPERATORS/op-sm-cs.cc OPERATORS/op-sm-m.cc\n\tOPERATORS/op-sm-s.cc OPERATORS/op-sm-scm.cc OPERATORS/op-sm-sm.cc\n\tOPERATORS/op-s-scm.cc OPERATORS/op-s-sm.cc ov-base-sparse.cc\n\tov-base-sparse.h ov-bool-sparse.cc ov-bool-sparse.h ov-cx-sparse.cc\n\tov-cx-sparse.h ov-re-sparse.cc ov-re-sparse.h sparse-base-lu.cc\n\tsparse-base-lu.h DLD-FUNCTIONS/sparse.cc sparse-xdiv.cc sparse-xdiv.h\n\tsparse-xpow.cc sparse-xpow.h DLD-FUNCTIONS/spdet.cc\n\tDLD-FUNCTIONS/splu.cc DLD-FUNCTIONS/spparms.cc: Remove additional\n\tlicensing clause with authors permission.\n\n\t2005-01-05  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/colamd.cc: Rename from colamdoct.cc. Base colamd.h\n\tnow found in COLAMD/colamd.h.\n\t(Fcolamd): Return value is now used.\n\t(Fsymamd): ditto.\n\n\t* Makefile.in: include colamd.cc in DLD_XSRC.\n\n\t* ov.h (sparse_matrix_value, sparse_complex_matrix_value,\n\tsparse_bool_matrix_value): New virtual functions\n\n\t* ov-base.cc (octave_base_value::sparse_matrix_value,\n\toctave_base_value::sparse_complex_matrix_value,\n\toctave_base_value::sparse_bool_matrix_value): New default sparse\n\tmatrix extraction functions.\n\n\t* ov-base.h (sparse_matrix_value, sparse_complex_matrix_value,\n\tsparse_bool_matrix_value): Declare them.\n\n\t* ov-re-mat.cc (octave_matrix::sparse_matrix_value,\n\toctave_matrix::sparse_complex_matrix_value): Conversion functions.\n\n\t* ov-re-mat.h (sparse_matrix_value, sparse_complex_matrix_value):\n\tDeclare them.\n\n\t* ov-cx-mat.cc (octave_complex_matrix::sparse_matrix_value,\n\toctave_complex_matrix::sparse_complex_matrix_value): Conversion\n\tfunctions.\n\n\t* ov-cx-mat.h (sparse_matrix_value, sparse_complex_matrix_value):\n\tDeclare them.\n\n\t* ov-bool-mat.h (sparse_matrix_value, sparse_complex_matrix_value,\n\tsparse_bool_matrix_value): Conversion functions.\n\n\t* DLD_FUNCTIONS/spdet.cc (Fspdet): Use the above constructors\n\tand conversion functions.\n\t* DLD_FUNCTIONS/splu.cc (Fsplu): ditto.\n\n\t2004-12-30  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/splu.cc (Fsplu): Avoid shadow warnings.\n\n\t* sparse-xpow.cc (elem_xpow): Delete unsed variables.\n\t* sparse-xdiv.cc (x_el_div): Likewise.\n\n\t* DLD-FUNCTIONS/det.cc (Fdet): Delete unused argument nargout.\n\t* DLD-FUNCTIONS/spdet.cc (Fspdet): Likewise.\n\n\t* DLD-FUNCTIONS/sparse.cc (Fnzmax): Return a value.\n\n\t* ov.cc, ov.h (octave_value::octave_value (const SparseMatrix&),\n\t(octave_value::octave_value (const SparseBoolMatrix&),\n\t(octave_value::octave_value (const SparseComplexMatrix&)):\n\tNew constructors.\n\n\t2004-12-29  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/sparse.cc (SPARSE_DIM_ARG_BODY): Rename from\n\tDEFUN_DLD_SPARSE_DIM_ARG.  Omit HELP arg.  Omit DEFUN_DLD, so the\n\tmacro only defines the function body.\n\t(Fspprod, Fspcumprod, Fspsum, Fspcumsum, Fspsumsq): Define with\n\tDEFUN_DLD, not DEFUN_DLD_SPARSE_DIM_ARG.  Use SPARSE_DIM_ARG_BODY\n\tto define function body.\n\n\t* DLD-FUNCTIONS/sparse.cc (load_sparse_type, sparse_type_loaded):\n\tDelete function, variable, and all uses.\n\t* ov.cc: Include ov-bool-sparse.h, ov-re-sparse.h, ov-cx-sparse.h.\n\t(install_types): Register sparse types.\n\n\tMerge of sparse code from David Bateman <dbateman@free.fr> and\n\tAndy Adler <adler@site.uottawa.ca>.\n\n\t* sparse-xdiv.cc, sparse-xpow.cc: New files.\n\t* Makefile.in (DIST_SRC): Add them to the list.\n\n\t* sparse-ops.h sparse-xdiv.h, sparse-xpow.h: New files.\n\t* Makefile.in (INCLUDES): Add them to the list.\n\n\t* DLD-FUNCTIONS/colamdoct.cc, DLD-FUNCTIONS/sparse.cc,\n\tDLD-FUNCTIONS/spdet.cc, DLD-FUNCTIONS/splu.cc,\n\tDLD-FUNCTIONS/spparms.cc: New files.\n\t* Makefile.in (DLD_XSRC): Add them to the list.\n\n\t* ov-base-sparse.cc, ov-base-sparse.h, ov-bool-sparse.cc,\n\tov-bool-sparse.h, ov-cx-sparse.cc, ov-cx-sparse.h,\n\tov-re-sparse.cc, ov-re-sparse.h: New files.\n\t* Makefile.in (OV_SPARSE_SRC, OV_SPARSE_INCLUDES): New lists.\n\t(OV_SRC): Add $(OV_SPARSE_SRC) to the list.\n\t(INCLUDES): Add $(OV_SPARSE_INCLUDES) to the list.\n\n\t* OPERATORS/op-bm-sbm.cc, OPERATORS/op-b-sbm.cc,\n\tOPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc,\n\tOPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc,\n\tOPERATORS/op-fil-sbm.cc, OPERATORS/op-fil-scm.cc,\n\tOPERATORS/op-fil-sm.cc, OPERATORS/op-m-scm.cc,\n\tOPERATORS/op-m-sm.cc, OPERATORS/op-sbm-b.cc,\n\tOPERATORS/op-sbm-bm.cc, OPERATORS/op-sbm-sbm.cc,\n\tOPERATORS/op-scm-cm.cc, OPERATORS/op-scm-cs.cc,\n\tOPERATORS/op-scm-m.cc, OPERATORS/op-scm-s.cc,\n\tOPERATORS/op-scm-scm.cc, OPERATORS/op-scm-sm.cc,\n\tOPERATORS/op-sm-cm.cc, OPERATORS/op-sm-cs.cc,\n\tOPERATORS/op-sm-m.cc, OPERATORS/op-sm-s.cc,\n\tOPERATORS/op-sm-scm.cc, OPERATORS/op-sm-sm.cc,\n\tOPERATORS/op-s-scm.cc, OPERATORS/op-s-sm.cc: New files.\n\t* Makefile.in (SPARSE_OP_XSRC): New list.\n\t(OP_XSRC): Add $(SPARSE_OP_XSRC) to the list.\n\n2005-02-23  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (fold (tree_binary_expression*)): Skip constant folding\n\tfor some expressions to preserve warnings.\n\t(Vwarn_associativity_change): New static variable.\n\t(warn_associativity_change): New function.\n\t(symbols_of_parse): DEFVAR warn_associativity_change.\n\t(maybe_warn_associativity_change): New function.\n\t(make_binary_op): Use it.\n\n2005-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (POW, EPOW): Use %left associativity for compatibility.\n\n\t* ov-base-int.cc (octave_baes_int_matrix<T>::load_binary):\n\tHandle arrays with only one dimension.\n\t* ov-bool-mat.cc (octave_bool_matrix::load_binary): Likewise.\n\t* ov-cell.cc (octave_cell::load_binary): Likewise.\n\t* ov-cell.cc (octave_complex_matrix::load_binary): Likewise.\n\t* ov-re-mat.cc (octave_matrix::load_binary): Likewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::load_binary): Likewise.\n\n\t* ov-mapper.cc (octave_mapper::subsref): Return retval after\n\tcalling next_subsref.\n\n\t* ov-mapper.cc (octave_builtin::subsref): If nargout is 0 and we\n\thave additional indexing to perform, set it to 1 before calling\n\tdo_multi_index_op.\n\n\t* oct-map.cc (Octave_map::intfield, Octave_map::stringfield):\n\tNew functions.\n\t* oct-map.h: Provide decls.\n\t* DLD-FUNCTIONS/time.cc (extract_tm): Use intfield and stringfield\n\tto access map elements.\n\n2005-02-21  John W. Eaton  <jwe@octave.org>\n\n\t* ov-builtin.cc (octave_builtin::subsref): If nargout is 0 and we\n\thave additional indexing to perform, set it to 1 before calling\n\tdo_multi_index_op.\n\t* ov-usr-fcn.cc (octave_user_function::subsref): Likewise.\n\n\t* DLD-FUNCTIONS/gplot.l (send_to_plot_stream):\n\tReplot with no previous plot is a no-op.\n\t(makeplot): Likewise.\n\t(Vautomatic_replot): Don't use this variable in low-level functions.\n\n2005-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (oct-gperf.h): Remove -E from list of gperf options.\n\n\t* data.cc (do_permute): Use zero-based indexing for permutation\n\tvector that is passed to octave_value::permute method.\n\tAllow permutation vector longer\tthan number of dimenensions of\n\tpermuted matrix.\n\n2005-02-17  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_API_VERSION): Now 2.1.64-cvs.\n\t(OCTAVE_API_VERSION): Now api-v12-cvs.\n\n2005-02-16  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-mat.h (octave_base_matrix::squeeze): Explicitly convert\n\tresult of matrix.squeeze() to MT.\n\n2005-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* dirfns.cc (deftypefn): Don't print to octave_stdout if nargout > 0.\n\n\t* pt-mat.cc (tree_matrix::rvalue): Min size of ra_idx is 2.\n\n\t* file-io.cc (Ffclear): New function.\n\n\t* sighandlers.h: Define SIGCHLD if it is not already defined and\n\tSIGCLD is defined.\n\n\t* sighandlers.cc (octave_set_signal_handler): Request system calls\n\trestarted if interrupted by signals (except for SIGALRM).\n\t* dirfns.cc (Fls): Don't bother with sleeping or checking errno.\n\n2005-02-11  John W. Eaton  <jwe@octave.org>\n\n\t* sighandlers.cc (sigpipe_handler): Don't try to take action.\n\tSet octave_signal_caught and octave_signals_caught here.\n\t(sigchld_handler): Call octave_child_list::wait here.\n\tSet octave_signal_caught and octave_signals_caught here.\n\t(octave_signals_caught): New static file-scope variable.\n\t(sigint_handler): Also set octave_signal_caught.\n\n\t* sighandlers.cc (sigpipe_handler):\n\n\t* DLD-FUNCTIONS/gplot.l (plot_stream_event_handler): Rename from\n\tplot_stream_death_handler.  Return true if plotter has exited.\n\tCall close_plot_stream with false arg.\n\t(plot_stream_pid): Delete static file-scope variable and all uses.\n\t(close_plot_stream): New arg, remove_from_child_list, with default\n\tvalue of true.  Only call octave_child_list::remove if\n\tremove_from_child_list is true.\n\n\t* pager.cc (octave_pager_pid, saved_interrupt_handler,\n\tinterrupt_handler_saved): Delete static file-scope variables and\n\tall uses.\n\t(clear_external_pager): Do nothing if external_pager is 0.\n\t(pager_event_handler): Rename from pager_death_handler.\n\tImprove warning message.  Return true if pager has exited.\n\t(octave_pager_buf::do_sync): Check errno == EPIPE after write.\n\t(flush_octave_stdout): No need to check external_pager before\n\tcalling clear_external_pager.\n\n\t* toplev.cc (recover_from_exception): Set octave_signal_caught to zero.\n\t(main_loop): Set octave_signal_hook to octave_signal_handler here.\n\n\t* sighandlers.cc (octave_signal_handler): New function.\n\t* sighanlders.h: Provide decl.\n\n\t* sighandlers.cc (install_signal_handlers): Initialize\n\toctave_signals_caught.\n\n\t* sighandlers.h (octave_child::status, have_status): New data members.\n\t(child_event_handler): Rename from dead_child_handler.\n\tChange all uses.\n\t(octave_child_list::reap, octave_child_list::wait): New functions.\n\t(octave_child_list::length, octave_child_list::do_length,\n\toctave_child_list::elem, octave_child_list::do_elem,\n\toctave_child_list::list, octave_child_list::curr_len): Delete.\n\n\t* sighandlers.h, sighandlers.cc\n\t(octave_child_list::octave_child_list_rep): New class.\n\n\t* input.cc (gnu_readline, octave_gets, get_user_input):\n\tCall OCTAVE_QUIT before doing anything.\n\n\t* base-list.h (octave_base_list<T>::remove_if): New function.\n\n\t* TEMPLATE-INST/Array-oc.cc: Delete.\n\t* Makefile.in (TI_XSRC): Remove from list.\n\n2005-02-10  Driss Ghaddab  <driss.ghaddab@free.fr>\n\n\t* cutils.c (octave_usleep) [HAVE_POLL]: Fix typo.\n\n2005-02-10  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (symbol_exist): Don't search path if explicitly\n\tasked for a variable or builtin.  From David Bateman\n\t<dbateman@free.fr>.\n\n2005-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* variables.cc (same_file): New static function.\n\t(symbol_out_of_date): Use it.\n\n\t* syscalls.cc (Fcanonicalize_file_name): New function.\n\n2005-02-08  Walter Landry  <landry@osc.edu>\n\n\t* symtab.h (symbol_record::mark_as_command): Avoid AIX compiler error.\n\n2005-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/find.cc (find_nonzero_elem_idx): Return [] instead\n\tof [](1x0) for scalar arg of zero.\n\n2005-02-06  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gplot.l (tmp_files): Delete.\n\tFrom Todd Neal <tolchz@tolchz.net>.\n\n2005-02-04  John W. Eaton  <jwe@octave.org>\n\n\t* sighandlers.cc (octave_child_list::~octave_child_list): Move here.\n\t* sighandlers.h: From here.\n\n2005-02-02  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (parse.cc): Expect 12 shift/reduce conflicts.\n\t* parse.y (loop_command): Allow \"for (k=1:10) ... endfor\".\n\n2005-01-27  David Bateman  <dbateman@free.fr>\n\n\t* ov-mapper.cc (octave_mapper::apply): Only work on real arguments\n\tif c_c_map_fcn or d_d_map_fcn or d_b_map_fcn is defined.xo\n\n2005-01-26  Joel Andersson  <snprintf@gmail.com>\n\n\t* help.cc (keywords): Document endswitch.\n\n2005-01-21  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/filter.cc (filter): Avoid slow Marray indexing ops.\n\n2005-01-20  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (EXTRAS): Move ov-base-mat.cc ov-base-scalar.cc here.\n\t(OV_SRC): From here.\n\n2005-01-18  John W. Eaton  <jwe@octave.org>\n\n\t* ov-complex.h (octave_complex::any): New function.\n\t* ov-scalar.h (octave_scalar::any): New function.\n\n\t* file-io.cc (Fmkstemp): Fix doc string.  Error message belongs in\n\tthird output value.  From Mats Jansson <mats.e.jansson@home.se>.\n\n2005-01-12  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/find.cc (Ffind): Make it work for character strings.\n\n2005-01-11  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/gplot.l (UNOP): Avoid trailing comment.\n\n2005-01-10  John W. Eaton  <jwe@octave.org>\n\n\t* ls-oct-ascii.cc (extract_keyword (std::istream&, const\n\tstring_vector&, std::string&, int&, const bool)):\n\tRemove duplicate definition.\n\n2004-12-27  Martin Dalecki  <martin@dalecki.de>\n\n\t* Cell.cc, c-file-ptr-stream.cc, comment-list.cc, oct-map.cc,\n\toct-obj.cc, ov-base.cc, ov-base-int.cc, ov-base-mat.cc,\n\tov-base-scalar.cc, ov-bool.cc, ov-bool-mat.cc, ov-builtin.cc,\n\tov.cc, ov-cell.cc, ov-ch-mat.cc, ov-colon.cc, ov-complex.cc,\n\tov-cs-list.cc, ov-cx-mat.cc, ov-dld-fcn.cc, ov-fcn.cc,\n\tov-fcn-handle.cc, ov-fcn-inline.cc, ov-file.cc, ov-int16.cc,\n\tov-int32.cc, ov-int64.cc, ov-int8.cc, ov-list.cc, ov-mapper.cc,\n\tov-range.cc, ov-re-mat.cc, ov-scalar.cc, ov-streamoff.cc,\n\tov-str-mat.cc, ov-struct.cc, ov-typeinfo.cc, ov-uint16.cc,\n\tov-uint32.cc, ov-uint64.cc, ov-uint8.cc, ov-usr-fcn.cc,\n\tov-va-args.cc, procstream.cc, pt-arg-list.cc, pt-assign.cc,\n\tpt-binop.cc, pt-bp.cc, pt.cc, pt-cell.cc, pt-check.cc, pt-cmd.cc,\n\tpt-colon.cc, pt-const.cc, pt-decl.cc, pt-except.cc, pt-exp.cc,\n\tpt-fcn-handle.cc, pt-id.cc, pt-idx.cc, pt-jump.cc, pt-loop.cc,\n\tpt-mat.cc, pt-misc.cc, pt-pr-code.cc, pt-select.cc, pt-stmt.cc,\n\tpt-unop.cc, symtab.cc, token.cc, unwind-prot.cc:\n\tDelete #pragma implementation.\n\n\t* Cell.h, c-file-ptr-stream.h, comment-list.h, oct-map.h,\n\toct-obj.h, ov-base.h, ov-base-int.h, ov-base-mat.h,\n\tov-base-scalar.h, ov-bool.h, ov-bool-mat.h, ov-builtin.h,\n\tov-cell.h, ov-ch-mat.h, ov-complex.h, ov-cs-list.h, ov-cx-mat.h,\n\tov-dld-fcn.h, ov-fcn.h, ov-fcn-handle.h, ov-fcn-inline.h,\n\tov-file.h, ov.h, ov-int16.h, ov-int32.h, ov-int64.h, ov-int8.h,\n\tov-list.h, ov-mapper.h, ov-range.h, ov-re-mat.h, ov-scalar.h,\n\tov-streamoff.h, ov-str-mat.h, ov-struct.h, ov-typeinfo.h,\n\tov-uint16.h, ov-uint32.h, ov-uint64.h, ov-uint8.h, ov-usr-fcn.h,\n\tprocstream.h, pt-arg-list.h, pt-assign.h, pt-binop.h, pt-bp.h,\n\tpt-cell.h, pt-check.h, pt-cmd.h, pt-colon.h, pt-const.h,\n\tpt-decl.h, pt-except.h, pt-exp.h, pt-fcn-handle.h, pt.h, pt-id.h,\n\tpt-idx.h, pt-jump.h, pt-loop.h, pt-mat.h, pt-misc.h, pt-pr-code.h,\n\tpt-select.h, pt-stmt.h, pt-unop.h, symtab.h, token.h,\n\tunwind-prot.h: Delete #pragma interface.\n\n2004-12-27  John W. Eaton  <jwe@octave.org>\n\n\tMerge of changes from Teemu Ikonen <tpikonen@pcu.helsinki.fi> to\n\tremove gnuplot from main parser.\n\n\t* pt-plot.cc, pt-plot.h: Delete.\n\t* Makefile.in (PT_SRC, PT_INCLUDES): Delete them from the lists.\n\n\t* DLD-FUNCTIONS/gplot.l: New file.\n\t* Makefile.in: Include it in the DLD_XSRC list.\n\n\t* dirfns.cc (octave_change_to_directory):\n\tDon't call do_external_plotter_cd.\n\n\t* symtab.h (symbol_record::TYPE): New element, RAWCOMMAND.\n\t(symbol_record::symbol_def::mark_as_rawcommand,\n\tsymbol_record::symbol_def::unmark_rawcommand,\n\tsymbol_record::symbol_def::is_rawcommand): New functions.\n\t(symbol_record::symbol_def::symbol_type): Bitfield is now 9 bits wide.\n\t(symbol_record::mark_as_rawcommand,\n\tsymbol_record::unmark_rawcommand, symbol_record::is_rawcommand):\n\tNew functions.\n\t(SYMTAB_ALL_TYPES): Include RAWCOMMAND.\n\n\t* parse.y (make_plot_command): Delete function.\n\t(tree_plot_command_type, subplot_type, subplot_list_type,\n\tplot_limits_type, plot_range_type, subplot_using_type,\n\tsubplot_style_type, subplot_axes_type):\n\tDelete non-terminal type decls.\n\t(PLOT, STYLE, AXES_TAG): Delete token types.\n\t(title, plot_command, plot_command2, plot_options, plot_command1,\n\tranges, ranges1, using, using1, style, axes): Delete non-terminals.\n\n\t* toplev.cc (do_octave_atexit): Don't call close_plot_stream.\n\n\t* variables.cc (rawcommand_set): New static variable.\n\t(is_marked_as_rawcommand, mark_as_rawcommand, unmark_rawcommand,\n\tFiscommand, Fmark_as_rawcommand, Funmark_rawcommand,\n\tFisrawcommand, is_rawcommand_name): New functions.\n\t* variables.h: Provide decl for is_rawcommand_name.\n\n\t* pt-bp.cc, pt-bp.h, pt-check.cc, pt-check.h, pt-pr-code.cc,\n\tpt-pr-code.h, pt-walk.h: Delete all declarations, definitions, and\n\tuses of visit_subplot, visit_subplot_axes, visit_subplot_list,\n\tvisit_subplot_style, and visit_subplot_using methods.\n\n\t* lex.h (lexer_flags): New field, doing_rawcommand.\n\t* lex.l (<COMMAND_START>[\\;\\,]): Also handle raw commands here.\n\t(lexer_flags::init): Initialize doing_racommand to false.\n\t(handle_identifier): Recognize raw commands ere.\n\t(handle_string): Don't do string escape conversions on raw command\n\tstrings.\n\n\t* octave.gperf: Delete gplot_kw, gsplot_kw, replot_kw.\n\n\t* lex.h (lexer_flags): Delete fields cant_be_identifier,\n\tdoing_set, in_plot_range, in_plot_using, in_plot_style,\n\tin_plot_axes, past_plot_range, and plotting.\n\t* lex.l: Delete all uses of these lexer flags and remove all\n\tspecial cases for plotting.\n\t(plot_style_token, plot_axes_token, is_plot_keyword): Delete.\n\n\t* file-io.cc, file-io.h (tmp_files, mark_for_deletion,\n\tcleanup_tmp_files): Move here.\n\t* pt-plot.cc, pt-plot.h: From here.\n\n\t* Makefile.in (PKG_ADD): New target.\n\t(all): Depend on PKG_ADD.\n\t(install-oct): Depend on PKG_ADD.  Install PKG_ADD file.\n\t(gplot.cc): New target.\n\t(stamp-prereq): Depend on gplot.cc.\n\t(VAR): Don't include $(DLD_SRC) here.\n\t(DLD_OBJ, DLD_DEF_FILES): Include .l files.\n\n\t* defun-int.h (DEFVAR, DEFCONST, DEFCONSTX): Move definition here.\n\t* defun.h: From here.\n\n2004-12-22  John W. Eaton  <jwe@octave.org>\n\n\t* ls-oct-ascii.cc (extract_keyword (std::istream&, const\n\tstring_vector&, std::string&, int&, const bool): New function.\n\t* ls-oct-ascii.h: Provide decl.\n\t* ov-bool-mat.cc (octave_bool_matrix::load_ascii):\n\tUse new extract_keyword function to avoid calling tellg/seekg.\n\t* ov-cell.cc (octave_cell::load_ascii): Likewise.\n\t* ov-cx-mat.cc (octave_complex_matrix::load_ascii): Likewise.\n\t* ov-re-mat.cc (octave_matrix::load_ascii): Likewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::load_ascii): Likewise.\n\n2004-12-20  John W. Eaton  <jwe@octave.org>\n\n\t* pt-idx.cc (tree_index_expression::has_magic_end): Return true if\n\tany argument list element has a magic end token.\n\n2004-12-03  John W. Eaton  <jwe@octave.org>\n\n  \t* version.h (OCTAVE_VERSION): Now 2.1.64.\n\n2004-12-03  Teemu Ikonen  <tpikonen@pcu.helsinki.fi>\n\n\t* file-io.cc: Doc string fixes.\n\n2004-12-02  David Bateman  <dbateman@free.fr>\n\n\t* input.cc (get_user_input): Only set nm and line for debugging if\n\tboth debug is true and curr_caller_function is non-null.\n\n2004-12-02  David Bateman  <dbateman@free.fr>\n\n\t* ls-mat5.cc (arrayclasstype): Add mxINT64_CLASS, mxUINT64_CLASS,\n\tmxFUNCTION_CLASS enum values.\n\t(read_mat5_integer_data): New template function.\n\t(OCTAVE_MAT5_INTEGER_READ): New macro.\n\t(read_mat5_binary_element): Handle reading integer types.\n\tEliminate automatic conversion from int to double.\n\t(write_mat5_integer_data): New template function.\n\tInstantiate it for the 8 integer data types\n\t(save_mat5_binary_element): Handle integer data types.\n\n\t* load-save.cc (Fload): Check file existence here.\n\tIf file does not exist, append \".mat\" to name and try again.\n\t(get_file_format): Delete check for file existence.\n\n2004-11-30  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (oct-gperf.h): Use -L C++ instead of -L ANSI_C.\n\tUse -Z octave_kw_hash option, delete -H and -N options.\n\t* lex.l (is_keyword_token): Use octave_kw_hash::in_word_set\n\tinstead of octave_kw_lookup.\n\t(is_keyword): Likewise.\n\n2004-11-22  John W. Eaton  <jwe@octave.org>\n\n\t* pt-arg-list.cc (tree_argument_list::convert_to_const_vector):\n\tCheck to see whether object is a function or function handle\n\tinstead of constant.\n\n2004-11-19  John W. Eaton  <jwe@octave.org>\n\n\t* ov-str-mat.cc (octave_char_matrix_str::do_index_op):\n\tSkip indexing operation if indices are invalid.\n\n\t* pr-output.cc (set_range_format, set_complex_matrix_format,\n\tset_complex_format, set_real_matrix_format, set_real_format):\n\tAlso specify std::ios::fixed for bank format.\n\n2004-11-17  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.63.\n\t(OCTAVE_API_VERSION): Now api-v12.\n\n2004-11-17  David Bateman  <dbateman@free.fr>\n\n\t* pt-arg-list.cc (F__end__): Ask dv for the number of elements\n\tinstead indexed_object.\n\n2004-11-16  David Bateman  <dbateman@free.fr>\n\n\t* ov.h (octave_value::numel): Now virtual.  Call rep->numel ().\n\t* ov.cc (octave_value::numel): Delete.\n\t* ov-base.h (octave_base_value::numel): New function.\n\n2004-11-12  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.62.\n\n2004-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-int-concat.cc: New file for mixed integer/other\n\tconcatentation operators.\n\t* Makefile.in (INTTYPE_OP_XSRC): Add it to the list.\n\n\t* ops.h (DEFNDCATOP_FN2): New macro.\n\n\t* OPERATORS/op-int.h (OCTAVE_CONCAT_FN2,\n\tOCTAVE_INSTALL_CONCAT_FN2, OCTAVE_DOUBLE_INT_CONCAT_FN,\n\tOCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN, OCTAVE_INT_DOUBLE_CONCAT_FN,\n\tOCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN): New macros.\n\n2004-11-09  David Bateman  <dbateman@free.fr>\n\n\t* Cell.cc (concat): Delete.\n\t(Cell::concat): New method.\n\t* Cell.h: Provide decls.\n\n\t* oct-map.cc (concat): Delete\n\t(Octave_map::concat): New method.\n\t* oct-map.h: Provide decls.\n\n\t* ov.h (typedef octave_value (*cat_op_fcn) (octave_value&,\n\tconst octave_value&, const Array<int>&): Change definition of\n\tcat_op_fcn so first argument is not constant.\n\n\t* ops.h (CATOPDECL): First arg is no longer constant.\n\t(DEFCATOP_FN, DEFNDCATOP_FN): Change to use new concat methods.\n\n\t* OPERATORS/op-chm.cc, OPERATORS/op-str-m.cc, OPERATORS/op-str-s.cc,\n\tOPERATORS/op-str-str.cc (DEFCATOP): Change explicit concat functions\n\tto use new concatenation methods.\n\n2004-11-05  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.61.\n\n\t* DLD-FUNCTIONS/det.cc (det): Always compute rcond so we can\n\tdetect numerically singular matrices.\n\n2004-11-04  John W. Eaton  <jwe@octave.org>\n\n\t* pt-colon.cc (tree_colon_expression::line,\n\ttree_colon_expression::column): New functions.\n\t* pt-colon.h: Provide decls.\n\n\t* oct-stream.cc (octave_stream::seek (long, int)): Return error\n\t(but leave file position unchanged) for attempt to seek beyond end\n\tof file.\n\n\t* DLD-FUNCTIONS/inv.cc (Finv): Check rcond value returned from\n\tLAPACK routines, and be careful to avoid optimizing away the\n\t1+rcond == 1.0 check.\n\t* DLD-FUNCTIONS/det.cc (Fdet): Likewise.\n\n2004-11-03  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (Fsize): Return 1 if requested dimension is larger than\n\tthe number of dimensions of the given object.\n\n2004-11-01  Claude Lacoursiere  <claude@hpc2n.umu.se>a\n\n\t* ls-hdf5.cc (read_hdf5_data): Expect num_obj to be in distinct group.\n\t* ov-cell.cc (octave_cell::load_hdf5): Likewise.\n\t* ov-list.cc (octave_list::load_hdf5): Likewise.\n\t* ov-struct.cc (octave_struct::load_hdf5): Likewise.\n\n2004-11-01  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/filter.cc (filter (MArray<T>&, MArray<T>&,\n\tMArrayN<T>&, MArrayN<T>&, int)): The variable si is now at least 2-D.\n\t(Ffilter): Force si to be 2-D, while allowing arbitrary vector\n\torientation.\n\n2004-11-01  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (INSTANTIATE_EYE): New macro.  Use it to instantiate\n\tidentity matrix functions for various matrix types.\n\n\t* variables.cc (do_who): Fix typo in for loop.\n\n2004-10-28  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (save_mat5_binary_element): Save structure elements\n\tin correct order.\n\n2004-10-26  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn.h (octave_function::octave_va_arg): No longer const.\n\n2004-10-22  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/filter.cc: Remove some unnecessary parens.\n\n2004-10-22  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/filter.cc (filter (MArray<T>&, MArray<T>&,\n\tMArrayN<T>&, MArrayN<T>&, int)): If value to filter is\n\tdimensionality 2 it might still be a vector, use special case.\n\n2004-10-21  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base.cc (INT_CONV_METHOD): Apply saturation semantics here too.\n\n2004-10-19  John W. Eaton  <jwe@octave.org>\n\n\t* ov-range.h (octave_range::write): New function.\n\n2004-10-18  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (symbol_record::dimensions_string_req_first_space,\n\tsymbol_record::make_dimensions_string): Use dims() for all objects.\n\n2004-10-18  Oyvind Kristiansen  <oyvinkri@stud.ntnu.no>\n\n\t* symtab.cc (symbol_table::parse_whos_line_format): Handle\n\tsize-of-parameter and center-specific format specifiers.\n\n2004-10-18  John W. Eaton  <jwe@octave.org>\n\n\t* pt-plot.cc (handle_plot_data): If plotting data from file,\n\talways use \"using\" clause.\n\n2004-10-12  David Bateman  <dbateman@free.fr>\n\n\t* pt-mat.cc (tm_row_const::tm_row_const_rep::do_init_element,\n\ttm_const::init): Dimensionality of matrices not necessarily the\n\tsame.  Check before comparing.\n\n2004-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* pt-fcn-handle.h (tree_fcn_handle::name): New function.\n\n2004-10-01  John W. Eaton  <jwe@octave.org>\n\n\t* ov-range.h (octave_range::valid_as_scalar_index): Ensure int value.\n\t(octave_range::valid_as_zero_index): Likewise.\n\n\t* ov-scalar.h (octave_scalar::valid_as_scalar_index): Ensure int value.\n\t(octave_scalar::valid_as_zero_index): Likewise.\n\n2004-09-24  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.60.\n\t(OCTAVE_API_VERSION): Now api-v11.\n\n\t* OPERATORS/op-int.h (OCTAVE_MM_INT_OPS): Include missing matrix\n\tby int matrix ops.\n\t(OCTAVE_INSTALL_MM_INT_OPS): Install them.\n\n\t* OPERATORS/op-i64-i64.cc: Define and install missing int64 by\n\tmatrix and scalar ops.\n\n2004-09-24  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-inline (Finline): Attempt better auto-detection of\n\tsymbols that should be recognized as arguments.\n\n2004-09-24  John W. Eaton  <jwe@octave.org>\n\n\t* ov-str-mat.cc (default_numeric_conversion_function): Return\n\tscalar object if numel == 1.\n\n2004-09-23  John W. Eaton  <jwe@octave.org>\n\n\t* ops.h\t(DEFSTRDBLCONVFN): New macro.\n\t* OPERATORS/op-double-conv.cc: Use it to define new conversion op.\n\tDefine new range to double matrix conversion.\n\t(install_int_conv_ops): Install new ops.\n\n\t* ops.h\t(DEFSTRINTCONVFN): New macro.\n\t* OPERATORS/op-int-conv.cc: Use it to define new conversion ops.\n\t(install_int_conv_ops): Install them.\n\n\t* (OCTAVE_SS_INT_OPS2, OCTAVE_SM_INT_OPS2, OCTAVE_MM_INT_OPS2,\n\tOCTAVE_INSTALL_SS_INT_OPS2, OCTAVE_INSTALL_SM_INT_OPS2,\n\tOCTAVE_INSTALL_MS_INT_OPS2, OCTAVE_INSTALL_MM_INT_OPS2):\n\tDelete unused macros.\n\n\t* OPERATORS/op-int.h (OCTAVE_SS_INT_BOOL_OPS): New args Z1 and Z2.\n\t(OCTAVE_SS_INT_OPS): Pass appropriately typed zero values to\n\tOCTAVE_SS_INT_BOOL_OPS.\n\t* OPERATORS/op-i64-i64.cc, OPERATORS/op-ui64-ui64.cc: Likewise.\n\n\t* pr-output.cc (pr_plus_format): Now template.\n\tSpecialize for Complex.\n\t(octave_print_internal): Lookup print_conv_type using\n\toctave_int<T>, not just T.\n\n\t* ov-struct.cc (octave_struct::subsref): Pass skip to next_subsref.\n\n\t* oct-stream.cc\t(do_read): Hitting EOF should not be an error.\n\n2004-09-22  John W. Eaton  <jwe@octave.org>\n\n\t* pt-plot.cc (send_to_plot_stream): Skip automatic replot if in\n\tmultiplot mode.\n\n\t* variables.cc (get_global_value): New arg, silent.\n\t* variables.h (get_global_value): Default value for silent arg is\n\tfalse.\n\n2004-09-22  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-inline.cc (Finline): When called with a single arg, derive\n\targument of inline function in a compatible manner.\n\n2004-09-22  Federico Zenith  <zenith@chemeng.ntnu.no>\n\n\t* DLD-FUNCTIONS/qz.cc (Fqz): New @tex section(s) in doc string for\n\tbetter formating of printed documentation.  Use @var in doc string.\n\n\t* DLD-FUNCTIONS/time.cc (Fstrftime): Fix typo in doc string.\n\t* error.cc (Flasterr, Flastwarn): Likewise.\n\t* mappers.cc (Farg, Fasinh, Fatanh, Ffinite, Fsin, Fsinh, Ftan):\n\tLikewise.\n\t* file-io.cc (Fmktemp): Likewise.\n\t* pt-plot.cc (symbols_of_pt_plot): Fix typos in doc string for\n\tgnuplot_has_frames.\n\n\t* input.cc (symbols_of_input): Replace --echo-input with new\n\t--echo-commands in PS4 doc string.\n\n\t* pt-assign.cc (symbols_of_pt_assign): Mark print_rhs_assign_val\n\tas built-in in doc string.\n\n\t* symtab.cc (symbols_of_symtab): Mark variables_can_hide_functions\n\tas built-in in doc string.\n\n2004-09-21  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.59.\n\n\t* oct-fstrm.h (octave_fstream::octave_fstream,\n\toctave_fstream::create): Set default float format to actual native\n\tformat, not flt_fmt_native.\n\t* oct-iostrm.h (octave_base_iostream::octave_base_iostream,\n\toctave_istream::octave_istream, octave_ostream::octave_ostream):\n\tLikewise.\n\t* oct-prcstrm.h (octave_iprocstream::octave_iprocstream,\n\toctave_oprocstream::octave_oprocstream,\n\toctave_iprocstream::create, octave_oprocstream::create):\n\tLikewise.\n\t* oct-stdstrm.h (octave_stdiostream::octave_stdiostream,\n\toctave_stdiostream::create):\n\tLikewise.\n\t* oct-stream.h (octave_base_stream::octave_base_stream):\n\tLikewise.\n\t* oct-strstrm.h (octave_base_strstream::octave_base_strstream,\n\toctave_istrstream::octave_istrstream, octave_istrstream::create):\n\tLikewise.\n\n2004-09-21  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (Freshape): Allow a single empty dimension argument\n\tto flag unknown dimension and calculate its value from the\n\tother dimensions.\n\n2004-09-21  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.h (symbol_record::~symbol_record): Delete definition if\n\tcount goes to zero.\n\t* symtab.cc (symbol_table::~symbol_table): Move here from symtab.h.\n\tCall delete on each symbol record in the table instead of just\n\tclearing them.\n\n2004-09-17 David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/sort.cc (ascending_compare, descending_compare):\n\tNow templates (avoids g++ 3.4.x compile problems).\n\tFix other uses of these functions to also treat them as templates.\n\t(mx_sort): For unsigned EIGHT_BYTE_INT versions correct the test\n\tfor the position of NaN.  Problems when mode was DESCENDING or\n\tUNDEFINED.  Use static_cast<unsigned int> (dim) rather than\n\t(unsigned int) dim.\n\t(IFloatFlip): Now static.\n\n2004-09-17  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/det.cc (Fdet): Only compute estimate of the\n\tcondition number if requested as output.\n\n\t* DLD-FUNCTIONS/schur.cc (Fschur): Only compute unitary matrix if\n\trequested as output.\n\n2004-09-17  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-inline.cc (octave_fcn_inline::octave_fcn_inline):\n\tCall eval_string instead of feval (\"eval\", ...).\n\tConstruct anonymous function handle to avoid going through the\n\tsymbol table.\n\n\t* ov-fcn-handle.h (octave_fcn_handle::fcn_val): New function.\n\t(octave_fcn_handle::octave_fcn_handle (const std:string&)):\n\tNew constructor.\n\n2004-09-16  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (frob_function): Clear id_name from curr_sym_tab, not\n\ttop_level_sym_tab.\n\n\t* symtab.cc (maybe_list): Count sizes using size_t, not int.\n\n\t* variables.cc (symbol_out_of_date): Always look in LOADPATH.\n\n2004-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-int-conv.cc: Define and install bool to int\n\tconversions.\n\t* OPERATORS/op-double-conv.cc: Define and install bool to double\n\tconversions.\n\n\t* ov.cc (octave_value::assign): Handle subsref for containers.\n\t* oct-lvalue.cc (octave_lvale::value): Likewise.\n\n\t* DLD-FUNCTIONS/sort.cc (mx_sort): Return octave_value, not\n\toctave_value list.\n\n2004-09-15  David Bateman  <dbateman@free.fr>\n\n\t* ov.cc (octave_value::octave_value (const ArrayN<char>&, bool)):\n\tNew Constructor .\n\t* ov.h: Provide decl.\n\n\t* DLD-FUNCTIONS/sort.cc (sortmode): New enum to define sort direction.\n\t(template <class T> class vec_index): New class to contain values and\n\tindex for indexed sorts, replacing all previous struct versions.\n\tInstantiate for double, Complex, char and octave_value.\n\t(template <class T> static octave_value_list mx_sort (ArrayN<T> &, int,\n\tsortmode)): New templated version of mx_sort replacing all previous\n\tversions, but specific to non indexed sorts. Instantiate for char\n\tand double if not IEEE754.\n\t(template <> static octave_value_list mx_sort (ArrayN<double> &,\n\tint, sortmode)): Specialized function of mx_sort of IEEE754.\n\t(template <class T> static octave_value_list mx_sort_indexed\n\t(ArrayN<T> &, int, sortmode)): New templated version of mx_sort\n\tfor indexed sorts. Instantiate for double, Complex, char and\n\toctave_value.\n\t(ascending_compare, descending_compare): Comparison functions\n\tfor double, char, vec_index<double> *, vec_index<Complex> *,\n\tvec_index<char> *, vec_index<octave_value>. Fix Complex comparison\n\toperator to sort by arg of values if absolute values are equal.\n\t(Fsort): Update docs for new mode argument and for sorting of\n\tstrings and cell arrays of strings. Implement mode argument to\n\tdefine ascending and descending sorts. Include sorting of cell\n\tarrays of strings. Adapt for new templated versions of the mx_sort\n\tfunction.\n\n2004-09-15  John W. Eaton  <jwe@octave.org>\n\n\t* ov-cell.cc (octave_cell::subsref): Pass nargout to next_subsref.\n\t* ov-builtin.cc (octave_builtin::subsref): Likewise.\n\t* ov-fcn-handle.cc (octave_fcn_handle::subsref): Likewise.\n\t* ov-list.cc (octave_list::subsref): Likewise.\n\t* ov-mapper.cc (octave_mapper::subsref): Likewise.\n\t* ov-struct.cc (octave_struct::subsref): Likewise.\n\t* ov-usr-fcn.cc (octave_user_function::subsref): Likewise.\n\n\t* ov-struct.cc, ov-struct.h (octave_struct::subsref (const\n\tstd::string&, const std::list<octave_value_list>&, int)):\n\tDefine this version.\n\t(octave_struct::subsref (const std::string&, const\n\tstd::list<octave_value_list>&)): Panic in this version.\n\t* ov-list.cc, ov-list.h: Likewise.\n\t* ov-cell.cc, ov-cell.h: Likewise.\n\n\t* ov.cc (octave_value::subsref (int, const std::string&, const\n\tstd::list<octave_value_list>&, size_t)): New function.\n\t* ov.h: Provide decl.\n\n\t* ov-cell.h (octave_cell::is_constant): Return false.\n\t* ov-struct.h (octave_struct::is_constant): Delete.\n\t* ov-list.h (octave_list::is_constant): Delete.\n\n2004-09-14  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/sort.cc (mx_sort (charNDArray&, bool, int)):\n\tNew function to sort character strings.\n\t(Fsort): Handle character strings.\n\n2004-09-11  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::save_ascii):\n\tWrite directly to OS.\n\t(octave_fcn_handle::load_ascii,\toctave_fcn_handle::load_binary,\n\toctave_fcn_handle::load_hdf5): Check parse status after calling\n\teval_string.  Don't dereference fh unless it is valid.\n\n2004-09-11  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::save_ascii,\n\toctave_fcn_handle::load_ascii, octave_fcn_handle::save_binary,\n\toctave_fcn_handle::load_binary, octave_fcn_handle::save_hdf5,\n\toctave_fcn_handle::load_hdf5): New functions.\n\t* ov-fcn-handle.h: Provide decls.\n\n\t* ov-fcn-inline.cc (octave_fcn_inline::load_ascii):\n\tAllow spaces in saved function.\n \t(octave_fcn_inline::save_hdf5): Properly close all HDF5 objects.\n\n\t* ls-oct-ascii.cc (read_ascii_data): Check return type of\n\t<octave_value>.load_ascii for errors reading the variables\n\n\t* variables.cc (lookup_function_handle, clear_variable,\n\tclear_symbol): New functions.\n\t* variables.h: Provide decls.\n\n2004-09-10  John W. Eaton  <jwe@octave.org>\n\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op): Use unwind\n\tprotect frame instead of a single unwind_protect::run.\n\t* ov-mapper.cc (octave_mapper::do_multi_index_op): Likewise.\n\n\t* data.cc (fill_matrix, identity_matrix):\n\tAlso allow logical data type.\n\n2004-09-10  David Bateman  <dbateman@free.fr>\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::double_value,\n\tOCTAVE_VALUE_INT_MATRIX_T::scalar_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::double_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::scalar_value): New functions.\n\n2004-09-10  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-scalar.h (octave_base_scalar::clone,\n\toctave_base_scalar::empty_clone): New functions.\n\n2004-09-09  John W. Eaton  <jwe@octave.org>\n\n\t* pt-pr-code.h (tree_print_code::newline): New optional arg, alt_nl.\n\t* pt-pr-code.cc (tree_print_code::newline): Use it if not printing\n\tnewlines.\n\t(tree_print_code::visit_statement): If we printed \";\", call\n\tnewline with optional arg set to \"\".\n\t(tree_print_code::printing_newlines): New data member.\n\t(tree_print_code::tree_print_code): Initialize it.\n\t(tree_print_code::suspend_newline, tree_print_code::resume_newline):\n\tNew functions.\n\t(tree_print_code::newline, tree_print_code::indent): Use it\n\n\t* ov-fcn-handle.cc (octave_fcn_handle::print_raw):\n\tPrint code for anonymous function handles.\n\n2004-09-08  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-handle.cc (Ffunc2str, Ffunctions): Don't call substr(1)\n\ton fh_nm, since we no longer need to skip \"@\" in the name.\n\n\t* error.cc (pr_where): Do a better job of printing location info.\n\n\t* input.cc (get_user_input): Print location info before the debug\n\tprompt.  From Keith Goodman <kwgoodman@gmail.com>.\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tSave and set curr_caller_function and curr_caller_statement here.\n\t* ov-mapper.cc (octave_mapper::do_multi_index_op): Likewise.\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op): Likewise.\n\n\t* pt-stmt.cc (curr_caller_statement): New variable.\n\t* pt-stmt.h: Provide decl.\n\n\t* toplev.cc (curr_caller_function): New variable.\n\t* toplev.h: Provide decl.\n\n\t* pt-arg-list.cc (convert_to_const_vector):\n\tUnwind-protect index_position before modifying it.\n\tDon't protect and set index_position unless stash_object is true.\n\n2004-09-08  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-inline.cc (octave_fcn_inline::save_ascii,\n\toctave_fcn_inline::load_ascii, octave_fcn_inline::save_binary,\n\toctave_fcn_inline::load_binary, octave_fcn_inline::save_hdf5,\n\toctave_fcn_inline::load_hdf5): New functions.\n\t* ov-fcn-inline.h: Provide decls.\n\n2004-09-08  John W. Eaton  <jwe@octave.org>\n\n\t* ov.h: Add octave_array_type_traits specialization for\n\tboolNDArray element type.\n\n2004-09-07  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc: Instantiate octave_stream::write for Array<bool>.\n\t(octave_stream::read): Expand read_fptr_table to include dt_logical.\n\n\t* ov-bool.h (octave_bool::write): New function.\n\t* ov-bool-mat.h (octave_bool_matrix::write): New function.\n\n\t* ov-fcn-inline.h (octave_fcn_inline::octave_fcn_inline): New copy\n\tconstructor.\n\t(octave_fcn_inline::clone, octave_fcn_inline::empty_clone):\n\tNew functions.\n\n\t* ov-fcn-handle.h (octave_fcn_handle::octave_fcn_handle): New copy\n\tconstructor.\n\t(octave_fcn_handle::clone, octave_fcn_handle::empty_clone):\n\tNew functions.\n\n2004-09-06  John W. Eaton  <jwe@octave.org>\n\n\t* ov.cc (install_types): Call octave_fcn_inline::register_type.\n\n\t* version.h (OCTAVE_API_VERSION): Now api-v10.\n\n\t* OPERATORS/op-b-b.cc, OPERATORS/op-bm-bm.cc: Define and install\n\tunary plus and unary minus operators.\n\n\t* OPERATORS/op-int.h, OPERATORS/op-cm-cm.cc,\n\tOPERATORS/op-cs-cs.cc, OPERATORS/op-m-m.cc, OPERATORS/op-range.cc:\n\tDefine and install unary plus operator.\n\n\t* ov.cc (unary_op_as_string): Handle op_uplus too.\n\n\t* parse.y (prefix_expr): Build unary plus op here instead of\n\tconverting to no-op.\n\t(make_prefix_op): Accept op_uplus.\n\n2004-09-03  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-b-bm.cc (DEFCONV): Define bool scalar to bool\n\tmatrix conversion.\n\t(install_b_bm_ops): Install it.\n\tInstall conversion for assignment of bool matrix to indexed bool.\n\t* OPERATORS/op-b-b.cc (install_b_b_ops): Install conversion for\n\tassignment of bool to indexed bool.\n\n2004-09-03  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-b-b.cc, OPERATORS/op-b-bm.cc, OPERATORS/op-bm-b.cc,\n\tOPERATORS/op-bm-bm.cc: Modify concatenation between boolean types\n\tso that it returns a boolean.\n\n\t* ov-bool.cc (octave_bool::do_index_op): Return boolean matrix.\n\n\t* ov-intx.h (do_index_op (const octave_value_list&, int)):\n\tNew function for indexed subsref of int types.\n\n2004-09-03  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-int.h (OCTAVE_SM_INT_OPS): Define int by double\n\tmixed comparison and bool ops.\n\t(OCTAVE_INSTALL_SM_INT_OPS): Install them.\n\t(OCTAVE_MS_INT_OPS): Define double by int mixed comparison and\n\tbool ops.\n\t(OCTAVE_INSTALL_MS_INT_OPS): Install them\n\n\t* OPERATORS/op-i8-i8.cc, OPERATORS/op-i16-i16.cc,\n\tOPERATORS/op-i32-i32.cc, OPERATORS/op-i64-i64.cc,\n\tOPERATORS/op-ui8-ui8.cc, OPERATORS/op-ui16-ui16.cc,\n\tOPERATORS/op-ui32-ui32.cc, OPERATORS/op-ui64-ui64.cc:\n\tDefine and install various mixed-type operators.\n\n\t* OPERATORS/op-int.h (OCTAVE_MM_INT_OPS): Also define mixed int\n\tand double matrix comparison and bool ops.\n\t(OCTAVE_INSTALL_MM_INT_OPS): Install them.\n\t(OCTAVE_SS_INT_BOOL_OPS, OCTAVE_SM_INT_BOOL_OPS,\n\tOCTAVE_MS_INT_BOOL_OPS, OCTAVE_MM_INT_BOOL_OPS):\n\tDefine logical AND and OR ops.\n\t(OCTAVE_INSTALL_SS_INT_BOOL_OPS, OCTAVE_INSTALL_SM_INT_BOOL_OPS,\n\tOCTAVE_INSTALL_MS_INT_BOOL_OPS, OCTAVE_INSTALL_MM_INT_BOOL_OPS):\n\tInstall them.\n\t(OCTAVE_MM_INT_CMP_OPS, OCTAVE_MM_INT_BOOL_OPS): Accept prefix arg.\n\t(OCTAVE_MM_CONV): New macro.\n\t(OCTAVE_MM_INT_OPS): Use it to define complex matrix conversion.\n\t(OCTAVE_MIXED_INT_CMP_OPS, OCTAVE_MIXED_INT_BOOL_OPS): New macros.\n\n\t* OPERATORS/op-int.h (OCTAVE_MS_INT_OPS): Don't define indexed int\n\tmatrix = complex scalar assignment ops.\n\t(OCTAVE_MS_INT_OPS): Don't define indexed int matrix = complex\n\tmatrix assignment ops.\n\t(OCTAVE_SM_CONV): New macro.\n\t(OCTAVE_SM_INT_OPS): Use it to define int scalar -> (int|complex)\n\tmatrix widening ops.\n\t(OCTAVE_RE_INT_ASSIGN_OPS, OCTAVE_CX_INT_ASSIGN_OPS): New macros.\n\t(OCTAVE_INT_OPS): Use them here.\n\t(OCTAVE_INSTALL_SS_INT_OPS): Install indexed int scalar = scalar\n\tand indexed int scalar = complex scalar assignment conversions.\n\t(OCTAVE_INSTALL_SM_INT_OPS): Install int scalar -> (int|complex)\n\tmatrix widening ops.  Install indexed int scalar =\n\t(int|real|complex) matrix assignment conversions.\n\t(OCTAVE_INSTALL_MS_INT_OPS): Install indexed int matrix = complex\n\tscalar assignment conversion.\n\t(OCTAVE_INSTALL_MM_INT_OPS): Install int matrix -> complex matrix\n\twidening op.  Install indexed int matrix = complex matrix\n\tassignment conversion.\n\t(OCTAVE_INSTALL_RE_INT_ASSIGN_OPS, OCTAVE_INSTALL_CX_INT_ASSIGN_OPS):\n\tNew macros.\n\t(OCTAVE_INSTALL_INT_OPS): Use them.\n\n\t* op-int.h: (OCTAVE_INSTALL_SM_INT_ASSIGNCONV): New macro.\n\t* OPERATORS/op-i8-i8.cc, OPERATORS/op-i16-i16.cc,\n\tOPERATORS/op-i32-i32.cc, OPERATORS/op-i64-i64.cc,\n\tOPERATORS/op-ui8-ui8.cc, OPERATORS/op-ui16-ui16.cc,\n\tOPERATORS/op-ui32-ui32.cc, OPERATORS/op-ui64-ui64.cc:\n\tUse it to define mixed size integer scalar/integer matrix\n\tassignment conversions.\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::complex_array_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::complex_array_vale):\n\tNew functions.\n\n2004-09-02  John W. Eaton  <jwe@octave.org>\n\n\t* DLD-FUNCTIONS/quad.cc (Fquad): Pass \"__quad_fcn_\" instead of\n\t\"__quad_fcn__\" to unique_symbol_name.\n\n\t* ov-fcn-inline.cc (octave_fcn_inline): Pass \"__inline_\" instead\n\tof \"__inline__\" to unique_symbol_name.\n\n\t* variables.cc (unique_symbol_name): Make better random symbol name.\n\n2004-09-01  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.58.\n\n\t* Makefile.in (OP_INCLUDES): New variable.\n\tInclude OPERATORS/op-int.h here.\n\t* Makefile.in (dist): Also link $(OP_INCLUDES).\n\n\t* Makefile.in (DISTFILES): Include $(EXTRAS) in the list.\n\n2004-09-01  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTION/quad.cc: Allow function handle and inline functions.\n\tUse a unique function name and delete it on exit.\n\n\t* ov.h (is_inline_function): New virtual function.\n\t* ov-fcn-inline.h (is_inline_function): New function.\n\t* ov-base.h (is_inline_function): New function.\n\n\t* ov-fcn-inline.cc (octave_fcn_handle::octave_fcn_handle):\n\tUse unique_symbol_name and clear_function instead of manipulating\n\tsymbol table directly.\n\n\t* variables.cc (unique_symbol_name): New function.\n\t(clear_function): New function.\n\t* variables.h: Provide decls.\n\n\t* dynamic-ld.cc (do_clear_function): Rename from clear_function.\n\n2004-09-01  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-i8-i8.cc, OPERATORS/op-i16-i16.cc,\n\tOPERATORS/op-i32-i32.cc, OPERATORS/op-i64-i64.cc,\n\tOPERATORS/op-ui8-ui8.cc, OPERATORS/op-ui16-ui16.cc,\n\tOPERATORS/op-ui32-ui32.cc, OPERATORS/op-ui64-ui64.cc:\n\tDefine and install mixed assignment ops.\n\t* op-int.h: Define mixed integer/double ops.\n\tDefine simple division ops.\n\n\t* ov-complex.h (octave_complex_scalar): New typedef to simplify\n\tvarious macros where naming consistency matters.\n\n2004-08-31  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-int.h (ss_pow, ms_el_pow, mm_el_pow): New power\n\tfunctions.\n\t(sm_el_pow): Return correct type.\n\t(OCTAVE_SS_POW_OPS, OCTAVE_SM_POW_OPS, OCTAVE_MS_POW_OPS,\n\tOCTAVE_MM_POW_OPS): New macros to define the power operator over\n\tinteger types.\n\t(OCTAVE_SS_INT_OPS, OCTAVE_SM_INT_OPS, OCTAVE_MS_INT_OPS,\n\tOCTAVE_MM_INT_OPS): Use the new macros for the power operators.\n\t(OCTAVE_INSTALL_SS_INT_OPS, OCTAVE_INSTALL_MS_INT_OPS,\n\tOCTAVE_INSTALL_MM_INT_OPS): Install new power functions.\n\n\t* OPERATORS/op-int-conv.cc (INT_CONV_FUNCTIONS): Correct return\n\ttypes for unsigned integer scalars and signed integer matrices.\n\n\t* ov-type-conv.h (OCTAVE_TYPE_CONV_BODY3): Conversion betwen same\n\ttypes returns the original value.\n\n\t* bitfcns.cc (BITOP): Fix for mixed scalar/matrix ops. Allow\n\toctave_range as an argument, by using class_name rather than\n\ttype_id to test.\n\n2004-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.cc (pr_int): Also handle bank_format.\n\t(octave_print_internal (std::ostream& os, const intNDArray<T>&,\n\tbool, int)): Likewise.\n\n2004-08-31  David Bateman  <dbateman@free.fr>\n\n\t* pr-output.cc (pr_int(std::ostream, const T&, int)):\n\tNew template function to print formatted integer types.\n\tInstantiate it for all of the integer types.\n\t(octave_print_internal (std::ostream, const intNDArray<T>&, bool,\n\tint)): Use pr_int.  Align output up in columns, and check for\n\tfree_format or plus_format.\n\t(octave_print_internal (std::ostream, const octave_int<T>&, bool)):\n\tUse pr_int.  Check for free_format and plus_format.\n\n\t* ls-hdf5.cc (hdf5_read_next_data): When importing hdf5 files,\n\tallow structures and lists (for backward compatibility).  Also\n\tallow importation of integer types into octave int and uint types.\n\n2004-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* data.cc (fill_matrix, identity_matrix): Convert class name to\n\toct_data_conv::data_type and switch on that.\n\t(identity_matrix (int, int)): New template.\n\t(identity_matrix (int, int, const std::string&)): Use it.\n\n\t* ov.h (octave_type_traits, octave_array_type_traits): Move here.\n\t* oct-stream.cc: From here.\n\n2004-08-31  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (Fzeros, Fones, Feye): Update help text for optional\n\tclass argument.\n\t(static octave_value identity_matrix (int, int, const std::string&)):\n\tNew function to create identity matrices with an arbitrary type.\n\t(Feye): Call new version of identity matrix function, even for scalars.\n\t(static octave_value fill_matrix (const octave_value_list&, double,\n\tconst char *)): Update to allow arbitrary classes of matrices to be\n\tcreated.\n\n2004-08-31  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat5.cc (read_int): New function.\n\n\t* oct-stream.cc (octave_base_stream::do_read,\n\toctave_base_stream::read, octave_base_stream::write): Delete.\n\t* oct-stream.h: Delete decls.\n\n\t* oct-stream.cc (octave_stream::read): Handle block_size and\n\tseparate input/output types.\n\t(octave_stream::write): Handle block_size and various input types.\n\t(octave_type_traits, octave_array_type_traits):\tNew traits classes.\n\t(do_read): New templates to read data and perform type conversion.\n\t(octave_stream::write (const Array<T>&, int,\n\toct_data_conv::data_type, int, oct_mach_info::float_format),\n\tdo_write, write_int):\n\tNew templates to write ints and perform type conversion.\n\tInstantiate for various Octave types.\n\n\t* ov.cc (octave_value::write): New function.\n\t* ov.h: Provide decl.\n\t* ov-base.cc (octave_base_value::write): New function.\n\t* ov-base.h: Provide decl.\n\t* ov-complex.h (octave_complex::write): New function.\n\t* ov-cx-mat.h (octave_complex_matrix::write): New function.\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::write): New function.\n\t(OCTAVE_VALUE_INT_SCALAR_T::write): New function.\n\t* ov-re-mat.h (octave_matrix::write): New function.\n\t* ov-scalar.h (octave_scalar::write): New function.\n\t* ov-str-mat.h (octave_char_matrix_str::write): New function.\n\n\t* file-io.cc (Ffread): Handle block size, to/from format in\n\tprecision argument.\n\t(Ffwrite): Handle block size in precision argument.\n\n2004-08-25  David Bateman  <dbateman@free.fr>\n\n\t* ov-cell.cc (octave_cell::subsasgn): Delete elements of cell array\n\twhen type is \"(\" and rhs is empty.\n\n2004-08-09  John W. Eaton  <jwe@octave.org>\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::index_vector,\n\tOCTAVE_VALUE_INT_SCALAR_T::index_vector): New functions.\n\n2004-08-06  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-struct.cc: New file.\n\t* ov-struct.h (octave_struct::resize (const dim_vector&)):\n\tNew function.\n\t* oct-map.h (Octave_map::resize (const dim_vector&)): New function.\n\t* ov-map.cc (Octave_map::reshape):\n\tCorrect return for same sized reshape.\n\t(Octave_map::resize (const dim_vector&)): New function.\n\t(concat (const Octave_map&, const Octave_map&, const Array<int>&)):\n\tComplete concatenation function.\n\t* Makefile.in (OP_XSRC): Include op-struct.cc in the list.\n\n2004-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* pt-stmt.h (tree_statement::set_command,\n\t(tree_statement::set_expression): New functions.\n\n\t* parse.y (param_list_beg): Handle pushing new symbol table\n\tcontext for anonymous function handle parameter lists here.\n\t(anon_fcn_handle): New non-terminal.\n\t(expression): Include anon_fcn_handle here.\n\t(make_anon_fcn_handle): New static function.\n\n2004-08-05  David Bateman  <dbateman@free.fr>\n\n\t* ov.cc (octave_value::fcn_inline_value): New virtual function.\n\t* ov.h (octave_value::fcn_inline_value): Provide decl.\n\t* ov-base.cc (octave_base_value::fcn_inline_value): New function\n\t* ov-base.h (octave_base_value::fcn_inline_value): Provide decl.\n\t* ov-fcn-handle.cc (octave_fcn_handle::octave_fcn_handle\n\t(const std::string&, const string_vector&, const std::string&),\n\toctave_fcn_handle::convert_to_str_internal, Finline, Fargnames,\n\tFformula, Fvectorize): Delete.\n\t(octave_fcn_handle::print_raw): Remove inline case.\n\t* ov-fcn-handle.h (octave_fcn_handle::fcn_type,\n\toctave_fcn_handle::octave_fcn_handle (const std::string&, const\n\tstring_vector&, const std::string&),\n\toctave_fcn_handle::inline_fcn_name,\n\toctave_fcn_handle::inline_fcn_text,\n\toctave_fcn_handle::inline_fcn_arg_names,\n\toctave_fcn_handle::is_inline,\n\toctave_fcn_handle::convert_to_str_internal,\n\toctave_fcn_handle::typ, octave_fcn_handle::iftext,\n\toctave_fcn_handle::ifargs): Delete constructors,\n\tfunctions, and data members (moved to ov-fcn-inline.h).\n\t* Makefile.in: Include ov-fcn-inline.h and ov-fcn-inline.cc where\n\tappropriate.\n\t* ov-fcn-inline.h, ov-fcn-inline.cc: New class.\n\n2004-08-05  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-int.cc (octave_base_int_matrix<T>::save_ascii,\n\toctave_base_int_matrix<T>::load_ascii,\n\toctave_base_int_matrix<T>::save_binary,\n\toctave_base_int_matrix<T>::load_binary,\n\toctave_base_int_matrix<T>::save_hdf5,\n\toctave_base_int_matrix<T>::load_hdf5,\n\toctave_base_int_matrix<T>::try_narrowing_conversion,\n\toctave_base_int_scalar<T>::print_raw,\n\toctave_base_int_scalar<T>::save_ascii,\n\toctave_base_int_scalar<T>::load_ascii,\n\toctave_base_int_scalar<T>::save_binary,\n\toctave_base_int_scalar<T>::load_binary,\n\toctave_base_int_scalar<T>::save_hdf5,\n\toctave_base_int_scalar<T>::load_hdf5):\n\tSprinkle with this-> as needed.\n\n\t* Makefile.in (EXTRAS): New macro.  Move ov-base-int.cc here from\n\tOV_INTTYPE_SRC.\n\t(INCLUDES_FOR_INSTALL): New macro.\n\t(install-inc, uninstall): Use it instead of INCLUDES.\n\n\t* variables.h (symbol_exist): Default for type is now \"any\".\n\n2004-08-05  David Bateman  <dbateman@free.fr>\n\n\t* ov-fcn-handle.cc (octave_fcn_handle (const std::string&,\n\tconst string_vector&, const std::string&)): New constructor for inline\n\tfunction handles.\n\t(octave_fcn_handle::print_raw): Allow inline functions to be printed.\n\t(octave_fcn_handle::convert_to_str_internal): New function to allow\n\tFchar to work on inlined function handles.\n\t(Finline, Fformula, Fargnames, Fvectorize): New functions.\n\t* ov-fcn-handle.h (octave_fcn_handle (const std::string&,\n\tconst string_vector&, const std::string&)): Provide decl.\n\t(octave_fcn_handle::convert_to_str_internal): Provide decl.\n\t(fcn_type): New enum for the type of function handle.\n\t(octave_fcn_handle::inline_fcn_text, octave_fcn_handle::is_inline,\n\toctave_fcn_handle::inline_fcn_arg_names): New functions.\n\t(octave_fcn_handle::typ, octave_fcn_handle::iftext,\n\toctave_fcn_handle::ifargs): New private variables for inline functions.\n\n2004-08-04  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (fcn_handle):\n\tRecognize '@' FCN_HANDLE rather than just FCN_HANDLE.\n\tDecrement lexer_flags.looking_at_function_handle here.\n\t* lex.h (lexical_feedback::looking_at_function_handle):\n\tNew data member.\n\t(lexical_feedback::init): Initialize it.\n\t* lex.l (handle_identifier): Only reject keywords if we are\n\tlooking at a function handle.\n\t(\"@\"): Recognize this separately from what follows.\n\tIncrement lexer_flags.looking_at_function_handle here.\n\n\t* ov-fcn-handle.h (octave_fcn_handle::octave_fcn_handle\n\t(octave_function*, const std::string)): Delete.\n\t* ov.h, ov.cc (octave_value::octave_value (octave_function *)): Delete.\n\t(octave_value::octave_value (octave_function *, const std::string)):\n\tDelete.\n\n\t* ov-fcn-handle.h (octave_fcn_handle::fcn): Now octave_value, not\n\tpointer to octave_function.\n\t(octave_fcn_handle::octave_fcn_handle (const octave_value&, const\n\tstd::string)): New constructor.\n\t* variables.cc (lookup_function): Return octave_value, not pointer\n\tto octave_function.  Change all uses.\n\t(lookup_user_function): Return octave_value, not pointer\n\tto octave_user_function.  Change all uses.\n\n2004-08-03  John W. Eaton  <jwe@octave.org>\n\n\t* ov-usr-fcn.cc (octave_user_fcn::do_multi_index_op): Call\n\tinstall_automatic_vars here.\n\t(octave_user_fcn::octave_user_fcn): Not here.\n\t(install_automatic_vars): Don't mark argn_sr, nargin_sr,\n\tnargout_sr, or varargin_sr as static.\n\n\t* oct-stream.cc (octave_scan): Avoid need for pushing two\n\tcharacters back on the input stream.\n\n2004-08-02  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_scan): For %i format, recognize numbers\n\twith leading 0x or 0X as hex and leading 0 as octal.\n\n\t* OPERATORS/op-fcn-handle.cc: Delete.\n\t* Makefile.in (OP_XSRC): Delete it from the list.\n\t* pr-output.cc (octave_print_internal (std::ostream&, const\n\tstd::string&, bool, int): New function.\n\t* ov-fcn-handle.cc (octave_value::subsref): New function.\n\t* ov-fcn-handle.h (class fcn_handle_elt, class fcn_handle_array):\n\tDelete.\n\t(class octave_fcn_handle): Derive from octave_base_value, not\n\toctave_base_matrix<fcn_handle_array>.\n\n\t* ov-cx-mat.cc (try_narrowing_conversion): Also allow complex to\n\treal conversion for N-d arrays.\n\n2004-07-30  John W. Eaton  <jwe@octave.org>\n\n\t* lex.l (<COMMAND_START>[^#% \\t\\r\\n\\;\\,\\\"\\'][^ \\t\\r\\n\\;\\,]*{S}*):\n\tAlso recognize \\r as a word list separator.\n\n2004-07-27  John W. Eaton  <jwe@octave.org>\n\n\t* bitfcns.cc (DO_BITSHIFT): Pass mask to bitshift.\n\t(bitshift (double, int, EIGHT_BYTE_INT): New arg, mask.\n\t(DO_UBITSHIFT, DO_SBITSHIFT): Use bitshfit, not operator >>.\n\tUse nbits function from octave_int type to set bits_in_type.\n\n\t* ov-struct.cc (Fisfield): Only print usage message if number of\n\targuments is incorrect.  Return false for invalid arguments.\n\tFrom Andy Adler <adler@site.uottawa.ca>.\n\n2004-07-27  David Bateman  <dbateman@free.fr>\n\n\t* Cell.cc (Cell::index): Quit early if an error occurs when\n\tcreating index vector object.\n\n\t* ov-int8.cc, ov-int16.cc, ov-int32.cc, ov-int64.cc, ov-uint8.cc,\n\tov-uint16.cc, ov-uint32.cc, ov-uint64.cc (HDF5_SAVE_TYPE): Define\n\tfor HDF5 native format for the type.\n\n\t* ov-base-int.h (save_ascii, save_binary, load_binary, save_hdf5):\n\tDelete unused arguments.\n\n\t* ov-base-int.cc (octave_base_int_matrix::save_ascii,\n\toctave_base_int_matrix::save_binary,\n\toctave_base_int_scalar::save_ascii,\n\toctave_base_int_scalar::save_binary,\n\toctave_base_int_scalar::save_hdf5): Delete unused argument.\n\n\t* ov-base-int.cc (octave_base_int_matrix::save_binary,\n\toctave_base_int_matrix::load_binary,\n\toctave_base_int_matrix::save_hdf5,\n\toctave_base_int_matrix::load_hdf5,\n\toctave_base_int_scalar::save_ascii,\n\toctave_base_int_scalar::load_ascii,\n\toctave_base_int_scalar::save_binary,\n\toctave_base_int_scalar::load_binary,\n\toctave_base_int_scalar::save_hdf5,\n\toctave_base_int_scalar::load_hdf5): Implement missing functions.\n\n2004-07-23  David Bateman  <dbateman@free.fr>\n\n\t* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::array_value,\n\tOCTAVE_VALUE_INT_SCALAR_T::array_value): new methods to extract array\n\tvalue from integer types.\n\n\t* bitfcns.cc (BITOPX): New Macro renamed from BITOP.\n\t(BITOP): Alter to allow different types and call BITOP appropriately.\n\t(DO_SBITSHIFT, DO_UBITSHIFT): New macros for signed, unsigned\n\tbitshifts.\n\n\t(DO_BITSHIFT): Test for shift of more bits than in type, which is\n\tundefined.  Generalize to allow double args as well.\n\t(Fbitshift): Add int and double types.\n\t(Fbitmax): Return 53 bit value which conforms to IEEE754 double\n\tmantissa.\n\t(Fintmax, Fintmin): New functions.\n\t(Fbitget, Fbitset, Fbitcmp): Delete.\n\n\t* OPERATORS/op-int.h: Add sm_el_pow function\n\n\t* ops.h (CATOPDECL, DEFCATOPX, DEFCATOP, DEFCATOP_FB, DEFNDCATOP_FN,\n\tCATOP_NONCONFORMANT, INSTALL_CATOP): New macros.\n\n\t* OPERATORS/op-b-b.cc, OPERATORS/op-b-bm.cc, OPERATORS/op-bm-b.cc,\n\tOPERATORS/op-bm-bm.cc, OPERATORS/op-cell.cc, OPERATORS/op-chm.cc,\n\tOPERATORS/op-cm-cm.cc, OPERATORS/op-cm-cs.cc, OPERATORS/op-cm-m.cc,\n\tOPERATORS/op-cm-s.cc, OPERATORS/op-cs-cm.cc, OPERATORS/op-cs-cs.cc,\n\tOPERATORS/op-cs-m.cc, OPERATORS/op-cs-s.cc, OPERATORS/op-m-cm.cc,\n\tOPERATORS/op-m-cs.cc, OPERATORS/op-m-m.cc, OPERATORS/op-m-s.cc,\n\tOPERATORS/op-range.cc, OPERATORS/op-s-cm.cc, OPERATORS/op-s-cs.cc,\n\tOPERATORS/op-s-m.cc, OPERATORS/op-s-s.cc, OPERATORS/op-str-str.cc,\n\tOPERATORS/op-str-m.cc, OPERATORS/op-str-s.cc (CATOPDECL, DEFCATOPX,\n\tDEFCATOP, DEFCATOP_FB, DEFNDCATOP_FN, CATOP_NONCONFORMANT,\n\tINSTALL_CATOP): Use them to define concatenation functions.\n\n\t* OPERATORS/op-int.h (OCTAVE_CONCAT_FN, OCTAVE_INSTALL_CONCAT_FN):\n\tNew macros to define and install concatentaion functions for int/uint\n\ttypes.\n\n\t* TEMPLATE-INST/Array-tc.cc (INSTANTIATE_ARRAY_CAT): Delete.\n\n\t* pt-mat.cc (tm_row_const::tm_row_const_rep::do_init_element):\n\tAlso append empty elements to the list of elements to be parsed.\n\t(tree_matrix::rvalue): Use new concatenation binary operators.\n\n\t* data.cc (cat_add_dims): Delete (now dim_vector::concat).\n\t(do_cat): Use new concatenation binary operators.\n\n\t* ov-typeinfo.cc (cat_op_fcn): Instantiate the array of cat functions.\n\t(register_cat_op, do_register_cat_op, do_lookup_cat_op): New functions.\n\t(cat_ops): Lookup table of binary concatentaion operators.\n\n\t* ov-typeinfo.h (lookup_cat_op): New function.\n\n\t* ov.cc (gripe_cat_op, gripe_cat_op_conv, do_cat_op): New functions.\n\n\t* ov.h (cat_op_fcn): Definition.\n\t(resize, do_cat_op): New functions.\n\n\t* ov-intx.h (resize): New_function\n\n\t* version.h (OCTAVE_API_VERSION): Bump version to api-v9.\n\n\t* Cell.cc, Cell.h, oct-map.cc, oct-map.h (cat): Delete.\n\t(concat): New function.\n\n\t* Cell.cc, Cell.h (insert): New function\n\n\t* ov-base.cc, ov-base.h, ov-scalar.h, ov-complex.h, ov-bool.h,\n\tov-range.h, ov-base-mat.h, (resize): New function.\n\n2004-07-23  John W. Eaton  <jwe@octave.org>\n\n\t* symtab.cc (whos_parameter): Move decl here, from symtab.h.\n\n2004-07-23  Oyvind Kristiansen  <oyvinkri@stud.ntnu.no>\n\n\t* symtab.cc (symbol_record::subsymbols_list): New method.\n\t(symbol_record::maybe_list): Call to subsymbols_list and merge\n\tresult with the original list of symbols.\n\n\t* symtab.cc (symbol_record::make_dimensions_string): New method.\n\t(symbol_record::print_symbol_info_line): Print N-d info.  Output\n\tfor long format now under control of format string.\n\t(symbol_table::maybe_list): Headers to whos listing updated.\n\tAlso print footer info.\n\t(symbol_table::print_descriptor): Method printing the\n\theader of whos listings.\n\t(symbol_table::parse_whos_line_format): New method.\n\t(whos_line_format, Vwhos_line_format): New built-in variables.\n\t(symbols_of_symtab): DEFVAR them.\n\t(symbol_record::nelem, symbol_record::symbol_def::nelem,\n\tsymbol_record::byte_size, symbol_record::symbol_def::byte_size):\n\tNew methods.\n\t(symbol_record::dimensions_string_req_first_space): New\tmethod.\n\t(symbol_record::dimensions_string_req_total_space): New\tmethod.\n\t* symtab.h (whos_parameter): New struct.  Container for one\n\tparameter in whos_line_format.\n\n2004-07-22  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* DLD-FUNCTIONS/dassl.cc (Fdassl): Fix doc string.\n\t* ov-struct.cc (Fstruct): Likewise.\n\t* symtab.cc (Fdebug_symtab_lookups): Likewise.\n\n2004-07-22  David Bateman  <dbateman@free.fr>\n\n\t* data.cc (Fsize): Return 1 for dimensions exceeding ndim.\n\n\t* ov.cc (octave_value::octave_value (const ArrayN<double>)):\n\tNew constructor.\n\t* ov.h: Provide decl.\n\t* ov-cx-mat.h (octave_complex_matrix (const ArrayN<Complex>&)):\n\tNew constructor.\n\t* ov-re-mat.h (octave_complex_matrix (const ArrayN<double>&)):\n\tNew constructor.\n\n\t* ov-re-mat.h (octave_matrix(const ArrayN<double>&)): New constructor\n\t* pt-loop.cc (DO_ND_LOOP): New macro for use of NDArray in for loop.\n\t(tree_simple_for_command::eval): Use it, and allow iteration over\n\tcell arrays.\n\n2004-07-12  John W. Eaton  <jwe@octave.org>\n\n\t* ov-intx.h: N-d array and scalar extractor functions take no args.\n\n\t* ov.h (octave_value::int8_scalar_value,\n\toctave_value::int16_scalar_value, octave_value::int32_scalar_value,\n\toctave_value::int64_scalar_value, octave_value::uint8_scalar_value,\n\toctave_value::uint16_scalar_value, octave_value::uint32_scalar_value,\n\toctave_value::uint64_scalar_value): New functions.\n\t* ov-base.cc (octave_base_value::int8_scalar_value,\n\toctave_base_value::int16_scalar_value,\n\toctave_base_value::int32_scalar_value,\n\toctave_base_value::int64_scalar_value,\n\toctave_base_value::uint8_scalar_value,\n\toctave_base_value::uint16_scalar_value,\n\toctave_base_value::uint32_scalar_value,\n\toctave_base_value::uint64_scalar_value): New functions.\n\t* ov-base.h: Provide decls.\n\n\t* lex.l: (Vtoken_count): New static variable.\n\t(COUNT_TOK_AND_RETURN): New macro.  Use it everywhere a token is\n\treturned to the parser.\n\t(F__token_count__): New function.\n\n2004-06-25  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-int-conv.cc: Add conversions for range type.\n\n2004-06-17  John W. Eaton  <jwe@octave.org>\n\n\t* bitfcns.cc (bitfcns): New file.\n\t* Makefile.in (DIST_SRC): Add it to the list.\n\n2004-06-16  John W. Eaton  <jwe@octave.org>\n\n\t* OPERATORS/op-int.h: New file.\n\t* OPERATORS/op-i16-i16.cc, OPERATORS/op-i8-i8.cc,\n\tOPERATORS/op-ui32-ui32.cc, OPERATORS/op-i32-i32.cc,\n\tOPERATORS/op-int-conv.cc, OPERATORS/op-ui64-ui64.cc,\n\tOPERATORS/op-i64-i64.cc, OPERATORS/op-ui16-ui16.cc,\n\tOPERATORS/op-ui8-ui8.cc: Use new macros from op-int.h.\n\n2004-06-14  John W. Eaton  <jwe@octave.org>\n\n\t* pr-output.h, pr-output.cc (octave_print_conv): New traits class.\n\t(template <class T> void octave_print_internal (std::ostream&,\n\tconst intNDArray<T>&, bool, int),\n\t(template <class T> void octave_print_internal (std::ostream&,\n\tconst octave_int<T>&, bool)): New template functions.\n\tInstantiate versions for new int types.\n\n\t* ov-typeinfo.h (octave_value_typeinfo::type_conv_ops):\n\tNew data member.\n\t(octave_value_typeinfo::register_type_conv_op,\n\toctave_value_typeinfo::lookup_type_conv_op,\n\toctave_value_typeinfo::do_register_type_conv_op,\n\toctave_value_typeinfo::do_lookup_type_conv_op): New functions.\n\n\t* ov-re-mat.cc (Fdouble): New function.\n\n\t* ov-range.h (octave_range::reshape): Reshape array_value, not\n\tmatrix_value.\n\n\t* ov-base-scalar.h (octave_base_scalar<ST>::all,\n\toctave_base_scalar<ST>::any, octave_base_scalar<ST>::is_true): Use\n\tST() instead of 0.0.\n\n\t* ov-base-mat.h (octave_base_matrix<MT>::byte_size): New function.\n\n\t* ops.h (INSTALL_COLNVOP, DEFCONVFNX, DEFDBLCONVFN, DEFCONVFN,\n\tDEFCONVFN2): New macros.\n\n\t* DLD-FUNCTIONS/filter.cc (Ffilter): Kluge type conversions.\n\n\t* ov.cc (install_types): Register new integer types.\n\n\t* ov.h, ov.cc (octave_value::octave_value (const octave_int8&),\n\toctave_value::octave_value (const octave_uint8&),\n\toctave_value::octave_value (const octave_int16&),\n\toctave_value::octave_value (const octave_uint16&),\n\toctave_value::octave_value (const octave_int32&),\n\toctave_value::octave_value (const octave_uint32&),\n\toctave_value::octave_value (const octave_int64&),\n\toctave_value::octave_value (const octave_uint64&),\n\toctave_value::octave_value (const int8NDArray&),\n\toctave_value::octave_value (const uint8NDArray&),\n\toctave_value::octave_value (const int16NDArray&),\n\toctave_value::octave_value (const uint16NDArray&),\n\toctave_value::octave_value (const int32NDArray&),\n\toctave_value::octave_value (const uint32NDArray&),\n\toctave_value::octave_value (const int64NDArray&),\n\toctave_value::octave_value (const uint64NDArray&)):\n\tNew constructors.\n\n\t* ov.h (octave_value::internal_rep): New function.\n\t(DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA): Also define\n\tstatic_type_id, static_type_name, and static_class_name\n\tfunctions.\n\n\t* Cell.h (Cell::reshape (const dim_vector&)): New forwarding\n\tfunction for return type conversion.\n\n\t* ov-int16.cc, ov-int16.h, ov-int32.cc, ov-int32.h, ov-int64.cc,\n\tov-int64.h, ov-int8.cc, ov-int8.h, ov-uint16.cc, ov-uint16.h,\n\tov-uint32.cc, ov-uint32.h, ov-uint64.cc, ov-uint64.h, ov-uint8.cc,\n\tov-uint8.h, ov-type-conv.h, ov-int-traits.h,\n\tOPERATORS/op-int-conv.cc, OPERATORS/op-double-conv.cc,\n\tOPERATORS/op-i16-i16.cc, OPERATORS/op-i32-i32.cc,\n\tOPERATORS/op-i64-i64.cc, OPERATORS/op-i8-i8.cc,\n\tOPERATORS/op-ui16-ui16.cc, OPERATORS/op-ui32-ui32.cc,\n\tOPERATORS/op-ui64-ui64.cc, OPERATORS/op-ui8-ui8.cc: New files.\n\tMakefile.in: Add them to the appropriate lists.\n\n2004-06-03  John W. Eaton  <jwe@octave.org>\n\n\t* ov-fcn-handle.h (octave_function_handle::is_matrix_type,\n\toctave_function_handle::is_numeric_type,\n\toctave_function_handle::is_constant,\n\toctave_function_handle::is_true): New functions.\n\t(octave_function_handle::is_defined): Delete (inherited version is\n\tOK).\n\n2004-06-03  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/filter.cc: Fix for length(a)=1 && length(b)=2 case.\n\n2004-05-07  John W. Eaton  <jwe@octave.org>\n\n\t* ov.cc (octave_value::print_with_name): Only print name tag if\n\tVprint_answer_id_name is true.\n\n\t* octave.cc (intern_argv): Insert __nargin__ in top_level_sym_tab\n\tinstead of making it a builtin variable.  Mark it static.\n\t* ov-usr-fcn.cc (octave_user_function::install_automatic_vars):\n\tMark local automatic variables static.\n\n2004-04-30  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (octave_base_stream::clearerr): New function.\n\t(octave_stream::clearerr): New function.\n\t(seek (long, int)): Call clearerr here.\n\t* oct-stdstrm.h (octave_stdiostream::clear): New function.\n\t* c-file-ptr-stream.h (c_file_ptr_buf::clear,\n\ti_c_file_ptr_stream::clear, o_c_file_ptr_stream::clear,\n\tio_c_file_ptr_stream::clear): New functions.\n\n2004-04-29  David Bateman  <dbateman@free.fr>\n\n\t* load-save.cc (Fload, Fsave): Accept -mat as well as -mat-binary.\n\n2004-04-27  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/sort.cc: Add missing \"class\" keywords to template\n\tinstantiations.\n\n2004-04-22  John W. Eaton  <jwe@octave.org>\n\n\t* pt-plot.cc (Fclearplot): Temporarily turn off automatic_replot.\n\tClear display after resetting title, labels, etc.\n\n2004-04-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-colon.cc (tree_colon_expression::rvalue): Also check for\n\terror_state after evaluating each subexpression.\n\n2004-04-22  David Bateman  <dbateman@free.fr>\n\n\t* ov-base-scalar.h (octave_base_scalar<ST>::permute): New function.\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::is_true): Make N-d aware.\n\n2004-04-22  John W. Eaton  <jwe@octave.org>\n\n\t* oct-stream.cc (printf_value_cache::curr_value): Now NDArray.\n\t(printf_value_cache::double_value): Extract N-d array, not Matrix.\n\n2004-04-21  John W. Eaton  <jwe@octave.org>\n\n\t* parse.y (function2): Pass id name to frob_function.  Delete id.\n\t(frob_function): Accept function name instead of identifier.\n\tDon't try to rename symbol table entry.  Lookup symbol record for\n\tfunction name here.  Insert name in symbol table if needed.\n\tOperate on symbol record instead of identifier.\n\n2004-04-21  David Bateman  <dbateman@free.fr>\n\n\t* DLD_FUNCTIONS/fft.cc(do_fft): Correctly initialize the variable dim\n\tfor scalar arguments.\n\n\t* DLD-FUNCTIONS/minmax.cc: Handle single vector arg correctly.\n\n2004-04-20  John W. Eaton  <jwe@octave.org>\n\n\t* ls-mat-ascii.cc (read_mat_ascii_data): Prepend \"X\" to keywords.\n\tOnly drop text after last \".\" in name.\n\n\t* lex.l (is_keyword): New function.\n\t(Fiskeyword): Use it.\n\t* lex.h: Provide decl.\n\n\t* lex.l (is_keyword_token): Rename from is_keyword.\n\n2004-04-16  John W. Eaton  <jwe@octave.org>\n\n\t* file-io.cc (maybe_warn_interface_change): New function.\n\t(fopen_mode_to_ios_mode): Use it.\n\n2004-04-16  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* file-io.cc (fopen_mode_to_ios_mode):  Default to binary mode.\n\t(Ffopen): Document 't' and 'b' mode flags.\n\n2004-04-16  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (DLD_XSRC): Add gcd.cc to the list.\n\n2004-04-16  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/gcd.cc: New file.\n\n2004-04-15  David Bateman  <dbateman@free.fr>\n\n\t* ov-ch-mat.h: convert_to_str_interal returns charNDArray.\n\n2004-04-12  John W. Eaton  <jwe@octave.org>\n\n\t* version.h (OCTAVE_BUGS_STATEMENT): Bug list is now bug@octave.org.\n\n2004-04-08  John W. Eaton  <jwe@octave.org>\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::do_index_op): Quit early\n\tif an error occurs when creating index vector object.\n\n\t* ov.cc (octave_value::numeric_assign): Always call maybe_mutate\n\ton return value.\n\n2004-04-06  David Bateman  <dbateman@free.fr>\n\n  \t* DLD_FUNCTIONS/sort.cc: Use the new template sort class, adapt for\n\tN-d arrays, and allow optional dim argument.\n\n\t* DLD_FUNCTIONS/fftn.cc: Save result of transpose operation.\n\tCheck for failure of transpose.\n\n2004-04-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-bool.h (octave_bool::bool_array_value): New function.\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::subsasgn): Don't allow\n\texpressions like x(i)(j) or x(i){j} when x is empty.\n\n\t* load-save.cc (get_file_format): Error if file does not exist.\n\t(Fload): Also complain here if specific file type is specified and\n\tfile does not exist.\n\n2004-04-02  Quentin Spencer  <qspencer@ieee.org>\n\n\t* parse.y: Use persistent instead of static in warnings messages.\n\n2004-04-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-decl.cc (tree_static_command::do_init): Initialize to empty\n\tmatrix by default.\n\n2004-04-02  David Bateman  <dbateman@free.fr>\n\n\t* ov-re-mat.cc (octave_matrix::convert_to_str_internal):\n\tReturn charNDArray.\n\t* ov-bool-mat.cc (octave_bool_matrix::convert_to_str_internal):\n\tCall array_value.\n\n\t* DLD-FUNCTIONS/besselj.cc, DLD-FUNCTIONS/betainc.cc,\n\tDLD-FUNCTIONS/gammainc.cc, DLD-FUNCTIONS/minmax.cc,\n\tDLD-FUNCTIONS/filter.cc:\n\tConvert for N-d array, better Matlab compatibility.\n\n\t* load-save.cc (Fload): Better handling of non existent files.\n\n2004-03-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-list.cc (octave_list::subsref): Correctly create return value.\n\tReturn comma-separate list if {-style indexing extracts more than\n\tone value.\n\n2004-03-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.57.\n\t(OCTAVE_API_VERSION): Now api-v8.\n\n\t* ov-cell.cc (octave_cell::save_hdf5): Handle empty cells.\n\t(octave_cell::load_hdf5): Likewise.\n\n2004-03-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::subsasgn): If empty,\n\tallow type conversion when indexing with \"{\" and \".\".\n\n2004-03-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (init_format_state): Also set compact_format.\n\t(pr_col_num_header): Print one newline character before column\n\theaders for compact format.\n\n2004-03-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_WWW_STATEMENT): New macro.\n\t(OCTAVE_STARTUP_MESSAGE): Include it here.\n\t(OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_WARRANTY_AND_BUGS): And here.\n\n\t* octave.cc (verbose_usage): Use OCTAVE_WWW_STATEMENT here.\n\n\t* DLD-FUNCTIONS/find.cc (find_nonzero_elem_idx): If there are no\n\tnonzero elements, return [](0x1) or [](1x0), not [](0x0).\n\tCorrectly preserve orientation for row vectors.\n\n2004-03-08  Petter Risholm  <risholm@idi.ntnu.no>\n\n\t* data.cc (do_cat): Check for length of args before getting dimension.\n\tNew arg, fname.  Print usage message corresponding to fname.\n\t(Fcat): Pass \"cat\" as fname arg to do_cat.\n\t(Fhorzcat): Pass \"horzcat\" as fname arg to do_cat.\n\t(Fvertcat): Pass \"vertcat\" as fname arg to do_cat.\n\n2004-03-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.56.\n\t(OCTAVE_API_VERSION): Now api-v7.\n\n2004-03-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-struct.cc (Frmfield): New function\n\n\t* oct-map.h (Octave_map::contains): Return bool, not int.\n\n\t* ov-cell.cc (Fiscellstr): No error if arg is not a cell array.\n\t(Fcellstr): Return arg if it is already a cell array of character\n\tstrings.\n\n2004-03-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-bool.cc (octave_bool::load_hdf5, octave_bool::save_hdf5):\n\tAvoid unnecessary casts.\n\t* ov-bool-mat.cc (octave_bool_matrix::load_hdf5,\n\toctave_bool_matrix::save_hdf5): Likewise.\n\t* ov-cell.cc (octave_cell::load_hdf5, octave_cell::save_hdf5):\n\tLikewise.\n\t* ov-complex.cc (octave_complex::load_hdf5,\n\toctave_complex::save_hdf5): Likewise.\n\t* ov-cx-mat.cc (octave_complex_matrix::load_hdf5,\n\toctave_complex_matrix::save_hdf5): Likewise.\n\t* ov-range.cc (octave_range::load_hdf5, octave_range::save_hdf5):\n\tLikewise.\n\t* ov-re-mat.cc (octave_matrix::load_hdf5, octave_matrix::save_hdf5):\n\tLikewise.\n\t* ov-scalar.cc (octave_scalar::load_hdf5, octave_scalar::save_hdf5):\n\tLikewise.\n\t* ov-str-mat.cc (octave_char_matrix_str::load_hdf5,\n\toctave_char_matrix_str::save_hdf5): Likewise.\n\n2004-03-03 David Bateman  <dbateman@free.fr>\n\n\t* ov-cell.cc (octave_cell::save_hdf5, octave_cell::load_hdf5):\n\tMake N-d aware.\n\n2004-03-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y: Delete spaces surrounding = in %name-prefix directive.\n\n2004-03-01  Petter Risholm  <risholm@idi.ntnu.no>\n\n\t* Cell.cc (Cell::cat): New function.\n\t* Cell.h: Provide decl.\n\n\t* oct-map.cc (Octave_map::cat): New function.\n\t* oct-map.h: Provide decl.\n\n\t* data.cc (Fcat): Speedup implementation.\n\n\t* data.cc (Fhorzcat, Fvertcat): New functions.\n\n\t* Array-tc.cc: Instantiate cat function.\n\n2004-03-01  David Bateman  <dbateman@free.fr>\n\n\t* ls-hdf5.cc (save_hdf5_empty, load_hdf5_empty): New functions\n\tto save/load empty matrices keeping their dimensions.\n\t* ls-hdf5.h (save_hdf5_empty, load_hdf5_empty): Provide decls.\n\n\t* ov-re-mat.cc (save_hdf5, load_hdf5): Cleanup, check empty matrix.\n\t* ov-cx-mat.cc (save_hdf5, load_hdf5): Ditto.\n\t* ov-bool-mat.cc (save_hdf5, load_hdf5): Ditto.\n\n\t* ov-str-mat.cc (save_ascoo, load_ascii, save_binary,\n\tload_binary, save_hdf5, load_hdf5): Cleanup, check empty matrix,\n\tand save/load N-d arrays.\n\n2004-02-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (execute_startup_files): Don't find current directory\n\tfor absolute name of local_rc until after executing home_rc.\n\n2004-02-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (input_event_hook): Return type is now int.  Return 0.\n\n\t* file-io.cc (do_stream_open): Don't call ::error if stream can't\n\tbe created.  Don't call ::fopen if arch is invalid.  Set error\n\tstate for stream if fopen fails.\n\t* oct-stream.h (octave_stream::error (const char *)): New function.\n\t(octave_stream::error (const std::string&)): Now public.\n\n2004-02-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (Fftell): Return long integer instead of streamoff_array.\n\t(do_stream_open): Create octave_stdiostream instead of octave_fstream.\n\n\t* oct-fstrm.cc (octave_fstream::seek, octave_fstream::tell):\n\tAlways fail.  Signatures now match C library functionsb.\n\t* oct-iostrm.cc (octave_base_iostream::seek,\n\toctave_base_iostream::tell): Likewise.\n\t* oct-strstrm.cc (octave_base_strstream::seek,\n\toctave_base_strstream::tell): Likewise.\n\n\t* oct-stream.cc (octave_stream::seek, octave_stream::tell):\n\tSignatures now match C-library functions.\n\n\t* oct-stdstrm.cc (octave_stdiostream::seek, octave_stdiostream::tell):\n\tCall io_c_file_ptr_stream::seek and tell.  Signatures now match\n\tC-library functions.\n\n\t* c-file-ptr-stream.h (c_file_ptr_buf::seek, c_file_ptr_buf::tell):\n\tNew functions.\n\t(i_c_file_ptr_stream::seek, i_c_file_ptr_stream::tell): Likewise.\n\t(o_c_file_ptr_stream::seek, o_c_file_ptr_stream::tell): Likewise.\n\t(io_c_file_ptr_stream::seek, io_c_file_ptr_stream::tell): Likewise.\n\n2004-02-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.55.\n\t(OCTAVE_API_VERSION): Now api-v6.\n\n\t* sighandlers.cc (sigfpe_handler, sigpipe_handler):\n\tDon't increment\toctave_interrupt_state if it is less than 0.\n\t(sigint_handler): If octave_interrupt_state is less than zero,\n\treset it.\n\n\t* pt-except.cc (do_catch_code): Call OCTAVE_QUIT here so the catch\n\tcode won't run if an interrupt is pending.  Don't run catch code\n\tif octave_interrupt_state is less than zero.\n\n2004-02-20  Per Persson  <persquare@mac.com>\n\n\t* Makefile.in (OCT_LINK_DEPS, OCTINTERP_LINK_DEPS):\n\tInclude\t$(LIBS) in the list before $(FLIBS).\n\n2004-02-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (octave_print_internal (std::ostream&, const\n\tRange&, bool, int)): Don't print values beyond the limits of the\n\trange.\n\n\t* sighandlers.cc (sigint_handler): Print message after two\n\tconsecutive interrupts, dump core after three or more.\n\n\t* load-save.cc (dump_octave_core): Handle core size limit.\n\tRename from save_user_variables.  Change all callers.\n\t(Fload, dump_octave_core, Fsave): Open HDF5 fils in binary mode.\n\t(do_save): Extract switch over file types to separate function.\n\n\t* load-save.cc (Voctave_core_file_limit): New variable.\n\t(octave_core_file_limit): New function.\n\t(symbols_of_load_save): Add DEFVAR for octave_core_file_limit.\n\n\t* load-save.cc (Voctave_core_file_name): New variable.\n\t(octave_core_file_name): New function.\n\t(symbols_of_load_save): Add DEFVAR for octave_core_file_name.\n\n\t* load-save.cc (Voctave_core_file_format):\n\tRename from Voctave_core_format.\n\t(octave_core_file_format): Rename from octave_core_format.\n\t(symbols_of_load_save): Fix DEFVAR to match.\n\n2004-02-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.cc (Fsizeof): New function.\n\n\t* ov.h (octave_value::byte_size): New function.\n\t* ov-base.h (octave_base_value::byte_size): New function.\n\t* ov-base-scalar.h (octave_base_scalar::byte_size): New function.\n\t* ov-bool-mat.h (octave_bool_matrix::byte_size): New function.\n\t* ov-ch-mat.h (octave_char_matrix::byte_size): New function.\n\t* ov-cx-mat.h (octave_complex_matrix::byte_size): New function.\n\t* ov-re-mat.h (octave_matrix::byte_size): New function.\n\t* ov-range.h (octave_range::byte_size): New function.\n\t* ov-cell.cc (octave_cell::byte_size): New function.\n\t* ov-cell.h: Provide decl.\n\t* ov-struct.cc (octave_struct::byte_size): New function.\n\t* ov-struct.h: Provide decl.\n\t* ov-streamoff.h (octave_streamoff::byte_size): New function.\n\t* ov-list.cc (octave_list::byte_size): New function.\n\t* ov-list.h: Provide decl.\n\n\t* xpow.cc (elem_xpow (const Matrix&, double)):\n\tConvert both operands to Complex if any element of A is negative.\n\t(elem_xpow (const NDArray&, double)): Likewise.\n\n2004-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (Voctave_core_format): New static_variable.\n\t(octave_core_format): New function.\n\t(symbols_of_load_save): Add DEFVAR for octave_core_format.\n\t(get_save_format): Rename from get_default_save_format.\n\tPass name of format as arg.  New optional arg, fallback_format.\n\tChange all uses.\n\t(save_user_variables): Use pass Voctave_core_format to\n\tget_save_format here.  Pass LS_BINARY as fallback_format.\n\n\t* sighandlers.cc (my_friendly_exit): New optional arg, save_vars.\n\tOnly call save_user_variables if save_vars is true.\n\t(sigint_handler): If interactive, offer to abort and save\n\tworkspace after three consecutive interrupts.\n\t(sigint_handler, sigpipe_handler, sigfpe_handler):\n\tIncrement octave_interrupt_handler instead of setting it to 1.\n\n2004-02-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.54.\n\t(OCTAVE_API_VERSION): Now api-v5.\n\n\t* Makefile.in (DLD_XSRC): Always include fftw_wisdom.cc.\n\n\t* DLD-FUNCTIONS/fftw_wisdom.cc:\n\tRename from DLD-FUNCTIONS/fft_wisdom.cc.\n\t(Vfftw_wisdom_prog): Delete extern decl.\n\t(Ffftw_wisdom): Rename from Ffft_wisdom.\n\tUse Vfftw_wisdom_prog instead of Vwisdom_prog.\n\tAlways define function.  Signal error if not configured to use FFTW3.\n\n\t* defaults.cc (symbols_of_defaults): Rename WISDOM_PROGRAM to be\n\tFFTW_WISDOM_PROGRAM.\n\t(Vfftw_wisdom_prog): Rename from Vwisdom_prog.\n\t(fftw_wisdom_program): Rename from wisdom_program.\n\tFor simplicity, always define FFTW_WISDOM_PROGRAM even when not\n\tusing fftw3.\n\t(set_default_wisdom_prog): Look for OCTAVE_FFTW_WISDOM_PROGRAM in\n\tthe environment instead of OCTAVE_WISDOM_PROGRAM.\n\t(set_default_fftw_wisdom_prog): Rename from set_default_wisdom_prog.\n\t* defaults.h.in (Vfftw_wisdom_prog): Provide extern decl.\n\n2004-02-16 David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/fft.cc: Adapt for Nd arrays, combine with ifft.cc.\n\t* DLD-FUNCTIONS/ifft.cc: Delete.\n\t* DLD-FUNCTIONS/fft2.cc: Adapt for Nd arrays, combine with ifft.cc.\n\t* DLD-FUNCTIONS/ifft2.cc: Delete.\n\t* DLD-FUNCTIONS/fftn.cc: New function for Nd FFT and inverse FFT.\n\t* DLD-FUNCTIONS/fft_wisdom.cc: New function to manipulate FFTW\n\twisdom.\n\n\t* Makefile.in: Remove ifft.cc and ifft2.cc.  Add fftn.cc and\n\tifftn.cc.  Make building of fft-wisdom.cc conditional on the\n\tvalue of FFTW_LIBS.\n\t* defaults.cc (Vwisdom_prog): New variable\n\t(set_default_wisdom_prog, wisdom_prog): New functions.\n\t(symbols_of_defaults): Add DEFVAR for wisdom_prog.\n\n2004-02-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-list.cc (octave_list::subsasgn): Call assign for Cell objects\n\there, not the base octave_value::assign.\n\n2004-02-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (yywrap): Don't #undef this symbol.\n\n2004-02-15  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* pt-mat.cc: Make [,] concatenation work for N-d arrays.\n\n2004-02-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (do_cat): Merge with Fcat.\n\n2004-02-15  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* ov-cell.cc (Fstruct2cell): New function.\n\n2004-02-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (OCTINTERP_LINK_DEPS, OCT_LINK_DEPS): Always define.\n\n\t* oct-conf.h.in: Add OCTAVE_CONF_DL_LD, OCTAVE_CONF_DL_LDFLAGS,\n\tand OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS.\n\tDelete OCTAVE_CONF_MKOCTFILE_SH_LDFLAGS.\n\n\t* toplev.cc (octave_config_info): Delete MKOCTFILE_SH_LDFLAGS.\n\tAdd DL_LD, DL_LDFLAGS, and MKOCTFILE_DL_LDFLAGS to the struct.\n\n2004-02-14  Per Persson  <persquare@mac.com>\n\n\t* Makefile.in (%.oct): Use DL_LD instead of SH_LD to build .oct files.\n\n2004-02-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-base-scalar.h (octave_base_scalar::squeeze): New function.\n\n2004-02-13  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* data.cc (Fcat): New function.\n\t* data.cc (do_cat): New function.\n\t* data.cc (cat_add_dims): New function.\n\n2004-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (main_loop): Call octave_parse, not yyparse.\n\t* octave.cc (octave_main): Increment octave_debug, not yydebug.\n\t* parse.y (%name-prefix): New directive, set to \"octave_\".\n\t* parse.h: Provide declarations for octave_lex and octave_parse\n\tinstead of yylex and yyparse.\n\t* lex.l (%option prefix): New directive, set to \"_octave\".\n\tDefine yylval to be octave_lval.\n\tMove definitions of YY_INPUT, YY_FATAL_ERROR, TOK_RETURN,\n\tTOK_PUSH_AND_RETURN, BIN_OP_RETURN, XBIN_OP_RETURN here.\n\t* lex.h: From here.\n\n2004-02-07  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* ov-struct.cc (Fcell2struct): New function.\n\t(cell2struct_check_args, cell2struct_construct_idx): Likewise.\n\n2004-02-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-scalar.h (octave_scalar::empty_clone):\n\tReturn empty octave_matrix, not an octave_scalar object.\n\t* ov-complex.h (octave_complex::empty_clone):\n\tReturn empty octave_complex_matrix, not an octave_complex object.\n\n2004-02-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-usr-fcn.h (octave_user_function::function_name): Delete.\n\t(octave_user_function::fcn_name): Delete unused data member.\n\t(octave_user_function::stash_function_name): Save name in\n\ttree_function::my_name instead of fcn_name.\n\tChange all uses of fcn_name to be my_name instead.\n\n\t* pt.h, pt.cc (tree::break_function): Now pointer to\n\toctave_function rather than octave_user_function object.\n\n\t* pt-bp.h (MAYBE_DO_BREAKPOINT): Use name instead of function_name\n\tto get name from curr_function.\n\t* pt-pr-code.cc (tree_print_code::visit_octave_user_function_header):\n\tlikewise.\n\t* debug.cc (Fdbwhere, Fdbtype, ): Likewise\n\t* error.cc (pr_where): Likewise.\n\t* variables.cc (Fmlock, Fmunlock, Fmislocked): Likewise.\n\t(lookup_function, lookup_user_function,\tlink_to_builtin_or_function):\n\tLikewise, for curr_parent_function.\n\n\t* debug.cc (get_user_function, Fdbwhere):\n\tCast curr_function to pointer to octave_user_function.\n\n\t* ov-mapper.cc (octave_mapper::do_multi_index_op):\n\tSave and restore curr_function here.\n\t* ov-builtin.cc (octave_builtin::do_multi_index_op): Likewise.\n\n\t* toplev.h, toplev.cc (curr_function, curr_parent_function): Now\n\tpointers to octave_function rather than octave_user_function objects.\n\n\t* ov-usr-fcn.h (octave_user_function::is_user_function): New function.\n\t* ov-fcn.h (octave_function::takes_varargs,\n\toctave_function::octave_va_start, octave_function::octave_va_arg,\n\toctave_function::octave_all_va_args,\n\toctave_function::takes_var_return, octave_function::octave_vr_val,\n\toctave_function::is_user_function): New virtual functions.\n\n2004-02-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-struct.cc (Fstruct): Use new Octave_map constructor to create\n\tstructures with specified sizes but no keys.\n\n\t* ov-struct.cc (Fstruct): New function, from Paul Kienzle\n\t<pkienzle@users.sf.net> and Petter Risholm  <risholm@stud.ntnu.no>.\n\n\t* oct-map.h (Octave_map::Octave_map): Allow dimension to be\n\tspecified for map with no keys.\n\n\t* ov-struct.cc (fieldnames): Return 0x1 cell array if no fieldnames.\n\n2004-02-05  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::do_index_op):\n\tDon't fail if number of indices is greater than 2.\n\n2004-02-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (Fsize): Update for N-d objects.\n\n\t* ls-mat5.cc (read_mat5_binary_element): Force conversion.\n\n\t* ov-base.cc (octave_base_value::char_matrix_value):\n\tPass force arg to convert_to_str.\n\n\t* data.cc (Freshape): Chop trailing singletons from new dimensions.\n\n2004-02-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* error.cc (defun_usage_message): Only accept one arg, a const\n\tstd::string& object.  Change all uses.  Pass nul-terminated string\n\tto defun_message_1.\n\t(defun_usage_message_1): New function, equivalent to old\n\tdefun_usage_message.\n\n\t* ov-base.cc (nint_value): Use fix, not NINT.\n\t(INT_CONV_METHOD): Likewise, use fix instead of just casting.\n\n\t* data.cc (make_diag): Use int_value instead of nint_value to\n\textract k for Matlab compatibility.\n\t(Flinspace): Likewise, for npoints.\n\t(fill_matrix): Likewise, for extracting dims.\n\t(Fsize): Likewise, for extracting dim argument.  Require int value.\n\t* utils.cc (get_dimensions): Likewise.  Use fix, not NINT.\n\n2004-02-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* error.cc (verror, error_1): New arg, os.  Use this instead\n\tof always printing to std:cerr.  Change all callers.\n\n\t* error.cc (defun_usage_message): New function.\n\t* error.h: Provide decl.\n\t* defun.cc (print_usage): Use it to display error message.\n\n\t* error.cc (verror): New arg, save_last_error.  Change all callers.\n\t(usage): Set error_state after calling verror.\n\n\t* oct-map.cc (Octave_map::assign (const std::string, const Cell&)):\n\tSet dimensions to RHS dimensions, not 1x1.\n\n2004-01-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-bool.cc, ov-cx-mat.cc, ov-re-mat.cc, ov-str-mat.cc:\n\tInclude <vector>.\n\t* file-io.cc, ls-hdf5.cc, ls-mat4.cc, ls-mat5.cc, ls-oct-binary.cc:\n\tInclude <vector>, not <memory> for new defn of OCTAVE_LOCAL_BUFFER.\n\t* load-save.cc, ls-mat-ascii.cc, ls-oct-ascii.cc\n\tNo need to include <memory> now.\n\n\t* DLD-FUNCTIONS/eig.cc (Feig): Use new optional arg for EIG to\n\tavoid computing eigenvectors if not requested.\n\tBased on a patch from David Bateman  <dbateman@free.fr>.\n\n2004-01-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cell.cc (all_strings): Always compute total required length\n\tof retval.\n\n2004-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.53.\n\t(OCTAVE_API_VERSION): Now api-v4.\n\n\t* error.cc (pr_where): New arg, print_code with default value true.\n\t(warning): Call pr_where with second arg false.\n\n\t* file-io.cc (Ffrewind): Only return value if nargout > 0.\n\t(Ffprintf): Likewise.\n\t(Fprintf): Likewise.\n\n\t* file-io.cc (Ffrewind): Return 0 for success, -1 for failure.\n\tMake docs match.\n\n\t* Makefile.in (distclean): Remove DOCSTRINGS.\n\t(maintainer-clean): Remove $(OPT_HANDLERS).\n\n2004-01-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cell.cc (octave_cell::subsref): Make '{' case N-d aware.\n\n\t* ov-scalar.cc (streamoff_array_value): New function.\n\t* ov-scalar.h: Provide decl.\n\n\t* OPERATORS/op-streamoff.cc (STREAMOFF_COMP_OP): New maco.\n\tUse it to define streamoff by matrix, streamoff by scalar, scalar\n\tby streamoff, and matrix by streamoff comparison operators.\n\t(install_streamoff_ops): Install them.\n\n\t* Cell.h (Cell::operator ()): Delete (we inherit them from Array<T>).\n\t(maybe_resize, elem_internal): Delete unused functions.\n\n\t* ls-mat5.cc (write_mat5_cell_array): Cell& arg is now const.\n\n2004-01-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (is_valid_function): If warn, also print error\n\tmessage if arg is not a string.\n\n\t* ov-usr-fcn.cc (Fnargin, Fnargout): New functions.\n\n\t* octave.cc (intern_argv): Lookup __nargin__ instead of nargin.\n\t* ov-usr-fcn.cc (octave_user_function::install_automatic_vars):\n\tLookup __nargin__ and __nargout__ instead of nargin and nargout.\n\n\t* variables.h (at_top_level): Now extern.\n\t(lookup_user_function): New function.\n\t* variables.cc: Provide decls.\n\n\t* ov.h, ov.cc (octave_value::user_function_value):\n\tNew virtual function.\n\t* ov-base.h, ov-base.cc (octave_base_value::user_function_value):\n\tProvide default version.\n\t* ov-usr-fcn.h (octave_user_function::user_function_value):\n\tNew function.\n\n\t* ov-re-mat.cc (complex_array_value): New function.\n\t* ov-re-mat.h: Provide decl.\n\n\t* ov-cell.cc (Fiscellstr): Don't return value on usage error.\n\n\t* error.cc: (symbols_of_error): Delete DEFVAR for error_text.\n\tDefine __error_text__ and error_text as aliases for lasterr.\n\n\t* error.cc (bind_global_error_variable,\tclear_global_error_variable):\n\tDelete.\n\t* variables.h: Delete decls.\n\n\t* parse.y (Feval, Fevalin): Don't call bind_global_error_variable.\n\tDon't add clear_global_error_variable to the unwind_protect stack.\n\tIncrement buffer_error_messages before evaluating \"eval\" code,\n\tdecrement it before evaluating \"catch\" code.\n\n\t* pt-except.cc (do_catch_code): Don't call bind_global_error_variable.\n\tDon't add clear_global_error_variable to the unwind_protect stack.\n\tDecrement buffer_error_messages here.\n\t(tree_try_catch_command::eval): Increment buffer_error_messages here.\n\n\t* error.cc, error.h (buffer_error_messages): Now an int.\n\n2004-01-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (octave_config_info): Add float_format,\n\twords_big_endian, and words_little_endian to the struct.\n\n2004-01-14  David Bateman  <dbateman@free.fr>\n\n\t* ov-cell.cc (octave_cell::load_hdf5): Fix for HDF5 version 1.6\n\thandling of number of objects in a group.\n\t* ov-struct.cc (octave_struct::load_hdf5): Likewise.\n\t* ov-list.cc (octave_list::load_hdf5): Likewise.\n\t* ls-hdf5.cc (read_hdf5_data): Likewise.\n\n2004-01-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ls-hdf5.h: Surround contents with #if defined (HAVE_HDF5).\n\n2004-01-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (convert_to_valid_int, get_size):\n\tUse lo_ieee_is_NaN_or_NA instead of xisnan.\n\t(octave_base_stream::do_printf): Correct special case check for\n\tNA, NaN, Inf, or out of range integers.\n\n\t* dirfns.cc (Fglob): Always return list of files as a cell array.\n\t(Freaddir): Likewise.\n\n\t* dirfns.cc (Fls): If nargout > 0, return ls output.\n\n2004-01-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (Fload): Assume -force by default.\n\n\t* oct-stream.cc (octave_base_stream::write):\n\tAllow fwrite (fid, \"some string\") to work.\n\n\t* toplev.cc (Fcomputer): Delete.\n\t(octave_config_info): Add unix and windows fields to the struct.\n\n2004-01-06  David Bateman  <dbateman@free.fr>\n\n\t* ls-hdf5.cc: Fix handle of old versus new format files.\n\n \t* ls-oct-binary.cc: Split the load/save functionality into the types\n \tthemselves.  Backward compatibility maintained.\n\n \t* ov-struct.cc (save_binary, load_binary):\n \t* ov-str-mat.cc (save_binary, load_binary):\n \t* ov-scalar.cc (save_binary, load_binary):\n \t* ov-re-mat.cc (save_binary, load_binary):\n \t* ov-range.cc (save_binary, load_binary):\n \t* ov-list.cc (save_binary, load_binary):\n \t* ov-cx-mat.cc (save_binary, load_binary):\n \t* ov-complex.cc (save_binary, load_binary):\n \t* ov-cell.cc (save_binary, load_binary):\n \t* ov-bool.cc (save_binary, load_binary):\n \t* ov-bool-mat.cc (save_binary, load_binary):\n\tNew functions for loading and saving structures in octave binary\n\tformat.\n\n \t* ov-str-mat.h (save_binary, load_binary):\n \t* ov-scalar.h (save_binary, load_binary):\n \t* ov-re-mat.h (save_binary, load_binary):\n \t* ov-range.h (save_binary, load_binary):\n \t* ov-list.h (save_binary, load_binary):\n \t* ov-cx-mat.h (save_binary, load_binary):\n \t* ov-complex.h (save_binary, load_binary):\n \t* ov-cell.h (save_binary, load_binary):\n \t* ov-bool.h (save_binary, load_binary):\n \t* ov-bool-mat.h (save_binary, load_binary):\n \t* ov-struct.h (save_binary, load_binary):\n\tProvide decls.\n\n \t* ov.h (save_binary, load_binary): New virtual functions.\n\n \t* ov-base.cc (save_binary, load_binary): New functions, for fallbacks\n \twith error message.\n \t* ov-base.h: Provide decls.\n\n \t* load-save.cc: Remove \"-import\" flag and make it the default.\n \t* load-save.h: Likewise.\n\n \t* ls-oct-ascii.cc: Split the load/save functionality into the types\n \tthemselves. Save \"string\" variables with the name \"string\" rather than\n \tstring array. Backward compatiability maintained in ov-cs-mat.cc.\n \tInclude new version of extract_keyword that halts if the next value is\n \tinvalid rather that searching for the next valid value.\n\n \t* ls-oct-ascii.h: Extract_keyword header updated.\n\tInclude definition of OCT_RBV and CELL_ELT_TAG, since they are now\n\tused elsewhere.\n\n \t* ls-hdf5.cc: Split load/save functionality into the types themselves.\n \tThe hdf5 format is changed so that each object is a group with a\n \tdataset \"type\" being a string with the octave_value type and the\n \tdataset or group \"value\" containing the value of the data, struct, etc.\n \tThis allows extensibility. Backward compatibility is maintained. The\n \t\"import\" flag is now assumed to always be true and has been removed.\n\n \t* ov-struct.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-str-mat.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-scalar.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n\t* ov-re-mat.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-range.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-list.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-cx-mat.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-complex.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-cell.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-bool.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-bool-mat.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \tNew functions for loading and saving structures in octave ascii\n\tand hdf5 formatted files.\n\n \t* ov-struct.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-str-mat.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-scalar.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-re-mat.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-range.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-list.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-cx-mat.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-complex.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-cell.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-bool.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \t* ov-bool-mat.h (save_ascii, load_ascii, save_hdf5, load_hdf5):\n \tProvide decls.\n\n \t* ov-typeinfo.cc (octave_value_typeinfo::do_lookup_type): Include\n \tmake_unique so that the stored type value is not used for all loaded\n \tvariables.\n\n \t* ov.h: (save_ascii, load_ascii, save_hdf5 and load_hdf5):\n\tNew virtual functions.\n\n  \t* ov-base.cc (save_ascii, load_ascii, save_hdf5, load_hdf5):\n\tNew functions, for fallbacks with error message.\n\t* ov-base.h: Provide decls.\n\n2003-12-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cx-mat.cc (octave_complex_matrix::assign): RHS arg is N-d.\n\t* ov-cx-mat.h: Fix decl.\n\n\t* ops.h (DEFNDASSIGNOP_FN): New macro.\n\t* OPERATORS/op-bm-b.cc, OPERATORS/op-bm-bm.cc,\n\tOPERATORS/op-cm-cm.cc, OPERATORS/op-cm-cs.cc,\n\tOPERATORS/op-cm-m.cc, OPERATORS/op-cm-s.cc, OPERATORS/op-m-m.cc,\n\tOPERATORS/op-m-s.cc: Use it instead of DEFASSIGNOP_FN.\n\n2003-12-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* xpow.cc (xpow (double, double)): Avoid apparent GNU libm bug.\n\n2003-12-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* symtab.cc (symbol_record::print_symbol_info_line):\n\tAlso check is_static to see if a symbol can be cleared.\n\n2003-12-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (is_keyword): Also allow varargout_kw if\n\tlexer_flags.looking_at_return_list is false provided that we are\n\tdefining a function and we haven't seen the function name yet.\n\t* parse.y (return_list): Don't require [] around varargout.\n\n\t* DLD-FUNCTIONS/find.cc (DO_FIND_OP): Delete macro.\n\t(find_to_fortran_idx): Delete.  Move guts of function to\n\tfind_nonzero_elem_idx.\n\t(find_nonzero_elem_idx): Now a template function.  Handle overall\n\tarray index here too.  Make it N-d aware.\n\n\t* pt-pr-code.cc (tree_print_code::visit_complex_for_command,\n\ttree_print_code::visit_octave_user_function_header,\n\ttree_print_code::visit_matrix, tree_print_code::visit_cell,\n\ttree_print_code::visit_multi_assignment): Keep track of nearest\n\t[, {, or ( nesting level.\n\t(tree_print_code::visit_index_expression): Likewise.  Check nesting\n\tlevel to decide how to print index.\n\t(tree_print_code::reset): Also reset nesting level stack.\n\n\t* pt-pr-code.h (tree_print_code::nesting): New data member.\n\t(tree_print_code::tree_print_code): Initialize it.\n\n\t* ov-base-mat.h (octave_base_matrix::octave_base_matrix (const MT&)):\n\tIf arg has no dimensions, resize to be 0x0.\n\n2003-12-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-map.cc (Octave_map::assign): Use Octave_map::contents member\n\tfunction instead of operator [].\n\t* ov-struct.cc (octave_struct::subsasgn): Likewise.\n\t* DLD-FUNCTIONS/time.cc (extract_tm): Likewise.\n\n\t* DLD-FUNCTIONS/time.cc\t(mk_tm_map): Use Octave_map::assign member\n\tfunction instead of operator [].\n\t* DLD-FUNCTIONS/getrusage.cc (Fgetrusage): Likewise.\n\t* DLD-FUNCTIONS/getgrent.cc (mk_gr_map): Likewise.\n\t* DLD-FUNCTIONS/getpwent.cc (mk_pw_map): Likewise.\n\t* load-save.cc (do_load): Likewise.\n\t* ls-hdf5.cc (hdf5_read_next_data): Likewise.\n\t* ls-mat5.cc (read_mat5_binary_element): Likewise.\n\t* oct-map.cc (Octave_map::reshape): Likewise.\n\t* oct-map.cc (Octave_map::index): Likewise.\n\t* ov-fcn-handle.cc (Ffunctions): Likewise.\n\t* pt-idx.cc (make_arg_struct): Likewise.\n\t* sighandlers.cc (make_sig_struct): Likewise.\n\t* syscalls.cc (mk_stat_map): Likewise.\n\t* toplev.cc (Foctave_config_info): Likewise.\n\n\t* ls-hdf5.cc (add_hdf5_data): Temporary Octave_map is now const.\n\t* ls-mat5.cc (save_mat5_binary_element): Likewise.\n\n\t* oct-map.cc (Octave_map::assign (const std::string&, const\n\toctave_value&)): New function.\n\t* oct-map.h: Provide decl.\n\t(Octave_map::contents (const std::string&)): New function.\n\t(Octave_map::operator [] (const std::string&) const): Delete.\n\t(Octave_map::operator [] (const std::string&)): Delete.\n\n2003-12-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* OPERATORS/op-cell.cc: Allow transpose for cell arrays.\n\t* OPERATORS/op-m-m.cc, OPERATORS/op-cm-cm.cc,\n\tOPERATORS/op-bm-bm.cc, OPERATORS/op-streamoff.cc,\n\tOPERATORS/op-str-str.cc: Improve error message for attempt to\n\ttranspose N-d object.\n\n2003-11-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-arg-list.cc (F__end__): Handle N-d objects.\n\n2003-11-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* OPERATORS/op-b-bm.cc: New file.\n\n\t* OPERATORS/op-bm-b.cc (op_el_and, op_el_or): Define and install.\n\t* OPERATORS/op-bm-bm.cc (op_el_and, op_el_or, assign): Likewise.\n\n\t* ov-str-mat.cc (CHAR_MATRIX_CONV): New macro.\n\t* ov-str-mat.h (octave_char_matrix_str::double_value,\n\toctave_char_matrix_str::matrix_value,\n\toctave_char_matrix_str::array_value,\n\toctave_char_matrix_str::complex_value,\n\toctave_char_matrix_str::complex_matrix_value,\n\t(octave_char_matrix_str::complex_array_value): Use it.\n\n\t* ov-bool-mat.cc (default_numeric_conversion_function):\n\tConvert to NDArray, not Matrix.\n\t* ov-str-mat.cc (default_numeric_conversion_function): Likewise.\n\n\t* ov-range.h (octave_range::array_value): New function.\n\t(octave_range::complex_array_value): Likewise.\n\t* ov-ch-mat.h (charNDArray::array_value): New function.\n\t(charNDArray::complex_array_value): Likewise.\n\t* ov-str-mat.h (octave_char_matrix_str::array_value): Likewise.\n\t(octave_char_matrix_str::complex_value): Likewise.\n\t(octave_char_matrix_str::complex_matrix_value): Likewise.\n\t(octave_char_matrix_str::complex_array_value): Likewise.\n\n\t* mappers.cc (acosh, log, log10, sqrt):\n\tUse octave_Inf instead of DBL_MAX for range limit.\n\n2003-11-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.52.\n\t(OCTAVE_API_VERSION): Now api-v3.\n\n\t* DLD-FUNCTIONS/rand.cc (do_rand): Pass function name from arg\n\tlist in calls to error.\n\n\t* ov-cs-list.cc, ov-cs-list.h (octave_cs_list::octave_cs_list):\n\tExplicitly initialize base class in constructors.\n\n\t* ov.h (octave_value::all_strings): Pass second arg to rep function.\n\n\t* ov.h (octave_value::string_value): Pass arg to rep function.\n\n\t* DLD-FUNCTIONS/dasrt.cc (dasrt_user_f): Delete unused arg names.\n\t* DLD-FUNCTIONS/rand.cc (Frand, Frandn): Likewise.\n\t* ls-hdf5.h (hdf5_streambase::hdf5_streambase): Likewise.\n\t* ls-hdf5.cc (read_hdf5_data): Likewise.\n\t* ls-utils.cc (get_save_type): Likewise.\n\t* parse.y (Fassignin): Likewise.\n\t* utils.cc (empty_arg): Likewise.\n\t* ov-usr-fcn.h (octave_user_function::subsref): Likewise.\n\t* ov-base-mat.h (octave_base_matrix::subsref): Likewise.\n\t* ov-mapper.h (octave_mapper::subsref): Likewise.\n\t* ov-builtin.h (octave_builtin::subsref): Likewise.\n\t* ov-complex.cc (octave_complex::complex_array_value): Likewise.\n\t* ov-cell.h (octave_cell::subsref): Likewise.\n\t* ov-base-scalar.h (octave_base_scalar::subsref): Likewise.\n\t* ov-struct.h (octave_struct::subsref): Likewise.\n\t* ov-range.h (octave_range::subsref): Likewise.\n\t* ov-list.h (octave_list::subsref): Likewise.\n\t* ov-base.cc (octave_base_value::print_info): Likewise.\n\t* pt-check.cc (tree_checker::visit_subplot_axes): Likewise.\n\t* pr-output.cc (octave_print_internal (std::ostream&, double, bool),\n\toctave_print_internal (std::ostream&, const Complex&, bool),\n\toctave_print_internal (std::ostream&, const ArrayN<std::string>&,\n\tbool, int): Likewise.\n\t* oct-stream.cc (octave_scan<> (std::istream&, const\n\tscanf_format_elt&, char*): Likewise\n\t* TEMPLATE-INST/Array-tc.cc (resize_fill_value<octave_value>):\n\tLikewise.\n\t* pt-bp.cc (tree_breakpoint::visit_octave_user_function,\n\ttree_breakpoint::visit_octave_user_function_header,\n\ttree_breakpoint::visit_octave_user_function_trailer,\n\ttree_breakpoint::visit_plot_limits,\n\ttree_breakpoint::visit_plot_range,\n\ttree_breakpoint::visit_subplot,\n\ttree_breakpoint::visit_subplot_axes,\n\ttree_breakpoint::visit_subplot_list,\n\ttree_breakpoint::visit_subplot_style,\n\ttree_breakpoint::visit_subplot_using): Likewise.\n\t* ov.cc (octave_value::column_vector_value,\n\t(octave_value::complex_column_vector_value,\n\t(octave_value::row_vector_value,\n\toctave_value::complex_row_vector_value,\n\toctave_value::do_non_const_unary_op): Likewise.\n\n\t* load-save.cc: Only include ls-hdf5.h if HAVE_HDF5 is defined.\n\tFrom Melqart <melqart@free.fr>.\n\n\t* pr-output.h (octave_fcn_handle::print_as_scalar): Delete.\n\n\t* pr-output.cc (octave_print_internal): New version for\n\tArrayN<std::string> objects.\n\t* pr-output.h: Provide decl.\n\t* ov-fcn-handle.cc (octave_fcn_handle::print_raw): Use it.\n\n\t* OPERATORS/op-fcn-handle.cc: New file.\n\t* Makefile.in (OP_XSRC): Add it to the list.\n\n\t* ov-fcn-handle.h, ov-fcn-handle.cc (octave_fcn_handle):\n\tNow an array of function handle objects.\n\n\t* ov.h, ov.cc (octave_value::octave_value (const fcn_handle_array&),\n\t(octave_value::octave_value (octave_function *f, const std::string&)):\n\tNew constructors.\n\t(octave_value::octave_value (const octave_fcn_handle&)): Delete.\n\n\t* ov-base-mat.cc (octave_base_matrix<T>::print_as_scalar):\n\tCheck dims instead of rows and columns.\n\n\t* ov.h (octave_value::is_function_handle): New function.\n\t* ov-base.h (octave_base_value::is_function_handle): New function.\n\n2003-11-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-bool-mat.h (octave_bool_matrix::array_value): Construct return\n\tvalue directly from matrix data member, not matrix.matrix_value ().\n\n\t* ov-re-mat.h (octave_matrix::index_vector): Construct idx_vector\n\tfrom NDArray, not Matrix.\n\n\t* ov-bool-mat.h (octave_bool_matrix::index_vector): Construct\n\tidx_vector from boolNDArray, not boolMatrix.\n\n\t* ov.cc (install_types): Also register dld function type.\n\n\t* OPERATORS/op-streamoff.cc: Install increment and decrement operators.\n\t* ov-streamoff.h (octave_streamoff::increment,\n\toctave_streamoff::decrement): New functions.\n\n\t* ov-streamoff.h, ov-streamoff.cc: Move streamoff_array class to\n\tliboctave/so-array.h and liboctave/so-array.cc.\n\n\t* oct-stream.cc (octave_stream::seek): Extract std::streamoff from\n\ttc_offset instead of int.\n\n\t* ov-re-mat.cc (octave_matrix::double_value): Use numel, not length.\n\n\t* ov-re-mat.cc (octave_matrix::streamoff_array_value): New function.\n\t* ov-re-mat.h: Provide decl.\n\n\t* ov-scalar.cc (octave_scalar::streamoff_value): New function.\n\t* ov-scalar.h: Provide decl.\n\n\t* ov.cc (octave_value::streamoff_array_value,\n\toctave_value::streamoff_value): New functions.\n\t* ov.h: Provide decls.\n\n\t* ov-base.cc (octave_base_value::streamoff_array_value,\n\toctave_base_value::streamoff_value): New functions.\n\t* ov-base.h: Provide decls.\n\n\t* ov-usr-fcn.cc (install_automatic_vars): Don't do anything unless\n\tsym_tab is defined.\n\n\t* ov-streamoff.h, ov-streamoff.cc, OPERATORS/op-streamoff.cc:\n\tNew files.\n\n\t* ov-cell.h (octave_value_cell::is_matrix_type): New function.\n\n\t* ov-mapper.h (octave_mapper::octave_mapper): No copying.\n\t* ov-fcn.h (octave_function::octave_function): Likewise.\n\t* ov-usr-fcn.h (octave_function::octave_function): Likewise.\n\t* ov-builtin.h (octave_builtin::octave_builtin): Likewise.\n\t* ov-dld-fcn.h (octave_dld_function::octave_dld_function): Likewise.\n\n2003-11-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-mapper.h (octave_mapper::octave_mapper): Make public.\n\tProvide copy constructor and assignment operator.\n\t* ov-fcn.h (octave_function::octave_function): Likewise.\n\t* ov-builtin.h (octave_builtin::octave_builtin): Likewise.\n\t* ov-dld-fcn.h (octave_dld_function::octave_dld_function): Likewise.\n\n\t* ov-typeinfo.cc (octave_value_typeinfo::register_type,\n\toctave_value_typeinfo::do_register_type): New arg, val.\n\tSave it\tin vals array.\n\t(octave_value_typeinfo::lookup_type,\n\toctave_value_typeinfo::do_lookup_type): New functions.\n\t* ov-typeinfo.h: Provide decl.\n\t(octave_value_typeinfo::vals): New data member.\n\t(octave_value_typeinfo::octave_value_typeinfo): Initialize it.\n\n\t* ov.h (DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA): Pass\n\n\t* ov.h (DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA): Define register_type\n\there.  Also pass an empty object of the to-be-registered type to\n\tregister_type.\n\t(DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA): Declare register_type\n\there, but don't define it.\n\n2003-11-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-fcn-handle.h (octave_fcn_handle::octave_fcn_handle (void)):\n\tNew constructor.\n\n\t* ov-usr-fcn.h (octave_user_function::octave_user_function):\n\tDelete decl for private constructor.\n\n\t* ov-str-mat.cc (octave_char_matrix_str::matrix_value):\n\tConversion to matrix is an error unless explicitly forced.\n\n\t* ov-str-mat.cc (octave_char_matrix_str::double_value): New function.\n\t* ov-str-mat.h: Provide decl.\n\n\t* ov-file.cc (print_raw): Use parens around ?: conditional used on\n\tRHS of << output operator.\n\n\t* c-file-ptr-stream.cc (c_file_ptr_buf::seekoff,\n\tc_file_ptr_buf::seekpos): Can't use fseek here, so just fail (by\n\treturning -1) until we have a better solution.\n\n\t* oct-stream.cc (octave_stream::tell): Return std::streamoff, not long.\n\t* oct-iostrm.cc (octave_base_iostream::tell): Likewise.\n\t* oct-stdstrm.cc (octave_stdiostream::tell): Likewise.\n\t* oct-strstrm.cc (octave_base_strstream::tell): Likewise.\n\t* oct-stream.h, oct-iostrm.h, oct-stdstrm.h, oct-strstrm.h:\n\tFix decls to match.\n\n2003-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ls-mat-ascii.cc (get_lines_and_columns): Delete second arg in\n\tcall to istream::seekg.\n\n\t* ov-mapper.cc (MAPPER_LOOP_2, any_element_less_than,\n\tany_element_greater_than, octave_mapper::apply):\n\tHandle N-d arrays.\n\n2003-11-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ls-mat5.cc (read_mat5_binary_element, save_mat5_binary_element):\n\tHandle N-d arrays.\n\n\t* lex.l (next_token_is_index_op): New function.\n\t(handle_close_bracket): Use it.\n\n\t* ls-hdf5.cc, ls-mat-ascii.cc, ls-mat4.cc, ls-mat5.cc,\n\tls-oct-ascii.cc, ls-oct-binary.cc, ls-utils.cc, ls-hdf5.h,\n\tls-mat-ascii.h, ls-mat4.h, ls-mat5.h, ls-oct-ascii.h,\n\tls-oct-binary.h, ls-utils.h: New files, extracted from load-save.cc.\n\t* Makefile.in: Add them to the appropriate lists.\n\n2003-11-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (octave_print_internal): Don't indent rows for\n\tplus_format.  Use pr_plus_format for Range type with plus_format.\n\t(plus_format_chars): New static variable.\n\t(set_format_style): Allow optional arg for plus format to set it.\n\t(pr_plus_format): Use it.\n\n\t* ov-bool.h (octave_bool::array_value,\n\toctave_bool::complex_array_value): New functions.\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::do_index_op):\n\tEnsure correct number of indices for Array indexing code.\n\n2003-11-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/qz.cc (qz): Use x.data()+offset instead of &a(i,j).\n\tFirst and third args for dlag2 are const.\n\n\t* DLD-FUNCTIONS/sort.cc (Fsort): Use const qualifier as appropriate.\n\n\t* DLD-FUNCTIONS/balance.cc (balance): Use data() instead of\n\tfortran_vec where appropriate in call to dggbak.\n\n\t* DLD-FUNCTIONS/dasrt.cc (dasrt_user_j): Simplify inserting x and\n\txdot in arg vector.\n\t(dasrt_user_f): Likewise.\n\t(dasrt_user_cf): Likewise.\n\t* DLD-FUNCTIONS/dassl.cc (dassl_user_function): Likewise.\n\t(dassl_user_jacobian): Likewise.\n\t* DLD-FUNCTIONS/lsode.cc (lsode_user_function): Likewise.\n\t(lsode_user_jacobian): Likewise.\n\t* DLD-FUNCTIONS/daspk.cc (daspk_user_function): Likewise.\n\t(daspk_user_jacobian): Likewise.\n\n2003-11-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-range.h (octave_range::reshape): New function.\n\n2003-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.51.\n\t(OCTAVE_API_VERSION): Now api-v2.\n\n\t* version.h (OCTAVE_BUGS_STATEMENT): Also tell people to look at\n\thttp://www.octave.org/bugs.html.\n\n\t* oct-map.cc (Octave_map::assign): Use resize, not resize and fill.\n\t* ov-typeinfo.cc (octave_value_typeinfo::do_register_type): Likewise.\n\n\t* Cell.cc (Cell::Cell): Pass dim_vector to resize instead of two ints.\n\n2003-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (stamp-liboctave-prereq): New target.\n\t($(DEF_FILES), $(MAKEDEPS)): Depend on it.\n\t(distclean): Remove it.\n\n\t* parse.y (cancel_obj_idx): New rule.\n\t(postfix_expr, prefix_expr): Use begin_obj_idx after every\n\tpostfix_expr on RHS.  Use cancel_obj_idx as soon as possible for\n\tcases where we are not working on an index expression.\n\n\t* lex.l (maybe_unput_comma, handle_close_bracket):\n\tDon't insert comma if we are looking at an object index and the\n\tclosest nesting level is a brace.\n\n\t* parse.y (postfix_expr): Use begin_obj_idx between postfix_expr\n\tand the indexing delimiter rather than after it.\n\n\t* lex.h (lexical_feedback::braceflag): New member variable.\n\t* lex.l\t(lexical_feedback::init): Initialize braceflag.\n\t(\\{{S}*): Increment lexer_flags.braceflag, not\n\tlexer_flags.bracketflag.\n\t(handle_close_bracket): Handle lexer_flags.braceflag and\n\tlexer_flags.bracketflag separately based on bracket_type.\n\tDelete unnecesary yyinput/yyunput.\n\n\t* lex.l (next_token_is_postfix_unary_op): Also recognize ++ and --.\n\n\t* ov-typeinfo.cc (octave_value_typeinfo::register_type,\n\toctave_value_typeinfo::do_register_type):\n\tNew arg, c_name for class name.\n\t* ov-base.cc, ov-bool-mat.cc, ov-bool.cc, ov-builtin.cc,\n\tov-cell.cc, ov-ch-mat.cc, ov-colon.cc, ov-complex.cc,\n\tov-cs-list.cc, ov-cx-mat.cc, ov-dld-fcn.cc, ov-fcn-handle.cc,\n\tov-file.cc, ov-list.cc, ov-mapper.cc, ov-range.cc, ov-re-mat.cc,\n\tov-scalar.cc, ov-str-mat.cc, ov-struct.cc, ov-usr-fcn.cc,\n\tov-va-args.cc: Pass class name to DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA.\n\t* ov.h (octave_value::class_name): New virtual function.\n\t(DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA): Define c_name, for class name.\n\tPass c_name to octave_value_typeinfo::register_type.\n\t(DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA): Declare static member\n\tc_name for class name.  Provide class_name member function.\n\n\t* ov-typeinfo.cc (Fclass): New function.\n\n2003-11-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (Fisvarname): Pass correct name to make_argv.\n\n\t* ov-cell.cc (Fiscellstr): New function.\n\n\t* ov-file.h (octave_file::all, octave_file::any,\n\toctave_file::dims, octave_file::is_real_type,\n\toctave_file::ist_real_scalar): New functions.\n\n\t* lex.l (bracket_brace_paren_nesting_level::is_bracket_or_brace):\n\tNew function.\n\t(handle_close_bracket): New arg, bracket_type.  Change all uses.\n\tFirst arg is now bool.\n\t(<MATRIX_START>{SNLCMT}*\\}{S}*): New pattern.\n\t(maybe_unput_comma): Handle brace nesting level the same as brackets.\n\t(handle_close_brace): Likewise.\n\t(<MATRIX_START>{S}+): Likewise.\n\t(<MATRIX_START>{S}*{COMMENT}{SNLCMT}*): Likewise.\n\t(<MATRIX_START>{S}*{NL}{SNLCMT}*): Likewise.\n\t({NL}): Likewise.\n\t({CCHAR}): Likewise.\n\t(\")\"): Likewise.\n\t(\\{{S}*): Handle the same as \\[{S}*.\n\t(\"}\"): Handle the same as \\].\n\n\t* Makefile.in (stamp-prereq): Add oct-gperf.h, parse.cc, and\n\tlex.cc to the list.\n\n2003-11-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cell.cc (print_as_scalar): New function.\n\t* ov-cell.h: Provide decl.\n\n\t* ov-cell.cc (octave_cell::print_name_tag): Delete.\n\t* ov-cell.h: Delete decl.\n\n\t* ov-base-mat.cc (octave_base_matrix::print_name_tag): Delete.\n\t* ov-base-mat.h: Delete decl.\n\n\t* ov-base.cc (octave_base_value::print_name_tag):\n\tUse print_as_scalar here.\n\t* ov.h (octave_base_value::print_as_scalar): New virtual function.\n\t* ov-base.h (octave_base_value::print_as_scalar):\n\tNew default implementation.\n\t* ov-base-mat.h (octave_base_matrix::pirnt_as_scalar):\n\tDon't declare as virtual here.\n\n\t* ov-struct.cc (octave_struct::print_raw): If only printing keys,\n\talso print dimensions of fields and overall array.\n\n\t* sysdep.cc (Fnative_float_format): New function.\n\n\t* input.cc (generate_possible_completions): Also append all\n\tpossible filename completions here.\n\n2003-11-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc: Explicitly instantiate octave_scan functions.\n\n\t* TEMPLATE-INST/Array-c.cc, TEMPLATE-INST/Array-os.cc,\n\tTEMPLATE-INST/Array-sym.cc, ov-typeinfo.cc:\n\tUse new INSTANTIATE_ARRAY macro.\n\n\t* data.cc (do_permute): New function.\n\t(Fpermute, Fipermute): Use it.\n\n\t* ov-base.cc (octave_base_value::permute): New function.\n\t* ov-base.h: Provide decl.\n\n\t* ov.h (octave_value::ipermute): New function.\n\n2003-11-11  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* data.cc (Fpermute, Fipermute): New functions.\n\t* ov.h (octave_value::permute): New function.\n\t* ov-base-mat.h (octave_base_matrix::permute): New function.\n\n2003-11-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-obj.h (octave_value_list): Internal representation is now\n\tstd::vector instead of Array.\n\n\t* ov-list.h, ov-list.cc: Internal representation is now Cell, not\n\toctave_value_list.\n\t(Flist): Print one-time warning.\n\n\t* ov.cc (octave_value::octave_value (const octave_value_list&, bool)):\n\tCope with octave_cs_list not being derived from octave_list.\n\n\t* ov-cs-list.cc (octave_cs_list): Handle conversion of Cell array\n\tto octave_value_list here.\n\n\t* ov-cs-list.h (class octave_cs_list): Derive from\n\toctave_base_value, not octave_list.\n\n\t* ov-cs-list.h, ov-cs-list.cc: Remove commented-out code.\n\n\t* TEMPLATE-INST/Array-tc.cc (resize_fill_value): Use modern\n\tspecialization syntax.\n\n\t* ov-cell.cc (octave_cell::print_raw): Use dim_vector::str.\n\n\t* Cell.cc, Cell.h, debug.cc, file-io.cc, load-save.cc,\n\toct-fstrm.cc, oct-iostrm.cc, oct-iostrm.h, oct-map.cc, oct-map.h,\n\toct-prcstrm.cc, oct-stdstrm.h, oct-stream.cc, oct-strstrm.h,\n\toctave.cc, ov-base.h, ov-cell.cc, ov.cc, ov.h, pt-cell.h,\n\tpt-mat.cc, pt-mat.h, pt-plot.cc, pt-stmt.cc, variables.cc,\n\tDLD-FUNCTIONS/rand.cc: Avoid -Wshadow warnings.\n\n2003-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_base_value::is_bool_matrix): New virtual function.\n\t* ov-base.h (octave_base_value::is_bool_matrix): New function.\n\n2003-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.cc (octave_value::length): If any dim is zero, return 0.\n\n\t* ov-cell.cc (octave_cell::subsref): When indexing with '{', quit\n\tearly if an error occurs in do_index_op.\n\n\t* ov.cc (octave_value::next_subsref): Don't do anything if\n\terror_state is true.\n\n\t* cutils.c (octave_usleep) [HAVE_SELECT]: Introduce new local\n\tscope for declaration of delay.\n\t[HAVE_POLL]: Likewise, for delay and pfd.\n\n\t* ov-base.cc (octave_base_value::bool_array_value):\n\tFunction takes no args.\n\t* ov-base.h: Likewise, for decl.\n\t* ov-bool-mat.h (boolNDArray::bool_array_value): Likewise.\n\n\t* ov-fcn.cc, ov-fcn.h (octave_value::clone,\n\toctave_value::empty_clone): Return type is octave_value*, not\n\toctave_function*.\n\n2003-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-str-mat.h (octave_char_matrix_str::reshape): New function.\n\tForce result to be a string.\n\n2003-10-29  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* data.cc (DATA_REDUCTION): Work on NDArray and ComplexNDArray\n\tobjects instead of Matrix and ComplexMatrix objects.\n\n2003-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-bool-mat.h (octave_bool_matrix::NDArray,\n\toctave_bool_matrix::ComplexNDArray): New functions.\n\n\t* ov-complex.cc (octave_complex::array_value,\n\toctave_complex::complex_array_value): New functions.\n\t* ov-complex.h: Provide decls.\n\n\t* ov-scalar.cc (octave_scalar::array_value,\n\toctave_scalar::complex_array_value): New functions.\n\t* ov-scalar.h: Provide decls.\n\n\t* oct-map.cc (Octave_map::reshape): New function.\n\t* oct-map.h: Provide decl.\n\n\t* ov-struct.h (octave_struct::reshape): New function.\n\n\t* Cell.h (Cell:Cell (const Array<octave_value>&): New constructor.\n\n\t* data.cc (Freshape): New function.\n\t* ov.h (octave_value::reshape): New function.\n\t* ov-base-mat.h (octave_base_matrix::reshape): New function.\n\t* ov-base.cc (octave_base_value::reshape): New function.\n\t* ov-base.h: Provide decl.\n\n\t* DLD-FUNCTIONS/balance.cc: lscale and rscale args for dggbak are\n\tconst.  Use data() instead of fortran_vec where possible.\n\t* DLD-FUNCTIONS/qz.cc: Likewise.\n\n\t* data.cc (fill_matrix): Remove trailing singletons before\n\tallocating the result matrix.\n\n\t* input.cc (get_user_input): Don't forget about the diary here.\n\n2003-10-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-list.h (octave_list::nelem): Delete.\n\t(octave_list::dims): New function.\n\t* ov-range.h (octave_list::dims): New function.\n\t* ov-struct.h (octave_struct::dims): New function.\n\t* ov-base-scalar.h (octave_base_scalar::dims): New function.\n\n\t* ov.h (octave_value::rows): No longer virtual.\n\t* ov.cc (octave_value::rows): Provide common implementation.\n\t* ov-base.h (octave_base_value::rows): Delete.\n\t* ov-base-mat.h (octave_base_matrix<T>::rows): Delete.\n\t* ov-base-scalar.h (octave_base_scalar<T>::rows): Delete.\n\t* ov-struct.h (octave_struct::rows): Delete.\n\t* ov-range.h (octave_range::rows): Delete.\n\n\t* ov.h (octave_value::columns): No longer virtual.\n\t* ov.cc (octave_value::columns): Provide common implementation.\n\t* ov-base.h (octave_base_value::columns): Delete.\n\t* ov-base-mat.h (octave_base_matrix<T>::columns): Delete.\n\t* ov-base-scalar.h (octave_base_scalar<T>::columns): Delete.\n\t* ov-struct.h (octave_struct::columns): Delete.\n\t* ov-range.h (octave_range::columns): Delete.\n\n\t* ov.h (octave_value::numel): No longer virtual.\n\t* ov.cc (octave_value::numel): Provide common implementation.\n\t* ov-base.h (octave_base_value::numel): Delete.\n\t* ov-base-mat.h (octave_base_matrix<T>::numel): Delete.\n\t* ov-base-scalar.h (octave_base_scalar<T>::numel): Delete.\n\t* ov-struct.h (octave_struct::numel): Delete.\n\n\t* ov-cs-list.h (octave_cs_list::dims): New function.\n\t(octave_cs_list::length): Delete.\n\n\t* ov.h (octave_value::ndims): No longer virtual.\n\t* ov.cc (octave_value::ndims): Provide common implementation.\n\t* ov-base.h (octave_base_value::ndims): Delete.\n\t* ov-base-mat.h (octave_base_matrix<T>::ndims): Delete.\n\t* ov-base-scalar.h (octave_base_scalar<T>::ndims): Delete.\n\t* ov-struct.h (octave_struct::ndims): Delete.\n\n\t* ov-cell.cc (Fcell): Make it work for N-d cells.\n\n\t* Cell.h (Cell::Cell  (const dim_vector&, const octave_value&)):\n\tNew constructor.\n\n\t* ov.h (octave_value::length): No longer virtual.\n\t* ov.cc (octave_value::length): Provide common implementation.\n\t* ov-base.h (octave_base_value::length): Delete.\n\t* ov-base-mat.h (octave_base_matrix<T>::length): Delete.\n\t* ov-base-scalar.h (octave_base_scalar<T>::length): Delete.\n\t* ov-struct.h (octave_struct::length): Delete.\n\t* ov-cs-list.h (octave_cs_list::length): Delete.\n\t* ov-list.h (octave_list::length): Delete.\n\t* ov-range.h (octave_range::length): Delete.\n\n\t* load-save.cc (save_mat5_binary_element): Use numel instead of\n\tarray_length.\n\t* ov-struct.cc (octave_struct::print_raw): Likewise.\n\t* pt-loop.cc (tree_complex_for_command::eval): Likewise.\n\t* oct-map.cc (Octave_map::numel): New function.\n\t* oct-map.h: Provide decl.\n\n\t* oct-map.cc, oct-map.h (Octave_map::array_length): Delete.\n\t(common_size): New static function.\n\t(Octave_map::assign): Make resizing work for N-d cell objects.\n\n\t* oct-map.cc (Octave_map::dims): New function.\n\t* oct-map.h: Provide decl.\n\n\t* pr-output.cc \t(print_empty_nd_array): New static function.\n\t(PRINT_ND_ARRAY): Use it.\n\n\t* ov.h (octave_value::is_empty): No longer virtual.  Return value\n\tbased on numel.\n\t* data.cc (Fisempty): Use it.\n\t(Fnumel): New function.\n\n\t* ov.h (octave_value::numel): New function.\n\t* ov-base.h (octave_base_value::numel): Likewise.\n\t* ov-base-mat.h (octave_base_matrix<T>::numel): Likewise.\n\t* ov-base-scalar.h  (octave_base_scalar<T>::numel): Likewise.\n\n2003-10-27  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::is_true):\n\tOnly work for 2-dimensional objects.\n\t* data.cc (ANY_ALL (FCN)): Allow dim to take values large than 2.\n\n\t* ov.h (octave_value::ndims): New function.\n\t* ov-base.h (octave_base_value::ndims): Likewise.\n\t* ov-base-scalar.h (octave_base_scalar<T>::ndims): Likewise.\n\t* ov-base-mat.cc (octave_base_matrix<MT>::ndims): New function.\n\t(octave_base_matrix<MT>::length): Move here from ov-base-mat.h.\n\tMake it work for N-d arrays.\n\t* ov-base-mat.h (octave_base_matrix<MT>::ndims): Provide decl.\n\t* data.cc (Fndims): New built-in function.\n\n2003-10-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/qz.cc:\n\tUse new F77 arg macros in declarations of external Fortran\n\tsubroutines and for calling them.\n\n\t* ops.h (DEFNDUNOP_OP, DEFNDUNOP_FN): New arg e, to name value\n\textractor function prefix.\n\t* OPERATORS/op-bm-bm.cc, OPERATORS/op-cm-cm.cc,\tOPERATORS/op-m-m.cc:\n\tChange all uses.\n\n\t* ov-cx-mat.h (octave_complex_matrix::complex_array_value,\n\toctave_char_matrix::char_array_value,\n\toctave_bool_matrix::bool_array_value): Rename from array_value.\n\t* OPERATORS/op-bm-bm.cc, OPERATORS/op-cm-cm.cc,\n\tOPERATORS/op-cm-cs.cc, OPERATORS/op-cm-m.cc,\n\tOPERATORS/op-cm-s.cc, OPERATORS/op-cs-cm.cc,\n\tOPERATORS/op-m-cm.cc, OPERATORS/op-m-m.cc,\n\tOPERATORS/op-s-cm.cc: Use complex_array, char_array, and\n\tbool_array as appropriate (instead of just array).\n\n\t* ov-base.cc (octave_base_value::array_value,\n\toctave_base_value::bool_array_value,\n\toctave_base_value::complex_array_value,\n\toctave_base_value::char_array_value): Provide default implementations.\n\t* ov-base.h: Provide decls.\n\n\t* ov.h (octave_value::array_value, octave_value::bool_array_value,\n\toctave_value::complex_array_value, octave_value::char_array_value):\n\tNew virtual functions.\n\n2003-10-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-idx.cc (make_subs_cell): Pass dim_vector object to resize.\n\n\t* ov-typeinfo.cc (octave_value_typeinfo::do_register_type):\n\tUse resize_and_fill for types.\n\n\t* oct-obj.h (octave_value_list::maybe_resize): Use resize_and_fill.\n\t(octave_value_list::resize (int, const octave_value&)): Likewise.\n\n\t* oct-map.cc (Octave_map::assign): Use resize_and_fill as needed.\n\n\t* Cell.h (Cell (void)): Default size is now 0x0.\n\n2003-10-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* OPERATORS/op-cm-m.cc, OPERATORS/op-cm-s.cc,\n\tOPERATORS/op-cs-m.cc, OPERATORS/op-m-cm.cc, OPERATORS/op-s-cm.cc:\n\tInclude headers for N-d operators.\n\n2003-10-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ops.h (DEFNDUNOP_OP, DEFNDUNOP_FN, DEFNDBINOP_OP,\n\tDEFNDBINOP_FN): New N-dimensional macros.\n\t* OPERATORS/op-bm-bm.cc, OPERATORS/op-cm-cm.cc,\n\tOPERATORS/op-cm-cs.cc, OPERATORS/op-cm-m.cc,\n\tOPERATORS/op-cm-s.cc, OPERATORS/op-cs-cm.cc,\n\tOPERATORS/op-cs-m.cc, OPERATORS/op-m-cm.cc,\n\tOPERATORS/op-m-cs.cc, OPERATORS/op-m-m.cc,\n\tOPERATORS/op-m-s.cc, OPERATORS/op-s-cm.cc,\n\tOPERATORS/op-s-m.cc: Use N-dimensional macros as appropriate.\n\n\t* DLD-FUNCTIONS/rand.cc (do_rand, Frand, Frandn):\n\tHandle N-dimensions.\n\n\t* xpow.cc (elem_xpow (double, const NDArray&),\n\telem_xpow (double, const ComplexNDArray&),\n\telem_xpow (const NDArray&, double),\n\telem_xpow (const NDArray&, const NDArray&),\n\telem_xpow (const NDArray&, const Complex&),\n\telem_xpow (const NDArray&, const ComplexNDArray&),\n\telem_xpow (const Complex&, const NDArray&),\n\telem_xpow (const Complex&, const ComplexNDArray&),\n\telem_xpow (const ComplexNDArray&, double),\n\telem_xpow (const ComplexNDArray&, const NDArray&),\n\telem_xpow (const ComplexNDArray&, const Complex&),\n\telem_xpow (const ComplexNDArray&, const ComplexNDArray&):\n\tNew functions.\n\t* xpow.h: Provide decls.\n\n\t* xdiv.cc (x_el_div (double, const NDArray&),\n\tx_el_div (double, const ComplexNDArray&),\n\tx_el_div (const Complex, const NDArray&),\n\tx_el_div (const Complex, const ComplexNDArray&)): New functions.\n\t* xdiv.h: Provide decls.\n\n\t* ov-bool-mat.h (boolNDArray::array_value): New function.\n\t* ov-ch-mat.h (charNDArray::array_value): New function.\n\t* ov-cx-mat.h (ComplexNDArray::array_value): New function.\n\t* ov-re-mat.h (NDArray::array_value): New function.\n\t(NDArray::double_nd_array_value): Delete.\n\n2003-10-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (text_getc): New static function.\n\t(gobble_leading_white_space): Use it to simplify EOL processing.\n\n2003-10-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (fopen_mode_to_ios_mode): Ignore \"t\" in mode string.\n\n\t* strfns.cc (Fischar): rename from Fisstr.\n\n2003-10-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (PRINT_ND_ARRAY): New macro.\n\t(octave_print_internal): Use it.\n\n2003-10-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.cc\t(octave_value::octave_value (const ArrayN<octave_value>&,\n\tbool)):\tNew constructor.\n\t* ov.h: Provide decl.\n\n\t* ov.h (octave_value::squeeze): New virtual function.\n\t* ov-base.cc (squeeze): Provide default implementation.\n\t* ov-base-mat.h (octave_base_matrix::squeeze): New function.\n\t* data.cc (Fsqueeze): New function.\n\n2003-10-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (make_valid_identifier): Return new string.\n\tArg is now string, not char *.\n\t(ident_is_all_digits): New function.\n\t(hdf5_read_next_data): Use it.\n\n2003-10-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (input_event_hook): Clear the event hook if hook_fcn\n\tdoes not name a valid function.\n\n2003-10-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mappers.cc (xabs): New function.\n\t(install_mapper_functions): Use it instead of abs for complex args\n\tin Octave's abs mapper function.\n\n2003-09-27  Joseph P. Skudlarek  <Jskud@Jskud.com>\n\n \t* DLD-FUNCTIONS/minmax.cc (min, max): Use @deftypefn machinery,\n \tdoc missing semantics, and add more examples to texinfo strings.\n\n2003-09-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (read_mat5_binary_element): Return early if the\n\tmiMATRIX element has length zero.\n\n2003-09-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cell.cc (octave_cell::subsasgn): Also attempt empty\n\tconversion after extracting single element from cell array to\n\tallow things like x{i}.elt = rhs to work.\n\n2003-09-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_value::dim_vector): New function.\n\n\t* ov.h, ov.cc (octave_value::octave_value (const Cell&)):\n\tNew arg, is_cs_list.\n\t(octave_value::octave_value (const NDArray&)):\n\tCreate octave_matrix object, not octave_double_nd_array object.\n\t(octave_value::octave_value (const ComplexNDArray&),\n\toctave_value::octave_value (const boolNDArray&),\n\toctave_value (const charNDArray&, bool)): New constructors.\n\n\t* ov.h, ov.cc (octave_value::nil_rep): New function.\n\t(octave_value::octave_value (void)): Use it to initialize empty\n\toctave_value objects.\n\n\t* ov-list.h, ov-list.cc (octave_list::octave_list (const Cell&)):\n\tNew constructor.\n\t* ov-cs-list.h (octave_cs_list::octave_cs_list (const Cell&)):\n\tLikewise.\n\n\t* data.cc (Fsize): Handle N-d objects.\n\n\t* pr-output.cc (octave_print_internal): New versions for NDArray,\n\tComplexNDArray, boolNDArray, and charNDArray objects.\n\t* pr-output.h: Provide decls.\n\n\t* ov-re-nd-array.h, ov-re-nd-array.cc: Delete.\n\n\t* Cell.h, Cell.cc, ov-base-mat.h, ov-base-mat.cc, ov-bool-mat.h,\n\tov-bool-mat.cc, ov-ch-mat.h, ov-ch-mat.cc, ov-cx-mat.h,\n\tov-cx-mat.cc, ov-re-mat.h, ov-re-mat.cc, ov-str-mat.h,\n\tov-str-mat.cc: Now N-dimensional.\n\n\t* oct-map.h, oct-map.cc: Now based on Cell ojects instead of\n\toctave_value_list objects.  Change all uses.\n\n\t* TEMPLATE-INST/Array-tc.cc: Also instantiate ArrayN objects.\n\tDon't instantiate assign funcitons for Array2 objects.\n\n2003-09-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc (symbols_of_pt_plot): Default for automatic replot is\n\tnow true.\n\n\t* pr-output.cc (Fformat): Doc fix.\n\t(current_output_max_field_width, current_output_precision):\n\tNew functions.\n\t(float_format::float_format (int, int, int)): Use them to provide\n\tdefault values for field width and precision.\n\t(print_g): New static variable.\n\t(set_real_format, set_real_matrix_format, set_complex_format)\n\t(set_complex_matrix_format, set_range_format): Handle print_g.\n\t(pr_float, pr_complex): Don't scale if using print_g.\n\t(set_format_style): Accept new \"g\" and \"G\" modifiers for short and\n\tlong formats and set print_g.\n\tSet default precision and width for short to 5, 10.\n\tSet default precision and width for long to 15, 20.\n\n2003-09-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* OPERATORS/op-m-cs.cc (complex_matrix_conv): Delete function.\n\t(install_m_cs_ops): Don't install complex_matrix_conv here.\n\n\t* OPERATORS/op-s-cs.cc (complex_matrix_conv): Delete function.\n\t(install_s_cs_ops): Don't install complex_matrix_conv here.\n\n\t* OPERATORS/op-s-s.cc (matrix_conv): Delete function.\n\t(install_s_s_ops): Don't install matrix_conv here.\n\n\t* OPERATORS/op-cs-s.cc (complex_matrix_conv): Delete function.\n\t(install_cs_s_ops): Don't install complex_matrix_conv here.\n\n\t* OPERATORS/op-cs-m.cc (complex_matrix_conv): Delete function.\n\t(install_cs_m_ops): Don't install complex_matrix_conv here.\n\n\t* OPERATORS/op-cs-cs.cc (complex_matrix_conv): Delete function.\n\t(install_cs_cs_ops): Don't install complex_matrix_conv here.\n\n\t* ov-typeinfo.cc (do_register_unary_op,\n\tdo_register_non_const_unary_op, do_register_binary_op,\n\tdo_register_assign_op, do_register_assignany_op,\n\tdo_register_pref_assign_conv, do_register_widening_op):\n\tPrint warning if installing a duplicate function.\n\n2003-09-10  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* data.cc, ov-base.cc, ov-base.h, ov.h, ov.cc, ov-re-mat.h,\n\tov-scalar.h, ov-re-nd-array.h, ov-re-nd-array.cc: Use NDArray, not\n\tArrayN<double>.\n\n2003-09-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_value::double_nd_array_value): New function.\n\t(octave_value::is_real_nd_array): New function.\n\n\t* ov-base.cc (octave_base_value::double_nd_array_value): New function.\n\t* ov-base.h: Provide decl.\n\t(octave_base_value::is_real_nd_array): New function.\n\n2003-09-09  Petter Risholm  <risholm@stud.ntnu.no>\n\n\t* ov-re-mat.h (octave_matrix::double_nd_array_value): New function.\n\t* ov-scalar.h (octave_scalar::double_nd_array_value): New function.\n\n\t* ov-re-nd-array.cc (octave_double_nd_array::assign): New function.\n\t(octave_double_nd_array::try_narrowing_conversion): Likewise.\n\t(octave_double_nd_array::valid_as_scalar_index): Likewise.\n\t(octave_double_nd_array::double_value): Likewise.\n\t(octave_double_nd_array::matrix_value): Likewise.\n\t(octave_double_nd_array::complex_value): Likewise.\n\t(octave_double_nd_array::convert_slice_to_matrix): Likewise.\n\t* ov-re-nd-array.h: Provide decls.\n\t(octave_double_nd_array::is_real_nd_array): New function.\n\t(octave_double_nd_array::double_nd_array_value): New function.\n\t(octave_double_nd_array::double_nd_array_value): New function.\n\n\t* OPERATORS/op-m-nd.cc, OPERATORS/op-nd-m.cc,\n\tOPERATORS/op-nd-nd.cc, OPERATORS/op-nd-s.cc, OPERATORS/op-s-nd.cc:\n\tNew files.\n\t* Makefile.in (OP_XSRC): Add them to the list.\n\n2003-09-09  David Bateman  <dbateman@free.fr>\n\n\t* OPERATORS/op-cs-s.cc (DEFBINOP): First arg is complex, second is\n\tdouble.\n\n2003-09-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-cell.cc (tree_cell::rvalue): Don't assume that the number of\n\telements in a tree_argument_list is the same as the number of\n\tobjects it contains (cs-list objects expand to more than one).\n\n\t* pt-mat.cc (tm_row_const::tm_row_const_rep::do_init_element):\n\tNew function, extracted from tm_row_const::tm_row_const_rep::init.\n\t(tm_row_const::tm_row_const_rep::init): Use it.\n\tAlso handle cs-list objects.\n\n\t* ov-cs-list.cc (octave_cs_list::print_raw): New function.\n\t* ov-cs-list.h (octave_cs_list::print_raw): Provide decl.\n\t* ov-list.h (octave_list::lst): Now protected instead of private.\n\n2003-09-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc (subplot_style::columns_ok): Allow boxes style to\n\thave 2 columns as well.\n\n2003-08-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dirfns.cc (Fls): Check EAGAIN to avoid losing output.\n\t* toplev.cc (run_command_and_return_output): Likewise.\n\n2003-08-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* OPERATORS/op-str-s.cc, OPERATORS/op-str-m.cc: New files.\n\t* Makefile.in (OP_XSRC): Add them to the list.\n\n2003-08-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.cc (maybe_add_or_del_packages): Use source_file instead\n\tof parse_and_execute.\n\t* parse.y (source_file): New function.\n\t(Fsource): Use it.\n\t* parse.h (source_file): Provide decl.\n\n2003-08-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (octave_vsnprintf): Copy va_list to avoid using more\n\tthan once.\n\n2003-08-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (octave_vsnprintf): Call octave_raw_vsnprintf instead\n\tof calling vsnprintf directly.\n\t(octave_vsnprintf) [HAVE_C99_VSNPRINTF]: Declare nchars to be size_t.\n\n2003-08-06  Heine Kolltveit  <kolltvei@idi.ntnu.no>\n\n\t* utils.cc (check_dimensions(Array<int>&, char),\n\tget_dimensions(octave_value&, char, Array<int>&): New functions.\n\t* utils.h (check_dimensions (Array<int>&, char),\n\tget_dimensions (octave_value&, char, Array<int>&)): Provide decl.\n\n\t* data.cc (fill_matrix): Also create N-d arrays.\n \t(Fones, Fzeros): Handle more than 2 args to create N-d arrays.\n\n2003-07-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (make_diag): Use std::abs instead of our own ABS macro.\n\n\t* utils.cc (identity_matrix): Move here from data.cc.\n\t(identity_matrix): Use std::min instead of our own MIN macro.\n\n\t* utils.h (identity_matrix): Provide decl.\n\n\t* DLD-FUNCTIONS/svd.cc (Fsvd): Improve handling of empty matrix arg.\n\n\t* ov.cc (octave_value(const ArrayN<Complex>&)): New constructor.\n\t* ov.h (octave_value(const ArrayN<Complex>&)): Provide decl.\n\n2003-07-30  Heine Kolltveit  <kolltvei@idi.ntnu.no>\n\n\t* ov.cc (octave_value(const ArrayN<double>&)): New constructor.\n\t* ov.h (octave_value(const ArrayN<double>&)): Provide decl.\n\n2003-07-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (Vpropagate_empty_matrices): Delete decl.\n\t* ov.cc: (Vpropagate_empty_matrices): Delete.\n\t(propagate_empty_matrices): Delete.\n\t(symbols_of_ov): Delete DEFVAR for propagate_empty_matrices.\n\n\t* utils.cc (empty_arg): Behave as though propagate_empty_matrices\n\tis always 1.\n\t* ov-range.cc (octave_range::is_true): Likewise.\n\t* ov-base-mat.cc (octave_base_matrix<MT>::is_true): Likewise.\n\n\t* octave.cc (maximum_braindamage): Also set\n\twarn_matlab_incompatible to TRUE.\n\n\t* lex.l (Vwhitespace_in_literal_matrix): Delete.\n\t(whitespace_in_literal_matrix): Delete.\n\t(symbols_of_lex): Delete DEFVAR for whitespace_in_literal_matrix.\n\t(<MATRIX_START>{S}*\\,{S}*, <MATRIX_START>{S}+,\n\t(<MATRIX_START>{S}*{COMMENT}{SNLCMT}*,\n\t<MATRIX_START>{S}*{NL}{SNLCMT}*, maybe_unput_comma): Behave as though\n\told Vwhitespace_in_literal_matrix variable is always 1.\n\n\t* octave.cc (maximum_braindamage): Don't set\n\twhitespace_in_literal_matrix.\n\n2003-07-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-lib): Use $(INSTALL), not\n\t$(INSTALL_PROGRAM) for $(SHLLIB) files.\n\n2003-07-29  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Makefile.in: Don't need special system.c for Cygwin.\n\t* oct-procbuf.cc: Use popen rather than fork/exec for Windows.\n\n2003-07-28  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* sysdep.cc (CYGWIN_init): Convert TMPDIR to system agnostic path.\n\n2003-07-25  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* help.cc (try_info, display_help_text):\n\tProtect spaces in filenames with quotes.\n\t* oct-hist.cc (do_edit_history): Likewise.\n\t* pt-plot.cc (open_plot_stream): Likewise.\n\n2003-07-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (get_size, octave_base_stream::error,\n\toctave_base_stream::do_gets, octave_base_stream::getl,\n\toctave_base_stream::gets, octave_base_stream::do_scanf,\n\toctave_base_stream::scanf, octave_base_stream::do_oscanf,\n\toctave_base_stream::oscanf, do_printf_conv,\n\toctave_base_stream::do_printf, octave_base_stream::printf,\n\toctave_base_stream::puts, octave_base_stream::invalid_operation,\n\toctave_stream::getl, octave_stream::gets, octave_stream::scanf,\n\toctave_stream::oscanf, octave_stream::printf, octave_stream::puts,\n\toctave_stream::invalid_stream_error): Handle name of calling\n\tfunction for error messages as a std::string object.  Change all\n\tcallers.\n\n\t* file-io.cc (Fprintf, Fputs): New functions, so we can get\n\tfunction prefixes on error messages right.\n\t(Ffgetl, Ffgets, Ffprintf, Fsprintf, Fputs, Ffscanf, Fsscanf):\n\tPass name of calling function to octave_stream method.\n\n\t* oct-stream.h (octave_base_stream::do_char_scanf,\n\toctave_base_stream::do_real_scanf): Delete unused decls.\n\n\t* load-save.cc (read_mat5_binary_element): Correctly read struct\n\tarrays.\n\n\t* pt-misc.cc (tree_parameter_list::initialize_undefined_elements):\n\tNew args, warnfor and nargout.  Change all callers.\n\t(symbols_of_pt_misc): New function.\n\t(warn_undefined_return_values): New function.\n\n\t* octave.cc (maximum_braindamage): Don't set\n\tdefine_all_return_values.\n\n\t* ov-usr-fcn.cc (ov_user_function::do_multi_index_op): Always\n\tintiialize undefined elements in ret_list to [].\n\tNever return last computed value.\n\t(Vreturn_last_computed_value, Vdefine_all_return_values): Delete.\n\t(return_last_computed_value, define_all_return_values): Delete.\n\t(symbols_of_ov_usr_fcn): Delete DEFVARs for\n\treturn_last_computed_value, define_all_return_values, and\n\tdefault_return_value.\n\n2003-07-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-misc.cc (tree_parameter_list::convert_to_const_vector):\n\tDon't skip undefined elements.\n\n2003-07-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (maximum_braindamage): Don't set\n\tdefault_global_variable_value or initialize_global_variables.\n\n\t* pt-decl.cc (Vinitialize_global_variables): Delete.\n\t(initialize_global_variables): Delete.\n\t(symbols_of_pt_decl): Delete.\n\t(tree_global_command::do_init): Default initial value is now\n\talways [].\n\n2003-07-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (maximum_braindamage): Don't set default_eval_print_flag.\n\n\t* parse.y (Vdefault_eval_print_flag): Delete:\n\t(default_eval_print_flag): Delete.\n\t(symbols_of_parse): Delete DEFVAR for default_eval_print_flag.\n\t(Feval, Fevalin): Return empty octave_value_list and turn printing\n\ton in eval_string if nargout is zero.\n\n\t* ov-list.cc (octave_list::assign): Check\n\tVwarn_resize_on_range_error, not Vresize_on_range_error.\n\n\t* ov.cc (Vwarn_resize_on_range_error): New variable.\n\t(warn_resize_on_range_error): New function.\n\t(symbols_of_ov): Add DEFVAR for warn_resize_on_range_error.\n\n\t* ov.cc (Vresize_on_range_error): Delete.\n\t(resize_on_range_error): Delete.\n\t(symbols_of_ov): Delete DEFVAR for resize_on_range_error.\n\n\t* pt-mat.cc (Vwarn_empty_list_elements): New variable.\n\t(warn_empty_list_elements): New function.\n\t(symbols_of_pt_mat): Add DEFVAR for warn_empty_list_elements.\n\t(tm_row_const::tm_row_const_rep::init, tm_const::init):\n\tCheck Vwarn_empty_list_elements, not Vempty_list_elements_ok.\n\n\t* pt-mat.cc (Vempty_list_elements_ok): Delete.\n\t(empty_list_elements_ok): Delete.\n\t(symbols_of_pt_mat): Delete DEFVAR for empty_list_elements_ok.\n\n2003-07-11  Russell Standish  <R.Standish@unsw.edu.au>\n\n\t* TEMPLATE-INST/Array-tc.cc (resize_fill_value): Provide\n\tspecialization.\n\n2003-07-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strfns.cc (Fchar): Force string conversions without warnings.\n\n\t* ov.h (octave_value::convert_to_str, octave_value::all_strings,\n\toctave_value::string_value, octave_value:convert_to_str_internal):\n\tNew arg, force.  Fix all derived classes to match.\n\n\t* strfns.cc (Fchar): Temporarily reset Vwarn_num_to_str to avoid\n\twarnings.\n\n\t* ov.cc (convert_to_str): New arg, force.\n\n\t* octave.cc (maximum_braindamage): Don't set treat_neg_dim_as_zero.\n\n\t* utils.cc (Vwarn_neg_dim_as_zero): New variable.\n\t(warn_neg_dim_as_zero): New function.\n\t(symbols_of_utils): Add DEFVAR for warn_neg_dim_as_zero.\n\t(check_dimensions): Check Vwarn_neg_dim_as_zero, not\n\tVtreat_neg_dim_as_zero.\n\n\t* utils.cc (Vtreat_neg_dim_as_zero): Delete.\n\t(treat_neg_dim_as_zero): Delete.\n\t(symbols_of_utils): Delete DEFVAR for treat_neg_dim_as_zero.\n\n2003-07-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (maximum_braindamage): Don't set prefer_column_vectors.\n\n\t* ov.cc (Vprefer_column_vectors): Delete.\n\t(prefer_column_vectors): Delete.\n\t(symbols_of_ov): Delete DEFVAR for prefer_column_vectors.\n\n\t* octave.cc (maximum_braindamage): Don't set do_fortran_indexing.\n\n\t* ov-re-mat.cc (octave_matrix::double_value,\n\toctave_matrix::complex_value): Use Vwarn_fortran_indexing, not\n\tVdo_fortran_indexing.\n\t* ov-range.cc (octave_range::double_value,\n\toctave_range::complex_value): Likewise.\n\t* ov-cx-mat.cc (octave_complex_matrix::double_value,\n\toctave_complex_matrix::complex_value): Likewise.\n\t* ov-ch-mat.cc (octave_char_matrix::double_value,\n\toctave_char_matrix::complex_value): Likewise.\n\t* ov-bool-mat.cc (octave_bool_matrix::double_value,\n\toctave_bool_matrix::complex_value): Likewise.\n\n\t* ov.cc (Vwarn_fortran_indexing): New variable.\n\t(warn_fortran_indexing): New function.\n\t(symbols_of_ov): Add DEFVAR for warn_fortran_indexing.\n\t(octave_value::vector_value, octave_value::int_vector_value,\n\t(octave_value::complex_vector_value): Check\n\tVwarn_fortran_indexing, not Vdo_fortran_indexing.\n\n\t* ov.h (Vwarn_fortran_indexing): Provide decl.\n\n\t* ov.cc (Vdo_fortran_indexing): Delete unused variable.\n\t(do_fortran_indexing): Delete unused function.\n\t(symbols_of_ov): Delete DEFVAR for do_fortran_indexing.\n\t* ov.h (Vdo_fortran_indexing): Delete decl.\n\n\t* ov.cc (octave_value::convert_to_str): Call convert_to_str_internal.\n\t(octave_value::convert_to_str_internal): New virtual function.\n\tRename all derived class convert_to_str functions to match.\n\n\t* variables.cc (generate_struct_completions): Set\n\tdiscard_warning_messages, not Vwarning_option.  Also protect\n\twarning_state.\n\n\t* parse.y (fold): Temporarily discard warning messages.\n\tAlso protect warning_state.\n\n\t* error.cc (discard_warning_messages): New variable.\n\t(vwarning): Use it.\n\t(warning): Don't print backtrace if discard_warning_messages is true.\n\n\t* ov.cc (octave_value::convert_to_str):\n\tHandle type conversion warning here.\n\n\t* gripes.cc (gripe_implicit_conversion):\n\tNew function accepting std::string args.\n\n\t* octave.cc (maximum_braindamage): Don't set\n\timplicit_num_to_str_ok or implicit_str_to_num_ok.\n\n\t* ov-base.cc (octave_base_value::char_matrix_value):\n\tVimplicit_num_to_str_ok no longer exists.\n\t(octave_base_value::all_strings): Likewise.\n\t(octave_base_value::string_value): Likewise.\n\n\t* ov-str-mat.cc (octave_char_matrix_str::matrix_value): Warn based\n\ton Vwarn_str_to_num instead of Vimplicit_str_to_num_ok.\n\n\t* ov.cc (Vwarn_num_to_str, Vwarn_str_to_num): New variables.\n\t(warn_num_to_str, warn_str_to_num): New functions.\n\t(symbols_of_ov): Add DEFVARs for warn_num_to_str and Vwarn_str_to_num.\n\t* ov.h (Vwarn_num_to_str, Vwarn_str_to_num): Provide decl.\n\n\t* ov.cc (Vimplicit_num_to_str_ok, Vimplicit_str_to_num_ok):\n\tDelete unused variables.\n\t(implicit_num_to_str_ok, implicit_str_to_num_ok):\n\tDelete unused functions.\n\t(symbols_of_ov): Delete DEFVARs for implicit_num_to_str_ok and\n\timplicit_str_to_num_ok.\n\t* ov.h (Vimplicit_num_to_str_ok, Vimplicit_str_to_num_ok):\n\tDelete decls.\n\n\t* pt-mat.cc (tree_matrix::rvalue): Vimplicit_num_to_str_ok no\n\tlonger exists.\n\n\t* ov.cc (Vwarn_imag_to_real): New variable.\n\t(warn_imag_to_real): New function.\n\t(symbols_of_ov): Add DEFVAR for warn_imag_to_real.\n\t* ov.h (Vwarn_imag_to_real): Provide decl.\n\n\t* ov.cc (Vok_to_lose_imaginary_part): Delete unused variable.\n\t(ok_to_lose_imaginary_part): Delete unused function.\n\t(symbols_of_ov): Delete DEFVAR for ok_to_lose_imaginary_part.\n\t* ov.h (Vok_to_lose_imaginary_part): Delete decl.\n\n\t* ov-complex.cc (octave_complex::double_value): Warn based on\n\tVwarn_imag_to_real instead of Vok_to_lose_imaginary_part.\n\t(octave_complex::matrix_value): Likewise.\n\t* ov-cx-mat.cc (octave_complex_matrix::double_value): Likewise.\n\t(octave_complex_matrix::matrix_value): Likewise.\n\n\t* octave.cc (maximum_braindamage): Don't set ok_to_lose_imaginary_part.\n\n2003-07-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (sig_hup_or_term_handler): New function.\n\t(install_signal_handlers): Install sig_hup_or_term_handler for\n\tSIGHUP and SIGTERM instead of generic_sig_handler.\n\t(Vsighup_dumps_octave_core, Vsigterm_dumps_octave_core):\n\tNew static variables.\n\t(sighup_dumps_octave_core, sigterm_dumps_octave_core):\n\tNew static functions.\n\t(symbols_of_sighandlers): Add DEFVARs for sighup_dumps_octave_core\n\tand sigterm_dumps_octave_core.\n\n\t* defaults.h.in (OCTAVE_LOCALAPIFCNFILEDIR, OCTAVE_LOCALAPIOCTFILEDIR):\n\tSubsitute new variables.\n\n\t* defun.cc (check_version): Compare version to OCTAVE_API_VERSION,\n\tnot OCTAVE_VERSION.  Mismatch is now fatal.\n\t* defun-int.h (DEFINE_FUN_INSTALLER_FUN3): Pass\n\tOCTAVE_API_VERSION instead of OCTAVE_VERSION to check_version.\n\t* version.h (OCTAVE_API_VERSION): New macro, initial value api-v1.\n\n\t* defaults.cc (Vdefault_exec_path): New static variable.\n\t(set_default_default_exec_path): New function.\n\t(install_defaults): Call it.\n\t(exec_path): Use it.\n\t(default_exec_path): New function.\n\t(symbols_of_defaults): Add DEFVAR for DEFAULT_EXEC_PATH.\n\n2003-07-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.h.in (OCTAVE_LOCALSTARTUPFILEDIR, OCTAVE_STARTUPFILEDIR):\n\tSet values directly instead of constructing them.\n\n2003-06-28  Arno J. Klaassen  <arno@heho.snv.jussieu.fr>\n\n\t* toplev.cc (octave_config_info): Key for OCTAVE_CONF_DEFS should\n\tbe DEFS, not UGLY_DEFS.\n\n2003-06-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.50.\n\n2003-06-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (symbol_exist): Distinguish between user and dld\n\tfunctions loaded in memory.\n\n2003-06-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-mat.cc (tm_row_const::init, tm_const::init): Don't ignore\n\tempty matrices that have one non-zero dimension.\n\n\t* variables.cc (symbol_exist): Use dir_path::find_first_of to\n\tsearch for .oct and .m files.\n\n\t* ov-base.cc (octave_base_value::subsasgn): Also allow type\n\tconversion for empty numeric objects with more than one index.\n\t* ov-base-mat.cc (octave_base_matrix<T>::subsasgn): Likewise.\n\n2003-06-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (do_who): New arg, return_list.  If return_list is\n\ttrue, return values in cell or struct arrays instead of printing.\n\t(Fwho, Fwhos): If nargout is 1, ask do_who to return lists of values.\n\t* oct-map.h (Octave_map (const std::string&, const octave_value_list&):\n\tNew constructor.\n\n2003-06-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-idx.cc (tree_index_expression::rvalue):\n\tCorrectly handle index expressions like x(end).f(end).\n\t(tree_index_expression::lvalue): Likewise.\n\n\t* pt-arg-list.cc (F__end__): Add nr, nc info to error messages.\n\n2003-06-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (set_format (const Matrix&, int&, double&)): Ask\n\tany_element_is_negative to return true for negative zero as well.\n\t(set_format (const ComplexMatrix&, int&, int&, double&)): Likewise.\n\n2003-06-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (main_loop): Set octave_interrupt_hook and\n\toctave_bad_alloc_hook to unwind_protect::run_all here.\n\t(recover_from_exception): Don't call unwind_protect::run_all here.\n\n\t* pt-except.cc (do_catch_code): Return immediately if\n\toctave_interrupt_immediately is nonzero.\n\n\t* sighandlers.cc (sigint_handler): If jumping, don't set\n\toctave_interrupt_state.\n\n2003-06-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (get_save_type): Avoid all save types other than\n\tLS_DOUBLE to avoid apparent Matlab bugs.\n\n2003-06-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (frob_function, parse_fcn_file): Handle help_buf as\n\tstack of strings.\n\t* lex.l ({CCHAR}): Handle help_buf as stack of strings.\n\tStore text returned from grab_help_text in help_buf here.\n\t(reset_parser): Handle help_buf as stack of strings.\n\t(prep_for_nested_function): Push empty string onto help_buf stack.\n\t(grab_help_text): Return help text instead of storing it in help_buf.\n\t* parse.h, parse.y (help_buf): Now a stack of strings.\n\n\t* oct-stream.cc (printf_value_cache::string_value): Don't attempt\n\tto extract values when none are available.\n\n2003-06-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc (Vgnuplot_has_multiplot): Delete variable.\n\t(gnuplot_has_multiplot): Delete.\n\t(symbols_of_pt_plot): Delete DEFVAR for gnuplot_has_multiplot.\n\n2003-05-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.49.\n\n2003-05-28  Teemu Ikonen  <tpikonen@pcu.helsinki.fi>\n\n\t* load-save.cc (save_mat5_binary_element, save_mat_binary_data):\n\tAllow saving of non-7-bit ASCII characters.\n\n2003-05-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (FINISH_CHARACTER_CONVERSION,\n\toctave_base_stream::do_scanf): Do a better job of resizing for\n\tcharachter conversions.\n\n2003-05-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cx-mat.cc (octave_complex_matrix::assign): Move definition here.\n\t* ov-cx-mat.h: From here.\n\n2003-05-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-range.cc (octave_range::try_narrowing_conversion): Convert to\n\t[](1x0) instead of [](0x0) if range is empty.\n\n2003-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Handle DESTDIR.\n\n2003-05-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l: Use yyunput (X, yytext) instead of unput (X) for newer\n\tversions of flex.\n\n2003-05-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.48.\n\n2003-05-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.47.\n\n2003-05-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (save_ascii_data): If saving a range with\n\tnon-integer base, limit, or increment, save as matrix instead.\n\t(get_save_type): Avoid unsigned types.\n\n2003-04-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (initialize_pathsearch): Don't save old and set new\n\tvalue of TEXMFDBS.\n\n\t* toplev.cc (restore_texmfdbs_envvar): Delete function.\n\t(Fsystem): Don't set and reset TEXMFDBS.\n\n\t* toplev.h, toplev.cc (octave_original_texmfdbs): Delete variable.\n\n2003-04-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/getpwent.cc (Fgetpwnam): Delete unnecessary\n\tc_str() method.\n\n2003-04-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc: Include <memory> for auto_ptr.\n\n2003-04-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (octave_config_info): Delete LIBKPATHSEA from struct.\n\t* oct-conf.h.in: Don't substitute LIBKPATHSEA.\n\n\t* octave.cc (octave_main): Don't call dir_path::set_program_name.\n\n2003-04-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-file.h (octave_file::empty_clone): Create an octave_scalar\n\tobject, not an octave_file object.\n\n2003-04-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (hdf5_read_next_data): Extract list before\n\tassigning to map element.\n\t(add_hdf5_data): Prefix faked names with '_' so they are valid\n\tidentifiers.\n\n2003-03-24  Mats Jansson  <mats.e.jansson@home.se>\n\n\t* syscalls.cc (Fkill): Fixed docstring typo.\n\n2003-03-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cell.h (octave_cell::is_matrix_type): New function.\n\n2003-03-09  Duncan Temple Lang  <duncan@research.bell-labs.com>\n\n\t* octave.cc (octave_main): New arg, embedded.\n\t* octave.h: Fix decl.\n\t* main.c: Pass 0 for embedded here.\n\n2003-03-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.46.\n\n\t* oct-conf.h.in: Undo previous change.\n\n\t* load-save.cc (read_mat5_binary_element): Handle structure arrays.\n\t(save_mat5_binary_element): Likewise.\n\n2003-03-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cell.cc (octave_cell::subsasgn): Use make_unique in\n\tappropriate places to preserve copy on write semantics.\n\n\t* oct-conf.h.in: Substitute OCTAVE_CONF_KPATHSEA_INCFLAGS.\n\n\t* oct-stdstrm.h (octave_stdiostream::output_stream): Return stream\n\tif mode is out, not in.\n\n2003-02-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strfns.cc (Fchar): New function.\n\n\t* ov-cell.cc (octave_cell::all_strings): Allow elements to be\n\tstring arrays.\n\t* ov.cc (octave_value::all_strings, octave_value::convert_to_str):\n\tNew optional arg, pad.  Change all derived classes.\n\n\t* ov-struct.cc (Ffieldnames, Fisfield): Move here from data.cc.\n\n\t* data.cc (Ffieldnames): Rename from Fstruct_elements.  Return\n\tcell array instead of a string array.\n\t(Fisfield): Rename from struct_contains.\n\n2003-02-22  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* toplev.cc: Put config info in array of strings, then convert to map.\n\n2003-02-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (symbol_exist): For names like foo.bar, don't omit\n\tthe part after the dot.\n\n2003-02-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (fun_to_call): New static variable.\n\t(octave_main): Pass it to main_loop.\n\t(long_opts): Accept --funcall.\n\t(usage_string, verbose_usage): Add --funcall.\n\n\t* toplev.cc (main_loop): New arg, fun_to_call.  If non-empty,\n\tevaluate this function before continuing.\n\n2003-02-21  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* file-io.cc (Fmkstemp): Use OCTAVE_LOCAL_BUFFER instead of using\n\tstd::auto_ptr directly.\n\n2003-02-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h, ov.cc (octave_value (long long int)): New constructor.\n\t(octave_value (unsigned long long int)): Likewise.\n\n\t* oct-obj.h (octave_value_list::operator delete): Handle systems\n\twith or without placement delete.\n\n2003-02-21  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* utils.cc (octave_vsnprintf): Return value of vsnprintf is int,\n\tnot size_t.  Make sure there is some space left in the buffer for\n\tvsnprintf versions which return the number of characters written\n\teven when the buffer is too short.\n\n2003-02-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* debug.cc (get_user_function): Use dynamic_cast, not static_cast.\n\n\t* ov-usr-fcn.cc (octave_user_function::traceback_error): Now const.\n\n\t* ov.cc (octave_value (const octave_fcn_handle&)): New constructor.\n\t(octave_value::fcn_handle_value): New virtual function.\n\t* ov-base.cc (octave_value::fcn_handle_value): Provide default.\n\t* ov-usr-fcn.cc (octave_user_function::stash_fcn_file_name): New\n\targ, nm.  Change all callers.\n\t* ov-fcn.h (octave_function::is_nested_function): New virtual function.\n\t* parse.y (get_feval_args): New function.\n\t(feval (octave_function *, const octave_value_list&, int)): Likewise.\n\t(feval (const octave_value_list&, int)): Allow the first arg to be\n\ta function handle as well as a string.\n\t* variables.cc (load_function): New function.\n\t* pt-walk.h, pt-pr-code.h, pt-pr-code.cc, pt-check.h, pt-check.cc,\n\tpt-bp.h, pt-bp.cc: Handle new tree_fcn_handle class.\n\t* pt-all.h: Include pt-fcn-handle.h.\n\t* pt-fcn-handle.h, pt-fcn-handle.cc, ov-fcn-handle.h,\n\tov-fcn-handle.cc: New files.\n\n2003-02-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (FCN_HANDLE): New token type.\n\t(fcn_handle): New non-terminal.\n\t(primary_expr): Also accept fcn_handle.\n\t(tree_fcn_handle_type): New %type.\n\t(union): New field, tree_fcn_handle_type.\n\t(make_fcn_handle): New function.\n\n\t* lex.l (@{IDENT}): Recognize function handle syntax.\n\t(@): Don't recognize \"@\" as a single token.\n\n\t* load-save.cc (struct hdf5_callback_data): Provide constructor.\n\t(hdf5_callback_data::name, hdf5_callback_data::doc): Now\n\tstd::string instead of char*.  Change all uses.\n\n2003-02-18  Roger Banks  <rbanks@colsa.com>\n\n\t* load-save.cc (read_ascii_data, read_ascii_data,\n\tread_mat5_binary_element, save_mat5_binary_element,\n\tsave_ascii_data): Handle cell arrays.\n\t(write_mat5_cell_array): New function.\n\n2003-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DLD_XSRC): Delete log.cc from the list.\n\tAdd sqrtm.cc to the list.\n\n\t* DLD-FUNCTIONS/log.cc: Delete.\n\n2003-02-18  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* DLD-FUNCTIONS/sqrtm.cc: New file.\n\n2003-02-18  David Bateman  <dbateman@free.fr>\n\n\t* DLD-FUNCTIONS/lu.cc (Flu): Allow non-square matrices.\n\n2003-02-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (read_binary_file_header, do_load, do_save,\n\twrite_header): No longer static.\n\t(load_save_format): Move enum decl to load-save.h.\n\n2003-02-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stdstrm.h, oct-stdstrm.cc (octave_base_stdiostream,\n\toctave_iostdiostream, octave_istdiostram, octave_ostdiostream):\n\tCombine all functionality into one class, octave_stdiostream.\n\tChange all uses.\n\n\t* file-io.cc (Ftmpfile, Fmkstemp): New functions.\n\t* oct-stdstrm.h (octave_iostdiostream): New class.\n\t(octave_istdiostream::octave_istdiostream,\n\toctave_istdiostream::create,\n\toctave_ostdiostream::octave_ostdiostream, octave_ostdiostream::create,\n\toctave_iostdiostream::octave_iostdiostream,\n\toctave_iostdiostream::create): Make close function the last arg.\n\tChange all uses.\n\n\t* c-file-ptr-stream.h (io_c_file_ptr_stream): New class.\n\n2003-02-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (maximum_braindamage): Set boolean built-in variables\n\tto true and false instead of 1.0 and 0.0.\n\t(octave_main): Likewise.\n\t* error.cc (Fwarning): Likewise.\n\n\t* pager.cc (Fmore): Make the no-arg case work too.\n\n\t* ov-str-mat.h (octave_char_matrix_str::is_real_type,\n\toctave_char_matrix_str::is_matrix_type,\n\toctave_char_matrix_str::is_numeric_type): Always return false.\n\n2003-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (<CCHAR>): If we are parsing a command, reset start state.\n\tUse BEGIN (INITIAL) instead of BEGIN 0.  Use parens around start\n\tstate in BEGIN statements.\n\n2003-02-13  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* variables.cc (Fmlock, Fmunlock, Fmislocked): New functions.\n\n\t* variables.cc (mlock, munlock, mislocked): New functions.\n\t* variables.h: Provide decls.\n\n\t* symtab.h (symbol_record::unmark_static): New function.\n\n2003-02-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* error.cc (reset_error_handler): New function.\n\t* toplev.cc (main_loop): Use it here.\n\t* lex.l (reset_parser): Don't set error_state and warning_state here.\n\t* parse.y (eval_string): Reset parser before calling yyparse.\n\n2003-01-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (Ffmod): New function.\n\n\t* c-file-ptr-stream.cc (c_file_ptr_buf::underflow_common): New\n\tfunction.\n\t* c-file-ptr-stream.h (c_file_ptr_buf::underflow,\n\tc_file_ptr_buf::uflow): Use it.\n\t(c_file_ptr_buf): Derive from std::streambuf, not OCTAVE_STD_FILEBUF.\n\tDon't cache file descriptor.\n\n2003-01-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/minmax.cc: Move min and max functions from here to\n\tliboctave/dMatrix.cc and liboctave/CMatrix.cc.\n\n2003-01-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/rand.cc: Rewrite to use new octave_rand functions.\n\n2003-01-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_base_stream::do_printf): Handle values\n\toutside the range of integers in int conversions for\n\tcompatibilitiy wtih Matlab.\n\n2003-01-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (get_mat_data_input_line): Handle lines with CR\n\tonly as separator.\n\n\t* oct-stream.cc (octave_base_stream::do_printf): Handle Inf and\n\tNaN in int conversions for compatibility with Matlab.\n\n\t* data.cc (symbols_of_data): Doc fix for realmin.\n\n\t* cutils.c (octave_raw_vsnprintf): New function.\n\t* utils.cc (octave_snprintf): Move here from cutils.c.\n\t(octave_Vsnprintf): Likewise.  Allow octave_raw_vsnprintf to be\n\tinterrupted.\n\t* utils.h (octave_vsnprintf, octave_snprintf): No longer extern \"C\".\n\n2003-01-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-loop.cc (tree_complex_for_command::eval): Fix typo.\n\n2003-01-16  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* mk-oct-links: Use $SED if set.\n\t* mkbuiltins: Likewise.\n\t* mkdefs: Likewise.\n\t* mkdocs: Likewise.\n\t* mkgendoc: Likewise.\n\t* mkops: Likewise.\n\n2003-01-11  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Makefile.in (gendoc$(BUILD_EXEEXT)): Pass $(BUILD_CXXFLAGS) and\n\t$(BUILD_LDFLAGS) to compiler.\n\n2003-01-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (Fassignin): New function.\n\n2003-01-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (make_sig_struct): New function.\n\t(symbols_of_sighandlers): Add DEFCONST for SIG struct.\n\n\t* syscalls.cc (Fkill): New function.\n\n2003-01-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (get_size): If only one dimension is specified and\n\tit is zero, also set the other dimension to zero instead of one.\n\n2003-01-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sysdep.cc [__DECCXX]: Add a kluge for some missing template\n\tfunctions.\n\n2003-01-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-usr-fcn.cc (octave_vr_val): Assert vr_list != 0, not vr_list.\n\t* variables.cc (builtin_string_variable, builtin_any_variable,\n\tbuiltin_real_scalar_variable, bind_builtin_variable): Likewise.\n\n\t* TEMPLATE-INST/Array-tc.cc: Provide specialization of\n\tArray<octave_value>::resize_fill_value before instantiation of\n\tArray<octave_value>.\n\n\t* oct-obj.h (octave_value_list::operator delete): Define version\n\tof delete operator to correspond to placement new operator.\n\n\t* mkgendoc: In generated code, define __USE_STD_IOSTREAM if using\n\tCompaq C++.\n\n\t* Makefile.in (distclean): Also remove doc-files and gendoc.cc.\n\n\t* input.cc (initialize_command_input): Use const for\n\tinitialization of char * from literal string.\n\n\t* pt-plot.cc (subplot::extract_plot_data): Call single_subsref,\n\tnot subsref.\n\t* ov.h, ov.cc (single_subsref (const std::string&, const\n\toctave_value_list&)): Rename from subsref.\n\n\t* symtab.cc (symbol_table::rename): Explicitly convert C string to\n\tstd::string so type of second arg of ?: matches third.\n\t(symbol_table::lookup): Likewise.\n\n\t* mappers.cc: Remove std:: qualifiers from C library names.\n\n2003-01-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-exp.h (tree_expression::has_magic_end): New pure virtual function.\n\t* pt-id.h (tree_identifier::has_magic_end): New function.\n\t* pt-colon.h (tree_colon_expression::has_magic_end): Likewise.\n\t* pt-idx.h (tree_index_expression::has_magic_end): Likewise.\n\t* pt-const.h (tree_constant::has_magic_end): Likewise.\n\t* pt-unop.h (tree_unary_expression::has_magic_end): Likewise.\n\t* pt-binop.h (tree_binary_expression::has_magic_end): Likewise.\n\t* pt-assign.h (tree_multi_assignment::has_magic_end): Likewise.\n\t(tree_simple_assignment::has_magic_end): Likewise.\n\t* pt-mat.cc (tree_matrix::has_magic_end): Likewise.\n\t* pt-arg-list.cc (tree_argument_list::has_magic_end): Likewise.\n\n\t* pt-arg-list.cc (tree_argument_list::append): Check all\n\texpression types for magic end token..\n\n\t* file-io.cc (Ftmpnam): Improve error checking.\n\t(symbols_of_file_io): Move definition of P_tmpdir here from dirfns.cc.\n\n\t* dirfns.cc (symbols_of_dirfns): Install new built-in constant\n\tP_tmpdir.\n\n2003-01-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dirfns.cc (symbols_of_dirfns): New function.\n\tInstall new built-in constant filesep.\n\n\t* utils.cc (Fisvaranme): New function.\n\t(valid_identifier): Identifiers can't start with digits!  Doh!\n\n\t* lex.l (Fiskeyword): New function.\n\n\t* Makefile.in (INCLUDES): Don't forget base-list.h.\n\n\t* symtab.cc (symbol_record::define): If definition already exists,\n\tredefine it instead of replacing it.\n\n\t* variables.cc (symbol_exist): Don't use reference when handling\n\tsr->def ().\n\n\t* pt-plot.cc (save_in_tmp_file): octave_value arg is now const.\n\t* pt-misc.cc (tree_parameter_list::initialize_undefined_elements):\n\tLikewise.\n\n\t* symtab.cc (symbol_record::clear): Don't do anything if the\n\tsymbol record is already undefined.\n\n2003-01-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-arg-list.cc (tree_argument_list::append): New function.\n\t(tree_argument_list::convert_to_const_vector): Don't save and\n\tset pointer to indexed object if list_includes_magic_end is false.\n\t* pt-arg-list.h (tree_argument_list::append): Provide decl.\n\t(tree_argument_list::list_includes_magic_end): New data member.\n\t(tree_argument_list::tree_argument_list): Initialize it.\n\n\t* ov-base.cc (octave_base_value::char_matrix_value,\n\toctave_base_value::all_strings,\toctave_base_value::string_value):\n\tAttempt conversions here if Vimplicit_num_to_num_ok is true.\n\n\t* ov.cc (Vimplicit_num_to_str_ok): Move here from pt-mat.cc and\n\tmake extern.\n\t* ov.h: Provide decl.\n\n\t* oct-stream.cc (printf_value_cache::looking_at_string): Delete.\n\t(printf_value_cache::string_value): Just attempt conversion.\n\t(octave_base_stream::do_printf): When doing '%s' format,\n\tjust attempt converstion.\n\n\t* file-io.cc (Ffread): Allow size to be omitted even when\n\tadditional arguments are given.\n\n2002-12-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-arg-list.cc (F__end__): Fail if rows or columns is negative.\n\t(tree_argument_list::convert_to_const_vector): Only protect and\n\tsave pointer to the indexed object if it is a constant.\n\n\t* syscalls.cc (Fmkfifo): Use long_value instead of cast.\n\n\t* ov.h (octave_value::short_value, octave_value::ushort_value,\n\toctave_value::uint_value, octave_value::long_value,\n\toctave_value::ulong_value): New functions.\n\n\t* syscalls.cc (mk_stat_map, Fgetegid, getgid, geteuid): Likewise.\n\tDelete unnecessary casts.\n\t* file-io.cc (Ffgetl, Ffgets, Fftell, Fsscanf): Likewise.\n\t* toplev.cc (Fsystem): Likewise.\n\n\t* ov-file.h (octave_file::double_value,\toctave_file::scalar_value):\n\tDelete unnecessry cast.\n\n\t* ov.cc (octave_value::octave_value): Add constructors for\n\toctave_time, short int, unsigned short int, unsigned int, long\n\tint, unsigned long int,\n\n\t* ov.h (octave_value::do_subsref (const std::string&, const\n\toctave_value_list&)): Rename from subsref.  Change all derived classes.\n\n\t* input.cc (generate_completion): Delete unused variable prefix_len.\n\n\t* ov.h (DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA): Delete volatile\n\tqualifier for decls of static_type_id and t_id.\n\t(DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA): Likewise, for def of t_id.\n\n2002-12-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (Ffile_in_path): Index args correctly.\n\n\t* utils.cc (Ffile_in_path): Call error, not print_usage, for\n\tinvalid option error.\n\t(Ffile_in_loadpath): Likewise.\n\n\t* load-save.cc: Use OCTAVE_LOCAL_BUFFER instead of local automatic\n\tarrays or using new/delete.\n\n\t* lex.l (.): Try another approach to handling EOF here.\n\n\t* load-save.cc (read_mat_ascii_data): Use isalpha and isalnum, not\n\t::isalpha and ::isalnum.\n\n\t* defaults.cc (maybe_add_or_del_packages): SCRIPT_FILE arg is now\n\ta const reference type.\n\n\t* ov.h (octave_value::subsref, octave_value::subsasgn,\n\toctave_value::assign, octave_value::do_non_const_unary_op,\n\toctave_value::numeric_assign): TYPE arg is now a const reference\n\ttype.  Change all derived classes.\n\n\t* ov.cc (octave_value::subsref (const std::string&, const\n\toctave_value_list&)): Move body here, from ov.h.\n\n\t* octave.cc (octave_main): Return 0 at end of function to avoid\n\tcompiler warnings.\n\n2002-12-30  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* parse.y: Fix typo in doc string.\n\n2002-12-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/lpsolve.cc (Flpsolve): Rename from Flp_solve.\n\t(Flpsolve_options): Rename ffrom Flp_solve_options.\n\n2002-12-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (Fevalin): New function.\n\n\t* variables.cc (curr_caller_sym_tab): New global variable.\n\t* variables.h: Provide decl.\n\t(initialize_symbol_tables): Initialize it.\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tProtect\tand set it here.\n\n2002-12-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (search_path_for_file): Second arg now string_vector.\n\tUse find_first_of, not find.\n\t(search_path_for_all_files): Second arg now string_vector.\n\tUse find_all_first_of, not find_all.\n\t(Ffile_in_path): Accept cell array of strings as first argument.\n\t(Ffile_in_loadpath): Likewise.\n\n\t* dynamic-ld.cc (octave_dynamic_loader::load): New arg, file_name.\n\t(octave_dynamic_loader::do_load): Likewise.  If file_name is not\n\tempty, use it instead of searching in path.\n\n\t* parse.y (load_fcn_from_file): Use find_first_of to perform search.\n\n\t* ov-cell.cc (octave_cell::all_strings): New function.\n\t* ov-cell.h: Provide decl.\n\n2002-12-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (function_end): If parsing a nested function, set\n\tlexer_flags.parsing_nested_function to -1.\n\t(frob_function): If lexer_flags.parsing_nested_function is\n\tnegative, set it to zero.\n\t* lex.h (lexical_feedback::parsing_nested_function): Now int.\n\tChange uses as needed.\n\n\t* lex.l (NESTED_FUNCTION_BEGIN): Rename from NESTED_FUNCTION_START.\n\tNow an exclusive start state.\n\t(NESTED_FUNCTION_END): New exclusive start state.\n\t(is_keyword): When matching a new function keyword in a nested\n\tfunction context, explicitly return END and set start state to\n\tNESTED_FUNCTION_END.\n\t(.): Accept EOF here too.\n\n\t* variables.cc (link_to_builtin_or_function): Maybe prepend parent\n\tfunction name symbol name.\n\n\t* parse.y (parent_function_name): New variable.\n\t(fcn_name): New non-terminal.\n\t(function2): Use it.\n\t(parsed_fcn_name): Fold into fcn_name.\n\t(function_end): Don't call check_for_garbage_after_fcn_def.\n\tSet lexer_flags.parsing_nested_function on EOF.\n\t* parse.h: Provide decl for parent_function_name.\n\n\t* ov-usr-fcn.h (octave_user_function::mark_as_nested_function,\n\t(octave_user_funciton::is_nested_function): New functions.\n\t(octave_user_function::nested_function): New data member.\n\t(octave_user_function::do_multi_index_op): Maybe protect and set\n\tcurr_parent_function pointer.\n\t* parse.y (frob_function): Maybe mark as nested function.\n\n\t* toplev.cc (curr_parent_function): New global variable.\n\t* toplev.h: Provide decl.\n\n\t* lex.l (check_for_garbage_after_fcn_def): Delete.\n\t* lex.h: Delete decl.\n\n\t* lex.l (prep_for_nested_function): New function.\n\t(<NESTED_FUNCTION_START>): Use it here.\n\t(is_keyword): And here.\n\t(lookup_identifier): Maybe prepend parent function name.\n\n\t* variables.cc (initialize_symbol_tables): Give names to the three\n\tmain symbol tables.\n\t* symtab.cc (symbol_table::lookup, symbol_table::rename): Print\n\tdebugging info if Vdebug_symtab_lookups is nonzero.\n\t(debug_symtab_lookups): New function.\n\t(Vdebug_symtab_lookups): New static variable.\n\t(symbols_of_symtab): DEFVAR it.\n\t* symtab.h (symbol_table::table_name): New member variable.\n\t(symtab_count): New static member variable.\n\t(symbol_table::symbol_table): Handle table name.\n\n2002-12-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (frob_function): Don't give nested functions the same\n\tname as the function file.\n\n\t* lex.h (lexical_feedback::parsing_nested_function): New data member.\n\t* lex.l (lexical_feedback::init): Initialize it to false.\n\t(<NESTED_FUNCTION_START>): Set lexer_flags.parsing_nested_function\n\tto true.\n\n\t* parse.y (symtab_context): Now a stack.  Change all uses.\n\n\t* lex.l (NESTED_FUNCTION_START): New start state to handle\n\t\"function\" keyword in a nested function context.\n\t(prep_for_function): New function.\n\t(is_keyword): Allow functions to be nested in function files.\n\n\t* lex.l (is_keyword): Maybe ignore END tokens.\n\tIncrement and decrement end_tokens_expected as appropriate.\n\t(handle_identifier): If is_keyword returns -1, return immediately.\n\t({IDENT}{S}*): Do nothing if handle_identifier returns -1.\n\n\t* parse.y (end_tokens_expected): New variable.\n\t(parse_fcn_file): Protect and set it.\n\n\t* parse.y (begin_obj_idx): Increment\n\tlexer_flags.looking_at_object_index.\n\t(postfix_expr): Decrement it as appropriate here.\n\n\t* lex.h (lexical_feedback::looking_at_object_index): Now int.\n\n\t* parse.y (postfix_expr): Reset\tlexer_flags.looking_at_object_index\n\tin () and {} cases too.\n\n2002-12-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-arg-list.cc (indexed_object, indexed_position):\n\tNew file-scope static variables.\n\t(tree_argument_list::convert_to_const_vector): New arg, object.\n\tProtect and set indexed_object and indexed_position.\n\t(F__end__): New function.\n\n\t* octave-lvalue.h (octave_lvalue::object): New member function.\n\t* pt-idx.cc (make_value_list): New arg, object.  Change all\n\tcallers.  Pass object to convert_to_const_vector.\n\n\t* lex.h (lexical_feedback.looking_at_object_index): New data member.\n\t* lex.l (lexical_feedback::init): Initialize it.\n\t(is_keyword): If looking at object index, end is not a keyword.\n\t(handle_identifier): If end is not a keyword, transform it to __end__.\n\t* parse.y (begin_obj_idx): New non-terminal.\n\t(postfix_expr): Use it.\n\n\t* defun.cc (install_builtin_function): New arg, can_hide_function.\n\t* defun-int.h: Fix decl.\n\t(DEFCONSTFUN_INTERNAL): New macro.\n\t* defun.h (DEFCONSTFUN): New macro.\n\t* mkbuiltins (XDEFCONSTFUN_INTERNAL): New macro.\n\t* mkgendoc: Likewise.\n\t* Makefile.in (DEFUN_PATTERN): Make it work for DEFCONSTFUN too.\n\t* symtab.h (symbol_record::can_hide_function): New data member.\n\t(symbol_record::symbol_record): Initialize it.\n\t* symtab.cc (symbol_record::variable_reference): Also check\n\tcan_hide_function flag.\n\n2002-12-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/time.cc (extract_tm): Use int_value() instead of\n\tcasting double_value() to int.\n\n\t* ov.cc (octave_value::next_subsref): Arg \"skip\" is now size_t.\n\n\t* oct-obj.h (octave_value_list::octave_value_list (double),\n\toctave_value_list::octave_value_list (const Matrix&),\n\toctave_value_list::octave_value_list (const DiagMatrix&),\n\toctave_value_list::octave_value_list (const RowVector&),\n\toctave_value_list::octave_value_list (const ColumnVector&),\n\toctave_value_list::octave_value_list (const Complex&),\n\toctave_value_list::octave_value_list (const ComplexMatrix&),\n\toctave_value_list::octave_value_list (const ComplexDiagMatrix&),\n\toctave_value_list::octave_value_list (const ComplexRowVector&),\n\toctave_value_list::octave_value_list (const ComplexColumnVector&),\n\toctave_value_list::octave_value_list (const char *),\n\toctave_value_list::octave_value_list (const std::string&),\n\toctave_value_list::octave_value_list (const string_vector&),\n\toctave_value_list::octave_value_list (double, double, double),\n\toctave_value_list::octave_value_list (const Range&): Delete.\n\tAdjust uses of octave_value/octave_value_list to handle this change.\n\n\t* ov.cc (octave_value::octave_value (int)): New constructor.\n\t* ov.h: Provide decl.\n\tIn files that construct integer-valued octave_value objects, use\n\tints instead of casing to double.\n\n2002-12-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (read_mat_ascii_data): Allow commas to separate values.\n\tTry harder to convert filenames to valid identifiers in a\n\tMatlab-compatible way.\n\n2002-12-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: No need to add $(LIBKPATHSEA) to LINK_DEPS, since\n\tit is not included in liboctave.\n\n2002-12-18  JD Cole  <jdcole@san.rr.com>\n\n\t* pt-check.cc (tree_checker::visit_subplot_axes,\n\ttree_checker::visit_do_until_command): New functions.\n\t* pt-check.h: Provide decl.\n\n2002-12-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (Fclear): Fix off-by-one error.\n\n\t* oct-stream.cc (octave_base_stream::do_gets): Correctly read\n\tlast line of file even if it does not end with new line\n\tcharacter.\n\n\t* pt-select.cc (equal): Don't look up == op, just try it and see\n\twhether it works.\n\n\t* oct-stream.cc (printf_format_list::printf_format_list):\n\tHandle empty format string.\n\n2002-12-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-mat.cc (class tm_row_const::tm_row_const_rep): Derive from\n\toctave_base_list instead of SLList.  Fix tm_row_const member\n\tfunctions as needed, change all uses.\n\t(class tm_const): Derive from octave_base_list, not SLList.  Fix\n\tmember functions as needed, change all uses.\n\t* pt-mat.h (class tree_matrix): Derive from octave_base_list\n\tinstead of including SLList object as data member.  Fix member\n\tfunctions as needed, change all uses.\n\n\t* pt-idx.h (tree_index_expression::args,\n\ttree_index_expression::arg_nm, tree_index_expression::dyn_field):\n\tNow std::list, not SLList.  Fix member functions as needed, change\n\tall uses.\n\n\t* oct-map.h (Octave_map::map): Now std::map instead of CHMap.\n\tFix member functions as needed, change all uses.\n\n\t* oct-lvalue.h (octave_lvalue::idx): Now std::list instead of\n\tSLList object.  Fix member functions as needed, change all uses.\n\n\t* dynamic-ld.cc (octave_shlib_list::lib_list): Now std::list\n\tinstead of DLList object.  Fix member functions as needed, change\n\tall uses.\n\n\t* ov.h (octave_value::subsref, octave_value::subsasgn):\n\tIndex arg is not std::list, not SLList.  Change all derived\n\tclasses, all uses.\n\n\t* pt-stmt.h (tree_statement_list): Derive from base_octave_list\n\tobject instead of including SLList object as data member.  Fix\n\tmember functions as needed, change all uses.\n\t* pt-select.h (tree_switch_case_list): Likewise.\n\t(tree_if_command_list): Likewise.\n\t* pt-misc.h (tree_parameter_list, tree_return_list,\n\ttree_va_return_list): Likewise.\n\t* pt-plot.h (subplot_list): Likewise.\n\t* pt-mat.h (tree_matrix): Likewise.\n\t* pt-decl.h (tree_decl_init_list): Likewise.\n\t* pt-arg-list.h (tree_argument_list): Likewise.\n\t* comment-list.h (octave_comment_list): Likewise.\n\n\t* BaseSLList.cc, DLList.cc, Map.cc, SLList.cc, SLStack.cc,\n\tStack.cc: Delete.\n\t* Makefile.in (DIST_SRC): Delete them from the list.\n\n\t* BaseSLList.h, DLList.h, Map.h, Pix.h, SLList.h, SLStack.h,\n\tStack.h: Delete\n\t* Makefile.in (INCLUDES): Delete them from the list.\n\n\t* Map-oct-obj.cc, SLList-expr.cc, SLList-misc.cc, SLList-plot.cc,\n\tSLList-tc.cc, SLList-tm.cc: Delete.\n\t* Makefile.in (TI_XSRC): Delete them from the list.\n\n\t* ov-base-mat.cc (octave_base_matrix::assign): Pass\n\tMT::resize_fill_value () as third arg for ::assign.\n\n\t* Cell.h (Cell::resize_fill_value): Use empty Matrix object, not\n\tundefined octave_value object.\n\t(Cell::Cell (int, int, const octave_value&)): Use\n\tresize_fill_value () as default value, not undefined octave_value\n\tobject.\n\n2002-12-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DEFUN_PATTERN): Make it work for DEFCMD too.\n\n\t* base-list.h: New file.\n\n2002-12-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (octave_interpreter_ready): New global variable.\n\t* toplev.h: Provide decl.\n\n\t* octave.cc (octave_main): Call execute_default_pkg_add_files just\n\tbefore executing startup files.  Set octave_interpreter_ready to\n\ttrue before calling execute_default_pkg_add_files.\n\n\t* defaults.cc (maybe_add_or_del_packages, default_load_path,\n\tupdate_load_path_dir_path): New static functions.\n\t(set_default_path, loadpath): Call update_load_path_dir_path.\n\t(symbols_of_defaults): Use DEFVAR, not DEFCONST for DEFAULT_LOADPATH.\n\t(execute_default_pkg_add_files): New function.\n\t* defaults.h.in: Provide decl.\n\n\t* utils.cc (search_path_for_all_files): New function.\n\t(Ffile_in_loadpath, Ffile_in_path): Allow search to return all\n\tfiles in the path.\n\n\t* Cell.cc (Cell (const string_vector&)): New constructor.\n\n\t* oct-obj.cc (octave_value_list::assign): Allow optional fill\n\tvalue for resizing.\n\t* oct-map.cc (Octave_map::assign): Pass fill_value in initial\n\tassignment too.\n\n2002-12-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* TEMPLATE-INST/Map-tc.cc, TEMPLATE-INST/Map-fnc.cc: Delete.\n\t* Makefile.in (TI_XSRC): Delete them from the list.\n\n\t* fn-cache.h (octave_fcn_file_name_cache::cache): Now std::map,\n\tnot CHMap.\n\n\t* TEMPLATE-INST/SLStack-i.cc, TEMPLATE-INST/SLStack-ovl.cc,\n\tTEMPLATE-INST/SLStack-pc.cc, TEMPLATE-INST/SLStack-str.cc,\n\tTEMPLATE-INST/SLStack-sym.cc, TEMPLATE-INST/SLStack-tok.cc,\n\tTEMPLATE-INST/SLStack-ue.cc, TEMPLATE-INST/SLStack-ui.cc:\n\tDelete unnecessary files.\n\t* Makefile.in (TI_XSRC): Delete them from the list.\n\n\t* toplev.cc (octave_atexit_functions): Now std::stack, not SLStack.\n\t* pt-plot.cc (tmp_files): Likewise.\n\t* lex.l (token_stack): Likewise.\n\t(class bracket_brace_paren_nesting_level): Make context a data\n\tmember instead of deriving from SLStack object.\n\tUse std::stack instead of SLStack.\n\t* ov-usr-fcn.h (octave_user_function::saved_args): Likewise.\n\t* symtab.h (symbol_record::context): Likewise.\n\t(symbol_record::global_link_context): Likewise.\n\n\t* unwind-prot.h (unwind_protect::elt_list): Rename from list.\n\tNow std::stack, not SLStack.\n\n\t* pt-stmt.h (tree_statement_list): Make list member data instead\n\tof deriving from SLList object.\n\t* pt-select.h (tree_switch_case_list): Likewise.\n\t(tree_if_command_list): Likewise.\n\t* pt-plot.h (subplot_list): Likewise.\n\t* pt-mat.h (tree_matrix): Likewise.\n\t* pt-decl.h (tree_decl_init_list): Likewise.\n\t* pt-arg-list.h (tree_argument_list): Likewise.\n\t* comment-list.h (octave_comment_list): Likewise.\n\n\t* defun.h (DEFCMD): Rename from DEFUN_TEXT.  Provide DEFUN_TEXT as\n\tan alias for DEFCMD.  Change all uses.\n\n\t* variables.cc (at_top_level): New function.\n\t(do_who, Fmark_as_command, Funmark_command): Use it.\n\n\t* lex.l (COMMAND_START): Rename from TEXT_FCN.  Change all uses.\n\t(MATRIX_START): Rename from MATRIX.  Change all uses.\n\t* variables.cc (command_function_set): Rename from\n\ttext_function_set.\n\t(mark_as_command): Rename from mark_as_text_function.\n\t(is_marked_as_command): Rename from is_marked_as_text_function.\n\t(Fmark_as_command): Rename from Fmark_as_text_function.\n\t(Funmark_command): Rename from Funmark_text_function.\n\t(is_command_name): Rename from is_text_function_name.\n\t* symtab.h (symbol_record::COMMAND): Rename from TEXT_FUNCTION.\n\t(symbol_record::mark_as_command): Rename from mark_as_text_function.\n\t(symbol_record::unmark_command): Rename from\n\tsymbol_record::unmark_text_function.\n\t(symbol_record::is_command): Rename from\n\tsymbol_record::is_text_function.\n\t(symbol_record::symbol_def::mark_as_command): Rename from\n\tsymbol_record::symbol_def::mark_as_text_function.\n\t(symbol_record::symbol_def::unmark_command): Rename from\n\tsymbol_record::symbol_def::unmark_text_function.\n\t(symbol_record::symbol_def::is_command): Rename from\n\tsymbol_record::symbol_def::is_text_function.\n\n\t* pt-jump.h, pt-jump.cc: Undo previous changes.\n\t* parse.y: Undo previous changes for brea, continue, and return.\n\n2002-11-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-stmt.cc (tree_statement::eval): Allow the lookup to execute\n\tscript files.  If script file has been executed, don't bother to\n\tcall expr->rvalue ().\n\n2002-11-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (OCTINTERP_LINK_DEPS): Include $(FLIBS) in\n\tOCTINTERP_LINK_DEPS.\n\n\t* variables.cc (text_function_set): New static data.\n\t(mark_as_text_function, unmark_text_function,\n\tis_marked_as_text_function, Fmark_as_text_function,\n\tFunmark_text_function): New functions.\n\t(is_text_function_name): Handle functions marked as text functions\n\tin special list, not just those marked in the symbol record.\n\t* symtab.h (symbol_record::mark_as_text_function,\n\tsymbol_record::unmark_text_function,\n\tsymbol_record::symbol_def::mark_as_text_function,\n\tsymbol_record::symbol_def::unmark_text_function): New functions.\n\n\t* oct-map.h (Octave_map::rows, Octave_map::columns): New functions.\n\t* ov-struct.h (octave_struct::rows, octave_struct::columns,\n\toctave_struct::length): New functions.\n\n2002-11-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-conf.h.in (OCTAVE_CONF_MKOCTFILE_SH_LDFLAGS): New macro.\n\t* toplev.cc (octave_config_info): Add it to the struct.\n\n\t* lex.l (<TEXT_FCN>): If yytext begins with # or %, don't\n\trecognize it as a string.\n\n\t* oct-map.h (Octave_map::operator[]): New const version.\n\t* oct-map.cc (equiv_keys): New function.\n\t(assign (const idx_vector&, const Octave_map&)): New function.\n\t* ov-struct.cc (octave_struct::subsasgn): Use it.\n\n2002-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.40.\n\n\t* p-b-b.cc, op-bm-bm.cc, op-chm.cc, op-cm-cm.cc, op-cm-cs.cc,\n\top-cm-m.cc, op-cm-s.cc, op-cs-cm.cc, op-cs-cs.cc, op-cs-m.cc,\n\top-cs-s.cc, op-fil-b.cc, op-fil-bm.cc, op-fil-cm.cc, op-fil-cs.cc,\n\top-fil-lis.cc, op-fil-m.cc, op-fil-rec.cc, op-fil-s.cc,\n\top-fil-str.cc, op-list.cc, op-m-cm.cc, op-m-cs.cc, op-m-m.cc,\n\top-m-s.cc, op-range.cc, op-s-cm.cc, op-s-cs.cc, op-s-m.cc,\n\top-s-s.cc, op-str-str.cc, op-bm-b.cc, op-cell.cc, BaseSLList.cc,\n\tBaseSLList.h, ChangeLog, Map.cc, Map.h, SLList.cc, SLList.h,\n\tSLStack.cc, SLStack.h, Stack.cc, Stack.h, oct-map.cc, oct-map.h,\n\toct-obj.cc, oct-obj.h, c-file-ptr-stream.cc, c-file-ptr-stream.h,\n\tov-base-mat.cc, ov-base-scalar.cc, ov-base-scalar.h, ov-base.cc,\n\tov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool.cc, ov-bool.h,\n\tov-builtin.cc, ov-builtin.h, ov-ch-mat.cc, ov-ch-mat.h,\n\tov-colon.cc, ov-complex.cc, ov-complex.h, ov.h, ov-cx-mat.cc,\n\tov-cx-mat.h, ov-fcn.cc, ov-fcn.h, ov-file.cc, ov-file.h,\n\tov-list.cc, ov-list.h, ov-mapper.cc, ov-mapper.h, ov-range.cc,\n\tov-range.h, ov-re-mat.cc, ov-re-mat.h, ov-scalar.cc, ov-scalar.h,\n\tov-str-mat.cc, ov-str-mat.h, ov-struct.cc, ov-struct.h,\n\tov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h,\n\tov-va-args.cc, ov.cc, ov-base-mat.h, procstream.cc, procstream.h,\n\tpt-arg-list.cc, pt-arg-list.h, pt-binop.cc, pt-binop.h,\n\tpt-check.cc, pt-check.h, pt-cmd.cc, pt-cmd.h, pt-colon.cc,\n\tpt-colon.h, pt-const.cc, pt-const.h, pt-decl.cc, pt-decl.h,\n\tpt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h, pt-id.cc, pt-id.h,\n\tpt-idx.cc, pt-idx.h, pt-jump.cc, pt-jump.h, pt-loop.cc, pt-loop.h,\n\tpt-mat.cc, pt-mat.h, pt-misc.cc, pt-misc.h, pt-pr-code.cc,\n\tpt-pr-code.h, pt-select.cc, pt-select.h, pt-stmt.cc, pt-stmt.h,\n\tpt-unop.cc, pt-unop.h, pt.cc, pt.h, symtab.h, token.cc, token.h,\n\tunwind-prot.cc, unwind-prot.h, ov-base-nd-array.cc,\n\tov-re-nd-array.h, ov-re-nd-array.cc, ov-base-nd-array.h,\n\tcomment-list.h, comment-list.cc, DLList.cc, DLList.h,\n\tov-dld-fcn.h, ov-dld-fcn.cc, Cell.cc, Cell.h, pt-cell.h,\n\tpt-cell.cc, ov-cell.h, ov-cell.cc, pt-plot.cc, pt-plot.h,\n\tpt-assign.cc, pt-assign.h, pt-bp.cc, pt-bp.h, symtab.cc,\n\tov-cs-list.h, ov-cs-list.cc:\n\tUse \"defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION)\" instead of\n\t\"! defined (NO_PRAGMA_INTERFACE_IMPLEMENTATION)\".\n\n2002-11-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-obj.h (octave_value_list::~octave_value_list): New function.\n\n2002-11-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/odessa.cc (odessa_user_j): Put T in args(1), not\n\targs(0).\n\n2002-11-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (symtab_context): Now extern.\n\t* parse.h: Provide decl.\n\t* lex.l (reset_parser): Set it to 0.\n\n2002-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-bp.cc (octave_debug_on_interrupt_state): New global variable.\n\t* pt-bp.h: Provide decl.\n\t(MAYBE_DO_BREAKPOINT): Check it.\n\n\t* sighandlers.cc (sigint_handler): Handle debug_on_interrupt.\n\t(Vdebug_on_interrupt): New static variable.\n\t(symbols_of_sighandlers): New function.  DEFVAR Vdebug_on_interrupt.\n\t(debug_on_interrupt): New function.\n\n\t* lex.h (YY_FATAL_ERROR): Use OCTAVE_QUIT here.\n\n\t* utils.cc (toplevel): Delete variable.\n\n\t* sighandlers.cc (OCTAVE_MEMORY_EXHAUSTED_ERROR): Delete.\n\n2002-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (octave_new_handler): Delete.\n\t(install_signal_handlers): Don't call set_new_handler.\n\t* toplev.cc (main_loop): Handle bad_alloc exception here.\n\n\t* sighandlers.cc (octave_new_handler): Allow return after\n\tOCTAVE_JUMP_TO_TOP_LEVEL.\n\t(sigfpe_handler): Likewise.\n\n2002-11-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (is_variable): New static function.\n\t(generate_struct_completions): Only evaluate objects that look\n\tlike variables.\n\n2002-11-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-jump.h, pt-jump.cc (tree_break_expression,\n\ttree_continue_expression, tree_return_expression): Rename from\n\ttree_break_command, tree_continue_command, tree_return_command.\n\tImplement as expressions that return TRUE instead of commands.\n\tChange all uses.\n\t* parse.y (make_break_expression, make_continue_expression,\n\tmake_return_expression): Rename from make_break_command,\n\tmake_continue_command, make_return_command.  Change all uses.\n\t(jump_expr): Rename from jump_command, type is now expression.\n\tUse in simple_expr, not command.\n\n\t* toplev.cc (octave_initialized): New global variable.\n\t(main_loop): Set it to true here.\n\t* sighandlers.cc (sigint_handler): Exit immediately if we have not\n\tfinished init process.\n\n\t* load-save.cc (extract_keyword): Return std::string, not char *.\n\tChange all uses.\n\t(read_ascii_data): Likewise.\n\t(read_binary_data): Likewise.\n\t(read_hdf5_data): Likewise.\n\t(read_mat_ascii_data): Likewise.\n\t(read_mat_binary_data): Likewise.\n\t(do_load): Name and doc are now std::string objects, not char *.\n\t(install_loaded_variable): Likewise.\n\t(read_hdf5_data): Doc is now std::string object, not char *&.\n\t(read_mat_ascii_data): Call OCTAVE_QUIT in strategic locations.\n\t(get_lines_and_columns): Likewise.\n\n\t* toplev.cc (main_loop): Call OCTAVE_QUIT after executing command.\n\t* parse.y (parse_and_execute (FILE *)): Likewise.\n\n2002-11-12  Joseph P. Skudlarek  <jskud@jskud.com>\n\n\t* input.cc (match_sans_spaces_semi): Rename from match_sans_spaces.\n\tIgnore trailing semicolons too.  Change all callers.\n\n2002-11-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.gperf: Allow \"persistent\" as a synonym for static.\n\n\t* defun-int.h (DEFUN_MAPPER_INTERNAL): Don't forget doc string\n\twhen creating octave_mapper object.\n\n\t* sysdep.cc (BSD_init): Avoid failure if FP_X_DNML is not defined.\n\n2002-11-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cutils.c: Be sure to always return buf.\n\n\tUndo previous vnprintf changes.  The portable snprintf I found\n\tdoes not handle floating point conversions...\n\n2002-11-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (liboctinterp.$(LIBEXT)): Include $(XERBLA) here.\n\t(octave.$(EXEEXT)): Not here.\n\t(liboctinterp.$(SHLEXT)): Include $(PIC_XERBLA) here.\n\n\t* main.c: Move decl for xerbla here from octave.cc.\n\n\t* cutils.c (octave_vsnprintf): Use portable_snprintf to avoid\n\thaving to cope with all kinds of buggy implementations.\n\n\t* snprintf.c: New file.\n\t* Makefile.in (DISTFILES): Add it to the list.\n\n\t* oct-snprintf.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\n\t* oct-snprintf.c: New file.\n\t* Makefile.in (DIST_SRC): Add it to the list.\n\n\t* toplev.cc (main_loop): Use SET_OCTAVE_INTERRUPT_IMMEDIATELY\n\tinstead of assigning octave_interrupt_immediately.\n\n2002-11-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (jump_to_top_level): Delete.\n\n\t* toplev.cc (toplevel): Delete.\n\t(main_loop): Adapt to new signal/exception handling scheme.\n\n\t* sighandlers.cc (octave_signal_mask, octave_save_signal_mask,\n\toctave_restore_signal_mask): Move to libcruft/misc/quit.cc.\n\t(sigint_handler) [USE_EXCEPTIONS_FOR_INTERRUPTS]: set\n\toctave_interrupt_state.  Only jump if octave_interrupt_immediately\n\tis true, and then only to enclosing context.\n\n\t* lex.h (YY_FATAL_ERROR): Use OCTAVE_JUMP_TO_TOP_LEVEL, not\n\tjump_to_top_level.\n\t* sighandlers.cc (octave_new_handler, sigfpe_handler, endif,\n\tsigpipe_handler): Likewise.\n\n\t* input.cc (gnu_readline): Surround call to\n\tcommand_editor::readline with\n\tBEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE and\n\tEND_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE.\n\n\t* data.cc, oct-stream.cc, ov-cell.cc, ov-mapper.cc, ov-re-mat.cc,\n\tov.cc, pr-output.cc, pt-loop.cc, pt-stmt.cc, xdiv.cc, xpow.cc,\n\tDLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/besselj.cc,\n\tDLD-FUNCTIONS/filter.cc, DLD-FUNCTIONS/find.cc,\n\tDLD-FUNCTIONS/kron.cc, DLD-FUNCTIONS/log.cc,\n\tDLD-FUNCTIONS/minmax.cc, DLD-FUNCTIONS/qz.cc,\n\tDLD-FUNCTIONS/rand.cc, DLD-FUNCTIONS/sort.cc: Sprinkle with\n\tOCTAVE_QUIT.\n\n\t* DLD-FUNCTIONS/odessa.cc (Fodessa): Correctly extract bsub from\n\tfunction arg.\n\n2002-11-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cutils.c (octave_vsnprintf): Handle C99 snprintf semantics.\n\n\t* oct-obj.h (octave_value_list::operator =): Copy names too.\n\t(octave_value_list::octave_value_list (const octave_value_list&)):\n\tLikewise.\n\n2002-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.39.\n\n\t* variables.cc (generate_struct_completions): Temporarily reset\n\tdiscard_error_messages and error_state\n\t(looks_like_struct): Temporarily reset Vwarning option,\n\terror_state, and discard_error_messages.\n\n\t* pt-idx.cc (tree_index_expression::eval_error): Now const.\n\t(tree_index_expression::get_struct_index): Require valid identifier.\n\t(tree_index_expression::make_arg_struct,\n\ttree_index_expression::rvalue, tree_index_expression::lvalue):\n\tHandle possible error from get_struct_index.\n\n\t* utils.cc (valid_identifier): Move here from load-save.cc.\n\t* utils.h: Provide decl.\n\n\t* input.cc (generate_possible_completions): Call\n\tcommand_editor::filename_completion_desired here.\n\t(generate_possible_completions): Don't generate struct completions\n\tif text contains directory separator or \"..\".\n\n2002-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/odessa.cc (odessa_user_f, odessa_user_j,\n\todessa_user_b): Reorder args for consistency with other solvers.\n\t(Fodessa): Use extract_function to set args.\n\t(odessa_user_j): Rename from odessa_user_mf.\n\n\t* DLD-FUNCTIONS/fsolve.cc (fsolve_user_function, fsolve_user_jacobian):\n\tPrint warning if user returns complex value.\n\t* DLD-FUNCTIONS/quad.cc (quad_user_function): Likewise.\n\t* DLD-FUNCTIONS/lsode.cc (lsode_user_function, lsode_user_jacobian):\n\tLikewise.\n\t* DLD-FUNCTIONS/dassl.cc (dassl_user_function, dassl_user_jacobian):\n\tLikewise.\n\t* DLD-FUNCTIONS/dasrt.cc (dasrt_user_f, dasrt_user_cf, dasrt_user_j):\n\tLikewise.\n\t* DLD-FUNCTIONS/daspk.cc (daspk_user_function, daspk_user_jacobian):\n\tLikewise.\n\n\t* DLD-FUNCTIONS/daspk.cc (daspk_user_jacobian): New function.\n\t(Fdaspk): Handle extracting Jacobian from function argument.\n\n\t* DLD-FUNCTIONS/fsolve.cc (fsolve_user_function): New function.\n\t(Ffsolve): Handle extracting Jacobian from function argument.\n\n\t* Makefile.in (%.oct): Depend on octave$(EXEEXT) so that octave\n\twill be built before any .oct files.\n\t(all): Depend on stamp-oct-links.\n\t(octave$(EXEEXT)): Don't depend on stamp-oct-links.\n\n\t* ov-base.cc (octave_base_value::subsasgn): Handle default numeric\n\tcase here.\n\t* ov-base-mat.cc (octave_base_matrix<MT>::subsasgn): Delete.\n\n2002-10-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (OCT_LINK_DEPS): Add $(BLAS_LIBS), $(FFTW_LIBS), and\n\t$(FLIBS).\n\n2002-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.38.\n\n\t* utils.cc (octave_vformat): Get return value from\n\tstreambuf::vform.\n\n\t* DLD-FUNCTIONS/fsolve.cc (Ffsolve): Always return solution.\n\tDon't barf on nargout == 3.\n\n\t* pt-idx.h (tree_index_expression::dyn_field): New data member.\n\t* pt-idx.cc (tree_index_expression::tree_index_expression\n\t(tree_expression*, tree_expression*, int, int)): New constructor.\n\t(tree_index_expression::append (tree_expression*)): New function.\n\t(tree_index_expression::get_struct_index): New function.\n\t(tree_index_expression::make_arg_struct): Handle dynamic fields.\n\t(tree_index_expression::rvalue): Likewise.\n\t(tree_index_expression::lvalue): Likewise.\n\n\t* parse.y (make_indirect_ref (tree_expression*, tree_expression*)):\n\tNew function.\n\t(indirect_ref_op): New non-terminal.\n\t(postfix_expr): Use it.\n\tRecognize dynamic struct field references.\n\t(parsing_indir): Delete unused non-terminal.\n\n\t* lex.l (\"(\"): Set lexer_flags.looking_at_indirect_ref to false here.\n\n\t* pt-idx.cc (tree_index_expression::name): Simplify.\n\n2002-10-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-conf.h.in (OCTAVE_CONF_HAVE_DLOPEN_API,\n\tOCTAVE_CONF_HAVE_LOADLIBRARY_API, OCTAVE_CONF_HAVE_SHL_LOAD_API):\n\tDelete.\n\t* toplev.cc (octave_config_info): Delete them from the struct\n\n\t* load-save.cc (read_ascii_data): Use octave_read_double and\n\toctave_read_complex so that we handle Inf, NaN, and NA.\n\t(read_mat_ascii_data): Likewise.\n\t(save_ascii_data): Use octave_write_double andoctave_write_complex.\n\n2002-10-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (octave_config_info): Rename WITH_DYNAMIC_LINKING to\n\tENABLE_DYNAMIC_LINKING.\n\t* oct-conf.h.in: Likewise.\n\t* mkbuiltins: Likewise.\n\t* fn-cache.cc (file_name_cache_elt::update): Likewise.\n\t* Makefile.in: Likewise.\n\n2002-10-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cutils.c (octave_vsnprintf): Buffer and buffer size now static.\n\t* utils.cc (octave_vformat): Don't free buffer returned from\n\toctave_vsnprintf here.\n\n\t* ov-usr-fcn.cc (va_arg, va_start, vr_val): Only print warning\n\tonce per session.\n\n\t* ov-mapper.cc (octave_mapper::apply): Don't try real_type case if\n\targ is a string and we have a ch_map_fcn.\n\n\t* Makefile.in: Add $(LIBKPATHSEA) to $(OCTAVE_LIBS) if\n\t$(INCLUDE_LINK_DEPS) is false, not if $(SHARED_LIBS) is false.\n\n2002-10-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/daspk.cc (daspk): Use set_options, not copy.\n\t* DLD-FUNCTIONS/dasrt.cc (dasrt): Likewise.\n\t* DLD-FUNCTIONS/dassl.cc (dassl): Likewise.\n\t* DLD-FUNCTIONS/fsolve.cc (fsolve): Likewise.\n\t* DLD-FUNCTIONS/lsode.cc (lsode): Likewise.\n\t* DLD-FUNCTIONS/odessa.cc (Fodessa): Likewise.\n\t* DLD-FUNCTIONS/quad.cc (Fquad): Likewise.\n\n2002-10-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-map.cc (Octave_map::assign): Fix typo in resizing.\n\n\t* pt-loop.cc (tree_complex_for_command::eval): Only return list\n\tfor val if struct array has more than one element.\n\t(tree_simple_for_command::eval): Likewise.\n\n\t* ov-struct.cc (octave_struct::print_raw): Don't create\n\toctave_list directly, use octave_value (const octave_value_list&)\n\tconstructor instead.\n\tCall print_with_name for tmp, not val(0).\n\n\t* version.h (OCTAVE_VERSION): Now 2.1.37.\n\t(OCTAVE_CONTRIB_STATEMENT): New macro.\n\t(OCTAVE_STARTUP_MESSAGE): Use it.\n\n2002-10-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (fill_matrix): If nargin is zero, use val, not 0.0.\n\n\t* main.c: New file.\n\t* octave.h: New file.\n\t* octave.cc (octave_main): Rename from main.\n\tInclude octave.h.\n\t* Makefile.in (OBJECTS): Add octave.o, builtins.o, and ops.o to\n\tthe list.\n\t(octave): Depend on and link main.o, not octave.o, builtins.o, and\n\tops.o (they are now in liboctinterp).\n\t(DEP_5): Add main.c here.\n\n\t* oct-conf.h.in: No need to substitute OCTAVE_CONF_OCTAVE_LITE.\n\t* toplev.cc (octave_config_info): Likewise, don't include it in\n\tstruct.\n\n\t* mkbuiltins: Remove check for OCTAVE_LITE, since it is now\n\timplied by WITH_DYNAMIC_LINKING.\n\t* Makefile.in: Likewise, replace tests for OCTAVE_LITE with tests\n\tfor WITH_DYNAMIC_LINKING instead.\n\n\t* oct-conf.h.in: Use OCTAVE_CONF_HAVE_DLOPEN_API,\n\tOCTAVE_CONF_HAVE_LOADLIBRARY_API, and\n\tOCTAVE_CONF_HAVE_SHL_LOAD_API instead of OCTAVE_CONF_WITH_DL and\n\tOCTAVE_CONF_WITH_SHL.\n\t* toplev.cc (octave_config_info): Likewise.\n\n2002-10-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (display_help_text): Quote output file name for Cygwin.\n\n\t* Makefile.in (install-lib): Don't bother with versions for\n\t$(SHLBIN) files.\n\n\t* help.cc (display_help_text): Match zero or more comment\n\tcharacters instead of one or more.\n\n\t* Makefile.in (install-oct): Process files from $(DLD_DEF_FILES),\n\tnot $(DLD_SRC).  Look for them in current directory, not $(srcdir).\n\n2002-10-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-mapper.cc (octave_mapper::apply): Handle real and complex\n\ttypes first.  If the arg is something else, try ch_map_fcn if it\n\tis defined.\n\n2002-10-15  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Makefile.in: If building shared but not static libs, only set\n\tXERBLA to the location of the pic object file if FPICFLAG is\n\tdefined.\n\n2002-10-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t*  DLD-FUNCTIONS/minmax.cc, DLD-FUNCTIONS/getrusage.cc, data.cc,\n\tfile-io.cc, ov-base.cc, ov-bool-mat.cc, ov-ch-mat.cc,\n\tov-complex.cc, ov-cx-mat.cc, ov-range.cc, ov-re-mat.cc,\n\tov-re-nd-array.cc: Change all uses of octave_Inf, octave_NA, and\n\toctave_NaN to be calls to lo_ieee_Inf_value, lo_ieee_NA_value, and\n\tlo_ieee_NaN_value instead of using the constants directly to avoid\n\tlinking problem with Cygwin.\n\n\t* Makefile.in (install): No need to use cd to create links.\n\n2002-10-14  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Makefile.in: Merge liboctave with liboct-readline and\n\tliboct-pathsearch.\n\tUse link dependencies for shared libs if INCLUDE_LINK_DEPS.\n\t(LIBRARIES): If doing shared libs, include versioned library in\tlist.\n\t(liboctinterp.$(SHLEXT), liboctinterp.$(SHLEXT_VER)): Reverse\n\tactions -- build unversioned library, symbolic link adds version\n\tinfo.\n\t(install, uninstall): Handle link and load forms of the library\n\tseparately.\n\n\t* toplev.cc (octave_config_info): Remove LIBOCT_READLINE and\n\tLIBOCT_PATHSEARCH, add LIBREADLINE.\n\t* oct-conf.h.in: Likewise.\n\n2002-10-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (handle_identifier): Don't enter token in local symbol\n\ttable if the following token is a dot and it looks like a binary\n\toperator.\n\t(force_local_variable): If name is not a variable, clear it before\n\tdefining.\n\n\t* oct-procbuf.cc (Vkluge_procbuf_delay): Make default 0 for all\n\tsystems.\n\n\t* octave.cc (execute_startup_files, initialize_pathsearch):\n\tUse file_ops::dir_sep_str instead of OCTAVE_DIR_SEP_STR.\n\t(main): Use file_ops::dir_sep_chars instead of OCTAVE_DIR_SEP_CHARS.\n\n\t* ov-re-mat.cc (octave_matrix::convert_to_str): Warn for out of\n\trange conversions.  For negative values, set to 0.\n\t* ov-scalar.cc (octave_scalar:convert_to_str): Likewise.\n\n\t* mappers.cc (xabs): New static function.\n\t(install_mapper_functions): Use it for abs for character matrices.\n\tHandle ch_map_flag separately from can_ret_cmplx_for_real in\n\tall uses of DEFUN_MAPPER.\n\t* defun.h (DEFUN_MAPPER): Handle ch_map_flag separately from\n\tcan_ret_cmplx_for_real.\n\t* defun-int.h (DEFUN_MAPPER_INTERNAL): Likewise.\n\t* mkbuiltins: Likewise.\n\t* mkgendoc: Likewise.\n\t* ov-mapper.cc (octave_mapper::apply): Use ch_map_flag and\n\tcan_ret_cmplx_for_real instead of flag.\n\t* ov-mapper.h (octave_mapper::ch_map_flag): Rename from flag.\n\t(octave_mapper::can_ret_cmplx_for_real): New data member.\n\t(octave_mapper::octave_mapper): Handle it here.\n\n2002-10-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (execute_startup_files): Don't forget directory\n\tseparator for local initfile.\n\n\t* move-if-change: Delete.\n\t* Makefile.in (DISTFILES): Delete it from the list.\n\n2002-10-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Use $(EXEEXT) and $(BUILD_EXEEXT) as appropriate.\n\n\t* pt-plot.cc (Vgnuplot_binary): Use GNUPLOT_BINARY as default.\n\n\t* octave.cc (execute_startup_files):\n\tUse octave_env::getcwd instead of \"./\".\n\tUse OCTAVE_DIR_SEP_STR instead of \"/\".\n\t(initialize_pathsearch): Use OCTAVE_DIR_SEP_STR instead of /.\n\t(main): Look for OCTAVE_DIR_SEP_CHARS, not '/'.\n\n2002-10-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (gendoc): Use $(BUILD_CXX), not $(CXX).\n\n2002-10-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (octave_sleep): Cast result of modf to unsigned int.\n\n2002-10-07  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* sighandlers.cc (my_friendly_exit): If kill is unavailable, use\n\traise.\n\n2002-10-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sysdep.cc (CYGWIN_init): New function.\n\t(sysdep_init) [__CYGWIN__]: Call it.\n\n\t* pt-plot.cc (subplot::handle_plot_data): Surround file names in\n\tsingle quotes, not double (for Windows).\n\t(do_external_plotter_cd): Likewise.\n\n2002-10-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cutils.c (octave_usleep): Call octave_sleep, not sleep.\n\n\t* utils.cc (octave_sleep (double)): New function.\n\t* utils.h: Provide decl.\n\t* sysdep.cc (Fpause, Fsleep): Use it.\n\n\t* cutils.c (do_octave_usleep): Merge with octave_usleep.\n\t(octave_usleep): Make it work for Windows systems.  From Paul\n\tKienzle <pkienzle@users.sf.net>.\n\n2002-10-03  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* cutils.c (octave_usleep): Make it work for Windows systems.\n\n\t* toplev.cc (Fsystem): Error message if fork is not available.\n\n2002-10-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cutils.c (octave_sleep): Handle Windows, which may not have\n\tsleep, but should have Sleep.\n\n\t* oct-conf.h.in (OCTAVE_CONF_SED): Add an entry for SED.\n\t* toplev.cc (octave_config_info): Likewise.\n\t* Makefile.in (oct-gperf.h): Use $(SED), not sed.\n\n2002-09-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (fopen_mode_to_ios_mode): Set ios::ate instead of\n\tios::app for \"a+\" mode.\n\t* oct-stream.cc (octave_stream::mode_as_string): Recognize\n\tios::ate, not ios::app as \"a+\" mode.\n\t(octave_stream::mode_as_string): Use parens since | has lower\n\tprecedence than ==.\n\n2002-09-26  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* sysdep.cc: Include conio.h if it exists.\n\t(octave_kbhit): Rename from kbhit.  Implement with _kbhit if it\n\texists. Change all callers.\n\t* cutils.c (octave_sleep): New function.\n\tChange all callers of sleep to use octave_sleep instead.\n\n2002-09-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* BaseSLList.cc, BaseSLList.h, Cell.cc, Cell.h, DLList.cc,\n\tDLList.h, Map.cc, Map.h, OPERATORS/op-b-b.cc,\n\tOPERATORS/op-bm-b.cc, OPERATORS/op-bm-bm.cc, OPERATORS/op-cell.cc,\n\tOPERATORS/op-chm.cc, OPERATORS/op-cm-cm.cc, OPERATORS/op-cm-cs.cc,\n\tOPERATORS/op-cm-m.cc, OPERATORS/op-cm-s.cc, OPERATORS/op-cs-cm.cc,\n\tOPERATORS/op-cs-cs.cc, OPERATORS/op-cs-m.cc, OPERATORS/op-cs-s.cc,\n\tOPERATORS/op-fil-b.cc, OPERATORS/op-fil-bm.cc,\n\tOPERATORS/op-fil-cm.cc, OPERATORS/op-fil-cs.cc,\n\tOPERATORS/op-fil-lis.cc, OPERATORS/op-fil-m.cc,\n\tOPERATORS/op-fil-rec.cc, OPERATORS/op-fil-s.cc,\n\tOPERATORS/op-fil-str.cc, OPERATORS/op-list.cc,\n\tOPERATORS/op-m-cm.cc, OPERATORS/op-m-cs.cc, OPERATORS/op-m-m.cc,\n\tOPERATORS/op-m-s.cc, OPERATORS/op-range.cc, OPERATORS/op-s-cm.cc,\n\tOPERATORS/op-s-cs.cc, OPERATORS/op-s-m.cc, OPERATORS/op-s-s.cc,\n\tOPERATORS/op-str-str.cc, SLList.cc, SLList.h, SLStack.cc,\n\tSLStack.h, Stack.cc, Stack.h, c-file-ptr-stream.cc,\n\tc-file-ptr-stream.h, comment-list.cc, comment-list.h, oct-map.cc,\n\toct-map.h, oct-obj.cc, oct-obj.h, ov-base-mat.cc, ov-base-mat.h,\n\tov-base-nd-array.cc, ov-base-nd-array.h, ov-base-scalar.cc,\n\tov-base-scalar.h, ov-base.cc, ov-base.h, ov-bool-mat.cc,\n\tov-bool-mat.h, ov-bool.cc, ov-bool.h, ov-builtin.cc, ov-builtin.h,\n\tov-cell.cc, ov-cell.h, ov-ch-mat.cc, ov-ch-mat.h, ov-colon.cc,\n\tov-complex.cc, ov-complex.h, ov-cs-list.cc ov-cs-list.h,\n\tov-cx-mat.cc, ov-cx-mat.h, ov-dld-fcn.cc, ov-dld-fcn.h, ov-fcn.cc,\n\tov-fcn.h, ov-file.cc, ov-file.h, ov-list.cc, ov-list.h,\n\tov-mapper.cc, ov-mapper.h, ov-range.cc, ov-range.h, ov-re-mat.cc,\n\tov-re-mat.h, ov-re-nd-array.cc, ov-re-nd-array.h, ov-scalar.cc,\n\tov-scalar.h, ov-str-mat.cc, ov-str-mat.h, ov-struct.cc,\n\tov-struct.h, ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc,\n\tov-usr-fcn.h, ov-va-args.cc, ov.cc, ov.h, procstream.cc,\n\tprocstream.h, pt-arg-list.cc, pt-arg-list.h, pt-assign.cc,\n\tpt-assign.h, pt-binop.cc, pt-binop.h, pt-bp.cc, pt-bp.h,\n\tpt-cell.cc, pt-cell.h, pt-check.cc, pt-check.h, pt-cmd.cc,\n\tpt-cmd.h, pt-colon.cc, pt-colon.h, pt-const.cc, pt-const.h,\n\tpt-decl.cc, pt-decl.h, pt-except.cc, pt-except.h, pt-exp.cc,\n\tpt-exp.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-jump.cc,\n\tpt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.cc, pt-mat.h, pt-misc.cc,\n\tpt-misc.h, pt-plot.cc, pt-plot.h, pt-pr-code.cc, pt-pr-code.h,\n\tpt-select.cc, pt-select.h, pt-stmt.cc, pt-stmt.h, pt-unop.cc,\n\tpt-unop.h, pt.cc, pt.h, symtab.cc, symtab.h, token.cc, token.h,\n\tunwind-prot.cc, unwind-prot.h:\n\tIf __GNUG__, use pragma interface/implementation.  Allow this to\n\tbe turned off by defining NO_PRAGMA_INTERFACE_IMPLEMENTATION.\n\n2002-09-26  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* mappers.cc (install_mapper_functions): Install erf, not xerf.\n\tInstall erfc, not xerfc.\n\n\t* pt-bp.cc (tree_breakpoint::visit_unwind_protect_command):\n\tRename lst1 and lst2 to avoid dlgs.h conflict.\n\n\t* parse.y: Replace TEXT with STRING to avoid winnt.h conflict.\n\t* lex.l: Ditto.\n\n\t* sysdep.cc (raw_mode): Non-fatal warning if raw_mode is not\n\tsupported.\n\n\t* sighandlers.cc: Don't define handlers for non-existent signals.\n\n\t* utils.cc: Don't include unneeded termio headers.\n\n2002-09-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* BaseSLList.cc, BaseSLList.h, Cell.cc, Cell.h, DLList.cc,\n\tDLList.h, Map.cc, Map.h, OPERATORS/op-b-b.cc,\n\tOPERATORS/op-bm-b.cc, OPERATORS/op-bm-bm.cc, OPERATORS/op-cell.cc,\n\tOPERATORS/op-chm.cc, OPERATORS/op-cm-cm.cc, OPERATORS/op-cm-cs.cc,\n\tOPERATORS/op-cm-m.cc, OPERATORS/op-cm-s.cc, OPERATORS/op-cs-cm.cc,\n\tOPERATORS/op-cs-cs.cc, OPERATORS/op-cs-m.cc, OPERATORS/op-cs-s.cc,\n\tOPERATORS/op-fil-b.cc, OPERATORS/op-fil-bm.cc,\n\tOPERATORS/op-fil-cm.cc, OPERATORS/op-fil-cs.cc,\n\tOPERATORS/op-fil-lis.cc, OPERATORS/op-fil-m.cc,\n\tOPERATORS/op-fil-rec.cc, OPERATORS/op-fil-s.cc,\n\tOPERATORS/op-fil-str.cc, OPERATORS/op-list.cc,\n\tOPERATORS/op-m-cm.cc, OPERATORS/op-m-cs.cc, OPERATORS/op-m-m.cc,\n\tOPERATORS/op-m-s.cc, OPERATORS/op-range.cc, OPERATORS/op-s-cm.cc,\n\tOPERATORS/op-s-cs.cc, OPERATORS/op-s-m.cc, OPERATORS/op-s-s.cc,\n\tOPERATORS/op-str-str.cc, SLList.cc, SLList.h, SLStack.cc,\n\tSLStack.h, Stack.cc, Stack.h, c-file-ptr-stream.cc,\n\tc-file-ptr-stream.h, comment-list.cc, comment-list.h, oct-map.cc,\n\toct-map.h, oct-obj.cc, oct-obj.h, ov-base-mat.cc, ov-base-mat.h,\n\tov-base-nd-array.cc, ov-base-nd-array.h, ov-base-scalar.cc,\n\tov-base-scalar.h, ov-base.cc, ov-base.h, ov-bool-mat.cc,\n\tov-bool-mat.h, ov-bool.cc, ov-bool.h, ov-builtin.cc, ov-builtin.h,\n\tov-cell.cc, ov-cell.h, ov-ch-mat.cc, ov-ch-mat.h, ov-colon.cc,\n\tov-complex.cc, ov-complex.h, ov-cs-list.cc ov-cs-list.h,\n\tov-cx-mat.cc, ov-cx-mat.h, ov-dld-fcn.cc, ov-dld-fcn.h, ov-fcn.cc,\n\tov-fcn.h, ov-file.cc, ov-file.h, ov-list.cc, ov-list.h,\n\tov-mapper.cc, ov-mapper.h, ov-range.cc, ov-range.h, ov-re-mat.cc,\n\tov-re-mat.h, ov-re-nd-array.cc, ov-re-nd-array.h, ov-scalar.cc,\n\tov-scalar.h, ov-str-mat.cc, ov-str-mat.h, ov-struct.cc,\n\tov-struct.h, ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc,\n\tov-usr-fcn.h, ov-va-args.cc, ov.cc, ov.h, procstream.cc,\n\tprocstream.h, pt-arg-list.cc, pt-arg-list.h, pt-assign.cc,\n\tpt-assign.h, pt-binop.cc, pt-binop.h, pt-bp.cc, pt-bp.h,\n\tpt-cell.cc, pt-cell.h, pt-check.cc, pt-check.h, pt-cmd.cc,\n\tpt-cmd.h, pt-colon.cc, pt-colon.h, pt-const.cc, pt-const.h,\n\tpt-decl.cc, pt-decl.h, pt-except.cc, pt-except.h, pt-exp.cc,\n\tpt-exp.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-jump.cc,\n\tpt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.cc, pt-mat.h, pt-misc.cc,\n\tpt-misc.h, pt-plot.cc, pt-plot.h, pt-pr-code.cc, pt-pr-code.h,\n\tpt-select.cc, pt-select.h, pt-stmt.cc, pt-stmt.h, pt-unop.cc,\n\tpt-unop.h, pt.cc, pt.h, symtab.cc, symtab.h, token.cc, token.h,\n\tunwind-prot.cc, unwind-prot.h:\n\tUse USE_PRAGMA_INTERFACE_IMPLEMENTATION instead of __GNUG__ to\n\tdecide whether to use the interface/implementation pragmas.\n\n2002-09-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc: Undo previous change.\n\n\t* ov-struct.cc (octave_struct::subsasgn): Ensure that indexed\n\tobject is not shared before calling subsasgn.\n\n2002-09-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc: Use % instead of # as comment character in ascii\n\tdata files.\n\n2002-08-17  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* c-file-ptr-stream.h (c_file_ptr_buf::c_file_ptr_buf): Add Intel\n\tC++ runtime support.\n\n\t* Cell.h, gripes.cc, ov-base-scalar.cc, ov-colon.cc, ov-fcn.cc,\n\tov-file.cc, ov-mapper.h, ov-va-args.cc, token.cc, xpow.cc,\n\tOPERATORS/op-b-b.cc, OPERATORS/op-bm-b.cc, OPERATORS/op-bm-bm.cc,\n\tOPERATORS/op-cell.cc, OPERATORS/op-chm.cc, OPERATORS/op-cm-cm.cc,\n\tOPERATORS/op-cm-cs.cc, OPERATORS/op-cm-m.cc, OPERATORS/op-cm-s.cc,\n\tOPERATORS/op-cs-cm.cc, OPERATORS/op-cs-cs.cc, OPERATORS/op-cs-m.cc,\n\tOPERATORS/op-cs-s.cc, OPERATORS/op-fil-b.cc, OPERATORS/op-fil-bm.cc,\n\tOPERATORS/op-fil-cm.cc, OPERATORS/op-fil-cs.cc,\n\tOPERATORS/op-fil-lis.cc, OPERATORS/op-fil-m.cc,\n\tOPERATORS/op-fil-rec.cc, OPERATORS/op-fil-s.cc,\n\tOPERATORS/op-fil-str.cc, OPERATORS/op-list.cc, OPERATORS/op-m-cm.cc,\n\tOPERATORS/op-m-cs.cc, OPERATORS/op-m-m.cc, OPERATORS/op-m-s.cc,\n\tOPERATORS/op-range.cc, OPERATORS/op-s-cm.cc, OPERATORS/op-s-cs.cc,\n\tOPERATORS/op-s-m.cc, OPERATORS/op-s-s.cc, OPERATORS/op-str-str.cc,\n\tTEMPLATE-INST/Array-sym.cc, TEMPLATE-INST/Array-tc.cc,\n\tTEMPLATE-INST/Map-tc.cc, TEMPLATE-INST/SLList-expr.cc,\n\tTEMPLATE-INST/SLList-tc.cc, TEMPLATE-INST/SLList-tm.cc,\n\tTEMPLATE-INST/SLStack-sym.cc: Make the implementation of\n\toctave_value_list visibile for template instantiation.\n\n2002-08-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/dasrt.cc: Include <iostream> not <iostream.h>.\n\n\t* pager.h: Include lo-sstream.h and use macros instead of using\n\tstrstreambuf class directly.\n\n\t* load-save.cc (read_mat_ascii_data): Handle istrstream here too.\n\n\t* procstream.h (procstream::procstream): Also accept std::string arg.\n\t(iprocstream::iprocstream, iprocstream::open): Likewise.\n\t(oprocstream::oprocstream, oprocstream::open): Likewise.\n\t(procstreambase::procstreambase, procstreambase::open): Likewise.\n\n\t* pt-plot.cc (gnuplot_terminal_type): Now std::string&, not char*.\n\t(send_to_plot_stream): Likewise, for cmd arg.\n\n\t* pt-plot.h, pt-plot.cc: Include lo-sstream.h and use macros\n\tinstead of using strstream classes directly.\n\t* oct-strstrm.h: Likewise.\n\t* error.h, error.cc: Likewise.\n\t* oct-stream.h, oct-stream.cc: Likewise.\n\t* lex.l: Likewise.\n\t* toplev.cc: Likewise.\n\t* utils.cc: Likewise.\n\t* pt.cc: Likewise.\n\t* pr-output.cc: Likewise.\n\t* ov-list.cc: Likewise.\n\t* ov-cs-list.cc: Likewise.\n\t* ov-cell.cc: Likewise.\n\t* load-save.cc: Likewise.\n\t* help.cc: Likewise.\n\t* dirfns.cc: Likewise.\n\n2002-08-15  Paul Kienzle  <pkienzle@jazz.ncnr.nist.gov>\n\n\t* input.cc (octave_read): Do a better job of buffering.\n\n2002-08-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DLD_DEF_FILES): New macro.\n\t(DEF_5): Delete.\n\t(DEF_4): Now only includes $(SOURCES).\n\t(DEF_FILES): Append $(DLD_DEF_FILES) here.\n\t(stamp-oct-links): Pass $(DLD_DEF_FILES) to mk-oct-links instead\n\tof a list of source files.\n\t* mk-oct-links: Work on .df files instead of .cc files.\n\n\t* parse.y (case_list): Allow it to be empty.\n\n\t* ov.cc, ov.h (octave_value::int_vector_value): New function.\n\n2002-08-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (OCTAVE_LIBS): Only include $(LIBKPATHSEA) if not\n\tusing shared libraries.\n\n\t* ov.cc (octave_value::octave_value (const octave_value_list&, bool)):\n\tDon't forget to assign rep.\n\n2002-08-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l: Warn for various Matlab-incompatibilities.\n\tNo longer accept <> for NOTEQ.\n\t(gripe_matlab_incompatible): New function.\n\t(maybe_gripe_matlab_incompatible_comment): Likewise.\n\t(gripe_matlab_incompatible_continuation): Likewise.\n\t(gripe_matlab_incompatible_operator): Likewise.\n\t(warn_matlab_incompatible): New function.\n\t(Vwarn_matlab_incompatible): New static variable.\n\t(symbols_of_lex): Add a DEFVAR for it.\n\n\n\t* file-io.cc (fopen_mode_to_ios_mode): Default value is std::ios::in.\n\tReturn std::ios::openmode instead of int.\n\n2002-08-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/dasrt.cc (DASRT_ABORT1, DASRT_ABORT2):\n\t\"##\" pastes tokens, not strings.\n\n\t* DLD-FUNCTIONS/odessa.cc: Add std:: qualifiers as needed.\n\n2002-08-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (Fisglobal): Rename from Fis_global.\n\t* file-io.cc (Fisstream): Rename from Fis_stream.\n\t* data.cc (Fisbool): Rename from Fis_bool.\n\t(Fiscomplex): Rename from Fis_complex.\n\t(Fislist): Rename from Fis_list.\n\t(Fismatrix): Rename from Fis_matrix.\n\t(Fisstruct): Rename from Fis_struct.\n\n\t* parse.y (switch_case): Make list of command optional.\n\n2002-08-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (pr_max_internal): Use octave_is_NaN_or_NA instead\n\tof xisnan.\n\t(pr_min_internal): Likewise.\n\t(output_max_field_width): Likewise.\n\t(output_precision): Likewise.\n\t(pr_any_float): Handle NA.\n\t* mappers.cc (Fisna, F_is_nan_or_na): New functions.\n\t* data.cc (symbols_of_data): New constant, NA.\n\n2002-08-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-binop.h (tree_binary_expression::is_binary_expression):\n\tNew function, return true.\n\t(tree_boolean_expression::is_boolean_expression): New function,\n\treturn true.\n\t* pt-exp.h (tree_expression::is_binary_expression): New function.\n\t(tree_expression::is_boolean_expression): Likewise.\n\t* parse.y (EXPR_OR_OR): Now lower precedence than EXPR_AND_AND.\n\t(EXPR_OR): Now lower precedence than EXPR_AND.\n\t(make_boolean_op): Maybe warn about change in precedence.\n\t(make_binary_op): Likewise.\n\t(Vwarn_precedence_change): New static variable.\n\t(warn_precedence_change): New function.\n\t(Vwarn_precedence_change): New DEFVAR.\n\n2002-08-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (ANY_ALL): Improve arg checks.\n\n2002-08-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_value::assign_op): New enum values, op_pow_eq and\n\top_el_pow_eq.\n\t* ov.cc (octave_value::assign_op_as_string): Handle them here.\n\t(ocatave_value::op_eq_to_binary_op): And here.\n\t* parse.y (POW_EQ, EPOW_EQ): New tokens.\n\t(assign_expr): Handle them here too.\n\t(make_assign_op): And here.\n\n\t* lex.l: Recognize {POW}= and {EPOW}=.\n\n2002-08-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-base-scalar.h (octave_base_scalar::all): New int arg.\n\t(octave_base_scalar::any): Likewise.\n\t* ov-range.h (octave_range::all): Likewise.\n\t(octave_range::any): Likewise.\n\n\t* Makefile.in (doc-files): Use mv, not move-if-change here.\n\n\t* variables.cc (symbol_exist): New function.\n\t(Fexist): Use it.  Handle optional type arg.  Make return codes\n\tmore compatible with Matlab.\n\n\t* data.cc (ANY_ALL): New macro.\n\t(Fany, Fall): Replace guts with ANY_ALL.\n\n2002-08-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (Fall, Fany): Handle optional DIM argument.\n\n\t* ov.h (octave_value::any): New arg, dim.\n\t(octave_value::all): Likewise.\n\t* ov-base.h (octave_base_value::any): Likewise.\n\t(octave_base_value::all): Likewise.\n\t* ov-base-mat.h (octave_base_matrix::any): Likewise.\n\t(octave_base_matrix::all): Likewise.\n\n\t* Makefile.in: Use $@-t instead of $@.t.\n\t(doc-files): Use move-if-change when creating doc-files.\n\n\t* error.cc (warning): Don't print warning backtrace at top level.\n\n\t* ov-cell.cc (octave_cell::print_raw): Print empty dimensions too.\n\t(octave_cell::print_name_tag): Don't print new line if cell is empty.\n\n\t* octave.cc (intern_argv): Don't install __argv__.\n\n\t* defun-int.h (UNDERSCORIFY): Delete.\n\t(DEFCONST_INTERNAL): Don't install double underscore versions of\n\tconstants since they aren't really needed.\n\t(DEFCONSTX_INTERNAL): Likewise.\n\n2002-07-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* symtab.cc (symbol_table::clear (void)): Clear all records.\n\t(symbol_table::clear (const std::string&)): Delete second arg.\n\tClear any symbol that matches, regardless of type.\n\n\t* symtab.h (symbol_table::variable_name_list): New function.\n\t(symbol_table::global_variable_name_list): Likewise.\n\t(symbol_table::user_function_name_list): Likewise.\n\n\t* symtab.h, symtab.cc (symbol_table::clear_variables): New function.\n\t(symbol_table::clear_functions): Likewise.\n\t(symbol_table::clear_globals): Likewise.\n\t(symbol_table::clear_variable): New function.\n\t(symbol_table::clear_function): Likewise.\n\t(symbol_table::clear_global): Likewise.\n\t(symbol_table::clear_variable_pattern): New function.\n\t(symbol_table::clear_function_pattern): Likewise.\n\t(symbol_table::clear_global_pattern): Likewise.\n\n\t* variables.cc (name_matches_any_pattern): Rename from\n\tvar_matches_any_pattern.\n\t(is_local_variable): New static inline function.\n\t(maybe_warn_exclusive): Likewise.\n\t(do_clear_all): Likewise.\n\t(do_clear_functions): Likewise.\n\t(do_clear_globals): Likewise.\n\t(do_clear_variables): Likewise.\n\t(do_clear_function): Likewise.\n\t(do_clear_global): Likewise.\n\t(do_clear_variable): Likewise.\n\t(do_clear_symbol): Likewise.\n\t(do_clear_function_pattern): Likewise.\n\t(do_clear_global_pattern): Likewise.\n\t(do_clear_variable_pattern): Likewise.\n\t(do_clear_symbol_pattern): Likewise.\n\t(do_clear_functions): Likewise.\n\t(do_clear_functions): Likewise.\n\t(do_clear_globals): Likewise.\n\t(do_clear_variables): Likewise.\n\t(do_clear_symbols): Likewise.\n\t(do_matlab_compatible_clear): Likewise.\n\t(CLEAR_OPTION_ERROR): New macro.\n\t(Fclear): Rewrite for Matlab compatibility and to cope with new\n\tsymbol table semantics.\n\n2002-07-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* symtab.cc (symbol_table::clear): Simply clear everything.\n\t(symbol_table::clear_functions, symbol_table::clear_globals,\n\tsymbol_table::clear_all): New functions.\n\n\t* symtab.h (symbol_record::symbol_def::next_elem): Delete.\n\t(symbol_record::symbol_def::symbol_def): Delete intializer.\n\n\t* symtab.h, symtab.cc (symbol_record::push_def): Delete.\n\t(symbol_record::remove_top_def): Delete.\n\t(symbol_record::replace_all_defs): Delete.\n\t(symbol_record::hides_fcn): Delete.\n\t(symbol_record::hides_builtin): Delete.\n\n\t* symtab.h (symbol_table::~symbol_table): Call clear before\n\tdeleting the table.\n\n\t* variables.cc (initialize_symbol_tables): Create fbi_sym_tab too.\n\t(Fexist): Look in fbi_sym_tab, not global_sym_tab.\n\n\t* parse.y (function_symtab): Rename from global_symtab.\n\tSet curr_sym_tab to fbi_sym_tab, not global_sym_tab.\n\tChange all uses of global_symtab to be function_symtab instead.\n\t(frob_function): Rename and look for function name in fbi_sym_tab,\n\tnot global_sym_tab.\n\t(parse_fcn_file): Clear function name from fbi_sym_tab, not\n\tglobal_sym_tab.\n\n\t* load-save.cc (save_vars): Look for built-in vars in fbi_sym_tab.\n\t* symtab.cc (symbol_record::link_to_builtin_variable): Likewise.\n\t* variables.cc (is_builtin_variable): Likewise.\n\t(bind_ans): Likewise.\n\t(bind_builtin_constant): Likewise.\n\t(bind_builtin_variable): Likewise.\n\t(builtin_string_variable): Likewise.\n\t(builtin_real_scalar_variable): Likewise.\n\t(builtin_any_variable): Likewise.\n\t(is_text_function_name): Likewise, for functions.\n\t(force_link_to_function): Likewise.\n\t(is_builtin_function_name): Likewise.\n\t(is_mapper_function_name): Likewise.\n\t(is_valid_function): Likewise.\n\t(Fclear): Likewise.\n\t(F__print_symtab_info__): Likewise.\n\t* defun.cc (print_usage): Likewise.\n\t(install_builtin_mapper): Likewise.\n\t(install_builtin_function): Likewise.\n\t(install_dld_function): Likewise.\n\t(Falias): Likewise.\n\t* dynamic-ld.cc (clear_function): Likewise.\n\t* variables.cc (do_who): Likewise, for built-ins and functions.\n\t(link_to_builtin_or_function): Likewise.\n\t* help.cc (LIST_SYMBOLS): Likewise.\n\t(make_name_list): Handle fbi_sym_tab too.\n\n\t* variables.cc (fbi_sym_tab): New symbol table.\n\t* variables.h (fbi_sym_tab): Provide decl.\n\n2002-07-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* symtab.h (symbol_record::alias): Delete unused arg force.\n\tChange all callers.\n\n\t* variables.cc (link_to_global_variable): Give local variable\n\tglobal value.\n\n\t* pt-id.cc (tree_identifier::link_to_global): Warn about global\n\tvariables that have been defined before being declared global.\n\tfor a global variable to be used before it is declared global.\n\t* pt-decl.cc (tree_global_command::do_init): Handle possible error\n\tfrom tree_identifier::link_to_global.\n\n2002-07-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.cc (silent_functions, Vsilent_functions): Move here.\n\t(octave_value::print_with_name): Don't print anything if we are\n\tevaluating a function and Vsilent_functions is true.\n\n\t* pt-stmt.cc: From here.\n\t(symbols_of_pt_stmt): Delete.\n\t(tree_statement_list::eval): Don't bother with Vsilent_functions here.\n\n2002-07-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (OPT_HANDLERS): New targets.\n\t(doc-files): New target.\n\t(gendoc.cc): Depend on doc-files, not $(DOC_FILES).\n\n\t* DLD-FUNCTIONS/daspk.cc, DLD-FUNCTIONS/dasrt.cc,\n\tDLD-FUNCTIONS/dassl.cc, DLD-FUNCTIONS/fsolve.cc,\n\tDLD-FUNCTIONS/lsode.cc, DLD-FUNCTIONS/odessa.cc\n\tDLD-FUNCTIONS/quad.cc: Replace option handling code with include\n\tdirective.\n\n2002-07-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-loop.cc (tree_simple_for_command::eval): Once we know the RHS\n\tis a matrix type check for real_type, not real_matrix.\n\n2002-07-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/quad.cc (quad): Cope with changes to Quad constructors.\n\n2002-07-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/daspk.cc (Fdaspk): Also return istate and error\n\tmessage.  Only generate error if user is not at least requesting\n\tthe istate output.\n\t* DLD-FUNCTIONS/dasrt.cc (Fdasrt): Likewise.\n\t* DLD-FUNCTIONS/dassl.cc (Fdassl): Likewise.\n\t* DLD-FUNCTIONS/lsode.cc (Fodessa): Likewise.\n\n2002-07-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/dasrt.cc (Fdasrt): No need to find ng here.\n\t(dasrt_user_j): New function.\n\t(Fdasrt): Handle Jacobian function.\n\n\t* DLD-FUNCTIONS/dassl.cc (dassl_user_jacobian): New function.\n\t(Fdassl): Handle Jacobian function.\n\n\t* DLD-FUNCTIONS/dasrt.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n2002-07-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (@): Handle new token.\n\t* parse.y (constant): Accept function handle syntax.\n\t(make_constant): Create function handles here.\n\n2002-07-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defun.cc (check_version): Improve error message.\n\t* error.cc (warning): Only print backtrace once per warning series.\n\tPrint backtrace before warning messages.\n\n2002-07-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (maybe_unput_comma): Also handle '{' as an indexing op.\n\n\t* DLD-FUNCTIONS/odessa.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n2002-07-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-assign.cc (tree_multi_assignment::rvalue): Call\n\tlhs->nargout_count, not lhs->length.\n\n\t* pt-arg-list.cc (tree_argument_list::convert_to_const_vector):\n\tHandle cs-list objects here.\n\t(tree_argument_list::nargout_count): New function.\n\t* pt-arg-list.h: Provide decl.\n\n\t* ov-cs-list.h, ov-cs-list.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* ov.cc: Include ov-cs-list.h.\n\tNew arg, is_cs_list for constructor taking octave_value_list arg.\n\t(install_types): Register ov_cs_list.\n\t* ov.h (octave_value::is_cs_list): New function.\n\t* ov-base.h (octave_base_value::is_cs_list): Likewise.\n\t* ov-cell.cc (octave_cell::subsref): Return cs-list for \"{\" indexing.\n\n2002-07-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-mat.cc (Vempty_list_elements_ok): Default value is now 1.\n\t* octave.cc (maximum_braindamage): No longer need to set value here.\n\n\t* ov-usr-fcn.cc (Fva_arg, Fva_start, Fvr_val): Warn that these\n\tfunctions are deprecated.\n\t* lex.l (EL): Warn that `...' is deprecated.\n\t* ov-usr-fcn.cc (octave_user_function::varargout_to_vr_val,\n\toctave_user_function::has_varargout): New functions.\n\t(Fvr_val): Ensure varargout is not defined.\n\t(octave_user_function::do_multi_index_op): Copy values from\n\tvarargout here.\n\n2002-07-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-usr-fcn.h (octave_user_function::varargin_sr): New data member.\n\t* ov-usr-fcn.cc (octave_user_function::octave_user_function):\n\tInitialize it.\n\t(bind_automatic_vars): Handle varargin.  Change\tall callers.\n\n\t* octave.gperf: Handle varargin and varargout as keywords.\n\t* lex.l (is_keyword): Likewise.\n\t(IDENT): Move all actions into handle_identifier.\n\t(handle_identifier): Now takes no args.\n\n\t* lex.l (EL): Return VARARGIN or VARARGOUT, not ELLIPSIS.\n\t* parse.y (param_list): Use VARARGIN instead of ELLIPSIS.\n\t(return_list): Use VARARGOUT instead of ELLIPSIS.\n\n\t* data.cc (make_diag const octave_value&, const octave_value&):\n\tAllow first arg to be 1x0 or 0x1.\n\n2002-07-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.cc (loadpath): Comment out previous change.\n\n\t* DLD-FUNCTIONS/fsolve.cc (Ffsolve): Return message too.  Only\n\tgenerate error if user is not at least requesting the info output.\n\n\t* DLD-FUNCTIONS/lsode.cc (Flsode): Fix typos in setting return value.\n\n2002-07-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (printf_value_cache::double_value): If the current\n\telement is empty and there are no more elements in the value list,\n\tset curr_state to conversion_error.\n\n\t* input.cc (initialize_command_input): Include (, ), {, and } as\n\tword break characters.\n\n\t* variables.cc (looks_like_struct): Don't evaluate text if it is a\n\tfunction.  From Ben Sapp <bsapp@lanl.gov>.\n\n\t* symtab.h (symbol_record::is_function): Also return true if\n\tsymbol is a text function or a mapper function.\n\n2002-06-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.cc (loadpath): Warn if loadpath doesn't contain\n\tleading, trailing, or doubled colon.\n\n\t* pt-decl.cc (tree_static_command::eval, tree_global_command::eval):\n\tCall error for any non-zero value of error_state.\n\t* pt-select.cc (tree_if_command::eval): Likewise.\n\t* pt-loop.cc (tree_while_command::eval_error): Don't check error_state.\n\t(tree_do_until_command::eval_error): Likewise.\n\t(tree_simple_for_command::eval_error): Likewise.\n\t(tree_complex_for_command::eval_error): Likewise.\n\t* pt-assign.cc (tree_multi_assignment::eval_error): Likewise.\n\t(tree_simple_assignment::eval_error): Likewise.\n\t* pt-idx.cc (tree_index_expression::eval_error): Likewise.\n\t* pt-colon.cc (tree_colon_expression::eval_error): Likewise.\n\t(tree_colon_expression::rvalue): Delete rendundant error_state check.\n\n2002-06-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-mapper.cc (MAPPER_LOOP, MAPPER_LOOP_1, MAPPER_LOOP_2): New\tmacros.\n\t(octave_mapper::apply): Use them to inline the mapper loops.\n\n\t* pt-unop.cc (tree_prefix_expression::rvalue): Ensure that the\n\toperand is defined for op_incr and op_decr.\n\t(tree_postfix_expression::rvalue): Likewise.\n\tFrom Ben Sapp <bsapp@lanl.gov>.\n\n2002-06-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-mapper.cc (octave_mapper::apply): Exit loops on error.\n\n2002-06-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-struct.cc (octave_struct::print_raw): Print field names with\n\tdata types if Vstruct_levels_to_print is 0.\n\t(octave_struct::print_name_tag): Don't emit newline if\n\tVstruct_levels_to_print is negative.\n\t* ov.cc (struct_levels_to_print): Allow negative values too.\n\n2002-05-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/lsode.cc (Flsode): Also return istate and error\n\tmessage.  Only generate error if user is not at least requesting\n\tthe istate output.\n\n\t* load-save.cc (hdf5_import_multidim, hdf5_check_attr,\n\thdf5_callback_data, hdf5_read_next_data, read_hdf5_data,\n\tadd_hdf5_data): Use 0, not NULL in calls to HDF routines.\n\n\t* oct-procbuf.cc (octave_procbuf::open): Use NULL, not 0 as last\n\targ in call to execl.\n\n\t* debug.cc (get_user_function): Initialise dbg_fcn to 0, not NULL.\n\n2002-05-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/lsode.cc (LSODE_options::da_set_opt_mf,\n\tLSODE_options::da_get_opt_mf): New typedefs.\n\t(LSODE_OPTIONS::da_set_fcn, LSODE_OPTIONS::da_get_fcn): New fields.\n\t(lsode_option_table): Fill them in.\n\t(set_lsode_option (const Array<double>&)): New function.\n\t(print_lsode_option_list): Handle vector options.\n\t(show_lsode_option_list): Likewise.\n\t(Flsode_options): Likewise.\n\n\t* DLD-FUNCTIONS/lsode.cc (LSODE_options::s_set_opt_mf,\n\tLSODE_options::s_get_opt_mf): New typedefs.\n\t(LSODE_OPTIONS::s_set_fcn, LSODE_OPTIONS::s_get_fcn): New fields.\n\t(lsode_option_table): Fill them in.\n\t(set_lsode_option (const std::string&)): New function.\n\t(print_lsode_option_list): Handle string options.\n\t(show_lsode_option_list): Likewise.\n\t(Flsode_options): Likewise.\n\n2002-05-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* c-file-ptr-stream.h (c_file_ptr_buf::fclose): New function.\n\t(c_file_ptr_buf::c_file_ptr_buf): Use it as default argument\n\tinstead of extern \"C\" fclose function.\n\t(i_c_file_ptr_stream::i_c_file_ptr_stream): Likewise.\n\t(o_c_file_ptr_stream::o_c_file_ptr_stream): Likewise.\n\t* oct-stdstrm.h (octave_istdiostream::octave_istdiostream): Likewise.\n\t(octave_istdiostream::create): Likewise.\n\t* oct-stdstrm.h (octave_ostdiostream::octave_ostdiostream): Likewise.\n\t(octave_ostdiostream::create): Likewise.\n\n\t* oct-prcstrm.cc (cxx_pclose): New static function.\n\t(octave_iprocstream::octave_iprocstream): Pass it to\n\toctave_istdiostream constructor instead of extern \"C\" pclose function.\n\t(octave_oprocstream::octave_oprocstream): Pass it to\n\toctave_ostdiostream constructor instead of extern \"C\" pclose function.\n\n\t* debug.cc (Fdbtype): Use C++ strings, not C strings.\n\n2002-05-22  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* debug.cc: Include cstdlib instead of stdlib.h. Include cstring.\n\t(dbtype): Use strchr instead of index.\n\t* TEMPLATE-INST/Array-tc.cc (Array<octave_value>::resize_fill_value):\n\tFix template specialization syntax.\n\n2002-05-17  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* c-file-ptr-stream.h (OCTAVE_STD_FILEBUF): New macro to handle\n\tvarious forms of extensions to std::filebuf.\n\t(c_file_ptr_buf::c_file_ptr_buf): Use.\n\t* pt-idx.cc (tree_index_expression::tree_index_expression): Remove\n\tdefault arguments are from definition.\n\t* symtab.cc (SYMBOL_DEF::print_info): Add std::.\n\t(symbol_record::print_info): Likewise.\n\t(symbol_table::print_info): Likewise.\n\n2002-05-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-map.cc (Octave_map::assign): Resize RHS if it is shorter\n\tthan existing struct array.\n\n\t* ov-cell.cc (octave_cell::subsasgn): If an error has occurred,\n\tskip final assignment step.\n\t* ov-list.cc (octave_list::subsasgn): Likewise.\n\t* oct-lvalue.cc (octave_lvalue::assign): Add parens to clarify intent.\n\t(octave_lvalue::do_unary_op): Likewise.\n\n\t* parse.y (function_end): Also accept end of input as end of\n\tfunction if input is coming from an eval string.\n\n\t* pr-output.cc (pr_any_float): Don't convert -0 to 0.\n\n2002-05-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (generate_completion): If it looks like we are\n\tcompleting a struct, set completion append char to '\\0'.\n\n\t* variables.cc (generate_struct_completions): Temporarily set\n\twarnings off here.\n\n\t* error.cc (warning): Don't do anything if Vdebug_option == \"off\".\n\tOnly print backtrace if Vdebug_option == \"backtrace\".\n\t(handle_message): Now returns a string containing the text of the\n\tformatted message.  Change all callers.\n\t(Fwarning): Now a text-style function.  Handle Matlab-compatible\n\twarning options.\n\t(Flasterr, Flastwarn, set_warning_option): New functions.\n\t(Vlast_error_message, Vlast_warning_message, Vwarning_frequency,\n\tVwarning_option): New static variables.\n\t(vwarning): Set Vlast_warning_message here too.\n\t(verror): Set Vlast_error_message here too.\n\n2002-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_value::get_count): Now const.\n\n\t* ov.h, ov.cc (octave_value::do_non_const_unary_op,\n\toctave_value::assign): Idx is now a list of octave_value_list\n\tobjects.\n\n\t* ov-base.cc, ov-base.h\t(octave_base_value::do_struct_elt_index_op,\n\toctave_base_value::struct_elt_ref): Delete.\n\t* ov-struct.cc, ov-struct.h (octave_sruct::do_struct_elt_index_op,\n\toctave_struct::struct_elt_ref): Delete.\n\t* ov.cc, ov.h (octave_value::do_struct_elt_index_op,\n\toctave_value::struct_elt_ref, octave_value::assign_struct_elt,\n\toctave_value::convert_and_assign, octave_value::try_assignment,\n\toctave_value::try_assignment_with_conversion,\n\toctave_value::simple_assign): Delete.\n\n\t* parse.y (make_index_expression): Type is now a single\n\tcharacter.  Change all callers.  If expr is already an index\n\texpression, append index to it.\n\t(make_indirect_ref): Likewise.\n\n\t* pt-pr-code.cc (octave_print_internal (std::ostream&, const\n\tCell&, bool, int)): Now just a dummy function, panic if called.\n\n\t* pt-idx.cc (tree_index_expression::make_arg_struct): New function.\n\t(tree_index_expression::type): Delete enum, rename from itype, now\n\ta string.\n\t(tree_index_expression::arg_nm): Now a list of string_vector objects.\n\t(tree_index_expression::idx): Now a list of tree_argument_list*\n\tobjects.\n\t(tree_index_expression::is_index_expression): Always return true.\n\t(tree_index_expression::apend, make_value_list, make_subs_cell):\n\tNew functions.\n\n\t* pt-pr-code.cc (visit_index_expression): Handle new definition of\n\ttree_index_expression object.\n\t* pt-check.cc (visit_index_expression): Likewise.\n\t* pt-bp.cc (visit_index_expression): Likewise.\n\n\t* ov-usr-fcn.h (octave_user_function::restore_args_passed):\n\tClear args_passed even if nothing was saved.\n\n\t* ov-base.cc (octave_base_value::subsasgn,\n\toctave_base_value::map_keys, octave_base_value::print_info):\n\tNew functions.\n\n\t* ov.h, ov.cc (octave_value::map_keys, octave_value::print_info,\n\toctave_value::subsref, octave_value::subsasgn,\n\toctave_value::numeric_assign, octave_value::next_subsref):\n\tNew functions.\n\t(octave_value::empty_conv): New static function.\n\t(octave_value (octave_value *, int)): New arg, count.\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::subsref,\n\toctave_base_matrix<MT>::subsasgn): New functions.\n\t* ov-base-mat.h: Provide decls.\n\n\t* ov-builtin.cc (octave_builtin::subsref): New function.\n\t* ov-builtin.h: Provide decl.\n\n\t* ov-range.cc (octave_range::subsref): New function.\n\t* ov-range.h: Provide decl.\n\n\t* ov-cell.cc (octave_cell::subsref, octave_cell::subsasgn,\n\toctave_cell::list_value, octave_cell::print,\n\toctave_cell::print_raw, octave_cell::print_name_tag): New functions.\n\t* ov-cell.h: Provide decls.\n\n\t* ov-struct.cc (octave_struct::dotref, octave_struct::subsref,\n\toctave_struct::subsasgn, gripe_invalid_index,\n\tgripe_invalid_index_for_assignment, grip_invalid_index_type,\n\tgripe_failed_assignment): New functions.\n\t(octave_struct::numeric_conv): New static function.\n\t* ov-struct.h: Provide decls.\n\t(octave_struct::is_constant): Return true.\n\t(octave_struct::map_keys): New function.\n\n\t* ov-list.cc (octave_list::subsref, octave_list::subsasgn):\n\tNew functions.\n\t* ov-list.h: Provide decls.\n\n\t* ov-usr-fcn.cc (octave_user_function::subsref,\n\toctave_user_function::print_symtab_info): New functions.\n\t* ov-usr-fcn.h: Provide decl.\n\n\t* ov-mapper.cc (octave_mapper::subsref): New function.\n\t* ov-mapper.h: Provide decl.\n\n\t* ov-base.cc (octave_base_value::subsref,\n\toctave_base_value::subsasgn): New functions.\n\t* ov-base.h: Provide decls.\n\n\t* ov-base.cc (octave_base_value::do_index_op): New arg, resize_ok.\n\t* ov-base-mat.cc (octave_base_matrix<MT>::do_index_op): Likewise.\n\t* ov-base-nd-array.cc (octave_base_nd_array<AT>::do_index_op): Ditto.\n\t* ov-bool-mat.cc (octave_bool::do_index_op): Ditto.\n\t* ov-str-mat.cc (octave_char_matrix_str::do_index_op): Ditto.\n\t* ov-range.cc (octave_range::do_index_op): Ditto.\n\t* ov-list.cc (octave_list::do_index_op): Ditto.\n\t* ov.cc (octave_value::do_index_op): Ditto.\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::print_info): New function.\n\n\t* ov-base-mat.h (octave_base_matrix<MT>::empty_clone): New function.\n\t* ov-base-nd-array.h (octave_base_nd_array<AT>::empty_clone): Ditto.\n\t* ov-base.h (octave_base_value::empty_clone): Ditto.\n\t* ov-bool-mat.h (octave_bool::empty_clone): Ditto.\n\t* ov-ch-mat.h (octave_char_matrix::empty_clone): Likewise.\n\t* ov-colon.h (octave_magic_colon::empty_clone): Likewise.\n\t* ov-complex.h (octave_complex::empty_clone): Likewise.\n\t* ov-cx-mat.h (octave_complex_matrix::empty_clone): Likewise.\n\t* ov-fcn.cc (octave_function::empty_clone): Likewise.\n\t* ov-file.h (octave_file::empty_clone): Likewise.\n\t* ov-range.h (octave_range::empty_clone): Likewise.\n\t* ov-list.h (octave_list::empty_clone): Likewise.\n\t* ov-re-mat.h (octave_matrix::empty_clone): Likewise.\n\t* ov-re-nd-array.h (octave_double_nd_array::empty_clone): Likewise.\n\t* ov-str-mat.h (octave_char_matrix_str::empty_clone): Likewise.\n\t* ov-struct.h (octave_struct::empty_clone): Likewise.\n\t* ov-va_args.h (octave_all_va_args::empty_clone): Likewise.\n\t* ov.h (octave_value::empty_clone): Likewise.\n\n\t* ov-base-mat.h (octave_base_matrix<MT>::clone): Now const.\n\t* ov-base-nd-array.h (octave_base_nd_array<AT>::clone): Likewise.\n\t* ov-base.h (octave_base_value::clone): Likewise.\n\t* ov-bool-mat.h (octave_bool::clone): Likewise.\n\t* ov-ch-mat.h (octave_char_matrix::clone): Likewise.\n\t* ov-colon.h (octave_magic_colon::clone): Likewise.\n\t* ov-complex.h (octave_complex::clone): Likewise.\n\t* ov-cx-mat.h (octave_complex_matrix::clone): Likewise.\n\t* ov-fcn.h (octave_function::clone): Likewise.\n\t* ov-file.h (octave_file::clone): Likewise.\n\t* ov-range.h (octave_range::clone): Likewise.\n\t* ov-list.h (octave_list::clone): Likewise.\n\t* ov-re-mat.h (octave_matrix::clone): Likewise.\n\t* ov-re-nd-array.h (octave_double_nd_array::clone): Likewise.\n\t* ov-str-mat.h (octave_char_matrix_str::clone): Likewise.\n\t* ov-struct.h (octave_struct::clone): Likewise.\n\t* ov-va_args.h (octave_all_va_args::clone): Likewise.\n\t* ov.h (octave_value::clone): Likewise.\n\n\t* oct-lvalue.cc (octave_lvalue::assign, octave_lvalue::set_index,\n\toctave_lvalue::do_unary_op): Idx is now a list of indices.  Simplify.\n\t* oct-lvalue.h (octave_lvalue::value): Simplify.\n\t(octave_lvalue::struct_elt_names): Delete data member.\n\t(octave_lvalue::type): Now string\n\tUpdate decls.\n\n\t* pt-exp.h (tree_expression::is_indirect_ref):\n\tDelete virtual function.\n\n\t* pt-plot.cc (subplot::extract_plot_data): Use subsref, instead of\n\tdo_index_op.\n\n\t* pt-stmt.cc (tree_statement::eval): Don't try to avoid binding\n\tans for structure references.\n\n\t* symtab.cc (symbol_record::symbol_def::print_info): Rename from\n\tsymbol_record::symbol_def::dump_symbol_info.\n\t(symbol_record::print_info): Rename from\n\tsymbol_record::dump_symbol_info.  Now const..\n\t(symbol_record::print_symbol_info_line): Now const.\n\t(symbol_table::print_info): Rename from print_stats.  Accept\n\tostream arg.  Now const.  Print more info.\n\t* symtab.h: Update decls.\n\n\t* toplev.cc (octave_config_info): Indexing a map now returns a\n\tlist, but we only want to return the first element.\n\n\t* variables.cc (generate_struct_completions, looks_like_struct):\n\tSimplify using eval_string.\n\t(F__print_symtab_info__): Rename from F__dump_symtab_info__.\n\tHandle \"top-level\" and individual function names in addition to\n\t\"global\".\n\t(F__print_symbol_info__): Rename from F___dump_symbol_info__.\n\n\t* octave.cc (intern_argv): Built-in variable argv is now a cell array.\n\n\t* ov-complex.cc (valid_scalar_indices): Delete.\n\t* ov-scalar.cc (valid_scalar_indices): Delete.\n\n\t* oct-obj.cc (octave_value_list::valid_scalar_indices): New function.\n\t(octave_value_list::index): New arg, resize_ok.\n\t* oct-obj.h: Provide decls.\n\n\t* oct-map.cc (Octave_map::keys): Rename from make_name_list.\n\tChange all uses.\n\t(Octave_map::assign, Octave_map::index): New functions.\n\t* oct-map.h: Provide decls.\n\n\t* data.cc (Fstruct_contains): Use map_value instead of\n\tdo_struct_elt_index_op.\n\n\t* Cell.h (Cell (const Array2<octave_value>&, int, int)):\n\tNew constructor.\n\t(Cell::resize_fill_value): New static function.\n\n\t* input.cc (initialize_command_input): Set basic and completer\n\tword break characters.\n\n2002-05-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_value::subsref): New function.\n\t* ov-base.cc (octave_base_value::subsref): Likewise.\n\n\t* ov-struct.cc (octave_struct::print_raw): Print scalar struct\n\tarrays more compactly.\n\n\t* DLD-FUNCTIONS/time.cc (extract_tm): Handle new struct array def.\n\n\t* oct-map.cc (Octave_map::array_len): New data member.\n\t(Octave_map::operator[], Octave_map::contsnts): Return\n\toctave_value_list, not Octave_value.  Change callers as necessary.\n\t(Octave_map::assign): New function.\n\t(Octave_map::array_length): New fucntion.\n\t* oct-obj.cc (octave_value_list::assign): New function.\n\n2002-05-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* TEMPLATE-INST/Map-oct-obj.cc: New file.\n\t* Makefile.in (TI_XSRC): Add it to the list.\n\n\t* oct-map.h (Octave_map): Make CHMap<octave_value_list> a data\n\tmember instead of deriving from CHMap<octave_value>, in\n\tpreparation for structure arrays.\n\n\t* pt-indir.h, pt-indir.cc: Delete.\n\n\t* pt-all.h: Don't include pt-indir.h.\n\n\t* Makefile.in (PT_SRC): Delete pt-indir.cc from the list.\n\t(PT_INCLUDES): Delete pt-indir.h from the list.\n\n\t* pt-walk.h (tree_walker::visit_indirect_ref): Delete.\n\t* pt-pr-code.h, pt-pr-code.cc (tree_print_code::visit_indirect_ref):\n\tLikewise.\n\t* pt-check.h, pt-check.cc (tree_checker::visit_indirect_ref): Likewise.\n\t* pt-bp.h, pt-bp.cc (tree_breakpoint::visit_indirect_ref): Likewise.\n\n\t* pt-walk.h: Delete forward decl for tree_indirect_ref.\n\t* variables.h: Likewise.\n\n\t* parse.y (make_indirect_ref): Return tree_index_expression, not\n\ttree_indirect_ref.\n\n\t* pt-idx.h (tree_index_expression::struct_elt_name): New function.\n\n\t* pt-idx.cc (tree_index_expression::lvalue): Handle dot case too.\n\t(tree_index_expression::name): Likewise.\n\t(tree_index_expression rvalue (int)): Likewise.\n\t(tree_index_expression::eval_error): Likewise.\n\t* pt-pr-code.cc (visit_index_expression): Likewise.\n\t* pt-bp.cc (tree_breakpoint::visit_index_expression): Likewise.\n\n\t* pt-idx.h (tree_index_expression::dot): New type enum element.\n\t(tree_index_expression::expr_type): New function.\n\t(tree_index_expression::tree_index_expression (tree_expression*,\n\tconst std::string&, int, int)): New constructor.\n\t(tree_index_expression::is_index_expression): Return value is now\n\tconditional on itype.\n\t(tree_index_expression::is_indirect_ref): New function.\n\t(tree_index_expression::lvalue_ok): Also return true if itype is dot.\n\n2002-05-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (ABORT_PARSE): Maybe restore symbol table context too.\n\n\t* pt-idx.h (tree_index_expression::type): New enum.\n\t(tree_index_expression::etype): New data member.\n\t* pt-idx.h (tree_index_expression::tree_index_expression):\n\tNew arg, t, to set type of index.\n\t* parse.y (make_index_expression): Likewise.\n\tChange all callers.\n\n\t* ov-base.cc (cell_conv): New conversion function.\n\t(install_base_type_conversions): Install it.\n\tInstall conversion for indexed assignment of octave_cells to\n\tundefined values.\n\n\t* TEMPLATE-INST/Array-tc.cc: Instantiate assign functions too.\n\t(Array<octave_value>::resize_fill_value (void)):\n\tProvide specialization for octave_value.\n\n\t* ov-cell.cc (octave_cell::assign (const octave_value_list&,\n\tconst octave_value&)): New function.\n\t* Cell.h (Cell::Cell (const octave_value&)): New function.\n\n\t* OPERATORS/op-cell.cc (install_list_ops): Use DEFASSIGNANYOP_FN\n\tand INSTALL_ASSIGNANYOP, not DEFASSIGNOP_FN and INSTALL_ASSIGNOP.\n\n2002-05-03  Cai Jianming  <caijianming@yahoo.co.uk>\n\n\t* OPERATORS/op-cell.cc: New file.\n\t* Makefile.in (OP_XSRC): Include it in the list.\n\n\t* parse.y (cell): Return a cell type instead of Matrix type.\n\n\t* ov.cc (install_types): Install octave_cell type.\n\n\t* pr-output.cc (octave_print_internal): Handle Cells.\n\t* pr-output.h (octave_print_internal): Provide decl.\n\n\t* ov-cell.h (octave_cell): Derive from octave_base_matrix<Cell>.\n\t* ov-cell.cc (do_index_op, assign, print, print_raw,\n\tprint_name_tag): Delete.\n\n\t* Cell.cc (allocator, index): Delete.\n\t* Cell.h (Cell): Derive from Array2<octave_value>.\n\tMost functions removed since we can use those from Array2 instead.\n\n2002-05-02  Cai Jianming  <caijianming@yahoo.co.uk>\n\n\t* ov-base-mat.cc (octave_base_matrix<MT>::assign):\n\tNew function.\n\t* ov-base-mat.h (octave_base_matrix<MT>::assign): Provide decl.\n\t* ov-bool-mat.cc (octave_bool_matrix::assign): Delete.\n\t* ov-bool-mat.h (octave_bool_matrix:assign): Delete decl\n\t* ov-cx-mat.cc (octave_complex_matrix::assign (const\n\toctave_value_list& idx, const ComplexMatrix&)): Delete.\n\t* ov-cx-mat.h (octave_complex_matrix:assign (const\n\toctave_value_list& idx, const ComplexMatrix&)): Replace decl with\n\tfunction.\n\t* ov-re-mat.cc (octave_bool_matrix::assign): Delete.\n\t* ov-re-mat.h (octave_bool_matrix:assign): Delete decl.\n\n2002-05-02  Cai Jianming  <caijianming@yahoo.co.uk>\n\n\t* OPERATORS/op-bm-b.cc: New file.x\n\t* Makefile.in (OP_XSRC): Add it to the list.\n\n2002-04-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (print_version_and_exit): Use\n\tOCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY, not\n\tOCTAVE_NAME_AND_VERSION.\n\n\t* octave.cc (verbose_usage):\n\tUse OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY, not\n\tOCTAVE_NAME_VERSION_AND_COPYRIGHT.\n\n\t* version.h (OCTAVE_COPYING_STATEMENT, OCTAVE_WARRANTY_STATEMENT,\n\tOCTAVE_NAME_VERSION_COPYRIGHT_COPYING_AND_WARRANTY,\n\tX_OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_WARRANTY_AND_BUGS,\n\tOCTAVE_NAME_VERSION_COPYRIGHT_COPYING_WARRANTY_AND_BUGS,\n\tOCTAVE_BUGS_STATEMENT): New macros.\n\t(OCTAVE_STARTUP_MESSAGE): Define in terms of\n\tX_OCTAVE_NAME_VERSION_COPYRIGHT_COPYING_WARRANTY_AND_BUGS\n\tto include bugs address and amplified warranty information.\n\n\t* DLD-FUNCTIONS/lsode.cc (Flsode): Delete unused variable nsteps.\n\n2002-04-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (additional_help_message): Use www.octave.org, not\n\twww.che.wisc.edu/octave/octave.html.\n\t* octave.cc (verbose_usage): Likewise.\n\n2002-04-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/daspk.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\n2002-04-25  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* DLD-FUNCTIONS/kron.cc: New file.\n\t* Makefile.in (DLD_SRC): Add it to the list.\n\n2002-04-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (save_symtab): New non-terminal.  Save current symbol\n\ttable context here.\n\t(function_beg): Use it.\n\t(symtab_context): New file-scope variable.\n\t(recover_from_parsing_function): Restore symbol table context here.\n\n2002-04-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (get_lines_and_columns): Handle CRLF as line\n\tseparator in addition to LF.\n\n2002-04-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (hdf5_ofstream::hdf5_ofstream):\n\tExplicitly List std::ostream(0) in constructor.\n\t(hdf5_ifstream::hdf5_ifstream):\n\tExplicitly List std::istream(0) in constructor.\n\t(hdf5_fstreambase::hdf5_fstreambase): Use std::ios::setstate, not set.\n\t(hdf5_fstreambase::close): Likewise.\n\t(hdf5_fstreambase::open): Likewise.\n\n2002-04-10  Ben Sapp  <bsapp@lanl.gov>\n\n\t* pt-stmt.cc (delete_breakpoint): List breakpoints if line < 0.\n\t* debug.cc (get_user_function): Check symbol by name first.\n\t(Fdbstop): Rename from Fdbg_set.\n\t(Fdbclear): Rename from Fdbg_delete.\n\t(Fdbstatus): Rename from Fdbg_list.\n\t(Fdbg_where): Rename from Fdbwhere.\n\t(do_dbtype, Fdbtype): New functions.\n\n2002-04-10  Peter Van Wieren  <peter.vanwiere@avlna.com>\n\n\t* load-save.cc (save_mat5_binary_element): Save elements of 2d\n\tcharacter matrices in proper order.\n\n2002-04-09  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* utils.cc (do_string_escapes): Handle \\0 too.\n\t(undo_string_escape): Likewise.\n\n2002-04-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (octave_config_info): Define struct member EXEEXT, not EXE.\n\t* Makefile.in (install-bin): Use $(EXEEXT), not $(EXE).\n\t* oct-conf.h.in (OCTAVE_CONF_EXEEXT): Define and substitute\n\tOCTAVE_CONF_EXEEXT, not OCTAVE_CONF_EXE.\n\n2002-04-03  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\t* DLD-FUNCTIONS/balance.cc: Use F77_FUNC instead of F77_FCN.\n\t* DLD-FUNCTIONS/qz.cc: Likewise.\n\t* DLD-FUNCTIONS/rand.cc: Likewise.\n\t* octave.cc: Likewise.\n\t* toplev.cc (Foctave_config_info): Delete use of FORTRAN_MAIN_FLAG.\n\t* oct-conf.h.in: Delete use of OCTAVE_CONF_FORTRAN_MAIN_FLAG.\n\t* syscalls.cc (mk_stat_map):\n\tUse HAVE_STRUCT_STAT_ST_RDEV instead of HAVE_ST_RDEV.\n\tUse HAVE_STRUCT_STAT_ST_BLKSIZE instead of HAVE_ST_BLKSIZE.\n\tUse HAVE_STRUCT_STAT_ST_BLOCKS instead of HAVE_ST_BLOCKS.\n\n2002-04-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l, lex.h (parser_end_of_input): New global variable.\n\t(reset_parser): Reset it here.\n\t* parse.y (input): Set it to TRUE on EOF.\n\t(parse_and_executed): Save and restore it, check it to correctly\n\tbreak out of parse-execute loop.\n\t(parse_fcn_file): Likewise.\n\t(eval_string): Likewise.\n\t* toplev.cc (main_loop): Likewise.\n\n\t* parse.y (input): Call YYACCEPT for END_OF_INPUT.\n\tReturn no-op command for bare newline.\n\t(parse_and_execute): Handle change in yyparse return value semantics.\n\n\t* toplev.cc (main_loop): Likewise.\n\n2002-03-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (parse_fcn_file): Call error if there is no input file.\n\t(parse_and_execute (FILE *): Protect get_input_from_eval_string.\n\tSet get_input_from_eval_string to false before calling yyparse.\n\t* lex.l (reset_parser): Also skip yyrestart (stdin) if\n\treading_script_file is true.\n\n2002-03-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-loop.cc (evaluating_looping_command): New global.\n\t(tree_while_command::eval): Protect evaluating_looping_command.\n\tSet it to true while evaluating loop.\n\t(tree_do_until_command::eval): Ditto.\n\t(tree_simple_for_command::eval): Ditto.\n\t(tree_complex_for_command::eval): Ditto.\n\t* pt-loop.h (evaluating_looping_command): Provide decl.\n\t* parse.y (parse_fcn_file): Protect get_input_from_eval_string.\n\tSet get_input_from_eval_string to false before calling yyparse.\n\t(make_break_command): Also check evaluating_looping_command.\n\t(make_continue_command): Also check evaluating_looping_command.\n\t(eval_string (const std::string&, bool, int&, int)): Loop over\n\tyyparse to handle multi-line strings.\n\tMove call to unwind_protect::run_frame to end of function.\n\tDon't reset parser before calling yyparse.\n\tCorrectly handle return, break, and continue.\n\n\t* input.cc (input_from_eval_string_pending): New global variable.\n\t(get_usr_input): Use it.\n\t* input.h (input_from_eval_string_pending): Provide decl.\n\n2002-03-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tDon't unwind_protect num_named_args (it doesn't change on\n\trecursive calls).\n\tDo re-initialize curr_va_arg_number to num_named_args after\n\tunwind_protecting.\n\n\t* ov-usr-fcn.h (octave_user_function::clear_args_passed): Delete.\n\t(octave_user_function::saved_args): New data member.\n\t(octave_user_function::save_args_passed): New function.\n\t(octave_user_function::restore_args_passed): Ditto.\n\t* ov-usr-fcn.cc (clear_args_passed): Delete.\n\t(restore_args_passed): New function.\n\t(octave_user_function::do_multi_index_op): Correctly save and\n\trestore args passed for recursive calls.\n\n\t* TEMPLATE-INST/SLStack-ovl.cc: New file.\n\t* Makefile.in: Add it to the list.\n\n2002-02-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):\n\tHandle define_all_return_values after function is evaluated.\n\tFrom Paul Kienzle <pkienzle@jazz.ncnr.nist.gov>.\n\n\t* ov-scalar.cc (convert_to_str): Use octave_value (std::string)\n\tconstructor instead of octave_value (char *) constructor so that\n\tsetstr (0) will work.\n\n\t* pager.cc (octave_pager_buf::sync): Set pointer to beginning\n\tof buffer after calling flush_currnt_contents_to_diary.\n\t(octave_diary_buf::sync): Call eback only once.\n\n2002-01-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (.): Remove test for EOF since it is already handled\n\tseparately.\n\n2001-12-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (save_mat5_binary_element):\n\tExtract dimensions directly from tc.\n\tHandle ranges the same as real matrices.\n\n2001-11-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (DATA_REDUCTION): If no DIM arg, pass -1 to FCN.\n\n2001-11-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-conf.h.in (FFTW_LIBS, LD_CXX, LIBOCT_PATHSEARCH,\n\tLIBOCT_READLINE, MKOCTFILE_LFLAGS): Substitute.\n\t* toplev.cc (octave_config_info): Add them to the map.\n\n2001-11-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/lsode.cc (Flsode): Don't bother to give OUTPUT\n\tmatrix a size before calling integration function.\n\n2001-11-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\tMakefile.in (OCTAVE_LIBS): Add $(LIBOCT_READLINE) and\n\t$(LIBOCT_PATHSEARCH) to the list.\n\n2001-10-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/dassl.cc (dassl_user_function): Allow user\n\tsupplied RES function to return IDID as second value.\n\n2001-07-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y: Clear help_buf after documenting function.\n\n2001-06-29  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* defun-int.h (DEFINE_FUN_INSTALLER_FUN{2,3}): New macros.\n\t(DEFINE_FUN_INSTALLER_FUN): Use.\n\t* dynamic-ld.cc ({STRINGIFY, STRINGIFY1}): New macros.\n\t(octave_dynamic_loader::mangle_name): Support dynamic linking\n\tfor GNU v3 and Sun C++ ABI.\n\n2001-06-26  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* c-file-ptr-stream.h (c_file_ptr_buf::c_file_ptr_buf): Add GCC3\n\tlibstdc++-v3 support.\n\t* load-save.cc (save_mat5_binary_element): Cast arguments to the\n\tcorrect type.\n\t(save_ascii_data): Eliminate compiler warning.\n\t* toplev.cc (system): Prefix std::.\n\n2001-05-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cx-mat.cc: Deleve unnecessary instantiation of assign function.\n\t* ov-re-mat.cc: Likewise.\n\t* ov-re-nd-array.cc: Likewise.\n\t* ov-str-mat.cc: Likewise.\n\t* ov-bool-mat.cc: Likewise.\n\n\t* load-save.cc (save_ascii_data): When saving string data, get raw\n\tstring value for matrix row since there may be embedded nuls.\n\n\t* pt-mat.cc (Vstring_fill_char): No longer static.\n\t* pt-mat.h: Provide declaration.\n\n2001-05-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (initialize_pathsearch): Save initial value of the\n\tTEXMFDBS environment variable here.\n\t* toplev.cc (restore_texmfdbs_envvar): New function.\n\t(Fsystem): Set TEXMFDBS back to original value before running\n\tsubprocesses.\n\n2001-05-02  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* Makefile.in (octave): Add $(FFTW_LIBS).\n\n2001-04-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/sort.cc (mx_sort): Check for NaNs in comparisons.\n\n2001-04-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (OCTAVE_LIBS): Delete $(LIBREADLINE) from the list.\n\t(octave): Delete TERMLIBS from link command.\n\t* oct-conf.h.in: Delete references to LIBREADLINE, TERMLIBS.\n\t* toplev.cc (octave_config_info): Delete entries for LIBREADLINE,\n\tTERMLIBS.\n\n2001-04-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-lib): Don't use mk-libdir-link.\n\t(install-inc): Don't use mk-includedir-link.\n\n2001-04-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (fold (tree_binary_expression *)):\n\tSet discard_error_messages here instead of buffer_error_messages.\n\tDon't add clear_global_error_variable to the unwind_protect stack.\n\t(fold (tree_unary_expression *)): Likewise.\n\t(finish_colon_expression): Likewise.\n\t(finish_matrix): Likewise.\n\n\t* error.cc (panic): Set discard_error_messages to false here.\n\t(verror): Return immediately if discard_error_messages is true.\n\n\t* error.cc (discard_error_messages): New global variable.\n\t* error.h: Provide declaration.\n\n2001-04-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l: If unexpected character is EOF, report EOF error instead\n\tof invalid character error.\n\n2001-04-18  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* load-save.cc (read_mat5_binary_element): Cast arguments to the\n\tcorrect type when adding stream positions.\n\t* DLD-FUNCTIONS/det.cc (det): Explicity create a Complex value to\n\twork around a Sun C++ type conversion bug.\n\n2001-04-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* symtab.cc (define_builtin_const): Don't call replace_all_defs\n\there.\n\n\t* error.cc (error_message_buffer): Now static.\n\t* error.h (error_message_buffer): Delete extern declaration.\n\n2001-03-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/besselj.cc (besselh): Use K arg.\n\tFrom: Thomas Stuart <tstuart@ing.sun.ac.za>.\n\n\t* oct-stream.cc (get_size): Don't allow [Inf, N] as a size\n\tspecification for the read and scanf functions.\n\t(get_size): SIZE is now an Array<double> instead of a Matrix object.\n\t(read): Likewise.  Change all callers.\n\t(scanf): Likewise.  Change all callers.\n\n2001-03-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/det.cc (Fdet): Only return rcond if nargout > 1.\n\t* DLD-FUNCTIONS/inv.cc (Finv): Only return rcond if nargout > 1.\n\n2001-03-26  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* DLD-FUNCTIONS/det.cc (Fdet): Suppress warning, but return rcond.\n\t* DLD_FUNCTIONS/inv.cc (Finv): Return rcond if requested.\n\n2001-02-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt.h (tree::break_statement): New static member.\n\t(tree::break_function): Make const.\n\t* pt.cc (tree::break_statement): Initialize here.\n\t(tree::break_function): Make const.\n\t* pb-bp.h (break_statement): Delete global variable declaration.\n\t* pt-bp.cc (break_statement): Delete global variable definition.\n\n\t* pt-bp.h (tree_breakpoint::bp_list): Rename from lst.\n\n\t* pt.h: Don't inlcude ov-usr-fcn.h.\n\tProvide forward declaration of octave_user_function class.\n\n2001-02-28  Ben Sapp  <bsapp@lanl.gov>\n\n\t* debug.cc (get_user_function): Simplify by using curr_function.\n\t(Fdbg_where): New function.\n\t(Fdbg_list): Now DLD_TEXT instead of DLD_FCN.\n\t(Fdbg_set): Likewise.\n\t(Fdbg_delete): Likewise.\n\n\t* pt-bp.h (break_statement): New global variable.\n\t(MAYBE_DO_BREAKPOINT): Check for dbg_next and dbg_step.\n\tPrint line, column, and current statement.\n\t* pt-bp.cc (break_statement): New global variable\n\t(tree_breakpoint::visit_do_until_command): Return immediately if\n\twe've already found the line.\n\t(tree_breakpoint::visit_colon_expression): Set breakpoint info here.\n\t(tree_breakpoint::visit_binary_expression): Recurse here when\n\tchecking for breakpoints.\n\n\t* debug.cc: Move here from DLD-FUNCTIONS/debug.cc.\n\t* Makefile.in (DIST_SRC): Add it to the list.\n\t(DLD_XSRC): Delete it from the list.\n\n\t* pt.h (tree::last_line, tree::break_function): New static members.\n\t* pt.cc(tree::last_line, tree::break_function): Initialize them.\n\n\t* pt-cell.h (tree_cell::tree_cell): Accept line and column info.\n\t* pt-mat.h (tree_matrix::tree_matrix): Likewise.\n\n\t* ov-usr-fcn.h (octave_user_function::sym_tab): Delete.\n\n\t* input.cc (get_user_input): Handle dbg_next.\n\tSet tree:break_function and tree::last_line when doing dbg_step.\n\n2001-02-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (handle_string): Save line and column information in token.\n\t(is_keyword): Save line and column information for plot style and\n\taxes tokens.\n\n\t* toplev.cc (main_loop): Set retval to non-zero value if error\n\toccurs when not interactive.\n\n2001-02-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (gobble_leading_white_space): Handle CRLF here too.\n\t* lex.l (check_for_garbage_after_fcn_def): Likewise.\n\n\t* lex.l: Add numeric value of character to error message for\n\tunrecognized characters.\n\n2001-02-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/minmax.cc (EMPTY_RETURN_CHECK): For empty matrix\n\targs, make Octave's min\tand max behave like Matlab.\n\n2001-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* OPERATORS/op-s-s.cc (el_or, el_and): Return bool value.\n\n2001-02-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-binop.cc (tree_boolean_expression::rvalue):\n\tDon't cast result to double.\n\n\t* OPERATORS/op-b-b.cc: Allow & and | operators to return bool values.\n\n2001-02-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (DATA_REDUCTION): Undo previous change.\n\n2001-02-13  Matthew W. Roberts  <matt@nephi.tamu.edu>\n\n\t* load-save.cc (Fload): Accept -4 as an alias for -v4 and -mat4-binary.\n\t(Fsave): Likewise.\n\n2001-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (lexical_feedbac::init):\n\tInitialize looking_at_matrix_or_assign_lhs too.\n\n2001-02-09  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (DATA_REDUCTION): Allow FCN(x,0) to be equivalent to FCN(x).\n\n2001-02-06  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* oct-stream.cc (octave_scan): Partially implement and specialize\n\tfor char*.  Delete the old template instantiations.\n\t(BEGIN_S_CONVERSION): Use strings instead of ostrstreambuf.\n\t(octave_base_stream::do_scanf): Pass correct parameter to\n\tdo_scan_conv.\n\n2001-02-05  Mumit Khan  <khan@nanotech.wisc.edu>\n\n\t* pr-output.cc (set_format): Add std:: namespace qualifier as\n\tneeded.\n\n\t* oct-stream.cc (octave_scan): Implement, and specialize for\n\tchar*. Delete the old template instantiations.\n\t(BEGIN_S_CONVERSION): Use strings instead of ostrstreambuf.\n\t(octave_base_stream::do_scanf): Pass correct parameter to\n\tdo_scan_conv.\n\n\t* Makefile.in (TEMPLATE_AR, TEMPLATE_ARFLAGS): Use to create\n\tarchive libraries containing templates.\n\n\t* c-file-ptr-stream.h: Include <fstream>. Use <cstdio> instead of\n\t<stdio.h>\n\t(c_file_ptr_buf::int_type): Compat typedef for non-ISO libstdc++.\n\t(c_file_ptr_buf::{overflow, underflow, uflow, pbackfail): Use.\n\t(c_file_ptr_buf::c_file_ptr_buf): Handle various compilers.\n\t(c_file_ptr_buf::file_number): New member function.\n\t(c_file_ptr_buf::fd): New private data.\n\t(i_c_file_ptr_stream::i_c_file_ptr_stream): Initialize stream\n\tcorrectly.\n\t(o_c_file_ptr_stream::o_c_file_ptr_stream): Likewise.\n\t* c-file-ptr-stream.cc\n\t(c_file_ptr_buf::{overflow, underflow, uflow, pbackfail): Add\n\tISO-compliant EOF handling.\n\t* oct-stream.cc (octave_base_stream::file_number): Use\n\tc_file_ptr_buf::file_number to get underlying file descriptor.\n\n\t* comment-list.cc: Add missing class qualifier.\n\n\t* file-io.cc, load-save.cc, mappers.cc, oct-fstrm.cc, oct-fstrm.h,\n\toct-iostrm.cc, oct-iostrm.h, oct-stdstrm.cc, oct-stdstrm.h,\n\toct-stream.cc, oct-stream.h, oct-strstrm.cc, oct-strstrm.h,\n\tov-base-nd-array.cc, ov-base-scalar.h, ov-complex.cc, ov-cx-mat.cc,\n\tpager.cc, pr-output.cc, procstream.h, pt-bp.h, utils.cc:\n\tAdd std:: namespace qualifier as needed, and replace\n\tdeprecated or invalid libstdc++-v2 names with standard ones\n\twhere appropriate.\n\n\t* DLD-FUNCTIONS/minmax.cc: Fix docstring.\n\n\t* oct-fstrm.cc (octave_fstream::octave_fstream): Maintain fix for\n\tlibstdc++-v2.\n\n\t* oct-stdstrm.cc (octave_ostdiostream::create): Remove default\n\tparameter value in definition.\n\n\t* oct-stream.cc (octave_stream::mode_as_string): Don't assume\n\tstd::iso::openmode is an integral quantity.\n\n\t* pager.cc, procstream.h: Initialize streams correctly.\n\n\t* utils.cc: Use CXX_ISO_COMPLIANT_LIBRARY guard.\n\n\t* ov-base-nd-array.cc (idx_list_to_idx_array): Inline.\n\n\t* ov-base-scalar.h (octave_base_scalar::octave_base_scalar): Use\n\t``const ST& s'' instead of ST to workaround gcc3 complex bug.\n\n2001-02-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (next_token_is_bin_op): Remove Checks for spacing except\n\tfor ops that begin with +, - but are not ++, --, +=, or -=.\n\n2001-02-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (get_user_input): Handle dbg_cont and dbg_step here.\n\t* debug.cc (Fdbg_cont): Delete.\n\t* pt-bp.h (MAYBE_DO_BREAKPOINT): Check tree::break_next here.\n\t* pt.h (tree::break_next): New static member.\n\t* pt.cc: Initialize it.\n\n\t* parse.h (feval (const octave_value_list&, int)):\n\tSet default value for nargout.\n\t(feval (const std::string&, const octave_value_list&, int)):\n\tSet default values for args and nargout.\n\n2001-02-01  Ben Sapp  <bsapp@lanl.gov>\n\n\t* DLD-FUNCTIONS/debug.cc: New file.\n\t* pt-bp.h, pt-bp.cc: New files, for breakpoints.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* pt-stmt.cc (tree_statement_list::set_breakpoint,\n\ttree_statement_list::delete_breakpoint,\n\ttree_statement_list::list_breakpoints): New functions.\n\n\t* pt.h (tree::break_point): New data member.\n\t(tree::set_breakpoint, tree::delete_breakpoint, tree::is_breakpoint):\n\tNew virtual functions.\n\n\t* pt-mat.cc (tree_matrix::rvalue): Check for breakpoint here.\n\t* pt-unop.cc (tree_prefix_expression::rvalue): Likewise.\n\t(tree_postfix_expression::rvalue): Likewise.\n\t* pt-loop.cc (tree_do_until_command::eval): Likewise.\n\t(DO_LOOP): Likewise.\n\t(tree_simple_for_command::eval): Likewise.\n\t(tree_complex_for_command::eval): Likewise.\n\t* pt-assign.cc (tree_simple_assignment::rvalue): Likewise.\n\t* pt-binop.cc (tree_binary_expression::rvalue): Likewise.\n\t(tree_boolean_expression::rvalue): Likewise.\n\t* pt-cell.cc (tree_cell::rvalue): Likewise.\n\t* pt-colon.cc (tree_colon_expression::rvalue): Likewise.\n\t* pt-except.cc (tree_try_catch_command::eval): Likewise.\n\t(tree_unwind_protect_command::eval): Likewise.\n\t* pt-id.cc (tree_identifier::rvalue): Likewise.\n\t(tree_identifier::lvalue): Likewise.\n\t* pt-indir.cc (tree_indirect_ref::rvalue): Likewise.\n\t* pt-jump.cc (tree_break_command::eval): Likewise.\n\t(tree_continue_command::eval): Likewise.\n\t(tree_return_command::eval): Likewise.\n\n2001-01-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Map.h, Map.cc (CHMap<C>::operator = (const CHMap&)): New function.\n\t(Map<C>::operator = (const Map&)): Likewise.\n\t(Map<C> (const Map&)): Likewise.\n\n\t* OPERATORS/op-cm-cs.cc, OPERATORS/op-cm-s.cc,\n\tOPERATORS/op-m-cs.cc, OPERATORS/op-m-s.cc:\n\tMake ldiv operator work for row vector by scalar ops.\n\n\t* OPERATORS/op-cs-cm.cc, OPERATORS/op-cs-m.cc,\n\tOPERATORS/op-s-cm.cc, OPERATORS/op-s-m.cc:\n\tMake div operator work for scalar by column vector ops.\n\n2001-01-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (safe_fclose): Discard comments at the end of a file.\n\n2001-01-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* error.cc (pr_where): Call pr_where_1 with two args, not one, to\n\tavoid processing format escapes that might appear in formatted code.\n\n2001-01-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* error.cc (vwarning): Write to output_buf, then send formatted\n\tmessage to diary and error streams.\n\n2001-01-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cx-mat.cc (octave_complex_matrix::try_narrowing_conversion):\n\tHandle empty matrix dimensions correctly.\n\n2000-12-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pager.h (octave_pager_buf::diary_skip): New data member.\n\t(octave_pager_buf::octave_pager_buf): Initialize it.\n\t* pager.cc (octave_pager_buf::set_diary_skip): New function.\n\t(octave_pager_stream::set_diary_skip): New function.\n\t(octave_pager_buf::sync): Call flush_current_contents_to_diary\n\tinstead of octave_diary.write.\n\t(octave_pager_buf::flush_current_contents_to_diary): Use\n\tdiary_skip, reset when done.\n\t(open_diary_file): Call octave_stdout.set_diary_skip here.\n\n2000-12-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/minmax.cc (EMPTY_RETURN_CHECK): New macro.\n\t(min, max): Use it.\n\n\t* DLD-FUNCTIONS/minmax.cc (MINMAX_BODY): New macro.  If single arg\n\tis empty, return empty matrix result and empty matrix for index.\n\t(Fmin, Fmax): Use MINMAX_BODY, so we have consistent definition\n\tfor min and max functions.\n\n2000-11-30  Joerg Specht  <joerg.specht@ins.uni-stuttgart.de>\n\n\t* help.cc (display_help_text): Append new line at end of doc string.\n\n2000-11-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/lsode.cc (LSODE_ABORT1, LSODE_ABORT2): Omit `##'\n\tin macro definition since they are not needed to paste strings\n\ttogether and picky compilers choke on them.\n\t* DLD-FUNCTIONS/quad.cc (QUAD_ABORT1, QUAD_ABORT2): Likewise.\n\t* DLD-FUNCTIONS/fsolve.cc (FSOLVE_ABORT1, FSOLVE_ABORT2): Likewise.\n\t* DLD-FUNCTIONS/dassl.cc (DASSL_ABORT1, DASSL_ABORT2): Likewise.\n\n2000-11-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkbuiltins (XDEFUNX_INTERNAL): New macro.\n\t* mkgendoc (XDEFUNX_INTERNAL): Likewise.\n\t* defun-int.h (DEFUNX_INTERNAL): Use it.\n\n\t* defun.h (DEFUNX): New macro.\n\t* defun-int.h (DEFUNX_INTERNAL, DECLARE_FUNX): New macro.\n\t(DECLARE_FUN): Define in terms of DECLARE_FUNX.\n\n\t* mkdefs: Read and print one line at a time, so we can force\n\tpatterns to match only at the beginning of a line.\n\n\t* defun-int.h (UNDERSCORIFY): Omit `##' in macro definition since\n\tthey are not needed to paste strings together and picky compilers\n\tchoke on them.\n\n2000-11-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (save_ascii_data_for_plotting): New function.\n\t* pt-plot.cc (save_in_tmp_file): Use it instead of save_ascii_data.\n\n\t* load-save.cc (save_ascii_data): Warn if saving Inf or NaN values.\n\tNew arg, infnan_warned.  Use it to warn just once per set.\n\tNow static.\n\t(do_save): New arg, infnan_warned.  Pass to save_ascii_data.\n\t(save_vars): Initialize infnan_warned here, pass to do_save.\n\n2000-11-16  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* file-io.cc (Ffprintf): If no file id parameter, don't return\n\tcount of characters if nargout is 0 (for compatibility with\n\tMatlab).\n\n2000-11-16  Ben Sapp  <bsapp@lanl.gov>\n\n\t* DLD-FUNCTIONS/rand.cc (do_rand): Declare loop counter as\n\tvolatile int, not just volatile.\n\n2000-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (skip_comments): Allow % as comment character too.\n\t(extract_keyword): Likewise.\n\n\t* Makefile.in (oct-gperf.h): Remove -a, -g, and -p flags for gperf.\n\n2000-10-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (do_load): Allow result to be returned instead of\n\tinserting variables in the symbol table.  Change patterned after\n\tpatch by Kian Ming Adam Chai <caijianming@yahoo.co.uk>.\n\n2000-10-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (ops.cc): Don't substitute BLAS_LIBS and LIBS here.\n\n\t* oct-conf.h.in (OCTAVE_CONF_SPECIAL_MATH_LIB): Delete.\n\t(OCTAVE_CONF_BLAS_LIBS): Add.\n\t* toplev.cc (octave_config_info): Likewise, add BLAS_LIBS and\n\tremove SPECIAL_MATH_LIB from the struct.\n\n\t* parse.y (feval (const octave_value_list&, int)): Don't panic\n\twhile processing arg names if arg.length() and arg_names.length()\n\tdiffer.\n\n2000-10-12  Paul Kienzle  <pkienzle@kienzle.powernet.co.uk>\n\n\t* ov-cell.h (octave_cell::is_cell): New function.\n\n\t* pt-select.cc (equal): New static function.\n\t(tree_switch_case::label_matches): Use it to compare case label\n\tagainst arg.  Handle cell arrays as case labels.\n\n2000-10-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\tChange patterned after patch by Cai Jianming\n\t<caijianming@yahoo.co.uk> to support for DIM arg in 2.0.x sources.\n\n\t* data.cc (DATA_REDUCTION): New macro.  Handle second DIM arg here.\n\t(Fcumprod): Replace function body with DATA_REDUCTION.\n\t(Fcumsum): Likewise.\n\t(Fprod): Likewise.\n\t(Fsum): Likewise.\n\t(Fsumsq): Likewise.\n\n2000-10-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* error.cc (pr_where_2): New function.\n\t(pr_where_1): Use it instead of error_1 to avoid setting error_state.\n\n2000-10-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* xdiv.cc (xdiv): Warn if execution falls through to lssolve.\n\n2000-09-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (FERRNO): New function (currently commented out).\n\n\t* c-file-ptr-stream.cc (c_file_ptr_buf::close): Call flush here.\n\t(c_file_ptr_buf::~c_file_ptr_buf): Not here.\n\t* c-file-ptr-stream.h (c_fie_ptr_buf::close_fcn): New typedef.\n\t(c_file_ptr_buf::cf): New data member.  Add default constructor arg.\n\t(class c_file_ptr_buf): Derive from filebuf, not streambuf.\n\t(i_c_file_ptr_stream, o_c_file_ptr_stream): Handle close function here.\n\t* oct-procstrm.cc (octave_iprocstream, octave_oprocstream): Likewise.\n\t(octave_iprocstream::do_close, octave_oprocstream::do_close): Delete.\n\t* oct-stdstrm.cc (octave_base_stdiostream::~octave_base_stdiostream):\n\tDon't do anything.\n\t(octave_istdiostream::create): Handle close function here.\n\t(octave_istdiostream::octave_istdiostream): Likewise.\n\t(octave_ostdiostream::create): Likewise.\n\t(octave_ostdiostream::octave_ostdiostream): Likewise.\n\t(class octave_base_stdiostream): Don't cache FILE pointer here.\n\n2000-09-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* syscalls.cc (Ffcntl): Don't assume that the file id passed in is\n\tthe same as the underlying system file id.\n\n2000-08-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y: Use octave_time, not time.\n\n2000-08-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (printf_value_cache::double_value): Also set\n\tcurr_stat to conversion_error if there are no values at all.\n\n2000-08-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dirfns.cc (Flink, Fsymlink, Freadlink): New functions.\n\n2000-08-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (Vsave_header_format_string): New variable.\n\t(symbols_of_load_save): DEFVAR it.\n\t(save_header_format, default_save_header_format): New functions.\n\t(write_header): Use Vsave_header_format_string here.\n\n2000-07-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-pr-code.h (tree_print_code::curr_print_indent_level,\n\t(tree_print_code::beginning_of_line): No longer static.\n\t(tree_print_code::tree_print_code): Initialize them here.\n\t* pt-pr-code.cc: Not here.\n\n\t* pt-stmt.cc (tree_statement::eval): Set curr_statement here.\n\t(tree_statement_list::eval): Not here.\n\n\tDebug-on-error stuff based on a patch submitted by Paul Kienzle\n\t<pkienzle@kienzle.powernet.co.uk> for 2.0.x.\n\n\t* error.cc (Vdebug_on_warning): New static flag variable.\n\t(debug_on_warning): New function.\n\t(symbols_of_warning): DEFVAR debug_on_warning.\n\t(warning): Handle debug_on_warning here.\n\n\t* input.cc (do_keyboard): New function.\n\t(Fkeyboard): Use it to do the real work.\n\t* pt-stmt.cc (curr_statement): New static variable.\n\t(tree_statement::eval): Save and restore it here.\n\t* error.cc (Vdebug_on_error): New static flag variable.\n\t(debug_on_error): New function.\n\t(symbols_of_error): DEFVAR debug_on_error.\n\t(pr_where, pr_where_1): New functions.\n\t(error): Handle debug_on_error here.\n\n2000-07-20  Joao Cardoso  <jcardoso@inescporto.pt>\n\n\t* Makefile.in (octave): Link with $(LD_CXX) instead of $(CXX)\n\n2000-07-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_base_stream::oscanf): Advance to next\n\tformat element before attempting to pick up any trailing stuff.\n\n2000-07-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (next_token_is_bin_op): Don't recognize `..' as a binary op.\n\n\t* load-save.cc (get_file_format): Call read_mat5_binary_file_header\n\twith third arg true instead of false, so we don't barf if the file\n\tis not a matlab v5 binary file.\n\n2000-07-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (octave): Link to ../libcruft/blas-xtra/xerbla.o here.\n\n\t* octave.cc (main): Remove kluge to attempt linking our version of\n\txerbla.\n\n2000-07-07  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\t* load-save.cc (have_h5giterate_bug): New file-scope variable.\n\t(hdf5_read_next_data): Only increment current_item if\n\thave_h5giterate_bug is true.\n\t(read_hdf5_data): Set have_h5giterate_bug here.\n\tOnly increment hs.current_item if have_h5giterate_bug is true.\n\n2000-07-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* c-file-ptr-stream.cc (c_file_ptr_buf::close):\n\tReturn -1 if file pointer is NULL.\n\tSet file pointer to 0 after closing.\n\t(c_file_ptr_buf::~c_file_ptr_buf): Call close after flushing.\n\n2000-07-05  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\t* Makefile.in (BLAS_LIBS): Substitute here.\n\t(octave): Use $(BLAS_LIBS) in the final link command.\n\n2000-06-30  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\t* Makefile.in (octave): Link $(FLIBS) last.\n\t* octave.cc (main): Force our own xerbla to be linked instead of\n\tsome system version.\n\n2000-06-29  James R. Van Zandt  <jrv@vanzandt.mv.com>\n\n\t* load-save.cc (load_save_format): New value, LS_MAT5_BINARY.\n\t(arrayclasstype, mat5_data_type): New enums.\n\t(read_mat5_binary_data): New function.\n\t(read_mat5_tag): New function.\n\t(read_mat5_binary_element): New function.\n\t(read_mat5_binary_file_header): New function.\n\t(get_file_format): Check for mat5 binary format too.\n\t(do_load): Handle mat5 binary format.\n\t(write_mat5_tag): New function.\n\t(write_mat5_array): New function.\n\t(class mat5_callback): New class.\n\t(save_mat5_binary_element): New functnon.\n\t(do_save): Handle mat5 binary format.\n\t(write_header): Handle LS_MAT5_BINARY case too.\n\t(save_user_variables): Handle LS_MAT5_BINARY case too.\n\t(Fsave): Handle LS_MAT5_BINARY case too.\n\t(Fload): Handle LS_MAT5_BINARY case too.\n\n2000-06-29  Steven G. Johnson  <stevenj@alum.mit.edu>\n\n\tAll of the following changes are protected by #ifdef HAVE_HDF5.\n\n\t* load-save.cc (load_save_format): New value, LS_HDF5.\n\t(make_valid_identifier): New function.\n\t(class hdf5_fstreambase, class hdf5_ifstream, class hdf5_ofstream):\n\tNew classes for reading and writing hdf5 data.\n\t(hdf5_types_compatible): New function.\n\t(hdf5_import_multidim): New function.\n\t(hdf5_check_attr): New function.\n\t(hdf5_read_next_data): New function.\n\t(hdf5_make_complex_type): New function.\n\t(hdf5_make_range_type): New function.\n\t(read_hdf5_data): New function.\n\t(get_file_format): Handle HDF5 format.\n\t(do_load): Handle LS_HDF5 case.\n\t(Fload): Handle HDF5 format.\n\t(hdf5_add_attr): New function.\n\t(save_type_to_hdf5): New function.\n\t(add_hdf5_data): New function.\n\t(do_save): Handle HDF5 format.\n\t(get_default_save_format): Handle LS_HDF5 case.\n\t(write_header): Handle LS_HDF5 case.\n\t(save_user_variables): Handle HDF5 format.\n\t(Fsave): Handle HDF5 format.\n\n2000-06-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (display_help_text): If writing to filter fails, send\n\tunformatted text to output stream.\n\n2000-06-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* OPERATORS/op-bm-bm.cc (eq): Define using mx_el_eq, not operator ==.\n\t(ne): Likewise, use mx_el_ne, not operator !=.\n\n\t* pr-output.cc (Fdisp): Delete.\n\n2000-06-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (float_format::float_format): Set default values\n\tfor width and precision to -1.\n\t(operator << (ostream&, pr_formatted_float&): Set width and\n\tprecision if values are >= 0.\n\t(set_real_format, set_real_matrix_format, set_range_format,\n\tset_complex_format, set_complex_matrix_format): If we have all\n\tintegers, infinities, or nans, set precision equal to field width.\n\n\t* load-save.cc (read_ascii_data): Allow empty strings and string\n\tvectors to be restored.\n\n\t* variables.cc (var_matches_any_pattern): New function.\n\t(Fclear): Use it to make exclusive clear work correctly.\n\n2000-06-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-range.h (octave_range::is_numeric_type): New function.\n\n\t* sysdep.cc (Fkbhit): Also ask for input if forced_interactive.\n\n2000-06-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (oct-gperf.h): Use $(GPERF) instead of gperf.\n\n2000-05-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/qz.cc (Fqz): When computing finite generalized\n\teigenvalues, don't write past the end of the array.\n\n2000-05-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-base-nd-array.h, ov-base-nd-array.cc, ov-re-nd-array.h,\n\tov-re-nd-array.h: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* pt-stmt.h, pt-stmt.cc (class tree_statement):\n\tStore comments associated with this parse tree element.\n\t* pt-select.h, pt-select.cc (class tree_if_clause,\n\tclass tree_if_command, class tree_switch_case\n\tclass tree_switch_command): Likewise.\n\t* pt-loop.h, pt-loop.cc (class tree_while_command,\n\tclass tree_do_until_command, class tree_simple_for_command,\n\tclass tree_complex_for_command): Likewise.\n\t* pt-except.h, pt-except.cc (class tree_try_catch_command,\n\tclass tree_unwind_protect_command): Likewise.\n\t* ov-usr-fcn.h, ov-usr-fcn.cc (class octave_user_function): Likewise.\n\t* pt-pr-code.h, pt-pr-code.cc (tree_print_code::print_comment_elt,\n\ttree_print_code::print_comment_list,\n\ttree_print_code::print_indented_comment): New functions.\n\t(tree_print_code::visit_simple_for_command,\n\ttree_print_code::visit_complex_for_command,\n\ttree_print_code::visit_octave_user_function_header,\n\ttree_print_code::visit_octave_user_function_trailer,\n\ttree_print_code::visit_if_command, tree_print_code::visit_statement,\n\ttree_print_code::visit_switch_case,\n\ttree_print_code::visit_switch_command,\n\ttree_print_code::visit_try_catch_command,\n\ttree_print_code::visit_unwind_protect_command\n\ttree_print_code::visit_while_command,\n\ttree_print_code::visit_do_until_command): Handle comments.\n\t* lex.l, parse.y: Handle comments in parse trees.\n\t* comment-list.h, comment-list.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\n2000-04-23  etienne grossmann  <etienne@anonimo.isr.ist.utl.pt>\n\n\t* pt-mat.cc (tm_row_const::tm_row_const_rep::eval_error):\n\tNew args x and y, for dimension mismatch info.\n\tChange callers where appropriate.\n\t(tm_const::init): Report mismatched column dimensions.\n\n2000-04-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sysdep.cc (kbhit): Also clear cin if at EOF.\n\n2000-04-11  Joao Cardoso  <jcardoso@inescn.pt>\n\n\t* sysdep.cc (kbhit): New arg, wait.\n\t(raw_mode): Ditto.\n\t(Fkbhit): If given an arg, call kbhit with wait = false.\n\n\t* DLD-FUNCTIONS/minmax.cc (Fmax, Fmin): Fix doc string.\n\n2000-04-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load): Undo previous change.\n\n2000-04-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc (octave_dynamic_loader::do_load): Also fail with\n\terror message if we don't find the mangled function name in the\n\tfile.\n\n2000-03-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (printf_value_cache::string_value): Return string\n\tmatrices in a Matlab-compatible way.\n\t(printf_value_cache): Redesign the way list_exhausted works.\n\n\t* oct-fstrm.cc (octave_fstream::do_close): New function.\n\t* oct-stdstrm.cc (octave_istdiostream::do_close): Ditto.\n\t(octave_ostdiostream::do_close): Ditto.\n\t* c-file-ptr-stream.cc (c_file_ptr_buf::close): Ditto.\n\t(i_c_file_ptr_stream::close): Ditto.\n\t(o_c_file_ptr_stream::close): Ditto.\n\t* oct-prcstrm.cc (octave_iprocstream::do_close): Ditto.\n\t(octave_oprocstream::do_close): Ditto.\n\t(octave_iprocstram::~octave_iprocstram): Call do_close here.\n\t(octave_iprocstram::~octave_oprocstram): Likewise.\n\n\t* oct-stream.h (octave_base_stream::do_close): New virtual function.\n\t(octave_base_stream::close): If stream is open, call do_close.\n\n\t* c-file-ptr-stream.cc (c_file_ptr_buf::flush): New function.\n\t(c_file_ptr_buf::~c_file_ptr_buf): Use it.\n\t(c_file_ptr_buf::overflow): Ditto.\n\t(c_file_ptr_buf::sync): Ditto.\n\n2000-03-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-procbuf.cc (octave_procbuf::open): Make output streams line\n\tbuffered.\n\n2000-03-24  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (my_friendly_exit): Prefix failure messages with\n\tpanic instead of error.\n\n\t* c-file-ptr-stream.cc (c_file_ptr_buf::~c_file_ptr_buf):\n\tAvoid dereferencing NULL pointer.\n\n\t* oct-stream.cc (printf_format_list::add_elt_to_list,\n\tprintf_format_list::process_conversion,\n\tprintf_format_list::finish_conversion): New args, flags, fw, and prec.\n\t(printf_format_list::printf_format_list): Save more complete info.\n\t(printf_format_list::printme): Print flags, fw, and prec.\n\t(octave_base_stream::printf): Simplify.\n\t(do_printf_conv): Delete have_arg arg, since it is always true now.\n\t(octave_base_stream::do_printf): Handle case of no args and %\n\tdirectly instead of using do_printf_conv.\n\t(printf_value_cache::exhausted): Rename from no_more_values.\n\t(DO_PCT_CONVERSION): New macro\n\t(octave_base_streain::do_scanf, octave_base_streain::do_oscanf):\n\tUse it.\n\t(scanf_format_list::finish_conversion): `%' counts as a conversion too.\n\tAlso don't forget to set type for it.\n\t(OCTAVE_SCAN_0): Delete.\n\t(OCTAVE_SCAN): Rename from OCTAVE_SCAN_1.\n\t(octave_base_stream::scanf, octave_base_stream::oscanf): Don't\n\tspecial-case number of conversions here.\n\t(octave_base_stream::oscanf, octave_base_stream::do_oscanf): Only\n\tcycle through fmt elements if the number of conversions is greater\n\tthan 0.\n\n\t* oct-stream.h (scanf_format_list::next): New arg, `cycle'.\n\t(printf_format_list::next): New arg, `cycle'.\n\t(printf_format_list::last_elt_p): New function.\n\t(printf_format_elt): New fields fw, prec, and flags.\n\tDefine copy constructor and assignment operator.\n\t(scanf_format_elt): Define copy constructor and assignment operator.\n\n2000-03-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (OCTAVE_SCAN_0, OCTAVE_SCAN_1): New macros.\n\t(do_scanf_conv, BEGIN_S_CONVERSION, BEGIN_CHAR_CLASS_CONVERSION,\n\tdo_scanf, scanf, do_oscanf, do_oscanf, oscanf): Use them instead\n\tof calling istream::scan directly.\n\t(octave_scan): New function.\n\t(do_scanf_conv): Second arg is now scanf_format_elt instead of char*.\n\tChange all callers.\n\n\t* oct-procbuf.h, oct-procbuf.cc (octave_procbuf):\n\tDerive from c_file_ptr_buf instead of filebuf.\n\n\t* oct-stream.cc (octave_base_stream::printf): Use octave_format\n\tinstead of ostream::form.  Return number of characters written.\n\n2000-03-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (do_printf_conv): Use octave_format instead of\n\tostream::form.  Return number of characters written.\n\t(octave_base_stream::do_printf): Return number of characters written.\n\n\t* error.cc (verror, vwarning): Use octave_format instead of\n\tostream::vform.\n\n\t* utils.cc (octave_format, octave_vformat): New functions.\n\t* cutils.c (octave_snprintf, octave_vsnprintf): New functions.\n\n\t* oct-lvalue.h (dummy_val): New static variable.\n\t(octave_lvalue::octave_lvalue): Use it to initialize val.\n\n\t* variables.cc (is_valid_function): Look in the global symbol\n\ttable for functions.\n\n2000-03-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (LIBRARIES): Conditionally define.\n\t(libraries): Depend on $(LIBRARIES).\n\t(octave): Depend on $(LIBRARIES), not libraries.  Also depend on\n\tstamp-prereq and stamp-oct-links.\n\t(all): Don't depend on stamp-prereq or stamp-oct-links.\n\t(liboctinterp.$(LIBEXT), liboctinterp.$(SHELXT)): Delete target\n\tbefore rebuilding.\n\n2000-03-21  Ben Sapp  <bsapp@nua.lampf.lanl.gov>:\n\n\t* Makefile.in (libraries): Depend only on library targets, not\n\tarchive members.\n\n2000-03-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (objects): New target\n\n\t* c_file_ptr_stream.h, c_file_ptr_stream.cc: New files.\n\t* oct-stdstrm.h, oct-stdstrm.cc, oct-prcstrm.cc:\n\tUse c_file_ptr_buf, i_c_file_ptr_stream, and o_c_fie_ptr_stream\n\tinstead of stdiobuf, istdiostream, and ostdiostream.\n\n\t* pr-output.cc (set_real_format, set_real_matrix_format,\n\tset_complex_format, set_complex_matrix_format, set_range_format):\n\tDo the right thing again for int, NaN, and Inf values.\n\n2000-03-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (pr_plus_format): Rename from do_plus_format.\n\tChange all callers.\n\t(pr_float, pr_complex): New arg, scale.  Handle scaling here.\n\t(float_format): New class for managing details of formatting\n\tfloats.  Use it instead of character string formats and the\n\tnonstandard form() function from the GNU iostream library.\n\n2000-02-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (clean): Also delete gendoc.\n\n2000-02-18  James R. Van Zandt  <jrv@vanzandt.mv.com>\n\n\t* load-save.cc (Vcrash_dumps_octave_core): Fix comment for this var.\n\n2000-02-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (handle_number): Don't transorm `[Dd]' to `e' if reading\n\thex.\n\n2000-02-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-inc): Install files in\n\t$(octincludedir)/octave.\n\t(uninstall): Remove them from the correct directory too.\n\n\t* defaults.h, defaults.cc (Vlocal_ver_arch_lib_dir): New variable.\n\t* defaults.cc (set_default_local_ver_arch_lib_dir): New function.\n\t(install_defaults): Call it.\n\t(exec_path): Prepend the versioned form of the local arch lib\n\tdirectory to the standard path.\n\t* defaults.h.in (OCTAVE_LOCALVERARCHLIBDIR,\n\tOCTAVE_LOCALVERFCNFILEDIR, OCTAVE_LOCALVEROCTFILEDIR):\n\tSubstitute these too.\n\t* toplev.cc (Foctave_config_info): Add them to the struct.\n\n2000-02-08  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (Foctave_config_info): Add MKOCTFILE_INCFLAGS to the\n\tstruct.\n\t* oct-conf.h.in (OCTAVE_CONF_MKOCTFILE_INCFLAGS): Define.\n\n2000-02-07  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/balance.cc (Fbalance): Explicitly request\n\tconversion from Matrix to ComplexMatrix.\n\t* DLD-FUNCTIONS/qz.cc (Fqz): Likewise.\n\n\t* ov-re-mat.h (octave_matrix::complex_matrix_value): Explicitly\n\trequest conversion from Matrix type.\n\n\t* ov-ch-mat.h (octave_char_matrix::matrix_value): Explicitly\n\trequest conversion from charMatrix type.\n\t(octave_char_matrix::complex_matrix_value): Likewise.\n\t* ov-bool-mat.h (octave_bool_matrix::matrix_value): Likewise.\n\t(octave_bool_matrix::complex_matrix_value): Likewise.\n\n\t* ov-range.h (octave_range::complex_matrix_value): Explicitly\n\trequest conversion from Matrix type.\n\n\t* ov-cx-mat.h, ov-re-mat.h: Explicitly request conversions from\n\tdiagonal matrix types in constructors.\n\n\t* mappers.cc (ximag, xreal): Return double, not Complex.\n\n\t* error.cc (panic): Turn off buffering of error messages.\n\tDon't call flush_octave_stdout here, verror will do it for us.\n\t(verror): Don't call flush_octave_stdout if buffering error messages.\n\n\t* pt-except.cc (tree_try_catch_command::eval): Only restore\n\tbuffer_error_message value (by running the unwind_protect element\n\tfor it) if it has been saved.\n\n\t* help.cc (Ftype): Return value if nargout is NOT equal to zero.\n\tDelete unnecessary unwind_protect::begin_frame().\n\n\t* toplev.cc (octave_config_info): Stuff lots of new config info in\n\tthe struct.\n\n\t* oct-conf.h.in: Delete TARGET_HOST_TYPE.\n\n2000-02-04  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* siglist.c: Include <signal.h>.\n\n\t* lex.l (is_plot_keyword): Add minimum match length in call to\n\talmost_match.\n\n\t* Makefile.in (%.df : %.cc): Don't pass -c to compiler.\n\n2000-02-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-base-mat.cc: Include pr-output.h here.\n\n\t* DLD-FUNCTIONS/rand.cc (curr_rand_dist): Return const char *\n\tinstead of char *.\n\n\t* oct-fstrm.cc (octave_fstream::seek, octave_fstream::tell):\n\tCall pubseekoff instead of seekoff.\n\n\t* DLD-FUNCTIONS/dassl.cc (print_dassl_option_list): Use stream\n\tmanipulators instead of GNU iostream-specific form function.\n\t* DLD-FUNCTIONS/fsolve.cc (print_fsolve_option_list): Ditto.\n\t* DLD-FUNCTIONS/lsode.cc (print_lsode_option_list): Ditto.\n\t* DLD-FUNCTIONS/quad.cc (print_quad_option_list): Ditto.\n\t* pr-output.cc (pr_scale_header): Ditto.\n\n\t* sighandlers.h: Include signal.h here.\n\t* sighandlers.cc: Not here.\n\n\t* utils.cc: Include setjmp.h, not csetjmp.\n\t* toplev.cc: Ditto.\n\n\t* sighandlers.cc: Include signal.h, not csignal.\n\n\t* pt-plot.h: Don't include csignal.\n\t* toplev.cc: Ditto.\n\t* oct-hist.cc: Ditto.\n\t* octave.cc: Ditto.\n\t* pager.cc: Ditto.\n\t* input.cc: Ditto.\n\t* help.cc: Ditto.\n\n\t* pt-plot.cc (send_to_plot_stream): Use operator== and substr\n\tmethod to do limited-length string comparison.\n\t* input.cc (generate_completion): Likewise.\n\t* ov-dld-fcn.cc (octave_dld_function::octave_dld_function): Likewise.\n\t* ov-usr-fcn.cc (octave_user_function::mark_as_system_fcn_file):\n\tLikewise.\n\n\t* utils.cc (check_preference): Expect exact string matches.\n\t* variables.cc (ignore_function_time_stamp): Likewise.\n\t* lex.l (whitespace_in_literal_matrix): Likewise.\n\n\t* mappers.cc (xconj, ximag, xreal): New functions.  Use them in\n\tDEFUN_MAPPER calls.\n\n\t* defun-int.h (DEFUN_MAPPER_INTERNAL): Cast function pointer args\n\tto octave_mapper constructor.\n\n2000-02-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* procstream.cc (procstreambase::procstreambase,\n\tprocstreambase::open, procstreambase::close):\n\tCall std::ios::setstate, not set.\n\n\t* lex.l (plot_axes_token): Declare plot_axes as const char *.\n\tDeclare tmp const char **.\n\n\t* oct-procbuf.h: Include fstream, not streambuf.h.\n\n\t* load-save.cc (Fsave): Call pubseekoff instead of seekoff.\n\t* oct-strstrm.cc (octave_base_strstream::tell): Likewise.\n\t(octave_base_strstream::seek): Likewise.\n\n\t* oct-stream.cc (octave_base_stream::read): Rename count to char_count.\n\t(octave_base_stream::do_gets): Likewise.\n\n\t* octave-stream.cc (octave_base_stream::write): Rename flt_fmt to ffmt.\n\t(octave_base_stream::read): Likewise.\n\n\t* TEMPLATE-INST/SLStack-sym.cc: Delete meaningless `extern\n\ttemplate' declarations.\n\t* TEMPLATE-INST/Array-tc.cc: Ditto.\n\n\t* TEMPLATE-INST/Map-fnc.cc: Don't try to instantiate goodCHptr or\n\tCHptr_to_index here.\n\t* TEMPLATE-INST/Map-tc.cc: Likewise.\n\t* Map.h (CHNode::goodCHptr, CHNode::CHptr_to_index): Now member\n\tfunctions.  Change all callers.\n\n\t* load-save.cc (read_binary_file_header): Declare magic_len `const'.\n\n\t* token.h (token::token (const token&), token::operator=):\n\tDelete unnecessary definitions.\n\n\t* oct-stream.cc (octave_stream::mode_as_string): Use\n\tstd::ios::binary, not std::ios::bin.\n\t* load-save.cc (Fsave, Fload, save_user_variables): Likewise.\n\n\t* DLD-FUNCTIONS/qz.cc (Fqz): Use Array<int> class instead of\n\ttrying to create automatic int array with variable size.\n\n\t* variables.cc (F__dump_symbol_info__): Fix continuation char.\n\t* mappers.cc (Ftoupper): Likewise.\n\t* DLD-FUNCTIONS/besselj.cc (Fairy, Fbesselj): Likewise.\n\t* DLD-FUNCTIONS/chol.cc (Fchol): Likewise.\n\t* DLD-FUNCTIONS/det.cc (Fdet): Likewise.\n\t* DLD-FUNCTIONS/eig.cc (Feig): Likewise.\n\t* DLD-FUNCTIONS/gammainc.cc (gammainc): Likewise.\n\t* DLD-FUNCTIONS/givens.cc (givens): Likewise.\n\t* DLD-FUNCTIONS/hess.cc (hess): Likewise.\n\t* DLD-FUNCTIONS/inv.cc (inv): Likewise.\n\t* DLD-FUNCTIONS/log.cc (logm): Likewise.\n\t* DLD-FUNCTIONS/lu.cc (lu): Likewise.\n\t* DLD-FUNCTIONS/qr.cc (qr): Likewise.\n\t* DLD-FUNCTIONS/schur.cc (schur): Likewise.\n\t* DLD-FUNCTIONS/balance.cc (balance): Likewise.\n\t* DLD-FUNCTIONS/svd.cc (svd): Likewise.\n\t* DLD-FUNCTIONS/syl.cc (syl): Likewise.\n\t* DLD-FUNCTIONS/expm.cc (Fexpm): Likewise.\n\n\t* token.h (token::token_type, token::end_tok_type,\n\ttoken::plot_tok_type): Delete extraneous comma from enum decls.\n\t* load-save.cc (load_save_format): Likewise.\n\n\t* pt-idx.cc (tree_index_expression::tree_index_expression):\n\tDelete default arg values.\n\t* oct-fstrm.cc (octave_fstream::octave_fstream): Likewise.\n\t* oct-stream.cc (octave_stream::octave_stream): Likewise.\n\n\t* siglist.h, siglist.c: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\t* siglist.c (sys_siglist): Move definition here from sighandlers.cc.\n\t* siglist.h (sys_siglist): Move declaration here from sighandlers.h.\n\n\t* ov.h, ov-bool.h, ov-bool-mat.h (bool_matrix_value):\n\tDelete unnecessary arg.\n\n\t* ov.h (octave_value::do_multi_index_op): Rename from do_index_op.\n\n\t* ov-fcn.h (octave_function::is_system_fcn_file): Now const.\n\n\t* Map.cc (index_to_CHptr): Now a macro.\n\t(CHMap<C>::hash): Now a member function.\n\n\t* defun-int.h (UNDERSCORIFY): New macro.\n\t(DEFCONST_INTERNAL, DEFCONSTX_INTERNAL): Use it.\n\n\t* data.cc (Fis_list): Fix continuation char.\n\t* defaults.cc (IMAGEPATH): Likewise.\n\n\t* Map.cc (CHptr_to_index, goodCHptr): Delete static decl.\n\n\t* ov.h (unary_op, binary_op, assign_op): Prepend `op_' to elts.\n\tChange all usses\n\n\t* All source files: Sprinkle with std:: qualifier as needed.\n\n2000-01-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (install_signal_handlers): Add std:: qualifier\n\tfor set_net_handler.\n\n\t* All source files: Include iostream, fstream, strstream,\n\tetc. as needed instead of using forward declarations for these\n\tclasses.\n\n2000-01-30  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (input_event_hook, Finput_event_hook): New functions.\n\t(hook_fcn, user_data): New static variables.\n\n2000-01-28  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-except.cc (do_catch_code): Don't do anything special for\n\ttree_return_command::returning, or tree_break_command::breaking.\n\n\t* error.cc (vwarning): New function.\n\t(warning): Use it instead of calling verror.\n\n\t* oct-stream.cc (octave_base_stream::oscanf):\n\tResult is now always nconv+1 elements.  Return count of successful\n\tconversions in last element.\n\t* file-io.cc (Ffscanf, Fsscanf, Fscanf): Fix doc string.\n\n\t* pt-except.cc (do_catch_code): Unwind-protect buffer_error_messages.\n\tBe sure to run all unwind-protects before returning.\n\t(tree_try_catch_command::eval): Add do_catch_code cleanup function\n\tto unwind-protect stack before resetting buffer_error_messages.\n\tUse unwind-protect to save and restore buffer_error_messages.\n\tIf there is no catch code, discard the cleanup function and run\n\tthe unwind-protect for buffer_error_messages.\n\n\t* error.cc (bind_global_error_variable): Avoid dereferencing\n\terror_message_buffer if it is NULL.\n\n\t* parse.y (evaluating_function_body): New global flag.\n\t* ov-usr-fcn.cc (octave_user_function::do_index_op):\n\tProtect and set it here.\n\t* parse.y (make_break_command, make_return_command): Check it here.\n\n\t* error.cc (warning_state): New global flag.\n\t(warning): Set it here.\n\t* lex.l (reset_parser): Clear it here.\n\t* parse.y (fold): Check it here.\n\n2000-01-27  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-walk.h (tree_walker::visit_do_until_command): New pure virtual.\n\t* pt-pr-code.cc (tree_print_code::visit_do_until_command):\n\tNew function.\n\t* pt-loop.h (tree_do_until_command): New class.\n\t(tree_while_command::expr, tree_while_command::list):\n\tNow protected instead of private.\n\t* parse.y (make_do_until_command): New function.\n\t(loop_command): Recognize do-until statement.\n\t(DO, UNTIL): New tokens.\n\n\t* input.cc (match_sans_spaces): Require non-blank part of test\n\tstring to match standard string exactly.\n\n2000-01-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.h (scanf_format_elt::char_class): New struct elt.\n\tAdd arg to constructor.\n\t(scanf_format_elt::special_conversion): New enum.\n\t* oct-stream.cc (scanf_format_list::add_elt_to_list): New arg,\n\tchar_class.  Pass it to scanf_format_elt constructor.\n\t(scanf_format_list::scanf_format_list): Create separate list\n\telements for whitespace and literal conversions.\n\t(expand_char_class): New function.\n\t(scanf_format_list::finish_conversion): Extract character class\n\t(not including the delimiting brackets) and expand the list of\n\tcharacters.  Pass the result to add_elt_to_list.\n\t(scanf_format_list::all_character_conversions): Also accept '^',\n\tscanf_format_elt::literal_conversion, and\n\tscanf_format_elt::whitespace_conversion types too.\n\t(DO_WHITESPACE_CONVERSION, BEGIN_CHAR_CLASS_CONVERSION,\n\tBEGIN_C_CONVERSION, BEGIN_S_CONVERSION, DO_LITERAL_CONVERSION):\n\tNew macros.\n\t(octave_base_stream::do_scanf, octave_base_stream::do_oscanf):\n\tUse them to avoid code duplication.\n\tHandle whitespace, literal text, and character class conversions.\n\t(octave_base_stream::oscanf): Loop over all format list elements,\n\tnot just the first nconv elements.  Clear status flags on is for\n\tall streams.\n\n2000-01-25  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* xdiv.cc (result_ok): Just check value of info.\n\t(solve_singularity_warning): New function.\n\t(xleftdiv, xdiv): Pass pointer to solve_singularity_warning to\n\tsolve function.\n\n\t* lex.l (handle_identifier): Set next_tok_is_eq if we are looking\n\tat `=', but not if we are looking at `=='.\n\n\t* pt-pr-code.cc (tree_print_code::visit_unwind_protect_command):\n\tPrint `unwind_protect_cleanup', not `cleanup_code'.\n\n\t* pager.cc (octave_pager_buf::flush_current_contents_to_diary):\n\tNew function.\n\t(octave_pager_stream::flush_current_contents_to_diary):\n\tDitto.\n\t(close_diary_file): Use the new octave_pager_stream function to\n\ttry to flush the current buffer to the diary when it is closed.\n\n\t* variables.cc (Fexist): Return 6 for built-in constants.\n\n\t* pt-plot.cc (Fgshow): Don't append \" \" after last arg.\n\t(Fgset): Likewise.\n\n2000-01-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-base-mat.h (octave_base_matrix::length): Return 0 for empty\n\tarrays.\n\n2000-01-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/time.cc (Fstrptime): New function.\n\n\t* load-save.cc (Fsave): Add missing else.\n\n2000-01-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/gammainc.cc (Fgammainc): Texinfoize doc string.\n\t* ov-typeinfo.cc (Ftypeinfo): Ditto.\n\t* parse.y (Vwarn_future_time_stamp): Ditto.\n\t* DLD-FUNCTIONS/minmax.cc (Fmax, Fmin): Ditto.\n\t* ov-usr-fcn.cc (Fva_arg, Fva_start, Fvr_val): Ditto.\n\t* defaults.cc (VOCTAVE_HOME, Frehash): Ditto.\n\t* toplev.cc (Fwarranty, Fcasesen): Ditto.\n\t* utils.cc (Fdo_string_escapes, Ffile_in_loadpath): Ditto.\n\t* variables.cc (F__dump_symtab_info__, F__dump_symbol_info__): Ditto.\n\t* ov-list.cc (Flist, Fappend, Fnth, Freverse, Fsplice): Ditto.\n\t* input.cc (Fread_readline_init_file): Ditto.\n\t* file-io.cc (Fis_stream): Ditto.\n\t* ov-cell.cc (Fiscell, Fcell): Ditto.\n\t* pt-assign.cc (Vprint_rhs_assign_val): Ditto.\n\t* pt-decl.cc (Vinitialize_global_variables): Ditto.\n\t* symtab.cc (Vvariables_can_hide_functions): Ditto.\n\n\t* pt-plot.cc (Fgraw, Fgset, Fgshow, Vgnuplot_command_plot,\n\tVgnuplot_command_replot, Vgnuplot_command_splot,\n\tVgnuplot_command_using, Vgnuplot_command_with,\n\tVgnuplot_command_axes, Vgnuplot_command_title,\n\tVgnuplot_command_end): Texinfoize doc strings.\n\n\t* oct-procbuf.cc (__kluge_procbuf_delay__): Rename from\n\tkluge_procbuf_delay.  Texinfoize doc string.\n\n2000-01-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (gobble_leading_whitespace): Discard first space character\n\tafter consecutive comment characters.\n\t* lex.l (grab_help_text): Ditto.\n\n\t* lex.l (Vwhitespace_in_literal_matrix, Vwarn_separator_insert,\n\tVwarn_single_quote_string): Texinfoize doc string.\n\n2000-01-11  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h, ov.cc (octave_value::column_vector_value,\n\toctave_value::row_vector_value,\n\toctave_value::complex_column_vector_value,\n\toctave_value::complex_row_vector_value): New functions.\n\t(octave_value::vector_value): Now returns Array<double>.\n\t(octave_value::complex_vector_value): Now returns Array<Complex>.\n\tSprinkle conversions where necessary.\n\n\t* ov.cc (Vprefer_column_vectors): Now static.\n\t* ov.h (octave_value (const ComplexRowVector&),\n\toctave_value (const ComplexColumnVector&),\n\toctave_value (const RowVector&), octave_value (const ColumnVector&)):\n\tDelete second arg.  Change all callers.\n\n\t* oct-obj.h (octave_value_list (const RowVector&),\n\toctave_value_list (const ColumnVector&),\n\toctave_value_list (const ComplexRowVector&),\n\toctave_value_list (const ComplexColumnVector&)): Likewise.\n\t* ov-cx-mat.h, ov-cx-mat.cc\n\t(octave_complex_matrix (const ComplexRowVector&),\n\t(octave_complex_matrix (const ComplexColumnVector&)):\n\tDelete second arg, simply create object with orientation\n\tcorresponding to vector arg.  Move constructors to class decl.\n\t* ov-re-mat.h, ov-re-mat.cc (octave_matrix (const RowVector&),\n\t(octave_matrix (const ColumnVector&)):\n\tDelete second arg, simply create object with orientation\n\tcorresponding to vector arg.  Move constructors to class decl.\n\n2000-01-07  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* mappers.cc (Fconj, Ferf, Ferfc, Fgamma, Fimag, Flgamma, Flog10,\n\tFreal, Fround): Add @seealso{...} to doc strings.\n\n2000-01-06  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (do_scanf): Do the right thing again for character\n\tconversions.\n\n\t* help.cc (display_help_text): Also strip out leading spaces\n\tbefore Texinfo @-commands before sending doc string to makeinfo.\n\t(display_help_text): Improve format of `See also' string.\n\n2000-01-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (display_help_text): Pass a definition for @seealso\n\tthrough the filter.\n\n1999-12-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (Vwarn_single_quote_string): New variable.\n\t(syms_of_lex): DEFVAR it.\n\t(warn_single_quote_string): New function.\n\t(gripe_single_quote_string): New function.\n\tUse new stuff to allow warnings for code that uses single quote\n\tcharacters to introduce string constants.\n\n1999-12-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkbuiltins: Add #undef quad to generated file.\n\n1999-12-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (Vwarn_separator_insert): New variable.\n\t(syms_of_lex): DEFVAR it.\n\t(warn_separator_insert): New function.\n\t(maybe_warn_separator_insert): New function.\n\tUse new stuff to allow warnings for code that might result in\n\tauto-insertion of commas or semicolons, depending on the value of\n\twhitespace_in_literal_matrix.\n\n\t* parse.y (Fsource): Record function file name here too.\n\n1999-12-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (link_to_global_variable): If the local symbol is\n\tnot a variable, don't bother to clear it.  Instead, just redefine\n\tit by aliasing to the global symbol.\n\n1999-11-23  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/balance.cc (Fbalance): Texinfoize doc string.\n\t* DLD-FUNCTIONS/det.cc (Fdet): Ditto.\n\t* DLD-FUNCTIONS/eig.cc (Feig): Ditto.\n\t* DLD-FUNCTIONS/givens.cc (Fgivens): Ditto.\n\t* DLD-FUNCTIONS/inv.cc (Finv): Ditto.\n\t* DLD-FUNCTIONS/chol.cc (Fchol): Ditto.\n\t* DLD-FUNCTIONS/hess.cc (Fhess): Ditto.\n\t* DLD-FUNCTIONS/lu.cc (Flu): Ditto.\n\t* DLD-FUNCTIONS/qr.cc (Fqr): Ditto.\n\t* DLD-FUNCTIONS/schur.cc (Fschur): Ditto.\n\t* DLD-FUNCTIONS/svd.cc (Fsvd): Ditto.\n\t* DLD-FUNCTIONS/expm.cc (Fexpm): Ditto.\n\t* DLD-FUNCTIONS/log.cc (Flogm, Fsqrtm): Ditto.\n\t* DLD-FUNCTIONS/syl.cc (Fsyl): Ditto.\n\t* DLD-FUNCTIONS/pinv.cc (Fpinv): Ditto.\n\t* DLD-FUNCTIONS/qz.cc (Fqz): Ditto.\n\t* DLD-FUNCTIONS/dassl.cc (Fdassl, Fdassl_options): Ditto.\n\t* DLD-FUNCTIONS/lsode.cc (Flsode, Flsode_options): Ditto.\n\t* data.cc (Flength, Fsize, Fisempty): Ditto.\n\t* sysdep.cc (Fkbhit): Ditto.\n\t* input.cc (Fkeyboard, Finput): Ditto.\n\t* variables.cc (ans): Ditto.\n\t* pr-output.cc (Fdisp, Fformat): Ditto.\n\t* ov.cc (Vprint_answer_id_name): Ditto.\n\t* defaults.cc (IMAGEPATH): Ditto.\n\t* error.cc (Ferror, Fwarning, Fusage, error_text, beep_on_error):\n\tDitto.\n\t* load-save.cc (Fload, Fsave, Vdefault_save_format,\n\tVsave_precision): Ditto.\n\t* file-io.cc (Ffflush, Ffopen, Ffclose, Ffputs, Ffgetl, Ffgets,\n\tFfprintf, Fsprintf, Fscanf, Ffscanf, Fsscanf, Ffread, Ffwrite,\n\tFfseek, Fftell, Ffeof, Fferror, Ffreport, Ftmpnam, Vstdin_file,\n\tVstdout_file, Vstderr_file, SEEK_SET, SEEK_CUR, SEEK_END): Ditto.\n\t* pager.cc (Vpager_binary, Vpage_output_immediately,\n\tVpage_screen_output, Fmore): Ditto.\n\n1999-11-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (Vtreat_neg_dim_as_zero): Texinfoize doc string.\n\t* DLD-FUNCTIONS/find.cc (Ffind): Ditto.\n\t* DLD-FUNCTIONS/rand.cc (Frand, Frandn): Ditto.\n\t* DLD-FUNCTIONS/sort.cc (Fsort): Ditto.\n\t* mappers.cc (Fisinf, Fisnan, Ffinite): Ditto.\n\t* data.cc (Fall, Fany, Fdiag, Fones, Fzeros, Feye, Flinspace): Ditto.\n\t* defaults.cc (Vloadpath, Vdefault_loadpath): Ditto.\n\t* parse.y (Feval, Ffeval, Vdefault_eval_print_flag,\n\tVwarn_missing_semicolon, Vwarn_function_name_clash, Fsource): Ditto.\n\t* ov-usr-fcn.cc (Vmax_recursion_depth, Vdefault_return_value,\n\tVdefine_all_return_values, Vreturn_last_computed_value): Ditto.\n\t* ov.cc (Vok_to_lose_imaginary_part, Vdo_fortran_indexing,\n\tVprefer_column_vectors, Vresize_on_range_error,\n\tVwarn_divide_by_zero): Ditto.\n\t* pt-stmt.cc (Vsilent_functions): Ditto.\n\t* variables.cc (Vignore_function_time_stamp): Ditto.\n\t* dynamic-ld.cc (Vwarn_reload_forces_clear): Ditto.\n\n1999-11-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/fft.cc (Ffft): Texinfoize doc string.\n\t* DLD-FUNCTIONS/ifft.cc (Fifft): Ditto.\n\t* DLD-FUNCTIONS/fft2.cc (Ffft2): Ditto.\n\t* DLD-FUNCTIONS/ifft2.cc (Fifft2): Ditto.\n\t* DLD-FUNCTIONS/filter.cc (Ffilter): Ditto.\n\t* DLD-FUNCTIONS/quad.cc (Fquad, Fquad_options): Ditto.\n\t* DLD-FUNCTIONS/colloc.cc (Fcolloc): Ditto.\n\t* DLD-FUNCTIONS/fsolve.cc (Ffsolve, Ffsolve_options): Ditto.\n\t* defaults.cc (Veditor): Ditto.\n\t* pt-plot.cc (Vautomatic_replot, Vgnuplot_binary,\n\tVgnuplot_has_frames, Vgnuplot_has_multiplot, Fclearplot,\n\tFcloseplot, Fpurge_tmp_files, Fishold, Fhold):\n\n\t* Makefile.in (parse.cc): Expect 11 shift/reduce conflicts now.\n\n1999-11-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (Vwarn_assign_as_truth_value,\tVwarn_variable_switch_label):\n\tTexinfoize doc strings.\n\n\t* DLD-FUNCTIONS/pinv.cc (Fpinv): Texinfoize doc string.\n\n\t* defun-int.h (DEFUN_DLD_INTERNAL): New macro.\n\t* defun-dld.h [MAKE_BUILTINS] (DEFUN_DLD): Simply expand to\n\tDEFUN_DLD_INTERNAL.\n\t* mkbuiltins: Generate code to define DEFUN_DLD_INTERNAL.\n\t* mkgendoc: Likewise.\n\n\t* Makefile.in (gendoc.o): Don't optimize when creating gendoc.\n\t(%.dc : %.cc): Delete rule.\n\n\t* pt-decl.cc (Vdefault_global_variable_value): Texinofize doc string.\n\t* variables.cc (Fclear, Fdocument, Fexist, Fis_global, Fwho): Ditto.\n\t* help.cc (Ftype, Fwhich): Ditto.\n\t* ov.cc (Vstruct_levels_to_print, Vimplicit_str_to_num_ok): Ditto.\n\t* data.cc (Fis_struct, Fstruct_elements, Fstruct_constains): Ditto.\n\t* strfns.cc (Fisstr, Fsetstr): Ditto.\n\t* pt-mat.cc: (Fimplicit_num_to_str_ok, Fstring_fill_char): Ditto.\n\t* utils.cc (Fundo_string_escapes): Ditto.\n\t* mappers.cc: (Fisalnum, Fisalpha, Fisascii, Fiscntrl, Fisdigit,\n\tFisgraph, Fislower, Fisprint, Fispunct, Fisspace, Fisupper,\n\tFisxdigit, Ftoascii, Ftolower, Ftoupper): Ditto.\n\n1999-11-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* syscalls.cc (symbols_of_syscalls): Use DEFCONSTX to define\n\tOctave constants for C macros like O_WRONLY.\n\n\t* oct-lvalue.cc (octave_lvalue::set_index): Disallow expressions\n\tlike x(i)(j) = rhs.\n\n1999-11-17  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* symtab.cc (symbol_record::type_as_string): New function.\n\n\t* symtab.cc (symbol_record::which): New functions.\n\t* help.cc (do_which): New functions.\n\t(Fwhich): Use them.\n\n\t* help.cc (help_from_symbol_table, help_from_file): New functions.\n\t(builtin_help): Use them.\n\n\t* help.cc (do_type): New function.\n\t(symbol_record::type): New function.\n\t(Ftype): Use them.\n\n\t* help.cc (print_symbol_type): Delete.\n\n\t* symtab.cc (symbol_table::name_list): Delete count arg.\n\t(symbol_table::symbol_list): Likewise.\n\t(symbol_table::glob): Likewise.  Also return Array<symbol_record *>\n\tinstead of symbol_record **.\n\tChange all callers.\n\t* help.cc (names, display_symtab_names): Delete count arg.\n\n\t* help.cc (print_symbol_type, Ftype): No longer need to look up\n\tfcn_file_name in the loadpath.\n\n\t* help.cc (print_symbol_type): Handle dld functions.\n\t(help_from_symbol_table, help_from_file): New functions.\n\t(builtin_help): Use them.\n\n1999-11-16  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-cell.cc (Fiscell, Fcell): New Functions.\n\t(octave_cell::do_index_op): New function.\n\n\t* utils.cc (get_dimensions): Move here from data.cc and make extern.\n\t(Vtreat_neg_dim_as_zero, treat_neg_dim_as_zero): Likewise.\n\t(symbols_of_utils): New function.\n\n\t* data.cc (fill_matrix (const octave_value_list&, double,\n\tconst char*)): New function.\n\t(Fones, Fzeros): Use it to avoid some code duplication.\n\n1999-11-15  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-cell.h, pt-cell.cc, ov-cell.h, ov-cell.cc, Cell.h, Cell.cc:\n\tNew files.\n\t* Makefile.in: Add them to the appropriate lists.\n\t* pt-walk.h (visit_cell (tree_cell&): New pure virtual.\n\t* pt-pr-code.cc (tree_print_code::visit_cell (tree_cell&)): New\n\tfunction.\n\t* TEMPLATE-INST/Array-tc.cc: Instantiate 2D arrays of octave_value\n\tobjects.\n\t* pt-all.h: Include pt-cell.h.\n\t* ov.h, ov.cc (octave_value::is_cell, octave_value::cell_value):\n\tNew functions.\n\t* ov-base.h, ov-base.cc (octave_value::is_cell,\n\toctave_value::cell_value): Provide defaults.\n\t* lex.h, lex.l: Handle `{' and `}' tokens (for cell arrays).\n\t(bracketflag): Rename from braceflag.\n\t(handle_close_bracket): Rename from handle_close_brace.\n\t(class bracket_brace_paren_nesting_level): Rename from\n\tbrace_paren_nesting_level.\n\t(bracket_brace_paren_nesting_level::bracket,\n\tbracket_brace_paren_nesting_level::is_bracket): New functions to\n\tkeep count of nesting level for `[' and `]'.\n\t(bracket_brace_paren_nesting_level::brace,\n\tbracket_brace_paren_nesting_level::is_brace): Now keeps count of\n\tnesting level for `{' and `}'.\n\t* parse.y (tree_cell_type): New type.\n\tGive '{' the same precedence and associativity as '(' and '.'\n\t(matrix_rows, matrix_rows1): Rename from rows, rows1.\n\t(cell, cell_rows, cell_rows1): New non-terminals.\n\t(cell_or_matrix_row): Rename from matrix_row.\n\t(primary_expr): Accept cell here.\n\t(postfix_expr): Allow indexing using '{' arg_list '}'.\n\t(finish_cell): New function.\n\n1999-11-12  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (jump_to_top_level): No longer declared extern \"C\".\n\n\t* cutils.c (octave_strcasecmp, octave_strncasecmp): New functions.\n\t* utils.cc (almost_match): Call octave_strncasecmp instead of\n\tcalling strncasecmp directly.\n\n1999-11-10  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y: Don't define warn_reload_forces_clear here.\n\n\t* Makefile.in (DISTFILES): Include DOCSTRINGS.\n\n1999-11-05  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (install_signal_handlers): Don't install\n\tsigwinch_handler.\n\n\t* oct-iostrm.h (octave_istream::eof, octave_ostream::eof): Provide\n\timplementation for these.\n\n\t* oct-stream.cc (octave_base_stream::do_scanf):\n\tThe stdin stream is only special if we are interactive.\n\t(octave_base_stream::scanf): Ditto.\n\t(octave_base_stream::do_oscanf): Ditto.\n\t(octave_base_stream::oscanf): Ditto.\n\n\t* ov.h (octave_value::is_stream): New predicate.\n\t* ov-file.h (octave_file::is_stream): Return true.\n\t* file-io.cc (Fis_stream): New function.\n\n\t* ov-file.h (class octave_file): stream is now an object instead\n\tof pointer.\n\t* ov-file.cc (octave_file::print_raw): Handle stream as object\n\tinstead of pointer.  Also print stream status.\n\n\t* ov-base.cc (octave_base_value::stream_value): Return object\n\tinstead of pointer.\n\n\t* ov.cc (octave_value::stream_value): Return object instead of pointer.\n\t(octave_value::octave_value (const octave_stream&)): Take const\n\treference instead of pointer arg.\n\n\t* TEMPLATE-INST/Array-os.cc: Instantiate Arrays of octave_stream\n\tobjects, not pointers to them.\n\n\t* OPERATORS/op-fil-b.cc: Cope with octave_stream class changes.\n\t* OPERATORS/op-fil-bm.cc: Likewise.\n\t* OPERATORS/op-fil-cm.cc: Likewise.\n\t* OPERATORS/op-fil-cs.cc: Likewise.\n\t* OPERATORS/op-fil-lis.cc: Likewise.\n\t* OPERATORS/op-fil-m.cc: Likewise.\n\t* OPERATORS/op-fil-rec.cc: Likewise.\n\t* OPERATORS/op-fil-s.cc: Likewise.\n\t* OPERATORS/op-fil-str.cc: Likewise.\n\t* file-io.cc: Likewise.\n\t* syscalls.cc (Fdup): Likewise.\n\n\t* oct-fstrm.cc, oct-fstrm.h, oct-iostrm.cc, oct-iostrm.h,\n\toct-prcstrm.cc, oct-prcstrm.h, oct-stdstrm.cc, oct-stdstrm.h,\n\toct-stream.cc, oct-stream.h, oct-strstrm.cc, oct-strstrm.h:\n\tRewrite to allow octave_stream objects to be used like values\n\tinstead of having to use pointers.\n\n1999-11-03  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_base_stream::do_scanf): If it looks like\n\twe have a matching failure, then reset the failbit in the stream\n\tstate.\n\t(octave_base_stream::do_oscanf): Likewise.\n\n1999-11-02  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* help.cc (Fhelp): Texinfoize doc string.\n\t* input.cc (Fecho, Fcompletion_matches): Ditto.\n\t* oct-hist.cc (Fedit_history, Fhistory, Frun_history): Ditto.\n\t* pager.cc (Fdiary): Ditto.\n\t* sysdep.cc (Fclc): Ditto.\n\t* toplev.cc (Fquit, Fatexit): Ditto.\n\n1999-11-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (yywrap): No longer static.\n\t(have_continuation): Declare input character as int, not char, so\n\tcomparison to EOF will work.\n\n1999-11-01  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defun.cc (print_usage): Use display_help_text instead of sending\n\thelp message directly to octave_stdout.\n\n1999-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defun-dld.h (INSTALL_DLD_FCNS, INSTALL_DLD_FCN): Delete definitions.\n\t* DLD-FUNCTIONS/dassl.cc: Don't use INSTALL_DLD_FCN or\n\tINSTALL_DLD_FCNS macros.  They are not necessary with the new code\n\tin dynamic-ld.cc.\n\t* DLD-FUNCTIONS/lsode.cc: Ditto.\n\t* DLD-FUNCTIONS/fsolve.cc: Ditto.\n\t* DLD-FUNCTIONS/quad.cc: Ditto.\n\t* DLD-FUNCTIONS/time.cc: Ditto.\n\t* DLD-FUNCTIONS/besselj.cc: Ditto.\n\t* DLD-FUNCTIONS/getgrent.cc: Ditto.\n\t* DLD-FUNCTIONS/getpwent.cc: Ditto.\n\t* DLD-FUNCTIONS/inv.cc: Ditto.\n\t* DLD-FUNCTIONS/log.cc: Ditto.\n\t* DLD-FUNCTIONS/minmax.cc: Ditto.\n\t* DLD-FUNCTIONS/rand.cc: Ditto.\n\n\t* dynamic-ld.cc, dynamic-ld.h: Major rewrite to allow reloading of\n\tdynamically linked functions.\n\n\t* symtab.cc (symbol_record::replace_all_defs): Don't allow top\n\tdefinition to be NULL.\n\t(symbol_table::clear): Allow dynamically linked functions to be\n\tcleared.\n\n\t* symtab.h (TYPE): New enum value, DLD_FUCTION.\n\t(symbol_type): Now 8 bits wide.\n\t(SYMTAB_ALL_TYPES): Include DLD_FUNCTION.\n\t(symbol_record::symbol_def::is_function): Also recognize dld functions.\n\t(symbol_record::symbol_def::is_dld_function): New function.\n\t(symbol_record::is_dld_function): Ditto.\n\n\t* defun.cc (install_dld_function): New function.\n\t* defun-int.h: Provide declaration here.\n\t(octave_dld_fcn_installer): New typedef.\n\t(DEFINE_FUN_INSTALLER_FUN): Installer function now takes an\n\toct_shlib object as an arg.  Allow installation of a function to\n\thappen more than once.\n\n\t* octave.cc (initialize_error_handlers): Call\n\tset_liboctave_warning_handler here too.\n\n\t* ov-builtin.h (is_builtin_function): Return true.\n\tData member is now protected, not private.\n\n\t* ov-fcn.h (is_dynamically_loaded_function): New predicate.\n\t(unload): New function.\n\tData members are now protected, not private.\n\n\t* ov.h (is_builtin_function, is_dld_function): New predicates.\n\t* ov-base.h (is_builtin_function, is_dld_function): Ditto.\n\n\t* parse.y (Vwarn_reload_forces_clear): New static flag.\n\t(warn_reload_forces_clear): New function.\n\t(symbols_of_parse): DEFVAR warn_reload_forces_clear.\n\n\t* variables.cc (Fclear): Look for dld functions too.\n\n\t* ov-dld-fcn.cc, ov-dld-fcn.h: New files.\n\t* Makefile.in (OV_INCLUDES, OV_SRC): Add them to the lists.\n\n\t* Makefile.in (DEFVAR_PATTERN): Also match DEFCONSTX.\n\n1999-10-26  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLList.h, DLList.cc: New files.\n\t* Makefile.in (INCLUDES, DIST_SRC): Add them to the lists.\n\n\t* DLD-FUNCTIONS/lsode.cc (Flsode): Be sure to call\n\tunwind_protect::run_frame before returning.\n\t* DLD-FUNCTIONS/quad.cc (Fquad): Likewise.\n\t* DLD-FUNCTIONS/fsolve.cc (Ffsolve): Likewise.\n\t* DLD-FUNCTIONS/dassl.cc (Fdassl): Likewise.\n\n\t* load-save.cc (read_mat_ascii_data): When reading from\n\ttmp_stream, check its state, not the state of is.\n\n\t* defun-dld.h (INSTALL_DLD_FCN, INSTALL_DLD_FCNS): New macros.\n\t* DLD-FUNCTIONS/dassl.cc: Use them.\n\t* DLD-FUNCTIONS/lsode.cc: Ditto.\n\t* DLD-FUNCTIONS/fsolve.cc: Ditto.\n\t* DLD-FUNCTIONS/quad.cc: Ditto.\n\t* DLD-FUNCTIONS/time.cc: Ditto.\n\t* DLD-FUNCTIONS/besselj.cc: Ditto.\n\t* DLD-FUNCTIONS/getgrent.cc: Ditto.\n\t* DLD-FUNCTIONS/getpwent.cc: Ditto.\n\t* DLD-FUNCTIONS/inv.cc: Ditto.\n\t* DLD-FUNCTIONS/log.cc: Ditto.\n\t* DLD-FUNCTIONS/minmax.cc: Ditto.\n\t* DLD-FUNCTIONS/rand.cc: Ditto.\n\n\t* data.cc (Flinspace): Let linspace functions handle errors.\n\n\t* mkgendoc (print_doc_string): Handle quoted names.\n\n\t* file-io.cc (symbols_of_file_io): Use DEFCONSTX for SEEK_SET,\n\tSEEK_CUR, and SEEK_END.\n\n\t* defun.h (DEFCONST): Just pass name, defn, and doc to\n\tDEFCONST_INTERNAL.\n\t(DEFCONSTX): Likewise, pass name, defn, and doc to DEFCONSTX_INTERNAL.\n\t* defun-int.h [MKBUILTINS] (DEFCONST_INTERNAL): Likewise, pass\n\tname, defn, and doc to XDEFCONST_INTERNAL.\n\t[MKBUILTINS] (DEFCONSTX_INTERNAL): New macro.\n\t(INSTALL_CONST): New macro.\n\t[! MKBUILTINS] (DEFCONST_INTERNAL): Use it to handle details here.\n\t[! MKBUILTINS] (DEFCONSTX_INTERNAL): Ditto.\n\t* mkgendoc: Fix definition of XDEFCONST_INTERNAL to match.\n\t* mkbuiltins: Ditto.\n\n\t* mkdefs: Match spaces before BEGIN_INSTALL_BUILTIN.\n\n\t* Makefile.in (DEFUN_PATTERN): Also match DEFUN_MAPPER.\n\n1999-10-26  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* data.cc (VI, VInf, VJ, VNaN, Ve, Veps, Vfalse, Vi, Vinf, Vj,\n\tVnan, Vpi, Vrealmax, Vrealmin): Texinfoize doc strings.\n\t* mappers.cc (Fabs, Facos, Facosh, Fangle, Farg, Fasin, Fasinh,\n\tFatan, Fatanh, Fceil, Fconj, Fcos, Fcosh, Ferf, Ferfc, Fexp,\n\tFfinite, Ffix, Ffloor, Fgamma, Fimag, Flgamma, Flog, Flog10,\n\tFreal, Fround, Fsign, Fsin, Fsinh, Fsqrt, Ftan, Ftanh): Ditto.\n\n1999-10-23  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* data.cc (Fis_matrix): Texinfoize doc string.\n\t* ov.cc\t(Vpropagate_empty_matrices): Ditto.\n\t* pt-mat.cc: (Vempty_list_elements_ok): Ditto.\n\t* pr-output.cc (Vfixed_point_format, Voutput_max_field_width,\n\tVoutput_precision, Vprint_empty_dimensions, Vsplit_long_rows):\n\tDitto.\n\n1999-10-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-usr-fcn.cc (octave_user_function::do_index_op): If\n\tVmax_recursion_depth is exceeded, call unwind_protect::run_frame\n\tbefore returning.\n\n1999-10-21  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* cutils.c (do_octave_usleep): Handle useconds > 1e6.\n\n\t* variables.h (is_valid_function): Provide default values for the\n\tstring argument.\n\n\t* symtab.cc (variable_reference): Maybe print warning (or error)\n\tabout variables that hide functions of the same name.\n\t(symbol_record::define (const octave_value&, unsigned int)): Ditto.\n\t(Vvariables_can_hide_functions): New static variable.\n\t(variables_can_hide_functions, symbols_of_symtab): New functions.\n\n\t* cutils.c: New file.\n\t* Makefile.in (SOURCES): Add it to the list.\n\t* utils.h: Declare octave_usleep here.\n\t* dirfns.cc (Fls): Simply all octave_usleep.\n\t* oct-procbuf.cc (octave_procbuf::open): Ditto.\n\t* sysdep.cc (Fusleep): Ditto.\n\t* toplev.cc (run_command_and_return_output): Ditto.\n\n1999-10-20  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (make_diag (const octave_value&, const octave_value&)):\n\tDelete special cases for scalars and simply attempt conversion of\n\tfirst arg to a matrix value.  If that fails, we will still see an\n\terror message.\n\n\t* Makefile.in (DISTFILES): Add mkgendoc to the list.\n\n1999-10-19  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (stmp-pic): New target.\n\t($(PICOBJS)): Depend on stmp-pic, not pic.\n\n\t* ov.h (get_rep): New function.\n\n\t* help.cc (display_help_text): Pass definitions for VERSION,\n\tOCTAVE_HOME, and TARGETHOSTTYPE to makeinfo.\n\n\t* DLD-FUNCTIONS/getgrent.cc: Texinfoize all doc strings.\n\t* DLD-FUNCTIONS/getpwent.cc: Ditto.\n\t* DLD-FUNCTIONS/getrusage.cc: Ditto.\n\t* DLD-FUNCTIONS/time.cc: Ditto.\n\n\t* defaults.cc (EXEC_PATH, OCTAVE_VERSION): Texinfoize doc strings.\n\t* dirfns.cc (Fcd, Fls, Fpwd, Freaddir, Fmkdir, Frmdir, Frename,\n\tFglob, Ffnmatch): Ditto.\n\t* file-io.cc (Fpopen, Fpclose, Fumask): Ditto.\n\t* sysdep.cc (Fgetenv, Fputenv, Fpause, Fsleep, Fusleep, Fisieee,\n\tFtilde_expand): Ditto.\n\t* toplev.cc (Fcomputer, Fsystem, Foctave_config_info): Ditto.\n\t* utils.cc (Ffile_in_path): Ditto.\n\t* syscalls.cc (Fdup2, Fexec, Ffcntl, Ffork, Fgetpgrp, Fgetpid,\n\tFgetppid, Fgetegid, Fgetgid, Fgeteuid, Fgetuid, Fmkfifo, Fpipe,\n\tFstat, Funlink, Fwaitpid, F): Ditto.\n\t(Flstat): Refer to stat for doc.\n\n\t* help.cc (looks_like_texinfo): New function.\n\t(display_help_text): Use it to see if the doc string looks like\n\tTexinfo source.  If so, use makeinfo to format the text before\n\tdisplaying it.\n\n\t* mkgendoc: New script.\n\t* Makefile.in: Use it to create gendoc.cc, which is compiled and\n\trun to create DOCSTRINGS file from sources.\n\n1999-10-18  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (help_from_info): Print `unable to find info' message if\n\ttry_info returns 127; otherwise, print `not indexed' message.\n\tDon't sleep after printing `not indexed' message.\n\n1999-10-14  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (fold (tree_unary_expression *)): New function.\n\t(make_prefix_op, make_postfix_op): Use it.\n\n1999-10-13  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (oct-gperf.h): Ask for ANSI-C output from gperf\n\t(requires gperf-2.7 or later).\n\n\t* sighandlers.cc (sigwinch_handler): New function.\n\t(install_signal_handlers): Install it.\n\nThu Sep 23 19:49:36 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (Fsystem): For async case, use execl instead of\n\tsystem, avoiding the need to exit after executing the subprocess.\n\nThu Sep  9 17:09:23 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (get_size): Allow zero values.\n\t(get_size): New arg, one_elt_size_spec.\n\t(do_scanf_conv): New arg, `conv_count'.  Change instantiation\n\trequests and all callers.\n\t(octave_base_stream::do_scanf): Improve scanning of strings.\n\t(octave_base_stream::do_oscanf): Remove size limit on %s conversions.\n\n\t* oct-stream.cc (scanf_format_list::all_character_conversions):\n\tDon't count %p as a character conversion.\n\nTue Sep  7 08:31:04 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (set_real_matrix_format, set_complex_matrix_format):\n\tMove check for fixed_point_format ahead of check for\n\tint_or_inf_or_nan.\n\nThu Sep  2 11:54:51 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-obj.cc (make_argv): Correctly handle empty strings as args.\n\nFri Aug 20 08:17:52 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/quad.cc (quad): Delete unused label.\n\n\t* unwind-prot.cc (saved_variable::~saved_variable): Don't try to\n\tdelete gen_ptr_value here.\n\nMon Aug 16 21:34:33 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (next_token_is_sep_op): New function.\n\t(handle_close_brace, maybe_unput_comma): Use it.\n\t(have_continuation): Also handle CRLF here.\n\nWed Aug 11 16:06:57 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (Ffopen): Make fopen (\"filename\") work and imply that\n\tMODE = \"r\".\n\nWed Jul 21 15:38:52 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (display_names_from_help_list): Sort names before\n\tlisting them.\n\t(print_symbol_type, Ftype): Also handle built-in constants.\n\t(LIST_SYMBOLS): Correct call to symbol_table::name_list.\n\t(simple_help): List constants here too.  List constants and\n\tvariables before functions, not after.  Sort names before listing\n\tthem.\n\n\t* variables.cc (do_who): Display built-in constants in a separate\n\tsection.\n\n\t* error.cc (bind_global_error_variable, clear_global_error_variable):\n\tCall bind_builtin_constant, not bind_builtin_variable to set\n\t__error_text__.\n\t* octave.cc (intern_argv): Likewise, for argv and __argv__.\n\n\t* defun.cc (install_builtin_constant): Move function guts to\n\tbind_builtin_constant in variables.cc.\n\t* variables.cc (bind_builtin_constant): New function.\n\n\t* symtab.cc (symbol_record::define, symbol_record::variable_reference):\n\tHandle constants the same as functions.\n\t(symbol_record::link_to_builtin_variable): New function.\n\t(symbol_record::define_builtin_const): New function.\n\t(symbol_record::define_as_fcn): Delete unused function.\n\t(symbol_record::read_only_error):\n\tHandle constants the same as variables.\n\t* symtab.h (symbol_record::BUILTIN_CONSTANT): New enum value.\n\t(symbol_record::symbol_type): Increase width to 7 bits.\n\t(symbol_record::symbol_def::is_constant): New function.\n\t(symbol_record::symbol_def::is_builtin_constant): New function.\n\t(symbol_record::is_constant): New function.\n\t(symbol_record::is_builtin_constant): New function.\n\t(SYMTAB_ALL_TYPES): Add symbol_record::BUILTIN_CONSTANT.\n\t* variables.cc (link_to_builtin_variable): Delete unused function.\n\t(link_to_builtin_or_function): Handle built-in constants here too.\n\n\t* defun.cc (install_builtin_variable): Delete inst_as_fcn arg.\n\t(install_builtin_constant): New function.\n\t(install_builtin_variable_as_function): Delete unused function.\n\t* defun.h (DEFVAR_INTERNAL): Delete inst_as_fcn arg.\n\t(DEFCONST_INTERNAL): New macro.\n\t* defun.h (DEFVAR): Delete inst_as_fcn arg.\n\t(DEFCONST, DEFCONSTX): Define using DEFCONST_INTERNAL instead of\n\tDEFVAR_INTERNAL.\n\t* data.cc, defaults.cc, error.cc, help.cc, input.cc, lex.l,\n\tload-save.cc, oct-hist.cc, oct-procbuf.cc, ov-fcn.h,\n\tov-usr-fcn.cc, ov.cc, pager.cc, parse.y, pr-output.cc,\n\tpt-assign.cc, pt-decl.cc, pt-mat.cc, pt-plot.cc, pt-stmt.cc,\n\ttoplev.cc, variables.cc:\n\tChange all invocations of DEFVAR to match new definition.\n\n\t* data.cc (symbols_of_data): Add DEFCONSTs for true and false.\n\nThu Jul 15 10:59:42 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (Fis_bool, Fis_complex, Fisempty, Fisnumeric, Fis_list,\n\tFis_map, Fis_struct): Return bool object.\n\t(Fisreal): New function.\n\n\t* ov-str-mat.h (octave_char_matrix_str): Only return true if\n\tVimplicit_str_to_num_ok is also true.\n\n\t* DLD-FUNCTIONS/time.cc (Ftime): Print usage message if\tany\n\targuments are supplied.\n\n\t* variables.cc (symbol_out_of_date): Call octave_time for time stamps.\n\n\t* fn-cache.h (octave_fcn_file_name_cache::timestamp):\n\tNow octave_time object.\n\n\t* strftime.c: Move to liboctave directory.\n\t* Makefile.in (DIST_SRC): Delete from list.\n\n\t* ov-usr-fcn.h (octave_user_function::t_parsed,\n\toctave_user_function::t_checked): Now octave_time objects.\n\t(octave_user_function::time_parsed,\n\t(octave_user_function::time_checked):\n\tReturn value is now octave_time object.\n\t(octave_user_function::mark_fcn_file_up_to_date)):\n\tArg is now octave_time object.\n\n\t* ov-fcn.h (octave_function::mark_fcn_file_up_to_date)):\n\tArg is now octave_time object.\n\t(octave_function::time_parsed, octave_function::time_checked):\n\tReturn value is now octave_time object.\n\n\t* input.cc (Vlast_prompt_time): Now an octave_time object.\n\t(octave_gets): Call octave_time::stamp() to set Vlast_prompt_time.\n\n\t* DLD-FUNCTIONS/time.cc (mk_tm_map, extract_tm, Ftime, Fgmtime,\n\tFlocaltime, Fmktime, Fstrftime): Use new classes defined in\n\tliboctave/oct-time.cc instead of accessing C functions directly.\n\nWed Jul 14 17:38:46 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* systime.h: Move to liboctave directory.\n\t* Makefile.in (INCLUDES): Delete it from the list\n\nTue Jul 13 14:34:57 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (sigchld_handler): Only wait for processes in\n\toctave_child_list.\n\t* toplev.cc (cmd_status): Delete unused static variable.\n\t(cmd_death_handler): Delete unused function.\n\t(run_command_and_return_output): Don't add cmd_death_handler to\n\toctave_child_list.  Simply extract command exit status from\n\tcalling close() on the procstream object.\n\nMon Jul 12 22:38:50 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defun.h (DEFUN_MAPPER): Handle new args, d_b_map and c_b_map.\n\t* defun-int.h (DEFUN_MAPPER_INTERNAL): Likewise.\n\t* mappers.cc (install_mapper_functions): Supply new args to\n\tall uses of DEFUN_MAPPER.\n\t* ov-mapper.cc (octave_mapper::apply): Handle mapper functions\n\tthat return bool objects.\n\t* ov-mapper.h (octave_mapper::d_b_mapper, octave_mapper::c_b_mapper):\n\tNew typedefs.\n\t(octave_mapper::octave_mapper): Handle new mapper function types.\n\n\t* DLD-FUNCTIONS/minmax.cc: Do a better job of handling NaNs.\n\nSun Jul 11 13:15:17 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (do_plus_format (ostream&, double)): New function.\n\t(octave_print_internal (ostream&, double, bool)): Use it.\n\t(octave_print_internal (ostream&, const Matrix&, bool, int)): Ditto.\n\n\t* pr-output.cc (do_plus_format (ostream&, const Complex&)):\n\tNew function.\n\t(octave_print_internal (ostream&, const Complex&, bool)): Use it.\n\t(octave_print_internal (ostream&, const ComplexMatrix&, bool, int)):\n\tDitto.\n\nSun Jun 20 23:04:00 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sysdep.cc: Include sys/ioctl.h if available.\n\nSat Jun 19 12:07:16 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (do_who): Make pattern and multiple non-option\n\targuments work.\n\nMon Jun  7 09:54:51 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (next_token_is_bin_op, next_token_is_postfix_unary_op,\n\thandle_number): Delete yytext arg.  Change all callers.\n\t(next_token_is_postfix_unary_op): Check the first character\n\tobtained from yyinput before calling it again.\n\t(next_token_is_bin_op): Do a more thorough check.\n\t(handle_identifier): Also enter token in local symbol table if the\n\tfollowing token is a dot and it looks like a binary operator.\n\t(whitespace_in_literal_matrix): Now static.\n\n\t* lex.l: Always use unput, not yyunput.\n\nFri May 28 11:02:37 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/chol.cc (Fchol): If two output arguments, never\n\tproduce error message.\n\nThu May 27 18:28:35 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/chol.cc (Fchol): Also return info as second output.\n\n\t* DLD-FUNCTIONS/minmax.cc (max (const ComplexMatrix&, const\n\tComplexMatrix&)): Correct test for real columns only.\n\t(min (const ComplexMatrix&, const ComplexMatrix&)): Likewise.\n\nWed Apr 14 12:54:25 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/dassl.cc (Fdassl): Prevent recursive calls.\n\t* DLD-FUNCTIONS/fsolve.cc (Ffsolve): Likewise.\n\t* DLD-FUNCTIONS/lsode.cc (Flsode): Likewise.\n\t* DLD-FUNCTIONS/quad.cc (Fquad): Likewise.\n\n\t* file-io.cc (Fsscanf, Ffscanf): Doc fix.\n\nSat Mar 27 11:07:51 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_value::count): New function.\n\t* symtab.cc (symbol_record::dump_symbol_info): New function.\n\t* symtab.cc (symbol_record::symbol_def::dump_symbol_info): Ditto.\n\t* variables.cc (F__dump_symbol_info__): Ditto.\n\n\t* pt-misc.cc (tree_parameter_list::clear): New function.\n\t* ov-usr-fcn.h (octave_user_function::clear_args_passed): Ditto.\n\t* ov-usr-fcn.cc (clear_param_list): New function.\n\t(clear_args_passed): New function.\n\t(octave_user_function::do_index_op): Use them to decrement\n\treference counts on local variables.\n\nFri Mar 26 00:51:53 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (libraries): Use the libfoo.a(objects) method of\n\tcreating static libs.\n\n\t* defaults.cc (symbols_of_defaults): Initialize LOADPATH to\n\tVload_path, not \":\".\n\nThu Mar 18 12:09:23 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (Fisnumeric): Fix typo.\n\nThu Mar  4 02:17:04 1999  James Macnicol  <jamesm@evans.ee.adfa.oz.au>\n\n\t* file-io.cc (Ffread, Ffwrite): Add uint16 and uint32 data types\n\tto doc string.\n\nWed Mar  3 11:55:17 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (handle_string): Allow \"\" to pass through unchanged if\n\tworking on a gset command.\n\nTue Mar  2 01:36:29 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (Fexist): If a variable isn't defined, only go on\n\tto look for a global by the same name if we are at the top level.\n\nFri Jan 29 02:18:36 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_NAME_AND_VERSION): Say `GNU Octave', not just\n\tOctave.\n\nThu Jan 28 21:29:16 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (Fcomputer): Use CANONICAL_HOST_TYPE, not TARGET_HOST_TYPE.\n\t(octave_config_info): Likewise.\n\t* version.h: Ditto.\n\n\t* sysdep.cc (Fpause): Flush output before getting user input.\n\nWed Jan 27 14:18:29 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DEFFUN_PATTERN, DEFVAR_PATTERN): Use egrep again.\n\tMake the patterns work with stupid egreps that don't like empty\n\telements in alternation patterns.\n\nFri Jan 22 04:41:48 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (save_ascii_data): Check for string type first,\n\tthen range, then the rest.\n\t(save_binary_data): Ditto.\n\n\t* pager.cc (more_than_a_screenful): Accept length as second arg.\n\tHandle long lines properly, assuming the terminal wraps long lines.\n\t(octave_pager_buf::do_sync): Accept length of data as second arg.\n\tUse write instead of << to put characters on output stream.\n\t(octave_pager_buf::sync): Don't assume data ends at first NUL.\n\t(octave_diary_buf::sync): Ditto.\n\nThu Jan 21 22:15:23 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (save_mat_binary_data): Check for string type\n\tfirst, then range, then the rest.\n\nWed Jan 20 12:01:14 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_base_stream::do_scanf): Handle short and\n\tlong ints correctly.\n\nFri Jan 15 13:04:58 1999  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (end_error): Handle case of endswitch too.\n\n\t* Makefile.in: Use basic regular expressions and grep instead of\n\tegrep to find files that contain DEFVAR, DEFCONST, or DEFUN.\n\nWed Dec  9 14:14:11 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (octave): Add $(RDYNAMIC_FLAG) to link command.\n\nFri Dec  4 20:26:33 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/time.cc (Fstrftime): Make it work even when not\n\tusing the GNU version of strftime, which allows passing NULL for\n\tthe buffer to determine the required size of the buffer.\n\nWed Dec  2 22:38:40 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (file_in_loadpath): Expect argc == 2, not 3.\n\nTue Nov 24 23:38:19 1998  Eric Norum  <eric@skatter.USask.Ca>\n\n\t* mkbuiltins: Also strip off leading `./' from file names.\n\t* mkops: Ditto.\n\nTue Nov 24 23:24:26 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strftime.c: Surround everything with #ifdef HAVE_STRFTIME / #endif.\n\n\t* lex.h (YY_FATAL_ERROR): Call yy_falta_error after\n\tjump_to_top_level to avoid gcc warning.\n\nFri Nov 20 13:34:47 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-bool.h, ov-bool.cc (class octave_bool): Derive from\n\toctave_base_scalar and get common functions via derivation.\n\t* ov-scalar.h, ov-scalar.cc (class octave_scalar): Ditto.\n\t* ov-complex.h, ov-complex.cc (class octave_complex): Ditto.\n\n\t* ov-base-scalar.h, ov-base-scalar.cc (class octave_base_scalar):\n\tNew files for new class definition.  Put common scalar data type\n\tstuff here.\n\t* Makefile.in (OV_INCLUDES, OV_SRC): Add them to the lists.\n\nThu Nov 19 14:30:25 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc (octave_dynamic_loader::mangle_name):\n\tPrepend underscore here.\n\t(octave_dynamic_loader::load_fcn_from_dot_oct_file): Not here.\n\n\t* ov-re-mat.h (octave_matrix_value): Delete experimental code for\n\thandling structure references for things like .rows, .cols, etc.\n\nWed Nov 18 01:18:46 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (VAR_FILES): Be more careful about matching.\n\t(DEF_FILES): Likewise.\n\n\t* ov-base-mat.h, ov-base-mat.cc, ov-bool-mat.h, ov-bool-mat.cc,\n\tov-ch-mat.h, ov-ch-mat.cc, ov-cx-mat.h, ov-cx-mat.cc,\n\tov-re-mat.h, ov-re-mat.cc: Move default definition of all, any,\n\tis_matrix_type, is_numeric_type, valid_as_zero_index, and\n\tdo_index_op to base class.\n\tProvide definitions that override the defaults where necessary.\n\n\t* mappers.cc: Don't include lo-specfun.h.\n\nTue Nov 17 14:35:56 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* besselj.cc (Fbesselh, Fairy); New functions.\n\t(Fbesselj, Fbessely, Fbesselk, Fbesseli): Update doc strings.\n\t(do_bessel): Handle additional args.\n\nFri Nov 13 14:47:11 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (NUMBER): Allow hexadecimal constants.\n\t(looks_like_hex): New function.\n\t(handle_number): Check for hexadecimal constants and convert them\n\tto unsigned integer values.\n\nThu Nov 12 11:13:24 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (gnu_readline): Check for EOF from command_editor::readline.\n\n\t* ov-str-mat.h, ov-str-mat.cc (class octave_char_matrix_str):\n\tGet common functions via new derivation scheme.\n\n\t* ov-bool-mat.h, ov-bool-mat.cc (class octave_bool_matrix):\n\tDerive from octave_base_matrix and get common functions via derivation.\n\t* ov-ch-mat.h, ov-ch-mat.cc (class octave_char_matrix): Ditto.\n\t* ov-cx-mat.h, ov-cx-mat.cc (class octave_complex_matrix): Ditto.\n\t* ov-re-mat.h, ov-re-mat.cc (class octave_real_matrix): Ditto.\n\n\t* ov-base-mat.h, ov-base-mat.cc (class octave_base_matrix): New\n\tfiles  for new class definition.  Put common matrix data type\n\tstuff here.\n\n\t* ov-list.cc (Fnth): New function.\n\n\t* ov-list.cc (octave_list::do_index_op): Allow more complex indexing.\n\n\t* oct-obj.cc (octave_value_list::index): New function.\n\t(octave_value_list::octve_value_list (Array<octave_value>)):\n\tNew private constructor.\n\n\t* ov-list.cc (Fsplice): Fix docstring to match.\n\t* oct-obj.cc (octave_value_list::splice): Allow special case\n\tsplice (x, length(x)+1, 0, y) to be equivalent to append (x, y).\n\n\t* ov-list.cc (Fappend): If an arg is a list, concatenate the lists\n\tinstead of appending arg as a single element.\n\nWed Nov 11 14:07:27 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (get_mat_data_input_line): New function.\n\t(get_lines_and_columns): Use it here.\n\t(read_mat_ascii_data): And here and do our own reading instead of\n\tusing Matrix::operator<<.\n\nTue Nov 10 16:12:25 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (make_constant): Initialize retval to 0.\n\n\t* toplev.h (clean_up_and_exit (void)): Delete declaration.\n\t* toplev.cc (do_octave_atexit): Move guts of clean_up_for_exit\n\there, but ensure that the actions are only executed once.\n\t* octave.cc (main): Don't register cleanup_tmp_files with atexit.\n\n\t* ov.h, ov.cc (class octave_value): Use DECLARE_OCTAVE_ALLOCATOR\n\tand DEFINE_OCTAVE_ALLOCATOR for uniform declaration and definition\n\tof allocator functions.  Use DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA\n\tand DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA for uniform declaration\n\tand definition of type id functions and data.\n\t* ov-usr-fcn.h, ov-usr-fcn.cc (class octave_user_function): Ditto.\n\t* ov-scalar.h, ov-scalar.cc (class octave_scalar): Ditto.\n\t* ov-re-mat.h ov-re-mat.cc (class octave_matrix): Ditto.\n\t* ov-range.h, ov-range.cc (class octave_range): Ditto.\n\t* ov-mapper.h, ov-mapper.cc (class octave_mapper): Ditto.\n\t* ov-list.h, ov-list.cc (class octave_list): Ditto.\n\t* ov-file.h, ov-file.cc (class octave_file): Ditto.\n\t* ov-fcn.h, ov-fcn.cc (class octave_function): Ditto.\n\t* ov-cx-mat.h, ov-cx-mat.cc (class octave_complex_matrix): Ditto.\n\t* ov-complex.h, ov-complex.cc (class octave_complex): Ditto.\n\t* ov-ch-mat.h, ov-ch-mat.cc (octave_char_matrix): Ditto.\n\t* ov-builtin.h, ov-builtin.cc (class octave_builtin): Ditto.\n\t* ov-bool.h, ov-bool.cc (class octave_bool): Ditto.\n\t* ov-bool-mat.h, ov-bool-mat.cc (octave_bool_matrix): Ditto.\n\n\t* ov.h (DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA): New macro.\n\t(DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA): Ditto.\n\nMon Nov  9 16:12:37 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (octave_print_internal): Reorder default args for\n\tcharMatrix version.\n\t(octave_print_internal): New function for boolMatrix.\n\n\t* version.h (OCTAVE_STARTUP_MESSAGE): Note that this is a\n\tdevelopment release.\n\n\t* toplev.cc (do_octave_atexit): Call flush_octave_stdout here.\n\t(clean_up_for_exit): And here.\n\nMon Nov  9 15:20:53 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (get_user_input): Check retval.length(), not\tretval.length.\n\nSun Nov  8 19:30:33 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-assign.cc (tree_simple_assignment::rvalue): If etype is\n\tasn_eq, don't evaluate ult again because retval is just rhs value.\n\t(tree_multi_assignment::rvalue): Likewise.\n\nFri Nov  6 12:14:29 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-loop.cc (tree_for_command::eval): Move code for string RHS\n\toutside if clause for matrix types.\n\n\t* pt-idx.cc: Don't forget to define arg_nm.\n\tMove contstructor here.\n\t* pt-idx.h: From here.\n\n\t* data.cc (Fisempty): Also return true for empty strings.\n\nWed Nov  4 17:21:41 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-base.cc (octave_base_value::rows, octave_base_value::columns,\n \toctave_base_value::length): Delete.\n\t* ov-base.h (octave_base_value::rows, octave_base_value::columns,\n \toctave_base_value::length): Define here.  All return -1 if not\n\tdefined in a derived class.\n\n\t* data.cc (Fis_matrix): Also return true if the arg is a range.\n\nTue Nov  3 09:40:24 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (Fis_bool): New function.\n\tAlso add alias for islogical.\n\n\t* ov.h (octave_value::is_bool_type): New function.\n\t* ov-base.h (octave_base_value::is_bool_type): Likewise.\n\t* ov-bool.h (octave_bool::is_bool_type): Likewise.\n\t* ov-bool-mat.h (octave_bool_matrix::is_bool_type): Likewise.\n\nMon Nov  2 13:36:04 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (handle_close_brace): Also handle case of ']' followed by\n\tother assignment ops (+=, -=, ...).\n\n\t* pt-assign.cc (tree_simple_assignment::rvalue): Correctly handle\n\treturn value and printing for operators other than `='.\n\t(tree_multi_assignment::rvalue): Likewise.\n\n\t* pt-assign.h (tree_multi_assignment::etype): New data member.\n\t* pt-assign.cc \t(tree_multi_assignment::rvalue): Use it instead of\n\tassuming `='.\n\t(tree_multi_assignment::oper): New function.\n\t* pt-pr-code.cc (tree_print_code::visit_multi_assignment): Use\n\tit instead of always printing `='.\n\t* parse.y (make_assign_op): Pass expression type to\n\ttree_multi_assignment constructor.\n\n\t* Makefile.in (stmp-pic): New target.\n\t($(PICOBJ)): Depend on stmp-pic, not pic.\n\t(clean): Delete stmp-pic.\n\nSun Nov  1 23:24:55 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mappers.cc (install_mapper_functions): Add alias for isfinite.\n\nSat Oct 31 08:46:55 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (Fisnumeric): New function.\n\nFri Oct 30 08:39:30 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-lvalue.cc (octave_lvalue::do_unary_op): Make it work for\n\tindexed ops too.\n\t* ov.cc (octave_value::unary_op_to_assign_op): New function.\n\t(octave_value::do_non_const_unary_op): New function for\tindexed ops.\n\n\t* parse.y (LEFTDIV_EQ, ELEFTDIV_EQ): New tokens.\n\t(assign_expr): Add rules for them.\n\t(make_assign_op): Handle them here too.\n\t* lex.l: Recognize them.\n\t* ov.h (octave_value::assign_op): Add ldiv_eq and el_ldiv_eq.\n\t* ov.cc (octave_value::assign_op_as_string): Ditto.\n\t(octave_value::op_eq_to_binary_op): Ditto.\n\t(octave_value::assign): Handle OP= style operators with brute force.\n\t(octave_value::simple_assign): New function.\n\n\t* parse.y (matrix): Dont' forget to reset\n\tlexer_flags.looking_at_matrix_or_assign_lhs.\n\n\t* oct-lvalue.cc (octave_lvalue::assign): Don't call change\n\tfunction if error occurs.\n\t(octave_lvalue::do_unary_op): If we have an index, fail with message.\n\nThu Oct 29 09:27:04 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.cc (do_binary_op): Protect against invalid type conversions.\n\t(try_assignment_with_conversion): Likewise.\n\t(do_unary_op): Likewise.\n\n\t* ov.h (OV_UNOP_FN, OV_UNOP_OP, OV_UNOP_FN_OP): New macros.\n\tUse them to define not, uminus, transpose, hermitian functions\n\tand operators ! and -.\n\t(OV_BINOP_FN, OV_BINOP_OP, OV_BINOP_FN_OP): New macros.\n\tUse them to define add, sub, mul, div, pow, ldiv, lshift, rshift,\n\tlt, le, eq, ge, gt, ne, el_mul, el_div, el_pow, el_ldiv, el_and,\n\tel_or, struct_ref, functions and operators <, <=, ==, >=, >, !=,\n\t+, -, *, and /.\n\n\t* ops.h (CONVDECLX): New macro.\n\t* ov-base.cc (matrix_conv, complex_matrix_conv, string_conv):\n\tUse it to declare these functions.\n\n\t* ops.h (CONVDECL, INSTALL_WIDENOP):\n\tPrefix function name with `oct_conv_'.\n\t(INSTALL_BINOP, BINOPDECL): Prefix function name with `oct_binop_'.\n\t(INSTALL_ASSIGNOP, INSTALL_ASSIGNANYOP, ASSIGNOPDECL):\n\tPrefix function name with `oct_assignop_'.\n\t(UNOPDECL, DEFNCUNOP_METHOD, INSTALL_UNOP, INSTALL_NCUNOP):\n\tPrefix function name with `oct_unop_'.\n\n\t* ov-str-mat.cc (default_numeric_conversion_function):\n\tReturn 0 if conversion fails.\n\n\t* parse.y (make_prefix_op, make_postfix_op): Use\n\toctave_value::unary_op enum.\n\n\t* pt-unop.cc (tree_prefix_expression::rvalue): Use new unary_op\n\tfunctions from octave_value and octave_lvalue classes.\n\t(tree_prefix_expression::rvalue): Likewise.\n\n\t* pt-unop.cc (tree_unary_expression::oper): Move here.\n\t(tree_prefix_expression::oper, tree_postfix_expression): From here.\n\n\t* pt-unop.h (tree_prefix_expression, tree_postfix_expression):\n\tDelete enums.\n\t(tree_unary_expression): Use octave_value::unary_op enum.\n\t* parse.y (make_prefix_op, make_postfix_op): Likewise.\n\n\t* oct-lvalue.h (octave_lvalue::do_unary_op): New function.\n\t(octave_lvalue::increment, octave_lvalue::decrement): Delete.\n\n\t* ov-typeinfo.h (octave_value_typeinfo::non_const_unary_ops):\n\tNew data member.\n\t* ov-typeinfo.h (octave_value_typeinfo::lookup_non_const_unary_op):\n\tNew function.\n\t* ov-typeinfo.cc (octave_value_typeinfo::register_non_const_unary_op):\n\tNew function.\n\t(octave_value_typeinfo::do_register_non_const_unary_op): Ditto.\n\t(octave_value_typeinfo::do_lookup_non_const_unary_op): Ditto.\n\n\t* ov.cc (octave_value::do_non_const_unary_op): New function.\n\n\t* Makefile.in (OP_XSRC): Add op-chm.cc and op-range.cc to the list.\n\n\t* OPERATORS/op-str-str.cc: Define string matrix unary operators here.\n\t(install_str_str_ops): Install them here.\n\t* ov-bool-mat.h (octave_bool_matrix::transpose,\n\toctave_bool_matrix_value::hermitian): Delete.\n\n\t* OPERATORS/op-chm.cc: New file.  Define char matrix unary operators.\n\t(install_chm_ops): Install them here.\n\t* ov-ch-mat.h (octave_char_matrix::transpose,\n\toctave_char_matrix_value::hermitian): Delete.\n\t* ops.cc (install_ops): Call install_chm_ops.\n\n\t* OPERATORS/op-bm-bm.cc: Define bool matrix unary operators here.\n\t(install_bm_bm_ops): Install them here.\n\t* ov-bool-mat.h (octave_bool_matrix::transpose,\n\toctave_bool_matrix_value::hermitian): Delete.\n\n\t* ov-bool.h (octave_bool::not, octave_bool::uminus,\n\toctave_bool::transpose, octave_bool::hermitian): Delete.\n\n\t* OPERATORS/op-cs-cs.cc: Define complex scalar unary operators here.\n\t(install_cs_cs_ops): Install them here.\n\t* ov-complex.h (octave_complex::not, octave_complex::uminus,\n\toctave_complex::transpose, octave_complex::hermitian): Delete.\n\n\t* OPERATORS/op-cm-cm.cc: Define complex matrix unary operators here.\n\t(install_cm_cm_ops): Install them here.\n\t* ov-cx-mat.h (octave_complex_matrix::not,\n\toctave_complex_matrix::uminus, octave_complex_matrix::transpose,\n \toctave_complex_matrix::hermitian): Delete.\n\n\t* OPERATORS/op-m-m.cc: Define matrix unary operators here.\n\t(install_m_m_ops): Install them here.\n\t* ov-re-mat.h (octave_matrix::not, octave_matrix::uminus,\n\toctave_matrix::transpose, octave_matrix::hermitian): Delete.\n\n\t* OPERATORS/op-range.cc: New file.  Define range unary operators.\n\t(install_range_ops): Install them here.\n\t* ov-range.h (octave_range::not, octave_range::uminus,\n\toctave_range::transpose, octave_range::hermitian): Delete.\n\t* ops.cc (install_ops): Call install_range_ops.\n\n\t* OPERATORS/op-s-s.cc: Define scalar unary operators here.\n\t(install_s_s_ops): Install them here.\n\t* ov-scalar.h (octave_scalar::not, octave_scalar::uminus,\n\toctave_scalar::transpose, octave_scalar::hermitian): Delete.\n\n\t* ops.h (INSTALL_UNOP, CAST_UNOP_ARG, UNOPDECL, DEFUNOPX, DEFUNOP,\n\tDEFUNOP_OP, DEFUNOP_FN): New macros.\n\n\t* ov.h (unary_op_fcn): New typedef.\n\t(octave_value::unary_op): New enum.\n\t* ov.cc (octave_value::octave_value): New function.\n\n\t* ov.h (octave_value::not, octave_value::uminus,\n\toctave_value::transpose, octave_value::hermitian,\n\toctave_value::increment, octave_value::decrement): Delete.\n\n\t* ov-base.cc (octave_base_value::not, octave_base_value::uminus,\n\toctave_base_value::transpose, octave_base_value::hermitian,\n\toctave_base_value::increment, octave_base_value::decrement): Delete.\n\n\t* ov.cc (gripe_unary_op): New function.\n\t(do_unary_op): New function.\n\t* ov-typeinfo.h (octave_value_typeinfo::unary_ops):\n\tNew data member.\n\t* ov-typeinfo.cc (octave_value_info::register_unary_op,\n\toctave_value_info::do_register_unary_op,\n\toctave_value_info::lookup_unary_op,\n\toctave_value_info::do_lookup_unary_op):\n\tNew functions.\n\n\t* ov-list.cc (Fsplice): Use new octave_value::int_value function here.\n\t(octave_list::do_index_op): Likewise.\n\t(octave_list::assign): Likewise.\n\t* toplev.cc (Fquit): Likewise.\n\t* syscalls.cc (Fwaitpid): Likewise.\n\t(Ffcntl): Likewise.\n\t* file-io.cc (do_fread): Likewise.\n\t(do_fwrite): Likewise.\n\t* data.cc (make_diag): Likewise.\n\t(Fsize): Likewise.\n\t(get_dimensions): Likewise.\n\t(Flinspace):\n\n\t* ov-base.cc (octave_base_value::int_value): New function.\n\t(octave_base_value::nint_value): Ditto.\n\t* ov.h (octave_value::int_value): Ditto.\n\t(octave_value::nint_value): Ditto.\n\n\t* ov-list.cc (octave_list::assign): Fix off-by-one error.\n\nWed Oct 28 11:01:37 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (read_mat_ascii_data): Try harder to convert file\n\tname to valid variable name.\n\n\t* data.cc (Fisempty, Fis_matrix): New functions.\n\n\t* ov-str-mat.h (octave_char_matrix_str::is_matrix_type): New function.\n\n\t* OPERATORS/op-list.cc: New file.\n\t* Makefile.in (OP_XSRC): Add it to the list.\n\n\t* ov-list.cc (octave_list::assign): New function.\n\n\t* ov-typeinfo.h (octave_value_typeinfo::assignany_ops):\n\tNew data member.\n\t* ov-typeinfo.cc (octave_value_info::register_assignany_op,\n\toctave_value_info::do_register_assignany_op,\n\toctave_value_info::lookup_assignany_op,\n\toctave_value_info::do_lookup_assignany_op):\n\tNew functions.\n\t* ov.cc (octave_value::try_assignment (octave_value::assign_op,\n\tconst octave_value_list&, const octave_value&)): If no assignment\n\toperator for particular RHS type exists, try finding one for\n\tgeneric octave_value as RHS type.\n\t* ops.h (DEFASSIGNANYOP_FN): New macro.\n\n\t* ov-list.cc (Fsplice): New function.\n\t* oct-obj.cc (octave_value_list::splice): New function.\n\n\t* ov.cc (Vresize_on_range_error): No longer static.\n\t* ov.h (Vresize_on_range_error): Provide extern declaration.\n\n\t* oct-procbuf.cc (symbols_of_oct_procbuf): Don't declare static.\n\n\t* data.cc (Flength): New function.\n\t* ov.h (octave_value::length): New virtual function.\n\t* ov-base.cc (octave_base_value::length): New function.\n\t(octave_base_value::rows, octave_base_value::columns): Move\n\tdefinitions here, from ov-base.h.  Don't return -1.  Instead,\n\tgripe about wrong argument type.\n\t* ov-bool-mat.h (octave_bool_matrix::length): New function.\n\t* ov-bool.h (octave_bool::length): Ditto.\n\t* ov-ch-mat.h (octave_char_matrix::length): Ditto.\n\t* ov-complex.h (octave_complex::length): Ditto.\n\t* ov-cx-mat.h (octave_complex_matrix::length): Ditto.\n\t* ov-list.h (octave_list::length): Ditto.\n\t* ov-range.h (octave_range::length): Ditto.\n\t* ov-re-mat.h (octave_matrix::length): Ditto.\n\t* ov-scalar.h (octave_scalar::length): Ditto.\n\nTue Oct 27 22:19:24 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-list.cc (octave_list::print_raw): Handle case of empty list.\n\t(octave_list::print_name_tag): Likewise.\n\n\t* octave.cc (intern_argv): Built-in variable argv is now a list of\n\tstrings instead of a string vector.\n\tAlways bind argv, making it an empty list if there are no args.\n\nMon Oct 26 08:41:46 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* xdiv.cc (mx_leftdiv_conform): Explicitly declare args to be\n\tpassed as references to const objects.  Fix explicit instantiation\n\trequests to match.\n\t(mx_div_conform): Likewise.\n\n\t* pt-unop.h (tree_prefix_expression): Reorder constructor args to\n\tput those with default values last.\n\t(tree_postfix_expression): Likewise.\n\t* parse.y: Change all callers.\n\nFri Oct 23 12:07:32 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (Ffile_in_loadpath): New function.\n\n\t* defaults.cc (Vload_path, Vdefault_load_path): Now static.\n\n\t* help.cc (simple_help): Use Vload_path_dir_path here instead of\n\ttrying to reconstruct it from Vload_path.\n\t* fn-cache.cc (octave_fcn_file_name_cache::do_list): Likewise.\n\t(octave_fcn_file_name_cache::update): Likewise.\n\n\t* defaults.cc (octave_loadpath): Construct Vload_path_dir_path\n\tusing Vdefault_load_path.\n\t(set_default_path): Likewise.\n\n\t* defaults.h, defaults.cc (maybe_add_default_load_path): Delete.\n\n\t* defaults.cc (Vdefault_load_path): New static variable.\n\t(set_default_path): Set it.\n\t(maybe_add_default_load_path): Use it.\n\t(symbols_of_defaults): Add DEFCONST for DEFAULT_LOADPATH.\n\tThanks to Rafael Laboissiere <rafael@icp.inpg.fr>.\n\n\t* defaults.cc (set_default_path): If OCTAVE_PATH is set in the\n\tenvironment, call maybe_add_default_load_path on it.\n\nTue Oct 20 20:58:04 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.cc (maybe_add_default_load_path): If LOADPATH contains\n\tan embedded \"::\", insert the default path there too.\n\nFri Oct 16 00:52:15 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (in_matrix_or_assign_lhs): New subroutine for lexical\n\tfeedback.\n\t(matrix): Use it.\n\t(assign_lhs): Ditto.\n\t* lex.h (lexical_feedback::looking_at_matrix_or_assign_lhs): New\n\tdata member.\n\t* lex.l (handle_identifier): Use it to handle keywords like `cd'\n\tas variables in contexts like [ab, cd] = foo ().\n\n\t* ov-str-mat.h\n\t(octave_char_matrix_str::octave_char_matrix_str (char c)):\n\tNew constructor.\n\t* ov-ch-mat.h (octave_char_matrix::octave_char_matrix (char c)):\n \tNew constructor.\n\t* ov.cc (octave_value::octave_value (char c): New constructor.\n\n\t* pt-loop.cc (tree_simple_for_command::eval): Handle case of RHS\n\tas string.\n\nThu Oct 15 00:56:47 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/rand.cc: Declare Fortran subroutines as returning\n\tint, not int*.\n\nWed Oct 14 23:51:31 1998  Georg Thimm  <thimm@idiap.ch>\n\n\t* load-save.cc (Vcrash_dumps_octave_core): New static variable.\n\t(save_user_variables): Only save variables if\n\tVcrash_dumps_octave_core is true.\n\t(symbols_of_load_save): Add DEFVAR for it here.\n\t(crash_dumps_octave_core): New function.\n\t* octave.cc (maximum_braindamage): Bind crash_dumps_octave_core to\n\t0.0 here.\n\nTue Oct 13 22:05:55 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (read_readline_init_file): New function.\n\nThu Oct  8 13:47:55 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-procbuf.h (octave_procbuf::wstatus): New data member.\n\tInitialize in constructors.\n\t(octave_procbuf::wait_status): New member function.\n\t* oct-procbuf.cc (octave_procbuf::sys_close): Use class data\n\tmember wstatus, not local variable.\n\t* procstream.cc (procstreambase::close): Don't call sys_close directly.\n\tGet subprocess exit status by calling wait_status for our procbuf.\n\t* pt-plot.cc (close_plot_stream): Send \"quit\" command to gnuplot\n\tbefore deleting plot_stream.\n\nThu Oct  1 22:39:44 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (Fis_complex): New function.\n\nFri Sep 25 11:50:44 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (write_header): Rename from write_binary_header.\n\tAlso write header for Octave ASCII files.\n\n\t* load-save.cc (Fsave): Implement -append option.\n\n\t* defaults.cc (Frehash): New function.\n\nFri Sep 25 11:50:44 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (help_from_info): Improve error message in case that\n\tinfo doesn't work.\n\nThu Sep 24 10:48:12 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DLD_XSRC): Replace qzval.cc with qz.cc\n\n\t* DLD-FUNCTIONS/balance.cc: Update from A. S. Hodel\n\t<scotte@eng.auburn.edu>.\n\n\t* DLD-FUNCTIONS/qz.cc: New file.\n\n\t* DLD-FUNCTIONS/qzval.cc: Delete.\n\n\t* parse.y (plot_command1): Don't allow it to be empty.\n\t(plot_command): Handle simple `PLOT' and `PLOT ranges' as special\n\tcases here.\n\nWed Sep 23 21:10:08 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l: Change <MATRIX>{SNLCMT}*\\n{SNLCMT}* pattern\n\tto <MATRIX>{S}*{COMMENT}{SNLCMT}* | <MATRIX>{S}*{NL}{SNLCMT}*.\n\nFri Sep  4 10:50:00 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (Ffwrite): Fix doc string.\n\nWed Sep  2 16:22:23 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (match_sans_spaces): Make it work.\n\n\t* toplev.cc (quit): Require nargout == 0.\n\n\t* input.cc (get_user_input): Only try matching \"exit\", \"quit\", and\n\t\"return\" if debugging.\n\nTue Sep  1 12:50:24 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc: Use -H as single character equivalent of --no-history.\n\nSat Aug 29 12:23:12 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-obj.cc (octave_value_list::make_argv): If some values are\n\tstring vectors, insert all the elements, not just the first.\n\nTue Aug 18 16:39:50 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_base_stream::do_gets): Accept last line of\n\tfile even if it doesn't end in a newline character.\n\nTue Aug 18 16:25:49 1998  Mumit Khan  <khan@xraylith.wisc.edu>\n\n\t* xdiv.cc (mx_leftdiv_conform, mx_div_conform): Instantiate correct\n\ttemplates.\n\nThu Jul 30 00:37:43 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-loop.cc (tree_for_command::eval): Check for range first.\n\tIf error occurs when extracting matrix value, return early.\n\tDon't bother to check for string type.\n\n\t* ov-ch-mat.h (octave_char_matrix::is_real_matrix): New function.\n\nTue Jun 23 15:09:54 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (clear_current_script_file_name): New function.\n\t(parse_fcn_file): Bind current_script_file_name while script is\n\texecuting.  Use unwind_protect to clear it once the script is\n\tfinished.\n\n\t* pt-plot.cc (Fgraw): New function.\n\nMon Jun 22 22:13:38 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (is_valid_function): Provide version that takes\n\tfunction name as string.\n\n\t* parse.y (binary_expr): Fix thinko that resulted in incorrect\n\tevaluation of -x^y.  Thanks to Richard Allan Holcombe\n\t<raholcom@unity.ncsu.edu>.\n\t(feval): Don't attempt to copy nonexistent arg names.\n\nMon Jun 22 21:35:50 1998  Richard Allan Holcombe  <raholcom@unity.ncsu.edu>\n\n\t* xpow.cc (xpow): Improve efficiency for matrix^(scalar int) case.\n\nThu Jun  4 12:42:46 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-usr-fcn.cc (octave_user_function::octave_all_va_args):\n\tIf num_args_passed < num_named_args, create zero length list.\n\nThu May 14 16:23:15 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/getrusage.cc: Include sys/types.h too.\n\nMon May 11 00:38:45 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pager.cc (Fdiary): Don't forget to set write_to_diary file if\n\tjust given a file name.\n\n\t* input.cc (octave_gets): Only send new line character to\n\toctave_diary if current_input_line is empty or doesn't already end\n\twith a new line character..\n\tDon't send input from function files or\tscripts to octave_diary.\n\nSun May  3 19:54:38 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (reset_parser): Also call yyrestart if forced_interactive\n\tis true, but not if input_from_startup_file is true.\n\nTue Apr 28 14:06:20 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-procbuf.cc (Vkluge_procbuf_delay): New static variable.\n\t(kluge_procbuf_delay): New function.\n\t(symbols_of_oct_procbuf): New function.\n\t(octave_procbuf::open): Delay Vkluge_procbuf_delay microseconds\n\tafter forking.\n\nThu Apr 23 15:41:08 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.cc (Vload_path_dir_path): New variable.\n\t* utils.cc (file_in_path): Use it.\n\n\t* utils.cc (search_path_for_file): Undo previous change.\n\t(file_in_path): Undo previous change.\n\t* defaults.cc (loadpath): Undo previous change.  Tilde expansion\n\tis once again handled correctly by the code in\n\tliboctave/pathsearch.cc.\n\nMon Apr 20 21:50:34 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (get_dimensions): Allow zeros ([], 3) to work, for\n\tcompatibility with Matlab.\n\n\t* dynamic-ld.cc [WITH_DL && ! HAVE_DLFCN_H]: Add declarations for\n\tdlopen, dlerror, dlsym, and dlclose.\n\n\t* octave.gperf: Handle __FILE__ and __LINE__.\n\t* lex.l (is_keyword): Likewise.\n\t* Makefile.in (oct-gperf.h): Pass -D option to gperf.\n\tPostprocess output of gperf to convert name of static variable\n\tfrom lookup to gperf_lookup, to avoid conflict with our\tfunction\n\tof the same name defined in variables.cc.\n\nSat Apr 18 20:17:10 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (USE_GNU_INFO): Delete uses of this macro.\n\nThu Apr 16 01:00:12 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc: Only include dlfcn.h if HAVE_DLFCN_H.\n\nWed Apr 15 01:03:05 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (Vlast_prompt_time): New global variable.\n\t(octave_gets): Set it.\n\t* ov-fcn.h (octave_function::time_checked): New virtual function\n\t(octave_function::mark_fcn_file_up_to_date): Ditto.\n\t* ov-usr-fcn.h (octave_user_function::time_checked): New function.\n\t(octave_user_function::mark_fcn_file_up_to_date): Ditto.\n\t(octave_user_function::t_checked): New data member.\n\t* variables.cc (symbol_out_of_date): Only check file time stamp if\n\ta prompt has been printed since the last time check.\n\n\t* pt-plot.h, pt-plot.cc (subplot_axes): New class.\n\t(subplot): Handle axes.\n\t(Vgnuplot_command_axes): New static variable.\n\t(gnuplot_command_axes): New function.\n\t(symbols_of_pt_plot): DEFVAR gnuplot_command_axes.\n\t* pt-walk.h (tree_walker::visit_subplot_axes): New virtual function.\n\t* parse.y (plot_options): Handle axes.\n\t* lex.l (plot_axes_token): New function.\n\t(is_keyword): Use it.\n\t(is_plot_keyword): Recognize \"axes\" and \"axis\".\n\t* lex.h (class lexical_feedback): New field, in_plot_axes.\n\t(lexical_feedback::init): Reset it.\n\nTue Apr 14 23:32:27 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (parse_fcn_file): New arg, force_script.  Change callers.\n\nFri Apr 10 11:01:27 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (type): Also print values of variables.\n\nWed Apr  8 01:00:58 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (set_format): Set scale to 1.0 if all elements are\n\tint or inf or nan.\n\n\t* parse.y (Vwarn_future_time_stamp): New variable.\n\t(symbols_of_parse): Add DEFVAR for it.\n\t(warn_future_time_stamp): New function.\n\t(frob_function_def): Maybe warn about files with future time stamps.\n\nThu Apr  2 20:43:45 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-arg-list.cc (tree_argument_list::convert_to_const_vector): In\n\terror messages, print element numbers starting with 1, not 0.\n\nSat Mar 28 15:25:44 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (clean_up_for_exit): New function.\n\t(clean_up_and_exit): Use it.\n\t* sighandlers.cc (my_friendly_exit): Call it instead of\n\tclean_up_and_exit, then do default action for signal.\n\n\t* sighandlers.cc (octave_new_handler): Call my_friendly_exit with\n\tsignal set to SIGABRT if it is defined, or -1 otherwise.\n\n\t* error.cc (verror): Fix thinko in attempt to skip `error: ' tag\n\twhen buffering error messages.\n\t* pt-except.cc (tree_try_catch::eval): Reset buffer_error_messages\n\there if\tjust discarding unwind_protect frame.\n\nWed Mar 18 12:35:18 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* xpow.cc (elem_xpow): For real-scalar .^ matrix case, result is\n\tcomplex only if real-scalar is negative and matrix has some\n\tnon-integer values.\n\nTue Mar 17 17:47:50 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc (Vgnuplot_command_plot, Vgnuplot_command_replot,\n\tVgnuplot_command_splot, Vgnuplot_command_using,\n\tVgnuplot_command_with, Vgnuplot_command_title,\n\tVgnuplot_command_end): New static variables.\n\t(symbols_of_pt_plot): DEFVAR them.\n\t(gnuplot_command_plot, gnuplot_command_replot,\n\tgnuplot_command_splot, gnuplot_command_using,\n\tgnuplot_command_with, gnuplot_command_title,\n\tgnuplot_command_end): New functions.\n\t(open_plot_stream, send_to_plot_stream, tree_plot_command::eval,\n\tsubplot_using::print, subplot_style::print, subplot::print,\n\tdo_external_plotter_cd, Fgset, Fgshow): Use them instead of the\n\tGPLOT_CMD_PLOT, GPLOT_CMD_REPLOT, GPLOT_CMD_SPLOT,\n\tGPLOT_CMD_USING, GPLOT_CMD_WITH, GPLOT_CMD_TITLE, and\n\tGPLOT_CMD_END macros.\n\nFri Feb 27 12:25:27 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (additional_help_message): Fix www address.\n\nTue Feb 24 00:42:59 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (simple_help): Put additional help message first.\n  \t(additional_help_message): Add information about web site and\n\tmailing list.\n\nFri Feb 20 00:41:06 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc (GPLOT_CMD_REPLOT): Clear before replot.\n\n\t* Makefile.in: Better handling of lib flags for linking.\n\nThu Feb 19 21:14:30 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-decl.cc (Vinitialize_global_values): New static variable.\n\t(initialize_global_variables): New function.\n\t(symbols_of_pt_decl): New function.\n\tDEFVAR Vinitialize_global_values and initialize_global_variables.\n\t(tree_global_command::do_init): If initialize_global_variables is\n\tnot true and the variable doesn't have an explicit initializer, don't\n\tinitialize it.  If we are giving it a default value, use the value\n\tof the variable defualt_global_variable_value.\n\t* octave.cc (maximum_braindamage): Set default_global_variable_value\n\tand initialize_global_variables to Matlab-compatible values.\n\nWed Feb 18 04:35:31 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/besselj.cc: Rename from bessel.cc.\n\t* Makefile.in (DLD_XSRC): Likewise.\n\n\t* syscalls.cc (Fvfork): Delete.\n\n\t* oct-procbuf.cc: Just use fork.\n\n\t* parse.y (feval): Provide version that takes function name\n\tseparate from other args.\n\t* parse.h: Declare it.\n\n\t* oct-procbuf.cc (octave_procbuf::open): Move declaration of\n\tchild_std_end outside of child scope and declare volatile.\n\nMon Feb 16 15:04:28 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y: Include cstdio, for SEEK_SET.\n\nThu Feb 12 22:07:00 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* system.c: New file.\n\t* Makefile.in (SOURCES): Add it to the list.\n\nFri Feb  6 01:23:18 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_base_stream::file_number): Rename from fileno.\n\tChange all uses.\n\n\t* fsolve.cc (fsolve_option_table): Add missing & to function names.\n\nThu Feb  5 02:27:18 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dirfns.cc (Fls): If first attempt at reading process output\n\tfails, sleep once and try again.\n\t* toplev.cc (run_command_and_return_output): Likewise.\n\n\t* oct-procbuf.cc (octave_procbuf::open): Use vfork if it is available.\n\n\t* syscalls.cc (Fvfork): New function.\n\n\t* ov-bool-mat.cc: Only declare assign function if\n\tCXX_NEW_FRIEND_TEMPLATE_DECL is not defined.\n\n\t* ov-base.h, ov-bool-mat.h, ov-bool.h, ov-ch-mat.h, ov-complex.h,\n\tov-cx-mat.h, ov-range.h, ov-re-mat.h, ov-scalar.h: Handle default\n\targs for *_value functions consistently.\n\n\t* symtab.cc (maybe_list_cmp_fcn): Declare args as void*, not\n\tvoid**, then use X_CAST.\n\n\t* OPERATORS/op-s-cm.cc: Include mx-cm-s.h.\n\n\t* defun-int.h: Include ov-builtin.h, ov-mapper.h, and symtab.h.\n\t(install_builtin_mapper, install_builtin_function,\n\tinstall_builtin_variable) Use specific types rather than void * in\n\tdeclaration.\n\t* defun.cc (install_builtin_mapper, install_builtin_function,\n\tinstall_builtin_variable): Likewise.  Eliminate casts.\n\n\t* load-save.cc (read_binary_data, read_mat_file_header,\n\tsave_binary_data): Use X_CAST, not static_cast.\n\t* unwind-prot.h (unwind_protect::save_ptr): Likewise.\n\t* Map.cc (goodCHptr, index_to_CHptr, CHptr_to_index): Likewise.\n\t* dynamic-ld.cc (octave_dlopen_dynamic_loder::resolve_reference):\n\tLikewise.\n\n\t* pt-mat.cc (tm_const::operator bool ()):\n\t(tm_row_const::operator bool ()): Likewise.\n\t* oct-stream.cc (printf_value_cache::operator bool ()): Likewise.\n\t(scanf_format_list::operator bool ()): Likewise.\n\t(printf_format_list::operator bool ()): Likewise.\n\t(octave_stream::operator bool ()): Likewise.\n\nWed Feb  4 13:08:29 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/minmax.cc: Include cmath, not oct-math.h.\n\n\t* syscalls.cc (Fdup2): Convert stream to actual system file id.\n\n\t* oct-stream.cc (octave_base_stream::fileno, octave_stream::fileno):\n\tNew functions.\n\nTue Feb  3 00:24:44 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.cc (exec_path): Append Vbin_dir to std_path.\n\n\t* octave.cc (initialize_pathsearch): Set TEXMFDBS, not TEXMF.\n\tLook for OCTAVE_DB_PATH in environment.\n\tSimplify using Vdata_dir and Vlibexec_dir.\n\n\t* defaults.h.in (Vdata_dir, Vlibexecdir): Declare new vars.\n\tdefaults.cc: Define them.\n\t(set_default_data_dir, set_default_libexecdir): New functions.\n\t(install_defaults): Call them.\n\n\t* defaults.h.in (OCTAVE_LIBEXECDIR): Define.\n\nMon Feb  2 02:43:16 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install, uninstall): Use $(octlibdir), not $(libdir).\n\tUse mk-libdir-link.\n\n\t* defaults.h.in (OCTAVE_OCTLIBDIR): Substitute value.\n\t(Vlib_dir): Delete declaration.\n\t* defaults.cc (Vlib_dir): Delete.\n\t(set_default_lib_dir): Delete.\n\t(install_defaults): Don't call set_default_lib_dir.\n\t(set_default_info_prog): If oct_info_prog is empty, set default to\n\t\"info\" -- we expect it to be somewhere in the user's path.\n\n\t* defun.h (DEFCONST, DEFCONSTX): Eliminate inst_as_fcn and chg_fcn\n\targs.  Always pass true for inst_as_fcn and 0 for chg_fcn to\n\tDEFVAR when creating built-in values like `e' or `stderr' that can\n\tbe redefined.  Change all uses.\n\n\t* help.cc (Ftype): Handle script files too.\n\t(Fwhich): Likewise.\n\nSat Jan 31 00:00:26 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-ch-mat.cc (octave_char_matrix::is_true): Make it work.\n\t* ov-str-mat.h, ov-str-mat.cc (octave_char_matrix_str::is_true):\n\tDelete.\n\n\t* load-save.cc (read_ascii_data): Allow strings of length 0.\n\tIf we don't find data on the first call, fail with error message.\n\t(do_load): Pass count of items read to read_ascii_data.\n\tAllow `load foo xyz' to work when foo contains only numbers.\n\nFri Jan 30 23:46:42 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-str-mat.h (octave_char_matrix_str::all): Delete.\n\t(octave_char_matrix_str::any): Delete.\n\t* ov-ch-mat.h (octave_char_matrix::all, octave_char_matrix::any):\n\tCall charMatrix::all, charMatrix::any.\n\nThu Jan 29 16:25:46 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (read_mat_binary_data): Handle third digit of MOPT\n\tas flag indicating row or column major ordering.\n\nWed Jan 28 00:18:17 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/dassl.cc (lsode_option_table):\n\tAdd missing & to function names.\n\t* DLD-FUNCTIONS/lsode.cc (lsode_option_table): Likewise.\n\t* DLD-FUNCTIONS/quad.cc (quad_option_table): Likewise.\n\n\t* Makefile.in (oct-gperf.h): Add -G option to gperf.\n\n\t* load-save.cc (get_save_type): Add `UL' and `L' suffixes to large\n\tconstant values.  For LS_INT, use <= and >= for comparison.\n\nMon Jan 26 13:17:59 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-usr-fcn.cc (Vmax_recursion_depth): New static variable.\n\t(max_recursion_depth): New fucnction\n\t(symbols_of_ov_usr_fcn): DEFVAR max_recursion_depth.\n\t(octave_user_function::do_index_op): Check Vmax_recursion_depth.\n\nThu Jan 22 13:45:26 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc (make_dynamic_loader): Fix typo.\n\nTue Jan 20 17:02:19 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (Fexist): If local symbol is undefined, check\n\tglobal table.\n\n\t* pr-output.cc (pr_max_internal): Initial value for result is\n\t-DBL_MAX, not DBL_MIN.\n\nThu Jan  8 11:54:33 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* xpow.cc (elem_xpow): If second arg of pow is complex, make sure\n\tfirst arg is also complex.\n\n\t* symtab.cc (symbol_table::rename): Properly insert new item at\n\tthe front of the list to avoid losing the rest of the items.\n\nThu Dec 11 23:30:03 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (Fclear): Increment index to skip -x arg.\n\nTue Dec  9 02:45:35 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (INCLUDES): Don't forget Pix.h.\n\n\t* BaseSLList.cc: Don't include nonstandard libg++ header files.\n\nSun Nov 30 14:58:56 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc: Include cmath, not oct-math.\n\t* sysdep.cc: Likewise.\n\n\t* DLD-FUNCTIONS/bessel.cc: New file.\n\t* Makefile.in (DLD_XSRC): Add it to the list.\n\nThu Nov 27 23:28:59 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (handle_string): Constructor for string class takes\n\t(size_t, char) args, not (char, size_t).\n\nWed Nov 26 00:39:34 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (OCTAVE_LIBS): Include $(SPECIAL_MATH_LIB) just\n\tahead of -lcruft.\n\nThu Nov 20 15:16:22 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (maximum_braindamage): Bind implicit_num_to_str_ok to 1.\n\t* pt-mat.cc (Vimplicit_num_to_str_ok): New static variable.\n\t(implicit_num_to_str_ok): New function.\n\t(symbols_of_pt_mat): DEFVAR implicit_num_to_str_ok.\n\t(tm_row_const::some_str): New data member.\n\t(tm_row_const::some_strings_p): New function.\n\t(tm_row_const::init): Set some_str.\n\t(tm_const::some_str): New data member.\n\t(tm_const::some_strings_p): New function.\n\t(tm_const::init): Set some_str.\n\t(tree_matrix::eval): If Vimplicit_num_to_str_ok is true and some\n\tof the elements are strings, force a string conversion before\n\treturning.\n\n\t* parse.y (fold, finish_colon_expression, finish_matrix):\n\tIf an error occurs, return the original expression.\n\tUse unwind_protect to restore error_state.\n\n\t* ov-ch-mat.h (octave_char_matrix::convert_to_str): Result is\n\tchar_matrix_str, not just char_matrix.\n\nWed Nov 19 02:05:40 1997  Mumit Khan  <khan@dhaka.xraylith.wisc.edu>\n\n\t* DLD-FUNCTIONS/filter.cc: Don't include extern template decls if\n\tCXX_NEW_FRIEND_TEMPLATE_DECL is defined.\n\t* ov-cx-mat.cc: Likewise.\n\t* ov-re-mat.cc: Likewise.\n\t* ov-str-mat.cc: Likewise.\n\n\t* ov-cx-mat.h (octave_complex_matrix::decrement,\n\toctave_complex_matrix):\tUse explicit Complex constructor.\n\nWed Nov 19 00:08:13 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-decl.cc (tree_global_command::do_init): Initialize global\n\tvalues to `[]'.  Only perform explicit initialization once.\n\nTue Nov 18 04:27:55 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (Vfixed_point_format): New variable.\n\t(fixed_point_format): New fucntion.\n\t(symbols_of_pr_output): Add DEFVAR for fixed_point_format.\n\t(set_real_matrix_format): Handle fixed point format\n\t(set_complex_matrix_format): Handle fixed point format\n\t(set_format): New arg, scale in Matrix, ComplexMatrix, Range versions.\n\t(pr_scale_header): New function.\n\t(octave_print_internal): Handle fixed point format in Matrix,\n\tComplexMatrix, and Range versions.\n\t* octave.cc (maximum_braindamage): Set fixed_point_format to 1.0.\n\n\t* utils.cc (do_string_escapes): Move here, from lex.l.\n\tArg is now const string& instead of char*.\n\tReturn new string object instead of modifying arg in place.\n\t(Fdo_string_escapes): New function.\n\t* lex.l (handle_string): Use new version of do_string_escapes.\n\n\t* lex.l (Vbackslash_escapes): Delete.\n\t(backslash_escapes): Delete.\n\t(do_string_escapes): Undo previous change.\n\t(eat_whitespace, eat_continuation): Undo previous change.\n\t(handle_string): Undo previous change.\n\t(symbols_of_lex): Undo previous change.\n\t* octave.cc (maximum_braindamage): Undo previous change.\n\nFri Nov 14 01:53:13 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (eval_string (const string&, bool, int&, int)): No\n\tlonger static.\n\t* parse.h: Provide declaration.\n\t* input.cc (get_user_input (const octave_value_list&, bool, int)):\n\tNew arg, nargout.  Pass it to eval_string.\n\t(keyboard): Pass nargout = 0 to get_user_input.\n\t(input): Pass nargout to get_user_input.\n\n\t* input.cc (get_user_input (const octave_value_list&, bool)):\n\tReturn octave_value_list() if user enters `quit', `exit', or `return'.\n\tIf debugging, let eval_string handle the printing chores and\n\treset error_state before asking for more input.\n\n\t* input.cc (Fkeyboard): Unconditionally turn on history here.\n\n\t* lex.l (have_continuation, have_ellipsis_continuation): Declare\n\targ as bool, not int.  Change callers.\n\n\t* lex.l (Vbackslash_escapes): New static variable.\n\t(backslash_escapes): New function.\n\t(do_string_escapes): Return immediately if ! Vbackslash_escapes.\n\t(eat_whitespace, eat_continuation): Only call have_continuation if\n\tVbackslash_escapes.\n\t(handle_string): Backslash is only special if Vbackslash_escapes.\n\t(symbols_of_lex): Add DEFVAR for backslash_escapes.\n\t* octave.cc (maximum_braindamage): Set backslash_escapes to 0.\n\nThu Nov 13 16:20:40 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (Fexist): Also return 2 if NAME is a regular file\n\tsomewhere in the LOADPATH.\n\n\t* data.cc (sumsq): Fix doc string.\n\n\t* parse.y (Fsource): Call parse_fcn_file, not parse_and_execute.\n\nTue Oct  7 16:51:01 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defun-int.h (DEFINE_FUN_INSTALLER_FUN): Set installed to true\n\tafter installing the function.\n\nThu Sep 25 10:17:26 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/filter.cc (Ffilter): Return second output value\n\teven when called with only 3 arguments.\n\nMon Sep 22 16:44:27 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/rand.cc (do_rand): Print error if first of two\n\targs is a string but doesn't match \"seed\".\n\t(Frand, Frandn): Fix doc string.\n\nMon Aug 25 10:42:07 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (get_user_input): Return an empty string if the user\n\tjust types RET.\n\nThu Jul 31 22:59:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l <TEXT_FCN>: Ensure that we handle words that begin with\n\tsingle or double quotes as strings.\n\nThu Jul 17 13:06:48 1997  Klaus Gebhardt  <gebhardt@crunch.ikp.physik.th-darmstadt.de>\n\n\t* DLD-FUNCTIONS/rand.cc (Frand): Use F77_XFCN to call getsd,\n\tsetsd, setall, setcgn, dgenunf, and dgennor since they can call\n\tXSTOPX.\n\nMon Jul 14 12:54:23 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc (octave_dynamic_loader::load_fcn_from_dot_oct_file):\n\tIf first attempt to load function fails, prepend and underscore\n\tand try again.\n\n\t* Makefile.in (install-inc): If defaults.h, oct-conf.h, or\n\toct-gperf.h don't exist in the current directory, look in $(srcdir).\n\nMon Jul  7 21:14:07 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/qr.cc (Fqr): Correctly handle nargout == 0.\n\nWed Jul  2 16:47:09 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* matherr.c: New file.  Move matherr function here.\n\t* sysdep.cc: From here.\n\t* Makefile.in (DIST_SRC): Add matherr.c to the list.\n\n\t* error.cc (handle_message): Avoid bug in g++ snapshot.\n\nThu Jun 26 22:04:09 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (file_in_path): Add default load path to PATH arg if\n\tit begins or ends with a colon.\n\nWed Jun 25 13:31:06 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-lvalue.h (octave_lvalue::struct_elt_ref): Ensure val is unique.\n\nFri Jun 20 12:33:35 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (cmd_death_handler): New function.\n\t(run_command_and_return_output): Insert pid of command in\n\toctave_child_list along with pointer to cmd_death_handler so we\n\tcan get the exit status without having to block SIGCHLD.\n\t(cleanup_iprocstream): Remove pid of command from octave_child_list.\n\nSun Jun 15 16:11:13 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* OPERATORS/op-cs-s.cc (ldiv): Doh, v1 is complex, v2 is real.\n\n\t* Makefile.in (DISTFILES): Add mkops to the list.\n\t(dist): Correctly link files in DLD-FUNCTIONS, OPERATORS, and\n\tTEMPLATE-INST subdirectories.\n\nFri Jun  6 04:30:57 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/npsol.cc, DLD-FUNCTIONS/qpsol.cc,\n\tDLD-FUNCTIONS/fsqp.cc: Delete.\n\t* Makefile.in (DLD_XSRC): Remove them from the list.\n\n\t* utils.cc (search_path_for_file): New arg, do_tilde_expansion.\n\tIf TRUE, perform tilde expansion on path before searching.\n\t(file_in_path): Call search_path_for_file with do_tilde_expansion\n\tset to false, since we've already performed tilde expansion on the\n\tload path.\n\n\t* defaults.cc (loadpath): Perform tilde expansion here.\n\nThu Jun  5 01:42:39 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Make building of static library optional.\n\t(liboctave.$(SHLEXT_VER)): Add $(SONAME_FLAGS) to command.\n\n\t* dynamic-ld.cc (octave_shl_load_dynamic_loader::resolve_reference):\n\tCall shl_findsym with type set to TYPE_UNDEFINED.\n\n\t* Makefile.in (stamp-picdir): Delete.\n\t(pic): New target.  Don't worry so much about creating pic\n\tdirectory only when it is really needed.\n\t(stamp-interp): Delete.\n\t(libraries): New target.  Depend on shared library directly.\n\nWed Jun  4 00:09:42 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (main): Call dir_path::set_program_name here.\n\nTue Jun  3 16:47:34 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (symbol_out_of_date): Make it work again.\n\n\t* parse.y (parse_and_execute): Move here from toplev.cc\n\t(default_eval_print_flag): Likewise.\n\t(safe_fclose): Likewise.\n\t(eval_string): Likewise.\n\t(Fsource): Likewise.\n\t(Ffeval): Likewise.\n\t(feval): Likewise.\n\t(Feval): Likewise.\n\t(symbols_of_parse): Define default_eval_print_flag here instead of\n\tin variables.cc.\n\t(looks_like_octave_copyright): Move here from variables.cc\n\t(gobble_leading_whitespace): Likeiwse.\n\t(is_function_file): Likewise.\n\t(restore_input_stream): Likewise.\n\t(parse_fcn_file): Likewise.\n\t(load_fcn_from_file): Likewise.\n\t(get_help_from_file): Likewise.\n\n\t* toplev.cc (syms_of_toplev): Define argv, program_name, and\n\tprogram_invocation_name here instead of in variables.cc.\n\n\t* parse.h (line_editing): Move here from toplev.h.  Now bool, not int.\n\t(reading_startup_message_printed) Likewise.\n\t(input_from_startup_file): Likewise.\n\t(input_from_command_line_file): Likewise.\n\n\t* load-save.cc: Use bool instead of int where appropriate.\n\n\t* input.h (enum echo_state): Move here from variables.h.\n\t(Vecho_executing_commands): Likewise.  Now bool, not int.\n\t* input.cc (echo_executing_commands): Move here from variables.cc.\n\t(symbols_of_input): Define echo_executing_commands here instead of\n\tin variables.cc.\n\n\t* octave.cc (program_invocation_name): Don't define.\n\t(intern_argv): Don't set program_invocation_name here.\n\t(main): Call octave_env::set_program_name here, not in intern_argv.\n\n\t* toplev.cc (quitting_gracefully): Move here from octave.h and\n\tmake static bool instead of extern int.\n\n\t* error.cc (bind_global_error_variable, clear_global_error_variable):\n\tMove here from variables.cc.\n\t(symbols_of_error): Define error_text here instead of in variables.cc.\n\n\t* pager.cc (write_to_diary_file): Now bool, not int.\n\t(really_flush_to_pager): Likewise.\n \t(flushing_to_pager): Likewise.\n\t* sighandlers.h (can_interrupt): Likewise.\n\t* error.h (buffer_error_messages): Likewise.\n\t* oct-hist.h (input_from_tmp_history_file, Vsaving_history): Likewise.\n\t* input.h (forced_interactive): Likewise.\n\t(get_input_from_eval_string): Likeiwse.\n\t(reading_script_file): Likeiwse.\n\t(reading_fcn_file): Likeiwse.\n\t(interactive): Likewise.\n\n\t* unwind-prot.cc (saved_variable::saved_variable (bool *, bool)):\n\tSet type_tag to boolean, not int.\n\nMon Jun  2 00:40:10 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.h (Octave_builtin_fcn): Delete typedef.\n\n\t* help.cc (make_name_list): Move here from variables.cc.\n\t(keyword_help, names): Now static.\n\t(struct help_list): Move declaration here from help.h.\n\n\t* oct-hist.cc (Vhistory_file, Vhistory_size, Vsaving_history):\n\tMove here from variables.cc.\n\t(symbols_of_oct_hist): New function.\n\n\t* version.h: Protect against multiple inclusion.\n\n\t* defun.cc (check_version): New function.\n\t* defun-int.h (DEFINE_FUN_INSTALLER_FUN): Use it.\n\n\t* help.h, help.cc (additional_help_message): Now extern.\n\t(operator_help): Now static.\n\n\t* defun.cc (print_usage): Move here from help.cc\n\t* DLD-FUNCTIONS/*.cc, data.cc, dirfns.cc, file-io.cc, input.cc,\n\tload-save.cc, octave.cc, ov-list.cc, ov-typeinfo.cc,\n\tov-usr-fcn.cc, pager.cc, pr-output.cc, pt-plot.cc, strfns.cc,\n\tsyscalls.cc, sysdep.cc, utils.cc, toplev.cc:\n\tDon't include help.h.\n\n\t* TEMPLATE-INST/Array-sym.cc: New file.\n\n\t* load-save.cc (do_load): Don't use ostream::form.\n\t* pr-output.cc: Likewise, at least where it is easy to do so.\n\t* oct-stream.cc: Ditto.\n\n\t* symtab.h (symbol_record::symbol_def::rows): New function.\n\t(symbol_record::symbol_def::columns): Ditto.\n\t(symbol_record::symbol_def::type_name): Ditto.\n\t(symbol_record::rows): Ditto\n\t(symbol_record::columns): Ditto\n\t(symbol_record::type_name): Ditto\n\n\t* symtab.h, symtab.cc (symbol_record::hides_fcn): New function.\n\t(symbol_record::hides_builtin): Ditto.\n\t(symbol_record::print_symbol_info_line): Ditto.\n\t(symbol_table::long_list): Delete.\n\t(symbol_table::symbol_list): New function.\n\t(symbol_table::maybe_list): Delete argc arg.\n\t(symbol_table::name_list): Rename from symbol_table::list.\n\tChange all callers.\n\n\t* symtab.h, symtab.cc (class symbol_record_info): Delete.\n\n\t* symtab.cc (matches_patterns): Use vector form of glob_match.\n\nSun Jun  1 14:04:26 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-check.h, pt-check.cc: New files, for semantic checking of\n\tparse trees.\n\n\t* symtab.h (class symbol_def): Now nested in symbol_record class.\n\t(enum TYPE): Move from symbol_def to symbol record class.  Change\n\tall uses.\n\n\t* symtab.h, symtab.cc (symbol_table::maybe_list): New function,\n\tfrom variables.cc.  Change all uses.\n\n\t* pt-idx.h (tree_identifier::lvalue_ok): New function.\n\t* pt-id.h (tree_index_expression::lvalue_ok): Likewise.\n\t* pt-indir.h (tree_indirect_ref::lvalue_ok): Likewise.\n\n\t* pt-pr-code.h, pt-pr-code.cc (tree_print_code::visit_oct_obj): Delete.\n\t* pt-walk.h (tree_walker::visit_oct_obj): Delete declaration.\n\n\t* lex.h (class lexical_feedback): Delete maybe_screwed_again.\n\t* lex.l (lexical_feedback::init): Don't set it.\n\nFri May 30 16:07:22 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mappers.cc: Include <cfloat> here.\n\nTue May 27 10:08:43 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (eval_string): Don't index tmp if it is empty.\n\nSat May 24 00:18:41 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (valid_identifier): Move here and make static.\n\t* symtab.h, symtab.cc (valid_identifier): Delete declaration and\n\tdefinition.\n\nFri May 23 22:54:28 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* symtab.h (symbol_def::symbol_def): Use initializer list instead\n\tof calling init_state.\n\t(symbol_def::init_state): Delete.\n\n\t* symtab.cc (symbol_table::print_stats): New function.\n\t* variables.cc (F__dump_symtab_info__): New function.\n\n\t* symtab.h, symtab.cc (symbol_table::hash): Return masked value.\n\t(symbol_table::table_size): New data member.\n\t(symbol_table::symbol_table): Set size of table in constructor.\n\t(HASH_TABLE_SIZE): Replace uses with table_size.\n\t(HASH_MASK): Delete.\n\t* variables.cc (initialize_symbol_tables): Set top-level and\n\tglobal symbol table sizes here.\n\nThu May 22 13:32:55 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc (octave_shl_load_dynamic_loader::resolve_reference):\n\tCall shl_findsym with type set to TYPE_PROCEDURE.  Pass the\n\taddress of the pointer we want to define.\n\nWed May 21 16:30:25 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/time.cc (extract_tm): Avoid memory leak in dealing\n\twith time zone.\n\n\t* Makefile.in (install-in): Use new mk-includedir-link macro.\n\t(install-lib): Install in $octlibdir.  Use new mk-libdir-link macro.\n\nTue May 20 01:24:11 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-list.cc (Flist): Rename from Fmake_list.\n\nMon May 19 14:45:58 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (maximum_braindamage): Set default_eval_print_flag to 0.\n\nSat May 17 16:32:23 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.cc (set_default_editor): Default is now Emacs, not vi.\n\nFri May 16 00:07:11 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-idx.cc (tree_index_expression::name): New function.\n\n\t* pt.cc\t(tree::str_print_code): New file, new convenience function.\n\t* pt-arg-list.cc (tree_argument_list::get_arg_names): Use it.\n\t* pt-assign.cc (tree_simple_assignment::rvalue): Likewise.\n\t(tree_multi_assignment::rvalue): Likewise.\n\n\t* pt-colon.h (tree_colon_expression::save_base): New data memmber.\n\t(tree_colon_expression::preserve_base): New function.\n\t* parse.y (finish_colon_expression): When converting to a simple\n\texpression, be sure to delete the original colon expression but\n\tnot the base value.\n\n\t* pt-mat.cc (tree_matrix::~tree_matrix): Actually do something.\n\n\t* pt-all.h: New file.\n\t* parse.y, lex.l, pt-pr-code.cc: Use it.\n\n\t* pt.h: Rename from pt-base.h.\n\n\t* All parse tree classes: Add private copy constructors and\n\tassignment operators to prevent copying.\n\n\t* pt-base.cc: Delete.\n\n\t* unwind-prot.h, unwind-prot.cc: Make a bit more object-oriented.\n\tChange all uses of unwind_protect stuff to match.\n\n\t* pt-jump.h, pt-jump.cc (breaking, continuing, returning):\n\tMake these flags static members of the corresponding class.\n\tChange all uses.\n\n\t* pt-assign.cc (tree_simple_assignment_expression::eval,\n\ttree_multi_assignment_expression::eval): Clear lvalue index here.\n\n\t* oct-lvalue.cc (octave_lvalue::assign): Don't clear index here.\n\t* oct-lvalue.h (octave_lvalue::clear_index): New function.\n\t(octave_lvalue::set_index): Rename from octave_lvalue::index.\n\tChange all callers.\n\nThu May 15 11:48:10 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-select.h, pt-select.cc (class tree_if_command_list,\n\tclass tree_if_clause, class tree_switch_case_list,\n\tclass tree_switch_case): Move here from pt-misc.h, pt-misc.cc.\n\t* pt-decl.h, pt-decl.cc (class tree_decl_init_list,\n\tclass tree_decl_elt): Move here from pt-mist.h, pt-misc.cc\n\n\t* pt-arg-list.h, pt-stmt.h: New files, extracted from pt-misc.h.\n\t* pt-arg-list.cc, pt-stmt.cc: New files, extracted from pt-misc.cc.\n\n\t* pt-decl.h, pt-except.h, pt-jump.h, pt-loop.h, pt-select.h:\n\tNew files, extraced from pt-cmd.h.\n\t* pt-decl.cc, pt-except.cc, pt-jump.cc, pt-loop.cc, pt-select.cc:\n\tNew files, extraced from pt-cmd.cc.\n\n\t* pt-unop.h, pt-binop.h, pt-colon.h, pt-idx.h, pt-assign.h:\n\tNew files, extracted from pt-exp.h\n\t* pt-unop.cc, pt-binop.cc, pt-colon.cc, pt-idx.cc, pt-assign.cc:\n\tNew files, extracted from pt-exp.cc\n\t* pt-exp.h, pt-exp.cc: Rename from pt-exp-base.h, pt-exp-base.cc.\n\n\t* oct-lvalue.h: Rename from oct-var-ref.h.  Rename class from\n\toctave_variable_reference to octave_lvalue.  Change all uses.\n\t* oct-lvalue.cc: Rename from oct-var-ref.cc.\n\n\t* variables.cc (bind_ans): Only bind ans and print result if value\n\tis defined.\n\n\t* defun.cc: New file.  Move functions for installing objects in\n\tthe symbol table here from variables.cc.\n\n\t* oct-obj.h, oct-obj.cc: Add custom allocator, fwiw.\n\n\t* toplev.cc (main_loop): Correctly increment command number.\n\n\t* TEMPLATE-INST/SLList-tm.cc: Don't instantiate lists of pointers\n\tto tree_matrix_row objects.\n\t* TEMPLATE-INST/SLList-misc.cc: Do instantiate lists of pointers\n\tto tree_argument_list objects.\n\n\t* DLD-FUNCTIONS/dassl.cc: Update to use new octave_function\n\tinterface to user-supplied functions.\n\t* DLD-FUNCTIONS/fsolve.cc: Likewise.\n\t* DLD-FUNCTIONS/lsode.cc: Likewise.\n\t* DLD-FUNCTIONS/npsol.cc: Likewise.\n\t* DLD-FUNCTIONS/quad.cc: Likewise.\n\n\t* dynamic-ld.h, dynamic-ld.cc (builtin_fcn_installer typedef):\n\tRename from builtin_fcn.\n\t(octave_dynamic_loader::load_fcn_from_dot_oct_file):\n\tSimplify by using new installer function defined by DEFUN_DLD.\n\n\t* defun-dld.h (DEFUN_DLD): Use DEFINE_FUN_INSTALLER_FUN instead of\n\tDEFINE_FUN_STRUCT_FUN.\n\t* defun.h (DEFUN_MAPPER): Use DEFUN_MAPPER_INTERNAL.\n\t* defun-int.h (DEFVAR_INTERNAL): Rename from DEFVAR_INT and move\n\there from defun.h.  Change all uses.\n\t(DEFUN_MAPPER_INTERNAL): New macro.\n\t(DEFINE_FUN_INSTALLER_FUN): New macro to define function that the\n\tdynamic loader calls to do all the work of installing a new function.\n\t(DEFINE_FUN_STRUCT_FUN): Delete.\n\n\t* parse.y: Rewrite to handle more general expressions.\n\t* lex.l: Corresponding changes.\n\n\t* pt-walk.h, pt-pr-code.h, pt-pr-code.cc: Cope with new parse tree\n\tobject structure.\n\n\t* pt-misc.cc (class tree_for_command): Split into\n\ttree_simple_for_command and tree_complex_for_command classes.\n\n\t* pt-misc.h, pt-misc.cc (tree_statement::eval): Handle identifier\n\tlookup and printing and binding ans here.\n\t(tree_statement_list::eval): Simplify.\n\t(tree_argument_list::all_elements_are_constant): New function.\n\t(class tree_decl_elt): Now contains id and expr, not an assignment\n\texpression.\n\n\t* pt-exp-base.h pt-exp.h pt-id.h pt-indir.h pt-mat.h pt-const.h,\n\tpt-exp-base.cc pt-exp.cc pt-id.cc pt-indir.cc pt-mat.cc pt-const.cc:\n\tReplace eval functions with rvalue and lvalue functions.\n\tChange all uses.\n\t(lvalue_ok, rvalue_ok): New functions, for future compile-time\n\tsemantic checks.\n\n\t* oct-var-ref.h (is_defined, is_map): New functions.\n\n\t* pt-exp.h (class tree_oct_obj): Delete.\n\n\t* variables.cc (extract_function, is_valid_function): Return\n\tpointer to octave_function, not octave_symbol.\n\t(link_to_global_variable): Rewrite.  Handle errors in\n\tsymbol_record::mark_as_linked_to_global.\n\n\t* symtab.h, symtab.cc (class symbol_def, class symbol_record):\n\tSymbols are now stored as octave_value objects only.\n\n\t* ov.cc (install_types): Register function types here.\n\t* ov-fcn.h, ov-fcn.cc, ov-builtin.h, ov-builtin.cc, ov-mapper.h,\n\tov-mapper.cc, ov-usr-fcn.h, ov-usr-fcn.cc: New classes for\n\tfunctions as values.\n\t* ov.h (class octave_value): Don't derive from octave_symbol.\n\t* oct-fcn.h, oct-fcn.cc, oct-builtin.h, oct-builtin.cc,\n\toct-mapper.h, oct-mapper.cc, oct-usr-fcn.h, oct-usr-fcn.cc,\n\toct-sym.h, oct-sym.cc: Delete.\n\nSun May 11 17:51:22 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (Ftype): Make it work again for functions.\n\n\t* pt-pr-code.cc (tree_print_code::print_parens): New function.\n\tUse it in other tree_print_code functions to handle printing all\n\tthe parens that we found when parsing the expression, not just one\n\tpair.\n\t* pt-exp-base.h (tree_expression::paren_count): Rename from\n\tis_in_parens.\n\t* parse.y (maybe_warn_assign_as_truth_value): Use new name.\n\n\t* parse.y (constant): New non-terminal.\n\t(simple_expr1): Use it.\n\n\t* parse.y (make_unary_op): Delete.\n\t(simple_expr1): Where appropriate, use make_prefix_op and\n\tmake_postfix_op instead of make_unary_op.  Allow increment and\n\tdecrement ops to work on expressions, not just identifiers.\n\t(make_prefix_op, make_postfix_op): Arg is expression, not identifier.\n\tHandle old unary_op cases too.\n\t(fold (tree_unary_expression *)): Delete.\n\t* pt-exp.h, pt-exp.cc (tree_prefix_expression::eval): Handle unary\n\tminus and not here.\n\t(tree_postfix_expression::eval): Likewise, for transpose and hermitian.\n\t(class tree_prefix_expression, class tree_postfix_expression):\n\tDerive from tree_unary_expression.  Delete identifier member.\n\tDelete ident member function.\n\t(tree_unary_expression): Don't handle evaluation here.\n\t* pt-exp-base.h (mark_in_parens): No longer virtual. Return this.\n\t(reference): New virtual function.\n\t(class tree_expression): Don't handle expression type here.\n\t* pt-mvr-base.h (tree_multi_val_ret::tree_multi_val_ret): Likewise.\n\t* pt-mvr.h, pt-mvr.cc (tree_multi_assignment_expression): Likewise.\n\t* pt-walk.h (visit_unary_expression): Delete declaration.\n\t* pt-pr-code.h, pt-pr-code.cc (visit_unary_expression): Delete.\n\t(visit_prefix_expression): Use operand(), not ident().\n\tnew, visit_postfix_expression):\n\t* pt-id.h, pt-id.cc (increment, decrement): Delete.\n\n\t* pt-misc.cc (tree_parameter_list::define_from_arg_vector): Get a\n\treference to each element and use the assignment operator instead\n\tof tree_identifier::define.\n\t* pt-id.h, pt-id.cc (tree_identifier::define): Delete versions\n\tthat take octave_value and octave_symbol args.\n\nSat May 10 23:32:13 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-indir.h, pt-indir.cc (tree_indirect_reference::value): Delete.\n\n\t* oct-var-ref.cc (octave_variable_ref::assign): Clear idx after\n\tassignment.\n\n\t* octave_value classes: Add is_constant, is_function, and\n\tfunction_value functions.\n\n\t* ov.h, ov.cc (assign): Return void, not reference to octave_value.\n\t(do_index_op): Rename, from index.\n\t(do_struct_elt_index_op): Rename, from struct_elt_val.\n\tAdd version that accepts index arg.\n\tChange all uses and derived classes to match.\n\t* pt-const.h (index): Delete.\n\t* oct-var-ref.h, oct-var-ref.cc (value): Handle indexed structure\n\tops here too.\n\nFri May  9 07:40:59 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-exp.cc (print_rhs_assign_val, symbols_of_pt_exp): New functions.\n\t(Vprint_rhs_assign_val): New static variable.\n\t(tree_simple_assignment_expression::eval): Use it to optionally\n\tallow the rhs (which is the result) of an assignment to be printed\n\tinstead of the left.\n\n\t* pt-exp.cc (tree_simple_assignment_expression::eval): Use new\n\toctave_variabl_reference::index function to handle indexing.\n\n\t* oct-var-ref.h, oct-var-ref.cc (idx): New data member.\n\t(octave_variable_reference::index): Set it.\n\t(octave_variable_reference::assign): Handle indexing here.\n\tDelete version of this function htat takes index arg.\n\n\t* variables.h (struct builtin_variable): Delete.\n\t* variables.cc (install_builtin_variable): Take all elts of\n\tbuiltin_variable struct directly.\n\t* defun.h (DEFVAR_INT): Call install_builtin_variable directly.\n\n\t* symtab.h, defun-int.h: Don't include variables.h.\n\n\t* symtab.h (symbol_record::sv_function): Move typedef here.\n\t* variables.h: From here.\n\n\t* oct-var-ref.h, oct-var-ref.cc: New files for\n\toctave_variable_reference class, extracted from variables.h and\n\tvariables.cc\n\t* Makefile.in: Add them to the appropriate lists.\n\n\t* oct-obj.h (octave_value_list::empty): New function.\n\n\t* variables.h (class octave_variable_reference):  Rewrite to work\n\tas a proxy class to store a pointer to octave_value and,\n\toptionally, the change function to call and the name of the\n\tstructure element we are referencing.  Handle assignment,\n\tincrement, decrement, and value operations.\n\nThu May  8 23:40:59 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-re-mat.h, ov-re-mat.cc (struct_elt_ref, struct_elt_val,\n\tassign_struct_elt): Provide functions for looking up and setting\n\tmatrix dimensions.\n\n\t* symtab.cc (symbol_record::define): Don't call sv_fcn here.\n\tDon't save and restore value here.\n\t(symbol_record::define_builtin_var): Do call sv_fcn here.\n\t(symbol_record::variable_reference): Don't make value unique here.\n\tReturn pointer to sv_fcn in octave_variable_reference.\n\n\t* pt-misc.cc (tree_parameter_list::initialize_undefined_elements):\n\tSimplify.\n\n\t* pt-id.h, pt-id.cc (tree_identifier::reference): Return\n\toctave_variable_reference, not octave_value&.\n\t* symtab.h, symtab.cc (symbol_record::variable_reference): Ditto.\n\t* pt-indir.h, pt-indir.cc (tree_indirect_ref::reference): Ditto.\n\tSimplify too.\n\n\t* pt-const.h (tree_constant::reference, tree_constant::value,\n\ttree_constant::assign):  Delete unnecessary functions.\n\t* pt-id.h, pt-id.cc (tree_identifier::assign): Ditto.\n\n\t* pt-cmd.cc (tree_for_command::do_for_loop_once): Simplify.\n\n\t* ov.h, ov.cc, ov-base.h, ov-base.cc, ov-struct.h, ov-struct.cc\n\t(struct_elt_ref): New arg, octave_value* parent.\n\tAllow deferred lookup.  Return octave_variable_reference, not\n\toctave_value&.\n\n\t* ov.h, ov.cc, ov-re-mat.h, ov-re-mat.cc (assign_struct_elt):\n\tNew virtual functions.\n\n\t* ov.h, ov.cc (Vresize_on_range_error): Now static.\n\n\t* pt-mvr.cc (tree_index_expression::eval): Delete redundant check\n\tof error_state.\n\nWed May  7 21:17:00 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (generate_completion): Rename from command_generator.\n\tUse string objects instead of char*.\n\t(generate_possible_completions): Let qsort also make matches unique.\n\t(initialize_command_input): Register generate_completion with the\n\tcommand_editor class.\n\t(completion_matches): Simplify using generate_completion.\n\n\t* pt-pr-code.cc (tree_print_code::visit_constant): For val, call\n\tprint_raw, not print.\n\n\t* oct-usr-fcn.h (octave_user_function::argn_sr): New data member.\n\t(octave_user_function::install_automatic_vars): Rename from\n\tinstall_nargin_and_nargout.\n\t(octave_user_function::bind_automatic_vars): Rename from\n\tbind_nargin_and_nargout.\n\t* oct-usr-fcn.cc (octave_user_function::eval): Extract arg names\n\tfrom args vector and bind them to argn.\n\t* oct-obj.h (octave_value_list::names): New data member.\n\t* oct-obj.cc (octave_value_list::stash_name_tags): New function.\n\t(octave_value_list::name_tags): Ditto.\n\t* pt-const.h, pt-const.cc (tree_constant::print_raw): New function.\n\t* pt-misc.h, pt-misc.cc (tree_argument_list::get_arg_names):\n\tNew function.\n\t* pt-mvr.h, pt-mvr.cc (class index_expression): Cache arg names.\n\t* toplev.cc (feval): Now static.  Handle arg names.\n\n\t* mkops: Cope with moving files defining operators to OPERATORS\n\tsubdirectory.\n\nTue May  6 00:48:59 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* DLD-FUNCTIONS/getgrent.cc: Use new octave_group class.\n\t* DLD-FUNCTIONS/getpwent.cc: Use new octave_passwd class.\n\n\t* syscalls.cc: Simplify by using new functions defined in\n\tliboctave/oct-syscalls.cc.\n\n\t* file-io.cc (Ftmpnam): Accept DIR and PREFIX args.\n\nMon May  5 00:54:03 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-str-mat.cc (octave_char_matrix_str::print_name_tag): Print\n\tempty strings on one line.\n\n\t* DLD-FUNCTIONS, OPERATORS, and\tTEMPLATE-INST: New subdirectories.\n\tMove appropriate files to new directories.\n\t* Makefile.in: Add DLD-FUNCTIONS, OPERATORS, and TEMPLATE-INST\n\tdirectories to VPATH.  Fix rules to work with new directory\n\tstructure.\n\nSun May  4 22:40:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t*  input.cc (initialize_command_input): Rename from\n\tinitialize_readline.\n\t(gnu_readline, octave_gets, get_user_input): Simplify, return\n\tstring, not char *.\n\n\t* Many of other files: Miscellaneous changes to go along with the\n\tchanges described in the liboctave/ChangeLog for May 4.  More code\n\tmoved from here to liboctave.\n\nFri May  2 19:50:33 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathlen.h: Move to ../liboctave.\n\nThu May  1 21:50:44 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (get_struct_elts): New fucntion.\n\t(looks_like_struct, generate_struct_completions): Move here from\n\tinput.cc, rewrite, and make work again.\n\nWed Apr 30 00:24:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool.cc, ov-bool.h,\n\tov-ch-mat.cc, ov-ch-mat.h, ov-complex.cc, ov-complex.h,\n\tov-cx-mat.cc, ov-cx-mat.h, ov-file.cc, ov-file.h, ov-list.cc,\n\tov-range.cc, ov-range.h, ov-re-mat.cc, ov-re-mat.h, ov-scalar.cc,\n\tov-scalar.h, ov-str-mat.cc, ov-struct.cc, ov.h (scalar_value):\n\tNew function.  Same as double_value, but name is consistent with\n\toctave_scalar class.\n\n\t* op-fil-b.cc, op-fil-cm.cc, op-fil-lis.cc, op-fil-rec.cc,\n\top-fil-str.cc, op-fil-bm.cc, op-fil-cs.cc, op-fil-m.cc,\n\top-fil-s.cc: New files.\n\n\t* ops.h (ASSIGNOPDECL, DEFASSIGNOP, DEFASSIGNOP_FN, CONVDECL,\n\tDEFCONV, BINOPDECL, DEFBINOPX, DEFBINOP, DEFBINOP_OP, DEFBINOP_FN,\n\tBINOP_NONCONFORMANT): New macros.\n\t* op-b-b.cc, op-bm-bm.cc, op-cm-cm.cc, op-cm-cs.cc, op-cm-m.cc,\n\top-cm-s.cc, op-cs-cm.cc, op-cs-cs.cc, op-cs-m.cc, op-cs-s.cc,\n\top-m-cm.cc, op-m-cs.cc, op-m-m.cc, op-m-s.cc, op-s-cm.cc,\n\top-s-cs.cc, op-s-m.cc, op-s-s.cc, op-str-str.cc: Use them.\n\n\t* Makefile.in (octave): Also depend on ops.o.\n\n\t* builtins.h: Delete.\n\t* octave.cc: Add extern declaration here.\n\n\t* mappers.h: Delete.\n\t* Makefile.in (INCLUDES): Delete from list.\n\t* mkbuiltins: Add extern declaration in builtins.cc.\n\n\t* mkops: New file.\n\t* ops.cc: Delete.\n\t* Makefile.in (SOURCES): Delete from the list.\n\t(ops.cc): New target.\n\t(OP_SOURCES): New list.  Move all op-*.cc files here from SOURCES.\n\tAdd $(OP_SOURCES) to SOURCES list.\n\n\t* variables.cc (symbols_of_variables): No longer static.\n\t* ov.cc (symbols_of_ov): Rename from symbols_of_value.\n\n\t* ov-base.h: Delete declaration for install_base_type_conversions.\n\t* op-b-b.h, op-bm-bm.h, op-cm-cm.h, op-cm-cs.h, op-cm-m.h,\n\top-cm-s.h, op-cs-cm.h, op-cs-cs.h, op-cs-m.h, op-cs-s.h,\n\top-m-cm.h, op-m-cs.h, op-m-m.h, op-m-s.h, op-s-cm.h, op-s-cs.h,\n\top-s-m.h, op-s-s.h, op-str-str.h: Delete.\n\t* Makefile.in (INCLUDES): Delete them from the list.\n\nTue Apr 29 22:27:49 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.h, variables.cc (install_builtin_variables): Delete.\n\t* mkbuiltins: Also generate install_builtin_variables function.\n\t* Makefile.in: Fix rule to call mkbuiltins with correct args.\n\t(clean): Also delete def-files and var-files.\n\t* defaults.h.in, dirfns.h, error.h, file-io.h, help.h, input.h,\n\tlex.h, load-save.h, oct-usr-fcn.h, pager.h, parse.h, pr-output.cc,\n\tpr-output.h, pt-mat.h, pt-misc.h, pt-plot.h, toplev.h:\n\tDelete declarations of symbols_of_* functions.\n\t* data.h, syscalls.h: Delete.\n\n\t* pr-output.cc (octave_print_internal): Leave printing of final\n\tnew line up to the caller.\n\n\t* ov.h, ov.cc (reset_indent_level, increment_indent_level,\n\tdecrement_indent_level, newline, indent, reset,\n\tcurr_print_indent_level, beginning_of_line):\n\tNew functions and static data to manage indent level for printing.\n\t(print_as_scalar): Delete.\n\t(print, print_with_name): Always require stream arg.\n\tChange all callers.\n\n\t* oct-stream.h (octave_stream::input_stream): Make publicly available.\n\t(octave_stream::output_stream): Likewise.\n\n\t* ov-base.h, ov-base.cc, ov.h, ov.cc, ov-file.h ov-base.h\n\t(is_file, stream_value, stream_number): New functions.\n\t* ov-file.h, ov-file.cc: New files for value class to manage files.\n\t* file-io.cc (symbols_of_file_io): Define stdin, stdout, and\n\tstderr as octve_file objects, not just integers.\n\t(Ffopen, Fpopen): Return octave_file objects, not integer file ids.\n\t* syscalls.cc (Fpipe): Likewise.\n\t* oct-stream.h, oct-stream.cc (octave_stream_list::insert):\n\tReturn octave_file object, not integer file id.\n\n\t* ov-base.cc, ov-bool-mat.cc, ov-bool.cc, ov-ch-mat.cc,\n\tov-complex.cc, ov-cx-mat.cc, ov-file.cc, ov-list.cc, ov-range.cc,\n\tov-re-mat.cc, ov-scalar.cc, ov-str-mat.cc, ov-struct.cc, ov.cc\n\t(print_name_tag, print_raw): New functions.\n\n\t* help.cc (Ftype): Don't cast symbol definition to tree_constant *.\n\n\t* variables.cc (link_to_global_variable): Don't try to define\n\tsymbol with tree_constant objects.\n\t(bind_ans): Call symbol_record::define directly and then\n\toctave_value::print_with_name instead of creating a temporary\n\tassignment expression.\n\n\t* pt-pr-code.cc (tree_print_code::indent): Don't use ostream::form.\n\n\t* pt-exp-base.h, pt-exp.h, pt-exp.cc (oper): Return string, not\n\tchar *.  Change all where necessary.\n\nMon Apr 28 16:33:49 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_value binary_op enum): Add lshift and rshift.\n\t(octave_value assign_op enum): Add lshift_eq and rshift_eq.\n\t* ov.cc (assign_op_as_string, binary_op_as_string): Include them.\n\t* parse.y (LSHIFT_EQ RSHIFT_EQ LSHIFT RSHIFT): New tokens.\n\tAdd them to the precedence list.\n\t(simple_expr): Add new operators.\n\t(make_assign_op, make_binary_op): Handle new operators.\n\t* lex.l: Recognize new operators.\n\n\t* lex.l: Recognize them.\n\nSun Apr 27 20:17:49 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-misc.cc (Vsilent_functions, silent_functions):\n\tMove here from oct-usr-fcn.cc.\n\t(symbols_of_pt_misc): New function.  DEFVAR silent_functions.\n\t(tree_statement_list::eval): Handle Vsilent_functions here instead\n\tof in octave_user_function::eval.\n\t(tree_statement::eval): New functions.\n\t(tree_statement_list::eval): Use them.\n\tChange print flag arg to silent flag.  Change all callers.\n\t* variables.cc (install_builtin_variables): Call symbols_of_pt_misc.\n\t* toplev.cc (parse_and_execute): Delete print arg.  Change all callers.\n\t(eval_string): Change print flag arg to silent flag.  Change callers.\n\n\t* dynamic-ld.h, dynamic-ld.cc: Rewrite to use singleton class.\n\t* variables.cc (load_fcn_from_file): Use new dynamic linking class.\n\n\t* dynamic-ld.h (Octave_builtin_fcn): Delete typedef.\n\t* dynamic-ld.cc: Simplify via the magic of function pointers.\n\n\t* pt-fcn.h pt-fcn.cc pt-fvc.h pt-fvc.cc pt-fvc-base.h pt-fvc-base.cc:\n\tDelete obsolete files.\n\t* Makefile.in: Remove them from various lists.\n\n\t* pt-walk.h (visit_octave_user_function): Rename from visit_function.\n\t(visit_builtin): Delete.\n\t* pt-pr-code.h, pt-pr-code.cc (visit_octave_user_function):\n\tRename from visit_function.\n\t(visit_octave_user_function_header): Rename from visit_function_header.\n\t(visit_octave_user_function_trailer): Rename from\n\tvisit_function_trailer.\n\n\t* ov.h, ov.cc (eval): New functions.\n\n\t* dassl.cc, fsolve.cc, lsode.cc, npsol.cc, qpsol.cc, quad.cc:\n\tDeclare user-defined functions as a pointer to an octave_symbol\n\tobject, not as a pointer to a tree_fvc object.\n\n\t* symtab.h, symtab.cc: Use new octave_symbol class.\n\t* variables.cc (install_builtin_function, install_builtin_mapper,\n\tinstall_builtin_variable, install_builtin_variable_as_function):\n\tMake work with new octave_symbol class and symbol table structure.\n\n\t* variables.h: Delete declaration of builtin_function struct.\n\t* defun-dld.h (DEFUN_DLD): Simplify.\n\t* defun-int.h (DEFINE_FUN_STRUCT): Delete.\n\t(DEFINE_FUN_STRUCT_FUN): Rewrite to not use static builtin_function\n\tobject.\n\n\t* mappers.h: Delete declaration of builtin_mapper_function struct.\n\t* mappers.cc: Declare wrapper functions static.\n\t* defun.h (DEFUN_MAPPER): Simplify.\n\n\t* oct-sym.h: New file.  Declare base class for Octave symbols.\n\t* ov.h: Derive octave_value class from octave_symbol.\n\t* oct-fcn.h, oct-fcn.cc: New files to declare and define\n\tbase class for functions.\n\t* oct-builtin.h, oct-builtin.cc: New files to declare and define\n\tclass for built-in functions.\n\t* oct-mapper.h, oct-mapper.cc: New files to declare and define\n\tclass for mapper functions.\n\t* oct-usr-fcn.h, oct-usr-fcn.cc: New files to declare and define\n\tbase class for user-defined functions.\n\t* Makefile.in: Add new files to appropriate lists.\n\n\t* pt-id.h, pt-id.cc: Move tree_identifier class here.\n\t* pt-fvc.h, pt-fvc.cc: From here.\n\n\t* pt-indir.h, pt-indir.cc: Move tree_indirect_ref class here.\n\t* pt-fvc.h, pt-fvc.cc: From here.\n\nThu Apr 24 03:58:16 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (magic_colon): New nonterminal.\n\t(arg_list): Simplify using magic_colon.\n\n\t* lex.h (class lexical_feedback): Delete maybe_screwed field.\n\tNew field, parsed_function name.\n\t* lex.l (lexical_feedback::init): Initialize it.\n\t(handle_identifier): Don't return SCREW.  Handle switching\n\tsymbol table context properly for `function f ()' vs `function x ='.\n\t(is_keyword): If looking at function keyword, don't set current\n\tsymbol table to point to the local table.\n\t* parse.y (recover_from_parsing_function): New function.\n\t(finish_function_def): Use identifier, not token.\n\tSimplify parsing of functions.\n\n\t* ov-list.h, ov-list.cc: New files to implement generic list type.\n\t* ov.cc (list_indent): New global variable.\n\t(increment_list_indent, decrement_list_indent): New functions.\n\t(install_types): Register octave_list type.\n\t* ov-base.cc (octave_base_value::is_list): New function.\n\n\t* oct-sym.h: New file.\n\t* ov.h (class octave_value): Derive from octave_symbol class.\n\n\t* pt-const.h, pt-const.cc: Delete lots of old useless cruft.\n\n\t* pt-exp.h, pt-exp.cc (tree_binary_expression): Use type codes for\n\toperators from octave_value instead of repeating them here.\n\n\t* pt-fvc-base.cc (tree_fvc::increment, tree_fvc::decrement): Delete.\n\t* pt-fvc.cc (tree_identifier::increment): Get reference to value\n\tand increment that instead of using virutal tree_fvc::increment\n\tfunction.\n\n\t* lex.l: Handle +=, -=, *=, /=, .+=, .-=, .*=, ./=, &=, and |= ops.\n\t* parse.y (make_assign_op): Rename from make_simple_assignment and\n\thandle different op types.\n\t(simple_expr1): Do new ops.\n\t* pt-misc.cc (initialize_undefined_elements): Pass op to assign.\n\t* pt-cmd.cc (tree_for_command::do_for_command_once): Likewise.\n\t* pt-fvc.cc (tree_identifier::assign): Pass op.\n\t* pt-exp.cc (tree_simple_assignment_expression): Handle new ops.\n\t* variables.cc (octave_variable_reference::assign): Likewise.\n\t* ov.h (class octave_value): Likewise.\n\t* ov.cc (octave_value::assign_op_as_string): New function.\n\t(octave_value::assign, octave_value::convert_and_assign,\n\toctave_value::try_assignment_with_conversion,\n\toctave_value::try_assignment): Pass op.\n\t* pt-pr-code.cc (tree_print_code::visit_simple_assignment_expression):\n\tUse expr.oper() instead of printing \"=\".\n\t* op-cm-cm.cc, op-cm-cs.cc, op-cm-m.cc, op-cm-s.cc, op-m-m.cc,\n\top-m-s.cc, op-str-str.cc: Pass op to INSTALL_ASSIGNOP.\n\t* ops.h (INSTALL_ASSIGNOP): Pass op.\n\t* ov-typeinfo.cc (do_register_assign_op): Include op type in table.\n\t(do_lookup_assign_op): Use op in lookup.\n\n\t* ops.h (INSTALL_UNOP): Delete.\n\n\t* input.cc (generate_struct_completions, looks_like_struct):\n\tDisable, since they don't work now anyway.\n\n\t* help.cc (Ftype): Work with octave_value instead of a pointer to\n\ttree_constant.\n\t* symtab.cc (symbol_record_info::symbol_record_info): Likewise.\n\nTue Apr 22 22:59:55 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (Ffprintf): If first arg is a string, assume FID = 1.\n\nFri Apr 18 20:16:34 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-obj.h, oct-obj.cc: Implement octave_value_list with\n\tArray<octave_value> as a data member, not as a class derived from\n\tArray<octave_value>.\n\t(octave_value_list::length, octave_value_list::resize,\n\toctave_value_list::prepend, octave_value_list::append,\n\toctave_value_list::reverse): New functions.\n\n\t* op-cm-cm.cc, op-cm-cs.cc, op-cm-m.cc, op-cm-s.cc, op-cs-cm.cc,\n\top-cs-m.cc, op-m-cm.cc, op-m-cs.cc, op-m-m.cc, op-m-s.cc,\n\top-s-cm.cc, op-s-m.cc: Use new bool ops from liboctave instead of\n\tthe macros defined in ops.h.\n\nThu Apr 17 13:12:22 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (ABORT_PARSE): Handle forced_interactive the same as\n\tinteractive.\n\nMon Apr 14 01:46:50 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (octave_read): Don't forget to free input buffer if it\n\texists and has zero length.\n\t(gnu_readline): Free buf if fgets returns 0.\n\nWed Apr  9 00:03:57 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* time.cc (mk_tm_map): Only set zone field if HAVE_TM_ZONE or\n\tHAVE_TZNAME are defined.\n\nTue Apr  8 12:39:21 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* time.cc (extract_tm): Set tm.tm_zone if HAVE_TM_ZONE is defined,\n\tnot if HAVE_TMZONE is defined.\n\n\t* Makefile.in (%.oct : %.o): Use $(SH_LD), not $(CXX).\n\nWed Apr  2 21:32:16 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc, dynamic-ld.h (init_dynamic_linker): Delete\n\tfunction and declaration.\n\t* octave.cc (main): Don't call it.\n\nMon Mar 31 00:37:48 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-base-exp.h (tree_expression::eval): Give arg a default value.\n\t* pt-const.h (tree_constant::eval): Likewise.\n\t* pt-exp.h (tree_prefix_expression::eval, tree_colon_expression::eval,\n\ttree_postfix_expression::eval, tree_unary_expression::eval,\n\ttree_binary_expression::eval, tree_boolean_expression::eval,\n\ttree_simple_assignment_expression::eval): Likewise.\n\t* pt-fcn.h (tree_function::eval): Likewise.\n\t* pt-fvc.h (tree_identifier::eval, tree_indirect_ref::eval,\n\ttree_builtin::eval): Likewise.\n\t* pt-mat.h (tree_matrix::eval): Likewise.\n\t* pt-misc.h (tree_statement_list::eval): Likewise.\n\t* pt-mvr-base.h (tree_multi_val_ret::eval): Likewise.\n\t* pt-mvr.h (tree_oct_obj::eval, tree_index_expression::eval,\n\ttree_multi_assignment_expression::eval): Likewise.\n\t* dassl.cc, fsolve.cc, load-save.cc, lsode.cc, npsol.cc, parse.y,\n\tpt-cmd.cc, pt-exp-base.cc, pt-exp.cc, pt-fvc.cc, pt-mat.cc,\n\tpt-misc.cc, pt-mvr.cc, pt-plot.cc, quad.cc, toplev.cc, variables.cc:\n\tChange callers of eval() to use bool instead of int and to make\n\tuse of default argument value.\n\n\t* toplev.h, toplev.cc (parse_and_execute, eval_string): Flag args\n\tare now bool instead of int.\n\n\t* symtab.h, symtab.cc: Use bool instead of int in more places.\n\t* variables.h, variables.cc: Likewise.\n\t* lex.h, lex.l: Likewise.\n\t* parse.y: Likewise.\n\t* help.cc, input.cc, lex.l, load-save.cc, parse.y, pt-fcn.cc:\n\tChange callers of symbol_table::lookup to use bool instead of int,\n\tand to make use of default arguments.\n\nFri Mar 28 15:33:11 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (Vwarn_comma_in_declaration): Delete.\n\t(symbols_of_parse): Delete DEFVAR for warn_comma_in_declaration.\n\t(decl1): Don't allow commas in declarations.\n\n\t* lsode.cc (struct LSODE_OPTIONS): Handle integer options.\n\t(print_lsode_option_list, set_lsode_option, show_lsode_option): Ditto.\n\t(lsode_option_table): Add element for step limit.\n\t(lsode_user_jacobian): New function.\n\t(Flsode): Allow function name arg to be a 2-element string array\n\tspecifying the function and jacobian function.\n\n\t* variables.cc (get_global_value, set_global_value): New functions.\n\nWed Mar 26 17:08:27 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\tImplement static variable declaration:\n\n\t* lex.l (is_keyword): Handle static.\n\t* octave.gperf: Likewise.\n\t* parse.y (Vwarn_comma_in_declaration): Rename from\n\tVwarn_comma_in_global_decl.\n\tHandle new static command.\n\t* pt-cmd.h, pt-cmd.cc (class tree_decl_command): New base class\n\tfor static and global declaration commands.\n\t(class tree_global_command): Derive from tree_decl_command.\n\t(class tree_static_command): New class, derived from tree_decl_command.\n\t* pt-fvc.cc, pt-fvc.h (tree_identifier::mark_as_static): New function.\n\t* pt-misc.h, pt-misc.h (class tree_decl_elt): Rename from tree_global.\n\t(class tree_decl_init_list): Rename from tree_global_init_list.\n\t* pt-pr-code.cc, pt-pr-code.h (tree_print_code::visit_decl_command):\n\tRename from visit_global_command.\n\t(tree_print_code::visit_decl_elt): Rename from visit_global.\n\t(tree_print_code::visit_decl_init_list): Rename from\n\tvisit_global_init_list.\n\t* pt-walk.h (tree_walker::visit_decl_command): Rename from\n\tvisit_global_command.\n\t(tree_walker::visit_decl_elt): Rename from visit_tree_global.\n\t(tree_walker::visit_decl_init_list): Rename from\n\tvisit_global_init_list.\n\t* variables.cc (link_to_global_variable): Trying to make a static\n\tvariable global is an error.\n\t* SLList-misc.cc: Instantiate lists of pointers to tree_decl_elt\n\tobjects, not tree_global objects.\n\t* symtab.h, symtab.cc (symbol_record::tagged_static): New field.\n\t(symbol_record::mark_as_static, symbol_record::is_static):\n\tNew functions.\n\t* symtab.cc (symbol_record::init_state): Initialize tagged_static.\n\t(symbol_record::clear): Don't clear static variables.\n\t* symtab.cc (push_context): Don't do anything for static variables.\n\nTue Mar 25 17:17:17 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-bool-mat.cc, ov-bool-mat.h, ov-bool.cc, ov-bool.h: New files.\n\n\t* defaults.cc (symbols_of_defaults): DEFCONST OCTAVE_HOME.\n\n\t* toplev.cc (octave_config_info): Delete use of CXXLIBS.\n\t* oct-conf.h.in: Ditto.\n\n\t* octave.cc (maximum_braindamage): Don't bind prefer_zero_one_indexing.\n\t* ov.h: Don't declare Vprefer_zero_one_indexing.\n\t* ov.cc: Don't define Vprefer_zero_one_indexing.\n\t(prefer_zero_one_indexing): Delete.\n\t(symbols_of_value): Delete DEFVAR for prefer_zero_one_indexing.\n\n\t* ov.h, ov.cc, ov-base.h, ov-base.cc: Add constructors and\n\textractors for bool and boolMatrix types.\n\n\t* ov.cc (install_types): Register octave_bool and\n\toctave_bool_matrix types.\n\n\t* op-cm-cm.cc, op-cm-cs.cc, op-cm-m.cc, op-cm-s.cc, op-cs-cm.cc,\n\top-cs-m.cc, op-m-cm.cc, op-m-cs.cc, op-m-m.cc, op-m-s.cc,\n\top-s-cm.cc, op-s-m.cc, op-s-s.cc, ov-re-mat.cc:\n\tReturn boolMatrix instead of Matrix object.\n\t* ops.h (BOOL_OP3, MX_MX_BOOL_OP): Likewise.\n\n\t* op-b-b.h, op-b-b.cc, op-bm-bm.h, op-bm-bm.cc: New files.\n\t* Makefile.in: Add them to the lists.\n\t* ops.cc: Include header files here.\n\t(install_ops): Call install_b_b_ops() and install_bm_bm_ops() here.\n\n\t* variables.cc (symbols_of_variables): Don't rely on default\n\tconversion from int to double for value returned from\n\tdefault_history_size().\n\n\t* pr-output.cc: Include cstdio.\n\n\t* parse.y (param_list_end): Fix typo in last change.\n\n\t* quad.cc (quad): Cast integer return values to double.\n\t* npsol.cc (show_npsol_option): Likewise.\n\t* qpsol.cc (show_qpsol_option): Likewise.\n\t* file-io.cc (Fsprintf, Ffwrite): Likewise.\n\nMon Mar 24 13:11:47 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-typeinfo.cc (typeinfo): If invoked with an argument, return\n\tthe type of the argument as a string.  Fix doc string.\n\nThu Mar 20 14:47:49 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mk-oct-links (links_dir): Don't use -h option for grep.  It's\n\tnot needed since we are working on one file at a time anyway.\n\nMon Mar 17 10:53:29 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (handle_identifier): When handling indirect_ref, set\n\tlexer_flags.quote_is_transpose to 1 so that a.b' to work as\n\texpected.\n\n\t* parse.y (param_list_beg, param_list_end): New nonterminals.\n\t(param_list, param_list1): Use them.\n\nWed Mar 12 16:57:28 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-strip): New target.\n\nMon Mar 10 22:38:16 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (clean): Delete .oct files too.\n\n\t* toplev.cc (Vdefault_eval_print_flag): New static variable.\n\t(eval_string): New arg, print.\n\t(Feval): Pass Vdefault_eval_print_flag to eval_string.\n\t(default_eval_print_flag): New function.\n\t(symbols_of_toplev): New function.\n\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* pt-exp.h, pt-exp.cc (class tree_boolean_expression): Rename enum\n\tfields `and' and `or' to `bool_and' and `bool_or'.\n\t(tree_unary_expression): Rename enum field `not' to `unot'.\n\t(class tree_binary_expression): Rename enum fields `and' and `or'\n\tto `el_and' and `el_or'.\n\t* parse.y: Change all uses.\n\n\t* time.cc (extract_tm): Truncate field values instead of rounding.\n\t(gmtime, localtime): Likewise, for timeval.\n\n\t* ov.h (class octave_value): Delete unused variable freeptr.\n\n\t* mappers.cc: Delete functions that are already in\n\tliboctave/lo-mappers.cc.\n\n\t* oct-strstrm.cc (octave_base_strstream::tell): Use const_cast,\n\tnot static_cast.\n\n\t* help.cc (help_from_list): Add missing const qualifiers.\n\t* help.h (struct help_list): Likewise.\n\t* lex.l (match_any, plot_style_token): Likewise.\n\t* load-save.cc (extract_keyword, ascii_save_type): Likewise.\n\t* oct-hist.cc (mk_tmp_hist_file): Likewise.\n\t* octave.cc (execute_startup_files): Likewise.\n\t* octave.gperf (struct octave_kw): Likewise.\n\t* pr-output.cc (pr_any_float): Likewise.\n\t* pt-mvr.cc (tree_index_expression::eval_error): Likewise.\n\t* pt-exp-base.h, pt-exp.h, pt-exp.cc: Likewise.\n\t* parse.y: Likewise.\n\nSun Mar  9 03:46:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-exp-base.h (tree_expression): Delete extra comma at end of list.\n\n\t* dirfns.cc error.cc file-io.cc fsolve.cc input.cc load-save.cc\n\tnpsol.cc pt-fcn.cc qpsol.cc quad.cc syscalls.cc toplev.cc\n\tvariables.cc: Eliminate embedded newlines in string constants.\n\n\t* Map.cc, data.cc, dirfns.cc, dynamic-ld.cc, file-io.cc,\n\tfsolve.cc, getgrent.cc, getpwent.cc, getrusage.cc, help.cc,\n\tinput.cc, load-save.cc, mappers.cc, minmax.cc, npsol.cc,\n\toct-fstrm.cc, oct-procbuf.h, oct-stdstrm.cc, oct-stdstrm.h,\n\toct-stream.cc, oct-stream.h, oct-strstrm.cc, octave.cc,\n\tov-base.h, ov-range.cc, ov-typeinfo.cc, ov.cc, pr-output.cc,\n\tpt-cmd.cc, pt-exp.cc, pt-fcn.cc, pt-fvc.cc, pt-mat.cc,\n\tpt-misc.cc, pt-plot.cc, qpsol.cc, quad.cc, sort.cc, strfns.cc,\n\tsymtab.cc, syscalls.cc, sysdep.cc, time.cc, toplev.cc,\n\tunwind-prot.cc, unwind-prot.h, variables.cc, xpow.cc:\n\tUse `static_cast<T> (val)' instead of old C-style `(T) val' casts.\n\nSat Mar  8 02:35:13 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (save_ascii_data, save_three_d): Where appropriate,\n\tuse bool instead of int.\n\t(save_binary_data, save_mat_binary_data, save_ascii_data):\n\tPrint warning instead of error for wrong type arg.\n\n\t* gripes.cc (gripe_wrong_type_arg): New arg, is_error.\n\n\t* pt-plot.cc (save_in_tmp_file): Call save_ascii_data with bool\n\targ, not int.\n\nFri Mar  7 00:56:16 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dassl.cc (show_dassl_option): For values that are determined\n\tautomatically, return a string instead of a magic value (-1.0).\n\t* fsolve.cc (show_fsolve_option): Likewise.\n\t* lsode.cc (show_lsode_option): Likewise.\n\t* npsol.cc (show_npsol_option): Likewise.\n\t* qpsol.cc (show_qpsol_option): Likewise.\n\n\t* variables.cc (extract_function): New function.\n\t* dassl.cc (Fdassl): Use it instead of is_valid_function.\n\t* fsolve.cc (Ffsolve): Likewise.\n\t* npsol.cc (Fnpsol): Likewise.\n\t* qpsol.cc (Fqpsol): Likewise.\n\t* quad.cc (Fquad): Likewise.\n\nThu Mar  6 20:07:24 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (my_friendly_exit, octave_new_handler,\n\tsigfpe_handler, sigpipe_handler): Don't all error() or warning().\n\n\t* pager.cc (pager_death_handler): Don't try to clear pager, just\n\tprint message to cerr.\n\t(do_sync): If the status of the pager is bad or it looks like it\n\tis dead, restore the interrupt handler.\n\n\t* load-save.cc (extract_keyword (istream&, char*, int&)):\n\tMove declaration of buf inside loop, to avoid deleting its guts\n\tand then trying to reuse it.\n\t(extract_keyword (istream&, char*)): Likewise.\n\nTue Mar  4 20:36:53 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-fcn.cc (tree_function::eval): Protect function from being\n\tredefined while it is being evaluated.\n\t(unprotect_function): New function, for use with unwind_protect stuff.\n\t* pt-fcn.h (tree_function::symtab_entry): New data member.\n\t(tree_function::init): Initialize it to 0.\n\t(tree_function::stash_symtab_ptr): New function.\n\t* parse.y (frob_function_def): Stash pointer to function's\n\tsymbol_record in the function definition.\n\n\t* symtab.cc (symbol_record::read_only_error): New argument,\n\taction.  Change all callers.\n\t(symbol_record::rename): Don't allow read-only symbols to be renamed.\n\n\t* variables.cc (Fexist): Don't let files with `.' in their names\n\tconfuse us.\n\n\t* symtab.cc (valid_identifier (const string&)): New function.\n\nSat Mar  1 15:23:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.5 released.\n\nSat Mar  1 01:34:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (stamp-oct-links): New target.  Make links in build\n\tdirectory too, so that the tests will work.\n\n\t* quad.cc: If quad is defined, undefine it.\n\n\t* octave.cc: If WITH_KPATHSEARCH is defined, don't define\n\tprogram_invocation_name or program_invocation_short_name.\n\n\t* strftime.c: Update to current version from FSF.\n\t* time.cc (Fstrftime): Call strftime with buf = 0 to get buffer\n\tsize, then call again to actually format the time struct.\n\nFri Feb 28 01:49:48 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\tImplement switch statement:\n\n\t* parse.y (Vwarn_variable_switch_label): New static variable.\n\t(warn_variable_switch_label): New function.\n\t(symbols_of_parse): Provide warn_variable_switch_label as Octave\n\tvariable here.\n\t(make_switch_case, finish_switch_command): New functions.\n\t(maybe_warn_variable_switch_label): New function.\n\t(end_error): Handle endswitch.\n\t(switch_command, case_list, case_list1, switch_case, default_case):\n\tNew nonterminals.\n\t(command): Add switch_command here.\n\t* lex.l\t(is_keyword): Handle switch, case, otherwise, and endswitch.\n\t* octave_gperf: Recognize switch, case, otherwise, and endswitch.\n\t* token.h (end_tok_type): New item, switch_end.\n\t* pt-cmd.cc (tree_switch_command): New class.\n\t* pt-misc.cc (tree_switch_case, tree_switch_case_list): New classes.\n\t* pt-pr-code.cc (tree_print_code::visit_switch_case,\n\ttree_print_code::visit_switch_case_list,\n\ttree_print_code::visit_switch_command): New functions.\n \t* pt-walk.h (tree_walker::visit_switch_case,\n\ttree_walker::visit_switch_case_list,\n\ttree_walker::visit_switch_command): New pure virtual declarations.\n\tImplement new switch statement.\n\t* SLList-misc.cc: Instantiate lists of pointers to\n\ttree_switch_case objects too.\n\n\t* lex.h, lex.l, parse.y: Delete all references to lexer_flags::iffing.\n\n\t* syswait.h: Include sys/wait.h on NeXT systems, but don't use the\n\tWIFEXTED, WEXITSTATUS, and WIFSIGNALLED macros defined there.\n\tAlso define waitpid in terms of wait4.  From Rex A. Dieter\n\t<rdieter@math.unl.edu>.\n\nWed Feb 26 16:43:31 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_base_stream::do_scanf): Don't report an\n\terror if a conversion fails or we reach EOF.\n\nTue Feb 25 22:21:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* time.cc (strftime): increase initial buffer size.\n\nMon Feb 24 17:49:21 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-fvc.cc (tree_builtin::eval): Enable checking for max number\n\tof arguments.\n\n\t* error.cc (handle_message): Don't fail if args is empty.\n\nSun Feb 23 22:42:52 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.h (lexical_feedback::looking_at_return_list): New field.\n\t(lexical_feedback::looking_at_parameter_list): Ditto.\n\t* lex.l (lexical_feedback::init): Initialize them.\n\t(handle_identifier): Use them.\n\t* parse.y: Likewise.\n\nFri Feb 21 15:35:18 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l: Require flex 2.5 or later (we really want 2.5.4 or later,\n\tbut there seems to be no good way to check the patchlevel).\n\n\t* oct-stream.cc (octave_base_stream::oscanf): Instead of returning\n\tan error, just quit processing after a conversion fails.\n\nThu Feb 20 02:58:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.4 released.\n\nWed Feb 19 10:30:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (octave_ignore_interrupts,\n\toctave_catch_interrupts, octave_set_interrupt_handler):\n\tReturn old value, not pointer to static data.  Fix all uses.\n\n\t* sighandlers.h (octave_interrupt_handler): Move declaration here.\n\t* sighandlers.cc: From here.\n\n\t* toplev.cc: Undo previous change.\n\n\t* lex.l (handle_identifier): Allow commands like ls, save, etc. to\n\talso be used as simple variable names.  Also make it possible to\n\tuse the normal function call syntax to invoke them.\n\nTue Feb 18 09:22:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (%.oct:%.o, %.oct:pic/%.o): Use $(SH_LDFLAGS) here.\n\n\t* Version 2.0.3 released.\n\nTue Feb 18 00:27:49 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (run_command_and_return_output):\n\tBlock SIGCHLD while running subprocess.\n\t(cleanup_iprocstream): Unblock it here.\n\n\t* sighandlers.h (BLOCK_SIGNAL, BLOCK_CHILD, UNBLOCK_CHILD): Move here.\n\t* sighandlers.cc: From here.\n\n\t* toplev.cc (system): Shift then mask exit status.\n\n\t* help.cc (try_info): Shift first, then mask exit status.\n\n\t* toplev.cc (octave_config_info): Handle option argument.\n\nFri Feb 14 16:23:30 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_base_stream::do_scanf): Don't forget to\n\tcheck to see if the result matrix needs resizing!\n\n\t* Makefile.in (bin-dist): Don't write empty strings to LIBRARIES.\n\nThu Feb 13 03:02:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (stamp-prereq): Depend on stamp-picdir.\n\t(all): Don't depend on stamp-prereq or stamp-picdir.\n\t(stamp-tinst, stamp-interp, libtinst.a, liboctinterp.a):\n\tDo depend on stamp-prereq.\n\t(stamp-picdir): Silence noise about making pic.\n\t(stamp-tinst, stamp-interp): Use $(SH_LD) $(SH_LDFLAGS) instead of\n\t$(CXX) -shared.\n\n\t* oct-conf.h.in: Reinstate RLD_FLAG.\n\t* toplev.cc (octave_config_info): Likewise.\n\n\t* data.cc (map_d_m, map_m_d, map_m_m): Rename from map.\n\t(Fatan2): Use new function names.\n\n\t* pt-fvc.cc (apply_mapper_fcn): Use member function map() instead\n\tof friend function.\n\n\t* gripes.cc (gripe_wrong_type_arg (const char*, const string&)):\n\tNew function.\n\nWed Feb 12 17:27:53 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* syscalls.cc (symbols_of_syscalls): Add O_ASYNC and O_SYNC.\n\nMon Feb 10 01:22:27 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dirfns.cc (Freaddir, Fmkdir, Frmdir, Frename):\n\tAlso return status and error message.\n\n\t* syscalls.cc (Fdup2, Fexec, Ffork, Ffcntl, Funlink, Fmkfifo,\n\tFpipe, Fwaitpid): Also return error message.\n\nSat Feb  8 17:16:09 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-exp.cc (tree_simple_assignment_expression::eval): Return\n\tvalue of RHS, but (if printing) print complete value of LHS.\n\n\t* pr-output.cc (octave_print_internal): Print a new line for empty\n\tstring matrices.\n\nWed Feb  5 14:30:44 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (scanf_format_list::process_conversion): Accept\n\tbut don't actually use h, l, and L modifiers.  Always insert l\n\tmodifier for floating point conversions.\n\nFri Jan 31 13:55:10 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pager.cc (do_sync): Always flush the cout stream after writing.\n\nWed Jan 29 08:25:29 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.cc (exec_path): Don't include bin_dir in std_path.\n\n\t* pager.cc (do_sync): Flush the cout stream after writing if\n\trunning in interactive or forced_interactive mode.\n\n\t* mk-oct-links: Rename from mk-oct-links.in.\n\tDon't use symbolic links.\n\t* Makefile.in: Distribute mk-oct-links, not mk-oct-links.in\n\t(mk-oct-links): Delete target.\n\t(install-oct, bin-dist): Don't depend on mk-oct-links.\n\tRun $(srcdir)/mk-oct-links, not ./mk-oct-links.\n\n\t* qr.cc (qr): Doc fix.\n\nTue Jan 28 10:48:28 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-inc): Create a relative symbolic link.\n\t(install-bin): Create a relative symbolic link.\n\nMon Jan 27 12:12:03 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.2 released.\n\n\t* Makefile.in (CXXFLAGS_NO_PT_FLAGS): Rename from XALL_CXXFLAGS.\n\tSubstitute bsd_gcc_kluge_targets_frag.\n\n\t* sysdep.cc (Fsleep): New function.\n\t(Fusleep): New function.\n\n\t* toplev.cc (octave_config_info): Don't include RLD_FLAG.\n\t* oct-conf.h.in: Don't define RLD_FLAG\n\nSun Jan 26 19:41:48 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (sigchld_handler): Block SIGCHLD while\n\tsigchld_hander is running.\n\nSat Jan 25 22:36:39 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (bin-dist): Update for 2.x.\n\nFri Jan 24 10:05:00 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mk-oct-links.in: New arg, -p, to just print list of files to link.\n\n\t* lex.l (handle_number): Convert `D' or `d' exponents to `e'\n\tbefore scanning.\n\nThu Jan 23 10:00:00 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-pr-code.h, pt-pr-code.cc (tree_print_code::visit_no_op_command):\n\tNew function.\n\t* pt-cmd.h, pt-cmd.cc (tree_no_op_command): New class.\n\t* parse.y (make_break_command, make_continue_command,\n\tmake_return_command): Where they don't really make sense, turn\n\tthese commands into no-ops.  Accept return and break if reading a\n\tscript file.\n\t* toplev.cc (parse_and_execute): Handle return and break in script\n\tfiles.  Quit executing commands if an error occurs when reading a\n\tscript file.  Set global_command to 0 after deleting it.\n\t(main_loop): If not interactive or forced_interactive, handle\n\tbreak and return, and quit executing commands if an error occurs.\n\tSet global_command to 0 after deleting it.\n\t* error.cc (Ferror): Doc fix.\n\t* pt-walk.h (tree_walker): Add declaration for visit_no_op_command.\n\nWed Jan 22 20:54:12 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (gnu_readline): If not using readline, flush\n\trl_outstream after printing prompt.\n\t(octave_gets): Also call flush_octave_stdout() if\n\tforced_interactive, not just if interactive.\n\t(do_input_echo): If forced_interactive, only echo prompt and\n\tcommand line if also reading a script file.\n\nTue Jan 21 23:02:34 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* SLList.h: Include \"BaseSLList.h\", not <BaseSLList.h>.\n\nMon Jan 20 11:11:12 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (token_stack): Don't declare static.\n\t* pt-plot.cc (tmp_files): Likewise.\n\t* toplev.cc (octave_atexit_functions): Likewise.\n\t* unwind-prot.cc (unwind_protect_list): Likewise.\n\n\t* ops.h (MX_MX_BOOL_OP): Correctly handle case of one or both\n\targuments being empty.  Change all callers.\n\n\t* oct-stream.cc (printf_value_cache::looking_at_string):\n\tHandle empty strings correctly now that they are 0x0.\n\n\t* file-io.cc: Don't include \"syswait.h\" here.\n\nSun Jan 19 22:38:45 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.h (octave_base_stream::seek): Declare offset arg as\n\tstreamoff, not streampos.\n\t(octave_stream::seek): Likewise.\n\t* oct-strstrm.h (octave_base_strstream::seek): Likewise.\n\t* oct-stdstrm.h (octave_base_stdiostream::seek): Likewise.\n\t* oct-iostrm.h (octave_base_iostream::seek): Likewise.\n\t* oct-fstrm.h (octave_fstream::seek): Likewise.\n\nFri Jan 17 18:13:10 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (Ffflush): Handle stdout as a special case.\n\n\t* oct-stream.cc (octave_stream_list::do_get_file_number):\n\tDo the work for octave_stream::get_file_number.\n\t(octave_stream_list::get_file_number): Convert to static function.\n\nWed Jan  8 11:42:44 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* log.cc (sqrtm): For complex arg case, compute sqrt, not log.\n\nTue Jan  7 00:16:41 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.1 released.\n\nMon Jan  6 00:00:07 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-mat.cc (tm_row_const_rep::all_mt): New variable.\n\t(tm_row_const::all_empty): New function.\n\t(tm_row_const::tm_row_const_rep::init): Set all_mt here.\n\t(tm_const::all_mt): New variable.\n\t(tm_const::all_emtpy): New function.\n\t(tm_const::init): Set all_mt here.\n\t(tree_matrix::eval): Return an empty matrix if the list contains\n\tonly empty elements.  If it contains only empty strings, return an\n\tempty string.\n\nSun Jan  5 12:50:25 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ops.h (SC_MX_BOOL_OP, MX_SC_BOOL_OP): New arg, empty_result.\n\t* op-cm-cm.cc, op-cm-cs.cc, op-cm-m.cc, op-cm-s.cc, op-cs-cm.cc,\n\top-cs-m.cc, op-m-cm.cc, op-m-cs.cc, op-m-m.cc, op-m-s.cc,\n\top-s-cm.cc, op-s-m.cc, op-str-str.cc: Change all uses of\n\tSC_MX_BOOL_OP and MX_SC_BOOL_OP macros.  Return correct results\n\tfor empty matrix cases.\n\n\t* pt-fcn.cc (tree_function::eval): If Vdefine_all_return_values is\n\ttrue, initialize return values before evaluating function, for\n\tcompatibility with Matlab.\n\n\t* oct-stream.cc (get_size): Correctly set size when arg is scalar.\n\nThu Jan  2 12:40:10 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-oct): Quote $(OCT_FILES) in for loop to\n\tavoid syntax error from ksh.\n\n\t* pr-output.cc (octave_print_internal): Avoid unused parameter\n\twarning from gcc.\n\nThu Dec 19 12:13:42 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_base_stream::do_scanf):\n\tDon't treat %l{e,f,g} differently from %{e,f,g}.\n\t(octave_base_stream::do_oscanf): Likewise.\n\n\t* sighandlers.cc (sigchld_handler): Fix typos.\n\nWed Dec 18 20:17:23 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (Ffgetl, Ffgets): Also return number of characters\tread.\n\n\t* ov-range.cc (octave_range::not): New function.\n\t* ov-range.h (octave_range::uminus): New function.\n\n\t* BaseSLList.cc: Include error.h.\n\t(BaseSLList::error): Call ::error() to process error message.\n\nFri Dec 13 02:38:19 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.cc (octave_value::convert_and_assign): Preserve lhs value if\n\tassignment fails.\n\nWed Dec 11 12:33:16 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc (GPLOT_CMD_END): Don't put semicolons at the end of\n\teach plot command; it causes trouble with gnuplot 3.5.\n\nTue Dec 10 00:31:13 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0 released.\n\n\t* pr-output.cc (set_format_style): Don't try to access argv unless\n\targc > 1.\n\n\t* SLList-expr.cc SLList-misc.cc SLList-plot.cc SLList-str.cc\n\tSLList-tc.cc SLList-tm.cc SLList.h SLStack-i.cc SLStack-pc.cc\n\tSLStack-str.cc SLStack-sym.cc SLStack-tok.cc SLStack-ue.cc\n\tSLStack-ui.cc, pt-mat.cc: Include Stack.h, Stack.cc, SLStack.cc,\n\tand SLList.cc as necessary.\n\n\t* Stack.cc, SLStack.cc, SLList.cc: New files.\n\t* Makefile.in (SOURCES): Add them to the list.\n\nMon Dec  9 12:03:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-bin): Use $(EXE) suffix so install will\n\tfind the right file on cygwin32 systems.\n\n\t* ov.h: Declare proper form of do_binary_op as friend to\n\toctave_value class.\n\nSat Dec  7 22:00:10 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (do_printf_conv, do_scanf_conv,\n\tdo_oscanf_num_conv, do_oscanf_str_conv): Convert to real\n\tfunctions instead of CPP macros, using templates where necessary.\n\t(do_oscanf_num_conv, do_oscanf_str_conv): Correctly handle\n\tdiscarded values.\n\nFri Dec  6 00:20:25 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.94.\n\n\t* Map-*.cc, SLList-*.cc, SLStack-*.cc: Include config.h.\n\n\t* ov.h: Don't include SLList.h.\n\n\t* SLStack.cc: Delete.  Move everything to SLStack.h.\n\n\t* BaseSLList.h, BaseSLList.cc: New files.  Split out the\n\tnon-template base class parts of SLList.\n\n\t* Makefile.in (TEMPLATE_SRC): Delete.  Move files to SOURCES.\n\t* Map.h, Map.cc: Add #pragma interface/implementation.\n\t* SLStack.h, SLStack.cc: Add #pragma interface/implementation.\n\n\t* SLList.h, SLList.cc: New files, from libg++, but with #pragma\n\tinterface/implementation.\n\t* Makefile.in (SOURCES): Add SLList.cc.\n\t(INCLUDES): Add SLList.h.\n\nThu Dec  5 18:36:44 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc: Don't include sun-utils.h.\n\nTue Dec  3 23:47:09 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* op-str-str.cc (eq, ne): Handle operations with scalars.\n\nThu Nov 21 12:30:36 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-str-mat.h (octave_char_matrix_str): Provide transpose and\n\thermitian operators.\n\t* ov-ch-mat.h (octave_char_matrix): Likewise.\n\nWed Nov 20 00:35:57 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.h (struct octave_interrupt_handler): Provide\n\tforward declaration here.\n\t* sighandlers.cc (octave_interrupt_handler): New struct.\n\t(octave_catch_interrupts): Rename from catch_interrupts.\n\t(octave_ignore_interrupts, octave_set_interrupt_handler):\n\tNew functions.\n\t* help.cc, oct-hist.cc, pager.cc, toplev.cc: Use new functions for\n\thandling interrupts so that we can hide the details of whether or\n\tnot we have to deal with SIGBREAK.\n\n\t* pt-plot.cc [! HAVE_POSIX_SIGNALS] (open_plot_stream):\n\tSimply ignore and restore the interrupt handler here.\n\n\t* sighandlers.cc (MAYBE_REINSTALL_SIGHANDLER): New macro.  Use it\n\tinstead of always checking MUST_REINSTALL_SIGHANDLERS everywhere.\n\t(sigchld_handler): If octave_child_list is empty, wait for any\n\tchild, but don't hang, and don't collect status info.\n\t[__EMX__] (sigchld_handler): Save and restore handlers for SIGINT,\n\tSIGBREAK, and SIGCHLD.  Ignore them while waiting on children.\n\t(install_signal_handlers): If SIGBREAK exists, handle it like SIGINT.\n\n\t* toplev.cc [USE_READLINE] (clean_up_and_exit):\n\tCall rl_deprep_terminal() to restore terminal settings.\n\n\t* sysdep.cc [__EMX__ && OS2] (Fextproc): New command.\n\t[__EMX__ && OS2] (FEXTPROC): Alias for Fextproc.\n\n\t* Version 1.93.\n\n\t* sysdep.cc (octave_chdir): [__EMX__]: Make copy of string before\n\tconverting to upper case.\n\n\t* getgrent.cc (mk_gr_map): Only set the passwd field if\n\tHAVE_GR_PASSWD is defined.\n\nTue Nov 19 12:01:13 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sysdep.cc (OS2_init): New function.\n\t[__EMX__] (sysdep_init): Call it.\n\n\t* lex.l (plot_style_token): Add new plot styles for gnuplot 3.6.\n\t* pt-plot.cc (subplot_style::columns_ok): Rename from\n\tsubplot_style::errorbars. Recognize more styles and do a better\n\tjob of diagnosing column number/style mismatches.\n\n\t* sighandlers.cc (my_friendly_exit): If we are called twice, try\n\tto remove the signal handler for SIGABRT and the call abort ().\n\n\t* help.cc (Ftype): If a function is defined from a file and\n\ttransformed text has not been requested, just print the contents\n\tof the file.\n\n\t* parse.y (fold): New functions for constant folding for binary\n\tand unary expressions.  Keep track of original text even when\n\ttransformations occur.\n\t(make_binary_op, make_boolean_op, make_unary_op): Use them.\n\t(finish_colon_expression, finish_matrix): Keep track of original\n\ttext even when transformations occur.\n\n\t* help.cc (Ftype): Don't mess with Vps4.\n\tHandle new option `-transformed'.\n\n\t* pt-const.h, pt-const.cc (tree_constant::print):\n\tNew arg, pr_orig_text.\n\n\t* pt-exp.h, pt-exp.cc (tree_colon_expression::is_range_constant):\n\tDelete.\n\n\t* pt-exp-base.h (tree_expression::original_text): New virtual function.\n\tpt-exp-base.cc (tree_expression::original_text): Default version.\n\n\t* pt-pr-code.h (tree_print_code::print_original_text,\n\ttree_print_code::prefix): New fields.\n\t* pt-pr-code.cc (tree_print_code::visit_constant): Pass\n\tprint_original_text to tree_constant::print().\n\t(tree_print_code::indent): Use prefix instead of Vps4.\n\t* pt-fcn.cc (tree_function::print_function_header,\n\ttree_function::print_function_trailer): Pass Vps4 to\n\ttree_print_code_constructor for prefix.\n\t* pt-misc.cc (tree_statement::maybe_echo_code): Pass Vps4 to\n\ttree_print_code_constructor for prefix.\n\n\t* pt-mat.h, pt-mat.cc (tree_matrix::all_elements_are_constant):\n\tRename from is_matrix_constant.\n\t(tree_matrix_row::all_elements_are_constant): Likewise.\n\tChange all callers.\n\nMon Nov 18 14:13:32 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-inc): Try harder to create the link from\n\tinclude/octave to include/octave-VERSION.\n\nSun Nov 17 14:14:48 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (parse.cc): Expect 13 shift/reduce conflicts.\n\n\t* parse.y (set_stmt_print_flag): New function.\n\t(sep_type): New member for bison %union declaration.\n\tSimplify rules for statement lists keeping track of the type of\n\tthe first separator in the values associated with the\n\tnonterminals for the separators.\n\n\t* lex.l (handle_identifier): Set lexer_flags.doing_set if the\n\ttoken is \"gset\", not \"set\".\n\nSat Nov 16 21:41:26 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (parse.cc, lex.cc): Add special rules for these files.\n\tDelete pattern rules for .y and .l files.\n\nFri Nov 15 13:48:02 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc: Put semicolons at the ends of all plot commands.\n\n\t* defaults.cc (subst_octave_home): Start subsequent searchs from\n\tthe end of the replaced text.\n\n\t* pr-output.cc (pr_any_float): Kluge for SCO systems.\n\n\t* pr-output.cc (pr_any_float, pr_complex): Don't declare inline.\n\n\t* mappers.cc: Include lo-ieee.h, for isinf and isnan on SCO\n\tsystems.\n\nThu Nov 14 00:06:19 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc (Fgset, Fgshow): New commands.\n\t(Fshow): Print warning and call gshow.\n\t(Fset): Print warning and call gset.\n\n\t* variables.cc (parse_fcn_file): Add unwind-protect for file\n\tpointer, so the file is always closed.\n\t(get_help_from_file): Likewise.\n\t* toplev.cc (parse_and_execute): Likewise.\n\n\t* Makefile.in (install-oct): Depend on mk-oct-links.\n\t(mk-oct-links): New target.\n\n\t* Version 1.92.\n\nWed Nov 13 11:13:22 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sighandlers.cc (sys_siglist): [__EMX__]: Add definitions.\n\n\t* octave.cc (execute_startup_files): Allow init file name ot be\n\tspecified by an environment variable.\n\n\t* dirfns.cc (make_absolute): [__EMX__]: Path is already absolute\n\tif it begins with any character followed by a colon.\n\n\t* load-save.cc (read_mat_ascii_matrix, get_lines_and_columns,\n\tget_complete_line): New functions, for reading headless text files.\n\t(load_save_format): Add LS_MAT_ASCII, for headless text files.\n\t(do_load): Handle LS_MAT_ASCII files.\n\tThanks to Mel Melchner <mjm@research.att.com> for initial version\n\tof this code.\n\n\t* sysdep.cc: Conditionally include ieeefp.h.\n\t(BSD_init, SCO_init): New functions.\n\t(sysdep_init): Conditionally call them here.\n\nTue Nov 12 00:14:56 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc (open_plot_stream): Don't block SIGCHLD.\n\n\t* load-save.cc (read_binary_data): When reading string arrays, be\n\tsure to create an octave_char_matrix_str object, not just an\n\toctave_char_matrix object.\n\t(read_ascii_data): Likewise.\n\nMon Nov 11 22:52:58 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (read_binary_data): Don't forget teminating NUL for\n\tstring that we plan to insert.\n\t(read_ascii_data): Likewise.\n\nSun Nov 10 16:58:07 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dirfns.cc (Ffnmatch): New function.\n\n\t* octave.cc (intern_argv): Use new string_vector constructor.\n\n\t* ov-str-mat.cc (octave_char_matrix_str::all_strings): Have\n\tcharMatrix::row_as_string() strip trailing whitespace.\n\n\t* dirfns.cc (Fglob): new function.\n\n\t* sysdep.cc (oct_tilde_expand): Provide version that works on\n\tstring vectors too.\n\t(Ftilde_expand): Work on string vector args.\n\n\t* load-save.cc (save_binary_data): Call char_matrix_value() to\n\textract charMatrix from octave_value object, not all_strings().\n\t(save_ascii_data): Likewise.\n\t* pt-mat.cc (tree_matrix::eval): Likewise.\n\n\t* ov.h (octave_value::all_strings): Return string_vector, not\n\tcharMatrix.\n\t* ov-base.cc (octave_base_value::all_strings): Likewise.\n\t* ov-str-mat.h, ov-str-mat.cc (octave_char_matrix_str::all_strings):\n\tLikewise.\n\nFri Nov  8 09:54:59 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defaults.cc, dynamic-ld.cc, fn-cache.cc, help.cc, oct-hist.cc,\n\toctave.cc, pager.cc, pt-fcn.cc, toplev.cc, utils.cc, variables.cc,\n\tlex.l: Change #include \"\" to #include <> for defaults.h,\n\toct-conf.h, oct-gperf.h, y.tab.h, and version.h, to avoid getting\n\tthem from $srcdir when we really want the version from the build\n\tdirectory.  (Maybe this should be done for all the include files,\n\tnot just those that are auto-generated?  Hmm.)\n\n\t* defaults.h.in (CXXLIB_LIST, CXXLIB_PATH, FLIB_LIST, FLIB_PATH):\n\tDelete.\n\n\t* Makefile.in (install-oct): Use $(INSTALL_PROGRAM) for .oct files.\n\nThu Nov  7 07:59:07 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (gobble_leading_white_space): New arg, update_pos.\n\t* (is_function_file): Don't update file position information here.\n\n\t* Version 1.91.\n\n\t* pt-fvc.cc (tree_indirect_ref::reference): If the lhs object is\n\tnot a map, convert it to one.\n\n\t* ov-typeinfo.h (init_tab_sz): New static member.\n\n\t* ov-struct.cc, ov-struct.h: Add hooks for custom memory management.\n\t* ov-scalar.cc, ov-scalar.h: Likewise.\n\t* ov-re-mat.cc, ov-re-mat.h: Likewise.\n\t* ov-range.cc, ov-range.h: Likewise.\n\t* ov-cx-mat.cc, ov-cx-mat.h: Likewise.\n\t* ov-complex.cc, ov-complex.h: Likewise.\n\t* ov-ch-mat.cc, ov-ch-mat.h: Likewise.\n\nWed Nov  6 12:32:48 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pager.cc (do_sync): Don't call clear_external_pager() here.\n\n\t* pt-const.h (tree_constant::allocator) New static member.\n\t(tree_constant::operator new, tree_constant::operator delete):\n\tImplement with custom allocator.\n\n\t* syscalls.cc (Fgetgid, Fgetegid): New functions.\n\n\t* sighandlers.cc (sigchld_handler): If necessary, reinstall\n\thandler after call to waitpid().\n\n\t* pager.cc (pager_death_handler): Don't use warning() to print\n\tmessage.\n\n\t* getgrent.cc: New file.\n\t* Makefile.in (DLD_SRC): Add it.\n\n\t* ov.cc (octave_value::print_with_name): Call is_map() instead of\n\tprint_as_structure().\n\t* ov-struct.cc (octave_struct::print): Likewise.\n\n\t* ov.h, ov.cc, pt-const.h: Delete force_numeric(), make_numeric(),\n\tconvert_to_matrix_type(), print_as_structure() member functions.\n\n\t* variables.cc (is_function_file): Call gobble_leading_whitespace\n\there to strip all leading whitespace and comments.\n\t(parse_fcn_file): If reading a function file, call\n\tgobble_leading_whitespace again after resetting parser state to\n\tgrab help text.\n\nTue Nov  5 13:00:35 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* syscalls.cc (Fgeteuid, Fgetuid): New functions.\n\n\t* getpwent.cc: Use gripe_not_supported from gripes.cc, instead of\n\tlocal gripe_not_implemented function.\n\n\t* input.cc, sysdep.cc, variables.cc: Only include readline.h and\n\thistory.h if USE_READLINE is defined.\n\n\t* help.cc: Make it compile without warnings even if USE_GNU_INFO\n\tis not defined.\n\n\t* sighandlers.h (octave_child_list): Don't define\n\tHAVE_POSIX_SIGNALS HERE.\n\n\t* sighandlers.cc (SIGHANDLER_RETURN): New macro.\n\t(generic_sig_handler, sigchld_handler, sigfpe_handler,\n\tsigint_handler, sigpipe_handler):  Use it.\n\t(sigchld_handler, sigfpe_handler, sigint_handler, sigpipe_handler):\n\tOnly reinstall signal handler if MUST_REINSTALL_SIGHANDLER is defined.\n\nSun Nov  3 00:45:30 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-const.cc (tree_constant::print): Just call val.print().\n\t* ov-base.cc, ov-ch-mat.cc, ov-colon.cc, ov-complex.cc,\n\tov-cx-mat.cc, ov-range.cc, ov-re-mat.cc, ov-scalar.cc,\n\tov-str-mat.cc, ov-struct.cc ov-va-args.cc, ov.cc (print):\n\tHandle pr_as_read_syntax arg.\n\n\t* defaults.cc (subst_octave_home): Search for prefix repeatedly in\n\tretval, not s.\n\n\t* gripes.h: Make declaration of gripes_not_supported match\n\tdefinition.\n\n\t* mk-oct-links.in: In sed command, match \"DEFUN_DLD *( *\", not\n\t\"DEFUN_DLD_BUILTIN *( *\".\n\n\t* chol.cc, colloc.cc, dassl.cc, det.cc, eig.cc, expm.cc, fft.cc,\n\tfft2.cc, filter.cc, find.cc, fsolve.cc, fsqp.cc, getpwent.cc,\n\tgetrusage.cc, givens.cc, hess.cc, ifft.cc, ifft2.cc, inv.cc,\n\tlog.cc, lpsolve.cc, lsode.cc, lu.cc, minmax.cc, npsol.cc, pinv.cc,\n\tqpsol.cc, qr.cc, quad.cc, qzval.cc, rand.cc, schur.cc, sort.cc,\n\tsvd.cc, syl.cc, time.cc: Change all uses of DEFUN_DLD_BUILTIN to\n\tbe just DEFUN_DLD.\n\n\t* defun-dld.h: Eliminate DEFUN_DLD_BUILTIN.\n\n\t* syswait.h: Use #ifdef HAVE_SYS_WAIT_H, not #if HAVE_SYS_WAIT_H\n\tto decide whether to include sys/wait.h.\n\n\t* pt-exp-base.h (tree_expression): Declare oper() here as a\n\tvirtual member function.\n\n\t* pt-pr-code.cc (tree_print_code::visit_constant): Check for\n\tstring before checking for char_matrix.\n\n\t* ov-ch-mat.cc (octave_char_matrix::print): Supply correct number\n\tof args to octave_print_internal().\n\nSat Nov  2 20:44:55 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (Ftmpnam): Rename from Foctave_temp_file_name.\n\n\t* Makefile.in (DLD_SRC): Move time.cc and getrusage.cc here from\n\tSOURCES.  Add getpwent.cc.\n\n\t* getrusage.cc: Rename from resource.cc.  Make getrusage a\n\tloadable function.\n\n\t* time.cc: Rename from timefns.cc.  Make time functions loadable.\n\n\t* getpwent.cc: New file.\n\nWed Oct 30 01:06:19 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.90.\n\n\t* Makefile.in (DISTFILES): Add ChangeLog.\n\n\t* ov-range.cc (octave_range::convert_to_str): New function.\n\n\t* ov-str-mat.h (octave_char_matrix_str::char_matrix_value):\n\tDelete function.  Already handled by octave_char_matrix class.\n\n\t* ov-ch-mat.h (octave_char_matrix::convert_to_str): New function.\n\n\t* pager.cc (Fmore): Set page_screen_output to 1.0 or 0.0, not\n\t\"true\" or \"false\".\n\n\t* ov-ch-mat.cc, ov-struct.cc, ov-struct.h, pr-output.cc,\n\tpt-cmd.cc, pt-const.cc, pt-const.h, pt-fcn.cc, pt-fvc-base.cc,\n\tpt-fvc-base.h, pt-fvc.cc, pt-fvc.h, rand.cc, sighandlers.cc,\n\tvariables.cc, variables.h: Delete unused code.\n\n\t* octave.cc: Only include pwd.h if HAVE_PWD_H.\n\n\t* oct-strstrm.h: Include <string>, not <string.h>.\n\n\t* defaults.cc, dirfns.cc, file-io.cc, help.cc, input.cc,\n \toct-hist.cc, oct-procbuf.cc, oct-procbuf.h, octave.cc, pager.h,\n \tprocstream.h, pt-misc.cc, pt-plot.cc, sighandlers.cc, strftime.c,\n \tsyscalls.cc, sysdep.cc, syswait.h, toplev.cc, utils.cc,\n \tvariables.cc: Only include sys/types.h if HAVE_SYS_TYPES_H.\n\n\t* error.h (panic): Use GCC_ATTR_NORETURN macro, not NORETURN.\n\t* toplev.h (clean_up_and_exit): Likewise.\n\t* utils.h (jump_to_top_level): Likewise.\n\n\t* derfaults.h.in, defaults.cc (local_arch_lib_dir): New variable.\n\t* defaults.cc (set_default_local_arch_lib_dir): New function.\n\t(install_defaults): Call it.\n\t(exec_path): Use Vlocal_arch_lib_dir here.\n\t* toplev.cc (octave_config_info): Add localarchlibdir to structure.\n\nTue Oct 29 15:54:27 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-oct): Don't do anything if $(OCT_FILES) is\n\tempty.\n\n\t* ov-range.cc (octave_range::index): New Function.\n\t(octave_range::all, octave_range::any, octave_range::is_true):\n\tMake these functions work.\n\n\t* ov.cc (octave_value::try_assignment_with_conversion): Remove\n\tleft over debugging print statements.\n\nMon Oct 28 10:49:03 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* strftime.c: Add missing #endif for previous change.\n\nSun Oct 27 14:06:44 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-hist.cc (do_history): Rewite option parsing to avoid\n\t(probably bogus) errors from g++ on cygwin32 system.\n\n\t* strftime.c: Use autoconf macros TIME_WITH_SYS_TIME and\n\tHAVE_SYS_TIME_H to decide which time.h files to include.\n\n\t* oct-stream.h, oct-stream.cc (octave_stream::error,\n\toctave_base_stream::error): Rename errno => err_num.\n\nSat Oct 26 10:40:05 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-hist.cc (do_history): Move declaration of file inside\n\tconditional.\n\n\t* defun.h (DEFVAR_INT): Set eternal flag with (svc_fcn != 0)\n\tinstead of (sv_fcn ? 1 : 0)\n\nFri Oct 25 01:10:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov-ch-mat.h (octave_char_matrix::any): Return 0.0 instead of false.\n\t(octave_char_matrix::all): Likewise.\n\n\t* input.cc (Fecho): When binding value of echo_executing_commands,\n\tcast ECHO_* to double.\n\n\t* sighandlers.cc (octave_child_list::do_remove): Delete unused\n\tvariable `enlarge'.\n\n\t* pt-const.h (tree_constant::tree_constant (const tree_constant&)):\n\tDon't pass arg to tree_fvc constructor.\n\n\t* resource.cc (getrusage): [HAVE_GETRUSAGE && RUSAGE_TIMES_ONLY]:\n\tOnly fill in time values.\n\nThu Oct 24 20:37:28 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y: Comment out the %expect declaration so byacc can\n\tcompile this file.\n\t(if_cmd_list): Add missing semicolon.\n\tInclude <cstdlib> for getenv if using byacc.\n\n\t* ov.h: Move typedefs outside of octave_value class scope to avoid\n\tproblem with cygwin32 beta16 compiler.\n\nFri Oct 18 13:44:33 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_value::index): Undo previous change.\n\t* ov.cc (octave_value constructors): Call maybe_mutate() in most\n\tcases.\n\n\t* ov-complex.cc (octave_complex::index): Avoid implicit type\n\tconversion back to scalar type.\n\t* ov-scalar.cc (octave_scalar::index): Likewise.\n\n\t* ov.h (octave_value::index): Call maybe_mutate() on retval before\n\treturning it.\n\nWed Oct 16 12:00:11 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ov.h (octave_value::struct_elt_val): New optional arg, silent.\n\t* ov-base.h, ov-base.cc, ov-struct.h, ov-struct.cc: Likewise, but\n\tfor the derived classes the arg is required.\n\n\t* data.cc (Fstruct_contains): Require arguments to be struct and\n\tstring, respectively.  Call octave_value::struct_elt_val with\n\tsilent flag set.\n\n\t* pt-mat.cc (tm_row_const::tm_row_const_rep::eval_error,\n\ttm_row_const::tm_row_const_rep::eval_warning): New functions.\n\t(tm_row_const::tm_row_const (const tree_matrix_row&): Use them to\n\tgive better error messages.\n\n\t* pt-fvc.cc (tree_identifier::eval): Avoid dereferencing null\n\tobject_to_eval.\n\nTue Oct 15 11:35:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* op-cs-cm.cc, op-cs-cs.cc, op-cs-m.cc, op-cs-s.cc\n\t(complex_matrix_conv): New functions.\n\tInstall preferred assignment conversion and widening ops.\n\n\t* op-s-cm.cc, op-s-cs.cc (complex_matrix_conv): New functions.\n\tInstall preferred assignment conversion and widening ops.\n\n\t* op-s-m.cc, op-s-s.cc (matrix_conv): New functions.\n\tInstall preferred assignment conversion and widening ops.\n\n\t* ov.cc (octave_value::try_assignment_with_conversion,\n\toctave_value::convert_and_assign, octave_value::try_assignment):\n\tNew functions.\n\t(octave_value::assign): Use them to implement twisted logic for\n\ttype conversions in assigments.\n\n\t* pt-const.h (tree_constant::maybe_mutate): New function.\n\t* ov.h (octave_value::maybe_mutate): New function.\n\t(octave_value::try_narrowing_conversion): New function.\n\tUse just one typedef for widening_op_fcn and numeric_conv_fcn.\n\tChange all uses.\n\t* ov-base.h, ov-complex.h, ov-complex.cc, ov-cx-mat.h,\n\tov-cx-mat.cc, ov-range.h, ov-range.cc, ov-re-mat.h, ov-re-mat.cc,\n\tProvide derived class versions of try try_narrowing_conversion().\n\n\t* pr-output.cc (octave_print_internal): Don't bother handing off\n\tto scalar/real versions, even when it would seem appropriate.\n\n\t* symtab.cc (symbol_def::define (tree_constant *)): Call\n\tmaybe_mutate on constants here.\n\nMon Oct 14 11:05:24 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-fvc.cc (tree_identifier::eval): If retval is undefined and\n\tthe object to eval is a constant, print\terror message.\n\n\t* Makefile (distclean): Remove *.oct too.\n\n\t* defun-int.h: Include variables.h here.\n\nSun Oct 13 10:52:28 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (print_symbol_info_line): Never print negative\n\tdiminsions.\n\n\t* symtab.h (octave_symbol_record_info): Store const_type as string.\n\t(octave_symbol_record_info::init): Delete.  Fix constructors.\n\t(octave_symbol_record_info::type_name): Handle const_type as string.\n\n\t* octave.cc (maximum_braindamage): Replace \"true\" with 1.0 and\n\t\"false\" with 0.0 in calls to bind_builtin_variable().\n\tInclude sun-utils.h here.\n\t(intern_argv): Also bind __argv__.\n\nSat Oct 12 13:40:21 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (distclean): Also delete mk-oct-links.\n\nFri Oct 11 13:13:13 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\tChanges for Octave's new type system:\n\n\t* arith-ops.cc: Delete.\n\t* pt-const.h, pt-const.cc: Massive changes.  Most functionality\n\tmoved to ov.h, ov.cc, and derived classes.\n\n\t* variables.h, variables.cc (octave_variable_reference): New class\n\tfor getting references to variables and structure elements used in\n\tassignments or value contexts.\n\n\t* symtab.h, symtab.cc (symbol_record::define (const octave_value&),\n\tsymbol_record::variable_value, symbol_record::variable_reference):\n\tNew functions.\n\t(symbol_record_info::type_name): Rename from type_as_string.\n\n\t* pt-fvc-base.h, pt-fvc-base.cc (tree_fvc::increment,\n\ttree_fvc::decrement): New functions to replace\n\ttree_fvc::bump_value.\n\t#if 0 assign and lookup_map_element functions.\n\n\t* pt-mvr.cc (tree_multi_assignment_expression::eval):\n\tGenerated RHS value is now a tree_constant.\n\n\t* pt-exp.h, pt-exp.cc (tree_boolean_expression): New class.\n\t(tree_unary_expression, tree_binary_expression,\n\ttree_boolean_expression): Move codes here from tree_expression.\n\t(tree_simple_assignment_expression): Cope with changes to way of\n\tdoing assignments.\n\n\t* pt-exp-base.h, pt-exp-base.cc (enum type): Delete codes for\n\tunary and binary ops.\n\t(tree_expression::expression_type): Delete.\n\t(tree_expression::is_logically_true): Hand off to\n\toctave_value::is_true to do real work.\n\n\t* pr-output.h, pr-output.cc (any_element_is_inf_or_nan,\n\tall_elements_are_ints): Delete.  Call member new functions for\n\tthese operations.\n\t(free_format, plus_format, bank_format, hex_format,\n\tcompact_format, print_e, print_big_e): Use bool, not int.\n\t(octave_print_internal): Hand off to scalar/real versions when\n\tappropriate.\n\n\t* octave.cc (main): Call initialize_types() and install_ops().\n\t(verbose_usage): Add WWW address to output.\n\n\t* parse.y (indirect_ref): Handle by making a tree instead of a\n\tlist using new version of tree_indirect_ref class.\n\n\t* parse.y (make_boolean_op): New function.  Use it instead of\n\tmake_binary_op to create trees for && and || ops.\n\t(make_binary_op): Codes come from tree_binary_expression now,\n\tinstead of tree_expression.\n\t(make_unary_op): Codes come from tree_unary_expression now,\n\tinstead of tree_expression.\n\t(make_boolean_op): Codes come from tree_boolean_expression.\n\n\t *parse.y (tree_constant_type): Change type to tree_constant* from\n\toctave_value*, and rename from octave_value_type.  Change uses.\n\n\t* defun.h (DEFVAR_INT): Pass octave_value not pointer to\n\toctave_value for defn when creating builtin_variable.\n\n\t* gripes.h, gripes.cc (gripe_invalid_conversion): Args are\n\tstrings, not char*.\n\t(gripe_implicit_conversion, gripe_divide_by_zero): New extern\n\tgripe functions.\n\n\t* mkbuiltins: For each file, create a separate static function to\n\tinstall builtins, then create another single extern function to\n\tcall all of them.\n\n\t* pt-fcn.cc (tree_function::bind_nargin_and_nargout):\n\tJust pass doubles and let symbol_record::define handle creating\n\tnew value.\n\n\t* pt-pr-code.cc, pt-pr-code.h (visit_constant): Renamed from\n\tvisit_octave_value.\n\t(visit_unary_expression): Use tree_expression::is_prefix_op()\n\tinstead of switch on op types.\n\n\t* pt-walk.h (visit_constant): Renamed from visit_octave_value.\n\n\t* pt-misc.cc (initialize_undefined_elements): Get reference to\n\ttmp, then assign.\n\t* pt-cmd.cc (do_for_loop_once): Likewise, for loop identifier.\n\n\t* input.cc (generate_struct_completions, looks_like_struct): Cast\n\ttmp_fvc to tree_constant*, not octave_value*.\n\t(get_user_input): Call print() on retval, not eval(1).\n\n\t* help.cc (Ftype): Cast defn to tree_constant*, not octave_value*.\n\n\t* balance.cc: Fix docstring.\n\n\t* dassl.cc, fsolve.cc, load-save.cc, lsode.cc, npsol.cc, qpsol.cc,\n\tquad.cc:\n\tInclude pt-fvc.h.\n\n\t* data.cc (Fstruct_contains): call octave_value::struct_elt_val,\n\tnot octave_value::lookup_map_element.\n\n\t* dirfns.cc (Fcd): Pass directory name as string directly to\n\tbind_builtin_variable instead of creating new octave_value.\n\n\t* toplev.cc: Include pt-fvc.h and lo-mappers.h\n\n\t* data.cc, error.cc, file-io.cc, load-save.cc, pager.cc,\n\tpt-mat.cc, pt-plot.cc, syscalls.cc, toplev.cc:\n\tInclude variables.h.\n\n\t* Array-tc.cc, Map-tc.cc, SLList-misc.cc SLList-tc.cc, data.cc,\n\tdefaults.cc, dynamic-ld.cc, error.cc, gripes.cc, lex.l, octave.cc,\n\toct-map.h, oct-map.cc, oct-obj.h, pt-cmd.cc, pt-exp.cc, pt-fcn.cc,\n\tpt-fvc-base.cc, pt-mat.cc, pt-misc.cc, pt-mvr-base.cc, pt-mvr.h,\n\tresource.cc, strfns.cc, sysdep.cc, timefns.cc, toplev.cc:\n\tInclude ov.h instead of pt-const.h.\n\n\t* xpow.cc (any_element_is_negative): Delete.\n\t(xpow and elem_xpow functions): Check conformance here.\n\n\t* xdiv.cc (mx_leftdiv_conform, mx_div_conform):\n\tNow template-based, taking Matrices instead of dimensions as args.\n\tChange all callers.\n\n\t* op-cm-cm.cc, op-cm-cm.h, op-cm-cs.cc, op-cm-cs.h, op-cm-m.cc,\n \top-cm-m.h, op-cm-s.cc, op-cm-s.h, op-cs-cm.cc, op-cs-cm.h,\n \top-cs-cs.cc, op-cs-cs.h, op-cs-m.cc, op-cs-m.h, op-cs-s.cc,\n \top-cs-s.h, op-m-cm.cc, op-m-cm.h, op-m-cs.cc, op-m-cs.h, op-m-m.cc,\n\top-m-m.h, op-m-s.cc, op-m-s.h, op-s-cm.cc, op-s-cm.h, op-s-cs.cc,\n \top-s-cs.h, op-s-m.cc, op-s-m.h, op-s-s.cc, op-s-s.h,\n \top-str-str.cc, op-str-str.h, ops.cc, ops.h, ov-base.cc, ov-base.h,\n \tov-ch-mat.cc, ov-ch-mat.h, ov-colon.cc, ov-colon.h, ov-complex.cc,\n \tov-complex.h, ov-cx-mat.cc, ov-cx-mat.h, ov-range.cc, ov-range.h,\n \tov-re-mat.cc, ov-re-mat.h, ov-scalar.cc, ov-scalar.h, ov-str-mat.cc,\n\tov-str-mat.h, ov-struct.cc, ov-struct.h, ov-typeinfo.cc,\n \tov-typeinfo.h, ov-va-args.cc, ov-va-args.h, ov.cc, ov.h:\n \tNew files for Octave's new type system.\n\t* Makefile.in: Add them to the appropriate lists.\n\nSat Sep 14 21:58:33 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mkbuiltins: Use .df instead of .def.\n\tWrite one function for each .df file, then call them\n\tall in install_builtin_functions().\n\t* Makefile.in: Handle .df instead of .def.\n\n\t* balance.cc (balance): Fix typo in doc string.\n\nWed Aug 28 21:01:49 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (verbose_usage): Include WWW address and bug-octave\n\tmailing list address.\n\nTue Aug 20 17:41:19 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: Only define pattern rules for making .oct files if\n\tOCTAVE_LITE is true.\n\tOnly add pic/ to $(TI_OBJ) if $(SHARED_LIBS) is true.\n\t(stamp-picdir): Only create a pic subdirectory if SHARED_LIBS or\n\tOCTAVE_LITE is true AND CPICFLAG or CXXPICFLAG is not empty.\n\n\t* minmax.cc (Fmin, Fmax): Deal with changes to Matrix class\n\tmin/max methods.\n\nThu Jul 25 01:42:38 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (generate_possible_completions): Force the names to be\n\tunique.\n\n\t* load-save.cc (read_mat_binary_data): Expect to read terminating\n\tNUL character in the variable name.\n\t(save_mat_binary_data): Likewise, save it here.\n\nWed Jul 24 05:08:07 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lsode.cc (Flsode): Don't set the return value if an error\n\toccurred during integration.\n\t* dassl.cc (Fdassl): Likewise.\n\n\t* file-io.cc (symbols_of_file_io): Redefine values of SEEK_SET,\n\tSEEK_CUR, and SEEK_END for Matlab compatibility.\n\t* oct-stream.cc (seek): Check for compatible values of ORIGIN arg.\n\tAlso handle \"bof\", \"cof\", and \"eof\".\n\nFri Jul 19 15:24:36 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-const.cc: When creating octave_value_reps from ComplexMatrix\n\tvalues, check to see if all the elements are actually real.\n\nTue Jul 16 10:53:42 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (decode_prompt_string): Swap meanings of \\h and \\H.\n\nMon Jul 15 16:01:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (run_command_and_return_output): Renamed from do_system.\n\t(Fsystem): Make `system (\"emacs\")' work as one would expect.\n\nSun Jul 14 17:34:33 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (Ffopen, Ffread, Ffwrite): Update doc strings,\n\tcorrectly handle default architecture and precision args.\n\n\t* load-save.cc (mopt_digit_to_float_format): Rename from\n\tget_floating_point_format.\n\t(float_format_to_mopt_digit): New function.\n\n\t* oct-stream.cc (octave_base_stream::read, octave_base_stream::write):\n\tSimplify by calling Matrix::read and Matrix::write to do real work\n\tof reading, writing, and format conversion.\n\n\t* oct-stream.h (octave_base_stream): Move data_type enum to\n\tliboctave/data-conv.h.  Use float_format from\n\tliboctave/mach-info.h instead of arch_type enum.\n\n\t* sysdep.h, sysdep.cc (octave_words_big_endian, ten_little_endians):\n \tDelete.  Now part of oct_mach_info class in liboctave.\n\nTue Jul  9 11:18:59 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* arith-ops.cc, balance.cc, dassl.cc, data.cc, filter.cc, find.cc,\n\tfsolve.cc, load-save.cc, log.cc, lsode.cc, minmax.cc, npsol.cc,\n\toct-obj.cc, oct-stream.cc, pr-output.cc, pt-cmd.cc, pt-const.cc,\n\tpt-fvc.cc, pt-plot.cc, quad.cc, rand.cc, sighandlers.cc, sort.cc,\n\tsyscalls.cc, unwind-prot.cc, xdiv.cc, xpow.cc:\n\tWhen indexing arrays, use operator() instead of elem() so that\n\tbounds checking can be done consistently.\n\nMon Jun 24 02:13:27 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-oct): Use INSTALL_PROGRAM, instead of\n\tINSTALL_DATA for installing shared libraries.\n\n\t* lex.l (grab_help_text): Ignore all initial comment characters,\n\tnot just the first.\n\t* variables.cc (gobble_leading_white_space): Likewise.\n\nSat Jun 22 22:43:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.h, input.cc (octave_completion_matches_called): New variable.\n\t(Fcompletion_matches): Set it to true on a successful call.\n\t* toplev.cc (main_loop): If octave_completion_matches_called is\n\ttrue, don't increment current_command_number.\n\nThu Jun 13 03:52:19 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (is_mapper_function_name,\n\tis_builtin_function_name): New functions.\n\t(Fdocument): Use them.\n\tDefine as regular function, not a text style function.\n\nThu Jun  6 00:09:25 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-plot.cc: Handle new built-in variable `gnuplot_has_frames'.\n\nWed Jun  5 14:45:04 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (decode_prompt_string): \\h now means the whole host\n\tname and \\H is the host name up to the first `.'.\n\nThu May 30 23:41:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* fn-cache.cc (octave_fcn_file_name_cache::do_list): Always\n\trecompute the lists of function files instead of trying to cache\n\tthem.\n\nTue May 28 12:05:24 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (warn_old_style_preference): New function.\n\t(check_preference): Use it.\n\n\t* fn-cache.h: Include <ctime> here.\n\nFri May 24 00:57:14 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (completion_matches): Don't return empty string_vectors.\n\n\t* octave.cc (long_opts): Add braindead.\n\nThu May 23 01:49:33 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (gnu_readline): New optional arg, force_readline.\n\t(get_user_input): Use it.\n\n\t* pt-const.cc (OCT_VAL_REP::assign): If converting the rhs to a\n\tnumeric value, convert a copy, not the actual object.\n\t(OCT_VAL_REP::do_index): Prevent s([]) from resulting in a string\n\twith zero rows.\n\n\t* mappers.cc: Handle toascii here.\n\t* strfns.cc: Not here.\n\n\t* mappers.cc: Handle tolower and toupper here.\n\t* mappers.h: Rename can_return_complex_for_real to flag and\n\toverload meaning for ch_mapper.\n\t* pt-fvc.cc (apply_mapper_fcn): Handle overloaded meaning.\n\n\t* syscalls.cc (stat): Return 3 values instead of just 1.\n\t(lstat): Likewise.\n\nWed May 22 02:34:20 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-const.cc (OCT_VAL_REP::make_numeric): For string to number\n\tconversions, correctly set type tag before calling force_numeric.\n\t(do_binary_op): Force string to number conversion if both args are\n\tstrings and we are doing some sort of comparison operation.\n\n\t* Makefile.in (stamp-tinst, stamp-interp): Use SH_TERMLIBS and\n\tSH_LIBS instead of TERMLIBS and LIBS.\n\n\t* pt-const.cc (do_unary_op): Add special case to handle\n\ttransposing strings.\n\n\t* pt-mat.cc (Vstring_fill_char): New variable.\n\t(symbols_of_pt_mat): DEFVAR it.\n\n\t* input.cc (generate_struct_completions,\n\tgenerate_possible_completions):\tReturn string_vector, not char **.\n\tChange all callers.\n\n\t* pt-const.cc (lookup_map_element): Use substr() correctly.\n\nTue May 21 21:37:17 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\n\t* octave.cc: New args --no-site-file and --no-init-file.  Delete\n\t--ignore-init-file.  The flag --norc (-f) implies both\n\t--no-site-file and --no-init-file.\n\nFri May 17 01:54:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (Fcompletion_matches): New function.\n\n\t* utils.cc (get_fcn_file_names): Delete.\n\t* help.cc (simple_help): Use new file name cache instead of\n\tcalling get_fcn_file_names.\n\t* variables.cc (make_name_list): Likewise.\n\n\t* fn-cache.h, fn-cache.cc, Map-fnc.cc: New files.\n\t* Makefile.in: Add them to the lists.\n\n\t* Makefile.in (uninstall): Install in octincludedir, not includedir.\n\n\t* pt-plot.h: Include <csignal> here.\n\nThu May 16 10:52:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (octave_stream::oscanf, octave_base_stream::oscanf,\n \toctave_base_stream::do_oscanf): New functions for backward\n\tcompatibility with older versions of Octave.\n\t(scanf_format_elt, scanf_format_list): Keep track of width specifier.\n\t* file-io.cc (Fscanf): New function.\n\t(Fscanf, Ffscanf, Fsscanf): Handle compatibility arg.\n\nWed May 15 01:00:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-stream.cc (do_scanf): If doing '%c' conversion, unset\n\tios::skipws on input stream.\n\n\t* sighandlers.h, sighandlers.cc (octave_child, octave_child_list):\n\tNew classes for keeping track of the child processes we create.\n\t(sigchld_handler): Check in octave_child_list to see if there is\n\tanything we can do for the child that died.\n\t* pager.cc: Register child pager process.\n\t* pt-plot.cc: Likewise, for the plotter.\n\t* Array-oc.cc: New file\n\t* Makefile.in (TI_SRC): Add it to the list.\n\n\t* pager.cc (do_sync): Don't check error_state.\n\t(flushing_output_to_pager): New static variable.\n\t(flush_octave_stdout): Use it to avoid doing anything if already\n\tflushing output.\n\n\t* sighandlers.cc (sigchld_handler): Call warning instead of\n\twriting directly to cerr.\n\t(sigpipe_handler): Call warning instead of message.\n\n\t* octave.cc (main): Call install_signal_handlers,\n\tinitialize_file_io, initialize_symbol_tables, and install_builtins\n\tbefore parsing command line options.\n\n\t* user-prefs.h, user-prefs.cc: Delete.\n\n\t* utils.cc (check_preference): Move here.\n\t* user-prefs.cc: From here.\n\n\t* defaults.cc: New file.  Move initialization stuff from\n\tvariables.cc.  Move DEFVARS for EDITOR, EXEC_PATH, LOADPATH,\n\tIMAGEPATH, and OCTAVE_VERSION here.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tINFO_FILE and INFO_PROGRAM.\n\t* help.cc: Move all of that here.\n\t(symbols_of_help): Add DEFVARS for INFO_FILE and INFO_PROGRAM.\n\nTue May 14 00:23:06 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pager.cc (do_sync): Be more defensive about sending stuff to the\n\texternal pager.\n\t* sighandlers.cc (sigchld_handler): For now, only wait for\n\toctave_pager_pid.  Don't call error().  Do set octave_pager_pid to\n\t-1 if the pager process no longer exists.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tPWD.\n\t* dirfns.cc: Move all of that here.\n\t(symbols_of_dirfns): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tdefault_save_format and save_precision.\n\t* load-save.cc: Move all of that here.\n\t(symbols_of_load_save): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\twarn_divide_by_zero.\n\t* arith-ops.cc: Move all of that here.\n\t(symbols_of_arith_ops): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* mappers.cc: Add wrappers for ctype is* functions so that they\n\twill work on systems that only define them as macros.\n\nMon May 13 00:27:08 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tsuppress_verbose_help_message.\n\t* help.cc: Move all of that here.\n\t(symbols_of_help): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\ttreat_neg_dim_as_zero.\n\t* pt-const.cc: Move all of that here.\n\n\t* pager.cc (octave_pager_stream::do_sync): Don't return early if\n\tnot interactive.\n\n\t* data.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\t* data.cc (symbols_of_data): New function.  Move definition of I,\n\tInf, J, NaN, e, eps, i, inf, j, nan, pi, realmin, and realmax here.\n\t* variables.cc: From here.\n\t(install_builtin_variables): Call symbols_of_data.\n\n\t* file-io.cc (symbols_of_file_io): New function.  Move definition\n\tof SEEK_CUR, SEEK_END, SEEK_SET, stdin, stdout, stderr here.\n\t* variables.cc: From here.\n\t(install_builtin_variables): Call symbols_of_file_io.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tdo_fortran_indexing, implicit_str_to_num_ok,\n\tok_to_lose_imaginary_part, prefer_column_vectors,\n\tprefer_zero_one_indexing, print_answer_id_name,\n\tpropagate_empty_matrices, resize_on_range_error, and\n\tstruct_levels_to_print.\n\t* pt-const.cc: Move all of that here.\n\t(symbols_of_pt_const): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\t* pt-fvc.cc (tree_identifier::assign): Use Vresize_on_range_error\n\tinstead of user_pref.resize_on_range_error here.\n\t* load-save.cc (save_mat_binary_data): Use Vimplicit_str_to_num_ok\n\tinstead of user_pref.implicit_str_to_num_ok here.\n\t* utils.cc (empty_arg): Use Vpropagate_empty_matrices instead of\n\tuser_pref.propagate_empty_matrices here.\n\t* pt-exp-base.cc (tree_expression::is_logically_true): Likewise..\n\n\t* pt-fcn.cc (symbols_of_pt_fcn): Also move DEFVAR for\n\tdefault_return_value here.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tps1, ps2, ps4, and completion_append_char.\n\t* input.cc: Move all of that here.\n\t(symbols_of_input): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\t* pt-pr-code.cc (indent): Use Vps4 instead of user_pref.ps4 here.\n\t* help.cc (Ftype): Also here.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tautomatic_replot, gnuplot_binary, and gnuplot_has_multiplot.\n\t* pt-plot.cc: Move all of that here.\n\t(symbols_of_pt_plot): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tbeep_on_error.\n\t* error.cc: Move all of that here.\n\t(symbols_of_error): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tempty_list_elements_ok.\n\t* pt-mat.cc: Move all of that here.\n\t(symbols_of_pt_mat): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tdefine_all_return_values, return_last_computed_value, and\n\tsilent_functions.\n\t* pt-fcn.cc: Move all of that here.\n\t(symbols_of_pt_fcn): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\twhitespace_in_literal_matrix.\n\t* lex.l: Move all of that here.\n\t(symbols_of_lex): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\twarn_assign_as_truth_value, warn_comma_in_global_decl,\n\twarn_function_name_clash, and warn_missing_semicolon.\n\t* parse.y: Move all of that here.\n\t(symbols_of_parse): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\toutput_precision, output_max_field_width, print_empty_dimensions,\n\tand split_long_rows.\n\t* pr-output.cc: Move all of that here.\n\t(symbols_of_pr_output): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\n\t* user-prefs.h, user-prefs.cc: Delete all stuff related to\n\tpage_screen_output, page_output_immediately, and pager_binary.\n\t* pager.cc: Move all of that here.\n\n\t* user-prefs.h (check_preference): Provide declaration.\n\t* user-prefs.cc (check_preference): Make external.\n\n\t* toplev.cc (Foctave_config_info): New function.\n\n\t* oct-conf.h.in: New file\n\t* Makefile.in (oct-conf.h): New target.\n\tAdd it to the appropriate lists.\n\n\t* sighandlers.cc (sigchld_handler): Don't complain about wait\n\treturning a negative value.\n\n\t* file-io.cc (Fsscanf, Fsprintf): Pass true for second arg of\n\toctave_stream constructor.\n\n\t* oct-stream.h (octave_stream): New field, preserve.\n\t(octave_stream::~octave_stream): If preserve, don't delete rep.\n\n\t* pager.cc (symbols_of_pager): Set default for\n\tpage_output_immediately to 0.\n\n\t* toplev.cc (do_system): Correctly handle return_output.\n\tAppend ends to output_buf before calling str().\n\n\t* variables.cc: If M_PI and M_E are available, use them.\n\n\t* mk-oct-links.in (links_dir): If old link exists, delete it first.\n\nSun May 12 01:46:07 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (DISTFILES): List defaults.h.in and oct-gperf.h here.\n\t(INCLUDES): Not here.\n\t(install-inc): New target.\n\t(uninstall): Also delete libraries and include files.\n\t(install-inc): If linkdir is a directory, leave it alone.\n\t(TERMLIBS, LIBPLPLOT, LIBDLFCN): Don't substitute here (now in\n\tMakeconf).\n\n\t* oct-stream.cc (octave_base_stream::do_read): Provide initial\n\tvalue for tmp var.\n\n\t* pt-walk.h, pt-pr-code.h, pt-pr-code.cc: New tree-walking classes.\n\t* Makefile.in: Add them to the appropriate lists.\n\t* pt-fvc-base.h, pt-exp-base.cc, pt-fvc-base.cc, pt-mvr-base.cc,\n\tpt-base.cc, pt-mvr.cc, pt-mat.h, pt-mat.cc, pt-fvc.cc,\n\tpt-const.cc, pt-cmd.cc, pt-const.h, pt-misc.cc, pt-plot.cc,\n\tpt-fcn.cc, pt-plot.h, pt-mvr.h, pt-mvr-base.h, pt-misc.h,\n\tpt-fcn.h, pt-exp.h, pt-exp.cc, pt-exp-base.h, pt-fvc.h, pt-cmd.h,\n\tpt-base.h:\n\tReplace print_code stuff with accept() functions.\n\tAdd member access functions where necessary.\n\t* help.cc (Ftype): Update to use new method of walking trees to\n\tprint text representation of user-defined functions.\n\n\t* file-io.cc (Ffscanf): Update doc string.\n\t(Fsscanf): Likewise.\n\n\t* oct-stream.cc (octave_base_stream::do_read): Correctly set max_size.\n\tPad mval with zeros on final resize.\n\t(octave_base_stream::do_scanf): Likewise.\n\t(do_scanf_conv): Correctly resize mval.\n\nSat May 11 05:14:09 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pager.cc (octave_pager_buf::sync): Correctly set bypass_pager.\n\n\t* lex.l (<MATRIX>{SNLCMT}*\\]{S}*): Match SNLCMT, not just SNL.\n\nFri May  3 11:05:30 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-const.cc (OCT_VAL_REP::set_index): Complain if type can't be\n\tindexed.\n\n\t* input.cc (get_user_input): Don't increment input line number if\n\tinput is coming from eval string.\n\n\t* user-prefs.cc: Allow empty strings for prompts.\n\nThu May  2 10:50:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-mvr.h (class tree_oct_obj): Declare values data member const.\n\nSun Apr 28 03:16:52 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* user-prefs.h (user_preferences): New field,\n\t`page_output_immediately'.\n\t* user-prefs.cc (init_user_prefs): Initialize it.\n\t(page_output_immediately): New function.\n\t* pager.cc (syms_of_pager): Add DEFVAR.\n\t(really_flush_to_pager): New file-scope variable.\n\t(flush_octave_stdout): Set and restore it.\n\t(octave_pager_buf::sync): Check it, user_pref.page_screen_output,\n\tand user_pref.page_output_immediately to decide when to really\n\tflush output.\n\t(more_than_a_screenful): New function.  If paging but not\n\timmediately, then check this too.\n\n\t* pager.cc (default_pager): Move here from variables.cc.  If pager\n\tis less and LESS is not in the environment, append useful flags.\n\t(symbols_of_pager): New function.\n\t* variables.cc (install_builtin_variables): Call it.\n\tDelete pager-related DEFVARs.\n\n\t* syswait.h (WIFSIGNALLED): Define if sys/wait.h doesn't.\n\n\t* sighandlers.cc: Handle SIGCHLD.\n\n\t* pager.cc, pager.h: Rewrite.\n\t* pt-mvr.cc, pt-misc.cc, pt-fcn.cc, pt-const.cc, oct-hist.cc,\n\tfile-io.cc, help.cc, variables.cc, qpsol.cc, dassl.cc, quad.cc,\n\tnpsol.cc, lsode.cc, fsolve.cc, load-save.cc, dirfns.cc, octave.cc,\n\ttoplev.cc, error.cc, input.cc:\n\tWrite to octave_stdout and octave_diary instead of calling\n\tmaybe_page_output() or maybe_write_to_diary_file().\n\n\t* oct-procbuf.h, oct-procbuf.cc: New files.\n\t* procstream.h (class procstreambase): Use octave_procbuf instead\n\tof procbuf from libg++, so we can get pids of subprocesses.\n\nFri Apr 26 01:21:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-const.cc (OCT_VAL_REP::do_index): Call maybe_mutate() before\n\treturning.\n\n\t* mappers.h (struct Mapper_fcn): Delete.\n\t(struct builtin_mapper_function): New field ch_mapper.\n\t* pt-fvc.h (tree_builtin): Convert type of mapper_fcn from\n\tMapper_fcn to builtin_mapper_function.\n\t* variables.cc (install_builtin_mapper): Likewise, for arg.\n\tSimplify, since we don't have to do the copying ourselves now.\n\t* pt-fvc.cc (apply_mapper_function): Handle ch_mapper case.\n\t* defun.h (DEFUN_MAPPER): Likewise.\n\t* mappers.cc (install_builtin_mappers): Likewise.\n\tAdd ctype is* functions here.\n\nThu Apr 25 00:57:06 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* arith-ops.h, defun-int.h, defun.h, dynamic-ld.h, gripes.h,\n\tload-save.h, oct-map.h, oct-obj.h, oct-stream.h, pt-cmd.h,\n\tpt-const.h, pt-exp-base.h, pt-exp.h, pt-fcn.h, pt-fvc-base.h,\n\tpt-fvc.h, pt-mat.h, pt-misc.h, pt-mvr-base.h, pt-mvr.h, pt-plot.h,\n\tsymtab.h, toplev.h, utils.h, variables.h, xpow.h, Array-tc.cc,\n\tMap-i.cc, Map-tc.cc, SLList-tc.cc, arith-ops.cc, balance.cc,\n\tbogus.cc, chol.cc, colloc.cc, dassl.cc, data.cc, det.cc,\n\tdirfns.cc, eig.cc, error.cc, expm.cc, fft.cc, fft2.cc, file-io.cc,\n\tfilter.cc, find.cc, fsolve.cc, fsqp.cc, givens.cc, gripes.cc,\n\thelp.cc, hess.cc, ifft.cc, ifft2.cc, input.cc, inv.cc,\n\tload-save.cc, log.cc, lpsolve.cc, lsode.cc, lu.cc, minmax.cc,\n\tnpsol.cc, oct-hist.cc, oct-obj.cc, oct-stream.cc, pager.cc,\n\tpinv.cc, pr-output.cc, pt-cmd.cc, pt-const.cc, pt-exp-base.cc,\n\tpt-exp.cc, pt-fcn.cc, pt-fvc-base.cc, pt-fvc.cc, pt-mat.cc,\n\tpt-misc.cc, pt-mvr-base.cc, pt-mvr.cc, pt-plot.cc, qpsol.cc,\n\tqr.cc, quad.cc, qzval.cc, rand.cc, resource.cc, schur.cc, sort.cc,\n\tstrfns.cc, svd.cc, syl.cc, symtab.cc, syscalls.cc, sysdep.cc,\n\ttimefns.cc, toplev.cc, utils.cc, variables.cc, xpow.cc, parse.y:\n\tRename tree_constant -> octave_value.\n\tRename Octave_object -> octave_value_list.\n\nWed Apr 24 22:15:34 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (Fsystem): Merge functionality of async_system and\n\tsync_system.\n\n\t* oct-fstrm.h, oct-iostrm.h, oct-prcstrm.h, oct-stdstrm.h,\n\toct-stream.h, oct-strstrm.h, oct-fstrm.cc, oct-iostrm.cc,\n\toct-prcstrm.cc, oct-stdstrm.cc, oct-stream.cc, oct-strstrm.cc,\n\tArray-os.cc: New files.\n\t* Makefile.in: Add them to the appropriate lists.\n\t* file-io.cc: Rewrite to use new stream classes.\n\nTue Apr 23 18:59:25 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* gripes.cc (gripe_not_supported): New function.\n\n\t* toplev.cc (do_octave_atexit, Fatexit): New functions.\n\t(octave_atexit_functions): New file-scope variable.\n\t* octave.cc (main): Register do_octave_atexit with atexit.\n\n\t* variables.cc (install_builtin_variables): Call\n\tsymbols_of_syscalls here.\n\n\t* syscalls.h, syscalls.cc: New files.\n\nMon Apr 22 21:14:01 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* syscalls.cc: New file.\n\t(Flstat, Fmkfifo, Fstat, Funlink, Fwait, Fwaitpid): Move here.\n\t* file-io.cc: From here.\n\t* Makefile.in (SOURCES): Add syscalls.cc to the list.\n\nWed Apr 17 18:34:10 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-info.h, file-info.cc: Delete files.\n\t* Makefile.in: Remove from lists.\n\n\t* toplev.cc (Fquit): Accept exit status argument.\n\t(Fflops): Delete (now a function file).\n\nThu Apr 11 16:20:20 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l: Recognize `.'.\n\tUpdate current_input_column even for unrecognized characters.\n\tReturn LEXICAL_ERROR for unrecognized characters.\n\nMon Apr  8 19:59:01 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (install_builtin_variables): Split into several\n\tfunctions to make compiling with g++ go faster and consume less\n\tmemory.\n\nSun Apr  7 16:25:35 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (Fsave): Print usage if i == argc.\n\t(Fload): Likewise.\n\nSat Apr  6 21:26:49 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (clean): Also delete pic/*.o\n\t(maintainer-clean, distclean): Also remove stamp-picdir,\n\tstamp-tinst, stamp-interp, and pic directory.\n\t(stamp-prereq): New target.\n\nWed Apr  3 11:19:30 1996  Rick Niles  <niles@axp745.gsfc.nasa.gov>\n\n\t* resource.cc: Don't make including sys/resource.h and sys/times.h\n\tmutually exclusive.\n\nFri Mar 29 13:43:37 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (distclean): Delete so_locations, which is created\n\ton DEC Alpha systems.\n\nThu Mar 28 02:53:48 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.h (undo_string_escape): Provide extern declaration here.\n\n\t* lex.l (NL): Allow \\r\\n as new line character.\n\t(.): Complain if invalid character is found on input\n\nFri Mar 22 03:47:52 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* resource.cc (getrusage): If getrusage is missing, try using\n\ttimes to at least fill in the cpu time values.  If neither one is\n\tavailable, return 0 for cpu times instead of NaN.\n\n\t* sighandlers.cc (octave_signal_mask): New file-scope variable.\n\t(octave_save_signal_mask, octave_restore_signal_mask): New functions.\n\t* toplev.cc (main_loop): Use them.\n\nWed Mar 20 01:21:28 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (get_fcn_file_names (const string&, int)): Resize\n\tretval to value of k, not i.\n\t(get_fcn_file_names (int)): In loop for copying names to retval,\n\tdon't increment j twice.\n\nMon Mar 18 22:27:19 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in ($(MAKEDEPS)): Depend on oct-gperf.h.\n\nFri Mar  1 18:15:52 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* fsolve.cc (fsolve_options): Delete unused argument nargout.\n\n\t* filter.cc: Use MArray instead of Array so that automatic\n\tconversions will work again.\n\nTue Feb 27 04:49:51 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (looks_like_octave_copyright): Make the strings\n\tthat we are trying to match both have length 29.\n\n\t* Makefile.in (install-bin): Use $(INSTALL_PROGRAM), not $(INSTALL).\n\n\t* load-save.cc (read_mat_binary_data): Make sure name is\n\tNUL terminated.\n\nMon Feb 26 18:18:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (whos): Make argv from tmp_args, not args.\n\n\t* defun.h (DEFCONSTX): Don't stringify name.\n\nSat Feb 24 01:12:59 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-oct): Make mk-oct-links executable.\n\t* mk-oct-links.in (links_dir): Update to match new format of\n\tDEFUN_DLD_BUILTIN macro.  Use LN_S, not just LN.\n\t(links_dir):\n\n\t* pr-output.cc (octave_print_internal): New arg, extra_indent, for\n\tversions of this function that take matrices and ranges.\n\t* pt-const.cc (TC_REP::print (ostream&)): Fix printing of structures.\n\tPass struct_indent to octave_print_internal as appropriate.\n\t(print_with_name (ostream&, const string&, bool)): Handle spacing\n\taround `=' differently for structures.\n\nFri Feb 23 04:51:04 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* token.cc (token (double, const string&, int, int)): Store orig_text.\n\nTue Feb 20 20:36:01 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (Fclear): Fix off-by-one error.\n\nSat Feb 17 16:54:02 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-hist.cc (default_history_file): Append \"/.octave_hist\" to\n\treturn value, not to home_directory.\n\nFri Feb 16 18:10:46 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc: (NINT, D_NINT): Move to liboctave.\n\n\t* sysdep.cc (octave_ieee_init): Move to liboctave.\n\n\t* procstream.h, procstream.cc: Rewrite.\n\n\t* pager.cc (cleanup_oprocstream): New static function.\n\t* toplev.cc (cleanup_iprocstream): Likewise.\n\t* dirfns.cc (cleanup_iprocstream): Likewise.\n\n\t* unwind-prot.cc (matrix_cleanup, complex_matrix_cleanup): Delete.\n\nThu Feb 15 22:03:28 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-obj.cc, oct-obj.h: Move most code to the header.\n\n\t* oct-obj.cc (make_argv, all_strings): New member functions.\n\t* utils.cc: Moved from here.\n\n\t* load-save.cc: Move byte swapping stuff to liboctave.\n\tMove float format conversion stuff to liboctave.\n\t(all_parts_int, too_large_for_float): Move to liboctave.\n\n\t* symtab.cc (valid_identifier): Move here.\n\t* load-save.cc: From here.\n\n\t* sysdep.cc: Move floating-point format stuff to liboctave.\n\t* pr-output.cc: Include float-fmt.h here.\n\nWed Feb 14 01:49:20 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defun.h, defun-dld.h, defun-int.h: Simplify interface for DEFUN,\n\tDEFUN_DLD, DEFVAR, and DEFCONST macros.  Change all uses.\n\n\t* qzval.cc: Move guts to liboctave.\n\nTue Feb 13 10:28:27 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (parse_fcn_file): Also avoid saving history if\n\tinput is from a script file.\n\n\t* help.cc (Ftype): Call unwind_protect_str for user_pref.ps4.\n\n\t* npsol.cc (nonlinear_constraints_ok): Now static.\n\n\t* npsol.cc (linear_constraints_ok): Now static.\n\t* qpsol.cc (linear_constraints_ok): Duplicate here.\n\n\t* data.cc (Flinspace): Don't print usage message if nargin == 2.\n\nSun Feb 11 14:20:32 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mk-oct-links.in: Rename from mk-oct-links.\n\t(LN_S): Use this variable instead of ln.\n\tSet -e option for shell.\n\tExit with status of last command.\n\tPrint message when making link.\n\t* Makefile.in (DISTFILES): Add mk-oct-links.in to the list.\n\t(install-oct): Run ./mk-oct-links, not $(srcdir)/mk-oct-links.\n\n\t* variables.cc (install_builtin_variables): Restore accidentally\n\tdeleted DEFVAR for save_precision.\n\nFri Feb  9 11:24:32 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (INCLUDES): Delete statdefs.h from the list (it's\n\tnow in the liboctave directory).\n\n\t* toplev.cc (toplevel): Define here.\n\t* octave.cc (toplevel): Not here.\n\n\t* toplev.cc (main_loop): New function.\n\t* octave.cc (main): Call it here instead of doing main loop\n\tactions here.\n\n\t* user-prefs.cc (do_fortran_indexing): Also set liboctave_dfi_flag.\n\t(prefer_column_vectors): Also set liboctave_pcv_flag.\n\t(prefer_zero_one_indexing): Also set liboctave_pzo_flag.\n\t(resize_on_range_error): Also set liboctave_rre_flag.\n\n\t* variables.cc (restore_command_history): New function.\n\t(parse_fcn_file): Use it here in unwind_protect.\n\n\t* dynamic-ld.cc (load_octave_oct_file): Reverse sense of test.\n\t(load_octave_builtin): Delete.\n\t(mangle_octave_oct_file_name): Delete.\n\n\t* pt-fvc.cc (tree_builtin::eval): Don't try to dynamically load\n\tfunctions here.\n\n\t* pr-output.cc (set_format_style): Decrement argc for first arg too.\n\n\t* input.cc (gnu_readline): If readline returns an empty string,\n\tconvert it to a string containing a single newline character.\n\n\t* octave.cc (octave_argv): Now a static string_vector.\n\t(intern_argv): Use string_vector ops, not charMatrix ops.\n\t* toplev.cc (octave_argv): Delete definition.\n\t* toplev.h (octave_argv): Delete declaration.\n\nThu Feb  8 10:58:24 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (conf-dist): New target.\n\nTue Feb  6 10:59:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (Ftype): Correctly handle structure names.\n\nSun Feb  4 02:02:20 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* qpsol.cc (Fqpsol): Call set_options(), not copy() to set\n\toptions for QPSOL objects.\n\n\t* npsol.cc (Fnpsol): Call set_options(), not copy() to set\n\toptions for NPSOL objects.\n\n\t* quad.cc (Fquad): Call set_options(), not copy() to set\n\toptions for Quad objects.\n\n\t* dynamic-ld.cc (load_octave_builtin): Don't call destructor on string.\n\t(load_octave_oct_file): Likewise.\n\tCheck oct_file.empty(), not just oct_file.\n\n\t* fsolve.cc (Ffsolve): Call set_options(), not copy() to set\n\toptions for NLEqn object.\n\n\t* variables.cc (do_who): Properly set match patterns from argument\n\tvector for call to maybe_list.\n\nSat Feb  3 03:29:33 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (long_opts): Properly set second field using new enum.\n\n\t* lsode.cc: Change ODE to LSODE where appropriate.\n\tUse LSODE_options, not ODE_options.\n\n\t* dassl.cc: Change DAE to DASSL where appropriate.\n\tUse DASSL_options, not ODE_options.\n\nFri Feb  2 01:41:37 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dirfns.cc: Include unistd.h.\n\n\t* parse.y, lex.l: Handle matrix lists without ml or mlnm stacks.\n\t* pt-mat.h, pt-mat.cc (tree_matrix):\n\tRewrite to use SLList instead of home brew list.\n\t* SLList-tm.cc: New file\n\t* Makefile.in: Add it to the lists.\n\t* SLStack-tm.cc: Delete.\n\t* Makefile.in: Delete it from the lists.\n\n\t* All pt-* files: Use bool instead of int where appropriate.\n\n\t* Makefile.in (DEP_SOURCES_3): Add octave.cc.\n\n\t* pt-const.h (class tree_constant::tree_constant_rep): Make\n\teverything in this class public, then it doesn't need to declare\n\tthe tree_constant class as a friend.\n\nThu Feb  1 01:42:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.h, lex.l, parse.h, parse.y (class lexical_feedback): New\n\tclass for lexer flags.  Replace lots of global vars with members\n\tof this class.\n\n\t* lex.l (class brace_paren_nesting_level): New class to replace\n\tnesting_level stack.  nesting_level is now an instance of this\n\tclass.\n\n\t* lex.l (yum_yum): New typedef.\n\t(ATE_NOTHING): New global var.\n\t(ATE_SPACE_OR_TAB, ATE_NEWLINE): Don't #define these, declare them\n\tas const yum_yum.\n\t(eat_whitespace, eat_continuation): Return yum_yum, not int.\n\n\t* lex.l (SHORT_CIRCUIT_LOGICALS): Delete.  Always do this for ||\n\tand && tokens.\n\t(yy_flex_alloc, yy_flex_realloc, yy_flex_free, next_char_is_space):\n\tDelete.\n\n\t* toplev.cc (verbose_flag): Delete definition.\n\t* toplev.h (verbose_flag): And declaration.\n\t* octave.cc (verbose_flag): Now static.\n\n\t* lex.l (lookup_identifier): Arg is now string, not char*.\n\t(handle_identifier, is_plot_keyword, is_keyword): Likewise.\n\t(strip_trailing_whitespace): Return value is now string, not char*.\n\t(plot_style_token): Likewise, for both arg and return value.\n\n\t* input.cc (octave_gets_line): Delete.\n\t(gnu_readline, octave_gets, octave_read):\n\tProperly handle input when using_readline is either true or false.\n\tDon't limit length of input lines to flex buffer size.\n\t(get_user_input): New function.\n\n\t* octave.cc (main): Handle --no-line-editing.\n\t* toplev.h (using_readline): Provide external declaration here.\n\t* input.h: Not here.\n\t* toplev.cc (using_readline): Define here.\n\t* input.cc: Not here.\n\n\t* toplev.h (no_line_editing): Delete declaration.\n\t* input.cc (no_line_editing): Delete definition.\n\nWed Jan 31 05:28:45 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* input.cc (DEFAULT_ARRAY_SIZE, PROMPT_GROWTH): Delete definitions\n\tof unused macros.\n\t(read_octal): Now static.\n\n\t* givens.cc (Fgivens): Use new functions from matrix classes\n\tinstead of calling Fortran functions directly.\n\t* syl.cc (Fsyl): Likewise.\n\t* expm.cc (Fexpm): Likewise.\n\nMon Jan 29 00:00:48 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc: Use new prog_args class instead of calling getopt\n\tdirectly.\n\n\t* getopt.h, getopt.c, getopt1.c: Move to liboctave directory.\n\t* Makefile: Remove from lists.\n\n\t* utils.cc (strconcat, read_until, discard_until): Delete.\n\n\t* pager.cc (terminal_columns, terminal_rows): Move to\n\tliboctave/oct-term.cc.\n\t* pager.cc, pr-output.cc: Include oct-term.h.\n\n\t* utils.cc (list_in_columns): Moved to liboctave/str-vec.cc.\n\tChange all callers to use new member function syntax.\n\n\t* dirfns.cc (absolute_program): Now static.\n\t(absolute_pathname): Delete.\n\n\t* pt-plot.cc (save_in_tmp_file): Call oct_tempnam, not\n\toctave_tmp_file_name.  Include file-ops.h.\n\t* file-io.cc (do_scanf, Foctave_tmp_file_name): Likewise.\n\t* oct-hist.cc (mk_tmp_hist_file): Likewise.\n\n\t* file-io.cc (Foctave_tmp_file_name): Move here.\n\t* utils.cc: From here.\n\n\t* utils.cc (octave_tmp_file_name): Move to liboctave/file-ops.cc.\n\n\t* tempname.c, tempnam.c: Move to liboctave directory.\n\t* Makefile.in: Remove from lists.\n\nSun Jan 28 19:00:52 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* xdiv.cc (all xdiv functions): Return Matrix or ComplexMatrix,\n\tnot tree_constant.\n\n\t* oct-hist.h, oct-hist.cc, toplev.cc, octave.cc, input.cc,\n\tfile-io.cc, user-prefs.cc: Rewrite to use new command_history\n\tclass instead of calling readline history functions directly.\n\n\t* utils.cc (get_fcn_file_names): Delete num arg.\n\nThu Jan 25 20:33:54 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (matches_patterns): Use new glob_match class\n\tinstead of calling fnmatch directly.\n\t* symtab.cc (matches_patterns, symbol_table::glob): Likewise.\n\t* variables.cc (Fclear): Likewise.\n\nWed Jan 24 02:05:22 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* fnmatch.h fnmatch.c: Delete.\n\t* Makefile.in: Add glob stuff in the appropriate places, remove\n\tfnmatch.h and fnmatch.c from lists.\n\n\t* octave.cc (program_invocation_name, program_invocation_short_name):\n\tMaybe declare.\n\t(initialize_globals): Maybe initialize them.\n\n\t* octave.cc (initialize_pathsearch): Define here, not in pathsearch.cc.\n\t* pathsearch.h, pathsearch.cc: Remove files.\n\t* Makefile.in: Remove them from the lists.\n\n\t* help.cc (simple_help): Ignore directories that don't have any .m\n\tor .oct files.\n\n\t* utils.cc (search_path_for_file): Use new dir_path class instead\n\tof calling kpathsea routines directly.\n\t(get_fcn_file_names): Likewise.\n\t* help.cc (simple_help): Likewise.\n\n\t* dirfns.cc (make_absolute): Don't convert empty arg to \"./\".\n\n\t* sysdir.h: Move to liboctave directory.\n\t* Makefile.in: Remove from lists.\n\n\t* dirfns.cc (Freaddir): Use new dir_entry class instead of calling\n\treaddir directly.  Include dir-ops.h, not sysdir.h.\n\t* utils.cc (get_fcn_file_names): Likewise.  Delete unnecessary\n\tfirst arg, change all callers.\n\nTue Jan 23 00:43:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* safe-xstat.hin, safe-xstat.cin, statdefs.h, file-ops.h,\n\tfile-ops.cc, filemode.c, mkdir.c, rmdir.c, rename.c:\n\tFiles moved to liboctave directory.\n\t* Makefile.in: Remove them from lists.  Move appropriate rules.\n\n\t* acosh.c, asinh.c, atanh.c, erf.c, erfc.c, gamma.c, lgamma.c:\n\tFiles moved to liboctave directory.\n\t* Makefile.in: Remove them from lists.\n\t* missing-math.h: Deleted.\n\t* pr-output.cc, sysdep.cc, minmax.cc, mappers.cc, expm.cc,\n\tarith-ops.cc: Include oct-math.h, not cmath or missing-math.h.\n\nMon Jan 22 19:33:05 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (Fexist): Use file_stat instead of calling stat\n\tdirectly.  Include file-ops.h, not statdefs.h.\n\t* octave.cc (execute_startup_files): Likewise.\n\t* file-io.cc (file_io_get_file, fopen_internal, popen_internal, Fstat):\n\tLikewise.\n\t(mk_stat_map): Likewise, use file_stat object, not struct stat.\n\t* oct-hist.cc (do_history): Likewise.\n\n\t* file-ops.h, file-stat.cc: New files.\n\t* Makefile.in: Include them.\n\t* dirfns.cc: Delete is_newer.  Don't include statdefs.h.\n\t* toplev.cc: Don't include statdefs.h.\n\nSun Jan 21 22:48:03 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-mvr.h, pt-fvc.h, Map.cc, Map.h, dynamic-ld.h,\n\tpt-fvc-base.cc, SLList-str.cc, pt-fcn.h, pt-fvc-base.h,\n\tSLStack-str.cc, pt-mvr.cc, pt-exp.cc, token.h, token.cc,\n\tuser-prefs.h, pt-base.cc, user-prefs.cc, dirfns.h, sysdep.h,\n\tsysdep.cc, input.h, parse.h, lex.l, parse.y, defun.h, mappers.h,\n\tpt-fvc.cc, pt-plot.h, load-save.h, octave.cc, defun-int.h, help.h,\n\tvariables.h, oct-map.h, oct-obj.h, oct-obj.cc, pt-const.cc,\n\toct-map.cc, input.cc, symtab.h, pt-const.h, pathsearch.cc,\n\tpr-output.h, pr-output.cc, toplev.h, timefns.cc, schur.cc,\n\tpt-plot.cc, pager.cc, load-save.cc, dynamic-ld.cc, dirfns.cc,\n\tdata.cc, file-info.h, file-info.cc, colloc.cc, utils.h, qpsol.cc,\n\tquad.cc, npsol.cc, lsode.cc, fsolve.cc, dassl.cc, file-io.cc,\n\thelp.cc, utils.cc, oct-hist.h, oct-hist.cc, symtab.cc, toplev.cc,\n\tpt-fcn.cc, unwind-prot.h, unwind-prot.cc, variables.cc:\n\tMost functions in these files that deal with character strings\n\thave been converted to use the string class insatead of char*.  If\n\tyou want more detailed information, you'll have to figure it out\n\tfor yourself.\n\nSat Jan 20 18:19:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc [WITH_DL]: Define RTLD_LAZY to be 1 if it is not\n\talready defined.\n\nSun Jan 14 07:48:05 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pt-const.cc (print_as_scalar, print_as_structure):\n\tMake these member functions.\n\t(tree_constant::print_with_name): New function, moved here from\n\told tree-expr.cc file (where it was called print_constant) and\n\tconverted to member function.  Change all callers.\n\nFri Jan 12 01:54:49 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (initialize_globals): Don't do kpathsearch stuff here.\n\t(main): Call initialize_pathsearch() here.\n\n\t* pathsearch.cc: New file.\n\t* Makefile.in (SOURCES): Add it to the list\n\n\t* oct-hist.h: Rename from octave-hist.h.\n\t* oct-hist.cc: Rename from octave-hist.cc.\n\t* Makefile.in, parse.y, other .cc files: Cope with it.\n\n\t* dynamic-ld.cc: Avoid warnings if !WITH_DYNAMIC_LINKING.\n\n\t* load-save.cc (save_ascii_data): string::data() returns const char*.\n\n\t* utils.h: Don't provide forward declaration for tree_constant.\n\n\t* oct-obj.h: Don't include mx-base.h or provide forward\n\tdeclarations for Matrix and Range types.\n\n\t* file-info.h: Don't include oct-obj.h.  Do include cstdio.\n\n\t* symtab.h: Don't provide forward declaration for ostream.\n\n\t* variables.h: Don't provide forward declarations for istream,\n\tostrstream, tree, builtin_function, or builtin_variable objects.\n\n\t* balance.cc, chol.cc, colloc.cc, dassl.cc, det.cc, eig.cc,\n\texpm.cc, fft.cc, fft2.cc, filter.cc, find.cc, fsolve.cc, fsqp.cc,\n\tgivens.cc, hess.cc, ifft.cc, ifft2.cc, inv.cc, log.cc, lpsolve.cc,\n\tlsode.cc, lu.cc, minmax.cc, npsol.cc, pinv.cc, qpsol.cc, qr.cc,\n\tquad.cc, qzval.cc, rand.cc, schur.cc, sort.cc, svd.cc, syl.cc:\n\tClean up #include statements.\n\n\t* pt-const.h: Don't include oct-obj.h or tree-base.h.\n\tProvide forward declaration of Octave_object here.\n\t* pt-const.cc: Include oct-obj.h here.\n\n\t* pt-mat.h, pt-fcn.h, pt-const.h, pt-misc.h, pt-plot.h,\n\tpt-exp-base.h, pt-cmd.h, pt-fvc-base.h, pt-mvr-base.h, pt-exp.h,\n\tpt-mvr.h, pt-fvc.h: New files, split from tree-expr.h and/or\n\trenamed from other tree-*.h files (pt == parse tree).\n\t* pt-base.cc, pt-const.cc, pt-exp.cc, pt-fvc-base.cc, pt-mat.cc,\n\tpt-mvr-base.cc, pt-plot.cc, pt-cmd.cc, pt-exp-base.cc, pt-fcn.cc,\n\tpt-fvc.cc, pt-misc.cc, pt-mvr.cc: Likewse, split from tree-expr.cc\n\tand/or other tree-*.cc files.\n\t* Makefile.in: Include them in the appropriate lists.\n\t* All: Fix #include statements to match.\n\n\t* Array-tc.cc: Don't instantiate ArrayRep objects.\n\nThu Jan 11 02:35:19 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-const.cc (tree_constant::eval (int, int, const Octave_object&)):\n\tDefine here instead of in tree-const.h.\n\nWed Jan 10 04:34:20 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-const.h (tree_constant::tree_constant (const string&):\n\t* tree-const.cc (TC_REP::tree_constant_rep (const string&)):\n\tNew constructor.\n\nTue Jan  9 04:10:29 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* rand.cc (do_rand): Use string_value() result directly instead of\n\tc_str() conversion.\n\t* balance.cc (Fbalance): Likewise.\n\n\t* tree-const.cc (TC_REP::string_value()):\n\tHandle new definition of charMatrix::row_as_string()\n\t* load-save.cc (save_ascii_data): Ditto.\n\t(save_binary_data): Ditto.\n\t* pr-output.cc (octave_print_internal): Ditto.\n\n\t* balance.cc (Fbalance):\n\tHandle new definition of TC_REP::string_value()\n\t* colloc.cc (Fcolloc): Ditto.\n\t* dassl.cc (Fdassl_options): Ditto.\n\t* data.cc (Fstruct_contains): Ditto.\n\t* dirfns.cc (Fmkdir): Ditto.\n\t(Freaddir): Ditto.\n\t(Frmdir): Ditto.\n\t(Frename): Ditto.\n\t* error.cc (handle_message): Ditto.\n\t* file-io.cc (process_printf_format): Ditto.\n\t(fopen_internal): Ditto.\n\t(file_io_get_file): Ditto.\n\t(return_valid_file): Ditto.\n\t(Flstat): Ditto.\n\t(Fstat): Ditto.\n\t(unlink_internal): Ditto.\n\t(mkfifo_internal): Ditto.\n\t(async_system_internal): Ditto.\n\t(sync_system_internal): Ditto.\n\t(execute_internal): Ditto.\n\t(popen_internal): Ditto.\n\t(fwrite_internal): Ditto.\n\t(fread_internal): Ditto.\n\t(do_printf): Ditto.\n\t(do_scanf): Ditto.\n\t* input.cc (get_user_input): Ditto.\n\t* lsode.cc (Flsode_options): Ditto.\n\t* npsol.cc (Fnpsol_options):Ditto.\n\t* qpsol.cc (Fqpsol_options):Ditto.\n\t* quad.cc (Fquad_options): Ditto.\n\t* rand.cc (do_rand): Ditto.\n\t* schur.cc (Fschur): Ditto.\n\t* sysdep.cc (Fputenv): Ditto.\n\t(Fgetenv): Ditto.\n\t* timefns.cc (extract_tm): Ditto.\n\t(Fstrftime): Ditto.\n\t* toplev.cc (Fsource): Ditto.\n\t(eval_string): Ditto.\n\t(Fsystem): Ditto.\n\t* tree-plot.cc (subplot::handle_plot_data): Ditto.\n\t* variables.cc (is_valid_function): Ditto.\n\t(Fis_global): Ditto.\n\t(Fexist): Ditto.\n\t(builtin_string_variable): Ditto.\n\t* utils.cc (make_argv): Ditto.\n\t(Fundo_string_escapes): Ditto.\n\nMon Jan  8 01:54:50 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-bin): Use $(LN_S), not just ln.\n\n\t* variables.cc (octave_fcn_file_dir): New function.\n\t* tree-expr.cc (mark_as_system_fcn_file): Use it instead of\n\toctave_lib_dir.\n\n\t* Makefile.in (clean): If $(SHARED_LIBS), also remove shared libs.\n\n\t* pr-output.cc (set_format (const ComplexMatrix&, int&, int&)):\n\tUnconditionally call all_elements_are_int_or_inf_or_nan().\n\t(set_format (const Matrix&, int&, int&)): Likewise.\n\nSun Jan  7 19:12:39 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc (oct_putenv): New function.\n\t* sysdep.cc (Fputenv): Use oct_putenv.\n\t* octave.cc (initialize_globals): Likewise.\n\nSat Jan  6 23:22:37 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sysdep.cc (Fputenv): New function.\n\n\t* input.cc (initialize_readline): Call rl_initialize() here.\n\n\t* octave.cc: Conditionally define atexit to be on_exit here.\n\t* toplev.cc: Not here.\n\nFri Jan  5 14:01:02 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc: Don't include <pwd.h> here.\n\n\t* octave-hist.cc, tree-plot.cc, utils.cc: Do include \"sysdep.h\".\n\n\t* dirfns.cc, file-io.cc, help.cc, load-save.cc, octave.cc,\n\toctave-hist.cc, tree-plot.cc, utils.cc:\n\tDon't include <readline/tilde.h>.\n\t* sysdep.h: Do include it here.\n\n\t* tree-const.cc (TC_REP::assign (tree_constant&, Octave_object&)):\n \tIf we have a matrix or range, call maybe_mutate before returning.\n\nSun Dec 31 15:56:18 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* npsol.cc (Fnpsol): Improve doc string.\n\t* qpsol.cc (Fqpsol): Likewise.\n\nFri Dec 29 21:46:58 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* defun-dld.h: Make work again for OCTAVE_LITE and\n\tWITH_DYNAMIC_LINKING.\n\n\t* Makefile.in: Handle shared libraries.\n\nWed Dec 27 17:47:51 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mk-oct-links: New file.\n\t* Makefile.in (install-oct): Use it.\n\t* f-*.cc: Rename to *.cc.\n\n\t* Makefile.in (install-bin, install-lib, install-oct): New targets.\n\t(install): Use them.\n\nTue Dec 26 21:38:22 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* toplev.cc (reading_startup_message_printed): Move initialization\n\there and make extern.\n\n\t* dirfns.cc, dynamic-ld.cc, help.cc, input.cc, octave-hist.cc,\n\toctave.cc, sighandlers.cc, sysdep.cc, tree-expr.cc, tree-misc.cc,\n\tutils.cc, variables.cc, parse.y, lex.l: Include toplev.h instead\n\tof octave.h.\n\t* toplev.h: rename from octave.h.\n\n\t* octave.cc (main): Delete unused variable saved_sigint_handler.\n\nSun Dec 24 00:26:54 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.cc: Massive re-write to handle dlopen/dlsym and\n\tshl_load/shl_findsym methods of dynamic linking.\n\n\t* utils.cc (get_fcn_file_names): Check for .oct files if\n\tWITH_DYNAMIC_LINKING, not WITH_DLD.\n\n\t* Makefile.in (LIB, TERMLIBS): Substitute values.\n\t(octave): Add $(LIBS) to link command and use $(TERMLIBS) instead\n\tof -ltermcap.\n\nSat Dec 23 21:56:12 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dynamic-ld.h, dynamic-ld.cc: Remove old unused code.\n\n\t* variables.cc (load_fcn_from_file):\n\tAlways call load_octave_oct_file.\n\nWed Dec 20 00:56:57 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pr-output.cc (set_real_format, set_real_matrix_format,\n\tset_complex_format, set_complex_matrix_format, set_range_format):\n\tNew functions.  Ensure the count of the digits to the right of the\n\tdecimal point is positive.\n\n\t* xpow.cc (xpow (const Matrix&, double)): Print warning if\n\tinverting singular matrix (but return value anyway, in the name of\n\tcompatibility).\n\txpow (const ComplexMatrix&, double)): Likewise.\n\n\t* f-inv.cc (Finv): If matrix is singular, return result anyway, in\n\tthe name of compatibility.\n\n\t* symtab.cc (symbol_record::pop_context):\n\tDon't assert (! context.empty ()).\n\n\t* tree-const.cc (TC_REP::char_matrix_value): Don't complain about\n\ttype conversion if object is an empty matrix.f\n\t(TC_REP::assign): If rhs is a string, don't convert to numeric\n\ttype if rhs is empty or \"\".\n\tOnly widen if rhs is not empty.\n\tDon't return 0x0 char_matrix if it is supposed to be a string.\n\n\t* arith-ops.h, mappers.h, pr-output.h, xdiv.h, xpow.h: Include\n\toct-cmplx.h in place of forward declaration for class Complex.\n\n\t* pr-output.cc, mappers.cc, arith-ops.cc, xdiv.cc, xpow.cc,\n\tutils.cc: Include \"oct-cmplx.h\" instead of <Complex.h>.\n\n\t* octave.cc (initialize_error_handlers): Don't call\n\tset_Complex_error_handler().\n\t(octave_Complex_error_handler): Delete unused function.\n\tDelete declaration for set_Complex_error_handler().\n\n\t* sighandlers.cc (catch_interrupts): New function.\n\t* octave.cc (main): Call catch_interrupts() instead of calling\n\toctave_set_signal_handler() directly.\n\nTue Dec 19 03:22:37 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (looks_like_octave_copyright): Also recognize the\n\tstring \" This program is free software\".\n\nThu Dec 14 01:54:06 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave-hist.cc (clean_up_history): Only write history file if\n\tuser_pref.saving_history.\n\n\t* octave-hist.cc (initialize_history, clean_up_history,\n\tdo_history): Perform tilde expansion on history file name.\n\n\t* octave.cc (main): Check `defined (HAVE_ON_EXIT)' not just\n\t`(HAVE_ON_EXIT)'.\n\n\t* user-prefs.h (user_preferences): New fields, `history_file' and\n\t`history_size'.\n\t* user-prefs.cc (init_user_prefs): Initialize them.\n\t(sv_history_file, history_size): New functions.\n\t* variables.cc (install_builtin_variables): Initialize user-level\n\tvariables history_file and history_size.\n\t* octave-hist.cc (default_history_size): Now extern.\n\t(default_history_file): Likewise.\n\t(octave_hist_size, octave_hist_file): Use user preference\n\tvariables instead.\n\t* octave.cc (main): Call initialize_history after\n\texecute_startup_files.\n\nFri Dec  8 15:53:59 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* user-prefs.h (user_preferences): New field, `saving_history'.\n\t* user-prefs.cc (init_user_prefs): Initialize it.\n\t(saving_history): New function.\n\t* variables.cc (install_builtin_variables): Initialize user-level\n\tvariable saving_history.\n\t* octave.cc (parse_and_execute): Don't reset value of\n\tsaving_history here.\n\t(main) Use user_pref.saving_history instead of saving_history.\n\t* variables.cc (parse_fcn_file): Likewise.\n\t* octave-hist.cc (maybe_save_history): Likewise.\n\tDon't save history if input_from_startup_file.\n\nMon Nov 27 23:05:52 1995  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* resource.cc: Include systime.h before <sys/resource.h>.\n\nTue Nov 14 14:09:40 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* error.cc: Include cstring.\n\n\t* tree-expr.cc (print_code): Decrement indent level after printing\n\tfunction body.\n\n\t* Makefile.in: Remove references to oct-str.cc, oct-str.h, and\n\tArray-string.cc.\n\n\t* tree-const.h: Don't include oct-str.h.\n\nMon Nov  6 11:16:49 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* parse.y (make_plot_command, finish_colon_expression,\n\tmake_unwind_protect, make_try_command, make_for_command,\n\tmake_break_command, make_continue_command, make_return_command,\n\tstart_if_command, finish_if_command, make_elseif_clause,\n\tmake_simple_assignment, make_multi_val_ret, start_function_def,\n\tfrob_function_def, finish_function_def, start_matrix,\n\tfinish_matrix):  New functions.  Use them in the grammar to clean\n\tthings up a bit.  Possibly convert matrix lists, colon\n\texpressions, binary expressions, and unary expressions to constant\n\tvalues.\n\t(tree_matrix_type): Delete.\n\t(simple_expr1): Handle all expression stuff here, including\n\tassignments.\n\t(simple_expr): Just check to see that simple_expr1 produced\n\tsomething useful.\n\n\t* tree-plot.cc, tree-plot.h: Move most simple constructors to the\n\theader file.\n\n\t* tree-expr.h (tree_expression::is_constant): Move virtual\n\tfunction definition here.\n\t(tree_fvc::is_constant): From here.\n\t(tree_expression::is_matrix_constant): New virtual function.\n\t(tree_expression::is_range_constant): New virtual function.\n\t* tree-expr.cc (tree_matrix::is_matrix_constant): New function.\n\t* tree-expr.cc (tree_colon_expression::is_range_constant): New\n\tfunction.\n\nFri Nov  3 03:42:04 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.cc, utils.h (jump_to_top_level): Declare as extern \"C\".\n\n\t* tree-const.h (tree_constant::eval ()): Only mutate if printing.\n\n\t* tree-const.cc (TC_REP::tree_constant_rep (const Complex&),\n\tTC_REP::tree_constant_rep (const ComplexMatrix&),\n\tTC_REP::tree_constant_rep (const ComplexDiagMatrix&),\n\tTC_REP::tree_constant_rep (const ComplexRowVector&),\n\tTC_REP::tree_constant_rep (const ComplexColumnVector&)):\n\tAlso check to see if we can convert to scalar_constant, not just\n\tcomplex_scalar_constant.\n\n\t* user-prefs.h (user_preferences): New field, `exec_path'.\n\t* user-prefs.cc (init_user_prefs): Initialize it.\n\t(sv_exec_path): New function.\n\t* variables.cc (install_builtin_variables): Add DEFUN for EXEC_PATH.\n\t(default_exec_path): New function.\n\t* octave.cc (exec_path): New global variable.\n\tDon't set and putenv() exec path here.\n\t(long_opts): Add --exec-path option.\n\t(main): Handle it.\n\t(initialize_globals): Set default value here.\n\n\t* user-prefs.h (user_preferences): New field, `info_prog'.\n\t* user-prefs.cc (init_user_prefs): Initialize it.\n\t(sv_info_prog): New function.\n\t* variables.cc (install_builtin_variables): Add DEFUN for INFO_PROGRAM.\n\t(default_info_prog): New function.\n\t* octave.cc (info_prog): New global variable.\n\t(initialize_globals): Set default value here.\n\t(long_opts): Add --info-prog option.\n\t(main): Handle it.\n\t* help.cc (try_info): Use user_pref.info_prog here.\n\n\t* octave.cc (initialize_globals): Put arch_dir and bin_dir ahead\n\tof shell_path when resetting PATH.\n\nThu Nov  2 04:30:13 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* f-rand.cc (Frandn): New function.\n\t(do_initialization): New function.\n\t(do_rand): New function for doing the real work.\n\t(Frand): Use it.\n\n\t* octave.cc (parse_and_execute): New arg, warn_for.  If given,\n\tprint message if file cannot be opened.\n\tSet curr_fcn_file_full_name here.\n\t(Fsource): Pass extra arg to parse_and_execute to get warning message.\n\n\t* tree-const.h: Handle line and column info for double, Complex,\n\tand char* constants.\n\n\t* parse.y (maybe_convert_to_ans_assign): Pass along line and\n\tcolumn info from expression.\n\n\t* parse.y (make_constant): New function.\n\t(simple_expr1, word_list): Use it.\n\n\t* input.cc, input.h (curr_fcn_file_full_name): New global.\n\t* variables.cc (load_fcn_from_file): Set it here.\n\t* parse.y (func_def2, yyerror, maybe_warn_missing_semi): Use it.\n\t(func_def2): If !reading_fcn_file, don't call strcmp if\n\tcurr_fcn_file_name is 0.\n\n\t* octave.cc (Fsource): New function.\n\t(parse_and_execute): Declare file name const char *.\n\t* input.cc (get_input_from_file): Likewise.\n\nWed Nov  1 13:54:34 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* f-filter.cc: New file.\n\t* Makefile.in (DLD_SRC): Add it to the list.\n\n\t* sysdep.h (gethostname): Change declaration to match definition\n\tin sysdep.cc.\n\n\t* resource.cc: Include sysdep.h here, for octave_NaN.\n\nTue Oct 31 02:12:18 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-const.cc (TC_REP::assign): After converting rhs to a\n\tnumeric type, use the converted value, not the original.\n\n\t* dirfns.cc (Fpwd): If nargout == 0, print the directory name\n\tinstead of returning it.\n\n\t* pager.cc (maybe_page_output): Call maybe_write_to_diary_file here.\n\t(flush_output_to_pager): Not here.\n\nMon Oct 30 23:39:43 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (install_builtin_commands): Add DEFVAR for\n\techo_executing_commands.\n\n\t* octave-hist.cc (do_edit_history): Handle new echo stuff.\n\t* variables.cc (parse_fcn_file): Likewise.\n\t* octave.cc (parse_and_execute): Likewise.\n\t(main): Likewise.\n\t* input.cc (do_input_echo):\n\t(Fecho): New function.\n\n\t* tree-expr.cc (tree_function::print_code_function_header,\n\ttree_function::print_code_function_trailer): New functions.\n\t(tree_function::print_code): Use them.\n\t(tree_function::eval): Likewise, if echoing commands.\n\t* tree-misc.cc (tree_statement::maybe_echo_code): New function.\n\n\t* user-prefs.h (user_preferences): New field, echo_executing_commands.\n\t(echo_state): New enum, for various types of echoing we do.\n\t* user-prefs.cc (echo_executing_commands): New function.\n\n\t* tree-base.cc (print_code_indent): Print PS4 as line prefix.\n\t* help.cc (Ftype): Add unwind_protect for ps4 and set it to \"\"\n\tbefore printing code.\n\n\t* tree-misc.h (tree_statement_list): New field, function_body.\n\t(tree_statement_list::mark_as_function_body): New function.\n\t* parse.y (func_def3): Mark function bodies.\n\n\t* pr-output.cc (octave_print_internal): Undo string escapes when\n\tprinting charMatrix as strings.\n\nSat Oct 28 17:38:29 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* utils.h (undo_string_escapes): Add missing const in declaration.\n\nFri Oct 27 03:49:44 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (next_available_file_number): New stack for keeping\n\ttrack of next available file number.\n\t(get_next_avail_file_num): New function.\n\t(fopen_file_for_user, fopen_internal, popen_internal,\n\texecute_internal): Use it.\n\nMon Oct 23 07:00:09 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-const.cc (TC_REP::convert_to_matrix_type,\n\ttree_constant::convert_to_matrix_type): New arg, make_complex.\n\t(TC_REP::set_index): New arg, rhs_is_complex.  Pass it to\n\tconvert_to_matrix_type.\n\t(TC_REP::assign): Pass rhs.is_complex_type() to set_index.\n\nThu Oct 19 00:38:38 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* xpow.cc: Include <climits>.\n\n\t* sysdep.cc (Fpause): Do pause even if not interactive.\n\n\t* tree-const.cc (TC_REP::assign): Don't make RHS numeric if both\n\tRHS and LHS are strings.\n\nWed Oct 18 22:19:16 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* f-expm.cc (Fexpm): Avoid taking log of negative number.  Also,\n\tdon't unnecessarily divide the input matrix by 1.0.\n\n\t* input.cc (decode_prompt_string): Recognize \\[ and \\] too.\n\t(initialize_readline): Bind M-p to history-search-backward and M-n\n\tto history-search-forward.\n\nTue Oct 17 04:31:06 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* xpow.cc (xpow): Handle integer powers better for complex^double.\n\t(elem_xpow): Likewise.\n\n\t* lex.l ({CCHAR}): If nesting_level.top() is BRACE, return ';',\n\tnot '\\n'.\n\nMon Oct 16 19:03:45 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* help.cc (Fwhich): Fix doc string.\n\n\t* variables.cc (Fexist): Update doc string.\n\nSun Oct 15 22:19:16 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Another massive set of changes to support character matrices\n\twith indexing.  The Octave_str_object class is no longer used.\n\tAnything having to do with Octave_str_object in the following\n\tfiles has been changed to use charMatrix instead: octave.h,\n\tload-save.cc, octave.cc, strfns.cc, data.cc, pr-output.h,\n\tpr-output.cc, tree-const.h, dirfns.cc, tree-const.cc,\n\ttree-expr.cc.\n\nSat Oct 14 22:28:18 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* f-sort.cc (mx_sort): Don't attempt to sort vectors that have\n\tonly one element, or matrices that have only one row.\n\nThu Oct 12 02:16:58 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* mappers.cc (install_mapper_functions): Add gammaln as an alias\n\tfor lgamma.\n\n\t* tree-const.h, tree-const.cc: Massive overhaul of indexing and\n\tindexed assignment functions.\n\t* tc-inlines.h, tc-rep.h: Remove files.\n\t* Makefile.in: Remove mention of them here too.\n\n\t* Makefile.in: Include $(TI_SRC) in DEP_SOURCES_3, not\n\t$(TI_SOURCES).\n\tInclude $(DLD_SRC) in DEP_SOURCES_3.\n\tInclude $(TI_SRC) in DEF_FILES_5.\n\nWed Oct 11 01:26:18 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (INCLUDES): Remove tc-inlines.h and tc-rep.h from\n\tthe list.\n\nMon Oct  9 08:31:04 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* lex.l (next_token_is_bin_op): Do match `.+', `.*', etc.\n\nSun Oct  8 18:19:56 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* idx-vector.h, idx-vector.cc: Delete files.\n\t* Makefile.in (SOURCES, INCLUDES): Remove them from lists.\n\nFri Oct  6 00:52:06 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* f-svd.cc (Fsvd): If nargout == 0 or nargout == 1, don't ask for\n\tU and V.\n\nWed Oct  4 00:04:57 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* f-npsol.cc (Fnpsol, Fnpsol_options): Avoid unused variable\n\twarnings if NPSOL_MISSING.\n\t* f-qpsol.cc (Fqpsol, Fqpsol_options): Likewise for QPSOL_MISSING.\n\n\t* Makefile.in (DISTFILES): Add octave.gperf.\n\n\t* lex.l (next_token_is_bin_op): Don't ever return true for `.'\n\tsince that causes problems with things like [ .1 .1 ].\n\nTue Oct  3 05:30:24 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (is_valid_function): Avoid setting error_state if\n\targument is not a string.\n\n\t* parse.y (maybe_warn_missing_semi): New function.\n\t(list1, list): Call it if statement not terminated by semicolon.\n\t* tree-misc.h (tree_statement::line, tree_statement::column):\n\tNew functions.\n\t* octave.cc (input_from_command_line_file): New global variable.\n\t(main): Set it.\n\t(parse_and_execute): Unwind-protect it and set it to zero.\n\t(eval_string): Likewise.\n\t* variables.cc (parse_fcn_file): Likewise.\n\n\t* user-prefs.cc (warn_missing_semicolon): New function.\n\t* user-prefs.h (user_preferences): New field, warn_missing_semicolon.\n\t* variables.cc (install_builtin_variables): DEFVAR it.\n\n\t* tree-expr.cc (tree_expression::is_logically_true): Actually use\n\targument.\n\nMon Oct  2 19:55:48 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (install_builtin_variables): Reduce the default\n\tvalue of save_precision to 15.\n\n\t* variables.cc (builtin_real_scalar_variable): Return 1 for\n\tsuccess, 0 for failure.\n\n\t* user-prefs.cc (struct_levels_to_print, set_save_precision,\n\tset_output_max_field_width, set_output_precision):\n\tChange sense of test for builtin_real_scalar_variable return value.\n\t(check_preference): Rename from check_str_pref.  Change all callers.\n\tAccept value of 0 to be the same as \"false\" and nonzero to be the\n\tsame as \"true\".\n\tDelete val to avoid memory leak.\n\t* variables.cc (install_builtin_variables): Change initial values\n\tfrom \"true\" to 1, \"false\" to 0.\n\n\t* variables.cc (install_builtin_variables): Add DEFVAR for\n\tgnuplot_has_multiplot.\n\n\t* user-prefs.h (user_preferences): New field,\n\t`gnuplot_has_multiplot'.\n\t* user-prefs.cc (init_user_prefs): Initialize it.\n\t(gnuplot_has_multiplot): New function.\n\nSat Sep 30 16:52:57 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* oct-gperf.h, octave.gperf: Newfiles.\n\t* Makefile.in (DISTFILES): Add octave.gperf.\n\t(INCLUDES): Add oct-gperf.h.\n\t(oct-gperf.h): New rule.\n\t(local-dist, dist): Depend on oct-gperf.h.\n\t* lex.l (is_keyword): Use perfect hash function to lookup\n\tkeywords.\n\nFri Sep 29 04:36:04 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* version.h (OCTAVE_NAME_AND_VERSION): Add TARGET_HOST_TYPE to this.\n\nThu Sep 28 00:03:51 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-expr.cc (tree_expression::is_logically_true): New function.\n\t* tree-cmd.cc (tree_while_command::eval): Use it instead of\n\thandling the test directly here.\n\t* tree-misc.cc (tree_if_clause::eval): Likewise\n\n\t* tree-const.cc (TC_REP::force_numeric): Don't try to print value\n\tof str_obj with %s.\n\n\t* error.cc (buffer_error_messages): Rename from\n\tsuppress_octave_error_messages.\n\t(error_message_buffer): New global variable.\n\t(verror): Handle buffering of messages.\n\t(handle_message): New function.\n\t(Ferror, Fwarning, Fusage): Use it instead of duplicating code.\n\n\t* octave.cc (Feval): Buffer error messages instead of supressing them.\n\n\t* lex.l (is_keyword): Recognize `try', `catch', and `end_try_catch'.\n\t* parse.y (TRY, CATCH): New tokens.\n\t(command): Recognize try-catch block.\n\t(end_error): Add cases for unwind_protect_end and try_catch_end.\n\t* token.h (end_tok_type): New field, try_catch_end.\n\t* tree-cmd.h, tree-cmd.cc (tree_try_catch): New class.\n\t* variables.cc (bind_global_error_variable): New Function.\n\t(clear_global_error_variable): Likewise.\n\t(install_builtin_variables): Add DEFCONST for __error_text__.\n\t* help.cc (keywords): Add `try', `catch', and `end_try_catch'.\n\n\t* tree-cmd.cc (tree_unwind_protect::eval): Undo previous change.\n\n\t* dirfns.cc (Freaddir, Fmkdir, Frmdir):\n\tDo tilde expansion on the argument.\n\nTue Sep 26 00:10:29 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* f-dassl.cc, f-fsolve.cc, f-lsode.cc, f-npsol.cc, f-quad.cc:\n\tDon't try to figure out if the user-supplied functions take the\n\tcorrect number of arguments.  Simply let the call fail.\n\t* variables.cc (takes_correct_nargs): Delete unused function.\n\t* tree-expr.cc (tree_builtin::eval): Don't complain for too many\n\targuments to mapper functions.\n\t* tree-expr.h, tree-expr.cc (tree_builtin, tree_function, tree_fvc):\n\tDelete unused function max_expected_args.\n\n\t* defun.h (DEFUN): Delete unnecessary args nargin_min and nargout_max.\n\tNew arg unused_arg_flags.\n\t(DEFUN_TEXT): Likewise.\n\t* defun-dld.h (DEFUN_DLD_BUILTIN): Likewise.\n\t* defun-int.h (DEFUN_INTERNAL, DECLARE_FUN, DEFINE_FUN_STRUCT):\n\tDo the real work.\n\n\t* data.cc, dirfns.cc, dynamic-ld.cc, error.cc, f-balance.cc,\n \tf-chol.cc, f-colloc.cc, f-dassl.cc, f-det.cc, f-eig.cc, f-expm.cc,\n \tf-fft.cc, f-fft2.cc, f-find.cc, f-fsolve.cc, f-fsqp.cc,\n \tf-givens.cc, f-hess.cc, f-ifft.cc, f-ifft2.cc, f-inv.cc, f-log.cc,\n \tf-lpsolve.cc, f-lsode.cc, f-lu.cc, f-minmax.cc, f-npsol.cc,\n \tf-pinv.cc, f-qpsol.cc, f-qr.cc, f-quad.cc, f-qzval.cc, f-rand.cc,\n \tf-schur.cc, f-sort.cc, f-svd.cc, f-syl.cc, file-io.cc, help.cc,\n \tinput.cc, lex.l, load-save.cc, mappers.cc, octave-hist.cc,\n \toctave.cc, octave.h, pager.cc, pr-output.cc, resource.cc,\n \tsighandlers.cc, strfns.cc, sysdep.cc, timefns.cc, token.cc,\n \ttree-const.cc, tree-expr.cc, tree-expr.h, tree-plot.cc,\n \tunwind-prot.cc, unwind-prot.h, utils.cc, variables.cc,\n \tvariables.h, version.h, xdiv.cc:\n\tAvoid unused variable warnings.\n\n\t* tree-expr.h (tree_oct_obj::print_value (ostream&)):\n\tDelete name of unused arg.\n\t(tree_fvc::save (ostream&, int, int): Likewise.\n\n\t* tree-const.h (tree_constant::tree_constant (magic_colon)):\n\tDelete name of unused arg.\n\t(tree_constant::tree_constant (all_va_args)): Likewise\n\t(ColumnVector vector_value (int, int)): Likewise.\n\t(ComplexColumnVector vector_value (int, int)): Likewise.\n\t(Octave_object::eval (int, int, const Octave_object&): Likewise.\n\n\t* octave.cc (execute_startup_files): Look for octaverc first in\n\tsite/m, then in $(version)/m.\n\t* variables.cc (get_local_site_defaults): New function.\n\t* defaults.h.in (OCTAVE_LOCALFCNFILEDIR, OCTAVE_LOCALSTARTUPFILEDIR):\n\tNew macros.\n\t* Makefile.in (defaults.h): Also substitute ${localfcndir}.\n\nMon Sep 25 17:01:03 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* variables.cc (install_builtin_variables): Add DEFCONST for \"e\".\n\nFri Sep 22 02:18:45 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dirfns.cc (Fls): Delete ls_command after using it, not before.\n\n\t* input.h, input.cc (gnu_readline): Don't declare gnu_readline\n\t`extern \"C\"'.\n\n\t* sysdep.h: Only declare gethostname if it is missing, then don't\n\tdeclare it `extern \"C\"'.\n\n\t* dirfns.cc: Don't declare strerror().\n\n\t* input.cc (command_generator): Use malloc, not xmalloc.  Don't\n\tdeclare xmalloc.\n\t(gnu_readline): Don't declare this `extern \"C\"'.\n\n\t* octave-hist.cc: Don't declare history_get().  It is now in\n\treadline/history.h.\n\n\t* input.cc: Don't declare history_get().  It is now in\n\treadline/readline.h.\n\n\t* resource.cc: Don't surround include of sys/resource.h in\n\t`extern\t\"C\" { }'.\n\n\t* fnmatch.h [__cplusplus]: Surround contents in `extern \"C\" { }'.\n\t* load-save.cc, symtab.cc, variables.cc: Don't surround\n\tfnmatch.h include in `extern \"C\" { }'.\n\n\t* help.cc: Don't #undef __FUNCTION_DEF before including\n\treadline/tilde.h.\n\n\t* dirfuns.cc, file-io.cc, help.cc, load-save.cc, octave-hist.cc,\n\tsysdep.cc, tree-plot.cc, utils.cc, variables.cc:\n\tDon't surround readline includes in `extern \"C\" { }'.\n\n\t* sysdep.cc: Move all include statements to top of file.\n\nTue Sep 19 01:58:21 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.cc (Fsystem): Use iprocstream *, and unwind_protect it.\n\t* pager.cc (flush_output_to_pager): Likewise.\n\t* dirfns.cc (Fls): Likewise.\n\t* tree-plot.cc (plot_stream): Now a pointer.\n\t(open_plot_stream): Deal with it.\n\t(send_to_plot_stream, cleanup_tmp_files, do_external_plotter_cd):\n\tLikewise.\n\n\t* procstream.cc (cleanup_iprocstream, cleanup_oprocstream):\n\tNew functions.\n\n\t* procstream.h, procstream.cc (class iprocstream, class oprocstream):\n\tKeep track of pbuf.  Initialize it to 0 in default constructors,\n\tdelete it in destructor.  Don't call close in destructor.\n\n\t* sighandlers.cc (octave_set_signal_handler): New function.\n\tUse this name instead of signal everywhere.\n\t* help.cc (try_info): Likewise.\n\t* pager.cc (flush_output_to_pager): Likewise.\n\t* octave.cc (main): Likewise.\n\t* octave-hist.cc (do_edit_history): Likewise.\n\n\t* input.cc (initialize_readline): Set rl_paren_string_delimiters\n\tto avoid treating single quotes as string delimiters when doing\n\tparen matching.\n\n\t* Makefile.in (SOURCES): Don't list Map.cc or SLStack.cc here.\n\n\t* tree-const.cc: Do include utils.h.\n\n\t* sysdep.cc: Don't surround terminal includes in extern \"C\".\n\tInclude them before readline.h.\n\n\t* Map.h: Don't include utils.h.\n\t(CHNode::CHNode (const char*, const C&, CHNode *t):\n\tDo strsave() inline.\n\n\t* input.cc (generate_possible_completions): Generate name list\n\teven when text == 0.\n\t(operate_and_get_next): Don't declare history_stifled, call\n\thistory_is_stifled () instead.\n\tDon't declare history_length, or max_input_history either.\n\tCheck (where >= history_length - 1) too, as in recent versions of\n\tbash.\n\n\t* user-prefs.h (user_prefs): New field, `completion_append_char'.\n\t* user-prefs.cc (init_user_prefs): Initialize it.\n\t(sv_completion_append_char): New function.\n\t* variables.cc (install_builtin_variables): Install\n\tcompletion_append_char.\n\t* input.cc (command_generator): Use it.\n\n\t* SLList-expr.cc, SLList-misc.cc, SLList-plot.cc, SLList-tc.cc,\n\tDLList-fi.cc: Include config.h.\n\t* DLList-fi.cc: Include file-info.h, not file-io.h.\n\nMon Sep 18 11:01:24 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.h (clean_up_and_exit): Tag with NORETURN instead of using\n\ttypedef trick.\n\t* error.h (panic): Likewise.\n\t* utils.h (jump_to_top_level): Likewise.\n\n\t* file-io.h: Protect from multiple includes with octave_file_io,\n\tnot octave_files.\n\n\t* file-info.h (class file_info): Convert to using std C++ string\n\tclass from char *.\n\t* file-info.cc: Likewise.  Don't include utils.h.\n\t* file-io.cc (return_valid_file, fopen_file_for_user,\n\tfflush_internal, do_scanf): Use operator ==, not strcmp.\n\t(close_files): Call error with file.name ().data (),\n\tnot file.name ().\n\t(freport_internal): Call form with file.mode ().data () and\n\tfile.name ().data ().\n\n\t* file-io.cc, file-io.h: Extract file_info class.\n\t* file-info.cc, file-info.h: New files for file_info class.\n\n\t* user-prefs.h (user_prefs): New field, `beep_on_error'.\n\t* user-prefs.cc (init_user_prefs): Initialize it.\n\t(beep_on_error): New function.\n\t* variables.cc (install_builtin_variables): Install beep_on_error.\n\t* octave.cc (maximum_braindamage): Set beep_on_error to \"true\".\n\t* error.cc (verror): Conditionally beep.\n\t(error): Don't reset error_state until after verror is called.\n\nSun Sep 17 16:41:25 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (read_mat_binary_data, read_ascii_data,\n\tsave_ascii_data, read_binary_data, save_binary_data):\n\tHandle string arrays.\n\nFri Sep 15 00:24:19 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* user-prefs.cc (struct_levels_to_print,\n\tset_output_max_field_width, set_output_precision,\n\tset_save_precision): Eliminate unecessary kludge variable.\n\n\t* variables.cc (gobble_leading_white_space): New arg,\n\tin_parts.  Change all callers.\n\n\t* lex.l (HELP_FCN): Delete start state.  The `help' command is now\n\thandled the same as any other text-style function.\n\n\t* gripes.cc (gripe_invalid_value_specified): New function\n\t* user-prefs.cc: Use it.\n\n\t* sysdep.cc (octave_words_big_endian): New global variable.\n\t(ten_little_endians): New function.\n\t(sysdep_init): Call it.\n\t* load-save.cc (words_big_endian): Use this at run-time instead of\n\tdepending on WORDS_BIGENDIAN at compile-time.\n\n\t* symtab.h (SYMTAB_VARIABLES): New macro.\n\t* variables.cc (Fclear): Use it instead of just\n\tsymbol_def::USER_VARIABLE when looking for variables.\n\n\t* octave.cc (main): If there is a file to execute, set\n\tprogram_invocation_name and program_name to the name of the file\n\tand argv to the remaining args.\n\t(intern_argv): Only define argv if there are some remaining\n\targuments.\n\n\t* defun.h (DEFVAR_INT): New macro.\n\t(DEFVAR): Define in terms of DEFVAR_INT.  Delete args protect and\n\teternal.\n\t(DEFCONST): New macro.\n\t* variables.cc (install_builtin_variables): Use DEFCONST where\n\tappropriate, change uses of DEFVAR to match new definition.\n\n\t* variables.cc (bind_builtin_variable): New variant that accepts\n\tconst tree_constant& value.\n\t(install_builtin_variables): Properly alphabetize DEFVAR for this.\n\n\t* octave.cc (short_opts): Prefix with `+' to prevent argv\n\tpermutation.\n\t(main): Don't use readline if forced_interactive.\n\t(traditional): New file-scope variable.\n\t(long_opts, usage_string, verbose_usage): Add `--traditional'.\n\t(maximum_braindamage): New function.\n\t(main): Call it if --traditional.\n\n\t* input.cc (do_input_echo): Print prompt correctly when\n\tforced_interactive is either true or false.\n\nThu Sep 14 00:54:06 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* data.cc (Fstruct_elements): New function.\n\n\t* file-io.cc (Fumask): New function.\n\n\t* dirfns.cc (Fmkdir, Frmdir, Frename): New functions.\n\n\t* Makefile.in: Add rules and dependencies for building safe-stat.o\n\tand safe-lstat.o.\n\n\t* mkdir.c, rename.c, rmdir.c: New files.\n\t* Makefile.in (SOURCES): Include them in the list.\n\n\t* safe-xstat.hin, safe-xstat.cin: New files\n\t* Makefile.in (DISTFILES): Include them in the list.\n\n\t* sighandlers.cc (octave_new_handler): Try to continue on memory\n\texhausted errors.\n\t(sigfpe_handler): Improve error message.\n\n\t* Makefile.in: Use `ifndef omit_deps', not `ifndef $(omit_deps)'.\n\n\t* dirfns.cc (Freaddir): New function.\n\n\t* f-sort.cc: Complete rewrite.  Now uses stable sort algorithm and\n\tcorrectly handles complex matrices containing columns of all real\n\tnumbers.\n\nWed Sep 13 03:16:40 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* arith-ops.cc: Unconditionally #define DIVIDE_BY_ZERO_ERROR.\n\n\t* variables.cc (install_builtin_variables): Unconditionally\n\tinstall NaN and nan.\n\n\t* mappers.cc (xisinf): Don't do bogus things if isinf, isnan, or\n\tfinite are missing.\n\t(xfinite): Likewise.\n\n\t* sysdep.cc (octave_ieee_init): Don't set octave_NaN and\n\toctave_Inf if values are not available.\n\n\t* resource.cc (mk_ru_map): Don't use ru_ or tv_ as prefixes to\n\tOctave names for the structure members.\n\nTue Sep 12 02:04:16 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* procstream.h, procstream.cc: Rewrite.\n\nMon Sep 11 18:42:05 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* filemode.c: New file, from Emacs.\n\t* Makefile.in (SOURCES): Add it to the list.\n\n\t* file-io.cc (Fstat, Flstat, mk_stat_map): New functions.\n\n\t* timefns.cc (mk_tm_map): Don't use tm_ as prefix to Octave names\n\tfor these structure members.\n\t(extract_tm): Likewise.\n\t(Flocaltime): Fix doc string to match.\n\nThu Sep  7 02:04:27 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* load-save.cc (save_user_variables): New function.\n\t* sighandlers.cc (my_friendly_exit): Call it before exiting.\n\t(sigfpe_handler): New function.\n\t(install_signal_handlers) [__alpha__]: Install it.\n\nWed Sep  6 14:35:10 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-cmd.cc (tree_unwind_protect::eval): Ignore errors and\n\tsuppress error messages while executing first block of\n\tunwind_protect commands.\n\n\t* parse.y (end_error): Add missing case for unwind_protect_end.\n\n\t* tree-expr.cc (tree_builtin::eval): Complain if no arguments\n\tgiven for mapper functions.\n\t(tree_fvc::lookup_map_element): Print error message for invalid\n\tstructure reference.\n\nTue Sep  5 02:04:12 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc, input.cc, load-save.cc, octave.cc, sysdep.cc,\n\tvariables.cc, octave-hist.cc, utils.cc, f-schur.cc, f-rand.cc,\n\tf-quad.cc, f-qpsol.cc, f-npsol.cc, f-lsode.cc, f-fsolve.cc,\n\tf-dassl.cc, f-colloc.cc, f-balance.cc, error.cc, data.cc:\n\tAdd const qualifiers where appropriate.\n\n\t* dirfns.h: Include <ctime>, for time_t.\n\n\t* tempname.c, file-io.cc, help.cc, input.cc, octave-hist.cc,\n\toctave.cc, sighandlers.cc, sysdep.cc, tree-expr.cc, tree-misc.cc,\n\ttree-plot.cc, utils.cc, variables.cc, sysdir.h:\n\tMove #include <sys/type.h> inside #ifdef HAVE_UNISTD_H.\n\n\t* syswait.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\t* file-io.cc, sighandlers.cc: Use it instead of including\n\tsys/wait.h directly.\n\n\t* octave.cc: Include statdefs.h, not sys/stat.h.\n\n\t* sysdir.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\t* dirfns.cc, utils.cc: Use it instead of including the headers\n\tdirectly.\n\n\t* pathlen.h: New file.\n\t* Makefile.in (INCLUDES): Add it to the list.\n\t* dirfns.cc, input.cc: Use it instead of including sys/param.h\n\tdirectly.\n\t* utils.cc: Don't include sys/param.h\n\nSun Sep  3 18:52:59 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-const.cc (TC_REP::string_value): Return const char*, not\n\tchar *.\n\n\t* All .cc, .y, .l, .y files: Include <cctype>, not <ctype.h>, and\n\tso on for all new C++ versions of these standard C headers.\n\nThu Aug 31 17:09:38 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* pathsearch.h: Also hide `string'.\n\n\t* oct-str.cc, oct-str.h: New files.\n\t* Makefile.in: Add to the appropriate lists.\n\t* tc-rep.h: Change char* to Octave_string* in anonymous union.\n\t* tree-expr.cc (tree_matrix::eval): Handle multiple element strings.\n\t* strfns.cc (toascii): Likewise.\n\t* tree-const.cc (print_as_string): Likewise.\n\t(TC_REP::force_numeric, TC_REP::rows, TC_REP::columns,\n\tTC_REP::double_value, TC_REP::complex_value, TC_REP::matrix_value,\n\tTC_REP::complex_matrix_value, TC_REP::convert_to_str): Likewise.\n\t(TC_REP::print): Call octave_print_internal for string case.\n\t(all_strings): New function.\n\tFix constructors to use new data structure.\n\t* pr-output.cc (octave_print_internal): Add version for strings.\n\t* Array-string.cc: New file.\n\n\t* octave.cc (octave_argv): New global variable.\n\t(intern_argv): New function.\n\t(main): Fix argument parsing to do the right thing for arguments\n\tto executable scripts.\n\t* variables.cc: Add DEFUNs for argv, program_invocation_name, and\n\tprogram_name.\n\n\t* defun.h (DEFVAR): Fix comment.\n\nThu Aug 24 00:02:00 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* file-io.cc (fgets_internal): Make second arg optional.  Add\n\toptional arg `strip_final_newline'.\n\t(Ffgets): Change to match new definition of fgets_internal.\n\t(Ffgetl): Implement using the new fgets_internal.\n\n\t* f-rand.cc (Frand): Update code for sizing return value to match\n\tthat used by ones, zeros, and eye.\n\nWed Aug 23 19:52:45 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-const.cc (do_vector_assign): Don't crash for\n\tA(range) = scalar, or A(matrix) = scalar.\n\n\t* f-dassl.cc (set_dassl_option): Rename from do_dassl_option.\n\t(show_dassl_option): New function.\n\t(Fdassl_options): Handle single arg.\n\t* f-fsolve.cc (set_fsolve_option): Rename from do_fsolve_option.\n\t(show_fsolve_option): New function.\n\t(Ffsolve_options): Handle single arg.\n\t* f-fsqp.cc (set_fsqp_option): Rename from do_fsqp_option.\n\t(show_fsqp_option): New function.\n\t(Ffsqp_options): Handle single arg.\n\t* f-lpsolve.cc (set_lpsolve_option): Rename from do_lpsolve_option.\n\t(show_lpsolve_option): New function.\n\t(Flpsolve_options): Handle single arg.\n\t* f-lsode.cc (set_lsode_option): Rename from do_lsode_option.\n\t(show_lsode_option): New function.\n\t(Flsode_options): Handle single arg.\n\t* f-npsol.cc (set_npsol_option): Rename from do_npsol_option.\n\t(show_npsol_option): New function.\n\t(Fnpsol_options): Handle single arg.\n\t* f-qpsol.cc (set_qpsol_option): Rename from do_qpsol_option.\n\t(show_qpsol_option): New function.\n\t(Fqpsol_options): Handle single arg.\n\t* f-quad.cc: (set_quad_option): Rename from do_quad_option.\n\t(show_quad_option): New function.\n\t(Fquad_options): Handle single arg.\n\t(Fquad): Doc fix.\n\nTue Aug 22 00:38:05 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-plot.cc (do_external_plotter_cd): New function.\n\t* dirfns.cc (octave_change_to_directory): New function.  If cd is\n\tsuccessful, also call do_external_plotter_cd().\n\t(Fcd): Call octave_change_to_directory(), not change_to_directory().\n\n\t* pr-output.cc (pr_any_float): Change declaration of counter to\n\tsize_t to avoid gcc warnings.\n\n\t* idx-vector.cc, octave-hist.cc, tree-const.cc, tree-expr.cc,\n\ttree-misc.cc, utils.cc, xpow.cc, Map.cc:\n\tUpdate for change in for loop variable scope for gcc 2.7.0.\n\nMon Aug 21 19:34:53 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* tree-const.cc (fortran_style_matrix_assignment): Properly handle\n\tcase of complex LHS, real RHS.\n\n\t* Makefile.in: Only include dependency files if $(omit_deps) is\n\tnot set.\n\nWed Jul  5 00:03:58 1995  John Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* sysdep.cc: Explicitly include string.h.\n\nSun Jun 25 00:18:10 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* load-save.cc (too_large_for_float (const Matrix&)):\n\tExtract elements as doubles, not Complex.\n\nSat Jun 24 22:59:15 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* pr-output.cc (any_element_is_inf_or_nan): Declare extern, not static.\n\t* f-svd.cc (Fsvd): Call here to avoid trying to take SVD of matrix\n\tcontaining Inf or NaN values.\n\n\t* pr-output.cc (bit_format): New file-scope variable.\n\t(set_format, pr_any_float): Handle bit_format.\n\t(octave_print_internal): Handle bit_format like bank_format.\n\t(init_format_state): Initialize bit_format.\n\t(set_format_style): Allow `format bit' and `format native-bit'.\n\nThu Jun  8 15:20:26 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* mappers.cc (arg, imag, signum): If arg is NaN, return NaN.\n\nMon May 15 14:47:04 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* pager.cc (Fdiary): Initialize diary_file here, not in the\n\tfile-scope declaration.\n\n\t* tree-expr.cc (tree_index_expression::eval):\n\tHandle nargin == 0 the same as other cases.\n\nTue May  2 10:02:23 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* load-save.cc (do_double_format_conversion): Add missing breaks.\n\t(do_float_format_conversion): Likewise.\n\nMon May  1 13:50:24 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makefile.in (OCTAVE_LIBS): Add @LIBPLPLOT@ to the list.\n\n\t* timefns.cc (Ftime): Handle GETTIMEOFDAY_NO_TZ.\n\n\t* Makefile.in (SOURCES): Delete tc-rep.cc, tc-rep-ass.cc, and\n\ttc-rep-idx.cc from the list.\n\n\t* tree-const.h: Add #pragma interface.\n\t* tree-const.cc: Add contents of tc-rep.cc, tc-rep-ass.cc, and\n\ttc-idx.cc to this file.  Add #pragma implementation.  This makes\n\ttree-const.cc large, but makes the final binary smaller.\n\n\t*  unwind-prot.h unwind-prot.cc token.cc token.h procstream.cc\n\tprocstream.h idx-vector.cc idx-vector.h symtab.cc symtab.h\n\toct-map.cc oct-map.h oct-obj.cc oct-obj.h tree-plot.h tree-plot.cc\n\ttree-misc.cc tree-misc.h tree-expr.cc tree-expr.h tree-cmd.cc\n\ttree-cmd.h tree-base.cc tree-base.h:\n\tAdd #pragma interface/implementation.\n\n\t* Makefile.in (OCTAVE_LIBS): Delete @LIBINFO@ from list.\n\t* help.cc: Don't include info headers or extern declarations for\n\tfunctions from info.\n\t(try_info): Call info as a subprocess.\tDelete second arg.\n\tHandle SIGINT here, not in help_from_info().\n\t(help_from_info): Complain if info doesn't work.\n\n\t* defun-dld.h (DEFUN_DLD_BUILTIN) [OCTAVE_LITE && MAKE_BUILTINS]:\n\tIf ! WITH_DLD, simply emit a character string constant.\n\nFri Apr 28 15:23:06 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* lex.l ({IDENT}{S}*): Don't delete tok.  That's handled by\n\tstrip_trailing_whitespace() now.\n\t(<HELP_FCN>[^ \\t\\n]*{S}*|<TEXT_FCN>[^ \\t\\n\\;\\,]*{S}*): Ditto.\n\n\t* pathsearch.h: Include kpathsea/progname.h.\n\t* octave.cc (initialize_globals): Call kpse_set_progname().\n\n\t* token.h: Declare copy constructor and operator = private.\n\t* token.cc: Abort if copy constructor or operator = is used.\n\nThu Apr 27 13:54:39 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* tree-expr.cc (lookup_map_element): Don't list default argument\n\tvalues here too.\n\n\t* pr-output.cc (hex_format): New file-scope variable.\n\t(set_format, pr_any_float): Handle hex_format.\n\t(octave_print_internal): Handle hex_format like bank_format.\n\t(init_format_state): Initialize hex_format.\n\t(set_format_style): Allow `format hex' and `format native-hex'.\n\n\t* variables.cc (bind_ans): Create ans_id each time with new and\n\task tree_simple_assignment_expression to handle cleaning it up.\n\tThis apparently plugs a memory leak.\n\n\t* help.cc (Ftype): Don't try to print map constants.  Handle\n\treferences to structure members.\n\nWed Apr 26 12:40:59 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* input.cc (generate_struct_completions): New function.\n\t(generate_possible_completions): Likewise.\n\t(looks_like_struct): Likewise.\n\t(command_generator): Handle completion of struct variables.\n\n\t* tree-expr.h, tree-expr.cc (tree_fvc::lookup_map_element):\n\tAdd insert and silent args.\n\n\t* oct-map.cc: New file.\n\t* Makefile.in (SOURCES): Add it to the list.\n\nMon Apr 24 09:41:02 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* variables.cc (Fexist): Handle structure references too.\n\n\t* tree-const.cc (lookup_map_element (const char*, int, int):\n\tNew function.\n\t(lookup_map_element (SLList<char*>&, int, int): New arg, silent.\n\t* tc-rep.cc (lookup_map_element): New arg, silent. If nonzero,\n\tdon't call error().\n\n\t* tc-rep.h (is_empty): Define here.\n\t* tree-const.h (is_empty): Hand off to TC_REP::is_empty().\n\n\t* data.cc (Fstruct_contains): Call lookup_map_element on args(0)\n\tinstead of extracting the map and calling contains() on it.\n\n\t* parse.y (EPLUS, EMINUS): New tokens.\n\t(simple_expr): Handle EPLUS, EMINUS the same as `+' and `-'.\n\t* lex.l (\".+\", \".-\"): New patterns.  Match these separately to\n\tdisallow using them as unary operators.\n\n\t* lex.l (next_token_is_bin_op): Simplify by noting that spacing\n\tonly matters for those tokens that can also be unary ops.\n\nFri Apr 21 14:34:45 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* load-save.cc (read_ascii_data): Allow reading of empty\n\tmatrices.\n\n\t* tc-rep-ass.cc (vector_assignment): Only assert that we are not\n\tdoing fortran-style indexing and that nr <= 1 || nc <= 1.\n\t(do_vector_assign): Handle assignment of [] when one dimension is\n\tzero and the other is anything.\n\nThu Apr 20 13:56:21 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* tc-rep-ass.cc (delete_rows, delete_columns): Simply return if\n\tnum_to_delete is 0.\n\n\t* lex.l (handle_identifier): Don't match plot option keywords\n\tinside parentheses or braces.\n\n\t* variables.cc (parse_fcn_file): Also delete tmp_help_txt if\n\trunning a script.\n\n\t* tree-cmd.h (tree_command): Add destructor.\n\n\t* tree-expr.h tree_simple_assignment_expression (lhs_idx_expr):\n\tHang on to idx_expr, not just its parts so it can be deleted.\n\t(init): Initialize it.\n\t* tree-expr.cc (~tree_simple_assignment_expression): Delete it.\n\n\t* tree-expr.h (tree_multi_val_ret, tree_oct_obj, tree_fvc,\n\ttree_identifier, tree_builtin, tree_function): Add destructors.\n\t* tree-expr.cc (tree_function::~tree_function): Delete some stuff.\n\n\t* tree-misc.h (tree_va_return_list): Add destructor.\n\n\t* octave.cc (__builtin_new, __builtin_delete): Provide our own,\n\tfor debugging.\n\n\t* utils.cc (strconcat): Don't depend on the return value from\n\tstrcat.\n\t(file_in_path): Simplify logic.\n\n\t* parse.y (maybe_convert_to_ans_assign): Create ans_id each time\n\twith new and ask tree_simple_assignment_expression to handle\n\tcleaning it up.  This apparently plugs a memory leak.\n\n\t* lex.l (strip_trailing_whitespace): Declare retval static.\n\tDelete it before saving next string.\n\n\t* error.cc (Ferror): Do call error() for empty string args.\n\t(error_1): Don't print anything if fmt is \"\" or \"\\n\", but do set\n\tthe error state appropriately.\n\n\t* tree-cmd.cc (tree_unwind_protect::eval): Handle return and break\n\tin the `try' part of the statement.\n\nMon Apr 10 19:29:44 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* f-expm.cc, f-givens.cc, f-qzval.cc, f-syl.cc, f-rand.cc:\n\tWhere appropriate, declare Fortran functions to take reference\n\tinstead of pointer args.  Change callers.\n\n\t* mappers.cc: Declare Fortran functions to take reference instead\n\tof pointer args.  Change callers.\n\n\t* gamma.c, lgamma.c, erfc.c, erf.c, atanh.c, asinh.c, acosh.c:\n\tDeclare Fortran functions to take reference instead of pointer\n\targs.\n\nSun Apr  9 19:38:53 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* file-io.cc (Fpopen, Fpclose, Fexecute, Fsync_system,\n\tFasync_system, Fwaitpid, Fmkfifo, Funlink): New functions.\n\n\t* sighandlers.cc (sigchld_handler): New function.\n\t(install_signal_handlers): Add call to install\n\tsigchld_handler. (This is #if 0'd out, waiting for code to help\n\tdetermine which child exited and what to do about it).\n\n\t* tree-expr.h (tree_oct_obj): New class.\n\n\t* tree-expr.h (tree_multi_assignment_expression::preserve): New\n\tdata member.  Add arg with default value to constructors.  Change\n\tcallers as necessary.\n\t* tree-expr.cc (~tree_multi_assignment_expression): Conditionally\n\tdelete lhs.\n\n\t* parse.y (make_multi_val_ret): Pass matrix instead of getting it\n\tfrom the global matrix list.\n\t(expression): Extract matrix from matrix list before calling\n\tmake_multi_val_ret().\n\n\t* parse.y (command): Handle new for loop syntax for structures.\n\n\t* tree-plot.h (subplot_list): Include tree_print_code() in\n\tinitializer lists for constructors.\n\t* tree-expr.h (tree_statement_list, tree_argument_list,\n\ttree_parameter_list, tree_return_list, tree_global_init_list,\n\ttree_if_command_list, ): Likewise.\n\n\t* tree-cmd.h (tree_for_command::id_list): New data member.\n\t(tree_for_command (tree_return_list*, tree_expression*,\n\ttree_statement_list*, int, int)): Likewise.\n\t* tree-cmd.cc (tree_for_command::eval): Handle for loops with\n\tstructures.\n\t(do_for_loop_once (tree_return_list*, Octave_object&, int&)):\n\tNew form for handling for loops with structures.\n\n\t* sysdep.cc (octave_ieee_init): Determine floating point format\n\there.\n\t(native_float_format): New global variable.\n\t(Fisieee): Compute return value from native_float_format, not by\n\tusing preprocessor macros.\n\t* sysdep.h (enum floating_point_format): Move declaration here.\n\t* load-save.cc: From here.\n\tAlways define all floating point format conversion routines.\n\t(do_double_format_conversion, do_float_format_conversion):\n\tUse native_float_format instead of preprocessor macros.\n\nSat Apr  8 15:41:35 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makefile (TEMPLATE_SRC): New variable.\n\t(DISTFILES): Add $(TEMPLATE_SRC).\n\t(SOURCES): Delete Map.cc and SLStack.cc from here.\n\n\t* variables.cc (install_builtin_variables): Use OCTAVE_VERSION\n\tinstead of version_string to initialize OCTAVE_VERSION.\n\t* version.h (version_string): Delete.\n\n\t* getopt.c (_getopt_internal): Initialize indfound to avoid warning.\n\nFri Apr  7 15:29:41 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* tc-inlines.h (REP_RHS_MATRIX): Just check to see if tc is real\n\tor complex.  If conversion fails, return.\n\nThu Apr  6 00:10:47 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* data.cc (Fstruct_contains): New function.\n\n\t* tc-rep.cc (print_code): Add extra parens around while condition\n\tto avoid warning.\n\t* utils.cc (undo_string_escapes): Likewise.\n\t* input.cc (decode_prompt_string): Likewise.  Also rewrite if\n\tstatement to avoid warning.\n\nTue Apr  4 22:54:17 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* tree-expr.cc (tree_multi_assignment_expression::eval,\n\ttree_simple_assignment_expression::eval):  Call print_constant\n\teven if user_pref.print_answer_id_name is false.\n\nMon Apr  3 17:57:14 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* tc-inlines.h (TC_REP): Avoid redefinition.\n\n\t* tree-const.h (do_binary_op, do_unary_op): Declare as friends of\n\ttree_constant class too.\n\n\t* tree-plot.h (subplot_using::have_values): Delete data member.\n\t* tree-plot.cc (subplot_using::eval): Always recompute values.\n\nFri Mar 31 10:18:32 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* tc-rep.cc (print): Print open brace for structures here.\n\t* tree-expr.cc (print_constant): Not here.\n\n\t* symtab.cc (define): Don't delete arg if sv_fcn fails.\n\n\t* tree-const.cc (print): New function.  Create ostrstream buffer\n\tand pass it to rep->print().\n\t* tree-const.h (eval (int)): Call print(), not rep->print().\n\t* tc-rep.cc (structure_indent_level): New file-scope variable.\n\t(print): New arg, output_buf, is stream to print to.\n\tPrint values of structure elements too.\n\n\t* user-prefs.h (user_preferences): New field, struct_levels_to_print.\n\t* user-prefs.cc (struct_levels_to_print): New function.\n\t* variables.cc (install_builtin_variables): Add DEFVAR for new\n\tvariable struct_levels_to_print.\n\n\t* tree-const.cc (print_as_scalar, print_as_structure): Move here\n\tfrom tree-expr.cc and make extern.\n\n\t* tree-expr.cc (print_as_structure): New function.\n\t(print_constant): Use it.\n\n\t* tree-expr.cc (print_constant): New arg, print_padding.\n\t(tree_simple_assignment_expression::eval): Use print_constant\n\tinstead of duplicating code here.\n\t(tree_multi_assignment_expression::eval): Likewise.\n\nThu Mar 30 13:24:11 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makefile.in (SOURCES): Add resource.cc.\n\t* resource.cc: New file, extracted from timefns.cc.\n\t(Fgetrusage): New function.\n\t* timefns.cc (cputime): Delete (now implemented in a function file\n\tusing new getrusage function).\n\nWed Mar 29 22:52:42 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* Makefile.in (SOURCES): Add strftime.c.\n\t* strftime.c: New file, from sh-utils distribution.\n\n\t* timefns.cc (mk_tm_map, extract_tm, Ftime, Fgmtime, Flocaltime,\n\tFmktime, Fstrftime): New basic time functions.\n\t(Fclock, Fdate): Delete (now implemented in function files using new\n\ttime functions).\n\nTue Mar 28 17:51:51 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* file-io.cc (return_valid_file, do_printf, do_scanf,\n\tfclose_internal, feof_internal, ferror_internal, fflush_internal,\n\tfgets_internal, fopen_internal, fread_internal, freport_internal,\n\tfrewind_internal, fseek_internal, ftell_internal,\n\tfwrite_internal): Declare static.\n\t* file-io.h: Delete extern declarations for them.\n\nFri Mar 24 09:52:50 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* pr-output.cc (pr_col_num_header): New function.\n\t(compact_format): New file-scope variable.\n\t(set_format_style): Handle loose and compact formats.\n\t(octave_print_internal (ostream&, const ComplexMatrix&, int)):\n\tReplace duplicate code with call to pr_col_num_header().\n\t(octave_print_internal (ostream&, const Matrix&, int): Likewise.\n\t(octave_print_internal (ostream&, const Range&, int): Likewise.\n\nTue Mar 21 08:44:48 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* mappers.cc (xgamma): Always use Slatec library function.\n\t* (xlgamma): Likewise.\n\t* Makefile.in (SOURCES): Don't include lgamma.c.\n\nFri Mar 17 22:38:39 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* tc-rep.cc (TC_REP::new): Don't try to keep track of newlist_tail.\n\tExplicitly initialize newlist to zero.\n\t* tree-const.cc (tree_constant::operator new): Likewise.\n\nFri Mar 10 12:40:24 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* tree-cmd.cc (quit_loop_now): Declare inline.\n\t(tree_for_command::do_for_loop_once): Split into two versions, one\n\tfor the general case and one for when the loop variable is a\n\tsimple identifier.\n\t(DO_LOOP): New macro.  Move tests outside of loop.\n\t(tree_for_command::eval): Speed up by checking to see if loop\n\tvariable is a simple identifier and by using DO_LOOP.\n\n\t* tree-const.h: New union of rep and freeptr.  The freeptr element\n\tis used for our custom memory management functions.\n\n\t* tc-rep.h: Add freeptr element to anonymous union (for our custom\n\tmemory management functions).\n\n\t* tree-const.cc (newlist, newlist_grow_size, newlist_tail): New\n\tstatic variables.\n\t(tree_constant::operator new): Always define to allow more\n\tefficient allocation of single tree_constants.\n\t(tree_constant::operator delete): Likewise, handle deletion of the\n\tmemory we allocate.\n\n\t* tc-rep.cc (newlist, newlist_grow_size, newlist_tail): New static\n\tvariables.\n\t(tree_constant::operator new): Always define to allow more\n\tefficient allocation of single tree_constants.\n\t(tree_constant::operator delete): Likewise, handle deletion of the\n\tmemory we allocate.\n\nFri Mar  3 14:00:08 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* error.cc (verror): Terminate output_buf with ends.\n\n\t* statdefs.h: Use C-style comment in first line instead of\n\tC++-style comment.\n\nMon Feb 27 10:11:18 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* parse.y (maybe_convert_to_ans_assign): Only lookup ans once.\n\t* variables.cc (bind_ans): New function.\n\t* tree-expr.cc (tree_identifier::eval (int)): Use it here.\n\t(tree_identifier::eval (int, int, const Octave_object&): And here.\n\n\t* tree-expr.cc (install_nargin_and_nargout): New function.\n\t* tree-expr.h (tree_function::tree_function (tree_statement_list *,\n\tsymbol_table *, int, int)): Call it.\n\n\t* tree-expr.cc (tree_function::bind_nargin_and_nargout): New function.\n\t(tree_function::eval): Call it insead of the one from variables.cc.\n\n\t* variables.cc (bind_nargin_and_nargout): #if 0 out.\n\nSun Feb 26 00:17:06 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* load-save.cc (Fload, Fsave): Free fname returned by tilde_expand().\n\t* dirfns.cc (Fls): Likewise.\n\n\t* tree-expr.cc (tree_multi_assignment_expression::eval (int, int,\n\tconst Octave_object&)): Call tree_return_list::operator () (Pix)\n\texplicitly.\n\n\t* octave.cc (initialize_globals): Put TEXMF in the environment for\n\tkpthsea.\n\n\t* Makefile.in (OCTAVE_LIBS): Use @LIBINFO@ and @LIBREADLINE@,\n\tsubstituted by configure.  Use kpathsea.a, not libkpathsea, so we\n\tdon't have to modify the kpathsea Makefile.\n\nSat Feb 25 18:59:26 1995  John Eaton  <jwe@schoch.che.utexas.edu>\n\n\t* pathsearch.cc: New file.\n\t* pathsearch.h: New file.\n\t* Makefile.in (INCLUDES): Include it in the list.\n\t* dynamic-ld.cc, help.cc, utils.cc: Use it instead of repeating\n\tidentical code multiple times.\n\n\t* variables.cc (install_builtin_variables): Only DEFVAR\n\tsuppress_verbose_help_message if USE_GNU_INFO.\n\n\t* help.cc (Fhelp): Only handle -i if USE_GNU_INFO.\n\t(additional_help_message): Only print message if USE_GNU_INFO.\n\t(builtin_help): New function.\n\t(help_from_info): New function.  Print warning if not USE_GNU_INFO.\n\nSee ChangeLog.1 in the top level directory for earlier changes.\n"
  },
  {
    "path": "etc/OLD-ChangeLogs/test-ChangeLog",
    "content": "2011-04-11  Rik  <octave@nomad.inbox5.com>\n\n\t* fntests.m: Remove deprecated and private functions from list of\n\tfunctions requiring tests.  Count functions with %!demo blocks as\n\thaving tests.\n\n2011-04-03  Rik  <octave@nomad.inbox5.com>\n\n\t* test_diag_perm.m: Reverse previous changeset.  Return 3-input form\n\tof diag().\n\n2011-04-01  Rik  <octave@nomad.inbox5.com>\n\n\t* test_diag_perm.m: Update diag tests to reflect removal of archaic\n\t3-input form of diag().\n\n2011-03-18  Rik  <octave@nomad.inbox5.com>\n\n\t* test_parser.m: Add operatore precedence tests.\n\n2011-03-01  Rik  <octave@nomad.inbox5.com>\n\n\t* test/test_index-wfi-t.m: Use modern warning function\n\trather than deprecated built-in variable to set warning state.\n\n2011-02-22  Rik  <octave@nomad.inbox5.com>\n\n\t* fntests.m: Use single quotes around regexp patterns.\n\n2011-02-19  Rik  <octave@nomad.inbox5.com>\n\n\t* fntests.m: Use PCRE regular expressions to simplify script.\n\n2011-02-02  Rik  <octave@nomad.inbox5.com>\n\n\t* build_sparse_tests.sh: Use testif to only run some sparse tests when\n\tnecessary libraries are installed.\n\n2011-01-14  John W. Eaton  <jwe@octave.org>\n\n\t* Update copyright notices for 2011.\n\n2010-12-13  Rik  <octave@nomad.inbox5.com>\n\n\t* test_switch.m : Add test for switch statement with otherwise clause,\n\tbut no cases.\n\n2010-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m: Set warning state off for Octave:deprecated-functions.\n\t(run_test_script): Do run tests for deprecated functions.\n\n2010-11-09  John W. Eaton  <jwe@octave.org>\n\n\t* test_parser.m: New file.\n\t* Makefile.am (FCN_FILES): Add it to the list.\n\n2010-09-29  Rik  <octave@nomad.inbox5.com>\n\n\t* fntests.m: Break output text differently for better readability.\n\n2010-09-28  Rik  <octave@nomad.inbox5.com>\n\n\t* test/@Gork/set.m, test/fntests.m, test/test_func.m, test/test_io.m:\n\tUntabify scripts.\n\n2010-09-27  Rik  <octave@nomad.inbox5.com>\n\n\t* fntests.m: Use single quotes for regex when possible.\n\n2010-09-26  Rik  <octave@nomad.inbox5.com>\n\n\t* fntests.m (has_tests, has_functions): Recode to remove requirement\n\tfor PCRE.\n\n2010-09-24  Rik  <octave@nomad.inbox5.com>\n\n\t* fntests.m: Rephrase output for clarity.\n\n2010-08-17  Rik  <octave@nomad.inbox5.com>\n\n\t* fntests.m: Add extra newline for more readable output.\n\n2010-07-30  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: New clean-local target to remove directories\n\tcreated automatically during testing.\n\n2010-04-28  John W. Eaton  <jwe@octave.org>\n\n\t* test_struct.m: Update expected error message text.\n\n2010-03-19  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* test_slice.m: Use ID check rather than message for invalid resizing.\n\n2010-03-05  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* test_logical-wfi-f.m: Update.\n\t* test_logical-wfi-t.m: Update.\n\t* test_struct.m Update.\n\n2010-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m (hasfunctions): Only check for DEFUN in .cc files.\n\tReturn true for all .m files.\n\n2010-01-14  David Grundberg  <davidg@cs.umu.se>\n\n\t* fntests.m (run_test_script): Check all *.cc files for tests.\n\n2010-01-13  Rik  <octave@nomad.inbox5.com>\n\n\t* build_bc_overload_tests.sh: Correct test syntax (= vs. ==)\n\n2010-01-13  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (test_bc_overloads.m): Accept expected results\n\tfile as argument.  Style fixes.\n\n2010-01-13  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* build_bc_overload_tests.sh: New shell script.\n\t* build_bc_overloads_expected.m: New source (not normally used).\n\t* bc_overloads_expected: New text file.\n\t* Makefile.am: Build test_bc_overloads.m.\n\n2009-12-25  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m (hastests): Use regexp instead of findstr and only\n\tmatch tests that appear as the first thing on a line.\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* build_sparse_tests.sh: Use lognrnd instead of deprecated lognormal_rnd\n\n2009-12-19  Rik  <octave@nomad.inbox5.com>\n\n\t* Makefile.am: Eliminate TOPDIR variable in favor of built-in automake\n\tvariables of top_builddir and top_srcdir.\n\n2009-12-17  Rik  <octdev@nomad.inbox5.com>\n\n\t* config/unix.exp: Remove obsolete file from repository\n\n2009-12-17  Rik  <octdev@nomad.inbox5.com>\n\n\t* @Blork/module.mk, @Cork/module.mk, @Dork/module.mk,\n\t@Gork/module.mk, @Pork/module.mk, @Sneetch/module.mk,\n\t@Snork/module.mk, @Spork/module.mk, Makefile.am: Distribute private\n\tfunction directories necessary for OOP tests to work in tarballs\n\n2009-12-03  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.am (CLEANFILES, DISTCLEANFILES): New variables.\n\n2009-11-10  John W. Eaton  <jwe@octave.org>\n\n\t* @Blork/module.mk, @Cork/module.mk, @Dork/module.mk,\n\t@Gork/module.mk, @Pork/module.mk, @Sneetch/module.mk,\n\t@Snork/module.mk, @Spork/module.mk, Makefile.am: New files.\n\t* Makefile.in: Delete.\n\n2009-10-19  Rik  <octdev@nomad.inbox5.com>\n\n\t* fntests.m: .cc files are now included in the list of files requiring\n\ttests only if they define a user function (DEFUN or DEFUN_DLD)\n\n2009-10-19  Rik  <octdev@nomad.inbox5.com>\n\n\t* fntests.m: Remove deprecated functions from list of functions\n\trequiring new tests to be written.\n\n2009-10-08  Rik  <octdev@nomad.inbox5.com>\n\n\t* fntests.m: Fix typo of an extra space in instructions to user.\n\n2009-10-05  Rik  <octdev@nomad.inbox5.com>\n\n\t* fntests.m: Fix typo directing users to the wrong log file\n\n2009-06-23  Robert T. Short  <octave@phaselockedsystems.com>\n\n\t* @Blork/Blork.m, @Blork/bleek.m, @Blork/display.m, @Blork/get.m,\n\t@Blork/set.m, @Cork/Cork.m, @Cork/click.m, @Cork/display.m,\n\t@Cork/get.m, @Cork/set.m, @Dork/Dork.m, @Dork/bling.m,\n\t@Dork/display.m, @Dork/gack.m, @Dork/get.m, @Dork/getStash.m,\n\t@Dork/private/myStash.m, @Dork/set.m, @Gork/Gork.m, @Gork/cork.m,\n\t@Gork/display.m, @Gork/gark.m, @Gork/get.m, @Gork/set.m,\n\t@Gork/subsasgn.m, @Gork/subsref.m, @Pork/Pork.m, @Pork/bling.m,\n\t@Pork/display.m, @Pork/get.m, @Pork/gurk.m,\n\t@Pork/private/myStash.m, @Pork/set.m, @Sneetch/Sneetch.m,\n\t@Sneetch/display.m, @Snork/Snork.m, @Snork/cack.m,\n\t@Snork/display.m, @Snork/end.m, @Snork/get.m, @Snork/getStash.m,\n\t@Snork/gick.m, @Snork/loadobj.m, @Snork/private/myStash.m,\n\t@Snork/saveobj.m, @Snork/set.m, @Snork/subsasgn.m,\n\t@Snork/subsindex.m, @Snork/subsref.m, @Spork/Spork.m,\n\t@Spork/cack.m, @Spork/display.m, @Spork/geek.m, @Spork/get.m,\n\t@Spork/getStash.m, @Spork/loadobj.m, @Spork/private/myStash.m,\n\t@Spork/saveobj.m, @Spork/set.m, test_classes.m: New files.\n\n2009-06-22  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* test_null_assign.m: Fix test.\n\n2009-04-17  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* test_struct.m: Add tests to prevent regression of bug with\n\tindexed assignment into empty struct array.\n\n2009-04-15  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* test_struct.m: Add tests for lazy copying in nested assignments\n\tof struct elements.\n\n2009-04-12  Thorsten Meyer  <thorsten.meyier@gmx.de>\n\n\t* test_contin.m, test_error.m, test_eval-catch.m, test_for.m,\n\ttest_global.m,  test_if.m, test_index-wfi-f.m,\n\t/test_index-wfi-t.m, test_io.m, test_logical-wfi-f.m,\n\ttest_logical-wfi-t.m, test_prefer.m, test_recursion.m,\n\ttest_return.m, test_string.m, test_struct.m, test_switch.m,\n\ttest_system.m, test_transpose.m, test_try.m, test_unwind.m,\n\ttest_while.m: Remove obsolete comments.\n\n2009-04-07  Carlo de Falco  <kingcrimson@tiscali.it>\n\n\t* test_io.m: Add a test for saving and reading a matrix with the\n\t\"-ascii\" format.\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* test_diag_perm.m: Add tests for permuting sparse matrices and\n\tfor the correct types from interactions between\n\tpseudo-scalars (1x1 matrices).\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* build_sparse_tests.sh: Add LU tests to the rectangular tests.\n\n2009-03-10  Jason Riedy  <jason@acm.org>\n\n\t* test_diag_perm.m: Add a test for conversion to sparse form.\n\n2009-03-09  Jason Riedy  <jason@acm.org>\n\n\t* test_diag_perm.m: Add tests for diag + sparse.\n\n2009-03-08  Jason Riedy  <jason@acm.org>\n\n\t* test_diag_perm.m: Add tests for inverse scaling and sparse structure.\n\n2009-03-08  Jason Riedy  <jason@acm.org>\n\n\t* test_diag_perm.m: Add tests for preserving sparse structure\n\twhen scaling.\n\n2009-02-25  John W. Eaton  <jwe@octave.org>\n\n\t* build_sparse_tests.sh: Note that saving sparse matrices to MAT\n\tfiles fails when using 64-bit indexing.\n\n2009-02-22  John W. Eaton  <jwe@octave.org>\n\n\t* build_sparse_tests.sh: Fix diag matrix divide by zero test.\n\n2009-02-18  John W. Eaton  <jwe@octave.org>\n\n\t* test_args.m: Don't use assert to test for function handles.\n\n2009-02-15  John W. Eaton  <jwe@octave.org>\n\n\t* test_io.m, test_prefer.m: Avoid command-style function call\n\tsyntax when assigning results.\n\n2009-02-09  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m (hastests): Error if fopen fails.\n\n2009-01-29  John W. Eaton  <jwe@octave.org>\n\n\t* test_system.m: Use isfield instead of struct_contains.\n\n2009-01-25  Thorsten Meyer  <thorsten@hexe>\n\n\t* test_struct.m: Add struct array tests.\n\n2009-01-23  Søren Hauberg  <hauberg@gmail.com>\n\n\t* test_prefer.m: Update to match new API of the 'type' function.\n\n2008-12-24  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m (hastests): Use fread instead of fscanf to preserve\n\twhitespace.\n\n2008-12-02  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* build_sparse_tests.sh: Fix test.\n\n2008-10-28  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* test_logical-wfi-f.m: Fix error messages.\n\t* test_logical-wfi-t.m: Fix error messages.\n\t* test_slice.m: Fix error messages.\n\n2008-09-26  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* test_null_assign.m: More test for null assignments.\n\n2008-09-18  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* test_null_assign.m: New tests.\n\n2008-06-11  John W. Eaton  <jwe@octave.org>\n\n\t* test_error.m: Fix tests for usage.\n\t* test_eval-catch.m, test_try.m: Fix expected output from lasterr.\n\n2008-06-02  David Bateman  <dbateman@free.fr>\n\n\t* test_arith.m: Delete and move tests close to function\n\tdefinitions.\n\t* test_func.m: Also test for single precision return values.\n\n\t* test_infnan.m, test_linalg.m, test_matrix.m, test_number.m):\n\tDelet and move tests close to function definitions.\n\t* test_range.m: Also test single precision examples.\n\n2008-05-19  Bill Denney  <bill@denney.ws>\n\n\t* test_args.m: Update format to allow running \"test test_args\"\n\tand add default argument tests.\n\n2008-05-09  Rafael Laboissiere  <rafael@debian.org>\n\n\t* test_io.m, test_system.m: Use ischar instead of deprecated isstr.\n\n2008-05-06  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m: Use puts instead of printf where appropriate.\n\tFix missing newline in message.\n\n2008-03-26  David Bateman  <dbateman@free.fr>\n\n\t* test_index-wfi-f.m: Split large block of tests.  New tests.\n\n2008-03-26  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m (report_files_with_no_tests): New function.\n\tUse it to report number of .m and .cc files without tests separately.\n\n2008-03-25  John W. Eaton  <jwe@octave.org>\n\n\t* test_index-wfi-f.m: New tests.\n\n2008-03-25  Jaroslav Hajek  <highegg@gmail.com>\n\n\t* test_io.m: Add test for save with -struct modifier.\n\n2008-03-20  David Bateman  <dbateman@free.fr>\n\n\t* test_func.m: Modify to test for char, cell and structure arrays.\n\n\t* test_func.m: New test code that ensures that all operations\n\twhich work on dimensions alone (squeeze, triu, etc.) work for all\n\tobjects and preserve type.\n\n2008-04-09  Michael Goffioul  <michael.goffioul@gmail.com>\n\n\t* test_string.m: Fix isprint test under Win32, where\n\tisprint(setstr(9)) is true.\n\t* test_system.m: Add condition for various syscall tests. Make cd test\n\table to deal with drive-letter-only pathnames (e.g. C:\\) under Win32.\n\n2008-03-07  John W. Eaton  <jwe@octave.org>\n\n\t* test_logical-wfi-t.m, test_logical-wfi-f.m: Update tests for\n\tlogical indexing bug fix.\n\n2008-03-06  John W. Eaton  <jwe@octave.org>\n\n\t* test_eval.m, test_diffeq.m, test_quad.m, test_signal.m:\n\tDelete files with no tests.\n\n2008-02-25  Ben Abbott  <bpabbott@mac.com>\n\n\t* test_eval-catch.m, test_io.m, test_try.m: Use cstrcat instead of\n\tstrcat.\n\n2008-02-22  David Bateman  <dbateman@free.fr>\n\n\t* build_sparse_tests.sh: Replaced removed sparse functions like\n\tspdiag with their generic names. Fix lu tests for modified\n\tsyntax. Test vector and scaling or LU and chol functions.\n\t* test_linalg.m: Change error message of failing chol/lu test.\n\n2008-02-19  David Bateman  <dbateman@free.fr>\n\n\t* build_sparse_tests.sh: Replaced removed spars functions like\n\tspmin, with their  generic names.\n\n2008-01-22  John W. Eaton  <jwe@octave.org>\n\n\t* test_poly.m, test_set.m, test_stats.m: Delete files with no tests.\n\n2008-01-22  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* test_linalg.m, test_matrix.m, test_number.m, test_poly.m,\n\ttest_signal.m, test_stats.m, test_string.m, test_system.m:\n\tMove tests to individual source files.\n\n2008-01-15  Thomas Weber  <thomas.weber.mail@gmail.com>\n\n\t* test_arith.m: Move tests to source files.\n\n2008-01-15  John W. Eaton  <jwe@octave.org>\n\n\t* test_audio.m, test_control.m, test_image.m, test_optim.m,\n\ttest_plot.m, test_unix.m: Delete files with no tests.\n\n2007-12-21  John W. Eaton  <jwe@octave.org>\n\n\tVersion 3.0.0 released.\n\n2007-12-18  David Bateman  <dbateman@free.fr>\n\n\t* build_sparse_tests.sh: Add tests for indexing like a([1,1],:),\n\ta(:,[1,1]) and sparse(42)([1,1]).\n\n2007-12-11  David Bateman  <dbateman@free.fr>\n\n\t* build_sparse_tests.sh: Drop argument to Fsparse to force mutation.\n\t* test_range.m: Ditto.\n\n2007-12-10  John W. Eaton  <jwe@octave.org>\n\n\t* test_nonlin.m: Delete.\n\n2007-12-03  David Bateman  <dbateman@free.fr>\n\n\t* fntests.m: Also count the skipped tests.\n\t* build_sparse_tests.sh: As appropriate make tests conditional on\n\tHAVE_UMFPACK, HAVE_CHOLMOD and HAVE_CXSPARSE.\n\n2007-11-26  David Bateman  <dbateman@free.fr>\n\n\t* build_sparse_tests.sh: More care with sparse return values.\n\n2007-10-30  Kim Hansen  <kimhanse@gmail.com>\n\n\t* build_sparse_tests.sh: Fix typo.\n\n2007-10-23  John W. Eaton  <jwe@octave.org>\n\n\t* build_sparse_tests.sh (gen_sparsesparse_elementop_tests):\n\tUse xtest for \"assert(as./bs,sparse(af./bf,true),100*eps);\" test.\n\n2007-10-12  John W. Eaton  <jwe@octave.org>\n\n\t* Change copyright notices in all files that are part of Octave to\n\tGPLv3 or any later version.\n\n2007-10-06  John W. Eaton  <jwe@octave.org>\n\n\t* test_poly.m: Move residue test to residue.m.\n\n2007-09-29  Kim Hansen  <kimhanse@gmail.com>\n\n\t* test_range.m: Test range data\n\n2007-09-21  John W. Eaton  <jwe@octave.org>\n\n\t* test_slice.m: Fix test for x = ones ([0, 2]); x(idx) = N case.\n\tSee change for liboctave/Array.cc.\n\n2007-06-15  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m: Also report expected failures in summary.\n\tImproved wording from Thomas Weber <thomas.weber.mail@gmail.com>.\n\n2007-06-06  John W. Eaton  <jwe@octave.org>\n\n\t* test_signal.m: Rename internal assert function to xassert.\n\n2007-04-26  David Bateman  <dbateman@free.fr>\n\n\t* test_for.m: Add tests for multi-dimensional matrices and cell\n\tarrays.\n\n2007-04-04  Rafael Laboissiere  <rafael@debian.org>\n\n\t* Makefile.in (clean): Also remove a.wav file created by\n\ttesting wavwrite.m.\n\n2007-04-03  Kim Hansen  <kimhanse@gmail.com>\n\n\t* test_slice.m: New file.\n\n2007-03-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (dist): Use ln, not $(LN_S).\n\n2007-02-26  From Michael Goffioul  <michael.goffioul@swing.be>\n\n\t* Makefile.in: Use $(LN_S) instead of ln or ln -s.\n\n2007-02-20  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (check): Use --norc instead of --no-site-file.\n\tFrom: Alex Zvoleff  <azvoleff@ucsd.edu>\n\n2007-02-19  John W. Eaton  <jwe@octave.org>\n\n\t* test_system.m: Handle confirm_recursive_rmdir as function\n\tinstead of built-in variable.\n\n2007-02-07  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m: Add plea for help writing tests.\n\n2007-01-11  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m: Also handle scripts directory in the build tree.\n\n\t* Makefile.in (OCTAVE_SCRIPT_PATH): Delete unused variable.\n\n2006-11-14  Luis F. Ortiz  <lortiz@interactivesupercomputing.com>\n\n\t* fntests.m: Include liboctave in the list of directories to test.\n\n2006-08-25  John W. Eaton  <jwe@octave.org>\n\n\t* test_io.m (testls): Allow for small variance in loaded values\n\tfor text data formats.  Use persistent local variables instead of\n\tresetting rand seed.\n\n2006-08-22  David Bateman  <dbateman@free.fr>\n\n\t* build_sparse_tests.sh: Don't force conversion to sparse boolean\n\treturn type for string mapper functions.\n\n2006-08-21  John W. Eaton  <jwe@octave.org>\n\n\t* test_io.m: Use isequal (a, b) instead of a != b.  Use isequal\n\tfor struct and cell tests instead of more complex constructs.\n\n2006-06-27  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (distclean): Also remove test_sparse.m.\n\n2006-06-07  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m: Keep track of files with tests and report total.\n\n2006-06-01  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m (print_test_file_name, print_pass_fail): New functions.\n\t(runtestdir, runtestscript): Use them.  Print info for each file\n\twith tests.  Print info about files without tests to log file.\n\t(run_test_dir): Rename from runtestdir.  Change all uses.\n\t(run_test_script): Rename from runtestscript.  Change all uses.\n\tHandle page_screen_output as a function instead of a built-in\n\tvariable.\n\n2006-05-04  John W. Eaton  <jwe@octave.org>\n\n\t* test_prefer.m: Adjust tests for eliminated built-in variables.\n\n2006-04-29  John W. Eaton  <jwe@octave.org>\n\n\t* Makefile.in (check): Use run-octave script.\n\n2006-04-28  John W. Eaton  <jwe@octave.org>\n\n\t* test_prefer.m: Adjust tests for new way of handling warning state.\n\t* build_sparse_tests.sh: Likewise.\n\n2006-04-11  John W. Eaton  <jwe@octave.org>\n\n\t* test_system.m, test_struct.m, test_string.m, test_quad.m,\n\ttest_number.m, test_nonlin.m, test_matrix.m, test_linalg.m,\n\ttest_io.m, test_diffeq.m, test_arith.m: Update for new usage\n\tmessage format.\n\n2006-04-03  David Bateman  <dbateman@free.fr>\n\n\t* test_number.m: Reverse sense of isscalar and isvector tests\n\tfor recent changes.\n\n2006-03-21  John W. Eaton  <jwe@octave.org>\n\n\t* test_system.m: Use cell arrays of character strings in fnmatch\n\ttests.\n\n2006-03-16  John W. Eaton  <jwe@octave.org>\n\n\t* test_system.m: End all *pwent tests with a call to endpwent.\n\tEnd all *grent tests with a call to endgrent.\n\n2006-03-14  John W. Eaton  <jwe@octave.org>\n\n\t* fntests.m: Prettier printing of output.\n\t* test_eval.m: Disable chatty tests.\n\n2006-03-08  David Bateman  <dbateman@free.fr>\n\n\t* test_system.m: Fix recursive rmdir test for recent change.\n\n2006-02-20  David Bateman  <dbateman@free.fr>\n\n\t* build_spase_tests.sh: Add tests for ldiv tests for rectangular\n\tdiagonal, permuted diagonal, triangular and permuted triangular\n\tmatrices.\n\n2006-02-09  David Bateman  <dbateman@free.fr>\n\n\t* build_sparse_tests.sh: Add tests for sparse QR solvers.\n\n2006-01-21  David Bateman  <dbateman@free.fr>\n\n\t* build_sparsetest.sh: Add new un-ordered indexing, assignment and\n\tdeletion tests.\n\n2006-01-13  Bill Denney  <bill@givebillmoney.com>\n\n\t* test_system.m: Use filesep instead of \"/\" where needed.\n\n2005-12-14  David Bateman  <dbateman@free.fr>\n\n\t* build_sparse_tests.sh: New script to build sparse matrix tests.\n\t* fntests.m: New script to run the octave test code, with \"make check\".\n\t* Makefile.in (DISTDIRS): Delete.\n\t(dist): Simplify.\n\t(OCTAVE_SCRIPT_PATH): Include . and $(srcdir).\n\t(check): Run tests with fntest.m instead of runtest.\n\t(test_sparse.m): New target.\n\t(clean): Remove fntests.log instead of octave.log and octave.sum.\n\n\t* tests/test_args.m, tests/test_infnan.m, tests/test_set.m,\n\ttests/test_arith.m, tests/test_io.m, tests/test_signal.m,\n\ttests/test_audio.m, tests/test_linalg.m, tests/test_sparse.m,\n\ttests/test_contin.m, tests/test_logical-wfi-f.m, tests/test_stats.m,\n\ttests/test_control.m, tests/test_logical-wfi-t.m, tests/test_string.m,\n\ttests/test_diffeq.m, tests/test_matrix.m, tests/test_struct.m,\n\ttests/test_error.m, tests/test_nonlin.m, tests/test_switch.m,\n\ttests/test_eval-catch.m, tests/test_number.m, tests/test_system.m,\n\ttests/test_eval.m, tests/test_optim.m, tests/test_transpose.m,\n\ttests/test_for.m, tests/test_plot.m, tests/test_try.m,\n\ttests/test_global.m, tests/test_poly.m, tests/test_unix.m,\n\ttests/test_if.m, tests/test_prefer.m, tests/test_unwind.m,\n\ttests/test_image.m, tests/test_quad.m, tests/test_while.m,\n\ttests/test_index-wfi-f.m, tests/test_recursion.m,\n\ttests/test_index-wfi-t.m, tests/test_return.m: Initial of conversion\n\tof DejaGnu tests to test/assert infrastructure.\n\n2005-05-11  John W. Eaton  <jwe@octave.org>\n\n\t* config/unix.exp: Start Octave with -H.\n\n2002-10-31  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/arith/prod-4.m, octave.test/arith/sum-4.m:\n\tCover more cases for empty matrices.\n\n2002-10-15  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* Makefile.in: Use @library_path_var@ instead of LD_LIBRARY_PATH.\n\n2002-09-27  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* qr-7.m: Remove randomness from complex matrix generator.\n\tIncrease tolerance on rosser matrix test.\n\n2002-09-26  Paul Kienzle  <pkienzle@users.sf.net>\n\n\t* octave.test/linalg/qr-7.m: Replace large random matrix tests\n\tof economy QR decomposition with small predictable tests.\n\tInclude numerically sensitive rosser matrix test.  Don't\n\treport the measured norms.\n\n2002-04-24  Bill Lash  <lash@tellabs.com>\n\n\t* test/octave.test/signal/signal.exp: Add unwrap test.\n\t* test/octave.test/signal/unwrap-1.m: New file.\n\n2002-04-24  David Billinghurst  <David.Billinghurst@riotinto.com.au>\n\n\t* octave.test/signal/signal.exp: Add tests for fft, ifft\n\tfft2, ifft2 and detrend.\n\t* octave.test/signal/detrend-1.m: New test.\n\t* octave.test/signal/detrend-2.m: New test.\n\t* octave.test/signal/detrend-3.m: New test.\n\t* octave.test/signal/fft-1.m: New test.\n\t* octave.test/signal/ifft-1.m: New test.\n\t* octave.test/signal/fft2-1.m: New test.\n\t* octave.test/signal/ifft2-1.m: New test.\n\n2002-04-22  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/diffeq/dassl-1.m (tol): Use relative tolerance for test.\n\t* octave.test/diffeq/dassl-2.m (tol): Likewise.\n\t* octave.test/diffeq/lsode-1.m (tol): Likewise.\n\t* octave.test/diffeq/lsode-2.m (tol): Likewise.\n\t* octave.test/diffeq/lsode-3.m (tol): Likewise.\n\n2002-04-12  Kienzle  <pkienzle@jazz.ncnr.nist.gov>\n\n\t* config/unix.exp: Allow running of individual tests with\n\t\"runtest *.exp\" from any of the directories under test/octave.test.\n\n2002-04-02  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/linalg/qr-7.m: New test.\n\tFrom Paul Kienzle <pkienzle@jazz.ncnr.nist.gov>.\n\n2001-04-24  Christoph Spiel  <cspiel@hammersmith-consulting.com>\n\n\t* Makefile.in (check): Allow user to specify which .exp file to run.\n\t* octave.test/try, octave.test/eval-catch: New directories and tests.\n\n2000-06-07  Ben Sapp  <bsapp@nua.lampf.lanl.gov>\n\n\t* octave.test/quad/quad-1.m: Use absolute value of difference\n\tfrom expected value when comparing with sqrt (eps).  Potential\n\tproblems like this were noticed by Przemek Klosowski\n\t<przemek@rrdjazz.nist.gov>.\n\t* octave.test/quad/quad-2.m: Likewise.\n\t* octave.test/arith/exp-1.m: Likewise.\n\t* octave.test/linalg/cond-1.m: Likewise.\n\t* octave.test/linalg/eig-1.m: Likewise.\n\t* octave.test/linalg/eig-2.m: Likewise.\n\t* octave.test/linalg/inv-1.m: Likewise.\n\t* octave.test/linalg/lu-2.m: Likewise.\n\t* octave.test/linalg/svd-2.m: Likewise.\n\t* octave.test/linalg/svd-10.m: Likewise.\n\n1999-10-29  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/system/mktime-1.m (t): Compare whole seconds only.\n\nFri Dec  4 20:55:47 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/system/clock-1.m: Use standard format specifiers %d\n\tand %H instead of %e and %k.\n\nFri Oct 23 15:53:01 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/arith/exp-5.m: New test.\n\n\t* octave.test/stats/mean-3.m: New version of mean accepts a second\n\toptional arg.\n\n\t* octave.test/system/date-1.m: Correct test for new Y2K-compliant\n\tdate function.\n\nWed May 27 00:38:27 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/diffeq/dassl-1.m, octave.test/diffeq/dassl-2.m,\n\toctave.test/diffeq/lsode-1.m: New tests, from David Billinghurst\n\t<David.Billinghurst@riotinto.com.au>.\n\n\t* octave.test/diffeq/lsode-2.m, octave.test/diffeq/lsode-3.m:\n \tNew tests, from Peter Hopfgartner <phopfgartner@memc.inet.it>.\n\nThu Apr 23 01:45:16 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in: If $(SHARED_LIBS), set LD_LIBRARY_PATH for running\n\tOctave before installation is complete.\n\nWed Apr 15 15:23:43 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/index/dfi-f/m-2.m, octave.test/index/dfi-f/index.exp:\n\tExpect this test to succed now.\n\nThu Mar  5 20:35:26 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/system/gmtime-1.m, octave.test/system/localtime-1.m:\n\tNot all systems have time zone info in the struct.\n\nMon Mar  2 14:36:50 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/io/binary-io-1.m (id): Use binary flag in fopen call.\n\nWed Apr  2 21:59:15 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/prefer/prefer.exp: Delete prefer-36 and prefer-37.\n\t* octave.test/prefer/prefer-36.m, octave.test/prefer/prefer-37.m:\n\tDelete test files.\n\nWed Mar 12 16:56:41 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (install-strip): New target.\n\nSat Mar  1 15:23:14 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.5 released.\n\nThu Feb 20 02:58:05 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.4 released.\n\nTue Feb 18 09:22:04 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.3 released.\n\nMon Jan 27 15:51:58 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.2 released.\n\nThu Jan 23 13:48:19 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* octave.test/unwind/unwind-2.m: Scripts now stop executing when\n\terrors are encountered.\n\n\t* octave.test/return/return.exp: Return at top level is no longer\n\tan error.\n\nTue Jan  7 00:16:23 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0.1 released.\n\nTue Dec 10 01:43:05 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 2.0 released.\n\nFri Dec  6 15:23:39 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.94.\n\nWed Nov 20 01:00:02 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.93.\n\nThu Nov 14 00:05:57 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.92\n\nThu Nov  7 12:43:03 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.91.\n\nWed Oct 30 17:19:12 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Version 1.90.\n\n\t* Makefile.in (DISTFILES): Add ChangeLog.\n\nFri Feb  9 21:40:49 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* Makefile.in (OCTAVE_SCRIPT_PATH): Add ../src directory (for .oct\n\tfiles) and current directory (why not?).\n\nSee ChangeLog.1 in the top level directory for earlier changes.\n"
  },
  {
    "path": "etc/RELEASE-CHECKLIST.wiki",
    "content": "= VERSION.1 Release Checklist =\n\n{{Note|'''Timeline''' (tentative)\n\n* YYYY-MM-DD 🚀 Release Kick-off ⚽ (default branch merged to stable)\n* YYYY-MM-DD 🛠️ 1st release candidate '''VERSION.0.90''' on https://alpha.gnu.org/gnu/octave/\n* YYYY-MM-DD 🏁 Final Release 🎉 '''VERSION.1.0''' on https://ftp.gnu.org/gnu/octave/ }}\n\nPlease use <code>&lt;strike&gt; &lt;/strike&gt;</code> to mark items below as done.\n\n== 🚀 Kick-off ⚽ ==\n\n=== ⚙️ Update stable and default branch to new version numbers ===\n\nCompletion Date:\n\n* Merge default onto stable to become the current stable release (see instructions \"Merging the default branch to stable before a release\" in <code>etc/HACKING.md</code>).\n* Bump version numbers in <code>configure.ac</code> on stable branch (see <code>etc/HACKING.md</code>).\n* Bump version numbers in <code>configure.ac</code> on default branch (see <code>etc/HACKING.md</code>).\n* Create new <code>etc/NEWS.VERSION+1.md</code> file on default branch by copying <code>etc/NEWS.VERSION.md</code> and then removing text so that it is a template file with headings only.\n\n=== ⚙️ Update gnulib to latest version ===\n\nCompletion Date:\n\n'''Must occur first''' as it could resolve existing, or create new, bug reports.  Run <code>./bootstrap</code> in the source tree after updating to the new gnulib version.\n\n=== ⚙️ Update Autoconf macros to latest version ===\n\nCompletion Date:\n\nThe following Autoconf macros are under version control in the <code>m4</code> directory.  The contents should be verified against the repository at https://github.com/autoconf-archive/autoconf-archive/tree/master/m4.\n\n    ax_blas.m4\n    ax_compare_version.m4\n    ax_cxx_compile_stdcxx.m4\n    ax_lapack.m4\n    ax_openmp.m4\n    ax_pthread.m4\n\nThe <code>pkg.m4</code> macro should be verified against the repository at https://github.com/pkgconf/pkgconf/blob/master/pkg.m4.\n\n=== 📢 Call for bug reports ===\n\nCompletion Date:\n\n* Put out a general call for reports on [https://octave.discourse.group/ Octave Discourse] for all outstanding, but unreported, known bugs.\n* Create Savannah <code>Release</code> tag <code>VERSION.0.90</code> on bug tracker for 1st release candidate.\n* Mark items that should be fixed for the release with this tag.\n* Update Savannah <code>Planned Release</code> and <code>Fixed Release</code> fields by adding <code>VERSION.1.0 (current stable)</code> and <code>VERSION+1.1.0 (current default)</code> tags to both.\n* Review bug overview at https://octave.space/savannah/.\n\n=== 📢 Update GUI translation files ===\n\nCompletion Date:\n\n* Call for updates ([https://octave.discourse.group/ Octave Discourse]) that might change GUI strings.\n* String freeze date:\n* Update language translation files (<code>*.ts</code>).  See instructions in <code>libgui/languages/build_ts/README.md</code>.\n* Create bug report on Savannah as a centralized location for uploading files and tracking status of translations.\n* Call for translations of GUI strings on [https://octave.discourse.group/c/maintainers/7 Octave Discourse Maintainers], CC-ing the translators (see [https://hg.savannah.gnu.org/hgweb/octave/file/tip/libgui/languages/translators list of translators]).\n* Collect translation files on Savannah bug report and push to Mercurial.\n\n=== ⚖️ GPL License activities ===\n\nCompletion Date:\n\n* Update copyright statements for all source controlled files.\n\n:Command to update copyright notifications\n:<code>hg locate | xargs sed -i 's/Copyright (C) \\([0-9][0-9][0-9][0-9]\\)-2023 The Octave Project Developers/Copyright (C) \\1-2024 The Octave Project Developers/; s/Copyright (C) 2023 The Octave Project Developers/Copyright (C) 2023-2024 The Octave Project Developers/'</code>\n\n:Command to check results before checking in\n:<code>hg diff | grep ^[-+][^-+] | sed 's/[0-9][0-9][0-9][0-9]-/YYYY-/' | sort -u</code>\n\n* Update dates in any other locations\n** MXE <code>README.html</code> file\n** <code>octave.texi, liboctave.texi, refcard.tex</code>\n\n* Add any new contributors to <code>doc/interpreter/contributors.in</code> who wish to be mentioned (don’t add them without permission).\n\n=== ✅ Style-check code base ===\n\nCompletion Date:\n\nThis will produce lots of whitespace changes, but no behavior changes.  '''Must occur after patches have been added''', since whitespace changes can prevent patches from applying.\n\n* [https://wiki.octave.org/Octave_style_guide m-file style check]\n* [https://wiki.octave.org/C%2B%2B_style_guide C++ style check]\n\n=== 📖 Review documentation ===\n\nCompletion Date:\n\n* Grammar check documentation (see <code>doc/interpreter/doccheck/README</code>).\n* Spell check documentation (<code>make spellcheck</code>).\n* Verify no functions missing from manual (<code>make doc/interpreter/undocumented_list</code>).\n* Verify deprecated functions removed from manual (<code>*.txi</code>) and from <code>@seealso</code> links.\n* Verify all formats (Info, HTML, PDF) build correctly.\n* Review <code>etc/NEWS.VERSION.md</code> for any features which should be announced.\n* Review <code>__unimplemented__.m</code> for the latest changes to [https://wiki.octave.org/Octave_Forge Octave Forge] packages and new Matlab functions.\n* Update <code>installer-files/README.html</code> in MXE Octave with version highlights.\n\n== 🔃 Repeat until all bugs are resolved ==\n\nCompletion Date of first iteration:\n\n=== ⚠️ Current state at Savannah ===\n\nBug overview at https://octave.space/savannah/.\n\n=== ✅ <code>make check</code> ===\n\n* Verify <code>make check</code> is passing on all [http://buildbot.octave.org:8010/#/waterfall buildbot combinations of OS and compilers] and [https://github.com/gnu-octave/octave/actions GitHub CI runners]. Also check [https://github.com/gnu-octave/octave-buildbot/actions test suite runs on “freshly brewed Octave for Windows”] (Kai’s buildbots on octave.space).\n* Use software tools to check quality of Octave code.\n** Check for memory leaks by configuring with <code>--enable-address-sanitizer-flags --disable-visibility-flags --disable-docs --disable-java</code> and compiling with <code>-g -O0</code> in <code>CFLAGS</code>, <code>CXXFLAGS</code>.\n** Check for bad memory accesses by configuring with <code>--disable-visibility-flags --disable-docs --disable-java</code> and compiling with <code>-g -O0 -fsanitize=undefined -fno-omit-frame-pointer</code> in <code>CFLAGS</code>, <code>CXXFLAGS</code>, and linking with <code>-fsanitize=undefined -fno-omit-frame-pointer</code> in <code>LDFLAGS</code>.\n** Update static code analysis results.\n*** For <code>clang</code>, do <code>scan-build make -j&lt;N&gt; all</code> and then <code>scan-view</code>.\n*** See [https://wiki.octave.org/PVS_static_analyzer_-_5.0_Release PVS static analyzer - 5.0 Release].\n** Use other tools such as <code>cppcheck</code>, etc.\n* Start discussion on [https://octave.discourse.group/c/maintainers/8 Octave Discourse Maintainers] about which failing tests that must be fixed and which can be declared '''WON’T FIX'''.\n\n=== 🛠️ Create new release candidate ===\n\n* Ensure correct version information (see \"Creating first release candidate for new MAJOR version\" and \"Release Numbering\" in <code>/etc/HACKING.md</code>).\n* Verify <code>make dist</code> works.\n* Verify <code>make distcheck</code> passes.\n* Make Windows binaries (see instructions \"Make Windows binaries\" in <code>etc/HACKING.md</code>).\n* Verify building from a tarball on Linux.  Verify that Windows binaries install and run.\n* Create a tag in the Mercurial repository on the changeset where the version number was updated (<code>hg tag rc-MAJOR-MINOR-PATCH</code>).\n* Sign tarballs and binaries with GPG key.\n** Use script <code>build-aux/make-gnu-fist-files</code> to simplify the procedure.\n* Upload release candidates to https://alpha.gnu.org/gnu/octave/.\n* Announce release candidate on [https://octave.discourse.group/ Octave Discourse] in both Maintainers and Help categories.\n\n== 🏁 Final Release 🎉 ==\n\n=== ⚙️ Update version information ===\n\nCompletion Date:\n\n* Ensure correct version information in <code>configure.ac</code> (see “Release Numbering” in <code>etc/HACKING.md</code>)\n** Update <code>AC_INIT</code> macro with version <code>MAJOR.MINOR.PATCH</code>.\n** Set <code>OCTAVE_MINOR_VERSION</code> to version <code>MINOR</code>.\n** Set <code>OCTAVE_PATCH_VERSION</code> to version <code>PATCH</code>.\n** Set <code>OCTAVE_RELEASE_DATE</code> to the current date.\n** Set the year in <code>OCTAVE_COPYRIGHT</code> to the current year.\n* Update <code>etc/NEWS.VERSION.md</code> (final release date in Summary header).\n* Update <code>CITATION</code> (version, year, URL) if not already done as part of &quot;GPL License activities&quot;.\n* Update <code>etc/icons/org.octave.Octave.appdata.xml</code> (Add <code><release></code> with release date and version number).\n\n=== 🛠️ Build, Verify, Sign, and Upload tarballs and Windows binaries ===\n\n* Make distribution tarballs and Windows binaries\n** Run <code>make dist</code> on Linux to produce distribution tarballs.\n** Make Windows binaries (see instructions \"Make Windows binaries\" in <code>etc/HACKING.md</code>).\n** Check [https://wiki.octave.org/Windows_Installer Windows Installer] (executable and zip formats) against false positive detection at [https://virustotal.com/ virustotal.com].\n* Verify building from a tarball on Linux.  Verify that Windows binaries install and run.\n* Create a tag in the Mercurial repository on the changeset where the version number was updated (<code>hg tag release-VERSION-1-0</code>).\n* Sign tarballs and binaries with GPG key.\n** Use script <code>build-aux/make-gnu-fist-files</code> to simplify the procedure.\n* Upload all tarballs to https://ftp.gnu.org/gnu/octave/.\n\n=== 🛠️ Update Octave web site, Octave wiki, and Savannah bug tracker ===\n\n* Update web site files: <code>NEWS-VERSION.html</code>, <code>index.in</code>, <code>news.in</code>, and <code>download.in</code>.\n:Steps documented in this [https://hg.octave.org/web-octave/rev/fe59d0118a2b changeset].\n* Upload documentation (manual HTML + PDF at <code>octave.org/doc</code>, version in <code>octave.org/.htaccess</code>, Doxygen at <code>octave.org/doxygen</code>)\n* Update Savannah bug tracker <code>Release</code> field to have new release number.\n* Update Savannah bug tracker: '''OPEN''' bugs marked as '''WON’T FIX''' should be marked as '''CONFIRMED''' (or more appropriate) for the final release.\n* Hide release candidate versions for <code>Release</code> field on Savannah.\n* Update Octave [[GNU_Octave_Wiki|wiki]]\n** Update https://wiki.octave.org/Release_History page.\n** Edit page [[Template:Release]] and update release version in code <pre><includeonly>MAJOR.MINOR.PATCH</includeonly></pre>\n** Edit page [[Template:Release Date]] and update month and day in code <pre><includeonly>MONTH DD, {{Release Year}}</includeonly></pre>\n** Edit page [[Template:Release Year]] and update year in code <pre><includeonly>YYYY</includeonly></pre>\n\n=== 📢 Announce final release ===\n\nCompletion Date:\n\n* Octave mailing-lists (yes, still) [mailto:help@octave.org help@octave.org] and [mailto:info-gnu@gnu.org info-gnu@gnu.org].\n* Octave web site (https://hg.octave.org/web-octave)\n\n=== ☑️ Post-Release ===\n\nCompletion Date:\n\n* Remove all deprecated functions scheduled for deletion on default branch.  These functions are tagged with <code>OCTAVE_DEPRECATED</code> in C++ or are m-files located in the directory <code>scripts/deprecated</code>.  Check file <code>etc/NEWS.VERSION-2.md</code> for list of features that have been deprecated.\n\n[[Category:Releases]]\n"
  },
  {
    "path": "etc/ROADMAP.md",
    "content": "Octave Roadmap (version 10 onwards)\n\nThis roadmap is intended to be a living document, and serves multiple purposes:\n* For developers to agree on activities and large-scale features,\n* To decide priorities,\n* To inform new contributors where they can contribute and feel ownership,\n* To allow easier parcelling of smaller activities into GSoC etc,\n* To be a transparent basis for any financial decisions to spend project money.\n\nThis document is different from a wishlist of features, such as those\npresent on the Octave wiki, in that this document lists names of people\nwilling to work on specific activities, whether they are contributors writing code\nthemselves, or existing Octave maintainers soliciting / reviewing / accepting code\nfrom new contributors.\n\n* For new contributors, this is a way to get your contribution\nreviewed and merged into the Octave codebase with more confidence, and a way\nto work with a more experienced Octave developer on a named activity so you too\ncan become an Octave developer over time.\n\n* For existing maintainers, this is a way to get new developers and\ncontributors in, which helps Octave development scale.\n\nIf you want to take ownership of some activity below, or create a new activity,\nplease edit the list as necessary, add your name, and post about it on Discourse.\nIf you can, please split up a large activity into smaller pieces that can then\nbe specifically written by new contributors, GSoC interns, etc.  The aim is to\nallow anyone to jump in to start contributing to a topic.\n\nThis roadmap process starts from Octave 10.  As has been the practice for many\nyears, a major version of Octave is released each year, and no single feature\nwill be \"required\" for any given version to be released, but it is good to have\ntarget versions for this list of features so that certain long-pending activities\nget more priority.\n\n- Better support for classdef. (LEAD?)\n  - Matlab-compatible classdef behavior.\n  - (Needs to be split up into smaller activities.)\n  - Target: Octave 10.\n\n- HDF5 compatibility with Matlab: (LEAD?)\n  - Deprecate Octave's native savefile formats in favor of Matlab-compatible HDF5.\n  - Decide how to handle backwards compatibility with older savefiles.\n  - Needs h5read/h5write as well as v7.3 MAT-file load/save support.\n  - Influenced by classdef decision above.\n  - Note: Examine Nelson's implementation.\n  - Target: Octave 10.\n\n- String class \"foo\" as distinct from array of characters 'foo'. (LEAD?)\n  - See https://octave.discourse.group/t/implementation-of-a-string-class/1089\n  - Depends on HDF5.\n  - Note: Examine Nelson's implementation.\n  - Target: Octave 10.\n\n- Dictionaries (aka associative arrays / hashmaps).  (LEAD? GUILLAUME?)\n  - See https://octave.discourse.group/t/adding-hashmaps-to-octave/3306\n  - Depends on HDF5 and string.\n  - Target: Octave 10.\n\n- Release bytecode interpreter.  (PETTER, JWE)\n  - First question: When Octave is released with the bytecode interpreter,\n    will it *replace* the tree-walker or will it sit alongside it? Once that\n    question is answered and agreed upon, these activities follow.\n  - Behavior compatibility with tree-walking interpreter.\n  - Code clarity and documentation.\n  - Style check.\n  - Performance experiments.\n  - Target: Octave 10\n\n- New command window widget.  (LEAD?)\n  - In Octave 9, this widget is available but experimental.  It can be invoked\n    with the runtime argument `--experimental-terminal-widget`. To make it\n    production quality (i.e., not experimental), the following features and\n    more need to be added:\n    - readline-like command line editing: recall history with up/down arrow keys\n    - capture output written to stdout/stderr\n    - a pager to enable `more on` to work\n    - search the contents of the command window\n    - clear the command window for `clc`\n  - Background: https://wiki.octave.org/GUI_terminal_widget\n  - Discussion: https://octave.discourse.group/t/new-command-window-widget/501\n  - Target: Octave 11\n\n- Graph theory routines (ARUN)\n  - These need a full overhaul and in some cases ground-up implementation.\n  - Matlab switched to graph objects some versions ago, as opposed to the\n    traditional approach (pre-2016) of directly manipulating adjacency matrices\n    and edge lists.\n  - Octave needs to implement / import many classical graph functions\n    (e.g., all-pairs shortest paths, transitive closure, betweenness centrality, etc).\n    These are not difficult to write, but have mostly been written by end users\n    for their own work, so the first effort is to converge on a usable function API.\n  - Possible dependency on HDF5 if graph classes are written as classdefs,\n    so graph objects will not be saved until then, but the rest of the\n    development can start and proceed.\n  - Target: Octave 11.\n\n- Argument blocks implementation.  (LEAD?)\n  - Some work has already been done, but needs to be completed.\n  - Target: Octave 11.\n\n- Assess OpenGL role and improvements.  (RIK?)\n  - May possibly need a paid consultant.\n  - Target: Octave 11\n\n- Replace GLPK with more performant solver for LP / MILP. (ARUN)\n  - Candidate: HiGHS.\n  - More generally, provide a usable API for optimization routines so that\n    users can drop in their own favorite solver.  The idea is that the user\n    should be able to switch backend solvers with just a simple change\n    like changing this:\n    `linprog (... , \"solver\", \"glpk\")`\n    to this:\n    `linprog (... , \"solver\", \"highs\")`\n    without changing any other user-written code.  Can this sort of thing\n    be done properly so that new solvers are easy to add to Octave by their\n    respective authors?\n  - Target: Octave 11\n"
  },
  {
    "path": "etc/gdbinit",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n############################################################\n## Disable the next line if you really need to see the\n## thread create/exit messages.\n\nset print thread-events off\n\n############################################################\n## Helpful macros for debugging Octave.\n\n## Programming Note: Don't strip the trailing space from the lines that\n## end with '\\ '.  GDB strips spaces from the ends of the lines, so\n## these are required to preserve the whitespace.\n\n############################################################\n## Display a dim-vector object.\n\ndefine display-dims\n  echo ndims: \\ \n  output $arg0.m_num_dims\n  echo \\ndims: \\ \n  output *$arg0.m_dims@$arg0.m_num_dims\n  echo \\n\n  dont-repeat\nend\n\ndocument display-dims\nUsage: display-dims DIM_VECTOR\nDisplay the contents of an Octave dimension vector.\nend\n\n############################################################\n## Display a dense array object.\n\ndefine display-dense-array\n  echo array object: \\ \n  output $arg0\n  echo \\ndimensions:\\n\n  display-dims $arg0.m_dimensions\n  echo \\nrep = \\ \n  output *$arg0.m_rep\n  echo \\nrep.data = \\ \n  output *$arg0.m_rep.m_data@$arg0.m_rep.m_len\n  echo \\nrep.slice_data = \\ \n  output *$arg0.m_slice_data@$arg0.m_slice_len\n  echo \\n\n  dont-repeat\nend\n\ndocument display-dense-array\nUsage: display-dense-array ARRAY\nDisplay the contents of an ordinary, i.e., dense Octave array.\n\nSee also [display-sparse-array] for showing the contents\nof sparse Octave arrays.\nend\n\n############################################################\n## Display a sparse array object.\n\ndefine display-sparse-array\n  echo sparse object: \\ \n  output $arg0\n  echo \\ndimensions:\\n \n  display-dims $arg0.m_dimensions\n  echo \\nrep = \\ \n  output *$arg0.m_rep\n  echo \\nrep.data = \\ \n  output *$arg0.m_rep.m_data@$arg0.m_rep.m_nzmax\n  echo \\nrep.ridx = \\ \n  output *$arg0.m_rep.m_ridx@$arg0.m_rep.m_nzmax\n  echo \\nrep.cidx = \\ \n  output *$arg0.m_rep.m_cidx@($arg0.m_rep.m_ncols+1)\n  echo \\n\n  dont-repeat\nend\n\ndocument display-sparse-array\nUsage: display-sparse-array SPARSE_ARRAY\nDisplay the contents of a sparse Octave array.\n\nSee also [display-dense-array] for showing the contents\nof ordinary Octave arrays.\nend\n\n############################################################\n## Display Octave debugging stack\n\ndefine show-octave-dbstack\n  call show_octave_dbstack ()\nend\n\ndocument show-octave-dbstack\nUsage: show-octave-dbstack\nDisplay the contents of the current Octave debugging stack.\n\nThis is the function stack that the Octave interpreter is processing\nand will be different from the C++ stack being debugged with gdb.\nend\n"
  },
  {
    "path": "etc/icons/org.octave.Octave.desktop.in",
    "content": "[Desktop Entry]\nName=GNU Octave\nComment=Interactive programming environment for numerical computations\nComment[ca]=Entorn de programació interactiva per a càlculs numèrics\nComment[de]=Interaktive Programmierumgebung für numerische Berechnungen\nComment[es]=Entorno de programación interactiva para cálculos numéricos\nComment[fr]=Environnement de programmation interactif pour le calcul numérique\nComment[hu]=Interaktív programozási környezet számszerű számításokhoz\nComment[it]=Ambiente di programmazione interattivo per il calcolo numerico\nComment[ja]=数値計算のための対話的なプログラミング環境\nComment[nl]=Interactieve programmeeromgeving voor numerieke berekeningen\nComment[pt]=Ambiente de programação interativo para computação numérica\nComment[zh]=数值计算交互式编程环境\nTryExec=%OCTAVE_PREFIX%/bin/octave\nExec=%OCTAVE_PREFIX%/bin/octave --gui %f\nIcon=octave\nTerminal=false\nType=Application\nCategories=Education;Science;Math;\nStartupNotify=false\nStartupWMClass=GNU Octave\nMimeType=text/x-octave;text/x-matlab;\nKeywords=science;math;matrix;numerical computation;plotting;\n"
  },
  {
    "path": "etc/icons/org.octave.Octave.metainfo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\nCopyright (C) 2013-2026 The Octave Project Developers\n\nSee the file COPYRIGHT.md in the top-level directory of this\ndistribution or <https://octave.org/copyright/>.\n\nThis file is part of Octave.\n\nOctave is free software: you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nOctave is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with Octave; see the file COPYING.  If not, see\n<https://www.gnu.org/licenses/>.\n\n-->\n<component type=\"desktop-application\">\n  <id>org.octave.Octave</id>\n  <metadata_license>FSFAP</metadata_license>\n  <project_license>GPL-3.0+</project_license>\n  <name>GNU Octave</name>\n  <summary>Interactive Scientific Programming</summary>\n  <summary xml:lang=\"ca\">Entorn de programació interactiva per a càlculs numèrics</summary>\n  <summary xml:lang=\"de\">Interaktives wissenschaftliches Programmieren</summary>\n  <summary xml:lang=\"es\">Entorno de programación interactiva para cálculos numéricos</summary>\n  <summary xml:lang=\"fr\">Environnement de programmation interactif pour le calcul numérique</summary>\n  <summary xml:lang=\"hu\">Interaktív programozási környezet számszerű számításokhoz</summary>\n  <summary xml:lang=\"it\">Ambiente di programmazione interattivo per il calcolo numerico</summary>\n  <summary xml:lang=\"ja\">数値計算のための対話的なプログラミング環境</summary>\n  <summary xml:lang=\"nl\">Interactieve programmeeromgeving voor numerieke berekeningen</summary>\n  <summary xml:lang=\"pt\">Ambiente de programação interativo para computação numérica</summary>\n  <summary xml:lang=\"zh\">数值计算交互式编程环境</summary>\n  <description>\n    <p>\n      GNU Octave is a high-level interpreted language, primarily intended for\n      numerical computations. It provides capabilities for the numerical\n      solution of linear and nonlinear problems, and for performing other\n      numerical experiments. It also provides extensive graphics capabilities\n      for data visualization and manipulation. Octave is normally used through\n      its interactive command line interface, but it can also be used to write\n      non-interactive programs. The Octave language is quite similar to\n      Matlab so that most programs are easily portable.\n    </p>\n    <p xml:lang=\"de\">\n      GNU Octave ist eine höhere, interpretierte Programmiersprache, die\n      hauptsächlich für numerische Berechnungen gedacht ist. Sie bietet\n      Funktionen für die numerische Lösung linearer und nichtlinearer Probleme\n      und für die Durchführung anderer numerischer Experimente. Darüber hinaus\n      bietet es umfangreiche Grafikfunktionen zur Datenvisualisierung und\n      -manipulation. Octave wird normalerweise mittels einer interaktiven\n      Befehlszeile verwendet, kann aber auch zum Schreiben nicht interaktiver\n      Programme verwendet werden. Die Octave-Programmiersprache ist sehr\n      ähnlich zu Matlab, so dass die meisten Programme leicht übertragbar sind.\n    </p>\n    <p xml:lang=\"es\">\n      GNU Octave es un lenguaje interpretado de alto nivel, destinado\n      principalmente a cálculos numéricos. Dispone capacidades para\n      la solución numérica de problemas lineales y no lineales, y para\n      realizar otros experimentos numéricos. También proporciona amplias\n      funcionalidades gráficas para la visualización y manipulación de datos.\n      Octave se usa normalmente a través de su interfaz de línea de comandos\n      interactiva, pero también se puede usar para escribir programas no\n      interactivos. El lenguaje Octave es muy similar a Matlab,\n      por lo que la mayoría de los programas son fáciles de portar.\n    </p>\n    <p xml:lang=\"fr\">\n      GNU Octave est un langage de programmation interprété, destiné\n      principalement au calcul numérique. Il fournit des fonctionnalités\n      pour la résolution de problèmes linéaires et non-linéaires, et pour toutes\n      sortes d'expériences numériques.  Il s'accompagne d'un système complet\n      de visualisation et de manipulation des données. Octave s’utilise\n      généralement via son environnement en lignes de commandes interactif,\n      mais il peut aussi être utilisé pour écrire des programmes non\n      interactifs. Le langage Octave est très similaire à Matlab de telle sorte\n      que les programmes Matlab sont très faciles à porter sous Octave.\n    </p>\n    <p xml:lang=\"hu\">\n      A GNU Octave egy magas szintű értelmezett nyelv, elsősorban numerikus\n      számításokhoz. Képességeket biztosít a lineáris és nemlineáris problémák\n      numerikus megoldására, valamint egyéb numerikus kísérletek elvégzésére.\n      Ezenkívül kiterjedt grafikus képességeket biztosít az adatok\n      megjelenítéséhez és manipulálásához. Az Octave-t általában az interaktív\n      parancssori felületen keresztül használják, de nem interaktív programok\n      írására is használható. Az Octave nyelv nagyon hasonló a Matlabhoz, így\n      a legtöbb program könnyen hordozható.\n    </p>\n    <p xml:lang=\"nl\">\n      GNU Octave is een hogere geïnterpreteerde taal, primair bedoeld voor\n      numerieke berekeningen. Het biedt mogelijkheden voor het numeriek\n      oplossen van lineaire en niet-lineaire problemen en andere numerieke\n      experimenten. Ook biedt het uitgebreide mogelijkheden for grafische\n      visualisatie en -manipulatie van data. Octave wordt meestal gebruikt\n      door middel van zijn interactieve opdrachtregelinterface (terminal)\n      maar kan ook gebruikt worden voor het schrijven van niet-interactieve\n      programma's. Octave's taal lijkt zeer veel op die van Matlab zodat de\n      meeste Matlabcode simpel te draaien is in Octave.\n    </p>\n    <p>\n      Octave has extensive tools for solving common numerical linear algebra\n      problems, finding the roots of nonlinear equations, integrating ordinary\n      functions, manipulating polynomials, and integrating ordinary\n      differential and differential-algebraic equations. It is easily\n      extensible and customizable via user-defined functions written in\n      Octave's own language, or using dynamically loaded modules written in\n      C++, C, Fortran, or other languages.\n    </p>\n    <p xml:lang=\"de\">\n      Octave verfügt über umfangreiche Werkzeuge zur Lösung gängiger\n      numerischer linearer Probleme der Algebra, zum Auffinden der Nullstellen\n      nichtlinearer Gleichungen, zur Integration gewöhnlicher Funktionen, zur\n      Manipulation von Polynomen und zur Integration gewöhnlicher\n      Differentialgleichungen und differential-algebraischer Gleichungen. Es\n      ist leicht erweiter- und anpassbar mittels benutzerdefinierter\n      Funktionen, die in Octaves eigener Programmiersprache geschrieben wurden,\n      oder über dynamisch geladene, in C++, C, Fortran oder anderen Sprachen\n      geschriebene Module.\n    </p>\n    <p xml:lang=\"es\">\n      Octave dispone de una amplia variedad de herramientas para resolver\n      problemas comunes de álgebra lineal numérica, encontrar\n      las raíces de ecuaciones no lineales, integrar funciones ordinarias,\n      manipular polinomios e integrar ecuaciones diferenciales ordinarias\n      y algebraicas diferenciales. Es fácilmente extensible y personalizable\n      a través de funciones definidas por el usuario escritas en el propio\n      lenguaje de Octave, o utilizando módulos cargados dinámicamente\n      escritos en C ++, C, Fortran u otros idiomas.\n    </p>\n    <p xml:lang=\"fr\">\n      Octave dispose de nombreux outils pour résoudre les problèmes classiques\n      d'algèbre linéaire, trouver les racines d'équations non-linéaires,\n      intégrer les fonctions ordinaires et les équations différentielles.\n      Il peut très facilement être étendu en définissant de nouvelles\n      fonctions écrites en langage Octave ou en utilisant des modules\n      chargés dynamiquement, écrits en C++, C, Fortran ou autres langages.\n    </p>\n    <p xml:lang=\"hu\">\n      Az Octave kiterjedt eszközökkel rendelkezik a gyakori numerikus lineáris\n      algebrai problémák megoldásához, a nemlineáris egyenletek gyökereinek\n      megkereséséhez, a hétköznapi függvények integrálásához, a polinomok\n      manipulálásához, valamint a közönséges differenciál- és differenciál-\n      algebrai egyenletek integrálásához. Könnyen bővíthető és testreszabható\n      a felhasználó által meghatározott, Octave saját nyelvén írt funkciókkal,\n      vagy dinamikusan betöltött modulokkal, C++, C, Fortran vagy más\n      nyelveken.\n    </p>\n    <p xml:lang=\"nl\">\n      Octave heeft een uitgebreide verzameling gereedschappen for het oplossen\n      van numerieke lineaire-algebra vraagstukken, vinden van wortels van\n      niet-lineaire vergelijkingen, integreren van gewone functies, manipuleren\n      van polynomen en integreren van gewone differentiaal- en algebrïsche\n      differentiaalvergelijkingen. Het is makkelijk uit te breiden en aan te\n      passen met behulp van door zelfgemaakte functies geschreven in Octave's\n      eigen taal en/of met dynamische te laden modules gechreven in C++, C,\n      Fortran of andere programmeertalen.\n    </p>\n  </description>\n\n  <screenshots>\n    <!--\n      From: https://www.freedesktop.org/software/appstream/docs/\n      All screenshots should have a 16:9 aspect ratio, and should have\n      a width that is no smaller than 620px. Screenshots should be in PNG\n      or JPEG format. PNG is the preferred format.\n    -->\n    <screenshot type=\"default\">\n      <caption>Graphical user interface</caption>\n      <image>https://octave.org/img/screenshot.png</image>\n    </screenshot>\n  </screenshots>\n\n  <branding>\n    <color type=\"primary\" scheme_preference=\"light\">#eef4f7</color>\n    <color type=\"primary\" scheme_preference=\"dark\">#1f2a33</color>\n  </branding>\n\n  <launchable type=\"desktop-id\">org.octave.Octave.desktop</launchable>\n  <provides>\n    <binary>octave</binary>\n  </provides>\n\n  <url type=\"homepage\">https://www.octave.org/</url>\n  <url type=\"bugtracker\">https://bugs.octave.org/</url>\n  <url type=\"faq\">https://wiki.octave.org/FAQ</url>\n  <url type=\"help\">https://octave.org/support</url>\n  <url type=\"donation\">https://www.octave.org/donate.html</url>\n  <url type=\"contact\">https://octave.org/support</url>\n  <url type=\"vcs-browser\">https://hg.savannah.gnu.org/hgweb/octave</url>\n  <url type=\"contribute\">https://octave.org/get-involved</url>\n  <update_contact>maintainers@octave.org</update_contact>\n  <project_group>GNU</project_group>\n  <developer_name>John W. Eaton and others</developer_name>\n  <developer id=\"org.octave\">\n    <name>John W. Eaton and others</name>\n  </developer>\n  <content_rating type=\"oars-1.0\"/>\n  <releases>\n    <release date=\"2026-02-18\" version=\"11.1.0\"/>\n    <release date=\"2025-09-23\" version=\"10.3.0\"/>\n    <release date=\"2025-05-29\" version=\"10.2.0\"/>\n    <release date=\"2025-03-25\" version=\"10.1.0\"/>\n    <release date=\"2025-02-05\" version=\"9.4.0\"/>\n    <release date=\"2024-12-12\" version=\"9.3.0\"/>\n    <release date=\"2024-06-01\" version=\"9.2.0\"/>\n    <release date=\"2024-03-14\" version=\"9.1.0\"/>\n    <release date=\"2023-11-05\" version=\"8.4.0\"/>\n    <release date=\"2023-08-08\" version=\"8.3.0\"/>\n    <release date=\"2023-04-13\" version=\"8.2.0\"/>\n    <release date=\"2023-03-07\" version=\"8.1.0\"/>\n    <release date=\"2022-11-02\" version=\"7.3.0\"/>\n    <release date=\"2022-07-28\" version=\"7.2.0\"/>\n    <release date=\"2022-04-06\" version=\"7.1.0\"/>\n    <release date=\"2021-10-30\" version=\"6.4.0\"/>\n    <release date=\"2021-07-11\" version=\"6.3.0\"/>\n    <release date=\"2021-02-19\" version=\"6.2.0\"/>\n    <release date=\"2020-11-26\" version=\"6.1.0\"/>\n    <release date=\"2020-01-31\" version=\"5.2.0\"/>\n    <release date=\"2019-02-23\" version=\"5.1.0\"/>\n    <release date=\"2018-08-09\" version=\"4.4.1\"/>\n    <release date=\"2018-04-30\" version=\"4.4.0\"/>\n    <release date=\"2018-03-13\" version=\"4.2.2\"/>\n  </releases>\n</component>\n"
  },
  {
    "path": "etc/module.mk",
    "content": "%canon_reldir%_EXTRA_DIST =\n\n%canon_reldir%_CLEANFILES =\n%canon_reldir%_DISTCLEANFILES =\n%canon_reldir%_MAINTAINERCLEANFILES =\n\n%canon_reldir%_EXTRA_DIST += \\\n  %reldir%/NEWS.1 \\\n  %reldir%/NEWS.2 \\\n  %reldir%/NEWS.3 \\\n  %reldir%/NEWS.4 \\\n  %reldir%/NEWS.5.md \\\n  %reldir%/NEWS.6.md \\\n  %reldir%/NEWS.7.md \\\n  %reldir%/NEWS.8.md \\\n  %reldir%/NEWS.9.md \\\n  %reldir%/NEWS.10.md \\\n  %reldir%/NEWS.11.md \\\n  %reldir%/NEWS.12.md \\\n  %reldir%/gdbinit\n\n%canon_reldir%_EXTRA_DIST += \\\n  %reldir%/OLD-ChangeLogs/ChangeLog \\\n  %reldir%/OLD-ChangeLogs/ChangeLog.1 \\\n  %reldir%/OLD-ChangeLogs/doc-ChangeLog \\\n  %reldir%/OLD-ChangeLogs/libcruft-ChangeLog \\\n  %reldir%/OLD-ChangeLogs/liboctave-ChangeLog \\\n  %reldir%/OLD-ChangeLogs/scripts-ChangeLog \\\n  %reldir%/OLD-ChangeLogs/src-ChangeLog \\\n  %reldir%/OLD-ChangeLogs/test-ChangeLog\n\nfallback_FONT_FILES = \\\n  %reldir%/fonts/FreeMono.otf \\\n  %reldir%/fonts/FreeMonoBold.otf \\\n  %reldir%/fonts/FreeMonoBoldOblique.otf \\\n  %reldir%/fonts/FreeMonoOblique.otf \\\n  %reldir%/fonts/FreeSans.otf \\\n  %reldir%/fonts/FreeSansBold.otf \\\n  %reldir%/fonts/FreeSansBoldOblique.otf \\\n  %reldir%/fonts/FreeSansOblique.otf\n\nif AMCOND_INSTALL_INTERNAL_FONT_FILES\noctfonts_DATA += \\\n  $(fallback_FONT_FILES)\nendif\n\n%canon_reldir%_EXTRA_DIST += \\\n  $(fallback_FONT_FILES)\n\nmetainfodir = $(datadir)/metainfo\n\nMETAINFO_XML_FILE := \\\n  %reldir%/icons/org.octave.Octave.metainfo.xml\n\nmetainfo_DATA = $(METAINFO_XML_FILE)\n\ndesktopdir = $(datadir)/applications\n\ndesktop_DATA = \\\n  %reldir%/icons/org.octave.Octave.desktop\n\nicon_IMAGE_FILES = \\\n  %reldir%/icons/octave-logo.svg \\\n  %reldir%/icons/octave-sombrero.png\n\nicon_PNG_SIZES = \\\n  1024 \\\n  512 \\\n  256 \\\n  128 \\\n  64 \\\n  48 \\\n  32 \\\n  24 \\\n  22 \\\n  16\n\nBUILT_PNG_ICONS = $(patsubst %,%reldir%/icons/octave-logo-%.png,$(icon_PNG_SIZES))\n\nWINDOWS_PNG_ICONS = $(filter %-16.png %-32.png %-48.png %-256.png,$(BUILT_PNG_ICONS))\n\nBUILT_ICONS = \\\n  $(BUILT_PNG_ICONS) \\\n  %reldir%/icons/octave-logo.ico\n\n%canon_reldir%_EXTRA_DIST += \\\n  $(BUILT_ICONS) \\\n  $(icon_IMAGE_FILES) \\\n  %reldir%/icons/octave-branding-samples.svg \\\n  %reldir%/icons/org.octave.Octave.metainfo.xml \\\n  %reldir%/icons/org.octave.Octave.desktop.in\n\nimage_DATA += \\\n  $(icon_IMAGE_FILES) \\\n  %reldir%/icons/octave-logo.ico\n\nDIRSTAMP_FILES += \\\n  %reldir%/icons/$(octave_dirstamp)\n\nall-local: all-icons\n\nall-icons: %reldir%/icons/org.octave.Octave.desktop $(BUILT_ICONS)\n\n%reldir%/icons/org.octave.Octave.desktop: %reldir%/icons/org.octave.Octave.desktop.in | %reldir%/icons/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(SED) < $< > $@-t \\\n\t  -e \"s|%OCTAVE_PREFIX%|${prefix}|\" && \\\n\tmv $@-t $@\n\n$(BUILT_PNG_ICONS): %reldir%/icons/octave-logo.svg | %reldir%/icons/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(RSVG_CONVERT) -w $(lastword $(subst -, ,$(patsubst %.png,%,$@))) -o $@-t $< && \\\n\tmv $@-t $@\n\n%reldir%/icons/octave-logo.ico: $(WINDOWS_PNG_ICONS) | %reldir%/icons/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(ICOTOOL) --create --raw  $(WINDOWS_PNG_ICONS) > $@-t && \\\n\tmv $@-t $@\n\n## Check that the release date and version number are in\n## $(METAINFO_XML_FILE), but only for actual releases, which means\n## we skip the test if the minor version number is 0 or the patch\n## version number is not 0.\n\nmetainfo-dist-hook:\n\t@test x\"$(DIST_IGNORE_METAINFO_VERSION)\" != x || \\\n\t test $(OCTAVE_MINOR_VERSION) -eq 0 || \\\n\t test $(OCTAVE_PATCH_VERSION) -ne 0 || \\\n\t grep \"<release *date=\\\"$(OCTAVE_RELEASE_DATE)\\\" *version=\\\"$(OCTAVE_VERSION)\\\"/>\" $(srcdir)/$(METAINFO_XML_FILE) > /dev/null || \\\n\t{ echo; \\\n\t  echo \"Packaging distribution requires the version number in the $(METAINFO_XML_FILE).\"; \\\n\t  echo \"Please update first or pass DIST_IGNORE_METAINFO_VERSION=1.\"; \\\n\t  echo \"Cannot package distribution!\"; \\\n\t  echo; exit 1; }\n.PHONY: metainfo-dist-hook\n\ninstall-data-local: install-icons\n\nuninstall-local: uninstall-icons\n\ninstall-icons:\n\tfor f in $(BUILT_PNG_ICONS); do \\\n\t  size=`echo $$f | $(SED) -n -e \"s/.*-\\([0-9]\\+\\)\\.png/\\1/p\"`; \\\n\t  if test -f $$f; then d=; else d=\"$(srcdir)/\"; fi; \\\n\t  $(MKDIR_P) $(DESTDIR)$(datadir)/icons/hicolor/$${size}x$${size}/apps; \\\n\t  $(INSTALL_DATA) \"$$d$$f\" $(DESTDIR)$(datadir)/icons/hicolor/$${size}x$${size}/apps/octave.png; \\\n\tdone\n\t$(MKDIR_P) $(DESTDIR)$(datadir)/icons/hicolor/scalable/apps\n\t$(INSTALL_DATA) $(srcdir)/%reldir%/icons/octave-logo.svg $(DESTDIR)$(datadir)/icons/hicolor/scalable/apps/octave.svg\n\nuninstall-icons:\n\tfor f in $(BUILT_PNG_ICONS); do \\\n\t  size=`echo $$f | $(SED) -n -e \"s/.*-\\([0-9]\\+\\)\\.png/\\1/p\"`; \\\n\t  rm -f $(DESTDIR)$(datadir)/icons/hicolor/$${size}x$${size}/apps/octave.png; \\\n\tdone\n\trm -f $(DESTDIR)$(datadir)/icons/hicolor/scalable/apps/octave.svg\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n\n%canon_reldir%_CLEANFILES += \\\n  %reldir%/icons/org.octave.Octave.desktop\n\n%canon_reldir%_MAINTAINERCLEANFILES += \\\n  $(BUILT_ICONS)\n\nCLEANFILES += $(%canon_reldir%_CLEANFILES)\nDISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)\nMAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)\n\netc-clean:\n\trm -f $(%canon_reldir%_CLEANFILES)\n\netc-distclean: etc-clean\n\trm -f $(%canon_reldir%_DISTCLEANFILES)\n\netc-maintainer-clean: etc-distclean\n\trm -f $(%canon_reldir%_MAINTAINERCLEANFILES)\n"
  },
  {
    "path": "examples/code/@FIRfilter/FIRfilter.m",
    "content": "## -*- texinfo -*-\n## @deftypefn  {} {} FIRfilter ()\n## @deftypefnx {} {} FIRfilter (@var{p})\n## Create a FIR filter with polynomial @var{p} as coefficient vector.\n## @end deftypefn\n\nfunction f = FIRfilter (p)\n\n  if (nargin == 0)\n    p = @polynomial ([1]);\n  elseif (! isa (p, \"polynomial\"))\n    error (\"@FIRfilter: P must be a polynomial object\");\n  endif\n\n  f.polynomial = [];\n  f = class (f, \"FIRfilter\", p);\n\nendfunction\n"
  },
  {
    "path": "examples/code/@FIRfilter/FIRfilter_aggregation.m",
    "content": "## -*- texinfo -*-\n## @deftypefn  {} {} FIRfilter ()\n## @deftypefnx {} {} FIRfilter (@var{p})\n## Create a FIR filter with polynomial @var{p} as coefficient vector.\n## @end deftypefn\n\nfunction f = FIRfilter (p)\n\n  if (nargin == 0)\n    f.polynomial = @polynomial ([1]);\n  else\n    if (! isa (p, \"polynomial\"))\n      error (\"@FIRfilter: P must be a polynomial object\");\n    endif\n\n    f.polynomial = p;\n  endif\n\n  f = class (f, \"FIRfilter\");\n\nendfunction\n"
  },
  {
    "path": "examples/code/@FIRfilter/display.m",
    "content": "function display (f)\n  printf (\"%s.polynomial\", inputname (1));\n  disp (f.polynomial);\nendfunction\n"
  },
  {
    "path": "examples/code/@FIRfilter/subsasgn.m",
    "content": "function fout = subsasgn (f, index, val)\n\n  switch (index.type)\n    case \".\"\n      fld = index.subs;\n      if (! strcmp (fld, \"polynomial\"))\n        error ('@FIRfilter/subsasgn: invalid property \"%s\"', fld);\n      endif\n      fout = f;\n      fout.polynomial = val;\n\n    otherwise\n      error (\"@FIRfilter/subsasgn: Invalid index type\")\n  endswitch\n\nendfunction\n"
  },
  {
    "path": "examples/code/@FIRfilter/subsref.m",
    "content": "function r = subsref (f, x)\n\n  switch (x.type)\n\n    case \"()\"\n      n = f.polynomial;\n      r = filter (n.poly, 1, x.subs{1});\n\n    case \".\"\n      fld = x.subs;\n      if (! strcmp (fld, \"polynomial\"))\n        error ('@FIRfilter/subsref: invalid property \"%s\"', fld);\n      endif\n      r = f.polynomial;\n\n    otherwise\n      error (\"@FIRfilter/subsref: invalid subscript type for FIR filter\");\n\n  endswitch\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/disp.m",
    "content": "function disp (p)\n\n  a = p.poly;\n  first = true;\n  for i = 1 : length (a);\n    if (a(i) != 0)\n      if (first)\n        first = false;\n      elseif (a(i) > 0 || isnan (a(i)))\n        printf (\" +\");\n      endif\n      if (a(i) < 0)\n        printf (\" -\");\n      endif\n      if (i == 1)\n        printf (\" %.5g\", abs (a(i)));\n      elseif (abs (a(i)) != 1)\n        printf (\" %.5g *\", abs (a(i)));\n      endif\n      if (i > 1)\n        printf (\" X\");\n      endif\n      if (i > 2)\n        printf (\" ^ %d\", i - 1);\n      endif\n    endif\n  endfor\n\n  if (first)\n    printf (\" 0\");\n  endif\n  printf (\"\\n\");\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/double.m",
    "content": "function a = double (p)\n  a = p.poly;\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/end.m",
    "content": "function r = end (obj, index_pos, num_indices)\n\n  if (num_indices != 1)\n    error (\"polynomial object may only have one index\");\n  endif\n\n  r = length (obj.poly) - 1;\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/get.m",
    "content": "function val = get (p, prop)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    val.poly = p.poly;\n  else\n    if (! ischar (prop))\n      error (\"@polynomial/get: PROPERTY must be a string\");\n    endif\n\n    switch (prop)\n      case \"poly\"\n        val = p.poly;\n      otherwise\n        error ('@polynomial/get: invalid PROPERTY \"%s\"', prop);\n    endswitch\n  endif\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/mtimes.m",
    "content": "function p = mtimes (a, b)\n  p = polynomial (conv (double (a), double (b)));\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/numel.m",
    "content": "function n = numel (obj, idx)\n  n = 1;  # always produce an array.\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/plot.m",
    "content": "function h = plot (p, varargin)\n\n  n = 128;\n  rmax = max (abs (roots (p.poly)));\n  x = [0 : (n - 1)] / (n - 1) * 2.2 * rmax - 1.1 * rmax;\n  if (nargout > 0)\n    h = plot (x, polyval (p, x), varargin{:});\n  else\n    plot (x, polyval (p, x), varargin{:});\n  endif\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/polynomial.m",
    "content": "## -*- texinfo -*-\n## @deftypefn  {} {} polynomial ()\n## @deftypefnx {} {} polynomial (@var{a})\n## Create a polynomial object representing the polynomial\n##\n## @example\n## a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n\n## @end example\n##\n## @noindent\n## from a vector of coefficients [a0 a1 a2 @dots{} an].\n## @end deftypefn\n\nfunction p = polynomial (a)\n\n  if (nargin == 0)\n    p.poly = 0;\n    p = class (p, \"polynomial\");\n  else\n    if (isa (a, \"polynomial\"))\n      p = a;\n    elseif (isreal (a) && isvector (a))\n      p.poly = a(:).';  # force row vector\n      p = class (p, \"polynomial\");\n    else\n      error (\"@polynomial: A must be a real vector\");\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/polynomial_superiorto.m",
    "content": "## -*- texinfo -*-\n## @deftypefn  {} {} polynomial ()\n## @deftypefnx {} {} polynomial (@var{a})\n## Create a polynomial object representing the polynomial\n##\n## @example\n## a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n\n## @end example\n##\n## @noindent\n## from a vector of coefficients [a0 a1 a2 @dots{} an].\n## @end deftypefn\n\nfunction p = polynomial (a)\n\n  if (nargin == 0)\n    p.poly = [0];\n    p = class (p, \"polynomial\");\n  else\n    if (strcmp (class (a), \"polynomial\"))\n      p = a;\n    elseif (isreal (a) && isvector (a))\n      p.poly = a(:).';  # force row vector\n      p = class (p, \"polynomial\");\n    else\n      error (\"@polynomial: A must be a real vector\");\n    endif\n  endif\n\n  superiorto (\"double\");\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/polyval.m",
    "content": "function [y, dy] = polyval (p, varargin)\n\n  if (nargout > 1)\n    [y, dy] = polyval (fliplr (p.poly), varargin{:});\n  else\n    y = polyval (fliplr (p.poly), varargin{:});\n  endif\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/roots.m",
    "content": "function r = roots (p)\n  r = roots (fliplr (p.poly));\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/set.m",
    "content": "function pout = set (p, varargin)\n\n  if (numel (varargin) < 2 || rem (numel (varargin), 2) != 0)\n    error (\"@polynomial/set: expecting PROPERTY/VALUE pairs\");\n  endif\n\n  pout = p;\n  while (numel (varargin) > 1)\n    prop = varargin{1};\n    val  = varargin{2};\n    varargin(1:2) = [];\n    if (! ischar (prop) || ! strcmp (prop, \"poly\"))\n      error (\"@polynomial/set: invalid PROPERTY for polynomial class\");\n    elseif (! (isreal (val) && isvector (val)))\n      error (\"@polynomial/set: VALUE must be a real vector\");\n    endif\n\n    pout.poly = val(:).';  # force row vector\n  endwhile\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/subsasgn.m",
    "content": "function p = subsasgn (p, s, val)\n\n  if (isempty (s))\n    error (\"@polynomial/subsasgn: needs index\");\n  endif\n\n  switch (s(1).type)\n\n    case \"{}\"\n      ind = s(1).subs;\n      if (numel (ind) != 1)\n        error (\"@polynomial/subsasgn: need exactly one index\");\n      elseif (numel (s) != 1)\n        error (\"@polynomial/subsasgn: chained subscripts not allowed for {}\");\n      endif\n\n      if (isnumeric (ind{1}))\n        p.poly(ind{1}+1) = val;\n      else\n        p.poly(ind{1}) = val;\n      endif\n\n    case \".\"\n      fld = s(1).subs;\n      if (! strcmp (fld, \"poly\"))\n        error ('@polynomial/subsasgn: invalid property \"%s\"', fld);\n      endif\n      if (numel (s) == 1)\n        p.poly = val;\n      else\n        p.poly = subsasgn (p.poly, s(2:end), val);\n      endif\n\n    otherwise\n      error (\"@polynomial/subsasgn: invalid subscript type\");\n\n  endswitch\n\nendfunction\n"
  },
  {
    "path": "examples/code/@polynomial/subsref.m",
    "content": "function r = subsref (p, s)\n\n  if (isempty (s))\n    error (\"@polynomial/subsref: missing index\");\n  endif\n\n  switch (s(1).type)\n\n    case \"()\"\n      idx = s(1).subs;\n      if (numel (idx) != 1)\n        error (\"@polynomial/subsref: need exactly one index\");\n      endif\n      r = polyval (fliplr (p.poly), idx{1});\n\n    case \"{}\"\n      idx = s(1).subs;\n      if (numel (idx) != 1)\n        error (\"@polynomial/subsref: need exactly one index\");\n      endif\n\n      if (isnumeric (idx{1}))\n        r = p.poly(idx{1}+1);\n      else\n        r = p.poly(idx{1});\n      endif\n\n    case \".\"\n      fld = s.subs;\n      if (! strcmp (fld, \"poly\"))\n        error ('@polynomial/subsref: invalid property \"%s\"', fld);\n      endif\n      r = p.poly;\n\n    otherwise\n      error (\"@polynomial/subsref: invalid subscript type\");\n\n  endswitch\n\n  if (numel (s) > 1)\n    r = subsref (r, s(2:end));\n  endif\n\nendfunction\n"
  },
  {
    "path": "examples/code/COPYING",
    "content": "Copyright notices are intentionally omitted from the files in the\nexamples directory.  We don't want copyright notices cluttering the\nmanual.\n"
  },
  {
    "path": "examples/code/addtwomatrices.cc",
    "content": "#include <octave/oct.h>\n\nDEFUN_DLD (addtwomatrices, args, , \"Add A to B\")\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  NDArray A = args(0).array_value ();\n  NDArray B = args(1).array_value ();\n\n  return octave_value (A + B);\n}\n"
  },
  {
    "path": "examples/code/celldemo.cc",
    "content": "#include <octave/oct.h>\n#include <octave/Cell.h>\n\nDEFUN_DLD (celldemo, args, , \"Cell Demo\")\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  Cell c = args(0).cell_value ();\n\n  octave_value_list retval;\n  retval.resize (c.numel ());    // faster code by pre-declaring size\n\n  for (octave_idx_type i = 0; i < c.numel (); i++)\n    {\n      retval(i) = c(i);          // using operator syntax\n      //retval(i) = c.elem (i);  // using method syntax\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "examples/code/embedded.cc",
    "content": "#include <iostream>\n#include <octave/oct.h>\n#include <octave/octave.h>\n#include <octave/parse.h>\n#include <octave/interpreter.h>\n\nint\nmain ()\n{\n  // Create interpreter.\n\n  octave::interpreter interpreter;\n\n  try\n    {\n      // Inhibit reading history file by calling\n      //\n      //   interpreter.initialize_history (false);\n\n      // Set custom load path here if you wish by calling\n      //\n      //   interpreter.initialize_load_path (false);\n\n      // Perform final initialization of interpreter, including\n      // executing commands from startup files by calling\n      //\n      //   interpreter.initialize ();\n      //\n      //   if (! interpreter.is_initialized ())\n      //     {\n      //       std::cerr << \"Octave interpreter initialization failed!\"\n      //                 << std::endl;\n      //       exit (1);\n      //     }\n      //\n      // You may skip this step if you don't need to do anything\n      // between reading the startup files and telling the interpreter\n      // that you are ready to execute commands.\n\n      // Tell the interpreter that we're ready to execute commands:\n\n      int status = interpreter.execute ();\n\n      if (status != 0)\n        {\n          std::cerr << \"creating embedded Octave interpreter failed!\"\n                    << std::endl;\n          return status;\n        }\n\n      octave_idx_type n = 2;\n      octave_value_list in;\n\n      for (octave_idx_type i = 0; i < n; i++)\n        in(i) = octave_value (5 * (i + 2));\n\n      octave_value_list out = octave::feval (\"gcd\", in, 1);\n\n      if (out.length () > 0)\n        std::cout << \"GCD of [\"\n                  << in(0).int_value ()\n                  << \", \"\n                  << in(1).int_value ()\n                  << \"] is \" << out(0).int_value ()\n                  << std::endl;\n      else\n        std::cout << \"invalid\\n\";\n    }\n  catch (const octave::exit_exception& ex)\n    {\n      std::cerr << \"Octave interpreter exited with status = \"\n                << ex.exit_status () << std::endl;\n    }\n  catch (const octave::execution_exception&)\n    {\n      std::cerr << \"error encountered in Octave evaluator!\" << std::endl;\n    }\n\n  return 0;\n}\n"
  },
  {
    "path": "examples/code/fortrandemo.cc",
    "content": "#include <octave/oct.h>\n#include <octave/f77-fcn.h>\n\nextern \"C\"\n{\n  F77_RET_T\n  F77_FUNC (fortransub, FORTRANSUB)\n    (const F77_INT&, F77_DBLE*, F77_CHAR_ARG_DECL F77_CHAR_ARG_LEN_DECL);\n}\n\nDEFUN_DLD (fortrandemo, args, , \"Fortran Demo\")\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  NDArray a = args(0).array_value ();\n\n  double *av = a.rwdata ();\n  octave_idx_type na = a.numel ();\n\n  OCTAVE_LOCAL_BUFFER (char, ctmp, 128);\n\n  F77_FUNC (fortransub, FORTRANSUB)\n            (na, av, ctmp F77_CHAR_ARG_LEN (128));\n\n  return ovl (a, std::string (ctmp));\n}\n"
  },
  {
    "path": "examples/code/fortransub.f",
    "content": "      subroutine fortransub (n, a, s)\n      implicit none\n      character*(*) s\n      real*8 a(*)\n      integer*4 i, n, ioerr\n      do i = 1, n\n        if (a(i) .eq. 0d0) then\n          call xstopx ('fortransub: divide by zero')\n        else\n          a(i) = 1d0 / a(i)\n        endif\n      enddo\n      write (unit = s, fmt = '(a,i3,a,a)', iostat = ioerr)\n     $       'There are ', n,\n     $       ' values in the input vector', char(0)\n      if (ioerr .ne. 0) then\n        call xstopx ('fortransub: error writing string')\n      endif\n      return\n      end\n"
  },
  {
    "path": "examples/code/funcdemo.cc",
    "content": "#include <octave/oct.h>\n#include <octave/parse.h>\n\nDEFMETHOD_DLD (funcdemo, interp, args, nargout, \"Function Demo\")\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  octave_value_list newargs;\n\n  for (octave_idx_type i = nargin - 1; i > 0; i--)\n    newargs(i-1) = args(i);\n\n  octave_value_list retval;\n\n  if (args(0).is_function_handle () || args(0).is_inline_function ()\n      || args(0).is_string ())\n    retval = interp.feval (args(0), newargs, nargout);\n  else\n    error (\"funcdemo: INPUT must be string, inline, or function handle\");\n\n  return retval;\n}\n"
  },
  {
    "path": "examples/code/globaldemo.cc",
    "content": "#include <octave/oct.h>\n#include <octave/interpreter.h>\n\nDEFMETHOD_DLD (globaldemo, interp, args, , \"Global Demo\")\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value retval;\n\n  std::string s = args(0).string_value ();\n\n  octave::symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value tmp = symtab.global_varval (s);\n\n  if (tmp.is_defined ())\n    retval = tmp;\n  else\n    retval = \"Global variable not found\";\n\n  symtab.global_assign (\"a\", 42.0);\n\n  return retval;\n}\n"
  },
  {
    "path": "examples/code/helloworld.cc",
    "content": "#include <octave/oct.h>\n\nDEFUN_DLD (helloworld, args, nargout,\n           \"Hello World Help String\")\n{\n  octave_stdout << \"Hello World has \"\n                << args.length () << \" input arguments and \"\n                << nargout << \" output arguments.\\n\";\n\n  // Return empty matrices for any outputs\n  octave_value_list retval (nargout);\n  for (int i = 0; i < nargout; i++)\n    retval(i) = octave_value (Matrix ());\n\n  return retval;\n}\n"
  },
  {
    "path": "examples/code/make_int.cc",
    "content": "#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n#include <ostream>\n#include <string>\n\n#include <octave/lo-utils.h>\n#include <octave/mappers.h>\n#include <octave/mx-base.h>\n#include <octave/str-vec.h>\n\n#include <octave/defun-dld.h>\n#include <octave/interpreter.h>\n#include <octave/ops.h>\n#include <octave/ov-base.h>\n#include <octave/ov-scalar.h>\n#include <octave/ov-typeinfo.h>\n#include <octave/ov.h>\n#include <octave/ovl.h>\n#include <octave/pager.h>\n#include <octave/pr-output.h>\n#include <octave/variables.h>\n\n\n// Integer values.\n\n// Derive from octave_base_dld_value instead of octave_base_value\n// so that octave_integer values created by that dynamically loaded\n// make_int.oct file will be tracked automatically and the .oct file\n// will not be closed until all functions and values that it creates are\n// deleted.\n\nclass\noctave_integer : public octave_base_dld_value\n{\npublic:\n\n  octave_integer ()\n    : octave_base_dld_value (), scalar (0) { }\n\n  octave_integer (int i)\n    : octave_base_dld_value (), scalar (i) { }\n\n  octave_integer (const octave_integer& s)\n    : octave_base_dld_value (), scalar (s.scalar) { }\n\n  ~octave_integer () = default;\n\n  octave_base_value * clone () { return new octave_integer (*this); }\n\n  octave::idx_vector index_vector (bool) const\n  { return octave::idx_vector ((double) scalar); }\n\n  int rows () const { return 1; }\n  int columns () const { return 1; }\n\n  bool is_constant () const { return true; }\n\n  bool is_defined () const { return true; }\n  bool is_real_scalar () const { return true; }\n\n  octave_value all () const { return (double) (scalar != 0); }\n  octave_value any () const { return (double) (scalar != 0); }\n\n  bool is_real_type () const { return true; }\n  bool is_scalar_type () const { return true; }\n  bool isnumeric () const { return true; }\n\n  bool valid_as_scalar_index () const\n  { return scalar == 1; }\n\n  bool valid_as_zero_index () const\n  { return scalar == 0; }\n\n  bool is_true () const { return (scalar != 0); }\n\n  double double_value (bool = false) const { return (double) scalar; }\n\n  int integer_value (bool = false) const { return scalar; }\n\n  Matrix matrix_value (bool = false) const { return Matrix (1, 1, scalar); }\n\n  Complex complex_value (bool = false) const { return scalar; }\n\n  ComplexMatrix complex_matrix_value (bool = false) const\n  { return ComplexMatrix (1, 1, Complex (scalar)); }\n\n  octave_value gnot () const { return octave_value ((double) ! scalar); }\n\n  octave_value uminus () const { return new octave_integer (- scalar); }\n\n  octave_value transpose () const { return new octave_integer (scalar); }\n\n  octave_value hermitian () const { return new octave_integer (scalar); }\n\n  void increment () { ++scalar; }\n\n  void decrement () { --scalar; }\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n\nprivate:\n\n  int scalar;\n\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA\n};\n\nvoid\noctave_integer::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  os << scalar;\n  newline (os);\n}\n\n#if defined (DEFUNOP_OP)\n#undef DEFUNOP_OP\n#endif\n\n#define DEFUNOP_OP(name, t, op)                                         \\\n  static octave_value                                                   \\\n  CONCAT2(oct_unop_, name) (const octave_base_value& a)                 \\\n  {                                                                     \\\n    const octave_ ## t& v = dynamic_cast<const octave_ ## t&> (a);      \\\n    return octave_value (new octave_integer (op v.t ## _value ()));     \\\n  }\n\nDEFUNOP_OP (gnot, integer, !)\nDEFUNOP_OP (uminus, integer, -)\nDEFUNOP_OP (transpose, integer, /* no-op */)\nDEFUNOP_OP (hermitian, integer, /* no-op */)\n\nDEFNCUNOP_METHOD (incr, integer, increment)\nDEFNCUNOP_METHOD (decr, integer, decrement)\n\n#if defined (DEFBINOP_OP)\n#undef DEFBINOP_OP\n#endif\n\n#define DEFBINOP_OP(name, t1, t2, op)                                   \\\n  static octave_value                                                   \\\n  CONCAT2(oct_binop_, name) (const octave_base_value& a1,               \\\n                             const octave_base_value& a2)               \\\n  {                                                                     \\\n    const octave_ ## t1& v1 = dynamic_cast<const octave_ ## t1&> (a1);  \\\n    const octave_ ## t2& v2 = dynamic_cast<const octave_ ## t2&> (a2);  \\\n    return octave_value                                                 \\\n      (new octave_integer (v1.t1 ## _value () op v2.t2 ## _value ()));  \\\n  }\n\n// integer by integer ops.\n\nDEFBINOP_OP (add, integer, integer, +)\nDEFBINOP_OP (sub, integer, integer, -)\nDEFBINOP_OP (mul, integer, integer, *)\n\nDEFBINOP (div, integer, integer)\n{\n  const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);\n  const octave_integer& v2 = dynamic_cast<const octave_integer&> (a2);\n\n  return new octave_integer (v1.integer_value () / v2.integer_value ());\n}\n\n\nDEFBINOP (i_s_div, integer, scalar)\n{\n  const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);\n  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);\n\n  return new octave_scalar (v1.double_value () / v2.double_value ());\n}\n\nDEFBINOP (ldiv, integer, integer)\n{\n  const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);\n  const octave_integer& v2 = dynamic_cast<const octave_integer&> (a2);\n\n  return new octave_integer (v2.integer_value () / v1.integer_value ());\n}\n\nDEFBINOP_OP (lt, integer, integer, <)\nDEFBINOP_OP (le, integer, integer, <=)\nDEFBINOP_OP (eq, integer, integer, ==)\nDEFBINOP_OP (ge, integer, integer, >=)\nDEFBINOP_OP (gt, integer, integer, >)\nDEFBINOP_OP (ne, integer, integer, !=)\n\nDEFBINOP_OP (el_mul, integer, integer, !=)\n\nDEFBINOP (el_div, integer, integer)\n{\n  const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);\n  const octave_integer& v2 = dynamic_cast<const octave_integer&> (a2);\n\n  return new octave_integer (v1.integer_value () / v2.integer_value ());\n}\n\nDEFBINOP (el_ldiv, integer, integer)\n{\n  const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);\n  const octave_integer& v2 = dynamic_cast<const octave_integer&> (a2);\n\n  return new octave_integer (v2.integer_value () / v1.integer_value ());\n}\n\nDEFBINOP_OP (el_and, integer, integer, &&)\nDEFBINOP_OP (el_or, integer, integer, ||)\n\nDEFMETHOD_DLD (make_int, interp, args, ,\n               \"int_val = make_int (val)\\n\\\n\\n\\\nCreates an integer variable from VAL.\")\n{\n  static bool type_loaded = false;\n\n  if (! type_loaded)\n    {\n      octave_integer::register_type ();\n\n      octave_stdout << \"installing integer type at type-id = \"\n                    << octave_integer::static_type_id () << \"\\n\";\n\n      octave::type_info& ti = interp.get_type_info ();\n\n      INSTALL_UNOP_TI (ti, op_not, octave_integer, gnot);\n      INSTALL_UNOP_TI (ti, op_uminus, octave_integer, uminus);\n      INSTALL_UNOP_TI (ti, op_transpose, octave_integer, transpose);\n      INSTALL_UNOP_TI (ti, op_hermitian, octave_integer, hermitian);\n\n      INSTALL_NCUNOP_TI (ti, op_incr, octave_integer, incr);\n      INSTALL_NCUNOP_TI (ti, op_decr, octave_integer, decr);\n\n      INSTALL_BINOP_TI (ti, op_add, octave_integer, octave_integer, add);\n      INSTALL_BINOP_TI (ti, op_sub, octave_integer, octave_integer, sub);\n      INSTALL_BINOP_TI (ti, op_mul, octave_integer, octave_integer, mul);\n      INSTALL_BINOP_TI (ti, op_div, octave_integer, octave_integer, div);\n      INSTALL_BINOP_TI (ti, op_ldiv, octave_integer, octave_integer, ldiv);\n      INSTALL_BINOP_TI (ti, op_lt, octave_integer, octave_integer, lt);\n      INSTALL_BINOP_TI (ti, op_le, octave_integer, octave_integer, le);\n      INSTALL_BINOP_TI (ti, op_eq, octave_integer, octave_integer, eq);\n      INSTALL_BINOP_TI (ti, op_ge, octave_integer, octave_integer, ge);\n      INSTALL_BINOP_TI (ti, op_gt, octave_integer, octave_integer, gt);\n      INSTALL_BINOP_TI (ti, op_ne, octave_integer, octave_integer, ne);\n      INSTALL_BINOP_TI (ti, op_el_mul, octave_integer, octave_integer, el_mul);\n      INSTALL_BINOP_TI (ti, op_el_div, octave_integer, octave_integer, el_div);\n      INSTALL_BINOP_TI (ti, op_el_ldiv, octave_integer, octave_integer, el_ldiv);\n      INSTALL_BINOP_TI (ti, op_el_and, octave_integer, octave_integer, el_and);\n      INSTALL_BINOP_TI (ti, op_el_or, octave_integer, octave_integer, el_or);\n\n      INSTALL_BINOP_TI (ti, op_div, octave_integer, octave_scalar, i_s_div);\n\n      type_loaded = true;\n    }\n\n  octave_value retval;\n\n  if (args.length () == 1)\n    {\n      double d = args(0).double_value ();\n\n      retval = octave_value (new octave_integer (octave::math::nint (d)));\n    }\n  else\n    print_usage ();\n\n  return retval;\n}\n\nDEFUN_DLD (doit, args, ,\n           \"doit (I)\")\n{\n  octave_value_list retval;\n\n  if (args.length () != 1)\n    {\n      print_usage ();\n      return retval;\n    }\n\n  if (args(0).type_id () == octave_integer::static_type_id ())\n    {\n      // At this point, we know we have a handle for an octave_integer\n      // object, so we can peek at the representation and extract the\n      // data.\n\n      const octave_base_value& rep = args(0).get_rep ();\n\n      int my_value = ((const octave_integer&) rep) . integer_value ();\n\n      message (\"doit\", \"your lucky number is: %d\", my_value);\n    }\n  else\n    err_wrong_type_arg (\"doit\", args(0));\n\n  return retval;\n}\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_integer, \"integer\", \"integer\");\n"
  },
  {
    "path": "examples/code/mex_celldemo.c",
    "content": "#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  mwSize n;\n  mwIndex i;\n\n  if (nrhs != 1 || ! mxIsCell (prhs[0]))\n    mexErrMsgTxt (\"ARG1 must be a cell\");\n\n  n = mxGetNumberOfElements (prhs[0]);\n  n = (n > nlhs ? nlhs : n);\n\n  for (i = 0; i < n; i++)\n    plhs[i] = mxDuplicateArray (mxGetCell (prhs[0], i));\n}\n"
  },
  {
    "path": "examples/code/mex_demo.c",
    "content": "// mex_demo.c -- example of a dynamically linked function for Octave.\n\n// To compile this file, type the command\n//\n//   mkoctfile --mex mex_demo.c\n//\n// from within Octave or from the shell prompt.  This will create a file\n// called mex_demo.mex that can be loaded by Octave.  To test the mex_demo.mex\n// file, start Octave and type the command\n//\n// d = mex_demo (\"easy as\", 1, 2, 3)\n//\n// at the Octave prompt.  Octave should respond by printing\n//\n//   Hello, world!\n//   I have 4 inputs and 1 output\n//   d =  1.2346\n\n// Additional samples of code are in the examples directory of the Octave\n// distribution.  See also the chapter External Code Interface in the\n// documentation.\n\n#include \"mex.h\"\n\n// Every user function should include \"mex.h\" which imports the basic set of\n// function prototypes necessary for dynamically linked functions.  In\n// particular, it will declare mexFunction which is used by every function\n// which will be visible to Octave.  A mexFunction is visible in Octave under\n// the name of the source code file without the extension.\n\n// The four arguments to mexFunction are:\n// 1) The number of return arguments (# of left-hand side args).\n// 2) An array of pointers to return arguments.\n// 3) The number of input arguments (# of right-hand side args).\n// 4) An array of pointers to input arguments.\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  mexPrintf (\"Hello, World!\\n\");\n\n  mexPrintf (\"I have %d inputs and %d outputs\\n\", nrhs, nlhs);\n\n  /* Demonstrate returning a matrix with a double value */\n  mxArray *v = mxCreateDoubleMatrix (1, 1, mxREAL);\n  double *data = mxGetPr (v);\n  *data = 1.23456789;\n  plhs[0] = v;\n\n  /* Return empty matrices for any other outputs */\n  int i;\n  for (i = 1; i < nlhs; i++)\n    plhs[i] = mxCreateDoubleMatrix (0, 0, mxREAL);\n}\n"
  },
  {
    "path": "examples/code/mex_fevaldemo.c",
    "content": "#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  char *str;\n\n  mexPrintf (\"Starting file mex_fevaldemo.mex\\n\");\n\n  mexPrintf (\"I have %d inputs and %d outputs\\n\", nrhs, nlhs);\n\n  if (nrhs < 1 || ! mxIsChar (prhs[0]))\n    mexErrMsgTxt (\"ARG1 must be a function name\");\n\n  str = mxArrayToString (prhs[0]);\n\n  mexPrintf (\"I'm going to call the function %s\\n\", str);\n\n  if (nlhs == 0)\n    nlhs = 1;  // Octave's automatic 'ans' variable\n\n  /* Cast prhs just to get rid of 'const' qualifier and stop compile warning */\n  mexCallMATLAB (nlhs, plhs, nrhs-1, (mxArray**)prhs+1, str);\n\n  mxFree (str);\n}\n"
  },
  {
    "path": "examples/code/mex_fevalf.f",
    "content": "      subroutine mexFunction (nlhs, plhs, nrhs, prhs)\n\n      implicit none\n\n      integer*4 nlhs, nrhs\n\n* The following will need to be integer*8 on 64-bit systems, otherwise\n* these variables won't be large enough to hold pointers...\n      integer*4 plhs(*), prhs(*)\n\n      integer*4 mxIsString, mxGetString, mxGetN, mexCallMATLAB\n      integer*4 status, len\n      character*100 str\n\n      call mexPrintf ('Hello, World!')\n\n      if (nrhs .lt. 1 .or. mxIsString (prhs(1)) .ne. 1) then\n        call mexErrMsgTxt ('function name expected')\n      endif\n\n      len = mxGetN (prhs(1))\n\n      status = mxGetString (prhs(1), str, 100)\n\n      call mexPrintf ('FORTRAN will call the interpreter now')\n\n      status = mexCallMATLAB (nlhs, plhs, nrhs-1, prhs(2), str(1:len))\n\n      return\n      end\n"
  },
  {
    "path": "examples/code/mex_funcdemo.c",
    "content": "#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  const char *nm;\n\n  nm = mexFunctionName ();\n  mexPrintf (\"You called function: %s\\n\", nm);\n  if (strcmp (nm, \"mex_funcdemo\") == 0)\n    mexPrintf (\"This is the principal function\\n\", nm);\n\n  return;\n}\n"
  },
  {
    "path": "examples/code/mex_hellodemo.c",
    "content": "#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  mexPrintf (\"Hello, World!\\n\");\n\n  mexPrintf (\"I have %d inputs and %d outputs\\n\", nrhs, nlhs);\n\n  /* Return empty matrices for any outputs */\n  int i;\n  for (i = 0; i < nlhs; i++)\n    plhs[i] = mxCreateDoubleMatrix (0, 0, mxREAL);\n}\n"
  },
  {
    "path": "examples/code/mex_pow2demo.c",
    "content": "#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  mwSize n;\n  mwIndex i;\n  double *vri, *vro;\n\n  if (nrhs != 1 || ! mxIsDouble (prhs[0]))\n    mexErrMsgTxt (\"ARG1 must be a double matrix\");\n\n  n = mxGetNumberOfElements (prhs[0]);\n  plhs[0] = mxCreateNumericArray (mxGetNumberOfDimensions (prhs[0]),\n                                  mxGetDimensions (prhs[0]),\n                                  mxGetClassID (prhs[0]),\n                                  mxIsComplex (prhs[0]));\n  vri = mxGetPr (prhs[0]);\n  vro = mxGetPr (plhs[0]);\n\n  if (mxIsComplex (prhs[0]))\n    {\n      double *vii, *vio;\n      vii = mxGetPi (prhs[0]);\n      vio = mxGetPi (plhs[0]);\n\n      for (i = 0; i < n; i++)\n        {\n          vro[i] = vri[i] * vri[i] - vii[i] * vii[i];\n          vio[i] = 2 * vri[i] * vii[i];\n        }\n    }\n  else\n    {\n      for (i = 0; i < n; i++)\n        vro[i] = vri[i] * vri[i];\n    }\n}\n"
  },
  {
    "path": "examples/code/mex_propdemo.c",
    "content": "#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  double handle;\n  char property[256];\n\n  if (nrhs < 2 || nrhs > 3)\n    mexErrMsgTxt (\"incorrect number of arguments\");\n  if (! mxIsDouble (prhs[0]))\n    mexErrMsgTxt (\"handle must be a double scalar\");\n  if (! mxIsChar (prhs[1]))\n    mexErrMsgTxt (\"property must be a string\");\n\n  handle = mxGetScalar (prhs[0]);\n  mxGetString (prhs[1], property, 256);\n  plhs[0] = mxDuplicateArray (mexGet (handle, property));\n\n  if (nrhs == 3)\n    if (mexSet (handle, property, mxDuplicateArray (prhs[2])))\n      mexErrMsgTxt (\"failed to set property\");\n}\n"
  },
  {
    "path": "examples/code/mex_setdemo.c",
    "content": "#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  char *str;\n  mxArray *v;\n  int found = 0;\n\n  if (nrhs != 2 || ! mxIsChar (prhs[0]))\n    mexErrMsgTxt (\"Arguments must be a symbol name and a value\");\n\n  str = mxArrayToString (prhs[0]);\n\n  // FIXME: If variable does not exist, error is reported which prevents\n  //        subsequent mexGetArray function from working.\n  v = mexGetArray (str, \"global\");\n  if (v)\n    {\n      mexPrintf (\"%s is a global variable with the following value:\\n\", str);\n      mexCallMATLAB (0, NULL, 1, &v, \"disp\");\n      found = 1;\n    }\n\n  if (! found)\n    v = mexGetArray (str, \"caller\");\n\n  if (! found && v)\n    {\n      mexPrintf (\"%s is a caller variable with the following value:\\n\", str);\n      mexCallMATLAB (0, NULL, 1, &v, \"disp\");\n    }\n\n  // WARNING!! Can't do this in MATLAB!  Must copy variable first.\n  mexPutVariable (\"caller\", str, prhs[1]);\n}\n"
  },
  {
    "path": "examples/code/mex_sparsedemo.c",
    "content": "#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  mwSize m, n, nz;\n  mxArray *v;\n  mwIndex i;\n  double *pr, *pi;\n  double *pr2, *pi2;\n  mwIndex *ir, *jc;\n  mwIndex *ir2, *jc2;\n\n  if (nrhs != 1 || ! mxIsSparse (prhs[0]))\n    mexErrMsgTxt (\"ARG1 must be a sparse matrix\");\n\n  m = mxGetM (prhs[0]);\n  n = mxGetN (prhs[0]);\n  nz = mxGetNzmax (prhs[0]);\n\n  if (mxIsComplex (prhs[0]))\n    {\n      mexPrintf (\"Matrix is %d-by-%d complex sparse matrix\", m, n);\n      mexPrintf (\" with %d elements\\n\", nz);\n\n      pr = mxGetPr (prhs[0]);\n      pi = mxGetPi (prhs[0]);\n      ir = mxGetIr (prhs[0]);\n      jc = mxGetJc (prhs[0]);\n\n      i = n;\n      while (jc[i] == jc[i-1] && i != 0) i--;\n\n      mexPrintf (\"last nonzero element (%d, %d) = (%g, %g)\\n\",\n                 ir[nz-1]+ 1, i, pr[nz-1], pi[nz-1]);\n\n      v = mxCreateSparse (m, n, nz, mxCOMPLEX);\n      pr2 = mxGetPr (v);\n      pi2 = mxGetPi (v);\n      ir2 = mxGetIr (v);\n      jc2 = mxGetJc (v);\n\n      for (i = 0; i < nz; i++)\n        {\n          pr2[i] = 2 * pr[i];\n          pi2[i] = 2 * pi[i];\n          ir2[i] = ir[i];\n        }\n      for (i = 0; i < n + 1; i++)\n        jc2[i] = jc[i];\n\n      if (nlhs > 0)\n        plhs[0] = v;\n    }\n  else if (mxIsLogical (prhs[0]))\n    {\n      mxLogical *pbr, *pbr2;\n      mexPrintf (\"Matrix is %d-by-%d logical sparse matrix\", m, n);\n      mexPrintf (\" with %d elements\\n\", nz);\n\n      pbr = mxGetLogicals (prhs[0]);\n      ir = mxGetIr (prhs[0]);\n      jc = mxGetJc (prhs[0]);\n\n      i = n;\n      while (jc[i] == jc[i-1] && i != 0) i--;\n      mexPrintf (\"last nonzero element (%d, %d) = %d\\n\",\n                 ir[nz-1]+ 1, i, pbr[nz-1]);\n\n      v = mxCreateSparseLogicalMatrix (m, n, nz);\n      pbr2 = mxGetLogicals (v);\n      ir2 = mxGetIr (v);\n      jc2 = mxGetJc (v);\n\n      for (i = 0; i < nz; i++)\n        {\n          pbr2[i] = pbr[i];\n          ir2[i] = ir[i];\n        }\n      for (i = 0; i < n + 1; i++)\n        jc2[i] = jc[i];\n\n      if (nlhs > 0)\n        plhs[0] = v;\n    }\n  else\n    {\n      mexPrintf (\"Matrix is %d-by-%d real sparse matrix\", m, n);\n      mexPrintf (\" with %d elements\\n\", nz);\n\n      pr = mxGetPr (prhs[0]);\n      ir = mxGetIr (prhs[0]);\n      jc = mxGetJc (prhs[0]);\n\n      i = n;\n      while (jc[i] == jc[i-1] && i != 0) i--;\n      mexPrintf (\"last nonzero element (%d, %d) = %g\\n\",\n                 ir[nz-1]+ 1, i, pr[nz-1]);\n\n      v = mxCreateSparse (m, n, nz, mxREAL);\n      pr2 = mxGetPr (v);\n      ir2 = mxGetIr (v);\n      jc2 = mxGetJc (v);\n\n      for (i = 0; i < nz; i++)\n        {\n          pr2[i] = 2 * pr[i];\n          ir2[i] = ir[i];\n        }\n      for (i = 0; i < n + 1; i++)\n        jc2[i] = jc[i];\n\n      if (nlhs > 0)\n        plhs[0] = v;\n    }\n}\n"
  },
  {
    "path": "examples/code/mex_stringdemo.c",
    "content": "#include <string.h>\n#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  mwSize m, n;\n  mwIndex i, j;\n  mxChar *pi, *po;\n\n  if (nrhs != 1 || ! mxIsChar (prhs[0])\n      || mxGetNumberOfDimensions (prhs[0]) > 2)\n    mexErrMsgTxt (\"ARG1 must be a char matrix\");\n\n  m = mxGetM (prhs[0]);\n  n = mxGetN (prhs[0]);\n  pi = mxGetChars (prhs[0]);\n  plhs[0] = mxCreateNumericMatrix (m, n, mxCHAR_CLASS, mxREAL);\n  po = mxGetChars (plhs[0]);\n\n  for (j = 0; j < n; j++)\n    for (i = 0; i < m; i++)\n      po[j*m + m - 1 - i] = pi[j*m + i];\n}\n"
  },
  {
    "path": "examples/code/mex_structdemo.c",
    "content": "#include \"mex.h\"\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  int i;\n  mwIndex j;\n  mxArray *v;\n  const char *keys[] = { \"this\", \"that\" };\n\n  if (nrhs != 1 || ! mxIsStruct (prhs[0]))\n    mexErrMsgTxt (\"ARG1 must be a struct\");\n\n  for (i = 0; i < mxGetNumberOfFields (prhs[0]); i++)\n    for (j = 0; j < mxGetNumberOfElements (prhs[0]); j++)\n      {\n        mexPrintf (\"field %s(%d) = \", mxGetFieldNameByNumber (prhs[0], i), j);\n        v = mxGetFieldByNumber (prhs[0], j, i);\n        mexCallMATLAB (0, NULL, 1, &v, \"disp\");\n      }\n\n  v = mxCreateStructMatrix (2, 2, 2, keys);\n\n  mxSetFieldByNumber (v, 0, 0, mxCreateString (\"this1\"));\n  mxSetFieldByNumber (v, 0, 1, mxCreateString (\"that1\"));\n  mxSetFieldByNumber (v, 1, 0, mxCreateString (\"this2\"));\n  mxSetFieldByNumber (v, 1, 1, mxCreateString (\"that2\"));\n  mxSetFieldByNumber (v, 2, 0, mxCreateString (\"this3\"));\n  mxSetFieldByNumber (v, 2, 1, mxCreateString (\"that3\"));\n  mxSetFieldByNumber (v, 3, 0, mxCreateString (\"this4\"));\n  mxSetFieldByNumber (v, 3, 1, mxCreateString (\"that4\"));\n\n  if (nlhs)\n    plhs[0] = v;\n}\n"
  },
  {
    "path": "examples/code/module.mk",
    "content": "%canon_reldir%_EXTRA_DIST =\n\n%canon_reldir%_CLEANFILES =\n%canon_reldir%_DISTCLEANFILES =\n%canon_reldir%_MAINTAINERCLEANFILES =\n\n%canon_reldir%_SRC = \\\n  %reldir%/@FIRfilter/FIRfilter.m \\\n  %reldir%/@FIRfilter/FIRfilter_aggregation.m \\\n  %reldir%/@FIRfilter/display.m \\\n  %reldir%/@FIRfilter/subsasgn.m \\\n  %reldir%/@FIRfilter/subsref.m \\\n  %reldir%/@polynomial/disp.m \\\n  %reldir%/@polynomial/double.m \\\n  %reldir%/@polynomial/end.m \\\n  %reldir%/@polynomial/get.m \\\n  %reldir%/@polynomial/mtimes.m \\\n  %reldir%/@polynomial/numel.m \\\n  %reldir%/@polynomial/plot.m \\\n  %reldir%/@polynomial/polynomial.m \\\n  %reldir%/@polynomial/polynomial_superiorto.m \\\n  %reldir%/@polynomial/polyval.m \\\n  %reldir%/@polynomial/roots.m \\\n  %reldir%/@polynomial/set.m \\\n  %reldir%/@polynomial/subsasgn.m \\\n  %reldir%/@polynomial/subsref.m \\\n  %reldir%/addtwomatrices.cc \\\n  %reldir%/celldemo.cc \\\n  %reldir%/embedded.cc \\\n  %reldir%/fortrandemo.cc \\\n  %reldir%/fortransub.f \\\n  %reldir%/funcdemo.cc \\\n  %reldir%/globaldemo.cc \\\n  %reldir%/helloworld.cc \\\n  %reldir%/make_int.cc \\\n  %reldir%/mex_demo.c \\\n  %reldir%/mex_celldemo.c \\\n  %reldir%/mex_fevaldemo.c \\\n  %reldir%/mex_fevalf.f \\\n  %reldir%/mex_funcdemo.c \\\n  %reldir%/mex_hellodemo.c \\\n  %reldir%/mex_pow2demo.c \\\n  %reldir%/mex_propdemo.c \\\n  %reldir%/mex_setdemo.c \\\n  %reldir%/mex_sparsedemo.c \\\n  %reldir%/mex_stringdemo.c \\\n  %reldir%/mex_structdemo.c \\\n  %reldir%/oct_demo.cc \\\n  %reldir%/oregonator.cc \\\n  %reldir%/oregonator.m \\\n  %reldir%/paramdemo.cc \\\n  %reldir%/polynomial2.m \\\n  %reldir%/standalone.cc \\\n  %reldir%/standalonebuiltin.cc \\\n  %reldir%/stringdemo.cc \\\n  %reldir%/structdemo.cc \\\n  %reldir%/unwinddemo.cc\n\n%canon_reldir%_EXTRA_DIST += \\\n  $(%canon_reldir%_SRC)\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n\nCLEANFILES += $(%canon_reldir%_CLEANFILES)\nDISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)\nMAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)\n\nexamples-clean:\n\trm -f $(%canon_reldir%_CLEANFILES)\n\nexamples-distclean: examples-clean\n\trm -f $(%canon_reldir%_DISTCLEANFILES)\n\nexamples-maintainer-clean: examples-distclean\n\trm -f $(%canon_reldir%_MAINTAINERCLEANFILES)\n"
  },
  {
    "path": "examples/code/oct_demo.cc",
    "content": "// oct_demo.cc -- example of a dynamically linked function for Octave.\n\n// To compile this file, type the command\n//\n//   mkoctfile oct_demo.cc\n//\n// from within Octave or from the shell prompt.  This will create a file\n// called oct_demo.oct that can be loaded by Octave.  To test the\n// oct_demo.oct file, start Octave and type the command\n//\n//   oct_demo (\"easy as\", 1, 2, 3)\n//\n// at the Octave prompt.  Octave should respond by printing\n//\n//   Hello, world!\n//   easy as\n//   1\n//   2\n//   3\n//   ans = 3\n\n// Additional samples of real dynamically loaded functions are available in\n// the files of the libinterp/dldfcn directory of the Octave distribution.\n// See also the chapter External Code Interface in the documentation.\n\n#include <iostream>\n\n#include <octave/oct.h>\n\n// Every user function should include <octave/oct.h> which imports the\n// basic set of Octave header files required.  In particular this will define\n// the DEFUN_DLD macro (defun-dld.h) which is used for every user function\n// that is visible to Octave.\n\n// The four arguments to the DEFUN_DLD macro are:\n// 1) The function name as seen in Octave.\n// 2) The variable to hold any inputs (of type octave_value_list)\n// 3) The number of output arguments\n// 4) A string to use as help text if 'help <function_name>' is entered.\n//\n// Note below that the third parameter (nargout) of DEFUN_DLD is not used.\n\nDEFUN_DLD (oct_demo, args, /* nargout */,\n           \"[...] = oct_demo (...)\\n\\\n\\n\\\nPrint a greeting followed by the values of all input arguments.\\n\\\n\\n\\\nReturn all arguments in reverse order.\")\n{\n  // The inputs to this are available in the variable named args.\n\n  int nargin = args.length ();\n\n  // The list of values to return.  See the declaration in ovl.h.\n\n  octave_value_list retval;\n\n  // This stream is normally connected to the pager.\n\n  octave_stdout << \"Hello, world!\\n\";\n\n  // The octave_value_list class is a zero-based array of octave_value objects.\n  // The declaration for the octave_value class is in the file ov.h.\n  // The print() method will send its output to octave_stdout,\n  // so it will also end up going through the pager.\n\n  for (int i = 0; i < nargin; i++)\n    {\n      octave_value tmp = args(i);\n      tmp.print (octave_stdout);\n      retval(nargin-i-1) = tmp;\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "examples/code/oregonator.cc",
    "content": "#include <octave/oct.h>\n\nDEFUN_DLD (oregonator, args, ,\n           \"The 'oregonator'.\\n\\\n\\n\\\nReference:\\n\\\n\\n\\\n  Oscillations in chemical systems.  IV.  Limit cycle behavior in a\\n\\\n  model of a real chemical reaction.  Richard J.  Field and Richard\\n\\\n  M. Noyes, The Journal of Chemical Physics, Volume 60 Number 5,\\n\\\n  March 1974.\")\n{\n  ColumnVector dx (3);\n\n  ColumnVector x (args(0).vector_value ());\n\n  dx(0) = 77.27 * (x(1) - x(0)*x(1) + x(0) - 8.375e-06*pow (x(0), 2.0));\n  dx(1) = (x(2) - x(0)*x(1) - x(1)) / 77.27;\n  dx(2) = 0.161*(x(0) - x(2));\n\n  return octave_value (dx);\n}\n"
  },
  {
    "path": "examples/code/oregonator.m",
    "content": "## The 'oregonator'.\n##\n## Reference:\n##\n##   Oscillations in chemical systems.  IV.  Limit cycle behavior in a\n##   model of a real chemical reaction.  Richard J.  Field and Richard\n##   M. Noyes, The Journal of Chemical Physics, Volume 60 Number 5,\n##   March 1974.\n\nfunction dx = oregonator (x, t)\n\n  dx = zeros (3, 1);\n\n  dx(1) = 77.27*(x(2) - x(1)*x(2) + x(1) - 8.375e-06*x(1)^2);\n  dx(2) = (x(3) - x(1)*x(2) - x(2)) / 77.27;\n  dx(3) = 0.161*(x(1) - x(3));\n\nend\n"
  },
  {
    "path": "examples/code/paramdemo.cc",
    "content": "#include <octave/oct.h>\n\nDEFUN_DLD (paramdemo, args, nargout, \"Parameter Check Demo\")\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  NDArray m = args(0).array_value ();\n\n  double min_val = -10.0;\n  double max_val = 10.0;\n\n  octave_stdout << \"Properties of input array:\\n\";\n\n  if (m.any_element_is_negative ())\n    octave_stdout << \"  includes negative values\\n\";\n\n  if (m.any_element_is_inf_or_nan ())\n    octave_stdout << \"  includes Inf or NaN values\\n\";\n\n  if (m.any_element_not_one_or_zero ())\n    octave_stdout << \"  includes other values than 1 and 0\\n\";\n\n  if (m.all_elements_are_int_or_inf_or_nan ())\n    octave_stdout << \"  includes only int, Inf or NaN values\\n\";\n\n  if (m.all_integers (min_val, max_val))\n    octave_stdout << \"  includes only integers in [-10,10]\\n\";\n\n  return octave_value_list ();\n}\n"
  },
  {
    "path": "examples/code/polynomial2.m",
    "content": "classdef polynomial2\n  properties\n    poly = 0;\n  endproperties\n\n  methods\n    function p = polynomial2 (a)\n      if (nargin == 1)\n        if (isa (a, \"polynomial2\"))\n          p.poly = a.poly;\n        elseif (isreal (a) && isvector (a))\n          p.poly = a(:).';  # force row vector\n        else\n          error (\"polynomial2: A must be a real vector\");\n        endif\n      endif\n    endfunction\n\n    function disp (p)\n      a = p.poly;\n      first = true;\n      for i = 1 : length (a);\n        if (a(i) != 0)\n          if (first)\n            first = false;\n          elseif (a(i) > 0 || isnan (a(i)))\n            printf (\" +\");\n          endif\n          if (a(i) < 0)\n            printf (\" -\");\n          endif\n          if (i == 1)\n            printf (\" %.5g\", abs (a(i)));\n          elseif (abs (a(i)) != 1)\n            printf (\" %.5g *\", abs (a(i)));\n          endif\n          if (i > 1)\n            printf (\" X\");\n          endif\n          if (i > 2)\n            printf (\" ^ %d\", i - 1);\n          endif\n        endif\n      endfor\n\n      if (first)\n        printf (\" 0\");\n      endif\n      printf (\"\\n\");\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "examples/code/standalone.cc",
    "content": "#include <iostream>\n#include <octave/oct.h>\n\nint\nmain ()\n{\n  std::cout << \"Hello Octave world!\\n\";\n\n  int n = 2;\n  Matrix a_matrix = Matrix (n, n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    for (octave_idx_type j = 0; j < n; j++)\n      a_matrix(i,j) = (i + 1) * 10 + (j + 1);\n\n  std::cout << a_matrix;\n\n  return 0;\n}\n"
  },
  {
    "path": "examples/code/standalonebuiltin.cc",
    "content": "#include <iostream>\n#include <octave/oct.h>\n#include <octave/builtin-defun-decls.h>\n\nint\nmain ()\n{\n  int n = 2;\n  Matrix a_matrix = Matrix (n, n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    for (octave_idx_type j = 0; j < n; j++)\n      a_matrix(i,j) = (i + 1) * 10 + (j + 1);\n\n  std::cout << \"This is a matrix:\" << std::endl\n            << a_matrix            << std::endl;\n\n  octave_value_list in;\n  in(0) = a_matrix;\n\n  octave_value_list out = octave::Fnorm (in, 1);\n  double norm_of_the_matrix = out(0).double_value ();\n\n  std::cout << \"This is the norm of the matrix:\" << std::endl\n            << norm_of_the_matrix                << std::endl;\n\n  return 0;\n}\n"
  },
  {
    "path": "examples/code/stringdemo.cc",
    "content": "#include <octave/oct.h>\n\nDEFUN_DLD (stringdemo, args, , \"String Demo\")\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value_list retval;\n\n  charMatrix ch = args(0).char_matrix_value ();\n\n  retval(1) = octave_value (ch, '\\'');  // Single Quote String\n\n  octave_idx_type nr = ch.rows ();\n\n  for (octave_idx_type i = 0; i < nr / 2; i++)\n    {\n      std::string tmp = ch.row_as_string (i);\n\n      ch.insert (ch.row_as_string (nr-i-1).c_str (), i, 0);\n      ch.insert (tmp.c_str (), nr-i-1, 0);\n    }\n\n  retval(0) = octave_value (ch, '\"');  // Double Quote String\n\n  return retval;\n}\n"
  },
  {
    "path": "examples/code/structdemo.cc",
    "content": "#include <octave/oct.h>\n#include <octave/ov-struct.h>\n\nDEFUN_DLD (structdemo, args, , \"Struct Demo\")\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  if (! args(0).isstruct ())\n    error (\"structdemo: ARG1 must be a struct\");\n\n  octave_scalar_map arg0 = args(0).scalar_map_value ();\n  //octave_map arg0 = args(0).map_value ();\n\n  if (! args(1).is_string ())\n    error (\"structdemo: ARG2 must be a character string\");\n\n  std::string arg1 = args(1).string_value ();\n\n  octave_value tmp = arg0.contents (arg1);\n  //octave_value tmp = arg0.contents (arg1)(0);\n\n  if (! tmp.is_defined ())\n    error (\"structdemo: struct does not have a field named '%s'\\n\",\n           arg1.c_str ());\n\n  octave_scalar_map st;\n\n  st.assign (\"selected\", tmp);\n\n  return octave_value (st);\n}\n"
  },
  {
    "path": "examples/code/unwinddemo.cc",
    "content": "#include <octave/oct.h>\n#include <octave/unwind-prot.h>\n\nvoid\nmy_err_handler (const char *fmt, ...)\n{\n  // Do nothing!!\n}\n\nvoid\nmy_err_with_id_handler (const char *id, const char *fmt, ...)\n{\n  // Do nothing!!\n}\n\nDEFUN_DLD (unwinddemo, args, nargout, \"Unwind Demo\")\n{\n  if (args.length () < 2)\n    print_usage ();\n\n  NDArray a = args(0).array_value ();\n  NDArray b = args(1).array_value ();\n\n  // Create unwind_action objects.  At the end of the enclosing scope,\n  // destructors for these objects will call the given functions with\n  // the specified arguments.\n\n  octave::unwind_action restore_warning_handler\n    (set_liboctave_warning_handler, current_liboctave_warning_handler);\n\n  octave::unwind_action restore_warning_with_id_handler\n    (set_liboctave_warning_with_id_handler,\n     current_liboctave_warning_with_id_handler);\n\n  set_liboctave_warning_handler (my_err_handler);\n  set_liboctave_warning_with_id_handler (my_err_with_id_handler);\n\n  return octave_value (quotient (a, b));\n}\n"
  },
  {
    "path": "examples/data/README",
    "content": "* penny data file:\n\n  See the discussion here:\n  https://savannah.gnu.org/patch/?func=detailitem&item_id=8472\n\n* west0479 data file:\n\n  Chemical engineering plant models Eight stage column section, all\n  rigorous from set CHEMWEST, from the Harwell-Boeing Collection.\n\n  west0479.mtx: original file obtained from\n  https://math.nist.gov/MatrixMarket/data/Harwell-Boeing/chemwest/west0479.html\n\n  west0479.mat: generated from west0479.mtx as follows:\n\n    x = load (\"west0479.mtx\");\n    nr = x(1,1);\n    nc = x(1,2);\n    i = x(2:end,1);\n    j = x(2:end,2);\n    sv = x(2:end,3);\n    west0479 = sparse(i, j, sv, nr, nc);\n    save -text west0479.mat west0479\n\n  Note that the original file has 1910 entries but 22 of them are exact\n  zeros:\n\n    384 86  0.0000000000000e+00\n    360 116  0.0000000000000e+00\n    361 117  0.0000000000000e+00\n    362 118  0.0000000000000e+00\n    238 224  0.0000000000000e+00\n    239 225  0.0000000000000e+00\n    240 226  0.0000000000000e+00\n    250 240  0.0000000000000e+00\n    251 241  0.0000000000000e+00\n    252 242  0.0000000000000e+00\n    272 259  0.0000000000000e+00\n    273 260  0.0000000000000e+00\n    274 261  0.0000000000000e+00\n    294 278  0.0000000000000e+00\n    295 279  0.0000000000000e+00\n    296 280  0.0000000000000e+00\n    316 297  0.0000000000000e+00\n    317 298  0.0000000000000e+00\n    318 299  0.0000000000000e+00\n    338 316  0.0000000000000e+00\n    339 317  0.0000000000000e+00\n    340 318  0.0000000000000e+00\n\n  These are not explicitly included in the west0479.mat file.\n"
  },
  {
    "path": "examples/data/module.mk",
    "content": "%canon_reldir%_EXTRA_DIST =\n\n%canon_reldir%_DAT = \\\n  %reldir%/penny.mat \\\n  %reldir%/west0479.mat\n\n%canon_reldir%_EXTRA_DIST += \\\n  $(%canon_reldir%_DAT) \\\n  %reldir%/README \\\n  %reldir%/west0479.mtx\n\noctdata_DATA += \\\n  $(%canon_reldir%_DAT)\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n"
  },
  {
    "path": "examples/data/penny.mat",
    "content": "# Created by Octave 3.8.1, Sun Jun 01 16:28:53 2014 CEST <weber@t61>\n# name: P\n# type: matrix\n# rows: 128\n# columns: 128\n 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 18 43 68 89 107 120 135 149 162 172 180 192 196 203 207 211 210 212 213 214 212 210 209 204 201 194 183 177 163 148 130 116 98 81 60 35 6 4 3 3 3 3 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 6 33 63 90 111 132 152 172 190 199 209 215 219 222 224 225 226 228 228 229 228 229 230 228 229 230 229 228 227 226 225 221 216 216 207 197 189 171 151 128 107 81 52 21 4 3 3 3 2 3 3 3 2 2 2 2 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 9 44 78 104 130 159 183 200 214 222 225 227 230 230 233 235 235 235 235 235 235 235 235 234 233 233 234 234 233 233 232 232 232 231 232 231 230 228 227 226 223 220 213 203 183 157 130 100 70 34 5 3 3 3 3 2 3 2 3 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 2 2 2 2 27 64 99 129 160 186 206 218 226 229 231 234 235 236 236 235 235 232 229 226 221 219 218 216 216 214 214 215 216 218 220 221 223 226 228 229 230 231 231 231 230 230 229 228 227 226 222 218 209 188 159 128 96 58 15 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 35 75 110 140 174 202 217 227 232 234 235 236 236 234 228 221 214 208 203 199 196 195 193 192 190 190 189 188 188 189 190 191 191 193 192 193 194 197 201 206 213 218 223 227 229 230 230 229 227 226 226 223 220 213 196 164 127 91 49 5 4 3 3 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2\n 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 10 52 92 129 164 196 217 226 232 235 236 237 234 224 214 205 198 193 191 187 186 187 183 183 182 181 179 178 178 181 179 179 179 179 180 180 180 179 178 179 180 182 184 186 190 195 200 209 217 223 227 228 229 228 227 225 224 222 217 204 173 135 96 52 5 3 3 3 3 3 2 3 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 8 52 93 131 165 200 221 229 234 236 237 234 225 212 201 193 188 185 183 180 178 176 175 174 173 173 182 174 171 177 180 170 175 184 170 169 176 180 179 177 172 169 169 171 174 176 178 179 182 185 188 194 203 212 221 226 228 227 227 226 224 223 219 208 184 144 103 54 5 3 3 3 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2\n 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 13 49 90 131 167 203 222 230 232 235 236 225 214 202 194 189 186 181 178 175 172 170 168 167 167 164 163 164 188 177 163 185 188 163 176 175 159 159 172 182 175 170 161 159 159 161 163 166 168 170 171 173 176 178 182 185 193 202 213 221 225 227 226 225 224 223 220 211 188 145 101 48 5 3 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 45 88 128 166 201 222 231 234 234 232 219 204 193 189 186 183 179 175 171 167 164 163 160 158 156 155 155 154 154 171 178 158 184 185 160 175 159 148 148 165 170 153 150 147 148 150 151 153 156 157 159 161 163 165 169 173 175 177 180 185 192 204 216 223 225 226 224 224 223 221 212 188 141 91 34 4 3 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2\n 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 1 2 3 41 82 125 163 199 220 228 229 235 229 216 201 191 185 181 180 180 184 186 174 163 158 155 152 150 148 145 145 144 144 145 154 173 159 174 174 169 168 142 136 137 159 166 161 141 138 138 141 142 144 146 148 149 151 154 157 160 170 170 169 172 174 176 179 186 198 210 222 226 225 224 224 222 220 212 181 130 80 15 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 1 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 20 71 114 154 194 220 230 230 235 231 215 200 193 187 180 177 173 181 198 188 183 188 162 150 146 143 141 139 136 135 135 135 135 138 162 167 159 156 166 155 129 126 127 151 143 137 129 129 130 132 133 136 137 140 141 144 145 148 151 165 177 183 174 167 168 170 173 176 182 195 211 222 225 225 223 222 221 219 206 166 114 53 4 3 2 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 33 85 132 172 211 231 236 233 233 220 206 196 191 184 179 174 169 165 164 188 174 156 162 176 146 139 135 132 130 128 126 125 125 125 125 139 156 146 130 154 147 119 116 117 139 139 122 122 120 121 122 126 127 128 130 132 135 137 139 141 146 150 173 177 176 173 162 163 167 171 175 181 193 208 220 224 223 223 222 220 217 197 159 102 36 4 3 2 3 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 14 72 124 166 210 235 244 239 235 221 203 195 191 187 187 181 169 162 158 156 154 174 166 143 145 166 136 129 126 122 120 118 116 115 114 114 115 127 139 118 114 133 118 106 106 110 134 136 135 128 114 114 115 117 118 120 122 124 127 128 131 134 138 145 165 147 150 153 153 155 159 163 169 173 176 183 198 214 222 224 223 222 220 219 209 177 118 53 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 38 96 144 187 227 246 247 240 228 207 198 191 186 186 200 195 194 180 156 151 147 144 158 166 137 136 155 129 120 116 113 111 109 106 105 104 104 104 106 109 101 100 102 99 97 97 99 105 109 112 110 105 105 107 108 110 112 114 116 119 120 124 126 131 148 151 138 140 142 146 148 151 166 175 168 169 172 175 185 202 217 223 223 222 220 219 218 201 142 79 4 3 3 3 3 2 2 2 2 2 2 3 2 2 2 2 2 2 2\n 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 56 114 161 204 242 249 245 236 216 203 195 188 182 178 192 187 168 170 182 157 143 138 136 140 160 137 134 143 117 111 108 105 102 98 98 96 95 93 93 92 92 90 89 89 88 88 87 89 89 91 91 94 95 98 98 100 102 105 106 108 111 113 115 118 123 146 133 130 132 135 138 141 147 174 179 183 172 164 167 171 176 193 210 221 223 223 221 220 220 212 164 102 27 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 67 126 172 217 248 248 245 228 210 201 193 186 181 174 171 193 173 156 150 163 164 135 130 126 126 149 148 141 120 107 102 99 96 94 91 89 87 87 85 83 82 82 82 82 82 82 80 81 81 82 82 82 84 87 89 91 93 94 97 99 101 103 105 107 112 122 137 121 122 125 128 131 135 147 168 154 161 179 160 159 163 166 172 180 201 216 222 222 222 218 219 216 182 121 52 4 3 3 2 2 2 3 2 2 2 2 2 2 2 2 2\n 2 2 1 2 2 2 2 2 2 2 2 1 2 2 2 7 83 137 185 230 249 247 238 217 204 198 193 187 179 172 166 162 182 173 148 142 146 163 128 122 117 116 126 126 111 100 96 93 91 88 86 83 81 79 78 76 75 76 78 80 85 89 89 81 78 76 76 76 77 78 80 81 83 85 87 89 91 92 95 97 100 104 116 118 113 115 118 121 125 131 156 163 143 147 170 153 153 156 159 164 168 175 192 211 221 223 222 220 219 219 189 133 65 4 3 2 2 3 2 2 2 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 2 2 2 2 2 2 2 20 91 147 197 240 248 248 232 209 200 196 193 198 196 175 165 158 154 163 172 142 135 139 155 121 113 110 106 103 99 93 90 86 84 82 80 78 75 73 72 73 72 72 86 90 93 97 100 100 93 95 93 93 91 83 78 81 85 82 80 81 82 84 86 88 90 93 95 99 102 104 107 110 114 120 130 150 154 162 162 152 143 144 149 153 158 162 165 172 184 205 219 223 222 220 219 220 205 151 80 4 3 3 3 3 3 3 2 3 3 2 2 2 2\n 2 1 2 2 2 2 1 2 2 2 2 2 2 3 80 141 192 233 249 250 232 210 200 194 190 198 197 183 170 159 153 148 143 153 160 140 143 145 115 106 102 97 93 89 85 81 78 75 74 72 71 68 69 72 83 90 91 95 97 94 101 106 111 108 103 98 97 104 107 108 104 99 98 89 75 76 77 78 80 82 85 88 91 94 96 99 102 106 112 128 138 127 141 153 134 134 138 142 146 151 170 162 163 168 175 193 213 222 222 221 219 219 220 180 111 30 3 3 2 3 2 2 2 1 2 2 2 2\n 2 1 2 1 2 2 2 1 2 2 2 2 35 97 156 207 245 251 246 220 205 196 190 184 190 196 170 163 158 157 145 139 133 132 142 143 133 112 101 96 91 88 84 78 77 72 69 68 65 66 66 68 83 89 93 101 106 111 114 115 114 116 122 119 111 107 115 121 122 114 107 102 101 98 82 71 72 72 74 76 79 81 84 87 90 93 96 101 107 119 116 118 138 141 126 129 133 137 142 162 167 155 158 163 167 175 193 214 222 222 221 219 219 219 169 97 9 3 2 3 2 2 2 2 2 2 2 2\n 2 2 2 2 2 1 2 1 2 2 1 31 102 158 210 247 253 243 217 205 196 188 181 176 188 189 161 155 168 176 142 132 125 120 117 113 106 99 93 88 83 80 76 72 69 65 62 60 61 70 85 88 88 90 101 114 121 126 131 133 131 131 137 132 131 136 135 135 130 125 121 118 114 105 96 90 76 69 70 72 73 76 77 82 84 87 90 93 99 103 106 111 131 134 120 125 127 132 143 161 148 148 153 158 163 166 172 189 212 221 221 220 219 221 219 171 96 8 3 3 2 2 2 2 2 2 2 2\n 1 1 2 2 1 2 2 2 2 2 6 81 143 197 241 253 247 222 206 197 190 182 175 169 168 187 162 150 154 166 163 130 120 114 109 105 98 92 87 82 78 72 69 65 62 59 57 57 65 88 96 100 101 103 110 122 134 140 144 147 146 148 150 146 145 144 142 139 134 131 133 133 131 120 108 107 102 92 80 78 74 72 74 75 78 81 83 87 91 95 98 102 110 119 115 116 120 126 148 150 137 141 146 166 168 159 164 169 181 205 219 222 221 220 218 221 187 112 16 3 3 2 2 2 2 2 2 2\n 1 2 2 2 2 2 2 2 2 2 80 140 194 241 254 244 220 205 197 190 183 175 168 163 158 169 173 148 142 152 148 123 112 106 102 96 92 86 81 76 70 67 63 60 56 53 55 68 86 91 97 106 111 114 118 128 146 153 154 153 157 156 153 149 147 146 141 135 129 130 142 144 145 138 125 118 117 124 124 117 108 94 79 71 73 75 78 82 85 89 92 97 100 103 108 111 115 126 148 134 131 135 148 166 151 152 157 162 168 179 204 220 222 221 220 218 222 182 105 11 3 2 2 2 2 2 2 2\n 2 2 2 2 2 2 2 1 1 66 135 189 237 253 248 220 205 198 190 183 175 168 162 157 151 150 158 160 156 147 126 113 106 101 96 90 85 80 75 71 64 60 57 54 51 51 71 79 90 94 110 118 124 131 138 143 155 162 161 156 161 161 155 146 143 139 135 129 127 136 150 151 149 140 129 127 131 139 136 131 118 98 85 74 70 70 73 76 79 82 86 90 94 98 102 106 109 125 141 124 126 134 157 146 142 148 152 157 163 169 182 204 220 222 220 219 217 223 175 93 4 3 2 2 3 3 2 2\n 2 1 2 1 1 2 2 1 54 125 182 235 252 249 224 206 198 191 185 176 169 161 155 150 145 140 137 134 131 120 110 104 99 95 89 84 79 75 70 64 59 54 52 49 56 76 89 97 101 114 124 133 147 154 152 152 165 168 168 163 165 165 157 140 130 130 129 129 135 149 153 153 151 137 127 133 139 148 151 142 122 108 94 87 69 66 69 71 74 77 81 85 88 92 95 100 104 115 136 124 128 148 140 133 137 141 146 152 158 165 171 182 205 220 222 220 219 219 223 170 88 4 3 3 2 2 2 2\n 2 2 1 1 2 2 1 58 128 186 235 252 244 219 205 197 195 187 176 168 161 154 148 143 137 132 126 121 113 108 103 98 93 86 81 76 73 67 61 57 53 51 53 70 95 108 114 120 127 138 148 160 167 164 162 169 175 176 173 173 169 168 156 139 131 132 136 142 146 149 151 155 147 134 138 146 150 158 157 145 131 115 99 89 84 70 65 68 70 74 76 80 84 87 91 94 99 105 122 133 135 126 123 128 133 137 144 157 172 168 169 174 188 211 221 221 220 218 226 214 142 45 3 3 2 2 3 3\n 1 2 2 2 2 2 43 114 173 225 248 245 220 207 198 192 200 202 172 164 155 148 142 136 131 125 120 113 107 101 97 91 86 79 74 69 66 60 57 53 55 73 95 112 126 132 135 142 149 160 169 177 179 178 179 181 181 181 180 178 176 170 163 144 136 134 137 141 145 144 151 156 149 148 150 153 159 160 159 154 146 131 114 101 89 83 64 62 65 68 71 74 78 81 85 88 92 96 101 107 111 114 117 121 127 132 140 171 170 181 169 168 174 187 212 221 221 219 219 228 208 129 30 3 3 2 2 2\n 2 2 2 1 2 23 96 161 217 245 245 225 209 202 194 189 182 193 190 161 150 143 137 131 125 119 113 106 101 96 91 85 79 74 68 64 60 56 53 53 68 86 111 131 141 145 148 155 165 176 181 185 187 186 185 186 185 185 184 183 178 169 165 148 136 133 134 141 147 148 152 155 146 143 143 149 159 158 156 158 152 143 121 107 96 83 63 59 60 63 67 69 72 76 79 82 86 90 94 98 103 107 113 118 122 128 137 166 149 162 170 162 167 173 191 214 221 221 219 218 227 197 109 4 3 3 2 3\n 2 2 2 1 2 64 130 189 235 248 236 214 205 198 195 187 179 173 186 184 151 141 133 126 121 116 109 103 98 93 87 81 75 69 64 60 56 53 50 59 73 90 113 139 146 150 151 153 171 180 183 188 188 187 188 189 189 187 185 184 177 168 165 156 143 142 142 142 151 149 145 150 138 133 136 146 151 151 154 154 151 146 139 111 91 85 69 55 56 58 61 63 66 69 73 76 79 84 88 91 96 100 106 111 125 132 128 156 153 144 150 154 159 164 171 190 213 222 221 220 218 229 198 113 4 2 3 3\n 2 2 2 2 60 128 188 235 249 234 213 204 198 211 216 208 195 184 182 181 160 135 125 120 115 108 102 97 91 86 80 74 69 63 58 55 52 51 58 77 92 109 134 146 152 156 153 172 179 181 186 191 186 184 189 191 191 190 190 185 179 178 171 155 150 150 150 153 154 147 151 148 141 140 141 144 143 142 142 139 131 128 122 98 83 75 61 51 52 54 56 61 62 66 69 72 76 79 82 87 91 96 102 108 131 132 125 156 147 138 143 149 154 160 168 175 200 220 222 220 218 225 227 159 62 4 2 3\n 1 2 2 35 108 172 224 248 240 216 208 199 192 191 205 200 184 174 168 163 148 127 120 114 108 103 97 92 87 80 75 70 64 60 55 51 50 63 81 92 107 125 143 152 160 163 169 182 180 180 187 192 188 186 188 191 194 194 193 192 190 187 176 162 157 157 159 160 158 154 156 155 152 147 148 146 142 136 130 126 118 110 106 90 75 68 53 45 48 50 52 55 58 61 64 67 71 74 77 82 86 91 96 102 117 137 137 151 138 133 139 144 150 156 163 170 180 207 220 222 220 218 231 216 134 24 3 3\n 2 2 2 67 138 197 236 249 226 214 205 197 188 181 177 189 186 157 146 138 130 121 116 110 104 99 93 88 82 77 72 66 61 57 53 48 49 73 90 103 119 133 151 159 166 175 180 187 183 177 182 190 192 189 186 191 194 195 195 194 192 189 184 173 165 163 164 167 165 161 162 162 154 156 157 157 153 145 134 122 114 105 91 76 66 60 45 41 43 45 48 51 53 56 58 62 65 68 72 76 80 85 90 94 101 113 128 132 125 127 132 138 144 153 169 163 170 180 207 222 222 220 219 231 211 129 15 3\n 2 2 43 116 179 232 251 233 216 207 205 203 183 175 169 164 175 168 139 130 122 114 108 104 98 92 88 82 77 72 67 62 57 52 48 45 53 85 103 114 127 141 158 172 178 186 190 192 188 179 178 184 192 193 190 190 191 193 194 193 193 189 185 179 174 174 173 173 173 170 166 164 167 167 166 166 164 159 148 133 118 100 72 58 54 41 35 36 38 41 43 47 49 52 55 57 60 64 68 71 75 78 84 89 94 100 106 112 116 121 127 133 140 153 181 172 166 172 186 214 222 221 219 217 233 190 97 3\n 2 12 89 159 217 251 243 220 209 201 202 210 192 171 163 155 150 152 135 122 115 108 102 98 92 87 82 77 72 67 63 57 53 47 44 43 67 94 108 119 134 142 161 177 185 190 194 195 192 185 180 182 193 194 190 187 187 191 191 194 195 193 188 184 183 182 181 180 179 173 175 176 175 174 173 172 172 170 163 149 130 106 73 50 34 31 30 32 35 37 40 42 44 48 51 54 56 60 63 66 70 74 80 84 89 94 100 106 110 116 122 128 135 144 169 187 166 168 176 195 218 222 221 219 224 230 157 49\n 2 81 152 210 249 246 222 210 201 193 187 191 195 173 154 146 138 131 122 114 106 101 95 90 85 79 75 71 65 61 56 51 47 43 40 56 82 103 114 133 139 150 166 180 186 189 194 195 192 184 181 193 196 194 190 188 189 191 193 195 191 186 188 189 187 187 185 183 183 183 183 181 181 181 180 178 179 178 172 160 140 114 81 36 26 26 26 29 31 33 36 39 41 44 47 50 52 55 60 63 67 71 75 80 85 90 96 102 108 114 121 126 134 153 174 182 181 166 172 182 211 222 221 220 218 233 190 91\n 53 126 188 244 247 228 215 205 195 188 180 174 178 181 159 140 131 123 115 108 100 95 89 84 79 74 70 65 60 56 51 47 42 37 37 63 86 109 122 138 146 157 167 179 187 191 192 188 186 189 191 197 197 194 192 189 189 194 195 191 183 185 189 188 189 188 188 186 186 185 186 186 185 186 184 183 183 181 178 172 156 134 102 51 23 24 24 26 28 30 33 34 37 40 43 46 49 51 55 59 62 66 71 75 80 86 91 97 103 109 117 124 147 160 155 161 178 171 167 174 193 217 223 221 220 224 229 150\n 98 167 227 247 239 221 209 199 189 181 173 167 160 162 160 137 125 117 109 102 95 89 83 78 73 69 65 59 54 51 47 42 37 33 36 67 88 116 131 141 156 164 169 180 187 191 190 180 174 186 196 198 197 196 195 193 190 192 192 185 180 185 191 192 191 190 189 189 188 189 189 189 190 190 188 186 186 184 182 176 165 147 122 79 24 20 21 23 25 26 28 29 34 35 38 41 44 47 51 55 57 62 66 70 76 81 87 93 99 106 117 141 148 138 136 142 152 156 162 168 177 201 221 222 221 220 232 205\n 141 204 247 249 226 214 203 194 184 175 167 160 153 146 139 127 118 110 103 96 89 84 78 72 68 64 59 55 50 45 41 38 33 30 34 69 91 122 136 147 161 167 170 179 183 188 189 180 173 180 196 196 193 190 188 189 186 186 185 180 180 185 188 190 191 192 191 191 190 190 190 191 192 192 190 190 188 186 183 179 169 154 134 102 43 18 18 19 22 23 24 27 28 32 35 37 41 44 47 49 54 57 62 66 71 77 83 88 94 102 115 128 124 125 130 136 143 149 157 164 172 185 213 221 222 220 218 231\n 163 224 250 242 222 211 200 191 181 172 163 156 149 141 132 123 114 107 99 92 85 79 74 68 64 59 55 51 46 41 38 33 30 28 34 67 92 118 137 148 159 165 169 178 183 185 188 186 183 183 192 190 184 181 182 179 175 177 180 178 180 182 182 187 191 191 190 191 190 190 191 191 192 192 192 192 191 189 186 180 173 161 145 122 82 23 16 18 18 20 20 22 24 27 30 33 35 38 43 45 49 52 56 61 66 71 77 81 88 95 102 110 114 119 124 131 136 143 150 157 166 175 190 216 223 221 220 224\n 211 252 245 224 213 202 192 182 174 165 156 149 140 132 123 115 107 99 92 85 78 73 68 63 58 54 50 44 40 36 32 29 25 25 50 76 103 123 139 151 158 165 175 179 180 186 187 187 188 187 183 180 178 176 173 171 172 175 173 174 180 180 183 187 190 189 189 189 190 189 190 191 192 192 192 193 192 189 185 178 168 158 142 119 83 23 14 14 15 17 17 19 22 24 27 30 33 36 39 41 45 49 54 59 62 68 73 79 85 91 99 105 111 117 122 128 134 141 147 155 164 172 182 208 222 222 221 218\n 242 255 231 218 207 196 187 177 169 160 152 143 135 126 117 109 101 94 87 81 74 69 63 58 54 47 44 39 36 31 28 26 22 22 51 76 100 121 133 148 157 165 175 177 179 185 187 188 189 184 176 174 174 172 171 175 176 173 168 171 179 184 185 187 189 189 189 189 188 187 188 190 190 191 191 192 192 188 184 178 168 157 143 122 91 31 13 12 13 14 15 16 18 21 24 27 30 32 36 39 42 47 51 55 60 64 69 75 81 87 94 101 106 112 118 125 130 137 144 151 159 167 176 192 218 223 221 220\n 250 251 227 214 204 194 183 175 165 156 148 140 131 122 113 105 97 90 83 77 71 65 59 54 48 45 40 36 31 29 26 22 20 20 33 70 91 112 128 143 156 163 172 177 179 183 185 181 183 183 181 173 171 173 179 183 180 173 172 175 178 182 188 187 189 189 189 188 185 184 185 186 187 189 190 191 190 188 185 179 169 159 147 132 107 57 13 10 10 11 12 14 15 17 20 22 25 28 32 35 38 42 45 50 54 59 64 70 76 82 88 94 102 107 113 119 125 131 138 145 153 161 169 178 198 220 223 221\n 255 231 218 205 196 185 177 167 158 150 140 132 123 114 106 98 90 84 77 71 64 59 53 49 43 38 34 31 27 25 21 18 16 16 32 73 97 114 132 149 158 164 170 176 178 180 180 176 176 181 182 180 177 184 187 187 179 176 177 181 184 182 187 187 186 187 187 184 181 180 182 183 185 187 188 189 188 187 183 177 168 157 148 133 104 48 10 9 8 9 10 11 12 15 17 20 23 26 29 33 36 40 44 47 52 57 61 67 73 79 85 92 99 106 111 117 123 129 136 143 151 158 166 176 190 218 224 222\n 245 224 211 201 191 181 172 162 153 144 136 126 117 108 100 93 85 78 73 66 59 54 49 45 39 34 30 27 24 21 18 16 14 13 28 65 94 116 134 149 157 160 167 176 178 177 175 174 173 174 174 178 183 188 186 183 177 173 172 180 185 184 183 183 181 184 184 182 179 176 177 180 181 182 184 186 187 186 182 177 170 162 152 138 112 62 10 8 7 7 8 8 10 12 15 17 20 23 27 30 33 37 41 45 49 53 58 63 69 76 81 87 94 101 107 113 119 125 132 139 147 154 163 171 181 206 223 223\n 231 218 207 196 185 176 167 157 149 139 131 121 112 103 96 88 80 74 68 62 55 50 45 40 35 30 27 23 21 18 15 13 11 11 29 60 82 111 133 148 157 162 164 176 179 175 169 170 169 171 174 178 184 185 177 171 168 166 170 177 181 181 177 179 178 179 180 179 174 170 171 174 175 177 181 183 183 183 181 179 175 166 158 145 121 75 14 6 5 5 5 6 7 9 13 14 18 20 24 27 31 34 38 41 46 50 55 61 66 72 77 84 90 97 103 109 116 122 129 135 143 150 158 167 176 191 219 224\n 224 212 201 191 181 172 162 153 143 134 125 115 107 99 91 83 77 70 64 57 51 46 41 36 32 27 24 20 19 15 13 11 10 10 28 65 83 108 130 145 155 163 164 173 179 173 164 168 169 172 180 184 183 177 169 160 158 164 168 168 172 171 169 174 175 175 176 174 168 166 166 168 169 171 174 177 178 179 181 181 178 171 162 149 130 91 31 6 4 4 3 4 5 7 9 11 14 18 20 25 28 31 35 39 44 48 52 57 62 68 74 80 87 93 100 106 112 118 125 132 139 147 155 163 172 180 208 224\n 219 207 196 187 177 167 158 148 138 130 120 111 103 94 85 79 72 66 59 54 48 42 37 32 28 24 22 18 15 13 11 10 8 7 25 66 88 109 129 140 151 159 163 168 177 173 162 166 173 182 184 182 174 165 161 152 154 163 161 158 161 160 163 165 166 170 174 170 165 162 161 160 162 164 166 169 172 175 180 181 178 171 161 152 133 98 42 6 4 3 2 3 3 5 7 9 12 15 18 22 25 29 32 36 40 44 49 53 58 64 70 76 83 89 96 103 109 116 121 129 135 143 150 159 167 176 194 220\n 213 203 193 182 172 163 154 144 135 125 116 106 98 89 82 74 67 61 56 49 44 38 34 30 26 22 18 16 13 11 9 7 5 6 20 62 85 107 125 133 145 154 158 163 171 173 162 162 173 182 179 172 157 148 152 146 150 154 149 149 150 152 155 156 159 166 170 166 160 157 155 154 155 158 160 163 168 176 180 178 170 156 146 139 126 96 48 6 4 3 3 2 2 2 4 7 9 12 16 19 23 26 30 33 38 41 45 51 55 61 68 73 80 86 92 99 106 112 118 126 133 140 147 155 163 172 181 212\n 212 201 192 181 171 161 152 143 132 123 113 104 96 87 80 72 65 59 53 47 42 36 32 28 24 21 17 15 11 10 8 6 4 4 10 53 71 97 118 127 133 147 155 156 165 170 165 161 170 176 168 163 145 132 136 147 143 140 140 139 142 148 150 152 156 163 163 160 156 151 150 150 151 152 155 158 164 174 178 173 160 137 118 114 110 92 57 10 4 3 2 2 2 2 2 4 6 10 13 16 20 23 27 30 34 37 41 46 51 57 63 69 75 81 88 94 101 108 114 120 127 135 142 151 158 166 174 190\n 205 195 184 174 164 155 146 136 125 116 106 98 90 81 73 67 60 54 48 41 37 32 28 23 20 17 14 11 8 7 6 5 3 3 29 58 77 98 117 127 130 142 153 153 158 167 163 161 172 162 156 147 126 120 138 141 129 123 129 131 140 147 148 152 156 163 159 156 149 146 146 145 147 150 155 160 168 174 171 158 136 101 84 84 86 69 36 4 3 2 2 2 2 2 2 2 5 7 11 15 18 22 25 28 31 35 40 44 49 55 60 66 73 79 87 93 100 107 113 120 126 134 141 148 156 164 172 185\n 203 194 182 173 163 153 143 134 124 114 104 96 87 80 72 64 58 52 46 40 34 30 26 22 18 15 13 10 8 6 4 3 3 3 20 53 75 89 108 120 130 136 147 154 158 165 168 164 170 159 156 145 127 121 127 135 122 112 115 126 137 147 146 149 155 161 160 158 151 148 147 146 144 147 153 159 165 166 160 145 135 116 76 68 71 64 35 4 3 3 2 3 2 2 2 2 3 5 9 11 15 19 22 24 28 31 35 40 45 51 56 62 69 75 82 89 95 102 109 115 122 129 135 143 151 159 167 176\n 197 188 177 167 157 147 137 124 117 107 98 90 82 74 67 60 53 47 41 36 31 27 22 19 16 12 9 7 5 3 3 2 2 3 31 60 74 90 106 119 131 139 144 147 155 164 172 175 173 158 156 138 121 113 124 123 111 104 109 125 141 149 149 150 159 162 160 158 155 154 152 148 146 147 153 155 155 149 135 131 121 92 60 59 64 57 20 4 3 2 3 2 2 2 2 2 2 3 7 10 13 17 19 23 25 29 34 39 44 49 55 61 68 74 81 87 95 102 108 115 121 127 135 142 150 158 167 175\n 194 184 173 163 153 143 133 123 113 104 95 87 79 71 64 57 51 45 39 33 28 25 20 17 13 11 9 6 3 2 2 2 2 2 33 58 71 85 101 114 126 137 142 141 147 158 166 172 172 161 156 136 112 107 116 113 109 111 117 127 141 147 154 153 158 163 164 161 159 158 156 153 149 149 150 149 141 130 123 119 112 78 51 49 58 58 30 4 3 2 2 2 2 2 2 3 3 2 5 8 11 13 16 20 23 27 32 36 42 47 53 58 65 72 78 85 92 99 106 112 119 125 132 139 147 155 163 173\n 191 181 170 160 149 139 130 119 110 101 92 83 75 67 61 54 48 42 36 31 26 22 18 14 12 9 7 4 3 3 2 2 2 2 31 54 69 84 97 109 122 132 138 141 144 148 154 162 167 162 155 134 107 109 108 109 113 119 125 132 142 149 153 158 160 162 162 164 162 161 160 158 154 151 149 145 133 127 124 123 112 76 49 45 51 55 45 7 3 3 2 2 2 2 2 2 2 2 3 6 9 12 13 18 21 25 29 34 39 44 50 56 63 70 76 83 91 97 104 110 117 123 129 137 144 153 161 169\n 190 179 169 158 149 139 129 118 108 99 90 82 75 67 60 53 47 41 35 30 25 22 18 15 11 8 6 4 3 3 2 3 3 2 16 42 60 79 93 105 116 126 133 141 145 144 143 143 156 163 157 141 110 107 107 119 122 124 128 132 139 147 155 159 161 162 163 163 163 163 164 163 160 157 153 150 138 131 129 128 118 92 53 49 49 53 52 36 5 2 3 2 2 3 2 2 2 2 2 3 6 9 12 15 19 22 26 31 35 40 47 53 59 66 73 79 87 93 100 106 113 119 126 132 140 148 156 164\n 184 173 163 152 143 132 122 112 103 94 86 78 71 63 56 50 43 37 32 28 23 20 16 12 10 6 4 3 3 3 3 3 2 2 13 37 59 76 91 106 116 123 131 139 145 140 136 140 147 158 153 136 110 100 110 132 131 128 129 130 135 144 151 156 158 160 162 162 163 163 164 163 161 158 156 151 141 136 133 128 116 81 55 54 54 55 53 41 6 3 3 3 2 2 2 2 2 2 2 2 5 8 11 14 18 21 25 30 35 40 46 52 59 65 72 78 86 92 99 105 112 119 125 131 139 148 156 165\n 180 170 160 150 139 129 119 109 99 93 83 75 67 60 54 47 41 36 30 26 22 18 14 11 8 5 4 3 3 2 3 2 3 2 2 28 53 67 81 101 111 116 127 130 137 137 128 136 139 155 151 140 112 100 107 131 131 127 125 124 126 133 141 146 149 153 158 159 158 158 160 159 160 158 157 155 150 144 139 131 116 84 62 57 56 56 54 48 27 4 3 2 3 2 2 2 2 2 2 2 3 7 9 13 16 21 24 28 33 38 44 50 57 64 70 77 84 90 97 104 110 117 123 130 137 145 153 162\n 178 167 157 147 136 126 116 106 97 88 80 73 65 58 51 45 39 34 29 25 21 17 13 10 8 5 3 3 3 2 2 2 2 2 2 19 46 62 67 89 103 108 122 124 127 131 126 129 136 148 151 143 121 104 106 121 126 121 118 117 119 123 130 135 139 146 152 152 151 150 151 154 156 156 156 156 155 152 145 133 114 84 69 60 57 57 55 52 41 6 3 3 3 2 2 2 2 2 2 2 2 4 8 11 14 19 23 27 32 37 42 49 55 61 68 75 82 89 95 102 108 115 121 128 136 143 151 159\n 175 164 154 144 133 123 113 104 94 86 78 71 64 57 50 43 38 33 28 24 20 16 13 10 7 4 3 2 3 2 2 2 2 2 2 12 38 55 59 71 88 103 120 124 125 130 131 132 132 138 148 141 131 116 109 108 116 112 110 112 115 120 124 128 133 139 144 142 140 138 142 147 151 153 153 154 153 152 147 135 116 87 73 62 58 58 56 54 49 28 3 3 2 2 2 2 2 2 2 2 2 3 7 10 13 17 21 26 30 35 41 47 53 60 66 73 80 88 94 100 106 113 120 126 134 141 149 158\n 172 162 152 141 131 121 110 101 92 84 77 69 62 55 48 42 36 31 27 23 20 15 12 10 6 4 3 3 3 3 2 2 2 2 3 2 27 45 59 67 79 101 117 124 126 128 127 130 129 129 142 139 131 132 128 113 112 107 105 107 111 117 120 125 129 133 135 133 130 127 131 139 146 150 151 151 151 149 144 133 115 94 77 66 60 58 57 56 53 43 5 3 3 3 2 3 2 2 2 2 2 2 5 9 12 16 19 24 28 34 40 45 52 58 65 72 78 85 91 99 105 112 118 125 132 140 147 155\n 170 160 149 139 128 118 108 100 91 82 75 67 60 54 47 41 35 31 26 22 18 15 12 9 6 4 3 3 3 3 3 3 2 2 2 1 12 39 57 68 82 101 113 120 121 123 119 116 119 122 132 140 132 133 134 122 111 106 103 104 110 115 119 121 126 128 127 127 122 120 121 128 138 146 147 148 149 148 140 129 113 96 84 70 60 58 56 55 55 50 27 4 3 2 3 3 2 2 2 2 2 2 4 7 11 15 19 23 27 32 37 44 51 56 63 70 77 83 91 97 103 110 117 123 131 139 146 154\n 168 158 147 136 126 116 106 97 88 80 73 65 59 52 46 40 35 30 26 22 19 15 12 9 6 4 3 3 3 2 2 2 2 2 2 2 2 34 57 63 78 96 104 112 118 117 119 111 115 120 122 131 135 139 137 126 115 105 104 105 110 116 117 117 123 126 124 124 123 118 116 120 128 138 142 144 145 143 135 124 111 101 87 68 64 62 57 53 53 52 38 5 3 3 2 3 2 2 2 2 2 2 4 6 10 14 17 21 26 31 36 43 48 56 62 69 75 82 89 96 102 109 115 122 129 137 144 152\n 166 156 145 134 124 114 105 95 87 79 71 64 57 50 45 39 34 30 26 22 19 15 12 9 6 4 3 3 2 2 3 2 3 3 2 2 2 27 53 60 71 89 96 101 113 116 116 118 117 115 114 112 124 138 141 132 119 102 105 106 112 114 115 115 118 124 124 120 122 120 118 115 119 128 132 135 137 135 128 120 111 103 82 70 75 76 68 60 56 51 38 5 3 3 3 2 2 2 2 2 2 3 2 6 10 13 17 20 24 30 35 41 47 53 60 68 75 81 88 94 101 107 114 121 128 136 142 151\n 165 154 143 133 122 112 103 94 85 78 70 62 56 50 44 39 33 28 25 21 18 15 12 9 7 4 3 3 3 2 2 2 2 2 2 2 2 15 47 59 65 83 92 98 108 115 116 117 113 108 107 104 102 122 136 134 115 96 106 109 112 115 115 116 117 122 124 122 122 121 117 113 113 118 123 125 126 124 121 116 111 100 72 67 74 73 67 58 49 39 21 4 3 3 2 3 2 2 2 2 2 2 2 4 8 12 15 19 24 28 33 39 46 53 59 66 73 80 87 94 100 106 114 119 127 134 141 149\n 163 153 141 131 121 111 101 92 84 76 69 61 56 49 43 38 33 30 25 21 18 15 12 10 7 4 3 2 2 2 2 2 2 2 2 2 2 3 33 55 68 79 90 100 107 110 110 113 109 102 95 97 89 92 112 113 100 95 104 112 114 116 117 118 119 121 123 122 120 119 117 113 109 110 113 116 114 113 111 110 106 92 64 60 59 55 44 29 18 6 4 3 2 2 2 3 2 2 2 2 2 2 2 4 7 11 14 18 22 28 32 38 45 51 58 65 71 78 86 92 99 105 112 118 125 132 140 148\n 161 151 140 130 119 109 100 91 83 75 68 61 55 49 43 37 33 29 25 21 19 15 12 9 7 4 3 3 2 2 2 1 2 2 2 2 2 2 14 40 57 72 85 97 105 106 101 103 106 97 95 91 84 79 79 90 95 98 105 112 116 118 121 123 121 121 122 122 121 119 116 111 104 101 105 101 99 98 99 100 93 78 65 58 54 47 12 3 3 2 2 2 2 3 2 2 2 2 2 2 2 3 2 3 6 10 13 17 21 26 31 37 43 50 57 63 70 77 84 91 97 104 111 117 124 131 139 146\n 160 149 138 129 117 108 98 89 82 74 67 60 55 48 42 37 32 28 25 21 18 15 12 10 8 5 4 3 2 3 2 2 2 2 2 2 2 2 7 33 47 65 76 90 99 103 101 97 104 102 95 92 86 83 77 85 96 102 108 113 118 120 121 124 125 123 124 123 121 119 115 109 101 99 99 94 90 91 94 94 86 77 70 63 57 44 6 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 9 12 16 20 25 31 36 42 49 55 63 70 76 83 90 97 103 110 116 123 130 137 145\n 158 147 137 127 116 107 97 89 81 73 67 60 53 47 42 37 32 28 25 21 19 16 13 11 8 6 4 3 3 2 2 2 2 2 2 2 2 2 6 33 40 63 71 80 87 92 100 99 100 102 97 92 89 86 83 84 95 104 110 114 119 121 122 126 126 127 125 123 121 118 114 107 99 97 95 85 84 88 92 89 81 78 74 66 57 42 5 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 8 11 16 20 24 30 35 42 48 54 62 68 75 83 90 96 103 109 115 122 129 136 144\n 157 147 137 126 116 107 97 88 80 73 66 59 53 46 41 37 33 29 25 22 20 16 14 11 9 7 5 3 3 3 3 3 3 2 2 2 2 2 3 29 38 60 66 76 79 83 93 94 90 98 96 93 91 90 88 87 92 101 109 115 118 122 123 127 127 127 126 121 117 117 112 105 100 98 93 81 85 89 85 84 81 75 70 63 53 38 5 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 8 11 15 19 24 28 35 40 47 54 61 68 75 82 89 96 103 108 115 122 128 136 143\n 159 148 138 128 117 108 99 90 82 74 67 61 54 48 43 37 33 29 26 23 20 17 14 13 10 8 6 5 4 3 2 3 2 2 2 2 2 2 2 8 34 51 59 72 80 79 85 93 94 93 93 94 93 93 94 92 91 94 103 111 117 121 122 126 127 127 125 120 114 112 111 106 101 99 94 84 90 91 89 86 72 61 58 53 45 29 5 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 10 14 17 22 27 33 39 45 51 58 66 73 80 87 93 100 106 113 120 126 133 141\n 156 145 135 124 114 105 96 88 80 72 66 58 53 47 42 37 33 29 25 23 20 18 15 13 11 8 7 5 4 3 3 2 2 3 2 2 2 1 2 6 32 47 57 73 82 81 84 86 90 90 92 93 94 94 95 94 91 92 102 110 116 121 122 126 127 126 123 118 115 112 109 104 100 100 91 89 94 93 91 77 58 53 51 43 29 7 3 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 7 11 15 19 24 29 34 40 46 52 60 67 74 81 88 95 102 108 114 121 128 136 142\n 157 147 137 127 117 107 98 89 82 74 67 61 54 48 43 38 34 31 27 25 21 19 16 14 12 10 8 7 5 4 3 3 2 2 2 2 2 2 2 2 13 34 40 59 74 77 77 82 82 86 90 93 95 97 97 97 95 91 93 103 111 115 119 124 125 124 123 122 118 114 110 108 104 102 94 91 96 96 91 74 63 63 61 53 39 6 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 7 10 14 18 22 27 32 38 44 51 58 64 72 80 86 93 100 106 112 119 126 132 140\n 155 145 134 124 114 105 96 88 80 73 66 60 53 47 42 38 34 30 27 24 22 19 16 14 13 11 9 7 5 4 4 3 2 3 2 2 2 2 2 2 4 23 33 44 56 68 77 78 80 86 90 93 98 100 100 98 96 93 90 98 108 113 115 121 123 121 123 123 119 115 114 111 107 103 93 93 94 94 84 67 64 61 55 44 23 4 3 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 5 8 11 15 19 24 28 34 39 45 52 59 66 73 81 88 94 101 108 114 121 127 135 142\n 154 144 134 124 114 105 95 88 80 73 67 60 54 48 43 39 35 31 28 26 22 20 17 15 13 11 9 7 6 5 4 4 3 3 2 2 2 2 2 2 2 3 15 29 47 61 72 76 80 86 90 95 98 101 102 101 98 95 90 93 104 110 113 118 120 120 122 122 121 119 117 114 110 104 94 91 91 90 84 70 66 60 48 23 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 8 11 15 19 24 29 34 40 46 53 60 66 73 80 87 94 101 108 114 121 128 135 142\n 157 146 136 126 116 107 98 90 82 76 69 62 57 51 45 41 37 33 30 27 24 21 19 17 15 13 11 8 7 7 6 4 3 4 3 2 2 2 2 2 2 2 2 6 37 55 66 74 80 85 90 95 99 101 103 103 101 97 95 91 96 104 110 114 118 118 120 121 122 123 121 116 114 108 98 94 90 91 90 80 69 61 48 21 4 3 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 8 10 14 18 22 28 33 39 45 52 58 65 72 79 86 92 99 106 113 119 127 133 141\n 154 144 134 124 114 105 96 89 80 75 68 62 56 50 45 41 38 34 30 28 25 22 19 18 16 13 11 10 8 7 6 5 5 4 3 2 2 2 2 2 2 2 2 18 46 59 69 77 83 88 93 97 100 102 104 105 103 98 95 92 93 100 105 111 115 115 115 120 122 123 121 119 114 107 97 96 96 94 93 86 75 63 50 33 5 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 5 8 11 16 19 24 29 35 41 47 53 60 67 74 81 88 94 101 108 115 121 128 135 143\n 155 145 134 124 114 106 97 88 82 75 69 63 57 52 47 43 39 36 32 29 26 23 21 19 17 15 13 11 9 8 7 6 5 4 3 3 2 2 2 2 2 2 4 36 55 68 74 79 85 90 94 97 100 103 105 106 106 102 96 93 92 94 98 104 110 114 114 118 120 121 123 120 115 110 102 99 103 102 100 96 86 75 62 51 30 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 9 13 16 20 25 30 35 41 48 55 60 68 74 82 89 95 102 109 115 122 129 136 143\n 155 144 134 123 114 105 97 89 82 76 69 64 59 53 49 45 41 37 34 31 27 25 23 20 19 16 14 12 11 10 7 7 6 5 3 3 3 2 2 2 2 2 20 41 57 70 81 86 88 91 94 98 101 103 105 107 106 104 98 94 91 90 90 97 101 109 114 117 118 118 121 121 117 113 106 103 106 106 106 102 93 86 78 65 50 31 6 3 3 2 2 2 2 2 1 2 2 2 2 2 2 2 2 3 6 9 13 17 21 26 31 36 42 49 55 61 68 75 82 89 95 102 109 116 123 130 137 144\n 154 144 134 124 114 106 98 90 83 77 71 65 60 55 50 45 42 39 36 33 30 27 24 22 19 17 15 15 13 11 9 8 7 6 5 4 3 2 2 2 2 11 38 49 59 70 81 90 95 97 97 98 100 103 104 106 107 105 101 96 92 88 88 91 95 103 107 109 113 114 118 121 118 117 111 106 109 110 109 104 96 92 87 78 66 49 26 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 4 6 10 14 18 22 27 32 38 43 49 55 62 69 76 83 90 97 103 110 117 124 130 137 145\n 154 145 135 124 115 107 98 90 84 77 72 67 61 56 51 48 44 41 38 34 31 29 26 24 22 20 17 16 15 12 12 10 9 7 5 5 3 3 2 2 2 23 48 63 72 75 82 88 94 100 102 102 101 102 103 105 105 104 102 98 93 90 87 88 91 95 101 104 105 109 113 118 119 117 114 106 110 110 106 102 96 92 88 80 68 51 28 4 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 7 11 15 19 23 28 34 38 45 50 57 63 70 77 84 91 98 105 111 118 125 131 138 146\n 158 149 142 128 119 113 104 96 87 80 75 70 66 60 55 51 47 44 41 38 34 31 29 26 25 23 21 18 16 15 14 13 11 10 8 6 5 3 2 2 3 29 51 67 77 86 90 90 92 96 100 104 106 104 103 103 103 103 102 99 95 90 87 86 88 91 95 100 99 100 103 108 114 113 114 109 107 107 101 98 94 89 84 77 67 51 30 5 3 3 2 1 2 2 2 2 2 2 2 2 2 2 2 5 8 11 14 18 24 28 33 39 45 50 57 63 70 77 84 90 97 104 111 118 124 130 137 145\n 156 157 164 130 127 142 132 123 95 81 77 96 92 84 62 53 70 70 65 52 36 33 44 45 42 39 35 24 27 20 17 16 16 15 9 6 4 3 2 3 18 46 64 76 84 91 98 99 96 96 99 103 107 109 107 104 102 101 100 97 93 87 85 84 86 88 91 93 92 91 93 99 105 106 102 99 98 97 93 91 88 81 73 69 57 40 16 4 3 3 2 2 2 2 2 2 2 2 2 2 1 2 4 7 9 13 17 22 26 31 36 42 47 54 60 67 74 80 87 93 100 107 114 121 127 133 140 147\n 158 158 170 132 128 145 119 123 114 83 80 105 90 79 63 55 79 70 64 73 47 35 52 62 53 57 48 26 33 44 20 22 42 22 9 6 4 3 2 3 32 55 70 80 88 94 100 104 105 100 99 101 105 108 109 108 106 101 99 96 92 87 83 79 81 84 86 87 87 85 84 88 91 93 85 81 81 82 82 82 81 77 66 58 49 31 6 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 5 8 10 14 18 23 28 32 37 43 49 56 61 68 74 81 88 94 102 108 115 121 128 135 141 149\n 159 159 171 133 130 150 120 126 114 85 83 108 83 71 60 57 82 67 51 74 54 36 36 42 56 44 27 23 23 46 43 46 37 14 9 6 4 3 3 13 45 64 76 85 92 97 102 105 108 109 105 102 102 105 107 109 109 107 102 98 93 88 83 79 79 80 81 82 82 82 83 80 76 77 73 66 64 65 65 65 66 64 56 44 34 17 4 3 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 9 12 15 20 24 29 34 39 44 51 58 63 69 76 83 89 96 104 110 117 123 129 136 142 150\n 160 160 173 136 132 152 142 138 111 87 85 111 104 87 62 58 85 82 78 76 47 38 35 36 63 40 26 22 23 31 53 45 18 13 9 7 4 3 3 33 57 72 82 90 96 101 104 108 109 111 112 111 105 103 104 106 108 109 107 102 97 91 84 78 76 79 79 79 78 79 82 78 68 62 58 53 49 47 46 47 47 45 39 26 15 5 3 3 2 2 2 2 2 2 2 2 2 1 2 2 2 4 7 10 14 18 22 26 31 36 42 47 52 59 65 72 78 84 91 98 104 111 118 124 130 138 144 151\n 166 158 178 144 130 154 126 120 130 95 87 107 92 77 64 61 78 83 73 78 49 39 36 36 59 51 27 23 22 24 39 43 17 13 10 7 5 4 10 43 64 78 88 93 100 103 106 108 109 111 112 114 114 111 105 104 105 107 108 107 105 99 91 82 76 76 76 76 77 77 78 76 69 58 49 39 34 29 26 26 25 24 21 10 4 3 3 2 2 2 2 2 2 2 2 1 2 2 2 2 3 5 8 11 14 18 23 27 32 36 42 47 53 60 66 72 79 85 92 98 105 112 118 124 130 137 143 150\n 172 161 177 145 133 156 135 123 127 96 90 109 90 76 69 63 79 75 54 71 61 41 37 37 59 52 28 23 21 23 39 41 17 12 11 7 5 7 35 58 76 87 94 99 103 107 109 109 111 111 111 113 115 116 114 107 104 106 107 107 107 105 101 91 79 74 75 76 76 74 73 71 65 57 46 30 14 7 5 4 3 3 3 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 4 7 10 13 16 20 25 30 34 39 44 50 56 62 68 74 81 88 94 101 107 113 120 126 132 139 145 152\n 167 162 159 140 138 144 138 126 104 94 93 107 104 96 74 64 81 64 52 64 63 42 37 38 61 42 26 23 21 24 45 31 16 11 8 7 8 34 59 76 88 96 102 106 108 110 111 110 110 110 112 112 114 116 117 115 109 106 106 107 107 106 104 99 86 76 74 77 75 73 68 64 59 53 38 14 4 3 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 4 6 9 12 16 20 23 28 33 38 44 48 53 60 66 72 79 85 91 98 105 111 117 123 130 135 142 149 156\n 171 161 153 144 135 128 122 114 106 99 93 90 83 77 72 66 63 60 55 52 48 45 41 37 40 35 27 24 21 21 28 27 15 10 9 8 16 49 72 87 97 104 108 112 113 113 113 112 110 110 109 111 113 114 115 117 118 115 109 107 106 107 106 105 101 94 84 79 77 74 72 64 57 49 39 9 5 4 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 8 10 14 17 21 25 30 34 39 44 50 55 61 67 73 80 87 93 100 106 112 119 125 130 136 142 149 156\n 170 161 152 143 135 128 122 114 107 100 94 88 82 77 71 66 63 60 55 52 48 43 40 36 35 30 26 23 21 20 19 17 14 11 10 19 46 65 85 97 106 111 114 117 117 117 115 113 111 110 109 111 112 114 115 116 117 118 116 110 107 107 107 106 104 101 96 89 80 77 73 64 53 38 21 8 7 7 5 5 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 8 10 14 16 20 24 29 33 38 43 48 53 59 65 72 78 84 91 97 104 110 116 122 128 134 140 147 153 160\n 172 163 154 146 138 131 124 116 109 103 96 90 84 78 73 68 64 60 56 52 48 44 40 37 33 31 27 24 21 19 17 14 13 11 15 41 61 76 89 100 109 114 119 120 121 119 117 115 113 111 110 110 111 113 114 115 116 118 119 117 112 108 107 106 106 105 103 100 92 82 75 63 40 20 11 10 9 9 8 7 6 5 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 5 7 10 13 15 19 22 26 31 35 40 46 50 55 62 67 74 80 86 93 100 106 112 119 124 130 136 142 148 155 162\n 175 166 157 149 141 133 127 119 111 105 99 92 86 80 75 70 66 62 58 53 49 45 41 38 34 32 27 24 21 19 16 14 11 14 34 57 72 85 95 103 110 115 120 122 124 123 121 120 116 114 112 110 110 111 113 113 115 116 119 120 118 112 109 107 107 106 107 105 103 94 77 63 34 15 12 11 13 12 10 9 8 6 4 3 3 3 3 3 2 3 2 2 2 2 2 2 4 6 9 12 15 18 22 25 29 33 37 42 48 53 58 64 69 77 83 90 96 102 108 114 121 126 132 138 144 151 157 163\n 177 168 160 151 143 136 128 121 114 107 101 94 89 82 77 73 68 64 59 55 50 47 44 39 35 32 29 26 22 19 16 15 14 24 48 66 79 90 98 105 109 113 117 122 125 125 124 123 120 117 114 112 111 110 111 111 113 115 118 120 120 120 113 109 109 108 108 108 107 105 95 72 51 22 15 14 14 13 13 12 10 7 4 4 3 3 2 3 2 2 2 2 2 2 2 3 5 8 11 14 18 20 23 27 32 36 41 45 49 56 61 67 73 79 86 91 98 105 111 117 123 129 135 140 146 153 159 166\n 182 173 164 156 147 140 132 125 118 111 104 98 92 87 81 76 71 67 62 57 53 50 45 41 39 34 31 28 24 21 18 16 16 31 54 70 82 91 99 105 109 112 114 117 122 125 127 127 126 122 119 116 114 111 112 111 110 113 116 118 121 123 122 116 110 109 110 111 111 108 106 96 69 44 20 16 16 16 15 13 12 9 7 5 3 3 2 3 2 2 2 2 2 2 4 5 7 10 12 16 18 22 26 29 34 38 42 46 51 57 61 67 73 79 86 92 99 106 112 118 124 130 135 142 148 155 160 166\n 184 175 166 158 151 142 135 127 120 113 107 101 94 89 84 78 73 68 64 60 55 51 47 43 39 35 32 29 25 22 19 18 21 45 63 76 86 94 100 105 109 112 114 116 119 123 126 129 129 127 123 120 117 114 112 111 110 111 114 117 119 122 123 124 118 111 111 114 115 113 109 97 79 56 36 19 18 18 16 14 12 10 8 6 3 3 3 3 3 3 3 2 3 3 5 6 9 12 14 17 20 25 28 32 35 40 44 48 53 59 64 70 76 82 88 95 101 108 114 121 126 132 137 143 149 156 162 169\n 186 176 170 160 153 145 137 130 123 116 110 104 97 91 87 81 75 70 65 61 56 54 48 45 40 38 33 30 27 22 20 18 31 55 70 81 90 97 102 106 111 113 115 116 118 121 122 126 130 131 129 124 121 118 114 112 110 111 112 115 118 122 125 126 125 120 116 116 120 122 121 104 89 82 69 42 31 29 18 15 13 11 9 7 4 4 2 2 2 2 2 3 4 5 7 9 11 14 17 20 23 27 30 33 39 41 47 50 56 61 67 72 79 85 91 98 103 111 117 123 129 135 140 145 152 158 165 171\n 187 178 169 161 153 145 138 131 123 117 110 104 98 93 87 81 76 72 66 61 57 52 48 44 41 37 33 30 26 22 20 26 51 70 80 91 97 102 108 111 115 117 118 119 120 122 121 123 127 133 132 128 125 121 117 113 112 111 112 114 118 122 125 127 128 127 122 120 123 137 135 118 97 90 82 56 31 30 19 16 14 12 9 7 6 5 4 4 4 4 4 5 7 7 9 12 14 17 19 23 26 29 34 37 41 45 50 54 60 65 71 77 83 90 96 102 108 115 121 127 133 138 144 150 156 161 169 176\n 193 183 174 166 157 150 143 135 128 121 114 108 102 96 91 85 79 75 69 65 60 56 52 47 44 39 35 31 27 23 21 32 58 74 86 95 102 108 112 115 119 121 122 124 124 123 122 122 121 126 133 133 130 127 123 119 115 112 112 113 116 120 124 127 129 129 130 130 134 137 141 127 104 96 91 73 43 30 29 19 16 13 12 9 8 7 6 5 5 5 6 7 9 10 12 13 15 19 21 25 28 32 35 38 42 47 51 55 61 66 72 78 85 91 97 104 110 116 122 128 134 139 145 150 157 163 170 178\n 193 184 175 166 159 150 142 136 129 122 115 109 103 97 92 86 80 75 71 65 61 56 52 48 44 40 35 32 28 25 29 57 75 87 97 106 112 116 119 123 125 127 128 128 128 127 126 124 122 122 128 134 134 131 127 122 117 114 114 114 116 121 125 128 131 131 131 138 140 137 143 127 109 97 88 67 39 31 35 20 16 15 13 11 10 8 7 8 8 8 9 10 11 12 14 17 19 22 24 27 31 35 39 42 45 50 54 59 64 70 76 83 90 96 102 108 114 120 127 132 138 143 148 154 160 167 174 182\n 196 187 178 170 161 154 146 138 131 125 118 111 106 101 95 89 84 77 72 67 63 59 54 50 45 41 36 32 29 28 50 72 87 98 107 114 120 123 127 130 132 134 133 132 132 131 128 125 123 121 121 126 132 134 131 126 120 116 115 116 117 121 125 128 133 132 132 142 143 135 143 135 111 93 86 62 31 28 27 19 18 17 15 13 11 11 9 10 10 10 12 13 13 15 17 19 22 25 27 30 34 38 41 45 48 52 57 62 67 73 80 86 92 98 105 111 118 124 130 135 141 146 151 157 163 170 177 185\n 199 190 181 172 164 156 148 140 134 127 120 115 108 103 97 92 86 80 74 70 65 60 55 51 47 43 37 34 31 41 70 87 99 110 118 124 130 132 135 136 139 139 139 138 136 134 132 128 125 122 121 121 125 134 134 129 123 120 118 118 119 120 127 131 135 135 136 145 147 147 143 132 98 82 70 43 31 36 25 21 20 18 16 14 13 13 12 12 13 14 14 15 16 18 19 22 24 27 30 34 37 40 43 47 51 58 59 65 71 77 83 89 96 101 108 115 121 128 134 138 143 148 153 159 166 173 181 187\n 203 194 184 175 167 159 151 144 137 130 123 118 112 106 100 94 89 83 77 72 67 62 57 53 48 44 39 36 40 67 87 101 112 121 127 132 136 140 141 142 144 144 143 142 141 139 136 133 129 125 123 122 122 128 136 134 129 123 120 119 119 120 125 132 136 137 138 146 149 149 143 130 100 84 67 48 44 37 27 22 22 20 19 17 16 15 15 15 15 16 18 19 20 26 23 26 28 31 35 38 41 44 47 51 54 58 64 70 78 82 87 93 99 105 112 118 124 132 138 142 146 151 157 162 168 176 183 190\n 206 198 190 181 172 164 156 149 142 135 128 123 116 110 104 99 92 86 81 75 71 65 61 55 51 46 43 42 59 81 98 112 122 130 135 140 142 144 146 147 147 147 147 146 144 143 142 139 136 132 128 127 125 125 129 137 135 129 123 121 119 119 123 129 136 140 138 142 144 142 142 132 113 98 82 63 52 50 31 27 24 23 21 20 18 17 16 17 18 19 20 22 24 45 47 29 30 35 56 68 72 65 51 53 57 61 72 99 110 112 94 94 100 107 113 119 128 154 169 154 149 152 157 164 170 177 185 192\n 207 200 190 182 173 165 158 150 143 136 130 123 118 111 106 100 94 88 82 76 71 66 61 56 51 48 47 64 86 103 117 127 134 139 144 147 148 150 150 149 148 148 147 146 144 144 143 143 141 137 133 131 128 127 127 135 135 130 124 121 119 119 122 130 138 143 145 147 148 147 140 130 119 104 88 72 58 53 47 30 27 25 23 21 22 20 19 20 21 21 24 26 30 58 42 32 35 66 68 58 66 85 69 59 62 69 105 104 101 125 109 100 105 112 118 126 154 173 176 150 152 156 162 168 175 184 189 196\n 211 202 194 186 177 169 161 154 147 140 134 127 121 115 108 102 96 91 85 79 74 68 63 59 55 52 65 86 105 119 130 137 143 145 150 152 153 153 152 150 149 148 146 142 139 138 139 141 142 140 138 136 133 130 127 129 136 134 127 121 118 118 121 128 138 145 148 151 151 152 147 136 126 114 99 83 67 56 53 46 30 28 26 24 24 22 22 23 24 25 27 29 32 62 45 35 43 74 50 47 52 78 90 64 66 75 111 96 94 125 117 104 109 115 122 149 164 167 179 151 155 159 165 172 179 187 193 199\n 214 205 198 188 180 172 165 158 151 145 137 130 124 118 112 106 100 94 88 82 77 71 66 61 57 65 86 105 121 131 140 145 149 151 154 155 156 155 153 152 150 149 147 143 139 134 130 130 134 139 140 140 136 132 128 127 132 136 130 122 118 117 119 125 137 145 151 155 156 155 152 144 132 123 111 95 78 64 55 53 45 32 29 27 26 25 26 26 26 28 30 31 37 65 47 38 44 75 55 50 53 71 98 68 70 77 107 121 120 135 110 108 113 121 146 161 145 163 181 154 157 162 168 175 182 190 195 203\n 217 209 201 193 185 176 169 162 154 147 141 134 127 122 115 109 102 96 90 83 79 73 68 64 63 85 104 121 133 142 149 152 155 156 157 158 158 158 156 154 152 151 149 147 143 139 133 126 125 128 133 139 139 135 131 129 128 136 133 126 120 118 118 123 134 146 154 156 158 159 157 152 138 129 121 109 94 76 63 54 54 45 33 30 29 28 29 29 30 32 33 35 40 69 50 41 45 70 80 57 57 72 102 72 74 91 119 120 121 135 122 112 118 144 164 146 146 169 185 160 161 166 171 178 185 192 199 209\n 222 213 204 196 189 180 173 165 158 151 144 137 131 125 118 112 106 99 93 87 82 76 70 67 80 104 121 135 145 152 157 159 160 161 161 160 159 159 157 156 154 152 149 149 148 144 140 132 124 121 122 127 135 137 134 130 128 132 136 130 125 121 121 123 132 145 155 159 161 162 160 157 148 132 127 121 110 92 77 63 54 54 45 35 32 32 31 33 33 34 36 39 44 72 52 45 47 52 66 58 62 83 104 75 78 108 117 96 100 120 145 117 128 160 171 172 176 185 192 191 190 170 174 181 188 195 203 219\n 225 217 208 200 192 185 176 169 162 155 148 141 135 129 122 116 108 103 96 91 85 79 73 74 99 120 135 147 156 162 165 166 167 165 164 162 160 158 157 155 152 151 151 150 151 149 145 139 131 123 119 119 124 133 136 131 128 130 138 133 127 124 123 126 131 144 156 161 163 164 163 161 155 141 130 126 121 110 94 77 62 54 55 45 36 34 35 35 37 38 39 42 48 75 55 49 52 54 57 60 65 97 102 77 83 113 118 98 104 125 154 124 128 142 149 156 165 183 195 185 184 174 177 184 192 199 207 231\n 232 223 215 206 199 191 183 176 167 161 154 147 141 134 127 121 114 108 102 96 89 84 77 81 111 129 145 157 166 172 175 175 173 173 170 167 163 158 156 153 151 148 149 150 151 151 150 147 141 132 124 118 118 122 132 135 133 129 136 139 132 128 126 126 132 140 154 162 164 165 166 164 160 154 139 131 127 123 114 98 81 63 54 56 47 39 38 39 39 40 43 45 49 74 70 53 55 58 60 64 70 103 96 80 84 96 127 125 122 142 155 129 127 131 136 142 149 168 193 169 171 175 180 187 194 201 212 234\n 238 227 219 211 203 195 187 180 172 164 158 151 144 138 131 125 118 112 107 99 92 86 82 101 126 145 160 172 179 182 184 184 183 181 179 177 173 167 161 156 151 147 144 147 150 152 152 150 147 139 131 122 118 118 123 134 141 145 144 143 138 132 129 129 131 140 152 162 166 167 167 168 165 161 152 136 132 128 123 112 97 79 61 56 59 46 42 42 43 43 46 49 52 59 59 56 59 62 64 69 92 106 83 83 88 93 109 132 143 145 135 127 131 134 138 145 151 164 183 170 173 179 185 191 198 206 224 236\n 245 229 220 212 205 198 190 182 175 167 160 153 147 140 134 127 121 114 107 102 94 88 99 130 150 164 175 182 187 188 189 189 188 186 184 181 179 175 170 165 157 151 145 143 146 149 151 150 149 143 135 125 119 117 121 130 143 154 153 149 142 137 133 133 135 142 154 165 168 169 170 170 168 165 159 142 135 132 127 119 104 89 71 60 60 59 47 46 46 48 49 52 55 57 58 62 64 67 71 96 105 85 84 87 93 99 105 112 120 124 127 132 136 139 143 150 156 163 168 171 177 184 191 197 204 217 236 236\n 241 238 227 219 211 204 196 189 181 174 166 159 152 147 140 134 127 120 113 106 99 96 116 143 161 173 181 186 191 192 191 192 191 190 187 185 182 180 177 172 168 162 156 147 142 143 147 149 150 148 143 136 127 122 117 122 134 149 156 152 148 142 138 137 136 142 150 162 169 171 172 172 172 171 168 160 143 138 134 126 114 102 89 74 64 64 63 52 50 51 52 56 58 59 62 65 67 71 88 106 93 85 87 91 97 101 107 112 118 123 128 133 138 142 147 152 158 164 169 175 180 186 193 199 207 224 237 235\n 219 247 232 224 217 208 201 193 185 177 171 164 158 151 145 138 132 125 118 111 104 110 138 159 173 181 186 190 191 194 193 193 192 192 190 187 185 182 178 175 172 168 164 158 149 139 140 145 147 149 146 143 136 127 121 119 128 142 157 155 150 146 142 141 140 143 150 160 169 171 173 173 175 175 174 169 155 143 139 133 120 110 100 87 74 66 68 64 55 54 55 58 61 64 66 68 72 76 86 89 86 88 92 96 100 106 112 116 121 126 131 137 142 146 152 157 162 168 173 179 185 191 197 204 214 234 236 234\n 197 244 235 228 219 211 203 195 188 181 174 168 161 155 148 141 135 128 120 114 111 137 158 174 183 188 191 192 193 195 195 193 193 191 190 188 184 181 178 175 172 169 166 162 153 143 136 139 145 147 147 145 142 135 126 120 125 140 156 156 151 146 145 143 144 146 152 161 169 173 175 176 179 180 178 174 163 147 143 138 125 115 106 97 85 74 71 73 62 60 61 62 65 69 71 74 76 80 84 88 91 94 97 101 106 112 117 121 127 131 136 141 147 152 157 163 168 173 179 185 192 197 204 212 232 237 235 230\n 165 227 246 231 224 216 207 201 193 186 179 172 166 159 153 146 139 132 126 120 127 153 168 181 188 193 196 196 196 194 195 195 193 193 190 187 184 181 178 175 172 170 167 164 157 149 138 133 140 145 146 146 146 141 133 125 124 133 154 158 153 149 148 147 148 148 152 159 168 174 176 178 181 183 182 180 172 155 149 145 136 124 116 108 98 86 78 77 77 66 65 67 68 71 75 79 81 84 88 92 95 98 101 106 111 116 120 125 129 135 140 145 150 156 161 167 172 178 184 190 196 202 209 221 236 235 233 231\n 129 191 241 238 229 222 213 206 199 192 184 177 171 165 158 151 144 137 130 125 141 162 176 186 193 197 199 198 197 196 196 195 194 192 190 187 183 179 176 174 171 170 168 164 158 152 144 134 134 140 143 144 146 144 140 132 128 132 149 161 158 153 150 150 150 152 152 156 165 175 178 181 183 185 186 184 178 166 156 152 146 137 125 117 109 99 89 81 82 82 72 72 73 77 79 82 85 90 92 95 101 103 107 111 116 120 125 130 135 139 144 149 155 159 165 171 176 182 189 195 200 206 215 234 237 235 232 225\n 85 155 212 246 234 226 219 211 203 197 190 182 175 169 162 156 149 141 136 132 152 169 181 191 198 201 202 201 199 197 196 195 194 192 190 186 183 178 175 172 171 168 167 164 160 153 146 139 132 134 139 141 143 144 142 136 134 134 144 162 162 158 153 148 149 150 150 153 160 170 179 182 185 188 189 187 182 176 164 159 154 147 138 128 118 109 101 91 83 88 87 77 78 81 83 87 90 92 97 101 104 107 111 115 120 125 129 133 139 143 148 153 159 164 169 175 181 187 194 199 204 211 226 237 236 233 230 186\n 19 94 163 220 244 233 226 218 210 202 197 189 182 175 168 161 155 147 140 137 154 172 184 192 199 203 205 205 203 200 196 194 193 192 190 187 183 179 175 173 170 169 168 167 163 157 151 145 138 129 132 135 137 142 144 140 138 137 140 154 167 165 160 154 152 152 150 148 152 160 176 184 186 190 191 190 188 183 175 167 163 155 148 139 128 119 111 103 94 88 94 93 83 85 87 90 93 96 101 104 108 111 115 119 123 128 132 137 141 146 151 156 162 167 174 178 184 190 196 201 207 215 234 237 235 232 226 162\n 1 68 139 197 244 238 229 222 214 206 200 193 185 178 172 165 157 150 145 142 166 182 190 197 202 205 207 207 205 201 197 193 192 191 190 185 182 177 174 172 171 169 167 169 167 159 152 148 142 132 127 130 131 139 144 141 139 140 142 153 170 170 166 163 163 162 160 156 159 165 178 187 191 194 194 193 191 187 181 173 166 158 152 143 132 123 114 109 101 92 96 102 93 89 92 95 98 102 106 109 113 117 120 125 129 133 137 142 147 152 156 162 166 173 178 185 191 196 202 207 214 232 238 236 232 228 169 84\n 1 3 73 143 200 243 237 230 222 215 206 200 193 185 178 171 164 157 150 147 166 184 192 198 203 206 208 208 207 204 199 194 191 190 189 186 183 178 175 172 171 171 172 171 171 167 161 153 148 142 128 121 124 129 140 143 140 140 142 145 164 174 173 169 167 166 166 161 157 160 172 187 192 196 197 196 195 192 189 182 175 166 157 151 143 131 122 115 110 102 96 102 109 103 97 99 102 105 109 113 116 120 124 128 133 136 140 145 150 155 160 165 170 175 181 187 193 199 203 210 220 237 236 235 231 211 138 37\n 2 2 27 97 162 221 243 234 228 220 212 205 198 191 183 176 168 162 154 152 171 187 195 200 205 207 208 209 209 205 201 195 191 190 188 185 183 180 176 173 171 170 171 170 173 171 167 161 153 148 136 117 117 120 133 142 140 140 144 144 158 176 178 175 172 171 169 165 160 160 169 186 196 200 200 199 197 196 194 189 181 175 166 156 149 139 129 121 117 112 102 104 112 116 105 104 106 109 112 117 120 124 128 132 136 141 145 149 154 159 164 169 174 180 186 193 197 202 208 215 234 238 234 233 224 160 74 4\n 2 1 1 49 117 180 229 242 233 226 219 210 204 196 188 182 173 166 159 157 177 191 198 203 206 208 209 209 209 208 203 197 191 189 187 184 183 181 178 175 172 172 169 168 171 173 169 163 159 154 145 124 111 114 124 139 140 142 143 142 152 174 182 181 177 174 173 169 164 161 167 185 199 204 204 201 200 199 199 195 188 183 175 164 154 146 137 129 122 118 110 109 114 122 122 111 111 113 117 121 125 129 133 137 141 145 149 154 159 163 167 173 179 185 191 196 201 206 214 229 237 237 233 228 180 103 4 4\n 1 1 1 17 84 149 207 243 238 230 222 214 207 200 192 185 177 168 162 168 186 196 202 205 208 210 210 210 210 208 205 198 190 186 184 183 182 181 180 178 175 173 166 166 168 172 170 163 158 156 150 131 110 111 119 137 140 141 142 142 152 174 187 186 182 178 175 172 165 162 167 185 203 207 207 203 203 203 202 197 192 187 183 172 158 147 141 133 127 123 117 116 119 127 131 123 118 120 123 127 130 134 137 142 146 151 154 159 164 169 173 179 185 191 196 201 206 213 228 237 236 233 229 189 111 12 3 3\n 1 1 1 1 34 100 162 218 243 236 229 221 212 204 197 189 181 173 167 176 192 200 205 208 210 212 211 211 210 210 208 205 197 189 184 182 182 182 182 180 178 176 168 168 166 168 171 168 160 153 152 143 120 107 112 134 139 141 142 140 148 169 187 191 188 184 180 176 170 164 166 179 201 209 210 207 205 206 206 202 196 190 188 181 169 153 145 141 135 129 123 123 121 130 138 139 128 125 128 131 135 138 143 146 151 155 159 164 168 173 179 185 191 196 200 206 211 224 237 237 234 230 200 129 37 3 4 3\n 1 1 1 1 1 37 101 162 215 241 238 229 221 212 203 196 188 180 173 177 194 203 207 211 212 213 213 213 212 211 211 209 206 199 192 185 185 182 182 182 180 179 175 173 169 168 168 171 167 157 149 149 138 113 107 123 138 141 142 140 143 162 182 195 196 192 186 181 177 170 166 171 191 210 212 210 207 208 208 207 201 196 191 190 183 171 154 145 142 138 130 125 127 127 139 146 147 133 132 135 138 141 145 149 153 157 162 167 172 177 182 188 195 199 203 209 217 234 238 235 231 224 166 89 6 4 4 3\n 1 1 1 1 1 4 68 132 186 230 242 233 226 215 207 199 191 183 177 189 202 208 212 213 215 215 215 215 214 214 212 211 208 204 199 194 188 184 183 182 180 180 175 175 172 169 168 170 170 162 148 144 141 117 109 124 139 143 143 140 146 167 185 198 202 197 193 187 182 174 169 172 191 212 215 211 208 210 212 210 204 200 193 193 190 181 165 150 145 142 133 128 133 133 144 151 154 143 138 140 143 147 151 155 159 163 168 173 178 184 189 195 200 204 210 217 235 238 236 231 221 164 90 5 4 3 3 3\n 1 2 1 1 1 1 14 79 140 193 235 240 232 222 213 204 196 187 181 193 205 211 215 217 218 219 219 218 217 216 215 213 210 206 203 200 196 191 188 184 183 180 180 178 176 173 170 169 171 169 156 144 141 128 112 120 140 143 143 143 146 165 186 198 206 205 199 194 187 179 172 173 187 213 217 215 211 212 214 215 211 205 198 195 193 190 181 163 149 145 139 133 139 137 146 156 160 159 145 145 147 151 155 159 163 168 173 178 184 189 196 200 204 210 216 233 238 237 232 225 176 106 10 3 3 3 3 3\n"
  },
  {
    "path": "examples/data/west0479.mat",
    "content": "# Created by Octave 5.2.0, Thu Jun 04 22:49:15 2020 EDT <jwe@devnull>\n# name: west0479\n# type: sparse matrix\n# nnz: 1888\n# rows: 479\n# columns: 479\n25 1 1\n31 1 -0.037648130000000002\n87 1 -0.34423959999999998\n26 2 1\n31 2 -0.024522619999999998\n88 2 -0.3737086\n27 3 1\n31 3 -0.036613039999999999\n89 3 -0.83693790000000001\n28 4 130\n29 4 -2.433767\n29 5 1\n30 5 -1.6140909999999999\n30 6 1.6140909999999999\n31 6 -0.21873210000000001\n87 6 -1\n88 6 -1\n89 6 -1\n32 7 -1.138352\n43 7 0.036694280000000003\n111 7 0.099316360000000006\n112 7 0.099316360000000006\n113 7 0.099316360000000006\n33 8 -0.5\n43 8 0.016117289999999999\n111 8 0.087245760000000006\n34 9 -0.36119180000000001\n43 9 0.01164286\n112 9 0.1050415\n35 10 -0.3218876\n43 10 0.01037591\n113 10 0.1404166\n36 11 -0.43624160000000001\n37 11 -0.76804249999999996\n38 11 -0.14302790000000001\n39 11 -0.15938859999999999\n37 12 1\n43 12 -0.048560819999999998\n111 12 -0.2628684\n38 13 1\n43 13 -0.030925950000000001\n112 13 -0.27901280000000001\n39 14 1\n43 14 -0.046123589999999999\n113 14 -0.62418819999999997\n40 15 5.2824359999999997\n42 15 -0.61239209999999999\n41 16 0.2886822\n42 16 -0.2163815\n42 17 1.3287739999999999\n43 17 -0.36946859999999998\n111 17 -1\n112 17 -1\n113 17 -1\n2 18 48.176470000000002\n8 18 -1\n11 18 -3.3474840000000003e-05\n3 19 83.5\n9 19 -1\n12 19 -4.1365390000000001e-05\n4 20 171.94120000000001\n10 20 -1\n13 20 -8.4843450000000005e-05\n5 21 96.651380000000003\n8 21 2.5\n11 21 3.3474840000000003e-05\n6 22 168.2706\n9 22 2.5\n12 22 4.1365390000000001e-05\n7 23 347.5872\n10 23 2.5\n13 23 8.4843450000000005e-05\n8 24 1\n17 24 -0.1106967\n27 24 1.605232\n9 25 1\n17 25 -0.089808520000000003\n10 26 1\n17 26 -0.15173690000000001\n11 27 1.0104550000000001\n18 27 -0.5\n12 28 1.005978\n18 28 -0.29999999999999999\n13 29 1.002885\n18 29 -0.20000000000000001\n14 30 1\n17 30 -0.1811855\n15 31 1\n17 31 -0.24002390000000001\n16 32 1\n17 32 -0.22654840000000001\n17 33 1\n19 33 -1\n30 33 1.5\n42 33 0.5\n18 34 1\n20 34 -316220\n23 34 -12323.690000000001\n24 34 -1\n30 34 -35226.800000000003\n41 34 18449.02\n19 35 5.2983390000000004\n21 35 0.0024526869999999998\n20 36 1080.8589999999999\n21 36 -0.2050215\n21 37 0.14419199999999999\n22 37 63.05986\n30 37 -0.1159299\n22 38 -18449.02\n24 38 0.84533389999999997\n40 38 -18449.02\n41 38 -15595.58\n23 39 1\n30 39 0.20204929999999999\n42 39 -0.88547100000000001\n24 40 0.0001000234\n30 40 2.4483389999999998\n42 40 0.81611299999999998\n68 41 1\n74 41 -0.0002278669\n99 41 -0.26243949999999999\n69 42 1\n74 42 -0.00041887629999999999\n100 42 -0.32161960000000001\n70 43 1\n74 43 -0.001576933\n101 43 -0.72647609999999996\n71 44 300\n72 44 -2.8518910000000002\n72 45 1\n73 45 -0.28701589999999999\n73 46 0.28701589999999999\n74 46 -0.0043413219999999999\n99 46 -1\n100 46 -1\n101 46 -1\n75 47 -1.138352\n86 47 0.042002860000000003\n123 47 0.9414806\n124 47 0.9414806\n125 47 0.9414806\n76 48 -0.3218876\n86 48 0.011877\n123 48 1.3310949999999999\n77 49 -0.36119180000000001\n86 49 0.013327240000000001\n124 49 0.99575290000000005\n78 50 -0.5\n86 50 0.01844898\n125 50 0.82705600000000001\n79 51 -1\n80 51 -19.239999999999998\n81 51 -3.8029999999999999\n82 51 -9.4809999999999999\n80 52 1\n86 52 -0.00088757840000000001\n123 52 -0.099473919999999993\n81 53 1\n86 53 -0.0013313680000000001\n124 53 -0.099473919999999993\n82 54 1\n86 54 -0.0022189459999999999\n125 54 -0.099473919999999993\n83 55 1.177613\n85 55 -3.1089630000000001\n84 56 0.99194249999999995\n85 56 -2.640056\n85 57 3.1921119999999998\n86 57 -0.044613630000000001\n123 57 -1\n124 57 -1\n125 57 -1\n45 58 109.86879999999999\n51 58 -1\n54 58 -3.3081099999999997e-05\n46 59 191.38460000000001\n52 59 -1\n55 59 -4.1084670000000001e-05\n47 60 395.4796\n53 60 -1\n56 60 -8.456383e-05\n48 61 221.73390000000001\n51 61 2.5\n54 61 3.3081099999999997e-05\n49 62 387.00920000000002\n52 62 2.5\n55 62 4.1084670000000001e-05\n50 63 800.81650000000002\n53 63 2.5\n56 63 8.456383e-05\n51 64 1\n60 64 -0.0091702290000000002\n52 65 1\n60 65 -0.046441099999999999\n53 66 1\n60 66 -0.48999189999999998\n54 67 1.0045299999999999\n61 67 -0.20000000000000001\n55 68 1.002591\n61 68 -0.29999999999999999\n56 69 1.00125\n61 69 -0.5\n57 70 1\n60 70 -0.037500529999999997\n58 71 1\n60 71 -0.124143\n59 72 1\n60 72 -0.29275319999999999\n60 73 1\n62 73 -1\n73 73 0.18537329999999999\n85 73 0.06179109\n61 74 1\n63 74 -316220\n66 74 -16364.190000000001\n67 74 -1\n73 74 -4696.7820000000002\n84 74 131.85400000000001\n62 75 22.12913\n64 75 0.95375259999999995\n63 76 2494.29\n64 76 -1.021587\n64 77 0.88782810000000001\n65 77 1.0400419999999999\n73 77 -2.640056\n65 78 -131.85400000000001\n67 78 0.0080574700000000006\n83 78 -131.85400000000001\n84 78 -1.0624089999999999\n66 79 1\n73 79 0.1016426\n85 79 -0.06179109\n67 80 0.0076452569999999999\n73 80 23.098949999999999\n85 80 7.699649\n31 81 1\n244 81 1\n43 82 1\n1 83 1\n17 83 -3.850231\n18 83 -8.4599350000000005e-05\n31 83 2.0159099999999999\n35 83 1\n43 83 1.596171\n243 83 -0.78975119999999999\n74 84 1\n388 84 0.88175619999999999\n86 85 1\n44 86 1\n60 86 -2.7937599999999998\n61 86 -8.4458229999999999e-05\n74 86 2.0156649999999998\n78 86 1\n86 86 1.5939939999999999\n387 86 -0.96191499999999996\n385 87 0.002424669\n386 87 0.030362779999999999\n387 87 0.67304509999999995\n388 87 1.45936\n96 88 0.016896609999999999\n97 88 0.034848030000000002\n98 88 -0.060080179999999997\n120 88 -0.55527170000000003\n121 88 -0.47703980000000001\n122 88 -0.1858293\n141 88 -1\n142 88 -1\n143 88 -1\n185 88 -55.188569999999999\n186 88 -95.676860000000005\n187 88 -215.83770000000001\n389 88 1\n438 88 1\n439 88 1\n440 88 1\n441 88 1\n442 88 1\n443 88 1\n450 88 -0.0018907559999999999\n451 88 -0.0015311400000000001\n452 88 -0.001013726\n455 88 2.5\n456 88 26.063700000000001\n458 88 1\n459 88 -1.5\n461 88 -9.6031809999999993\n462 88 -9.4541850000000007\n463 88 -9.4376809999999995\n464 88 -48.295720000000003\n472 88 0.90759219999999996\n473 88 -4.3759670000000002\n474 88 -8.997992\n475 88 -8.8819579999999991\n476 88 1\n182 89 1\n183 89 1\n184 89 1\n391 89 1\n455 89 -1\n456 89 -26.063700000000001\n458 89 -1\n468 89 1\n388 90 -1.45936\n467 90 1\n479 91 1\n203 92 -1\n204 92 -1\n205 92 -1\n209 92 1\n210 92 1\n211 92 1\n382 92 56.953099999999999\n385 92 0.70583249999999997\n437 92 1\n453 92 -0.64913719999999997\n454 92 -3.2948409999999999e-05\n467 92 0.53807479999999996\n469 92 1\n479 92 0.082471119999999995\n203 93 -1\n204 93 -1\n205 93 -1\n209 93 1\n210 93 1\n211 93 1\n383 93 11.58384\n386 93 0.70583249999999997\n437 93 1\n453 93 -1.021542\n454 93 -4.0990330000000002e-05\n467 93 -0.36302479999999998\n470 93 1\n479 93 0.069522609999999999\n203 94 -1\n204 94 -1\n205 94 -1\n209 94 1\n210 94 1\n211 94 1\n384 94 0.3209631\n387 94 0.70583249999999997\n437 94 1\n453 94 -2.049007\n454 94 -8.4470029999999998e-05\n467 94 0.91353620000000002\n471 94 1\n479 94 0.83976379999999995\n241 95 0.55083519999999997\n242 95 0.4489223\n243 95 0.0002425203\n244 95 0.40528330000000001\n108 96 -0.067276619999999995\n109 96 -0.15700610000000001\n110 96 -0.097475699999999998\n132 96 -0.25060070000000001\n133 96 -0.2802617\n134 96 0.1008491\n245 96 -1\n395 96 1\n396 96 1\n397 96 1\n398 96 1\n399 96 1\n400 96 1\n407 96 -0.0028636019999999998\n408 96 -0.0023162590000000002\n409 96 -0.00153089\n412 96 2.5\n413 96 11.5878\n415 96 1\n416 96 -1.101224\n418 96 -1.3644320000000001\n419 96 -1.2188209999999999\n420 96 -1.2108589999999999\n421 96 -34.621049999999997\n429 96 0.60313589999999995\n430 96 -0.59963840000000002\n431 96 -1.403392\n432 96 -1.3703860000000001\n433 96 1\n246 97 1\n412 97 -1\n413 97 -11.5878\n415 97 -1\n425 97 1\n244 98 -0.40528330000000001\n424 98 1\n436 99 1\n160 100 -0.85938400000000004\n161 100 -0.773339\n162 100 -0.79517400000000005\n238 100 -1\n241 100 1\n394 100 1\n410 100 -1.623659\n411 100 -3.3032779999999999e-05\n424 100 3.5720350000000001\n426 100 1\n436 100 0.92435319999999999\n160 101 -1.171821\n161 101 -1.277352\n162 101 -1.250508\n239 101 -1\n242 101 1\n394 101 1\n410 101 -2.4602889999999999\n411 101 -4.1050809999999997e-05\n424 101 -2.1785329999999998\n427 101 1\n436 101 0.65098420000000001\n160 102 -2.3280470000000002\n161 102 -2.4161549999999998\n162 102 -2.5121660000000001\n240 102 -1\n243 102 1\n394 102 1\n410 102 -4.7536199999999997\n411 102 -8.45305e-05\n424 102 6.1671399999999998\n428 102 1\n436 102 3.3966910000000001\n241 103 0.043736570000000002\n242 103 0.57396460000000005\n243 103 0.15834899999999999\n244 103 0.18781249999999999\n253 103 -0.044344130000000002\n254 103 -0.58193779999999995\n255 103 -0.16054869999999999\n256 103 -1\n135 104 -1\n136 104 -1\n137 104 -1\n151 104 -62.680900000000001\n152 104 -123.89\n153 104 -464.35550000000001\n245 104 1\n248 104 -0.051646549999999999\n249 104 -0.32417620000000003\n148 105 1\n149 105 1\n150 105 1\n247 105 1\n244 106 -0.18781249999999999\n248 106 1\n256 106 1\n249 107 1\n147 108 1\n169 108 -1\n170 108 -1\n171 108 -1\n175 108 1\n176 108 1\n177 108 1\n238 108 9.7738750000000003\n241 108 0.77605020000000002\n248 108 7.2528309999999996\n249 108 0.78041000000000005\n253 108 -0.78683060000000005\n147 109 1\n169 109 -1\n170 109 -1\n171 109 -1\n175 109 1\n176 109 1\n177 109 1\n239 109 0.60698209999999997\n242 109 0.77605020000000002\n248 109 -2.3895080000000002\n249 109 0.68493979999999999\n254 109 -0.78683060000000005\n147 110 1\n169 110 -1\n170 110 -1\n171 110 -1\n175 110 1\n176 110 1\n177 110 1\n240 110 0.001188564\n243 110 0.77605020000000002\n248 110 11.55883\n249 110 2.2026439999999998\n255 110 -0.78683060000000005\n363 111 -0.17051479999999999\n364 111 -0.43429630000000002\n365 111 -0.26674209999999998\n366 111 -2.609302\n385 111 0.1956447\n386 111 0.49830160000000001\n387 111 0.30605369999999998\n388 111 0.42239599999999999\n215 112 1\n216 112 1\n217 112 1\n218 112 1\n219 112 1\n220 112 1\n227 112 -0.0018907559999999999\n228 112 -0.0015311400000000001\n229 112 -0.001013726\n232 112 2.5\n233 112 16.672409999999999\n235 112 1\n236 112 -1.5\n389 112 -1\n392 112 -0.46212130000000001\n393 112 -0.1234962\n232 113 -1\n233 113 -16.672409999999999\n235 113 -1\n368 113 -1\n369 113 -1\n390 113 1\n366 114 2.609302\n388 114 -0.42239599999999999\n392 114 1\n393 115 1\n181 116 1\n194 116 -0.58697619999999995\n195 116 -0.50651550000000001\n196 116 -0.5139918\n230 116 -1.0366850000000001\n231 116 -3.2948409999999999e-05\n363 116 -0.87155309999999997\n382 116 -1\n385 116 1\n392 116 2.63998\n393 116 0.55742069999999999\n181 117 1\n194 117 -0.80016370000000003\n195 117 -0.83640899999999996\n196 117 -0.8081026\n230 117 -1.6376949999999999\n231 117 -4.0990330000000002e-05\n364 117 -0.87155309999999997\n383 117 -1\n386 117 1\n392 117 -1.7736780000000001\n393 117 0.40754220000000002\n181 118 1\n194 118 -1.5893889999999999\n195 118 -1.5818110000000001\n196 118 -1.6231180000000001\n230 118 -3.205686\n231 118 -8.4470029999999998e-05\n365 118 -0.87155309999999997\n384 118 -1\n387 118 1\n392 118 4.4676090000000004\n393 118 2.2475290000000001\n93 119 -1\n96 119 -1\n248 119 -0.40421560000000001\n262 119 -0.1818777\n284 119 -0.1563455\n306 119 -0.15456990000000001\n328 119 -0.1521778\n350 119 -0.091905799999999996\n372 119 -0.0078705370000000004\n94 120 -1\n97 120 -1\n248 120 -1.8091710000000001\n262 120 -3.1896550000000001\n284 120 -3.3490190000000002\n306 120 -3.358644\n328 120 -3.3085849999999999\n350 120 -1.96787\n372 120 -0.11333559999999999\n95 121 -1\n98 121 -1\n248 121 -2.4566020000000002\n262 121 -4.1011280000000001\n284 121 -4.2908920000000004\n306 121 -4.3026030000000004\n328 121 -4.2541469999999997\n350 121 -2.9523890000000002\n372 121 -1.157365\n93 122 -0.0081214960000000006\n96 122 -0.016896609999999999\n248 122 -0.0045387600000000002\n262 122 -0.00217052\n284 122 -0.0018740689999999999\n306 122 -0.0018533180000000001\n328 122 -0.0018248369999999999\n350 122 -0.001106561\n372 122 -0.0001054494\n94 123 -0.016749989999999999\n97 123 -0.034848030000000002\n248 123 -0.041896919999999997\n262 123 -0.078506679999999995\n284 123 -0.082793510000000001\n306 123 -0.083055320000000002\n328 123 -0.081826380000000004\n350 123 -0.048866050000000001\n372 123 -0.0031317319999999999\n95 124 -0.028878029999999999\n98 124 -0.060080179999999997\n248 124 -0.098082240000000001\n262 124 -0.17402809999999999\n284 124 -0.18288550000000001\n306 124 -0.1834374\n328 124 -0.18139140000000001\n350 124 -0.12639719999999999\n372 124 -0.055136770000000002\n105 125 -1\n108 125 -1\n264 125 -0.76362319999999995\n286 125 -0.5413211\n308 125 -0.52907530000000003\n330 125 -0.52832599999999996\n352 125 -0.52965340000000005\n374 125 -0.59901059999999995\n392 125 -0.57467679999999999\n106 126 -1\n109 126 -1\n264 126 -1.4679789999999999\n286 126 -1.289806\n308 126 -1.279992\n330 126 -1.279385\n352 126 -1.2801739999999999\n374 126 -1.3601430000000001\n392 126 -0.71491899999999997\n107 127 -1\n110 127 -1\n264 127 -0.0043708569999999997\n286 127 -0.0039541009999999998\n308 127 -0.0039318030000000002\n330 127 -0.0039476679999999997\n352 127 -0.0047490229999999998\n374 127 -0.072455389999999995\n392 127 -1.6023639999999999\n105 128 -0.1122933\n108 128 -0.067276619999999995\n264 128 -0.054601370000000003\n286 128 -0.038877219999999997\n308 128 -0.03800866\n330 128 -0.037958989999999998\n352 128 -0.038208859999999997\n374 128 -0.048085490000000002\n392 128 -0.05817862\n106 129 -0.2620633\n109 129 -0.15700610000000001\n264 129 -0.24496080000000001\n286 129 -0.2161806\n308 129 -0.21459739999999999\n330 129 -0.21451909999999999\n352 129 -0.21552299999999999\n374 129 -0.25480999999999998\n392 129 -0.16890749999999999\n107 130 -0.1626995\n110 130 -0.097475699999999998\n264 130 -0.00045281759999999999\n286 130 -0.00041145290000000001\n308 130 -0.00040925029999999999\n330 130 -0.0004109467\n352 130 -0.00049637369999999995\n374 130 -0.0084271850000000002\n392 130 -0.2350352\n117 131 -1\n120 131 -1\n249 131 -0.069702840000000002\n263 131 -0.019243320000000001\n285 131 -0.01583793\n307 131 -0.01561791\n329 131 -0.01558321\n351 131 -0.01471856\n373 131 -0.0057599519999999996\n118 132 -1\n121 132 -1\n249 132 -0.74171359999999997\n263 132 -0.80234939999999999\n285 132 -0.80658470000000004\n307 132 -0.80682860000000001\n329 132 -0.80550310000000003\n351 132 -0.74926979999999999\n373 132 -0.19719700000000001\n119 133 -1\n122 133 -1\n249 133 -0.51275979999999999\n263 133 -0.52522530000000001\n285 133 -0.52614130000000003\n307 133 -0.52622449999999998\n329 133 -0.52730270000000001\n351 133 -0.57231860000000001\n373 133 -1.025242\n117 134 -0.46575929999999999\n120 134 -0.96900310000000001\n249 134 -0.044884880000000002\n263 134 -0.01317012\n285 134 -0.01088739\n307 134 -0.010739240000000001\n329 134 -0.01071655\n351 134 -0.01016303\n373 134 -0.0044257189999999998\n118 135 -0.57440230000000003\n121 135 -1.195033\n249 135 -0.58903419999999995\n263 135 -0.67721739999999997\n285 135 -0.68380180000000002\n307 135 -0.68420530000000002\n329 135 -0.68315610000000004\n351 135 -0.63804399999999994\n373 135 -0.18686159999999999\n119 136 -0.2292285\n122 136 -0.47690549999999998\n249 136 -0.1625065\n263 136 -0.17691419999999999\n285 136 -0.1780062\n307 136 -0.17808560000000001\n329 136 -0.17846999999999999\n351 136 -0.19449250000000001\n373 136 -0.38770260000000001\n129 137 -1\n132 137 -1\n265 137 -0.34272789999999997\n287 137 -0.2911376\n309 137 -0.2876937\n331 137 -0.28748889999999999\n353 137 -0.28823179999999998\n375 137 -0.30269869999999999\n393 137 -0.17507890000000001\n130 138 -1\n133 138 -1\n265 138 -1.0623339999999999\n287 138 -1.118506\n309 138 -1.1222529999999999\n331 138 -1.122512\n353 138 -1.1232850000000001\n375 138 -1.1082339999999999\n393 138 -0.35118640000000001\n131 139 -1\n134 139 -1\n265 139 -0.0023999820000000002\n287 139 -0.00260173\n309 139 -0.0026156270000000001\n331 139 -0.0026280330000000001\n353 139 -0.0031617350000000002\n375 139 -0.044793810000000003\n393 139 -0.59723090000000001\n129 140 -2.0182530000000001\n132 140 -1.209166\n265 140 -0.44044889999999998\n287 140 -0.3758029\n309 140 -0.37146430000000003\n331 140 -0.37124049999999997\n353 140 -0.37371090000000001\n375 140 -0.43672879999999997\n393 140 -0.31856279999999998\n130 141 -2.5626880000000001\n133 141 -1.535345\n265 141 -1.7335130000000001\n287 141 -1.833245\n309 141 -1.839915\n331 141 -1.840541\n353 141 -1.849286\n375 141 -2.0302660000000001\n393 141 -0.81137049999999999\n131 142 -0.92554289999999995\n134 142 -0.55450670000000002\n265 142 -0.0014144089999999999\n287 142 -0.001540086\n309 142 -0.0015487579999999999\n331 142 -0.0015562740000000001\n353 142 -0.001879925\n375 142 -0.029637400000000001\n393 142 -0.49833870000000002\n135 143 -1.4338919999999999\n141 143 -2.1577039999999998\n266 143 -1.523971\n288 143 -1.530708\n310 143 -1.531148\n332 143 -1.5313159999999999\n354 143 -1.537533\n376 143 -1.710928\n136 144 -0.94320599999999999\n142 144 -1.4193260000000001\n267 144 -1.0024599999999999\n289 144 -1.006891\n311 144 -1.0071810000000001\n333 144 -1.0072909999999999\n355 144 -1.0113810000000001\n377 144 -1.1254390000000001\n137 145 -0.59645269999999995\n143 145 -0.89753530000000004\n268 145 -0.63392269999999995\n290 145 -0.63672519999999999\n312 145 -0.63690829999999998\n334 145 -0.63697809999999999\n356 145 -0.63956420000000003\n378 145 -0.71169090000000002\n135 146 -1\n141 146 -1\n266 146 -1\n288 146 -1\n310 146 -1\n332 146 -1\n354 146 -1\n376 146 -1\n136 147 -1\n142 147 -1\n267 147 -1\n289 147 -1\n311 147 -1\n333 147 -1\n355 147 -1\n377 147 -1\n137 148 -1\n143 148 -1\n268 148 -1\n290 148 -1\n312 148 -1\n334 148 -1\n356 148 -1\n378 148 -1\n138 149 -1\n148 149 1\n238 149 0.55083519999999997\n139 150 -1\n149 150 1.6474949999999999\n239 150 0.73959730000000001\n140 151 -1\n150 151 841.35159999999996\n240 151 0.2040448\n144 152 -1\n182 152 1\n382 152 0.1956447\n145 153 -1\n183 153 1\n383 153 0.49830160000000001\n146 154 -1\n184 154 3.1156220000000001\n384 154 0.95354779999999995\n395 155 66.224919999999997\n401 155 -1\n404 155 -3.3282569999999997e-05\n396 156 115.06229999999999\n402 156 -1\n405 156 -4.122831e-05\n397 157 237.33869999999999\n403 157 -1\n406 157 -8.4706899999999994e-05\n398 158 133.245\n401 158 2.5\n404 158 3.3282569999999997e-05\n399 159 232.26390000000001\n402 159 2.5\n405 159 4.122831e-05\n400 160 480.18209999999999\n403 160 2.5\n406 160 8.4706899999999994e-05\n160 161 -0.47337899999999999\n401 161 1\n410 161 -0.2116876\n161 162 -0.57343169999999999\n402 162 1\n410 162 -0.31667149999999999\n162 163 -0.00060925110000000003\n403 163 1\n410 163 -3.511874e-07\n163 164 -4575.0039999999999\n404 164 1.0075620000000001\n411 164 -0.55083519999999997\n164 165 -3681.4160000000002\n405 165 1.004324\n411 165 -0.4489223\n165 166 -1787.818\n406 166 1.002087\n411 166 -0.0002425203\n160 167 -0.52605639999999998\n161 167 -0.42598229999999998\n407 167 1\n410 167 -0.47048839999999997\n160 168 -0.00056459870000000005\n162 168 -0.4380098\n408 168 1\n410 168 -0.00050495930000000002\n161 169 -0.00058596669999999996\n162 169 -0.56138089999999996\n409 169 1\n410 169 -0.00064718760000000001\n163 170 -1\n164 170 -1\n165 170 -1\n410 170 1\n412 170 -1\n423 170 0.061444209999999999\n435 170 0.0204814\n157 171 -1\n163 171 4124.0600000000004\n164 171 4124.0600000000004\n165 171 4124.0600000000004\n411 171 1\n413 171 -316220\n416 171 -20034.240000000002\n417 171 -1\n423 171 -2625.6570000000002\n434 171 222.12899999999999\n412 172 18.737269999999999\n414 172 0.94488159999999999\n413 173 1494.367\n414 173 -1.02078\n158 174 -0.99186010000000002\n163 174 -17.922339999999998\n164 174 -17.922339999999998\n165 174 -17.922339999999998\n414 174 0.86282899999999996\n415 174 1.0497190000000001\n423 174 -0.73414950000000001\n157 175 0.0081398600000000005\n415 175 -222.12899999999999\n417 175 0.0081398600000000005\n433 175 -222.12899999999999\n434 175 -1.8080989999999999\n163 176 -1.0913280000000001\n164 176 -1.629397\n165 176 -1.4448529999999999\n416 176 1\n423 176 0.047364059999999999\n435 176 -0.027898139999999998\n417 177 0.0045385340000000003\n423 177 7.5792400000000004\n435 177 2.5264129999999998\n148 178 -1\n178 178 -1\n149 179 -1\n179 179 -1\n150 180 -1\n180 180 -1\n148 181 1.0266459999999999\n166 181 -1\n149 182 1.0737239999999999\n167 182 -1\n150 183 1.2081470000000001\n168 183 -1\n148 184 -1\n154 184 -1\n149 185 -1\n155 185 -1\n150 186 -1\n156 186 -1\n215 187 99.149730000000005\n221 187 -1\n224 187 -3.311398e-05\n216 188 172.6396\n222 188 -1\n225 188 -4.1108120000000002e-05\n217 189 356.63979999999998\n223 189 -1\n226 189 -8.4587179999999994e-05\n218 190 200.0008\n221 190 2.5\n224 190 3.311398e-05\n219 191 349.00330000000002\n222 191 2.5\n225 191 4.1108120000000002e-05\n220 192 722.06780000000003\n223 192 2.5\n226 192 8.4587179999999994e-05\n194 193 -0.1148388\n221 193 1\n230 193 -0.011645920000000001\n195 194 -0.41678389999999998\n222 194 1\n230 194 -0.17006160000000001\n196 195 -0.49676140000000002\n223 195 1\n230 195 -0.2436893\n197 196 -5276.8620000000001\n224 196 1.0050250000000001\n231 196 -0.1956447\n198 197 -4241.5910000000003\n225 197 1.002874\n231 197 -0.49830160000000001\n199 198 -2058.2939999999999\n226 198 1.001387\n231 198 -0.30605369999999998\n194 199 -0.39872279999999999\n195 199 -0.099097089999999999\n227 199 1\n230 199 -0.080869759999999999\n194 200 -0.48643839999999999\n196 200 -0.1005598\n228 200 1\n230 200 -0.098660410000000004\n195 201 -0.48411900000000002\n196 201 -0.4026788\n229 201 1\n230 201 -0.39507300000000001\n197 202 -1\n198 202 -1\n199 202 -1\n230 202 1\n232 202 -1\n191 203 -1\n197 203 3297.623\n198 203 3297.623\n199 203 3297.623\n231 203 1\n233 203 -316220\n236 203 -18966.66\n237 203 -1\n232 204 22.66987\n234 204 0.95486020000000005\n233 205 2248.7060000000001\n234 205 -1.0206550000000001\n192 206 -0.99229509999999999\n197 206 -21.898569999999999\n198 206 -21.898569999999999\n199 206 -21.898569999999999\n234 206 0.89000959999999996\n235 206 1.0392049999999999\n191 207 0.0077048969999999996\n235 207 -146.1362\n237 207 0.0077048969999999996\n197 208 -0.65890519999999997\n198 208 -1.1064970000000001\n199 208 -1.000909\n236 208 1\n237 209 0.0068956570000000003\n182 210 -1\n212 210 -1\n183 211 -1\n213 211 -1\n184 212 -1\n214 212 -1\n182 213 1\n200 213 -1\n183 214 1.0226759999999999\n201 214 -1\n184 215 1.091418\n202 215 -1\n182 216 -1\n188 216 -1\n183 217 -1\n189 217 -1\n184 218 -1\n190 218 -1\n241 219 -0.19969609999999999\n242 219 -0.78596160000000004\n243 219 -0.00064128229999999996\n244 219 0.40690409999999999\n253 219 0.20247019999999999\n254 219 0.79687960000000002\n255 219 0.00065019060000000002\n256 219 -2.166544\n257 220 -1\n264 220 -0.30001499999999998\n265 220 -0.40746149999999998\n246 221 -1\n247 221 -1\n258 221 1\n244 222 0.40690409999999999\n256 222 -2.166544\n264 222 1\n265 223 1\n241 224 -0.98629889999999998\n250 224 -1\n253 224 1\n261 224 1\n264 224 3.5018579999999999\n265 224 1.241884\n242 225 -0.98629889999999998\n251 225 -1\n254 225 1\n261 225 1\n264 225 -2.149559\n265 225 0.93602390000000002\n243 226 -0.98629889999999998\n252 226 -1\n255 226 1\n261 226 1\n264 226 6.0259859999999996\n265 226 4.0868380000000002\n253 227 0.0119553\n254 227 0.61475029999999997\n255 227 0.1605955\n256 227 0.59918099999999996\n275 227 -0.011949680000000001\n276 227 -0.61446120000000004\n277 227 -0.16052\n278 227 -1\n257 228 1\n262 228 -0.093350859999999994\n263 228 -0.34681810000000002\n266 228 -1\n267 228 -1\n268 228 -1\n259 229 1\n256 230 -0.59918099999999996\n262 230 1\n278 230 1\n263 231 1\n250 232 13.33342\n253 232 0.78730109999999998\n260 232 1\n262 232 12.12026\n263 232 0.77025089999999996\n275 232 -0.78693089999999999\n251 233 1.020551\n254 233 0.78730109999999998\n260 233 1\n262 233 -3.9843989999999998\n263 233 0.681342\n276 233 -0.78693089999999999\n252 234 0.0031874849999999999\n255 234 0.78730109999999998\n260 234 1\n262 234 19.25216\n263 234 2.236907\n277 234 -0.78693089999999999\n253 235 -0.17008129999999999\n254 235 -0.82969219999999999\n255 235 -0.00069701409999999996\n256 235 2.5673629999999998\n275 235 0.1700014\n276 235 0.82930199999999998\n277 235 0.00069668629999999996\n278 235 -4.2847869999999997\n279 236 -1\n286 236 -0.25546930000000001\n287 236 -0.41224569999999999\n258 237 -1\n259 237 -1\n280 237 1\n256 238 2.5673629999999998\n278 238 -4.2847869999999997\n286 238 1\n287 239 1\n253 240 -1.0004710000000001\n272 240 -1\n275 240 1\n283 240 1\n286 240 2.9555289999999999\n287 240 1.2544139999999999\n254 241 -1.0004710000000001\n273 241 -1\n276 241 1\n283 241 1\n286 241 -1.8159689999999999\n287 241 0.94521189999999999\n255 242 -1.0004710000000001\n274 242 -1\n277 242 1\n283 242 1\n286 242 5.0849970000000004\n287 242 4.1364789999999996\n250 243 0.20247019999999999\n269 243 -1\n251 244 0.79687960000000002\n270 244 -1\n252 245 0.20398230000000001\n271 245 -1\n275 246 0.0098180809999999993\n276 246 0.61664169999999996\n278 246 0.95579440000000004\n297 246 -0.0098175689999999999\n298 246 -0.61660959999999998\n299 246 -0.16051480000000001\n300 246 -1\n279 247 1\n284 247 -0.098217899999999997\n285 247 -0.34856389999999998\n288 247 -1\n289 247 -1\n290 247 -1\n281 248 1\n278 249 -0.95579440000000004\n284 249 1\n300 249 1\n285 250 1\n272 251 13.626709999999999\n275 251 0.78698299999999999\n282 251 1\n284 251 12.68233\n285 251 0.76942869999999997\n297 251 -0.78694200000000003\n273 252 1.058389\n276 252 0.78698299999999999\n282 252 1\n284 252 -4.1684890000000001\n285 252 0.68102850000000004\n298 252 -0.78694200000000003\n274 253 0.0034155829999999998\n277 253 0.78698299999999999\n282 253 1\n284 253 20.139959999999999\n285 253 2.2394150000000002\n299 253 -0.78694200000000003\n275 254 -0.16786980000000001\n276 254 -0.83148250000000001\n277 254 -0.00069990470000000002\n278 254 4.3289929999999996\n297 254 0.16786100000000001\n298 254 0.83143909999999999\n299 254 0.00069986820000000004\n300 254 -4.5292089999999998\n301 255 -1\n308 255 -0.2530153\n309 255 -0.4125625\n280 256 -1\n281 256 -1\n302 256 1\n278 257 4.3289929999999996\n300 257 -4.5292089999999998\n308 257 1\n309 258 1\n275 259 -1.0000519999999999\n294 259 -1\n297 259 1\n305 259 1\n308 259 2.9254359999999999\n309 259 1.2552490000000001\n276 260 -1.0000519999999999\n295 260 -1\n298 260 1\n305 260 1\n308 260 -1.797593\n309 260 0.94582429999999995\n277 261 -1.0000519999999999\n296 261 -1\n299 261 1\n305 261 1\n308 261 5.0331659999999996\n309 261 4.1397830000000004\n272 262 0.1700014\n291 262 -1\n273 263 0.82930199999999998\n292 263 -1\n274 264 0.20397290000000001\n293 264 -1\n297 265 0.0096798500000000003\n298 265 0.61671089999999995\n299 265 0.1605181\n300 265 0.99729840000000003\n319 265 -0.0096801700000000001\n320 265 -0.61673129999999998\n321 265 -0.16052340000000001\n322 265 -1\n301 266 1\n306 266 -0.09852872\n307 266 -0.34867100000000001\n310 266 -1\n311 266 -1\n312 266 -1\n303 267 1\n300 268 -0.99729840000000003\n306 268 1\n322 268 1\n307 269 1\n294 270 13.64601\n297 270 0.78690890000000002\n304 270 1\n306 270 12.716189999999999\n307 270 0.7693586\n319 270 -0.78693489999999999\n295 271 1.060897\n298 271 0.78690890000000002\n304 271 1\n306 271 -4.1795749999999998\n307 271 0.68099359999999998\n320 271 -0.78693489999999999\n296 272 0.003430968\n299 272 0.78690890000000002\n304 272 1\n306 272 20.19341\n307 272 2.2395320000000001\n321 272 -0.78693489999999999\n297 273 -0.16772329999999999\n298 273 -0.83154050000000002\n299 273 -0.00070311129999999996\n300 273 4.531911\n319 273 0.16772880000000001\n320 273 0.83156799999999997\n321 273 0.0007031346\n322 273 -4.5441880000000001\n323 274 -1\n330 274 -0.25288909999999998\n331 274 -0.41262900000000002\n302 275 -1\n303 275 -1\n324 275 1\n300 276 4.531911\n322 276 -4.5441880000000001\n330 276 1\n331 277 1\n297 278 -0.99996689999999999\n316 278 -1\n319 278 1\n327 278 1\n330 278 2.9235699999999998\n331 278 1.2552939999999999\n298 279 -0.99996689999999999\n317 279 -1\n320 279 1\n327 279 1\n330 279 -1.7964899999999999\n331 279 0.94585160000000001\n299 280 -0.99996689999999999\n318 280 -1\n321 280 1\n327 280 1\n330 280 5.029935\n331 280 4.1401399999999997\n294 281 0.16786100000000001\n313 281 -1\n295 282 0.83143909999999999\n314 282 -1\n296 283 0.20398559999999999\n315 283 -1\n319 284 0.0096473500000000007\n320 284 0.61499680000000001\n321 284 0.1606638\n322 284 1.012275\n341 284 -0.0096630710000000005\n342 284 -0.61599899999999996\n343 284 -0.1609257\n344 284 -1\n323 285 1\n328 285 -0.097740149999999998\n329 285 -0.348389\n332 285 -1\n333 285 -1\n334 285 -1\n325 286 1\n322 287 -1.012275\n328 287 1\n344 287 1\n329 288 1\n316 289 13.653370000000001\n319 289 0.78530800000000001\n326 289 1\n328 289 12.53604\n329 289 0.76861380000000001\n341 289 -0.7865877\n317 290 1.0618540000000001\n320 290 0.78530800000000001\n326 290 1\n328 290 -4.1203450000000004\n329 290 0.68034459999999997\n342 290 -0.7865877\n318 291 0.0034368480000000002\n321 291 0.78530800000000001\n326 291 1\n328 291 19.9072\n329 291 2.2374860000000001\n343 291 -0.7865877\n319 292 -0.16769600000000001\n320 292 -0.8298335\n321 292 -0.00084358209999999998\n322 292 4.5319130000000003\n341 292 0.16796929999999999\n342 292 0.83118579999999997\n343 292 0.00084495670000000003\n344 292 -4.4769569999999996\n345 293 -1\n352 293 -0.25422820000000002\n353 293 -0.41467850000000001\n324 294 -1\n325 294 -1\n346 294 1\n322 295 4.5319120000000002\n344 295 -4.4769569999999996\n352 295 1\n353 296 1\n319 297 -0.99837310000000001\n338 297 -1\n341 297 1\n349 297 1\n352 297 2.9258000000000002\n353 297 1.2548710000000001\n320 298 -0.99837310000000001\n339 298 -1\n342 298 1\n349 298 1\n352 298 -1.799474\n353 298 0.94529589999999997\n321 299 -0.99837310000000001\n340 299 -1\n343 299 1\n349 299 1\n352 299 5.032978\n353 299 4.1465319999999997\n316 300 0.16772880000000001\n335 300 -1\n317 301 0.83156799999999997\n336 301 -1\n318 302 0.20458699999999999\n337 302 -1\n341 303 0.0089580030000000008\n342 303 0.56239150000000004\n343 303 0.17143159999999999\n344 303 1.5349870000000001\n363 303 -0.0093684010000000002\n364 303 -0.58815669999999998\n365 303 -0.17928549999999999\n366 303 -1\n345 304 1\n350 304 -0.076424569999999997\n351 304 -0.33630700000000002\n354 304 -1\n355 304 -1\n356 304 -1\n347 305 1\n344 306 -1.5349870000000001\n350 306 1\n366 306 1\n351 307 1\n338 308 13.9277\n341 308 0.74278120000000003\n348 308 1\n350 308 7.7124139999999999\n351 308 0.73754050000000004\n363 308 -0.77681060000000002\n339 309 1.0977920000000001\n342 309 0.74278120000000003\n348 309 1\n350 309 -2.5345339999999998\n351 309 0.65320800000000001\n364 309 -0.77681060000000002\n340 310 0.00366104\n343 310 0.74278120000000003\n348 310 1\n350 310 12.244490000000001\n351 310 2.151386\n365 310 -0.77681060000000002\n341 311 -0.1672642\n342 311 -0.77757829999999994\n343 311 -0.01135093\n344 311 3.9419710000000001\n363 311 0.1749272\n364 311 0.81320190000000003\n365 311 0.01187095\n366 311 -2.568082\n367 312 -1\n374 312 -0.31132270000000001\n375 312 -0.45572679999999999\n346 313 -1\n347 313 -1\n368 313 1\n344 314 3.9419710000000001\n366 314 -2.568082\n374 314 1\n375 315 1\n341 316 -0.95619350000000003\n360 316 -1\n363 316 1\n371 316 1\n374 316 3.149454\n375 316 1.212998\n342 317 -0.95619350000000003\n361 317 -1\n364 317 1\n371 317 1\n374 317 -1.985919\n375 317 0.9070684\n343 318 -0.95619350000000003\n362 318 -1\n365 318 1\n371 318 1\n374 318 5.3936869999999999\n375 318 4.2274630000000002\n338 319 0.16796929999999999\n357 319 -1\n339 320 0.83118579999999997\n358 320 -1\n340 321 0.2307969\n359 321 -1\n363 322 0.0049560029999999996\n364 322 0.2092511\n365 322 0.4341566\n366 322 6.177384\n385 322 -0.0056864039999999999\n386 322 -0.24008989999999999\n387 322 -0.49814130000000001\n388 322 -1\n367 323 1\n372 323 -0.051899590000000002\n373 323 -0.22819929999999999\n376 323 -1\n377 323 -1\n378 323 -1\n369 324 1\n366 325 -6.177384\n372 325 1\n388 325 1\n373 326 1\n360 327 22.88466\n363 327 0.64836369999999999\n370 327 1\n372 327 1.04345\n373 327 0.42175859999999998\n385 327 -0.74391759999999996\n361 328 2.5197029999999998\n364 328 0.64836369999999999\n370 328 1\n372 328 -0.3414664\n373 328 0.3798898\n386 328 -0.74391759999999996\n362 329 0.017727920000000001\n365 329 0.64836369999999999\n370 329 1\n372 329 1.6460520000000001\n373 329 1.3054760000000001\n387 329 -0.74391759999999996\n360 330 0.1749272\n379 330 -1\n361 331 0.81320190000000003\n380 331 -1\n362 332 0.66961899999999996\n381 332 -1\n87 333 6.3180579999999997\n93 333 1.008121\n88 334 2.1016520000000001\n94 334 0.98324999999999996\n89 335 10.216340000000001\n95 335 0.97112200000000004\n90 336 4.7715329999999998\n96 336 1.0168969999999999\n91 337 1.5445530000000001\n97 337 0.96515200000000001\n92 338 7.4032580000000001\n98 338 0.93991979999999997\n99 339 276.76479999999998\n105 339 0.88770669999999996\n100 340 192.19040000000001\n106 340 1.2620629999999999\n101 341 465.29739999999998\n107 341 0.8373005\n102 342 402.63529999999997\n108 342 0.93272339999999998\n103 343 243.95160000000001\n109 343 1.157006\n104 344 694.42570000000001\n110 344 0.90252429999999995\n111 345 2.1471689999999999\n117 345 0.73310410000000004\n112 346 1.830354\n118 346 0.77070689999999997\n113 347 5.4194959999999996\n119 347 0.91067969999999998\n114 348 1.5934600000000001\n120 348 0.44472830000000002\n115 349 1.5193589999999999\n121 349 0.52296010000000004\n116 350 5.9272710000000002\n122 350 0.81417070000000002\n123 351 8.6013230000000007\n129 351 0.58171510000000004\n124 352 6.1974850000000004\n130 352 0.53220719999999999\n125 353 37.67033\n131 353 1.1683300000000001\n126 354 10.955349999999999\n132 354 0.74939929999999999\n127 355 8.2864269999999998\n133 355 0.71973830000000005\n128 356 35.092930000000003\n134 356 1.100849\n135 357 0.4338919\n138 357 2.2797130000000001\n136 358 0.1137572\n139 358 0.60698209999999997\n137 359 0.4035473\n140 359 0.0080049890000000005\n141 360 1.1577040000000001\n144 360 4.0422279999999997\n142 361 0.41932589999999997\n145 361 2.449611\n143 362 0.10246470000000001\n146 362 0.36475180000000001\n151 363 172.5745\n154 363 14.91761\n152 364 161.58449999999999\n155 364 12.0938\n153 365 145.31450000000001\n156 365 5.7400960000000003\n157 366 0.0045018890000000002\n158 366 0.95263589999999998\n159 366 -1\n158 367 0.94488159999999999\n163 367 19.882059999999999\n164 367 15.998699999999999\n165 367 7.7694989999999997\n159 368 1.00814\n163 368 98.828980000000001\n164 368 147.5558\n165 368 130.84370000000001\n160 369 1\n163 369 1.8011980000000001\n161 370 1\n164 370 2.196221\n162 371 1\n165 371 2.0607380000000002\n163 372 19.882059999999999\n166 372 0.9740453\n164 373 15.998699999999999\n167 373 0.93133779999999999\n165 374 7.7694989999999997\n168 374 0.82771399999999995\n169 375 -1\n172 375 -1\n175 375 0.056357909999999997\n176 375 0.056357909999999997\n177 375 0.056357909999999997\n170 376 -1\n173 376 -1\n175 376 0.73959730000000001\n176 376 0.73959730000000001\n177 376 0.73959730000000001\n171 377 -1\n174 377 -1\n175 377 0.2040448\n176 377 0.2040448\n177 377 0.2040448\n172 378 1\n175 378 -1\n173 379 1\n176 379 -1\n174 380 1\n177 380 -1\n175 381 1\n178 381 1\n176 382 1\n179 382 1\n177 383 1\n180 383 1\n102 384 -19.453890000000001\n418 384 1\n424 384 -0.09530421\n103 385 -22.090309999999999\n419 385 1\n424 385 -0.088197620000000004\n104 386 -49.563589999999998\n420 386 1\n424 386 -0.00010690420000000001\n421 387 179.7345\n422 387 -2.5957400000000002\n422 388 1\n423 388 -0.09621652\n102 389 -1\n103 389 -1\n104 389 -1\n423 389 0.09621652\n424 389 -0.0088937280000000001\n126 390 0.93082790000000004\n127 390 0.93082790000000004\n128 390 0.93082790000000004\n425 390 -1.138352\n436 390 0.095341780000000001\n126 391 0.81769789999999998\n426 391 -0.55083519999999997\n436 391 0.04613478\n127 392 0.81769789999999998\n427 392 -0.4489223\n436 392 0.037599149999999998\n128 393 6.8068650000000002\n428 393 -0.0020188419999999999\n436 393 0.0001690866\n429 394 -0.60313589999999995\n430 394 -1.1914260000000001\n431 394 -0.2090101\n432 394 -0.2323664\n126 395 -1.5881989999999999\n430 395 1\n436 395 -0.089606729999999996\n127 396 -1.7894779999999999\n431 396 1\n436 396 -0.082283250000000002\n128 397 -4.012804\n432 397 1\n436 397 -9.9680419999999997e-05\n433 398 1.186874\n435 398 -0.87134319999999998\n434 399 0.99186010000000002\n435 399 -0.73414950000000001\n126 400 -1\n127 400 -1\n128 400 -1\n435 400 0.89782490000000004\n436 400 -0.1024269\n185 401 263.30250000000001\n188 401 16.710229999999999\n186 402 252.3125\n189 402 15.091379999999999\n187 403 236.04249999999999\n190 403 11.440289999999999\n191 404 0.0068429329999999998\n192 404 0.96227439999999997\n193 404 -1\n192 405 0.95486020000000005\n197 405 35.042119999999997\n198 405 28.167190000000002\n199 405 13.66854\n193 406 1.0077050000000001\n197 406 85.846760000000003\n198 406 144.16210000000001\n199 406 130.40539999999999\n194 407 1\n197 407 1.6589050000000001\n195 408 1\n198 408 2.1064970000000001\n196 409 1\n199 409 2.000909\n197 410 35.042119999999997\n200 410 1\n198 411 28.167190000000002\n201 411 0.97782690000000005\n199 412 13.66854\n202 412 0.91623940000000004\n203 413 -1\n206 413 -1\n209 413 0.0034351899999999999\n210 413 0.0034351899999999999\n211 413 0.0034351899999999999\n204 414 -1\n207 414 -1\n209 414 0.043016970000000002\n210 414 0.043016970000000002\n211 414 0.043016970000000002\n205 415 -1\n208 415 -1\n209 415 0.95354779999999995\n210 415 0.95354779999999995\n211 415 0.95354779999999995\n206 416 1\n209 416 -1\n207 417 1\n210 417 -1\n208 418 1\n211 418 -1\n209 419 1\n212 419 1\n210 420 1\n213 420 1\n211 421 1\n214 421 1\n90 422 -0.047613129999999997\n461 422 1\n467 422 -2.3334699999999999e-05\n91 423 -0.057464349999999997\n462 423 1\n467 423 -0.00035266559999999999\n92 424 -0.12956039999999999\n463 424 1\n467 424 -0.017625419999999999\n464 425 270.46249999999998\n465 425 -2.8000669999999999\n465 426 1\n466 426 -1.6856930000000001\n90 427 -1\n91 427 -1\n92 427 -1\n466 427 1.6856930000000001\n467 427 -0.1426674\n114 428 0.12149740000000001\n115 428 0.12149740000000001\n116 428 0.12149740000000001\n468 428 -1.138352\n479 428 0.021230519999999999\n114 429 0.60555749999999997\n469 429 -0.019490179999999999\n479 429 0.00036349629999999998\n115 430 0.3357927\n470 430 -0.13533829999999999\n479 430 0.0025240900000000001\n116 431 0.1067309\n471 431 -0.95354779999999995\n479 431 0.017783879999999998\n472 432 -0.90759219999999996\n473 432 -5.7118219999999997\n474 432 -0.93568410000000002\n475 432 -1.0346550000000001\n114 433 -0.043240929999999997\n473 433 1\n479 433 -2.5956110000000001e-05\n115 434 -0.052174909999999998\n474 434 1\n479 434 -0.00039218899999999998\n116 435 -0.1176314\n475 435 1\n479 435 -0.019600159999999998\n476 436 5.3140780000000003\n478 436 -1.002184\n477 437 0.34483720000000001\n478 437 -0.26478620000000003\n114 438 -1\n115 438 -1\n116 438 -1\n478 438 1.7669710000000001\n479 438 -0.1747406\n438 439 99.149730000000005\n444 439 -1\n447 439 -3.311398e-05\n439 440 172.6396\n445 440 -1\n448 440 -4.1108120000000002e-05\n440 441 356.63979999999998\n446 441 -1\n449 441 -8.4587179999999994e-05\n441 442 200.0008\n444 442 2.5\n447 442 3.311398e-05\n442 443 349.00330000000002\n445 443 2.5\n448 443 4.1108120000000002e-05\n443 444 722.06780000000003\n446 444 2.5\n449 444 8.4587179999999994e-05\n444 445 1\n453 445 -1.4485650000000001e-06\n445 446 1\n453 446 -0.0005113292\n446 447 1\n453 447 -0.95438869999999998\n447 448 1.0050250000000001\n454 448 -0.0034351899999999999\n448 449 1.002874\n454 449 -0.043016970000000002\n449 450 1.001387\n454 450 -0.95354779999999995\n450 451 1\n453 451 -4.9455600000000001e-05\n451 452 1\n453 452 -0.0021775570000000001\n452 453 1\n453 453 -0.042871529999999998\n453 454 1\n455 454 -1\n466 454 1.5\n478 454 0.5\n454 455 1\n456 455 -316220\n459 455 -12132.58\n460 455 -1\n466 455 -20451.810000000001\n477 455 9152.7510000000002\n455 456 9.1463570000000001\n457 456 0.0037734919999999998\n456 457 2248.7060000000001\n457 457 -0.12505330000000001\n457 458 0.067588380000000003\n458 458 65.087119999999999\n466 458 -0.18859039999999999\n458 459 -9152.7510000000002\n460 459 0.75439429999999996\n476 459 -9152.7510000000002\n477 459 -6904.7830000000004\n459 460 1\n466 460 0.18569289999999999\n478 460 -0.5\n460 461 0.00019167939999999999\n466 461 2.6684519999999998\n478 461 0.88948400000000005\n266 462 0.52397099999999996\n269 462 2.5902729999999998\n267 463 0.1209036\n270 463 1\n268 464 0.36607729999999999\n271 464 0.018323329999999999\n288 465 0.53070830000000002\n291 465 2.6120320000000001\n289 466 0.12143809999999999\n292 466 1\n290 467 0.36327480000000001\n293 467 0.019398479999999999\n310 468 0.53114850000000002\n313 468 2.6134469999999999\n311 469 0.1214731\n314 469 1\n312 470 0.36309170000000002\n315 470 0.01947045\n332 471 0.53131620000000002\n335 471 2.6139860000000001\n333 472 0.12148639999999999\n336 472 1\n334 473 0.36302190000000001\n337 473 0.01949793\n354 474 0.53753340000000005\n357 474 2.63388\n355 475 0.12197959999999999\n358 475 1\n356 476 0.36043579999999997\n359 476 0.020538460000000001\n376 477 0.71092829999999996\n379 477 3.1304669999999999\n377 478 0.13573579999999999\n380 478 1\n378 479 0.28830909999999998\n381 479 0.071489880000000006\n"
  },
  {
    "path": "examples/data/west0479.mtx",
    "content": "%%MatrixMarket matrix coordinate real general\n479 479 1910\n25 1  1.0000000000000e+00\n31 1 -3.7648130000000e-02\n87 1 -3.4423960000000e-01\n26 2  1.0000000000000e+00\n31 2 -2.4522620000000e-02\n88 2 -3.7370860000000e-01\n27 3  1.0000000000000e+00\n31 3 -3.6613040000000e-02\n89 3 -8.3693790000000e-01\n28 4  1.3000000000000e+02\n29 4 -2.4337670000000e+00\n29 5  1.0000000000000e+00\n30 5 -1.6140910000000e+00\n30 6  1.6140910000000e+00\n31 6 -2.1873210000000e-01\n87 6 -1.0000000000000e+00\n88 6 -1.0000000000000e+00\n89 6 -1.0000000000000e+00\n32 7 -1.1383520000000e+00\n43 7  3.6694280000000e-02\n111 7  9.9316360000000e-02\n112 7  9.9316360000000e-02\n113 7  9.9316360000000e-02\n33 8 -5.0000000000000e-01\n43 8  1.6117290000000e-02\n111 8  8.7245760000000e-02\n34 9 -3.6119180000000e-01\n43 9  1.1642860000000e-02\n112 9  1.0504150000000e-01\n35 10 -3.2188760000000e-01\n43 10  1.0375910000000e-02\n113 10  1.4041660000000e-01\n36 11 -4.3624160000000e-01\n37 11 -7.6804250000000e-01\n38 11 -1.4302790000000e-01\n39 11 -1.5938860000000e-01\n37 12  1.0000000000000e+00\n43 12 -4.8560820000000e-02\n111 12 -2.6286840000000e-01\n38 13  1.0000000000000e+00\n43 13 -3.0925950000000e-02\n112 13 -2.7901280000000e-01\n39 14  1.0000000000000e+00\n43 14 -4.6123590000000e-02\n113 14 -6.2418820000000e-01\n40 15  5.2824360000000e+00\n42 15 -6.1239210000000e-01\n41 16  2.8868220000000e-01\n42 16 -2.1638150000000e-01\n42 17  1.3287740000000e+00\n43 17 -3.6946860000000e-01\n111 17 -1.0000000000000e+00\n112 17 -1.0000000000000e+00\n113 17 -1.0000000000000e+00\n2 18  4.8176470000000e+01\n8 18 -1.0000000000000e+00\n11 18 -3.3474840000000e-05\n3 19  8.3500000000000e+01\n9 19 -1.0000000000000e+00\n12 19 -4.1365390000000e-05\n4 20  1.7194120000000e+02\n10 20 -1.0000000000000e+00\n13 20 -8.4843450000000e-05\n5 21  9.6651380000000e+01\n8 21  2.5000000000000e+00\n11 21  3.3474840000000e-05\n6 22  1.6827060000000e+02\n9 22  2.5000000000000e+00\n12 22  4.1365390000000e-05\n7 23  3.4758720000000e+02\n10 23  2.5000000000000e+00\n13 23  8.4843450000000e-05\n8 24  1.0000000000000e+00\n17 24 -1.1069670000000e-01\n27 24  1.6052320000000e+00\n9 25  1.0000000000000e+00\n17 25 -8.9808520000000e-02\n10 26  1.0000000000000e+00\n17 26 -1.5173690000000e-01\n11 27  1.0104550000000e+00\n18 27 -5.0000000000000e-01\n12 28  1.0059780000000e+00\n18 28 -3.0000000000000e-01\n13 29  1.0028850000000e+00\n18 29 -2.0000000000000e-01\n14 30  1.0000000000000e+00\n17 30 -1.8118550000000e-01\n15 31  1.0000000000000e+00\n17 31 -2.4002390000000e-01\n16 32  1.0000000000000e+00\n17 32 -2.2654840000000e-01\n17 33  1.0000000000000e+00\n19 33 -1.0000000000000e+00\n30 33  1.5000000000000e+00\n42 33  5.0000000000000e-01\n18 34  1.0000000000000e+00\n20 34 -3.1622000000000e+05\n23 34 -1.2323690000000e+04\n24 34 -1.0000000000000e+00\n30 34 -3.5226800000000e+04\n41 34  1.8449020000000e+04\n19 35  5.2983390000000e+00\n21 35  2.4526870000000e-03\n20 36  1.0808590000000e+03\n21 36 -2.0502150000000e-01\n21 37  1.4419200000000e-01\n22 37  6.3059860000000e+01\n30 37 -1.1592990000000e-01\n22 38 -1.8449020000000e+04\n24 38  8.4533390000000e-01\n40 38 -1.8449020000000e+04\n41 38 -1.5595580000000e+04\n23 39  1.0000000000000e+00\n30 39  2.0204930000000e-01\n42 39 -8.8547100000000e-01\n24 40  1.0002340000000e-04\n30 40  2.4483390000000e+00\n42 40  8.1611300000000e-01\n68 41  1.0000000000000e+00\n74 41 -2.2786690000000e-04\n99 41 -2.6243950000000e-01\n69 42  1.0000000000000e+00\n74 42 -4.1887630000000e-04\n100 42 -3.2161960000000e-01\n70 43  1.0000000000000e+00\n74 43 -1.5769330000000e-03\n101 43 -7.2647610000000e-01\n71 44  3.0000000000000e+02\n72 44 -2.8518910000000e+00\n72 45  1.0000000000000e+00\n73 45 -2.8701590000000e-01\n73 46  2.8701590000000e-01\n74 46 -4.3413220000000e-03\n99 46 -1.0000000000000e+00\n100 46 -1.0000000000000e+00\n101 46 -1.0000000000000e+00\n75 47 -1.1383520000000e+00\n86 47  4.2002860000000e-02\n123 47  9.4148060000000e-01\n124 47  9.4148060000000e-01\n125 47  9.4148060000000e-01\n76 48 -3.2188760000000e-01\n86 48  1.1877000000000e-02\n123 48  1.3310950000000e+00\n77 49 -3.6119180000000e-01\n86 49  1.3327240000000e-02\n124 49  9.9575290000000e-01\n78 50 -5.0000000000000e-01\n86 50  1.8448980000000e-02\n125 50  8.2705600000000e-01\n79 51 -1.0000000000000e+00\n80 51 -1.9240000000000e+01\n81 51 -3.8030000000000e+00\n82 51 -9.4810000000000e+00\n80 52  1.0000000000000e+00\n86 52 -8.8757840000000e-04\n123 52 -9.9473920000000e-02\n81 53  1.0000000000000e+00\n86 53 -1.3313680000000e-03\n124 53 -9.9473920000000e-02\n82 54  1.0000000000000e+00\n86 54 -2.2189460000000e-03\n125 54 -9.9473920000000e-02\n83 55  1.1776130000000e+00\n85 55 -3.1089630000000e+00\n84 56  9.9194250000000e-01\n85 56 -2.6400560000000e+00\n85 57  3.1921120000000e+00\n86 57 -4.4613630000000e-02\n123 57 -1.0000000000000e+00\n124 57 -1.0000000000000e+00\n125 57 -1.0000000000000e+00\n45 58  1.0986880000000e+02\n51 58 -1.0000000000000e+00\n54 58 -3.3081100000000e-05\n46 59  1.9138460000000e+02\n52 59 -1.0000000000000e+00\n55 59 -4.1084670000000e-05\n47 60  3.9547960000000e+02\n53 60 -1.0000000000000e+00\n56 60 -8.4563830000000e-05\n48 61  2.2173390000000e+02\n51 61  2.5000000000000e+00\n54 61  3.3081100000000e-05\n49 62  3.8700920000000e+02\n52 62  2.5000000000000e+00\n55 62  4.1084670000000e-05\n50 63  8.0081650000000e+02\n53 63  2.5000000000000e+00\n56 63  8.4563830000000e-05\n51 64  1.0000000000000e+00\n60 64 -9.1702290000000e-03\n52 65  1.0000000000000e+00\n60 65 -4.6441100000000e-02\n53 66  1.0000000000000e+00\n60 66 -4.8999190000000e-01\n54 67  1.0045300000000e+00\n61 67 -2.0000000000000e-01\n55 68  1.0025910000000e+00\n61 68 -3.0000000000000e-01\n56 69  1.0012500000000e+00\n61 69 -5.0000000000000e-01\n57 70  1.0000000000000e+00\n60 70 -3.7500530000000e-02\n58 71  1.0000000000000e+00\n60 71 -1.2414300000000e-01\n59 72  1.0000000000000e+00\n60 72 -2.9275320000000e-01\n60 73  1.0000000000000e+00\n62 73 -1.0000000000000e+00\n73 73  1.8537330000000e-01\n85 73  6.1791090000000e-02\n61 74  1.0000000000000e+00\n63 74 -3.1622000000000e+05\n66 74 -1.6364190000000e+04\n67 74 -1.0000000000000e+00\n73 74 -4.6967820000000e+03\n84 74  1.3185400000000e+02\n62 75  2.2129130000000e+01\n64 75  9.5375260000000e-01\n63 76  2.4942900000000e+03\n64 76 -1.0215870000000e+00\n64 77  8.8782810000000e-01\n65 77  1.0400420000000e+00\n73 77 -2.6400560000000e+00\n65 78 -1.3185400000000e+02\n67 78  8.0574700000000e-03\n83 78 -1.3185400000000e+02\n84 78 -1.0624090000000e+00\n66 79  1.0000000000000e+00\n73 79  1.0164260000000e-01\n85 79 -6.1791090000000e-02\n67 80  7.6452570000000e-03\n73 80  2.3098950000000e+01\n85 80  7.6996490000000e+00\n31 81  1.0000000000000e+00\n244 81  1.0000000000000e+00\n43 82  1.0000000000000e+00\n1 83  1.0000000000000e+00\n17 83 -3.8502310000000e+00\n18 83 -8.4599350000000e-05\n31 83  2.0159100000000e+00\n35 83  1.0000000000000e+00\n43 83  1.5961710000000e+00\n243 83 -7.8975120000000e-01\n74 84  1.0000000000000e+00\n388 84  8.8175620000000e-01\n86 85  1.0000000000000e+00\n44 86  1.0000000000000e+00\n60 86 -2.7937600000000e+00\n61 86 -8.4458230000000e-05\n74 86  2.0156650000000e+00\n78 86  1.0000000000000e+00\n86 86  1.5939940000000e+00\n384 86  0.0000000000000e+00\n387 86 -9.6191500000000e-01\n385 87  2.4246690000000e-03\n386 87  3.0362780000000e-02\n387 87  6.7304510000000e-01\n388 87  1.4593600000000e+00\n96 88  1.6896610000000e-02\n97 88  3.4848030000000e-02\n98 88 -6.0080180000000e-02\n120 88 -5.5527170000000e-01\n121 88 -4.7703980000000e-01\n122 88 -1.8582930000000e-01\n141 88 -1.0000000000000e+00\n142 88 -1.0000000000000e+00\n143 88 -1.0000000000000e+00\n185 88 -5.5188570000000e+01\n186 88 -9.5676860000000e+01\n187 88 -2.1583770000000e+02\n389 88  1.0000000000000e+00\n438 88  1.0000000000000e+00\n439 88  1.0000000000000e+00\n440 88  1.0000000000000e+00\n441 88  1.0000000000000e+00\n442 88  1.0000000000000e+00\n443 88  1.0000000000000e+00\n450 88 -1.8907560000000e-03\n451 88 -1.5311400000000e-03\n452 88 -1.0137260000000e-03\n455 88  2.5000000000000e+00\n456 88  2.6063700000000e+01\n458 88  1.0000000000000e+00\n459 88 -1.5000000000000e+00\n461 88 -9.6031810000000e+00\n462 88 -9.4541850000000e+00\n463 88 -9.4376810000000e+00\n464 88 -4.8295720000000e+01\n472 88  9.0759220000000e-01\n473 88 -4.3759670000000e+00\n474 88 -8.9979920000000e+00\n475 88 -8.8819580000000e+00\n476 88  1.0000000000000e+00\n182 89  1.0000000000000e+00\n183 89  1.0000000000000e+00\n184 89  1.0000000000000e+00\n391 89  1.0000000000000e+00\n455 89 -1.0000000000000e+00\n456 89 -2.6063700000000e+01\n458 89 -1.0000000000000e+00\n468 89  1.0000000000000e+00\n388 90 -1.4593600000000e+00\n467 90  1.0000000000000e+00\n479 91  1.0000000000000e+00\n203 92 -1.0000000000000e+00\n204 92 -1.0000000000000e+00\n205 92 -1.0000000000000e+00\n209 92  1.0000000000000e+00\n210 92  1.0000000000000e+00\n211 92  1.0000000000000e+00\n382 92  5.6953100000000e+01\n385 92  7.0583250000000e-01\n437 92  1.0000000000000e+00\n453 92 -6.4913720000000e-01\n454 92 -3.2948410000000e-05\n467 92  5.3807480000000e-01\n469 92  1.0000000000000e+00\n479 92  8.2471120000000e-02\n203 93 -1.0000000000000e+00\n204 93 -1.0000000000000e+00\n205 93 -1.0000000000000e+00\n209 93  1.0000000000000e+00\n210 93  1.0000000000000e+00\n211 93  1.0000000000000e+00\n383 93  1.1583840000000e+01\n386 93  7.0583250000000e-01\n437 93  1.0000000000000e+00\n453 93 -1.0215420000000e+00\n454 93 -4.0990330000000e-05\n467 93 -3.6302480000000e-01\n470 93  1.0000000000000e+00\n479 93  6.9522610000000e-02\n203 94 -1.0000000000000e+00\n204 94 -1.0000000000000e+00\n205 94 -1.0000000000000e+00\n209 94  1.0000000000000e+00\n210 94  1.0000000000000e+00\n211 94  1.0000000000000e+00\n384 94  3.2096310000000e-01\n387 94  7.0583250000000e-01\n437 94  1.0000000000000e+00\n453 94 -2.0490070000000e+00\n454 94 -8.4470030000000e-05\n467 94  9.1353620000000e-01\n471 94  1.0000000000000e+00\n479 94  8.3976380000000e-01\n241 95  5.5083520000000e-01\n242 95  4.4892230000000e-01\n243 95  2.4252030000000e-04\n244 95  4.0528330000000e-01\n108 96 -6.7276620000000e-02\n109 96 -1.5700610000000e-01\n110 96 -9.7475700000000e-02\n132 96 -2.5060070000000e-01\n133 96 -2.8026170000000e-01\n134 96  1.0084910000000e-01\n245 96 -1.0000000000000e+00\n395 96  1.0000000000000e+00\n396 96  1.0000000000000e+00\n397 96  1.0000000000000e+00\n398 96  1.0000000000000e+00\n399 96  1.0000000000000e+00\n400 96  1.0000000000000e+00\n407 96 -2.8636020000000e-03\n408 96 -2.3162590000000e-03\n409 96 -1.5308900000000e-03\n412 96  2.5000000000000e+00\n413 96  1.1587800000000e+01\n415 96  1.0000000000000e+00\n416 96 -1.1012240000000e+00\n418 96 -1.3644320000000e+00\n419 96 -1.2188210000000e+00\n420 96 -1.2108590000000e+00\n421 96 -3.4621050000000e+01\n429 96  6.0313590000000e-01\n430 96 -5.9963840000000e-01\n431 96 -1.4033920000000e+00\n432 96 -1.3703860000000e+00\n433 96  1.0000000000000e+00\n246 97  1.0000000000000e+00\n412 97 -1.0000000000000e+00\n413 97 -1.1587800000000e+01\n415 97 -1.0000000000000e+00\n425 97  1.0000000000000e+00\n244 98 -4.0528330000000e-01\n424 98  1.0000000000000e+00\n436 99  1.0000000000000e+00\n160 100 -8.5938400000000e-01\n161 100 -7.7333900000000e-01\n162 100 -7.9517400000000e-01\n238 100 -1.0000000000000e+00\n241 100  1.0000000000000e+00\n394 100  1.0000000000000e+00\n410 100 -1.6236590000000e+00\n411 100 -3.3032780000000e-05\n424 100  3.5720350000000e+00\n426 100  1.0000000000000e+00\n436 100  9.2435320000000e-01\n160 101 -1.1718210000000e+00\n161 101 -1.2773520000000e+00\n162 101 -1.2505080000000e+00\n239 101 -1.0000000000000e+00\n242 101  1.0000000000000e+00\n394 101  1.0000000000000e+00\n410 101 -2.4602890000000e+00\n411 101 -4.1050810000000e-05\n424 101 -2.1785330000000e+00\n427 101  1.0000000000000e+00\n436 101  6.5098420000000e-01\n160 102 -2.3280470000000e+00\n161 102 -2.4161550000000e+00\n162 102 -2.5121660000000e+00\n240 102 -1.0000000000000e+00\n243 102  1.0000000000000e+00\n394 102  1.0000000000000e+00\n410 102 -4.7536200000000e+00\n411 102 -8.4530500000000e-05\n424 102  6.1671400000000e+00\n428 102  1.0000000000000e+00\n436 102  3.3966910000000e+00\n241 103  4.3736570000000e-02\n242 103  5.7396460000000e-01\n243 103  1.5834900000000e-01\n244 103  1.8781250000000e-01\n253 103 -4.4344130000000e-02\n254 103 -5.8193780000000e-01\n255 103 -1.6054870000000e-01\n256 103 -1.0000000000000e+00\n135 104 -1.0000000000000e+00\n136 104 -1.0000000000000e+00\n137 104 -1.0000000000000e+00\n151 104 -6.2680900000000e+01\n152 104 -1.2389000000000e+02\n153 104 -4.6435550000000e+02\n245 104  1.0000000000000e+00\n248 104 -5.1646550000000e-02\n249 104 -3.2417620000000e-01\n148 105  1.0000000000000e+00\n149 105  1.0000000000000e+00\n150 105  1.0000000000000e+00\n247 105  1.0000000000000e+00\n244 106 -1.8781250000000e-01\n248 106  1.0000000000000e+00\n256 106  1.0000000000000e+00\n249 107  1.0000000000000e+00\n147 108  1.0000000000000e+00\n169 108 -1.0000000000000e+00\n170 108 -1.0000000000000e+00\n171 108 -1.0000000000000e+00\n175 108  1.0000000000000e+00\n176 108  1.0000000000000e+00\n177 108  1.0000000000000e+00\n238 108  9.7738750000000e+00\n241 108  7.7605020000000e-01\n248 108  7.2528310000000e+00\n249 108  7.8041000000000e-01\n253 108 -7.8683060000000e-01\n147 109  1.0000000000000e+00\n169 109 -1.0000000000000e+00\n170 109 -1.0000000000000e+00\n171 109 -1.0000000000000e+00\n175 109  1.0000000000000e+00\n176 109  1.0000000000000e+00\n177 109  1.0000000000000e+00\n239 109  6.0698210000000e-01\n242 109  7.7605020000000e-01\n248 109 -2.3895080000000e+00\n249 109  6.8493980000000e-01\n254 109 -7.8683060000000e-01\n147 110  1.0000000000000e+00\n169 110 -1.0000000000000e+00\n170 110 -1.0000000000000e+00\n171 110 -1.0000000000000e+00\n175 110  1.0000000000000e+00\n176 110  1.0000000000000e+00\n177 110  1.0000000000000e+00\n240 110  1.1885640000000e-03\n243 110  7.7605020000000e-01\n248 110  1.1558830000000e+01\n249 110  2.2026440000000e+00\n255 110 -7.8683060000000e-01\n363 111 -1.7051480000000e-01\n364 111 -4.3429630000000e-01\n365 111 -2.6674210000000e-01\n366 111 -2.6093020000000e+00\n385 111  1.9564470000000e-01\n386 111  4.9830160000000e-01\n387 111  3.0605370000000e-01\n388 111  4.2239600000000e-01\n215 112  1.0000000000000e+00\n216 112  1.0000000000000e+00\n217 112  1.0000000000000e+00\n218 112  1.0000000000000e+00\n219 112  1.0000000000000e+00\n220 112  1.0000000000000e+00\n227 112 -1.8907560000000e-03\n228 112 -1.5311400000000e-03\n229 112 -1.0137260000000e-03\n232 112  2.5000000000000e+00\n233 112  1.6672410000000e+01\n235 112  1.0000000000000e+00\n236 112 -1.5000000000000e+00\n389 112 -1.0000000000000e+00\n392 112 -4.6212130000000e-01\n393 112 -1.2349620000000e-01\n232 113 -1.0000000000000e+00\n233 113 -1.6672410000000e+01\n235 113 -1.0000000000000e+00\n368 113 -1.0000000000000e+00\n369 113 -1.0000000000000e+00\n390 113  1.0000000000000e+00\n366 114  2.6093020000000e+00\n388 114 -4.2239600000000e-01\n392 114  1.0000000000000e+00\n393 115  1.0000000000000e+00\n181 116  1.0000000000000e+00\n194 116 -5.8697620000000e-01\n195 116 -5.0651550000000e-01\n196 116 -5.1399180000000e-01\n230 116 -1.0366850000000e+00\n231 116 -3.2948410000000e-05\n360 116  0.0000000000000e+00\n363 116 -8.7155310000000e-01\n382 116 -1.0000000000000e+00\n385 116  1.0000000000000e+00\n392 116  2.6399800000000e+00\n393 116  5.5742070000000e-01\n181 117  1.0000000000000e+00\n194 117 -8.0016370000000e-01\n195 117 -8.3640900000000e-01\n196 117 -8.0810260000000e-01\n230 117 -1.6376950000000e+00\n231 117 -4.0990330000000e-05\n361 117  0.0000000000000e+00\n364 117 -8.7155310000000e-01\n383 117 -1.0000000000000e+00\n386 117  1.0000000000000e+00\n392 117 -1.7736780000000e+00\n393 117  4.0754220000000e-01\n181 118  1.0000000000000e+00\n194 118 -1.5893890000000e+00\n195 118 -1.5818110000000e+00\n196 118 -1.6231180000000e+00\n230 118 -3.2056860000000e+00\n231 118 -8.4470030000000e-05\n362 118  0.0000000000000e+00\n365 118 -8.7155310000000e-01\n384 118 -1.0000000000000e+00\n387 118  1.0000000000000e+00\n392 118  4.4676090000000e+00\n393 118  2.2475290000000e+00\n93 119 -1.0000000000000e+00\n96 119 -1.0000000000000e+00\n248 119 -4.0421560000000e-01\n262 119 -1.8187770000000e-01\n284 119 -1.5634550000000e-01\n306 119 -1.5456990000000e-01\n328 119 -1.5217780000000e-01\n350 119 -9.1905800000000e-02\n372 119 -7.8705370000000e-03\n94 120 -1.0000000000000e+00\n97 120 -1.0000000000000e+00\n248 120 -1.8091710000000e+00\n262 120 -3.1896550000000e+00\n284 120 -3.3490190000000e+00\n306 120 -3.3586440000000e+00\n328 120 -3.3085850000000e+00\n350 120 -1.9678700000000e+00\n372 120 -1.1333560000000e-01\n95 121 -1.0000000000000e+00\n98 121 -1.0000000000000e+00\n248 121 -2.4566020000000e+00\n262 121 -4.1011280000000e+00\n284 121 -4.2908920000000e+00\n306 121 -4.3026030000000e+00\n328 121 -4.2541470000000e+00\n350 121 -2.9523890000000e+00\n372 121 -1.1573650000000e+00\n93 122 -8.1214960000000e-03\n96 122 -1.6896610000000e-02\n248 122 -4.5387600000000e-03\n262 122 -2.1705200000000e-03\n284 122 -1.8740690000000e-03\n306 122 -1.8533180000000e-03\n328 122 -1.8248370000000e-03\n350 122 -1.1065610000000e-03\n372 122 -1.0544940000000e-04\n94 123 -1.6749990000000e-02\n97 123 -3.4848030000000e-02\n248 123 -4.1896920000000e-02\n262 123 -7.8506680000000e-02\n284 123 -8.2793510000000e-02\n306 123 -8.3055320000000e-02\n328 123 -8.1826380000000e-02\n350 123 -4.8866050000000e-02\n372 123 -3.1317320000000e-03\n95 124 -2.8878030000000e-02\n98 124 -6.0080180000000e-02\n248 124 -9.8082240000000e-02\n262 124 -1.7402810000000e-01\n284 124 -1.8288550000000e-01\n306 124 -1.8343740000000e-01\n328 124 -1.8139140000000e-01\n350 124 -1.2639720000000e-01\n372 124 -5.5136770000000e-02\n105 125 -1.0000000000000e+00\n108 125 -1.0000000000000e+00\n264 125 -7.6362320000000e-01\n286 125 -5.4132110000000e-01\n308 125 -5.2907530000000e-01\n330 125 -5.2832600000000e-01\n352 125 -5.2965340000000e-01\n374 125 -5.9901060000000e-01\n392 125 -5.7467680000000e-01\n106 126 -1.0000000000000e+00\n109 126 -1.0000000000000e+00\n264 126 -1.4679790000000e+00\n286 126 -1.2898060000000e+00\n308 126 -1.2799920000000e+00\n330 126 -1.2793850000000e+00\n352 126 -1.2801740000000e+00\n374 126 -1.3601430000000e+00\n392 126 -7.1491900000000e-01\n107 127 -1.0000000000000e+00\n110 127 -1.0000000000000e+00\n264 127 -4.3708570000000e-03\n286 127 -3.9541010000000e-03\n308 127 -3.9318030000000e-03\n330 127 -3.9476680000000e-03\n352 127 -4.7490230000000e-03\n374 127 -7.2455390000000e-02\n392 127 -1.6023640000000e+00\n105 128 -1.1229330000000e-01\n108 128 -6.7276620000000e-02\n264 128 -5.4601370000000e-02\n286 128 -3.8877220000000e-02\n308 128 -3.8008660000000e-02\n330 128 -3.7958990000000e-02\n352 128 -3.8208860000000e-02\n374 128 -4.8085490000000e-02\n392 128 -5.8178620000000e-02\n106 129 -2.6206330000000e-01\n109 129 -1.5700610000000e-01\n264 129 -2.4496080000000e-01\n286 129 -2.1618060000000e-01\n308 129 -2.1459740000000e-01\n330 129 -2.1451910000000e-01\n352 129 -2.1552300000000e-01\n374 129 -2.5481000000000e-01\n392 129 -1.6890750000000e-01\n107 130 -1.6269950000000e-01\n110 130 -9.7475700000000e-02\n264 130 -4.5281760000000e-04\n286 130 -4.1145290000000e-04\n308 130 -4.0925030000000e-04\n330 130 -4.1094670000000e-04\n352 130 -4.9637370000000e-04\n374 130 -8.4271850000000e-03\n392 130 -2.3503520000000e-01\n117 131 -1.0000000000000e+00\n120 131 -1.0000000000000e+00\n249 131 -6.9702840000000e-02\n263 131 -1.9243320000000e-02\n285 131 -1.5837930000000e-02\n307 131 -1.5617910000000e-02\n329 131 -1.5583210000000e-02\n351 131 -1.4718560000000e-02\n373 131 -5.7599520000000e-03\n118 132 -1.0000000000000e+00\n121 132 -1.0000000000000e+00\n249 132 -7.4171360000000e-01\n263 132 -8.0234940000000e-01\n285 132 -8.0658470000000e-01\n307 132 -8.0682860000000e-01\n329 132 -8.0550310000000e-01\n351 132 -7.4926980000000e-01\n373 132 -1.9719700000000e-01\n119 133 -1.0000000000000e+00\n122 133 -1.0000000000000e+00\n249 133 -5.1275980000000e-01\n263 133 -5.2522530000000e-01\n285 133 -5.2614130000000e-01\n307 133 -5.2622450000000e-01\n329 133 -5.2730270000000e-01\n351 133 -5.7231860000000e-01\n373 133 -1.0252420000000e+00\n117 134 -4.6575930000000e-01\n120 134 -9.6900310000000e-01\n249 134 -4.4884880000000e-02\n263 134 -1.3170120000000e-02\n285 134 -1.0887390000000e-02\n307 134 -1.0739240000000e-02\n329 134 -1.0716550000000e-02\n351 134 -1.0163030000000e-02\n373 134 -4.4257190000000e-03\n118 135 -5.7440230000000e-01\n121 135 -1.1950330000000e+00\n249 135 -5.8903420000000e-01\n263 135 -6.7721740000000e-01\n285 135 -6.8380180000000e-01\n307 135 -6.8420530000000e-01\n329 135 -6.8315610000000e-01\n351 135 -6.3804400000000e-01\n373 135 -1.8686160000000e-01\n119 136 -2.2922850000000e-01\n122 136 -4.7690550000000e-01\n249 136 -1.6250650000000e-01\n263 136 -1.7691420000000e-01\n285 136 -1.7800620000000e-01\n307 136 -1.7808560000000e-01\n329 136 -1.7847000000000e-01\n351 136 -1.9449250000000e-01\n373 136 -3.8770260000000e-01\n129 137 -1.0000000000000e+00\n132 137 -1.0000000000000e+00\n265 137 -3.4272790000000e-01\n287 137 -2.9113760000000e-01\n309 137 -2.8769370000000e-01\n331 137 -2.8748890000000e-01\n353 137 -2.8823180000000e-01\n375 137 -3.0269870000000e-01\n393 137 -1.7507890000000e-01\n130 138 -1.0000000000000e+00\n133 138 -1.0000000000000e+00\n265 138 -1.0623340000000e+00\n287 138 -1.1185060000000e+00\n309 138 -1.1222530000000e+00\n331 138 -1.1225120000000e+00\n353 138 -1.1232850000000e+00\n375 138 -1.1082340000000e+00\n393 138 -3.5118640000000e-01\n131 139 -1.0000000000000e+00\n134 139 -1.0000000000000e+00\n265 139 -2.3999820000000e-03\n287 139 -2.6017300000000e-03\n309 139 -2.6156270000000e-03\n331 139 -2.6280330000000e-03\n353 139 -3.1617350000000e-03\n375 139 -4.4793810000000e-02\n393 139 -5.9723090000000e-01\n129 140 -2.0182530000000e+00\n132 140 -1.2091660000000e+00\n265 140 -4.4044890000000e-01\n287 140 -3.7580290000000e-01\n309 140 -3.7146430000000e-01\n331 140 -3.7124050000000e-01\n353 140 -3.7371090000000e-01\n375 140 -4.3672880000000e-01\n393 140 -3.1856280000000e-01\n130 141 -2.5626880000000e+00\n133 141 -1.5353450000000e+00\n265 141 -1.7335130000000e+00\n287 141 -1.8332450000000e+00\n309 141 -1.8399150000000e+00\n331 141 -1.8405410000000e+00\n353 141 -1.8492860000000e+00\n375 141 -2.0302660000000e+00\n393 141 -8.1137050000000e-01\n131 142 -9.2554290000000e-01\n134 142 -5.5450670000000e-01\n265 142 -1.4144090000000e-03\n287 142 -1.5400860000000e-03\n309 142 -1.5487580000000e-03\n331 142 -1.5562740000000e-03\n353 142 -1.8799250000000e-03\n375 142 -2.9637400000000e-02\n393 142 -4.9833870000000e-01\n135 143 -1.4338920000000e+00\n141 143 -2.1577040000000e+00\n266 143 -1.5239710000000e+00\n288 143 -1.5307080000000e+00\n310 143 -1.5311480000000e+00\n332 143 -1.5313160000000e+00\n354 143 -1.5375330000000e+00\n376 143 -1.7109280000000e+00\n136 144 -9.4320600000000e-01\n142 144 -1.4193260000000e+00\n267 144 -1.0024600000000e+00\n289 144 -1.0068910000000e+00\n311 144 -1.0071810000000e+00\n333 144 -1.0072910000000e+00\n355 144 -1.0113810000000e+00\n377 144 -1.1254390000000e+00\n137 145 -5.9645270000000e-01\n143 145 -8.9753530000000e-01\n268 145 -6.3392270000000e-01\n290 145 -6.3672520000000e-01\n312 145 -6.3690830000000e-01\n334 145 -6.3697810000000e-01\n356 145 -6.3956420000000e-01\n378 145 -7.1169090000000e-01\n135 146 -1.0000000000000e+00\n141 146 -1.0000000000000e+00\n266 146 -1.0000000000000e+00\n288 146 -1.0000000000000e+00\n310 146 -1.0000000000000e+00\n332 146 -1.0000000000000e+00\n354 146 -1.0000000000000e+00\n376 146 -1.0000000000000e+00\n136 147 -1.0000000000000e+00\n142 147 -1.0000000000000e+00\n267 147 -1.0000000000000e+00\n289 147 -1.0000000000000e+00\n311 147 -1.0000000000000e+00\n333 147 -1.0000000000000e+00\n355 147 -1.0000000000000e+00\n377 147 -1.0000000000000e+00\n137 148 -1.0000000000000e+00\n143 148 -1.0000000000000e+00\n268 148 -1.0000000000000e+00\n290 148 -1.0000000000000e+00\n312 148 -1.0000000000000e+00\n334 148 -1.0000000000000e+00\n356 148 -1.0000000000000e+00\n378 148 -1.0000000000000e+00\n138 149 -1.0000000000000e+00\n148 149  1.0000000000000e+00\n238 149  5.5083520000000e-01\n139 150 -1.0000000000000e+00\n149 150  1.6474950000000e+00\n239 150  7.3959730000000e-01\n140 151 -1.0000000000000e+00\n150 151  8.4135160000000e+02\n240 151  2.0404480000000e-01\n144 152 -1.0000000000000e+00\n182 152  1.0000000000000e+00\n382 152  1.9564470000000e-01\n145 153 -1.0000000000000e+00\n183 153  1.0000000000000e+00\n383 153  4.9830160000000e-01\n146 154 -1.0000000000000e+00\n184 154  3.1156220000000e+00\n384 154  9.5354780000000e-01\n395 155  6.6224920000000e+01\n401 155 -1.0000000000000e+00\n404 155 -3.3282570000000e-05\n396 156  1.1506230000000e+02\n402 156 -1.0000000000000e+00\n405 156 -4.1228310000000e-05\n397 157  2.3733870000000e+02\n403 157 -1.0000000000000e+00\n406 157 -8.4706900000000e-05\n398 158  1.3324500000000e+02\n401 158  2.5000000000000e+00\n404 158  3.3282570000000e-05\n399 159  2.3226390000000e+02\n402 159  2.5000000000000e+00\n405 159  4.1228310000000e-05\n400 160  4.8018210000000e+02\n403 160  2.5000000000000e+00\n406 160  8.4706900000000e-05\n160 161 -4.7337900000000e-01\n401 161  1.0000000000000e+00\n410 161 -2.1168760000000e-01\n161 162 -5.7343170000000e-01\n402 162  1.0000000000000e+00\n410 162 -3.1667150000000e-01\n162 163 -6.0925110000000e-04\n403 163  1.0000000000000e+00\n410 163 -3.5118740000000e-07\n163 164 -4.5750040000000e+03\n404 164  1.0075620000000e+00\n411 164 -5.5083520000000e-01\n164 165 -3.6814160000000e+03\n405 165  1.0043240000000e+00\n411 165 -4.4892230000000e-01\n165 166 -1.7878180000000e+03\n406 166  1.0020870000000e+00\n411 166 -2.4252030000000e-04\n160 167 -5.2605640000000e-01\n161 167 -4.2598230000000e-01\n407 167  1.0000000000000e+00\n410 167 -4.7048840000000e-01\n160 168 -5.6459870000000e-04\n162 168 -4.3800980000000e-01\n408 168  1.0000000000000e+00\n410 168 -5.0495930000000e-04\n161 169 -5.8596670000000e-04\n162 169 -5.6138090000000e-01\n409 169  1.0000000000000e+00\n410 169 -6.4718760000000e-04\n163 170 -1.0000000000000e+00\n164 170 -1.0000000000000e+00\n165 170 -1.0000000000000e+00\n410 170  1.0000000000000e+00\n412 170 -1.0000000000000e+00\n423 170  6.1444210000000e-02\n435 170  2.0481400000000e-02\n157 171 -1.0000000000000e+00\n163 171  4.1240600000000e+03\n164 171  4.1240600000000e+03\n165 171  4.1240600000000e+03\n411 171  1.0000000000000e+00\n413 171 -3.1622000000000e+05\n416 171 -2.0034240000000e+04\n417 171 -1.0000000000000e+00\n423 171 -2.6256570000000e+03\n434 171  2.2212900000000e+02\n412 172  1.8737270000000e+01\n414 172  9.4488160000000e-01\n413 173  1.4943670000000e+03\n414 173 -1.0207800000000e+00\n158 174 -9.9186010000000e-01\n163 174 -1.7922340000000e+01\n164 174 -1.7922340000000e+01\n165 174 -1.7922340000000e+01\n414 174  8.6282900000000e-01\n415 174  1.0497190000000e+00\n423 174 -7.3414950000000e-01\n157 175  8.1398600000000e-03\n415 175 -2.2212900000000e+02\n417 175  8.1398600000000e-03\n433 175 -2.2212900000000e+02\n434 175 -1.8080990000000e+00\n163 176 -1.0913280000000e+00\n164 176 -1.6293970000000e+00\n165 176 -1.4448530000000e+00\n416 176  1.0000000000000e+00\n423 176  4.7364060000000e-02\n435 176 -2.7898140000000e-02\n417 177  4.5385340000000e-03\n423 177  7.5792400000000e+00\n435 177  2.5264130000000e+00\n148 178 -1.0000000000000e+00\n178 178 -1.0000000000000e+00\n149 179 -1.0000000000000e+00\n179 179 -1.0000000000000e+00\n150 180 -1.0000000000000e+00\n180 180 -1.0000000000000e+00\n148 181  1.0266460000000e+00\n166 181 -1.0000000000000e+00\n149 182  1.0737240000000e+00\n167 182 -1.0000000000000e+00\n150 183  1.2081470000000e+00\n168 183 -1.0000000000000e+00\n148 184 -1.0000000000000e+00\n154 184 -1.0000000000000e+00\n149 185 -1.0000000000000e+00\n155 185 -1.0000000000000e+00\n150 186 -1.0000000000000e+00\n156 186 -1.0000000000000e+00\n215 187  9.9149730000000e+01\n221 187 -1.0000000000000e+00\n224 187 -3.3113980000000e-05\n216 188  1.7263960000000e+02\n222 188 -1.0000000000000e+00\n225 188 -4.1108120000000e-05\n217 189  3.5663980000000e+02\n223 189 -1.0000000000000e+00\n226 189 -8.4587180000000e-05\n218 190  2.0000080000000e+02\n221 190  2.5000000000000e+00\n224 190  3.3113980000000e-05\n219 191  3.4900330000000e+02\n222 191  2.5000000000000e+00\n225 191  4.1108120000000e-05\n220 192  7.2206780000000e+02\n223 192  2.5000000000000e+00\n226 192  8.4587180000000e-05\n194 193 -1.1483880000000e-01\n221 193  1.0000000000000e+00\n230 193 -1.1645920000000e-02\n195 194 -4.1678390000000e-01\n222 194  1.0000000000000e+00\n230 194 -1.7006160000000e-01\n196 195 -4.9676140000000e-01\n223 195  1.0000000000000e+00\n230 195 -2.4368930000000e-01\n197 196 -5.2768620000000e+03\n224 196  1.0050250000000e+00\n231 196 -1.9564470000000e-01\n198 197 -4.2415910000000e+03\n225 197  1.0028740000000e+00\n231 197 -4.9830160000000e-01\n199 198 -2.0582940000000e+03\n226 198  1.0013870000000e+00\n231 198 -3.0605370000000e-01\n194 199 -3.9872280000000e-01\n195 199 -9.9097090000000e-02\n227 199  1.0000000000000e+00\n230 199 -8.0869760000000e-02\n194 200 -4.8643840000000e-01\n196 200 -1.0055980000000e-01\n228 200  1.0000000000000e+00\n230 200 -9.8660410000000e-02\n195 201 -4.8411900000000e-01\n196 201 -4.0267880000000e-01\n229 201  1.0000000000000e+00\n230 201 -3.9507300000000e-01\n197 202 -1.0000000000000e+00\n198 202 -1.0000000000000e+00\n199 202 -1.0000000000000e+00\n230 202  1.0000000000000e+00\n232 202 -1.0000000000000e+00\n191 203 -1.0000000000000e+00\n197 203  3.2976230000000e+03\n198 203  3.2976230000000e+03\n199 203  3.2976230000000e+03\n231 203  1.0000000000000e+00\n233 203 -3.1622000000000e+05\n236 203 -1.8966660000000e+04\n237 203 -1.0000000000000e+00\n232 204  2.2669870000000e+01\n234 204  9.5486020000000e-01\n233 205  2.2487060000000e+03\n234 205 -1.0206550000000e+00\n192 206 -9.9229510000000e-01\n197 206 -2.1898570000000e+01\n198 206 -2.1898570000000e+01\n199 206 -2.1898570000000e+01\n234 206  8.9000960000000e-01\n235 206  1.0392050000000e+00\n191 207  7.7048970000000e-03\n235 207 -1.4613620000000e+02\n237 207  7.7048970000000e-03\n197 208 -6.5890520000000e-01\n198 208 -1.1064970000000e+00\n199 208 -1.0009090000000e+00\n236 208  1.0000000000000e+00\n237 209  6.8956570000000e-03\n182 210 -1.0000000000000e+00\n212 210 -1.0000000000000e+00\n183 211 -1.0000000000000e+00\n213 211 -1.0000000000000e+00\n184 212 -1.0000000000000e+00\n214 212 -1.0000000000000e+00\n182 213  1.0000000000000e+00\n200 213 -1.0000000000000e+00\n183 214  1.0226760000000e+00\n201 214 -1.0000000000000e+00\n184 215  1.0914180000000e+00\n202 215 -1.0000000000000e+00\n182 216 -1.0000000000000e+00\n188 216 -1.0000000000000e+00\n183 217 -1.0000000000000e+00\n189 217 -1.0000000000000e+00\n184 218 -1.0000000000000e+00\n190 218 -1.0000000000000e+00\n241 219 -1.9969610000000e-01\n242 219 -7.8596160000000e-01\n243 219 -6.4128230000000e-04\n244 219  4.0690410000000e-01\n253 219  2.0247020000000e-01\n254 219  7.9687960000000e-01\n255 219  6.5019060000000e-04\n256 219 -2.1665440000000e+00\n257 220 -1.0000000000000e+00\n264 220 -3.0001500000000e-01\n265 220 -4.0746150000000e-01\n246 221 -1.0000000000000e+00\n247 221 -1.0000000000000e+00\n258 221  1.0000000000000e+00\n244 222  4.0690410000000e-01\n256 222 -2.1665440000000e+00\n264 222  1.0000000000000e+00\n265 223  1.0000000000000e+00\n238 224  0.0000000000000e+00\n241 224 -9.8629890000000e-01\n250 224 -1.0000000000000e+00\n253 224  1.0000000000000e+00\n261 224  1.0000000000000e+00\n264 224  3.5018580000000e+00\n265 224  1.2418840000000e+00\n239 225  0.0000000000000e+00\n242 225 -9.8629890000000e-01\n251 225 -1.0000000000000e+00\n254 225  1.0000000000000e+00\n261 225  1.0000000000000e+00\n264 225 -2.1495590000000e+00\n265 225  9.3602390000000e-01\n240 226  0.0000000000000e+00\n243 226 -9.8629890000000e-01\n252 226 -1.0000000000000e+00\n255 226  1.0000000000000e+00\n261 226  1.0000000000000e+00\n264 226  6.0259860000000e+00\n265 226  4.0868380000000e+00\n253 227  1.1955300000000e-02\n254 227  6.1475030000000e-01\n255 227  1.6059550000000e-01\n256 227  5.9918100000000e-01\n275 227 -1.1949680000000e-02\n276 227 -6.1446120000000e-01\n277 227 -1.6052000000000e-01\n278 227 -1.0000000000000e+00\n257 228  1.0000000000000e+00\n262 228 -9.3350860000000e-02\n263 228 -3.4681810000000e-01\n266 228 -1.0000000000000e+00\n267 228 -1.0000000000000e+00\n268 228 -1.0000000000000e+00\n259 229  1.0000000000000e+00\n256 230 -5.9918100000000e-01\n262 230  1.0000000000000e+00\n278 230  1.0000000000000e+00\n263 231  1.0000000000000e+00\n250 232  1.3333420000000e+01\n253 232  7.8730110000000e-01\n260 232  1.0000000000000e+00\n262 232  1.2120260000000e+01\n263 232  7.7025090000000e-01\n275 232 -7.8693090000000e-01\n251 233  1.0205510000000e+00\n254 233  7.8730110000000e-01\n260 233  1.0000000000000e+00\n262 233 -3.9843990000000e+00\n263 233  6.8134200000000e-01\n276 233 -7.8693090000000e-01\n252 234  3.1874850000000e-03\n255 234  7.8730110000000e-01\n260 234  1.0000000000000e+00\n262 234  1.9252160000000e+01\n263 234  2.2369070000000e+00\n277 234 -7.8693090000000e-01\n253 235 -1.7008130000000e-01\n254 235 -8.2969220000000e-01\n255 235 -6.9701410000000e-04\n256 235  2.5673630000000e+00\n275 235  1.7000140000000e-01\n276 235  8.2930200000000e-01\n277 235  6.9668630000000e-04\n278 235 -4.2847870000000e+00\n279 236 -1.0000000000000e+00\n286 236 -2.5546930000000e-01\n287 236 -4.1224570000000e-01\n258 237 -1.0000000000000e+00\n259 237 -1.0000000000000e+00\n280 237  1.0000000000000e+00\n256 238  2.5673630000000e+00\n278 238 -4.2847870000000e+00\n286 238  1.0000000000000e+00\n287 239  1.0000000000000e+00\n250 240  0.0000000000000e+00\n253 240 -1.0004710000000e+00\n272 240 -1.0000000000000e+00\n275 240  1.0000000000000e+00\n283 240  1.0000000000000e+00\n286 240  2.9555290000000e+00\n287 240  1.2544140000000e+00\n251 241  0.0000000000000e+00\n254 241 -1.0004710000000e+00\n273 241 -1.0000000000000e+00\n276 241  1.0000000000000e+00\n283 241  1.0000000000000e+00\n286 241 -1.8159690000000e+00\n287 241  9.4521190000000e-01\n252 242  0.0000000000000e+00\n255 242 -1.0004710000000e+00\n274 242 -1.0000000000000e+00\n277 242  1.0000000000000e+00\n283 242  1.0000000000000e+00\n286 242  5.0849970000000e+00\n287 242  4.1364790000000e+00\n250 243  2.0247020000000e-01\n269 243 -1.0000000000000e+00\n251 244  7.9687960000000e-01\n270 244 -1.0000000000000e+00\n252 245  2.0398230000000e-01\n271 245 -1.0000000000000e+00\n275 246  9.8180810000000e-03\n276 246  6.1664170000000e-01\n278 246  9.5579440000000e-01\n297 246 -9.8175690000000e-03\n298 246 -6.1660960000000e-01\n299 246 -1.6051480000000e-01\n300 246 -1.0000000000000e+00\n279 247  1.0000000000000e+00\n284 247 -9.8217900000000e-02\n285 247 -3.4856390000000e-01\n288 247 -1.0000000000000e+00\n289 247 -1.0000000000000e+00\n290 247 -1.0000000000000e+00\n281 248  1.0000000000000e+00\n278 249 -9.5579440000000e-01\n284 249  1.0000000000000e+00\n300 249  1.0000000000000e+00\n285 250  1.0000000000000e+00\n272 251  1.3626710000000e+01\n275 251  7.8698300000000e-01\n282 251  1.0000000000000e+00\n284 251  1.2682330000000e+01\n285 251  7.6942870000000e-01\n297 251 -7.8694200000000e-01\n273 252  1.0583890000000e+00\n276 252  7.8698300000000e-01\n282 252  1.0000000000000e+00\n284 252 -4.1684890000000e+00\n285 252  6.8102850000000e-01\n298 252 -7.8694200000000e-01\n274 253  3.4155830000000e-03\n277 253  7.8698300000000e-01\n282 253  1.0000000000000e+00\n284 253  2.0139960000000e+01\n285 253  2.2394150000000e+00\n299 253 -7.8694200000000e-01\n275 254 -1.6786980000000e-01\n276 254 -8.3148250000000e-01\n277 254 -6.9990470000000e-04\n278 254  4.3289930000000e+00\n297 254  1.6786100000000e-01\n298 254  8.3143910000000e-01\n299 254  6.9986820000000e-04\n300 254 -4.5292090000000e+00\n301 255 -1.0000000000000e+00\n308 255 -2.5301530000000e-01\n309 255 -4.1256250000000e-01\n280 256 -1.0000000000000e+00\n281 256 -1.0000000000000e+00\n302 256  1.0000000000000e+00\n278 257  4.3289930000000e+00\n300 257 -4.5292090000000e+00\n308 257  1.0000000000000e+00\n309 258  1.0000000000000e+00\n272 259  0.0000000000000e+00\n275 259 -1.0000520000000e+00\n294 259 -1.0000000000000e+00\n297 259  1.0000000000000e+00\n305 259  1.0000000000000e+00\n308 259  2.9254360000000e+00\n309 259  1.2552490000000e+00\n273 260  0.0000000000000e+00\n276 260 -1.0000520000000e+00\n295 260 -1.0000000000000e+00\n298 260  1.0000000000000e+00\n305 260  1.0000000000000e+00\n308 260 -1.7975930000000e+00\n309 260  9.4582430000000e-01\n274 261  0.0000000000000e+00\n277 261 -1.0000520000000e+00\n296 261 -1.0000000000000e+00\n299 261  1.0000000000000e+00\n305 261  1.0000000000000e+00\n308 261  5.0331660000000e+00\n309 261  4.1397830000000e+00\n272 262  1.7000140000000e-01\n291 262 -1.0000000000000e+00\n273 263  8.2930200000000e-01\n292 263 -1.0000000000000e+00\n274 264  2.0397290000000e-01\n293 264 -1.0000000000000e+00\n297 265  9.6798500000000e-03\n298 265  6.1671090000000e-01\n299 265  1.6051810000000e-01\n300 265  9.9729840000000e-01\n319 265 -9.6801700000000e-03\n320 265 -6.1673130000000e-01\n321 265 -1.6052340000000e-01\n322 265 -1.0000000000000e+00\n301 266  1.0000000000000e+00\n306 266 -9.8528720000000e-02\n307 266 -3.4867100000000e-01\n310 266 -1.0000000000000e+00\n311 266 -1.0000000000000e+00\n312 266 -1.0000000000000e+00\n303 267  1.0000000000000e+00\n300 268 -9.9729840000000e-01\n306 268  1.0000000000000e+00\n322 268  1.0000000000000e+00\n307 269  1.0000000000000e+00\n294 270  1.3646010000000e+01\n297 270  7.8690890000000e-01\n304 270  1.0000000000000e+00\n306 270  1.2716190000000e+01\n307 270  7.6935860000000e-01\n319 270 -7.8693490000000e-01\n295 271  1.0608970000000e+00\n298 271  7.8690890000000e-01\n304 271  1.0000000000000e+00\n306 271 -4.1795750000000e+00\n307 271  6.8099360000000e-01\n320 271 -7.8693490000000e-01\n296 272  3.4309680000000e-03\n299 272  7.8690890000000e-01\n304 272  1.0000000000000e+00\n306 272  2.0193410000000e+01\n307 272  2.2395320000000e+00\n321 272 -7.8693490000000e-01\n297 273 -1.6772330000000e-01\n298 273 -8.3154050000000e-01\n299 273 -7.0311130000000e-04\n300 273  4.5319110000000e+00\n319 273  1.6772880000000e-01\n320 273  8.3156800000000e-01\n321 273  7.0313460000000e-04\n322 273 -4.5441880000000e+00\n323 274 -1.0000000000000e+00\n330 274 -2.5288910000000e-01\n331 274 -4.1262900000000e-01\n302 275 -1.0000000000000e+00\n303 275 -1.0000000000000e+00\n324 275  1.0000000000000e+00\n300 276  4.5319110000000e+00\n322 276 -4.5441880000000e+00\n330 276  1.0000000000000e+00\n331 277  1.0000000000000e+00\n294 278  0.0000000000000e+00\n297 278 -9.9996690000000e-01\n316 278 -1.0000000000000e+00\n319 278  1.0000000000000e+00\n327 278  1.0000000000000e+00\n330 278  2.9235700000000e+00\n331 278  1.2552940000000e+00\n295 279  0.0000000000000e+00\n298 279 -9.9996690000000e-01\n317 279 -1.0000000000000e+00\n320 279  1.0000000000000e+00\n327 279  1.0000000000000e+00\n330 279 -1.7964900000000e+00\n331 279  9.4585160000000e-01\n296 280  0.0000000000000e+00\n299 280 -9.9996690000000e-01\n318 280 -1.0000000000000e+00\n321 280  1.0000000000000e+00\n327 280  1.0000000000000e+00\n330 280  5.0299350000000e+00\n331 280  4.1401400000000e+00\n294 281  1.6786100000000e-01\n313 281 -1.0000000000000e+00\n295 282  8.3143910000000e-01\n314 282 -1.0000000000000e+00\n296 283  2.0398560000000e-01\n315 283 -1.0000000000000e+00\n319 284  9.6473500000000e-03\n320 284  6.1499680000000e-01\n321 284  1.6066380000000e-01\n322 284  1.0122750000000e+00\n341 284 -9.6630710000000e-03\n342 284 -6.1599900000000e-01\n343 284 -1.6092570000000e-01\n344 284 -1.0000000000000e+00\n323 285  1.0000000000000e+00\n328 285 -9.7740150000000e-02\n329 285 -3.4838900000000e-01\n332 285 -1.0000000000000e+00\n333 285 -1.0000000000000e+00\n334 285 -1.0000000000000e+00\n325 286  1.0000000000000e+00\n322 287 -1.0122750000000e+00\n328 287  1.0000000000000e+00\n344 287  1.0000000000000e+00\n329 288  1.0000000000000e+00\n316 289  1.3653370000000e+01\n319 289  7.8530800000000e-01\n326 289  1.0000000000000e+00\n328 289  1.2536040000000e+01\n329 289  7.6861380000000e-01\n341 289 -7.8658770000000e-01\n317 290  1.0618540000000e+00\n320 290  7.8530800000000e-01\n326 290  1.0000000000000e+00\n328 290 -4.1203450000000e+00\n329 290  6.8034460000000e-01\n342 290 -7.8658770000000e-01\n318 291  3.4368480000000e-03\n321 291  7.8530800000000e-01\n326 291  1.0000000000000e+00\n328 291  1.9907200000000e+01\n329 291  2.2374860000000e+00\n343 291 -7.8658770000000e-01\n319 292 -1.6769600000000e-01\n320 292 -8.2983350000000e-01\n321 292 -8.4358210000000e-04\n322 292  4.5319130000000e+00\n341 292  1.6796930000000e-01\n342 292  8.3118580000000e-01\n343 292  8.4495670000000e-04\n344 292 -4.4769570000000e+00\n345 293 -1.0000000000000e+00\n352 293 -2.5422820000000e-01\n353 293 -4.1467850000000e-01\n324 294 -1.0000000000000e+00\n325 294 -1.0000000000000e+00\n346 294  1.0000000000000e+00\n322 295  4.5319120000000e+00\n344 295 -4.4769570000000e+00\n352 295  1.0000000000000e+00\n353 296  1.0000000000000e+00\n316 297  0.0000000000000e+00\n319 297 -9.9837310000000e-01\n338 297 -1.0000000000000e+00\n341 297  1.0000000000000e+00\n349 297  1.0000000000000e+00\n352 297  2.9258000000000e+00\n353 297  1.2548710000000e+00\n317 298  0.0000000000000e+00\n320 298 -9.9837310000000e-01\n339 298 -1.0000000000000e+00\n342 298  1.0000000000000e+00\n349 298  1.0000000000000e+00\n352 298 -1.7994740000000e+00\n353 298  9.4529590000000e-01\n318 299  0.0000000000000e+00\n321 299 -9.9837310000000e-01\n340 299 -1.0000000000000e+00\n343 299  1.0000000000000e+00\n349 299  1.0000000000000e+00\n352 299  5.0329780000000e+00\n353 299  4.1465320000000e+00\n316 300  1.6772880000000e-01\n335 300 -1.0000000000000e+00\n317 301  8.3156800000000e-01\n336 301 -1.0000000000000e+00\n318 302  2.0458700000000e-01\n337 302 -1.0000000000000e+00\n341 303  8.9580030000000e-03\n342 303  5.6239150000000e-01\n343 303  1.7143160000000e-01\n344 303  1.5349870000000e+00\n363 303 -9.3684010000000e-03\n364 303 -5.8815670000000e-01\n365 303 -1.7928550000000e-01\n366 303 -1.0000000000000e+00\n345 304  1.0000000000000e+00\n350 304 -7.6424570000000e-02\n351 304 -3.3630700000000e-01\n354 304 -1.0000000000000e+00\n355 304 -1.0000000000000e+00\n356 304 -1.0000000000000e+00\n347 305  1.0000000000000e+00\n344 306 -1.5349870000000e+00\n350 306  1.0000000000000e+00\n366 306  1.0000000000000e+00\n351 307  1.0000000000000e+00\n338 308  1.3927700000000e+01\n341 308  7.4278120000000e-01\n348 308  1.0000000000000e+00\n350 308  7.7124140000000e+00\n351 308  7.3754050000000e-01\n363 308 -7.7681060000000e-01\n339 309  1.0977920000000e+00\n342 309  7.4278120000000e-01\n348 309  1.0000000000000e+00\n350 309 -2.5345340000000e+00\n351 309  6.5320800000000e-01\n364 309 -7.7681060000000e-01\n340 310  3.6610400000000e-03\n343 310  7.4278120000000e-01\n348 310  1.0000000000000e+00\n350 310  1.2244490000000e+01\n351 310  2.1513860000000e+00\n365 310 -7.7681060000000e-01\n341 311 -1.6726420000000e-01\n342 311 -7.7757830000000e-01\n343 311 -1.1350930000000e-02\n344 311  3.9419710000000e+00\n363 311  1.7492720000000e-01\n364 311  8.1320190000000e-01\n365 311  1.1870950000000e-02\n366 311 -2.5680820000000e+00\n367 312 -1.0000000000000e+00\n374 312 -3.1132270000000e-01\n375 312 -4.5572680000000e-01\n346 313 -1.0000000000000e+00\n347 313 -1.0000000000000e+00\n368 313  1.0000000000000e+00\n344 314  3.9419710000000e+00\n366 314 -2.5680820000000e+00\n374 314  1.0000000000000e+00\n375 315  1.0000000000000e+00\n338 316  0.0000000000000e+00\n341 316 -9.5619350000000e-01\n360 316 -1.0000000000000e+00\n363 316  1.0000000000000e+00\n371 316  1.0000000000000e+00\n374 316  3.1494540000000e+00\n375 316  1.2129980000000e+00\n339 317  0.0000000000000e+00\n342 317 -9.5619350000000e-01\n361 317 -1.0000000000000e+00\n364 317  1.0000000000000e+00\n371 317  1.0000000000000e+00\n374 317 -1.9859190000000e+00\n375 317  9.0706840000000e-01\n340 318  0.0000000000000e+00\n343 318 -9.5619350000000e-01\n362 318 -1.0000000000000e+00\n365 318  1.0000000000000e+00\n371 318  1.0000000000000e+00\n374 318  5.3936870000000e+00\n375 318  4.2274630000000e+00\n338 319  1.6796930000000e-01\n357 319 -1.0000000000000e+00\n339 320  8.3118580000000e-01\n358 320 -1.0000000000000e+00\n340 321  2.3079690000000e-01\n359 321 -1.0000000000000e+00\n363 322  4.9560030000000e-03\n364 322  2.0925110000000e-01\n365 322  4.3415660000000e-01\n366 322  6.1773840000000e+00\n385 322 -5.6864040000000e-03\n386 322 -2.4008990000000e-01\n387 322 -4.9814130000000e-01\n388 322 -1.0000000000000e+00\n367 323  1.0000000000000e+00\n372 323 -5.1899590000000e-02\n373 323 -2.2819930000000e-01\n376 323 -1.0000000000000e+00\n377 323 -1.0000000000000e+00\n378 323 -1.0000000000000e+00\n369 324  1.0000000000000e+00\n366 325 -6.1773840000000e+00\n372 325  1.0000000000000e+00\n388 325  1.0000000000000e+00\n373 326  1.0000000000000e+00\n360 327  2.2884660000000e+01\n363 327  6.4836370000000e-01\n370 327  1.0000000000000e+00\n372 327  1.0434500000000e+00\n373 327  4.2175860000000e-01\n385 327 -7.4391760000000e-01\n361 328  2.5197030000000e+00\n364 328  6.4836370000000e-01\n370 328  1.0000000000000e+00\n372 328 -3.4146640000000e-01\n373 328  3.7988980000000e-01\n386 328 -7.4391760000000e-01\n362 329  1.7727920000000e-02\n365 329  6.4836370000000e-01\n370 329  1.0000000000000e+00\n372 329  1.6460520000000e+00\n373 329  1.3054760000000e+00\n387 329 -7.4391760000000e-01\n360 330  1.7492720000000e-01\n379 330 -1.0000000000000e+00\n361 331  8.1320190000000e-01\n380 331 -1.0000000000000e+00\n362 332  6.6961900000000e-01\n381 332 -1.0000000000000e+00\n87 333  6.3180580000000e+00\n93 333  1.0081210000000e+00\n88 334  2.1016520000000e+00\n94 334  9.8325000000000e-01\n89 335  1.0216340000000e+01\n95 335  9.7112200000000e-01\n90 336  4.7715330000000e+00\n96 336  1.0168970000000e+00\n91 337  1.5445530000000e+00\n97 337  9.6515200000000e-01\n92 338  7.4032580000000e+00\n98 338  9.3991980000000e-01\n99 339  2.7676480000000e+02\n105 339  8.8770670000000e-01\n100 340  1.9219040000000e+02\n106 340  1.2620630000000e+00\n101 341  4.6529740000000e+02\n107 341  8.3730050000000e-01\n102 342  4.0263530000000e+02\n108 342  9.3272340000000e-01\n103 343  2.4395160000000e+02\n109 343  1.1570060000000e+00\n104 344  6.9442570000000e+02\n110 344  9.0252430000000e-01\n111 345  2.1471690000000e+00\n117 345  7.3310410000000e-01\n112 346  1.8303540000000e+00\n118 346  7.7070690000000e-01\n113 347  5.4194960000000e+00\n119 347  9.1067970000000e-01\n114 348  1.5934600000000e+00\n120 348  4.4472830000000e-01\n115 349  1.5193590000000e+00\n121 349  5.2296010000000e-01\n116 350  5.9272710000000e+00\n122 350  8.1417070000000e-01\n123 351  8.6013230000000e+00\n129 351  5.8171510000000e-01\n124 352  6.1974850000000e+00\n130 352  5.3220720000000e-01\n125 353  3.7670330000000e+01\n131 353  1.1683300000000e+00\n126 354  1.0955350000000e+01\n132 354  7.4939930000000e-01\n127 355  8.2864270000000e+00\n133 355  7.1973830000000e-01\n128 356  3.5092930000000e+01\n134 356  1.1008490000000e+00\n135 357  4.3389190000000e-01\n138 357  2.2797130000000e+00\n136 358  1.1375720000000e-01\n139 358  6.0698210000000e-01\n137 359  4.0354730000000e-01\n140 359  8.0049890000000e-03\n141 360  1.1577040000000e+00\n144 360  4.0422280000000e+00\n142 361  4.1932590000000e-01\n145 361  2.4496110000000e+00\n143 362  1.0246470000000e-01\n146 362  3.6475180000000e-01\n151 363  1.7257450000000e+02\n154 363  1.4917610000000e+01\n152 364  1.6158450000000e+02\n155 364  1.2093800000000e+01\n153 365  1.4531450000000e+02\n156 365  5.7400960000000e+00\n157 366  4.5018890000000e-03\n158 366  9.5263590000000e-01\n159 366 -1.0000000000000e+00\n158 367  9.4488160000000e-01\n163 367  1.9882060000000e+01\n164 367  1.5998700000000e+01\n165 367  7.7694990000000e+00\n159 368  1.0081400000000e+00\n163 368  9.8828980000000e+01\n164 368  1.4755580000000e+02\n165 368  1.3084370000000e+02\n160 369  1.0000000000000e+00\n163 369  1.8011980000000e+00\n161 370  1.0000000000000e+00\n164 370  2.1962210000000e+00\n162 371  1.0000000000000e+00\n165 371  2.0607380000000e+00\n163 372  1.9882060000000e+01\n166 372  9.7404530000000e-01\n164 373  1.5998700000000e+01\n167 373  9.3133780000000e-01\n165 374  7.7694990000000e+00\n168 374  8.2771400000000e-01\n169 375 -1.0000000000000e+00\n172 375 -1.0000000000000e+00\n175 375  5.6357910000000e-02\n176 375  5.6357910000000e-02\n177 375  5.6357910000000e-02\n170 376 -1.0000000000000e+00\n173 376 -1.0000000000000e+00\n175 376  7.3959730000000e-01\n176 376  7.3959730000000e-01\n177 376  7.3959730000000e-01\n171 377 -1.0000000000000e+00\n174 377 -1.0000000000000e+00\n175 377  2.0404480000000e-01\n176 377  2.0404480000000e-01\n177 377  2.0404480000000e-01\n172 378  1.0000000000000e+00\n175 378 -1.0000000000000e+00\n173 379  1.0000000000000e+00\n176 379 -1.0000000000000e+00\n174 380  1.0000000000000e+00\n177 380 -1.0000000000000e+00\n175 381  1.0000000000000e+00\n178 381  1.0000000000000e+00\n176 382  1.0000000000000e+00\n179 382  1.0000000000000e+00\n177 383  1.0000000000000e+00\n180 383  1.0000000000000e+00\n102 384 -1.9453890000000e+01\n418 384  1.0000000000000e+00\n424 384 -9.5304210000000e-02\n103 385 -2.2090310000000e+01\n419 385  1.0000000000000e+00\n424 385 -8.8197620000000e-02\n104 386 -4.9563590000000e+01\n420 386  1.0000000000000e+00\n424 386 -1.0690420000000e-04\n421 387  1.7973450000000e+02\n422 387 -2.5957400000000e+00\n422 388  1.0000000000000e+00\n423 388 -9.6216520000000e-02\n102 389 -1.0000000000000e+00\n103 389 -1.0000000000000e+00\n104 389 -1.0000000000000e+00\n423 389  9.6216520000000e-02\n424 389 -8.8937280000000e-03\n126 390  9.3082790000000e-01\n127 390  9.3082790000000e-01\n128 390  9.3082790000000e-01\n425 390 -1.1383520000000e+00\n436 390  9.5341780000000e-02\n126 391  8.1769790000000e-01\n426 391 -5.5083520000000e-01\n436 391  4.6134780000000e-02\n127 392  8.1769790000000e-01\n427 392 -4.4892230000000e-01\n436 392  3.7599150000000e-02\n128 393  6.8068650000000e+00\n428 393 -2.0188420000000e-03\n436 393  1.6908660000000e-04\n429 394 -6.0313590000000e-01\n430 394 -1.1914260000000e+00\n431 394 -2.0901010000000e-01\n432 394 -2.3236640000000e-01\n126 395 -1.5881990000000e+00\n430 395  1.0000000000000e+00\n436 395 -8.9606730000000e-02\n127 396 -1.7894780000000e+00\n431 396  1.0000000000000e+00\n436 396 -8.2283250000000e-02\n128 397 -4.0128040000000e+00\n432 397  1.0000000000000e+00\n436 397 -9.9680420000000e-05\n433 398  1.1868740000000e+00\n435 398 -8.7134320000000e-01\n434 399  9.9186010000000e-01\n435 399 -7.3414950000000e-01\n126 400 -1.0000000000000e+00\n127 400 -1.0000000000000e+00\n128 400 -1.0000000000000e+00\n435 400  8.9782490000000e-01\n436 400 -1.0242690000000e-01\n185 401  2.6330250000000e+02\n188 401  1.6710230000000e+01\n186 402  2.5231250000000e+02\n189 402  1.5091380000000e+01\n187 403  2.3604250000000e+02\n190 403  1.1440290000000e+01\n191 404  6.8429330000000e-03\n192 404  9.6227440000000e-01\n193 404 -1.0000000000000e+00\n192 405  9.5486020000000e-01\n197 405  3.5042120000000e+01\n198 405  2.8167190000000e+01\n199 405  1.3668540000000e+01\n193 406  1.0077050000000e+00\n197 406  8.5846760000000e+01\n198 406  1.4416210000000e+02\n199 406  1.3040540000000e+02\n194 407  1.0000000000000e+00\n197 407  1.6589050000000e+00\n195 408  1.0000000000000e+00\n198 408  2.1064970000000e+00\n196 409  1.0000000000000e+00\n199 409  2.0009090000000e+00\n197 410  3.5042120000000e+01\n200 410  1.0000000000000e+00\n198 411  2.8167190000000e+01\n201 411  9.7782690000000e-01\n199 412  1.3668540000000e+01\n202 412  9.1623940000000e-01\n203 413 -1.0000000000000e+00\n206 413 -1.0000000000000e+00\n209 413  3.4351900000000e-03\n210 413  3.4351900000000e-03\n211 413  3.4351900000000e-03\n204 414 -1.0000000000000e+00\n207 414 -1.0000000000000e+00\n209 414  4.3016970000000e-02\n210 414  4.3016970000000e-02\n211 414  4.3016970000000e-02\n205 415 -1.0000000000000e+00\n208 415 -1.0000000000000e+00\n209 415  9.5354780000000e-01\n210 415  9.5354780000000e-01\n211 415  9.5354780000000e-01\n206 416  1.0000000000000e+00\n209 416 -1.0000000000000e+00\n207 417  1.0000000000000e+00\n210 417 -1.0000000000000e+00\n208 418  1.0000000000000e+00\n211 418 -1.0000000000000e+00\n209 419  1.0000000000000e+00\n212 419  1.0000000000000e+00\n210 420  1.0000000000000e+00\n213 420  1.0000000000000e+00\n211 421  1.0000000000000e+00\n214 421  1.0000000000000e+00\n90 422 -4.7613130000000e-02\n461 422  1.0000000000000e+00\n467 422 -2.3334700000000e-05\n91 423 -5.7464350000000e-02\n462 423  1.0000000000000e+00\n467 423 -3.5266560000000e-04\n92 424 -1.2956040000000e-01\n463 424  1.0000000000000e+00\n467 424 -1.7625420000000e-02\n464 425  2.7046250000000e+02\n465 425 -2.8000670000000e+00\n465 426  1.0000000000000e+00\n466 426 -1.6856930000000e+00\n90 427 -1.0000000000000e+00\n91 427 -1.0000000000000e+00\n92 427 -1.0000000000000e+00\n466 427  1.6856930000000e+00\n467 427 -1.4266740000000e-01\n114 428  1.2149740000000e-01\n115 428  1.2149740000000e-01\n116 428  1.2149740000000e-01\n468 428 -1.1383520000000e+00\n479 428  2.1230520000000e-02\n114 429  6.0555750000000e-01\n469 429 -1.9490180000000e-02\n479 429  3.6349630000000e-04\n115 430  3.3579270000000e-01\n470 430 -1.3533830000000e-01\n479 430  2.5240900000000e-03\n116 431  1.0673090000000e-01\n471 431 -9.5354780000000e-01\n479 431  1.7783880000000e-02\n472 432 -9.0759220000000e-01\n473 432 -5.7118220000000e+00\n474 432 -9.3568410000000e-01\n475 432 -1.0346550000000e+00\n114 433 -4.3240930000000e-02\n473 433  1.0000000000000e+00\n479 433 -2.5956110000000e-05\n115 434 -5.2174910000000e-02\n474 434  1.0000000000000e+00\n479 434 -3.9218900000000e-04\n116 435 -1.1763140000000e-01\n475 435  1.0000000000000e+00\n479 435 -1.9600160000000e-02\n476 436  5.3140780000000e+00\n478 436 -1.0021840000000e+00\n477 437  3.4483720000000e-01\n478 437 -2.6478620000000e-01\n114 438 -1.0000000000000e+00\n115 438 -1.0000000000000e+00\n116 438 -1.0000000000000e+00\n478 438  1.7669710000000e+00\n479 438 -1.7474060000000e-01\n438 439  9.9149730000000e+01\n444 439 -1.0000000000000e+00\n447 439 -3.3113980000000e-05\n439 440  1.7263960000000e+02\n445 440 -1.0000000000000e+00\n448 440 -4.1108120000000e-05\n440 441  3.5663980000000e+02\n446 441 -1.0000000000000e+00\n449 441 -8.4587180000000e-05\n441 442  2.0000080000000e+02\n444 442  2.5000000000000e+00\n447 442  3.3113980000000e-05\n442 443  3.4900330000000e+02\n445 443  2.5000000000000e+00\n448 443  4.1108120000000e-05\n443 444  7.2206780000000e+02\n446 444  2.5000000000000e+00\n449 444  8.4587180000000e-05\n444 445  1.0000000000000e+00\n453 445 -1.4485650000000e-06\n445 446  1.0000000000000e+00\n453 446 -5.1132920000000e-04\n446 447  1.0000000000000e+00\n453 447 -9.5438870000000e-01\n447 448  1.0050250000000e+00\n454 448 -3.4351900000000e-03\n448 449  1.0028740000000e+00\n454 449 -4.3016970000000e-02\n449 450  1.0013870000000e+00\n454 450 -9.5354780000000e-01\n450 451  1.0000000000000e+00\n453 451 -4.9455600000000e-05\n451 452  1.0000000000000e+00\n453 452 -2.1775570000000e-03\n452 453  1.0000000000000e+00\n453 453 -4.2871530000000e-02\n453 454  1.0000000000000e+00\n455 454 -1.0000000000000e+00\n466 454  1.5000000000000e+00\n478 454  5.0000000000000e-01\n454 455  1.0000000000000e+00\n456 455 -3.1622000000000e+05\n459 455 -1.2132580000000e+04\n460 455 -1.0000000000000e+00\n466 455 -2.0451810000000e+04\n477 455  9.1527510000000e+03\n455 456  9.1463570000000e+00\n457 456  3.7734920000000e-03\n456 457  2.2487060000000e+03\n457 457 -1.2505330000000e-01\n457 458  6.7588380000000e-02\n458 458  6.5087120000000e+01\n466 458 -1.8859040000000e-01\n458 459 -9.1527510000000e+03\n460 459  7.5439430000000e-01\n476 459 -9.1527510000000e+03\n477 459 -6.9047830000000e+03\n459 460  1.0000000000000e+00\n466 460  1.8569290000000e-01\n478 460 -5.0000000000000e-01\n460 461  1.9167940000000e-04\n466 461  2.6684520000000e+00\n478 461  8.8948400000000e-01\n266 462  5.2397100000000e-01\n269 462  2.5902730000000e+00\n267 463  1.2090360000000e-01\n270 463  1.0000000000000e+00\n268 464  3.6607730000000e-01\n271 464  1.8323330000000e-02\n288 465  5.3070830000000e-01\n291 465  2.6120320000000e+00\n289 466  1.2143810000000e-01\n292 466  1.0000000000000e+00\n290 467  3.6327480000000e-01\n293 467  1.9398480000000e-02\n310 468  5.3114850000000e-01\n313 468  2.6134470000000e+00\n311 469  1.2147310000000e-01\n314 469  1.0000000000000e+00\n312 470  3.6309170000000e-01\n315 470  1.9470450000000e-02\n332 471  5.3131620000000e-01\n335 471  2.6139860000000e+00\n333 472  1.2148640000000e-01\n336 472  1.0000000000000e+00\n334 473  3.6302190000000e-01\n337 473  1.9497930000000e-02\n354 474  5.3753340000000e-01\n357 474  2.6338800000000e+00\n355 475  1.2197960000000e-01\n358 475  1.0000000000000e+00\n356 476  3.6043580000000e-01\n359 476  2.0538460000000e-02\n376 477  7.1092830000000e-01\n379 477  3.1304670000000e+00\n377 478  1.3573580000000e-01\n380 478  1.0000000000000e+00\n378 479  2.8830910000000e-01\n381 479  7.1489880000000e-02\n"
  },
  {
    "path": "examples/module.mk",
    "content": "%canon_reldir%_EXTRA_DIST =\n\ninclude %reldir%/code/module.mk\ninclude %reldir%/data/module.mk\n\n%canon_reldir%_EXTRA_DIST += \\\n  %reldir%/code/COPYING\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n"
  },
  {
    "path": "libgui/graphics/BaseControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QEvent>\n#include <QKeyEvent>\n#include <QMouseEvent>\n#include <QWidget>\n\n#include \"BaseControl.h\"\n#include \"ContextMenu.h\"\n#include \"QtHandlesUtils.h\"\n\n#include \"octave-qt-features.h\"\n\n#include \"graphics.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic void\nupdatePalette (const uicontrol::properties& props, QWidget *w)\n{\n  QPalette p = w->palette ();\n\n  if (props.style_is (\"edit\")\n      || props.style_is (\"listbox\"))\n    {\n      Matrix bg_color = props.get_backgroundcolor_rgb ();\n      // Matlab compatibility: Default color is ignored, and rendered as\n      // white ([1.0, 1.0, 1.0]).  See bug #58261.\n      if (bg_color(0) == bg_color(1) && bg_color(0) == bg_color(2)\n          && (std::abs (bg_color(1) - 0.94) < .005))\n        bg_color.fill (1.0);\n\n      p.setColor (QPalette::Active, QPalette::Base,\n                  Utils::fromRgb (bg_color));\n      p.setColor (QPalette::Inactive, QPalette::Base,\n                  Utils::fromRgb (bg_color));\n      p.setColor (QPalette::Active, QPalette::Text,\n                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));\n      p.setColor (QPalette::Inactive, QPalette::Text,\n                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));\n    }\n  else if (props.style_is (\"popupmenu\"))\n    {\n      // popupmenu (QComboBox) is a listbox with a button.\n      // This requires setting colors for both.\n      QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ());\n      QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ());\n      QString qss = QString (\":enabled { background: %1 none;\\n\"\n                                        \"color: %2; }\")\n                    .arg(bcol.name ()).arg (fcol.name ());\n      w->setStyleSheet (qss);\n      return;\n    }\n  else if (props.style_is (\"radiobutton\")\n           || props.style_is (\"checkbox\"))\n    {\n      p.setColor (QPalette::Active, QPalette::Button,\n                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));\n      p.setColor (QPalette::Inactive, QPalette::Button,\n                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));\n      p.setColor (QPalette::Active, QPalette::WindowText,\n                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));\n      p.setColor (QPalette::Inactive, QPalette::WindowText,\n                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));\n    }\n  else if (props.style_is (\"pushbutton\")\n           || props.style_is (\"togglebutton\"))\n    {\n      QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ());\n      QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ());\n      QString qss = QString (\":enabled { background: %1 none;\\n\"\n                                        \"color: %2; }\")\n                    .arg(bcol.name ()).arg (fcol.name ());\n      w->setStyleSheet (qss);\n      return;\n    }\n  else\n    {\n      p.setColor (QPalette::Active, QPalette::Window,\n                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));\n      p.setColor (QPalette::Inactive, QPalette::Window,\n                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));\n      p.setColor (QPalette::Active, QPalette::WindowText,\n                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));\n      p.setColor (QPalette::Inactive, QPalette::WindowText,\n                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));\n    }\n\n  w->setPalette (p);\n}\n\nBaseControl::BaseControl (octave::interpreter& interp,\n                          const graphics_object& go, QWidget *w)\n  : Object (interp, go, w), m_normalizedFont (false),\n    m_keyPressHandlerDefined (false)\n{\n  qObject ()->setObjectName (\"UIControl\");\n  init (w);\n}\n\nvoid\nBaseControl::init (QWidget *w, bool callBase)\n{\n  if (callBase)\n    Object::init (w, callBase);\n\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  Matrix bb = up.get_boundingbox (false);\n  w->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)),\n                  octave::math::round (bb(2)), octave::math::round (bb(3)));\n  w->setFont (Utils::computeFont<uicontrol> (up, bb(3)));\n  updatePalette (up, w);\n  if (up.enable_is (\"inactive\"))\n    w->blockSignals (true);\n  else\n    w->setEnabled (up.enable_is (\"on\"));\n  w->setToolTip (Utils::fromStdString (up.get_tooltipstring ()));\n  w->setVisible (up.is_visible ());\n  m_keyPressHandlerDefined = ! up.get_keypressfcn ().isempty ();\n\n  w->installEventFilter (this);\n\n  m_normalizedFont = up.fontunits_is (\"normalized\");\n}\n\nBaseControl::~BaseControl ()\n{ }\n\nvoid\nBaseControl::redraw ()\n{\n  update (uicontrol::properties::ID_POSITION);\n}\n\nvoid\nBaseControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QWidget *w = qWidget<QWidget> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_POSITION:\n      {\n        Matrix bb = up.get_boundingbox (false);\n        w->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)),\n                        octave::math::round (bb(2)), octave::math::round (bb(3)));\n      }\n      break;\n\n    case uicontrol::properties::ID_FONTNAME:\n    case uicontrol::properties::ID_FONTSIZE:\n    case uicontrol::properties::ID_FONTWEIGHT:\n    case uicontrol::properties::ID_FONTANGLE:\n      w->setFont (Utils::computeFont<uicontrol> (up));\n      break;\n\n    case uicontrol::properties::ID_FONTUNITS:\n      // FIXME: We shouldn't have to do anything, octave should update\n      //        the \"fontsize\" property automatically to the new units.\n      //        Hence the actual font used shouldn't change.\n      m_normalizedFont = up.fontunits_is (\"normalized\");\n      break;\n\n    case uicontrol::properties::ID_BACKGROUNDCOLOR:\n    case uicontrol::properties::ID_FOREGROUNDCOLOR:\n      updatePalette (up, w);\n      break;\n\n    case uicontrol::properties::ID_ENABLE:\n      if (up.enable_is (\"inactive\"))\n        {\n          w->blockSignals (true);\n          w->setEnabled (true);\n        }\n      else\n        {\n          w->blockSignals (false);\n          w->setEnabled (up.enable_is (\"on\"));\n        }\n      break;\n\n    case uicontrol::properties::ID_TOOLTIPSTRING:\n      w->setToolTip (Utils::fromStdString (up.get_tooltipstring ()));\n      break;\n\n    case base_properties::ID_VISIBLE:\n      w->setVisible (up.is_visible ());\n      break;\n\n    case uicontrol::properties::ID_KEYPRESSFCN:\n      m_keyPressHandlerDefined = ! up.get_keypressfcn ().isempty ();\n      break;\n\n    case uicontrol::properties::ID___FOCUS__:\n      if (up.is___focus__ ())\n        w->setFocus ();\n      else\n        w->clearFocus ();\n      break;\n\n    default:\n      break;\n    }\n}\n\nbool\nBaseControl::eventFilter (QObject *watched, QEvent *xevent)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  switch (xevent->type ())\n    {\n    case QEvent::Resize:\n      if (m_normalizedFont)\n        {\n          octave::autolock guard (gh_mgr.graphics_lock ());\n\n          qWidget<QWidget> ()->setFont (Utils::computeFont<uicontrol>\n                                        (properties<uicontrol> ()));\n        }\n      break;\n\n    case QEvent::MouseButtonPress:\n      {\n        octave::autolock guard (gh_mgr.graphics_lock ());\n\n        QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);\n        graphics_object go = object ();\n        uicontrol::properties& up = Utils::properties<uicontrol> (go);\n        graphics_object fig = go.get_ancestor (\"figure\");\n        if (fig)\n          {\n            Q_EMIT gh_set_event (fig.get_handle (), \"currentobject\",\n                                 m_handle.value (), false);\n\n            if (m->button () != Qt::LeftButton || ! up.enable_is (\"on\"))\n              {\n                Q_EMIT gh_set_event (fig.get_handle (), \"selectiontype\",\n                                     Utils::figureSelectionType (m), false);\n                Q_EMIT gh_set_event (fig.get_handle (), \"currentpoint\",\n                                     Utils::figureCurrentPoint (fig, m),\n                                     false);\n                Q_EMIT gh_callback_event (fig.get_handle (),\n                                          \"windowbuttondownfcn\");\n                Q_EMIT gh_callback_event (m_handle, \"buttondownfcn\");\n\n                if (m->button () == Qt::RightButton)\n                  ContextMenu::executeAt (m_interpreter, up,\n#if defined (HAVE_QSINGLEPOINTEVENT_CLASS)\n                                          m->globalPosition ().toPoint ());\n#else\n                                          m->globalPos ());\n#endif\n              }\n            else\n              {\n                if (up.style_is (\"listbox\"))\n                  Q_EMIT gh_set_event (fig.get_handle (), \"selectiontype\",\n                                       Utils::figureSelectionType (m),\n                                       false);\n                else\n                  Q_EMIT gh_set_event (fig.get_handle (), \"selectiontype\",\n                                       octave_value (\"normal\"), false);\n              }\n          }\n      }\n      break;\n\n    case QEvent::MouseMove:\n      if (qWidget<QWidget> ()->hasMouseTracking ())\n        {\n          octave::autolock guard (gh_mgr.graphics_lock ());\n\n          QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);\n          graphics_object go = object ();\n          graphics_object fig = go.get_ancestor (\"figure\");\n\n          if (fig)\n            {\n              Q_EMIT gh_set_event (fig.get_handle (), \"currentpoint\",\n                                   Utils::figureCurrentPoint (fig, m), false);\n              Q_EMIT gh_callback_event (fig.get_handle (),\n                                        \"windowbuttonmotionfcn\");\n            }\n        }\n      break;\n\n    case QEvent::KeyPress:\n      if (m_keyPressHandlerDefined)\n        {\n          octave::autolock guard (gh_mgr.graphics_lock ());\n\n          octave_scalar_map keyEvent =\n            Utils::makeKeyEventStruct (dynamic_cast<QKeyEvent *> (xevent));\n          keyEvent.setfield (\"Source\",\n                             object ().get_handle ().as_octave_value ());\n          keyEvent.setfield (\"EventName\", \"KeyPress\");\n\n          graphics_object fig = object ().get_ancestor (\"figure\");\n\n          Q_EMIT gh_set_event (fig.get_handle (), \"currentcharacter\",\n                               keyEvent.getfield (\"Character\"), false);\n          Q_EMIT gh_callback_event (m_handle, \"keypressfcn\", keyEvent);\n        }\n      break;\n\n    case QEvent::FocusIn:\n      Q_EMIT gh_set_event (m_handle, \"__focus__\", \"on\", false);\n      break;\n\n    case QEvent::FocusOut:\n      Q_EMIT gh_set_event (m_handle, \"__focus__\", \"off\", false);\n      break;\n\n    default:\n      break;\n    }\n\n  return Object::eventFilter (watched, xevent);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/BaseControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_BaseControl_h)\n#define octave_BaseControl_h 1\n\n#include \"Object.h\"\n\nclass QEvent;\nclass QObject;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass BaseControl : public Object\n{\npublic:\n  BaseControl (octave::interpreter& interp,\n               const graphics_object& go, QWidget *w);\n  ~BaseControl ();\n\n  Container * innerContainer () { return nullptr; }\n\n  bool eventFilter (QObject *watched, QEvent *e);\n\nprotected:\n  void init (QWidget *w, bool callBase = false);\n  void redraw ();\n  void update (int pId);\n\nprivate:\n  bool m_normalizedFont;\n  bool m_keyPressHandlerDefined;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/ButtonControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QAbstractButton>\n\n#include \"ButtonControl.h\"\n#include \"ButtonGroup.h\"\n#include \"Container.h\"\n#include \"QtHandlesUtils.h\"\n\n#include \"graphics.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nButtonControl::ButtonControl (octave::interpreter& interp,\n                              const graphics_object& go,\n                              QAbstractButton *btn)\n  : BaseControl (interp, go, btn), m_blockCallback (false)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  QString str = Utils::fromStdString (up.get_string_string ());\n  str.replace (\"&\", \"&&\");\n  btn->setText (str);\n  if (btn->isCheckable () || up.style_is (\"togglebutton\"))\n    {\n      btn->setCheckable (true);\n\n      Matrix value = up.get_value ().matrix_value ();\n\n      if (value.numel () > 0 && value(0) == up.get_max ())\n        btn->setChecked (true);\n    }\n\n  connect (btn, &QAbstractButton::clicked, this, &ButtonControl::clicked);\n  connect (btn, &QAbstractButton::toggled, this, &ButtonControl::toggled);\n}\n\nButtonControl::~ButtonControl ()\n{ }\n\nvoid\nButtonControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QAbstractButton *btn = qWidget<QAbstractButton> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_STRING:\n      {\n        QString str = Utils::fromStdString (up.get_string_string ());\n        str.replace (\"&\", \"&&\");\n        btn->setText (str);\n        break;\n      }\n\n    case uicontrol::properties::ID_VALUE:\n      m_blockCallback = true;\n      if (btn->isCheckable ())\n        {\n          Matrix value = up.get_value ().matrix_value ();\n\n          if (value.numel () > 0)\n            {\n              double dValue = value(0);\n\n              if (dValue != 0.0 && dValue != 1.0)\n                warning (\"button value not within valid display range\");\n              else if (dValue == up.get_min () && btn->isChecked ())\n                {\n                  btn->setChecked (false);\n                  if (up.style_is (\"radiobutton\") || up.style_is (\"togglebutton\"))\n                    {\n                      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n                      Object *parent = Object::parentObject (m_interpreter, gh_mgr.get_object (up.get___myhandle__ ()));\n                      ButtonGroup *btnGroup = dynamic_cast<ButtonGroup *>(parent);\n                      if (btnGroup)\n                        btnGroup->selectNothing ();\n                    }\n                }\n              else if (dValue == up.get_max () && ! btn->isChecked ())\n                btn->setChecked (true);\n            }\n        }\n      m_blockCallback = false;\n      break;\n\n    default:\n      BaseControl::update (pId);\n      break;\n    }\n}\n\nvoid\nButtonControl::toggled (bool checked)\n{\n  QAbstractButton *btn = qWidget<QAbstractButton> ();\n\n  if (! m_blockCallback && btn->isCheckable ())\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      uicontrol::properties& up = properties<uicontrol> ();\n\n      Matrix oldValue = up.get_value ().matrix_value ();\n      double newValue = (checked ? up.get_max () : up.get_min ());\n\n      if (oldValue.numel () != 1 || (newValue != oldValue(0)))\n        Q_EMIT gh_set_event (m_handle, \"value\", newValue, false);\n      Q_EMIT gh_callback_event (m_handle, \"callback\");\n    }\n}\n\nvoid\nButtonControl::clicked ()\n{\n  QAbstractButton *btn = qWidget<QAbstractButton> ();\n\n  if (! btn->isCheckable ())\n    Q_EMIT gh_callback_event (m_handle, \"callback\");\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/ButtonControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ButtonControl_h)\n#define octave_ButtonControl_h 1\n\n#include \"BaseControl.h\"\n\nclass QAbstractButton;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass ButtonControl : public BaseControl\n{\n  Q_OBJECT\n\npublic:\n  ButtonControl (octave::interpreter& interp,\n                 const graphics_object& go, QAbstractButton *btn);\n  ~ButtonControl ();\n\nprotected:\n  void update (int pId);\n\nprivate Q_SLOTS:\n  void clicked ();\n  void toggled (bool checked);\n\nprivate:\n  bool m_blockCallback;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/ButtonGroup.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QAbstractButton>\n#include <QButtonGroup>\n#include <QEvent>\n#include <QFrame>\n#include <QLabel>\n#include <QMouseEvent>\n#include <QRadioButton>\n#include <QTimer>\n\n#include \"Canvas.h\"\n#include \"Container.h\"\n#include \"ContextMenu.h\"\n#include \"ButtonGroup.h\"\n#include \"ToggleButtonControl.h\"\n#include \"RadioButtonControl.h\"\n#include \"QtHandlesUtils.h\"\n#include \"octave-qt-features.h\"\n#include \"qt-graphics-toolkit.h\"\n\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic int\nframeStyleFromProperties (const uibuttongroup::properties& pp)\n{\n  if (pp.bordertype_is (\"none\"))\n    return QFrame::NoFrame;\n  else if (pp.bordertype_is (\"etchedin\"))\n    return (QFrame::Box | QFrame::Sunken);\n  else if (pp.bordertype_is (\"etchedout\"))\n    return (QFrame::Box | QFrame::Raised);\n  else if (pp.bordertype_is (\"beveledin\"))\n    return (QFrame::Panel | QFrame::Sunken);\n  else if (pp.bordertype_is (\"beveledout\"))\n    return (QFrame::Panel | QFrame::Raised);\n  else\n    return (QFrame::Panel | QFrame::Plain);\n}\n\nstatic void\nsetupPalette (const uibuttongroup::properties& pp, QPalette& p)\n{\n  p.setColor (QPalette::Window,\n              Utils::fromRgb (pp.get_backgroundcolor_rgb ()));\n  p.setColor (QPalette::WindowText,\n              Utils::fromRgb (pp.get_foregroundcolor_rgb ()));\n  p.setColor (QPalette::Light,\n              Utils::fromRgb (pp.get_highlightcolor_rgb ()));\n  p.setColor (QPalette::Dark,\n              Utils::fromRgb (pp.get_shadowcolor_rgb ()));\n}\n\nstatic int\nborderWidthFromProperties (const uibuttongroup::properties& pp)\n{\n  int bw = 0;\n\n  if (! pp.bordertype_is (\"none\"))\n    {\n      bw = octave::math::round (pp.get_borderwidth ());\n      if (pp.bordertype_is (\"etchedin\") || pp.bordertype_is (\"etchedout\"))\n        bw *= 2;\n    }\n\n  return bw;\n}\n\nButtonGroup *\nButtonGroup::create (octave::interpreter& interp, const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        {\n          QFrame *frame = new QFrame (container);\n          return new ButtonGroup (interp, go,\n                                  new QButtonGroup (frame), frame);\n        }\n    }\n\n  return nullptr;\n}\n\nButtonGroup::ButtonGroup (octave::interpreter& interp,\n                          const graphics_object& go,\n                          QButtonGroup *buttongroup, QFrame *frame)\n  : Object (interp, go, frame), m_hiddenbutton (nullptr),\n    m_container (nullptr), m_title (nullptr), m_blockUpdates (false)\n{\n  uibuttongroup::properties& pp = properties<uibuttongroup> ();\n\n  frame->setObjectName (\"UIButtonGroup\");\n  frame->setAutoFillBackground (true);\n  Matrix bb = pp.get_boundingbox (false);\n  frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)),\n                      octave::math::round (bb(2)), octave::math::round (bb(3)));\n  frame->setFrameStyle (frameStyleFromProperties (pp));\n  frame->setLineWidth (octave::math::round (pp.get_borderwidth ()));\n  QPalette pal = frame->palette ();\n  setupPalette (pp, pal);\n  frame->setPalette (pal);\n  m_buttongroup = buttongroup;\n  m_hiddenbutton = new QRadioButton (frame);\n  m_hiddenbutton->hide ();\n  m_buttongroup->addButton (m_hiddenbutton);\n\n  m_container = new Container (frame, interp);\n  m_container->canvas (m_handle);\n\n  connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)),\n           this, SIGNAL (interpeter_event (const fcn_callback&)));\n\n  connect (m_container, SIGNAL (interpeter_event (const meth_callback&)),\n           this, SIGNAL (interpeter_event (const meth_callback&)));\n\n  if (frame->hasMouseTracking ())\n    {\n      for (auto *w : frame->findChildren<QWidget *> ())\n        w->setMouseTracking (true);\n      for (auto *w : buttongroup->findChildren<QWidget *> ())\n        w->setMouseTracking (true);\n    }\n\n  QString title = Utils::fromStdString (pp.get_title ());\n  if (! title.isEmpty ())\n    {\n      m_title = new QLabel (title, frame);\n      m_title->setAutoFillBackground (true);\n      m_title->setContentsMargins (4, 0, 4, 0);\n      m_title->setPalette (pal);\n      m_title->setFont (Utils::computeFont<uibuttongroup> (pp, bb(3)));\n    }\n\n  frame->installEventFilter (this);\n  m_container->installEventFilter (this);\n\n  if (pp.is_visible ())\n    {\n      QTimer::singleShot (0, frame, &QFrame::show);\n      // FIXME: What is the intent here?  QButtonGroup::show is not a\n      // member of QButtonGroup.\n      QTimer::singleShot (0, buttongroup, SLOT (show ()));\n    }\n  else\n    frame->hide ();\n\n  connect (m_buttongroup,\n           qOverload<QAbstractButton *> (&QButtonGroup::buttonClicked),\n           this, &ButtonGroup::buttonClicked);\n}\n\nButtonGroup::~ButtonGroup ()\n{ }\n\nbool\nButtonGroup::eventFilter (QObject *watched, QEvent *xevent)\n{\n  if (! m_blockUpdates)\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      if (watched == qObject ())\n        {\n          switch (xevent->type ())\n            {\n            case QEvent::Resize:\n              {\n                octave::autolock guard (gh_mgr.graphics_lock ());\n\n                graphics_object go = object ();\n\n                if (go.valid_object ())\n                  {\n                    if (m_title)\n                      {\n                        const uibuttongroup::properties& pp =\n                          Utils::properties<uibuttongroup> (go);\n\n                        if (pp.fontunits_is (\"normalized\"))\n                          {\n                            QFrame *frame = qWidget<QFrame> ();\n\n                            m_title->setFont (Utils::computeFont<uibuttongroup>\n                                              (pp, frame->height ()));\n                            m_title->resize (m_title->sizeHint ());\n                          }\n                      }\n                    updateLayout ();\n                  }\n              }\n              break;\n\n            case QEvent::MouseButtonPress:\n              {\n                QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);\n\n                if (m->button () == Qt::RightButton)\n                  {\n                    octave::autolock guard (gh_mgr.graphics_lock ());\n\n                    ContextMenu::executeAt (m_interpreter, properties (),\n#if defined (HAVE_QSINGLEPOINTEVENT_CLASS)\n                                            m->globalPosition ().toPoint ());\n#else\n                                            m->globalPos ());\n#endif\n                  }\n              }\n              break;\n\n            default:\n              break;\n            }\n        }\n      else if (watched == m_container)\n        {\n          switch (xevent->type ())\n            {\n            case QEvent::Resize:\n              if (qWidget<QWidget> ()->isVisible ())\n                {\n                  octave::autolock guard (gh_mgr.graphics_lock ());\n\n                  properties ().update_boundingbox ();\n                }\n              break;\n\n            default:\n              break;\n            }\n        }\n    }\n\n  return false;\n}\n\nvoid\nButtonGroup::update (int pId)\n{\n  uibuttongroup::properties& pp = properties<uibuttongroup> ();\n  QFrame *frame = qWidget<QFrame> ();\n\n  m_blockUpdates = true;\n\n  switch (pId)\n    {\n    case uibuttongroup::properties::ID_POSITION:\n      {\n        Matrix bb = pp.get_boundingbox (false);\n\n        frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)),\n                            octave::math::round (bb(2)), octave::math::round (bb(3)));\n        updateLayout ();\n      }\n      break;\n\n    case uibuttongroup::properties::ID_BORDERWIDTH:\n      frame->setLineWidth (octave::math::round (pp.get_borderwidth ()));\n      updateLayout ();\n      break;\n\n    case uibuttongroup::properties::ID_BACKGROUNDCOLOR:\n    case uibuttongroup::properties::ID_FOREGROUNDCOLOR:\n    case uibuttongroup::properties::ID_HIGHLIGHTCOLOR:\n    case uibuttongroup::properties::ID_SHADOWCOLOR:\n      {\n        QPalette pal = frame->palette ();\n\n        setupPalette (pp, pal);\n        frame->setPalette (pal);\n        if (m_title)\n          m_title->setPalette (pal);\n      }\n      break;\n\n    case uibuttongroup::properties::ID_TITLE:\n      {\n        QString title = Utils::fromStdString (pp.get_title ());\n\n        if (title.isEmpty ())\n          {\n            if (m_title)\n              delete m_title;\n            m_title = nullptr;\n          }\n        else\n          {\n            if (! m_title)\n              {\n                QPalette pal = frame->palette ();\n\n                m_title = new QLabel (title, frame);\n                m_title->setAutoFillBackground (true);\n                m_title->setContentsMargins (4, 0, 4, 0);\n                m_title->setPalette (pal);\n                m_title->setFont (Utils::computeFont<uibuttongroup> (pp));\n                m_title->show ();\n              }\n            else\n              {\n                m_title->setText (title);\n                m_title->resize (m_title->sizeHint ());\n              }\n          }\n        updateLayout ();\n      }\n      break;\n\n    case uibuttongroup::properties::ID_TITLEPOSITION:\n      updateLayout ();\n      break;\n\n    case uibuttongroup::properties::ID_BORDERTYPE:\n      frame->setFrameStyle (frameStyleFromProperties (pp));\n      updateLayout ();\n      break;\n\n    case uibuttongroup::properties::ID_FONTNAME:\n    case uibuttongroup::properties::ID_FONTSIZE:\n    case uibuttongroup::properties::ID_FONTWEIGHT:\n    case uibuttongroup::properties::ID_FONTANGLE:\n      if (m_title)\n        {\n          m_title->setFont (Utils::computeFont<uibuttongroup> (pp));\n          m_title->resize (m_title->sizeHint ());\n          updateLayout ();\n        }\n      break;\n\n    case uibuttongroup::properties::ID_VISIBLE:\n      frame->setVisible (pp.is_visible ());\n      updateLayout ();\n      break;\n\n    case uibuttongroup::properties::ID_SELECTEDOBJECT:\n      {\n        graphics_handle h = pp.get_selectedobject ();\n\n        gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n        octave::autolock guard (gh_mgr.graphics_lock ());\n\n        graphics_object go = gh_mgr.get_object (h);\n\n        Object *selectedObject = qt_graphics_toolkit::toolkitObject (go);\n        ToggleButtonControl *toggle = static_cast<ToggleButtonControl *>\n                                      (selectedObject);\n        RadioButtonControl *radio = static_cast<RadioButtonControl *>(selectedObject);\n        if (toggle)\n          {\n            go.get_properties ().set (\"value\", 1);\n          }\n        else if (radio)\n          {\n            go.get_properties ().set (\"value\", 1);\n          }\n        else\n          {\n            m_hiddenbutton->setChecked (true);\n          }\n      }\n      break;\n\n    default:\n      break;\n    }\n\n  m_blockUpdates = false;\n}\n\nvoid\nButtonGroup::redraw ()\n{\n  update (uibuttongroup::properties::ID_POSITION);\n\n  // FIXME: is it really necessary to update the opengl canvas here?\n  Canvas *canvas = m_container->canvas (m_handle);\n\n  if (canvas)\n    canvas->redraw ();\n}\n\nvoid\nButtonGroup::updateLayout ()\n{\n  uibuttongroup::properties& pp = properties<uibuttongroup> ();\n  QFrame *frame = qWidget<QFrame> ();\n\n  Matrix bb = pp.get_boundingbox (true);\n  int bw = borderWidthFromProperties (pp);\n\n  frame->setFrameRect (QRect (octave::math::round (bb(0)) - bw,\n                              octave::math::round (bb(1)) - bw,\n                              octave::math::round (bb(2)) + 2*bw, octave::math::round (bb(3)) + 2*bw));\n  m_container->setGeometry (octave::math::round (bb(0)),\n                            octave::math::round (bb(1)),\n                            octave::math::round (bb(2)), octave::math::round (bb(3)));\n\n  if (m_blockUpdates)\n    pp.update_boundingbox ();\n\n  if (m_title)\n    {\n      QSize sz = m_title->sizeHint ();\n      int offset = 5;\n\n      if (pp.titleposition_is (\"lefttop\"))\n        m_title->move (bw+offset, 0);\n      else if (pp.titleposition_is (\"righttop\"))\n        m_title->move (frame->width () - bw - offset - sz.width (), 0);\n      else if (pp.titleposition_is (\"leftbottom\"))\n        m_title->move (bw+offset, frame->height () - sz.height ());\n      else if (pp.titleposition_is (\"rightbottom\"))\n        m_title->move (frame->width () - bw - offset - sz.width (),\n                       frame->height () - sz.height ());\n      else if (pp.titleposition_is (\"centertop\"))\n        m_title->move (frame->width () / 2 - sz.width () / 2, 0);\n      else if (pp.titleposition_is (\"centerbottom\"))\n        m_title->move (frame->width () / 2 - sz.width () / 2,\n                       frame->height () - sz.height ());\n    }\n}\n\nvoid\nButtonGroup::selectNothing ()\n{\n  m_hiddenbutton->setChecked (true);\n}\n\nvoid\nButtonGroup::addButton (QAbstractButton *btn)\n{\n  m_buttongroup->addButton (btn);\n  connect (btn, &QAbstractButton::toggled, this, &ButtonGroup::buttonToggled);\n}\n\nvoid\nButtonGroup::buttonToggled (bool toggled)\n{\n  Q_UNUSED (toggled);\n  if (! m_blockUpdates)\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      uibuttongroup::properties& bp = properties<uibuttongroup> ();\n\n      graphics_handle oldValue = bp.get_selectedobject ();\n\n      QAbstractButton *checkedBtn = m_buttongroup->checkedButton ();\n\n      graphics_handle newValue = graphics_handle ();\n      if (checkedBtn != m_hiddenbutton)\n        {\n          Object *checkedObj = Object::fromQObject (checkedBtn);\n          newValue = checkedObj->properties ().get___myhandle__ ();\n        }\n\n      if (oldValue != newValue)\n        Q_EMIT gh_set_event (m_handle, \"selectedobject\",\n                             newValue.as_octave_value (), false);\n    }\n}\n\nvoid\nButtonGroup::buttonClicked (QAbstractButton *btn)\n{\n  Q_UNUSED (btn);\n\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  uibuttongroup::properties& bp = properties<uibuttongroup> ();\n\n  graphics_handle oldValue = bp.get_selectedobject ();\n\n  QAbstractButton *checkedBtn = m_buttongroup->checkedButton ();\n  Object *checkedObj = Object::fromQObject (checkedBtn);\n  graphics_handle newValue = checkedObj->properties ().get___myhandle__ ();\n\n  if (oldValue != newValue)\n    {\n      octave_scalar_map eventData;\n      eventData.setfield (\"OldValue\", oldValue.as_octave_value ());\n      eventData.setfield (\"NewValue\", newValue.as_octave_value ());\n      eventData.setfield (\"Source\", bp.get___myhandle__ ().as_octave_value ());\n      eventData.setfield (\"EventName\", \"SelectionChanged\");\n      octave_value selectionChangedEventObject (eventData);\n      Q_EMIT gh_callback_event (m_handle, \"selectionchangedfcn\",\n                                selectionChangedEventObject);\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/ButtonGroup.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ButtonGroup_h)\n#define octave_ButtonGroup_h 1\n\n#include \"Object.h\"\n\nclass QAbstractButton;\nclass QButtonGroup;\nclass QFrame;\nclass QLabel;\nclass QRadioButton;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass Container;\n\nclass ButtonGroup : public Object\n{\n  Q_OBJECT\n\npublic:\n  ButtonGroup (octave::interpreter& interp,\n               const graphics_object& go, QButtonGroup *buttongroup,\n               QFrame *frame);\n  ~ButtonGroup ();\n\n  Container * innerContainer () { return m_container; }\n\n  bool eventFilter (QObject *watched, QEvent *event);\n\n  static ButtonGroup *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\n  void addButton (QAbstractButton *btn);\n\n  void selectNothing ();\n\nprotected:\n  void update (int pId);\n  void redraw ();\n\nprivate Q_SLOTS:\n  void buttonToggled (bool toggled);\n  void buttonClicked (QAbstractButton *btn);\n\nprivate:\n  void updateLayout ();\n\nprivate:\n  QButtonGroup *m_buttongroup;\n  QRadioButton *m_hiddenbutton;\n  Container *m_container;\n  QLabel *m_title;\n  bool m_blockUpdates;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/Canvas.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QApplication>\n#include <QBitmap>\n#include <QCursor>\n#include <QInputDialog>\n#include <QList>\n#include <QMouseEvent>\n#include <QWheelEvent>\n#include <QRectF>\n\n#include \"Canvas.h\"\n#include \"ContextMenu.h\"\n#include \"GLCanvas.h\"\n#include \"QtHandlesUtils.h\"\n#include \"qt-graphics-toolkit.h\"\n\n#include \"annotation-dialog.h\"\n#include \"gui-settings.h\"\n#include \"octave-qt-features.h\"\n#include \"qt-interpreter-events.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"graphics.h\"\n#include \"interpreter.h\"\n#include \"oct-opengl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\nCanvas::redraw (bool sync)\n{\n  QWidget *w = qWidget ();\n\n  if (w)\n    {\n      if (sync)\n        w->repaint ();\n      else\n        w->update ();\n    }\n}\n\nvoid\nCanvas::blockRedraw (bool block)\n{\n  m_redrawBlocked = block;\n}\n\nQCursor\nCanvas::make_cursor (const QString& name, int hot_x, int hot_y)\n{\n  gui_settings settings;\n\n  QIcon icon = settings.icon (name);\n\n  return QCursor (icon.pixmap (22, 22), hot_x, hot_y);\n}\n\nvoid\nCanvas::setCursor (MouseMode mode, std::string fallback,\n                   QImage cdata, Matrix hotspot)\n{\n  QWidget *w = qWidget ();\n  QCursor cursor = Qt::ArrowCursor;\n  if (w)\n    {\n      switch (mode)\n        {\n        case NoMode:\n          {\n            cursor = Qt::ArrowCursor;\n\n            if (fallback == \"arrow\")\n              cursor = Qt::ArrowCursor;\n            else if (fallback == \"botl\")\n              cursor = make_cursor (\"bottom_left_corner\", 5, 16);\n            else if (fallback == \"botr\")\n              cursor = make_cursor (\"bottom_right_corner\", 16, 16);\n            else if (fallback == \"bottom\")\n              cursor = make_cursor (\"bottom_side\", 11, 16);\n            else if (fallback == \"circle\")\n              cursor = make_cursor (\"circle\", 10, 10);\n            else if (fallback == \"cross\" || fallback == \"crosshair\")\n              cursor = make_cursor (\"cross\", 10, 10);\n            else if (fallback == \"custom\")\n              {\n                if (hotspot(0) > cdata.width () || hotspot(0) < 1.0\n                    || hotspot(1) > cdata.height () || hotspot(1) < 1.0)\n                  hotspot = Matrix (1, 2, 1);\n\n                cursor = QCursor (QPixmap::fromImage (cdata),\n                                  static_cast<int> (hotspot(1) - 1),\n                                  static_cast<int> (hotspot(0) - 1));\n              }\n            else if (fallback == \"fleur\")\n              cursor = make_cursor (\"fleur\", 10, 4);\n            else if (fallback == \"hand\")\n              cursor = make_cursor (\"hand2\", 7, 3);\n            else if (fallback == \"ibeam\")\n              cursor = Qt::IBeamCursor;\n            else if (fallback == \"left\")\n              cursor = make_cursor (\"left_side\", 4, 10);\n            else if (fallback == \"right\")\n              cursor = make_cursor (\"right_side\", 17, 10);\n            else if (fallback == \"top\")\n              cursor = make_cursor (\"top_side\", 11, 4);\n            else if (fallback == \"topl\")\n              cursor = make_cursor (\"top_left_corner\", 4, 4);\n            else if (fallback == \"topr\")\n              cursor = make_cursor (\"top_right_corner\", 16, 4);\n            else if (fallback == \"watch\")\n              cursor = Qt::BusyCursor;\n          }\n          break;\n        case SelectMode:\n          cursor = Qt::ArrowCursor;\n          break;\n\n        case PanMode:\n          cursor = make_cursor (\"figure-pan\");\n          break;\n\n        case RotateMode:\n          cursor = make_cursor (\"figure-rotate\");\n          break;\n\n        case TextMode:\n          cursor = Qt::IBeamCursor;\n          break;\n\n        case ZoomInMode:\n          cursor = make_cursor (\"figure-zoom-in\", 9, 9);\n          break;\n\n        case ZoomOutMode:\n          cursor = make_cursor (\"figure-zoom-out\", 9, 9);\n          break;\n\n        default:\n          cursor = Qt::ArrowCursor;\n          break;\n        }\n      w->setCursor (cursor);\n    }\n}\n\n/*\n   Two updateCurrentPoint() routines are required:\n   1) Used for QMouseEvents where cursor position data is in callback from Qt.\n   2) Used for QKeyEvents where cursor position must be determined.\n*/\nvoid\nCanvas::updateCurrentPoint (const graphics_object& fig,\n                            const graphics_object& obj, QMouseEvent *event)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  Q_EMIT gh_set_event (fig.get_handle (), \"currentpoint\",\n                       Utils::figureCurrentPoint (fig, event), false);\n\n  Matrix children = obj.get_properties ().get_children ();\n  octave_idx_type num_children = children.numel ();\n\n  for (int i = 0; i < num_children; i++)\n    {\n      graphics_object childObj (gh_mgr.get_object (children(i)));\n\n      if (childObj.isa (\"axes\"))\n        {\n          axes::properties& ap = Utils::properties<axes> (childObj);\n          Matrix x_zlim = ap.get_transform_zlim ();\n          graphics_xform x_form = ap.get_transform ();\n\n          QPoint mouse_position = event->pos ();\n          ColumnVector p1\n            = x_form.untransform (mouse_position.x (), mouse_position.y (),\n                                  x_zlim(0));\n          ColumnVector p2\n            = x_form.untransform (mouse_position.x (), mouse_position.y (),\n                                  x_zlim(1));\n\n          Matrix cp (2, 3, 0.0);\n\n          cp(0, 0) = p1(0); cp(0, 1) = p1(1); cp(0, 2) = p1(2);\n          cp(1, 0) = p2(0); cp(1, 1) = p2(1); cp(1, 2) = p2(2);\n\n          Q_EMIT gh_set_event (childObj.get_handle (), \"currentpoint\", cp,\n                               false);\n        }\n    }\n}\n\nvoid\nCanvas::updateCurrentPoint (const graphics_object& fig,\n                            const graphics_object& obj)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  Q_EMIT gh_set_event (fig.get_handle (), \"currentpoint\",\n                       Utils::figureCurrentPoint (fig), false);\n\n  Matrix children = obj.get_properties ().get_children ();\n  octave_idx_type num_children = children.numel ();\n\n  for (int i = 0; i < num_children; i++)\n    {\n      graphics_object childObj (gh_mgr.get_object (children(i)));\n\n      if (childObj.isa (\"axes\"))\n        {\n          // FIXME: QCursor::pos() may give inaccurate results with\n          //        asynchronous window systems like X11 over ssh.\n          QWidget *w = qWidget ();\n          QPoint p = w->mapFromGlobal (QCursor::pos ());\n          axes::properties& ap = Utils::properties<axes> (childObj);\n          Matrix x_zlim = ap.get_transform_zlim ();\n          graphics_xform x_form = ap.get_transform ();\n\n          ColumnVector p1 = x_form.untransform (p.x (), p.y (), x_zlim(0));\n          ColumnVector p2 = x_form.untransform (p.x (), p.y (), x_zlim(1));\n\n          Matrix cp (2, 3, 0.0);\n\n          cp(0, 0) = p1(0); cp(0, 1) = p1(1); cp(0, 2) = p1(2);\n          cp(1, 0) = p2(0); cp(1, 1) = p2(1); cp(1, 2) = p2(2);\n\n          Q_EMIT gh_set_event (childObj.get_handle (), \"currentpoint\", cp,\n                               false);\n        }\n    }\n}\n\nstatic void\nautoscale_axes (gh_manager& gh_mgr, axes::properties& ap)\n{\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  // Reset zoom stack\n  ap.clear_zoom_stack (false);\n\n  ap.set_xlimmode (\"auto\");\n  ap.set_ylimmode (\"auto\");\n  ap.set_zlimmode (\"auto\");\n}\n\nvoid\nCanvas::canvasPaintEvent ()\n{\n  if (! m_redrawBlocked)\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      draw (m_handle);\n\n      if ((m_mouseMode == ZoomInMode && m_mouseAxes.ok ()) || m_rectMode)\n        drawZoomBox (m_mouseAnchor, m_mouseCurrent);\n    }\n}\n\nstatic bool\npan_enabled (const graphics_object figObj)\n{\n  // Getting pan mode property:\n  octave_value ov_pm\n    = Utils::properties<figure> (figObj).get___pan_mode__ ();\n\n  octave_scalar_map pm = ov_pm.scalar_map_value ();\n\n  return pm.contents (\"Enable\").string_value () == \"on\";\n}\n\nstatic std::string\npan_mode (const graphics_object figObj)\n{\n  // Getting pan mode property:\n  octave_value ov_pm\n    = Utils::properties<figure> (figObj).get___pan_mode__ ();\n\n  octave_scalar_map pm = ov_pm.scalar_map_value ();\n\n  return pm.contents (\"Motion\").string_value ();\n}\n\nstatic bool\nzoom_enabled (const graphics_object figObj)\n{\n  // Getting zoom mode property:\n  octave_value ov_zm\n    = Utils::properties<figure> (figObj).get___zoom_mode__ ();\n\n  octave_scalar_map zm = ov_zm.scalar_map_value ();\n\n  return zm.contents (\"Enable\").string_value () == \"on\";\n}\n\nstatic std::string\nzoom_mode (const graphics_object figObj)\n{\n  // Getting zoom mode property:\n  octave_value ov_zm\n    = Utils::properties<figure> (figObj).get___zoom_mode__ ();\n\n  octave_scalar_map zm = ov_zm.scalar_map_value ();\n\n  return zm.contents (\"Motion\").string_value ();\n}\n\nvoid\nCanvas::select_object (graphics_object obj, QMouseEvent *event,\n                       graphics_object& currentObj, graphics_object& axesObj,\n                       bool axes_only, std::vector<std::string> omit)\n{\n  QList<graphics_object> axesList;\n  Matrix children = obj.get_properties ().get_all_children ();\n  octave_idx_type num_children = children.numel ();\n\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  for (int i = 0; i < num_children; i++)\n    {\n      graphics_object childObj (gh_mgr.get_object (children(i)));\n\n      if (childObj.isa (\"axes\"))\n        {\n          auto p = omit.begin ();\n          bool omitfound = false;\n          while (p != omit.end () && ! omitfound)\n            {\n              omitfound = (childObj.get (\"tag\").string_value () == *p);\n              p++;\n            }\n          if (! omitfound)\n            axesList.append (childObj);\n        }\n      else if (childObj.isa (\"uicontrol\") || childObj.isa (\"uipanel\")\n               || childObj.isa (\"uibuttongroup\") || childObj.isa (\"uitable\"))\n        {\n          Matrix bb = childObj.get_properties ().get_boundingbox (false);\n          QRectF r (bb(0), bb(1), bb(2), bb(3));\n\n          r.adjust (-5, -5, 5, 5);\n\n#if defined (HAVE_QSINGLEPOINTEVENT_CLASS)\n          QPointF mouse_pos = event->position ();\n#else\n          QPointF mouse_pos = event->localPos ();\n#endif\n          bool rect_contains_pos = r.contains (mouse_pos);\n          if (rect_contains_pos)\n            {\n              currentObj = childObj;\n              break;\n            }\n        }\n    }\n\n  if (axes_only)\n    {\n      QPoint pt = event->pos ();\n\n      for (QList<graphics_object>::ConstIterator it = axesList.begin ();\n           it != axesList.end (); ++it)\n        {\n          const axes::properties& ap =\n            dynamic_cast<const axes::properties&> ((*it).get_properties ());\n\n          ColumnVector p0 = ap.pixel2coord (pt.x (), pt.y ());\n          Matrix xlim = ap.get_xlim ().matrix_value ();\n          Matrix ylim = ap.get_ylim ().matrix_value ();\n\n          if (xlim(0) < p0(0) && xlim(1) > p0(0)\n              && ylim(0) < p0(1) && ylim(1) > p0(1))\n            {\n              axesObj = *it;\n              return;\n            }\n        }\n    }\n  else if (! currentObj)\n    {\n      for (QList<graphics_object>::ConstIterator it = axesList.begin ();\n           it != axesList.end (); ++it)\n        {\n          graphics_object go = selectFromAxes (*it, event->pos ());\n\n          if (go)\n            {\n              currentObj = go;\n              axesObj = *it;\n            }\n          // FIXME: is this really necessary? the axes object should\n          //        have been selected through selectFromAxes anyway\n          else if (it->get_properties ().is_hittest ())\n            {\n              Matrix bb = it->get_properties ().get_boundingbox (true);\n              QRectF r (bb(0), bb(1), bb(2), bb(3));\n\n              // Allow a rectangle (e.g., Zoom box) to be slightly outside\n              // the axes and still select it.\n              r.adjust (-20, -20, 20, 20);\n\n#if defined (HAVE_QSINGLEPOINTEVENT_CLASS)\n              QPointF mouse_pos = event->position ();\n#else\n              QPointF mouse_pos = event->localPos ();\n#endif\n              bool rect_contains_pos = r.contains (mouse_pos);\n              if (rect_contains_pos)\n                axesObj = *it;\n            }\n\n          if (axesObj && currentObj)\n            break;\n        }\n    }\n}\n\nvoid\nCanvas::canvasMouseMoveEvent (QMouseEvent *event)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  graphics_object ax = gh_mgr.get_object (m_mouseAxes);\n\n  if (m_mouseMode != NoMode && (ax.valid_object () || m_mouseMode == TextMode))\n    {\n      switch (m_mouseMode)\n        {\n        case RotateMode:\n          {\n            axes::properties& ap = Utils::properties<axes> (ax);\n\n            QPoint mouse_position = event->pos ();\n            ap.rotate3d (m_mouseCurrent.x (), mouse_position.x (),\n                         m_mouseCurrent.y (), mouse_position.y ());\n\n            // Update current mouse position\n            m_mouseCurrent = event->pos ();\n\n            // Force immediate redraw\n            redraw (true);\n          }\n          break;\n        case TextMode:\n        case ZoomInMode:\n        case ZoomOutMode:\n          m_mouseCurrent = event->pos ();\n          redraw (true);\n          break;\n\n        case PanMode:\n          {\n            axes::properties& ap = Utils::properties<axes> (ax);\n\n            graphics_object figObj (ax.get_ancestor (\"figure\"));\n\n            std::string mode = pan_mode (figObj);\n\n            ColumnVector p0 = ap.pixel2coord (m_mouseCurrent.x (),\n                                              m_mouseCurrent.y ());\n            QPoint mouse_position = event->pos ();\n            ColumnVector p1 = ap.pixel2coord (mouse_position.x (),\n                                              mouse_position.y ());\n\n            ap.translate_view (mode, p0(0), p1(0), p0(1), p1(1));\n\n            // Update current mouse position\n            m_mouseCurrent = event->pos ();\n\n            // Force immediate redraw\n            redraw (true);\n          }\n\n        default:\n          break;\n        }\n    }\n  else if (m_mouseMode == NoMode)\n    {\n      graphics_object obj = gh_mgr.get_object (m_handle);\n\n      if (obj.valid_object ())\n        {\n          graphics_object figObj (obj.get_ancestor (\"figure\"));\n\n          if (figObj.valid_object ()\n              && ! figObj.get (\"windowbuttonmotionfcn\").isempty ())\n            {\n              updateCurrentPoint (figObj, obj, event);\n              Q_EMIT gh_callback_event (figObj.get_handle (),\n                                        \"windowbuttonmotionfcn\");\n            }\n        }\n    }\n\n  // Update mouse coordinates in the figure window status bar\n  graphics_object obj = gh_mgr.get_object (m_handle);\n  graphics_object figObj = obj.get_ancestor (\"figure\");\n\n  if (figObj.valid_object () && obj.valid_object ())\n    {\n      graphics_object currentObj, axesObj;\n      std::vector<std::string> omit = {\"legend\", \"colorbar\", \"scribeoverlay\"};\n      select_object (obj, event, currentObj, axesObj, true, omit);\n\n      if (axesObj.valid_object ())\n        {\n          // FIXME: should we use signal/slot mechanism instead of\n          //        directly calling parent fig methods\n          Figure *fig =\n            dynamic_cast<Figure *> (qt_graphics_toolkit::toolkitObject (figObj));\n          axes::properties& ap = Utils::properties<axes> (axesObj);\n\n          if (fig)\n            {\n              QPoint mouse_position = event->pos ();\n              fig->updateStatusBar (ap.pixel2coord (mouse_position.x (),\n                                                    mouse_position.y ()));\n            }\n        }\n    }\n}\n\nvoid\nCanvas::canvasMouseDoubleClickEvent (QMouseEvent *event)\n{\n  // same processing as normal click, but event type is MouseButtonDblClick\n  canvasMousePressEvent (event);\n}\n\nstatic double\nbutton_number (QMouseEvent *event)\n{\n  double retval = 0;\n\n  switch (event->button ())\n    {\n    case Qt::LeftButton:\n      retval = 1;\n      break;\n\n    case Qt::MiddleButton:\n      retval = 2;\n      break;\n\n    case Qt::RightButton:\n      retval = 3;\n      break;\n\n    default:\n      break;\n    }\n\n  return retval;\n}\n\nvoid\nCanvas::canvasMousePressEvent (QMouseEvent *event)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  graphics_object obj = gh_mgr.get_object (m_handle);\n\n  bool isdblclick = (event->type () == QEvent::MouseButtonDblClick);\n\n  if (obj.valid_object ())\n    {\n      graphics_object figObj (obj.get_ancestor (\"figure\"));\n\n      // Any click in a figure canvas makes it current\n      if (figObj)\n        {\n          graphics_object root = gh_mgr.get_object (0);\n          Utils::properties<root_figure> (root)\n          .set_currentfigure (figObj.get_handle ().as_octave_value ());\n        }\n\n      graphics_object currentObj, axesObj;\n\n      // Retrieve selected object.\n      select_object (obj, event, currentObj, axesObj);\n\n      // currentObj may be invalid if, e.g., all objects under the mouse\n      // click had \"hittest\" -> \"off\" or \"pickableparts\" -> \"none\".  In that\n      // case, replace with underlying figObj which always accepts mouse\n      // clicks.\n      if (! currentObj.valid_object ())\n        currentObj = figObj;\n      else if (! currentObj.get_properties ().is_hittest ())\n        {\n          // Objects with \"hittest\"->\"off\" pass the mouse event to their\n          // parent and so on.\n          graphics_object tmpgo;\n          tmpgo = gh_mgr.get_object (currentObj.get_parent ());\n          while (tmpgo && ! tmpgo.get_properties ().is_hittest ())\n            tmpgo = gh_mgr.get_object (tmpgo.get_parent ());\n\n          if (tmpgo && tmpgo.get_handle () != 0.0)\n            currentObj = tmpgo;\n          else\n            currentObj = graphics_object ();\n        }\n\n      // Make selected axes current\n      bool valid_axes = axesObj.valid_object ()\n                        && axesObj.get_properties ().handlevisibility_is (\"on\")\n                        && axesObj.get_properties ().get_tag () != \"legend\"\n                        && axesObj.get_properties ().get_tag () != \"colorbar\";\n\n      if (valid_axes)\n        Utils::properties<figure> (figObj)\n        .set_currentaxes (axesObj.get_handle ().as_octave_value ());\n\n      Figure *fig = dynamic_cast<Figure *> (qt_graphics_toolkit::toolkitObject (figObj));\n\n      MouseMode newMouseMode = NoMode;\n\n      if (fig)\n        newMouseMode = fig->mouseMode ();\n\n      switch (newMouseMode)\n        {\n        case NoMode:\n          {\n            // Update the figure \"currentobject\"\n            auto& fprop = Utils::properties<figure> (figObj);\n\n            if (currentObj\n                && currentObj.get_properties ().handlevisibility_is (\"on\"))\n              fprop.set_currentobject (currentObj.get_handle ()\n                                       .as_octave_value ());\n            else\n              fprop.set_currentobject (Matrix ());\n\n            // Update figure \"selectiontype\" and \"currentpoint\"\n            Q_EMIT gh_set_event (figObj.get_handle (), \"selectiontype\",\n                                 Utils::figureSelectionType (event, isdblclick),\n                                 false);\n\n            updateCurrentPoint (figObj, obj, event);\n\n            Q_EMIT gh_callback_event (figObj.get_handle (),\n                                      \"windowbuttondownfcn\",\n                                      button_number (event));\n\n            // Execute the \"buttondownfcn\" of the selected object.  If the\n            // latter is empty then execute the figure \"buttondownfcn\"\n            if (currentObj && ! currentObj.get (\"buttondownfcn\").isempty ())\n              Q_EMIT gh_callback_event (currentObj.get_handle (),\n                                        \"buttondownfcn\", button_number (event));\n            else if (figObj && ! figObj.get (\"buttondownfcn\").isempty ())\n              Q_EMIT gh_callback_event (figObj.get_handle (),\n                                        \"buttondownfcn\", button_number (event));\n\n            // Show context menu of the selected object\n            if (currentObj && event->button () == Qt::RightButton)\n              ContextMenu::executeAt (m_interpreter,\n                                      currentObj.get_properties (),\n#if defined (HAVE_QSINGLEPOINTEVENT_CLASS)\n                                      event->globalPosition ().toPoint ());\n#else\n                                      event->globalPos ());\n#endif\n          }\n          break;\n\n        case TextMode:\n          {\n            if (event->modifiers () == Qt::NoModifier)\n              {\n                switch (event->buttons ())\n                  {\n                  case Qt::LeftButton:\n                    m_mouseAnchor = m_mouseCurrent = event->pos ();\n                    m_mouseMode = newMouseMode;\n                    m_rectMode = true;\n                  }\n              }\n            redraw (false);\n          }\n          break;\n\n        case PanMode:\n        case RotateMode:\n        case ZoomInMode:\n        case ZoomOutMode:\n          if (valid_axes)\n            {\n              bool redraw_figure = true;\n\n              if (isdblclick)\n                {\n                  if (event->button () == Qt::LeftButton)\n                    {\n                      axes::properties& ap = Utils::properties<axes> (axesObj);\n\n                      autoscale_axes (gh_mgr, ap);\n                    }\n                  else\n                    {\n                      redraw_figure = false;\n                    }\n                }\n              else if (event->modifiers () == Qt::NoModifier)\n                {\n                  switch (event->buttons ())\n                    {\n                    case Qt::LeftButton:\n                      m_mouseAnchor = m_mouseCurrent = event->pos ();\n                      m_mouseAxes = axesObj.get_handle ();\n                      m_mouseMode = newMouseMode;\n                      m_clickMode = newMouseMode == ZoomInMode;\n                      break;\n\n                    case Qt::RightButton:\n                      if (newMouseMode == ZoomInMode)\n                        {\n                          m_mouseAnchor = m_mouseCurrent = event->pos ();\n                          m_mouseAxes = axesObj.get_handle ();\n                          m_mouseMode = newMouseMode;\n                          m_clickMode = false;\n                        }\n\n                      break;\n\n                    case Qt::MiddleButton:\n                      {\n                        axes::properties& ap =\n                          Utils::properties<axes> (axesObj);\n\n                        autoscale_axes (gh_mgr, ap);\n                      }\n                      break;\n\n                    default:\n                      redraw_figure = false;\n                      break;\n                    }\n                }\n              else if (event->modifiers () == Qt::ShiftModifier)\n                {\n                  switch (event->buttons ())\n                    {\n                    case Qt::LeftButton:\n                      if (newMouseMode == ZoomInMode)\n                        {\n                          m_mouseAnchor = m_mouseCurrent = event->pos ();\n                          m_mouseAxes = axesObj.get_handle ();\n                          m_mouseMode = newMouseMode;\n                          m_clickMode = false;\n                        }\n                      break;\n\n                    default:\n                      redraw_figure = false;\n                      break;\n                    }\n                }\n\n              if (redraw_figure)\n                redraw (false);\n            }\n          break;\n\n        default:\n          break;\n        }\n    }\n\n}\n\nvoid\nCanvas::canvasMouseReleaseEvent (QMouseEvent *event)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  if ((m_mouseMode == ZoomInMode || m_mouseMode == ZoomOutMode)\n      && m_mouseAxes.ok ())\n    {\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      graphics_object ax = gh_mgr.get_object (m_mouseAxes);\n\n      if (ax.valid_object ())\n        {\n          axes::properties& ap = Utils::properties<axes> (ax);\n\n          graphics_object obj = gh_mgr.get_object (m_handle);\n\n          graphics_object figObj (obj.get_ancestor (\"figure\"));\n\n          std::string zm = zoom_mode (figObj);\n\n          QPoint mouse_position = event->pos ();\n          if (m_mouseAnchor == mouse_position)\n            {\n              double factor = (m_clickMode ? 2.0 : 0.5);\n\n              ColumnVector p1 = ap.pixel2coord (mouse_position.x (),\n                                                mouse_position.y ());\n\n              ap.zoom_about_point (zm, p1(0), p1(1), factor);\n            }\n          else if (m_mouseMode == ZoomInMode)\n            {\n              ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (),\n                                                m_mouseAnchor.y ());\n              ColumnVector p1 = ap.pixel2coord (mouse_position.x (),\n                                                mouse_position.y ());\n\n              Matrix xl (1, 2, 0.0);\n              Matrix yl (1, 2, 0.0);\n\n              xl(0) = std::min (p0(0), p1(0));\n              xl(1) = std::max (p0(0), p1(0));\n              yl(0) = std::min (p0(1), p1(1));\n              yl(1) = std::max (p0(1), p1(1));\n\n              ap.zoom (zm, xl, yl);\n            }\n\n          redraw (false);\n        }\n    }\n  else if (m_mouseMode == NoMode)\n    {\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      graphics_object obj = gh_mgr.get_object (m_handle);\n\n      if (obj.valid_object ())\n        {\n          graphics_object figObj (obj.get_ancestor (\"figure\"));\n\n          updateCurrentPoint (figObj, obj, event);\n          Q_EMIT gh_callback_event (figObj.get_handle (), \"windowbuttonupfcn\");\n        }\n    }\n  else if (m_mouseMode == TextMode)\n    {\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      graphics_object figObj\n        = gh_mgr.get_object (m_handle).get_ancestor (\"figure\");\n\n      if (figObj.valid_object ())\n        {\n          QWidget *w = qWidget ();\n          if (w)\n            {\n              QPoint mouse_position = event->pos ();\n              Matrix bb = figObj.get (\"position\").matrix_value ();\n              bb(0) = m_mouseAnchor.x () / bb(2);\n              bb(1) = 1.0 - (m_mouseAnchor.y () / bb(3));\n              bb(2) = (mouse_position.x () - m_mouseAnchor.x ()) / bb(2);\n              bb(3) = (m_mouseAnchor.y () - mouse_position.y ()) / bb(3);\n\n              octave_value_list props = ovl (\"textbox\", bb);\n\n              annotation_dialog anno_dlg (w, props);\n\n              if (anno_dlg.exec () == QDialog::Accepted)\n                {\n                  props = anno_dlg.get_properties ();\n                  props.prepend (figObj.get_handle ().as_octave_value ());\n\n                  Q_EMIT interpreter_event\n                  ([this, props] (octave::interpreter& interp)\n                  {\n                    // INTERPRETER THREAD\n\n                    interp.feval (\"annotation\", props);\n\n                    redraw ();\n                  });\n                }\n            }\n        }\n    }\n  m_rectMode = false;\n  m_mouseAxes = graphics_handle ();\n  m_mouseMode = NoMode;\n}\n\nvoid\nCanvas::canvasWheelEvent (QWheelEvent *event)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  graphics_object obj = gh_mgr.get_object (m_handle);\n\n  if (obj.valid_object ())\n    {\n      std::string mode;\n\n      graphics_object figObj (obj.get_ancestor (\"figure\"));\n\n      graphics_object axesObj;\n\n      Matrix children = obj.get_properties ().get_children ();\n      octave_idx_type num_children = children.numel ();\n\n      for (int i = 0; i < num_children; i++)\n        {\n          graphics_object childObj (gh_mgr.get_object (children(i)));\n\n          if (childObj.isa (\"axes\"))\n            {\n#if defined (HAVE_QWHEELEVENT_POSITION)\n              QPoint pos = event->position ().toPoint ();\n#else\n              QPoint pos = event->pos ();\n#endif\n              graphics_object go = selectFromAxes (childObj, pos);\n\n              if (go)\n                {\n                  axesObj = childObj;\n                  break;\n                }\n            }\n        }\n\n      if (axesObj)\n        {\n          MouseMode newMouseMode = NoMode;\n\n          Figure *fig = dynamic_cast<Figure *> (qt_graphics_toolkit::toolkitObject (figObj));\n\n          if (fig)\n            newMouseMode = fig->mouseMode ();\n\n          if (axesObj.get_properties ().handlevisibility_is (\"on\"))\n            {\n              Utils::properties<figure> (figObj)\n              .set_currentaxes (axesObj.get_handle ().as_octave_value ());\n\n              if (zoom_enabled (figObj))\n                {\n                  if (event->angleDelta ().y () > 0)\n                    newMouseMode = ZoomInMode;\n                  else\n                    newMouseMode = ZoomOutMode;\n\n                  mode = zoom_mode (figObj);\n                }\n              else if (pan_enabled (figObj))\n                {\n                  newMouseMode = PanMode;\n\n                  mode = pan_mode (figObj);\n                }\n            }\n\n          bool redrawFigure = true;\n\n          switch (newMouseMode)\n            {\n            case ZoomInMode:\n            case ZoomOutMode:\n              {\n                axes::properties& ap = Utils::properties<axes> (axesObj);\n\n                // Control how fast to zoom when using scroll wheel.\n                double wheel_zoom_speed = ap.get_mousewheelzoom ();\n\n                // Determine if we're zooming in or out.\n                double factor = (newMouseMode == ZoomInMode\n                                 ? 1 / (1.0 - wheel_zoom_speed)\n                                 : 1.0 - wheel_zoom_speed);\n\n                // FIXME: should we zoom about point for 2-D plots?\n\n                ap.zoom (mode, factor);\n              }\n              break;\n\n            case PanMode:\n              {\n                axes::properties& ap = Utils::properties<axes> (axesObj);\n\n                double factor = (event->angleDelta ().y () > 0 ? 0.1 : -0.1);\n\n                if (event->modifiers () == Qt::NoModifier\n                    && mode != \"horizontal\")\n                  ap.pan (\"vertical\", factor);\n                else if (event->modifiers () == Qt::ShiftModifier\n                         && mode != \"vertical\")\n                  ap.pan (\"horizontal\", factor);\n              }\n              break;\n\n            default:\n              redrawFigure = false;\n              break;\n            }\n\n          if (redrawFigure)\n            redraw (false);\n        }\n\n      if (! figObj.get (\"windowscrollwheelfcn\").isempty ())\n        {\n          octave_scalar_map eventData = Utils::makeScrollEventStruct (event);\n          Q_EMIT gh_callback_event (m_handle, \"windowscrollwheelfcn\",\n                                    eventData);\n        }\n    }\n}\n\nbool\nCanvas::canvasKeyPressEvent (QKeyEvent *event)\n{\n  if (m_eventMask & KeyPress)\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      graphics_object obj = gh_mgr.get_object (m_handle);\n\n      if (obj.valid_object ())\n        {\n          graphics_object figObj (obj.get_ancestor (\"figure\"));\n\n          updateCurrentPoint (figObj, obj);\n\n          octave_scalar_map eventData = Utils::makeKeyEventStruct (event);\n          eventData.setfield (\"Source\",\n                              figObj.get_handle ().as_octave_value ());\n          eventData.setfield (\"EventName\", \"KeyPress\");\n\n          Q_EMIT gh_set_event (figObj.get_handle (), \"currentcharacter\",\n                               eventData.getfield (\"Character\"), false);\n          Q_EMIT gh_callback_event (figObj.get_handle (), \"keypressfcn\",\n                                    eventData);\n        }\n\n      return true;\n    }\n\n  return false;\n}\n\nbool\nCanvas::canvasKeyReleaseEvent (QKeyEvent *event)\n{\n  if (! event->isAutoRepeat () && (m_eventMask & KeyRelease))\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      graphics_object obj = gh_mgr.get_object (m_handle);\n\n      if (obj.valid_object ())\n        {\n          graphics_object figObj (obj.get_ancestor (\"figure\"));\n          octave_scalar_map eventData = Utils::makeKeyEventStruct (event);\n          eventData.setfield (\"Source\",\n                              figObj.get_handle ().as_octave_value ());\n          eventData.setfield (\"EventName\", \"KeyRelease\");\n\n          Q_EMIT gh_callback_event (figObj.get_handle (), \"keyreleasefcn\",\n                                    eventData);\n        }\n\n      return true;\n    }\n\n  return false;\n}\n\nCanvas *\nCanvas::create (octave::interpreter& interp,\n                const graphics_handle& handle, QWidget *parent,\n                const std::string& /* name */)\n{\n  // Only OpenGL\n  return new GLCanvas (interp, handle, parent);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/Canvas.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Canvas_h)\n#define octave_Canvas_h 1\n\n#include <QObject>\n#include <QPoint>\n\n#include \"event-manager.h\"\n#include \"graphics.h\"\n\n#include \"Figure.h\"\n\nclass QKeyEvent;\nclass QMouseEvent;\nclass QWheelEvent;\nclass QWidget;\n\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass Canvas : public QObject\n{\n  Q_OBJECT\n\npublic:\n  enum EventMask\n  {\n    KeyPress   = 0x01,\n    KeyRelease = 0x02\n  };\n\npublic:\n  virtual ~Canvas () = default;\n\n  void redraw (bool sync = false);\n  void blockRedraw (bool block = true);\n\n  void print (const QString& file_cmd, const QString& term)\n  {\n    do_print (file_cmd, term, m_handle);\n  }\n\n  void addEventMask (int m) { m_eventMask |= m; }\n  void clearEventMask (int m) { m_eventMask &= (~m); }\n  void setEventMask (int m) { m_eventMask = m; }\n\n  void setCursor (MouseMode mode, std::string fallback,\n                  QImage cdata, Matrix hotspot);\n\n  virtual QWidget * qWidget () = 0;\n\n  static Canvas *\n  create (octave::interpreter& interp, const graphics_handle& handle,\n          QWidget *parent, const std::string& name);\n\n  virtual uint8NDArray getPixels () { return do_getPixels (m_handle); };\n\nQ_SIGNALS:\n\n  void interpreter_event (const octave::fcn_callback& fcn);\n  void interpreter_event (const octave::meth_callback& meth);\n\n  void gh_callback_event (const graphics_handle& h, const std::string& name);\n\n  void gh_callback_event (const graphics_handle& h, const std::string& name,\n                          const octave_value& data);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value, bool notify_toolkit);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value, bool notify_toolkit,\n                     bool redraw_figure);\nprotected:\n  virtual void draw (const graphics_handle& handle) = 0;\n  virtual void drawZoomBox (const QPoint& p1, const QPoint& p2) = 0;\n  virtual void resize (int x, int y, int width, int height) = 0;\n  virtual graphics_object selectFromAxes (const graphics_object& ax,\n                                          const QPoint& pt) = 0;\n  virtual uint8NDArray do_getPixels (const graphics_handle& handle) = 0;\n  virtual void do_print (const QString& file_cmd, const QString& term,\n                         const graphics_handle& handle) = 0;\n\nprotected:\n\n  Canvas (octave::interpreter& interp, const graphics_handle& handle)\n    : QObject (), m_interpreter (interp), m_handle (handle),\n      m_redrawBlocked (false), m_mouseMode (NoMode), m_clickMode (false),\n      m_eventMask (0), m_rectMode (false)\n  { }\n\npublic:\n  void canvasToggleAxes (const graphics_handle& handle);\n  void canvasToggleGrid (const graphics_handle& handle);\n  void canvasAutoAxes (const graphics_handle& handle);\n  void canvasPaintEvent ();\n  void canvasMouseDoubleClickEvent (QMouseEvent *event);\n  void canvasMouseMoveEvent (QMouseEvent *event);\n  void canvasMousePressEvent (QMouseEvent *event);\n  void canvasMouseReleaseEvent (QMouseEvent *event);\n  void canvasWheelEvent (QWheelEvent *event);\n  bool canvasKeyPressEvent (QKeyEvent *event);\n  bool canvasKeyReleaseEvent (QKeyEvent *event);\n\n  void updateCurrentPoint (const graphics_object& fig,\n                           const graphics_object& obj, QMouseEvent *event);\n  void updateCurrentPoint (const graphics_object& fig,\n                           const graphics_object& obj);\n\n  void select_object (graphics_object obj, QMouseEvent *event,\n                      graphics_object& currentObj, graphics_object& axesObj,\n                      bool axes_only = false,\n                      std::vector<std::string> omit = std::vector<std::string> ());\n\nprotected:\n\n  octave::interpreter& m_interpreter;\n\nprivate:\n\n  QCursor make_cursor (const QString& name, int hot_x = -1, int hot_y = -1);\n\n  graphics_handle m_handle;\n  bool m_redrawBlocked;\n  MouseMode m_mouseMode;\n  bool m_clickMode;              // True: ZoomIn, False: ZoomOut\n  QPoint m_mouseAnchor;\n  QPoint m_mouseCurrent;\n  graphics_handle m_mouseAxes;\n  int m_eventMask;\n  bool m_rectMode;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/CheckBoxControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QCheckBox>\n\n#include \"CheckBoxControl.h\"\n#include \"Container.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nCheckBoxControl *\nCheckBoxControl::create (octave::interpreter& interp,\n                         const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new CheckBoxControl (interp, go,\n                                    new QCheckBox (container));\n    }\n\n  return nullptr;\n}\n\nCheckBoxControl::CheckBoxControl (octave::interpreter& interp,\n                                  const graphics_object& go, QCheckBox *box)\n  : ButtonControl (interp, go, box)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  box->setAutoFillBackground (true);\n  if (up.enable_is (\"inactive\"))\n    box->setCheckable (false);\n}\n\nCheckBoxControl::~CheckBoxControl ()\n{ }\n\nvoid\nCheckBoxControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QCheckBox *box = qWidget<QCheckBox> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_ENABLE:\n      {\n        if (up.enable_is (\"inactive\"))\n          box->setCheckable (false);\n        else\n          box->setCheckable (true);\n        ButtonControl::update (pId);\n      }\n      break;\n\n    default:\n      ButtonControl::update (pId);\n      break;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/CheckBoxControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_CheckBoxControl_h)\n#define octave_CheckBoxControl_h 1\n\n#include \"ButtonControl.h\"\n\nclass QCheckBox;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass CheckBoxControl : public ButtonControl\n{\npublic:\n  CheckBoxControl (octave::interpreter& interp, const graphics_object& go,\n                   QCheckBox *box);\n  ~CheckBoxControl ();\n\n  static CheckBoxControl *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/Container.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QChildEvent>\n#include <QVBoxLayout>\n\n#include \"Canvas.h\"\n#include \"Container.h\"\n#include \"Object.h\"\n#include \"QtHandlesUtils.h\"\n\n#include \"graphics.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nContainer::Container (QWidget *xparent, octave::interpreter& interp)\n  : ContainerBase (xparent), m_interpreter (interp), m_canvas (nullptr)\n{\n  setFocusPolicy (Qt::ClickFocus);\n}\n\nContainer::~Container ()\n{\n  delete m_canvas;\n}\n\nCanvas *\nContainer::canvas (const graphics_handle& gh, bool xcreate)\n{\n  if (! m_canvas && xcreate)\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      graphics_object go = gh_mgr.get_object (gh);\n\n      if (go)\n        {\n          graphics_object fig = go.get_ancestor (\"figure\");\n\n          m_canvas = Canvas::create (m_interpreter, gh, this,\n                                     fig.get (\"renderer\").string_value ());\n\n          connect (m_canvas, qOverload<const octave::fcn_callback&> (&Canvas::interpreter_event),\n                   this, qOverload<const octave::fcn_callback&> (&Container::interpreter_event));\n\n          connect (m_canvas, qOverload<const octave::meth_callback&> (&Canvas::interpreter_event),\n                   this, qOverload<const octave::meth_callback&> (&Container::interpreter_event));\n\n          connect (m_canvas,\n                   SIGNAL (gh_callback_event (const graphics_handle&,\n                                              const std::string&)),\n                   this,\n                   SIGNAL (gh_callback_event (const graphics_handle&,\n                                              const std::string&)));\n\n          connect (m_canvas,\n                   SIGNAL (gh_callback_event (const graphics_handle&,\n                                              const std::string&,\n                                              const octave_value&)),\n                   this,\n                   SIGNAL (gh_callback_event (const graphics_handle&,\n                                              const std::string&,\n                                              const octave_value&)));\n\n          connect (m_canvas,\n                   SIGNAL (gh_set_event (const graphics_handle&,\n                                         const std::string&,\n                                         const octave_value&)),\n                   this,\n                   SIGNAL (gh_set_event (const graphics_handle&,\n                                         const std::string&,\n                                         const octave_value&)));\n\n          connect (m_canvas,\n                   SIGNAL (gh_set_event (const graphics_handle&,\n                                         const std::string&,\n                                         const octave_value&, bool)),\n                   this,\n                   SIGNAL (gh_set_event (const graphics_handle&,\n                                         const std::string&,\n                                         const octave_value&, bool)));\n\n          connect (m_canvas,\n                   SIGNAL (gh_set_event (const graphics_handle&,\n                                         const std::string&,\n                                         const octave_value&, bool, bool)),\n                   this,\n                   SIGNAL (gh_set_event (const graphics_handle&,\n                                         const std::string&,\n                                         const octave_value&, bool, bool)));\n\n          QWidget *canvasWidget = m_canvas->qWidget ();\n\n          canvasWidget->lower ();\n          canvasWidget->show ();\n          canvasWidget->setGeometry (0, 0, width (), height ());\n        }\n    }\n\n  return m_canvas;\n}\n\nvoid\nContainer::resizeEvent (QResizeEvent * /* event */)\n{\n  if (m_canvas)\n    m_canvas->qWidget ()->setGeometry (0, 0, width (), height ());\n\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  for (auto *qObj : children ())\n    {\n      if (qObj->isWidgetType ())\n        {\n          Object *obj = Object::fromQObject (qObj);\n\n          if (obj)\n            {\n              graphics_object go = obj->object ();\n\n              if (go.valid_object ())\n                {\n                  Matrix bb = go.get_properties ().get_boundingbox (false);\n\n                  obj->qWidget<QWidget> ()->setGeometry\n                    (octave::math::round (bb(0)),\n                     octave::math::round (bb(1)),\n                     octave::math::round (bb(2)),\n                     octave::math::round (bb(3)));\n                }\n            }\n        }\n    }\n}\n\nvoid\nContainer::childEvent (QChildEvent *xevent)\n{\n  // Enable mouse tracking in child widgets as they are added if the\n  // container also has mouse tracking enabled.  There is no need to\n  // do this when child objects are removed.\n\n  if (xevent->added ())\n    {\n      QObject *obj = xevent->child ();\n\n      if (obj && obj->isWidgetType ())\n        {\n          QWidget *widget = qobject_cast<QWidget *> (obj);\n\n          if (widget)\n            widget->setMouseTracking (hasMouseTracking ());\n        }\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/Container.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Container_h)\n#define octave_Container_h 1\n\n#include <QWidget>\n\n#include \"GenericEventNotify.h\"\n\n#include \"event-manager.h\"\n#include \"graphics.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDECLARE_GENERICEVENTNOTIFY_SENDER(ContainerBase, QWidget);\n\nclass Canvas;\n\nclass Container : public ContainerBase\n{\n  Q_OBJECT\n\npublic:\n  Container (QWidget *parent, octave::interpreter& interp);\n  ~Container ();\n\n  Canvas * canvas (const graphics_handle& handle, bool create = true);\n\nQ_SIGNALS:\n\n  void interpreter_event (const octave::fcn_callback& fcn);\n  void interpreter_event (const octave::meth_callback& meth);\n\n  void gh_callback_event (const graphics_handle& h, const std::string& name);\n\n  void gh_callback_event (const graphics_handle& h, const std::string& name,\n                          const octave_value& data);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value, bool notify_toolkit);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value, bool notify_toolkit,\n                     bool redraw_figure);\n\nprotected:\n  void childEvent (QChildEvent *event);\n  void resizeEvent (QResizeEvent *event);\n\nprivate:\n  octave::interpreter& m_interpreter;\n  Canvas *m_canvas;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/ContextMenu.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QMenu>\n\n#include \"ContextMenu.h\"\n#include \"QtHandlesUtils.h\"\n#include \"qt-graphics-toolkit.h\"\n\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nContextMenu *\nContextMenu::create (octave::interpreter& interp, const graphics_object& go)\n{\n  Object *xparent = parentObject (interp, go);\n\n  if (xparent)\n    {\n      QWidget *w = xparent->qWidget<QWidget> ();\n\n      return new ContextMenu (interp, go, new QMenu (w));\n    }\n\n  return nullptr;\n}\n\nContextMenu::ContextMenu (octave::interpreter& interp,\n                          const graphics_object& go, QMenu *xmenu)\n  : Object (interp, go, xmenu)\n{\n  xmenu->setAutoFillBackground (true);\n\n  connect (xmenu, &QMenu::aboutToShow, this, &ContextMenu::aboutToShow);\n  connect (xmenu, &QMenu::aboutToHide, this, &ContextMenu::aboutToHide);\n}\n\nContextMenu::~ContextMenu ()\n{ }\n\nvoid\nContextMenu::update (int pId)\n{\n  uicontextmenu::properties& up = properties<uicontextmenu> ();\n  QMenu *xmenu = qWidget<QMenu> ();\n\n  switch (pId)\n    {\n    case base_properties::ID_VISIBLE:\n      if (up.is_visible ())\n        {\n          Matrix pos = up.get_position ().matrix_value ();\n          QWidget *parentW = xmenu->parentWidget ();\n          QPoint pt;\n\n          pt.rx () = octave::math::round (pos(0));\n          pt.ry () = parentW->height () - octave::math::round (pos(1));\n          pt = parentW->mapToGlobal (pt);\n\n          xmenu->popup (pt);\n        }\n      else\n        xmenu->hide ();\n      break;\n    default:\n      Object::update (pId);\n      break;\n    }\n}\n\nvoid\nContextMenu::aboutToShow ()\n{\n  Q_EMIT gh_callback_event (m_handle, \"callback\");\n  Q_EMIT gh_set_event (m_handle, \"visible\", \"on\", false);\n}\n\nvoid\nContextMenu::aboutToHide ()\n{\n  Q_EMIT gh_set_event (m_handle, \"visible\", \"off\", false);\n}\n\nQWidget *\nContextMenu::menu ()\n{\n  return qWidget<QWidget> ();\n}\n\nvoid\nContextMenu::executeAt (octave::interpreter& interp,\n                        const base_properties& props, const QPoint& pt)\n{\n  graphics_handle h = props.get_uicontextmenu ();\n\n  if (h.ok ())\n    {\n      gh_manager& gh_mgr = interp.get_gh_manager ();\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      graphics_object go = gh_mgr.get_object (h);\n\n      if (go.valid_object ())\n        {\n          ContextMenu *cMenu =\n            dynamic_cast<ContextMenu *> (qt_graphics_toolkit::toolkitObject (go));\n\n          if (cMenu)\n            {\n              QMenu *menu = cMenu->qWidget<QMenu> ();\n\n              if (menu)\n                menu->popup (pt);\n            }\n        }\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/ContextMenu.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ContextMenu_h)\n#define octave_ContextMenu_h 1\n\n#include <QPoint>\n\n#include \"MenuContainer.h\"\n#include \"Object.h\"\n\nclass QMenu;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass ContextMenu : public Object, public MenuContainer\n{\n  Q_OBJECT\n\npublic:\n  ContextMenu (octave::interpreter& interp,\n               const graphics_object& go, QMenu *menu);\n  ~ContextMenu ();\n\n  static ContextMenu *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\n  static void executeAt (octave::interpreter& interp,\n                         const base_properties& props, const QPoint& pt);\n\n  Container * innerContainer () { return nullptr; }\n\n  QWidget * menu ();\n\nprotected:\n  void update (int pId);\n\nprivate Q_SLOTS:\n  void aboutToShow ();\n  void aboutToHide ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/EditControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QLineEdit>\n\n#include \"Container.h\"\n#include \"EditControl.h\"\n#include \"TextEdit.h\"\n#include \"QtHandlesUtils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nEditControl *\nEditControl::create (octave::interpreter& interp, const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        {\n          const uicontrol::properties& up = Utils::properties<uicontrol> (go);\n\n          if ((up.get_max () - up.get_min ()) > 1)\n            return new EditControl (interp, go,\n                                    new TextEdit (container));\n          else\n            return new EditControl (interp, go,\n                                    new QLineEdit (container));\n        }\n    }\n\n  return nullptr;\n}\n\nEditControl::EditControl (octave::interpreter& interp,\n                          const graphics_object& go, QLineEdit *edit)\n  : BaseControl (interp, go, edit), m_multiLine (false),\n    m_textChanged (false)\n{\n  init (edit);\n}\n\nvoid\nEditControl::init (QLineEdit *edit, bool callBase)\n{\n  if (callBase)\n    BaseControl::init (edit, callBase);\n\n  m_multiLine = false;\n  initCommon (edit);\n\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  if (up.enable_is (\"inactive\"))\n    edit->setReadOnly (true);\n  else\n    edit->setEnabled (up.enable_is (\"on\"));\n  edit->setText (Utils::fromStdString (up.get_string_string ()));\n  edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),\n                                          up.get_verticalalignment ()));\n\n  connect (edit, &QLineEdit::textEdited,\n           this, &EditControl::textChanged);\n  connect (edit, &QLineEdit::editingFinished,\n           this, &EditControl::editingFinished);\n  connect (edit, &QLineEdit::returnPressed,\n           this, &EditControl::returnPressed);\n}\n\nEditControl::EditControl (octave::interpreter& interp,\n                          const graphics_object& go, TextEdit *edit)\n  : BaseControl (interp, go, edit), m_multiLine (true),\n    m_textChanged (false)\n{\n  init (edit);\n}\n\nvoid\nEditControl::init (TextEdit *edit, bool callBase)\n{\n  if (callBase)\n    BaseControl::init (edit, callBase);\n\n  m_multiLine = true;\n  initCommon (edit);\n\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  if (up.enable_is (\"inactive\"))\n    edit->setReadOnly (true);\n  else\n    edit->setEnabled (up.enable_is (\"on\"));\n  edit->setAcceptRichText (false);\n  edit->setPlainText (Utils::fromStringVector\n                      (up.get_string_vector ()).join (\"\\n\"));\n  edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),\n                                          up.get_verticalalignment ()));\n\n  connect (edit, &TextEdit::textChanged,\n           this, &EditControl::textChanged);\n  connect (edit, &TextEdit::editingFinished,\n           this, &EditControl::editingFinished);\n  connect (edit, &TextEdit::returnPressed,\n           this, &EditControl::returnPressed);\n}\n\nEditControl::~EditControl ()\n{ }\n\nvoid\nEditControl::initCommon (QWidget *)\n{\n  m_textChanged = false;\n}\n\nvoid\nEditControl::update (int pId)\n{\n  bool handled = false;\n\n  if (m_multiLine)\n    handled = updateMultiLine (pId);\n  else\n    handled = updateSingleLine (pId);\n\n  if (! handled)\n    {\n      switch (pId)\n        {\n        default:\n          BaseControl::update (pId);\n          break;\n        }\n    }\n}\n\nbool\nEditControl::updateSingleLine (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QLineEdit *edit = qWidget<QLineEdit> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_STRING:\n      edit->setText (Utils::fromStdString (up.get_string_string ()));\n      return true;\n\n    case uicontrol::properties::ID_HORIZONTALALIGNMENT:\n    case uicontrol::properties::ID_VERTICALALIGNMENT:\n      edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),\n                                              up.get_verticalalignment ()));\n      return true;\n\n    case uicontrol::properties::ID_ENABLE:\n      if (up.enable_is (\"inactive\"))\n        edit->setReadOnly (true);\n      else\n        {\n          edit->setReadOnly (false);\n          edit->setEnabled (up.enable_is (\"on\"));\n        }\n      return true;\n\n    case uicontrol::properties::ID_MIN:\n    case uicontrol::properties::ID_MAX:\n      if ((up.get_max () - up.get_min ()) > 1)\n        {\n          QWidget *container = edit->parentWidget ();\n\n          delete edit;\n          init (new TextEdit (container), true);\n        }\n      return true;\n\n    default:\n      break;\n    }\n\n  return false;\n}\n\nbool\nEditControl::updateMultiLine (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  TextEdit *edit = qWidget<TextEdit> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_STRING:\n      edit->setPlainText (Utils::fromStringVector\n                          (up.get_string_vector ()).join (\"\\n\"));\n      return true;\n\n    case uicontrol::properties::ID_HORIZONTALALIGNMENT:\n    case uicontrol::properties::ID_VERTICALALIGNMENT:\n      edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),\n                                              up.get_verticalalignment ()));\n      return true;\n\n    case uicontrol::properties::ID_ENABLE:\n      if (up.enable_is (\"inactive\"))\n        edit->setReadOnly (true);\n      else\n        {\n          edit->setReadOnly (false);\n          edit->setEnabled (up.enable_is (\"on\"));\n        }\n      return true;\n\n    case uicontrol::properties::ID_MIN:\n    case uicontrol::properties::ID_MAX:\n      if ((up.get_max () - up.get_min ()) <= 1)\n        {\n          QWidget *container = edit->parentWidget ();\n\n          delete edit;\n          init (new QLineEdit (container), true);\n        }\n      return true;\n\n    default:\n      break;\n    }\n\n  return false;\n}\n\nvoid\nEditControl::textChanged ()\n{\n  m_textChanged = true;\n}\n\nvoid\nEditControl::returnPressed ()\n{\n  QString txt = (m_multiLine\n                 ? qWidget<TextEdit> ()->toPlainText ()\n                 : qWidget<QLineEdit> ()->text ());\n\n  if (m_textChanged)\n    {\n      if (m_multiLine)\n        Q_EMIT gh_set_event (m_handle, \"string\",\n                             Utils::toCellString (txt.split (\"\\n\")), false);\n      else\n        Q_EMIT gh_set_event (m_handle, \"string\",\n                             Utils::toStdString (txt), false);\n\n      m_textChanged = false;\n    }\n\n  if (txt.length () > 0)\n    Q_EMIT gh_callback_event (m_handle, \"callback\");\n}\n\nvoid\nEditControl::editingFinished ()\n{\n  if (m_textChanged)\n    {\n      QString txt = (m_multiLine\n                     ? qWidget<TextEdit> ()->toPlainText ()\n                     : qWidget<QLineEdit> ()->text ());\n      if (m_multiLine)\n        Q_EMIT gh_set_event (m_handle, \"string\",\n                             Utils::toCellString (txt.split (\"\\n\")), false);\n      else\n        Q_EMIT gh_set_event (m_handle, \"string\", Utils::toStdString (txt),\n                             false);\n      Q_EMIT gh_callback_event (m_handle, \"callback\");\n\n      m_textChanged = false;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/EditControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_EditControl_h)\n#define octave_EditControl_h 1\n\n#include \"BaseControl.h\"\n\nclass QLineEdit;\nclass QWidget;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass TextEdit;\n\nclass EditControl : public BaseControl\n{\n  Q_OBJECT\n\npublic:\n  EditControl (octave::interpreter& interp,\n               const graphics_object& go, QLineEdit *edit);\n\n  EditControl (octave::interpreter& interp,\n               const graphics_object& go, TextEdit *edit);\n\n  ~EditControl ();\n\n  static EditControl *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n\nprivate:\n  void init (QLineEdit *edit, bool callBase = false);\n  void init (TextEdit *edit, bool callBase = false);\n  void initCommon (QWidget *widget);\n  bool updateSingleLine (int pId);\n  bool updateMultiLine (int pId);\n\nprivate Q_SLOTS:\n  void textChanged ();\n  void editingFinished ();\n  void returnPressed ();\n\nprivate:\n  bool m_multiLine;\n  bool m_textChanged;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/Figure.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QAction>\n#include <QActionEvent>\n#include <QApplication>\n#include <QClipboard>\n#include <QEvent>\n#include <QFileDialog>\n#include <QFileInfo>\n#include <QFrame>\n#include <QImage>\n#include <QMainWindow>\n#include <QMenu>\n#include <QMenuBar>\n#include <QMessageBox>\n#include <QtDebug>\n#include <QTimer>\n#include <QToolBar>\n#include <QWindow>\n#include <QScreen>\n\n#include \"Canvas.h\"\n#include \"Container.h\"\n#include \"Figure.h\"\n#include \"FigureWindow.h\"\n#include \"QtHandlesUtils.h\"\n\n#include \"gui-preferences-global.h\"\n#include \"qt-interpreter-events.h\"\n\n#include \"file-ops.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"version.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDECLARE_GENERICEVENTNOTIFY_SENDER(MenuBar, QMenuBar);\n\nstatic QRect\nboundingBoxToRect (const Matrix& bb)\n{\n  QRect r;\n\n  if (bb.numel () == 4)\n    {\n      r = QRect (octave::math::round (bb(0)), octave::math::round (bb(1)),\n                 octave::math::round (bb(2)), octave::math::round (bb(3)));\n      if (! r.isValid ())\n        r = QRect ();\n    }\n\n  return r;\n}\n\nstatic QImage\npointer_to_qimage (const Matrix& cdata)\n{\n  QImage retval (cdata.rows (), cdata.columns (), QImage::Format_ARGB32);\n  QColor tmp (\"White\");\n  QColor black (\"Black\");\n  QColor white (\"White\");\n  for (octave_idx_type ii = 0; ii < cdata.rows (); ii++)\n    for (octave_idx_type jj = 0; jj < cdata.columns (); jj++)\n      {\n        if (cdata(ii, jj) == 1.0)\n          tmp = black;\n        else if (cdata(ii, jj) == 2.0)\n          tmp = white;\n        else\n          tmp.setAlpha (0);\n\n        retval.setPixel (jj, ii, tmp.rgba ());\n      }\n\n  return retval;\n}\n\nFigure *\nFigure::create (octave::interpreter& interp,\n                const graphics_object& go)\n{\n  return new Figure (interp, go, new FigureWindow ());\n}\n\nFigure::Figure (octave::interpreter& interp,\n                const graphics_object& go, FigureWindow *win)\n  : Object (interp, go, win), m_blockUpdates (false),\n    m_figureToolBar (nullptr), m_menuBar (nullptr), m_innerRect (),\n    m_outerRect (), m_previousHeight (0), m_resizable (true)\n{\n  m_container = new Container (win, interp);\n  win->setCentralWidget (m_container);\n\n  connect (m_container, qOverload<const octave::fcn_callback&> (&Container::interpreter_event),\n           this, qOverload<const octave::fcn_callback&> (&Figure::interpreter_event));\n\n  connect (m_container, qOverload<const octave::meth_callback&> (&Container::interpreter_event),\n           this, qOverload<const octave::meth_callback&> (&Figure::interpreter_event));\n\n  figure::properties& fp = properties<figure> ();\n\n#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)\n  fp.set___device_pixel_ratio__ (win->devicePixelRatioF ());\n#else\n  fp.set___device_pixel_ratio__ (win->devicePixelRatio ());\n#endif\n\n  // Adjust figure position\n  m_innerRect = boundingBoxToRect (fp.get_boundingbox (true));\n  m_outerRect = boundingBoxToRect (fp.get_boundingbox (false));\n\n  set_geometry (m_innerRect);\n\n  // Menubar\n  m_menuBar = new MenuBar (win);\n  win->setMenuBar (m_menuBar);\n  m_menuBar->addReceiver (this);\n  m_menuBar->setStyleSheet (m_menuBar->styleSheet () + global_menubar_style);\n\n  // Status bar\n  m_statusBar = win->statusBar ();\n  m_statusBar->setVisible (false);\n\n  if (fp.toolbar_is (\"figure\")\n      || (fp.toolbar_is (\"auto\") && fp.menubar_is (\"figure\")))\n    showFigureStatusBar (true);\n\n  // Enable mouse tracking unconditionally\n  enableMouseTracking ();\n\n  // When this constructor gets called all properties are already\n  // set, even non default.  We force \"update\" here to get things right.\n\n  // Figure title\n  update (figure::properties::ID_NUMBERTITLE);\n\n  // Decide what keyboard events we listen to\n  Canvas *canvas = m_container->canvas (m_handle);\n  if (canvas)\n    canvas->setEventMask (0);\n  update (figure::properties::ID_KEYPRESSFCN);\n  update (figure::properties::ID_KEYRELEASEFCN);\n\n  // modal style\n  update (figure::properties::ID_WINDOWSTYLE);\n\n  // Handle resizing constraints\n  update (figure::properties::ID_RESIZE);\n\n  // Custom pointer data\n  update (figure::properties::ID_POINTERSHAPECDATA);\n\n  // Visibility\n  update (figure::properties::ID_VISIBLE);\n\n  connect (this, &Figure::asyncUpdate, this, &Figure::updateContainer);\n\n  // Register for the signal that indicates when a window has moved\n  // to a different screen\n  connect (win, &FigureWindow::figureWindowShown,\n           this, &Figure::figureWindowShown);\n\n  win->addReceiver (this);\n  m_container->addReceiver (this);\n}\n\nFigure::~Figure ()\n{ }\n\nQString\nFigure::fileName ()\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  const figure::properties& fp = properties<figure> ();\n\n  std::string name = fp.get_filename ();\n\n  return QString::fromStdString (name);\n}\n\nvoid\nFigure::setFileName (const QString& name)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  figure::properties& fp = properties<figure> ();\n\n  fp.set_filename (name.toStdString ());\n}\n\nMouseMode\nFigure::mouseMode ()\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  const figure::properties& fp = properties<figure> ();\n\n  std::string mode = fp.get___mouse_mode__ ();\n\n  if (mode == \"zoom\")\n    {\n      octave_scalar_map zm = fp.get___zoom_mode__ ().scalar_map_value ();\n\n      std::string direction = zm.getfield (\"Direction\").string_value ();\n\n      mode += ' ' + direction;\n    }\n\n  if (mode == \"rotate\")\n    return RotateMode;\n  else if (mode == \"zoom in\")\n    return ZoomInMode;\n  else if (mode == \"zoom out\")\n    return ZoomOutMode;\n  else if (mode == \"pan\")\n    return PanMode;\n  else if (mode == \"text\")\n    return TextMode;\n\n  return NoMode;\n}\n\nvoid\nFigure::set_geometry (QRect r)\n{\n  QMainWindow *win = qWidget<QMainWindow> ();\n\n  if (! m_resizable)\n    {\n      win->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred);\n      win->setFixedSize (QSize (QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));\n    }\n\n  // Unlock window if it is maximized or full-screen\n  int state = win->windowState ();\n  if (state == Qt::WindowFullScreen || state == Qt::WindowMaximized)\n    win->setWindowState (Qt::WindowNoState);\n\n  win->setGeometry (r);\n\n  if (! m_resizable)\n    {\n      win->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);\n      win->setFixedSize (win->size ());\n    }\n}\n\nContainer *\nFigure::innerContainer ()\n{\n  return m_container;\n}\n\nvoid\nFigure::redraw ()\n{\n  Canvas *canvas = m_container->canvas (m_handle);\n\n  if (canvas)\n    canvas->redraw ();\n\n  for (auto *qobj : qWidget<QWidget> ()->findChildren<QObject *> ())\n    {\n      if (qobj->objectName () == \"UIPanel\"\n          || qobj->objectName () == \"UIButtonGroup\"\n          || qobj->objectName () == \"UIControl\"\n          || qobj->objectName () == \"UITable\")\n        {\n          Object *obj = Object::fromQObject (qobj);\n\n          if (obj)\n            obj->slotRedraw ();\n        }\n    }\n}\n\nvoid\nFigure::show ()\n{\n  QWidget *win = qWidget<QWidget> ();\n\n  win->activateWindow ();\n  win->raise ();\n}\n\nvoid\nFigure::print (const QString& file_cmd, const QString& term)\n{\n  Canvas *canvas = m_container->canvas (m_handle);\n\n  if (canvas)\n    canvas->print (file_cmd, term);\n}\n\nuint8NDArray\nFigure::slotGetPixels ()\n{\n  uint8NDArray retval;\n  Canvas *canvas = m_container->canvas (m_handle);\n\n  if (canvas)\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      gh_mgr.process_events ();\n      octave::autolock guard (gh_mgr.graphics_lock ());\n      retval = canvas->getPixels ();\n    }\n\n  return retval;\n}\n\nvoid\nFigure::beingDeleted ()\n{\n  Canvas *canvas = m_container->canvas (m_handle.value (), false);\n\n  if (canvas)\n    canvas->blockRedraw (true);\n\n  m_container->removeReceiver (this);\n  qWidget<FigureWindow> ()->removeReceiver (this);\n}\n\nvoid\nFigure::update (int pId)\n{\n  if (m_blockUpdates)\n    return;\n\n  figure::properties& fp = properties<figure> ();\n\n  if (fp.is___printing__ ())\n    return;\n\n  QMainWindow *win = qWidget<QMainWindow> ();\n\n  // If the window doesn't exist, there's nothing we can do.\n  if (! win)\n    return;\n\n  m_blockUpdates = true;\n\n  switch (pId)\n    {\n    case figure::properties::ID_POSITION:\n      {\n        m_innerRect = boundingBoxToRect (fp.get_boundingbox (true));\n        int toffset = 0;\n        int boffset = 0;\n\n        for (auto *tb : win->findChildren<QToolBar *> ())\n          if (! tb->isHidden ())\n            toffset += tb->sizeHint ().height ();\n\n        if (! m_menuBar->isHidden ())\n          toffset += m_menuBar->sizeHint ().height ();\n\n        if (! m_statusBar->isHidden ())\n          boffset += m_statusBar->sizeHint ().height ();\n\n        set_geometry (m_innerRect.adjusted (0, -toffset, 0, boffset));\n      }\n      break;\n\n    case figure::properties::ID_NAME:\n    case figure::properties::ID_NUMBERTITLE:\n      win->setWindowTitle (Utils::fromStdString (fp.get_title ()));\n      break;\n\n    case figure::properties::ID_VISIBLE:\n      if (fp.is_visible ())\n        {\n          QTimer::singleShot (0, win, &QMainWindow::show);\n          if (! fp.is___gl_window__ ())\n            {\n              gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n              octave::autolock guard (gh_mgr.graphics_lock ());\n              fp.set (\"__gl_window__\", \"on\");\n            }\n        }\n      else\n        win->hide ();\n      break;\n\n    case figure::properties::ID_RESIZE:\n      if (fp.is_resize ())\n        {\n          win->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred);\n          win->setFixedSize (QSize (QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));\n          m_resizable = true;\n        }\n      else\n        {\n          win->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);\n          win->setFixedSize (win->size ());\n          m_resizable = false;\n        }\n      break;\n\n    case figure::properties::ID_MENUBAR:\n    case figure::properties::ID_TOOLBAR:\n      if (fp.toolbar_is (\"none\"))\n        showFigureStatusBar (false);\n      else if (fp.toolbar_is (\"figure\"))\n        showFigureStatusBar (true);\n      else  // \"auto\"\n        showFigureStatusBar (fp.menubar_is (\"figure\"));\n      break;\n\n    case figure::properties::ID_KEYPRESSFCN:\n      {\n        Canvas *canvas = m_container->canvas (m_handle);\n\n        if (canvas)\n          {\n            if (fp.get_keypressfcn ().isempty ())\n              canvas->clearEventMask (Canvas::KeyPress);\n            else\n              canvas->addEventMask (Canvas::KeyPress);\n          }\n\n        // Signal the change to uipanels as well\n        for (auto *qobj : qWidget<QWidget> ()->findChildren<QObject *> ())\n          {\n            if (qobj->objectName () == \"UIPanel\")\n              {\n                Object *obj = Object::fromQObject (qobj);\n\n                if (obj)\n                  {\n                    if (fp.get_keypressfcn ().isempty ())\n                      obj->innerContainer ()->canvas (m_handle)->\n                        clearEventMask (Canvas::KeyPress);\n                    else\n                      obj->innerContainer ()->canvas (m_handle)->\n                        addEventMask (Canvas::KeyPress);\n                  }\n              }\n          }\n      }\n      break;\n\n    case figure::properties::ID_KEYRELEASEFCN:\n      {\n        Canvas *canvas = m_container->canvas (m_handle);\n\n        if (canvas)\n          {\n            if (fp.get_keyreleasefcn ().isempty ())\n              canvas->clearEventMask (Canvas::KeyRelease);\n            else\n              canvas->addEventMask (Canvas::KeyRelease);\n          }\n        break;\n        // Signal the change to uipanels as well\n        for (auto *qobj : qWidget<QWidget> ()->findChildren<QObject *> ())\n          {\n            if (qobj->objectName () == \"UIPanel\")\n              {\n                Object *obj = Object::fromQObject (qobj);\n\n                if (obj)\n                  {\n                    if (fp.get_keypressfcn ().isempty ())\n                      obj->innerContainer ()->canvas (m_handle)->\n                        clearEventMask (Canvas::KeyRelease);\n                    else\n                      obj->innerContainer ()->canvas (m_handle)->\n                        addEventMask (Canvas::KeyRelease);\n                  }\n              }\n          }\n      }\n      break;\n\n    case figure::properties::ID_WINDOWSTYLE:\n      if (fp.windowstyle_is (\"modal\"))\n        {\n          bool is_visible = win->isVisible ();\n\n          // if window is already visible, need to hide and reshow it in order to\n          // make it use the modal settings\n          if (is_visible)\n            win->setVisible (false);\n\n          win->setWindowModality (Qt::ApplicationModal);\n          win->setVisible (is_visible);\n        }\n      else\n        win->setWindowModality (Qt::NonModal);\n\n      break;\n\n    case figure::properties::ID_POINTERSHAPECDATA:\n      m_pointer_cdata =\n        pointer_to_qimage (fp.get_pointershapecdata ().matrix_value ());\n      if (fp.get_pointer () != \"custom\")\n        break;\n      OCTAVE_FALLTHROUGH;\n\n    case figure::properties::ID_POINTER:\n    case figure::properties::ID_POINTERSHAPEHOTSPOT:\n    case figure::properties::ID___MOUSE_MODE__:\n    case figure::properties::ID___ZOOM_MODE__:\n      {\n        Canvas *canvas = m_container->canvas (m_handle);\n\n        if (canvas)\n          canvas->setCursor (mouseMode (), fp.get_pointer (),\n                             m_pointer_cdata,\n                             fp.get_pointershapehotspot ().matrix_value ());\n      }\n      break;\n\n    default:\n      break;\n    }\n\n  m_blockUpdates = false;\n}\n\nvoid\nFigure::showFigureStatusBar (bool visible)\n{\n  if (m_statusBar\n      && (! m_statusBar->isHidden ()) != visible)\n    {\n      int dy = m_statusBar->sizeHint ().height ();\n      QRect r = qWidget<QWidget> ()->geometry ();\n\n      if (! visible)\n        r.adjust (0, 0, 0, -dy);\n      else\n        r.adjust (0, 0, 0, dy);\n\n      m_blockUpdates = true;\n      set_geometry (r);\n      m_statusBar->setVisible (visible);\n      m_blockUpdates = false;\n\n      updateBoundingBox (false);\n    }\n}\n\nvoid\nFigure::updateFigureHeight (int dh)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n  graphics_object go = object ();\n\n  if (go.valid_object () && dh != 0)\n    {\n      QRect r = qWidget<QWidget> ()->geometry ();\n\n      r.adjust (0, dh, 0, 0);\n\n      m_blockUpdates = true;\n      set_geometry (r);\n      m_blockUpdates = false;\n\n      updateBoundingBox (false);\n    }\n}\n\nvoid\nFigure::updateStatusBar (ColumnVector pt)\n{\n  if (! m_statusBar->isHidden ())\n    m_statusBar->showMessage (QString (\"(%1, %2)\")\n                              .arg (pt(0), 0, 'g', 5)\n                              .arg (pt(1), 0, 'g', 5));\n}\n\nvoid\nFigure::do_connections (const QObject *receiver, const QObject * /* emitter */)\n{\n  Object::do_connections (receiver);\n  Object::do_connections (receiver, m_container->canvas (m_handle));\n}\n\nQWidget *\nFigure::menu ()\n{\n  return qWidget<QMainWindow> ()->menuBar ();\n}\n\nvoid\nFigure::updateBoundingBox (bool internal, int flags)\n{\n  QWidget *win = qWidget<QWidget> ();\n  Matrix bb (1, 4);\n  std::string prop;\n\n  if (internal)\n    {\n      prop = \"position\";\n      QRect r = m_innerRect;\n\n      if (flags & UpdateBoundingBoxPosition)\n        r.moveTopLeft (win->mapToGlobal (m_container->pos ()));\n      if (flags & UpdateBoundingBoxSize)\n        r.setSize (m_container->size ());\n\n      if (r.isValid () && r != m_innerRect)\n        {\n          m_innerRect = r;\n\n          bb(0) = r.x ();\n          bb(1) = r.y ();\n          bb(2) = r.width ();\n          bb(3) = r.height ();\n        }\n      else\n        return;\n    }\n  else\n    {\n      prop = \"outerposition\";\n      QRect r = m_outerRect;\n\n      if (flags & UpdateBoundingBoxPosition)\n        r.moveTopLeft (win->pos ());\n      if (flags & UpdateBoundingBoxSize)\n        r.setSize (win->frameGeometry ().size ());\n\n      if (r.isValid () && r != m_outerRect)\n        {\n          m_outerRect = r;\n\n          bb(0) = r.x ();\n          bb(1) = r.y ();\n          bb(2) = r.width ();\n          bb(3) = r.height ();\n        }\n      else\n        return;\n    }\n\n  figure::properties& fp = properties<figure> ();\n\n  Q_EMIT gh_set_event (m_handle, prop, fp.bbox2position (bb), false,\n                       prop == \"position\");\n}\n\nbool\nFigure::eventNotifyBefore (QObject *obj, QEvent *xevent)\n{\n  if (! m_blockUpdates)\n    {\n      // Clicking the toolbar or the menubar makes this figure current\n      if (xevent->type () == QEvent::MouseButtonPress)\n        {\n          figure::properties& fp = properties<figure> ();\n\n          gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n          graphics_object root = gh_mgr.get_object (0);\n\n          if (fp.get_handlevisibility () == \"on\")\n            root.set (\"currentfigure\",\n                      fp.get___myhandle__ ().as_octave_value ());\n        }\n\n      if (obj == m_container)\n        {\n          // Do nothing...\n        }\n      else if (obj == m_menuBar)\n        {\n          switch (xevent->type ())\n            {\n            case QEvent::ActionAdded:\n            case QEvent::ActionChanged:\n            case QEvent::ActionRemoved:\n              m_previousHeight = m_menuBar->sizeHint ().height ();\n\n            default:\n              break;\n            }\n        }\n      else\n        {\n          switch (xevent->type ())\n            {\n            case QEvent::Close:\n              xevent->ignore ();\n              Q_EMIT gh_callback_event (m_handle, \"closerequestfcn\");\n              return true;\n\n            default:\n              break;\n            }\n        }\n    }\n\n  return false;\n}\n\nvoid\nFigure::eventNotifyAfter (QObject *watched, QEvent *xevent)\n{\n  if (! m_blockUpdates)\n    {\n      if (watched == m_container)\n        {\n          gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n          switch (xevent->type ())\n            {\n            case QEvent::Resize:\n              updateBoundingBox (true, UpdateBoundingBoxSize);\n              break;\n\n            case QEvent::ChildAdded:\n              if (dynamic_cast<QChildEvent *> (xevent)->child ()->isWidgetType())\n                {\n                  octave::autolock guard (gh_mgr.graphics_lock ());\n                  update (figure::properties::ID_TOOLBAR);\n\n                  enableMouseTracking ();\n                }\n              break;\n\n            case QEvent::ChildRemoved:\n              if (dynamic_cast<QChildEvent *> (xevent)->child ()->isWidgetType())\n                {\n                  octave::autolock guard (gh_mgr.graphics_lock ());\n                  update (figure::properties::ID_TOOLBAR);\n                }\n              break;\n\n            default:\n              break;\n            }\n        }\n      else if (watched == m_menuBar)\n        {\n          switch (xevent->type ())\n            {\n            case QEvent::ActionAdded:\n            case QEvent::ActionChanged:\n            case QEvent::ActionRemoved:\n              // The menubar may have been resized if no action is visible\n              {\n                QAction *a = dynamic_cast<QActionEvent *> (xevent)->action ();\n                int currentHeight = m_menuBar->sizeHint ().height ();\n                if (currentHeight != m_previousHeight\n                    && ! a->isSeparator ())\n                  updateFigureHeight (m_previousHeight - currentHeight);\n              }\n              break;\n\n            default:\n              break;\n            }\n        }\n      else\n        {\n          switch (xevent->type ())\n            {\n            case QEvent::Move:\n              updateBoundingBox (false, UpdateBoundingBoxPosition);\n              updateBoundingBox (true, UpdateBoundingBoxPosition);\n              break;\n\n            case QEvent::Resize:\n              updateBoundingBox (false, UpdateBoundingBoxSize);\n              break;\n\n            default:\n              break;\n            }\n        }\n    }\n}\n\nvoid\nFigure::addCustomToolBar (QToolBar *bar, bool visible, bool isdefault)\n{\n  QMainWindow *win = qWidget<QMainWindow> ();\n\n  if (isdefault)\n    m_figureToolBar = bar;\n\n  if (! visible)\n    win->addToolBar (bar);\n  else\n    {\n      QSize sz = bar->sizeHint ();\n      QRect r = win->geometry ();\n\n      r.adjust (0, -sz.height (), 0, 0);\n\n      m_blockUpdates = true;\n      set_geometry (r);\n      win->addToolBarBreak ();\n      win->addToolBar (bar);\n      m_blockUpdates = false;\n\n      updateBoundingBox (false);\n    }\n}\n\nvoid\nFigure::showCustomToolBar (QToolBar *bar, bool visible)\n{\n  QMainWindow *win = qWidget<QMainWindow> ();\n\n  if ((! bar->isHidden ()) != visible)\n    {\n      QSize sz = bar->sizeHint ();\n      QRect r = win->geometry ();\n\n      if (visible)\n        r.adjust (0, -sz.height (), 0, 0);\n      else\n        r.adjust (0, sz.height (), 0, 0);\n\n      m_blockUpdates = true;\n      set_geometry (r);\n      bar->setVisible (visible);\n      m_blockUpdates = false;\n\n      updateBoundingBox (false);\n    }\n}\n\nvoid\nFigure::updateContainer ()\n{\n  redraw ();\n}\n\nvoid\nFigure::figureWindowShown ()\n{\n  QWindow *window = qWidget<QMainWindow> ()->windowHandle ();\n\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  figure::properties& fp = properties<figure> ();\n\n#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)\n  QMainWindow *main_win = qWidget<QMainWindow> ();\n  fp.set___device_pixel_ratio__ (main_win->devicePixelRatioF ());\n#else\n  QScreen *screen = window->screen ();\n  fp.set___device_pixel_ratio__ (screen->devicePixelRatio ());\n#endif\n\n  connect (window, &QWindow::screenChanged, this, &Figure::screenChanged);\n}\n\nvoid\nFigure::screenChanged (QScreen *screen)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  figure::properties& fp = properties<figure> ();\n  double old_dpr = fp.get___device_pixel_ratio__ ();\n\n#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)\n  QMainWindow *main_win = qWidget<QMainWindow> ();\n  double new_dpr = main_win->devicePixelRatioF ();\n\n  octave_unused_parameter (screen);\n#else\n  double new_dpr = screen->devicePixelRatio ();\n#endif\n\n  if (old_dpr != new_dpr)\n    {\n      fp.set___device_pixel_ratio__ (new_dpr);\n\n      // For some obscure reason, changing the __device_pixel_ratio__ property\n      // from the GUI thread does not necessarily trigger a redraw.  Force it.\n      redraw ();\n    }\n}\n\nvoid\nFigure::enableMouseTracking ()\n{\n  // Enable mouse tracking on every widgets\n  m_container->setMouseTracking (true);\n\n  Canvas *canvas = m_container->canvas (m_handle);\n\n  if (canvas)\n    canvas->qWidget ()->setMouseTracking (true);\n\n  for (auto *w : m_container->findChildren<QWidget *> ())\n    w->setMouseTracking (true);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/Figure.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Figure_h)\n#define octave_Figure_h 1\n\n#include <QRect>\n#include <QStatusBar>\n\n#include \"GenericEventNotify.h\"\n#include \"MenuContainer.h\"\n#include \"Object.h\"\n\nclass QMainWindow;\nclass QToolBar;\nclass QScreen;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nenum MouseMode\n{\n  NoMode,\n  RotateMode,\n  ZoomInMode,\n  ZoomOutMode,\n  PanMode,\n  SelectMode,\n  TextMode\n};\n\nclass Container;\nclass FigureWindow;\nclass MenuBar;\nclass ToolBar;\n\nclass Figure :\n  public Object,\n  public MenuContainer,\n  public GenericEventNotifyReceiver\n{\n  Q_OBJECT\n\n  friend class ToolBar;\n\npublic:\n  Figure (octave::interpreter& interp,\n          const graphics_object& go, FigureWindow *win);\n  ~Figure ();\n\n  static Figure *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\n  QString fileName ();\n  void setFileName (const QString& name);\n\n  MouseMode mouseMode ();\n\n  Container * innerContainer ();\n  QWidget * menu ();\n  void updateStatusBar (ColumnVector pt);\n\n  void do_connections (const QObject *receiver,\n                       const QObject *emitter = nullptr);\n\n  bool eventNotifyBefore (QObject *watched, QEvent *event);\n  void eventNotifyAfter (QObject *watched, QEvent *event);\n\nprotected:\n  enum UpdateBoundingBoxFlag\n  {\n    UpdateBoundingBoxPosition = 0x1,\n    UpdateBoundingBoxSize     = 0x2,\n    UpdateBoundingBoxAll      = 0x3\n  };\n\nprotected:\n  void redraw ();\n  void show ();\n  void print (const QString& file_cmd, const QString& term);\n  void update (int pId);\n  void updateBoundingBox (bool internal = false, int flags = 0);\n  void beingDeleted ();\n\nprivate:\n  void showFigureStatusBar (bool visible);\n  void addCustomToolBar (QToolBar *bar, bool visible, bool isdefault);\n  void showCustomToolBar (QToolBar *bar, bool visible);\n  void set_geometry (QRect r);\n\n  void enableMouseTracking ();\n\nprivate Q_SLOTS:\n  void updateFigureHeight (int delta_h);\n  void updateContainer ();\n  void figureWindowShown ();\n  void screenChanged (QScreen *);\n\npublic Q_SLOTS:\n  uint8NDArray slotGetPixels ();\n\nQ_SIGNALS:\n  void asyncUpdate ();\n  void interpreter_event (const octave::fcn_callback& fcn);\n  void interpreter_event (const octave::meth_callback& meth);\n\nprivate:\n  Container *m_container;\n  bool m_blockUpdates;\n  QToolBar *m_figureToolBar;\n  MenuBar *m_menuBar;\n  QStatusBar *m_statusBar;\n  QRect m_innerRect;\n  QRect m_outerRect;\n  QImage m_pointer_cdata;\n  int m_previousHeight;\n  bool m_resizable;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/FigureWindow.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QMenu>\n\n#include \"FigureWindow.h\"\n#include \"gui-preferences-dw.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nFigureWindow::FigureWindow (QWidget *xparent)\n  : FigureWindowBase (xparent)\n{\n  // Set icon from application resources.  Since FigureWindow is also used by\n  // msgbox (in turn used by helpdlg, warndlg, ...), the logo should be the\n  // neutral Octave icon:\n  setWindowIcon (QIcon (dw_icon_set_names[\"NONE\"]));\n}\n\nFigureWindow::~FigureWindow ()\n{ }\n\nQMenu *\nFigureWindow::createPopupMenu ()\n{\n  // For the time being, disable menubar/toolbar popup menu\n  return nullptr;\n}\n\nvoid\nFigureWindow::showEvent (QShowEvent *ev)\n{\n  QMainWindow::showEvent (ev);\n  Q_EMIT figureWindowShown ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/FigureWindow.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_FigureWindow_h)\n#define octave_FigureWindow_h 1\n\n#include <QMainWindow>\n\n#include \"GenericEventNotify.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDECLARE_GENERICEVENTNOTIFY_SENDER(FigureWindowBase, QMainWindow);\n\nclass FigureWindow : public FigureWindowBase\n{\n  Q_OBJECT\n\npublic:\n  explicit FigureWindow (QWidget *parent = nullptr);\n  ~FigureWindow ();\n\n  QMenu * createPopupMenu ();\n\nprotected:\n  void showEvent (QShowEvent *ev);\n\nQ_SIGNALS:\n  void figureWindowShown ();\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/GLCanvas.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"GLCanvas.h\"\n#include \"gl-select.h\"\n\n#include \"gl-render.h\"\n#include \"gl2ps-print.h\"\n#include \"graphics.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nGLWidget::GLWidget (Canvas& parent_canvas, QWidget *parent)\n  : QOpenGLWidget (parent), m_parent_canvas (parent_canvas),\n    m_glfcns (), m_renderer (m_glfcns)\n{\n  setFocusPolicy (Qt::ClickFocus);\n  setFocus ();\n  setUpdateBehavior (QOpenGLWidget::PartialUpdate);\n}\n\nGLWidget::~GLWidget () { }\n\nvoid\nGLWidget::initializeGL ()\n{\n  // The qopengl_functions object (part of Octave, not Qt) is just\n  // wrapper around QOpenGLFunctions_1_1.  Does initialization really\n  // need to be deferred until initializeGL is called?\n\n  m_glfcns.init ();\n\n  // All other resources we need are currently (supposed to be)\n  // managed by the QOpenGLWidget object so there is else nothing to\n  // do here.  If we used custom shader programs, then we would need\n  // to initialize them here.\n}\n\nvoid\nGLWidget::draw (graphics_object go)\n{\n  if (go)\n    {\n      if (! begin_rendering ())\n        return;\n\n      unwind_action reset_current ([this] () { end_rendering (); });\n\n      graphics_object fig = go.get_ancestor (\"figure\");\n      double dpr = fig.get (\"__device_pixel_ratio__\").double_value ();\n      m_renderer.set_viewport (dpr * width (), dpr * height ());\n      m_renderer.set_device_pixel_ratio (dpr);\n\n      m_renderer.draw (go);\n    }\n}\n\nuint8NDArray\nGLWidget::do_getPixels (graphics_object go)\n{\n  uint8NDArray retval;\n\n  if (go && go.isa (\"figure\"))\n    {\n      Matrix pos = go.get (\"position\").matrix_value ();\n      double dpr = go.get (\"__device_pixel_ratio__\").double_value ();\n      pos(2) *= dpr;\n      pos(3) *= dpr;\n\n      if (! begin_rendering ())\n        return uint8NDArray ();\n\n      unwind_action reset_current ([this] () { end_rendering (); });\n\n      // When the figure is not visible or its size is frozen for printing,\n      // we use a framebuffer object to make sure we are rendering on a\n      // suitably large frame.\n      if (go.get (\"visible\").string_value () == \"off\"\n          || go.get (\"__printing__\").string_value () == \"on\")\n        {\n          QOpenGLFramebufferObject\n            fbo (pos(2), pos(3),\n                 QOpenGLFramebufferObject::Attachment::Depth);\n\n          fbo.bind ();\n\n          unwind_action release_fbo ([&fbo] () { fbo.release (); });\n\n          m_renderer.set_viewport (pos(2), pos(3));\n          m_renderer.set_device_pixel_ratio (dpr);\n          m_renderer.draw (go);\n\n          retval = m_renderer.get_pixels (pos(2), pos(3));\n        }\n      else\n        {\n          m_renderer.set_viewport (pos(2), pos(3));\n          m_renderer.set_device_pixel_ratio (dpr);\n          m_renderer.draw (go);\n\n          retval = m_renderer.get_pixels (pos(2), pos(3));\n        }\n    }\n\n  return retval;\n}\n\nvoid\nGLWidget::do_print (const QString& file_cmd, const QString& term,\n                    graphics_object go)\n{\n  if (go.valid_object ())\n    {\n      if (! begin_rendering ())\n        return;\n\n      unwind_action reset_current ([this] () { end_rendering (); });\n\n      graphics_object fig (go.get_ancestor (\"figure\"));\n\n      if (fig.get (\"visible\").string_value () == \"on\")\n        octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (),\n                             term.toStdString ());\n      else\n        {\n          // When the figure is not visible, we use a framebuffer object\n          // to make sure we are rendering on a suitably large frame.\n          Matrix pos = fig.get (\"position\").matrix_value ();\n          double dpr = fig.get (\"__device_pixel_ratio__\").double_value ();\n          pos(2) *= dpr;\n          pos(3) *= dpr;\n\n          QOpenGLFramebufferObject\n            fbo (pos(2), pos(3),\n                 QOpenGLFramebufferObject::Attachment::Depth);\n\n          fbo.bind ();\n\n          unwind_action release_fbo ([&fbo] () { fbo.release (); });\n\n          octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (),\n                               term.toStdString ());\n        }\n    }\n}\n\ngraphics_object\nGLWidget::selectFromAxes (const graphics_object& ax, const QPoint& pt)\n{\n  if (ax)\n    {\n      if (! begin_rendering ())\n        return graphics_object ();\n\n      unwind_action reset_current ([this] () { end_rendering (); });\n\n      octave::opengl_selector s (m_glfcns);\n\n      s.set_viewport (width (), height ());\n\n      return s.select (ax, pt.x (), height () - pt.y (),\n                       octave::select_ignore_hittest);\n    }\n\n  return graphics_object ();\n}\n\nvoid\nGLWidget::drawZoomBox (const QPoint& p1, const QPoint& p2)\n{\n  Matrix overlaycolor (3, 1);\n  overlaycolor(0) = 0.45;\n  overlaycolor(1) = 0.62;\n  overlaycolor(2) = 0.81;\n  double overlayalpha = 0.1;\n  Matrix bordercolor = overlaycolor;\n  double borderalpha = 0.9;\n  double borderwidth = 1.5;\n\n  if (! begin_rendering ())\n    return;\n\n  unwind_action reset_current ([this] () { end_rendering (); });\n\n  m_renderer.draw_zoom_box (width (), height (),\n                            p1.x (), p1.y (), p2.x (), p2.y (),\n                            overlaycolor, overlayalpha,\n                            bordercolor, borderalpha, borderwidth);\n}\n\nvoid\nGLWidget::paintGL ()\n{\n  m_parent_canvas.canvasPaintEvent ();\n}\n\nvoid\nGLWidget::mouseDoubleClickEvent (QMouseEvent *xevent)\n{\n  m_parent_canvas.canvasMouseDoubleClickEvent (xevent);\n}\n\nvoid\nGLWidget::mouseMoveEvent (QMouseEvent *xevent)\n{\n  m_parent_canvas.canvasMouseMoveEvent (xevent);\n}\n\nvoid\nGLWidget::mousePressEvent (QMouseEvent *xevent)\n{\n  m_parent_canvas.canvasMousePressEvent (xevent);\n}\n\nvoid\nGLWidget::mouseReleaseEvent (QMouseEvent *xevent)\n{\n  m_parent_canvas.canvasMouseReleaseEvent (xevent);\n}\n\nvoid\nGLWidget::wheelEvent (QWheelEvent *xevent)\n{\n  m_parent_canvas.canvasWheelEvent (xevent);\n}\n\nvoid\nGLWidget::keyPressEvent (QKeyEvent *xevent)\n{\n  if (! m_parent_canvas.canvasKeyPressEvent (xevent))\n    QOpenGLWidget::keyPressEvent (xevent);\n}\n\nvoid\nGLWidget::keyReleaseEvent (QKeyEvent *xevent)\n{\n  if (! m_parent_canvas.canvasKeyReleaseEvent (xevent))\n    QOpenGLWidget::keyReleaseEvent (xevent);\n}\n\nbool\nGLWidget::begin_rendering ()\n{\n  bool retval = true;\n\n  if (! isValid ())\n    {\n      // FIXME: Is this really the right way to manager offscreen\n      // rendering for printing?\n\n      static bool os_ctx_ok = true;\n\n      if (os_ctx_ok && ! m_os_context.isValid ())\n        {\n          // Try to initialize offscreen context\n          m_os_surface.create ();\n\n          if (! m_os_context.create ())\n            {\n              os_ctx_ok = false;\n              return false;\n            }\n        }\n\n      retval = m_os_context.makeCurrent (&m_os_surface);\n    }\n  else\n    makeCurrent ();\n\n  return retval;\n}\n\nvoid\nGLWidget::end_rendering ()\n{\n  doneCurrent ();\n}\n\nGLCanvas::GLCanvas (octave::interpreter& interp,\n                    const graphics_handle& gh, QWidget *parent)\n  : Canvas (interp, gh), m_glwidget (new GLWidget (*this, parent))\n{ }\n\nGLCanvas::~GLCanvas ()\n{\n  delete m_glwidget;\n}\n\nvoid\nGLCanvas::draw (const graphics_handle& gh)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard  (gh_mgr.graphics_lock ());\n\n  graphics_object go = gh_mgr.get_object (gh);\n\n  m_glwidget->draw (go);\n}\n\nuint8NDArray\nGLCanvas::do_getPixels (const graphics_handle& gh)\n{\n  uint8NDArray retval;\n\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  graphics_object go = gh_mgr.get_object (gh);\n\n  return m_glwidget->do_getPixels (go);\n}\n\nvoid\nGLCanvas::do_print (const QString& file_cmd, const QString& term,\n                    const graphics_handle& handle)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard  (gh_mgr.graphics_lock ());\n\n  graphics_object go = gh_mgr.get_object (handle);\n\n  try\n    {\n      m_glwidget->do_print (file_cmd, term, go);\n    }\n  catch (octave::execution_exception& ee)\n    {\n      Q_EMIT interpreter_event\n        ([ee] ()\n        {\n          // INTERPRETER THREAD\n          throw ee;\n        });\n    }\n}\n\ngraphics_object\nGLCanvas::selectFromAxes (const graphics_object& ax, const QPoint& pt)\n{\n  return m_glwidget->selectFromAxes (ax, pt);\n}\n\nvoid\nGLCanvas::drawZoomBox (const QPoint& p1, const QPoint& p2)\n{\n  m_glwidget->drawZoomBox (p1, p2);\n}\n\nbool\nGLCanvas::begin_rendering ()\n{\n  return m_glwidget->begin_rendering ();\n}\n\nvoid\nGLCanvas::end_rendering ()\n{\n  m_glwidget->end_rendering ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/GLCanvas.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_GLCanvas_h)\n#define octave_GLCanvas_h 1\n\n#include <QOffscreenSurface>\n#include <QOpenGLContext>\n#include <QOpenGLFramebufferObject>\n#include <QOpenGLWidget>\n\n#include \"Canvas.h\"\n\n#include \"gl-render.h\"\n#include \"qopengl-functions.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass GLWidget : public QOpenGLWidget\n{\n  Q_OBJECT\n\npublic:\n\n  GLWidget (Canvas& parent_canvas, QWidget *parent);\n\n  ~GLWidget ();\n\n  void initializeGL ();\n\n  void draw (graphics_object go);\n  uint8NDArray do_getPixels (graphics_object go);\n  void do_print (const QString& file_cmd, const QString& term,\n                 graphics_object go);\n  void drawZoomBox (const QPoint& p1, const QPoint& p2);\n  void resize (int /* x */, int /* y */,\n               int /* width */, int /* height */) { }\n  graphics_object selectFromAxes (const graphics_object& ax,\n                                  const QPoint& pt);\n\n  bool begin_rendering ();\n  void end_rendering ();\n\nprotected:\n\n  void paintGL ();\n  void mouseDoubleClickEvent (QMouseEvent *event);\n  void mouseMoveEvent (QMouseEvent *event);\n  void mousePressEvent (QMouseEvent *event);\n  void mouseReleaseEvent (QMouseEvent *event);\n  void wheelEvent (QWheelEvent *event);\n  void keyPressEvent (QKeyEvent *event);\n  void keyReleaseEvent (QKeyEvent *event);\n\nprivate:\n\n  Canvas& m_parent_canvas;\n\n  qopengl_functions m_glfcns;\n  opengl_renderer m_renderer;\n\n  QOpenGLContext m_os_context;\n  QOffscreenSurface m_os_surface;\n};\n\nclass GLCanvas : public Canvas\n{\npublic:\n\n  GLCanvas (octave::interpreter& interp, const graphics_handle& handle,\n            QWidget *parent);\n\n  ~GLCanvas ();\n\n  void draw (const graphics_handle& handle);\n  uint8NDArray do_getPixels (const graphics_handle& handle);\n  void do_print (const QString& file_cmd, const QString& term,\n                 const graphics_handle& handle);\n  void drawZoomBox (const QPoint& p1, const QPoint& p2);\n  void resize (int /* x */, int /* y */,\n               int /* width */, int /* height */) { }\n  graphics_object selectFromAxes (const graphics_object& ax,\n                                  const QPoint& pt);\n\n  QWidget * qWidget () { return m_glwidget; }\n\nprivate:\n\n  GLWidget *m_glwidget;\n\n  bool begin_rendering ();\n  void end_rendering ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/GenericEventNotify.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_GenericEventNotify_h)\n#define octave_GenericEventNotify_h 1\n\n#include <QSet>\n\nclass QEvent;\nclass QObject;\nclass QWidget;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass GenericEventNotifyReceiver;\n\nclass GenericEventNotifySender\n{\npublic:\n  GenericEventNotifySender () : m_receivers () { }\n  virtual ~GenericEventNotifySender () = default;\n\n  void addReceiver (GenericEventNotifyReceiver *r)\n  { m_receivers.insert (r); }\n\n  void removeReceiver (GenericEventNotifyReceiver *r)\n  { m_receivers.remove (r); }\n\nprotected:\n  bool notifyReceiversBefore (QObject *obj, QEvent *evt);\n  void notifyReceiversAfter (QObject *obj, QEvent *evt);\n\nprivate:\n  QSet<GenericEventNotifyReceiver *> m_receivers;\n};\n\nclass GenericEventNotifyReceiver\n{\npublic:\n  GenericEventNotifyReceiver () { }\n  virtual ~GenericEventNotifyReceiver () = default;\n\n  virtual bool eventNotifyBefore (QObject *obj, QEvent *evt) = 0;\n  virtual void eventNotifyAfter (QObject *obj, QEvent *evt) = 0;\n};\n\ninline bool\nGenericEventNotifySender::notifyReceiversBefore (QObject *obj, QEvent *evt)\n{\n  for (auto *r : m_receivers)\n    if (r->eventNotifyBefore (obj, evt))\n      return true;\n\n  return false;\n}\n\ninline void\nGenericEventNotifySender::notifyReceiversAfter (QObject *obj, QEvent *evt)\n{\n  for (auto *r : m_receivers)\n    r->eventNotifyAfter (obj, evt);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#define DECLARE_GENERICEVENTNOTIFY_SENDER(T,B) \\\nclass T : public B, public GenericEventNotifySender \\\n{ \\\npublic: \\\n  T (QWidget *xparent) : B (xparent), GenericEventNotifySender () { } \\\n  ~ T () = default; \\\n\\\n  bool event (QEvent *evt) \\\n    { \\\n      bool result = true; \\\n      if (! notifyReceiversBefore (this, evt)) \\\n        result = B::event (evt); \\\n      notifyReceiversAfter (this, evt); \\\n      return result; \\\n    } \\\n}\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/KeyMap.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QMap>\n#include <Qt>\n\n#include \"KeyMap.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nnamespace KeyMap\n{\n  QMap<int, std::string> makeKeyMapper ()\n  {\n    QMap<int, std::string> keyMapper;\n\n    keyMapper[Qt::Key_Escape] = \"escape\";\n    keyMapper[Qt::Key_Tab] = \"tab\";\n    keyMapper[Qt::Key_Backtab] = \"backtab\";\n    keyMapper[Qt::Key_Backspace] = \"backspace\";\n    keyMapper[Qt::Key_Return] = \"return\";\n    keyMapper[Qt::Key_Enter] = \"enter\";\n    keyMapper[Qt::Key_Insert] = \"insert\";\n    keyMapper[Qt::Key_Delete] = \"delete\";\n    keyMapper[Qt::Key_Pause] = \"pause\";\n    keyMapper[Qt::Key_Print] = \"print\";\n    keyMapper[Qt::Key_SysReq] = \"sysreq\";\n    keyMapper[Qt::Key_Clear] = \"clear\";\n    keyMapper[Qt::Key_Home] = \"home\";\n    keyMapper[Qt::Key_End] = \"end\";\n    keyMapper[Qt::Key_Left] = \"left\";\n    keyMapper[Qt::Key_Up] = \"up\";\n    keyMapper[Qt::Key_Right] = \"right\";\n    keyMapper[Qt::Key_Down] = \"down\";\n    keyMapper[Qt::Key_PageUp] = \"pageup\";\n    keyMapper[Qt::Key_PageDown] = \"pagedown\";\n    keyMapper[Qt::Key_Shift] = \"shift\";\n    keyMapper[Qt::Key_Control] = \"control\";\n    keyMapper[Qt::Key_Meta] = \"meta\";\n    keyMapper[Qt::Key_Alt] = \"alt\";\n    keyMapper[Qt::Key_CapsLock] = \"capslock\";\n    keyMapper[Qt::Key_NumLock] = \"numlock\";\n    keyMapper[Qt::Key_ScrollLock] = \"scrolllock\";\n    keyMapper[Qt::Key_F1] = \"f1\";\n    keyMapper[Qt::Key_F2] = \"f2\";\n    keyMapper[Qt::Key_F3] = \"f3\";\n    keyMapper[Qt::Key_F4] = \"f4\";\n    keyMapper[Qt::Key_F5] = \"f5\";\n    keyMapper[Qt::Key_F6] = \"f6\";\n    keyMapper[Qt::Key_F7] = \"f7\";\n    keyMapper[Qt::Key_F8] = \"f8\";\n    keyMapper[Qt::Key_F9] = \"f9\";\n    keyMapper[Qt::Key_F10] = \"f10\";\n    keyMapper[Qt::Key_F11] = \"f11\";\n    keyMapper[Qt::Key_F12] = \"f12\";\n    keyMapper[Qt::Key_F13] = \"f13\";\n    keyMapper[Qt::Key_F14] = \"f14\";\n    keyMapper[Qt::Key_F15] = \"f15\";\n    keyMapper[Qt::Key_F16] = \"f16\";\n    keyMapper[Qt::Key_F17] = \"f17\";\n    keyMapper[Qt::Key_F18] = \"f18\";\n    keyMapper[Qt::Key_F19] = \"f19\";\n    keyMapper[Qt::Key_F20] = \"f20\";\n    keyMapper[Qt::Key_F21] = \"f21\";\n    keyMapper[Qt::Key_F22] = \"f22\";\n    keyMapper[Qt::Key_F23] = \"f23\";\n    keyMapper[Qt::Key_F24] = \"f24\";\n    keyMapper[Qt::Key_F25] = \"f25\";\n    keyMapper[Qt::Key_F26] = \"f26\";\n    keyMapper[Qt::Key_F27] = \"f27\";\n    keyMapper[Qt::Key_F28] = \"f28\";\n    keyMapper[Qt::Key_F29] = \"f29\";\n    keyMapper[Qt::Key_F30] = \"f30\";\n    keyMapper[Qt::Key_F31] = \"f31\";\n    keyMapper[Qt::Key_F32] = \"f32\";\n    keyMapper[Qt::Key_F33] = \"f33\";\n    keyMapper[Qt::Key_F34] = \"f34\";\n    keyMapper[Qt::Key_F35] = \"f35\";\n    keyMapper[Qt::Key_Super_L] = \"super_l\";\n    keyMapper[Qt::Key_Super_R] = \"super_r\";\n    keyMapper[Qt::Key_Menu] = \"menu\";\n    keyMapper[Qt::Key_Hyper_L] = \"hyper_l\";\n    keyMapper[Qt::Key_Hyper_R] = \"hyper_r\";\n    keyMapper[Qt::Key_Help] = \"help\";\n    keyMapper[Qt::Key_Direction_L] = \"direction_l\";\n    keyMapper[Qt::Key_Direction_R] = \"direction_r\";\n    keyMapper[Qt::Key_Space] = \"space\";\n    keyMapper[Qt::Key_Exclam] = \"exclam\";\n    keyMapper[Qt::Key_QuoteDbl] = \"quotedbl\";\n    keyMapper[Qt::Key_NumberSign] = \"numbersign\";\n    keyMapper[Qt::Key_Dollar] = \"dollar\";\n    keyMapper[Qt::Key_Percent] = \"percent\";\n    keyMapper[Qt::Key_Ampersand] = \"ampersand\";\n    keyMapper[Qt::Key_Apostrophe] = \"apostrophe\";\n    keyMapper[Qt::Key_ParenLeft] = \"parenleft\";\n    keyMapper[Qt::Key_ParenRight] = \"parenright\";\n    keyMapper[Qt::Key_Asterisk] = \"asterisk\";\n    keyMapper[Qt::Key_Plus] = \"plus\";\n    keyMapper[Qt::Key_Comma] = \"comma\";\n    keyMapper[Qt::Key_Minus] = \"minus\";\n    keyMapper[Qt::Key_Period] = \"period\";\n    keyMapper[Qt::Key_Slash] = \"slash\";\n    keyMapper[Qt::Key_0] = \"0\";\n    keyMapper[Qt::Key_1] = \"1\";\n    keyMapper[Qt::Key_2] = \"2\";\n    keyMapper[Qt::Key_3] = \"3\";\n    keyMapper[Qt::Key_4] = \"4\";\n    keyMapper[Qt::Key_5] = \"5\";\n    keyMapper[Qt::Key_6] = \"6\";\n    keyMapper[Qt::Key_7] = \"7\";\n    keyMapper[Qt::Key_8] = \"8\";\n    keyMapper[Qt::Key_9] = \"9\";\n    keyMapper[Qt::Key_Colon] = \"colon\";\n    keyMapper[Qt::Key_Semicolon] = \"semicolon\";\n    keyMapper[Qt::Key_Less] = \"less\";\n    keyMapper[Qt::Key_Equal] = \"equal\";\n    keyMapper[Qt::Key_Greater] = \"greater\";\n    keyMapper[Qt::Key_Question] = \"question\";\n    keyMapper[Qt::Key_At] = \"at\";\n    keyMapper[Qt::Key_A] = \"a\";\n    keyMapper[Qt::Key_B] = \"b\";\n    keyMapper[Qt::Key_C] = \"c\";\n    keyMapper[Qt::Key_D] = \"d\";\n    keyMapper[Qt::Key_E] = \"e\";\n    keyMapper[Qt::Key_F] = \"f\";\n    keyMapper[Qt::Key_G] = \"g\";\n    keyMapper[Qt::Key_H] = \"h\";\n    keyMapper[Qt::Key_I] = \"i\";\n    keyMapper[Qt::Key_J] = \"j\";\n    keyMapper[Qt::Key_K] = \"k\";\n    keyMapper[Qt::Key_L] = \"l\";\n    keyMapper[Qt::Key_M] = \"m\";\n    keyMapper[Qt::Key_N] = \"n\";\n    keyMapper[Qt::Key_O] = \"o\";\n    keyMapper[Qt::Key_P] = \"p\";\n    keyMapper[Qt::Key_Q] = \"q\";\n    keyMapper[Qt::Key_R] = \"r\";\n    keyMapper[Qt::Key_S] = \"s\";\n    keyMapper[Qt::Key_T] = \"t\";\n    keyMapper[Qt::Key_U] = \"u\";\n    keyMapper[Qt::Key_V] = \"v\";\n    keyMapper[Qt::Key_W] = \"w\";\n    keyMapper[Qt::Key_X] = \"x\";\n    keyMapper[Qt::Key_Y] = \"y\";\n    keyMapper[Qt::Key_Z] = \"z\";\n    keyMapper[Qt::Key_BracketLeft] = \"bracketleft\";\n    keyMapper[Qt::Key_Backslash] = \"backslash\";\n    keyMapper[Qt::Key_BracketRight] = \"bracketright\";\n    keyMapper[Qt::Key_AsciiCircum] = \"asciicircum\";\n    keyMapper[Qt::Key_Underscore] = \"underscore\";\n    keyMapper[Qt::Key_QuoteLeft] = \"quoteleft\";\n    keyMapper[Qt::Key_BraceLeft] = \"braceleft\";\n    keyMapper[Qt::Key_Bar] = \"bar\";\n    keyMapper[Qt::Key_BraceRight] = \"braceright\";\n    keyMapper[Qt::Key_AsciiTilde] = \"asciitilde\";\n\n    keyMapper[Qt::Key_nobreakspace] = \"nobreakspace\";\n    keyMapper[Qt::Key_exclamdown] = \"exclamdown\";\n    keyMapper[Qt::Key_cent] = \"cent\";\n    keyMapper[Qt::Key_sterling] = \"sterling\";\n    keyMapper[Qt::Key_currency] = \"currency\";\n    keyMapper[Qt::Key_yen] = \"yen\";\n    keyMapper[Qt::Key_brokenbar] = \"brokenbar\";\n    keyMapper[Qt::Key_section] = \"section\";\n    keyMapper[Qt::Key_diaeresis] = \"diaeresis\";\n    keyMapper[Qt::Key_copyright] = \"copyright\";\n    keyMapper[Qt::Key_ordfeminine] = \"ordfeminine\";\n    keyMapper[Qt::Key_guillemotleft] = \"guillemotleft\";\n    keyMapper[Qt::Key_notsign] = \"notsign\";\n    keyMapper[Qt::Key_hyphen] = \"hyphen\";\n    keyMapper[Qt::Key_registered] = \"registered\";\n    keyMapper[Qt::Key_macron] = \"macron\";\n    keyMapper[Qt::Key_degree] = \"degree\";\n    keyMapper[Qt::Key_plusminus] = \"plusminus\";\n    keyMapper[Qt::Key_twosuperior] = \"twosuperior\";\n    keyMapper[Qt::Key_threesuperior] = \"threesuperior\";\n    keyMapper[Qt::Key_acute] = \"acute\";\n    // FIXME: Should the following value be changed to \"micro\"?  The string is,\n    //        e.g., used as the value of the field \"Key\" that is passed to the\n    //        \"KeyPressFcn\" callback.\n#if defined (HAVE_QT_KEY_MICRO)\n    keyMapper[Qt::Key_micro] = \"mu\";\n#else\n    keyMapper[Qt::Key_mu] = \"mu\";\n#endif\n    keyMapper[Qt::Key_paragraph] = \"paragraph\";\n    keyMapper[Qt::Key_periodcentered] = \"periodcentered\";\n    keyMapper[Qt::Key_cedilla] = \"cedilla\";\n    keyMapper[Qt::Key_onesuperior] = \"onesuperior\";\n    keyMapper[Qt::Key_masculine] = \"masculine\";\n    keyMapper[Qt::Key_guillemotright] = \"guillemotright\";\n    keyMapper[Qt::Key_onequarter] = \"onequarter\";\n    keyMapper[Qt::Key_onehalf] = \"onehalf\";\n    keyMapper[Qt::Key_threequarters] = \"threequarters\";\n    keyMapper[Qt::Key_questiondown] = \"questiondown\";\n    keyMapper[Qt::Key_Agrave] = \"agrave\";\n    keyMapper[Qt::Key_Aacute] = \"aacute\";\n    keyMapper[Qt::Key_Acircumflex] = \"acircumflex\";\n    keyMapper[Qt::Key_Atilde] = \"atilde\";\n    keyMapper[Qt::Key_Adiaeresis] = \"adiaeresis\";\n    keyMapper[Qt::Key_Aring] = \"aring\";\n    keyMapper[Qt::Key_AE] = \"ae\";\n    keyMapper[Qt::Key_Ccedilla] = \"ccedilla\";\n    keyMapper[Qt::Key_Egrave] = \"egrave\";\n    keyMapper[Qt::Key_Eacute] = \"eacute\";\n    keyMapper[Qt::Key_Ecircumflex] = \"ecircumflex\";\n    keyMapper[Qt::Key_Ediaeresis] = \"ediaeresis\";\n    keyMapper[Qt::Key_Igrave] = \"igrave\";\n    keyMapper[Qt::Key_Iacute] = \"iacute\";\n    keyMapper[Qt::Key_Icircumflex] = \"icircumflex\";\n    keyMapper[Qt::Key_Idiaeresis] = \"idiaeresis\";\n    keyMapper[Qt::Key_ETH] = \"eth\";\n    keyMapper[Qt::Key_Ntilde] = \"ntilde\";\n    keyMapper[Qt::Key_Ograve] = \"ograve\";\n    keyMapper[Qt::Key_Oacute] = \"oacute\";\n    keyMapper[Qt::Key_Ocircumflex] = \"ocircumflex\";\n    keyMapper[Qt::Key_Otilde] = \"otilde\";\n    keyMapper[Qt::Key_Odiaeresis] = \"odiaeresis\";\n    keyMapper[Qt::Key_multiply] = \"multiply\";\n    keyMapper[Qt::Key_Ooblique] = \"ooblique\";\n    keyMapper[Qt::Key_Ugrave] = \"ugrave\";\n    keyMapper[Qt::Key_Uacute] = \"uacute\";\n    keyMapper[Qt::Key_Ucircumflex] = \"ucircumflex\";\n    keyMapper[Qt::Key_Udiaeresis] = \"udiaeresis\";\n    keyMapper[Qt::Key_Yacute] = \"yacute\";\n    keyMapper[Qt::Key_THORN] = \"thorn\";\n    keyMapper[Qt::Key_ssharp] = \"ssharp\";\n    keyMapper[Qt::Key_division] = \"division\";\n    keyMapper[Qt::Key_ydiaeresis] = \"ydiaeresis\";\n\n    return keyMapper;\n  }\n\n  std::string\n  qKeyToKeyString (int key)\n  {\n    static const QMap<int, std::string> keyMapper = makeKeyMapper ();\n\n    return keyMapper.value (key, \"<unknown key>\");\n  }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/KeyMap.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_KeyMap_h)\n#define octave_KeyMap_h 1\n\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nnamespace KeyMap\n{\n  std::string qKeyToKeyString (int key);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/ListBoxControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QListWidget>\n#include <QEvent>\n#include <QMouseEvent>\n\n#include \"Container.h\"\n#include \"ListBoxControl.h\"\n#include \"QtHandlesUtils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic void\nupdateSelection (QListWidget *list, const Matrix& value)\n{\n  octave_idx_type n = value.numel ();\n  int lc = list->count ();\n\n  list->clearSelection ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      int idx = octave::math::round (value(i));\n\n      if (1 <= idx && idx <= lc)\n        {\n          list->item (idx-1)->setSelected (true);\n          list->scrollToItem (list->item (idx-1));\n          if (i == 0\n              && list->selectionMode () == QAbstractItemView::SingleSelection)\n            break;\n        }\n      else\n        {\n          // Invalid selection.\n          list->clearSelection ();\n          break;\n        }\n    }\n}\n\nListBoxControl *\nListBoxControl::create (octave::interpreter& interp,\n                        const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new ListBoxControl (interp, go,\n                                   new QListWidget (container));\n    }\n\n  return nullptr;\n}\n\nListBoxControl::ListBoxControl (octave::interpreter& interp,\n                                const graphics_object& go, QListWidget *list)\n  : BaseControl (interp, go, list), m_blockCallback (false),\n    m_selectionChanged (false)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  list->addItems (Utils::fromStringVector (up.get_string_vector ()));\n  if ((up.get_max () - up.get_min ()) > 1)\n    list->setSelectionMode (QAbstractItemView::ExtendedSelection);\n  else\n    list->setSelectionMode (QAbstractItemView::SingleSelection);\n  Matrix value = up.get_value ().matrix_value ();\n  if (value.numel () > 0)\n    {\n      octave_idx_type n = value.numel ();\n      int lc = list->count ();\n\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          int idx = octave::math::round (value(i));\n\n          if (1 <= idx && idx <= lc)\n            {\n              list->item (idx-1)->setSelected (true);\n              list->scrollToItem (list->item (idx-1));\n              if (i == 0 && (list->selectionMode ()\n                             == QAbstractItemView::SingleSelection))\n                break;\n            }\n        }\n    }\n\n  list->viewport ()->installEventFilter (this);\n\n  connect (list, &QListWidget::itemSelectionChanged,\n           this, &ListBoxControl::itemSelectionChanged);\n  connect (list, &QListWidget::activated,\n           this, &ListBoxControl::itemActivated);\n  connect (list, &QListWidget::itemPressed,\n           this, &ListBoxControl::itemPressed);\n}\n\nListBoxControl::~ListBoxControl ()\n{ }\n\nvoid\nListBoxControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QListWidget *list = qWidget<QListWidget> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_STRING:\n      m_blockCallback = true;\n      list->clear ();\n      list->addItems (Utils::fromStringVector (up.get_string_vector ()));\n      updateSelection (list, up.get_value ().matrix_value ());\n      m_blockCallback = false;\n      break;\n\n    case uicontrol::properties::ID_MIN:\n    case uicontrol::properties::ID_MAX:\n      if ((up.get_max () - up.get_min ()) > 1)\n        list->setSelectionMode (QAbstractItemView::ExtendedSelection);\n      else\n        list->setSelectionMode (QAbstractItemView::SingleSelection);\n      break;\n\n    case uicontrol::properties::ID_LISTBOXTOP:\n      {\n        int idx = octave::math::fix (up.get_listboxtop ());\n        if (idx > 0)\n          list->scrollToItem (list->item (idx-1),\n                              QAbstractItemView::PositionAtTop);\n        break;\n      }\n\n    case uicontrol::properties::ID_VALUE:\n      m_blockCallback = true;\n      updateSelection (list, up.get_value ().matrix_value ());\n      m_blockCallback = false;\n      break;\n\n    default:\n      BaseControl::update (pId);\n      break;\n    }\n}\n\nvoid\nListBoxControl::sendSelectionChange ()\n{\n  if (! m_blockCallback)\n    {\n      QListWidget *list = qWidget<QListWidget> ();\n\n      QModelIndexList l = list->selectionModel ()->selectedIndexes ();\n      Matrix value (dim_vector (1, l.size ()));\n      int i = 0;\n\n      for (const auto& idx : l)\n        value(i++) = idx.row () + 1;\n\n      Q_EMIT gh_set_event (m_handle, \"value\", octave_value (value), false);\n      Q_EMIT gh_callback_event (m_handle, \"callback\");\n    }\n\n  m_selectionChanged = false;\n}\n\nvoid\nListBoxControl::itemSelectionChanged ()\n{\n  if (! m_blockCallback)\n    m_selectionChanged = true;\n}\n\nvoid\nListBoxControl::itemActivated (const QModelIndex&)\n{\n  m_selectionChanged = true;\n}\nvoid\nListBoxControl::itemPressed (QListWidgetItem *)\n{\n  m_selectionChanged = true;\n}\n\nbool\nListBoxControl::eventFilter (QObject *watched, QEvent *e)\n{\n  // listbox change\n  if (watched == m_qobject)\n    {\n      switch (e->type ())\n        {\n        case QEvent::KeyRelease:\n          if (m_selectionChanged)\n            sendSelectionChange ();\n          m_selectionChanged = false;\n          break;\n\n        default:\n          break;\n        }\n\n      return Object::eventFilter (watched, e);\n    }\n  // listbox viewport\n  else\n    {\n      bool override_return = false;\n      QListWidget *list = qWidget<QListWidget> ();\n\n      switch (e->type ())\n        {\n        case QEvent::MouseButtonPress:\n          {\n            QMouseEvent *m = dynamic_cast<QMouseEvent *> (e);\n\n            if (m->button () & Qt::RightButton)\n              override_return = true;\n            else\n              {\n                if (! list->indexAt (m->pos ()).isValid ())\n                  override_return = true;\n                m_selectionChanged = true;\n              }\n            break;\n          }\n        case QEvent::MouseButtonRelease:\n          {\n            QMouseEvent *m = dynamic_cast<QMouseEvent *> (e);\n\n            if (m->button () & Qt::RightButton)\n              override_return = true;\n\n            else if (! list->indexAt (m->pos ()).isValid ())\n              {\n                list->setCurrentRow (list->count () - 1);\n                override_return = true;\n              }\n\n            if (m_selectionChanged)\n              sendSelectionChange ();\n            m_selectionChanged = false;\n\n            break;\n          }\n        default:\n          break;\n\n        }\n      return BaseControl::eventFilter (watched, e) || override_return;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/ListBoxControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ListBoxControl_h)\n#define octave_ListBoxControl_h 1\n\n#include \"BaseControl.h\"\n\nclass QListWidget;\nclass QListWidgetItem;\nclass QModelIndex;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass ListBoxControl : public BaseControl\n{\n  Q_OBJECT\n\npublic:\n  ListBoxControl (octave::interpreter& interp, const graphics_object& go,\n                  QListWidget *list);\n  ~ListBoxControl ();\n\n  static ListBoxControl *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n  bool eventFilter (QObject *watched, QEvent *e);\n  void sendSelectionChange ();\n\nprivate Q_SLOTS:\n  void itemSelectionChanged ();\n  void itemActivated (const QModelIndex&);\n  void itemPressed (QListWidgetItem *);\n\nprivate:\n  bool m_blockCallback;\n  bool m_selectionChanged;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/Logger.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdio>\n\n#include <QMutex>\n#include <QMutexLocker>\n#include <QProcessEnvironment>\n\n#include \"Logger.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nLogger *Logger::s_instance = nullptr;\nQMutex *Logger::s_mutex = nullptr;\n\nLogger::Logger ()\n  : m_debugEnabled (false)\n{\n  QProcessEnvironment pe (QProcessEnvironment::systemEnvironment ());\n\n  if (pe.value (\"OCTAVE_QTHANDLES_DEBUG\", \"0\") != \"0\")\n    m_debugEnabled = true;\n\n  // FIXME: Deprecated, remove in Octave 13.\n  if (pe.value (\"QTHANDLES_DEBUG\", \"0\") != \"0\")\n    {\n      m_debugEnabled = true;\n\n      static bool warned = false;\n      if (! warned)\n        {\n          qWarning (\"The environment variable QTHANDLES_DEBUG is deprecated and will be removed from a future version of Octave, please use OCTAVE_QTHANDLES_DEBUG instead\\n\");\n          warned = true;\n        }\n    }\n}\n\nLogger::~Logger ()\n{ }\n\nLogger *\nLogger::instance ()\n{\n  if (! s_instance)\n    {\n      s_instance = new Logger ();\n      s_mutex = new QMutex ();\n    }\n\n  return s_instance;\n}\n\n#define STATIC_LOGGER(fcn)                      \\\n  void Logger::fcn (const char *fmt, ...)       \\\n  {                                             \\\n    QMutexLocker lock (s_mutex);                \\\n    va_list vl;                                 \\\n    va_start (vl, fmt);                         \\\n    instance ()->fcn ## V (fmt, vl);            \\\n    va_end (vl);                                \\\n  }\n\nSTATIC_LOGGER (debug)\n\nvoid\nLogger::debugV (const char *fmt, va_list arg)\n{\n  if (m_debugEnabled)\n    {\n      vfprintf (stderr, fmt, arg);\n      fprintf (stderr, \"\\n\");\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/Logger.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Logger_h)\n#define octave_Logger_h 1\n\n#include <cstdarg>\n\nclass QMutex;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass Logger\n{\npublic:\n  static void debug (const char *fmt, ...);\n\nprivate:\n  bool m_debugEnabled;\n\n  static Logger *s_instance;\n  static QMutex *s_mutex;\n\nprivate:\n  Logger ();\n  ~Logger ();\n\n  static Logger * instance ();\n\n  void debugV (const char *fmt, va_list arg);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/Menu.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QAction>\n#include <QMainWindow>\n#include <QMenu>\n#include <QMenuBar>\n\n#include \"Figure.h\"\n#include \"Menu.h\"\n#include \"QtHandlesUtils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic QKeySequence\naccelSequence (const uimenu::properties& up)\n{\n  std::string s (up.get_accelerator ());\n\n  if (! s.empty ())\n    {\n      char c = s[0];\n      int keyMod = Qt::CTRL;\n\n      if (c >= 'A' && c <= 'Z')\n        keyMod |= Qt::SHIFT;\n      if (c >= 'a' && c <= 'z')\n        c -= ('a' - 'A');\n      if (c >= 'A' && c <= 'Z')\n        return QKeySequence (keyMod | static_cast<int> (c));\n    }\n\n  return QKeySequence ();\n}\n\nMenu *\nMenu::create (octave::interpreter& interp,\n              const graphics_object& go)\n{\n  Object *parent_obj = parentObject (interp, go);\n\n  if (parent_obj)\n    {\n      QObject *qObj = parent_obj->qObject ();\n\n      if (qObj)\n        return new Menu (interp, go, new QAction (qObj),\n                         parent_obj);\n    }\n\n  return nullptr;\n}\n\nMenu::Menu (octave::interpreter& interp,\n            const graphics_object& go, QAction *action, Object *xparent)\n  : Object (interp, go, action), m_parent (nullptr),\n    m_separator (nullptr)\n{\n  uimenu::properties& up = properties<uimenu> ();\n\n  action->setText (Utils::fromStdString (up.get_text ()));\n\n  if (up.is_checked ())\n    {\n      action->setCheckable (true);\n      action->setChecked (up.is_checked ());\n    }\n\n  action->setEnabled (up.is_enable ());\n  action->setShortcut (accelSequence (up));\n  action->setVisible (up.is_visible ());\n\n  if (up.is_separator ())\n    {\n      m_separator = new QAction (action);\n      m_separator->setSeparator (true);\n      m_separator->setVisible (up.is_visible ());\n    }\n\n  MenuContainer *menuContainer = dynamic_cast<MenuContainer *> (xparent);\n\n  if (menuContainer)\n    m_parent = menuContainer->menu ();\n\n  if (m_parent)\n    {\n      int pos = static_cast<int> (up.get_position ());\n\n      if (pos <= 0)\n        {\n          if (m_separator)\n            m_parent->insertAction (nullptr, m_separator);\n          m_parent->insertAction (nullptr, action);\n\n          int count = 0;\n\n          for (auto *a : m_parent->actions ())\n            if (! a->isSeparator ())\n              count++;\n\n          up.get_property (\"position\").set\n          (octave_value (static_cast<double> (count)), true, false);\n        }\n      else\n        {\n\n          int count = 0;\n          QAction *before = nullptr;\n\n          for (auto *a : m_parent->actions ())\n            {\n              if (! a->isSeparator ())\n                {\n                  count++;\n                  if (pos <= count)\n                    {\n                      before = a;\n                      break;\n                    }\n                }\n            }\n\n          if (m_separator)\n            m_parent->insertAction (before, m_separator);\n          m_parent->insertAction (before, action);\n\n          if (before)\n            updateSiblingPositions ();\n          else\n            up.get_property (\"position\").set\n            (octave_value (static_cast<double> (count+1)), true, false);\n        }\n    }\n\n  connect (action, &QAction::triggered, this, &Menu::actionTriggered);\n}\n\nMenu::~Menu ()\n{ }\n\nvoid\nMenu::update (int pId)\n{\n  uimenu::properties& up = properties<uimenu> ();\n  QAction *action = qWidget<QAction> ();\n\n  switch (pId)\n    {\n    case uimenu::properties::ID_TEXT:\n      action->setText (Utils::fromStdString (up.get_text ()));\n      break;\n\n    case uimenu::properties::ID_CHECKED:\n      if (up.is_checked ())\n        {\n          action->setCheckable (true);\n          action->setChecked (up.is_checked ());\n        }\n      else\n        {\n          action->setChecked (false);\n          action->setCheckable (false);\n        }\n      break;\n\n    case uimenu::properties::ID_ENABLE:\n      action->setEnabled (up.is_enable ());\n      break;\n\n    case uimenu::properties::ID_ACCELERATOR:\n      if (! action->menu ())\n        action->setShortcut (accelSequence (up));\n      break;\n\n    case uimenu::properties::ID_SEPARATOR:\n      if (up.is_separator ())\n        {\n          if (! m_separator)\n            {\n              m_separator = new QAction (action);\n              m_separator->setSeparator (true);\n              m_separator->setVisible (up.is_visible ());\n              if (m_parent)\n                m_parent->insertAction (action, m_separator);\n            }\n        }\n      else\n        {\n          if (m_separator)\n            delete m_separator;\n          m_separator = nullptr;\n        }\n      break;\n\n    case uimenu::properties::ID_VISIBLE:\n      action->setVisible (up.is_visible ());\n      if (m_separator)\n        m_separator->setVisible (up.is_visible ());\n      break;\n\n    case uimenu::properties::ID_POSITION:\n      {\n        if (m_separator)\n          m_parent->removeAction (m_separator);\n\n        m_parent->removeAction (action);\n\n        int pos = static_cast<int> (up.get_position ());\n        QAction *before = nullptr;\n\n        if (pos > 0)\n          {\n            int count = 0;\n\n            for (auto *a : m_parent->actions ())\n              {\n                if (! a->isSeparator ())\n                  {\n                    count++;\n                    if (pos <= count)\n                      {\n                        before = a;\n                        break;\n                      }\n                  }\n              }\n          }\n\n        if (m_separator)\n          m_parent->insertAction (before, m_separator);\n\n        m_parent->insertAction (before, action);\n\n        updateSiblingPositions ();\n      }\n      break;\n\n    default:\n      Object::update (pId);\n      break;\n    }\n}\n\nQWidget *\nMenu::menu ()\n{\n  QAction *action = qWidget<QAction> ();\n  QMenu *action_menu = action->menu ();\n\n  if (! action_menu)\n    {\n      action_menu = new QMenu (qobject_cast<QWidget *> (action->parent ()));\n      action->setMenu (action_menu);\n      action->setShortcut (QKeySequence ());\n      connect (action_menu, &QMenu::aboutToShow, this, &Menu::actionHovered);\n    }\n\n  return action_menu;\n}\n\nvoid\nMenu::actionTriggered ()\n{\n  QAction *action = qWidget<QAction> ();\n\n  if (action->isCheckable ())\n    action->setChecked (! action->isChecked ());\n  Q_EMIT gh_callback_event (m_handle, \"menuselectedfcn\");\n}\n\nvoid\nMenu::actionHovered ()\n{\n  Q_EMIT gh_callback_event (m_handle, \"menuselectedfcn\");\n}\n\nvoid\nMenu::updateSiblingPositions ()\n{\n  if (m_parent)\n    {\n      double count = 1.0;\n\n      for (auto *a : m_parent->actions ())\n        {\n          if (! a->isSeparator ())\n            {\n              Object *aObj = Object::fromQObject (a);\n\n              if (aObj)\n                {\n                  graphics_object go = aObj->object ();\n\n                  // Probably overkill as a uimenu child can only be another\n                  // uimenu object.\n                  if (go.isa (\"uimenu\"))\n                    {\n                      uimenu::properties& up = Utils::properties<uimenu> (go);\n\n                      up.get_property (\"position\").set\n                      (octave_value (count), true, false);\n                    }\n                }\n\n              count++;\n            }\n        }\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/Menu.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Menu_h)\n#define octave_Menu_h 1\n\n#include \"MenuContainer.h\"\n#include \"Object.h\"\n\nclass QAction;\nclass QMenu;\nclass QWidget;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass Menu : public Object, public MenuContainer\n{\n  Q_OBJECT\n\npublic:\n  Menu (octave::interpreter& interp,\n        const graphics_object& go, QAction *action, Object *parent);\n  ~Menu ();\n\n  static Menu *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\n  Container * innerContainer () { return nullptr; }\n\n  QWidget * menu ();\n\nprotected:\n  void update (int pId);\n\nprivate Q_SLOTS:\n  void actionTriggered ();\n  void actionHovered ();\n\nprivate:\n  void updateSiblingPositions ();\n\nprivate:\n  QWidget *m_parent;\n  QAction *m_separator;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/MenuContainer.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_MenuContainer_h)\n#define octave_MenuContainer_h 1\n\nclass QWidget;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass MenuContainer\n{\npublic:\n  virtual QWidget * menu () = 0;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/Object.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QString>\n#include <QVariant>\n\n#include \"Object.h\"\n#include \"QtHandlesUtils.h\"\n#include \"qt-graphics-toolkit.h\"\n\n#include \"graphics.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nObject::Object (octave::interpreter& interp,\n                const graphics_object& go, QObject *obj)\n  : QObject (), m_interpreter (interp), m_go (go),\n    m_handle (go.get_handle ()), m_qobject (nullptr)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (! guard)\n    qCritical (\"octave::Object::Object: \"\n               \"creating Object (h=%g) without a valid lock!!!\",\n               m_handle.value ());\n\n  init (obj);\n}\n\nvoid\nObject::init (QObject *obj, bool)\n{\n  if (m_qobject)\n    qCritical (\"octave::Object::init: \"\n               \"resetting QObject while in invalid state\");\n\n  m_qobject = obj;\n\n  if (m_qobject)\n    {\n      m_qobject->setProperty (\"octave::Object\",\n                              QVariant::fromValue<void *> (this));\n      connect (m_qobject, &QObject::destroyed,\n               this, &Object::objectDestroyed);\n    }\n}\n\nObject::~Object ()\n{ }\n\ngraphics_object\nObject::object () const\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock (), false);\n\n  if (! guard)\n    qCritical (\"octave::Object::object: \"\n               \"accessing graphics object (h=%g) without a valid lock!!!\",\n               m_handle.value ());\n\n  return m_go;\n}\n\nvoid\nObject::slotUpdate (int pId)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  switch (pId)\n    {\n    // Special case for objects being deleted, as it's very likely\n    // that the graphics_object already has been destroyed when this\n    // is executed (because of the async behavior).\n    case base_properties::ID_BEINGDELETED:\n      beingDeleted ();\n      break;\n\n    default:\n      if (object ().valid_object ())\n        update (pId);\n      break;\n    }\n}\n\nvoid\nObject::slotFinalize ()\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  finalize ();\n}\n\nvoid\nObject::slotRedraw ()\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (object ().valid_object ())\n    redraw ();\n}\n\nvoid\nObject::slotShow ()\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (object ().valid_object ())\n    show ();\n}\n\nvoid\nObject::slotPrint (const QString& file_cmd, const QString& term)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (object ().valid_object ())\n    print (file_cmd, term);\n}\n\nvoid\nObject::update (int /* pId */)\n{ }\n\nvoid\nObject::finalize ()\n{\n  if (m_qobject)\n    {\n      delete m_qobject;\n      m_qobject = nullptr;\n    }\n  deleteLater ();\n}\n\nvoid\nObject::redraw ()\n{ }\n\nvoid\nObject::show ()\n{ }\n\nvoid\nObject::print (const QString& /* file_cmd */, const QString& /* term */)\n{ }\n\nvoid\nObject::beingDeleted ()\n{ }\n\nvoid\nObject::objectDestroyed (QObject *obj)\n{\n  if (obj && obj == m_qobject)\n    m_qobject = nullptr;\n}\n\nObject *\nObject::parentObject (octave::interpreter& interp, const graphics_object& go)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  Object *parent = qt_graphics_toolkit::toolkitObject\n                   (gh_mgr.get_object (go.get_parent ()));\n\n  return parent;\n}\n\nObject *\nObject::fromQObject (QObject *obj)\n{\n  QVariant v = obj->property (\"octave::Object\");\n\n  if (v.isValid ())\n    return reinterpret_cast<Object *> (qvariant_cast<void *> (v));\n\n  return nullptr;\n}\n\nvoid\nObject::do_connections (const QObject *receiver, const QObject *emitter)\n{\n  if (! emitter)\n    emitter = this;\n\n  connect (emitter,\n           SIGNAL (interpreter_event (const octave::fcn_callback&)),\n           receiver,\n           SLOT (interpreter_event (const octave::fcn_callback&)));\n\n  connect (emitter,\n           SIGNAL (interpreter_event (const octave::meth_callback&)),\n           receiver,\n           SLOT (interpreter_event (const octave::meth_callback&)));\n\n  connect (emitter,\n           SIGNAL (gh_callback_event (const graphics_handle&,\n                                      const std::string&)),\n           receiver,\n           SLOT (gh_callback_event (const graphics_handle&,\n                                    const std::string&)));\n\n  connect (emitter,\n           SIGNAL (gh_callback_event (const graphics_handle&,\n                                      const std::string&,\n                                      const octave_value&)),\n           receiver,\n           SLOT (gh_callback_event (const graphics_handle&,\n                                    const std::string&,\n                                    const octave_value&)));\n\n  connect (emitter,\n           SIGNAL (gh_set_event (const graphics_handle&,\n                                 const std::string&,\n                                 const octave_value&)),\n           receiver,\n           SLOT (gh_set_event (const graphics_handle&,\n                               const std::string&,\n                               const octave_value&)));\n\n  connect (emitter,\n           SIGNAL (gh_set_event (const graphics_handle&,\n                                 const std::string&,\n                                 const octave_value&, bool)),\n           receiver,\n           SLOT (gh_set_event (const graphics_handle&,\n                               const std::string&,\n                               const octave_value&, bool)));\n\n  connect (emitter,\n           SIGNAL (gh_set_event (const graphics_handle&,\n                                 const std::string&,\n                                 const octave_value&,\n                                 bool, bool)),\n           receiver,\n           SLOT (gh_set_event (const graphics_handle&,\n                               const std::string&,\n                               const octave_value&,\n                               bool, bool)));\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/Object.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Object_h)\n#define octave_Object_h 1\n\n#include <QObject>\n\n#include \"event-manager.h\"\n#include \"graphics.h\"\n\nclass QObject;\nclass QString;\nclass QWidget;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass Container;\nclass ObjectProxy;\n\nclass Object : public QObject\n{\n  Q_OBJECT\n\npublic:\n  Object (octave::interpreter& interp, const graphics_object& go,\n          QObject *obj = nullptr);\n\n  virtual ~Object ();\n\n  base_properties& properties ()\n  { return object ().get_properties (); }\n\n  const base_properties& properties () const\n  { return object ().get_properties (); }\n\n  template <typename T>\n  typename T::properties& properties ()\n  {\n    return dynamic_cast<typename T::properties&>\n           (object ().get_properties ());\n  }\n\n  template <typename T>\n  const typename T::properties& properties () const\n  {\n    return dynamic_cast<const typename T::properties&>\n           (object ().get_properties ());\n  }\n\n  graphics_object object () const;\n\n  virtual QObject * qObject () { return m_qobject; }\n\n  template <typename T>\n  T * qWidget () { return qobject_cast<T *>(qObject ()); }\n\n  virtual Container * innerContainer () = 0;\n\n  static Object * fromQObject (QObject *obj);\n\n  virtual void do_connections (const QObject *receiver,\n                               const QObject *emitter = nullptr);\n\nQ_SIGNALS:\n\n  void interpreter_event (const octave::fcn_callback& fcn);\n  void interpreter_event (const octave::meth_callback& meth);\n\n  void gh_callback_event (const graphics_handle& h, const std::string& name);\n\n  void gh_callback_event (const graphics_handle& h, const std::string& name,\n                          const octave_value& data);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value, bool notify_toolkit);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value, bool notify_toolkit,\n                     bool redraw_figure);\n\npublic Q_SLOTS:\n  void slotUpdate (int pId);\n  void slotFinalize ();\n  void slotRedraw ();\n  void slotShow ();\n  void slotPrint (const QString& file_cmd, const QString& term);\n\n  void objectDestroyed (QObject *obj = nullptr);\n\nprotected:\n  static Object *\n  parentObject (octave::interpreter& interp, const graphics_object& go);\n\n  void init (QObject *obj, bool callBase = false);\n\n  virtual void update (int pId);\n  virtual void finalize ();\n  virtual void redraw ();\n  virtual void show ();\n  virtual void print (const QString& file_cmd, const QString& term);\n\n  virtual void beingDeleted ();\n\nprotected:\n\n  octave::interpreter& m_interpreter;\n\n  // Store the graphics object directly so that it will exist when\n  // we need it.  Previously, it was possible for the graphics\n  // toolkit to get a handle to a figure, then have the interpreter\n  // thread delete the corresponding object before the graphics\n  // toolkit (GUI) thread had a chance to display it.  It should be OK\n  // to store this object and use it in both threads (graphics_object\n  // uses a std::shared_ptr) provided that we protect access with\n  // mutex locks.\n  graphics_object m_go;\n\n  // Handle to the graphics object.  This may be redundant now.\n  // Also, the whole ObjectProxy thing may not need to store a\n  // pointer now?  Maybe we can just have a lookup table from figure\n  // handle to Object?  What does the FLTK toolkit do?  Why does\n  // this seem to be so complicated?\n  graphics_handle m_handle;\n\n  QObject *m_qobject;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/ObjectProxy.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QCoreApplication>\n#include <QString>\n#include <QThread>\n\n#include \"Object.h\"\n#include \"ObjectProxy.h\"\n\n#include \"oct-mutex.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nObjectProxy::ObjectProxy (Object *obj)\n  : QObject (), m_object (nullptr)\n{\n  init (obj);\n}\n\nvoid\nObjectProxy::init (Object *obj)\n{\n  if (obj != m_object)\n    {\n      if (m_object)\n        {\n          disconnect (this, &ObjectProxy::sendUpdate,\n                      m_object, &Object::slotUpdate);\n          disconnect (this, &ObjectProxy::sendRedraw,\n                      m_object, &Object::slotRedraw);\n          disconnect (this, &ObjectProxy::sendShow,\n                      m_object, &Object::slotShow);\n        }\n\n      m_object = obj;\n\n      if (m_object)\n        {\n          connect (this, &ObjectProxy::sendUpdate,\n                   m_object, &Object::slotUpdate);\n          connect (this, &ObjectProxy::sendRedraw,\n                   m_object, &Object::slotRedraw);\n          connect (this, &ObjectProxy::sendShow,\n                   m_object, &Object::slotShow);\n        }\n    }\n}\n\nvoid\nObjectProxy::setObject (Object *obj)\n{\n  // Eventually destroy previous Object\n  if (m_object)\n    finalize ();\n\n  init (obj);\n}\n\nvoid\nObjectProxy::update (int pId)\n{\n  Q_EMIT sendUpdate (pId);\n}\n\nvoid\nObjectProxy::finalize ()\n{\n  if (! m_object)\n    error (\"ObjectProxy::finalize: invalid GUI Object\");\n\n  Qt::ConnectionType t = Qt::BlockingQueuedConnection;\n\n  if (QThread::currentThread () == QCoreApplication::instance ()->thread ())\n    t = Qt::DirectConnection;\n\n  if (! QMetaObject::invokeMethod (m_object, \"slotFinalize\", t))\n    error (\"ObjectProxy::finalize: unable to delete GUI Object\");\n}\n\nvoid\nObjectProxy::redraw ()\n{\n  Q_EMIT sendRedraw ();\n}\n\nvoid\nObjectProxy::show ()\n{\n  Q_EMIT sendShow ();\n}\n\nvoid\nObjectProxy::print (const QString& file_cmd, const QString& term)\n{\n  if (! m_object)\n    error (\"ObjectProxy::print: invalid GUI Object\");\n\n  Qt::ConnectionType t = Qt::BlockingQueuedConnection;\n\n  if (QThread::currentThread () == QCoreApplication::instance ()->thread ())\n    t = Qt::DirectConnection;\n\n  if (! QMetaObject::invokeMethod (m_object, \"slotPrint\", t,\n                                   Q_ARG (QString, file_cmd),\n                                   Q_ARG (QString, term)))\n    error (\"ObjectProxy::print: unable to print figure\");\n}\n\nuint8NDArray\nObjectProxy::get_pixels ()\n{\n  if (! m_object)\n    error (\"ObjectProxy::finalize: invalid GUI Object\");\n\n  uint8NDArray retval;\n\n  // The ObjectProxy is generally ran from the interpreter thread\n  // while the actual Figure (Object) lives in the gui thread.  The\n  // following ensures synchronous execution of the Figure method and\n  // allows retrieving a return value.\n\n  Qt::ConnectionType t = Qt::BlockingQueuedConnection;\n\n  if (QThread::currentThread () == QCoreApplication::instance ()->thread ())\n    t = Qt::DirectConnection;\n\n  QMetaObject::invokeMethod (m_object, \"slotGetPixels\", t,\n                             Q_RETURN_ARG (uint8NDArray, retval));\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/ObjectProxy.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ObjectProxy_h)\n#define octave_ObjectProxy_h 1\n\n#include \"uint8NDArray.h\"\n\n#include <QObject>\n\nclass QString;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass Object;\n\nclass ObjectProxy : public QObject\n{\n  Q_OBJECT\n\npublic:\n  ObjectProxy (Object *obj = nullptr);\n\n  void update (int pId);\n  void finalize ();\n  void redraw ();\n  void show ();\n  void print (const QString& file_cmd, const QString& term);\n  uint8NDArray get_pixels ();\n\n  Object * object () { return m_object; }\n  void setObject (Object *obj);\n\nQ_SIGNALS:\n  void sendUpdate (int pId);\n  void sendRedraw ();\n  void sendShow ();\n\nprivate:\n  void init (Object *obj);\n\nprivate:\n  Object *m_object;\n};\n\nOCTAVE_END_NAMESPACE(octave);\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/Panel.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QEvent>\n#include <QFrame>\n#include <QLabel>\n#include <QMouseEvent>\n#include <QTimer>\n\n#include \"Canvas.h\"\n#include \"Container.h\"\n#include \"ContextMenu.h\"\n#include \"Panel.h\"\n#include \"QtHandlesUtils.h\"\n\n#include \"graphics.h\"\n#include \"interpreter.h\"\n#include \"octave-qt-features.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic int\nframeStyleFromProperties (const uipanel::properties& pp)\n{\n  if (pp.bordertype_is (\"none\"))\n    return QFrame::NoFrame;\n  else if (pp.bordertype_is (\"etchedin\"))\n    return (QFrame::Box | QFrame::Sunken);\n  else if (pp.bordertype_is (\"etchedout\"))\n    return (QFrame::Box | QFrame::Raised);\n  else if (pp.bordertype_is (\"beveledin\"))\n    return (QFrame::Panel | QFrame::Sunken);\n  else if (pp.bordertype_is (\"beveledout\"))\n    return (QFrame::Panel | QFrame::Raised);\n  else\n    return (QFrame::Panel | QFrame::Plain);\n}\n\nstatic void\nsetupPalette (const uipanel::properties& pp, QPalette& p)\n{\n  p.setColor (QPalette::Window,\n              Utils::fromRgb (pp.get_backgroundcolor_rgb ()));\n  p.setColor (QPalette::WindowText,\n              Utils::fromRgb (pp.get_foregroundcolor_rgb ()));\n  p.setColor (QPalette::Light,\n              Utils::fromRgb (pp.get_highlightcolor_rgb ()));\n  p.setColor (QPalette::Dark,\n              Utils::fromRgb (pp.get_shadowcolor_rgb ()));\n}\n\nstatic int\nborderWidthFromProperties (const uipanel::properties& pp)\n{\n  int bw = 0;\n\n  if (! pp.bordertype_is (\"none\"))\n    {\n      bw = octave::math::round (pp.get_borderwidth ());\n      if (pp.bordertype_is (\"etchedin\") || pp.bordertype_is (\"etchedout\"))\n        bw *= 2;\n    }\n\n  return bw;\n}\n\nPanel *\nPanel::create (octave::interpreter& interp,\n               const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new Panel (interp, go, new QFrame (container));\n    }\n\n  return nullptr;\n}\n\nPanel::Panel (octave::interpreter& interp,\n              const graphics_object& go, QFrame *frame)\n  : Object (interp, go, frame), m_container (nullptr),\n    m_title (nullptr), m_blockUpdates (false),\n    m_previous_bbox (Matrix (1, 4, 0))\n{\n  uipanel::properties& pp = properties<uipanel> ();\n\n  frame->setObjectName (\"UIPanel\");\n  frame->setAutoFillBackground (true);\n  Matrix bb = pp.get_boundingbox (false);\n  frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)),\n                      octave::math::round (bb(2)), octave::math::round (bb(3)));\n  frame->setFrameStyle (frameStyleFromProperties (pp));\n  frame->setLineWidth (octave::math::round (pp.get_borderwidth ()));\n  QPalette pal = frame->palette ();\n  setupPalette (pp, pal);\n  frame->setPalette (pal);\n\n  m_container = new Container (frame, interp);\n  m_container->canvas (m_handle);\n\n  connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)),\n           this, SIGNAL (interpeter_event (const fcn_callback&)));\n\n  connect (m_container, SIGNAL (interpeter_event (const meth_callback&)),\n           this, SIGNAL (interpeter_event (const meth_callback&)));\n\n  if (frame->hasMouseTracking ())\n    {\n      for (auto *w : frame->findChildren<QWidget *> ())\n        w->setMouseTracking (true);\n    }\n\n  QString title = Utils::fromStdString (pp.get_title ());\n  if (! title.isEmpty ())\n    {\n      m_title = new QLabel (title, frame);\n      m_title->setAutoFillBackground (true);\n      m_title->setContentsMargins (4, 0, 4, 0);\n      m_title->setPalette (pal);\n      m_title->setFont (Utils::computeFont<uipanel> (pp, bb(3)));\n    }\n\n  frame->installEventFilter (this);\n  m_container->installEventFilter (this);\n\n  graphics_object fig (go.get_ancestor (\"figure\"));\n  if (! fig.get (\"keypressfcn\").isempty ())\n    m_container->canvas (m_handle)->addEventMask (Canvas::KeyPress);\n\n  if (! fig.get (\"keyreleasefcn\").isempty ())\n    m_container->canvas (m_handle)->addEventMask (Canvas::KeyRelease);\n\n  if (pp.is_visible ())\n    QTimer::singleShot (0, frame, &QFrame::show);\n  else\n    frame->hide ();\n}\n\nPanel::~Panel ()\n{ }\n\nbool\nPanel::eventFilter (QObject *watched, QEvent *xevent)\n{\n  if (! m_blockUpdates)\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      if (watched == qObject ())\n        {\n          switch (xevent->type ())\n            {\n            case QEvent::Resize:\n              {\n                octave::autolock guard (gh_mgr.graphics_lock ());\n\n                graphics_object go = object ();\n\n                if (go.valid_object ())\n                  {\n                    if (m_title)\n                      {\n                        const uipanel::properties& pp =\n                          Utils::properties<uipanel> (go);\n\n                        if (pp.fontunits_is (\"normalized\"))\n                          {\n                            QFrame *frame = qWidget<QFrame> ();\n\n                            m_title->setFont (Utils::computeFont<uipanel>\n                                              (pp, frame->height ()));\n                            m_title->resize (m_title->sizeHint ());\n                          }\n                      }\n                    updateLayout ();\n                  }\n              }\n              break;\n\n            case QEvent::MouseButtonPress:\n              {\n                QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);\n\n                if (m->button () == Qt::RightButton)\n                  {\n                    octave::autolock guard (gh_mgr.graphics_lock ());\n\n                    graphics_object go = object ();\n\n                    if (go.valid_object ())\n                      ContextMenu::executeAt (m_interpreter,\n                                              go.get_properties (),\n#if defined (HAVE_QSINGLEPOINTEVENT_CLASS)\n                                              m->globalPosition ().toPoint ());\n#else\n                                              m->globalPos ());\n#endif\n                  }\n              }\n              break;\n\n            default:\n              break;\n            }\n        }\n      else if (watched == m_container)\n        {\n          switch (xevent->type ())\n            {\n            case QEvent::Resize:\n              if (qWidget<QWidget> ()->isVisible ())\n                {\n                  octave::autolock guard (gh_mgr.graphics_lock ());\n\n                  graphics_object go = object ();\n\n                  if (go.valid_object ())\n                    go.get_properties ().update_boundingbox ();\n                }\n              break;\n\n            default:\n              break;\n            }\n        }\n    }\n\n  return false;\n}\n\nvoid\nPanel::update (int pId)\n{\n  uipanel::properties& pp = properties<uipanel> ();\n  QFrame *frame = qWidget<QFrame> ();\n\n  m_blockUpdates = true;\n\n  switch (pId)\n    {\n    case uipanel::properties::ID_POSITION:\n      {\n        Matrix bb = pp.get_boundingbox (false);\n        if (m_previous_bbox(0) != bb(0) || m_previous_bbox(1) != bb(1)\n            || m_previous_bbox(2) != bb(2) || m_previous_bbox(3) != bb(3))\n          {\n            frame->setGeometry (octave::math::round (bb(0)),\n                                octave::math::round (bb(1)),\n                                octave::math::round (bb(2)),\n                                octave::math::round (bb(3)));\n            updateLayout ();\n          }\n        m_previous_bbox = bb;\n      }\n      break;\n\n    case uipanel::properties::ID_BORDERWIDTH:\n      frame->setLineWidth (octave::math::round (pp.get_borderwidth ()));\n      updateLayout ();\n      break;\n\n    case uipanel::properties::ID_BACKGROUNDCOLOR:\n    case uipanel::properties::ID_FOREGROUNDCOLOR:\n    case uipanel::properties::ID_HIGHLIGHTCOLOR:\n    case uipanel::properties::ID_SHADOWCOLOR:\n      {\n        QPalette pal = frame->palette ();\n\n        setupPalette (pp, pal);\n        frame->setPalette (pal);\n        if (m_title)\n          m_title->setPalette (pal);\n      }\n      break;\n\n    case uipanel::properties::ID_TITLE:\n      {\n        QString title = Utils::fromStdString (pp.get_title ());\n\n        if (title.isEmpty ())\n          {\n            if (m_title)\n              delete m_title;\n            m_title = nullptr;\n          }\n        else\n          {\n            if (! m_title)\n              {\n                QPalette pal = frame->palette ();\n\n                m_title = new QLabel (title, frame);\n                m_title->setAutoFillBackground (true);\n                m_title->setContentsMargins (4, 0, 4, 0);\n                m_title->setPalette (pal);\n                m_title->setFont (Utils::computeFont<uipanel> (pp));\n                m_title->show ();\n              }\n            else\n              {\n                m_title->setText (title);\n                m_title->resize (m_title->sizeHint ());\n              }\n          }\n        updateLayout ();\n      }\n      break;\n\n    case uipanel::properties::ID_TITLEPOSITION:\n      updateLayout ();\n      break;\n\n    case uipanel::properties::ID_BORDERTYPE:\n      frame->setFrameStyle (frameStyleFromProperties (pp));\n      updateLayout ();\n      break;\n\n    case uipanel::properties::ID_FONTNAME:\n    case uipanel::properties::ID_FONTSIZE:\n    case uipanel::properties::ID_FONTWEIGHT:\n    case uipanel::properties::ID_FONTANGLE:\n      if (m_title)\n        {\n          m_title->setFont (Utils::computeFont<uipanel> (pp));\n          m_title->resize (m_title->sizeHint ());\n          updateLayout ();\n        }\n      break;\n\n    case uipanel::properties::ID_VISIBLE:\n      frame->setVisible (pp.is_visible ());\n      updateLayout ();\n      break;\n\n    default:\n      break;\n    }\n\n  m_blockUpdates = false;\n}\n\nvoid\nPanel::redraw ()\n{\n  update (uipanel::properties::ID_POSITION);\n\n  Canvas *canvas = m_container->canvas (m_handle);\n\n  if (canvas)\n    canvas->redraw ();\n}\n\nvoid\nPanel::updateLayout ()\n{\n  uipanel::properties& pp = properties<uipanel> ();\n  QFrame *frame = qWidget<QFrame> ();\n\n  Matrix bb = pp.get_boundingbox (true);\n  int bw = borderWidthFromProperties (pp);\n\n  frame->setFrameRect (QRect (octave::math::round (bb(0)) - bw,\n                              octave::math::round (bb(1)) - bw,\n                              octave::math::round (bb(2)) + 2*bw, octave::math::round (bb(3)) + 2*bw));\n  m_container->setGeometry (octave::math::round (bb(0)),\n                            octave::math::round (bb(1)),\n                            octave::math::round (bb(2)), octave::math::round (bb(3)));\n\n  if (m_blockUpdates)\n    pp.update_boundingbox ();\n\n  if (m_title)\n    {\n      QSize sz = m_title->sizeHint ();\n      int offset = 5;\n\n      if (pp.titleposition_is (\"lefttop\"))\n        m_title->move (bw+offset, 0);\n      else if (pp.titleposition_is (\"righttop\"))\n        m_title->move (frame->width () - bw - offset - sz.width (), 0);\n      else if (pp.titleposition_is (\"leftbottom\"))\n        m_title->move (bw+offset, frame->height () - sz.height ());\n      else if (pp.titleposition_is (\"rightbottom\"))\n        m_title->move (frame->width () - bw - offset - sz.width (),\n                       frame->height () - sz.height ());\n      else if (pp.titleposition_is (\"centertop\"))\n        m_title->move (frame->width () / 2 - sz.width () / 2, 0);\n      else if (pp.titleposition_is (\"centerbottom\"))\n        m_title->move (frame->width () / 2 - sz.width () / 2,\n                       frame->height () - sz.height ());\n    }\n}\n\nvoid\nPanel::do_connections (const QObject *receiver, const QObject * /* emitter */)\n{\n  Object::do_connections (receiver);\n  Object::do_connections (receiver, m_container->canvas (m_handle));\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/Panel.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Panel_h)\n#define octave_Panel_h 1\n\n#include \"Object.h\"\n\nclass QFrame;\nclass QLabel;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass Container;\n\nclass Panel : public Object\n{\npublic:\n  Panel (octave::interpreter& interp,\n         const graphics_object& go, QFrame *frame);\n  ~Panel ();\n\n  Container * innerContainer () { return m_container; }\n\n  bool eventFilter (QObject *watched, QEvent *event);\n\n  static Panel *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\n  void do_connections (const QObject *receiver,\n                       const QObject *emitter = nullptr);\n\nprotected:\n  void update (int pId);\n  void redraw ();\n\nprivate:\n  void updateLayout ();\n\nprivate:\n  Container *m_container;\n  QLabel *m_title;\n  bool m_blockUpdates;\n  Matrix m_previous_bbox;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/PopupMenuControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QComboBox>\n\n#include \"Container.h\"\n#include \"PopupMenuControl.h\"\n#include \"QtHandlesUtils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nPopupMenuControl *\nPopupMenuControl::create (octave::interpreter& interp,\n                          const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new PopupMenuControl (interp, go,\n                                     new QComboBox (container));\n    }\n\n  return nullptr;\n}\n\nPopupMenuControl::PopupMenuControl (octave::interpreter& interp,\n                                    const graphics_object& go,\n                                    QComboBox *box)\n  : BaseControl (interp, go, box), m_blockUpdate (false)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  box->addItems (Utils::fromStdString (up.get_string_string ()).split ('|'));\n\n  update (uicontrol::properties::ID_VALUE);\n\n  connect (box, qOverload<int> (&QComboBox::activated),\n           this, &PopupMenuControl::currentIndexChanged);\n}\n\nPopupMenuControl::~PopupMenuControl ()\n{ }\n\nvoid\nPopupMenuControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QComboBox *box = qWidget<QComboBox> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_STRING:\n      m_blockUpdate = true;\n      {\n        int oldCurrent = box->currentIndex ();\n\n        box->clear ();\n        box->addItems (Utils::fromStdString\n                       (up.get_string_string ()).split ('|'));\n        if (box->count () > 0\n            && oldCurrent >= 0\n            && oldCurrent < box->count ())\n          {\n            box->setCurrentIndex (oldCurrent);\n          }\n        else\n          {\n            Q_EMIT gh_set_event (m_handle, \"value\",\n                                 octave_value (box->count () > 0 ? 1.0 : 0.0),\n                                 false);\n          }\n      }\n      m_blockUpdate = false;\n      break;\n\n    case uicontrol::properties::ID_VALUE:\n      m_blockUpdate = true;\n      {\n        Matrix value = up.get_value ().matrix_value ();\n\n        if (value.numel () > 0)\n          {\n            if (value(0) != static_cast<int> (value(0)))\n              warning (\"popupmenu value should be integer\");\n            else\n              {\n                int newIndex = int (value(0)) - 1;\n\n                if (newIndex >= 0 && newIndex < box->count ())\n                  {\n                    if (newIndex != box->currentIndex ())\n                      box->setCurrentIndex (newIndex);\n                  }\n                else\n                  warning (\"popupmenu value not within valid display range\");\n              }\n          }\n      }\n      m_blockUpdate = false;\n      break;\n\n    default:\n      BaseControl::update (pId);\n      break;\n    }\n}\n\nvoid\nPopupMenuControl::currentIndexChanged (int index)\n{\n  if (! m_blockUpdate)\n    {\n      Q_EMIT gh_set_event (m_handle, \"value\",\n                           octave_value (double (index + 1)), false);\n      Q_EMIT gh_callback_event (m_handle, \"callback\");\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/PopupMenuControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_PopupMenuControl_h)\n#define octave_PopupMenuControl_h 1\n\n#include \"BaseControl.h\"\n\nclass QComboBox;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass PopupMenuControl : public BaseControl\n{\n  Q_OBJECT\n\npublic:\n  PopupMenuControl (octave::interpreter& interp, const graphics_object& go,\n                    QComboBox *box);\n  ~PopupMenuControl ();\n\n  static PopupMenuControl *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n\nprivate Q_SLOTS:\n  void currentIndexChanged (int index);\n\nprivate:\n  bool m_blockUpdate;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/PushButtonControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QPushButton>\n#include <QtDebug>\n\n#include \"PushButtonControl.h\"\n#include \"Container.h\"\n#include \"QtHandlesUtils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nPushButtonControl *\nPushButtonControl::create (octave::interpreter& interp,\n                           const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new PushButtonControl (interp, go,\n                                      new QPushButton (container));\n    }\n\n  return nullptr;\n}\n\nPushButtonControl::PushButtonControl (octave::interpreter& interp,\n                                      const graphics_object& go,\n                                      QPushButton *btn)\n  : ButtonControl (interp, go, btn)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  btn->setAutoFillBackground (true);\n  octave_value cdat = up.get_cdata ();\n  QImage img = Utils::makeImageFromCData (cdat,\n                                          cdat.columns (), cdat.rows ());\n  btn->setIcon (QIcon (QPixmap::fromImage (img)));\n  btn->setIconSize (QSize (cdat.columns (), cdat.rows ()));\n}\n\nPushButtonControl::~PushButtonControl ()\n{ }\n\nvoid\nPushButtonControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QPushButton *btn = qWidget<QPushButton> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_CDATA:\n      {\n        octave_value cdat = up.get_cdata ();\n        QImage img = Utils::makeImageFromCData (cdat,\n                                                cdat.rows (),\n                                                cdat.columns ());\n        btn->setIcon (QIcon (QPixmap::fromImage (img)));\n        btn->setIconSize (QSize (cdat.columns (), cdat.rows ()));\n      }\n      break;\n\n    default:\n      ButtonControl::update (pId);\n      break;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/PushButtonControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_PushButtonControl_h)\n#define octave_PushButtonControl_h 1\n\n#include \"ButtonControl.h\"\n\nclass QPushButton;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass PushButtonControl : public ButtonControl\n{\npublic:\n  PushButtonControl (octave::interpreter& interp, const graphics_object& go,\n                     QPushButton *btn);\n  ~PushButtonControl ();\n\n  static PushButtonControl *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/PushTool.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"PushTool.h\"\n\n#include \"ToolBarButton.cc\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nPushTool *\nPushTool::create (octave::interpreter& interp, const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      QWidget *parentWidget = parent->qWidget<QWidget> ();\n\n      if (parentWidget)\n        return new PushTool (interp, go,\n                             new QAction (parentWidget));\n    }\n\n  return nullptr;\n}\n\nPushTool::PushTool (octave::interpreter& interp,\n                    const graphics_object& go, QAction *action)\n  : ToolBarButton<uipushtool> (interp, go, action)\n{\n  connect (action, &QAction::triggered, this, &PushTool::clicked);\n}\n\nPushTool::~PushTool ()\n{ }\n\nvoid\nPushTool::update (int pId)\n{\n  switch (pId)\n    {\n    default:\n      ToolBarButton<uipushtool>::update (pId);\n      break;\n    }\n}\n\nvoid\nPushTool::clicked ()\n{\n  Q_EMIT gh_callback_event (m_handle, \"clickedcallback\");\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/PushTool.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_PushTool_h)\n#define octave_PushTool_h 1\n\n#include \"ToolBarButton.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass PushTool : public ToolBarButton<uipushtool>\n{\n  Q_OBJECT\n\npublic:\n  PushTool (octave::interpreter& interp,\n            const graphics_object& go, QAction *action);\n  ~PushTool ();\n\n  static PushTool *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n\nprivate Q_SLOTS:\n  void clicked ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/QtHandlesUtils.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <list>\n\n#include <QApplication>\n#include <QKeyEvent>\n#include <QMouseEvent>\n\n#include \"Container.h\"\n#include \"KeyMap.h\"\n#include \"Object.h\"\n#include \"QtHandlesUtils.h\"\n#include \"qt-graphics-toolkit.h\"\n\n#include \"oct-string.h\"\n\n#include \"graphics.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nnamespace Utils\n{\n\n  QString\n  fromStdString (const std::string& s)\n  {\n    return QString::fromUtf8 (s.c_str ());\n  }\n\n  std::string\n  toStdString (const QString& s)\n  {\n    return std::string (s.toUtf8 ().data ());\n  }\n\n  QStringList\n  fromStringVector (const string_vector& v)\n  {\n    QStringList l;\n    octave_idx_type n = v.numel ();\n\n    for (octave_idx_type i = 0; i < n; i++)\n      l << fromStdString (v[i]);\n\n    return l;\n  }\n\n  string_vector\n  toStringVector (const QStringList& l)\n  {\n    string_vector v (l.length ());\n    int i = 0;\n\n    for (const auto& s : l)\n      v[i++] = toStdString (s);\n\n    return v;\n  }\n\n  Cell\n  toCellString (const QStringList& l)\n  {\n    QStringList tmp = l;\n\n    // don't get any empty lines from end of the list\n    while ((tmp.length () > 0) && tmp.last ().isEmpty ())\n      {\n        tmp.removeLast ();\n      }\n    // no strings converts to a 1x1 cell with empty string\n    if (tmp.isEmpty ())\n      tmp += \"\";\n\n    Cell v (toStringVector (tmp));\n    return v;\n  }\n\n  template <typename T>\n  QFont\n  computeFont (const typename T::properties& props, int height)\n  {\n    QFont f (fromStdString (props.get_fontname ()));\n\n    static std::map<std::string, QFont::Weight> weightMap;\n    static std::map<std::string, QFont::Style> angleMap;\n    static bool mapsInitialized = false;\n\n    if (! mapsInitialized)\n      {\n        weightMap[\"normal\"] = QFont::Normal;\n        weightMap[\"bold\"] = QFont::Bold;\n\n        angleMap[\"normal\"] = QFont::StyleNormal;\n        angleMap[\"italic\"] = QFont::StyleItalic;\n        angleMap[\"oblique\"] = QFont::StyleOblique;\n\n        mapsInitialized = true;\n      }\n\n    f.setPointSizeF (props.get___fontsize_points__ (height));\n    f.setWeight (weightMap[props.get_fontweight ()]);\n    f.setStyle (angleMap[props.get_fontangle ()]);\n\n    return f;\n  }\n\n  template QFont computeFont<uicontrol> (const uicontrol::properties& props,\n                                         int height);\n\n  template QFont computeFont<uipanel> (const uipanel::properties& props,\n                                       int height);\n\n  template QFont computeFont<uibuttongroup> (const uibuttongroup::properties&\n                                             props,\n                                             int height);\n\n  template QFont computeFont<uitable> (const uitable::properties& props,\n                                       int height);\n\n  QColor\n  fromRgb (const Matrix& rgb)\n  {\n    QColor c;\n\n    if (rgb.numel () == 3)\n      c.setRgbF (rgb(0), rgb(1), rgb(2));\n\n    return c;\n  }\n\n  Matrix\n  toRgb (const QColor& c)\n  {\n    Matrix rgb (1, 3);\n    double *rgbData = rgb.rwdata ();\n\n#if HAVE_QCOLOR_FLOAT_TYPE\n    float tmp[3];\n#else\n    // qreal is a typedef for double except for ARM CPU architectures\n    // where it is a typedef for float (Bug #44970).\n    qreal tmp[3];\n#endif\n    c.getRgbF (tmp, tmp+1, tmp+2);\n    rgbData[0] = tmp[0]; rgbData[1] = tmp[1]; rgbData[2] = tmp[2];\n\n    return rgb;\n  }\n\n  std::string\n  figureSelectionType (QMouseEvent *event, bool isDoubleClick)\n  {\n    if (isDoubleClick)\n      return \"open\";\n    else\n      {\n        Qt::MouseButtons buttons = event->buttons ();\n        Qt::KeyboardModifiers mods = event->modifiers ();\n\n        if (mods == Qt::NoModifier)\n          {\n            if (buttons == Qt::LeftButton)\n              return \"normal\";\n            else if (buttons == Qt::RightButton)\n              return \"alt\";\n            else if (buttons == Qt::MiddleButton\n                     || buttons == (Qt::LeftButton | Qt::RightButton))\n              return \"extend\";\n          }\n        else if (buttons == Qt::LeftButton)\n          {\n            if (mods == Qt::ShiftModifier)\n              return \"extend\";\n            else if (mods == Qt::ControlModifier)\n              return \"alt\";\n          }\n      }\n\n    return \"normal\";\n  }\n\n  /*\n    Two figureCurrentPoint() routines are required:\n    1) Used for QMouseEvents where cursor position data is in callback from Qt.\n    2) Used for QKeyEvents where cursor position must be determined.\n  */\n  Matrix\n  figureCurrentPoint (const graphics_object& fig, QMouseEvent *event)\n  {\n    Object *tkFig = qt_graphics_toolkit::toolkitObject (fig);\n\n    if (tkFig)\n      {\n        Container *c = tkFig->innerContainer ();\n\n        if (c)\n          {\n            QPoint qp = event->pos ();\n\n            return tkFig->properties<figure> ().map_from_boundingbox (qp.x (),\n                                                                      qp.y ());\n          }\n      }\n\n    return Matrix (1, 2, 0.0);\n  }\n\n  Matrix\n  figureCurrentPoint (const graphics_object& fig)\n  {\n    Object *tkFig = qt_graphics_toolkit::toolkitObject (fig);\n\n    if (tkFig)\n      {\n        Container *c = tkFig->innerContainer ();\n\n        if (c)\n          {\n            // FIXME: QCursor::pos() may give inaccurate results with\n            //        asynchronous window systems like X11 over ssh.\n            QPoint qp = c->mapFromGlobal (QCursor::pos ());\n\n            return tkFig->properties<figure> ().map_from_boundingbox (qp.x (),\n                                                                      qp.y ());\n          }\n      }\n\n    return Matrix (1, 2, 0.0);\n  }\n\n  Qt::Alignment\n  fromHVAlign (const std::string& halign, const std::string& valign)\n  {\n    Qt::Alignment flags;\n\n    if (octave::string::strcmpi (halign, \"left\"))\n      flags |= Qt::AlignLeft;\n    else if (octave::string::strcmpi (halign, \"center\"))\n      flags |= Qt::AlignHCenter;\n    else if (octave::string::strcmpi (halign, \"right\"))\n      flags |= Qt::AlignRight;\n    else\n      flags |= Qt::AlignLeft;\n\n    if (octave::string::strcmpi (valign, \"middle\"))\n      flags |= Qt::AlignVCenter;\n    else if (octave::string::strcmpi (valign, \"top\"))\n      flags |= Qt::AlignTop;\n    else if (octave::string::strcmpi (valign, \"bottom\"))\n      flags |= Qt::AlignBottom;\n    else\n      flags |= Qt::AlignVCenter;\n\n    return flags;\n  }\n\n  QImage\n  makeImageFromCData (const octave_value& v, int width, int height)\n  {\n    const dim_vector& dv = v.dims ();\n\n    if (dv.ndims () == 3 && dv(2) == 3)\n      {\n        int w = qMin (dv(1), static_cast<octave_idx_type> (width));\n        int h = qMin (dv(0), static_cast<octave_idx_type> (height));\n\n        // If size mismatch, take data from center of CDATA and\n        // place in center of QImage.\n        int x_img_off = (w < width ? (width - w) / 2 : 0);\n        int y_img_off = (h < height ? (height - h) / 2 : 0);\n        int x_cdat_off = (dv(1) > w ? (dv(1) - w) / 2 : 0);\n        int y_cdat_off = (dv(0) > h ? (dv(0) - h) / 2 : 0);\n\n        QImage img (width, height, QImage::Format_ARGB32);\n        img.fill (qRgba (0, 0, 0, 0));\n\n        if (v.is_uint8_type ())\n          {\n            uint8NDArray d = v.uint8_array_value ();\n\n            for (int i = x_cdat_off; i < w + x_cdat_off; i++)\n              for (int j = y_cdat_off; j < h + y_cdat_off; j++)\n                {\n                  int r = d(j, i, 0);\n                  int g = d(j, i, 1);\n                  int b = d(j, i, 2);\n                  int a = 255;\n\n                  img.setPixel (x_img_off + i - x_cdat_off,\n                                y_img_off + j - y_cdat_off,\n                                qRgba (r, g, b, a));\n                }\n          }\n        else if (v.is_single_type ())\n          {\n            FloatNDArray f = v.float_array_value ();\n\n            for (int i = x_cdat_off; i < w + x_cdat_off; i++)\n              for (int j = y_cdat_off; j < h + y_cdat_off; j++)\n                {\n                  float r = f(j, i, 0);\n                  float g = f(j, i, 1);\n                  float b = f(j, i, 2);\n                  int a = (octave::math::isnan (r) || octave::math::isnan (g)\n                           || octave::math::isnan (b) ? 0 : 255);\n\n                  img.setPixel (x_img_off + i - x_cdat_off,\n                                y_img_off + j - y_cdat_off,\n                                qRgba (octave::math::round (r * 255),\n                                       octave::math::round (g * 255),\n                                       octave::math::round (b * 255),\n                                       a));\n                }\n          }\n        else if (v.isreal ())\n          {\n            NDArray d = v.array_value ();\n\n            for (int i = x_cdat_off; i < w + x_cdat_off; i++)\n              for (int j = y_cdat_off; j < h + y_cdat_off; j++)\n                {\n                  double r = d(j, i, 0);\n                  double g = d(j, i, 1);\n                  double b = d(j, i, 2);\n                  int a = (octave::math::isnan (r) || octave::math::isnan (g)\n                           || octave::math::isnan (b) ? 0 : 255);\n\n                  img.setPixel (x_img_off + i - x_cdat_off,\n                                y_img_off + j - y_cdat_off,\n                                qRgba (octave::math::round (r * 255),\n                                       octave::math::round (g * 255),\n                                       octave::math::round (b * 255),\n                                       a));\n                }\n          }\n\n        return img;\n      }\n\n    return QImage ();\n  }\n\n  octave_scalar_map\n  makeKeyEventStruct (QKeyEvent *event)\n  {\n    octave_scalar_map retval;\n\n    retval.setfield (\"Character\", toStdString (event->text ()));\n\n    std::list<std::string> modList;\n    Qt::KeyboardModifiers mods = event->modifiers ();\n\n    if (mods & Qt::ShiftModifier)\n      modList.push_back (\"shift\");\n    if (mods & Qt::ControlModifier)\n#if defined (Q_OS_MAC)\n      modList.push_back (\"command\");\n#else\n      modList.push_back (\"control\");\n#endif\n    if (mods & Qt::AltModifier)\n      modList.push_back (\"alt\");\n#if defined (Q_OS_MAC)\n    if (mods & Qt::MetaModifier)\n      modList.push_back (\"control\");\n#endif\n\n    retval.setfield (\"Modifier\", Cell (modList));\n\n    retval.setfield (\"Key\", KeyMap::qKeyToKeyString (event->key ()));\n\n    return retval;\n  }\n\n  octave_scalar_map\n  makeScrollEventStruct (QWheelEvent *event)\n  {\n    octave_scalar_map retval;\n\n    // We assume a standard mouse with 15 degree steps and Qt returns\n    // 1/8 of a degree.\n    int ydelta = -(event->angleDelta ().y ());\n\n    retval.setfield (\"VerticalScrollCount\", octave_value (ydelta / 120));\n\n    // FIXME: Is there any way to access the number of lines a scroll step\n    // should correspond to?\n    retval.setfield (\"VerticalScrollAmount\", octave_value (3));\n    retval.setfield (\"EventName\", octave_value (\"WindowScrollWheel\"));\n\n    return retval;\n  }\n\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/QtHandlesUtils.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_QtHandlesUtils_h)\n#define octave_QtHandlesUtils_h 1\n\n#include <QColor>\n#include <QFont>\n#include <QImage>\n#include <QString>\n#include <QStringList>\n\n#include <string>\n\n#include \"graphics.h\"\n\nclass QKeyEvent;\nclass QMouseEvent;\nclass QWheelEvent;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nnamespace Utils\n{\n  QString fromStdString (const std::string& s);\n  std::string toStdString (const QString& s);\n\n  QStringList fromStringVector (const string_vector& v);\n  string_vector toStringVector (const QStringList& l);\n\n  Cell toCellString (const QStringList& l);\n\n  template <typename T>\n  QFont computeFont (const typename T::properties& props, int height = -1);\n\n  QColor fromRgb (const Matrix& rgb);\n  Matrix toRgb (const QColor& c);\n\n  Qt::Alignment fromHVAlign (const std::string& halign,\n                             const std::string& valign);\n\n  std::string figureSelectionType (QMouseEvent *event,\n                                   bool isDoubleClick = false);\n\n  Matrix figureCurrentPoint (const graphics_object& fig, QMouseEvent *event);\n  Matrix figureCurrentPoint (const graphics_object& fig);\n\n  template <typename T>\n  inline typename T::properties&\n  properties (graphics_object& obj)\n  { return dynamic_cast<typename T::properties&> (obj.get_properties ()); }\n\n  template <typename T>\n  inline const typename T::properties&\n  properties (const graphics_object& obj)\n  { return dynamic_cast<const typename T::properties&> (obj.get_properties ()); }\n\n  QImage makeImageFromCData (const octave_value& v, int width = -1,\n                             int height = -1);\n\n  octave_scalar_map makeKeyEventStruct (QKeyEvent *event);\n  octave_scalar_map makeScrollEventStruct (QWheelEvent *event);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/RadioButtonControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QRadioButton>\n\n#include \"ButtonGroup.h\"\n#include \"RadioButtonControl.h\"\n#include \"Container.h\"\n#include \"QtHandlesUtils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nRadioButtonControl *\nRadioButtonControl::create (octave::interpreter& interp,\n                            const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new RadioButtonControl (interp, go,\n                                       new QRadioButton (container));\n    }\n\n  return nullptr;\n}\n\nRadioButtonControl::RadioButtonControl (octave::interpreter& interp,\n                                        const graphics_object& go,\n                                        QRadioButton *radio)\n  : ButtonControl (interp, go, radio)\n{\n  Object *parent = parentObject (interp, go);\n  ButtonGroup *btnGroup = dynamic_cast<ButtonGroup *>(parent);\n  if (btnGroup)\n    btnGroup->addButton (radio);\n\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  radio->setAutoFillBackground (true);\n  radio->setAutoExclusive (false);\n  if (up.enable_is (\"inactive\"))\n    radio->setCheckable (false);\n}\n\nRadioButtonControl::~RadioButtonControl ()\n{ }\n\nvoid\nRadioButtonControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QRadioButton *btn = qWidget<QRadioButton> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_ENABLE:\n      {\n        if (up.enable_is (\"inactive\"))\n          btn->setCheckable (false);\n        else\n          btn->setCheckable (true);\n        ButtonControl::update (pId);\n      }\n      break;\n\n    default:\n      ButtonControl::update (pId);\n      break;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/RadioButtonControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_RadioButton_h)\n#define octave_RadioButton_h 1\n\n#include \"ButtonControl.h\"\n\nclass QRadioButton;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass RadioButtonControl : public ButtonControl\n{\npublic:\n  RadioButtonControl (octave::interpreter& interp, const graphics_object& go,\n                      QRadioButton *box);\n  ~RadioButtonControl ();\n\n  static RadioButtonControl * create (octave::interpreter& interp,\n                                      const graphics_object& go);\n\nprotected:\n  void update (int pId);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/SliderControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QScrollBar>\n\n#include \"Container.h\"\n#include \"SliderControl.h\"\n#include \"QtHandlesUtils.h\"\n\n#include \"graphics.h\"\n#include \"interpreter.h\"\n\n#define RANGE_INT_MAX 1000000\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nSliderControl *\nSliderControl::create (octave::interpreter& interp,\n                       const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new SliderControl (interp, go,\n                                  new QScrollBar (container));\n    }\n\n  return nullptr;\n}\n\nSliderControl::SliderControl (octave::interpreter& interp,\n                              const graphics_object& go,\n                              QAbstractSlider *slider)\n  : BaseControl (interp, go, slider), m_blockUpdates (false)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  slider->setTracking (false);\n  Matrix bb = up.get_boundingbox ();\n  bool vertical_slider = ( bb(2) < bb(3) );\n  slider->setOrientation (vertical_slider ? Qt::Vertical : Qt::Horizontal);\n  if (vertical_slider)\n    slider->setInvertedAppearance (true);  // Matlab compatibility\n  Matrix steps = up.get_sliderstep ().matrix_value ();\n  slider->setMinimum (0);\n  slider->setMaximum (RANGE_INT_MAX);\n  slider->setSingleStep (octave::math::round (steps(0) * RANGE_INT_MAX));\n  slider->setPageStep (octave::math::round (steps(1) * RANGE_INT_MAX));\n  Matrix value = up.get_value ().matrix_value ();\n  if (value.numel () > 0)\n    {\n      double dmin = up.get_min (), dmax = up.get_max ();\n\n      slider->setValue (octave::math::round (((value(0) - dmin) / (dmax - dmin))\n                                             * RANGE_INT_MAX));\n    }\n\n  connect (slider, &QAbstractSlider::valueChanged,\n           this, &SliderControl::valueChanged);\n}\n\nSliderControl::~SliderControl ()\n{ }\n\nvoid\nSliderControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QScrollBar *slider = qWidget<QScrollBar> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_SLIDERSTEP:\n      {\n        Matrix steps = up.get_sliderstep ().matrix_value ();\n\n        slider->setSingleStep (octave::math::round (steps(0) * RANGE_INT_MAX));\n        slider->setPageStep (octave::math::round (steps(1) * RANGE_INT_MAX));\n      }\n      break;\n\n    case uicontrol::properties::ID_VALUE:\n      {\n        Matrix value = up.get_value ().matrix_value ();\n        double dmax = up.get_max (), dmin = up.get_min ();\n\n        if (value.numel () > 0)\n          {\n            int ival = octave::math::round (((value(0) - dmin) / (dmax - dmin))\n                                            * RANGE_INT_MAX);\n\n            m_blockUpdates = true;\n            slider->setValue (ival);\n            m_blockUpdates = false;\n          }\n      }\n      break;\n\n    default:\n      BaseControl::update (pId);\n      break;\n    }\n}\n\nvoid\nSliderControl::valueChanged (int ival)\n{\n  if (! m_blockUpdates)\n    {\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      graphics_object go = object ();\n\n      if (go.valid_object ())\n        {\n          uicontrol::properties& up = Utils::properties<uicontrol> (go);\n\n          Matrix value = up.get_value ().matrix_value ();\n          double dmin = up.get_min (), dmax = up.get_max ();\n\n          int ival_tmp = (value.numel () > 0 ?\n                          octave::math::round (((value(0) - dmin) / (dmax - dmin))\n                                               * RANGE_INT_MAX) :\n                          0);\n\n          if (ival != ival_tmp || value.numel () > 0)\n            {\n              double dval = dmin + (ival * (dmax - dmin) / RANGE_INT_MAX);\n\n              Q_EMIT gh_set_event (m_handle, \"value\", octave_value (dval));\n              Q_EMIT gh_callback_event (m_handle, \"callback\");\n            }\n        }\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/SliderControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_SliderControl_h)\n#define octave_SliderControl_h 1\n\n#include \"BaseControl.h\"\n\nclass QAbstractSlider;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass SliderControl : public BaseControl\n{\n  Q_OBJECT\n\npublic:\n  SliderControl (octave::interpreter& interp,\n                 const graphics_object& go, QAbstractSlider *slider);\n  ~SliderControl ();\n\n  static SliderControl *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n\nprivate Q_SLOTS:\n  void valueChanged (int ival);\n\nprivate:\n  bool m_blockUpdates;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/Table.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QCheckBox>\n#include <QComboBox>\n#include <QEvent>\n#include <QFrame>\n#include <QHBoxLayout>\n#include <QHeaderView>\n#include <QLabel>\n#include <QLineEdit>\n#include <QModelIndexList>\n#include <QMouseEvent>\n#include <QString>\n#include <QStringList>\n#include <QTableWidget>\n#include <QTableWidgetItem>\n#include <QTimer>\n\n#include \"Container.h\"\n#include \"ContextMenu.h\"\n#include \"Table.h\"\n#include \"QtHandlesUtils.h\"\n\n#include \"graphics.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"oct-stream.h\"\n#include \"oct-string.h\"\n#include \"oct-strstrm.h\"\n#include \"octave-qt-features.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic const int AUTO_WIDTH = 75;\n\n#define AUTO_HEIGHT (tp.get_fontsize () * 2 - 1)\n\nstatic QSize\nrealQSizeForTable (QTableWidget *t)\n{\n  int w = t->verticalHeader ()->width () + 4;\n  for (int i = 0; i < t->columnCount (); i++)\n    w += t->columnWidth (i);\n  int h = t->horizontalHeader ()->height () + 4;\n  for (int i = 0; i < t->rowCount (); i++)\n    h += t->rowHeight (i);\n  return QSize (w, h);\n}\n\n#define FORMATNUMBER(type)                                                    \\\nstatic QString formatNumber (type d,                                        \\\n                             char format = 'f',                             \\\n                             int precision = 4)                             \\\n{                                                                           \\\n  type ten = 10;                                                            \\\n  if (format == 'n')                                                        \\\n    {                                                                       \\\n      if (d == floor (d))                                                   \\\n        return QString::number (d, 'g', precision);                         \\\n      else if (d <= pow (ten, precision - 1)                                \\\n               && d > pow (ten, 1 - precision))                             \\\n        return QString::number (d, 'f', precision);                         \\\n      else                                                                  \\\n        return QString::number (d, 'e', precision);                         \\\n    }                                                                       \\\n  else if (format == 'F')                                                   \\\n    {                                                                       \\\n      int exponent = floor (log10 (d) / 3) * 3;                             \\\n      d *= pow (ten, -exponent);                                            \\\n      return QString::number (d, 'f', precision) + \"e\" +                    \\\n        (exponent < 0 ? \"-\" : \"+\") +                                        \\\n        QString (\"%1\").arg (abs (exponent), 3, 10, QChar ('0'));            \\\n    }                                                                       \\\n  else if (format == 'E')                                                   \\\n    {                                                                       \\\n      int exponent = floor (log10 (d) / 3) * 3;                             \\\n      d *=  pow (ten, -exponent);                                           \\\n      return QString::number (d,                                            \\\n                              'f',                                          \\\n                              precision - floor (log10 (d)) - 1) +          \\\n             \"e\" + (exponent < 0 ? \"-\" : \"+\") +                             \\\n             QString (\"%1\").arg (abs (exponent), 3, 10, QChar ('0'));       \\\n    }                                                                       \\\n  else                                                                      \\\n    return QString::number (d, format, precision);                          \\\n}\n\nFORMATNUMBER(double)\nFORMATNUMBER(float)\n\n#undef FORMATNUMBER\n\nstatic QString formatComplex (Complex c, char format = 'f', int precision = 4)\n{\n  return formatNumber (c.real (), format, precision) + \" + \"\n         + formatNumber (c.imag (), format, precision) + \"i\";\n}\n\n#define FORMAT_VALUE_EXCEPT_RAT(f,l)                      \\\nif (format == \"numeric\" || format == \"short\")           \\\n  text = formatNumber (value, 'n', f);                  \\\nelse if (format == \"short f\" || format == \"shortf\")     \\\n  text = formatNumber (value, 'f', f);                  \\\nelse if (format == \"short e\" || format == \"shorte\")     \\\n  text = formatNumber (value, 'e', f);                  \\\nelse if (format == \"short eng\" || format == \"shorteng\") \\\n  text = formatNumber (value, 'F', f);                  \\\nelse if (format == \"short g\" || format == \"shortg\")     \\\n  text = formatNumber (value, 'g', f + 1);              \\\nelse if (format == \"long\")                              \\\n  text = formatNumber (value, 'n', l);                  \\\nelse if (format == \"long f\" || format == \"longf\")       \\\n  text = formatNumber (value, 'f', l);                  \\\nelse if (format == \"long e\" || format == \"longe\")       \\\n  text = formatNumber (value, 'e', l);                  \\\nelse if (format == \"long eng\" || format == \"longeng\")   \\\n  text = formatNumber (value, 'E', l);                  \\\nelse if (format == \"long g\" || format == \"longg\")       \\\n  text = formatNumber (value, 'g', l + 1);              \\\nelse if (format == \"bank\")                              \\\n  text = QString::number (value, 'f', 2);               \\\nelse if (format == \"+\")                                 \\\n  if (value > 0)                                        \\\n    text = Utils::fromStdString (\"+\");                  \\\n  else if (value < 0)                                   \\\n    text = Utils::fromStdString (\"-\");                  \\\n  else                                                  \\\n    text = Utils::fromStdString (\"\");\n\n#define FORMAT_VALUE(f,l)                                               \\\nFORMAT_VALUE_EXCEPT_RAT(f,l)                                          \\\nelse if (format == \"rat\")                                             \\\n  text = Utils::fromStdString (rational_approx (double (value), 0));  \\\nelse                                                                  \\\n  {                                                                   \\\n    text = formatNumber (value, 'n', f);                              \\\n    flag = Qt::AlignLeft ;                                            \\\n  }\n\n#define FORMAT_UINT_VALUE()                    \\\ntext = QString::number (value);              \\\nif (format == \"char\"  || format == \"popup\")  \\\n  flag = Qt::AlignLeft;                      \\\nelse if (format == \"+\")                      \\\n  {                                          \\\n    if (value > 0)                           \\\n      text = Utils::fromStdString (\"+\");     \\\n    else                                     \\\n      text = Utils::fromStdString (\"\");      \\\n  }\n\n#define FORMAT_INT_VALUE()                     \\\ntext = QString::number (value);              \\\nif (format == \"char\" || format == \"popup\")   \\\n  flag = Qt::AlignLeft ;                     \\\nelse if (format == \"+\")                      \\\n  {                                          \\\n    if (value > 0)                           \\\n      text = Utils::fromStdString (\"+\");     \\\n    else if (value < 0)                      \\\n      text = Utils::fromStdString (\"-\");     \\\n    else                                     \\\n      text = Utils::fromStdString (\"\");      \\\n  }\n\nstatic std::pair<Qt::AlignmentFlag, QString>\nqStringValueFor (octave_value val, std::string format = \"\")\n{\n  Qt::AlignmentFlag flag = Qt::AlignRight;\n  QString text;\n  if (val.isempty ())\n    {\n      text = \"\";\n      flag = Qt::AlignLeft;\n    }\n  else if (val.is_string ())\n    {\n      text = octave::Utils::fromStdString (val.string_value ());\n      flag = Qt::AlignLeft;\n    }\n  else if (val.iscomplex ())\n    {\n      // Matlab has multiple complex types, we only have double.\n      Complex c = val.complex_value ();\n      if (format == \"short\")\n        text = formatComplex (c, 'f', 4);\n      else if (format == \"short e\" || format == \"shorte\")\n        text = formatComplex (c, 'e', 4);\n      else if (format == \"short eng\" || format == \"shorteng\")\n        text = formatComplex (c, 'E', 4);\n      else if (format == \"short g\" || format == \"shortg\")\n        text = formatComplex (c, 'g', 5);\n      else if (format == \"long\")\n        text = formatComplex (c, 'f', 15);\n      else if (format == \"long e\" || format == \"longe\")\n        text = formatComplex (c, 'e', 15);\n      else if (format == \"long eng\" || format == \"longeng\")\n        text = formatComplex (c, 'E', 15);\n      else if (format == \"long g\" || format == \"longg\")\n        text = formatComplex (c, 'g', 16);\n      else if (format == \"bank\")\n        text = QString::number (c.real (), 'f', 2);\n      else if (format == \"+\")\n        {\n          if (c.real () > 0)\n            text = Utils::fromStdString (\"+\");\n          else if (c.real () < 0)\n            text = Utils::fromStdString (\"-\");\n          else\n            text = Utils::fromStdString (\"\");\n        }\n      else if (format == \"rat\")\n        text = Utils::fromStdString (rational_approx (c.real (), 0)) + \" + \"\n               + Utils::fromStdString (rational_approx (c.imag (), 0)) + \"i\";\n      else if (format == \"numeric\")\n        text = QString::number (c.real (), 'g', 5) + \" + \"\n               + QString::number (c.imag (), 'g', 5) + \"i\";\n      else\n        {\n          text = QString::number (c.real (), 'g', 5) + \" + \"\n                 + QString::number (c.imag (), 'g', 5) + \"i\";\n          flag = Qt::AlignLeft;\n        }\n    }\n  else if (val.is_double_type () )\n    {\n      double value = val.double_value ();\n      FORMAT_VALUE(4, 15)\n    }\n  else if (val.is_single_type ())\n    {\n      float value = val.float_value ();\n      FORMAT_VALUE(4, 7)\n    }\n  else if (val.is_int8_type ())\n    {\n      short int value = val.short_value ();\n      FORMAT_INT_VALUE()\n    }\n  else if (val.is_uint8_type ())\n    {\n      unsigned short int value = val.ushort_value ();\n      FORMAT_UINT_VALUE()\n    }\n  else if (val.is_int16_type ())\n    {\n      int value = val.int_value ();\n      FORMAT_INT_VALUE()\n    }\n  else if (val.is_uint16_type ())\n    {\n      unsigned int value = val.uint_value ();\n      FORMAT_UINT_VALUE()\n    }\n  else if (val.is_int32_type ())\n    {\n      long int value = val.long_value ();\n      FORMAT_INT_VALUE()\n    }\n  else if (val.is_uint32_type ())\n    {\n      unsigned long int value = val.ulong_value ();\n      FORMAT_UINT_VALUE()\n    }\n  else if (val.is_int64_type ())\n    {\n      int64_t value = val.int64_value ();\n      FORMAT_INT_VALUE()\n    }\n  else if (val.is_uint64_type ())\n    {\n      uint64_t value = val.uint64_value ();\n      FORMAT_UINT_VALUE()\n    }\n  else if (val.islogical ())\n    {\n      bool b = val.bool_value ();\n      if (format == \"char\" || format == \"popup\" || format == \"\")\n        {\n          text = Utils::fromStdString (b ? \"true\" : \"false\");\n          flag = Qt::AlignLeft;\n        }\n      else if (format == \"+\")\n        {\n          text = Utils::fromStdString (b ? \"+\" : \"\");\n          flag = Qt::AlignLeft;\n        }\n      else\n        text = Utils::fromStdString (b ? \"1\" : \"0\");\n    }\n  else\n    {\n      // FIXME: Should we warn about the unknown conversion?  If so,\n      // how?  We can't just call Octave's warning function here.\n\n      text = Utils::fromStdString (val.string_value (true));\n    }\n\n  return std::make_pair (flag, text);\n}\n\n#undef FORMAT_VALUE\n#undef FORMAT_VALUE_EXCEPT_RAT\n#undef FORMAT_UINT_VALUE\n#undef FORMAT_INT_VALUE\n\nstatic QTableWidgetItem *\nitemFor (octave_value val, std::string format = \"\", bool enabled = false)\n{\n  QTableWidgetItem *retval = new QTableWidgetItem ();\n  std::pair<Qt::AlignmentFlag, QString> flag_and_text =\n    qStringValueFor (val, format);\n  retval->setTextAlignment (flag_and_text.first);\n  retval->setText (flag_and_text.second);\n\n  if (enabled)\n    retval->setFlags (retval->flags () | Qt::ItemIsEditable);\n  else\n    retval->setFlags (retval->flags () & ~Qt::ItemIsEditable);\n\n  return retval;\n}\n\nstatic octave_value\nattempt_type_conversion (const octave_value& ov,\n                         const octave_value& old_value)\n{\n  octave_value retval;\n\n  // Define a macro to help with the conversion of strings to integers\n  // FIXME: these will happily integer overflow in the (u)int64 case\n  // - this probably doesn't matter.\n#define SCANF_AND_CONVERT(name,ctype,format)           \\\nelse if (old_value.is_ ## name ## _type ())          \\\n  {                                                  \\\n    ctype val;                                       \\\n    int n;                                           \\\n    const std::string cxx_str = ov.string_value ();  \\\n    const char *c_str = cxx_str.c_str ();            \\\n    int error = sscanf (c_str, format, &val, &n);    \\\n    if (error != 1 || c_str[n])                      \\\n      {                                              \\\n        val = 0;                                     \\\n      }                                              \\\n    retval = octave_value ( octave_ ## name (val));  \\\n  }\n\n  if (old_value.is_string ())\n    retval = ov;\n  SCANF_AND_CONVERT(int8, int64_t, \"%\" PRId64 \" %n\")\n  SCANF_AND_CONVERT(uint8, uint64_t, \"%\" PRIu64 \" %n\")\n  SCANF_AND_CONVERT(int16, int64_t, \"%\" PRId64 \" %n\")\n  SCANF_AND_CONVERT(uint16, uint64_t, \"%\" PRIu64 \" %n\")\n  SCANF_AND_CONVERT(int32, int64_t, \"%\" PRId64 \" %n\")\n  SCANF_AND_CONVERT(uint32, uint64_t, \"%\" PRIu64 \" %n\")\n  SCANF_AND_CONVERT(int64, int64_t, \"%\" PRId64 \" %n\")\n  SCANF_AND_CONVERT(uint64, uint64_t, \"%\" PRIu64 \" %n\")\n\n#undef SCANF_AND_CONVERT\n\n  else if (old_value.isnumeric () && ! old_value.isinteger ())\n    {\n      // Basically need to do str2double\n      Complex complex = octave::string::str2double (ov.string_value ());\n      if (old_value.is_single_type ())\n        retval = octave_value (FloatComplex (complex));\n      else\n        retval = octave_value (complex);\n    }\n  else if (old_value.islogical ())\n    {\n      // Right: Matlab basically needs this to be true or false, we should\n      // accept 1 too.\n      if (ov.string_value ()  == \"true\" || ov.string_value () == \"1\")\n        retval = octave_value (true);\n      else\n        retval = octave_value (false);\n    }\n  else\n    retval = octave_value (octave::string::str2double (ov.string_value ()));\n  return retval;\n}\n\nQWidget *\nTable::checkBoxForLogical (octave_value val, bool enabled = false)\n{\n  QWidget *retval = new QWidget (m_tableWidget);\n  QCheckBox *checkBox = new QCheckBox ();\n  QHBoxLayout *layout = new QHBoxLayout (retval);\n  layout->addWidget (checkBox);\n  layout->setAlignment (Qt::AlignCenter);\n  layout->setContentsMargins (0, 0, 0, 0);\n  retval->setLayout (layout);\n\n  if ((val.islogical () || val.is_bool_scalar ()) && val.bool_value ())\n    checkBox->setCheckState (Qt::Checked);\n  else\n    checkBox->setCheckState (Qt::Unchecked);\n\n  checkBox->setAttribute (Qt::WA_TransparentForMouseEvents, true);\n  checkBox->setFocusPolicy (Qt::NoFocus);\n  checkBox->setProperty (\"Enabled\", QVariant (enabled));\n\n  return retval;\n}\n\nTable *\nTable::create (octave::interpreter& interp,\n               const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new Table (interp, go, new QTableWidget (container));\n    }\n\n  return 0;\n}\n\nTable::Table (octave::interpreter& interp,\n              const graphics_object& go, QTableWidget *tableWidget)\n  : Object (interp, go, tableWidget), m_tableWidget (tableWidget),\n    m_curData (), m_blockUpdates (false)\n{\n  qObject ()->setObjectName (\"UItable\");\n  uitable::properties& tp = properties<uitable> ();\n\n  m_curData = octave_value (tp.get_data ());\n  Matrix bb = tp.get_boundingbox (false);\n  m_tableWidget->setObjectName (\"UITable\");\n  m_tableWidget->setAutoFillBackground (true);\n  m_tableWidget->setGeometry (octave::math::round (bb(0)),\n                              octave::math::round (bb(1)),\n                              octave::math::round (bb(2)),\n                              octave::math::round (bb(3)));\n  m_tableWidget->setFont (Utils::computeFont<uitable> (tp)) ;\n  m_tableWidget->setSelectionBehavior (QAbstractItemView::SelectItems);\n  // Workaround Qt behavior which stops setColumnWidth from working for small\n  // column widths (see bug #63422).\n  m_tableWidget->horizontalHeader()->setMinimumSectionSize (1);\n  updatePalette ();\n  m_keyPressHandlerDefined = ! tp.get_keypressfcn ().isempty ();\n  m_keyReleaseHandlerDefined = ! tp.get_keyreleasefcn ().isempty ();\n  updateData ();\n  updateRowname ();\n  updateColumnname ();\n  updateColumnwidth ();\n  updateEnable ();  // Also does rearrangeableColumns\n  m_tableWidget->setToolTip (Utils::fromStdString (tp.get_tooltipstring ()));\n  m_tableWidget->setVisible (tp.is_visible ());\n  updateExtent ();\n  m_tableWidget->installEventFilter (this);\n\n  connect (m_tableWidget, &QTableWidget::itemChanged,\n           this, &Table::itemChanged);\n  connect (m_tableWidget, &QTableWidget::cellClicked,\n           this, &Table::cellClicked);\n  connect (m_tableWidget, &QTableWidget::itemSelectionChanged,\n           this, &Table::itemSelectionChanged);\n}\n\nTable::~Table () { }\n\nvoid\nTable::itemSelectionChanged ()\n{\n  if (! (properties<uitable> ().get_cellselectioncallback ().isempty ()))\n    {\n      QModelIndexList modelIndexList =\n        m_tableWidget->selectionModel ()->selectedIndexes ();\n      int length = modelIndexList.size ();\n      Matrix indices = Matrix (length, 2);\n      for (int i = 0; i < length; i++)\n        {\n          indices(i, 0) = modelIndexList.value (i).row () + 1;\n          indices(i, 1) = modelIndexList.value (i).column () + 1;\n        }\n      octave_scalar_map eventData;\n      eventData.setfield (\"Indices\", indices);\n      octave_value cellSelectionCallbackEventObject (eventData);\n      Q_EMIT gh_callback_event (m_handle, \"cellselectioncallback\",\n                                cellSelectionCallbackEventObject);\n    }\n}\n\nvoid\nTable::cellClicked (int row, int col)\n{\n  QCheckBox *checkBox = nullptr;\n  QWidget *widget\n    = qobject_cast<QWidget *> (m_tableWidget->cellWidget (row, col));\n  if (widget && ! widget->children ().isEmpty ())\n    {\n      QHBoxLayout *layout\n        = qobject_cast<QHBoxLayout *> (widget->children ().first ());\n\n      if (layout && layout->count () > 0)\n        checkBox = qobject_cast<QCheckBox *> (layout->itemAt (0)-> widget ());\n    }\n\n  if (checkBox && checkBox->property (\"Enabled\").toBool ())\n    checkBoxClicked (row, col, checkBox);\n}\n\nvoid\nTable::sendCellEditCallback (int row,\n                             int col,\n                             octave_value old_value,\n                             octave_value new_value,\n                             octave_value edit_data,\n                             octave_value error)\n{\n  if (!(properties<uitable> ().get_celleditcallback ().isempty ()))\n    {\n      Matrix indices = Matrix (1, 2);\n      indices(0, 0) = row + 1;\n      indices(0, 1) = col + 1;\n\n      octave_scalar_map eventData;\n      eventData.setfield (\"Indices\", indices);\n      eventData.setfield (\"PreviousData\", old_value);\n      eventData.setfield (\"NewData\", new_value);\n      eventData.setfield (\"EditData\", edit_data);\n      eventData.setfield (\"Error\", error);\n\n      octave_value cellEditCallbackEventObject (eventData);\n\n      Q_EMIT gh_callback_event (m_handle, \"celleditcallback\",\n                                cellEditCallbackEventObject);\n    }\n}\n\nvoid\nTable::comboBoxCurrentIndexChanged (const QString& value)\n{\n  if (m_blockUpdates)\n    return;\n\n  m_blockUpdates = true;\n\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  octave_value data = octave_value (m_curData);\n  bool ok = false;\n\n  QComboBox *comboBox = qobject_cast<QComboBox *> (sender ());\n  int row = comboBox->property (\"row\").toInt ();\n  int col = comboBox->property (\"col\").toInt ();\n\n  octave_value edit_data = octave_value (Utils::toStdString (value));\n\n  if (row < data.rows () && col < data.columns ())\n    {\n      if (data.iscell ())\n        {\n          Cell cell = data.cell_value ();\n          octave_value old_data = cell(row, col);\n          if (cell(row, col).is_string ())\n            {\n              cell(row, col) = edit_data;\n              if (edit_data.string_value () != old_data.string_value ())\n                {\n                  m_curData = octave_value (cell);\n                  Q_EMIT gh_set_event (m_handle, \"data\", octave_value (cell),\n                                       false);\n                }\n\n              octave_value error = octave_value (\"\");\n              sendCellEditCallback (row, col,\n                                    old_data,\n                                    edit_data,\n                                    edit_data,\n                                    error);\n              ok = true;\n            }\n          else\n            {\n              cell(row, col) = attempt_type_conversion (edit_data, old_data);\n\n              // Inform the QTableWidget of our change\n              updateData (row, col, cell(row, col),\n                          columnformat (col), columneditable (col));\n\n              m_curData = octave_value (cell);\n              Q_EMIT gh_set_event (m_handle, \"data\", octave_value (cell),\n                                   false);\n\n              octave_value error = octave_value (\"\");\n              sendCellEditCallback (row,\n                                    col,\n                                    old_data,\n                                    cell(row, col),\n                                    edit_data,\n                                    error);\n              ok = true;\n            }\n        }\n      else\n        {\n          octave_value old_data = data.is_matrix_type ()\n                                  ? data.fast_elem_extract (row + col * data.rows ())\n                                  : octave_value ();\n          data.fast_elem_insert (row + col * data.rows (),\n                                 attempt_type_conversion (edit_data, old_data));\n\n          // Inform the QTableWidget of our change\n          updateData (row,\n                      col,\n                      data.fast_elem_extract (row + col * data.rows ()),\n                      columnformat (col),\n                      columneditable (col));\n\n          m_curData = octave_value (data);\n          Q_EMIT gh_set_event (m_handle, \"data\", data, false);\n\n          octave_value error = octave_value (\"\");\n          sendCellEditCallback (row,\n                                col,\n                                old_data,\n                                data.fast_elem_extract (row + col * data.rows ()),\n                                edit_data,\n                                error);\n          ok = true;\n        }\n    }\n  else\n    {\n      // Reset the QTableWidgetItem\n      updateData (row, col, octave_value (\"\"), columnformat (col),\n                  columneditable (col));\n\n      octave_value error =\n        octave_value (\"Table data is not editable at this location.\");\n      sendCellEditCallback (row,\n                            col,\n                            octave_value (),\n                            octave_value (),\n                            edit_data,\n                            error);\n    }\n\n  if (! ok)\n    {\n      comboBox->setCurrentIndex (-1);\n      comboBox->setEditable (true);\n      comboBox->setEditText (comboBox->property (\"original_value\").toString ());\n      comboBox->lineEdit ()->setReadOnly (true);\n    }\n  m_blockUpdates = false;\n}\n\nvoid\nTable::checkBoxClicked (int row, int col, QCheckBox *checkBox)\n{\n  if (m_blockUpdates)\n    return;\n  m_blockUpdates = true;\n\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  bool new_value = ! checkBox->isChecked ();\n\n  octave_value data = octave_value (m_curData);\n  if (data.islogical ())\n    {\n      // EASY WE JUST CONVERT\n      boolMatrix matrix = data.bool_matrix_value ();\n      if (row < matrix.rows () && col < matrix.columns ())\n        {\n          bool old_value = matrix(row, col);\n          matrix(row, col) = new_value;\n          checkBox->setChecked (new_value);\n          if (new_value != old_value)\n            {\n              m_curData = octave_value (matrix);\n              Q_EMIT gh_set_event (m_handle, \"data\", octave_value (matrix),\n                                   false);\n            }\n\n          sendCellEditCallback (row, col,\n                                octave_value (old_value),\n                                octave_value (new_value),\n                                octave_value (new_value),\n                                octave_value (\"\"));\n\n        }\n      else\n        {\n          sendCellEditCallback (row,\n                                col,\n                                octave_value (),\n                                octave_value (),\n                                octave_value (new_value),\n                                octave_value (\"Table data is not editable at this location.\"));\n        }\n    }\n  else if (data.iscell ())\n    {\n      Cell cell = data.cell_value ();\n      if (row < cell.rows () && col < cell.columns ())\n        {\n          if (cell(row, col).islogical ())\n            {\n              bool old_value = cell(row, col).bool_value ();\n              cell(row, col) = octave_value (new_value);\n              checkBox->setChecked (new_value);\n              if (new_value != old_value)\n                {\n                  m_curData = octave_value (cell);\n                  Q_EMIT gh_set_event (m_handle, \"data\", octave_value (cell),\n                                       false);\n                }\n\n              sendCellEditCallback (row,\n                                    col,\n                                    octave_value (old_value),\n                                    octave_value (new_value),\n                                    octave_value (new_value),\n                                    octave_value (\"\"));\n            }\n          else\n            {\n              sendCellEditCallback (row,\n                                    col,\n                                    cell(row, col),\n                                    octave_value (),\n                                    octave_value (new_value),\n                                    octave_value (\"Cannot convert logical edit to other type.\"));\n            }\n        }\n      else\n        {\n          sendCellEditCallback (row,\n                                col,\n                                cell(row, col),\n                                octave_value (),\n                                octave_value (new_value),\n                                octave_value (\"Table data is not editable at this location.\"));\n        }\n    }\n  else if (data.is_matrix_type ())\n    {\n      if (row < data.rows () && col < data.columns ())\n        {\n          sendCellEditCallback (row,\n                                col,\n                                data.fast_elem_extract (row + col * data.rows ()),\n                                octave_value (),\n                                octave_value (new_value),\n                                octave_value (\"Cannot convert logical edit to other type.\"));\n        }\n      else\n        {\n          sendCellEditCallback (row,\n                                col,\n                                data.fast_elem_extract (row + col * data.rows ()),\n                                octave_value (),\n                                octave_value (new_value),\n                                octave_value (\"Table data is not editable at this location.\"));\n        }\n    }\n  m_blockUpdates = false;\n}\n\nvoid\nTable::itemChanged (QTableWidgetItem *item)\n{\n  if (m_blockUpdates)\n    return;\n  m_blockUpdates = true;\n\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  octave_value data = octave_value (m_curData);\n\n  int row = item->row ();\n  int col = item->column ();\n  octave_value edit_data = octave_value (Utils::toStdString (item->text ()));\n  octave_value new_value;\n  octave_value old_value;\n  octave_value new_data;\n\n  if (row < data.rows () && col < data.columns ())\n    {\n      if (data.iscell ())\n        {\n          old_value = data.cell_value () (row, col);\n        }\n      else if (data.is_matrix_type ())\n        {\n          old_value = data.fast_elem_extract (row + col * data.rows ());\n        }\n\n      // Now we need to coerce the new_value in to the type of the old_value\n      if (old_value.is_string ())\n        new_value = edit_data;\n      else\n        {\n          new_value = attempt_type_conversion (edit_data, old_value);\n          std::pair<Qt::AlignmentFlag, QString> flag_and_text =\n            qStringValueFor (new_value, columnformat (col));\n          item->setTextAlignment (flag_and_text.first);\n          item->setText (flag_and_text.second);\n        }\n\n      if (data.iscell ())\n        {\n          Cell cell = data.cell_value ();\n          cell(row, col) = new_value;\n          new_data = octave_value (cell);\n        }\n      else\n        {\n          data.fast_elem_insert (row + col * data.rows (), new_value);\n          new_data = data;\n        }\n      m_curData = octave_value (new_data);\n      Q_EMIT gh_set_event (m_handle, \"data\", new_data, false);\n\n      sendCellEditCallback (row,\n                            col,\n                            octave_value (old_value),\n                            octave_value (new_value),\n                            octave_value (new_value),\n                            octave_value (\"\"));\n    }\n  else\n    {\n      item->setText (\"\");\n\n      octave_value error =\n        octave_value (\"Table data is not editable at this location.\");\n      sendCellEditCallback (row,\n                            col,\n                            octave_value (),\n                            octave_value (),\n                            edit_data,\n                            error);\n    }\n\n  m_blockUpdates = false;\n}\n\nvoid\nTable::redraw ()\n{\n  update (uitable::properties::ID_POSITION);\n}\n\nvoid\nTable::update (int pId)\n{\n  uitable::properties& tp = properties<uitable> ();\n\n  switch (pId)\n    {\n    case uitable::properties::ID_BACKGROUNDCOLOR:\n    case uitable::properties::ID_FOREGROUNDCOLOR:\n      updatePalette ();\n      break;\n\n    case uitable::properties::ID_COLUMNNAME:\n      updateColumnname ();\n      updateColumnwidth ();\n      break;\n\n    case uitable::properties::ID_COLUMNWIDTH:\n      updateColumnwidth ();\n      break;\n\n    case uitable::properties::ID_COLUMNEDITABLE:\n    case uitable::properties::ID_COLUMNFORMAT:\n    case uitable::properties::ID_DATA:\n      m_blockUpdates = true;\n      m_curData = octave_value (tp.get_data ());\n      updateData ();\n      updateRowname ();\n      updateColumnname ();\n      updateColumnwidth ();\n      updateEnable ();\n      m_blockUpdates = false;\n      break;\n\n    case uitable::properties::ID_ENABLE:\n      updateEnable ();\n      break;\n\n    case uitable::properties::ID_KEYPRESSFCN:\n      m_keyPressHandlerDefined = ! tp.get_keypressfcn ().isempty ();\n      break;\n\n    case uitable::properties::ID_KEYRELEASEFCN:\n      m_keyReleaseHandlerDefined = ! tp.get_keyreleasefcn ().isempty ();\n      break;\n\n    case uitable::properties::ID_FONTNAME:\n    case uitable::properties::ID_FONTSIZE:\n    case uitable::properties::ID_FONTWEIGHT:\n    case uitable::properties::ID_FONTANGLE:\n      if (m_tableWidget)\n        {\n          m_tableWidget->setFont (Utils::computeFont<uitable> (tp));\n          for (int row = 0; row < m_tableWidget->rowCount (); row++)\n            {\n              m_tableWidget->setRowHeight (row, AUTO_HEIGHT);\n            }\n        }\n      break;\n\n    case uitable::properties::ID_POSITION:\n      {\n        Matrix bb = tp.get_boundingbox (false);\n        m_tableWidget->setGeometry (octave::math::round (bb(0)),\n                                    octave::math::round (bb(1)),\n                                    octave::math::round (bb(2)),\n                                    octave::math::round (bb(3)));\n        updateExtent ();\n      }\n      break;\n\n    case uitable::properties::ID_REARRANGEABLECOLUMNS:\n      updateRearrangeableColumns ();\n      break;\n\n    case uitable::properties::ID_ROWNAME:\n      updateRowname ();\n      break;\n\n    case uitable::properties::ID_ROWSTRIPING:\n      updatePalette ();\n      break;\n\n    case uitable::properties::ID_TOOLTIPSTRING:\n      m_tableWidget->setToolTip (Utils::fromStdString (tp.get_tooltipstring ()));\n      break;\n\n    case base_properties::ID_VISIBLE:\n      m_tableWidget->setVisible (tp.is_visible ());\n      break;\n\n    default:\n      break;\n\n    }\n}\n\nvoid\nTable::updateColumnname ()\n{\n  uitable::properties& tp = properties<uitable> ();\n\n  // Reset the Column Count\n  m_tableWidget->setColumnCount (tp.get_data ().columns ());\n\n  octave_value columnname = tp.get_columnname ();\n  QStringList l;\n  bool visible = true;\n\n  if (columnname.is_string () && columnname.string_value (false) == \"numbered\")\n    for (int i = 0; i < m_tableWidget->columnCount (); i++)\n      l << QString::number (i + 1);\n  else if (columnname.is_string ())\n    {\n      if (m_tableWidget->columnCount () > 0)\n        l << Utils::fromStdString (columnname.string_value ());\n      for (int i = 1; i < m_tableWidget->columnCount (); i++)\n        l << \"\";\n    }\n  else if (columnname.isempty ())\n    {\n      for (int i = 0; i < m_tableWidget->columnCount (); i++)\n        l << \"\";\n\n      visible = false;\n    }\n  else if (columnname.iscell ())\n    {\n      octave_idx_type n = columnname.numel ();\n      Cell cell_value = columnname.cell_value ();\n      octave_idx_type i = 0;\n\n      for (; i < n; i++)\n        {\n          octave_value v = cell_value(i);\n          if (v.is_string ())\n            l << Utils::fromStdString (v.string_value (true));\n          else if (v.is_matrix_type ())\n            {\n              Matrix data = v.matrix_value ();\n\n              if (data.isempty ())\n                l << \"\";\n              /* Now Matlab does something very strange here:\n               * If data is a row or column matrix,\n               * then each datapoint is added.\n               * Otherwise, nothing is set.  */\n              else if (data.rows () > 1 && data.cols () > 1)\n                l << \"\";\n              else\n                for (octave_idx_type j = 0; j < data.numel (); j++)\n                  l << QString::number (data(j));\n            }\n          else if (v.isnumeric ())\n            l << QString::number (v.double_value ());\n          // FIXME: Should this just be an error?  struct or cell at this point.\n          else\n            l << QString::number (v.double_value ());\n        }\n      // Any remaining columns are unlabeled\n      for (; i < m_tableWidget->columnCount (); i++)\n        l << \"\";\n    }\n  else if (columnname.is_matrix_type () || columnname.is_scalar_type ())\n    {\n      octave_idx_type n = columnname.numel ();\n      Matrix matrix_value = columnname.matrix_value ();\n      octave_idx_type i = 0;\n\n      for (; i < n; i++)\n        l << QString::number (matrix_value(i));\n      for (; i < m_tableWidget->columnCount (); i++)\n        l << \"\";\n    }\n  else\n    {\n      // FIXME: Would it be better to error here when unknown value found?\n      for (int i = 0; i < m_tableWidget->columnCount (); i++)\n        l << \"\";\n      visible = false;\n    }\n\n  l.replaceInStrings (\"|\", \"\\n\");\n\n  // Now add the columns as required\n  if (m_tableWidget->columnCount () < l.length ())\n    {\n      int oldColumnCount = m_tableWidget->columnCount ();\n      m_tableWidget->setColumnCount (l.length ());\n      for (int col = oldColumnCount; col < l.length (); col++)\n        {\n          std::string format = columnformat (col);\n          bool enabled = columneditable (col);\n\n          for (int row = 0; row < m_tableWidget->rowCount (); row++)\n            updateData (row, col, octave_value (\"\"), format, enabled);\n        }\n    }\n\n  m_tableWidget->setHorizontalHeaderLabels (l);\n  m_tableWidget->horizontalHeader ()->setVisible (visible);\n}\n\nvoid\nTable::updateColumnwidth ()\n{\n  uitable::properties& tp = properties<uitable> ();\n\n  octave_value columnwidth = tp.get_columnwidth ();\n  if (columnwidth.isempty ())\n    {\n      for (int i = 0; i < m_tableWidget->columnCount (); i++)\n        m_tableWidget->setColumnWidth (i, AUTO_WIDTH);\n    }\n  else if (columnwidth.is_string ())\n    {\n      std::string option = columnwidth.string_value (false);\n      if (option == \"auto\")\n        {\n          for (int i = 0; i < m_tableWidget->columnCount (); i++)\n            m_tableWidget->setColumnWidth (i, AUTO_WIDTH);\n        }\n      else if (option == \"fit\")\n        {\n          for (int i = 0; i < m_tableWidget->columnCount (); i++)\n            {\n              int column_size = (qobject_cast<QAbstractItemView *> (m_tableWidget))->sizeHintForColumn (i);\n              int header_size = m_tableWidget->horizontalHeader ()->sectionSizeHint (i);\n\n              if (column_size > header_size)\n                m_tableWidget->setColumnWidth (i, column_size);\n              else\n                m_tableWidget->setColumnWidth (i, header_size);\n            }\n        }\n    }\n  else if (columnwidth.iscell ())\n    {\n      Cell cell_value = columnwidth.cell_value ();\n      int i = 0;\n      for (; i < m_tableWidget->columnCount () && i < cell_value.numel (); i++)\n        {\n          octave_value v = cell_value (i);\n          if (v.is_string ())\n            {\n              std::string option = v.string_value (false);\n              if (option == \"auto\")\n                m_tableWidget->setColumnWidth (i, AUTO_WIDTH);\n              else if (option == \"fit\")\n                {\n                  int column_size = (qobject_cast<QAbstractItemView *> (m_tableWidget))->sizeHintForColumn (i);\n                  int header_size = m_tableWidget->horizontalHeader ()->sectionSizeHint (i);\n\n                  if (column_size > header_size)\n                    m_tableWidget->setColumnWidth (i, column_size);\n                  else\n                    m_tableWidget->setColumnWidth (i, header_size);\n                }\n            }\n          else\n            {\n              int w = int (v.double_value ());\n              m_tableWidget->setColumnWidth (i, w);\n            }\n        }\n      // Remaining columns use \"auto\" width for Matlab compatibility.\n      for (; i < m_tableWidget->columnCount (); i++)\n        m_tableWidget->setColumnWidth (i, AUTO_WIDTH);\n    }\n  else if (columnwidth.is_matrix_type ())\n    {\n      // FIXME: 2025/10/27: Added call to error_impossible().\n      //        If no bug reports for 2 years, remove code entirely.\n      error_impossible ();\n    }\n}\n\nbool inline\nTable::columneditable (int col)\n{\n  uitable::properties& tp = properties<uitable> ();\n  boolNDArray columneditable = tp.get_columneditable ().bool_array_value ();\n  bool editable = false;\n\n  if (! columneditable.isempty () && col < columneditable.numel ())\n    editable = columneditable.xelem (col);\n  else if (! columneditable.isempty () && columneditable.numel () == 1)\n    editable = columneditable.xelem (0);\n\n  return editable;\n}\n\nstd::string inline\nTable::columnformat (int col)\n{\n  uitable::properties& tp = properties<uitable> ();\n  std::string format = \"\";\n  octave_value ov_columnformat = tp.get_columnformat ();\n\n  if (ov_columnformat.iscell ())\n    {\n      Cell columnformat = ov_columnformat.cell_value ();\n      if (! columnformat.isempty () && col < columnformat.numel ())\n        {\n          octave_value format_value = columnformat.xelem (col);\n\n          if (! format_value.isempty () && format_value.is_string ())\n            format = format_value.string_value ();\n          else if (! format_value.isempty () && format_value.iscell ())\n            format = \"popup\";\n        }\n    }\n  else if (ov_columnformat.is_string ())\n    {\n      format = ov_columnformat.string_value ();\n    }\n  return format;\n}\n\nvoid inline\nTable::updateDataColumn (int col)\n{\n  octave_value data = properties<uitable> ().get_data ();\n\n  std::string format = columnformat (col);\n  bool is_editable = columneditable (col);\n\n  for (octave_idx_type row = 0; row < data.rows (); row++)\n    updateData (row,\n                col,\n                data.iscell ()\n                ? data.cell_value () (row, col)\n                : data.fast_elem_extract (row + col * data.rows ()),\n                format,\n                is_editable);\n}\n\nvoid inline\nTable::updateData (int row, int col)\n{\n  octave_value data = properties<uitable> ().get_data ();\n  updateData (row,\n              col,\n              data.iscell ()\n              ? data.cell_value () (row, col)\n              : data.fast_elem_extract (row + col * data.rows ()),\n              columnformat (col),\n              columneditable (col));\n}\n\nvoid inline\nTable::updateData (int row, int col, octave_value value,\n                   std::string format = \"\", bool enabled = false)\n{\n  if (format == \"logical\" || (format == \"\" && value.islogical ()))\n    {\n      if (m_tableWidget->item (row, col))\n        delete m_tableWidget->item (row, col);\n\n      m_tableWidget->setCellWidget (row, col, checkBoxForLogical (value, enabled));\n      m_tableWidget->cellWidget (row, col)->setProperty (\"row\", QVariant (row));\n      m_tableWidget->cellWidget (row, col)->setProperty (\"col\", QVariant (col));\n    }\n  else if (format == \"popup\" && enabled)\n    {\n      if (m_tableWidget->item (row, col))\n        delete m_tableWidget->item (row, col);\n\n      QString string_value = qStringValueFor (value, format).second;\n      uitable::properties& tp = properties<uitable> ();\n      octave_value format_value = tp.get_columnformat ().cell_value ().xelem (col);\n\n      QComboBox *comboBox = new QComboBox ();\n      comboBox->setProperty (\"row\", QVariant (row));\n      comboBox->setProperty (\"col\", QVariant (col));\n\n      int index = -1;\n      for (int k = 0; k < format_value.numel (); k++)\n        {\n          QString popup_item\n            = Utils::fromStdString (format_value.fast_elem_extract (k).string_value ());\n\n          comboBox->addItem (popup_item);\n\n          if (popup_item == string_value)\n            index = k;\n        }\n      comboBox->setCurrentIndex (index);\n\n      if (index < 0)\n        {\n          comboBox->setEditable (true);\n          comboBox->setEditText (string_value);\n          comboBox->lineEdit ()->setReadOnly (true);\n        }\n\n      comboBox->setProperty (\"original_value\", QVariant (string_value));\n\n      comboBox->installEventFilter (this);\n      m_tableWidget->setCellWidget (row, col, comboBox);\n      connect (comboBox, &QComboBox::currentTextChanged,\n               this, &Table::comboBoxCurrentIndexChanged);\n    }\n  else\n    {\n      if (m_tableWidget->cellWidget (row, col))\n        delete m_tableWidget->cellWidget (row, col);\n      m_tableWidget->setItem (row, col, itemFor (value, format, enabled));\n    }\n}\n\nvoid\nTable::updateData ()\n{\n  uitable::properties& tp = properties<uitable> ();\n\n  octave_value data = tp.get_data ();\n\n  m_tableWidget->setRowCount (data.rows ());\n  m_tableWidget->setColumnCount (data.columns ());\n\n  for (octave_idx_type col = 0; col < data.columns (); col++)\n    updateDataColumn (col);\n\n  for (octave_idx_type row = 0; row < m_tableWidget->rowCount (); row++)\n    m_tableWidget->setRowHeight (row, AUTO_HEIGHT);\n}\n\nvoid\nTable::updateEnable ()\n{\n  uitable::properties& tp = properties<uitable> ();\n  bool enabled = tp.is_enable ();\n  m_tableWidget->setEnabled (enabled);\n\n  bool rearrangeableColumns = tp.is_rearrangeablecolumns ();\n\n  // Set selection mode\n  m_tableWidget->setSelectionMode (enabled\n                                   ? QAbstractItemView::ExtendedSelection\n                                   : QAbstractItemView::NoSelection);\n\n  // Set rearrangeablecolumns\n  m_tableWidget->horizontalHeader ()->setSectionsMovable (enabled && rearrangeableColumns);\n  m_tableWidget->horizontalHeader ()->setDragEnabled (enabled && rearrangeableColumns);\n  m_tableWidget->horizontalHeader ()->setDragDropMode (QAbstractItemView::InternalMove);\n\n  // Turn off column editable\n  for (int col = 0; col < m_tableWidget->columnCount (); col++)\n    {\n      bool editable = columneditable (col);\n\n      for (int row = 0; row < m_tableWidget->rowCount (); row++)\n        if (QTableWidgetItem *item = m_tableWidget->item (row, col))\n          {\n            Qt::ItemFlags flags = item->flags ();\n            if (enabled && editable)\n              item->setFlags (flags | Qt::ItemIsEditable);\n            else\n              item->setFlags (flags & ~Qt::ItemIsEditable);\n          }\n        else if (QWidget *widget = m_tableWidget->cellWidget (row, col))\n          {\n            QCheckBox *checkBox = nullptr;\n            if (widget && ! widget->children ().isEmpty ())\n              {\n                QHBoxLayout *layout\n                  = qobject_cast<QHBoxLayout *> (widget->children ().first ());\n\n                if (layout && layout->count () > 0)\n                  checkBox = qobject_cast<QCheckBox *> (layout->itemAt (0)-> widget ());\n              }\n\n            if (checkBox)\n              widget->setProperty (\"Enabled\", QVariant (enabled & editable));\n            else\n              {\n                widget->setAttribute (Qt::WA_TransparentForMouseEvents,\n                                      !(editable & enabled));\n\n                widget->setFocusPolicy (Qt::NoFocus);\n              }\n          }\n    }\n}\n\nvoid\nTable::updateExtent ()\n{\n  QSize s = realQSizeForTable (m_tableWidget);\n  Matrix extent = Matrix (1, 4);\n  extent(0, 0) = 0;\n  extent(0, 1) = 0;\n  extent(0, 2) = s.width ();\n  extent(0, 3) = s.height () ;\n  graphics_object go = object ();\n  Q_EMIT gh_set_event (go.get_handle (), \"extent\", extent, false);\n}\n\nvoid\nTable::updatePalette ()\n{\n  uitable::properties& tp = properties<uitable> ();\n\n  QPalette p = m_tableWidget->palette ();\n  p.setColor (QPalette::Text,\n              Utils::fromRgb (tp.get_foregroundcolor_rgb ()));\n  p.setColor (QPalette::Base,\n              Utils::fromRgb (tp.get_backgroundcolor_rgb ()));\n  p.setColor (QPalette::AlternateBase,\n              Utils::fromRgb (tp.get_alternatebackgroundcolor_rgb ()));\n  m_tableWidget->setPalette (p);\n  m_tableWidget->setAlternatingRowColors (tp.is_rowstriping ());\n  // FIXME: Handle multiple alternating background colors\n}\n\nvoid\nTable::updateRowname ()\n{\n  uitable::properties& tp = properties<uitable> ();\n\n  // Reset the row count\n  m_tableWidget->setRowCount (tp.get_data ().rows ());\n\n  octave_value rowname = tp.get_rowname ();\n  QStringList l;\n  bool visible = true;\n\n  if (rowname.is_string () && rowname.string_value (false) == \"numbered\")\n    for (int i = 0; i < m_tableWidget->rowCount (); i++)\n      l << QString::number (i + 1);\n  else if (rowname.is_string ())\n    {\n      if (m_tableWidget->rowCount () > 0)\n        l << Utils::fromStdString (rowname.string_value ());\n      for (int i = 1; i < m_tableWidget->rowCount (); i++)\n        l << \"\";\n    }\n  else if (rowname.isempty ())\n    {\n      for (int i = 0; i < m_tableWidget->rowCount (); i++)\n        l << \"\";\n      visible = false;\n    }\n  else if (rowname.iscell ())\n    {\n      octave_idx_type n = rowname.numel ();\n      Cell cell_value = rowname.cell_value ();\n      octave_idx_type i = 0;\n\n      for (; i < n; i++)\n        {\n          octave_value v = cell_value(i);\n          if (v.is_string ())\n            l << Utils::fromStdString (v.string_value (true));\n          else if (v.is_matrix_type ())\n            {\n              Matrix data = v.matrix_value ();\n\n              if (data.isempty ())\n                l << \"\";\n              /* Now Matlab does something very strange here:\n               * If data is a row or column matrix,\n               * then each datapoint is added.\n               * Otherwise, nothing is set.  */\n              else if (data.rows () > 1 && data.cols () > 1)\n                l << \"\";\n              else\n                for (octave_idx_type j = 0; j < data.numel (); j++)\n                  l << QString::number (data(j));\n            }\n          else if (v.isnumeric ())\n            l << QString::number (v.double_value (true));\n          // FIXME: Should this just be an error?  struct or cell at this point.\n          else\n            l << QString::number (v.double_value (true));\n        }\n      // Any remaining rows are unlabeled\n      for (; i < m_tableWidget->rowCount (); i++)\n        l << \"\";\n    }\n  else if (rowname.is_matrix_type () || rowname.is_scalar_type ())\n    {\n      octave_idx_type n = rowname.numel ();\n      Matrix matrix_value = rowname.matrix_value ();\n      octave_idx_type i = 0;\n\n      for (; i < n; i++)\n        l << QString::number (matrix_value(i));\n      for (; i < m_tableWidget->rowCount (); i++)\n        l << \"\";\n    }\n  else\n    {\n      // FIXME: Would it be better to error here when unknown value found?\n      for (int i = 0; i < m_tableWidget->columnCount (); i++)\n        l << \"\";\n      visible = false;\n    }\n\n  // Add dummy rows as required\n  if (m_tableWidget->rowCount () < l.length ())\n    {\n      int oldRowCount = m_tableWidget->rowCount ();\n      m_tableWidget->setRowCount (l.length ());\n\n      for (int col = 0; col < m_tableWidget->columnCount (); col++)\n        {\n          std::string format = columnformat (col);\n          bool enabled = columneditable (col);\n\n          for (int row = oldRowCount; row < l.length (); row++)\n            {\n              m_tableWidget->setRowHeight (row, AUTO_HEIGHT);\n\n              updateData (row, col, octave_value (\"\"), format, enabled);\n            }\n        }\n    }\n\n  m_tableWidget->setVerticalHeaderLabels (l);\n  m_tableWidget->verticalHeader ()->setVisible (visible);\n}\n\nvoid\nTable::updateRearrangeableColumns ()\n{\n  uitable::properties& tp = properties<uitable> ();\n\n  bool rearrangeableColumns = tp.is_rearrangeablecolumns ();\n  bool enabled = tp.is_enable ();\n\n  m_tableWidget->horizontalHeader ()->setSectionsMovable (enabled && rearrangeableColumns);\n  m_tableWidget->horizontalHeader ()->setDragEnabled (enabled && rearrangeableColumns);\n  m_tableWidget->horizontalHeader ()->setDragDropMode (QAbstractItemView::InternalMove);\n}\n\nbool\nTable::eventFilter (QObject *watched, QEvent *xevent)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  //uitable::properties& tp = properties<uitable> ();\n  if (qobject_cast<QTableWidget *> (watched))\n    {\n      switch (xevent->type ())\n        {\n        case QEvent::Resize:\n          {\n            octave::autolock guard (gh_mgr.graphics_lock ());\n\n            graphics_object go = object ();\n            if (go.valid_object ())\n              {\n                const uitable::properties& tp =\n                  Utils::properties<uitable> (go);\n                if (tp.fontunits_is (\"normalized\"))\n                  m_tableWidget->setFont (Utils::computeFont<uitable> (tp));\n              }\n          }\n          break;\n\n        case QEvent::MouseButtonPress:\n          {\n            octave::autolock guard (gh_mgr.graphics_lock ());\n\n            QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);\n            graphics_object go = object ();\n            const uitable::properties& tp =\n              Utils::properties<uitable> (go);\n            graphics_object fig = go.get_ancestor (\"figure\");\n\n            if (m->button () != Qt::LeftButton || ! tp.is_enable ())\n              {\n                Q_EMIT gh_set_event (fig.get_handle (), \"selectiontype\",\n                                     Utils::figureSelectionType (m), false);\n                Q_EMIT gh_set_event (fig.get_handle (), \"currentpoint\",\n                                     Utils::figureCurrentPoint (fig, m),\n                                     false);\n                Q_EMIT gh_callback_event (fig.get_handle (),\n                                          \"windowbuttondownfcn\");\n                Q_EMIT gh_callback_event (m_handle, \"buttondownfcn\");\n\n                if (m->button () == Qt::RightButton)\n                  ContextMenu::executeAt (m_interpreter, properties (),\n#if defined (HAVE_QSINGLEPOINTEVENT_CLASS)\n                                          m->globalPosition ().toPoint ());\n#else\n                                          m->globalPos ());\n#endif\n              }\n            else\n              {\n                Q_EMIT gh_set_event (fig.get_handle (), \"selectiontype\",\n                                     octave_value (\"normal\"), false);\n              }\n          }\n          break;\n\n        case QEvent::KeyPress:\n          {\n            QKeyEvent *k = dynamic_cast<QKeyEvent *> (xevent);\n            if (m_keyPressHandlerDefined)\n              {\n                octave::autolock guard (gh_mgr.graphics_lock ());\n\n                octave_scalar_map keyEvent = Utils::makeKeyEventStruct (k);\n                keyEvent.setfield (\"Source\",\n                                   object ().get_handle ().as_octave_value ());\n                keyEvent.setfield (\"EventName\", \"KeyPress\");\n\n                graphics_object fig = object ().get_ancestor (\"figure\");\n\n                Q_EMIT gh_set_event (fig.get_handle (), \"currentcharacter\",\n                                     keyEvent.getfield (\"Character\"), false);\n                Q_EMIT gh_callback_event (m_handle, \"keypressfcn\", keyEvent);\n              }\n            int row = m_tableWidget->currentRow ();\n            int col = m_tableWidget->currentColumn ();\n            switch (k->key ())\n              {\n              case Qt::Key_Space:\n                {\n                  QCheckBox *checkBox = nullptr;\n\n                  QWidget *widget\n                    = qobject_cast<QWidget *> (m_tableWidget->cellWidget (row, col));\n\n                  if (widget && ! widget->children ().isEmpty ())\n                    {\n                      QHBoxLayout *layout\n                        = qobject_cast<QHBoxLayout *> (widget->children ().first ());\n\n                      if (layout && layout->count () > 0)\n                        checkBox = qobject_cast<QCheckBox *> (layout->itemAt (0)-> widget ());\n                    }\n\n                  if (checkBox && checkBox->property (\"Enabled\").toBool ())\n                    checkBoxClicked (row, col, checkBox);\n\n                  QComboBox *comboBox\n                    = qobject_cast<QComboBox *> (m_tableWidget->cellWidget (row, col));\n\n                  if (comboBox)\n                    comboBox->showPopup ();\n                }\n                break;\n\n              case Qt::Key_Return:\n              case Qt::Key_Enter:\n                {\n                  if (k->modifiers () == Qt::NoModifier)\n                    {\n                      if (row + 1 < m_tableWidget->rowCount ())\n                        m_tableWidget->setCurrentCell (row + 1, col);\n                      else\n                        {\n                          if (col + 1 < m_tableWidget->columnCount ())\n                            m_tableWidget->setCurrentCell (0, col + 1);\n                          else\n                            m_tableWidget->setCurrentCell (0, 0);\n                        }\n                    }\n                  else if (k->modifiers () == Qt::ShiftModifier)\n                    {\n                      if (row - 1 >= 0)\n                        m_tableWidget->setCurrentCell (row - 1, col);\n                      else\n                        {\n                          if (col - 1 >= 0)\n                            m_tableWidget->setCurrentCell\n                            (m_tableWidget->rowCount () - 1,\n                             col - 1);\n                          else\n                            m_tableWidget->setCurrentCell\n                            (m_tableWidget->rowCount () - 1,\n                             m_tableWidget->columnCount () - 1);\n                        }\n                    }\n                }\n                break;\n\n              default:\n                break;\n              }\n          }\n          break;\n\n        case QEvent::KeyRelease:\n          {\n            if (m_keyReleaseHandlerDefined)\n              {\n                octave::autolock guard (gh_mgr.graphics_lock ());\n\n                QKeyEvent *k = dynamic_cast<QKeyEvent *> (xevent);\n\n                octave_scalar_map keyEvent = Utils::makeKeyEventStruct (k);\n                keyEvent.setfield (\"Source\",\n                                   object ().get_handle ().as_octave_value ());\n                keyEvent.setfield (\"EventName\", \"KeyRelease\");\n\n                graphics_object fig = object ().get_ancestor (\"figure\");\n\n                Q_EMIT gh_set_event (fig.get_handle (), \"currentcharacter\",\n                                     keyEvent.getfield (\"Character\"), false);\n                Q_EMIT gh_callback_event (m_handle, \"keyreleasefcn\", keyEvent);\n              }\n          }\n          break;\n\n        default:\n          break;\n        }\n    }\n  else if (qobject_cast<QComboBox *> (watched))\n    {\n      switch (xevent->type ())\n        {\n        case QEvent::MouseButtonPress:\n          {\n            octave::autolock guard (gh_mgr.graphics_lock ());\n\n            QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);\n            graphics_object go = object ();\n            const uitable::properties& tp = Utils::properties<uitable> (go);\n            graphics_object fig = go.get_ancestor (\"figure\");\n\n            if (m->button () != Qt::LeftButton || ! tp.is_enable ())\n              {\n                Q_EMIT gh_set_event (fig.get_handle (), \"selectiontype\",\n                                     Utils::figureSelectionType (m), false);\n                Q_EMIT gh_set_event (fig.get_handle (), \"currentpoint\",\n                                     Utils::figureCurrentPoint (fig, m),\n                                     false);\n                Q_EMIT gh_callback_event (fig.get_handle (),\n                                          \"windowbuttondownfcn\");\n                Q_EMIT gh_callback_event (m_handle, \"buttondownfcn\");\n\n                if (m->button () == Qt::RightButton)\n                  ContextMenu::executeAt (m_interpreter, tp,\n#if defined (HAVE_QSINGLEPOINTEVENT_CLASS)\n                                          m->globalPosition ().toPoint ());\n#else\n                                          m->globalPos ());\n#endif\n              }\n            else\n              {\n                Q_EMIT gh_set_event (fig.get_handle (), \"selectiontype\",\n                                     Utils::figureSelectionType (m), false);\n\n                QComboBox *comboBox_0 = qobject_cast<QComboBox *> (watched);\n                for (int row = 0; row < m_tableWidget->rowCount (); row++)\n                  {\n                    for (int col = 0; col < m_tableWidget->columnCount (); col++)\n                      {\n                        QComboBox *comboBox_1\n                          = qobject_cast<QComboBox *> (m_tableWidget->cellWidget (row, col));\n\n                        if (comboBox_0 == comboBox_1)\n                          m_tableWidget->setCurrentCell (row, col);\n                      }\n                  }\n              }\n          }\n          break;\n\n        default:\n          break;\n        }\n    }\n  return false;\n}\n\n#undef AUTO_HEIGHT\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/Table.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Table_h)\n#define octave_Table_h 1\n\n#include \"Object.h\"\n\nclass QCheckBox;\nclass QTableWidget;\nclass QTableWidgetItem;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass Container;\n\nclass Table : public Object\n{\n  Q_OBJECT\n\npublic:\n  Table (octave::interpreter& interp,\n         const graphics_object& go, QTableWidget *tableWidget);\n  ~Table ();\n\n  Container * innerContainer () { return m_container; }\n\n  bool eventFilter (QObject *watched, QEvent *event);\n\n  static Table *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n  void redraw ();\n  void updateColumnname ();\n  void updateColumnwidth ();\n  void updateData ();\n  void updateEnable ();\n  void updateExtent ();\n  void updatePalette ();\n  void updateRearrangeableColumns ();\n  void updateRowname ();\n\nprivate Q_SLOTS:\n  void itemChanged (QTableWidgetItem *item);\n  void comboBoxCurrentIndexChanged (const QString& value);\n  void cellClicked (int row, int col);\n  void itemSelectionChanged ();\n\nprivate:\n  Container *m_container;\n  QTableWidget *m_tableWidget;\n  octave_value m_curData;\n  bool m_blockUpdates;\n  bool m_keyPressHandlerDefined;\n  bool m_keyReleaseHandlerDefined;\n  QWidget * checkBoxForLogical (octave_value cal, bool enabled);\n  void updateData (int row, int col, octave_value value, std::string format,\n                   bool enabled);\n  void updateData (int row, int col);\n  void updateDataColumn (int col);\n  std::string columnformat (int column);\n  bool columneditable (int column);\n  void sendCellEditCallback (int row, int col, octave_value old_value,\n                             octave_value new_value, octave_value edit_data, octave_value error);\n  void checkBoxClicked (int row, int col, QCheckBox *checkBox);\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/TextControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QLabel>\n\n#include \"Container.h\"\n#include \"TextControl.h\"\n#include \"QtHandlesUtils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nTextControl *\nTextControl::create (octave::interpreter& interp, const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new TextControl (interp, go, new QLabel (container));\n    }\n\n  return nullptr;\n}\n\nTextControl::TextControl (octave::interpreter& interp,\n                          const graphics_object& go, QLabel *label)\n  : BaseControl (interp, go, label)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  label->setAutoFillBackground (true);\n  label->setTextFormat (Qt::PlainText);\n  label->setWordWrap (false);\n  label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),\n                       up.get_verticalalignment ()));\n  label->setText (Utils::fromStringVector (up.get_string_vector ()).join (\"\\n\"));\n}\n\nTextControl::~TextControl ()\n{ }\n\nvoid\nTextControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QLabel *label = qWidget<QLabel> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_STRING:\n      label->setText (Utils::fromStringVector (up.get_string_vector ()).join (\"\\n\"));\n      break;\n\n    case uicontrol::properties::ID_HORIZONTALALIGNMENT:\n    case uicontrol::properties::ID_VERTICALALIGNMENT:\n      label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),\n                           up.get_verticalalignment ()));\n      break;\n\n    default:\n      BaseControl::update (pId);\n      break;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/TextControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_TextControl_h)\n#define octave_TextControl_h 1\n\n#include \"BaseControl.h\"\n\nclass QLabel;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass TextControl : public BaseControl\n{\npublic:\n  TextControl (octave::interpreter& interp,\n               const graphics_object& go, QLabel *label);\n  ~TextControl ();\n\n  static TextControl *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/TextEdit.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QKeyEvent>\n\n#include \"TextEdit.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\nTextEdit::focusOutEvent (QFocusEvent *xevent)\n{\n  QTextEdit::focusOutEvent (xevent);\n\n  Q_EMIT editingFinished ();\n}\n\nvoid\nTextEdit::keyPressEvent (QKeyEvent *xevent)\n{\n  QTextEdit::keyPressEvent (xevent);\n\n  if ((xevent->key () == Qt::Key_Return\n       || xevent->key () == Qt::Key_Enter)\n      && xevent->modifiers () == Qt::ControlModifier)\n    Q_EMIT returnPressed ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/TextEdit.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_TextEdit_h)\n#define octave_TextEdit_h 1\n\n#include <QTextEdit>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass TextEdit : public QTextEdit\n{\n  Q_OBJECT\n\npublic:\n  TextEdit (QWidget *xparent) : QTextEdit (xparent) { }\n  ~TextEdit () = default;\n\nQ_SIGNALS:\n  void editingFinished ();\n  void returnPressed ();\n\nprotected:\n  void focusOutEvent (QFocusEvent *event);\n  void keyPressEvent (QKeyEvent *event);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/ToggleButtonControl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QPushButton>\n\n#include \"ToggleButtonControl.h\"\n#include \"ButtonGroup.h\"\n#include \"Container.h\"\n#include \"QtHandlesUtils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nToggleButtonControl *\nToggleButtonControl::create (octave::interpreter& interp,\n                             const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      Container *container = parent->innerContainer ();\n\n      if (container)\n        return new ToggleButtonControl (interp, go,\n                                        new QPushButton (container));\n    }\n\n  return nullptr;\n}\n\nToggleButtonControl::ToggleButtonControl (octave::interpreter& interp,\n                                          const graphics_object& go,\n                                          QPushButton *btn)\n  : ButtonControl (interp, go, btn)\n{\n  Object *parent = parentObject (interp, go);\n  ButtonGroup *btnGroup = dynamic_cast<ButtonGroup *>(parent);\n  if (btnGroup)\n    btnGroup->addButton (btn);\n\n  uicontrol::properties& up = properties<uicontrol> ();\n\n  btn->setCheckable (true);\n  btn->setAutoFillBackground (true);\n  octave_value cdat = up.get_cdata ();\n  QImage img = Utils::makeImageFromCData (cdat,\n                                          cdat.columns (), cdat.rows ());\n  btn->setIcon (QIcon (QPixmap::fromImage (img)));\n  btn->setIconSize (QSize (cdat.columns (), cdat.rows ()));\n}\n\nToggleButtonControl::~ToggleButtonControl ()\n{ }\n\nvoid\nToggleButtonControl::update (int pId)\n{\n  uicontrol::properties& up = properties<uicontrol> ();\n  QPushButton *btn = qWidget<QPushButton> ();\n\n  switch (pId)\n    {\n    case uicontrol::properties::ID_CDATA:\n      {\n        octave_value cdat = up.get_cdata ();\n        QImage img = Utils::makeImageFromCData (cdat,\n                                                cdat.rows (),\n                                                cdat.columns ());\n        btn->setIcon (QIcon (QPixmap::fromImage (img)));\n        btn->setIconSize (QSize (cdat.columns (), cdat.rows ()));\n      }\n      break;\n\n    default:\n      ButtonControl::update (pId);\n      break;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/ToggleButtonControl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ToggleButtonControl_h)\n#define octave_ToggleButtonControl_h 1\n\n#include \"ButtonControl.h\"\n\nclass QPushButton;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass ToggleButtonControl : public ButtonControl\n{\npublic:\n  ToggleButtonControl (octave::interpreter& interp,\n                       const graphics_object& go, QPushButton *box);\n  ~ToggleButtonControl ();\n\n  static ToggleButtonControl *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/ToggleTool.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ToggleTool.h\"\n\n#include \"ToolBarButton.cc\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nToggleTool *\nToggleTool::create (octave::interpreter& interp, const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      QWidget *parentWidget = parent->qWidget<QWidget> ();\n\n      if (parentWidget)\n        return new ToggleTool (interp, go,\n                               new QAction (parentWidget));\n    }\n\n  return nullptr;\n}\n\nToggleTool::ToggleTool (octave::interpreter& interp,\n                        const graphics_object& go, QAction *action)\n  : ToolBarButton<uitoggletool> (interp, go, action)\n{\n  uitoggletool::properties& tp = properties<uitoggletool> ();\n\n  action->setCheckable (true);\n  action->setChecked (tp.is_state ());\n\n  connect (action, &QAction::toggled, this, &ToggleTool::triggered);\n}\n\nToggleTool::~ToggleTool ()\n{ }\n\nvoid\nToggleTool::update (int pId)\n{\n  uitoggletool::properties& tp = properties<uitoggletool> ();\n  QAction *action = qWidget<QAction> ();\n\n  switch (pId)\n    {\n    case uitoggletool::properties::ID_STATE:\n      action->setChecked (tp.is_state ());\n      break;\n\n    default:\n      ToolBarButton<uitoggletool>::update (pId);\n      break;\n    }\n}\n\nvoid\nToggleTool::triggered (bool checked)\n{\n  Q_EMIT gh_set_event (m_handle, \"state\", checked, false);\n  Q_EMIT gh_callback_event (m_handle, checked ? \"oncallback\" : \"offcallback\");\n  Q_EMIT gh_callback_event (m_handle, \"clickedcallback\");\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/ToggleTool.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ToggleTool_h)\n#define octave_ToggleTool_h 1\n\n#include \"ToolBarButton.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass ToggleTool : public ToolBarButton<uitoggletool>\n{\n  Q_OBJECT\n\npublic:\n  ToggleTool (octave::interpreter& interp,\n              const graphics_object& go,\n              QAction *action);\n  ~ToggleTool ();\n\n  static ToggleTool *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\nprotected:\n  void update (int pId);\n\nprivate Q_SLOTS:\n  void triggered (bool checked);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/ToolBar.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QAction>\n#include <QActionEvent>\n#include <QApplication>\n#include <QEvent>\n#include <QIcon>\n#include <QMainWindow>\n#include <QPixmap>\n#include <QTimer>\n#include <QToolBar>\n\n#include \"Figure.h\"\n#include \"ToolBar.h\"\n#include \"QtHandlesUtils.h\"\n\n#include \"gui-preferences-global.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic QIcon makeEmptyIcon ()\n{\n  QPixmap pix (16, 16);\n\n  pix.fill (Qt::transparent);\n\n  return QIcon (pix);\n}\n\nstatic QAction *\naddEmptyAction (QToolBar *bar)\n{\n  static const QIcon empty_icon = makeEmptyIcon ();\n\n  QAction *a = bar->addAction (empty_icon, \"Empty Toolbar\");\n\n  a->setEnabled (false);\n  a->setToolTip (\"\");\n\n  return a;\n}\n\nToolBar *\nToolBar::create (octave::interpreter& interp,\n                 const graphics_object& go)\n{\n  Object *parent = parentObject (interp, go);\n\n  if (parent)\n    {\n      QWidget *parentWidget = parent->qWidget<QWidget> ();\n\n      if (parentWidget)\n        return new ToolBar (interp, go,\n                            new QToolBar (parentWidget));\n    }\n\n  return nullptr;\n}\n\nToolBar::ToolBar (octave::interpreter& interp,\n                  const graphics_object& go, QToolBar *bar)\n  : Object (interp, go, bar), m_empty (nullptr), m_figure (nullptr)\n{\n  uitoolbar::properties& tp = properties<uitoolbar> ();\n\n  bar->setFloatable (false);\n  bar->setMovable (false);\n  bar->setVisible (tp.is_visible ());\n  bar->setStyleSheet (bar->styleSheet () + global_toolbar_style);\n\n  m_empty = addEmptyAction (bar);\n\n  m_figure =\n    dynamic_cast<Figure *> (Object::fromQObject (bar->parentWidget ()));\n\n  if (m_figure)\n    m_figure->addCustomToolBar (bar, tp.is_visible (),\n                                tp.get_tag () == \"__default_toolbar__\");\n\n  bar->installEventFilter (this);\n}\n\nToolBar::~ToolBar ()\n{ }\n\nvoid\nToolBar::update (int pId)\n{\n  uitoolbar::properties& tp = properties<uitoolbar> ();\n  QToolBar *bar = qWidget<QToolBar> ();\n\n  switch (pId)\n    {\n    case base_properties::ID_VISIBLE:\n      if (m_figure)\n        m_figure->showCustomToolBar (bar, tp.is_visible ());\n      break;\n\n    default:\n      Object::update (pId);\n      break;\n    }\n}\n\nbool\nToolBar::eventFilter (QObject *watched, QEvent *xevent)\n{\n  if (watched == qObject ())\n    {\n      switch (xevent->type ())\n        {\n        case QEvent::ActionAdded:\n        case QEvent::ActionRemoved:\n          {\n            QActionEvent *ae = dynamic_cast<QActionEvent *> (xevent);\n            QToolBar *bar = qWidget<QToolBar> ();\n\n            if (ae->action () != m_empty)\n              {\n                if (xevent->type () == QEvent::ActionAdded)\n                  {\n                    if (bar->actions ().size () == 2)\n                      QTimer::singleShot (0, this, &ToolBar::hideEmpty);\n                  }\n                else\n                  {\n                    if (bar->actions ().size () == 1)\n                      m_empty->setVisible (true);\n                  }\n              }\n          }\n          break;\n\n        default:\n          break;\n        }\n    }\n\n  return false;\n}\n\nvoid\nToolBar::hideEmpty ()\n{\n  m_empty->setVisible (false);\n}\n\nvoid\nToolBar::beingDeleted ()\n{\n  if (m_figure)\n    {\n      QToolBar *bar = qWidget<QToolBar> ();\n\n      if (bar)\n        m_figure->showCustomToolBar (bar, false);\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/ToolBar.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ToolBar_h)\n#define octave_ToolBar_h 1\n\n#include \"Object.h\"\n\nclass QAction;\nclass QToolBar;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass Figure;\n\nclass ToolBar : public Object\n{\n  Q_OBJECT\n\npublic:\n  ToolBar (octave::interpreter& interp,\n           const graphics_object& go, QToolBar *bar);\n  ~ToolBar ();\n\n  static ToolBar *\n  create (octave::interpreter& interp,\n          const graphics_object& go);\n\n  Container * innerContainer () { return nullptr; }\n\n  bool eventFilter (QObject *watched, QEvent *event);\n\nprotected:\n  void update (int pId);\n  void beingDeleted ();\n\nprivate Q_SLOTS:\n  void hideEmpty ();\n\nprivate:\n  QAction *m_empty;\n  Figure *m_figure;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/ToolBarButton.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <QAction>\n#include <QIcon>\n#include <QString>\n#include <QWidget>\n\n#include \"ToolBarButton.h\"\n#include \"QtHandlesUtils.h\"\n#include \"gui-preferences-global.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T>\nToolBarButton<T>::ToolBarButton (octave::interpreter& interp,\n                                 const graphics_object& go, QAction *action)\n  : Object (interp, go, action), m_separator (nullptr)\n{\n  typename T::properties& tp = properties<T> ();\n\n  action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ()));\n  action->setVisible (tp.is_visible ());\n\n  // Get the icon data from cdata or as a named icon\n  QImage img = Utils::makeImageFromCData (tp.get_cdata (), 24, 24);\n\n  if (img.width () == 0)\n    {\n      QIcon ico;\n      std::string name = tp.get___named_icon__ ();\n      if (! name.empty ())\n        ico = get_icon (name);\n\n      action->setIcon (ico);\n    }\n  else\n    action->setIcon (QIcon (QPixmap::fromImage (img)));\n\n  if (tp.is_separator ())\n    {\n      m_separator = new QAction (action);\n      m_separator->setSeparator (true);\n      m_separator->setVisible (tp.is_visible ());\n    }\n  action->setEnabled (tp.is_enable ());\n\n  QWidget *w = qobject_cast<QWidget *> (action->parent ());\n\n  w->insertAction (w->actions ().back (), action);\n  if (m_separator)\n    w->insertAction (action, m_separator);\n}\n\ntemplate <typename T>\nToolBarButton<T>::~ToolBarButton ()\n{ }\n\ntemplate <typename T>\nvoid\nToolBarButton<T>::update (int pId)\n{\n  typename T::properties& tp = properties<T> ();\n  QAction *action = qWidget<QAction> ();\n\n  switch (pId)\n    {\n    case base_properties::ID_VISIBLE:\n      action->setVisible (tp.is_visible ());\n      if (m_separator)\n        m_separator->setVisible (tp.is_visible ());\n      break;\n\n    case T::properties::ID_TOOLTIPSTRING:\n      action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ()));\n      break;\n\n    case T::properties::ID_CDATA:\n      {\n        // Get the icon data from cdata or as a named icon\n        QImage img = Utils::makeImageFromCData (tp.get_cdata (), 24, 24);\n\n        if (img.width () == 0)\n          {\n            QIcon ico;\n            std::string name = tp.get___named_icon__ ();\n            if (! name.empty ())\n              ico = get_icon (name);\n\n            action->setIcon (ico);\n          }\n        else\n          action->setIcon (QIcon (QPixmap::fromImage (img)));\n      }\n      break;\n\n    case T::properties::ID_SEPARATOR:\n      if (tp.is_separator ())\n        {\n          if (! m_separator)\n            {\n              m_separator = new QAction (action);\n              m_separator->setSeparator (true);\n              m_separator->setVisible (tp.is_visible ());\n\n              QWidget *w = qobject_cast<QWidget *> (action->parent ());\n\n              w->insertAction (action, m_separator);\n            }\n        }\n      else\n        {\n          if (m_separator)\n            delete m_separator;\n          m_separator = nullptr;\n        }\n      break;\n\n    case T::properties::ID_ENABLE:\n      action->setEnabled (tp.is_enable ());\n      break;\n\n    default:\n      Object::update (pId);\n      break;\n    }\n}\n\ntemplate <typename T>\nQIcon\nToolBarButton<T>::get_icon (const std::string& name)\n{\n  return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE)\n                + QString::fromStdString (name) + global_icon_extension);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/ToolBarButton.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ToolBarButton_h)\n#define octave_ToolBarButton_h 1\n\n#include \"Object.h\"\n\nclass QAction;\nclass QIcon;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass Container;\n\ntemplate <typename T>\nclass ToolBarButton : public Object\n{\npublic:\n  ToolBarButton (octave::interpreter& interp,\n                 const graphics_object& go, QAction *action);\n  ~ToolBarButton ();\n\n  Container * innerContainer () { return nullptr; }\n\nprotected:\n  void update (int pId);\n\nprivate:\n  QAction *m_separator;\n\n  QIcon get_icon (const std::string& name);\n};\n\nOCTAVE_END_NAMESPACE(octave);\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/annotation-dialog.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QColorDialog>\n#include <QPushButton>\n#include <QPalette>\n\n#include \"gui-settings.h\"\n#include \"gui-preferences-gp.h\"\n#include \"gui-settings.h\"\n\n#include \"QtHandlesUtils.h\"\n#include \"annotation-dialog.h\"\n#include \"ui-annotation-dialog.h\"\n\nannotation_dialog::annotation_dialog (QWidget *p, const octave_value_list& pr):\n  QDialog (p), m_ui (new Ui::annotation_dialog)\n{\n  m_props = pr;\n\n  init ();\n}\n\nvoid\nannotation_dialog::init ()\n{\n  m_ui->setupUi (this);\n\n  octave::gui_settings settings;\n\n  // restore last geometry\n  if (settings.contains (gp_annotation_geometry.settings_key ()))\n    restoreGeometry (settings.byte_array_value (gp_annotation_geometry));\n\n  // connect signals\n  connect (m_ui->button_box, &QDialogButtonBox::clicked,\n           this, &annotation_dialog::button_clicked);\n\n  connect (m_ui->edit_string, &QLineEdit::textChanged,\n           this, &annotation_dialog::edit_string_changed);\n\n  connect (m_ui->btn_color, &QPushButton::clicked,\n           this, &annotation_dialog::prompt_for_color);\n\n  connect (m_ui->btn_background_color, &QPushButton::clicked,\n           this, &annotation_dialog::prompt_for_color);\n\n  connect (m_ui->btn_edge_color, &QPushButton::clicked,\n           this, &annotation_dialog::prompt_for_color);\n\n  // set gui element to default values\n  m_ui->cb_fit_box_to_text->setChecked (true);\n  m_ui->cb_horz_align->setCurrentIndex (m_ui->cb_horz_align->findText (\"left\"));\n  m_ui->cb_vert_align->setCurrentIndex (m_ui->cb_vert_align->findText (\"middle\"));\n\n  // set gui elements to any values from input properties\n  set_gui_props ();\n}\n\nannotation_dialog::~annotation_dialog ()\n{\n  delete m_ui;\n}\n\n// internal slots\n\nvoid\nannotation_dialog::button_clicked (QAbstractButton *button)\n{\n  QDialogButtonBox::ButtonRole button_role\n    = m_ui->button_box->buttonRole (button);\n\n  octave::gui_settings settings;\n\n  // save position\n  settings.setValue (gp_annotation_geometry.settings_key (), saveGeometry ());\n\n  if (button_role == QDialogButtonBox::ApplyRole\n      || button_role == QDialogButtonBox::AcceptRole)\n    {\n      get_gui_props ();\n    }\n\n  if (button_role == QDialogButtonBox::RejectRole\n      || button_role == QDialogButtonBox::AcceptRole)\n    close ();\n}\n\noctave_value_list\nannotation_dialog::get_properties () const\n{\n  return m_props;\n}\n\nvoid\nannotation_dialog::get_gui_props ()\n{\n  // set props to the values of the gui\n  m_props = octave_value_list ();\n\n  Matrix position (1, 4);\n  position(0) = m_ui->sb_x->value ();\n  position(1) = m_ui->sb_y->value ();\n  position(2) = m_ui->sb_width->value ();\n  position(3) = m_ui->sb_height->value ();\n  m_props.append (ovl (\"textbox\", position));\n\n  m_props.append (ovl (\"string\", m_ui->edit_string->text ().toStdString ()));\n  m_props.append (ovl (\"fitboxtotext\",\n                       m_ui->cb_fit_box_to_text->isChecked () ? \"on\" : \"off\"));\n\n  // FIXME: only \"normalized\" units is selectable, change the code below\n  //        once more units are added in the UI.\n  std::string tmpstr;\n  m_props.append (ovl (\"units\", \"normalized\"));\n\n  tmpstr = (m_ui->cb_horz_align->currentIndex () == 0 ? \"left\" :\n            (m_ui->cb_horz_align->currentIndex () == 1 ? \"center\" : \"right\"));\n  m_props.append (ovl (\"horizontalalignment\", tmpstr));\n\n  tmpstr = (m_ui->cb_vert_align->currentIndex () == 0 ? \"top\" :\n            (m_ui->cb_horz_align->currentIndex () == 1 ? \"middle\" : \"bottom\"));\n  m_props.append (ovl (\"verticalalignment\", tmpstr));\n\n  tmpstr = m_ui->cb_font_name->currentText ().toStdString ();\n  m_props.append (ovl (\"fontname\", tmpstr));\n\n  m_props.append (ovl (\"fontsize\", m_ui->sb_font_size->value ()));\n  m_props.append (ovl (\"fontweight\",\n                       m_ui->cb_font_bold->isChecked () ? \"bold\" : \"normal\"));\n  m_props.append (ovl (\"fontangle\",\n                       m_ui->cb_font_italic->isChecked () ? \"italic\" : \"normal\"));\n  m_props.append (ovl (\"color\", octave::Utils::toRgb (m_ui->btn_color->palette ().\n                       color (QPalette::Button))));\n\n  // FIXME: only \"none\" linestyle is selectable, change the code bellow\n  //        once more linestyles are added in the UI.\n  m_props.append (ovl (\"linestyle\", \"none\"));\n}\n\nvoid\nannotation_dialog::set_gui_props ()\n{\n  // set the gui to the values from the props\n  octave_idx_type len = m_props.length ();\n\n  for (int i=0; i<len/2; i++)\n    {\n      std::string name = m_props(i*2).string_value ();\n\n      if (name == \"textbox\")\n        {\n          Matrix position = m_props(2*i +1).matrix_value ();\n          int nels = position.numel ();\n          if (nels >= 2)\n            {\n              m_ui->sb_x->setValue (position(0));\n              m_ui->sb_y->setValue (position(1));\n            }\n          else\n            {\n              m_ui->sb_x->setValue (0);\n              m_ui->sb_y->setValue (0);\n            }\n          if (nels >= 4)\n            {\n              m_ui->sb_width->setValue (position(2));\n              m_ui->sb_height->setValue (position(3));\n            }\n          // FIXME: Should there be an else branch here?\n          // In annotation.m \"textbox\" is forced to have a 4-elem vector.\n        }\n      else if (name == \"string\")\n        {\n          // FIXME: handle if is array of strings ?\n          m_ui->edit_string->setText (m_props(2*i +1).string_value ().c_str ());\n        }\n      else if (name == \"fitboxtotext\")\n        {\n          m_ui->cb_fit_box_to_text->setChecked (m_props(1*i +1).string_value () == \"on\");\n        }\n      else if (name == \"units\")\n        {\n          m_ui->cb_units->setCurrentIndex\n            (m_ui->cb_units->findText (m_props(1*i +1).string_value ().c_str ()));\n        }\n      else if (name == \"horizontalalignment\")\n        {\n          m_ui->cb_horz_align->setCurrentIndex\n            (m_ui->cb_horz_align->findText (m_props(1*i +1).string_value ().c_str ()));\n        }\n      else if (name == \"verticalalignment\")\n        {\n          m_ui->cb_vert_align->setCurrentIndex\n            (m_ui->cb_vert_align->findText (m_props(1*i +1).string_value ().c_str ()));\n        }\n      else if (name == \"fontname\")\n        {\n          m_ui->cb_vert_align->setCurrentIndex\n            (m_ui->cb_font_name->findText (m_props(1*i +1).string_value ().c_str ()));\n        }\n      else if (name == \"fontsize\")\n        {\n          m_ui->sb_font_size->setValue (m_props(1*i +1).float_value ());\n        }\n      else if (name == \"fontweight\")\n        {\n          m_ui->cb_font_bold->setChecked (m_props(1*i +1).string_value () == \"bold\");\n        }\n      else if (name == \"fontangle\")\n        {\n          m_ui->cb_font_italic->setChecked (m_props(1*i +1).string_value () == \"italic\");\n        }\n      else if (name == \"color\")\n        {\n          QColor color;\n          if (m_props(1*i +1).is_matrix_type ())\n            color = octave::Utils::fromRgb (m_props(2*i +1).matrix_value ());\n          else\n#if defined (HAVE_QCOLOR_FROMSTRING)\n            color.fromString (m_props(2*i +1).string_value ());\n#else\n            color.setNamedColor (m_props(2*i +1).string_value ().c_str ());\n#endif\n\n          if (color.isValid ())\n            m_ui->btn_color->setPalette (QPalette (color));\n        }\n\n    }\n\n  edit_string_changed (m_ui->edit_string->text ());\n}\n\nvoid\nannotation_dialog::edit_string_changed (const QString& str)\n{\n  m_ui->button_box->button (QDialogButtonBox::Ok)->setEnabled (str.length () > 0);\n}\n\nvoid\nannotation_dialog::prompt_for_color ()\n{\n  QWidget *widg = dynamic_cast<QWidget *> (sender ());\n  if (widg)\n    {\n      QColor color = widg->palette ().color (QPalette::Button);\n\n      color = QColorDialog::getColor (color, this);\n\n      if (color.isValid ())\n        {\n          widg->setPalette (QPalette (color));\n\n          QString css = QString (\"background-color: %1; border: 1px solid %2;\")\n                        .arg (color.name ())\n                        .arg (\"#000000\");\n\n          widg->setStyleSheet (css);\n          widg->update ();\n        }\n    }\n}\n"
  },
  {
    "path": "libgui/graphics/annotation-dialog.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_annotation_dialog_h)\n#define octave_annotation_dialog_h 1\n\n#include <QDialog>\n#include <QLineEdit>\n#include <QAbstractButton>\n\n#include \"ovl.h\"\n\nnamespace Ui\n{\n  class annotation_dialog;\n}\n\nclass annotation_dialog : public QDialog\n{\n  Q_OBJECT\npublic:\n  annotation_dialog (QWidget *parent, const octave_value_list& pr);\n  ~annotation_dialog ();\n\n  octave_value_list get_properties () const;\n\nprivate Q_SLOTS:\n  // slots for dialog's buttons\n  void button_clicked (QAbstractButton *button);\n  void edit_string_changed (const QString& str);\n  void prompt_for_color ();\n\nprivate:\n  void init ();\n\n  void get_gui_props ();\n  void set_gui_props ();\n\n  Ui::annotation_dialog *m_ui;\n  octave_value_list m_props;\n};\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/annotation-dialog.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>annotation_dialog</class>\n <widget class=\"QDialog\" name=\"annotation_dialog\">\n  <property name=\"windowModality\">\n   <enum>Qt::WindowModal</enum>\n  </property>\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>621</width>\n    <height>401</height>\n   </rect>\n  </property>\n  <property name=\"windowTitle\">\n   <string>Annotation</string>\n  </property>\n  <layout class=\"QVBoxLayout\" name=\"verticalLayout\">\n   <item>\n    <widget class=\"QGroupBox\" name=\"groupBox\">\n     <property name=\"title\">\n      <string>Text</string>\n     </property>\n     <layout class=\"QGridLayout\" name=\"gridLayout\">\n      <item row=\"0\" column=\"0\">\n       <widget class=\"QLabel\" name=\"label\">\n        <property name=\"text\">\n         <string>String</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"1\" colspan=\"6\">\n       <widget class=\"QLineEdit\" name=\"edit_string\"/>\n      </item>\n      <item row=\"1\" column=\"0\">\n       <widget class=\"QLabel\" name=\"label_11\">\n        <property name=\"text\">\n         <string>Font</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"1\" colspan=\"2\">\n       <widget class=\"QFontComboBox\" name=\"cb_font_name\">\n        <property name=\"sizePolicy\">\n         <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n          <horstretch>0</horstretch>\n          <verstretch>0</verstretch>\n         </sizepolicy>\n        </property>\n        <property name=\"editable\">\n         <bool>false</bool>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"3\">\n       <widget class=\"QSpinBox\" name=\"sb_font_size\">\n        <property name=\"sizePolicy\">\n         <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n          <horstretch>0</horstretch>\n          <verstretch>0</verstretch>\n         </sizepolicy>\n        </property>\n        <property name=\"minimum\">\n         <number>2</number>\n        </property>\n        <property name=\"maximum\">\n         <number>96</number>\n        </property>\n        <property name=\"value\">\n         <number>10</number>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"4\">\n       <widget class=\"QPushButton\" name=\"cb_font_bold\">\n        <property name=\"toolTip\">\n         <string>bold</string>\n        </property>\n        <property name=\"text\">\n         <string>b</string>\n        </property>\n        <property name=\"checkable\">\n         <bool>true</bool>\n        </property>\n        <property name=\"autoDefault\">\n         <bool>false</bool>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"5\">\n       <widget class=\"QPushButton\" name=\"cb_font_italic\">\n        <property name=\"toolTip\">\n         <string>italic</string>\n        </property>\n        <property name=\"text\">\n         <string>i</string>\n        </property>\n        <property name=\"checkable\">\n         <bool>true</bool>\n        </property>\n        <property name=\"autoDefault\">\n         <bool>false</bool>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"6\">\n       <widget class=\"QPushButton\" name=\"btn_color\">\n        <property name=\"palette\">\n         <palette>\n          <active>\n           <colorrole role=\"WindowText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Button\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Light\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Midlight\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Dark\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Mid\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Text\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"BrightText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ButtonText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Base\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Window\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Shadow\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"AlternateBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>220</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n          </active>\n          <inactive>\n           <colorrole role=\"WindowText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Button\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Light\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Midlight\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Dark\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Mid\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Text\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"BrightText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ButtonText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Base\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Window\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Shadow\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"AlternateBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>220</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n          </inactive>\n          <disabled>\n           <colorrole role=\"WindowText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Button\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Light\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Midlight\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Dark\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Mid\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Text\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"BrightText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ButtonText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Base\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Window\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Shadow\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"AlternateBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>220</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n          </disabled>\n         </palette>\n        </property>\n        <property name=\"toolTip\">\n         <string>color</string>\n        </property>\n        <property name=\"autoFillBackground\">\n         <bool>false</bool>\n        </property>\n        <property name=\"styleSheet\">\n         <string notr=\"true\">background-color: #000000; border: 1px solid #000000;</string>\n        </property>\n        <property name=\"text\">\n         <string/>\n        </property>\n        <property name=\"autoDefault\">\n         <bool>false</bool>\n        </property>\n        <property name=\"flat\">\n         <bool>true</bool>\n        </property>\n       </widget>\n      </item>\n      <item row=\"2\" column=\"0\" colspan=\"2\">\n       <widget class=\"QLabel\" name=\"label_13\">\n        <property name=\"text\">\n         <string>Horizontal alignment</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"2\" column=\"2\">\n       <widget class=\"QComboBox\" name=\"cb_horz_align\">\n        <item>\n         <property name=\"text\">\n          <string>left</string>\n         </property>\n        </item>\n        <item>\n         <property name=\"text\">\n          <string>middle</string>\n         </property>\n        </item>\n        <item>\n         <property name=\"text\">\n          <string>right</string>\n         </property>\n        </item>\n       </widget>\n      </item>\n      <item row=\"2\" column=\"3\" colspan=\"2\">\n       <widget class=\"QLabel\" name=\"label_14\">\n        <property name=\"text\">\n         <string>Vertical alignment</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"2\" column=\"5\" colspan=\"2\">\n       <widget class=\"QComboBox\" name=\"cb_vert_align\">\n        <item>\n         <property name=\"text\">\n          <string>top</string>\n         </property>\n        </item>\n        <item>\n         <property name=\"text\">\n          <string>middle</string>\n         </property>\n        </item>\n        <item>\n         <property name=\"text\">\n          <string>bottom</string>\n         </property>\n        </item>\n       </widget>\n      </item>\n     </layout>\n    </widget>\n   </item>\n   <item>\n    <widget class=\"QGroupBox\" name=\"groupBox_2\">\n     <property name=\"title\">\n      <string>Position</string>\n     </property>\n     <layout class=\"QGridLayout\" name=\"gridLayout_2\">\n      <item row=\"0\" column=\"0\">\n       <widget class=\"QLabel\" name=\"label_21\">\n        <property name=\"text\">\n         <string>X</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"1\">\n       <widget class=\"QDoubleSpinBox\" name=\"sb_x\">\n        <property name=\"minimum\">\n         <double>0.000000000000000</double>\n        </property>\n        <property name=\"singleStep\">\n         <double>0.010000000000000</double>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"2\">\n       <widget class=\"QLabel\" name=\"label_22\">\n        <property name=\"text\">\n         <string>Y</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"3\">\n       <widget class=\"QDoubleSpinBox\" name=\"sb_y\">\n        <property name=\"minimum\">\n         <double>0.000000000000000</double>\n        </property>\n        <property name=\"singleStep\">\n         <double>0.010000000000000</double>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"4\">\n       <widget class=\"QLabel\" name=\"label_23\">\n        <property name=\"text\">\n         <string>Width</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"5\">\n       <widget class=\"QDoubleSpinBox\" name=\"sb_width\">\n        <property name=\"minimum\">\n         <double>-99.989999999999995</double>\n        </property>\n        <property name=\"singleStep\">\n         <double>0.010000000000000</double>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"6\">\n       <widget class=\"QLabel\" name=\"label_24\">\n        <property name=\"text\">\n         <string>Height</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"7\">\n       <widget class=\"QDoubleSpinBox\" name=\"sb_height\">\n        <property name=\"minimum\">\n         <double>-99.000000000000000</double>\n        </property>\n        <property name=\"singleStep\">\n         <double>0.010000000000000</double>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"0\">\n       <widget class=\"QLabel\" name=\"label_18\">\n        <property name=\"text\">\n         <string>units</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"1\" colspan=\"2\">\n       <widget class=\"QComboBox\" name=\"cb_units\">\n        <item>\n         <property name=\"text\">\n          <string>normalized</string>\n         </property>\n        </item>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"4\" colspan=\"2\">\n       <widget class=\"QCheckBox\" name=\"cb_fit_box_to_text\">\n        <property name=\"text\">\n         <string>Fit to box</string>\n        </property>\n       </widget>\n      </item>\n     </layout>\n    </widget>\n   </item>\n   <item>\n    <widget class=\"QGroupBox\" name=\"groupBox_3\">\n     <property name=\"enabled\">\n      <bool>false</bool>\n     </property>\n     <property name=\"title\">\n      <string>Box</string>\n     </property>\n     <layout class=\"QGridLayout\" name=\"gridLayout_3\">\n      <item row=\"0\" column=\"0\">\n       <widget class=\"QLabel\" name=\"label_19\">\n        <property name=\"text\">\n         <string>Background</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"1\">\n       <widget class=\"QPushButton\" name=\"btn_background_color\">\n        <property name=\"palette\">\n         <palette>\n          <active>\n           <colorrole role=\"WindowText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Button\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Light\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Midlight\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Dark\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>127</red>\n              <green>127</green>\n              <blue>127</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Mid\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>170</red>\n              <green>170</green>\n              <blue>170</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Text\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"BrightText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ButtonText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Base\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Window\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Shadow\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"AlternateBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>220</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n          </active>\n          <inactive>\n           <colorrole role=\"WindowText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Button\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Light\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Midlight\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Dark\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>127</red>\n              <green>127</green>\n              <blue>127</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Mid\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>170</red>\n              <green>170</green>\n              <blue>170</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Text\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"BrightText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ButtonText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Base\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Window\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Shadow\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"AlternateBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>220</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n          </inactive>\n          <disabled>\n           <colorrole role=\"WindowText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>127</red>\n              <green>127</green>\n              <blue>127</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Button\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Light\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Midlight\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Dark\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>127</red>\n              <green>127</green>\n              <blue>127</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Mid\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>170</red>\n              <green>170</green>\n              <blue>170</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Text\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>127</red>\n              <green>127</green>\n              <blue>127</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"BrightText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ButtonText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>127</red>\n              <green>127</green>\n              <blue>127</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Base\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Window\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Shadow\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"AlternateBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>255</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipBase\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>255</red>\n              <green>255</green>\n              <blue>220</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"ToolTipText\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n          </disabled>\n         </palette>\n        </property>\n        <property name=\"autoFillBackground\">\n         <bool>false</bool>\n        </property>\n        <property name=\"styleSheet\">\n         <string notr=\"true\">background-color: #ffffff; border: 1px solid #000000;</string>\n        </property>\n        <property name=\"text\">\n         <string/>\n        </property>\n        <property name=\"autoDefault\">\n         <bool>false</bool>\n        </property>\n        <property name=\"flat\">\n         <bool>true</bool>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"2\">\n       <widget class=\"QLabel\" name=\"label_20\">\n        <property name=\"text\">\n         <string>Edge</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"3\" colspan=\"2\">\n       <widget class=\"QPushButton\" name=\"btn_edge_color\">\n        <property name=\"palette\">\n         <palette>\n          <active>\n           <colorrole role=\"Button\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Base\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Window\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n          </active>\n          <inactive>\n           <colorrole role=\"Button\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Base\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Window\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n          </inactive>\n          <disabled>\n           <colorrole role=\"Button\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Base\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n           <colorrole role=\"Window\">\n            <brush brushstyle=\"SolidPattern\">\n             <color alpha=\"255\">\n              <red>0</red>\n              <green>0</green>\n              <blue>0</blue>\n             </color>\n            </brush>\n           </colorrole>\n          </disabled>\n         </palette>\n        </property>\n        <property name=\"autoFillBackground\">\n         <bool>false</bool>\n        </property>\n        <property name=\"styleSheet\">\n         <string notr=\"true\">background-color: #000000; border: 1px solid #000000;</string>\n        </property>\n        <property name=\"text\">\n         <string/>\n        </property>\n        <property name=\"autoDefault\">\n         <bool>false</bool>\n        </property>\n        <property name=\"flat\">\n         <bool>true</bool>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"5\" colspan=\"2\">\n       <spacer name=\"horizontalSpacer_2\">\n        <property name=\"orientation\">\n         <enum>Qt::Horizontal</enum>\n        </property>\n        <property name=\"sizeHint\" stdset=\"0\">\n         <size>\n          <width>167</width>\n          <height>20</height>\n         </size>\n        </property>\n       </spacer>\n      </item>\n      <item row=\"1\" column=\"0\">\n       <widget class=\"QLabel\" name=\"label_15\">\n        <property name=\"text\">\n         <string>Line style</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"1\">\n       <widget class=\"QComboBox\" name=\"cb_line_style\">\n        <item>\n         <property name=\"text\">\n          <string>none</string>\n         </property>\n        </item>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"2\" colspan=\"2\">\n       <widget class=\"QLabel\" name=\"label_16\">\n        <property name=\"text\">\n         <string>Line width</string>\n        </property>\n        <property name=\"alignment\">\n         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"4\" colspan=\"2\">\n       <widget class=\"QSpinBox\" name=\"sb_line_width\">\n        <property name=\"sizePolicy\">\n         <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n          <horstretch>0</horstretch>\n          <verstretch>0</verstretch>\n         </sizepolicy>\n        </property>\n        <property name=\"minimum\">\n         <number>2</number>\n        </property>\n        <property name=\"maximum\">\n         <number>96</number>\n        </property>\n        <property name=\"value\">\n         <number>10</number>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"6\">\n       <spacer name=\"horizontalSpacer\">\n        <property name=\"orientation\">\n         <enum>Qt::Horizontal</enum>\n        </property>\n        <property name=\"sizeHint\" stdset=\"0\">\n         <size>\n          <width>137</width>\n          <height>20</height>\n         </size>\n        </property>\n       </spacer>\n      </item>\n     </layout>\n    </widget>\n   </item>\n   <item>\n    <widget class=\"QDialogButtonBox\" name=\"button_box\">\n     <property name=\"orientation\">\n      <enum>Qt::Horizontal</enum>\n     </property>\n     <property name=\"standardButtons\">\n      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>\n     </property>\n    </widget>\n   </item>\n  </layout>\n </widget>\n <tabstops>\n  <tabstop>edit_string</tabstop>\n  <tabstop>cb_font_name</tabstop>\n  <tabstop>cb_font_bold</tabstop>\n  <tabstop>cb_font_italic</tabstop>\n  <tabstop>sb_font_size</tabstop>\n  <tabstop>cb_horz_align</tabstop>\n  <tabstop>cb_vert_align</tabstop>\n  <tabstop>cb_units</tabstop>\n  <tabstop>cb_fit_box_to_text</tabstop>\n  <tabstop>btn_edge_color</tabstop>\n  <tabstop>button_box</tabstop>\n </tabstops>\n <resources/>\n <connections>\n  <connection>\n   <sender>button_box</sender>\n   <signal>accepted()</signal>\n   <receiver>annotation_dialog</receiver>\n   <slot>accept()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>242</x>\n     <y>339</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>157</x>\n     <y>274</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>button_box</sender>\n   <signal>rejected()</signal>\n   <receiver>annotation_dialog</receiver>\n   <slot>reject()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>310</x>\n     <y>339</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>286</x>\n     <y>274</y>\n    </hint>\n   </hints>\n  </connection>\n </connections>\n</ui>\n"
  },
  {
    "path": "libgui/graphics/gl-select.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gl-select.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\nopengl_selector::apply_pick_matrix ()\n{\n  GLdouble p_matrix[16];\n\n  m_glfcns.glGetDoublev (GL_PROJECTION_MATRIX, p_matrix);\n  m_glfcns.glMatrixMode (GL_PROJECTION);\n  m_glfcns.glLoadIdentity ();\n\n  // The following block is equivalent to gluPickMatrix, but we avoid\n  // using glu functions so that we can call OpenGL functions through\n  // the QOpenGLFunctions class so that the OpenGL implementation may\n  // be selected dynamically.\n\n  Matrix viewport = get_viewport_scaled ();\n\n  if (m_size > 0)\n    {\n      m_glfcns.glTranslatef ((viewport(2) - 2 * (m_xp - viewport(0))) / m_size,\n                             (viewport(3) - 2 * (m_yp - viewport(1))) / m_size, 0);\n\n      m_glfcns.glScalef (viewport(2) / m_size, viewport(3) / m_size, 1.0);\n    }\n\n  m_glfcns.glMultMatrixd (p_matrix);\n  m_glfcns.glMatrixMode (GL_MODELVIEW);\n}\n\nvoid\nopengl_selector::setup_opengl_transformation (const axes::properties& props)\n{\n  opengl_renderer::setup_opengl_transformation (props);\n  apply_pick_matrix ();\n}\n\nvoid\nopengl_selector::init_marker (const std::string& m, double sz, float width)\n{\n  opengl_renderer::init_marker (m, sz, width);\n  apply_pick_matrix ();\n}\n\n# define BUFFER_SIZE 128\n\ngraphics_object\nopengl_selector::select (const graphics_object& ax, int x, int y, int flags)\n{\n  m_glfcns.glEnable (GL_DEPTH_TEST);\n  m_glfcns.glDepthFunc (GL_LEQUAL);\n\n  m_xp = x;\n  m_yp = y;\n\n  GLuint select_buffer[BUFFER_SIZE];\n\n  m_glfcns.glSelectBuffer (BUFFER_SIZE, select_buffer);\n  m_glfcns.glRenderMode (GL_SELECT);\n  m_glfcns.glInitNames ();\n\n  m_object_map.clear ();\n\n  draw (ax);\n\n  int hits = m_glfcns.glRenderMode (GL_RENDER);\n  graphics_object obj;\n\n  if (hits > 0)\n    {\n      GLuint current_minZ = 0xffffffff;\n      GLuint current_name = 0xffffffff;\n\n      for (int i = 0, j = 0; i < hits && j < BUFFER_SIZE-3; i++)\n        {\n          GLuint n = select_buffer[j++];\n          GLuint minZ = select_buffer[j++];\n\n          j++; // skip maxZ\n          if (((flags & select_last) == 0 && (minZ <= current_minZ))\n              || ((flags & select_last) != 0 && (minZ >= current_minZ)))\n            {\n              bool candidate = true;\n              GLuint name =\n                select_buffer[std::min (j + n, GLuint (BUFFER_SIZE)) - 1];\n\n              if ((flags & select_ignore_hittest) == 0)\n                {\n                  graphics_object go = m_object_map[name];\n\n                  if (! go.get_properties ().is_hittest ())\n                    candidate = false;\n                }\n\n              if (candidate)\n                {\n                  current_minZ = minZ;\n                  current_name = name;\n                }\n\n              j += n;\n            }\n          else\n            j += n;\n        }\n\n      if (current_name != 0xffffffff)\n        obj = m_object_map[current_name];\n    }\n  else if (hits < 0)\n    warning (\"opengl_selector::select: selection buffer overflow\");\n\n  m_object_map.clear ();\n\n  return obj;\n}\n\nvoid\nopengl_selector::draw (const graphics_object& go, bool toplevel)\n{\n  GLuint name = m_object_map.size ();\n\n  m_object_map[name] = go;\n  m_glfcns.glPushName (name);\n  set_selecting (true);\n  opengl_renderer::draw (go, toplevel);\n  set_selecting (false);\n  m_glfcns.glPopName ();\n}\n\nvoid\nopengl_selector::fake_text (double x, double y, double z, const Matrix& bbox,\n                            bool use_scale)\n{\n  ColumnVector xpos, xp1, xp2;\n\n  xpos = get_transform ().transform (x, y, z, use_scale);\n\n  xp1 = xp2 = xpos;\n  xp1(0) += bbox(0);\n  xp1(1) -= bbox(1);\n  xp2(0) += (bbox(0) + bbox(2));\n  xp2(1) -= (bbox(1) + bbox(3));\n\n  ColumnVector p1, p2, p3, p4;\n\n  p1 = get_transform ().untransform (xp1(0), xp1(1), xp1(2), false);\n  p2 = get_transform ().untransform (xp2(0), xp1(1), xp1(2), false);\n  p3 = get_transform ().untransform (xp2(0), xp2(1), xp1(2), false);\n  p4 = get_transform ().untransform (xp1(0), xp2(1), xp1(2), false);\n\n  m_glfcns.glBegin (GL_QUADS);\n  m_glfcns.glVertex3dv (p1.data ());\n  m_glfcns.glVertex3dv (p2.data ());\n  m_glfcns.glVertex3dv (p3.data ());\n  m_glfcns.glVertex3dv (p4.data ());\n  m_glfcns.glEnd ();\n}\n\nvoid\nopengl_selector::draw_text (const text::properties& props)\n{\n  if (props.get_string ().isempty ())\n    return;\n\n  Matrix pos = props.get_data_position ();\n  const Matrix bbox = props.get_extent_matrix ();\n\n  fake_text (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0, bbox);\n}\n\nMatrix\nopengl_selector::render_text (const std::string& txt,\n                              double x, double y, double z,\n                              int halign, int valign, double rotation)\n{\n  uint8NDArray pixels;\n  Matrix bbox (1, 4, 0.0);\n\n  // FIXME: probably more efficient to only compute bbox instead\n  //        of doing full text rendering...\n  text_to_pixels (txt, pixels, bbox, halign, valign, rotation);\n  fake_text (x, y, z, bbox, false);\n\n  return bbox;\n}\n\nvoid\nopengl_selector::draw_image (const image::properties& props)\n{\n  Matrix xd = props.get_xdata ().matrix_value ();\n  octave_idx_type nc = props.get_cdata ().columns ();\n  double x_pix_size = (nc == 1 ? 1 : (xd(1) - xd(0)) / (nc - 1));\n\n  Matrix yd = props.get_ydata ().matrix_value ();\n  octave_idx_type nr = props.get_cdata ().rows ();\n  double y_pix_size = (nr == 1 ? 1 : (yd(1) - yd(0)) / (nr - 1));\n\n  ColumnVector p1 (3, 0.0), p2 (3, 0.0), p3 (3, 0.0), p4 (3, 0.0);\n  p1(0) = xd(0) - x_pix_size/2;\n  p1(1) = yd(0) - y_pix_size/2;\n\n  p2(0) = xd(1) + x_pix_size/2;\n  p2(1) = yd(0) - y_pix_size/2;\n\n  p3(0) = xd(1) + x_pix_size/2;\n  p3(1) = yd(1) + y_pix_size/2;\n\n  p4(0) = xd(0) - x_pix_size/2;\n  p4(1) = yd(1) + y_pix_size/2;\n\n  m_glfcns.glBegin (GL_QUADS);\n  m_glfcns.glVertex3dv (p1.data ());\n  m_glfcns.glVertex3dv (p2.data ());\n  m_glfcns.glVertex3dv (p3.data ());\n  m_glfcns.glVertex3dv (p4.data ());\n  m_glfcns.glEnd ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/graphics/gl-select.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gl_select_h)\n#define octave_gl_select_h 1\n\n#include <map>\n#include <string>\n\n#include \"gl-render.h\"\n#include \"oct-opengl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nenum select_flags\n{\n  select_ignore_hittest = 0x01,\n  select_last           = 0x02\n};\n\nclass opengl_selector : public opengl_renderer\n{\npublic:\n  opengl_selector (opengl_functions& glfcns)\n    : opengl_renderer (glfcns), m_size (5)\n  { }\n\n  virtual ~opengl_selector () = default;\n\n  graphics_object select (const graphics_object& ax, int x, int y,\n                          int flags = 0);\n\n  virtual void draw (const graphics_object& go, bool toplevel = true);\n\nprotected:\n  virtual void draw_text (const text::properties& props);\n\n  virtual void draw_image (const image::properties& props);\n\n  virtual void setup_opengl_transformation (const axes::properties& props);\n\n  virtual void init_marker (const std::string& m, double size, float width);\n\n  virtual Matrix render_text (const std::string& txt,\n                              double x, double y, double z,\n                              int halign, int valign, double rotation = 0.0);\n\nprivate:\n  void apply_pick_matrix ();\n\n  void fake_text (double x, double y, double z, const Matrix& bbox,\n                  bool use_scale = true);\n\nprivate:\n  // The mouse coordinate of the selection/picking point\n  int m_xp, m_yp;\n\n  // The size (in pixels) of the picking window\n  int m_size;\n\n  // The OpenGL name mapping\n  std::map<GLuint, graphics_object> m_object_map;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/module.mk",
    "content": "OCTAVE_GUI_GRAPHICS_MOC = \\\n  %reldir%/moc-ButtonControl.cc \\\n  %reldir%/moc-ButtonGroup.cc \\\n  %reldir%/moc-Canvas.cc \\\n  %reldir%/moc-Container.cc \\\n  %reldir%/moc-ContextMenu.cc \\\n  %reldir%/moc-EditControl.cc \\\n  %reldir%/moc-Figure.cc \\\n  %reldir%/moc-FigureWindow.cc \\\n  %reldir%/moc-GLCanvas.cc \\\n  %reldir%/moc-ListBoxControl.cc \\\n  %reldir%/moc-Menu.cc \\\n  %reldir%/moc-Object.cc \\\n  %reldir%/moc-ObjectProxy.cc \\\n  %reldir%/moc-PopupMenuControl.cc \\\n  %reldir%/moc-PushTool.cc \\\n  %reldir%/moc-SliderControl.cc \\\n  %reldir%/moc-Table.cc \\\n  %reldir%/moc-TextEdit.cc \\\n  %reldir%/moc-ToggleTool.cc \\\n  %reldir%/moc-ToolBar.cc \\\n  %reldir%/moc-annotation-dialog.cc \\\n  %reldir%/moc-qt-graphics-toolkit.cc\n\n$(OCTAVE_GUI_GRAPHICS_MOC): | %reldir%/$(octave_dirstamp)\n\nDIRSTAMP_FILES += \\\n  %reldir%/$(octave_dirstamp)\n\nlibgraphics_MOC = \\\n  $(OCTAVE_GUI_GRAPHICS_MOC)\n\nlibgraphics_MOC_H = $(libgraphics_MOC:.cc=.h)\n\nlibgraphics_UI = \\\n  %reldir%/annotation-dialog.ui\n\nlibgraphics_UI_H = $(patsubst %reldir%/%.ui, %reldir%/ui-%.h, $(libgraphics_UI))\n\n$(libgraphics_UI_H): | %reldir%/$(octave_dirstamp)\n\nBUILT_SOURCES += $(libgraphics_UI_H)\n\nnoinst_HEADERS += \\\n  %reldir%/BaseControl.h \\\n  %reldir%/ButtonControl.h \\\n  %reldir%/ButtonGroup.h \\\n  %reldir%/Canvas.h \\\n  %reldir%/CheckBoxControl.h \\\n  %reldir%/Container.h \\\n  %reldir%/ContextMenu.h \\\n  %reldir%/EditControl.h \\\n  %reldir%/Figure.h \\\n  %reldir%/FigureWindow.h \\\n  %reldir%/GLCanvas.h \\\n  %reldir%/GenericEventNotify.h \\\n  %reldir%/KeyMap.h \\\n  %reldir%/ListBoxControl.h \\\n  %reldir%/Logger.h \\\n  %reldir%/Menu.h \\\n  %reldir%/MenuContainer.h \\\n  %reldir%/Object.h \\\n  %reldir%/ObjectProxy.h \\\n  %reldir%/Panel.h \\\n  %reldir%/PopupMenuControl.h \\\n  %reldir%/PushButtonControl.h \\\n  %reldir%/PushTool.h \\\n  %reldir%/QtHandlesUtils.h \\\n  %reldir%/RadioButtonControl.h \\\n  %reldir%/SliderControl.h \\\n  %reldir%/Table.h \\\n  %reldir%/TextControl.h \\\n  %reldir%/TextEdit.h \\\n  %reldir%/ToggleButtonControl.h \\\n  %reldir%/ToggleTool.h \\\n  %reldir%/ToolBar.h \\\n  %reldir%/ToolBarButton.h \\\n  %reldir%/annotation-dialog.h \\\n  %reldir%/gl-select.h \\\n  %reldir%/qopengl-functions.h \\\n  %reldir%/qt-graphics-toolkit.h \\\n  $(TEMPLATE_SRC)\n\n%canon_reldir%_libgraphics_la_SOURCES = \\\n  %reldir%/BaseControl.cc \\\n  %reldir%/ButtonControl.cc \\\n  %reldir%/ButtonGroup.cc \\\n  %reldir%/Canvas.cc \\\n  %reldir%/CheckBoxControl.cc \\\n  %reldir%/Container.cc \\\n  %reldir%/ContextMenu.cc \\\n  %reldir%/EditControl.cc \\\n  %reldir%/Figure.cc \\\n  %reldir%/FigureWindow.cc \\\n  %reldir%/GLCanvas.cc \\\n  %reldir%/KeyMap.cc \\\n  %reldir%/ListBoxControl.cc \\\n  %reldir%/Logger.cc \\\n  %reldir%/Menu.cc \\\n  %reldir%/Object.cc \\\n  %reldir%/ObjectProxy.cc \\\n  %reldir%/Panel.cc \\\n  %reldir%/PopupMenuControl.cc \\\n  %reldir%/PushButtonControl.cc \\\n  %reldir%/PushTool.cc \\\n  %reldir%/QtHandlesUtils.cc \\\n  %reldir%/RadioButtonControl.cc \\\n  %reldir%/SliderControl.cc \\\n  %reldir%/Table.cc \\\n  %reldir%/TextControl.cc \\\n  %reldir%/TextEdit.cc \\\n  %reldir%/ToggleButtonControl.cc \\\n  %reldir%/ToggleTool.cc \\\n  %reldir%/ToolBar.cc \\\n  %reldir%/annotation-dialog.cc \\\n  %reldir%/gl-select.cc \\\n  %reldir%/qt-graphics-toolkit.cc\n\nTEMPLATE_SRC = \\\n  %reldir%/ToolBarButton.cc\n\nnodist_%canon_reldir%_libgraphics_la_SOURCES = $(libgraphics_MOC)\n\n%canon_reldir%_libgraphics_la_CPPFLAGS = \\\n  $(AM_CPPFLAGS) \\\n  $(FT2_CPPFLAGS) \\\n  $(FONTCONFIG_CPPFLAGS) \\\n  $(HDF5_CPPFLAGS) \\\n  @OCTGUI_DLL_DEFS@ \\\n  @QT_CPPFLAGS@ \\\n  -I%reldir% -I$(srcdir)/%reldir% \\\n  -Ilibgui/src -I$(srcdir)/libgui/src \\\n  -Iliboctave \\\n  -I$(srcdir)/liboctave/array \\\n  -Iliboctave/numeric -I$(srcdir)/liboctave/numeric \\\n  -Iliboctave/operators -I$(srcdir)/liboctave/operators \\\n  -I$(srcdir)/liboctave/system \\\n  -I$(srcdir)/liboctave/util \\\n  -Ilibinterp -I$(srcdir)/libinterp \\\n  -I$(srcdir)/libinterp/template-inst \\\n  -Ilibinterp/parse-tree -I$(srcdir)/libinterp/parse-tree \\\n  -Ilibinterp/corefcn -I$(srcdir)/libinterp/corefcn \\\n  -I$(srcdir)/libinterp/octave-value\n\nnoinst_LTLIBRARIES += %reldir%/libgraphics.la\n\nlibgui_EXTRA_DIST += \\\n  $(libgraphics_UI)\n\nlibgui_CLEANFILES += \\\n  $(GRAPHICS_OCT_FILES) \\\n  $(GRAPHICS_PKG_ADD_FILE) \\\n  $(libgraphics_MOC) \\\n  $(libgraphics_MOC_H) \\\n  $(libgraphics_UI_H)\n"
  },
  {
    "path": "libgui/graphics/qopengl-functions.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_qopengl_functions_h)\n#define octave_qopengl_functions_h 1\n\n#include \"oct-opengl.h\"\n\n#if defined (HAVE_QOPENGLFUNCTIONS_1_1)\n#  include <QOpenGLFunctions_1_1>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// If we don't have QOPENGLFUNCTIONS_1_1, then we will default to\n// calling OpenGL functions directly through the base\n// opengl_functions class.\n\nclass qopengl_functions : public opengl_functions\n{\npublic:\n\n  qopengl_functions ()\n#if defined (HAVE_QOPENGLFUNCTIONS_1_1)\n    : m_glfcns ()\n#endif\n  { }\n\n  qopengl_functions (const qopengl_functions&) = default;\n\n  qopengl_functions& operator = (const qopengl_functions&) = default;\n\n  ~qopengl_functions () = default;\n\n  void init ()\n  {\n#if defined (HAVE_QOPENGLFUNCTIONS_1_1)\n    m_glfcns.initializeOpenGLFunctions ();\n#endif\n  }\n\n#if defined (HAVE_QOPENGLFUNCTIONS_1_1)\n\n  void glAlphaFunc (GLenum fcn, GLclampf ref)\n  {\n    m_glfcns.glAlphaFunc (fcn, ref);\n  }\n\n  void glBegin (GLenum mode)\n  {\n    m_glfcns.glBegin (mode);\n  }\n\n  void glBindTexture (GLenum target, GLuint texture)\n  {\n    m_glfcns.glBindTexture (target, texture);\n  }\n\n  void glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,\n                 GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)\n  {\n    m_glfcns.glBitmap (width, height, xorig, yorig, xmove, ymove, bitmap);\n  }\n\n  void glBlendFunc (GLenum sfactor, GLenum dfactor)\n  {\n    m_glfcns.glBlendFunc (sfactor, dfactor);\n  }\n\n  void glCallList (GLuint list)\n  {\n    m_glfcns.glCallList (list);\n  }\n\n  void glClearColor (GLclampf red, GLclampf green, GLclampf blue,\n                     GLclampf alpha)\n  {\n    m_glfcns.glClearColor (red, green, blue, alpha);\n  }\n\n  void glClear (GLbitfield mask)\n  {\n    m_glfcns.glClear (mask);\n  }\n\n  void glClipPlane (GLenum plane, const GLdouble *equation)\n  {\n    m_glfcns.glClipPlane (plane, equation);\n  }\n\n  void glColor3dv (const GLdouble *v)\n  {\n    m_glfcns.glColor3dv (v);\n  }\n\n  void glColor3f (GLfloat red, GLfloat green, GLfloat blue)\n  {\n    m_glfcns.glColor3f (red, green, blue);\n  }\n\n  void glColor3fv (const GLfloat *v)\n  {\n    m_glfcns.glColor3fv (v);\n  }\n\n  void glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha)\n  {\n    m_glfcns.glColor4d (red, green, blue, alpha);\n  }\n\n  void glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)\n  {\n    m_glfcns.glColor4f (red, green, blue, alpha);\n  }\n\n  void glColor4fv (const GLfloat *v)\n  {\n    m_glfcns.glColor4fv (v);\n  }\n\n  void glDeleteLists (GLuint list, GLsizei range)\n  {\n    m_glfcns.glDeleteLists (list, range);\n  }\n\n  void glDeleteTextures (GLsizei n, const GLuint *textures)\n  {\n    m_glfcns.glDeleteTextures (n, textures);\n  }\n\n  void glDepthFunc (GLenum fcn)\n  {\n    m_glfcns.glDepthFunc (fcn);\n  }\n\n  void glDisable (GLenum cap)\n  {\n    m_glfcns.glDisable (cap);\n  }\n\n  void glDrawPixels (GLsizei width, GLsizei height, GLenum format,\n                     GLenum type, const GLvoid *pixels)\n  {\n    m_glfcns.glDrawPixels (width, height, format, type, pixels);\n  }\n\n  void glEdgeFlag (GLboolean flag)\n  {\n    m_glfcns.glEdgeFlag (flag);\n  }\n\n  void glEnable (GLenum cap)\n  {\n    m_glfcns.glEnable (cap);\n  }\n\n  void glEndList ()\n  {\n    m_glfcns.glEndList ();\n  }\n\n  void glEnd ()\n  {\n    m_glfcns.glEnd ();\n  }\n\n  void glFinish ()\n  {\n    m_glfcns.glFinish ();\n  }\n\n  GLuint glGenLists (GLsizei range)\n  {\n    return m_glfcns.glGenLists (range);\n  }\n\n  void glGenTextures (GLsizei n, GLuint *textures)\n  {\n    m_glfcns.glGenTextures (n, textures);\n  }\n\n  void glGetBooleanv (GLenum pname, GLboolean *data)\n  {\n    m_glfcns.glGetBooleanv (pname, data);\n  }\n\n  void glGetDoublev (GLenum pname, GLdouble *data)\n  {\n    m_glfcns.glGetDoublev (pname, data);\n  }\n\n  GLenum glGetError ()\n  {\n    return m_glfcns.glGetError ();\n  }\n\n  void glGetFloatv (GLenum pname, GLfloat *data)\n  {\n    m_glfcns.glGetFloatv (pname, data);\n  }\n\n  void glGetIntegerv (GLenum pname, GLint *data)\n  {\n    m_glfcns.glGetIntegerv (pname, data);\n  }\n\n  const GLubyte * glGetString (GLenum name)\n  {\n    return m_glfcns.glGetString (name);\n  }\n\n  void glHint (GLenum target, GLenum mode)\n  {\n    m_glfcns.glHint (target, mode);\n  }\n\n  void glInitNames ()\n  {\n    m_glfcns.glInitNames ();\n  }\n\n  GLboolean glIsEnabled (GLenum cap)\n  {\n    return m_glfcns.glIsEnabled (cap);\n  }\n\n  void glLightfv (GLenum light, GLenum pname, const GLfloat *params)\n  {\n    m_glfcns.glLightfv (light, pname, params);\n  }\n\n  void glLineStipple (GLint factor, GLushort pattern)\n  {\n    m_glfcns.glLineStipple (factor, pattern);\n  }\n\n  void glLineWidth (GLfloat width)\n  {\n    m_glfcns.glLineWidth (width);\n  }\n\n  void glLoadIdentity ()\n  {\n    m_glfcns.glLoadIdentity ();\n  }\n\n  void glMaterialf (GLenum face, GLenum pname, GLfloat param)\n  {\n    m_glfcns.glMaterialf (face, pname, param);\n  }\n\n  void glMaterialfv (GLenum face, GLenum pname, const GLfloat *params)\n  {\n    m_glfcns.glMaterialfv (face, pname, params);\n  }\n\n  void glMatrixMode (GLenum mode)\n  {\n    m_glfcns.glMatrixMode (mode);\n  }\n\n  void glMultMatrixd (const GLdouble *m)\n  {\n    m_glfcns.glMultMatrixd (m);\n  }\n\n  void glNewList (GLuint list, GLenum mode)\n  {\n    m_glfcns.glNewList (list, mode);\n  }\n\n  void glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz)\n  {\n    m_glfcns.glNormal3d (nx, ny, nz);\n  }\n\n  void glNormal3dv (const GLdouble *v)\n  {\n    m_glfcns.glNormal3dv (v);\n  }\n\n  void glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top,\n                GLdouble near_val, GLdouble far_val)\n  {\n    m_glfcns.glOrtho (left, right, bottom, top, near_val, far_val);\n  }\n\n  void glPixelStorei (GLenum pname, GLint param)\n  {\n    m_glfcns.glPixelStorei (pname, param);\n  }\n\n  void glPixelZoom (GLfloat xfactor, GLfloat yfactor)\n  {\n    m_glfcns.glPixelZoom (xfactor, yfactor);\n  }\n\n  void glPolygonMode (GLenum face, GLenum mode)\n  {\n    m_glfcns.glPolygonMode (face, mode);\n  }\n\n  void glPolygonOffset (GLfloat factor, GLfloat units)\n  {\n    m_glfcns.glPolygonOffset (factor, units);\n  }\n\n  void glPopAttrib ()\n  {\n    m_glfcns.glPopAttrib ();\n  }\n\n  void glPopMatrix ()\n  {\n    m_glfcns.glPopMatrix ();\n  }\n\n  void glPopName ()\n  {\n    m_glfcns.glPopName ();\n  }\n\n  void glPushAttrib (GLbitfield mask)\n  {\n    m_glfcns.glPushAttrib (mask);\n  }\n\n  void glPushMatrix ()\n  {\n    m_glfcns.glPushMatrix ();\n  }\n\n  void glPushName (GLuint name)\n  {\n    m_glfcns.glPushName (name);\n  }\n\n  void glRasterPos3d (GLdouble x, GLdouble y, GLdouble z)\n  {\n    m_glfcns.glRasterPos3d (x, y, z);\n  }\n\n  void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height,\n                     GLenum format, GLenum type, GLvoid *pixels)\n  {\n    m_glfcns.glReadPixels (x, y, width, height, format, type, pixels);\n  }\n\n  GLint glRenderMode (GLenum mode)\n  {\n    return m_glfcns.glRenderMode (mode);\n  }\n\n  void glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)\n  {\n    m_glfcns.glRotated (angle, x, y, z);\n  }\n\n  void glScaled (GLdouble x, GLdouble y, GLdouble z)\n  {\n    m_glfcns.glScaled (x, y, z);\n  }\n\n  void glScalef (GLfloat x, GLfloat y, GLfloat z)\n  {\n    m_glfcns.glScalef (x, y, z);\n  }\n\n  void glSelectBuffer (GLsizei size, GLuint *buffer)\n  {\n    m_glfcns.glSelectBuffer (size, buffer);\n  }\n\n  void glShadeModel (GLenum mode)\n  {\n    m_glfcns.glShadeModel (mode);\n  }\n\n  void glTexCoord2d (GLdouble s, GLdouble t)\n  {\n    m_glfcns.glTexCoord2d (s, t);\n  }\n\n  void glTexImage2D (GLenum target, GLint level, GLint internalFormat,\n                     GLsizei width, GLsizei height, GLint border,\n                     GLenum format, GLenum type, const GLvoid *pixels)\n  {\n    m_glfcns.glTexImage2D (target, level, internalFormat, width, height,\n                           border, format, type, pixels);\n  }\n\n  void glTexParameteri (GLenum target, GLenum pname, GLint param)\n  {\n    m_glfcns.glTexParameteri (target, pname, param);\n  }\n\n  void glTranslated (GLdouble x, GLdouble y, GLdouble z)\n  {\n    m_glfcns.glTranslated (x, y, z);\n  }\n\n  void glTranslatef (GLfloat x, GLfloat y, GLfloat z)\n  {\n    m_glfcns.glTranslatef (x, y, z);\n  }\n\n  void glVertex2d (GLdouble x, GLdouble y)\n  {\n    m_glfcns.glVertex2d (x, y);\n  }\n\n  void glVertex3d (GLdouble x, GLdouble y, GLdouble z)\n  {\n    m_glfcns.glVertex3d (x, y, z);\n  }\n\n  void glVertex3dv (const GLdouble *v)\n  {\n    m_glfcns.glVertex3dv (v);\n  }\n\n  void glViewport (GLint x, GLint y, GLsizei width, GLsizei height)\n  {\n    m_glfcns.glViewport (x, y, width, height);\n  }\n\nprivate:\n\n  QOpenGLFunctions_1_1 m_glfcns;\n\n#endif\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/graphics/qt-graphics-toolkit.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdint>\n\n#include <QApplication>\n#include <QFontMetrics>\n#include <QThread>\n\n#include \"ButtonGroup.h\"\n#include \"CheckBoxControl.h\"\n#include \"ContextMenu.h\"\n#include \"EditControl.h\"\n#include \"Figure.h\"\n#include \"ListBoxControl.h\"\n#include \"Logger.h\"\n#include \"Menu.h\"\n#include \"Object.h\"\n#include \"ObjectProxy.h\"\n#include \"Panel.h\"\n#include \"PopupMenuControl.h\"\n#include \"PushButtonControl.h\"\n#include \"PushTool.h\"\n#include \"QtHandlesUtils.h\"\n#include \"RadioButtonControl.h\"\n#include \"SliderControl.h\"\n#include \"Table.h\"\n#include \"TextControl.h\"\n#include \"ToggleButtonControl.h\"\n#include \"ToggleTool.h\"\n#include \"ToolBar.h\"\n#include \"qt-graphics-toolkit.h\"\n\n#include \"event-manager.h\"\n#include \"graphics.h\"\n#include \"interpreter.h\"\n\n//#if INTPTR_MAX == INT32_MAX\n//# define OCTAVE_PTR_TYPE octave_uint32\n//# define OCTAVE_INTPTR_TYPE uint32_t\n//# define OCTAVE_PTR_SCALAR uint32_scalar_value\n//#else\n# define OCTAVE_PTR_TYPE octave_uint64\n# define OCTAVE_INTPTR_TYPE uint64_t\n# define OCTAVE_PTR_SCALAR uint64_scalar_value\n//#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic std::string\ntoolkitObjectProperty (const graphics_object& go)\n{\n  if (go.isa (\"figure\"))\n    return \"__plot_stream__\";\n  else if (go.isa (\"uicontrol\")\n           || go.isa (\"uipanel\")\n           || go.isa (\"uibuttongroup\")\n           || go.isa (\"uimenu\")\n           || go.isa (\"uicontextmenu\")\n           || go.isa (\"uitable\")\n           || go.isa (\"uitoolbar\")\n           || go.isa (\"uipushtool\")\n           || go.isa (\"uitoggletool\"))\n    return \"__object__\";\n  else\n    qCritical (\"octave::qt_graphics_toolkit: no __object__ property known for object \"\n               \"of type %s\", go.type ().c_str ());\n\n  return \"\";\n}\n\nqt_graphics_toolkit::qt_graphics_toolkit (octave::interpreter& interp)\n  : QObject (), base_graphics_toolkit (\"qt\"), m_interpreter (interp)\n{\n  // Implemented with a signal/slot connection in order to properly\n  // cross from the interpreter thread (where requests to create\n  // graphics object are initiated) to the GUI application thread\n  // (where they are actually created and displayed).\n  // We need to make sure the GUI Object and its proxy are properly\n  // created before the initialize method returns, so we use a\n  // BlockingQueuedConnection.  After the signal is emitted, the interpreter\n  // thread is locked until the slot has returned.\n\n  connect (this, &qt_graphics_toolkit::create_object_signal,\n           this, &qt_graphics_toolkit::create_object,\n           Qt::BlockingQueuedConnection);\n}\n\nbool\nqt_graphics_toolkit::initialize (const graphics_object& go)\n{\n  if (go.isa (\"figure\")\n      || (go.isa (\"uicontrol\") && go.get (\"style\").string_value () != \"frame\")\n      || go.isa (\"uipanel\")\n      || go.isa (\"uibuttongroup\")\n      || go.isa (\"uimenu\")\n      || go.isa (\"uicontextmenu\")\n      || go.isa (\"uitable\")\n      || go.isa (\"uitoolbar\")\n      || go.isa (\"uipushtool\")\n      || go.isa (\"uitoggletool\"))\n    {\n      // FIXME: We need to unlock the mutex here but we have no way to know\n      // if it was previously locked by this thread, and thus if we should\n      // re-lock it.\n\n      gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n      gh_mgr.unlock ();\n\n      Logger::debug (\"qt_graphics_toolkit::initialize %s from thread %p\",\n                     go.type ().c_str (), QThread::currentThreadId ());\n\n      ObjectProxy *proxy = new ObjectProxy ();\n      graphics_object gObj (go);\n\n      OCTAVE_PTR_TYPE tmp (reinterpret_cast<OCTAVE_INTPTR_TYPE> (proxy));\n      gObj.get_properties ().set (toolkitObjectProperty (go), tmp);\n\n      Q_EMIT create_object_signal (go.get_handle ().value ());\n\n      return true;\n    }\n\n  return false;\n}\n\nvoid\nqt_graphics_toolkit::update (const graphics_object& go, int pId)\n{\n  // Rule out obvious properties we want to ignore.\n  if (pId == figure::properties::ID___PLOT_STREAM__\n      || pId == uicontrol::properties::ID___OBJECT__\n      || pId == uipanel::properties::ID___OBJECT__\n      || pId == uibuttongroup::properties::ID___OBJECT__\n      || pId == uimenu::properties::ID___OBJECT__\n      || pId == uicontextmenu::properties::ID___OBJECT__\n      || pId == uitable::properties::ID___OBJECT__\n      || pId == uitoolbar::properties::ID___OBJECT__\n      || pId == uipushtool::properties::ID___OBJECT__\n      || pId == uitoggletool::properties::ID___OBJECT__\n      || pId == base_properties::ID___MODIFIED__)\n    return;\n\n  Logger::debug (\"qt_graphics_toolkit::update %s(%d) from thread %p\",\n                 go.type ().c_str (), pId, QThread::currentThreadId ());\n\n  ObjectProxy *proxy = toolkitObjectProxy (go);\n\n  if (proxy)\n    {\n      if ((go.isa (\"uicontrol\")\n           && pId == uicontrol::properties::ID_STYLE)\n          || (go.isa (\"uitable\")\n              && pId == uitable::properties::ID_DATA))\n        {\n          // Special case: we need to recreate the control widget\n          // associated with the octave graphics_object\n          // FIXME: For uitable, it would only be necessary to recreate\n          // the table widget if the type of the displayed values changes\n          // between Boolean and non-Boolean (bug #63388).\n\n          finalize (go);\n          initialize (go);\n        }\n      else\n        proxy->update (pId);\n    }\n}\n\nvoid\nqt_graphics_toolkit::finalize (const graphics_object& go)\n{\n  // FIXME: We need to unlock the mutex here but we have no way to know if\n  // if it was previously locked by this thread, and thus if we should\n  // re-lock it.\n\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  gh_mgr.unlock ();\n\n  Logger::debug (\"qt_graphics_toolkit::finalize %s from thread %p\",\n                 go.type ().c_str (), QThread::currentThreadId ());\n\n  ObjectProxy *proxy = toolkitObjectProxy (go);\n\n  if (proxy)\n    {\n      proxy->finalize ();\n      delete proxy;\n\n      graphics_object gObj (go);\n\n      gObj.get_properties ().set (toolkitObjectProperty (go), Matrix ());\n    }\n}\n\nvoid\nqt_graphics_toolkit::redraw_figure (const graphics_object& go) const\n{\n  if (go.get_properties ().is_visible ())\n    {\n      ObjectProxy *proxy = toolkitObjectProxy (go);\n\n      if (proxy)\n        proxy->redraw ();\n    }\n}\n\nvoid\nqt_graphics_toolkit::show_figure (const graphics_object& go) const\n{\n  if (go.get_properties ().is_visible ())\n    {\n      ObjectProxy *proxy = toolkitObjectProxy (go);\n\n      if (proxy)\n        proxy->show ();\n    }\n}\n\nvoid\nqt_graphics_toolkit::print_figure (const graphics_object& go,\n                                   const std::string& term,\n                                   const std::string& file_cmd,\n                                   const std::string& /*debug_file*/) const\n{\n  ObjectProxy *proxy = toolkitObjectProxy (go);\n\n  if (proxy)\n    proxy->print (QString::fromStdString (file_cmd),\n                  QString::fromStdString (term));\n}\n\nuint8NDArray\nqt_graphics_toolkit::get_pixels (const graphics_object& go) const\n{\n  uint8NDArray retval;\n\n  if (go.isa (\"figure\"))\n    {\n      ObjectProxy *proxy = toolkitObjectProxy (go);\n\n      if (proxy)\n        retval = proxy->get_pixels ();\n    }\n\n  return retval;\n}\n\nMatrix\nqt_graphics_toolkit::get_text_extent (const graphics_object& go) const\n{\n  Matrix ext (1, 4, 0.0);\n\n  if (go.isa (\"uicontrol\"))\n    {\n      octave_value str = go.get (\"string\");\n      if (! str.isempty ())\n        {\n          const uicontrol::properties& up =\n            dynamic_cast<const uicontrol::properties&> (go.get_properties ());\n          Matrix bb = up.get_boundingbox (false);\n          QFont font = Utils::computeFont<uicontrol> (up, bb(3));\n          QFontMetrics fm (font);\n\n          QString s;\n          QSize sz;\n\n          if (str.is_string ())\n            {\n              s = QString::fromStdString (str.string_value ());\n              sz = fm.size (Qt::TextSingleLine, s);\n              ext(2) = sz.width ();\n              ext(3) = sz.height ();\n            }\n          else if (str.iscellstr ())\n            {\n              string_vector sv = str.string_vector_value ();\n              double wd = 0.0;\n              double hg = 0.0;\n              for (octave_idx_type ii = 0; ii < sv.numel (); ii++)\n                {\n                  s = QString::fromStdString (sv(ii));\n                  sz = fm.size (Qt::TextSingleLine, s);\n                  wd = std::max (wd, static_cast<double> (sz.width ()));\n                  hg = std::max (hg, static_cast<double> (sz.height ()));\n                }\n\n              ext(2) = wd;\n              // FIXME: Find a better way to determine the height of, e.g.,\n              // listbox uicontrol objects\n              ext(3) = hg * sv.numel ();\n            }\n        }\n    }\n\n  return ext;\n}\n\nObject *\nqt_graphics_toolkit::toolkitObject (const graphics_object& go)\n{\n  ObjectProxy *proxy = toolkitObjectProxy (go);\n\n  if (proxy)\n    return proxy->object ();\n\n  return nullptr;\n}\n\nObjectProxy *\nqt_graphics_toolkit::toolkitObjectProxy (const graphics_object& go)\n{\n  if (go)\n    {\n      octave_value ov = go.get (toolkitObjectProperty (go));\n\n      if (ov.is_defined () && ! ov.isempty ())\n        {\n          OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value ();\n\n          return reinterpret_cast<ObjectProxy *> (ptr);\n        }\n    }\n\n  return nullptr;\n}\n\nvoid\nqt_graphics_toolkit::interpreter_event (const octave::fcn_callback& fcn)\n{\n  octave::event_manager& evmgr = m_interpreter.get_event_manager ();\n\n  evmgr.post_event (fcn);\n}\n\nvoid\nqt_graphics_toolkit::interpreter_event (const octave::meth_callback& meth)\n{\n  octave::event_manager& evmgr = m_interpreter.get_event_manager ();\n\n  evmgr.post_event (meth);\n}\n\nvoid\nqt_graphics_toolkit::create_object (double handle)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  graphics_object go (gh_mgr.get_object (graphics_handle (handle)));\n\n  if (! go.valid_object ())\n    {\n      qWarning (\"qt_graphics_toolkit::create_object: invalid object for handle %g\",\n                handle);\n      return;\n    }\n\n  if (go.get_properties ().is_beingdeleted ())\n    {\n      qWarning (\"qt_graphics_toolkit::create_object: object is being deleted\");\n      return;\n    }\n\n  ObjectProxy *proxy = qt_graphics_toolkit::toolkitObjectProxy (go);\n\n  if (! proxy)\n    {\n      qWarning (\"qt_graphics_toolkit::create_object: no proxy for handle %g\",\n                handle);\n      return;\n    }\n\n  Logger::debug (\"qt_graphics_toolkit::create_object: \"\n                 \"create %s from thread %p\",\n                 go.type ().c_str (), QThread::currentThreadId ());\n\n  Object *obj = nullptr;\n\n  if (go.isa (\"figure\"))\n    obj = Figure::create (m_interpreter, go);\n  else if (go.isa (\"uicontrol\"))\n    {\n      uicontrol::properties& up =\n        Utils::properties<uicontrol> (go);\n\n      if (up.style_is (\"pushbutton\"))\n        obj = PushButtonControl::create (m_interpreter, go);\n      else if (up.style_is (\"edit\"))\n        obj = EditControl::create (m_interpreter, go);\n      else if (up.style_is (\"checkbox\"))\n        obj = CheckBoxControl::create (m_interpreter, go);\n      else if (up.style_is (\"radiobutton\"))\n        obj = RadioButtonControl::create (m_interpreter, go);\n      else if (up.style_is (\"togglebutton\"))\n        obj = ToggleButtonControl::create (m_interpreter, go);\n      else if (up.style_is (\"text\"))\n        obj = TextControl::create (m_interpreter, go);\n      else if (up.style_is (\"popupmenu\"))\n        obj = PopupMenuControl::create (m_interpreter, go);\n      else if (up.style_is (\"slider\"))\n        obj = SliderControl::create (m_interpreter, go);\n      else if (up.style_is (\"listbox\"))\n        obj = ListBoxControl::create (m_interpreter, go);\n    }\n  else if (go.isa (\"uibuttongroup\"))\n    obj = ButtonGroup::create (m_interpreter, go);\n  else if (go.isa (\"uipanel\"))\n    obj = Panel::create (m_interpreter, go);\n  else if (go.isa (\"uimenu\"))\n    obj = Menu::create (m_interpreter, go);\n  else if (go.isa (\"uicontextmenu\"))\n    obj = ContextMenu::create (m_interpreter, go);\n  else if (go.isa (\"uitable\"))\n    obj = Table::create (m_interpreter, go);\n  else if (go.isa (\"uitoolbar\"))\n    obj = ToolBar::create (m_interpreter, go);\n  else if (go.isa (\"uipushtool\"))\n    obj = PushTool::create (m_interpreter, go);\n  else if (go.isa (\"uitoggletool\"))\n    obj = ToggleTool::create (m_interpreter, go);\n  else\n    qWarning (\"qt_graphics_toolkit::create_object: unsupported type '%s'\",\n              go.type ().c_str ());\n\n  if (obj)\n    {\n      proxy->setObject (obj);\n      obj->do_connections (this);\n    }\n}\n\nvoid\nqt_graphics_toolkit::gh_callback_event (const graphics_handle& h,\n                                        const std::string& nm)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  gh_mgr.post_callback (h, nm);\n}\n\nvoid\nqt_graphics_toolkit::gh_callback_event (const graphics_handle& h,\n                                        const std::string& nm,\n                                        const octave_value& data)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  gh_mgr.post_callback (h, nm, data);\n}\n\nvoid\nqt_graphics_toolkit::gh_set_event (const graphics_handle& h,\n                                   const std::string& nm,\n                                   const octave_value& value)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  gh_mgr.post_set (h, nm, value);\n}\n\nvoid\nqt_graphics_toolkit::gh_set_event (const graphics_handle& h,\n                                   const std::string& nm,\n                                   const octave_value& value,\n                                   bool notify_toolkit)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  gh_mgr.post_set (h, nm, value, notify_toolkit);\n}\n\nvoid\nqt_graphics_toolkit::gh_set_event (const graphics_handle& h,\n                                   const std::string& nm,\n                                   const octave_value& value,\n                                   bool notify_toolkit,\n                                   bool redraw_figure)\n{\n  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n  gh_mgr.post_set (h, nm, value, notify_toolkit, redraw_figure);\n}\n\nOCTAVE_END_NAMESPACE(octave);\n"
  },
  {
    "path": "libgui/graphics/qt-graphics-toolkit.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_qt_graphics_toolkit_h)\n#define octave_qt_graphics_toolkit_h 1\n\n#include <QObject>\n\n#include \"event-manager.h\"\n#include \"graphics.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass Object;\nclass ObjectProxy;\n\nclass qt_graphics_toolkit\n  : public QObject, public octave::base_graphics_toolkit\n{\n  Q_OBJECT\n\npublic:\n\n  qt_graphics_toolkit (octave::interpreter& interp);\n\n  ~qt_graphics_toolkit () = default;\n\n  // The interpreter may call graphics toolkit functions that we\n  // implement here.  The Qt GUI that manages these actions runs in a\n  // separate thread.  So in order to correctly cross from the\n  // interpreter thread to the GUI thread, these functions should emit\n  // signals (in the interpreter thread) that are handled by slots\n  // that will run in the GUI thread.  This design is similar to the\n  // event_manager, interpreter_events, and qt_interpreter_events\n  // classes work to pass messages from the interpreter to the GUI.\n  //\n  // FIXME: currently most of these functions do not emit signals.\n  // They may work because they use locking and the gh_manager class,\n  // but it might be better to use Qt signals and slots.  In any case,\n  // we should ensure that they are correctly handling the connection\n  // between the interpreter and GUI threads.\n\n  bool is_valid () const { return true; }\n\n  void redraw_figure (const graphics_object& h) const;\n\n  void show_figure (const graphics_object& h) const;\n\n  void update (const graphics_object& obj, int pId);\n\n  bool initialize (const graphics_object& obj);\n\n  void finalize (const graphics_object& obj);\n\n  void print_figure (const graphics_object& go,\n                     const std::string& term,\n                     const std::string& file_cmd,\n                     const std::string& /*debug_file*/) const;\n\n  uint8NDArray get_pixels (const graphics_object& go) const;\n\n  Matrix get_text_extent (const graphics_object& go) const;\n\n  static Object * toolkitObject (const graphics_object& go);\n\n  static ObjectProxy * toolkitObjectProxy (const graphics_object& go);\n\nQ_SIGNALS:\n\n  void create_object_signal (double handle);\n\npublic Q_SLOTS:\n\n  void interpreter_event (const octave::fcn_callback& fcn);\n  void interpreter_event (const octave::meth_callback& meth);\n\n  void create_object (double handle);\n\n  void gh_callback_event (const graphics_handle& h, const std::string& name);\n\n  void gh_callback_event (const graphics_handle& h, const std::string& name,\n                          const octave_value& data);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value, bool notify_toolkit);\n\n  void gh_set_event (const graphics_handle& h, const std::string& name,\n                     const octave_value& value, bool notify_toolkit,\n                     bool redraw_figure);\nprivate:\n\n  octave::interpreter& m_interpreter;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/kb-layouts/default.keytab",
    "content": "# [README.default.Keytab] Buildin Keyboard Table\n#\n# To customize your keyboard, copy this file to something\n# ending with .keytab and change it to meet you needs.\n# Please read the README.KeyTab and the README.keyboard\n# in this case.\n#\n# --------------------------------------------------------------\n\nkeyboard \"Default (XFree 4)\"\n\n# --------------------------------------------------------------\n#\n# Note that this particular table is a \"risc\" version made to\n# ease customization without bothering with obsolete details.\n# See VT100.keytab for the more hairy stuff.\n#\n# --------------------------------------------------------------\n\n# common keys\n\nkey Escape             : \"\\E\"\n\nkey Tab   -Shift       : \"\\t\"\nkey Tab   +Shift+Ansi  : \"\\E[Z\"\nkey Tab   +Shift-Ansi  : \"\\t\"\nkey Backtab     +Ansi  : \"\\E[Z\"\nkey Backtab     -Ansi  : \"\\t\"\n\nkey Return-Shift-NewLine : \"\\r\"\nkey Return-Shift+NewLine : \"\\r\\n\"\n\nkey Return+Shift         : \"\\EOM\"\n\n# Backspace and Delete codes are preserving CTRL-H.\n\nkey Backspace      : \"\\x7f\"\n\n# Arrow keys in VT52 mode\n# shift up/down are reserved for scrolling.\n# shift left/right are reserved for switching between tabs (this is hardcoded).\n\nkey Up   -Shift-Ansi : \"\\EA\"\nkey Down -Shift-Ansi : \"\\EB\"\nkey Right-Shift-Ansi : \"\\EC\"\nkey Left -Shift-Ansi : \"\\ED\"\n\n# Arrow keys in ANSI mode with Application - and Normal Cursor Mode)\n\nkey Up    -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOA\"\nkey Down  -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOB\"\nkey Right -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOC\"\nkey Left  -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOD\"\n\nkey Up    -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[A\"\nkey Down  -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[B\"\nkey Right -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[C\"\nkey Left  -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[D\"\n\nkey Up    -Shift+AnyMod+Ansi                     : \"\\E[1;*A\"\nkey Down  -Shift+AnyMod+Ansi                     : \"\\E[1;*B\"\nkey Right -Shift+AnyMod+Ansi                     : \"\\E[1;*C\"\nkey Left  -Shift+AnyMod+Ansi                     : \"\\E[1;*D\"\n\n# other grey PC keys\n\nkey Enter+NewLine : \"\\r\\n\"\nkey Enter-NewLine : \"\\r\"\n\nkey Home        -AnyMod     -AppCuKeys           : \"\\E[H\"\nkey End         -AnyMod     -AppCuKeys           : \"\\E[F\"\nkey Home        -AnyMod     +AppCuKeys           : \"\\EOH\"\nkey End         -AnyMod     +AppCuKeys           : \"\\EOF\"\nkey Home        +AnyMod                          : \"\\E[1;*H\"\nkey End         +AnyMod                          : \"\\E[1;*F\"\n\nkey Insert      -AnyMod                          : \"\\E[2~\"\nkey Delete      -AnyMod                          : \"\\E[3~\"\nkey Insert      +AnyMod                          : \"\\E[2;*~\"\nkey Delete      +AnyMod                          : \"\\E[3;*~\"\n\nkey Prior -Shift-AnyMod                          : \"\\E[5~\"\nkey Next  -Shift-AnyMod                          : \"\\E[6~\"\nkey Prior -Shift+AnyMod                          : \"\\E[5;*~\"\nkey Next  -Shift+AnyMod                          : \"\\E[6;*~\"\n\n# Function keys\nkey F1          -AnyMod                          : \"\\EOP\"\nkey F2          -AnyMod                          : \"\\EOQ\"\nkey F3          -AnyMod                          : \"\\EOR\"\nkey F4          -AnyMod                          : \"\\EOS\"\nkey F5          -AnyMod                          : \"\\E[15~\"\nkey F6          -AnyMod                          : \"\\E[17~\"\nkey F7          -AnyMod                          : \"\\E[18~\"\nkey F8          -AnyMod                          : \"\\E[19~\"\nkey F9          -AnyMod                          : \"\\E[20~\"\nkey F10         -AnyMod                          : \"\\E[21~\"\nkey F11         -AnyMod                          : \"\\E[23~\"\nkey F12         -AnyMod                          : \"\\E[24~\"\n\nkey F1          +AnyMod                          : \"\\EO*P\"\nkey F2          +AnyMod                          : \"\\EO*Q\"\nkey F3          +AnyMod                          : \"\\EO*R\"\nkey F4          +AnyMod                          : \"\\EO*S\"\nkey F5          +AnyMod                          : \"\\E[15;*~\"\nkey F6          +AnyMod                          : \"\\E[17;*~\"\nkey F7          +AnyMod                          : \"\\E[18;*~\"\nkey F8          +AnyMod                          : \"\\E[19;*~\"\nkey F9          +AnyMod                          : \"\\E[20;*~\"\nkey F10         +AnyMod                          : \"\\E[21;*~\"\nkey F11         +AnyMod                          : \"\\E[23;*~\"\nkey F12         +AnyMod                          : \"\\E[24;*~\"\n\n# Work around dead keys\n\nkey Space +Control : \"\\x00\"\n\n# Some keys are used by konsole to cause operations.\n# The scroll* operations refer to the history buffer.\n\nkey Up    +Shift-AppScreen  : scrollLineUp\nkey Prior +Shift-AppScreen  : scrollPageUp\nkey Down  +Shift-AppScreen  : scrollLineDown\nkey Next  +Shift-AppScreen  : scrollPageDown\n\n#key Up    +Shift  : scrollLineUp\n#key Prior +Shift  : scrollPageUp\n#key Down  +Shift  : scrollLineDown\n#key Next  +Shift  : scrollPageDown\n\nkey ScrollLock     : scrollLock\n\n# keypad characters are not offered differently by Qt.\n"
  },
  {
    "path": "libgui/kb-layouts/linux.keytab",
    "content": "# [linux.keytab] Konsole Keyboard Table (Linux console keys)\n#\n# --------------------------------------------------------------\n\n# NOT TESTED, MAY NEED SOME CLEANUPS\nkeyboard \"Linux console\"\n\n# --------------------------------------------------------------\n#\n# This configuration table allows to customize the\n# meaning of the keys.\n#\n# The syntax is that each entry has the form :\n#\n#   \"key\" Keyname { (\"+\"|\"-\") Modename } \":\" (String|Operation)\n#\n# Keynames are those defined in <qnamespace.h> with the\n# \"Qt::Key_\" removed. (We'd better insert the list here)\n#\n# Mode names are :\n#\n# - Shift\n# - Alt\n# - Control\n#\n#   The VT100 emulation has two modes that can affect the\n#   sequences emitted by certain keys. These modes are\n#   under control of the client program.\n#\n# - Newline     : effects Return and Enter key.\n# - Application : effects Up and Down key.\n#\n# - Ansi        : effects Up and Down key (This is for VT52, really).\n#\n# Operations are\n#\n# - scrollUpLine\n# - scrollUpPage\n# - scrollDownLine\n# - scrollDownPage\n#\n# - emitSelection\n#\n# If the key is not found here, the text of the\n# key event as provided by QT is emitted, possibly\n# preceded by ESC if the Alt key is pressed.\n#\n# --------------------------------------------------------------\n\nkey Escape : \"\\E\"\nkey Tab    : \"\\t\"\n\n# VT100 can add an extra \\n after return.\n# The NewLine mode is set by an escape sequence.\n\nkey Return-NewLine : \"\\r\"\nkey Return+NewLine : \"\\r\\n\"\n\n# Some desperately try to save the ^H.\n\nkey Backspace : \"\\x7f\"\nkey Delete    : \"\\E[3~\"\n\n# These codes are for the VT52 mode of VT100\n# The Ansi mode (i.e. VT100 mode) is set by\n# an escape sequence\n\nkey Up   -Shift-Ansi : \"\\EA\"\nkey Down -Shift-Ansi : \"\\EB\"\nkey Right-Shift-Ansi : \"\\EC\"\nkey Left -Shift-Ansi : \"\\ED\"\n\n# VT100 emits a mode bit together\n# with the arrow keys.The AppCuKeys\n# mode is set by an escape sequence.\n\nkey Up   -Shift+Ansi+AppCuKeys : \"\\EOA\"\nkey Down -Shift+Ansi+AppCuKeys : \"\\EOB\"\nkey Right-Shift+Ansi+AppCuKeys : \"\\EOC\"\nkey Left -Shift+Ansi+AppCuKeys : \"\\EOD\"\n\nkey Up   -Shift+Ansi-AppCuKeys : \"\\E[A\"\nkey Down -Shift+Ansi-AppCuKeys : \"\\E[B\"\nkey Right-Shift+Ansi-AppCuKeys : \"\\E[C\"\nkey Left -Shift+Ansi-AppCuKeys : \"\\E[D\"\n\n# linux functions keys F1-F5 differ from xterm\n\nkey F1 : \"\\E[[A\"\nkey F2 : \"\\E[[B\"\nkey F3 : \"\\E[[C\"\nkey F4 : \"\\E[[D\"\nkey F5 : \"\\E[[E\"\n\nkey F6     : \"\\E[17~\"\nkey F7     : \"\\E[18~\"\nkey F8     : \"\\E[19~\"\nkey F9     : \"\\E[20~\"\nkey F10    : \"\\E[21~\"\nkey F11    : \"\\E[23~\"\nkey F12    : \"\\E[24~\"\n\nkey Home   : \"\\E[1~\"\nkey End    : \"\\E[4~\"\n\nkey Prior -Shift : \"\\E[5~\"\nkey Next  -Shift : \"\\E[6~\"\nkey Insert-Shift : \"\\E[2~\"\n\n# Keypad-Enter. See comment on Return above.\n\nkey Enter+NewLine : \"\\r\\n\"\nkey Enter-NewLine : \"\\r\"\n\nkey Space +Control : \"\\x00\"\n\n# some of keys are used by konsole.\n\nkey Up    +Shift   : scrollLineUp\nkey Prior +Shift   : scrollPageUp\nkey Down  +Shift   : scrollLineDown\nkey Next  +Shift   : scrollPageDown\n\nkey ScrollLock     : scrollLock\n\n#----------------------------------------------------------\n\n# keypad characters as offered by Qt\n# cannot be recognized as such.\n\n#----------------------------------------------------------\n\n# Following other strings as emitted by konsole.\n"
  },
  {
    "path": "libgui/kb-layouts/vt420pc.keytab",
    "content": "# [vt420pc.keytab] Konsole Keyboard Table (VT420pc keys)\n# adapted by ferdinand gassauer f.gassauer@aon.at\n# Nov 2000\n#\n################################################################\n#\n# The escape sequences emitted by the\n# keys Shift+F1 to Shift+F12 might not fit your needs\n#\n################# IMPORTANT NOTICE #############################\n# the key bindings (Kcontrol -> look and feel -> keybindgs)\n# overrule the settings in this file. The key bindings might be\n# changed by the user WITHOUT notification of the maintainer of\n# the keytab file. Konsole will not work as expected by\n# the maintainer of the keytab file.\n################################################################\n#\n# --------------------------------------------------------------\n\nkeyboard \"DEC VT420 Terminal\"\n\n# --------------------------------------------------------------\n#\n# This configuration table allows to customize the\n# meaning of the keys.\n#\n# The syntax is that each entry has the form :\n#\n#   \"key\" Keyname { (\"+\"|\"-\") Modename } \":\" (String|Operation)\n#\n# Keynames are those defined in <qnamespace.h> with the\n# \"Qt::Key_\" removed. (We'd better insert the list here)\n#\n# Mode names are :\n#\n# - Shift\n# - Alt\n# - Control\n#\n#   The VT100 emulation has two modes that can affect the\n#   sequences emitted by certain keys. These modes are\n#   under control of the client program.\n#\n# - Newline     : effects Return and Enter key.\n# - Application : effects Up and Down key.\n#\n# - Ansi        : effects Up and Down key (This is for VT52, really).\n#\n# Operations are\n#\n# - scrollUpLine\n# - scrollUpPage\n# - scrollDownLine\n# - scrollDownPage\n#\n# - emitSelection\n#\n# If the key is not found here, the text of the\n# key event as provided by QT is emitted, possibly\n# preceded by ESC if the Alt key is pressed.\n#\n# --------------------------------------------------------------\n\nkey Escape : \"\\E\"\nkey Tab    : \"\\t\"\nkey Backtab: \"\\E[Z\"\n\n# VT100 can add an extra \\n after return.\n# The NewLine mode is set by an escape sequence.\n\nkey Return-NewLine : \"\\r\"\nkey Return+NewLine : \"\\r\\n\"\n\n# Some desperately try to save the ^H.\n# may be not everyone wants this\n\nkey Backspace : \"\\x08\"  # Control H\nkey Delete    : \"\\x7f\"\n\n# These codes are for the VT420pc\n# The Ansi mode (i.e. VT100 mode) is set by\n# an escape sequence\n\nkey Up   -Shift-Ansi : \"\\EA\"\nkey Down -Shift-Ansi : \"\\EB\"\nkey Right-Shift-Ansi : \"\\EC\"\nkey Left -Shift-Ansi : \"\\ED\"\n\n# VT100 emits a mode bit together\n# with the arrow keys.The AppCuKeys\n# mode is set by an escape sequence.\n\nkey Up   -Shift+Ansi+AppCuKeys : \"\\EOA\"\nkey Down -Shift+Ansi+AppCuKeys : \"\\EOB\"\nkey Right-Shift+Ansi+AppCuKeys : \"\\EOC\"\nkey Left -Shift+Ansi+AppCuKeys : \"\\EOD\"\n\nkey Up   -Shift+Ansi-AppCuKeys : \"\\E[A\"\nkey Down -Shift+Ansi-AppCuKeys : \"\\E[B\"\nkey Right-Shift+Ansi-AppCuKeys : \"\\E[C\"\nkey Left -Shift+Ansi-AppCuKeys : \"\\E[D\"\n\n# function keys\n\nkey F1 -Shift    : \"\\E[11~\"\nkey F2 -Shift    : \"\\E[12~\"\nkey F3 -Shift    : \"\\E[13~\"\nkey F4 -Shift    : \"\\E[14~\"\nkey F5 -Shift    : \"\\E[15~\"\nkey F6 -Shift    : \"\\E[17~\"\nkey F7 -Shift    : \"\\E[18~\"\nkey F8 -Shift    : \"\\E[19~\"\nkey F9 -Shift    : \"\\E[20~\"\nkey F10-Shift    : \"\\E[21~\"\nkey F11-Shift    : \"\\E[23~\"\nkey F12-Shift    : \"\\E[24~\"\n#\n# Shift F1-F12\n#\nkey F1 +Shift    : \"\\E[11;2~\"\nkey F2 +Shift    : \"\\E[12;2~\"\nkey F3 +Shift    : \"\\E[13;2~\"\nkey F4 +Shift    : \"\\E[14;2~\"\nkey F5 +Shift    : \"\\E[15;2~\"\nkey F6 +Shift    : \"\\E[17;2~\"\nkey F7 +Shift    : \"\\E[18;2~\"\nkey F8 +Shift    : \"\\E[19;2~\"\nkey F9 +Shift    : \"\\E[20;2~\"\nkey F10+Shift    : \"\\E[21;2~\"\nkey F11+Shift    : \"\\E[23;2~\"\nkey F12+Shift    : \"\\E[24;2~\"\n\nkey Home   : \"\\E[H\"\nkey End    : \"\\E[F\"\n\nkey Prior -Shift : \"\\E[5~\"\nkey Next  -Shift : \"\\E[6~\"\nkey Insert-Shift : \"\\E[2~\"\n\n# Keypad-Enter. See comment on Return above.\n\nkey Enter+NewLine : \"\\r\\n\"\nkey Enter-NewLine : \"\\r\"\n\nkey Space +Control : \"\\x00\"\n\n# some of keys are used by konsole.\n\nkey Up    +Shift   : scrollLineUp\nkey Prior +Shift   : scrollPageUp\nkey Down  +Shift   : scrollLineDown\nkey Next  +Shift   : scrollPageDown\n\nkey ScrollLock     : scrollLock\n\n#----------------------------------------------------------\n\n# keypad characters as offered by Qt\n# cannot be recognized as such.\n\n#----------------------------------------------------------\n\n# Following other strings as emitted by konsole.\n"
  },
  {
    "path": "libgui/languages/ast_ES.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"es_ES\">\n<context>\n    <name>QApplication</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qmessagebox.cpp\" line=\"+2902\"/>\n        <source>Application &quot;%1&quot; requires Qt %2, found Qt %3.</source>\n        <translation>L&apos;aplicación %1 requier Qt %2, topose Qt %3.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Incompatible Qt Library Error</source>\n        <translation>Error de compatibilidá de la biblioteca Qt</translation>\n    </message>\n</context>\n<context>\n    <name>QColorDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qcolordialog.cpp\" line=\"+1473\"/>\n        <source>Hu&amp;e:</source>\n        <translation>&amp;Tonu:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Sat:</source>\n        <translation>&amp;Saturación:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Val:</source>\n        <translation>&amp;Valor:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Red:</source>\n        <translation>Collo&amp;ráu:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Green:</source>\n        <translation>&amp;Verde:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bl&amp;ue:</source>\n        <translation>Az&amp;ul:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A&amp;lpha channel:</source>\n        <translation>Canal a&amp;lfa:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;HTML:</source>\n        <translation>&amp;HTML:</translation>\n    </message>\n    <message>\n        <location line=\"+184\"/>\n        <source>Cursor at %1, %2\nPress ESC to cancel</source>\n        <translation>Cursor en %1, %2\nCalcar ESC pa cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>Select Color</source>\n        <translation>Seleicionar color</translation>\n    </message>\n    <message>\n        <location line=\"+204\"/>\n        <source>&amp;Basic colors</source>\n        <translation>Colores &amp;básicos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Custom colors</source>\n        <translation>&amp;Colores personalizáos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add to Custom Colors</source>\n        <translation>&amp;Amestar a los colores personalizáos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Pick Screen Color</source>\n        <translation>Escoyer color de &amp;pantalla</translation>\n    </message>\n</context>\n<context>\n    <name>QDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qdialog.cpp\" line=\"+677\"/>\n        <source>What&apos;s This?</source>\n        <translation>¿Qué ye esto?</translation>\n    </message>\n</context>\n<context>\n    <name>QDialogButtonBox</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qmessagebox.cpp\" line=\"-793\"/>\n        <location line=\"+452\"/>\n        <source>OK</source>\n        <translation>OK</translation>\n    </message>\n</context>\n<context>\n    <name>QErrorMessage</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qerrormessage.cpp\" line=\"+86\"/>\n        <source>An error occurred</source>\n        <translation>Ocurrió un error</translation>\n    </message>\n    <message>\n        <location line=\"+91\"/>\n        <source>Debug Message:</source>\n        <translation>Mensaxe de depuración:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Warning:</source>\n        <translation>Avisu:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Critical Error:</source>\n        <translation>Error críticu:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Fatal Error:</source>\n        <translation>Error fatal:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Information:</source>\n        <translation>Información:</translation>\n    </message>\n    <message>\n        <location line=\"+256\"/>\n        <source>&amp;Show this message again</source>\n        <translation>Amo&amp;sar esti mensaxe otra vez</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;OK</source>\n        <translation>&amp;OK</translation>\n    </message>\n</context>\n<context>\n    <name>QFileDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfiledialog.cpp\" line=\"+582\"/>\n        <location filename=\"build_ts/octave-qt/qfiledialog_symbian.cpp\" line=\"+192\"/>\n        <source>Find Directory</source>\n        <translation>Direutoriu atopáu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open</source>\n        <translation>Abrir</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Save As</source>\n        <translation>Guardar como</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Directory:</source>\n        <translation>Direutoriu:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File &amp;name:</source>\n        <translation>&amp;Nome del ficheru:</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <location line=\"+12\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Abrir</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>&amp;Choose</source>\n        <translation>Es&amp;coyer</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Save</source>\n        <translation>&amp;Guardar</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Show </source>\n        <translation>Ver </translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Renomar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Delete</source>\n        <translation>&amp;Borrar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show &amp;hidden files</source>\n        <translation>Ver ficheros &amp;ocultos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;New Folder</source>\n        <translation>&amp;Nuevu direutoriu</translation>\n    </message>\n    <message>\n        <location line=\"+859\"/>\n        <source>All files (*)</source>\n        <translation>Toos los ficheros (*)</translation>\n    </message>\n    <message>\n        <location line=\"+171\"/>\n        <source>Directories</source>\n        <translation>Direutorios</translation>\n    </message>\n    <message>\n        <location line=\"+973\"/>\n        <source>%1 already exists.\nDo you want to replace it?</source>\n        <translation>%1 ya esiste.\n¿Quier reemplazalu?</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <location line=\"+1120\"/>\n        <source>%1\nDirectory not found.\nPlease verify the correct directory name was given.</source>\n        <translation>%1\nDireutoriu nun atopáu.\nPor favor, verifique qu&apos;indicó&apos;l nome correutu.</translation>\n    </message>\n    <message>\n        <location line=\"-1118\"/>\n        <source>%1\nFile not found.\nPlease verify the correct file name was given.</source>\n        <translation>%1\nFicheru nun atopáu.\nPor favor, verifique qu&apos;indicó&apos;l nome correutu.</translation>\n    </message>\n    <message>\n        <location line=\"+762\"/>\n        <source>New Folder</source>\n        <translation>Nueva carpeta</translation>\n    </message>\n    <message>\n        <location line=\"+130\"/>\n        <location line=\"+5\"/>\n        <source>Delete</source>\n        <translation>Eliminar</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>&apos;%1&apos; is write protected.\nDo you want to delete it anyway?</source>\n        <translation>&apos;%1&apos; ta protexío contra escritura.\n¿Quier borralo igualmente?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Are you sure you want to delete &apos;%1&apos;?</source>\n        <translation>¿Ta seguru de que quier borrar &apos;%1&apos;?</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Could not delete directory.</source>\n        <translation>Nun se pudo borrar el direutoriu.</translation>\n    </message>\n    <message>\n        <location line=\"+441\"/>\n        <source>Recent Places</source>\n        <translation>Llugares recientes</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfiledialog_win.cpp\" line=\"+131\"/>\n        <source>All Files (*.*)</source>\n        <translation>Toos los ficheros (*.*)</translation>\n    </message>\n</context>\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translatorcomment>Ye nun porque va delantre d&apos;una forma verbal</translatorcomment>\n        <translation>Nome de ficheru nun válidu</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfilesystemmodel.cpp\" line=\"+964\"/>\n        <source>Name</source>\n        <translation>Nome</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Size</source>\n        <translation>Tamañu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Kind</source>\n        <comment>Match OS X Finder</comment>\n        <translation>Tipu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Type</source>\n        <comment>All other platforms</comment>\n        <translation>Tipu</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Date Modified</source>\n        <translation>Fecha de modificación</translation>\n    </message>\n</context>\n<context>\n    <name>QFontDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfontdialog.cpp\" line=\"+141\"/>\n        <source>Select Font</source>\n        <translation>Seleicionar fonte</translation>\n    </message>\n    <message>\n        <location line=\"+600\"/>\n        <source>&amp;Font</source>\n        <translation>&amp;Fonte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Font st&amp;yle</source>\n        <translation>&amp;Estilu de fonte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Size</source>\n        <translation>&amp;Tamañu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Effects</source>\n        <translation>Efeutos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stri&amp;keout</source>\n        <translation>&amp;Tachar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Underline</source>\n        <translation>S&amp;ubrayar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sample</source>\n        <translation>Exemplu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Wr&amp;iting System</source>\n        <translation>Sistema de cod&amp;ificación</translation>\n    </message>\n</context>\n<context>\n    <name>QHelpSearchQueryWidget</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qhelpsearchquerywidget.cpp\" line=\"+62\"/>\n        <source>Search for:</source>\n        <translation>Buscar:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search</source>\n        <translation>Buscar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Previous search</source>\n        <translation>Búsqueda previa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next search</source>\n        <translation>Búsqueda siguiente</translation>\n    </message>\n</context>\n<context>\n    <name>QInputDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qinputdialog.cpp\" line=\"+209\"/>\n        <source>Enter a value:</source>\n        <translation>Introduzca un valor:</translation>\n    </message>\n</context>\n<context>\n    <name>QMessageBox</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qmessagebox.cpp\" line=\"-2404\"/>\n        <source>Show Details...</source>\n        <translation>Ver detalles...</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source>Hide Details...</source>\n        <translation>Ancultar detalles...</translation>\n    </message>\n    <message>\n        <location line=\"+1815\"/>\n        <source>&lt;h3&gt;About Qt&lt;/h3&gt;&lt;p&gt;This program uses Qt version %1.&lt;/p&gt;</source>\n        <translation>&lt;h3&gt;Sobre Qt&lt;/h3&gt;&lt;p&gt;Esti programa usa Qt versión %1.&lt;/p&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&lt;p&gt;Qt is a C++ toolkit for cross-platform application development.&lt;/p&gt;&lt;p&gt;Qt provides single-source portability across all major desktop operating systems. It is also available for embedded Linux and other embedded and mobile operating systems.&lt;/p&gt;&lt;p&gt;Qt is available under multiple licensing options designed to accommodate the needs of our various users.&lt;/p&gt;&lt;p&gt;Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of GNU (L)GPL.&lt;/p&gt;&lt;p&gt;Qt licensed under GNU (L)GPL is appropriate for the development of Qt&amp;nbsp;applications provided you can comply with the terms and conditions of the respective licenses.&lt;/p&gt;&lt;p&gt;Please see &lt;a href=&quot;https://%2/&quot;&gt;%2&lt;/a&gt; for an overview of Qt licensing.&lt;/p&gt;&lt;p&gt;Copyright (C) The Qt Company Ltd. and other contributors.&lt;/p&gt;&lt;p&gt;Qt and the Qt logo are trademarks of The Qt Company Ltd.&lt;/p&gt;&lt;p&gt;Qt is The Qt Company Ltd. product developed as an open source project. See &lt;a href=&quot;https://%3/&quot;&gt;%3&lt;/a&gt; for more information.&lt;/p&gt;</source>\n        <extracomment>Leave this text untranslated or include a verbatim copy of it below and note that it is the authoritative version in case of doubt.</extracomment>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+26\"/>\n        <source>About Qt</source>\n        <translation>Sobre Qt</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Diferencia col tamañu predetermináu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Color de fondu. Predetermináu a maxenta (255,0,255)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translatorcomment>Abreviatura pa caracteres en negrita</translatorcomment>\n        <translation>b</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translatorcomment>Abreviatura pa caracteres en cursiva</translatorcomment>\n        <translation>c</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translatorcomment>Abreviatura pa caracteres subrayados</translatorcomment>\n        <translation>s</translation>\n    </message>\n</context>\n<context>\n    <name>QPageSetupWidget</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_unix.cpp\" line=\"+260\"/>\n        <source>Millimeters (mm)</source>\n        <translation>Milímetros (mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Inches (in)</source>\n        <translation>Pulgaes (in)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Points (pt)</source>\n        <translation>Puntos (pt)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Pica (P̸)</source>\n        <translation>Piques (P̸)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Didot (DD)</source>\n        <translation>Didots (DD)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cicero (CC)</source>\n        <translation>Ciceros (CC)</translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <location line=\"+17\"/>\n        <source>Custom</source>\n        <translation>Personalizáo</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>mm</source>\n        <extracomment>Unit &apos;Millimeter&apos;</extracomment>\n        <translation>mm</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>pt</source>\n        <extracomment>Unit &apos;Points&apos;</extracomment>\n        <translation>pt</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>in</source>\n        <extracomment>Unit &apos;Inch&apos;</extracomment>\n        <translation>in</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>P̸</source>\n        <extracomment>Unit &apos;Pica&apos;</extracomment>\n        <translation>P̸</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>DD</source>\n        <extracomment>Unit &apos;Didot&apos;</extracomment>\n        <translation>DD</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>CC</source>\n        <extracomment>Unit &apos;Cicero&apos;</extracomment>\n        <translation>CC</translation>\n    </message>\n</context>\n<context>\n    <name>QPlatformTheme</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qplatformtheme.cpp\" line=\"+793\"/>\n        <source>OK</source>\n        <translation>OK</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Save</source>\n        <translation>Guardar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Save All</source>\n        <translation>Guardar too</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open</source>\n        <translation>Abrir</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Yes</source>\n        <translation>&amp;Sí</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Yes to &amp;All</source>\n        <translation>&amp;Sí a too</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;No</source>\n        <translation>&amp;Non</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>N&amp;o to All</source>\n        <translation>N&amp;on a too</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Abort</source>\n        <translation>Abortar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Retry</source>\n        <translation>Raintenar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Ignore</source>\n        <translation>Inorar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Close</source>\n        <translation>Zarrar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Discard</source>\n        <translation>Descartar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Help</source>\n        <translation>Ayuda</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Apply</source>\n        <translation>Aplicar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reset</source>\n        <translation>Reiniciar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Restore Defaults</source>\n        <translation>Restaurar a valores por defeutu</translation>\n    </message>\n</context>\n<context>\n    <name>QPrintDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qabstractprintdialog.cpp\" line=\"+61\"/>\n        <location line=\"+16\"/>\n        <location filename=\"build_ts/octave-qt/qprintdialog_win.cpp\" line=\"+239\"/>\n        <source>Print</source>\n        <translation>Imprimir</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_unix.cpp\" line=\"-155\"/>\n        <source>Left to Right, Top to Bottom</source>\n        <translation>Izquierda a derecha, arriba a abaxo</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Left to Right, Bottom to Top</source>\n        <translation>Izquierda a derecha, abaxo a arriba</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Right to Left, Bottom to Top</source>\n        <translation>Derecha a izquierda, abaxo a arriba</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Right to Left, Top to Bottom</source>\n        <translation>Derecha a izquierda, arriba a abaxo</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Bottom to Top, Left to Right</source>\n        <translation>Abaxo a arriba, izquierda a derecha</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Bottom to Top, Right to Left</source>\n        <translation>Abaxo a arriba, derecha a izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Top to Bottom, Left to Right</source>\n        <translation>Arriba a abaxo, izquierda a derecha</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Top to Bottom, Right to Left</source>\n        <translation>Arriba a abaxo, derecha a izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>1 (1x1)</source>\n        <translation>1 (1x1)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>2 (2x1)</source>\n        <translation>2 (2x1)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>4 (2x2)</source>\n        <translation>4 (2x2)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>6 (2x3)</source>\n        <translation>6 (2x3)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>9 (3x3)</source>\n        <translation>9 (3x3)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>16 (4x4)</source>\n        <translation>16 (4x4)</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_qws.cpp\" line=\"+148\"/>\n        <source>File exists</source>\n        <translation>El ficheru esiste</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&lt;qt&gt;Do you want to overwrite it?&lt;/qt&gt;</source>\n        <translation>&lt;qt&gt;¿Quier reescribilu?&lt;/qt&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+184\"/>\n        <source>A0 (841 x 1189 mm)</source>\n        <translation>A0 (841 x 1189 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A1 (594 x 841 mm)</source>\n        <translation>A1 (594 x 841 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A2 (420 x 594 mm)</source>\n        <translation>A2 (420 x 594 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A3 (297 x 420 mm)</source>\n        <translation>A3 (297 x 420 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A4 (210 x 297 mm, 8.26 x 11.7 inches)</source>\n        <translation>A4 (210 x 297 mm, 8.26 x 11.7 in)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A5 (148 x 210 mm)</source>\n        <translation>A5 (148 x 210 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A6 (105 x 148 mm)</source>\n        <translation>A6 (105 x 148 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A7 (74 x 105 mm)</source>\n        <translation>A7 (74 x 105 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A8 (52 x 74 mm)</source>\n        <translation>A8 (52 x 74 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A9 (37 x 52 mm)</source>\n        <translation>A9 (37 x 52 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B0 (1000 x 1414 mm)</source>\n        <translation>B0 (1000 x 1414 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B1 (707 x 1000 mm)</source>\n        <translation>B1 (707 x 1000 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B2 (500 x 707 mm)</source>\n        <translation>B2 (500 x 707 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B3 (353 x 500 mm)</source>\n        <translation>B3 (353 x 500 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B4 (250 x 353 mm)</source>\n        <translation>B4 (250 x 353 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B5 (176 x 250 mm, 6.93 x 9.84 inches)</source>\n        <translation>B5 (176 x 250 mm, 6.93 x 9.84 in)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B6 (125 x 176 mm)</source>\n        <translation>B6 (125 x 176 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B7 (88 x 125 mm)</source>\n        <translation>B7 (88 x 125 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B8 (62 x 88 mm)</source>\n        <translation>B8 (62 x 88 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B9 (44 x 62 mm)</source>\n        <translation>B9 (44 x 62 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B10 (31 x 44 mm)</source>\n        <translation>B10 (31 x 44 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>C5E (163 x 229 mm)</source>\n        <translation>C5E (163 x 229 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>DLE (110 x 220 mm)</source>\n        <translation>DLE (110 x 220 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Executive (7.5 x 10 inches, 191 x 254 mm)</source>\n        <translation>Executivu (191 x 254 mm, 7.5 x 10 in)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Folio (210 x 330 mm)</source>\n        <translation>Foliu (210 x 330 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Ledger (432 x 279 mm)</source>\n        <translation>Llibru de contabilidá (432 x 279 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Legal (8.5 x 14 inches, 216 x 356 mm)</source>\n        <translation>Llegal (216 x 356 mm, 8.5 x 14 in)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Letter (8.5 x 11 inches, 216 x 279 mm)</source>\n        <translation>Carta (216 x 279 mm, 8.5 x 11 in)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Tabloid (279 x 432 mm)</source>\n        <translation>Tabloide (279 x 432 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>US Common #10 Envelope (105 x 241 mm)</source>\n        <translation>Sobre #10 de EEUU (105 x 241 mm)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Print all</source>\n        <translation>Imprimir too</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print selection</source>\n        <translation>Imprimir seleición</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print range</source>\n        <translation>Imprimir rangu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print current page</source>\n        <translation>Imprimir la páxina actual</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_unix.cpp\" line=\"+608\"/>\n        <source>All Pages</source>\n        <translation>Toes les páxines</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Odd Pages</source>\n        <translation>Páxines impares</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Even Pages</source>\n        <translation>Páxines pares</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <location line=\"+224\"/>\n        <source>&amp;Options &gt;&gt;</source>\n        <translation>&amp;Opciones &gt;&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>&amp;Print</source>\n        <translation>Im&amp;primir</translation>\n    </message>\n    <message>\n        <location line=\"+223\"/>\n        <source>&amp;Options &lt;&lt;</source>\n        <translation>&amp;Opciones &lt;&lt;</translation>\n    </message>\n    <message>\n        <location line=\"+148\"/>\n        <source>Invalid Pages Definition</source>\n        <translation>Definición inválida de páxines</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 does not follow the correct syntax. Please use &apos;,&apos; to separate ranges and pages, &apos;-&apos; to define ranges and make sure ranges do not intersect with each other.</source>\n        <translation>%1 nun sigue la sintaxis correuta. Por favor, emplegue &apos;,&apos; pa separar rangos y páxines, &apos;-&apos; pa definir rangos y asegúrese de que los rangos nun se cruzan unos con otros.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Duplex Settings Conflicts</source>\n        <translation>Conflictos cola configuración de la impresión a doble cara</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>There are conflicts in duplex settings. Do you want to fix them?</source>\n        <translation>Hay conflictos cola configuración de la impresión a doble cara. ¿Quier arreglalos?</translation>\n    </message>\n    <message>\n        <location line=\"+76\"/>\n        <source>Print to File (PDF)</source>\n        <translation>Imprimir a ficheru (PDF)</translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <source>Local file</source>\n        <translation>Ficheru local</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Write PDF file</source>\n        <translation>Escribir ficheru PDF</translation>\n    </message>\n    <message>\n        <location line=\"+47\"/>\n        <source>Print To File ...</source>\n        <translation>Imprimir a ficheru...</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>%1 is a directory.\nPlease choose a different file name.</source>\n        <translation>%1 ye un direutoriu.\nPor favor, escoya otru nome diferente.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>File %1 is not writable.\nPlease choose a different file name.</source>\n        <translation>Nun se pue escribir nel ficheru %1.\nPor favor, escoya otru nome diferente.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>%1 already exists.\nDo you want to overwrite it?</source>\n        <translation>%1 ya esiste.\n¿Quier sobreescribilu?</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Options &apos;Pages Per Sheet&apos; and &apos;Page Set&apos; cannot be used together.\nPlease turn one of those options off.</source>\n        <translation>Les opciones &apos;páxines per fueya&apos; y &apos;asignar páxina&apos; nun se puen usar xuntes.\nPor favor, escoya una sola de les dos.</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_win.cpp\" line=\"+1\"/>\n        <source>The &apos;From&apos; value cannot be greater than the &apos;To&apos; value.</source>\n        <translation>El valor &apos;desde&apos; nun pue ser mayor que &apos;hasta&apos;.</translation>\n    </message>\n</context>\n<context>\n    <name>QPrintPreviewDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qabstractpagesetupdialog.cpp\" line=\"+68\"/>\n        <location line=\"+12\"/>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_unix.cpp\" line=\"+389\"/>\n        <location line=\"+8\"/>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_win.cpp\" line=\"+18\"/>\n        <location line=\"+7\"/>\n        <source>Page Setup</source>\n        <translation>Configuración de páxina</translation>\n    </message>\n</context>\n<context>\n    <name>QPrintPropertiesDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_unix.cpp\" line=\"-987\"/>\n        <source>Printer Properties</source>\n        <translation>Propiedaes de la impresora</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Job Options</source>\n        <translation>Opciones del trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Page Setup Conflicts</source>\n        <translation>Conflictos de la configuración de páxina</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>There are conflicts in page setup options. Do you want to fix them?</source>\n        <translation>Hay conflictos coles opciones de configuración de páxina. ¿Quier arreglalos?</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Advanced Option Conflicts</source>\n        <translation>Conflictos con opciones avanzaes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>There are conflicts in some advanced options. Do you want to fix them?</source>\n        <translation>Hay conflictos en dalgunes opciones avanzaes. ¿Quier arreglalos?</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>Editar &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Ayuda de &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Documentación de &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Apegar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Seleicionar too</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Executar seleición</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>Editar seleición</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>Ayuda de la seleición</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>Documentación de la seleición</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Llimpiar ventana</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Editar %1 en llinia %2</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>seleición copiada al portapapeles</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>Por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Error</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentariu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Númberu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Pallabra clave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Cadena con comilles dobles</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Cadena con comilles simples</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Escalar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>Expansión de parámetros</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Acentos graves</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Delimitador de documentu equí</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Documentu ente comilles simples equí</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>Por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentariu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Pallabra clave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>Etiqueta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>Ancultar caráuter de comandu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>Comandu esternu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Variable</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>Por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>Inactivu por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>Comentariu de C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>Comentariu de C inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>Comentariu de C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>Comentariu de C++ inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>Comentariu de JavaDoc al estilu de C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>Comentariu de JavaDoc al estilu de C inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Númberu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Númberu inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Pallabra clave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Pallabra clave inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Cadena de testu con comilles dobles</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>Cadena de testu con comilles dobles inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Cadena de testu con comilles simples</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>Cadena de testu con comilles simples inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>IDL UUID inactivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>Bloque de preprocesador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>Bloque de preprocesador inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Operador inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Identificador inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>Cadena en sin zarrar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>Cadena en sin zarrar inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>Cadena C# literal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>Cadena C# literal inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>Espresión regular de JavaScript</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>Espresión regular de JavaScript inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>Comentario de JavaDoc en estilo C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>Comentario de JavaDoc en estilo C++ inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>Pallabres clave e identificadores secundarios</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Pallabres clave e identificadores secundarios inactivos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>Pallabra clave de JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>Pallabra clave de JavaDoc inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>Pallabra clave de error de JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>Pallabra clave de error de JavaDoc inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Clases globales y typedefs</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Clases globales y typedefs inactivos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>Cadena de C++ bruta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>Cadena de C++ bruta inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation>Cadena con comillas triples de Vala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation>Cadena con comillas triples de Vala inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation>Cadena hash-quoted de Pike</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation>Cadena hash-quoted de Pike inactiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation>Comentariu del preprocesador de C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation>Comentariu del preprocesador de C inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation>Comentariu del preprocesador en estilu JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation>Comentariu del preprocesador en estilu JavaDoc inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation>Literal definiu pol usuariu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation>Literal definiu pol usuariu inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation>Marcador de tarea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation>Marcador de tarea inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation>Secuencia d&apos;escape</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation>Secuencia d&apos;escape inactiva</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>Por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentariu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Comandu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>Cabecera</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Posición</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Llína borrada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Llínia añadía</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Linia cambiada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation>Añadíu parche d&apos;adición</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation>Elimináu parche d&apos;adición</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation>Añadíu parche d&apos;eliminación</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation>Elimináu parche d&apos;eliminación</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>Por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentariu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Comandu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Númberu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Pallabra clave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Cadena con comilles simples</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Cadena con comilles dobles</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>Por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Error</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentariu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Númberu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Pallabra clave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Cadena con comilles dobles</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Cadena con comilles simples</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Escalar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>Vector</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>Hash</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Tabla de símbolos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>Espresión regular</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>Sustitución</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Acentos graves</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>Seición de datos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Delimitador de documentu equí</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Documentu ente comilles simples equí</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>Documentu ente comilles dobles equí</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>Documentu ente acentos graves equí</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>Cadena entrecomillada (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>Cadena entrecomillada (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>Cadena entrecomillada (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>Cadena entrecomillada (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>Cadena entrecomillada (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>POD literal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>Prototipu de subrutina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>Identificador de formatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>Cuerpu del formatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>Cadena con comilles dobles (variable interpolada)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>Traducción</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>Espresión regular (variable interpolada)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>Sustitución (variable interpolada)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>Acentos graves (variable interpolada)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>Documentu ente comilles dobles equí (variable interpolada)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>Documentu ente acentos graves equí (variable interpolada)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>Cadena entrecomillada (qq, variable interpolada)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>Cadena entrecomillada (qx, variable interpolada)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>Cadena entrecomillada (qr, variable interpolada)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>&amp;Desfacer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Refacer</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>Cor&amp;tar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>&amp;Pegar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Eliminar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Seleicionar too</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Abrir enllace</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Copiar direición d&apos;enllace</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Enviar un corréu electrónicu a...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>Copiar la direición de corréu electrónicu</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Editar %1 en llinia %2</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Anotación</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Testu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Cadena de testu</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Tipu de fonte</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>negrita</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>n</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>cursiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>c</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>color</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>centru</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>derecha</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>Alliniación horizontal</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>Alliniación vertical</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translatorcomment>Aquí dudo si va neutru o non. Nun sé si &quot;parte&quot; ye incontable</translatorcomment>\n        <translation>parte cimero</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translatorcomment>Aquí dudo si va neutru o non. Nun sé si &quot;parte&quot; ye incontable</translatorcomment>\n        <translation>parte baxero</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Posición</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Anchor</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Altor</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>Unidaes</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalizao</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Axustar a cuadru</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Cuadru</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translatorcomment>En este contexto es más adecuada la traducción &quot;fondo&quot; en lugar de &quot;segundo plano&quot;</translatorcomment>\n        <translation>Fondu</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translatorcomment>Borde u orilla</translatorcomment>\n        <translation>Borde</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Estilu de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>nengún</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Anchor de llinia</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Seleicionar too</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Pausa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Parar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Siguir</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Widget de comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Noticies de la comunidá d&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>Valor predetermináu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Error</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>Entrada d&apos;ordes</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Documentación d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>Nun se pudo copiar l&apos;ayuda a un ficheru temporal.\nLa capacidá de búsqueda pue vese afeutada.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>Nun se pudieron configurar los datos necesarios pa&apos;l\nvisor de documentación. Ye posible qu&apos;el módulu de SQlite de\nla biblioteca Qt nun te instaláu.\nL&apos;ayuda tará disponible namás na ventana de comandos.</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>Conteníu</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Introduzca&apos;l testu a buscar nel índice de funciones</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Buscar</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>Índice de funciones</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Favoritos</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>Dir al índice xeneral</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Dir p&apos;atrás</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Páxines anteriores</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>Dir p&apos;alantre</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Páxines siguientes</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Buscar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Ampliar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Reducir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Zoom orixinal</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>Marcar la páxina actual como favoritu</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>Imposible amosar el ficheru d&apos;ayuda %1.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nNun se cargaron favoritos de documentación</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: cargando favoritos de documentación</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Introduzca testu pa buscar en favoritos</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Filtriar</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Nueva carpeta</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Abrir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Renomar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>Elimin&amp;ar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>&amp;Añadir carpeta</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>Ancultar la ventana de &amp;búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>Amosar la ventana de &amp;búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: guardando favoritos de documentación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>Imposible escribir el ficheru %1:\n%2.\n\nNun se guardaron los favoritos de documentación.\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>Imposible lleer el ficheru %1:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>Nun s&apos;alcontró elementu d&apos;iniciu en %1.\n¿Ficheru de favoritos nun válidu?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>El ficheru\n%1\nnun ye un ficheru XBEL versión 1.0 válidu.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Títulu desconocíu</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Documentación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Consulte la documentación pa obtener ayuda.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Zarrar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>Zarrar &amp;too</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>Zarrar los &amp;otros</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>Cambiar al widget de la &amp;izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>Cambiar al widget de la &amp;derecha</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation>Abrir l&apos;editor de ficheros</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation>Facer clicl pa poner el focu nel editor</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Zarrar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>Zarrar &amp;too</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Executar</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Asignar el &amp;direutoriu actual</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Editor d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>Nun se pue abrir l&apos;editor de testu personalizáu\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Tovía nun esiste una configuración pa l&apos;editor.\n¿Quier abrir les preferencies?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Siguir</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Guardar archivu y executar</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Editor d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>Archivu nun guardáu. Hay abiertu nel editor un archivu col nome seleicionáu\n%1.</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>La pestaña asociada de l&apos;editor de testu desapaeció.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>Nun se pue abrir l&apos;archivu\n%1\npa lleer: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>L&apos;archivu\n%1\nnun esiste. ¿Quier crealu?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Crear</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>No se pue abrir l&apos;archivu\n%1\npa escribir: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Archivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>Archivos &amp;recientes de l&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>&amp;Editar función</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>&amp;Guardar archivu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>Guardar archivu &amp;como...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Zarrar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Zarrar too</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Zarrar otros archivos</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Imprimir...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Editar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Refacer</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>Cor&amp;tar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>&amp;Buscar y reemplazar...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>Buscar &amp;siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>Buscar &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>&amp;Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Eliminar llinia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Copiar llinia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Cortar llinia</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Eliminar hasta&apos;l principiu de pallabra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Eliminar hasta&apos;l fin de pallabra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Eliminar hasta&apos;l principiu de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Eliminar hasta&apos;l final de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Duplicar seleición/llinia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Intercambiar llinies</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>&amp;Amosar llista de comandos coincidentes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Formatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>Convertir seleición a &amp;mayúscules</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>Convertir seleición a m&amp;inúscules</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>&amp;Comentar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>&amp;Eliminar comentariu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Comentar (seleicionando cadena de testu)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>&amp;Sangría rigurosa de la seleición</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>&amp;Eliminar sangría rigurosa de la seleición</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Aplicar sangría a códigu</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Convertir caracteres de fin de llinia a &amp;Windows (CR+LF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Convertir caracteres de fin de llinia a &amp;Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Convertir caracteres de fin de llinia a &amp;Mac antiguo (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>&amp;Navegación</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>&amp;Dir a llinia...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Dir a paréntesis correspondiente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Seleicionar a paréntesis correspondiente</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>Marcador &amp;siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>Marcador &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>&amp;Alternar marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>&amp;Eliminar tolos marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Preferencies...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>Preferencies d&apos;&amp;estilos...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>&amp;Ver</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>&amp;Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>Amosar númberos de &amp;llinia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>Amosar &amp;espacios en blanco</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Amosar carauteres de &amp;fin de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>Amosar guíes de &amp;sangría</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>Amosar &amp;marcador de llargor de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>Amosar &amp;barra de ferramientes</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>Amosar barra d&apos;&amp;estáu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>Amosar barra de &amp;desplazamientu horizontal</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>&amp;Ampliar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>&amp;Reducir</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>Tamañu &amp;normal</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>&amp;Ordenar pestañes alfabéticamente</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Depurar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>&amp;Alternar puntos d&apos;interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>Puntu d&apos;interrupción &amp;siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>Puntu d&apos;interrupción &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>&amp;Eliminar tolos puntos d&apos;interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>&amp;Executar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Guardar y executar/siguir</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>Executar &amp;seleición</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Guardar ficheru y executar tolos &amp;tests</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Guardar ficheru y executar toes les &amp;demos</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Ayuda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>&amp;Ayuda de pallabres clave</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>&amp;Documentación de pallabres clave</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>Archivos recientes</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Copiar la &amp;ruta completa de l&apos;archivu</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>Llinia:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>Columna:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>Codificación:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>Fin de llinia:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Condición de puntu d&apos;interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>ERROR: </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Editor d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>Nun se pue añadir un puntu d&apos;interrupción a un archivu modificáu o ensin nome.\nPue guardar el ficheru y añadir el puntu d&apos;interrupción o cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Dir a la llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Númberu de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Comentar testu seleicionáu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Comentar cadena de testu a utilizar:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;ensin nome&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>¿Quier cancelar el cierre, guardar o descartar los cambios?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>L&apos;archivu\n\n  %1\n\nta a puntu de ser zerráu, pero foi modificáu.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>Imposible lleer l&apos;archivu &apos;%1&apos;\ncola codificación seleicionada &apos;%2&apos;: %3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>Hubo problemes na llectura de l&apos;archivu\n%1\ncola codificación seleicionada %2.\n\nLa modificación y l&apos;almacenamientu de l&apos;archivu podría significar pérdida de datos.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>&amp;Editar de toos modos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>Cambi&amp;ar codificación</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>Z&amp;arrar</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Seleicione una nueva codificación por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Por favor, seleicione una nueva codificación\npa la recarga de l&apos;archivu actual.\n\nEsto nun cambiará la codificación predeterminada.\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Depurar programa o guardar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Esti archivu ta siendo executáu.\n¿Quier interrumpir la depuración y guardar?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>Nun se pudo abrir l&apos;archivu %1 pa escribir:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>Los cambios nun se pudieron guardar nel archivu\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Archivos d&apos;Octave (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Tolos archivos (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>&quot;%1&quot;\nnun ye un identificador válidu.\n\nSi mantien esi nome d&apos;archivu nun-y será posible\nllamar al so script emplegando&apos;l so nome como comandu d&apos;Octave.\n\n¿Quier seleicionar otru nome?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>El conteníu actual de l&apos;editor nun se pue escribir\ncola codificación seleicionada %1.\nEl so usu podría ocasionar una pérdida de datos.\n\nPor favor, seleicione otra codificación.</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1\n ya esiste\n¿Quier sobrescribilu?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nAvisu: el conteníu de l&apos;editor foi modificáu.</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>Paez que l&apos;archivu &apos;%1&apos; foi modificáu por otra aplicación. ¿Quier recargalu?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>Paez que l&apos;archivu\n%1\nfoi elimináu o renomáu. ¿Quier guardalu agora?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Tamañu de l&apos;archivu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Tipu d&apos;archivu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Fecha de modificación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Amosar ocultos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Alternar colores de files</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Introduzca la ruta o&apos;l nome de l&apos;archivu</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Direutoriu superior</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Amosar el direutoriu d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Dir al direutoriu actual d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Seleicionar el direutoriu d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Asignar el direutoriu actual del navegador como direutoriu d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Acciones nel direutoriu actual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Amosar el direutoriu d&apos;iniciu</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Asignar direutoriu del navegador...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Buscar archivos...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Nuevu archivu...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Nuevu direutoriu...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Doble clic pa abrir l&apos;archivu o la carpeta; clic nel botón derechu pa ver les alternatives</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Renomar...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Abrir</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Abrir nel esplorador d&apos;archivos del sistema</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Abrir nel editor de testu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Copiar seleición al portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Executar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Cargar datos</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Asignar direutoriu actual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Añadir a la ruta de trabayu (path)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Direutorios seleicionaos</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Direutorios y subdireutorios seleicionaos</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Eliminar de la ruta de trabayu (path)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Eliminar...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Eliminar archivu/direutoriu</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>¿Ta seguru de que quier eliminar los %1 ficheros seleicionaos?\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>¿Ta seguru de que quier eliminar\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>Nun se pue eliminar un direutoriu que nun te vacíu</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Error al borrar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>No se pudo eliminar el ficheru &quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Seleicionar el direutoriu de l&apos;esplorador d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Crear archivu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>¡Crear archivu en\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Nuevu archivu.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Error al crear l&apos;archivu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>Nun se pudo crear l&apos;archivu\n&quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Crear direutoriu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>¡Crear carpeta en\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Nuevu direutoriu</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>Nun se pudo renomar l&apos;archivu &quot;%1&quot; a &quot;%2&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Esplorador d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Esplorar los sos archivos</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>Sistema de ficheros</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>Editor d&apos;archivos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>¡Disfrútelu!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Terminar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Deseamos qu&apos;Octave seya-y una ferramienta útil.&lt;/p&gt;\n&lt;p&gt;Si alcuentra dalgún problema esisten una serie de víes pa obtener ayuda, qu&apos;incluyen opciones comerciales, un panel de discusión, una wiki y otros canales basaos na comunidá.\nPue atopar más información al respeutu visitando &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (abre una ventana esterna del navegador).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Pa obtener más información acerca d&apos;Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visite &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (abre una ventana esterna del navegador)&lt;/li&gt;\n&lt;li&gt;Vea la documentación online en &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; o &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; (l&apos;enllace ábrese n&apos;una ventana esterna del navegador)&lt;/li&gt;\n&lt;li&gt;Abra&apos;l navegador de documentación col menú d&apos;ayuda&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Editor: buscar y reemplazar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Buscar:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Introduzca&apos;l testu a buscar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>Reem&amp;plazar:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>Introduzca&apos;l testu de reemplazu</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>Distinguir &amp;mayúscules/minúscules</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>Buscar dende&apos;l &amp;principiu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>&amp;Marcar mientres se busca</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>Buscar &amp;siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>Buscar &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>&amp;Reemplazar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>Reemplazar &amp;too</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>&amp;Más...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>Pallabres &amp;completes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>&amp;Espresiones regulares</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>Buscar hacia &amp;atrás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>Buscar se&amp;leición</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Buscar dende&apos;l final</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Buscar dende l&apos;iniciu</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Reemplazar resultáu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 instancia/es reemplazada/es</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Resultáu de la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>Nun s&apos;atoparon más coincidencies</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Buscar archivos</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Denomináu:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>Empezar en:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Introduzca&apos;l direutoriu inicial de búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Esplorar...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Esplorar pa seleicionar el direutoriu inicial de búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Direutoriu actual</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>Asignar el direutoriu actual como direutoriu d&apos;iniciu de búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Buscar en subdireutorios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Buscar archivos de forma recursiva nos direutorios</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Incluir nomes de direutorios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Incluir direutorios que coicidan nos resultaos de la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Inorar mayúscules/minúscules</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>Nun tener en cuenta mayúscules/minúscules</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>Que contenga&apos;l testu:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>Incluir nos resultaos namás los ficheros que contengan el testu especificáu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Testu a coincidir</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Resultaos: doble clic abre&apos;l ficheru o asigna el direutoriu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Resultaos de la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>Inactivu.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Introduzca los patrones de búsqueda pa&apos;l nome del ficheru.\nPuen asignase varios separaos por puntu y coma &apos;;&apos;.\nPor exemplu, &apos;*.cc; *.h&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>Buscar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Empezar la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Detener</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Detener la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>Nome de l&apos;archivu/ubicación</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Conteníu de l&apos;archivu</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>Buscando...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 coincidencia/es</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Seleicionar el direutoriu de búsqueda</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Nome de l&apos;archivu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Direutoriu</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Faga doble clic pa abrir l&apos;archivu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Faga doble clic pa asignar el direutoriu</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Buscar:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>Buscar p&apos;alantre</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Buscar p&apos;atrás</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Zarrar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Zarrar el cuadru de búsqueda</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Error %1 al crear el ficheru de configuración\n%2\nAsegúrese de que tien permisos de llectura y escritura pa\n%3\n\nL&apos;entornu gráficu d&apos;Octave zarrarase.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Error críticu d&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Esplorar y buscar nel historial de comandos.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Evaluar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Crear un guion (script)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Ancultar la ventana de filtráu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Amosar el filtru</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Faga doble clic nun comandu pa introducilu na ventana de comandos.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Introduzca testu pa filtriar l&apos;historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Filtriar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Historial de comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>¡Bienveníu a Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Paez que ta utilizando l&apos;interfaz gráfica d&apos;Octave por primera vegada n&apos;esta computadora.\nPulse &apos;Siguiente&apos; pa crear un archivu de configuración e iniciar Octave.&lt;/p&gt;\n&lt;p&gt;L&apos;archivu de configuración guardarase&apos;n&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Desacoplar widget</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Zarrar widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Perfiláu</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>¿Ta seguru de que quier salir d&apos;Octave?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Guardar l&apos;espaciu de trabayu como</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Cargar espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>Acerca d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Esplorar direutorios</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Archivos d&apos;Octave (*.m);;Tolos archivos (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Nueva función</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Nome pa la nueva función:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>%1 ye una función integrada (built-in), compilada o inline,\npolo que nun se pue editar.</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>Nun s&apos;alcuentra la función %1</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Editor d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Archivu</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Abrir...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Abrir un archivu esistente nel editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Cargar espaciu de trabayu...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Guardar l&apos;espaciu de trabayu como...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Salir</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Nuevu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Nuevu guion (script)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Nueva función...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Nueva figura</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Editar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Desfacer</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Pegar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Seleicionar too</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Llimpiar el portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Buscar archivos...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Llimpiar la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Llimpiar l&apos;historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Llimpiar l&apos;espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Asignar ruta de trabayu (path)...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Preferencies...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>&amp;Depurar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Saltu individual</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Saltar a</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Salir de</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Siguir</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Salir del mou de depuración</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>&amp;Ferramientes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>Iniciar sesión de &amp;perfiláu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>&amp;Reanudar sesión de perfiláu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>&amp;Detener sesión de perfiláu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>&amp;Amosar los datos de perfiláu</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>&amp;Ventana</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Amosar la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Amosar l&apos;historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Amosar l&apos;esplorador d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Amosar l&apos;espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Amosar editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Amosar documentación</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Amosar editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Esplorador d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Documentación</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Widget anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Restablecer l&apos;esquema de ventana predetermináu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Ayuda</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Informar de fallu (bug)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Paquetes d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>Involúcrese</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Donar a Octave</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>En discu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>En llinia</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Noticies</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Notes de la versión</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Noticies de la comunidá</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Barra de ferramientes</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Introduzca&apos;l nome del direutoriu</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Direutoriu actual: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Direutoriu superior</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nLas fontes de noticies de la comunidá d&apos;Octave parez que nun tan disponibles.\n&lt;/p&gt;\n&lt;p&gt;\nPa ver les últimes novedaes visite\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\ncuando tenga conexón a la web (l&apos;enlace ábrese nun navegador esternu).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Los desarrolladores d&apos;Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nLa conexón a la web pa amosar les últimes noticies de la comunidá d&apos;Octave deshabilitose.\n&lt;/p&gt;\n&lt;p&gt;\nPa ver les últimes noticies visite\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\ncuando tenga conexón a la rede (l&apos;enllace ábrese nun navegador esternu)\no active na ventana de configuración la opción para veles.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Los desarrolladores d&apos;Octave, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Ancultar widget</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Acoplar widget</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Desacoplar widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>Ayuda sobre</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>Documentación sobre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>Editar</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop en casu de...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Editor d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>Falló la creación d&apos;archivos temporales.\nAsegúrese de que tien permisu d&apos;escritura nel direutoriu\n%1\n\n&quot;Executar seleición&quot; requier ficheros temporales.</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>Presione &apos;%1&apos; pa reemplazar tolos casos de &apos;%2&apos; con &apos;%3&apos;.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>Valor predetermináu</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Crear</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>L&apos;archivu\n%1\nnun esiste. ¿Quier crealu?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Editor d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>L&apos;archivu %1 nun esiste nes rutes de trabayu (path). Pa executar o depurar la función que ta editando tien que cambiar al direutoriu %2 o agregalu a les rutas de trabayu.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>Esiste un archivu col mesmu nome que %1 na ruta de trabayu (path). Pa executar o depurar la función que ta editándose cambie al direutoriu %2.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Cambiar direutoriu o agregar direutoriu a la ruta de trabayu (path)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>&amp;Cambiar direutoriu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>&amp;Agregar direutoriu a ruta de trabayu (path)</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>L&apos;archivu de notes de la versión %1 ta vacíu.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>L&apos;archivu de notes de la versión %1 nun se pue lleer.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Notes de la versión d&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Asignar rutes de trabayu (path)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Tolos cambios tienen efeutu inmediatu.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Añadir direutoriu...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Direutoriu individual</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Direutoriu y subdireutorios</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>Mover al principiu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>Mover al final</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Mover arriba</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Mover abaxo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Eliminar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Recargar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Guardar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Desfacer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Desfacer l&apos;últimu cambiu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Desfacer tolos cambios</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Abrir direutoriu</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>Primeru</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>Últimu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>Izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>Derecha</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Primer planu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Segundu planu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Seleición</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>Cursor</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Primer planu seleicionáu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Segundu planu seleicionáu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Fondu alternativu</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>argumentu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>global</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>persistente</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Variables d&apos;entornu</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>Mou de color secundariu (claru/escuru)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>Cambiu a un conxuntu de colores alternativu.\nÚtil pa la definición de modos lluminosos/escuros.\nDescártense los cambios nun aplicaos.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>La recarga de los colores por defeutu\ndepende del mou seleicionáu actual.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>La recarga de los valores d&apos;estilu por defeutu\ndepende del mou seleicionáu actual.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>&amp;Recargar colores por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>&amp;Recarga l&apos;estilu por defeutu</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Cargando les preferencies actuales... </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Configuración del sistema</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>Cursor IBeam</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>Cursor de bloque</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>Cursor de subrayao</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>Color de la llinia resaltada actual (por defeutu, maxenta (255,0,255))</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Axuste del direutorio d&apos;iniciu d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Axuste del direutoriu d&apos;iniciu de l&apos;esplorador d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Aplicando preferencies... </translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>Fallo al abrir %1 como archivu d&apos;atayos de tecláu d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Activar atributos de color</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Ancultar conseyos d&apos;usu</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Importar atayos de tecláu dende archivu...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Archivu d&apos;accesu direutu d&apos;Octave (*.osc);;Tolos archivos (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Exportar atayos de tecláu a archivu...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Sobrescribir atayos de tecláu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Ta a puntu de sobrescribir tolos atayos de tecláu.\n¿Gustaría-y guardar el conxuntu actual o cancelar esta aición?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>Nun guardar</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Preferencies de l&apos;entornu gráficu d&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Noticies de la comunidá</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Nel momento d&apos;iniciar Octave, de manera opcional farase una revisón del sitiu web del proyeutu pa buscar noticies e información acerca de la comunidá.\nEsto ocurrirá como máximo una vegada al día y les noticies desplegaranse namás si esisten cambios recientes dende la última visita al sitiu web.&lt;/p&gt;\n&lt;p&gt;Tamién se pue acceder a les noticies calcando &quot;Noticies de la comunidá&quot; nel menú &quot;Ayuda&quot;, o visitando\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Permitir a Octave conectase a la web nel iniciu pa amosar les últimes noticies e información de la comunidá.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Introduzca nuevu atayu de tecláu</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Introduzca atayu de tecláu\nAición: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Introduzca l&apos;atayu tecleándolu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Añadir el modificador Shift\n(permite introducir tecles numériques)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Atayu de tecláu actual</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Atayu de tecláu por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Llimpiar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Establecer como por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Atayu de tecláu doble</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>L&apos;atayu de tecláu seleicionáu\n  &quot;%1&quot;\nta agora n&apos;usu pa la aición\n  &quot;%2&quot;.\n¿Quier utilizalu y eliminar la configuración anterior?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Global</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Menú archivu</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Menú editar</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Menú depuración</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Menú de ferramientes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Menú ventana</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Menú ayuda</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Menú noticies</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Manexu de widgets apegaos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Manexu de pestañes en widgets apegaos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Buscar y reemplazar en widgets apegaos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Zoom nel editor y documentación</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Menú ver</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Menú executar</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Visor de documentación</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Esplorador</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>l&apos;ítem %1 nun s&apos;alcontró na configuración de los atayos de tecláu</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Bienveníu a GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>¡Bienveníu a Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Ventana de comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Apegar widget</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Editor de variables: </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Desapegar widget</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Restablecer xeometría</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Volver a apegar</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Editar variables.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Barra de ferramientes de l&apos;editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Guardar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Guardar variable nun archivu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Guardar en formatu...</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Guardar variable nun ficheru en formatu...</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Cortar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Cortar datos al portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Copiar datos al portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Apegar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Apegar portapapeles a variable de datos</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Dibuxar</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Dibuxar datos seleicionaos</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Dibuxar datos seleicionaos</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Arriba</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>Dir un nivel p&apos;arriba na xerarquía de variables</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>Guardar variable %1 como</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Cortar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Apegar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Llimpiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Eliminar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Variable de la seleición</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Trasponer</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> columnes</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> columna</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> files</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> fila</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Bienveníu a GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>Nome</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Clase</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensión</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Atributu</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Clic col botón derechu pa copiar, renomar o amosar</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>complexo</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Clase</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensión</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Atributu</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Ver variables nel espaciu de trabayu activu.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Introduzca testu pa filtriar l&apos;espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Filtriar</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Ver les variables de l&apos;espaciu de trabayu activu.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Colores pa los atributos de variable:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Abrir nel editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Copiar nome</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Copiar valor</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Renomar</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Sólo los símbolos de nivel superior puen ser renomaos</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Ancultar la ventana de filtriar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Amosar el filtru</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>Nun se pue abrir el fluxu redirixíu fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>Nun se pue desactivar l&apos;almacenamientu&apos;n buffer del fluxu fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>Nun se pue aplicar la función dup() de la biblioteca estándar de C al fluxu redirixíu fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>Nun se pue crear la tubería pal fluxu redirixíu fd = %1:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>Nun se pue aplicar la función dup2() de la biblioteca estándar de C al fluxu redirixíu fd = %1\npa crear la tubería fd = %2: %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Error na escucha de los fluxos redirixíos</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <translation>Error lliendo del fluxu redirixíu fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\nLa redireición de salida a </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> nun funcionará.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\nError: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Xeneral</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Sólo logo d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Iconos de testu</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Graphic icons</source>\n        <translation>Iconos gráficos</translation>\n    </message>\n    <message>\n        <location line=\"-341\"/>\n        <source>Dock widget title bar</source>\n        <translation>Widget de barra de títulu</translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation>Pequeñu</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Grande</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>Estilu personalizáu</translation>\n    </message>\n    <message>\n        <location line=\"+244\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Estes configuraciones aplicaranse dempués de la carga de cualquier archivu d&apos;iniciu .octaverc.</translation>\n    </message>\n    <message>\n        <location line=\"+353\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+187\"/>\n        <source>Show EOL characters</source>\n        <translation>Amosar carauteres de fin de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Axustar les llinies demasiao llargues al tamañu de la ventana</translation>\n    </message>\n    <message>\n        <location line=\"+558\"/>\n        <source>Default EOL mode</source>\n        <translation>Caráuter de fin de llinia por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"-503\"/>\n        <source>Indent width</source>\n        <translation>Anchor de sangría</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Sangrar con tabulación</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Sangría automática</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Anchor del tabulador</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Amosar guíes de sangría</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>La tecla de retrocesu quita sangría</translation>\n    </message>\n    <message>\n        <location line=\"+120\"/>\n        <source>Match keywords</source>\n        <translation>Coincidir en pallabres clave</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Distinguir mayúscules/minúscules</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Sustituir pallabra con suxerencia</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Coincidir pallabres en documentu</translation>\n    </message>\n    <message>\n        <location line=\"-643\"/>\n        <source>Use custom file editor</source>\n        <translation>Utilizar editor d&apos;archivos personalizáu</translation>\n    </message>\n    <message>\n        <location line=\"+1009\"/>\n        <source>Editor Styles</source>\n        <translation>Estilos de l&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"-1485\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Tipu de fonte</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Amosar númberos de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Show whitespace</source>\n        <translation>Amosar espacios en blanco</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Nun amosar los espacios usaos pa la sangría</translation>\n    </message>\n    <message>\n        <location line=\"+935\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Númberu de carauteres a escribir antes d&apos;amosar la llista: </translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Crear archivos non existentes ensin consultar</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>llinia de comandos (%f=archivu, %l=llinia):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Tipu de cursor:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Usar color de primer planu</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Tamañu de fonte</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Esplorador d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"-2118\"/>\n        <source>Interface</source>\n        <translation>Interfaz</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Confirmar enantes de salir</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Amosar barra d&apos;estáu</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Testu inactivu</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Activu</translation>\n    </message>\n    <message>\n        <location line=\"-89\"/>\n        <source>Normal</source>\n        <translation>Normal</translation>\n    </message>\n    <message>\n        <location line=\"+128\"/>\n        <source>Background inactive</source>\n        <translation>Fondu inactivu</translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation>Iniciu d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Esplorar</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Esto funciona correutamente con fontes con espaciáu fixo. Dibúxase la llinia n&apos;una posición basada nel anchor d&apos;un caráuter de la fonte por defeutu. Esto podría nun funcionar correutamente si los estilos utilicen fontes proporcionales o si s&apos;utilicen fontes de varios tamaños, negrita, cursiva y testos normales.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Activar plegao de códigu</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CR+LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translatorcomment>No sé cómo traducirlo exactamente</translatorcomment>\n        <translation>Mac antiguo (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Amosar barra de desplazamientu horizontal</translation>\n    </message>\n    <message>\n        <location line=\"-970\"/>\n        <source>Preferences</source>\n        <translation>Preferencies</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(requier reiniciu)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Usar selector d&apos;archivos nativu</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Iconos de la barra de ferramientes</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Llingua</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Widgets d&apos;iconos de ventana</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Estilu</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Tema pa los iconos (requier reiniciu)</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>3-D</source>\n        <translation>3D</translation>\n    </message>\n    <message>\n        <location line=\"+157\"/>\n        <source>Blinking cursor</source>\n        <translation>Cursor parpadiante</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Amosar pantalla d&apos;iniciu</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Direutoriu de trabayu inicial de l&apos;intérprete d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Restaurar el direutoriu de trabayu de la sesión anterior</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Establecer el focu na ventana de comandos cuando se execute un comandu n&apos;otru widget</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Amosar el puntu de depuración na ventana de comandos además de nel editor</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Colores de la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Show tool bar</source>\n        <translation>Amosar barra de ferramientes</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Tamañu del númberu como diferencia cola fonte de l&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Resaltáu de la llinia actual (color configurable nel editor d&apos;estilos)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Resaltar toles apaiciones de pallabra seleicionada con doble clic</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Pestañes</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pestañes xiraes: verticales cuando tan arriba o abaxo y horizontales cuando se configuren a l&apos;izquierda o a la derecha. El botón de zarrar nun se amosa nes pestañes xiraes.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Comentarios (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Cadenes consideraes pa descomentar testu</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Cadena utilizada pa comentar testu seleicionáu</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Llinies llargues</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Partir llinies llargues a partir del llargor de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Partir llinies sólo&apos;n comentarios</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Llargor de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Marcador de llinia llarga</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Llinia</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Fondu</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>Indentation</source>\n        <translation>Sangrao</translation>\n    </message>\n    <message>\n        <location line=\"+127\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Sangrao con tabulador</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Inserción automática dempués de &quot;if&quot;, etc.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Na</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot;, etc.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Auto completion</source>\n        <translation>Completáo automático</translation>\n    </message>\n    <message>\n        <location line=\"+101\"/>\n        <source>With Octave builtins</source>\n        <translation>Con funciones internes d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Con funciones d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Amosar llista de comandos coincidentes automáticamente</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Debugging</source>\n        <translation>Depurao</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Amosar siempre puntos d&apos;interrupción y punteros nel depurador (abrir l&apos;archivu relacionáu si ta zarráu)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Manexu d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Recargar los archivos modificaos esternamente ensin consultar</translation>\n    </message>\n    <message>\n        <location line=\"-50\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Restaurar pestañes de l&apos;editor de sesión anterior nel iniciu o cuando l&apos;editor se muestra de nuevo dempués del cierre</translation>\n    </message>\n    <message>\n        <location line=\"-31\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Codificación de testu usada pa cargar y guardar</translation>\n    </message>\n    <message>\n        <location line=\"+71\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Zarrar tolos archivos cuando&apos;l widget de l&apos;editor te zarráu/ocultu</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>Forzar nueva llinia al final del ficheru al guardalu</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>Eliminar espacios extra al final de les llinies del archivu al guardalu</translation>\n    </message>\n    <message>\n        <location line=\"+144\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Seleición de fonte, tamañu (como diferencia con respeuto al grandor por defeutu), estilu (&lt;b&gt;n&lt;/b&gt;egrita, &lt;b&gt;c&lt;/b&gt;ursiva, &lt;b&gt;s&lt;/b&gt;ubrayao), color y color de fondu (pa l&apos;últimu casu, el maxenta (255,0,255) ye un sustitutu pa&apos;l color de fondu por defeutu).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+848\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - zarrar el cuadru de diálogu y aplicar la configuración&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Aplicar - &lt;/span&gt;aplicar la configuración y mantener el cuadru de diálogu abiertu&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancelar - &lt;/span&gt;zarrar el cuadru de diálogu y descartar los cambios que nun s&apos;hayan aplicao previamente&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; recargar la configutación descartando los cambios que tovía nun s&apos;hayan aplicao&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-2254\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Cambiar el tamañu del buffer elimina l&apos;historial)</translation>\n    </message>\n    <message>\n        <location line=\"-260\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Si se seleiciona, actívase&apos;l focu nos widgets anclaos na ventana principal según la posición del ratu. Esto persigue un comportamientu igual al de l&apos;entornu d&apos;escritoriu.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>El focu nos widgets anclaos na ventana principal actívase según la posición del ratu</translation>\n    </message>\n    <message>\n        <location line=\"+285\"/>\n        <source>History buffer Size</source>\n        <translation>Tamañu del buffer pa l&apos;historial</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Rotated tabs</source>\n        <translation>Pestañes xiraes</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Posición</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>Anchor máximu de les pestañes, en carauteres (0: ilimitada)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Anchor máximu de les pestañes, en carauteres. Útil especialmente pa pestañes rotaes.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+871\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>El direutoriu del cuadru abiertu siguela ruta del ficheru de l&apos;editor en vez del direutoriu actual d&apos;Octave </translation>\n    </message>\n    <message>\n        <location line=\"+98\"/>\n        <source>Behavior</source>\n        <translation>Comportamientu</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Restaurar últimu direutoriu de la sesión previa</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>Directoriu inicial de l&apos;esplorador d&apos;archivos (sólo si nun ta sincronizáu col direutoriu inicial d&apos;Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Estensiones d&apos;archivu pa abrir nel editor de testu predetermináu (separaes por &apos;;&apos;):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Colores pa atributos de variables</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Usar la fonte de la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Importar conxuntu d&apos;atayos de tecláu</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Exportar conxuntu d&apos;atayos de tecláu</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Restablecer atayos de tecláu a valores predeterminaos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Valor predetermináu/por defeutu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation>Actual</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Rede</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Permitir a Octave la conexón al sitiu web pa amosar les últimes noticies e información</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Proxy</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Seleicionar &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; o &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. La última opción indica que&apos;l tipu de proxy tomarase de la primera variable que contenga datos del conxuntu ALL_PROXY, HTTP_PROXY y HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Utilizar servidor proxy</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Altor predeterminao de fila</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Anchor predeterminao de columna</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Colores de l&apos;editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Usar colores de files alternos</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Desactivar los atayos de tecláu globales pa evitar\nconflictos coles combinaciones de tecles pa readline.\nEsceiciones: Ctrl-C pa la interrupción de l&apos;intérprete\ny atayos pa&apos;l cambiu a otros widgets.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Desactivar los atayos de tecláu globales cuando&apos;l focu te na ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Sincronizar el direutoriu de trabayu d&apos;Octave col esplorador d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+348\"/>\n        <source>Shortcuts</source>\n        <translation>Atayos de tecláu</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Export</source>\n        <translation>Esportar</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importar</translation>\n    </message>\n    <message>\n        <location line=\"-44\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Desactivar los atayos de tecláu pa evitar conflictos\ncoles combinaciones de tecles de readline.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>Desactivar los atayos de tecláu de la ventana principal cuando la ventana de comandos te activa</translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Editar atayos de tecláu faciendo doble clic na columna &quot;Actual&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Aición</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Nome del host:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Tipu de proxy:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Puertu:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Nome d&apos;usuariu:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Contraseña:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Desaperar/apegar widget</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Zarrar widget</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Nuevu archivu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Nueva función</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Nueva figura</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Abrir archivu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Cargar espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Guardar l&apos;espaciu de trabayu como</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Salir d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Pegar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Desfacer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Seleicionar too</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Llimpiar el portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>Buscar n&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Llimpiar la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Llimpiar l&apos;historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Llimpiar l&apos;espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Asignar rutes de trabayu (path)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Preferencies</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Saltu individual</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>Saltar a</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Salir de</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Siguir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Salir del mou de depuración</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Iniciar/detener sesión de perfilao</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Siguir sesión de perfilao</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Amosar datos de perfilao</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Amosar la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Amosar l&apos;historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Amosar l&apos;esplorador d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Amosar l&apos;espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Amosar editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Amosar documentación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Amosar editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Esplorador d&apos;archivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Espaciu de trabayu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Documentación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Widget anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Restablecer l&apos;esquema de ventana predetermináu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Ver la documentación almacenada&apos;n discu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Amosar la documentación en llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Informar de fallu (bug)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Paquetes d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Colaborar con Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Recursos pal desarrollador d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>Acerca d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Notes de la versión</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Noticies de la comunidá</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Zarrar pestaña</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Zarrar toles pestañes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Zarrar otres pestañes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Cambiar a pestaña izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Cambiar a pestaña derecha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Mover pestaña hacia la izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Mover pestaña hacia la derecha</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Ampliar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Reducir</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Zoom normal</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Editar función</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Guardar archivu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Guardar figura como</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Imprimir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Refacer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Cortar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Buscar y reemplazar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Buscar siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Buscar anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Eliminar hasta&apos;l principiu de pallabra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Eliminar hasta&apos;l fin de pallabra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Eliminar hasta&apos;l principiu de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Eliminar hasta&apos;l final de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Eliminar llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Copiar llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Cortar llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Duplicar seleición/llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Intercambiar llinies</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Amosar llista de comandos coincidentes</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Comentar la seleición</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Descomentar la seleición</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Comentar seleición (seleicionando cadena de testu)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Convertir la seleición a mayúscules</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Convertir la seleición a minúscules</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Sangría rigurosa de la seleición</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Eliminar sangría rigurosa de la seleición</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Aplicar sangría a códigu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Convertir carauteres de fin de llinia a Windows</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Convertir carauteres de fin de llinia a Unix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Convertir carauteres de fin de llinia a Mac</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Dir a la llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Mover a paréntesis correspondiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Seleicionar a paréntesis correspondiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Alternar marcador</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Marcador siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Marcador anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Eliminar tolos marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Preferencies d&apos;estilos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Amosar númberos de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Amosar espacios en blanco</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Amosar fines de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Amosar guíes de sangría</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Amosar marcador de largor de llinia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Amosar barra de ferramientes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Amosar barra d&apos;estáu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Amosar barra de desplazamientu horizontal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Ordenar pestañes alfabéticamente</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Alternar puntos d&apos;interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Puntu d&apos;interrupción siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Puntu d&apos;interrupción anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Eliminar tolos puntos d&apos;interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Executar archivu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Executar seleición</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Executar los tests</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Executar les demos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Ayuda de pallabres clave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Documentación de pallabres clave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>Dir a la páxina principal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>Una páxina p&apos;atrás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>Una páxina p&apos;alantre</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Marcar esta páxina como favorita</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/be_BY.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"be_BY\">\n<context>\n    <name>QApplication</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qmessagebox.cpp\" line=\"+2902\"/>\n        <source>Application &quot;%1&quot; requires Qt %2, found Qt %3.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Incompatible Qt Library Error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QColorDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qcolordialog.cpp\" line=\"+1473\"/>\n        <source>Hu&amp;e:</source>\n        <translation>Ад&amp;ценне:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Sat:</source>\n        <translation>&amp;Насычанасць:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Val:</source>\n        <translation>&amp;Светласць:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Red:</source>\n        <translation>&amp;Чырвоны:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Green:</source>\n        <translation>&amp;Зялёны:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bl&amp;ue:</source>\n        <translation>Сі&amp;ні:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A&amp;lpha channel:</source>\n        <translation>А&amp;льфа:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;HTML:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+184\"/>\n        <source>Cursor at %1, %2\nPress ESC to cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>Select Color</source>\n        <translation>Пазначыць колер</translation>\n    </message>\n    <message>\n        <location line=\"+204\"/>\n        <source>&amp;Basic colors</source>\n        <translation>&amp;Базавыя колеры</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Custom colors</source>\n        <translation>&amp;Свае колеры</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add to Custom Colors</source>\n        <translation>&amp;Дадаць да сваіх колераў</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Pick Screen Color</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qdialog.cpp\" line=\"+677\"/>\n        <source>What&apos;s This?</source>\n        <translation>Што гэта?</translation>\n    </message>\n</context>\n<context>\n    <name>QDialogButtonBox</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qmessagebox.cpp\" line=\"-793\"/>\n        <location line=\"+452\"/>\n        <source>OK</source>\n        <translation>Добра</translation>\n    </message>\n</context>\n<context>\n    <name>QErrorMessage</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qerrormessage.cpp\" line=\"+86\"/>\n        <source>An error occurred</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+91\"/>\n        <source>Debug Message:</source>\n        <translation>Адладачнае паведамленне:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Warning:</source>\n        <translation>Папярэджанне:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Critical Error:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Fatal Error:</source>\n        <translation>Фатальная памылка:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Information:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+256\"/>\n        <source>&amp;Show this message again</source>\n        <translation>&amp;Паказваць гэтае паведамленне зноў</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;OK</source>\n        <translation>&amp;Добра</translation>\n    </message>\n</context>\n<context>\n    <name>QFileDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfiledialog.cpp\" line=\"+582\"/>\n        <location filename=\"build_ts/octave-qt/qfiledialog_symbian.cpp\" line=\"+192\"/>\n        <source>Find Directory</source>\n        <translation>Знайсці каталог</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open</source>\n        <translation>Адкрыць</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Save As</source>\n        <translation>Захаваць як</translation>\n    </message>\n    <message>\n        <location line=\"+85\"/>\n        <source>Show </source>\n        <translation>Паказаць </translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Пераназваць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Delete</source>\n        <translation>&amp;Выдаліць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show &amp;hidden files</source>\n        <translation>Паказаць &amp;схаваныя файлы</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;New Folder</source>\n        <translation>&amp;Новы каталог</translation>\n    </message>\n    <message>\n        <location line=\"-69\"/>\n        <source>Directory:</source>\n        <translation>Каталог:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File &amp;name:</source>\n        <translation>&amp;Назва файла:</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <location line=\"+12\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Адкрыць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Save</source>\n        <translation>&amp;Захаваць</translation>\n    </message>\n    <message>\n        <location line=\"+895\"/>\n        <source>All files (*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+171\"/>\n        <source>Directories</source>\n        <translation>Каталогі</translation>\n    </message>\n    <message>\n        <location line=\"+1886\"/>\n        <source>Are you sure you want to delete &apos;%1&apos;?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2958\"/>\n        <source>&amp;Choose</source>\n        <translation>&amp;Выбраць</translation>\n    </message>\n    <message>\n        <location line=\"+2058\"/>\n        <location line=\"+1120\"/>\n        <source>%1\nDirectory not found.\nPlease verify the correct directory name was given.</source>\n        <translation>%1\nКаталог не знойдзены.\nПераправерце, ці карэктную назву каталогу вы задалі.</translation>\n    </message>\n    <message>\n        <location line=\"-1133\"/>\n        <source>%1 already exists.\nDo you want to replace it?</source>\n        <translation>%1 ужо існуе.\nЗамяніць яго?</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>%1\nFile not found.\nPlease verify the correct file name was given.</source>\n        <translation>%1\nФайл не знойдзены.\nПераправерце, ці карэктную назву файла вы задалі.</translation>\n    </message>\n    <message>\n        <location line=\"+762\"/>\n        <source>New Folder</source>\n        <translation>Новы каталог</translation>\n    </message>\n    <message>\n        <location line=\"+130\"/>\n        <location line=\"+5\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\">Выдаліць</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>&apos;%1&apos; is write protected.\nDo you want to delete it anyway?</source>\n        <translation>&apos;%1&apos; абаронены ад запісу.\nВыдаліць яго ўсё адно?</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Could not delete directory.</source>\n        <translation>Не выйшла выдаліць каталог.</translation>\n    </message>\n    <message>\n        <location line=\"+441\"/>\n        <source>Recent Places</source>\n        <translation>Ранейшыя месцы</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfiledialog_win.cpp\" line=\"+131\"/>\n        <source>All Files (*.*)</source>\n        <translation>Усе файлы (*.*)</translation>\n    </message>\n</context>\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Памылковая назва файла</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfilesystemmodel.cpp\" line=\"+964\"/>\n        <source>Name</source>\n        <translation>Назва</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Size</source>\n        <translation>Памер</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Kind</source>\n        <comment>Match OS X Finder</comment>\n        <translation>Тып (Kind)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Type</source>\n        <comment>All other platforms</comment>\n        <translation>Тып</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Date Modified</source>\n        <translation>Дата змянення</translation>\n    </message>\n</context>\n<context>\n    <name>QFontDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfontdialog.cpp\" line=\"+141\"/>\n        <source>Select Font</source>\n        <translation>Пазначыць шрыфт</translation>\n    </message>\n    <message>\n        <location line=\"+600\"/>\n        <source>&amp;Font</source>\n        <translation>&amp;Шрыфт</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Font st&amp;yle</source>\n        <translation>Стыль ш&amp;рыфту</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Size</source>\n        <translation>&amp;Памер</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Effects</source>\n        <translation>Эфекты</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stri&amp;keout</source>\n        <translation>Закрэ&amp;слены</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Underline</source>\n        <translation>&amp;Падкрэслены</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sample</source>\n        <translation>Узор</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Wr&amp;iting System</source>\n        <translation>Сістэма нап&amp;ісання</translation>\n    </message>\n</context>\n<context>\n    <name>QHelpSearchQueryWidget</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qhelpsearchquerywidget.cpp\" line=\"+62\"/>\n        <source>Search for:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Previous search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-3\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QInputDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qinputdialog.cpp\" line=\"+209\"/>\n        <source>Enter a value:</source>\n        <translation>Задайце значэнне:</translation>\n    </message>\n</context>\n<context>\n    <name>QMessageBox</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qmessagebox.cpp\" line=\"-2404\"/>\n        <source>Show Details...</source>\n        <translation>Падрабязнасці...</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source>Hide Details...</source>\n        <translation>Схаваць падрабязнасці...</translation>\n    </message>\n    <message>\n        <location line=\"+1815\"/>\n        <source>&lt;h3&gt;About Qt&lt;/h3&gt;&lt;p&gt;This program uses Qt version %1.&lt;/p&gt;</source>\n        <translation>&lt;h3&gt;Пра Qt&lt;/h3&gt;&lt;p&gt;Гэтая праграма выкарыстоўва Qt версіі %1.&lt;/p&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&lt;p&gt;Qt is a C++ toolkit for cross-platform application development.&lt;/p&gt;&lt;p&gt;Qt provides single-source portability across all major desktop operating systems. It is also available for embedded Linux and other embedded and mobile operating systems.&lt;/p&gt;&lt;p&gt;Qt is available under multiple licensing options designed to accommodate the needs of our various users.&lt;/p&gt;&lt;p&gt;Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of GNU (L)GPL.&lt;/p&gt;&lt;p&gt;Qt licensed under GNU (L)GPL is appropriate for the development of Qt&amp;nbsp;applications provided you can comply with the terms and conditions of the respective licenses.&lt;/p&gt;&lt;p&gt;Please see &lt;a href=&quot;https://%2/&quot;&gt;%2&lt;/a&gt; for an overview of Qt licensing.&lt;/p&gt;&lt;p&gt;Copyright (C) The Qt Company Ltd. and other contributors.&lt;/p&gt;&lt;p&gt;Qt and the Qt logo are trademarks of The Qt Company Ltd.&lt;/p&gt;&lt;p&gt;Qt is The Qt Company Ltd. product developed as an open source project. See &lt;a href=&quot;https://%3/&quot;&gt;%3&lt;/a&gt; for more information.&lt;/p&gt;</source>\n        <extracomment>Leave this text untranslated or include a verbatim copy of it below and note that it is the authoritative version in case of doubt.</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+26\"/>\n        <source>About Qt</source>\n        <translation>Пра Qt</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation type=\"unfinished\">Розніца ад стандартнага памеру</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation type=\"unfinished\">Для фону ружовы колер (255,0,255) азначае стандартны колер фону {255, 0, 255)?}</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation type=\"unfinished\">т</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation type=\"unfinished\">к</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation type=\"unfinished\">п</translation>\n    </message>\n</context>\n<context>\n    <name>QPageSetupWidget</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_unix.cpp\" line=\"+260\"/>\n        <source>Millimeters (mm)</source>\n        <translation>Міліметры (мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Inches (in)</source>\n        <translation>Цалі (цл)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Points (pt)</source>\n        <translation>Пункты (пт)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Pica (P̸)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Didot (DD)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cicero (CC)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <location line=\"+17\"/>\n        <source>Custom</source>\n        <translation type=\"unfinished\">Адмысловы</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>mm</source>\n        <extracomment>Unit &apos;Millimeter&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>pt</source>\n        <extracomment>Unit &apos;Points&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>in</source>\n        <extracomment>Unit &apos;Inch&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>P̸</source>\n        <extracomment>Unit &apos;Pica&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>DD</source>\n        <extracomment>Unit &apos;Didot&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>CC</source>\n        <extracomment>Unit &apos;Cicero&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QPlatformTheme</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qplatformtheme.cpp\" line=\"+793\"/>\n        <source>OK</source>\n        <translation type=\"unfinished\">Добра</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Save All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">Адкрыць</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Yes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Yes to &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;No</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>N&amp;o to All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Abort</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Retry</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Ignore</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Скасаваць</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Discard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Help</source>\n        <translation type=\"unfinished\">Даведка</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Apply</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reset</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Restore Defaults</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QPrintDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qabstractprintdialog.cpp\" line=\"+61\"/>\n        <location line=\"+16\"/>\n        <location filename=\"build_ts/octave-qt/qprintdialog_win.cpp\" line=\"+239\"/>\n        <source>Print</source>\n        <translation>Друк</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_qws.cpp\" line=\"+148\"/>\n        <source>File exists</source>\n        <translation>Файл існуе</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&lt;qt&gt;Do you want to overwrite it?&lt;/qt&gt;</source>\n        <translation>&lt;qt&gt;Перапісаць яго?&lt;/qt&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+184\"/>\n        <source>A0 (841 x 1189 mm)</source>\n        <translation>A0 (841 x 1189 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A1 (594 x 841 mm)</source>\n        <translation>A1 (594 x 841 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A2 (420 x 594 mm)</source>\n        <translation>A2 (420 x 594 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A3 (297 x 420 mm)</source>\n        <translation>A3 (297 x 420 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A4 (210 x 297 mm, 8.26 x 11.7 inches)</source>\n        <translation>A4 (210 x 297 мм, 8.26 x 11.7 цаляў)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A5 (148 x 210 mm)</source>\n        <translation>A5 (148 x 210 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A6 (105 x 148 mm)</source>\n        <translation>A6 (105 x 148 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A7 (74 x 105 mm)</source>\n        <translation>A7 (74 x 105 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A8 (52 x 74 mm)</source>\n        <translation>A8 (52 x 74 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A9 (37 x 52 mm)</source>\n        <translation>A9 (37 x 52 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B0 (1000 x 1414 mm)</source>\n        <translation>B0 (1000 x 1414 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B1 (707 x 1000 mm)</source>\n        <translation>B1 (707 x 1000 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B2 (500 x 707 mm)</source>\n        <translation>B2 (500 x 707 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B3 (353 x 500 mm)</source>\n        <translation>B3 (353 x 500 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B4 (250 x 353 mm)</source>\n        <translation>B4 (250 x 353 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B5 (176 x 250 mm, 6.93 x 9.84 inches)</source>\n        <translation>B5 (176 x 250 мм, 6.93 x 9.84 цаляў)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B6 (125 x 176 mm)</source>\n        <translation>B6 (125 x 176 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B7 (88 x 125 mm)</source>\n        <translation>B7 (88 x 125 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B8 (62 x 88 mm)</source>\n        <translation>B8 (62 x 88 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B9 (44 x 62 mm)</source>\n        <translation>B9 (44 x 62 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B10 (31 x 44 mm)</source>\n        <translation>B10 (31 x 44 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>C5E (163 x 229 mm)</source>\n        <translation>C5E (163 x 229 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>DLE (110 x 220 mm)</source>\n        <translation>DLE (110 x 220 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Executive (7.5 x 10 inches, 191 x 254 mm)</source>\n        <translation>Executive (7.5 x 10 цаляў, 191 x 254 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Folio (210 x 330 mm)</source>\n        <translation>Folio (210 x 330 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Ledger (432 x 279 mm)</source>\n        <translation>Ledger (432 x 279 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Legal (8.5 x 14 inches, 216 x 356 mm)</source>\n        <translation>Legal (8.5 x 14 цаляў, 216 x 356 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Letter (8.5 x 11 inches, 216 x 279 mm)</source>\n        <translation>Letter (8.5 x 11 цаляў, 216 x 279 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Tabloid (279 x 432 mm)</source>\n        <translation>Tabloid (279 x 432 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>US Common #10 Envelope (105 x 241 mm)</source>\n        <translation>US Common #10 Envelope (105 x 241 мм)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Print all</source>\n        <translation>Друкаваць усё</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print selection</source>\n        <translation>Друкаваць вылучанае</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print range</source>\n        <translation>Друк некалькіх старонак</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print current page</source>\n        <translation>Друкаваць бягучую старонку</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_unix.cpp\" line=\"+608\"/>\n        <source>All Pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Odd Pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Even Pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <location line=\"+224\"/>\n        <source>&amp;Options &gt;&gt;</source>\n        <translation>&amp;Настаўленні &gt;&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>&amp;Print</source>\n        <translation>&amp;Друкаваць</translation>\n    </message>\n    <message>\n        <location line=\"+223\"/>\n        <source>&amp;Options &lt;&lt;</source>\n        <translation>&amp;Настаўленні &lt;&lt;</translation>\n    </message>\n    <message>\n        <location line=\"+148\"/>\n        <source>Invalid Pages Definition</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 does not follow the correct syntax. Please use &apos;,&apos; to separate ranges and pages, &apos;-&apos; to define ranges and make sure ranges do not intersect with each other.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Duplex Settings Conflicts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>There are conflicts in duplex settings. Do you want to fix them?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+76\"/>\n        <source>Print to File (PDF)</source>\n        <translation>Друк у файл (PDF)</translation>\n    </message>\n    <message>\n        <location line=\"+55\"/>\n        <source>Write PDF file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+100\"/>\n        <source>Options &apos;Pages Per Sheet&apos; and &apos;Page Set&apos; cannot be used together.\nPlease turn one of those options off.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-101\"/>\n        <source>Local file</source>\n        <translation>Лакальны файл</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>Print To File ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>%1 is a directory.\nPlease choose a different file name.</source>\n        <translation>%1 - гэта каталог.\nКалі ласка, пазначце іншую назву файла.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>File %1 is not writable.\nPlease choose a different file name.</source>\n        <translation>Файл %1 не даступны на запіс.\nКалі ласка, пазначце іншую назву файла.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>%1 already exists.\nDo you want to overwrite it?</source>\n        <translation>%1 ужо існуе.\nПерапісаць яго?</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_win.cpp\" line=\"+1\"/>\n        <source>The &apos;From&apos; value cannot be greater than the &apos;To&apos; value.</source>\n        <translation>Значэнне &apos;З&apos; не можа перавышаць значэнне &apos;Да&apos;.</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_unix.cpp\" line=\"-155\"/>\n        <source>Left to Right, Top to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Left to Right, Bottom to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Right to Left, Bottom to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Right to Left, Top to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Bottom to Top, Left to Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Bottom to Top, Right to Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Top to Bottom, Left to Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Top to Bottom, Right to Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>1 (1x1)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>2 (2x1)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>4 (2x2)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>6 (2x3)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>9 (3x3)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>16 (4x4)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QPrintPreviewDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qabstractpagesetupdialog.cpp\" line=\"+68\"/>\n        <location line=\"+12\"/>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_unix.cpp\" line=\"+389\"/>\n        <location line=\"+8\"/>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_win.cpp\" line=\"+18\"/>\n        <location line=\"+7\"/>\n        <source>Page Setup</source>\n        <translation>Настаўленні старонкі</translation>\n    </message>\n</context>\n<context>\n    <name>QPrintPropertiesDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_unix.cpp\" line=\"-964\"/>\n        <source>Printer Properties</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Job Options</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Page Setup Conflicts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>There are conflicts in page setup options. Do you want to fix them?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Advanced Option Conflicts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>There are conflicts in some advanced options. Do you want to fix them?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Капіяваць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Уставіць</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Вылучыць усё</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>вылучэнне скапіявана ў буфер абмену</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>Стандартны</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Памылкі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Каментары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Лікі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключавыя словы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Радкі у двукоссях</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Радкі ў апострафах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Аператары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Ідэнтыфікатары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Скаляры</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>Раскрыванні зменных</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>У касых апострафах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Межнік here-document</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Here-document у апострафах</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>Стандартны</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Каментары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключавыя словы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>Цэтлікі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>Хаваць кіроўныя знакі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>Знешні загад</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Зменныя</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Аператары</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>Стандартны</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>Неактыўны, стандартна</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>Каментары C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>Неактыўныя каментары C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>Каментары C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>Неактыўныя каментары C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>Каментары C у стылі JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>Неактыўныя каментары C у стылі JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Лікі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Неактыўныя лікі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключавыя словы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Неактыўныя ключавыя словы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Радкі у двукоссях</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>Неактыўныя радкі у двукоссях</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Радкі ў апострафах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>Неактыўныя радкі ў апострафах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>Неактыўны IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>Блокі прэпрацэсара</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>Неактыўныя блокі прэпрацэсара</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Аператары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Неактыўныя аператары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Ідэнтыфікатары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Неактыўныя ідэнтыфікатары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>Незакрытыя радкі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>Неактыўныя незакрытыя радкі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>Літаральныя радкі C#</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>Неактыўныя літаральныя радкі C# </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>Рэгулярныя выразы JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>Неактыўныя рэгулярныя выразы JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>Каментары C++ у стылі JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>Неактыўныя каментары C++ у стылі JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>Другасныя ключавыя словы і ідэнтыфікатары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Неактыўныя другасныя ключавыя словы і ідэнтыфікатары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>Ключавыя словы JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>Неактыўныя ключавыя словы JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>Памылкі ключавых словаў JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>Неактыўныя памылкі ключавых словаў JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Глабальныя класы і typedef&apos;ы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Неактыўныя глабальныя класы і typedef&apos;ы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>Звычайныя радкі C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>Неактыўныя звычайныя радкі C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>Стандартны</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Каментары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Загады</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>Загалоўкі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Пазіцыі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Выдаленыя радкі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Дададзеныя радкі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Змененыя радкі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>Стандартны</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Каментары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Загады</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Лікі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключавыя словы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Радкі ў апострафах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Аператары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Ідэнтыфікатары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Радкі у двукоссях</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>Стандартны</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Памылкі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Каментары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Лікі</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключавыя словы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Радкі у двукоссях</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Радкі ў апострафах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Аператары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Ідэнтыфікатары</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Скаляры</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>Масівы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>Хэшы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Табліцы сімвалаў</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>Рэгулярныя выразы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>Замены</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>У касых апострафах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>Data section</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Межнік here-document</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Here-document у апострафах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>Here-document у двукоссях</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>Here-document у касых апострафах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>Радкі ў двукоссях (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>Радкі ў двукоссях (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>Радкі ў двукоссях (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>Радкі ў двукоссях (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>Радкі ў двукоссях (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>Літаральны POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>Прататыпы падпраграм</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>Ідэнтыфікатары фарматаў</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>Целы фарматаў</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>Радкі у двукоссях (інтэрпаляваныя зменныя)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>Пераклады</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>Рэгулярныя выразы (інтэрпаляваныя зменныя)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>Замены (інтэрпаляваныя зменныя)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>У касых апострафах (інтэрпаляваныя зменныя)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>Here-document у двукоссях (інтэрпаляваныя зменныя)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>Here-document у касых апострафах (інтэрпаляваныя зменныя)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>Радкі ў двукоссях (qq, інтэрпаляваныя зменныя)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>Радкі ў двукоссях (qx, інтэрпаляваныя зменныя)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>Радкі ў двукоссях (qr, інтэрпаляваныя зменныя)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>&amp;Адрабіць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Паўтарыць</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>Вы&amp;разаць</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Капіяваць</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>&amp;Уставіць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Выдаліць</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Вылучыць усё</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation type=\"unfinished\">Шрыфт</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation type=\"unfinished\">т</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation type=\"unfinished\">к</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\">Пазіцыі</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Вылучыць усё</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Спыніць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Працягваць</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation type=\"unfinished\">Навіны супольнасці Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Стандартны</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\">Памылкі</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Шукаць</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation type=\"unfinished\">Новы каталог</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation type=\"unfinished\">&amp;Адкрыць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation type=\"unfinished\">&amp;Пераназваць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Дакументацыя</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation type=\"unfinished\">Па даведку звяртайцеся да дакументацыі.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Закрыць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Закрыць</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Выканаць</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Рэдактар Octave</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Працягваць</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation type=\"unfinished\">Захаваць і выканаць файл</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Рэдактар Octave</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation type=\"unfinished\">Асацыяваная картка рэдактара знікла.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">Файл\n%1\nне існуе. Жадаеце стварыць яго?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Скасаваць</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Файл</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation type=\"unfinished\">&amp;Ранейшыя файлы</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation type=\"unfinished\">&amp;Змяніць функцыю</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation type=\"unfinished\">&amp;Захаваць файл</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation type=\"unfinished\">Захаваць файл &amp;як...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Закрыць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation type=\"unfinished\">Закрыць усё</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation type=\"unfinished\">Закрыць іншыя файлы</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation type=\"unfinished\">Друк...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Змяніць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\">&amp;Паўтарыць</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\">Вы&amp;разаць</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation type=\"unfinished\">&amp;Знайсці і замяніць...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation type=\"unfinished\">&amp;Шукаць раней</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation type=\"unfinished\">&amp;Закаментаваць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation type=\"unfinished\">&amp;Раскаментаваць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation type=\"unfinished\">П&amp;ерайсці да радка...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation type=\"unfinished\">&amp;Наступная закладка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation type=\"unfinished\">Па&amp;пярэдняя закладка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation type=\"unfinished\">&amp;Паставіць/прыбраць закладку</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation type=\"unfinished\">&amp;Выдаліць усе закладкі</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation type=\"unfinished\">&amp;Настаўленні...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation type=\"unfinished\">&amp;Настаўленні выгляду...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation type=\"unfinished\">&amp;Адладка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation type=\"unfinished\">Дадаць/зняць &amp;пункт спыну</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation type=\"unfinished\">&amp;Наступны пункт спыну</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation type=\"unfinished\">Па&amp;пярэдні пункт спыну</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation type=\"unfinished\">&amp;Прыбраць усе пункты спыну</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation type=\"unfinished\">&amp;Выканаць</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation type=\"unfinished\">Выканаць &amp;вылучанае</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Даведка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation type=\"unfinished\">&amp;Даведка па ключавым слове</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation type=\"unfinished\">&amp;Дакументацыя па ключавым слове</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Рэдактар</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Рэдактар Octave</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation type=\"unfinished\">Перайсці да радка</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation type=\"unfinished\">Нумар радка</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation type=\"unfinished\">&lt;без назвы&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Закрыць</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation type=\"unfinished\">Усе файлы (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation type=\"unfinished\">\n\nУвага: змесціва ў рэдактары было зменена!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation type=\"unfinished\">Выглядае на тое, што &apos;%1&apos; быў зменены іншай праграмай. Перачытаць яго?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation type=\"unfinished\">Выглядае, што файл\n%1\nбыў выдалены або пераназваны. Можа, захаваць яго зараз?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation type=\"unfinished\">Памер файла</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation type=\"unfinished\">Тып файла</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation type=\"unfinished\">Дата змянення</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation type=\"unfinished\">Паказваць схаваныя</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation type=\"unfinished\">Колеры радкоў чаргуюцца</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation type=\"unfinished\">Пазначце шлях або назву файла</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\">Перайсці каталогам вышэй</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation type=\"unfinished\">Перайсці да каталогу Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation type=\"unfinished\">Перайсці да дзейнага каталога Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation type=\"unfinished\">Задаць каталог Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation type=\"unfinished\">Дзеянні з дзейным каталогам</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation type=\"unfinished\">Перайсці да хатняга каталогу</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\">Шукаць файлы...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation type=\"unfinished\">Новы файл...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation type=\"unfinished\">Новы каталог...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">Адкрыць</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation type=\"unfinished\">Капіяваць вылучанае ў буфер</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Выканаць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation type=\"unfinished\">Загрузіць звесткі</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation type=\"unfinished\">Задаць дзейны каталог</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation type=\"unfinished\">Выдаліць файл ці каталог</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation type=\"unfinished\">Сапраўды жадаеце выдаліць</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation type=\"unfinished\">Немагчыма выдаліць каталог, бо ён не пусты</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation type=\"unfinished\">Задаванне каталогу файлавага аглядніка</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation type=\"unfinished\">Стварыць файл</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Стварыць файл у\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation type=\"unfinished\">Стварыць каталог</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Стварыць каталог у\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation type=\"unfinished\">Новы каталог</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Файлавы агляднік</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation type=\"unfinished\">Прыемнага карыстання!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Раней</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation type=\"unfinished\">Скончыць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Скасаваць</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation type=\"unfinished\">З улікам &amp;рэгістру</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation type=\"unfinished\">Шукаць ад &amp;пачатку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation type=\"unfinished\">&amp;Цыклічны пошук</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation type=\"unfinished\">&amp;Замяніць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation type=\"unfinished\">Замяніць &amp;усё</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation type=\"unfinished\">&amp;Больш параметраў...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation type=\"unfinished\">&amp;Суцэльныя словы</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation type=\"unfinished\">Шукаць &amp;назад</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation type=\"unfinished\">Шукаць вы&amp;лучанае</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation type=\"unfinished\">Шукаць ад канца</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation type=\"unfinished\">Шукаць ад пачатку</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation type=\"unfinished\">Вынік замены</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation type=\"unfinished\">%1 элементаў заменена</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation type=\"unfinished\">Вынік пошуку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation type=\"unfinished\">Больш нічога не знойдзена</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation type=\"unfinished\">Пошук файлаў</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation type=\"unfinished\">Маска назваў:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation type=\"unfinished\">Пачынаць з:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation type=\"unfinished\">Задайце каталог, з якога пачынаць пошук</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation type=\"unfinished\">Агляд...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation type=\"unfinished\">Пазначыць каталог пачатку пошуку</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation type=\"unfinished\">Шукаць ува ўсіх падкаталогах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation type=\"unfinished\">Дадаваць пасавальныя каталогі ў вынікі пошуку</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation type=\"unfinished\">Змяшчае тэкст:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation type=\"unfinished\">Тэкст для пошуку</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation type=\"unfinished\">Вынікі пошуку</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation type=\"unfinished\">Idle.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Шукаць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation type=\"unfinished\">Пачаць пошук адпаведных файлаў</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Спыніць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation type=\"unfinished\">Змесціва файла</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation type=\"unfinished\">Ідзе пошук...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation type=\"unfinished\">Пазначыць каталог пошуку</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation type=\"unfinished\">Назва файла</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation type=\"unfinished\">Каталог</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation type=\"unfinished\">Крытычная памылка Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation type=\"unfinished\">Агляд і пошук па гісторыі загадаў.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Капіяваць</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation type=\"unfinished\">Вылічыць</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation type=\"unfinished\">Стварыць сцэнар</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Гісторыя загадаў</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Вітаем у Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">Далей</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Скасаваць</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\">&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Выглядае, што на гэтым кампутары вы выкарыстоўваеце графічны інтэрфэйс Octave упершыню.\nНацісніце &apos;Далей&apos;, каб запісаць файл канфігурацыі і запусціць Octave.&lt;/p&gt;\n&lt;p&gt;Файл канфігурацыі запісаны ў&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\">Захаваць прастору зменных як</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">Загрузіць прастору зменных</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Пра Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation type=\"unfinished\">Агляд каталогаў</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation type=\"unfinished\">Файлы Octave (*.m);;Усе файлы (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\">Новая функцыя</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation type=\"unfinished\">Назва новай функцыі:</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Рэдактар Octave</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Файл</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation type=\"unfinished\">Адкрыць...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation type=\"unfinished\">Загрузіць прастору зменных...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation type=\"unfinished\">Захаваць прастору зменных як...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation type=\"unfinished\">Выйсці</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation type=\"unfinished\">Новы</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Змяніць</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Адрабіць</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Капіяваць</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Уставіць</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Вылучыць усё</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Ачысціць буфер</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\">Шукаць файлы...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">Ачысціць загаднае акно</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Ачысціць гісторыю загадаў</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Ачысціць прастору зменных</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation type=\"unfinished\">Настаўленні...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation type=\"unfinished\">Ад&amp;ладка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">Крок</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Крок наперад</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">Крок назад</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Працягваць</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation type=\"unfinished\">&amp;Акно</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\">Паказваць загаднае акно</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">Паказваць гісторыю загадаў</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Паказваць файлавы агляднік</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">Паказваць прастору зменных</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">Паказваць рэдактар</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">Паказваць дакументацыю</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Загаднае акно</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Гісторыя загадаў</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Файлавы агляднік</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Прастора зменных</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Рэдактар</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Дакументацыя</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\">Стандартнае размеркаванне вокнаў</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Даведка</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Паведаміць пра хібу</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Пакеты Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation type=\"unfinished\">На дыску</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation type=\"unfinished\">Анлайн</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation type=\"unfinished\">&amp;Навіны</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Заўвагі да выпуску</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Навіны супольнасці</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation type=\"unfinished\">Пазначце назву каталогу</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation type=\"unfinished\">Дзейны каталог:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\">Перайсці каталогам вышэй</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\">&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nВыглядае, што крыніца навінаў супольнасці Octave недаступная.\n&lt;/p&gt;\n&lt;p&gt;\nКаб атрымаць апошнія навіны, наведайце\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;,\nкалі маеце злучэнне з Сецівам (спасылка адкрыецца ў знешнім браўзэры).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Распрацоўнікі Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation type=\"unfinished\">Даведка пра</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation type=\"unfinished\">Дакументацыя пра</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation type=\"unfinished\">Змяніць</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Рэдактар Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Стандартны</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Скасаваць</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">Файл\n%1\nне існуе. Жадаеце стварыць яго?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Рэдактар Octave</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation type=\"unfinished\">Змяніць каталог або Дадаць каталог да дзейнага шляху</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation type=\"unfinished\">Файл заўваг да выпуску &apos;%1&apos; пусты.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation type=\"unfinished\">Файл заўваг да выпуску &apos;%1&apos; не выйшла прачытаць.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation type=\"unfinished\">Заўвагі да выпуску Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation type=\"unfinished\">глабальная</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation type=\"unfinished\">Сістэмная</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation type=\"unfinished\">IBeam</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation type=\"unfinished\">Блок</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation type=\"unfinished\">Падкрэсленне</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Навіны супольнасці</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Раней</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">Далей</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Скасаваць</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Рэдактар</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Вітаем у GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Вітаем у Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Загаднае акно</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Капіяваць</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Уставіць</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Капіяваць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Уставіць</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\">Выдаліць</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Вітаем у GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation type=\"unfinished\">Назва</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Клас</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Памернасць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Значэнне</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation type=\"unfinished\">Правы пстрык каб капіяваць, пераназваць ці адлюстраваць</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation type=\"unfinished\">камплексны</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Клас</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Памернасць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Значэнне</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Прастора зменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation type=\"unfinished\">Прагляд зменных дзейнай прасторы.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation type=\"unfinished\">Выгляд зменных у актыўнай прасторы зменных.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation type=\"unfinished\">Пераназваць</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Агульныя</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Толькі эмблема Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translatorcomment>не пэўны</translatorcomment>\n        <translation>Літарныя значкі</translation>\n    </message>\n    <message>\n        <location line=\"-334\"/>\n        <source>Dock widget title bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+565\"/>\n        <source>Editor</source>\n        <translation>Рэдактар</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-516\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+494\"/>\n        <source>Show tool bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+221\"/>\n        <source>Rotated tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\">Пазіцыі</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+260\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Indentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation>Даўжыня водступу</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Табуляцыя робіць водступ</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Аўтаводступы</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Даўжыня табуляцыі</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translatorcomment>- не пэўны\n- даўжэй не трэба, не змяшчаецца!</translatorcomment>\n        <translation>Паказваць накіравальныя водступаў</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Backspace прыбірае водступ</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>Для ключавых словаў</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Улічваць рэгістр</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Замяняць слова на прапанаванае</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Для словаў з дакумента</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation>Свой файлавы рэдактар</translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation>Выгляд рэдактара</translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Шрыфт</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Паказваць нумары радкоў</translation>\n    </message>\n    <message>\n        <location line=\"-866\"/>\n        <source>Interface</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-72\"/>\n        <source>Graphic icons</source>\n        <translation>Графічныя значкі</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Background inactive</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1305\"/>\n        <source>Show whitespace</source>\n        <translation>Паказваць прагальныя знакі</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Не паказваць прагальныя знакі ў водступах</translation>\n    </message>\n    <message>\n        <location line=\"+1125\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Ствараць няісныя файлы без пытанняў</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>Загад (%f=файл, %l-радок):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Тып курсора:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Выкар. колер пярэдняга плану</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Памер шрыфту</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Файлавы агляднік</translation>\n    </message>\n    <message>\n        <location line=\"-2031\"/>\n        <source>Normal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+359\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+540\"/>\n        <source>Show EOL characters</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1812\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\">Загады</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+191\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Behavior</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Прастора зменных</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Стандартны</translation>\n    </message>\n    <message>\n        <location line=\"+232\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-227\"/>\n        <source>Actual</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Сетка</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Дазволіць Octave злучацца з вэб-сайтам Octave для адлюстравання навінаў і свежай інфармацыі</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Выкарыстоўваць проксі-сервер</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Сінхранізаваць дзейны каталог Octave з файлавым агляднікам</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+302\"/>\n        <source>Shortcuts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Назва хоста:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Тып проксі:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Порт:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Імя карыстальніка:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Пароль:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation type=\"unfinished\">Новы файл</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\">Новая функцыя</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">Загрузіць прастору зменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\">Захаваць прастору зменных як</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Капіяваць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Уставіць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Адрабіць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Вылучыць усё</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Ачысціць буфер</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">Ачысціць загаднае акно</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Ачысціць гісторыю загадаў</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Ачысціць прастору зменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">Крок</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Крок наперад</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">Крок назад</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Працягваць</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\">Паказваць загаднае акно</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">Паказваць гісторыю загадаў</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Паказваць файлавы агляднік</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">Паказваць прастору зменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">Паказваць рэдактар</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">Паказваць дакументацыю</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Загаднае акно</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Гісторыя загадаў</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Файлавы агляднік</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Прастора зменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Рэдактар</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Дакументацыя</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\">Стандартнае размеркаванне вокнаў</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Паведаміць пра хібу</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Пакеты Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation type=\"unfinished\">Палепшыць Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation type=\"unfinished\">Рэсурсы распрацоўніка Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Пра Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Заўвагі да выпуску</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Навіны супольнасці</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation type=\"unfinished\">Друк</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/build_ts/README.md",
    "content": "# Updating language files for the Octave GUI\n\n## Why updating and when?\n\nBefore a new release of Octave, the language files `libgui/languages/*.ts`\nhave to be updated with changed or new strings in the source files in order to\nadd translations afterwards.\n\n## How to update the files (*.ts)\n\nThe update is carried out by the Qt-tool `lupdate` which collect strings in\nsource files found in the search path(s) provided as input argument to\n`lupdate`.  The tool `lupdate` is called from the script\n\n- `libgui/languages/build_ts/update_ts_files`\n\nwhich also determines the required search paths for each language.\n\nBesides source folders within `libgui`, the search path is extended by some Qt\nand Qsci files, collected in\n\n- `libgui/build_ts/octave-qt` and\n- `libgui/build_ts/octave-qsci`\n\nrespectively, whenever there are no translation files for the language from Qt\nor QScintilla.\n\nThe following steps are required in order to update the language files\n`libgui/languages/*.ts`:\n\n1. Change into `libgui/languages`\n2. Start the update by calling `./build_ts/update_ts_files`\n3. Select the language files that should be updated.\n\nAs `lupdate` is not able to expand the macros for the octave namespace,\nthe script `update_ts_files` first copies the GUI sources into a temporary\ndirectory where all namespace macros are replaced with their expansions.\nTherefore, do **not** abort the script with `<Ctrl+C>` but only by typing\n`q` at a prompt for translating a language ot not. Otherwise, the temporary\ncopies of the sources are not removed.\n\n## Updating Qt and Qsci used for the language files\n\nFrom time to time, for example when a new major version of Qt is available, the\nsource files in\n\n- `libgui/build_ts/octave-qt` and\n- `libgui/build_ts/octave-qsci`\n\nshould also be updated.  These sources are scanned for strings for languages\nwhere no translation is provided by Qt and/or QScintilla.  The sources are\nupdated with the following steps:\n\n1. Download the Qt sources (example for Qt6):\n    1. `git clone git://code.qt.io/qt/qt5.git qt6`\n    2. `cd qt6`\n    3. `git switch 6.X` where X is the current minor version\n    4. `perl init-repository`\n2. [Download the latest QScintilla](https://riverbankcomputing.com/software/qscintilla/download) and unpack the archive to the desired location\n3. Change into `libgui/languages/build_ts`\n4. Call `./update_external_sources  path_qt  path_qsci` where `path_qt` and\n   `path_qsci` are the absolute or relative paths to the Qt and QScintilla\n   sources respectively.\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qsciabstractapis.h",
    "content": "// This module defines interface to the QsciAbstractAPIs class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCIABSTRACTAPIS_H\n#define QSCIABSTRACTAPIS_H\n\n#include <QList>\n#include <QObject>\n#include <QStringList>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qsciscintilla.h>\n\n\nclass QsciLexer;\n\n\n//! \\brief The QsciAbstractAPIs class represents the interface to the textual\n//! API information used in call tips and for auto-completion.  A sub-class\n//! will provide the actual implementation of the interface.\n//!\n//! API information is specific to a particular language lexer but can be\n//! shared by multiple instances of the lexer.\nclass QSCINTILLA_EXPORT QsciAbstractAPIs : public QObject\n{\n    Q_OBJECT\n\npublic:\n    //! Constructs a QsciAbstractAPIs instance attached to lexer \\a lexer.  \\a\n    //! lexer becomes the instance's parent object although the instance can\n    //! also be subsequently attached to other lexers.\n    QsciAbstractAPIs(QsciLexer *lexer);\n\n    //! Destroy the QsciAbstractAPIs instance.\n    virtual ~QsciAbstractAPIs();\n\n    //! Return the lexer that the instance is attached to.\n    QsciLexer *lexer() const;\n\n    //! Update the list \\a list with API entries derived from \\a context.  \\a\n    //! context is the list of words in the text preceding the cursor position.\n    //! The characters that make up a word and the characters that separate\n    //! words are defined by the lexer.  The last word is a partial word and\n    //! may be empty if the user has just entered a word separator.\n    virtual void updateAutoCompletionList(const QStringList &context,\n            QStringList &list) = 0;\n\n    //! This is called when the user selects the entry \\a selection from the\n    //! auto-completion list.  A sub-class can use this as a hint to provide\n    //! more specific API entries in future calls to\n    //! updateAutoCompletionList().  The default implementation does nothing.\n    virtual void autoCompletionSelected(const QString &selection);\n\n    //! Return the call tips valid for the context \\a context.  (Note that the\n    //! last word of the context will always be empty.)  \\a commas is the number\n    //! of commas the user has typed after the context and before the cursor\n    //! position.  The exact position of the list of call tips can be adjusted\n    //! by specifying a corresponding left character shift in \\a shifts.  This\n    //! is normally done to correct for any displayed context according to \\a\n    //! style.\n    //!\n    //! \\sa updateAutoCompletionList()\n    virtual QStringList callTips(const QStringList &context, int commas,\n            QsciScintilla::CallTipsStyle style, QList<int> &shifts) = 0;\n\nprivate:\n    QsciLexer *lex;\n\n    QsciAbstractAPIs(const QsciAbstractAPIs &);\n    QsciAbstractAPIs &operator=(const QsciAbstractAPIs &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qsciapis.h",
    "content": "// This module defines interface to the QsciAPIs class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCIAPIS_H\n#define QSCIAPIS_H\n\n#include <QList>\n#include <QObject>\n#include <QPair>\n#include <QStringList>\n\n#include <Qsci/qsciabstractapis.h>\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qsciscintilla.h>\n\n\nclass QsciAPIsPrepared;\nclass QsciAPIsWorker;\nclass QsciLexer;\n\n\n//! \\brief The QsciAPIs class provies an implementation of the textual API\n//! information used in call tips and for auto-completion.\n//!\n//! Raw API information is read from one or more files.  Each API function is\n//! described by a single line of text comprising the function's name, followed\n//! by the function's optional comma separated parameters enclosed in\n//! parenthesis, and finally followed by optional explanatory text.\n//!\n//! A function name may be followed by a `?' and a number.  The number is used\n//! by auto-completion to display a registered QPixmap with the function name.\n//!\n//! All function names are used by auto-completion, but only those that include\n//! function parameters are used in call tips.\n//!\n//! QScintilla only deals with prepared API information and not the raw\n//! information described above.  This is done so that large APIs can be\n//! handled while still being responsive to user input.  The conversion of raw\n//! information to prepared information is time consuming (think tens of\n//! seconds) and implemented in a separate thread.  Prepared information can\n//! be quickly saved to and loaded from files.  Such files are portable between\n//! different architectures.\n//!\n//! QScintilla based applications that want to support large APIs would\n//! normally provide the user with the ability to specify a set of, possibly\n//! project specific, raw API files and convert them to prepared files that are\n//! loaded quickly when the application is invoked.\nclass QSCINTILLA_EXPORT QsciAPIs : public QsciAbstractAPIs\n{\n    Q_OBJECT\n\npublic:\n    //! Constructs a QsciAPIs instance attached to lexer \\a lexer.  \\a lexer\n    //! becomes the instance's parent object although the instance can also be\n    //! subsequently attached to other lexers.\n    QsciAPIs(QsciLexer *lexer);\n\n    //! Destroy the QsciAPIs instance.\n    virtual ~QsciAPIs();\n\n    //! Add the single raw API entry \\a entry to the current set.\n    //!\n    //! \\sa clear(), load(), remove()\n    void add(const QString &entry);\n\n    //! Deletes all raw API information.\n    //!\n    //! \\sa add(), load(), remove()\n    void clear();\n\n    //! Load the API information from the file named \\a filename, adding it to\n    //! the current set.  Returns true if successful, otherwise false.\n    bool load(const QString &filename);\n\n    //! Remove the single raw API entry \\a entry from the current set.\n    //!\n    //! \\sa add(), clear(), load()\n    void remove(const QString &entry);\n\n    //! Convert the current raw API information to prepared API information.\n    //! This is implemented by a separate thread.\n    //!\n    //! \\sa cancelPreparation()\n    void prepare();\n\n    //! Cancel the conversion of the current raw API information to prepared\n    //! API information.\n    //!\n    //! \\sa prepare()\n    void cancelPreparation();\n\n    //! Return the default name of the prepared API information file.  It is\n    //! based on the name of the associated lexer and in the directory defined\n    //! by the QSCIDIR environment variable.  If the environment variable isn't\n    //! set then $HOME/.qsci is used.\n    QString defaultPreparedName() const;\n\n    //! Check to see is a prepared API information file named \\a filename\n    //! exists.  If \\a filename is empty then the value returned by\n    //! defaultPreparedName() is used.  Returns true if successful, otherwise\n    //! false.\n    //!\n    //! \\sa defaultPreparedName()\n    bool isPrepared(const QString &filename = QString()) const;\n\n    //! Load the prepared API information from the file named \\a filename.  If\n    //! \\a filename is empty then a name is constructed based on the name of\n    //! the associated lexer and saved in the directory defined by the QSCIDIR\n    //! environment variable.  If the environment variable isn't set then\n    //! $HOME/.qsci is used.  Returns true if successful, otherwise false.\n    bool loadPrepared(const QString &filename = QString());\n\n    //! Save the prepared API information to the file named \\a filename.  If\n    //! \\a filename is empty then a name is constructed based on the name of\n    //! the associated lexer and saved in the directory defined by the QSCIDIR\n    //! environment variable.  If the environment variable isn't set then\n    //! $HOME/.qsci is used.  Returns true if successful, otherwise false.\n    bool savePrepared(const QString &filename = QString()) const;\n\n    //! \\reimp\n    virtual void updateAutoCompletionList(const QStringList &context,\n            QStringList &list);\n\n    //! \\reimp\n    virtual void autoCompletionSelected(const QString &sel);\n\n    //! \\reimp\n    virtual QStringList callTips(const QStringList &context, int commas,\n            QsciScintilla::CallTipsStyle style, QList<int> &shifts);\n\n    //! \\internal Reimplemented to receive termination events from the worker\n    //! thread.\n    virtual bool event(QEvent *e);\n\n    //! Return a list of the installed raw API file names for the associated\n    //! lexer.\n    QStringList installedAPIFiles() const;\n\nsignals:\n    //! This signal is emitted when the conversion of raw API information to\n    //! prepared API information has been cancelled.\n    //!\n    //! \\sa apiPreparationFinished(), apiPreparationStarted()\n    void apiPreparationCancelled();\n\n    //! This signal is emitted when the conversion of raw API information to\n    //! prepared API information starts and can be used to give some visual\n    //! feedback to the user.\n    //!\n    //! \\sa apiPreparationCancelled(), apiPreparationFinished()\n    void apiPreparationStarted();\n    \n    //! This signal is emitted when the conversion of raw API information to\n    //! prepared API information has finished.\n    //!\n    //! \\sa apiPreparationCancelled(), apiPreparationStarted()\n    void apiPreparationFinished();\n\nprivate:\n    friend class QsciAPIsPrepared;\n    friend class QsciAPIsWorker;\n\n    // This indexes a word in a set of raw APIs.  The first part indexes the\n    // entry in the set, the second part indexes the word within the entry.\n    typedef QPair<quint32, quint32> WordIndex;\n\n    // This is a list of word indexes.\n    typedef QList<WordIndex> WordIndexList;\n\n    QsciAPIsWorker *worker;\n    QStringList old_context;\n    QStringList::const_iterator origin;\n    int origin_len;\n    QString unambiguous_context;\n    QStringList apis;\n    QsciAPIsPrepared *prep;\n\n    static bool enoughCommas(const QString &s, int commas);\n\n    QStringList positionOrigin(const QStringList &context, QString &path);\n    bool originStartsWith(const QString &path, const QString &wsep);\n    const WordIndexList *wordIndexOf(const QString &word) const;\n    void lastCompleteWord(const QString &word, QStringList &with_context,\n            bool &unambig);\n    void lastPartialWord(const QString &word, QStringList &with_context,\n            bool &unambig);\n    void addAPIEntries(const WordIndexList &wl, bool complete,\n            QStringList &with_context, bool &unambig);\n    QString prepName(const QString &filename, bool mkpath = false) const;\n    void deleteWorker();\n\n    QsciAPIs(const QsciAPIs &);\n    QsciAPIs &operator=(const QsciAPIs &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscicommand.h",
    "content": "// This defines the interface to the QsciCommand class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCICOMMAND_H\n#define QSCICOMMAND_H\n\n#include <qstring.h>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qsciscintillabase.h>\n\n\nclass QsciScintilla;\n\n\n//! \\brief The QsciCommand class represents an internal editor command that may\n//! have one or two keys bound to it.\n//!\n//! Methods are provided to change the keys bound to the command and to remove\n//! a key binding.  Each command has a user friendly description of the command\n//! for use in key mapping dialogs.\nclass QSCINTILLA_EXPORT QsciCommand\n{\npublic:\n    //! This enum defines the different commands that can be assigned to a key.\n    enum Command {\n        //! Move down one line.\n        LineDown = QsciScintillaBase::SCI_LINEDOWN,\n\n        //! Extend the selection down one line.\n        LineDownExtend = QsciScintillaBase::SCI_LINEDOWNEXTEND,\n\n        //! Extend the rectangular selection down one line.\n        LineDownRectExtend = QsciScintillaBase::SCI_LINEDOWNRECTEXTEND,\n\n        //! Scroll the view down one line.\n        LineScrollDown = QsciScintillaBase::SCI_LINESCROLLDOWN,\n\n        //! Move up one line.\n        LineUp = QsciScintillaBase::SCI_LINEUP,\n\n        //! Extend the selection up one line.\n        LineUpExtend = QsciScintillaBase::SCI_LINEUPEXTEND,\n\n        //! Extend the rectangular selection up one line.\n        LineUpRectExtend = QsciScintillaBase::SCI_LINEUPRECTEXTEND,\n\n        //! Scroll the view up one line.\n        LineScrollUp = QsciScintillaBase::SCI_LINESCROLLUP,\n\n        //! Scroll to the start of the document.\n        ScrollToStart = QsciScintillaBase::SCI_SCROLLTOSTART,\n\n        //! Scroll to the end of the document.\n        ScrollToEnd = QsciScintillaBase::SCI_SCROLLTOEND,\n\n        //! Scroll vertically to centre the current line.\n        VerticalCentreCaret = QsciScintillaBase::SCI_VERTICALCENTRECARET,\n\n        //! Move down one paragraph.\n        ParaDown = QsciScintillaBase::SCI_PARADOWN,\n\n        //! Extend the selection down one paragraph.\n        ParaDownExtend = QsciScintillaBase::SCI_PARADOWNEXTEND,\n\n        //! Move up one paragraph.\n        ParaUp = QsciScintillaBase::SCI_PARAUP,\n\n        //! Extend the selection up one paragraph.\n        ParaUpExtend = QsciScintillaBase::SCI_PARAUPEXTEND,\n\n        //! Move left one character.\n        CharLeft = QsciScintillaBase::SCI_CHARLEFT,\n\n        //! Extend the selection left one character.\n        CharLeftExtend = QsciScintillaBase::SCI_CHARLEFTEXTEND,\n\n        //! Extend the rectangular selection left one character.\n        CharLeftRectExtend = QsciScintillaBase::SCI_CHARLEFTRECTEXTEND,\n\n        //! Move right one character.\n        CharRight = QsciScintillaBase::SCI_CHARRIGHT,\n\n        //! Extend the selection right one character.\n        CharRightExtend = QsciScintillaBase::SCI_CHARRIGHTEXTEND,\n\n        //! Extend the rectangular selection right one character.\n        CharRightRectExtend = QsciScintillaBase::SCI_CHARRIGHTRECTEXTEND,\n\n        //! Move left one word.\n        WordLeft = QsciScintillaBase::SCI_WORDLEFT,\n\n        //! Extend the selection left one word.\n        WordLeftExtend = QsciScintillaBase::SCI_WORDLEFTEXTEND,\n\n        //! Move right one word.\n        WordRight = QsciScintillaBase::SCI_WORDRIGHT,\n\n        //! Extend the selection right one word.\n        WordRightExtend = QsciScintillaBase::SCI_WORDRIGHTEXTEND,\n\n        //! Move to the end of the previous word.\n        WordLeftEnd = QsciScintillaBase::SCI_WORDLEFTEND,\n\n        //! Extend the selection to the end of the previous word.\n        WordLeftEndExtend = QsciScintillaBase::SCI_WORDLEFTENDEXTEND,\n\n        //! Move to the end of the next word.\n        WordRightEnd = QsciScintillaBase::SCI_WORDRIGHTEND,\n\n        //! Extend the selection to the end of the next word.\n        WordRightEndExtend = QsciScintillaBase::SCI_WORDRIGHTENDEXTEND,\n\n        //! Move left one word part.\n        WordPartLeft = QsciScintillaBase::SCI_WORDPARTLEFT,\n\n        //! Extend the selection left one word part.\n        WordPartLeftExtend = QsciScintillaBase::SCI_WORDPARTLEFTEXTEND,\n\n        //! Move right one word part.\n        WordPartRight = QsciScintillaBase::SCI_WORDPARTRIGHT,\n\n        //! Extend the selection right one word part.\n        WordPartRightExtend = QsciScintillaBase::SCI_WORDPARTRIGHTEXTEND,\n\n        //! Move to the start of the document line.\n        Home = QsciScintillaBase::SCI_HOME,\n\n        //! Extend the selection to the start of the document line.\n        HomeExtend = QsciScintillaBase::SCI_HOMEEXTEND,\n\n        //! Extend the rectangular selection to the start of the document line.\n        HomeRectExtend = QsciScintillaBase::SCI_HOMERECTEXTEND,\n\n        //! Move to the start of the displayed line.\n        HomeDisplay = QsciScintillaBase::SCI_HOMEDISPLAY,\n\n        //! Extend the selection to the start of the displayed line.\n        HomeDisplayExtend = QsciScintillaBase::SCI_HOMEDISPLAYEXTEND,\n\n        //! Move to the start of the displayed or document line.\n        HomeWrap = QsciScintillaBase::SCI_HOMEWRAP,\n\n        //! Extend the selection to the start of the displayed or document\n        //! line.\n        HomeWrapExtend = QsciScintillaBase::SCI_HOMEWRAPEXTEND,\n\n        //! Move to the first visible character in the document line.\n        VCHome = QsciScintillaBase::SCI_VCHOME,\n\n        //! Extend the selection to the first visible character in the document\n        //! line.\n        VCHomeExtend = QsciScintillaBase::SCI_VCHOMEEXTEND,\n\n        //! Extend the rectangular selection to the first visible character in\n        //! the document line.\n        VCHomeRectExtend = QsciScintillaBase::SCI_VCHOMERECTEXTEND,\n\n        //! Move to the first visible character of the displayed or document\n        //! line.\n        VCHomeWrap = QsciScintillaBase::SCI_VCHOMEWRAP,\n\n        //! Extend the selection to the first visible character of the\n        //! displayed or document line.\n        VCHomeWrapExtend = QsciScintillaBase::SCI_VCHOMEWRAPEXTEND,\n\n        //! Move to the end of the document line.\n        LineEnd = QsciScintillaBase::SCI_LINEEND,\n\n        //! Extend the selection to the end of the document line.\n        LineEndExtend = QsciScintillaBase::SCI_LINEENDEXTEND,\n\n        //! Extend the rectangular selection to the end of the document line.\n        LineEndRectExtend = QsciScintillaBase::SCI_LINEENDRECTEXTEND,\n\n        //! Move to the end of the displayed line.\n        LineEndDisplay = QsciScintillaBase::SCI_LINEENDDISPLAY,\n\n        //! Extend the selection to the end of the displayed line.\n        LineEndDisplayExtend = QsciScintillaBase::SCI_LINEENDDISPLAYEXTEND,\n\n        //! Move to the end of the displayed or document line.\n        LineEndWrap = QsciScintillaBase::SCI_LINEENDWRAP,\n\n        //! Extend the selection to the end of the displayed or document line.\n        LineEndWrapExtend = QsciScintillaBase::SCI_LINEENDWRAPEXTEND,\n\n        //! Move to the start of the document.\n        DocumentStart = QsciScintillaBase::SCI_DOCUMENTSTART,\n\n        //! Extend the selection to the start of the document.\n        DocumentStartExtend = QsciScintillaBase::SCI_DOCUMENTSTARTEXTEND,\n\n        //! Move to the end of the document.\n        DocumentEnd = QsciScintillaBase::SCI_DOCUMENTEND,\n\n        //! Extend the selection to the end of the document.\n        DocumentEndExtend = QsciScintillaBase::SCI_DOCUMENTENDEXTEND,\n\n        //! Move up one page.\n        PageUp = QsciScintillaBase::SCI_PAGEUP,\n\n        //! Extend the selection up one page.\n        PageUpExtend = QsciScintillaBase::SCI_PAGEUPEXTEND,\n\n        //! Extend the rectangular selection up one page.\n        PageUpRectExtend = QsciScintillaBase::SCI_PAGEUPRECTEXTEND,\n\n        //! Move down one page.\n        PageDown = QsciScintillaBase::SCI_PAGEDOWN,\n\n        //! Extend the selection down one page.\n        PageDownExtend = QsciScintillaBase::SCI_PAGEDOWNEXTEND,\n\n        //! Extend the rectangular selection down one page.\n        PageDownRectExtend = QsciScintillaBase::SCI_PAGEDOWNRECTEXTEND,\n\n        //! Stuttered move up one page.\n        StutteredPageUp = QsciScintillaBase::SCI_STUTTEREDPAGEUP,\n\n        //! Stuttered extend the selection up one page.\n        StutteredPageUpExtend = QsciScintillaBase::SCI_STUTTEREDPAGEUPEXTEND,\n\n        //! Stuttered move down one page.\n        StutteredPageDown = QsciScintillaBase::SCI_STUTTEREDPAGEDOWN,\n\n        //! Stuttered extend the selection down one page.\n        StutteredPageDownExtend = QsciScintillaBase::SCI_STUTTEREDPAGEDOWNEXTEND,\n\n        //! Delete the current character.\n        Delete = QsciScintillaBase::SCI_CLEAR,\n\n        //! Delete the previous character.\n        DeleteBack = QsciScintillaBase::SCI_DELETEBACK,\n\n        //! Delete the previous character if not at start of line.\n        DeleteBackNotLine = QsciScintillaBase::SCI_DELETEBACKNOTLINE,\n\n        //! Delete the word to the left.\n        DeleteWordLeft = QsciScintillaBase::SCI_DELWORDLEFT,\n\n        //! Delete the word to the right.\n        DeleteWordRight = QsciScintillaBase::SCI_DELWORDRIGHT,\n\n        //! Delete right to the end of the next word.\n        DeleteWordRightEnd = QsciScintillaBase::SCI_DELWORDRIGHTEND,\n\n        //! Delete the line to the left.\n        DeleteLineLeft = QsciScintillaBase::SCI_DELLINELEFT,\n\n        //! Delete the line to the right.\n        DeleteLineRight = QsciScintillaBase::SCI_DELLINERIGHT,\n\n        //! Delete the current line.\n        LineDelete = QsciScintillaBase::SCI_LINEDELETE,\n\n        //! Cut the current line to the clipboard.\n        LineCut = QsciScintillaBase::SCI_LINECUT,\n\n        //! Copy the current line to the clipboard.\n        LineCopy = QsciScintillaBase::SCI_LINECOPY,\n\n        //! Transpose the current and previous lines.\n        LineTranspose = QsciScintillaBase::SCI_LINETRANSPOSE,\n\n        //! Duplicate the current line.\n        LineDuplicate = QsciScintillaBase::SCI_LINEDUPLICATE,\n\n        //! Select the whole document.\n        SelectAll = QsciScintillaBase::SCI_SELECTALL,\n\n        //! Move the selected lines up one line.\n        MoveSelectedLinesUp = QsciScintillaBase::SCI_MOVESELECTEDLINESUP,\n\n        //! Move the selected lines down one line.\n        MoveSelectedLinesDown = QsciScintillaBase::SCI_MOVESELECTEDLINESDOWN,\n\n        //! Duplicate the selection.\n        SelectionDuplicate = QsciScintillaBase::SCI_SELECTIONDUPLICATE,\n\n        //! Convert the selection to lower case.\n        SelectionLowerCase = QsciScintillaBase::SCI_LOWERCASE,\n\n        //! Convert the selection to upper case.\n        SelectionUpperCase = QsciScintillaBase::SCI_UPPERCASE,\n\n        //! Cut the selection to the clipboard.\n        SelectionCut = QsciScintillaBase::SCI_CUT,\n\n        //! Copy the selection to the clipboard.\n        SelectionCopy = QsciScintillaBase::SCI_COPY,\n\n        //! Paste from the clipboard.\n        Paste = QsciScintillaBase::SCI_PASTE,\n\n        //! Toggle insert/overtype.\n        EditToggleOvertype = QsciScintillaBase::SCI_EDITTOGGLEOVERTYPE,\n\n        //! Insert a platform dependent newline.\n        Newline = QsciScintillaBase::SCI_NEWLINE,\n\n        //! Insert a formfeed.\n        Formfeed = QsciScintillaBase::SCI_FORMFEED,\n\n        //! Indent one level.\n        Tab = QsciScintillaBase::SCI_TAB,\n\n        //! De-indent one level.\n        Backtab = QsciScintillaBase::SCI_BACKTAB,\n\n        //! Cancel any current operation.\n        Cancel = QsciScintillaBase::SCI_CANCEL,\n\n        //! Undo the last command.\n        Undo = QsciScintillaBase::SCI_UNDO,\n\n        //! Redo the last command.\n        Redo = QsciScintillaBase::SCI_REDO,\n\n        //! Zoom in.\n        ZoomIn = QsciScintillaBase::SCI_ZOOMIN,\n\n        //! Zoom out.\n        ZoomOut = QsciScintillaBase::SCI_ZOOMOUT,\n\n        //! Reverse the selected lines.\n        ReverseLines = QsciScintillaBase::SCI_LINEREVERSE,\n    };\n\n    //! Return the command that will be executed by this instance.\n    Command command() const {return scicmd;}\n\n    //! Execute the command.\n    void execute();\n\n    //! Binds the key \\a key to the command.  If \\a key is 0 then the key\n    //! binding is removed.  If \\a key is invalid then the key binding is\n    //! unchanged.  Valid keys are any visible or control character or any\n    //! of \\c Qt::Key_Down, \\c Qt::Key_Up, \\c Qt::Key_Left, \\c Qt::Key_Right,\n    //! \\c Qt::Key_Home, \\c Qt::Key_End, \\c Qt::Key_PageUp,\n    //! \\c Qt::Key_PageDown, \\c Qt::Key_Delete, \\c Qt::Key_Insert,\n    //! \\c Qt::Key_Escape, \\c Qt::Key_Backspace, \\c Qt::Key_Tab,\n    //! \\c Qt::Key_Backtab, \\c Qt::Key_Return, \\c Qt::Key_Enter,\n    //! \\c Qt::Key_Super_L, \\c Qt::Key_Super_R or \\c Qt::Key_Menu.  Keys may be\n    //! modified with any combination of \\c Qt::ShiftModifier,\n    //! \\c Qt::ControlModifier, \\c Qt::AltModifier and \\c Qt::MetaModifier.\n    //!\n    //! \\sa key(), setAlternateKey(), validKey()\n    void setKey(int key);\n\n    //! Binds the alternate key \\a altkey to the command.  If \\a key is 0\n    //! then the alternate key binding is removed.\n    //!\n    //! \\sa alternateKey(), setKey(), validKey()\n    void setAlternateKey(int altkey);\n\n    //! The key that is currently bound to the command is returned.\n    //!\n    //! \\sa setKey(), alternateKey()\n    int key() const {return qkey;}\n\n    //! The alternate key that is currently bound to the command is\n    //! returned.\n    //!\n    //! \\sa setAlternateKey(), key()\n    int alternateKey() const {return qaltkey;}\n\n    //! If the key \\a key is valid then true is returned.\n    static bool validKey(int key);\n\n    //! The user friendly description of the command is returned.\n    QString description() const;\n\nprivate:\n    friend class QsciCommandSet;\n\n    QsciCommand(QsciScintilla *qs, Command cmd, int key, int altkey,\n            const char *desc);\n\n    void bindKey(int key,int &qk,int &scik);\n\n    QsciScintilla *qsCmd;\n    Command scicmd;\n    int qkey, scikey, qaltkey, scialtkey;\n    const char *descCmd;\n\n    QsciCommand(const QsciCommand &);\n    QsciCommand &operator=(const QsciCommand &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscicommandset.h",
    "content": "// This defines the interface to the QsciCommandSet class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCICOMMANDSET_H\n#define QSCICOMMANDSET_H\n\n#include <qglobal.h>\n\n#include <QList>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscicommand.h>\n\n\nQT_BEGIN_NAMESPACE\nclass QSettings;\nQT_END_NAMESPACE\n\nclass QsciScintilla;\n\n\n//! \\brief The QsciCommandSet class represents the set of all internal editor\n//! commands that may have keys bound.\n//!\n//! Methods are provided to access the individual commands and to read and\n//! write the current bindings from and to settings files.\nclass QSCINTILLA_EXPORT QsciCommandSet\n{\npublic:\n    //! The key bindings for each command in the set are read from the\n    //! settings \\a qs.  \\a prefix is prepended to the key of each entry.\n    //! true is returned if there was no error.\n    //!\n    //! \\sa writeSettings()\n    bool readSettings(QSettings &qs, const char *prefix = \"/Scintilla\");\n\n    //! The key bindings for each command in the set are written to the\n    //! settings \\a qs.  \\a prefix is prepended to the key of each entry.\n    //! true is returned if there was no error.\n    //!\n    //! \\sa readSettings()\n    bool writeSettings(QSettings &qs, const char *prefix = \"/Scintilla\");\n\n    //! The commands in the set are returned as a list.\n    QList<QsciCommand *> &commands() {return cmds;}\n\n    //! The primary keys bindings for all commands are removed.\n    void clearKeys();\n\n    //! The alternate keys bindings for all commands are removed.\n    void clearAlternateKeys();\n\n    // Find the command that is bound to \\a key.\n    QsciCommand *boundTo(int key) const;\n\n    // Find a specific command \\a command.\n    QsciCommand *find(QsciCommand::Command command) const;\n\nprivate:\n    friend class QsciScintilla;\n\n    QsciCommandSet(QsciScintilla *qs);\n    ~QsciCommandSet();\n\n    QsciScintilla *qsci;\n    QList<QsciCommand *> cmds;\n\n    QsciCommandSet(const QsciCommandSet &);\n    QsciCommandSet &operator=(const QsciCommandSet &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscidocument.h",
    "content": "// This defines the interface to the QsciDocument class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCIDOCUMENT_H\n#define QSCIDOCUMENT_H\n\n#include <Qsci/qsciglobal.h>\n\n\nclass QsciScintillaBase;\nclass QsciDocumentP;\n\n\n//! \\brief The QsciDocument class represents a document to be edited.\n//!\n//! It is an opaque class that can be attached to multiple instances of\n//! QsciScintilla to create different simultaneous views of the same document.\n//! QsciDocument uses implicit sharing so that copying class instances is a\n//! cheap operation.\nclass QSCINTILLA_EXPORT QsciDocument\n{\npublic:\n    //! Create a new unattached document.\n    QsciDocument();\n    virtual ~QsciDocument();\n\n    QsciDocument(const QsciDocument &);\n    QsciDocument &operator=(const QsciDocument &);\n\nprivate:\n    friend class QsciScintilla;\n\n    void attach(const QsciDocument &that);\n    void detach();\n    void display(QsciScintillaBase *qsb, const QsciDocument *from);\n    void undisplay(QsciScintillaBase *qsb);\n\n    bool isModified() const;\n    void setModified(bool m);\n\n    QsciDocumentP *pdoc;\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qsciglobal.h",
    "content": "// This module defines various things common to all of the Scintilla Qt port.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCIGLOBAL_H\n#define QSCIGLOBAL_H\n\n#include <qglobal.h>\n\n\n#define QSCINTILLA_VERSION      0x020e00\n#define QSCINTILLA_VERSION_STR  \"2.14.0\"\n\n\n// We only support Qt v5.11 and later.\n#if QT_VERSION < 0x050b00\n#error \"Qt v5.11.0 or later is required\"\n#endif\n\n\n// Define QSCINTILLA_MAKE_DLL to create a QScintilla shared library, or\n// define QSCINTILLA_DLL to link against a QScintilla shared library, or define\n// neither to either build or link against a static QScintilla library.\n#if defined(QSCINTILLA_DLL)\n#define QSCINTILLA_EXPORT       Q_DECL_IMPORT\n#elif defined(QSCINTILLA_MAKE_DLL)\n#define QSCINTILLA_EXPORT       Q_DECL_EXPORT\n#else\n#define QSCINTILLA_EXPORT\n#endif\n\n\n#if !defined(QT_BEGIN_NAMESPACE)\n#define QT_BEGIN_NAMESPACE\n#define QT_END_NAMESPACE\n#endif\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexer.h",
    "content": "// This defines the interface to the QsciLexer class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXER_H\n#define QSCILEXER_H\n\n#include <QColor>\n#include <QFont>\n#include <QMap>\n#include <QObject>\n#include <QString>\n\n#include <Qsci/qsciglobal.h>\n\n\nQT_BEGIN_NAMESPACE\nclass QSettings;\nQT_END_NAMESPACE\n\nclass QsciAbstractAPIs;\nclass QsciScintilla;\n\n\n//! \\brief The QsciLexer class is an abstract class used as a base for language\n//! lexers.\n//!\n//! A lexer scans the text breaking it up into separate language objects, e.g.\n//! keywords, strings, operators.  The lexer then uses a different style to\n//! draw each object.  A style is identified by a style number and has a number\n//! of attributes, including colour and font.  A specific language lexer will\n//! implement appropriate default styles which can be overriden by an\n//! application by further sub-classing the specific language lexer.\n//!\n//! A lexer may provide one or more sets of words to be recognised as keywords.\n//! Most lexers only provide one set, but some may support languages embedded\n//! in other languages and provide several sets.\n//!\n//! QsciLexer provides convenience methods for saving and restoring user\n//! preferences for fonts and colours.\n//!\n//! If you want to write a lexer for a new language then you can add it to the\n//! underlying Scintilla code and implement a corresponding QsciLexer sub-class\n//! to manage the different styles used.  Alternatively you can implement a\n//! sub-class of QsciLexerCustom.\nclass QSCINTILLA_EXPORT QsciLexer : public QObject\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciLexer with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexer(QObject *parent = 0);\n\n    //! Destroy the QSciLexer.\n    virtual ~QsciLexer();\n\n    //! Returns the name of the language.  It must be re-implemented by a\n    //! sub-class.\n    virtual const char *language() const = 0;\n\n    //! Returns the name of the lexer.  If 0 is returned then the lexer's\n    //! numeric identifier is used.  The default implementation returns 0.\n    //!\n    //! \\sa lexerId()\n    virtual const char *lexer() const;\n\n    //! Returns the identifier (i.e. a QsciScintillaBase::SCLEX_* value) of the\n    //! lexer.  This is only used if lexer() returns 0.  The default\n    //! implementation returns QsciScintillaBase::SCLEX_CONTAINER.\n    //!\n    //! \\sa lexer()\n    virtual int lexerId() const;\n\n    //! Returns the current API set or 0 if there isn't one.\n    //!\n    //! \\sa setAPIs()\n    QsciAbstractAPIs *apis() const;\n\n    //! Returns the characters that can fill up auto-completion.\n    virtual const char *autoCompletionFillups() const;\n\n    //! Returns the list of character sequences that can separate\n    //! auto-completion words.  The first in the list is assumed to be the\n    //! sequence used to separate words in the lexer's API files.\n    virtual QStringList autoCompletionWordSeparators() const;\n\n    //! Returns the auto-indentation style.  The default is 0 if the\n    //! language is block structured, or QsciScintilla::AiMaintain if not.\n    //!\n    //! \\sa setAutoIndentStyle(), QsciScintilla::AiMaintain,\n    //! QsciScintilla::AiOpening, QsciScintilla::AiClosing\n    int autoIndentStyle();\n\n    //! Returns a space separated list of words or characters in a particular\n    //! style that define the end of a block for auto-indentation.  The style\n    //! is returned via \\a style.\n    virtual const char *blockEnd(int *style = 0) const;\n\n    //! Returns the number of lines prior to the current one when determining\n    //! the scope of a block when auto-indenting.\n    virtual int blockLookback() const;\n\n    //! Returns a space separated list of words or characters in a particular\n    //! style that define the start of a block for auto-indentation.  The style\n    //! is returned via \\a style.\n    virtual const char *blockStart(int *style = 0) const;\n\n    //! Returns a space separated list of keywords in a particular style that\n    //! define the start of a block for auto-indentation.  The style is\n    //! returned via \\a style.\n    virtual const char *blockStartKeyword(int *style = 0) const;\n\n    //! Returns the style used for braces for brace matching.\n    virtual int braceStyle() const;\n\n    //! Returns true if the language is case sensitive.  The default is true.\n    virtual bool caseSensitive() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //! The default colour is that returned by defaultColor().\n    //!\n    //! \\sa defaultColor(), paper()\n    virtual QColor color(int style) const;\n\n    //! Returns the end-of-line for style number \\a style.  The default is\n    //! false.\n    virtual bool eolFill(int style) const;\n\n    //! Returns the font for style number \\a style.  The default font is\n    //! that returned by defaultFont().\n    //!\n    //! \\sa defaultFont()\n    virtual QFont font(int style) const;\n\n    //! Returns the view used for indentation guides.\n    virtual int indentationGuideView() const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.  Keyword sets are numbered\n    //! from 1.  0 is returned if there is no such set.\n    virtual const char *keywords(int set) const;\n\n    //! Returns the number of the style used for whitespace.  The default\n    //! implementation returns 0 which is the convention adopted by most\n    //! lexers.\n    virtual int defaultStyle() const;\n\n    //! Returns the descriptive name for style number \\a style.  For a valid\n    //! style number for this language a non-empty QString must be returned.\n    //! If the style number is invalid then an empty QString must be returned.\n    //! This is intended to be used in user preference dialogs.\n    virtual QString description(int style) const = 0;\n\n    //! Returns the background colour of the text for style number\n    //! \\a style.\n    //!\n    //! \\sa defaultPaper(), color()\n    virtual QColor paper(int style) const;\n\n    //! Returns the default text colour.\n    //!\n    //! \\sa setDefaultColor()\n    QColor defaultColor() const;\n\n    //! Returns the default text colour for style number \\a style.\n    virtual QColor defaultColor(int style) const;\n\n    //! Returns the default end-of-line for style number \\a style.  The default\n    //! is false.\n    virtual bool defaultEolFill(int style) const;\n\n    //! Returns the default font.\n    //!\n    //! \\sa setDefaultFont()\n    QFont defaultFont() const;\n\n    //! Returns the default font for style number \\a style.\n    virtual QFont defaultFont(int style) const;\n\n    //! Returns the default paper colour.\n    //!\n    //! \\sa setDefaultPaper()\n    QColor defaultPaper() const;\n\n    //! Returns the default paper colour for style number \\a style.\n    virtual QColor defaultPaper(int style) const;\n\n    //! Returns the QsciScintilla instance that the lexer is currently attached\n    //! to or 0 if it is unattached.\n    QsciScintilla *editor() const {return attached_editor;}\n\n    //! The current set of APIs is set to \\a apis.  If \\a apis is 0 then any\n    //! existing APIs for this lexer are removed.\n    //!\n    //! \\sa apis()\n    void setAPIs(QsciAbstractAPIs *apis);\n\n    //! The default text colour is set to \\a c.\n    //!\n    //! \\sa defaultColor(), color()\n    void setDefaultColor(const QColor &c);\n\n    //! The default font is set to \\a f.\n    //!\n    //! \\sa defaultFont(), font()\n    void setDefaultFont(const QFont &f);\n\n    //! The default paper colour is set to \\a c.\n    //!\n    //! \\sa defaultPaper(), paper()\n    void setDefaultPaper(const QColor &c);\n\n    //! \\internal Set the QsciScintilla instance that the lexer is attached to.\n    virtual void setEditor(QsciScintilla *editor);\n\n    //! The colour, paper, font and end-of-line for each style number, and\n    //! all lexer specific properties are read from the settings \\a qs.\n    //! \\a prefix is prepended to the key of each entry.  true is returned\n    //! if there was no error.\n    //!\n    //! \\sa writeSettings(), QsciScintilla::setLexer()\n    bool readSettings(QSettings &qs,const char *prefix = \"/Scintilla\");\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    virtual void refreshProperties();\n\n    //! Returns the number of style bits needed by the lexer.  Normally this\n    //! should only be re-implemented by custom lexers.  This is deprecated and\n    //! no longer has any effect.\n    virtual int styleBitsNeeded() const;\n\n    //! Returns the string of characters that comprise a word.  The default is\n    //! 0 which implies the upper and lower case alphabetic characters and\n    //! underscore.\n    virtual const char *wordCharacters() const;\n\n    //! The colour, paper, font and end-of-line for each style number, and\n    //! all lexer specific properties are written to the settings \\a qs.\n    //! \\a prefix is prepended to the key of each entry.  true is returned\n    //! if there was no error.\n    //!\n    //! \\sa readSettings()\n    bool writeSettings(QSettings &qs,\n               const char *prefix = \"/Scintilla\") const;\n\npublic slots:\n    //! The auto-indentation style is set to \\a autoindentstyle.\n    //!\n    //! \\sa autoIndentStyle(), QsciScintilla::AiMaintain,\n    //! QsciScintilla::AiOpening, QsciScintilla::AiClosing\n    virtual void setAutoIndentStyle(int autoindentstyle);\n\n    //! The foreground colour for style number \\a style is set to \\a c.  If\n    //! \\a style is -1 then the colour is set for all styles.\n    virtual void setColor(const QColor &c,int style = -1);\n\n    //! The end-of-line fill for style number \\a style is set to\n    //! \\a eoffill.  If \\a style is -1 then the fill is set for all styles.\n    virtual void setEolFill(bool eoffill,int style = -1);\n\n    //! The font for style number \\a style is set to \\a f.  If \\a style is\n    //! -1 then the font is set for all styles.\n    virtual void setFont(const QFont &f,int style = -1);\n\n    //! The background colour for style number \\a style is set to \\a c.  If\n    //! \\a style is -1 then the colour is set for all styles.\n    virtual void setPaper(const QColor &c,int style = -1);\n\nsignals:\n    //! This signal is emitted when the foreground colour of style number\n    //! \\a style has changed.  The new colour is \\a c.\n    void colorChanged(const QColor &c,int style);\n\n    //! This signal is emitted when the end-of-file fill of style number\n    //! \\a style has changed.  The new fill is \\a eolfilled.\n    void eolFillChanged(bool eolfilled,int style);\n\n    //! This signal is emitted when the font of style number \\a style has\n    //! changed.  The new font is \\a f.\n    void fontChanged(const QFont &f,int style);\n\n    //! This signal is emitted when the background colour of style number\n    //! \\a style has changed.  The new colour is \\a c.\n    void paperChanged(const QColor &c,int style);\n\n    //! This signal is emitted when the value of the lexer property \\a prop\n    //! needs to be changed.  The new value is \\a val.\n    void propertyChanged(const char *prop, const char *val);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    virtual bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    virtual bool writeProperties(QSettings &qs,const QString &prefix) const;\n\n    //! \\internal Convert a QString to encoded bytes.\n    QByteArray textAsBytes(const QString &text) const;\n\n    //! \\internal Convert encoded bytes to a QString.\n    QString bytesAsText(const char *bytes, int size) const;\n\nprivate:\n    struct StyleData {\n        QFont font;\n        QColor color;\n        QColor paper;\n        bool eol_fill;\n    };\n\n    struct StyleDataMap {\n        bool style_data_set;\n        QMap<int, StyleData> style_data;\n    };\n\n    StyleDataMap *style_map;\n\n    int autoIndStyle;\n    QFont defFont;\n    QColor defColor;\n    QColor defPaper;\n    QsciAbstractAPIs *apiSet;\n    QsciScintilla *attached_editor;\n\n    void setStyleDefaults() const;\n    StyleData &styleData(int style) const;\n\n    QsciLexer(const QsciLexer &);\n    QsciLexer &operator=(const QsciLexer &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexeravs.h",
    "content": "// This defines the interface to the QsciLexerAVS class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERAVS_H\n#define QSCILEXERAVS_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerAVS class encapsulates the Scintilla AVS lexer.\nclass QSCINTILLA_EXPORT QsciLexerAVS : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! AVS lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A block comment.\n        BlockComment = 1,\n\n        //! A nested block comment.\n        NestedBlockComment = 2,\n\n        //! A line comment.\n        LineComment = 3,\n\n        //! A number.\n        Number = 4,\n\n        //! An operator.\n        Operator = 5,\n\n        //! An identifier\n        Identifier = 6,\n\n        //! A string.\n        String = 7,\n\n        //! A triple quoted string.\n        TripleString = 8,\n\n        //! A keyword (as defined by keyword set number 1)..\n        Keyword = 9,\n\n        //! A filter (as defined by keyword set number 2).\n        Filter = 10,\n\n        //! A plugin (as defined by keyword set number 3).\n        Plugin = 11,\n\n        //! A function (as defined by keyword set number 4).\n        Function = 12,\n\n        //! A clip property (as defined by keyword set number 5).\n        ClipProperty = 13,\n\n        //! A keyword defined in keyword set number 6.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet6 = 14\n    };\n\n    //! Construct a QsciLexerAVS with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerAVS(QObject *parent = 0);\n\n    //! Destroys the QsciLexerAVS instance.\n    virtual ~QsciLexerAVS();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the propertyChanged()\n    //! signal as required.\n    void refreshProperties();\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const;\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\npublic slots:\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n\n    bool fold_comments;\n    bool fold_compact;\n\n    QsciLexerAVS(const QsciLexerAVS &);\n    QsciLexerAVS &operator=(const QsciLexerAVS &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerbash.h",
    "content": "// This defines the interface to the QsciLexerBash class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERBASH_H\n#define QSCILEXERBASH_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerBash class encapsulates the Scintilla Bash lexer.\nclass QSCINTILLA_EXPORT QsciLexerBash : public QsciLexer\n{\n\tQ_OBJECT\n\npublic:\n\t//! This enum defines the meanings of the different styles used by the\n\t//! Bash lexer.\n\tenum {\n\t\t//! The default.\n\t\tDefault = 0,\n\n\t\t//! An error.\n\t\tError = 1,\n\n\t\t//! A comment.\n\t\tComment = 2,\n\n\t\t//! A number.\n\t\tNumber = 3,\n\n\t\t//! A keyword.\n\t\tKeyword = 4,\n\n\t\t//! A double-quoted string.\n\t\tDoubleQuotedString = 5,\n\n\t\t//! A single-quoted string.\n\t\tSingleQuotedString = 6,\n\n\t\t//! An operator.\n\t\tOperator = 7,\n\n\t\t//! An identifier\n\t\tIdentifier = 8,\n\n\t\t//! A scalar.\n\t\tScalar = 9,\n\n\t\t//! Parameter expansion.\n\t\tParameterExpansion = 10,\n\n\t\t//! Backticks.\n\t\tBackticks = 11,\n\n\t\t//! A here document delimiter.\n\t\tHereDocumentDelimiter = 12,\n\n\t\t//! A single quoted here document.\n\t\tSingleQuotedHereDocument = 13\n\t};\n\n\t//! Construct a QsciLexerBash with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n\tQsciLexerBash(QObject *parent = 0);\n\n\t//! Destroys the QsciLexerBash instance.\n\tvirtual ~QsciLexerBash();\n\n\t//! Returns the name of the language.\n\tconst char *language() const;\n\n\t//! Returns the name of the lexer.  Some lexers support a number of\n\t//! languages.\n\tconst char *lexer() const;\n\n\t//! \\internal Returns the style used for braces for brace matching.\n\tint braceStyle() const;\n\n\t//! Returns the string of characters that comprise a word.\n\tconst char *wordCharacters() const;\n\n\t//! Returns the foreground colour of the text for style number \\a style.\n\t//!\n\t//! \\sa defaultPaper()\n\tQColor defaultColor(int style) const;\n\n\t//! Returns the end-of-line fill for style number \\a style.\n\tbool defaultEolFill(int style) const;\n\n\t//! Returns the font for style number \\a style.\n\tQFont defaultFont(int style) const;\n\n\t//! Returns the background colour of the text for style number \\a style.\n\t//!\n\t//! \\sa defaultColor()\n\tQColor defaultPaper(int style) const;\n\n\t//! Returns the set of keywords for the keyword set \\a set recognised\n\t//! by the lexer as a space separated string.\n\tconst char *keywords(int set) const;\n\n\t//! Returns the descriptive name for style number \\a style.  If the\n\t//! style is invalid for this language then an empty QString is returned.\n\t//! This is intended to be used in user preference dialogs.\n\tQString description(int style) const;\n\n\t//! Causes all properties to be refreshed by emitting the\n\t//! propertyChanged() signal as required.\n\tvoid refreshProperties();\n\n\t//! Returns true if multi-line comment blocks can be folded.\n\t//!\n\t//! \\sa setFoldComments()\n\tbool foldComments() const;\n\n\t//! Returns true if trailing blank lines are included in a fold block.\n\t//!\n\t//! \\sa setFoldCompact()\n\tbool foldCompact() const;\n\npublic slots:\n\t//! If \\a fold is true then multi-line comment blocks can be folded.\n\t//! The default is false.\n\t//!\n\t//! \\sa foldComments()\n\tvirtual void setFoldComments(bool fold);\n\n\t//! If \\a fold is true then trailing blank lines are included in a fold\n\t//! block. The default is true.\n\t//!\n\t//! \\sa foldCompact()\n\tvirtual void setFoldCompact(bool fold);\n\nprotected:\n\t//! The lexer's properties are read from the settings \\a qs.  \\a prefix\n\t//! (which has a trailing '/') should be used as a prefix to the key of\n\t//! each setting.  true is returned if there is no error.\n\t//!\n\tbool readProperties(QSettings &qs,const QString &prefix);\n\n\t//! The lexer's properties are written to the settings \\a qs.\n\t//! \\a prefix (which has a trailing '/') should be used as a prefix to\n\t//! the key of each setting.  true is returned if there is no error.\n\t//!\n\tbool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n\tvoid setCommentProp();\n\tvoid setCompactProp();\n\n\tbool fold_comments;\n\tbool fold_compact;\n\n\tQsciLexerBash(const QsciLexerBash &);\n\tQsciLexerBash &operator=(const QsciLexerBash &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerbatch.h",
    "content": "// This defines the interface to the QsciLexerBatch class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERBATCH_H\n#define QSCILEXERBATCH_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerBatch class encapsulates the Scintilla batch file\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerBatch : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! batch file lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A keyword.\n        Keyword = 2,\n\n        //! A label.\n        Label = 3,\n\n        //! An hide command character.\n        HideCommandChar = 4,\n\n        //! An external command .\n        ExternalCommand = 5,\n\n        //! A variable.\n        Variable = 6,\n        \n        //! An operator\n        Operator = 7\n    };\n\n    //! Construct a QsciLexerBatch with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerBatch(QObject *parent = 0);\n\n    //! Destroys the QsciLexerBatch instance.\n    virtual ~QsciLexerBatch();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! \\internal Returns true if the language is case sensitive.\n    bool caseSensitive() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    QsciLexerBatch(const QsciLexerBatch &);\n    QsciLexerBatch &operator=(const QsciLexerBatch &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexercmake.h",
    "content": "// This defines the interface to the QsciLexerCMake class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERCMAKE_H\n#define QSCILEXERCMAKE_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerCMake class encapsulates the Scintilla CMake lexer.\nclass QSCINTILLA_EXPORT QsciLexerCMake : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! CMake lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A string.\n        String = 2,\n\n        //! A left quoted string.\n        StringLeftQuote = 3,\n\n        //! A right quoted string.\n        StringRightQuote = 4,\n\n        //! A function.  (Defined by keyword set number 1.)\n        Function = 5,\n\n        //! A variable. (Defined by keyword set number 2.)\n        Variable = 6,\n\n        //! A label.\n        Label = 7,\n\n        //! A keyword defined in keyword set number 3.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet3 = 8,\n\n        //! A WHILE block.\n        BlockWhile = 9,\n\n        //! A FOREACH block.\n        BlockForeach = 10,\n\n        //! An IF block.\n        BlockIf = 11,\n\n        //! A MACRO block.\n        BlockMacro = 12,\n\n        //! A variable within a string.\n        StringVariable = 13,\n\n        //! A number.\n        Number = 14\n    };\n\n    //! Construct a QsciLexerCMake with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerCMake(QObject *parent = 0);\n\n    //! Destroys the QsciLexerCMake instance.\n    virtual ~QsciLexerCMake();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the propertyChanged()\n    //! signal as required.\n    void refreshProperties();\n\n    //! Returns true if ELSE blocks can be folded.\n    //!\n    //! \\sa setFoldAtElse()\n    bool foldAtElse() const;\n\npublic slots:\n    //! If \\a fold is true then ELSE blocks can be folded.  The default is\n    //! false.\n    //!\n    //! \\sa foldAtElse()\n    virtual void setFoldAtElse(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setAtElseProp();\n\n    bool fold_atelse;\n\n    QsciLexerCMake(const QsciLexerCMake &);\n    QsciLexerCMake &operator=(const QsciLexerCMake &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexercoffeescript.h",
    "content": "// This defines the interface to the QsciLexerCoffeeScript class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERCOFFEESCRIPT_H\n#define QSCILEXERCOFFEESCRIPT_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerCoffeeScript class encapsulates the Scintilla\n//! CoffeeScript lexer.\nclass QSCINTILLA_EXPORT QsciLexerCoffeeScript : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! C++ lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A C-style comment.\n        Comment = 1,\n\n        //! A C++-style comment line.\n        CommentLine = 2,\n\n        //! A JavaDoc/Doxygen C-style comment.\n        CommentDoc = 3,\n\n        //! A number.\n        Number = 4,\n\n        //! A keyword.\n        Keyword = 5,\n\n        //! A double-quoted string.\n        DoubleQuotedString = 6,\n\n        //! A single-quoted string.\n        SingleQuotedString = 7,\n\n        //! An IDL UUID.\n        UUID = 8,\n\n        //! A pre-processor block.\n        PreProcessor = 9,\n\n        //! An operator.\n        Operator = 10,\n\n        //! An identifier\n        Identifier = 11,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 12,\n\n        //! A C# verbatim string.\n        VerbatimString = 13,\n\n        //! A regular expression.\n        Regex = 14,\n\n        //! A JavaDoc/Doxygen C++-style comment line.\n        CommentLineDoc = 15,\n\n        //! A keyword defined in keyword set number 2.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet2 = 16,\n\n        //! A JavaDoc/Doxygen keyword.\n        CommentDocKeyword = 17,\n\n        //! A JavaDoc/Doxygen keyword error defined in keyword set number 3.\n        //! The class must be sub-classed and re-implement keywords() to make\n        //! use of this style.\n        CommentDocKeywordError = 18,\n\n        //! A global class defined in keyword set number 4.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        GlobalClass = 19,\n\n        //! A block comment.\n        CommentBlock = 22,\n\n        //! A block regular expression.\n        BlockRegex = 23,\n\n        //! A block regular expression comment.\n        BlockRegexComment = 24,\n\n        //! An instance property.\n        InstanceProperty = 25,\n    };\n\n    //! Construct a QsciLexerCoffeeScript with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerCoffeeScript(QObject *parent = 0);\n\n    //! Destroys the QsciLexerCoffeeScript instance.\n    virtual ~QsciLexerCoffeeScript();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the character sequences that can separate\n    //! auto-completion words.\n    QStringList autoCompletionWordSeparators() const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the end of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockEnd(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStart(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of keywords in a\n    //! particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStartKeyword(int *style = 0) const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.  Set 1 is normally used for\n    //! primary keywords and identifiers.  Set 2 is normally used for secondary\n    //! keywords and identifiers.  Set 3 is normally used for documentation\n    //! comment keywords.  Set 4 is normally used for global classes and\n    //! typedefs.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if '$' characters are allowed in identifier names.\n    //!\n    //! \\sa setDollarsAllowed()\n    bool dollarsAllowed() const {return dollars;}\n\n    //! If \\a allowed is true then '$' characters are allowed in identifier\n    //! names.  The default is true.\n    //!\n    //! \\sa dollarsAllowed()\n    void setDollarsAllowed(bool allowed);\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const {return fold_comments;}\n\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    void setFoldComments(bool fold);\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;}\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    void setFoldCompact(bool fold);\n\n    //! Returns true if preprocessor lines (after the preprocessor\n    //! directive) are styled.\n    //!\n    //! \\sa setStylePreprocessor()\n    bool stylePreprocessor() const {return style_preproc;}\n\n    //! If \\a style is true then preprocessor lines (after the preprocessor\n    //! directive) are styled.  The default is false.\n    //!\n    //! \\sa stylePreprocessor()\n    void setStylePreprocessor(bool style);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    //! \\sa writeProperties()\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    //! \\sa readProperties()\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n    void setStylePreprocProp();\n    void setDollarsProp();\n\n    bool fold_comments;\n    bool fold_compact;\n    bool style_preproc;\n    bool dollars;\n\n    QsciLexerCoffeeScript(const QsciLexerCoffeeScript &);\n    QsciLexerCoffeeScript &operator=(const QsciLexerCoffeeScript &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexercpp.h",
    "content": "// This defines the interface to the QsciLexerCPP class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERCPP_H\n#define QSCILEXERCPP_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerCPP class encapsulates the Scintilla C++\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerCPP : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! C++ lexer.\n    enum {\n        //! The default.\n        Default = 0,\n        InactiveDefault = Default + 64,\n\n        //! A C comment.\n        Comment = 1,\n        InactiveComment = Comment + 64,\n\n        //! A C++ comment line.\n        CommentLine = 2,\n        InactiveCommentLine = CommentLine + 64,\n\n        //! A JavaDoc/Doxygen style C comment.\n        CommentDoc = 3,\n        InactiveCommentDoc = CommentDoc + 64,\n\n        //! A number.\n        Number = 4,\n        InactiveNumber = Number + 64,\n\n        //! A keyword.\n        Keyword = 5,\n        InactiveKeyword = Keyword + 64,\n\n        //! A double-quoted string.\n        DoubleQuotedString = 6,\n        InactiveDoubleQuotedString = DoubleQuotedString + 64,\n\n        //! A single-quoted string.\n        SingleQuotedString = 7,\n        InactiveSingleQuotedString = SingleQuotedString + 64,\n\n        //! An IDL UUID.\n        UUID = 8,\n        InactiveUUID = UUID + 64,\n\n        //! A pre-processor block.\n        PreProcessor = 9,\n        InactivePreProcessor = PreProcessor + 64,\n\n        //! An operator.\n        Operator = 10,\n        InactiveOperator = Operator + 64,\n\n        //! An identifier\n        Identifier = 11,\n        InactiveIdentifier = Identifier + 64,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 12,\n        InactiveUnclosedString = UnclosedString + 64,\n\n        //! A C# verbatim string.\n        VerbatimString = 13,\n        InactiveVerbatimString = VerbatimString + 64,\n\n        //! A JavaScript regular expression.\n        Regex = 14,\n        InactiveRegex = Regex + 64,\n\n        //! A JavaDoc/Doxygen style C++ comment line.\n        CommentLineDoc = 15,\n        InactiveCommentLineDoc = CommentLineDoc + 64,\n\n        //! A keyword defined in keyword set number 2.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet2 = 16,\n        InactiveKeywordSet2 = KeywordSet2 + 64,\n\n        //! A JavaDoc/Doxygen keyword.\n        CommentDocKeyword = 17,\n        InactiveCommentDocKeyword = CommentDocKeyword + 64,\n\n        //! A JavaDoc/Doxygen keyword error.\n        CommentDocKeywordError = 18,\n        InactiveCommentDocKeywordError = CommentDocKeywordError + 64,\n\n        //! A global class or typedef defined in keyword set number 5.  The\n        //! class must be sub-classed and re-implement keywords() to make use\n        //! of this style.\n        GlobalClass = 19,\n        InactiveGlobalClass = GlobalClass + 64,\n\n        //! A C++ raw string.\n        RawString = 20,\n        InactiveRawString = RawString + 64,\n\n        //! A Vala triple-quoted verbatim string.\n        TripleQuotedVerbatimString = 21,\n        InactiveTripleQuotedVerbatimString = TripleQuotedVerbatimString + 64,\n\n        //! A Pike hash-quoted string.\n        HashQuotedString = 22,\n        InactiveHashQuotedString = HashQuotedString + 64,\n\n        //! A pre-processor stream comment.\n        PreProcessorComment = 23,\n        InactivePreProcessorComment = PreProcessorComment + 64,\n\n        //! A JavaDoc/Doxygen style pre-processor comment.\n        PreProcessorCommentLineDoc = 24,\n        InactivePreProcessorCommentLineDoc = PreProcessorCommentLineDoc + 64,\n\n        //! A user-defined literal.\n        UserLiteral = 25,\n        InactiveUserLiteral = UserLiteral + 64,\n\n        //! A task marker.\n        TaskMarker = 26,\n        InactiveTaskMarker = TaskMarker + 64,\n\n        //! An escape sequence.\n        EscapeSequence = 27,\n        InactiveEscapeSequence = EscapeSequence + 64,\n    };\n\n    //! Construct a QsciLexerCPP with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.  \\a caseInsensitiveKeywords is true if the\n    //! lexer ignores the case of keywords.\n    QsciLexerCPP(QObject *parent = 0, bool caseInsensitiveKeywords = false);\n\n    //! Destroys the QsciLexerCPP instance.\n    virtual ~QsciLexerCPP();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the character sequences that can separate\n    //! auto-completion words.\n    QStringList autoCompletionWordSeparators() const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the end of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockEnd(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStart(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of keywords in a\n    //! particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStartKeyword(int *style = 0) const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.  Set 1 is normally used for\n    //! primary keywords and identifiers.  Set 2 is normally used for secondary\n    //! keywords and identifiers.  Set 3 is normally used for documentation\n    //! comment keywords.  Set 4 is normally used for global classes and\n    //! typedefs.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if \"} else {\" lines can be folded.\n    //!\n    //! \\sa setFoldAtElse()\n    bool foldAtElse() const {return fold_atelse;}\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const {return fold_comments;}\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;}\n\n    //! Returns true if preprocessor blocks can be folded.\n    //!\n    //! \\sa setFoldPreprocessor()\n    bool foldPreprocessor() const {return fold_preproc;}\n\n    //! Returns true if preprocessor lines (after the preprocessor\n    //! directive) are styled.\n    //!\n    //! \\sa setStylePreprocessor()\n    bool stylePreprocessor() const {return style_preproc;}\n\n    //! If \\a allowed is true then '$' characters are allowed in identifier\n    //! names.  The default is true.\n    //!\n    //! \\sa dollarsAllowed()\n    void setDollarsAllowed(bool allowed);\n\n    //! Returns true if '$' characters are allowed in identifier names.\n    //!\n    //! \\sa setDollarsAllowed()\n    bool dollarsAllowed() const {return dollars;}\n\n    //! If \\a enabled is true then triple quoted strings are highlighted.  The\n    //! default is false.\n    //!\n    //! \\sa highlightTripleQuotedStrings()\n    void setHighlightTripleQuotedStrings(bool enabled);\n\n    //! Returns true if triple quoted strings should be highlighted.\n    //!\n    //! \\sa setHighlightTripleQuotedStrings()\n    bool highlightTripleQuotedStrings() const {return highlight_triple;}\n\n    //! If \\a enabled is true then hash quoted strings are highlighted.  The\n    //! default is false.\n    //!\n    //! \\sa highlightHashQuotedStrings()\n    void setHighlightHashQuotedStrings(bool enabled);\n\n    //! Returns true if hash quoted strings should be highlighted.\n    //!\n    //! \\sa setHighlightHashQuotedStrings()\n    bool highlightHashQuotedStrings() const {return highlight_hash;}\n\n    //! If \\a enabled is true then back-quoted raw strings are highlighted.\n    //! The default is false.\n    //!\n    //! \\sa highlightBackQuotedStrings()\n    void setHighlightBackQuotedStrings(bool enabled);\n\n    //! Returns true if back-quoted raw strings should be highlighted.\n    //!\n    //! \\sa setHighlightBackQuotedStrings()\n    bool highlightBackQuotedStrings() const {return highlight_back;}\n\n    //! If \\a enabled is true then escape sequences in strings are highlighted.\n    //! The default is false.\n    //!\n    //! \\sa highlightEscapeSequences()\n    void setHighlightEscapeSequences(bool enabled);\n\n    //! Returns true if escape sequences in strings should be highlighted.\n    //!\n    //! \\sa setHighlightEscapeSequences()\n    bool highlightEscapeSequences() const {return highlight_escape;}\n\n    //! If \\a allowed is true then escape sequences are allowed in verbatim\n    //! strings.  The default is false.\n    //!\n    //! \\sa verbatimStringEscapeSequencesAllowed()\n    void setVerbatimStringEscapeSequencesAllowed(bool allowed);\n\n    //! Returns true if hash quoted strings should be highlighted.\n    //!\n    //! \\sa setVerbatimStringEscapeSequencesAllowed()\n    bool verbatimStringEscapeSequencesAllowed() const {return vs_escape;}\n\npublic slots:\n    //! If \\a fold is true then \"} else {\" lines can be folded.  The\n    //! default is false.\n    //!\n    //! \\sa foldAtElse()\n    virtual void setFoldAtElse(bool fold);\n\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\n    //! If \\a fold is true then preprocessor blocks can be folded.  The\n    //! default is true.\n    //!\n    //! \\sa foldPreprocessor()\n    virtual void setFoldPreprocessor(bool fold);\n\n    //! If \\a style is true then preprocessor lines (after the preprocessor\n    //! directive) are styled.  The default is false.\n    //!\n    //! \\sa stylePreprocessor()\n    virtual void setStylePreprocessor(bool style);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    //! \\sa writeProperties()\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    //! \\sa readProperties()\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setAtElseProp();\n    void setCommentProp();\n    void setCompactProp();\n    void setPreprocProp();\n    void setStylePreprocProp();\n    void setDollarsProp();\n    void setHighlightTripleProp();\n    void setHighlightHashProp();\n    void setHighlightBackProp();\n    void setHighlightEscapeProp();\n    void setVerbatimStringEscapeProp();\n\n    bool fold_atelse;\n    bool fold_comments;\n    bool fold_compact;\n    bool fold_preproc;\n    bool style_preproc;\n    bool dollars;\n    bool highlight_triple;\n    bool highlight_hash;\n    bool highlight_back;\n    bool highlight_escape;\n    bool vs_escape;\n\n    bool nocase;\n\n    QsciLexerCPP(const QsciLexerCPP &);\n    QsciLexerCPP &operator=(const QsciLexerCPP &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexercsharp.h",
    "content": "// This defines the interface to the QsciLexerCSharp class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERCSHARP_H\n#define QSCILEXERCSHARP_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexercpp.h>\n\n\n//! \\brief The QsciLexerCSharp class encapsulates the Scintilla C#\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerCSharp : public QsciLexerCPP\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciLexerCSharp with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerCSharp(QObject *parent = 0);\n\n    //! Destroys the QsciLexerCSharp instance.\n    virtual ~QsciLexerCSharp();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    QsciLexerCSharp(const QsciLexerCSharp &);\n    QsciLexerCSharp &operator=(const QsciLexerCSharp &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexercss.h",
    "content": "// This defines the interface to the QsciLexerCSS class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERCSS_H\n#define QSCILEXERCSS_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerCSS class encapsulates the Scintilla CSS lexer.\nclass QSCINTILLA_EXPORT QsciLexerCSS : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! CSS lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A tag.\n        Tag = 1,\n\n        //! A class selector.\n        ClassSelector = 2,\n\n        //! A pseudo class.  The list of pseudo classes is defined by keyword\n        //! set 2.\n        PseudoClass = 3,\n\n        //! An unknown pseudo class.\n        UnknownPseudoClass = 4,\n\n        //! An operator.\n        Operator = 5,\n\n        //! A CSS1 property.  The list of CSS1 properties is defined by keyword\n        //! set 1.\n        CSS1Property = 6,\n\n        //! An unknown property.\n        UnknownProperty = 7,\n\n        //! A value.\n        Value = 8,\n\n        //! A comment.\n        Comment = 9,\n\n        //! An ID selector.\n        IDSelector = 10,\n\n        //! An important value.\n        Important = 11,\n\n        //! An @-rule.\n        AtRule = 12,\n\n        //! A double-quoted string.\n        DoubleQuotedString = 13,\n\n        //! A single-quoted string.\n        SingleQuotedString = 14,\n\n        //! A CSS2 property.  The list of CSS2 properties is defined by keyword\n        //! set 3.\n        CSS2Property = 15,\n\n        //! An attribute.\n        Attribute = 16,\n\n        //! A CSS3 property.  The list of CSS3 properties is defined by keyword\n        //! set 4.\n        CSS3Property = 17,\n\n        //! A pseudo element.  The list of pseudo elements is defined by\n        //! keyword set 5.\n        PseudoElement = 18,\n\n        //! An extended (browser specific) CSS property.  The list of extended\n        //! CSS properties is defined by keyword set 6.\n        ExtendedCSSProperty = 19,\n\n        //! An extended (browser specific) pseudo class.  The list of extended\n        //! pseudo classes is defined by keyword set 7.\n        ExtendedPseudoClass = 20,\n\n        //! An extended (browser specific) pseudo element.  The list of\n        //! extended pseudo elements is defined by keyword set 8.\n        ExtendedPseudoElement = 21,\n\n        //! A media rule.\n        MediaRule = 22,\n\n        //! A variable.\n        Variable = 23,\n    };\n\n    //! Construct a QsciLexerCSS with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerCSS(QObject *parent = 0);\n\n    //! Destroys the QsciLexerCSS instance.\n    virtual ~QsciLexerCSS();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the end of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockEnd(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStart(int *style = 0) const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    QColor defaultColor(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const;\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\n    //! If \\a enabled is true then support for HSS is enabled.  The default is\n    //! false.\n    //!\n    //! \\sa HSSLanguage()\n    void setHSSLanguage(bool enabled);\n\n    //! Returns true if support for HSS is enabled.\n    //!\n    //! \\sa setHSSLanguage()\n    bool HSSLanguage() const {return hss_language;}\n\n    //! If \\a enabled is true then support for Less CSS is enabled.  The\n    //! default is false.\n    //!\n    //! \\sa LessLanguage()\n    void setLessLanguage(bool enabled);\n\n    //! Returns true if support for Less CSS is enabled.\n    //!\n    //! \\sa setLessLanguage()\n    bool LessLanguage() const {return less_language;}\n\n    //! If \\a enabled is true then support for Sassy CSS is enabled.  The\n    //! default is false.\n    //!\n    //! \\sa SCSSLanguage()\n    void setSCSSLanguage(bool enabled);\n\n    //! Returns true if support for Sassy CSS is enabled.\n    //!\n    //! \\sa setSCSSLanguage()\n    bool SCSSLanguage() const {return scss_language;}\n\npublic slots:\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n    void setHSSProp();\n    void setLessProp();\n    void setSCSSProp();\n\n    bool fold_comments;\n    bool fold_compact;\n    bool hss_language;\n    bool less_language;\n    bool scss_language;\n\n    QsciLexerCSS(const QsciLexerCSS &);\n    QsciLexerCSS &operator=(const QsciLexerCSS &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexercustom.h",
    "content": "// This defines the interface to the QsciLexerCustom class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERCUSTOM_H\n#define QSCILEXERCUSTOM_H\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\nclass QsciScintilla;\nclass QsciStyle;\n\n\n//! \\brief The QsciLexerCustom class is an abstract class used as a base for\n//! new language lexers.\n//!\n//! The advantage of implementing a new lexer this way (as opposed to adding\n//! the lexer to the underlying Scintilla code) is that it does not require the\n//! QScintilla library to be re-compiled.  It also makes it possible to\n//! integrate external lexers.\n//!\n//! All that is necessary to implement a new lexer is to define appropriate\n//! styles and to re-implement the styleText() method.\nclass QSCINTILLA_EXPORT QsciLexerCustom : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciLexerCustom with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerCustom(QObject *parent = 0);\n\n    //! Destroy the QSciLexerCustom.\n    virtual ~QsciLexerCustom();\n\n    //! The next \\a length characters starting from the current styling\n    //! position have their style set to style number \\a style.  The current\n    //! styling position is moved.  The styling position is initially set by\n    //! calling startStyling().\n    //!\n    //! \\sa startStyling(), styleText()\n    void setStyling(int length, int style);\n\n    //! The next \\a length characters starting from the current styling\n    //! position have their style set to style \\a style.  The current styling\n    //! position is moved.  The styling position is initially set by calling\n    //! startStyling().\n    //!\n    //! \\sa startStyling(), styleText()\n    void setStyling(int length, const QsciStyle &style);\n\n    //! The styling position is set to \\a start.  \\a styleBits is unused.\n    //!\n    //! \\sa setStyling(), styleBitsNeeded(), styleText()\n    void startStyling(int pos, int styleBits = 0);\n\n    //! This is called when the section of text beginning at position \\a start\n    //! and up to position \\a end needs to be styled.  \\a start will always be\n    //! at the start of a line.  The text is styled by calling startStyling()\n    //! followed by one or more calls to setStyling().  It must be\n    //! re-implemented by a sub-class.\n    //!\n    //! \\sa setStyling(), startStyling(), QsciScintilla::bytes(),\n    //! QsciScintilla::text()\n    virtual void styleText(int start, int end) = 0;\n\n    //! \\reimp\n    virtual void setEditor(QsciScintilla *editor);\n\n    //! \\reimp This re-implementation returns 5 as the number of style bits\n    //! needed.\n    virtual int styleBitsNeeded() const;\n\nprivate slots:\n    void handleStyleNeeded(int pos);\n\nprivate:\n    QsciLexerCustom(const QsciLexerCustom &);\n    QsciLexerCustom &operator=(const QsciLexerCustom &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerd.h",
    "content": "// This defines the interface to the QsciLexerD class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERD_H\n#define QSCILEXERD_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerD class encapsulates the Scintilla D lexer.\nclass QSCINTILLA_EXPORT QsciLexerD : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the D\n    //! lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A comment line.\n        CommentLine = 2,\n\n        //! A JavaDoc and Doxygen comment.\n        CommentDoc = 3,\n\n        //! A nested comment.\n        CommentNested = 4,\n\n        //! A number.\n        Number = 5,\n\n        //! A keyword.\n        Keyword = 6,\n\n        //! A secondary keyword.\n        KeywordSecondary = 7,\n\n        //! A doc keyword\n        KeywordDoc = 8,\n        \n        //! Typedefs and aliases\n        Typedefs = 9,\n        \n        //! A string.\n        String = 10,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 11,\n        \n        //! A character\n        Character = 12,\n\n        //! An operator.\n        Operator = 13,\n\n        //! An identifier\n        Identifier = 14,\n\n        //! A JavaDoc and Doxygen line.\n        CommentLineDoc = 15,\n\n        //! A JavaDoc and Doxygen  keyword.\n        CommentDocKeyword = 16,\n\n        //! A JavaDoc and Doxygen keyword error.\n        CommentDocKeywordError = 17,\n\n        //! A backquoted string.\n        BackquoteString = 18,\n\n        //! A raw, hexadecimal or delimited string.\n        RawString = 19,\n\n        //! A keyword defined in keyword set number 5.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet5 = 20,\n\n        //! A keyword defined in keyword set number 6.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet6 = 21,\n\n        //! A keyword defined in keyword set number 7.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet7 = 22,\n    };\n\n    //! Construct a QsciLexerD with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerD(QObject *parent = 0);\n\n    //! Destroys the QsciLexerD instance.\n    virtual ~QsciLexerD();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the character sequences that can separate\n    //! auto-completion words.\n    QStringList autoCompletionWordSeparators() const;\n\n    //! \\internal Returns a space separated list of words or characters in a\n    //! particular style that define the end of a block for auto-indentation.\n    //! The styles is returned via \\a style.\n    const char *blockEnd(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of words or characters in a\n    //! particular style that define the start of a block for auto-indentation.\n    //! The styles is returned via \\a style.\n    const char *blockStart(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of keywords in a particular\n    //! style that define the start of a block for auto-indentation.  The\n    //! styles is returned via \\a style.\n    const char *blockStartKeyword(int *style = 0) const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised by\n    //! the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the style\n    //! is invalid for this language then an empty QString is returned.  This\n    //! is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the propertyChanged()\n    //! signal as required.\n    void refreshProperties();\n\n    //! Returns true if \"} else {\" lines can be folded.\n    //!\n    //! \\sa setFoldAtElse()\n    bool foldAtElse() const;\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const;\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\npublic slots:\n    //! If \\a fold is true then \"} else {\" lines can be folded.  The default is\n    //! false.\n    //!\n    //! \\sa foldAtElse()\n    virtual void setFoldAtElse(bool fold);\n\n    //! If \\a fold is true then multi-line comment blocks can be folded.  The\n    //! default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    //! \\sa writeProperties()\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    //! \\sa readProperties()\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setAtElseProp();\n    void setCommentProp();\n    void setCompactProp();\n\n    bool fold_atelse;\n    bool fold_comments;\n    bool fold_compact;\n\n    QsciLexerD(const QsciLexerD &);\n    QsciLexerD &operator=(const QsciLexerD &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerdiff.h",
    "content": "// This defines the interface to the QsciLexerDiff class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERDIFF_H\n#define QSCILEXERDIFF_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerDiff class encapsulates the Scintilla Diff\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerDiff : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Diff lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A command.\n        Command = 2,\n\n        //! A header.\n        Header = 3,\n\n        //! A position.\n        Position = 4,\n\n        //! A line removed.\n        LineRemoved = 5,\n\n        //! A line added.\n        LineAdded = 6,\n\n        //! A line changed.\n        LineChanged = 7,\n\n        //! An adding patch added.\n        AddingPatchAdded = 8,\n\n        //! A removing patch added.\n        RemovingPatchAdded = 9,\n\n        //! An adding patch added.\n        AddingPatchRemoved = 10,\n\n        //! A removing patch added.\n        RemovingPatchRemoved = 11,\n    };\n\n    //! Construct a QsciLexerDiff with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerDiff(QObject *parent = 0);\n\n    //! Destroys the QsciLexerDiff instance.\n    virtual ~QsciLexerDiff();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    QColor defaultColor(int style) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    QsciLexerDiff(const QsciLexerDiff &);\n    QsciLexerDiff &operator=(const QsciLexerDiff &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexeredifact.h",
    "content": "// This defines the interface to the QsciLexerEDIFACT class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXEREDIFACT_H\n#define QSCILEXEREDIFACT_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerEDIFACT class encapsulates the Scintilla EDIFACT lexer.\nclass QSCINTILLA_EXPORT QsciLexerEDIFACT : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! EDIFACT lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A segment start.\n        SegmentStart = 1,\n\n        //! A segment end.\n        SegmentEnd = 2,\n\n        //! An element separator.\n        ElementSeparator = 3,\n\n        //! A composite separator.\n        CompositeSeparator = 4,\n\n        //! A release separator.\n        ReleaseSeparator = 5,\n\n        //! A UNA segment header.\n        UNASegmentHeader = 6,\n\n        //! A UNH segment header.\n        UNHSegmentHeader = 7,\n\n        //! A bad segment.\n        BadSegment = 8,\n    };\n\n    //! Construct a QsciLexerEDIFACT with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerEDIFACT(QObject *parent = 0);\n\n    //! Destroys the QsciLexerEDIFACT instance.\n    virtual ~QsciLexerEDIFACT();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    QsciLexerEDIFACT(const QsciLexerEDIFACT &);\n    QsciLexerEDIFACT &operator=(const QsciLexerEDIFACT &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerfortran.h",
    "content": "// This defines the interface to the QsciLexerFortran class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERFORTRAN_H\n#define QSCILEXERFORTRAN_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexerfortran77.h>\n\n\n//! \\brief The QsciLexerFortran class encapsulates the Scintilla Fortran lexer.\nclass QSCINTILLA_EXPORT QsciLexerFortran : public QsciLexerFortran77\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciLexerFortran with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerFortran(QObject *parent = 0);\n\n    //! Destroys the QsciLexerFortran instance.\n    virtual ~QsciLexerFortran();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\nprivate:\n    QsciLexerFortran(const QsciLexerFortran &);\n    QsciLexerFortran &operator=(const QsciLexerFortran &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerfortran77.h",
    "content": "// This defines the interface to the QsciLexerFortran77 class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERFORTRAN77_H\n#define QSCILEXERFORTRAN77_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerFortran77 class encapsulates the Scintilla Fortran77\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerFortran77 : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Fortran77 lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A number.\n        Number = 2,\n\n        //! A single-quoted string.\n        SingleQuotedString = 3,\n\n        //! A double-quoted string.\n        DoubleQuotedString = 4,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 5,\n\n        //! An operator.\n        Operator = 6,\n\n        //! An identifier\n        Identifier = 7,\n\n        //! A keyword.\n        Keyword = 8,\n\n        //! An intrinsic function.\n        IntrinsicFunction = 9,\n\n        //! An extended, non-standard or user defined function.\n        ExtendedFunction = 10,\n\n        //! A pre-processor block.\n        PreProcessor = 11,\n\n        //! An operator in .NAME. format.\n        DottedOperator = 12,\n\n        //! A label.\n        Label = 13,\n\n        //! A continuation.\n        Continuation = 14\n    };\n\n    //! Construct a QsciLexerFortran77 with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerFortran77(QObject *parent = 0);\n\n    //! Destroys the QsciLexerFortran77 instance.\n    virtual ~QsciLexerFortran77();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\npublic slots:\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    //! \\sa writeProperties()\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    //! \\sa readProperties()\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCompactProp();\n\n    bool fold_compact;\n\n    QsciLexerFortran77(const QsciLexerFortran77 &);\n    QsciLexerFortran77 &operator=(const QsciLexerFortran77 &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerhtml.h",
    "content": "// This defines the interface to the QsciLexerHTML class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERHTML_H\n#define QSCILEXERHTML_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerHTML class encapsulates the Scintilla HTML lexer.\nclass QSCINTILLA_EXPORT QsciLexerHTML : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! HTML lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A tag.\n        Tag = 1,\n\n        //! An unknown tag.\n        UnknownTag = 2,\n\n        //! An attribute.\n        Attribute = 3,\n\n        //! An unknown attribute.\n        UnknownAttribute = 4,\n\n        //! An HTML number.\n        HTMLNumber = 5,\n\n        //! An HTML double-quoted string.\n        HTMLDoubleQuotedString = 6,\n\n        //! An HTML single-quoted string.\n        HTMLSingleQuotedString = 7,\n\n        //! Other text within a tag.\n        OtherInTag = 8,\n\n        //! An HTML comment.\n        HTMLComment = 9,\n\n        //! An entity.\n        Entity = 10,\n\n        //! The end of an XML style tag.\n        XMLTagEnd = 11,\n\n        //! The start of an XML fragment.\n        XMLStart = 12,\n\n        //! The end of an XML fragment.\n        XMLEnd = 13,\n\n        //! A script tag.\n        Script = 14,\n\n        //! The start of an ASP fragment with @.\n        ASPAtStart = 15,\n\n        //! The start of an ASP fragment.\n        ASPStart = 16,\n\n        //! CDATA.\n        CDATA = 17,\n\n        //! The start of a PHP fragment.\n        PHPStart = 18,\n\n        //! An unquoted HTML value.\n        HTMLValue = 19,\n\n        //! An ASP X-Code comment.\n        ASPXCComment = 20,\n\n        //! The default for SGML.\n        SGMLDefault = 21,\n\n        //! An SGML command.\n        SGMLCommand = 22,\n\n        //! The first parameter of an SGML command.\n        SGMLParameter = 23,\n\n        //! An SGML double-quoted string.\n        SGMLDoubleQuotedString = 24,\n\n        //! An SGML single-quoted string.\n        SGMLSingleQuotedString = 25,\n\n        //! An SGML error.\n        SGMLError = 26,\n\n        //! An SGML special entity.\n        SGMLSpecial = 27,\n\n        //! An SGML entity.\n        SGMLEntity = 28,\n\n        //! An SGML comment.\n        SGMLComment = 29,\n\n        //! A comment with the first parameter of an SGML command.\n        SGMLParameterComment = 30,\n\n        //! The default for an SGML block.\n        SGMLBlockDefault = 31,\n\n        //! The start of a JavaScript fragment.\n        JavaScriptStart = 40,\n\n        //! The default for JavaScript.\n        JavaScriptDefault = 41,\n\n        //! A JavaScript comment.\n        JavaScriptComment = 42,\n\n        //! A JavaScript line comment.\n        JavaScriptCommentLine = 43,\n\n        //! A JavaDoc style JavaScript comment.\n        JavaScriptCommentDoc = 44,\n\n        //! A JavaScript number.\n        JavaScriptNumber = 45,\n\n        //! A JavaScript word.\n        JavaScriptWord = 46,\n\n        //! A JavaScript keyword.\n        JavaScriptKeyword = 47,\n\n        //! A JavaScript double-quoted string.\n        JavaScriptDoubleQuotedString = 48,\n\n        //! A JavaScript single-quoted string.\n        JavaScriptSingleQuotedString = 49,\n\n        //! A JavaScript symbol.\n        JavaScriptSymbol = 50,\n\n        //! The end of a JavaScript line where a string is not closed.\n        JavaScriptUnclosedString = 51,\n\n        //! A JavaScript regular expression.\n        JavaScriptRegex = 52,\n\n        //! The start of an ASP JavaScript fragment.\n        ASPJavaScriptStart = 55,\n\n        //! The default for ASP JavaScript.\n        ASPJavaScriptDefault = 56,\n\n        //! An ASP JavaScript comment.\n        ASPJavaScriptComment = 57,\n\n        //! An ASP JavaScript line comment.\n        ASPJavaScriptCommentLine = 58,\n\n        //! An ASP JavaDoc style JavaScript comment.\n        ASPJavaScriptCommentDoc = 59,\n\n        //! An ASP JavaScript number.\n        ASPJavaScriptNumber = 60,\n\n        //! An ASP JavaScript word.\n        ASPJavaScriptWord = 61,\n\n        //! An ASP JavaScript keyword.\n        ASPJavaScriptKeyword = 62,\n\n        //! An ASP JavaScript double-quoted string.\n        ASPJavaScriptDoubleQuotedString = 63,\n\n        //! An ASP JavaScript single-quoted string.\n        ASPJavaScriptSingleQuotedString = 64,\n\n        //! An ASP JavaScript symbol.\n        ASPJavaScriptSymbol = 65,\n\n        //! The end of an ASP JavaScript line where a string is not\n        //! closed.\n        ASPJavaScriptUnclosedString = 66,\n\n        //! An ASP JavaScript regular expression.\n        ASPJavaScriptRegex = 67,\n\n        //! The start of a VBScript fragment.\n        VBScriptStart = 70,\n\n        //! The default for VBScript.\n        VBScriptDefault = 71,\n\n        //! A VBScript comment.\n        VBScriptComment = 72,\n\n        //! A VBScript number.\n        VBScriptNumber = 73,\n\n        //! A VBScript keyword.\n        VBScriptKeyword = 74,\n\n        //! A VBScript string.\n        VBScriptString = 75,\n\n        //! A VBScript identifier.\n        VBScriptIdentifier = 76,\n\n        //! The end of a VBScript line where a string is not closed.\n        VBScriptUnclosedString = 77,\n\n        //! The start of an ASP VBScript fragment.\n        ASPVBScriptStart = 80,\n\n        //! The default for ASP VBScript.\n        ASPVBScriptDefault = 81,\n\n        //! An ASP VBScript comment.\n        ASPVBScriptComment = 82,\n\n        //! An ASP VBScript number.\n        ASPVBScriptNumber = 83,\n\n        //! An ASP VBScript keyword.\n        ASPVBScriptKeyword = 84,\n\n        //! An ASP VBScript string.\n        ASPVBScriptString = 85,\n\n        //! An ASP VBScript identifier.\n        ASPVBScriptIdentifier = 86,\n\n        //! The end of an ASP VBScript line where a string is not\n        //! closed.\n        ASPVBScriptUnclosedString = 87,\n\n        //! The start of a Python fragment.\n        PythonStart = 90,\n\n        //! The default for Python.\n        PythonDefault = 91,\n\n        //! A Python comment.\n        PythonComment = 92,\n\n        //! A Python number.\n        PythonNumber = 93,\n\n        //! A Python double-quoted string.\n        PythonDoubleQuotedString = 94,\n\n        //! A Python single-quoted string.\n        PythonSingleQuotedString = 95,\n\n        //! A Python keyword.\n        PythonKeyword = 96,\n\n        //! A Python triple single-quoted string.\n        PythonTripleSingleQuotedString = 97,\n\n        //! A Python triple double-quoted string.\n        PythonTripleDoubleQuotedString = 98,\n\n        //! The name of a Python class.\n        PythonClassName = 99,\n\n        //! The name of a Python function or method.\n        PythonFunctionMethodName = 100,\n\n        //! A Python operator.\n        PythonOperator = 101,\n\n        //! A Python identifier.\n        PythonIdentifier = 102,\n\n        //! The start of an ASP Python fragment.\n        ASPPythonStart = 105,\n\n        //! The default for ASP Python.\n        ASPPythonDefault = 106,\n\n        //! An ASP Python comment.\n        ASPPythonComment = 107,\n\n        //! An ASP Python number.\n        ASPPythonNumber = 108,\n\n        //! An ASP Python double-quoted string.\n        ASPPythonDoubleQuotedString = 109,\n\n        //! An ASP Python single-quoted string.\n        ASPPythonSingleQuotedString = 110,\n\n        //! An ASP Python keyword.\n        ASPPythonKeyword = 111,\n\n        //! An ASP Python triple single-quoted string.\n        ASPPythonTripleSingleQuotedString = 112,\n\n        //! An ASP Python triple double-quoted string.\n        ASPPythonTripleDoubleQuotedString = 113,\n\n        //! The name of an ASP Python class.\n        ASPPythonClassName = 114,\n\n        //! The name of an ASP Python function or method.\n        ASPPythonFunctionMethodName = 115,\n\n        //! An ASP Python operator.\n        ASPPythonOperator = 116,\n\n        //! An ASP Python identifier\n        ASPPythonIdentifier = 117,\n\n        //! The default for PHP.\n        PHPDefault = 118,\n\n        //! A PHP double-quoted string.\n        PHPDoubleQuotedString = 119,\n\n        //! A PHP single-quoted string.\n        PHPSingleQuotedString = 120,\n\n        //! A PHP keyword.\n        PHPKeyword = 121,\n\n        //! A PHP number.\n        PHPNumber = 122,\n\n        //! A PHP variable.\n        PHPVariable = 123,\n\n        //! A PHP comment.\n        PHPComment = 124,\n\n        //! A PHP line comment.\n        PHPCommentLine = 125,\n\n        //! A PHP double-quoted variable.\n        PHPDoubleQuotedVariable = 126,\n\n        //! A PHP operator.\n        PHPOperator = 127\n    };\n\n    //! Construct a QsciLexerHTML with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerHTML(QObject *parent = 0);\n\n    //! Destroys the QsciLexerHTML instance.\n    virtual ~QsciLexerHTML();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the auto-completion fillup characters.\n    const char *autoCompletionFillups() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if tags are case sensitive.\n    //!\n    //! \\sa setCaseSensitiveTags()\n    bool caseSensitiveTags() const {return case_sens_tags;}\n\n    //! If \\a enabled is true then Django templates are enabled.  The default\n    //! is false.\n    //!\n    //! \\sa djangoTemplates()\n    void setDjangoTemplates(bool enabled);\n\n    //! Returns true if support for Django templates is enabled.\n    //!\n    //! \\sa setDjangoTemplates()\n    bool djangoTemplates() const {return django_templates;}\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;}\n\n    //! Returns true if preprocessor blocks can be folded.\n    //!\n    //! \\sa setFoldPreprocessor()\n    bool foldPreprocessor() const {return fold_preproc;}\n\n    //! If \\a fold is true then script comments can be folded.  The default is\n    //! false.\n    //!\n    //! \\sa foldScriptComments()\n    void setFoldScriptComments(bool fold);\n\n    //! Returns true if script comments can be folded.\n    //!\n    //! \\sa setFoldScriptComments()\n    bool foldScriptComments() const {return fold_script_comments;}\n\n    //! If \\a fold is true then script heredocs can be folded.  The default is\n    //! false.\n    //!\n    //! \\sa foldScriptHeredocs()\n    void setFoldScriptHeredocs(bool fold);\n\n    //! Returns true if script heredocs can be folded.\n    //!\n    //! \\sa setFoldScriptHeredocs()\n    bool foldScriptHeredocs() const {return fold_script_heredocs;}\n\n    //! If \\a enabled is true then Mako templates are enabled.  The default is\n    //! false.\n    //!\n    //! \\sa makoTemplates()\n    void setMakoTemplates(bool enabled);\n\n    //! Returns true if support for Mako templates is enabled.\n    //!\n    //! \\sa setMakoTemplates()\n    bool makoTemplates() const {return mako_templates;}\n\npublic slots:\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\n    //! If \\a fold is true then preprocessor blocks can be folded.  The\n    //! default is false.\n    //!\n    //! \\sa foldPreprocessor()\n    virtual void setFoldPreprocessor(bool fold);\n\n    //! If \\a sens is true then tags are case sensitive.  The default is false.\n    //!\n    //! \\sa caseSensitiveTags()\n    virtual void setCaseSensitiveTags(bool sens);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCompactProp();\n    void setPreprocProp();\n    void setCaseSensTagsProp();\n    void setScriptCommentsProp();\n    void setScriptHeredocsProp();\n    void setDjangoProp();\n    void setMakoProp();\n\n    bool fold_compact;\n    bool fold_preproc;\n    bool case_sens_tags;\n    bool fold_script_comments;\n    bool fold_script_heredocs;\n    bool django_templates;\n    bool mako_templates;\n\n    QsciLexerHTML(const QsciLexerHTML &);\n    QsciLexerHTML &operator=(const QsciLexerHTML &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexeridl.h",
    "content": "// This defines the interface to the QsciLexerIDL class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERIDL_H\n#define QSCILEXERIDL_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexercpp.h>\n\n\n//! \\brief The QsciLexerIDL class encapsulates the Scintilla IDL\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerIDL : public QsciLexerCPP\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciLexerIDL with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerIDL(QObject *parent = 0);\n\n    //! Destroys the QsciLexerIDL instance.\n    virtual ~QsciLexerIDL();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    QColor defaultColor(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    QsciLexerIDL(const QsciLexerIDL &);\n    QsciLexerIDL &operator=(const QsciLexerIDL &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjava.h",
    "content": "// This defines the interface to the QsciLexerJava class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERJAVA_H\n#define QSCILEXERJAVA_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexercpp.h>\n\n\n//! \\brief The QsciLexerJava class encapsulates the Scintilla Java lexer.\nclass QSCINTILLA_EXPORT QsciLexerJava : public QsciLexerCPP\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciLexerJava with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerJava(QObject *parent = 0);\n\n    //! Destroys the QsciLexerJava instance.\n    virtual ~QsciLexerJava();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\nprivate:\n    QsciLexerJava(const QsciLexerJava &);\n    QsciLexerJava &operator=(const QsciLexerJava &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjavascript.h",
    "content": "// This defines the interface to the QsciLexerJavaScript class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERJSCRIPT_H\n#define QSCILEXERJSCRIPT_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexercpp.h>\n\n\n//! \\brief The QsciLexerJavaScript class encapsulates the Scintilla JavaScript\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerJavaScript : public QsciLexerCPP\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciLexerJavaScript with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerJavaScript(QObject *parent = 0);\n\n    //! Destroys the QsciLexerJavaScript instance.\n    virtual ~QsciLexerJavaScript();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    friend class QsciLexerHTML;\n\n    static const char *keywordClass;\n\n    QsciLexerJavaScript(const QsciLexerJavaScript &);\n    QsciLexerJavaScript &operator=(const QsciLexerJavaScript &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjson.h",
    "content": "// This defines the interface to the QsciLexerJSON class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERJSON_H\n#define QSCILEXERJSON_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerJSON class encapsulates the Scintilla JSON lexer.\nclass QSCINTILLA_EXPORT QsciLexerJSON : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! JSON lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A number.\n        Number = 1,\n\n        //! A string.\n        String = 2,\n\n        //! An unclosed string.\n        UnclosedString = 3,\n\n        //! A property.\n        Property = 4,\n\n        //! An escape sequence.\n        EscapeSequence = 5,\n\n        //! A line comment.\n        CommentLine = 6,\n\n        //! A block comment.\n        CommentBlock = 7,\n\n        //! An operator.\n        Operator = 8,\n\n        //! An Internationalised Resource Identifier (IRI).\n        IRI = 9,\n\n        //! A JSON-LD compact IRI.\n        IRICompact = 10,\n\n        //! A JSON keyword.\n        Keyword = 11,\n\n        //! A JSON-LD keyword.\n        KeywordLD = 12,\n\n        //! A parsing error.\n        Error = 13,\n    };\n\n    //! Construct a QsciLexerJSON with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerJSON(QObject *parent = 0);\n\n    //! Destroys the QsciLexerJSON instance.\n    virtual ~QsciLexerJSON();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! If \\a highlight is true then line and block comments will be\n    //! highlighted.  The default is true.\n    //!\n    //! \\sa hightlightComments()\n    void setHighlightComments(bool highlight);\n\n    //! Returns true if line and block comments are highlighted\n    //!\n    //! \\sa setHightlightComments()\n    bool highlightComments() const {return allow_comments;}\n\n    //! If \\a highlight is true then escape sequences in strings are\n    //! highlighted.  The default is true.\n    //!\n    //! \\sa highlightEscapeSequences()\n    void setHighlightEscapeSequences(bool highlight);\n\n    //! Returns true if escape sequences in strings are highlighted.\n    //!\n    //! \\sa setHighlightEscapeSequences()\n    bool highlightEscapeSequences() const {return escape_sequence;}\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    void setFoldCompact(bool fold);\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;}\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n\tvoid setAllowCommentsProp();\n\tvoid setEscapeSequenceProp();\n\tvoid setCompactProp();\n\n\tbool allow_comments;\n\tbool escape_sequence;\n\tbool fold_compact;\n\n    QsciLexerJSON(const QsciLexerJSON &);\n    QsciLexerJSON &operator=(const QsciLexerJSON &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerlua.h",
    "content": "// This defines the interface to the QsciLexerLua class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERLUA_H\n#define QSCILEXERLUA_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerLua class encapsulates the Scintilla Lua\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerLua : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Lua lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A block comment.\n        Comment = 1,\n\n        //! A line comment.\n        LineComment = 2,\n\n        //! A number.\n        Number = 4,\n\n        //! A keyword.\n        Keyword = 5,\n\n        //! A string.\n        String = 6,\n\n        //! A character.\n        Character = 7,\n\n        //! A literal string.\n        LiteralString = 8,\n\n        //! Preprocessor\n        Preprocessor = 9,\n\n        //! An operator.\n        Operator = 10,\n\n        //! An identifier\n        Identifier = 11,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 12,\n\n        //! Basic functions.\n        BasicFunctions = 13,\n\n        //! String, table and maths functions.\n        StringTableMathsFunctions = 14,\n\n        //! Coroutines, I/O and system facilities.\n        CoroutinesIOSystemFacilities = 15,\n\n        //! A keyword defined in keyword set number 5.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet5 = 16,\n\n        //! A keyword defined in keyword set number 6.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet6 = 17,\n\n        //! A keyword defined in keyword set number 7.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet7 = 18,\n\n        //! A keyword defined in keyword set number 8.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet8 = 19,\n\n        //! A label.\n        Label = 20\n    };\n\n    //! Construct a QsciLexerLua with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerLua(QObject *parent = 0);\n\n    //! Destroys the QsciLexerLua instance.\n    virtual ~QsciLexerLua();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the character sequences that can separate\n    //! auto-completion words.\n    QStringList autoCompletionWordSeparators() const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStart(int *style = 0) const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\npublic slots:\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCompactProp();\n\n    bool fold_compact;\n\n    QsciLexerLua(const QsciLexerLua &);\n    QsciLexerLua &operator=(const QsciLexerLua &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexermakefile.h",
    "content": "// This defines the interface to the QsciLexerMakefile class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERMAKEFILE_H\n#define QSCILEXERMAKEFILE_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerMakefile class encapsulates the Scintilla\n//! Makefile lexer.\nclass QSCINTILLA_EXPORT QsciLexerMakefile : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Makefile lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A pre-processor directive.\n        Preprocessor = 2,\n\n        //! A variable.\n        Variable = 3,\n\n        //! An operator.\n        Operator = 4,\n\n        //! A target.\n        Target = 5,\n\n        //! An error.\n        Error = 9\n    };\n\n    //! Construct a QsciLexerMakefile with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerMakefile(QObject *parent = 0);\n\n    //! Destroys the QsciLexerMakefile instance.\n    virtual ~QsciLexerMakefile();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    QsciLexerMakefile(const QsciLexerMakefile &);\n    QsciLexerMakefile &operator=(const QsciLexerMakefile &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexermarkdown.h",
    "content": "// This defines the interface to the QsciLexerMarkdown class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERMARKDOWN_H\n#define QSCILEXERMARKDOWN_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerMarkdown class encapsulates the Scintilla Markdown\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerMarkdown : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Markdown lexer.\n\n    // Note that some values are omitted (ie. LINE_BEGIN and PRECHAR) as these\n    // seem to be internal state information rather than indicating that text\n    // should be styled differently.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! Special (e.g. end-of-line codes if enabled).\n        Special = 1,\n\n        //! Strong emphasis using double asterisks.\n        StrongEmphasisAsterisks = 2,\n\n        //! Strong emphasis using double underscores.\n        StrongEmphasisUnderscores = 3,\n\n        //! Emphasis using single asterisks.\n        EmphasisAsterisks = 4,\n\n        //! Emphasis using single underscores.\n        EmphasisUnderscores = 5,\n\n        //! A level 1 header.\n        Header1 = 6,\n\n        //! A level 2 header.\n        Header2 = 7,\n\n        //! A level 3 header.\n        Header3 = 8,\n\n        //! A level 4 header.\n        Header4 = 9,\n\n        //! A level 5 header.\n        Header5 = 10,\n\n        //! A level 6 header.\n        Header6 = 11,\n\n        //! Pre-char (up to three indent spaces, e.g. for a sub-list).\n        Prechar = 12,\n\n        //! An unordered list item.\n        UnorderedListItem = 13,\n\n        //! An ordered list item.\n        OrderedListItem = 14,\n\n        //! A block quote.\n        BlockQuote = 15,\n\n        //! Strike out.\n        StrikeOut = 16,\n\n        //! A horizontal rule.\n        HorizontalRule = 17,\n\n        //! A link.\n        Link = 18,\n\n        //! Code between backticks.\n        CodeBackticks = 19,\n\n        //! Code between double backticks.\n        CodeDoubleBackticks = 20,\n\n        //! A code block.\n        CodeBlock = 21,\n    };\n\n    //! Construct a QsciLexerMarkdown with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerMarkdown(QObject *parent = 0);\n\n    //! Destroys the QsciLexerMarkdown instance.\n    virtual ~QsciLexerMarkdown();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    QsciLexerMarkdown(const QsciLexerMarkdown &);\n    QsciLexerMarkdown &operator=(const QsciLexerMarkdown &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexermatlab.h",
    "content": "// This defines the interface to the QsciLexerMatlab class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERMATLAB_H\n#define QSCILEXERMATLAB_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerMatlab class encapsulates the Scintilla Matlab file\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerMatlab : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Matlab file lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A command.\n        Command = 2,\n\n        //! A number.\n        Number = 3,\n\n        //! A keyword.\n        Keyword = 4,\n\n        //! A single quoted string.\n        SingleQuotedString = 5,\n\n        //! An operator\n        Operator = 6,\n\n        //! An identifier.\n        Identifier = 7,\n\n        //! A double quoted string.\n        DoubleQuotedString = 8\n    };\n\n    //! Construct a QsciLexerMatlab with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerMatlab(QObject *parent = 0);\n\n    //! Destroys the QsciLexerMatlab instance.\n    virtual ~QsciLexerMatlab();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    QsciLexerMatlab(const QsciLexerMatlab &);\n    QsciLexerMatlab &operator=(const QsciLexerMatlab &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexeroctave.h",
    "content": "// This defines the interface to the QsciLexerOctave class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXEROCTAVE_H\n#define QSCILEXEROCTAVE_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexermatlab.h>\n\n\n//! \\brief The QsciLexerOctave class encapsulates the Scintilla Octave file\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerOctave : public QsciLexerMatlab\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciLexerOctave with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerOctave(QObject *parent = 0);\n\n    //! Destroys the QsciLexerOctave instance.\n    virtual ~QsciLexerOctave();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\nprivate:\n    QsciLexerOctave(const QsciLexerOctave &);\n    QsciLexerOctave &operator=(const QsciLexerOctave &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpascal.h",
    "content": "// This defines the interface to the QsciLexerPascal class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERPASCAL_H\n#define QSCILEXERPASCAL_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerPascal class encapsulates the Scintilla Pascal lexer.\nclass QSCINTILLA_EXPORT QsciLexerPascal : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! C++ lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! An identifier\n        Identifier = 1,\n\n        //! A '{ ... }' style comment.\n        Comment = 2,\n\n        //! A '(* ... *)' style comment.\n        CommentParenthesis = 3,\n\n        //! A comment line.\n        CommentLine = 4,\n\n        //! A '{$ ... }' style pre-processor block.\n        PreProcessor = 5,\n\n        //! A '(*$ ... *)' style pre-processor block.\n        PreProcessorParenthesis = 6,\n\n        //! A number.\n        Number = 7,\n\n        //! A hexadecimal number.\n        HexNumber = 8,\n\n        //! A keyword.\n        Keyword = 9,\n\n        //! A single-quoted string.\n        SingleQuotedString = 10,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 11,\n\n        //! A character.\n        Character = 12,\n\n        //! An operator.\n        Operator = 13,\n\n        //! Inline Asm.\n        Asm = 14\n    };\n\n    //! Construct a QsciLexerPascal with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerPascal(QObject *parent = 0);\n\n    //! Destroys the QsciLexerPascal instance.\n    virtual ~QsciLexerPascal();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the character sequences that can separate\n    //! auto-completion words.\n    QStringList autoCompletionWordSeparators() const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the end of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockEnd(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStart(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of keywords in a\n    //! particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStartKeyword(int *style = 0) const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const;\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\n    //! Returns true if preprocessor blocks can be folded.\n    //!\n    //! \\sa setFoldPreprocessor()\n    bool foldPreprocessor() const;\n\n    //! If \\a enabled is true then some keywords will only be highlighted in an\n    //! appropriate context (similar to how the Delphi IDE works).  The default\n    //! is true.\n    //!\n    //! \\sa smartHighlighting()\n    void setSmartHighlighting(bool enabled);\n\n    //! Returns true if some keywords will only be highlighted in an\n    //! appropriate context (similar to how the Delphi IDE works).\n    //!\n    //! \\sa setSmartHighlighting()\n    bool smartHighlighting() const;\n\npublic slots:\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\n    //! If \\a fold is true then preprocessor blocks can be folded.  The\n    //! default is true.\n    //!\n    //! \\sa foldPreprocessor()\n    virtual void setFoldPreprocessor(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    //! \\sa writeProperties()\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    //! \\sa readProperties()\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n    void setPreprocProp();\n    void setSmartHighlightProp();\n\n    bool fold_comments;\n    bool fold_compact;\n    bool fold_preproc;\n    bool smart_highlight;\n\n    QsciLexerPascal(const QsciLexerPascal &);\n    QsciLexerPascal &operator=(const QsciLexerPascal &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerperl.h",
    "content": "// This defines the interface to the QsciLexerPerl class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERPERL_H\n#define QSCILEXERPERL_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerPerl class encapsulates the Scintilla Perl\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerPerl : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Perl lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! An error.\n        Error = 1,\n\n        //! A comment.\n        Comment = 2,\n\n        //! A POD.\n        POD = 3,\n\n        //! A number.\n        Number = 4,\n\n        //! A keyword.\n        Keyword = 5,\n\n        //! A double-quoted string.\n        DoubleQuotedString = 6,\n\n        //! A single-quoted string.\n        SingleQuotedString = 7,\n\n        //! An operator.\n        Operator = 10,\n\n        //! An identifier\n        Identifier = 11,\n\n        //! A scalar.\n        Scalar = 12,\n\n        //! An array.\n        Array = 13,\n\n        //! A hash.\n        Hash = 14,\n\n        //! A symbol table.\n        SymbolTable = 15,\n\n        //! A regular expression.\n        Regex = 17,\n\n        //! A substitution.\n        Substitution = 18,\n\n        //! Backticks.\n        Backticks = 20,\n\n        //! A data section.\n        DataSection = 21,\n\n        //! A here document delimiter.\n        HereDocumentDelimiter = 22,\n\n        //! A single quoted here document.\n        SingleQuotedHereDocument = 23,\n\n        //! A double quoted here document.\n        DoubleQuotedHereDocument = 24,\n\n        //! A backtick here document.\n        BacktickHereDocument = 25,\n\n        //! A quoted string (q).\n        QuotedStringQ = 26,\n\n        //! A quoted string (qq).\n        QuotedStringQQ = 27,\n\n        //! A quoted string (qx).\n        QuotedStringQX = 28,\n\n        //! A quoted string (qr).\n        QuotedStringQR = 29,\n\n        //! A quoted string (qw).\n        QuotedStringQW = 30,\n\n        //! A verbatim POD.\n        PODVerbatim = 31,\n\n        //! A Subroutine prototype.\n        SubroutinePrototype = 40,\n\n        //! A format identifier.\n        FormatIdentifier = 41,\n\n        //! A format body.\n        FormatBody = 42,\n\n        //! A double-quoted string (interpolated variable).\n        DoubleQuotedStringVar = 43,\n\n        //! A translation.\n        Translation = 44,\n\n        //! A regular expression (interpolated variable).\n        RegexVar = 54,\n\n        //! A substitution (interpolated variable).\n        SubstitutionVar = 55,\n\n        //! Backticks (interpolated variable).\n        BackticksVar = 57,\n\n        //! A double quoted here document (interpolated variable).\n        DoubleQuotedHereDocumentVar = 61,\n\n        //! A backtick here document (interpolated variable).\n        BacktickHereDocumentVar = 62,\n\n        //! A quoted string (qq, interpolated variable).\n        QuotedStringQQVar = 64,\n\n        //! A quoted string (qx, interpolated variable).\n        QuotedStringQXVar = 65,\n\n        //! A quoted string (qr, interpolated variable).\n        QuotedStringQRVar = 66\n    };\n\n    //! Construct a QsciLexerPerl with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerPerl(QObject *parent = 0);\n\n    //! Destroys the QsciLexerPerl instance.\n    virtual ~QsciLexerPerl();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the character sequences that can separate\n    //! auto-completion words.\n    QStringList autoCompletionWordSeparators() const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the end of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockEnd(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStart(int *style = 0) const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number\n    //! \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! If \\a fold is true then \"} else {\" lines can be folded.  The default is\n    //! false.\n    //!\n    //! \\sa foldAtElse()\n    void setFoldAtElse(bool fold);\n\n    //! Returns true if \"} else {\" lines can be folded.\n    //!\n    //! \\sa setFoldAtElse()\n    bool foldAtElse() const {return fold_atelse;}\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const;\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\n    //! If \\a fold is true then packages can be folded.  The default is true.\n    //!\n    //! \\sa foldPackages()\n    void setFoldPackages(bool fold);\n\n    //! Returns true if packages can be folded.\n    //!\n    //! \\sa setFoldPackages()\n    bool foldPackages() const;\n\n    //! If \\a fold is true then POD blocks can be folded.  The default is true.\n    //!\n    //! \\sa foldPODBlocks()\n    void setFoldPODBlocks(bool fold);\n\n    //! Returns true if POD blocks can be folded.\n    //!\n    //! \\sa setFoldPODBlocks()\n    bool foldPODBlocks() const;\n\npublic slots:\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setAtElseProp();\n    void setCommentProp();\n    void setCompactProp();\n    void setPackagesProp();\n    void setPODBlocksProp();\n\n    bool fold_atelse;\n    bool fold_comments;\n    bool fold_compact;\n    bool fold_packages;\n    bool fold_pod_blocks;\n\n    QsciLexerPerl(const QsciLexerPerl &);\n    QsciLexerPerl &operator=(const QsciLexerPerl &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpo.h",
    "content": "// This defines the interface to the QsciLexerPO class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERPO_H\n#define QSCILEXERPO_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerPO class encapsulates the Scintilla PO lexer.\nclass QSCINTILLA_EXPORT QsciLexerPO : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! PO lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A message identifier.\n        MessageId = 2,\n\n        //! The text of a message identifier.\n        MessageIdText = 3,\n\n        //! A message string.\n        MessageString = 4,\n\n        //! The text of a message string.\n        MessageStringText = 5,\n\n        //! A message context.\n        MessageContext = 6,\n\n        //! The text of a message context.\n        MessageContextText = 7,\n\n        //! The \"fuzzy\" flag.\n        Fuzzy = 8,\n\n        //! A programmer comment.\n        ProgrammerComment = 9,\n\n        //! A reference.\n        Reference = 10,\n\n        //! A flag.\n        Flags = 11,\n\n        //! A message identifier text end-of-line.\n        MessageIdTextEOL = 12,\n\n        //! A message string text end-of-line.\n        MessageStringTextEOL = 13,\n\n        //! A message context text end-of-line.\n        MessageContextTextEOL = 14\n    };\n\n    //! Construct a QsciLexerPO with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerPO(QObject *parent = 0);\n\n    //! Destroys the QsciLexerPO instance.\n    virtual ~QsciLexerPO();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the propertyChanged()\n    //! signal as required.\n    void refreshProperties();\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const;\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\npublic slots:\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n\n    bool fold_comments;\n    bool fold_compact;\n\n    QsciLexerPO(const QsciLexerPO &);\n    QsciLexerPO &operator=(const QsciLexerPO &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpostscript.h",
    "content": "// This defines the interface to the QsciLexerPostScript class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERPOSTSCRIPT_H\n#define QSCILEXERPOSTSCRIPT_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerPostScript class encapsulates the Scintilla PostScript\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerPostScript : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! PostScript lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A DSC comment.\n        DSCComment = 2,\n\n        //! A DSC comment value.\n        DSCCommentValue = 3,\n\n        //! A number.\n        Number = 4,\n\n        //! A name.\n        Name = 5,\n\n        //! A keyword.\n        Keyword = 6,\n\n        //! A literal.\n        Literal = 7,\n\n        //! An immediately evaluated literal.\n        ImmediateEvalLiteral = 8,\n\n        //! Array parenthesis.\n        ArrayParenthesis = 9,\n\n        //! Dictionary parenthesis.\n        DictionaryParenthesis = 10,\n\n        //! Procedure parenthesis.\n        ProcedureParenthesis = 11,\n\n        //! Text.\n        Text = 12,\n\n        //! A hexadecimal string.\n        HexString = 13,\n\n        //! A base85 string.\n        Base85String = 14,\n\n        //! A bad string character.\n        BadStringCharacter = 15\n    };\n\n    //! Construct a QsciLexerPostScript with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerPostScript(QObject *parent = 0);\n\n    //! Destroys the QsciLexerPostScript instance.\n    virtual ~QsciLexerPostScript();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.  Set 5 can be used to provide\n    //! additional user defined keywords.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the propertyChanged()\n    //! signal as required.\n    void refreshProperties();\n\n    //! Returns true if tokens should be marked.\n    //!\n    //! \\sa setTokenize()\n    bool tokenize() const;\n\n    //! Returns the PostScript level.\n    //!\n    //! \\sa setLevel()\n    int level() const;\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\n    //! Returns true if else blocks can be folded.\n    //!\n    //! \\sa setFoldAtElse()\n    bool foldAtElse() const;\n\npublic slots:\n    //! If \\a tokenize is true then tokens are marked.  The default is false.\n    //!\n    //! \\sa tokenize()\n    virtual void setTokenize(bool tokenize);\n\n    //! The PostScript level is set to \\a level.  The default is 3.\n    //!\n    //! \\sa level()\n    virtual void setLevel(int level);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\n    //! If \\a fold is true then else blocks can be folded.  The default is\n    //! false.\n    //!\n    //! \\sa foldAtElse()\n    virtual void setFoldAtElse(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setTokenizeProp();\n    void setLevelProp();\n    void setCompactProp();\n    void setAtElseProp();\n\n    bool ps_tokenize;\n    int ps_level;\n    bool fold_compact;\n    bool fold_atelse;\n\n    QsciLexerPostScript(const QsciLexerPostScript &);\n    QsciLexerPostScript &operator=(const QsciLexerPostScript &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpov.h",
    "content": "// This defines the interface to the QsciLexerPOV class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERPOV_H\n#define QSCILEXERPOV_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerPOV class encapsulates the Scintilla POV lexer.\nclass QSCINTILLA_EXPORT QsciLexerPOV : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! POV lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A comment line.\n        CommentLine = 2,\n\n        //! A number.\n        Number = 3,\n\n        //! An operator.\n        Operator = 4,\n\n        //! An identifier\n        Identifier = 5,\n\n        //! A string.\n        String = 6,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 7,\n\n        //! A directive.\n        Directive = 8,\n\n        //! A bad directive.\n        BadDirective = 9,\n\n        //! Objects, CSG and appearance.\n        ObjectsCSGAppearance = 10,\n\n        //! Types, modifiers and items.\n        TypesModifiersItems = 11,\n\n        //! Predefined identifiers.\n        PredefinedIdentifiers = 12,\n\n        //! Predefined identifiers.\n        PredefinedFunctions = 13,\n\n        //! A keyword defined in keyword set number 6.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet6 = 14,\n\n        //! A keyword defined in keyword set number 7.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet7 = 15,\n\n        //! A keyword defined in keyword set number 8.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet8 = 16\n    };\n\n    //! Construct a QsciLexerPOV with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerPOV(QObject *parent = 0);\n\n    //! Destroys the QsciLexerPOV instance.\n    virtual ~QsciLexerPOV();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the propertyChanged()\n    //! signal as required.\n    void refreshProperties();\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const;\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\n    //! Returns true if directives can be folded.\n    //!\n    //! \\sa setFoldDirectives()\n    bool foldDirectives() const;\n\npublic slots:\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\n    //! If \\a fold is true then directives can be folded.  The default is\n    //! false.\n    //!\n    //! \\sa foldDirectives()\n    virtual void setFoldDirectives(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n    void setDirectiveProp();\n\n    bool fold_comments;\n    bool fold_compact;\n    bool fold_directives;\n\n    QsciLexerPOV(const QsciLexerPOV &);\n    QsciLexerPOV &operator=(const QsciLexerPOV &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerproperties.h",
    "content": "// This defines the interface to the QsciLexerProperties class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERPROPERTIES_H\n#define QSCILEXERPROPERTIES_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerProperties class encapsulates the Scintilla\n//! Properties lexer.\nclass QSCINTILLA_EXPORT QsciLexerProperties : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Properties lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A section.\n        Section = 2,\n\n        //! An assignment operator.\n        Assignment = 3,\n\n        //! A default value.\n        DefaultValue = 4,\n\n        //! A key.\n        Key = 5\n    };\n\n    //! Construct a QsciLexerProperties with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerProperties(QObject *parent = 0);\n\n    //! Destroys the QsciLexerProperties instance.\n    virtual ~QsciLexerProperties();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the style\n    //! is invalid for this language then an empty QString is returned.  This\n    //! is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;}\n\n    //! If \\a enable is true then initial spaces in a line are allowed.  The\n    //! default is true.\n    //!\n    //! \\sa initialSpaces()\n    void setInitialSpaces(bool enable);\n\n    //! Returns true if initial spaces in a line are allowed.\n    //!\n    //! \\sa setInitialSpaces()\n    bool initialSpaces() const {return initial_spaces;}\n\npublic slots:\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    //! \\sa writeProperties()\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    //! \\sa readProperties()\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCompactProp();\n    void setInitialSpacesProp();\n\n    bool fold_compact;\n    bool initial_spaces;\n\n    QsciLexerProperties(const QsciLexerProperties &);\n    QsciLexerProperties &operator=(const QsciLexerProperties &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpython.h",
    "content": "// This defines the interface to the QsciLexerPython class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERPYTHON_H\n#define QSCILEXERPYTHON_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n#include \"Qsci/qsciscintillabase.h\"\n\n\n//! \\brief The QsciLexerPython class encapsulates the Scintilla Python lexer.\nclass QSCINTILLA_EXPORT QsciLexerPython : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Python lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A number.\n        Number = 2,\n\n        //! A double-quoted string.\n        DoubleQuotedString = 3,\n\n        //! A single-quoted string.\n        SingleQuotedString = 4,\n\n        //! A keyword.\n        Keyword = 5,\n\n        //! A triple single-quoted string.\n        TripleSingleQuotedString = 6,\n\n        //! A triple double-quoted string.\n        TripleDoubleQuotedString = 7,\n\n        //! The name of a class.\n        ClassName = 8,\n\n        //! The name of a function or method.\n        FunctionMethodName = 9,\n\n        //! An operator.\n        Operator = 10,\n\n        //! An identifier\n        Identifier = 11,\n\n        //! A comment block.\n        CommentBlock = 12,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 13,\n\n        //! A highlighted identifier.  These are defined by keyword set\n        //! 2.  Reimplement keywords() to define keyword set 2.\n        HighlightedIdentifier = 14,\n\n        //! A decorator.\n        Decorator = 15,\n\n        //! A double-quoted f-string.\n        DoubleQuotedFString = 16,\n\n        //! A single-quoted f-string.\n        SingleQuotedFString = 17,\n\n        //! A triple single-quoted f-string.\n        TripleSingleQuotedFString = 18,\n\n        //! A triple double-quoted f-string.\n        TripleDoubleQuotedFString = 19,\n    };\n\n    //! This enum defines the different conditions that can cause\n    //! indentations to be displayed as being bad.\n    enum IndentationWarning {\n        //! Bad indentation is not displayed differently.\n        NoWarning = 0,\n\n        //! The indentation is inconsistent when compared to the\n        //! previous line, ie. it is made up of a different combination\n        //! of tabs and/or spaces.\n        Inconsistent = 1,\n\n        //! The indentation is made up of spaces followed by tabs.\n        TabsAfterSpaces = 2,\n\n        //! The indentation contains spaces.\n        Spaces = 3,\n\n        //! The indentation contains tabs.\n        Tabs = 4\n    };\n\n    //! Construct a QsciLexerPython with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerPython(QObject *parent = 0);\n\n    //! Destroys the QsciLexerPython instance.\n    virtual ~QsciLexerPython();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the character sequences that can separate\n    //! auto-completion words.\n    QStringList autoCompletionWordSeparators() const;\n\n    //! \\internal Returns the number of lines prior to the current one when\n    //! determining the scope of a block when auto-indenting.\n    int blockLookback() const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStart(int *style = 0) const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! \\internal Returns the view used for indentation guides.\n    virtual int indentationGuideView() const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if indented comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const {return fold_comments;}\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    void setFoldCompact(bool fold);\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;}\n\n    //! Returns true if triple quoted strings can be folded.\n    //!\n    //! \\sa setFoldQuotes()\n    bool foldQuotes() const {return fold_quotes;}\n\n    //! Returns the condition that will cause bad indentations to be\n    //! displayed.\n    //!\n    //! \\sa setIndentationWarning()\n    QsciLexerPython::IndentationWarning indentationWarning() const {return indent_warn;}\n\n    //! If \\a enabled is true then sub-identifiers defined in keyword set 2\n    //! will be highlighted.  For example, if it is false and \"open\" is defined\n    //! in keyword set 2 then \"foo.open\" will not be highlighted.  The default\n    //! is true.\n    //!\n    //! \\sa highlightSubidentifiers()\n    void setHighlightSubidentifiers(bool enabled);\n\n    //! Returns true if string literals are allowed to span newline characters.\n    //!\n    //! \\sa setHighlightSubidentifiers()\n    bool highlightSubidentifiers() const {return highlight_subids;}\n\n    //! If \\a allowed is true then string literals are allowed to span newline\n    //! characters.  The default is false.\n    //!\n    //! \\sa stringsOverNewlineAllowed()\n    void setStringsOverNewlineAllowed(bool allowed);\n\n    //! Returns true if string literals are allowed to span newline characters.\n    //!\n    //! \\sa setStringsOverNewlineAllowed()\n    bool stringsOverNewlineAllowed() const {return strings_over_newline;}\n\n    //! If \\a allowed is true then Python v2 unicode string literals (e.g.\n    //! u\"utf8\") are allowed.  The default is true.\n    //!\n    //! \\sa v2UnicodeAllowed()\n    void setV2UnicodeAllowed(bool allowed);\n\n    //! Returns true if Python v2 unicode string literals (e.g. u\"utf8\") are\n    //! allowed.\n    //!\n    //! \\sa setV2UnicodeAllowed()\n    bool v2UnicodeAllowed() const {return v2_unicode;}\n\n    //! If \\a allowed is true then Python v3 binary and octal literals (e.g.\n    //! 0b1011, 0o712) are allowed.  The default is true.\n    //!\n    //! \\sa v3BinaryOctalAllowed()\n    void setV3BinaryOctalAllowed(bool allowed);\n\n    //! Returns true if Python v3 binary and octal literals (e.g. 0b1011,\n    //! 0o712) are allowed.\n    //!\n    //! \\sa setV3BinaryOctalAllowed()\n    bool v3BinaryOctalAllowed() const {return v3_binary_octal;}\n\n    //! If \\a allowed is true then Python v3 bytes string literals (e.g.\n    //! b\"bytes\") are allowed.  The default is true.\n    //!\n    //! \\sa v3BytesAllowed()\n    void setV3BytesAllowed(bool allowed);\n\n    //! Returns true if Python v3 bytes string literals (e.g. b\"bytes\") are\n    //! allowed.\n    //!\n    //! \\sa setV3BytesAllowed()\n    bool v3BytesAllowed() const {return v3_bytes;}\n\npublic slots:\n    //! If \\a fold is true then indented comment blocks can be folded.  The\n    //! default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then triple quoted strings can be folded.  The\n    //! default is false.\n    //!\n    //! \\sa foldQuotes()\n    virtual void setFoldQuotes(bool fold);\n\n    //! Sets the condition that will cause bad indentations to be\n    //! displayed.\n    //!\n    //! \\sa indentationWarning()\n    virtual void setIndentationWarning(QsciLexerPython::IndentationWarning warn);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n    void setQuotesProp();\n    void setTabWhingeProp();\n    void setStringsOverNewlineProp();\n    void setV2UnicodeProp();\n    void setV3BinaryOctalProp();\n    void setV3BytesProp();\n    void setHighlightSubidsProp();\n\n    bool fold_comments;\n    bool fold_compact;\n    bool fold_quotes;\n    IndentationWarning indent_warn;\n    bool strings_over_newline;\n    bool v2_unicode;\n    bool v3_binary_octal;\n    bool v3_bytes;\n    bool highlight_subids;\n\n    friend class QsciLexerHTML;\n\n    static const char *keywordClass;\n\n    QsciLexerPython(const QsciLexerPython &);\n    QsciLexerPython &operator=(const QsciLexerPython &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerruby.h",
    "content": "// This defines the interface to the QsciLexerRuby class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERRUBY_H\n#define QSCILEXERRUBY_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerRuby class encapsulates the Scintilla Ruby lexer.\nclass QSCINTILLA_EXPORT QsciLexerRuby : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Ruby lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! An error.\n        Error = 1,\n\n        //! A comment.\n        Comment = 2,\n\n        //! A POD.\n        POD = 3,\n\n        //! A number.\n        Number = 4,\n\n        //! A keyword.\n        Keyword = 5,\n\n        //! A double-quoted string.\n        DoubleQuotedString = 6,\n\n        //! A single-quoted string.\n        SingleQuotedString = 7,\n\n        //! The name of a class.\n        ClassName = 8,\n\n        //! The name of a function or method.\n        FunctionMethodName = 9,\n\n        //! An operator.\n        Operator = 10,\n\n        //! An identifier\n        Identifier = 11,\n\n        //! A regular expression.\n        Regex = 12,\n\n        //! A global.\n        Global = 13,\n\n        //! A symbol.\n        Symbol = 14,\n\n        //! The name of a module.\n        ModuleName = 15,\n\n        //! An instance variable.\n        InstanceVariable = 16,\n\n        //! A class variable.\n        ClassVariable = 17,\n\n        //! Backticks.\n        Backticks = 18,\n\n        //! A data section.\n        DataSection = 19,\n\n        //! A here document delimiter.\n        HereDocumentDelimiter = 20,\n\n        //! A here document.\n        HereDocument = 21,\n\n        //! A %q string.\n        PercentStringq = 24,\n\n        //! A %Q string.\n        PercentStringQ = 25,\n\n        //! A %x string.\n        PercentStringx = 26,\n\n        //! A %r string.\n        PercentStringr = 27,\n\n        //! A %w string.\n        PercentStringw = 28,\n\n        //! A demoted keyword.\n        DemotedKeyword = 29,\n\n        //! stdin.\n        Stdin = 30,\n\n        //! stdout.\n        Stdout = 31,\n\n        //! stderr.\n        Stderr = 40\n    };\n\n    //! Construct a QsciLexerRuby with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerRuby(QObject *parent = 0);\n\n    //! Destroys the QsciLexerRuby instance.\n    virtual ~QsciLexerRuby();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the end of a block for\n    //! auto-indentation.  The style is returned via \\a style.\n    const char *blockEnd(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of words or characters in\n    //! a particular style that define the start of a block for\n    //! auto-indentation.  The styles is returned via \\a style.\n    const char *blockStart(int *style = 0) const;\n\n    //! \\internal Returns a space separated list of keywords in a\n    //! particular style that define the start of a block for\n    //! auto-indentation.  The style is returned via \\a style.\n    const char *blockStartKeyword(int *style = 0) const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultpaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the style\n    //! is invalid for this language then an empty QString is returned.  This\n    //! is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    void setFoldComments(bool fold);\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const {return fold_comments;}\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    void setFoldCompact(bool fold);\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;}\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs, const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs, const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n\n    bool fold_comments;\n    bool fold_compact;\n\n    QsciLexerRuby(const QsciLexerRuby &);\n    QsciLexerRuby &operator=(const QsciLexerRuby &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerspice.h",
    "content": "// This defines the interface to the QsciLexerSpice class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERSPICE_H\n#define QSCILEXERSPICE_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerSpice class encapsulates the Scintilla Spice lexer.\nclass QSCINTILLA_EXPORT QsciLexerSpice : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Spice lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! An identifier.\n        Identifier = 1,\n\n        //! A command.\n        Command = 2,\n\n        //! A function.\n        Function = 3,\n\n        //! A parameter.\n        Parameter = 4,\n\n        //! A number.\n        Number = 5,\n\n        //! A delimiter.\n        Delimiter = 6,\n\n        //! A value.\n        Value = 7,\n\n        //! A comment.\n        Comment = 8\n    };\n\n    //! Construct a QsciLexerSpice with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerSpice(QObject *parent = 0);\n\n    //! Destroys the QsciLexerSpice instance.\n    virtual ~QsciLexerSpice();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\nprivate:\n    QsciLexerSpice(const QsciLexerSpice &);\n    QsciLexerSpice &operator=(const QsciLexerSpice &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexersql.h",
    "content": "// This defines the interface to the QsciLexerSQL class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERSQL_H\n#define QSCILEXERSQL_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerSQL class encapsulates the Scintilla SQL lexer.\nclass QSCINTILLA_EXPORT QsciLexerSQL : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! SQL lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A line comment.\n        CommentLine = 2,\n\n        //! A JavaDoc/Doxygen style comment.\n        CommentDoc = 3,\n\n        //! A number.\n        Number = 4,\n\n        //! A keyword.\n        Keyword = 5,\n\n        //! A double-quoted string.\n        DoubleQuotedString = 6,\n\n        //! A single-quoted string.\n        SingleQuotedString = 7,\n\n        //! An SQL*Plus keyword.\n        PlusKeyword = 8,\n\n        //! An SQL*Plus prompt.\n        PlusPrompt = 9,\n\n        //! An operator.\n        Operator = 10,\n\n        //! An identifier\n        Identifier = 11,\n\n        //! An SQL*Plus comment.\n        PlusComment = 13,\n\n        //! A '#' line comment.\n        CommentLineHash = 15,\n\n        //! A JavaDoc/Doxygen keyword.\n        CommentDocKeyword = 17,\n\n        //! A JavaDoc/Doxygen keyword error.\n        CommentDocKeywordError = 18,\n\n        //! A keyword defined in keyword set number 5.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        //! Note that keywords must be defined using lower case.\n        KeywordSet5 = 19,\n\n        //! A keyword defined in keyword set number 6.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        //! Note that keywords must be defined using lower case.\n        KeywordSet6 = 20,\n\n        //! A keyword defined in keyword set number 7.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        //! Note that keywords must be defined using lower case.\n        KeywordSet7 = 21,\n\n        //! A keyword defined in keyword set number 8.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        //! Note that keywords must be defined using lower case.\n        KeywordSet8 = 22,\n\n        //! A quoted identifier.\n        QuotedIdentifier = 23,\n\n        //! A quoted operator.\n        QuotedOperator = 24,\n    };\n\n    //! Construct a QsciLexerSQL with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerSQL(QObject *parent = 0);\n\n    //! Destroys the QsciLexerSQL instance.\n    virtual ~QsciLexerSQL();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised by\n    //! the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the style\n    //! is invalid for this language then an empty QString is returned.  This\n    //! is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! Returns true if backslash escapes are enabled.\n    //!\n    //! \\sa setBackslashEscapes()\n    bool backslashEscapes() const {return backslash_escapes;}\n\n    //! If \\a enable is true then words may contain dots (i.e. periods or full\n    //! stops).  The default is false.\n    //!\n    //! \\sa dottedWords()\n    void setDottedWords(bool enable);\n\n    //! Returns true if words may contain dots (i.e. periods or full stops).\n    //!\n    //! \\sa setDottedWords()\n    bool dottedWords() const {return allow_dotted_word;}\n\n    //! If \\a fold is true then ELSE blocks can be folded.  The default is\n    //! false.\n    //!\n    //! \\sa foldAtElse()\n    void setFoldAtElse(bool fold);\n\n    //! Returns true if ELSE blocks can be folded.\n    //!\n    //! \\sa setFoldAtElse()\n    bool foldAtElse() const {return at_else;}\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const {return fold_comments;}\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;}\n\n    //! If \\a fold is true then only BEGIN blocks can be folded.  The default\n    //! is false.\n    //!\n    //! \\sa foldOnlyBegin()\n    void setFoldOnlyBegin(bool fold);\n\n    //! Returns true if BEGIN blocks only can be folded.\n    //!\n    //! \\sa setFoldOnlyBegin()\n    bool foldOnlyBegin() const {return only_begin;}\n\n    //! If \\a enable is true then '#' is used as a comment character.  It is\n    //! typically enabled for MySQL and disabled for Oracle.  The default is\n    //! false.\n    //!\n    //! \\sa hashComments()\n    void setHashComments(bool enable);\n\n    //! Returns true if '#' is used as a comment character.\n    //!\n    //! \\sa setHashComments()\n    bool hashComments() const {return numbersign_comment;}\n\n    //! If \\a enable is true then quoted identifiers are enabled.  The default\n    //! is false.\n    //!\n    //! \\sa quotedIdentifiers()\n    void setQuotedIdentifiers(bool enable);\n\n    //! Returns true if quoted identifiers are enabled.\n    //!\n    //! \\sa setQuotedIdentifiers()\n    bool quotedIdentifiers() const {return backticks_identifier;}\n\npublic slots:\n    //! If \\a enable is true then backslash escapes are enabled.  The\n    //! default is false.\n    //!\n    //! \\sa backslashEscapes()\n    virtual void setBackslashEscapes(bool enable);\n\n    //! If \\a fold is true then multi-line comment blocks can be folded.  The\n    //! default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs, const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs, const QString &prefix) const;\n\nprivate:\n    void setAtElseProp();\n    void setCommentProp();\n    void setCompactProp();\n    void setOnlyBeginProp();\n    void setBackticksIdentifierProp();\n    void setNumbersignCommentProp();\n    void setBackslashEscapesProp();\n    void setAllowDottedWordProp();\n\n    bool at_else;\n    bool fold_comments;\n    bool fold_compact;\n    bool only_begin;\n    bool backticks_identifier;\n    bool numbersign_comment;\n    bool backslash_escapes;\n    bool allow_dotted_word;\n\n    QsciLexerSQL(const QsciLexerSQL &);\n    QsciLexerSQL &operator=(const QsciLexerSQL &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexertcl.h",
    "content": "// This defines the interface to the QsciLexerTCL class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERTCL_H\n#define QSCILEXERTCL_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerTCL class encapsulates the Scintilla TCL lexer.\nclass QSCINTILLA_EXPORT QsciLexerTCL : public QsciLexer\n{\n\tQ_OBJECT\n\npublic:\n\t//! This enum defines the meanings of the different styles used by the TCL\n\t//! lexer.\n\tenum {\n\t\t//! The default.\n\t\tDefault = 0,\n\n\t\t//! A comment.\n\t\tComment = 1,\n\n\t\t//! A comment line.\n\t\tCommentLine = 2,\n\n\t\t//! A number.\n\t\tNumber = 3,\n\n\t\t//! A quoted keyword.\n\t\tQuotedKeyword = 4,\n\n\t\t//! A quoted string.\n\t\tQuotedString = 5,\n\n\t\t//! An operator.\n\t\tOperator = 6,\n\n\t\t//! An identifier\n\t\tIdentifier = 7,\n\n\t\t//! A substitution.\n\t\tSubstitution = 8,\n\n\t\t//! A substitution starting with a brace.\n\t\tSubstitutionBrace = 9,\n\n\t\t//! A modifier.\n\t\tModifier = 10,\n\n\t\t//! Expand keyword (defined in keyword set number 5).\n\t\tExpandKeyword = 11,\n\n        //! A TCL keyword (defined in keyword set number 1).\n        TCLKeyword = 12,\n\n        //! A Tk keyword (defined in keyword set number 2).\n        TkKeyword = 13,\n\n        //! An iTCL keyword (defined in keyword set number 3).\n        ITCLKeyword = 14,\n\n        //! A Tk command (defined in keyword set number 4).\n        TkCommand = 15,\n\n        //! A keyword defined in keyword set number 6.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet6 = 16,\n\n        //! A keyword defined in keyword set number 7.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet7 = 17,\n\n        //! A keyword defined in keyword set number 8.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet8 = 18,\n\n        //! A keyword defined in keyword set number 9.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet9 = 19,\n\n        //! A comment box.\n        CommentBox = 20,\n\n        //! A comment block.\n        CommentBlock = 21\n\t};\n\n\t//! Construct a QsciLexerTCL with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n\tQsciLexerTCL(QObject *parent = 0);\n\n\t//! Destroys the QsciLexerTCL instance.\n\tvirtual ~QsciLexerTCL();\n\n\t//! Returns the name of the language.\n\tconst char *language() const;\n\n\t//! Returns the name of the lexer.  Some lexers support a number of\n\t//! languages.\n\tconst char *lexer() const;\n\n\t//! \\internal Returns the style used for braces for brace matching.\n\tint braceStyle() const;\n\n\t//! Returns the foreground colour of the text for style number \\a style.\n\t//!\n\t//! \\sa defaultPaper()\n\tQColor defaultColor(int style) const;\n\n\t//! Returns the end-of-line fill for style number \\a style.\n\tbool defaultEolFill(int style) const;\n\n\t//! Returns the font for style number \\a style.\n\tQFont defaultFont(int style) const;\n\n\t//! Returns the background colour of the text for style number \\a style.\n\t//!\n\t//! \\sa defaultColor()\n\tQColor defaultPaper(int style) const;\n\n\t//! Returns the set of keywords for the keyword set \\a set recognised\n\t//! by the lexer as a space separated string.\n\tconst char *keywords(int set) const;\n\n\t//! Returns the descriptive name for style number \\a style.  If the style\n\t//! is invalid for this language then an empty QString is returned.  This\n\t//! is intended to be used in user preference dialogs.\n\tQString description(int style) const;\n\n\t//! Causes all properties to be refreshed by emitting the\n\t//! propertyChanged() signal as required.\n\tvoid refreshProperties();\n\n\t//! If \\a fold is true then multi-line comment blocks can be folded.  The\n    //! default is false.\n\t//!\n\t//! \\sa foldComments()\n\tvoid setFoldComments(bool fold);\n\n    //! Returns true if multi-line comment blocks can be folded.\n\t//!\n\t//! \\sa setFoldComments()\n\tbool foldComments() const {return fold_comments;}\n\nprotected:\n\t//! The lexer's properties are read from the settings \\a qs.  \\a prefix\n\t//! (which has a trailing '/') should be used as a prefix to the key of\n\t//! each setting.  true is returned if there is no error.\n\t//!\n\tbool readProperties(QSettings &qs,const QString &prefix);\n\n\t//! The lexer's properties are written to the settings \\a qs.\n\t//! \\a prefix (which has a trailing '/') should be used as a prefix to\n\t//! the key of each setting.  true is returned if there is no error.\n\t//!\n\tbool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n\tvoid setCommentProp();\n\n\tbool fold_comments;\n\n\tQsciLexerTCL(const QsciLexerTCL &);\n\tQsciLexerTCL &operator=(const QsciLexerTCL &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexertex.h",
    "content": "// This defines the interface to the QsciLexerTeX class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERTEX_H\n#define QSCILEXERTEX_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerTeX class encapsulates the Scintilla TeX lexer.\nclass QSCINTILLA_EXPORT QsciLexerTeX : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! TeX lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A special.\n        Special = 1,\n\n        //! A group.\n        Group = 2,\n\n        //! A symbol.\n        Symbol = 3,\n\n        //! A command.\n        Command = 4,\n\n        //! Text.\n        Text = 5\n    };\n\n    //! Construct a QsciLexerTeX with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerTeX(QObject *parent = 0);\n\n    //! Destroys the QsciLexerTeX instance.\n    virtual ~QsciLexerTeX();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    QColor defaultColor(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! If \\a fold is true then multi-line comment blocks can be folded.  The\n    //! default is false.\n    //!\n    //! \\sa foldComments()\n    void setFoldComments(bool fold);\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const {return fold_comments;}\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    void setFoldCompact(bool fold);\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;}\n\n    //! If \\a enable is true then comments are processed as TeX source\n    //! otherwise they are ignored.  The default is false.\n    //!\n    //! \\sa processComments()\n    void setProcessComments(bool enable);\n\n    //! Returns true if comments are processed as TeX source.\n    //!\n    //! \\sa setProcessComments()\n    bool processComments() const {return process_comments;}\n\n    //! If \\a enable is true then \\\\if<unknown> processed is processed as a\n    //! command.  The default is true.\n    //!\n    //! \\sa processIf()\n    void setProcessIf(bool enable);\n\n    //! Returns true if \\\\if<unknown> is processed as a command.\n    //!\n    //! \\sa setProcessIf()\n    bool processIf() const {return process_if;}\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs, const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs, const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n    void setProcessCommentsProp();\n    void setAutoIfProp();\n\n    bool fold_comments;\n    bool fold_compact;\n    bool process_comments;\n    bool process_if;\n\n    QsciLexerTeX(const QsciLexerTeX &);\n    QsciLexerTeX &operator=(const QsciLexerTeX &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerverilog.h",
    "content": "// This defines the interface to the QsciLexerVerilog class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERVERILOG_H\n#define QSCILEXERVERILOG_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerVerilog class encapsulates the Scintilla Verilog\n//! lexer.\nclass QSCINTILLA_EXPORT QsciLexerVerilog : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! Verilog lexer.\n    enum {\n        //! The default.\n        Default = 0,\n        InactiveDefault = Default + 64,\n\n        //! A comment.\n        Comment = 1,\n        InactiveComment = Comment + 64,\n\n        //! A line comment.\n        CommentLine = 2,\n        InactiveCommentLine = CommentLine + 64,\n\n        //! A bang comment.\n        CommentBang = 3,\n        InactiveCommentBang = CommentBang + 64,\n\n        //! A number\n        Number = 4,\n        InactiveNumber = Number + 64,\n\n        //! A keyword.\n        Keyword = 5,\n        InactiveKeyword = Keyword + 64,\n\n        //! A string.\n        String = 6,\n        InactiveString = String + 64,\n\n        //! A keyword defined in keyword set number 2.  The class must\n        //! be sub-classed and re-implement keywords() to make use of\n        //! this style.\n        KeywordSet2 = 7,\n        InactiveKeywordSet2 = KeywordSet2 + 64,\n\n        //! A system task.\n        SystemTask = 8,\n        InactiveSystemTask = SystemTask + 64,\n\n        //! A pre-processor block.\n        Preprocessor = 9,\n        InactivePreprocessor = Preprocessor + 64,\n\n        //! An operator.\n        Operator = 10,\n        InactiveOperator = Operator + 64,\n\n        //! An identifier.\n        Identifier = 11,\n        InactiveIdentifier = Identifier + 64,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 12,\n        InactiveUnclosedString = UnclosedString + 64,\n\n        //! A keyword defined in keyword set number 4.  The class must\n        //! be sub-classed and re-implement keywords() to make use of\n        //! this style.  This set is intended to be used for user defined\n        //! identifiers and tasks.\n        UserKeywordSet = 19,\n        InactiveUserKeywordSet = UserKeywordSet + 64,\n\n        //! A keyword comment.\n        CommentKeyword = 20,\n        InactiveCommentKeyword = CommentKeyword + 64,\n\n        //! An input port declaration.\n        DeclareInputPort = 21,\n        InactiveDeclareInputPort = DeclareInputPort + 64,\n\n        //! An output port declaration.\n        DeclareOutputPort = 22,\n        InactiveDeclareOutputPort = DeclareOutputPort + 64,\n\n        //! An input/output port declaration.\n        DeclareInputOutputPort = 23,\n        InactiveDeclareInputOutputPort = DeclareInputOutputPort + 64,\n\n        //! A port connection.\n        PortConnection = 24,\n        InactivePortConnection = PortConnection + 64,\n    };\n\n    //! Construct a QsciLexerVerilog with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerVerilog(QObject *parent = 0);\n\n    //! Destroys the QsciLexerVerilog instance.\n    virtual ~QsciLexerVerilog();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the string of characters that comprise a word.\n    const char *wordCharacters() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! If \\a fold is true then \"} else {\" lines can be folded.  The\n    //! default is false.\n    //!\n    //! \\sa foldAtElse()\n    void setFoldAtElse(bool fold);\n\n    //! Returns true if \"} else {\" lines can be folded.\n    //!\n    //! \\sa setFoldAtElse()\n    bool foldAtElse() const {return fold_atelse;}\n\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    void setFoldComments(bool fold);\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const {return fold_comments;}\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    void setFoldCompact(bool fold);\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const {return fold_compact;};\n\n    //! If \\a fold is true then preprocessor blocks can be folded.  The\n    //! default is true.\n    //!\n    //! \\sa foldPreprocessor()\n    void setFoldPreprocessor(bool fold);\n\n    //! Returns true if preprocessor blocks can be folded.\n    //!\n    //! \\sa setFoldPreprocessor()\n    bool foldPreprocessor() const {return fold_preproc;};\n\n    //! If \\a fold is true then modules can be folded.  The default is false.\n    //!\n    //! \\sa foldAtModule()\n    void setFoldAtModule(bool fold);\n\n    //! Returns true if modules can be folded.\n    //!\n    //! \\sa setFoldAtModule()\n    bool foldAtModule() const {return fold_atmodule;};\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    //! \\sa writeProperties()\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    //! \\sa readProperties()\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setAtElseProp();\n    void setCommentProp();\n    void setCompactProp();\n    void setPreprocProp();\n    void setAtModuleProp();\n\n    bool fold_atelse;\n    bool fold_comments;\n    bool fold_compact;\n    bool fold_preproc;\n    bool fold_atmodule;\n\n    QsciLexerVerilog(const QsciLexerVerilog &);\n    QsciLexerVerilog &operator=(const QsciLexerVerilog &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexervhdl.h",
    "content": "// This defines the interface to the QsciLexerVHDL class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERVHDL_H\n#define QSCILEXERVHDL_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerVHDL class encapsulates the Scintilla VHDL lexer.\nclass QSCINTILLA_EXPORT QsciLexerVHDL : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! VHDL lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! A comment line.\n        CommentLine = 2,\n\n        //! A number.\n        Number = 3,\n\n        //! A string.\n        String = 4,\n\n        //! An operator.\n        Operator = 5,\n\n        //! An identifier\n        Identifier = 6,\n\n        //! The end of a line where a string is not closed.\n        UnclosedString = 7,\n\n        //! A keyword.\n        Keyword = 8,\n\n        //! A standard operator.\n        StandardOperator = 9,\n\n        //! An attribute.\n        Attribute = 10,\n\n        //! A standard function.\n        StandardFunction = 11,\n\n        //! A standard package.\n        StandardPackage = 12,\n\n        //! A standard type.\n        StandardType = 13,\n\n        //! A keyword defined in keyword set number 7.  The class must be\n        //! sub-classed and re-implement keywords() to make use of this style.\n        KeywordSet7 = 14,\n\n        //! A comment block.\n        CommentBlock = 15,\n    };\n\n    //! Construct a QsciLexerVHDL with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerVHDL(QObject *parent = 0);\n\n    //! Destroys the QsciLexerVHDL instance.\n    virtual ~QsciLexerVHDL();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! \\internal Returns the style used for braces for brace matching.\n    int braceStyle() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the propertyChanged()\n    //! signal as required.\n    void refreshProperties();\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const;\n\n    //! Returns true if trailing blank lines are included in a fold block.\n    //!\n    //! \\sa setFoldCompact()\n    bool foldCompact() const;\n\n    //! Returns true if else blocks can be folded.\n    //!\n    //! \\sa setFoldAtElse()\n    bool foldAtElse() const;\n\n    //! Returns true if begin blocks can be folded.\n    //!\n    //! \\sa setFoldAtBegin()\n    bool foldAtBegin() const;\n\n    //! Returns true if blocks can be folded at a parenthesis.\n    //!\n    //! \\sa setFoldAtParenthesis()\n    bool foldAtParenthesis() const;\n\npublic slots:\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is true.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\n    //! If \\a fold is true then trailing blank lines are included in a fold\n    //! block. The default is true.\n    //!\n    //! \\sa foldCompact()\n    virtual void setFoldCompact(bool fold);\n\n    //! If \\a fold is true then else blocks can be folded.  The default is\n    //! true.\n    //!\n    //! \\sa foldAtElse()\n    virtual void setFoldAtElse(bool fold);\n\n    //! If \\a fold is true then begin blocks can be folded.  The default is\n    //! true.\n    //!\n    //! \\sa foldAtBegin()\n    virtual void setFoldAtBegin(bool fold);\n\n    //! If \\a fold is true then blocks can be folded at a parenthesis.  The\n    //! default is true.\n    //!\n    //! \\sa foldAtParenthesis()\n    virtual void setFoldAtParenthesis(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n    void setCompactProp();\n    void setAtElseProp();\n    void setAtBeginProp();\n    void setAtParenthProp();\n\n    bool fold_comments;\n    bool fold_compact;\n    bool fold_atelse;\n    bool fold_atbegin;\n    bool fold_atparenth;\n\n    QsciLexerVHDL(const QsciLexerVHDL &);\n    QsciLexerVHDL &operator=(const QsciLexerVHDL &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexerxml.h",
    "content": "// This defines the interface to the QsciLexerXML class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERXML_H\n#define QSCILEXERXML_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexerhtml.h>\n\n\n//! \\brief The QsciLexerXML class encapsulates the Scintilla XML lexer.\nclass QSCINTILLA_EXPORT QsciLexerXML : public QsciLexerHTML\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciLexerXML with parent \\a parent.  \\a parent is typically\n    //! the QsciScintilla instance.\n    QsciLexerXML(QObject *parent = 0);\n\n    //! Destroys the QsciLexerXML instance.\n    virtual ~QsciLexerXML();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Causes all properties to be refreshed by emitting the\n    //! propertyChanged() signal as required.\n    void refreshProperties();\n\n    //! If \\a allowed is true then scripts are styled.  The default is true.\n    //!\n    //! \\sa scriptsStyled()\n    void setScriptsStyled(bool styled);\n\n    //! Returns true if scripts are styled.\n    //!\n    //! \\sa setScriptsStyled()\n    bool scriptsStyled() const;\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs, const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs, const QString &prefix) const;\n\nprivate:\n    void setScriptsProp();\n\n    bool scripts;\n\n    QsciLexerXML(const QsciLexerXML &);\n    QsciLexerXML &operator=(const QsciLexerXML &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscilexeryaml.h",
    "content": "// This defines the interface to the QsciLexerYAML class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCILEXERYAML_H\n#define QSCILEXERYAML_H\n\n#include <QObject>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscilexer.h>\n\n\n//! \\brief The QsciLexerYAML class encapsulates the Scintilla YAML lexer.\nclass QSCINTILLA_EXPORT QsciLexerYAML : public QsciLexer\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the meanings of the different styles used by the\n    //! YAML lexer.\n    enum {\n        //! The default.\n        Default = 0,\n\n        //! A comment.\n        Comment = 1,\n\n        //! An identifier.\n        Identifier = 2,\n\n        //! A keyword\n        Keyword = 3,\n\n        //! A number.\n        Number = 4,\n\n        //! A reference.\n        Reference = 5,\n\n        //! A document delimiter.\n        DocumentDelimiter = 6,\n\n        //! A text block marker.\n        TextBlockMarker = 7,\n\n        //! A syntax error marker.\n        SyntaxErrorMarker = 8,\n\n        //! An operator.\n        Operator = 9\n    };\n\n    //! Construct a QsciLexerYAML with parent \\a parent.  \\a parent is\n    //! typically the QsciScintilla instance.\n    QsciLexerYAML(QObject *parent = 0);\n\n    //! Destroys the QsciLexerYAML instance.\n    virtual ~QsciLexerYAML();\n\n    //! Returns the name of the language.\n    const char *language() const;\n\n    //! Returns the name of the lexer.  Some lexers support a number of\n    //! languages.\n    const char *lexer() const;\n\n    //! Returns the foreground colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultPaper()\n    QColor defaultColor(int style) const;\n\n    //! Returns the end-of-line fill for style number \\a style.\n    bool defaultEolFill(int style) const;\n\n    //! Returns the font for style number \\a style.\n    QFont defaultFont(int style) const;\n\n    //! Returns the background colour of the text for style number \\a style.\n    //!\n    //! \\sa defaultColor()\n    QColor defaultPaper(int style) const;\n\n    //! Returns the set of keywords for the keyword set \\a set recognised\n    //! by the lexer as a space separated string.\n    const char *keywords(int set) const;\n\n    //! Returns the descriptive name for style number \\a style.  If the\n    //! style is invalid for this language then an empty QString is returned.\n    //! This is intended to be used in user preference dialogs.\n    QString description(int style) const;\n\n    //! Causes all properties to be refreshed by emitting the propertyChanged()\n    //! signal as required.\n    void refreshProperties();\n\n    //! Returns true if multi-line comment blocks can be folded.\n    //!\n    //! \\sa setFoldComments()\n    bool foldComments() const;\n\npublic slots:\n    //! If \\a fold is true then multi-line comment blocks can be folded.\n    //! The default is false.\n    //!\n    //! \\sa foldComments()\n    virtual void setFoldComments(bool fold);\n\nprotected:\n    //! The lexer's properties are read from the settings \\a qs.  \\a prefix\n    //! (which has a trailing '/') should be used as a prefix to the key of\n    //! each setting.  true is returned if there is no error.\n    //!\n    bool readProperties(QSettings &qs,const QString &prefix);\n\n    //! The lexer's properties are written to the settings \\a qs.\n    //! \\a prefix (which has a trailing '/') should be used as a prefix to\n    //! the key of each setting.  true is returned if there is no error.\n    //!\n    bool writeProperties(QSettings &qs,const QString &prefix) const;\n\nprivate:\n    void setCommentProp();\n\n    bool fold_comments;\n\n    QsciLexerYAML(const QsciLexerYAML &);\n    QsciLexerYAML &operator=(const QsciLexerYAML &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscimacro.h",
    "content": "// This defines the interface to the QsciMacro class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCIMACRO_H\n#define QSCIMACRO_H\n\n#include <QList>\n#include <QObject>\n#include <QString>\n\n#include <Qsci/qsciglobal.h>\n\n\nclass QsciScintilla;\n\n\n//! \\brief The QsciMacro class represents a sequence of recordable editor\n//! commands.\n//!\n//! Methods are provided to convert convert a macro to and from a textual\n//! representation so that they can be easily written to and read from\n//! permanent storage.\nclass QSCINTILLA_EXPORT QsciMacro : public QObject\n{\n    Q_OBJECT\n\npublic:\n    //! Construct a QsciMacro with parent \\a parent.\n    QsciMacro(QsciScintilla *parent);\n\n    //! Construct a QsciMacro from the printable ASCII representation \\a asc,\n    //! with parent \\a parent.\n    QsciMacro(const QString &asc, QsciScintilla *parent);\n\n    //! Destroy the QsciMacro instance.\n    virtual ~QsciMacro();\n\n    //! Clear the contents of the macro.\n    void clear();\n\n    //! Load the macro from the printable ASCII representation \\a asc.  Returns\n    //! true if there was no error.\n    //!\n    //! \\sa save()\n    bool load(const QString &asc);\n\n    //! Return a printable ASCII representation of the macro.  It is guaranteed\n    //! that only printable ASCII characters are used and that double quote\n    //! characters will not be used.\n    //!\n    //! \\sa load()\n    QString save() const;\n\npublic slots:\n    //! Play the macro.\n    virtual void play();\n\n    //! Start recording user commands and add them to the macro.\n    virtual void startRecording();\n\n    //! Stop recording user commands.\n    virtual void endRecording();\n\nprivate slots:\n    void record(unsigned int msg, unsigned long wParam, void *lParam);\n\nprivate:\n    struct Macro {\n        unsigned int msg;\n        unsigned long wParam;\n        QByteArray text;\n    };\n\n    QsciScintilla *qsci;\n    QList<Macro> macro;\n\n    QsciMacro(const QsciMacro &);\n    QsciMacro &operator=(const QsciMacro &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qsciprinter.h",
    "content": "// This module defines interface to the QsciPrinter class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCIPRINTER_H\n#define QSCIPRINTER_H\n\n// This is needed for Qt v5.0.0-alpha.\n#if defined(B0)\n#undef B0\n#endif\n\n#include <qprinter.h>\n\n#if !defined(QT_NO_PRINTER)\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qsciscintilla.h>\n\n\nQT_BEGIN_NAMESPACE\nclass QRect;\nclass QPainter;\nQT_END_NAMESPACE\n\nclass QsciScintillaBase;\n\n\n//! \\brief The QsciPrinter class is a sub-class of the Qt QPrinter class that\n//! is able to print the text of a Scintilla document.\n//!\n//! The class can be further sub-classed to alter to layout of the text, adding\n//! headers and footers for example.\nclass QSCINTILLA_EXPORT QsciPrinter : public QPrinter\n{\npublic:\n    //! Constructs a printer paint device with mode \\a mode.\n    QsciPrinter(PrinterMode mode = ScreenResolution);\n\n    //! Destroys the QsciPrinter instance.\n    virtual ~QsciPrinter();\n\n    //! Format a page, by adding headers and footers for example, before the\n    //! document text is drawn on it.  \\a painter is the painter to be used to\n    //! add customised text and graphics.  \\a drawing is true if the page is\n    //! actually being drawn rather than being sized.  \\a painter drawing\n    //! methods must only be called when \\a drawing is true.  \\a area is the\n    //! area of the page that will be used to draw the text.  This should be\n    //! modified if it is necessary to reserve space for any customised text or\n    //! graphics.  By default the area is relative to the printable area of the\n    //! page.  Use QPrinter::setFullPage() before calling printRange() if you\n    //! want to try and print over the whole page.  \\a pagenr is the number of\n    //! the page.  The first page is numbered 1.\n    virtual void formatPage(QPainter &painter, bool drawing, QRect &area,\n            int pagenr);\n\n    //! Return the number of points to add to each font when printing.\n    //!\n    //! \\sa setMagnification()\n    int magnification() const {return mag;}\n\n    //! Sets the number of points to add to each font when printing to \\a\n    //! magnification.\n    //!\n    //! \\sa magnification()\n    virtual void setMagnification(int magnification);\n\n    //! Print a range of lines from the Scintilla instance \\a qsb using the\n    //! supplied QPainter \\a painter.  \\a from is the first line to print and a\n    //! negative value signifies the first line of text.  \\a to is the last\n    //! line to print and a negative value signifies the last line of text.\n    //! true is returned if there was no error.\n    virtual int printRange(QsciScintillaBase *qsb, QPainter &painter,\n            int from = -1, int to = -1);\n\n    //! Print a range of lines from the Scintilla instance \\a qsb using a\n    //! default QPainter.  \\a from is the first line to print and a negative\n    //! value signifies the first line of text.  \\a to is the last line to\n    //! print and a negative value signifies the last line of text.  true is\n    //! returned if there was no error.\n    virtual int printRange(QsciScintillaBase *qsb, int from = -1, int to = -1);\n\n    //! Return the line wrap mode used when printing.  The default is\n    //! QsciScintilla::WrapWord.\n    //!\n    //! \\sa setWrapMode()\n    QsciScintilla::WrapMode wrapMode() const {return wrap;}\n\n    //! Sets the line wrap mode used when printing to \\a wmode.\n    //!\n    //! \\sa wrapMode()\n    virtual void setWrapMode(QsciScintilla::WrapMode wmode);\n\nprivate:\n    int mag;\n    QsciScintilla::WrapMode wrap;\n\n    QsciPrinter(const QsciPrinter &);\n    QsciPrinter &operator=(const QsciPrinter &);\n};\n\n#endif\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qsciscintilla.h",
    "content": "// This module defines the \"official\" high-level API of the Qt port of\n// Scintilla.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCISCINTILLA_H\n#define QSCISCINTILLA_H\n\n#include <QByteArray>\n#include <QList>\n#include <QObject>\n#include <QPointer>\n#include <QStringList>\n\n#include <Qsci/qsciglobal.h>\n#include <Qsci/qscicommand.h>\n#include <Qsci/qscidocument.h>\n#include <Qsci/qsciscintillabase.h>\n\n\nQT_BEGIN_NAMESPACE\nclass QAction;\nclass QImage;\nclass QIODevice;\nclass QMenu;\nclass QPoint;\nQT_END_NAMESPACE\n\nclass QsciCommandSet;\nclass QsciLexer;\nclass QsciStyle;\nclass QsciStyledText;\nclass QsciListBoxQt;\n\n\n//! \\brief The QsciScintilla class implements a higher level, more Qt-like,\n//! API to the Scintilla editor widget.\n//!\n//! QsciScintilla implements methods, signals and slots similar to those found\n//! in other Qt editor classes. It also provides a higher level interface to\n//! features specific to Scintilla such as syntax styling, call tips,\n//! auto-indenting and auto-completion than that provided by QsciScintillaBase.\nclass QSCINTILLA_EXPORT QsciScintilla : public QsciScintillaBase\n{\n    Q_OBJECT\n\npublic:\n    //! This enum defines the different auto-indentation styles.\n    enum {\n        //! A line is automatically indented to match the previous line.\n        AiMaintain = 0x01,\n\n        //! If the language supported by the current lexer has a specific start\n        //! of block character (e.g. { in C++), then a line that begins with\n        //! that character is indented as well as the lines that make up the\n        //! block.  It may be logically ored with AiClosing.\n        AiOpening = 0x02,\n\n        //! If the language supported by the current lexer has a specific end\n        //! of block character (e.g. } in C++), then a line that begins with\n        //! that character is indented as well as the lines that make up the\n        //! block.  It may be logically ored with AiOpening.\n        AiClosing = 0x04\n    };\n\n    //! This enum defines the different annotation display styles.\n    enum AnnotationDisplay {\n        //! Annotations are not displayed.\n        AnnotationHidden = ANNOTATION_HIDDEN,\n\n        //! Annotations are drawn left justified with no adornment.\n        AnnotationStandard = ANNOTATION_STANDARD,\n\n        //! Annotations are surrounded by a box.\n        AnnotationBoxed = ANNOTATION_BOXED,\n\n        //! Annotations are indented to match the text.\n        AnnotationIndented = ANNOTATION_INDENTED,\n    };\n\n    //! This enum defines the behavior if an auto-completion list contains a\n    //! single entry.\n    enum AutoCompletionUseSingle {\n        //! The single entry is not used automatically and the auto-completion\n        //! list is displayed.\n        AcusNever,\n\n        //! The single entry is used automatically when auto-completion is\n        //! explicitly requested (using autoCompleteFromAPIs() or\n        //! autoCompleteFromDocument()) but not when auto-completion is\n        //! triggered as the user types.\n        AcusExplicit,\n\n        //! The single entry is used automatically and the auto-completion list\n        //! is not displayed.\n        AcusAlways\n    };\n\n    //! This enum defines the different sources for auto-completion lists.\n    enum AutoCompletionSource {\n        //! No sources are used, ie. automatic auto-completion is disabled.\n        AcsNone,\n\n        //! The source is all available sources.\n        AcsAll,\n\n        //! The source is the current document.\n        AcsDocument,\n\n        //! The source is any installed APIs.\n        AcsAPIs\n    };\n\n    //! This enum defines the different brace matching modes.  The character\n    //! pairs {}, [] and () are treated as braces.  The Python lexer will also\n    //! match a : with the end of the corresponding indented block.\n    enum BraceMatch {\n        //! Brace matching is disabled.\n        NoBraceMatch,\n\n        //! Brace matching is enabled for a brace immediately before the\n        //! current position.\n        StrictBraceMatch,\n\n        //! Brace matching is enabled for a brace immediately before or after\n        //! the current position.\n        SloppyBraceMatch\n    };\n\n    //! This enum defines the different call tip positions.\n    enum CallTipsPosition {\n        //! Call tips are placed below the text.\n        CallTipsBelowText,\n\n        //! Call tips are placed above the text.\n        CallTipsAboveText,\n    };\n\n    //! This enum defines the different call tip styles.\n    enum CallTipsStyle {\n        //! Call tips are disabled.\n        CallTipsNone,\n\n        //! Call tips are displayed without a context.  A context is any scope\n        //! (e.g. a C++ namespace or a Python module) prior to the function\n        //! name.\n        CallTipsNoContext,\n\n        //! Call tips are displayed with a context only if the user hasn't\n        //! already implicitly identified the context using autocompletion.\n        //! Note that this style may not always be able to align the call tip\n        //! with the text being entered.\n        CallTipsNoAutoCompletionContext,\n\n        //! Call tips are displayed with a context.  Note that this style\n        //! may not always be able to align the call tip with the text being\n        //! entered.\n        CallTipsContext\n    };\n\n    //! This enum defines the different edge modes for long lines.\n    enum EdgeMode {\n        //! Long lines are not marked.\n        EdgeNone = EDGE_NONE,\n\n        //! A vertical line is drawn at the column set by setEdgeColumn().\n        //! This is recommended for monospace fonts.\n        EdgeLine = EDGE_LINE,\n\n        //! The background color of characters after the column limit is\n        //! changed to the color set by setEdgeColor().  This is recommended\n        //! for proportional fonts.\n        EdgeBackground = EDGE_BACKGROUND,\n\n        //! Multiple vertical lines are drawn at the columns defined by\n        //! multiple calls to addEdgeColumn().\n        EdgeMultipleLines = EDGE_MULTILINE,\n    };\n\n    //! This enum defines the different end-of-line modes.\n    enum EolMode {\n        //! A carriage return/line feed as used on Windows systems.\n        EolWindows = SC_EOL_CRLF,\n\n        //! A line feed as used on Unix systems, including OS/X.\n        EolUnix = SC_EOL_LF,\n\n        //! A carriage return as used on Mac systems prior to OS/X.\n        EolMac = SC_EOL_CR\n    };\n\n    //! This enum defines the different styles for the folding margin.\n    enum FoldStyle {\n        //! Folding is disabled.\n        NoFoldStyle,\n\n        //! Plain folding style using plus and minus symbols.\n        PlainFoldStyle,\n\n        //! Circled folding style using circled plus and minus symbols.\n        CircledFoldStyle,\n\n        //! Boxed folding style using boxed plus and minus symbols.\n        BoxedFoldStyle,\n\n        //! Circled tree style using a flattened tree with circled plus and\n        //! minus symbols and rounded corners.\n        CircledTreeFoldStyle,\n\n        //! Boxed tree style using a flattened tree with boxed plus and minus\n        //! symbols and right-angled corners.\n        BoxedTreeFoldStyle\n    };\n\n    //! This enum defines the different indicator styles.\n    enum IndicatorStyle {\n        //! A single straight underline.\n        PlainIndicator = INDIC_PLAIN,\n\n        //! A squiggly underline that requires 3 pixels of descender space.\n        SquiggleIndicator = INDIC_SQUIGGLE,\n\n        //! A line of small T shapes.\n        TTIndicator = INDIC_TT,\n\n        //! Diagonal hatching.\n        DiagonalIndicator = INDIC_DIAGONAL,\n\n        //! Strike out.\n        StrikeIndicator = INDIC_STRIKE,\n\n        //! An indicator with no visual appearence.\n        HiddenIndicator = INDIC_HIDDEN,\n\n        //! A rectangle around the text.\n        BoxIndicator = INDIC_BOX,\n\n        //! A rectangle with rounded corners around the text with the interior\n        //! usually more transparent than the border.\n        RoundBoxIndicator = INDIC_ROUNDBOX,\n\n        //! A rectangle around the text with the interior usually more\n        //! transparent than the border.  It does not colour the top pixel of\n        //! the line so that indicators on contiguous lines are visually\n        //! distinct and disconnected.\n        StraightBoxIndicator = INDIC_STRAIGHTBOX,\n\n        //! A rectangle around the text with the interior usually more\n        //! transparent than the border.  Unlike StraightBoxIndicator it covers\n        //! the entire character area.\n        FullBoxIndicator = INDIC_FULLBOX,\n\n        //! A dashed underline.\n        DashesIndicator = INDIC_DASH,\n\n        //! A dotted underline.\n        DotsIndicator = INDIC_DOTS,\n\n        //! A squiggly underline that requires 2 pixels of descender space and\n        //! so will fit under smaller fonts.\n        SquiggleLowIndicator = INDIC_SQUIGGLELOW,\n\n        //! A dotted rectangle around the text with the interior usually more\n        //! transparent than the border.\n        DotBoxIndicator = INDIC_DOTBOX,\n\n        //! A version of SquiggleIndicator that uses a pixmap.  This is quicker\n        //! but may be of lower quality.\n        SquigglePixmapIndicator = INDIC_SQUIGGLEPIXMAP,\n\n        //! A thick underline typically used for the target during Asian\n        //! language input composition.\n        ThickCompositionIndicator = INDIC_COMPOSITIONTHICK,\n\n        //! A thin underline typically used for non-target ranges during Asian\n        //! language input composition.\n        ThinCompositionIndicator = INDIC_COMPOSITIONTHIN,\n\n        //! The color of the text is set to the color of the indicator's\n        //! foreground.\n        TextColorIndicator = INDIC_TEXTFORE,\n\n        //! A triangle below the start of the indicator range.\n        TriangleIndicator = INDIC_POINT,\n\n        //! A triangle below the centre of the first character in the indicator\n        //! range.\n        TriangleCharacterIndicator = INDIC_POINTCHARACTER,\n\n        //! A vertical gradient between the indicator's foreground colour at\n        //! top to fully transparent at the bottom.\n        GradientIndicator = INDIC_GRADIENT,\n\n        //! A vertical gradient with the indicator's foreground colour in the\n        //! middle and fading to fully transparent at the top and bottom.\n        CentreGradientIndicator = INDIC_GRADIENTCENTRE,\n    };\n\n    //! This enum defines the different margin options.\n    enum {\n        //! Reset all margin options.\n        MoNone = SC_MARGINOPTION_NONE,\n\n        //! If this is set then only the first sub-line of a wrapped line will\n        //! be selected when clicking on a margin.\n        MoSublineSelect = SC_MARGINOPTION_SUBLINESELECT\n    };\n\n    //! This enum defines the different margin types.\n    enum MarginType {\n        //! The margin contains symbols, including those used for folding.\n        SymbolMargin = SC_MARGIN_SYMBOL,\n\n        //! The margin contains symbols and uses the default foreground color\n        //! as its background color.\n        SymbolMarginDefaultForegroundColor = SC_MARGIN_FORE,\n\n        //! The margin contains symbols and uses the default background color\n        //! as its background color.\n        SymbolMarginDefaultBackgroundColor = SC_MARGIN_BACK,\n\n        //! The margin contains line numbers.\n        NumberMargin = SC_MARGIN_NUMBER,\n\n        //! The margin contains styled text.\n        TextMargin = SC_MARGIN_TEXT,\n\n        //! The margin contains right justified styled text.\n        TextMarginRightJustified = SC_MARGIN_RTEXT,\n\n        //! The margin contains symbols and uses the color set by\n        //! setMarginBackgroundColor() as its background color.\n        SymbolMarginColor = SC_MARGIN_COLOUR,\n    };\n\n    //! This enum defines the different pre-defined marker symbols.\n    enum MarkerSymbol {\n        //! A circle.\n        Circle = SC_MARK_CIRCLE,\n\n        //! A rectangle.\n        Rectangle = SC_MARK_ROUNDRECT,\n\n        //! A triangle pointing to the right.\n        RightTriangle = SC_MARK_ARROW,\n\n        //! A smaller rectangle.\n        SmallRectangle = SC_MARK_SMALLRECT,\n\n        //! An arrow pointing to the right.\n        RightArrow = SC_MARK_SHORTARROW,\n\n        //! An invisible marker that allows code to track the movement\n        //! of lines.\n        Invisible = SC_MARK_EMPTY,\n\n        //! A triangle pointing down.\n        DownTriangle = SC_MARK_ARROWDOWN,\n\n        //! A drawn minus sign.\n        Minus = SC_MARK_MINUS,\n\n        //! A drawn plus sign.\n        Plus = SC_MARK_PLUS,\n\n        //! A vertical line drawn in the background colour.\n        VerticalLine = SC_MARK_VLINE,\n\n        //! A bottom left corner drawn in the background colour.\n        BottomLeftCorner = SC_MARK_LCORNER,\n\n        //! A vertical line with a centre right horizontal line drawn\n        //! in the background colour.\n        LeftSideSplitter = SC_MARK_TCORNER,\n\n        //! A drawn plus sign in a box.\n        BoxedPlus = SC_MARK_BOXPLUS,\n\n        //! A drawn plus sign in a connected box.\n        BoxedPlusConnected = SC_MARK_BOXPLUSCONNECTED,\n\n        //! A drawn minus sign in a box.\n        BoxedMinus = SC_MARK_BOXMINUS,\n\n        //! A drawn minus sign in a connected box.\n        BoxedMinusConnected = SC_MARK_BOXMINUSCONNECTED,\n\n        //! A rounded bottom left corner drawn in the background\n        //! colour.\n        RoundedBottomLeftCorner = SC_MARK_LCORNERCURVE,\n\n        //! A vertical line with a centre right curved line drawn in the\n        //! background colour.\n        LeftSideRoundedSplitter = SC_MARK_TCORNERCURVE,\n\n        //! A drawn plus sign in a circle.\n        CircledPlus = SC_MARK_CIRCLEPLUS,\n\n        //! A drawn plus sign in a connected box.\n        CircledPlusConnected = SC_MARK_CIRCLEPLUSCONNECTED,\n\n        //! A drawn minus sign in a circle.\n        CircledMinus = SC_MARK_CIRCLEMINUS,\n\n        //! A drawn minus sign in a connected circle.\n        CircledMinusConnected = SC_MARK_CIRCLEMINUSCONNECTED,\n\n        //! No symbol is drawn but the line is drawn with the same background\n        //! color as the marker's.\n        Background = SC_MARK_BACKGROUND,\n\n        //! Three drawn dots.\n        ThreeDots = SC_MARK_DOTDOTDOT,\n\n        //! Three drawn arrows pointing right.\n        ThreeRightArrows = SC_MARK_ARROWS,\n\n        //! A full rectangle (ie. the margin background) using the marker's\n        //! background color.\n        FullRectangle = SC_MARK_FULLRECT,\n\n        //! A left rectangle (ie. the left part of the margin background) using\n        //! the marker's background color.\n        LeftRectangle = SC_MARK_LEFTRECT,\n\n        //! No symbol is drawn but the line is drawn underlined using the\n        //! marker's background color.\n        Underline = SC_MARK_UNDERLINE,\n\n        //! A bookmark.\n        Bookmark = SC_MARK_BOOKMARK,\n    };\n\n    //! This enum defines how tab characters are drawn when whitespace is\n    //! visible.\n    enum TabDrawMode {\n        //! An arrow stretching to the tab stop.\n        TabLongArrow = SCTD_LONGARROW,\n\n        //! A horizontal line stretching to the tab stop.\n        TabStrikeOut = SCTD_STRIKEOUT,\n    };\n\n    //! This enum defines the different whitespace visibility modes.  When\n    //! whitespace is visible spaces are displayed as small centred dots and\n    //! tabs are displayed as light arrows pointing to the right.\n    enum WhitespaceVisibility {\n        //! Whitespace is invisible.\n        WsInvisible = SCWS_INVISIBLE,\n\n        //! Whitespace is always visible.\n        WsVisible = SCWS_VISIBLEALWAYS,\n\n        //! Whitespace is visible after the whitespace used for indentation.\n        WsVisibleAfterIndent = SCWS_VISIBLEAFTERINDENT,\n\n        //! Whitespace used for indentation is visible.\n        WsVisibleOnlyInIndent = SCWS_VISIBLEONLYININDENT,\n    };\n\n    //! This enum defines the different line wrap modes.\n    enum WrapMode {\n        //! Lines are not wrapped.\n        WrapNone = SC_WRAP_NONE,\n\n        //! Lines are wrapped at word boundaries.\n        WrapWord = SC_WRAP_WORD,\n\n        //! Lines are wrapped at character boundaries.\n        WrapCharacter = SC_WRAP_CHAR,\n\n        //! Lines are wrapped at whitespace boundaries.\n        WrapWhitespace = SC_WRAP_WHITESPACE,\n    };\n\n    //! This enum defines the different line wrap visual flags.\n    enum WrapVisualFlag {\n        //! No wrap flag is displayed.\n        WrapFlagNone,\n\n        //! A wrap flag is displayed by the text.\n        WrapFlagByText,\n\n        //! A wrap flag is displayed by the border.\n        WrapFlagByBorder,\n\n        //! A wrap flag is displayed in the line number margin.\n        WrapFlagInMargin\n    };\n\n    //! This enum defines the different line wrap indentation modes.\n    enum WrapIndentMode {\n        //! Wrapped sub-lines are indented by the amount set by\n        //! setWrapVisualFlags().\n        WrapIndentFixed = SC_WRAPINDENT_FIXED,\n\n        //! Wrapped sub-lines are indented by the same amount as the first\n        //! sub-line.\n        WrapIndentSame = SC_WRAPINDENT_SAME,\n\n        //! Wrapped sub-lines are indented by the same amount as the first\n        //! sub-line plus one more level of indentation.\n        WrapIndentIndented = SC_WRAPINDENT_INDENT,\n\n        //! Wrapped sub-lines are indented by the same amount as the first\n        //! sub-line plus two more level of indentation.\n        WrapIndentDeeplyIndented = SC_WRAPINDENT_DEEPINDENT\n    };\n\n    //! Construct an empty QsciScintilla with parent \\a parent.\n    QsciScintilla(QWidget *parent = 0);\n\n    //! Destroys the QsciScintilla instance.\n    virtual ~QsciScintilla();\n\n    //! Returns the API context, which is a list of words, before the position\n    //! \\a pos in the document.  The context can be used by auto-completion and\n    //! call tips to help to identify which API call the user is referring to.\n    //! In the default implementation the current lexer determines what\n    //! characters make up a word, and what characters determine the boundaries\n    //! of words (ie. the start characters).  If there is no current lexer then\n    //! the context will consist of a single word.  On return \\a context_start\n    //! will contain the position in the document of the start of the context\n    //! and \\a last_word_start will contain the position in the document of the\n    //! start of the last word of the context.\n    virtual QStringList apiContext(int pos, int &context_start,\n            int &last_word_start);\n\n    //! Annotate the line \\a line with the text \\a text using the style number\n    //! \\a style.\n    void annotate(int line, const QString &text, int style);\n\n    //! Annotate the line \\a line with the text \\a text using the style \\a\n    //! style.\n    void annotate(int line, const QString &text, const QsciStyle &style);\n\n    //! Annotate the line \\a line with the styled text \\a text.\n    void annotate(int line, const QsciStyledText &text);\n\n    //! Annotate the line \\a line with the list of styled text \\a text.\n    void annotate(int line, const QList<QsciStyledText> &text);\n\n    //! Returns the annotation on line \\a line, if any.\n    QString annotation(int line) const;\n\n    //! Returns the display style for annotations.\n    //!\n    //! \\sa setAnnotationDisplay()\n    AnnotationDisplay annotationDisplay() const;\n\n    //! The annotations on line \\a line are removed.  If \\a line is negative\n    //! then all annotations are removed.\n    void clearAnnotations(int line = -1);\n\n    //! Returns true if auto-completion lists are case sensitive.\n    //!\n    //! \\sa setAutoCompletionCaseSensitivity()\n    bool autoCompletionCaseSensitivity() const;\n\n    //! Returns true if auto-completion fill-up characters are enabled.\n    //!\n    //! \\sa setAutoCompletionFillups(), setAutoCompletionFillupsEnabled()\n    bool autoCompletionFillupsEnabled() const;\n\n    //! Returns true if the rest of the word to the right of the current cursor\n    //! is removed when an item from an auto-completion list is selected.\n    //!\n    //! \\sa setAutoCompletionReplaceWord()\n    bool autoCompletionReplaceWord() const;\n\n    //! Returns true if the only item in an auto-completion list with a single\n    //! entry is automatically used and the list not displayed.  Note that this\n    //! is deprecated and autoCompletionUseSingle() should be used instead.\n    //!\n    //! \\sa setAutoCompletionShowSingle()\n    bool autoCompletionShowSingle() const;\n\n    //! Returns the current source for the auto-completion list when it is\n    //! being displayed automatically as the user types.\n    //!\n    //! \\sa setAutoCompletionSource()\n    AutoCompletionSource autoCompletionSource() const {return acSource;}\n\n    //! Returns the current threshold for the automatic display of the\n    //! auto-completion list as the user types.\n    //!\n    //! \\sa setAutoCompletionThreshold()\n    int autoCompletionThreshold() const {return acThresh;}\n\n    //! Returns the current behavior when an auto-completion list contains a\n    //! single entry.\n    //!\n    //! \\sa setAutoCompletionUseSingle()\n    AutoCompletionUseSingle autoCompletionUseSingle() const;\n\n    //! Returns true if auto-indentation is enabled.\n    //!\n    //! \\sa setAutoIndent()\n    bool autoIndent() const {return autoInd;}\n\n    //! Returns true if the backspace key unindents a line instead of deleting\n    //! a character.  The default is false.\n    //!\n    //! \\sa setBackspaceUnindents(), tabIndents(), setTabIndents()\n    bool backspaceUnindents() const;\n\n    //! Mark the beginning of a sequence of actions that can be undone by a\n    //! single call to undo().\n    //!\n    //! \\sa endUndoAction(), undo()\n    void beginUndoAction();\n\n    //! Returns the brace matching mode.\n    //!\n    //! \\sa setBraceMatching()\n    BraceMatch braceMatching() const {return braceMode;}\n\n    //! Returns the encoded text between positions \\a start and \\a end.  This\n    //! is typically used by QsciLexerCustom::styleText().\n    //!\n    //! \\sa text()\n    QByteArray bytes(int start, int end) const;\n\n    //! Returns the current call tip position.\n    //!\n    //! \\sa setCallTipsPosition()\n    CallTipsPosition callTipsPosition() const {return call_tips_position;}\n\n    //! Returns the current call tip style.\n    //!\n    //! \\sa setCallTipsStyle()\n    CallTipsStyle callTipsStyle() const {return call_tips_style;}\n\n    //! Returns the maximum number of call tips that are displayed.\n    //!\n    //! \\sa setCallTipsVisible()\n    int callTipsVisible() const {return maxCallTips;}\n\n    //! Cancel any previous call to findFirst(), findFirstInSelection() or\n    //! findNext() so that replace() does nothing.\n    void cancelFind();\n\n    //! Cancel any current auto-completion or user defined list.\n    void cancelList();\n\n    //! Returns true if the current language lexer is case sensitive.  If there\n    //! is no current lexer then true is returned.\n    bool caseSensitive() const;\n\n    //! Clear all current folds, i.e. ensure that all lines are displayed\n    //! unfolded.\n    //!\n    //! \\sa setFolding()\n    void clearFolds();\n\n    //! Clears the range of text with indicator \\a indicatorNumber starting at\n    //! position \\a indexFrom in line \\a lineFrom and finishing at position\n    //! \\a indexTo in line \\a lineTo.\n    //!\n    //! \\sa fillIndicatorRange()\n    void clearIndicatorRange(int lineFrom, int indexFrom, int lineTo,\n            int indexTo, int indicatorNumber);\n\n    //! Clear all registered images.\n    //!\n    //! \\sa registerImage()\n    void clearRegisteredImages();\n\n    //! Returns the widget's text (ie. foreground) colour.\n    //!\n    //! \\sa setColor()\n    QColor color() const;\n\n    //! Returns a list of the line numbers that have contracted folds.  This is\n    //! typically used to save the fold state of a document.\n    //!\n    //! \\sa setContractedFolds()\n    QList<int> contractedFolds() const;\n\n    //! All the lines of the text have their end-of-lines converted to mode\n    //! \\a mode.\n    //!\n    //! \\sa eolMode(), setEolMode()\n    void convertEols(EolMode mode);\n\n    //! Create the standard context menu which is shown when the user clicks\n    //! with the right mouse button.  It is called from contextMenuEvent().\n    //! The menu's ownership is transferred to the caller.\n    QMenu *createStandardContextMenu();\n\n    //! Returns the attached document.\n    //!\n    //! \\sa setDocument()\n    QsciDocument document() const {return doc;}\n\n    //! Mark the end of a sequence of actions that can be undone by a single\n    //! call to undo().\n    //!\n    //! \\sa beginUndoAction(), undo()\n    void endUndoAction();\n\n    //! Returns the color of the marker used to show that a line has exceeded\n    //! the length set by setEdgeColumn().\n    //!\n    //! \\sa setEdgeColor(), \\sa setEdgeColumn\n    QColor edgeColor() const;\n\n    //! Returns the number of the column after which lines are considered to be\n    //! long.\n    //!\n    //! \\sa setEdgeColumn()\n    int edgeColumn() const;\n\n    //! Returns the edge mode which determines how long lines are marked.\n    //!\n    //! \\sa setEdgeMode()\n    EdgeMode edgeMode() const;\n\n    //! Set the default font.  This has no effect if a language lexer has been\n    //! set.\n    void setFont(const QFont &f);\n\n    //! Returns the end-of-line mode.\n    //!\n    //! \\sa setEolMode()\n    EolMode eolMode() const;\n\n    //! Returns the visibility of end-of-lines.\n    //!\n    //! \\sa setEolVisibility()\n    bool eolVisibility() const;\n\n    //! Returns the extra space added to the height of a line above the\n    //! baseline of the text.\n    //!\n    //! \\sa setExtraAscent(), extraDescent()\n    int extraAscent() const;\n\n    //! Returns the extra space added to the height of a line below the\n    //! baseline of the text.\n    //!\n    //! \\sa setExtraDescent(), extraAscent()\n    int extraDescent() const;\n\n    //! Fills the range of text with indicator \\a indicatorNumber starting at\n    //! position \\a indexFrom in line \\a lineFrom and finishing at position\n    //! \\a indexTo in line \\a lineTo.\n    //!\n    //! \\sa clearIndicatorRange()\n    void fillIndicatorRange(int lineFrom, int indexFrom, int lineTo,\n            int indexTo, int indicatorNumber);\n\n    //! Find the first occurrence of the string \\a expr and return true if\n    //! \\a expr was found, otherwise returns false.  If \\a expr is found it\n    //! becomes the current selection.\n    //!\n    //! If \\a re is true then \\a expr is interpreted as a regular expression\n    //! rather than a simple string.\n    //!\n    //! If \\a cs is true then the search is case sensitive.\n    //!\n    //! If \\a wo is true then the search looks for whole word matches only,\n    //! otherwise it searches for any matching text.\n    //!\n    //! If \\a wrap is true then the search wraps around the end of the text.\n    //!\n    //! If \\a forward is true (the default) then the search is forward from the\n    //! starting position to the end of the text, otherwise it is backwards to\n    //! the beginning of the text. \n    //!\n    //! If either \\a line or \\a index are negative (the default) then the\n    //! search begins from the current cursor position.  Otherwise the search\n    //! begins at position \\a index of line \\a line.\n    //!\n    //! If \\a show is true (the default) then any text found is made visible\n    //! (ie. it is unfolded).\n    //!\n    //! If \\a posix is true then a regular expression is treated in a more\n    //! POSIX compatible manner by interpreting bare ( and ) as tagged sections\n    //! rather than \\( and \\).\n    //!\n    //! If \\a cxx11 is true then a regular expression is treated as a Cxx11\n    //! regular expression.\n    //!\n    //! \\sa cancelFind(), findFirstInSelection(), findNext(), replace()\n    virtual bool findFirst(const QString &expr, bool re, bool cs, bool wo,\n            bool wrap, bool forward = true, int line = -1, int index = -1,\n            bool show = true, bool posix = false, bool cxx11 = false);\n\n    //! Find the first occurrence of the string \\a expr in the current\n    //! selection and return true if \\a expr was found, otherwise returns\n    //! false.  If \\a expr is found it becomes the current selection.  The\n    //! original selection is restored when a subsequent call to findNext()\n    //! returns false.\n    //!\n    //! If \\a re is true then \\a expr is interpreted as a regular expression\n    //! rather than a simple string.\n    //!\n    //! If \\a cs is true then the search is case sensitive.\n    //!\n    //! If \\a wo is true then the search looks for whole word matches only,\n    //! otherwise it searches for any matching text.\n    //!\n    //! If \\a forward is true (the default) then the search is forward from the\n    //! start to the end of the selection, otherwise it is backwards from the\n    //! end to the start of the selection.\n    //!\n    //! If \\a show is true (the default) then any text found is made visible\n    //! (ie. it is unfolded).\n    //!\n    //! If \\a posix is true then a regular expression is treated in a more\n    //! POSIX compatible manner by interpreting bare ( and ) as tagged sections\n    //! rather than \\( and \\).\n    //!\n    //! If \\a cxx11 is true then a regular expression is treated as a Cxx11\n    //! regular expression.\n    //!\n    //! \\sa cancelFind(), findFirst(), findNext(), replace()\n    virtual bool findFirstInSelection(const QString &expr, bool re, bool cs,\n            bool wo, bool forward = true, bool show = true,\n            bool posix = false, bool cxx11 = false);\n\n    //! Find the next occurence of the string found using findFirst() or\n    //! findFirstInSelection().\n    //!\n    //! \\sa cancelFind(), findFirst(), findFirstInSelection(), replace()\n    virtual bool findNext();\n\n    //! Find a brace and it's match.  \\a brace is updated with the position of\n    //! the brace and will be -1 if there is none.  \\a is updated with the\n    //! position of the matching brace and will be -1 if there is none.\n    //! \\a mode specifies how braces are matched.  true is returned if the\n    //! current position is inside a pair of braces.\n    bool findMatchingBrace(long &brace, long &other, BraceMatch mode);\n\n    //! Returns the number of the first visible line.\n    //!\n    //! \\sa setFirstVisibleLine()\n    int firstVisibleLine() const;\n\n    //! Returns the current folding style.\n    //!\n    //! \\sa setFolding()\n    FoldStyle folding() const {return fold;}\n\n    //! Sets \\a *line and \\a *index to the line and index of the cursor.\n    //!\n    //! \\sa setCursorPosition()\n    void getCursorPosition(int *line, int *index) const;\n\n    //! If there is a selection, \\a *lineFrom is set to the line number in\n    //! which the selection begins and \\a *lineTo is set to the line number in\n    //! which the selection ends.  (They could be the same.)  \\a *indexFrom is\n    //! set to the index at which the selection begins within \\a *lineFrom, and\n    //! \\a *indexTo is set to the index at which the selection ends within\n    //! \\a *lineTo.  If there is no selection, \\a *lineFrom, \\a *indexFrom,\n    //! \\a *lineTo and \\a *indexTo are all set to -1. \n    //!\n    //! \\sa setSelection()\n    void getSelection(int *lineFrom, int *indexFrom, int *lineTo,\n            int *indexTo) const;\n\n    //! Returns true if some text is selected.\n    //!\n    //! \\sa selectedText()\n    bool hasSelectedText() const {return selText;}\n\n    //! Returns the number of characters that line \\a line is indented by.\n    //!\n    //! \\sa setIndentation()\n    int indentation(int line) const;\n\n    //! Returns true if the display of indentation guides is enabled.\n    //!\n    //! \\sa setIndentationGuides()\n    bool indentationGuides() const;\n\n    //! Returns true if indentations are created using tabs and spaces, rather\n    //! than just spaces.  The default is true.\n    //!\n    //! \\sa setIndentationsUseTabs()\n    bool indentationsUseTabs() const;\n\n    //! Returns the indentation width in characters.  The default is 0 which\n    //! means that the value returned by tabWidth() is actually used.\n    //!\n    //! \\sa setIndentationWidth(), tabWidth()\n    int indentationWidth() const;\n\n    //! Define a type of indicator using the style \\a style with the indicator\n    //! number \\a indicatorNumber.  If \\a indicatorNumber is -1 then the\n    //! indicator number is automatically allocated.  The indicator number is\n    //! returned or -1 if too many types of indicator have been defined.\n    //!\n    //! Indicators are used to display additional information over the top of\n    //! styling.  They can be used to show, for example, syntax errors,\n    //! deprecated names and bad indentation by drawing lines under text or\n    //! boxes around text.\n    //!\n    //! There may be up to 32 types of indicator defined at a time.  The first\n    //! 8 are normally used by lexers.  By default indicator number 0 is a\n    //! dark green SquiggleIndicator, 1 is a blue TTIndicator, and 2 is a red\n    //! PlainIndicator.\n    int indicatorDefine(IndicatorStyle style, int indicatorNumber = -1);\n\n    //! Returns true if the indicator \\a indicatorNumber is drawn under the\n    //! text (i.e. in the background).  The default is false.\n    //!\n    //! \\sa setIndicatorDrawUnder()\n    bool indicatorDrawUnder(int indicatorNumber) const;\n\n    //! Returns true if a call tip is currently active.\n    bool isCallTipActive() const;\n\n    //! Returns true if an auto-completion or user defined list is currently\n    //! active.\n    bool isListActive() const;\n\n    //! Returns true if the text has been modified.\n    //!\n    //! \\sa setModified(), modificationChanged()\n    bool isModified() const;\n\n    //! Returns true if the text edit is read-only.\n    //!\n    //! \\sa setReadOnly()\n    bool isReadOnly() const;\n\n    //! Returns true if there is something that can be redone.\n    //!\n    //! \\sa redo()\n    bool isRedoAvailable() const;\n\n    //! Returns true if there is something that can be undone.\n    //!\n    //! \\sa undo()\n    bool isUndoAvailable() const;\n\n    //! Returns true if text is interpreted as being UTF8 encoded.  The default\n    //! is to interpret the text as Latin1 encoded.\n    //!\n    //! \\sa setUtf8()\n    bool isUtf8() const;\n\n    //! Returns true if character \\a ch is a valid word character.\n    //!\n    //! \\sa wordCharacters()\n    bool isWordCharacter(char ch) const;\n\n    //! Returns the line which is at \\a point pixel coordinates or -1 if there\n    //! is no line at that point.\n    int lineAt(const QPoint &point) const;\n\n    //! QScintilla uses the combination of a line number and a character index\n    //! from the start of that line to specify the position of a character\n    //! within the text.  The underlying Scintilla instead uses a byte index\n    //! from the start of the text.  This will convert the \\a position byte\n    //! index to the \\a *line line number and \\a *index character index.\n    //!\n    //! \\sa positionFromLineIndex()\n    void lineIndexFromPosition(int position, int *line, int *index) const;\n\n    //! Returns the length of line \\a line int bytes or -1 if there is no such\n    //! line.  In order to get the length in characters use text(line).length().\n    int lineLength(int line) const;\n\n    //! Returns the number of lines of text.\n    int lines() const;\n\n    //! Returns the length of the text edit's text in bytes.  In order to get\n    //! the length in characters use text().length().\n    int length() const;\n\n    //! Returns the current language lexer used to style text.  If it is 0 then\n    //! syntax styling is disabled.\n    //!\n    //! \\sa setLexer()\n    QsciLexer *lexer() const;\n\n    //! Returns the background color of margin \\a margin.\n    //!\n    //! \\sa setMarginBackgroundColor()\n    QColor marginBackgroundColor(int margin) const;\n\n    //! Returns true if line numbers are enabled for margin \\a margin.\n    //!\n    //! \\sa setMarginLineNumbers(), marginType(), SCI_GETMARGINTYPEN\n    bool marginLineNumbers(int margin) const;\n\n    //! Returns the marker mask of margin \\a margin.\n    //!\n    //! \\sa setMarginMask(), QsciMarker, SCI_GETMARGINMASKN\n    int marginMarkerMask(int margin) const;\n\n    //! Returns the margin options.  The default is MoNone.\n    //!\n    //! \\sa setMarginOptions(), MoNone, MoSublineSelect.\n    int marginOptions() const;\n\n    //! Returns true if margin \\a margin is sensitive to mouse clicks.\n    //!\n    //! \\sa setMarginSensitivity(), marginClicked(), SCI_GETMARGINTYPEN\n    bool marginSensitivity(int margin) const;\n\n    //! Returns the type of margin \\a margin.\n    //!\n    //! \\sa setMarginType(), SCI_GETMARGINTYPEN\n    MarginType marginType(int margin) const;\n\n    //! Returns the width in pixels of margin \\a margin.\n    //!\n    //! \\sa setMarginWidth(), SCI_GETMARGINWIDTHN\n    int marginWidth(int margin) const;\n\n    //! Returns the number of margins.\n    //!\n    //! \\sa setMargins()\n    int margins() const;\n\n    //! Define a type of marker using the symbol \\a sym with the marker number\n    //! \\a markerNumber.  If \\a markerNumber is -1 then the marker number is\n    //! automatically allocated.  The marker number is returned or -1 if too\n    //! many types of marker have been defined.\n    //!\n    //! Markers are small geometric symbols and characters used, for example,\n    //! to indicate the current line or, in debuggers, to indicate breakpoints.\n    //! If a margin has a width of 0 then its markers are not drawn, but their\n    //! background colours affect the background colour of the corresponding\n    //! line of text.\n    //!\n    //! There may be up to 32 types of marker defined at a time and each line\n    //! of text has a set of marker instances associated with it.  Markers are\n    //! drawn according to their numerical identifier.  Markers try to move\n    //! with their text by tracking where the start of their line moves to.\n    //! For example, when a line is deleted its markers are added to previous\n    //! line's markers.\n    //!\n    //! Each marker type is identified by a marker number.  Each instance of a\n    //! marker is identified by a marker handle.\n    int markerDefine(MarkerSymbol sym, int markerNumber = -1);\n\n    //! Define a marker using the character \\a ch with the marker number\n    //! \\a markerNumber.  If \\a markerNumber is -1 then the marker number is\n    //! automatically allocated.  The marker number is returned or -1 if too\n    //! many markers have been defined.\n    int markerDefine(char ch, int markerNumber = -1);\n\n    //! Define a marker using a copy of the pixmap \\a pm with the marker number\n    //! \\a markerNumber.  If \\a markerNumber is -1 then the marker number is\n    //! automatically allocated.  The marker number is returned or -1 if too\n    //! many markers have been defined.\n    int markerDefine(const QPixmap &pm, int markerNumber = -1);\n\n    //! Define a marker using a copy of the image \\a im with the marker number\n    //! \\a markerNumber.  If \\a markerNumber is -1 then the marker number is\n    //! automatically allocated.  The marker number is returned or -1 if too\n    //! many markers have been defined.\n    int markerDefine(const QImage &im, int markerNumber = -1);\n\n    //! Add an instance of marker number \\a markerNumber to line number\n    //! \\a linenr.  A handle for the marker is returned which can be used to\n    //! track the marker's position, or -1 if the \\a markerNumber was invalid.\n    //!\n    //! \\sa markerDelete(), markerDeleteAll(), markerDeleteHandle()\n    int markerAdd(int linenr, int markerNumber);\n\n    //! Returns the 32 bit mask of marker numbers at line number \\a linenr.\n    //!\n    //! \\sa markerAdd()\n    unsigned markersAtLine(int linenr) const;\n\n    //! Delete all markers with the marker number \\a markerNumber in the line\n    //! \\a linenr.  If \\a markerNumber is -1 then delete all markers from line\n    //! \\a linenr.\n    //!\n    //! \\sa markerAdd(), markerDeleteAll(), markerDeleteHandle()\n    void markerDelete(int linenr, int markerNumber = -1);\n\n    //! Delete the all markers with the marker number \\a markerNumber.  If\n    //! \\a markerNumber is -1 then delete all markers.\n    //!\n    //! \\sa markerAdd(), markerDelete(), markerDeleteHandle()\n    void markerDeleteAll(int markerNumber = -1);\n\n    //! Delete the the marker instance with the marker handle \\a mhandle.\n    //!\n    //! \\sa markerAdd(), markerDelete(), markerDeleteAll()\n    void markerDeleteHandle(int mhandle);\n\n    //! Return the line number that contains the marker instance with the\n    //! marker handle \\a mhandle.\n    int markerLine(int mhandle) const;\n\n    //! Return the number of the next line to contain at least one marker from\n    //! a 32 bit mask of markers.  \\a linenr is the line number to start the\n    //! search from.  \\a mask is the mask of markers to search for.\n    //!\n    //! \\sa markerFindPrevious()\n    int markerFindNext(int linenr, unsigned mask) const;\n\n    //! Return the number of the previous line to contain at least one marker\n    //! from a 32 bit mask of markers.  \\a linenr is the line number to start\n    //! the search from.  \\a mask is the mask of markers to search for.\n    //!\n    //! \\sa markerFindNext()\n    int markerFindPrevious(int linenr, unsigned mask) const;\n\n    //! Returns true if text entered by the user will overwrite existing text.\n    //!\n    //! \\sa setOverwriteMode()\n    bool overwriteMode() const;\n\n    //! Returns the widget's paper (ie. background) colour.\n    //!\n    //! \\sa setPaper()\n    QColor paper() const;\n\n    //! QScintilla uses the combination of a line number and a character index\n    //! from the start of that line to specify the position of a character\n    //! within the text.  The underlying Scintilla instead uses a byte index\n    //! from the start of the text.  This will return the byte index\n    //! corresponding to the \\a line line number and \\a index character index.\n    //!\n    //! \\sa lineIndexFromPosition()\n    int positionFromLineIndex(int line, int index) const;\n\n    //! Reads the current document from the \\a io device and returns true if\n    //! there was no error.\n    //!\n    //! \\sa write()\n    bool read(QIODevice *io);\n\n    //! Recolours the document between the \\a start and \\a end positions.\n    //! \\a start defaults to the start of the document and \\a end defaults to\n    //! the end of the document.\n    virtual void recolor(int start = 0, int end = -1);\n\n    //! Register an image \\a pm with ID \\a id.  Registered images can be\n    //! displayed in auto-completion lists.\n    //!\n    //! \\sa clearRegisteredImages(), QsciLexer::apiLoad()\n    void registerImage(int id, const QPixmap &pm);\n\n    //! Register an image \\a im with ID \\a id.  Registered images can be\n    //! displayed in auto-completion lists.\n    //!\n    //! \\sa clearRegisteredImages(), QsciLexer::apiLoad()\n    void registerImage(int id, const QImage &im);\n\n    //! Replace the current selection, set by a previous call to findFirst(),\n    //! findFirstInSelection() or findNext(), with \\a replaceStr.\n    //!\n    //! \\sa cancelFind(), findFirst(), findFirstInSelection(), findNext()\n    virtual void replace(const QString &replaceStr);\n\n    //! Reset the fold margin colours to their defaults.\n    //!\n    //! \\sa setFoldMarginColors()\n    void resetFoldMarginColors();\n\n    //! Resets the background colour of an active hotspot area to the default.\n    //!\n    //! \\sa setHotspotBackgroundColor(), resetHotspotForegroundColor()\n    void resetHotspotBackgroundColor();\n\n    //! Resets the foreground colour of an active hotspot area to the default.\n    //!\n    //! \\sa setHotspotForegroundColor(), resetHotspotBackgroundColor()\n    void resetHotspotForegroundColor();\n\n    //! Gets the assumed document width in pixels.\n    //!\n    //! \\sa setScrollWidth(), setScrollWidthTracking()\n    int scrollWidth() const;\n\n    //! Returns true if scroll width tracking is enabled.\n    //!\n    //! \\sa scrollWidth(), setScrollWidthTracking()\n    bool scrollWidthTracking() const;\n\n    //! The fold margin may be drawn as a one pixel sized checkerboard pattern\n    //! of two colours, \\a fore and \\a back.\n    //!\n    //! \\sa resetFoldMarginColors()\n    void setFoldMarginColors(const QColor &fore, const QColor &back);\n\n    //! Set the display style for annotations.  The default is\n    //! AnnotationStandard.\n    //!\n    //! \\sa annotationDisplay()\n    void setAnnotationDisplay(AnnotationDisplay display);\n\n    //! Enable the use of fill-up characters, either those explicitly set or\n    //! those set by a lexer.  By default, fill-up characters are disabled.\n    //!\n    //! \\sa autoCompletionFillupsEnabled(), setAutoCompletionFillups()\n    void setAutoCompletionFillupsEnabled(bool enabled);\n\n    //! A fill-up character is one that, when entered while an auto-completion\n    //! list is being displayed, causes the currently selected item from the\n    //! list to be added to the text followed by the fill-up character.\n    //! \\a fillups is the set of fill-up characters.  If a language lexer has\n    //! been set then this is ignored and the lexer defines the fill-up\n    //! characters.  The default is that no fill-up characters are set.\n    //!\n    //! \\sa autoCompletionFillupsEnabled(), setAutoCompletionFillupsEnabled()\n    void setAutoCompletionFillups(const char *fillups);\n\n    //! A word separator is a sequence of characters that, when entered, causes\n    //! the auto-completion list to be displayed.  If a language lexer has been\n    //! set then this is ignored and the lexer defines the word separators.\n    //! The default is that no word separators are set.\n    //!\n    //! \\sa setAutoCompletionThreshold()\n    void setAutoCompletionWordSeparators(const QStringList &separators);\n\n    //! Set the background colour of call tips to \\a col.  The default is\n    //! white.\n    void setCallTipsBackgroundColor(const QColor &col);\n\n    //! Set the foreground colour of call tips to \\a col.  The default is\n    //! mid-gray.\n    void setCallTipsForegroundColor(const QColor &col);\n\n    //! Set the highlighted colour of call tip text to \\a col.  The default is\n    //! dark blue.\n    void setCallTipsHighlightColor(const QColor &col);\n\n    //! Set the current call tip position.  The default is CallTipsBelowText.\n    //!\n    //! \\sa callTipsPosition()\n    void setCallTipsPosition(CallTipsPosition position);\n\n    //! Set the current call tip style.  The default is CallTipsNoContext.\n    //!\n    //! \\sa callTipsStyle()\n    void setCallTipsStyle(CallTipsStyle style);\n\n    //! Set the maximum number of call tips that are displayed to \\a nr.  If\n    //! the maximum number is 0 then all applicable call tips are displayed.\n    //! If the maximum number is -1 then one call tip will be displayed with up\n    //! and down arrows that allow the use to scroll through the full list.\n    //! The default is -1.\n    //!\n    //! \\sa callTipsVisible()\n    void setCallTipsVisible(int nr);\n\n    //! Sets each line in the \\a folds list of line numbers to be a contracted\n    //! fold.  This is typically used to restore the fold state of a document.\n    //!\n    //! \\sa contractedFolds()\n    void setContractedFolds(const QList<int> &folds);\n\n    //! Attach the document \\a document, replacing the currently attached\n    //! document.\n    //!\n    //! \\sa document()\n    void setDocument(const QsciDocument &document);\n\n    //! Add \\a colnr to the columns which are displayed with a vertical line.\n    //! The edge mode must be set to EdgeMultipleLines.\n    //!\n    //! \\sa clearEdgeColumns()\n    void addEdgeColumn(int colnr, const QColor &col);\n\n    //! Remove any columns added by previous calls to addEdgeColumn().\n    //!\n    //! \\sa addEdgeColumn()\n    void clearEdgeColumns();\n\n    //! Set the color of the marker used to show that a line has exceeded the\n    //! length set by setEdgeColumn().\n    //!\n    //! \\sa edgeColor(), \\sa setEdgeColumn\n    void setEdgeColor(const QColor &col);\n\n    //! Set the number of the column after which lines are considered to be\n    //! long.\n    //!\n    //! \\sa edgeColumn()\n    void setEdgeColumn(int colnr);\n\n    //! Set the edge mode which determines how long lines are marked.\n    //!\n    //! \\sa edgeMode()\n    void setEdgeMode(EdgeMode mode);\n\n    //! Set the number of the first visible line to \\a linenr.\n    //!\n    //! \\sa firstVisibleLine()\n    void setFirstVisibleLine(int linenr);\n\n    //! Enables or disables, according to \\a under, if the indicator\n    //! \\a indicatorNumber is drawn under or over the text (i.e. in the\n    //! background or foreground).  If \\a indicatorNumber is -1 then the state\n    //! of all indicators is set.\n    //!\n    //! \\sa indicatorDrawUnder()\n    void setIndicatorDrawUnder(bool under, int indicatorNumber = -1);\n\n    //! Set the foreground colour of indicator \\a indicatorNumber to \\a col.\n    //! If \\a indicatorNumber is -1 then the colour of all indicators is set.\n    void setIndicatorForegroundColor(const QColor &col, int indicatorNumber = -1);\n\n    //! Set the foreground colour of indicator \\a indicatorNumber to \\a col\n    //! when the mouse is over it or the caret moved into it.  If\n    //! \\a indicatorNumber is -1 then the colour of all indicators is set.\n    void setIndicatorHoverForegroundColor(const QColor &col, int indicatorNumber = -1);\n\n    //! Set the style of indicator \\a indicatorNumber to \\a style when the\n    //! mouse is over it or the caret moved into it.  If \\a indicatorNumber is\n    //! -1 then the style of all indicators is set.\n    void setIndicatorHoverStyle(IndicatorStyle style, int indicatorNumber = -1);\n\n    //! Set the outline colour of indicator \\a indicatorNumber to \\a col.\n    //! If \\a indicatorNumber is -1 then the colour of all indicators is set.\n    //! At the moment only the alpha value of the colour has any affect.\n    void setIndicatorOutlineColor(const QColor &col, int indicatorNumber = -1);\n\n    //! Sets the background color of margin \\a margin to \\a col.\n    //!\n    //! \\sa marginBackgroundColor()\n    void setMarginBackgroundColor(int margin, const QColor &col);\n\n    //! Set the margin options to \\a options.\n    //!\n    //! \\sa marginOptions(), MoNone, MoSublineSelect.\n    void setMarginOptions(int options);\n\n    //! Set the margin text of line \\a line with the text \\a text using the\n    //! style number \\a style.\n    void setMarginText(int line, const QString &text, int style);\n\n    //! Set the margin text of line \\a line with the text \\a text using the\n    //! style \\a style.\n    void setMarginText(int line, const QString &text, const QsciStyle &style);\n\n    //! Set the margin text of line \\a line with the styled text \\a text.\n    void setMarginText(int line, const QsciStyledText &text);\n\n    //! Set the margin text of line \\a line with the list of styled text \\a\n    //! text.\n    void setMarginText(int line, const QList<QsciStyledText> &text);\n\n    //! Set the type of margin \\a margin to type \\a type.\n    //!\n    //! \\sa marginType(), SCI_SETMARGINTYPEN\n    void setMarginType(int margin, MarginType type);\n\n    //! The margin text on line \\a line is removed.  If \\a line is negative\n    //! then all margin text is removed.\n    void clearMarginText(int line = -1);\n\n    //! Set the number of margins to \\a margins.\n    //!\n    //! \\sa margins()\n    void setMargins(int margins);\n\n    //! Set the background colour, including the alpha component, of marker\n    //! \\a markerNumber to \\a col.  If \\a markerNumber is -1 then the colour of\n    //! all markers is set.  The default is white.\n    //!\n    //! \\sa setMarkerForegroundColor()\n    void setMarkerBackgroundColor(const QColor &col, int markerNumber = -1);\n\n    //! Set the foreground colour of marker \\a markerNumber to \\a col.  If\n    //! \\a markerNumber is -1 then the colour of all markers is set.  The\n    //! default is black.\n    //!\n    //! \\sa setMarkerBackgroundColor()\n    void setMarkerForegroundColor(const QColor &col, int markerNumber = -1);\n\n    //! Set the background colour used to display matched braces to \\a col.  It\n    //! is ignored if an indicator is being used.  The default is white.\n    //!\n    //! \\sa setMatchedBraceForegroundColor(), setMatchedBraceIndicator()\n    void setMatchedBraceBackgroundColor(const QColor &col);\n\n    //! Set the foreground colour used to display matched braces to \\a col.  It\n    //! is ignored if an indicator is being used.  The default is red.\n    //!\n    //! \\sa setMatchedBraceBackgroundColor(), setMatchedBraceIndicator()\n    void setMatchedBraceForegroundColor(const QColor &col);\n\n    //! Set the indicator used to display matched braces to \\a indicatorNumber.\n    //! The default is not to use an indicator.\n    //!\n    //! \\sa resetMatchedBraceIndicator(), setMatchedBraceBackgroundColor()\n    void setMatchedBraceIndicator(int indicatorNumber);\n\n    //! Stop using an indicator to display matched braces.\n    //!\n    //! \\sa setMatchedBraceIndicator()\n    void resetMatchedBraceIndicator();\n\n    //! For performance, QScintilla does not measure the display width of the\n    //! document to determine the properties of the horizontal scroll bar.\n    //! Instead, an assumed width is used.  This sets the document width in\n    //! pixels assumed by QScintilla to \\a pixelWidth.  The default value is\n    //! 2000.\n    //!\n    //! \\sa scrollWidth(), setScrollWidthTracking()\n    void setScrollWidth(int pixelWidth);\n\n    //! If scroll width tracking is enabled then the scroll width is adjusted\n    //! to ensure that all of the lines currently displayed can be completely\n    //! scrolled.  This mode never adjusts the scroll width to be narrower.\n    //! This sets the scroll width tracking to \\a enabled.\n    //!\n    //! \\sa setScrollWidth(), scrollWidthTracking()\n    void setScrollWidthTracking(bool enabled);\n\n    //! Sets the mode used to draw tab characters when whitespace is visible to\n    //! \\a mode.  The default is to use an arrow.\n    //!\n    //! \\sa tabDrawMode()\n    void setTabDrawMode(TabDrawMode mode);\n\n    //! Set the background colour used to display unmatched braces to \\a col.\n    //! It is ignored if an indicator is being used.  The default is white.\n    //!\n    //! \\sa setUnmatchedBraceForegroundColor(), setUnmatchedBraceIndicator()\n    void setUnmatchedBraceBackgroundColor(const QColor &col);\n\n    //! Set the foreground colour used to display unmatched braces to \\a col.\n    //! It is ignored if an indicator is being used.  The default is blue.\n    //!\n    //! \\sa setUnmatchedBraceBackgroundColor(), setUnmatchedBraceIndicator()\n    void setUnmatchedBraceForegroundColor(const QColor &col);\n\n    //! Set the indicator used to display unmatched braces to\n    //! \\a indicatorNumber.  The default is not to use an indicator.\n    //!\n    //! \\sa resetUnmatchedBraceIndicator(), setUnmatchedBraceBackgroundColor()\n    void setUnmatchedBraceIndicator(int indicatorNumber);\n\n    //! Stop using an indicator to display unmatched braces.\n    //!\n    //! \\sa setUnmatchedBraceIndicator()\n    void resetUnmatchedBraceIndicator();\n\n    //! Set the visual flags displayed when a line is wrapped.  \\a endFlag\n    //! determines if and where the flag at the end of a line is displayed.\n    //! \\a startFlag determines if and where the flag at the start of a line is\n    //! displayed.  \\a indent is the number of characters a wrapped line is\n    //! indented by.  By default no visual flags are displayed.\n    void setWrapVisualFlags(WrapVisualFlag endFlag,\n            WrapVisualFlag startFlag = WrapFlagNone, int indent = 0);\n\n    //! Returns the selected text or an empty string if there is no currently\n    //! selected text.\n    //!\n    //! \\sa hasSelectedText()\n    QString selectedText() const;\n\n    //! Returns whether or not the selection is drawn up to the right hand\n    //! border.\n    //!\n    //! \\sa setSelectionToEol()\n    bool selectionToEol() const;\n\n    //! Sets the background colour of an active hotspot area to \\a col.\n    //!\n    //! \\sa resetHotspotBackgroundColor(), setHotspotForegroundColor()\n    void setHotspotBackgroundColor(const QColor &col);\n\n    //! Sets the foreground colour of an active hotspot area to \\a col.\n    //!\n    //! \\sa resetHotspotForegroundColor(), setHotspotBackgroundColor()\n    void setHotspotForegroundColor(const QColor &col);\n\n    //! Enables or disables, according to \\a enable, the underlining of an\n    //! active hotspot area.  The default is false.\n    void setHotspotUnderline(bool enable);\n\n    //! Enables or disables, according to \\a enable, the wrapping of a hotspot\n    //! area to following lines.  The default is true.\n    void setHotspotWrap(bool enable);\n\n    //! Sets whether or not the selection is drawn up to the right hand border.\n    //! \\a filled is set if the selection is drawn to the border.\n    //!\n    //! \\sa selectionToEol()\n    void setSelectionToEol(bool filled);\n\n    //! Sets the extra space added to the height of a line above the baseline\n    //! of the text to \\a extra.\n    //!\n    //! \\sa extraAscent(), setExtraDescent()\n    void setExtraAscent(int extra);\n\n    //! Sets the extra space added to the height of a line below the baseline\n    //! of the text to \\a extra.\n    //!\n    //! \\sa extraDescent(), setExtraAscent()\n    void setExtraDescent(int extra);\n\n    //! Text entered by the user will overwrite existing text if \\a overwrite\n    //! is true.\n    //!\n    //! \\sa overwriteMode()\n    void setOverwriteMode(bool overwrite);\n\n    //! Sets the background colour of visible whitespace to \\a col.  If \\a col\n    //! is an invalid color (the default) then the color specified by the\n    //! current lexer is used.\n    void setWhitespaceBackgroundColor(const QColor &col);\n\n    //! Sets the foreground colour of visible whitespace to \\a col.  If \\a col\n    //! is an invalid color (the default) then the color specified by the\n    //! current lexer is used.\n    void setWhitespaceForegroundColor(const QColor &col);\n\n    //! Sets the size of the dots used to represent visible whitespace.\n    //!\n    //! \\sa whitespaceSize()\n    void setWhitespaceSize(int size);\n\n    //! Sets the line wrap indentation mode to \\a mode.  The default is\n    //! WrapIndentFixed.\n    //!\n    //! \\sa wrapIndentMode()\n    void setWrapIndentMode(WrapIndentMode mode);\n\n    //! Displays a user defined list which can be interacted with like an\n    //! auto-completion list.  \\a id is an identifier for the list which is\n    //! passed as an argument to the userListActivated() signal and must be at\n    //! least 1.  \\a list is the text with which the list is populated.\n    //!\n    //! \\sa cancelList(), isListActive(), userListActivated()\n    void showUserList(int id, const QStringList &list);\n\n    //! The standard command set is returned.\n    QsciCommandSet *standardCommands() const {return stdCmds;}\n\n    //! Returns the mode used to draw tab characters when whitespace is\n    //! visible.\n    //!\n    //! \\sa setTabDrawMode()\n    TabDrawMode tabDrawMode() const;\n\n    //! Returns true if the tab key indents a line instead of inserting a tab\n    //! character.  The default is true.\n    //!\n    //! \\sa setTabIndents(), backspaceUnindents(), setBackspaceUnindents()\n    bool tabIndents() const;\n\n    //! Returns the tab width in characters.  The default is 8.\n    //!\n    //! \\sa setTabWidth()\n    int tabWidth() const;\n\n    //! Returns the text of the current document.\n    //!\n    //! \\sa setText()\n    QString text() const;\n\n    //! \\overload\n    //!\n    //! Returns the text of line \\a line.\n    //!\n    //! \\sa setText()\n    QString text(int line) const;\n\n    //! \\overload\n    //!\n    //! Returns the text between positions \\a start and \\a end.  This is\n    //! typically used by QsciLexerCustom::styleText().\n    //!\n    //! \\sa bytes(), setText()\n    QString text(int start, int end) const;\n\n    //! Returns the height in pixels of the text in line number \\a linenr.\n    int textHeight(int linenr) const;\n\n    //! Returns the size of the dots used to represent visible whitespace.\n    //!\n    //! \\sa setWhitespaceSize()\n    int whitespaceSize() const;\n\n    //! Returns the visibility of whitespace.\n    //!\n    //! \\sa setWhitespaceVisibility()\n    WhitespaceVisibility whitespaceVisibility() const;\n\n    //! Returns the word at the \\a line line number and \\a index character\n    //! index.\n    QString wordAtLineIndex(int line, int index) const;\n\n    //! Returns the word at the \\a point pixel coordinates.\n    QString wordAtPoint(const QPoint &point) const;\n\n    //! Returns the set of valid word character as defined by the current\n    //! language lexer.  If there is no current lexer then the set contains an\n    //! an underscore, numbers and all upper and lower case alphabetic\n    //! characters.\n    //!\n    //! \\sa isWordCharacter()\n    const char *wordCharacters() const;\n\n    //! Returns the line wrap mode.\n    //!\n    //! \\sa setWrapMode()\n    WrapMode wrapMode() const;\n\n    //! Returns the line wrap indentation mode.\n    //!\n    //! \\sa setWrapIndentMode()\n    WrapIndentMode wrapIndentMode() const;\n\n    //! Writes the current document to the \\a io device and returns true if\n    //! there was no error.\n    //!\n    //! \\sa read()\n    bool write(QIODevice *io) const;\n\npublic slots:\n    //! Appends the text \\a text to the end of the text edit.  Note that the\n    //! undo/redo history is cleared by this function.\n    virtual void append(const QString &text);\n\n    //! Display an auto-completion list based on any installed APIs, the\n    //! current contents of the document and the characters immediately to the\n    //! left of the cursor.\n    //!\n    //! \\sa autoCompleteFromAPIs(), autoCompleteFromDocument()\n    virtual void autoCompleteFromAll();\n\n    //! Display an auto-completion list based on any installed APIs and the\n    //! characters immediately to the left of the cursor.\n    //!\n    //! \\sa autoCompleteFromAll(), autoCompleteFromDocument(),\n    //! setAutoCompletionAPIs()\n    virtual void autoCompleteFromAPIs();\n\n    //! Display an auto-completion list based on the current contents of the\n    //! document and the characters immediately to the left of the cursor.\n    //!\n    //! \\sa autoCompleteFromAll(), autoCompleteFromAPIs()\n    virtual void autoCompleteFromDocument();\n\n    //! Display a call tip based on the the characters immediately to the left\n    //! of the cursor.\n    virtual void callTip();\n\n    //! Deletes all the text in the text edit.\n    virtual void clear();\n\n    //! Copies any selected text to the clipboard.\n    //!\n    //! \\sa copyAvailable(), cut(), paste()\n    virtual void copy();\n\n    //! Copies any selected text to the clipboard and then deletes the text.\n    //!\n    //! \\sa copy(), paste()\n    virtual void cut();\n\n    //! Ensures that the cursor is visible.\n    virtual void ensureCursorVisible();\n\n    //! Ensures that the line number \\a line is visible.\n    virtual void ensureLineVisible(int line);\n\n    //! If any lines are currently folded then they are all unfolded.\n    //! Otherwise all lines are folded.  This has the same effect as clicking\n    //! in the fold margin with the shift and control keys pressed.  If\n    //! \\a children is not set (the default) then only the top level fold\n    //! points are affected, otherwise the state of all fold points are\n    //! changed.\n    virtual void foldAll(bool children = false);\n\n    //! If the line \\a line is folded then it is unfolded.  Otherwise it is\n    //! folded.  This has the same effect as clicking in the fold margin.\n    virtual void foldLine(int line);\n\n    //! Increases the indentation of line \\a line by an indentation width.\n    //!\n    //! \\sa unindent()\n    virtual void indent(int line);\n\n    //! Insert the text \\a text at the current position.\n    virtual void insert(const QString &text);\n\n    //! Insert the text \\a text in the line \\a line at the position\n    //! \\a index.\n    virtual void insertAt(const QString &text, int line, int index);\n\n    //! If the cursor is either side of a brace character then move it to the\n    //! position of the corresponding brace.\n    virtual void moveToMatchingBrace();\n\n    //! Pastes any text from the clipboard into the text edit at the current\n    //! cursor position.\n    //!\n    //! \\sa copy(), cut()\n    virtual void paste();\n\n    //! Redo the last change or sequence of changes.\n    //!\n    //! \\sa isRedoAvailable()\n    virtual void redo();\n\n    //! Removes any selected text.\n    //!\n    //! \\sa replaceSelectedText()\n    virtual void removeSelectedText();\n\n    //! Replaces any selected text with \\a text.\n    //!\n    //! \\sa removeSelectedText()\n    virtual void replaceSelectedText(const QString &text);\n\n    //! Resets the background colour of selected text to the default.\n    //!\n    //! \\sa setSelectionBackgroundColor(), resetSelectionForegroundColor()\n    virtual void resetSelectionBackgroundColor();\n\n    //! Resets the foreground colour of selected text to the default.\n    //!\n    //! \\sa setSelectionForegroundColor(), resetSelectionBackgroundColor()\n    virtual void resetSelectionForegroundColor();\n\n    //! If \\a select is true (the default) then all the text is selected.  If\n    //! \\a select is false then any currently selected text is deselected.\n    virtual void selectAll(bool select = true);\n\n    //! If the cursor is either side of a brace character then move it to the\n    //! position of the corresponding brace and select the text between the\n    //! braces.\n    virtual void selectToMatchingBrace();\n\n    //! If \\a cs is true then auto-completion lists are case sensitive.  The\n    //! default is true.  Note that setting a lexer may change the case\n    //! sensitivity.\n    //!\n    //! \\sa autoCompletionCaseSensitivity()\n    virtual void setAutoCompletionCaseSensitivity(bool cs);\n\n    //! If \\a replace is true then when an item from an auto-completion list is\n    //! selected, the rest of the word to the right of the current cursor is\n    //! removed.  The default is false.\n    //!\n    //! \\sa autoCompletionReplaceWord()\n    virtual void setAutoCompletionReplaceWord(bool replace);\n\n    //! If \\a single is true then when there is only a single entry in an\n    //! auto-completion list it is automatically used and the list is not\n    //! displayed.  This only has an effect when auto-completion is explicitly\n    //! requested (using autoCompleteFromAPIs() and autoCompleteFromDocument())\n    //! and has no effect when auto-completion is triggered as the user types.\n    //! The default is false.  Note that this is deprecated and\n    //! setAutoCompletionUseSingle() should be used instead.\n    //!\n    //! \\sa autoCompletionShowSingle()\n    virtual void setAutoCompletionShowSingle(bool single);\n\n    //! Sets the source for the auto-completion list when it is being displayed\n    //! automatically as the user types to \\a source.  The default is AcsNone,\n    //! ie. it is disabled.\n    //!\n    //! \\sa autoCompletionSource()\n    virtual void setAutoCompletionSource(AutoCompletionSource source);\n\n    //! Sets the threshold for the automatic display of the auto-completion\n    //! list as the user types to \\a thresh.  The threshold is the number of\n    //! characters that the user must type before the list is displayed.  If\n    //! the threshold is less than or equal to 0 then the list is disabled.\n    //! The default is -1.\n    //!\n    //! \\sa autoCompletionThreshold(), setAutoCompletionWordSeparators()\n    virtual void setAutoCompletionThreshold(int thresh);\n\n    //! Sets the behavior of the auto-completion list when it has a single\n    //! entry.  The default is AcusNever.\n    //!\n    //! \\sa autoCompletionUseSingle()\n    virtual void setAutoCompletionUseSingle(AutoCompletionUseSingle single);\n\n    //! If \\a autoindent is true then auto-indentation is enabled.  The default\n    //! is false.\n    //!\n    //! \\sa autoIndent()\n    virtual void setAutoIndent(bool autoindent);\n\n    //! Sets the brace matching mode to \\a bm.  The default is NoBraceMatching.\n    //!\n    //! \\sa braceMatching()\n    virtual void setBraceMatching(BraceMatch bm);\n\n    //! If \\a deindent is true then the backspace key will unindent a line\n    //! rather then delete a character.\n    //!\n    //! \\sa backspaceUnindents(), tabIndents(), setTabIndents()\n    virtual void setBackspaceUnindents(bool unindent);\n\n    //! Sets the foreground colour of the caret to \\a col.\n    virtual void setCaretForegroundColor(const QColor &col);\n\n    //! Sets the background colour, including the alpha component, of the line\n    //! containing the caret to \\a col.\n    //!\n    //! \\sa setCaretLineVisible()\n    virtual void setCaretLineBackgroundColor(const QColor &col);\n\n    //! Sets the width of the frame of the line containing the caret to \\a\n    //! width.\n    virtual void setCaretLineFrameWidth(int width);\n\n    //! Enables or disables, according to \\a enable, the background color of\n    //! the line containing the caret.\n    //!\n    //! \\sa setCaretLineBackgroundColor()\n    virtual void setCaretLineVisible(bool enable);\n\n    //! Sets the width of the caret to \\a width pixels.  A \\a width of 0 makes\n    //! the caret invisible.\n    virtual void setCaretWidth(int width);\n\n    //! The widget's text (ie. foreground) colour is set to \\a c.  This has no\n    //! effect if a language lexer has been set.\n    //!\n    //! \\sa color()\n    virtual void setColor(const QColor &c);\n\n    //! Sets the cursor to the line \\a line at the position \\a index.\n    //!\n    //! \\sa getCursorPosition()\n    virtual void setCursorPosition(int line, int index);\n\n    //! Sets the end-of-line mode to \\a mode.  The default is the platform's\n    //! natural mode.\n    //!\n    //! \\sa eolMode()\n    virtual void setEolMode(EolMode mode);\n\n    //! If \\a visible is true then end-of-lines are made visible.  The default\n    //! is that they are invisible.\n    //!\n    //! \\sa eolVisibility()\n    virtual void setEolVisibility(bool visible);\n\n    //! Sets the folding style for margin \\a margin to \\a fold.  The default\n    //! style is NoFoldStyle (ie. folding is disabled) and the default margin\n    //! is 2.\n    //!\n    //! \\sa folding()\n    virtual void setFolding(FoldStyle fold, int margin = 2);\n\n    //! Sets the indentation of line \\a line to \\a indentation characters.\n    //!\n    //! \\sa indentation()\n    virtual void setIndentation(int line, int indentation);\n\n    //! Enables or disables, according to \\a enable, this display of\n    //! indentation guides.\n    //!\n    //! \\sa indentationGuides()\n    virtual void setIndentationGuides(bool enable);\n\n    //! Set the background colour of indentation guides to \\a col.\n    //!\n    //! \\sa setIndentationGuidesForegroundColor()\n    virtual void setIndentationGuidesBackgroundColor(const QColor &col);\n\n    //! Set the foreground colour of indentation guides to \\a col.\n    //!\n    //! \\sa setIndentationGuidesBackgroundColor()\n    virtual void setIndentationGuidesForegroundColor(const QColor &col);\n\n    //! If \\a tabs is true then indentations are created using tabs and spaces,\n    //! rather than just spaces.\n    //!\n    //! \\sa indentationsUseTabs()\n    virtual void setIndentationsUseTabs(bool tabs);\n\n    //! Sets the indentation width to \\a width characters.  If \\a width is 0\n    //! then the value returned by tabWidth() is used.\n    //!\n    //! \\sa indentationWidth(), tabWidth()\n    virtual void setIndentationWidth(int width);\n\n    //! Sets the specific language lexer used to style text to \\a lex.  If\n    //! \\a lex is 0 then syntax styling is disabled.\n    //!\n    //! \\sa lexer()\n    virtual void setLexer(QsciLexer *lexer = 0);\n\n    //! Set the background colour of all margins to \\a col.  The default is a\n    //! gray.\n    //!\n    //! \\sa setMarginsForegroundColor()\n    virtual void setMarginsBackgroundColor(const QColor &col);\n\n    //! Set the font used in all margins to \\a f.\n    virtual void setMarginsFont(const QFont &f);\n\n    //! Set the foreground colour of all margins to \\a col.  The default is\n    //! black.\n    //!\n    //! \\sa setMarginsBackgroundColor()\n    virtual void setMarginsForegroundColor(const QColor &col);\n\n    //! Enables or disables, according to \\a lnrs, the display of line numbers\n    //! in margin \\a margin.\n    //!\n    //! \\sa marginLineNumbers(), setMarginType(), SCI_SETMARGINTYPEN\n    virtual void setMarginLineNumbers(int margin, bool lnrs);\n\n    //! Sets the marker mask of margin \\a margin to \\a mask.  Only those\n    //! markers whose bit is set in the mask are displayed in the margin.\n    //!\n    //! \\sa marginMarkerMask(), QsciMarker, SCI_SETMARGINMASKN\n    virtual void setMarginMarkerMask(int margin, int mask);\n\n    //! Enables or disables, according to \\a sens, the sensitivity of margin\n    //! \\a margin to mouse clicks.  If the user clicks in a sensitive margin\n    //! the marginClicked() signal is emitted.\n    //!\n    //! \\sa marginSensitivity(), marginClicked(), SCI_SETMARGINSENSITIVEN\n    virtual void setMarginSensitivity(int margin, bool sens);\n\n    //! Sets the width of margin \\a margin to \\a width pixels.  If the width of\n    //! a margin is 0 then it is not displayed.\n    //!\n    //! \\sa marginWidth(), SCI_SETMARGINWIDTHN\n    virtual void setMarginWidth(int margin, int width);\n\n    //! Sets the width of margin \\a margin so that it is wide enough to display\n    //! \\a s in the current margin font.\n    //!\n    //! \\sa marginWidth(), SCI_SETMARGINWIDTHN\n    virtual void setMarginWidth(int margin, const QString &s);\n\n    //! Sets the modified state of the text edit to \\a m.  Note that it is only\n    //! possible to clear the modified state (where \\a m is false).  Attempts\n    //! to set the modified state (where \\a m is true) are ignored.\n    //!\n    //! \\sa isModified(), modificationChanged()\n    virtual void setModified(bool m);\n\n    //! The widget's paper (ie. background) colour is set to \\a c.  This has no\n    //! effect if a language lexer has been set.\n    //!\n    //! \\sa paper()\n    virtual void setPaper(const QColor &c);\n\n    //! Sets the read-only state of the text edit to \\a ro.\n    //!\n    //! \\sa isReadOnly()\n    virtual void setReadOnly(bool ro);\n\n    //! Sets the selection which starts at position \\a indexFrom in line\n    //! \\a lineFrom and ends at position \\a indexTo in line \\a lineTo.  The\n    //! cursor is moved to position \\a indexTo in \\a lineTo.\n    //!\n    //! \\sa getSelection()\n    virtual void setSelection(int lineFrom, int indexFrom, int lineTo,\n            int indexTo);\n\n    //! Sets the background colour, including the alpha component, of selected\n    //! text to \\a col.\n    //!\n    //! \\sa resetSelectionBackgroundColor(), setSelectionForegroundColor()\n    virtual void setSelectionBackgroundColor(const QColor &col);\n\n    //! Sets the foreground colour of selected text to \\a col.\n    //!\n    //! \\sa resetSelectionForegroundColor(), setSelectionBackgroundColor()\n    virtual void setSelectionForegroundColor(const QColor &col);\n\n    //! If \\a indent is true then the tab key will indent a line rather than\n    //! insert a tab character.\n    //!\n    //! \\sa tabIndents(), backspaceUnindents(), setBackspaceUnindents()\n    virtual void setTabIndents(bool indent);\n\n    //! Sets the tab width to \\a width characters.\n    //!\n    //! \\sa tabWidth()\n    virtual void setTabWidth(int width);\n\n    //! Replaces all of the current text with \\a text.  Note that the\n    //! undo/redo history is cleared by this function.\n    //!\n    //! \\sa text()\n    virtual void setText(const QString &text);\n\n    //! Sets the current text encoding.  If \\a cp is true then UTF8 is used,\n    //! otherwise Latin1 is used.\n    //!\n    //! \\sa isUtf8()\n    virtual void setUtf8(bool cp);\n\n    //! Sets the visibility of whitespace to mode \\a mode.  The default is that\n    //! whitespace is invisible.\n    //!\n    //! \\sa whitespaceVisibility()\n    virtual void setWhitespaceVisibility(WhitespaceVisibility mode);\n\n    //! Sets the line wrap mode to \\a mode.  The default is that lines are not\n    //! wrapped.\n    //!\n    //! \\sa wrapMode()\n    virtual void setWrapMode(WrapMode mode);\n\n    //! Undo the last change or sequence of changes.\n    //!\n    //! Scintilla has multiple level undo and redo.  It will continue to record\n    //! undoable actions until memory runs out.  Sequences of typing or\n    //! deleting are compressed into single actions to make it easier to undo\n    //! and redo at a sensible level of detail.  Sequences of actions can be\n    //! combined into actions that are undone as a unit.  These sequences occur\n    //! between calls to beginUndoAction() and endUndoAction().  These\n    //! sequences can be nested and only the top level sequences are undone as\n    //! units. \n    //!\n    //! \\sa beginUndoAction(), endUndoAction(), isUndoAvailable()\n    virtual void undo();\n\n    //! Decreases the indentation of line \\a line by an indentation width.\n    //!\n    //! \\sa indent()\n    virtual void unindent(int line);\n\n    //! Zooms in on the text by by making the base font size \\a range points\n    //! larger and recalculating all font sizes.\n    //!\n    //! \\sa zoomOut(), zoomTo()\n    virtual void zoomIn(int range);\n\n    //! \\overload\n    //!\n    //! Zooms in on the text by by making the base font size one point larger\n    //! and recalculating all font sizes.\n    virtual void zoomIn();\n\n    //! Zooms out on the text by by making the base font size \\a range points\n    //! smaller and recalculating all font sizes.\n    //!\n    //! \\sa zoomIn(), zoomTo()\n    virtual void zoomOut(int range);\n\n    //! \\overload\n    //!\n    //! Zooms out on the text by by making the base font size one point larger\n    //! and recalculating all font sizes.\n    virtual void zoomOut();\n\n    //! Zooms the text by making the base font size \\a size points and\n    //! recalculating all font sizes.\n    //!\n    //! \\sa zoomIn(), zoomOut()\n    virtual void zoomTo(int size);\n\nsignals:\n    //! This signal is emitted whenever the cursor position changes.  \\a line\n    //! contains the line number and \\a index contains the character index\n    //! within the line.\n    void cursorPositionChanged(int line, int index);\n\n    //! This signal is emitted whenever text is selected or de-selected.\n    //! \\a yes is true if text has been selected and false if text has been\n    //! deselected.  If \\a yes is true then copy() can be used to copy the\n    //! selection to the clipboard.  If \\a yes is false then copy() does\n    //! nothing. \n    //!\n    //! \\sa copy(), selectionChanged()\n    void copyAvailable(bool yes);\n\n    //! This signal is emitted whenever the user clicks on an indicator.  \\a\n    //! line is the number of the line where the user clicked.  \\a index is the\n    //! character index within the line.  \\a state is the state of the modifier\n    //! keys (Qt::ShiftModifier, Qt::ControlModifier, Qt::AltModifer and\n    //! Qt::MetaModifier) when the user clicked.\n    //!\n    //! \\sa indicatorReleased()\n    void indicatorClicked(int line, int index, Qt::KeyboardModifiers state);\n\n    //! This signal is emitted whenever the user releases the mouse on an\n    //! indicator.  \\a line is the number of the line where the user clicked.\n    //! \\a index is the character index within the line.  \\a state is the state\n    //! of the modifier keys (Qt::ShiftModifier, Qt::ControlModifier,\n    //! Qt::AltModifer and Qt::MetaModifier) when the user released the mouse.\n    //!\n    //! \\sa indicatorClicked()\n    void indicatorReleased(int line, int index, Qt::KeyboardModifiers state);\n\n    //! This signal is emitted whenever the number of lines of text changes.\n    void linesChanged();\n\n    //! This signal is emitted whenever the user clicks on a sensitive margin.\n    //! \\a margin is the margin.  \\a line is the number of the line where the\n    //! user clicked.  \\a state is the state of the modifier keys\n    //! (Qt::ShiftModifier, Qt::ControlModifier, Qt::AltModifer and\n    //! Qt::MetaModifier) when the user clicked.\n    //!\n    //! \\sa marginSensitivity(), setMarginSensitivity()\n    void marginClicked(int margin, int line, Qt::KeyboardModifiers state);\n\n    //! This signal is emitted whenever the user right-clicks on a sensitive\n    //! margin.  \\a margin is the margin.  \\a line is the number of the line\n    //! where the user clicked.  \\a state is the state of the modifier keys\n    //! (Qt::ShiftModifier, Qt::ControlModifier, Qt::AltModifer and\n    //! Qt::MetaModifier) when the user clicked.\n    //!\n    //! \\sa marginSensitivity(), setMarginSensitivity()\n    void marginRightClicked(int margin, int line, Qt::KeyboardModifiers state);\n\n    //! This signal is emitted whenever the user attempts to modify read-only\n    //! text.\n    //!\n    //! \\sa isReadOnly(), setReadOnly()\n    void modificationAttempted();\n\n    //! This signal is emitted whenever the modification state of the text\n    //! changes.  \\a m is true if the text has been modified.\n    //!\n    //! \\sa isModified(), setModified()\n    void modificationChanged(bool m);\n\n    //! This signal is emitted whenever the selection changes.\n    //!\n    //! \\sa copyAvailable()\n    void selectionChanged();\n\n    //! This signal is emitted whenever the text in the text edit changes.\n    void textChanged();\n\n    //! This signal is emitted when an item in a user defined list is activated\n    //! (selected).  \\a id is the list identifier.  \\a string is the text of\n    //! the item.\n    //!\n    //! \\sa showUserList()\n    void userListActivated(int id, const QString &string);\n\nprotected:\n    //! \\reimp\n    virtual bool event(QEvent *e);\n\n    //! \\reimp\n    virtual void changeEvent(QEvent *e);\n\n    //! \\reimp\n    virtual void contextMenuEvent(QContextMenuEvent *e);\n\n    //! \\reimp\n    virtual void wheelEvent(QWheelEvent *e);\n\nprivate slots:\n    void handleCallTipClick(int dir);\n    void handleCharAdded(int charadded);\n    void handleIndicatorClick(int pos, int modifiers);\n    void handleIndicatorRelease(int pos, int modifiers);\n    void handleMarginClick(int pos, int margin, int modifiers);\n    void handleMarginRightClick(int pos, int margin, int modifiers);\n    void handleModified(int pos, int mtype, const char *text, int len,\n            int added, int line, int foldNow, int foldPrev, int token,\n            int annotationLinesAdded);\n    void handlePropertyChange(const char *prop, const char *val);\n    void handleSavePointReached();\n    void handleSavePointLeft();\n    void handleSelectionChanged(bool yes);\n    void handleAutoCompletionSelection();\n    void handleUserListSelection(const char *text, int id);\n\n    void handleStyleColorChange(const QColor &c, int style);\n    void handleStyleEolFillChange(bool eolfill, int style);\n    void handleStyleFontChange(const QFont &f, int style);\n    void handleStylePaperChange(const QColor &c, int style);\n\n    void handleUpdateUI(int updated);\n\n    void delete_selection();\n\nprivate:\n    void detachLexer();\n\n    enum IndentState {\n        isNone,\n        isKeywordStart,\n        isBlockStart,\n        isBlockEnd\n    };\n\n    void maintainIndentation(char ch, long pos);\n    void autoIndentation(char ch, long pos);\n    void autoIndentLine(long pos, int line, int indent);\n    int blockIndent(int line);\n    IndentState getIndentState(int line);\n    bool rangeIsWhitespace(long spos, long epos);\n    int findStyledWord(const char *text, int style, const char *words);\n\n    void checkMarker(int &markerNumber);\n    void checkIndicator(int &indicatorNumber);\n    static void allocateId(int &id, unsigned &allocated, int min, int max);\n    int currentIndent() const;\n    int indentWidth() const;\n    bool doFind();\n    int simpleFind();\n    void foldClick(int lineClick, int bstate);\n    void foldChanged(int line, int levelNow, int levelPrev);\n    void foldExpand(int &line, bool doExpand, bool force = false,\n            int visLevels = 0, int level = -1);\n    void setFoldMarker(int marknr, int mark = SC_MARK_EMPTY);\n    void setLexerStyle(int style);\n    void setStylesFont(const QFont &f, int style);\n    void setEnabledColors(int style, QColor &fore, QColor &back);\n\n    void braceMatch();\n    long checkBrace(long pos, int brace_style, bool &colonMode);\n    void gotoMatchingBrace(bool select);\n\n    void startAutoCompletion(AutoCompletionSource acs, bool checkThresh,\n            bool choose_single);\n\n    int adjustedCallTipPosition(int ctshift) const;\n    bool getSeparator(int &pos) const;\n    QString getWord(int &pos) const;\n    char getCharacter(int &pos) const;\n    bool isStartChar(char ch) const;\n\n    bool ensureRW();\n    void insertAtPos(const QString &text, int pos);\n    static int mapModifiers(int modifiers);\n\n    QString wordAtPosition(int position) const;\n\n    QByteArray styleText(const QList<QsciStyledText> &styled_text,\n            char **styles, int style_offset = 0);\n\n    struct FindState\n    {\n        enum Status\n        {\n            Finding,\n            FindingInSelection,\n            Idle\n        };\n\n        FindState() : status(Idle) {}\n\n        Status status;\n        QString expr;\n        bool wrap;\n        bool forward;\n        int flags;\n        long startpos, startpos_orig;\n        long endpos, endpos_orig;\n        bool show;\n    };\n\n    FindState findState;\n\n    unsigned allocatedMarkers;\n    unsigned allocatedIndicators;\n    int oldPos;\n    int ctPos;\n    bool selText;\n    FoldStyle fold;\n    int foldmargin;\n    bool autoInd;\n    BraceMatch braceMode;\n    AutoCompletionSource acSource;\n    int acThresh;\n    QStringList wseps;\n    const char *wchars;\n    CallTipsPosition call_tips_position;\n    CallTipsStyle call_tips_style;\n    int maxCallTips;\n    QStringList ct_entries;\n    int ct_cursor;\n    QList<int> ct_shifts;\n    AutoCompletionUseSingle use_single;\n    QPointer<QsciLexer> lex;\n    QsciCommandSet *stdCmds;\n    QsciDocument doc;\n    QColor nl_text_colour;\n    QColor nl_paper_colour;\n    QByteArray explicit_fillups;\n    bool fillups_enabled;\n\n    // The following allow QsciListBoxQt to distinguish between an\n    // auto-completion list and a user list, and to return the full selection\n    // of an auto-completion list.\n    friend class QsciListBoxQt;\n\n    QString acSelection;\n    bool isAutoCompletionList() const;\n\n    void set_shortcut(QAction *action, QsciCommand::Command cmd_id) const;\n\n    QsciScintilla(const QsciScintilla &);\n    QsciScintilla &operator=(const QsciScintilla &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qsciscintillabase.h",
    "content": "// This class defines the \"official\" low-level API.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCISCINTILLABASE_H\n#define QSCISCINTILLABASE_H\n\n#include <qglobal.h>\n\n#include <QAbstractScrollArea>\n#include <QByteArray>\n#include <QPoint>\n#include <QTimer>\n\n#include <Qsci/qsciglobal.h>\n\n\nQT_BEGIN_NAMESPACE\nclass QColor;\nclass QImage;\nclass QMimeData;\nclass QPainter;\nclass QPixmap;\nclass QUrl;\nQT_END_NAMESPACE\n\nclass QsciScintillaQt;\n\n\n//! \\brief The QsciScintillaBase class implements the Scintilla editor widget\n//! and its low-level API.\n//!\n//! Scintilla (http://www.scintilla.org) is a powerful C++ editor class that\n//! supports many features including syntax styling, error indicators, code\n//! completion and call tips. It is particularly useful as a programmer's\n//! editor.\n//!\n//! QsciScintillaBase is a port to Qt of Scintilla. It implements the standard\n//! Scintilla API which consists of a number of messages each taking up to\n//! two arguments.\n//!\n//! See QsciScintilla for the implementation of a higher level API that is more\n//! consistent with the rest of the Qt toolkit.\nclass QSCINTILLA_EXPORT QsciScintillaBase : public QAbstractScrollArea\n{\n    Q_OBJECT\n\npublic:\n    //! The low-level Scintilla API is implemented as a set of messages each of\n    //! which takes up to two parameters (\\a wParam and \\a lParam) and\n    //! optionally return a value. This enum defines all the possible messages.\n    enum\n    {\n        //!\n        SCI_START = 2000,\n\n        //!\n        SCI_OPTIONAL_START = 3000,\n\n        //!\n        SCI_LEXER_START = 4000,\n\n        //! This message appends some text to the end of the document.\n        //! \\a wParam is the length of the text.\n        //! \\a lParam is the text to be appended.\n        SCI_ADDTEXT = 2001,\n\n        //!\n        SCI_ADDSTYLEDTEXT = 2002,\n\n        //!\n        SCI_INSERTTEXT = 2003,\n\n        //!\n        SCI_CLEARALL = 2004,\n\n        //!\n        SCI_CLEARDOCUMENTSTYLE = 2005,\n\n        //!\n        SCI_GETLENGTH = 2006,\n\n        //!\n        SCI_GETCHARAT = 2007,\n\n        //! This message returns the current position.\n        //! \n        //! \\sa SCI_SETCURRENTPOS\n        SCI_GETCURRENTPOS = 2008,\n\n        //! This message returns the anchor.\n        //! \n        //! \\sa SCI_SETANCHOR\n        SCI_GETANCHOR = 2009,\n\n        //!\n        SCI_GETSTYLEAT = 2010,\n\n        //!\n        SCI_REDO = 2011,\n\n        //!\n        SCI_SETUNDOCOLLECTION = 2012,\n\n        //!\n        SCI_SELECTALL = 2013,\n\n        //! This message marks the current state of the text as the the save\n        //! point. This is usually done when the text is saved or loaded.\n        //! \n        //! \\sa SCN_SAVEPOINTREACHED(), SCN_SAVEPOINTLEFT()\n        SCI_SETSAVEPOINT = 2014,\n\n        //!\n        SCI_GETSTYLEDTEXT = 2015,\n\n        //!\n        SCI_CANREDO = 2016,\n\n        //! This message returns the line that contains a particular instance\n        //! of a marker.\n        //! \\a wParam is the handle of the marker.\n        //!\n        //! \\sa SCI_MARKERADD\n        SCI_MARKERLINEFROMHANDLE = 2017,\n\n        //! This message removes a particular instance of a marker.\n        //! \\a wParam is the handle of the marker.\n        //!\n        //! \\sa SCI_MARKERADD\n        SCI_MARKERDELETEHANDLE = 2018,\n\n        //!\n        SCI_GETUNDOCOLLECTION = 2019,\n\n        //!\n        SCI_GETVIEWWS = 2020,\n\n        //!\n        SCI_SETVIEWWS = 2021,\n\n        //!\n        SCI_POSITIONFROMPOINT = 2022,\n\n        //!\n        SCI_POSITIONFROMPOINTCLOSE = 2023,\n\n        //!\n        SCI_GOTOLINE = 2024,\n\n        //! This message clears the current selection and sets the current\n        //! position.\n        //! \\a wParam is the new current position.\n        //! \n        //! \\sa SCI_SETCURRENTPOS\n        SCI_GOTOPOS = 2025,\n\n        //! This message sets the anchor.\n        //! \\a wParam is the new anchor.\n        //! \n        //! \\sa SCI_GETANCHOR\n        SCI_SETANCHOR = 2026,\n\n        //!\n        SCI_GETCURLINE = 2027,\n\n        //! This message returns the character position of the start of the\n        //! text that needs to be syntax styled.\n        //! \n        //! \\sa SCN_STYLENEEDED()\n        SCI_GETENDSTYLED = 2028,\n\n        //!\n        SCI_CONVERTEOLS = 2029,\n\n        //!\n        SCI_GETEOLMODE = 2030,\n\n        //!\n        SCI_SETEOLMODE = 2031,\n\n        //!\n        SCI_STARTSTYLING = 2032,\n\n        //!\n        SCI_SETSTYLING = 2033,\n\n        //!\n        SCI_GETBUFFEREDDRAW = 2034,\n\n        //!\n        SCI_SETBUFFEREDDRAW = 2035,\n\n        //!\n        SCI_SETTABWIDTH = 2036,\n\n        //!\n        SCI_GETTABWIDTH = 2121,\n\n        //!\n        SCI_SETCODEPAGE = 2037,\n\n        //! This message sets the symbol used to draw one of 32 markers.  Some\n        //! markers have pre-defined uses, see the SC_MARKNUM_* values.\n        //! \\a wParam is the number of the marker.\n        //! \\a lParam is the marker symbol and is one of the SC_MARK_* values.\n        //!\n        //! \\sa SCI_MARKERADD, SCI_MARKERDEFINEPIXMAP,\n        //! SCI_MARKERDEFINERGBAIMAGE\n        SCI_MARKERDEFINE = 2040,\n\n        //! This message sets the foreground colour used to draw a marker.  A\n        //! colour is represented as a 24 bit value.  The 8 least significant\n        //! bits correspond to red, the middle 8 bits correspond to green, and\n        //! the 8 most significant bits correspond to blue.  The default value\n        //! is 0x000000.\n        //! \\a wParam is the number of the marker.\n        //! \\a lParam is the colour.\n        //!\n        //! \\sa SCI_MARKERSETBACK\n        SCI_MARKERSETFORE = 2041,\n\n        //! This message sets the background colour used to draw a marker.  A\n        //! colour is represented as a 24 bit value.  The 8 least significant\n        //! bits correspond to red, the middle 8 bits correspond to green, and\n        //! the 8 most significant bits correspond to blue.  The default value\n        //! is 0xffffff.\n        //! \\a wParam is the number of the marker.\n        //! \\a lParam is the colour.\n        //!\n        //! \\sa SCI_MARKERSETFORE\n        SCI_MARKERSETBACK = 2042,\n\n        //! This message adds a marker to a line.  A handle for the marker is\n        //! returned which can be used to track the marker's position.\n        //! \\a wParam is the line number.\n        //! \\a lParam is the number of the marker.\n        //!\n        //! \\sa SCI_MARKERDELETE, SCI_MARKERDELETEALL,\n        //! SCI_MARKERDELETEHANDLE\n        SCI_MARKERADD = 2043,\n\n        //! This message deletes a marker from a line.\n        //! \\a wParam is the line number.\n        //! \\a lParam is the number of the marker.\n        //!\n        //! \\sa SCI_MARKERADD, SCI_MARKERDELETEALL\n        SCI_MARKERDELETE = 2044,\n\n        //! This message deletes all occurences of a marker.\n        //! \\a wParam is the number of the marker.  If \\a wParam is -1 then all\n        //! markers are removed.\n        //!\n        //! \\sa SCI_MARKERADD, SCI_MARKERDELETE\n        SCI_MARKERDELETEALL = 2045,\n\n        //! This message returns the 32 bit mask of markers at a line.\n        //! \\a wParam is the line number.\n        SCI_MARKERGET = 2046,\n\n        //! This message looks for the next line to contain at least one marker\n        //! contained in a 32 bit mask of markers and returns the line number.\n        //! \\a wParam is the line number to start the search from.\n        //! \\a lParam is the mask of markers to search for.\n        //!\n        //! \\sa SCI_MARKERPREVIOUS\n        SCI_MARKERNEXT = 2047,\n\n        //! This message looks for the previous line to contain at least one\n        //! marker contained in a 32 bit mask of markers and returns the line\n        //! number.\n        //! \\a wParam is the line number to start the search from.\n        //! \\a lParam is the mask of markers to search for.\n        //!\n        //! \\sa SCI_MARKERNEXT\n        SCI_MARKERPREVIOUS = 2048,\n\n        //! This message sets the symbol used to draw one of the 32 markers to\n        //! a pixmap.  Pixmaps use the SC_MARK_PIXMAP marker symbol.\n        //! \\a wParam is the number of the marker.\n        //! \\a lParam is a pointer to a QPixmap instance.  Note that in other\n        //! ports of Scintilla this is a pointer to either raw or textual XPM\n        //! image data.\n        //!\n        //! \\sa SCI_MARKERDEFINE, SCI_MARKERDEFINERGBAIMAGE\n        SCI_MARKERDEFINEPIXMAP = 2049,\n\n        //! This message sets what can be displayed in a margin.\n        //! \\a wParam is the number of the margin.\n        //! \\a lParam is the logical or of the SC_MARGIN_* values.\n        //!\n        //! \\sa SCI_GETMARGINTYPEN\n        SCI_SETMARGINTYPEN = 2240,\n\n        //! This message returns what can be displayed in a margin.\n        //! \\a wParam is the number of the margin.\n        //!\n        //! \\sa SCI_SETMARGINTYPEN\n        SCI_GETMARGINTYPEN = 2241,\n\n        //! This message sets the width of a margin in pixels.\n        //! \\a wParam is the number of the margin.\n        //! \\a lParam is the new margin width.\n        //!\n        //! \\sa SCI_GETMARGINWIDTHN\n        SCI_SETMARGINWIDTHN = 2242,\n\n        //! This message returns the width of a margin in pixels.\n        //! \\a wParam is the number of the margin.\n        //!\n        //! \\sa SCI_SETMARGINWIDTHN\n        SCI_GETMARGINWIDTHN = 2243,\n\n        //! This message sets the mask of a margin.  The mask is a 32 value\n        //! with one bit for each possible marker.  If a bit is set then the\n        //! corresponding marker is displayed.  By default, all markers are\n        //! displayed.\n        //! \\a wParam is the number of the margin.\n        //! \\a lParam is the new margin mask.\n        //!\n        //! \\sa SCI_GETMARGINMASKN, SCI_MARKERDEFINE\n        SCI_SETMARGINMASKN = 2244,\n\n        //! This message returns the mask of a margin.\n        //! \\a wParam is the number of the margin.\n        //!\n        //! \\sa SCI_SETMARGINMASKN\n        SCI_GETMARGINMASKN = 2245,\n\n        //! This message sets the sensitivity of a margin to mouse clicks.\n        //! \\a wParam is the number of the margin.\n        //! \\a lParam is non-zero to make the margin sensitive to mouse clicks.\n        //! When the mouse is clicked the SCN_MARGINCLICK() signal is emitted.\n        //!\n        //! \\sa SCI_GETMARGINSENSITIVEN, SCN_MARGINCLICK()\n        SCI_SETMARGINSENSITIVEN = 2246,\n\n        //! This message returns the sensitivity of a margin to mouse clicks.\n        //! \\a wParam is the number of the margin.\n        //!\n        //! \\sa SCI_SETMARGINSENSITIVEN, SCN_MARGINCLICK()\n        SCI_GETMARGINSENSITIVEN = 2247,\n\n        //! This message sets the cursor shape displayed over a margin.\n        //! \\a wParam is the number of the margin.\n        //! \\a lParam is the cursor shape, normally either SC_CURSORARROW or\n        //! SC_CURSORREVERSEARROW.  Note that, currently, QScintilla implements\n        //! both of these as Qt::ArrowCursor.\n        //!\n        //! \\sa SCI_GETMARGINCURSORN\n        SCI_SETMARGINCURSORN = 2248,\n\n        //! This message returns the cursor shape displayed over a margin.\n        //! \\a wParam is the number of the margin.\n        //!\n        //! \\sa SCI_SETMARGINCURSORN\n        SCI_GETMARGINCURSORN = 2249,\n\n        //!\n        SCI_STYLECLEARALL = 2050,\n\n        //!\n        SCI_STYLESETFORE = 2051,\n\n        //!\n        SCI_STYLESETBACK = 2052,\n\n        //!\n        SCI_STYLESETBOLD = 2053,\n\n        //!\n        SCI_STYLESETITALIC = 2054,\n\n        //!\n        SCI_STYLESETSIZE = 2055,\n\n        //!\n        SCI_STYLESETFONT = 2056,\n\n        //!\n        SCI_STYLESETEOLFILLED = 2057,\n\n        //!\n        SCI_STYLERESETDEFAULT = 2058,\n\n        //!\n        SCI_STYLESETUNDERLINE = 2059,\n\n        //!\n        SCI_STYLESETCASE = 2060,\n\n        //!\n        SCI_STYLESETSIZEFRACTIONAL = 2061,\n\n        //!\n        SCI_STYLEGETSIZEFRACTIONAL = 2062,\n\n        //!\n        SCI_STYLESETWEIGHT = 2063,\n\n        //!\n        SCI_STYLEGETWEIGHT = 2064,\n\n        //!\n        SCI_STYLESETCHARACTERSET = 2066,\n\n        //!\n        SCI_SETSELFORE = 2067,\n\n        //!\n        SCI_SETSELBACK = 2068,\n\n        //!\n        SCI_SETCARETFORE = 2069,\n\n        //!\n        SCI_ASSIGNCMDKEY = 2070,\n\n        //!\n        SCI_CLEARCMDKEY = 2071,\n\n        //!\n        SCI_CLEARALLCMDKEYS = 2072,\n\n        //!\n        SCI_SETSTYLINGEX = 2073,\n\n        //!\n        SCI_STYLESETVISIBLE = 2074,\n\n        //!\n        SCI_GETCARETPERIOD = 2075,\n\n        //!\n        SCI_SETCARETPERIOD = 2076,\n\n        //!\n        SCI_SETWORDCHARS = 2077,\n\n        //!\n        SCI_BEGINUNDOACTION = 2078,\n\n        //!\n        SCI_ENDUNDOACTION = 2079,\n\n        //!\n        SCI_INDICSETSTYLE = 2080,\n\n        //!\n        SCI_INDICGETSTYLE = 2081,\n\n        //!\n        SCI_INDICSETFORE = 2082,\n\n        //!\n        SCI_INDICGETFORE = 2083,\n\n        //!\n        SCI_SETWHITESPACEFORE = 2084,\n\n        //!\n        SCI_SETWHITESPACEBACK = 2085,\n\n        //!\n        SCI_SETWHITESPACESIZE = 2086,\n\n        //!\n        SCI_GETWHITESPACESIZE = 2087,\n\n        //!\n        SCI_SETSTYLEBITS = 2090,\n\n        //!\n        SCI_GETSTYLEBITS = 2091,\n\n        //!\n        SCI_SETLINESTATE = 2092,\n\n        //!\n        SCI_GETLINESTATE = 2093,\n\n        //!\n        SCI_GETMAXLINESTATE = 2094,\n\n        //!\n        SCI_GETCARETLINEVISIBLE = 2095,\n\n        //!\n        SCI_SETCARETLINEVISIBLE = 2096,\n\n        //!\n        SCI_GETCARETLINEBACK = 2097,\n\n        //!\n        SCI_SETCARETLINEBACK = 2098,\n\n        //!\n        SCI_STYLESETCHANGEABLE = 2099,\n\n        //!\n        SCI_AUTOCSHOW = 2100,\n\n        //!\n        SCI_AUTOCCANCEL = 2101,\n\n        //!\n        SCI_AUTOCACTIVE = 2102,\n\n        //!\n        SCI_AUTOCPOSSTART = 2103,\n\n        //!\n        SCI_AUTOCCOMPLETE = 2104,\n\n        //!\n        SCI_AUTOCSTOPS = 2105,\n\n        //!\n        SCI_AUTOCSETSEPARATOR = 2106,\n\n        //!\n        SCI_AUTOCGETSEPARATOR = 2107,\n\n        //!\n        SCI_AUTOCSELECT = 2108,\n\n        //!\n        SCI_AUTOCSETCANCELATSTART = 2110,\n\n        //!\n        SCI_AUTOCGETCANCELATSTART = 2111,\n\n        //!\n        SCI_AUTOCSETFILLUPS = 2112,\n\n        //!\n        SCI_AUTOCSETCHOOSESINGLE = 2113,\n\n        //!\n        SCI_AUTOCGETCHOOSESINGLE = 2114,\n\n        //!\n        SCI_AUTOCSETIGNORECASE = 2115,\n\n        //!\n        SCI_AUTOCGETIGNORECASE = 2116,\n\n        //!\n        SCI_USERLISTSHOW = 2117,\n\n        //!\n        SCI_AUTOCSETAUTOHIDE = 2118,\n\n        //!\n        SCI_AUTOCGETAUTOHIDE = 2119,\n\n        //!\n        SCI_AUTOCSETDROPRESTOFWORD = 2270,\n\n        //!\n        SCI_AUTOCGETDROPRESTOFWORD = 2271,\n\n        //!\n        SCI_SETINDENT = 2122,\n\n        //!\n        SCI_GETINDENT = 2123,\n\n        //!\n        SCI_SETUSETABS = 2124,\n\n        //!\n        SCI_GETUSETABS = 2125,\n\n        //!\n        SCI_SETLINEINDENTATION = 2126,\n\n        //!\n        SCI_GETLINEINDENTATION = 2127,\n\n        //!\n        SCI_GETLINEINDENTPOSITION = 2128,\n\n        //!\n        SCI_GETCOLUMN = 2129,\n\n        //!\n        SCI_SETHSCROLLBAR = 2130,\n\n        //!\n        SCI_GETHSCROLLBAR = 2131,\n\n        //!\n        SCI_SETINDENTATIONGUIDES = 2132,\n\n        //!\n        SCI_GETINDENTATIONGUIDES = 2133,\n\n        //!\n        SCI_SETHIGHLIGHTGUIDE = 2134,\n\n        //!\n        SCI_GETHIGHLIGHTGUIDE = 2135,\n\n        //!\n        SCI_GETLINEENDPOSITION = 2136,\n\n        //!\n        SCI_GETCODEPAGE = 2137,\n\n        //!\n        SCI_GETCARETFORE = 2138,\n\n        //! This message returns a non-zero value if the document is read-only.\n        //! \n        //! \\sa SCI_SETREADONLY\n        SCI_GETREADONLY = 2140,\n\n        //! This message sets the current position.\n        //! \\a wParam is the new current position.\n        //! \n        //! \\sa SCI_GETCURRENTPOS\n        SCI_SETCURRENTPOS = 2141,\n\n        //!\n        SCI_SETSELECTIONSTART = 2142,\n\n        //!\n        SCI_GETSELECTIONSTART = 2143,\n\n        //!\n        SCI_SETSELECTIONEND = 2144,\n\n        //!\n        SCI_GETSELECTIONEND = 2145,\n\n        //!\n        SCI_SETPRINTMAGNIFICATION = 2146,\n\n        //!\n        SCI_GETPRINTMAGNIFICATION = 2147,\n\n        //!\n        SCI_SETPRINTCOLOURMODE = 2148,\n\n        //!\n        SCI_GETPRINTCOLOURMODE = 2149,\n\n        //!\n        SCI_FINDTEXT = 2150,\n\n        //!\n        SCI_FORMATRANGE = 2151,\n\n        //!\n        SCI_GETFIRSTVISIBLELINE = 2152,\n\n        //!\n        SCI_GETLINE = 2153,\n\n        //!\n        SCI_GETLINECOUNT = 2154,\n\n        //!\n        SCI_SETMARGINLEFT = 2155,\n\n        //!\n        SCI_GETMARGINLEFT = 2156,\n\n        //!\n        SCI_SETMARGINRIGHT = 2157,\n\n        //!\n        SCI_GETMARGINRIGHT = 2158,\n\n        //! This message returns a non-zero value if the document has been\n        //! modified.\n        SCI_GETMODIFY = 2159,\n\n        //!\n        SCI_SETSEL = 2160,\n\n        //!\n        SCI_GETSELTEXT = 2161,\n\n        //!\n        SCI_GETTEXTRANGE = 2162,\n\n        //!\n        SCI_HIDESELECTION = 2163,\n\n        //!\n        SCI_POINTXFROMPOSITION = 2164,\n\n        //!\n        SCI_POINTYFROMPOSITION = 2165,\n\n        //!\n        SCI_LINEFROMPOSITION = 2166,\n\n        //!\n        SCI_POSITIONFROMLINE = 2167,\n\n        //!\n        SCI_LINESCROLL = 2168,\n\n        //!\n        SCI_SCROLLCARET = 2169,\n\n        //!\n        SCI_REPLACESEL = 2170,\n\n        //! This message sets the read-only state of the document.\n        //! \\a wParam is the new read-only state of the document.\n        //! \n        //! \\sa SCI_GETREADONLY\n        SCI_SETREADONLY = 2171,\n\n        //!\n        SCI_NULL = 2172,\n\n        //!\n        SCI_CANPASTE = 2173,\n\n        //!\n        SCI_CANUNDO = 2174,\n\n        //! This message empties the undo buffer.\n        SCI_EMPTYUNDOBUFFER = 2175,\n\n        //!\n        SCI_UNDO = 2176,\n\n        //!\n        SCI_CUT = 2177,\n\n        //!\n        SCI_COPY = 2178,\n\n        //!\n        SCI_PASTE = 2179,\n\n        //!\n        SCI_CLEAR = 2180,\n\n        //! This message sets the text of the document.\n        //! \\a wParam is unused.\n        //! \\a lParam is the new text of the document.\n        //! \n        //! \\sa SCI_GETTEXT\n        SCI_SETTEXT = 2181,\n\n        //! This message gets the text of the document.\n        //! \\a wParam is size of the buffer that the text is copied to.\n        //! \\a lParam is the address of the buffer that the text is copied to.\n        //! \n        //! \\sa SCI_SETTEXT\n        SCI_GETTEXT = 2182,\n\n        //! This message returns the length of the document.\n        SCI_GETTEXTLENGTH = 2183,\n\n        //!\n        SCI_GETDIRECTFUNCTION = 2184,\n\n        //!\n        SCI_GETDIRECTPOINTER = 2185,\n\n        //!\n        SCI_SETOVERTYPE = 2186,\n\n        //!\n        SCI_GETOVERTYPE = 2187,\n\n        //!\n        SCI_SETCARETWIDTH = 2188,\n\n        //!\n        SCI_GETCARETWIDTH = 2189,\n\n        //!\n        SCI_SETTARGETSTART = 2190,\n\n        //!\n        SCI_GETTARGETSTART = 2191,\n\n        //!\n        SCI_SETTARGETEND = 2192,\n\n        //!\n        SCI_GETTARGETEND = 2193,\n\n        //!\n        SCI_REPLACETARGET = 2194,\n\n        //!\n        SCI_REPLACETARGETRE = 2195,\n\n        //!\n        SCI_SEARCHINTARGET = 2197,\n\n        //!\n        SCI_SETSEARCHFLAGS = 2198,\n\n        //!\n        SCI_GETSEARCHFLAGS = 2199,\n\n        //!\n        SCI_CALLTIPSHOW = 2200,\n\n        //!\n        SCI_CALLTIPCANCEL = 2201,\n\n        //!\n        SCI_CALLTIPACTIVE = 2202,\n\n        //!\n        SCI_CALLTIPPOSSTART = 2203,\n\n        //!\n        SCI_CALLTIPSETHLT = 2204,\n\n        //!\n        SCI_CALLTIPSETBACK = 2205,\n\n        //!\n        SCI_CALLTIPSETFORE = 2206,\n\n        //!\n        SCI_CALLTIPSETFOREHLT = 2207,\n\n        //!\n        SCI_AUTOCSETMAXWIDTH = 2208,\n\n        //!\n        SCI_AUTOCGETMAXWIDTH = 2209,\n\n        //! This message is not implemented.\n        SCI_AUTOCSETMAXHEIGHT = 2210,\n\n        //!\n        SCI_AUTOCGETMAXHEIGHT = 2211,\n\n        //!\n        SCI_CALLTIPUSESTYLE = 2212,\n\n        //!\n        SCI_CALLTIPSETPOSITION = 2213,\n\n        //!\n        SCI_CALLTIPSETPOSSTART = 2214,\n\n        //!\n        SCI_VISIBLEFROMDOCLINE = 2220,\n\n        //!\n        SCI_DOCLINEFROMVISIBLE = 2221,\n\n        //!\n        SCI_SETFOLDLEVEL = 2222,\n\n        //!\n        SCI_GETFOLDLEVEL = 2223,\n\n        //!\n        SCI_GETLASTCHILD = 2224,\n\n        //!\n        SCI_GETFOLDPARENT = 2225,\n\n        //!\n        SCI_SHOWLINES = 2226,\n\n        //!\n        SCI_HIDELINES = 2227,\n\n        //!\n        SCI_GETLINEVISIBLE = 2228,\n\n        //!\n        SCI_SETFOLDEXPANDED = 2229,\n\n        //!\n        SCI_GETFOLDEXPANDED = 2230,\n\n        //!\n        SCI_TOGGLEFOLD = 2231,\n\n        //!\n        SCI_ENSUREVISIBLE = 2232,\n\n        //!\n        SCI_SETFOLDFLAGS = 2233,\n\n        //!\n        SCI_ENSUREVISIBLEENFORCEPOLICY = 2234,\n\n        //!\n        SCI_WRAPCOUNT = 2235,\n\n        //!\n        SCI_GETALLLINESVISIBLE = 2236,\n\n        //!\n        SCI_FOLDLINE = 2237,\n\n        //!\n        SCI_FOLDCHILDREN = 2238,\n\n        //!\n        SCI_EXPANDCHILDREN = 2239,\n\n        //!\n        SCI_SETMARGINBACKN = 2250,\n\n        //!\n        SCI_GETMARGINBACKN = 2251,\n\n        //!\n        SCI_SETMARGINS = 2252,\n\n        //!\n        SCI_GETMARGINS = 2253,\n\n        //!\n        SCI_SETTABINDENTS = 2260,\n\n        //!\n        SCI_GETTABINDENTS = 2261,\n\n        //!\n        SCI_SETBACKSPACEUNINDENTS = 2262,\n\n        //!\n        SCI_GETBACKSPACEUNINDENTS = 2263,\n\n        //!\n        SCI_SETMOUSEDWELLTIME = 2264,\n\n        //!\n        SCI_GETMOUSEDWELLTIME = 2265,\n\n        //!\n        SCI_WORDSTARTPOSITION = 2266,\n\n        //!\n        SCI_WORDENDPOSITION = 2267,\n\n        //!\n        SCI_SETWRAPMODE = 2268,\n\n        //!\n        SCI_GETWRAPMODE = 2269,\n\n        //!\n        SCI_SETLAYOUTCACHE = 2272,\n\n        //!\n        SCI_GETLAYOUTCACHE = 2273,\n\n        //!\n        SCI_SETSCROLLWIDTH = 2274,\n\n        //!\n        SCI_GETSCROLLWIDTH = 2275,\n\n        //! This message returns the width of some text when rendered in a\n        //! particular style.\n        //! \\a wParam is the style number and is one of the STYLE_* values or\n        //! one of the styles defined by a lexer.\n        //! \\a lParam is a pointer to the text.\n        SCI_TEXTWIDTH = 2276,\n\n        //!\n        SCI_SETENDATLASTLINE = 2277,\n\n        //!\n        SCI_GETENDATLASTLINE = 2278,\n\n        //!\n        SCI_TEXTHEIGHT = 2279,\n\n        //!\n        SCI_SETVSCROLLBAR = 2280,\n\n        //!\n        SCI_GETVSCROLLBAR = 2281,\n\n        //!\n        SCI_APPENDTEXT = 2282,\n\n        //!\n        SCI_GETTWOPHASEDRAW = 2283,\n\n        //!\n        SCI_SETTWOPHASEDRAW = 2284,\n\n        //!\n        SCI_AUTOCGETTYPESEPARATOR = 2285,\n\n        //!\n        SCI_AUTOCSETTYPESEPARATOR = 2286,\n\n        //!\n        SCI_TARGETFROMSELECTION = 2287,\n\n        //!\n        SCI_LINESJOIN = 2288,\n\n        //!\n        SCI_LINESSPLIT = 2289,\n\n        //!\n        SCI_SETFOLDMARGINCOLOUR = 2290,\n\n        //!\n        SCI_SETFOLDMARGINHICOLOUR = 2291,\n\n        //!\n        SCI_MARKERSETBACKSELECTED = 2292,\n\n        //!\n        SCI_MARKERENABLEHIGHLIGHT = 2293,\n\n        //!\n        SCI_LINEDOWN = 2300,\n\n        //!\n        SCI_LINEDOWNEXTEND = 2301,\n\n        //!\n        SCI_LINEUP = 2302,\n\n        //!\n        SCI_LINEUPEXTEND = 2303,\n\n        //!\n        SCI_CHARLEFT = 2304,\n\n        //!\n        SCI_CHARLEFTEXTEND = 2305,\n\n        //!\n        SCI_CHARRIGHT = 2306,\n\n        //!\n        SCI_CHARRIGHTEXTEND = 2307,\n\n        //!\n        SCI_WORDLEFT = 2308,\n\n        //!\n        SCI_WORDLEFTEXTEND = 2309,\n\n        //!\n        SCI_WORDRIGHT = 2310,\n\n        //!\n        SCI_WORDRIGHTEXTEND = 2311,\n\n        //!\n        SCI_HOME = 2312,\n\n        //!\n        SCI_HOMEEXTEND = 2313,\n\n        //!\n        SCI_LINEEND = 2314,\n\n        //!\n        SCI_LINEENDEXTEND = 2315,\n\n        //!\n        SCI_DOCUMENTSTART = 2316,\n\n        //!\n        SCI_DOCUMENTSTARTEXTEND = 2317,\n\n        //!\n        SCI_DOCUMENTEND = 2318,\n\n        //!\n        SCI_DOCUMENTENDEXTEND = 2319,\n\n        //!\n        SCI_PAGEUP = 2320,\n\n        //!\n        SCI_PAGEUPEXTEND = 2321,\n\n        //!\n        SCI_PAGEDOWN = 2322,\n\n        //!\n        SCI_PAGEDOWNEXTEND = 2323,\n\n        //!\n        SCI_EDITTOGGLEOVERTYPE = 2324,\n\n        //!\n        SCI_CANCEL = 2325,\n\n        //!\n        SCI_DELETEBACK = 2326,\n\n        //!\n        SCI_TAB = 2327,\n\n        //!\n        SCI_BACKTAB = 2328,\n\n        //!\n        SCI_NEWLINE = 2329,\n\n        //!\n        SCI_FORMFEED = 2330,\n\n        //!\n        SCI_VCHOME = 2331,\n\n        //!\n        SCI_VCHOMEEXTEND = 2332,\n\n        //!\n        SCI_ZOOMIN = 2333,\n\n        //!\n        SCI_ZOOMOUT = 2334,\n\n        //!\n        SCI_DELWORDLEFT = 2335,\n\n        //!\n        SCI_DELWORDRIGHT = 2336,\n\n        //!\n        SCI_LINECUT = 2337,\n\n        //!\n        SCI_LINEDELETE = 2338,\n\n        //!\n        SCI_LINETRANSPOSE = 2339,\n\n        //!\n        SCI_LOWERCASE = 2340,\n\n        //!\n        SCI_UPPERCASE = 2341,\n\n        //!\n        SCI_LINESCROLLDOWN = 2342,\n\n        //!\n        SCI_LINESCROLLUP = 2343,\n\n        //!\n        SCI_DELETEBACKNOTLINE = 2344,\n\n        //!\n        SCI_HOMEDISPLAY = 2345,\n\n        //!\n        SCI_HOMEDISPLAYEXTEND = 2346,\n\n        //!\n        SCI_LINEENDDISPLAY = 2347,\n\n        //!\n        SCI_LINEENDDISPLAYEXTEND = 2348,\n\n        //!\n        SCI_MOVECARETINSIDEVIEW = 2401,\n\n        //!\n        SCI_LINELENGTH = 2350,\n\n        //!\n        SCI_BRACEHIGHLIGHT = 2351,\n\n        //!\n        SCI_BRACEBADLIGHT = 2352,\n\n        //!\n        SCI_BRACEMATCH = 2353,\n\n        //!\n        SCI_LINEREVERSE = 2354,\n\n        //!\n        SCI_GETVIEWEOL = 2355,\n\n        //!\n        SCI_SETVIEWEOL = 2356,\n\n        //!\n        SCI_GETDOCPOINTER = 2357,\n\n        //!\n        SCI_SETDOCPOINTER = 2358,\n\n        //!\n        SCI_SETMODEVENTMASK = 2359,\n\n        //!\n        SCI_GETEDGECOLUMN = 2360,\n\n        //!\n        SCI_SETEDGECOLUMN = 2361,\n\n        //!\n        SCI_GETEDGEMODE = 2362,\n\n        //!\n        SCI_SETEDGEMODE = 2363,\n\n        //!\n        SCI_GETEDGECOLOUR = 2364,\n\n        //!\n        SCI_SETEDGECOLOUR = 2365,\n\n        //!\n        SCI_SEARCHANCHOR = 2366,\n\n        //!\n        SCI_SEARCHNEXT = 2367,\n\n        //!\n        SCI_SEARCHPREV = 2368,\n\n        //!\n        SCI_LINESONSCREEN = 2370,\n\n        //!\n        SCI_USEPOPUP = 2371,\n\n        //!\n        SCI_SELECTIONISRECTANGLE = 2372,\n\n        //!\n        SCI_SETZOOM = 2373,\n\n        //!\n        SCI_GETZOOM = 2374,\n\n        //!\n        SCI_CREATEDOCUMENT = 2375,\n\n        //!\n        SCI_ADDREFDOCUMENT = 2376,\n\n        //!\n        SCI_RELEASEDOCUMENT = 2377,\n\n        //!\n        SCI_GETMODEVENTMASK = 2378,\n\n        //!\n        SCI_SETFOCUS = 2380,\n\n        //!\n        SCI_GETFOCUS = 2381,\n\n        //!\n        SCI_SETSTATUS = 2382,\n\n        //!\n        SCI_GETSTATUS = 2383,\n\n        //!\n        SCI_SETMOUSEDOWNCAPTURES = 2384,\n\n        //!\n        SCI_GETMOUSEDOWNCAPTURES = 2385,\n\n        //!\n        SCI_SETCURSOR = 2386,\n\n        //!\n        SCI_GETCURSOR = 2387,\n\n        //!\n        SCI_SETCONTROLCHARSYMBOL = 2388,\n\n        //!\n        SCI_GETCONTROLCHARSYMBOL = 2389,\n\n        //!\n        SCI_WORDPARTLEFT = 2390,\n\n        //!\n        SCI_WORDPARTLEFTEXTEND = 2391,\n\n        //!\n        SCI_WORDPARTRIGHT = 2392,\n\n        //!\n        SCI_WORDPARTRIGHTEXTEND = 2393,\n\n        //!\n        SCI_SETVISIBLEPOLICY = 2394,\n\n        //!\n        SCI_DELLINELEFT = 2395,\n\n        //!\n        SCI_DELLINERIGHT = 2396,\n\n        //!\n        SCI_SETXOFFSET = 2397,\n\n        //!\n        SCI_GETXOFFSET = 2398,\n\n        //!\n        SCI_CHOOSECARETX = 2399,\n\n        //!\n        SCI_GRABFOCUS = 2400,\n\n        //!\n        SCI_SETXCARETPOLICY = 2402,\n\n        //!\n        SCI_SETYCARETPOLICY = 2403,\n\n        //!\n        SCI_LINEDUPLICATE = 2404,\n\n        //! This message takes a copy of an image and registers it so that it\n        //! can be refered to by a unique integer identifier.\n        //! \\a wParam is the image's identifier.\n        //! \\a lParam is a pointer to a QPixmap instance.  Note that in other\n        //! ports of Scintilla this is a pointer to either raw or textual XPM\n        //! image data.\n        //!\n        //! \\sa SCI_CLEARREGISTEREDIMAGES, SCI_REGISTERRGBAIMAGE\n        SCI_REGISTERIMAGE = 2405,\n\n        //!\n        SCI_SETPRINTWRAPMODE = 2406,\n\n        //!\n        SCI_GETPRINTWRAPMODE = 2407,\n\n        //! This message de-registers all currently registered images.\n        //!\n        //! \\sa SCI_REGISTERIMAGE, SCI_REGISTERRGBAIMAGE\n        SCI_CLEARREGISTEREDIMAGES = 2408,\n\n        //!\n        SCI_STYLESETHOTSPOT = 2409,\n\n        //!\n        SCI_SETHOTSPOTACTIVEFORE = 2410,\n\n        //!\n        SCI_SETHOTSPOTACTIVEBACK = 2411,\n\n        //!\n        SCI_SETHOTSPOTACTIVEUNDERLINE = 2412,\n\n        //!\n        SCI_PARADOWN = 2413,\n\n        //!\n        SCI_PARADOWNEXTEND = 2414,\n\n        //!\n        SCI_PARAUP = 2415,\n\n        //!\n        SCI_PARAUPEXTEND = 2416,\n\n        //!\n        SCI_POSITIONBEFORE = 2417,\n\n        //!\n        SCI_POSITIONAFTER = 2418,\n\n        //!\n        SCI_COPYRANGE = 2419,\n\n        //!\n        SCI_COPYTEXT = 2420,\n\n        //!\n        SCI_SETHOTSPOTSINGLELINE = 2421,\n\n        //!\n        SCI_SETSELECTIONMODE = 2422,\n\n        //!\n        SCI_GETSELECTIONMODE = 2423,\n\n        //!\n        SCI_GETLINESELSTARTPOSITION = 2424,\n\n        //!\n        SCI_GETLINESELENDPOSITION = 2425,\n\n        //!\n        SCI_LINEDOWNRECTEXTEND = 2426,\n\n        //!\n        SCI_LINEUPRECTEXTEND = 2427,\n\n        //!\n        SCI_CHARLEFTRECTEXTEND = 2428,\n\n        //!\n        SCI_CHARRIGHTRECTEXTEND = 2429,\n\n        //!\n        SCI_HOMERECTEXTEND = 2430,\n\n        //!\n        SCI_VCHOMERECTEXTEND = 2431,\n\n        //!\n        SCI_LINEENDRECTEXTEND = 2432,\n\n        //!\n        SCI_PAGEUPRECTEXTEND = 2433,\n\n        //!\n        SCI_PAGEDOWNRECTEXTEND = 2434,\n\n        //!\n        SCI_STUTTEREDPAGEUP = 2435,\n\n        //!\n        SCI_STUTTEREDPAGEUPEXTEND = 2436,\n\n        //!\n        SCI_STUTTEREDPAGEDOWN = 2437,\n\n        //!\n        SCI_STUTTEREDPAGEDOWNEXTEND = 2438,\n\n        //!\n        SCI_WORDLEFTEND = 2439,\n\n        //!\n        SCI_WORDLEFTENDEXTEND = 2440,\n\n        //!\n        SCI_WORDRIGHTEND = 2441,\n\n        //!\n        SCI_WORDRIGHTENDEXTEND = 2442,\n\n        //!\n        SCI_SETWHITESPACECHARS = 2443,\n\n        //!\n        SCI_SETCHARSDEFAULT = 2444,\n\n        //!\n        SCI_AUTOCGETCURRENT = 2445,\n\n        //!\n        SCI_ALLOCATE = 2446,\n\n        //!\n        SCI_HOMEWRAP = 2349,\n\n        //!\n        SCI_HOMEWRAPEXTEND = 2450,\n\n        //!\n        SCI_LINEENDWRAP = 2451,\n\n        //!\n        SCI_LINEENDWRAPEXTEND = 2452,\n\n        //!\n        SCI_VCHOMEWRAP = 2453,\n\n        //!\n        SCI_VCHOMEWRAPEXTEND = 2454,\n\n        //!\n        SCI_LINECOPY = 2455,\n\n        //!\n        SCI_FINDCOLUMN = 2456,\n\n        //!\n        SCI_GETCARETSTICKY = 2457,\n\n        //!\n        SCI_SETCARETSTICKY = 2458,\n\n        //!\n        SCI_TOGGLECARETSTICKY = 2459,\n\n        //!\n        SCI_SETWRAPVISUALFLAGS = 2460,\n\n        //!\n        SCI_GETWRAPVISUALFLAGS = 2461,\n\n        //!\n        SCI_SETWRAPVISUALFLAGSLOCATION = 2462,\n\n        //!\n        SCI_GETWRAPVISUALFLAGSLOCATION = 2463,\n\n        //!\n        SCI_SETWRAPSTARTINDENT = 2464,\n\n        //!\n        SCI_GETWRAPSTARTINDENT = 2465,\n\n        //!\n        SCI_MARKERADDSET = 2466,\n\n        //!\n        SCI_SETPASTECONVERTENDINGS = 2467,\n\n        //!\n        SCI_GETPASTECONVERTENDINGS = 2468,\n\n        //!\n        SCI_SELECTIONDUPLICATE = 2469,\n\n        //!\n        SCI_SETCARETLINEBACKALPHA = 2470,\n\n        //!\n        SCI_GETCARETLINEBACKALPHA = 2471,\n\n        //!\n        SCI_SETWRAPINDENTMODE = 2472,\n\n        //!\n        SCI_GETWRAPINDENTMODE = 2473,\n\n        //!\n        SCI_MARKERSETALPHA = 2476,\n\n        //!\n        SCI_GETSELALPHA = 2477,\n\n        //!\n        SCI_SETSELALPHA = 2478,\n\n        //!\n        SCI_GETSELEOLFILLED = 2479,\n\n        //!\n        SCI_SETSELEOLFILLED = 2480,\n\n        //!\n        SCI_STYLEGETFORE = 2481,\n\n        //!\n        SCI_STYLEGETBACK = 2482,\n\n        //!\n        SCI_STYLEGETBOLD = 2483,\n\n        //!\n        SCI_STYLEGETITALIC = 2484,\n\n        //!\n        SCI_STYLEGETSIZE = 2485,\n\n        //!\n        SCI_STYLEGETFONT = 2486,\n\n        //!\n        SCI_STYLEGETEOLFILLED = 2487,\n\n        //!\n        SCI_STYLEGETUNDERLINE = 2488,\n\n        //!\n        SCI_STYLEGETCASE = 2489,\n\n        //!\n        SCI_STYLEGETCHARACTERSET = 2490,\n\n        //!\n        SCI_STYLEGETVISIBLE = 2491,\n\n        //!\n        SCI_STYLEGETCHANGEABLE = 2492,\n\n        //!\n        SCI_STYLEGETHOTSPOT = 2493,\n\n        //!\n        SCI_GETHOTSPOTACTIVEFORE = 2494,\n\n        //!\n        SCI_GETHOTSPOTACTIVEBACK = 2495,\n\n        //!\n        SCI_GETHOTSPOTACTIVEUNDERLINE = 2496,\n\n        //!\n        SCI_GETHOTSPOTSINGLELINE = 2497,\n\n        //!\n        SCI_BRACEHIGHLIGHTINDICATOR = 2498,\n\n        //!\n        SCI_BRACEBADLIGHTINDICATOR = 2499,\n\n        //!\n        SCI_SETINDICATORCURRENT = 2500,\n\n        //!\n        SCI_GETINDICATORCURRENT = 2501,\n\n        //!\n        SCI_SETINDICATORVALUE = 2502,\n\n        //!\n        SCI_GETINDICATORVALUE = 2503,\n\n        //!\n        SCI_INDICATORFILLRANGE = 2504,\n\n        //!\n        SCI_INDICATORCLEARRANGE = 2505,\n\n        //!\n        SCI_INDICATORALLONFOR = 2506,\n\n        //!\n        SCI_INDICATORVALUEAT = 2507,\n\n        //!\n        SCI_INDICATORSTART = 2508,\n\n        //!\n        SCI_INDICATOREND = 2509,\n\n        //!\n        SCI_INDICSETUNDER = 2510,\n\n        //!\n        SCI_INDICGETUNDER = 2511,\n\n        //!\n        SCI_SETCARETSTYLE = 2512,\n\n        //!\n        SCI_GETCARETSTYLE = 2513,\n\n        //!\n        SCI_SETPOSITIONCACHE = 2514,\n\n        //!\n        SCI_GETPOSITIONCACHE = 2515,\n\n        //!\n        SCI_SETSCROLLWIDTHTRACKING = 2516,\n\n        //!\n        SCI_GETSCROLLWIDTHTRACKING = 2517,\n\n        //!\n        SCI_DELWORDRIGHTEND = 2518,\n\n        //! This message copies the selection.  If the selection is empty then\n        //! copy the line with the caret.\n        SCI_COPYALLOWLINE = 2519,\n\n        //! This message returns a pointer to the document text.  Any\n        //! subsequent message will invalidate the pointer.\n        SCI_GETCHARACTERPOINTER = 2520,\n\n        //!\n        SCI_INDICSETALPHA = 2523,\n\n        //!\n        SCI_INDICGETALPHA = 2524,\n\n        //!\n        SCI_SETEXTRAASCENT = 2525,\n\n        //!\n        SCI_GETEXTRAASCENT = 2526,\n\n        //!\n        SCI_SETEXTRADESCENT = 2527,\n\n        //!\n        SCI_GETEXTRADESCENT = 2528,\n\n        //!\n        SCI_MARKERSYMBOLDEFINED = 2529,\n\n        //!\n        SCI_MARGINSETTEXT = 2530,\n\n        //!\n        SCI_MARGINGETTEXT = 2531,\n\n        //!\n        SCI_MARGINSETSTYLE = 2532,\n\n        //!\n        SCI_MARGINGETSTYLE = 2533,\n\n        //!\n        SCI_MARGINSETSTYLES = 2534,\n\n        //!\n        SCI_MARGINGETSTYLES = 2535,\n\n        //!\n        SCI_MARGINTEXTCLEARALL = 2536,\n\n        //!\n        SCI_MARGINSETSTYLEOFFSET = 2537,\n\n        //!\n        SCI_MARGINGETSTYLEOFFSET = 2538,\n\n        //!\n        SCI_SETMARGINOPTIONS = 2539,\n\n        //!\n        SCI_ANNOTATIONSETTEXT = 2540,\n\n        //!\n        SCI_ANNOTATIONGETTEXT = 2541,\n\n        //!\n        SCI_ANNOTATIONSETSTYLE = 2542,\n\n        //!\n        SCI_ANNOTATIONGETSTYLE = 2543,\n\n        //!\n        SCI_ANNOTATIONSETSTYLES = 2544,\n\n        //!\n        SCI_ANNOTATIONGETSTYLES = 2545,\n\n        //!\n        SCI_ANNOTATIONGETLINES = 2546,\n\n        //!\n        SCI_ANNOTATIONCLEARALL = 2547,\n\n        //!\n        SCI_ANNOTATIONSETVISIBLE = 2548,\n\n        //!\n        SCI_ANNOTATIONGETVISIBLE = 2549,\n\n        //!\n        SCI_ANNOTATIONSETSTYLEOFFSET = 2550,\n\n        //!\n        SCI_ANNOTATIONGETSTYLEOFFSET = 2551,\n\n        //!\n        SCI_RELEASEALLEXTENDEDSTYLES = 2552,\n\n        //!\n        SCI_ALLOCATEEXTENDEDSTYLES = 2553,\n\n        //!\n        SCI_SETEMPTYSELECTION = 2556,\n\n        //!\n        SCI_GETMARGINOPTIONS = 2557,\n\n        //!\n        SCI_INDICSETOUTLINEALPHA = 2558,\n\n        //!\n        SCI_INDICGETOUTLINEALPHA = 2559,\n\n        //!\n        SCI_ADDUNDOACTION = 2560,\n\n        //!\n        SCI_CHARPOSITIONFROMPOINT = 2561,\n\n        //!\n        SCI_CHARPOSITIONFROMPOINTCLOSE = 2562,\n\n        //!\n        SCI_SETMULTIPLESELECTION = 2563,\n\n        //!\n        SCI_GETMULTIPLESELECTION = 2564,\n\n        //!\n        SCI_SETADDITIONALSELECTIONTYPING = 2565,\n\n        //!\n        SCI_GETADDITIONALSELECTIONTYPING = 2566,\n\n        //!\n        SCI_SETADDITIONALCARETSBLINK = 2567,\n\n        //!\n        SCI_GETADDITIONALCARETSBLINK = 2568,\n\n        //!\n        SCI_SCROLLRANGE = 2569,\n\n        //!\n        SCI_GETSELECTIONS = 2570,\n\n        //!\n        SCI_CLEARSELECTIONS = 2571,\n\n        //!\n        SCI_SETSELECTION = 2572,\n\n        //!\n        SCI_ADDSELECTION = 2573,\n\n        //!\n        SCI_SETMAINSELECTION = 2574,\n\n        //!\n        SCI_GETMAINSELECTION = 2575,\n\n        //!\n        SCI_SETSELECTIONNCARET = 2576,\n\n        //!\n        SCI_GETSELECTIONNCARET = 2577,\n\n        //!\n        SCI_SETSELECTIONNANCHOR = 2578,\n\n        //!\n        SCI_GETSELECTIONNANCHOR = 2579,\n\n        //!\n        SCI_SETSELECTIONNCARETVIRTUALSPACE = 2580,\n\n        //!\n        SCI_GETSELECTIONNCARETVIRTUALSPACE = 2581,\n\n        //!\n        SCI_SETSELECTIONNANCHORVIRTUALSPACE = 2582,\n\n        //!\n        SCI_GETSELECTIONNANCHORVIRTUALSPACE = 2583,\n\n        //!\n        SCI_SETSELECTIONNSTART = 2584,\n\n        //!\n        SCI_GETSELECTIONNSTART = 2585,\n\n        //!\n        SCI_SETSELECTIONNEND = 2586,\n\n        //!\n        SCI_GETSELECTIONNEND = 2587,\n\n        //!\n        SCI_SETRECTANGULARSELECTIONCARET = 2588,\n\n        //!\n        SCI_GETRECTANGULARSELECTIONCARET = 2589,\n\n        //!\n        SCI_SETRECTANGULARSELECTIONANCHOR = 2590,\n\n        //!\n        SCI_GETRECTANGULARSELECTIONANCHOR = 2591,\n\n        //!\n        SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE = 2592,\n\n        //!\n        SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE = 2593,\n\n        //!\n        SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE = 2594,\n\n        //!\n        SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE = 2595,\n\n        //!\n        SCI_SETVIRTUALSPACEOPTIONS = 2596,\n\n        //!\n        SCI_GETVIRTUALSPACEOPTIONS = 2597,\n\n        //!\n        SCI_SETRECTANGULARSELECTIONMODIFIER = 2598,\n\n        //!\n        SCI_GETRECTANGULARSELECTIONMODIFIER = 2599,\n\n        //!\n        SCI_SETADDITIONALSELFORE = 2600,\n\n        //!\n        SCI_SETADDITIONALSELBACK = 2601,\n\n        //!\n        SCI_SETADDITIONALSELALPHA = 2602,\n\n        //!\n        SCI_GETADDITIONALSELALPHA = 2603,\n\n        //!\n        SCI_SETADDITIONALCARETFORE = 2604,\n\n        //!\n        SCI_GETADDITIONALCARETFORE = 2605,\n\n        //!\n        SCI_ROTATESELECTION = 2606,\n\n        //!\n        SCI_SWAPMAINANCHORCARET = 2607,\n\n        //!\n        SCI_SETADDITIONALCARETSVISIBLE = 2608,\n\n        //!\n        SCI_GETADDITIONALCARETSVISIBLE = 2609,\n\n        //!\n        SCI_AUTOCGETCURRENTTEXT = 2610,\n\n        //!\n        SCI_SETFONTQUALITY = 2611,\n\n        //!\n        SCI_GETFONTQUALITY = 2612,\n\n        //!\n        SCI_SETFIRSTVISIBLELINE = 2613,\n\n        //!\n        SCI_SETMULTIPASTE = 2614,\n\n        //!\n        SCI_GETMULTIPASTE = 2615,\n\n        //!\n        SCI_GETTAG = 2616,\n\n        //!\n        SCI_CHANGELEXERSTATE = 2617,\n\n        //!\n        SCI_CONTRACTEDFOLDNEXT = 2618,\n\n        //!\n        SCI_VERTICALCENTRECARET = 2619,\n\n        //!\n        SCI_MOVESELECTEDLINESUP = 2620,\n\n        //!\n        SCI_MOVESELECTEDLINESDOWN = 2621,\n\n        //!\n        SCI_SETIDENTIFIER = 2622,\n\n        //!\n        SCI_GETIDENTIFIER = 2623,\n\n        //! This message sets the width of an RGBA image specified by a future\n        //! call to SCI_MARKERDEFINERGBAIMAGE or SCI_REGISTERRGBAIMAGE.\n        //!\n        //! \\sa SCI_RGBAIMAGESETHEIGHT, SCI_MARKERDEFINERGBAIMAGE,\n        //! SCI_REGISTERRGBAIMAGE.\n        SCI_RGBAIMAGESETWIDTH = 2624,\n\n        //! This message sets the height of an RGBA image specified by a future\n        //! call to SCI_MARKERDEFINERGBAIMAGE or SCI_REGISTERRGBAIMAGE.\n        //!\n        //! \\sa SCI_RGBAIMAGESETWIDTH, SCI_MARKERDEFINERGBAIMAGE,\n        //! SCI_REGISTERRGBAIMAGE.\n        SCI_RGBAIMAGESETHEIGHT = 2625,\n\n        //! This message sets the symbol used to draw one of the 32 markers to\n        //! an RGBA image.  RGBA images use the SC_MARK_RGBAIMAGE marker\n        //! symbol.\n        //! \\a wParam is the number of the marker.\n        //! \\a lParam is a pointer to a QImage instance.  Note that in other\n        //! ports of Scintilla this is a pointer to raw RGBA image data.\n        //!\n        //! \\sa SCI_MARKERDEFINE, SCI_MARKERDEFINEPIXMAP\n        SCI_MARKERDEFINERGBAIMAGE = 2626,\n\n        //! This message takes a copy of an image and registers it so that it\n        //! can be refered to by a unique integer identifier.\n        //! \\a wParam is the image's identifier.\n        //! \\a lParam is a pointer to a QImage instance.  Note that in other\n        //! ports of Scintilla this is a pointer to raw RGBA image data.\n        //!\n        //! \\sa SCI_CLEARREGISTEREDIMAGES, SCI_REGISTERIMAGE\n        SCI_REGISTERRGBAIMAGE = 2627,\n\n        //!\n        SCI_SCROLLTOSTART = 2628,\n\n        //!\n        SCI_SCROLLTOEND = 2629,\n\n        //!\n        SCI_SETTECHNOLOGY = 2630,\n\n        //!\n        SCI_GETTECHNOLOGY = 2631,\n\n        //!\n        SCI_CREATELOADER = 2632,\n\n        //!\n        SCI_COUNTCHARACTERS = 2633,\n\n        //!\n        SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR = 2634,\n\n        //!\n        SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR = 2635,\n\n        //!\n        SCI_AUTOCSETMULTI = 2636,\n\n        //!\n        SCI_AUTOCGETMULTI = 2637,\n\n        //!\n        SCI_FINDINDICATORSHOW = 2640,\n\n        //!\n        SCI_FINDINDICATORFLASH = 2641,\n\n        //!\n        SCI_FINDINDICATORHIDE = 2642,\n\n        //!\n        SCI_GETRANGEPOINTER = 2643,\n\n        //!\n        SCI_GETGAPPOSITION = 2644,\n\n        //!\n        SCI_DELETERANGE = 2645,\n\n        //!\n        SCI_GETWORDCHARS = 2646,\n\n        //!\n        SCI_GETWHITESPACECHARS = 2647,\n\n        //!\n        SCI_SETPUNCTUATIONCHARS = 2648,\n\n        //!\n        SCI_GETPUNCTUATIONCHARS = 2649,\n\n        //!\n        SCI_GETSELECTIONEMPTY = 2650,\n\n        //!\n        SCI_RGBAIMAGESETSCALE = 2651,\n\n        //!\n        SCI_VCHOMEDISPLAY = 2652,\n\n        //!\n        SCI_VCHOMEDISPLAYEXTEND = 2653,\n\n        //!\n        SCI_GETCARETLINEVISIBLEALWAYS = 2654,\n\n        //!\n        SCI_SETCARETLINEVISIBLEALWAYS = 2655,\n\n        //!\n        SCI_SETLINEENDTYPESALLOWED = 2656,\n\n        //!\n        SCI_GETLINEENDTYPESALLOWED = 2657,\n\n        //!\n        SCI_GETLINEENDTYPESACTIVE = 2658,\n\n        //!\n        SCI_AUTOCSETORDER = 2660,\n\n        //!\n        SCI_AUTOCGETORDER = 2661,\n\n        //!\n        SCI_FOLDALL = 2662,\n\n        //!\n        SCI_SETAUTOMATICFOLD = 2663,\n\n        //!\n        SCI_GETAUTOMATICFOLD = 2664,\n\n        //!\n        SCI_SETREPRESENTATION = 2665,\n\n        //!\n        SCI_GETREPRESENTATION = 2666,\n\n        //!\n        SCI_CLEARREPRESENTATION = 2667,\n\n        //!\n        SCI_SETMOUSESELECTIONRECTANGULARSWITCH = 2668,\n\n        //!\n        SCI_GETMOUSESELECTIONRECTANGULARSWITCH = 2669,\n\n        //!\n        SCI_POSITIONRELATIVE = 2670,\n\n        //!\n        SCI_DROPSELECTIONN = 2671,\n\n        //!\n        SCI_CHANGEINSERTION = 2672,\n\n        //!\n        SCI_GETPHASESDRAW = 2673,\n\n        //!\n        SCI_SETPHASESDRAW = 2674,\n\n        //!\n        SCI_CLEARTABSTOPS = 2675,\n\n        //!\n        SCI_ADDTABSTOP = 2676,\n\n        //!\n        SCI_GETNEXTTABSTOP = 2677,\n\n        //!\n        SCI_GETIMEINTERACTION = 2678,\n\n        //!\n        SCI_SETIMEINTERACTION = 2679,\n\n        //!\n        SCI_INDICSETHOVERSTYLE = 2680,\n\n        //!\n        SCI_INDICGETHOVERSTYLE = 2681,\n\n        //!\n        SCI_INDICSETHOVERFORE = 2682,\n\n        //!\n        SCI_INDICGETHOVERFORE = 2683,\n\n        //!\n        SCI_INDICSETFLAGS = 2684,\n\n        //!\n        SCI_INDICGETFLAGS = 2685,\n\n        //!\n        SCI_SETTARGETRANGE = 2686,\n\n        //!\n        SCI_GETTARGETTEXT = 2687,\n\n        //!\n        SCI_MULTIPLESELECTADDNEXT = 2688,\n\n        //!\n        SCI_MULTIPLESELECTADDEACH = 2689,\n\n        //!\n        SCI_TARGETWHOLEDOCUMENT = 2690,\n\n        //!\n        SCI_ISRANGEWORD = 2691,\n\n        //!\n        SCI_SETIDLESTYLING = 2692,\n\n        //!\n        SCI_GETIDLESTYLING = 2693,\n\n        //!\n        SCI_MULTIEDGEADDLINE = 2694,\n\n        //!\n        SCI_MULTIEDGECLEARALL = 2695,\n\n        //!\n        SCI_SETMOUSEWHEELCAPTURES = 2696,\n\n        //!\n        SCI_GETMOUSEWHEELCAPTURES = 2697,\n\n        //!\n        SCI_GETTABDRAWMODE = 2698,\n\n        //!\n        SCI_SETTABDRAWMODE = 2699,\n\n        //!\n        SCI_TOGGLEFOLDSHOWTEXT = 2700,\n\n        //!\n        SCI_FOLDDISPLAYTEXTSETSTYLE = 2701,\n\n        //!\n        SCI_SETACCESSIBILITY = 2702,\n\n        //!\n        SCI_GETACCESSIBILITY = 2703,\n\n        //!\n        SCI_GETCARETLINEFRAME = 2704,\n\n        //!\n        SCI_SETCARETLINEFRAME = 2705,\n\n        //!\n        SCI_STARTRECORD = 3001,\n\n        //!\n        SCI_STOPRECORD = 3002,\n\n        //! This message sets the number of the lexer to use for syntax\n        //! styling.\n        //! \\a wParam is the number of the lexer and is one of the SCLEX_*\n        //! values.\n        SCI_SETLEXER = 4001,\n\n        //! This message returns the number of the lexer being used for syntax\n        //! styling.\n        SCI_GETLEXER = 4002,\n\n        //!\n        SCI_COLOURISE = 4003,\n\n        //!\n        SCI_SETPROPERTY = 4004,\n\n        //!\n        SCI_SETKEYWORDS = 4005,\n\n        //! This message sets the name of the lexer to use for syntax styling.\n        //! \\a wParam is unused.\n        //! \\a lParam is the name of the lexer.\n        SCI_SETLEXERLANGUAGE = 4006,\n\n        //!\n        SCI_LOADLEXERLIBRARY = 4007,\n\n        //!\n        SCI_GETPROPERTY = 4008,\n\n        //!\n        SCI_GETPROPERTYEXPANDED = 4009,\n\n        //!\n        SCI_GETPROPERTYINT = 4010,\n\n        //!\n        SCI_GETSTYLEBITSNEEDED = 4011,\n\n        //!\n        SCI_GETLEXERLANGUAGE = 4012,\n\n        //!\n        SCI_PRIVATELEXERCALL = 4013,\n\n        //!\n        SCI_PROPERTYNAMES = 4014,\n\n        //!\n        SCI_PROPERTYTYPE = 4015,\n\n        //!\n        SCI_DESCRIBEPROPERTY = 4016,\n\n        //!\n        SCI_DESCRIBEKEYWORDSETS = 4017,\n\n        //!\n        SCI_GETLINEENDTYPESSUPPORTED = 4018,\n\n        //!\n        SCI_ALLOCATESUBSTYLES = 4020,\n\n        //!\n        SCI_GETSUBSTYLESSTART = 4021,\n\n        //!\n        SCI_GETSUBSTYLESLENGTH = 4022,\n\n        //!\n        SCI_GETSTYLEFROMSUBSTYLE = 4027,\n\n        //!\n        SCI_GETPRIMARYSTYLEFROMSTYLE = 4028,\n\n        //!\n        SCI_FREESUBSTYLES = 4023,\n\n        //!\n        SCI_SETIDENTIFIERS = 4024,\n\n        //!\n        SCI_DISTANCETOSECONDARYSTYLES = 4025,\n\n        //!\n        SCI_GETSUBSTYLEBASES = 4026,\n\n        //!\n        SCI_GETLINECHARACTERINDEX = 2710,\n\n        //!\n        SCI_ALLOCATELINECHARACTERINDEX = 2711,\n\n        //!\n        SCI_RELEASELINECHARACTERINDEX = 2712,\n\n        //!\n        SCI_LINEFROMINDEXPOSITION = 2713,\n\n        //!\n        SCI_INDEXPOSITIONFROMLINE = 2714,\n\n        //!\n        SCI_COUNTCODEUNITS = 2715,\n\n        //!\n        SCI_POSITIONRELATIVECODEUNITS = 2716,\n\n        //!\n        SCI_GETNAMEDSTYLES = 4029,\n\n        //!\n        SCI_NAMEOFSTYLE = 4030,\n\n        //!\n        SCI_TAGSOFSTYLE = 4031,\n\n        //!\n        SCI_DESCRIPTIONOFSTYLE = 4032,\n\n        //!\n        SCI_GETMOVEEXTENDSSELECTION = 2706,\n\n        //!\n        SCI_SETCOMMANDEVENTS = 2717,\n\n        //!\n        SCI_GETCOMMANDEVENTS = 2718,\n\n        //!\n        SCI_GETDOCUMENTOPTIONS = 2379,\n    };\n\n\tenum\n\t{\n\t\tSC_AC_FILLUP = 1,\n\t\tSC_AC_DOUBLECLICK = 2,\n\t\tSC_AC_TAB = 3,\n\t\tSC_AC_NEWLINE = 4,\n\t\tSC_AC_COMMAND = 5,\n\t};\n\n    enum\n    {\n        SC_ALPHA_TRANSPARENT = 0,\n        SC_ALPHA_OPAQUE = 255,\n        SC_ALPHA_NOALPHA = 256\n    };\n\n    enum\n    {\n        SC_CARETSTICKY_OFF = 0,\n        SC_CARETSTICKY_ON = 1,\n        SC_CARETSTICKY_WHITESPACE = 2\n    };\n\n    enum\n    {\n        SC_DOCUMENTOPTION_DEFAULT = 0x0000,\n        SC_DOCUMENTOPTION_STYLES_NONE = 0x0001,\n        SC_DOCUMENTOPTION_TEXT_LARGE = 0x0100,\n    };\n\n    enum\n    {\n        SC_EFF_QUALITY_MASK = 0x0f,\n        SC_EFF_QUALITY_DEFAULT = 0,\n        SC_EFF_QUALITY_NON_ANTIALIASED = 1,\n        SC_EFF_QUALITY_ANTIALIASED = 2,\n        SC_EFF_QUALITY_LCD_OPTIMIZED = 3\n    };\n\n    enum\n    {\n        SC_IDLESTYLING_NONE = 0,\n        SC_IDLESTYLING_TOVISIBLE = 1,\n        SC_IDLESTYLING_AFTERVISIBLE = 2,\n        SC_IDLESTYLING_ALL = 3,\n    };\n\n    enum\n    {\n        SC_IME_WINDOWED = 0,\n        SC_IME_INLINE = 1,\n    };\n\n    enum\n    {\n        SC_LINECHARACTERINDEX_NONE = 0,\n        SC_LINECHARACTERINDEX_UTF32 = 1,\n        SC_LINECHARACTERINDEX_UTF16 = 2,\n    };\n\n    enum\n    {\n        SC_MARGINOPTION_NONE = 0x00,\n        SC_MARGINOPTION_SUBLINESELECT = 0x01\n    };\n\n    enum\n    {\n        SC_MULTIAUTOC_ONCE = 0,\n        SC_MULTIAUTOC_EACH = 1\n    };\n\n    enum\n    {\n        SC_MULTIPASTE_ONCE = 0,\n        SC_MULTIPASTE_EACH = 1\n    };\n\n    enum\n    {\n        SC_POPUP_NEVER = 0,\n        SC_POPUP_ALL = 1,\n        SC_POPUP_TEXT = 2,\n    };\n\n    //! This enum defines the different selection modes.\n    //!\n    //! \\sa SCI_GETSELECTIONMODE, SCI_SETSELECTIONMODE\n    enum\n    {\n        SC_SEL_STREAM = 0,\n        SC_SEL_RECTANGLE = 1,\n        SC_SEL_LINES = 2,\n        SC_SEL_THIN = 3\n    };\n\n    enum\n    {\n        SC_STATUS_OK = 0,\n        SC_STATUS_FAILURE = 1,\n        SC_STATUS_BADALLOC = 2,\n        SC_STATUS_WARN_START = 1000,\n        SC_STATUS_WARNREGEX = 1001,\n    };\n\n    enum\n    {\n        SC_TYPE_BOOLEAN = 0,\n        SC_TYPE_INTEGER = 1,\n        SC_TYPE_STRING = 2\n    };\n\n    enum\n    {\n        SC_UPDATE_CONTENT = 0x01,\n        SC_UPDATE_SELECTION = 0x02,\n        SC_UPDATE_V_SCROLL = 0x04,\n        SC_UPDATE_H_SCROLL = 0x08\n    };\n\n    enum\n    {\n        SC_WRAPVISUALFLAG_NONE = 0x0000,\n        SC_WRAPVISUALFLAG_END = 0x0001,\n        SC_WRAPVISUALFLAG_START = 0x0002,\n        SC_WRAPVISUALFLAG_MARGIN = 0x0004\n    };\n\n    enum\n    {\n        SC_WRAPVISUALFLAGLOC_DEFAULT = 0x0000,\n        SC_WRAPVISUALFLAGLOC_END_BY_TEXT = 0x0001,\n        SC_WRAPVISUALFLAGLOC_START_BY_TEXT = 0x0002\n    };\n\n    enum\n    {\n        SCTD_LONGARROW = 0,\n        SCTD_STRIKEOUT = 1,\n    };\n\n    enum\n    {\n        SCVS_NONE = 0,\n        SCVS_RECTANGULARSELECTION = 1,\n        SCVS_USERACCESSIBLE = 2,\n        SCVS_NOWRAPLINESTART = 4,\n    };\n\n    enum\n    {\n        SCWS_INVISIBLE = 0,\n        SCWS_VISIBLEALWAYS = 1,\n        SCWS_VISIBLEAFTERINDENT = 2,\n        SCWS_VISIBLEONLYININDENT = 3,\n    };\n\n    enum\n    {\n        SC_EOL_CRLF = 0,\n        SC_EOL_CR = 1,\n        SC_EOL_LF = 2\n    };\n\n    enum\n    {\n        SC_CP_DBCS = 1,\n        SC_CP_UTF8 = 65001\n    };\n\n    //! This enum defines the different marker symbols.\n    //!\n    //! \\sa SCI_MARKERDEFINE\n    enum\n    {\n        //! A circle.\n        SC_MARK_CIRCLE = 0,\n\n        //! A rectangle.\n        SC_MARK_ROUNDRECT = 1,\n\n        //! A triangle pointing to the right.\n        SC_MARK_ARROW = 2,\n\n        //! A smaller rectangle.\n        SC_MARK_SMALLRECT = 3,\n\n        //! An arrow pointing to the right.\n        SC_MARK_SHORTARROW = 4,\n\n        //! An invisible marker that allows code to track the movement\n        //! of lines.\n        SC_MARK_EMPTY = 5,\n\n        //! A triangle pointing down.\n        SC_MARK_ARROWDOWN = 6,\n\n        //! A drawn minus sign.\n        SC_MARK_MINUS = 7,\n\n        //! A drawn plus sign.\n        SC_MARK_PLUS = 8,\n\n        //! A vertical line drawn in the background colour.\n        SC_MARK_VLINE = 9,\n\n        //! A bottom left corner drawn in the background colour.\n        SC_MARK_LCORNER = 10,\n\n        //! A vertical line with a centre right horizontal line drawn\n        //! in the background colour.\n        SC_MARK_TCORNER = 11,\n\n        //! A drawn plus sign in a box.\n        SC_MARK_BOXPLUS = 12,\n\n        //! A drawn plus sign in a connected box.\n        SC_MARK_BOXPLUSCONNECTED = 13,\n\n        //! A drawn minus sign in a box.\n        SC_MARK_BOXMINUS = 14,\n\n        //! A drawn minus sign in a connected box.\n        SC_MARK_BOXMINUSCONNECTED = 15,\n\n        //! A rounded bottom left corner drawn in the background\n        //! colour.\n        SC_MARK_LCORNERCURVE = 16,\n\n        //! A vertical line with a centre right curved line drawn in\n        //! the background colour.\n        SC_MARK_TCORNERCURVE = 17,\n\n        //! A drawn plus sign in a circle.\n        SC_MARK_CIRCLEPLUS = 18,\n\n        //! A drawn plus sign in a connected box.\n        SC_MARK_CIRCLEPLUSCONNECTED = 19,\n\n        //! A drawn minus sign in a circle.\n        SC_MARK_CIRCLEMINUS = 20,\n\n        //! A drawn minus sign in a connected circle.\n        SC_MARK_CIRCLEMINUSCONNECTED = 21,\n\n        //! No symbol is drawn but the line is drawn with the same background\n        //! color as the marker's.\n        SC_MARK_BACKGROUND = 22,\n\n        //! Three drawn dots.\n        SC_MARK_DOTDOTDOT = 23,\n\n        //! Three drawn arrows pointing right.\n        SC_MARK_ARROWS = 24,\n\n        //! An XPM format pixmap.\n        SC_MARK_PIXMAP = 25,\n\n        //! A full rectangle (ie. the margin background) using the marker's\n        //! background color.\n        SC_MARK_FULLRECT = 26,\n\n        //! A left rectangle (ie. the left part of the margin background) using\n        //! the marker's background color.\n        SC_MARK_LEFTRECT = 27,\n\n        //! The value is available for plugins to use.\n        SC_MARK_AVAILABLE = 28,\n\n        //! The line is underlined using the marker's background color.\n        SC_MARK_UNDERLINE = 29,\n\n        //! A RGBA format image.\n        SC_MARK_RGBAIMAGE = 30,\n\n        //! A bookmark.\n        SC_MARK_BOOKMARK = 31,\n\n        //! Characters can be used as symbols by adding this to the ASCII value\n        //! of the character.\n        SC_MARK_CHARACTER = 10000\n    };\n\n    enum\n    {\n        SC_MARKNUM_FOLDEREND = 25,\n        SC_MARKNUM_FOLDEROPENMID = 26,\n        SC_MARKNUM_FOLDERMIDTAIL = 27,\n        SC_MARKNUM_FOLDERTAIL = 28,\n        SC_MARKNUM_FOLDERSUB = 29,\n        SC_MARKNUM_FOLDER = 30,\n        SC_MARKNUM_FOLDEROPEN = 31,\n        SC_MASK_FOLDERS = 0xfe000000\n    };\n\n    //! This enum defines what can be displayed in a margin.\n    //!\n    //! \\sa SCI_GETMARGINTYPEN, SCI_SETMARGINTYPEN\n    enum\n    {\n        //! The margin can display symbols.  Note that all margins can display\n        //! symbols.\n        SC_MARGIN_SYMBOL = 0,\n\n        //! The margin will display line numbers.\n        SC_MARGIN_NUMBER = 1,\n\n        //! The margin's background color will be set to the default background\n        //! color.\n        SC_MARGIN_BACK = 2,\n\n        //! The margin's background color will be set to the default foreground\n        //! color.\n        SC_MARGIN_FORE = 3,\n\n        //! The margin will display text.\n        SC_MARGIN_TEXT = 4,\n\n        //! The margin will display right justified text.\n        SC_MARGIN_RTEXT = 5,\n\n        //! The margin's background color will be set to the color set by\n        //! SCI_SETMARGINBACKN.\n        SC_MARGIN_COLOUR = 6,\n    };\n\n    enum\n    {\n        STYLE_DEFAULT = 32,\n        STYLE_LINENUMBER = 33,\n        STYLE_BRACELIGHT = 34,\n        STYLE_BRACEBAD = 35,\n        STYLE_CONTROLCHAR = 36,\n        STYLE_INDENTGUIDE = 37,\n        STYLE_CALLTIP = 38,\n        STYLE_FOLDDISPLAYTEXT = 39,\n        STYLE_LASTPREDEFINED = 39,\n        STYLE_MAX = 255\n    };\n\n    enum\n    {\n        SC_CHARSET_ANSI = 0,\n        SC_CHARSET_DEFAULT = 1,\n        SC_CHARSET_BALTIC = 186,\n        SC_CHARSET_CHINESEBIG5 = 136,\n        SC_CHARSET_EASTEUROPE = 238,\n        SC_CHARSET_GB2312 = 134,\n        SC_CHARSET_GREEK = 161,\n        SC_CHARSET_HANGUL = 129,\n        SC_CHARSET_MAC = 77,\n        SC_CHARSET_OEM = 255,\n        SC_CHARSET_RUSSIAN = 204,\n        SC_CHARSET_OEM866 = 866,\n        SC_CHARSET_CYRILLIC = 1251,\n        SC_CHARSET_SHIFTJIS = 128,\n        SC_CHARSET_SYMBOL = 2,\n        SC_CHARSET_TURKISH = 162,\n        SC_CHARSET_JOHAB = 130,\n        SC_CHARSET_HEBREW = 177,\n        SC_CHARSET_ARABIC = 178,\n        SC_CHARSET_VIETNAMESE = 163,\n        SC_CHARSET_THAI = 222,\n        SC_CHARSET_8859_15 = 1000\n    };\n\n    enum\n    {\n        SC_CASE_MIXED = 0,\n        SC_CASE_UPPER = 1,\n        SC_CASE_LOWER = 2,\n        SC_CASE_CAMEL = 3,\n    };\n\n    //! This enum defines the different indentation guide views.\n    //!\n    //! \\sa SCI_GETINDENTATIONGUIDES, SCI_SETINDENTATIONGUIDES\n    enum\n    {\n        //! No indentation guides are shown.\n        SC_IV_NONE = 0,\n\n        //! Indentation guides are shown inside real indentation white space.\n        SC_IV_REAL = 1,\n\n        //! Indentation guides are shown beyond the actual indentation up to\n        //! the level of the next non-empty line.  If the previous non-empty\n        //! line was a fold header then indentation guides are shown for one\n        //! more level of indent than that line.  This setting is good for\n        //! Python.\n        SC_IV_LOOKFORWARD = 2,\n\n        //! Indentation guides are shown beyond the actual indentation up to\n        //! the level of the next non-empty line or previous non-empty line\n        //! whichever is the greater.  This setting is good for most languages.\n        SC_IV_LOOKBOTH = 3\n    };\n\n    enum\n    {\n        INDIC_PLAIN = 0,\n        INDIC_SQUIGGLE = 1,\n        INDIC_TT = 2,\n        INDIC_DIAGONAL = 3,\n        INDIC_STRIKE = 4,\n        INDIC_HIDDEN = 5,\n        INDIC_BOX = 6,\n        INDIC_ROUNDBOX = 7,\n        INDIC_STRAIGHTBOX = 8,\n        INDIC_DASH = 9,\n        INDIC_DOTS = 10,\n        INDIC_SQUIGGLELOW = 11,\n        INDIC_DOTBOX = 12,\n        INDIC_SQUIGGLEPIXMAP = 13,\n        INDIC_COMPOSITIONTHICK = 14,\n        INDIC_COMPOSITIONTHIN = 15,\n        INDIC_FULLBOX = 16,\n        INDIC_TEXTFORE = 17,\n        INDIC_POINT = 18,\n        INDIC_POINTCHARACTER = 19,\n        INDIC_GRADIENT = 20,\n        INDIC_GRADIENTCENTRE = 21,\n\n        INDIC_IME = 32,\n        INDIC_IME_MAX = 35,\n\n        INDIC_CONTAINER = 8,\n        INDIC_MAX = 35,\n        INDIC0_MASK = 0x20,\n        INDIC1_MASK = 0x40,\n        INDIC2_MASK = 0x80,\n        INDICS_MASK = 0xe0,\n\n        SC_INDICVALUEBIT = 0x01000000,\n        SC_INDICVALUEMASK = 0x00ffffff,\n        SC_INDICFLAG_VALUEBEFORE = 1,\n    };\n\n    enum\n    {\n        SC_PRINT_NORMAL = 0,\n        SC_PRINT_INVERTLIGHT = 1,\n        SC_PRINT_BLACKONWHITE = 2,\n        SC_PRINT_COLOURONWHITE = 3,\n        SC_PRINT_COLOURONWHITEDEFAULTBG = 4,\n        SC_PRINT_SCREENCOLOURS = 5,\n    };\n\n    enum\n    {\n        SCFIND_WHOLEWORD = 2,\n        SCFIND_MATCHCASE = 4,\n        SCFIND_WORDSTART = 0x00100000,\n        SCFIND_REGEXP = 0x00200000,\n        SCFIND_POSIX = 0x00400000,\n        SCFIND_CXX11REGEX = 0x00800000,\n    };\n\n    enum\n    {\n        SC_FOLDDISPLAYTEXT_HIDDEN = 0,\n        SC_FOLDDISPLAYTEXT_STANDARD = 1,\n        SC_FOLDDISPLAYTEXT_BOXED = 2,\n    };\n\n    enum\n    {\n        SC_FOLDLEVELBASE = 0x00400,\n        SC_FOLDLEVELWHITEFLAG = 0x01000,\n        SC_FOLDLEVELHEADERFLAG = 0x02000,\n        SC_FOLDLEVELNUMBERMASK = 0x00fff\n    };\n\n    enum\n    {\n        SC_FOLDFLAG_LINEBEFORE_EXPANDED = 0x0002,\n        SC_FOLDFLAG_LINEBEFORE_CONTRACTED = 0x0004,\n        SC_FOLDFLAG_LINEAFTER_EXPANDED = 0x0008,\n        SC_FOLDFLAG_LINEAFTER_CONTRACTED = 0x0010,\n        SC_FOLDFLAG_LEVELNUMBERS = 0x0040,\n        SC_FOLDFLAG_LINESTATE = 0x0080,\n    };\n\n    enum\n    {\n        SC_LINE_END_TYPE_DEFAULT = 0,\n        SC_LINE_END_TYPE_UNICODE = 1,\n    };\n\n    enum\n    {\n        SC_TIME_FOREVER = 10000000\n    };\n\n    enum\n    {\n        SC_WRAP_NONE = 0,\n        SC_WRAP_WORD = 1,\n        SC_WRAP_CHAR = 2,\n        SC_WRAP_WHITESPACE = 3,\n    };\n\n    enum\n    {\n        SC_WRAPINDENT_FIXED = 0,\n        SC_WRAPINDENT_SAME = 1,\n        SC_WRAPINDENT_INDENT = 2,\n        SC_WRAPINDENT_DEEPINDENT = 3,\n    };\n\n    enum\n    {\n        SC_CACHE_NONE = 0,\n        SC_CACHE_CARET = 1,\n        SC_CACHE_PAGE = 2,\n        SC_CACHE_DOCUMENT = 3\n    };\n\n    enum\n    {\n        SC_PHASES_ONE = 0,\n        SC_PHASES_TWO = 1,\n        SC_PHASES_MULTIPLE = 2,\n    };\n\n    enum\n    {\n        ANNOTATION_HIDDEN = 0,\n        ANNOTATION_STANDARD = 1,\n        ANNOTATION_BOXED = 2,\n        ANNOTATION_INDENTED = 3,\n    };\n\n    enum\n    {\n        EDGE_NONE = 0,\n        EDGE_LINE = 1,\n        EDGE_BACKGROUND = 2,\n        EDGE_MULTILINE = 3,\n    };\n\n    enum\n    {\n        SC_CURSORNORMAL = -1,\n        SC_CURSORARROW = 2,\n        SC_CURSORWAIT = 4,\n        SC_CURSORREVERSEARROW = 7\n    };\n\n    enum\n    {\n        UNDO_MAY_COALESCE = 1\n    };\n\n    enum\n    {\n        VISIBLE_SLOP = 0x01,\n        VISIBLE_STRICT = 0x04\n    };\n\n    enum\n    {\n        CARET_SLOP = 0x01,\n        CARET_STRICT = 0x04,\n        CARET_JUMPS = 0x10,\n        CARET_EVEN = 0x08\n    };\n\n    enum\n    {\n        CARETSTYLE_INVISIBLE = 0,\n        CARETSTYLE_LINE = 1,\n        CARETSTYLE_BLOCK = 2\n    };\n\n    enum\n    {\n        SC_MOD_INSERTTEXT = 0x1,\n        SC_MOD_DELETETEXT = 0x2,\n        SC_MOD_CHANGESTYLE = 0x4,\n        SC_MOD_CHANGEFOLD = 0x8,\n        SC_PERFORMED_USER = 0x10,\n        SC_PERFORMED_UNDO = 0x20,\n        SC_PERFORMED_REDO = 0x40,\n        SC_MULTISTEPUNDOREDO = 0x80,\n        SC_LASTSTEPINUNDOREDO = 0x100,\n        SC_MOD_CHANGEMARKER = 0x200,\n        SC_MOD_BEFOREINSERT = 0x400,\n        SC_MOD_BEFOREDELETE = 0x800,\n        SC_MULTILINEUNDOREDO = 0x1000,\n        SC_STARTACTION = 0x2000,\n        SC_MOD_CHANGEINDICATOR = 0x4000,\n        SC_MOD_CHANGELINESTATE = 0x8000,\n        SC_MOD_CHANGEMARGIN = 0x10000,\n        SC_MOD_CHANGEANNOTATION = 0x20000,\n        SC_MOD_CONTAINER = 0x40000,\n        SC_MOD_LEXERSTATE = 0x80000,\n        SC_MOD_INSERTCHECK = 0x100000,\n        SC_MOD_CHANGETABSTOPS = 0x200000,\n        SC_MODEVENTMASKALL = 0x3fffff\n    };\n\n    enum\n    {\n        SCK_DOWN = 300,\n        SCK_UP = 301,\n        SCK_LEFT = 302,\n        SCK_RIGHT = 303,\n        SCK_HOME = 304,\n        SCK_END = 305,\n        SCK_PRIOR = 306,\n        SCK_NEXT = 307,\n        SCK_DELETE = 308,\n        SCK_INSERT = 309,\n        SCK_ESCAPE = 7,\n        SCK_BACK = 8,\n        SCK_TAB = 9,\n        SCK_RETURN = 13,\n        SCK_ADD = 310,\n        SCK_SUBTRACT = 311,\n        SCK_DIVIDE = 312,\n        SCK_WIN = 313,\n        SCK_RWIN = 314,\n        SCK_MENU = 315\n    };\n\n    //! This enum defines the different modifier keys.\n    enum\n    {\n        //! No modifier key.\n        SCMOD_NORM = 0,\n\n        //! Shift key.\n        SCMOD_SHIFT = 1,\n\n        //! Control key (the Command key on OS/X, the Ctrl key on other\n        //! platforms).\n        SCMOD_CTRL = 2,\n\n        //! Alt key.\n        SCMOD_ALT = 4,\n\n        //! This is the same as SCMOD_META on all platforms.\n        SCMOD_SUPER = 8,\n\n        //! Meta key (the Ctrl key on OS/X, the Windows key on other\n        //! platforms).\n        SCMOD_META = 16\n    };\n\n    //! This enum defines the different language lexers.\n    //!\n    //! \\sa SCI_GETLEXER, SCI_SETLEXER\n    enum\n    {\n        //! No lexer is selected and the SCN_STYLENEEDED signal is emitted so\n        //! that the application can style the text as needed.  This is the\n        //! default.\n        SCLEX_CONTAINER = 0,\n\n        //! Select the null lexer that does no syntax styling.\n        SCLEX_NULL = 1,\n\n        //! Select the Python lexer.\n        SCLEX_PYTHON = 2,\n\n        //! Select the C++ lexer.\n        SCLEX_CPP = 3,\n\n        //! Select the HTML lexer.\n        SCLEX_HTML = 4,\n\n        //! Select the XML lexer.\n        SCLEX_XML = 5,\n\n        //! Select the Perl lexer.\n        SCLEX_PERL = 6,\n\n        //! Select the SQL lexer.\n        SCLEX_SQL = 7,\n\n        //! Select the Visual Basic lexer.\n        SCLEX_VB = 8,\n\n        //! Select the lexer for properties style files.\n        SCLEX_PROPERTIES = 9,\n\n        //! Select the lexer for error list style files.\n        SCLEX_ERRORLIST = 10,\n\n        //! Select the Makefile lexer.\n        SCLEX_MAKEFILE = 11,\n\n        //! Select the Windows batch file lexer.\n        SCLEX_BATCH = 12,\n\n        //! Select the LaTex lexer.\n        SCLEX_LATEX = 14,\n\n        //! Select the Lua lexer.\n        SCLEX_LUA = 15,\n\n        //! Select the lexer for diff output.\n        SCLEX_DIFF = 16,\n\n        //! Select the lexer for Apache configuration files.\n        SCLEX_CONF = 17,\n\n        //! Select the Pascal lexer.\n        SCLEX_PASCAL = 18,\n\n        //! Select the Avenue lexer.\n        SCLEX_AVE = 19,\n\n        //! Select the Ada lexer.\n        SCLEX_ADA = 20,\n\n        //! Select the Lisp lexer.\n        SCLEX_LISP = 21,\n\n        //! Select the Ruby lexer.\n        SCLEX_RUBY = 22,\n\n        //! Select the Eiffel lexer.\n        SCLEX_EIFFEL = 23,\n\n        //! Select the Eiffel lexer folding at keywords.\n        SCLEX_EIFFELKW = 24,\n\n        //! Select the Tcl lexer.\n        SCLEX_TCL = 25,\n\n        //! Select the lexer for nnCron files.\n        SCLEX_NNCRONTAB = 26,\n\n        //! Select the Bullant lexer.\n        SCLEX_BULLANT = 27,\n\n        //! Select the VBScript lexer.\n        SCLEX_VBSCRIPT = 28,\n\n        //! Select the ASP lexer.\n        SCLEX_ASP = SCLEX_HTML,\n\n        //! Select the PHP lexer.\n        SCLEX_PHP = SCLEX_HTML,\n\n        //! Select the Baan lexer.\n        SCLEX_BAAN = 31,\n\n        //! Select the Matlab lexer.\n        SCLEX_MATLAB = 32,\n\n        //! Select the Scriptol lexer.\n        SCLEX_SCRIPTOL = 33,\n\n        //! Select the assembler lexer (';' comment character).\n        SCLEX_ASM = 34,\n\n        //! Select the C++ lexer with case insensitive keywords.\n        SCLEX_CPPNOCASE = 35,\n\n        //! Select the FORTRAN lexer.\n        SCLEX_FORTRAN = 36,\n\n        //! Select the FORTRAN77 lexer.\n        SCLEX_F77 = 37,\n\n        //! Select the CSS lexer.\n        SCLEX_CSS = 38,\n\n        //! Select the POV lexer.\n        SCLEX_POV = 39,\n\n        //! Select the Basser Lout typesetting language lexer.\n        SCLEX_LOUT = 40,\n\n        //! Select the EScript lexer.\n        SCLEX_ESCRIPT = 41,\n\n        //! Select the PostScript lexer.\n        SCLEX_PS = 42,\n\n        //! Select the NSIS lexer.\n        SCLEX_NSIS = 43,\n\n        //! Select the MMIX assembly language lexer.\n        SCLEX_MMIXAL = 44,\n\n        //! Select the Clarion lexer.\n        SCLEX_CLW = 45,\n\n        //! Select the Clarion lexer with case insensitive keywords.\n        SCLEX_CLWNOCASE = 46,\n\n        //! Select the MPT text log file lexer.\n        SCLEX_LOT = 47,\n\n        //! Select the YAML lexer.\n        SCLEX_YAML = 48,\n\n        //! Select the TeX lexer.\n        SCLEX_TEX = 49,\n\n        //! Select the Metapost lexer.\n        SCLEX_METAPOST = 50,\n\n        //! Select the PowerBASIC lexer.\n        SCLEX_POWERBASIC = 51,\n\n        //! Select the Forth lexer.\n        SCLEX_FORTH = 52,\n\n        //! Select the Erlang lexer.\n        SCLEX_ERLANG = 53,\n\n        //! Select the Octave lexer.\n        SCLEX_OCTAVE = 54,\n\n        //! Select the MS SQL lexer.\n        SCLEX_MSSQL = 55,\n\n        //! Select the Verilog lexer.\n        SCLEX_VERILOG = 56,\n\n        //! Select the KIX-Scripts lexer.\n        SCLEX_KIX = 57,\n\n        //! Select the Gui4Cli lexer.\n        SCLEX_GUI4CLI = 58,\n\n        //! Select the Specman E lexer.\n        SCLEX_SPECMAN = 59,\n\n        //! Select the AutoIt3 lexer.\n        SCLEX_AU3 = 60,\n\n        //! Select the APDL lexer.\n        SCLEX_APDL = 61,\n\n        //! Select the Bash lexer.\n        SCLEX_BASH = 62,\n\n        //! Select the ASN.1 lexer.\n        SCLEX_ASN1 = 63,\n\n        //! Select the VHDL lexer.\n        SCLEX_VHDL = 64,\n\n        //! Select the Caml lexer.\n        SCLEX_CAML = 65,\n\n        //! Select the BlitzBasic lexer.\n        SCLEX_BLITZBASIC = 66,\n\n        //! Select the PureBasic lexer.\n        SCLEX_PUREBASIC = 67,\n\n        //! Select the Haskell lexer.\n        SCLEX_HASKELL = 68,\n\n        //! Select the PHPScript lexer.\n        SCLEX_PHPSCRIPT = 69,\n\n        //! Select the TADS3 lexer.\n        SCLEX_TADS3 = 70,\n\n        //! Select the REBOL lexer.\n        SCLEX_REBOL = 71,\n\n        //! Select the Smalltalk lexer.\n        SCLEX_SMALLTALK = 72,\n\n        //! Select the FlagShip lexer.\n        SCLEX_FLAGSHIP = 73,\n\n        //! Select the Csound lexer.\n        SCLEX_CSOUND = 74,\n\n        //! Select the FreeBasic lexer.\n        SCLEX_FREEBASIC = 75,\n\n        //! Select the InnoSetup lexer.\n        SCLEX_INNOSETUP = 76,\n\n        //! Select the Opal lexer.\n        SCLEX_OPAL = 77,\n\n        //! Select the Spice lexer.\n        SCLEX_SPICE = 78,\n\n        //! Select the D lexer.\n        SCLEX_D = 79,\n\n        //! Select the CMake lexer.\n        SCLEX_CMAKE = 80,\n\n        //! Select the GAP lexer.\n        SCLEX_GAP = 81,\n\n        //! Select the PLM lexer.\n        SCLEX_PLM = 82,\n\n        //! Select the Progress lexer.\n        SCLEX_PROGRESS = 83,\n\n        //! Select the Abaqus lexer.\n        SCLEX_ABAQUS = 84,\n\n        //! Select the Asymptote lexer.\n        SCLEX_ASYMPTOTE = 85,\n\n        //! Select the R lexer.\n        SCLEX_R = 86,\n\n        //! Select the MagikSF lexer.\n        SCLEX_MAGIK = 87,\n\n        //! Select the PowerShell lexer.\n        SCLEX_POWERSHELL = 88,\n\n        //! Select the MySQL lexer.\n        SCLEX_MYSQL = 89,\n\n        //! Select the gettext .po file lexer.\n        SCLEX_PO = 90,\n\n        //! Select the TAL lexer.\n        SCLEX_TAL = 91,\n\n        //! Select the COBOL lexer.\n        SCLEX_COBOL = 92,\n\n        //! Select the TACL lexer.\n        SCLEX_TACL = 93,\n\n        //! Select the Sorcus lexer.\n        SCLEX_SORCUS = 94,\n\n        //! Select the PowerPro lexer.\n        SCLEX_POWERPRO = 95,\n\n        //! Select the Nimrod lexer.\n        SCLEX_NIMROD = 96,\n\n        //! Select the SML lexer.\n        SCLEX_SML = 97,\n\n        //! Select the Markdown lexer.\n        SCLEX_MARKDOWN = 98,\n\n        //! Select the txt2tags lexer.\n        SCLEX_TXT2TAGS = 99,\n\n        //! Select the 68000 assembler lexer.\n        SCLEX_A68K = 100,\n\n        //! Select the Modula 3 lexer.\n        SCLEX_MODULA = 101,\n\n        //! Select the CoffeeScript lexer.\n        SCLEX_COFFEESCRIPT = 102,\n\n        //! Select the Take Command lexer.\n        SCLEX_TCMD = 103,\n\n        //! Select the AviSynth lexer.\n        SCLEX_AVS = 104,\n\n        //! Select the ECL lexer.\n        SCLEX_ECL = 105,\n\n        //! Select the OScript lexer.\n        SCLEX_OSCRIPT = 106,\n\n        //! Select the Visual Prolog lexer.\n        SCLEX_VISUALPROLOG = 107,\n\n        //! Select the Literal Haskell lexer.\n        SCLEX_LITERATEHASKELL = 108,\n\n        //! Select the Structured Text lexer.\n        SCLEX_STTXT = 109,\n\n        //! Select the KVIrc lexer.\n        SCLEX_KVIRC = 110,\n\n        //! Select the Rust lexer.\n        SCLEX_RUST = 111,\n\n        //! Select the MSC Nastran DMAP lexer.\n        SCLEX_DMAP = 112,\n\n        //! Select the assembler lexer ('#' comment character).\n        SCLEX_AS = 113,\n\n        //! Select the DMIS lexer.\n        SCLEX_DMIS = 114,\n\n        //! Select the lexer for Windows registry files.\n        SCLEX_REGISTRY = 115,\n\n        //! Select the BibTex lexer.\n        SCLEX_BIBTEX = 116,\n\n        //! Select the Motorola S-Record hex lexer.\n        SCLEX_SREC = 117,\n\n        //! Select the Intel hex lexer.\n        SCLEX_IHEX = 118,\n\n        //! Select the Tektronix extended hex lexer.\n        SCLEX_TEHEX = 119,\n\n        //! Select the JSON hex lexer.\n        SCLEX_JSON = 120,\n\n        //! Select the EDIFACT lexer.\n        SCLEX_EDIFACT = 121,\n\n        //! Select the pseudo-lexer used for the indentation-based folding of\n        //! files.\n        SCLEX_INDENT = 122,\n\n        //! Select the Maxima lexer.\n        SCLEX_MAXIMA = 123,\n\n        //! Select the Stata lexer.\n        SCLEX_STATA = 124,\n\n        //! Select the SAS lexer.\n        SCLEX_SAS = 125,\n    };\n\n    enum\n    {\n        SC_WEIGHT_NORMAL = 400,\n        SC_WEIGHT_SEMIBOLD = 600,\n        SC_WEIGHT_BOLD = 700,\n    };\n\n    enum\n    {\n        SC_TECHNOLOGY_DEFAULT = 0,\n        SC_TECHNOLOGY_DIRECTWRITE = 1,\n        SC_TECHNOLOGY_DIRECTWRITERETAIN = 2,\n        SC_TECHNOLOGY_DIRECTWRITEDC = 3,\n    };\n\n    enum\n    {\n        SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE = 0,\n        SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE = 1,\n    };\n\n    enum\n    {\n        SC_FONT_SIZE_MULTIPLIER = 100,\n    };\n\n    enum\n    {\n        SC_FOLDACTION_CONTRACT = 0,\n        SC_FOLDACTION_EXPAND = 1,\n        SC_FOLDACTION_TOGGLE = 2,\n    };\n\n    enum\n    {\n        SC_AUTOMATICFOLD_SHOW = 0x0001,\n        SC_AUTOMATICFOLD_CLICK = 0x0002,\n        SC_AUTOMATICFOLD_CHANGE = 0x0004,\n    };\n\n    enum\n    {\n        SC_ORDER_PRESORTED = 0,\n        SC_ORDER_PERFORMSORT = 1,\n        SC_ORDER_CUSTOM = 2,\n    };\n\n    //! Construct an empty QsciScintillaBase with parent \\a parent.\n    explicit QsciScintillaBase(QWidget *parent = 0);\n\n    //! Destroys the QsciScintillaBase instance.\n    virtual ~QsciScintillaBase();\n\n    //! Returns a pointer to a QsciScintillaBase instance, or 0 if there isn't\n    //! one.  This can be used by the higher level API to send messages that\n    //! aren't associated with a particular instance.\n    static QsciScintillaBase *pool();\n\n    //! Replaces the existing horizontal scroll bar with \\a scrollBar.  The\n    //! existing scroll bar is deleted.  This should be called instead of\n    //! QAbstractScrollArea::setHorizontalScrollBar().\n    void replaceHorizontalScrollBar(QScrollBar *scrollBar);\n\n    //! Replaces the existing vertical scroll bar with \\a scrollBar.  The\n    //! existing scroll bar is deleted.  This should be called instead of\n    //! QAbstractScrollArea::setHorizontalScrollBar().\n    void replaceVerticalScrollBar(QScrollBar *scrollBar);\n\n    //! Send the Scintilla message \\a msg with the optional parameters \\a\n    //! wParam and \\a lParam.\n    long SendScintilla(unsigned int msg, unsigned long wParam = 0,\n            long lParam = 0) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, unsigned long wParam,\n            void *lParam) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, uintptr_t wParam,\n            const char *lParam) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, const char *lParam) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, const char *wParam,\n            const char *lParam) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, long wParam) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, int wParam) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, long cpMin, long cpMax,\n            char *lpstrText) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, unsigned long wParam,\n            const QColor &col) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, const QColor &col) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, unsigned long wParam, QPainter *hdc,\n            const QRect &rc, long cpMin, long cpMax) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, unsigned long wParam,\n            const QPixmap &lParam) const;\n\n    //! \\overload\n    long SendScintilla(unsigned int msg, unsigned long wParam,\n            const QImage &lParam) const;\n\n    //! Send the Scintilla message \\a msg and return a pointer result.\n    void *SendScintillaPtrResult(unsigned int msg) const;\n\n    //! \\internal\n    static int commandKey(int qt_key, int &modifiers);\n\nsignals:\n    //! This signal is emitted when text is selected or de-selected.\n    //! \\a yes is true if text has been selected and false if text has been\n    //! deselected.\n    void QSCN_SELCHANGED(bool yes);\n\n    //! This signal is emitted when the user cancels an auto-completion list.\n    //!\n    //! \\sa SCN_AUTOCSELECTION()\n    void SCN_AUTOCCANCELLED();\n\n    //! This signal is emitted when the user deletes a character when an\n    //! auto-completion list is active.\n    void SCN_AUTOCCHARDELETED();\n\n    //! This signal is emitted after an auto-completion has inserted its text.\n    //! \\a selection is the text of the selection.  \\a position is the start\n    //! position of the word being completed.  \\a ch is the fillup character\n    //! that triggered the selection if method is SC_AC_FILLUP.  \\a method is\n    //! the method used to trigger the selection.\n    //!\n    //! \\sa SCN_AUTOCCANCELLED(), SCN_AUTOCSELECTION()\n    void SCN_AUTOCCOMPLETED(const char *selection, int position, int ch, int method);\n\n    //! This signal is emitted when the user selects an item in an\n    //! auto-completion list.  It is emitted before the selection is inserted.\n    //! The insertion can be cancelled by sending an SCI_AUTOCANCEL message\n    //! from a connected slot.\n    //! \\a selection is the text of the selection.  \\a position is the start\n    //! position of the word being completed.  \\a ch is the fillup character\n    //! that triggered the selection if method is SC_AC_FILLUP.  \\a method is\n    //! the method used to trigger the selection.\n    //!\n    //! \\sa SCN_AUTOCCANCELLED(), SCN_AUTOCCOMPLETED()\n    void SCN_AUTOCSELECTION(const char *selection, int position, int ch, int method);\n\n    //! \\overload\n    void SCN_AUTOCSELECTION(const char *selection, int position);\n\n    //! This signal is emitted when the user highlights an item in an\n    //! auto-completion or user list.\n    //! \\a selection is the text of the selection.  \\a id is an identifier for\n    //! the list which was passed as an argument to the SCI_USERLISTSHOW\n    //! message or 0 if the list is an auto-completion list.  \\a position is\n    //! the position that the list was displayed at.\n    void SCN_AUTOCSELECTIONCHANGE(const char *selection, int id, int position);\n\n    //! This signal is emitted when the document has changed for any reason.\n    void SCEN_CHANGE();\n\n    //! This signal is emitted when the user clicks on a calltip.\n    //! \\a direction is 1 if the user clicked on the up arrow, 2 if the user\n    //! clicked on the down arrow, and 0 if the user clicked elsewhere.\n    void SCN_CALLTIPCLICK(int direction);\n\n    //! This signal is emitted whenever the user enters an ordinary character\n    //! into the text.\n    //! \\a charadded is the character. It can be used to decide to display a\n    //! call tip or an auto-completion list.\n    void SCN_CHARADDED(int charadded);\n\n    //! This signal is emitted when the user double clicks.\n    //! \\a position is the position in the text where the click occured.\n    //! \\a line is the number of the line in the text where the click occured.\n    //! \\a modifiers is the logical or of the modifier keys that were pressed\n    //! when the user double clicked.\n    void SCN_DOUBLECLICK(int position, int line, int modifiers);\n\n    //! This signal is emitted when the user moves the mouse (or presses a key)\n    //! after keeping it in one position for the dwell period.\n    //! \\a position is the position in the text where the mouse dwells.\n    //! \\a x is the x-coordinate where the mouse dwells.  \\a y is the\n    //! y-coordinate where the mouse dwells.\n    //! \n    //! \\sa SCN_DWELLSTART, SCI_SETMOUSEDWELLTIME\n    void SCN_DWELLEND(int position, int x, int y);\n\n    //! This signal is emitted when the user keeps the mouse in one position\n    //! for the dwell period.\n    //! \\a position is the position in the text where the mouse dwells.\n    //! \\a x is the x-coordinate where the mouse dwells.  \\a y is the\n    //! y-coordinate where the mouse dwells.\n    //!\n    //! \\sa SCN_DWELLEND, SCI_SETMOUSEDWELLTIME\n    void SCN_DWELLSTART(int position, int x, int y);\n\n    //! This signal is emitted when focus is received.\n    void SCN_FOCUSIN();\n\n    //! This signal is emitted when focus is lost.\n    void SCN_FOCUSOUT();\n\n    //! This signal is emitted when the user clicks on text in a style with the\n    //! hotspot attribute set.\n    //! \\a position is the position in the text where the click occured.\n    //! \\a modifiers is the logical or of the modifier keys that were pressed\n    //! when the user clicked.\n    void SCN_HOTSPOTCLICK(int position, int modifiers);\n\n    //! This signal is emitted when the user double clicks on text in a style\n    //! with the hotspot attribute set.\n    //! \\a position is the position in the text where the double click occured.\n    //! \\a modifiers is the logical or of the modifier keys that were pressed\n    //! when the user double clicked.\n    void SCN_HOTSPOTDOUBLECLICK(int position, int modifiers);\n\n    //! This signal is emitted when the user releases the mouse button on text\n    //! in a style with the hotspot attribute set.\n    //! \\a position is the position in the text where the release occured.\n    //! \\a modifiers is the logical or of the modifier keys that were pressed\n    //! when the user released the button.\n    void SCN_HOTSPOTRELEASECLICK(int position, int modifiers);\n\n    //! This signal is emitted when the user clicks on text that has an\n    //! indicator.\n    //! \\a position is the position in the text where the click occured.\n    //! \\a modifiers is the logical or of the modifier keys that were pressed\n    //! when the user clicked.\n    void SCN_INDICATORCLICK(int position, int modifiers);\n\n    //! This signal is emitted when the user releases the mouse button on text\n    //! that has an indicator.\n    //! \\a position is the position in the text where the release occured.\n    //! \\a modifiers is the logical or of the modifier keys that were pressed\n    //! when the user released.\n    void SCN_INDICATORRELEASE(int position, int modifiers);\n\n    //! This signal is emitted when a recordable editor command has been\n    //! executed.\n    void SCN_MACRORECORD(unsigned int, unsigned long, void *);\n\n    //! This signal is emitted when the user clicks on a sensitive margin.\n    //! \\a position is the position of the start of the line against which the\n    //! user clicked.\n    //! \\a modifiers is the logical or of the modifier keys that were pressed\n    //! when the user clicked.\n    //! \\a margin is the number of the margin the user clicked in: 0, 1 or 2.\n    //! \n    //! \\sa SCI_GETMARGINSENSITIVEN, SCI_SETMARGINSENSITIVEN\n    void SCN_MARGINCLICK(int position, int modifiers, int margin);\n\n    //! This signal is emitted when the user right-clicks on a sensitive\n    //! margin.  \\a position is the position of the start of the line against\n    //! which the user clicked.\n    //! \\a modifiers is the logical or of the modifier keys that were pressed\n    //! when the user clicked.\n    //! \\a margin is the number of the margin the user clicked in: 0, 1 or 2.\n    //! \n    //! \\sa SCI_GETMARGINSENSITIVEN, SCI_SETMARGINSENSITIVEN\n    void SCN_MARGINRIGHTCLICK(int position, int modifiers, int margin);\n\n    //!\n    void SCN_MODIFIED(int, int, const char *, int, int, int, int, int, int, int);\n\n    //! This signal is emitted when the user attempts to modify read-only\n    //! text.\n    void SCN_MODIFYATTEMPTRO();\n\n    //!\n    void SCN_NEEDSHOWN(int, int);\n\n    //! This signal is emitted when painting has been completed.  It is useful\n    //! to trigger some other change but to have the paint be done first to\n    //! appear more reponsive to the user.\n    void SCN_PAINTED();\n\n    //! This signal is emitted when the current state of the text no longer\n    //! corresponds to the state of the text at the save point.\n    //! \n    //! \\sa SCI_SETSAVEPOINT, SCN_SAVEPOINTREACHED()\n    void SCN_SAVEPOINTLEFT();\n\n    //! This signal is emitted when the current state of the text corresponds\n    //! to the state of the text at the save point. This allows feedback to be\n    //! given to the user as to whether the text has been modified since it was\n    //! last saved.\n    //! \n    //! \\sa SCI_SETSAVEPOINT, SCN_SAVEPOINTLEFT()\n    void SCN_SAVEPOINTREACHED();\n\n    //! This signal is emitted when a range of text needs to be syntax styled.\n    //! The range is from the value returned by the SCI_GETENDSTYLED message\n    //! and \\a position.  It is only emitted if the currently selected lexer is\n    //! SCLEX_CONTAINER.\n    //!\n    //! \\sa SCI_COLOURISE, SCI_GETENDSTYLED\n    void SCN_STYLENEEDED(int position);\n\n    //! This signal is emitted when a URI is dropped.\n    //! \\a url is the value of the URI.\n    void SCN_URIDROPPED(const QUrl &url);\n\n    //! This signal is emitted when either the text or styling of the text has\n    //! changed or the selection range or scroll position has changed.\n    //! \\a updated contains the set of SC_UPDATE_* flags describing the changes\n    //! since the signal was last emitted.\n    void SCN_UPDATEUI(int updated);\n\n    //! This signal is emitted when the user selects an item in a user list.\n    //! \\a selection is the text of the selection.  \\a id is an identifier for\n    //! the list which was passed as an argument to the SCI_USERLISTSHOW\n    //! message and must be at least 1.  \\a ch is the fillup character that\n    //! triggered the selection if method is SC_AC_FILLUP.  \\a method is the\n    //! method used to trigger the selection.  \\a position is the position that\n    //! the list was displayed at.\n    //!\n    //! \\sa SCI_USERLISTSHOW, SCN_AUTOCSELECTION()\n    void SCN_USERLISTSELECTION(const char *selection, int id, int ch, int method, int position);\n\n    //! \\overload\n    void SCN_USERLISTSELECTION(const char *selection, int id, int ch, int method);\n\n    //! \\overload\n    void SCN_USERLISTSELECTION(const char *selection, int id);\n\n    //!\n    void SCN_ZOOM();\n\nprotected:\n    //! Returns true if the contents of a MIME data object can be decoded and\n    //! inserted into the document.  It is called during drag and paste\n    //! operations.\n    //! \\a source is the MIME data object.\n    //!\n    //! \\sa fromMimeData(), toMimeData()\n    virtual bool canInsertFromMimeData(const QMimeData *source) const;\n\n    //! Returns the text of a MIME data object.  It is called when a drag and\n    //! drop is completed and when text is pasted from the clipboard.\n    //! \\a source is the MIME data object.  On return \\a rectangular is set if\n    //! the text corresponds to a rectangular selection.\n    //!\n    //! \\sa canInsertFromMimeData(), toMimeData()\n    virtual QByteArray fromMimeData(const QMimeData *source, bool &rectangular) const;\n\n    //! Returns a new MIME data object containing some text and whether it\n    //! corresponds to a rectangular selection.  It is called when a drag and\n    //! drop is started and when the selection is copied to the clipboard.\n    //! Ownership of the object is passed to the caller.  \\a text is the text.\n    //! \\a rectangular is set if the text corresponds to a rectangular\n    //! selection.\n    //!\n    //! \\sa canInsertFromMimeData(), fromMimeData()\n    virtual QMimeData *toMimeData(const QByteArray &text, bool rectangular) const;\n\n    //! \\reimp\n    virtual void changeEvent(QEvent *e);\n\n    //! Re-implemented to handle the context menu.\n    virtual void contextMenuEvent(QContextMenuEvent *e);\n\n    //! Re-implemented to handle drag enters.\n    virtual void dragEnterEvent(QDragEnterEvent *e);\n\n    //! Re-implemented to handle drag leaves.\n    virtual void dragLeaveEvent(QDragLeaveEvent *e);\n\n    //! Re-implemented to handle drag moves.\n    virtual void dragMoveEvent(QDragMoveEvent *e);\n\n    //! Re-implemented to handle drops.\n    virtual void dropEvent(QDropEvent *e);\n\n    //! Re-implemented to tell Scintilla it has the focus.\n    virtual void focusInEvent(QFocusEvent *e);\n\n    //! Re-implemented to tell Scintilla it has lost the focus.\n    virtual void focusOutEvent(QFocusEvent *e);\n\n    //! Re-implemented to allow tabs to be entered as text.\n    virtual bool focusNextPrevChild(bool next);\n\n    //! Re-implemented to handle key presses.\n    virtual void keyPressEvent(QKeyEvent *e);\n\n    //! Re-implemented to handle composed characters.\n    virtual void inputMethodEvent(QInputMethodEvent *event);\n    virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;\n\n    //! Re-implemented to handle mouse double-clicks.\n    virtual void mouseDoubleClickEvent(QMouseEvent *e);\n\n    //! Re-implemented to handle mouse moves.\n    virtual void mouseMoveEvent(QMouseEvent *e);\n\n    //! Re-implemented to handle mouse presses.\n    virtual void mousePressEvent(QMouseEvent *e);\n\n    //! Re-implemented to handle mouse releases.\n    virtual void mouseReleaseEvent(QMouseEvent *e);\n\n    //! Re-implemented to paint the viewport.\n    virtual void paintEvent(QPaintEvent *e);\n\n    //! Re-implemented to handle resizes.\n    virtual void resizeEvent(QResizeEvent *e);\n\n    //! \\internal Re-implemented to handle scrolling.\n    virtual void scrollContentsBy(int dx, int dy);\n\n    //! \\internal This helps to work around some Scintilla bugs.\n    void setScrollBars();\n\n    //! \\internal Convert a QString to encoded bytes.\n    QByteArray textAsBytes(const QString &text) const;\n\n    //! \\internal Convert encoded bytes to a QString.\n    QString bytesAsText(const char *bytes, int size) const;\n\n    //! Give access to the text convertors.\n    friend class QsciAccessibleScintillaBase;\n    friend class QsciLexer;\n\n    //! \\internal A helper for QsciScintilla::contextMenuEvent().\n    bool contextMenuNeeded(int x, int y) const;\n\nprivate slots:\n    void handleVSb(int value);\n    void handleHSb(int value);\n\nprivate:\n    // This is needed to allow QsciScintillaQt to emit this class's signals.\n    friend class QsciScintillaQt;\n\n    QsciScintillaQt *sci;\n    QPoint triple_click_at;\n    QTimer triple_click;\n    int preeditPos;\n    int preeditNrBytes;\n    QString preeditString;\n    bool clickCausedFocus;\n\n    void connectHorizontalScrollBar();\n    void connectVerticalScrollBar();\n\n    void acceptAction(QDropEvent *e);\n\n    int eventModifiers(QMouseEvent *e);\n\n    QsciScintillaBase(const QsciScintillaBase &);\n    QsciScintillaBase &operator=(const QsciScintillaBase &);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscistyle.h",
    "content": "// This module defines interface to the QsciStyle class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCISTYLE_H\n#define QSCISTYLE_H\n\n#include <qcolor.h>\n#include <qfont.h>\n#include <qstring.h>\n\n#include <Qsci/qsciglobal.h>\n\n\nclass QsciScintillaBase;\n\n\n//! \\brief The QsciStyle class encapsulates all the attributes of a style.\n//!\n//! Each character of a document has an associated style which determines how\n//! the character is displayed, e.g. its font and color.  A style is identified\n//! by a number.  Lexers define styles for each of the language's features so\n//! that they are displayed differently.  Some style numbers have hard-coded\n//! meanings, e.g. the style used for call tips.\nclass QSCINTILLA_EXPORT QsciStyle\n{\npublic:\n    //! This enum defines the different ways the displayed case of the text can\n    //! be changed.\n    enum TextCase {\n        //! The text is displayed as its original case.\n        OriginalCase = 0,\n\n        //! The text is displayed as upper case.\n        UpperCase = 1,\n\n        //! The text is displayed as lower case.\n        LowerCase = 2\n    };\n\n    //! Constructs a QsciStyle instance for style number \\a style.  If \\a style\n    //! is negative then a new style number is automatically allocated if\n    //! possible.  If it is not possible then style() will return a negative\n    //! value.\n    //!\n    //! \\sa style()\n    QsciStyle(int style = -1);\n\n    //! Constructs a QsciStyle instance for style number \\a style.  If \\a style\n    //! is negative then a new style number is automatically allocated if\n    //! possible.  If it is not possible then style() will return a negative\n    //! value.  The styles description, color, paper color, font and\n    //! end-of-line fill are set to \\a description, \\a color, \\a paper, \\a font\n    //! and \\a eolFill respectively.\n    //!\n    //! \\sa style()\n    QsciStyle(int style, const QString &description, const QColor &color,\n            const QColor &paper, const QFont &font, bool eolFill = false);\n\n    //! \\internal Apply the style to a particular editor.\n    void apply(QsciScintillaBase *sci) const;\n\n    //! The style's number is set to \\a style.\n    //!\n    //! \\sa style()\n    void setStyle(int style) {style_nr = style;}\n\n    //! Returns the number of the style.  This will be negative if the style is\n    //! invalid.\n    //!\n    //! \\sa setStyle()\n    int style() const {return style_nr;}\n\n    //! The style's description is set to \\a description.\n    //!\n    //! \\sa description()\n    void setDescription(const QString &description) {style_description = description;}\n\n    //! Returns the style's description.\n    //!\n    //! \\sa setDescription()\n    QString description() const {return style_description;}\n\n    //! The style's foreground color is set to \\a color.  The default is taken\n    //! from the application's default palette.\n    //!\n    //! \\sa color()\n    void setColor(const QColor &color);\n\n    //! Returns the style's foreground color.\n    //!\n    //! \\sa setColor()\n    QColor color() const {return style_color;}\n\n    //! The style's background color is set to \\a paper.  The default is taken\n    //! from the application's default palette.\n    //!\n    //! \\sa paper()\n    void setPaper(const QColor &paper);\n\n    //! Returns the style's background color.\n    //!\n    //! \\sa setPaper()\n    QColor paper() const {return style_paper;}\n\n    //! The style's font is set to \\a font.  The default is the application's\n    //! default font.\n    //!\n    //! \\sa font()\n    void setFont(const QFont &font);\n\n    //! Returns the style's font.\n    //!\n    //! \\sa setFont()\n    QFont font() const {return style_font;}\n\n    //! The style's end-of-line fill is set to \\a fill.  The default is false.\n    //!\n    //! \\sa eolFill()\n    void setEolFill(bool fill);\n\n    //! Returns the style's end-of-line fill.\n    //!\n    //! \\sa setEolFill()\n    bool eolFill() const {return style_eol_fill;}\n\n    //! The style's text case is set to \\a text_case.  The default is\n    //! OriginalCase.\n    //!\n    //! \\sa textCase()\n    void setTextCase(TextCase text_case);\n\n    //! Returns the style's text case.\n    //!\n    //! \\sa setTextCase()\n    TextCase textCase() const {return style_case;}\n\n    //! The style's visibility is set to \\a visible.  The default is true.\n    //!\n    //! \\sa visible()\n    void setVisible(bool visible);\n\n    //! Returns the style's visibility.\n    //!\n    //! \\sa setVisible()\n    bool visible() const {return style_visible;}\n\n    //! The style's changeability is set to \\a changeable.  The default is\n    //! true.\n    //!\n    //! \\sa changeable()\n    void setChangeable(bool changeable);\n\n    //! Returns the style's changeability.\n    //!\n    //! \\sa setChangeable()\n    bool changeable() const {return style_changeable;}\n\n    //! The style's sensitivity to mouse clicks is set to \\a hotspot.  The\n    //! default is false.\n    //!\n    //! \\sa hotspot()\n    void setHotspot(bool hotspot);\n\n    //! Returns the style's sensitivity to mouse clicks.\n    //!\n    //! \\sa setHotspot()\n    bool hotspot() const {return style_hotspot;}\n\n    //! Refresh the style settings.\n    void refresh();\n\nprivate:\n    int style_nr;\n    QString style_description;\n    QColor style_color;\n    QColor style_paper;\n    QFont style_font;\n    bool style_eol_fill;\n    TextCase style_case;\n    bool style_visible;\n    bool style_changeable;\n    bool style_hotspot;\n\n    void init(int style);\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/Qsci/qscistyledtext.h",
    "content": "// This module defines interface to the QsciStyledText class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#ifndef QSCISTYLEDTEXT_H\n#define QSCISTYLEDTEXT_H\n\n#include <qstring.h>\n\n#include <Qsci/qsciglobal.h>\n\n\nclass QsciScintillaBase;\nclass QsciStyle;\n\n\n//! \\brief The QsciStyledText class is a container for a piece of text and the\n//! style used to display the text.\nclass QSCINTILLA_EXPORT QsciStyledText\n{\npublic:\n    //! Constructs a QsciStyledText instance for text \\a text and style number\n    //! \\a style.\n    QsciStyledText(const QString &text, int style);\n\n    //! Constructs a QsciStyledText instance for text \\a text and style \\a\n    //! style.\n    QsciStyledText(const QString &text, const QsciStyle &style);\n\n    //! \\internal Apply the style to a particular editor.\n    void apply(QsciScintillaBase *sci) const;\n\n    //! Returns a reference to the text.\n    const QString &text() const {return styled_text;}\n\n    //! Returns the number of the style.\n    int style() const;\n\nprivate:\n    QString styled_text;\n    int style_nr;\n    const QsciStyle *explicit_style;\n};\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qscilexer.cpp",
    "content": "// This module implements the QsciLexer class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qscilexer.h\"\n\n#include <qapplication.h>\n#include <qcolor.h>\n#include <qfont.h>\n#include <qsettings.h>\n\n#include \"Qsci/qsciapis.h\"\n#include \"Qsci/qsciscintilla.h\"\n#include \"Qsci/qsciscintillabase.h\"\n\n\n// The ctor.\nQsciLexer::QsciLexer(QObject *parent)\n    : QObject(parent),\n      autoIndStyle(-1), apiSet(0), attached_editor(0)\n{\n#if defined(Q_OS_WIN)\n    defFont = QFont(\"Verdana\", 10);\n#elif defined(Q_OS_MAC)\n    defFont = QFont(\"Menlo\", 12);\n#else\n    defFont = QFont(\"Bitstream Vera Sans\", 9);\n#endif\n\n    // Set the default fore and background colours.\n    QPalette pal = QApplication::palette();\n    defColor = pal.text().color();\n    defPaper = pal.base().color();\n\n    // Putting this on the heap means we can keep the style getters const.\n    style_map = new StyleDataMap;\n    style_map->style_data_set = false;\n}\n\n\n// The dtor.\nQsciLexer::~QsciLexer()\n{\n    delete style_map;\n}\n\n\n// Set the attached editor.\nvoid QsciLexer::setEditor(QsciScintilla *editor)\n{\n    attached_editor = editor;\n}\n\n\n// Return the lexer name.\nconst char *QsciLexer::lexer() const\n{\n    return 0;\n}\n\n\n// Return the lexer identifier.\nint QsciLexer::lexerId() const\n{\n    return QsciScintillaBase::SCLEX_CONTAINER;\n}\n\n\n// Return the number of style bits needed by the lexer.\nint QsciLexer::styleBitsNeeded() const\n{\n    return 8;\n}\n\n\n// Make sure the style defaults have been set.\nvoid QsciLexer::setStyleDefaults() const\n{\n    if (!style_map->style_data_set)\n    {\n        for (int i = 0; i <= QsciScintillaBase::STYLE_MAX; ++i)\n            if (!description(i).isEmpty())\n                styleData(i);\n\n        style_map->style_data_set = true;\n    }\n}\n\n\n// Return a reference to a style's data, setting up the defaults if needed.\nQsciLexer::StyleData &QsciLexer::styleData(int style) const\n{\n    StyleData &sd = style_map->style_data[style];\n\n    // See if this is a new style by checking if the colour is valid.\n    if (!sd.color.isValid())\n    {\n        sd.color = defaultColor(style);\n        sd.paper = defaultPaper(style);\n        sd.font = defaultFont(style);\n        sd.eol_fill = defaultEolFill(style);\n    }\n\n    return sd;\n}\n\n\n// Set the APIs associated with the lexer.\nvoid QsciLexer::setAPIs(QsciAbstractAPIs *apis)\n{\n    apiSet = apis;\n}\n\n\n// Return a pointer to the current APIs if there are any.\nQsciAbstractAPIs *QsciLexer::apis() const\n{\n    return apiSet;\n}\n\n\n// Default implementation to return the set of fill up characters that can end\n// auto-completion.\nconst char *QsciLexer::autoCompletionFillups() const\n{\n    return \"(\";\n}\n\n\n// Default implementation to return the view used for indentation guides.\nint QsciLexer::indentationGuideView() const\n{\n    return QsciScintillaBase::SC_IV_LOOKBOTH;\n}\n\n\n// Default implementation to return the list of character sequences that can\n// separate auto-completion words.\nQStringList QsciLexer::autoCompletionWordSeparators() const\n{\n    return QStringList();\n}\n\n\n// Default implementation to return the list of keywords that can start a\n// block.\nconst char *QsciLexer::blockStartKeyword(int *) const\n{\n    return 0;\n}\n\n\n// Default implementation to return the list of characters that can start a\n// block.\nconst char *QsciLexer::blockStart(int *) const\n{\n    return 0;\n}\n\n\n// Default implementation to return the list of characters that can end a\n// block.\nconst char *QsciLexer::blockEnd(int *) const\n{\n    return 0;\n}\n\n\n// Default implementation to return the style used for braces.\nint QsciLexer::braceStyle() const\n{\n    return -1;\n}\n\n\n// Default implementation to return the number of lines to look back when\n// auto-indenting.\nint QsciLexer::blockLookback() const\n{\n    return 20;\n}\n\n\n// Default implementation to return the case sensitivity of the language.\nbool QsciLexer::caseSensitive() const\n{\n    return true;\n}\n\n\n// Default implementation to return the characters that make up a word.\nconst char *QsciLexer::wordCharacters() const\n{\n    return 0;\n}\n\n\n// Default implementation to return the style used for whitespace.\nint QsciLexer::defaultStyle() const\n{\n    return 0;\n}\n\n\n// Returns the foreground colour of the text for a style.\nQColor QsciLexer::color(int style) const\n{\n    return styleData(style).color;\n}\n\n\n// Returns the background colour of the text for a style.\nQColor QsciLexer::paper(int style) const\n{\n    return styleData(style).paper;\n}\n\n\n// Returns the font for a style.\nQFont QsciLexer::font(int style) const\n{\n    return styleData(style).font;\n}\n\n\n// Returns the end-of-line fill for a style.\nbool QsciLexer::eolFill(int style) const\n{\n    return styleData(style).eol_fill;\n}\n\n\n// Returns the set of keywords.\nconst char *QsciLexer::keywords(int) const\n{\n    return 0;\n}\n\n\n// Returns the default EOL fill for a style.\nbool QsciLexer::defaultEolFill(int) const\n{\n    return false;\n}\n\n\n// Returns the default font for a style.\nQFont QsciLexer::defaultFont(int) const\n{\n    return defaultFont();\n}\n\n\n// Returns the default font.\nQFont QsciLexer::defaultFont() const\n{\n    return defFont;\n}\n\n\n// Sets the default font.\nvoid QsciLexer::setDefaultFont(const QFont &f)\n{\n    defFont = f;\n}\n\n\n// Returns the default text colour for a style.\nQColor QsciLexer::defaultColor(int) const\n{\n    return defaultColor();\n}\n\n\n// Returns the default text colour.\nQColor QsciLexer::defaultColor() const\n{\n    return defColor;\n}\n\n\n// Sets the default text colour.\nvoid QsciLexer::setDefaultColor(const QColor &c)\n{\n    defColor = c;\n}\n\n\n// Returns the default paper colour for a styles.\nQColor QsciLexer::defaultPaper(int) const\n{\n    return defaultPaper();\n}\n\n\n// Returns the default paper colour.\nQColor QsciLexer::defaultPaper() const\n{\n    return defPaper;\n}\n\n\n// Sets the default paper colour.\nvoid QsciLexer::setDefaultPaper(const QColor &c)\n{\n    defPaper = c;\n\n    // Normally the default values are only intended to provide defaults when a\n    // lexer is first setup because once a style has been referenced then a\n    // copy of the default is made.  However the default paper is a special\n    // case because there is no other way to set the background colour used\n    // where there is no text.  Therefore we also actively set it.\n    setPaper(c, QsciScintillaBase::STYLE_DEFAULT);\n}\n\n\n// Read properties from the settings.\nbool QsciLexer::readProperties(QSettings &,const QString &)\n{\n    return true;\n}\n\n\n// Refresh all properties.\nvoid QsciLexer::refreshProperties()\n{\n}\n\n\n// Write properties to the settings.\nbool QsciLexer::writeProperties(QSettings &,const QString &) const\n{\n    return true;\n}\n\n\n// Restore the user settings.\nbool QsciLexer::readSettings(QSettings &qs,const char *prefix)\n{\n    bool ok, flag, rc = true;\n    int num;\n    QString key, full_key;\n    QStringList fdesc;\n\n    setStyleDefaults();\n\n    // Read the styles.\n    for (int i = 0; i <= QsciScintillaBase::STYLE_MAX; ++i)\n    {\n        // Ignore invalid styles.\n        if (description(i).isEmpty())\n            continue;\n\n        key = QString(\"%1/%2/style%3/\").arg(prefix).arg(language()).arg(i);\n\n        // Read the foreground colour.\n        full_key = key + \"color\";\n\n        ok = qs.contains(full_key);\n        num = qs.value(full_key).toInt();\n\n        if (ok)\n            setColor(QColor((num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff), i);\n        else\n            rc = false;\n\n        // Read the end-of-line fill.\n        full_key = key + \"eolfill\";\n\n        ok = qs.contains(full_key);\n        flag = qs.value(full_key, false).toBool();\n\n        if (ok)\n            setEolFill(flag, i);\n        else\n            rc = false;\n\n        // Read the font.  First try the deprecated format that uses an integer\n        // point size.\n        full_key = key + \"font\";\n\n        ok = qs.contains(full_key);\n        fdesc = qs.value(full_key).toStringList();\n\n        if (ok && fdesc.count() == 5)\n        {\n            QFont f;\n\n            f.setFamily(fdesc[0]);\n            f.setPointSize(fdesc[1].toInt());\n            f.setBold(fdesc[2].toInt());\n            f.setItalic(fdesc[3].toInt());\n            f.setUnderline(fdesc[4].toInt());\n\n            setFont(f, i);\n        }\n        else\n            rc = false;\n\n        // Now try the newer font format that uses a floating point point size.\n        // It is not an error if it doesn't exist.\n        full_key = key + \"font2\";\n\n        ok = qs.contains(full_key);\n        fdesc = qs.value(full_key).toStringList();\n\n        if (ok)\n        {\n            // Allow for future versions with more fields.\n            if (fdesc.count() >= 5)\n            {\n                QFont f;\n\n                f.setFamily(fdesc[0]);\n                f.setPointSizeF(fdesc[1].toDouble());\n                f.setBold(fdesc[2].toInt());\n                f.setItalic(fdesc[3].toInt());\n                f.setUnderline(fdesc[4].toInt());\n\n                setFont(f, i);\n            }\n            else\n            {\n                rc = false;\n            }\n        }\n\n        // Read the background colour.\n        full_key = key + \"paper\";\n\n        ok = qs.contains(full_key);\n        num = qs.value(full_key).toInt();\n\n        if (ok)\n            setPaper(QColor((num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff), i);\n        else\n            rc = false;\n    }\n\n    // Read the properties.\n    key = QString(\"%1/%2/properties/\").arg(prefix).arg(language());\n\n    if (!readProperties(qs,key))\n        rc = false;\n\n    refreshProperties();\n\n    // Read the rest.\n    key = QString(\"%1/%2/\").arg(prefix).arg(language());\n\n    // Read the default foreground colour.\n    full_key = key + \"defaultcolor\";\n\n    ok = qs.contains(full_key);\n    num = qs.value(full_key).toInt();\n\n    if (ok)\n        setDefaultColor(QColor((num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff));\n    else\n        rc = false;\n\n    // Read the default background colour.\n    full_key = key + \"defaultpaper\";\n\n    ok = qs.contains(full_key);\n    num = qs.value(full_key).toInt();\n\n    if (ok)\n        setDefaultPaper(QColor((num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff));\n    else\n        rc = false;\n\n    // Read the default font.  First try the deprecated format that uses an\n    // integer point size.\n    full_key = key + \"defaultfont\";\n\n    ok = qs.contains(full_key);\n    fdesc = qs.value(full_key).toStringList();\n\n    if (ok && fdesc.count() == 5)\n    {\n        QFont f;\n\n        f.setFamily(fdesc[0]);\n        f.setPointSize(fdesc[1].toInt());\n        f.setBold(fdesc[2].toInt());\n        f.setItalic(fdesc[3].toInt());\n        f.setUnderline(fdesc[4].toInt());\n\n        setDefaultFont(f);\n    }\n    else\n        rc = false;\n\n    // Now try the newer font format that uses a floating point point size.  It\n    // is not an error if it doesn't exist.\n    full_key = key + \"defaultfont2\";\n\n    ok = qs.contains(full_key);\n    fdesc = qs.value(full_key).toStringList();\n\n    if (ok)\n    {\n        // Allow for future versions with more fields.\n        if (fdesc.count() >= 5)\n        {\n            QFont f;\n\n            f.setFamily(fdesc[0]);\n            f.setPointSizeF(fdesc[1].toDouble());\n            f.setBold(fdesc[2].toInt());\n            f.setItalic(fdesc[3].toInt());\n            f.setUnderline(fdesc[4].toInt());\n\n            setDefaultFont(f);\n        }\n        else\n        {\n            rc = false;\n        }\n    }\n\n    full_key = key + \"autoindentstyle\";\n\n    ok = qs.contains(full_key);\n    num = qs.value(full_key).toInt();\n\n    if (ok)\n        setAutoIndentStyle(num);\n    else\n        rc = false;\n\n    return rc;\n}\n\n\n// Save the user settings.\nbool QsciLexer::writeSettings(QSettings &qs,const char *prefix) const\n{\n    bool rc = true;\n    QString key, fmt(\"%1\");\n    int num;\n    QStringList fdesc;\n\n    setStyleDefaults();\n\n    // Write the styles.\n    for (int i = 0; i <= QsciScintillaBase::STYLE_MAX; ++i)\n    {\n        // Ignore invalid styles.\n        if (description(i).isEmpty())\n            continue;\n\n        QColor c;\n\n        key = QString(\"%1/%2/style%3/\").arg(prefix).arg(language()).arg(i);\n\n        // Write the foreground colour.\n        c = color(i);\n        num = (c.red() << 16) | (c.green() << 8) | c.blue();\n\n        qs.setValue(key + \"color\", num);\n\n        // Write the end-of-line fill.\n        qs.setValue(key + \"eolfill\", eolFill(i));\n\n        // Write the font using the deprecated format.\n        QFont f = font(i);\n\n        fdesc.clear();\n        fdesc += f.family();\n        fdesc += fmt.arg(f.pointSize());\n\n        // The casts are for Borland.\n        fdesc += fmt.arg((int)f.bold());\n        fdesc += fmt.arg((int)f.italic());\n        fdesc += fmt.arg((int)f.underline());\n\n        qs.setValue(key + \"font\", fdesc);\n\n        // Write the font using the newer format.\n        fdesc[1] = fmt.arg(f.pointSizeF());\n\n        qs.setValue(key + \"font2\", fdesc);\n\n        // Write the background colour.\n        c = paper(i);\n        num = (c.red() << 16) | (c.green() << 8) | c.blue();\n\n        qs.setValue(key + \"paper\", num);\n    }\n\n    // Write the properties.\n    key = QString(\"%1/%2/properties/\").arg(prefix).arg(language());\n\n    if (!writeProperties(qs,key))\n        rc = false;\n\n    // Write the rest.\n    key = QString(\"%1/%2/\").arg(prefix).arg(language());\n\n    // Write the default foreground colour.\n    num = (defColor.red() << 16) | (defColor.green() << 8) | defColor.blue();\n\n    qs.setValue(key + \"defaultcolor\", num);\n\n    // Write the default background colour.\n    num = (defPaper.red() << 16) | (defPaper.green() << 8) | defPaper.blue();\n\n    qs.setValue(key + \"defaultpaper\", num);\n\n    // Write the default font using the deprecated format.\n    fdesc.clear();\n    fdesc += defFont.family();\n    fdesc += fmt.arg(defFont.pointSize());\n\n    // The casts are for Borland.\n    fdesc += fmt.arg((int)defFont.bold());\n    fdesc += fmt.arg((int)defFont.italic());\n    fdesc += fmt.arg((int)defFont.underline());\n\n    qs.setValue(key + \"defaultfont\", fdesc);\n\n    // Write the font using the newer format.\n    fdesc[1] = fmt.arg(defFont.pointSizeF());\n\n    qs.setValue(key + \"defaultfont2\", fdesc);\n\n    qs.setValue(key + \"autoindentstyle\", autoIndStyle);\n\n    return rc;\n}\n\n\n// Return the auto-indentation style.\nint QsciLexer::autoIndentStyle()\n{\n    // We can't do this in the ctor because we want the virtuals to work.\n    if (autoIndStyle < 0)\n        autoIndStyle = (blockStartKeyword() || blockStart() || blockEnd()) ?\n                    0 : QsciScintilla::AiMaintain;\n\n    return autoIndStyle;\n}\n\n\n// Set the auto-indentation style.\nvoid QsciLexer::setAutoIndentStyle(int autoindentstyle)\n{\n    autoIndStyle = autoindentstyle;\n}\n\n\n// Set the foreground colour for a style.\nvoid QsciLexer::setColor(const QColor &c, int style)\n{\n    if (style >= 0)\n    {\n        styleData(style).color = c;\n        emit colorChanged(c, style);\n    }\n    else\n        for (int i = 0; i <= QsciScintillaBase::STYLE_MAX; ++i)\n            if (!description(i).isEmpty())\n                setColor(c, i);\n}\n\n\n// Set the end-of-line fill for a style.\nvoid QsciLexer::setEolFill(bool eolfill, int style)\n{\n    if (style >= 0)\n    {\n        styleData(style).eol_fill = eolfill;\n        emit eolFillChanged(eolfill, style);\n    }\n    else\n        for (int i = 0; i <= QsciScintillaBase::STYLE_MAX; ++i)\n            if (!description(i).isEmpty())\n                setEolFill(eolfill, i);\n}\n\n\n// Set the font for a style.\nvoid QsciLexer::setFont(const QFont &f, int style)\n{\n    if (style >= 0)\n    {\n        styleData(style).font = f;\n        emit fontChanged(f, style);\n    }\n    else\n        for (int i = 0; i <= QsciScintillaBase::STYLE_MAX; ++i)\n            if (!description(i).isEmpty())\n                setFont(f, i);\n}\n\n\n// Set the background colour for a style.\nvoid QsciLexer::setPaper(const QColor &c, int style)\n{\n    if (style >= 0)\n    {\n        styleData(style).paper = c;\n        emit paperChanged(c, style);\n    }\n    else\n    {\n        for (int i = 0; i <= QsciScintillaBase::STYLE_MAX; ++i)\n            if (!description(i).isEmpty())\n                setPaper(c, i);\n\n        emit paperChanged(c, QsciScintillaBase::STYLE_DEFAULT);\n    }\n}\n\n\n// Encode a QString as bytes.\nQByteArray QsciLexer::textAsBytes(const QString &text) const\n{\n    Q_ASSERT(attached_editor);\n\n    return attached_editor->textAsBytes(text);\n}\n\n\n// Decode bytes as a QString.\nQString QsciLexer::bytesAsText(const char *bytes, int size) const\n{\n    Q_ASSERT(attached_editor);\n\n    return attached_editor->bytesAsText(bytes, size);\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qscilexerbash.cpp",
    "content": "// This module implements the QsciLexerBash class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qscilexerbash.h\"\n\n#include <qcolor.h>\n#include <qfont.h>\n#include <qsettings.h>\n\n\n// The ctor.\nQsciLexerBash::QsciLexerBash(QObject *parent)\n    : QsciLexer(parent), fold_comments(false), fold_compact(true)\n{\n}\n\n\n// The dtor.\nQsciLexerBash::~QsciLexerBash()\n{\n}\n\n\n// Returns the language name.\nconst char *QsciLexerBash::language() const\n{\n    return \"Bash\";\n}\n\n\n// Returns the lexer name.\nconst char *QsciLexerBash::lexer() const\n{\n    return \"bash\";\n}\n\n\n// Return the style used for braces.\nint QsciLexerBash::braceStyle() const\n{\n    return Operator;\n}\n\n\n// Return the string of characters that comprise a word.\nconst char *QsciLexerBash::wordCharacters() const\n{\n    return \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$@%&\";\n}\n\n\n// Returns the foreground colour of the text for a style.\nQColor QsciLexerBash::defaultColor(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return QColor(0x80,0x80,0x80);\n\n    case Error:\n    case Backticks:\n        return QColor(0xff,0xff,0x00);\n\n    case Comment:\n        return QColor(0x00,0x7f,0x00);\n\n    case Number:\n        return QColor(0x00,0x7f,0x7f);\n\n    case Keyword:\n        return QColor(0x00,0x00,0x7f);\n\n    case DoubleQuotedString:\n    case SingleQuotedString:\n    case SingleQuotedHereDocument:\n        return QColor(0x7f,0x00,0x7f);\n\n    case Operator:\n    case Identifier:\n    case Scalar:\n    case ParameterExpansion:\n    case HereDocumentDelimiter:\n        return QColor(0x00,0x00,0x00);\n    }\n\n    return QsciLexer::defaultColor(style);\n}\n\n\n// Returns the end-of-line fill for a style.\nbool QsciLexerBash::defaultEolFill(int style) const\n{\n    switch (style)\n    {\n    case SingleQuotedHereDocument:\n        return true;\n    }\n\n    return QsciLexer::defaultEolFill(style);\n}\n\n\n// Returns the font of the text for a style.\nQFont QsciLexerBash::defaultFont(int style) const\n{\n    QFont f;\n\n    switch (style)\n    {\n    case Comment:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Comic Sans MS\",9);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Comic Sans MS\", 12);\n#else\n        f = QFont(\"Bitstream Vera Serif\",9);\n#endif\n        break;\n\n    case Keyword:\n    case Operator:\n        f = QsciLexer::defaultFont(style);\n        f.setBold(true);\n        break;\n\n    case DoubleQuotedString:\n    case SingleQuotedString:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Courier New\",10);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Courier\", 12);\n#else\n        f = QFont(\"Bitstream Vera Sans Mono\",9);\n#endif\n        break;\n\n    default:\n        f = QsciLexer::defaultFont(style);\n    }\n\n    return f;\n}\n\n\n// Returns the set of keywords.\nconst char *QsciLexerBash::keywords(int set) const\n{\n    if (set == 1)\n        return\n            \"alias ar asa awk banner basename bash bc bdiff break \"\n            \"bunzip2 bzip2 cal calendar case cat cc cd chmod \"\n            \"cksum clear cmp col comm compress continue cp cpio \"\n            \"crypt csplit ctags cut date dc dd declare deroff dev \"\n            \"df diff diff3 dircmp dirname do done du echo ed \"\n            \"egrep elif else env esac eval ex exec exit expand \"\n            \"export expr false fc fgrep fi file find fmt fold for \"\n            \"function functions getconf getopt getopts grep gres \"\n            \"hash head help history iconv id if in integer jobs \"\n            \"join kill local lc let line ln logname look ls m4 \"\n            \"mail mailx make man mkdir more mt mv newgrp nl nm \"\n            \"nohup ntps od pack paste patch pathchk pax pcat perl \"\n            \"pg pr print printf ps pwd read readonly red return \"\n            \"rev rm rmdir sed select set sh shift size sleep sort \"\n            \"spell split start stop strings strip stty sum \"\n            \"suspend sync tail tar tee test then time times touch \"\n            \"tr trap true tsort tty type typeset ulimit umask \"\n            \"unalias uname uncompress unexpand uniq unpack unset \"\n            \"until uudecode uuencode vi vim vpax wait wc whence \"\n            \"which while who wpaste wstart xargs zcat \"\n\n            \"chgrp chown chroot dir dircolors factor groups \"\n            \"hostid install link md5sum mkfifo mknod nice pinky \"\n            \"printenv ptx readlink seq sha1sum shred stat su tac \"\n            \"unlink users vdir whoami yes\";\n\n    return 0;\n}\n\n\n// Returns the user name of a style.\nQString QsciLexerBash::description(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return tr(\"Default\");\n\n    case Error:\n        return tr(\"Error\");\n\n    case Comment:\n        return tr(\"Comment\");\n\n    case Number:\n        return tr(\"Number\");\n\n    case Keyword:\n        return tr(\"Keyword\");\n\n    case DoubleQuotedString:\n        return tr(\"Double-quoted string\");\n\n    case SingleQuotedString:\n        return tr(\"Single-quoted string\");\n\n    case Operator:\n        return tr(\"Operator\");\n\n    case Identifier:\n        return tr(\"Identifier\");\n\n    case Scalar:\n        return tr(\"Scalar\");\n\n    case ParameterExpansion:\n        return tr(\"Parameter expansion\");\n\n    case Backticks:\n        return tr(\"Backticks\");\n\n    case HereDocumentDelimiter:\n        return tr(\"Here document delimiter\");\n\n    case SingleQuotedHereDocument:\n        return tr(\"Single-quoted here document\");\n    }\n\n    return QString();\n}\n\n\n// Returns the background colour of the text for a style.\nQColor QsciLexerBash::defaultPaper(int style) const\n{\n    switch (style)\n    {\n    case Error:\n        return QColor(0xff,0x00,0x00);\n\n    case Scalar:\n        return QColor(0xff,0xe0,0xe0);\n\n    case ParameterExpansion:\n        return QColor(0xff,0xff,0xe0);\n\n    case Backticks:\n        return QColor(0xa0,0x80,0x80);\n\n    case HereDocumentDelimiter:\n    case SingleQuotedHereDocument:\n        return QColor(0xdd,0xd0,0xdd);\n    }\n\n    return QsciLexer::defaultPaper(style);\n}\n\n\n// Refresh all properties.\nvoid QsciLexerBash::refreshProperties()\n{\n    setCommentProp();\n    setCompactProp();\n}\n\n\n// Read properties from the settings.\nbool QsciLexerBash::readProperties(QSettings &qs, const QString &prefix)\n{\n    int rc = true;\n\n    fold_comments = qs.value(prefix + \"foldcomments\", false).toBool();\n    fold_compact = qs.value(prefix + \"foldcompact\", true).toBool();\n\n    return rc;\n}\n\n\n// Write properties to the settings.\nbool QsciLexerBash::writeProperties(QSettings &qs, const QString &prefix) const\n{\n    int rc = true;\n\n    qs.setValue(prefix + \"foldcomments\", fold_comments);\n    qs.setValue(prefix + \"foldcompact\", fold_compact);\n\n    return rc;\n}\n\n\n// Return true if comments can be folded.\nbool QsciLexerBash::foldComments() const\n{\n    return fold_comments;\n}\n\n\n// Set if comments can be folded.\nvoid QsciLexerBash::setFoldComments(bool fold)\n{\n    fold_comments = fold;\n\n    setCommentProp();\n}\n\n\n// Set the \"fold.comment\" property.\nvoid QsciLexerBash::setCommentProp()\n{\n    emit propertyChanged(\"fold.comment\", (fold_comments ? \"1\" : \"0\"));\n}\n\n\n// Return true if folds are compact.\nbool QsciLexerBash::foldCompact() const\n{\n    return fold_compact;\n}\n\n\n// Set if folds are compact\nvoid QsciLexerBash::setFoldCompact(bool fold)\n{\n    fold_compact = fold;\n\n    setCompactProp();\n}\n\n\n// Set the \"fold.compact\" property.\nvoid QsciLexerBash::setCompactProp()\n{\n    emit propertyChanged(\"fold.compact\", (fold_compact ? \"1\" : \"0\"));\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qscilexerbatch.cpp",
    "content": "// This module implements the QsciLexerBatch class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qscilexerbatch.h\"\n\n#include <qcolor.h>\n#include <qfont.h>\n#include <qsettings.h>\n\n\n// The ctor.\nQsciLexerBatch::QsciLexerBatch(QObject *parent)\n    : QsciLexer(parent)\n{\n}\n\n\n// The dtor.\nQsciLexerBatch::~QsciLexerBatch()\n{\n}\n\n\n// Returns the language name.\nconst char *QsciLexerBatch::language() const\n{\n    return \"Batch\";\n}\n\n\n// Returns the lexer name.\nconst char *QsciLexerBatch::lexer() const\n{\n    return \"batch\";\n}\n\n\n// Return the string of characters that comprise a word.\nconst char *QsciLexerBatch::wordCharacters() const\n{\n    return \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-\";\n}\n\n\n// Returns the foreground colour of the text for a style.\nQColor QsciLexerBatch::defaultColor(int style) const\n{\n    switch (style)\n    {\n    case Default:\n    case Operator:\n        return QColor(0x00,0x00,0x00);\n\n    case Comment:\n        return QColor(0x00,0x7f,0x00);\n\n    case Keyword:\n    case ExternalCommand:\n        return QColor(0x00,0x00,0x7f);\n\n    case Label:\n        return QColor(0x7f,0x00,0x7f);\n\n    case HideCommandChar:\n        return QColor(0x7f,0x7f,0x00);\n\n    case Variable:\n        return QColor(0x80,0x00,0x80);\n    }\n\n    return QsciLexer::defaultColor(style);\n}\n\n\n// Returns the end-of-line fill for a style.\nbool QsciLexerBatch::defaultEolFill(int style) const\n{\n    switch (style)\n    {\n    case Label:\n        return true;\n    }\n\n    return QsciLexer::defaultEolFill(style);\n}\n\n\n// Returns the font of the text for a style.\nQFont QsciLexerBatch::defaultFont(int style) const\n{\n    QFont f;\n\n    switch (style)\n    {\n    case Comment:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Comic Sans MS\",9);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Comic Sans MS\", 12);\n#else\n        f = QFont(\"Bitstream Vera Serif\",9);\n#endif\n        break;\n\n    case Keyword:\n        f = QsciLexer::defaultFont(style);\n        f.setBold(true);\n        break;\n\n    case ExternalCommand:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Courier New\",10);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Courier\", 12);\n#else\n        f = QFont(\"Bitstream Vera Sans Mono\",9);\n#endif\n        f.setBold(true);\n        break;\n\n    default:\n        f = QsciLexer::defaultFont(style);\n    }\n\n    return f;\n}\n\n\n// Returns the set of keywords.\nconst char *QsciLexerBatch::keywords(int set) const\n{\n    if (set == 1)\n        return\n            \"rem set if exist errorlevel for in do break call \"\n            \"chcp cd chdir choice cls country ctty date del \"\n            \"erase dir echo exit goto loadfix loadhigh mkdir md \"\n            \"move path pause prompt rename ren rmdir rd shift \"\n            \"time type ver verify vol com con lpt nul\";\n\n    return 0;\n}\n\n\n// Return the case sensitivity.\nbool QsciLexerBatch::caseSensitive() const\n{\n    return false;\n}\n\n\n// Returns the user name of a style.\nQString QsciLexerBatch::description(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return tr(\"Default\");\n\n    case Comment:\n        return tr(\"Comment\");\n\n    case Keyword:\n        return tr(\"Keyword\");\n\n    case Label:\n        return tr(\"Label\");\n\n    case HideCommandChar:\n        return tr(\"Hide command character\");\n\n    case ExternalCommand:\n        return tr(\"External command\");\n\n    case Variable:\n        return tr(\"Variable\");\n\n    case Operator:\n        return tr(\"Operator\");\n    }\n\n    return QString();\n}\n\n\n// Returns the background colour of the text for a style.\nQColor QsciLexerBatch::defaultPaper(int style) const\n{\n    switch (style)\n    {\n    case Label:\n        return QColor(0x60,0x60,0x60);\n    }\n\n    return QsciLexer::defaultPaper(style);\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qscilexercpp.cpp",
    "content": "// This module implements the QsciLexerCPP class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qscilexercpp.h\"\n\n#include <qcolor.h>\n#include <qfont.h>\n#include <qsettings.h>\n\n\n// The ctor.\nQsciLexerCPP::QsciLexerCPP(QObject *parent, bool caseInsensitiveKeywords)\n    : QsciLexer(parent),\n      fold_atelse(false), fold_comments(false), fold_compact(true),\n      fold_preproc(true), style_preproc(false), dollars(true),\n      highlight_triple(false), highlight_hash(false), highlight_back(false),\n      highlight_escape(false), vs_escape(false),\n      nocase(caseInsensitiveKeywords)\n{\n}\n\n\n// The dtor.\nQsciLexerCPP::~QsciLexerCPP()\n{\n}\n\n\n// Returns the language name.\nconst char *QsciLexerCPP::language() const\n{\n    return \"C++\";\n}\n\n\n// Returns the lexer name.\nconst char *QsciLexerCPP::lexer() const\n{\n    return (nocase ? \"cppnocase\" : \"cpp\");\n}\n\n\n// Return the set of character sequences that can separate auto-completion\n// words.\nQStringList QsciLexerCPP::autoCompletionWordSeparators() const\n{\n    QStringList wl;\n\n    wl << \"::\" << \"->\" << \".\";\n\n    return wl;\n}\n\n\n// Return the list of keywords that can start a block.\nconst char *QsciLexerCPP::blockStartKeyword(int *style) const\n{\n    if (style)\n        *style = Keyword;\n\n    return \"case catch class default do else finally for if private \"\n           \"protected public struct try union while\";\n}\n\n\n// Return the list of characters that can start a block.\nconst char *QsciLexerCPP::blockStart(int *style) const\n{\n    if (style)\n        *style = Operator;\n\n    return \"{\";\n}\n\n\n// Return the list of characters that can end a block.\nconst char *QsciLexerCPP::blockEnd(int *style) const\n{\n    if (style)\n        *style = Operator;\n\n    return \"}\";\n}\n\n\n// Return the style used for braces.\nint QsciLexerCPP::braceStyle() const\n{\n    return Operator;\n}\n\n\n// Return the string of characters that comprise a word.\nconst char *QsciLexerCPP::wordCharacters() const\n{\n    return \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_#\";\n}\n\n\n// Returns the foreground colour of the text for a style.\nQColor QsciLexerCPP::defaultColor(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return QColor(0x80, 0x80, 0x80);\n\n    case Comment:\n    case CommentLine:\n        return QColor(0x00, 0x7f, 0x00);\n\n    case CommentDoc:\n    case CommentLineDoc:\n    case PreProcessorCommentLineDoc:\n        return QColor(0x3f, 0x70, 0x3f);\n\n    case Number:\n        return QColor(0x00, 0x7f, 0x7f);\n\n    case Keyword:\n        return QColor(0x00, 0x00, 0x7f);\n\n    case DoubleQuotedString:\n    case SingleQuotedString:\n    case RawString:\n        return QColor(0x7f, 0x00, 0x7f);\n\n    case PreProcessor:\n        return QColor(0x7f, 0x7f, 0x00);\n\n    case Operator:\n    case UnclosedString:\n        return QColor(0x00, 0x00, 0x00);\n\n    case VerbatimString:\n    case TripleQuotedVerbatimString:\n    case HashQuotedString:\n        return QColor(0x00, 0x7f, 0x00);\n\n    case Regex:\n        return QColor(0x3f, 0x7f, 0x3f);\n\n    case CommentDocKeyword:\n        return QColor(0x30, 0x60, 0xa0);\n\n    case CommentDocKeywordError:\n        return QColor(0x80, 0x40, 0x20);\n\n    case PreProcessorComment:\n        return QColor(0x65, 0x99, 0x00);\n\n    case InactiveDefault:\n    case InactiveUUID:\n    case InactiveCommentLineDoc:\n    case InactiveKeywordSet2:\n    case InactiveCommentDocKeyword:\n    case InactiveCommentDocKeywordError:\n    case InactivePreProcessorCommentLineDoc:\n        return QColor(0xc0, 0xc0, 0xc0);\n\n    case InactiveComment:\n    case InactiveCommentLine:\n    case InactiveNumber:\n    case InactiveVerbatimString:\n    case InactiveTripleQuotedVerbatimString:\n    case InactiveHashQuotedString:\n        return QColor(0x90, 0xb0, 0x90);\n\n    case InactiveCommentDoc:\n        return QColor(0xd0, 0xd0, 0xd0);\n\n    case InactiveKeyword:\n        return QColor(0x90, 0x90, 0xb0);\n\n    case InactiveDoubleQuotedString:\n    case InactiveSingleQuotedString:\n    case InactiveRawString:\n        return QColor(0xb0, 0x90, 0xb0);\n\n    case InactivePreProcessor:\n        return QColor(0xb0, 0xb0, 0x90);\n\n    case InactiveOperator:\n    case InactiveIdentifier:\n    case InactiveGlobalClass:\n        return QColor(0xb0, 0xb0, 0xb0);\n\n    case InactiveUnclosedString:\n        return QColor(0x00, 0x00, 0x00);\n\n    case InactiveRegex:\n        return QColor(0x7f, 0xaf, 0x7f);\n\n    case InactivePreProcessorComment:\n        return QColor(0xa0, 0xc0, 0x90);\n\n    case UserLiteral:\n        return QColor(0xc0, 0x60, 0x00);\n\n    case InactiveUserLiteral:\n        return QColor(0xd7, 0xa0, 0x90);\n\n    case TaskMarker:\n        return QColor(0xbe, 0x07, 0xff);\n\n    case InactiveTaskMarker:\n        return QColor(0xc3, 0xa1, 0xcf);\n    }\n\n    return QsciLexer::defaultColor(style);\n}\n\n\n// Returns the end-of-line fill for a style.\nbool QsciLexerCPP::defaultEolFill(int style) const\n{\n    switch (style)\n    {\n    case UnclosedString:\n    case InactiveUnclosedString:\n    case VerbatimString:\n    case InactiveVerbatimString:\n    case Regex:\n    case InactiveRegex:\n    case TripleQuotedVerbatimString:\n    case InactiveTripleQuotedVerbatimString:\n    case HashQuotedString:\n    case InactiveHashQuotedString:\n        return true;\n    }\n\n    return QsciLexer::defaultEolFill(style);\n}\n\n\n// Returns the font of the text for a style.\nQFont QsciLexerCPP::defaultFont(int style) const\n{\n    QFont f;\n\n    switch (style)\n    {\n    case Comment:\n    case InactiveComment:\n    case CommentLine:\n    case InactiveCommentLine:\n    case CommentDoc:\n    case InactiveCommentDoc:\n    case CommentLineDoc:\n    case InactiveCommentLineDoc:\n    case CommentDocKeyword:\n    case InactiveCommentDocKeyword:\n    case CommentDocKeywordError:\n    case InactiveCommentDocKeywordError:\n    case TaskMarker:\n    case InactiveTaskMarker:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Comic Sans MS\",9);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Comic Sans MS\", 12);\n#else\n        f = QFont(\"Bitstream Vera Serif\",9);\n#endif\n        break;\n\n    case Keyword:\n    case InactiveKeyword:\n    case Operator:\n    case InactiveOperator:\n        f = QsciLexer::defaultFont(style);\n        f.setBold(true);\n        break;\n\n    case DoubleQuotedString:\n    case InactiveDoubleQuotedString:\n    case SingleQuotedString:\n    case InactiveSingleQuotedString:\n    case UnclosedString:\n    case InactiveUnclosedString:\n    case VerbatimString:\n    case InactiveVerbatimString:\n    case Regex:\n    case InactiveRegex:\n    case TripleQuotedVerbatimString:\n    case InactiveTripleQuotedVerbatimString:\n    case HashQuotedString:\n    case InactiveHashQuotedString:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Courier New\",10);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Courier\", 12);\n#else\n        f = QFont(\"Bitstream Vera Sans Mono\",9);\n#endif\n        break;\n\n    default:\n        f = QsciLexer::defaultFont(style);\n    }\n\n    return f;\n}\n\n\n// Returns the set of keywords.\nconst char *QsciLexerCPP::keywords(int set) const\n{\n    if (set == 1)\n        return\n            \"and and_eq asm auto bitand bitor bool break case \"\n            \"catch char class compl const const_cast continue \"\n            \"default delete do double dynamic_cast else enum \"\n            \"explicit export extern false float for friend goto if \"\n            \"inline int long mutable namespace new not not_eq \"\n            \"operator or or_eq private protected public register \"\n            \"reinterpret_cast return short signed sizeof static \"\n            \"static_cast struct switch template this throw true \"\n            \"try typedef typeid typename union unsigned using \"\n            \"virtual void volatile wchar_t while xor xor_eq\";\n\n    if (set == 3)\n        return\n            \"a addindex addtogroup anchor arg attention author b \"\n            \"brief bug c class code date def defgroup deprecated \"\n            \"dontinclude e em endcode endhtmlonly endif \"\n            \"endlatexonly endlink endverbatim enum example \"\n            \"exception f$ f[ f] file fn hideinitializer \"\n            \"htmlinclude htmlonly if image include ingroup \"\n            \"internal invariant interface latexonly li line link \"\n            \"mainpage name namespace nosubgrouping note overload \"\n            \"p page par param post pre ref relates remarks return \"\n            \"retval sa section see showinitializer since skip \"\n            \"skipline struct subsection test throw todo typedef \"\n            \"union until var verbatim verbinclude version warning \"\n            \"weakgroup $ @ \\\\ & < > # { }\";\n\n    return 0;\n}\n\n\n// Returns the user name of a style.\nQString QsciLexerCPP::description(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return tr(\"Default\");\n\n    case InactiveDefault:\n        return tr(\"Inactive default\");\n\n    case Comment:\n        return tr(\"C comment\");\n\n    case InactiveComment:\n        return tr(\"Inactive C comment\");\n\n    case CommentLine:\n        return tr(\"C++ comment\");\n\n    case InactiveCommentLine:\n        return tr(\"Inactive C++ comment\");\n\n    case CommentDoc:\n        return tr(\"JavaDoc style C comment\");\n\n    case InactiveCommentDoc:\n        return tr(\"Inactive JavaDoc style C comment\");\n\n    case Number:\n        return tr(\"Number\");\n\n    case InactiveNumber:\n        return tr(\"Inactive number\");\n\n    case Keyword:\n        return tr(\"Keyword\");\n\n    case InactiveKeyword:\n        return tr(\"Inactive keyword\");\n\n    case DoubleQuotedString:\n        return tr(\"Double-quoted string\");\n\n    case InactiveDoubleQuotedString:\n        return tr(\"Inactive double-quoted string\");\n\n    case SingleQuotedString:\n        return tr(\"Single-quoted string\");\n\n    case InactiveSingleQuotedString:\n        return tr(\"Inactive single-quoted string\");\n\n    case UUID:\n        return tr(\"IDL UUID\");\n\n    case InactiveUUID:\n        return tr(\"Inactive IDL UUID\");\n\n    case PreProcessor:\n        return tr(\"Pre-processor block\");\n\n    case InactivePreProcessor:\n        return tr(\"Inactive pre-processor block\");\n\n    case Operator:\n        return tr(\"Operator\");\n\n    case InactiveOperator:\n        return tr(\"Inactive operator\");\n\n    case Identifier:\n        return tr(\"Identifier\");\n\n    case InactiveIdentifier:\n        return tr(\"Inactive identifier\");\n\n    case UnclosedString:\n        return tr(\"Unclosed string\");\n\n    case InactiveUnclosedString:\n        return tr(\"Inactive unclosed string\");\n\n    case VerbatimString:\n        return tr(\"C# verbatim string\");\n\n    case InactiveVerbatimString:\n        return tr(\"Inactive C# verbatim string\");\n\n    case Regex:\n        return tr(\"JavaScript regular expression\");\n\n    case InactiveRegex:\n        return tr(\"Inactive JavaScript regular expression\");\n\n    case CommentLineDoc:\n        return tr(\"JavaDoc style C++ comment\");\n\n    case InactiveCommentLineDoc:\n        return tr(\"Inactive JavaDoc style C++ comment\");\n\n    case KeywordSet2:\n        return tr(\"Secondary keywords and identifiers\");\n\n    case InactiveKeywordSet2:\n        return tr(\"Inactive secondary keywords and identifiers\");\n\n    case CommentDocKeyword:\n        return tr(\"JavaDoc keyword\");\n\n    case InactiveCommentDocKeyword:\n        return tr(\"Inactive JavaDoc keyword\");\n\n    case CommentDocKeywordError:\n        return tr(\"JavaDoc keyword error\");\n\n    case InactiveCommentDocKeywordError:\n        return tr(\"Inactive JavaDoc keyword error\");\n\n    case GlobalClass:\n        return tr(\"Global classes and typedefs\");\n\n    case InactiveGlobalClass:\n        return tr(\"Inactive global classes and typedefs\");\n\n    case RawString:\n        return tr(\"C++ raw string\");\n\n    case InactiveRawString:\n        return tr(\"Inactive C++ raw string\");\n\n    case TripleQuotedVerbatimString:\n        return tr(\"Vala triple-quoted verbatim string\");\n\n    case InactiveTripleQuotedVerbatimString:\n        return tr(\"Inactive Vala triple-quoted verbatim string\");\n\n    case HashQuotedString:\n        return tr(\"Pike hash-quoted string\");\n\n    case InactiveHashQuotedString:\n        return tr(\"Inactive Pike hash-quoted string\");\n\n    case PreProcessorComment:\n        return tr(\"Pre-processor C comment\");\n\n    case InactivePreProcessorComment:\n        return tr(\"Inactive pre-processor C comment\");\n\n    case PreProcessorCommentLineDoc:\n        return tr(\"JavaDoc style pre-processor comment\");\n\n    case InactivePreProcessorCommentLineDoc:\n        return tr(\"Inactive JavaDoc style pre-processor comment\");\n\n    case UserLiteral:\n        return tr(\"User-defined literal\");\n\n    case InactiveUserLiteral:\n        return tr(\"Inactive user-defined literal\");\n\n    case TaskMarker:\n        return tr(\"Task marker\");\n\n    case InactiveTaskMarker:\n        return tr(\"Inactive task marker\");\n\n    case EscapeSequence:\n        return tr(\"Escape sequence\");\n\n    case InactiveEscapeSequence:\n        return tr(\"Inactive escape sequence\");\n    }\n\n    return QString();\n}\n\n\n// Returns the background colour of the text for a style.\nQColor QsciLexerCPP::defaultPaper(int style) const\n{\n    switch (style)\n    {\n    case UnclosedString:\n    case InactiveUnclosedString:\n        return QColor(0xe0,0xc0,0xe0);\n\n    case VerbatimString:\n    case InactiveVerbatimString:\n    case TripleQuotedVerbatimString:\n    case InactiveTripleQuotedVerbatimString:\n        return QColor(0xe0,0xff,0xe0);\n\n    case Regex:\n    case InactiveRegex:\n        return QColor(0xe0,0xf0,0xe0);\n\n    case RawString:\n    case InactiveRawString:\n        return QColor(0xff,0xf3,0xff);\n\n    case HashQuotedString:\n    case InactiveHashQuotedString:\n        return QColor(0xe7,0xff,0xd7);\n    }\n\n    return QsciLexer::defaultPaper(style);\n}\n\n\n// Refresh all properties.\nvoid QsciLexerCPP::refreshProperties()\n{\n    setAtElseProp();\n    setCommentProp();\n    setCompactProp();\n    setPreprocProp();\n    setStylePreprocProp();\n    setDollarsProp();\n    setHighlightTripleProp();\n    setHighlightHashProp();\n    setHighlightBackProp();\n    setHighlightEscapeProp();\n    setVerbatimStringEscapeProp();\n}\n\n\n// Read properties from the settings.\nbool QsciLexerCPP::readProperties(QSettings &qs,const QString &prefix)\n{\n    fold_atelse = qs.value(prefix + \"foldatelse\", false).toBool();\n    fold_comments = qs.value(prefix + \"foldcomments\", false).toBool();\n    fold_compact = qs.value(prefix + \"foldcompact\", true).toBool();\n    fold_preproc = qs.value(prefix + \"foldpreprocessor\", true).toBool();\n    style_preproc = qs.value(prefix + \"stylepreprocessor\", false).toBool();\n    dollars = qs.value(prefix + \"dollars\", true).toBool();\n    highlight_triple = qs.value(prefix + \"highlighttriple\", false).toBool();\n    highlight_hash = qs.value(prefix + \"highlighthash\", false).toBool();\n    highlight_back = qs.value(prefix + \"highlightback\", false).toBool();\n    highlight_escape = qs.value(prefix + \"highlightescape\", false).toBool();\n    vs_escape = qs.value(prefix + \"verbatimstringescape\", false).toBool();\n\n    return true;\n}\n\n\n// Write properties to the settings.\nbool QsciLexerCPP::writeProperties(QSettings &qs,const QString &prefix) const\n{\n    qs.setValue(prefix + \"foldatelse\", fold_atelse);\n    qs.setValue(prefix + \"foldcomments\", fold_comments);\n    qs.setValue(prefix + \"foldcompact\", fold_compact);\n    qs.setValue(prefix + \"foldpreprocessor\", fold_preproc);\n    qs.setValue(prefix + \"stylepreprocessor\", style_preproc);\n    qs.setValue(prefix + \"dollars\", dollars);\n    qs.setValue(prefix + \"highlighttriple\", highlight_triple);\n    qs.setValue(prefix + \"highlighthash\", highlight_hash);\n    qs.setValue(prefix + \"highlightback\", highlight_back);\n    qs.setValue(prefix + \"highlightescape\", highlight_escape);\n    qs.setValue(prefix + \"verbatimstringescape\", vs_escape);\n\n    return true;\n}\n\n\n// Set if else can be folded.\nvoid QsciLexerCPP::setFoldAtElse(bool fold)\n{\n    fold_atelse = fold;\n\n    setAtElseProp();\n}\n\n\n// Set the \"fold.at.else\" property.\nvoid QsciLexerCPP::setAtElseProp()\n{\n    emit propertyChanged(\"fold.at.else\",(fold_atelse ? \"1\" : \"0\"));\n}\n\n\n// Set if comments can be folded.\nvoid QsciLexerCPP::setFoldComments(bool fold)\n{\n    fold_comments = fold;\n\n    setCommentProp();\n}\n\n\n// Set the \"fold.comment\" property.\nvoid QsciLexerCPP::setCommentProp()\n{\n    emit propertyChanged(\"fold.comment\",(fold_comments ? \"1\" : \"0\"));\n}\n\n\n// Set if folds are compact\nvoid QsciLexerCPP::setFoldCompact(bool fold)\n{\n    fold_compact = fold;\n\n    setCompactProp();\n}\n\n\n// Set the \"fold.compact\" property.\nvoid QsciLexerCPP::setCompactProp()\n{\n    emit propertyChanged(\"fold.compact\",(fold_compact ? \"1\" : \"0\"));\n}\n\n\n// Set if preprocessor blocks can be folded.\nvoid QsciLexerCPP::setFoldPreprocessor(bool fold)\n{\n    fold_preproc = fold;\n\n    setPreprocProp();\n}\n\n\n// Set the \"fold.preprocessor\" property.\nvoid QsciLexerCPP::setPreprocProp()\n{\n    emit propertyChanged(\"fold.preprocessor\",(fold_preproc ? \"1\" : \"0\"));\n}\n\n\n// Set if preprocessor lines are styled.\nvoid QsciLexerCPP::setStylePreprocessor(bool style)\n{\n    style_preproc = style;\n\n    setStylePreprocProp();\n}\n\n\n// Set the \"styling.within.preprocessor\" property.\nvoid QsciLexerCPP::setStylePreprocProp()\n{\n    emit propertyChanged(\"styling.within.preprocessor\",(style_preproc ? \"1\" : \"0\"));\n}\n\n\n// Set if '$' characters are allowed.\nvoid QsciLexerCPP::setDollarsAllowed(bool allowed)\n{\n    dollars = allowed;\n\n    setDollarsProp();\n}\n\n\n// Set the \"lexer.cpp.allow.dollars\" property.\nvoid QsciLexerCPP::setDollarsProp()\n{\n    emit propertyChanged(\"lexer.cpp.allow.dollars\",(dollars ? \"1\" : \"0\"));\n}\n\n\n// Set if triple quoted strings are highlighted.\nvoid QsciLexerCPP::setHighlightTripleQuotedStrings(bool enabled)\n{\n    highlight_triple = enabled;\n\n    setHighlightTripleProp();\n}\n\n\n// Set the \"lexer.cpp.triplequoted.strings\" property.\nvoid QsciLexerCPP::setHighlightTripleProp()\n{\n    emit propertyChanged(\"lexer.cpp.triplequoted.strings\",\n            (highlight_triple ? \"1\" : \"0\"));\n}\n\n\n// Set if hash quoted strings are highlighted.\nvoid QsciLexerCPP::setHighlightHashQuotedStrings(bool enabled)\n{\n    highlight_hash = enabled;\n\n    setHighlightHashProp();\n}\n\n\n// Set the \"lexer.cpp.hashquoted.strings\" property.\nvoid QsciLexerCPP::setHighlightHashProp()\n{\n    emit propertyChanged(\"lexer.cpp.hashquoted.strings\",\n            (highlight_hash ? \"1\" : \"0\"));\n}\n\n\n// Set if back-quoted strings are highlighted.\nvoid QsciLexerCPP::setHighlightBackQuotedStrings(bool enabled)\n{\n    highlight_back = enabled;\n\n    setHighlightBackProp();\n}\n\n\n// Set the \"lexer.cpp.backquoted.strings\" property.\nvoid QsciLexerCPP::setHighlightBackProp()\n{\n    emit propertyChanged(\"lexer.cpp.backquoted.strings\",\n            (highlight_back ? \"1\" : \"0\"));\n}\n\n\n// Set if escape sequences in strings are highlighted.\nvoid QsciLexerCPP::setHighlightEscapeSequences(bool enabled)\n{\n    highlight_escape = enabled;\n\n    setHighlightEscapeProp();\n}\n\n\n// Set the \"lexer.cpp.escape.sequence\" property.\nvoid QsciLexerCPP::setHighlightEscapeProp()\n{\n    emit propertyChanged(\"lexer.cpp.escape.sequence\",\n            (highlight_escape ? \"1\" : \"0\"));\n}\n\n\n// Set if escape sequences in verbatim strings are allowed.\nvoid QsciLexerCPP::setVerbatimStringEscapeSequencesAllowed(bool allowed)\n{\n    vs_escape = allowed;\n\n    setVerbatimStringEscapeProp();\n}\n\n\n// Set the \"lexer.cpp.verbatim.strings.allow.escapes\" property.\nvoid QsciLexerCPP::setVerbatimStringEscapeProp()\n{\n    emit propertyChanged(\"lexer.cpp.verbatim.strings.allow.escapes\",\n            (vs_escape ? \"1\" : \"0\"));\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qscilexerdiff.cpp",
    "content": "// This module implements the QsciLexerDiff class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qscilexerdiff.h\"\n\n#include <qcolor.h>\n#include <qfont.h>\n#include <qsettings.h>\n\n\n// The ctor.\nQsciLexerDiff::QsciLexerDiff(QObject *parent)\n    : QsciLexer(parent)\n{\n}\n\n\n// The dtor.\nQsciLexerDiff::~QsciLexerDiff()\n{\n}\n\n\n// Returns the language name.\nconst char *QsciLexerDiff::language() const\n{\n    return \"Diff\";\n}\n\n\n// Returns the lexer name.\nconst char *QsciLexerDiff::lexer() const\n{\n    return \"diff\";\n}\n\n\n// Return the string of characters that comprise a word.\nconst char *QsciLexerDiff::wordCharacters() const\n{\n    return \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-\";\n}\n\n\n// Returns the foreground colour of the text for a style.\nQColor QsciLexerDiff::defaultColor(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return QColor(0x00,0x00,0x00);\n\n    case Comment:\n        return QColor(0x00,0x7f,0x00);\n\n    case Command:\n        return QColor(0x7f,0x7f,0x00);\n\n    case Header:\n        return QColor(0x7f,0x00,0x00);\n\n    case Position:\n        return QColor(0x7f,0x00,0x7f);\n\n    case LineRemoved:\n    case AddingPatchRemoved:\n    case RemovingPatchRemoved:\n        return QColor(0x00,0x7f,0x7f);\n\n    case LineAdded:\n    case AddingPatchAdded:\n    case RemovingPatchAdded:\n        return QColor(0x00,0x00,0x7f);\n\n    case LineChanged:\n        return QColor(0x7f,0x7f,0x7f);\n    }\n\n    return QsciLexer::defaultColor(style);\n}\n\n\n// Returns the user name of a style.\nQString QsciLexerDiff::description(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return tr(\"Default\");\n\n    case Comment:\n        return tr(\"Comment\");\n\n    case Command:\n        return tr(\"Command\");\n\n    case Header:\n        return tr(\"Header\");\n\n    case Position:\n        return tr(\"Position\");\n\n    case LineRemoved:\n        return tr(\"Removed line\");\n\n    case LineAdded:\n        return tr(\"Added line\");\n\n    case LineChanged:\n        return tr(\"Changed line\");\n\n    case AddingPatchAdded:\n        return tr(\"Added adding patch\");\n\n    case RemovingPatchAdded:\n        return tr(\"Removed adding patch\");\n\n    case AddingPatchRemoved:\n        return tr(\"Added removing patch\");\n\n    case RemovingPatchRemoved:\n        return tr(\"Removed removing patch\");\n    }\n\n    return QString();\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qscilexermatlab.cpp",
    "content": "// This module implements the QsciLexerMatlab class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qscilexermatlab.h\"\n\n#include <qcolor.h>\n#include <qfont.h>\n\n\n// The ctor.\nQsciLexerMatlab::QsciLexerMatlab(QObject *parent)\n    : QsciLexer(parent)\n{\n}\n\n\n// The dtor.\nQsciLexerMatlab::~QsciLexerMatlab()\n{\n}\n\n\n// Returns the language name.\nconst char *QsciLexerMatlab::language() const\n{\n    return \"Matlab\";\n}\n\n\n// Returns the lexer name.\nconst char *QsciLexerMatlab::lexer() const\n{\n    return \"matlab\";\n}\n\n\n// Returns the foreground colour of the text for a style.\nQColor QsciLexerMatlab::defaultColor(int style) const\n{\n    switch (style)\n    {\n    case Default:\n    case Operator:\n        return QColor(0x00,0x00,0x00);\n\n    case Comment:\n        return QColor(0x00,0x7f,0x00);\n\n    case Command:\n        return QColor(0x7f,0x7f,0x00);\n\n    case Number:\n        return QColor(0x00,0x7f,0x7f);\n\n    case Keyword:\n        return QColor(0x00,0x00,0x7f);\n\n    case SingleQuotedString:\n    case DoubleQuotedString:\n        return QColor(0x7f,0x00,0x7f);\n    }\n\n    return QsciLexer::defaultColor(style);\n}\n\n\n// Returns the font of the text for a style.\nQFont QsciLexerMatlab::defaultFont(int style) const\n{\n    QFont f;\n\n    switch (style)\n    {\n    case Comment:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Comic Sans MS\",9);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Comic Sans MS\", 12);\n#else\n        f = QFont(\"Bitstream Vera Serif\",9);\n#endif\n        break;\n\n    case Keyword:\n    case Operator:\n        f = QsciLexer::defaultFont(style);\n        f.setBold(true);\n        break;\n\n    default:\n        f = QsciLexer::defaultFont(style);\n    }\n\n    return f;\n}\n\n\n// Returns the set of keywords.\nconst char *QsciLexerMatlab::keywords(int set) const\n{\n    if (set == 1)\n        return\n            \"break case catch continue else elseif end for function \"\n            \"global if otherwise persistent return switch try while\";\n\n    return 0;\n}\n\n\n// Returns the user name of a style.\nQString QsciLexerMatlab::description(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return tr(\"Default\");\n\n    case Comment:\n        return tr(\"Comment\");\n\n    case Command:\n        return tr(\"Command\");\n\n    case Number:\n        return tr(\"Number\");\n\n    case Keyword:\n        return tr(\"Keyword\");\n\n    case SingleQuotedString:\n        return tr(\"Single-quoted string\");\n\n    case Operator:\n        return tr(\"Operator\");\n\n    case Identifier:\n        return tr(\"Identifier\");\n\n    case DoubleQuotedString:\n        return tr(\"Double-quoted string\");\n    }\n\n    return QString();\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qscilexeroctave.cpp",
    "content": "// This module implements the QsciLexerOctave class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qscilexeroctave.h\"\n\n#include <qcolor.h>\n#include <qfont.h>\n\n\n// The ctor.\nQsciLexerOctave::QsciLexerOctave(QObject *parent)\n    : QsciLexerMatlab(parent)\n{\n}\n\n\n// The dtor.\nQsciLexerOctave::~QsciLexerOctave()\n{\n}\n\n\n// Returns the language name.\nconst char *QsciLexerOctave::language() const\n{\n    return \"Octave\";\n}\n\n\n// Returns the lexer name.\nconst char *QsciLexerOctave::lexer() const\n{\n    return \"octave\";\n}\n\n\n// Returns the set of keywords.\nconst char *QsciLexerOctave::keywords(int set) const\n{\n    if (set == 1)\n        return\n            \"__FILE__ __LINE__ break case catch classdef continue do else \"\n            \"elseif end end_try_catch end_unwind_protect endclassdef \"\n            \"endenumeration endevents endfor endfunction endif endmethods \"\n            \"endparfor endproperties endswitch endwhile enumeration events \"\n            \"for function get global if methods otherwise parfor persistent \"\n            \"properties return set static switch try until unwind_protect \"\n            \"unwind_protect_cleanup while\";\n\n    return 0;\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qscilexerperl.cpp",
    "content": "// This module implements the QsciLexerPerl class.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qscilexerperl.h\"\n\n#include <qcolor.h>\n#include <qfont.h>\n#include <qsettings.h>\n\n\n// The ctor.\nQsciLexerPerl::QsciLexerPerl(QObject *parent)\n    : QsciLexer(parent),\n      fold_atelse(false), fold_comments(false), fold_compact(true),\n      fold_packages(true), fold_pod_blocks(true)\n{\n}\n\n\n// The dtor.\nQsciLexerPerl::~QsciLexerPerl()\n{\n}\n\n\n// Returns the language name.\nconst char *QsciLexerPerl::language() const\n{\n    return \"Perl\";\n}\n\n\n// Returns the lexer name.\nconst char *QsciLexerPerl::lexer() const\n{\n    return \"perl\";\n}\n\n\n// Return the set of character sequences that can separate auto-completion\n// words.\nQStringList QsciLexerPerl::autoCompletionWordSeparators() const\n{\n    QStringList wl;\n\n    wl << \"::\" << \"->\";\n\n    return wl;\n}\n\n\n// Return the list of characters that can start a block.\nconst char *QsciLexerPerl::blockStart(int *style) const\n{\n    if (style)\n        *style = Operator;\n\n    return \"{\";\n}\n\n\n// Return the list of characters that can end a block.\nconst char *QsciLexerPerl::blockEnd(int *style) const\n{\n    if (style)\n        *style = Operator;\n\n    return \"}\";\n}\n\n\n// Return the style used for braces.\nint QsciLexerPerl::braceStyle() const\n{\n    return Operator;\n}\n\n\n// Return the string of characters that comprise a word.\nconst char *QsciLexerPerl::wordCharacters() const\n{\n    return \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$@%&\";\n}\n\n\n// Returns the foreground colour of the text for a style.\nQColor QsciLexerPerl::defaultColor(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return QColor(0x80,0x80,0x80);\n\n    case Error:\n    case Backticks:\n    case QuotedStringQX:\n        return QColor(0xff,0xff,0x00);\n\n    case Comment:\n        return QColor(0x00,0x7f,0x00);\n\n    case POD:\n    case PODVerbatim:\n        return QColor(0x00,0x40,0x00);\n\n    case Number:\n        return QColor(0x00,0x7f,0x7f);\n\n    case Keyword:\n        return QColor(0x00,0x00,0x7f);\n\n    case DoubleQuotedString:\n    case SingleQuotedString:\n    case SingleQuotedHereDocument:\n    case DoubleQuotedHereDocument:\n    case BacktickHereDocument:\n    case QuotedStringQ:\n    case QuotedStringQQ:\n        return QColor(0x7f,0x00,0x7f);\n\n    case Operator:\n    case Identifier:\n    case Scalar:\n    case Array:\n    case Hash:\n    case SymbolTable:\n    case Regex:\n    case Substitution:\n    case HereDocumentDelimiter:\n    case QuotedStringQR:\n    case QuotedStringQW:\n    case SubroutinePrototype:\n    case Translation:\n        return QColor(0x00,0x00,0x00);\n\n    case DataSection:\n        return QColor(0x60,0x00,0x00);\n\n    case FormatIdentifier:\n    case FormatBody:\n        return QColor(0xc0,0x00,0xc0);\n\n    case DoubleQuotedStringVar:\n    case RegexVar:\n    case SubstitutionVar:\n    case BackticksVar:\n    case DoubleQuotedHereDocumentVar:\n    case BacktickHereDocumentVar:\n    case QuotedStringQQVar:\n    case QuotedStringQXVar:\n    case QuotedStringQRVar:\n        return QColor(0xd0, 0x00, 0x00);\n    }\n\n    return QsciLexer::defaultColor(style);\n}\n\n\n// Returns the end-of-line fill for a style.\nbool QsciLexerPerl::defaultEolFill(int style) const\n{\n    switch (style)\n    {\n    case POD:\n    case DataSection:\n    case SingleQuotedHereDocument:\n    case DoubleQuotedHereDocument:\n    case BacktickHereDocument:\n    case PODVerbatim:\n    case FormatBody:\n    case DoubleQuotedHereDocumentVar:\n    case BacktickHereDocumentVar:\n        return true;\n    }\n\n    return QsciLexer::defaultEolFill(style);\n}\n\n\n// Returns the font of the text for a style.\nQFont QsciLexerPerl::defaultFont(int style) const\n{\n    QFont f;\n\n    switch (style)\n    {\n    case Comment:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Comic Sans MS\",9);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Comic Sans MS\", 12);\n#else\n        f = QFont(\"Bitstream Vera Serif\",9);\n#endif\n        break;\n\n    case POD:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Times New Roman\",11);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Times New Roman\", 12);\n#else\n        f = QFont(\"Bitstream Charter\",10);\n#endif\n        break;\n\n    case Keyword:\n    case Operator:\n    case DoubleQuotedHereDocument:\n    case FormatIdentifier:\n    case RegexVar:\n    case SubstitutionVar:\n    case BackticksVar:\n    case DoubleQuotedHereDocumentVar:\n    case BacktickHereDocumentVar:\n    case QuotedStringQXVar:\n    case QuotedStringQRVar:\n        f = QsciLexer::defaultFont(style);\n        f.setBold(true);\n        break;\n\n    case DoubleQuotedString:\n    case SingleQuotedString:\n    case QuotedStringQQ:\n    case PODVerbatim:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Courier New\",10);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Courier\", 12);\n#else\n        f = QFont(\"Bitstream Vera Sans Mono\",9);\n#endif\n        break;\n\n    case BacktickHereDocument:\n    case SubroutinePrototype:\n        f = QsciLexer::defaultFont(style);\n        f.setItalic(true);\n        break;\n\n    case DoubleQuotedStringVar:\n    case QuotedStringQQVar:\n#if defined(Q_OS_WIN)\n        f = QFont(\"Courier New\",10);\n#elif defined(Q_OS_MAC)\n        f = QFont(\"Courier\", 12);\n#else\n        f = QFont(\"Bitstream Vera Sans Mono\",9);\n#endif\n        f.setBold(true);\n        break;\n\n    default:\n        f = QsciLexer::defaultFont(style);\n    }\n\n    return f;\n}\n\n\n// Returns the set of keywords.\nconst char *QsciLexerPerl::keywords(int set) const\n{\n    if (set == 1)\n        return\n            \"NULL __FILE__ __LINE__ __PACKAGE__ __DATA__ __END__ \"\n            \"AUTOLOAD BEGIN CORE DESTROY END EQ GE GT INIT LE LT \"\n            \"NE CHECK abs accept alarm and atan2 bind binmode \"\n            \"bless caller chdir chmod chomp chop chown chr chroot \"\n            \"close closedir cmp connect continue cos crypt \"\n            \"dbmclose dbmopen defined delete die do dump each \"\n            \"else elsif endgrent endhostent endnetent endprotoent \"\n            \"endpwent endservent eof eq eval exec exists exit exp \"\n            \"fcntl fileno flock for foreach fork format formline \"\n            \"ge getc getgrent getgrgid getgrnam gethostbyaddr \"\n            \"gethostbyname gethostent getlogin getnetbyaddr \"\n            \"getnetbyname getnetent getpeername getpgrp getppid \"\n            \"getpriority getprotobyname getprotobynumber \"\n            \"getprotoent getpwent getpwnam getpwuid getservbyname \"\n            \"getservbyport getservent getsockname getsockopt glob \"\n            \"gmtime goto grep gt hex if index int ioctl join keys \"\n            \"kill last lc lcfirst le length link listen local \"\n            \"localtime lock log lstat lt m map mkdir msgctl \"\n            \"msgget msgrcv msgsnd my ne next no not oct open \"\n            \"opendir or ord our pack package pipe pop pos print \"\n            \"printf prototype push q qq qr quotemeta qu qw qx \"\n            \"rand read readdir readline readlink readpipe recv \"\n            \"redo ref rename require reset return reverse \"\n            \"rewinddir rindex rmdir s scalar seek seekdir select \"\n            \"semctl semget semop send setgrent sethostent \"\n            \"setnetent setpgrp setpriority setprotoent setpwent \"\n            \"setservent setsockopt shift shmctl shmget shmread \"\n            \"shmwrite shutdown sin sleep socket socketpair sort \"\n            \"splice split sprintf sqrt srand stat study sub \"\n            \"substr symlink syscall sysopen sysread sysseek \"\n            \"system syswrite tell telldir tie tied time times tr \"\n            \"truncate uc ucfirst umask undef unless unlink unpack \"\n            \"unshift untie until use utime values vec wait \"\n            \"waitpid wantarray warn while write x xor y\";\n\n    return 0;\n}\n\n\n// Returns the user name of a style.\nQString QsciLexerPerl::description(int style) const\n{\n    switch (style)\n    {\n    case Default:\n        return tr(\"Default\");\n\n    case Error:\n        return tr(\"Error\");\n\n    case Comment:\n        return tr(\"Comment\");\n\n    case POD:\n        return tr(\"POD\");\n\n    case Number:\n        return tr(\"Number\");\n\n    case Keyword:\n        return tr(\"Keyword\");\n\n    case DoubleQuotedString:\n        return tr(\"Double-quoted string\");\n\n    case SingleQuotedString:\n        return tr(\"Single-quoted string\");\n\n    case Operator:\n        return tr(\"Operator\");\n\n    case Identifier:\n        return tr(\"Identifier\");\n\n    case Scalar:\n        return tr(\"Scalar\");\n\n    case Array:\n        return tr(\"Array\");\n\n    case Hash:\n        return tr(\"Hash\");\n\n    case SymbolTable:\n        return tr(\"Symbol table\");\n\n    case Regex:\n        return tr(\"Regular expression\");\n\n    case Substitution:\n        return tr(\"Substitution\");\n\n    case Backticks:\n        return tr(\"Backticks\");\n\n    case DataSection:\n        return tr(\"Data section\");\n\n    case HereDocumentDelimiter:\n        return tr(\"Here document delimiter\");\n\n    case SingleQuotedHereDocument:\n        return tr(\"Single-quoted here document\");\n\n    case DoubleQuotedHereDocument:\n        return tr(\"Double-quoted here document\");\n\n    case BacktickHereDocument:\n        return tr(\"Backtick here document\");\n\n    case QuotedStringQ:\n        return tr(\"Quoted string (q)\");\n\n    case QuotedStringQQ:\n        return tr(\"Quoted string (qq)\");\n\n    case QuotedStringQX:\n        return tr(\"Quoted string (qx)\");\n\n    case QuotedStringQR:\n        return tr(\"Quoted string (qr)\");\n\n    case QuotedStringQW:\n        return tr(\"Quoted string (qw)\");\n\n    case PODVerbatim:\n        return tr(\"POD verbatim\");\n\n    case SubroutinePrototype:\n        return tr(\"Subroutine prototype\");\n\n    case FormatIdentifier:\n        return tr(\"Format identifier\");\n\n    case FormatBody:\n        return tr(\"Format body\");\n\n    case DoubleQuotedStringVar:\n        return tr(\"Double-quoted string (interpolated variable)\");\n\n    case Translation:\n        return tr(\"Translation\");\n\n    case RegexVar:\n        return tr(\"Regular expression (interpolated variable)\");\n\n    case SubstitutionVar:\n        return tr(\"Substitution (interpolated variable)\");\n\n    case BackticksVar:\n        return tr(\"Backticks (interpolated variable)\");\n\n    case DoubleQuotedHereDocumentVar:\n        return tr(\"Double-quoted here document (interpolated variable)\");\n\n    case BacktickHereDocumentVar:\n        return tr(\"Backtick here document (interpolated variable)\");\n\n    case QuotedStringQQVar:\n        return tr(\"Quoted string (qq, interpolated variable)\");\n\n    case QuotedStringQXVar:\n        return tr(\"Quoted string (qx, interpolated variable)\");\n\n    case QuotedStringQRVar:\n        return tr(\"Quoted string (qr, interpolated variable)\");\n    }\n\n    return QString();\n}\n\n\n// Returns the background colour of the text for a style.\nQColor QsciLexerPerl::defaultPaper(int style) const\n{\n    switch (style)\n    {\n    case Error:\n        return QColor(0xff,0x00,0x00);\n\n    case POD:\n        return QColor(0xe0,0xff,0xe0);\n\n    case Scalar:\n        return QColor(0xff,0xe0,0xe0);\n\n    case Array:\n        return QColor(0xff,0xff,0xe0);\n\n    case Hash:\n        return QColor(0xff,0xe0,0xff);\n\n    case SymbolTable:\n        return QColor(0xe0,0xe0,0xe0);\n\n    case Regex:\n        return QColor(0xa0,0xff,0xa0);\n\n    case Substitution:\n    case Translation:\n        return QColor(0xf0,0xe0,0x80);\n\n    case Backticks:\n    case BackticksVar:\n    case QuotedStringQXVar:\n        return QColor(0xa0,0x80,0x80);\n\n    case DataSection:\n        return QColor(0xff,0xf0,0xd8);\n\n    case HereDocumentDelimiter:\n    case SingleQuotedHereDocument:\n    case DoubleQuotedHereDocument:\n    case BacktickHereDocument:\n    case DoubleQuotedHereDocumentVar:\n    case BacktickHereDocumentVar:\n        return QColor(0xdd,0xd0,0xdd);\n\n    case PODVerbatim:\n        return QColor(0xc0,0xff,0xc0);\n\n    case FormatBody:\n        return QColor(0xff,0xf0,0xff);\n    }\n\n    return QsciLexer::defaultPaper(style);\n}\n\n\n// Refresh all properties.\nvoid QsciLexerPerl::refreshProperties()\n{\n    setAtElseProp();\n    setCommentProp();\n    setCompactProp();\n    setPackagesProp();\n    setPODBlocksProp();\n}\n\n\n// Read properties from the settings.\nbool QsciLexerPerl::readProperties(QSettings &qs,const QString &prefix)\n{\n    int rc = true;\n\n    fold_atelse = qs.value(prefix + \"foldatelse\", false).toBool();\n    fold_comments = qs.value(prefix + \"foldcomments\", false).toBool();\n    fold_compact = qs.value(prefix + \"foldcompact\", true).toBool();\n    fold_packages = qs.value(prefix + \"foldpackages\", true).toBool();\n    fold_pod_blocks = qs.value(prefix + \"foldpodblocks\", true).toBool();\n\n    return rc;\n}\n\n\n// Write properties to the settings.\nbool QsciLexerPerl::writeProperties(QSettings &qs,const QString &prefix) const\n{\n    int rc = true;\n\n    qs.setValue(prefix + \"foldatelse\", fold_atelse);\n    qs.setValue(prefix + \"foldcomments\", fold_comments);\n    qs.setValue(prefix + \"foldcompact\", fold_compact);\n    qs.setValue(prefix + \"foldpackages\", fold_packages);\n    qs.setValue(prefix + \"foldpodblocks\", fold_pod_blocks);\n\n    return rc;\n}\n\n\n// Return true if comments can be folded.\nbool QsciLexerPerl::foldComments() const\n{\n    return fold_comments;\n}\n\n\n// Set if comments can be folded.\nvoid QsciLexerPerl::setFoldComments(bool fold)\n{\n    fold_comments = fold;\n\n    setCommentProp();\n}\n\n\n// Set the \"fold.comment\" property.\nvoid QsciLexerPerl::setCommentProp()\n{\n    emit propertyChanged(\"fold.comment\",(fold_comments ? \"1\" : \"0\"));\n}\n\n\n// Return true if folds are compact.\nbool QsciLexerPerl::foldCompact() const\n{\n    return fold_compact;\n}\n\n\n// Set if folds are compact\nvoid QsciLexerPerl::setFoldCompact(bool fold)\n{\n    fold_compact = fold;\n\n    setCompactProp();\n}\n\n\n// Set the \"fold.compact\" property.\nvoid QsciLexerPerl::setCompactProp()\n{\n    emit propertyChanged(\"fold.compact\",(fold_compact ? \"1\" : \"0\"));\n}\n\n\n// Return true if packages can be folded.\nbool QsciLexerPerl::foldPackages() const\n{\n    return fold_packages;\n}\n\n\n// Set if packages can be folded.\nvoid QsciLexerPerl::setFoldPackages(bool fold)\n{\n    fold_packages = fold;\n\n    setPackagesProp();\n}\n\n\n// Set the \"fold.perl.package\" property.\nvoid QsciLexerPerl::setPackagesProp()\n{\n    emit propertyChanged(\"fold.perl.package\",(fold_packages ? \"1\" : \"0\"));\n}\n\n\n// Return true if POD blocks can be folded.\nbool QsciLexerPerl::foldPODBlocks() const\n{\n    return fold_pod_blocks;\n}\n\n\n// Set if POD blocks can be folded.\nvoid QsciLexerPerl::setFoldPODBlocks(bool fold)\n{\n    fold_pod_blocks = fold;\n\n    setPODBlocksProp();\n}\n\n\n// Set the \"fold.perl.pod\" property.\nvoid QsciLexerPerl::setPODBlocksProp()\n{\n    emit propertyChanged(\"fold.perl.pod\",(fold_pod_blocks ? \"1\" : \"0\"));\n}\n\n\n// Set if else can be folded.\nvoid QsciLexerPerl::setFoldAtElse(bool fold)\n{\n    fold_atelse = fold;\n\n    setAtElseProp();\n}\n\n\n// Set the \"fold.perl.at.else\" property.\nvoid QsciLexerPerl::setAtElseProp()\n{\n    emit propertyChanged(\"fold.perl.at.else\",(fold_atelse ? \"1\" : \"0\"));\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qsciscintilla.cpp",
    "content": "// This module implements the \"official\" high-level API of the Qt port of\n// Scintilla.  It is modelled on QTextEdit - a method of the same name should\n// behave in the same way.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qsciscintilla.h\"\n\n#include <string.h>\n\n#include <QAction>\n#include <QApplication>\n#include <QColor>\n#include <QEvent>\n#include <QImage>\n#include <QIODevice>\n#include <QKeyEvent>\n#include <QKeySequence>\n#include <QMenu>\n#include <QPoint>\n\n#include \"Qsci/qsciabstractapis.h\"\n#include \"Qsci/qscicommandset.h\"\n#include \"Qsci/qscilexer.h\"\n#include \"Qsci/qscistyle.h\"\n#include \"Qsci/qscistyledtext.h\"\n\n\n// Make sure these match the values in Scintilla.h.  We don't #include that\n// file because it just causes more clashes.\n#define KEYWORDSET_MAX  8\n#define MARKER_MAX      31\n\n// The list separators for auto-completion and user lists.\nconst char acSeparator = '\\x03';\nconst char userSeparator = '\\x04';\n\n// The default fold margin width.\nstatic const int defaultFoldMarginWidth = 14;\n\n// The default set of characters that make up a word.\nstatic const char *defaultWordChars = \"_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\n\n// Forward declarations.\nstatic QColor asQColor(long sci_colour);\n\n\n// The ctor.\nQsciScintilla::QsciScintilla(QWidget *parent)\n    : QsciScintillaBase(parent),\n      allocatedMarkers(0), allocatedIndicators(7), oldPos(-1), selText(false),\n      fold(NoFoldStyle), foldmargin(2), autoInd(false),\n      braceMode(NoBraceMatch), acSource(AcsNone), acThresh(-1),\n      wchars(defaultWordChars), call_tips_position(CallTipsBelowText),\n      call_tips_style(CallTipsNoContext), maxCallTips(-1),\n      use_single(AcusNever), explicit_fillups(\"\"), fillups_enabled(false)\n{\n    connect(this,SIGNAL(SCN_MODIFYATTEMPTRO()),\n             SIGNAL(modificationAttempted()));\n\n    connect(this,SIGNAL(SCN_MODIFIED(int,int,const char *,int,int,int,int,int,int,int)),\n             SLOT(handleModified(int,int,const char *,int,int,int,int,int,int,int)));\n    connect(this,SIGNAL(SCN_CALLTIPCLICK(int)),\n             SLOT(handleCallTipClick(int)));\n    connect(this,SIGNAL(SCN_CHARADDED(int)),\n             SLOT(handleCharAdded(int)));\n    connect(this,SIGNAL(SCN_INDICATORCLICK(int,int)),\n             SLOT(handleIndicatorClick(int,int)));\n    connect(this,SIGNAL(SCN_INDICATORRELEASE(int,int)),\n             SLOT(handleIndicatorRelease(int,int)));\n    connect(this,SIGNAL(SCN_MARGINCLICK(int,int,int)),\n             SLOT(handleMarginClick(int,int,int)));\n    connect(this,SIGNAL(SCN_MARGINRIGHTCLICK(int,int,int)),\n             SLOT(handleMarginRightClick(int,int,int)));\n    connect(this,SIGNAL(SCN_SAVEPOINTREACHED()),\n             SLOT(handleSavePointReached()));\n    connect(this,SIGNAL(SCN_SAVEPOINTLEFT()),\n             SLOT(handleSavePointLeft()));\n    connect(this,SIGNAL(SCN_UPDATEUI(int)),\n             SLOT(handleUpdateUI(int)));\n    connect(this,SIGNAL(QSCN_SELCHANGED(bool)),\n             SLOT(handleSelectionChanged(bool)));\n    connect(this,SIGNAL(SCN_AUTOCSELECTION(const char *,int)),\n             SLOT(handleAutoCompletionSelection()));\n    connect(this,SIGNAL(SCN_USERLISTSELECTION(const char *,int)),\n             SLOT(handleUserListSelection(const char *,int)));\n\n    // Set the default font.\n    setFont(QApplication::font());\n\n    // Set the default fore and background colours.\n    QPalette pal = QApplication::palette();\n    setColor(pal.text().color());\n    setPaper(pal.base().color());\n    setSelectionForegroundColor(pal.highlightedText().color());\n    setSelectionBackgroundColor(pal.highlight().color());\n\n#if defined(Q_OS_WIN)\n    setEolMode(EolWindows);\n#else\n    // Note that EolMac is pre-OS/X.\n    setEolMode(EolUnix);\n#endif\n\n    // Capturing the mouse seems to cause problems on multi-head systems. Qt\n    // should do the right thing anyway.\n    SendScintilla(SCI_SETMOUSEDOWNCAPTURES, 0UL);\n\n    setMatchedBraceForegroundColor(Qt::blue);\n    setUnmatchedBraceForegroundColor(Qt::red);\n\n    setAnnotationDisplay(AnnotationStandard);\n    setLexer();\n\n    // Set the visible policy.  These are the same as SciTE's defaults\n    // which, presumably, are sensible.\n    SendScintilla(SCI_SETVISIBLEPOLICY, VISIBLE_STRICT | VISIBLE_SLOP, 4);\n\n    // The default behaviour is unexpected.\n    SendScintilla(SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR,\n            SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE);\n\n    // Create the standard command set.\n    stdCmds = new QsciCommandSet(this);\n\n    doc.display(this,0);\n}\n\n\n// The dtor.\nQsciScintilla::~QsciScintilla()\n{\n    // Detach any current lexer.\n    detachLexer();\n\n    doc.undisplay(this);\n    delete stdCmds;\n}\n\n\n// Return the current text colour.\nQColor QsciScintilla::color() const\n{\n    return nl_text_colour;\n}\n\n\n// Set the text colour.\nvoid QsciScintilla::setColor(const QColor &c)\n{\n    if (lex.isNull())\n    {\n        // Assume style 0 applies to everything so that we don't need to use\n        // SCI_STYLECLEARALL which clears everything.\n        SendScintilla(SCI_STYLESETFORE, 0, c);\n        nl_text_colour = c;\n    }\n}\n\n\n// Return the overwrite mode.\nbool QsciScintilla::overwriteMode() const\n{\n    return SendScintilla(SCI_GETOVERTYPE);\n}\n\n\n// Set the overwrite mode.\nvoid QsciScintilla::setOverwriteMode(bool overwrite)\n{\n    SendScintilla(SCI_SETOVERTYPE, overwrite);\n}\n\n\n// Return the current paper colour.\nQColor QsciScintilla::paper() const\n{\n    return nl_paper_colour;\n}\n\n\n// Set the paper colour.\nvoid QsciScintilla::setPaper(const QColor &c)\n{\n    if (lex.isNull())\n    {\n        // Assume style 0 applies to everything so that we don't need to use\n        // SCI_STYLECLEARALL which clears everything.  We still have to set the\n        // default style as well for the background without any text.\n        SendScintilla(SCI_STYLESETBACK, 0, c);\n        SendScintilla(SCI_STYLESETBACK, STYLE_DEFAULT, c);\n        nl_paper_colour = c;\n    }\n}\n\n\n// Set the default font.\nvoid QsciScintilla::setFont(const QFont &f)\n{\n    if (lex.isNull())\n    {\n        // Assume style 0 applies to everything so that we don't need to use\n        // SCI_STYLECLEARALL which clears everything.\n        setStylesFont(f, 0);\n        QWidget::setFont(f);\n    }\n}\n\n\n// Enable/disable auto-indent.\nvoid QsciScintilla::setAutoIndent(bool autoindent)\n{\n    autoInd = autoindent;\n}\n\n\n// Set the brace matching mode.\nvoid QsciScintilla::setBraceMatching(BraceMatch bm)\n{\n    braceMode = bm;\n}\n\n\n// Handle the addition of a character.\nvoid QsciScintilla::handleCharAdded(int ch)\n{\n    // Ignore if there is a selection.\n    long pos = SendScintilla(SCI_GETSELECTIONSTART);\n\n    if (pos != SendScintilla(SCI_GETSELECTIONEND) || pos == 0)\n        return;\n\n    // If auto-completion is already active then see if this character is a\n    // start character.  If it is then create a new list which will be a subset\n    // of the current one.  The case where it isn't a start character seems to\n    // be handled correctly elsewhere.\n    if (isListActive() && isStartChar(ch))\n    {\n        cancelList();\n        startAutoCompletion(acSource, false, use_single == AcusAlways);\n\n        return;\n    }\n\n    // Handle call tips.\n    if (call_tips_style != CallTipsNone && !lex.isNull() && strchr(\"(),\", ch) != NULL)\n        callTip();\n\n    // Handle auto-indentation.\n    if (autoInd)\n    {\n        if (lex.isNull() || (lex->autoIndentStyle() & AiMaintain))\n            maintainIndentation(ch, pos);\n        else\n            autoIndentation(ch, pos);\n    }\n\n    // See if we might want to start auto-completion.\n    if (!isCallTipActive() && acSource != AcsNone)\n    {\n        if (isStartChar(ch))\n            startAutoCompletion(acSource, false, use_single == AcusAlways);\n        else if (acThresh >= 1 && isWordCharacter(ch))\n            startAutoCompletion(acSource, true, use_single == AcusAlways);\n    }\n}\n\n\n// See if a call tip is active.\nbool QsciScintilla::isCallTipActive() const\n{\n    return SendScintilla(SCI_CALLTIPACTIVE);\n}\n\n\n// Handle a possible change to any current call tip.\nvoid QsciScintilla::callTip()\n{\n    QsciAbstractAPIs *apis = lex->apis();\n\n    if (!apis)\n        return;\n\n    int pos, commas = 0;\n    bool found = false;\n    char ch;\n\n    pos = SendScintilla(SCI_GETCURRENTPOS);\n\n    // Move backwards through the line looking for the start of the current\n    // call tip and working out which argument it is.\n    while ((ch = getCharacter(pos)) != '\\0')\n    {\n        if (ch == ',')\n            ++commas;\n        else if (ch == ')')\n        {\n            int depth = 1;\n\n            // Ignore everything back to the start of the corresponding\n            // parenthesis.\n            while ((ch = getCharacter(pos)) != '\\0')\n            {\n                if (ch == ')')\n                    ++depth;\n                else if (ch == '(' && --depth == 0)\n                    break;\n            }\n        }\n        else if (ch == '(')\n        {\n            found = true;\n            break;\n        }\n    }\n\n    // Cancel any existing call tip.\n    SendScintilla(SCI_CALLTIPCANCEL);\n\n    // Done if there is no new call tip to set.\n    if (!found)\n        return;\n\n    QStringList context = apiContext(pos, pos, ctPos);\n\n    if (context.isEmpty())\n        return;\n\n    // The last word is complete, not partial.\n    context << QString();\n\n    ct_cursor = 0;\n    ct_shifts.clear();\n    ct_entries = apis->callTips(context, commas, call_tips_style, ct_shifts);\n\n    int nr_entries = ct_entries.count();\n\n    if (nr_entries == 0)\n        return;\n\n    if (maxCallTips > 0 && maxCallTips < nr_entries)\n    {\n        ct_entries = ct_entries.mid(0, maxCallTips);\n        nr_entries = maxCallTips;\n    }\n\n    int shift;\n    QString ct;\n\n    int nr_shifts = ct_shifts.count();\n\n    if (maxCallTips < 0 && nr_entries > 1)\n    {\n        shift = (nr_shifts > 0 ? ct_shifts.first() : 0);\n        ct = ct_entries[0];\n        ct.prepend('\\002');\n    }\n    else\n    {\n        if (nr_shifts > nr_entries)\n            nr_shifts = nr_entries;\n\n        // Find the biggest shift.\n        shift = 0;\n\n        for (int i = 0; i < nr_shifts; ++i)\n        {\n            int sh = ct_shifts[i];\n\n            if (shift < sh)\n                shift = sh;\n        }\n\n        ct = ct_entries.join(\"\\n\");\n    }\n\n    QByteArray ct_bytes = textAsBytes(ct);\n    const char *cts = ct_bytes.constData();\n\n    SendScintilla(SCI_CALLTIPSHOW, adjustedCallTipPosition(shift), cts);\n\n    // Done if there is more than one call tip.\n    if (nr_entries > 1)\n        return;\n\n    // Highlight the current argument.\n    const char *astart;\n\n    if (commas == 0)\n        astart = strchr(cts, '(');\n    else\n        for (astart = strchr(cts, ','); astart && --commas > 0; astart = strchr(astart + 1, ','))\n            ;\n\n    if (!astart || !*++astart)\n        return;\n\n    // The end is at the next comma or unmatched closing parenthesis.\n    const char *aend;\n    int depth = 0;\n\n    for (aend = astart; *aend; ++aend)\n    {\n        char ch = *aend;\n\n        if (ch == ',' && depth == 0)\n            break;\n        else if (ch == '(')\n            ++depth;\n        else if (ch == ')')\n        {\n            if (depth == 0)\n                break;\n\n            --depth;\n        }\n    }\n\n    if (astart != aend)\n        SendScintilla(SCI_CALLTIPSETHLT, astart - cts, aend - cts);\n}\n\n\n// Handle a call tip click.\nvoid QsciScintilla::handleCallTipClick(int dir)\n{\n    int nr_entries = ct_entries.count();\n\n    // Move the cursor while bounds checking.\n    if (dir == 1)\n    {\n        if (ct_cursor - 1 < 0)\n            return;\n\n        --ct_cursor;\n    }\n    else if (dir == 2)\n    {\n        if (ct_cursor + 1 >= nr_entries)\n            return;\n\n        ++ct_cursor;\n    }\n    else\n        return;\n\n    int shift = (ct_shifts.count() > ct_cursor ? ct_shifts[ct_cursor] : 0);\n    QString ct = ct_entries[ct_cursor];\n\n    // Add the arrows.\n    if (ct_cursor < nr_entries - 1)\n        ct.prepend('\\002');\n\n    if (ct_cursor > 0)\n        ct.prepend('\\001');\n\n    SendScintilla(SCI_CALLTIPSHOW, adjustedCallTipPosition(shift),\n            textAsBytes(ct).constData());\n}\n\n\n// Shift the position of the call tip (to take any context into account) but\n// don't go before the start of the line.\nint QsciScintilla::adjustedCallTipPosition(int ctshift) const\n{\n    int ct = ctPos;\n\n    if (ctshift)\n    {\n        int ctmin = SendScintilla(SCI_POSITIONFROMLINE, SendScintilla(SCI_LINEFROMPOSITION, ct));\n\n        if (ct - ctshift < ctmin)\n            ct = ctmin;\n    }\n\n    return ct;\n}\n\n\n// Return the list of words that make up the context preceding the given\n// position.  The list will only have more than one element if there is a lexer\n// set and it defines start strings.  If so, then the last element might be\n// empty if a start string has just been typed.  On return pos is at the start\n// of the context.\nQStringList QsciScintilla::apiContext(int pos, int &context_start,\n        int &last_word_start)\n{\n    enum {\n        Either,\n        Separator,\n        Word\n    };\n\n    QStringList words;\n    int good_pos = pos, expecting = Either;\n\n    last_word_start = -1;\n\n    while (pos > 0)\n    {\n        if (getSeparator(pos))\n        {\n            if (expecting == Either)\n                words.prepend(QString());\n            else if (expecting == Word)\n                break;\n\n            good_pos = pos;\n            expecting = Word;\n        }\n        else\n        {\n            QString word = getWord(pos);\n\n            if (word.isEmpty() || expecting == Separator)\n                break;\n\n            words.prepend(word);\n            good_pos = pos;\n            expecting = Separator;\n\n            // Return the position of the start of the last word if required.\n            if (last_word_start < 0)\n                last_word_start = pos;\n        }\n\n        // Strip any preceding spaces (mainly around operators).\n        char ch;\n\n        while ((ch = getCharacter(pos)) != '\\0')\n        {\n            // This is the same definition of space that Scintilla uses.\n            if (ch != ' ' && (ch < 0x09 || ch > 0x0d))\n            {\n                ++pos;\n                break;\n            }\n        }\n    }\n\n    // A valid sequence always starts with a word and so should be expecting a\n    // separator.\n    if (expecting != Separator)\n        words.clear();\n\n    context_start = good_pos;\n\n    return words;\n}\n\n\n// Try and get a lexer's word separator from the text before the current\n// position.  Return true if one was found and adjust the position accordingly.\nbool QsciScintilla::getSeparator(int &pos) const\n{\n    int opos = pos;\n\n    // Go through each separator.\n    for (int i = 0; i < wseps.count(); ++i)\n    {\n        const QString &ws = wseps[i];\n\n        // Work backwards.\n        uint l;\n\n        for (l = ws.length(); l; --l)\n        {\n            char ch = getCharacter(pos);\n\n            if (ch == '\\0' || ws.at(l - 1) != ch)\n                break;\n        }\n\n        if (!l)\n            return true;\n\n        // Reset for the next separator.\n        pos = opos;\n    }\n\n    return false;\n}\n\n\n// Try and get a word from the text before the current position.  Return the\n// word if one was found and adjust the position accordingly.\nQString QsciScintilla::getWord(int &pos) const\n{\n    QString word;\n    bool numeric = true;\n    char ch;\n\n    while ((ch = getCharacter(pos)) != '\\0')\n    {\n        if (!isWordCharacter(ch))\n        {\n            ++pos;\n            break;\n        }\n\n        if (ch < '0' || ch > '9')\n            numeric = false;\n\n        word.prepend(ch);\n    }\n\n    // We don't auto-complete numbers.\n    if (numeric)\n        word.truncate(0);\n\n    return word;\n}\n\n\n// Get the \"next\" character (ie. the one before the current position) in the\n// current line.  The character will be '\\0' if there are no more.\nchar QsciScintilla::getCharacter(int &pos) const\n{\n    if (pos <= 0)\n        return '\\0';\n\n    char ch = SendScintilla(SCI_GETCHARAT, --pos);\n\n    // Don't go past the end of the previous line.\n    if (ch == '\\n' || ch == '\\r')\n    {\n        ++pos;\n        return '\\0';\n    }\n\n    return ch;\n}\n\n\n// See if a character is an auto-completion start character, ie. the last\n// character of a word separator.\nbool QsciScintilla::isStartChar(char ch) const\n{\n    QString s = QChar(ch);\n\n    for (int i = 0; i < wseps.count(); ++i)\n        if (wseps[i].endsWith(s))\n            return true;\n\n    return false;\n}\n\n\n// Possibly start auto-completion.\nvoid QsciScintilla::startAutoCompletion(AutoCompletionSource acs,\n        bool checkThresh, bool choose_single)\n{\n    int start, ignore;\n    QStringList context = apiContext(SendScintilla(SCI_GETCURRENTPOS), start,\n            ignore);\n\n    if (context.isEmpty())\n        return;\n\n    // Get the last word's raw data and length.\n    QByteArray s = textAsBytes(context.last());\n    const char *last_data = s.constData();\n    int last_len = s.length();\n\n    if (checkThresh && last_len < acThresh)\n        return;\n\n    // Generate the string representing the valid words to select from.\n    QStringList wlist;\n\n    if ((acs == AcsAll || acs == AcsAPIs) && !lex.isNull())\n    {\n        QsciAbstractAPIs *apis = lex->apis();\n\n        if (apis)\n            apis->updateAutoCompletionList(context, wlist);\n    }\n\n    if (acs == AcsAll || acs == AcsDocument)\n    {\n        int sflags = SCFIND_WORDSTART;\n\n        if (!SendScintilla(SCI_AUTOCGETIGNORECASE))\n            sflags |= SCFIND_MATCHCASE;\n\n        SendScintilla(SCI_SETSEARCHFLAGS, sflags);\n\n        int pos = 0;\n        int dlen = SendScintilla(SCI_GETLENGTH);\n        int caret = SendScintilla(SCI_GETCURRENTPOS);\n        int clen = caret - start;\n        char *orig_context = new char[clen + 1];\n\n        SendScintilla(SCI_GETTEXTRANGE, start, caret, orig_context);\n\n        for (;;)\n        {\n            int fstart;\n\n            SendScintilla(SCI_SETTARGETSTART, pos);\n            SendScintilla(SCI_SETTARGETEND, dlen);\n\n            if ((fstart = SendScintilla(SCI_SEARCHINTARGET, clen, orig_context)) < 0)\n                break;\n\n            // Move past the root part.\n            pos = fstart + clen;\n\n            // Skip if this is the context we are auto-completing.\n            if (pos == caret)\n                continue;\n\n            // Get the rest of this word.\n            QString w = last_data;\n\n            while (pos < dlen)\n            {\n                char ch = SendScintilla(SCI_GETCHARAT, pos);\n\n                if (!isWordCharacter(ch))\n                    break;\n\n                w += ch;\n                ++pos;\n            }\n\n            // Add the word if it isn't already there.\n            if (!w.isEmpty())\n            {\n                bool keep;\n\n                // If there are APIs then check if the word is already present\n                // as an API word (i.e. with a trailing space).\n                if (acs == AcsAll)\n                {\n                    QString api_w = w;\n                    api_w.append(' ');\n\n                    keep = !wlist.contains(api_w);\n                }\n                else\n                {\n                    keep = true;\n                }\n\n                if (keep && !wlist.contains(w))\n                    wlist.append(w);\n            }\n        }\n\n        delete []orig_context;\n    }\n\n    if (wlist.isEmpty())\n        return;\n\n    wlist.sort();\n\n    SendScintilla(SCI_AUTOCSETCHOOSESINGLE, choose_single);\n    SendScintilla(SCI_AUTOCSETSEPARATOR, acSeparator);\n\n    SendScintilla(SCI_AUTOCSHOW, last_len,\n            textAsBytes(wlist.join(QChar(acSeparator))).constData());\n}\n\n\n// Maintain the indentation of the previous line.\nvoid QsciScintilla::maintainIndentation(char ch, long pos)\n{\n    if (ch != '\\r' && ch != '\\n')\n        return;\n\n    int curr_line = SendScintilla(SCI_LINEFROMPOSITION, pos);\n\n    // Get the indentation of the preceding non-zero length line.\n    int ind = 0;\n\n    for (int line = curr_line - 1; line >= 0; --line)\n    {\n        if (SendScintilla(SCI_GETLINEENDPOSITION, line) >\n            SendScintilla(SCI_POSITIONFROMLINE, line))\n        {\n            ind = indentation(line);\n            break;\n        }\n    }\n\n    if (ind > 0)\n        autoIndentLine(pos, curr_line, ind);\n}\n\n\n// Implement auto-indentation.\nvoid QsciScintilla::autoIndentation(char ch, long pos)\n{\n    int curr_line = SendScintilla(SCI_LINEFROMPOSITION, pos);\n    int ind_width = indentWidth();\n    long curr_line_start = SendScintilla(SCI_POSITIONFROMLINE, curr_line);\n\n    const char *block_start = lex->blockStart();\n    bool start_single = (block_start && qstrlen(block_start) == 1);\n\n    const char *block_end = lex->blockEnd();\n    bool end_single = (block_end && qstrlen(block_end) == 1);\n\n    if (end_single && block_end[0] == ch)\n    {\n        if (!(lex->autoIndentStyle() & AiClosing) && rangeIsWhitespace(curr_line_start, pos - 1))\n            autoIndentLine(pos, curr_line, blockIndent(curr_line - 1) - ind_width);\n    }\n    else if (start_single && block_start[0] == ch)\n    {\n        // De-indent if we have already indented because the previous line was\n        // a start of block keyword.\n        if (!(lex->autoIndentStyle() & AiOpening) && curr_line > 0 && getIndentState(curr_line - 1) == isKeywordStart && rangeIsWhitespace(curr_line_start, pos - 1))\n            autoIndentLine(pos, curr_line, blockIndent(curr_line - 1) - ind_width);\n    }\n    else if (ch == '\\r' || ch == '\\n')\n    {\n        // Don't auto-indent the line (ie. preserve its existing indentation)\n        // if we have inserted a new line above by pressing return at the start\n        // of this line - in other words, if the previous line is empty.\n        long prev_line_length = SendScintilla(SCI_GETLINEENDPOSITION, curr_line - 1) - SendScintilla(SCI_POSITIONFROMLINE, curr_line - 1);\n\n        if (prev_line_length != 0)\n            autoIndentLine(pos, curr_line, blockIndent(curr_line - 1));\n    }\n}\n\n\n// Set the indentation for a line.\nvoid QsciScintilla::autoIndentLine(long pos, int line, int indent)\n{\n    if (indent < 0)\n        return;\n\n    long pos_before = SendScintilla(SCI_GETLINEINDENTPOSITION, line);\n    SendScintilla(SCI_SETLINEINDENTATION, line, indent);\n    long pos_after = SendScintilla(SCI_GETLINEINDENTPOSITION, line);\n    long new_pos = -1;\n\n    if (pos_after > pos_before)\n    {\n        new_pos = pos + (pos_after - pos_before);\n    }\n    else if (pos_after < pos_before && pos >= pos_after)\n    {\n        if (pos >= pos_before)\n            new_pos = pos + (pos_after - pos_before);\n        else\n            new_pos = pos_after;\n    }\n\n    if (new_pos >= 0)\n        SendScintilla(SCI_SETSEL, new_pos, new_pos);\n}\n\n\n// Return the indentation of the block defined by the given line (or something\n// significant before).\nint QsciScintilla::blockIndent(int line)\n{\n    if (line < 0)\n        return 0;\n\n    // Handle the trvial case.\n    if (!lex->blockStartKeyword() && !lex->blockStart() && !lex->blockEnd())\n        return indentation(line);\n\n    int line_limit = line - lex->blockLookback();\n\n    if (line_limit < 0)\n        line_limit = 0;\n\n    for (int l = line; l >= line_limit; --l)\n    {\n        IndentState istate = getIndentState(l);\n\n        if (istate != isNone)\n        {\n            int ind_width = indentWidth();\n            int ind = indentation(l);\n\n            if (istate == isBlockStart)\n            {\n                if (!(lex -> autoIndentStyle() & AiOpening))\n                    ind += ind_width;\n            }\n            else if (istate == isBlockEnd)\n            {\n                if (lex -> autoIndentStyle() & AiClosing)\n                    ind -= ind_width;\n\n                if (ind < 0)\n                    ind = 0;\n            }\n            else if (line == l)\n                ind += ind_width;\n\n            return ind;\n        }\n    }\n\n    return indentation(line);\n}\n\n\n// Return true if all characters starting at spos up to, but not including\n// epos, are spaces or tabs.\nbool QsciScintilla::rangeIsWhitespace(long spos, long epos)\n{\n    while (spos < epos)\n    {\n        char ch = SendScintilla(SCI_GETCHARAT, spos);\n\n        if (ch != ' ' && ch != '\\t')\n            return false;\n\n        ++spos;\n    }\n\n    return true;\n}\n\n\n// Returns the indentation state of a line.\nQsciScintilla::IndentState QsciScintilla::getIndentState(int line)\n{\n    IndentState istate;\n\n    // Get the styled text.\n    long spos = SendScintilla(SCI_POSITIONFROMLINE, line);\n    long epos = SendScintilla(SCI_POSITIONFROMLINE, line + 1);\n\n    char *text = new char[(epos - spos + 1) * 2];\n\n    SendScintilla(SCI_GETSTYLEDTEXT, spos, epos, text);\n\n    int style, bstart_off, bend_off;\n\n    // Block start/end takes precedence over keywords.\n    const char *bstart_words = lex->blockStart(&style);\n    bstart_off = findStyledWord(text, style, bstart_words);\n\n    const char *bend_words = lex->blockEnd(&style);\n    bend_off = findStyledWord(text, style, bend_words);\n\n    // If there is a block start but no block end characters then ignore it\n    // unless the block start is the last significant thing on the line, ie.\n    // assume Python-like blocking.\n    if (bstart_off >= 0 && !bend_words)\n        for (int i = bstart_off * 2; text[i] != '\\0'; i += 2)\n            if (!QChar(text[i]).isSpace())\n                return isNone;\n\n    if (bstart_off > bend_off)\n        istate = isBlockStart;\n    else if (bend_off > bstart_off)\n        istate = isBlockEnd;\n    else\n    {\n        const char *words = lex->blockStartKeyword(&style);\n\n        istate = (findStyledWord(text,style,words) >= 0) ? isKeywordStart : isNone;\n    }\n\n    delete[] text;\n\n    return istate;\n}\n\n\n// text is a pointer to some styled text (ie. a character byte followed by a\n// style byte).  style is a style number.  words is a space separated list of\n// words.  Returns the position in the text immediately after the last one of\n// the words with the style.  The reason we are after the last, and not the\n// first, occurance is that we are looking for words that start and end a block\n// where the latest one is the most significant.\nint QsciScintilla::findStyledWord(const char *text, int style,\n        const char *words)\n{\n    if (!words)\n        return -1;\n\n    // Find the range of text with the style we are looking for.\n    const char *stext;\n\n    for (stext = text; stext[1] != style; stext += 2)\n        if (stext[0] == '\\0')\n            return -1;\n\n    // Move to the last character.\n    const char *etext = stext;\n\n    while (etext[2] != '\\0')\n        etext += 2;\n\n    // Backtrack until we find the style.  There will be one.\n    while (etext[1] != style)\n        etext -= 2;\n\n    // Look for each word in turn.\n    while (words[0] != '\\0')\n    {\n        // Find the end of the word.\n        const char *eword = words;\n\n        while (eword[1] != ' ' && eword[1] != '\\0')\n            ++eword;\n\n        // Now search the text backwards.\n        const char *wp = eword;\n\n        for (const char *tp = etext; tp >= stext; tp -= 2)\n        {\n            if (tp[0] != wp[0] || tp[1] != style)\n            {\n                // Reset the search.\n                wp = eword;\n                continue;\n            }\n\n            // See if all the word has matched.\n            if (wp-- == words)\n                return ((tp - text) / 2) + (eword - words) + 1;\n        }\n\n        // Move to the start of the next word if there is one.\n        words = eword + 1;\n\n        if (words[0] == ' ')\n            ++words;\n    }\n\n    return -1;\n}\n\n\n// Return true if the code page is UTF8.\nbool QsciScintilla::isUtf8() const\n{\n    return (SendScintilla(SCI_GETCODEPAGE) == SC_CP_UTF8);\n}\n\n\n// Set the code page.\nvoid QsciScintilla::setUtf8(bool cp)\n{\n    SendScintilla(SCI_SETCODEPAGE, (cp ? SC_CP_UTF8 : 0));\n}\n\n\n// Return the end-of-line mode.\nQsciScintilla::EolMode QsciScintilla::eolMode() const\n{\n    return (EolMode)SendScintilla(SCI_GETEOLMODE);\n}\n\n\n// Set the end-of-line mode.\nvoid QsciScintilla::setEolMode(EolMode mode)\n{\n    SendScintilla(SCI_SETEOLMODE, mode);\n}\n\n\n// Convert the end-of-lines to a particular mode.\nvoid QsciScintilla::convertEols(EolMode mode)\n{\n    SendScintilla(SCI_CONVERTEOLS, mode);\n}\n\n\n// Add an edge column.\nvoid QsciScintilla::addEdgeColumn(int colnr, const QColor &col)\n{\n    SendScintilla(SCI_MULTIEDGEADDLINE, colnr, col);\n}\n\n\n// Clear all multi-edge columns.\nvoid QsciScintilla::clearEdgeColumns()\n{\n    SendScintilla(SCI_MULTIEDGECLEARALL);\n}\n\n\n// Return the edge colour.\nQColor QsciScintilla::edgeColor() const\n{\n    return asQColor(SendScintilla(SCI_GETEDGECOLOUR));\n}\n\n\n// Set the edge colour.\nvoid QsciScintilla::setEdgeColor(const QColor &col)\n{\n    SendScintilla(SCI_SETEDGECOLOUR, col);\n}\n\n\n// Return the edge column.\nint QsciScintilla::edgeColumn() const\n{\n    return SendScintilla(SCI_GETEDGECOLUMN);\n}\n\n\n// Set the edge column.\nvoid QsciScintilla::setEdgeColumn(int colnr)\n{\n    SendScintilla(SCI_SETEDGECOLUMN, colnr);\n}\n\n\n// Return the edge mode.\nQsciScintilla::EdgeMode QsciScintilla::edgeMode() const\n{\n    return (EdgeMode)SendScintilla(SCI_GETEDGEMODE);\n}\n\n\n// Set the edge mode.\nvoid QsciScintilla::setEdgeMode(EdgeMode mode)\n{\n    SendScintilla(SCI_SETEDGEMODE, mode);\n}\n\n\n// Return the end-of-line visibility.\nbool QsciScintilla::eolVisibility() const\n{\n    return SendScintilla(SCI_GETVIEWEOL);\n}\n\n\n// Set the end-of-line visibility.\nvoid QsciScintilla::setEolVisibility(bool visible)\n{\n    SendScintilla(SCI_SETVIEWEOL, visible);\n}\n\n\n// Return the extra ascent.\nint QsciScintilla::extraAscent() const\n{\n    return SendScintilla(SCI_GETEXTRAASCENT);\n}\n\n\n// Set the extra ascent.\nvoid QsciScintilla::setExtraAscent(int extra)\n{\n    SendScintilla(SCI_SETEXTRAASCENT, extra);\n}\n\n\n// Return the extra descent.\nint QsciScintilla::extraDescent() const\n{\n    return SendScintilla(SCI_GETEXTRADESCENT);\n}\n\n\n// Set the extra descent.\nvoid QsciScintilla::setExtraDescent(int extra)\n{\n    SendScintilla(SCI_SETEXTRADESCENT, extra);\n}\n\n\n// Return the whitespace size.\nint QsciScintilla::whitespaceSize() const\n{\n    return SendScintilla(SCI_GETWHITESPACESIZE);\n}\n\n\n// Set the whitespace size.\nvoid QsciScintilla::setWhitespaceSize(int size)\n{\n    SendScintilla(SCI_SETWHITESPACESIZE, size);\n}\n\n\n// Set the whitespace background colour.\nvoid QsciScintilla::setWhitespaceBackgroundColor(const QColor &col)\n{\n    SendScintilla(SCI_SETWHITESPACEBACK, col.isValid(), col);\n}\n\n\n// Set the whitespace foreground colour.\nvoid QsciScintilla::setWhitespaceForegroundColor(const QColor &col)\n{\n    SendScintilla(SCI_SETWHITESPACEFORE, col.isValid(), col);\n}\n\n\n// Return the whitespace visibility.\nQsciScintilla::WhitespaceVisibility QsciScintilla::whitespaceVisibility() const\n{\n    return (WhitespaceVisibility)SendScintilla(SCI_GETVIEWWS);\n}\n\n\n// Set the whitespace visibility.\nvoid QsciScintilla::setWhitespaceVisibility(WhitespaceVisibility mode)\n{\n    SendScintilla(SCI_SETVIEWWS, mode);\n}\n\n\n// Return the tab draw mode.\nQsciScintilla::TabDrawMode QsciScintilla::tabDrawMode() const\n{\n    return (TabDrawMode)SendScintilla(SCI_GETTABDRAWMODE);\n}\n\n\n// Set the tab draw mode.\nvoid QsciScintilla::setTabDrawMode(TabDrawMode mode)\n{\n    SendScintilla(SCI_SETTABDRAWMODE, mode);\n}\n\n\n// Return the line wrap mode.\nQsciScintilla::WrapMode QsciScintilla::wrapMode() const\n{\n    return (WrapMode)SendScintilla(SCI_GETWRAPMODE);\n}\n\n\n// Set the line wrap mode.\nvoid QsciScintilla::setWrapMode(WrapMode mode)\n{\n    SendScintilla(SCI_SETLAYOUTCACHE,\n            (mode == WrapNone ? SC_CACHE_CARET : SC_CACHE_DOCUMENT));\n    SendScintilla(SCI_SETWRAPMODE, mode);\n}\n\n\n// Return the line wrap indent mode.\nQsciScintilla::WrapIndentMode QsciScintilla::wrapIndentMode() const\n{\n    return (WrapIndentMode)SendScintilla(SCI_GETWRAPINDENTMODE);\n}\n\n\n// Set the line wrap indent mode.\nvoid QsciScintilla::setWrapIndentMode(WrapIndentMode mode)\n{\n    SendScintilla(SCI_SETWRAPINDENTMODE, mode);\n}\n\n\n// Set the line wrap visual flags.\nvoid QsciScintilla::setWrapVisualFlags(WrapVisualFlag endFlag,\n        WrapVisualFlag startFlag, int indent)\n{\n    int flags = SC_WRAPVISUALFLAG_NONE;\n    int loc = SC_WRAPVISUALFLAGLOC_DEFAULT;\n\n    switch (endFlag)\n    {\n    case WrapFlagNone:\n        break;\n\n    case WrapFlagByText:\n        flags |= SC_WRAPVISUALFLAG_END;\n        loc |= SC_WRAPVISUALFLAGLOC_END_BY_TEXT;\n        break;\n\n    case WrapFlagByBorder:\n        flags |= SC_WRAPVISUALFLAG_END;\n        break;\n\n    case WrapFlagInMargin:\n        flags |= SC_WRAPVISUALFLAG_MARGIN;\n        break;\n    }\n\n    switch (startFlag)\n    {\n    case WrapFlagNone:\n        break;\n\n    case WrapFlagByText:\n        flags |= SC_WRAPVISUALFLAG_START;\n        loc |= SC_WRAPVISUALFLAGLOC_START_BY_TEXT;\n        break;\n\n    case WrapFlagByBorder:\n        flags |= SC_WRAPVISUALFLAG_START;\n        break;\n\n    case WrapFlagInMargin:\n        flags |= SC_WRAPVISUALFLAG_MARGIN;\n        break;\n    }\n\n    SendScintilla(SCI_SETWRAPVISUALFLAGS, flags);\n    SendScintilla(SCI_SETWRAPVISUALFLAGSLOCATION, loc);\n    SendScintilla(SCI_SETWRAPSTARTINDENT, indent);\n}\n\n\n// Set the folding style.\nvoid QsciScintilla::setFolding(FoldStyle folding, int margin)\n{\n    fold = folding;\n    foldmargin = margin;\n\n    if (folding == NoFoldStyle)\n    {\n        SendScintilla(SCI_SETMARGINWIDTHN, margin, 0L);\n        return;\n    }\n\n    int mask = SendScintilla(SCI_GETMODEVENTMASK);\n    SendScintilla(SCI_SETMODEVENTMASK, mask | SC_MOD_CHANGEFOLD);\n\n    SendScintilla(SCI_SETFOLDFLAGS, SC_FOLDFLAG_LINEAFTER_CONTRACTED);\n\n    SendScintilla(SCI_SETMARGINTYPEN, margin, (long)SC_MARGIN_SYMBOL);\n    SendScintilla(SCI_SETMARGINMASKN, margin, SC_MASK_FOLDERS);\n    SendScintilla(SCI_SETMARGINSENSITIVEN, margin, 1);\n\n    // Set the marker symbols to use.\n    switch (folding)\n    {\n    case NoFoldStyle:\n        break;\n\n    case PlainFoldStyle:\n        setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS);\n        setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_PLUS);\n        setFoldMarker(SC_MARKNUM_FOLDERSUB);\n        setFoldMarker(SC_MARKNUM_FOLDERTAIL);\n        setFoldMarker(SC_MARKNUM_FOLDEREND);\n        setFoldMarker(SC_MARKNUM_FOLDEROPENMID);\n        setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL);\n        break;\n\n    case CircledFoldStyle:\n        setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_CIRCLEMINUS);\n        setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_CIRCLEPLUS);\n        setFoldMarker(SC_MARKNUM_FOLDERSUB);\n        setFoldMarker(SC_MARKNUM_FOLDERTAIL);\n        setFoldMarker(SC_MARKNUM_FOLDEREND);\n        setFoldMarker(SC_MARKNUM_FOLDEROPENMID);\n        setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL);\n        break;\n\n    case BoxedFoldStyle:\n        setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS);\n        setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS);\n        setFoldMarker(SC_MARKNUM_FOLDERSUB);\n        setFoldMarker(SC_MARKNUM_FOLDERTAIL);\n        setFoldMarker(SC_MARKNUM_FOLDEREND);\n        setFoldMarker(SC_MARKNUM_FOLDEROPENMID);\n        setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL);\n        break;\n\n    case CircledTreeFoldStyle:\n        setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_CIRCLEMINUS);\n        setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_CIRCLEPLUS);\n        setFoldMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE);\n        setFoldMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNERCURVE);\n        setFoldMarker(SC_MARKNUM_FOLDEREND, SC_MARK_CIRCLEPLUSCONNECTED);\n        setFoldMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_CIRCLEMINUSCONNECTED);\n        setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNERCURVE);\n        break;\n\n    case BoxedTreeFoldStyle:\n        setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS);\n        setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS);\n        setFoldMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE);\n        setFoldMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNER);\n        setFoldMarker(SC_MARKNUM_FOLDEREND, SC_MARK_BOXPLUSCONNECTED);\n        setFoldMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_BOXMINUSCONNECTED);\n        setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNER);\n        break;\n    }\n\n    SendScintilla(SCI_SETMARGINWIDTHN, margin, defaultFoldMarginWidth);\n}\n\n\n// Clear all current folds.\nvoid QsciScintilla::clearFolds()\n{\n    recolor();\n\n    int maxLine = SendScintilla(SCI_GETLINECOUNT);\n\n    for (int line = 0; line < maxLine; line++)\n    {\n        int level = SendScintilla(SCI_GETFOLDLEVEL, line);\n\n        if (level & SC_FOLDLEVELHEADERFLAG)\n        {\n            SendScintilla(SCI_SETFOLDEXPANDED, line, 1);\n            foldExpand(line, true, false, 0, level);\n            line--;\n        }\n    }\n}\n\n\n// Set up a folder marker.\nvoid QsciScintilla::setFoldMarker(int marknr, int mark)\n{\n    SendScintilla(SCI_MARKERDEFINE, marknr, mark);\n\n    if (mark != SC_MARK_EMPTY)\n    {\n        SendScintilla(SCI_MARKERSETFORE, marknr, QColor(Qt::white));\n        SendScintilla(SCI_MARKERSETBACK, marknr, QColor(Qt::black));\n    }\n}\n\n\n// Handle a click in the fold margin.  This is mostly taken from SciTE.\nvoid QsciScintilla::foldClick(int lineClick, int bstate)\n{\n    bool shift = bstate & Qt::ShiftModifier;\n    bool ctrl = bstate & Qt::ControlModifier;\n\n    if (shift && ctrl)\n    {\n        foldAll();\n        return;\n    }\n\n    int levelClick = SendScintilla(SCI_GETFOLDLEVEL, lineClick);\n\n    if (levelClick & SC_FOLDLEVELHEADERFLAG)\n    {\n        if (shift)\n        {\n            // Ensure all children are visible.\n            SendScintilla(SCI_SETFOLDEXPANDED, lineClick, 1);\n            foldExpand(lineClick, true, true, 100, levelClick);\n        }\n        else if (ctrl)\n        {\n            if (SendScintilla(SCI_GETFOLDEXPANDED, lineClick))\n            {\n                // Contract this line and all its children.\n                SendScintilla(SCI_SETFOLDEXPANDED, lineClick, 0L);\n                foldExpand(lineClick, false, true, 0, levelClick);\n            }\n            else\n            {\n                // Expand this line and all its children.\n                SendScintilla(SCI_SETFOLDEXPANDED, lineClick, 1);\n                foldExpand(lineClick, true, true, 100, levelClick);\n            }\n        }\n        else\n        {\n            // Toggle this line.\n            SendScintilla(SCI_TOGGLEFOLD, lineClick);\n        }\n    }\n}\n\n\n// Do the hard work of hiding and showing lines.  This is mostly taken from\n// SciTE.\nvoid QsciScintilla::foldExpand(int &line, bool doExpand, bool force,\n        int visLevels, int level)\n{\n    int lineMaxSubord = SendScintilla(SCI_GETLASTCHILD, line,\n            level & SC_FOLDLEVELNUMBERMASK);\n\n    line++;\n\n    while (line <= lineMaxSubord)\n    {\n        if (force)\n        {\n            if (visLevels > 0)\n                SendScintilla(SCI_SHOWLINES, line, line);\n            else\n                SendScintilla(SCI_HIDELINES, line, line);\n        }\n        else if (doExpand)\n            SendScintilla(SCI_SHOWLINES, line, line);\n\n        int levelLine = level;\n\n        if (levelLine == -1)\n            levelLine = SendScintilla(SCI_GETFOLDLEVEL, line);\n\n        if (levelLine & SC_FOLDLEVELHEADERFLAG)\n        {\n            if (force)\n            {\n                if (visLevels > 1)\n                    SendScintilla(SCI_SETFOLDEXPANDED, line, 1);\n                else\n                    SendScintilla(SCI_SETFOLDEXPANDED, line, 0L);\n\n                foldExpand(line, doExpand, force, visLevels - 1);\n            }\n            else if (doExpand)\n            {\n                if (!SendScintilla(SCI_GETFOLDEXPANDED, line))\n                    SendScintilla(SCI_SETFOLDEXPANDED, line, 1);\n\n                foldExpand(line, true, force, visLevels - 1);\n            }\n            else\n                foldExpand(line, false, force, visLevels - 1);\n        }\n        else\n            line++;\n    }\n}\n\n\n// Fully expand (if there is any line currently folded) all text.  Otherwise,\n// fold all text.  This is mostly taken from SciTE.\nvoid QsciScintilla::foldAll(bool children)\n{\n    recolor();\n\n    int maxLine = SendScintilla(SCI_GETLINECOUNT);\n    bool expanding = true;\n\n    for (int lineSeek = 0; lineSeek < maxLine; lineSeek++)\n    {\n        if (SendScintilla(SCI_GETFOLDLEVEL,lineSeek) & SC_FOLDLEVELHEADERFLAG)\n        {\n            expanding = !SendScintilla(SCI_GETFOLDEXPANDED, lineSeek);\n            break;\n        }\n    }\n\n    for (int line = 0; line < maxLine; line++)\n    {\n        int level = SendScintilla(SCI_GETFOLDLEVEL, line);\n\n        if (!(level & SC_FOLDLEVELHEADERFLAG))\n            continue;\n\n        if (children ||\n            (SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK)))\n        {\n            if (expanding)\n            {\n                SendScintilla(SCI_SETFOLDEXPANDED, line, 1);\n                foldExpand(line, true, false, 0, level);\n                line--;\n            }\n            else\n            {\n                int lineMaxSubord = SendScintilla(SCI_GETLASTCHILD, line, -1);\n\n                SendScintilla(SCI_SETFOLDEXPANDED, line, 0L);\n\n                if (lineMaxSubord > line)\n                    SendScintilla(SCI_HIDELINES, line + 1, lineMaxSubord);\n            }\n        }\n    }\n}\n\n\n// Handle a fold change.  This is mostly taken from SciTE.\nvoid QsciScintilla::foldChanged(int line,int levelNow,int levelPrev)\n{\n    if (levelNow & SC_FOLDLEVELHEADERFLAG)\n    {\n        if (!(levelPrev & SC_FOLDLEVELHEADERFLAG))\n            SendScintilla(SCI_SETFOLDEXPANDED, line, 1);\n    }\n    else if (levelPrev & SC_FOLDLEVELHEADERFLAG)\n    {\n        if (!SendScintilla(SCI_GETFOLDEXPANDED, line))\n        {\n            // Removing the fold from one that has been contracted so should\n            // expand.  Otherwise lines are left invisible with no way to make\n            // them visible.\n            foldExpand(line, true, false, 0, levelPrev);\n        }\n    }\n}\n\n\n// Toggle the fold for a line if it contains a fold marker.\nvoid QsciScintilla::foldLine(int line)\n{\n    SendScintilla(SCI_TOGGLEFOLD, line);\n}\n\n\n// Return the list of folded lines.\nQList<int> QsciScintilla::contractedFolds() const\n{\n    QList<int> folds;\n    int linenr = 0, fold_line;\n\n    while ((fold_line = SendScintilla(SCI_CONTRACTEDFOLDNEXT, linenr)) >= 0)\n    {\n        folds.append(fold_line);\n        linenr = fold_line + 1;\n    }\n\n    return folds;\n}\n\n\n// Set the fold state from a list.\nvoid QsciScintilla::setContractedFolds(const QList<int> &folds)\n{\n    for (int i = 0; i < folds.count(); ++i)\n    {\n        int line = folds[i];\n        int last_line = SendScintilla(SCI_GETLASTCHILD, line, -1);\n\n        SendScintilla(SCI_SETFOLDEXPANDED, line, 0L);\n        SendScintilla(SCI_HIDELINES, line + 1, last_line);\n    }\n}\n\n\n// Handle the SCN_MODIFIED notification.\nvoid QsciScintilla::handleModified(int pos, int mtype, const char *text,\n        int len, int added, int line, int foldNow, int foldPrev, int token,\n        int annotationLinesAdded)\n{\n    Q_UNUSED(pos);\n    Q_UNUSED(text);\n    Q_UNUSED(len);\n    Q_UNUSED(token);\n    Q_UNUSED(annotationLinesAdded);\n\n    if (mtype & SC_MOD_CHANGEFOLD)\n    {\n        if (fold)\n            foldChanged(line, foldNow, foldPrev);\n    }\n\n    if (mtype & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT))\n    {\n        emit textChanged();\n\n        if (added != 0)\n            emit linesChanged();\n    }\n}\n\n\n// Zoom in a number of points.\nvoid QsciScintilla::zoomIn(int range)\n{\n    zoomTo(SendScintilla(SCI_GETZOOM) + range);\n}\n\n\n// Zoom in a single point.\nvoid QsciScintilla::zoomIn()\n{\n    SendScintilla(SCI_ZOOMIN);\n}\n\n\n// Zoom out a number of points.\nvoid QsciScintilla::zoomOut(int range)\n{\n    zoomTo(SendScintilla(SCI_GETZOOM) - range);\n}\n\n\n// Zoom out a single point.\nvoid QsciScintilla::zoomOut()\n{\n    SendScintilla(SCI_ZOOMOUT);\n}\n\n\n// Set the zoom to a number of points.\nvoid QsciScintilla::zoomTo(int size)\n{\n    if (size < -10)\n        size = -10;\n    else if (size > 20)\n        size = 20;\n\n    SendScintilla(SCI_SETZOOM, size);\n}\n\n\n// Find the first occurrence of a string.\nbool QsciScintilla::findFirst(const QString &expr, bool re, bool cs, bool wo,\n        bool wrap, bool forward, int line, int index, bool show, bool posix,\n        bool cxx11)\n{\n    if (expr.isEmpty())\n    {\n        findState.status = FindState::Idle;\n        return false;\n    }\n\n    findState.status = FindState::Finding;\n    findState.expr = expr;\n    findState.wrap = wrap;\n    findState.forward = forward;\n\n    findState.flags =\n        (cs ? SCFIND_MATCHCASE : 0) |\n        (wo ? SCFIND_WHOLEWORD : 0) |\n        (re ? SCFIND_REGEXP : 0) |\n        (posix ? SCFIND_POSIX : 0) |\n        (cxx11 ? SCFIND_CXX11REGEX : 0);\n\n    if (line < 0 || index < 0)\n        findState.startpos = SendScintilla(SCI_GETCURRENTPOS);\n    else\n        findState.startpos = positionFromLineIndex(line, index);\n\n    if (forward)\n        findState.endpos = SendScintilla(SCI_GETLENGTH);\n    else\n        findState.endpos = 0;\n\n    findState.show = show;\n\n    return doFind();\n}\n\n\n// Find the first occurrence of a string in the current selection.\nbool QsciScintilla::findFirstInSelection(const QString &expr, bool re, bool cs,\n        bool wo, bool forward, bool show, bool posix, bool cxx11)\n{\n    if (expr.isEmpty())\n    {\n        findState.status = FindState::Idle;\n        return false;\n    }\n\n    findState.status = FindState::FindingInSelection;\n    findState.expr = expr;\n    findState.wrap = false;\n    findState.forward = forward;\n\n    findState.flags =\n        (cs ? SCFIND_MATCHCASE : 0) |\n        (wo ? SCFIND_WHOLEWORD : 0) |\n        (re ? SCFIND_REGEXP : 0) |\n        (posix ? SCFIND_POSIX : 0) |\n        (cxx11 ? SCFIND_CXX11REGEX : 0);\n\n    findState.startpos_orig = SendScintilla(SCI_GETSELECTIONSTART);\n    findState.endpos_orig = SendScintilla(SCI_GETSELECTIONEND);\n\n    if (forward)\n    {\n        findState.startpos = findState.startpos_orig;\n        findState.endpos = findState.endpos_orig;\n    }\n    else\n    {\n        findState.startpos = findState.endpos_orig;\n        findState.endpos = findState.startpos_orig;\n    }\n\n    findState.show = show;\n\n    return doFind();\n}\n\n\n// Cancel any current search.\nvoid QsciScintilla::cancelFind()\n{\n    findState.status = FindState::Idle;\n}\n\n\n// Find the next occurrence of a string.\nbool QsciScintilla::findNext()\n{\n    if (findState.status == FindState::Idle)\n        return false;\n\n    return doFind();\n}\n\n\n// Do the hard work of the find methods.\nbool QsciScintilla::doFind()\n{\n    SendScintilla(SCI_SETSEARCHFLAGS, findState.flags);\n\n    int pos = simpleFind();\n\n    // See if it was found.  If not and wraparound is wanted, try again.\n    if (pos == -1 && findState.wrap)\n    {\n        if (findState.forward)\n        {\n            findState.startpos = 0;\n            findState.endpos = SendScintilla(SCI_GETLENGTH);\n        }\n        else\n        {\n            findState.startpos = SendScintilla(SCI_GETLENGTH);\n            findState.endpos = 0;\n        }\n\n        pos = simpleFind();\n    }\n\n    if (pos == -1)\n    {\n        // Restore the original selection.\n        if (findState.status == FindState::FindingInSelection)\n            SendScintilla(SCI_SETSEL, findState.startpos_orig,\n                    findState.endpos_orig);\n\n        findState.status = FindState::Idle;\n        return false;\n    }\n\n    // It was found.\n    long targstart = SendScintilla(SCI_GETTARGETSTART);\n    long targend = SendScintilla(SCI_GETTARGETEND);\n\n    // Ensure the text found is visible if required.\n    if (findState.show)\n    {\n        int startLine = SendScintilla(SCI_LINEFROMPOSITION, targstart);\n        int endLine = SendScintilla(SCI_LINEFROMPOSITION, targend);\n\n        for (int i = startLine; i <= endLine; ++i)\n            SendScintilla(SCI_ENSUREVISIBLEENFORCEPOLICY, i);\n    }\n\n    // Now set the selection.\n    SendScintilla(SCI_SETSEL, targstart, targend);\n\n    // Finally adjust the start position so that we don't find the same one\n    // again.\n    if (findState.forward)\n        findState.startpos = targend;\n    else if ((findState.startpos = targstart - 1) < 0)\n        findState.startpos = 0;\n\n    return true;\n}\n\n\n// Do a simple find between the start and end positions.\nint QsciScintilla::simpleFind()\n{\n    if (findState.startpos == findState.endpos)\n        return -1;\n\n    SendScintilla(SCI_SETTARGETSTART, findState.startpos);\n    SendScintilla(SCI_SETTARGETEND, findState.endpos);\n\n    QByteArray s = textAsBytes(findState.expr);\n\n    return SendScintilla(SCI_SEARCHINTARGET, s.length(), s.constData());\n}\n\n\n// Replace the text found with the previous find method.\nvoid QsciScintilla::replace(const QString &replaceStr)\n{\n    if (findState.status == FindState::Idle)\n        return;\n\n    long start = SendScintilla(SCI_GETSELECTIONSTART);\n    long orig_len = SendScintilla(SCI_GETSELECTIONEND) - start;\n\n    SendScintilla(SCI_TARGETFROMSELECTION);\n\n    int cmd = (findState.flags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET;\n\n    long len = SendScintilla(cmd, -1, textAsBytes(replaceStr).constData());\n\n    // Reset the selection.\n    SendScintilla(SCI_SETSELECTIONSTART, start);\n    SendScintilla(SCI_SETSELECTIONEND, start + len);\n\n    // Fix the original selection.\n    findState.endpos_orig += (len - orig_len);\n\n    if (findState.forward)\n    {\n        findState.startpos = start + len;\n        findState.endpos += (len - orig_len);\n    }\n}\n\n\n// Query the modified state.\nbool QsciScintilla::isModified() const\n{\n    return doc.isModified();\n}\n\n\n// Set the modified state.\nvoid QsciScintilla::setModified(bool m)\n{\n    if (!m)\n        SendScintilla(SCI_SETSAVEPOINT);\n}\n\n\n// Handle the SCN_INDICATORCLICK notification.\nvoid QsciScintilla::handleIndicatorClick(int pos, int modifiers)\n{\n    int state = mapModifiers(modifiers);\n    int line, index;\n\n    lineIndexFromPosition(pos, &line, &index);\n\n    emit indicatorClicked(line, index, Qt::KeyboardModifiers(state));\n}\n\n\n// Handle the SCN_INDICATORRELEASE notification.\nvoid QsciScintilla::handleIndicatorRelease(int pos, int modifiers)\n{\n    int state = mapModifiers(modifiers);\n    int line, index;\n\n    lineIndexFromPosition(pos, &line, &index);\n\n    emit indicatorReleased(line, index, Qt::KeyboardModifiers(state));\n}\n\n\n// Handle the SCN_MARGINCLICK notification.\nvoid QsciScintilla::handleMarginClick(int pos, int modifiers, int margin)\n{\n    int state = mapModifiers(modifiers);\n    int line = SendScintilla(SCI_LINEFROMPOSITION, pos);\n\n    if (fold && margin == foldmargin)\n        foldClick(line, state);\n    else\n        emit marginClicked(margin, line, Qt::KeyboardModifiers(state));\n}\n\n\n// Handle the SCN_MARGINRIGHTCLICK notification.\nvoid QsciScintilla::handleMarginRightClick(int pos, int modifiers, int margin)\n{\n    int state = mapModifiers(modifiers);\n    int line = SendScintilla(SCI_LINEFROMPOSITION, pos);\n\n    emit marginRightClicked(margin, line, Qt::KeyboardModifiers(state));\n}\n\n\n// Handle the SCN_SAVEPOINTREACHED notification.\nvoid QsciScintilla::handleSavePointReached()\n{\n    doc.setModified(false);\n    emit modificationChanged(false);\n}\n\n\n// Handle the SCN_SAVEPOINTLEFT notification.\nvoid QsciScintilla::handleSavePointLeft()\n{\n    doc.setModified(true);\n    emit modificationChanged(true);\n}\n\n\n// Handle the QSCN_SELCHANGED signal.\nvoid QsciScintilla::handleSelectionChanged(bool yes)\n{\n    selText = yes;\n\n    emit copyAvailable(yes);\n    emit selectionChanged();\n}\n\n\n// Get the current selection.\nvoid QsciScintilla::getSelection(int *lineFrom, int *indexFrom, int *lineTo,\n        int *indexTo) const\n{\n    if (selText)\n    {\n        lineIndexFromPosition(SendScintilla(SCI_GETSELECTIONSTART), lineFrom,\n                indexFrom);\n        lineIndexFromPosition(SendScintilla(SCI_GETSELECTIONEND), lineTo,\n                indexTo);\n    }\n    else\n        *lineFrom = *indexFrom = *lineTo = *indexTo = -1;\n}\n\n\n// Sets the current selection.\nvoid QsciScintilla::setSelection(int lineFrom, int indexFrom, int lineTo,\n        int indexTo)\n{\n    SendScintilla(SCI_SETSEL, positionFromLineIndex(lineFrom, indexFrom),\n            positionFromLineIndex(lineTo, indexTo));\n}\n\n\n// Set the background colour of selected text.\nvoid QsciScintilla::setSelectionBackgroundColor(const QColor &col)\n{\n    int alpha = col.alpha();\n\n    if (alpha == 255)\n        alpha = SC_ALPHA_NOALPHA;\n\n    SendScintilla(SCI_SETSELBACK, 1, col);\n    SendScintilla(SCI_SETSELALPHA, alpha);\n}\n\n\n// Set the foreground colour of selected text.\nvoid QsciScintilla::setSelectionForegroundColor(const QColor &col)\n{\n    SendScintilla(SCI_SETSELFORE, 1, col);\n}\n\n\n// Reset the background colour of selected text to the default.\nvoid QsciScintilla::resetSelectionBackgroundColor()\n{\n    SendScintilla(SCI_SETSELALPHA, SC_ALPHA_NOALPHA);\n    SendScintilla(SCI_SETSELBACK, 0UL);\n}\n\n\n// Reset the foreground colour of selected text to the default.\nvoid QsciScintilla::resetSelectionForegroundColor()\n{\n    SendScintilla(SCI_SETSELFORE, 0UL);\n}\n\n\n// Set the fill to the end-of-line for the selection.\nvoid QsciScintilla::setSelectionToEol(bool filled)\n{\n    SendScintilla(SCI_SETSELEOLFILLED, filled);\n}\n\n\n// Return the fill to the end-of-line for the selection.\nbool QsciScintilla::selectionToEol() const\n{\n    return SendScintilla(SCI_GETSELEOLFILLED);\n}\n\n\n// Set the width of the caret.\nvoid QsciScintilla::setCaretWidth(int width)\n{\n    SendScintilla(SCI_SETCARETWIDTH, width);\n}\n\n\n// Set the width of the frame of the line containing the caret.\nvoid QsciScintilla::setCaretLineFrameWidth(int width)\n{\n    SendScintilla(SCI_SETCARETLINEFRAME, width);\n}\n\n\n// Set the foreground colour of the caret.\nvoid QsciScintilla::setCaretForegroundColor(const QColor &col)\n{\n    SendScintilla(SCI_SETCARETFORE, col);\n}\n\n\n// Set the background colour of the line containing the caret.\nvoid QsciScintilla::setCaretLineBackgroundColor(const QColor &col)\n{\n    int alpha = col.alpha();\n\n    if (alpha == 255)\n        alpha = SC_ALPHA_NOALPHA;\n\n    SendScintilla(SCI_SETCARETLINEBACK, col);\n    SendScintilla(SCI_SETCARETLINEBACKALPHA, alpha);\n}\n\n\n// Set the state of the background colour of the line containing the caret.\nvoid QsciScintilla::setCaretLineVisible(bool enable)\n{\n    SendScintilla(SCI_SETCARETLINEVISIBLE, enable);\n}\n\n\n// Set the background colour of a hotspot area.\nvoid QsciScintilla::setHotspotBackgroundColor(const QColor &col)\n{\n    SendScintilla(SCI_SETHOTSPOTACTIVEBACK, 1, col);\n}\n\n\n// Set the foreground colour of a hotspot area.\nvoid QsciScintilla::setHotspotForegroundColor(const QColor &col)\n{\n    SendScintilla(SCI_SETHOTSPOTACTIVEFORE, 1, col);\n}\n\n\n// Reset the background colour of a hotspot area to the default.\nvoid QsciScintilla::resetHotspotBackgroundColor()\n{\n    SendScintilla(SCI_SETHOTSPOTACTIVEBACK, 0UL);\n}\n\n\n// Reset the foreground colour of a hotspot area to the default.\nvoid QsciScintilla::resetHotspotForegroundColor()\n{\n    SendScintilla(SCI_SETHOTSPOTACTIVEFORE, 0UL);\n}\n\n\n// Set the underline of a hotspot area.\nvoid QsciScintilla::setHotspotUnderline(bool enable)\n{\n    SendScintilla(SCI_SETHOTSPOTACTIVEUNDERLINE, enable);\n}\n\n\n// Set the wrapping of a hotspot area.\nvoid QsciScintilla::setHotspotWrap(bool enable)\n{\n    SendScintilla(SCI_SETHOTSPOTSINGLELINE, !enable);\n}\n\n\n// Query the read-only state.\nbool QsciScintilla::isReadOnly() const\n{\n    return SendScintilla(SCI_GETREADONLY);\n}\n\n\n// Set the read-only state.\nvoid QsciScintilla::setReadOnly(bool ro)\n{\n    setAttribute(Qt::WA_InputMethodEnabled, !ro);\n    SendScintilla(SCI_SETREADONLY, ro);\n}\n\n\n// Append the given text.\nvoid QsciScintilla::append(const QString &text)\n{\n    bool ro = ensureRW();\n\n    QByteArray s = textAsBytes(text);\n    SendScintilla(SCI_APPENDTEXT, s.length(), s.constData());\n\n    SendScintilla(SCI_EMPTYUNDOBUFFER);\n\n    setReadOnly(ro);\n}\n\n\n// Insert the given text at the current position.\nvoid QsciScintilla::insert(const QString &text)\n{\n    insertAtPos(text, -1);\n}\n\n\n// Insert the given text at the given line and offset.\nvoid QsciScintilla::insertAt(const QString &text, int line, int index)\n{\n    insertAtPos(text, positionFromLineIndex(line, index));\n}\n\n\n// Insert the given text at the given position.\nvoid QsciScintilla::insertAtPos(const QString &text, int pos)\n{\n    bool ro = ensureRW();\n\n    SendScintilla(SCI_BEGINUNDOACTION);\n    SendScintilla(SCI_INSERTTEXT, pos, textAsBytes(text).constData());\n    SendScintilla(SCI_ENDUNDOACTION);\n\n    setReadOnly(ro);\n}\n\n\n// Begin a sequence of undoable actions.\nvoid QsciScintilla::beginUndoAction()\n{\n    SendScintilla(SCI_BEGINUNDOACTION);\n}\n\n\n// End a sequence of undoable actions.\nvoid QsciScintilla::endUndoAction()\n{\n    SendScintilla(SCI_ENDUNDOACTION);\n}\n\n\n// Redo a sequence of actions.\nvoid QsciScintilla::redo()\n{\n    SendScintilla(SCI_REDO);\n}\n\n\n// Undo a sequence of actions.\nvoid QsciScintilla::undo()\n{\n    SendScintilla(SCI_UNDO);\n}\n\n\n// See if there is something to redo.\nbool QsciScintilla::isRedoAvailable() const\n{\n    return SendScintilla(SCI_CANREDO);\n}\n\n\n// See if there is something to undo.\nbool QsciScintilla::isUndoAvailable() const\n{\n    return SendScintilla(SCI_CANUNDO);\n}\n\n\n// Return the number of lines.\nint QsciScintilla::lines() const\n{\n    return SendScintilla(SCI_GETLINECOUNT);\n}\n\n\n// Return the line at a position.\nint QsciScintilla::lineAt(const QPoint &pos) const\n{\n    long chpos = SendScintilla(SCI_POSITIONFROMPOINTCLOSE, pos.x(), pos.y());\n\n    if (chpos < 0)\n        return -1;\n\n    return SendScintilla(SCI_LINEFROMPOSITION, chpos);\n}\n\n\n// Return the length of a line.\nint QsciScintilla::lineLength(int line) const\n{\n    if (line < 0 || line >= SendScintilla(SCI_GETLINECOUNT))\n        return -1;\n\n    return SendScintilla(SCI_LINELENGTH, line);\n}\n\n\n// Return the length of the current text.\nint QsciScintilla::length() const\n{\n    return SendScintilla(SCI_GETTEXTLENGTH);\n}\n\n\n// Remove any selected text.\nvoid QsciScintilla::removeSelectedText()\n{\n    SendScintilla(SCI_REPLACESEL, \"\");\n}\n\n\n// Replace any selected text.\nvoid QsciScintilla::replaceSelectedText(const QString &text)\n{\n    SendScintilla(SCI_REPLACESEL, textAsBytes(text).constData());\n}\n\n\n// Return the current selected text.\nQString QsciScintilla::selectedText() const\n{\n    if (!selText)\n        return QString();\n\n    int size = SendScintilla(SCI_GETSELECTIONEND) - SendScintilla(SCI_GETSELECTIONSTART);\n    char *buf = new char[size + 1];\n\n    SendScintilla(SCI_GETSELTEXT, buf);\n\n    QString qs = bytesAsText(buf, size);\n    delete[] buf;\n\n    return qs;\n}\n\n\n// Return the current text.\nQString QsciScintilla::text() const\n{\n    int size = length();\n    char *buf = new char[size + 1];\n\n    // Note that the docs seem to be wrong and we need to ask for the length\n    // plus the '\\0'.\n    SendScintilla(SCI_GETTEXT, size + 1, buf);\n\n    QString qs = bytesAsText(buf, size);\n    delete[] buf;\n\n    return qs;\n}\n\n\n// Return the text of a line.\nQString QsciScintilla::text(int line) const\n{\n    int size = lineLength(line);\n\n    if (size < 1)\n        return QString();\n\n    char *buf = new char[size];\n\n    SendScintilla(SCI_GETLINE, line, buf);\n\n    QString qs = bytesAsText(buf, size);\n    delete[] buf;\n\n    return qs;\n}\n\n\n// Return the text between two positions.\nQString QsciScintilla::text(int start, int end) const\n{\n    int size = end - start;\n    char *buf = new char[size + 1];\n    SendScintilla(SCI_GETTEXTRANGE, start, end, buf);\n    QString text = bytesAsText(buf, size);\n    delete[] buf;\n\n    return text;\n}\n\n\n// Return the text as encoded bytes between two positions.\nQByteArray QsciScintilla::bytes(int start, int end) const\n{\n    QByteArray bytes(end - start + 1, '\\0');\n\n    SendScintilla(SCI_GETTEXTRANGE, start, end, bytes.data());\n\n    return bytes;\n}\n\n\n// Set the given text.\nvoid QsciScintilla::setText(const QString &text)\n{\n    bool ro = ensureRW();\n\n    SendScintilla(SCI_CLEARALL);\n    QByteArray bytes = textAsBytes(text);\n    SendScintilla(SCI_ADDTEXT, bytes.size(), bytes.constData());\n    SendScintilla(SCI_EMPTYUNDOBUFFER);\n\n    setReadOnly(ro);\n}\n\n\n// Get the cursor position\nvoid QsciScintilla::getCursorPosition(int *line, int *index) const\n{\n    lineIndexFromPosition(SendScintilla(SCI_GETCURRENTPOS), line, index);\n}\n\n\n// Set the cursor position\nvoid QsciScintilla::setCursorPosition(int line, int index)\n{\n    SendScintilla(SCI_GOTOPOS, positionFromLineIndex(line, index));\n}\n\n\n// Ensure the cursor is visible.\nvoid QsciScintilla::ensureCursorVisible()\n{\n    SendScintilla(SCI_SCROLLCARET);\n}\n\n\n// Ensure a line is visible.\nvoid QsciScintilla::ensureLineVisible(int line)\n{\n    SendScintilla(SCI_ENSUREVISIBLEENFORCEPOLICY, line);\n}\n\n\n// Copy text to the clipboard.\nvoid QsciScintilla::copy()\n{\n    SendScintilla(SCI_COPY);\n}\n\n\n// Cut text to the clipboard.\nvoid QsciScintilla::cut()\n{\n    SendScintilla(SCI_CUT);\n}\n\n\n// Paste text from the clipboard.\nvoid QsciScintilla::paste()\n{\n    SendScintilla(SCI_PASTE);\n}\n\n\n// Select all text, or deselect any selected text.\nvoid QsciScintilla::selectAll(bool select)\n{\n    if (select)\n        SendScintilla(SCI_SELECTALL);\n    else\n        SendScintilla(SCI_SETANCHOR, SendScintilla(SCI_GETCURRENTPOS));\n}\n\n\n// Delete all text.\nvoid QsciScintilla::clear()\n{\n    bool ro = ensureRW();\n\n    SendScintilla(SCI_CLEARALL);\n    SendScintilla(SCI_EMPTYUNDOBUFFER);\n\n    setReadOnly(ro);\n}\n\n\n// Return the indentation of a line.\nint QsciScintilla::indentation(int line) const\n{\n    return SendScintilla(SCI_GETLINEINDENTATION, line);\n}\n\n\n// Set the indentation of a line.\nvoid QsciScintilla::setIndentation(int line, int indentation)\n{\n    SendScintilla(SCI_BEGINUNDOACTION);\n    SendScintilla(SCI_SETLINEINDENTATION, line, indentation);\n    SendScintilla(SCI_ENDUNDOACTION);\n}\n\n\n// Indent a line.\nvoid QsciScintilla::indent(int line)\n{\n    setIndentation(line, indentation(line) + indentWidth());\n}\n\n\n// Unindent a line.\nvoid QsciScintilla::unindent(int line)\n{\n    int newIndent = indentation(line) - indentWidth();\n\n    if (newIndent < 0)\n        newIndent = 0;\n\n    setIndentation(line, newIndent);\n}\n\n\n// Return the indentation of the current line.\nint QsciScintilla::currentIndent() const\n{\n    return indentation(SendScintilla(SCI_LINEFROMPOSITION,\n                SendScintilla(SCI_GETCURRENTPOS)));\n}\n\n\n// Return the current indentation width.\nint QsciScintilla::indentWidth() const\n{\n    int w = indentationWidth();\n\n    if (w == 0)\n        w = tabWidth();\n\n    return w;\n}\n\n\n// Return the state of indentation guides.\nbool QsciScintilla::indentationGuides() const\n{\n    return (SendScintilla(SCI_GETINDENTATIONGUIDES) != SC_IV_NONE);\n}\n\n\n// Enable and disable indentation guides.\nvoid QsciScintilla::setIndentationGuides(bool enable)\n{\n    int iv;\n\n    if (!enable)\n        iv = SC_IV_NONE;\n    else if (lex.isNull())\n        iv = SC_IV_REAL;\n    else\n        iv = lex->indentationGuideView();\n\n    SendScintilla(SCI_SETINDENTATIONGUIDES, iv);\n}\n\n\n// Set the background colour of indentation guides.\nvoid QsciScintilla::setIndentationGuidesBackgroundColor(const QColor &col)\n{\n    SendScintilla(SCI_STYLESETBACK, STYLE_INDENTGUIDE, col);\n}\n\n\n// Set the foreground colour of indentation guides.\nvoid QsciScintilla::setIndentationGuidesForegroundColor(const QColor &col)\n{\n    SendScintilla(SCI_STYLESETFORE, STYLE_INDENTGUIDE, col);\n}\n\n\n// Return the indentation width.\nint QsciScintilla::indentationWidth() const\n{\n    return SendScintilla(SCI_GETINDENT);\n}\n\n\n// Set the indentation width.\nvoid QsciScintilla::setIndentationWidth(int width)\n{\n    SendScintilla(SCI_SETINDENT, width);\n}\n\n\n// Return the tab width.\nint QsciScintilla::tabWidth() const\n{\n    return SendScintilla(SCI_GETTABWIDTH);\n}\n\n\n// Set the tab width.\nvoid QsciScintilla::setTabWidth(int width)\n{\n    SendScintilla(SCI_SETTABWIDTH, width);\n}\n\n\n// Return the effect of the backspace key.\nbool QsciScintilla::backspaceUnindents() const\n{\n    return SendScintilla(SCI_GETBACKSPACEUNINDENTS);\n}\n\n\n// Set the effect of the backspace key.\nvoid QsciScintilla::setBackspaceUnindents(bool unindents)\n{\n    SendScintilla(SCI_SETBACKSPACEUNINDENTS, unindents);\n}\n\n\n// Return the effect of the tab key.\nbool QsciScintilla::tabIndents() const\n{\n    return SendScintilla(SCI_GETTABINDENTS);\n}\n\n\n// Set the effect of the tab key.\nvoid QsciScintilla::setTabIndents(bool indents)\n{\n    SendScintilla(SCI_SETTABINDENTS, indents);\n}\n\n\n// Return the indentation use of tabs.\nbool QsciScintilla::indentationsUseTabs() const\n{\n    return SendScintilla(SCI_GETUSETABS);\n}\n\n\n// Set the indentation use of tabs.\nvoid QsciScintilla::setIndentationsUseTabs(bool tabs)\n{\n    SendScintilla(SCI_SETUSETABS, tabs);\n}\n\n\n// Return the number of margins.\nint QsciScintilla::margins() const\n{\n    return SendScintilla(SCI_GETMARGINS);\n}\n\n\n// Set the number of margins.\nvoid QsciScintilla::setMargins(int margins)\n{\n    SendScintilla(SCI_SETMARGINS, margins);\n}\n\n\n// Return the margin background colour.\nQColor QsciScintilla::marginBackgroundColor(int margin) const\n{\n    return asQColor(SendScintilla(SCI_GETMARGINBACKN, margin));\n}\n\n\n// Set the margin background colour.\nvoid QsciScintilla::setMarginBackgroundColor(int margin, const QColor &col)\n{\n    SendScintilla(SCI_SETMARGINBACKN, margin, col);\n}\n\n\n// Return the margin options.\nint QsciScintilla::marginOptions() const\n{\n    return SendScintilla(SCI_GETMARGINOPTIONS);\n}\n\n\n// Set the margin options.\nvoid QsciScintilla::setMarginOptions(int options)\n{\n    SendScintilla(SCI_SETMARGINOPTIONS, options);\n}\n\n\n// Return the margin type.\nQsciScintilla::MarginType QsciScintilla::marginType(int margin) const\n{\n    return (MarginType)SendScintilla(SCI_GETMARGINTYPEN, margin);\n}\n\n\n// Set the margin type.\nvoid QsciScintilla::setMarginType(int margin, QsciScintilla::MarginType type)\n{\n    SendScintilla(SCI_SETMARGINTYPEN, margin, type);\n}\n\n\n// Clear margin text.\nvoid QsciScintilla::clearMarginText(int line)\n{\n    if (line < 0)\n        SendScintilla(SCI_MARGINTEXTCLEARALL);\n    else\n        SendScintilla(SCI_MARGINSETTEXT, line, (const char *)0);\n}\n\n\n// Annotate a line.\nvoid QsciScintilla::setMarginText(int line, const QString &text, int style)\n{\n    int style_offset = SendScintilla(SCI_MARGINGETSTYLEOFFSET);\n\n    SendScintilla(SCI_MARGINSETTEXT, line, textAsBytes(text).constData());\n    SendScintilla(SCI_MARGINSETSTYLE, line, style - style_offset);\n}\n\n\n// Annotate a line.\nvoid QsciScintilla::setMarginText(int line, const QString &text, const QsciStyle &style)\n{\n    style.apply(this);\n\n    setMarginText(line, text, style.style());\n}\n\n\n// Annotate a line.\nvoid QsciScintilla::setMarginText(int line, const QsciStyledText &text)\n{\n    text.apply(this);\n\n    setMarginText(line, text.text(), text.style());\n}\n\n\n// Annotate a line.\nvoid QsciScintilla::setMarginText(int line, const QList<QsciStyledText> &text)\n{\n    char *styles;\n    QByteArray styled_text = styleText(text, &styles,\n            SendScintilla(SCI_MARGINGETSTYLEOFFSET));\n\n    SendScintilla(SCI_MARGINSETTEXT, line, styled_text.constData());\n    SendScintilla(SCI_MARGINSETSTYLES, line, styles);\n\n    delete[] styles;\n}\n\n\n// Return the state of line numbers in a margin.\nbool QsciScintilla::marginLineNumbers(int margin) const\n{\n    return SendScintilla(SCI_GETMARGINTYPEN, margin);\n}\n\n\n// Enable and disable line numbers in a margin.\nvoid QsciScintilla::setMarginLineNumbers(int margin, bool lnrs)\n{\n    SendScintilla(SCI_SETMARGINTYPEN, margin,\n            lnrs ? SC_MARGIN_NUMBER : SC_MARGIN_SYMBOL);\n}\n\n\n// Return the marker mask of a margin.\nint QsciScintilla::marginMarkerMask(int margin) const\n{\n    return SendScintilla(SCI_GETMARGINMASKN, margin);\n}\n\n\n// Set the marker mask of a margin.\nvoid QsciScintilla::setMarginMarkerMask(int margin,int mask)\n{\n    SendScintilla(SCI_SETMARGINMASKN, margin, mask);\n}\n\n\n// Return the state of a margin's sensitivity.\nbool QsciScintilla::marginSensitivity(int margin) const\n{\n    return SendScintilla(SCI_GETMARGINSENSITIVEN, margin);\n}\n\n\n// Enable and disable a margin's sensitivity.\nvoid QsciScintilla::setMarginSensitivity(int margin,bool sens)\n{\n    SendScintilla(SCI_SETMARGINSENSITIVEN, margin, sens);\n}\n\n\n// Return the width of a margin.\nint QsciScintilla::marginWidth(int margin) const\n{\n    return SendScintilla(SCI_GETMARGINWIDTHN, margin);\n}\n\n\n// Set the width of a margin.\nvoid QsciScintilla::setMarginWidth(int margin, int width)\n{\n    SendScintilla(SCI_SETMARGINWIDTHN, margin, width);\n}\n\n\n// Set the width of a margin to the width of some text.\nvoid QsciScintilla::setMarginWidth(int margin, const QString &s)\n{\n    int width = SendScintilla(SCI_TEXTWIDTH, STYLE_LINENUMBER,\n            textAsBytes(s).constData());\n\n    setMarginWidth(margin, width);\n}\n\n\n// Set the background colour of all margins.\nvoid QsciScintilla::setMarginsBackgroundColor(const QColor &col)\n{\n    handleStylePaperChange(col, STYLE_LINENUMBER);\n}\n\n\n// Set the foreground colour of all margins.\nvoid QsciScintilla::setMarginsForegroundColor(const QColor &col)\n{\n    handleStyleColorChange(col, STYLE_LINENUMBER);\n}\n\n\n// Set the font of all margins.\nvoid QsciScintilla::setMarginsFont(const QFont &f)\n{\n    setStylesFont(f, STYLE_LINENUMBER);\n}\n\n\n// Define an indicator.\nint QsciScintilla::indicatorDefine(IndicatorStyle style, int indicatorNumber)\n{\n    checkIndicator(indicatorNumber);\n\n    if (indicatorNumber >= 0)\n        SendScintilla(SCI_INDICSETSTYLE, indicatorNumber,\n                static_cast<long>(style));\n\n    return indicatorNumber;\n}\n\n\n// Return the state of an indicator being drawn under the text.\nbool QsciScintilla::indicatorDrawUnder(int indicatorNumber) const\n{\n    if (indicatorNumber < 0 || indicatorNumber >= INDIC_IME)\n        return false;\n\n    return SendScintilla(SCI_INDICGETUNDER, indicatorNumber);\n}\n\n\n// Set the state of indicators being drawn under the text.\nvoid QsciScintilla::setIndicatorDrawUnder(bool under, int indicatorNumber)\n{\n    if (indicatorNumber < INDIC_IME)\n    {\n        // We ignore allocatedIndicators to allow any indicators defined\n        // elsewhere (e.g. in lexers) to be set.\n        if (indicatorNumber < 0)\n        {\n            for (int i = 0; i < INDIC_IME; ++i)\n                SendScintilla(SCI_INDICSETUNDER, i, under);\n        }\n        else\n        {\n            SendScintilla(SCI_INDICSETUNDER, indicatorNumber, under);\n        }\n    }\n}\n\n\n// Set the indicator foreground colour.\nvoid QsciScintilla::setIndicatorForegroundColor(const QColor &col,\n        int indicatorNumber)\n{\n    if (indicatorNumber < INDIC_IME)\n    {\n        int alpha = col.alpha();\n\n        // We ignore allocatedIndicators to allow any indicators defined\n        // elsewhere (e.g. in lexers) to be set.\n        if (indicatorNumber < 0)\n        {\n            for (int i = 0; i < INDIC_IME; ++i)\n            {\n                SendScintilla(SCI_INDICSETFORE, i, col);\n                SendScintilla(SCI_INDICSETALPHA, i, alpha);\n            }\n        }\n        else\n        {\n            SendScintilla(SCI_INDICSETFORE, indicatorNumber, col);\n            SendScintilla(SCI_INDICSETALPHA, indicatorNumber, alpha);\n        }\n    }\n}\n\n\n// Set the indicator hover foreground colour.\nvoid QsciScintilla::setIndicatorHoverForegroundColor(const QColor &col,\n        int indicatorNumber)\n{\n    if (indicatorNumber < INDIC_IME)\n    {\n        // We ignore allocatedIndicators to allow any indicators defined\n        // elsewhere (e.g. in lexers) to be set.\n        if (indicatorNumber < 0)\n        {\n            for (int i = 0; i < INDIC_IME; ++i)\n                SendScintilla(SCI_INDICSETHOVERFORE, i, col);\n        }\n        else\n        {\n            SendScintilla(SCI_INDICSETHOVERFORE, indicatorNumber, col);\n        }\n    }\n}\n\n\n// Set the indicator hover style.\nvoid QsciScintilla::setIndicatorHoverStyle(IndicatorStyle style,\n        int indicatorNumber)\n{\n    if (indicatorNumber < INDIC_IME)\n    {\n        // We ignore allocatedIndicators to allow any indicators defined\n        // elsewhere (e.g. in lexers) to be set.\n        if (indicatorNumber < 0)\n        {\n            for (int i = 0; i < INDIC_IME; ++i)\n                SendScintilla(SCI_INDICSETHOVERSTYLE, i,\n                        static_cast<long>(style));\n        }\n        else\n        {\n            SendScintilla(SCI_INDICSETHOVERSTYLE, indicatorNumber,\n                    static_cast<long>(style));\n        }\n    }\n}\n\n\n// Set the indicator outline colour.\nvoid QsciScintilla::setIndicatorOutlineColor(const QColor &col, int indicatorNumber)\n{\n    if (indicatorNumber < INDIC_IME)\n    {\n        int alpha = col.alpha();\n\n        // We ignore allocatedIndicators to allow any indicators defined\n        // elsewhere (e.g. in lexers) to be set.\n        if (indicatorNumber < 0)\n        {\n            for (int i = 0; i < INDIC_IME; ++i)\n                SendScintilla(SCI_INDICSETOUTLINEALPHA, i, alpha);\n        }\n        else\n        {\n            SendScintilla(SCI_INDICSETOUTLINEALPHA, indicatorNumber, alpha);\n        }\n    }\n}\n\n\n// Fill a range with an indicator.\nvoid QsciScintilla::fillIndicatorRange(int lineFrom, int indexFrom,\n        int lineTo, int indexTo, int indicatorNumber)\n{\n    if (indicatorNumber < INDIC_IME)\n    {\n        int start = positionFromLineIndex(lineFrom, indexFrom);\n        int finish = positionFromLineIndex(lineTo, indexTo);\n\n        // We ignore allocatedIndicators to allow any indicators defined\n        // elsewhere (e.g. in lexers) to be set.\n        if (indicatorNumber < 0)\n        {\n            for (int i = 0; i < INDIC_IME; ++i)\n            {\n                SendScintilla(SCI_SETINDICATORCURRENT, i);\n                SendScintilla(SCI_INDICATORFILLRANGE, start, finish - start);\n            }\n        }\n        else\n        {\n            SendScintilla(SCI_SETINDICATORCURRENT, indicatorNumber);\n            SendScintilla(SCI_INDICATORFILLRANGE, start, finish - start);\n        }\n    }\n}\n\n\n// Clear a range with an indicator.\nvoid QsciScintilla::clearIndicatorRange(int lineFrom, int indexFrom,\n        int lineTo, int indexTo, int indicatorNumber)\n{\n    if (indicatorNumber < INDIC_IME)\n    {\n        int start = positionFromLineIndex(lineFrom, indexFrom);\n        int finish = positionFromLineIndex(lineTo, indexTo);\n\n        // We ignore allocatedIndicators to allow any indicators defined\n        // elsewhere (e.g. in lexers) to be set.\n        if (indicatorNumber < 0)\n        {\n            for (int i = 0; i < INDIC_IME; ++i)\n            {\n                SendScintilla(SCI_SETINDICATORCURRENT, i);\n                SendScintilla(SCI_INDICATORCLEARRANGE, start, finish - start);\n            }\n        }\n        else\n        {\n            SendScintilla(SCI_SETINDICATORCURRENT, indicatorNumber);\n            SendScintilla(SCI_INDICATORCLEARRANGE, start, finish - start);\n        }\n    }\n}\n\n\n// Define a marker based on a symbol.\nint QsciScintilla::markerDefine(MarkerSymbol sym, int markerNumber)\n{\n    checkMarker(markerNumber);\n\n    if (markerNumber >= 0)\n        SendScintilla(SCI_MARKERDEFINE, markerNumber, static_cast<long>(sym));\n\n    return markerNumber;\n}\n\n\n// Define a marker based on a character.\nint QsciScintilla::markerDefine(char ch, int markerNumber)\n{\n    checkMarker(markerNumber);\n\n    if (markerNumber >= 0)\n        SendScintilla(SCI_MARKERDEFINE, markerNumber,\n                static_cast<long>(SC_MARK_CHARACTER) + ch);\n\n    return markerNumber;\n}\n\n\n// Define a marker based on a QPixmap.\nint QsciScintilla::markerDefine(const QPixmap &pm, int markerNumber)\n{\n    checkMarker(markerNumber);\n\n    if (markerNumber >= 0)\n        SendScintilla(SCI_MARKERDEFINEPIXMAP, markerNumber, pm);\n\n    return markerNumber;\n}\n\n\n// Define a marker based on a QImage.\nint QsciScintilla::markerDefine(const QImage &im, int markerNumber)\n{\n    checkMarker(markerNumber);\n\n    if (markerNumber >= 0)\n    {\n        SendScintilla(SCI_RGBAIMAGESETHEIGHT, im.height());\n        SendScintilla(SCI_RGBAIMAGESETWIDTH, im.width());\n        SendScintilla(SCI_MARKERDEFINERGBAIMAGE, markerNumber, im);\n    }\n\n    return markerNumber;\n}\n\n\n// Add a marker to a line.\nint QsciScintilla::markerAdd(int linenr, int markerNumber)\n{\n    if (markerNumber < 0 || markerNumber > MARKER_MAX || (allocatedMarkers & (1 << markerNumber)) == 0)\n        return -1;\n\n    return SendScintilla(SCI_MARKERADD, linenr, markerNumber);\n}\n\n\n// Get the marker mask for a line.\nunsigned QsciScintilla::markersAtLine(int linenr) const\n{\n    return SendScintilla(SCI_MARKERGET, linenr);\n}\n\n\n// Delete a marker from a line.\nvoid QsciScintilla::markerDelete(int linenr, int markerNumber)\n{\n    if (markerNumber <= MARKER_MAX)\n    {\n        if (markerNumber < 0)\n        {\n            unsigned am = allocatedMarkers;\n\n            for (int m = 0; m <= MARKER_MAX; ++m)\n            {\n                if (am & 1)\n                    SendScintilla(SCI_MARKERDELETE, linenr, m);\n\n                am >>= 1;\n            }\n        }\n        else if (allocatedMarkers & (1 << markerNumber))\n            SendScintilla(SCI_MARKERDELETE, linenr, markerNumber);\n    }\n}\n\n\n// Delete a marker from the text.\nvoid QsciScintilla::markerDeleteAll(int markerNumber)\n{\n    if (markerNumber <= MARKER_MAX)\n    {\n        if (markerNumber < 0)\n            SendScintilla(SCI_MARKERDELETEALL, -1);\n        else if (allocatedMarkers & (1 << markerNumber))\n            SendScintilla(SCI_MARKERDELETEALL, markerNumber);\n    }\n}\n\n\n// Delete a marker handle from the text.\nvoid QsciScintilla::markerDeleteHandle(int mhandle)\n{\n    SendScintilla(SCI_MARKERDELETEHANDLE, mhandle);\n}\n\n\n// Return the line containing a marker instance.\nint QsciScintilla::markerLine(int mhandle) const\n{\n    return SendScintilla(SCI_MARKERLINEFROMHANDLE, mhandle);\n}\n\n\n// Search forwards for a marker.\nint QsciScintilla::markerFindNext(int linenr, unsigned mask) const\n{\n    return SendScintilla(SCI_MARKERNEXT, linenr, mask);\n}\n\n\n// Search backwards for a marker.\nint QsciScintilla::markerFindPrevious(int linenr, unsigned mask) const\n{\n    return SendScintilla(SCI_MARKERPREVIOUS, linenr, mask);\n}\n\n\n// Set the marker background colour.\nvoid QsciScintilla::setMarkerBackgroundColor(const QColor &col, int markerNumber)\n{\n    if (markerNumber <= MARKER_MAX)\n    {\n        int alpha = col.alpha();\n\n        // An opaque background would make the text invisible.\n        if (alpha == 255)\n            alpha = SC_ALPHA_NOALPHA;\n\n        if (markerNumber < 0)\n        {\n            unsigned am = allocatedMarkers;\n\n            for (int m = 0; m <= MARKER_MAX; ++m)\n            {\n                if (am & 1)\n                {\n                    SendScintilla(SCI_MARKERSETBACK, m, col);\n                    SendScintilla(SCI_MARKERSETALPHA, m, alpha);\n                }\n\n                am >>= 1;\n            }\n        }\n        else if (allocatedMarkers & (1 << markerNumber))\n        {\n            SendScintilla(SCI_MARKERSETBACK, markerNumber, col);\n            SendScintilla(SCI_MARKERSETALPHA, markerNumber, alpha);\n        }\n    }\n}\n\n\n// Set the marker foreground colour.\nvoid QsciScintilla::setMarkerForegroundColor(const QColor &col, int markerNumber)\n{\n    if (markerNumber <= MARKER_MAX)\n    {\n        if (markerNumber < 0)\n        {\n            unsigned am = allocatedMarkers;\n\n            for (int m = 0; m <= MARKER_MAX; ++m)\n            {\n                if (am & 1)\n                    SendScintilla(SCI_MARKERSETFORE, m, col);\n\n                am >>= 1;\n            }\n        }\n        else if (allocatedMarkers & (1 << markerNumber))\n        {\n            SendScintilla(SCI_MARKERSETFORE, markerNumber, col);\n        }\n    }\n}\n\n\n// Check a marker, allocating a marker number if necessary.\nvoid QsciScintilla::checkMarker(int &markerNumber)\n{\n    allocateId(markerNumber, allocatedMarkers, 0, MARKER_MAX);\n}\n\n\n// Check an indicator, allocating an indicator number if necessary.\nvoid QsciScintilla::checkIndicator(int &indicatorNumber)\n{\n    allocateId(indicatorNumber, allocatedIndicators, INDIC_CONTAINER,\n            INDIC_IME - 1);\n}\n\n\n// Make sure an identifier is valid and allocate it if necessary.\nvoid QsciScintilla::allocateId(int &id, unsigned &allocated, int min, int max)\n{\n    if (id >= 0)\n    {\n        // Note that we allow existing identifiers to be explicitly redefined.\n        if (id > max)\n            id = -1;\n    }\n    else\n    {\n        unsigned aids = allocated >> min;\n\n        // Find the smallest unallocated identifier.\n        for (id = min; id <= max; ++id)\n        {\n            if ((aids & 1) == 0)\n                break;\n\n            aids >>= 1;\n        }\n    }\n\n    // Allocate the identifier if it is valid.\n    if (id >= 0)\n        allocated |= (1 << id);\n}\n\n\n// Reset the fold margin colours.\nvoid QsciScintilla::resetFoldMarginColors()\n{\n    SendScintilla(SCI_SETFOLDMARGINHICOLOUR, 0, 0L);\n    SendScintilla(SCI_SETFOLDMARGINCOLOUR, 0, 0L);\n}\n\n\n// Set the fold margin colours.\nvoid QsciScintilla::setFoldMarginColors(const QColor &fore, const QColor &back)\n{\n    SendScintilla(SCI_SETFOLDMARGINHICOLOUR, 1, fore);\n    SendScintilla(SCI_SETFOLDMARGINCOLOUR, 1, back);\n}\n\n\n// Set the call tips background colour.\nvoid QsciScintilla::setCallTipsBackgroundColor(const QColor &col)\n{\n    SendScintilla(SCI_CALLTIPSETBACK, col);\n}\n\n\n// Set the call tips foreground colour.\nvoid QsciScintilla::setCallTipsForegroundColor(const QColor &col)\n{\n    SendScintilla(SCI_CALLTIPSETFORE, col);\n}\n\n\n// Set the call tips highlight colour.\nvoid QsciScintilla::setCallTipsHighlightColor(const QColor &col)\n{\n    SendScintilla(SCI_CALLTIPSETFOREHLT, col);\n}\n\n\n// Set the matched brace background colour.\nvoid QsciScintilla::setMatchedBraceBackgroundColor(const QColor &col)\n{\n    SendScintilla(SCI_STYLESETBACK, STYLE_BRACELIGHT, col);\n}\n\n\n// Set the matched brace foreground colour.\nvoid QsciScintilla::setMatchedBraceForegroundColor(const QColor &col)\n{\n    SendScintilla(SCI_STYLESETFORE, STYLE_BRACELIGHT, col);\n}\n\n\n// Set the matched brace indicator.\nvoid QsciScintilla::setMatchedBraceIndicator(int indicatorNumber)\n{\n    SendScintilla(SCI_BRACEHIGHLIGHTINDICATOR, 1, indicatorNumber);\n}\n\n\n// Reset the matched brace indicator.\nvoid QsciScintilla::resetMatchedBraceIndicator()\n{\n    SendScintilla(SCI_BRACEHIGHLIGHTINDICATOR, 0, 0L);\n}\n\n\n// Set the unmatched brace background colour.\nvoid QsciScintilla::setUnmatchedBraceBackgroundColor(const QColor &col)\n{\n    SendScintilla(SCI_STYLESETBACK, STYLE_BRACEBAD, col);\n}\n\n\n// Set the unmatched brace foreground colour.\nvoid QsciScintilla::setUnmatchedBraceForegroundColor(const QColor &col)\n{\n    SendScintilla(SCI_STYLESETFORE, STYLE_BRACEBAD, col);\n}\n\n\n// Set the unmatched brace indicator.\nvoid QsciScintilla::setUnmatchedBraceIndicator(int indicatorNumber)\n{\n    SendScintilla(SCI_BRACEBADLIGHTINDICATOR, 1, indicatorNumber);\n}\n\n\n// Reset the unmatched brace indicator.\nvoid QsciScintilla::resetUnmatchedBraceIndicator()\n{\n    SendScintilla(SCI_BRACEBADLIGHTINDICATOR, 0, 0L);\n}\n\n\n// Detach any lexer.\nvoid QsciScintilla::detachLexer()\n{\n    if (!lex.isNull())\n    {\n        lex->setEditor(0);\n        lex->disconnect(this);\n\n        SendScintilla(SCI_STYLERESETDEFAULT);\n        SendScintilla(SCI_STYLECLEARALL);\n    }\n}\n\n\n// Set the lexer.\nvoid QsciScintilla::setLexer(QsciLexer *lexer)\n{\n    // Detach any current lexer.\n    detachLexer();\n\n    // Connect up the new lexer.\n    lex = lexer;\n\n    if (lex)\n    {\n        SendScintilla(SCI_CLEARDOCUMENTSTYLE);\n\n        if (lex->lexer())\n            SendScintilla(SCI_SETLEXERLANGUAGE, lex->lexer());\n        else\n            SendScintilla(SCI_SETLEXER, lex->lexerId());\n\n        lex->setEditor(this);\n\n        connect(lex,SIGNAL(colorChanged(const QColor &, int)),\n                SLOT(handleStyleColorChange(const QColor &, int)));\n        connect(lex,SIGNAL(eolFillChanged(bool, int)),\n                SLOT(handleStyleEolFillChange(bool, int)));\n        connect(lex,SIGNAL(fontChanged(const QFont &, int)),\n                SLOT(handleStyleFontChange(const QFont &, int)));\n        connect(lex,SIGNAL(paperChanged(const QColor &, int)),\n                SLOT(handleStylePaperChange(const QColor &, int)));\n        connect(lex,SIGNAL(propertyChanged(const char *, const char *)),\n                SLOT(handlePropertyChange(const char *, const char *)));\n\n        SendScintilla(SCI_SETPROPERTY, \"fold\", \"1\");\n        SendScintilla(SCI_SETPROPERTY, \"fold.html\", \"1\");\n\n        // Set the keywords.  Scintilla allows for sets numbered 0 to\n        // KEYWORDSET_MAX (although the lexers only seem to exploit 0 to\n        // KEYWORDSET_MAX - 1).  We number from 1 in line with SciTE's property\n        // files.\n        for (int k = 0; k <= KEYWORDSET_MAX; ++k)\n        {\n            const char *kw = lex -> keywords(k + 1);\n\n            if (!kw)\n                kw = \"\";\n\n            SendScintilla(SCI_SETKEYWORDS, k, kw);\n        }\n\n        // Initialise each style.  Do the default first so its (possibly\n        // incorrect) font setting gets reset when style 0 is set.\n        setLexerStyle(STYLE_DEFAULT);\n\n        for (int s = 0; s <= STYLE_MAX; ++s)\n            if (!lex->description(s).isEmpty())\n                setLexerStyle(s);\n\n        // Initialise the properties.\n        lex->refreshProperties();\n\n        // Set the auto-completion fillups and word separators.\n        setAutoCompletionFillupsEnabled(fillups_enabled);\n        wseps = lex->autoCompletionWordSeparators();\n\n        wchars = lex->wordCharacters();\n\n        if (!wchars)\n            wchars = defaultWordChars;\n\n        SendScintilla(SCI_AUTOCSETIGNORECASE, !lex->caseSensitive());\n\n        recolor();\n    }\n    else\n    {\n        SendScintilla(SCI_SETLEXER, SCLEX_CONTAINER);\n\n        setColor(nl_text_colour);\n        setPaper(nl_paper_colour);\n\n        SendScintilla(SCI_AUTOCSETFILLUPS, \"\");\n        SendScintilla(SCI_AUTOCSETIGNORECASE, false);\n        wseps.clear();\n        wchars = defaultWordChars;\n    }\n}\n\n\n// Set a particular style of the current lexer.\nvoid QsciScintilla::setLexerStyle(int style)\n{\n    handleStyleColorChange(lex->color(style), style);\n    handleStyleEolFillChange(lex->eolFill(style), style);\n    handleStyleFontChange(lex->font(style), style);\n    handleStylePaperChange(lex->paper(style), style);\n}\n\n\n// Get the current lexer.\nQsciLexer *QsciScintilla::lexer() const\n{\n    return lex;\n}\n\n\n// Handle a change in lexer style foreground colour.\nvoid QsciScintilla::handleStyleColorChange(const QColor &c, int style)\n{\n    SendScintilla(SCI_STYLESETFORE, style, c);\n}\n\n\n// Handle a change in lexer style end-of-line fill.\nvoid QsciScintilla::handleStyleEolFillChange(bool eolfill, int style)\n{\n    SendScintilla(SCI_STYLESETEOLFILLED, style, eolfill);\n}\n\n\n// Handle a change in lexer style font.\nvoid QsciScintilla::handleStyleFontChange(const QFont &f, int style)\n{\n    setStylesFont(f, style);\n\n    if (style == lex->braceStyle())\n    {\n        setStylesFont(f, STYLE_BRACELIGHT);\n        setStylesFont(f, STYLE_BRACEBAD);\n    }\n}\n\n\n// Set the font for a style.\nvoid QsciScintilla::setStylesFont(const QFont &f, int style)\n{\n    SendScintilla(SCI_STYLESETFONT, style, f.family().toLatin1().data());\n    SendScintilla(SCI_STYLESETSIZEFRACTIONAL, style,\n            long(f.pointSizeF() * SC_FONT_SIZE_MULTIPLIER));\n\n    // Pass the Qt weight via the back door.\n    SendScintilla(SCI_STYLESETWEIGHT, style, -f.weight());\n\n    SendScintilla(SCI_STYLESETITALIC, style, f.italic());\n    SendScintilla(SCI_STYLESETUNDERLINE, style, f.underline());\n\n    // Tie the font settings of the default style to that of style 0 (the style\n    // conventionally used for whitespace by lexers).  This is needed so that\n    // fold marks, indentations, edge columns etc are set properly.\n    if (style == 0)\n        setStylesFont(f, STYLE_DEFAULT);\n}\n\n\n// Handle a change in lexer style background colour.\nvoid QsciScintilla::handleStylePaperChange(const QColor &c, int style)\n{\n    SendScintilla(SCI_STYLESETBACK, style, c);\n}\n\n\n// Handle a change in lexer property.\nvoid QsciScintilla::handlePropertyChange(const char *prop, const char *val)\n{\n    SendScintilla(SCI_SETPROPERTY, prop, val);\n}\n\n\n// Handle a change to the user visible user interface.\nvoid QsciScintilla::handleUpdateUI(int)\n{\n    int newPos = SendScintilla(SCI_GETCURRENTPOS);\n\n    if (newPos != oldPos)\n    {\n        oldPos = newPos;\n\n        int line = SendScintilla(SCI_LINEFROMPOSITION, newPos);\n        int col = SendScintilla(SCI_GETCOLUMN, newPos);\n\n        emit cursorPositionChanged(line, col);\n    }\n\n    if (braceMode != NoBraceMatch)\n        braceMatch();\n}\n\n\n// Handle brace matching.\nvoid QsciScintilla::braceMatch()\n{\n    long braceAtCaret, braceOpposite;\n\n    findMatchingBrace(braceAtCaret, braceOpposite, braceMode);\n\n    if (braceAtCaret >= 0 && braceOpposite < 0)\n    {\n        SendScintilla(SCI_BRACEBADLIGHT, braceAtCaret);\n        SendScintilla(SCI_SETHIGHLIGHTGUIDE, 0UL);\n    }\n    else\n    {\n        char chBrace = SendScintilla(SCI_GETCHARAT, braceAtCaret);\n\n        SendScintilla(SCI_BRACEHIGHLIGHT, braceAtCaret, braceOpposite);\n\n        long columnAtCaret = SendScintilla(SCI_GETCOLUMN, braceAtCaret);\n        long columnOpposite = SendScintilla(SCI_GETCOLUMN, braceOpposite);\n\n        if (chBrace == ':')\n        {\n            long lineStart = SendScintilla(SCI_LINEFROMPOSITION, braceAtCaret);\n            long indentPos = SendScintilla(SCI_GETLINEINDENTPOSITION,\n                    lineStart);\n            long indentPosNext = SendScintilla(SCI_GETLINEINDENTPOSITION,\n                    lineStart + 1);\n\n            columnAtCaret = SendScintilla(SCI_GETCOLUMN, indentPos);\n\n            long columnAtCaretNext = SendScintilla(SCI_GETCOLUMN,\n                    indentPosNext);\n            long indentSize = SendScintilla(SCI_GETINDENT);\n\n            if (columnAtCaretNext - indentSize > 1)\n                columnAtCaret = columnAtCaretNext - indentSize;\n\n            if (columnOpposite == 0)\n                columnOpposite = columnAtCaret;\n        }\n\n        long column = columnAtCaret;\n\n        if (column > columnOpposite)\n            column = columnOpposite;\n\n        SendScintilla(SCI_SETHIGHLIGHTGUIDE, column);\n    }\n}\n\n\n// Check if the character at a position is a brace.\nlong QsciScintilla::checkBrace(long pos, int brace_style, bool &colonMode)\n{\n    long brace_pos = -1;\n    char ch = SendScintilla(SCI_GETCHARAT, pos);\n\n    if (ch == ':')\n    {\n        // A bit of a hack, we should really use a virtual.\n        if (!lex.isNull() && qstrcmp(lex->lexer(), \"python\") == 0)\n        {\n            brace_pos = pos;\n            colonMode = true;\n        }\n    }\n    else if (ch && strchr(\"[](){}<>\", ch))\n    {\n        if (brace_style < 0)\n            brace_pos = pos;\n        else\n        {\n            int style = SendScintilla(SCI_GETSTYLEAT, pos) & 0x1f;\n\n            if (style == brace_style)\n                brace_pos = pos;\n        }\n    }\n\n    return brace_pos;\n}\n\n\n// Find a brace and it's match.  Return true if the current position is inside\n// a pair of braces.\nbool QsciScintilla::findMatchingBrace(long &brace, long &other, BraceMatch mode)\n{\n    bool colonMode = false;\n    int brace_style = (lex.isNull() ? -1 : lex->braceStyle());\n\n    brace = -1;\n    other = -1;\n\n    long caretPos = SendScintilla(SCI_GETCURRENTPOS);\n\n    if (caretPos > 0)\n        brace = checkBrace(caretPos - 1, brace_style, colonMode);\n\n    bool isInside = false;\n\n    if (brace < 0 && mode == SloppyBraceMatch)\n    {\n        brace = checkBrace(caretPos, brace_style, colonMode);\n\n        if (brace >= 0 && !colonMode)\n            isInside = true;\n    }\n\n    if (brace >= 0)\n    {\n        if (colonMode)\n        {\n            // Find the end of the Python indented block.\n            long lineStart = SendScintilla(SCI_LINEFROMPOSITION, brace);\n            long lineMaxSubord = SendScintilla(SCI_GETLASTCHILD, lineStart, -1);\n\n            other = SendScintilla(SCI_GETLINEENDPOSITION, lineMaxSubord);\n        }\n        else\n            other = SendScintilla(SCI_BRACEMATCH, brace, 0L);\n\n        if (other > brace)\n            isInside = !isInside;\n    }\n\n    return isInside;\n}\n\n\n// Move to the matching brace.\nvoid QsciScintilla::moveToMatchingBrace()\n{\n    gotoMatchingBrace(false);\n}\n\n\n// Select to the matching brace.\nvoid QsciScintilla::selectToMatchingBrace()\n{\n    gotoMatchingBrace(true);\n}\n\n\n// Move to the matching brace and optionally select the text.\nvoid QsciScintilla::gotoMatchingBrace(bool select)\n{\n    long braceAtCaret;\n    long braceOpposite;\n\n    bool isInside = findMatchingBrace(braceAtCaret, braceOpposite,\n            SloppyBraceMatch);\n\n    if (braceOpposite >= 0)\n    {\n        // Convert the character positions into caret positions based on\n        // whether the caret position was inside or outside the braces.\n        if (isInside)\n        {\n            if (braceOpposite > braceAtCaret)\n                braceAtCaret++;\n            else\n                braceOpposite++;\n        }\n        else\n        {\n            if (braceOpposite > braceAtCaret)\n                braceOpposite++;\n            else\n                braceAtCaret++;\n        }\n\n        ensureLineVisible(SendScintilla(SCI_LINEFROMPOSITION, braceOpposite));\n\n        if (select)\n            SendScintilla(SCI_SETSEL, braceAtCaret, braceOpposite);\n        else\n            SendScintilla(SCI_SETSEL, braceOpposite, braceOpposite);\n    }\n}\n\n\n// Return a position from a line number and an index within the line.\nint QsciScintilla::positionFromLineIndex(int line, int index) const\n{\n    int pos = SendScintilla(SCI_POSITIONFROMLINE, line);\n\n    // Allow for multi-byte characters.\n    for(int i = 0; i < index; i++)\n        pos = SendScintilla(SCI_POSITIONAFTER, pos);\n\n    return pos;\n}\n\n\n// Return a line number and an index within the line from a position.\nvoid QsciScintilla::lineIndexFromPosition(int position, int *line, int *index) const\n{\n    int lin = SendScintilla(SCI_LINEFROMPOSITION, position);\n    int linpos = SendScintilla(SCI_POSITIONFROMLINE, lin);\n    int indx = 0;\n\n    // Allow for multi-byte characters.\n    while (linpos < position)\n    {\n        int new_linpos = SendScintilla(SCI_POSITIONAFTER, linpos);\n\n        // If the position hasn't moved then we must be at the end of the text\n        // (which implies that the position passed was beyond the end of the\n        // text).\n        if (new_linpos == linpos)\n            break;\n\n        linpos = new_linpos;\n        ++indx;\n    }\n\n    *line = lin;\n    *index = indx;\n}\n\n\n// Set the source of the automatic auto-completion list.\nvoid QsciScintilla::setAutoCompletionSource(AutoCompletionSource source)\n{\n    acSource = source;\n}\n\n\n// Set the threshold for automatic auto-completion.\nvoid QsciScintilla::setAutoCompletionThreshold(int thresh)\n{\n    acThresh = thresh;\n}\n\n\n// Set the auto-completion word separators if there is no current lexer.\nvoid QsciScintilla::setAutoCompletionWordSeparators(const QStringList &separators)\n{\n    if (lex.isNull())\n        wseps = separators;\n}\n\n\n// Explicitly auto-complete from all sources.\nvoid QsciScintilla::autoCompleteFromAll()\n{\n    startAutoCompletion(AcsAll, false, use_single != AcusNever);\n}\n\n\n// Explicitly auto-complete from the APIs.\nvoid QsciScintilla::autoCompleteFromAPIs()\n{\n    startAutoCompletion(AcsAPIs, false, use_single != AcusNever);\n}\n\n\n// Explicitly auto-complete from the document.\nvoid QsciScintilla::autoCompleteFromDocument()\n{\n    startAutoCompletion(AcsDocument, false, use_single != AcusNever);\n}\n\n\n// Check if a character can be in a word.\nbool QsciScintilla::isWordCharacter(char ch) const\n{\n    return (strchr(wchars, ch) != NULL);\n}\n\n\n// Return the set of valid word characters.\nconst char *QsciScintilla::wordCharacters() const\n{\n    return wchars;\n}\n\n\n// Recolour the document.\nvoid QsciScintilla::recolor(int start, int end)\n{\n    SendScintilla(SCI_COLOURISE, start, end);\n}\n\n\n// Registered a QPixmap image.\nvoid QsciScintilla::registerImage(int id, const QPixmap &pm)\n{\n    SendScintilla(SCI_REGISTERIMAGE, id, pm);\n}\n\n\n// Registered a QImage image.\nvoid QsciScintilla::registerImage(int id, const QImage &im)\n{\n    SendScintilla(SCI_RGBAIMAGESETHEIGHT, im.height());\n    SendScintilla(SCI_RGBAIMAGESETWIDTH, im.width());\n    SendScintilla(SCI_REGISTERRGBAIMAGE, id, im);\n}\n\n\n// Clear all registered images.\nvoid QsciScintilla::clearRegisteredImages()\n{\n    SendScintilla(SCI_CLEARREGISTEREDIMAGES);\n}\n\n\n// Enable auto-completion fill-ups.\nvoid QsciScintilla::setAutoCompletionFillupsEnabled(bool enable)\n{\n    const char *fillups;\n\n    if (!enable)\n        fillups = \"\";\n    else if (!lex.isNull())\n        fillups = lex->autoCompletionFillups();\n    else\n        fillups = explicit_fillups.data();\n\n    SendScintilla(SCI_AUTOCSETFILLUPS, fillups);\n\n    fillups_enabled = enable;\n}\n\n\n// See if auto-completion fill-ups are enabled.\nbool QsciScintilla::autoCompletionFillupsEnabled() const\n{\n    return fillups_enabled;\n}\n\n\n// Set the fill-up characters for auto-completion if there is no current lexer.\nvoid QsciScintilla::setAutoCompletionFillups(const char *fillups)\n{\n    explicit_fillups = fillups;\n    setAutoCompletionFillupsEnabled(fillups_enabled);\n}\n\n\n// Set the case sensitivity for auto-completion.\nvoid QsciScintilla::setAutoCompletionCaseSensitivity(bool cs)\n{\n    SendScintilla(SCI_AUTOCSETIGNORECASE, !cs);\n}\n\n\n// Return the case sensitivity for auto-completion.\nbool QsciScintilla::autoCompletionCaseSensitivity() const\n{\n    return !SendScintilla(SCI_AUTOCGETIGNORECASE);\n}\n\n\n// Set the replace word mode for auto-completion.\nvoid QsciScintilla::setAutoCompletionReplaceWord(bool replace)\n{\n    SendScintilla(SCI_AUTOCSETDROPRESTOFWORD, replace);\n}\n\n\n// Return the replace word mode for auto-completion.\nbool QsciScintilla::autoCompletionReplaceWord() const\n{\n    return SendScintilla(SCI_AUTOCGETDROPRESTOFWORD);\n}\n\n\n// Set the single item mode for auto-completion.\nvoid QsciScintilla::setAutoCompletionUseSingle(AutoCompletionUseSingle single)\n{\n    use_single = single;\n}\n\n\n// Return the single item mode for auto-completion.\nQsciScintilla::AutoCompletionUseSingle QsciScintilla::autoCompletionUseSingle() const\n{\n    return use_single;\n}\n\n\n// Set the single item mode for auto-completion (deprecated).\nvoid QsciScintilla::setAutoCompletionShowSingle(bool single)\n{\n    use_single = (single ? AcusExplicit : AcusNever);\n}\n\n\n// Return the single item mode for auto-completion (deprecated).\nbool QsciScintilla::autoCompletionShowSingle() const\n{\n    return (use_single != AcusNever);\n}\n\n\n// Set current call tip position.\nvoid QsciScintilla::setCallTipsPosition(CallTipsPosition position)\n{\n    SendScintilla(SCI_CALLTIPSETPOSITION, (position == CallTipsAboveText));\n    call_tips_position = position;\n}\n\n\n// Set current call tip style.\nvoid QsciScintilla::setCallTipsStyle(CallTipsStyle style)\n{\n    call_tips_style = style;\n}\n\n\n// Set maximum number of call tips displayed.\nvoid QsciScintilla::setCallTipsVisible(int nr)\n{\n    maxCallTips = nr;\n}\n\n\n// Set the document to display.\nvoid QsciScintilla::setDocument(const QsciDocument &document)\n{\n    if (doc.pdoc != document.pdoc)\n    {\n        doc.undisplay(this);\n        doc.attach(document);\n        doc.display(this,&document);\n    }\n}\n\n\n// Ensure the document is read-write and return true if was was read-only.\nbool QsciScintilla::ensureRW()\n{\n    bool ro = isReadOnly();\n\n    if (ro)\n        setReadOnly(false);\n\n    return ro;\n}\n\n\n// Return the number of the first visible line.\nint QsciScintilla::firstVisibleLine() const\n{\n    return SendScintilla(SCI_GETFIRSTVISIBLELINE);\n}\n\n\n// Set the number of the first visible line.\nvoid QsciScintilla::setFirstVisibleLine(int linenr)\n{\n    SendScintilla(SCI_SETFIRSTVISIBLELINE, linenr);\n}\n\n\n// Return the height in pixels of the text in a particular line.\nint QsciScintilla::textHeight(int linenr) const\n{\n    return SendScintilla(SCI_TEXTHEIGHT, linenr);\n}\n\n\n// See if auto-completion or user list is active.\nbool QsciScintilla::isListActive() const\n{\n    return SendScintilla(SCI_AUTOCACTIVE);\n}\n\n\n// Cancel any current auto-completion or user list.\nvoid QsciScintilla::cancelList()\n{\n    SendScintilla(SCI_AUTOCCANCEL);\n}\n\n\n// Handle a selection from the auto-completion list.\nvoid QsciScintilla::handleAutoCompletionSelection()\n{\n    if (!lex.isNull())\n    {\n        QsciAbstractAPIs *apis = lex->apis();\n\n        if (apis)\n            apis->autoCompletionSelected(acSelection);\n    }\n}\n\n\n// Display a user list.\nvoid QsciScintilla::showUserList(int id, const QStringList &list)\n{\n    // Sanity check to make sure auto-completion doesn't get confused.\n    if (id <= 0)\n        return;\n\n    SendScintilla(SCI_AUTOCSETSEPARATOR, userSeparator);\n\n    SendScintilla(SCI_USERLISTSHOW, id,\n            textAsBytes(list.join(QChar(userSeparator))).constData());\n}\n\n\n// Translate the SCN_USERLISTSELECTION notification into something more useful.\nvoid QsciScintilla::handleUserListSelection(const char *text, int id)\n{\n    emit userListActivated(id, QString(text));\n\n    // Make sure the editor hasn't been deactivated as a side effect.\n    activateWindow();\n}\n\n\n// Return the case sensitivity of any lexer.\nbool QsciScintilla::caseSensitive() const\n{\n    return lex.isNull() ? true : lex->caseSensitive();\n}\n\n\n// Return true if the current list is an auto-completion list rather than a\n// user list.\nbool QsciScintilla::isAutoCompletionList() const\n{\n    return (SendScintilla(SCI_AUTOCGETSEPARATOR) == acSeparator);\n}\n\n\n// Read the text from a QIODevice.\nbool QsciScintilla::read(QIODevice *io)\n{\n    const int min_size = 1024 * 8;\n\n    int buf_size = min_size;\n    char *buf = new char[buf_size];\n\n    int data_len = 0;\n    bool ok = true;\n\n    qint64 part;\n\n    // Read the whole lot in so we don't have to worry about character\n    // boundaries.\n    do\n    {\n        // Make sure there is a minimum amount of room.\n        if (buf_size - data_len < min_size)\n        {\n            buf_size *= 2;\n            char *new_buf = new char[buf_size * 2];\n\n            memcpy(new_buf, buf, data_len);\n            delete[] buf;\n            buf = new_buf;\n        }\n\n        part = io->read(buf + data_len, buf_size - data_len - 1);\n        data_len += part;\n    }\n    while (part > 0);\n\n    if (part < 0)\n        ok = false;\n    else\n    {\n        buf[data_len] = '\\0';\n\n        bool ro = ensureRW();\n\n        SendScintilla(SCI_SETTEXT, buf);\n        SendScintilla(SCI_EMPTYUNDOBUFFER);\n\n        setReadOnly(ro);\n    }\n\n    delete[] buf;\n\n    return ok;\n}\n\n\n// Write the text to a QIODevice.\nbool QsciScintilla::write(QIODevice *io) const\n{\n    const char *buf = reinterpret_cast<const char *>(SendScintillaPtrResult(SCI_GETCHARACTERPOINTER));\n\n    const char *bp = buf;\n    uint buflen = qstrlen(buf);\n\n    while (buflen > 0)\n    {\n        qint64 part = io->write(bp, buflen);\n\n        if (part < 0)\n            return false;\n\n        bp += part;\n        buflen -= part;\n    }\n\n    return true;\n}\n\n\n// Return the word at the given coordinates.\nQString QsciScintilla::wordAtLineIndex(int line, int index) const\n{\n    return wordAtPosition(positionFromLineIndex(line, index));\n}\n\n\n// Return the word at the given coordinates.\nQString QsciScintilla::wordAtPoint(const QPoint &point) const\n{\n    long close_pos = SendScintilla(SCI_POSITIONFROMPOINTCLOSE, point.x(),\n            point.y());\n\n    return wordAtPosition(close_pos);\n}\n\n\n// Return the word at the given position.\nQString QsciScintilla::wordAtPosition(int position) const\n{\n    if (position < 0)\n        return QString();\n\n    long start_pos = SendScintilla(SCI_WORDSTARTPOSITION, position, true);\n    long end_pos = SendScintilla(SCI_WORDENDPOSITION, position, true);\n\n    if (start_pos >= end_pos)\n        return QString();\n\n    return text(start_pos, end_pos);\n}\n\n\n// Return the display style for annotations.\nQsciScintilla::AnnotationDisplay QsciScintilla::annotationDisplay() const\n{\n    return (AnnotationDisplay)SendScintilla(SCI_ANNOTATIONGETVISIBLE);\n}\n\n\n// Set the display style for annotations.\nvoid QsciScintilla::setAnnotationDisplay(QsciScintilla::AnnotationDisplay display)\n{\n    SendScintilla(SCI_ANNOTATIONSETVISIBLE, display);\n    setScrollBars();\n}\n\n\n// Clear annotations.\nvoid QsciScintilla::clearAnnotations(int line)\n{\n    if (line >= 0)\n        SendScintilla(SCI_ANNOTATIONSETTEXT, line, (const char *)0);\n    else\n        SendScintilla(SCI_ANNOTATIONCLEARALL);\n\n    setScrollBars();\n}\n\n\n// Annotate a line.\nvoid QsciScintilla::annotate(int line, const QString &text, int style)\n{\n    int style_offset = SendScintilla(SCI_ANNOTATIONGETSTYLEOFFSET);\n\n    SendScintilla(SCI_ANNOTATIONSETTEXT, line, textAsBytes(text).constData());\n    SendScintilla(SCI_ANNOTATIONSETSTYLE, line, style - style_offset);\n\n    setScrollBars();\n}\n\n\n// Annotate a line.\nvoid QsciScintilla::annotate(int line, const QString &text, const QsciStyle &style)\n{\n    style.apply(this);\n\n    annotate(line, text, style.style());\n}\n\n\n// Annotate a line.\nvoid QsciScintilla::annotate(int line, const QsciStyledText &text)\n{\n    text.apply(this);\n\n    annotate(line, text.text(), text.style());\n}\n\n\n// Annotate a line.\nvoid QsciScintilla::annotate(int line, const QList<QsciStyledText> &text)\n{\n    char *styles;\n    QByteArray styled_text = styleText(text, &styles,\n            SendScintilla(SCI_ANNOTATIONGETSTYLEOFFSET));\n\n    SendScintilla(SCI_ANNOTATIONSETTEXT, line, styled_text.constData());\n    SendScintilla(SCI_ANNOTATIONSETSTYLES, line, styles);\n\n    delete[] styles;\n}\n\n\n// Get the annotation for a line, if any.\nQString QsciScintilla::annotation(int line) const\n{\n    int size = SendScintilla(SCI_ANNOTATIONGETTEXT, line, (const char *)0);\n    char *buf = new char[size + 1];\n\n    QString qs = bytesAsText(buf, size);\n    delete[] buf;\n\n    return qs;\n}\n\n\n// Convert a list of styled text to the low-level arrays.\nQByteArray QsciScintilla::styleText(const QList<QsciStyledText> &styled_text,\n        char **styles, int style_offset)\n{\n    QString text;\n    int i;\n\n    // Build the full text.\n    for (i = 0; i < styled_text.count(); ++i)\n    {\n        const QsciStyledText &st = styled_text[i];\n\n        st.apply(this);\n\n        text.append(st.text());\n    }\n\n    QByteArray s = textAsBytes(text);\n\n    // There is a style byte for every byte.\n    char *sp = *styles = new char[s.length()];\n\n    for (i = 0; i < styled_text.count(); ++i)\n    {\n        const QsciStyledText &st = styled_text[i];\n        QByteArray part = textAsBytes(st.text());\n        int part_length = part.length();\n\n        for (int c = 0; c < part_length; ++c)\n            *sp++ = (char)(st.style() - style_offset);\n    }\n\n    return s;\n}\n\n\n// Convert Scintilla modifiers to the Qt equivalent.\nint QsciScintilla::mapModifiers(int modifiers)\n{\n    int state = 0;\n\n    if (modifiers & SCMOD_SHIFT)\n        state |= Qt::ShiftModifier;\n\n    if (modifiers & SCMOD_CTRL)\n        state |= Qt::ControlModifier;\n\n    if (modifiers & SCMOD_ALT)\n        state |= Qt::AltModifier;\n\n    if (modifiers & (SCMOD_SUPER | SCMOD_META))\n        state |= Qt::MetaModifier;\n\n    return state;\n}\n\n\n// Re-implemented to handle shortcut overrides.\nbool QsciScintilla::event(QEvent *e)\n{\n    if (e->type() == QEvent::ShortcutOverride && !isReadOnly())\n    {\n        QKeyEvent *ke = static_cast<QKeyEvent *>(e);\n\n        if (ke->key())\n        {\n            // We want ordinary characters.\n            if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier || ke->modifiers() == Qt::KeypadModifier) && ke->key() < Qt::Key_Escape)\n            {\n                ke->accept();\n                return true;\n            }\n\n            // We want any key that is bound.\n            QsciCommand *cmd = stdCmds->boundTo(ke->key() | (ke->modifiers() & ~Qt::KeypadModifier));\n\n            if (cmd)\n            {\n                ke->accept();\n                return true;\n            }\n        }\n    }\n\n    return QsciScintillaBase::event(e);\n}\n\n\n// Re-implemented to zoom when the Control modifier is pressed.\nvoid QsciScintilla::wheelEvent(QWheelEvent *e)\n{\n#if defined(Q_OS_MAC)\n    const Qt::KeyboardModifier zoom_modifier = Qt::MetaModifier;\n#else\n    const Qt::KeyboardModifier zoom_modifier = Qt::ControlModifier;\n#endif\n\n   if ((e->modifiers() & zoom_modifier) != 0)\n   {\n       QPoint ad = e->angleDelta();\n       int delta = (qAbs(ad.x()) > qAbs(ad.y())) ? ad.x() : ad.y();\n\n       if (delta > 0)\n           zoomIn();\n       else\n           zoomOut();\n   }\n   else \n   {\n       QsciScintillaBase::wheelEvent(e);\n   }\n}\n\n\n// Re-implemented to handle chenges to the enabled state.\nvoid QsciScintilla::changeEvent(QEvent *e)\n{\n    QsciScintillaBase::changeEvent(e);\n\n    if (e->type() != QEvent::EnabledChange)\n        return;\n\n    if (isEnabled())\n        SendScintilla(SCI_SETCARETSTYLE, CARETSTYLE_LINE);\n    else\n        SendScintilla(SCI_SETCARETSTYLE, CARETSTYLE_INVISIBLE);\n\n    QColor fore = palette().color(QPalette::Disabled, QPalette::Text);\n    QColor back = palette().color(QPalette::Disabled, QPalette::Base);\n\n    if (lex.isNull())\n    {\n        if (isEnabled())\n        {\n            fore = nl_text_colour;\n            back = nl_paper_colour;\n        }\n\n        SendScintilla(SCI_STYLESETFORE, 0, fore);\n\n        // Assume style 0 applies to everything so that we don't need to use\n        // SCI_STYLECLEARALL which clears everything.  We still have to set the\n        // default style as well for the background without any text.\n        SendScintilla(SCI_STYLESETBACK, 0, back);\n        SendScintilla(SCI_STYLESETBACK, STYLE_DEFAULT, back);\n    }\n    else\n    {\n        setEnabledColors(STYLE_DEFAULT, fore, back);\n\n        for (int s = 0; s <= STYLE_MAX; ++s)\n            if (!lex->description(s).isNull())\n                setEnabledColors(s, fore, back);\n    }\n}\n\n\n// Set the foreground and background colours for a style.\nvoid QsciScintilla::setEnabledColors(int style, QColor &fore, QColor &back)\n{\n    if (isEnabled())\n    {\n        fore = lex->color(style);\n        back = lex->paper(style);\n    }\n\n    handleStyleColorChange(fore, style);\n    handleStylePaperChange(back, style);\n}\n\n\n// Re-implemented to implement a more Qt-like context menu.\nvoid QsciScintilla::contextMenuEvent(QContextMenuEvent *e)\n{\n    if (contextMenuNeeded(e->x(), e->y()))\n    {\n        QMenu *menu = createStandardContextMenu();\n\n        if (menu)\n        {\n            menu->setAttribute(Qt::WA_DeleteOnClose);\n            menu->popup(e->globalPos());\n        }\n    }\n}\n\n\n// Create an instance of the standard context menu.\nQMenu *QsciScintilla::createStandardContextMenu()\n{\n    bool read_only = isReadOnly();\n    bool has_selection = hasSelectedText();\n    QMenu *menu = new QMenu(this);\n    QAction *action;\n\n    if (!read_only)\n    {\n        action = menu->addAction(tr(\"&Undo\"), this, SLOT(undo()));\n        set_shortcut(action, QsciCommand::Undo);\n        action->setEnabled(isUndoAvailable());\n\n        action = menu->addAction(tr(\"&Redo\"), this, SLOT(redo()));\n        set_shortcut(action, QsciCommand::Redo);\n        action->setEnabled(isRedoAvailable());\n\n        menu->addSeparator();\n\n        action = menu->addAction(tr(\"Cu&t\"), this, SLOT(cut()));\n        set_shortcut(action, QsciCommand::SelectionCut);\n        action->setEnabled(has_selection);\n    }\n\n    action = menu->addAction(tr(\"&Copy\"), this, SLOT(copy()));\n    set_shortcut(action, QsciCommand::SelectionCopy);\n    action->setEnabled(has_selection);\n\n    if (!read_only)\n    {\n        action = menu->addAction(tr(\"&Paste\"), this, SLOT(paste()));\n        set_shortcut(action, QsciCommand::Paste);\n        action->setEnabled(SendScintilla(SCI_CANPASTE));\n\n        action = menu->addAction(tr(\"Delete\"), this, SLOT(delete_selection()));\n        action->setEnabled(has_selection);\n    }\n\n    if (!menu->isEmpty())\n        menu->addSeparator();\n\n    action = menu->addAction(tr(\"Select All\"), this, SLOT(selectAll()));\n    set_shortcut(action, QsciCommand::SelectAll);\n    action->setEnabled(length() != 0);\n\n    return menu;\n}\n\n\n// Set the shortcut for an action using any current key binding.\nvoid QsciScintilla::set_shortcut(QAction *action, QsciCommand::Command cmd_id) const\n{\n    QsciCommand *cmd = stdCmds->find(cmd_id);\n\n    if (cmd && cmd->key())\n        action->setShortcut(QKeySequence(cmd->key()));\n}\n\n\n// Delete the current selection.\nvoid QsciScintilla::delete_selection()\n{\n    SendScintilla(SCI_CLEAR);\n}\n\n\n// Convert a Scintilla colour to a QColor.\nstatic QColor asQColor(long sci_colour)\n{\n    return QColor(\n            ((int)sci_colour) & 0x00ff,\n            ((int)(sci_colour >> 8)) & 0x00ff,\n            ((int)(sci_colour >> 16)) & 0x00ff);\n}\n\n\n// Set the scroll width.\nvoid QsciScintilla::setScrollWidth(int pixelWidth)\n{\n    SendScintilla(SCI_SETSCROLLWIDTH, pixelWidth);\n}\n\n// Get the scroll width.\nint QsciScintilla::scrollWidth() const\n{\n    return SendScintilla(SCI_GETSCROLLWIDTH);\n}\n\n\n// Set scroll width tracking.\nvoid QsciScintilla::setScrollWidthTracking(bool enabled)\n{\n    SendScintilla(SCI_SETSCROLLWIDTHTRACKING, enabled);\n}\n\n\n// Get scroll width tracking.\nbool QsciScintilla::scrollWidthTracking() const\n{\n    return SendScintilla(SCI_GETSCROLLWIDTHTRACKING);\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qsci/qsciscintillabase.cpp",
    "content": "// This module implements the \"official\" low-level API.\n//\n// Copyright (c) 2023 Riverbank Computing Limited <info@riverbankcomputing.com>\n// \n// This file is part of QScintilla.\n// \n// This file may be used under the terms of the GNU General Public License\n// version 3.0 as published by the Free Software Foundation and appearing in\n// the file LICENSE included in the packaging of this file.  Please review the\n// following information to ensure the GNU General Public License version 3.0\n// requirements will be met: http://www.gnu.org/copyleft/gpl.html.\n// \n// If you do not wish to use this file under the terms of the GPL version 3.0\n// then you may purchase a commercial license.  For more information contact\n// info@riverbankcomputing.com.\n// \n// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\n// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n\n\n#include \"Qsci/qsciscintillabase.h\"\n\n#include <QApplication>\n#include <QClipboard>\n#include <QColor>\n#include <QContextMenuEvent>\n#include <QDragEnterEvent>\n#include <QDragMoveEvent>\n#include <QDropEvent>\n#include <QDragLeaveEvent>\n#include <QFocusEvent>\n#include <QKeyEvent>\n#include <QList>\n#include <QMimeData>\n#include <QMouseEvent>\n#include <QPaintEvent>\n#include <QScrollBar>\n#include <QStyle>\n\n#include \"SciAccessibility.h\"\n#include \"ScintillaQt.h\"\n\n\n// The #defines in Scintilla.h and the enums in qsciscintillabase.h conflict\n// (because we want to use the same names) so we have to undefine those we use\n// in this file.\n#undef  SCI_SETCARETPERIOD\n#undef  SCK_DOWN\n#undef  SCK_UP\n#undef  SCK_LEFT\n#undef  SCK_RIGHT\n#undef  SCK_HOME\n#undef  SCK_END\n#undef  SCK_PRIOR\n#undef  SCK_NEXT\n#undef  SCK_DELETE\n#undef  SCK_INSERT\n#undef  SCK_ESCAPE\n#undef  SCK_BACK\n#undef  SCK_TAB\n#undef  SCK_RETURN\n#undef  SCK_ADD\n#undef  SCK_SUBTRACT\n#undef  SCK_DIVIDE\n#undef  SCK_WIN\n#undef  SCK_RWIN\n#undef  SCK_MENU\n#undef  SCN_URIDROPPED\n\n\n// Remember if we have linked the lexers.\nstatic bool lexersLinked = false;\n\n// The list of instances.\nstatic QList<QsciScintillaBase *> poolList;\n\n// Mime support.\nstatic const QLatin1String mimeTextPlain(\"text/plain\");\nstatic const QLatin1String mimeRectangularWin(\"MSDEVColumnSelect\");\nstatic const QLatin1String mimeRectangular(\"text/x-qscintilla-rectangular\");\n\n#if QT_VERSION < 0x060000 && defined(Q_OS_OSX)\nextern void initialiseRectangularPasteboardMime();\n#endif\n\n\n// The ctor.\nQsciScintillaBase::QsciScintillaBase(QWidget *parent)\n    : QAbstractScrollArea(parent), preeditPos(-1), preeditNrBytes(0),\n            clickCausedFocus(false)\n{\n#if !defined(QT_NO_ACCESSIBILITY)\n    QsciAccessibleScintillaBase::initialise();\n#endif\n\n    connectVerticalScrollBar();\n    connectHorizontalScrollBar();\n\n    setAcceptDrops(true);\n    setFocusPolicy(Qt::WheelFocus);\n    setAttribute(Qt::WA_KeyCompression);\n    setAttribute(Qt::WA_InputMethodEnabled);\n    setInputMethodHints(\n            Qt::ImhNoAutoUppercase|Qt::ImhNoPredictiveText|Qt::ImhMultiLine);\n\n    viewport()->setBackgroundRole(QPalette::Base);\n    viewport()->setMouseTracking(true);\n    viewport()->setAttribute(Qt::WA_NoSystemBackground);\n\n    triple_click.setSingleShot(true);\n\n#if QT_VERSION < 0x060000 && defined(Q_OS_OSX)\n    initialiseRectangularPasteboardMime();\n#endif\n\n    sci = new QsciScintillaQt(this);\n\n    SendScintilla(SCI_SETCARETPERIOD, QApplication::cursorFlashTime() / 2);\n\n    // Make sure the lexers are linked in.\n    if (!lexersLinked)\n    {\n        Scintilla_LinkLexers();\n        lexersLinked = true;\n    }\n\n    // Add it to the pool.\n    poolList.append(this);\n}\n\n\n// The dtor.\nQsciScintillaBase::~QsciScintillaBase()\n{\n    // The QsciScintillaQt object isn't a child so delete it explicitly.\n    delete sci;\n\n    // Remove it from the pool.\n    poolList.removeAt(poolList.indexOf(this));\n}\n\n\n// Return an instance from the pool.\nQsciScintillaBase *QsciScintillaBase::pool()\n{\n    return poolList.first();\n}\n\n\n// Tell Scintilla to update the scroll bars.  Scintilla should be doing this\n// itself.\nvoid QsciScintillaBase::setScrollBars()\n{\n    sci->SetScrollBars();\n}\n\n\n// Send a message to the real Scintilla widget using the low level Scintilla\n// API.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, unsigned long wParam,\n        long lParam) const\n{\n    return sci->WndProc(msg, wParam, lParam);\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, unsigned long wParam,\n        void *lParam) const\n{\n    return sci->WndProc(msg, wParam, reinterpret_cast<sptr_t>(lParam));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, uintptr_t wParam,\n        const char *lParam) const\n{\n    return sci->WndProc(msg, wParam, reinterpret_cast<sptr_t>(lParam));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg,\n        const char *lParam) const\n{\n    return sci->WndProc(msg, static_cast<uptr_t>(0),\n            reinterpret_cast<sptr_t>(lParam));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, const char *wParam,\n        const char *lParam) const\n{\n    return sci->WndProc(msg, reinterpret_cast<uptr_t>(wParam),\n            reinterpret_cast<sptr_t>(lParam));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, long wParam) const\n{\n    return sci->WndProc(msg, static_cast<uptr_t>(wParam),\n            static_cast<sptr_t>(0));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, int wParam) const\n{\n    return sci->WndProc(msg, static_cast<uptr_t>(wParam),\n            static_cast<sptr_t>(0));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, long cpMin, long cpMax,\n        char *lpstrText) const\n{\n    Sci_TextRange tr;\n\n    tr.chrg.cpMin = cpMin;\n    tr.chrg.cpMax = cpMax;\n    tr.lpstrText = lpstrText;\n\n    return sci->WndProc(msg, static_cast<uptr_t>(0),\n            reinterpret_cast<sptr_t>(&tr));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, unsigned long wParam,\n        const QColor &col) const\n{\n    sptr_t lParam = (col.blue() << 16) | (col.green() << 8) | col.red();\n\n    return sci->WndProc(msg, wParam, lParam);\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, const QColor &col) const\n{\n    uptr_t wParam = (col.blue() << 16) | (col.green() << 8) | col.red();\n\n    return sci->WndProc(msg, wParam, static_cast<sptr_t>(0));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, unsigned long wParam,\n        QPainter *hdc, const QRect &rc, long cpMin, long cpMax) const\n{\n    Sci_RangeToFormat rf;\n\n    rf.hdc = rf.hdcTarget = reinterpret_cast<Scintilla::SurfaceID>(hdc);\n\n    rf.rc.left = rc.left();\n    rf.rc.top = rc.top();\n    rf.rc.right = rc.right() + 1;\n    rf.rc.bottom = rc.bottom() + 1;\n\n    rf.chrg.cpMin = cpMin;\n    rf.chrg.cpMax = cpMax;\n\n    return sci->WndProc(msg, wParam, reinterpret_cast<sptr_t>(&rf));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, unsigned long wParam,\n        const QPixmap &lParam) const\n{\n    return sci->WndProc(msg, wParam, reinterpret_cast<sptr_t>(&lParam));\n}\n\n\n// Overloaded message send.\nlong QsciScintillaBase::SendScintilla(unsigned int msg, unsigned long wParam,\n        const QImage &lParam) const\n{\n    return sci->WndProc(msg, wParam, reinterpret_cast<sptr_t>(&lParam));\n}\n\n\n// Send a message to the real Scintilla widget using the low level Scintilla\n// API that returns a pointer result.\nvoid *QsciScintillaBase::SendScintillaPtrResult(unsigned int msg) const\n{\n    return reinterpret_cast<void *>(sci->WndProc(msg, static_cast<uptr_t>(0),\n            static_cast<sptr_t>(0)));\n}\n\n\n// Re-implemented to handle font changes\nvoid QsciScintillaBase::changeEvent(QEvent *e)\n{\n    if (e->type() == QEvent::FontChange || e->type() == QEvent::ApplicationFontChange)\n        sci->InvalidateStyleRedraw();\n\n    QAbstractScrollArea::changeEvent(e);\n}\n\n\n// Re-implemented to handle the context menu.\nvoid QsciScintillaBase::contextMenuEvent(QContextMenuEvent *e)\n{\n    sci->ContextMenu(Scintilla::Point(e->globalX(), e->globalY()));\n}\n\n\n// Re-implemented to tell the widget it has the focus.\nvoid QsciScintillaBase::focusInEvent(QFocusEvent *e)\n{\n    sci->SetFocusState(true);\n    clickCausedFocus = (e->reason() == Qt::MouseFocusReason);\n    QAbstractScrollArea::focusInEvent(e);\n}\n\n\n// Re-implemented to tell the widget it has lost the focus.\nvoid QsciScintillaBase::focusOutEvent(QFocusEvent *e)\n{\n    if (e->reason() == Qt::ActiveWindowFocusReason)\n    {\n        // Only tell Scintilla we have lost focus if the new active window\n        // isn't our auto-completion list.  This is probably only an issue on\n        // Linux and there are still problems because subsequent focus out\n        // events don't always seem to get generated (at least with Qt5).\n\n        QWidget *aw = QApplication::activeWindow();\n\n        if (!aw || aw->parent() != this || !aw->inherits(\"QsciSciListBox\"))\n            sci->SetFocusState(false);\n    }\n    else\n    {\n        sci->SetFocusState(false);\n    }\n\n    QAbstractScrollArea::focusOutEvent(e);\n}\n\n\n// Re-implemented to make sure tabs are passed to the editor.\nbool QsciScintillaBase::focusNextPrevChild(bool next)\n{\n    if (!sci->pdoc->IsReadOnly())\n        return false;\n\n    return QAbstractScrollArea::focusNextPrevChild(next);\n}\n\n\n// Handle key presses.\nvoid QsciScintillaBase::keyPressEvent(QKeyEvent *e)\n{\n    int modifiers = 0;\n\n    if (e->modifiers() & Qt::ShiftModifier)\n        modifiers |= SCMOD_SHIFT;\n\n    if (e->modifiers() & Qt::ControlModifier)\n        modifiers |= SCMOD_CTRL;\n\n    if (e->modifiers() & Qt::AltModifier)\n        modifiers |= SCMOD_ALT;\n\n    if (e->modifiers() & Qt::MetaModifier)\n        modifiers |= SCMOD_META;\n\n    int key = commandKey(e->key(), modifiers);\n\n    if (key)\n    {\n        bool consumed = false;\n\n        sci->KeyDownWithModifiers(key, modifiers, &consumed);\n\n        if (consumed)\n        {\n            e->accept();\n            return;\n        }\n    }\n\n    QString text = e->text();\n\n    if (!text.isEmpty() && text[0].isPrint())\n    {\n        QByteArray bytes = textAsBytes(text);\n        sci->AddCharUTF(bytes.data(), bytes.length());\n        e->accept();\n    }\n    else\n    {\n        QAbstractScrollArea::keyPressEvent(e);\n    }\n}\n\n\n// Map a Qt key to a valid Scintilla command key, or 0 if none.\nint QsciScintillaBase::commandKey(int qt_key, int &modifiers)\n{\n    int key;\n\n    switch (qt_key)\n    {\n    case Qt::Key_Down:\n        key = SCK_DOWN;\n        break;\n\n    case Qt::Key_Up:\n        key = SCK_UP;\n        break;\n\n    case Qt::Key_Left:\n        key = SCK_LEFT;\n        break;\n\n    case Qt::Key_Right:\n        key = SCK_RIGHT;\n        break;\n\n    case Qt::Key_Home:\n        key = SCK_HOME;\n        break;\n\n    case Qt::Key_End:\n        key = SCK_END;\n        break;\n\n    case Qt::Key_PageUp:\n        key = SCK_PRIOR;\n        break;\n\n    case Qt::Key_PageDown:\n        key = SCK_NEXT;\n        break;\n\n    case Qt::Key_Delete:\n        key = SCK_DELETE;\n        break;\n\n    case Qt::Key_Insert:\n        key = SCK_INSERT;\n        break;\n\n    case Qt::Key_Escape:\n        key = SCK_ESCAPE;\n        break;\n\n    case Qt::Key_Backspace:\n        key = SCK_BACK;\n        break;\n\n    case Qt::Key_Tab:\n        key = SCK_TAB;\n        break;\n\n    case Qt::Key_Backtab:\n        // Scintilla assumes a backtab is shift-tab.\n        key = SCK_TAB;\n        modifiers |= SCMOD_SHIFT;\n        break;\n\n    case Qt::Key_Return:\n    case Qt::Key_Enter:\n        key = SCK_RETURN;\n        break;\n\n    case Qt::Key_Super_L:\n        key = SCK_WIN;\n        break;\n\n    case Qt::Key_Super_R:\n        key = SCK_RWIN;\n        break;\n\n    case Qt::Key_Menu:\n        key = SCK_MENU;\n        break;\n\n    default:\n        if ((key = qt_key) > 0x7f)\n            key = 0;\n    }\n\n    return key;\n}\n\n\n// Encode a QString as bytes.\nQByteArray QsciScintillaBase::textAsBytes(const QString &text) const\n{\n    if (sci->IsUnicodeMode())\n        return text.toUtf8();\n\n    return text.toLatin1();\n}\n\n\n// Decode bytes as a QString.\nQString QsciScintillaBase::bytesAsText(const char *bytes, int size) const\n{\n    if (sci->IsUnicodeMode())\n        return QString::fromUtf8(bytes, size);\n\n    return QString::fromLatin1(bytes, size);\n}\n\n\n// Handle a mouse button double click.\nvoid QsciScintillaBase::mouseDoubleClickEvent(QMouseEvent *e)\n{\n    if (e->button() != Qt::LeftButton)\n    {\n        e->ignore();\n        return;\n    }\n\n    setFocus();\n\n    // Make sure Scintilla will interpret this as a double-click.\n    unsigned clickTime = sci->lastClickTime + Scintilla::Platform::DoubleClickTime() - 1;\n\n    sci->ButtonDownWithModifiers(Scintilla::Point(e->x(), e->y()), clickTime,\n            eventModifiers(e));\n\n    // Remember the current position and time in case it turns into a triple\n    // click.\n    triple_click_at = e->globalPos();\n    triple_click.start(QApplication::doubleClickInterval());\n}\n\n\n// Handle a mouse move.\nvoid QsciScintillaBase::mouseMoveEvent(QMouseEvent *e)\n{\n    sci->ButtonMoveWithModifiers(Scintilla::Point(e->x(), e->y()), 0,\n            eventModifiers(e));\n}\n\n\n// Handle a mouse button press.\nvoid QsciScintillaBase::mousePressEvent(QMouseEvent *e)\n{\n    setFocus();\n\n    Scintilla::Point pt(e->x(), e->y());\n\n    if (e->button() == Qt::LeftButton || e->button() == Qt::RightButton)\n    {\n        unsigned clickTime;\n\n        // It is a triple click if the timer is running and the mouse hasn't\n        // moved too much.\n        if (triple_click.isActive() && (e->globalPos() - triple_click_at).manhattanLength() < QApplication::startDragDistance())\n            clickTime = sci->lastClickTime + Scintilla::Platform::DoubleClickTime() - 1;\n        else\n            clickTime = sci->lastClickTime + Scintilla::Platform::DoubleClickTime() + 1;\n\n        triple_click.stop();\n\n        // Scintilla uses the Alt modifier to initiate rectangular selection.\n        // However the GTK port (under X11, not Windows) uses the Control\n        // modifier (by default, although it is configurable).  It does this\n        // because most X11 window managers hijack Alt-drag to move the window.\n        // We do the same, except that (for the moment at least) we don't allow\n        // the modifier to be configured.\n        bool shift = e->modifiers() & Qt::ShiftModifier;\n        bool ctrl = e->modifiers() & Qt::ControlModifier;\n#if defined(Q_OS_MAC) || defined(Q_OS_WIN)\n        bool alt = e->modifiers() & Qt::AltModifier;\n#else\n        bool alt = ctrl;\n#endif\n\n        if (e->button() == Qt::LeftButton)\n            sci->ButtonDownWithModifiers(pt, clickTime,\n                    QsciScintillaQt::ModifierFlags(shift, ctrl, alt));\n        else\n            sci->RightButtonDownWithModifiers(pt, clickTime,\n                    QsciScintillaQt::ModifierFlags(shift, ctrl, alt));\n    }\n    else if (e->button() == Qt::MiddleButton)\n    {\n        QClipboard *cb = QApplication::clipboard();\n\n        if (cb->supportsSelection())\n        {\n            int pos = sci->PositionFromLocation(pt);\n\n            sci->sel.Clear();\n            sci->SetSelection(pos, pos);\n\n            sci->pasteFromClipboard(QClipboard::Selection);\n        }\n    }\n}\n\n\n// Handle a mouse button releases.\nvoid QsciScintillaBase::mouseReleaseEvent(QMouseEvent *e)\n{\n    if (e->button() != Qt::LeftButton)\n        return;\n\n    Scintilla::Point pt(e->x(), e->y());\n\n    if (sci->HaveMouseCapture())\n    {\n        bool ctrl = e->modifiers() & Qt::ControlModifier;\n\n        sci->ButtonUpWithModifiers(pt, 0,\n                QsciScintillaQt::ModifierFlags(false, ctrl, false));\n    }\n\n    if (!sci->pdoc->IsReadOnly() && !sci->PointInSelMargin(pt) && qApp->autoSipEnabled())\n    {\n        QStyle::RequestSoftwareInputPanel rsip = QStyle::RequestSoftwareInputPanel(style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));\n\n        if (!clickCausedFocus || rsip == QStyle::RSIP_OnMouseClick)\n            qApp->inputMethod()->show();\n    }\n\n    clickCausedFocus = false;\n}\n\n\n// Handle paint events.\nvoid QsciScintillaBase::paintEvent(QPaintEvent *e)\n{\n    sci->paintEvent(e);\n}\n\n\n// Handle resize events.\nvoid QsciScintillaBase::resizeEvent(QResizeEvent *)\n{\n    sci->ChangeSize();\n}\n\n\n// Re-implemented to suppress the default behaviour as Scintilla works at a\n// more fundamental level.  Note that this means that replacing the scrollbars\n// with custom versions does not work.\nvoid QsciScintillaBase::scrollContentsBy(int, int)\n{\n}\n\n\n// Handle the vertical scrollbar.\nvoid QsciScintillaBase::handleVSb(int value)\n{\n    sci->ScrollTo(value);\n}\n\n\n// Handle the horizontal scrollbar.\nvoid QsciScintillaBase::handleHSb(int value)\n{\n    sci->HorizontalScrollTo(value);\n}\n\n\n// Handle drag enters.\nvoid QsciScintillaBase::dragEnterEvent(QDragEnterEvent *e)\n{\n    QsciScintillaBase::dragMoveEvent(e);\n}\n\n\n// Handle drag leaves.\nvoid QsciScintillaBase::dragLeaveEvent(QDragLeaveEvent *)\n{\n    sci->SetDragPosition(Scintilla::SelectionPosition());\n}\n\n\n// Handle drag moves.\nvoid QsciScintillaBase::dragMoveEvent(QDragMoveEvent *e)\n{\n    if (e->mimeData()->hasUrls())\n    {\n        e->acceptProposedAction();\n    }\n    else\n    {\n        sci->SetDragPosition(\n                sci->SPositionFromLocation(\n                        Scintilla::Point(e->pos().x(), e->pos().y()), false,\n                        false, sci->UserVirtualSpace()));\n\n        acceptAction(e);\n    }\n}\n\n\n// Handle drops.\nvoid QsciScintillaBase::dropEvent(QDropEvent *e)\n{\n    if (e->mimeData()->hasUrls())\n    {\n        e->acceptProposedAction();\n\n        foreach (const QUrl &url, e->mimeData()->urls())\n            emit SCN_URIDROPPED(url);\n\n        return;\n    }\n\n    acceptAction(e);\n\n    if (!e->isAccepted())\n        return;\n\n    bool moving;\n    int len;\n    const char *s;\n    bool rectangular;\n\n    moving = (e->dropAction() == Qt::MoveAction);\n\n    QByteArray text = fromMimeData(e->mimeData(), rectangular);\n    len = text.length();\n    s = text.data();\n\n    std::string dest = Scintilla::Document::TransformLineEnds(s, len,\n                sci->pdoc->eolMode);\n\n    sci->DropAt(sci->posDrop, dest.c_str(), dest.length(), moving,\n            rectangular);\n\n    sci->Redraw();\n}\n\n\nvoid QsciScintillaBase::acceptAction(QDropEvent *e)\n{\n    if (sci->pdoc->IsReadOnly() || !canInsertFromMimeData(e->mimeData()))\n        e->ignore();\n    else\n        e->acceptProposedAction();\n}\n\n\n// See if a MIME data object can be decoded.\nbool QsciScintillaBase::canInsertFromMimeData(const QMimeData *source) const\n{\n    return source->hasFormat(mimeTextPlain);\n}\n\n\n// Create text from a MIME data object.\nQByteArray QsciScintillaBase::fromMimeData(const QMimeData *source, bool &rectangular) const\n{\n    // See if it is rectangular.  We try all of the different formats that\n    // Scintilla supports in case we are working across different platforms.\n    if (source->hasFormat(mimeRectangularWin))\n        rectangular = true;\n    else if (source->hasFormat(mimeRectangular))\n        rectangular = true;\n    else\n        rectangular = false;\n\n    // Note that we don't support Scintilla's hack of adding a '\\0' as Qt\n    // strips it off under the covers when pasting from another process.\n    QString utf8 = source->text();\n    QByteArray text;\n\n    if (sci->IsUnicodeMode())\n        text = utf8.toUtf8();\n    else\n        text = utf8.toLatin1();\n\n    return text;\n}\n\n\n// Create a MIME data object for some text.\nQMimeData *QsciScintillaBase::toMimeData(const QByteArray &text, bool rectangular) const\n{\n    QMimeData *mime = new QMimeData;\n\n    QString utf8;\n\n    if (sci->IsUnicodeMode())\n        utf8 = QString::fromUtf8(text.constData(), text.size());\n    else\n        utf8 = QString::fromLatin1(text.constData(), text.size());\n\n    mime->setText(utf8);\n\n    if (rectangular)\n    {\n        // Use the platform specific \"standard\" for specifying a rectangular\n        // selection.\n#if defined(Q_OS_WIN)\n        mime->setData(mimeRectangularWin, QByteArray());\n#else\n        mime->setData(mimeRectangular, QByteArray());\n#endif\n    }\n\n    return mime;\n}\n\n\n// Connect up the vertical scroll bar.\nvoid QsciScintillaBase::connectVerticalScrollBar()\n{\n    connect(verticalScrollBar(), SIGNAL(valueChanged(int)),\n            SLOT(handleVSb(int)));\n}\n\n\n// Connect up the horizontal scroll bar.\nvoid QsciScintillaBase::connectHorizontalScrollBar()\n{\n    connect(horizontalScrollBar(), SIGNAL(valueChanged(int)),\n            SLOT(handleHSb(int)));\n}\n\n\n//! Replace the vertical scroll bar.\nvoid QsciScintillaBase::replaceVerticalScrollBar(QScrollBar *scrollBar)\n{\n    setVerticalScrollBar(scrollBar);\n    connectVerticalScrollBar();\n}\n\n\n// Replace the horizontal scroll bar.\nvoid QsciScintillaBase::replaceHorizontalScrollBar(QScrollBar *scrollBar)\n{\n    setHorizontalScrollBar(scrollBar);\n    connectHorizontalScrollBar();\n}\n\n\n// Return true if a context menu should be displayed.  This is provided as a\n// helper to QsciScintilla::contextMenuEvent().  A proper design would break\n// backwards compatibility.\nbool QsciScintillaBase::contextMenuNeeded(int x, int y) const\n{\n    Scintilla::Point pt(x, y);\n\n    // Clear any selection if the mouse is outside.\n    if (!sci->PointInSelection(pt))\n        sci->SetEmptySelection(sci->PositionFromLocation(pt));\n\n    // Respect SC_POPUP_*.\n    return sci->ShouldDisplayPopup(pt);\n}\n\n\n// Return the Scintilla keyboard modifiers set for a mouse event.\nint QsciScintillaBase::eventModifiers(QMouseEvent *e)\n{\n    bool shift = e->modifiers() & Qt::ShiftModifier;\n    bool ctrl = e->modifiers() & Qt::ControlModifier;\n    bool alt = e->modifiers() & Qt::AltModifier;\n\n    return QsciScintillaQt::ModifierFlags(shift, ctrl, alt);\n}\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qabstractpagesetupdialog.cpp",
    "content": "/****************************************************************************\n**\n** Copyright (C) 2015 The Qt Company Ltd.\n** Contact: http://www.qt.io/licensing/\n**\n** This file is part of the QtGui module of the Qt Toolkit.\n**\n** $QT_BEGIN_LICENSE:LGPL$\n** Commercial License Usage\n** Licensees holding valid commercial Qt licenses may use this file in\n** accordance with the commercial license agreement provided with the\n** Software or, alternatively, in accordance with the terms contained in\n** a written agreement between you and The Qt Company. For licensing terms\n** and conditions see http://www.qt.io/terms-conditions. For further\n** information use the contact form at http://www.qt.io/contact-us.\n**\n** GNU Lesser General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU Lesser\n** General Public License version 2.1 or version 3 as published by the Free\n** Software Foundation and appearing in the file LICENSE.LGPLv21 and\n** LICENSE.LGPLv3 included in the packaging of this file. Please review the\n** following information to ensure the GNU Lesser General Public License\n** requirements will be met: https://www.gnu.org/licenses/lgpl.html and\n** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n**\n** As a special exception, The Qt Company gives you certain additional\n** rights. These rights are described in The Qt Company LGPL Exception\n** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n**\n** GNU General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU\n** General Public License version 3.0 as published by the Free Software\n** Foundation and appearing in the file LICENSE.GPL included in the\n** packaging of this file.  Please review the following information to\n** ensure the GNU General Public License version 3.0 requirements will be\n** met: http://www.gnu.org/copyleft/gpl.html.\n**\n** $QT_END_LICENSE$\n**\n****************************************************************************/\n\n#include \"qabstractpagesetupdialog.h\"\n#include \"qabstractpagesetupdialog_p.h\"\n\n#ifndef QT_NO_PRINTDIALOG\n\n#include <QtCore/qcoreapplication.h>\n#include <QtGui/qprinter.h>\n\nQT_BEGIN_NAMESPACE\n\n/*!\n    \\internal\n    \\class QAbstractPageSetupDialog\n\n    \\brief The QAbstractPageSetupDialog class provides a base for\n    implementations of page setup dialogs.\n*/\n\n/*!\n    Constructs the page setup dialog for the printer \\a printer with\n    \\a parent as parent widget.\n*/\nQAbstractPageSetupDialog::QAbstractPageSetupDialog(QPrinter *printer, QWidget *parent)\n    : QDialog(*(new QAbstractPageSetupDialogPrivate), parent)\n{\n    Q_D(QAbstractPageSetupDialog);\n    setWindowTitle(QCoreApplication::translate(\"QPrintPreviewDialog\", \"Page Setup\"));\n    d->setPrinter(printer);\n}\n\n/*!\n    \\internal\n*/\nQAbstractPageSetupDialog::QAbstractPageSetupDialog(QAbstractPageSetupDialogPrivate &ptr,\n                                                   QPrinter *printer, QWidget *parent)\n    : QDialog(ptr, parent)\n{\n    Q_D(QAbstractPageSetupDialog);\n    setWindowTitle(QCoreApplication::translate(\"QPrintPreviewDialog\", \"Page Setup\"));\n    d->setPrinter(printer);\n}\n\nQAbstractPageSetupDialog::~QAbstractPageSetupDialog()\n{\n    Q_D(QAbstractPageSetupDialog);\n    if (d->opts & QPageSetupDialog::OwnsPrinter)\n        delete d->printer;\n}\n\n/*!\n    Returns the printer that this page setup dialog is operating on.\n*/\nQPrinter *QAbstractPageSetupDialog::printer()\n{\n    Q_D(QAbstractPageSetupDialog);\n    return d->printer;\n}\n\nvoid QAbstractPageSetupDialogPrivate::setPrinter(QPrinter *newPrinter)\n{\n    if (newPrinter) {\n        printer = newPrinter;\n    } else {\n        printer = new QPrinter;\n        opts |= QPageSetupDialog::OwnsPrinter;\n    }\n#ifndef Q_WS_X11\n    if (printer->outputFormat() != QPrinter::NativeFormat)\n        qWarning(\"QPageSetupDialog: Cannot be used on non-native printers\");\n#endif\n}\n\n/*!\n    \\fn int QAbstractPageSetupDialog::exec()\n\n    This virtual function is called to pop up the dialog. It must be\n    reimplemented in subclasses.\n*/\n\n/*!\n    \\reimp\n*/\nvoid QAbstractPageSetupDialog::done(int result)\n{\n    Q_D(QAbstractPageSetupDialog);\n    QDialog::done(result);\n    if (d->receiverToDisconnectOnClose) {\n        disconnect(this, SIGNAL(accepted()),\n                   d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);\n        d->receiverToDisconnectOnClose = 0;\n    }\n    d->memberToDisconnectOnClose.clear();\n\n}\n\nQT_END_NAMESPACE\n\n#endif // QT_NO_PRINTDIALOG\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qabstractprintdialog.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qabstractprintdialog_p.h\"\n#include \"qcoreapplication.h\"\n#include \"qprintdialog.h\"\n#include \"qprinter.h\"\n#include \"private/qprinter_p.h\"\n\nQT_BEGIN_NAMESPACE\n\n/*!\n    \\class QAbstractPrintDialog\n    \\brief The QAbstractPrintDialog class provides a base implementation for\n    print dialogs used to configure printers.\n\n    \\ingroup printing\n    \\inmodule QtPrintSupport\n\n    This class implements getter and setter functions that are used to\n    customize settings shown in print dialogs, but it is not used directly.\n    Use QPrintDialog to display a print dialog in your application.\n\n    \\sa QPrintDialog, QPrinter\n*/\n\n/*!\n    \\enum QAbstractPrintDialog::PrintRange\n\n    Used to specify the print range selection option.\n\n    \\value AllPages All pages should be printed.\n    \\value Selection Only the selection should be printed.\n    \\value PageRange The specified page range should be printed.\n    \\value CurrentPage Only the currently visible page should be printed.\n\n    \\sa QPrinter::PrintRange\n*/\n\n/*!\n    \\enum QAbstractPrintDialog::PrintDialogOption\n\n    Used to specify which parts of the print dialog should be visible.\n\n    \\value PrintToFile The print to file option is enabled.\n    \\value PrintSelection The print selection option is enabled.\n    \\value PrintPageRange The page range selection option is enabled.\n    \\value PrintShowPageSize  Show the page size + margins page only if this is enabled.\n    \\value PrintCollateCopies The collate copies option is enabled\n    \\value PrintCurrentPage The print current page option is enabled\n*/\n\n/*!\n    Constructs an abstract print dialog for \\a printer with \\a parent\n    as parent widget.\n*/\nQAbstractPrintDialog::QAbstractPrintDialog(QPrinter *printer, QWidget *parent)\n    : QDialog(*(new QAbstractPrintDialogPrivate), parent)\n{\n    Q_D(QAbstractPrintDialog);\n    setWindowTitle(QCoreApplication::translate(\"QPrintDialog\", \"Print\"));\n    d->setPrinter(printer);\n    d->minPage = printer->fromPage();\n    int to = printer->toPage();\n    d->maxPage = to > 0 ? to : INT_MAX;\n}\n\n/*!\n     \\internal\n*/\nQAbstractPrintDialog::QAbstractPrintDialog(QAbstractPrintDialogPrivate &ptr,\n                                           QPrinter *printer,\n                                           QWidget *parent)\n    : QDialog(ptr, parent)\n{\n    Q_D(QAbstractPrintDialog);\n    setWindowTitle(QCoreApplication::translate(\"QPrintDialog\", \"Print\"));\n    d->setPrinter(printer);\n}\n\n/*!\n    \\internal\n*/\nQAbstractPrintDialog::~QAbstractPrintDialog()\n{\n    Q_D(QAbstractPrintDialog);\n    if (d->ownsPrinter)\n        delete d->printer;\n}\n\n/*!\n    Sets the given \\a option to be enabled if \\a on is true;\n    otherwise, clears the given \\a option.\n\n    \\sa options, testOption()\n*/\nvoid QPrintDialog::setOption(PrintDialogOption option, bool on)\n{\n    auto *d = static_cast<QAbstractPrintDialogPrivate *>(d_ptr.data());\n    if (!(d->options & option) != !on)\n        setOptions(d->options ^ option);\n}\n\n/*!\n    Returns \\c true if the given \\a option is enabled; otherwise, returns\n    false.\n\n    \\sa options, setOption()\n*/\nbool QPrintDialog::testOption(PrintDialogOption option) const\n{\n    auto *d = static_cast<const QAbstractPrintDialogPrivate *>(d_ptr.data());\n    return (d->options & option) != 0;\n}\n\n/*!\n    \\property QPrintDialog::options\n    \\brief the various options that affect the look and feel of the dialog\n    \\since 4.5\n\n    By default, all options are disabled.\n\n    Options should be set before showing the dialog. Setting them while the\n    dialog is visible is not guaranteed to have an immediate effect on the\n    dialog (depending on the option and on the platform).\n\n    \\sa setOption(), testOption()\n*/\nvoid QPrintDialog::setOptions(PrintDialogOptions options)\n{\n    auto *d = static_cast<QAbstractPrintDialogPrivate *>(d_ptr.data());\n\n    PrintDialogOptions changed = (options ^ d->options);\n    if (!changed)\n        return;\n\n    d->options = options;\n}\n\nQPrintDialog::PrintDialogOptions QPrintDialog::options() const\n{\n    auto *d = static_cast<const QAbstractPrintDialogPrivate *>(d_ptr.data());\n    return d->options;\n}\n\n/*!\n    Sets the print range option in to be \\a range.\n */\nvoid QAbstractPrintDialog::setPrintRange(PrintRange range)\n{\n    Q_D(QAbstractPrintDialog);\n    d->printer->setPrintRange(QPrinter::PrintRange(range));\n}\n\n/*!\n    Returns the print range.\n*/\nQAbstractPrintDialog::PrintRange QAbstractPrintDialog::printRange() const\n{\n    Q_D(const QAbstractPrintDialog);\n    return QAbstractPrintDialog::PrintRange(d->pd->printRange);\n}\n\n/*!\n    Sets the page range in this dialog to be from \\a min to \\a max. This also\n    enables the PrintPageRange option.\n*/\nvoid QAbstractPrintDialog::setMinMax(int min, int max)\n{\n    Q_D(QAbstractPrintDialog);\n    Q_ASSERT_X(min <= max, \"QAbstractPrintDialog::setMinMax\",\n               \"'min' must be less than or equal to 'max'\");\n    d->minPage = min;\n    d->maxPage = max;\n    d->options |= PrintPageRange;\n}\n\n/*!\n    Returns the minimum page in the page range.\n    By default, this value is set to 1.\n*/\nint QAbstractPrintDialog::minPage() const\n{\n    Q_D(const QAbstractPrintDialog);\n    return d->minPage;\n}\n\n/*!\n    Returns the maximum page in the page range. As of Qt 4.4, this\n    function returns INT_MAX by default. Previous versions returned 1\n    by default.\n*/\nint QAbstractPrintDialog::maxPage() const\n{\n    Q_D(const QAbstractPrintDialog);\n    return d->maxPage;\n}\n\n/*!\n    Sets the range in the print dialog to be from \\a from to \\a to.\n*/\nvoid QAbstractPrintDialog::setFromTo(int from, int to)\n{\n    Q_D(QAbstractPrintDialog);\n    Q_ASSERT_X(from <= to, \"QAbstractPrintDialog::setFromTo\",\n               \"'from' must be less than or equal to 'to'\");\n    d->printer->setFromTo(from, to);\n\n    if (d->minPage == 0 && d->maxPage == 0)\n        setMinMax(1, to);\n}\n\n/*!\n    Returns the first page to be printed\n    By default, this value is set to 0.\n*/\nint QAbstractPrintDialog::fromPage() const\n{\n    Q_D(const QAbstractPrintDialog);\n    return d->printer->fromPage();\n}\n\n/*!\n    Returns the last page to be printed.\n    By default, this value is set to 0.\n*/\nint QAbstractPrintDialog::toPage() const\n{\n    Q_D(const QAbstractPrintDialog);\n    return d->printer->toPage();\n}\n\n\n/*!\n    Returns the printer that this printer dialog operates\n    on.\n*/\nQPrinter *QAbstractPrintDialog::printer() const\n{\n    Q_D(const QAbstractPrintDialog);\n    return d->printer;\n}\n\nvoid QAbstractPrintDialogPrivate::setPrinter(QPrinter *newPrinter)\n{\n    if (newPrinter) {\n        printer = newPrinter;\n        ownsPrinter = false;\n        if (printer->fromPage() || printer->toPage())\n            options |= QAbstractPrintDialog::PrintPageRange;\n    } else {\n        printer = new QPrinter;\n        ownsPrinter = true;\n    }\n    pd = printer->d_func();\n}\n\n/*!\n    \\class QPrintDialog\n\n    \\brief The QPrintDialog class provides a dialog for specifying\n    the printer's configuration.\n\n    \\ingroup standard-dialogs\n    \\ingroup printing\n    \\inmodule QtPrintSupport\n\n    The dialog allows users to change document-related settings, such\n    as the paper size and orientation, type of print (color or\n    grayscale), range of pages, and number of copies to print.\n\n    Controls are also provided to enable users to choose from the\n    printers available, including any configured network printers.\n\n    Typically, QPrintDialog objects are constructed with a QPrinter\n    object, and executed using the exec() function.\n\n    \\snippet code/src_gui_dialogs_qabstractprintdialog.cpp 0\n\n    If the dialog is accepted by the user, the QPrinter object is\n    correctly configured for printing.\n\n    \\table\n    \\row\n    \\li \\inlineimage plastique-printdialog.png\n    \\li \\inlineimage plastique-printdialog-properties.png\n    \\endtable\n\n    The printer dialog (shown above in Plastique style) enables access to common\n    printing properties. On X11 platforms that use the CUPS printing system, the\n    settings for each available printer can be modified via the dialog's\n    \\uicontrol{Properties} push button.\n\n    On Windows and \\macos, the native print dialog is used, which means that\n    some QWidget and QDialog properties set on the dialog won't be respected.\n    The native print dialog on \\macos does not support setting printer options,\n    i.e. setOptions() and setOption() have no effect.\n\n    In Qt 4.4, it was possible to use the static functions to show a sheet on\n    \\macos. This is no longer supported in Qt 4.5. If you want this\n    functionality, use QPrintDialog::open().\n\n    \\sa QPageSetupDialog, QPrinter\n*/\n\n/*!\n    \\fn QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)\n\n    Constructs a new modal printer dialog for the given \\a printer\n    with the given \\a parent.\n*/\n\n/*!\n    \\fn QPrintDialog::~QPrintDialog()\n\n    Destroys the print dialog.\n*/\n\n/*!\n    \\fn int QPrintDialog::exec()\n    \\reimp\n*/\n\n/*!\n    \\since 4.4\n\n    Set a list of widgets as \\a tabs to be shown on the print dialog, if supported.\n\n    Currently this option is only supported on X11.\n\n    Setting the option tabs will transfer their ownership to the print dialog.\n*/\nvoid QAbstractPrintDialog::setOptionTabs(const QList<QWidget*> &tabs)\n{\n    Q_D(QAbstractPrintDialog);\n    d->setTabs(tabs);\n}\n\n/*!\n\n    \\fn void QPrintDialog::accepted(QPrinter *printer)\n\n    This signal is emitted when the user accepts the values set in the print dialog.\n    The \\a printer parameter includes the printer that the settings were applied to.\n*/\n\n/*!\n    \\fn QPrinter *QPrintDialog::printer()\n\n    Returns the printer that this printer dialog operates\n    on. This can be useful when using the QPrintDialog::open() method.\n*/\n\n/*!\n  Closes the dialog and sets its result code to \\a result. If this dialog\n  is shown with exec(), done() causes the local event loop to finish,\n  and exec() to return \\a result.\n\n  \\note This function does not apply to the Native Print Dialog on the Mac\n  \\macos and Windows platforms, because the dialog is required to be modal\n  and only the user can close it.\n\n  \\sa QDialog::done()\n*/\nvoid QPrintDialog::done(int result)\n{\n    auto *d = static_cast<QAbstractPrintDialogPrivate *>(d_ptr.data());\n    if (result == Accepted) {\n        // Emit accepted(QPrinter*) at the same time as the dialog\n        // is accepted. Doing it here is too late, as done() will\n        // also emit finished().\n        QObject::connect(this, &QDialog::accepted, this, [this]{\n            emit accepted(printer());\n        }, Qt::SingleShotConnection);\n    }\n    QDialog::done(result);\n    if (d->receiverToDisconnectOnClose) {\n        disconnect(this, SIGNAL(accepted(QPrinter*)),\n                   d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);\n        d->receiverToDisconnectOnClose = nullptr;\n    }\n    d->memberToDisconnectOnClose.clear();\n}\n\n/*!\n    \\since 4.5\n    \\overload\n\n    Opens the dialog and connects its accepted() signal to the slot specified\n    by \\a receiver and \\a member.\n\n    The signal will be disconnected from the slot when the dialog is closed.\n*/\nvoid QPrintDialog::open(QObject *receiver, const char *member)\n{\n    auto *d = static_cast<QAbstractPrintDialogPrivate *>(d_ptr.data());\n    connect(this, SIGNAL(accepted(QPrinter*)), receiver, member);\n    d->receiverToDisconnectOnClose = receiver;\n    d->memberToDisconnectOnClose = member;\n    QDialog::open();\n}\n\nQT_END_NAMESPACE\n\n#include \"moc_qabstractprintdialog.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qcolordialog.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qcolordialog.h\"\n\n#include \"qapplication.h\"\n#include \"qdrawutil.h\"\n#include \"qevent.h\"\n#include \"qimage.h\"\n#if QT_CONFIG(draganddrop)\n#include <qdrag.h>\n#endif\n#include \"qlabel.h\"\n#include \"qlayout.h\"\n#include \"qlineedit.h\"\n#if QT_CONFIG(menu)\n#include \"qmenu.h\"\n#endif\n#include \"qpainter.h\"\n#include \"qpixmap.h\"\n#include \"qpushbutton.h\"\n#if QT_CONFIG(regularexpression)\n#include <qregularexpression.h>\n#endif\n#if QT_CONFIG(settings)\n#include \"qsettings.h\"\n#endif\n#include \"qsharedpointer.h\"\n#include \"qstyle.h\"\n#include \"qstyleoption.h\"\n#include \"qvalidator.h\"\n#include \"qmimedata.h\"\n#include \"qspinbox.h\"\n#include \"qdialogbuttonbox.h\"\n#include \"qscreen.h\"\n#include \"qcursor.h\"\n#include \"qtimer.h\"\n#include \"qwindow.h\"\n\n#include \"private/qdialog_p.h\"\n\n#include <qpa/qplatformintegration.h>\n#include <qpa/qplatformservices.h>\n#include <private/qguiapplication_p.h>\n\n#include <QtCore/qpointer.h>\n\n#include <algorithm>\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\nnamespace QtPrivate {\nclass QColorLuminancePicker;\nclass QColorPicker;\nclass QColorShower;\nclass QWellArray;\nclass QColorWell;\nclass QColorPickingEventFilter;\n} // namespace QtPrivate\n\nusing QColorLuminancePicker = QtPrivate::QColorLuminancePicker;\nusing QColorPicker = QtPrivate::QColorPicker;\nusing QColorShower = QtPrivate::QColorShower;\nusing QWellArray = QtPrivate::QWellArray;\nusing QColorWell = QtPrivate::QColorWell;\nusing QColorPickingEventFilter = QtPrivate::QColorPickingEventFilter;\n\nclass QColorDialogPrivate : public QDialogPrivate\n{\n    Q_DECLARE_PUBLIC(QColorDialog)\n\npublic:\n    enum SetColorMode {\n        ShowColor = 0x1,\n        SelectColor = 0x2,\n        SetColorAll = ShowColor | SelectColor\n    };\n\n    QColorDialogPrivate() : options(QColorDialogOptions::create())\n#ifdef Q_OS_WIN32\n        , updateTimer(0)\n#endif\n    {}\n\n    QPlatformColorDialogHelper *platformColorDialogHelper() const\n        { return static_cast<QPlatformColorDialogHelper *>(platformHelper()); }\n\n    void init(const QColor &initial);\n    void initWidgets();\n    QRgb currentColor() const;\n    QColor currentQColor() const;\n    void setCurrentColor(const QColor &color, SetColorMode setColorMode = SetColorAll);\n    void setCurrentRgbColor(QRgb rgb);\n    void setCurrentQColor(const QColor &color);\n    bool selectColor(const QColor &color);\n    QColor grabScreenColor(const QPoint &p);\n\n    int currentAlpha() const;\n    void setCurrentAlpha(int a);\n    void showAlpha(bool b);\n    bool isAlphaVisible() const;\n    void retranslateStrings();\n    bool supportsColorPicking() const;\n\n    void addCustom();\n    void _q_setCustom(int index, QRgb color);\n\n    void newHsv(int h, int s, int v);\n    void newColorTypedIn(QRgb rgb);\n    void nextCustom(int, int);\n    void newCustom(int, int);\n    void newStandard(int, int);\n    void pickScreenColor();\n    void updateColorPicking();\n    void updateColorLabelText(const QPoint &);\n    void updateColorPicking(const QPoint &pos);\n    void releaseColorPicking();\n    bool handleColorPickingMouseMove(QMouseEvent *e);\n    bool handleColorPickingMouseButtonRelease(QMouseEvent *e);\n    bool handleColorPickingKeyPress(QKeyEvent *e);\n\n    bool canBeNativeDialog() const override;\n    void setVisible(bool visible) override;\n\n    QWellArray *custom;\n    QWellArray *standard;\n\n    QDialogButtonBox *buttons;\n    QVBoxLayout *leftLay;\n    QColorPicker *cp;\n    QColorLuminancePicker *lp;\n    QColorShower *cs;\n    QLabel *lblBasicColors;\n    QLabel *lblCustomColors;\n    QLabel *lblScreenColorInfo;\n    QPushButton *ok;\n    QPushButton *cancel;\n    QPushButton *addCusBt;\n    QPushButton *eyeDropperButton = nullptr;\n    QColor selectedQColor;\n    int nextCust;\n    bool smallDisplay;\n    bool screenColorPicking;\n    QColorPickingEventFilter *colorPickingEventFilter;\n    QRgb beforeScreenColorPicking;\n    QSharedPointer<QColorDialogOptions> options;\n\n    QPointer<QObject> receiverToDisconnectOnClose;\n    QByteArray memberToDisconnectOnClose;\n#ifdef Q_OS_WIN32\n    QTimer *updateTimer;\n    QWindow dummyTransparentWindow;\n#endif\n\nprivate:\n    virtual void initHelper(QPlatformDialogHelper *h) override;\n    virtual void helperPrepareShow(QPlatformDialogHelper *h) override;\n};\n\n//////////// QWellArray BEGIN\n\nnamespace QtPrivate {\n\nclass QWellArray : public QWidget\n{\n    Q_OBJECT\n    Q_PROPERTY(int selectedColumn READ selectedColumn)\n    Q_PROPERTY(int selectedRow READ selectedRow)\n\npublic:\n    QWellArray(int rows, int cols, QWidget* parent=nullptr);\n    ~QWellArray() {}\n    QString cellContent(int row, int col) const;\n\n    int selectedColumn() const { return selCol; }\n    int selectedRow() const { return selRow; }\n\n    virtual void setCurrent(int row, int col);\n    virtual void setSelected(int row, int col);\n\n    QSize sizeHint() const override;\n\n    inline int cellWidth() const\n        { return cellw; }\n\n    inline int cellHeight() const\n        { return cellh; }\n\n    inline int rowAt(int y) const\n        { return y / cellh; }\n\n    inline int columnAt(int x) const\n        { if (isRightToLeft()) return ncols - (x / cellw) - 1; return x / cellw; }\n\n    inline int rowY(int row) const\n        { return cellh * row; }\n\n    inline int columnX(int column) const\n        { if (isRightToLeft()) return cellw * (ncols - column - 1); return cellw * column; }\n\n    inline int numRows() const\n        { return nrows; }\n\n    inline int numCols() const\n        {return ncols; }\n\n    inline QRect cellRect() const\n        { return QRect(0, 0, cellw, cellh); }\n\n    inline QSize gridSize() const\n        { return QSize(ncols * cellw, nrows * cellh); }\n\n    QRect cellGeometry(int row, int column)\n        {\n            QRect r;\n            if (row >= 0 && row < nrows && column >= 0 && column < ncols)\n                r.setRect(columnX(column), rowY(row), cellw, cellh);\n            return r;\n        }\n\n    inline void updateCell(int row, int column) { update(cellGeometry(row, column)); }\n\nsignals:\n    void selected(int row, int col);\n    void currentChanged(int row, int col);\n    void colorChanged(int index, QRgb color);\n\nprotected:\n    virtual void paintCell(QPainter *, int row, int col, const QRect&);\n    virtual void paintCellContents(QPainter *, int row, int col, const QRect&);\n\n    void mousePressEvent(QMouseEvent*) override;\n    void mouseReleaseEvent(QMouseEvent*) override;\n    void keyPressEvent(QKeyEvent*) override;\n    void focusInEvent(QFocusEvent*) override;\n    void focusOutEvent(QFocusEvent*) override;\n    void paintEvent(QPaintEvent *) override;\n\nprivate:\n    Q_DISABLE_COPY(QWellArray)\n\n    int nrows;\n    int ncols;\n    int cellw;\n    int cellh;\n    int curRow;\n    int curCol;\n    int selRow;\n    int selCol;\n};\n\nvoid QWellArray::paintEvent(QPaintEvent *e)\n{\n    QRect r = e->rect();\n    int cx = r.x();\n    int cy = r.y();\n    int ch = r.height();\n    int cw = r.width();\n    int colfirst = columnAt(cx);\n    int collast = columnAt(cx + cw);\n    int rowfirst = rowAt(cy);\n    int rowlast = rowAt(cy + ch);\n\n    if (isRightToLeft()) {\n        int t = colfirst;\n        colfirst = collast;\n        collast = t;\n    }\n\n    QPainter painter(this);\n    QPainter *p = &painter;\n    QRect rect(0, 0, cellWidth(), cellHeight());\n\n\n    if (collast < 0 || collast >= ncols)\n        collast = ncols-1;\n    if (rowlast < 0 || rowlast >= nrows)\n        rowlast = nrows-1;\n\n    // Go through the rows\n    for (int r = rowfirst; r <= rowlast; ++r) {\n        // get row position and height\n        int rowp = rowY(r);\n\n        // Go through the columns in the row r\n        // if we know from where to where, go through [colfirst, collast],\n        // else go through all of them\n        for (int c = colfirst; c <= collast; ++c) {\n            // get position and width of column c\n            int colp = columnX(c);\n            // Translate painter and draw the cell\n            rect.translate(colp, rowp);\n            paintCell(p, r, c, rect);\n            rect.translate(-colp, -rowp);\n        }\n    }\n}\n\nQWellArray::QWellArray(int rows, int cols, QWidget *parent)\n    : QWidget(parent)\n        ,nrows(rows), ncols(cols)\n{\n    setFocusPolicy(Qt::StrongFocus);\n    cellw = 28;\n    cellh = 24;\n    curCol = 0;\n    curRow = 0;\n    selCol = -1;\n    selRow = -1;\n}\n\nQSize QWellArray::sizeHint() const\n{\n    ensurePolished();\n    return gridSize().boundedTo(QSize(640, 480));\n}\n\n\nvoid QWellArray::paintCell(QPainter* p, int row, int col, const QRect &rect)\n{\n    int b = 3; //margin\n\n    const QPalette & g = palette();\n    QStyleOptionFrame opt;\n    opt.initFrom(this);\n    int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this);\n    opt.lineWidth = dfw;\n    opt.midLineWidth = 1;\n    opt.rect = rect.adjusted(b, b, -b, -b);\n    opt.palette = g;\n    opt.state = QStyle::State_Enabled | QStyle::State_Sunken;\n    style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this);\n    b += dfw;\n\n    if ((row == curRow) && (col == curCol)) {\n        if (hasFocus()) {\n            QStyleOptionFocusRect opt;\n            opt.palette = g;\n            opt.rect = rect;\n            opt.state = QStyle::State_None | QStyle::State_KeyboardFocusChange;\n            style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, this);\n        }\n    }\n    paintCellContents(p, row, col, opt.rect.adjusted(dfw, dfw, -dfw, -dfw));\n}\n\n/*\n  Reimplement this function to change the contents of the well array.\n */\nvoid QWellArray::paintCellContents(QPainter *p, int row, int col, const QRect &r)\n{\n    Q_UNUSED(row);\n    Q_UNUSED(col);\n    p->fillRect(r, Qt::white);\n    p->setPen(Qt::black);\n    p->drawLine(r.topLeft(), r.bottomRight());\n    p->drawLine(r.topRight(), r.bottomLeft());\n}\n\nvoid QWellArray::mousePressEvent(QMouseEvent *e)\n{\n    // The current cell marker is set to the cell the mouse is pressed in\n    QPoint pos = e->position().toPoint();\n    setCurrent(rowAt(pos.y()), columnAt(pos.x()));\n}\n\nvoid QWellArray::mouseReleaseEvent(QMouseEvent * /* event */)\n{\n    // The current cell marker is set to the cell the mouse is clicked in\n    setSelected(curRow, curCol);\n}\n\n\n/*\n  Sets the cell currently having the focus. This is not necessarily\n  the same as the currently selected cell.\n*/\n\nvoid QWellArray::setCurrent(int row, int col)\n{\n    if ((curRow == row) && (curCol == col))\n        return;\n\n    if (row < 0 || col < 0)\n        row = col = -1;\n\n    int oldRow = curRow;\n    int oldCol = curCol;\n\n    curRow = row;\n    curCol = col;\n\n    updateCell(oldRow, oldCol);\n    updateCell(curRow, curCol);\n\n    emit currentChanged(curRow, curCol);\n}\n\n/*\n  Sets the currently selected cell to \\a row, \\a column. If \\a row or\n  \\a column are less than zero, the current cell is unselected.\n\n  Does not set the position of the focus indicator.\n*/\nvoid QWellArray::setSelected(int row, int col)\n{\n    int oldRow = selRow;\n    int oldCol = selCol;\n\n    if (row < 0 || col < 0)\n        row = col = -1;\n\n    selCol = col;\n    selRow = row;\n\n    updateCell(oldRow, oldCol);\n    updateCell(selRow, selCol);\n    if (row >= 0)\n        emit selected(row, col);\n\n#if QT_CONFIG(menu)\n    if (isVisible() && qobject_cast<QMenu*>(parentWidget()))\n        parentWidget()->close();\n#endif\n}\n\nvoid QWellArray::focusInEvent(QFocusEvent*)\n{\n    updateCell(curRow, curCol);\n    emit currentChanged(curRow, curCol);\n}\n\n\nvoid QWellArray::focusOutEvent(QFocusEvent*)\n{\n    updateCell(curRow, curCol);\n}\n\nvoid QWellArray::keyPressEvent(QKeyEvent* e)\n{\n    switch(e->key()) {                        // Look at the key code\n    case Qt::Key_Left:                                // If 'left arrow'-key,\n        if (curCol > 0)                        // and cr't not in leftmost col\n            setCurrent(curRow, curCol - 1);        // set cr't to next left column\n        break;\n    case Qt::Key_Right:                                // Correspondingly...\n        if (curCol < numCols()-1)\n            setCurrent(curRow, curCol + 1);\n        break;\n    case Qt::Key_Up:\n        if (curRow > 0)\n            setCurrent(curRow - 1, curCol);\n        break;\n    case Qt::Key_Down:\n        if (curRow < numRows()-1)\n            setCurrent(curRow + 1, curCol);\n        break;\n#if 0\n    // bad idea that shouldn't have been implemented; very counterintuitive\n    case Qt::Key_Return:\n    case Qt::Key_Enter:\n        /*\n          ignore the key, so that the dialog get it, but still select\n          the current row/col\n        */\n        e->ignore();\n        // fallthrough intended\n#endif\n    case Qt::Key_Space:\n        setSelected(curRow, curCol);\n        break;\n    default:                                // If not an interesting key,\n        e->ignore();                        // we don't accept the event\n        return;\n    }\n\n} // namespace QtPrivate\n\n//////////// QWellArray END\n\n// Event filter to be installed on the dialog while in color-picking mode.\nclass QColorPickingEventFilter : public QObject {\npublic:\n    explicit QColorPickingEventFilter(QColorDialogPrivate *dp, QObject *parent) : QObject(parent), m_dp(dp) {}\n\n    bool eventFilter(QObject *, QEvent *event) override\n    {\n        switch (event->type()) {\n        case QEvent::MouseMove:\n            return m_dp->handleColorPickingMouseMove(static_cast<QMouseEvent *>(event));\n        case QEvent::MouseButtonRelease:\n            return m_dp->handleColorPickingMouseButtonRelease(static_cast<QMouseEvent *>(event));\n        case QEvent::KeyPress:\n            return m_dp->handleColorPickingKeyPress(static_cast<QKeyEvent *>(event));\n        default:\n            break;\n        }\n        return false;\n    }\n\nprivate:\n    QColorDialogPrivate *m_dp;\n};\n\n} // unnamed namespace\n\n/*!\n    Returns the number of custom colors supported by QColorDialog. All\n    color dialogs share the same custom colors.\n*/\nint QColorDialog::customCount()\n{\n    return QColorDialogOptions::customColorCount();\n}\n\n/*!\n    Returns the custom color at the given \\a index as a QColor value.\n*/\nQColor QColorDialog::customColor(int index)\n{\n    return QColor(QColorDialogOptions::customColor(index));\n}\n\n/*!\n    Sets the custom color at \\a index to the QColor \\a color value.\n\n    \\note This function does not apply to the Native Color Dialog on the\n    \\macos platform. If you still require this function, use the\n    QColorDialog::DontUseNativeDialog option.\n*/\nvoid QColorDialog::setCustomColor(int index, QColor color)\n{\n    QColorDialogOptions::setCustomColor(index, color.rgba());\n}\n\n/*!\n    \\since 5.0\n\n    Returns the standard color at the given \\a index as a QColor value.\n*/\nQColor QColorDialog::standardColor(int index)\n{\n    return QColor(QColorDialogOptions::standardColor(index));\n}\n\n/*!\n    Sets the standard color at \\a index to the QColor \\a color value.\n\n    \\note This function does not apply to the Native Color Dialog on the\n    \\macos platform. If you still require this function, use the\n    QColorDialog::DontUseNativeDialog option.\n*/\nvoid QColorDialog::setStandardColor(int index, QColor color)\n{\n    QColorDialogOptions::setStandardColor(index, color.rgba());\n}\n\nstatic inline void rgb2hsv(QRgb rgb, int &h, int &s, int &v)\n{\n    QColor c;\n    c.setRgb(rgb);\n    c.getHsv(&h, &s, &v);\n}\n\nnamespace QtPrivate {\n\nclass QColorWell : public QWellArray\n{\npublic:\n    QColorWell(QWidget *parent, int r, int c, const QRgb *vals)\n        :QWellArray(r, c, parent), values(vals), mousePressed(false), oldCurrent(-1, -1)\n    { setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); }\n\nprotected:\n    void paintCellContents(QPainter *, int row, int col, const QRect&) override;\n    void mousePressEvent(QMouseEvent *e) override;\n    void mouseMoveEvent(QMouseEvent *e) override;\n    void mouseReleaseEvent(QMouseEvent *e) override;\n#if QT_CONFIG(draganddrop)\n    void dragEnterEvent(QDragEnterEvent *e) override;\n    void dragLeaveEvent(QDragLeaveEvent *e) override;\n    void dragMoveEvent(QDragMoveEvent *e) override;\n    void dropEvent(QDropEvent *e) override;\n#endif\n\nprivate:\n    const QRgb *values;\n    bool mousePressed;\n    QPoint pressPos;\n    QPoint oldCurrent;\n\n};\n\nvoid QColorWell::paintCellContents(QPainter *p, int row, int col, const QRect &r)\n{\n    int i = row + col*numRows();\n    p->fillRect(r, QColor(values[i]));\n}\n\nvoid QColorWell::mousePressEvent(QMouseEvent *e)\n{\n    oldCurrent = QPoint(selectedRow(), selectedColumn());\n    QWellArray::mousePressEvent(e);\n    mousePressed = true;\n    pressPos = e->position().toPoint();\n}\n\nvoid QColorWell::mouseMoveEvent(QMouseEvent *e)\n{\n    QWellArray::mouseMoveEvent(e);\n#if QT_CONFIG(draganddrop)\n    if (!mousePressed)\n        return;\n    if ((pressPos - e->position().toPoint()).manhattanLength() > QApplication::startDragDistance()) {\n        setCurrent(oldCurrent.x(), oldCurrent.y());\n        int i = rowAt(pressPos.y()) + columnAt(pressPos.x()) * numRows();\n        QColor col(values[i]);\n        QMimeData *mime = new QMimeData;\n        mime->setColorData(col);\n        QPixmap pix(cellWidth(), cellHeight());\n        pix.fill(col);\n        QPainter p(&pix);\n        p.drawRect(0, 0, pix.width() - 1, pix.height() - 1);\n        p.end();\n        QDrag *drg = new QDrag(this);\n        drg->setMimeData(mime);\n        drg->setPixmap(pix);\n        mousePressed = false;\n        drg->exec(Qt::CopyAction);\n    }\n#endif\n}\n\n#if QT_CONFIG(draganddrop)\nvoid QColorWell::dragEnterEvent(QDragEnterEvent *e)\n{\n    if (qvariant_cast<QColor>(e->mimeData()->colorData()).isValid())\n        e->accept();\n    else\n        e->ignore();\n}\n\nvoid QColorWell::dragLeaveEvent(QDragLeaveEvent *)\n{\n    if (hasFocus())\n        parentWidget()->setFocus();\n}\n\nvoid QColorWell::dragMoveEvent(QDragMoveEvent *e)\n{\n    if (qvariant_cast<QColor>(e->mimeData()->colorData()).isValid()) {\n        setCurrent(rowAt(e->position().toPoint().y()), columnAt(e->position().toPoint().x()));\n        e->accept();\n    } else {\n        e->ignore();\n    }\n}\n\nvoid QColorWell::dropEvent(QDropEvent *e)\n{\n    QColor col = qvariant_cast<QColor>(e->mimeData()->colorData());\n    if (col.isValid()) {\n        int i = rowAt(e->position().toPoint().y()) + columnAt(e->position().toPoint().x()) * numRows();\n        emit colorChanged(i, col.rgb());\n        e->accept();\n    } else {\n        e->ignore();\n    }\n}\n\n#endif // QT_CONFIG(draganddrop)\n\nvoid QColorWell::mouseReleaseEvent(QMouseEvent *e)\n{\n    if (!mousePressed)\n        return;\n    QWellArray::mouseReleaseEvent(e);\n    mousePressed = false;\n}\n\nclass QColorPicker : public QFrame\n{\n    Q_OBJECT\npublic:\n    QColorPicker(QWidget* parent);\n    ~QColorPicker();\n\n    void setCrossVisible(bool visible);\npublic slots:\n    void setCol(int h, int s);\n\nsignals:\n    void newCol(int h, int s);\n\nprotected:\n    QSize sizeHint() const override;\n    void paintEvent(QPaintEvent*) override;\n    void mouseMoveEvent(QMouseEvent *) override;\n    void mousePressEvent(QMouseEvent *) override;\n    void resizeEvent(QResizeEvent *) override;\n\nprivate:\n    int hue;\n    int sat;\n\n    QPoint colPt();\n    int huePt(const QPoint &pt);\n    int satPt(const QPoint &pt);\n    void setCol(const QPoint &pt);\n\n    QPixmap pix;\n    bool crossVisible;\n};\n\n} // namespace QtPrivate\n\nstatic int pWidth = 220;\nstatic int pHeight = 200;\n\nnamespace QtPrivate {\n\nclass QColorLuminancePicker : public QWidget\n{\n    Q_OBJECT\npublic:\n    QColorLuminancePicker(QWidget* parent=nullptr);\n    ~QColorLuminancePicker();\n\npublic slots:\n    void setCol(int h, int s, int v);\n    void setCol(int h, int s);\n\nsignals:\n    void newHsv(int h, int s, int v);\n\nprotected:\n    void paintEvent(QPaintEvent*) override;\n    void mouseMoveEvent(QMouseEvent *) override;\n    void mousePressEvent(QMouseEvent *) override;\n\nprivate:\n    enum { foff = 3, coff = 4 }; //frame and contents offset\n    int val;\n    int hue;\n    int sat;\n\n    int y2val(int y);\n    int val2y(int val);\n    void setVal(int v);\n\n    QPixmap *pix;\n};\n\n\nint QColorLuminancePicker::y2val(int y)\n{\n    int d = height() - 2*coff - 1;\n    return 255 - (y - coff)*255/d;\n}\n\nint QColorLuminancePicker::val2y(int v)\n{\n    int d = height() - 2*coff - 1;\n    return coff + (255-v)*d/255;\n}\n\nQColorLuminancePicker::QColorLuminancePicker(QWidget* parent)\n    :QWidget(parent)\n{\n    hue = 100; val = 100; sat = 100;\n    pix = nullptr;\n    //    setAttribute(WA_NoErase, true);\n}\n\nQColorLuminancePicker::~QColorLuminancePicker()\n{\n    delete pix;\n}\n\nvoid QColorLuminancePicker::mouseMoveEvent(QMouseEvent *m)\n{\n    if (m->buttons() == Qt::NoButton) {\n        m->ignore();\n        return;\n    }\n    setVal(y2val(m->position().toPoint().y()));\n}\nvoid QColorLuminancePicker::mousePressEvent(QMouseEvent *m)\n{\n    setVal(y2val(m->position().toPoint().y()));\n}\n\nvoid QColorLuminancePicker::setVal(int v)\n{\n    if (val == v)\n        return;\n    val = qMax(0, qMin(v,255));\n    delete pix; pix=nullptr;\n    repaint();\n    emit newHsv(hue, sat, val);\n}\n\n//receives from a hue,sat chooser and relays.\nvoid QColorLuminancePicker::setCol(int h, int s)\n{\n    setCol(h, s, val);\n    emit newHsv(h, s, val);\n}\n\nvoid QColorLuminancePicker::paintEvent(QPaintEvent *)\n{\n    int w = width() - 5;\n\n    QRect r(0, foff, w, height() - 2*foff);\n    int wi = r.width() - 2;\n    int hi = r.height() - 2;\n    if (!pix || pix->height() != hi || pix->width() != wi) {\n        delete pix;\n        QImage img(wi, hi, QImage::Format_RGB32);\n        int y;\n        uint *pixel = (uint *) img.scanLine(0);\n        for (y = 0; y < hi; y++) {\n            uint *end = pixel + wi;\n            std::fill(pixel, end, QColor::fromHsv(hue, sat, y2val(y + coff)).rgb());\n            pixel = end;\n        }\n        pix = new QPixmap(QPixmap::fromImage(img));\n    }\n    QPainter p(this);\n    p.drawPixmap(1, coff, *pix);\n    const QPalette &g = palette();\n    qDrawShadePanel(&p, r, g, true);\n    p.setPen(g.windowText().color());\n    p.setBrush(g.windowText());\n    p.eraseRect(w, 0, 5, height());\n    const int y = val2y(val);\n    const std::array<QPoint, 3> points = {QPoint(w, y), QPoint(w + 5, y + 5), QPoint(w + 5, y - 5)};\n    p.drawPolygon(points.data(), static_cast<int>(points.size()));\n}\n\nvoid QColorLuminancePicker::setCol(int h, int s , int v)\n{\n    val = v;\n    hue = h;\n    sat = s;\n    delete pix; pix=nullptr;\n    repaint();\n}\n\nQPoint QColorPicker::colPt()\n{\n    QRect r = contentsRect();\n    return QPoint((360 - hue) * (r.width() - 1) / 360, (255 - sat) * (r.height() - 1) / 255);\n}\n\nint QColorPicker::huePt(const QPoint &pt)\n{\n    QRect r = contentsRect();\n    return 360 - pt.x() * 360 / (r.width() - 1);\n}\n\nint QColorPicker::satPt(const QPoint &pt)\n{\n    QRect r = contentsRect();\n    return 255 - pt.y() * 255 / (r.height() - 1);\n}\n\nvoid QColorPicker::setCol(const QPoint &pt)\n{\n    setCol(huePt(pt), satPt(pt));\n}\n\nQColorPicker::QColorPicker(QWidget* parent)\n    : QFrame(parent)\n    , crossVisible(true)\n{\n    hue = 0; sat = 0;\n    setCol(150, 255);\n\n    setAttribute(Qt::WA_NoSystemBackground);\n    setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) );\n}\n\nQColorPicker::~QColorPicker()\n{\n}\n\nvoid QColorPicker::setCrossVisible(bool visible)\n{\n    if (crossVisible != visible) {\n        crossVisible = visible;\n        update();\n    }\n}\n\nQSize QColorPicker::sizeHint() const\n{\n    return QSize(pWidth + 2*frameWidth(), pHeight + 2*frameWidth());\n}\n\nvoid QColorPicker::setCol(int h, int s)\n{\n    int nhue = qMin(qMax(0,h), 359);\n    int nsat = qMin(qMax(0,s), 255);\n    if (nhue == hue && nsat == sat)\n        return;\n\n    QRect r(colPt(), QSize(20,20));\n    hue = nhue; sat = nsat;\n    r = r.united(QRect(colPt(), QSize(20,20)));\n    r.translate(contentsRect().x()-9, contentsRect().y()-9);\n    //    update(r);\n    repaint(r);\n}\n\nvoid QColorPicker::mouseMoveEvent(QMouseEvent *m)\n{\n    QPoint p = m->position().toPoint() - contentsRect().topLeft();\n    if (m->buttons() == Qt::NoButton) {\n        m->ignore();\n        return;\n    }\n    setCol(p);\n    emit newCol(hue, sat);\n}\n\nvoid QColorPicker::mousePressEvent(QMouseEvent *m)\n{\n    QPoint p = m->position().toPoint() - contentsRect().topLeft();\n    setCol(p);\n    emit newCol(hue, sat);\n}\n\nvoid QColorPicker::paintEvent(QPaintEvent* )\n{\n    QPainter p(this);\n    drawFrame(&p);\n    QRect r = contentsRect();\n\n    p.drawPixmap(r.topLeft(), pix);\n\n    if (crossVisible) {\n        QPoint pt = colPt() + r.topLeft();\n        p.setPen(Qt::black);\n        p.fillRect(pt.x()-9, pt.y(), 20, 2, Qt::black);\n        p.fillRect(pt.x(), pt.y()-9, 2, 20, Qt::black);\n    }\n}\n\nvoid QColorPicker::resizeEvent(QResizeEvent *ev)\n{\n    QFrame::resizeEvent(ev);\n\n    int w = width() - frameWidth() * 2;\n    int h = height() - frameWidth() * 2;\n    QImage img(w, h, QImage::Format_RGB32);\n    int x, y;\n    uint *pixel = (uint *) img.scanLine(0);\n    for (y = 0; y < h; y++) {\n        const uint *end = pixel + w;\n        x = 0;\n        while (pixel < end) {\n            QPoint p(x, y);\n            QColor c;\n            c.setHsv(huePt(p), satPt(p), 200);\n            *pixel = c.rgb();\n            ++pixel;\n            ++x;\n        }\n    }\n    pix = QPixmap::fromImage(img);\n}\n\n\nclass QColSpinBox : public QSpinBox\n{\npublic:\n    QColSpinBox(QWidget *parent)\n        : QSpinBox(parent) { setRange(0, 255); }\n    void setValue(int i) {\n        const QSignalBlocker blocker(this);\n        QSpinBox::setValue(i);\n    }\n};\n\nclass QColorShowLabel;\n\nclass QColorShower : public QWidget\n{\n    Q_OBJECT\npublic:\n    QColorShower(QColorDialog *parent);\n\n    //things that don't emit signals\n    void setHsv(int h, int s, int v);\n\n    int currentAlpha() const\n    { return (colorDialog->options() & QColorDialog::ShowAlphaChannel) ? alphaEd->value() : 255; }\n    void setCurrentAlpha(int a) { alphaEd->setValue(a); rgbEd(); }\n    void showAlpha(bool b);\n    bool isAlphaVisible() const;\n\n    QRgb currentColor() const { return curCol; }\n    QColor currentQColor() const { return curQColor; }\n    void retranslateStrings();\n    void updateQColor();\n\npublic slots:\n    void setRgb(QRgb rgb);\n\nsignals:\n    void newCol(QRgb rgb);\n    void currentColorChanged(const QColor &color);\n\nprivate slots:\n    void rgbEd();\n    void hsvEd();\n    void htmlEd();\n\nprivate:\n    void showCurrentColor();\n    int hue, sat, val;\n    QRgb curCol;\n    QColor curQColor;\n    QLabel *lblHue;\n    QLabel *lblSat;\n    QLabel *lblVal;\n    QLabel *lblRed;\n    QLabel *lblGreen;\n    QLabel *lblBlue;\n    QLabel *lblHtml;\n    QColSpinBox *hEd;\n    QColSpinBox *sEd;\n    QColSpinBox *vEd;\n    QColSpinBox *rEd;\n    QColSpinBox *gEd;\n    QColSpinBox *bEd;\n    QColSpinBox *alphaEd;\n    QLabel *alphaLab;\n    QLineEdit *htEd;\n    QColorShowLabel *lab;\n    bool rgbOriginal;\n    QColorDialog *colorDialog;\n    QGridLayout *gl;\n\n    friend class QT_PREPEND_NAMESPACE(QColorDialog);\n    friend class QT_PREPEND_NAMESPACE(QColorDialogPrivate);\n};\n\nclass QColorShowLabel : public QFrame\n{\n    Q_OBJECT\n\npublic:\n    QColorShowLabel(QWidget *parent) : QFrame(parent) {\n        setFrameStyle(QFrame::Panel|QFrame::Sunken);\n        setAcceptDrops(true);\n        mousePressed = false;\n    }\n    void setColor(QColor c) { col = c; }\n\nsignals:\n    void colorDropped(QRgb);\n\nprotected:\n    void paintEvent(QPaintEvent *) override;\n    void mousePressEvent(QMouseEvent *e) override;\n    void mouseMoveEvent(QMouseEvent *e) override;\n    void mouseReleaseEvent(QMouseEvent *e) override;\n#if QT_CONFIG(draganddrop)\n    void dragEnterEvent(QDragEnterEvent *e) override;\n    void dragLeaveEvent(QDragLeaveEvent *e) override;\n    void dropEvent(QDropEvent *e) override;\n#endif\n\nprivate:\n    QColor col;\n    bool mousePressed;\n    QPoint pressPos;\n};\n\nvoid QColorShowLabel::paintEvent(QPaintEvent *e)\n{\n    QPainter p(this);\n    drawFrame(&p);\n    p.fillRect(contentsRect()&e->rect(), col);\n}\n\nvoid QColorShower::showAlpha(bool b)\n{\n    alphaLab->setVisible(b);\n    alphaEd->setVisible(b);\n}\n\ninline bool QColorShower::isAlphaVisible() const\n{\n    return alphaLab->isVisible();\n}\n\nvoid QColorShowLabel::mousePressEvent(QMouseEvent *e)\n{\n    mousePressed = true;\n    pressPos = e->position().toPoint();\n}\n\nvoid QColorShowLabel::mouseMoveEvent(QMouseEvent *e)\n{\n#if !QT_CONFIG(draganddrop)\n    Q_UNUSED(e);\n#else\n    if (!mousePressed)\n        return;\n    if ((pressPos - e->position().toPoint()).manhattanLength() > QApplication::startDragDistance()) {\n        QMimeData *mime = new QMimeData;\n        mime->setColorData(col);\n        QPixmap pix(30, 20);\n        pix.fill(col);\n        QPainter p(&pix);\n        p.drawRect(0, 0, pix.width() - 1, pix.height() - 1);\n        p.end();\n        QDrag *drg = new QDrag(this);\n        drg->setMimeData(mime);\n        drg->setPixmap(pix);\n        mousePressed = false;\n        drg->exec(Qt::CopyAction);\n    }\n#endif\n}\n\n#if QT_CONFIG(draganddrop)\nvoid QColorShowLabel::dragEnterEvent(QDragEnterEvent *e)\n{\n    if (qvariant_cast<QColor>(e->mimeData()->colorData()).isValid())\n        e->accept();\n    else\n        e->ignore();\n}\n\nvoid QColorShowLabel::dragLeaveEvent(QDragLeaveEvent *)\n{\n}\n\nvoid QColorShowLabel::dropEvent(QDropEvent *e)\n{\n    QColor color = qvariant_cast<QColor>(e->mimeData()->colorData());\n    if (color.isValid()) {\n        col = color;\n        repaint();\n        emit colorDropped(col.rgb());\n        e->accept();\n    } else {\n        e->ignore();\n    }\n}\n#endif // QT_CONFIG(draganddrop)\n\nvoid QColorShowLabel::mouseReleaseEvent(QMouseEvent *)\n{\n    if (!mousePressed)\n        return;\n    mousePressed = false;\n}\n\nQColorShower::QColorShower(QColorDialog *parent)\n    : QWidget(parent)\n{\n    colorDialog = parent;\n\n    curCol = qRgb(255, 255, 255);\n    curQColor = Qt::white;\n\n    gl = new QGridLayout(this);\n    const int s = gl->spacing();\n    gl->setContentsMargins(s, s, s, s);\n    lab = new QColorShowLabel(this);\n\n#ifdef QT_SMALL_COLORDIALOG\n    lab->setMinimumHeight(60);\n#endif\n    lab->setMinimumWidth(60);\n\n// For QVGA screens only the comboboxes and color label are visible.\n// For nHD screens only color and luminence pickers and color label are visible.\n#if !defined(QT_SMALL_COLORDIALOG)\n    gl->addWidget(lab, 0, 0, -1, 1);\n#else\n    gl->addWidget(lab, 0, 0, 1, -1);\n#endif\n    connect(lab, &QColorShowLabel::colorDropped, this, &QColorShower::newCol);\n    connect(lab, &QColorShowLabel::colorDropped, this, &QColorShower::setRgb);\n\n    hEd = new QColSpinBox(this);\n    hEd->setRange(0, 359);\n    lblHue = new QLabel(this);\n#ifndef QT_NO_SHORTCUT\n    lblHue->setBuddy(hEd);\n#endif\n    lblHue->setAlignment(Qt::AlignRight|Qt::AlignVCenter);\n#if !defined(QT_SMALL_COLORDIALOG)\n    gl->addWidget(lblHue, 0, 1);\n    gl->addWidget(hEd, 0, 2);\n#else\n    gl->addWidget(lblHue, 1, 0);\n    gl->addWidget(hEd, 2, 0);\n#endif\n\n    sEd = new QColSpinBox(this);\n    lblSat = new QLabel(this);\n#ifndef QT_NO_SHORTCUT\n    lblSat->setBuddy(sEd);\n#endif\n    lblSat->setAlignment(Qt::AlignRight|Qt::AlignVCenter);\n#if !defined(QT_SMALL_COLORDIALOG)\n    gl->addWidget(lblSat, 1, 1);\n    gl->addWidget(sEd, 1, 2);\n#else\n    gl->addWidget(lblSat, 1, 1);\n    gl->addWidget(sEd, 2, 1);\n#endif\n\n    vEd = new QColSpinBox(this);\n    lblVal = new QLabel(this);\n#ifndef QT_NO_SHORTCUT\n    lblVal->setBuddy(vEd);\n#endif\n    lblVal->setAlignment(Qt::AlignRight|Qt::AlignVCenter);\n#if !defined(QT_SMALL_COLORDIALOG)\n    gl->addWidget(lblVal, 2, 1);\n    gl->addWidget(vEd, 2, 2);\n#else\n    gl->addWidget(lblVal, 1, 2);\n    gl->addWidget(vEd, 2, 2);\n#endif\n\n    rEd = new QColSpinBox(this);\n    lblRed = new QLabel(this);\n#ifndef QT_NO_SHORTCUT\n    lblRed->setBuddy(rEd);\n#endif\n    lblRed->setAlignment(Qt::AlignRight|Qt::AlignVCenter);\n#if !defined(QT_SMALL_COLORDIALOG)\n    gl->addWidget(lblRed, 0, 3);\n    gl->addWidget(rEd, 0, 4);\n#else\n    gl->addWidget(lblRed, 3, 0);\n    gl->addWidget(rEd, 4, 0);\n#endif\n\n    gEd = new QColSpinBox(this);\n    lblGreen = new QLabel(this);\n#ifndef QT_NO_SHORTCUT\n    lblGreen->setBuddy(gEd);\n#endif\n    lblGreen->setAlignment(Qt::AlignRight|Qt::AlignVCenter);\n#if !defined(QT_SMALL_COLORDIALOG)\n    gl->addWidget(lblGreen, 1, 3);\n    gl->addWidget(gEd, 1, 4);\n#else\n    gl->addWidget(lblGreen, 3, 1);\n    gl->addWidget(gEd, 4, 1);\n#endif\n\n    bEd = new QColSpinBox(this);\n    lblBlue = new QLabel(this);\n#ifndef QT_NO_SHORTCUT\n    lblBlue->setBuddy(bEd);\n#endif\n    lblBlue->setAlignment(Qt::AlignRight|Qt::AlignVCenter);\n#if !defined(QT_SMALL_COLORDIALOG)\n    gl->addWidget(lblBlue, 2, 3);\n    gl->addWidget(bEd, 2, 4);\n#else\n    gl->addWidget(lblBlue, 3, 2);\n    gl->addWidget(bEd, 4, 2);\n#endif\n\n    alphaEd = new QColSpinBox(this);\n    alphaLab = new QLabel(this);\n#ifndef QT_NO_SHORTCUT\n    alphaLab->setBuddy(alphaEd);\n#endif\n    alphaLab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);\n#if !defined(QT_SMALL_COLORDIALOG)\n    gl->addWidget(alphaLab, 3, 1, 1, 3);\n    gl->addWidget(alphaEd, 3, 4);\n#else\n    gl->addWidget(alphaLab, 1, 3, 3, 1);\n    gl->addWidget(alphaEd, 4, 3);\n#endif\n    alphaEd->hide();\n    alphaLab->hide();\n    lblHtml = new QLabel(this);\n    htEd = new QLineEdit(this);\n    htEd->setObjectName(\"qt_colorname_lineedit\");\n#ifndef QT_NO_SHORTCUT\n    lblHtml->setBuddy(htEd);\n#endif\n\n#if QT_CONFIG(regularexpression)\n    QRegularExpression regExp(QStringLiteral(\"#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\"));\n    QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, this);\n    htEd->setValidator(validator);\n#else\n    htEd->setReadOnly(true);\n#endif\n    htEd->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);\n\n    lblHtml->setAlignment(Qt::AlignRight|Qt::AlignVCenter);\n#if defined(QT_SMALL_COLORDIALOG)\n    gl->addWidget(lblHtml, 5, 0);\n    gl->addWidget(htEd, 5, 1, 1, /*colspan=*/ 2);\n#else\n    gl->addWidget(lblHtml, 5, 1);\n    gl->addWidget(htEd, 5, 2, 1, /*colspan=*/ 3);\n#endif\n\n    connect(hEd, &QSpinBox::valueChanged, this, &QColorShower::hsvEd);\n    connect(sEd, &QSpinBox::valueChanged, this, &QColorShower::hsvEd);\n    connect(vEd, &QSpinBox::valueChanged, this, &QColorShower::hsvEd);\n\n    connect(rEd, &QSpinBox::valueChanged, this, &QColorShower::rgbEd);\n    connect(gEd, &QSpinBox::valueChanged, this, &QColorShower::rgbEd);\n    connect(bEd, &QSpinBox::valueChanged, this, &QColorShower::rgbEd);\n    connect(alphaEd, &QSpinBox::valueChanged, this, &QColorShower::rgbEd);\n    connect(htEd, &QLineEdit::textEdited, this, &QColorShower::htmlEd);\n\n    retranslateStrings();\n}\n\n} // namespace QtPrivate\n\ninline QRgb QColorDialogPrivate::currentColor() const { return cs->currentColor(); }\ninline int QColorDialogPrivate::currentAlpha() const { return cs->currentAlpha(); }\ninline void QColorDialogPrivate::setCurrentAlpha(int a) { cs->setCurrentAlpha(a); }\ninline void QColorDialogPrivate::showAlpha(bool b) { cs->showAlpha(b); }\ninline bool QColorDialogPrivate::isAlphaVisible() const { return cs->isAlphaVisible(); }\n\nQColor QColorDialogPrivate::currentQColor() const\n{\n    if (nativeDialogInUse)\n        return platformColorDialogHelper()->currentColor();\n    return cs->currentQColor();\n}\n\nvoid QColorShower::showCurrentColor()\n{\n    lab->setColor(currentColor());\n    lab->repaint();\n}\n\nvoid QColorShower::rgbEd()\n{\n    rgbOriginal = true;\n    curCol = qRgba(rEd->value(), gEd->value(), bEd->value(), currentAlpha());\n\n    rgb2hsv(currentColor(), hue, sat, val);\n\n    hEd->setValue(hue);\n    sEd->setValue(sat);\n    vEd->setValue(val);\n\n    htEd->setText(QColor(curCol).name());\n\n    showCurrentColor();\n    emit newCol(currentColor());\n    updateQColor();\n}\n\nvoid QColorShower::hsvEd()\n{\n    rgbOriginal = false;\n    hue = hEd->value();\n    sat = sEd->value();\n    val = vEd->value();\n\n    QColor c;\n    c.setHsv(hue, sat, val);\n    curCol = c.rgb();\n\n    rEd->setValue(qRed(currentColor()));\n    gEd->setValue(qGreen(currentColor()));\n    bEd->setValue(qBlue(currentColor()));\n\n    htEd->setText(c.name());\n\n    showCurrentColor();\n    emit newCol(currentColor());\n    updateQColor();\n}\n\nvoid QColorShower::htmlEd()\n{\n    QString t = htEd->text();\n    if (t.isEmpty())\n        return;\n\n    if (!t.startsWith(u\"#\")) {\n        t.prepend(u\"#\");\n        QSignalBlocker blocker(htEd);\n        htEd->setText(t);\n    }\n\n    QColor c = QColor::fromString(t);\n    if (!c.isValid())\n        return;\n\n    curCol = qRgba(c.red(), c.green(), c.blue(), currentAlpha());\n    rgb2hsv(curCol, hue, sat, val);\n\n    hEd->setValue(hue);\n    sEd->setValue(sat);\n    vEd->setValue(val);\n\n    rEd->setValue(qRed(currentColor()));\n    gEd->setValue(qGreen(currentColor()));\n    bEd->setValue(qBlue(currentColor()));\n\n    showCurrentColor();\n    emit newCol(currentColor());\n    updateQColor();\n}\n\nvoid QColorShower::setRgb(QRgb rgb)\n{\n    rgbOriginal = true;\n    curCol = rgb;\n\n    rgb2hsv(currentColor(), hue, sat, val);\n\n    hEd->setValue(hue);\n    sEd->setValue(sat);\n    vEd->setValue(val);\n\n    rEd->setValue(qRed(currentColor()));\n    gEd->setValue(qGreen(currentColor()));\n    bEd->setValue(qBlue(currentColor()));\n\n    htEd->setText(QColor(rgb).name());\n\n    showCurrentColor();\n    updateQColor();\n}\n\nvoid QColorShower::setHsv(int h, int s, int v)\n{\n    if (h < -1 || (uint)s > 255 || (uint)v > 255)\n        return;\n\n    rgbOriginal = false;\n    hue = h; val = v; sat = s;\n    QColor c;\n    c.setHsv(hue, sat, val);\n    curCol = c.rgb();\n\n    hEd->setValue(hue);\n    sEd->setValue(sat);\n    vEd->setValue(val);\n\n    rEd->setValue(qRed(currentColor()));\n    gEd->setValue(qGreen(currentColor()));\n    bEd->setValue(qBlue(currentColor()));\n\n    htEd->setText(c.name());\n\n    showCurrentColor();\n    updateQColor();\n}\n\nvoid QColorShower::retranslateStrings()\n{\n    lblHue->setText(QColorDialog::tr(\"Hu&e:\"));\n    lblSat->setText(QColorDialog::tr(\"&Sat:\"));\n    lblVal->setText(QColorDialog::tr(\"&Val:\"));\n    lblRed->setText(QColorDialog::tr(\"&Red:\"));\n    lblGreen->setText(QColorDialog::tr(\"&Green:\"));\n    lblBlue->setText(QColorDialog::tr(\"Bl&ue:\"));\n    alphaLab->setText(QColorDialog::tr(\"A&lpha channel:\"));\n    lblHtml->setText(QColorDialog::tr(\"&HTML:\"));\n}\n\nvoid QColorShower::updateQColor()\n{\n    QColor oldQColor(curQColor);\n    curQColor.setRgba(qRgba(qRed(curCol), qGreen(curCol), qBlue(curCol), currentAlpha()));\n    if (curQColor != oldQColor)\n        emit currentColorChanged(curQColor);\n}\n\n//sets all widgets to display h,s,v\nvoid QColorDialogPrivate::newHsv(int h, int s, int v)\n{\n    if (!nativeDialogInUse) {\n        cs->setHsv(h, s, v);\n        cp->setCol(h, s);\n        lp->setCol(h, s, v);\n    }\n}\n\n//sets all widgets to display rgb\nvoid QColorDialogPrivate::setCurrentRgbColor(QRgb rgb)\n{\n    if (!nativeDialogInUse) {\n        cs->setRgb(rgb);\n        newColorTypedIn(rgb);\n    }\n}\n\n// hack; doesn't keep curCol in sync, so use with care\nvoid QColorDialogPrivate::setCurrentQColor(const QColor &color)\n{\n    Q_Q(QColorDialog);\n    if (cs->curQColor != color) {\n        cs->curQColor = color;\n        emit q->currentColorChanged(color);\n    }\n}\n\n// size of standard and custom color selector\nenum {\n    colorColumns = 8,\n    standardColorRows = 6,\n    customColorRows = 2\n};\n\nbool QColorDialogPrivate::selectColor(const QColor &col)\n{\n    QRgb color = col.rgb();\n    // Check standard colors\n    if (standard) {\n        const QRgb *standardColors = QColorDialogOptions::standardColors();\n        const QRgb *standardColorsEnd = standardColors + standardColorRows * colorColumns;\n        const QRgb *match = std::find(standardColors, standardColorsEnd, color);\n        if (match != standardColorsEnd) {\n            const int index = int(match - standardColors);\n            const int column = index / standardColorRows;\n            const int row = index % standardColorRows;\n            newStandard(row, column);\n            standard->setCurrent(row, column);\n            standard->setSelected(row, column);\n            standard->setFocus();\n            return true;\n        }\n    }\n    // Check custom colors\n    if (custom) {\n        const QRgb *customColors = QColorDialogOptions::customColors();\n        const QRgb *customColorsEnd = customColors + customColorRows * colorColumns;\n        const QRgb *match = std::find(customColors, customColorsEnd, color);\n        if (match != customColorsEnd) {\n            const int index = int(match - customColors);\n            const int column = index / customColorRows;\n            const int row = index % customColorRows;\n            newCustom(row, column);\n            custom->setCurrent(row, column);\n            custom->setSelected(row, column);\n            custom->setFocus();\n            return true;\n        }\n    }\n    return false;\n}\n\nQColor QColorDialogPrivate::grabScreenColor(const QPoint &p)\n{\n    QScreen *screen = QGuiApplication::screenAt(p);\n    if (!screen)\n        screen = QGuiApplication::primaryScreen();\n    const QRect screenRect = screen->geometry();\n    const QPixmap pixmap =\n            screen->grabWindow(0, p.x() - screenRect.x(), p.y() - screenRect.y(), 1, 1);\n    const QImage i = pixmap.toImage();\n    return i.pixel(0, 0);\n}\n\n//sets all widgets except cs to display rgb\nvoid QColorDialogPrivate::newColorTypedIn(QRgb rgb)\n{\n    if (!nativeDialogInUse) {\n        int h, s, v;\n        rgb2hsv(rgb, h, s, v);\n        cp->setCol(h, s);\n        lp->setCol(h, s, v);\n    }\n}\n\nvoid QColorDialogPrivate::nextCustom(int r, int c)\n{\n    nextCust = r + customColorRows * c;\n}\n\nvoid QColorDialogPrivate::newCustom(int r, int c)\n{\n    const int i = r + customColorRows * c;\n    setCurrentRgbColor(QColorDialogOptions::customColor(i));\n    if (standard)\n        standard->setSelected(-1,-1);\n}\n\nvoid QColorDialogPrivate::newStandard(int r, int c)\n{\n    setCurrentRgbColor(QColorDialogOptions::standardColor(r + c * 6));\n    if (custom)\n        custom->setSelected(-1,-1);\n}\n\nvoid QColorDialogPrivate::pickScreenColor()\n{\n    Q_Q(QColorDialog);\n\n    auto *platformServices = QGuiApplicationPrivate::platformIntegration()->services();\n    if (platformServices && platformServices->hasCapability(QPlatformServices::Capability::ColorPicking)) {\n        if (auto *colorPicker = platformServices->colorPicker(q->windowHandle())) {\n            q->connect(colorPicker, &QPlatformServiceColorPicker::colorPicked, q,\n                       [q, colorPicker](const QColor &color) {\n                           colorPicker->deleteLater();\n                           q->setCurrentColor(color);\n                       });\n            colorPicker->pickColor();\n            return;\n        }\n    }\n\n    if (!colorPickingEventFilter)\n        colorPickingEventFilter = new QColorPickingEventFilter(this, q);\n    q->installEventFilter(colorPickingEventFilter);\n    // If user pushes Escape, the last color before picking will be restored.\n    beforeScreenColorPicking = cs->currentColor();\n#ifndef QT_NO_CURSOR\n    q->grabMouse(Qt::CrossCursor);\n#else\n    q->grabMouse();\n#endif\n\n#ifdef Q_OS_WIN32\n    // On Windows mouse tracking doesn't work over other processes's windows\n    updateTimer->start(30);\n\n    // HACK: Because mouse grabbing doesn't work across processes, we have to have a dummy,\n    // invisible window to catch the mouse click, otherwise we will click whatever we clicked\n    // and loose focus.\n    dummyTransparentWindow.show();\n#endif\n    q->grabKeyboard();\n    /* With setMouseTracking(true) the desired color can be more precisely picked up,\n     * and continuously pushing the mouse button is not necessary.\n     */\n    q->setMouseTracking(true);\n\n    addCusBt->setDisabled(true);\n    buttons->setDisabled(true);\n    if (eyeDropperButton) {\n        eyeDropperButton->setDisabled(true);\n        const QPoint globalPos = QCursor::pos();\n        q->setCurrentColor(grabScreenColor(globalPos));\n        updateColorLabelText(globalPos);\n    }\n}\n\nvoid QColorDialogPrivate::updateColorLabelText(const QPoint &globalPos)\n{\n    if (lblScreenColorInfo)\n        lblScreenColorInfo->setText(QColorDialog::tr(\"Cursor at %1, %2\\nPress ESC to cancel\")\n                                .arg(globalPos.x())\n                                .arg(globalPos.y()));\n}\n\nvoid QColorDialogPrivate::releaseColorPicking()\n{\n    Q_Q(QColorDialog);\n    cp->setCrossVisible(true);\n    q->removeEventFilter(colorPickingEventFilter);\n    q->releaseMouse();\n#ifdef Q_OS_WIN32\n    updateTimer->stop();\n    dummyTransparentWindow.setVisible(false);\n#endif\n    q->releaseKeyboard();\n    q->setMouseTracking(false);\n    lblScreenColorInfo->setText(\"\\n\"_L1);\n    addCusBt->setDisabled(false);\n    buttons->setDisabled(false);\n    eyeDropperButton->setDisabled(false);\n}\n\nvoid QColorDialogPrivate::init(const QColor &initial)\n{\n    Q_Q(QColorDialog);\n\n    q->setSizeGripEnabled(false);\n    q->setWindowTitle(QColorDialog::tr(\"Select Color\"));\n\n    // default: use the native dialog if possible.  Can be overridden in setOptions()\n    nativeDialogInUse = (platformColorDialogHelper() != nullptr);\n    colorPickingEventFilter = nullptr;\n    nextCust = 0;\n\n    if (!nativeDialogInUse)\n        initWidgets();\n\n#ifdef Q_OS_WIN32\n    dummyTransparentWindow.resize(1, 1);\n    dummyTransparentWindow.setFlags(Qt::Tool | Qt::FramelessWindowHint);\n#endif\n\n    q->setCurrentColor(initial);\n}\n\nvoid QColorDialogPrivate::initWidgets()\n{\n    Q_Q(QColorDialog);\n    QVBoxLayout *mainLay = new QVBoxLayout(q);\n    // there's nothing in this dialog that benefits from sizing up\n    mainLay->setSizeConstraint(QLayout::SetFixedSize);\n\n    QHBoxLayout *topLay = new QHBoxLayout();\n    mainLay->addLayout(topLay);\n\n    leftLay = nullptr;\n\n#if defined(QT_SMALL_COLORDIALOG)\n    smallDisplay = true;\n    const int lumSpace = 20;\n#else\n    // small displays (e.g. PDAs) cannot fit the full color dialog,\n    // so just use the color picker.\n    smallDisplay = (QGuiApplication::primaryScreen()->virtualGeometry().width() < 480 || QGuiApplication::primaryScreen()->virtualGeometry().height() < 350);\n    const int lumSpace = topLay->spacing() / 2;\n#endif\n\n    if (!smallDisplay) {\n        leftLay = new QVBoxLayout;\n        topLay->addLayout(leftLay);\n\n        standard = new QColorWell(q, standardColorRows, colorColumns, QColorDialogOptions::standardColors());\n        lblBasicColors = new QLabel(q);\n#ifndef QT_NO_SHORTCUT\n        lblBasicColors->setBuddy(standard);\n#endif\n        QObjectPrivate::connect(standard, &QColorWell::selected,\n                                this, &QColorDialogPrivate::newStandard);\n        leftLay->addWidget(lblBasicColors);\n        leftLay->addWidget(standard);\n\n#if !defined(QT_SMALL_COLORDIALOG)\n        if (supportsColorPicking()) {\n            eyeDropperButton = new QPushButton();\n            leftLay->addWidget(eyeDropperButton);\n            lblScreenColorInfo = new QLabel(\"\\n\"_L1);\n            leftLay->addWidget(lblScreenColorInfo);\n            QObjectPrivate::connect(eyeDropperButton, &QPushButton::clicked,\n                                    this, &QColorDialogPrivate::pickScreenColor);\n        } else {\n            eyeDropperButton = nullptr;\n            lblScreenColorInfo = nullptr;\n        }\n#endif\n\n        leftLay->addStretch();\n\n        custom = new QColorWell(q, customColorRows, colorColumns, QColorDialogOptions::customColors());\n        custom->setAcceptDrops(true);\n\n        QObjectPrivate::connect(custom, &QColorWell::selected, this, &QColorDialogPrivate::newCustom);\n        QObjectPrivate::connect(custom, &QColorWell::currentChanged, this, &QColorDialogPrivate::nextCustom);\n\n        QObject::connect(custom, &QWellArray::colorChanged, q, [this] (int index, QRgb color) {\n            QColorDialogOptions::setCustomColor(index, color);\n            if (custom)\n                custom->update();\n        });\n\n        lblCustomColors = new QLabel(q);\n#ifndef QT_NO_SHORTCUT\n        lblCustomColors->setBuddy(custom);\n#endif\n        leftLay->addWidget(lblCustomColors);\n        leftLay->addWidget(custom);\n\n        addCusBt = new QPushButton(q);\n        QObjectPrivate::connect(addCusBt, &QPushButton::clicked, this, &QColorDialogPrivate::addCustom);\n        leftLay->addWidget(addCusBt);\n    } else {\n        // better color picker size for small displays\n#if defined(QT_SMALL_COLORDIALOG)\n        QSize screenSize = QGuiApplication::screenAt(QCursor::pos())->availableGeometry().size();\n        pWidth = pHeight = qMin(screenSize.width(), screenSize.height());\n        pHeight -= 20;\n        if (screenSize.height() > screenSize.width())\n            pWidth -= 20;\n#else\n        pWidth = 150;\n        pHeight = 100;\n#endif\n        custom = nullptr;\n        standard = nullptr;\n    }\n\n    QVBoxLayout *rightLay = new QVBoxLayout;\n    topLay->addLayout(rightLay);\n\n    QHBoxLayout *pickLay = new QHBoxLayout;\n    rightLay->addLayout(pickLay);\n\n    QVBoxLayout *cLay = new QVBoxLayout;\n    pickLay->addLayout(cLay);\n    cp = new QColorPicker(q);\n\n    cp->setFrameStyle(QFrame::Panel | QFrame::Sunken);\n\n#if defined(QT_SMALL_COLORDIALOG)\n    cp->hide();\n#else\n    cLay->addSpacing(lumSpace);\n    cLay->addWidget(cp);\n#endif\n    cLay->addSpacing(lumSpace);\n\n    lp = new QColorLuminancePicker(q);\n#if defined(QT_SMALL_COLORDIALOG)\n    lp->hide();\n#else\n    lp->setFixedWidth(20);\n    pickLay->addSpacing(10);\n    pickLay->addWidget(lp);\n    pickLay->addStretch();\n#endif\n\n    QObject::connect(cp, &QColorPicker::newCol, lp, qOverload<int, int>(&QColorLuminancePicker::setCol));\n    QObjectPrivate::connect(lp, &QColorLuminancePicker::newHsv, this, &QColorDialogPrivate::newHsv);\n\n    rightLay->addStretch();\n\n    cs = new QColorShower(q);\n    pickLay->setContentsMargins(cs->gl->contentsMargins());\n    QObjectPrivate::connect(cs, &QColorShower::newCol,\n                            this, &QColorDialogPrivate::newColorTypedIn);\n    QObject::connect(cs, &QColorShower::currentColorChanged,\n                     q, &QColorDialog::currentColorChanged);\n#if defined(QT_SMALL_COLORDIALOG)\n    topLay->addWidget(cs);\n#else\n    rightLay->addWidget(cs);\n    if (leftLay)\n        leftLay->addSpacing(cs->gl->contentsMargins().right());\n#endif\n\n    buttons = new QDialogButtonBox(q);\n    mainLay->addWidget(buttons);\n\n    ok = buttons->addButton(QDialogButtonBox::Ok);\n    QObject::connect(ok, &QPushButton::clicked, q, &QColorDialog::accept);\n    ok->setDefault(true);\n    cancel = buttons->addButton(QDialogButtonBox::Cancel);\n    QObject::connect(cancel, &QPushButton::clicked, q, &QColorDialog::reject);\n\n#ifdef Q_OS_WIN32\n    updateTimer = new QTimer(q);\n    QObjectPrivate::connect(updateTimer, &QTimer::timeout,\n                            this, qOverload<>(&QColorDialogPrivate::updateColorPicking));\n#endif\n    retranslateStrings();\n}\n\nvoid QColorDialogPrivate::initHelper(QPlatformDialogHelper *h)\n{\n    QColorDialog *d = q_func();\n    auto *colorDialogHelper = static_cast<QPlatformColorDialogHelper*>(h);\n    QObject::connect(colorDialogHelper, &QPlatformColorDialogHelper::currentColorChanged,\n                     d, &QColorDialog::currentColorChanged);\n    QObject::connect(colorDialogHelper, &QPlatformColorDialogHelper::colorSelected,\n                     d, &QColorDialog::colorSelected);\n    colorDialogHelper->setOptions(options);\n}\n\nvoid QColorDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)\n{\n    options->setWindowTitle(q_func()->windowTitle());\n}\n\nvoid QColorDialogPrivate::addCustom()\n{\n    QColorDialogOptions::setCustomColor(nextCust, cs->currentColor());\n    if (custom)\n        custom->update();\n    nextCust = (nextCust+1) % QColorDialogOptions::customColorCount();\n}\n\nvoid QColorDialogPrivate::retranslateStrings()\n{\n    if (nativeDialogInUse)\n        return;\n\n    if (!smallDisplay) {\n        lblBasicColors->setText(QColorDialog::tr(\"&Basic colors\"));\n        lblCustomColors->setText(QColorDialog::tr(\"&Custom colors\"));\n        addCusBt->setText(QColorDialog::tr(\"&Add to Custom Colors\"));\n#if !defined(QT_SMALL_COLORDIALOG)\n        if (eyeDropperButton)\n            eyeDropperButton->setText(QColorDialog::tr(\"&Pick Screen Color\"));\n#endif\n    }\n\n    cs->retranslateStrings();\n}\n\nbool QColorDialogPrivate::supportsColorPicking() const\n{\n    const auto integration = QGuiApplicationPrivate::platformIntegration();\n    return integration->hasCapability(QPlatformIntegration::ScreenWindowGrabbing)\n            || integration->services()->hasCapability(QPlatformServices::Capability::ColorPicking);\n}\n\nbool QColorDialogPrivate::canBeNativeDialog() const\n{\n    // Don't use Q_Q here! This function is called from ~QDialog,\n    // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).\n    const QDialog * const q = static_cast<const QDialog*>(q_ptr);\n    if (nativeDialogInUse)\n        return true;\n    if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)\n        || q->testAttribute(Qt::WA_DontShowOnScreen)\n        || (options->options() & QColorDialog::DontUseNativeDialog)) {\n        return false;\n    }\n\n    return strcmp(QColorDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;\n}\n\nstatic const Qt::WindowFlags qcd_DefaultWindowFlags =\n        Qt::Dialog | Qt::WindowTitleHint\n        | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;\n\n/*!\n    \\class QColorDialog\n    \\brief The QColorDialog class provides a dialog widget for specifying colors.\n\n    \\ingroup standard-dialogs\n    \\inmodule QtWidgets\n\n    The color dialog's function is to allow users to choose colors.\n    For example, you might use this in a drawing program to allow the\n    user to set the brush color.\n\n    The static functions provide modal color dialogs.\n    \\omit\n    If you require a modeless dialog, use the QColorDialog constructor.\n    \\endomit\n\n    The static getColor() function shows the dialog, and allows the user to\n    specify a color. This function can also be used to let users choose a\n    color with a level of transparency: pass the ShowAlphaChannel option as\n    an additional argument.\n\n    The user can store customCount() different custom colors. The\n    custom colors are shared by all color dialogs, and remembered\n    during the execution of the program. Use setCustomColor() to set\n    the custom colors, and use customColor() to get them.\n\n    When pressing the \"Pick Screen Color\" button, the cursor changes to a haircross\n    and the colors on the screen are scanned. The user can pick up one by clicking\n    the mouse or the Enter button. Pressing Escape restores the last color selected\n    before entering this mode.\n\n    The \\l{dialogs/standarddialogs}{Standard Dialogs} example shows\n    how to use QColorDialog as well as other built-in Qt dialogs.\n\n    \\image fusion-colordialog.png A color dialog in the Fusion widget style.\n\n    \\sa QColor, QFileDialog, QFontDialog, {Standard Dialogs Example}\n*/\n\n/*!\n    Constructs a color dialog with the given \\a parent.\n*/\nQColorDialog::QColorDialog(QWidget *parent)\n    : QColorDialog(QColor(Qt::white), parent)\n{\n}\n\n/*!\n    Constructs a color dialog with the given \\a parent and specified\n    \\a initial color.\n*/\nQColorDialog::QColorDialog(const QColor &initial, QWidget *parent)\n    : QDialog(*new QColorDialogPrivate, parent, qcd_DefaultWindowFlags)\n{\n    Q_D(QColorDialog);\n    d->init(initial);\n}\n\nvoid QColorDialogPrivate::setCurrentColor(const QColor &color,  SetColorMode setColorMode)\n{\n    if (nativeDialogInUse) {\n        platformColorDialogHelper()->setCurrentColor(color);\n        return;\n    }\n\n    if (setColorMode & ShowColor) {\n        setCurrentRgbColor(color.rgb());\n        setCurrentAlpha(color.alpha());\n    }\n    if (setColorMode & SelectColor)\n        selectColor(color);\n}\n\n/*!\n    \\property QColorDialog::currentColor\n    \\brief the currently selected color in the dialog\n*/\n\nvoid QColorDialog::setCurrentColor(const QColor &color)\n{\n    Q_D(QColorDialog);\n    d->setCurrentColor(color);\n}\n\nQColor QColorDialog::currentColor() const\n{\n    Q_D(const QColorDialog);\n    return d->currentQColor();\n}\n\n/*!\n    Returns the color that the user selected by clicking the \\uicontrol{OK}\n    or equivalent button.\n\n    \\note This color is not always the same as the color held by the\n    \\l currentColor property since the user can choose different colors\n    before finally selecting the one to use.\n*/\nQColor QColorDialog::selectedColor() const\n{\n    Q_D(const QColorDialog);\n    return d->selectedQColor;\n}\n\n/*!\n    Sets the given \\a option to be enabled if \\a on is true;\n    otherwise, clears the given \\a option.\n\n    \\sa options, testOption()\n*/\nvoid QColorDialog::setOption(ColorDialogOption option, bool on)\n{\n    const QColorDialog::ColorDialogOptions previousOptions = options();\n    if (!(previousOptions & option) != !on)\n        setOptions(previousOptions ^ option);\n}\n\n/*!\n    Returns \\c true if the given \\a option is enabled; otherwise, returns\n    false.\n\n    \\sa options, setOption()\n*/\nbool QColorDialog::testOption(ColorDialogOption option) const\n{\n    Q_D(const QColorDialog);\n    return d->options->testOption(static_cast<QColorDialogOptions::ColorDialogOption>(option));\n}\n\n/*!\n    \\property QColorDialog::options\n    \\brief the various options that affect the look and feel of the dialog\n\n    By default, all options are disabled.\n\n    Options should be set before showing the dialog. Setting them while the\n    dialog is visible is not guaranteed to have an immediate effect on the\n    dialog (depending on the option and on the platform).\n\n    \\sa setOption(), testOption()\n*/\nvoid QColorDialog::setOptions(ColorDialogOptions options)\n{\n    Q_D(QColorDialog);\n\n    if (QColorDialog::options() == options)\n        return;\n\n    d->options->setOptions(QColorDialogOptions::ColorDialogOptions(int(options)));\n    if ((options & DontUseNativeDialog) && d->nativeDialogInUse) {\n        d->nativeDialogInUse = false;\n        d->initWidgets();\n    }\n    if (!d->nativeDialogInUse) {\n        d->buttons->setVisible(!(options & NoButtons));\n        d->showAlpha(options & ShowAlphaChannel);\n        if (d->eyeDropperButton)\n            d->eyeDropperButton->setVisible(!(options & NoEyeDropperButton));\n    }\n}\n\nQColorDialog::ColorDialogOptions QColorDialog::options() const\n{\n    Q_D(const QColorDialog);\n    return QColorDialog::ColorDialogOptions(int(d->options->options()));\n}\n\n/*!\n    \\enum QColorDialog::ColorDialogOption\n\n    This enum specifies various options that affect the look and feel\n    of a color dialog.\n\n    \\value ShowAlphaChannel Allow the user to select the alpha component of a color.\n    \\value NoButtons Don't display \\uicontrol{OK} and \\uicontrol{Cancel} buttons. (Useful for \"live dialogs\".)\n    \\value NoEyeDropperButton Hide the \\uicontrol{Eye Dropper} button. This value was added in Qt 6.6.\n    \\value DontUseNativeDialog  Use Qt's standard color dialog instead of the operating system\n                                native color dialog.\n\n    \\sa options, setOption(), testOption(), windowModality()\n*/\n\n/*!\n    \\fn void QColorDialog::currentColorChanged(const QColor &color)\n\n    This signal is emitted whenever the current color changes in the dialog.\n    The current color is specified by \\a color.\n\n    \\sa color, colorSelected()\n*/\n\n/*!\n    \\fn void QColorDialog::colorSelected(const QColor &color);\n\n    This signal is emitted just after the user has clicked \\uicontrol{OK} to\n    select a color to use. The chosen color is specified by \\a color.\n\n    \\sa color, currentColorChanged()\n*/\n\n/*!\n    Changes the visibility of the dialog. If \\a visible is true, the dialog\n    is shown; otherwise, it is hidden.\n*/\nvoid QColorDialog::setVisible(bool visible)\n{\n    // will call QColorDialogPrivate::setVisible override\n    QDialog::setVisible(visible);\n}\n\n/*!\n    \\internal\n\n    The implementation of QColorDialog::setVisible() has to live here so that the call\n    to hide() in ~QDialog calls this function; it wouldn't call the override of\n    QDialog::setVisible().\n*/\nvoid QColorDialogPrivate::setVisible(bool visible)\n{\n    Q_Q(QColorDialog);\n\n    if (visible)\n        selectedQColor = QColor();\n\n    if (nativeDialogInUse) {\n        if (setNativeDialogVisible(visible)) {\n            // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below\n            // updates the state correctly, but skips showing the non-native version:\n            q->setAttribute(Qt::WA_DontShowOnScreen);\n        } else {\n            initWidgets();\n        }\n    } else {\n        q->setAttribute(Qt::WA_DontShowOnScreen, false);\n    }\n\n    QDialogPrivate::setVisible(visible);\n}\n\n/*!\n    Opens the dialog and connects its colorSelected() signal to the slot specified\n    by \\a receiver and \\a member.\n\n    The signal will be disconnected from the slot when the dialog is closed.\n*/\nvoid QColorDialog::open(QObject *receiver, const char *member)\n{\n    Q_D(QColorDialog);\n    connect(this, SIGNAL(colorSelected(QColor)), receiver, member);\n    d->receiverToDisconnectOnClose = receiver;\n    d->memberToDisconnectOnClose = member;\n    QDialog::open();\n}\n\n/*!\n    Pops up a modal color dialog with the given window \\a title (or \"Select Color\" if none is\n    specified), lets the user choose a color, and returns that color. The color is initially set\n    to \\a initial. The dialog is a child of \\a parent. It returns an invalid (see\n    QColor::isValid()) color if the user cancels the dialog.\n\n    The \\a options argument allows you to customize the dialog.\n*/\nQColor QColorDialog::getColor(const QColor &initial, QWidget *parent, const QString &title,\n                              ColorDialogOptions options)\n{\n    QAutoPointer<QColorDialog> dlg(new QColorDialog(parent));\n    if (!title.isEmpty())\n        dlg->setWindowTitle(title);\n    dlg->setOptions(options);\n    dlg->setCurrentColor(initial);\n\n    // If the dlg was deleted with a parent window,\n    // dlg == nullptr after leaving the exec().\n    dlg->exec();\n    if (bool(dlg))\n        return dlg->selectedColor();\n    else\n        return QColor();\n}\n\n/*!\n    Destroys the color dialog.\n*/\n\nQColorDialog::~QColorDialog()\n{\n}\n\n/*!\n    \\reimp\n*/\nvoid QColorDialog::changeEvent(QEvent *e)\n{\n    Q_D(QColorDialog);\n    if (e->type() == QEvent::LanguageChange)\n        d->retranslateStrings();\n    QDialog::changeEvent(e);\n}\n\nvoid QColorDialogPrivate::updateColorPicking()\n{\n#ifndef QT_NO_CURSOR\n    Q_Q(QColorDialog);\n    static QPoint lastGlobalPos;\n    QPoint newGlobalPos = QCursor::pos();\n    if (lastGlobalPos == newGlobalPos)\n        return;\n    lastGlobalPos = newGlobalPos;\n\n    if (!q->rect().contains(q->mapFromGlobal(newGlobalPos))) { // Inside the dialog mouse tracking works, handleColorPickingMouseMove will be called\n        updateColorPicking(newGlobalPos);\n#ifdef Q_OS_WIN32\n        dummyTransparentWindow.setPosition(newGlobalPos);\n#endif\n    }\n#endif // ! QT_NO_CURSOR\n}\n\nvoid QColorDialogPrivate::updateColorPicking(const QPoint &globalPos)\n{\n    const QColor color = grabScreenColor(globalPos);\n    // QTBUG-39792, do not change standard, custom color selectors while moving as\n    // otherwise it is not possible to pre-select a custom cell for assignment.\n    setCurrentColor(color, ShowColor);\n    updateColorLabelText(globalPos);\n}\n\nbool QColorDialogPrivate::handleColorPickingMouseMove(QMouseEvent *e)\n{\n    // If the cross is visible the grabbed color will be black most of the times\n    cp->setCrossVisible(!cp->geometry().contains(e->position().toPoint()));\n\n    updateColorPicking(e->globalPosition().toPoint());\n    return true;\n}\n\nbool QColorDialogPrivate::handleColorPickingMouseButtonRelease(QMouseEvent *e)\n{\n    setCurrentColor(grabScreenColor(e->globalPosition().toPoint()), SetColorAll);\n    releaseColorPicking();\n    return true;\n}\n\nbool QColorDialogPrivate::handleColorPickingKeyPress(QKeyEvent *e)\n{\n    Q_Q(QColorDialog);\n#if QT_CONFIG(shortcut)\n    if (e->matches(QKeySequence::Cancel)) {\n        releaseColorPicking();\n        q->setCurrentColor(beforeScreenColorPicking);\n    } else\n#endif\n      if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {\n        q->setCurrentColor(grabScreenColor(QCursor::pos()));\n        releaseColorPicking();\n    }\n    e->accept();\n    return true;\n}\n\n/*!\n  Closes the dialog and sets its result code to \\a result. If this dialog\n  is shown with exec(), done() causes the local event loop to finish,\n  and exec() to return \\a result.\n\n  \\sa QDialog::done()\n*/\nvoid QColorDialog::done(int result)\n{\n    Q_D(QColorDialog);\n    if (result == Accepted) {\n        d->selectedQColor = d->currentQColor();\n        emit colorSelected(d->selectedQColor);\n    } else {\n        d->selectedQColor = QColor();\n    }\n    QDialog::done(result);\n    if (d->receiverToDisconnectOnClose) {\n        disconnect(this, SIGNAL(colorSelected(QColor)),\n                   d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);\n        d->receiverToDisconnectOnClose = nullptr;\n    }\n    d->memberToDisconnectOnClose.clear();\n}\n\nQT_END_NAMESPACE\n\n#include \"qcolordialog.moc\"\n#include \"moc_qcolordialog.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qcolordialog_symbian.cpp",
    "content": "/****************************************************************************\n**\n** Copyright (C) 2015 The Qt Company Ltd.\n** Contact: http://www.qt.io/licensing/\n**\n** This file is part of the QtGui module of the Qt Toolkit.\n**\n** $QT_BEGIN_LICENSE:LGPL$\n** Commercial License Usage\n** Licensees holding valid commercial Qt licenses may use this file in\n** accordance with the commercial license agreement provided with the\n** Software or, alternatively, in accordance with the terms contained in\n** a written agreement between you and The Qt Company. For licensing terms\n** and conditions see http://www.qt.io/terms-conditions. For further\n** information use the contact form at http://www.qt.io/contact-us.\n**\n** GNU Lesser General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU Lesser\n** General Public License version 2.1 or version 3 as published by the Free\n** Software Foundation and appearing in the file LICENSE.LGPLv21 and\n** LICENSE.LGPLv3 included in the packaging of this file. Please review the\n** following information to ensure the GNU Lesser General Public License\n** requirements will be met: https://www.gnu.org/licenses/lgpl.html and\n** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n**\n** As a special exception, The Qt Company gives you certain additional\n** rights. These rights are described in The Qt Company LGPL Exception\n** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n**\n** GNU General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU\n** General Public License version 3.0 as published by the Free Software\n** Foundation and appearing in the file LICENSE.GPL included in the\n** packaging of this file.  Please review the following information to\n** ensure the GNU General Public License version 3.0 requirements will be\n** met: http://www.gnu.org/copyleft/gpl.html.\n**\n** $QT_END_LICENSE$\n**\n****************************************************************************/\n\n#include \"qcolordialog_p.h\"\n\n#ifndef QT_NO_COLORDIALOG\n\n\n#include \"qcolor.h\"\n#include \"private/qguiplatformplugin_p.h\"\n\n#ifdef Q_WS_S60\n#include <AknColourSelectionGrid.h>\n#endif\n\n#include \"private/qt_s60_p.h\"\n\nQT_BEGIN_NAMESPACE\n\nQColor launchSymbianColorDialog(QColor initial)\n{\n    QColor currentColor = QColor::Invalid;\n#ifdef Q_WS_S60\n    QT_TRAP_THROWING(\n        CArrayFixFlat<TRgb>* array = new( ELeave ) CArrayFixFlat<TRgb>(17);\n        CleanupStack::PushL(array);\n        array->AppendL(KRgbBlack);\n        array->AppendL(KRgbDarkGray);\n        array->AppendL(KRgbDarkRed);\n        array->AppendL(KRgbDarkGreen);\n        array->AppendL(KRgbDarkYellow);\n        array->AppendL(KRgbDarkBlue);\n        array->AppendL(KRgbDarkMagenta);\n        array->AppendL(KRgbDarkCyan);\n        array->AppendL(KRgbRed);\n        array->AppendL(KRgbGreen);\n        array->AppendL(KRgbYellow);\n        array->AppendL(KRgbBlue);\n        array->AppendL(KRgbMagenta);\n        array->AppendL(KRgbCyan);\n        array->AppendL(KRgbGray);\n        array->AppendL(KRgbWhite);\n\n        TRgb initialColour(initial.red(), initial.green(), initial.blue(), initial.alpha());\n\n        TBool noneChosen = EFalse; // If true shows the default colour button\n        CAknColourSelectionGrid* colourSelectionGrid =\n            CAknColourSelectionGrid::NewL(array, EFalse, noneChosen, initialColour);\n        CleanupStack::PushL(colourSelectionGrid);\n\n        if (colourSelectionGrid->ExecuteLD()) {\n            currentColor.setRgb(initialColour.Red(), initialColour.Green(),\n                                initialColour.Blue(), initialColour.Alpha());\n        }\n        CleanupStack::Pop(colourSelectionGrid);\n        CleanupStack::PopAndDestroy(array);\n    );\n#endif\n    return currentColor;\n}\n\nQColor qtSymbianGetColor(const QColor &initial)\n{\n    return launchSymbianColorDialog(initial);\n}\n\nQT_END_NAMESPACE\n\n#endif // QT_NO_COLORDIALOG\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qdialog.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include <QtWidgets/qtwidgetsglobal.h>\n#if QT_CONFIG(colordialog)\n#include \"qcolordialog.h\"\n#endif\n#if QT_CONFIG(fontdialog)\n#include \"qfontdialog.h\"\n#endif\n#if QT_CONFIG(filedialog)\n#include \"qfiledialog.h\"\n#endif\n\n#include \"qevent.h\"\n#include \"qapplication.h\"\n#include \"qlayout.h\"\n#if QT_CONFIG(sizegrip)\n#include \"qsizegrip.h\"\n#endif\n#if QT_CONFIG(whatsthis)\n#include \"qwhatsthis.h\"\n#endif\n#if QT_CONFIG(menu)\n#include \"qmenu.h\"\n#endif\n#include \"qcursor.h\"\n#if QT_CONFIG(messagebox)\n#include \"qmessagebox.h\"\n#endif\n#if QT_CONFIG(errormessage)\n#include \"qerrormessage.h\"\n#endif\n#include <qpa/qplatformtheme.h>\n#include \"private/qdialog_p.h\"\n#include \"private/qguiapplication_p.h\"\n#if QT_CONFIG(accessibility)\n#include \"qaccessible.h\"\n#endif\n\nQT_BEGIN_NAMESPACE\n\nstatic inline int themeDialogType(const QDialog *dialog)\n{\n#if QT_CONFIG(filedialog)\n    if (qobject_cast<const QFileDialog *>(dialog))\n        return QPlatformTheme::FileDialog;\n#endif\n#if QT_CONFIG(colordialog)\n    if (qobject_cast<const QColorDialog *>(dialog))\n        return QPlatformTheme::ColorDialog;\n#endif\n#if QT_CONFIG(fontdialog)\n    if (qobject_cast<const QFontDialog *>(dialog))\n        return QPlatformTheme::FontDialog;\n#endif\n#if QT_CONFIG(messagebox)\n    if (qobject_cast<const QMessageBox *>(dialog))\n        return QPlatformTheme::MessageDialog;\n#endif\n#if QT_CONFIG(errormessage)\n    if (qobject_cast<const QErrorMessage *>(dialog))\n        return QPlatformTheme::MessageDialog;\n#endif\n#if !QT_CONFIG(filedialog) && !QT_CONFIG(colordialog) && !QT_CONFIG(fontdialog) && \\\n    !QT_CONFIG(messagebox) && !QT_CONFIG(errormessage)\n    Q_UNUSED(dialog);\n#endif\n    return -1;\n}\n\nQDialogPrivate::~QDialogPrivate()\n{\n    delete m_platformHelper;\n}\n\nQPlatformDialogHelper *QDialogPrivate::platformHelper() const\n{\n    // Delayed creation of the platform, ensuring that\n    // that qobject_cast<> on the dialog works in the plugin.\n    if (!m_platformHelperCreated && canBeNativeDialog()) {\n        m_platformHelperCreated = true;\n        QDialogPrivate *ncThis = const_cast<QDialogPrivate *>(this);\n        QDialog *dialog = ncThis->q_func();\n        const int type = themeDialogType(dialog);\n        if (type >= 0) {\n            m_platformHelper = QGuiApplicationPrivate::platformTheme()\n                    ->createPlatformDialogHelper(static_cast<QPlatformTheme::DialogType>(type));\n            if (m_platformHelper) {\n                QObject::connect(m_platformHelper, SIGNAL(accept()), dialog, SLOT(accept()));\n                QObject::connect(m_platformHelper, SIGNAL(reject()), dialog, SLOT(reject()));\n                ncThis->initHelper(m_platformHelper);\n            }\n        }\n    }\n    return m_platformHelper;\n}\n\nbool QDialogPrivate::canBeNativeDialog() const\n{\n    if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs))\n        return false;\n\n    QDialogPrivate *ncThis = const_cast<QDialogPrivate *>(this);\n    QDialog *dialog = ncThis->q_func();\n    const int type = themeDialogType(dialog);\n    if (type >= 0)\n        return QGuiApplicationPrivate::platformTheme()\n                ->usePlatformNativeDialog(static_cast<QPlatformTheme::DialogType>(type));\n    return false;\n}\n\n/*!\n    \\internal\n\n    Properly closes dialog and sets the \\a resultCode.\n */\nvoid QDialogPrivate::close(int resultCode)\n{\n    Q_Q(QDialog);\n\n    q->setResult(resultCode);\n\n    if (!data.is_closing) {\n        // Until Qt 6.3 we didn't close dialogs, so they didn't receive a QCloseEvent.\n        // It is likely that subclasses implement closeEvent and handle them as rejection\n        // (like QMessageBox and QProgressDialog do), so eat those events.\n        struct CloseEventEater : QObject\n        {\n            using QObject::QObject;\n        protected:\n            bool eventFilter(QObject *o, QEvent *e) override\n            {\n                if (e->type() == QEvent::Close)\n                    return true;\n                return QObject::eventFilter(o, e);\n            }\n        } closeEventEater;\n        q->installEventFilter(&closeEventEater);\n        QWidgetPrivate::close();\n    } else {\n        // If the close was initiated outside of QDialog we will end up\n        // here via QDialog::closeEvent calling reject(), in which case\n        // we need to hide the dialog to ensure QDialog::closeEvent does\n        // not ignore the close event. FIXME: Why is QDialog doing this?\n        q->hide();\n    }\n\n    resetModalitySetByOpen();\n}\n\nQWindow *QDialogPrivate::transientParentWindow() const\n{\n    Q_Q(const QDialog);\n    if (const QWidget *parent = q->nativeParentWidget())\n        return parent->windowHandle();\n    else if (q->windowHandle())\n        return q->windowHandle()->transientParent();\n    return nullptr;\n}\n\nbool QDialogPrivate::setNativeDialogVisible(bool visible)\n{\n    if (QPlatformDialogHelper *helper = platformHelper()) {\n        if (visible) {\n            Q_Q(QDialog);\n            helperPrepareShow(helper);\n            nativeDialogInUse = helper->show(q->windowFlags(), q->windowModality(), transientParentWindow());\n        } else if (nativeDialogInUse) {\n            helper->hide();\n        }\n    }\n    return nativeDialogInUse;\n}\n\nQVariant QDialogPrivate::styleHint(QPlatformDialogHelper::StyleHint hint) const\n{\n    if (const QPlatformDialogHelper *helper = platformHelper())\n        return helper->styleHint(hint);\n    return QPlatformDialogHelper::defaultStyleHint(hint);\n}\n\n/*!\n    \\class QDialog\n    \\brief The QDialog class is the base class of dialog windows.\n\n    \\ingroup dialog-classes\n    \\ingroup abstractwidgets\n    \\inmodule QtWidgets\n\n    A dialog window is a top-level window mostly used for short-term\n    tasks and brief communications with the user. QDialogs may be\n    modal or modeless. QDialogs can\n    provide a \\l{#return}{return value}, and they can have \\l{#default}{default buttons}. QDialogs can also have a QSizeGrip in their\n    lower-right corner, using setSizeGripEnabled().\n\n    Note that QDialog (and any other widget that has type \\c Qt::Dialog) uses\n    the parent widget slightly differently from other classes in Qt. A dialog is\n    always a top-level widget, but if it has a parent, its default location is\n    centered on top of the parent's top-level widget (if it is not top-level\n    itself). It will also share the parent's taskbar entry.\n\n    Use the overload of the QWidget::setParent() function to change\n    the ownership of a QDialog widget. This function allows you to\n    explicitly set the window flags of the reparented widget; using\n    the overloaded function will clear the window flags specifying the\n    window-system properties for the widget (in particular it will\n    reset the Qt::Dialog flag).\n\n    \\note The parent relationship of the dialog does \\e{not} imply\n    that the dialog will always be stacked on top of the parent\n    window. To ensure that the dialog is always on top, make the\n    dialog modal. This also applies for child windows of the dialog\n    itself. To ensure that child windows of the dialog stay on top\n    of the dialog, make the child windows modal as well.\n\n    \\section1 Modal Dialogs\n\n    A \\b{modal} dialog is a dialog that blocks input to other\n    visible windows in the same application. Dialogs that are used to\n    request a file name from the user or that are used to set\n    application preferences are usually modal. Dialogs can be\n    \\l{Qt::ApplicationModal}{application modal} (the default) or\n    \\l{Qt::WindowModal}{window modal}.\n\n    When an application modal dialog is opened, the user must finish\n    interacting with the dialog and close it before they can access\n    any other window in the application. Window modal dialogs only\n    block access to the window associated with the dialog, allowing\n    the user to continue to use other windows in an application.\n\n    The most common way to display a modal dialog is to call its\n    \\l open() function. Alternatively, you can call \\l setModal(true) or\n    \\l setWindowModality(), and then \\l show(). In both cases, once the dialog is\n    displayed, the control is immediately returned to the caller. You must connect\n    to the \\l finished() signal to know when the dialog is closed and what its\n    \\l {#return} {return value} is. Alternatively, you can connect to the\n    \\l accepted() and \\l rejected() signals.\n\n    When implementing a custom dialog, to close the dialog and return an\n    appropriate value, connect a default button, for example, an OK button, to the\n    \\l accept() slot, and a Cancel button to the \\l reject() slot. Alternatively,\n    you can call the \\l done() slot with \\c Accepted or \\c Rejected.\n\n    If you show the modal dialog to perform a long-running operation, it is\n    recommended to perform the operation in a background worker thread, so that\n    it does not interfere with the GUI thread.\n\n    \\warning When using \\l open() or \\l show(), the modal dialog should not be\n    created on the stack, so that it does not get destroyed as soon as the control\n    returns to the caller.\n\n    \\note There is a way to show a modal dialog in a blocking mode by calling\n    \\l exec(). In this case, the control returns to the GUI thread only when the\n    dialog is closed. However, such approach is discouraged, because it creates a\n    nested event loop, which is not fully supported by some platforms.\n\n    \\section1 Modeless Dialogs\n\n    A \\b{modeless} dialog is a dialog that operates\n    independently of other windows in the same application. Find and\n    replace dialogs in word-processors are often modeless to allow the\n    user to interact with both the application's main window and with\n    the dialog.\n\n    Modeless dialogs are displayed using show(), which returns control\n    to the caller immediately.\n\n    If you invoke the \\l{QWidget::show()}{show()} function after hiding\n    a dialog, the dialog will be displayed in its original position. This is\n    because the window manager decides the position for windows that\n    have not been explicitly placed by the programmer. To preserve the\n    position of a dialog that has been moved by the user, save its position\n    in your \\l{QWidget::closeEvent()}{closeEvent()}  handler and then\n    move the dialog to that position, before showing it again.\n\n    \\target default\n    \\section1 Default Button\n\n    A dialog's \\e default button is the button that's pressed when the\n    user presses Enter (Return). This button is used to signify that\n    the user accepts the dialog's settings and wants to close the\n    dialog. Use QPushButton::setDefault(), QPushButton::isDefault()\n    and QPushButton::autoDefault() to set and control the dialog's\n    default button.\n\n    \\target escapekey\n    \\section1 Escape Key\n\n    If the user presses the Esc key in a dialog, QDialog::reject()\n    will be called. This will cause the window to close:\n    The \\l{QCloseEvent}{close event} cannot be \\l{QEvent::ignore()}{ignored}.\n\n    \\section1 Extensibility\n\n    Extensibility is the ability to show the dialog in two ways: a\n    partial dialog that shows the most commonly used options, and a\n    full dialog that shows all the options. Typically an extensible\n    dialog will initially appear as a partial dialog, but with a\n    \\uicontrol More toggle button. If the user presses the\n    \\uicontrol More button down, the dialog is expanded.\n\n    \\target return\n    \\section1 Return Value (Modal Dialogs)\n\n    Modal dialogs are often used in situations where a return value is\n    required, e.g. to indicate whether the user pressed \\uicontrol OK or\n    \\uicontrol Cancel. A dialog can be closed by calling the accept() or the\n    reject() slots, and exec() will return \\c Accepted or \\c Rejected\n    as appropriate. The exec() call returns the result of the dialog.\n    The result is also available from result() if the dialog has not\n    been destroyed.\n\n    In order to modify your dialog's close behavior, you can reimplement\n    the functions accept(), reject() or done(). The\n    \\l{QWidget::closeEvent()}{closeEvent()} function should only be\n    reimplemented to preserve the dialog's position or to override the\n    standard close or reject behavior.\n\n    \\target examples\n    \\section1 Code Examples\n\n    A modal dialog:\n\n    \\snippet dialogs/dialogs.cpp 1\n\n    A modeless dialog:\n\n    \\snippet dialogs/dialogs.cpp 0\n\n    A dialog with an extension:\n\n    \\snippet dialogs/dialogs.cpp extension\n\n    By setting the \\l{QLayout::}{sizeConstraint} property of the dialog's\n    layout to \\l{QLayout::}{SetFixedSize}, the dialog will not be resizable\n    by the user, and will automatically shrink when the extension gets hidden.\n\n    \\sa QDialogButtonBox, QTabWidget, QWidget, QProgressDialog,\n        {Standard Dialogs Example}\n*/\n\n/*! \\enum QDialog::DialogCode\n\n    The value returned by a modal dialog.\n\n    \\value Accepted\n    \\value Rejected\n*/\n\n/*!\n  \\property QDialog::sizeGripEnabled\n  \\brief whether the size grip is enabled\n\n  A QSizeGrip is placed in the bottom-right corner of the dialog when this\n  property is enabled. By default, the size grip is disabled.\n*/\n\n\n/*!\n  Constructs a dialog with parent \\a parent.\n\n  A dialog is always a top-level widget, but if it has a parent, its\n  default location is centered on top of the parent. It will also\n  share the parent's taskbar entry.\n\n  The widget flags \\a f are passed on to the QWidget constructor.\n  If, for example, you don't want a What's This button in the title bar\n  of the dialog, pass Qt::WindowTitleHint | Qt::WindowSystemMenuHint in \\a f.\n\n  \\sa QWidget::setWindowFlags()\n*/\n\nQDialog::QDialog(QWidget *parent, Qt::WindowFlags f)\n    : QWidget(*new QDialogPrivate, parent,\n              f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))\n{\n}\n\n/*!\n  \\overload\n  \\internal\n*/\nQDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f)\n    : QWidget(dd, parent, f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))\n{\n}\n\n/*!\n  Destroys the QDialog, deleting all its children.\n*/\n\nQDialog::~QDialog()\n{\n    QT_TRY {\n        // Need to hide() here, as our (to-be) overridden hide()\n        // will not be called in ~QWidget.\n        hide();\n    } QT_CATCH(...) {\n        // we're in the destructor - just swallow the exception\n    }\n}\n\n/*!\n  \\internal\n  This function is called by the push button \\a pushButton when it\n  becomes the default button. If \\a pushButton is \\nullptr, the dialogs\n  default default button becomes the default button. This is what a\n  push button calls when it loses focus.\n*/\n#if QT_CONFIG(pushbutton)\nvoid QDialogPrivate::setDefault(QPushButton *pushButton)\n{\n    Q_Q(QDialog);\n    bool hasMain = false;\n    QList<QPushButton*> list = q->findChildren<QPushButton*>();\n    for (int i=0; i<list.size(); ++i) {\n        QPushButton *pb = list.at(i);\n        if (pb->window() == q) {\n            if (pb == mainDef)\n                hasMain = true;\n            if (pb != pushButton)\n                pb->setDefault(false);\n        }\n    }\n    if (!pushButton && hasMain)\n        mainDef->setDefault(true);\n    if (!hasMain)\n        mainDef = pushButton;\n}\n\n/*!\n  \\internal\n  This function sets the default default push button to \\a pushButton.\n  This function is called by QPushButton::setDefault().\n*/\nvoid QDialogPrivate::setMainDefault(QPushButton *pushButton)\n{\n    mainDef = nullptr;\n    setDefault(pushButton);\n}\n\n/*!\n  \\internal\n  Hides the default button indicator. Called when non auto-default\n  push button get focus.\n */\nvoid QDialogPrivate::hideDefault()\n{\n    Q_Q(QDialog);\n    QList<QPushButton*> list = q->findChildren<QPushButton*>();\n    for (int i=0; i<list.size(); ++i) {\n        list.at(i)->setDefault(false);\n    }\n}\n#endif\n\nvoid QDialogPrivate::resetModalitySetByOpen()\n{\n    Q_Q(QDialog);\n    if (resetModalityTo != -1 && !q->testAttribute(Qt::WA_SetWindowModality)) {\n        // open() changed the window modality and the user didn't touch it afterwards; restore it\n        q->setWindowModality(Qt::WindowModality(resetModalityTo));\n        q->setAttribute(Qt::WA_SetWindowModality, wasModalitySet);\n#ifdef Q_OS_MAC\n        Q_ASSERT(resetModalityTo != Qt::WindowModal);\n        q->setParent(q->parentWidget(), Qt::Dialog);\n#endif\n    }\n    resetModalityTo = -1;\n}\n\n/*!\n  In general returns the modal dialog's result code, \\c Accepted or\n  \\c Rejected.\n\n  \\note When called on a QMessageBox instance, the returned value is a\n  value of the \\l QMessageBox::StandardButton enum.\n\n  Do not call this function if the dialog was constructed with the\n  Qt::WA_DeleteOnClose attribute.\n*/\nint QDialog::result() const\n{\n    Q_D(const QDialog);\n    return d->rescode;\n}\n\n/*!\n  \\fn void QDialog::setResult(int i)\n\n  Sets the modal dialog's result code to \\a i.\n\n  \\note We recommend that you use one of the values defined by\n  QDialog::DialogCode.\n*/\nvoid QDialog::setResult(int r)\n{\n    Q_D(QDialog);\n    d->rescode = r;\n}\n\n/*!\n    Shows the dialog as a \\l{QDialog#Modal Dialogs}{window modal dialog},\n    returning immediately.\n\n    \\sa exec(), show(), result(), setWindowModality()\n*/\nvoid QDialog::open()\n{\n    Q_D(QDialog);\n\n    Qt::WindowModality modality = windowModality();\n    if (modality != Qt::WindowModal) {\n        d->resetModalityTo = modality;\n        d->wasModalitySet = testAttribute(Qt::WA_SetWindowModality);\n        setWindowModality(Qt::WindowModal);\n        setAttribute(Qt::WA_SetWindowModality, false);\n#ifdef Q_OS_MAC\n        setParent(parentWidget(), Qt::Sheet);\n#endif\n    }\n\n    setResult(0);\n    show();\n}\n\n/*!\n    Shows the dialog as a \\l{QDialog#Modal Dialogs}{modal dialog},\n    blocking until the user closes it. The function returns a \\l\n    DialogCode result.\n\n    If the dialog is \\l{Qt::ApplicationModal}{application modal}, users cannot\n    interact with any other window in the same application until they close\n    the dialog. If the dialog is \\l{Qt::ApplicationModal}{window modal}, only\n    interaction with the parent window is blocked while the dialog is open.\n    By default, the dialog is application modal.\n\n    \\note Avoid using this function; instead, use \\c{open()}. Unlike exec(),\n    open() is asynchronous, and does not spin an additional event loop. This\n    prevents a series of dangerous bugs from happening (e.g. deleting the\n    dialog's parent while the dialog is open via exec()). When using open() you\n    can connect to the finished() signal of QDialog to be notified when the\n    dialog is closed.\n\n    \\sa open(), show(), result(), setWindowModality()\n*/\n\nint QDialog::exec()\n{\n    Q_D(QDialog);\n\n    if (Q_UNLIKELY(d->eventLoop)) {\n        qWarning(\"QDialog::exec: Recursive call detected\");\n        return -1;\n    }\n\n    bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose);\n    setAttribute(Qt::WA_DeleteOnClose, false);\n\n    d->resetModalitySetByOpen();\n\n    bool wasShowModal = testAttribute(Qt::WA_ShowModal);\n    setAttribute(Qt::WA_ShowModal, true);\n    setResult(0);\n\n    show();\n\n    QPointer<QDialog> guard = this;\n    if (d->nativeDialogInUse) {\n        d->platformHelper()->exec();\n    } else {\n        QEventLoop eventLoop;\n        d->eventLoop = &eventLoop;\n        (void) eventLoop.exec(QEventLoop::DialogExec);\n    }\n    if (guard.isNull())\n        return QDialog::Rejected;\n    d->eventLoop = nullptr;\n\n    setAttribute(Qt::WA_ShowModal, wasShowModal);\n\n    int res = result();\n    if (d->nativeDialogInUse)\n        d->helperDone(static_cast<QDialog::DialogCode>(res), d->platformHelper());\n    if (deleteOnClose)\n        delete this;\n    return res;\n}\n\n/*!\n  Closes the dialog and sets its result code to \\a r. The finished() signal\n  will emit \\a r; if \\a r is QDialog::Accepted or QDialog::Rejected, the\n  accepted() or the rejected() signals will also be emitted, respectively.\n\n  If this dialog is shown with exec(), done() also causes the local event loop\n  to finish, and exec() to return \\a r.\n\n  As with QWidget::close(), done() deletes the dialog if the\n  Qt::WA_DeleteOnClose flag is set. If the dialog is the application's\n  main widget, the application terminates. If the dialog is the\n  last window closed, the QGuiApplication::lastWindowClosed() signal is\n  emitted.\n\n  \\sa accept(), reject(), QApplication::activeWindow(), QCoreApplication::quit()\n*/\n\nvoid QDialog::done(int r)\n{\n    QPointer<QDialog> guard(this);\n\n    Q_D(QDialog);\n    d->close(r);\n\n    if (!guard)\n        return;\n\n    int dialogCode = d->dialogCode();\n    if (dialogCode == QDialog::Accepted)\n        emit accepted();\n    else if (dialogCode == QDialog::Rejected)\n        emit rejected();\n\n    if (guard)\n        emit finished(r);\n}\n\n/*!\n  Hides the modal dialog and sets the result code to \\c Accepted.\n\n  \\sa reject(), done()\n*/\n\nvoid QDialog::accept()\n{\n    done(Accepted);\n}\n\n/*!\n  Hides the modal dialog and sets the result code to \\c Rejected.\n\n  \\sa accept(), done()\n*/\n\nvoid QDialog::reject()\n{\n    done(Rejected);\n}\n\n/*! \\reimp */\nbool QDialog::eventFilter(QObject *o, QEvent *e)\n{\n    return QWidget::eventFilter(o, e);\n}\n\n/*****************************************************************************\n  Event handlers\n *****************************************************************************/\n\n#ifndef QT_NO_CONTEXTMENU\n/*! \\reimp */\nvoid QDialog::contextMenuEvent(QContextMenuEvent *e)\n{\n#if !QT_CONFIG(whatsthis) || !QT_CONFIG(menu)\n    Q_UNUSED(e);\n#else\n    QWidget *w = childAt(e->pos());\n    if (!w) {\n        w = rect().contains(e->pos()) ? this : nullptr;\n        if (!w)\n            return;\n    }\n    while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis))\n        w = w->isWindow() ? nullptr : w->parentWidget();\n    if (w) {\n        QPointer<QMenu> p = new QMenu(this);\n        QAction *wt = p.data()->addAction(tr(\"What's This?\"));\n        if (p.data()->exec(e->globalPos()) == wt) {\n            QHelpEvent e(QEvent::WhatsThis, w->rect().center(),\n                         w->mapToGlobal(w->rect().center()));\n            QCoreApplication::sendEvent(w, &e);\n        }\n        delete p.data();\n    }\n#endif\n}\n#endif // QT_NO_CONTEXTMENU\n\n/*! \\reimp */\nvoid QDialog::keyPressEvent(QKeyEvent *e)\n{\n#ifndef QT_NO_SHORTCUT\n    //   Calls reject() if Escape is pressed. Simulates a button\n    //   click for the default button if Enter is pressed. Move focus\n    //   for the arrow keys. Ignore the rest.\n    if (e->matches(QKeySequence::Cancel)) {\n        reject();\n    } else\n#endif\n    if (!e->modifiers() || (e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter)) {\n        switch (e->key()) {\n#if QT_CONFIG(pushbutton)\n        case Qt::Key_Enter:\n        case Qt::Key_Return: {\n            QList<QPushButton*> list = findChildren<QPushButton*>();\n            for (int i=0; i<list.size(); ++i) {\n                QPushButton *pb = list.at(i);\n                if (pb->isDefault() && pb->isVisible()) {\n                    if (pb->isEnabled())\n                        pb->click();\n                    return;\n                }\n            }\n        }\n        break;\n#endif\n        default:\n            e->ignore();\n            return;\n        }\n    } else {\n        e->ignore();\n    }\n}\n\n/*! \\reimp */\nvoid QDialog::closeEvent(QCloseEvent *e)\n{\n#if QT_CONFIG(whatsthis)\n    if (isModal() && QWhatsThis::inWhatsThisMode())\n        QWhatsThis::leaveWhatsThisMode();\n#endif\n    if (isVisible()) {\n        QPointer<QObject> that = this;\n        reject();\n        if (that && isVisible())\n            e->ignore();\n    } else {\n        e->accept();\n    }\n}\n\n/*****************************************************************************\n  Geometry management.\n *****************************************************************************/\n\n/*! \\reimp\n*/\n\nvoid QDialog::setVisible(bool visible)\n{\n    Q_D(QDialog);\n\n    if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) != visible)\n        return;\n\n    d->setVisible(visible);\n}\n\nvoid QDialogPrivate::setVisible(bool visible)\n{\n    Q_Q(QDialog);\n    if (!q->testAttribute(Qt::WA_DontShowOnScreen) && canBeNativeDialog() && setNativeDialogVisible(visible))\n        return;\n\n    // We should not block windows by the invisible modal dialog\n    // if a platform-specific dialog is implemented as an in-process\n    // Qt window, because in this case it will also be blocked.\n    const bool dontBlockWindows = q->testAttribute(Qt::WA_DontShowOnScreen)\n            && styleHint(QPlatformDialogHelper::DialogIsQtWindow).toBool();\n    Qt::WindowModality oldModality;\n    bool wasModalitySet;\n\n    if (dontBlockWindows) {\n        oldModality = q->windowModality();\n        wasModalitySet = q->testAttribute(Qt::WA_SetWindowModality);\n        q->setWindowModality(Qt::NonModal);\n    }\n\n    if (visible) {\n        QWidgetPrivate::setVisible(visible);\n\n        // Window activation might be prevented. We can't test isActiveWindow here,\n        // as the window will be activated asynchronously by the window manager.\n        if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) {\n            QWidget *fw = q->window()->focusWidget();\n            if (!fw)\n                fw = q;\n\n            /*\n            The following block is to handle a special case, and does not\n            really follow proper logic in concern of autoDefault and TAB\n            order. However, it's here to ease usage for the users. If a\n            dialog has a default QPushButton, and first widget in the TAB\n            order also is a QPushButton, then we give focus to the main\n            default QPushButton. This simplifies code for the developers,\n            and actually catches most cases... If not, then they simply\n            have to use [widget*]->setFocus() themselves...\n            */\n#if QT_CONFIG(pushbutton)\n            if (mainDef && fw->focusPolicy() == Qt::NoFocus) {\n                QWidget *first = fw;\n                while ((first = first->nextInFocusChain()) != fw && first->focusPolicy() == Qt::NoFocus)\n                    ;\n                if (first != mainDef && qobject_cast<QPushButton*>(first))\n                    mainDef->setFocus();\n            }\n            if (!mainDef && q->isWindow()) {\n                QWidget *w = fw;\n                while ((w = w->nextInFocusChain()) != fw) {\n                    QPushButton *pb = qobject_cast<QPushButton *>(w);\n                    if (pb && pb->autoDefault() && pb->focusPolicy() != Qt::NoFocus) {\n                        pb->setDefault(true);\n                        break;\n                    }\n                }\n            }\n#endif\n            if (fw && !fw->hasFocus()) {\n                QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason);\n                QCoreApplication::sendEvent(fw, &e);\n            }\n        }\n\n#if QT_CONFIG(accessibility)\n        QAccessibleEvent event(q, QAccessible::DialogStart);\n        QAccessible::updateAccessibility(&event);\n#endif\n\n    } else {\n\n#if QT_CONFIG(accessibility)\n        if (q->isVisible()) {\n            QAccessibleEvent event(q, QAccessible::DialogEnd);\n            QAccessible::updateAccessibility(&event);\n        }\n#endif\n\n        // Reimplemented to exit a modal event loop when the dialog is hidden.\n        QWidgetPrivate::setVisible(visible);\n        if (eventLoop)\n            eventLoop->exit();\n    }\n\n    if (dontBlockWindows) {\n        q->setWindowModality(oldModality);\n        q->setAttribute(Qt::WA_SetWindowModality, wasModalitySet);\n    }\n\n#if QT_CONFIG(pushbutton)\n    const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();\n    if (mainDef && q->isActiveWindow()\n        && theme->themeHint(QPlatformTheme::DialogSnapToDefaultButton).toBool())\n        QCursor::setPos(mainDef->mapToGlobal(mainDef->rect().center()));\n#endif\n}\n\n/*!\\reimp */\nvoid QDialog::showEvent(QShowEvent *event)\n{\n    if (!event->spontaneous() && !testAttribute(Qt::WA_Moved)) {\n        Qt::WindowStates  state = windowState();\n        adjustPosition(parentWidget());\n        setAttribute(Qt::WA_Moved, false); // not really an explicit position\n        if (state != windowState())\n            setWindowState(state);\n    }\n}\n\n/*! \\internal */\nvoid QDialog::adjustPosition(QWidget* w)\n{\n    Q_D(QDialog);\n\n    if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())\n        if (theme->themeHint(QPlatformTheme::WindowAutoPlacement).toBool())\n            return;\n    QPoint p(0, 0);\n    int extraw = 0, extrah = 0;\n    const QWindow *parentWindow = nullptr;\n    if (w) {\n        w = w->window();\n    } else {\n        parentWindow = d->transientParentWindow();\n    }\n    QRect desk;\n    QScreen *scrn = nullptr;\n    if (w)\n        scrn = w->screen();\n    else if (parentWindow)\n        scrn = parentWindow->screen();\n    else if (QGuiApplication::primaryScreen()->virtualSiblings().size() > 1)\n        scrn = QGuiApplication::screenAt(QCursor::pos());\n    else\n        scrn = screen();\n    if (scrn)\n        desk = scrn->availableGeometry();\n\n    QWidgetList list = QApplication::topLevelWidgets();\n    for (int i = 0; (extraw == 0 || extrah == 0) && i < list.size(); ++i) {\n        QWidget * current = list.at(i);\n        if (current->isVisible()) {\n            int framew = current->geometry().x() - current->x();\n            int frameh = current->geometry().y() - current->y();\n\n            extraw = qMax(extraw, framew);\n            extrah = qMax(extrah, frameh);\n        }\n    }\n\n    // sanity check for decoration frames. With embedding, we\n    // might get extraordinary values\n    if (extraw == 0 || extrah == 0 || extraw >= 10 || extrah >= 40) {\n        extrah = 40;\n        extraw = 10;\n    }\n\n\n    if (w) {\n        // Use pos() if the widget is embedded into a native window\n        QPoint pp;\n        if (w->windowHandle() && qvariant_cast<WId>(w->windowHandle()->property(\"_q_embedded_native_parent_handle\")))\n            pp = w->pos();\n        else\n            pp = w->mapToGlobal(QPoint(0,0));\n        p = QPoint(pp.x() + w->width()/2,\n                    pp.y() + w->height()/ 2);\n    } else if (parentWindow) {\n        // QTBUG-63406: Widget-based dialog in QML, which has no Widget parent\n        // but a transient parent window.\n        QPoint pp = parentWindow->mapToGlobal(QPoint(0, 0));\n        p = QPoint(pp.x() + parentWindow->width() / 2, pp.y() + parentWindow->height() / 2);\n    } else {\n        // p = middle of the desktop\n        p = QPoint(desk.x() + desk.width()/2, desk.y() + desk.height()/2);\n    }\n\n    // p = origin of this\n    p = QPoint(p.x()-width()/2 - extraw,\n                p.y()-height()/2 - extrah);\n\n\n    if (p.x() + extraw + width() > desk.x() + desk.width())\n        p.setX(desk.x() + desk.width() - width() - extraw);\n    if (p.x() < desk.x())\n        p.setX(desk.x());\n\n    if (p.y() + extrah + height() > desk.y() + desk.height())\n        p.setY(desk.y() + desk.height() - height() - extrah);\n    if (p.y() < desk.y())\n        p.setY(desk.y());\n\n    // QTBUG-52735: Manually set the correct target screen since scaling in a\n    // subsequent call to QWindow::resize() may otherwise use the wrong factor\n    // if the screen changed notification is still in an event queue.\n    if (scrn) {\n        if (QWindow *window = windowHandle())\n            window->setScreen(scrn);\n    }\n\n    move(p);\n}\n\n/*! \\reimp */\nQSize QDialog::sizeHint() const\n{\n    Q_D(const QDialog);\n    if (d->extension) {\n        if (d->orientation == Qt::Horizontal)\n            return QSize(QWidget::sizeHint().width(),\n                        qMax(QWidget::sizeHint().height(),d->extension->sizeHint().height()));\n        else\n            return QSize(qMax(QWidget::sizeHint().width(), d->extension->sizeHint().width()),\n                        QWidget::sizeHint().height());\n    }\n    return QWidget::sizeHint();\n}\n\n\n/*! \\reimp */\nQSize QDialog::minimumSizeHint() const\n{\n    Q_D(const QDialog);\n    if (d->extension) {\n        if (d->orientation == Qt::Horizontal)\n            return QSize(QWidget::minimumSizeHint().width(),\n                        qMax(QWidget::minimumSizeHint().height(), d->extension->minimumSizeHint().height()));\n        else\n            return QSize(qMax(QWidget::minimumSizeHint().width(), d->extension->minimumSizeHint().width()),\n                        QWidget::minimumSizeHint().height());\n    }\n\n    return QWidget::minimumSizeHint();\n}\n\n/*!\n    \\property QDialog::modal\n    \\brief whether show() should pop up the dialog as modal or modeless\n\n    By default, this property is \\c false and show() pops up the dialog\n    as modeless. Setting this property to true is equivalent to setting\n    QWidget::windowModality to Qt::ApplicationModal.\n\n    exec() ignores the value of this property and always pops up the\n    dialog as modal.\n\n    \\sa QWidget::windowModality, show(), exec()\n*/\n\nvoid QDialog::setModal(bool modal)\n{\n    setAttribute(Qt::WA_ShowModal, modal);\n}\n\n\nbool QDialog::isSizeGripEnabled() const\n{\n#if QT_CONFIG(sizegrip)\n    Q_D(const QDialog);\n    return !!d->resizer;\n#else\n    return false;\n#endif\n}\n\n\nvoid QDialog::setSizeGripEnabled(bool enabled)\n{\n#if !QT_CONFIG(sizegrip)\n    Q_UNUSED(enabled);\n#else\n    Q_D(QDialog);\n#if QT_CONFIG(sizegrip)\n    d->sizeGripEnabled = enabled;\n    if (enabled && d->doShowExtension)\n        return;\n#endif\n    if (!enabled != !d->resizer) {\n        if (enabled) {\n            d->resizer = new QSizeGrip(this);\n            // adjustSize() processes all events, which is suboptimal\n            d->resizer->resize(d->resizer->sizeHint());\n            if (isRightToLeft())\n                d->resizer->move(rect().bottomLeft() -d->resizer->rect().bottomLeft());\n            else\n                d->resizer->move(rect().bottomRight() -d->resizer->rect().bottomRight());\n            d->resizer->raise();\n            d->resizer->show();\n        } else {\n            delete d->resizer;\n            d->resizer = nullptr;\n        }\n    }\n#endif // QT_CONFIG(sizegrip)\n}\n\n\n\n/*! \\reimp */\nvoid QDialog::resizeEvent(QResizeEvent *)\n{\n#if QT_CONFIG(sizegrip)\n    Q_D(QDialog);\n    if (d->resizer) {\n        if (isRightToLeft())\n            d->resizer->move(rect().bottomLeft() -d->resizer->rect().bottomLeft());\n        else\n            d->resizer->move(rect().bottomRight() -d->resizer->rect().bottomRight());\n        d->resizer->raise();\n    }\n#endif\n}\n\n/*! \\fn void QDialog::finished(int result)\n\n    This signal is emitted when the dialog's \\a result code has been\n    set, either by the user or by calling done(), accept(), or\n    reject().\n\n    Note that this signal is \\e not emitted when hiding the dialog\n    with hide() or setVisible(false). This includes deleting the\n    dialog while it is visible.\n\n    \\sa accepted(), rejected()\n*/\n\n/*! \\fn void QDialog::accepted()\n\n    This signal is emitted when the dialog has been accepted either by\n    the user or by calling accept() or done() with the\n    QDialog::Accepted argument.\n\n    Note that this signal is \\e not emitted when hiding the dialog\n    with hide() or setVisible(false). This includes deleting the\n    dialog while it is visible.\n\n    \\sa finished(), rejected()\n*/\n\n/*! \\fn void QDialog::rejected()\n\n    This signal is emitted when the dialog has been rejected either by\n    the user or by calling reject() or done() with the\n    QDialog::Rejected argument.\n\n    Note that this signal is \\e not emitted when hiding the dialog\n    with hide() or setVisible(false). This includes deleting the\n    dialog while it is visible.\n\n    \\sa finished(), accepted()\n*/\n\nQT_END_NAMESPACE\n#include \"moc_qdialog.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qdialogbuttonbox.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include <QtCore/qhash.h>\n#include <QtWidgets/qpushbutton.h>\n#include <QtWidgets/qstyle.h>\n#include <QtWidgets/qlayout.h>\n#include <QtWidgets/qdialog.h>\n#include <QtWidgets/qapplication.h>\n#include <private/qwidget_p.h>\n#include <private/qguiapplication_p.h>\n#include <QtGui/qpa/qplatformdialoghelper.h>\n#include <QtGui/qpa/qplatformtheme.h>\n#include <QtGui/qaction.h>\n\n#include \"qdialogbuttonbox.h\"\n#include \"qdialogbuttonbox_p.h\"\n\n#include <QtCore/qpointer.h>\n\nQT_BEGIN_NAMESPACE\n\n/*!\n    \\class QDialogButtonBox\n    \\since 4.2\n    \\brief The QDialogButtonBox class is a widget that presents buttons in a\n    layout that is appropriate to the current widget style.\n\n    \\ingroup dialog-classes\n    \\inmodule QtWidgets\n\n    Dialogs and message boxes typically present buttons in a layout that\n    conforms to the interface guidelines for that platform. Invariably,\n    different platforms have different layouts for their dialogs.\n    QDialogButtonBox allows a developer to add buttons to it and will\n    automatically use the appropriate layout for the user's desktop\n    environment.\n\n    Most buttons for a dialog follow certain roles. Such roles include:\n\n    \\list\n    \\li Accepting or rejecting the dialog.\n    \\li Asking for help.\n    \\li Performing actions on the dialog itself (such as resetting fields or\n       applying changes).\n    \\endlist\n\n    There can also be alternate ways of dismissing the dialog which may cause\n    destructive results.\n\n    Most dialogs have buttons that can almost be considered standard (e.g.\n    \\uicontrol OK and \\uicontrol Cancel buttons). It is sometimes convenient to create these\n    buttons in a standard way.\n\n    There are a couple ways of using QDialogButtonBox. One ways is to create\n    the buttons (or button texts) yourself and add them to the button box,\n    specifying their role.\n\n    \\snippet dialogs/dialogs.cpp buttonbox\n\n    Alternatively, QDialogButtonBox provides several standard buttons (e.g. OK, Cancel, Save)\n    that you can use. They exist as flags so you can OR them together in the constructor.\n\n    \\snippet dialogs/tabdialog/tabdialog.cpp 2\n\n    You can mix and match normal buttons and standard buttons.\n\n    Currently the buttons are laid out in the following way if the button box is horizontal:\n    \\table\n    \\row \\li \\inlineimage buttonbox-gnomelayout-horizontal.png GnomeLayout Horizontal\n         \\li Button box laid out in horizontal GnomeLayout\n    \\row \\li \\inlineimage buttonbox-kdelayout-horizontal.png KdeLayout Horizontal\n         \\li Button box laid out in horizontal KdeLayout\n    \\row \\li \\inlineimage buttonbox-maclayout-horizontal.png MacLayout Horizontal\n         \\li Button box laid out in horizontal MacLayout\n    \\row \\li \\inlineimage buttonbox-winlayout-horizontal.png  WinLayout Horizontal\n         \\li Button box laid out in horizontal WinLayout\n    \\endtable\n\n    The buttons are laid out the following way if the button box is vertical:\n\n    \\table\n    \\row \\li GnomeLayout\n         \\li KdeLayout\n         \\li MacLayout\n         \\li WinLayout\n    \\row \\li \\inlineimage buttonbox-gnomelayout-vertical.png GnomeLayout Vertical\n         \\li \\inlineimage buttonbox-kdelayout-vertical.png KdeLayout Vertical\n         \\li \\inlineimage buttonbox-maclayout-vertical.png MacLayout Vertical\n         \\li \\inlineimage buttonbox-winlayout-vertical.png WinLayout Vertical\n    \\endtable\n\n    Additionally, button boxes that contain only buttons with ActionRole or\n    HelpRole can be considered modeless and have an alternate look on \\macos:\n\n    \\table\n    \\row \\li modeless horizontal MacLayout\n         \\li \\inlineimage buttonbox-mac-modeless-horizontal.png Screenshot of modeless horizontal MacLayout\n    \\row \\li modeless vertical MacLayout\n         \\li \\inlineimage buttonbox-mac-modeless-vertical.png Screenshot of modeless vertical MacLayout\n    \\endtable\n\n    When a button is clicked in the button box, the clicked() signal is emitted\n    for the actual button is that is pressed. For convenience, if the button\n    has an AcceptRole, RejectRole, or HelpRole, the accepted(), rejected(), or\n    helpRequested() signals are emitted respectively.\n\n    If you want a specific button to be default you need to call\n    QPushButton::setDefault() on it yourself. However, if there is no default\n    button set and to preserve which button is the default button across\n    platforms when using the QPushButton::autoDefault property, the first push\n    button with the accept role is made the default button when the\n    QDialogButtonBox is shown,\n\n    \\sa QMessageBox, QPushButton, QDialog\n*/\nQDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient)\n    : orientation(orient), buttonLayout(nullptr), center(false)\n{\n    struct EventFilter : public QObject\n    {\n        EventFilter(QDialogButtonBoxPrivate *d) : d(d) {};\n\n        bool eventFilter(QObject *obj, QEvent *event) override\n        {\n            QAbstractButton *button = qobject_cast<QAbstractButton *>(obj);\n            return button ? d->handleButtonShowAndHide(button, event) : false;\n        }\n\n    private:\n        QDialogButtonBoxPrivate *d;\n\n    };\n\n    filter.reset(new EventFilter(this));\n}\n\nvoid QDialogButtonBoxPrivate::initLayout()\n{\n    Q_Q(QDialogButtonBox);\n    layoutPolicy = QDialogButtonBox::ButtonLayout(q->style()->styleHint(QStyle::SH_DialogButtonLayout, nullptr, q));\n    bool createNewLayout = buttonLayout == nullptr\n        || (orientation == Qt::Horizontal && qobject_cast<QVBoxLayout *>(buttonLayout) != 0)\n        || (orientation == Qt::Vertical && qobject_cast<QHBoxLayout *>(buttonLayout) != 0);\n    if (createNewLayout) {\n        delete buttonLayout;\n        if (orientation == Qt::Horizontal)\n            buttonLayout = new QHBoxLayout(q);\n        else\n            buttonLayout = new QVBoxLayout(q);\n    }\n\n    int left, top, right, bottom;\n    setLayoutItemMargins(QStyle::SE_PushButtonLayoutItem);\n    getLayoutItemMargins(&left, &top, &right, &bottom);\n    buttonLayout->setContentsMargins(-left, -top, -right, -bottom);\n\n    if (!q->testAttribute(Qt::WA_WState_OwnSizePolicy)) {\n        QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::ButtonBox);\n        if (orientation == Qt::Vertical)\n            sp.transpose();\n        q->setSizePolicy(sp);\n        q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);\n    }\n}\n\nvoid QDialogButtonBoxPrivate::resetLayout()\n{\n    initLayout();\n    layoutButtons();\n}\n\nvoid QDialogButtonBoxPrivate::addButtonsToLayout(const QList<QAbstractButton *> &buttonList,\n                                                 bool reverse)\n{\n    int start = reverse ? buttonList.size() - 1 : 0;\n    int end = reverse ? -1 : buttonList.size();\n    int step = reverse ? -1 : 1;\n\n    for (int i = start; i != end; i += step) {\n        QAbstractButton *button = buttonList.at(i);\n        buttonLayout->addWidget(button);\n        button->show();\n    }\n}\n\nvoid QDialogButtonBoxPrivate::layoutButtons()\n{\n    Q_Q(QDialogButtonBox);\n    const int MacGap = 36 - 8;    // 8 is the default gap between a widget and a spacer item\n\n    QBoolBlocker blocker(ignoreShowAndHide);\n    for (int i = buttonLayout->count() - 1; i >= 0; --i) {\n        QLayoutItem *item = buttonLayout->takeAt(i);\n        if (QWidget *widget = item->widget())\n            widget->hide();\n        delete item;\n    }\n\n    int tmpPolicy = layoutPolicy;\n\n    static const int M = 5;\n    static const int ModalRoles[M] = { QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::RejectRole,\n        QPlatformDialogHelper::DestructiveRole, QPlatformDialogHelper::YesRole, QPlatformDialogHelper::NoRole };\n    if (tmpPolicy == QDialogButtonBox::MacLayout) {\n        bool hasModalButton = false;\n        for (int i = 0; i < M; ++i) {\n            if (!buttonLists[ModalRoles[i]].isEmpty()) {\n                hasModalButton = true;\n                break;\n            }\n        }\n        if (!hasModalButton)\n            tmpPolicy = 4;  // Mac modeless\n    }\n\n    const int *currentLayout = QPlatformDialogHelper::buttonLayout(\n        orientation, static_cast<QPlatformDialogHelper::ButtonLayout>(tmpPolicy));\n\n    if (center)\n        buttonLayout->addStretch();\n\n    const QList<QAbstractButton *> &acceptRoleList = buttonLists[QPlatformDialogHelper::AcceptRole];\n\n    while (*currentLayout != QPlatformDialogHelper::EOL) {\n        int role = (*currentLayout & ~QPlatformDialogHelper::Reverse);\n        bool reverse = (*currentLayout & QPlatformDialogHelper::Reverse);\n\n        switch (role) {\n        case QPlatformDialogHelper::Stretch:\n            if (!center)\n                buttonLayout->addStretch();\n            break;\n        case QPlatformDialogHelper::AcceptRole: {\n            if (acceptRoleList.isEmpty())\n                break;\n            // Only the first one\n            QAbstractButton *button = acceptRoleList.first();\n            buttonLayout->addWidget(button);\n            button->show();\n        }\n            break;\n        case QPlatformDialogHelper::AlternateRole:\n            if (acceptRoleList.size() > 1)\n                addButtonsToLayout(acceptRoleList.mid(1), reverse);\n            break;\n        case QPlatformDialogHelper::DestructiveRole:\n            {\n                const QList<QAbstractButton *> &list = buttonLists[role];\n\n                /*\n                    Mac: Insert a gap on the left of the destructive\n                    buttons to ensure that they don't get too close to\n                    the help and action buttons (but only if there are\n                    some buttons to the left of the destructive buttons\n                    (and the stretch, whence buttonLayout->count() > 1\n                    and not 0)).\n                */\n                if (tmpPolicy == QDialogButtonBox::MacLayout\n                        && !list.isEmpty() && buttonLayout->count() > 1)\n                    buttonLayout->addSpacing(MacGap);\n\n                addButtonsToLayout(list, reverse);\n\n                /*\n                    Insert a gap between the destructive buttons and the\n                    accept and reject buttons.\n                */\n                if (tmpPolicy == QDialogButtonBox::MacLayout && !list.isEmpty())\n                    buttonLayout->addSpacing(MacGap);\n            }\n            break;\n        case QPlatformDialogHelper::RejectRole:\n        case QPlatformDialogHelper::ActionRole:\n        case QPlatformDialogHelper::HelpRole:\n        case QPlatformDialogHelper::YesRole:\n        case QPlatformDialogHelper::NoRole:\n        case QPlatformDialogHelper::ApplyRole:\n        case QPlatformDialogHelper::ResetRole:\n            addButtonsToLayout(buttonLists[role], reverse);\n        }\n        ++currentLayout;\n    }\n\n    QWidgetList layoutWidgets;\n    for (int i = 0; i < buttonLayout->count(); ++i) {\n        if (auto *widget = buttonLayout->itemAt(i)->widget())\n            layoutWidgets << widget;\n    }\n\n    q->setFocusProxy(nullptr);\n    if (!layoutWidgets.isEmpty()) {\n        QWidget *prev = layoutWidgets.constLast();\n        for (QWidget *here : layoutWidgets) {\n            QWidget::setTabOrder(prev, here);\n            prev = here;\n            if (auto *pushButton = qobject_cast<QPushButton *>(prev); pushButton && pushButton->isDefault())\n                q->setFocusProxy(pushButton);\n        }\n    }\n\n    if (center)\n        buttonLayout->addStretch();\n}\n\nQPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardButton sbutton,\n                                                   LayoutRule layoutRule)\n{\n    Q_Q(QDialogButtonBox);\n    int icon = 0;\n\n    switch (sbutton) {\n    case QDialogButtonBox::Ok:\n        icon = QStyle::SP_DialogOkButton;\n        break;\n    case QDialogButtonBox::Save:\n        icon = QStyle::SP_DialogSaveButton;\n        break;\n    case QDialogButtonBox::Open:\n        icon = QStyle::SP_DialogOpenButton;\n        break;\n    case QDialogButtonBox::Cancel:\n        icon = QStyle::SP_DialogCancelButton;\n        break;\n    case QDialogButtonBox::Close:\n        icon = QStyle::SP_DialogCloseButton;\n        break;\n    case QDialogButtonBox::Apply:\n        icon = QStyle::SP_DialogApplyButton;\n        break;\n    case QDialogButtonBox::Reset:\n        icon = QStyle::SP_DialogResetButton;\n        break;\n    case QDialogButtonBox::Help:\n        icon = QStyle::SP_DialogHelpButton;\n        break;\n    case QDialogButtonBox::Discard:\n        icon = QStyle::SP_DialogDiscardButton;\n        break;\n    case QDialogButtonBox::Yes:\n        icon = QStyle::SP_DialogYesButton;\n        break;\n    case QDialogButtonBox::No:\n        icon = QStyle::SP_DialogNoButton;\n        break;\n    case QDialogButtonBox::YesToAll:\n        icon = QStyle::SP_DialogYesToAllButton;\n        break;\n    case QDialogButtonBox::NoToAll:\n        icon = QStyle::SP_DialogNoToAllButton;\n        break;\n    case QDialogButtonBox::SaveAll:\n        icon = QStyle::SP_DialogSaveAllButton;\n        break;\n    case QDialogButtonBox::Abort:\n        icon = QStyle::SP_DialogAbortButton;\n        break;\n    case QDialogButtonBox::Retry:\n        icon = QStyle::SP_DialogRetryButton;\n        break;\n    case QDialogButtonBox::Ignore:\n        icon = QStyle::SP_DialogIgnoreButton;\n        break;\n    case QDialogButtonBox::RestoreDefaults:\n        icon = QStyle::SP_RestoreDefaultsButton;\n        break;\n    case QDialogButtonBox::NoButton:\n        return nullptr;\n        ;\n    }\n    QPushButton *button = new QPushButton(QGuiApplicationPrivate::platformTheme()->standardButtonText(sbutton), q);\n    QStyle *style = q->style();\n    if (style->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons, nullptr, q) && icon != 0)\n        button->setIcon(style->standardIcon(QStyle::StandardPixmap(icon), nullptr, q));\n    if (style != QApplication::style()) // Propagate style\n        button->setStyle(style);\n    standardButtonMap.insert(button, sbutton);\n    QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::buttonRole(static_cast<QPlatformDialogHelper::StandardButton>(sbutton));\n    if (Q_UNLIKELY(role == QPlatformDialogHelper::InvalidRole))\n        qWarning(\"QDialogButtonBox::createButton: Invalid ButtonRole, button not added\");\n    else\n        addButton(button, static_cast<QDialogButtonBox::ButtonRole>(role), layoutRule);\n#if QT_CONFIG(shortcut)\n    const QKeySequence standardShortcut = QGuiApplicationPrivate::platformTheme()->standardButtonShortcut(sbutton);\n    if (!standardShortcut.isEmpty())\n        button->setShortcut(standardShortcut);\n#endif\n    return button;\n}\n\nvoid QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role,\n                                        LayoutRule layoutRule, AddRule addRule)\n{\n    buttonLists[role].append(button);\n    switch (addRule) {\n    case AddRule::Connect:\n        QObjectPrivate::connect(button, &QAbstractButton::clicked,\n                               this, &QDialogButtonBoxPrivate::handleButtonClicked);\n        QObjectPrivate::connect(button, &QAbstractButton::destroyed,\n                               this, &QDialogButtonBoxPrivate::handleButtonDestroyed);\n        button->installEventFilter(filter.get());\n        break;\n    case AddRule::SkipConnect:\n        break;\n    }\n\n    switch (layoutRule) {\n    case LayoutRule::DoLayout:\n        layoutButtons();\n        break;\n    case LayoutRule::SkipLayout:\n        break;\n    }\n}\n\nvoid QDialogButtonBoxPrivate::createStandardButtons(QDialogButtonBox::StandardButtons buttons)\n{\n    uint i = QDialogButtonBox::FirstButton;\n    while (i <= QDialogButtonBox::LastButton) {\n        if (i & buttons)\n            createButton(QDialogButtonBox::StandardButton(i), LayoutRule::SkipLayout);\n        i = i << 1;\n    }\n    layoutButtons();\n}\n\nvoid QDialogButtonBoxPrivate::retranslateStrings()\n{\n    for (const auto &it : std::as_const(standardButtonMap)) {\n        const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(it.second);\n        if (!text.isEmpty())\n            it.first->setText(text);\n    }\n}\n\n/*!\n    Constructs an empty, horizontal button box with the given \\a parent.\n\n    \\sa orientation, addButton()\n*/\nQDialogButtonBox::QDialogButtonBox(QWidget *parent)\n    : QDialogButtonBox(Qt::Horizontal, parent)\n{\n}\n\n/*!\n    Constructs an empty button box with the given \\a orientation and \\a parent.\n\n    \\sa orientation, addButton()\n*/\nQDialogButtonBox::QDialogButtonBox(Qt::Orientation orientation, QWidget *parent)\n    : QWidget(*new QDialogButtonBoxPrivate(orientation), parent, { })\n{\n    d_func()->initLayout();\n}\n\n/*!\n    \\since 5.2\n\n    Constructs a horizontal button box with the given \\a parent, containing\n    the standard buttons specified by \\a buttons.\n\n    \\sa orientation, addButton()\n*/\nQDialogButtonBox::QDialogButtonBox(StandardButtons buttons, QWidget *parent)\n    : QDialogButtonBox(buttons, Qt::Horizontal, parent)\n{\n}\n\n/*!\n    Constructs a button box with the given \\a orientation and \\a parent, containing\n    the standard buttons specified by \\a buttons.\n\n    \\sa orientation, addButton()\n*/\nQDialogButtonBox::QDialogButtonBox(StandardButtons buttons, Qt::Orientation orientation,\n                                   QWidget *parent)\n    : QDialogButtonBox(orientation, parent)\n{\n    d_func()->createStandardButtons(buttons);\n}\n\n/*!\n    Destroys the button box.\n*/\nQDialogButtonBox::~QDialogButtonBox()\n{\n    Q_D(QDialogButtonBox);\n\n    d->ignoreShowAndHide = true;\n\n    // QObjectPrivate::connect requires explicit disconnect in destructor\n    // otherwise the connection may kick in on child destruction and reach\n    // the parent's destroyed private object\n    d->disconnectAll();\n}\n\n/*!\n    \\enum QDialogButtonBox::ButtonRole\n\n//! [buttonrole-enum]\n    This enum describes the roles that can be used to describe buttons in\n    the button box. Combinations of these roles are as flags used to\n    describe different aspects of their behavior.\n\n    \\value InvalidRole The button is invalid.\n    \\value AcceptRole Clicking the button causes the dialog to be accepted\n           (e.g. OK).\n    \\value RejectRole Clicking the button causes the dialog to be rejected\n           (e.g. Cancel).\n    \\value DestructiveRole Clicking the button causes a destructive change\n           (e.g. for Discarding Changes) and closes the dialog.\n    \\value ActionRole Clicking the button causes changes to the elements within\n           the dialog.\n    \\value HelpRole The button can be clicked to request help.\n    \\value YesRole The button is a \"Yes\"-like button.\n    \\value NoRole The button is a \"No\"-like button.\n    \\value ApplyRole The button applies current changes.\n    \\value ResetRole The button resets the dialog's fields to default values.\n\n    \\omitvalue NRoles\n\n    \\sa StandardButton\n//! [buttonrole-enum]\n*/\n\n/*!\n    \\enum QDialogButtonBox::StandardButton\n\n    These enums describe flags for standard buttons. Each button has a\n    defined \\l ButtonRole.\n\n    \\value Ok An \"OK\" button defined with the \\l AcceptRole.\n    \\value Open An \"Open\" button defined with the \\l AcceptRole.\n    \\value Save A \"Save\" button defined with the \\l AcceptRole.\n    \\value Cancel A \"Cancel\" button defined with the \\l RejectRole.\n    \\value Close A \"Close\" button defined with the \\l RejectRole.\n    \\value Discard A \"Discard\" or \"Don't Save\" button, depending on the platform,\n                    defined with the \\l DestructiveRole.\n    \\value Apply An \"Apply\" button defined with the \\l ApplyRole.\n    \\value Reset A \"Reset\" button defined with the \\l ResetRole.\n    \\value RestoreDefaults A \"Restore Defaults\" button defined with the \\l ResetRole.\n    \\value Help A \"Help\" button defined with the \\l HelpRole.\n    \\value SaveAll A \"Save All\" button defined with the \\l AcceptRole.\n    \\value Yes A \"Yes\" button defined with the \\l YesRole.\n    \\value YesToAll A \"Yes to All\" button defined with the \\l YesRole.\n    \\value No A \"No\" button defined with the \\l NoRole.\n    \\value NoToAll A \"No to All\" button defined with the \\l NoRole.\n    \\value Abort An \"Abort\" button defined with the \\l RejectRole.\n    \\value Retry A \"Retry\" button defined with the \\l AcceptRole.\n    \\value Ignore An \"Ignore\" button defined with the \\l AcceptRole.\n\n    \\value NoButton An invalid button.\n\n    \\omitvalue FirstButton\n    \\omitvalue LastButton\n\n    \\sa ButtonRole, standardButtons\n*/\n\n/*!\n    \\enum QDialogButtonBox::ButtonLayout\n\n    This enum describes the layout policy to be used when arranging the buttons\n    contained in the button box.\n\n    \\value WinLayout Use a policy appropriate for applications on Windows.\n    \\value MacLayout Use a policy appropriate for applications on \\macos.\n    \\value KdeLayout Use a policy appropriate for applications on KDE.\n    \\value GnomeLayout Use a policy appropriate for applications on GNOME.\n    \\value AndroidLayout Use a policy appropriate for applications on Android.\n                            This enum value was added in Qt 5.10.\n\n    The button layout is specified by the \\l{style()}{current style}. However,\n    on the X11 platform, it may be influenced by the desktop environment.\n*/\n\n/*!\n    \\fn void QDialogButtonBox::clicked(QAbstractButton *button)\n\n    This signal is emitted when a button inside the button box is clicked. The\n    specific button that was pressed is specified by \\a button.\n\n    \\sa accepted(), rejected(), helpRequested()\n*/\n\n/*!\n    \\fn void QDialogButtonBox::accepted()\n\n    This signal is emitted when a button inside the button box is clicked, as long\n    as it was defined with the \\l AcceptRole or \\l YesRole.\n\n    \\sa rejected(), clicked(), helpRequested()\n*/\n\n/*!\n    \\fn void QDialogButtonBox::rejected()\n\n    This signal is emitted when a button inside the button box is clicked, as long\n    as it was defined with the \\l RejectRole or \\l NoRole.\n\n    \\sa accepted(), helpRequested(), clicked()\n*/\n\n/*!\n    \\fn void QDialogButtonBox::helpRequested()\n\n    This signal is emitted when a button inside the button box is clicked, as long\n    as it was defined with the \\l HelpRole.\n\n    \\sa accepted(), rejected(), clicked()\n*/\n\n/*!\n    \\property QDialogButtonBox::orientation\n    \\brief the orientation of the button box\n\n    By default, the orientation is horizontal (i.e. the buttons are laid out\n    side by side). The possible orientations are Qt::Horizontal and\n    Qt::Vertical.\n*/\nQt::Orientation QDialogButtonBox::orientation() const\n{\n    return d_func()->orientation;\n}\n\nvoid QDialogButtonBox::setOrientation(Qt::Orientation orientation)\n{\n    Q_D(QDialogButtonBox);\n    if (orientation == d->orientation)\n        return;\n\n    d->orientation = orientation;\n    d->resetLayout();\n}\n\n/*!\n    Clears the button box, deleting all buttons within it.\n\n    \\sa removeButton(), addButton()\n*/\nvoid QDialogButtonBox::clear()\n{\n    Q_D(QDialogButtonBox);\n    // Remove the created standard buttons, they should be in the other lists, which will\n    // do the deletion\n    d->standardButtonMap.clear();\n    for (int i = 0; i < NRoles; ++i) {\n        QList<QAbstractButton *> &list = d->buttonLists[i];\n        for (auto button : std::as_const(list)) {\n            QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,\n                                       d, &QDialogButtonBoxPrivate::handleButtonDestroyed);\n            delete button;\n        }\n        list.clear();\n    }\n}\n\n/*!\n    Returns a list of all buttons that have been added to the button box.\n\n    \\sa buttonRole(), addButton(), removeButton()\n*/\nQList<QAbstractButton *> QDialogButtonBox::buttons() const\n{\n    Q_D(const QDialogButtonBox);\n    return d->allButtons();\n}\n\nQList<QAbstractButton *> QDialogButtonBoxPrivate::visibleButtons() const\n{\n    QList<QAbstractButton *> finalList;\n    for (int i = 0; i < QDialogButtonBox::NRoles; ++i) {\n        const QList<QAbstractButton *> &list = buttonLists[i];\n        for (int j = 0; j < list.size(); ++j)\n            finalList.append(list.at(j));\n    }\n    return finalList;\n}\n\nQList<QAbstractButton *> QDialogButtonBoxPrivate::allButtons() const\n{\n    QList<QAbstractButton *> ret(visibleButtons());\n    ret.reserve(ret.size() + hiddenButtons.size());\n    for (const auto &it : hiddenButtons)\n        ret.push_back(it.first);\n    return ret;\n}\n\n/*!\n    Returns the button role for the specified \\a button. This function returns\n    \\l InvalidRole if \\a button is \\nullptr or has not been added to the button box.\n\n    \\sa buttons(), addButton()\n*/\nQDialogButtonBox::ButtonRole QDialogButtonBox::buttonRole(QAbstractButton *button) const\n{\n    Q_D(const QDialogButtonBox);\n    for (int i = 0; i < NRoles; ++i) {\n        const QList<QAbstractButton *> &list = d->buttonLists[i];\n        for (int j = 0; j < list.size(); ++j) {\n            if (list.at(j) == button)\n                return ButtonRole(i);\n        }\n    }\n    return d->hiddenButtons.value(button, InvalidRole);\n}\n\n/*!\n    Removes \\a button from the button box without deleting it and sets its parent to zero.\n\n    \\sa clear(), buttons(), addButton()\n*/\nvoid QDialogButtonBox::removeButton(QAbstractButton *button)\n{\n    Q_D(QDialogButtonBox);\n    d->removeButton(button, QDialogButtonBoxPrivate::RemoveReason::ManualRemove);\n}\n\n/*!\n   \\internal\n   Removes \\param button.\n   \\param reason determines the behavior following the removal:\n   \\list\n   \\li \\c ManualRemove disconnects all signals and removes the button from standardButtonMap.\n   \\li \\c HideEvent keeps connections alive, standard buttons remain in standardButtonMap.\n   \\li \\c Destroyed removes the button from standardButtonMap. Signals remain untouched, because\n          the button might already be only a QObject, the destructor of which handles disconnecting.\n   \\endlist\n */\nvoid QDialogButtonBoxPrivate::removeButton(QAbstractButton *button, RemoveReason reason)\n{\n    if (!button)\n        return;\n\n    // Remove button from hidden buttons and roles\n    hiddenButtons.remove(button);\n    for (int i = 0; i < QDialogButtonBox::NRoles; ++i)\n        buttonLists[i].removeOne(button);\n\n    switch (reason) {\n    case RemoveReason::ManualRemove:\n        button->setParent(nullptr);\n        QObjectPrivate::disconnect(button, &QAbstractButton::clicked,\n                                   this, &QDialogButtonBoxPrivate::handleButtonClicked);\n        QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,\n                                   this, &QDialogButtonBoxPrivate::handleButtonDestroyed);\n        button->removeEventFilter(filter.get());\n        Q_FALLTHROUGH();\n    case RemoveReason::Destroyed:\n        standardButtonMap.remove(reinterpret_cast<QPushButton *>(button));\n        break;\n    case RemoveReason::HideEvent:\n        break;\n    }\n}\n\n/*!\n    Adds the given \\a button to the button box with the specified \\a role.\n    If the role is invalid, the button is not added.\n\n    If the button has already been added, it is removed and added again with the\n    new role.\n\n    \\note The button box takes ownership of the button.\n\n    \\sa removeButton(), clear()\n*/\nvoid QDialogButtonBox::addButton(QAbstractButton *button, ButtonRole role)\n{\n    Q_D(QDialogButtonBox);\n    if (Q_UNLIKELY(role <= InvalidRole || role >= NRoles)) {\n        qWarning(\"QDialogButtonBox::addButton: Invalid ButtonRole, button not added\");\n        return;\n    }\n    removeButton(button);\n    button->setParent(this);\n    d->addButton(button, role);\n}\n\n/*!\n    Creates a push button with the given \\a text, adds it to the button box for the\n    specified \\a role, and returns the corresponding push button. If \\a role is\n    invalid, no button is created, and zero is returned.\n\n    \\sa removeButton(), clear()\n*/\nQPushButton *QDialogButtonBox::addButton(const QString &text, ButtonRole role)\n{\n    Q_D(QDialogButtonBox);\n    if (Q_UNLIKELY(role <= InvalidRole || role >= NRoles)) {\n        qWarning(\"QDialogButtonBox::addButton: Invalid ButtonRole, button not added\");\n        return nullptr;\n    }\n    QPushButton *button = new QPushButton(text, this);\n    d->addButton(button, role);\n    return button;\n}\n\n/*!\n    Adds a standard \\a button to the button box if it is valid to do so, and returns\n    a push button. If \\a button is invalid, it is not added to the button box, and\n    zero is returned.\n\n    \\sa removeButton(), clear()\n*/\nQPushButton *QDialogButtonBox::addButton(StandardButton button)\n{\n    Q_D(QDialogButtonBox);\n    return d->createButton(button);\n}\n\n/*!\n    \\property QDialogButtonBox::standardButtons\n    \\brief collection of standard buttons in the button box\n\n    This property controls which standard buttons are used by the button box.\n\n    \\sa addButton()\n*/\nvoid QDialogButtonBox::setStandardButtons(StandardButtons buttons)\n{\n    Q_D(QDialogButtonBox);\n    // Clear out all the old standard buttons, then recreate them.\n    const auto oldButtons = d->standardButtonMap.keys();\n    d->standardButtonMap.clear();\n    qDeleteAll(oldButtons);\n\n    d->createStandardButtons(buttons);\n}\n\nQDialogButtonBox::StandardButtons QDialogButtonBox::standardButtons() const\n{\n    Q_D(const QDialogButtonBox);\n    StandardButtons standardButtons = NoButton;\n    for (const auto value : d->standardButtonMap.values())\n        standardButtons |= value;\n    return standardButtons;\n}\n\n/*!\n    Returns the QPushButton corresponding to the standard button \\a which,\n    or \\nullptr if the standard button doesn't exist in this button box.\n\n    \\sa standardButton(), standardButtons(), buttons()\n*/\nQPushButton *QDialogButtonBox::button(StandardButton which) const\n{\n    Q_D(const QDialogButtonBox);\n\n    for (const auto &it : std::as_const(d->standardButtonMap)) {\n        if (it.second == which)\n            return it.first;\n    }\n    return nullptr;\n}\n\n/*!\n    Returns the standard button enum value corresponding to the given \\a button,\n    or NoButton if the given \\a button isn't a standard button.\n\n    \\sa button(), buttons(), standardButtons()\n*/\nQDialogButtonBox::StandardButton QDialogButtonBox::standardButton(QAbstractButton *button) const\n{\n    Q_D(const QDialogButtonBox);\n    return d->standardButtonMap.value(static_cast<QPushButton *>(button));\n}\n\nvoid QDialogButtonBoxPrivate::handleButtonClicked()\n{\n    Q_Q(QDialogButtonBox);\n    if (QAbstractButton *button = qobject_cast<QAbstractButton *>(q->sender())) {\n        // Can't fetch this *after* emitting clicked, as clicked may destroy the button\n        // or change its role. Now changing the role is not possible yet, but arguably\n        // both clicked and accepted/rejected/etc. should be emitted \"atomically\"\n        // depending on whatever role the button had at the time of the click.\n        const QDialogButtonBox::ButtonRole buttonRole = q->buttonRole(button);\n        QPointer<QDialogButtonBox> guard(q);\n\n        emit q->clicked(button);\n\n        if (!guard)\n            return;\n\n        switch (QPlatformDialogHelper::ButtonRole(buttonRole)) {\n        case QPlatformDialogHelper::AcceptRole:\n        case QPlatformDialogHelper::YesRole:\n            emit q->accepted();\n            break;\n        case QPlatformDialogHelper::RejectRole:\n        case QPlatformDialogHelper::NoRole:\n            emit q->rejected();\n            break;\n        case QPlatformDialogHelper::HelpRole:\n            emit q->helpRequested();\n            break;\n        default:\n            break;\n        }\n    }\n}\n\nvoid QDialogButtonBoxPrivate::handleButtonDestroyed()\n{\n    Q_Q(QDialogButtonBox);\n    if (QObject *object = q->sender())\n        removeButton(reinterpret_cast<QAbstractButton *>(object), RemoveReason::Destroyed);\n}\n\nbool QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton *button, QEvent *event)\n{\n    Q_Q(QDialogButtonBox);\n\n    const QEvent::Type type = event->type();\n\n    if ((type != QEvent::HideToParent && type != QEvent::ShowToParent) || ignoreShowAndHide)\n        return false;\n\n    switch (type) {\n    case QEvent::HideToParent: {\n        const QDialogButtonBox::ButtonRole role = q->buttonRole(button);\n        if (role != QDialogButtonBox::ButtonRole::InvalidRole) {\n            removeButton(button, RemoveReason::HideEvent);\n            hiddenButtons.insert(button, role);\n            layoutButtons();\n        }\n        break;\n    }\n    case QEvent::ShowToParent:\n        if (hiddenButtons.contains(button)) {\n            const auto role = hiddenButtons.take(button);\n            addButton(button, role, LayoutRule::DoLayout, AddRule::SkipConnect);\n            if (role == QDialogButtonBox::AcceptRole)\n                ensureFirstAcceptIsDefault();\n        }\n        break;\n    default: break;\n    }\n\n    return false;\n}\n\n/*!\n    \\property QDialogButtonBox::centerButtons\n    \\brief whether the buttons in the button box are centered\n\n    By default, this property is \\c false. This behavior is appropriate\n    for most types of dialogs. A notable exception is message boxes\n    on most platforms (e.g. Windows), where the button box is\n    centered horizontally.\n\n    \\sa QMessageBox\n*/\nvoid QDialogButtonBox::setCenterButtons(bool center)\n{\n    Q_D(QDialogButtonBox);\n    if (d->center != center) {\n        d->center = center;\n        d->resetLayout();\n    }\n}\n\nbool QDialogButtonBox::centerButtons() const\n{\n    Q_D(const QDialogButtonBox);\n    return d->center;\n}\n\n/*!\n    \\reimp\n*/\nvoid QDialogButtonBox::changeEvent(QEvent *event)\n{\n    Q_D(QDialogButtonBox);\n    switch (event->type()) {\n    case QEvent::StyleChange:  // Propagate style\n        if (!d->standardButtonMap.empty()) {\n            QStyle *newStyle = style();\n            for (auto key : d->standardButtonMap.keys())\n                key->setStyle(newStyle);\n        }\n#ifdef Q_OS_MAC\n        Q_FALLTHROUGH();\n    case QEvent::MacSizeChange:\n#endif\n        d->resetLayout();\n        QWidget::changeEvent(event);\n        break;\n    default:\n        QWidget::changeEvent(event);\n        break;\n    }\n}\n\nvoid QDialogButtonBoxPrivate::ensureFirstAcceptIsDefault()\n{\n    Q_Q(QDialogButtonBox);\n    const QList<QAbstractButton *> &acceptRoleList = buttonLists[QDialogButtonBox::AcceptRole];\n    QPushButton *firstAcceptButton = acceptRoleList.isEmpty()\n                                   ? nullptr\n                                   : qobject_cast<QPushButton *>(acceptRoleList.at(0));\n\n    if (!firstAcceptButton)\n        return;\n\n    bool hasDefault = false;\n    QWidget *dialog = nullptr;\n    QWidget *p = q;\n    while (p && !p->isWindow()) {\n        p = p->parentWidget();\n        if ((dialog = qobject_cast<QDialog *>(p)))\n            break;\n    }\n\n    QWidget *parent = dialog ? dialog : q;\n    Q_ASSERT(parent);\n\n    const auto pushButtons = parent->findChildren<QPushButton *>();\n    for (QPushButton *pushButton : pushButtons) {\n        if (pushButton->isDefault() && pushButton != firstAcceptButton) {\n            hasDefault = true;\n            break;\n        }\n    }\n    if (!hasDefault && firstAcceptButton) {\n        firstAcceptButton->setDefault(true);\n        // When the QDialogButtonBox is focused, and it doesn't have an\n        // explicit focus widget, it will transfer focus to its focus\n        // proxy, which is the first button in the layout. This behavior,\n        // combined with the behavior that QPushButtons in a QDialog will\n        // by default have their autoDefault set to true, results in the\n        // focus proxy/first button stealing the default button status\n        // immediately when the button box is focused, which is not what\n        // we want. Account for this by explicitly making the firstAcceptButton\n        // focused as well, unless an explicit focus widget has been set, or\n        // a dialog child has Qt::StrongFocus.\n        if (dialog && !(QWidgetPrivate::get(dialog)->hasChildWithFocusPolicy(Qt::StrongFocus, q)\n                        || dialog->focusWidget()))\n            firstAcceptButton->setFocus();\n    }\n}\n\nvoid QDialogButtonBoxPrivate::disconnectAll()\n{\n    Q_Q(QDialogButtonBox);\n    const auto buttons = q->findChildren<QAbstractButton *>();\n    for (auto *button : buttons)\n        button->disconnect(q);\n}\n\n/*!\n    \\reimp\n*/\nbool QDialogButtonBox::event(QEvent *event)\n{\n    Q_D(QDialogButtonBox);\n    switch (event->type()) {\n    case QEvent::Show:\n        d->ensureFirstAcceptIsDefault();\n        break;\n\n    case QEvent::LanguageChange:\n        d->retranslateStrings();\n        break;\n\n    default: break;\n    }\n\n    return QWidget::event(event);\n}\n\nQT_END_NAMESPACE\n\n#include \"moc_qdialogbuttonbox.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qdialogsbinarycompat_win.cpp",
    "content": "/****************************************************************************\n**\n** Copyright (C) 2015 The Qt Company Ltd.\n** Contact: http://www.qt.io/licensing/\n**\n** This file is part of the QtGui module of the Qt Toolkit.\n**\n** $QT_BEGIN_LICENSE:LGPL$\n** Commercial License Usage\n** Licensees holding valid commercial Qt licenses may use this file in\n** accordance with the commercial license agreement provided with the\n** Software or, alternatively, in accordance with the terms contained in\n** a written agreement between you and The Qt Company. For licensing terms\n** and conditions see http://www.qt.io/terms-conditions. For further\n** information use the contact form at http://www.qt.io/contact-us.\n**\n** GNU Lesser General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU Lesser\n** General Public License version 2.1 or version 3 as published by the Free\n** Software Foundation and appearing in the file LICENSE.LGPLv21 and\n** LICENSE.LGPLv3 included in the packaging of this file. Please review the\n** following information to ensure the GNU Lesser General Public License\n** requirements will be met: https://www.gnu.org/licenses/lgpl.html and\n** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n**\n** As a special exception, The Qt Company gives you certain additional\n** rights. These rights are described in The Qt Company LGPL Exception\n** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n**\n** GNU General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU\n** General Public License version 3.0 as published by the Free Software\n** Foundation and appearing in the file LICENSE.GPL included in the\n** packaging of this file.  Please review the following information to\n** ensure the GNU General Public License version 3.0 requirements will be\n** met: http://www.gnu.org/copyleft/gpl.html.\n**\n** $QT_END_LICENSE$\n**\n****************************************************************************/\n\n#include <qglobal.h>\n\n// ### Qt 5: eliminate this file\n\n/*\n    This is evil. MSVC doesn't let us remove private symbols, nor change their\n    visibility; yet there are some symbols we really needed to make public, e.g.,\n    ~QColorDialog(), and then there were some totally needless symbols in our\n    header files, e.g., setSelectedAlpha(). So we define a new version of\n    QColorDialog & Co. with only the private symbols that we removed from the\n    public header files. The friends are there only to prevent potential compiler\n    warnings.\n\n    It would have been nicer to export the missing symbols as mangled \"C\" symbols\n    instead but unfortunately MSVC uses out-of-reach characters like @ and . in\n    their mangled C++ symbols.\n*/\n\n#if QT_VERSION < 0x050000 && defined(Q_CC_MSVC)\n\nQT_BEGIN_NAMESPACE\n\n#include <QtGui/QColor>\n#include <QtGui/QFont>\n\nclass QColorDialogPrivate;\nclass QFontDialogPrivate;\nclass QInputDialogPrivate;\nclass QWidget;\n\nclass Q_GUI_EXPORT QColorDialog\n{\nprivate:\n    explicit QColorDialog(QWidget *, bool);\n    ~QColorDialog();\n\n    void setColor(const QColor &);\n    QColor color() const;\n    bool selectColor(const QColor &);\n    void setSelectedAlpha(int);\n    int selectedAlpha() const;\n\n    friend class QColorDialogPrivate;\n};\n\nQColorDialog::QColorDialog(QWidget *, bool) {}\nQColorDialog::~QColorDialog() {}\nvoid QColorDialog::setColor(const QColor &) {}\nQColor QColorDialog::color() const { return QColor(); }\nbool QColorDialog::selectColor(const QColor &) { return false; }\nvoid QColorDialog::setSelectedAlpha(int) {}\nint QColorDialog::selectedAlpha() const { return 0; }\n\nclass Q_GUI_EXPORT QFontDialog\n{\nprivate:\n    explicit QFontDialog(QWidget *, bool, Qt::WindowFlags);\n    ~QFontDialog();\n\n    QFont font() const;\n    void setFont(const QFont &);\n    void updateFamilies();\n    void updateStyles();\n    void updateSizes();\n\n    static QFont getFont(bool *, const QFont *, QWidget *);\n\n    friend class QFontDialogPrivate;\n};\n\nQFontDialog::QFontDialog(QWidget *, bool, Qt::WindowFlags) {}\nQFontDialog::~QFontDialog() {}\nQFont QFontDialog::font() const { return QFont(); }\nvoid QFontDialog::setFont(const QFont &) { }\nvoid QFontDialog::updateFamilies() {}\nvoid QFontDialog::updateStyles() {}\nvoid QFontDialog::updateSizes() {}\nQFont QFontDialog::getFont(bool *, const QFont *, QWidget *) { return QFont(); }\n\nclass Q_GUI_EXPORT QInputDialog\n{\nprivate:\n    enum Type { LineEdit, SpinBox, DoubleSpinBox, ComboBox, EditableComboBox };\n\n    QInputDialog(const QString &, QWidget *, Type, Qt::WindowFlags);\n    QInputDialog(const QString &, const QString &, QWidget *, QWidget *, Qt::WindowFlags);\n    ~QInputDialog();\n};\n\nQInputDialog::QInputDialog(const QString &, QWidget *, Type, Qt::WindowFlags) {}\nQInputDialog::QInputDialog(const QString &, const QString &, QWidget *, QWidget *, Qt::WindowFlags) {}\nQInputDialog::~QInputDialog() {}\n\nQT_END_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qerrormessage.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qerrormessage.h\"\n\n#include \"qapplication.h\"\n#include \"qcheckbox.h\"\n#include \"qlabel.h\"\n#include \"qlayout.h\"\n#if QT_CONFIG(messagebox)\n#include \"qmessagebox.h\"\n#endif\n#include \"qpushbutton.h\"\n#include \"qstringlist.h\"\n#include \"qtextedit.h\"\n#include \"qdialog_p.h\"\n#include \"qpixmap.h\"\n#include \"qmetaobject.h\"\n#include \"qthread.h\"\n#include \"qset.h\"\n\n#include <queue>\n\n#include <stdio.h>\n#include <stdlib.h>\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\nclass QErrorMessagePrivate : public QDialogPrivate\n{\n    Q_DECLARE_PUBLIC(QErrorMessage)\npublic:\n    struct Message {\n        QString content;\n        QString type;\n    };\n\n    QPushButton * ok;\n    QCheckBox * again;\n    QTextEdit * errors;\n    QLabel * icon;\n    std::queue<Message> pending;\n    QSet<QString> doNotShow;\n    QSet<QString> doNotShowType;\n    QString currentMessage;\n    QString currentType;\n\n    bool isMessageToBeShown(const QString &message, const QString &type) const;\n    bool nextPending();\n    void retranslateStrings();\n\n    void setVisible(bool) override;\n\nprivate:\n    void initHelper(QPlatformDialogHelper *) override;\n    void helperPrepareShow(QPlatformDialogHelper *) override;\n};\n\n\nvoid QErrorMessagePrivate::initHelper(QPlatformDialogHelper *helper)\n{\n    Q_Q(QErrorMessage);\n    auto *messageDialogHelper = static_cast<QPlatformMessageDialogHelper *>(helper);\n    QObject::connect(messageDialogHelper, &QPlatformMessageDialogHelper::checkBoxStateChanged, q,\n        [this](Qt::CheckState state) {\n            again->setCheckState(state);\n        }\n    );\n    QObject::connect(messageDialogHelper, &QPlatformMessageDialogHelper::clicked, q,\n        [this](QPlatformDialogHelper::StandardButton, QPlatformDialogHelper::ButtonRole) {\n            Q_Q(QErrorMessage);\n            q->accept();\n        }\n    );\n}\n\nvoid QErrorMessagePrivate::helperPrepareShow(QPlatformDialogHelper *helper)\n{\n    Q_Q(QErrorMessage);\n    auto *messageDialogHelper = static_cast<QPlatformMessageDialogHelper *>(helper);\n    QSharedPointer<QMessageDialogOptions> options = QMessageDialogOptions::create();\n    options->setText(currentMessage);\n    options->setWindowTitle(q->windowTitle());\n    options->setText(QErrorMessage::tr(\"An error occurred\"));\n    options->setInformativeText(currentMessage);\n    options->setStandardIcon(QMessageDialogOptions::Critical);\n    options->setCheckBox(again->text(), again->checkState());\n    messageDialogHelper->setOptions(options);\n}\n\nnamespace {\nclass QErrorMessageTextView : public QTextEdit\n{\npublic:\n    QErrorMessageTextView(QWidget *parent)\n        : QTextEdit(parent) { setReadOnly(true); }\n\n    virtual QSize minimumSizeHint() const override;\n    virtual QSize sizeHint() const override;\n};\n} // unnamed namespace\n\nQSize QErrorMessageTextView::minimumSizeHint() const\n{\n    return QSize(50, 50);\n}\n\nQSize QErrorMessageTextView::sizeHint() const\n{\n    return QSize(250, 75);\n}\n\n/*!\n    \\class QErrorMessage\n\n    \\brief The QErrorMessage class provides an error message display dialog.\n\n    \\ingroup standard-dialog\n    \\inmodule QtWidgets\n\n    An error message widget consists of a text label and a checkbox. The\n    checkbox lets the user control whether the same error message will be\n    displayed again in the future, typically displaying the text,\n    \"Show this message again\" translated into the appropriate local\n    language.\n\n    For production applications, the class can be used to display messages which\n    the user only needs to see once. To use QErrorMessage like this, you create\n    the dialog in the usual way, and show it by calling the showMessage() slot or\n    connecting signals to it.\n\n    The static qtHandler() function installs a message handler\n    using qInstallMessageHandler() and creates a QErrorMessage that displays\n    qDebug(), qWarning() and qFatal() messages. This is most useful in\n    environments where no console is available to display warnings and\n    error messages.\n\n    In both cases QErrorMessage will queue pending messages and display\n    them in order, with each new message being shown as soon as the user\n    has accepted the previous message. Once the user has specified that a\n    message is not to be shown again it is automatically skipped, and the\n    dialog will show the next appropriate message in the queue.\n\n    The \\l{dialogs/standarddialogs}{Standard Dialogs} example shows\n    how to use QErrorMessage as well as other built-in Qt dialogs.\n\n    \\image qerrormessage.png\n\n    \\sa QMessageBox, QStatusBar::showMessage(), {Standard Dialogs Example}\n*/\n\nstatic QErrorMessage * qtMessageHandler = nullptr;\n\nstatic void deleteStaticcQErrorMessage() // post-routine\n{\n    if (qtMessageHandler) {\n        delete qtMessageHandler;\n        qtMessageHandler = nullptr;\n    }\n}\n\nstatic bool metFatal = false;\n\nstatic QString msgType2i18nString(QtMsgType t)\n{\n    static_assert(QtDebugMsg == 0);\n    static_assert(QtWarningMsg == 1);\n    static_assert(QtCriticalMsg == 2);\n    static_assert(QtFatalMsg == 3);\n    static_assert(QtInfoMsg == 4);\n\n    // adjust the array below if any of the above fire...\n\n    const char * const messages[] = {\n        QT_TRANSLATE_NOOP(\"QErrorMessage\", \"Debug Message:\"),\n        QT_TRANSLATE_NOOP(\"QErrorMessage\", \"Warning:\"),\n        QT_TRANSLATE_NOOP(\"QErrorMessage\", \"Critical Error:\"),\n        QT_TRANSLATE_NOOP(\"QErrorMessage\", \"Fatal Error:\"),\n        QT_TRANSLATE_NOOP(\"QErrorMessage\", \"Information:\"),\n    };\n    Q_ASSERT(size_t(t) < sizeof messages / sizeof *messages);\n\n    return QCoreApplication::translate(\"QErrorMessage\", messages[t]);\n}\n\nstatic QtMessageHandler originalMessageHandler = nullptr;\n\nstatic void jump(QtMsgType t, const QMessageLogContext &context, const QString &m)\n{\n    const auto forwardToOriginalHandler = qScopeGuard([&] {\n       if (originalMessageHandler)\n            originalMessageHandler(t, context, m);\n    });\n\n    if (!qtMessageHandler)\n        return;\n\n    auto *defaultCategory = QLoggingCategory::defaultCategory();\n    if (context.category && defaultCategory\n        && qstrcmp(context.category, defaultCategory->categoryName()) != 0)\n        return;\n\n    QString rich = \"<p><b>\"_L1 + msgType2i18nString(t) + \"</b></p>\"_L1\n                   + Qt::convertFromPlainText(m, Qt::WhiteSpaceNormal);\n\n    // ### work around text engine quirk\n    if (rich.endsWith(\"</p>\"_L1))\n        rich.chop(4);\n\n    if (!metFatal) {\n        if (QThread::currentThread() == qApp->thread()) {\n            qtMessageHandler->showMessage(rich);\n        } else {\n            QMetaObject::invokeMethod(qtMessageHandler,\n                                      \"showMessage\",\n                                      Qt::QueuedConnection,\n                                      Q_ARG(QString, rich));\n        }\n        metFatal = (t == QtFatalMsg);\n    }\n}\n\n\n/*!\n    Constructs and installs an error handler window with the given \\a\n    parent.\n\n    The default \\l{Qt::WindowModality} {window modality} of the dialog\n    depends on the platform. The window modality can be overridden via\n    setWindowModality() before calling showMessage().\n*/\n\nQErrorMessage::QErrorMessage(QWidget * parent)\n    : QDialog(*new QErrorMessagePrivate, parent)\n{\n    Q_D(QErrorMessage);\n\n#if defined(Q_OS_MACOS)\n    setWindowModality(parent ? Qt::WindowModal : Qt::ApplicationModal);\n#endif\n\n    d->icon = new QLabel(this);\n    d->errors = new QErrorMessageTextView(this);\n    d->again = new QCheckBox(this);\n    d->ok = new QPushButton(this);\n    QGridLayout * grid = new QGridLayout(this);\n\n    connect(d->ok, SIGNAL(clicked()), this, SLOT(accept()));\n\n    grid->addWidget(d->icon,   0, 0, Qt::AlignTop);\n    grid->addWidget(d->errors, 0, 1);\n    grid->addWidget(d->again,  1, 1, Qt::AlignTop);\n    grid->addWidget(d->ok,     2, 0, 1, 2, Qt::AlignCenter);\n    grid->setColumnStretch(1, 42);\n    grid->setRowStretch(0, 42);\n\n#if QT_CONFIG(messagebox)\n    const auto iconSize = style()->pixelMetric(QStyle::PM_MessageBoxIconSize, nullptr, this);\n    const auto icon = style()->standardIcon(QStyle::SP_MessageBoxInformation, nullptr, this);\n    d->icon->setPixmap(icon.pixmap(QSize(iconSize, iconSize), devicePixelRatio()));\n    d->icon->setAlignment(Qt::AlignHCenter | Qt::AlignTop);\n#endif\n    d->again->setChecked(true);\n    d->ok->setFocus();\n\n    d->retranslateStrings();\n}\n\n\n/*!\n    Destroys the error message dialog.\n*/\n\nQErrorMessage::~QErrorMessage()\n{\n    if (this == qtMessageHandler) {\n        qtMessageHandler = nullptr;\n        QtMessageHandler currentMessagHandler = qInstallMessageHandler(nullptr);\n        if (currentMessagHandler != jump)\n            qInstallMessageHandler(currentMessagHandler);\n        else\n            qInstallMessageHandler(originalMessageHandler);\n        originalMessageHandler = nullptr;\n    }\n}\n\n\n/*! \\reimp */\n\nvoid QErrorMessage::done(int a)\n{\n    Q_D(QErrorMessage);\n    if (!d->again->isChecked()) {\n        if (d->currentType.isEmpty()) {\n            if (!d->currentMessage.isEmpty())\n                d->doNotShow.insert(d->currentMessage);\n        } else {\n            d->doNotShowType.insert(d->currentType);\n        }\n    }\n    d->currentMessage.clear();\n    d->currentType.clear();\n\n    QDialog::done(a);\n\n    if (d->nextPending()) {\n        show();\n    } else {\n        if (this == qtMessageHandler && metFatal)\n            exit(1);\n    }\n}\n\n\n/*!\n    Returns a pointer to a QErrorMessage object that outputs the\n    default Qt messages. This function creates such an object, if there\n    isn't one already.\n\n    The object will only output log messages of QLoggingCategory::defaultCategory().\n\n    The object will forward all messages to the original message handler.\n\n    \\sa qInstallMessageHandler\n*/\n\nQErrorMessage * QErrorMessage::qtHandler()\n{\n    if (!qtMessageHandler) {\n        qtMessageHandler = new QErrorMessage(nullptr);\n        qAddPostRoutine(deleteStaticcQErrorMessage); // clean up\n        qtMessageHandler->setWindowTitle(QCoreApplication::applicationName());\n        originalMessageHandler = qInstallMessageHandler(jump);\n    }\n    return qtMessageHandler;\n}\n\n\n/*! \\internal */\n\nbool QErrorMessagePrivate::isMessageToBeShown(const QString &message, const QString &type) const\n{\n    return !message.isEmpty()\n        && (type.isEmpty() ? !doNotShow.contains(message) : !doNotShowType.contains(type));\n}\n\nbool QErrorMessagePrivate::nextPending()\n{\n    while (!pending.empty()) {\n        QString message = std::move(pending.front().content);\n        QString type = std::move(pending.front().type);\n        pending.pop();\n        if (isMessageToBeShown(message, type)) {\n#ifndef QT_NO_TEXTHTMLPARSER\n            errors->setHtml(message);\n#else\n            errors->setPlainText(message);\n#endif\n            currentMessage = std::move(message);\n            currentType = std::move(type);\n            again->setChecked(true);\n            return true;\n        }\n    }\n    return false;\n}\n\n\n/*!\n    Shows the given message, \\a message, and returns immediately. If the user\n    has requested for the message not to be shown again, this function does\n    nothing.\n\n    Normally, the message is displayed immediately. However, if there are\n    pending messages, it will be queued to be displayed later.\n*/\n\nvoid QErrorMessage::showMessage(const QString &message)\n{\n    showMessage(message, QString());\n}\n\n/*!\n    \\overload\n\n    Shows the given message, \\a message, and returns immediately. If the user\n    has requested for messages of type, \\a type, not to be shown again, this\n    function does nothing.\n\n    Normally, the message is displayed immediately. However, if there are\n    pending messages, it will be queued to be displayed later.\n\n    \\sa showMessage()\n*/\n\nvoid QErrorMessage::showMessage(const QString &message, const QString &type)\n{\n    Q_D(QErrorMessage);\n    if (!d->isMessageToBeShown(message, type))\n        return;\n    d->pending.push({message, type});\n    if (!isVisible() && d->nextPending())\n        show();\n}\n\nvoid QErrorMessagePrivate::setVisible(bool visible)\n{\n    Q_Q(QErrorMessage);\n\n    if (canBeNativeDialog())\n        setNativeDialogVisible(visible);\n\n    // Update WA_DontShowOnScreen based on whether the native dialog was shown,\n    // so that QDialog::setVisible(visible) below updates the QWidget state correctly,\n    // but skips showing the non-native version.\n    q->setAttribute(Qt::WA_DontShowOnScreen, nativeDialogInUse);\n\n    QDialogPrivate::setVisible(visible);\n}\n\n/*!\n    \\reimp\n*/\nvoid QErrorMessage::changeEvent(QEvent *e)\n{\n    Q_D(QErrorMessage);\n    if (e->type() == QEvent::LanguageChange) {\n        d->retranslateStrings();\n    }\n    QDialog::changeEvent(e);\n}\n\nvoid QErrorMessagePrivate::retranslateStrings()\n{\n    again->setText(QErrorMessage::tr(\"&Show this message again\"));\n    ok->setText(QErrorMessage::tr(\"&OK\"));\n}\n\nQT_END_NAMESPACE\n\n#include \"moc_qerrormessage.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qfiledialog.cpp",
    "content": "// Copyright (C) 2020 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#define QT_NO_URL_CAST_FROM_STRING\n\n#include <qvariant.h>\n#include <private/qwidgetitemdata_p.h>\n#include \"qfiledialog.h\"\n\n#include \"qfiledialog_p.h\"\n#include <private/qapplication_p.h>\n#include <private/qguiapplication_p.h>\n#include <qfontmetrics.h>\n#include <qaction.h>\n#include <qactiongroup.h>\n#include <qheaderview.h>\n#if QT_CONFIG(shortcut)\n#  include <qshortcut.h>\n#endif\n#include <qgridlayout.h>\n#if QT_CONFIG(menu)\n#include <qmenu.h>\n#endif\n#if QT_CONFIG(messagebox)\n#include <qmessagebox.h>\n#endif\n#include <stdlib.h>\n#if QT_CONFIG(settings)\n#include <qsettings.h>\n#endif\n#include <qdebug.h>\n#if QT_CONFIG(mimetype)\n#include <qmimedatabase.h>\n#endif\n#if QT_CONFIG(regularexpression)\n#include <qregularexpression.h>\n#endif\n#include <qapplication.h>\n#include <qstylepainter.h>\n#include \"ui_qfiledialog.h\"\n#if defined(Q_OS_UNIX)\n#include <pwd.h>\n#include <unistd.h> // for pathconf() on OS X\n#elif defined(Q_OS_WIN)\n#  include <QtCore/qt_windows.h>\n#endif\n#if defined(Q_OS_WASM)\n#include <private/qwasmlocalfileaccess_p.h>\n#endif\n\n#include <algorithm>\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\nQ_GLOBAL_STATIC(QUrl, lastVisitedDir)\n\n/*!\n  \\class QFileDialog\n  \\brief The QFileDialog class provides a dialog that allows users to select files or directories.\n  \\ingroup standard-dialogs\n  \\inmodule QtWidgets\n\n  The QFileDialog class enables a user to traverse the file system\n  to select one or many files or a directory.\n\n  \\image qtquickdialogs-filedialog-gtk.png\n\n  The easiest way to create a QFileDialog is to use the static functions,\n  such as \\l getOpenFileName().\n\n  \\snippet code/src_gui_dialogs_qfiledialog.cpp 0\n\n  In the above example, a modal QFileDialog is created using a static\n  function. The dialog initially displays the contents of the \"/home/jana\"\n  directory, and displays files matching the patterns given in the\n  string \"Image Files (*.png *.jpg *.bmp)\". The parent of the file dialog\n  is set to \\e this, and the window title is set to \"Open Image\".\n\n  If you want to use multiple filters, separate each one with\n  \\e two semicolons. For example:\n\n  \\snippet code/src_gui_dialogs_qfiledialog.cpp 1\n\n  You can create your own QFileDialog without using the static\n  functions. By calling setFileMode(), you can specify what the user must\n  select in the dialog:\n\n  \\snippet code/src_gui_dialogs_qfiledialog.cpp 2\n\n  In the above example, the mode of the file dialog is set to\n  AnyFile, meaning that the user can select any file, or even specify a\n  file that doesn't exist. This mode is useful for creating a\n  \"Save As\" file dialog. Use ExistingFile if the user must select an\n  existing file, or \\l Directory if only a directory can be selected.\n  See the \\l QFileDialog::FileMode enum for the complete list of modes.\n\n  The fileMode property contains the mode of operation for the dialog;\n  this indicates what types of objects the user is expected to select.\n  Use setNameFilter() to set the dialog's file filter. For example:\n\n  \\snippet code/src_gui_dialogs_qfiledialog.cpp 3\n\n  In the above example, the filter is set to \\c{\"Images (*.png *.xpm *.jpg)\"}.\n  This means that only files with the extension \\c png, \\c xpm,\n  or \\c jpg are shown in the QFileDialog. You can apply\n  several filters by using setNameFilters(). Use selectNameFilter() to select\n  one of the filters you've given as the file dialog's default filter.\n\n  The file dialog has two view modes: \\l{QFileDialog::}{List} and\n  \\l{QFileDialog::}{Detail}.\n  \\l{QFileDialog::}{List} presents the contents of the current directory\n  as a list of file and directory names. \\l{QFileDialog::}{Detail} also\n  displays a list of file and directory names, but provides additional\n  information alongside each name, such as the file size and modification\n  date. Set the mode with setViewMode():\n\n  \\snippet code/src_gui_dialogs_qfiledialog.cpp 4\n\n  The last important function you need to use when creating your\n  own file dialog is selectedFiles().\n\n  \\snippet code/src_gui_dialogs_qfiledialog.cpp 5\n\n  In the above example, a modal file dialog is created and shown. If\n  the user clicked OK, the file they selected is put in \\c fileName.\n\n  The dialog's working directory can be set with setDirectory().\n  Each file in the current directory can be selected using\n  the selectFile() function.\n\n  The \\l{dialogs/standarddialogs}{Standard Dialogs} example shows\n  how to use QFileDialog as well as other built-in Qt dialogs.\n\n  By default, a platform-native file dialog is used if the platform has\n  one. In that case, the widgets that would otherwise be used to construct the\n  dialog are not instantiated, so related accessors such as layout() and\n  itemDelegate() return null. Also, not all platforms show file dialogs\n  with a title bar, so be aware that the caption text might not be visible to\n  the user. You can set the \\l DontUseNativeDialog option or set the\n  \\l{Qt::AA_DontUseNativeDialogs}{AA_DontUseNativeDialogs} application attribute\n  to ensure that the widget-based implementation is used instead of the native dialog.\n\n  \\sa QDir, QFileInfo, QFile, QColorDialog, QFontDialog, {Standard Dialogs Example}\n*/\n\n/*!\n    \\enum QFileDialog::AcceptMode\n\n    \\value AcceptOpen\n    \\value AcceptSave\n*/\n\n/*!\n    \\enum QFileDialog::ViewMode\n\n    This enum describes the view mode of the file dialog; that is, what\n    information about each file is displayed.\n\n    \\value Detail Displays an icon, a name, and details for each item in\n                  the directory.\n    \\value List   Displays only an icon and a name for each item in the\n                  directory.\n\n    \\sa setViewMode()\n*/\n\n/*!\n    \\enum QFileDialog::FileMode\n\n    This enum is used to indicate what the user may select in the file\n    dialog; that is, what the dialog returns if the user clicks OK.\n\n    \\value AnyFile        The name of a file, whether it exists or not.\n    \\value ExistingFile   The name of a single existing file.\n    \\value Directory      The name of a directory. Both files and\n                          directories are displayed. However, the native Windows\n                          file dialog does not support displaying files in the\n                          directory chooser.\n    \\value ExistingFiles  The names of zero or more existing files.\n\n    \\sa setFileMode()\n*/\n\n/*!\n    \\enum QFileDialog::Option\n\n    Options that influence the behavior of the dialog.\n\n    \\value ShowDirsOnly Only show directories. By\n    default, both files and directories are shown.\\br\n    This option is only effective in the \\l Directory file mode.\n\n    \\value DontResolveSymlinks Don't resolve symlinks.\n    By default, symlinks are resolved.\n\n    \\value DontConfirmOverwrite Don't ask for confirmation if an\n    existing file is selected. By default, confirmation is requested.\\br\n    This option is only effective if \\l acceptMode is \\l {QFileDialog::}{AcceptSave}).\n    It is furthermore not used on macOS for native file dialogs.\n\n    \\value DontUseNativeDialog Don't use a platform-native file dialog,\n    but the widget-based one provided by Qt.\\br\n    By default, a native file dialog is shown unless you use a subclass\n    of QFileDialog that contains the Q_OBJECT macro, the global\n    \\l{Qt::}{AA_DontUseNativeDialogs} application attribute is set, or the platform\n    does not have a native dialog of the type that you require.\\br\n    For the option to be effective, you must set it before changing\n    other properties of the dialog, or showing the dialog.\n\n    \\value ReadOnly Indicates that the model is read-only.\n\n    \\value HideNameFilterDetails Indicates if the file name filter details are\n    hidden or not.\n\n    \\value DontUseCustomDirectoryIcons Always use the default directory icon.\\br\n    Some platforms allow the user to set a different icon, but custom icon lookup\n    might cause significant performance issues over network or removable drives.\\br\n    Setting this will enable the\n    \\l{QAbstractFileIconProvider::}{DontUseCustomDirectoryIcons}\n    option in \\l{iconProvider()}.\\br\n    This enum value was added in Qt 5.2.\n\n    \\sa options, testOption\n*/\n\n/*!\n  \\enum QFileDialog::DialogLabel\n\n  \\value LookIn\n  \\value FileName\n  \\value FileType\n  \\value Accept\n  \\value Reject\n*/\n\n/*!\n    \\fn void QFileDialog::filesSelected(const QStringList &selected)\n\n    When the selection changes for local operations and the dialog is\n    accepted, this signal is emitted with the (possibly empty) list\n    of \\a selected files.\n\n    \\sa currentChanged(), QDialog::Accepted\n*/\n\n/*!\n    \\fn void QFileDialog::urlsSelected(const QList<QUrl> &urls)\n\n    When the selection changes and the dialog is accepted, this signal is\n    emitted with the (possibly empty) list of selected \\a urls.\n\n    \\sa currentUrlChanged(), QDialog::Accepted\n    \\since 5.2\n*/\n\n/*!\n    \\fn void QFileDialog::fileSelected(const QString &file)\n\n    When the selection changes for local operations and the dialog is\n    accepted, this signal is emitted with the (possibly empty)\n    selected \\a file.\n\n    \\sa currentChanged(), QDialog::Accepted\n*/\n\n/*!\n    \\fn void QFileDialog::urlSelected(const QUrl &url)\n\n    When the selection changes and the dialog is accepted, this signal is\n    emitted with the (possibly empty) selected \\a url.\n\n    \\sa currentUrlChanged(), QDialog::Accepted\n    \\since 5.2\n*/\n\n/*!\n    \\fn void QFileDialog::currentChanged(const QString &path)\n\n    When the current file changes for local operations, this signal is\n    emitted with the new file name as the \\a path parameter.\n\n    \\sa filesSelected()\n*/\n\n/*!\n    \\fn void QFileDialog::currentUrlChanged(const QUrl &url)\n\n    When the current file changes, this signal is emitted with the\n    new file URL as the \\a url parameter.\n\n    \\sa urlsSelected()\n    \\since 5.2\n*/\n\n/*!\n  \\fn void QFileDialog::directoryEntered(const QString &directory)\n\n  This signal is emitted for local operations when the user enters\n  a \\a directory.\n*/\n\n/*!\n  \\fn void QFileDialog::directoryUrlEntered(const QUrl &directory)\n\n  This signal is emitted when the user enters a \\a directory.\n\n  \\since 5.2\n*/\n\n/*!\n  \\fn void QFileDialog::filterSelected(const QString &filter)\n\n  This signal is emitted when the user selects a \\a filter.\n*/\n\nQT_BEGIN_INCLUDE_NAMESPACE\n#include <QMetaEnum>\n#if QT_CONFIG(shortcut)\n#  include <qshortcut.h>\n#endif\nQT_END_INCLUDE_NAMESPACE\n\n/*!\n    \\fn QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags flags)\n\n    Constructs a file dialog with the given \\a parent and widget \\a flags.\n*/\nQFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f)\n    : QDialog(*new QFileDialogPrivate, parent, f)\n{\n    Q_D(QFileDialog);\n    QFileDialogArgs args;\n    d->init(args);\n}\n\n/*!\n    Constructs a file dialog with the given \\a parent and \\a caption that\n    initially displays the contents of the specified \\a directory.\n    The contents of the directory are filtered before being shown in the\n    dialog, using a semicolon-separated list of filters specified by\n    \\a filter.\n*/\nQFileDialog::QFileDialog(QWidget *parent,\n                     const QString &caption,\n                     const QString &directory,\n                     const QString &filter)\n    : QDialog(*new QFileDialogPrivate, parent, { })\n{\n    Q_D(QFileDialog);\n    QFileDialogArgs args(QUrl::fromLocalFile(directory));\n    args.filter = filter;\n    args.caption = caption;\n    d->init(args);\n}\n\n/*!\n    \\internal\n*/\nQFileDialog::QFileDialog(const QFileDialogArgs &args)\n    : QDialog(*new QFileDialogPrivate, args.parent, { })\n{\n    Q_D(QFileDialog);\n    d->init(args);\n    setFileMode(args.mode);\n    setOptions(args.options);\n    selectFile(args.selection);\n}\n\n/*!\n    Destroys the file dialog.\n*/\nQFileDialog::~QFileDialog()\n{\n    Q_D(QFileDialog);\n#if QT_CONFIG(settings)\n    d->saveSettings();\n#endif\n    if (QPlatformFileDialogHelper *platformHelper = d->platformFileDialogHelper()) {\n        // QIOSFileDialog emits directoryChanged while hiding, causing an assert\n        // because of a partially destroyed QFileDialog.\n        QObjectPrivate::disconnect(platformHelper, &QPlatformFileDialogHelper::directoryEntered,\n                                   d, &QFileDialogPrivate::nativeEnterDirectory);\n    }\n}\n\n/*!\n    Sets the \\a urls that are located in the sidebar.\n\n    For instance:\n\n    \\snippet filedialogurls/filedialogurls.cpp 0\n\n    Then the file dialog looks like this:\n\n    \\image filedialogurls.png\n\n    \\sa sidebarUrls()\n*/\nvoid QFileDialog::setSidebarUrls(const QList<QUrl> &urls)\n{\n    Q_D(QFileDialog);\n    if (!d->nativeDialogInUse)\n        d->qFileDialogUi->sidebar->setUrls(urls);\n}\n\n/*!\n    Returns a list of urls that are currently in the sidebar\n*/\nQList<QUrl> QFileDialog::sidebarUrls() const\n{\n    Q_D(const QFileDialog);\n    return (d->nativeDialogInUse ? QList<QUrl>() : d->qFileDialogUi->sidebar->urls());\n}\n\nstatic const qint32 QFileDialogMagic = 0xbe;\n\n/*!\n    Saves the state of the dialog's layout, history and current directory.\n\n    Typically this is used in conjunction with QSettings to remember the size\n    for a future session. A version number is stored as part of the data.\n*/\nQByteArray QFileDialog::saveState() const\n{\n    Q_D(const QFileDialog);\n    int version = 4;\n    QByteArray data;\n    QDataStream stream(&data, QIODevice::WriteOnly);\n    stream.setVersion(QDataStream::Qt_5_0);\n\n    stream << qint32(QFileDialogMagic);\n    stream << qint32(version);\n    if (d->usingWidgets()) {\n        stream << d->qFileDialogUi->splitter->saveState();\n        stream << d->qFileDialogUi->sidebar->urls();\n    } else {\n        stream << d->splitterState;\n        stream << d->sidebarUrls;\n    }\n    stream << history();\n    stream << *lastVisitedDir();\n    if (d->usingWidgets())\n        stream << d->qFileDialogUi->treeView->header()->saveState();\n    else\n        stream << d->headerData;\n    stream << qint32(viewMode());\n    return data;\n}\n\n/*!\n    Restores the dialogs's layout, history and current directory to the \\a state specified.\n\n    Typically this is used in conjunction with QSettings to restore the size\n    from a past session.\n\n    Returns \\c false if there are errors\n*/\nbool QFileDialog::restoreState(const QByteArray &state)\n{\n    Q_D(QFileDialog);\n    QByteArray sd = state;\n    QDataStream stream(&sd, QIODevice::ReadOnly);\n    stream.setVersion(QDataStream::Qt_5_0);\n    if (stream.atEnd())\n        return false;\n    QStringList history;\n    QUrl currentDirectory;\n    qint32 marker;\n    qint32 v;\n    qint32 viewMode;\n    stream >> marker;\n    stream >> v;\n    // the code below only supports versions 3 and 4\n    if (marker != QFileDialogMagic || (v != 3 && v != 4))\n        return false;\n\n    stream >> d->splitterState\n           >> d->sidebarUrls\n           >> history;\n    if (v == 3) {\n        QString currentDirectoryString;\n        stream >> currentDirectoryString;\n        currentDirectory = QUrl::fromLocalFile(currentDirectoryString);\n    } else {\n        stream >> currentDirectory;\n    }\n    stream >> d->headerData\n           >> viewMode;\n\n    setDirectoryUrl(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());\n    setViewMode(static_cast<QFileDialog::ViewMode>(viewMode));\n\n    if (!d->usingWidgets())\n        return true;\n\n    return d->restoreWidgetState(history, -1);\n}\n\n/*!\n    \\reimp\n*/\nvoid QFileDialog::changeEvent(QEvent *e)\n{\n    Q_D(QFileDialog);\n    if (e->type() == QEvent::LanguageChange) {\n        d->retranslateWindowTitle();\n        d->retranslateStrings();\n    }\n    QDialog::changeEvent(e);\n}\n\nQFileDialogPrivate::QFileDialogPrivate()\n    :\n#if QT_CONFIG(proxymodel)\n        proxyModel(nullptr),\n#endif\n        model(nullptr),\n        currentHistoryLocation(-1),\n        renameAction(nullptr),\n        deleteAction(nullptr),\n        showHiddenAction(nullptr),\n        useDefaultCaption(true),\n        qFileDialogUi(nullptr),\n        options(QFileDialogOptions::create())\n{\n}\n\nQFileDialogPrivate::~QFileDialogPrivate()\n{\n}\n\nvoid QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)\n{\n    Q_Q(QFileDialog);\n    auto *fileDialogHelper = static_cast<QPlatformFileDialogHelper *>(h);\n    QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::fileSelected,\n                            this, &QFileDialogPrivate::emitUrlSelected);\n    QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::filesSelected,\n                            this, &QFileDialogPrivate::emitUrlsSelected);\n    QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::currentChanged,\n                            this, &QFileDialogPrivate::nativeCurrentChanged);\n    QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::directoryEntered,\n                            this, &QFileDialogPrivate::nativeEnterDirectory);\n    QObject::connect(fileDialogHelper, &QPlatformFileDialogHelper::filterSelected,\n                     q, &QFileDialog::filterSelected);\n    fileDialogHelper->setOptions(options);\n}\n\nvoid QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)\n{\n    Q_Q(QFileDialog);\n    options->setWindowTitle(q->windowTitle());\n    options->setHistory(q->history());\n    if (usingWidgets())\n        options->setSidebarUrls(qFileDialogUi->sidebar->urls());\n    if (options->initiallySelectedNameFilter().isEmpty())\n        options->setInitiallySelectedNameFilter(q->selectedNameFilter());\n    if (options->initiallySelectedFiles().isEmpty())\n        options->setInitiallySelectedFiles(userSelectedFiles());\n}\n\nvoid QFileDialogPrivate::helperDone(QDialog::DialogCode code, QPlatformDialogHelper *)\n{\n    if (code == QDialog::Accepted) {\n        Q_Q(QFileDialog);\n        q->setViewMode(static_cast<QFileDialog::ViewMode>(options->viewMode()));\n        q->setSidebarUrls(options->sidebarUrls());\n        q->setHistory(options->history());\n    }\n}\n\nvoid QFileDialogPrivate::retranslateWindowTitle()\n{\n    Q_Q(QFileDialog);\n    if (!useDefaultCaption || setWindowTitle != q->windowTitle())\n        return;\n    if (q->acceptMode() == QFileDialog::AcceptOpen) {\n        const QFileDialog::FileMode fileMode = q->fileMode();\n        if (fileMode == QFileDialog::Directory)\n            q->setWindowTitle(QFileDialog::tr(\"Find Directory\"));\n        else\n            q->setWindowTitle(QFileDialog::tr(\"Open\"));\n    } else\n        q->setWindowTitle(QFileDialog::tr(\"Save As\"));\n\n    setWindowTitle = q->windowTitle();\n}\n\nvoid QFileDialogPrivate::setLastVisitedDirectory(const QUrl &dir)\n{\n    *lastVisitedDir() = dir;\n}\n\nvoid QFileDialogPrivate::updateLookInLabel()\n{\n    if (options->isLabelExplicitlySet(QFileDialogOptions::LookIn))\n        setLabelTextControl(QFileDialog::LookIn, options->labelText(QFileDialogOptions::LookIn));\n}\n\nvoid QFileDialogPrivate::updateFileNameLabel()\n{\n    if (options->isLabelExplicitlySet(QFileDialogOptions::FileName)) {\n        setLabelTextControl(QFileDialog::FileName, options->labelText(QFileDialogOptions::FileName));\n    } else {\n        switch (q_func()->fileMode()) {\n        case QFileDialog::Directory:\n            setLabelTextControl(QFileDialog::FileName, QFileDialog::tr(\"Directory:\"));\n            break;\n        default:\n            setLabelTextControl(QFileDialog::FileName, QFileDialog::tr(\"File &name:\"));\n            break;\n        }\n    }\n}\n\nvoid QFileDialogPrivate::updateFileTypeLabel()\n{\n    if (options->isLabelExplicitlySet(QFileDialogOptions::FileType))\n        setLabelTextControl(QFileDialog::FileType, options->labelText(QFileDialogOptions::FileType));\n}\n\nvoid QFileDialogPrivate::updateOkButtonText(bool saveAsOnFolder)\n{\n    Q_Q(QFileDialog);\n    // 'Save as' at a folder: Temporarily change to \"Open\".\n    if (saveAsOnFolder) {\n        setLabelTextControl(QFileDialog::Accept, QFileDialog::tr(\"&Open\"));\n    } else if (options->isLabelExplicitlySet(QFileDialogOptions::Accept)) {\n        setLabelTextControl(QFileDialog::Accept, options->labelText(QFileDialogOptions::Accept));\n        return;\n    } else {\n        switch (q->fileMode()) {\n        case QFileDialog::Directory:\n            setLabelTextControl(QFileDialog::Accept, QFileDialog::tr(\"&Choose\"));\n            break;\n        default:\n            setLabelTextControl(QFileDialog::Accept,\n                                q->acceptMode() == QFileDialog::AcceptOpen ?\n                                    QFileDialog::tr(\"&Open\")  :\n                                    QFileDialog::tr(\"&Save\"));\n            break;\n        }\n    }\n}\n\nvoid QFileDialogPrivate::updateCancelButtonText()\n{\n    if (options->isLabelExplicitlySet(QFileDialogOptions::Reject))\n        setLabelTextControl(QFileDialog::Reject, options->labelText(QFileDialogOptions::Reject));\n}\n\nvoid QFileDialogPrivate::retranslateStrings()\n{\n    Q_Q(QFileDialog);\n    /* WIDGETS */\n    if (options->useDefaultNameFilters())\n        q->setNameFilter(QFileDialogOptions::defaultNameFilterString());\n    if (!usingWidgets())\n        return;\n\n    QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();\n    QAbstractItemModel *abstractModel = model;\n#if QT_CONFIG(proxymodel)\n    if (proxyModel)\n        abstractModel = proxyModel;\n#endif\n    const int total = qMin(abstractModel->columnCount(QModelIndex()), int(actions.size() + 1));\n    for (int i = 1; i < total; ++i) {\n        actions.at(i - 1)->setText(QFileDialog::tr(\"Show \") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());\n    }\n\n    /* MENU ACTIONS */\n    renameAction->setText(QFileDialog::tr(\"&Rename\"));\n    deleteAction->setText(QFileDialog::tr(\"&Delete\"));\n    showHiddenAction->setText(QFileDialog::tr(\"Show &hidden files\"));\n    newFolderAction->setText(QFileDialog::tr(\"&New Folder\"));\n    qFileDialogUi->retranslateUi(q);\n    updateLookInLabel();\n    updateFileNameLabel();\n    updateFileTypeLabel();\n    updateCancelButtonText();\n}\n\nvoid QFileDialogPrivate::emitFilesSelected(const QStringList &files)\n{\n    Q_Q(QFileDialog);\n    emit q->filesSelected(files);\n    if (files.size() == 1)\n        emit q->fileSelected(files.first());\n}\n\nbool QFileDialogPrivate::canBeNativeDialog() const\n{\n    // Don't use Q_Q here! This function is called from ~QDialog,\n    // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).\n    const QDialog * const q = static_cast<const QDialog*>(q_ptr);\n    if (nativeDialogInUse)\n        return true;\n    if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)\n        || q->testAttribute(Qt::WA_DontShowOnScreen)\n        || (options->options() & QFileDialog::DontUseNativeDialog)) {\n        return false;\n    }\n\n    return strcmp(QFileDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;\n}\n\nbool QFileDialogPrivate::usingWidgets() const\n{\n    return !nativeDialogInUse && qFileDialogUi;\n}\n\n/*!\n    Sets the given \\a option to be enabled if \\a on is true; otherwise,\n    clears the given \\a option.\n\n    Options (particularly the \\l DontUseNativeDialog option) should be set\n    before changing dialog properties or showing the dialog.\n\n    Setting options while the dialog is visible is not guaranteed to have\n    an immediate effect on the dialog (depending on the option and on the\n    platform).\n\n    Setting options after changing other properties may cause these\n    values to have no effect.\n\n    \\sa options, testOption()\n*/\nvoid QFileDialog::setOption(Option option, bool on)\n{\n    const QFileDialog::Options previousOptions = options();\n    if (!(previousOptions & option) != !on)\n        setOptions(previousOptions ^ option);\n}\n\n/*!\n    Returns \\c true if the given \\a option is enabled; otherwise, returns\n    false.\n\n    \\sa options, setOption()\n*/\nbool QFileDialog::testOption(Option option) const\n{\n    Q_D(const QFileDialog);\n    return d->options->testOption(static_cast<QFileDialogOptions::FileDialogOption>(option));\n}\n\n/*!\n    \\property QFileDialog::options\n    \\brief The various options that affect the look and feel of the dialog.\n\n    By default, all options are disabled.\n\n    Options (particularly the \\l DontUseNativeDialog option) should be set\n    before changing dialog properties or showing the dialog.\n\n    Setting options while the dialog is visible is not guaranteed to have\n    an immediate effect on the dialog (depending on the option and on the\n    platform).\n\n    Setting options after changing other properties may cause these\n    values to have no effect.\n\n    \\sa setOption(), testOption()\n*/\nvoid QFileDialog::setOptions(Options options)\n{\n    Q_D(QFileDialog);\n\n    Options changed = (options ^ QFileDialog::options());\n    if (!changed)\n        return;\n\n    d->options->setOptions(QFileDialogOptions::FileDialogOptions(int(options)));\n\n    if (options & DontUseNativeDialog) {\n        d->nativeDialogInUse = false;\n        d->createWidgets();\n    }\n\n    if (d->usingWidgets()) {\n        if (changed & DontResolveSymlinks)\n            d->model->setResolveSymlinks(!(options & DontResolveSymlinks));\n        if (changed & ReadOnly) {\n            bool ro = (options & ReadOnly);\n            d->model->setReadOnly(ro);\n            d->qFileDialogUi->newFolderButton->setEnabled(!ro);\n            d->renameAction->setEnabled(!ro);\n            d->deleteAction->setEnabled(!ro);\n        }\n\n        if (changed & DontUseCustomDirectoryIcons) {\n            QFileIconProvider::Options providerOptions = iconProvider()->options();\n            providerOptions.setFlag(QFileIconProvider::DontUseCustomDirectoryIcons,\n                                    options & DontUseCustomDirectoryIcons);\n            iconProvider()->setOptions(providerOptions);\n        }\n    }\n\n    if (changed & HideNameFilterDetails)\n        setNameFilters(d->options->nameFilters());\n\n    if (changed & ShowDirsOnly)\n        setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);\n}\n\nQFileDialog::Options QFileDialog::options() const\n{\n    Q_D(const QFileDialog);\n    static_assert((int)QFileDialog::ShowDirsOnly == (int)QFileDialogOptions::ShowDirsOnly);\n    static_assert((int)QFileDialog::DontResolveSymlinks == (int)QFileDialogOptions::DontResolveSymlinks);\n    static_assert((int)QFileDialog::DontConfirmOverwrite == (int)QFileDialogOptions::DontConfirmOverwrite);\n    static_assert((int)QFileDialog::DontUseNativeDialog == (int)QFileDialogOptions::DontUseNativeDialog);\n    static_assert((int)QFileDialog::ReadOnly == (int)QFileDialogOptions::ReadOnly);\n    static_assert((int)QFileDialog::HideNameFilterDetails == (int)QFileDialogOptions::HideNameFilterDetails);\n    static_assert((int)QFileDialog::DontUseCustomDirectoryIcons == (int)QFileDialogOptions::DontUseCustomDirectoryIcons);\n    return QFileDialog::Options(int(d->options->options()));\n}\n\n/*!\n    This function shows the dialog, and connects the slot specified by \\a receiver\n    and \\a member to the signal that informs about selection changes. If the fileMode is\n    ExistingFiles, this is the filesSelected() signal, otherwise it is the fileSelected() signal.\n\n    The signal is disconnected from the slot when the dialog is closed.\n*/\nvoid QFileDialog::open(QObject *receiver, const char *member)\n{\n    Q_D(QFileDialog);\n    const char *signal = (fileMode() == ExistingFiles) ? SIGNAL(filesSelected(QStringList))\n                                                       : SIGNAL(fileSelected(QString));\n    connect(this, signal, receiver, member);\n    d->signalToDisconnectOnClose = signal;\n    d->receiverToDisconnectOnClose = receiver;\n    d->memberToDisconnectOnClose = member;\n\n    QDialog::open();\n}\n\n\n/*!\n    \\reimp\n*/\nvoid QFileDialog::setVisible(bool visible)\n{\n    // will call QFileDialogPrivate::setVisible override\n    QDialog::setVisible(visible);\n}\n\n/*!\n    \\internal\n\n    The logic has to live here so that the call to hide() in ~QDialog calls\n    this function; it wouldn't call an override of QDialog::setVisible().\n*/\nvoid QFileDialogPrivate::setVisible(bool visible)\n{\n    Q_Q(QFileDialog);\n\n    if (canBeNativeDialog()){\n        if (setNativeDialogVisible(visible)){\n            // Set WA_DontShowOnScreen so that QDialogPrivate::setVisible(visible) below\n            // updates the state correctly, but skips showing the non-native version:\n            q->setAttribute(Qt::WA_DontShowOnScreen);\n#if QT_CONFIG(fscompleter)\n            // So the completer doesn't try to complete and therefore show a popup\n            if (!nativeDialogInUse)\n                completer->setModel(nullptr);\n#endif\n        } else {\n            createWidgets();\n            q->setAttribute(Qt::WA_DontShowOnScreen, false);\n#if QT_CONFIG(fscompleter)\n            if (!nativeDialogInUse) {\n                if (proxyModel != nullptr)\n                    completer->setModel(proxyModel);\n                else\n                    completer->setModel(model);\n            }\n#endif\n        }\n    }\n\n    if (visible && usingWidgets())\n        qFileDialogUi->fileNameEdit->setFocus();\n\n    QDialogPrivate::setVisible(visible);\n}\n\n/*!\n    \\internal\n    set the directory to url\n*/\nvoid QFileDialogPrivate::goToUrl(const QUrl &url)\n{\n    //The shortcut in the side bar may have a parent that is not fetched yet (e.g. an hidden file)\n    //so we force the fetching\n    QFileSystemModelPrivate::QFileSystemNode *node = model->d_func()->node(url.toLocalFile(), true);\n    QModelIndex idx =  model->d_func()->index(node);\n    enterDirectory(idx);\n}\n\n/*!\n    \\fn void QFileDialog::setDirectory(const QDir &directory)\n\n    \\overload\n*/\n\n/*!\n    Sets the file dialog's current \\a directory.\n\n    \\note On iOS, if you set \\a directory to \\l{QStandardPaths::standardLocations()}\n        {QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last()},\n        a native image picker dialog is used for accessing the user's photo album.\n        The filename returned can be loaded using QFile and related APIs.\n        For this to be enabled, the Info.plist assigned to QMAKE_INFO_PLIST in the\n        project file must contain the key \\c NSPhotoLibraryUsageDescription. See\n        Info.plist documentation from Apple for more information regarding this key.\n        This feature was added in Qt 5.5.\n*/\nvoid QFileDialog::setDirectory(const QString &directory)\n{\n    Q_D(QFileDialog);\n    QString newDirectory = directory;\n    //we remove .. and . from the given path if exist\n    if (!directory.isEmpty())\n        newDirectory = QDir::cleanPath(directory);\n\n    if (!directory.isEmpty() && newDirectory.isEmpty())\n        return;\n\n    QUrl newDirUrl = QUrl::fromLocalFile(newDirectory);\n    QFileDialogPrivate::setLastVisitedDirectory(newDirUrl);\n\n    d->options->setInitialDirectory(QUrl::fromLocalFile(directory));\n    if (!d->usingWidgets()) {\n        d->setDirectory_sys(newDirUrl);\n        return;\n    }\n    if (d->rootPath() == newDirectory)\n        return;\n    QModelIndex root = d->model->setRootPath(newDirectory);\n    if (!d->nativeDialogInUse) {\n        d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);\n        if (root != d->rootIndex()) {\n#if QT_CONFIG(fscompleter)\n            if (directory.endsWith(u'/'))\n                d->completer->setCompletionPrefix(newDirectory);\n            else\n                d->completer->setCompletionPrefix(newDirectory + u'/');\n#endif\n            d->setRootIndex(root);\n        }\n        d->qFileDialogUi->listView->selectionModel()->clear();\n    }\n}\n\n/*!\n    Returns the directory currently being displayed in the dialog.\n*/\nQDir QFileDialog::directory() const\n{\n    Q_D(const QFileDialog);\n    if (d->nativeDialogInUse) {\n        QString dir = d->directory_sys().toLocalFile();\n        return QDir(dir.isEmpty() ? d->options->initialDirectory().toLocalFile() : dir);\n    }\n    return d->rootPath();\n}\n\n/*!\n    Sets the file dialog's current \\a directory url.\n\n    \\note The non-native QFileDialog supports only local files.\n\n    \\note On Windows, it is possible to pass URLs representing\n    one of the \\e {virtual folders}, such as \"Computer\" or \"Network\".\n    This is done by passing a QUrl using the scheme \\c clsid followed\n    by the CLSID value with the curly braces removed. For example the URL\n    \\c clsid:374DE290-123F-4565-9164-39C4925E467B denotes the download\n    location. For a complete list of possible values, see the MSDN documentation on\n    \\l{https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid}{KNOWNFOLDERID}.\n    This feature was added in Qt 5.5.\n\n    \\sa QUuid\n    \\since 5.2\n*/\nvoid QFileDialog::setDirectoryUrl(const QUrl &directory)\n{\n    Q_D(QFileDialog);\n    if (!directory.isValid())\n        return;\n\n    QFileDialogPrivate::setLastVisitedDirectory(directory);\n    d->options->setInitialDirectory(directory);\n\n    if (d->nativeDialogInUse)\n        d->setDirectory_sys(directory);\n    else if (directory.isLocalFile())\n        setDirectory(directory.toLocalFile());\n    else if (Q_UNLIKELY(d->usingWidgets()))\n        qWarning(\"Non-native QFileDialog supports only local files\");\n}\n\n/*!\n    Returns the url of the directory currently being displayed in the dialog.\n\n    \\since 5.2\n*/\nQUrl QFileDialog::directoryUrl() const\n{\n    Q_D(const QFileDialog);\n    if (d->nativeDialogInUse)\n        return d->directory_sys();\n    else\n        return QUrl::fromLocalFile(directory().absolutePath());\n}\n\n// FIXME Qt 5.4: Use upcoming QVolumeInfo class to determine this information?\nstatic inline bool isCaseSensitiveFileSystem(const QString &path)\n{\n    Q_UNUSED(path);\n#if defined(Q_OS_WIN)\n    // Return case insensitive unconditionally, even if someone has a case sensitive\n    // file system mounted, wrongly capitalized drive letters will cause mismatches.\n    return false;\n#elif defined(Q_OS_MACOS)\n    return pathconf(QFile::encodeName(path).constData(), _PC_CASE_SENSITIVE) == 1;\n#else\n    return true;\n#endif\n}\n\n// Determine the file name to be set on the line edit from the path\n// passed to selectFile() in mode QFileDialog::AcceptSave.\nstatic inline QString fileFromPath(const QString &rootPath, QString path)\n{\n    if (!QFileInfo(path).isAbsolute())\n        return path;\n    if (path.startsWith(rootPath, isCaseSensitiveFileSystem(rootPath) ? Qt::CaseSensitive : Qt::CaseInsensitive))\n        path.remove(0, rootPath.size());\n\n    if (path.isEmpty())\n        return path;\n\n    if (path.at(0) == QDir::separator()\n#ifdef Q_OS_WIN\n            //On Windows both cases can happen\n            || path.at(0) == u'/'\n#endif\n            ) {\n            path.remove(0, 1);\n    }\n    return path;\n}\n\n/*!\n    Selects the given \\a filename in the file dialog.\n\n    \\sa selectedFiles()\n*/\nvoid QFileDialog::selectFile(const QString &filename)\n{\n    Q_D(QFileDialog);\n    if (filename.isEmpty())\n        return;\n\n    if (!d->usingWidgets()) {\n        QUrl url;\n        if (QFileInfo(filename).isRelative()) {\n            url = d->options->initialDirectory();\n            QString path = url.path();\n            if (!path.endsWith(u'/'))\n                path += u'/';\n            url.setPath(path + filename);\n        } else {\n            url = QUrl::fromLocalFile(filename);\n        }\n        d->selectFile_sys(url);\n        d->options->setInitiallySelectedFiles(QList<QUrl>() << url);\n        return;\n    }\n\n    if (!QDir::isRelativePath(filename)) {\n        QFileInfo info(filename);\n        QString filenamePath = info.absoluteDir().path();\n\n        if (d->model->rootPath() != filenamePath)\n            setDirectory(filenamePath);\n    }\n\n    QModelIndex index = d->model->index(filename);\n    d->qFileDialogUi->listView->selectionModel()->clear();\n    if (!isVisible() || !d->lineEdit()->hasFocus())\n        d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));\n}\n\n/*!\n    Selects the given \\a url in the file dialog.\n\n    \\note The non-native QFileDialog supports only local files.\n\n    \\sa selectedUrls()\n    \\since 5.2\n*/\nvoid QFileDialog::selectUrl(const QUrl &url)\n{\n    Q_D(QFileDialog);\n    if (!url.isValid())\n        return;\n\n    if (d->nativeDialogInUse)\n        d->selectFile_sys(url);\n    else if (url.isLocalFile())\n        selectFile(url.toLocalFile());\n    else\n        qWarning(\"Non-native QFileDialog supports only local files\");\n}\n\n#ifdef Q_OS_UNIX\nstatic QString homeDirFromPasswdEntry(const QString &path, const QByteArray &userName)\n{\n#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)\n    passwd pw;\n    passwd *tmpPw;\n    long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);\n    if (bufSize == -1)\n        bufSize = 1024;\n    QVarLengthArray<char, 1024> buf(bufSize);\n    int err = 0;\n#  if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0 < 199506L)\n    tmpPw = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size());\n#  else\n    err = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size(), &tmpPw);\n#  endif\n    if (err || !tmpPw)\n        return path;\n    return QFile::decodeName(pw.pw_dir);\n#else\n    passwd *pw = getpwnam(userName.constData());\n    if (!pw)\n        return path;\n    return QFile::decodeName(pw->pw_dir);\n#endif // defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)\n}\n\nQ_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path)\n{\n    if (!path.startsWith(u'~'))\n        return path;\n\n    if (path.size() == 1) // '~'\n        return QDir::homePath();\n\n    QStringView sv(path);\n    const qsizetype sepIndex = sv.indexOf(QDir::separator());\n    if (sepIndex == 1) // '~/' or '~/a/b/c'\n        return QDir::homePath() + sv.sliced(1);\n\n#if defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)\n    if (sepIndex == -1)\n        return QDir::homePath();\n    return QDir::homePath() + sv.sliced(sepIndex);\n#else\n    const qsizetype userNameLen = sepIndex != -1 ? sepIndex - strlen(\"~\") // '~user/a/b'\n                                                 : path.size() - strlen(\"~\"); // '~user'\n    const QByteArray userName = sv.sliced(1, userNameLen).toLocal8Bit();\n    QString homePath = homeDirFromPasswdEntry(path, userName);\n    if (sepIndex == -1)\n        return homePath;\n    return homePath + sv.sliced(sepIndex);\n#endif // defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)\n}\n#endif\n\n/**\n    Returns the text in the line edit which can be one or more file names\n  */\nQStringList QFileDialogPrivate::typedFiles() const\n{\n    Q_Q(const QFileDialog);\n    QStringList files;\n    QString editText = lineEdit()->text();\n    if (!editText.contains(u'\"')) {\n#ifdef Q_OS_UNIX\n        const QString prefix = q->directory().absolutePath() + QDir::separator();\n        if (QFile::exists(prefix + editText))\n            files << editText;\n        else\n            files << qt_tildeExpansion(editText);\n#else\n        files << editText;\n        Q_UNUSED(q);\n#endif\n    } else {\n        // \" is used to separate files like so: \"file1\" \"file2\" \"file3\" ...\n        // ### need escape character for filenames with quotes (\")\n        QStringList tokens = editText.split(u'\\\"');\n        for (int i=0; i<tokens.size(); ++i) {\n            if ((i % 2) == 0)\n                continue; // Every even token is a separator\n#ifdef Q_OS_UNIX\n            const QString token = tokens.at(i);\n            const QString prefix = q->directory().absolutePath() + QDir::separator();\n            if (QFile::exists(prefix + token))\n                files << token;\n            else\n                files << qt_tildeExpansion(token);\n#else\n            files << toInternal(tokens.at(i));\n#endif\n        }\n    }\n    return addDefaultSuffixToFiles(files);\n}\n\n// Return selected files without defaulting to the root of the file system model\n// used for initializing QFileDialogOptions for native dialogs. The default is\n// not suitable for native dialogs since it mostly equals directory().\nQList<QUrl> QFileDialogPrivate::userSelectedFiles() const\n{\n    QList<QUrl> files;\n\n    if (!usingWidgets())\n        return addDefaultSuffixToUrls(selectedFiles_sys());\n\n    const QModelIndexList selectedRows = qFileDialogUi->listView->selectionModel()->selectedRows();\n    files.reserve(selectedRows.size());\n    for (const QModelIndex &index : selectedRows)\n        files.append(QUrl::fromLocalFile(index.data(QFileSystemModel::FilePathRole).toString()));\n\n    if (files.isEmpty() && !lineEdit()->text().isEmpty()) {\n        const QStringList typedFilesList = typedFiles();\n        files.reserve(typedFilesList.size());\n        for (const QString &path : typedFilesList)\n            files.append(QUrl::fromLocalFile(path));\n    }\n\n    return files;\n}\n\nQStringList QFileDialogPrivate::addDefaultSuffixToFiles(const QStringList &filesToFix) const\n{\n    QStringList files;\n    for (int i=0; i<filesToFix.size(); ++i) {\n        QString name = toInternal(filesToFix.at(i));\n        QFileInfo info(name);\n        // if the filename has no suffix, add the default suffix\n        const QString defaultSuffix = options->defaultSuffix();\n        if (!defaultSuffix.isEmpty() && !info.isDir() && !info.fileName().contains(u'.'))\n            name += u'.' + defaultSuffix;\n\n        if (info.isAbsolute()) {\n            files.append(name);\n        } else {\n            // at this point the path should only have Qt path separators.\n            // This check is needed since we might be at the root directory\n            // and on Windows it already ends with slash.\n            QString path = rootPath();\n            if (!path.endsWith(u'/'))\n                path += u'/';\n            path += name;\n            files.append(path);\n        }\n    }\n    return files;\n}\n\nQList<QUrl> QFileDialogPrivate::addDefaultSuffixToUrls(const QList<QUrl> &urlsToFix) const\n{\n    QList<QUrl> urls;\n    urls.reserve(urlsToFix.size());\n    // if the filename has no suffix, add the default suffix\n    const QString defaultSuffix = options->defaultSuffix();\n    for (QUrl url : urlsToFix) {\n        if (!defaultSuffix.isEmpty()) {\n            const QString urlPath = url.path();\n            const auto idx = urlPath.lastIndexOf(u'/');\n            if (idx != (urlPath.size() - 1) && !QStringView{urlPath}.mid(idx + 1).contains(u'.'))\n                url.setPath(urlPath + u'.' + defaultSuffix);\n        }\n        urls.append(url);\n    }\n    return urls;\n}\n\n\n/*!\n    Returns a list of strings containing the absolute paths of the\n    selected files in the dialog. If no files are selected, or\n    the mode is not ExistingFiles or ExistingFile, selectedFiles() contains the current path in the viewport.\n\n    \\sa selectedNameFilter(), selectFile()\n*/\nQStringList QFileDialog::selectedFiles() const\n{\n    Q_D(const QFileDialog);\n\n    QStringList files;\n    const QList<QUrl> userSelectedFiles = d->userSelectedFiles();\n    files.reserve(userSelectedFiles.size());\n    for (const QUrl &file : userSelectedFiles)\n        files.append(file.toString(QUrl::PreferLocalFile));\n\n    if (files.isEmpty() && d->usingWidgets()) {\n        const FileMode fm = fileMode();\n        if (fm != ExistingFile && fm != ExistingFiles)\n            files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());\n    }\n    return files;\n}\n\n/*!\n    Returns a list of urls containing the selected files in the dialog.\n    If no files are selected, or the mode is not ExistingFiles or\n    ExistingFile, selectedUrls() contains the current path in the viewport.\n\n    \\sa selectedNameFilter(), selectUrl()\n    \\since 5.2\n*/\nQList<QUrl> QFileDialog::selectedUrls() const\n{\n    Q_D(const QFileDialog);\n    if (d->nativeDialogInUse) {\n        return d->userSelectedFiles();\n    } else {\n        QList<QUrl> urls;\n        const QStringList selectedFileList = selectedFiles();\n        urls.reserve(selectedFileList.size());\n        for (const QString &file : selectedFileList)\n            urls.append(QUrl::fromLocalFile(file));\n        return urls;\n    }\n}\n\n/*\n    Makes a list of filters from ;;-separated text.\n    Used by the mac and windows implementations\n*/\nQStringList qt_make_filter_list(const QString &filter)\n{\n    if (filter.isEmpty())\n        return QStringList();\n\n    auto sep = \";;\"_L1;\n    if (!filter.contains(sep) && filter.contains(u'\\n'))\n        sep = \"\\n\"_L1;\n\n    return filter.split(sep);\n}\n\n/*!\n    Sets the filter used in the file dialog to the given \\a filter.\n\n    If \\a filter contains a pair of parentheses containing one or more\n    filename-wildcard patterns, separated by spaces, then only the\n    text contained in the parentheses is used as the filter. This means\n    that these calls are all equivalent:\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 6\n\n    \\note With Android's native file dialog, the mime type matching the given\n        name filter is used because only mime types are supported.\n\n    \\sa setMimeTypeFilters(), setNameFilters()\n*/\nvoid QFileDialog::setNameFilter(const QString &filter)\n{\n    setNameFilters(qt_make_filter_list(filter));\n}\n\n\n/*\n    Strip the filters by removing the details, e.g. (*.*).\n*/\nQStringList qt_strip_filters(const QStringList &filters)\n{\n#if QT_CONFIG(regularexpression)\n    QStringList strippedFilters;\n    static const QRegularExpression r(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp));\n    strippedFilters.reserve(filters.size());\n    for (const QString &filter : filters) {\n        QString filterName;\n        auto match = r.match(filter);\n        if (match.hasMatch())\n            filterName = match.captured(1);\n        strippedFilters.append(filterName.simplified());\n    }\n    return strippedFilters;\n#else\n    return filters;\n#endif\n}\n\n\n/*!\n    Sets the \\a filters used in the file dialog.\n\n    Note that the filter \\b{*.*} is not portable, because the historical\n    assumption that the file extension determines the file type is not\n    consistent on every operating system. It is possible to have a file with no\n    dot in its name (for example, \\c Makefile). In a native Windows file\n    dialog, \\b{*.*} matches such files, while in other types of file dialogs\n    it might not match. So, it's better to use \\b{*} if you mean to select any file.\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 7\n\n    \\l setMimeTypeFilters() has the advantage of providing all possible name\n    filters for each file type. For example, JPEG images have three possible\n    extensions; if your application can open such files, selecting the\n    \\c image/jpeg mime type as a filter allows you to open all of them.\n*/\nvoid QFileDialog::setNameFilters(const QStringList &filters)\n{\n    Q_D(QFileDialog);\n    QStringList cleanedFilters;\n    cleanedFilters.reserve(filters.size());\n    for (const QString &filter : filters)\n        cleanedFilters << filter.simplified();\n\n    d->options->setNameFilters(cleanedFilters);\n\n    if (!d->usingWidgets())\n        return;\n\n    d->qFileDialogUi->fileTypeCombo->clear();\n    if (cleanedFilters.isEmpty())\n        return;\n\n    if (testOption(HideNameFilterDetails))\n        d->qFileDialogUi->fileTypeCombo->addItems(qt_strip_filters(cleanedFilters));\n    else\n        d->qFileDialogUi->fileTypeCombo->addItems(cleanedFilters);\n\n    d->useNameFilter(0);\n}\n\n/*!\n    Returns the file type filters that are in operation on this file\n    dialog.\n*/\nQStringList QFileDialog::nameFilters() const\n{\n    return d_func()->options->nameFilters();\n}\n\n/*!\n    Sets the current file type \\a filter. Multiple filters can be\n    passed in \\a filter by separating them with semicolons or spaces.\n\n    \\sa setNameFilter(), setNameFilters(), selectedNameFilter()\n*/\nvoid QFileDialog::selectNameFilter(const QString &filter)\n{\n    Q_D(QFileDialog);\n    d->options->setInitiallySelectedNameFilter(filter);\n    if (!d->usingWidgets()) {\n        d->selectNameFilter_sys(filter);\n        return;\n    }\n    int i = -1;\n    if (testOption(HideNameFilterDetails)) {\n        const QStringList filters = qt_strip_filters(qt_make_filter_list(filter));\n        if (!filters.isEmpty())\n            i = d->qFileDialogUi->fileTypeCombo->findText(filters.first());\n    } else {\n        i = d->qFileDialogUi->fileTypeCombo->findText(filter);\n    }\n    if (i >= 0) {\n        d->qFileDialogUi->fileTypeCombo->setCurrentIndex(i);\n        d->useNameFilter(d->qFileDialogUi->fileTypeCombo->currentIndex());\n    }\n}\n\n/*!\n    Returns the filter that the user selected in the file dialog.\n\n    \\sa selectedFiles()\n*/\nQString QFileDialog::selectedNameFilter() const\n{\n    Q_D(const QFileDialog);\n    if (!d->usingWidgets())\n        return d->selectedNameFilter_sys();\n\n    if (testOption(HideNameFilterDetails)) {\n        const auto idx = d->qFileDialogUi->fileTypeCombo->currentIndex();\n        if (idx >= 0 && idx < d->options->nameFilters().size())\n            return d->options->nameFilters().at(d->qFileDialogUi->fileTypeCombo->currentIndex());\n    }\n    return d->qFileDialogUi->fileTypeCombo->currentText();\n}\n\n/*!\n    Returns the filter that is used when displaying files.\n\n    \\sa setFilter()\n*/\nQDir::Filters QFileDialog::filter() const\n{\n    Q_D(const QFileDialog);\n    if (d->usingWidgets())\n        return d->model->filter();\n    return d->options->filter();\n}\n\n/*!\n    Sets the filter used by the model to \\a filters. The filter is used\n    to specify the kind of files that should be shown.\n\n    \\sa filter()\n*/\n\nvoid QFileDialog::setFilter(QDir::Filters filters)\n{\n    Q_D(QFileDialog);\n    d->options->setFilter(filters);\n    if (!d->usingWidgets()) {\n        d->setFilter_sys();\n        return;\n    }\n\n    d->model->setFilter(filters);\n    d->showHiddenAction->setChecked((filters & QDir::Hidden));\n}\n\n#if QT_CONFIG(mimetype)\n\nstatic QString nameFilterForMime(const QString &mimeType)\n{\n    QMimeDatabase db;\n    QMimeType mime(db.mimeTypeForName(mimeType));\n    if (mime.isValid()) {\n        if (mime.isDefault()) {\n            return QFileDialog::tr(\"All files (*)\");\n        } else {\n            const QString patterns = mime.globPatterns().join(u' ');\n            return mime.comment() + \" (\"_L1 + patterns + u')';\n        }\n    }\n    return QString();\n}\n\n/*!\n    \\since 5.2\n\n    Sets the \\a filters used in the file dialog, from a list of MIME types.\n\n    Convenience method for setNameFilters().\n    Uses QMimeType to create a name filter from the glob patterns and description\n    defined in each MIME type.\n\n    Use application/octet-stream for the \"All files (*)\" filter, since that\n    is the base MIME type for all files.\n\n    Calling setMimeTypeFilters overrides any previously set name filters,\n    and changes the return value of nameFilters().\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 13\n*/\nvoid QFileDialog::setMimeTypeFilters(const QStringList &filters)\n{\n    Q_D(QFileDialog);\n    QStringList nameFilters;\n    for (const QString &mimeType : filters) {\n        const QString text = nameFilterForMime(mimeType);\n        if (!text.isEmpty())\n            nameFilters.append(text);\n    }\n    setNameFilters(nameFilters);\n    d->options->setMimeTypeFilters(filters);\n}\n\n/*!\n    \\since 5.2\n\n    Returns the MIME type filters that are in operation on this file\n    dialog.\n*/\nQStringList QFileDialog::mimeTypeFilters() const\n{\n    return d_func()->options->mimeTypeFilters();\n}\n\n/*!\n    \\since 5.2\n\n    Sets the current MIME type \\a filter.\n\n*/\nvoid QFileDialog::selectMimeTypeFilter(const QString &filter)\n{\n    Q_D(QFileDialog);\n    d->options->setInitiallySelectedMimeTypeFilter(filter);\n\n    const QString filterForMime = nameFilterForMime(filter);\n\n    if (!d->usingWidgets()) {\n        d->selectMimeTypeFilter_sys(filter);\n        if (d->selectedMimeTypeFilter_sys().isEmpty() && !filterForMime.isEmpty()) {\n            selectNameFilter(filterForMime);\n        }\n    } else if (!filterForMime.isEmpty()) {\n        selectNameFilter(filterForMime);\n    }\n}\n\n#endif // mimetype\n\n/*!\n * \\since 5.9\n * \\return The mimetype of the file that the user selected in the file dialog.\n */\nQString QFileDialog::selectedMimeTypeFilter() const\n{\n    Q_D(const QFileDialog);\n    QString mimeTypeFilter;\n    if (!d->usingWidgets())\n        mimeTypeFilter = d->selectedMimeTypeFilter_sys();\n\n#if QT_CONFIG(mimetype)\n    if (mimeTypeFilter.isNull() && !d->options->mimeTypeFilters().isEmpty()) {\n        const auto nameFilter = selectedNameFilter();\n        const auto mimeTypes = d->options->mimeTypeFilters();\n        for (const auto &mimeType: mimeTypes) {\n            QString filter = nameFilterForMime(mimeType);\n            if (testOption(HideNameFilterDetails))\n                filter = qt_strip_filters({ filter }).constFirst();\n            if (filter == nameFilter) {\n                mimeTypeFilter = mimeType;\n                break;\n            }\n        }\n    }\n#endif\n\n    return mimeTypeFilter;\n}\n\n/*!\n    \\property QFileDialog::viewMode\n    \\brief The way files and directories are displayed in the dialog.\n\n    By default, the \\c Detail mode is used to display information about\n    files and directories.\n\n    \\sa ViewMode\n*/\nvoid QFileDialog::setViewMode(QFileDialog::ViewMode mode)\n{\n    Q_D(QFileDialog);\n    d->options->setViewMode(static_cast<QFileDialogOptions::ViewMode>(mode));\n    if (!d->usingWidgets())\n        return;\n    if (mode == Detail)\n        d->showDetailsView();\n    else\n        d->showListView();\n}\n\nQFileDialog::ViewMode QFileDialog::viewMode() const\n{\n    Q_D(const QFileDialog);\n    if (!d->usingWidgets())\n        return static_cast<QFileDialog::ViewMode>(d->options->viewMode());\n    return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);\n}\n\n/*!\n    \\property QFileDialog::fileMode\n    \\brief The file mode of the dialog.\n\n    The file mode defines the number and type of items that the user is\n    expected to select in the dialog.\n\n    By default, this property is set to AnyFile.\n\n    This function sets the labels for the FileName and\n    \\l{QFileDialog::}{Accept} \\l{DialogLabel}s. It is possible to set\n    custom text after the call to setFileMode().\n\n    \\sa FileMode\n*/\nvoid QFileDialog::setFileMode(QFileDialog::FileMode mode)\n{\n    Q_D(QFileDialog);\n    d->options->setFileMode(static_cast<QFileDialogOptions::FileMode>(mode));\n    if (!d->usingWidgets())\n        return;\n\n    d->retranslateWindowTitle();\n\n    // set selection mode and behavior\n    QAbstractItemView::SelectionMode selectionMode;\n    if (mode == QFileDialog::ExistingFiles)\n        selectionMode = QAbstractItemView::ExtendedSelection;\n    else\n        selectionMode = QAbstractItemView::SingleSelection;\n    d->qFileDialogUi->listView->setSelectionMode(selectionMode);\n    d->qFileDialogUi->treeView->setSelectionMode(selectionMode);\n    // set filter\n    d->model->setFilter(d->filterForMode(filter()));\n    // setup file type for directory\n    if (mode == Directory) {\n        d->qFileDialogUi->fileTypeCombo->clear();\n        d->qFileDialogUi->fileTypeCombo->addItem(tr(\"Directories\"));\n        d->qFileDialogUi->fileTypeCombo->setEnabled(false);\n    }\n    d->updateFileNameLabel();\n    d->updateOkButtonText();\n    d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));\n    d->updateOkButton();\n}\n\nQFileDialog::FileMode QFileDialog::fileMode() const\n{\n    Q_D(const QFileDialog);\n    return static_cast<FileMode>(d->options->fileMode());\n}\n\n/*!\n    \\property QFileDialog::acceptMode\n    \\brief The accept mode of the dialog.\n\n    The action mode defines whether the dialog is for opening or saving files.\n\n    By default, this property is set to \\l{AcceptOpen}.\n\n    \\sa AcceptMode\n*/\nvoid QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)\n{\n    Q_D(QFileDialog);\n    d->options->setAcceptMode(static_cast<QFileDialogOptions::AcceptMode>(mode));\n    // clear WA_DontShowOnScreen so that d->canBeNativeDialog() doesn't return false incorrectly\n    setAttribute(Qt::WA_DontShowOnScreen, false);\n    if (!d->usingWidgets())\n        return;\n    QDialogButtonBox::StandardButton button = (mode == AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);\n    d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);\n    d->qFileDialogUi->buttonBox->button(button)->setEnabled(false);\n    d->updateOkButton();\n    if (mode == AcceptSave) {\n        d->qFileDialogUi->lookInCombo->setEditable(false);\n    }\n    d->retranslateWindowTitle();\n}\n\n/*!\n    \\property QFileDialog::supportedSchemes\n    \\brief The URL schemes that the file dialog should allow navigating to.\n    \\since 5.6\n\n    Setting this property allows to restrict the type of URLs the\n    user can select. It is a way for the application to declare\n    the protocols it supports to fetch the file content. An empty list\n    means that no restriction is applied (the default).\n    Support for local files (\"file\" scheme) is implicit and always enabled;\n    it is not necessary to include it in the restriction.\n*/\n\nvoid QFileDialog::setSupportedSchemes(const QStringList &schemes)\n{\n    Q_D(QFileDialog);\n    d->options->setSupportedSchemes(schemes);\n}\n\nQStringList QFileDialog::supportedSchemes() const\n{\n    return d_func()->options->supportedSchemes();\n}\n\n/*\n    Returns the file system model index that is the root index in the\n    views\n*/\nQModelIndex QFileDialogPrivate::rootIndex() const {\n    return mapToSource(qFileDialogUi->listView->rootIndex());\n}\n\nQAbstractItemView *QFileDialogPrivate::currentView() const {\n    if (!qFileDialogUi->stackedWidget)\n        return nullptr;\n    if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())\n        return qFileDialogUi->listView;\n    return qFileDialogUi->treeView;\n}\n\nQLineEdit *QFileDialogPrivate::lineEdit() const {\n    return (QLineEdit*)qFileDialogUi->fileNameEdit;\n}\n\nlong QFileDialogPrivate::maxNameLength(const QString &path)\n{\n#if defined(Q_OS_UNIX)\n    return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);\n#elif defined(Q_OS_WIN)\n    DWORD maxLength;\n    const QString drive = path.left(3);\n    if (::GetVolumeInformation(reinterpret_cast<const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) == false)\n        return -1;\n    return maxLength;\n#else\n    Q_UNUSED(path);\n#endif\n    return -1;\n}\n\n/*\n    Sets the view root index to be the file system model index\n*/\nvoid QFileDialogPrivate::setRootIndex(const QModelIndex &index) const {\n    Q_ASSERT(index.isValid() ? index.model() == model : true);\n    QModelIndex idx = mapFromSource(index);\n    qFileDialogUi->treeView->setRootIndex(idx);\n    qFileDialogUi->listView->setRootIndex(idx);\n}\n/*\n    Select a file system model index\n    returns the index that was selected (or not depending upon sortfilterproxymodel)\n*/\nQModelIndex QFileDialogPrivate::select(const QModelIndex &index) const {\n    Q_ASSERT(index.isValid() ? index.model() == model : true);\n\n    QModelIndex idx = mapFromSource(index);\n    if (idx.isValid() && !qFileDialogUi->listView->selectionModel()->isSelected(idx))\n        qFileDialogUi->listView->selectionModel()->select(idx,\n            QItemSelectionModel::Select | QItemSelectionModel::Rows);\n    return idx;\n}\n\nQFileDialog::AcceptMode QFileDialog::acceptMode() const\n{\n    Q_D(const QFileDialog);\n    return static_cast<AcceptMode>(d->options->acceptMode());\n}\n\n/*!\n    \\property QFileDialog::defaultSuffix\n    \\brief Suffix added to the filename if no other suffix was specified.\n\n    This property specifies a string that is added to the\n    filename if it has no suffix yet. The suffix is typically\n    used to indicate the file type (e.g. \"txt\" indicates a text\n    file).\n\n    If the first character is a dot ('.'), it is removed.\n*/\nvoid QFileDialog::setDefaultSuffix(const QString &suffix)\n{\n    Q_D(QFileDialog);\n    d->options->setDefaultSuffix(suffix);\n}\n\nQString QFileDialog::defaultSuffix() const\n{\n    Q_D(const QFileDialog);\n    return d->options->defaultSuffix();\n}\n\n/*!\n    Sets the browsing history of the filedialog to contain the given\n    \\a paths.\n*/\nvoid QFileDialog::setHistory(const QStringList &paths)\n{\n    Q_D(QFileDialog);\n    if (d->usingWidgets())\n        d->qFileDialogUi->lookInCombo->setHistory(paths);\n}\n\nvoid QFileDialogComboBox::setHistory(const QStringList &paths)\n{\n    m_history = paths;\n    // Only populate the first item, showPopup will populate the rest if needed\n    QList<QUrl> list;\n    const QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());\n    //On windows the popup display the \"C:\\\", convert to nativeSeparators\n    const QUrl url = idx.isValid()\n                   ? QUrl::fromLocalFile(QDir::toNativeSeparators(idx.data(QFileSystemModel::FilePathRole).toString()))\n                   : QUrl(\"file:\"_L1);\n    if (url.isValid())\n        list.append(url);\n    urlModel->setUrls(list);\n}\n\n/*!\n    Returns the browsing history of the filedialog as a list of paths.\n*/\nQStringList QFileDialog::history() const\n{\n    Q_D(const QFileDialog);\n    if (!d->usingWidgets())\n        return QStringList();\n    QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();\n    //On windows the popup display the \"C:\\\", convert to nativeSeparators\n    QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());\n    if (!currentHistory.contains(newHistory))\n        currentHistory << newHistory;\n    return currentHistory;\n}\n\n/*!\n    Sets the item delegate used to render items in the views in the\n    file dialog to the given \\a delegate.\n\n    Any existing delegate will be removed, but not deleted. QFileDialog\n    does not take ownership of \\a delegate.\n\n    \\warning You should not share the same instance of a delegate between views.\n    Doing so can cause incorrect or unintuitive editing behavior since each\n    view connected to a given delegate may receive the \\l{QAbstractItemDelegate::}{closeEditor()}\n    signal, and attempt to access, modify or close an editor that has already been closed.\n\n    Note that the model used is QFileSystemModel. It has custom item data roles, which is\n    described by the \\l{QFileSystemModel::}{Roles} enum. You can use a QFileIconProvider if\n    you only want custom icons.\n\n    \\sa itemDelegate(), setIconProvider(), QFileSystemModel\n*/\nvoid QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)\n{\n    Q_D(QFileDialog);\n    if (!d->usingWidgets())\n        return;\n    d->qFileDialogUi->listView->setItemDelegate(delegate);\n    d->qFileDialogUi->treeView->setItemDelegate(delegate);\n}\n\n/*!\n  Returns the item delegate used to render the items in the views in the filedialog.\n*/\nQAbstractItemDelegate *QFileDialog::itemDelegate() const\n{\n    Q_D(const QFileDialog);\n    if (!d->usingWidgets())\n        return nullptr;\n    return d->qFileDialogUi->listView->itemDelegate();\n}\n\n/*!\n    Sets the icon provider used by the filedialog to the specified \\a provider.\n*/\nvoid QFileDialog::setIconProvider(QAbstractFileIconProvider *provider)\n{\n    Q_D(QFileDialog);\n    if (!d->usingWidgets())\n        return;\n    d->model->setIconProvider(provider);\n    //It forces the refresh of all entries in the side bar, then we can get new icons\n    d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls());\n}\n\n/*!\n    Returns the icon provider used by the filedialog.\n*/\nQAbstractFileIconProvider *QFileDialog::iconProvider() const\n{\n    Q_D(const QFileDialog);\n    if (!d->model)\n        return nullptr;\n    return d->model->iconProvider();\n}\n\nvoid QFileDialogPrivate::setLabelTextControl(QFileDialog::DialogLabel label, const QString &text)\n{\n    if (!qFileDialogUi)\n        return;\n    switch (label) {\n    case QFileDialog::LookIn:\n        qFileDialogUi->lookInLabel->setText(text);\n        break;\n    case QFileDialog::FileName:\n        qFileDialogUi->fileNameLabel->setText(text);\n        break;\n    case QFileDialog::FileType:\n        qFileDialogUi->fileTypeLabel->setText(text);\n        break;\n    case QFileDialog::Accept:\n        if (q_func()->acceptMode() == QFileDialog::AcceptOpen) {\n            if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Open))\n                button->setText(text);\n        } else {\n            if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Save))\n                button->setText(text);\n        }\n        break;\n    case QFileDialog::Reject:\n        if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel))\n            button->setText(text);\n        break;\n    }\n}\n\n/*!\n    Sets the \\a text shown in the filedialog in the specified \\a label.\n*/\n\nvoid QFileDialog::setLabelText(DialogLabel label, const QString &text)\n{\n    Q_D(QFileDialog);\n    d->options->setLabelText(static_cast<QFileDialogOptions::DialogLabel>(label), text);\n    d->setLabelTextControl(label, text);\n}\n\n/*!\n    Returns the text shown in the filedialog in the specified \\a label.\n*/\nQString QFileDialog::labelText(DialogLabel label) const\n{\n    Q_D(const QFileDialog);\n    if (!d->usingWidgets())\n        return d->options->labelText(static_cast<QFileDialogOptions::DialogLabel>(label));\n    QPushButton *button;\n    switch (label) {\n    case LookIn:\n        return d->qFileDialogUi->lookInLabel->text();\n    case FileName:\n        return d->qFileDialogUi->fileNameLabel->text();\n    case FileType:\n        return d->qFileDialogUi->fileTypeLabel->text();\n    case Accept:\n        if (acceptMode() == AcceptOpen)\n            button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);\n        else\n            button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);\n        if (button)\n            return button->text();\n        break;\n    case Reject:\n        button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);\n        if (button)\n            return button->text();\n        break;\n    }\n    return QString();\n}\n\n/*!\n    This is a convenience static function that returns an existing file\n    selected by the user. If the user presses Cancel, it returns a null string.\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 8\n\n    The function creates a modal file dialog with the given \\a parent widget.\n    If \\a parent is not \\nullptr, the dialog is shown centered over the\n    parent widget.\n\n    The file dialog's working directory is set to \\a dir. If \\a dir\n    includes a file name, the file is selected. Only files that match the\n    given \\a filter are shown. The selected filter is set to \\a selectedFilter.\n    The parameters \\a dir, \\a selectedFilter, and \\a filter may be empty\n    strings. If you want multiple filters, separate them with ';;', for\n    example:\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 14\n\n    The \\a options argument holds various options about how to run the dialog.\n    See the QFileDialog::Option enum for more information on the flags you can\n    pass.\n\n    The dialog's caption is set to \\a caption. If \\a caption is not specified,\n    then a default caption will be used.\n\n    On Windows, and \\macos, this static function uses the\n    native file dialog and not a QFileDialog. Note that the \\macos native file\n    dialog does not show a title bar.\n\n    On Windows the dialog spins a blocking modal event loop that does not\n    dispatch any QTimers, and if \\a parent is not \\nullptr then it positions\n    the dialog just below the parent's title bar.\n\n    On Unix/X11, the normal behavior of the file dialog is to resolve and\n    follow symlinks. For example, if \\c{/usr/tmp} is a symlink to \\c{/var/tmp},\n    the file dialog changes to \\c{/var/tmp} after entering \\c{/usr/tmp}. If\n    \\a options includes DontResolveSymlinks, the file dialog treats\n    symlinks as regular directories.\n\n    \\sa getOpenFileNames(), getSaveFileName(), getExistingDirectory()\n*/\nQString QFileDialog::getOpenFileName(QWidget *parent,\n                               const QString &caption,\n                               const QString &dir,\n                               const QString &filter,\n                               QString *selectedFilter,\n                               Options options)\n{\n    const QStringList schemes = QStringList(QStringLiteral(\"file\"));\n    const QUrl selectedUrl = getOpenFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,\n                                            selectedFilter, options, schemes);\n    if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())\n        return selectedUrl.toLocalFile();\n    else\n        return selectedUrl.toString();\n}\n\n/*!\n    This is a convenience static function that returns an existing file\n    selected by the user. If the user presses Cancel, it returns an\n    empty url.\n\n    The function is used similarly to QFileDialog::getOpenFileName(). In\n    particular \\a parent, \\a caption, \\a dir, \\a filter, \\a selectedFilter\n    and \\a options are used in exactly the same way.\n\n    The main difference with QFileDialog::getOpenFileName() comes from\n    the ability offered to the user to select a remote file. That's why\n    the return type and the type of \\a dir is QUrl.\n\n    The \\a supportedSchemes argument allows to restrict the type of URLs the\n    user is able to select. It is a way for the application to declare\n    the protocols it will support to fetch the file content. An empty list\n    means that no restriction is applied (the default).\n    Support for local files (\"file\" scheme) is implicit and always enabled;\n    it is not necessary to include it in the restriction.\n\n    When possible, this static function uses the native file dialog and\n    not a QFileDialog. On platforms that don't support selecting remote\n    files, Qt will allow to select only local files.\n\n    \\sa getOpenFileName(), getOpenFileUrls(), getSaveFileUrl(), getExistingDirectoryUrl()\n    \\since 5.2\n*/\nQUrl QFileDialog::getOpenFileUrl(QWidget *parent,\n                                 const QString &caption,\n                                 const QUrl &dir,\n                                 const QString &filter,\n                                 QString *selectedFilter,\n                                 Options options,\n                                 const QStringList &supportedSchemes)\n{\n    QFileDialogArgs args(dir);\n    args.parent = parent;\n    args.caption = caption;\n    args.filter = filter;\n    args.mode = ExistingFile;\n    args.options = options;\n\n    QAutoPointer<QFileDialog> dialog(new QFileDialog(args));\n    dialog->setSupportedSchemes(supportedSchemes);\n    if (selectedFilter && !selectedFilter->isEmpty())\n        dialog->selectNameFilter(*selectedFilter);\n    const int execResult = dialog->exec();\n    if (bool(dialog) && execResult == QDialog::Accepted) {\n        if (selectedFilter)\n            *selectedFilter = dialog->selectedNameFilter();\n        return dialog->selectedUrls().value(0);\n    }\n    return QUrl();\n}\n\n/*!\n    This is a convenience static function that returns one or more existing\n    files selected by the user.\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 9\n\n    This function creates a modal file dialog with the given \\a parent widget.\n    If \\a parent is not \\nullptr, the dialog is shown centered over the\n    parent widget.\n\n    The file dialog's working directory is set to \\a dir. If \\a dir\n    includes a file name, the file is selected. The filter is set to\n    \\a filter so that only those files which match the filter are shown. The\n    filter selected is set to \\a selectedFilter. The parameters \\a dir,\n    \\a selectedFilter and \\a filter can be empty strings. If you need multiple\n    filters, separate them with ';;', for instance:\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 14\n\n    The dialog's caption is set to \\a caption. If \\a caption is not specified,\n    then a default caption is used.\n\n    On Windows and \\macos, this static function uses the\n    native file dialog and not a QFileDialog. Note that the \\macos native file\n    dialog does not show a title bar.\n\n    On Windows the dialog spins a blocking modal event loop that does not\n    dispatch any QTimers, and if \\a parent is not \\nullptr then it positions\n    the dialog just below the parent's title bar.\n\n    On Unix/X11, the normal behavior of the file dialog is to resolve and\n    follow symlinks. For example, if \\c{/usr/tmp} is a symlink to \\c{/var/tmp},\n    the file dialog will change to \\c{/var/tmp} after entering \\c{/usr/tmp}.\n    The \\a options argument holds various options about how to run the dialog,\n    see the QFileDialog::Option enum for more information on the flags you can\n    pass.\n\n    \\sa getOpenFileName(), getSaveFileName(), getExistingDirectory()\n*/\nQStringList QFileDialog::getOpenFileNames(QWidget *parent,\n                                          const QString &caption,\n                                          const QString &dir,\n                                          const QString &filter,\n                                          QString *selectedFilter,\n                                          Options options)\n{\n    const QStringList schemes = QStringList(QStringLiteral(\"file\"));\n    const QList<QUrl> selectedUrls = getOpenFileUrls(parent, caption, QUrl::fromLocalFile(dir),\n                                                     filter, selectedFilter, options, schemes);\n    QStringList fileNames;\n    fileNames.reserve(selectedUrls.size());\n    for (const QUrl &url : selectedUrls)\n        fileNames.append(url.toString(QUrl::PreferLocalFile));\n    return fileNames;\n}\n\n/*!\n    This is a convenience static function that returns one or more existing\n    files selected by the user. If the user presses Cancel, it returns an\n    empty list.\n\n    The function is used similarly to QFileDialog::getOpenFileNames(). In\n    particular \\a parent, \\a caption, \\a dir, \\a filter, \\a selectedFilter\n    and \\a options are used in exactly the same way.\n\n    The main difference with QFileDialog::getOpenFileNames() comes from\n    the ability offered to the user to select remote files. That's why\n    the return type and the type of \\a dir are respectively QList<QUrl>\n    and QUrl.\n\n    The \\a supportedSchemes argument allows to restrict the type of URLs the\n    user can select. It is a way for the application to declare\n    the protocols it supports to fetch the file content. An empty list\n    means that no restriction is applied (the default).\n    Support for local files (\"file\" scheme) is implicit and always enabled;\n    it is not necessary to include it in the restriction.\n\n    When possible, this static function uses the native file dialog and\n    not a QFileDialog. On platforms that don't support selecting remote\n    files, Qt will allow to select only local files.\n\n    \\sa getOpenFileNames(), getOpenFileUrl(), getSaveFileUrl(), getExistingDirectoryUrl()\n    \\since 5.2\n*/\nQList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent,\n                                         const QString &caption,\n                                         const QUrl &dir,\n                                         const QString &filter,\n                                         QString *selectedFilter,\n                                         Options options,\n                                         const QStringList &supportedSchemes)\n{\n    QFileDialogArgs args(dir);\n    args.parent = parent;\n    args.caption = caption;\n    args.filter = filter;\n    args.mode = ExistingFiles;\n    args.options = options;\n\n    QAutoPointer<QFileDialog> dialog(new QFileDialog(args));\n    dialog->setSupportedSchemes(supportedSchemes);\n    if (selectedFilter && !selectedFilter->isEmpty())\n        dialog->selectNameFilter(*selectedFilter);\n    const int execResult = dialog->exec();\n    if (bool(dialog) && execResult == QDialog::Accepted) {\n        if (selectedFilter)\n            *selectedFilter = dialog->selectedNameFilter();\n        return dialog->selectedUrls();\n    }\n    return QList<QUrl>();\n}\n\n/*!\n    This is a convenience static function that returns the content of a file\n    selected by the user.\n\n    Use this function to access local files on Qt for WebAssembly, if the web sandbox\n    restricts file access. Its implementation enables displaying a native file dialog in\n    the browser, where the user selects a file based on the \\a nameFilter parameter.\n\n    \\a parent is ignored on Qt for WebAssembly. Pass \\a parent on other platforms, to make\n    the popup a child of another widget. If the platform doesn't support native file\n    dialogs, the function falls back to QFileDialog.\n\n    The function is asynchronous and returns immediately. The \\a fileOpenCompleted\n    callback will be called when a file has been selected and its contents have been\n    read into memory.\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 15\n    \\since 5.13\n*/\nvoid QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function<void(const QString &, const QByteArray &)> &fileOpenCompleted, QWidget *parent)\n{\n#ifdef Q_OS_WASM\n    Q_UNUSED(parent);\n    auto openFileImpl = std::make_shared<std::function<void(void)>>();\n    QString fileName;\n    QByteArray fileContent;\n    *openFileImpl = [=]() mutable {\n        auto fileDialogClosed = [&](bool fileSelected) {\n            if (!fileSelected) {\n                fileOpenCompleted(fileName, fileContent);\n                openFileImpl.reset();\n            }\n        };\n        auto acceptFile = [&](uint64_t size, const std::string name) -> char * {\n            const uint64_t twoGB = 1ULL << 31; // QByteArray limit\n            if (size > twoGB)\n                return nullptr;\n\n            fileName = QString::fromStdString(name);\n            fileContent.resize(size);\n            return fileContent.data();\n        };\n        auto fileContentReady = [&]() mutable {\n            fileOpenCompleted(fileName, fileContent);\n            openFileImpl.reset();\n        };\n\n        QWasmLocalFileAccess::openFile(nameFilter.toStdString(), fileDialogClosed, acceptFile, fileContentReady);\n    };\n\n    (*openFileImpl)();\n#else\n    QFileDialog *dialog = new QFileDialog(parent);\n    dialog->setFileMode(QFileDialog::ExistingFile);\n    dialog->setNameFilter(nameFilter);\n    dialog->setAttribute(Qt::WA_DeleteOnClose);\n\n    auto fileSelected = [=](const QString &fileName) {\n        QByteArray fileContent;\n        if (!fileName.isNull()) {\n            QFile selectedFile(fileName);\n            if (selectedFile.open(QIODevice::ReadOnly))\n                fileContent = selectedFile.readAll();\n        }\n        fileOpenCompleted(fileName, fileContent);\n    };\n\n    connect(dialog, &QFileDialog::fileSelected, dialog, fileSelected);\n    dialog->show();\n#endif\n}\n\n/*!\n    This is a convenience static function that saves \\a fileContent to a file, using\n    a file name and location chosen by the user. \\a fileNameHint can be provided to\n    suggest a file name to the user.\n\n    Use this function to save content to local files on Qt for WebAssembly, if the web sandbox\n    restricts file access. Its implementation enables displaying a native file dialog in the\n    browser, where the user specifies an output file based on the \\a fileNameHint argument.\n\n    \\a parent is ignored on Qt for WebAssembly. Pass \\a parent on other platforms, to make\n    the popup a child of another widget. If the platform doesn't support native file\n    dialogs, the function falls back to QFileDialog.\n\n    The function is asynchronous and returns immediately.\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 16\n    \\since 5.14\n*/\nvoid QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint, QWidget *parent)\n{\n#ifdef Q_OS_WASM\n    Q_UNUSED(parent);\n    QWasmLocalFileAccess::saveFile(fileContent, fileNameHint.toStdString());\n#else\n    QFileDialog *dialog = new QFileDialog(parent);\n    dialog->setAcceptMode(QFileDialog::AcceptSave);\n    dialog->setFileMode(QFileDialog::AnyFile);\n    dialog->selectFile(fileNameHint);\n\n    auto fileSelected = [=](const QString &fileName) {\n        if (!fileName.isNull()) {\n            QFile selectedFile(fileName);\n            if (selectedFile.open(QIODevice::WriteOnly))\n                selectedFile.write(fileContent);\n        }\n    };\n\n    connect(dialog, &QFileDialog::fileSelected, dialog, fileSelected);\n    dialog->setAttribute(Qt::WA_DeleteOnClose);\n    dialog->show();\n#endif\n}\n\n/*!\n    This is a convenience static function that returns a file name selected\n    by the user. The file does not have to exist.\n\n    It creates a modal file dialog with the given \\a parent widget. If\n    \\a parent is not \\nullptr, the dialog will be shown centered over the\n    parent widget.\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 11\n\n    The file dialog's working directory is set to \\a dir. If \\a dir\n    includes a file name, the file is selected. Only files that match the\n    \\a filter are shown. The filter selected is set to \\a selectedFilter. The\n    parameters \\a dir, \\a selectedFilter, and \\a filter may be empty strings.\n    Multiple filters are separated with ';;'. For instance:\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 14\n\n    The \\a options argument holds various options about how to run the dialog,\n    see the QFileDialog::Option enum for more information on the flags you can\n    pass.\n\n    The default filter can be chosen by setting \\a selectedFilter to the\n    desired value.\n\n    The dialog's caption is set to \\a caption. If \\a caption is not specified,\n    a default caption is used.\n\n    On Windows, and \\macos, this static function uses the\n    native file dialog and not a QFileDialog.\n\n    On Windows the dialog spins a blocking modal event loop that does not\n    dispatch any QTimers, and if \\a parent is not \\nullptr then it\n    positions the dialog just below the parent's title bar. On \\macos, with its\n    native file dialog, the filter argument is ignored.\n\n    On Unix/X11, the normal behavior of the file dialog is to resolve and\n    follow symlinks. For example, if \\c{/usr/tmp} is a symlink to \\c{/var/tmp},\n    the file dialog changes to \\c{/var/tmp} after entering \\c{/usr/tmp}. If\n    \\a options includes DontResolveSymlinks, the file dialog treats symlinks\n    as regular directories.\n\n    \\sa getOpenFileName(), getOpenFileNames(), getExistingDirectory()\n*/\nQString QFileDialog::getSaveFileName(QWidget *parent,\n                                     const QString &caption,\n                                     const QString &dir,\n                                     const QString &filter,\n                                     QString *selectedFilter,\n                                     Options options)\n{\n    const QStringList schemes = QStringList(QStringLiteral(\"file\"));\n    const QUrl selectedUrl = getSaveFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,\n                                            selectedFilter, options, schemes);\n    if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())\n        return selectedUrl.toLocalFile();\n    else\n        return selectedUrl.toString();\n}\n\n/*!\n    This is a convenience static function that returns a file selected by\n    the user. The file does not have to exist. If the user presses Cancel,\n    it returns an empty url.\n\n    The function is used similarly to QFileDialog::getSaveFileName(). In\n    particular \\a parent, \\a caption, \\a dir, \\a filter, \\a selectedFilter\n    and \\a options are used in exactly the same way.\n\n    The main difference with QFileDialog::getSaveFileName() comes from\n    the ability offered to the user to select a remote file. That's why\n    the return type and the type of \\a dir is QUrl.\n\n    The \\a supportedSchemes argument allows to restrict the type of URLs the\n    user can select. It is a way for the application to declare\n    the protocols it supports to save the file content. An empty list\n    means that no restriction is applied (the default).\n    Support for local files (\"file\" scheme) is implicit and always enabled;\n    it is not necessary to include it in the restriction.\n\n    When possible, this static function uses the native file dialog and\n    not a QFileDialog. On platforms that don't support selecting remote\n    files, Qt will allow to select only local files.\n\n    \\sa getSaveFileName(), getOpenFileUrl(), getOpenFileUrls(), getExistingDirectoryUrl()\n    \\since 5.2\n*/\nQUrl QFileDialog::getSaveFileUrl(QWidget *parent,\n                                 const QString &caption,\n                                 const QUrl &dir,\n                                 const QString &filter,\n                                 QString *selectedFilter,\n                                 Options options,\n                                 const QStringList &supportedSchemes)\n{\n    QFileDialogArgs args(dir);\n    args.parent = parent;\n    args.caption = caption;\n    args.filter = filter;\n    args.mode = AnyFile;\n    args.options = options;\n\n    QAutoPointer<QFileDialog> dialog(new QFileDialog(args));\n    dialog->setSupportedSchemes(supportedSchemes);\n    dialog->setAcceptMode(AcceptSave);\n    if (selectedFilter && !selectedFilter->isEmpty())\n        dialog->selectNameFilter(*selectedFilter);\n    const int execResult = dialog->exec();\n    if (bool(dialog) && execResult == QDialog::Accepted) {\n        if (selectedFilter)\n            *selectedFilter = dialog->selectedNameFilter();\n        return dialog->selectedUrls().value(0);\n    }\n    return QUrl();\n}\n\n/*!\n    This is a convenience static function that returns an existing\n    directory selected by the user.\n\n    \\snippet code/src_gui_dialogs_qfiledialog.cpp 12\n\n    This function creates a modal file dialog with the given \\a parent widget.\n    If \\a parent is not \\nullptr, the dialog is shown centered over the\n    parent widget.\n\n    The dialog's working directory is set to \\a dir, and the caption is set to\n    \\a caption. Either of these can be an empty string in which case the\n    current directory and a default caption are used respectively.\n\n    The \\a options argument holds various options about how to run the dialog.\n    See the QFileDialog::Option enum for more information on the flags you can\n    pass. To ensure a native file dialog, \\l{QFileDialog::}{ShowDirsOnly} must\n    be set.\n\n    On Windows and \\macos, this static function uses the\n    native file dialog and not a QFileDialog. However, the native Windows file\n    dialog does not support displaying files in the directory chooser. You need\n    to pass the \\l{QFileDialog::}{DontUseNativeDialog} option, or set the global\n    \\\\l{Qt::}{AA_DontUseNativeDialogs} application attribute to display files using a\n    QFileDialog.\n\n    Note that the \\macos native file dialog does not show a title bar.\n\n    On Unix/X11, the normal behavior of the file dialog is to resolve and\n    follow symlinks. For example, if \\c{/usr/tmp} is a symlink to \\c{/var/tmp},\n    the file dialog changes to \\c{/var/tmp} after entering \\c{/usr/tmp}. If\n    \\a options includes DontResolveSymlinks, the file dialog treats\n    symlinks as regular directories.\n\n    On Windows, the dialog spins a blocking modal event loop that does not\n    dispatch any QTimers, and if \\a parent is not \\nullptr then it positions\n    the dialog just below the parent's title bar.\n\n    \\sa getOpenFileName(), getOpenFileNames(), getSaveFileName()\n*/\nQString QFileDialog::getExistingDirectory(QWidget *parent,\n                                          const QString &caption,\n                                          const QString &dir,\n                                          Options options)\n{\n    const QStringList schemes = QStringList(QStringLiteral(\"file\"));\n    const QUrl selectedUrl =\n            getExistingDirectoryUrl(parent, caption, QUrl::fromLocalFile(dir), options, schemes);\n    if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())\n        return selectedUrl.toLocalFile();\n    else\n        return selectedUrl.toString();\n}\n\n/*!\n    This is a convenience static function that returns an existing\n    directory selected by the user. If the user presses Cancel, it\n    returns an empty url.\n\n    The function is used similarly to QFileDialog::getExistingDirectory().\n    In particular \\a parent, \\a caption, \\a dir and \\a options are used\n    in exactly the same way.\n\n    The main difference with QFileDialog::getExistingDirectory() comes from\n    the ability offered to the user to select a remote directory. That's why\n    the return type and the type of \\a dir is QUrl.\n\n    The \\a supportedSchemes argument allows to restrict the type of URLs the\n    user is able to select. It is a way for the application to declare\n    the protocols it supports to fetch the file content. An empty list\n    means that no restriction is applied (the default).\n    Support for local files (\"file\" scheme) is implicit and always enabled;\n    it is not necessary to include it in the restriction.\n\n    When possible, this static function uses the native file dialog and\n    not a QFileDialog. On platforms that don't support selecting remote\n    files, Qt allows to select only local files.\n\n    \\sa getExistingDirectory(), getOpenFileUrl(), getOpenFileUrls(), getSaveFileUrl()\n    \\since 5.2\n*/\nQUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent,\n                                          const QString &caption,\n                                          const QUrl &dir,\n                                          Options options,\n                                          const QStringList &supportedSchemes)\n{\n    QFileDialogArgs args(dir);\n    args.parent = parent;\n    args.caption = caption;\n    args.mode = Directory;\n    args.options = options;\n\n    QAutoPointer<QFileDialog> dialog(new QFileDialog(args));\n    dialog->setSupportedSchemes(supportedSchemes);\n    const int execResult = dialog->exec();\n    if (bool(dialog) && execResult == QDialog::Accepted)\n        return dialog->selectedUrls().value(0);\n    return QUrl();\n}\n\ninline static QUrl _qt_get_directory(const QUrl &url, const QFileInfo &local)\n{\n    if (url.isLocalFile()) {\n        QFileInfo info = local;\n        if (!local.isAbsolute())\n            info = QFileInfo(QDir::current(), url.toLocalFile());\n        const QFileInfo pathInfo(info.absolutePath());\n        if (!pathInfo.exists() || !pathInfo.isDir())\n            return QUrl();\n        if (info.exists() && info.isDir())\n            return QUrl::fromLocalFile(QDir::cleanPath(info.absoluteFilePath()));\n        return QUrl::fromLocalFile(pathInfo.absoluteFilePath());\n    } else {\n        return url;\n    }\n}\n\ninline static void _qt_init_lastVisited() {\n#if QT_CONFIG(settings)\n    if (lastVisitedDir()->isEmpty()) {\n        QSettings settings(QSettings::UserScope, u\"QtProject\"_s);\n        const QString &lastVisisted = settings.value(\"FileDialog/lastVisited\", QString()).toString();\n        *lastVisitedDir() = QUrl::fromLocalFile(lastVisisted);\n    }\n#endif\n}\n\n/*\n    Initialize working directory and selection from \\a url.\n*/\nQFileDialogArgs::QFileDialogArgs(const QUrl &url)\n{\n    // default case, re-use QFileInfo to avoid stat'ing\n    const QFileInfo local(url.toLocalFile());\n    // Get the initial directory URL\n    if (!url.isEmpty())\n        directory = _qt_get_directory(url, local);\n    if (directory.isEmpty()) {\n        _qt_init_lastVisited();\n        const QUrl lastVisited = *lastVisitedDir();\n        if (lastVisited != url)\n            directory = _qt_get_directory(lastVisited, QFileInfo());\n    }\n    if (directory.isEmpty())\n        directory = QUrl::fromLocalFile(QDir::currentPath());\n\n    /*\n    The initial directory can contain both the initial directory\n    and initial selection, e.g. /home/user/foo.txt\n    */\n    if (selection.isEmpty() && !url.isEmpty()) {\n        if (url.isLocalFile()) {\n            if (!local.isDir())\n                selection = local.fileName();\n        } else {\n            // With remote URLs we can only assume.\n            selection = url.fileName();\n        }\n    }\n}\n\n/*!\n \\reimp\n*/\nvoid QFileDialog::done(int result)\n{\n    Q_D(QFileDialog);\n\n    QDialog::done(result);\n\n    if (d->receiverToDisconnectOnClose) {\n        disconnect(this, d->signalToDisconnectOnClose,\n                   d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);\n        d->receiverToDisconnectOnClose = nullptr;\n    }\n    d->memberToDisconnectOnClose.clear();\n    d->signalToDisconnectOnClose.clear();\n}\n\nbool QFileDialogPrivate::itemAlreadyExists(const QString &fileName)\n{\n#if QT_CONFIG(messagebox)\n    Q_Q(QFileDialog);\n    const QString msg = QFileDialog::tr(\"%1 already exists.\\nDo you want to replace it?\").arg(fileName);\n    using B = QMessageBox;\n    const auto res = B::warning(q, q->windowTitle(), msg, B::Yes | B::No, B::No);\n    return res == B::Yes;\n#endif\n    return false;\n}\n\nvoid QFileDialogPrivate::itemNotFound(const QString &fileName, QFileDialog::FileMode mode)\n{\n#if QT_CONFIG(messagebox)\n    Q_Q(QFileDialog);\n    const QString message = mode == QFileDialog::Directory\n            ? QFileDialog::tr(\"%1\\nDirectory not found.\\n\"\n                              \"Please verify the correct directory name was given.\")\n            : QFileDialog::tr(\"%1\\nFile not found.\\nPlease verify the \"\n                              \"correct file name was given.\");\n\n    QMessageBox::warning(q, q->windowTitle(), message.arg(fileName));\n#endif // QT_CONFIG(messagebox)\n}\n\n/*!\n \\reimp\n*/\nvoid QFileDialog::accept()\n{\n    Q_D(QFileDialog);\n    if (!d->usingWidgets()) {\n        const QList<QUrl> urls = selectedUrls();\n        if (urls.isEmpty())\n            return;\n        d->emitUrlsSelected(urls);\n        if (urls.size() == 1)\n            d->emitUrlSelected(urls.first());\n        QDialog::accept();\n        return;\n    }\n\n    const QStringList files = selectedFiles();\n    if (files.isEmpty())\n        return;\n    QString lineEditText = d->lineEdit()->text();\n    // \"hidden feature\" type .. and then enter, and it will move up a dir\n    // special case for \"..\"\n    if (lineEditText == \"..\"_L1) {\n        d->navigateToParent();\n        const QSignalBlocker blocker(d->qFileDialogUi->fileNameEdit);\n        d->lineEdit()->selectAll();\n        return;\n    }\n\n    const auto mode = fileMode();\n    switch (mode) {\n    case Directory: {\n        QString fn = files.first();\n        QFileInfo info(fn);\n        if (!info.exists())\n            info = QFileInfo(d->getEnvironmentVariable(fn));\n        if (!info.exists()) {\n            d->itemNotFound(info.fileName(), mode);\n            return;\n        }\n        if (info.isDir()) {\n            d->emitFilesSelected(files);\n            QDialog::accept();\n        }\n        return;\n    }\n\n    case AnyFile: {\n        QString fn = files.first();\n        QFileInfo info(fn);\n        if (info.isDir()) {\n            setDirectory(info.absoluteFilePath());\n            return;\n        }\n\n        if (!info.exists()) {\n            const long maxNameLength = d->maxNameLength(info.path());\n            if (maxNameLength >= 0 && info.fileName().size() > maxNameLength)\n                return;\n        }\n\n        // check if we have to ask for permission to overwrite the file\n        if (!info.exists() || testOption(DontConfirmOverwrite) || acceptMode() == AcceptOpen) {\n            d->emitFilesSelected(QStringList(fn));\n            QDialog::accept();\n        } else {\n            if (d->itemAlreadyExists(info.fileName())) {\n                d->emitFilesSelected(QStringList(fn));\n                QDialog::accept();\n            }\n        }\n        return;\n    }\n\n    case ExistingFile:\n    case ExistingFiles:\n        for (const auto &file : files) {\n            QFileInfo info(file);\n            if (!info.exists())\n                info = QFileInfo(d->getEnvironmentVariable(file));\n            if (!info.exists()) {\n                d->itemNotFound(info.fileName(), mode);\n                return;\n            }\n            if (info.isDir()) {\n                setDirectory(info.absoluteFilePath());\n                d->lineEdit()->clear();\n                return;\n            }\n        }\n        d->emitFilesSelected(files);\n        QDialog::accept();\n        return;\n    }\n}\n\n#if QT_CONFIG(settings)\nvoid QFileDialogPrivate::saveSettings()\n{\n    Q_Q(QFileDialog);\n    QSettings settings(QSettings::UserScope, u\"QtProject\"_s);\n    settings.beginGroup(\"FileDialog\");\n\n    if (usingWidgets()) {\n        settings.setValue(\"sidebarWidth\", qFileDialogUi->splitter->sizes().constFirst());\n        settings.setValue(\"shortcuts\", QUrl::toStringList(qFileDialogUi->sidebar->urls()));\n        settings.setValue(\"treeViewHeader\", qFileDialogUi->treeView->header()->saveState());\n    }\n    QStringList historyUrls;\n    const QStringList history = q->history();\n    historyUrls.reserve(history.size());\n    for (const QString &path : history)\n        historyUrls << QUrl::fromLocalFile(path).toString();\n    settings.setValue(\"history\", historyUrls);\n    settings.setValue(\"lastVisited\", lastVisitedDir()->toString());\n    const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator(\"ViewMode\"));\n    settings.setValue(\"viewMode\", QLatin1StringView(viewModeMeta.key(q->viewMode())));\n    settings.setValue(\"qtVersion\", QT_VERSION_STR \"\"_L1);\n}\n\nbool QFileDialogPrivate::restoreFromSettings()\n{\n    Q_Q(QFileDialog);\n    QSettings settings(QSettings::UserScope, u\"QtProject\"_s);\n    if (!settings.childGroups().contains(\"FileDialog\"_L1))\n        return false;\n    settings.beginGroup(\"FileDialog\");\n\n    q->setDirectoryUrl(lastVisitedDir()->isEmpty() ? settings.value(\"lastVisited\").toUrl() : *lastVisitedDir());\n\n    QByteArray viewModeStr = settings.value(\"viewMode\").toString().toLatin1();\n    const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator(\"ViewMode\"));\n    bool ok = false;\n    int viewMode = viewModeMeta.keyToValue(viewModeStr.constData(), &ok);\n    if (!ok)\n        viewMode = QFileDialog::List;\n    q->setViewMode(static_cast<QFileDialog::ViewMode>(viewMode));\n\n    sidebarUrls = QUrl::fromStringList(settings.value(\"shortcuts\").toStringList());\n    headerData = settings.value(\"treeViewHeader\").toByteArray();\n\n    if (!usingWidgets())\n        return true;\n\n    QStringList history;\n    const auto urlStrings = settings.value(\"history\").toStringList();\n    for (const QString &urlStr : urlStrings) {\n        QUrl url(urlStr);\n        if (url.isLocalFile())\n            history << url.toLocalFile();\n    }\n\n    return restoreWidgetState(history, settings.value(\"sidebarWidth\", -1).toInt());\n}\n#endif // settings\n\nbool QFileDialogPrivate::restoreWidgetState(QStringList &history, int splitterPosition)\n{\n    Q_Q(QFileDialog);\n    if (splitterPosition >= 0) {\n        QList<int> splitterSizes;\n        splitterSizes.append(splitterPosition);\n        splitterSizes.append(qFileDialogUi->splitter->widget(1)->sizeHint().width());\n        qFileDialogUi->splitter->setSizes(splitterSizes);\n    } else {\n        if (!qFileDialogUi->splitter->restoreState(splitterState))\n            return false;\n        QList<int> list = qFileDialogUi->splitter->sizes();\n        if (list.size() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) {\n            for (int i = 0; i < list.size(); ++i)\n                list[i] = qFileDialogUi->splitter->widget(i)->sizeHint().width();\n            qFileDialogUi->splitter->setSizes(list);\n        }\n    }\n\n    qFileDialogUi->sidebar->setUrls(sidebarUrls);\n\n    static const int MaxHistorySize = 5;\n    if (history.size() > MaxHistorySize)\n        history.erase(history.begin(), history.end() - MaxHistorySize);\n    q->setHistory(history);\n\n    QHeaderView *headerView = qFileDialogUi->treeView->header();\n    if (!headerView->restoreState(headerData))\n        return false;\n\n    QList<QAction*> actions = headerView->actions();\n    QAbstractItemModel *abstractModel = model;\n#if QT_CONFIG(proxymodel)\n    if (proxyModel)\n        abstractModel = proxyModel;\n#endif\n    const int total = qMin(abstractModel->columnCount(QModelIndex()), int(actions.size() + 1));\n    for (int i = 1; i < total; ++i)\n        actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));\n\n    return true;\n}\n\n/*!\n    \\internal\n\n    Create widgets, layout and set default values\n*/\nvoid QFileDialogPrivate::init(const QFileDialogArgs &args)\n{\n    Q_Q(QFileDialog);\n    if (!args.caption.isEmpty()) {\n        useDefaultCaption = false;\n        setWindowTitle = args.caption;\n        q->setWindowTitle(args.caption);\n    }\n\n    q->setAcceptMode(QFileDialog::AcceptOpen);\n    nativeDialogInUse = platformFileDialogHelper() != nullptr;\n    if (!nativeDialogInUse)\n        createWidgets();\n    q->setFileMode(QFileDialog::AnyFile);\n    if (!args.filter.isEmpty())\n        q->setNameFilter(args.filter);\n    q->setDirectoryUrl(args.directory);\n    if (args.directory.isLocalFile())\n        q->selectFile(args.selection);\n    else\n        q->selectUrl(args.directory);\n\n#if QT_CONFIG(settings)\n    // Try to restore from the FileDialog settings group; if it fails, fall back\n    // to the pre-5.5 QByteArray serialized settings.\n    if (!restoreFromSettings()) {\n        const QSettings settings(QSettings::UserScope, u\"QtProject\"_s);\n        q->restoreState(settings.value(\"Qt/filedialog\").toByteArray());\n    }\n#endif\n\n#if defined(Q_EMBEDDED_SMALLSCREEN)\n    qFileDialogUi->lookInLabel->setVisible(false);\n    qFileDialogUi->fileNameLabel->setVisible(false);\n    qFileDialogUi->fileTypeLabel->setVisible(false);\n    qFileDialogUi->sidebar->hide();\n#endif\n\n    const QSize sizeHint = q->sizeHint();\n    if (sizeHint.isValid())\n       q->resize(sizeHint);\n}\n\n/*!\n    \\internal\n\n    Create the widgets, set properties and connections\n*/\nvoid QFileDialogPrivate::createWidgets()\n{\n    if (qFileDialogUi)\n        return;\n    Q_Q(QFileDialog);\n\n    // This function is sometimes called late (e.g as a fallback from setVisible). In that case we\n    // need to ensure that the following UI code (setupUI in particular) doesn't reset any explicitly\n    // set window state or geometry.\n    QSize preSize = q->testAttribute(Qt::WA_Resized) ? q->size() : QSize();\n    Qt::WindowStates preState = q->windowState();\n\n    model = new QFileSystemModel(q);\n    model->setIconProvider(&defaultIconProvider);\n    model->setFilter(options->filter());\n    model->setObjectName(\"qt_filesystem_model\"_L1);\n    if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())\n        model->setNameFilterDisables(helper->defaultNameFilterDisables());\n    else\n        model->setNameFilterDisables(false);\n    model->d_func()->disableRecursiveSort = true;\n    QObjectPrivate::connect(model, &QFileSystemModel::fileRenamed,\n                            this, &QFileDialogPrivate::fileRenamed);\n    QObjectPrivate::connect(model, &QFileSystemModel::rootPathChanged,\n                            this, &QFileDialogPrivate::pathChanged);\n    QObjectPrivate::connect(model, &QFileSystemModel::rowsInserted,\n                            this, &QFileDialogPrivate::rowsInserted);\n    model->setReadOnly(false);\n\n    qFileDialogUi.reset(new Ui_QFileDialog());\n    qFileDialogUi->setupUi(q);\n\n    QList<QUrl> initialBookmarks;\n    initialBookmarks << QUrl(\"file:\"_L1)\n                     << QUrl::fromLocalFile(QDir::homePath());\n    qFileDialogUi->sidebar->setModelAndUrls(model, initialBookmarks);\n    QObjectPrivate::connect(qFileDialogUi->sidebar, &QSidebar::goToUrl,\n                            this, &QFileDialogPrivate::goToUrl);\n\n    QObject::connect(qFileDialogUi->buttonBox, &QDialogButtonBox::accepted,\n                     q, &QFileDialog::accept);\n    QObject::connect(qFileDialogUi->buttonBox, &QDialogButtonBox::rejected,\n                     q, &QFileDialog::reject);\n\n    qFileDialogUi->lookInCombo->setFileDialogPrivate(this);\n    QObjectPrivate::connect(qFileDialogUi->lookInCombo, &QComboBox::textActivated,\n                            this, &QFileDialogPrivate::goToDirectory);\n\n    qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);\n    qFileDialogUi->lookInCombo->setDuplicatesEnabled(false);\n\n    // filename\n    qFileDialogUi->fileNameEdit->setFileDialogPrivate(this);\n#ifndef QT_NO_SHORTCUT\n    qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);\n#endif\n#if QT_CONFIG(fscompleter)\n    completer = new QFSCompleter(model, q);\n    qFileDialogUi->fileNameEdit->setCompleter(completer);\n#endif // QT_CONFIG(fscompleter)\n\n    qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText);\n\n    QObjectPrivate::connect(qFileDialogUi->fileNameEdit, &QLineEdit::textChanged,\n                            this, &QFileDialogPrivate::autoCompleteFileName);\n    QObjectPrivate::connect(qFileDialogUi->fileNameEdit, &QLineEdit::textChanged,\n                            this, &QFileDialogPrivate::updateOkButton);\n    QObject::connect(qFileDialogUi->fileNameEdit, &QLineEdit::returnPressed,\n                     q, &QFileDialog::accept);\n\n    // filetype\n    qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(false);\n    qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);\n    qFileDialogUi->fileTypeCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);\n    QObjectPrivate::connect(qFileDialogUi->fileTypeCombo, &QComboBox::activated,\n                            this, &QFileDialogPrivate::useNameFilter);\n    QObject::connect(qFileDialogUi->fileTypeCombo, &QComboBox::textActivated,\n                     q, &QFileDialog::filterSelected);\n\n    qFileDialogUi->listView->setFileDialogPrivate(this);\n    qFileDialogUi->listView->setModel(model);\n    QObjectPrivate::connect(qFileDialogUi->listView, &QAbstractItemView::activated,\n                            this, &QFileDialogPrivate::enterDirectory);\n    QObjectPrivate::connect(qFileDialogUi->listView, &QAbstractItemView::customContextMenuRequested,\n                            this, &QFileDialogPrivate::showContextMenu);\n#ifndef QT_NO_SHORTCUT\n    QShortcut *shortcut = new QShortcut(QKeySequence::Delete, qFileDialogUi->listView);\n    QObjectPrivate::connect(shortcut, &QShortcut::activated,\n                            this, &QFileDialogPrivate::deleteCurrent);\n#endif\n\n    qFileDialogUi->treeView->setFileDialogPrivate(this);\n    qFileDialogUi->treeView->setModel(model);\n    QHeaderView *treeHeader = qFileDialogUi->treeView->header();\n    QFontMetrics fm(q->font());\n    treeHeader->resizeSection(0, fm.horizontalAdvance(\"wwwwwwwwwwwwwwwwwwwwwwwwww\"_L1));\n    treeHeader->resizeSection(1, fm.horizontalAdvance(\"128.88 GB\"_L1));\n    treeHeader->resizeSection(2, fm.horizontalAdvance(\"mp3Folder\"_L1));\n    treeHeader->resizeSection(3, fm.horizontalAdvance(\"10/29/81 02:02PM\"_L1));\n    treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);\n\n    QActionGroup *showActionGroup = new QActionGroup(q);\n    showActionGroup->setExclusive(false);\n    QObjectPrivate::connect(showActionGroup, &QActionGroup::triggered,\n                            this, &QFileDialogPrivate::showHeader);\n\n    QAbstractItemModel *abstractModel = model;\n#if QT_CONFIG(proxymodel)\n    if (proxyModel)\n        abstractModel = proxyModel;\n#endif\n    for (int i = 1; i < abstractModel->columnCount(QModelIndex()); ++i) {\n        QAction *showHeader = new QAction(showActionGroup);\n        showHeader->setCheckable(true);\n        showHeader->setChecked(true);\n        treeHeader->addAction(showHeader);\n    }\n\n    QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());\n    qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());\n\n    QObjectPrivate::connect(qFileDialogUi->treeView, &QAbstractItemView::activated,\n                            this, &QFileDialogPrivate::enterDirectory);\n    QObjectPrivate::connect(qFileDialogUi->treeView, &QAbstractItemView::customContextMenuRequested,\n                            this, &QFileDialogPrivate::showContextMenu);\n#ifndef QT_NO_SHORTCUT\n    shortcut = new QShortcut(QKeySequence::Delete, qFileDialogUi->treeView);\n    QObjectPrivate::connect(shortcut, &QShortcut::activated,\n                            this, &QFileDialogPrivate::deleteCurrent);\n#endif\n\n    // Selections\n    QItemSelectionModel *selections = qFileDialogUi->listView->selectionModel();\n    QObjectPrivate::connect(selections, &QItemSelectionModel::selectionChanged,\n                            this, &QFileDialogPrivate::selectionChanged);\n    QObjectPrivate::connect(selections, &QItemSelectionModel::currentChanged,\n                            this, &QFileDialogPrivate::currentChanged);\n    qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);\n\n    createToolButtons();\n    createMenuActions();\n\n#if QT_CONFIG(settings)\n    // Try to restore from the FileDialog settings group; if it fails, fall back\n    // to the pre-5.5 QByteArray serialized settings.\n    if (!restoreFromSettings()) {\n        const QSettings settings(QSettings::UserScope, u\"QtProject\"_s);\n        q->restoreState(settings.value(\"Qt/filedialog\").toByteArray());\n    }\n#endif\n\n    // Initial widget states from options\n    q->setFileMode(static_cast<QFileDialog::FileMode>(options->fileMode()));\n    q->setAcceptMode(static_cast<QFileDialog::AcceptMode>(options->acceptMode()));\n    q->setViewMode(static_cast<QFileDialog::ViewMode>(options->viewMode()));\n    q->setOptions(static_cast<QFileDialog::Options>(static_cast<int>(options->options())));\n    if (!options->sidebarUrls().isEmpty())\n        q->setSidebarUrls(options->sidebarUrls());\n    q->setDirectoryUrl(options->initialDirectory());\n#if QT_CONFIG(mimetype)\n    if (!options->mimeTypeFilters().isEmpty())\n        q->setMimeTypeFilters(options->mimeTypeFilters());\n    else\n#endif\n    if (!options->nameFilters().isEmpty())\n        q->setNameFilters(options->nameFilters());\n    q->selectNameFilter(options->initiallySelectedNameFilter());\n    q->setDefaultSuffix(options->defaultSuffix());\n    q->setHistory(options->history());\n    const auto initiallySelectedFiles = options->initiallySelectedFiles();\n    if (initiallySelectedFiles.size() == 1)\n        q->selectFile(initiallySelectedFiles.first().fileName());\n    for (const QUrl &url : initiallySelectedFiles)\n        q->selectUrl(url);\n    lineEdit()->selectAll();\n    updateOkButton();\n    retranslateStrings();\n    q->resize(preSize.isValid() ? preSize : q->sizeHint());\n    q->setWindowState(preState);\n}\n\nvoid QFileDialogPrivate::showHeader(QAction *action)\n{\n    Q_Q(QFileDialog);\n    QActionGroup *actionGroup = qobject_cast<QActionGroup*>(q->sender());\n    qFileDialogUi->treeView->header()->setSectionHidden(int(actionGroup->actions().indexOf(action) + 1),\n                                                        !action->isChecked());\n}\n\n#if QT_CONFIG(proxymodel)\n/*!\n    Sets the model for the views to the given \\a proxyModel.  This is useful if you\n    want to modify the underlying model; for example, to add columns, filter\n    data or add drives.\n\n    Any existing proxy model is removed, but not deleted.  The file dialog\n    takes ownership of the \\a proxyModel.\n\n    \\sa proxyModel()\n*/\nvoid QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)\n{\n    Q_D(QFileDialog);\n    if (!d->usingWidgets())\n        return;\n    if ((!proxyModel && !d->proxyModel)\n        || (proxyModel == d->proxyModel))\n        return;\n\n    QModelIndex idx = d->rootIndex();\n    if (d->proxyModel)\n        QObjectPrivate::disconnect(d->proxyModel, &QAbstractProxyModel::rowsInserted,\n                                   d, &QFileDialogPrivate::rowsInserted);\n    else\n        QObjectPrivate::disconnect(d->model, &QAbstractItemModel::rowsInserted,\n                                   d, &QFileDialogPrivate::rowsInserted);\n\n    if (proxyModel != nullptr) {\n        proxyModel->setParent(this);\n        d->proxyModel = proxyModel;\n        proxyModel->setSourceModel(d->model);\n        d->qFileDialogUi->listView->setModel(d->proxyModel);\n        d->qFileDialogUi->treeView->setModel(d->proxyModel);\n#if QT_CONFIG(fscompleter)\n        d->completer->setModel(d->proxyModel);\n        d->completer->proxyModel = d->proxyModel;\n#endif\n        QObjectPrivate::connect(d->proxyModel, &QAbstractItemModel::rowsInserted,\n                                d, &QFileDialogPrivate::rowsInserted);\n    } else {\n        d->proxyModel = nullptr;\n        d->qFileDialogUi->listView->setModel(d->model);\n        d->qFileDialogUi->treeView->setModel(d->model);\n#if QT_CONFIG(fscompleter)\n        d->completer->setModel(d->model);\n        d->completer->sourceModel = d->model;\n        d->completer->proxyModel = nullptr;\n#endif\n        QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsInserted,\n                                d, &QFileDialogPrivate::rowsInserted);\n    }\n    QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());\n    d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());\n\n    d->setRootIndex(idx);\n\n    // reconnect selection\n    QItemSelectionModel *selections = d->qFileDialogUi->listView->selectionModel();\n    QObjectPrivate::connect(selections, &QItemSelectionModel::selectionChanged,\n                            d, &QFileDialogPrivate::selectionChanged);\n    QObjectPrivate::connect(selections, &QItemSelectionModel::currentChanged,\n                            d, &QFileDialogPrivate::currentChanged);\n}\n\n/*!\n    Returns the proxy model used by the file dialog.  By default no proxy is set.\n\n    \\sa setProxyModel()\n*/\nQAbstractProxyModel *QFileDialog::proxyModel() const\n{\n    Q_D(const QFileDialog);\n    return d->proxyModel;\n}\n#endif // QT_CONFIG(proxymodel)\n\n/*!\n    \\internal\n\n    Create tool buttons, set properties and connections\n*/\nvoid QFileDialogPrivate::createToolButtons()\n{\n    Q_Q(QFileDialog);\n    qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack, nullptr, q));\n    qFileDialogUi->backButton->setAutoRaise(true);\n    qFileDialogUi->backButton->setEnabled(false);\n    QObjectPrivate::connect(qFileDialogUi->backButton, &QPushButton::clicked,\n                            this, &QFileDialogPrivate::navigateBackward);\n\n    qFileDialogUi->forwardButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward, nullptr, q));\n    qFileDialogUi->forwardButton->setAutoRaise(true);\n    qFileDialogUi->forwardButton->setEnabled(false);\n    QObjectPrivate::connect(qFileDialogUi->forwardButton, &QPushButton::clicked,\n                            this, &QFileDialogPrivate::navigateForward);\n\n    qFileDialogUi->toParentButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent, nullptr, q));\n    qFileDialogUi->toParentButton->setAutoRaise(true);\n    qFileDialogUi->toParentButton->setEnabled(false);\n    QObjectPrivate::connect(qFileDialogUi->toParentButton, &QPushButton::clicked,\n                            this, &QFileDialogPrivate::navigateToParent);\n\n    qFileDialogUi->listModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView, nullptr, q));\n    qFileDialogUi->listModeButton->setAutoRaise(true);\n    qFileDialogUi->listModeButton->setDown(true);\n    QObjectPrivate::connect(qFileDialogUi->listModeButton, &QPushButton::clicked,\n                            this, &QFileDialogPrivate::showListView);\n\n    qFileDialogUi->detailModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView, nullptr, q));\n    qFileDialogUi->detailModeButton->setAutoRaise(true);\n    QObjectPrivate::connect(qFileDialogUi->detailModeButton, &QPushButton::clicked,\n                            this, &QFileDialogPrivate::showDetailsView);\n\n    QSize toolSize(qFileDialogUi->fileNameEdit->sizeHint().height(), qFileDialogUi->fileNameEdit->sizeHint().height());\n    qFileDialogUi->backButton->setFixedSize(toolSize);\n    qFileDialogUi->listModeButton->setFixedSize(toolSize);\n    qFileDialogUi->detailModeButton->setFixedSize(toolSize);\n    qFileDialogUi->forwardButton->setFixedSize(toolSize);\n    qFileDialogUi->toParentButton->setFixedSize(toolSize);\n\n    qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder, nullptr, q));\n    qFileDialogUi->newFolderButton->setFixedSize(toolSize);\n    qFileDialogUi->newFolderButton->setAutoRaise(true);\n    qFileDialogUi->newFolderButton->setEnabled(false);\n    QObjectPrivate::connect(qFileDialogUi->newFolderButton, &QPushButton::clicked,\n                            this, &QFileDialogPrivate::createDirectory);\n}\n\n/*!\n    \\internal\n\n    Create actions which will be used in the right click.\n*/\nvoid QFileDialogPrivate::createMenuActions()\n{\n    Q_Q(QFileDialog);\n\n    QAction *goHomeAction =  new QAction(q);\n#ifndef QT_NO_SHORTCUT\n    goHomeAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_H);\n#endif\n    QObjectPrivate::connect(goHomeAction, &QAction::triggered,\n                            this, &QFileDialogPrivate::goHome);\n    q->addAction(goHomeAction);\n\n    // ### TODO add Desktop & Computer actions\n\n    QAction *goToParent =  new QAction(q);\n    goToParent->setObjectName(\"qt_goto_parent_action\"_L1);\n#ifndef QT_NO_SHORTCUT\n    goToParent->setShortcut(Qt::CTRL | Qt::Key_Up);\n#endif\n    QObjectPrivate::connect(goToParent, &QAction::triggered,\n                            this, &QFileDialogPrivate::navigateToParent);\n    q->addAction(goToParent);\n\n    renameAction = new QAction(q);\n    renameAction->setEnabled(false);\n    renameAction->setObjectName(\"qt_rename_action\"_L1);\n    QObjectPrivate::connect(renameAction, &QAction::triggered,\n                            this, &QFileDialogPrivate::renameCurrent);\n\n    deleteAction = new QAction(q);\n    deleteAction->setEnabled(false);\n    deleteAction->setObjectName(\"qt_delete_action\"_L1);\n    QObjectPrivate::connect(deleteAction, &QAction::triggered,\n                            this, &QFileDialogPrivate::deleteCurrent);\n\n    showHiddenAction = new QAction(q);\n    showHiddenAction->setObjectName(\"qt_show_hidden_action\"_L1);\n    showHiddenAction->setCheckable(true);\n    QObjectPrivate::connect(showHiddenAction, &QAction::triggered,\n                            this, &QFileDialogPrivate::showHidden);\n\n    newFolderAction = new QAction(q);\n    newFolderAction->setObjectName(\"qt_new_folder_action\"_L1);\n    QObjectPrivate::connect(newFolderAction, &QAction::triggered,\n                            this, &QFileDialogPrivate::createDirectory);\n}\n\nvoid QFileDialogPrivate::goHome()\n{\n    Q_Q(QFileDialog);\n    q->setDirectory(QDir::homePath());\n}\n\n\nvoid QFileDialogPrivate::saveHistorySelection()\n{\n    if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size())\n        return;\n    auto &item = currentHistory[currentHistoryLocation];\n    item.selection.clear();\n    const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows();\n    for (const auto &index : selectedIndexes)\n        item.selection.append(QPersistentModelIndex(index));\n}\n\n/*!\n    \\internal\n\n    Update history with new path, buttons, and combo\n*/\nvoid QFileDialogPrivate::pathChanged(const QString &newPath)\n{\n    Q_Q(QFileDialog);\n    qFileDialogUi->toParentButton->setEnabled(QFileInfo::exists(model->rootPath()));\n    qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));\n    q->setHistory(qFileDialogUi->lookInCombo->history());\n\n    const QString newNativePath = QDir::toNativeSeparators(newPath);\n\n    // equal paths indicate this was invoked by _q_navigateBack/Forward()\n    if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) {\n        if (currentHistoryLocation >= 0)\n            saveHistorySelection();\n        while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.size()) {\n            currentHistory.removeLast();\n        }\n        currentHistory.append({newNativePath, PersistentModelIndexList()});\n        ++currentHistoryLocation;\n    }\n    qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);\n    qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);\n}\n\nvoid QFileDialogPrivate::navigate(HistoryItem &historyItem)\n{\n    Q_Q(QFileDialog);\n    q->setDirectory(historyItem.path);\n    // Restore selection unless something has changed in the file system\n    if (qFileDialogUi.isNull() || historyItem.selection.isEmpty())\n        return;\n    if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(),\n                    [](const QPersistentModelIndex &i) { return !i.isValid(); })) {\n        historyItem.selection.clear();\n        return;\n    }\n\n    QAbstractItemView *view = q->viewMode() == QFileDialog::List\n        ? static_cast<QAbstractItemView *>(qFileDialogUi->listView)\n        : static_cast<QAbstractItemView *>(qFileDialogUi->treeView);\n    auto selectionModel = view->selectionModel();\n    const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select\n        | QItemSelectionModel::Rows;\n    selectionModel->select(historyItem.selection.constFirst(),\n                           flags | QItemSelectionModel::Clear | QItemSelectionModel::Current);\n    auto it = historyItem.selection.cbegin() + 1;\n    const auto end = historyItem.selection.cend();\n    for (; it != end; ++it)\n        selectionModel->select(*it, flags);\n\n    view->scrollTo(historyItem.selection.constFirst());\n}\n\n/*!\n    \\internal\n\n    Navigates to the last directory viewed in the dialog.\n*/\nvoid QFileDialogPrivate::navigateBackward()\n{\n    if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {\n        saveHistorySelection();\n        navigate(currentHistory[--currentHistoryLocation]);\n    }\n}\n\n/*!\n    \\internal\n\n    Navigates to the last directory viewed in the dialog.\n*/\nvoid QFileDialogPrivate::navigateForward()\n{\n    if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {\n        saveHistorySelection();\n        navigate(currentHistory[++currentHistoryLocation]);\n    }\n}\n\n/*!\n    \\internal\n\n    Navigates to the parent directory of the currently displayed directory\n    in the dialog.\n*/\nvoid QFileDialogPrivate::navigateToParent()\n{\n    Q_Q(QFileDialog);\n    QDir dir(model->rootDirectory());\n    QString newDirectory;\n    if (dir.isRoot()) {\n        newDirectory = model->myComputer().toString();\n    } else {\n        dir.cdUp();\n        newDirectory = dir.absolutePath();\n    }\n    q->setDirectory(newDirectory);\n    emit q->directoryEntered(newDirectory);\n}\n\n/*!\n    \\internal\n\n    Creates a new directory, first asking the user for a suitable name.\n*/\nvoid QFileDialogPrivate::createDirectory()\n{\n    Q_Q(QFileDialog);\n    qFileDialogUi->listView->clearSelection();\n\n    QString newFolderString = QFileDialog::tr(\"New Folder\");\n    QString folderName = newFolderString;\n    QString prefix = q->directory().absolutePath() + QDir::separator();\n    if (QFile::exists(prefix + folderName)) {\n        qlonglong suffix = 2;\n        while (QFile::exists(prefix + folderName)) {\n            folderName = newFolderString + QString::number(suffix++);\n        }\n    }\n\n    QModelIndex parent = rootIndex();\n    QModelIndex index = model->mkdir(parent, folderName);\n    if (!index.isValid())\n        return;\n\n    index = select(index);\n    if (index.isValid()) {\n        qFileDialogUi->treeView->setCurrentIndex(index);\n        currentView()->edit(index);\n    }\n}\n\nvoid QFileDialogPrivate::showListView()\n{\n    qFileDialogUi->listModeButton->setDown(true);\n    qFileDialogUi->detailModeButton->setDown(false);\n    qFileDialogUi->treeView->hide();\n    qFileDialogUi->listView->show();\n    qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->listView->parentWidget());\n    qFileDialogUi->listView->doItemsLayout();\n}\n\nvoid QFileDialogPrivate::showDetailsView()\n{\n    qFileDialogUi->listModeButton->setDown(false);\n    qFileDialogUi->detailModeButton->setDown(true);\n    qFileDialogUi->listView->hide();\n    qFileDialogUi->treeView->show();\n    qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->treeView->parentWidget());\n    qFileDialogUi->treeView->doItemsLayout();\n}\n\n/*!\n    \\internal\n\n    Show the context menu for the file/dir under position\n*/\nvoid QFileDialogPrivate::showContextMenu(const QPoint &position)\n{\n#if !QT_CONFIG(menu)\n    Q_UNUSED(position);\n#else\n    Q_Q(QFileDialog);\n    QAbstractItemView *view = nullptr;\n    if (q->viewMode() == QFileDialog::Detail)\n        view = qFileDialogUi->treeView;\n    else\n        view = qFileDialogUi->listView;\n    QModelIndex index = view->indexAt(position);\n    index = mapToSource(index.sibling(index.row(), 0));\n\n    QMenu *menu = new QMenu(view);\n    menu->setAttribute(Qt::WA_DeleteOnClose);\n\n    if (index.isValid()) {\n        // file context menu\n        const bool ro = model && model->isReadOnly();\n        QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());\n        renameAction->setEnabled(!ro && p & QFile::WriteUser);\n        menu->addAction(renameAction);\n        deleteAction->setEnabled(!ro && p & QFile::WriteUser);\n        menu->addAction(deleteAction);\n        menu->addSeparator();\n    }\n    menu->addAction(showHiddenAction);\n    if (qFileDialogUi->newFolderButton->isVisible()) {\n        newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());\n        menu->addAction(newFolderAction);\n    }\n    menu->popup(view->viewport()->mapToGlobal(position));\n\n#endif // QT_CONFIG(menu)\n}\n\n/*!\n    \\internal\n*/\nvoid QFileDialogPrivate::renameCurrent()\n{\n    Q_Q(QFileDialog);\n    QModelIndex index = qFileDialogUi->listView->currentIndex();\n    index = index.sibling(index.row(), 0);\n    if (q->viewMode() == QFileDialog::List)\n        qFileDialogUi->listView->edit(index);\n    else\n        qFileDialogUi->treeView->edit(index);\n}\n\nbool QFileDialogPrivate::removeDirectory(const QString &path)\n{\n    QModelIndex modelIndex = model->index(path);\n    return model->remove(modelIndex);\n}\n\n/*!\n    \\internal\n\n    Deletes the currently selected item in the dialog.\n*/\nvoid QFileDialogPrivate::deleteCurrent()\n{\n    if (model->isReadOnly())\n        return;\n\n    const QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();\n    for (auto it = list.crbegin(), end = list.crend(); it != end; ++it) {\n        QPersistentModelIndex index = *it;\n        if (index == qFileDialogUi->listView->rootIndex())\n            continue;\n\n        index = mapToSource(index.sibling(index.row(), 0));\n        if (!index.isValid())\n            continue;\n\n        QString fileName = index.data(QFileSystemModel::FileNameRole).toString();\n        QString filePath = index.data(QFileSystemModel::FilePathRole).toString();\n\n        QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());\n#if QT_CONFIG(messagebox)\n        Q_Q(QFileDialog);\n        if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), QFileDialog::tr(\"Delete\"),\n                                    QFileDialog::tr(\"'%1' is write protected.\\nDo you want to delete it anyway?\")\n                                    .arg(fileName),\n                                     QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No))\n            return;\n        else if (QMessageBox::warning(q_func(), QFileDialog::tr(\"Delete\"),\n                                      QFileDialog::tr(\"Are you sure you want to delete '%1'?\")\n                                      .arg(fileName),\n                                      QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)\n            return;\n\n        // the event loop has run, we have to validate if the index is valid because the model might have removed it.\n        if (!index.isValid())\n            return;\n\n#else\n        if (!(p & QFile::WriteUser))\n            return;\n#endif // QT_CONFIG(messagebox)\n\n        if (model->isDir(index) && !model->fileInfo(index).isSymLink()) {\n            if (!removeDirectory(filePath)) {\n#if QT_CONFIG(messagebox)\n            QMessageBox::warning(q, q->windowTitle(),\n                                QFileDialog::tr(\"Could not delete directory.\"));\n#endif\n            }\n        } else {\n            model->remove(index);\n        }\n    }\n}\n\nvoid QFileDialogPrivate::autoCompleteFileName(const QString &text)\n{\n    if (text.startsWith(\"//\"_L1) || text.startsWith(u'\\\\')) {\n        qFileDialogUi->listView->selectionModel()->clearSelection();\n        return;\n    }\n\n    const QStringList multipleFiles = typedFiles();\n    if (multipleFiles.size() > 0) {\n        QModelIndexList oldFiles = qFileDialogUi->listView->selectionModel()->selectedRows();\n        QList<QModelIndex> newFiles;\n        for (const auto &file : multipleFiles) {\n            QModelIndex idx = model->index(file);\n            if (oldFiles.removeAll(idx) == 0)\n                newFiles.append(idx);\n        }\n        for (const auto &newFile : std::as_const(newFiles))\n            select(newFile);\n        if (lineEdit()->hasFocus()) {\n            auto *sm = qFileDialogUi->listView->selectionModel();\n            for (const auto &oldFile : std::as_const(oldFiles))\n                sm->select(oldFile, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);\n        }\n    }\n}\n\n/*!\n    \\internal\n*/\nvoid QFileDialogPrivate::updateOkButton()\n{\n    Q_Q(QFileDialog);\n    QPushButton *button =  qFileDialogUi->buttonBox->button((q->acceptMode() == QFileDialog::AcceptOpen)\n                    ? QDialogButtonBox::Open : QDialogButtonBox::Save);\n    if (!button)\n        return;\n    const QFileDialog::FileMode fileMode = q->fileMode();\n\n    bool enableButton = true;\n    bool isOpenDirectory = false;\n\n    const QStringList files = q->selectedFiles();\n    QString lineEditText = lineEdit()->text();\n\n    if (lineEditText.startsWith(\"//\"_L1) || lineEditText.startsWith(u'\\\\')) {\n        button->setEnabled(true);\n        updateOkButtonText();\n        return;\n    }\n\n    if (files.isEmpty()) {\n        enableButton = false;\n    } else if (lineEditText == \"..\"_L1) {\n        isOpenDirectory = true;\n    } else {\n        switch (fileMode) {\n        case QFileDialog::Directory: {\n            QString fn = files.first();\n            QModelIndex idx = model->index(fn);\n            if (!idx.isValid())\n                idx = model->index(getEnvironmentVariable(fn));\n            if (!idx.isValid() || !model->isDir(idx))\n                enableButton = false;\n            break;\n        }\n        case QFileDialog::AnyFile: {\n            QString fn = files.first();\n            QFileInfo info(fn);\n            QModelIndex idx = model->index(fn);\n            QString fileDir;\n            QString fileName;\n            if (info.isDir()) {\n                fileDir = info.canonicalFilePath();\n            } else {\n                fileDir = fn.mid(0, fn.lastIndexOf(u'/'));\n                fileName = fn.mid(fileDir.size() + 1);\n            }\n            if (lineEditText.contains(\"..\"_L1)) {\n                fileDir = info.canonicalFilePath();\n                fileName = info.fileName();\n            }\n\n            if (fileDir == q->directory().canonicalPath() && fileName.isEmpty()) {\n                enableButton = false;\n                break;\n            }\n            if (idx.isValid() && model->isDir(idx)) {\n                isOpenDirectory = true;\n                enableButton = true;\n                break;\n            }\n            if (!idx.isValid()) {\n                const long maxLength = maxNameLength(fileDir);\n                enableButton = maxLength < 0 || fileName.size() <= maxLength;\n            }\n            break;\n        }\n        case QFileDialog::ExistingFile:\n        case QFileDialog::ExistingFiles:\n            for (const auto &file : files) {\n                QModelIndex idx = model->index(file);\n                if (!idx.isValid())\n                    idx = model->index(getEnvironmentVariable(file));\n                if (!idx.isValid()) {\n                    enableButton = false;\n                    break;\n                }\n                if (idx.isValid() && model->isDir(idx)) {\n                    isOpenDirectory = true;\n                    break;\n                }\n            }\n            break;\n        default:\n            break;\n        }\n    }\n\n    button->setEnabled(enableButton);\n    updateOkButtonText(isOpenDirectory);\n}\n\n/*!\n    \\internal\n*/\nvoid QFileDialogPrivate::currentChanged(const QModelIndex &index)\n{\n    updateOkButton();\n    emit q_func()->currentChanged(index.data(QFileSystemModel::FilePathRole).toString());\n}\n\n/*!\n    \\internal\n\n    This is called when the user double clicks on a file with the corresponding\n    model item \\a index.\n*/\nvoid QFileDialogPrivate::enterDirectory(const QModelIndex &index)\n{\n    Q_Q(QFileDialog);\n    // My Computer or a directory\n    QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index;\n    QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString();\n    if (path.isEmpty() || model->isDir(sourceIndex)) {\n        const QFileDialog::FileMode fileMode = q->fileMode();\n        q->setDirectory(path);\n        emit q->directoryEntered(path);\n        if (fileMode == QFileDialog::Directory) {\n            // ### find out why you have to do both of these.\n            lineEdit()->setText(QString());\n            lineEdit()->clear();\n        }\n    } else {\n        // Do not accept when shift-clicking to multi-select a file in environments with single-click-activation (KDE)\n        if ((!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, nullptr, qFileDialogUi->treeView)\n             || q->fileMode() != QFileDialog::ExistingFiles || !(QGuiApplication::keyboardModifiers() & Qt::CTRL))\n            && index.model()->flags(index) & Qt::ItemIsEnabled) {\n            q->accept();\n        }\n    }\n}\n\n/*!\n    \\internal\n\n    Changes the file dialog's current directory to the one specified\n    by \\a path.\n*/\nvoid QFileDialogPrivate::goToDirectory(const QString &path)\n{\n    enum { UrlRole = Qt::UserRole + 1 };\n\n #if QT_CONFIG(messagebox)\n    Q_Q(QFileDialog);\n#endif\n    QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),\n                                                    qFileDialogUi->lookInCombo->modelColumn(),\n                                                    qFileDialogUi->lookInCombo->rootModelIndex());\n    QString path2 = path;\n    if (!index.isValid())\n        index = mapFromSource(model->index(getEnvironmentVariable(path)));\n    else {\n        path2 = index.data(UrlRole).toUrl().toLocalFile();\n        index = mapFromSource(model->index(path2));\n    }\n    QDir dir(path2);\n    if (!dir.exists())\n        dir.setPath(getEnvironmentVariable(path2));\n\n    if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {\n        enterDirectory(index);\n#if QT_CONFIG(messagebox)\n    } else {\n        QString message = QFileDialog::tr(\"%1\\nDirectory not found.\\nPlease verify the \"\n                                          \"correct directory name was given.\");\n        QMessageBox::warning(q, q->windowTitle(), message.arg(path2));\n#endif // QT_CONFIG(messagebox)\n    }\n}\n\n/*!\n    \\internal\n\n    Sets the current name filter to be nameFilter and\n    update the qFileDialogUi->fileNameEdit when in AcceptSave mode with the new extension.\n*/\nvoid QFileDialogPrivate::useNameFilter(int index)\n{\n    QStringList nameFilters = options->nameFilters();\n    if (index == nameFilters.size()) {\n        QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();\n        nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());\n        options->setNameFilters(nameFilters);\n    }\n\n    QString nameFilter = nameFilters.at(index);\n    QStringList newNameFilters = QPlatformFileDialogHelper::cleanFilterList(nameFilter);\n    if (q_func()->acceptMode() == QFileDialog::AcceptSave) {\n        QString newNameFilterExtension;\n        if (newNameFilters.size() > 0)\n            newNameFilterExtension = QFileInfo(newNameFilters.at(0)).suffix();\n\n        QString fileName = lineEdit()->text();\n        const QString fileNameExtension = QFileInfo(fileName).suffix();\n        if (!fileNameExtension.isEmpty() && !newNameFilterExtension.isEmpty()) {\n            const qsizetype fileNameExtensionLength = fileNameExtension.size();\n            fileName.replace(fileName.size() - fileNameExtensionLength,\n                             fileNameExtensionLength, newNameFilterExtension);\n            qFileDialogUi->listView->clearSelection();\n            lineEdit()->setText(fileName);\n        }\n    }\n\n    model->setNameFilters(newNameFilters);\n}\n\n/*!\n    \\internal\n\n    This is called when the model index corresponding to the current file is changed\n    from \\a index to \\a current.\n*/\nvoid QFileDialogPrivate::selectionChanged()\n{\n    const QFileDialog::FileMode fileMode = q_func()->fileMode();\n    const QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();\n    bool stripDirs = fileMode != QFileDialog::Directory;\n\n    QStringList allFiles;\n    for (const auto &index : indexes) {\n        if (stripDirs && model->isDir(mapToSource(index)))\n            continue;\n        allFiles.append(index.data().toString());\n    }\n    if (allFiles.size() > 1)\n        for (qsizetype i = 0; i < allFiles.size(); ++i) {\n            allFiles.replace(i, QString(u'\"' + allFiles.at(i) + u'\"'));\n    }\n\n    QString finalFiles = allFiles.join(u' ');\n    if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())\n        lineEdit()->setText(finalFiles);\n    else\n        updateOkButton();\n}\n\n/*!\n    \\internal\n\n    Includes hidden files and directories in the items displayed in the dialog.\n*/\nvoid QFileDialogPrivate::showHidden()\n{\n    Q_Q(QFileDialog);\n    QDir::Filters dirFilters = q->filter();\n    dirFilters.setFlag(QDir::Hidden, showHiddenAction->isChecked());\n    q->setFilter(dirFilters);\n}\n\n/*!\n    \\internal\n\n    When parent is root and rows have been inserted when none was there before\n    then select the first one.\n*/\nvoid QFileDialogPrivate::rowsInserted(const QModelIndex &parent)\n{\n    if (!qFileDialogUi->treeView\n        || parent != qFileDialogUi->treeView->rootIndex()\n        || !qFileDialogUi->treeView->selectionModel()\n        || qFileDialogUi->treeView->selectionModel()->hasSelection()\n        || qFileDialogUi->treeView->model()->rowCount(parent) == 0)\n        return;\n}\n\nvoid QFileDialogPrivate::fileRenamed(const QString &path, const QString &oldName, const QString &newName)\n{\n    const QFileDialog::FileMode fileMode = q_func()->fileMode();\n    if (fileMode == QFileDialog::Directory) {\n        if (path == rootPath() && lineEdit()->text() == oldName)\n            lineEdit()->setText(newName);\n    }\n}\n\nvoid QFileDialogPrivate::emitUrlSelected(const QUrl &file)\n{\n    Q_Q(QFileDialog);\n    emit q->urlSelected(file);\n    if (file.isLocalFile())\n        emit q->fileSelected(file.toLocalFile());\n}\n\nvoid QFileDialogPrivate::emitUrlsSelected(const QList<QUrl> &files)\n{\n    Q_Q(QFileDialog);\n    emit q->urlsSelected(files);\n    QStringList localFiles;\n    for (const QUrl &file : files)\n        if (file.isLocalFile())\n            localFiles.append(file.toLocalFile());\n    if (!localFiles.isEmpty())\n        emit q->filesSelected(localFiles);\n}\n\nvoid QFileDialogPrivate::nativeCurrentChanged(const QUrl &file)\n{\n    Q_Q(QFileDialog);\n    emit q->currentUrlChanged(file);\n    if (file.isLocalFile())\n        emit q->currentChanged(file.toLocalFile());\n}\n\nvoid QFileDialogPrivate::nativeEnterDirectory(const QUrl &directory)\n{\n    Q_Q(QFileDialog);\n    emit q->directoryUrlEntered(directory);\n    if (!directory.isEmpty()) { // Windows native dialogs occasionally emit signals with empty strings.\n        *lastVisitedDir() = directory;\n        if (directory.isLocalFile())\n            emit q->directoryEntered(directory.toLocalFile());\n    }\n}\n\n/*!\n    \\internal\n\n    For the list and tree view watch keys to goto parent and back in the history\n\n    returns \\c true if handled\n*/\nbool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {\n\n#if QT_CONFIG(shortcut)\n    Q_Q(QFileDialog);\n    if (event->matches(QKeySequence::Cancel)) {\n        q->reject();\n        return true;\n    }\n#endif\n    switch (event->key()) {\n    case Qt::Key_Backspace:\n        navigateToParent();\n        return true;\n    case Qt::Key_Back:\n#ifdef QT_KEYPAD_NAVIGATION\n        if (QApplicationPrivate::keypadNavigationEnabled())\n            return false;\n#endif\n    case Qt::Key_Left:\n        if (event->key() == Qt::Key_Back || event->modifiers() == Qt::AltModifier) {\n            navigateBackward();\n            return true;\n        }\n        break;\n    default:\n        break;\n    }\n    return false;\n}\n\nQString QFileDialogPrivate::getEnvironmentVariable(const QString &string)\n{\n#ifdef Q_OS_UNIX\n    if (string.size() > 1 && string.startsWith(u'$')) {\n        return qEnvironmentVariable(QStringView{string}.mid(1).toLatin1().constData());\n    }\n#else\n    if (string.size() > 2 && string.startsWith(u'%') && string.endsWith(u'%')) {\n        return qEnvironmentVariable(QStringView{string}.mid(1, string.size() - 2).toLatin1().constData());\n    }\n#endif\n    return string;\n}\n\nvoid QFileDialogComboBox::setFileDialogPrivate(QFileDialogPrivate *d_pointer) {\n    d_ptr = d_pointer;\n    urlModel = new QUrlModel(this);\n    urlModel->showFullPath = true;\n    urlModel->setFileSystemModel(d_ptr->model);\n    setModel(urlModel);\n}\n\nvoid QFileDialogComboBox::showPopup()\n{\n    if (model()->rowCount() > 1)\n        QComboBox::showPopup();\n\n    urlModel->setUrls(QList<QUrl>());\n    QList<QUrl> list;\n    QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());\n    while (idx.isValid()) {\n        QUrl url = QUrl::fromLocalFile(idx.data(QFileSystemModel::FilePathRole).toString());\n        if (url.isValid())\n            list.append(url);\n        idx = idx.parent();\n    }\n    // add \"my computer\"\n    list.append(QUrl(\"file:\"_L1));\n    urlModel->addUrls(list, 0);\n    idx = model()->index(model()->rowCount() - 1, 0);\n\n    // append history\n    QList<QUrl> urls;\n    for (int i = 0; i < m_history.size(); ++i) {\n        QUrl path = QUrl::fromLocalFile(m_history.at(i));\n        if (!urls.contains(path))\n            urls.prepend(path);\n    }\n    if (urls.size() > 0) {\n        model()->insertRow(model()->rowCount());\n        idx = model()->index(model()->rowCount()-1, 0);\n        // ### TODO maybe add a horizontal line before this\n        model()->setData(idx, QFileDialog::tr(\"Recent Places\"));\n        QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());\n        if (m) {\n            Qt::ItemFlags flags = m->flags(idx);\n            flags &= ~Qt::ItemIsEnabled;\n            m->item(idx.row(), idx.column())->setFlags(flags);\n        }\n        urlModel->addUrls(urls, -1, false);\n    }\n    setCurrentIndex(0);\n\n    QComboBox::showPopup();\n}\n\n// Exact same as QComboBox::paintEvent(), except we elide the text.\nvoid QFileDialogComboBox::paintEvent(QPaintEvent *)\n{\n    QStylePainter painter(this);\n    painter.setPen(palette().color(QPalette::Text));\n\n    // draw the combobox frame, focusrect and selected etc.\n    QStyleOptionComboBox opt;\n    initStyleOption(&opt);\n\n    QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,\n                                                QStyle::SC_ComboBoxEditField, this);\n    int size = editRect.width() - opt.iconSize.width() - 4;\n    opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);\n    painter.drawComplexControl(QStyle::CC_ComboBox, opt);\n\n    // draw the icon and text\n    painter.drawControl(QStyle::CE_ComboBoxLabel, opt);\n}\n\nvoid QFileDialogListView::setFileDialogPrivate(QFileDialogPrivate *d_pointer)\n{\n    d_ptr = d_pointer;\n    setSelectionBehavior(QAbstractItemView::SelectRows);\n    setWrapping(true);\n    setResizeMode(QListView::Adjust);\n    setEditTriggers(QAbstractItemView::EditKeyPressed);\n    setContextMenuPolicy(Qt::CustomContextMenu);\n#if QT_CONFIG(draganddrop)\n    setDragDropMode(QAbstractItemView::InternalMove);\n#endif\n}\n\nQSize QFileDialogListView::sizeHint() const\n{\n    int height = qMax(10, sizeHintForRow(0));\n    return QSize(QListView::sizeHint().width() * 2, height * 30);\n}\n\nvoid QFileDialogListView::keyPressEvent(QKeyEvent *e)\n{\n#ifdef QT_KEYPAD_NAVIGATION\n    if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {\n        QListView::keyPressEvent(e);\n        return;\n    }\n#endif // QT_KEYPAD_NAVIGATION\n\n    if (!d_ptr->itemViewKeyboardEvent(e))\n        QListView::keyPressEvent(e);\n    e->accept();\n}\n\nvoid QFileDialogTreeView::setFileDialogPrivate(QFileDialogPrivate *d_pointer)\n{\n    d_ptr = d_pointer;\n    setSelectionBehavior(QAbstractItemView::SelectRows);\n    setRootIsDecorated(false);\n    setItemsExpandable(false);\n    setSortingEnabled(true);\n    header()->setSortIndicator(0, Qt::AscendingOrder);\n    header()->setStretchLastSection(false);\n    setTextElideMode(Qt::ElideMiddle);\n    setEditTriggers(QAbstractItemView::EditKeyPressed);\n    setContextMenuPolicy(Qt::CustomContextMenu);\n#if QT_CONFIG(draganddrop)\n    setDragDropMode(QAbstractItemView::InternalMove);\n#endif\n}\n\nvoid QFileDialogTreeView::keyPressEvent(QKeyEvent *e)\n{\n#ifdef QT_KEYPAD_NAVIGATION\n    if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {\n        QTreeView::keyPressEvent(e);\n        return;\n    }\n#endif // QT_KEYPAD_NAVIGATION\n\n    if (!d_ptr->itemViewKeyboardEvent(e))\n        QTreeView::keyPressEvent(e);\n    e->accept();\n}\n\nQSize QFileDialogTreeView::sizeHint() const\n{\n    int height = qMax(10, sizeHintForRow(0));\n    QSize sizeHint = header()->sizeHint();\n    return QSize(sizeHint.width() * 4, height * 30);\n}\n\n/*!\n    // FIXME: this is a hack to avoid propagating key press events\n    // to the dialog and from there to the \"Ok\" button\n*/\nvoid QFileDialogLineEdit::keyPressEvent(QKeyEvent *e)\n{\n#ifdef QT_KEYPAD_NAVIGATION\n    if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {\n        QLineEdit::keyPressEvent(e);\n        return;\n    }\n#endif // QT_KEYPAD_NAVIGATION\n\n#if QT_CONFIG(shortcut)\n    int key = e->key();\n#endif\n    QLineEdit::keyPressEvent(e);\n#if QT_CONFIG(shortcut)\n    if (!e->matches(QKeySequence::Cancel) && key != Qt::Key_Back)\n#endif\n        e->accept();\n}\n\n#if QT_CONFIG(fscompleter)\n\nQString QFSCompleter::pathFromIndex(const QModelIndex &index) const\n{\n    const QFileSystemModel *dirModel;\n    if (proxyModel)\n        dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());\n    else\n        dirModel = sourceModel;\n    QString currentLocation = dirModel->rootPath();\n    QString path = index.data(QFileSystemModel::FilePathRole).toString();\n    if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {\n#if defined(Q_OS_UNIX)\n        if (currentLocation == QDir::separator())\n            return path.remove(0, currentLocation.size());\n#endif\n        if (currentLocation.endsWith(u'/'))\n            return path.remove(0, currentLocation.size());\n        else\n            return path.remove(0, currentLocation.size()+1);\n    }\n    return index.data(QFileSystemModel::FilePathRole).toString();\n}\n\nQStringList QFSCompleter::splitPath(const QString &path) const\n{\n    if (path.isEmpty())\n        return QStringList(completionPrefix());\n\n    QString pathCopy = QDir::toNativeSeparators(path);\n    QChar sep = QDir::separator();\n#if defined(Q_OS_WIN)\n    if (pathCopy == \"\\\\\"_L1 || pathCopy == \"\\\\\\\\\"_L1)\n        return QStringList(pathCopy);\n    QString doubleSlash(\"\\\\\\\\\"_L1);\n    if (pathCopy.startsWith(doubleSlash))\n        pathCopy = pathCopy.mid(2);\n    else\n        doubleSlash.clear();\n#elif defined(Q_OS_UNIX)\n    {\n        QString tildeExpanded = qt_tildeExpansion(pathCopy);\n        if (tildeExpanded != pathCopy) {\n            QFileSystemModel *dirModel;\n            if (proxyModel)\n                dirModel = qobject_cast<QFileSystemModel *>(proxyModel->sourceModel());\n            else\n                dirModel = sourceModel;\n            dirModel->fetchMore(dirModel->index(tildeExpanded));\n        }\n        pathCopy = std::move(tildeExpanded);\n    }\n#endif\n\n#if defined(Q_OS_WIN)\n    QStringList parts = pathCopy.split(sep, Qt::SkipEmptyParts);\n    if (!doubleSlash.isEmpty() && !parts.isEmpty())\n        parts[0].prepend(doubleSlash);\n    if (pathCopy.endsWith(sep))\n        parts.append(QString());\n#else\n    QStringList parts = pathCopy.split(sep);\n    if (pathCopy[0] == sep) // read the \"/\" at the beginning as the split removed it\n        parts[0] = sep;\n#endif\n\n#if defined(Q_OS_WIN)\n    bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(u':');\n#else\n    bool startsFromRoot = pathCopy[0] == sep;\n#endif\n    if (parts.size() == 1 || (parts.size() > 1 && !startsFromRoot)) {\n        const QFileSystemModel *dirModel;\n        if (proxyModel)\n            dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());\n        else\n            dirModel = sourceModel;\n        QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());\n#if defined(Q_OS_WIN)\n        if (currentLocation.endsWith(u':'))\n            currentLocation.append(sep);\n#endif\n        if (currentLocation.contains(sep) && path != currentLocation) {\n            QStringList currentLocationList = splitPath(currentLocation);\n            while (!currentLocationList.isEmpty() && parts.size() > 0 && parts.at(0) == \"..\"_L1) {\n                parts.removeFirst();\n                currentLocationList.removeLast();\n            }\n            if (!currentLocationList.isEmpty() && currentLocationList.constLast().isEmpty())\n                currentLocationList.removeLast();\n            return currentLocationList + parts;\n        }\n    }\n    return parts;\n}\n\n#endif // QT_CONFIG(completer)\n\n\nQT_END_NAMESPACE\n\n#include \"moc_qfiledialog.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qfiledialog_symbian.cpp",
    "content": "/****************************************************************************\n**\n** Copyright (C) 2015 The Qt Company Ltd.\n** Contact: http://www.qt.io/licensing/\n**\n** This file is part of the QtGui module of the Qt Toolkit.\n**\n** $QT_BEGIN_LICENSE:LGPL$\n** Commercial License Usage\n** Licensees holding valid commercial Qt licenses may use this file in\n** accordance with the commercial license agreement provided with the\n** Software or, alternatively, in accordance with the terms contained in\n** a written agreement between you and The Qt Company. For licensing terms\n** and conditions see http://www.qt.io/terms-conditions. For further\n** information use the contact form at http://www.qt.io/contact-us.\n**\n** GNU Lesser General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU Lesser\n** General Public License version 2.1 or version 3 as published by the Free\n** Software Foundation and appearing in the file LICENSE.LGPLv21 and\n** LICENSE.LGPLv3 included in the packaging of this file. Please review the\n** following information to ensure the GNU Lesser General Public License\n** requirements will be met: https://www.gnu.org/licenses/lgpl.html and\n** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n**\n** As a special exception, The Qt Company gives you certain additional\n** rights. These rights are described in The Qt Company LGPL Exception\n** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n**\n** GNU General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU\n** General Public License version 3.0 as published by the Free Software\n** Foundation and appearing in the file LICENSE.GPL included in the\n** packaging of this file.  Please review the following information to\n** ensure the GNU General Public License version 3.0 requirements will be\n** met: http://www.gnu.org/copyleft/gpl.html.\n**\n** $QT_END_LICENSE$\n**\n****************************************************************************/\n\n#include \"qfiledialog.h\"\n\n#ifndef QT_NO_FILEDIALOG\n\n#include <private/qfiledialog_p.h>\n#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2)\n#include <driveinfo.h>\n#include <AknCommonDialogsDynMem.h>\n#include <CAknMemorySelectionDialogMultiDrive.h>\n#include <MAknFileFilter.h>\n#endif\n#include \"private/qcore_symbian_p.h\"\n\nQT_BEGIN_NAMESPACE\n\nextern QStringList qt_make_filter_list(const QString &filter); // defined in qfiledialog.cpp\nextern QStringList qt_clean_filter_list(const QString &filter); // defined in qfiledialog.cpp\n\nenum DialogMode { DialogOpen, DialogSave, DialogFolder };\n#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2)\nclass CExtensionFilter : public CBase, public MAknFileFilter\n{\npublic:\n    void setFilter(const QString filter)\n    {\n        QStringList unparsedFiltersList = qt_make_filter_list(filter);\n        QStringList filterList;\n        filterRxList.clear();\n\n        foreach (QString unparsedFilter, unparsedFiltersList) {\n            filterList << qt_clean_filter_list(unparsedFilter);\n        }\n        foreach (QString currentFilter, filterList) {\n            QRegExp filterRx(currentFilter, Qt::CaseInsensitive, QRegExp::Wildcard);\n            filterRxList << filterRx;\n        }\n    }\n\n    TBool Accept(const TDesC &/*aDriveAndPath*/, const TEntry &aEntry) const\n    {\n        //If no filter for files, all can be accepted\n        if (filterRxList.isEmpty())\n            return ETrue;\n\n        if (aEntry.IsDir())\n            return ETrue;\n\n        foreach (QRegExp rx, filterRxList) {\n            QString fileName = qt_TDesC2QString(aEntry.iName);\n            if (rx.exactMatch(fileName))\n                return ETrue;\n        }\n\n        return EFalse;\n    }\n\nprivate:\n    QList<QRegExp> filterRxList;\n};\n#endif\n\nstatic QString launchSymbianDialog(const QString dialogCaption, const QString startDirectory,\n                                   const QString filter, DialogMode dialogMode)\n{\n    QString selection;\n#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2)\n    TFileName startFolder;\n    if (!startDirectory.isEmpty()) {\n        QString dir = QDir::toNativeSeparators(QFileDialogPrivate::workingDirectory(startDirectory));\n        startFolder = qt_QString2TPtrC(dir);\n    }\n    TInt types = AknCommonDialogsDynMem::EMemoryTypeMMCExternal|\n                 AknCommonDialogsDynMem::EMemoryTypeInternalMassStorage|\n                 AknCommonDialogsDynMem::EMemoryTypePhone;\n\n    TPtrC titlePtr(qt_QString2TPtrC(dialogCaption));\n    TFileName target;\n    bool select = false;\n    int tryCount = 2;\n    while (tryCount--) {\n        TInt err(KErrNone);\n        TRAP(err,\n            if (dialogMode == DialogOpen) {\n                CExtensionFilter* extensionFilter = new (ELeave) CExtensionFilter;\n                CleanupStack::PushL(extensionFilter);\n                extensionFilter->setFilter(filter);\n                select = AknCommonDialogsDynMem::RunSelectDlgLD(types, target,\n                         startFolder, 0, 0, titlePtr, extensionFilter);\n                CleanupStack::PopAndDestroy(extensionFilter);\n            } else if (dialogMode == DialogSave) {\n                QString defaultFileName = QFileDialogPrivate::initialSelection(startDirectory);\n                target = qt_QString2TPtrC(defaultFileName);\n                select = AknCommonDialogsDynMem::RunSaveDlgLD(types, target,\n                         startFolder, 0, 0, titlePtr);\n            } else if (dialogMode == DialogFolder) {\n                select = AknCommonDialogsDynMem::RunFolderSelectDlgLD(types, target, startFolder,\n                            0, 0, titlePtr, NULL, NULL);\n            }\n        );\n\n        if (err == KErrNone) {\n            tryCount = 0;\n        } else {\n            // Symbian native file dialog doesn't allow accessing files outside C:/Data\n            // It will always leave in that case, so default into QDir::homePath() in error cases.\n            QString dir = QDir::toNativeSeparators(QDir::homePath());\n            startFolder = qt_QString2TPtrC(dir);\n        }\n    }\n    if (select) {\n        QFileInfo fi(qt_TDesC2QString(target));\n        selection = fi.absoluteFilePath();\n    }\n#endif\n    return selection;\n}\n\nQString qtSymbianGetOpenFileName(const QString &caption,\n                                 const QString &dir,\n                                 const QString &filter)\n{\n    return launchSymbianDialog(caption, dir, filter, DialogOpen);\n}\n\nQStringList qtSymbianGetOpenFileNames(const QString &caption,\n                                      const QString &dir,\n                                      const QString &filter)\n{\n    QString fileName;\n    fileName.append(launchSymbianDialog(caption, dir, filter, DialogOpen));\n    QStringList fileList;\n    fileList << fileName;\n\n    return fileList;\n}\n\nQString qtSymbianGetSaveFileName(const QString &caption,\n                                 const QString &dir)\n{\n    return launchSymbianDialog(caption, dir, QString(), DialogSave);\n}\n\nQString qtSymbianGetExistingDirectory(const QString &caption,\n                                      const QString &dir)\n{\n    QString folderCaption;\n    if (!caption.isEmpty()) {\n        folderCaption.append(caption);\n    } else {\n        // Title for folder selection dialog is mandatory\n        folderCaption.append(QFileDialog::tr(\"Find Directory\"));\n    }\n    return launchSymbianDialog(folderCaption, dir, QString(), DialogFolder);\n}\n\nQT_END_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qfiledialog_win.cpp",
    "content": "/****************************************************************************\n**\n** Copyright (C) 2015 The Qt Company Ltd.\n** Contact: http://www.qt.io/licensing/\n**\n** This file is part of the QtGui module of the Qt Toolkit.\n**\n** $QT_BEGIN_LICENSE:LGPL$\n** Commercial License Usage\n** Licensees holding valid commercial Qt licenses may use this file in\n** accordance with the commercial license agreement provided with the\n** Software or, alternatively, in accordance with the terms contained in\n** a written agreement between you and The Qt Company. For licensing terms\n** and conditions see http://www.qt.io/terms-conditions. For further\n** information use the contact form at http://www.qt.io/contact-us.\n**\n** GNU Lesser General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU Lesser\n** General Public License version 2.1 or version 3 as published by the Free\n** Software Foundation and appearing in the file LICENSE.LGPLv21 and\n** LICENSE.LGPLv3 included in the packaging of this file. Please review the\n** following information to ensure the GNU Lesser General Public License\n** requirements will be met: https://www.gnu.org/licenses/lgpl.html and\n** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n**\n** As a special exception, The Qt Company gives you certain additional\n** rights. These rights are described in The Qt Company LGPL Exception\n** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n**\n** GNU General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU\n** General Public License version 3.0 as published by the Free Software\n** Foundation and appearing in the file LICENSE.GPL included in the\n** packaging of this file.  Please review the following information to\n** ensure the GNU General Public License version 3.0 requirements will be\n** met: http://www.gnu.org/copyleft/gpl.html.\n**\n** $QT_END_LICENSE$\n**\n****************************************************************************/\n\n#include \"qfiledialog.h\"\n\n#ifndef QT_NO_FILEDIALOG\n\n#include <private/qfiledialog_p.h>\n#include <qapplication.h>\n#include <private/qapplication_p.h>\n#include <qt_windows.h>\n#include <qglobal.h>\n#include <qregexp.h>\n#include <qbuffer.h>\n#include <qdir.h>\n#include <qstringlist.h>\n#include <private/qsystemlibrary_p.h>\n#include \"qfiledialog_win_p.h\"\n\n#ifdef Q_WS_WINCE\n#include <commdlg.h>\nbool qt_priv_ptr_valid = false;\n#else\n//we have to declare them here because they're not present for all SDK/compilers\nstatic const IID   QT_IID_IFileOpenDialog  = {0xd57c7288, 0xd4ad, 0x4768, {0xbe, 0x02, 0x9d, 0x96, 0x95, 0x32, 0xd9, 0x60} };\nstatic const IID   QT_IID_IShellItem       = {0x43826d1e, 0xe718, 0x42ee, {0xbc, 0x55, 0xa1, 0xe2, 0x61, 0xc3, 0x7b, 0xfe} };\nstatic const CLSID QT_CLSID_FileOpenDialog = {0xdc1c5a9c, 0xe88a, 0x4dde, {0xa5, 0xa1, 0x60, 0xf8, 0x2a, 0x20, 0xae, 0xf7} };\n#endif\n\n\ntypedef qt_LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(qt_BROWSEINFO*);\nstatic PtrSHBrowseForFolder ptrSHBrowseForFolder = 0;\ntypedef BOOL (WINAPI *PtrSHGetPathFromIDList)(qt_LPITEMIDLIST, LPWSTR);\nstatic PtrSHGetPathFromIDList ptrSHGetPathFromIDList = 0;\ntypedef HRESULT (WINAPI *PtrSHGetMalloc)(LPMALLOC *);\nstatic PtrSHGetMalloc ptrSHGetMalloc = 0;\n\n\nQT_BEGIN_NAMESPACE\n\nstatic void qt_win_resolve_libs()\n{\n    static bool triedResolve = false;\n    if (!triedResolve) {\n#if !defined(Q_WS_WINCE)\n        QSystemLibrary lib(QLatin1String(\"shell32\"));\n        ptrSHBrowseForFolder = (PtrSHBrowseForFolder)lib.resolve(\"SHBrowseForFolderW\");\n        ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)lib.resolve(\"SHGetPathFromIDListW\");\n        ptrSHGetMalloc = (PtrSHGetMalloc)lib.resolve(\"SHGetMalloc\");\n#else\n        // CE stores them in a different lib and does not use unicode version\n        QSystemLibrary lib(QLatin1String(\"Ceshell\"));\n        ptrSHBrowseForFolder = (PtrSHBrowseForFolder)lib.resolve(\"SHBrowseForFolder\");\n        ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)lib.resolve(\"SHGetPathFromIDList\");\n        ptrSHGetMalloc = (PtrSHGetMalloc)lib.resolve(\"SHGetMalloc\");\n        if (ptrSHBrowseForFolder && ptrSHGetPathFromIDList && ptrSHGetMalloc)\n            qt_priv_ptr_valid = true;\n#endif\n\n        triedResolve = true;\n    }\n}\n\nextern const char* qt_file_dialog_filter_reg_exp; // defined in qfiledialog.cpp\nextern QStringList qt_make_filter_list(const QString &filter);\n\nconst int maxNameLen = 1023;\nconst int maxMultiLen = 65535;\n\n// Returns the wildcard part of a filter.\nstatic QString qt_win_extract_filter(const QString &rawFilter)\n{\n    QString result = rawFilter;\n    QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));\n    int index = r.indexIn(result);\n    if (index >= 0)\n        result = r.cap(2);\n    QStringList list = result.split(QLatin1Char(' '));\n    for(QStringList::iterator it = list.begin(); it < list.end(); ++it) {\n        if (*it == QLatin1String(\"*\")) {\n            *it = QLatin1String(\"*.*\");\n            break;\n        }\n    }\n    return list.join(QLatin1String(\";\"));\n}\n\nstatic QStringList qt_win_make_filters_list(const QString &filter)\n{\n    QString f(filter);\n\n    if (f.isEmpty())\n        f = QFileDialog::tr(\"All Files (*.*)\");\n\n    return qt_make_filter_list(f);\n}\n\n// Makes a NUL-oriented Windows filter from a Qt filter.\nstatic QString qt_win_filter(const QString &filter, bool hideFiltersDetails)\n{\n    QStringList filterLst = qt_win_make_filters_list(filter);\n    QStringList::Iterator it = filterLst.begin();\n    QString winfilters;\n    QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));\n    for (; it != filterLst.end(); ++it) {\n        QString subfilter = *it;\n        if (!subfilter.isEmpty()) {\n            if (hideFiltersDetails) {\n                int index = r.indexIn(subfilter);\n                if (index >= 0)\n                    winfilters += r.cap(1);\n            } else {\n                winfilters += subfilter;\n            }\n            winfilters += QChar();\n            winfilters += qt_win_extract_filter(subfilter);\n            winfilters += QChar();\n        }\n    }\n    winfilters += QChar();\n    return winfilters;\n}\n\nstatic QString qt_win_selected_filter(const QString &filter, DWORD idx)\n{\n    return qt_win_make_filters_list(filter).at((int)idx - 1);\n}\n\nstatic QString tFilters, tTitle, tInitDir;\n\nstatic OPENFILENAME* qt_win_make_OFN(QWidget *parent,\n                                     const QString& initialSelection,\n                                     const QString& initialDirectory,\n                                     const QString& title,\n                                     const QString& filters,\n                                     QFileDialog::FileMode mode,\n                                     QFileDialog::Options options)\n{\n    if (parent)\n        parent = parent->window();\n    else\n        parent = QApplication::activeWindow();\n\n    tInitDir = QDir::toNativeSeparators(initialDirectory);\n    tFilters = filters;\n    tTitle = title;\n    QString initSel = QDir::toNativeSeparators(initialSelection);\n    if (!initSel.isEmpty()) {\n        initSel.remove(QLatin1Char('<'));\n        initSel.remove(QLatin1Char('>'));\n        initSel.remove(QLatin1Char('\\\"'));\n        initSel.remove(QLatin1Char('|'));\n    }\n\n    int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen;\n    wchar_t *tInitSel = new wchar_t[maxLen + 1];\n    if (initSel.length() > 0 && initSel.length() <= maxLen)\n        memcpy(tInitSel, initSel.utf16(), (initSel.length()+1)*sizeof(QChar));\n    else\n        tInitSel[0] = 0;\n\n    OPENFILENAME* ofn = new OPENFILENAME;\n    memset(ofn, 0, sizeof(OPENFILENAME));\n\n    ofn->lStructSize = sizeof(OPENFILENAME);\n    ofn->hwndOwner = parent ? parent->winId() : 0;\n    ofn->lpstrFilter = (wchar_t*)tFilters.utf16();\n    ofn->lpstrFile = tInitSel;\n    ofn->nMaxFile = maxLen;\n    ofn->lpstrInitialDir = (wchar_t*)tInitDir.utf16();\n    ofn->lpstrTitle = (wchar_t*)tTitle.utf16();\n    ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_PATHMUSTEXIST);\n    if (mode == QFileDialog::ExistingFile ||\n         mode == QFileDialog::ExistingFiles)\n        ofn->Flags |= (OFN_FILEMUSTEXIST);\n    if (mode == QFileDialog::ExistingFiles)\n        ofn->Flags |= (OFN_ALLOWMULTISELECT);\n    if (!(options & QFileDialog::DontConfirmOverwrite))\n        ofn->Flags |= OFN_OVERWRITEPROMPT;\n\n    return ofn;\n}\n\nstatic void qt_win_clean_up_OFN(OPENFILENAME **ofn)\n{\n    delete [] (*ofn)->lpstrFile;\n    delete *ofn;\n    *ofn = 0;\n}\n\nextern void qt_win_eatMouseMove();\n\nQString qt_win_get_open_file_name(const QFileDialogArgs &args,\n                                  QString *initialDirectory,\n                                  QString *selectedFilter)\n{\n    QString result;\n\n    QString isel = args.selection;\n\n    if (initialDirectory && initialDirectory->left(5) == QLatin1String(\"file:\"))\n        initialDirectory->remove(0, 5);\n    QFileInfo fi(*initialDirectory);\n\n    if (initialDirectory && !fi.isDir()) {\n        *initialDirectory = fi.absolutePath();\n        if (isel.isEmpty())\n            isel = fi.fileName();\n    }\n\n    if (!fi.exists())\n        *initialDirectory = QDir::homePath();\n\n    DWORD selFilIdx = 0;\n\n    int idx = 0;\n    if (selectedFilter) {\n        QStringList filterLst = qt_win_make_filters_list(args.filter);\n        idx = filterLst.indexOf(*selectedFilter);\n    }\n\n    QDialog modal_widget;\n    modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);\n    modal_widget.setParent(args.parent, Qt::Window);\n    QApplicationPrivate::enterModal(&modal_widget);\n\n    bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails;\n    OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection,\n                                        args.directory, args.caption,\n                                        qt_win_filter(args.filter, hideFiltersDetails),\n                                        QFileDialog::ExistingFile,\n                                        args.options);\n    if (idx)\n        ofn->nFilterIndex = idx + 1;\n    if (GetOpenFileName(ofn)) {\n        result = QString::fromWCharArray(ofn->lpstrFile);\n        selFilIdx = ofn->nFilterIndex;\n    }\n    qt_win_clean_up_OFN(&ofn);\n\n    QApplicationPrivate::leaveModal(&modal_widget);\n\n    qt_win_eatMouseMove();\n\n    if (result.isEmpty())\n        return result;\n\n    fi = result;\n    *initialDirectory = fi.path();\n    if (selectedFilter)\n        *selectedFilter = qt_win_selected_filter(args.filter, selFilIdx);\n    return fi.absoluteFilePath();\n}\n\nQString qt_win_get_save_file_name(const QFileDialogArgs &args,\n                                  QString *initialDirectory,\n                                  QString *selectedFilter)\n{\n    QString result;\n\n    QString isel = args.selection;\n    if (initialDirectory && initialDirectory->left(5) == QLatin1String(\"file:\"))\n        initialDirectory->remove(0, 5);\n    QFileInfo fi(*initialDirectory);\n\n    if (initialDirectory && !fi.isDir()) {\n        *initialDirectory = fi.absolutePath();\n        if (isel.isEmpty())\n            isel = fi.fileName();\n    }\n\n    if (!fi.exists())\n        *initialDirectory = QDir::homePath();\n\n    DWORD selFilIdx = 0;\n\n    int idx = 0;\n    if (selectedFilter) {\n        QStringList filterLst = qt_win_make_filters_list(args.filter);\n        idx = filterLst.indexOf(*selectedFilter);\n    }\n\n    QDialog modal_widget;\n    modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);\n    modal_widget.setParent(args.parent, Qt::Window);\n    QApplicationPrivate::enterModal(&modal_widget);\n    bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails;\n    // This block is used below for the lpstrDefExt member.\n    // Note that the current MSDN docs document this member wrong.\n    // It should rather be documented as \"the default extension if no extension was given and if the\n    // current filter does not have a extension (e.g (*)). If the current filter have an extension, use\n    // the extension of the current filter\"\n    QString defaultSaveExt;\n    if (selectedFilter && !selectedFilter->isEmpty()) {\n        defaultSaveExt = qt_win_extract_filter(*selectedFilter);\n        // make sure we only have the extension\n        int firstDot = defaultSaveExt.indexOf(QLatin1Char('.'));\n        if (firstDot != -1) {\n            defaultSaveExt.remove(0, firstDot + 1);\n        } else {\n            defaultSaveExt.clear();\n        }\n    }\n\n    OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection,\n                                        args.directory, args.caption,\n                                        qt_win_filter(args.filter, hideFiltersDetails),\n                                        QFileDialog::AnyFile,\n                                        args.options);\n\n    ofn->lpstrDefExt = (wchar_t*)defaultSaveExt.utf16();\n\n    if (idx)\n        ofn->nFilterIndex = idx + 1;\n    if (GetSaveFileName(ofn)) {\n        result = QString::fromWCharArray(ofn->lpstrFile);\n        selFilIdx = ofn->nFilterIndex;\n    }\n    qt_win_clean_up_OFN(&ofn);\n\n#if defined(Q_WS_WINCE)\n    int semIndex = result.indexOf(QLatin1Char(';'));\n    if (semIndex >= 0)\n        result = result.left(semIndex);\n#endif\n\n    QApplicationPrivate::leaveModal(&modal_widget);\n\n    qt_win_eatMouseMove();\n\n    if (result.isEmpty())\n        return result;\n\n    fi = result;\n    *initialDirectory = fi.path();\n    if (selectedFilter)\n        *selectedFilter = qt_win_selected_filter(args.filter, selFilIdx);\n    return fi.absoluteFilePath();\n}\n\n\n#ifndef Q_WS_WINCE\n\ntypedef HRESULT (WINAPI *PtrSHCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);\nstatic PtrSHCreateItemFromParsingName pSHCreateItemFromParsingName = 0;\n\nstatic bool qt_win_set_IFileDialogOptions(IFileDialog *pfd,\n                                          const QString& initialSelection,\n                                          const QString& initialDirectory,\n                                          const QString& title,\n                                          const QStringList& filterLst,\n                                          QFileDialog::FileMode mode,\n                                          QFileDialog::Options options)\n{\n    if (!pSHCreateItemFromParsingName) {\n        // This function is available only in Vista & above.\n        QSystemLibrary shellLib(QLatin1String(\"Shell32\"));\n        pSHCreateItemFromParsingName = (PtrSHCreateItemFromParsingName)\n            shellLib.resolve(\"SHCreateItemFromParsingName\");\n        if (!pSHCreateItemFromParsingName)\n            return false;\n    }\n    HRESULT hr;\n    QString winfilters;\n    int numFilters = 0;\n    quint32 currentOffset = 0;\n    QList<quint32> offsets;\n    QStringList::ConstIterator it = filterLst.begin();\n    // Create the native filter string and save offset to each entry.\n    for (; it != filterLst.end(); ++it) {\n        QString subfilter = *it;\n        if (!subfilter.isEmpty()) {\n            offsets<<currentOffset;\n            //Here the COMMON_ITEM_DIALOG API always add the details for the filter (e.g. *.txt)\n            //so we don't need to handle the flag HideNameFilterDetails.\n            winfilters += subfilter; // The name of the filter.\n            winfilters += QChar();\n            currentOffset += subfilter.size()+1;\n            offsets<<currentOffset;\n            QString spec = qt_win_extract_filter(subfilter);\n            winfilters += spec; // The actual filter spec.\n            winfilters += QChar();\n            currentOffset += spec.size()+1;\n            numFilters++;\n        }\n    }\n    // Add the filters to the file dialog.\n    if (numFilters) {\n        wchar_t *szData = (wchar_t*)winfilters.utf16();\n        qt_COMDLG_FILTERSPEC *filterSpec = new qt_COMDLG_FILTERSPEC[numFilters];\n        for(int i = 0; i<numFilters; i++) {\n            filterSpec[i].pszName = szData+offsets[i*2];\n            filterSpec[i].pszSpec = szData+offsets[(i*2)+1];\n        }\n        hr = pfd->SetFileTypes(numFilters, filterSpec);\n        delete []filterSpec;\n    }\n    // Set the starting folder.\n    tInitDir = QDir::toNativeSeparators(initialDirectory);\n    if (!tInitDir.isEmpty()) {\n        IShellItem *psiDefaultFolder;\n        hr = pSHCreateItemFromParsingName((wchar_t*)tInitDir.utf16(), NULL, QT_IID_IShellItem, \n            reinterpret_cast<void**>(&psiDefaultFolder));\n\n        if (SUCCEEDED(hr)) {\n            hr = pfd->SetFolder(psiDefaultFolder);\n            psiDefaultFolder->Release();\n        }\n    }\n    // Set the currently selected file.\n    QString initSel = QDir::toNativeSeparators(initialSelection);\n    if (!initSel.isEmpty()) {\n        initSel.remove(QLatin1Char('<'));\n        initSel.remove(QLatin1Char('>'));\n        initSel.remove(QLatin1Char('\\\"'));\n        initSel.remove(QLatin1Char('|'));\n    }\n    if (!initSel.isEmpty()) {\n        hr = pfd->SetFileName((wchar_t*)initSel.utf16());\n    }\n    // Set the title for the file dialog.\n    if (!title.isEmpty()) {\n        hr = pfd->SetTitle((wchar_t*)title.utf16());\n    }\n    // Set other flags for the dialog.\n    DWORD newOptions;\n    hr = pfd->GetOptions(&newOptions);\n    if (SUCCEEDED(hr)) {\n        newOptions |= FOS_NOCHANGEDIR;\n        if (mode == QFileDialog::ExistingFile ||\n             mode == QFileDialog::ExistingFiles)\n            newOptions |= (FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST);\n        if (mode == QFileDialog::ExistingFiles)\n            newOptions |= FOS_ALLOWMULTISELECT;\n        if (!(options & QFileDialog::DontConfirmOverwrite))\n            newOptions |= FOS_OVERWRITEPROMPT;\n        hr = pfd->SetOptions(newOptions);\n    }\n    return SUCCEEDED(hr);\n}\n\nstatic QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,\n                                       QString *initialDirectory,\n                                       const QStringList &filterList,\n                                       QString *selectedFilter,\n                                       int selectedFilterIndex)\n{\n    QStringList result;\n    QDialog modal_widget;\n    modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);\n    modal_widget.setParent(args.parent, Qt::Window);\n    QApplicationPrivate::enterModal(&modal_widget);\n    // Multiple selection is allowed only in IFileOpenDialog.\n    IFileOpenDialog *pfd = 0;\n    HRESULT hr = CoCreateInstance(QT_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, QT_IID_IFileOpenDialog, \n        reinterpret_cast<void**>(&pfd));\n\n    if (SUCCEEDED(hr)) {\n        qt_win_set_IFileDialogOptions(pfd, args.selection,\n                                      args.directory, args.caption,\n                                      filterList, QFileDialog::ExistingFiles,\n                                      args.options);\n        // Set the currently selected filter (one-based index).\n        hr = pfd->SetFileTypeIndex(selectedFilterIndex+1);\n        QWidget *parentWindow = args.parent;\n        if (parentWindow)\n            parentWindow = parentWindow->window();\n        else\n            parentWindow = QApplication::activeWindow();\n        // Show the file dialog.\n        hr = pfd->Show(parentWindow ? parentWindow->winId() : 0);\n        if (SUCCEEDED(hr)) {\n            // Retrieve the results.\n            IShellItemArray *psiaResults;\n            hr = pfd->GetResults(&psiaResults);\n            if (SUCCEEDED(hr)) {\n                DWORD numItems = 0;\n                psiaResults->GetCount(&numItems);\n                for (DWORD i = 0; i<numItems; i++) {\n                    IShellItem *psi = 0;\n                    hr = psiaResults->GetItemAt(i, &psi);\n                    if (SUCCEEDED(hr)) {\n                        // Retrieve the file name from shell item.\n                        wchar_t *pszPath;\n                        hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);\n                        if (SUCCEEDED(hr)) {\n                            QString fileName = QString::fromWCharArray(pszPath);\n                            result.append(fileName);\n                            CoTaskMemFree(pszPath);\n                        }\n                        psi->Release(); // Free the current item.\n                    }\n                }\n                psiaResults->Release(); // Free the array of items.\n            }\n        }\n    }\n    QApplicationPrivate::leaveModal(&modal_widget);\n\n    qt_win_eatMouseMove();\n\n    if (!result.isEmpty()) {\n        // Retrieve the current folder name.\n        IShellItem *psi = 0;\n        hr = pfd->GetFolder(&psi);\n        if (SUCCEEDED(hr)) {\n            wchar_t *pszPath;\n            hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);\n            if (SUCCEEDED(hr)) {\n                *initialDirectory = QString::fromWCharArray(pszPath);\n                CoTaskMemFree(pszPath);\n            }\n            psi->Release();\n        }\n        // Retrieve the currently selected filter.\n        if (selectedFilter) {\n            quint32 filetype = 0;\n            hr = pfd->GetFileTypeIndex(&filetype);\n            if (SUCCEEDED(hr) && filetype && filetype <= (quint32)filterList.length()) {\n                // This is a one-based index, not zero-based.\n                *selectedFilter = filterList[filetype-1];\n            }\n        }\n    }\n    if (pfd)\n        pfd->Release();\n    return result;\n}\n\nQString qt_win_CID_get_existing_directory(const QFileDialogArgs &args)\n{\n    QString result;\n    QDialog modal_widget;\n    modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);\n    modal_widget.setParent(args.parent, Qt::Window);\n    QApplicationPrivate::enterModal(&modal_widget);\n\n    IFileOpenDialog *pfd = 0;\n    HRESULT hr = CoCreateInstance(QT_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,\n                                  QT_IID_IFileOpenDialog, reinterpret_cast<void**>(&pfd));\n\n    if (SUCCEEDED(hr)) {\n        qt_win_set_IFileDialogOptions(pfd, args.selection,\n                                      args.directory, args.caption,\n                                      QStringList(), QFileDialog::ExistingFile,\n                                      args.options);\n\n        // Set the FOS_PICKFOLDERS flag\n        DWORD newOptions;\n        hr = pfd->GetOptions(&newOptions);\n        newOptions |= (FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM);\n        if (SUCCEEDED(hr) && SUCCEEDED((hr = pfd->SetOptions(newOptions)))) {\n            QWidget *parentWindow = args.parent;\n            if (parentWindow)\n                parentWindow = parentWindow->window();\n            else\n                parentWindow = QApplication::activeWindow();\n\n            // Show the file dialog.\n            hr = pfd->Show(parentWindow ? parentWindow->winId() : 0);\n            if (SUCCEEDED(hr)) {\n                // Retrieve the result\n                IShellItem *psi = 0;\n                hr = pfd->GetResult(&psi);\n                if (SUCCEEDED(hr)) {\n                    // Retrieve the file name from shell item.\n                    wchar_t *pszPath;\n                    hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);\n                    if (SUCCEEDED(hr)) {\n                        result = QString::fromWCharArray(pszPath);\n                        CoTaskMemFree(pszPath);\n                    }\n                    psi->Release(); // Free the current item.\n                }\n            }\n        }\n    }\n    QApplicationPrivate::leaveModal(&modal_widget);\n\n    qt_win_eatMouseMove();\n\n    if (pfd)\n        pfd->Release();\n    return result;\n}\n\n#endif\n\nQStringList qt_win_get_open_file_names(const QFileDialogArgs &args,\n                                       QString *initialDirectory,\n                                       QString *selectedFilter)\n{\n    QFileInfo fi;\n    QDir dir;\n\n    if (initialDirectory && initialDirectory->left(5) == QLatin1String(\"file:\"))\n        initialDirectory->remove(0, 5);\n    fi = QFileInfo(*initialDirectory);\n\n    if (initialDirectory && !fi.isDir()) {\n        *initialDirectory = fi.absolutePath();\n    }\n\n    if (!fi.exists())\n        *initialDirectory = QDir::homePath();\n\n    DWORD selFilIdx = 0;\n\n    QStringList filterLst = qt_win_make_filters_list(args.filter);\n    int idx = 0;\n    if (selectedFilter) {\n        idx = filterLst.indexOf(*selectedFilter);\n    }\n    // Windows Vista (& above) allows users to search from file dialogs. If user selects\n    // multiple files belonging to different folders from these search results, the\n    // GetOpenFileName() will return only one folder name for all the files. To retrieve\n    // the correct path for all selected files, we have to use Common Item Dialog interfaces.\n#ifndef Q_WS_WINCE\n    if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))\n        return qt_win_CID_get_open_file_names(args, initialDirectory, filterLst, selectedFilter, idx);\n#endif\n\n    QStringList result;\n    QDialog modal_widget;\n    modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);\n    modal_widget.setParent(args.parent, Qt::Window);\n    QApplicationPrivate::enterModal(&modal_widget);\n\n    bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails;\n    OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection,\n                                        args.directory, args.caption,\n                                        qt_win_filter(args.filter, hideFiltersDetails),\n                                        QFileDialog::ExistingFiles,\n                                        args.options);\n    if (idx)\n        ofn->nFilterIndex = idx + 1;\n    if (GetOpenFileName(ofn)) {\n        QString fileOrDir = QString::fromWCharArray(ofn->lpstrFile);\n        selFilIdx = ofn->nFilterIndex;\n        int offset = fileOrDir.length() + 1;\n        if (ofn->lpstrFile[offset] == 0) {\n            // Only one file selected; has full path\n            fi.setFile(fileOrDir);\n            QString res = fi.absoluteFilePath();\n            if (!res.isEmpty())\n                result.append(res);\n        }\n        else {\n            // Several files selected; first string is path\n            dir.setPath(fileOrDir);\n            QString f;\n            while(!(f = QString::fromWCharArray(ofn->lpstrFile + offset)).isEmpty()) {\n                fi.setFile(dir, f);\n                QString res = fi.absoluteFilePath();\n                if (!res.isEmpty())\n                    result.append(res);\n                offset += f.length() + 1;\n            }\n        }\n    }\n    qt_win_clean_up_OFN(&ofn);\n\n    QApplicationPrivate::leaveModal(&modal_widget);\n\n    qt_win_eatMouseMove();\n\n    if (!result.isEmpty()) {\n        *initialDirectory = fi.path();    // only save the path if there is a result\n        if (selectedFilter)\n            *selectedFilter = qt_win_selected_filter(args.filter, selFilIdx);\n    }\n    return result;\n}\n\n// MFC Directory Dialog. Contrib: Steve Williams (minor parts from Scott Powers)\n\nstatic int __stdcall winGetExistDirCallbackProc(HWND hwnd,\n                                                UINT uMsg,\n                                                LPARAM lParam,\n                                                LPARAM lpData)\n{\n    if (uMsg == BFFM_INITIALIZED && lpData != 0) {\n        QString *initDir = (QString *)(lpData);\n        if (!initDir->isEmpty()) {\n            SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16()));\n        }\n    } else if (uMsg == BFFM_SELCHANGED) {\n        qt_win_resolve_libs();\n        if (ptrSHGetPathFromIDList) {\n            wchar_t path[MAX_PATH];\n            ptrSHGetPathFromIDList(qt_LPITEMIDLIST(lParam), path);\n            QString tmpStr = QString::fromWCharArray(path);\n            if (!tmpStr.isEmpty())\n                SendMessage(hwnd, BFFM_ENABLEOK, 1, 1);\n            else\n                SendMessage(hwnd, BFFM_ENABLEOK, 0, 0);\n            SendMessage(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path));\n        }\n    }\n    return 0;\n}\n\nQString qt_win_get_existing_directory(const QFileDialogArgs &args)\n{\n#ifndef Q_WS_WINCE\n    if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))\n        return qt_win_CID_get_existing_directory(args);\n#endif\n\n    QString currentDir = QDir::currentPath();\n    QString result;\n    QWidget *parent = args.parent;\n    if (parent)\n        parent = parent->window();\n    else\n        parent = QApplication::activeWindow();\n    if (parent)\n        parent->createWinId();\n\n    QDialog modal_widget;\n    modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);\n    modal_widget.setParent(parent, Qt::Window);\n    QApplicationPrivate::enterModal(&modal_widget);\n\n    QString initDir = QDir::toNativeSeparators(args.directory);\n    wchar_t path[MAX_PATH];\n    wchar_t initPath[MAX_PATH];\n    initPath[0] = 0;\n    path[0] = 0;\n    tTitle = args.caption;\n\n    qt_BROWSEINFO bi;\n\n    Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));\n    bi.hwndOwner = (parent ? parent->winId() : 0);\n    bi.pidlRoot = NULL;\n    //### This does not seem to be respected? - the dialog always displays \"Browse for folder\"\n    bi.lpszTitle = (wchar_t*)tTitle.utf16();\n    bi.pszDisplayName = initPath;\n    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE;\n    bi.lpfn = winGetExistDirCallbackProc;\n    bi.lParam = LPARAM(&initDir);\n\n    qt_win_resolve_libs();\n    if (ptrSHBrowseForFolder) {\n        qt_LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder(&bi);\n        if (pItemIDList) {\n            ptrSHGetPathFromIDList(pItemIDList, path);\n            IMalloc *pMalloc;\n            if (ptrSHGetMalloc(&pMalloc) == NOERROR) {\n                pMalloc->Free(pItemIDList);\n                pMalloc->Release();\n                result = QString::fromWCharArray(path);\n            }\n        }\n    }\n    tTitle = QString();\n\n    QApplicationPrivate::leaveModal(&modal_widget);\n\n    qt_win_eatMouseMove();\n\n    if (!result.isEmpty())\n        result.replace(QLatin1Char('\\\\'), QLatin1Char('/'));\n    return result;\n}\n\n\nQT_END_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qfileinfogatherer.cpp",
    "content": "// Copyright (C) 2020 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qfileinfogatherer_p.h\"\n#include <qcoreapplication.h>\n#include <qdebug.h>\n#include <qdirlisting.h>\n#include <private/qabstractfileiconprovider_p.h>\n#include <private/qfileinfo_p.h>\n#ifndef Q_OS_WIN\n#  include <unistd.h>\n#  include <sys/types.h>\n#endif\n#if defined(Q_OS_VXWORKS)\n#  include \"qplatformdefs.h\"\n#endif\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\n#ifdef QT_BUILD_INTERNAL\nQ_CONSTINIT static QBasicAtomicInt fetchedRoot = Q_BASIC_ATOMIC_INITIALIZER(false);\nQ_AUTOTEST_EXPORT void qt_test_resetFetchedRoot()\n{\n    fetchedRoot.storeRelaxed(false);\n}\n\nQ_AUTOTEST_EXPORT bool qt_test_isFetchedRoot()\n{\n    return fetchedRoot.loadRelaxed();\n}\n#endif\n\nstatic QString translateDriveName(const QFileInfo &drive)\n{\n    QString driveName = drive.absoluteFilePath();\n#ifdef Q_OS_WIN\n    if (driveName.startsWith(u'/')) // UNC host\n        return drive.fileName();\n    if (driveName.endsWith(u'/'))\n        driveName.chop(1);\n#endif // Q_OS_WIN\n    return driveName;\n}\n\n/*!\n    Creates thread\n*/\nQFileInfoGatherer::QFileInfoGatherer(QObject *parent)\n    : QThread(parent)\n    , m_iconProvider(&defaultProvider)\n{\n    start(LowPriority);\n}\n\n/*!\n    Destroys thread\n*/\nQFileInfoGatherer::~QFileInfoGatherer()\n{\n    requestAbort();\n    wait();\n}\n\nbool QFileInfoGatherer::event(QEvent *event)\n{\n    if (event->type() == QEvent::DeferredDelete && isRunning()) {\n        // We have been asked to shut down later but were blocked,\n        // so the owning QFileSystemModel proceeded with its shut-down\n        // and deferred the destruction of the gatherer.\n        // If we are still blocked now, then we have three bad options:\n        // terminate, wait forever (preventing the process from shutting down),\n        // or accept a memory leak.\n        requestAbort();\n        if (!wait(5000)) {\n            // If the application is shutting down, then we terminate.\n            // Otherwise assume that sooner or later the thread will finish,\n            // and we delete it then.\n            if (QCoreApplication::closingDown())\n                terminate();\n            else\n                connect(this, &QThread::finished, this, [this]{ delete this; });\n            return true;\n        }\n    }\n\n    return QThread::event(event);\n}\n\nvoid QFileInfoGatherer::requestAbort()\n{\n    requestInterruption();\n    QMutexLocker locker(&mutex);\n    condition.wakeAll();\n}\n\nvoid QFileInfoGatherer::setResolveSymlinks(bool enable)\n{\n    Q_UNUSED(enable);\n#ifdef Q_OS_WIN\n    m_resolveSymlinks = enable;\n#endif\n}\n\nvoid QFileInfoGatherer::driveAdded()\n{\n    fetchExtendedInformation(QString(), QStringList());\n}\n\nvoid QFileInfoGatherer::driveRemoved()\n{\n    QStringList drives;\n    const QFileInfoList driveInfoList = QDir::drives();\n    for (const QFileInfo &fi : driveInfoList)\n        drives.append(translateDriveName(fi));\n    emit newListOfFiles(QString(), drives);\n}\n\nbool QFileInfoGatherer::resolveSymlinks() const\n{\n#ifdef Q_OS_WIN\n    return m_resolveSymlinks;\n#else\n    return false;\n#endif\n}\n\nvoid QFileInfoGatherer::setIconProvider(QAbstractFileIconProvider *provider)\n{\n    m_iconProvider = provider;\n}\n\nQAbstractFileIconProvider *QFileInfoGatherer::iconProvider() const\n{\n    return m_iconProvider;\n}\n\n/*!\n    Fetch extended information for all \\a files in \\a path\n\n    \\sa updateFile(), update(), resolvedName()\n*/\nvoid QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStringList &files)\n{\n    QMutexLocker locker(&mutex);\n    // See if we already have this dir/file in our queue\n    qsizetype loc = 0;\n    while ((loc = this->path.lastIndexOf(path, loc - 1)) != -1) {\n        if (this->files.at(loc) == files)\n            return;\n    }\n\n#if QT_CONFIG(thread)\n    this->path.push(path);\n    this->files.push(files);\n    condition.wakeAll();\n#else // !QT_CONFIG(thread)\n    getFileInfos(path, files);\n#endif // QT_CONFIG(thread)\n\n#if QT_CONFIG(filesystemwatcher)\n    if (files.isEmpty()\n        && !path.isEmpty()\n        && !path.startsWith(\"//\"_L1) /*don't watch UNC path*/) {\n        if (!watchedDirectories().contains(path))\n            watchPaths(QStringList(path));\n    }\n#endif\n}\n\n/*!\n    Fetch extended information for all \\a filePath\n\n    \\sa fetchExtendedInformation()\n*/\nvoid QFileInfoGatherer::updateFile(const QString &filePath)\n{\n    QString dir = filePath.mid(0, filePath.lastIndexOf(u'/'));\n    QString fileName = filePath.mid(dir.size() + 1);\n    fetchExtendedInformation(dir, QStringList(fileName));\n}\n\nQStringList QFileInfoGatherer::watchedFiles() const\n{\n#if QT_CONFIG(filesystemwatcher)\n    if (m_watcher)\n        return m_watcher->files();\n#endif\n    return {};\n}\n\nQStringList QFileInfoGatherer::watchedDirectories() const\n{\n#if QT_CONFIG(filesystemwatcher)\n    if (m_watcher)\n        return m_watcher->directories();\n#endif\n    return {};\n}\n\nvoid QFileInfoGatherer::createWatcher()\n{\n#if QT_CONFIG(filesystemwatcher)\n    m_watcher = new QFileSystemWatcher(this);\n    connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &QFileInfoGatherer::list);\n    connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &QFileInfoGatherer::updateFile);\n#  if defined(Q_OS_WIN)\n    const QVariant listener = m_watcher->property(\"_q_driveListener\");\n    if (listener.canConvert<QObject *>()) {\n        if (QObject *driveListener = listener.value<QObject *>()) {\n            connect(driveListener, SIGNAL(driveAdded()), this, SLOT(driveAdded()));\n            connect(driveListener, SIGNAL(driveRemoved()), this, SLOT(driveRemoved()));\n        }\n    }\n#  endif // Q_OS_WIN\n#endif\n}\n\nvoid QFileInfoGatherer::watchPaths(const QStringList &paths)\n{\n#if QT_CONFIG(filesystemwatcher)\n    if (m_watching) {\n        if (m_watcher == nullptr)\n            createWatcher();\n        m_watcher->addPaths(paths);\n    }\n#else\n    Q_UNUSED(paths);\n#endif\n}\n\nvoid QFileInfoGatherer::unwatchPaths(const QStringList &paths)\n{\n#if QT_CONFIG(filesystemwatcher)\n    if (m_watcher && !paths.isEmpty())\n        m_watcher->removePaths(paths);\n#else\n    Q_UNUSED(paths);\n#endif\n}\n\nbool QFileInfoGatherer::isWatching() const\n{\n    bool result = false;\n#if QT_CONFIG(filesystemwatcher)\n    QMutexLocker locker(&mutex);\n    result = m_watching;\n#endif\n    return result;\n}\n\n/*! \\internal\n\n    If \\a v is \\c false, the QFileSystemWatcher used internally will be deleted\n    and subsequent calls to watchPaths() will do nothing.\n\n    If \\a v is \\c true, subsequent calls to watchPaths() will add those paths to\n    the filesystem watcher; watchPaths() will initialize a QFileSystemWatcher if\n    one hasn't already been initialized.\n*/\nvoid QFileInfoGatherer::setWatching(bool v)\n{\n#if QT_CONFIG(filesystemwatcher)\n    QMutexLocker locker(&mutex);\n    if (v != m_watching) {\n        m_watching = v;\n        if (!m_watching)\n            delete std::exchange(m_watcher, nullptr);\n    }\n#else\n    Q_UNUSED(v);\n#endif\n}\n\n/*\n    List all files in \\a directoryPath\n\n    \\sa listed()\n*/\nvoid QFileInfoGatherer::clear()\n{\n#if QT_CONFIG(filesystemwatcher)\n    QMutexLocker locker(&mutex);\n    unwatchPaths(watchedFiles());\n    unwatchPaths(watchedDirectories());\n#endif\n}\n\n/*\n    Remove a \\a path from the watcher\n\n    \\sa listed()\n*/\nvoid QFileInfoGatherer::removePath(const QString &path)\n{\n#if QT_CONFIG(filesystemwatcher)\n    QMutexLocker locker(&mutex);\n    unwatchPaths(QStringList(path));\n#else\n    Q_UNUSED(path);\n#endif\n}\n\n/*\n    List all files in \\a directoryPath\n\n    \\sa listed()\n*/\nvoid QFileInfoGatherer::list(const QString &directoryPath)\n{\n    fetchExtendedInformation(directoryPath, QStringList());\n}\n\n/*\n    Until aborted wait to fetch a directory or files\n*/\nvoid QFileInfoGatherer::run()\n{\n    forever {\n        // Disallow termination while we are holding a mutex or can be\n        // woken up cleanly.\n        setTerminationEnabled(false);\n        QMutexLocker locker(&mutex);\n        while (!isInterruptionRequested() && path.isEmpty())\n            condition.wait(&mutex);\n        if (isInterruptionRequested())\n            return;\n        const QString thisPath = std::as_const(path).front();\n        path.pop_front();\n        const QStringList thisList = std::as_const(files).front();\n        files.pop_front();\n        locker.unlock();\n\n        // Some of the system APIs we call when gathering file infomration\n        // might hang (e.g. waiting for network), so we explicitly allow\n        // termination now.\n        setTerminationEnabled(true);\n        getFileInfos(thisPath, thisList);\n    }\n}\n\nQExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const\n{\n    QExtendedInformation info(fileInfo);\n    if (m_iconProvider) {\n        info.icon = m_iconProvider->icon(fileInfo);\n        info.displayType = m_iconProvider->type(fileInfo);\n    } else {\n        info.displayType = QAbstractFileIconProviderPrivate::getFileType(fileInfo);\n    }\n#if QT_CONFIG(filesystemwatcher)\n    // ### Not ready to listen all modifications by default\n    static const bool watchFiles = qEnvironmentVariableIsSet(\"QT_FILESYSTEMMODEL_WATCH_FILES\");\n    if (watchFiles) {\n        if (!fileInfo.exists() && !fileInfo.isSymLink()) {\n            const_cast<QFileInfoGatherer *>(this)->\n                unwatchPaths(QStringList(fileInfo.absoluteFilePath()));\n        } else {\n            const QString path = fileInfo.absoluteFilePath();\n            if (!path.isEmpty() && fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable()\n                && !watchedFiles().contains(path)) {\n                const_cast<QFileInfoGatherer *>(this)->watchPaths(QStringList(path));\n            }\n        }\n    }\n#endif // filesystemwatcher\n\n#ifdef Q_OS_WIN\n    if (m_resolveSymlinks && info.isSymLink(/* ignoreNtfsSymLinks = */ true)) {\n        QFileInfo resolvedInfo(QFileInfo(fileInfo.symLinkTarget()).canonicalFilePath());\n        if (resolvedInfo.exists()) {\n            emit nameResolved(fileInfo.filePath(), resolvedInfo.fileName());\n        }\n    }\n#endif\n    return info;\n}\n\n/*\n    Get specific file info's, batch the files so update when we have 100\n    items and every 200ms after that\n */\nvoid QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &files)\n{\n    // List drives\n    if (path.isEmpty()) {\n#ifdef QT_BUILD_INTERNAL\n        fetchedRoot.storeRelaxed(true);\n#endif\n        QList<std::pair<QString, QFileInfo>> updatedFiles;\n        auto addToUpdatedFiles = [&updatedFiles](QFileInfo &&fileInfo) {\n            fileInfo.stat();\n            updatedFiles.emplace_back(std::pair{translateDriveName(fileInfo), fileInfo});\n        };\n\n        if (files.isEmpty()) {\n            // QDir::drives() calls QFSFileEngine::drives() which creates the QFileInfoList on\n            // the stack and return it, so this list is not shared, so no detaching.\n            QFileInfoList infoList = QDir::drives();\n            updatedFiles.reserve(infoList.size());\n            for (auto rit = infoList.rbegin(), rend = infoList.rend(); rit != rend; ++rit)\n                addToUpdatedFiles(std::move(*rit));\n        } else {\n            updatedFiles.reserve(files.size());\n            for (auto rit = files.crbegin(), rend = files.crend(); rit != rend; ++rit)\n                addToUpdatedFiles(QFileInfo(*rit));\n        }\n        emit updates(path, updatedFiles);\n        return;\n    }\n\n    QElapsedTimer base;\n    base.start();\n    QFileInfo fileInfo;\n    bool firstTime = true;\n    QList<std::pair<QString, QFileInfo>> updatedFiles;\n    QStringList filesToCheck = files;\n\n    QStringList allFiles;\n    if (files.isEmpty()) {\n        // Use QDirListing::IteratorFlags when QFileSystemModel is\n        // changed to use them too\n        constexpr auto dirFilters = QDir::AllEntries | QDir::System | QDir::Hidden;\n        for (const auto &dirEntry : QDirListing(path, {}, dirFilters.toInt())) {\n            if (isInterruptionRequested())\n                break;\n            fileInfo = dirEntry.fileInfo();\n            fileInfo.stat();\n            allFiles.append(fileInfo.fileName());\n            fetch(fileInfo, base, firstTime, updatedFiles, path);\n        }\n    }\n    if (!allFiles.isEmpty())\n        emit newListOfFiles(path, allFiles);\n\n    QStringList::const_iterator filesIt = filesToCheck.constBegin();\n    while (!isInterruptionRequested() && filesIt != filesToCheck.constEnd()) {\n        fileInfo.setFile(path + QDir::separator() + *filesIt);\n        ++filesIt;\n        fileInfo.stat();\n        fetch(fileInfo, base, firstTime, updatedFiles, path);\n    }\n    if (!updatedFiles.isEmpty())\n        emit updates(path, updatedFiles);\n    emit directoryLoaded(path);\n}\n\nvoid QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bool &firstTime,\n                              QList<std::pair<QString, QFileInfo>> &updatedFiles, const QString &path)\n{\n    updatedFiles.emplace_back(std::pair(fileInfo.fileName(), fileInfo));\n    QElapsedTimer current;\n    current.start();\n    if ((firstTime && updatedFiles.size() > 100) || base.msecsTo(current) > 1000) {\n        emit updates(path, updatedFiles);\n        updatedFiles.clear();\n        base = current;\n        firstTime = false;\n    }\n}\n\nQT_END_NAMESPACE\n\n#include \"moc_qfileinfogatherer_p.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qfilesystemmodel.cpp",
    "content": "// Copyright (C) 2020 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qfilesystemmodel_p.h\"\n#include \"qfilesystemmodel.h\"\n#include <qabstractfileiconprovider.h>\n#include <qlocale.h>\n#include <qmimedata.h>\n#include <qurl.h>\n#include <qdebug.h>\n#include <QtCore/qcollator.h>\n#if QT_CONFIG(regularexpression)\n#  include <QtCore/qregularexpression.h>\n#endif\n\n#include <algorithm>\n\n#ifdef Q_OS_WIN\n#  include <QtCore/QVarLengthArray>\n#  include <qt_windows.h>\n#  include <shlobj.h>\n#endif\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\n/*!\n    \\enum QFileSystemModel::Roles\n    \\value FileIconRole\n    \\value FilePathRole\n    \\value FileNameRole\n    \\value FilePermissions\n    \\value FileInfoRole The QFileInfo object for the index\n*/\n\n/*!\n    \\class QFileSystemModel\n    \\since 4.4\n\n    \\brief The QFileSystemModel class provides a data model for the local filesystem.\n\n    \\ingroup model-view\n    \\inmodule QtGui\n\n    This class provides access to the local filesystem, providing functions\n    for renaming and removing files and directories, and for creating new\n    directories. In the simplest case, it can be used with a suitable display\n    widget as part of a browser or filter.\n\n    QFileSystemModel can be accessed using the standard interface provided by\n    QAbstractItemModel, but it also provides some convenience functions that are\n    specific to a directory model.\n    The fileInfo(), isDir(), fileName() and filePath() functions provide information\n    about the underlying files and directories related to items in the model.\n    Directories can be created and removed using mkdir(), rmdir().\n\n    \\section1 Example Usage\n\n    A directory model that displays the contents of a default directory\n    is usually constructed with a parent object:\n\n    \\snippet shareddirmodel/main.cpp 2\n\n    A tree view can be used to display the contents of the model\n\n    \\snippet shareddirmodel/main.cpp 4\n\n    and the contents of a particular directory can be displayed by\n    setting the tree view's root index:\n\n    \\snippet shareddirmodel/main.cpp 7\n\n    The view's root index can be used to control how much of a\n    hierarchical model is displayed. QFileSystemModel provides a convenience\n    function that returns a suitable model index for a path to a\n    directory within the model.\n\n    \\section1 Caching and Performance\n\n    QFileSystemModel uses a separate thread to populate itself, so it will not\n    cause the main thread to hang as the file system is being queried. Calls to\n    rowCount() will return \\c 0 until the model populates a directory. The thread\n    in which the QFileSystemModel lives needs to run an event loop to process\n    the incoming data.\n\n    QFileSystemModel will not start populating itself until setRootPath() is\n    called. This prevents any unnecessary querying of the system's root file\n    system, such as enumerating the drives on Windows, until that point.\n\n    QFileSystemModel keeps a cache with file information. The cache is\n    automatically kept up to date using the QFileSystemWatcher.\n\n    \\sa {Model Classes}\n*/\n\n/*!\n    \\fn bool QFileSystemModel::rmdir(const QModelIndex &index)\n\n    Removes the directory corresponding to the model item \\a index in the\n    file system model and \\b{deletes the corresponding directory from the\n    file system}, returning true if successful. If the directory cannot be\n    removed, false is returned.\n\n    \\warning This function deletes directories from the file system; it does\n    \\b{not} move them to a location where they can be recovered.\n\n    \\sa remove()\n*/\n\n/*!\n    \\fn QString QFileSystemModel::fileName(const QModelIndex &index) const\n\n    Returns the file name for the item stored in the model under the given\n    \\a index.\n*/\n\n/*!\n    \\fn QIcon QFileSystemModel::fileIcon(const QModelIndex &index) const\n\n    Returns the icon for the item stored in the model under the given\n    \\a index.\n*/\n\n/*!\n    \\fn QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const\n\n    Returns the QFileInfo for the item stored in the model under the given\n    \\a index.\n*/\nQFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const\n{\n    Q_D(const QFileSystemModel);\n    return d->node(index)->fileInfo();\n}\n\n/*!\n    \\fn void QFileSystemModel::rootPathChanged(const QString &newPath);\n\n    This signal is emitted whenever the root path has been changed to a \\a newPath.\n*/\n\n/*!\n    \\fn void QFileSystemModel::fileRenamed(const QString &path, const QString &oldName, const QString &newName)\n\n    This signal is emitted whenever a file with the \\a oldName is successfully\n    renamed to \\a newName.  The file is located in the directory \\a path.\n*/\n\n/*!\n    \\since 4.7\n    \\fn void QFileSystemModel::directoryLoaded(const QString &path)\n\n    This signal is emitted when the gatherer thread has finished to load the \\a path.\n\n*/\n\n/*!\n    \\fn bool QFileSystemModel::remove(const QModelIndex &index)\n\n    Removes the model item \\a index from the file system model and \\b{deletes the\n    corresponding file from the file system}, returning true if successful. If the\n    item cannot be removed, false is returned.\n\n    \\warning This function deletes files from the file system; it does \\b{not}\n    move them to a location where they can be recovered.\n\n    \\sa rmdir()\n*/\n\nbool QFileSystemModel::remove(const QModelIndex &aindex)\n{\n    Q_D(QFileSystemModel);\n\n    const QString path = d->filePath(aindex);\n    const QFileInfo fileInfo(path);\n#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)\n    // QTBUG-65683: Remove file system watchers prior to deletion to prevent\n    // failure due to locked files on Windows.\n    const QStringList watchedPaths = d->unwatchPathsAt(aindex);\n#endif // filesystemwatcher && Q_OS_WIN\n    const bool success = (fileInfo.isFile() || fileInfo.isSymLink())\n            ? QFile::remove(path) : QDir(path).removeRecursively();\n#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)\n    if (!success)\n        d->watchPaths(watchedPaths);\n#endif // filesystemwatcher && Q_OS_WIN\n    return success;\n}\n\n/*!\n  Constructs a file system model with the given \\a parent.\n*/\nQFileSystemModel::QFileSystemModel(QObject *parent) :\n    QFileSystemModel(*new QFileSystemModelPrivate, parent)\n{\n}\n\n/*!\n    \\internal\n*/\nQFileSystemModel::QFileSystemModel(QFileSystemModelPrivate &dd, QObject *parent)\n    : QAbstractItemModel(dd, parent)\n{\n    Q_D(QFileSystemModel);\n    d->init();\n}\n\n/*!\n  Destroys this file system model.\n*/\nQFileSystemModel::~QFileSystemModel() = default;\n\n/*!\n    \\reimp\n*/\nQModelIndex QFileSystemModel::index(int row, int column, const QModelIndex &parent) const\n{\n    Q_D(const QFileSystemModel);\n    if (row < 0 || column < 0 || row >= rowCount(parent) || column >= columnCount(parent))\n        return QModelIndex();\n\n    // get the parent node\n    QFileSystemModelPrivate::QFileSystemNode *parentNode = (d->indexValid(parent) ? d->node(parent) :\n                                                   const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&d->root));\n    Q_ASSERT(parentNode);\n\n    // now get the internal pointer for the index\n    const int i = d->translateVisibleLocation(parentNode, row);\n    if (i >= parentNode->visibleChildren.size())\n        return QModelIndex();\n    const QString &childName = parentNode->visibleChildren.at(i);\n    const QFileSystemModelPrivate::QFileSystemNode *indexNode = parentNode->children.value(childName);\n    Q_ASSERT(indexNode);\n\n    return createIndex(row, column, const_cast<QFileSystemModelPrivate::QFileSystemNode*>(indexNode));\n}\n\n/*!\n    \\reimp\n*/\nQModelIndex QFileSystemModel::sibling(int row, int column, const QModelIndex &idx) const\n{\n    if (row == idx.row() && column < columnCount(idx.parent())) {\n        // cheap sibling operation: just adjust the column:\n        return createIndex(row, column, idx.internalPointer());\n    } else {\n        // for anything else: call the default implementation\n        // (this could probably be optimized, too):\n        return QAbstractItemModel::sibling(row, column, idx);\n    }\n}\n\n/*!\n    \\overload\n\n    Returns the model item index for the given \\a path and \\a column.\n*/\nQModelIndex QFileSystemModel::index(const QString &path, int column) const\n{\n    Q_D(const QFileSystemModel);\n    QFileSystemModelPrivate::QFileSystemNode *node = d->node(path, false);\n    return d->index(node, column);\n}\n\n/*!\n    \\internal\n\n    Return the QFileSystemNode that goes to index.\n  */\nQFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QModelIndex &index) const\n{\n    if (!index.isValid())\n        return const_cast<QFileSystemNode*>(&root);\n    QFileSystemModelPrivate::QFileSystemNode *indexNode = static_cast<QFileSystemModelPrivate::QFileSystemNode*>(index.internalPointer());\n    Q_ASSERT(indexNode);\n    return indexNode;\n}\n\n#ifdef Q_OS_WIN32\nstatic QString qt_GetLongPathName(const QString &strShortPath)\n{\n    if (strShortPath.isEmpty()\n        || strShortPath == \".\"_L1 || strShortPath == \"..\"_L1)\n        return strShortPath;\n    if (strShortPath.length() == 2 && strShortPath.endsWith(u':'))\n        return strShortPath.toUpper();\n    const QString absPath = QDir(strShortPath).absolutePath();\n    if (absPath.startsWith(\"//\"_L1)\n        || absPath.startsWith(\"\\\\\\\\\"_L1)) // unc\n        return QDir::fromNativeSeparators(absPath);\n    if (absPath.startsWith(u'/'))\n        return QString();\n    const QString inputString = \"\\\\\\\\?\\\\\"_L1 + QDir::toNativeSeparators(absPath);\n    QVarLengthArray<TCHAR, MAX_PATH> buffer(MAX_PATH);\n    DWORD result = ::GetLongPathName((wchar_t*)inputString.utf16(),\n                                     buffer.data(),\n                                     buffer.size());\n    if (result > DWORD(buffer.size())) {\n        buffer.resize(result);\n        result = ::GetLongPathName((wchar_t*)inputString.utf16(),\n                                   buffer.data(),\n                                   buffer.size());\n    }\n    if (result > 4) {\n        QString longPath = QString::fromWCharArray(buffer.data() + 4); // ignoring prefix\n        longPath[0] = longPath.at(0).toUpper(); // capital drive letters\n        return QDir::fromNativeSeparators(longPath);\n    } else {\n        return QDir::fromNativeSeparators(strShortPath);\n    }\n}\n\nstatic inline void chopSpaceAndDot(QString &element)\n{\n    if (element == \".\"_L1 || element == \"..\"_L1)\n        return;\n    // On Windows, \"filename    \" and \"filename\" are equivalent and\n    // \"filename  .  \" and \"filename\" are equivalent\n    // \"filename.......\" and \"filename\" are equivalent Task #133928\n    // whereas \"filename  .txt\" is still \"filename  .txt\"\n    while (element.endsWith(u'.') || element.endsWith(u' '))\n        element.chop(1);\n\n    // If a file is saved as ' Foo.txt', where the leading character(s)\n    // is an ASCII Space (0x20), it will be saved to the file system as 'Foo.txt'.\n    while (element.startsWith(u' '))\n        element.remove(0, 1);\n}\n\n#endif\n\n/*!\n    \\internal\n\n    Given a path return the matching QFileSystemNode or &root if invalid\n*/\nQFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QString &path, bool fetch) const\n{\n    Q_Q(const QFileSystemModel);\n    Q_UNUSED(q);\n    if (path.isEmpty() || path == myComputer() || path.startsWith(u':'))\n        return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);\n\n    // Construct the nodes up to the new root path if they need to be built\n    QString absolutePath;\n#ifdef Q_OS_WIN32\n    QString longPath = qt_GetLongPathName(path);\n#else\n    QString longPath = path;\n#endif\n    if (longPath == rootDir.path())\n        absolutePath = rootDir.absolutePath();\n    else\n        absolutePath = QDir(longPath).absolutePath();\n\n    // ### TODO can we use bool QAbstractFileEngine::caseSensitive() const?\n    QStringList pathElements = absolutePath.split(u'/', Qt::SkipEmptyParts);\n    if ((pathElements.isEmpty())\n#if !defined(Q_OS_WIN)\n        && QDir::fromNativeSeparators(longPath) != \"/\"_L1\n#endif\n        )\n        return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);\n    QModelIndex index = QModelIndex(); // start with \"My Computer\"\n    QString elementPath;\n    QChar separator = u'/';\n    QString trailingSeparator;\n#if defined(Q_OS_WIN)\n    if (absolutePath.startsWith(\"//\"_L1)) { // UNC path\n        QString host = \"\\\\\\\\\"_L1 + pathElements.constFirst();\n        if (absolutePath == QDir::fromNativeSeparators(host))\n            absolutePath.append(u'/');\n        if (longPath.endsWith(u'/') && !absolutePath.endsWith(u'/'))\n            absolutePath.append(u'/');\n        if (absolutePath.endsWith(u'/'))\n            trailingSeparator = \"\\\\\"_L1;\n        int r = 0;\n        auto rootNode = const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);\n        auto it = root.children.constFind(host);\n        if (it != root.children.cend()) {\n            host = it.key(); // Normalize case for lookup in visibleLocation()\n        } else {\n            if (pathElements.count() == 1 && !absolutePath.endsWith(u'/'))\n                return rootNode;\n            QFileInfo info(host);\n            if (!info.exists())\n                return rootNode;\n            QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);\n            p->addNode(rootNode, host,info);\n            p->addVisibleFiles(rootNode, QStringList(host));\n        }\n        r = rootNode->visibleLocation(host);\n        r = translateVisibleLocation(rootNode, r);\n        index = q->index(r, 0, QModelIndex());\n        pathElements.pop_front();\n        separator = u'\\\\';\n        elementPath = host;\n        elementPath.append(separator);\n    } else {\n        if (!pathElements.at(0).contains(u':')) {\n            QString rootPath = QDir(longPath).rootPath();\n            pathElements.prepend(rootPath);\n        }\n        if (pathElements.at(0).endsWith(u'/'))\n            pathElements[0].chop(1);\n    }\n#else\n    // add the \"/\" item, since it is a valid path element on Unix\n    if (absolutePath[0] == u'/')\n        pathElements.prepend(\"/\"_L1);\n#endif\n\n    QFileSystemModelPrivate::QFileSystemNode *parent = node(index);\n\n    for (int i = 0; i < pathElements.size(); ++i) {\n        QString element = pathElements.at(i);\n        if (i != 0)\n            elementPath.append(separator);\n        elementPath.append(element);\n        if (i == pathElements.size() - 1)\n            elementPath.append(trailingSeparator);\n#ifdef Q_OS_WIN\n        // If after stripping the characters there is nothing left then we\n        // just return the parent directory as it is assumed that the path\n        // is referring to the parent.\n        chopSpaceAndDot(element);\n        // Only filenames that can't possibly exist will be end up being empty\n        if (element.isEmpty())\n            return parent;\n#endif\n        bool alreadyExisted = parent->children.contains(element);\n\n        // we couldn't find the path element, we create a new node since we\n        // _know_ that the path is valid\n        if (alreadyExisted) {\n            if ((parent->children.size() == 0)\n                || (parent->caseSensitive()\n                    && parent->children.value(element)->fileName != element)\n                || (!parent->caseSensitive()\n                    && parent->children.value(element)->fileName.toLower() != element.toLower()))\n                alreadyExisted = false;\n        }\n\n        QFileSystemModelPrivate::QFileSystemNode *node;\n        if (!alreadyExisted) {\n            // Someone might call ::index(\"file://cookie/monster/doesn't/like/veggies\"),\n            // a path that doesn't exists, I.E. don't blindly create directories.\n            QFileInfo info(elementPath);\n            if (!info.exists())\n                return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);\n            QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);\n            node = p->addNode(parent, element,info);\n#if QT_CONFIG(filesystemwatcher)\n            node->populate(fileInfoGatherer->getInfo(info));\n#endif\n        } else {\n            node = parent->children.value(element);\n        }\n\n        Q_ASSERT(node);\n        if (!node->isVisible) {\n            // It has been filtered out\n            if (alreadyExisted && node->hasInformation() && !fetch)\n                return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);\n\n            QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);\n            p->addVisibleFiles(parent, QStringList(element));\n            if (!p->bypassFilters.contains(node))\n                p->bypassFilters[node] = 1;\n            QString dir = q->filePath(this->index(parent));\n            if (!node->hasInformation() && fetch) {\n                Fetching f = { std::move(dir), std::move(element), node };\n                p->toFetch.append(std::move(f));\n                p->fetchingTimer.start(0, const_cast<QFileSystemModel*>(q));\n            }\n        }\n        parent = node;\n    }\n\n    return parent;\n}\n\n/*!\n    \\reimp\n*/\nvoid QFileSystemModel::timerEvent(QTimerEvent *event)\n{\n    Q_D(QFileSystemModel);\n    if (event->timerId() == d->fetchingTimer.timerId()) {\n        d->fetchingTimer.stop();\n#if QT_CONFIG(filesystemwatcher)\n        for (int i = 0; i < d->toFetch.size(); ++i) {\n            const QFileSystemModelPrivate::QFileSystemNode *node = d->toFetch.at(i).node;\n            if (!node->hasInformation()) {\n                d->fileInfoGatherer->fetchExtendedInformation(d->toFetch.at(i).dir,\n                                                 QStringList(d->toFetch.at(i).file));\n            } else {\n                // qDebug(\"yah!, you saved a little gerbil soul\");\n            }\n        }\n#endif\n        d->toFetch.clear();\n    }\n}\n\n/*!\n    Returns \\c true if the model item \\a index represents a directory;\n    otherwise returns \\c false.\n*/\nbool QFileSystemModel::isDir(const QModelIndex &index) const\n{\n    // This function is for public usage only because it could create a file info\n    Q_D(const QFileSystemModel);\n    if (!index.isValid())\n        return true;\n    QFileSystemModelPrivate::QFileSystemNode *n = d->node(index);\n    if (n->hasInformation())\n        return n->isDir();\n    return fileInfo(index).isDir();\n}\n\n/*!\n    Returns the size in bytes of \\a index. If the file does not exist, 0 is returned.\n  */\nqint64 QFileSystemModel::size(const QModelIndex &index) const\n{\n    Q_D(const QFileSystemModel);\n    if (!index.isValid())\n        return 0;\n    return d->node(index)->size();\n}\n\n/*!\n    Returns the type of file \\a index such as \"Directory\" or \"JPEG file\".\n  */\nQString QFileSystemModel::type(const QModelIndex &index) const\n{\n    Q_D(const QFileSystemModel);\n    if (!index.isValid())\n        return QString();\n    return d->node(index)->type();\n}\n\n/*!\n    Returns the date and time (in local time) when \\a index was last modified.\n\n    This is an overloaded function, equivalent to calling:\n    \\code\n    lastModified(index, QTimeZone::LocalTime);\n    \\endcode\n\n    If \\a index is invalid, a default constructed QDateTime is returned.\n */\nQDateTime QFileSystemModel::lastModified(const QModelIndex &index) const\n{\n    return lastModified(index, QTimeZone::LocalTime);\n}\n\n/*!\n    \\since 6.6\n    Returns the date and time, in the time zone \\a tz, when\n    \\a index was last modified.\n\n    Typical arguments for \\a tz are \\c QTimeZone::UTC or \\c QTimeZone::LocalTime.\n    UTC does not require any conversion from the time returned by the native file\n    system API, therefore getting the time in UTC is potentially faster. LocalTime\n    is typically chosen if the time is shown to the user.\n\n    If \\a index is invalid, a default constructed QDateTime is returned.\n */\nQDateTime QFileSystemModel::lastModified(const QModelIndex &index, const QTimeZone &tz) const\n{\n    Q_D(const QFileSystemModel);\n    if (!index.isValid())\n        return QDateTime();\n    return d->node(index)->lastModified(tz);\n}\n\n/*!\n    \\reimp\n*/\nQModelIndex QFileSystemModel::parent(const QModelIndex &index) const\n{\n    Q_D(const QFileSystemModel);\n    if (!d->indexValid(index))\n        return QModelIndex();\n\n    QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(index);\n    Q_ASSERT(indexNode != nullptr);\n    QFileSystemModelPrivate::QFileSystemNode *parentNode = indexNode->parent;\n    if (parentNode == nullptr || parentNode == &d->root)\n        return QModelIndex();\n\n    // get the parent's row\n    QFileSystemModelPrivate::QFileSystemNode *grandParentNode = parentNode->parent;\n    Q_ASSERT(grandParentNode->children.contains(parentNode->fileName));\n    int visualRow = d->translateVisibleLocation(grandParentNode, grandParentNode->visibleLocation(grandParentNode->children.value(parentNode->fileName)->fileName));\n    if (visualRow == -1)\n        return QModelIndex();\n    return createIndex(visualRow, 0, parentNode);\n}\n\n/*\n    \\internal\n\n    return the index for node\n*/\nQModelIndex QFileSystemModelPrivate::index(const QFileSystemModelPrivate::QFileSystemNode *node, int column) const\n{\n    Q_Q(const QFileSystemModel);\n    QFileSystemModelPrivate::QFileSystemNode *parentNode = (node ? node->parent : nullptr);\n    if (node == &root || !parentNode)\n        return QModelIndex();\n\n    // get the parent's row\n    Q_ASSERT(node);\n    if (!node->isVisible)\n        return QModelIndex();\n\n    int visualRow = translateVisibleLocation(parentNode, parentNode->visibleLocation(node->fileName));\n    return q->createIndex(visualRow, column, const_cast<QFileSystemNode*>(node));\n}\n\n/*!\n    \\reimp\n*/\nbool QFileSystemModel::hasChildren(const QModelIndex &parent) const\n{\n    Q_D(const QFileSystemModel);\n    if (parent.column() > 0)\n        return false;\n\n    if (!parent.isValid()) // drives\n        return true;\n\n    const QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent);\n    Q_ASSERT(indexNode);\n    return (indexNode->isDir());\n}\n\n/*!\n    \\reimp\n */\nbool QFileSystemModel::canFetchMore(const QModelIndex &parent) const\n{\n    Q_D(const QFileSystemModel);\n    if (!d->setRootPath)\n        return false;\n    const QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent);\n    return (!indexNode->populatedChildren);\n}\n\n/*!\n    \\reimp\n */\nvoid QFileSystemModel::fetchMore(const QModelIndex &parent)\n{\n    Q_D(QFileSystemModel);\n    if (!d->setRootPath)\n        return;\n    QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent);\n    if (indexNode->populatedChildren)\n        return;\n    indexNode->populatedChildren = true;\n#if QT_CONFIG(filesystemwatcher)\n    d->fileInfoGatherer->list(filePath(parent));\n#endif\n}\n\n/*!\n    \\reimp\n*/\nint QFileSystemModel::rowCount(const QModelIndex &parent) const\n{\n    Q_D(const QFileSystemModel);\n    if (parent.column() > 0)\n        return 0;\n\n    if (!parent.isValid())\n        return d->root.visibleChildren.size();\n\n    const QFileSystemModelPrivate::QFileSystemNode *parentNode = d->node(parent);\n    return parentNode->visibleChildren.size();\n}\n\n/*!\n    \\reimp\n*/\nint QFileSystemModel::columnCount(const QModelIndex &parent) const\n{\n    return (parent.column() > 0) ? 0 : QFileSystemModelPrivate::NumColumns;\n}\n\n/*!\n    Returns the data stored under the given \\a role for the item \"My Computer\".\n\n    \\sa Qt::ItemDataRole\n */\nQVariant QFileSystemModel::myComputer(int role) const\n{\n#if QT_CONFIG(filesystemwatcher)\n    Q_D(const QFileSystemModel);\n#endif\n    switch (role) {\n    case Qt::DisplayRole:\n        return QFileSystemModelPrivate::myComputer();\n#if QT_CONFIG(filesystemwatcher)\n    case Qt::DecorationRole:\n        if (auto *provider = d->fileInfoGatherer->iconProvider())\n            return provider->icon(QAbstractFileIconProvider::Computer);\n    break;\n#endif\n    }\n    return QVariant();\n}\n\n/*!\n    \\reimp\n*/\nQVariant QFileSystemModel::data(const QModelIndex &index, int role) const\n{\n    Q_D(const QFileSystemModel);\n    if (!index.isValid() || index.model() != this)\n        return QVariant();\n\n    switch (role) {\n    case Qt::EditRole:\n        if (index.column() == QFileSystemModelPrivate::NameColumn)\n            return d->name(index);\n        Q_FALLTHROUGH();\n    case Qt::DisplayRole:\n        switch (index.column()) {\n        case QFileSystemModelPrivate::NameColumn: return d->displayName(index);\n        case QFileSystemModelPrivate::SizeColumn: return d->size(index);\n        case QFileSystemModelPrivate::TypeColumn: return d->type(index);\n        case QFileSystemModelPrivate::TimeColumn: return d->time(index);\n        default:\n            qWarning(\"data: invalid display value column %d\", index.column());\n            break;\n        }\n        break;\n    case FilePathRole:\n        return filePath(index);\n    case FileNameRole:\n        return d->name(index);\n    case FileInfoRole:\n        return QVariant::fromValue(fileInfo(index));\n    case Qt::DecorationRole:\n        if (index.column() == QFileSystemModelPrivate::NameColumn) {\n            QIcon icon = d->icon(index);\n#if QT_CONFIG(filesystemwatcher)\n            if (icon.isNull()) {\n                using P = QAbstractFileIconProvider;\n                if (auto *provider = d->fileInfoGatherer->iconProvider())\n                    icon = provider->icon(d->node(index)->isDir() ? P::Folder: P::File);\n            }\n#endif // filesystemwatcher\n            return icon;\n        }\n        break;\n    case Qt::TextAlignmentRole:\n        if (index.column() == QFileSystemModelPrivate::SizeColumn)\n            return QVariant(Qt::AlignTrailing | Qt::AlignVCenter);\n        break;\n    case FilePermissions:\n        int p = permissions(index);\n        return p;\n    }\n\n    return QVariant();\n}\n\n/*!\n    \\internal\n*/\nQString QFileSystemModelPrivate::size(const QModelIndex &index) const\n{\n    if (!index.isValid())\n        return QString();\n    const QFileSystemNode *n = node(index);\n    if (n->isDir()) {\n#ifdef Q_OS_MAC\n        return \"--\"_L1;\n#else\n        return \"\"_L1;\n#endif\n    // Windows   - \"\"\n    // OS X      - \"--\"\n    // Konqueror - \"4 KB\"\n    // Nautilus  - \"9 items\" (the number of children)\n    }\n    return size(n->size());\n}\n\nQString QFileSystemModelPrivate::size(qint64 bytes)\n{\n    return QLocale::system().formattedDataSize(bytes);\n}\n\n/*!\n    \\internal\n*/\nQString QFileSystemModelPrivate::time(const QModelIndex &index) const\n{\n    if (!index.isValid())\n        return QString();\n#if QT_CONFIG(datestring)\n    return QLocale::system().toString(node(index)->lastModified(QTimeZone::LocalTime), QLocale::ShortFormat);\n#else\n    Q_UNUSED(index);\n    return QString();\n#endif\n}\n\n/*\n    \\internal\n*/\nQString QFileSystemModelPrivate::type(const QModelIndex &index) const\n{\n    if (!index.isValid())\n        return QString();\n    return node(index)->type();\n}\n\n/*!\n    \\internal\n*/\nQString QFileSystemModelPrivate::name(const QModelIndex &index) const\n{\n    if (!index.isValid())\n        return QString();\n    QFileSystemNode *dirNode = node(index);\n    if (\n#if QT_CONFIG(filesystemwatcher)\n        fileInfoGatherer->resolveSymlinks() &&\n#endif\n        !resolvedSymLinks.isEmpty() && dirNode->isSymLink(/* ignoreNtfsSymLinks = */ true)) {\n        QString fullPath = QDir::fromNativeSeparators(filePath(index));\n        return resolvedSymLinks.value(fullPath, dirNode->fileName);\n    }\n    return dirNode->fileName;\n}\n\n/*!\n    \\internal\n*/\nQString QFileSystemModelPrivate::displayName(const QModelIndex &index) const\n{\n#if defined(Q_OS_WIN)\n    QFileSystemNode *dirNode = node(index);\n    if (!dirNode->volumeName.isEmpty())\n        return dirNode->volumeName;\n#endif\n    return name(index);\n}\n\n/*!\n    \\internal\n*/\nQIcon QFileSystemModelPrivate::icon(const QModelIndex &index) const\n{\n    if (!index.isValid())\n        return QIcon();\n    return node(index)->icon();\n}\n\n/*!\n    \\reimp\n*/\nbool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, int role)\n{\n    Q_D(QFileSystemModel);\n    if (!idx.isValid()\n        || idx.column() != 0\n        || role != Qt::EditRole\n        || (flags(idx) & Qt::ItemIsEditable) == 0) {\n        return false;\n    }\n\n    QString newName = value.toString();\n#ifdef Q_OS_WIN\n    chopSpaceAndDot(newName);\n    if (newName.isEmpty())\n        return false;\n#endif\n\n    QString oldName = idx.data().toString();\n    if (newName == oldName)\n        return true;\n\n    const QString parentPath = filePath(parent(idx));\n\n    if (newName.isEmpty() || QDir::toNativeSeparators(newName).contains(QDir::separator()))\n        return false;\n\n#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)\n    // QTBUG-65683: Remove file system watchers prior to renaming to prevent\n    // failure due to locked files on Windows.\n    const QStringList watchedPaths = d->unwatchPathsAt(idx);\n#endif // filesystemwatcher && Q_OS_WIN\n    if (!QDir(parentPath).rename(oldName, newName)) {\n#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)\n        d->watchPaths(watchedPaths);\n#endif\n        return false;\n    } else {\n        /*\n            *After re-naming something we don't want the selection to change*\n            - can't remove rows and later insert\n            - can't quickly remove and insert\n            - index pointer can't change because treeview doesn't use persistent index's\n\n            - if this get any more complicated think of changing it to just\n              use layoutChanged\n         */\n\n        QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(idx);\n        QFileSystemModelPrivate::QFileSystemNode *parentNode = indexNode->parent;\n        int visibleLocation = parentNode->visibleLocation(parentNode->children.value(indexNode->fileName)->fileName);\n\n        parentNode->visibleChildren.removeAt(visibleLocation);\n        std::unique_ptr<QFileSystemModelPrivate::QFileSystemNode> nodeToRename(parentNode->children.take(oldName));\n        nodeToRename->fileName = newName;\n        nodeToRename->parent = parentNode;\n#if QT_CONFIG(filesystemwatcher)\n        nodeToRename->populate(d->fileInfoGatherer->getInfo(QFileInfo(parentPath, newName)));\n#endif\n        nodeToRename->isVisible = true;\n        parentNode->children[newName] = nodeToRename.release();\n        parentNode->visibleChildren.insert(visibleLocation, newName);\n\n        d->delayedSort();\n        emit fileRenamed(parentPath, oldName, newName);\n    }\n    return true;\n}\n\n/*!\n    \\reimp\n*/\nQVariant QFileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const\n{\n    switch (role) {\n    case Qt::DecorationRole:\n        if (section == 0) {\n            // ### TODO oh man this is ugly and doesn't even work all the way!\n            // it is still 2 pixels off\n            QImage pixmap(16, 1, QImage::Format_ARGB32_Premultiplied);\n            pixmap.fill(Qt::transparent);\n            return pixmap;\n        }\n        break;\n    case Qt::TextAlignmentRole:\n        return Qt::AlignLeft;\n    }\n\n    if (orientation != Qt::Horizontal || role != Qt::DisplayRole)\n        return QAbstractItemModel::headerData(section, orientation, role);\n\n    QString returnValue;\n    switch (section) {\n    case QFileSystemModelPrivate::NameColumn:\n        returnValue = tr(\"Name\");\n        break;\n    case QFileSystemModelPrivate::SizeColumn:\n        returnValue = tr(\"Size\");\n        break;\n    case QFileSystemModelPrivate::TypeColumn:\n        returnValue =\n#ifdef Q_OS_MAC\n                    tr(\"Kind\", \"Match OS X Finder\");\n#else\n                    tr(\"Type\", \"All other platforms\");\n#endif\n        break;\n    // Windows   - Type\n    // OS X      - Kind\n    // Konqueror - File Type\n    // Nautilus  - Type\n    case QFileSystemModelPrivate::TimeColumn:\n        returnValue = tr(\"Date Modified\");\n        break;\n    default: return QVariant();\n    }\n    return returnValue;\n}\n\n/*!\n    \\reimp\n*/\nQt::ItemFlags QFileSystemModel::flags(const QModelIndex &index) const\n{\n    Q_D(const QFileSystemModel);\n    Qt::ItemFlags flags = QAbstractItemModel::flags(index);\n    if (!index.isValid())\n        return flags;\n\n    QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(index);\n    if (d->nameFilterDisables && !d->passNameFilters(indexNode)) {\n        flags &= ~Qt::ItemIsEnabled;\n        // ### TODO you shouldn't be able to set this as the current item, task 119433\n        return flags;\n    }\n\n    flags |= Qt::ItemIsDragEnabled;\n\n    if (!indexNode->isDir())\n        flags |= Qt::ItemNeverHasChildren;\n    if (d->readOnly)\n        return flags;\n    if ((index.column() == 0) && indexNode->permissions() & QFile::WriteUser) {\n        flags |= Qt::ItemIsEditable;\n        if (indexNode->isDir())\n            flags |= Qt::ItemIsDropEnabled;\n    }\n    return flags;\n}\n\n/*!\n    \\internal\n*/\nvoid QFileSystemModelPrivate::performDelayedSort()\n{\n    Q_Q(QFileSystemModel);\n    q->sort(sortColumn, sortOrder);\n}\n\n\n/*\n    \\internal\n    Helper functor used by sort()\n*/\nclass QFileSystemModelSorter\n{\npublic:\n    inline QFileSystemModelSorter(int column) : sortColumn(column)\n    {\n        naturalCompare.setNumericMode(true);\n        naturalCompare.setCaseSensitivity(Qt::CaseInsensitive);\n    }\n\n    bool compareNodes(const QFileSystemModelPrivate::QFileSystemNode *l,\n                    const QFileSystemModelPrivate::QFileSystemNode *r) const\n    {\n        switch (sortColumn) {\n        case QFileSystemModelPrivate::NameColumn: {\n#ifndef Q_OS_MAC\n            // place directories before files\n            bool left = l->isDir();\n            bool right = r->isDir();\n            if (left ^ right)\n                return left;\n#endif\n            return naturalCompare.compare(l->fileName, r->fileName) < 0;\n                }\n        case QFileSystemModelPrivate::SizeColumn:\n        {\n            // Directories go first\n            bool left = l->isDir();\n            bool right = r->isDir();\n            if (left ^ right)\n                return left;\n\n            qint64 sizeDifference = l->size() - r->size();\n            if (sizeDifference == 0)\n                return naturalCompare.compare(l->fileName, r->fileName) < 0;\n\n            return sizeDifference < 0;\n        }\n        case QFileSystemModelPrivate::TypeColumn:\n        {\n            int compare = naturalCompare.compare(l->type(), r->type());\n            if (compare == 0)\n                return naturalCompare.compare(l->fileName, r->fileName) < 0;\n\n            return compare < 0;\n        }\n        case QFileSystemModelPrivate::TimeColumn:\n        {\n            const QDateTime left = l->lastModified(QTimeZone::UTC);\n            const QDateTime right = r->lastModified(QTimeZone::UTC);\n            if (left == right)\n                return naturalCompare.compare(l->fileName, r->fileName) < 0;\n\n            return left < right;\n        }\n        }\n        Q_ASSERT(false);\n        return false;\n    }\n\n    bool operator()(const QFileSystemModelPrivate::QFileSystemNode *l,\n                    const QFileSystemModelPrivate::QFileSystemNode *r) const\n    {\n        return compareNodes(l, r);\n    }\n\n\nprivate:\n    QCollator naturalCompare;\n    int sortColumn;\n};\n\n/*\n    \\internal\n\n    Sort all of the children of parent\n*/\nvoid QFileSystemModelPrivate::sortChildren(int column, const QModelIndex &parent)\n{\n    Q_Q(QFileSystemModel);\n    QFileSystemModelPrivate::QFileSystemNode *indexNode = node(parent);\n    if (indexNode->children.size() == 0)\n        return;\n\n    QList<QFileSystemModelPrivate::QFileSystemNode *> values;\n\n    for (auto iterator = indexNode->children.constBegin(), cend = indexNode->children.constEnd(); iterator != cend; ++iterator) {\n        if (filtersAcceptsNode(iterator.value())) {\n            values.append(iterator.value());\n        } else {\n            iterator.value()->isVisible = false;\n        }\n    }\n    QFileSystemModelSorter ms(column);\n    std::sort(values.begin(), values.end(), ms);\n    // First update the new visible list\n    indexNode->visibleChildren.clear();\n    //No more dirty item we reset our internal dirty index\n    indexNode->dirtyChildrenIndex = -1;\n    indexNode->visibleChildren.reserve(values.size());\n    for (QFileSystemNode *node : std::as_const(values)) {\n        indexNode->visibleChildren.append(node->fileName);\n        node->isVisible = true;\n    }\n\n    if (!disableRecursiveSort) {\n        for (int i = 0; i < q->rowCount(parent); ++i) {\n            const QModelIndex childIndex = q->index(i, 0, parent);\n            QFileSystemModelPrivate::QFileSystemNode *indexNode = node(childIndex);\n            //Only do a recursive sort on visible nodes\n            if (indexNode->isVisible)\n                sortChildren(column, childIndex);\n        }\n    }\n}\n\n/*!\n    \\reimp\n*/\nvoid QFileSystemModel::sort(int column, Qt::SortOrder order)\n{\n    Q_D(QFileSystemModel);\n    if (d->sortOrder == order && d->sortColumn == column && !d->forceSort)\n        return;\n\n    emit layoutAboutToBeChanged();\n    QModelIndexList oldList = persistentIndexList();\n    QList<std::pair<QFileSystemModelPrivate::QFileSystemNode *, int>> oldNodes;\n    oldNodes.reserve(oldList.size());\n    for (const QModelIndex &oldNode : oldList)\n        oldNodes.emplace_back(d->node(oldNode), oldNode.column());\n\n    if (!(d->sortColumn == column && d->sortOrder != order && !d->forceSort)) {\n        //we sort only from where we are, don't need to sort all the model\n        d->sortChildren(column, index(rootPath()));\n        d->sortColumn = column;\n        d->forceSort = false;\n    }\n    d->sortOrder = order;\n\n    QModelIndexList newList;\n    newList.reserve(oldNodes.size());\n    for (const auto &[node, col]: std::as_const(oldNodes))\n        newList.append(d->index(node, col));\n\n    changePersistentIndexList(oldList, newList);\n    emit layoutChanged({}, VerticalSortHint);\n}\n\n/*!\n    Returns a list of MIME types that can be used to describe a list of items\n    in the model.\n*/\nQStringList QFileSystemModel::mimeTypes() const\n{\n    return QStringList(\"text/uri-list\"_L1);\n}\n\n/*!\n    Returns an object that contains a serialized description of the specified\n    \\a indexes. The format used to describe the items corresponding to the\n    indexes is obtained from the mimeTypes() function.\n\n    If the list of indexes is empty, \\nullptr is returned rather than a\n    serialized empty list.\n*/\nQMimeData *QFileSystemModel::mimeData(const QModelIndexList &indexes) const\n{\n    QList<QUrl> urls;\n    QList<QModelIndex>::const_iterator it = indexes.begin();\n    for (; it != indexes.end(); ++it)\n        if ((*it).column() == QFileSystemModelPrivate::NameColumn)\n            urls << QUrl::fromLocalFile(filePath(*it));\n    QMimeData *data = new QMimeData();\n    data->setUrls(urls);\n    return data;\n}\n\n/*!\n    Handles the \\a data supplied by a drag and drop operation that ended with\n    the given \\a action over the row in the model specified by the \\a row and\n    \\a column and by the \\a parent index. Returns true if the operation was\n    successful.\n\n    \\sa supportedDropActions()\n*/\nbool QFileSystemModel::dropMimeData(const QMimeData *data, Qt::DropAction action,\n                             int row, int column, const QModelIndex &parent)\n{\n    Q_UNUSED(row);\n    Q_UNUSED(column);\n    if (!parent.isValid() || isReadOnly())\n        return false;\n\n    bool success = true;\n    QString to = filePath(parent) + QDir::separator();\n\n    QList<QUrl> urls = data->urls();\n    QList<QUrl>::const_iterator it = urls.constBegin();\n\n    switch (action) {\n    case Qt::CopyAction:\n        for (; it != urls.constEnd(); ++it) {\n            QString path = (*it).toLocalFile();\n            success = QFile::copy(path, to + QFileInfo(path).fileName()) && success;\n        }\n        break;\n    case Qt::LinkAction:\n        for (; it != urls.constEnd(); ++it) {\n            QString path = (*it).toLocalFile();\n            success = QFile::link(path, to + QFileInfo(path).fileName()) && success;\n        }\n        break;\n    case Qt::MoveAction:\n        for (; it != urls.constEnd(); ++it) {\n            QString path = (*it).toLocalFile();\n            success = QFile::rename(path, to + QFileInfo(path).fileName()) && success;\n        }\n        break;\n    default:\n        return false;\n    }\n\n    return success;\n}\n\n/*!\n    \\reimp\n*/\nQt::DropActions QFileSystemModel::supportedDropActions() const\n{\n    return Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;\n}\n\n/*!\n    \\reimp\n*/\nQHash<int, QByteArray> QFileSystemModel::roleNames() const\n{\n    auto ret = QAbstractItemModel::roleNames();\n    ret.insert(QFileSystemModel::FileIconRole,\n               QByteArrayLiteral(\"fileIcon\")); // == Qt::decoration\n    ret.insert(QFileSystemModel::FilePathRole, QByteArrayLiteral(\"filePath\"));\n    ret.insert(QFileSystemModel::FileNameRole, QByteArrayLiteral(\"fileName\"));\n    ret.insert(QFileSystemModel::FilePermissions, QByteArrayLiteral(\"filePermissions\"));\n    ret.insert(QFileSystemModel::FileInfoRole, QByteArrayLiteral(\"fileInfo\"));\n    return ret;\n}\n\n/*!\n    \\enum QFileSystemModel::Option\n    \\since 5.14\n\n    \\value DontWatchForChanges Do not add file watchers to the paths.\n    This reduces overhead when using the model for simple tasks\n    like line edit completion.\n\n    \\value DontResolveSymlinks Don't resolve symlinks in the file\n    system model. By default, symlinks are resolved.\n\n    \\value DontUseCustomDirectoryIcons Always use the default directory icon.\n    Some platforms allow the user to set a different icon. Custom icon lookup\n    causes a big performance impact over network or removable drives.\n    This sets the QFileIconProvider::DontUseCustomDirectoryIcons\n    option in the icon provider accordingly.\n\n    \\sa resolveSymlinks\n*/\n\n/*!\n    \\since 5.14\n    Sets the given \\a option to be enabled if \\a on is true; otherwise,\n    clears the given \\a option.\n\n    Options should be set before changing properties.\n\n    \\sa options, testOption()\n*/\nvoid QFileSystemModel::setOption(Option option, bool on)\n{\n    QFileSystemModel::Options previousOptions = options();\n    setOptions(previousOptions.setFlag(option, on));\n}\n\n/*!\n    \\since 5.14\n\n    Returns \\c true if the given \\a option is enabled; otherwise, returns\n    false.\n\n    \\sa options, setOption()\n*/\nbool QFileSystemModel::testOption(Option option) const\n{\n    return options().testFlag(option);\n}\n\n/*!\n    \\property QFileSystemModel::options\n    \\brief the various options that affect the model\n    \\since 5.14\n\n    By default, all options are disabled.\n\n    Options should be set before changing properties.\n\n    \\sa setOption(), testOption()\n*/\nvoid QFileSystemModel::setOptions(Options options)\n{\n    const Options changed = (options ^ QFileSystemModel::options());\n\n    if (changed.testFlag(DontResolveSymlinks))\n        setResolveSymlinks(!options.testFlag(DontResolveSymlinks));\n\n#if QT_CONFIG(filesystemwatcher)\n    Q_D(QFileSystemModel);\n    if (changed.testFlag(DontWatchForChanges))\n        d->fileInfoGatherer->setWatching(!options.testFlag(DontWatchForChanges));\n#endif\n\n    if (changed.testFlag(DontUseCustomDirectoryIcons)) {\n        if (auto provider = iconProvider()) {\n            QAbstractFileIconProvider::Options providerOptions = provider->options();\n            providerOptions.setFlag(QAbstractFileIconProvider::DontUseCustomDirectoryIcons,\n                                    options.testFlag(QFileSystemModel::DontUseCustomDirectoryIcons));\n            provider->setOptions(providerOptions);\n        } else {\n            qWarning(\"Setting QFileSystemModel::DontUseCustomDirectoryIcons has no effect when no provider is used\");\n        }\n    }\n}\n\nQFileSystemModel::Options QFileSystemModel::options() const\n{\n    QFileSystemModel::Options result;\n    result.setFlag(DontResolveSymlinks, !resolveSymlinks());\n#if QT_CONFIG(filesystemwatcher)\n    Q_D(const QFileSystemModel);\n    result.setFlag(DontWatchForChanges, !d->fileInfoGatherer->isWatching());\n#else\n    result.setFlag(DontWatchForChanges);\n#endif\n    if (auto provider = iconProvider()) {\n        result.setFlag(DontUseCustomDirectoryIcons,\n                       provider->options().testFlag(QAbstractFileIconProvider::DontUseCustomDirectoryIcons));\n    }\n    return result;\n}\n\n/*!\n    Returns the path of the item stored in the model under the\n    \\a index given.\n*/\nQString QFileSystemModel::filePath(const QModelIndex &index) const\n{\n    Q_D(const QFileSystemModel);\n    QString fullPath = d->filePath(index);\n    QFileSystemModelPrivate::QFileSystemNode *dirNode = d->node(index);\n    if (dirNode->isSymLink()\n#if QT_CONFIG(filesystemwatcher)\n        && d->fileInfoGatherer->resolveSymlinks()\n#endif\n        && d->resolvedSymLinks.contains(fullPath)\n        && dirNode->isDir()) {\n        QFileInfo fullPathInfo(dirNode->fileInfo());\n        if (!dirNode->hasInformation())\n            fullPathInfo = QFileInfo(fullPath);\n        QString canonicalPath = fullPathInfo.canonicalFilePath();\n        auto *canonicalNode = d->node(fullPathInfo.canonicalFilePath(), false);\n        QFileInfo resolvedInfo = canonicalNode->fileInfo();\n        if (!canonicalNode->hasInformation())\n            resolvedInfo = QFileInfo(canonicalPath);\n        if (resolvedInfo.exists())\n            return resolvedInfo.filePath();\n    }\n    return fullPath;\n}\n\nQString QFileSystemModelPrivate::filePath(const QModelIndex &index) const\n{\n    Q_Q(const QFileSystemModel);\n    Q_UNUSED(q);\n    if (!index.isValid())\n        return QString();\n    Q_ASSERT(index.model() == q);\n\n    QStringList path;\n    QModelIndex idx = index;\n    while (idx.isValid()) {\n        QFileSystemModelPrivate::QFileSystemNode *dirNode = node(idx);\n        if (dirNode)\n            path.prepend(dirNode->fileName);\n        idx = idx.parent();\n    }\n    QString fullPath = QDir::fromNativeSeparators(path.join(QDir::separator()));\n#if !defined(Q_OS_WIN)\n    if ((fullPath.size() > 2) && fullPath[0] == u'/' && fullPath[1] == u'/')\n        fullPath = fullPath.mid(1);\n#else\n    if (fullPath.length() == 2 && fullPath.endsWith(u':'))\n        fullPath.append(u'/');\n#endif\n    return fullPath;\n}\n\n/*!\n    Create a directory with the \\a name in the \\a parent model index.\n*/\nQModelIndex QFileSystemModel::mkdir(const QModelIndex &parent, const QString &name)\n{\n    Q_D(QFileSystemModel);\n    if (!parent.isValid())\n        return parent;\n\n    QString fileName = name;\n#ifdef Q_OS_WIN\n    chopSpaceAndDot(fileName);\n    if (fileName.isEmpty())\n        return QModelIndex();\n#endif\n\n    QDir dir(filePath(parent));\n    if (!dir.mkdir(fileName))\n        return QModelIndex();\n    QFileSystemModelPrivate::QFileSystemNode *parentNode = d->node(parent);\n    d->addNode(parentNode, fileName, QFileInfo());\n    Q_ASSERT(parentNode->children.contains(fileName));\n    QFileSystemModelPrivate::QFileSystemNode *node = parentNode->children[fileName];\n#if QT_CONFIG(filesystemwatcher)\n    node->populate(d->fileInfoGatherer->getInfo(QFileInfo(dir.absolutePath() + QDir::separator() + fileName)));\n#endif\n    d->addVisibleFiles(parentNode, QStringList(fileName));\n    return d->index(node);\n}\n\n/*!\n    Returns the complete OR-ed together combination of QFile::Permission for the \\a index.\n */\nQFile::Permissions QFileSystemModel::permissions(const QModelIndex &index) const\n{\n    Q_D(const QFileSystemModel);\n    return d->node(index)->permissions();\n}\n\n/*!\n    Sets the directory that is being watched by the model to \\a newPath by\n    installing a \\l{QFileSystemWatcher}{file system watcher} on it. Any\n    changes to files and directories within this directory will be\n    reflected in the model.\n\n    If the path is changed, the rootPathChanged() signal will be emitted.\n\n    \\note This function does not change the structure of the model or\n    modify the data available to views. In other words, the \"root\" of\n    the model is \\e not changed to include only files and directories\n    within the directory specified by \\a newPath in the file system.\n\n    \\sa {QTreeView::setRootIndex()}, {QtQuick::}{TreeView::rootIndex}\n  */\nQModelIndex QFileSystemModel::setRootPath(const QString &newPath)\n{\n    Q_D(QFileSystemModel);\n#ifdef Q_OS_WIN\n#ifdef Q_OS_WIN32\n    QString longNewPath = qt_GetLongPathName(newPath);\n#else\n    QString longNewPath = QDir::fromNativeSeparators(newPath);\n#endif\n#else\n    QString longNewPath = newPath;\n#endif\n    //we remove .. and . from the given path if exist\n    if (!newPath.isEmpty())\n        longNewPath = QDir::cleanPath(longNewPath);\n\n    d->setRootPath = true;\n\n    //user don't ask for the root path (\"\") but the conversion failed\n    if (!newPath.isEmpty() && longNewPath.isEmpty())\n        return d->index(rootPath());\n\n    if (d->rootDir.path() == longNewPath)\n        return d->index(rootPath());\n\n    auto node = d->node(longNewPath);\n    QFileInfo newPathInfo;\n    if (node && node->hasInformation())\n        newPathInfo = node->fileInfo();\n    else\n        newPathInfo = QFileInfo(longNewPath);\n\n    bool showDrives = (longNewPath.isEmpty() || longNewPath == QFileSystemModelPrivate::myComputer());\n    if (!showDrives && !newPathInfo.exists())\n        return d->index(rootPath());\n\n    //We remove the watcher on the previous path\n    if (!rootPath().isEmpty() && rootPath() != \".\"_L1) {\n        //This remove the watcher for the old rootPath\n#if QT_CONFIG(filesystemwatcher)\n        d->fileInfoGatherer->removePath(rootPath());\n#endif\n        //This line \"marks\" the node as dirty, so the next fetchMore\n        //call on the path will ask the gatherer to install a watcher again\n        //But it doesn't re-fetch everything\n        d->node(rootPath())->populatedChildren = false;\n    }\n\n    // We have a new valid root path\n    d->rootDir = QDir(longNewPath);\n    QModelIndex newRootIndex;\n    if (showDrives) {\n        // otherwise dir will become '.'\n        d->rootDir.setPath(\"\"_L1);\n    } else {\n        newRootIndex = d->index(d->rootDir.path());\n    }\n    fetchMore(newRootIndex);\n    emit rootPathChanged(longNewPath);\n    d->forceSort = true;\n    d->delayedSort();\n    return newRootIndex;\n}\n\n/*!\n    The currently set root path\n\n    \\sa rootDirectory()\n*/\nQString QFileSystemModel::rootPath() const\n{\n    Q_D(const QFileSystemModel);\n    return d->rootDir.path();\n}\n\n/*!\n    The currently set directory\n\n    \\sa rootPath()\n*/\nQDir QFileSystemModel::rootDirectory() const\n{\n    Q_D(const QFileSystemModel);\n    QDir dir(d->rootDir);\n    dir.setNameFilters(nameFilters());\n    dir.setFilter(filter());\n    return dir;\n}\n\n/*!\n    Sets the \\a provider of file icons for the directory model.\n*/\nvoid QFileSystemModel::setIconProvider(QAbstractFileIconProvider *provider)\n{\n    Q_D(QFileSystemModel);\n#if QT_CONFIG(filesystemwatcher)\n    d->fileInfoGatherer->setIconProvider(provider);\n#endif\n    d->root.updateIcon(provider, QString());\n}\n\n/*!\n    Returns the file icon provider for this directory model.\n*/\nQAbstractFileIconProvider *QFileSystemModel::iconProvider() const\n{\n#if QT_CONFIG(filesystemwatcher)\n    Q_D(const QFileSystemModel);\n    return d->fileInfoGatherer->iconProvider();\n#else\n    return nullptr;\n#endif\n}\n\n/*!\n    Sets the directory model's filter to that specified by \\a filters.\n\n    Note that the filter you set should always include the QDir::AllDirs enum value,\n    otherwise QFileSystemModel won't be able to read the directory structure.\n\n    \\sa QDir::Filters\n*/\nvoid QFileSystemModel::setFilter(QDir::Filters filters)\n{\n    Q_D(QFileSystemModel);\n    if (d->filters == filters)\n        return;\n    const bool changingCaseSensitivity =\n        filters.testFlag(QDir::CaseSensitive) != d->filters.testFlag(QDir::CaseSensitive);\n    d->filters = filters;\n    if (changingCaseSensitivity)\n        d->rebuildNameFilterRegexps();\n    d->forceSort = true;\n    d->delayedSort();\n}\n\n/*!\n    Returns the filter specified for the directory model.\n\n    If a filter has not been set, the default filter is QDir::AllEntries |\n    QDir::NoDotAndDotDot | QDir::AllDirs.\n\n    \\sa QDir::Filters\n*/\nQDir::Filters QFileSystemModel::filter() const\n{\n    Q_D(const QFileSystemModel);\n    return d->filters;\n}\n\n/*!\n    \\property QFileSystemModel::resolveSymlinks\n    \\brief Whether the directory model should resolve symbolic links\n\n    This is only relevant on Windows.\n\n    By default, this property is \\c true.\n\n    \\sa QFileSystemModel::Options\n*/\nvoid QFileSystemModel::setResolveSymlinks(bool enable)\n{\n#if QT_CONFIG(filesystemwatcher)\n    Q_D(QFileSystemModel);\n    d->fileInfoGatherer->setResolveSymlinks(enable);\n#else\n    Q_UNUSED(enable);\n#endif\n}\n\nbool QFileSystemModel::resolveSymlinks() const\n{\n#if QT_CONFIG(filesystemwatcher)\n    Q_D(const QFileSystemModel);\n    return d->fileInfoGatherer->resolveSymlinks();\n#else\n    return false;\n#endif\n}\n\n/*!\n    \\property QFileSystemModel::readOnly\n    \\brief Whether the directory model allows writing to the file system\n\n    If this property is set to false, the directory model will allow renaming, copying\n    and deleting of files and directories.\n\n    This property is \\c true by default\n*/\nvoid QFileSystemModel::setReadOnly(bool enable)\n{\n    Q_D(QFileSystemModel);\n    d->readOnly = enable;\n}\n\nbool QFileSystemModel::isReadOnly() const\n{\n    Q_D(const QFileSystemModel);\n    return d->readOnly;\n}\n\n/*!\n    \\property QFileSystemModel::nameFilterDisables\n    \\brief Whether files that don't pass the name filter are hidden or disabled\n\n    This property is \\c true by default\n*/\nvoid QFileSystemModel::setNameFilterDisables(bool enable)\n{\n    Q_D(QFileSystemModel);\n    if (d->nameFilterDisables == enable)\n        return;\n    d->nameFilterDisables = enable;\n    d->forceSort = true;\n    d->delayedSort();\n}\n\nbool QFileSystemModel::nameFilterDisables() const\n{\n    Q_D(const QFileSystemModel);\n    return d->nameFilterDisables;\n}\n\n/*!\n    Sets the name \\a filters to apply against the existing files.\n*/\nvoid QFileSystemModel::setNameFilters(const QStringList &filters)\n{\n#if QT_CONFIG(regularexpression)\n    Q_D(QFileSystemModel);\n\n    if (!d->bypassFilters.isEmpty()) {\n        // update the bypass filter to only bypass the stuff that must be kept around\n        d->bypassFilters.clear();\n        // We guarantee that rootPath will stick around\n        QPersistentModelIndex root(index(rootPath()));\n        const QModelIndexList persistentList = persistentIndexList();\n        for (const auto &persistentIndex : persistentList) {\n            QFileSystemModelPrivate::QFileSystemNode *node = d->node(persistentIndex);\n            while (node) {\n                if (d->bypassFilters.contains(node))\n                    break;\n                if (node->isDir())\n                    d->bypassFilters[node] = true;\n                node = node->parent;\n            }\n        }\n    }\n\n    d->nameFilters = filters;\n    d->rebuildNameFilterRegexps();\n    d->forceSort = true;\n    d->delayedSort();\n#else\n    Q_UNUSED(filters);\n#endif\n}\n\n/*!\n    Returns a list of filters applied to the names in the model.\n*/\nQStringList QFileSystemModel::nameFilters() const\n{\n#if QT_CONFIG(regularexpression)\n    Q_D(const QFileSystemModel);\n    return d->nameFilters;\n#else\n    return QStringList();\n#endif\n}\n\n/*!\n    \\reimp\n*/\nbool QFileSystemModel::event(QEvent *event)\n{\n#if QT_CONFIG(filesystemwatcher)\n    Q_D(QFileSystemModel);\n    if (event->type() == QEvent::LanguageChange) {\n        d->root.retranslateStrings(d->fileInfoGatherer->iconProvider(), QString());\n        return true;\n    }\n#endif\n    return QAbstractItemModel::event(event);\n}\n\nbool QFileSystemModel::rmdir(const QModelIndex &aindex)\n{\n    QString path = filePath(aindex);\n    const bool success = QDir().rmdir(path);\n#if QT_CONFIG(filesystemwatcher)\n    if (success) {\n        QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());\n        d->fileInfoGatherer->removePath(path);\n    }\n#endif\n    return success;\n}\n\n/*!\n     \\internal\n\n    Performed quick listing and see if any files have been added or removed,\n    then fetch more information on visible files.\n */\nvoid QFileSystemModelPrivate::directoryChanged(const QString &directory, const QStringList &files)\n{\n    QFileSystemModelPrivate::QFileSystemNode *parentNode = node(directory, false);\n    if (parentNode->children.size() == 0)\n        return;\n    QStringList toRemove;\n    QStringList newFiles = files;\n    std::sort(newFiles.begin(), newFiles.end());\n    for (auto i = parentNode->children.constBegin(), cend = parentNode->children.constEnd(); i != cend; ++i) {\n        QStringList::iterator iterator = std::lower_bound(newFiles.begin(), newFiles.end(), i.value()->fileName);\n        if ((iterator == newFiles.end()) || (i.value()->fileName < *iterator))\n            toRemove.append(i.value()->fileName);\n    }\n    for (int i = 0 ; i < toRemove.size() ; ++i )\n        removeNode(parentNode, toRemove[i]);\n}\n\n#if defined(Q_OS_WIN)\nstatic QString volumeName(const QString &path)\n{\n    IShellItem *item = nullptr;\n    const QString native = QDir::toNativeSeparators(path);\n    HRESULT hr = SHCreateItemFromParsingName(reinterpret_cast<const wchar_t *>(native.utf16()),\n                                             nullptr, IID_IShellItem,\n                                             reinterpret_cast<void **>(&item));\n    if (FAILED(hr))\n        return QString();\n    LPWSTR name = nullptr;\n    hr = item->GetDisplayName(SIGDN_NORMALDISPLAY, &name);\n    if (FAILED(hr))\n        return QString();\n    QString result = QString::fromWCharArray(name);\n    CoTaskMemFree(name);\n    item->Release();\n    return result;\n}\n#endif // Q_OS_WIN\n\n/*!\n    \\internal\n\n    Adds a new file to the children of parentNode\n\n    *WARNING* this will change the count of children\n*/\nQFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFileSystemNode *parentNode, const QString &fileName, const QFileInfo& info)\n{\n    // In the common case, itemLocation == count() so check there first\n    QFileSystemModelPrivate::QFileSystemNode *node = new QFileSystemModelPrivate::QFileSystemNode(fileName, parentNode);\n#if QT_CONFIG(filesystemwatcher)\n    node->populate(info);\n#else\n    Q_UNUSED(info);\n#endif\n#if defined(Q_OS_WIN)\n    //The parentNode is \"\" so we are listing the drives\n    if (parentNode->fileName.isEmpty())\n        node->volumeName = volumeName(fileName);\n#endif\n    Q_ASSERT(!parentNode->children.contains(fileName));\n    parentNode->children.insert(fileName, node);\n    return node;\n}\n\n/*!\n    \\internal\n\n    File at parentNode->children(itemLocation) has been removed, remove from the lists\n    and emit signals if necessary\n\n    *WARNING* this will change the count of children and could change visibleChildren\n */\nvoid QFileSystemModelPrivate::removeNode(QFileSystemModelPrivate::QFileSystemNode *parentNode, const QString& name)\n{\n    Q_Q(QFileSystemModel);\n    QModelIndex parent = index(parentNode);\n    bool indexHidden = isHiddenByFilter(parentNode, parent);\n\n    int vLocation = parentNode->visibleLocation(name);\n    if (vLocation >= 0 && !indexHidden)\n        q->beginRemoveRows(parent, translateVisibleLocation(parentNode, vLocation),\n                                       translateVisibleLocation(parentNode, vLocation));\n    QFileSystemNode * node = parentNode->children.take(name);\n    delete node;\n    // cleanup sort files after removing rather then re-sorting which is O(n)\n    if (vLocation >= 0)\n        parentNode->visibleChildren.removeAt(vLocation);\n    if (vLocation >= 0 && !indexHidden)\n        q->endRemoveRows();\n}\n\n/*!\n    \\internal\n\n    File at parentNode->children(itemLocation) was not visible before, but now should be\n    and emit signals if necessary.\n\n    *WARNING* this will change the visible count\n */\nvoid QFileSystemModelPrivate::addVisibleFiles(QFileSystemNode *parentNode, const QStringList &newFiles)\n{\n    Q_Q(QFileSystemModel);\n    QModelIndex parent = index(parentNode);\n    bool indexHidden = isHiddenByFilter(parentNode, parent);\n    if (!indexHidden) {\n        q->beginInsertRows(parent, parentNode->visibleChildren.size() , parentNode->visibleChildren.size() + newFiles.size() - 1);\n    }\n\n    if (parentNode->dirtyChildrenIndex == -1)\n        parentNode->dirtyChildrenIndex = parentNode->visibleChildren.size();\n\n    for (const auto &newFile : newFiles) {\n        parentNode->visibleChildren.append(newFile);\n        parentNode->children.value(newFile)->isVisible = true;\n    }\n    if (!indexHidden)\n      q->endInsertRows();\n}\n\n/*!\n    \\internal\n\n    File was visible before, but now should NOT be\n\n    *WARNING* this will change the visible count\n */\nvoid QFileSystemModelPrivate::removeVisibleFile(QFileSystemNode *parentNode, int vLocation)\n{\n    Q_Q(QFileSystemModel);\n    if (vLocation == -1)\n        return;\n    QModelIndex parent = index(parentNode);\n    bool indexHidden = isHiddenByFilter(parentNode, parent);\n    if (!indexHidden)\n        q->beginRemoveRows(parent, translateVisibleLocation(parentNode, vLocation),\n                                       translateVisibleLocation(parentNode, vLocation));\n    parentNode->children.value(parentNode->visibleChildren.at(vLocation))->isVisible = false;\n    parentNode->visibleChildren.removeAt(vLocation);\n    if (!indexHidden)\n        q->endRemoveRows();\n}\n\n/*!\n    \\internal\n\n    The thread has received new information about files,\n    update and emit dataChanged if it has actually changed.\n */\nvoid QFileSystemModelPrivate::fileSystemChanged(const QString &path,\n                                                   const QList<std::pair<QString, QFileInfo>> &updates)\n{\n#if QT_CONFIG(filesystemwatcher)\n    Q_Q(QFileSystemModel);\n    QList<QString> rowsToUpdate;\n    QStringList newFiles;\n    QFileSystemModelPrivate::QFileSystemNode *parentNode = node(path, false);\n    QModelIndex parentIndex = index(parentNode);\n    for (const auto &update : updates) {\n        QString fileName = update.first;\n        Q_ASSERT(!fileName.isEmpty());\n        QExtendedInformation info = fileInfoGatherer->getInfo(update.second);\n        bool previouslyHere = parentNode->children.contains(fileName);\n        if (!previouslyHere) {\n#ifdef Q_OS_WIN\n            chopSpaceAndDot(fileName);\n            if (fileName.isEmpty())\n                continue;\n#endif\n            addNode(parentNode, fileName, info.fileInfo());\n        }\n        QFileSystemModelPrivate::QFileSystemNode * node = parentNode->children.value(fileName);\n        bool isCaseSensitive = parentNode->caseSensitive();\n        if (isCaseSensitive) {\n            if (node->fileName != fileName)\n                continue;\n        } else {\n            if (QString::compare(node->fileName,fileName,Qt::CaseInsensitive) != 0)\n                continue;\n        }\n        if (isCaseSensitive) {\n            Q_ASSERT(node->fileName == fileName);\n        } else {\n            node->fileName = fileName;\n        }\n\n        if (*node != info ) {\n            node->populate(info);\n            bypassFilters.remove(node);\n            // brand new information.\n            if (filtersAcceptsNode(node)) {\n                if (!node->isVisible) {\n                    newFiles.append(fileName);\n                } else {\n                    rowsToUpdate.append(fileName);\n                }\n            } else {\n                if (node->isVisible) {\n                    int visibleLocation = parentNode->visibleLocation(fileName);\n                    removeVisibleFile(parentNode, visibleLocation);\n                } else {\n                    // The file is not visible, don't do anything\n                }\n            }\n        }\n    }\n\n    // bundle up all of the changed signals into as few as possible.\n    std::sort(rowsToUpdate.begin(), rowsToUpdate.end());\n    QString min;\n    QString max;\n    for (const QString &value : std::as_const(rowsToUpdate)) {\n        //##TODO is there a way to bundle signals with QString as the content of the list?\n        /*if (min.isEmpty()) {\n            min = value;\n            if (i != rowsToUpdate.count() - 1)\n                continue;\n        }\n        if (i != rowsToUpdate.count() - 1) {\n            if ((value == min + 1 && max.isEmpty()) || value == max + 1) {\n                max = value;\n                continue;\n            }\n        }*/\n        max = value;\n        min = value;\n        int visibleMin = parentNode->visibleLocation(min);\n        int visibleMax = parentNode->visibleLocation(max);\n        if (visibleMin >= 0\n            && visibleMin < parentNode->visibleChildren.size()\n            && parentNode->visibleChildren.at(visibleMin) == min\n            && visibleMax >= 0) {\n            // don't use NumColumns here, a subclass might override columnCount\n            const int lastColumn = q->columnCount(parentIndex) - 1;\n            const QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMin),\n                                             QFileSystemModelPrivate::NameColumn, parentIndex);\n            const QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMax),\n                                                lastColumn, parentIndex);\n            // We document that emitting dataChanged with indexes that don't have the\n            // same parent is undefined behavior.\n            Q_ASSERT(bottom.parent() == top.parent());\n            emit q->dataChanged(top, bottom);\n        }\n\n        /*min = QString();\n        max = QString();*/\n    }\n\n    if (newFiles.size() > 0) {\n        addVisibleFiles(parentNode, newFiles);\n    }\n\n    if (newFiles.size() > 0 || (sortColumn != 0 && rowsToUpdate.size() > 0)) {\n        forceSort = true;\n        delayedSort();\n    }\n#else\n    Q_UNUSED(path);\n    Q_UNUSED(updates);\n#endif // filesystemwatcher\n}\n\n/*!\n    \\internal\n*/\nvoid QFileSystemModelPrivate::resolvedName(const QString &fileName, const QString &resolvedName)\n{\n    resolvedSymLinks[fileName] = resolvedName;\n}\n\n#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)\n// Remove file system watchers at/below the index and return a list of previously\n// watched files. This should be called prior to operations like rename/remove\n// which might fail due to watchers on platforms like Windows. The watchers\n// should be restored on failure.\nQStringList QFileSystemModelPrivate::unwatchPathsAt(const QModelIndex &index)\n{\n    const QFileSystemModelPrivate::QFileSystemNode *indexNode = node(index);\n    if (indexNode == nullptr)\n        return QStringList();\n    const Qt::CaseSensitivity caseSensitivity = indexNode->caseSensitive()\n        ? Qt::CaseSensitive : Qt::CaseInsensitive;\n    const QString path = indexNode->fileInfo().absoluteFilePath();\n\n    QStringList result;\n    const auto filter = [path, caseSensitivity] (const QString &watchedPath)\n    {\n        const int pathSize = path.size();\n        if (pathSize == watchedPath.size()) {\n            return path.compare(watchedPath, caseSensitivity) == 0;\n        } else if (watchedPath.size() > pathSize) {\n            return watchedPath.at(pathSize) == u'/'\n                && watchedPath.startsWith(path, caseSensitivity);\n        }\n        return false;\n    };\n\n    const QStringList &watchedFiles = fileInfoGatherer->watchedFiles();\n    std::copy_if(watchedFiles.cbegin(), watchedFiles.cend(),\n                 std::back_inserter(result), filter);\n\n    const QStringList &watchedDirectories = fileInfoGatherer->watchedDirectories();\n    std::copy_if(watchedDirectories.cbegin(), watchedDirectories.cend(),\n                 std::back_inserter(result), filter);\n\n    fileInfoGatherer->unwatchPaths(result);\n    return result;\n}\n#endif // filesystemwatcher && Q_OS_WIN\n\nQFileSystemModelPrivate::QFileSystemModelPrivate()\n#if QT_CONFIG(filesystemwatcher)\n    : fileInfoGatherer(new QFileInfoGatherer)\n#endif // filesystemwatcher\n{\n}\n\nQFileSystemModelPrivate::~QFileSystemModelPrivate()\n{\n#if QT_CONFIG(filesystemwatcher)\n    fileInfoGatherer->requestAbort();\n    if (!fileInfoGatherer->wait(1000)) {\n        // If the thread hangs, perhaps because the network was disconnected\n        // while the gatherer was stat'ing a remote file, then don't block\n        // shutting down the model (which might block a file dialog and the\n        // main thread). Schedule the gatherer for later deletion; it's\n        // destructor will wait for the thread to finish.\n        auto *rawGatherer = fileInfoGatherer.release();\n        rawGatherer->deleteLater();\n    }\n#endif // filesystemwatcher\n}\n\n/*!\n    \\internal\n*/\nvoid QFileSystemModelPrivate::init()\n{\n    delayedSortTimer.setSingleShot(true);\n\n    qRegisterMetaType<QList<std::pair<QString, QFileInfo>>>();\n#if QT_CONFIG(filesystemwatcher)\n    QObjectPrivate::connect(fileInfoGatherer.get(), &QFileInfoGatherer::newListOfFiles,\n                            this, &QFileSystemModelPrivate::directoryChanged);\n    QObjectPrivate::connect(fileInfoGatherer.get(), &QFileInfoGatherer::updates,\n                            this, &QFileSystemModelPrivate::fileSystemChanged);\n    QObjectPrivate::connect(fileInfoGatherer.get(), &QFileInfoGatherer::nameResolved,\n                            this, &QFileSystemModelPrivate::resolvedName);\n    Q_Q(QFileSystemModel);\n    q->connect(fileInfoGatherer.get(), &QFileInfoGatherer::directoryLoaded,\n               q, &QFileSystemModel::directoryLoaded);\n#endif // filesystemwatcher\n    QObjectPrivate::connect(&delayedSortTimer, &QTimer::timeout,\n                            this, &QFileSystemModelPrivate::performDelayedSort,\n                            Qt::QueuedConnection);\n}\n\n/*!\n    \\internal\n\n    Returns \\c false if node doesn't pass the filters otherwise true\n\n    QDir::Modified is not supported\n    QDir::Drives is not supported\n*/\nbool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) const\n{\n    // When the model is set to only show files, then a node representing a dir\n    // should be hidden regardless of bypassFilters.\n    // QTBUG-74471\n    const bool hideDirs = (filters & (QDir::Dirs | QDir::AllDirs)) == 0;\n    const bool shouldHideDirNode = hideDirs && node->isDir();\n\n    // always accept drives\n    if (node->parent == &root || (!shouldHideDirNode && bypassFilters.contains(node)))\n        return true;\n\n    // If we don't know anything yet don't accept it\n    if (!node->hasInformation())\n        return false;\n\n    const bool filterPermissions = ((filters & QDir::PermissionMask)\n                                   && (filters & QDir::PermissionMask) != QDir::PermissionMask);\n    const bool hideFiles         = !(filters & QDir::Files);\n    const bool hideReadable      = !(!filterPermissions || (filters & QDir::Readable));\n    const bool hideWritable      = !(!filterPermissions || (filters & QDir::Writable));\n    const bool hideExecutable    = !(!filterPermissions || (filters & QDir::Executable));\n    const bool hideHidden        = !(filters & QDir::Hidden);\n    const bool hideSystem        = !(filters & QDir::System);\n    const bool hideSymlinks      = (filters & QDir::NoSymLinks);\n    const bool hideDot           = (filters & QDir::NoDot);\n    const bool hideDotDot        = (filters & QDir::NoDotDot);\n\n    // Note that we match the behavior of entryList and not QFileInfo on this.\n    bool isDot    = (node->fileName == \".\"_L1);\n    bool isDotDot = (node->fileName == \"..\"_L1);\n    if (   (hideHidden && !(isDot || isDotDot) && node->isHidden())\n        || (hideSystem && node->isSystem())\n        || (hideDirs && node->isDir())\n        || (hideFiles && node->isFile())\n        || (hideSymlinks && node->isSymLink())\n        || (hideReadable && node->isReadable())\n        || (hideWritable && node->isWritable())\n        || (hideExecutable && node->isExecutable())\n        || (hideDot && isDot)\n        || (hideDotDot && isDotDot))\n        return false;\n\n    return nameFilterDisables || passNameFilters(node);\n}\n\n/*\n    \\internal\n\n    Returns \\c true if node passes the name filters and should be visible.\n */\nbool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const\n{\n#if QT_CONFIG(regularexpression)\n    if (nameFilters.isEmpty())\n        return true;\n\n    // Check the name regularexpression filters\n    if (!(node->isDir() && (filters & QDir::AllDirs))) {\n        const auto matchesNodeFileName = [node](const QRegularExpression &re)\n        {\n            return node->fileName.contains(re);\n        };\n        return std::any_of(nameFiltersRegexps.begin(),\n                           nameFiltersRegexps.end(),\n                           matchesNodeFileName);\n    }\n#else\n    Q_UNUSED(node);\n#endif\n    return true;\n}\n\n#if QT_CONFIG(regularexpression)\nvoid QFileSystemModelPrivate::rebuildNameFilterRegexps()\n{\n    nameFiltersRegexps.clear();\n    nameFiltersRegexps.reserve(nameFilters.size());\n    const auto cs = (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;\n    const auto convertWildcardToRegexp = [cs](const QString &nameFilter)\n    {\n        return QRegularExpression::fromWildcard(nameFilter, cs);\n    };\n    std::transform(nameFilters.constBegin(),\n                   nameFilters.constEnd(),\n                   std::back_inserter(nameFiltersRegexps),\n                   convertWildcardToRegexp);\n}\n#endif\n\nQT_END_NAMESPACE\n\n#include \"moc_qfilesystemmodel.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qfontdialog.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qwindowdefs.h\"\n#include \"qfontdialog.h\"\n\n#include \"qfontdialog_p.h\"\n\n#include <qapplication.h>\n#include <qcheckbox.h>\n#include <qcombobox.h>\n#include <qevent.h>\n#include <qgroupbox.h>\n#include <qlabel.h>\n#include <qlayout.h>\n#include <qlineedit.h>\n#include <qpushbutton.h>\n#include <qstyle.h>\n#include <qdialogbuttonbox.h>\n#include <qheaderview.h>\n#include <qlistview.h>\n#include <qstringlistmodel.h>\n#include <qvalidator.h>\n#include <private/qfontdatabase_p.h>\n#include <private/qdialog_p.h>\n#include <private/qfont_p.h>\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\nclass QFontListView : public QListView\n{\n    Q_OBJECT\npublic:\n    QFontListView(QWidget *parent);\n    inline QStringListModel *model() const {\n        return static_cast<QStringListModel *>(QListView::model());\n    }\n    inline void setCurrentItem(int item) {\n        QListView::setCurrentIndex(static_cast<QAbstractListModel*>(model())->index(item));\n    }\n    inline int currentItem() const {\n        return QListView::currentIndex().row();\n    }\n    inline int count() const {\n        return model()->rowCount();\n    }\n    inline QString currentText() const {\n        int row = QListView::currentIndex().row();\n        return row < 0 ? QString() : model()->stringList().at(row);\n    }\n    void currentChanged(const QModelIndex &current, const QModelIndex &previous) override {\n        QListView::currentChanged(current, previous);\n        if (current.isValid())\n            emit highlighted(current.row());\n    }\n    QString text(int i) const {\n        return model()->stringList().at(i);\n    }\nsignals:\n    void highlighted(int);\n};\n\nQFontListView::QFontListView(QWidget *parent)\n    : QListView(parent)\n{\n    setModel(new QStringListModel(parent));\n    setEditTriggers(NoEditTriggers);\n}\n\nstatic const Qt::WindowFlags qfd_DefaultWindowFlags =\n        Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;\n\nQFontDialogPrivate::QFontDialogPrivate()\n    : writingSystem(QFontDatabase::Any),\n      options(QFontDialogOptions::create())\n{\n}\n\nQFontDialogPrivate::~QFontDialogPrivate()\n{\n}\n\n/*!\n  \\class QFontDialog\n  \\ingroup standard-dialogs\n  \\inmodule QtWidgets\n\n  \\brief The QFontDialog class provides a dialog widget for selecting a font.\n\n    A font dialog is created through one of the static getFont()\n    functions.\n\n  Examples:\n\n  \\snippet code/src_gui_dialogs_qfontdialog.cpp 0\n\n    The dialog can also be used to set a widget's font directly:\n  \\snippet code/src_gui_dialogs_qfontdialog.cpp 1\n  If the user clicks OK the font they chose will be used for myWidget,\n  and if they click Cancel the original font is used.\n\n  \\image fusion-fontdialog.png A font dialog in the Fusion widget style.\n\n  \\sa QFont, QFontInfo, QFontMetrics, QColorDialog, QFileDialog,\n      {Standard Dialogs Example}\n*/\n\n/*!\n    Constructs a standard font dialog.\n\n    Use setCurrentFont() to set the initial font attributes.\n\n    The \\a parent parameter is passed to the QDialog constructor.\n\n    \\sa getFont()\n*/\nQFontDialog::QFontDialog(QWidget *parent)\n    : QDialog(*new QFontDialogPrivate, parent, qfd_DefaultWindowFlags)\n{\n    Q_D(QFontDialog);\n    d->init();\n}\n\n/*!\n    Constructs a standard font dialog with the given \\a parent and specified\n    \\a initial font.\n*/\nQFontDialog::QFontDialog(const QFont &initial, QWidget *parent)\n    : QFontDialog(parent)\n{\n    setCurrentFont(initial);\n}\n\nvoid QFontDialogPrivate::init()\n{\n    Q_Q(QFontDialog);\n\n    q->setSizeGripEnabled(true);\n    q->setWindowTitle(QFontDialog::tr(\"Select Font\"));\n\n    // grid\n    familyEdit = new QLineEdit(q);\n    familyEdit->setReadOnly(true);\n    familyList = new QFontListView(q);\n    familyEdit->setFocusProxy(familyList);\n\n    familyAccel = new QLabel(q);\n#ifndef QT_NO_SHORTCUT\n    familyAccel->setBuddy(familyList);\n#endif\n    familyAccel->setIndent(2);\n\n    styleEdit = new QLineEdit(q);\n    styleEdit->setReadOnly(true);\n    styleList = new QFontListView(q);\n    styleEdit->setFocusProxy(styleList);\n\n    styleAccel = new QLabel(q);\n#ifndef QT_NO_SHORTCUT\n    styleAccel->setBuddy(styleList);\n#endif\n    styleAccel->setIndent(2);\n\n    sizeEdit = new QLineEdit(q);\n    sizeEdit->setFocusPolicy(Qt::ClickFocus);\n    QIntValidator *validator = new QIntValidator(1, 512, q);\n    sizeEdit->setValidator(validator);\n    sizeList = new QFontListView(q);\n\n    sizeAccel = new QLabel(q);\n#ifndef QT_NO_SHORTCUT\n    sizeAccel->setBuddy(sizeEdit);\n#endif\n    sizeAccel->setIndent(2);\n\n    // effects box\n    effects = new QGroupBox(q);\n    QVBoxLayout *vbox = new QVBoxLayout(effects);\n    strikeout = new QCheckBox(effects);\n    vbox->addWidget(strikeout);\n    underline = new QCheckBox(effects);\n    vbox->addWidget(underline);\n\n    sample = new QGroupBox(q);\n    QHBoxLayout *hbox = new QHBoxLayout(sample);\n    sampleEdit = new QLineEdit(sample);\n    sampleEdit->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));\n    sampleEdit->setAlignment(Qt::AlignCenter);\n    // Note that the sample text is *not* translated with tr(), as the\n    // characters used depend on the charset encoding.\n    sampleEdit->setText(\"AaBbYyZz\"_L1);\n    hbox->addWidget(sampleEdit);\n\n    writingSystemCombo = new QComboBox(q);\n\n    writingSystemAccel = new QLabel(q);\n#ifndef QT_NO_SHORTCUT\n    writingSystemAccel->setBuddy(writingSystemCombo);\n#endif\n    writingSystemAccel->setIndent(2);\n\n    size = 0;\n    smoothScalable = false;\n\n    QObjectPrivate::connect(writingSystemCombo, &QComboBox::activated,\n                            this, &QFontDialogPrivate::writingSystemHighlighted);\n    QObjectPrivate::connect(familyList, &QFontListView::highlighted,\n                            this, &QFontDialogPrivate::familyHighlighted);\n    QObjectPrivate::connect(styleList, &QFontListView::highlighted,\n                            this, &QFontDialogPrivate::styleHighlighted);\n    QObjectPrivate::connect(sizeList, &QFontListView::highlighted,\n                            this, &QFontDialogPrivate::sizeHighlighted);\n    QObjectPrivate::connect(sizeEdit, &QLineEdit::textChanged,\n                            this, &QFontDialogPrivate::sizeChanged);\n\n    QObjectPrivate::connect(strikeout, &QCheckBox::clicked,\n                            this, &QFontDialogPrivate::updateSample);\n    QObjectPrivate::connect(underline, &QCheckBox::clicked, this,\n                            &QFontDialogPrivate::updateSample);\n\n    for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {\n        QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);\n        QString writingSystemName = QFontDatabase::writingSystemName(ws);\n        if (writingSystemName.isEmpty())\n            break;\n        writingSystemCombo->addItem(writingSystemName);\n    }\n\n    updateFamilies();\n    if (familyList->count() != 0) {\n        familyList->setCurrentItem(0);\n        sizeList->setCurrentItem(0);\n    }\n\n    // grid layout\n    QGridLayout *mainGrid = new QGridLayout(q);\n\n    int spacing = mainGrid->spacing();\n    if (spacing >= 0) {     // uniform spacing\n       mainGrid->setSpacing(0);\n\n       mainGrid->setColumnMinimumWidth(1, spacing);\n       mainGrid->setColumnMinimumWidth(3, spacing);\n\n       int margin = 0;\n       mainGrid->getContentsMargins(nullptr, nullptr, nullptr, &margin);\n\n       mainGrid->setRowMinimumHeight(3, margin);\n       mainGrid->setRowMinimumHeight(6, 2);\n       mainGrid->setRowMinimumHeight(8, margin);\n    }\n\n    mainGrid->addWidget(familyAccel, 0, 0);\n    mainGrid->addWidget(familyEdit, 1, 0);\n    mainGrid->addWidget(familyList, 2, 0);\n\n    mainGrid->addWidget(styleAccel, 0, 2);\n    mainGrid->addWidget(styleEdit, 1, 2);\n    mainGrid->addWidget(styleList, 2, 2);\n\n    mainGrid->addWidget(sizeAccel, 0, 4);\n    mainGrid->addWidget(sizeEdit, 1, 4);\n    mainGrid->addWidget(sizeList, 2, 4);\n\n    mainGrid->setColumnStretch(0, 38);\n    mainGrid->setColumnStretch(2, 24);\n    mainGrid->setColumnStretch(4, 10);\n\n    mainGrid->addWidget(effects, 4, 0);\n\n    mainGrid->addWidget(sample, 4, 2, 4, 3);\n\n    mainGrid->addWidget(writingSystemAccel, 5, 0);\n    mainGrid->addWidget(writingSystemCombo, 7, 0);\n\n    buttonBox = new QDialogButtonBox(q);\n    mainGrid->addWidget(buttonBox, 9, 0, 1, 5);\n\n    QPushButton *button\n            = static_cast<QPushButton *>(buttonBox->addButton(QDialogButtonBox::Ok));\n    QObject::connect(buttonBox, &QDialogButtonBox::accepted, q, &QDialog::accept);\n    button->setDefault(true);\n\n    buttonBox->addButton(QDialogButtonBox::Cancel);\n    QObject::connect(buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject);\n\n    q->resize(500, 360);\n\n    sizeEdit->installEventFilter(q);\n    familyList->installEventFilter(q);\n    styleList->installEventFilter(q);\n    sizeList->installEventFilter(q);\n\n    familyList->setFocus();\n    retranslateStrings();\n    sampleEdit->setObjectName(\"qt_fontDialog_sampleEdit\"_L1);\n}\n\n/*!\n  \\internal\n Destroys the font dialog and frees up its storage.\n*/\n\nQFontDialog::~QFontDialog()\n{\n}\n\n/*!\n  Executes a modal font dialog and returns a font.\n\n  If the user clicks \\uicontrol OK, the selected font is returned. If the user\n  clicks \\uicontrol Cancel, the \\a initial font is returned.\n\n  The dialog is constructed with the given \\a parent and the options specified\n  in \\a options. \\a title is shown as the window title of the dialog and  \\a\n  initial is the initially selected font. If the \\a ok parameter is not-null,\n  the value it refers to is set to true if the user clicks \\uicontrol OK, and set to\n  false if the user clicks \\uicontrol Cancel.\n\n  Examples:\n  \\snippet code/src_gui_dialogs_qfontdialog.cpp 2\n\n    The dialog can also be used to set a widget's font directly:\n  \\snippet code/src_gui_dialogs_qfontdialog.cpp 3\n  In this example, if the user clicks OK the font they chose will be\n  used, and if they click Cancel the original font is used.\n*/\nQFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget *parent, const QString &title,\n                           FontDialogOptions options)\n{\n    return QFontDialogPrivate::getFont(ok, initial, parent, title, options);\n}\n\n/*!\n    \\overload\n\n  Executes a modal font dialog and returns a font.\n\n  If the user clicks \\uicontrol OK, the selected font is returned. If the user\n  clicks \\uicontrol Cancel, the Qt default font is returned.\n\n  The dialog is constructed with the given \\a parent.\n  If the \\a ok parameter is not-null, the value it refers to is set\n  to true if the user clicks \\uicontrol OK, and false if the user clicks\n  \\uicontrol Cancel.\n\n  Example:\n  \\snippet code/src_gui_dialogs_qfontdialog.cpp 4\n*/\nQFont QFontDialog::getFont(bool *ok, QWidget *parent)\n{\n    QFont initial;\n    return QFontDialogPrivate::getFont(ok, initial, parent, QString(), { });\n}\n\nQFont QFontDialogPrivate::getFont(bool *ok, const QFont &initial, QWidget *parent,\n                                  const QString &title, QFontDialog::FontDialogOptions options)\n{\n    QAutoPointer<QFontDialog> dlg(new QFontDialog(parent));\n    dlg->setOptions(options);\n    dlg->setCurrentFont(initial);\n    if (!title.isEmpty())\n        dlg->setWindowTitle(title);\n\n    int ret = (dlg->exec() || (options & QFontDialog::NoButtons));\n    if (ok)\n        *ok = !!ret;\n    if (ret && bool(dlg)) {\n        return dlg->selectedFont();\n    } else {\n        return initial;\n    }\n}\n\n/*!\n    \\internal\n    An event filter to make the Up, Down, PageUp and PageDown keys work\n    correctly in the line edits. The source of the event is the object\n    \\a o and the event is \\a e.\n*/\n\nbool QFontDialog::eventFilter(QObject *o , QEvent *e)\n{\n    Q_D(QFontDialog);\n    if (e->type() == QEvent::KeyPress) {\n        QKeyEvent *k = static_cast<QKeyEvent *>(e);\n        if (o == d->sizeEdit &&\n        (k->key() == Qt::Key_Up ||\n             k->key() == Qt::Key_Down ||\n         k->key() == Qt::Key_PageUp ||\n         k->key() == Qt::Key_PageDown)) {\n\n            int ci = d->sizeList->currentItem();\n            QCoreApplication::sendEvent(d->sizeList, k);\n\n            if (ci != d->sizeList->currentItem()\n                    && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, this))\n                d->sizeEdit->selectAll();\n            return true;\n        } else if ((o == d->familyList || o == d->styleList) &&\n                    (k->key() == Qt::Key_Return || k->key() == Qt::Key_Enter)) {\n            k->accept();\n        accept();\n            return true;\n        }\n    } else if (e->type() == QEvent::FocusIn\n               && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, this)) {\n        if (o == d->familyList)\n            d->familyEdit->selectAll();\n        else if (o == d->styleList)\n            d->styleEdit->selectAll();\n        else if (o == d->sizeList)\n            d->sizeEdit->selectAll();\n    } else if (e->type() == QEvent::MouseButtonPress && o == d->sizeList) {\n            d->sizeEdit->setFocus();\n    }\n    return QDialog::eventFilter(o, e);\n}\n\nvoid QFontDialogPrivate::initHelper(QPlatformDialogHelper *h)\n{\n    Q_Q(QFontDialog);\n    auto *fontDialogHelper = static_cast<QPlatformFontDialogHelper *>(h);\n    fontDialogHelper->setOptions(options);\n    fontDialogHelper->setCurrentFont(q->currentFont());\n    QObject::connect(fontDialogHelper, &QPlatformFontDialogHelper::currentFontChanged,\n                     q, &QFontDialog::currentFontChanged);\n    QObject::connect(fontDialogHelper, &QPlatformFontDialogHelper::fontSelected,\n                     q, &QFontDialog::fontSelected);\n}\n\nvoid QFontDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)\n{\n    options->setWindowTitle(q_func()->windowTitle());\n}\n\n/*\n    Updates the contents of the \"font family\" list box. This\n    function can be reimplemented if you have special requirements.\n*/\n\nvoid QFontDialogPrivate::updateFamilies()\n{\n    Q_Q(QFontDialog);\n\n    enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };\n\n    const QFontDialog::FontDialogOptions scalableMask = (QFontDialog::ScalableFonts | QFontDialog::NonScalableFonts);\n    const QFontDialog::FontDialogOptions spacingMask = (QFontDialog::ProportionalFonts | QFontDialog::MonospacedFonts);\n    const QFontDialog::FontDialogOptions options = q->options();\n\n    QStringList familyNames;\n    const auto families = QFontDatabase::families(writingSystem);\n    for (const QString &family : families) {\n        if (QFontDatabase::isPrivateFamily(family))\n            continue;\n\n        if ((options & scalableMask) && (options & scalableMask) != scalableMask) {\n            if (bool(options & QFontDialog::ScalableFonts) != QFontDatabase::isSmoothlyScalable(family))\n                continue;\n        }\n        if ((options & spacingMask) && (options & spacingMask) != spacingMask) {\n            if (bool(options & QFontDialog::MonospacedFonts) != QFontDatabase::isFixedPitch(family))\n                continue;\n        }\n        familyNames << family;\n    }\n\n    familyList->model()->setStringList(familyNames);\n\n    QString foundryName1, familyName1, foundryName2, familyName2;\n    int bestFamilyMatch = -1;\n    match_t bestFamilyType = MATCH_NONE;\n\n    QFont f;\n\n    // ##### do the right thing for a list of family names in the font.\n    QFontDatabasePrivate::parseFontName(family, foundryName1, familyName1);\n\n    QStringList::const_iterator it = familyNames.constBegin();\n    int i = 0;\n    for(; it != familyNames.constEnd(); ++it, ++i) {\n        QFontDatabasePrivate::parseFontName(*it, foundryName2, familyName2);\n\n        //try to match...\n        if (familyName1 == familyName2) {\n            bestFamilyType = MATCH_FAMILY;\n            if (foundryName1 == foundryName2) {\n                bestFamilyMatch = i;\n                break;\n            }\n            if (bestFamilyMatch < MATCH_FAMILY)\n                bestFamilyMatch = i;\n        }\n\n        //and try some fall backs\n        match_t type = MATCH_NONE;\n        if (bestFamilyType <= MATCH_NONE && familyName2 == \"helvetica\"_L1)\n            type = MATCH_LAST_RESORT;\n        if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.families().constFirst())\n            type = MATCH_APP;\n        // ### add fallback for writingSystem\n        if (type != MATCH_NONE) {\n            bestFamilyType = type;\n            bestFamilyMatch = i;\n        }\n    }\n\n    if (i != -1 && bestFamilyType != MATCH_NONE)\n        familyList->setCurrentItem(bestFamilyMatch);\n    else\n        familyList->setCurrentItem(0);\n    familyEdit->setText(familyList->currentText());\n    if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)\n            && familyList->hasFocus())\n        familyEdit->selectAll();\n\n    updateStyles();\n}\n\n/*\n    Updates the contents of the \"font style\" list box. This\n    function can be reimplemented if you have special requirements.\n*/\nvoid QFontDialogPrivate::updateStyles()\n{\n    Q_Q(QFontDialog);\n    QStringList styles = QFontDatabase::styles(familyList->currentText());\n    styleList->model()->setStringList(styles);\n\n    if (styles.isEmpty()) {\n        styleEdit->clear();\n        smoothScalable = false;\n    } else {\n        if (!style.isEmpty()) {\n            bool found = false;\n            bool first = true;\n            QString cstyle = style;\n\n        redo:\n            for (int i = 0; i < static_cast<int>(styleList->count()); i++) {\n                if (cstyle == styleList->text(i)) {\n                     styleList->setCurrentItem(i);\n                     found = true;\n                     break;\n                 }\n            }\n            if (!found && first) {\n                if (cstyle.contains(\"Italic\"_L1)) {\n                    cstyle.replace(\"Italic\"_L1, \"Oblique\"_L1);\n                    first = false;\n                    goto redo;\n                } else if (cstyle.contains(\"Oblique\"_L1)) {\n                    cstyle.replace(\"Oblique\"_L1, \"Italic\"_L1);\n                    first = false;\n                    goto redo;\n                } else if (cstyle.contains(\"Regular\"_L1)) {\n                    cstyle.replace(\"Regular\"_L1, \"Normal\"_L1);\n                    first = false;\n                    goto redo;\n                } else if (cstyle.contains(\"Normal\"_L1)) {\n                    cstyle.replace(\"Normal\"_L1, \"Regular\"_L1);\n                    first = false;\n                    goto redo;\n                }\n            }\n            if (!found)\n                styleList->setCurrentItem(0);\n        } else {\n            styleList->setCurrentItem(0);\n        }\n\n        styleEdit->setText(styleList->currentText());\n        if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)\n                && styleList->hasFocus())\n            styleEdit->selectAll();\n\n        smoothScalable = QFontDatabase::isSmoothlyScalable(familyList->currentText(), styleList->currentText());\n    }\n\n    updateSizes();\n}\n\n/*!\n    \\internal\n    Updates the contents of the \"font size\" list box. This\n  function can be reimplemented if you have special requirements.\n*/\n\nvoid QFontDialogPrivate::updateSizes()\n{\n    Q_Q(QFontDialog);\n\n    if (!familyList->currentText().isEmpty()) {\n        QList<int> sizes = QFontDatabase::pointSizes(familyList->currentText(), styleList->currentText());\n\n        int i = 0;\n        int current = -1;\n        QStringList str_sizes;\n        str_sizes.reserve(sizes.size());\n        for(QList<int>::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); ++it) {\n            str_sizes.append(QString::number(*it));\n            if (current == -1 && *it == size)\n                current = i;\n            ++i;\n        }\n        sizeList->model()->setStringList(str_sizes);\n        if (current != -1)\n            sizeList->setCurrentItem(current);\n\n        const QSignalBlocker blocker(sizeEdit);\n        sizeEdit->setText((smoothScalable ? QString::number(size) : sizeList->currentText()));\n        if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)\n                && sizeList->hasFocus())\n            sizeEdit->selectAll();\n    } else {\n        sizeEdit->clear();\n    }\n\n    updateSample();\n}\n\nvoid QFontDialogPrivate::updateSample()\n{\n    // compute new font\n    int pSize = sizeEdit->text().toInt();\n    QFont newFont(QFontDatabase::font(familyList->currentText(), style, pSize));\n    newFont.setStrikeOut(strikeout->isChecked());\n    newFont.setUnderline(underline->isChecked());\n\n    if (familyList->currentText().isEmpty())\n        sampleEdit->clear();\n\n    updateSampleFont(newFont);\n}\n\nvoid QFontDialogPrivate::updateSampleFont(const QFont &newFont)\n{\n    Q_Q(QFontDialog);\n    if (newFont != sampleEdit->font()) {\n        sampleEdit->setFont(newFont);\n        emit q->currentFontChanged(newFont);\n    }\n}\n\n/*!\n    \\internal\n*/\nvoid QFontDialogPrivate::writingSystemHighlighted(int index)\n{\n    writingSystem = QFontDatabase::WritingSystem(index);\n    sampleEdit->setText(QFontDatabase::writingSystemSample(writingSystem));\n    updateFamilies();\n}\n\n/*!\n    \\internal\n*/\nvoid QFontDialogPrivate::familyHighlighted(int i)\n{\n    Q_Q(QFontDialog);\n    family = familyList->text(i);\n    familyEdit->setText(family);\n    if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)\n            && familyList->hasFocus())\n        familyEdit->selectAll();\n\n    updateStyles();\n}\n\n\n/*!\n    \\internal\n*/\n\nvoid QFontDialogPrivate::styleHighlighted(int index)\n{\n    Q_Q(QFontDialog);\n    QString s = styleList->text(index);\n    styleEdit->setText(s);\n    if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)\n            && styleList->hasFocus())\n        styleEdit->selectAll();\n\n    style = s;\n\n    updateSizes();\n}\n\n\n/*!\n    \\internal\n*/\n\nvoid QFontDialogPrivate::sizeHighlighted(int index)\n{\n    Q_Q(QFontDialog);\n    QString s = sizeList->text(index);\n    sizeEdit->setText(s);\n    if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)\n            && sizeEdit->hasFocus())\n        sizeEdit->selectAll();\n\n    size = s.toInt();\n    updateSample();\n}\n\n/*!\n    \\internal\n    This slot is called if the user changes the font size.\n    The size is passed in the \\a s argument as a \\e string.\n*/\n\nvoid QFontDialogPrivate::sizeChanged(const QString &s)\n{\n    // no need to check if the conversion is valid, since we have an QIntValidator in the size edit\n    int size = s.toInt();\n    if (this->size == size)\n        return;\n\n    this->size = size;\n    if (sizeList->count() != 0) {\n        int i;\n        for (i = 0; i < sizeList->count() - 1; i++) {\n            if (sizeList->text(i).toInt() >= this->size)\n                break;\n        }\n        const QSignalBlocker blocker(sizeList);\n        if (sizeList->text(i).toInt() == this->size)\n            sizeList->setCurrentItem(i);\n        else\n            sizeList->clearSelection();\n    }\n    updateSample();\n}\n\nvoid QFontDialogPrivate::retranslateStrings()\n{\n    familyAccel->setText(QFontDialog::tr(\"&Font\"));\n    styleAccel->setText(QFontDialog::tr(\"Font st&yle\"));\n    sizeAccel->setText(QFontDialog::tr(\"&Size\"));\n    effects->setTitle(QFontDialog::tr(\"Effects\"));\n    strikeout->setText(QFontDialog::tr(\"Stri&keout\"));\n    underline->setText(QFontDialog::tr(\"&Underline\"));\n    sample->setTitle(QFontDialog::tr(\"Sample\"));\n    writingSystemAccel->setText(QFontDialog::tr(\"Wr&iting System\"));\n}\n\n/*!\n    \\reimp\n*/\nvoid QFontDialog::changeEvent(QEvent *e)\n{\n    Q_D(QFontDialog);\n    if (e->type() == QEvent::LanguageChange) {\n        d->retranslateStrings();\n    }\n    QDialog::changeEvent(e);\n}\n\n/*!\n    \\property QFontDialog::currentFont\n    \\brief the current font of the dialog.\n*/\n\n/*!\n    Sets the font highlighted in the QFontDialog to the given \\a font.\n\n    \\sa selectedFont()\n*/\nvoid QFontDialog::setCurrentFont(const QFont &font)\n{\n    Q_D(QFontDialog);\n    d->family = font.families().value(0);\n    d->style = QFontDatabase::styleString(font);\n    d->size = font.pointSize();\n    if (d->size == -1) {\n        QFontInfo fi(font);\n        d->size = fi.pointSize();\n    }\n    d->strikeout->setChecked(font.strikeOut());\n    d->underline->setChecked(font.underline());\n    d->updateFamilies();\n\n    if (d->nativeDialogInUse) {\n        if (QPlatformFontDialogHelper *helper = d->platformFontDialogHelper())\n            helper->setCurrentFont(font);\n    }\n}\n\n/*!\n    Returns the current font.\n\n    \\sa selectedFont()\n*/\nQFont QFontDialog::currentFont() const\n{\n    Q_D(const QFontDialog);\n\n    if (d->nativeDialogInUse) {\n        if (const QPlatformFontDialogHelper *helper = d->platformFontDialogHelper())\n            return helper->currentFont();\n    }\n    return d->sampleEdit->font();\n}\n\n/*!\n    Returns the font that the user selected by clicking the \\uicontrol{OK}\n    or equivalent button.\n\n    \\note This font is not always the same as the font held by the\n    \\l currentFont property since the user can choose different fonts\n    before finally selecting the one to use.\n*/\nQFont QFontDialog::selectedFont() const\n{\n    Q_D(const QFontDialog);\n    return d->selectedFont;\n}\n\n/*!\n    \\enum QFontDialog::FontDialogOption\n\n    This enum specifies various options that affect the look and feel\n    of a font dialog.\n\n    For instance, it allows to specify which type of font should be\n    displayed. If none are specified all fonts available will be listed.\n\n    Note that the font filtering options might not be supported on some\n    platforms (e.g. Mac). They are always supported by the non native\n    dialog (used on Windows or Linux).\n\n    \\value NoButtons Don't display \\uicontrol{OK} and \\uicontrol{Cancel} buttons. (Useful for \"live dialogs\".)\n    \\value DontUseNativeDialog Use Qt's standard font dialog on the Mac instead of Apple's\n                               native font panel.\n    \\value ScalableFonts Show scalable fonts\n    \\value NonScalableFonts Show non scalable fonts\n    \\value MonospacedFonts Show monospaced fonts\n    \\value ProportionalFonts Show proportional fonts\n\n    \\sa options, setOption(), testOption()\n*/\n\n/*!\n    Sets the given \\a option to be enabled if \\a on is true;\n    otherwise, clears the given \\a option.\n\n    \\sa options, testOption()\n*/\nvoid QFontDialog::setOption(FontDialogOption option, bool on)\n{\n    const QFontDialog::FontDialogOptions previousOptions = options();\n    if (!(previousOptions & option) != !on)\n        setOptions(previousOptions ^ option);\n}\n\n/*!\n    Returns \\c true if the given \\a option is enabled; otherwise, returns\n    false.\n\n    \\sa options, setOption()\n*/\nbool QFontDialog::testOption(FontDialogOption option) const\n{\n    Q_D(const QFontDialog);\n    return d->options->testOption(static_cast<QFontDialogOptions::FontDialogOption>(option));\n}\n\n/*!\n    \\property QFontDialog::options\n    \\brief the various options that affect the look and feel of the dialog\n\n    By default, all options are disabled.\n\n    Options should be set before showing the dialog. Setting them while the\n    dialog is visible is not guaranteed to have an immediate effect on the\n    dialog (depending on the option and on the platform).\n\n    \\sa setOption(), testOption()\n*/\nvoid QFontDialog::setOptions(FontDialogOptions options)\n{\n    Q_D(QFontDialog);\n\n    if (QFontDialog::options() == options)\n        return;\n\n    d->options->setOptions(QFontDialogOptions::FontDialogOptions(int(options)));\n    d->buttonBox->setVisible(!(options & NoButtons));\n}\n\nQFontDialog::FontDialogOptions QFontDialog::options() const\n{\n    Q_D(const QFontDialog);\n    return QFontDialog::FontDialogOptions(int(d->options->options()));\n}\n\n/*!\n    Opens the dialog and connects its fontSelected() signal to the slot specified\n    by \\a receiver and \\a member.\n\n    The signal will be disconnected from the slot when the dialog is closed.\n*/\nvoid QFontDialog::open(QObject *receiver, const char *member)\n{\n    Q_D(QFontDialog);\n    connect(this, SIGNAL(fontSelected(QFont)), receiver, member);\n    d->receiverToDisconnectOnClose = receiver;\n    d->memberToDisconnectOnClose = member;\n    QDialog::open();\n}\n\n/*!\n    \\fn void QFontDialog::currentFontChanged(const QFont &font)\n\n    This signal is emitted when the current font is changed. The new font is\n    specified in \\a font.\n\n    The signal is emitted while a user is selecting a font. Ultimately, the\n    chosen font may differ from the font currently selected.\n\n    \\sa currentFont, fontSelected(), selectedFont()\n*/\n\n/*!\n    \\fn void QFontDialog::fontSelected(const QFont &font)\n\n    This signal is emitted when a font has been selected. The selected font is\n    specified in \\a font.\n\n    The signal is only emitted when a user has chosen the final font to be\n    used. It is not emitted while the user is changing the current font in the\n    font dialog.\n\n    \\sa selectedFont(), currentFontChanged(), currentFont\n*/\n\n/*!\n    \\reimp\n*/\nvoid QFontDialog::setVisible(bool visible)\n{\n    // will call QFontDialogPrivate::setVisible\n    QDialog::setVisible(visible);\n}\n\n/*!\n    \\internal\n\n    The implementation of QFontDialog::setVisible() has to live here so that the call\n    to hide() in ~QDialog calls this function; it wouldn't call the override of\n    QDialog::setVisible().\n*/\nvoid QFontDialogPrivate::setVisible(bool visible)\n{\n    Q_Q(QFontDialog);\n\n    if (canBeNativeDialog())\n        setNativeDialogVisible(visible);\n    if (nativeDialogInUse) {\n        // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below\n        // updates the state correctly, but skips showing the non-native version:\n        q->setAttribute(Qt::WA_DontShowOnScreen, true);\n    } else {\n        q->setAttribute(Qt::WA_DontShowOnScreen, false);\n    }\n    QDialogPrivate::setVisible(visible);\n}\n\n/*!\n  Closes the dialog and sets its result code to \\a result. If this dialog\n  is shown with exec(), done() causes the local event loop to finish,\n  and exec() to return \\a result.\n\n  \\sa QDialog::done()\n*/\nvoid QFontDialog::done(int result)\n{\n    Q_D(QFontDialog);\n    if (result == Accepted) {\n        // We check if this is the same font we had before, if so we emit currentFontChanged\n        QFont selectedFont = currentFont();\n        if (selectedFont != d->selectedFont)\n            emit(currentFontChanged(selectedFont));\n        d->selectedFont = selectedFont;\n        emit fontSelected(d->selectedFont);\n    } else\n        d->selectedFont = QFont();\n    if (d->receiverToDisconnectOnClose) {\n        disconnect(this, SIGNAL(fontSelected(QFont)),\n                   d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);\n        d->receiverToDisconnectOnClose = nullptr;\n    }\n    d->memberToDisconnectOnClose.clear();\n    QDialog::done(result);\n}\n\nbool QFontDialogPrivate::canBeNativeDialog() const\n{\n    // Don't use Q_Q here! This function is called from ~QDialog,\n    // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).\n    const QDialog * const q = static_cast<const QDialog*>(q_ptr);\n    if (nativeDialogInUse)\n        return true;\n    if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)\n        || q->testAttribute(Qt::WA_DontShowOnScreen)\n        || (options->options() & QFontDialog::DontUseNativeDialog)) {\n        return false;\n    }\n\n    return strcmp(QFontDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;\n}\n\nQT_END_NAMESPACE\n\n#include \"qfontdialog.moc\"\n#include \"moc_qfontdialog.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qhelpsearchquerywidget.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qhelpsearchquerywidget.h\"\n\n#include <QtCore/qabstractitemmodel.h>\n#include <QtCore/qstringlist.h>\n#include <QtGui/qevent.h>\n#include <QtWidgets/qcompleter.h>\n#include <QtWidgets/qlabel.h>\n#include <QtWidgets/qlayout.h>\n#include <QtWidgets/qlineedit.h>\n#include <QtWidgets/qpushbutton.h>\n#include <QtWidgets/qtoolbutton.h>\n\nQT_BEGIN_NAMESPACE\n\nclass QHelpSearchQueryWidgetPrivate : public QObject\n{\npublic:\n    struct QueryHistory {\n        explicit QueryHistory() : curQuery(-1) {}\n        QStringList queries;\n        int curQuery = 0;\n    };\n\n    class CompleterModel : public QAbstractListModel\n    {\n    public:\n        explicit CompleterModel(QObject *parent) : QAbstractListModel(parent) { }\n\n        int rowCount(const QModelIndex &parent = QModelIndex()) const override\n        {\n            return parent.isValid() ? 0 : termList.size();\n        }\n\n        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override\n        {\n            if (!index.isValid() || index.row() >= termList.size()||\n                (role != Qt::EditRole && role != Qt::DisplayRole))\n                return {};\n            return termList.at(index.row());\n        }\n\n        void addTerm(const QString &term)\n        {\n            if (!termList.contains(term)) {\n                beginResetModel();\n                termList.append(term);\n                endResetModel();\n            }\n        }\n\n    private:\n        QStringList termList;\n    };\n\n    QHelpSearchQueryWidgetPrivate() : m_searchCompleter(new CompleterModel(this), this) {}\n\n    void retranslate()\n    {\n        m_searchLabel->setText(QHelpSearchQueryWidget::tr(\"Search for:\"));\n        m_searchButton->setText(QHelpSearchQueryWidget::tr(\"Search\"));\n#if QT_CONFIG(tooltip)\n        m_prevQueryButton->setToolTip(QHelpSearchQueryWidget::tr(\"Previous search\"));\n        m_nextQueryButton->setToolTip(QHelpSearchQueryWidget::tr(\"Next search\"));\n#endif\n    }\n\n    void saveQuery(const QString &query)\n    {\n        // We only add the query to the list if it is different from the last one.\n        if (!m_queries.queries.isEmpty() && m_queries.queries.last() == query)\n            return;\n\n        m_queries.queries.append(query);\n        static_cast<CompleterModel *>(m_searchCompleter.model())->addTerm(query);\n    }\n\n    void nextOrPrevQuery(int maxOrMinIndex, int addend, QToolButton *thisButton,\n        QToolButton *otherButton)\n    {\n        m_lineEdit->clear();\n\n        // Otherwise, the respective button would be disabled.\n        Q_ASSERT(m_queries.curQuery != maxOrMinIndex);\n\n        m_queries.curQuery = qBound(0, m_queries.curQuery + addend, m_queries.queries.size() - 1);\n        const QString &query = m_queries.queries.at(m_queries.curQuery);\n        m_lineEdit->setText(query);\n\n        if (m_queries.curQuery == maxOrMinIndex)\n            thisButton->setEnabled(false);\n        otherButton->setEnabled(true);\n    }\n\n    void enableOrDisableToolButtons()\n    {\n        m_prevQueryButton->setEnabled(m_queries.curQuery > 0);\n        m_nextQueryButton->setEnabled(m_queries.curQuery < m_queries.queries.size() - 1);\n    }\n\n    bool eventFilter(QObject *ob, QEvent *event) override\n    {\n        if (event->type() == QEvent::KeyPress) {\n            QKeyEvent *const keyEvent = static_cast<QKeyEvent *>(event);\n            if (keyEvent->key() == Qt::Key_Down) {\n                if (m_queries.curQuery + 1 < m_queries.queries.size())\n                    nextQuery();\n                return true;\n            }\n            if (keyEvent->key() == Qt::Key_Up) {\n                if (m_queries.curQuery > 0)\n                    prevQuery();\n                return true;\n            }\n        }\n        return QObject::eventFilter(ob, event);\n    }\n\n    void searchRequested()\n    {\n        saveQuery(m_lineEdit->text());\n        m_queries.curQuery = m_queries.queries.size() - 1;\n        if (m_queries.curQuery > 0)\n            m_prevQueryButton->setEnabled(true);\n        m_nextQueryButton->setEnabled(false);\n    }\n\n    void nextQuery()\n    {\n        nextOrPrevQuery(m_queries.queries.size() - 1, 1, m_nextQueryButton, m_prevQueryButton);\n    }\n\n    void prevQuery() { nextOrPrevQuery(0, -1, m_prevQueryButton, m_nextQueryButton); }\n\n    QLabel *m_searchLabel = nullptr;\n    QPushButton *m_searchButton = nullptr;\n    QLineEdit *m_lineEdit = nullptr;\n    QToolButton *m_nextQueryButton = nullptr;\n    QToolButton *m_prevQueryButton = nullptr;\n    QueryHistory m_queries;\n    QCompleter m_searchCompleter;\n    bool m_compactMode = false;\n};\n\n/*!\n    \\class QHelpSearchQueryWidget\n    \\since 4.4\n    \\inmodule QtHelp\n    \\brief The QHelpSearchQueryWidget class provides a simple line edit or\n    an advanced widget to enable the user to input a search term in a\n    standardized input mask.\n*/\n\n/*!\n    \\fn void QHelpSearchQueryWidget::search()\n\n    This signal is emitted when a the user has the search button invoked.\n    After receiving the signal you can ask the QHelpSearchQueryWidget for the\n    search input that you may pass to the QHelpSearchEngine::search() function.\n*/\n\n/*!\n    Constructs a new search query widget with the given \\a parent.\n*/\nQHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent)\n    : QWidget(parent)\n    , d(new QHelpSearchQueryWidgetPrivate)\n{\n    QVBoxLayout *vLayout = new QVBoxLayout(this);\n    vLayout->setContentsMargins({});\n\n    QHBoxLayout* hBoxLayout = new QHBoxLayout;\n    d->m_searchLabel = new QLabel(this);\n    d->m_lineEdit = new QLineEdit(this);\n    d->m_lineEdit->setClearButtonEnabled(true);\n    d->m_lineEdit->setCompleter(&d->m_searchCompleter);\n    d->m_lineEdit->installEventFilter(d);\n    d->m_prevQueryButton = new QToolButton(this);\n    d->m_prevQueryButton->setArrowType(Qt::LeftArrow);\n    d->m_prevQueryButton->setEnabled(false);\n    d->m_nextQueryButton = new QToolButton(this);\n    d->m_nextQueryButton->setArrowType(Qt::RightArrow);\n    d->m_nextQueryButton->setEnabled(false);\n    d->m_searchButton = new QPushButton(this);\n    hBoxLayout->addWidget(d->m_searchLabel);\n    hBoxLayout->addWidget(d->m_lineEdit);\n    hBoxLayout->addWidget(d->m_prevQueryButton);\n    hBoxLayout->addWidget(d->m_nextQueryButton);\n    hBoxLayout->addWidget(d->m_searchButton);\n\n    vLayout->addLayout(hBoxLayout);\n\n    connect(d->m_prevQueryButton, &QAbstractButton::clicked, this, [this] { d->prevQuery(); });\n    connect(d->m_nextQueryButton, &QAbstractButton::clicked, this, [this] { d->nextQuery(); });\n    connect(d->m_searchButton, &QAbstractButton::clicked, this, &QHelpSearchQueryWidget::search);\n    connect(d->m_lineEdit, &QLineEdit::returnPressed, this, &QHelpSearchQueryWidget::search);\n\n    d->retranslate();\n    connect(this, &QHelpSearchQueryWidget::search, this, [this] { d->searchRequested(); });\n    setCompactMode(true);\n}\n\n/*!\n    Destroys the search query widget.\n*/\nQHelpSearchQueryWidget::~QHelpSearchQueryWidget()\n{\n    delete d;\n}\n\n/*!\n    Expands the search query widget so that the extended search fields are shown.\n*/\nvoid QHelpSearchQueryWidget::expandExtendedSearch()\n{\n    // TODO: no extended search anymore, deprecate it?\n}\n\n/*!\n    Collapses the search query widget so that only the default search field is\n    shown.\n*/\nvoid QHelpSearchQueryWidget::collapseExtendedSearch()\n{\n    // TODO: no extended search anymore, deprecate it?\n}\n\n#if QT_DEPRECATED_SINCE(5, 9)\nQT_WARNING_PUSH\nQT_WARNING_DISABLE_DEPRECATED\n/*!\n    \\deprecated\n\n    Use searchInput() instead.\n*/\nQList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const\n{\n    return {{QHelpSearchQuery::DEFAULT, searchInput().split(QChar::Space, Qt::SkipEmptyParts)}};\n}\n\n/*!\n    \\deprecated\n\n    Use setSearchInput() instead.\n*/\nvoid QHelpSearchQueryWidget::setQuery(const QList<QHelpSearchQuery> &queryList)\n{\n    if (queryList.isEmpty())\n        return;\n\n    setSearchInput(queryList.first().wordList.join(QChar::Space));\n}\nQT_WARNING_POP\n#endif // QT_DEPRECATED_SINCE(5, 9)\n\n/*!\n    \\since 5.9\n\n    Returns a search phrase to use in combination with the\n    QHelpSearchEngine::search(const QString &searchInput) function.\n*/\nQString QHelpSearchQueryWidget::searchInput() const\n{\n    if (d->m_queries.queries.isEmpty())\n        return {};\n    return d->m_queries.queries.last();\n}\n\n/*!\n    \\since 5.9\n\n    Sets the QHelpSearchQueryWidget input field to the value specified by\n    \\a searchInput.\n\n    \\note The QHelpSearchEngine::search(const QString &searchInput) function has\n    to be called to perform the actual search.\n*/\nvoid QHelpSearchQueryWidget::setSearchInput(const QString &searchInput)\n{\n    d->m_lineEdit->clear();\n    d->m_lineEdit->setText(searchInput);\n    d->searchRequested();\n}\n\nbool QHelpSearchQueryWidget::isCompactMode() const\n{\n    return d->m_compactMode;\n}\n\nvoid QHelpSearchQueryWidget::setCompactMode(bool on)\n{\n    if (d->m_compactMode != on) {\n        d->m_compactMode = on;\n        d->m_prevQueryButton->setVisible(!on);\n        d->m_nextQueryButton->setVisible(!on);\n        d->m_searchLabel->setVisible(!on);\n    }\n}\n\n/*!\n    \\reimp\n*/\nvoid QHelpSearchQueryWidget::focusInEvent(QFocusEvent *focusEvent)\n{\n    if (focusEvent->reason() != Qt::MouseFocusReason) {\n        d->m_lineEdit->selectAll();\n        d->m_lineEdit->setFocus();\n    }\n}\n\n/*!\n    \\reimp\n*/\nvoid QHelpSearchQueryWidget::changeEvent(QEvent *event)\n{\n    if (event->type() == QEvent::LanguageChange)\n        d->retranslate();\n    else\n        QWidget::changeEvent(event);\n}\n\nQT_END_NAMESPACE\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qinputdialog.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qinputdialog.h\"\n\n#include \"qapplication.h\"\n#include \"qcombobox.h\"\n#include \"qdialogbuttonbox.h\"\n#include \"qlabel.h\"\n#include \"qlayout.h\"\n#include \"qlineedit.h\"\n#include \"qplaintextedit.h\"\n#include \"qlistview.h\"\n#include \"qpushbutton.h\"\n#include \"qspinbox.h\"\n#include \"qstackedlayout.h\"\n#include \"qvalidator.h\"\n#include \"qevent.h\"\n#include \"qdialog_p.h\"\n\n#include <QtCore/qpointer.h>\n\nQT_USE_NAMESPACE\n\nenum CandidateSignal {\n    TextValueSelectedSignal,\n    IntValueSelectedSignal,\n    DoubleValueSelectedSignal,\n\n    NumCandidateSignals\n};\n\nstatic const char *candidateSignal(int which)\n{\n    switch (CandidateSignal(which)) {\n    case TextValueSelectedSignal:   return SIGNAL(textValueSelected(QString));\n    case IntValueSelectedSignal:    return SIGNAL(intValueSelected(int));\n    case DoubleValueSelectedSignal: return SIGNAL(doubleValueSelected(double));\n\n    case NumCandidateSignals:\n        break;\n    };\n    Q_UNREACHABLE_RETURN(nullptr);\n}\n\nstatic const char *signalForMember(const char *member)\n{\n    QByteArray normalizedMember(QMetaObject::normalizedSignature(member));\n\n    for (int i = 0; i < NumCandidateSignals; ++i)\n        if (QMetaObject::checkConnectArgs(candidateSignal(i), normalizedMember))\n            return candidateSignal(i);\n\n    // otherwise, use fit-all accepted signal:\n    return SIGNAL(accepted());\n}\n\nQT_BEGIN_NAMESPACE\n\n/*\n    These internal classes add extra validation to QSpinBox and QDoubleSpinBox by emitting\n    textChanged(bool) after events that may potentially change the visible text. Return or\n    Enter key presses are not propagated if the visible text is invalid. Instead, the visible\n    text is modified to the last valid value.\n*/\nclass QInputDialogSpinBox : public QSpinBox\n{\n    Q_OBJECT\n\npublic:\n    QInputDialogSpinBox(QWidget *parent)\n        : QSpinBox(parent) {\n        connect(lineEdit(), &QLineEdit::textChanged,\n                this, &QInputDialogSpinBox::notifyTextChanged);\n        connect(this, &QInputDialogSpinBox::editingFinished,\n                this, &QInputDialogSpinBox::notifyTextChanged);\n    }\n\nsignals:\n    void textChanged(bool);\n\nprivate slots:\n    void notifyTextChanged() { emit textChanged(hasAcceptableInput()); }\n\nprivate:\n    void keyPressEvent(QKeyEvent *event) override {\n        if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && !hasAcceptableInput()) {\n            setProperty(\"value\", property(\"value\"));\n        } else {\n            QSpinBox::keyPressEvent(event);\n        }\n        notifyTextChanged();\n    }\n\n    void mousePressEvent(QMouseEvent *event) override {\n        QSpinBox::mousePressEvent(event);\n        notifyTextChanged();\n    }\n};\n\nclass QInputDialogDoubleSpinBox : public QDoubleSpinBox\n{\n    Q_OBJECT\n\npublic:\n    QInputDialogDoubleSpinBox(QWidget *parent = nullptr)\n        : QDoubleSpinBox(parent) {\n        connect(lineEdit(), &QLineEdit::textChanged,\n                this, &QInputDialogDoubleSpinBox::notifyTextChanged);\n        connect(this, &QInputDialogDoubleSpinBox::editingFinished,\n                this, &QInputDialogDoubleSpinBox::notifyTextChanged);\n    }\n\nsignals:\n    void textChanged(bool);\n\nprivate slots:\n    void notifyTextChanged() { emit textChanged(hasAcceptableInput()); }\n\nprivate:\n    void keyPressEvent(QKeyEvent *event) override {\n        if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && !hasAcceptableInput()) {\n            setProperty(\"value\", property(\"value\"));\n        } else {\n            QDoubleSpinBox::keyPressEvent(event);\n        }\n        notifyTextChanged();\n    }\n\n    void mousePressEvent(QMouseEvent *event) override {\n        QDoubleSpinBox::mousePressEvent(event);\n        notifyTextChanged();\n    }\n};\n\nclass QInputDialogListView : public QListView\n{\npublic:\n    QInputDialogListView(QWidget *parent = nullptr) : QListView(parent) {}\n    QVariant inputMethodQuery(Qt::InputMethodQuery query) const override\n    {\n        if (query == Qt::ImEnabled)\n            return false;\n        return QListView::inputMethodQuery(query);\n    }\n};\n\nclass QInputDialogPrivate : public QDialogPrivate\n{\n    Q_DECLARE_PUBLIC(QInputDialog)\n\npublic:\n    QInputDialogPrivate();\n\n    void ensureLayout();\n    void ensureLineEdit();\n    void ensurePlainTextEdit();\n    void ensureComboBox();\n    void ensureListView();\n    void ensureIntSpinBox();\n    void ensureDoubleSpinBox();\n    void ensureEnabledConnection(QAbstractSpinBox *spinBox);\n    void setInputWidget(QWidget *widget);\n    void chooseRightTextInputWidget();\n    void setComboBoxText(const QString &text);\n    void setListViewText(const QString &text);\n    QString listViewText() const;\n    void ensureLayout() const { const_cast<QInputDialogPrivate *>(this)->ensureLayout(); }\n    bool useComboBoxOrListView() const { return comboBox && comboBox->count() > 0; }\n    void textChanged(const QString &text);\n    void plainTextEditTextChanged();\n    void currentRowChanged(const QModelIndex &newIndex, const QModelIndex &oldIndex);\n\n    mutable QLabel *label;\n    mutable QDialogButtonBox *buttonBox;\n    mutable QLineEdit *lineEdit;\n    mutable QPlainTextEdit *plainTextEdit;\n    mutable QSpinBox *intSpinBox;\n    mutable QDoubleSpinBox *doubleSpinBox;\n    mutable QComboBox *comboBox;\n    mutable QInputDialogListView *listView;\n    mutable QWidget *inputWidget;\n    mutable QVBoxLayout *mainLayout;\n    QInputDialog::InputDialogOptions opts;\n    QString textValue;\n    QPointer<QObject> receiverToDisconnectOnClose;\n    QByteArray memberToDisconnectOnClose;\n};\n\nQInputDialogPrivate::QInputDialogPrivate()\n    : label(nullptr), buttonBox(nullptr), lineEdit(nullptr), plainTextEdit(nullptr), intSpinBox(nullptr), doubleSpinBox(nullptr),\n      comboBox(nullptr), listView(nullptr), inputWidget(nullptr), mainLayout(nullptr)\n{\n}\n\nvoid QInputDialogPrivate::ensureLayout()\n{\n    Q_Q(QInputDialog);\n\n    if (mainLayout)\n        return;\n\n    if (!inputWidget) {\n        ensureLineEdit();\n        inputWidget = lineEdit;\n    }\n\n    if (!label)\n        label = new QLabel(QInputDialog::tr(\"Enter a value:\"), q);\n#ifndef QT_NO_SHORTCUT\n    label->setBuddy(inputWidget);\n#endif\n    label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);\n\n    buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);\n    QObject::connect(buttonBox, &QDialogButtonBox::accepted, q, &QDialog::accept);\n    QObject::connect(buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject);\n\n    mainLayout = new QVBoxLayout(q);\n    mainLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);\n    mainLayout->addWidget(label);\n    mainLayout->addWidget(inputWidget);\n    mainLayout->addWidget(buttonBox);\n    ensureEnabledConnection(qobject_cast<QAbstractSpinBox *>(inputWidget));\n    inputWidget->show();\n}\n\nvoid QInputDialogPrivate::ensureLineEdit()\n{\n    Q_Q(QInputDialog);\n    if (!lineEdit) {\n        lineEdit = new QLineEdit(q);\n#ifndef QT_NO_IM\n        qt_widget_private(lineEdit)->inheritsInputMethodHints = 1;\n#endif\n        lineEdit->hide();\n        QObjectPrivate::connect(lineEdit, &QLineEdit::textChanged,\n                                this, &QInputDialogPrivate::textChanged);\n    }\n}\n\nvoid QInputDialogPrivate::ensurePlainTextEdit()\n{\n    Q_Q(QInputDialog);\n    if (!plainTextEdit) {\n        plainTextEdit = new QPlainTextEdit(q);\n        plainTextEdit->setLineWrapMode(QPlainTextEdit::NoWrap);\n#ifndef QT_NO_IM\n        qt_widget_private(plainTextEdit)->inheritsInputMethodHints = 1;\n#endif\n        plainTextEdit->hide();\n        QObjectPrivate::connect(plainTextEdit, &QPlainTextEdit::textChanged,\n                                this, &QInputDialogPrivate::plainTextEditTextChanged);\n    }\n}\n\nvoid QInputDialogPrivate::ensureComboBox()\n{\n    Q_Q(QInputDialog);\n    if (!comboBox) {\n        comboBox = new QComboBox(q);\n#ifndef QT_NO_IM\n        qt_widget_private(comboBox)->inheritsInputMethodHints = 1;\n#endif\n        comboBox->hide();\n        QObjectPrivate::connect(comboBox, &QComboBox::editTextChanged,\n                                this, &QInputDialogPrivate::textChanged);\n        QObjectPrivate::connect(comboBox, &QComboBox::currentTextChanged,\n                                this, &QInputDialogPrivate::textChanged);\n    }\n}\n\nvoid QInputDialogPrivate::ensureListView()\n{\n    Q_Q(QInputDialog);\n    if (!listView) {\n        ensureComboBox();\n        listView = new QInputDialogListView(q);\n        listView->hide();\n        listView->setEditTriggers(QAbstractItemView::NoEditTriggers);\n        listView->setSelectionMode(QAbstractItemView::SingleSelection);\n        listView->setModel(comboBox->model());\n        listView->setCurrentIndex(QModelIndex()); // ###\n        QObjectPrivate::connect(listView->selectionModel(),\n                                &QItemSelectionModel::currentRowChanged,\n                                this, &QInputDialogPrivate::currentRowChanged);\n    }\n}\n\nvoid QInputDialogPrivate::ensureIntSpinBox()\n{\n    Q_Q(QInputDialog);\n    if (!intSpinBox) {\n        intSpinBox = new QInputDialogSpinBox(q);\n        intSpinBox->hide();\n        QObject::connect(intSpinBox, &QInputDialogSpinBox::valueChanged,\n                         q, &QInputDialog::intValueChanged);\n    }\n}\n\nvoid QInputDialogPrivate::ensureDoubleSpinBox()\n{\n    Q_Q(QInputDialog);\n    if (!doubleSpinBox) {\n        doubleSpinBox = new QInputDialogDoubleSpinBox(q);\n        doubleSpinBox->hide();\n        QObject::connect(doubleSpinBox, &QInputDialogDoubleSpinBox::valueChanged,\n                         q, &QInputDialog::doubleValueChanged);\n    }\n}\n\nvoid QInputDialogPrivate::ensureEnabledConnection(QAbstractSpinBox *spinBox)\n{\n    if (spinBox) {\n        QAbstractButton *okButton = buttonBox->button(QDialogButtonBox::Ok);\n        QObject::connect(spinBox, SIGNAL(textChanged(bool)), okButton, SLOT(setEnabled(bool)), Qt::UniqueConnection);\n    }\n}\n\nvoid QInputDialogPrivate::setInputWidget(QWidget *widget)\n{\n    Q_ASSERT(widget);\n    if (inputWidget == widget)\n        return;\n\n    if (mainLayout) {\n        Q_ASSERT(inputWidget);\n        mainLayout->removeWidget(inputWidget);\n        inputWidget->hide();\n        mainLayout->insertWidget(1, widget);\n        widget->show();\n\n        // disconnect old input widget\n        QAbstractButton *okButton = buttonBox->button(QDialogButtonBox::Ok);\n        if (QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(inputWidget))\n            QObject::disconnect(spinBox, SIGNAL(textChanged(bool)), okButton, SLOT(setEnabled(bool)));\n\n        // connect new input widget and update enabled state of OK button\n        QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(widget);\n        ensureEnabledConnection(spinBox);\n        okButton->setEnabled(!spinBox || spinBox->hasAcceptableInput());\n    }\n\n    inputWidget = widget;\n\n    // synchronize the text shown in the new text editor with the current\n    // textValue\n    if (widget == lineEdit) {\n        lineEdit->setText(textValue);\n    } else if (widget == plainTextEdit) {\n        plainTextEdit->setPlainText(textValue);\n    } else if (widget == comboBox) {\n        setComboBoxText(textValue);\n    } else if (widget == listView) {\n        setListViewText(textValue);\n        ensureLayout();\n        buttonBox->button(QDialogButtonBox::Ok)->setEnabled(listView->selectionModel()->hasSelection());\n    }\n}\n\nvoid QInputDialogPrivate::chooseRightTextInputWidget()\n{\n    QWidget *widget;\n\n    if (useComboBoxOrListView()) {\n        if ((opts & QInputDialog::UseListViewForComboBoxItems) && !comboBox->isEditable()) {\n            ensureListView();\n            widget = listView;\n        } else {\n            widget = comboBox;\n        }\n    } else if (opts & QInputDialog::UsePlainTextEditForTextInput) {\n        ensurePlainTextEdit();\n        widget = plainTextEdit;\n    } else {\n        ensureLineEdit();\n        widget = lineEdit;\n    }\n\n    setInputWidget(widget);\n\n    if (inputWidget == comboBox) {\n        textChanged(comboBox->currentText());\n    } else if (inputWidget == listView) {\n        textChanged(listViewText());\n    }\n}\n\nvoid QInputDialogPrivate::setComboBoxText(const QString &text)\n{\n    int index = comboBox->findText(text);\n    if (index != -1) {\n        comboBox->setCurrentIndex(index);\n    } else if (comboBox->isEditable()) {\n        comboBox->setEditText(text);\n    }\n}\n\nvoid QInputDialogPrivate::setListViewText(const QString &text)\n{\n    int row = comboBox->findText(text);\n    if (row != -1) {\n        QModelIndex index(comboBox->model()->index(row, 0));\n        listView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Clear\n                                                         | QItemSelectionModel::SelectCurrent);\n    }\n}\n\nQString QInputDialogPrivate::listViewText() const\n{\n    if (listView->selectionModel()->hasSelection()) {\n        int row = listView->selectionModel()->selectedRows().value(0).row();\n        return comboBox->itemText(row);\n    } else {\n        return QString();\n    }\n}\n\nvoid QInputDialogPrivate::textChanged(const QString &text)\n{\n    Q_Q(QInputDialog);\n    if (textValue != text) {\n        textValue = text;\n        emit q->textValueChanged(text);\n    }\n}\n\nvoid QInputDialogPrivate::plainTextEditTextChanged()\n{\n    Q_Q(QInputDialog);\n    QString text = plainTextEdit->toPlainText();\n    if (textValue != text) {\n        textValue = text;\n        emit q->textValueChanged(text);\n    }\n}\n\nvoid QInputDialogPrivate::currentRowChanged(const QModelIndex &newIndex,\n                                            const QModelIndex & /* oldIndex */)\n{\n    textChanged(comboBox->model()->data(newIndex).toString());\n    buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);\n}\n\n/*!\n    \\class QInputDialog\n    \\brief The QInputDialog class provides a simple convenience dialog to get a\n    single value from the user.\n    \\ingroup standard-dialogs\n    \\inmodule QtWidgets\n\n    The input value can be a string, a number or an item from a list. A label\n    must be set to tell the user what they should enter.\n\n    Five static convenience functions are provided: getText(), getMultiLineText(),\n    getInt(), getDouble(), and getItem(). All the functions can be used in a similar way,\n    for example:\n\n    \\snippet dialogs/standarddialogs/dialog.cpp 3\n\n    The \\c ok variable is set to true if the user clicks \\uicontrol OK; otherwise, it\n    is set to false.\n\n    \\image inputdialogs.png Input Dialogs\n\n    The \\l{dialogs/standarddialogs}{Standard Dialogs} example shows how to use\n    QInputDialog as well as other built-in Qt dialogs.\n\n    \\sa QMessageBox, {Standard Dialogs Example}\n*/\n\n/*!\n    \\enum QInputDialog::InputMode\n\n    This enum describes the different modes of input that can be selected for\n    the dialog.\n\n    \\value TextInput   Used to input text strings.\n    \\value IntInput    Used to input integers.\n    \\value DoubleInput Used to input floating point numbers with double\n                       precision accuracy.\n\n    \\sa inputMode\n*/\n\n/*!\n    Constructs a new input dialog with the given \\a parent and window \\a flags.\n*/\nQInputDialog::QInputDialog(QWidget *parent, Qt::WindowFlags flags)\n    : QDialog(*new QInputDialogPrivate, parent, flags)\n{\n}\n\n/*!\n    Destroys the input dialog.\n*/\nQInputDialog::~QInputDialog()\n{\n}\n\n/*!\n    \\property QInputDialog::inputMode\n\n    \\brief the mode used for input\n\n    This property helps determine which widget is used for entering input into\n    the dialog.\n*/\nvoid QInputDialog::setInputMode(InputMode mode)\n{\n    Q_D(QInputDialog);\n\n    QWidget *widget;\n\n    /*\n        Warning: Some functions in QInputDialog rely on implementation details\n        of the code below. Look for the comments that accompany the calls to\n        setInputMode() throughout this file before you change the code below.\n    */\n\n    switch (mode) {\n    case IntInput:\n        d->ensureIntSpinBox();\n        widget = d->intSpinBox;\n        break;\n    case DoubleInput:\n        d->ensureDoubleSpinBox();\n        widget = d->doubleSpinBox;\n        break;\n    default:\n        Q_ASSERT(mode == TextInput);\n        d->chooseRightTextInputWidget();\n        return;\n    }\n\n    d->setInputWidget(widget);\n}\n\nQInputDialog::InputMode QInputDialog::inputMode() const\n{\n    Q_D(const QInputDialog);\n\n    if (d->inputWidget) {\n        if (d->inputWidget == d->intSpinBox) {\n            return IntInput;\n        } else if (d->inputWidget == d->doubleSpinBox) {\n            return DoubleInput;\n        }\n    }\n\n    return TextInput;\n}\n\n/*!\n    \\property QInputDialog::labelText\n\n    \\brief the label's text which describes what needs to be input\n*/\nvoid QInputDialog::setLabelText(const QString &text)\n{\n    Q_D(QInputDialog);\n    if (!d->label) {\n        d->label = new QLabel(text, this);\n    } else {\n        d->label->setText(text);\n    }\n}\n\nQString QInputDialog::labelText() const\n{\n    Q_D(const QInputDialog);\n    d->ensureLayout();\n    return d->label->text();\n}\n\n/*!\n    \\enum QInputDialog::InputDialogOption\n\n    This enum specifies various options that affect the look and feel\n    of an input dialog.\n\n    \\value NoButtons Don't display \\uicontrol{OK} and \\uicontrol{Cancel} buttons (useful for \"live dialogs\").\n    \\value UseListViewForComboBoxItems Use a QListView rather than a non-editable QComboBox for\n                                       displaying the items set with setComboBoxItems().\n    \\value UsePlainTextEditForTextInput Use a QPlainTextEdit for multiline text input. This value was\n                                       introduced in 5.2.\n\n    \\sa options, setOption(), testOption()\n*/\n\n/*!\n    Sets the given \\a option to be enabled if \\a on is true;\n    otherwise, clears the given \\a option.\n\n    \\sa options, testOption()\n*/\nvoid QInputDialog::setOption(InputDialogOption option, bool on)\n{\n    Q_D(QInputDialog);\n    if (!(d->opts & option) != !on)\n        setOptions(d->opts ^ option);\n}\n\n/*!\n    Returns \\c true if the given \\a option is enabled; otherwise, returns\n    false.\n\n    \\sa options, setOption()\n*/\nbool QInputDialog::testOption(InputDialogOption option) const\n{\n    Q_D(const QInputDialog);\n    return (d->opts & option) != 0;\n}\n\n/*!\n    \\property QInputDialog::options\n    \\brief the various options that affect the look and feel of the dialog\n\n    By default, all options are disabled.\n\n    \\sa setOption(), testOption()\n*/\nvoid QInputDialog::setOptions(InputDialogOptions options)\n{\n    Q_D(QInputDialog);\n\n    InputDialogOptions changed = (options ^ d->opts);\n    if (!changed)\n        return;\n\n    d->opts = options;\n    d->ensureLayout();\n\n    if (changed & NoButtons)\n        d->buttonBox->setVisible(!(options & NoButtons));\n    if ((changed & UseListViewForComboBoxItems) && inputMode() == TextInput)\n        d->chooseRightTextInputWidget();\n    if ((changed & UsePlainTextEditForTextInput) && inputMode() == TextInput)\n        d->chooseRightTextInputWidget();\n}\n\nQInputDialog::InputDialogOptions QInputDialog::options() const\n{\n    Q_D(const QInputDialog);\n    return d->opts;\n}\n\n/*!\n    \\property QInputDialog::textValue\n\n    \\brief the text value for the input dialog\n\n    This property is only relevant when the input dialog is used in\n    TextInput mode.\n*/\nvoid QInputDialog::setTextValue(const QString &text)\n{\n    Q_D(QInputDialog);\n\n    setInputMode(TextInput);\n    if (d->inputWidget == d->lineEdit) {\n        d->lineEdit->setText(text);\n    } else if (d->inputWidget == d->plainTextEdit) {\n        d->plainTextEdit->setPlainText(text);\n    } else if (d->inputWidget == d->comboBox) {\n        d->setComboBoxText(text);\n    } else {\n        d->setListViewText(text);\n    }\n}\n\nQString QInputDialog::textValue() const\n{\n    Q_D(const QInputDialog);\n    return d->textValue;\n}\n\n/*!\n    \\property QInputDialog::textEchoMode\n\n    \\brief the echo mode for the text value\n\n    This property is only relevant when the input dialog is used in\n    TextInput mode.\n*/\nvoid QInputDialog::setTextEchoMode(QLineEdit::EchoMode mode)\n{\n    Q_D(QInputDialog);\n    d->ensureLineEdit();\n    d->lineEdit->setEchoMode(mode);\n}\n\nQLineEdit::EchoMode QInputDialog::textEchoMode() const\n{\n    Q_D(const QInputDialog);\n    if (d->lineEdit) {\n        return d->lineEdit->echoMode();\n    } else {\n        return QLineEdit::Normal;\n    }\n}\n\n/*!\n    \\property QInputDialog::comboBoxEditable\n\n    \\brief whether or not the combo box used in the input dialog is editable\n*/\nvoid QInputDialog::setComboBoxEditable(bool editable)\n{\n    Q_D(QInputDialog);\n    d->ensureComboBox();\n    d->comboBox->setEditable(editable);\n    if (inputMode() == TextInput)\n        d->chooseRightTextInputWidget();\n}\n\nbool QInputDialog::isComboBoxEditable() const\n{\n    Q_D(const QInputDialog);\n    if (d->comboBox) {\n        return d->comboBox->isEditable();\n    } else {\n        return false;\n    }\n}\n\n/*!\n    \\property QInputDialog::comboBoxItems\n\n    \\brief the items used in the combo box for the input dialog\n*/\nvoid QInputDialog::setComboBoxItems(const QStringList &items)\n{\n    Q_D(QInputDialog);\n\n    d->ensureComboBox();\n    {\n        const QSignalBlocker blocker(d->comboBox);\n        d->comboBox->clear();\n        d->comboBox->addItems(items);\n    }\n\n    if (inputMode() == TextInput)\n        d->chooseRightTextInputWidget();\n}\n\nQStringList QInputDialog::comboBoxItems() const\n{\n    Q_D(const QInputDialog);\n    QStringList result;\n    if (d->comboBox) {\n        const int count = d->comboBox->count();\n        result.reserve(count);\n        for (int i = 0; i < count; ++i)\n            result.append(d->comboBox->itemText(i));\n    }\n    return result;\n}\n\n/*!\n    \\property QInputDialog::intValue\n    \\brief the current integer value accepted as input\n\n    This property is only relevant when the input dialog is used in\n    IntInput mode.\n*/\nvoid QInputDialog::setIntValue(int value)\n{\n    Q_D(QInputDialog);\n    setInputMode(IntInput);\n    d->intSpinBox->setValue(value);\n}\n\nint QInputDialog::intValue() const\n{\n    Q_D(const QInputDialog);\n    if (d->intSpinBox) {\n        return d->intSpinBox->value();\n    } else {\n        return 0;\n    }\n}\n\n/*!\n    \\property QInputDialog::intMinimum\n    \\brief the minimum integer value accepted as input\n\n    This property is only relevant when the input dialog is used in\n    IntInput mode.\n*/\nvoid QInputDialog::setIntMinimum(int min)\n{\n    Q_D(QInputDialog);\n    d->ensureIntSpinBox();\n    d->intSpinBox->setMinimum(min);\n}\n\nint QInputDialog::intMinimum() const\n{\n    Q_D(const QInputDialog);\n    if (d->intSpinBox) {\n        return d->intSpinBox->minimum();\n    } else {\n        return 0;\n    }\n}\n\n/*!\n    \\property QInputDialog::intMaximum\n    \\brief the maximum integer value accepted as input\n\n    This property is only relevant when the input dialog is used in\n    IntInput mode.\n*/\nvoid QInputDialog::setIntMaximum(int max)\n{\n    Q_D(QInputDialog);\n    d->ensureIntSpinBox();\n    d->intSpinBox->setMaximum(max);\n}\n\nint QInputDialog::intMaximum() const\n{\n    Q_D(const QInputDialog);\n    if (d->intSpinBox) {\n        return d->intSpinBox->maximum();\n    } else {\n        return 99;\n    }\n}\n\n/*!\n    Sets the range of integer values accepted by the dialog when used in\n    IntInput mode, with minimum and maximum values specified by \\a min and\n    \\a max respectively.\n*/\nvoid QInputDialog::setIntRange(int min, int max)\n{\n    Q_D(QInputDialog);\n    d->ensureIntSpinBox();\n    d->intSpinBox->setRange(min, max);\n}\n\n/*!\n    \\property QInputDialog::intStep\n    \\brief the step by which the integer value is increased and decreased\n\n    This property is only relevant when the input dialog is used in\n    IntInput mode.\n*/\nvoid QInputDialog::setIntStep(int step)\n{\n    Q_D(QInputDialog);\n    d->ensureIntSpinBox();\n    d->intSpinBox->setSingleStep(step);\n}\n\nint QInputDialog::intStep() const\n{\n    Q_D(const QInputDialog);\n    if (d->intSpinBox) {\n        return d->intSpinBox->singleStep();\n    } else {\n        return 1;\n    }\n}\n\n/*!\n    \\property QInputDialog::doubleValue\n    \\brief the current double precision floating point value accepted as input\n\n    This property is only relevant when the input dialog is used in\n    DoubleInput mode.\n*/\nvoid QInputDialog::setDoubleValue(double value)\n{\n    Q_D(QInputDialog);\n    setInputMode(DoubleInput);\n    d->doubleSpinBox->setValue(value);\n}\n\ndouble QInputDialog::doubleValue() const\n{\n    Q_D(const QInputDialog);\n    if (d->doubleSpinBox) {\n        return d->doubleSpinBox->value();\n    } else {\n        return 0.0;\n    }\n}\n\n/*!\n    \\property QInputDialog::doubleMinimum\n    \\brief the minimum double precision floating point value accepted as input\n\n    This property is only relevant when the input dialog is used in\n    DoubleInput mode.\n*/\nvoid QInputDialog::setDoubleMinimum(double min)\n{\n    Q_D(QInputDialog);\n    d->ensureDoubleSpinBox();\n    d->doubleSpinBox->setMinimum(min);\n}\n\ndouble QInputDialog::doubleMinimum() const\n{\n    Q_D(const QInputDialog);\n    if (d->doubleSpinBox) {\n        return d->doubleSpinBox->minimum();\n    } else {\n        return 0.0;\n    }\n}\n\n/*!\n    \\property QInputDialog::doubleMaximum\n    \\brief the maximum double precision floating point value accepted as input\n\n    This property is only relevant when the input dialog is used in\n    DoubleInput mode.\n*/\nvoid QInputDialog::setDoubleMaximum(double max)\n{\n    Q_D(QInputDialog);\n    d->ensureDoubleSpinBox();\n    d->doubleSpinBox->setMaximum(max);\n}\n\ndouble QInputDialog::doubleMaximum() const\n{\n    Q_D(const QInputDialog);\n    if (d->doubleSpinBox) {\n        return d->doubleSpinBox->maximum();\n    } else {\n        return 99.99;\n    }\n}\n\n/*!\n    Sets the range of double precision floating point values accepted by the\n    dialog when used in DoubleInput mode, with minimum and maximum values\n    specified by \\a min and \\a max respectively.\n*/\nvoid QInputDialog::setDoubleRange(double min, double max)\n{\n    Q_D(QInputDialog);\n    d->ensureDoubleSpinBox();\n    d->doubleSpinBox->setRange(min, max);\n}\n\n/*!\n    \\property QInputDialog::doubleDecimals\n\n    \\brief sets the precision of the double spinbox in decimals\n\n    \\sa QDoubleSpinBox::setDecimals()\n*/\nvoid QInputDialog::setDoubleDecimals(int decimals)\n{\n    Q_D(QInputDialog);\n    d->ensureDoubleSpinBox();\n    d->doubleSpinBox->setDecimals(decimals);\n}\n\nint QInputDialog::doubleDecimals() const\n{\n    Q_D(const QInputDialog);\n    if (d->doubleSpinBox) {\n        return d->doubleSpinBox->decimals();\n    } else {\n        return 2;\n    }\n}\n\n/*!\n    \\property QInputDialog::okButtonText\n\n    \\brief the text for the button used to accept the entry in the dialog\n*/\nvoid QInputDialog::setOkButtonText(const QString &text)\n{\n    Q_D(const QInputDialog);\n    d->ensureLayout();\n    d->buttonBox->button(QDialogButtonBox::Ok)->setText(text);\n}\n\nQString QInputDialog::okButtonText() const\n{\n    Q_D(const QInputDialog);\n    d->ensureLayout();\n    return d->buttonBox->button(QDialogButtonBox::Ok)->text();\n}\n\n/*!\n    \\property QInputDialog::cancelButtonText\n    \\brief the text for the button used to cancel the dialog\n*/\nvoid QInputDialog::setCancelButtonText(const QString &text)\n{\n    Q_D(const QInputDialog);\n    d->ensureLayout();\n    d->buttonBox->button(QDialogButtonBox::Cancel)->setText(text);\n}\n\nQString QInputDialog::cancelButtonText() const\n{\n    Q_D(const QInputDialog);\n    d->ensureLayout();\n    return d->buttonBox->button(QDialogButtonBox::Cancel)->text();\n}\n\n/*!\n    This function connects one of its signals to the slot specified by \\a receiver\n    and \\a member. The specific signal depends on the arguments that are specified\n    in \\a member. These are:\n\n    \\list\n      \\li textValueSelected() if \\a member has a QString for its first argument.\n      \\li intValueSelected() if \\a member has an int for its first argument.\n      \\li doubleValueSelected() if \\a member has a double for its first argument.\n      \\li accepted() if \\a member has NO arguments.\n    \\endlist\n\n    The signal will be disconnected from the slot when the dialog is closed.\n*/\nvoid QInputDialog::open(QObject *receiver, const char *member)\n{\n    Q_D(QInputDialog);\n    connect(this, signalForMember(member), receiver, member);\n    d->receiverToDisconnectOnClose = receiver;\n    d->memberToDisconnectOnClose = member;\n    QDialog::open();\n}\n\n/*!\n    \\reimp\n*/\nQSize QInputDialog::minimumSizeHint() const\n{\n    Q_D(const QInputDialog);\n    d->ensureLayout();\n    return QDialog::minimumSizeHint();\n}\n\n/*!\n    \\reimp\n*/\nQSize QInputDialog::sizeHint() const\n{\n    Q_D(const QInputDialog);\n    d->ensureLayout();\n    return QDialog::sizeHint();\n}\n\n/*!\n    \\reimp\n*/\nvoid QInputDialog::setVisible(bool visible)\n{\n    Q_D(const QInputDialog);\n    if (visible) {\n        d->ensureLayout();\n        d->inputWidget->setFocus();\n        if (d->inputWidget == d->lineEdit) {\n            d->lineEdit->selectAll();\n        } else if (d->inputWidget == d->plainTextEdit) {\n            d->plainTextEdit->selectAll();\n        } else if (d->inputWidget == d->intSpinBox) {\n            d->intSpinBox->selectAll();\n        } else if (d->inputWidget == d->doubleSpinBox) {\n            d->doubleSpinBox->selectAll();\n        }\n    }\n    QDialog::setVisible(visible);\n}\n\n/*!\n  Closes the dialog and sets its result code to \\a result. If this dialog\n  is shown with exec(), done() causes the local event loop to finish,\n  and exec() to return \\a result.\n\n  \\sa QDialog::done()\n*/\nvoid QInputDialog::done(int result)\n{\n    Q_D(QInputDialog);\n    QDialog::done(result);\n    if (result) {\n        InputMode mode = inputMode();\n        switch (mode) {\n        case DoubleInput:\n            emit doubleValueSelected(doubleValue());\n            break;\n        case IntInput:\n            emit intValueSelected(intValue());\n            break;\n        default:\n            Q_ASSERT(mode == TextInput);\n            emit textValueSelected(textValue());\n        }\n    }\n    if (d->receiverToDisconnectOnClose) {\n        disconnect(this, signalForMember(d->memberToDisconnectOnClose),\n                   d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);\n        d->receiverToDisconnectOnClose = nullptr;\n    }\n    d->memberToDisconnectOnClose.clear();\n}\n\n/*!\n    Static convenience function to get a string from the user.\n\n    \\a title is the text which is displayed in the title bar of the dialog.\n    \\a label is the text which is shown to the user (it should say what should\n    be entered).\n    \\a text is the default text which is placed in the line edit.\n    \\a mode is the echo mode the line edit will use.\n    \\a inputMethodHints is the input method hints that will be used in the\n    edit widget if an input method is active.\n\n    If \\a ok is nonnull \\e {*ok} will be set to true if the user pressed\n    \\uicontrol OK and to false if the user pressed \\uicontrol Cancel. The dialog's parent\n    is \\a parent. The dialog will be modal and uses the specified widget\n    \\a flags.\n\n    If the dialog is accepted, this function returns the text in the dialog's\n    line edit. If the dialog is rejected, a null QString is returned.\n\n    Use this static function like this:\n\n    \\snippet dialogs/standarddialogs/dialog.cpp 3\n\n    \\sa getInt(), getDouble(), getItem(), getMultiLineText()\n*/\n\nQString QInputDialog::getText(QWidget *parent, const QString &title, const QString &label,\n                              QLineEdit::EchoMode mode, const QString &text, bool *ok,\n                              Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)\n{\n    QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));\n    dialog->setWindowTitle(title);\n    dialog->setLabelText(label);\n    dialog->setTextValue(text);\n    dialog->setTextEchoMode(mode);\n    dialog->setInputMethodHints(inputMethodHints);\n\n    const int ret = dialog->exec();\n    if (ok)\n        *ok = !!ret;\n    if (bool(dialog) && ret) {\n        return dialog->textValue();\n    } else {\n        return QString();\n    }\n}\n\n/*!\n    \\since 5.2\n\n    Static convenience function to get a multiline string from the user.\n\n    \\a title is the text which is displayed in the title bar of the dialog.\n    \\a label is the text which is shown to the user (it should say what should\n    be entered).\n    \\a text is the default text which is placed in the plain text edit.\n    \\a inputMethodHints is the input method hints that will be used in the\n    edit widget if an input method is active.\n\n    If \\a ok is nonnull \\e {*ok} will be set to true if the user pressed\n    \\uicontrol OK and to false if the user pressed \\uicontrol Cancel. The dialog's parent\n    is \\a parent. The dialog will be modal and uses the specified widget\n    \\a flags.\n\n    If the dialog is accepted, this function returns the text in the dialog's\n    plain text edit. If the dialog is rejected, a null QString is returned.\n\n    Use this static function like this:\n\n    \\snippet dialogs/standarddialogs/dialog.cpp 4\n\n    \\sa getInt(), getDouble(), getItem(), getText()\n*/\n\nQString QInputDialog::getMultiLineText(QWidget *parent, const QString &title, const QString &label,\n                                       const QString &text, bool *ok, Qt::WindowFlags flags,\n                                       Qt::InputMethodHints inputMethodHints)\n{\n    QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));\n    dialog->setOptions(QInputDialog::UsePlainTextEditForTextInput);\n    dialog->setWindowTitle(title);\n    dialog->setLabelText(label);\n    dialog->setTextValue(text);\n    dialog->setInputMethodHints(inputMethodHints);\n\n    const int ret = dialog->exec();\n    if (ok)\n        *ok = !!ret;\n    if (bool(dialog) && ret) {\n        return dialog->textValue();\n    } else {\n        return QString();\n    }\n}\n\n/*!\n    Static convenience function to get an integer input from the user.\n\n    \\a title is the text which is displayed in the title bar of the dialog.\n    \\a label is the text which is shown to the user (it should say what should\n    be entered).\n    \\a value is the default integer which the spinbox will be set to.\n    \\a min and \\a max are the minimum and maximum values the user may choose.\n    \\a step is the amount by which the values change as the user presses the\n    arrow buttons to increment or decrement the value.\n\n    If \\a ok is nonnull *\\a ok will be set to true if the user pressed \\uicontrol OK\n    and to false if the user pressed \\uicontrol Cancel. The dialog's parent is\n    \\a parent. The dialog will be modal and uses the widget \\a flags.\n\n    On success, this function returns the integer which has been entered by the\n    user; on failure, it returns the initial \\a value.\n\n    Use this static function like this:\n\n    \\snippet dialogs/standarddialogs/dialog.cpp 0\n\n    \\sa getText(), getDouble(), getItem(), getMultiLineText()\n*/\n\nint QInputDialog::getInt(QWidget *parent, const QString &title, const QString &label, int value,\n                         int min, int max, int step, bool *ok, Qt::WindowFlags flags)\n{\n    QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));\n    dialog->setWindowTitle(title);\n    dialog->setLabelText(label);\n    dialog->setIntRange(min, max);\n    dialog->setIntValue(value);\n    dialog->setIntStep(step);\n\n    const int ret = dialog->exec();\n    if (ok)\n        *ok = !!ret;\n    if (bool(dialog) && ret) {\n        return dialog->intValue();\n    } else {\n        return value;\n    }\n}\n\n/*!\n    Static convenience function to get a floating point number from the user.\n\n    \\a title is the text which is displayed in the title bar of the dialog.\n    \\a label is the text which is shown to the user (it should say what should\n    be entered).\n    \\a value is the default floating point number that the line edit will be\n    set to.\n    \\a min and \\a max are the minimum and maximum values the user may choose.\n    \\a decimals is the maximum number of decimal places the number may have.\n    \\a step is the amount by which the values change as the user presses the\n    arrow buttons to increment or decrement the value.\n\n    If \\a ok is nonnull, *\\a ok will be set to true if the user pressed \\uicontrol OK\n    and to false if the user pressed \\uicontrol Cancel. The dialog's parent is\n    \\a parent. The dialog will be modal and uses the widget \\a flags.\n\n    This function returns the floating point number which has been entered by\n    the user.\n\n    Use this static function like this:\n\n    \\snippet dialogs/standarddialogs/dialog.cpp 1\n\n    \\sa getText(), getInt(), getItem(), getMultiLineText()\n*/\n\ndouble QInputDialog::getDouble(QWidget *parent, const QString &title, const QString &label,\n                               double value, double min, double max, int decimals, bool *ok,\n                               Qt::WindowFlags flags, double step)\n{\n    QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));\n    dialog->setWindowTitle(title);\n    dialog->setLabelText(label);\n    dialog->setDoubleDecimals(decimals);\n    dialog->setDoubleRange(min, max);\n    dialog->setDoubleValue(value);\n    dialog->setDoubleStep(step);\n\n    const int ret = dialog->exec();\n    if (ok)\n        *ok = !!ret;\n    if (bool(dialog) && ret) {\n        return dialog->doubleValue();\n    } else {\n        return value;\n    }\n}\n\n/*!\n    Static convenience function to let the user select an item from a string\n    list.\n\n    \\a title is the text which is displayed in the title bar of the dialog.\n    \\a label is the text which is shown to the user (it should say what should\n    be entered).\n    \\a items is the string list which is inserted into the combo box.\n    \\a current is the number  of the item which should be the current item.\n    \\a inputMethodHints is the input method hints that will be used if the\n    combo box is editable and an input method is active.\n\n    If \\a editable is true the user can enter their own text; otherwise, the\n    user may only select one of the existing items.\n\n    If \\a ok is nonnull \\e {*ok} will be set to true if the user pressed\n    \\uicontrol OK and to false if the user pressed \\uicontrol Cancel. The dialog's parent\n    is \\a parent. The dialog will be modal and uses the widget \\a flags.\n\n    This function returns the text of the current item, or if \\a editable is\n    true, the current text of the combo box.\n\n    Use this static function like this:\n\n    \\snippet dialogs/standarddialogs/dialog.cpp 2\n\n    \\sa getText(), getInt(), getDouble(), getMultiLineText()\n*/\n\nQString QInputDialog::getItem(QWidget *parent, const QString &title, const QString &label,\n                              const QStringList &items, int current, bool editable, bool *ok,\n                              Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)\n{\n    QString text(items.value(current));\n\n    QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));\n    dialog->setWindowTitle(title);\n    dialog->setLabelText(label);\n    dialog->setComboBoxItems(items);\n    dialog->setTextValue(text);\n    dialog->setComboBoxEditable(editable);\n    dialog->setInputMethodHints(inputMethodHints);\n\n    const int ret = dialog->exec();\n    if (ok)\n        *ok = !!ret;\n    if (bool(dialog) && ret) {\n        return dialog->textValue();\n    } else {\n        return text;\n    }\n}\n\n/*!\n    \\property QInputDialog::doubleStep\n    \\since 5.10\n    \\brief the step by which the double value is increased and decreased\n\n    This property is only relevant when the input dialog is used in\n    DoubleInput mode.\n*/\n\nvoid QInputDialog::setDoubleStep(double step)\n{\n    Q_D(QInputDialog);\n    d->ensureDoubleSpinBox();\n    d->doubleSpinBox->setSingleStep(step);\n}\n\ndouble QInputDialog::doubleStep() const\n{\n    Q_D(const QInputDialog);\n    if (d->doubleSpinBox)\n        return d->doubleSpinBox->singleStep();\n    else\n        return 1.0;\n}\n\n/*!\n    \\fn void QInputDialog::doubleValueChanged(double value)\n\n    This signal is emitted whenever the double value changes in the dialog.\n    The current value is specified by \\a value.\n\n    This signal is only relevant when the input dialog is used in\n    DoubleInput mode.\n*/\n\n/*!\n    \\fn void QInputDialog::doubleValueSelected(double value)\n\n    This signal is emitted whenever the user selects a double value by\n    accepting the dialog; for example, by clicking the \\uicontrol{OK} button.\n    The selected value is specified by \\a value.\n\n    This signal is only relevant when the input dialog is used in\n    DoubleInput mode.\n*/\n\n/*!\n    \\fn void QInputDialog::intValueChanged(int value)\n\n    This signal is emitted whenever the integer value changes in the dialog.\n    The current value is specified by \\a value.\n\n    This signal is only relevant when the input dialog is used in\n    IntInput mode.\n*/\n\n/*!\n    \\fn void QInputDialog::intValueSelected(int value)\n\n    This signal is emitted whenever the user selects a integer value by\n    accepting the dialog; for example, by clicking the \\uicontrol{OK} button.\n    The selected value is specified by \\a value.\n\n    This signal is only relevant when the input dialog is used in\n    IntInput mode.\n*/\n\n/*!\n    \\fn void QInputDialog::textValueChanged(const QString &text)\n\n    This signal is emitted whenever the text string changes in the dialog.\n    The current string is specified by \\a text.\n\n    This signal is only relevant when the input dialog is used in\n    TextInput mode.\n*/\n\n/*!\n    \\fn void QInputDialog::textValueSelected(const QString &text)\n\n    This signal is emitted whenever the user selects a text string by\n    accepting the dialog; for example, by clicking the \\uicontrol{OK} button.\n    The selected string is specified by \\a text.\n\n    This signal is only relevant when the input dialog is used in\n    TextInput mode.\n*/\n\nQT_END_NAMESPACE\n\n#include \"qinputdialog.moc\"\n#include \"moc_qinputdialog.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qmessagebox.cpp",
    "content": "// Copyright (C) 2021 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include <QtWidgets/qmessagebox.h>\n\n#include <QtWidgets/qdialogbuttonbox.h>\n#include \"private/qlabel_p.h\"\n#include \"private/qapplication_p.h\"\n#include <QtCore/qlist.h>\n#include <QtCore/qdebug.h>\n#include <QtWidgets/qstyle.h>\n#include <QtWidgets/qstyleoption.h>\n#include <QtWidgets/qgridlayout.h>\n#include <QtWidgets/qpushbutton.h>\n#include <QtWidgets/qcheckbox.h>\n#include <QtGui/qaccessible.h>\n#include <QtGui/qicon.h>\n#include <QtGui/qtextdocument.h>\n#include <QtWidgets/qapplication.h>\n#if QT_CONFIG(textedit)\n#include <QtWidgets/qtextedit.h>\n#endif\n#if QT_CONFIG(menu)\n#include <QtWidgets/qmenu.h>\n#endif\n#include \"qdialog_p.h\"\n#include <QtGui/qfont.h>\n#include <QtGui/qfontmetrics.h>\n#include <QtGui/qclipboard.h>\n#include \"private/qabstractbutton_p.h\"\n#include <QtGui/qpa/qplatformtheme.h>\n\n#include <QtCore/qanystringview.h>\n#include <QtCore/qdebug.h>\n#include <QtCore/qpointer.h>\n#include <QtCore/qversionnumber.h>\n\n#ifdef Q_OS_WIN\n#    include <QtCore/qt_windows.h>\n#include <qpa/qplatformnativeinterface.h>\n#endif\n\n#include <optional>\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\n#if defined(Q_OS_WIN)\nHMENU qt_getWindowsSystemMenu(const QWidget *w)\n{\n    if (QWindow *window = QApplicationPrivate::windowForWidget(w))\n        if (void *handle = QGuiApplication::platformNativeInterface()->nativeResourceForWindow(\"handle\", window))\n            return GetSystemMenu(reinterpret_cast<HWND>(handle), false);\n    return 0;\n}\n#endif\n\nstatic_assert(qToUnderlying(QMessageBox::ButtonRole::NRoles) ==\n              qToUnderlying(QDialogButtonBox::ButtonRole::NRoles),\n              \"QMessageBox::ButtonRole and QDialogButtonBox::ButtonRole out of sync!\");\n\nstatic_assert(std::is_same_v<std::underlying_type_t<QMessageBox::ButtonRole>,\n                             std::underlying_type_t<QDialogButtonBox::ButtonRole>>);\n\n// StandardButton enums have different underlying types\n// => qToUnderlying and std::is_same_v won't work\n// ### Qt 7: make them have the same underlying type\nstatic_assert(static_cast<int>(QMessageBox::StandardButton::LastButton) ==\n              static_cast<int>(QDialogButtonBox::StandardButton::LastButton),\n              \"QMessageBox::StandardButton and QDialogButtonBox::StandardButton out of sync!\");\n\nenum Button { Old_Ok = 1, Old_Cancel = 2, Old_Yes = 3, Old_No = 4, Old_Abort = 5, Old_Retry = 6,\n              Old_Ignore = 7, Old_YesAll = 8, Old_NoAll = 9, Old_ButtonMask = 0xFF,\n              NewButtonMask = 0xFFFFFC00 };\n\nenum DetailButtonLabel { ShowLabel = 0, HideLabel = 1 };\n#if QT_CONFIG(textedit)\nclass QMessageBoxDetailsText : public QWidget\n{\n    Q_OBJECT\npublic:\n    class TextEdit : public QTextEdit\n    {\n    public:\n        TextEdit(QWidget *parent=nullptr) : QTextEdit(parent) { }\n#ifndef QT_NO_CONTEXTMENU\n        void contextMenuEvent(QContextMenuEvent * e) override\n        {\n            if (QMenu *menu = createStandardContextMenu()) {\n                menu->setAttribute(Qt::WA_DeleteOnClose);\n                menu->popup(e->globalPos());\n            }\n        }\n#endif // QT_NO_CONTEXTMENU\n    };\n\n    QMessageBoxDetailsText(QWidget *parent=nullptr)\n        : QWidget(parent)\n        , copyAvailable(false)\n    {\n        QVBoxLayout *layout = new QVBoxLayout;\n        layout->setContentsMargins(QMargins());\n        QFrame *line = new QFrame(this);\n        line->setFrameShape(QFrame::HLine);\n        line->setFrameShadow(QFrame::Sunken);\n        layout->addWidget(line);\n        textEdit = new TextEdit();\n        textEdit->setFixedHeight(100);\n        textEdit->setFocusPolicy(Qt::NoFocus);\n        textEdit->setReadOnly(true);\n        layout->addWidget(textEdit);\n        setLayout(layout);\n\n        connect(textEdit, &TextEdit::copyAvailable,\n                this, &QMessageBoxDetailsText::textCopyAvailable);\n    }\n    void setText(const QString &text) { textEdit->setPlainText(text); }\n    QString text() const { return textEdit->toPlainText(); }\n\n    bool copy()\n    {\n#ifdef QT_NO_CLIPBOARD\n        return false;\n#else\n        if (!copyAvailable)\n            return false;\n        textEdit->copy();\n        return true;\n#endif\n    }\n\n    void selectAll()\n    {\n        textEdit->selectAll();\n    }\n\nprivate slots:\n    void textCopyAvailable(bool available)\n    {\n        copyAvailable = available;\n    }\n\nprivate:\n    bool copyAvailable;\n    TextEdit *textEdit;\n};\n#endif // QT_CONFIG(textedit)\n\nclass DetailButton : public QPushButton\n{\npublic:\n    DetailButton(QWidget *parent) : QPushButton(label(ShowLabel), parent)\n    {\n        setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);\n    }\n\n    QString label(DetailButtonLabel label) const\n    { return label == ShowLabel ? QMessageBox::tr(\"Show Details...\") : QMessageBox::tr(\"Hide Details...\"); }\n\n    void setLabel(DetailButtonLabel lbl)\n    { setText(label(lbl)); }\n\n    QSize sizeHint() const override\n    {\n        ensurePolished();\n        QStyleOptionButton opt;\n        initStyleOption(&opt);\n        const QFontMetrics fm = fontMetrics();\n        opt.text = label(ShowLabel);\n        QSize sz = fm.size(Qt::TextShowMnemonic, opt.text);\n        QSize ret = style()->sizeFromContents(QStyle::CT_PushButton, &opt, sz, this);\n        opt.text = label(HideLabel);\n        sz = fm.size(Qt::TextShowMnemonic, opt.text);\n        ret = ret.expandedTo(style()->sizeFromContents(QStyle::CT_PushButton, &opt, sz, this));\n        return ret;\n    }\n};\n\nclass QMessageBoxPrivate : public QDialogPrivate\n{\n    Q_DECLARE_PUBLIC(QMessageBox)\n\npublic:\n    QMessageBoxPrivate() : escapeButton(nullptr), defaultButton(nullptr), checkbox(nullptr), clickedButton(nullptr), detailsButton(nullptr),\n#if QT_CONFIG(textedit)\n                           detailsText(nullptr),\n#endif\n                           compatMode(false), autoAddOkButton(true),\n                           detectedEscapeButton(nullptr), informativeLabel(nullptr),\n                           options(QMessageDialogOptions::create()) { }\n\n    void init(const QString &title = QString(), const QString &text = QString());\n    void setupLayout();\n    void buttonClicked(QAbstractButton *);\n    void helperClicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role);\n    void setClickedButton(QAbstractButton *button);\n\n    QAbstractButton *findButton(int button0, int button1, int button2, int flags);\n    void addOldButtons(int button0, int button1, int button2);\n\n    QAbstractButton *abstractButtonForId(int id) const;\n    int execReturnCode(QAbstractButton *button);\n\n    void detectEscapeButton();\n    void updateSize();\n    int layoutMinimumWidth();\n    void retranslateStrings();\n\n    void setVisible(bool visible) override;\n    bool canBeNativeDialog() const override;\n\n    static int showOldMessageBox(QWidget *parent, QMessageBox::Icon icon,\n                                 const QString &title, const QString &text,\n                                 int button0, int button1, int button2);\n    static int showOldMessageBox(QWidget *parent, QMessageBox::Icon icon,\n                                 const QString &title, const QString &text,\n                                 const QString &button0Text,\n                                 const QString &button1Text,\n                                 const QString &button2Text,\n                                 int defaultButtonNumber,\n                                 int escapeButtonNumber);\n\n    static QMessageBox::StandardButton showNewMessageBox(QWidget *parent,\n                QMessageBox::Icon icon, const QString& title, const QString& text,\n                QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);\n\n    static QPixmap standardIcon(QMessageBox::Icon icon, QMessageBox *mb);\n    static QMessageBox::StandardButton standardButtonForRole(QMessageBox::ButtonRole role);\n\n    QLabel *label;\n    QMessageBox::Icon icon;\n    QLabel *iconLabel;\n    QDialogButtonBox *buttonBox;\n    QList<QAbstractButton *> customButtonList;\n    QAbstractButton *escapeButton;\n    QPushButton *defaultButton;\n    QCheckBox *checkbox;\n    QAbstractButton *clickedButton;\n    DetailButton *detailsButton;\n#if QT_CONFIG(textedit)\n    QMessageBoxDetailsText *detailsText;\n#endif\n    bool compatMode;\n    bool autoAddOkButton;\n    QAbstractButton *detectedEscapeButton;\n    QLabel *informativeLabel;\n    QPointer<QObject> receiverToDisconnectOnClose;\n    QByteArray memberToDisconnectOnClose;\n    QByteArray signalToDisconnectOnClose;\n    QSharedPointer<QMessageDialogOptions> options;\nprivate:\n    void initHelper(QPlatformDialogHelper *) override;\n    void helperPrepareShow(QPlatformDialogHelper *) override;\n    int dialogCode() const override;\n};\n\nvoid QMessageBoxPrivate::init(const QString &title, const QString &text)\n{\n    Q_Q(QMessageBox);\n\n    label = new QLabel;\n    label->setObjectName(\"qt_msgbox_label\"_L1);\n    label->setTextInteractionFlags(Qt::TextInteractionFlags(q->style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, nullptr, q)));\n    label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);\n    label->setOpenExternalLinks(true);\n    iconLabel = new QLabel(q);\n    iconLabel->setObjectName(\"qt_msgboxex_icon_label\"_L1);\n    iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);\n\n    buttonBox = new QDialogButtonBox;\n    buttonBox->setObjectName(\"qt_msgbox_buttonbox\"_L1);\n    buttonBox->setCenterButtons(q->style()->styleHint(QStyle::SH_MessageBox_CenterButtons, nullptr, q));\n    QObjectPrivate::connect(buttonBox, &QDialogButtonBox::clicked,\n                            this, &QMessageBoxPrivate::buttonClicked);\n    setupLayout();\n    if (!title.isEmpty() || !text.isEmpty()) {\n        q->setWindowTitle(title);\n        q->setText(text);\n    }\n    q->setModal(true);\n#ifdef Q_OS_MAC\n    QFont f = q->font();\n    f.setBold(true);\n    label->setFont(f);\n#endif\n    icon = QMessageBox::NoIcon;\n}\n\nvoid QMessageBoxPrivate::setupLayout()\n{\n    Q_Q(QMessageBox);\n    delete q->layout();\n    QGridLayout *grid = new QGridLayout;\n    const bool hasIcon = !iconLabel->pixmap().isNull();\n\n    if (hasIcon)\n        grid->addWidget(iconLabel, 0, 0, 2, 1, Qt::AlignTop);\n    iconLabel->setVisible(hasIcon);\n#ifdef Q_OS_MAC\n    QSpacerItem *indentSpacer = new QSpacerItem(14, 1, QSizePolicy::Fixed, QSizePolicy::Fixed);\n#else\n    QSpacerItem *indentSpacer = new QSpacerItem(hasIcon ? 7 : 15, 1, QSizePolicy::Fixed, QSizePolicy::Fixed);\n#endif\n    grid->addItem(indentSpacer, 0, hasIcon ? 1 : 0, 2, 1);\n    grid->addWidget(label, 0, hasIcon ? 2 : 1, 1, 1);\n    if (informativeLabel) {\n#ifndef Q_OS_MAC\n        informativeLabel->setContentsMargins(0, 7, 0, 7);\n#endif\n        grid->addWidget(informativeLabel, 1, hasIcon ? 2 : 1, 1, 1);\n    }\n    if (checkbox) {\n        grid->addWidget(checkbox, informativeLabel ? 2 : 1, hasIcon ? 2 : 1, 1, 1, Qt::AlignLeft);\n#ifdef Q_OS_MAC\n        grid->addItem(new QSpacerItem(1, 15, QSizePolicy::Fixed, QSizePolicy::Fixed), grid->rowCount(), 0);\n#else\n        grid->addItem(new QSpacerItem(1, 7, QSizePolicy::Fixed, QSizePolicy::Fixed), grid->rowCount(), 0);\n#endif\n    }\n#ifdef Q_OS_MAC\n    grid->addWidget(buttonBox, grid->rowCount(), hasIcon ? 2 : 1, 1, 1);\n    grid->setContentsMargins(0, 0, 0, 0);\n    grid->setVerticalSpacing(8);\n    grid->setHorizontalSpacing(0);\n    q->setContentsMargins(24, 15, 24, 20);\n    grid->setRowStretch(1, 100);\n    grid->setRowMinimumHeight(2, 6);\n#else\n    grid->addWidget(buttonBox, grid->rowCount(), 0, 1, grid->columnCount());\n#endif\n#if QT_CONFIG(textedit)\n    if (detailsText)\n        grid->addWidget(detailsText, grid->rowCount(), 0, 1, grid->columnCount());\n#endif\n    grid->setSizeConstraint(QLayout::SetNoConstraint);\n    q->setLayout(grid);\n\n    retranslateStrings();\n    updateSize();\n}\n\nint QMessageBoxPrivate::layoutMinimumWidth()\n{\n    layout->activate();\n    return layout->totalMinimumSize().width();\n}\n\nvoid QMessageBoxPrivate::updateSize()\n{\n    Q_Q(QMessageBox);\n\n    if (!q->isVisible())\n        return;\n\n    const QSize screenSize = q->screen()->availableGeometry().size();\n    int hardLimit = qMin(screenSize.width() - 480, 1000); // can never get bigger than this\n    // on small screens allows the messagebox be the same size as the screen\n    if (screenSize.width() <= 1024)\n        hardLimit = screenSize.width();\n#ifdef Q_OS_MAC\n    int softLimit = qMin(screenSize.width()/2, 420);\n#else\n    // note: ideally on windows, hard and soft limits but it breaks compat\n    int softLimit = qMin(screenSize.width()/2, 500);\n#endif\n\n    if (informativeLabel)\n        informativeLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);\n\n    label->setWordWrap(false); // makes the label return min size\n    int width = layoutMinimumWidth();\n\n    if (width > softLimit) {\n        label->setWordWrap(true);\n        width = qMax(softLimit, layoutMinimumWidth());\n\n        if (width > hardLimit) {\n            label->d_func()->ensureTextControl();\n            if (QWidgetTextControl *control = label->d_func()->control) {\n                QTextOption opt = control->document()->defaultTextOption();\n                opt.setWrapMode(QTextOption::WrapAnywhere);\n                control->document()->setDefaultTextOption(opt);\n            }\n            width = hardLimit;\n        }\n    }\n\n    if (informativeLabel) {\n        label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);\n        QSizePolicy policy(QSizePolicy::Minimum, QSizePolicy::Preferred);\n        policy.setHeightForWidth(true);\n        informativeLabel->setSizePolicy(policy);\n        width = qMax(width, layoutMinimumWidth());\n        if (width > hardLimit) { // longest word is really big, so wrap anywhere\n            informativeLabel->d_func()->ensureTextControl();\n            if (QWidgetTextControl *control = informativeLabel->d_func()->control) {\n                QTextOption opt = control->document()->defaultTextOption();\n                opt.setWrapMode(QTextOption::WrapAnywhere);\n                control->document()->setDefaultTextOption(opt);\n            }\n            width = hardLimit;\n        }\n        policy.setHeightForWidth(label->wordWrap());\n        label->setSizePolicy(policy);\n    }\n\n    QFontMetrics fm(QApplication::font(\"QMdiSubWindowTitleBar\"));\n    int windowTitleWidth = qMin(fm.horizontalAdvance(q->windowTitle()) + 50, hardLimit);\n    if (windowTitleWidth > width)\n        width = windowTitleWidth;\n\n    layout->activate();\n    int height = (layout->hasHeightForWidth())\n                     ? layout->totalHeightForWidth(width)\n                     : layout->totalMinimumSize().height();\n\n    q->setFixedSize(width, height);\n    QCoreApplication::removePostedEvents(q, QEvent::LayoutRequest);\n}\n\nstatic int oldButton(int button)\n{\n    switch (button & QMessageBox::ButtonMask) {\n    case QMessageBox::Ok:\n        return Old_Ok;\n    case QMessageBox::Cancel:\n        return Old_Cancel;\n    case QMessageBox::Yes:\n        return Old_Yes;\n    case QMessageBox::No:\n        return Old_No;\n    case QMessageBox::Abort:\n        return Old_Abort;\n    case QMessageBox::Retry:\n        return Old_Retry;\n    case QMessageBox::Ignore:\n        return Old_Ignore;\n    case QMessageBox::YesToAll:\n        return Old_YesAll;\n    case QMessageBox::NoToAll:\n        return Old_NoAll;\n    default:\n        return 0;\n    }\n}\n\nint QMessageBoxPrivate::execReturnCode(QAbstractButton *button)\n{\n    if (int standardButton = buttonBox->standardButton(button)) {\n        // When using a QMessageBox with standard buttons, the return\n        // code is a StandardButton value indicating the standard button\n        // that was clicked.\n        if (compatMode)\n            return oldButton(standardButton);\n        else\n            return standardButton;\n    } else {\n        // When using QMessageBox with custom buttons, the return code\n        // is an opaque value, and the user is expected to use clickedButton()\n        // to determine which button was clicked. We make sure to keep the opaque\n        // value out of the QDialog::DialogCode range, so we can distinguish them.\n        auto customButtonIndex = customButtonList.indexOf(button);\n        if (customButtonIndex >= 0)\n            return QDialog::DialogCode::Accepted + customButtonIndex + 1;\n        else\n            return customButtonIndex; // Not found, return -1\n    }\n}\n\nint QMessageBoxPrivate::dialogCode() const\n{\n    Q_Q(const QMessageBox);\n\n    if (rescode <= QDialog::Accepted) {\n        return rescode;\n    } else if (clickedButton) {\n        switch (q->buttonRole(clickedButton)) {\n        case QMessageBox::AcceptRole:\n        case QMessageBox::YesRole:\n            return QDialog::Accepted;\n        case QMessageBox::RejectRole:\n        case QMessageBox::NoRole:\n            return QDialog::Rejected;\n        default:\n            ;\n        }\n    }\n\n    return QDialogPrivate::dialogCode();\n}\n\nvoid QMessageBoxPrivate::buttonClicked(QAbstractButton *button)\n{\n    Q_Q(QMessageBox);\n#if QT_CONFIG(textedit)\n    if (detailsButton && detailsText && button == detailsButton) {\n        detailsButton->setLabel(detailsText->isHidden() ? HideLabel : ShowLabel);\n        detailsText->setHidden(!detailsText->isHidden());\n        updateSize();\n    } else\n#endif\n    {\n        setClickedButton(button);\n\n        if (receiverToDisconnectOnClose) {\n            QObject::disconnect(q, signalToDisconnectOnClose, receiverToDisconnectOnClose,\n                                memberToDisconnectOnClose);\n            receiverToDisconnectOnClose = nullptr;\n        }\n        signalToDisconnectOnClose.clear();\n        memberToDisconnectOnClose.clear();\n    }\n}\n\nvoid QMessageBoxPrivate::setClickedButton(QAbstractButton *button)\n{\n    Q_Q(QMessageBox);\n\n    clickedButton = button;\n    emit q->buttonClicked(clickedButton);\n\n    auto resultCode = execReturnCode(button);\n    q->done(resultCode);\n}\n\nvoid QMessageBoxPrivate::helperClicked(QPlatformDialogHelper::StandardButton helperButton, QPlatformDialogHelper::ButtonRole role)\n{\n    Q_UNUSED(role);\n    Q_Q(QMessageBox);\n\n    // Map back to QAbstractButton, so that the message box behaves the same from\n    // the outside, regardless of whether it's backed by a native helper or not.\n    QAbstractButton *dialogButton = helperButton > QPlatformDialogHelper::LastButton ?\n        static_cast<QAbstractButton *>(options->customButton(helperButton)->button) :\n        q->button(QMessageBox::StandardButton(helperButton));\n\n    Q_ASSERT(dialogButton);\n\n    // Simulate click by explicitly clicking the button. This will ensure that\n    // any logic of the button that responds to the click is respected, including\n    // plumbing back to buttonClicked above based on the clicked() signal.\n    dialogButton->click();\n}\n\n/*!\n    \\class QMessageBox\n\n    \\brief The QMessageBox class provides a modal dialog for informing\n    the user or for asking the user a question and receiving an answer.\n\n    \\ingroup standard-dialogs\n    \\inmodule QtWidgets\n\n    A message box displays a primary \\l{QMessageBox::text}{text} to\n    alert the user to a situation, an \\l{QMessageBox::informativeText}\n    {informative text} to further explain the situation, and an optional\n    \\l{QMessageBox::detailedText} {detailed text} to provide even more data\n    if the user requests it.\n\n    A message box can also display an \\l{QMessageBox::icon} {icon}\n    and \\l{QMessageBox::standardButtons} {standard buttons} for\n    accepting a user response.\n\n    Two APIs for using QMessageBox are provided, the property-based\n    API, and the static functions. Calling one of the static functions\n    is the simpler approach, but it is less flexible than using the\n    property-based API, and the result is less informative. Using the\n    property-based API is recommended.\n\n    \\section1 The Property-based API\n\n    To use the property-based API, construct an instance of\n    QMessageBox, set the desired properties, and call exec() to show\n    the message. The simplest configuration is to set only the\n    \\l{QMessageBox::text} {message text} property.\n\n    \\snippet code/src_gui_dialogs_qmessagebox.cpp 5\n\n    The user must click the \\uicontrol{OK} button to dismiss the message\n    box. The rest of the GUI is blocked until the message box is\n    dismissed.\n\n    \\image msgbox1.png\n\n    A better approach than just alerting the user to an event is to\n    also ask the user what to do about it.\n\n    Set the \\l{QMessageBox::standardButtons} {standard buttons}\n    property to the set of buttons you want as the set of user\n    responses. The buttons are specified by combining values from\n    StandardButtons using the bitwise OR operator. The display order\n    for the buttons is platform-dependent. For example, on Windows,\n    \\uicontrol{Save} is displayed to the left of \\uicontrol{Cancel}, whereas on\n    \\macos, the order is reversed. Mark one of your standard buttons to be your\n    \\l{QMessageBox::defaultButton()} {default button}.\n\n    The \\l{QMessageBox::informativeText} {informative text} property can\n    be used to add additional context to help the user choose the appropriate action.\n\n    \\snippet code/src_gui_dialogs_qmessagebox.cpp 6\n\n    \\image msgbox2.png\n\n    The exec() slot returns the StandardButtons value of the button\n    that was clicked.\n\n    \\snippet code/src_gui_dialogs_qmessagebox.cpp 7\n\n    To give the user more information to help them choose the appropriate,\n    action, set the \\l{QMessageBox::detailedText} {detailed text} property.\n    Depending on the platform the \\l{QMessageBox::detailedText} {detailed text},\n    may require the user to click a \\uicontrol{Show Details...} button to be shown.\n\n    \\image msgbox3.png\n\n    Clicking the \\uicontrol{Show Details...} button displays the detailed text.\n\n    \\image msgbox4.png\n\n    \\section2 Rich Text and the Text Format Property\n\n    The \\l{QMessageBox::detailedText} {detailed text} property is\n    always interpreted as plain text. The \\l{QMessageBox::text} {main\n    text} and \\l{QMessageBox::informativeText} {informative text}\n    properties can be either plain text or rich text. These strings\n    are interpreted according to the setting of the\n    \\l{QMessageBox::textFormat} {text format} property. The default\n    setting is \\l{Qt::AutoText} {auto-text}.\n\n    Note that for some plain text strings containing XML\n    meta-characters, the auto-text \\l{Qt::mightBeRichText()} {rich\n    text detection test} may fail causing your plain text string to be\n    interpreted incorrectly as rich text. In these rare cases, use\n    Qt::convertFromPlainText() to convert your plain text string to a\n    visually equivalent rich text string, or set the\n    \\l{QMessageBox::textFormat} {text format} property explicitly with\n    setTextFormat().\n\n    \\section2 Severity Levels and the Icon and Pixmap Properties\n\n    QMessageBox supports four predefined message severity levels, or message\n    types, which really only differ in the predefined icon they each show.\n    Specify one of the four predefined message types by setting the\n    \\l{QMessageBox::icon}{icon} property to one of the\n    \\l{QMessageBox::Icon}{predefined icons}. The following rules are\n    guidelines:\n\n    \\table\n    \\row\n    \\li \\image qmessagebox-quest.png\n    \\li \\l Question\n    \\li For asking a question during normal operations.\n    \\row\n    \\li \\image qmessagebox-info.png\n    \\li \\l Information\n    \\li For reporting information about normal operations.\n    \\row\n    \\li \\image qmessagebox-warn.png\n    \\li \\l Warning\n    \\li For reporting non-critical errors.\n    \\row\n    \\li \\image qmessagebox-crit.png\n    \\li \\l Critical\n    \\li For reporting critical errors.\n    \\endtable\n\n    \\l{QMessageBox::Icon}{Predefined icons} are not defined by QMessageBox, but\n    provided by the style. The default value is \\l{QMessageBox::NoIcon}\n    {No Icon}. The message boxes are otherwise the same for all cases. When\n    using a standard icon, use the one recommended in the table, or use the\n    one recommended by the style guidelines for your platform. If none of the\n    standard icons is right for your message box, you can use a custom icon by\n    setting the \\l{QMessageBox::iconPixmap}{icon pixmap} property instead of\n    setting the \\l{QMessageBox::icon}{icon} property.\n\n    In summary, to set an icon, use \\e{either} setIcon() for one of the\n    standard icons, \\e{or} setIconPixmap() for a custom icon.\n\n    \\section1 The Static Functions API\n\n    Building message boxes with the static functions API, although\n    convenient, is less flexible than using the property-based API,\n    because the static function signatures lack parameters for setting\n    the \\l{QMessageBox::informativeText} {informative text} and\n    \\l{QMessageBox::detailedText} {detailed text} properties. One\n    work-around for this has been to use the \\c{title} parameter as\n    the message box main text and the \\c{text} parameter as the\n    message box informative text. Because this has the obvious\n    drawback of making a less readable message box, platform\n    guidelines do not recommend it. The \\e{Microsoft Windows User\n    Interface Guidelines} recommend using the\n    \\l{QCoreApplication::applicationName} {application name} as the\n    \\l{QMessageBox::setWindowTitle()} {window's title}, which means\n    that if you have an informative text in addition to your main\n    text, you must concatenate it to the \\c{text} parameter.\n\n    Note that the static function signatures have changed with respect\n    to their button parameters, which are now used to set the\n    \\l{QMessageBox::standardButtons} {standard buttons} and the\n    \\l{QMessageBox::defaultButton()} {default button}.\n\n    Static functions are available for creating information(),\n    question(), warning(), and critical() message boxes.\n\n    \\snippet code/src_gui_dialogs_qmessagebox.cpp 0\n\n    The \\l{dialogs/standarddialogs}{Standard Dialogs} example shows\n    how to use QMessageBox and the other built-in Qt dialogs.\n\n    \\section1 Advanced Usage\n\n    If the \\l{QMessageBox::StandardButtons} {standard buttons} are not\n    flexible enough for your message box, you can use the addButton()\n    overload that takes a text and a ButtonRole to add custom\n    buttons. The ButtonRole is used by QMessageBox to determine the\n    ordering of the buttons on screen (which varies according to the\n    platform). You can test the value of clickedButton() after calling\n    exec(). For example,\n\n    \\snippet code/src_gui_dialogs_qmessagebox.cpp 2\n\n    \\section1 Default and Escape Keys\n\n    The default button (i.e., the button activated when \\uicontrol Enter is\n    pressed) can be specified using setDefaultButton(). If a default\n    button is not specified, QMessageBox tries to find one based on\n    the \\l{ButtonRole} {button roles} of the buttons used in the\n    message box.\n\n    The escape button (the button activated when \\uicontrol Esc is pressed)\n    can be specified using setEscapeButton().  If an escape button is\n    not specified, QMessageBox tries to find one using these rules:\n\n    \\list 1\n\n    \\li If there is only one button, it is the button activated when\n    \\uicontrol Esc is pressed.\n\n    \\li If there is a \\l Cancel button, it is the button activated when\n    \\uicontrol Esc is pressed.\n\n    \\li If there is exactly one button having either\n       \\l{QMessageBox::RejectRole} {the Reject role} or the\n       \\l{QMessageBox::NoRole} {the No role}, it is the button\n       activated when \\uicontrol Esc is pressed.\n\n    \\endlist\n\n    When an escape button can't be determined using these rules,\n    pressing \\uicontrol Esc has no effect.\n\n    \\sa QDialogButtonBox, {Standard Dialogs Example}\n*/\n\n/*!\n    \\enum QMessageBox::ButtonRole\n\n    \\include qdialogbuttonbox.cpp buttonrole-enum\n*/\n\n/*!\n    \\enum QMessageBox::StandardButton\n\n    These enums describe flags for standard buttons. Each button has a\n    defined \\l ButtonRole.\n\n    \\value Ok An \"OK\" button defined with the \\l AcceptRole.\n    \\value Open An \"Open\" button defined with the \\l AcceptRole.\n    \\value Save A \"Save\" button defined with the \\l AcceptRole.\n    \\value Cancel A \"Cancel\" button defined with the \\l RejectRole.\n    \\value Close A \"Close\" button defined with the \\l RejectRole.\n    \\value Discard A \"Discard\" or \"Don't Save\" button, depending on the platform,\n                    defined with the \\l DestructiveRole.\n    \\value Apply An \"Apply\" button defined with the \\l ApplyRole.\n    \\value Reset A \"Reset\" button defined with the \\l ResetRole.\n    \\value RestoreDefaults A \"Restore Defaults\" button defined with the \\l ResetRole.\n    \\value Help A \"Help\" button defined with the \\l HelpRole.\n    \\value SaveAll A \"Save All\" button defined with the \\l AcceptRole.\n    \\value Yes A \"Yes\" button defined with the \\l YesRole.\n    \\value YesToAll A \"Yes to All\" button defined with the \\l YesRole.\n    \\value No A \"No\" button defined with the \\l NoRole.\n    \\value NoToAll A \"No to All\" button defined with the \\l NoRole.\n    \\value Abort An \"Abort\" button defined with the \\l RejectRole.\n    \\value Retry A \"Retry\" button defined with the \\l AcceptRole.\n    \\value Ignore An \"Ignore\" button defined with the \\l AcceptRole.\n\n    \\value NoButton An invalid button.\n\n    \\omitvalue FirstButton\n    \\omitvalue LastButton\n\n    The following values are obsolete:\n\n    \\value YesAll Use YesToAll instead.\n    \\value NoAll Use NoToAll instead.\n    \\value Default Use the \\c defaultButton argument of\n           information(), warning(), etc. instead, or call\n           setDefaultButton().\n    \\value Escape Call setEscapeButton() instead.\n    \\value FlagMask\n    \\value ButtonMask\n\n    \\sa ButtonRole, standardButtons\n*/\n\n/*!\n    \\enum QMessageBox::Option\n    \\since 6.6\n    \\value DontUseNativeDialog Don't use the native message dialog.\n*/\n\n/*!\n    \\fn void QMessageBox::buttonClicked(QAbstractButton *button)\n\n    This signal is emitted whenever a button is clicked inside the QMessageBox.\n    The button that was clicked in returned in \\a button.\n*/\n\n/*!\n    Constructs an \\l{Qt::ApplicationModal} {application modal} message box with no text and no buttons.\n    \\a parent is passed to the QDialog constructor.\n\n    The window modality can be overridden via setWindowModality() before calling show().\n\n    \\note Using open() or exec() to show the message box affects the window modality.\n    Please see the detailed documentation for each function for more information.\n\n    On \\macos, if you want your message box to appear\n    as a Qt::Sheet of its \\a parent, set the message box's\n    \\l{setWindowModality()} {window modality} to Qt::WindowModal or use open().\n    Otherwise, the message box will be a standard dialog.\n\n    \\sa setWindowTitle(), setText(), setIcon(), setStandardButtons(), setWindowModality()\n\n*/\nQMessageBox::QMessageBox(QWidget *parent)\n    : QDialog(*new QMessageBoxPrivate, parent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)\n{\n    Q_D(QMessageBox);\n    d->init();\n}\n\n/*!\n    Constructs an \\l{Qt::ApplicationModal} {application modal} message box with the given \\a icon,\n    \\a title, \\a text, and standard \\a buttons. Standard or custom buttons can be\n    added at any time using addButton(). The \\a parent and \\a f\n    arguments are passed to the QDialog constructor.\n\n    The window modality can be overridden via setWindowModality() before calling show().\n\n    \\note Using open() or exec() to show the message box affects the window modality.\n    Please see the detailed documentation for each function for more information.\n\n    On \\macos, if \\a parent is not \\nullptr and you want your message box\n    to appear as a Qt::Sheet of that parent, set the message box's\n    \\l{setWindowModality()} {window modality} to Qt::WindowModal\n    (default). Otherwise, the message box will be a standard dialog.\n\n    \\sa setWindowTitle(), setText(), setIcon(), setStandardButtons(), setWindowModality()\n*/\nQMessageBox::QMessageBox(Icon icon, const QString &title, const QString &text,\n                         StandardButtons buttons, QWidget *parent,\n                         Qt::WindowFlags f)\n: QDialog(*new QMessageBoxPrivate, parent, f | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)\n{\n    Q_D(QMessageBox);\n    d->init(title, text);\n    setIcon(icon);\n    if (buttons != NoButton)\n        setStandardButtons(buttons);\n}\n\n/*!\n    Destroys the message box.\n*/\nQMessageBox::~QMessageBox()\n{\n}\n\n/*!\n    Adds the given \\a button to the message box with the specified \\a\n    role.\n\n    \\sa removeButton(), button(), setStandardButtons()\n*/\nvoid QMessageBox::addButton(QAbstractButton *button, ButtonRole role)\n{\n    Q_D(QMessageBox);\n    if (!button)\n        return;\n    removeButton(button);\n\n    if (button->text().isEmpty()) {\n        if (auto *platformTheme = QGuiApplicationPrivate::platformTheme()) {\n            if (auto standardButton = QMessageBoxPrivate::standardButtonForRole(role))\n                button->setText(platformTheme->standardButtonText(standardButton));\n        }\n\n        if (button->text().isEmpty()) {\n            qWarning() << \"Cannot add\" << button << \"without title\";\n            return;\n        }\n    }\n\n    d->buttonBox->addButton(button, (QDialogButtonBox::ButtonRole)role);\n    d->customButtonList.append(button);\n    d->autoAddOkButton = false;\n}\n\nQMessageBox::StandardButton QMessageBoxPrivate::standardButtonForRole(QMessageBox::ButtonRole role)\n{\n    switch (role) {\n    case QMessageBox::AcceptRole: return QMessageBox::Ok;\n    case QMessageBox::RejectRole: return QMessageBox::Cancel;\n    case QMessageBox::DestructiveRole: return QMessageBox::Discard;\n    case QMessageBox::HelpRole: return QMessageBox::Help;\n    case QMessageBox::ApplyRole: return QMessageBox::Apply;\n    case QMessageBox::YesRole: return QMessageBox::Yes;\n    case QMessageBox::NoRole: return QMessageBox::No;\n    case QMessageBox::ResetRole: return QMessageBox::Reset;\n    default: return QMessageBox::NoButton;\n    }\n}\n\n/*!\n    \\overload\n\n    Creates a button with the given \\a text, adds it to the message box for the\n    specified \\a role, and returns it.\n*/\nQPushButton *QMessageBox::addButton(const QString& text, ButtonRole role)\n{\n    Q_D(QMessageBox);\n    QPushButton *pushButton = new QPushButton(text);\n    addButton(pushButton, role);\n    d->updateSize();\n    return pushButton;\n}\n\n/*!\n    \\overload\n\n    Adds a standard \\a button to the message box if it is valid to do so, and\n    returns the push button.\n\n    \\sa setStandardButtons()\n*/\nQPushButton *QMessageBox::addButton(StandardButton button)\n{\n    Q_D(QMessageBox);\n    QPushButton *pushButton = d->buttonBox->addButton((QDialogButtonBox::StandardButton)button);\n    if (pushButton)\n        d->autoAddOkButton = false;\n    return pushButton;\n}\n\n/*!\n    Removes \\a button from the button box without deleting it.\n\n    \\sa addButton(), setStandardButtons()\n*/\nvoid QMessageBox::removeButton(QAbstractButton *button)\n{\n    Q_D(QMessageBox);\n    d->customButtonList.removeAll(button);\n    if (d->escapeButton == button)\n        d->escapeButton = nullptr;\n    if (d->defaultButton == button)\n        d->defaultButton = nullptr;\n    d->buttonBox->removeButton(button);\n    d->updateSize();\n}\n\n/*!\n    \\property QMessageBox::standardButtons\n    \\brief collection of standard buttons in the message box\n\n    This property controls which standard buttons are used by the message box.\n\n    By default, this property contains no standard buttons.\n\n    \\sa addButton()\n*/\nvoid QMessageBox::setStandardButtons(StandardButtons buttons)\n{\n    Q_D(QMessageBox);\n    d->buttonBox->setStandardButtons(QDialogButtonBox::StandardButtons(int(buttons)));\n\n    QList<QAbstractButton *> buttonList = d->buttonBox->buttons();\n    if (!buttonList.contains(d->escapeButton))\n        d->escapeButton = nullptr;\n    if (!buttonList.contains(d->defaultButton))\n        d->defaultButton = nullptr;\n    d->autoAddOkButton = false;\n    d->updateSize();\n}\n\nQMessageBox::StandardButtons QMessageBox::standardButtons() const\n{\n    Q_D(const QMessageBox);\n    return QMessageBox::StandardButtons(int(d->buttonBox->standardButtons()));\n}\n\n/*!\n    Returns the standard button enum value corresponding to the given \\a button,\n    or NoButton if the given \\a button isn't a standard button.\n\n    \\sa button(), standardButtons()\n*/\nQMessageBox::StandardButton QMessageBox::standardButton(QAbstractButton *button) const\n{\n    Q_D(const QMessageBox);\n    return (QMessageBox::StandardButton)d->buttonBox->standardButton(button);\n}\n\n/*!\n    Returns a pointer corresponding to the standard button \\a which,\n    or \\nullptr if the standard button doesn't exist in this message box.\n\n    \\note Modifying the properties of the returned button may not be reflected\n    in native implementations of the message dialog. To customize dialog\n    buttons add a \\l{addButton(QAbstractButton *button, QMessageBox::ButtonRole role)}\n    {custom button} or \\l{addButton(const QString &text, QMessageBox::ButtonRole role)}\n    {button title} instead, or set the \\l Option::DontUseNativeDialog option.\n\n    \\sa standardButtons, standardButton()\n*/\nQAbstractButton *QMessageBox::button(StandardButton which) const\n{\n    Q_D(const QMessageBox);\n    return d->buttonBox->button(QDialogButtonBox::StandardButton(which));\n}\n\n/*!\n    Returns the button that is activated when escape is pressed.\n\n    By default, QMessageBox attempts to automatically detect an\n    escape button as follows:\n\n    \\list 1\n    \\li If there is only one button, it is made the escape button.\n    \\li If there is a \\l Cancel button, it is made the escape button.\n    \\li On \\macos only, if there is exactly one button with the role\n       QMessageBox::RejectRole, it is made the escape button.\n    \\endlist\n\n    When an escape button could not be automatically detected, pressing\n    \\uicontrol Esc has no effect.\n\n    \\sa addButton()\n*/\nQAbstractButton *QMessageBox::escapeButton() const\n{\n    Q_D(const QMessageBox);\n    return d->escapeButton;\n}\n\n/*!\n    Sets the button that gets activated when the \\uicontrol Escape key is\n    pressed to \\a button.\n\n    \\sa addButton(), clickedButton()\n*/\nvoid QMessageBox::setEscapeButton(QAbstractButton *button)\n{\n    Q_D(QMessageBox);\n    if (d->buttonBox->buttons().contains(button))\n        d->escapeButton = button;\n}\n\n/*!\n    Sets the buttons that gets activated when the \\uicontrol Escape key is\n    pressed to \\a button.\n\n    \\sa addButton(), clickedButton()\n*/\nvoid QMessageBox::setEscapeButton(QMessageBox::StandardButton button)\n{\n    Q_D(QMessageBox);\n    setEscapeButton(d->buttonBox->button(QDialogButtonBox::StandardButton(button)));\n}\n\nvoid QMessageBoxPrivate::detectEscapeButton()\n{\n    if (escapeButton) { // escape button explicitly set\n        detectedEscapeButton = escapeButton;\n        return;\n    }\n\n    // Cancel button automatically becomes escape button\n    detectedEscapeButton = buttonBox->button(QDialogButtonBox::Cancel);\n    if (detectedEscapeButton)\n        return;\n\n    // If there is only one button, make it the escape button\n    const QList<QAbstractButton *> buttons = buttonBox->buttons();\n    if (buttons.size() == 1) {\n        detectedEscapeButton = buttons.first();\n        return;\n    }\n\n    // If there are two buttons and one of them is the \"Show Details...\"\n    // button, then make the other one the escape button\n    if (buttons.size() == 2 && detailsButton) {\n        auto idx = buttons.indexOf(detailsButton);\n        if (idx != -1) {\n            detectedEscapeButton = buttons.at(1 - idx);\n            return;\n        }\n    }\n\n    // if the message box has one RejectRole button, make it the escape button\n    for (auto *button : buttons) {\n        if (buttonBox->buttonRole(button) == QDialogButtonBox::RejectRole) {\n            if (detectedEscapeButton) { // already detected!\n                detectedEscapeButton = nullptr;\n                break;\n            }\n            detectedEscapeButton = button;\n        }\n    }\n    if (detectedEscapeButton)\n        return;\n\n    // if the message box has one NoRole button, make it the escape button\n    for (auto *button : buttons) {\n        if (buttonBox->buttonRole(button) == QDialogButtonBox::NoRole) {\n            if (detectedEscapeButton) { // already detected!\n                detectedEscapeButton = nullptr;\n                break;\n            }\n            detectedEscapeButton = button;\n        }\n    }\n}\n\n/*!\n    Returns the button that was clicked by the user,\n    or \\nullptr if the user hit the \\uicontrol Esc key and\n    no \\l{setEscapeButton()}{escape button} was set.\n\n    If exec() hasn't been called yet, returns nullptr.\n\n    Example:\n\n    \\snippet code/src_gui_dialogs_qmessagebox.cpp 3\n\n    \\sa standardButton(), button()\n*/\nQAbstractButton *QMessageBox::clickedButton() const\n{\n    Q_D(const QMessageBox);\n    return d->clickedButton;\n}\n\n/*!\n    Returns the button that should be the message box's\n    \\l{QPushButton::setDefault()}{default button}. Returns nullptr\n    if no default button was set.\n\n    \\sa addButton(), QPushButton::setDefault()\n*/\nQPushButton *QMessageBox::defaultButton() const\n{\n    Q_D(const QMessageBox);\n    return d->defaultButton;\n}\n\n/*!\n    Sets the message box's \\l{QPushButton::setDefault()}{default button}\n    to \\a button.\n\n    \\sa addButton(), QPushButton::setDefault()\n*/\nvoid QMessageBox::setDefaultButton(QPushButton *button)\n{\n    Q_D(QMessageBox);\n    if (!d->buttonBox->buttons().contains(button))\n        return;\n    d->defaultButton = button;\n    button->setDefault(true);\n    button->setFocus();\n}\n\n/*!\n    Sets the message box's \\l{QPushButton::setDefault()}{default button}\n    to \\a button.\n\n    \\sa addButton(), QPushButton::setDefault()\n*/\nvoid QMessageBox::setDefaultButton(QMessageBox::StandardButton button)\n{\n    Q_D(QMessageBox);\n    setDefaultButton(d->buttonBox->button(QDialogButtonBox::StandardButton(button)));\n}\n\n/*! \\since 5.2\n\n    Sets the checkbox \\a cb on the message dialog. The message box takes ownership of the checkbox.\n    The argument \\a cb can be \\nullptr to remove an existing checkbox from the message box.\n\n    \\sa checkBox()\n*/\n\nvoid QMessageBox::setCheckBox(QCheckBox *cb)\n{\n    Q_D(QMessageBox);\n\n    if (cb == d->checkbox)\n        return;\n\n    if (d->checkbox) {\n        d->checkbox->hide();\n        layout()->removeWidget(d->checkbox);\n        if (d->checkbox->parentWidget() == this) {\n            d->checkbox->setParent(nullptr);\n            d->checkbox->deleteLater();\n        }\n    }\n    d->checkbox = cb;\n    if (d->checkbox) {\n        QSizePolicy sp = d->checkbox->sizePolicy();\n        sp.setHorizontalPolicy(QSizePolicy::MinimumExpanding);\n        d->checkbox->setSizePolicy(sp);\n    }\n    d->setupLayout();\n}\n\n\n/*! \\since 5.2\n\n    Returns the checkbox shown on the dialog. This is \\nullptr if no checkbox is set.\n    \\sa setCheckBox()\n*/\n\nQCheckBox* QMessageBox::checkBox() const\n{\n    Q_D(const QMessageBox);\n    return d->checkbox;\n}\n\n/*!\n    \\since 6.6\n    Sets the given \\a option to be enabled if \\a on is true; otherwise,\n    clears the given \\a option.\n\n    Options (particularly the \\l Option::DontUseNativeDialog option) should be set\n    before showing the dialog.\n\n    Setting options while the dialog is visible is not guaranteed to have\n    an immediate effect on the dialog.\n\n    Setting options after changing other properties may cause these\n    values to have no effect.\n\n    \\sa options, testOption()\n*/\nvoid QMessageBox::setOption(QMessageBox::Option option, bool on)\n{\n    const QMessageBox::Options previousOptions = options();\n    if (!(previousOptions & option) != !on)\n        setOptions(previousOptions ^ option);\n}\n\n/*!\n    \\since 6.6\n\n    Returns \\c true if the given \\a option is enabled; otherwise, returns\n    false.\n\n    \\sa options, setOption()\n*/\nbool QMessageBox::testOption(QMessageBox::Option option) const\n{\n    Q_D(const QMessageBox);\n    return d->options->testOption(static_cast<QMessageDialogOptions::Option>(option));\n}\n\nvoid QMessageBox::setOptions(QMessageBox::Options options)\n{\n    Q_D(QMessageBox);\n\n    if (QMessageBox::options() == options)\n        return;\n\n    d->options->setOptions(QMessageDialogOptions::Option(int(options)));\n}\n\nQMessageBox::Options QMessageBox::options() const\n{\n    Q_D(const QMessageBox);\n    return QMessageBox::Options(int(d->options->options()));\n}\n\n/*!\n    \\property QMessageBox::options\n    \\brief Options that affect the look and feel of the dialog.\n    \\since 6.6\n\n    By default, these options are disabled.\n\n    The option \\l Option::DontUseNativeDialog should be set\n    before changing dialog properties or showing the dialog.\n\n    Setting options while the dialog is visible is not guaranteed to have\n    an immediate effect on the dialog.\n\n    Setting options after changing other properties may cause these\n    values to have no effect.\n\n    \\sa setOption(), testOption()\n*/\n\n/*!\n  \\property QMessageBox::text\n  \\brief the message box text to be displayed.\n\n  The text should be a brief sentence or phrase that describes the situation,\n  ideally formulated as a neutral statement, or a call-to-action question.\n\n  The text will be interpreted either as a plain text or as rich text,\n  depending on the text format setting (\\l QMessageBox::textFormat).\n  The default setting is Qt::AutoText, i.e., the message box will try\n  to auto-detect the format of the text.\n\n  The default value of this property is an empty string.\n\n  \\sa textFormat, QMessageBox::informativeText, QMessageBox::detailedText\n*/\nQString QMessageBox::text() const\n{\n    Q_D(const QMessageBox);\n    return d->label->text();\n}\n\nvoid QMessageBox::setText(const QString &text)\n{\n    Q_D(QMessageBox);\n    d->label->setText(text);\n    d->label->setWordWrap(d->label->textFormat() == Qt::RichText\n        || (d->label->textFormat() == Qt::AutoText && Qt::mightBeRichText(text)));\n    d->updateSize();\n}\n\n/*!\n    \\enum QMessageBox::Icon\n\n    This enum has the following values:\n\n    \\value NoIcon the message box does not have any icon.\n\n    \\value Question an icon indicating that\n    the message is asking a question.\n\n    \\value Information an icon indicating that\n    the message is nothing out of the ordinary.\n\n    \\value Warning an icon indicating that the\n    message is a warning, but can be dealt with.\n\n    \\value Critical an icon indicating that\n    the message represents a critical problem.\n\n*/\n\n/*!\n    \\property QMessageBox::icon\n    \\brief the message box's icon\n\n    The icon of the message box can be specified with one of the\n    values:\n\n    \\list\n    \\li QMessageBox::NoIcon\n    \\li QMessageBox::Question\n    \\li QMessageBox::Information\n    \\li QMessageBox::Warning\n    \\li QMessageBox::Critical\n    \\endlist\n\n    The default is QMessageBox::NoIcon.\n\n    The pixmap used to display the actual icon depends on the current\n    \\l{QWidget::style()} {GUI style}. You can also set a custom pixmap\n    for the icon by setting the \\l{QMessageBox::iconPixmap} {icon\n    pixmap} property.\n\n    \\sa iconPixmap\n*/\nQMessageBox::Icon QMessageBox::icon() const\n{\n    Q_D(const QMessageBox);\n    return d->icon;\n}\n\nvoid QMessageBox::setIcon(Icon icon)\n{\n    Q_D(QMessageBox);\n    setIconPixmap(QMessageBoxPrivate::standardIcon((QMessageBox::Icon)icon,\n                                                   this));\n    d->icon = icon;\n}\n\n/*!\n    \\property QMessageBox::iconPixmap\n    \\brief the current icon\n\n    The icon currently used by the message box. Note that it's often\n    hard to draw one pixmap that looks appropriate in all GUI styles;\n    you may want to supply a different pixmap for each platform.\n\n    By default, this property is undefined.\n\n    \\sa icon\n*/\nQPixmap QMessageBox::iconPixmap() const\n{\n    Q_D(const QMessageBox);\n    return d->iconLabel->pixmap();\n}\n\nvoid QMessageBox::setIconPixmap(const QPixmap &pixmap)\n{\n    Q_D(QMessageBox);\n    d->iconLabel->setPixmap(pixmap);\n    d->icon = NoIcon;\n    d->setupLayout();\n}\n\n/*!\n    \\property QMessageBox::textFormat\n    \\brief the format of the text displayed by the message box\n\n    The current text format used by the message box. See the \\l\n    Qt::TextFormat enum for an explanation of the possible options.\n\n    The default format is Qt::AutoText.\n\n    \\sa setText()\n*/\nQt::TextFormat QMessageBox::textFormat() const\n{\n    Q_D(const QMessageBox);\n    return d->label->textFormat();\n}\n\nvoid QMessageBox::setTextFormat(Qt::TextFormat format)\n{\n    Q_D(QMessageBox);\n    d->label->setTextFormat(format);\n    d->label->setWordWrap(format == Qt::RichText\n                    || (format == Qt::AutoText && Qt::mightBeRichText(d->label->text())));\n    if (d->informativeLabel)\n        d->informativeLabel->setTextFormat(format);\n    d->updateSize();\n}\n\n/*!\n    \\property QMessageBox::textInteractionFlags\n    \\since 5.1\n\n    Specifies how the label of the message box should interact with user\n    input.\n\n    The default value depends on the style.\n\n    \\sa QStyle::SH_MessageBox_TextInteractionFlags\n*/\n\nQt::TextInteractionFlags QMessageBox::textInteractionFlags() const\n{\n    Q_D(const QMessageBox);\n    return d->label->textInteractionFlags();\n}\n\nvoid QMessageBox::setTextInteractionFlags(Qt::TextInteractionFlags flags)\n{\n    Q_D(QMessageBox);\n    d->label->setTextInteractionFlags(flags);\n}\n\n/*!\n    \\reimp\n*/\nbool QMessageBox::event(QEvent *e)\n{\n    bool result =QDialog::event(e);\n    switch (e->type()) {\n        case QEvent::LayoutRequest:\n            d_func()->updateSize();\n            break;\n        case QEvent::LanguageChange:\n            d_func()->retranslateStrings();\n            break;\n        default:\n            break;\n    }\n    return result;\n}\n\n/*!\n    \\reimp\n*/\nvoid QMessageBox::resizeEvent(QResizeEvent *event)\n{\n    QDialog::resizeEvent(event);\n}\n\n/*!\n    \\reimp\n*/\nvoid QMessageBox::closeEvent(QCloseEvent *e)\n{\n    Q_D(QMessageBox);\n    if (!d->detectedEscapeButton) {\n        e->ignore();\n        return;\n    }\n    QDialog::closeEvent(e);\n    if (!d->clickedButton) {\n        d->clickedButton = d->detectedEscapeButton;\n        setResult(d->execReturnCode(d->detectedEscapeButton));\n    }\n}\n\n/*!\n    \\reimp\n*/\nvoid QMessageBox::changeEvent(QEvent *ev)\n{\n    Q_D(QMessageBox);\n    switch (ev->type()) {\n    case QEvent::StyleChange:\n    {\n        if (d->icon != NoIcon)\n            setIcon(d->icon);\n        Qt::TextInteractionFlags flags(style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, nullptr, this));\n        d->label->setTextInteractionFlags(flags);\n        d->buttonBox->setCenterButtons(style()->styleHint(QStyle::SH_MessageBox_CenterButtons, nullptr, this));\n        if (d->informativeLabel)\n            d->informativeLabel->setTextInteractionFlags(flags);\n        Q_FALLTHROUGH();\n    }\n    case QEvent::FontChange:\n    case QEvent::ApplicationFontChange:\n#ifdef Q_OS_MAC\n    {\n        QFont f = font();\n        f.setBold(true);\n        d->label->setFont(f);\n    }\n#endif\n        Q_FALLTHROUGH();\n    default:\n        break;\n    }\n    QDialog::changeEvent(ev);\n}\n\n/*!\n    \\reimp\n*/\nvoid QMessageBox::keyPressEvent(QKeyEvent *e)\n{\n#if QT_CONFIG(shortcut)\n        Q_D(QMessageBox);\n        if (e->matches(QKeySequence::Cancel)) {\n            if (d->detectedEscapeButton) {\n#ifdef Q_OS_MAC\n                d->detectedEscapeButton->animateClick();\n#else\n                d->detectedEscapeButton->click();\n#endif\n            }\n            return;\n        }\n#endif // QT_CONFIG(shortcut)\n\n#if !defined(QT_NO_CLIPBOARD) && !defined(QT_NO_SHORTCUT)\n\n#if QT_CONFIG(textedit)\n        if (e == QKeySequence::Copy) {\n            if (d->detailsText && d->detailsText->isVisible() && d->detailsText->copy()) {\n                e->setAccepted(true);\n                return;\n            }\n        } else if (e == QKeySequence::SelectAll && d->detailsText && d->detailsText->isVisible()) {\n            d->detailsText->selectAll();\n            e->setAccepted(true);\n            return;\n        }\n#endif // QT_CONFIG(textedit)\n\n#if defined(Q_OS_WIN)\n        if (e == QKeySequence::Copy) {\n            const auto separator = \"---------------------------\\n\"_L1;\n            QString textToCopy;\n            textToCopy += separator + windowTitle() + u'\\n' + separator // title\n                          + d->label->text() + u'\\n' + separator;       // text\n\n            if (d->informativeLabel)\n                textToCopy += d->informativeLabel->text() + u'\\n' + separator;\n\n            const QList<QAbstractButton *> buttons = d->buttonBox->buttons();\n            for (const auto *button : buttons)\n                textToCopy += button->text() + \"   \"_L1;\n            textToCopy += u'\\n' + separator;\n#if QT_CONFIG(textedit)\n            if (d->detailsText)\n                textToCopy += d->detailsText->text() + u'\\n' + separator;\n#endif\n            QGuiApplication::clipboard()->setText(textToCopy);\n            return;\n        }\n#endif // Q_OS_WIN\n\n#endif // !QT_NO_CLIPBOARD && !QT_NO_SHORTCUT\n\n#ifndef QT_NO_SHORTCUT\n    if (!(e->modifiers() & (Qt::AltModifier | Qt::ControlModifier | Qt::MetaModifier))) {\n        int key = e->key() & ~Qt::MODIFIER_MASK;\n        if (key) {\n            const QList<QAbstractButton *> buttons = d->buttonBox->buttons();\n            for (auto *pb : buttons) {\n                QKeySequence shortcut = pb->shortcut();\n                if (!shortcut.isEmpty() && key == shortcut[0].key()) {\n                    pb->animateClick();\n                    return;\n                }\n            }\n        }\n    }\n#endif\n    QDialog::keyPressEvent(e);\n}\n\n/*!\n    Opens the dialog and connects its finished() or buttonClicked() signal to\n    the slot specified by \\a receiver and \\a member. If the slot in \\a member\n    has a pointer for its first parameter the connection is to buttonClicked(),\n    otherwise the connection is to finished().\n\n    The signal will be disconnected from the slot when the dialog is closed.\n*/\nvoid QMessageBox::open(QObject *receiver, const char *member)\n{\n    Q_D(QMessageBox);\n    const char *signal = member && strchr(member, '*') ? SIGNAL(buttonClicked(QAbstractButton*))\n                                                       : SIGNAL(finished(int));\n    connect(this, signal, receiver, member);\n    d->signalToDisconnectOnClose = signal;\n    d->receiverToDisconnectOnClose = receiver;\n    d->memberToDisconnectOnClose = member;\n    QDialog::open();\n}\n\nvoid QMessageBoxPrivate::setVisible(bool visible)\n{\n    Q_Q(QMessageBox);\n\n    // Last minute setup\n    if (autoAddOkButton)\n        q->addButton(QMessageBox::Ok);\n    detectEscapeButton();\n\n    if (canBeNativeDialog())\n        setNativeDialogVisible(visible);\n\n    // Update WA_DontShowOnScreen based on whether the native dialog was shown,\n    // so that QDialog::setVisible(visible) below updates the QWidget state correctly,\n    // but skips showing the non-native version.\n    q->setAttribute(Qt::WA_DontShowOnScreen, nativeDialogInUse);\n\n    QDialogPrivate::setVisible(visible);\n}\n\n/*!\n    Returns a list of all the buttons that have been added to the message box.\n\n    \\sa buttonRole(), addButton(), removeButton()\n*/\nQList<QAbstractButton *> QMessageBox::buttons() const\n{\n    Q_D(const QMessageBox);\n    return d->buttonBox->buttons();\n}\n\n/*!\n    Returns the button role for the specified \\a button. This function returns\n    \\l InvalidRole if \\a button is \\nullptr or has not been added to the message box.\n\n    \\sa buttons(), addButton()\n*/\nQMessageBox::ButtonRole QMessageBox::buttonRole(QAbstractButton *button) const\n{\n    Q_D(const QMessageBox);\n    return QMessageBox::ButtonRole(d->buttonBox->buttonRole(button));\n}\n\n/*!\n    \\reimp\n*/\nvoid QMessageBox::showEvent(QShowEvent *e)\n{\n    Q_D(QMessageBox);\n    d->clickedButton = nullptr;\n    d->updateSize();\n\n#if QT_CONFIG(accessibility)\n    QAccessibleEvent event(this, QAccessible::Alert);\n    QAccessible::updateAccessibility(&event);\n#endif\n#if defined(Q_OS_WIN)\n    if (const HMENU systemMenu = qt_getWindowsSystemMenu(this)) {\n        EnableMenuItem(systemMenu, SC_CLOSE, d->detectedEscapeButton ?\n                       MF_BYCOMMAND|MF_ENABLED : MF_BYCOMMAND|MF_GRAYED);\n    }\n#endif\n    QDialog::showEvent(e);\n}\n\n\nstatic QMessageBox::StandardButton showNewMessageBox(QWidget *parent,\n    QMessageBox::Icon icon,\n    const QString& title, const QString& text,\n    QMessageBox::StandardButtons buttons,\n    QMessageBox::StandardButton defaultButton)\n{\n    // necessary for source compatibility with Qt 4.0 and 4.1\n    // handles (Yes, No) and (Yes|Default, No)\n    if (defaultButton && !(buttons & defaultButton)) {\n        const int defaultButtons = defaultButton | QMessageBox::Default;\n        const int otherButtons = buttons.toInt();\n        const int ret = QMessageBoxPrivate::showOldMessageBox(parent, icon, title,\n                                                              text, otherButtons,\n                                                              defaultButtons, 0);\n        return static_cast<QMessageBox::StandardButton>(ret);\n    }\n\n    QMessageBox msgBox(icon, title, text, QMessageBox::NoButton, parent);\n    QDialogButtonBox *buttonBox = msgBox.findChild<QDialogButtonBox*>();\n    Q_ASSERT(buttonBox != nullptr);\n\n    uint mask = QMessageBox::FirstButton;\n    while (mask <= QMessageBox::LastButton) {\n        uint sb = buttons & mask;\n        mask <<= 1;\n        if (!sb)\n            continue;\n        QPushButton *button = msgBox.addButton((QMessageBox::StandardButton)sb);\n        // Choose the first accept role as the default\n        if (msgBox.defaultButton())\n            continue;\n        if ((defaultButton == QMessageBox::NoButton && buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)\n            || (defaultButton != QMessageBox::NoButton && sb == uint(defaultButton)))\n            msgBox.setDefaultButton(button);\n    }\n    if (msgBox.exec() == -1)\n        return QMessageBox::Cancel;\n    return msgBox.standardButton(msgBox.clickedButton());\n}\n\n/*!\n    Opens an information message box with the given \\a title and\n    \\a text in front of the specified \\a parent widget.\n\n    The standard \\a buttons are added to the message box.\n    \\a defaultButton specifies the button used when \\uicontrol Enter is pressed.\n    \\a defaultButton must refer to a button that was given in \\a buttons.\n    If \\a defaultButton is QMessageBox::NoButton, QMessageBox\n    chooses a suitable default automatically.\n\n    Returns the identity of the standard button that was clicked. If\n    \\uicontrol Esc was pressed instead, the \\l{Default and Escape Keys}\n    {escape button} is returned.\n\n    The message box is an \\l{Qt::ApplicationModal}{application modal}\n    dialog box.\n\n    \\warning Do not delete \\a parent during the execution of the dialog.\n             If you want to do this, you should create the dialog\n             yourself using one of the QMessageBox constructors.\n\n    \\sa question(), warning(), critical()\n*/\nQMessageBox::StandardButton QMessageBox::information(QWidget *parent, const QString &title,\n                               const QString& text, StandardButtons buttons,\n                               StandardButton defaultButton)\n{\n    return showNewMessageBox(parent, Information, title, text, buttons,\n                             defaultButton);\n}\n\n\n/*!\n    Opens a question message box with the given \\a title and \\a\n    text in front of the specified \\a parent widget.\n\n    The standard \\a buttons are added to the message box. \\a\n    defaultButton specifies the button used when \\uicontrol Enter is\n    pressed. \\a defaultButton must refer to a button that was given in \\a buttons.\n    If \\a defaultButton is QMessageBox::NoButton, QMessageBox\n    chooses a suitable default automatically.\n\n    Returns the identity of the standard button that was clicked. If\n    \\uicontrol Esc was pressed instead, the \\l{Default and Escape Keys}\n    {escape button} is returned.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n    \\warning Do not delete \\a parent during the execution of the dialog.\n             If you want to do this, you should create the dialog\n             yourself using one of the QMessageBox constructors.\n\n    \\sa information(), warning(), critical()\n*/\nQMessageBox::StandardButton QMessageBox::question(QWidget *parent, const QString &title,\n                            const QString& text, StandardButtons buttons,\n                            StandardButton defaultButton)\n{\n    return showNewMessageBox(parent, Question, title, text, buttons, defaultButton);\n}\n\n/*!\n    Opens a warning message box with the given \\a title and \\a\n    text in front of the specified \\a parent widget.\n\n    The standard \\a buttons are added to the message box. \\a\n    defaultButton specifies the button used when \\uicontrol Enter is\n    pressed. \\a defaultButton must refer to a button that was given in \\a buttons.\n    If \\a defaultButton is QMessageBox::NoButton, QMessageBox\n    chooses a suitable default automatically.\n\n    Returns the identity of the standard button that was clicked. If\n    \\uicontrol Esc was pressed instead, the \\l{Default and Escape Keys}\n    {escape button} is returned.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n    \\warning Do not delete \\a parent during the execution of the dialog.\n             If you want to do this, you should create the dialog\n             yourself using one of the QMessageBox constructors.\n\n    \\sa question(), information(), critical()\n*/\nQMessageBox::StandardButton QMessageBox::warning(QWidget *parent, const QString &title,\n                        const QString& text, StandardButtons buttons,\n                        StandardButton defaultButton)\n{\n    return showNewMessageBox(parent, Warning, title, text, buttons, defaultButton);\n}\n\n/*!\n    Opens a critical message box with the given \\a title and \\a\n    text in front of the specified \\a parent widget.\n\n    The standard \\a buttons are added to the message box. \\a\n    defaultButton specifies the button used when \\uicontrol Enter is\n    pressed. \\a defaultButton must refer to a button that was given in \\a buttons.\n    If \\a defaultButton is QMessageBox::NoButton, QMessageBox\n    chooses a suitable default automatically.\n\n    Returns the identity of the standard button that was clicked. If\n    \\uicontrol Esc was pressed instead, the \\l{Default and Escape Keys}\n    {escape button} is returned.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n    \\warning Do not delete \\a parent during the execution of the dialog.\n             If you want to do this, you should create the dialog\n             yourself using one of the QMessageBox constructors.\n\n    \\sa question(), warning(), information()\n*/\nQMessageBox::StandardButton QMessageBox::critical(QWidget *parent, const QString &title,\n                         const QString& text, StandardButtons buttons,\n                         StandardButton defaultButton)\n{\n    return showNewMessageBox(parent, Critical, title, text, buttons, defaultButton);\n}\n\n/*!\n    Displays a simple about box with title \\a title and text \\a\n    text. The about box's parent is \\a parent.\n\n    about() looks for a suitable icon in four locations:\n\n    \\list 1\n    \\li It prefers \\l{QWidget::windowIcon()}{parent->icon()}\n    if that exists.\n    \\li If not, it tries the top-level widget containing \\a parent.\n    \\li If that fails, it tries the \\l{QApplication::activeWindow()}{active window.}\n    \\li As a last resort it uses the Information icon.\n    \\endlist\n\n    The about box has a single button labelled \"OK\".\n\n    On \\macos, the about box is popped up as a modeless window; on\n    other platforms, it is currently application modal.\n\n    \\sa QWidget::windowIcon(), QApplication::activeWindow()\n*/\nvoid QMessageBox::about(QWidget *parent, const QString &title, const QString &text)\n{\n#ifdef Q_OS_MAC\n    static QPointer<QMessageBox> oldMsgBox;\n\n    if (oldMsgBox && oldMsgBox->text() == text) {\n        oldMsgBox->show();\n        oldMsgBox->raise();\n        oldMsgBox->activateWindow();\n        return;\n    }\n#endif\n\n    QMessageBox *msgBox = new QMessageBox(Information, title, text, NoButton, parent\n#ifdef Q_OS_MAC\n                                          , Qt::WindowTitleHint | Qt::WindowSystemMenuHint\n#endif\n    );\n    msgBox->setAttribute(Qt::WA_DeleteOnClose);\n    QIcon icon = msgBox->windowIcon();\n    msgBox->setIconPixmap(icon.pixmap(QSize(64, 64), msgBox->devicePixelRatio()));\n\n    // should perhaps be a style hint\n#ifdef Q_OS_MAC\n    oldMsgBox = msgBox;\n    auto *d = msgBox->d_func();\n    d->buttonBox->setCenterButtons(true);\n#ifdef Q_OS_IOS\n    msgBox->setModal(true);\n#else\n    msgBox->setModal(false);\n#endif\n    msgBox->show();\n#else\n    msgBox->exec();\n#endif\n}\n\n/*!\n    Displays a simple message box about Qt, with the given \\a title\n    and centered over \\a parent (if \\a parent is not \\nullptr). The message\n    includes the version number of Qt being used by the application.\n\n    This is useful for inclusion in the \\uicontrol Help menu of an application,\n    as shown in the \\l{mainwindows/menus}{Menus} example.\n\n    QApplication provides this functionality as a slot.\n\n    On \\macos, the aboutQt box is popped up as a modeless window; on\n    other platforms, it is currently application modal.\n\n    \\sa QApplication::aboutQt()\n*/\nvoid QMessageBox::aboutQt(QWidget *parent, const QString &title)\n{\n#ifdef Q_OS_MAC\n    static QPointer<QMessageBox> oldMsgBox;\n\n    if (oldMsgBox) {\n        oldMsgBox->show();\n        oldMsgBox->raise();\n        oldMsgBox->activateWindow();\n        return;\n    }\n#endif\n\n    QString translatedTextAboutQtCaption;\n    translatedTextAboutQtCaption = QMessageBox::tr(\n        \"<h3>About Qt</h3>\"\n        \"<p>This program uses Qt version %1.</p>\"\n        ).arg(QT_VERSION_STR \"\"_L1);\n    //: Leave this text untranslated or include a verbatim copy of it below\n    //: and note that it is the authoritative version in case of doubt.\n    const QString translatedTextAboutQtText = QMessageBox::tr(\n        \"<p>Qt is a C++ toolkit for cross-platform application \"\n        \"development.</p>\"\n        \"<p>Qt provides single-source portability across all major desktop \"\n        \"operating systems. It is also available for embedded Linux and other \"\n        \"embedded and mobile operating systems.</p>\"\n        \"<p>Qt is available under multiple licensing options designed \"\n        \"to accommodate the needs of our various users.</p>\"\n        \"<p>Qt licensed under our commercial license agreement is appropriate \"\n        \"for development of proprietary/commercial software where you do not \"\n        \"want to share any source code with third parties or otherwise cannot \"\n        \"comply with the terms of GNU (L)GPL.</p>\"\n        \"<p>Qt licensed under GNU (L)GPL is appropriate for the \"\n        \"development of Qt&nbsp;applications provided you can comply with the terms \"\n        \"and conditions of the respective licenses.</p>\"\n        \"<p>Please see <a href=\\\"https://%2/\\\">%2</a> \"\n        \"for an overview of Qt licensing.</p>\"\n        \"<p>Copyright (C) The Qt Company Ltd. and other \"\n        \"contributors.</p>\"\n        \"<p>Qt and the Qt logo are trademarks of The Qt Company Ltd.</p>\"\n        \"<p>Qt is The Qt Company Ltd. product developed as an open source \"\n        \"project. See <a href=\\\"https://%3/\\\">%3</a> for more information.</p>\"\n        ).arg(QStringLiteral(\"qt.io/licensing\"),\n              QStringLiteral(\"qt.io\"));\n    QMessageBox *msgBox = new QMessageBox(parent);\n    msgBox->setAttribute(Qt::WA_DeleteOnClose);\n    msgBox->setWindowTitle(title.isEmpty() ? tr(\"About Qt\") : title);\n    msgBox->setText(translatedTextAboutQtCaption);\n    msgBox->setInformativeText(translatedTextAboutQtText);\n\n    QPixmap pm(\":/qt-project.org/qmessagebox/images/qtlogo-64.png\"_L1);\n    if (!pm.isNull())\n        msgBox->setIconPixmap(pm);\n\n    // should perhaps be a style hint\n#ifdef Q_OS_MAC\n    oldMsgBox = msgBox;\n    auto *d = msgBox->d_func();\n    d->buttonBox->setCenterButtons(true);\n#ifdef Q_OS_IOS\n    msgBox->setModal(true);\n#else\n    msgBox->setModal(false);\n#endif\n    msgBox->show();\n#else\n    msgBox->exec();\n#endif\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////\n// Source and binary compatibility routines for 4.0 and 4.1\n\nstatic QMessageBox::StandardButton newButton(int button)\n{\n    // this is needed for source compatibility with Qt 4.0 and 4.1\n    if (button == QMessageBox::NoButton || (button & NewButtonMask))\n        return QMessageBox::StandardButton(button & QMessageBox::ButtonMask);\n\n    return QMessageBox::NoButton;\n}\n\nstatic bool detectedCompat(int button0, int button1, int button2)\n{\n    if (button0 != 0 && !(button0 & NewButtonMask))\n        return true;\n    if (button1 != 0 && !(button1 & NewButtonMask))\n        return true;\n    if (button2 != 0 && !(button2 & NewButtonMask))\n        return true;\n    return false;\n}\n\nQAbstractButton *QMessageBoxPrivate::findButton(int button0, int button1, int button2, int flags)\n{\n    Q_Q(QMessageBox);\n    int button = 0;\n\n    if (button0 & flags) {\n        button = button0;\n    } else if (button1 & flags) {\n        button = button1;\n    } else if (button2 & flags) {\n        button = button2;\n    }\n    return q->button(newButton(button));\n}\n\nvoid QMessageBoxPrivate::addOldButtons(int button0, int button1, int button2)\n{\n    Q_Q(QMessageBox);\n    q->addButton(newButton(button0));\n    q->addButton(newButton(button1));\n    q->addButton(newButton(button2));\n    q->setDefaultButton(\n        static_cast<QPushButton *>(findButton(button0, button1, button2, QMessageBox::Default)));\n    q->setEscapeButton(findButton(button0, button1, button2, QMessageBox::Escape));\n    compatMode = detectedCompat(button0, button1, button2);\n}\n\nQAbstractButton *QMessageBoxPrivate::abstractButtonForId(int id) const\n{\n    Q_Q(const QMessageBox);\n    QAbstractButton *result = customButtonList.value(id);\n    if (result)\n        return result;\n    if (id & QMessageBox::FlagMask)    // for compatibility with Qt 4.0/4.1 (even if it is silly)\n        return nullptr;\n    return q->button(newButton(id));\n}\n\nint QMessageBoxPrivate::showOldMessageBox(QWidget *parent, QMessageBox::Icon icon,\n                                          const QString &title, const QString &text,\n                                          int button0, int button1, int button2)\n{\n    QMessageBox messageBox(icon, title, text, QMessageBox::NoButton, parent);\n    messageBox.d_func()->addOldButtons(button0, button1, button2);\n    return messageBox.exec();\n}\n\nint QMessageBoxPrivate::showOldMessageBox(QWidget *parent, QMessageBox::Icon icon,\n                                            const QString &title, const QString &text,\n                                            const QString &button0Text,\n                                            const QString &button1Text,\n                                            const QString &button2Text,\n                                            int defaultButtonNumber,\n                                            int escapeButtonNumber)\n{\n    QMessageBox messageBox(icon, title, text, QMessageBox::NoButton, parent);\n    QString myButton0Text = button0Text;\n    if (myButton0Text.isEmpty())\n        myButton0Text = QDialogButtonBox::tr(\"OK\");\n    messageBox.addButton(myButton0Text, QMessageBox::ActionRole);\n    if (!button1Text.isEmpty())\n        messageBox.addButton(button1Text, QMessageBox::ActionRole);\n    if (!button2Text.isEmpty())\n        messageBox.addButton(button2Text, QMessageBox::ActionRole);\n\n    const QList<QAbstractButton *> &buttonList = messageBox.d_func()->customButtonList;\n    messageBox.setDefaultButton(static_cast<QPushButton *>(buttonList.value(defaultButtonNumber)));\n    messageBox.setEscapeButton(buttonList.value(escapeButtonNumber));\n\n    messageBox.exec();\n\n    // Ignore exec return value and use button index instead,\n    // as that's what the documentation promises.\n    return buttonList.indexOf(messageBox.clickedButton());\n}\n\nvoid QMessageBoxPrivate::retranslateStrings()\n{\n#if QT_CONFIG(textedit)\n    if (detailsButton && detailsText)\n        detailsButton->setLabel(detailsText->isHidden() ? ShowLabel : HideLabel);\n#endif\n}\n\n#if QT_DEPRECATED_SINCE(6,2)\n/*!\n    \\deprecated\n\n    Constructs a message box with a \\a title, a \\a text, an \\a icon,\n    and up to three buttons.\n\n    The \\a icon must be one of the following:\n    \\list\n    \\li QMessageBox::NoIcon\n    \\li QMessageBox::Question\n    \\li QMessageBox::Information\n    \\li QMessageBox::Warning\n    \\li QMessageBox::Critical\n    \\endlist\n\n    Each button, \\a button0, \\a button1 and \\a button2, can have one\n    of the following values:\n    \\list\n    \\li QMessageBox::NoButton\n    \\li QMessageBox::Ok\n    \\li QMessageBox::Cancel\n    \\li QMessageBox::Yes\n    \\li QMessageBox::No\n    \\li QMessageBox::Abort\n    \\li QMessageBox::Retry\n    \\li QMessageBox::Ignore\n    \\li QMessageBox::YesAll\n    \\li QMessageBox::NoAll\n    \\endlist\n\n    Use QMessageBox::NoButton for the later parameters to have fewer\n    than three buttons in your message box. If you don't specify any\n    buttons at all, QMessageBox will provide an Ok button.\n\n    One of the buttons can be OR-ed with the QMessageBox::Default\n    flag to make it the default button (clicked when Enter is\n    pressed).\n\n    One of the buttons can be OR-ed with the QMessageBox::Escape flag\n    to make it the cancel or close button (clicked when \\uicontrol Esc is\n    pressed).\n\n    \\snippet dialogs/dialogs.cpp 2\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n    The \\a parent and \\a f arguments are passed to\n    the QDialog constructor.\n\n    \\sa setWindowTitle(), setText(), setIcon()\n*/\nQMessageBox::QMessageBox(const QString &title, const QString &text, Icon icon,\n                         int button0, int button1, int button2, QWidget *parent,\n                         Qt::WindowFlags f)\n    : QDialog(*new QMessageBoxPrivate, parent,\n              f /*| Qt::MSWindowsFixedSizeDialogHint #### */| Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)\n{\n    Q_D(QMessageBox);\n    d->init(title, text);\n    setIcon(icon);\n    d->addOldButtons(button0, button1, button2);\n}\n\n/*!\n    \\deprecated [6.2]. Use the overload taking StandardButtons instead.\n\n    Opens an information message box with the given \\a title and the\n    \\a text. The dialog may have up to three buttons. Each of the\n    buttons, \\a button0, \\a button1 and \\a button2 may be set to one\n    of the following values:\n\n    \\list\n    \\li QMessageBox::NoButton\n    \\li QMessageBox::Ok\n    \\li QMessageBox::Cancel\n    \\li QMessageBox::Yes\n    \\li QMessageBox::No\n    \\li QMessageBox::Abort\n    \\li QMessageBox::Retry\n    \\li QMessageBox::Ignore\n    \\li QMessageBox::YesAll\n    \\li QMessageBox::NoAll\n    \\endlist\n\n    If you don't want all three buttons, set the last button, or last\n    two buttons to QMessageBox::NoButton.\n\n    One button can be OR-ed with QMessageBox::Default, and one\n    button can be OR-ed with QMessageBox::Escape.\n\n    Returns the identity (QMessageBox::Ok, or QMessageBox::No, etc.)\n    of the button that was clicked.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n  \\warning Do not delete \\a parent during the execution of the dialog.\n           If you want to do this, you should create the dialog\n           yourself using one of the QMessageBox constructors.\n\n    \\sa question(), warning(), critical()\n*/\nint QMessageBox::information(QWidget *parent, const QString &title, const QString& text,\n                               int button0, int button1, int button2)\n{\n    return QMessageBoxPrivate::showOldMessageBox(parent, Information, title, text,\n                                                   button0, button1, button2);\n}\n\n/*!\n    \\deprecated [6.2] Use the overload taking StandardButtons instead.\n    \\overload\n\n    Displays an information message box with the given \\a title and\n    \\a text, as well as one, two or three buttons. Returns the index\n    of the button that was clicked (0, 1 or 2).\n\n    \\a button0Text is the text of the first button, and is optional.\n    If \\a button0Text is not supplied, \"OK\" (translated) will be\n    used. \\a button1Text is the text of the second button, and is\n    optional. \\a button2Text is the text of the third button, and is\n    optional. \\a defaultButtonNumber (0, 1 or 2) is the index of the\n    default button; pressing Return or Enter is the same as clicking\n    the default button. It defaults to 0 (the first button). \\a\n    escapeButtonNumber is the index of the escape button; pressing\n    \\uicontrol Esc is the same as clicking this button. It defaults to -1;\n    supply 0, 1 or 2 to make pressing \\uicontrol Esc equivalent to clicking\n    the relevant button.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n  \\warning Do not delete \\a parent during the execution of the dialog.\n           If you want to do this, you should create the dialog\n           yourself using one of the QMessageBox constructors.\n\n    \\sa question(), warning(), critical()\n*/\n\nint QMessageBox::information(QWidget *parent, const QString &title, const QString& text,\n                               const QString& button0Text, const QString& button1Text,\n                               const QString& button2Text, int defaultButtonNumber,\n                               int escapeButtonNumber)\n{\n    return QMessageBoxPrivate::showOldMessageBox(parent, Information, title, text,\n                                                   button0Text, button1Text, button2Text,\n                                                   defaultButtonNumber, escapeButtonNumber);\n}\n\n/*!\n    \\deprecated [6.2]. Use the overload taking StandardButtons\n    instead.\n\n    Opens a question message box with the given \\a title and \\a text.\n    The dialog may have up to three buttons. Each of the buttons, \\a\n    button0, \\a button1 and \\a button2 may be set to one of the\n    following values:\n\n    \\list\n    \\li QMessageBox::NoButton\n    \\li QMessageBox::Ok\n    \\li QMessageBox::Cancel\n    \\li QMessageBox::Yes\n    \\li QMessageBox::No\n    \\li QMessageBox::Abort\n    \\li QMessageBox::Retry\n    \\li QMessageBox::Ignore\n    \\li QMessageBox::YesAll\n    \\li QMessageBox::NoAll\n    \\endlist\n\n    If you don't want all three buttons, set the last button, or last\n    two buttons to QMessageBox::NoButton.\n\n    One button can be OR-ed with QMessageBox::Default, and one\n    button can be OR-ed with QMessageBox::Escape.\n\n    Returns the identity (QMessageBox::Yes, or QMessageBox::No, etc.)\n    of the button that was clicked.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n  \\warning Do not delete \\a parent during the execution of the dialog.\n           If you want to do this, you should create the dialog\n           yourself using one of the QMessageBox constructors.\n\n    \\sa information(), warning(), critical()\n*/\nint QMessageBox::question(QWidget *parent, const QString &title, const QString& text,\n                            int button0, int button1, int button2)\n{\n    return QMessageBoxPrivate::showOldMessageBox(parent, Question, title, text,\n                                                   button0, button1, button2);\n}\n\n/*!\n    \\deprecated [6.2]. Use the overload taking StandardButtons instead.\n    \\overload\n\n    Displays a question message box with the given \\a title and \\a\n    text, as well as one, two or three buttons. Returns the index of\n    the button that was clicked (0, 1 or 2).\n\n    \\a button0Text is the text of the first button, and is optional.\n    If \\a button0Text is not supplied, \"OK\" (translated) will be used.\n    \\a button1Text is the text of the second button, and is optional.\n    \\a button2Text is the text of the third button, and is optional.\n    \\a defaultButtonNumber (0, 1 or 2) is the index of the default\n    button; pressing Return or Enter is the same as clicking the\n    default button. It defaults to 0 (the first button). \\a\n    escapeButtonNumber is the index of the Escape button; pressing\n    Escape is the same as clicking this button. It defaults to -1;\n    supply 0, 1 or 2 to make pressing Escape equivalent to clicking\n    the relevant button.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n  \\warning Do not delete \\a parent during the execution of the dialog.\n           If you want to do this, you should create the dialog\n           yourself using one of the QMessageBox constructors.\n\n    \\sa information(), warning(), critical()\n*/\nint QMessageBox::question(QWidget *parent, const QString &title, const QString& text,\n                            const QString& button0Text, const QString& button1Text,\n                            const QString& button2Text, int defaultButtonNumber,\n                            int escapeButtonNumber)\n{\n    return QMessageBoxPrivate::showOldMessageBox(parent, Question, title, text,\n                                                   button0Text, button1Text, button2Text,\n                                                   defaultButtonNumber, escapeButtonNumber);\n}\n\n\n/*!\n    \\deprecated [6.2]. Use the overload taking StandardButtons instead.\n\n    Opens a warning message box with the given \\a title and \\a text.\n    The dialog may have up to three buttons. Each of the button\n    parameters, \\a button0, \\a button1 and \\a button2 may be set to\n    one of the following values:\n\n    \\list\n    \\li QMessageBox::NoButton\n    \\li QMessageBox::Ok\n    \\li QMessageBox::Cancel\n    \\li QMessageBox::Yes\n    \\li QMessageBox::No\n    \\li QMessageBox::Abort\n    \\li QMessageBox::Retry\n    \\li QMessageBox::Ignore\n    \\li QMessageBox::YesAll\n    \\li QMessageBox::NoAll\n    \\endlist\n\n    If you don't want all three buttons, set the last button, or last\n    two buttons to QMessageBox::NoButton.\n\n    One button can be OR-ed with QMessageBox::Default, and one\n    button can be OR-ed with QMessageBox::Escape.\n\n    Returns the identity (QMessageBox::Ok or QMessageBox::No or ...)\n    of the button that was clicked.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n  \\warning Do not delete \\a parent during the execution of the dialog.\n           If you want to do this, you should create the dialog\n           yourself using one of the QMessageBox constructors.\n\n    \\sa information(), question(), critical()\n*/\nint QMessageBox::warning(QWidget *parent, const QString &title, const QString& text,\n                           int button0, int button1, int button2)\n{\n    return QMessageBoxPrivate::showOldMessageBox(parent, Warning, title, text,\n                                                   button0, button1, button2);\n}\n\n/*!\n    \\deprecated [6.2]. Use the overload taking StandardButtons instead.\n    \\overload\n\n    Displays a warning message box with the given \\a title and \\a\n    text, as well as one, two, or three buttons. Returns the number\n    of the button that was clicked (0, 1, or 2).\n\n    \\a button0Text is the text of the first button, and is optional.\n    If \\a button0Text is not supplied, \"OK\" (translated) will be used.\n    \\a button1Text is the text of the second button, and is optional,\n    and \\a button2Text is the text of the third button, and is\n    optional. \\a defaultButtonNumber (0, 1 or 2) is the index of the\n    default button; pressing Return or Enter is the same as clicking\n    the default button. It defaults to 0 (the first button). \\a\n    escapeButtonNumber is the index of the Escape button; pressing\n    Escape is the same as clicking this button. It defaults to -1;\n    supply 0, 1, or 2 to make pressing Escape equivalent to clicking\n    the relevant button.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n  \\warning Do not delete \\a parent during the execution of the dialog.\n           If you want to do this, you should create the dialog\n           yourself using one of the QMessageBox constructors.\n\n    \\sa information(), question(), critical()\n*/\nint QMessageBox::warning(QWidget *parent, const QString &title, const QString& text,\n                           const QString& button0Text, const QString& button1Text,\n                           const QString& button2Text, int defaultButtonNumber,\n                           int escapeButtonNumber)\n{\n    return QMessageBoxPrivate::showOldMessageBox(parent, Warning, title, text,\n                                                   button0Text, button1Text, button2Text,\n                                                   defaultButtonNumber, escapeButtonNumber);\n}\n\n/*!\n    \\deprecated [6.2]. Use the overload taking StandardButtons instead.\n\n    Opens a critical message box with the given \\a title and \\a text.\n    The dialog may have up to three buttons. Each of the button\n    parameters, \\a button0, \\a button1 and \\a button2 may be set to\n    one of the following values:\n\n    \\list\n    \\li QMessageBox::NoButton\n    \\li QMessageBox::Ok\n    \\li QMessageBox::Cancel\n    \\li QMessageBox::Yes\n    \\li QMessageBox::No\n    \\li QMessageBox::Abort\n    \\li QMessageBox::Retry\n    \\li QMessageBox::Ignore\n    \\li QMessageBox::YesAll\n    \\li QMessageBox::NoAll\n    \\endlist\n\n    If you don't want all three buttons, set the last button, or last\n    two buttons to QMessageBox::NoButton.\n\n    One button can be OR-ed with QMessageBox::Default, and one\n    button can be OR-ed with QMessageBox::Escape.\n\n    Returns the identity (QMessageBox::Ok, or QMessageBox::No, etc.)\n    of the button that was clicked.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n  \\warning Do not delete \\a parent during the execution of the dialog.\n           If you want to do this, you should create the dialog\n           yourself using one of the QMessageBox constructors.\n\n    \\sa information(), question(), warning()\n*/\n\nint QMessageBox::critical(QWidget *parent, const QString &title, const QString& text,\n                          int button0, int button1, int button2)\n{\n    return QMessageBoxPrivate::showOldMessageBox(parent, Critical, title, text,\n                                                 button0, button1, button2);\n}\n\n/*!\n    \\deprecated [6.2]. Use the overload taking StandardButtons instead.\n    \\overload\n\n    Displays a critical error message box with the given \\a title and\n    \\a text, as well as one, two, or three buttons. Returns the\n    number of the button that was clicked (0, 1 or 2).\n\n    \\a button0Text is the text of the first button, and is optional.\n    If \\a button0Text is not supplied, \"OK\" (translated) will be used.\n    \\a button1Text is the text of the second button, and is optional,\n    and \\a button2Text is the text of the third button, and is\n    optional. \\a defaultButtonNumber (0, 1 or 2) is the index of the\n    default button; pressing Return or Enter is the same as clicking\n    the default button. It defaults to 0 (the first button). \\a\n    escapeButtonNumber is the index of the Escape button; pressing\n    Escape is the same as clicking this button. It defaults to -1;\n    supply 0, 1, or 2 to make pressing Escape equivalent to clicking\n    the relevant button.\n\n    The message box is an \\l{Qt::ApplicationModal} {application modal}\n    dialog box.\n\n  \\warning Do not delete \\a parent during the execution of the dialog.\n           If you want to do this, you should create the dialog\n           yourself using one of the QMessageBox constructors.\n\n    \\sa information(), question(), warning()\n*/\nint QMessageBox::critical(QWidget *parent, const QString &title, const QString& text,\n                            const QString& button0Text, const QString& button1Text,\n                            const QString& button2Text, int defaultButtonNumber,\n                            int escapeButtonNumber)\n{\n    return QMessageBoxPrivate::showOldMessageBox(parent, Critical, title, text,\n                                                   button0Text, button1Text, button2Text,\n                                                   defaultButtonNumber, escapeButtonNumber);\n}\n\n\n/*!\n    \\deprecated [6.2]\n\n    Returns the text of the message box button \\a button, or\n    an empty string if the message box does not contain the button.\n\n    Use button() and QPushButton::text() instead.\n*/\nQString QMessageBox::buttonText(int button) const\n{\n    Q_D(const QMessageBox);\n\n    if (QAbstractButton *abstractButton = d->abstractButtonForId(button)) {\n        return abstractButton->text();\n    } else if (d->buttonBox->buttons().isEmpty() && (button == Ok || button == Old_Ok)) {\n        // for compatibility with Qt 4.0/4.1\n        return QDialogButtonBox::tr(\"OK\");\n    }\n    return QString();\n}\n\n/*!\n    \\deprecated [6.2]\n\n    Sets the text of the message box button \\a button to \\a text.\n    Setting the text of a button that is not in the message box is\n    silently ignored.\n\n    Use addButton() instead.\n*/\nvoid QMessageBox::setButtonText(int button, const QString &text)\n{\n    Q_D(QMessageBox);\n    if (QAbstractButton *abstractButton = d->abstractButtonForId(button)) {\n        abstractButton->setText(text);\n    } else if (d->buttonBox->buttons().isEmpty() && (button == Ok || button == Old_Ok)) {\n        // for compatibility with Qt 4.0/4.1\n        addButton(QMessageBox::Ok)->setText(text);\n    }\n}\n#endif // QT_DEPRECATED_SINCE(6,2)\n\n\n#if QT_CONFIG(textedit)\n/*!\n  \\property QMessageBox::detailedText\n  \\brief the text to be displayed in the details area.\n\n  The text will be interpreted as a plain text.\n\n  By default, this property contains an empty string.\n\n  \\sa QMessageBox::text, QMessageBox::informativeText\n*/\nQString QMessageBox::detailedText() const\n{\n    Q_D(const QMessageBox);\n    return d->detailsText ? d->detailsText->text() : QString();\n}\n\nvoid QMessageBox::setDetailedText(const QString &text)\n{\n    Q_D(QMessageBox);\n    if (text.isEmpty()) {\n        if (d->detailsText) {\n            d->detailsText->hide();\n            d->detailsText->deleteLater();\n        }\n        d->detailsText = nullptr;\n        removeButton(d->detailsButton);\n        if (d->detailsButton) {\n            d->detailsButton->hide();\n            d->detailsButton->deleteLater();\n        }\n        d->detailsButton = nullptr;\n    } else {\n        if (!d->detailsText) {\n            d->detailsText = new QMessageBoxDetailsText(this);\n            d->detailsText->hide();\n        }\n        if (!d->detailsButton) {\n            const bool autoAddOkButton = d->autoAddOkButton; // QTBUG-39334, addButton() clears the flag.\n            d->detailsButton = new DetailButton(this);\n            addButton(d->detailsButton, QMessageBox::ActionRole);\n            d->autoAddOkButton = autoAddOkButton;\n        }\n        d->detailsText->setText(text);\n    }\n    d->setupLayout();\n}\n#endif // QT_CONFIG(textedit)\n\n/*!\n  \\property QMessageBox::informativeText\n\n  \\brief the informative text that provides a fuller description for\n  the message\n\n  Informative text can be used to expand upon the text() to give more\n  information to the user, for example describing the consequences of\n  the situation, or suggestion alternative solutions.\n\n  The text will be interpreted either as a plain text or as rich text,\n  depending on the text format setting (\\l QMessageBox::textFormat).\n  The default setting is Qt::AutoText, i.e., the message box will try\n  to auto-detect the format of the text.\n\n  By default, this property contains an empty string.\n\n  \\sa textFormat, QMessageBox::text, QMessageBox::detailedText\n*/\nQString QMessageBox::informativeText() const\n{\n    Q_D(const QMessageBox);\n    return d->informativeLabel ? d->informativeLabel->text() : QString();\n}\n\nvoid QMessageBox::setInformativeText(const QString &text)\n{\n    Q_D(QMessageBox);\n    if (text.isEmpty()) {\n        if (d->informativeLabel) {\n            d->informativeLabel->hide();\n            d->informativeLabel->deleteLater();\n        }\n        d->informativeLabel = nullptr;\n    } else {\n        if (!d->informativeLabel) {\n            QLabel *label = new QLabel;\n            label->setObjectName(\"qt_msgbox_informativelabel\"_L1);\n            label->setTextInteractionFlags(Qt::TextInteractionFlags(style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, nullptr, this)));\n            label->setAlignment(Qt::AlignTop | Qt::AlignLeft);\n            label->setOpenExternalLinks(true);\n#ifdef Q_OS_MAC\n            // apply a smaller font the information label on the mac\n            label->setFont(qt_app_fonts_hash()->value(\"QTipLabel\"));\n#endif\n            label->setWordWrap(true);\n            label->setTextFormat(d->label->textFormat());\n            d->informativeLabel = label;\n        }\n        d->informativeLabel->setText(text);\n    }\n    d->setupLayout();\n}\n\n/*!\n    This function shadows QWidget::setWindowTitle().\n\n    Sets the title of the message box to \\a title. On \\macos,\n    the window title is ignored (as required by the \\macos\n    Guidelines).\n*/\nvoid QMessageBox::setWindowTitle(const QString &title)\n{\n    // Message boxes on the mac do not have a title\n#ifndef Q_OS_MAC\n    QDialog::setWindowTitle(title);\n#else\n    Q_UNUSED(title);\n#endif\n}\n\n\n/*!\n    This function shadows QWidget::setWindowModality().\n\n    Sets the modality of the message box to \\a windowModality.\n\n    On \\macos, if the modality is set to Qt::WindowModal and the message box\n    has a parent, then the message box will be a Qt::Sheet, otherwise the\n    message box will be a standard dialog.\n*/\nvoid QMessageBox::setWindowModality(Qt::WindowModality windowModality)\n{\n    QDialog::setWindowModality(windowModality);\n\n    if (parentWidget() && windowModality == Qt::WindowModal)\n        setParent(parentWidget(), Qt::Sheet);\n    else\n        setParent(parentWidget(), Qt::Dialog);\n    setDefaultButton(d_func()->defaultButton);\n}\n\n\nQPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb)\n{\n    QStyle *style = mb ? mb->style() : QApplication::style();\n    int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, nullptr, mb);\n    QIcon tmpIcon;\n    switch (icon) {\n    case QMessageBox::Information:\n        tmpIcon = style->standardIcon(QStyle::SP_MessageBoxInformation, nullptr, mb);\n        break;\n    case QMessageBox::Warning:\n        tmpIcon = style->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, mb);\n        break;\n    case QMessageBox::Critical:\n        tmpIcon = style->standardIcon(QStyle::SP_MessageBoxCritical, nullptr, mb);\n        break;\n    case QMessageBox::Question:\n        tmpIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, mb);\n        break;\n    default:\n        break;\n    }\n    if (!tmpIcon.isNull()) {\n        qreal dpr = mb ? mb->devicePixelRatio() : qApp->devicePixelRatio();\n        return tmpIcon.pixmap(QSize(iconSize, iconSize), dpr);\n    }\n    return QPixmap();\n}\n\nvoid QMessageBoxPrivate::initHelper(QPlatformDialogHelper *h)\n{\n    auto *messageDialogHelper = static_cast<QPlatformMessageDialogHelper *>(h);\n    QObjectPrivate::connect(messageDialogHelper, &QPlatformMessageDialogHelper::clicked,\n                            this, &QMessageBoxPrivate::helperClicked);\n    // Forward state via lambda, so that we can handle addition and removal\n    // of checkbox via setCheckBox() after initializing helper.\n    QObject::connect(messageDialogHelper, &QPlatformMessageDialogHelper::checkBoxStateChanged,\n        q_ptr, [this](Qt::CheckState state) {\n            if (checkbox)\n                checkbox->setCheckState(state);\n        }\n    );\n    messageDialogHelper->setOptions(options);\n}\n\nstatic QMessageDialogOptions::StandardIcon helperIcon(QMessageBox::Icon i)\n{\n    switch (i) {\n    case QMessageBox::NoIcon:\n        return QMessageDialogOptions::NoIcon;\n    case QMessageBox::Information:\n        return QMessageDialogOptions::Information;\n    case QMessageBox::Warning:\n        return QMessageDialogOptions::Warning;\n    case QMessageBox::Critical:\n        return QMessageDialogOptions::Critical;\n    case QMessageBox::Question:\n        return QMessageDialogOptions::Question;\n    }\n    return QMessageDialogOptions::NoIcon;\n}\n\nstatic QPlatformDialogHelper::StandardButtons helperStandardButtons(QMessageBox * q)\n{\n    QPlatformDialogHelper::StandardButtons buttons(int(q->standardButtons()));\n    return buttons;\n}\n\nbool QMessageBoxPrivate::canBeNativeDialog() const\n{\n    // Don't use Q_Q here! This function is called from ~QDialog,\n    // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).\n    const QDialog * const q = static_cast<const QMessageBox*>(q_ptr);\n    if (nativeDialogInUse)\n        return true;\n    if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)\n        || q->testAttribute(Qt::WA_DontShowOnScreen)\n        || q->testAttribute(Qt::WA_StyleSheet)\n        || (options->options() & QMessageDialogOptions::Option::DontUseNativeDialog)) {\n        return false;\n    }\n\n    if (strcmp(QMessageBox::staticMetaObject.className(), q->metaObject()->className()) != 0)\n        return false;\n\n#if QT_CONFIG(menu)\n    for (auto *customButton : buttonBox->buttons()) {\n        if (QPushButton *pushButton = qobject_cast<QPushButton *>(customButton)) {\n            // We can't support buttons with menus in native dialogs (yet)\n            if (pushButton->menu())\n                return false;\n        }\n    }\n#endif\n\n    return QDialogPrivate::canBeNativeDialog();\n}\n\nvoid QMessageBoxPrivate::helperPrepareShow(QPlatformDialogHelper *)\n{\n    Q_Q(QMessageBox);\n    options->setWindowTitle(q->windowTitle());\n    options->setText(q->text());\n    options->setInformativeText(q->informativeText());\n#if QT_CONFIG(textedit)\n    options->setDetailedText(q->detailedText());\n#endif\n    options->setStandardIcon(helperIcon(q->icon()));\n    options->setIconPixmap(q->iconPixmap());\n\n    // Clear up front, since we might have prepared earlier\n    options->clearCustomButtons();\n\n    // Add standard buttons and resolve default/escape button\n    auto standardButtons = helperStandardButtons(q);\n    for (int button = QDialogButtonBox::StandardButton::FirstButton;\n             button <= QDialogButtonBox::StandardButton::LastButton; button <<= 1) {\n        auto *standardButton = buttonBox->button(QDialogButtonBox::StandardButton(button));\n        if (!standardButton)\n            continue;\n\n        if (auto *platformTheme = QGuiApplicationPrivate::platformTheme()) {\n            if (standardButton->text() != platformTheme->standardButtonText(button)) {\n                // The standard button has been customized, so add it as\n                // a custom button instead.\n                const auto buttonRole = buttonBox->buttonRole(standardButton);\n                options->addButton(standardButton->text(),\n                    static_cast<QPlatformDialogHelper::ButtonRole>(buttonRole),\n                    standardButton, button);\n                standardButtons &= ~QPlatformDialogHelper::StandardButton(button);\n            }\n        }\n\n        if (standardButton == defaultButton)\n            options->setDefaultButton(button);\n        else if (standardButton == detectedEscapeButton)\n            options->setEscapeButton(button);\n    }\n    options->setStandardButtons(standardButtons);\n\n    // Add custom buttons and resolve default/escape button\n    for (auto *customButton : customButtonList) {\n        // Unless it's the details button, since we don't do any\n        // plumbing for the button's action in that case.\n        if (customButton == detailsButton)\n            continue;\n\n        const auto buttonRole = buttonBox->buttonRole(customButton);\n        const int buttonId = options->addButton(customButton->text(),\n            static_cast<QPlatformDialogHelper::ButtonRole>(buttonRole),\n            customButton);\n\n        if (customButton == defaultButton)\n            options->setDefaultButton(buttonId);\n        else if (customButton == detectedEscapeButton)\n            options->setEscapeButton(buttonId);\n    }\n\n    if (checkbox)\n        options->setCheckBox(checkbox->text(), checkbox->checkState());\n}\n\nvoid qRequireVersion(int argc, char *argv[], QAnyStringView req)\n{\n    const auto required = QVersionNumber::fromString(req).normalized();\n    const auto current = QVersionNumber::fromString(qVersion()).normalized();\n    if (current >= required)\n        return;\n    std::optional<QApplication> application;\n    if (!qApp)\n        application.emplace(argc, argv);\n    const QString message = QApplication::tr(\"Application \\\"%1\\\" requires Qt %2, found Qt %3.\")\n                                    .arg(qAppName(), required.toString(), current.toString());\n    QMessageBox::critical(nullptr, QApplication::tr(\"Incompatible Qt Library Error\"),\n                          message, QMessageBox::Abort);\n    qFatal(\"%ls\", qUtf16Printable(message));\n}\n\n#if QT_DEPRECATED_SINCE(6,2)\n/*!\n    \\deprecated [6.2]\n\n    Returns the pixmap used for a standard icon. This allows the\n    pixmaps to be used in more complex message boxes. \\a icon\n    specifies the required icon, e.g. QMessageBox::Question,\n    QMessageBox::Information, QMessageBox::Warning or\n    QMessageBox::Critical.\n\n    Call QStyle::standardIcon() with QStyle::SP_MessageBoxInformation etc.\n    instead.\n*/\n\nQPixmap QMessageBox::standardIcon(Icon icon)\n{\n    return QMessageBoxPrivate::standardIcon(icon, nullptr);\n}\n#endif\n\n/*!\n    \\typedef QMessageBox::Button\n    \\deprecated\n\n    Use QMessageBox::StandardButton instead.\n*/\n\n/*!\n    \\fn int QMessageBox::information(QWidget *parent, const QString &title,\n                                     const QString& text, StandardButton button0,\n                                     StandardButton button1)\n    \\fn int QMessageBox::warning(QWidget *parent, const QString &title,\n                                 const QString& text, StandardButton button0,\n                                 StandardButton button1)\n    \\fn int QMessageBox::critical(QWidget *parent, const QString &title,\n                                  const QString& text, StandardButton button0,\n                                  StandardButton button1)\n    \\fn int QMessageBox::question(QWidget *parent, const QString &title,\n                                  const QString& text, StandardButton button0,\n                                  StandardButton button1)\n    \\internal\n\n    ### Needed for Qt 4 source compatibility\n*/\n\n/*!\n  \\fn int QMessageBox::exec()\n\n  Shows the message box as a \\l{QDialog#Modal Dialogs}{modal dialog},\n  blocking until the user closes it.\n\n  When using a QMessageBox with standard buttons, this function returns a\n  \\l StandardButton value indicating the standard button that was clicked.\n  When using QMessageBox with custom buttons, this function returns an\n  opaque value; use clickedButton() to determine which button was clicked.\n\n  \\note The result() function returns also \\l StandardButton value instead\n  of \\l QDialog::DialogCode.\n\n  Users cannot interact with any other window in the same\n  application until they close the dialog, either by clicking a\n  button or by using a mechanism provided by the window system.\n\n  \\sa show(), result()\n*/\n\n/*!\n    \\macro QT_REQUIRE_VERSION(int argc, char **argv, const char *version)\n    \\relates QMessageBox\n\n    This macro can be used to ensure that the application is run\n    with a recent enough version of Qt. This is especially useful\n    if your application depends on a specific bug fix introduced in a\n    bug-fix release (for example, 6.1.2).\n\n    The \\a argc and \\a argv parameters are the \\c main() function's\n    \\c argc and \\c argv parameters. The \\a version parameter is a\n    string literal that specifies which version of Qt the application\n    requires (for example, \"6.1.2\").\n\n    Example:\n\n    \\snippet code/src_gui_dialogs_qmessagebox.cpp 4\n*/\n\nQT_END_NAMESPACE\n\n#include \"moc_qmessagebox.cpp\"\n#include \"qmessagebox.moc\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qpagesetupdialog.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qpagesetupdialog.h\"\n#include <private/qpagesetupdialog_p.h>\n\n#include <QtPrintSupport/qprinter.h>\n\nQT_BEGIN_NAMESPACE\n\n/*!\n    \\class QPageSetupDialog\n\n    \\brief The QPageSetupDialog class provides a configuration dialog\n    for the page-related options on a printer.\n\n    \\ingroup standard-dialogs\n    \\ingroup printing\n    \\inmodule QtPrintSupport\n\n    On Windows and \\macos the page setup dialog is implemented using\n    the native page setup dialogs.\n\n    Note that on Windows and \\macos custom paper sizes won't be\n    reflected in the native page setup dialogs. Additionally, custom\n    page margins set on a QPrinter won't show in the native \\macos\n    page setup dialog.\n\n    \\sa QPrinter, QPrintDialog\n*/\n\n\n/*!\n    \\fn QPageSetupDialog::QPageSetupDialog(QPrinter *printer, QWidget *parent)\n\n    Constructs a page setup dialog that configures \\a printer with \\a\n    parent as the parent widget.\n*/\n\n/*!\n    \\fn QPageSetupDialog::~QPageSetupDialog()\n\n    Destroys the page setup dialog.\n*/\n\n/*!\n    \\since 4.5\n\n    \\fn QPageSetupDialog::QPageSetupDialog(QWidget *parent)\n\n    Constructs a page setup dialog that configures a default-constructed\n    QPrinter with \\a parent as the parent widget.\n\n    \\sa printer()\n*/\n\n/*!\n    \\fn QPrinter *QPageSetupDialog::printer()\n\n    Returns the printer that was passed to the QPageSetupDialog\n    constructor.\n*/\n\nQPageSetupDialogPrivate::QPageSetupDialogPrivate(QPrinter *prntr) : printer(nullptr), ownsPrinter(false)\n{\n    setPrinter(prntr);\n}\n\nvoid QPageSetupDialogPrivate::setPrinter(QPrinter *newPrinter)\n{\n    if (printer && ownsPrinter)\n        delete printer;\n\n    if (newPrinter) {\n        printer = newPrinter;\n        ownsPrinter = false;\n    } else {\n        printer = new QPrinter;\n        ownsPrinter = true;\n    }\n    if (printer->outputFormat() != QPrinter::NativeFormat)\n        qWarning(\"QPageSetupDialog: Cannot be used on non-native printers\");\n}\n\n/*!\n    \\overload\n    \\since 4.5\n\n    Opens the dialog and connects its accepted() signal to the slot specified\n    by \\a receiver and \\a member.\n\n    The signal will be disconnected from the slot when the dialog is closed.\n*/\nvoid QPageSetupDialog::open(QObject *receiver, const char *member)\n{\n    Q_D(QPageSetupDialog);\n    connect(this, SIGNAL(accepted()), receiver, member);\n    d->receiverToDisconnectOnClose = receiver;\n    d->memberToDisconnectOnClose = member;\n    QDialog::open();\n}\n\n#if defined(Q_OS_MACOS) || defined(Q_OS_WIN)\n/*! \\fn void QPageSetupDialog::setVisible(bool visible)\n    \\reimp\n*/\n#endif\n\nQPageSetupDialog::~QPageSetupDialog()\n{\n    Q_D(QPageSetupDialog);\n    if (d->ownsPrinter)\n        delete d->printer;\n}\n\nQPrinter *QPageSetupDialog::printer()\n{\n    Q_D(QPageSetupDialog);\n    return d->printer;\n}\n\n/*!\n    \\fn int QPageSetupDialog::exec()\n\n    This virtual function is called to pop up the dialog. It must be\n    reimplemented in subclasses.\n*/\n\n/*!\n    \\reimp\n*/\nvoid QPageSetupDialog::done(int result)\n{\n    Q_D(QPageSetupDialog);\n    QDialog::done(result);\n    if (d->receiverToDisconnectOnClose) {\n        disconnect(this, SIGNAL(accepted()),\n                   d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);\n        d->receiverToDisconnectOnClose = nullptr;\n    }\n    d->memberToDisconnectOnClose.clear();\n\n}\n\nQT_END_NAMESPACE\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qpagesetupdialog_unix.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qpagesetupdialog.h\"\n\n#include \"qpagesetupdialog_unix_p.h\"\n\n#include <private/qpagesetupdialog_p.h>\n#include <private/qprintdevice_p.h>\n#if QT_CONFIG(cups)\n#include <private/qcups_p.h>\n#endif\n\n#include \"qpainter.h\"\n#include \"qprintdialog.h\"\n#include \"qstringconverter.h\"\n#include \"qdialogbuttonbox.h\"\n#include <ui_qpagesetupwidget.h>\n\n#include <QtPrintSupport/qprinter.h>\n\n#include <qpa/qplatformprintplugin.h>\n#include <qpa/qplatformprintersupport.h>\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\nextern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits);\n\n// Disabled until we have support for papersources on unix\n// #define PSD_ENABLE_PAPERSOURCE\n\n#ifdef PSD_ENABLE_PAPERSOURCE\nstatic const char *paperSourceNames[] = {\n    \"Only One\",\n    \"Lower\",\n    \"Middle\",\n    \"Manual\",\n    \"Envelope\",\n    \"Envelope manual\",\n    \"Auto\",\n    \"Tractor\",\n    \"Small format\",\n    \"Large format\",\n    \"Large capacity\",\n    \"Cassette\",\n    \"Form source\",\n    0\n};\n\nstruct PaperSourceNames\n{\n    PaperSourceNames(const char *nam, QPrinter::PaperSource ps)\n        : paperSource(ps), name(nam) {}\n    QPrinter::PaperSource paperSource;\n    const char *name;\n};\n#endif\n\n\n// QPagePreview\n// - Private widget to display preview of page layout\n// - Embedded in QPageSetupWidget\n\nclass QPagePreview : public QWidget\n{\npublic:\n    QPagePreview(QWidget *parent) : QWidget(parent)\n    {\n        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);\n        setMinimumSize(50, 50);\n    }\n\n    void setPageLayout(const QPageLayout &layout)\n    {\n        m_pageLayout = layout;\n        update();\n    }\n\n    void setPagePreviewLayout(int columns, int rows)\n    {\n      m_pagePreviewColumns = columns;\n      m_pagePreviewRows = rows;\n      update();\n    }\n\nprotected:\n    void paintEvent(QPaintEvent *) override\n    {\n        QSize pageSize = m_pageLayout.fullRectPoints().size();\n        QSizeF scaledSize = pageSize.scaled(width() - 10, height() - 10, Qt::KeepAspectRatio);\n        QRect pageRect = QRect(QPoint(0,0), scaledSize.toSize());\n        pageRect.moveCenter(rect().center());\n        qreal width_factor = scaledSize.width() / pageSize.width();\n        qreal height_factor = scaledSize.height() / pageSize.height();\n        QMarginsF margins = m_pageLayout.margins(QPageLayout::Point);\n        int left = qRound(margins.left() * width_factor);\n        int top = qRound(margins.top() * height_factor);\n        int right = qRound(margins.right() * width_factor);\n        int bottom = qRound(margins.bottom() * height_factor);\n        QRect marginRect(pageRect.x() + left, pageRect.y() + top,\n                         pageRect.width() - (left + right + 1), pageRect.height() - (top + bottom + 1));\n\n        QPainter p(this);\n        QColor shadow(palette().mid().color());\n        for (int i=1; i<6; ++i) {\n            shadow.setAlpha(180-i*30);\n            QRect offset(pageRect.adjusted(i, i, i, i));\n            p.setPen(shadow);\n            p.drawLine(offset.left(), offset.bottom(), offset.right(), offset.bottom());\n            p.drawLine(offset.right(), offset.top(), offset.right(), offset.bottom()-1);\n        }\n        p.fillRect(pageRect, palette().light());\n\n        if (marginRect.isValid()) {\n            p.setPen(QPen(palette().color(QPalette::Dark), 0, Qt::DotLine));\n            p.drawRect(marginRect);\n\n            marginRect.adjust(2, 2, -1, -1);\n            p.setClipRect(marginRect);\n            QFont font;\n            font.setPointSizeF(font.pointSizeF()*0.25);\n            p.setFont(font);\n            p.setPen(palette().color(QPalette::Dark));\n            QString text(\"Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.\"_L1);\n            for (int i=0; i<3; ++i)\n                text += text;\n\n            const int spacing = pageRect.width() * 0.1;\n            const int textWidth = (marginRect.width() - (spacing * (m_pagePreviewColumns-1))) / m_pagePreviewColumns;\n            const int textHeight = (marginRect.height() - (spacing * (m_pagePreviewRows-1))) / m_pagePreviewRows;\n\n            for (int x = 0 ; x < m_pagePreviewColumns; ++x) {\n                for (int y = 0 ; y < m_pagePreviewRows; ++y) {\n                    QRect textRect(marginRect.left() + x * (textWidth + spacing),\n                                   marginRect.top() + y * (textHeight + spacing),\n                                   textWidth, textHeight);\n                    p.drawText(textRect, Qt::TextWordWrap|Qt::AlignVCenter, text);\n                }\n            }\n        }\n    }\n\nprivate:\n    // Page Layout\n    QPageLayout m_pageLayout;\n    // Pages Per Sheet / n-up layout\n    int m_pagePreviewColumns, m_pagePreviewRows;\n};\n\n\n// QUnixPageSetupDialogPrivate\n// - Linux / Cups implementation of QPageSetupDialogPrivate\n// - Embeds QPageSetupWidget\n\nclass QUnixPageSetupDialogPrivate : public QPageSetupDialogPrivate\n{\n    Q_DECLARE_PUBLIC(QPageSetupDialog)\n\npublic:\n    QUnixPageSetupDialogPrivate(QPrinter *printer);\n    ~QUnixPageSetupDialogPrivate();\n    void init();\n\n    QPageSetupWidget *widget;\n};\n\nQUnixPageSetupDialogPrivate::QUnixPageSetupDialogPrivate(QPrinter *printer) : QPageSetupDialogPrivate(printer)\n{\n}\n\nQUnixPageSetupDialogPrivate::~QUnixPageSetupDialogPrivate()\n{\n}\n\nvoid QUnixPageSetupDialogPrivate::init()\n{\n    Q_Q(QPageSetupDialog);\n\n    widget = new QPageSetupWidget(q);\n    widget->setPrinter(printer, nullptr, printer->outputFormat(), printer->printerName());\n\n    QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok\n                                                     | QDialogButtonBox::Cancel,\n                                                     Qt::Horizontal, q);\n    QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));\n    QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));\n\n    QVBoxLayout *lay = new QVBoxLayout(q);\n    lay->addWidget(widget);\n    lay->addWidget(buttons);\n}\n\n// QPageSetupWidget\n// - Private widget implementation for Linux / CUPS\n// - Embeds QPagePreview\n// - TODO Could be made public as a stand-alone widget?\n\nQPageSetupWidget::QPageSetupWidget(QWidget *parent)\n    : QWidget(parent),\n      m_pagePreview(nullptr),\n      m_printer(nullptr),\n      m_printDevice(nullptr),\n#if QT_CONFIG(cups)\n      m_pageSizePpdOption(nullptr),\n#endif\n      m_outputFormat(QPrinter::PdfFormat),\n      m_units(QPageLayout::Point),\n      m_savedUnits(QPageLayout::Point),\n      m_savedPagesPerSheet(-1),\n      m_savedPagesPerSheetLayout(-1),\n      m_blockSignals(false),\n      m_realCustomPageSizeIndex(-1)\n{\n    m_ui.setupUi(this);\n\n    QVBoxLayout *lay = new QVBoxLayout(m_ui.preview);\n    m_pagePreview = new QPagePreview(m_ui.preview);\n    m_pagePreview->setPagePreviewLayout(1, 1);\n\n    lay->addWidget(m_pagePreview);\n\n    setAttribute(Qt::WA_WState_Polished, false);\n\n#ifdef PSD_ENABLE_PAPERSOURCE\n    for (int i=0; paperSourceNames[i]; ++i)\n        m_ui.paperSource->insertItem(paperSourceNames[i]);\n#else\n    m_ui.paperSourceLabel->setVisible(false);\n    m_ui.paperSource->setVisible(false);\n#endif\n\n    m_ui.reverseLandscape->setVisible(false);\n    m_ui.reversePortrait->setVisible(false);\n\n    initUnits();\n    initPagesPerSheet();\n\n    connect(m_ui.unitCombo, &QComboBox::activated, this, &QPageSetupWidget::unitChanged);\n\n    connect(m_ui.pageSizeCombo, &QComboBox::currentIndexChanged, this, &QPageSetupWidget::pageSizeChanged);\n    connect(m_ui.pageWidth, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::pageSizeChanged);\n    connect(m_ui.pageHeight, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::pageSizeChanged);\n\n    connect(m_ui.leftMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::leftMarginChanged);\n    connect(m_ui.topMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::topMarginChanged);\n    connect(m_ui.rightMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::rightMarginChanged);\n    connect(m_ui.bottomMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::bottomMarginChanged);\n\n    connect(m_ui.portrait, &QRadioButton::clicked, this, &QPageSetupWidget::pageOrientationChanged);\n    connect(m_ui.landscape, &QRadioButton::clicked, this, &QPageSetupWidget::pageOrientationChanged);\n\n    connect(m_ui.pagesPerSheetCombo, &QComboBox::currentIndexChanged, this, &QPageSetupWidget::pagesPerSheetChanged);\n}\n\n// Init the Units combo box\nvoid QPageSetupWidget::initUnits()\n{\n    m_ui.unitCombo->addItem(tr(\"Millimeters (mm)\"), QVariant::fromValue(QPageLayout::Millimeter));\n    m_ui.unitCombo->addItem(tr(\"Inches (in)\"), QVariant::fromValue(QPageLayout::Inch));\n    m_ui.unitCombo->addItem(tr(\"Points (pt)\"), QVariant::fromValue(QPageLayout::Point));\n    m_ui.unitCombo->addItem(tr(\"Pica (P̸)\"), QVariant::fromValue(QPageLayout::Pica));\n    m_ui.unitCombo->addItem(tr(\"Didot (DD)\"), QVariant::fromValue(QPageLayout::Didot));\n    m_ui.unitCombo->addItem(tr(\"Cicero (CC)\"), QVariant::fromValue(QPageLayout::Cicero));\n\n    // Initially default to locale measurement system, mm if metric, in otherwise\n    m_ui.unitCombo->setCurrentIndex(QLocale().measurementSystem() != QLocale::MetricSystem);\n}\n\n// Init the Pages Per Sheet (n-up) combo boxes if using CUPS\nvoid QPageSetupWidget::initPagesPerSheet()\n{\n#if QT_CONFIG(cups)\n    m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr(\"Left to Right, Top to Bottom\"),\n                                           QVariant::fromValue(QCUPSSupport::LeftToRightTopToBottom));\n    m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr(\"Left to Right, Bottom to Top\"),\n                                           QVariant::fromValue(QCUPSSupport::LeftToRightBottomToTop));\n    m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr(\"Right to Left, Bottom to Top\"),\n                                           QVariant::fromValue(QCUPSSupport::RightToLeftBottomToTop));\n    m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr(\"Right to Left, Top to Bottom\"),\n                                           QVariant::fromValue(QCUPSSupport::RightToLeftTopToBottom));\n    m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr(\"Bottom to Top, Left to Right\"),\n                                           QVariant::fromValue(QCUPSSupport::BottomToTopLeftToRight));\n    m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr(\"Bottom to Top, Right to Left\"),\n                                           QVariant::fromValue(QCUPSSupport::BottomToTopRightToLeft));\n    m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr(\"Top to Bottom, Left to Right\"),\n                                           QVariant::fromValue(QCUPSSupport::TopToBottomLeftToRight));\n    m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr(\"Top to Bottom, Right to Left\"),\n                                           QVariant::fromValue(QCUPSSupport::TopToBottomRightToLeft));\n\n    m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr(\"1 (1x1)\"),\n                                     QVariant::fromValue(QCUPSSupport::OnePagePerSheet));\n    m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr(\"2 (2x1)\"),\n                                     QVariant::fromValue(QCUPSSupport::TwoPagesPerSheet));\n    m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr(\"4 (2x2)\"),\n                                     QVariant::fromValue(QCUPSSupport::FourPagesPerSheet));\n    m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr(\"6 (2x3)\"),\n                                     QVariant::fromValue(QCUPSSupport::SixPagesPerSheet));\n    m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr(\"9 (3x3)\"),\n                                     QVariant::fromValue(QCUPSSupport::NinePagesPerSheet));\n    m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr(\"16 (4x4)\"),\n                                     QVariant::fromValue(QCUPSSupport::SixteenPagesPerSheet));\n\n    // Set to QCUPSSupport::OnePagePerSheet\n    m_ui.pagesPerSheetCombo->setCurrentIndex(0);\n    // Set to QCUPSSupport::LeftToRightTopToBottom\n    m_ui.pagesPerSheetLayoutCombo->setCurrentIndex(0);\n#else\n    // Disable if CUPS wasn't found\n    m_ui.pagesPerSheetButtonGroup->hide();\n#endif\n}\n\nvoid QPageSetupWidget::initPageSizes()\n{\n    m_blockSignals = true;\n\n    m_ui.pageSizeCombo->clear();\n\n    m_realCustomPageSizeIndex = -1;\n\n    if (m_outputFormat == QPrinter::NativeFormat && !m_printerName.isEmpty()) {\n        QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();\n        if (ps) {\n            QPrintDevice printDevice = ps->createPrintDevice(m_printerName);\n            const QPageSize defaultSize = printDevice.defaultPageSize();\n            const auto pageSizes = printDevice.supportedPageSizes();\n            for (const QPageSize &pageSize : pageSizes)\n                m_ui.pageSizeCombo->addItem(pageSize.name(), QVariant::fromValue(pageSize));\n            if (m_ui.pageSizeCombo->count() > 0) {\n                if (printDevice.supportsCustomPageSizes()) {\n                    m_ui.pageSizeCombo->addItem(tr(\"Custom\"));\n                    m_realCustomPageSizeIndex = m_ui.pageSizeCombo->count() - 1;\n                }\n                m_blockSignals = false;\n\n                // If the defaultSize is index 0, setCurrentIndex won't emit the currentIndexChanged\n                // signal; workaround the issue by initially setting the currentIndex to -1\n                m_ui.pageSizeCombo->setCurrentIndex(-1);\n                m_ui.pageSizeCombo->setCurrentIndex(m_ui.pageSizeCombo->findData(QVariant::fromValue(defaultSize)));\n                return;\n            }\n        }\n    }\n\n    // If PdfFormat or no available printer page sizes, populate with all page sizes\n    for (int id = 0; id < QPageSize::LastPageSize; ++id) {\n        if (QPageSize::PageSizeId(id) == QPageSize::Custom) {\n            m_ui.pageSizeCombo->addItem(tr(\"Custom\"));\n            m_realCustomPageSizeIndex = m_ui.pageSizeCombo->count() - 1;\n        } else {\n            QPageSize pageSize = QPageSize(QPageSize::PageSizeId(id));\n            m_ui.pageSizeCombo->addItem(pageSize.name(), QVariant::fromValue(pageSize));\n        }\n    }\n\n    m_blockSignals = false;\n}\n\n// Set the dialog to use the given QPrinter\n// Usually only called on first creation\nvoid QPageSetupWidget::setPrinter(QPrinter *printer, QPrintDevice *printDevice,\n                                  QPrinter::OutputFormat outputFormat, const QString &printerName)\n{\n    m_printer = printer;\n    m_printDevice = printDevice;\n\n#if QT_CONFIG(cups)\n    // find the PageSize cups option\n    m_pageSizePpdOption = m_printDevice ? QCUPSSupport::findPpdOption(\"PageSize\", m_printDevice) : nullptr;\n#endif\n\n    // Initialize the layout to the current QPrinter layout\n    m_pageLayout = m_printer->pageLayout();\n\n    // Assume if margins are Points then is by default, so set to locale default units\n    if (m_pageLayout.units() == QPageLayout::Point) {\n        if (QLocale().measurementSystem() == QLocale::MetricSystem)\n            m_pageLayout.setUnits(QPageLayout::Millimeter);\n        else\n            m_pageLayout.setUnits(QPageLayout::Inch);\n    }\n    m_units = m_pageLayout.units();\n    m_pagePreview->setPageLayout(m_pageLayout);\n\n    m_outputFormat = outputFormat;\n    m_printerName = printerName;\n    initPageSizes();\n    updateWidget();\n    updateSavedValues();\n\n    if (m_ui.pageSizeCombo->currentIndex() == -1) {\n        // This can happen in raw printers that since they don't have a default\n        // page size none will get selected so just default to the first size (A4)\n        m_ui.pageSizeCombo->setCurrentIndex(0);\n    }\n}\n\n// Update the widget with the current settings\n// TODO Break up into more intelligent chunks?\nvoid QPageSetupWidget::updateWidget()\n{\n    m_blockSignals = true;\n\n    QString suffix;\n    switch (m_units) {\n    case QPageLayout::Millimeter:\n        //: Unit 'Millimeter'\n        suffix = tr(\"mm\");\n        break;\n    case QPageLayout::Point:\n        //: Unit 'Points'\n        suffix = tr(\"pt\");\n        break;\n    case QPageLayout::Inch:\n        //: Unit 'Inch'\n        suffix = tr(\"in\");\n        break;\n    case QPageLayout::Pica:\n        //: Unit 'Pica'\n        suffix = tr(\"P̸\");\n        break;\n    case QPageLayout::Didot:\n        //: Unit 'Didot'\n        suffix = tr(\"DD\");\n        break;\n    case QPageLayout::Cicero:\n        //: Unit 'Cicero'\n        suffix = tr(\"CC\");\n        break;\n    }\n\n    m_ui.unitCombo->setCurrentIndex(m_ui.unitCombo->findData(QVariant::fromValue(m_units)));\n\n    const bool isCustom = m_ui.pageSizeCombo->currentIndex() == m_realCustomPageSizeIndex && m_realCustomPageSizeIndex != -1;\n    if (!isCustom)\n        m_ui.pageSizeCombo->setCurrentIndex(m_ui.pageSizeCombo->findData(QVariant::fromValue(m_pageLayout.pageSize())));\n\n    QMarginsF min;\n    QMarginsF max;\n\n    if (m_pageLayout.mode() == QPageLayout::FullPageMode) {\n        min = QMarginsF(0.0, 0.0, 0.0, 0.0);\n        max = QMarginsF(9999.9999, 9999.9999, 9999.9999, 9999.9999);\n    } else {\n        min = m_pageLayout.minimumMargins();\n        max = m_pageLayout.maximumMargins();\n    }\n\n    m_ui.leftMargin->setSuffix(suffix);\n    m_ui.leftMargin->setMinimum(min.left());\n    m_ui.leftMargin->setMaximum(max.left());\n    m_ui.leftMargin->setValue(m_pageLayout.margins().left());\n\n    m_ui.rightMargin->setSuffix(suffix);\n    m_ui.rightMargin->setMinimum(min.right());\n    m_ui.rightMargin->setMaximum(max.right());\n    m_ui.rightMargin->setValue(m_pageLayout.margins().right());\n\n    m_ui.topMargin->setSuffix(suffix);\n    m_ui.topMargin->setMinimum(min.top());\n    m_ui.topMargin->setMaximum(max.top());\n    m_ui.topMargin->setValue(m_pageLayout.margins().top());\n\n    m_ui.bottomMargin->setSuffix(suffix);\n    m_ui.bottomMargin->setMinimum(min.bottom());\n    m_ui.bottomMargin->setMaximum(max.bottom());\n    m_ui.bottomMargin->setValue(m_pageLayout.margins().bottom());\n\n    m_ui.pageWidth->setSuffix(suffix);\n    m_ui.pageWidth->setValue(m_pageLayout.fullRect(m_units).width());\n    m_ui.pageWidth->setEnabled(isCustom);\n    m_ui.widthLabel->setEnabled(isCustom);\n\n    m_ui.pageHeight->setSuffix(suffix);\n    m_ui.pageHeight->setValue(m_pageLayout.fullRect(m_units).height());\n    m_ui.pageHeight->setEnabled(isCustom);\n    m_ui.heightLabel->setEnabled(isCustom);\n\n    m_ui.portrait->setChecked(m_pageLayout.orientation() == QPageLayout::Portrait);\n    m_ui.landscape->setChecked(m_pageLayout.orientation() == QPageLayout::Landscape);\n\n    m_ui.pagesPerSheetButtonGroup->setEnabled(m_outputFormat == QPrinter::NativeFormat);\n\n#ifdef PSD_ENABLE_PAPERSOURCE\n    m_ui.paperSource->setCurrentItem(printer->paperSource());\n#endif\n\n    m_blockSignals = false;\n}\n\n// Set the dialog chosen options on the QPrinter\n// Normally only called when the QPrintDialog or QPageSetupDialog OK button is pressed\nvoid QPageSetupWidget::setupPrinter() const\n{\n    m_printer->setPageLayout(m_pageLayout);\n    m_printer->setPageOrientation(m_pageLayout.orientation());\n#if QT_CONFIG(cups)\n    QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(m_ui.pagesPerSheetCombo->currentData()\n);\n    QCUPSSupport::PagesPerSheetLayout pagesPerSheetLayout = qvariant_cast<QCUPSSupport::PagesPerSheetLayout>(m_ui.pagesPerSheetLayoutCombo->currentData()\n);\n    QCUPSSupport::setPagesPerSheetLayout(m_printer, pagesPerSheet, pagesPerSheetLayout);\n#endif\n#ifdef PSD_ENABLE_PAPERSOURCE\n    m_printer->setPaperSource((QPrinter::PaperSource)m_ui.paperSource->currentIndex());\n#endif\n}\n\nvoid QPageSetupWidget::updateSavedValues()\n{\n    m_savedUnits = m_units;\n    m_savedPageLayout = m_pageLayout;\n    m_savedPagesPerSheet = m_ui.pagesPerSheetCombo->currentIndex();\n    m_savedPagesPerSheetLayout = m_ui.pagesPerSheetLayoutCombo->currentIndex();\n}\n\nvoid QPageSetupWidget::revertToSavedValues()\n{\n    m_units = m_savedUnits;\n    m_pageLayout = m_savedPageLayout;\n    m_pagePreview->setPageLayout(m_pageLayout);\n\n    updateWidget();\n\n    m_ui.pagesPerSheetCombo->setCurrentIndex(m_savedPagesPerSheet);\n    m_ui.pagesPerSheetLayoutCombo->setCurrentIndex(m_savedPagesPerSheetLayout);\n}\n\n#if QT_CONFIG(cups)\nbool QPageSetupWidget::hasPpdConflict() const\n{\n    if (m_pageSizePpdOption) {\n        if (m_pageSizePpdOption->conflicted) {\n            const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr);\n            const int pixmap_size = m_ui.pageSizeCombo->sizeHint().height() * .75;\n            m_ui.pageSizeWarningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));\n        } else {\n            m_ui.pageSizeWarningLabel->setPixmap(QPixmap());\n        }\n        return m_pageSizePpdOption->conflicted;\n    }\n\n    return false;\n}\n#endif\n\n// Updates size/preview after the combobox has been changed.\nvoid QPageSetupWidget::pageSizeChanged()\n{\n    QPageSize pageSize;\n    if (m_ui.pageSizeCombo->currentIndex() != m_realCustomPageSizeIndex) {\n        pageSize = qvariant_cast<QPageSize>(m_ui.pageSizeCombo->currentData());\n\n#if QT_CONFIG(cups)\n        if (m_pageSizePpdOption) {\n            ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(m_printDevice->property(PDPK_PpdFile));\n            QStringDecoder toUtf16(ppd->lang_encoding, QStringDecoder::Flag::Stateless);\n            if (!toUtf16.isValid()) {\n                qWarning() << \"QPrinSupport: Cups uses unsupported encoding\" << ppd->lang_encoding;\n                toUtf16 = QStringDecoder(QStringDecoder::Utf8);\n            }\n            for (int i = 0; i < m_pageSizePpdOption->num_choices; ++i) {\n                const ppd_choice_t *choice = &m_pageSizePpdOption->choices[i];\n                if (toUtf16(choice->text) == m_ui.pageSizeCombo->currentText()) {\n                    const auto values = QStringList{} << QString::fromLatin1(m_pageSizePpdOption->keyword)\n                                                      << QString::fromLatin1(choice->choice);\n                    m_printDevice->setProperty(PDPK_PpdOption, values);\n                    emit ppdOptionChanged();\n                    break;\n                }\n            }\n        }\n#endif\n\n    } else {\n        QSizeF customSize;\n        if (m_pageLayout.orientation() == QPageLayout::Landscape)\n            customSize = QSizeF(m_ui.pageHeight->value(), m_ui.pageWidth->value());\n        else\n            customSize = QSizeF(m_ui.pageWidth->value(), m_ui.pageHeight->value());\n        pageSize = QPageSize(customSize, QPageSize::Unit(m_units));\n\n#if QT_CONFIG(cups)\n        if (m_pageSizePpdOption) {\n            const auto values = QStringList{} << QString::fromLatin1(m_pageSizePpdOption->keyword)\n                                              << QStringLiteral(\"Custom\");\n            m_printDevice->setProperty(PDPK_PpdOption, values);\n            emit ppdOptionChanged();\n        }\n#endif\n    }\n\n    // We always need to update the m_pageSizePpdOption when the page size changes\n    // even if it's from inside updateWidget, so do not move up\n    if (m_blockSignals)\n        return;\n\n    const QMarginsF printable = m_printDevice ? m_printDevice->printableMargins(pageSize, m_pageLayout.orientation(), m_printer->resolution())\n                                              : QMarginsF();\n    m_pageLayout.setPageSize(pageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units()));\n    m_pagePreview->setPageLayout(m_pageLayout);\n\n    updateWidget();\n}\n\nvoid QPageSetupWidget::pageOrientationChanged()\n{\n    if (m_blockSignals)\n        return;\n    m_pageLayout.setOrientation(m_ui.portrait->isChecked() ? QPageLayout::Portrait : QPageLayout::Landscape);\n    m_pagePreview->setPageLayout(m_pageLayout);\n    updateWidget();\n}\n\nvoid QPageSetupWidget::pagesPerSheetChanged()\n{\n#if QT_CONFIG(cups)\n    switch (m_ui.pagesPerSheetCombo->currentData().toInt()) {\n    case QCUPSSupport::OnePagePerSheet:\n        m_pagePreview->setPagePreviewLayout(1, 1);\n        break;\n    case QCUPSSupport::TwoPagesPerSheet:\n        m_pagePreview->setPagePreviewLayout(1, 2);\n        break;\n    case QCUPSSupport::FourPagesPerSheet:\n        m_pagePreview->setPagePreviewLayout(2, 2);\n        break;\n    case QCUPSSupport::SixPagesPerSheet:\n        m_pagePreview->setPagePreviewLayout(3, 2);\n        break;\n    case QCUPSSupport::NinePagesPerSheet:\n        m_pagePreview->setPagePreviewLayout(3, 3);\n        break;\n    case QCUPSSupport::SixteenPagesPerSheet:\n        m_pagePreview->setPagePreviewLayout(4, 4);\n        break;\n    }\n#endif\n}\n\nvoid QPageSetupWidget::unitChanged()\n{\n    if (m_blockSignals)\n        return;\n    m_units = qvariant_cast<QPageLayout::Unit>(m_ui.unitCombo->currentData());\n    m_pageLayout.setUnits(m_units);\n    updateWidget();\n}\n\nvoid QPageSetupWidget::topMarginChanged(double newValue)\n{\n    if (m_blockSignals)\n        return;\n    m_pageLayout.setTopMargin(newValue);\n    m_pagePreview->setPageLayout(m_pageLayout);\n}\n\nvoid QPageSetupWidget::bottomMarginChanged(double newValue)\n{\n    if (m_blockSignals)\n        return;\n    m_pageLayout.setBottomMargin(newValue);\n    m_pagePreview->setPageLayout(m_pageLayout);\n}\n\nvoid QPageSetupWidget::leftMarginChanged(double newValue)\n{\n    if (m_blockSignals)\n        return;\n    m_pageLayout.setLeftMargin(newValue);\n    m_pagePreview->setPageLayout(m_pageLayout);\n}\n\nvoid QPageSetupWidget::rightMarginChanged(double newValue)\n{\n    if (m_blockSignals)\n        return;\n    m_pageLayout.setRightMargin(newValue);\n    m_pagePreview->setPageLayout(m_pageLayout);\n}\n\n// QPageSetupDialog\n// - Public Linux / CUPS class implementation\n\nQPageSetupDialog::QPageSetupDialog(QPrinter *printer, QWidget *parent)\n    : QDialog(*(new QUnixPageSetupDialogPrivate(printer)), parent)\n{\n    Q_D(QPageSetupDialog);\n    setWindowTitle(QCoreApplication::translate(\"QPrintPreviewDialog\", \"Page Setup\"));\n    static_cast<QUnixPageSetupDialogPrivate *>(d)->init();\n}\n\nQPageSetupDialog::QPageSetupDialog(QWidget *parent)\n    : QDialog(*(new QUnixPageSetupDialogPrivate(nullptr)), parent)\n{\n    Q_D(QPageSetupDialog);\n    setWindowTitle(QCoreApplication::translate(\"QPrintPreviewDialog\", \"Page Setup\"));\n    static_cast<QUnixPageSetupDialogPrivate *>(d)->init();\n}\n\nint QPageSetupDialog::exec()\n{\n    Q_D(QPageSetupDialog);\n\n    int ret = QDialog::exec();\n    if (ret == Accepted) {\n        static_cast <QUnixPageSetupDialogPrivate*>(d)->widget->setupPrinter();\n        static_cast <QUnixPageSetupDialogPrivate*>(d)->widget->updateSavedValues();\n    } else {\n        static_cast <QUnixPageSetupDialogPrivate*>(d)->widget->revertToSavedValues();\n    }\n    return ret;\n}\n\nQT_END_NAMESPACE\n\n#include \"moc_qpagesetupdialog_unix_p.cpp\"\n\n#include \"moc_qpagesetupdialog.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qpagesetupdialog_win.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qpagesetupdialog.h\"\n\n#include <qapplication.h>\n\n#include <private/qprintengine_win_p.h>\n#include \"qpagesetupdialog_p.h\"\n#include \"qprinter.h\"\n#include <qpa/qplatformnativeinterface.h>\n\nQT_BEGIN_NAMESPACE\n\nQPageSetupDialog::QPageSetupDialog(QPrinter *printer, QWidget *parent)\n    : QDialog(*(new QPageSetupDialogPrivate(printer)), parent)\n{\n    setWindowTitle(QCoreApplication::translate(\"QPrintPreviewDialog\", \"Page Setup\"));\n    setAttribute(Qt::WA_DontShowOnScreen);\n}\n\nQPageSetupDialog::QPageSetupDialog(QWidget *parent)\n    : QDialog(*(new QPageSetupDialogPrivate(nullptr)), parent)\n{\n    setWindowTitle(QCoreApplication::translate(\"QPrintPreviewDialog\", \"Page Setup\"));\n    setAttribute(Qt::WA_DontShowOnScreen);\n}\n\nint QPageSetupDialog::exec()\n{\n    Q_D(QPageSetupDialog);\n\n    if (d->printer->outputFormat() != QPrinter::NativeFormat)\n        return Rejected;\n\n    QWin32PrintEngine *engine = static_cast<QWin32PrintEngine*>(d->printer->paintEngine());\n    QWin32PrintEnginePrivate *ep = static_cast<QWin32PrintEnginePrivate *>(engine->d_ptr.data());\n\n    PAGESETUPDLG psd;\n    memset(&psd, 0, sizeof(PAGESETUPDLG));\n    psd.lStructSize = sizeof(PAGESETUPDLG);\n\n    // we need a temp DEVMODE struct if we don't have a global DEVMODE\n    HGLOBAL hDevMode = nullptr;\n    int devModeSize = 0;\n    if (!engine->globalDevMode()) {\n        devModeSize = sizeof(DEVMODE) + ep->devMode->dmDriverExtra;\n        hDevMode = GlobalAlloc(GHND, devModeSize);\n        if (hDevMode) {\n            void *dest = GlobalLock(hDevMode);\n            memcpy(dest, ep->devMode, devModeSize);\n            GlobalUnlock(hDevMode);\n        }\n        psd.hDevMode = hDevMode;\n    } else {\n        psd.hDevMode = engine->globalDevMode();\n    }\n\n    HGLOBAL *tempDevNames = engine->createGlobalDevNames();\n    psd.hDevNames = tempDevNames;\n\n    QWidget *parent = parentWidget();\n    parent = parent ? parent->window() : QApplication::activeWindow();\n    Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));\n\n    QWindow *parentWindow = parent ? parent->windowHandle() : nullptr;\n    psd.hwndOwner = parentWindow\n        ? HWND(QGuiApplication::platformNativeInterface()->nativeResourceForWindow(\"handle\", parentWindow))\n        : nullptr;\n    psd.Flags = PSD_MARGINS;\n    QPageLayout layout = d->printer->pageLayout();\n    switch (layout.units()) {\n    case QPageLayout::Millimeter:\n    case QPageLayout::Inch:\n        break;\n    case QPageLayout::Point:\n    case QPageLayout::Pica:\n    case QPageLayout::Didot:\n    case QPageLayout::Cicero:\n        layout.setUnits(QLocale::system().measurementSystem() == QLocale::MetricSystem ? QPageLayout::Millimeter\n                                                                                       : QPageLayout::Inch);\n        break;\n    }\n    qreal multiplier = 1.0;\n    if (layout.units() == QPageLayout::Millimeter) {\n        psd.Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;\n        multiplier = 100.0;\n    } else { // QPageLayout::Inch)\n        psd.Flags |= PSD_INTHOUSANDTHSOFINCHES;\n        multiplier = 1000.0;\n    }\n    psd.rtMargin.left   = layout.margins().left() * multiplier;\n    psd.rtMargin.top    = layout.margins().top() * multiplier;\n    psd.rtMargin.right  = layout.margins().right() * multiplier;\n    psd.rtMargin.bottom = layout.margins().bottom() * multiplier;\n\n    QDialog::setVisible(true);\n    bool result = PageSetupDlg(&psd);\n    QDialog::setVisible(false);\n    if (result) {\n        engine->setGlobalDevMode(psd.hDevNames, psd.hDevMode);\n        QPageSize pageSize;\n        // try to read orientation and paper size ID from the dialog's devmode struct\n        if (psd.hDevMode) {\n            DEVMODE *rDevmode = reinterpret_cast<DEVMODE*>(GlobalLock(psd.hDevMode));\n            if (rDevmode->dmFields & DM_ORIENTATION) {\n                layout.setOrientation(rDevmode->dmOrientation == DMORIENT_PORTRAIT\n                                      ? QPageLayout::Portrait : QPageLayout::Landscape);\n            }\n            if (rDevmode->dmFields & DM_PAPERSIZE)\n                pageSize = QPageSize::id(rDevmode->dmPaperSize);\n            GlobalUnlock(rDevmode);\n        }\n        // fall back to use our own matching, and assume that paper that's wider than long means landscape\n        if (!pageSize.isValid() || pageSize.id() == QPageSize::Custom) {\n            QSizeF unitSize(psd.ptPaperSize.x / multiplier, psd.ptPaperSize.y / multiplier);\n            if (unitSize.width() > unitSize.height()) {\n                layout.setOrientation(QPageLayout::Landscape);\n                unitSize.transpose();\n            } else {\n                layout.setOrientation(QPageLayout::Portrait);\n            }\n            pageSize = QPageSize(unitSize, layout.units() == QPageLayout::Inch\n                                                           ? QPageSize::Inch : QPageSize::Millimeter);\n        }\n        layout.setPageSize(pageSize, layout.minimumMargins());\n\n        const QMarginsF margins(psd.rtMargin.left, psd.rtMargin.top, psd.rtMargin.right, psd.rtMargin.bottom);\n        layout.setMargins(margins / multiplier, QPageLayout::OutOfBoundsPolicy::Clamp);\n        d->printer->setPageLayout(layout);\n\n        // copy from our temp DEVMODE struct\n        if (!engine->globalDevMode() && hDevMode) {\n            // Make sure memory is allocated\n            if (ep->ownsDevMode && ep->devMode)\n                free(ep->devMode);\n            ep->devMode = reinterpret_cast<DEVMODE *>(malloc(devModeSize));\n            QWin32PrintEnginePrivate::initializeDevMode(ep->devMode);\n            ep->ownsDevMode = true;\n\n            // Copy\n            void *src = GlobalLock(hDevMode);\n            memcpy(ep->devMode, src, devModeSize);\n            GlobalUnlock(hDevMode);\n        }\n    }\n\n    if (!engine->globalDevMode() && hDevMode)\n        GlobalFree(hDevMode);\n    GlobalFree(tempDevNames);\n    done(result);\n    return result;\n}\n\nvoid QPageSetupDialog::setVisible(bool visible)\n{\n    if (!visible)\n        return;\n    exec();\n}\n\nQT_END_NAMESPACE\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qplatformtheme.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qplatformtheme.h\"\n\n#include \"qplatformtheme_p.h\"\n\n#include <QtCore/QVariant>\n#include <QtCore/QStringList>\n#include <QtCore/qfileinfo.h>\n#include <qicon.h>\n#include <qpalette.h>\n#include <qtextformat.h>\n#include <private/qiconloader_p.h>\n#include <private/qguiapplication_p.h>\n#include <qpa/qplatformintegration.h>\n#include <qpa/qplatformdialoghelper.h>\n\n#include <algorithm>\n\nQT_BEGIN_NAMESPACE\n\n/*!\n    \\class QPlatformTheme\n    \\since 5.0\n    \\internal\n    \\preliminary\n    \\ingroup qpa\n    \\brief The QPlatformTheme class allows customizing the UI based on themes.\n\n    See the init_platform function in qguiapplication.cpp for the complete\n    platform initialization process.\n*/\n\n/*!\n    \\enum QPlatformTheme::ThemeHint\n\n    This enum describes the available theme hints.\n\n    \\value CursorFlashTime (int) Cursor flash time in ms, overriding\n                                 QPlatformIntegration::styleHint.\n\n    \\value KeyboardInputInterval (int) Keyboard input interval in ms, overriding\n                                 QPlatformIntegration::styleHint.\n\n    \\value MouseDoubleClickInterval (int) Mouse double click interval in ms,\n                                    overriding QPlatformIntegration::styleHint.\n\n    \\value MouseDoubleClickDistance (int) The maximum distance in logical pixels which the mouse can travel\n                        between clicks in order for the click sequence to be handled as a double click.\n                        The default value is 5 logical pixels.\n\n    \\value MousePressAndHoldInterval (int) Mouse press and hold interval in ms,\n                                    overriding QPlatformIntegration::styleHint.\n\n    \\value StartDragDistance (int) Start drag distance,\n                             overriding QPlatformIntegration::styleHint.\n\n    \\value StartDragTime (int) Start drag time in ms,\n                               overriding QPlatformIntegration::styleHint.\n\n    \\value WheelScrollLines (int) The number of lines to scroll a widget, when the mouse wheel is rotated.\n                        The default value is 3.  \\sa QApplication::wheelScrollLines()\n\n    \\value KeyboardAutoRepeatRate (int) Keyboard auto repeat rate,\n                                  overriding QPlatformIntegration::styleHint.\n\n    \\value PasswordMaskDelay (int) Pass word mask delay in ms,\n                                   overriding QPlatformIntegration::styleHint.\n\n    \\value StartDragVelocity (int) Velocity of a drag,\n                                   overriding QPlatformIntegration::styleHint.\n\n    \\value TextCursorWidth  (int) Determines the width of the text cursor.\n\n    \\value DropShadow       (bool) Determines whether the drop shadow effect for\n                            tooltips or whatsthis is enabled.\n\n    \\value MaximumScrollBarDragDistance (int) Determines the value returned by\n                            QStyle::pixelMetric(PM_MaximumDragDistance)\n\n    \\value ToolButtonStyle (int) A value representing a Qt::ToolButtonStyle.\n\n    \\value ToolBarIconSize Icon size for tool bars.\n\n    \\value SystemIconThemeName (QString) Name of the icon theme.\n\n    \\value SystemIconFallbackThemeName (QString) Name of the fallback icon theme.\n\n    \\value IconThemeSearchPaths (QStringList) Search paths for icons.\n\n    \\value ItemViewActivateItemOnSingleClick (bool) Activate items by single click.\n\n    \\value StyleNames (QStringList) A list of preferred style names.\n\n    \\value WindowAutoPlacement (bool) A boolean value indicating whether Windows\n                               (particularly dialogs) are placed by the system\n                               (see _NET_WM_FULL_PLACEMENT in X11).\n\n    \\value DialogButtonBoxLayout (int) An integer representing a\n                                 QDialogButtonBox::ButtonLayout value.\n\n    \\value DialogButtonBoxButtonsHaveIcons (bool) A boolean value indicating whether\n                                            the buttons of a QDialogButtonBox should have icons.\n\n    \\value UseFullScreenForPopupMenu (bool) Pop menus can cover the full screen including task bar.\n\n    \\value KeyboardScheme (int) An integer value (enum KeyboardSchemes) specifying the\n                           keyboard scheme.\n\n    \\value UiEffects (int) A flag value consisting of UiEffect values specifying the enabled UI animations.\n\n    \\value SpellCheckUnderlineStyle (int) A QTextCharFormat::UnderlineStyle specifying\n                                    the underline style used misspelled words when spell checking.\n\n    \\value TabFocusBehavior (int) A Qt::TabFocusBehavior specifying\n                         the behavior of focus change when tab key was pressed.\n                         This enum value was added in Qt 5.5.\n\n    \\value DialogSnapToDefaultButton (bool) Whether the mouse should snap to the default button when a dialog\n                                     becomes visible.\n\n    \\value ContextMenuOnMouseRelease (bool) Whether the context menu should be shown on mouse release.\n\n    \\value TouchDoubleTapDistance (int) The maximum distance in logical pixels which a touchpoint can travel\n                        between taps in order for the tap sequence to be handled as a double tap.\n                        The default value is double the MouseDoubleClickDistance, or 10 logical pixels\n                        if that is not specified.\n\n    \\value ShowShortcutsInContextMenus (bool) Whether to display shortcut key sequences in context menus.\n\n    \\value InteractiveResizeAcrossScreens (bool) Whether using the whole virtual geometry of all the screens\n                        as basis for the resize.\n                        This enum value has been added in Qt 6.2.\n\n    \\value ShowDirectoriesFirst (bool) Whether directories should be shown\n           first (before files) in file dialogs.\n           This enum value was added in Qt 6.3.\n\n    \\value PreselectFirstFileInDirectory (bool) Whether the first file in a directory\n           should be automatically selected when a file dialog opens.\n           This enum value was added in Qt 6.3.\n\n    \\value ButtonPressKeys (QList<Qt::Key>) A list of keys that can be used to press buttons via keyboard input.\n\n    \\value SetFocusOnTouchRelease (bool) Whether focus objects (line edits etc) should receive\n           input focus after a touch/mouse release.\n           This enum value has been added in Qt 6.5.\n\n    \\value MouseCursorTheme (QString) Name of the mouse cursor theme.\n           This enum value has been added in Qt 6.5.\n\n    \\value MouseCursorSize (QSize) Size of the mouse cursor.\n           This enum value has been added in Qt 6.5.\n\n    \\sa themeHint(), QStyle::pixelMetric()\n*/\n\n\n#if QT_CONFIG(shortcut)\n// Table of key bindings. It must be sorted on key sequence:\n// The integer value of VK_KEY | Modifier Keys (e.g., VK_META, and etc.)\n// A priority of 1 indicates that this is the primary key binding when multiple are defined.\n\nenum KeyPlatform {\n    KB_Win = (1 << QPlatformTheme::WindowsKeyboardScheme),\n    KB_Mac = (1 << QPlatformTheme::MacKeyboardScheme),\n    KB_X11 = (1 << QPlatformTheme::X11KeyboardScheme),\n    KB_KDE = (1 << QPlatformTheme::KdeKeyboardScheme),\n    KB_Gnome = (1 << QPlatformTheme::GnomeKeyboardScheme),\n    KB_CDE = (1 << QPlatformTheme::CdeKeyboardScheme),\n    KB_All = 0xffff\n};\n\nconst QKeyBinding QPlatformThemePrivate::keyBindings[] = {\n    //   StandardKey                            Priority    Key Sequence                            Platforms\n    {QKeySequence::HelpContents,            1,          Qt::CTRL | Qt::Key_Question,            KB_Mac},\n    {QKeySequence::HelpContents,            0,          Qt::Key_F1,                             KB_Win | KB_X11},\n    {QKeySequence::WhatsThis,               1,          Qt::SHIFT | Qt::Key_F1,                 KB_All},\n    {QKeySequence::Open,                    1,          Qt::CTRL | Qt::Key_O,                   KB_All},\n    {QKeySequence::Close,                   0,          Qt::CTRL | Qt::Key_F4,                  KB_Mac},\n    {QKeySequence::Close,                   1,          Qt::CTRL | Qt::Key_F4,                  KB_Win},\n    {QKeySequence::Close,                   1,          Qt::CTRL | Qt::Key_W,                   KB_Mac},\n    {QKeySequence::Close,                   0,          Qt::CTRL | Qt::Key_W,                   KB_Win | KB_X11},\n    {QKeySequence::Save,                    1,          Qt::CTRL | Qt::Key_S,                   KB_All},\n    {QKeySequence::New,                     1,          Qt::CTRL | Qt::Key_N,                   KB_All},\n    {QKeySequence::Delete,                  0,          Qt::CTRL | Qt::Key_D,                   KB_X11}, //emacs (line edit only)\n    {QKeySequence::Delete,                  1,          Qt::Key_Delete,                         KB_All},\n    {QKeySequence::Delete,                  0,          Qt::META | Qt::Key_D,                   KB_Mac},\n    {QKeySequence::Cut,                     1,          Qt::CTRL | Qt::Key_X,                   KB_All},\n    {QKeySequence::Cut,                     0,          Qt::SHIFT | Qt::Key_Delete,             KB_Win | KB_X11}, //## Check if this should work on mac\n    {QKeySequence::Cut,                     0,          Qt::Key_F20,                            KB_X11}, //Cut on sun keyboards\n    {QKeySequence::Cut,                     0,          Qt::META | Qt::Key_K,                   KB_Mac},\n    {QKeySequence::Copy,                    0,          Qt::CTRL | Qt::Key_Insert,              KB_X11 | KB_Win},\n    {QKeySequence::Copy,                    1,          Qt::CTRL | Qt::Key_C,                   KB_All},\n    {QKeySequence::Copy,                    0,          Qt::Key_F16,                            KB_X11}, //Copy on sun keyboards\n    {QKeySequence::Paste,                   0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Insert,  KB_X11},\n    {QKeySequence::Paste,                   1,          Qt::CTRL | Qt::Key_V,                   KB_All},\n    {QKeySequence::Paste,                   0,          Qt::SHIFT | Qt::Key_Insert,             KB_Win | KB_X11},\n    {QKeySequence::Paste,                   0,          Qt::Key_F18,                            KB_X11}, //Paste on sun keyboards\n    {QKeySequence::Paste,                   0,          Qt::META | Qt::Key_Y,                   KB_Mac},\n    {QKeySequence::Undo,                    0,          Qt::ALT  | Qt::Key_Backspace,           KB_Win},\n    {QKeySequence::Undo,                    1,          Qt::CTRL | Qt::Key_Z,                   KB_All},\n    {QKeySequence::Undo,                    0,          Qt::Key_F14,                            KB_X11}, //Undo on sun keyboards\n    {QKeySequence::Redo,                    0,          Qt::ALT  | Qt::SHIFT | Qt::Key_Backspace,KB_Win},\n    {QKeySequence::Redo,                    0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Z,       KB_Mac},\n    {QKeySequence::Redo,                    0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Z,       KB_Win | KB_X11},\n    {QKeySequence::Redo,                    1,          Qt::CTRL | Qt::Key_Y,                   KB_Win},\n    {QKeySequence::Back,                    1,          Qt::ALT  | Qt::Key_Left,                KB_Win | KB_X11},\n    {QKeySequence::Back,                    0,          Qt::CTRL | Qt::Key_Left,                KB_Mac},\n    {QKeySequence::Back,                    1,          Qt::CTRL | Qt::Key_BracketLeft,         KB_Mac},\n    {QKeySequence::Back,                    0,          Qt::Key_Backspace,                      KB_Win},\n    {QKeySequence::Forward,                 1,          Qt::ALT  | Qt::Key_Right,               KB_Win | KB_X11},\n    {QKeySequence::Forward,                 0,          Qt::CTRL | Qt::Key_Right,               KB_Mac},\n    {QKeySequence::Forward,                 1,          Qt::CTRL | Qt::Key_BracketRight,        KB_Mac},\n    {QKeySequence::Forward,                 0,          Qt::SHIFT | Qt::Key_Backspace,          KB_Win},\n    {QKeySequence::Refresh,                 1,          Qt::CTRL | Qt::Key_R,                   KB_Gnome | KB_Mac},\n    {QKeySequence::Refresh,                 0,          Qt::Key_F5,                             KB_Win | KB_X11},\n    {QKeySequence::ZoomIn,                  1,          Qt::CTRL | Qt::Key_Plus,                KB_All},\n    {QKeySequence::ZoomOut,                 1,          Qt::CTRL | Qt::Key_Minus,               KB_All},\n    {QKeySequence::Print,                   1,          Qt::CTRL | Qt::Key_P,                   KB_All},\n    {QKeySequence::AddTab,                  1,          Qt::CTRL | Qt::SHIFT | Qt::Key_N,       KB_KDE},\n    {QKeySequence::AddTab,                  0,          Qt::CTRL | Qt::Key_T,                   KB_All},\n    {QKeySequence::NextChild,               0,          Qt::CTRL | Qt::Key_F6,                  KB_Win},\n    {QKeySequence::NextChild,               0,          Qt::CTRL | Qt::Key_Tab,                 KB_Mac}, //different priority from above\n    {QKeySequence::NextChild,               1,          Qt::CTRL | Qt::Key_Tab,                 KB_Win | KB_X11},\n    {QKeySequence::NextChild,               1,          Qt::CTRL | Qt::Key_BraceRight,          KB_Mac},\n    {QKeySequence::NextChild,               0,          Qt::CTRL | Qt::Key_Comma,               KB_KDE},\n    {QKeySequence::NextChild,               0,          Qt::Key_Forward,                        KB_All},\n    {QKeySequence::PreviousChild,           0,          Qt::CTRL | Qt::SHIFT | Qt::Key_F6,      KB_Win},\n    {QKeySequence::PreviousChild,           0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, KB_Mac },//different priority from above\n    {QKeySequence::PreviousChild,           1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, KB_Win | KB_X11},\n    {QKeySequence::PreviousChild,           1,          Qt::CTRL | Qt::Key_BraceLeft,           KB_Mac},\n    {QKeySequence::PreviousChild,           0,          Qt::CTRL | Qt::Key_Period,              KB_KDE},\n    {QKeySequence::PreviousChild,           0,          Qt::Key_Back,                           KB_All},\n    {QKeySequence::Find,                    0,          Qt::CTRL | Qt::Key_F,                   KB_All},\n    {QKeySequence::FindNext,                0,          Qt::CTRL | Qt::Key_G,                   KB_Win},\n    {QKeySequence::FindNext,                1,          Qt::CTRL | Qt::Key_G,                   KB_Gnome | KB_Mac},\n    {QKeySequence::FindNext,                1,          Qt::Key_F3,                             KB_Win},\n    {QKeySequence::FindNext,                0,          Qt::Key_F3,                             KB_X11},\n    {QKeySequence::FindPrevious,            0,          Qt::CTRL | Qt::SHIFT | Qt::Key_G,       KB_Win},\n    {QKeySequence::FindPrevious,            1,          Qt::CTRL | Qt::SHIFT | Qt::Key_G,       KB_Gnome | KB_Mac},\n    {QKeySequence::FindPrevious,            1,          Qt::SHIFT | Qt::Key_F3,                 KB_Win},\n    {QKeySequence::FindPrevious,            0,          Qt::SHIFT | Qt::Key_F3,                 KB_X11},\n    {QKeySequence::Replace,                 0,          Qt::CTRL | Qt::Key_R,                   KB_KDE},\n    {QKeySequence::Replace,                 0,          Qt::CTRL | Qt::Key_H,                   KB_Gnome},\n    {QKeySequence::Replace,                 0,          Qt::CTRL | Qt::Key_H,                   KB_Win},\n    {QKeySequence::SelectAll,               1,          Qt::CTRL | Qt::Key_A,                   KB_All},\n    {QKeySequence::Bold,                    1,          Qt::CTRL | Qt::Key_B,                   KB_All},\n    {QKeySequence::Italic,                  0,          Qt::CTRL | Qt::Key_I,                   KB_All},\n    {QKeySequence::Underline,               1,          Qt::CTRL | Qt::Key_U,                   KB_All},\n    {QKeySequence::MoveToNextChar,          1,          Qt::Key_Right,                          KB_All},\n    {QKeySequence::MoveToNextChar,          0,          Qt::META | Qt::Key_F,                   KB_Mac},\n    {QKeySequence::MoveToPreviousChar,      1,          Qt::Key_Left,                           KB_All},\n    {QKeySequence::MoveToPreviousChar,      0,          Qt::META | Qt::Key_B,                   KB_Mac},\n    {QKeySequence::MoveToNextWord,          0,          Qt::ALT  | Qt::Key_Right,               KB_Mac},\n    {QKeySequence::MoveToNextWord,          0,          Qt::CTRL | Qt::Key_Right,               KB_Win | KB_X11},\n    {QKeySequence::MoveToPreviousWord,      0,          Qt::ALT  | Qt::Key_Left,                KB_Mac},\n    {QKeySequence::MoveToPreviousWord,      0,          Qt::CTRL | Qt::Key_Left,                KB_Win | KB_X11},\n    {QKeySequence::MoveToNextLine,          1,          Qt::Key_Down,                           KB_All},\n    {QKeySequence::MoveToNextLine,          0,          Qt::META | Qt::Key_N,                   KB_Mac},\n    {QKeySequence::MoveToPreviousLine,      1,          Qt::Key_Up,                             KB_All},\n    {QKeySequence::MoveToPreviousLine,      0,          Qt::META | Qt::Key_P,                   KB_Mac},\n    {QKeySequence::MoveToNextPage,          0,          Qt::META | Qt::Key_PageDown,            KB_Mac},\n    {QKeySequence::MoveToNextPage,          0,          Qt::META | Qt::Key_Down,                KB_Mac},\n    {QKeySequence::MoveToNextPage,          0,          Qt::META | Qt::Key_V,                   KB_Mac},\n    {QKeySequence::MoveToNextPage,          0,          Qt::ALT  | Qt::Key_PageDown,            KB_Mac },\n    {QKeySequence::MoveToNextPage,          1,          Qt::Key_PageDown,                       KB_All},\n    {QKeySequence::MoveToPreviousPage,      0,          Qt::META | Qt::Key_PageUp,              KB_Mac},\n    {QKeySequence::MoveToPreviousPage,      0,          Qt::META | Qt::Key_Up,                  KB_Mac},\n    {QKeySequence::MoveToPreviousPage,      0,          Qt::ALT  | Qt::Key_PageUp,              KB_Mac },\n    {QKeySequence::MoveToPreviousPage,      1,          Qt::Key_PageUp,                         KB_All},\n    {QKeySequence::MoveToStartOfLine,       0,          Qt::META | Qt::Key_Left,                KB_Mac},\n    {QKeySequence::MoveToStartOfLine,       0,          Qt::CTRL | Qt::Key_Left,                KB_Mac },\n    {QKeySequence::MoveToStartOfLine,       0,          Qt::Key_Home,                           KB_Win | KB_X11},\n    {QKeySequence::MoveToEndOfLine,         0,          Qt::META | Qt::Key_Right,               KB_Mac},\n    {QKeySequence::MoveToEndOfLine,         0,          Qt::CTRL | Qt::Key_Right,               KB_Mac },\n    {QKeySequence::MoveToEndOfLine,         0,          Qt::Key_End,                            KB_Win | KB_X11},\n    {QKeySequence::MoveToEndOfLine,         0,          Qt::CTRL | Qt::Key_E,                   KB_X11},\n    {QKeySequence::MoveToStartOfBlock,      0,          Qt::META | Qt::Key_A,                   KB_Mac},\n    {QKeySequence::MoveToStartOfBlock,      1,          Qt::ALT  | Qt::Key_Up,                  KB_Mac}, //mac only\n    {QKeySequence::MoveToEndOfBlock,        0,          Qt::META | Qt::Key_E,                   KB_Mac},\n    {QKeySequence::MoveToEndOfBlock,        1,          Qt::ALT  | Qt::Key_Down,                KB_Mac}, //mac only\n    {QKeySequence::MoveToStartOfDocument,   1,          Qt::CTRL | Qt::Key_Up,                  KB_Mac},\n    {QKeySequence::MoveToStartOfDocument,   0,          Qt::CTRL | Qt::Key_Home,                KB_Win | KB_X11},\n    {QKeySequence::MoveToStartOfDocument,   0,          Qt::Key_Home,                           KB_Mac},\n    {QKeySequence::MoveToEndOfDocument,     1,          Qt::CTRL | Qt::Key_Down,                KB_Mac},\n    {QKeySequence::MoveToEndOfDocument,     0,          Qt::CTRL | Qt::Key_End,                 KB_Win | KB_X11},\n    {QKeySequence::MoveToEndOfDocument,     0,          Qt::Key_End,                            KB_Mac},\n    {QKeySequence::SelectNextChar,          0,          Qt::SHIFT | Qt::Key_Right,              KB_All},\n    {QKeySequence::SelectPreviousChar,      0,          Qt::SHIFT | Qt::Key_Left,               KB_All},\n    {QKeySequence::SelectNextWord,          0,          Qt::ALT  | Qt::SHIFT | Qt::Key_Right,   KB_Mac},\n    {QKeySequence::SelectNextWord,          0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Right,   KB_Win | KB_X11},\n    {QKeySequence::SelectPreviousWord,      0,          Qt::ALT  | Qt::SHIFT | Qt::Key_Left,    KB_Mac},\n    {QKeySequence::SelectPreviousWord,      0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Left,    KB_Win | KB_X11},\n    {QKeySequence::SelectNextLine,          0,          Qt::SHIFT | Qt::Key_Down,               KB_All},\n    {QKeySequence::SelectPreviousLine,      0,          Qt::SHIFT | Qt::Key_Up,                 KB_All},\n    {QKeySequence::SelectNextPage,          0,          Qt::SHIFT | Qt::Key_PageDown,           KB_All},\n    {QKeySequence::SelectPreviousPage,      0,          Qt::SHIFT | Qt::Key_PageUp,             KB_All},\n    {QKeySequence::SelectStartOfLine,       0,          Qt::META | Qt::SHIFT | Qt::Key_Left,    KB_Mac},\n    {QKeySequence::SelectStartOfLine,       1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Left,    KB_Mac },\n    {QKeySequence::SelectStartOfLine,       0,          Qt::SHIFT | Qt::Key_Home,               KB_Win | KB_X11},\n    {QKeySequence::SelectEndOfLine,         0,          Qt::META | Qt::SHIFT | Qt::Key_Right,   KB_Mac},\n    {QKeySequence::SelectEndOfLine,         1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Right,   KB_Mac },\n    {QKeySequence::SelectEndOfLine,         0,          Qt::SHIFT | Qt::Key_End,                KB_Win | KB_X11},\n    {QKeySequence::SelectStartOfBlock,      1,          Qt::ALT  | Qt::SHIFT | Qt::Key_Up,      KB_Mac}, //mac only\n    {QKeySequence::SelectStartOfBlock,      0,          Qt::META | Qt::SHIFT | Qt::Key_A,       KB_Mac},\n    {QKeySequence::SelectEndOfBlock,        1,          Qt::ALT  | Qt::SHIFT | Qt::Key_Down,    KB_Mac}, //mac only\n    {QKeySequence::SelectEndOfBlock,        0,          Qt::META | Qt::SHIFT | Qt::Key_E,       KB_Mac},\n    {QKeySequence::SelectStartOfDocument,   1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Up,      KB_Mac},\n    {QKeySequence::SelectStartOfDocument,   0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Home,    KB_Win | KB_X11},\n    {QKeySequence::SelectStartOfDocument,   0,          Qt::SHIFT | Qt::Key_Home,               KB_Mac},\n    {QKeySequence::SelectEndOfDocument,     1,          Qt::CTRL | Qt::SHIFT | Qt::Key_Down,    KB_Mac},\n    {QKeySequence::SelectEndOfDocument,     0,          Qt::CTRL | Qt::SHIFT | Qt::Key_End,     KB_Win | KB_X11},\n    {QKeySequence::SelectEndOfDocument,     0,          Qt::SHIFT | Qt::Key_End,                KB_Mac},\n    {QKeySequence::DeleteStartOfWord,       0,          Qt::ALT  | Qt::Key_Backspace,           KB_Mac},\n    {QKeySequence::DeleteStartOfWord,       0,          Qt::CTRL | Qt::Key_Backspace,           KB_X11 | KB_Win},\n    {QKeySequence::DeleteEndOfWord,         0,          Qt::ALT  | Qt::Key_Delete,              KB_Mac},\n    {QKeySequence::DeleteEndOfWord,         0,          Qt::CTRL | Qt::Key_Delete,              KB_X11 | KB_Win},\n    {QKeySequence::DeleteEndOfLine,         0,          Qt::CTRL | Qt::Key_K,                   KB_X11}, //emacs (line edit only)\n    {QKeySequence::InsertParagraphSeparator,0,          Qt::Key_Enter,                          KB_All},\n    {QKeySequence::InsertParagraphSeparator,0,          Qt::Key_Return,                         KB_All},\n    {QKeySequence::InsertLineSeparator,     0,          Qt::META | Qt::Key_Enter,               KB_Mac},\n    {QKeySequence::InsertLineSeparator,     0,          Qt::META | Qt::Key_Return,              KB_Mac},\n    {QKeySequence::InsertLineSeparator,     0,          Qt::SHIFT | Qt::Key_Enter,              KB_All},\n    {QKeySequence::InsertLineSeparator,     0,          Qt::SHIFT | Qt::Key_Return,             KB_All},\n    {QKeySequence::InsertLineSeparator,     0,          Qt::META | Qt::Key_O,                   KB_Mac},\n    {QKeySequence::SaveAs,                  0,          Qt::CTRL | Qt::SHIFT | Qt::Key_S,       KB_All},\n    {QKeySequence::Preferences,             0,          Qt::CTRL | Qt::Key_Comma,               KB_Mac},\n    {QKeySequence::Preferences,             0,          Qt::CTRL | Qt::SHIFT | Qt::Key_Comma,   KB_KDE},\n    {QKeySequence::Quit,                    0,          Qt::CTRL | Qt::Key_Q,                   KB_X11 | KB_Gnome | KB_KDE | KB_Mac},\n    {QKeySequence::FullScreen,              1,          Qt::META | Qt::CTRL | Qt::Key_F,        KB_Mac},\n    {QKeySequence::FullScreen,              0,          Qt::ALT  | Qt::Key_Enter,               KB_Win},\n    {QKeySequence::FullScreen,              0,          Qt::CTRL | Qt::SHIFT | Qt::Key_F,       KB_KDE},\n    {QKeySequence::FullScreen,              1,          Qt::CTRL | Qt::Key_F11,                 KB_Gnome},\n    {QKeySequence::FullScreen,              1,          Qt::Key_F11,                            KB_Win | KB_KDE},\n    {QKeySequence::Deselect,                0,          Qt::CTRL | Qt::SHIFT | Qt::Key_A,       KB_X11},\n    {QKeySequence::DeleteCompleteLine,      0,          Qt::CTRL | Qt::Key_U,                   KB_X11},\n    {QKeySequence::Backspace,               1,          Qt::Key_Backspace,                      KB_Mac},\n    {QKeySequence::Backspace,               0,          Qt::META | Qt::Key_H,                   KB_Mac},\n    {QKeySequence::Cancel,                  0,          Qt::Key_Escape,                         KB_All},\n    {QKeySequence::Cancel,                  0,          Qt::CTRL | Qt::Key_Period,              KB_Mac}\n};\n\nconst uint QPlatformThemePrivate::numberOfKeyBindings = sizeof(QPlatformThemePrivate::keyBindings)/(sizeof(QKeyBinding));\n#endif\n\nQPlatformThemePrivate::QPlatformThemePrivate()\n        : systemPalette(nullptr)\n{ }\n\nQPlatformThemePrivate::~QPlatformThemePrivate()\n{\n    delete systemPalette;\n}\n\nQ_GUI_EXPORT QPalette qt_fusionPalette()\n{\n    auto theme = QGuiApplicationPrivate::platformTheme();\n    const bool darkAppearance = theme\n                              ? theme->colorScheme() == Qt::ColorScheme::Dark\n                              : false;\n    const QColor windowText = darkAppearance ? QColor(240, 240, 240) : Qt::black;\n    const QColor backGround = darkAppearance ? QColor(50, 50, 50) : QColor(239, 239, 239);\n    const QColor light = backGround.lighter(150);\n    const QColor mid = (backGround.darker(130));\n    const QColor midLight = mid.lighter(110);\n    const QColor base = darkAppearance ? backGround.darker(140) : Qt::white;\n    const QColor disabledBase(backGround);\n    const QColor dark = backGround.darker(150);\n    const QColor darkDisabled = QColor(209, 209, 209).darker(110);\n    const QColor text = darkAppearance ? windowText : Qt::black;\n    const QColor highlight = QColor(48, 140, 198);\n    const QColor hightlightedText = darkAppearance ? windowText : Qt::white;\n    const QColor disabledText = darkAppearance ? QColor(130, 130, 130) : QColor(190, 190, 190);\n    const QColor button = backGround;\n    const QColor shadow = dark.darker(135);\n    const QColor disabledShadow = shadow.lighter(150);\n    const QColor disabledHighlight(145, 145, 145);\n    QColor placeholder = text;\n    placeholder.setAlpha(128);\n\n    QPalette fusionPalette(windowText, backGround, light, dark, mid, text, base);\n    fusionPalette.setBrush(QPalette::Midlight, midLight);\n    fusionPalette.setBrush(QPalette::Button, button);\n    fusionPalette.setBrush(QPalette::Shadow, shadow);\n    fusionPalette.setBrush(QPalette::HighlightedText, hightlightedText);\n\n    fusionPalette.setBrush(QPalette::Disabled, QPalette::Text, disabledText);\n    fusionPalette.setBrush(QPalette::Disabled, QPalette::WindowText, disabledText);\n    fusionPalette.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledText);\n    fusionPalette.setBrush(QPalette::Disabled, QPalette::Base, disabledBase);\n    fusionPalette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled);\n    fusionPalette.setBrush(QPalette::Disabled, QPalette::Shadow, disabledShadow);\n\n    fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, highlight);\n    fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, highlight);\n    fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, disabledHighlight);\n\n    fusionPalette.setBrush(QPalette::Active, QPalette::Accent, highlight);\n    fusionPalette.setBrush(QPalette::Inactive, QPalette::Accent, highlight);\n    fusionPalette.setBrush(QPalette::Disabled, QPalette::Accent, disabledHighlight);\n\n    fusionPalette.setBrush(QPalette::PlaceholderText, placeholder);\n\n    // Use a more legible light blue on dark backgrounds than the default Qt::blue.\n    if (darkAppearance)\n        fusionPalette.setBrush(QPalette::Link, highlight);\n\n    return fusionPalette;\n}\n\nvoid QPlatformThemePrivate::initializeSystemPalette()\n{\n    Q_ASSERT(!systemPalette);\n    systemPalette = new QPalette(qt_fusionPalette());\n}\n\nQPlatformTheme::QPlatformTheme()\n    : d_ptr(new QPlatformThemePrivate)\n{\n\n}\n\nQPlatformTheme::QPlatformTheme(QPlatformThemePrivate *priv)\n    : d_ptr(priv)\n{ }\n\nQPlatformTheme::~QPlatformTheme()\n{\n\n}\n\nbool QPlatformTheme::usePlatformNativeDialog(DialogType type) const\n{\n    Q_UNUSED(type);\n    return false;\n}\n\nQPlatformDialogHelper *QPlatformTheme::createPlatformDialogHelper(DialogType type) const\n{\n    Q_UNUSED(type);\n    return nullptr;\n}\n\nQt::ColorScheme QPlatformTheme::colorScheme() const\n{\n    return Qt::ColorScheme::Unknown;\n}\n\nvoid QPlatformTheme::requestColorScheme(Qt::ColorScheme scheme)\n{\n    Q_UNUSED(scheme);\n}\n\nconst QPalette *QPlatformTheme::palette(Palette type) const\n{\n    Q_D(const QPlatformTheme);\n    if (type == QPlatformTheme::SystemPalette) {\n        if (!d->systemPalette)\n            const_cast<QPlatformTheme *>(this)->d_ptr->initializeSystemPalette();\n        return d->systemPalette;\n    }\n    return nullptr;\n}\n\nconst QFont *QPlatformTheme::font(Font type) const\n{\n    Q_UNUSED(type);\n    return nullptr;\n}\n\n/*!\n    \\brief Return a pixmap for \\a standardPixmap, at the given \\a size.\n\n    The implementation should not take system DPR into account, and\n    always return a pixmap with a DPR of 1. It's up to the consumer\n    to account for DPR and request a pixmap of the right size.\n*/\nQPixmap QPlatformTheme::standardPixmap(StandardPixmap standardPixmap, const QSizeF &size) const\n{\n    Q_UNUSED(standardPixmap);\n    Q_UNUSED(size);\n    // TODO Should return QCommonStyle pixmaps?\n    return QPixmap();\n}\n\n/*!\n    \\brief Return an icon for \\a fileInfo, observing \\a iconOptions.\n\n    This function is queried by QFileIconProvider and similar classes to obtain\n    an icon for a file. If it does not return a non-null icon, fileIconPixmap()\n    is queried for a specific size.\n\n    \\since 5.8\n*/\n\nQIcon QPlatformTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const\n{\n    Q_UNUSED(fileInfo);\n    Q_UNUSED(iconOptions);\n    // TODO Should return QCommonStyle pixmaps?\n    return QIcon();\n}\n\nQVariant QPlatformTheme::themeHint(ThemeHint hint) const\n{\n    // For theme hints which mirror platform integration style hints, query\n    // the platform integration. The base QPlatformIntegration::styleHint()\n    // function will in turn query QPlatformTheme::defaultThemeHint() if there\n    // is no custom value.\n    switch (hint) {\n    case QPlatformTheme::CursorFlashTime:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::CursorFlashTime);\n    case QPlatformTheme::KeyboardInputInterval:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::KeyboardInputInterval);\n    case QPlatformTheme::KeyboardAutoRepeatRate:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::KeyboardAutoRepeatRate);\n    case QPlatformTheme::MouseDoubleClickInterval:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::MouseDoubleClickInterval);\n    case QPlatformTheme::StartDragDistance:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::StartDragDistance);\n    case QPlatformTheme::StartDragTime:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::StartDragTime);\n    case QPlatformTheme::StartDragVelocity:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::StartDragVelocity);\n    case QPlatformTheme::PasswordMaskDelay:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::PasswordMaskDelay);\n    case QPlatformTheme::PasswordMaskCharacter:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::PasswordMaskCharacter);\n    case QPlatformTheme::MousePressAndHoldInterval:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::MousePressAndHoldInterval);\n    case QPlatformTheme::ItemViewActivateItemOnSingleClick:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ItemViewActivateItemOnSingleClick);\n    case QPlatformTheme::UiEffects:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::UiEffects);\n    case QPlatformTheme::ShowShortcutsInContextMenus:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ShowShortcutsInContextMenus);\n    case QPlatformTheme::SetFocusOnTouchRelease:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::SetFocusOnTouchRelease);\n    case QPlatformTheme::FlickStartDistance:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FlickStartDistance);\n    case QPlatformTheme::FlickMaximumVelocity:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FlickMaximumVelocity);\n    case QPlatformTheme::FlickDeceleration:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FlickDeceleration);\n    case QPlatformTheme::UnderlineShortcut:\n        return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::UnderlineShortcut);\n    default:\n        return QPlatformTheme::defaultThemeHint(hint);\n    }\n}\n\nQVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)\n{\n    switch (hint) {\n    case QPlatformTheme::CursorFlashTime:\n        return QVariant(1000);\n    case QPlatformTheme::KeyboardInputInterval:\n        return QVariant(400);\n    case QPlatformTheme::KeyboardAutoRepeatRate:\n        return QVariant(30);\n    case QPlatformTheme::MouseDoubleClickInterval:\n        return QVariant(400);\n    case QPlatformTheme::StartDragDistance:\n        return QVariant(10);\n    case QPlatformTheme::StartDragTime:\n        return QVariant(500);\n    case QPlatformTheme::PasswordMaskDelay:\n        return QVariant(int(0));\n    case QPlatformTheme::PasswordMaskCharacter:\n        return QVariant(QChar(u'\\x25CF'));\n    case QPlatformTheme::StartDragVelocity:\n        return QVariant(int(0)); // no limit\n    case QPlatformTheme::UseFullScreenForPopupMenu:\n        return QVariant(false);\n    case QPlatformTheme::WindowAutoPlacement:\n        return QVariant(false);\n    case QPlatformTheme::DialogButtonBoxLayout:\n        return QVariant(int(0));\n    case QPlatformTheme::DialogButtonBoxButtonsHaveIcons:\n        return QVariant(false);\n    case QPlatformTheme::ItemViewActivateItemOnSingleClick:\n        return QVariant(false);\n    case QPlatformTheme::ToolButtonStyle:\n        return QVariant(int(Qt::ToolButtonIconOnly));\n    case QPlatformTheme::ToolBarIconSize:\n        return QVariant(int(0));\n    case QPlatformTheme::SystemIconThemeName:\n    case QPlatformTheme::SystemIconFallbackThemeName:\n        return QVariant(QString());\n    case QPlatformTheme::IconThemeSearchPaths:\n        return QVariant(QStringList());\n    case QPlatformTheme::IconFallbackSearchPaths:\n        return QVariant(QStringList());\n    case QPlatformTheme::StyleNames:\n        return QVariant(QStringList());\n    case QPlatformTheme::ShowShortcutsInContextMenus:\n        return QVariant(true);\n    case TextCursorWidth:\n        return QVariant(1);\n    case DropShadow:\n        return QVariant(false);\n    case MaximumScrollBarDragDistance:\n        return QVariant(-1);\n    case KeyboardScheme:\n        return QVariant(int(WindowsKeyboardScheme));\n    case UiEffects:\n        return QVariant(int(0));\n    case SpellCheckUnderlineStyle:\n        return QVariant(int(QTextCharFormat::WaveUnderline));\n    case TabFocusBehavior:\n        return QVariant(int(Qt::TabFocusAllControls));\n    case IconPixmapSizes:\n        return QVariant::fromValue(QList<int>());\n    case DialogSnapToDefaultButton:\n    case ContextMenuOnMouseRelease:\n        return QVariant(false);\n    case MousePressAndHoldInterval:\n        return QVariant(800);\n    case MouseDoubleClickDistance:\n        {\n            bool ok = false;\n            const int dist = qEnvironmentVariableIntValue(\"QT_DBL_CLICK_DIST\", &ok);\n            return QVariant(ok ? dist : 5);\n        }\n    case WheelScrollLines:\n        return QVariant(3);\n    case TouchDoubleTapDistance:\n        {\n            bool ok = false;\n            int dist = qEnvironmentVariableIntValue(\"QT_DBL_TAP_DIST\", &ok);\n            if (!ok)\n                dist = defaultThemeHint(MouseDoubleClickDistance).toInt(&ok) * 2;\n            return QVariant(ok ? dist : 10);\n        }\n    case MouseQuickSelectionThreshold:\n        return QVariant(10);\n    case InteractiveResizeAcrossScreens:\n        return true;\n    case ShowDirectoriesFirst:\n        return true;\n    case PreselectFirstFileInDirectory:\n        return false;\n    case ButtonPressKeys:\n        return QVariant::fromValue(QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Select }));\n    case SetFocusOnTouchRelease:\n        return false;\n    case FlickStartDistance:\n        return QVariant(15);\n    case FlickMaximumVelocity:\n        return QVariant(2500);\n    case FlickDeceleration:\n        return QVariant(1500);\n    case MenuBarFocusOnAltPressRelease:\n        return false;\n    case MouseCursorTheme:\n        return QVariant(QString());\n    case MouseCursorSize:\n        return QVariant(QSize(16, 16));\n    case UnderlineShortcut:\n        return true;\n    case ShowIconsInMenus:\n        return true;\n    case PreferFileIconFromTheme:\n        return false;\n    }\n\n    return QVariant();\n}\n\nQPlatformMenuItem *QPlatformTheme::createPlatformMenuItem() const\n{\n    return nullptr;\n}\n\nQPlatformMenu *QPlatformTheme::createPlatformMenu() const\n{\n    return nullptr;\n}\n\nQPlatformMenuBar *QPlatformTheme::createPlatformMenuBar() const\n{\n    return nullptr;\n}\n\n#ifndef QT_NO_SYSTEMTRAYICON\n/*!\n   Factory function for QSystemTrayIcon. This function will return 0 if the platform\n   integration does not support creating any system tray icon.\n*/\nQPlatformSystemTrayIcon *QPlatformTheme::createPlatformSystemTrayIcon() const\n{\n    return nullptr;\n}\n#endif\n\n/*!\n   Factory function for the QIconEngine used by QIcon::fromTheme(). By default this\n   function returns a QIconLoaderEngine, but subclasses can reimplement it to\n   provide their own.\n\n   It is especially useful to benefit from some platform specific facilities or\n   optimizations like an inter-process cache in systems mostly built with Qt.\n\n   \\since 5.1\n*/\nQIconEngine *QPlatformTheme::createIconEngine(const QString &iconName) const\n{\n    return new QIconLoaderEngine(iconName);\n}\n\n#if QT_CONFIG(shortcut)\n// mixed-mode predicate: all of these overloads are actually needed (but not all for every compiler)\nstruct ByStandardKey {\n    typedef bool result_type;\n\n    bool operator()(QKeySequence::StandardKey lhs, QKeySequence::StandardKey rhs) const\n    { return lhs < rhs; }\n\n    bool operator()(const QKeyBinding& lhs, const QKeyBinding& rhs) const\n    { return operator()(lhs.standardKey, rhs.standardKey); }\n\n    bool operator()(QKeySequence::StandardKey lhs, const QKeyBinding& rhs) const\n    { return operator()(lhs, rhs.standardKey); }\n\n    bool operator()(const QKeyBinding& lhs, QKeySequence::StandardKey rhs) const\n    { return operator()(lhs.standardKey, rhs); }\n};\n\n/*!\n   Returns the key sequence that should be used for a standard action.\n\n  \\since 5.2\n */\nQList<QKeySequence> QPlatformTheme::keyBindings(QKeySequence::StandardKey key) const\n{\n    const uint platform = QPlatformThemePrivate::currentKeyPlatforms();\n    QList <QKeySequence> list;\n\n    std::pair<const QKeyBinding *, const QKeyBinding *> range =\n        std::equal_range(QPlatformThemePrivate::keyBindings,\n                         QPlatformThemePrivate::keyBindings + QPlatformThemePrivate::numberOfKeyBindings,\n                         key, ByStandardKey());\n\n    for (const QKeyBinding *it = range.first; it < range.second; ++it) {\n        if (!(it->platform & platform))\n            continue;\n\n        uint shortcut = it->shortcut.toCombined();\n\n        if (it->priority > 0)\n            list.prepend(QKeySequence(shortcut));\n        else\n            list.append(QKeySequence(shortcut));\n    }\n\n    return list;\n}\n#endif\n\n/*!\n   Returns the text of a standard \\a button.\n\n  \\since 5.3\n  \\sa QPlatformDialogHelper::StandardButton\n */\n\nQString QPlatformTheme::standardButtonText(int button) const\n{\n    return QPlatformTheme::defaultStandardButtonText(button);\n}\n\n#if QT_CONFIG(shortcut)\n/*!\n   Returns the mnemonic that should be used for a standard \\a button.\n\n  \\since 5.9\n  \\sa QPlatformDialogHelper::StandardButton\n */\n\nQKeySequence QPlatformTheme::standardButtonShortcut(int button) const\n{\n    Q_UNUSED(button);\n    return QKeySequence();\n}\n#endif // QT_CONFIG(shortcut)\n\nQString QPlatformTheme::defaultStandardButtonText(int button)\n{\n    switch (button) {\n    case QPlatformDialogHelper::Ok:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"OK\");\n    case QPlatformDialogHelper::Save:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Save\");\n    case QPlatformDialogHelper::SaveAll:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Save All\");\n    case QPlatformDialogHelper::Open:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Open\");\n    case QPlatformDialogHelper::Yes:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"&Yes\");\n    case QPlatformDialogHelper::YesToAll:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Yes to &All\");\n    case QPlatformDialogHelper::No:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"&No\");\n    case QPlatformDialogHelper::NoToAll:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"N&o to All\");\n    case QPlatformDialogHelper::Abort:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Abort\");\n    case QPlatformDialogHelper::Retry:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Retry\");\n    case QPlatformDialogHelper::Ignore:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Ignore\");\n    case QPlatformDialogHelper::Close:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Close\");\n    case QPlatformDialogHelper::Cancel:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Cancel\");\n    case QPlatformDialogHelper::Discard:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Discard\");\n    case QPlatformDialogHelper::Help:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Help\");\n    case QPlatformDialogHelper::Apply:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Apply\");\n    case QPlatformDialogHelper::Reset:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Reset\");\n    case QPlatformDialogHelper::RestoreDefaults:\n        return QCoreApplication::translate(\"QPlatformTheme\", \"Restore Defaults\");\n    default:\n        break;\n    }\n    return QString();\n}\n\nQString QPlatformTheme::removeMnemonics(const QString &original)\n{\n    const auto mnemonicInParentheses = [](QStringView text) {\n        /* Format of mnemonics to remove is /\\(&[^&]\\)/ but accept full-width\n           forms of ( and ) as equivalent, for cross-platform compatibility with\n           MS (and consequent behavior of translators, see QTBUG-110829).\n        */\n        Q_ASSERT(text.size() == 4); // Caller's responsibility.\n        constexpr QChar wideOpen = u'\\uff08', wideClose = u'\\uff09';\n        if (!text.startsWith(u'(') && !text.startsWith(wideOpen))\n            return false;\n        if (text[1] != u'&' || text[2] == u'&')\n            return false;\n        return text.endsWith(u')') || text.endsWith(wideClose);\n    };\n    QString returnText(original.size(), u'\\0');\n    int finalDest = 0;\n    QStringView text(original);\n    while (!text.isEmpty()) {\n        if (text.startsWith(u'&')) {\n            text = text.sliced(1);\n            if (text.isEmpty())\n                break;\n        } else if (text.size() >= 4 && mnemonicInParentheses(text.first(4))) {\n            // Advance over the matched mnemonic:\n            text = text.sliced(4);\n            // Also strip any leading space before it:\n            while (finalDest > 0 && returnText.at(finalDest - 1).isSpace())\n                --finalDest;\n            continue;\n        }\n        returnText[finalDest] = text.front();\n        text = text.sliced(1);\n        ++finalDest;\n    }\n    returnText.truncate(finalDest);\n    return returnText;\n}\n\nunsigned QPlatformThemePrivate::currentKeyPlatforms()\n{\n    const uint keyboardScheme = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::KeyboardScheme).toInt();\n    unsigned result = 1u << keyboardScheme;\n#if QT_CONFIG(shortcut)\n    if (keyboardScheme == QPlatformTheme::KdeKeyboardScheme\n        || keyboardScheme == QPlatformTheme::GnomeKeyboardScheme\n        || keyboardScheme == QPlatformTheme::CdeKeyboardScheme)\n        result |= KB_X11;\n#endif\n    return result;\n}\n\nQString QPlatformTheme::name() const\n{\n    return d_func()->name;\n}\n\nQT_END_NAMESPACE\n\n#include \"moc_qplatformtheme.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qprintdialog_qws.cpp",
    "content": "/****************************************************************************\n**\n** Copyright (C) 2015 The Qt Company Ltd.\n** Contact: http://www.qt.io/licensing/\n**\n** This file is part of the QtGui module of the Qt Toolkit.\n**\n** $QT_BEGIN_LICENSE:LGPL$\n** Commercial License Usage\n** Licensees holding valid commercial Qt licenses may use this file in\n** accordance with the commercial license agreement provided with the\n** Software or, alternatively, in accordance with the terms contained in\n** a written agreement between you and The Qt Company. For licensing terms\n** and conditions see http://www.qt.io/terms-conditions. For further\n** information use the contact form at http://www.qt.io/contact-us.\n**\n** GNU Lesser General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU Lesser\n** General Public License version 2.1 or version 3 as published by the Free\n** Software Foundation and appearing in the file LICENSE.LGPLv21 and\n** LICENSE.LGPLv3 included in the packaging of this file. Please review the\n** following information to ensure the GNU Lesser General Public License\n** requirements will be met: https://www.gnu.org/licenses/lgpl.html and\n** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n**\n** As a special exception, The Qt Company gives you certain additional\n** rights. These rights are described in The Qt Company LGPL Exception\n** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n**\n** GNU General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU\n** General Public License version 3.0 as published by the Free Software\n** Foundation and appearing in the file LICENSE.GPL included in the\n** packaging of this file.  Please review the following information to\n** ensure the GNU General Public License version 3.0 requirements will be\n** met: http://www.gnu.org/copyleft/gpl.html.\n**\n** $QT_END_LICENSE$\n**\n****************************************************************************/\n\n#include \"qplatformdefs.h\"\n\n#include <private/qabstractprintdialog_p.h>\n#include \"qprintdialog.h\"\n\n#ifndef QT_NO_PRINTDIALOG\n\n#include \"qapplication.h\"\n#include \"qbuttongroup.h\"\n#include \"qradiobutton.h\"\n#include \"qcombobox.h\"\n#include \"qspinbox.h\"\n#include \"qprinter.h\"\n#include \"qlineedit.h\"\n#include \"qdir.h\"\n#include \"qmessagebox.h\"\n#include \"qinputdialog.h\"\n#include \"qlayout.h\"\n#include \"qlabel.h\"\n\n#include \"qlibrary.h\"\n\n#ifndef QT_NO_NIS\n\n#ifndef BOOL_DEFINED\n#define BOOL_DEFINED\n#endif\n\n#include <rpcsvc/ypclnt.h>\n#include <rpcsvc/yp_prot.h>\n\n#endif //QT_NO_NIS\n\n#include <ctype.h>\n#include <stdlib.h>\n\n#include <qdebug.h>\n\nQT_BEGIN_NAMESPACE\n\ntypedef void (*QPrintDialogCreator)(QPrintDialog *parent);\nQ_GUI_EXPORT QPrintDialogCreator _qt_print_dialog_creator;\n\nclass QPrintDialogPrivate : public QAbstractPrintDialogPrivate\n{\n    Q_DECLARE_PUBLIC(QPrintDialog)\npublic:\n    QButtonGroup *printerOrFile;\n    bool outputToFile;\n    QRadioButton *printToPrinterButton;\n    QRadioButton *printToFileButton;\n    QLineEdit *fileName;\n\n    QButtonGroup *colorMode;\n    QRadioButton *printColor;\n    QRadioButton *printGray;\n    QPrinter::ColorMode colorMode2;\n\n    QComboBox *orientationCombo, *sizeCombo;\n    QPrinter::PaperSize pageSize;\n    QPrinter::Orientation orientation;\n\n    QSpinBox *copies;\n    int numCopies;\n    QPrinter::PaperSize indexToPaperSize[QPrinter::NPaperSize];\n\n    QComboBox *rangeCombo;\n    QSpinBox *firstPage;\n    QSpinBox *lastPage;\n\n    QComboBox *pageOrderCombo;\n    QPrinter::PageOrder pageOrder2;\n\n    QString faxNum;\n\n    void init();\n\n    void _q_okClicked();\n    void _q_printerOrFileSelected(QAbstractButton *b);\n    void _q_paperSizeSelected(int);\n    void _q_orientSelected(int);\n    void _q_pageOrderSelected(int);\n    void _q_colorModeSelected(QAbstractButton *);\n    void _q_setNumCopies(int);\n    void _q_printRangeSelected(int);\n    void _q_setFirstPage(int);\n    void _q_setLastPage(int);\n    void _q_fileNameEditChanged(const QString &text);\n\n    void setupDestination();\n    void setupPrinterSettings();\n    void setupPaper();\n    void setupOptions();\n\n    void setPrinter(QPrinter *p, bool pickUpSettings);\n};\n\nstatic void isc(QPrintDialogPrivate *d, const QString & text,\n                 QPrinter::PaperSize ps);\n\nvoid QPrintDialogPrivate::_q_okClicked()\n{\n    Q_Q(QPrintDialog);\n#ifndef QT_NO_MESSAGEBOX\n    if (outputToFile && fileName->isModified() && QFileInfo(fileName->text()).exists()) {\n        int confirm = QMessageBox::warning(\n            q, QPrintDialog::tr(\"File exists\"),\n            QPrintDialog::tr(\"<qt>Do you want to overwrite it?</qt>\"),\n            QMessageBox::Yes, QMessageBox::No);\n        if (confirm == QMessageBox::No)\n            return;\n    }\n#endif // QT_NO_MESSAGEBOX\n\n    lastPage->interpretText();\n    firstPage->interpretText();\n    copies->interpretText();\n    if (outputToFile) {\n        printer->setOutputFileName(fileName->text());\n    }\n    printer->setOrientation(orientation);\n    printer->setPaperSize(pageSize);\n    printer->setPageOrder(pageOrder2);\n    printer->setColorMode(colorMode2);\n    printer->setCopyCount(numCopies);\n\n    switch ((rangeCombo->itemData(rangeCombo->currentIndex())).toInt()){\n    case (int)QPrintDialog::AllPages:\n        q->setPrintRange(QPrintDialog::AllPages);\n        q->setFromTo(0, 0);\n        break;\n    case (int)QPrintDialog::Selection:\n        q->setPrintRange(QPrintDialog::Selection);\n        q->setFromTo(0, 0);\n        break;\n    case (int)QPrintDialog::PageRange:\n        q->setPrintRange(QPrintDialog::PageRange);\n        q->setFromTo(firstPage->value(), lastPage->value());\n        break;\n    case (int)QPrintDialog::CurrentPage:\n        q->setPrintRange(QPrintDialog::CurrentPage);\n        q->setFromTo(0, 0);\n        break;\n    }\n    q->accept();\n}\n\nvoid QPrintDialogPrivate::_q_printerOrFileSelected(QAbstractButton *b)\n{\n    outputToFile = (b == printToFileButton);\n    if (outputToFile) {\n        _q_fileNameEditChanged(fileName->text());\n        if (!fileName->isModified() && fileName->text().isEmpty()) {\n            QString file = \"print.tiff\";\n            fileName->setText(file);\n            fileName->setCursorPosition(file.length());\n            fileName->selectAll();\n            fileName->setModified(true); // confirm overwrite when OK clicked\n\n        }\n        fileName->setEnabled(true);\n        fileName->setFocus();\n    } else {\n        fileName->setText(QString());\n        if (fileName->isEnabled())\n            fileName->setEnabled(false);\n    }\n}\n\nvoid QPrintDialogPrivate::_q_paperSizeSelected(int id)\n{\n    if (id < QPrinter::NPaperSize)\n        pageSize = QPrinter::PaperSize(indexToPaperSize[id]);\n}\n\nvoid QPrintDialogPrivate::_q_orientSelected(int id)\n{\n    orientation = (QPrinter::Orientation)id;\n}\n\nvoid QPrintDialogPrivate::_q_pageOrderSelected(int id)\n{\n    pageOrder2 = (QPrinter::PageOrder)id;\n}\n\nvoid QPrintDialogPrivate::_q_colorModeSelected(QAbstractButton *b)\n{\n    colorMode2 = (b == printColor) ? QPrinter::Color : QPrinter::GrayScale;\n}\n\nvoid QPrintDialogPrivate::_q_setNumCopies(int copies)\n{\n    numCopies = copies;\n}\n\nvoid QPrintDialogPrivate::_q_printRangeSelected(int id)\n{\n    bool enable = (rangeCombo->itemData(id).toInt() == (int)QPrintDialog::PageRange);\n    firstPage->setEnabled(enable);\n    lastPage->setEnabled(enable);\n}\n\nvoid QPrintDialogPrivate::_q_setFirstPage(int fp)\n{\n    Q_Q(QPrintDialog);\n    if (printer) {\n        lastPage->setMinimum(fp);\n        lastPage->setMaximum(qMax(fp, q->maxPage()));\n    }\n}\n\nvoid QPrintDialogPrivate::_q_setLastPage(int lp)\n{\n    Q_Q(QPrintDialog);\n    if (printer) {\n        firstPage->setMinimum(qMin(lp, q->minPage()));\n        firstPage->setMaximum(lp);\n    }\n}\n\nvoid QPrintDialogPrivate::_q_fileNameEditChanged(const QString &text)\n{\n    Q_UNUSED(text);\n}\n\nvoid QPrintDialogPrivate::setupDestination()\n{\n    Q_Q(QPrintDialog);\n\n    // print destinations\n    printerOrFile = new QButtonGroup(q);\n    QObject::connect(printerOrFile, SIGNAL(buttonClicked(QAbstractButton*)),\n            q, SLOT(_q_printerOrFileSelected(QAbstractButton*)));\n\n    printToPrinterButton = q->findChild<QRadioButton *>(\"printToPrinterButton\");\n    printerOrFile->addButton(printToPrinterButton);\n    printToFileButton = q->findChild<QRadioButton *>(\"printToFileButton\");\n    printerOrFile->addButton(printToFileButton);\n\n    // file name\n    fileName = q->findChild<QLineEdit *>(\"fileName\");\n    QObject::connect(fileName, SIGNAL(textChanged(QString)),\n            q, SLOT(_q_fileNameEditChanged(QString)));\n\n    outputToFile = false;\n}\n\nvoid QPrintDialogPrivate::setupPrinterSettings()\n{\n    Q_Q(QPrintDialog);\n\n    // color mode\n    colorMode = new QButtonGroup(q);\n    QObject::connect(colorMode, SIGNAL(buttonClicked(QAbstractButton*)),\n        q, SLOT(_q_colorModeSelected(QAbstractButton*)));\n\n    printColor = q->findChild<QRadioButton *>(\"printColor\");\n    colorMode->addButton(printColor);\n    printGray = q->findChild<QRadioButton *>(\"printGray\");\n    colorMode->addButton(printGray);\n}\n\nvoid isc(QPrintDialogPrivate *ptr, const QString & text, QPrinter::PaperSize ps)\n{\n    if (ptr && !text.isEmpty() && ps < QPrinter::NPaperSize) {\n        ptr->sizeCombo->addItem(text);\n        int index = ptr->sizeCombo->count()-1;\n        if (index >= 0 && index < QPrinter::NPaperSize)\n            ptr->indexToPaperSize[index] = ps;\n    }\n}\n\nvoid QPrintDialogPrivate::setupPaper()\n{\n    Q_Q(QPrintDialog);\n\n    pageSize = QPrinter::A4;\n\n    // paper orientation\n    orientationCombo = q->findChild<QComboBox *>(\"orientationCombo\");\n    orientation = QPrinter::Portrait;\n    QObject::connect(orientationCombo, SIGNAL(activated(int)),\n            q, SLOT(_q_orientSelected(int)));\n\n    // paper size\n    sizeCombo = q->findChild<QComboBox *>(\"sizeCombo\");\n\n    int n;\n    for(n=0; n<QPrinter::NPaperSize; n++)\n        indexToPaperSize[n] = QPrinter::A4;\n\n    isc(this, QPrintDialog::tr(\"A0 (841 x 1189 mm)\"), QPrinter::A0);\n    isc(this, QPrintDialog::tr(\"A1 (594 x 841 mm)\"), QPrinter::A1);\n    isc(this, QPrintDialog::tr(\"A2 (420 x 594 mm)\"), QPrinter::A2);\n    isc(this, QPrintDialog::tr(\"A3 (297 x 420 mm)\"), QPrinter::A3);\n    isc(this, QPrintDialog::tr(\"A4 (210 x 297 mm, 8.26 x 11.7 inches)\"), QPrinter::A4);\n    isc(this, QPrintDialog::tr(\"A5 (148 x 210 mm)\"), QPrinter::A5);\n    isc(this, QPrintDialog::tr(\"A6 (105 x 148 mm)\"), QPrinter::A6);\n    isc(this, QPrintDialog::tr(\"A7 (74 x 105 mm)\"), QPrinter::A7);\n    isc(this, QPrintDialog::tr(\"A8 (52 x 74 mm)\"), QPrinter::A8);\n    isc(this, QPrintDialog::tr(\"A9 (37 x 52 mm)\"), QPrinter::A9);\n    isc(this, QPrintDialog::tr(\"B0 (1000 x 1414 mm)\"), QPrinter::B0);\n    isc(this, QPrintDialog::tr(\"B1 (707 x 1000 mm)\"), QPrinter::B1);\n    isc(this, QPrintDialog::tr(\"B2 (500 x 707 mm)\"), QPrinter::B2);\n    isc(this, QPrintDialog::tr(\"B3 (353 x 500 mm)\"), QPrinter::B3);\n    isc(this, QPrintDialog::tr(\"B4 (250 x 353 mm)\"), QPrinter::B4);\n    isc(this, QPrintDialog::tr(\"B5 (176 x 250 mm, 6.93 x 9.84 inches)\"), QPrinter::B5);\n    isc(this, QPrintDialog::tr(\"B6 (125 x 176 mm)\"), QPrinter::B6);\n    isc(this, QPrintDialog::tr(\"B7 (88 x 125 mm)\"), QPrinter::B7);\n    isc(this, QPrintDialog::tr(\"B8 (62 x 88 mm)\"), QPrinter::B8);\n    isc(this, QPrintDialog::tr(\"B9 (44 x 62 mm)\"), QPrinter::B9);\n    isc(this, QPrintDialog::tr(\"B10 (31 x 44 mm)\"), QPrinter::B10);\n    isc(this, QPrintDialog::tr(\"C5E (163 x 229 mm)\"), QPrinter::C5E);\n    isc(this, QPrintDialog::tr(\"DLE (110 x 220 mm)\"), QPrinter::DLE);\n    isc(this, QPrintDialog::tr(\"Executive (7.5 x 10 inches, 191 x 254 mm)\"), QPrinter::Executive);\n    isc(this, QPrintDialog::tr(\"Folio (210 x 330 mm)\"), QPrinter::Folio);\n    isc(this, QPrintDialog::tr(\"Ledger (432 x 279 mm)\"), QPrinter::Ledger);\n    isc(this, QPrintDialog::tr(\"Legal (8.5 x 14 inches, 216 x 356 mm)\"), QPrinter::Legal);\n    isc(this, QPrintDialog::tr(\"Letter (8.5 x 11 inches, 216 x 279 mm)\"), QPrinter::Letter);\n    isc(this, QPrintDialog::tr(\"Tabloid (279 x 432 mm)\"), QPrinter::Tabloid);\n    isc(this, QPrintDialog::tr(\"US Common #10 Envelope (105 x 241 mm)\"), QPrinter::Comm10E);\n\n    QObject::connect(sizeCombo, SIGNAL(activated(int)),\n             q, SLOT(_q_paperSizeSelected(int)));\n}\n\nvoid QPrintDialogPrivate::setupOptions()\n{\n    Q_Q(QPrintDialog);\n\n    // no. of copies\n    copies = q->findChild<QSpinBox *>(\"copies\");\n    QObject::connect(copies, SIGNAL(valueChanged(int)),\n            q, SLOT(_q_setNumCopies(int)));\n\n    // print range\n    rangeCombo = q->findChild<QComboBox *>(\"rangeCombo\");\n    rangeCombo->addItem(QPrintDialog::tr(\"Print all\"), QPrintDialog::AllPages);\n    rangeCombo->addItem(QPrintDialog::tr(\"Print selection\"), QPrintDialog::Selection);\n    rangeCombo->addItem(QPrintDialog::tr(\"Print range\"), QPrintDialog::PageRange);\n    rangeCombo->addItem(QPrintDialog::tr(\"Print current page\"), QPrintDialog::CurrentPage);\n    QObject::connect(rangeCombo, SIGNAL(activated(int)),\n            q, SLOT(_q_printRangeSelected(int)));\n\n    // page range\n    firstPage = q->findChild<QSpinBox *>(\"firstPage\");\n    firstPage->setRange(1, 9999);\n    firstPage->setValue(1);\n    QObject::connect(firstPage, SIGNAL(valueChanged(int)),\n            q, SLOT(_q_setFirstPage(int)));\n\n    lastPage = q->findChild<QSpinBox *>(\"lastPage\");\n    lastPage->setRange(1, 9999);\n    lastPage->setValue(1);\n    QObject::connect(lastPage, SIGNAL(valueChanged(int)),\n            q, SLOT(_q_setLastPage(int)));\n\n    // print order\n    pageOrderCombo = q->findChild<QComboBox *>(\"pageOrderCombo\");\n    QObject::connect(pageOrderCombo, SIGNAL(activated(int)),\n            q, SLOT(_q_pageOrderSelected(int)));\n}\n\nbool QPrintDialog::eventFilter(QObject *o, QEvent *e)\n{\n    Q_UNUSED(o);\n\n    Q_D(QPrintDialog);\n    switch (e->type()){\n    case QEvent::KeyPress:\n        switch (static_cast<QKeyEvent*>(e)->key()) {\n        case Qt::Key_Back:\n            d->_q_okClicked();\n            return true;\n        }\n        break;\n    default:\n        break;\n    }\n    return false;\n}\n\nQPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)\n    : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)\n{\n    d_func()->init();\n}\n\nQPrintDialog::QPrintDialog(QWidget *parent)\n    : QAbstractPrintDialog(*(new QPrintDialogPrivate), 0, parent)\n{\n    d_func()->init();\n}\n\nQPrintDialog::~QPrintDialog()\n{\n}\n\nvoid QPrintDialogPrivate::setPrinter(QPrinter *p, bool pickUpSettings)\n{\n    Q_Q(QPrintDialog);\n    printer = p;\n\n    if (p && pickUpSettings) {\n        // top to bottom in the old dialog.\n        // printer or file\n        outputToFile = !p->outputFileName().isEmpty() && q->isOptionEnabled(QPrintDialog::PrintToFile);\n        if (outputToFile)\n            printToFileButton->setChecked(true);\n        else\n            printToPrinterButton->setChecked(true);\n        fileName->setEnabled(outputToFile);\n\n        // file name\n        if (q->isOptionEnabled(QPrintDialog::PrintToFile)) {\n            fileName->setText(p->outputFileName());\n            fileName->setModified(!fileName->text().isEmpty());\n        } else {\n            printToFileButton->setEnabled(false);\n        }\n\n        // orientation\n        orientationCombo->setCurrentIndex((int)p->orientation());\n        _q_orientSelected(p->orientation());\n\n        // page size\n        int n = 0;\n        while (n < QPrinter::NPaperSize &&\n                indexToPaperSize[n] != p->pageSize())\n            n++;\n        sizeCombo->setCurrentIndex(n);\n        _q_paperSizeSelected(n);\n\n        // page order\n        pageOrder2 = p->pageOrder();\n        pageOrderCombo->setCurrentIndex((int)pageOrder2);\n\n        // color mode\n        colorMode2 = p->colorMode();\n        if (colorMode2 == QPrinter::Color)\n            printColor->setChecked(true);\n        else\n            printGray->setChecked(true);\n\n        // number of copies\n        copies->setValue(p->copyCount());\n        _q_setNumCopies(p->copyCount());\n    }\n\n    if (p) {\n        if (!q->isOptionEnabled(QPrintDialog::PrintSelection)\n                && rangeCombo->findData(QPrintDialog::Selection) > 0)\n            rangeCombo->removeItem(rangeCombo->findData(QPrintDialog::Selection));\n        if (!q->isOptionEnabled(QPrintDialog::PrintPageRange)\n                && rangeCombo->findData(QPrintDialog::PageRange) > 0)\n            rangeCombo->removeItem(rangeCombo->findData(QPrintDialog::PageRange));\n        if (!q->isOptionEnabled(QPrintDialog::PrintCurrentPage)\n                && rangeCombo->findData(QPrintDialog::CurrentPage) > 0)\n            rangeCombo->removeItem(rangeCombo->findData(QPrintDialog::CurrentPage));\n\n        switch (q->printRange()) {\n        case QPrintDialog::AllPages:\n            rangeCombo->setCurrentIndex((int)(QPrintDialog::AllPages));\n            break;\n        case QPrintDialog::Selection:\n            rangeCombo->setCurrentIndex((int)(QPrintDialog::Selection));\n            break;\n        case QPrintDialog::PageRange:\n            rangeCombo->setCurrentIndex((int)(QPrintDialog::PageRange));\n            break;\n        case QPrintDialog::CurrentPage:\n            rangeCombo->setCurrentIndex((int)(QPrintDialog::CurrentPage));\n            break;\n        }\n    }\n\n    if (p && q->maxPage()) {\n        int from = q->minPage();\n        int to = q->maxPage();\n        if (q->printRange() == QPrintDialog::PageRange) {\n            from = q->fromPage();\n            to = q->toPage();\n        }\n        firstPage->setRange(q->minPage(), to);\n        lastPage->setRange(from, q->maxPage());\n        firstPage->setValue(from);\n        lastPage->setValue(to);\n    }\n}\n\nint QPrintDialog::exec()\n{\n    Q_D(QPrintDialog);\n    d->setPrinter(d->printer, true);\n    return QDialog::exec();\n}\n\nvoid QPrintDialogPrivate::init()\n{\n    Q_Q(QPrintDialog);\n    numCopies = 1;\n\n    if (_qt_print_dialog_creator)\n        (*_qt_print_dialog_creator)(q);\n\n    setupDestination();\n    setupPrinterSettings();\n    setupPaper();\n    setupOptions();\n\n    setPrinter(printer, true);\n\n    q->installEventFilter(q);\n}\n\nvoid QPrintDialog::setVisible(bool visible)\n{\n    QAbstractPrintDialog::setVisible(visible);\n}\n\nQT_END_NAMESPACE\n\n#include \"moc_qprintdialog.cpp\"\n#include \"qrc_qprintdialog.cpp\"\n\n#endif // QT_NO_PRINTDIALOG\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qprintdialog_unix.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include \"qplatformdefs.h\"\n#include <QtPrintSupport/private/qtprintsupportglobal_p.h>\n\n#include \"private/qabstractprintdialog_p.h\"\n#if QT_CONFIG(messagebox)\n#include <QtWidgets/qmessagebox.h>\n#endif\n#include \"qprintdialog.h\"\n#if QT_CONFIG(filedialog)\n#include \"qfiledialog.h\"\n#endif\n#include <QtCore/qdebug.h>\n#include <QtCore/qdir.h>\n#include <QtCore/qglobal.h>\n#include <QtCore/qstringconverter.h>\n#include <QtGui/qevent.h>\n#if QT_CONFIG(filesystemmodel)\n#include <QtGui/qfilesystemmodel.h>\n#endif\n#include <QtWidgets/qstyleditemdelegate.h>\n#include <QtWidgets/qformlayout.h>\n#include <QtPrintSupport/qprinter.h>\n\n#include <qpa/qplatformprintplugin.h>\n#include <qpa/qplatformprintersupport.h>\n\n#include <private/qprintdevice_p.h>\n\n#include <QtWidgets/qdialogbuttonbox.h>\n\n#if QT_CONFIG(regularexpression)\n#include <qregularexpression.h>\n#endif\n\n#if QT_CONFIG(completer)\n#include <private/qcompleter_p.h>\n#endif\n#include \"ui_qprintpropertieswidget.h\"\n#include \"ui_qprintsettingsoutput.h\"\n#include \"ui_qprintwidget.h\"\n\n#if QT_CONFIG(cups)\nQ_DECLARE_METATYPE(const ppd_option_t *)\n#include <private/qcups_p.h>\n#if QT_CONFIG(cupsjobwidget)\n#include \"qcupsjobwidget_p.h\"\n#endif\n#endif\n\n/*\n\nPrint dialog class declarations\n\n    QPrintDialog:            The main Print Dialog, nothing really held here.\n\n    QUnixPrintWidget:\n    QUnixPrintWidgetPrivate: The real Unix Print Dialog implementation.\n\n                             Directly includes the upper half of the Print Dialog\n                             containing the Printer Selection widgets and\n                             Properties button.\n\n                             Embeds the Properties pop-up dialog from\n                             QPrintPropertiesDialog\n\n                             Embeds the lower half from separate widget class\n                             QPrintDialogPrivate\n\n                             Layout in qprintwidget.ui\n\n    QPrintDialogPrivate:     The lower half of the Print Dialog containing the\n                             Copies and Options tabs that expands when the\n                             Options button is selected.\n\n                             Layout in qprintsettingsoutput.ui\n\n    QPrintPropertiesDialog:  Dialog displayed when clicking on Properties button to\n                             allow editing of Page and Advanced tabs.\n\n                             Layout in qprintpropertieswidget.ui\n*/\n\nstatic void _q_pdu_initResources()\n{\n    Q_INIT_RESOURCE(qprintdialog);\n}\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\nclass QPrintPropertiesDialog : public QDialog\n{\n    Q_OBJECT\npublic:\n    QPrintPropertiesDialog(QPrinter *printer, QPrintDevice *currentPrintDevice,\n                           QPrinter::OutputFormat outputFormat, const QString &printerName,\n                           QAbstractPrintDialog *parent);\n    ~QPrintPropertiesDialog();\n\n    void setupPrinter() const;\n\nprivate slots:\n    void reject() override;\n    void accept() override;\n\nprivate:\n    void showEvent(QShowEvent *event) override;\n\n    friend class QUnixPrintWidgetPrivate;\n#if QT_CONFIG(cups)\n    QPrinter *m_printer;\n#endif\n    Ui::QPrintPropertiesWidget widget;\n    QDialogButtonBox *m_buttons;\n#if QT_CONFIG(cupsjobwidget)\n    QCupsJobWidget *m_jobOptions;\n#endif\n\n#if QT_CONFIG(cups)\n    bool createAdvancedOptionsWidget();\n    void setPrinterAdvancedCupsOptions() const;\n    void revertAdvancedOptionsToSavedValues() const;\n    void advancedOptionsUpdateSavedValues() const;\n    bool anyPpdOptionConflict() const;\n    bool anyAdvancedOptionConflict() const;\n\n    QPrintDevice *m_currentPrintDevice;\n\n    QStringDecoder toUnicode;\n    QList<QComboBox*> m_advancedOptionsCombos;\n#endif\n};\n\nclass QUnixPrintWidgetPrivate;\n\nclass QUnixPrintWidget : public QWidget\n{\n    Q_OBJECT\n\npublic:\n    explicit QUnixPrintWidget(QPrinter *printer, QWidget *parent = nullptr);\n    ~QUnixPrintWidget();\n    void updatePrinter();\n\nprivate:\n    friend class QPrintDialog;\n    friend class QPrintDialogPrivate;\n    friend class QUnixPrintWidgetPrivate;\n    QUnixPrintWidgetPrivate *d;\n    Q_PRIVATE_SLOT(d, void _q_printerChanged(int))\n    Q_PRIVATE_SLOT(d, void _q_btnBrowseClicked())\n    Q_PRIVATE_SLOT(d, void _q_btnPropertiesClicked())\n};\n\nclass QUnixPrintWidgetPrivate\n{\npublic:\n    QUnixPrintWidgetPrivate(QUnixPrintWidget *q, QPrinter *prn);\n    ~QUnixPrintWidgetPrivate();\n\n    bool checkFields();\n    void setupPrinter();\n    void setOptionsPane(QPrintDialogPrivate *pane);\n    void setupPrinterProperties();\n// slots\n    void _q_printerChanged(int index);\n    void _q_btnPropertiesClicked();\n    void _q_btnBrowseClicked();\n\n    QUnixPrintWidget * const parent;\n    QPrintPropertiesDialog *propertiesDialog;\n    Ui::QPrintWidget widget;\n    QPrintDialog * q;\n    QPrinter *printer;\n    QPrintDevice m_currentPrintDevice;\n\n    void updateWidget();\n\n#if QT_CONFIG(cups)\n    void setPpdDuplex(QPrinter::DuplexMode mode);\n    ppd_option_t *m_duplexPpdOption;\n#endif\n\nprivate:\n    QPrintDialogPrivate *optionsPane;\n    bool filePrintersAdded;\n};\n\nclass QPrintDialogPrivate : public QAbstractPrintDialogPrivate\n{\n    Q_DECLARE_PUBLIC(QPrintDialog)\n    Q_DECLARE_TR_FUNCTIONS(QPrintDialog)\npublic:\n    QPrintDialogPrivate();\n    ~QPrintDialogPrivate();\n\n    void init();\n\n    void selectPrinter(const QPrinter::OutputFormat outputFormat);\n\n    void _q_togglePageSetCombo(bool);\n#if QT_CONFIG(messagebox)\n    void _q_checkFields();\n#endif\n    void _q_collapseOrExpandDialog();\n\n#if QT_CONFIG(cups)\n    void updatePpdDuplexOption(QRadioButton *radio);\n#endif\n    void setupPrinter();\n    void updateWidgets();\n\n    virtual void setTabs(const QList<QWidget*> &tabs) override;\n\n    Ui::QPrintSettingsOutput options;\n    QUnixPrintWidget *top;\n    QWidget *bottom;\n    QDialogButtonBox *buttons;\n    QPushButton *collapseButton;\n    QPrinter::OutputFormat printerOutputFormat;\nprivate:\n    void setExplicitDuplexMode(QPrint::DuplexMode duplexMode);\n    // duplex mode explicitly set by user, QPrint::DuplexAuto otherwise\n    QPrint::DuplexMode explicitDuplexMode;\n};\n\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n\n/*\n\n    QPrintPropertiesDialog\n\n    Dialog displayed when clicking on Properties button to allow editing of Page\n    and Advanced tabs.\n\n*/\n\nQPrintPropertiesDialog::QPrintPropertiesDialog(QPrinter *printer, QPrintDevice *currentPrintDevice,\n                                               QPrinter::OutputFormat outputFormat, const QString &printerName,\n                                               QAbstractPrintDialog *parent)\n    : QDialog(parent)\n#if QT_CONFIG(cups)\n    , m_printer(printer)\n#endif\n{\n    setWindowTitle(tr(\"Printer Properties\"));\n    QVBoxLayout *lay = new QVBoxLayout(this);\n    QWidget *content = new QWidget(this);\n    widget.setupUi(content);\n    m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);\n    lay->addWidget(content);\n    lay->addWidget(m_buttons);\n\n    connect(m_buttons->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &QPrintPropertiesDialog::accept);\n    connect(m_buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &QPrintPropertiesDialog::reject);\n\n    widget.pageSetup->setPrinter(printer, currentPrintDevice, outputFormat, printerName);\n\n#if QT_CONFIG(cupsjobwidget)\n    m_jobOptions = new QCupsJobWidget(printer, currentPrintDevice);\n    widget.tabs->insertTab(1, m_jobOptions, tr(\"Job Options\"));\n#endif\n\n    const int advancedTabIndex = widget.tabs->indexOf(widget.cupsPropertiesPage);\n#if QT_CONFIG(cups)\n    m_currentPrintDevice = currentPrintDevice;\n    const bool anyWidgetCreated = createAdvancedOptionsWidget();\n\n    widget.tabs->setTabEnabled(advancedTabIndex, anyWidgetCreated);\n\n    connect(widget.pageSetup, &QPageSetupWidget::ppdOptionChanged, this, [this] {\n        widget.conflictsLabel->setVisible(anyPpdOptionConflict());\n    });\n\n#else\n    Q_UNUSED(currentPrintDevice);\n    widget.tabs->setTabEnabled(advancedTabIndex, false);\n#endif\n}\n\nQPrintPropertiesDialog::~QPrintPropertiesDialog()\n{\n}\n\nvoid QPrintPropertiesDialog::setupPrinter() const\n{\n#if QT_CONFIG(cups)\n    QCUPSSupport::clearCupsOptions(m_printer);\n#endif\n\n    widget.pageSetup->setupPrinter();\n#if QT_CONFIG(cupsjobwidget)\n    m_jobOptions->setupPrinter();\n#endif\n\n#if QT_CONFIG(cups)\n    // Set Color by default, that will change if the \"ColorModel\" property is available\n    m_printer->setColorMode(QPrinter::Color);\n\n    setPrinterAdvancedCupsOptions();\n#endif\n}\n\nvoid QPrintPropertiesDialog::reject()\n{\n    widget.pageSetup->revertToSavedValues();\n\n#if QT_CONFIG(cupsjobwidget)\n    m_jobOptions->revertToSavedValues();\n#endif\n\n#if QT_CONFIG(cups)\n    revertAdvancedOptionsToSavedValues();\n#endif\n    QDialog::reject();\n}\n\nvoid QPrintPropertiesDialog::accept()\n{\n#if QT_CONFIG(cups) && QT_CONFIG(messagebox)\n    if (widget.pageSetup->hasPpdConflict()) {\n        widget.tabs->setCurrentWidget(widget.tabPage);\n        const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr(\"Page Setup Conflicts\"),\n                                                                        tr(\"There are conflicts in page setup options. Do you want to fix them?\"),\n                                                                        QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);\n        if (answer != QMessageBox::No)\n            return;\n    } else if (anyAdvancedOptionConflict()) {\n        widget.tabs->setCurrentWidget(widget.cupsPropertiesPage);\n        const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr(\"Advanced Option Conflicts\"),\n                                                                        tr(\"There are conflicts in some advanced options. Do you want to fix them?\"),\n                                                                        QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);\n        if (answer != QMessageBox::No)\n            return;\n    }\n    advancedOptionsUpdateSavedValues();\n#endif\n\n#if QT_CONFIG(cupsjobwidget)\n    m_jobOptions->updateSavedValues();\n#endif\n\n    widget.pageSetup->updateSavedValues();\n\n    QDialog::accept();\n}\n\nvoid QPrintPropertiesDialog::showEvent(QShowEvent *event)\n{\n#if QT_CONFIG(cups)\n    widget.conflictsLabel->setVisible(anyPpdOptionConflict());\n#endif\n    QDialog::showEvent(event);\n}\n\n#if QT_CONFIG(cups)\n\n// Used to store the ppd_option_t for each QComboBox that represents an advanced option\nstatic const char *ppdOptionProperty = \"_q_ppd_option\";\n\n// Used to store the originally selected choice index for each QComboBox that represents an advanced option\nstatic const char *ppdOriginallySelectedChoiceProperty = \"_q_ppd_originally_selected_choice\";\n\n// Used to store the warning label pointer for each QComboBox that represents an advanced option\nstatic const char *warningLabelProperty = \"_q_warning_label\";\n\nstatic bool isBlacklistedGroup(const ppd_group_t *group) noexcept\n{\n    return qstrcmp(group->name, \"InstallableOptions\") == 0;\n};\n\nstatic bool isBlacklistedOption(const char *keyword) noexcept\n{\n    // We already let the user set these options elsewhere\n    const char *cupsOptionBlacklist[] = {\n        \"Collate\",\n        \"Copies\",\n        \"OutputOrder\",\n        \"PageRegion\",\n        \"PageSize\",\n        \"Duplex\" // handled by the main dialog\n    };\n    auto equals = [](const char *keyword) {\n        return [keyword](const char *candidate) {\n            return qstrcmp(keyword, candidate) == 0;\n        };\n    };\n    return std::any_of(std::begin(cupsOptionBlacklist), std::end(cupsOptionBlacklist), equals(keyword));\n};\n\nbool QPrintPropertiesDialog::createAdvancedOptionsWidget()\n{\n    bool anyWidgetCreated = false;\n\n    ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(m_currentPrintDevice->property(PDPK_PpdFile));\n\n    if (ppd) {\n        toUnicode = QStringDecoder(ppd->lang_encoding, QStringDecoder::Flag::Stateless);\n        if (!toUnicode.isValid()) {\n            qWarning() << \"QPrinSupport: Cups uses unsupported encoding\" << ppd->lang_encoding;\n            toUnicode = QStringDecoder(QStringDecoder::Utf8, QStringDecoder::Flag::Stateless);\n        }\n\n        QWidget *holdingWidget = new QWidget();\n        QVBoxLayout *layout = new QVBoxLayout(holdingWidget);\n\n        for (int i = 0; i < ppd->num_groups; ++i) {\n            const ppd_group_t *group = &ppd->groups[i];\n\n            if (!isBlacklistedGroup(group)) {\n                QFormLayout *groupLayout = new QFormLayout();\n\n                for (int i = 0; i < group->num_options; ++i) {\n                    const ppd_option_t *option = &group->options[i];\n\n                    if (!isBlacklistedOption(option->keyword)) {\n                        QComboBox *choicesCb = new QComboBox();\n\n                        const auto setPpdOptionFromCombo = [this, choicesCb, option] {\n                            // We can't use choicesCb->currentIndex() to know the index of the option in the choices[] array\n                            // because some of them may not be present in the list because they conflict with the\n                            // installable options so use the index passed on addItem\n                            const int selectedChoiceIndex = choicesCb->currentData().toInt();\n                            const auto values = QStringList{} << QString::fromLatin1(option->keyword)\n                                                                << QString::fromLatin1(option->choices[selectedChoiceIndex].choice);\n                            m_currentPrintDevice->setProperty(PDPK_PpdOption, values);\n                            widget.conflictsLabel->setVisible(anyPpdOptionConflict());\n                        };\n\n                        bool foundMarkedChoice = false;\n                        bool markedChoiceNotAvailable = false;\n                        for (int i = 0; i < option->num_choices; ++i) {\n                            const ppd_choice_t *choice = &option->choices[i];\n                            const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(choice->choice);\n                            const bool choiceIsInstallableConflict = m_currentPrintDevice->isFeatureAvailable(PDPK_PpdChoiceIsInstallableConflict, values);\n                            if (choiceIsInstallableConflict && static_cast<int>(choice->marked) == 1) {\n                                markedChoiceNotAvailable = true;\n                            } else if (!choiceIsInstallableConflict) {\n                                choicesCb->addItem(toUnicode(choice->text), i);\n                                if (static_cast<int>(choice->marked) == 1) {\n                                    choicesCb->setCurrentIndex(choicesCb->count() - 1);\n                                    choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));\n                                    foundMarkedChoice = true;\n                                } else if (!foundMarkedChoice && qstrcmp(choice->choice, option->defchoice) == 0) {\n                                    choicesCb->setCurrentIndex(choicesCb->count() - 1);\n                                    choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));\n                                }\n                            }\n                        }\n\n                        if (markedChoiceNotAvailable) {\n                            // If the user default option is not available because of it conflicting with\n                            // the installed options, we need to set the internal ppd value to the value\n                            // being shown in the combo\n                            setPpdOptionFromCombo();\n                        }\n\n                        if (choicesCb->count() > 1) {\n\n                            connect(choicesCb, &QComboBox::currentIndexChanged, this, setPpdOptionFromCombo);\n\n                            // We need an extra label at the end to show the conflict warning\n                            QWidget *choicesCbWithLabel = new QWidget();\n                            QHBoxLayout *choicesCbWithLabelLayout = new QHBoxLayout(choicesCbWithLabel);\n                            choicesCbWithLabelLayout->setContentsMargins(0, 0, 0, 0);\n                            QLabel *warningLabel = new QLabel();\n                            choicesCbWithLabelLayout->addWidget(choicesCb);\n                            choicesCbWithLabelLayout->addWidget(warningLabel);\n\n                            QLabel *optionLabel = new QLabel(toUnicode(option->text));\n                            groupLayout->addRow(optionLabel, choicesCbWithLabel);\n                            anyWidgetCreated = true;\n                            choicesCb->setProperty(ppdOptionProperty, QVariant::fromValue(option));\n                            choicesCb->setProperty(warningLabelProperty, QVariant::fromValue(warningLabel));\n                            m_advancedOptionsCombos << choicesCb;\n                        } else {\n                            delete choicesCb;\n                        }\n                    }\n                }\n\n                if (groupLayout->rowCount() > 0) {\n                    QGroupBox *groupBox = new QGroupBox(toUnicode(group->text));\n                    groupBox->setLayout(groupLayout);\n                    layout->addWidget(groupBox);\n                } else {\n                    delete groupLayout;\n                }\n            }\n        }\n\n        layout->addStretch();\n        widget.scrollArea->setWidget(holdingWidget);\n    }\n\n    return anyWidgetCreated;\n}\n\nvoid QPrintPropertiesDialog::setPrinterAdvancedCupsOptions() const\n{\n    for (const QComboBox *choicesCb : m_advancedOptionsCombos) {\n        const ppd_option_t *option = qvariant_cast<const ppd_option_t *>(choicesCb->property(ppdOptionProperty));\n\n        // We can't use choicesCb->currentIndex() to know the index of the option in the choices[] array\n        // because some of them may not be present in the list because they conflict with the\n        // installable options so use the index passed on addItem\n        const int selectedChoiceIndex = choicesCb->currentData().toInt();\n        const char *selectedChoice = option->choices[selectedChoiceIndex].choice;\n\n        if (qstrcmp(option->keyword, \"ColorModel\") == 0)\n            m_printer->setColorMode(qstrcmp(selectedChoice, \"Gray\") == 0 ? QPrinter::GrayScale : QPrinter::Color);\n\n        if (qstrcmp(option->defchoice, selectedChoice) != 0)\n            QCUPSSupport::setCupsOption(m_printer, QString::fromLatin1(option->keyword), QString::fromLatin1(selectedChoice));\n    }\n}\n\nvoid QPrintPropertiesDialog::revertAdvancedOptionsToSavedValues() const\n{\n    for (QComboBox *choicesCb : m_advancedOptionsCombos) {\n        const int originallySelectedChoice = qvariant_cast<int>(choicesCb->property(ppdOriginallySelectedChoiceProperty));\n        const int newComboIndexToSelect = choicesCb->findData(originallySelectedChoice);\n        choicesCb->setCurrentIndex(newComboIndexToSelect);\n        // The currentIndexChanged lambda takes care of resetting the ppd option\n    }\n    widget.conflictsLabel->setVisible(anyPpdOptionConflict());\n}\n\nvoid QPrintPropertiesDialog::advancedOptionsUpdateSavedValues() const\n{\n    for (QComboBox *choicesCb : m_advancedOptionsCombos)\n        choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, choicesCb->currentData());\n}\n\nbool QPrintPropertiesDialog::anyPpdOptionConflict() const\n{\n    // we need to execute both since besides returning true/false they update the warning icons\n    const bool pageSetupConflicts = widget.pageSetup->hasPpdConflict();\n    const bool advancedOptionConflicts = anyAdvancedOptionConflict();\n    return pageSetupConflicts || advancedOptionConflicts;\n}\n\nbool QPrintPropertiesDialog::anyAdvancedOptionConflict() const\n{\n    const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr);\n\n    bool anyConflicted = false;\n\n    for (const QComboBox *choicesCb : m_advancedOptionsCombos) {\n        const ppd_option_t *option = qvariant_cast<const ppd_option_t *>(choicesCb->property(ppdOptionProperty));\n        QLabel *warningLabel = qvariant_cast<QLabel *>(choicesCb->property(warningLabelProperty));\n        if (option->conflicted) {\n            anyConflicted = true;\n            const int pixmap_size = choicesCb->sizeHint().height() * .75;\n            warningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));\n        } else {\n            warningLabel->setPixmap(QPixmap());\n        }\n    }\n\n    return anyConflicted;\n}\n\n#endif\n\n\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n\n/*\n\n    QPrintDialogPrivate\n\n    The lower half of the Print Dialog containing the Copies and Options\n    tabs that expands when the Options button is selected.\n\n*/\nQPrintDialogPrivate::QPrintDialogPrivate()\n    : top(nullptr), bottom(nullptr), buttons(nullptr), collapseButton(nullptr),\n      explicitDuplexMode(QPrint::DuplexAuto)\n{\n    _q_pdu_initResources();\n}\n\nQPrintDialogPrivate::~QPrintDialogPrivate()\n{\n}\n\nvoid QPrintDialogPrivate::init()\n{\n    Q_Q(QPrintDialog);\n\n    top = new QUnixPrintWidget(q->printer(), q);\n    bottom = new QWidget(q);\n    options.setupUi(bottom);\n    options.color->setIconSize(QSize(32, 32));\n    options.color->setIcon(QIcon(\":/qt-project.org/dialogs/qprintdialog/images/status-color.png\"_L1));\n    options.grayscale->setIconSize(QSize(32, 32));\n    options.grayscale->setIcon(QIcon(\":/qt-project.org/dialogs/qprintdialog/images/status-gray-scale.png\"_L1));\n\n#if QT_CONFIG(cups)\n    // Add Page Set widget if CUPS is available\n    options.pageSetCombo->addItem(tr(\"All Pages\"), QVariant::fromValue(QCUPSSupport::AllPages));\n    options.pageSetCombo->addItem(tr(\"Odd Pages\"), QVariant::fromValue(QCUPSSupport::OddPages));\n    options.pageSetCombo->addItem(tr(\"Even Pages\"), QVariant::fromValue(QCUPSSupport::EvenPages));\n#else\n    delete options.pagesRadioButton;\n    delete options.pagesLineEdit;\n    options.pagesRadioButton = nullptr;\n    options.pagesLineEdit = nullptr;\n#endif\n\n    top->d->setOptionsPane(this);\n\n    buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);\n    collapseButton = new QPushButton(QPrintDialog::tr(\"&Options >>\"), buttons);\n    buttons->addButton(collapseButton, QDialogButtonBox::ResetRole);\n    bottom->setVisible(false);\n\n    QPushButton *printButton = buttons->button(QDialogButtonBox::Ok);\n    printButton->setText(QPrintDialog::tr(\"&Print\"));\n    printButton->setDefault(true);\n\n    QVBoxLayout *lay = new QVBoxLayout(q);\n    lay->addWidget(top);\n    lay->addWidget(bottom);\n    lay->addWidget(buttons);\n\n#if !QT_CONFIG(messagebox)\n    QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));\n#else\n    QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(_q_checkFields()));\n#endif\n    QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));\n\n    QObject::connect(options.printSelection, SIGNAL(toggled(bool)),\n                     q, SLOT(_q_togglePageSetCombo(bool)));\n\n    QObject::connect(options.printCurrentPage, SIGNAL(toggled(bool)),\n                     q, SLOT(_q_togglePageSetCombo(bool)));\n\n    QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));\n\n    QObject::connect(options.noDuplex, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexNone); });\n    QObject::connect(options.duplexLong, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexLongSide); });\n    QObject::connect(options.duplexShort, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexShortSide); });\n\n#if QT_CONFIG(cups)\n    QObject::connect(options.noDuplex, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.noDuplex); });\n    QObject::connect(options.duplexLong, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.duplexLong); });\n    QObject::connect(options.duplexShort, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.duplexShort); });\n#endif\n}\n\n// initialize printer options\nvoid QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputFormat)\n{\n        Q_Q(QPrintDialog);\n        QPrinter *p = q->printer();\n        printerOutputFormat = outputFormat;\n\n        // printer supports duplex mode?\n        const auto supportedDuplexMode = top->d->m_currentPrintDevice.supportedDuplexModes();\n        options.duplexLong->setEnabled(supportedDuplexMode.contains(QPrint::DuplexLongSide));\n        options.duplexShort->setEnabled(supportedDuplexMode.contains(QPrint::DuplexShortSide));\n\n        if (p->colorMode() == QPrinter::Color)\n            options.color->setChecked(true);\n        else\n            options.grayscale->setChecked(true);\n\n        // duplex priorities to be as follows:\n        // 1) a user-selected duplex value in the dialog has highest priority\n        // 2) duplex value set in the QPrinter\n        QPrint::DuplexMode duplex;\n        if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))\n            duplex = explicitDuplexMode;\n        else\n            duplex = static_cast<QPrint::DuplexMode>(p->duplex());\n        switch (duplex) {\n        case QPrint::DuplexNone:\n            options.noDuplex->setChecked(true); break;\n        case QPrint::DuplexLongSide:\n        case QPrint::DuplexAuto:\n            options.duplexLong->setChecked(true); break;\n        case QPrint::DuplexShortSide:\n            options.duplexShort->setChecked(true); break;\n        }\n        options.copies->setValue(p->copyCount());\n        options.collate->setChecked(p->collateCopies());\n        options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);\n\n        if (outputFormat == QPrinter::PdfFormat || options.printSelection->isChecked()\n            || options.printCurrentPage->isChecked())\n\n            options.pageSetCombo->setEnabled(false);\n        else\n            options.pageSetCombo->setEnabled(true);\n\n#if QT_CONFIG(cups)\n        // Disable complex page ranges widget when printing to pdf\n        // It doesn't work since it relies on cups to do the heavy lifting and cups\n        // is not used when printing to PDF\n        options.pagesRadioButton->setEnabled(outputFormat != QPrinter::PdfFormat);\n\n        // Disable color options on main dialog if not printing to file, it will be handled by CUPS advanced dialog\n        options.colorMode->setVisible(outputFormat == QPrinter::PdfFormat);\n#endif\n}\n\n#if QT_CONFIG(cups)\n\nvoid QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)\n{\n    const bool checked = radio->isChecked();\n    if (checked) {\n        if (radio == options.noDuplex) top->d->setPpdDuplex(QPrinter::DuplexNone);\n        else if (radio == options.duplexLong) top->d->setPpdDuplex(QPrinter::DuplexLongSide);\n        else if (radio == options.duplexShort) top->d->setPpdDuplex(QPrinter::DuplexShortSide);\n    }\n    const bool conflict = checked && top->d->m_duplexPpdOption && top->d->m_duplexPpdOption->conflicted;\n    radio->setIcon(conflict ? QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr) : QIcon());\n}\n\n#endif\n\nvoid QPrintDialogPrivate::setExplicitDuplexMode(const QPrint::DuplexMode duplexMode)\n{\n    explicitDuplexMode = duplexMode;\n}\n\nvoid QPrintDialogPrivate::setupPrinter()\n{\n    // First setup the requested OutputFormat, Printer and Page Size first\n    top->d->setupPrinter();\n\n    // Then setup Print Job options\n    Q_Q(QPrintDialog);\n    QPrinter* p = q->printer();\n\n    if (options.duplex->isEnabled()) {\n        if (options.noDuplex->isChecked())\n            p->setDuplex(QPrinter::DuplexNone);\n        else if (options.duplexLong->isChecked())\n            p->setDuplex(QPrinter::DuplexLongSide);\n        else\n            p->setDuplex(QPrinter::DuplexShortSide);\n    }\n\n#if QT_CONFIG(cups)\n    // When printing to a device the colorMode will be set by the advanced panel\n    if (p->outputFormat() == QPrinter::PdfFormat)\n#endif\n        p->setColorMode(options.color->isChecked() ? QPrinter::Color : QPrinter::GrayScale);\n\n    p->setPageOrder(options.reverse->isChecked() ? QPrinter::LastPageFirst : QPrinter::FirstPageFirst);\n\n    // print range\n    if (options.printAll->isChecked()) {\n        p->setPrintRange(QPrinter::AllPages);\n        p->setPageRanges(QPageRanges());\n    } else if (options.printSelection->isChecked()) {\n        p->setPrintRange(QPrinter::Selection);\n        p->setPageRanges(QPageRanges());\n    } else if (options.printCurrentPage->isChecked()) {\n        p->setPrintRange(QPrinter::CurrentPage);\n        p->setPageRanges(QPageRanges());\n    } else if (options.printRange->isChecked()) {\n        if (q->testOption(QPrintDialog::PrintPageRange)) {\n            p->setPrintRange(QPrinter::PageRange);\n            p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));\n        } else {\n            // This case happens when CUPS server-side page range is enabled\n            // Setting the range to the printer occurs below\n            p->setPrintRange(QPrinter::AllPages);\n            p->setPageRanges(QPageRanges());\n        }\n    }\n\n#if QT_CONFIG(cups)\n    if (options.pagesRadioButton->isChecked()) {\n        const QPageRanges ranges = QPageRanges::fromString(options.pagesLineEdit->text());\n        if (!ranges.isEmpty()) {\n            p->setPrintRange(QPrinter::PageRange);\n            p->setPageRanges(ranges);\n        }\n\n        // server-side page filtering\n        QCUPSSupport::setPageRange(p, ranges.toString());\n    }\n\n    // page set\n    if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) {\n        //If the application is selecting pages and the first page number is even then need to adjust the odd-even accordingly\n        QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(options.pageSetCombo->itemData(options.pageSetCombo->currentIndex()));\n        if (q->testOption(QPrintDialog::PrintPageRange)\n            && p->printRange() == QPrinter::PageRange\n            && (q->fromPage() % 2 == 0)) {\n\n            switch (pageSet) {\n            case QCUPSSupport::AllPages:\n                break;\n            case QCUPSSupport::OddPages:\n                QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages);\n                break;\n            case QCUPSSupport::EvenPages:\n                QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages);\n                break;\n            }\n        } else if (pageSet != QCUPSSupport::AllPages) {\n            QCUPSSupport::setPageSet(p, pageSet);\n        }\n\n        // server-side page range, since we set the page range on the printer to 0-0/AllPages above,\n        // we need to take the values directly from the widget as q->fromPage() will return 0\n        if (!q->testOption(QPrintDialog::PrintPageRange) && options.printRange->isChecked())\n            QCUPSSupport::setPageRange(p, options.from->value(), qMax(options.from->value(), options.to->value()));\n    }\n#endif\n\n    // copies\n    p->setCopyCount(options.copies->value());\n    p->setCollateCopies(options.collate->isChecked());\n}\n\nvoid QPrintDialogPrivate::_q_togglePageSetCombo(bool checked)\n{\n    if (printerOutputFormat == QPrinter::PdfFormat)\n        return;\n\n    options.pageSetCombo->setDisabled(checked);\n}\n\nvoid QPrintDialogPrivate::_q_collapseOrExpandDialog()\n{\n    int collapseHeight = 0;\n    Q_Q(QPrintDialog);\n    QWidget *widgetToHide = bottom;\n    if (widgetToHide->isVisible()) {\n        collapseButton->setText(QPrintDialog::tr(\"&Options >>\"));\n        collapseHeight = widgetToHide->y() + widgetToHide->height() - (top->y() + top->height());\n    }\n    else\n        collapseButton->setText(QPrintDialog::tr(\"&Options <<\"));\n    widgetToHide->setVisible(! widgetToHide->isVisible());\n    if (! widgetToHide->isVisible()) { // make it shrink\n        q->layout()->activate();\n        q->resize( QSize(q->width(), q->height() - collapseHeight) );\n    }\n}\n\n#if QT_CONFIG(messagebox)\nvoid QPrintDialogPrivate::_q_checkFields()\n{\n    Q_Q(QPrintDialog);\n    if (top->d->checkFields())\n        q->accept();\n}\n#endif // QT_CONFIG(messagebox)\n\n\nvoid QPrintDialogPrivate::updateWidgets()\n{\n    Q_Q(QPrintDialog);\n    options.gbPrintRange->setVisible(q->testOption(QPrintDialog::PrintPageRange) ||\n                                     q->testOption(QPrintDialog::PrintSelection) ||\n                                     q->testOption(QPrintDialog::PrintCurrentPage));\n\n    options.printRange->setEnabled(q->testOption(QPrintDialog::PrintPageRange));\n    options.printSelection->setVisible(q->testOption(QPrintDialog::PrintSelection));\n    options.printCurrentPage->setVisible(q->testOption(QPrintDialog::PrintCurrentPage));\n    options.collate->setVisible(q->testOption(QPrintDialog::PrintCollateCopies));\n\n#if QT_CONFIG(cups)\n    // Don't display Page Set if only Selection or Current Page are enabled\n    if (!q->testOption(QPrintDialog::PrintPageRange)\n        && (q->testOption(QPrintDialog::PrintSelection) || q->testOption(QPrintDialog::PrintCurrentPage))) {\n        options.pageSetCombo->setVisible(false);\n        options.pageSetLabel->setVisible(false);\n    } else {\n        options.pageSetCombo->setVisible(true);\n        options.pageSetLabel->setVisible(true);\n    }\n\n    if (!q->testOption(QPrintDialog::PrintPageRange)) {\n        // If we can do CUPS server side pages selection,\n        // display the page range widgets\n        options.gbPrintRange->setVisible(true);\n        options.printRange->setEnabled(true);\n    }\n#endif\n\n    switch (q->printRange()) {\n    case QPrintDialog::AllPages:\n        options.printAll->setChecked(true);\n        options.pageSetCombo->setEnabled(true);\n        break;\n    case QPrintDialog::Selection:\n        options.printSelection->setChecked(true);\n        options.pageSetCombo->setEnabled(false);\n        break;\n    case QPrintDialog::PageRange:\n        options.printRange->setChecked(true);\n        options.pageSetCombo->setEnabled(true);\n        break;\n    case QPrintDialog::CurrentPage:\n        if (q->testOption(QPrintDialog::PrintCurrentPage)) {\n            options.printCurrentPage->setChecked(true);\n            options.pageSetCombo->setEnabled(false);\n        }\n        break;\n    default:\n        break;\n    }\n    const int minPage = qMax(1, qMin(q->minPage() , q->maxPage()));\n    const int maxPage = qMax(1, q->maxPage() == INT_MAX ? 9999 : q->maxPage());\n\n    options.from->setMinimum(minPage);\n    options.to->setMinimum(minPage);\n    options.from->setMaximum(maxPage);\n    options.to->setMaximum(maxPage);\n\n    options.from->setValue(q->fromPage());\n    options.to->setValue(q->toPage());\n    top->d->updateWidget();\n}\n\nvoid QPrintDialogPrivate::setTabs(const QList<QWidget*> &tabWidgets)\n{\n    QList<QWidget*>::ConstIterator iter = tabWidgets.begin();\n    while(iter != tabWidgets.constEnd()) {\n        QWidget *tab = *iter;\n        options.tabs->addTab(tab, tab->windowTitle());\n        ++iter;\n    }\n}\n\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n\n/*\n\n    QPrintDialog\n\n    The main Print Dialog.\n\n*/\n\nQPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)\n    : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)\n{\n    Q_D(QPrintDialog);\n    d->init();\n}\n\n/*!\n    Constructs a print dialog with the given \\a parent.\n*/\nQPrintDialog::QPrintDialog(QWidget *parent)\n    : QAbstractPrintDialog(*(new QPrintDialogPrivate), nullptr, parent)\n{\n    Q_D(QPrintDialog);\n    d->init();\n}\n\nQPrintDialog::~QPrintDialog()\n{\n}\n\nvoid QPrintDialog::setVisible(bool visible)\n{\n    Q_D(QPrintDialog);\n\n    if (visible)\n        d->updateWidgets();\n\n    QAbstractPrintDialog::setVisible(visible);\n}\n\nint QPrintDialog::exec()\n{\n    return QAbstractPrintDialog::exec();\n}\n\nvoid QPrintDialog::accept()\n{\n    Q_D(QPrintDialog);\n#if QT_CONFIG(cups) && QT_CONFIG(messagebox)\n    if (d->options.pagesRadioButton->isChecked()) {\n        const QString rangesText = d->options.pagesLineEdit->text();\n        if (rangesText.isEmpty() || QPageRanges::fromString(rangesText).isEmpty()) {\n            QMessageBox::critical(this, tr(\"Invalid Pages Definition\"),\n                                  tr(\"%1 does not follow the correct syntax. Please use ',' to separate \"\n                                     \"ranges and pages, '-' to define ranges and make sure ranges do \"\n                                     \"not intersect with each other.\").arg(rangesText),\n                                  QMessageBox::Ok, QMessageBox::Ok);\n            return;\n        }\n    }\n    if (d->top->d->m_duplexPpdOption && d->top->d->m_duplexPpdOption->conflicted) {\n        const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr(\"Duplex Settings Conflicts\"),\n                                                                        tr(\"There are conflicts in duplex settings. Do you want to fix them?\"),\n                                                                        QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);\n        if (answer != QMessageBox::No)\n            return;\n    }\n#endif\n    d->setupPrinter();\n    QDialog::accept();\n}\n\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n\n/*\n\n    QUnixPrintWidget && QUnixPrintWidgetPrivate\n\n    The upper half of the Print Dialog containing the Printer Selection widgets\n\n*/\n\n#if defined (Q_OS_UNIX)\n\n/*! \\internal\n*/\nQUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn)\n    : parent(p), propertiesDialog(nullptr), printer(prn),\n#if QT_CONFIG(cups)\n      m_duplexPpdOption(nullptr),\n#endif\n      optionsPane(nullptr), filePrintersAdded(false)\n{\n    q = nullptr;\n    if (parent)\n        q = qobject_cast<QPrintDialog*> (parent->parent());\n\n    widget.setupUi(parent);\n\n    int currentPrinterIndex = 0;\n    QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();\n    if (ps) {\n        const QStringList printers = ps->availablePrintDeviceIds();\n        const QString defaultPrinter = ps->defaultPrintDeviceId();\n\n        widget.printers->addItems(printers);\n\n        const QString selectedPrinter = prn && !prn->printerName().isEmpty() ? prn->printerName() : defaultPrinter;\n        const int idx = printers.indexOf(selectedPrinter);\n\n        if (idx >= 0)\n            currentPrinterIndex = idx;\n    }\n    widget.properties->setEnabled(true);\n\n#if QT_CONFIG(filesystemmodel) && QT_CONFIG(completer)\n    QFileSystemModel *fsm = new QFileSystemModel(widget.filename);\n    fsm->setRootPath(QDir::homePath());\n    widget.filename->setCompleter(new QCompleter(fsm, widget.filename));\n#endif\n    _q_printerChanged(currentPrinterIndex);\n\n    QObject::connect(widget.printers, SIGNAL(currentIndexChanged(int)),\n                     parent, SLOT(_q_printerChanged(int)));\n    QObject::connect(widget.fileBrowser, SIGNAL(clicked()), parent, SLOT(_q_btnBrowseClicked()));\n    QObject::connect(widget.properties, SIGNAL(clicked()), parent, SLOT(_q_btnPropertiesClicked()));\n\n    // disable features that QPrinter does not yet support.\n    widget.preview->setVisible(false);\n}\n\nvoid QUnixPrintWidgetPrivate::updateWidget()\n{\n    const bool printToFile = q == nullptr || q->testOption(QPrintDialog::PrintToFile);\n    if (printToFile && !filePrintersAdded) {\n        if (widget.printers->count())\n            widget.printers->insertSeparator(widget.printers->count());\n        widget.printers->addItem(QPrintDialog::tr(\"Print to File (PDF)\"));\n        filePrintersAdded = true;\n        if (widget.printers->count() == 1)\n            _q_printerChanged(0);\n    }\n    if (!printToFile && filePrintersAdded) {\n        widget.printers->removeItem(widget.printers->count()-1);\n        widget.printers->removeItem(widget.printers->count()-1);\n        if (widget.printers->count())\n            widget.printers->removeItem(widget.printers->count()-1); // remove separator\n        filePrintersAdded = false;\n    }\n    if (printer && filePrintersAdded && (printer->outputFormat() != QPrinter::NativeFormat\n                                         || printer->printerName().isEmpty()))\n    {\n        if (printer->outputFormat() == QPrinter::PdfFormat)\n            widget.printers->setCurrentIndex(widget.printers->count() - 1);\n        widget.filename->setEnabled(true);\n        widget.lOutput->setEnabled(true);\n    }\n\n    widget.filename->setVisible(printToFile);\n    widget.lOutput->setVisible(printToFile);\n    widget.fileBrowser->setVisible(printToFile);\n\n    if (q)\n        widget.properties->setVisible(q->testOption(QAbstractPrintDialog::PrintShowPageSize));\n}\n\nQUnixPrintWidgetPrivate::~QUnixPrintWidgetPrivate()\n{\n}\n\nvoid QUnixPrintWidgetPrivate::_q_printerChanged(int index)\n{\n    if (index < 0)\n        return;\n    const int printerCount = widget.printers->count();\n    widget.filename->setEnabled(false);\n    widget.lOutput->setEnabled(false);\n\n    // Reset properties dialog when printer is changed\n    if (propertiesDialog){\n        delete propertiesDialog;\n        propertiesDialog = nullptr;\n    }\n\n#if QT_CONFIG(cups)\n    m_duplexPpdOption = nullptr;\n#endif\n\n    if (filePrintersAdded) {\n        Q_ASSERT(index != printerCount - 2); // separator\n        if (index == printerCount - 1) { // PDF\n            widget.location->setText(QPrintDialog::tr(\"Local file\"));\n            widget.type->setText(QPrintDialog::tr(\"Write PDF file\"));\n            widget.properties->setEnabled(true);\n            widget.filename->setEnabled(true);\n            QString filename = widget.filename->text();\n            widget.filename->setText(filename);\n            widget.lOutput->setEnabled(true);\n            printer->setOutputFormat(QPrinter::PdfFormat);\n            m_currentPrintDevice = QPrintDevice();\n            if (optionsPane)\n                optionsPane->selectPrinter(QPrinter::PdfFormat);\n            return;\n        }\n    }\n\n    if (printer) {\n        printer->setOutputFormat(QPrinter::NativeFormat);\n\n        QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();\n        if (ps)\n            m_currentPrintDevice = ps->createPrintDevice(widget.printers->itemText(index));\n        else\n            m_currentPrintDevice = QPrintDevice();\n\n        printer->setPrinterName(m_currentPrintDevice.id());\n\n        widget.location->setText(m_currentPrintDevice.location());\n        widget.type->setText(m_currentPrintDevice.makeAndModel());\n        if (optionsPane)\n            optionsPane->selectPrinter(QPrinter::NativeFormat);\n    }\n\n#if QT_CONFIG(cups)\n    m_duplexPpdOption = QCUPSSupport::findPpdOption(\"Duplex\", &m_currentPrintDevice);\n#endif\n}\n\nvoid QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)\n{\n    optionsPane = pane;\n    if (optionsPane)\n        optionsPane->selectPrinter(QPrinter::NativeFormat);\n}\n\nvoid QUnixPrintWidgetPrivate::_q_btnBrowseClicked()\n{\n    QString filename = widget.filename->text();\n#if QT_CONFIG(filedialog)\n    filename = QFileDialog::getSaveFileName(parent, QPrintDialog::tr(\"Print To File ...\"), filename,\n                                            QString(), nullptr, QFileDialog::DontConfirmOverwrite);\n#else\n    filename.clear();\n#endif\n    if (!filename.isEmpty()) {\n        widget.filename->setText(filename);\n        widget.printers->setCurrentIndex(widget.printers->count() - 1); // the pdf one\n    }\n}\n\n#if QT_CONFIG(messagebox)\nbool QUnixPrintWidgetPrivate::checkFields()\n{\n    if (widget.filename->isEnabled()) {\n        QString file = widget.filename->text();\n        QFile f(file);\n        QFileInfo fi(f);\n        bool exists = fi.exists();\n        bool opened = false;\n        if (exists && fi.isDir()) {\n            QMessageBox::warning(q, q->windowTitle(),\n                            QPrintDialog::tr(\"%1 is a directory.\\nPlease choose a different file name.\").arg(file));\n            return false;\n        } else if ((exists && !fi.isWritable()) || !(opened = f.open(QFile::Append))) {\n            QMessageBox::warning(q, q->windowTitle(),\n                            QPrintDialog::tr(\"File %1 is not writable.\\nPlease choose a different file name.\").arg(file));\n            return false;\n        } else if (exists) {\n            int ret = QMessageBox::question(q, q->windowTitle(),\n                                            QPrintDialog::tr(\"%1 already exists.\\nDo you want to overwrite it?\").arg(file),\n                                            QMessageBox::Yes|QMessageBox::No, QMessageBox::No);\n            if (ret == QMessageBox::No)\n                return false;\n        }\n        if (opened) {\n            f.close();\n            if (!exists)\n                f.remove();\n        }\n    }\n\n#if QT_CONFIG(cups)\n    if (propertiesDialog) {\n        QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo\n                                                                    ->currentData());\n\n        QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(optionsPane->options.pageSetCombo->currentData());\n\n\n        if (pagesPerSheet != QCUPSSupport::OnePagePerSheet\n            && pageSet != QCUPSSupport::AllPages) {\n            QMessageBox::warning(q, q->windowTitle(),\n                                 QPrintDialog::tr(\"Options 'Pages Per Sheet' and 'Page Set' cannot be used together.\\nPlease turn one of those options off.\"));\n            return false;\n        }\n    }\n#endif\n\n    // Every test passed. Accept the dialog.\n    return true;\n}\n#endif // QT_CONFIG(messagebox)\n\nvoid QUnixPrintWidgetPrivate::setupPrinterProperties()\n{\n    delete propertiesDialog;\n\n    QPrinter::OutputFormat outputFormat;\n    QString printerName;\n\n    if (q->testOption(QPrintDialog::PrintToFile)\n        && (widget.printers->currentIndex() == widget.printers->count() - 1)) {// PDF\n        outputFormat = QPrinter::PdfFormat;\n    } else {\n        outputFormat = QPrinter::NativeFormat;\n        printerName = widget.printers->currentText();\n    }\n\n    propertiesDialog = new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q);\n}\n\n#if QT_CONFIG(cups)\nvoid QUnixPrintWidgetPrivate::setPpdDuplex(QPrinter::DuplexMode mode)\n{\n    auto values = QStringList{} << QStringLiteral(\"Duplex\");\n    if (mode == QPrinter::DuplexNone) values << QStringLiteral(\"None\");\n    else if (mode == QPrinter::DuplexLongSide) values << QStringLiteral(\"DuplexNoTumble\");\n    else if (mode == QPrinter::DuplexShortSide) values << QStringLiteral(\"DuplexTumble\");\n\n    m_currentPrintDevice.setProperty(PDPK_PpdOption, values);\n}\n#endif\n\nvoid QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()\n{\n    if (!propertiesDialog)\n        setupPrinterProperties();\n    propertiesDialog->exec();\n\n#if QT_CONFIG(cups)\n    // update the warning icon on the duplex options if needed\n    optionsPane->updatePpdDuplexOption(optionsPane->options.noDuplex);\n    optionsPane->updatePpdDuplexOption(optionsPane->options.duplexLong);\n    optionsPane->updatePpdDuplexOption(optionsPane->options.duplexShort);\n#endif\n}\n\nvoid QUnixPrintWidgetPrivate::setupPrinter()\n{\n    const int printerCount = widget.printers->count();\n    const int index = widget.printers->currentIndex();\n\n    if (filePrintersAdded && index == printerCount - 1) { // PDF\n        printer->setPrinterName(QString());\n        Q_ASSERT(index != printerCount - 2); // separator\n        printer->setOutputFormat(QPrinter::PdfFormat);\n        QString path = widget.filename->text();\n        if (QDir::isRelativePath(path))\n            path = QDir::homePath() + QDir::separator() + path;\n        printer->setOutputFileName(path);\n    }\n    else {\n        printer->setPrinterName(widget.printers->currentText());\n        printer->setOutputFileName(QString());\n    }\n\n    if (!propertiesDialog)\n        setupPrinterProperties();\n\n    propertiesDialog->setupPrinter();\n}\n\n/*! \\internal\n*/\nQUnixPrintWidget::QUnixPrintWidget(QPrinter *printer, QWidget *parent)\n    : QWidget(parent), d(new QUnixPrintWidgetPrivate(this, printer))\n{\n    if (printer == nullptr)\n        return;\n    if (printer->outputFileName().isEmpty()) {\n        QString home = QDir::homePath();\n        QString cur = QDir::currentPath();\n        if (!home.endsWith(u'/'))\n            home += u'/';\n        if (!cur.startsWith(home))\n            cur = home;\n        else if (!cur.endsWith(u'/'))\n            cur += u'/';\n        if (QGuiApplication::platformName() == \"xcb\"_L1) {\n            if (printer->docName().isEmpty()) {\n                cur += \"print.pdf\"_L1;\n            } else {\n#if QT_CONFIG(regularexpression)\n                const QRegularExpression re(QStringLiteral(\"(.*)\\\\.\\\\S+\"));\n                auto match = re.match(printer->docName());\n                if (match.hasMatch())\n                    cur += match.captured(1);\n                else\n#endif\n                    cur += printer->docName();\n                cur += \".pdf\"_L1;\n            }\n        } // xcb\n\n        d->widget.filename->setText(cur);\n    }\n    else\n        d->widget.filename->setText(printer->outputFileName());\n    const QString printerName = printer->printerName();\n    if (!printerName.isEmpty()) {\n        const int i = d->widget.printers->findText(printerName);\n        if (i >= 0)\n            d->widget.printers->setCurrentIndex(i);\n    }\n    // PDF printer not added to the dialog yet, we'll handle those cases in QUnixPrintWidgetPrivate::updateWidget\n}\n\n/*! \\internal\n*/\nQUnixPrintWidget::~QUnixPrintWidget()\n{\n    delete d;\n}\n\n/*! \\internal\n\n    Updates the printer with the states held in the QUnixPrintWidget.\n*/\nvoid QUnixPrintWidget::updatePrinter()\n{\n    d->setupPrinter();\n}\n\n#if QT_CONFIG(cups)\n\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n\n#endif // QT_CONFIG(cups)\n#endif // defined (Q_OS_UNIX)\n\nQT_END_NAMESPACE\n\n#include \"moc_qprintdialog.cpp\"\n#include \"qprintdialog_unix.moc\"\n"
  },
  {
    "path": "libgui/languages/build_ts/octave-qt/qprintdialog_win.cpp",
    "content": "// Copyright (C) 2016 The Qt Company Ltd.\n// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n\n#include <QtPrintSupport/qtprintsupportglobal.h>\n\n#include \"qprintdialog.h\"\n\n#include <qwidget.h>\n#include <qapplication.h>\n#include <qmessagebox.h>\n#include <private/qapplication_p.h>\n\n#include \"qabstractprintdialog_p.h\"\n#include <private/qprintengine_win_p.h>\n#include \"../kernel/qprinter_p.h\"\n\n#if !defined(PD_NOCURRENTPAGE)\n#define PD_NOCURRENTPAGE    0x00800000\n#define PD_RESULT_PRINT 1\n#define PD_RESULT_APPLY 2\n#define START_PAGE_GENERAL  0XFFFFFFFF\n#endif\n\nQT_BEGIN_NAMESPACE\n\nusing namespace Qt::StringLiterals;\n\n//extern void qt_win_eatMouseMove();\n\nclass QPrintDialogPrivate : public QAbstractPrintDialogPrivate\n{\n    Q_DECLARE_PUBLIC(QPrintDialog)\npublic:\n    QPrintDialogPrivate()\n        : engine(0), ep(0)\n    {\n    }\n\n    int openWindowsPrintDialogModally();\n\n    QWin32PrintEngine *engine;\n    QWin32PrintEnginePrivate *ep;\n};\n\nstatic void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWindow *parentWindow,\n                                    QPrintDialog *pdlg,\n                                    QPrintDialogPrivate *d, HGLOBAL *tempDevNames)\n{\n    DEVMODE *devMode = d->ep->devMode;\n\n    if (devMode) {\n        int size = sizeof(DEVMODE) + devMode->dmDriverExtra;\n        pd->hDevMode = GlobalAlloc(GHND, size);\n        {\n            void *dest = GlobalLock(pd->hDevMode);\n            memcpy(dest, devMode, size);\n            GlobalUnlock(pd->hDevMode);\n        }\n    } else {\n        pd->hDevMode = NULL;\n    }\n    pd->hDevNames  = tempDevNames;\n\n    pd->Flags = PD_RETURNDC;\n    pd->Flags |= PD_USEDEVMODECOPIESANDCOLLATE;\n\n    if (!pdlg->testOption(QPrintDialog::PrintSelection))\n        pd->Flags |= PD_NOSELECTION;\n    if (pdlg->testOption(QPrintDialog::PrintPageRange)) {\n        pd->nMinPage = pdlg->minPage();\n        pd->nMaxPage = pdlg->maxPage();\n    }\n\n    if (!pdlg->testOption(QPrintDialog::PrintToFile))\n        pd->Flags |= PD_DISABLEPRINTTOFILE;\n\n    if (pdlg->testOption(QPrintDialog::PrintSelection) && pdlg->printRange() == QPrintDialog::Selection)\n        pd->Flags |= PD_SELECTION;\n    else if (pdlg->testOption(QPrintDialog::PrintPageRange) && pdlg->printRange() == QPrintDialog::PageRange)\n        pd->Flags |= PD_PAGENUMS;\n    else if (pdlg->testOption(QPrintDialog::PrintCurrentPage) && pdlg->printRange() == QPrintDialog::CurrentPage)\n        pd->Flags |= PD_CURRENTPAGE;\n    else\n        pd->Flags |= PD_ALLPAGES;\n\n    // As stated by MSDN, to enable collate option when minpage==maxpage==0\n    // set the PD_NOPAGENUMS flag\n    if (pd->nMinPage==0 && pd->nMaxPage==0)\n        pd->Flags |= PD_NOPAGENUMS;\n\n    // Disable Current Page option if not required as default is Enabled\n    if (!pdlg->testOption(QPrintDialog::PrintCurrentPage))\n        pd->Flags |= PD_NOCURRENTPAGE;\n\n    // Default to showing the General tab first\n    pd->nStartPage = START_PAGE_GENERAL;\n\n    // We don't support more than one page range in the QPrinter API yet.\n    pd->nPageRanges = 1;\n    pd->nMaxPageRanges = 1;\n\n    if (d->ep->printToFile)\n        pd->Flags |= PD_PRINTTOFILE;\n\n    WId wId = parentWindow ? parentWindow->winId() : 0;\n    //QTBUG-118899 PrintDlg needs valid window handle in hwndOwner\n    //So in case there is no valid handle in the application,\n    //use the desktop as valid handle.\n    pd->hwndOwner = wId != 0 ? HWND(wId) : GetDesktopWindow();\n    pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage());\n    pd->lpPageRanges[0].nToPage   = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1;\n    pd->nCopies = d->printer->copyCount();\n}\n\nstatic void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d)\n{\n    if (pd->Flags & PD_SELECTION) {\n        pdlg->setPrintRange(QPrintDialog::Selection);\n        pdlg->printer()->setPageRanges(QPageRanges());\n    } else if (pd->Flags & PD_PAGENUMS) {\n        pdlg->setPrintRange(QPrintDialog::PageRange);\n        pdlg->setFromTo(pd->lpPageRanges[0].nFromPage, pd->lpPageRanges[0].nToPage);\n    } else if (pd->Flags & PD_CURRENTPAGE) {\n        pdlg->setPrintRange(QPrintDialog::CurrentPage);\n       pdlg->printer()->setPageRanges(QPageRanges());\n    } else { // PD_ALLPAGES\n        pdlg->setPrintRange(QPrintDialog::AllPages);\n        pdlg->printer()->setPageRanges(QPageRanges());\n    }\n\n    d->ep->printToFile = (pd->Flags & PD_PRINTTOFILE) != 0;\n\n    d->engine->setGlobalDevMode(pd->hDevNames, pd->hDevMode);\n\n    if (d->ep->printToFile && d->ep->fileName.isEmpty())\n        d->ep->fileName = \"FILE:\"_L1;\n    else if (!d->ep->printToFile && d->ep->fileName == \"FILE:\"_L1)\n        d->ep->fileName.clear();\n}\n\nstatic bool warnIfNotNative(QPrinter *printer)\n{\n    if (printer->outputFormat() != QPrinter::NativeFormat) {\n        qWarning(\"QPrintDialog: Cannot be used on non-native printers\");\n        return false;\n    }\n    return true;\n}\n\nQPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)\n    : QAbstractPrintDialog( *(new QPrintDialogPrivate), printer, parent)\n{\n    Q_D(QPrintDialog);\n    if (!warnIfNotNative(d->printer))\n        return;\n    d->engine = static_cast<QWin32PrintEngine *>(d->printer->printEngine());\n    d->ep = static_cast<QWin32PrintEngine *>(d->printer->printEngine())->d_func();\n    setAttribute(Qt::WA_DontShowOnScreen);\n}\n\nQPrintDialog::QPrintDialog(QWidget *parent)\n    : QAbstractPrintDialog( *(new QPrintDialogPrivate), 0, parent)\n{\n    Q_D(QPrintDialog);\n    if (!warnIfNotNative(d->printer))\n        return;\n    d->engine = static_cast<QWin32PrintEngine *>(d->printer->printEngine());\n    d->ep = static_cast<QWin32PrintEngine *>(d->printer->printEngine())->d_func();\n    setAttribute(Qt::WA_DontShowOnScreen);\n}\n\nQPrintDialog::~QPrintDialog()\n{\n}\n\nint QPrintDialog::exec()\n{\n    if (!warnIfNotNative(printer()))\n        return 0;\n\n    Q_D(QPrintDialog);\n    return d->openWindowsPrintDialogModally();\n}\n\nint QPrintDialogPrivate::openWindowsPrintDialogModally()\n{\n    Q_Q(QPrintDialog);\n    QWindow *parentWindow = q->windowHandle() ? q->windowHandle()->transientParent() : nullptr;\n    if (!parentWindow) {\n        QWidget *parent = q->parentWidget();\n        if (parent)\n            parent = parent->window();\n        else\n            parent = QApplication::activeWindow();\n\n        // If there is no window, fall back to the print dialog itself\n        if (!parent)\n            parent = q;\n\n        parentWindow = parent->windowHandle();\n    }\n\n    q->QDialog::setVisible(true);\n\n    HGLOBAL *tempDevNames = engine->createGlobalDevNames();\n\n    bool done;\n    bool result;\n    bool doPrinting;\n\n    PRINTPAGERANGE pageRange;\n    PRINTDLGEX pd;\n    memset(&pd, 0, sizeof(PRINTDLGEX));\n    pd.lStructSize = sizeof(PRINTDLGEX);\n    pd.lpPageRanges = &pageRange;\n    qt_win_setup_PRINTDLGEX(&pd, parentWindow, q, this, tempDevNames);\n\n    do {\n        done = true;\n        doPrinting = false;\n        result = (PrintDlgEx(&pd) == S_OK);\n        if (result && (pd.dwResultAction == PD_RESULT_PRINT\n                       || pd.dwResultAction == PD_RESULT_APPLY))\n        {\n            doPrinting = (pd.dwResultAction == PD_RESULT_PRINT);\n            if ((pd.Flags & PD_PAGENUMS)\n                && (pd.lpPageRanges[0].nFromPage > pd.lpPageRanges[0].nToPage))\n            {\n                pd.lpPageRanges[0].nFromPage = 1;\n                pd.lpPageRanges[0].nToPage = 1;\n                done = false;\n            }\n            if (pd.hDC == 0)\n                result = false;\n        }\n\n        if (!done) {\n            QMessageBox::warning(nullptr,\n                                 QPrintDialog::tr(\"Print\"),\n                                 QPrintDialog::tr(\"The 'From' value cannot be greater than the 'To' value.\"));\n        }\n    } while (!done);\n\n    q->QDialog::setVisible(false);\n\n//    qt_win_eatMouseMove();\n\n    // write values back...\n    if (result && (pd.dwResultAction == PD_RESULT_PRINT\n                   || pd.dwResultAction == PD_RESULT_APPLY))\n    {\n        qt_win_read_back_PRINTDLGEX(&pd, q, this);\n        // update printer validity\n        printer->d_func()->validPrinter = !printer->printerName().isEmpty();\n    }\n\n    // Cleanup...\n    GlobalFree(tempDevNames);\n\n    q->done(result && doPrinting);\n\n    return result && doPrinting;\n}\n\nvoid QPrintDialog::setVisible(bool visible)\n{\n    Q_D(QPrintDialog);\n\n    // its always modal, so we cannot hide a native print dialog\n    if (!visible)\n        return;\n\n    if (!warnIfNotNative(d->printer))\n        return;\n\n    (void)d->openWindowsPrintDialogModally();\n    return;\n}\n\nQT_END_NAMESPACE\n\n#include \"moc_qprintdialog.cpp\"\n"
  },
  {
    "path": "libgui/languages/build_ts/update_external_sources",
    "content": "#!/bin/bash\n\n# This scripts updates the external source files from Qt and QScintilla\n# in the subdirectories \"octave-qt\" and \"octave-qsci\". These files are\n# later used by the script \"update_ts_files\" for languages for which\n# without translations provided by Qt and/or QScintilla in order to get\n# the strings to translate\n#\n# Syntax\n#\n#     update_external_sources  path-to-qt-src  path-to-qsci-src\n#\n# Parameter\n#\n#     path-to-qt-src:   Relative or absolute path to the new Qt\n#                       sources\n#     path-to-qsci-src: Relative or absolute path to the new\n#                       QScintilla sources\n#\n\nif [ $# -ne 2 ]\nthen\n  echo\n  echo \"Syntax\"\n  echo\n  echo \"     update_external_sources  path-to-qt-src  path-to-qsci-src\"\n  echo\n  echo \"Parameter\"\n  echo\n  echo \"     path-to-qt-src:   Relative or absolute path to the new Qt\"\n  echo \"                       sources\"\n  echo \"     path-to-qsci-src: Relative or absolute path to the new\"\n  echo \"                       QScintilla sources\"\n  echo\n  exit\nfi\n\nQT=$1\nQSCI=$2\n\nOCTQT=\"octave-qt\"\nOCTQSCI=\"octave-qsci\"\n\nif [ ! -d $QT ]\nthen\n    echo \"Directory $QT does not exist.\"\n    exit 1\nfi\nif [ ! -d $QSCI ]\nthen\n    echo \"Directory $QSCI does not exist.\"\n    exit 1\nfi\n\necho\necho \"$OCTQT\"\necho\n\nfor file in $(find $OCTQT -maxdepth 1 -not -type d)\ndo\n    bfile=`basename $file`\n    find $QT -type f -name $bfile -exec cp -v -u \"{}\" $OCTQT \\;\ndone\n\necho\necho \"$OCTQSCI\"\necho\n\nfor file in $(find $OCTQSCI -maxdepth 1 -not -type d)\ndo\n    bfile=`basename $file`\n    find $QSCI -type f -name $bfile -exec cp -v -u \"{}\" $OCTQSCI \\;\ndone\n\necho\necho \"$OCTQSCI/Qsci\"\necho\n\nfor file in $(find $OCTQSCI/Qsci -maxdepth 1 -not -type d)\ndo\n    bfile=`basename $file`\n    find $QSCI -type f -name $bfile -exec cp -v -u \"{}\" $OCTQSCI/Qsci \\;\ndone\n\necho\necho done\necho\n"
  },
  {
    "path": "libgui/languages/build_ts/update_ts_files",
    "content": "#!/bin/bash\n\n# This scripts has to be called from the folder libgui/languages\n# where the *.ts files for each provided translation are located\necho \"---------------------------------------------\"\necho\necho \" Updating language file from current sources \"\necho\necho \"   Do NOT interrupt this script by Ctrl-C,\"\necho \"   use 'q' instead.\"\necho\necho \"---------------------------------------------\"\n\n# lupdate does not recognize the macro for the octave namespace.\n# As a workaround, the relevant sources are copied into a temporary\n# directory where the macros for beginning and ending a namespace\n# are expanded into the original C++ syntax.\necho\necho -n \"Preparing temporary sources ... \"\n\nOCTAVE_TEMP=\"__octave_temp_gui_sources__\"\nmkdir $OCTAVE_TEMP\ncp -a ../graphics $OCTAVE_TEMP/\ncp -a ../qterminal $OCTAVE_TEMP/\ncp -a ../src $OCTAVE_TEMP/\n\nfind $OCTAVE_TEMP -type f -exec \\\n      sed -i -e 's/OCTAVE_BEGIN_NAMESPACE\\s*(\\([^)]\\+\\))/namespace \\1 \\{/g'\\\n             -e 's/OCTAVE_END_NAMESPACE\\s*(\\([^)]\\+\\))/\\}/g' {} \\;\n\necho \"done\"\n\n\n# Now set the base search path for lupdate to the temporary sources\nSEARCH_PATH_COMMON=\"$OCTAVE_TEMP/graphics $OCTAVE_TEMP/qterminal $OCTAVE_TEMP/src\"\n\n# Path to Qt and QScintilla files with strings that should also be\n# translated by octave in case that Qt or QScintilla does not provide\n# translations for the current language\nSEARCH_PATH_QT=\"build_ts/octave-qt\"\nSEARCH_PATH_QSCI=\"build_ts/octave-qsci\"\n\n# The directory with translations provided by Qt and QScintilla\n# First test qt above qt5 which provides QT_INSTALL_TRANSLATIONS\n# by \"qtpaths --query\"\nQT_LANG_DIR=`qtpaths6 --query 2>/dev/null | grep QT_INSTALL_TRANSLATIONS | sed -e 's/QT_INSTALL_TRANSLATIONS://'`\nif [[ -z $QT_LANG_DIR ]]; then\n  # No \"qtpaths6\", try \"qtpaths\" instead (might be qt5 though)\n  QT_LANG_DIR=`qtpaths --query 2>/dev/null | grep QT_INSTALL_TRANSLATIONS | sed -e 's/QT_INSTALL_TRANSLATIONS://'`\n  if [[ -z $QT_LANG_DIR ]]; then\n    # No qt6 or no qt6 translations found: \"qtpaths\" does not provide\n    # \"--query\" for qt5, therefore test qt5 with \"qtdiag\"\n    QT_LANG_DIR=`qtdiag 2>/dev/null | grep TranslationsPath | sed -e 's/  TranslationsPath: //'`\n  fi\nfi\n\necho \"Qt translations: $QT_LANG_DIR\"\n\nLUPDATE=\"/usr/bin/lupdate-qt6\"\nif [[ ! -f $LUPDATE ]]; then\n  LUPDATE=\"/usr/lib/qt6/bin/lupdate\"\n  if [[ ! -f $LUPDATE ]]; then\n    LUPDATE=\"/usr/bin/lupdate\"\n    if [[ ! -f $LUPDATE ]]; then\n      echo \"No lupdate tool found, no update of ts-files possible.\"\n      exit 1\n    fi\n  fi\nfi\n\necho \"lupdate tool: $LUPDATE\"\n\n# Update all ts files\nfor file in $(ls -b1 *.ts)\ndo\n\n  xx=${file/_*/}\n  xx_yy=${file/.*/}\n\n  # Set the search path to the minimal one used for each ts file\n  SEARCH_PATH=$SEARCH_PATH_COMMON\n  T_QT=\"YES\"\n  T_QSCI=\"YES\"\n\n  # Look for translations provided by Qt and QScintilla and extend the search\n  # path if no existing translations are found.  In this case we have to scan\n  # the locally collected source files.\n  if [ $xx_yy != \"en_US\" ]; then  # No translation required for en_US\n    if [ -z $QT_LANG_DIR ]; then\n      # No translations for Qt found at all\n      SEARCH_PATH=\"$SEARCH_PATH $SEARCH_PATH_QT $SEARCH_PATH_QSCI\"\n      T_QT=\"NO\"\n      T_QSCI=\"NO\"\n    else\n      # Look for Qt translations for the current language\n      if [ \"`ls $QT_LANG_DIR | grep -i qt_$xx.qm | wc -l`\" -eq 0 ] &&\n         [ \"`ls $QT_LANG_DIR | grep -i qt_$xx_yy.qm | wc -l`\" -eq 0 ]; then\n         SEARCH_PATH=\"$SEARCH_PATH $SEARCH_PATH_QT\"\n         T_QT=\"NO\"\n      fi\n      # Look for QScintilla translations\n      if [ \"`ls $QT_LANG_DIR | grep -i qscintilla_$xx.qm | wc -l`\" -eq 0 ] &&\n         [ \"`ls $QT_LANG_DIR | grep -i qscintilla_$xx_yy.qm | wc -l`\" -eq 0 ]; then\n         SEARCH_PATH=\"$SEARCH_PATH $SEARCH_PATH_QSCI\"\n         T_QSCI=\"NO\"\n      fi\n    fi\n  fi\n  echo\n  echo\n  echo \"$xx_yy: Existing translations for Qt: $T_QT, QSci: $T_QSCI\"\n\n  # Do the update after user's confirmation\n  SEARCH_PATH_CLEAN=${SEARCH_PATH//\"$OCTAVE_TEMP/\"/}\n  echo         \"       => scan for strings in following paths:\"\n  echo         \"          $SEARCH_PATH_CLEAN\"\n  read -N 1 -p \"       => Update (y/[n]/q)? \" ANS;\n\n  if [ \"$ANS\" = \"q\" ]; then\n    break\n  fi\n\n  if [ \"$ANS\" = \"y\" ]; then\n    echo\n    $LUPDATE -no-obsolete -locations relative $SEARCH_PATH -ts $file\n    sed -i -e \"s/$OCTAVE_TEMP/../g\" $file   # fix path to sources\n  fi\n\ndone\n\n\n# Remove temporary copy of source files\necho\necho\necho -n \"Removing temporary sources ... \"\nrm -rf $OCTAVE_TEMP\necho \"done\"\necho\n"
  },
  {
    "path": "libgui/languages/ca_ES.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"ca_ES\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Diferència amb la mida predeterminada</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Color de fons; rosa (255,0,255) per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>n</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>c</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>s</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Copia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Enganxa</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Selecciona-ho tot</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\">Executa la selecció</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Neteja la finestra</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Edita %1 a la línia %2</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>selecció desada al porta-retalls</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\">Error</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\">Posició</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\">Error</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\">&amp;Refés</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\">Ta&amp;lla</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\">Esborra</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Selecciona-ho tot</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Obre l&apos;enllaç</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Copia l&apos;adreça de l&apos;enllaç</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Envia un correu electrònic a...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>Copia l&apos;adreça de correu electrònic</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Edita %1 a la línia %2</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Anotació</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Text</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Cadena de text</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Tipus de lletra</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>negreta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>n</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>cursiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>c</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>color</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>esquerra</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>centre</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>dreta</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>superior</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>inferior</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Posició</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Amplada</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Alçada</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>unitats</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalitzat</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Ajusta a la casella</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Casella</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Fons</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Vora</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Estil de línia</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>cap</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Amplada de línia</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Selecciona-ho tot</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Atura</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Continua</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation type=\"unfinished\">Notícies de la comunitat de l&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\">Error</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation type=\"unfinished\">Documentació de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation type=\"unfinished\">No s&apos;ha pogut copiar el conjunt d&apos;ajuda a un fitxer\ntemporal. Les funcions de cerca es poden veure afectades.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation type=\"unfinished\">Contingut</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\">Cerca</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Cerca</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">Amplia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">Redueix</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation type=\"unfinished\">No es pot registrar el fitxer d&apos;ajuda %1.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">Filtra</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Documentació</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation type=\"unfinished\">Consulta la documentació per obtenir ajuda.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Tanca</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Tanca</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Executa</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation type=\"unfinished\">No s&apos;ha pogut obrir l&apos;editor de text personalitzat\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation type=\"unfinished\">Encara no existeix cap configuració per a l&apos;editor personalitzat.\nVols obrir la configuració?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Continua</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation type=\"unfinished\">Desa el fitxer i executa</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation type=\"unfinished\">La pestanya associada de l&apos;editor de text ha desaparegut.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">El fitxer\n%1\nno existeix. Vols crear-lo?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">Crea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancel·la</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation type=\"unfinished\">Fitxers &amp;recents de l&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation type=\"unfinished\">&amp;Edita la funció</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation type=\"unfinished\">&amp;Desa el fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation type=\"unfinished\">Desa el fitxer &amp;com a...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Tanca</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation type=\"unfinished\">Tanca-ho tot</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation type=\"unfinished\">Tanca els altres fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation type=\"unfinished\">Imprimeix...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Edita</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\">&amp;Refés</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\">Ta&amp;lla</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation type=\"unfinished\">&amp;Cerca i substitueix...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation type=\"unfinished\">Cerca l&apos;&amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation type=\"unfinished\">&amp;Ordres</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\">Esborra la línia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">Copia la línia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">Talla la línia</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">Esborra fins l&apos;inici de la paraula</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">Esborra fins la fi de la paraula</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">Esborra fins l&apos;inici de la línia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">Esborra fins la fi de la línia</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">Duplica la selecció/línia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">Intercanvia la línia</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation type=\"unfinished\">&amp;Mostra la llista de compleció</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation type=\"unfinished\">&amp;Format</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation type=\"unfinished\">Posa la selecció en &amp;majúscules</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation type=\"unfinished\">Posa la selecció en m&amp;inúscules</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation type=\"unfinished\">&amp;Comenta</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation type=\"unfinished\">&amp;Descomenta</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation type=\"unfinished\">Comenta (Seleccionant la cadena de text)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation type=\"unfinished\">&amp;Sagna la selecció</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\">&amp;Neteja el sagnat de la selecció</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\">Sagna el codi</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation type=\"unfinished\">Converteix a la fi de línia de &amp;Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation type=\"unfinished\">Converteix a la fi de línia de &amp;Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation type=\"unfinished\">Converteix a la fi de línia de Legacy &amp;Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation type=\"unfinished\">&amp;Navegació</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation type=\"unfinished\">&amp;Ves a la línia...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\">Desplaça&apos;t al parèntesi corresponent</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\">Selecciona fins el parèntesi corresponent</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation type=\"unfinished\">Marcardor &amp;següent</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation type=\"unfinished\">Marcador &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation type=\"unfinished\">&amp;Commuta el marcador</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation type=\"unfinished\">&amp;Elimina totes les adreces d&apos;interès</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation type=\"unfinished\">&amp;Preferències...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation type=\"unfinished\">Preferències d&apos;&amp;estils...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation type=\"unfinished\">&amp;Visualitza</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation type=\"unfinished\">&amp;Edita</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation type=\"unfinished\">Mostra els números de &amp;línia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation type=\"unfinished\">Mostra els &amp;espais en blanc</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation type=\"unfinished\">Mostra la &amp;fi de línia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation type=\"unfinished\">Mostra els marcadors de &amp;sagnat</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation type=\"unfinished\">Mostra el &amp;marcador de línia llarga</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation type=\"unfinished\">Mostra la &amp;barra d&apos;eines</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation type=\"unfinished\">Mostra la barra d&apos;&amp;estat</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation type=\"unfinished\">Mostra la barra de &amp;desplaçament horitzontal</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation type=\"unfinished\">&amp;Amplia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation type=\"unfinished\">&amp;Redueix</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation type=\"unfinished\">Mida &amp;normal</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation type=\"unfinished\">&amp;Depura</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation type=\"unfinished\">&amp;Commuta el punt d&apos;interrupció</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation type=\"unfinished\">Punt d&apos;interrupció &amp;següent</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation type=\"unfinished\">Punt d&apos;interrupció &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation type=\"unfinished\">&amp;Elimina tots els punts d&apos;interrupció</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation type=\"unfinished\">&amp;Executa</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation type=\"unfinished\">Executa la &amp;selecció</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Ajuda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation type=\"unfinished\">&amp;Ajuda de paraules clau</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation type=\"unfinished\">&amp;Documentació de paraules clau</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation type=\"unfinished\">Fitxers recents</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation type=\"unfinished\">línia:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation type=\"unfinished\">columna:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation type=\"unfinished\">codificació:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation type=\"unfinished\">fi de línia:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation type=\"unfinished\">Condició de punt d&apos;interrupció</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation type=\"unfinished\">Ves a la línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation type=\"unfinished\">Número de línia</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation type=\"unfinished\">Comenta el text seleccionat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation type=\"unfinished\">Cadena de text de comentari a utilitzar:</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation type=\"unfinished\">&lt;sense nom&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation type=\"unfinished\">El fitxer\n\n  %1\n\nés a punt per ser tancat, però ha estat modificat.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Tanca</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation type=\"unfinished\">Depura o Desa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation type=\"unfinished\">Aquest fitxer s&apos;està executant.\nVols interrompre la depuració i desar?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation type=\"unfinished\">Fitxers d&apos;Octave (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation type=\"unfinished\">Tots els fitxers (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation type=\"unfinished\">&quot;%1&quot;\nno és un identificador vàlid.\n\nSi manteniu aquest nom de fitxer, no podreu executar el codi pel seu nom a l&apos;Octave.\n\nVols seleccionar un altre nom?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation type=\"unfinished\">\n\nAvís: El contingut de l&apos;editor ha estat modificat!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation type=\"unfinished\">Sembla que el fitxer &apos;%1&apos; ha estat modificat per una altra aplicació. Vols recarregar-lo?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation type=\"unfinished\">Sembla que el fitxer\n%1\nha estat esborrat o reanomenat. Vols desar-lo ara?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation type=\"unfinished\">Mida del fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation type=\"unfinished\">Tipus de fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation type=\"unfinished\">Data de modificació</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation type=\"unfinished\">Mostra els ocults</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation type=\"unfinished\">Alterna els colors de les files</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation type=\"unfinished\">Introdueix el camí o el nom del fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\">Directori superior</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation type=\"unfinished\">Mostra el directori de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation type=\"unfinished\">Ves al directori actual de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation type=\"unfinished\">Estableix el directori de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation type=\"unfinished\">Estableix el directori actual del navegador com a directori de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation type=\"unfinished\">Accions al directori actual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation type=\"unfinished\">Mostra el directori d&apos;inici</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation type=\"unfinished\">Estableix el directori del navegador...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\">Cerca fitxers...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation type=\"unfinished\">Nou fitxer...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation type=\"unfinished\">Nou directori...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation type=\"unfinished\">Reanomena...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">Obre</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation type=\"unfinished\">Obre a l&apos;explorador de fitxers del sistema</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation type=\"unfinished\">Obre a l&apos;editor de text</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation type=\"unfinished\">Desa la selecció al porta-retalls</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Executa</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation type=\"unfinished\">Carrega dades</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation type=\"unfinished\">Estableix el directori actual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation type=\"unfinished\">Esborra...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation type=\"unfinished\">Esborra el fitxer/directori</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation type=\"unfinished\">N&apos;estàs segur que vols esborrar\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation type=\"unfinished\">No es pot esborrar un directori no buit</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation type=\"unfinished\">Estableix el directori de l&apos;explorador de fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation type=\"unfinished\">Crea un fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Crea un fitxer a\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation type=\"unfinished\">Nou fitxer.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation type=\"unfinished\">Crea un directori</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Crea una carpeta a\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation type=\"unfinished\">Nou directori</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Explorador de fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation type=\"unfinished\">Explora els fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation type=\"unfinished\">Gaudeix-ne!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation type=\"unfinished\">Acaba</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancel·la</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation type=\"unfinished\">Distingeix entre &amp;majúscules/minúscules</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation type=\"unfinished\">Cerca des de l&apos;&amp;inici</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation type=\"unfinished\">&amp;Cerca recursiva</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation type=\"unfinished\">&amp;Substitueix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation type=\"unfinished\">Substitueix-ho &amp;tot</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation type=\"unfinished\">&amp;Més...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation type=\"unfinished\">Paraules &amp;completes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation type=\"unfinished\">Cerca cap &amp;enrere</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation type=\"unfinished\">Cerca se&amp;lecció</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation type=\"unfinished\">Cerca des de la fi</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation type=\"unfinished\">Cerca des de l&apos;inici</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation type=\"unfinished\">Substitueix el resultat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation type=\"unfinished\">%1 instàncies substituïdes</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation type=\"unfinished\">Resultat de la cerca</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation type=\"unfinished\">No s&apos;han trobat coincidències</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation type=\"unfinished\">Cerca fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation type=\"unfinished\">Nom:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation type=\"unfinished\">Comença a:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation type=\"unfinished\">Introdueix el directori inicial</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation type=\"unfinished\">Explora...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation type=\"unfinished\">Explora per seleccionar el directori inicial</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation type=\"unfinished\">Cerca als subdirectoris</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation type=\"unfinished\">Cerca fitxers als directoris</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation type=\"unfinished\">Inclou els noms dels directoris</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation type=\"unfinished\">Inclou els directoris coincidents als resultats de cerca</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation type=\"unfinished\">Conté el text:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation type=\"unfinished\">Text a coincidir</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation type=\"unfinished\">Resultats de la cerca</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation type=\"unfinished\">Inactiu.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Cerca</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation type=\"unfinished\">Comença la cerca pels fitxers coincidents</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Atura</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation type=\"unfinished\">Contingut del fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation type=\"unfinished\">Cercant...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation type=\"unfinished\">%1 coincidènci-(a/es)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation type=\"unfinished\">Estableix el directori de cerca</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation type=\"unfinished\">Nom del fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation type=\"unfinished\">Directori</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation type=\"unfinished\">Cerca:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation type=\"unfinished\">Cerca cap endavant</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation type=\"unfinished\">Cerca cap enrere</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation type=\"unfinished\">Error crític de l&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation type=\"unfinished\">Explora i cerca a l&apos;historial d&apos;ordres.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copia</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation type=\"unfinished\">Evalua</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation type=\"unfinished\">Bolca a un fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\">Oculta el filtre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\">Mostra el filtre</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation type=\"unfinished\">Introdueix text a filtrar a l&apos;historial d&apos;ordres</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">Filtra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Historial d&apos;ordres</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Benvingut a l&apos;Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">Següent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancel·la</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\">&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Sembla que estàs utilitzant la interfície gràfica de l&apos;Octave per primer cop en aquest ordinador.\nFeu clic a &apos;Següent&apos; per crear un fitxer de configuració i iniciar l&apos;Octave.&lt;/p&gt;\n&lt;p&gt;El fitxer de configuració s&apos;ha desat a&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation type=\"unfinished\">N&apos;estàs segur que vols sortir de l&apos;Octave?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\">Desa l&apos;espai de treball com a</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Quant a l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation type=\"unfinished\">Explora directoris</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation type=\"unfinished\">Fitxers de l&apos;Octave (*.m);;Tots els fitxers (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\">Nova funció</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation type=\"unfinished\">Nom de la nova funció:</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation type=\"unfinished\">No es pot trobar la funció %1</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation type=\"unfinished\">Obre...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation type=\"unfinished\">Obre un fitxer existent a l&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation type=\"unfinished\">Carrega un espai de treball...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation type=\"unfinished\">Desa l&apos;espai de treball com a...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation type=\"unfinished\">Sortir</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation type=\"unfinished\">Nou</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation type=\"unfinished\">Nou fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation type=\"unfinished\">Nova funció...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">Nova figura</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Edita</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Desfés</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Enganxa</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Selecciona-ho tot</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Neteja el porta-retalls</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\">Cerca fitxers...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Neteja l&apos;historial d&apos;ordres</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Neteja l&apos;espai de treball</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation type=\"unfinished\">Preferències...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation type=\"unfinished\">&amp;Depura</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">Pas</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Pas entrant</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">Pas sortint</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Continua</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\">Atura la depuració</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation type=\"unfinished\">&amp;Finestra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">Mostra l&apos;historial d&apos;ordres</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Mostra l&apos;explorador de fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">Mostra l&apos;espai de treball</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">Mostra l&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">Mostra la documentació</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\">Mostra l&apos;editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Finestra del terminal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Historial d&apos;ordres</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Explorador de fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Espai de treball</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Documentació</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\">Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\">Restaura el disseny de les finestres per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Ajuda</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Informa d&apos;un error</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Paquets de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation type=\"unfinished\">Donatius</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation type=\"unfinished\">Local</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation type=\"unfinished\">En línia</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation type=\"unfinished\">&amp;Notícies</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Notes de la versió</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Notícies de la comunitat</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation type=\"unfinished\">Barra d&apos;eines</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation type=\"unfinished\">Introdueix el nom del directori</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation type=\"unfinished\">Directori actual: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\">Directori superior</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\">&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s La font de notícies de la comunitat de l&apos;Octave sembla no estar disponible.\n&lt;/p&gt;\n&lt;p&gt;\nPer accedir a les últimes novetats, visita\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nquan tingui connexió al web (l&apos;enllaç s&apos;obre a un navegador extern).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Els desenvolupadors de l&apos;Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation type=\"unfinished\">Ajuda quant a</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation type=\"unfinished\">Documentació quant a</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation type=\"unfinished\">Edita</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation type=\"unfinished\">Fes clic a &apos;%1&apos; per substituir tots els casos de &apos;%2&apos; amb &apos;%3&apos;.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Per defecte</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">Crea</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancel·la</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">El fitxer\n%1\nno existeix. Vols crear-lo?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation type=\"unfinished\">El fitxer %1 no existeix als camins de càrrega. Per executar o depurar la funció que s&apos;està editant s&apos;ha de canviar al directori %2 o afegir aquest als camins de càrrega.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation type=\"unfinished\">Existeix un fitxer amb el mateix nom %1 al camí de càrrega. Per executar o depurar la funció que s&apos;està editant desplaça&apos;t al directori %2.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation type=\"unfinished\">Canvia el directori o afegeix directori al camí de càrrega</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation type=\"unfinished\">&amp;Canvia el directori</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation type=\"unfinished\">&amp;Afegeix el directori al camí de càrrega</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation type=\"unfinished\">El fitxer de notes de versió %1 està buit.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation type=\"unfinished\">El fitxer de notes de versió %1 no es pot llegir.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation type=\"unfinished\">Notes de la versió de l&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\">Desa</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation type=\"unfinished\">Primer pla</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\">Fons</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation type=\"unfinished\">Primer pla seleccionat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation type=\"unfinished\">Fons seleccionat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation type=\"unfinished\">global</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation type=\"unfinished\">Configuració de sistema</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation type=\"unfinished\">Cursor en forma d&apos;I</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation type=\"unfinished\">Cursor en forma de bloc</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation type=\"unfinished\">Cursor en forma de subratllat</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation type=\"unfinished\">Estableix el directori d&apos;inici de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation type=\"unfinished\">Estableix el directori d&apos;inici de l&apos;explorador de fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation type=\"unfinished\">Importa dreceres des d&apos;un fitxer...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation type=\"unfinished\">Fitxer de dreceres de l&apos;Octave (*.osc);;Tots els fitxers (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation type=\"unfinished\">Sobreescriu les dreceres</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation type=\"unfinished\">Ets a punt de sobreescriure totes les dreceres.\nVols desar el conjunt de dreceres actual o cancel·lar l&apos;acció?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation type=\"unfinished\">No dessis</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Notícies de la comunitat</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">Següent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancel·la</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\">&lt;html&gt;&lt;body&gt;\n&lt;p&gt;En iniciar l&apos;Octave, opcionalment es revisarà el lloc web de l&apos;Octave per cercar notícies i informació en quant a la comunitat de l&apos;Octave.\nAquesta revisió es farà una vegada al dia com a màxim i les notícies sols es mostraran si existeixen canvis recents des de l&apos;última visita.&lt;/p&gt;\n&lt;p&gt;També pots accedir a les notícies seleccionant &quot;Notícies de la comunitat&quot; al menú &quot;Ajuda&quot;, o visitant\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\">Neteja</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation type=\"unfinished\">Estableix com a per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation type=\"unfinished\">Drecera alternativa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation type=\"unfinished\">Global</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation type=\"unfinished\">Menú Fitxer</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation type=\"unfinished\">Menú Edita</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation type=\"unfinished\">Menú Depura</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation type=\"unfinished\">Menú Finestra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation type=\"unfinished\">Menú Ajuda</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation type=\"unfinished\">Menú Notícies</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation type=\"unfinished\">Comportament de les pestanyes als plafons</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editor</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation type=\"unfinished\">Menú Visualitza</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation type=\"unfinished\">Menú Executa</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Benvingut al GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Benvingut a l&apos;Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Finestra del terminal</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation type=\"unfinished\">Restaura la geometria</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation type=\"unfinished\">Reacobla</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\">Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation type=\"unfinished\">Edita variables.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation type=\"unfinished\">Barra d&apos;eines de l&apos;editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\">Desa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation type=\"unfinished\">Desa la variable a un fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Talla</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation type=\"unfinished\">Talla les dades al porta-retall</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copia</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation type=\"unfinished\">Desa les dades al porta-retalls</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Enganxa</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation type=\"unfinished\">Enganxa el porta-retalls a una variable de dades</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation type=\"unfinished\">Representa gràficament</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation type=\"unfinished\">Representa gràficament les dades seleccionades</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation type=\"unfinished\">Representa gràficament les dades seleccionades</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation type=\"unfinished\">Puja</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation type=\"unfinished\">Puja un nivell cap amunt en la jerarquia de la variable</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation type=\"unfinished\">Desa la variable %1 com a</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Talla</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Enganxa</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\">Neteja</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\">Esborra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation type=\"unfinished\">Crea una variable des de la selecció</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation type=\"unfinished\">Transposa</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Benvingut al GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation type=\"unfinished\">Nom</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Dimensió</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">Atribut</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation type=\"unfinished\">Clic per copiar, reanomenar o mostrar</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation type=\"unfinished\">complex</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Dimensió</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">Atribut</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Espai de treball</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation type=\"unfinished\">Visualitza les variables de l&apos;espai de treball actiu.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation type=\"unfinished\">Introdueix un text per filtrar l&apos;espai de treball</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">Filtra</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation type=\"unfinished\">Visualitza les variables de l&apos;espai de treball actiu.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation type=\"unfinished\">Colors per als atributs de variable:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation type=\"unfinished\">Obre a l&apos;editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation type=\"unfinished\">Copia el nom</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation type=\"unfinished\">Copia el valor</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation type=\"unfinished\">Reanomena</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation type=\"unfinished\">Sols els símbols del nivell superior poden ser reanomenats</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\">Oculta el filtre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\">Mostra el filtre</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>General</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Sols el logotip de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Icones tipogràfiques</translation>\n    </message>\n    <message>\n        <location line=\"-334\"/>\n        <source>Dock widget title bar</source>\n        <translation>Acobla el plafó de la barra de títol</translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation>Petit</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Gran</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>Estil personalitzat</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation type=\"unfinished\">3D</translation>\n    </message>\n    <message>\n        <location line=\"+565\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Funciona bé amb lletres d&apos;espaiat fix. La línia es dibuixa en una posició basada en l&apos;amplada del caràcter espai de la lletra per defecte. Pot no funcionar bé si l&apos;estil utilitza fonts proporcionals o si es combinen lletres de mides diferents, o lletra normal amb negreta i/o cursiva.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Activa el plegament de codi</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation type=\"unfinished\">Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Mostra la barra de desplaçament horitzontal</translation>\n    </message>\n    <message>\n        <location line=\"-516\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+494\"/>\n        <source>Show tool bar</source>\n        <translation>Mostra la barra d&apos;eines</translation>\n    </message>\n    <message>\n        <location line=\"+221\"/>\n        <source>Rotated tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\">Posició</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+260\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Ajusta les línies llargues segons la vora de la finestra actual</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Indentation</source>\n        <translation>Sagnat</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation>Amplada del sagnat</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>El tabulador sagna la línia</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Sagnat automàtic</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Amplada del tabulador</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Mostra els marcadors de sagnat</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>La tecla de retrocés elimina el sagnat</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation>El sagnat utilitza el tabulat</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation>Autocompleció</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>Coincidència de paraules clau</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Distingeix entre majúscules i minúscules</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Substitueix la paraula pel suggeriment</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Coincidència de paraules al document</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation>Amb funcions internes de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Amb funcions de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Mostra la llista d&apos;ordres coincidents automàticament</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Recarrega els fitxers modificats externament sense consultar</translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation>Utilitza un editor de fitxers personalitzat</translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Codificació del text utilitzat per carregar i desar</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation>Estils de l&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Canviar la mida de l&apos;historial neteja el contingut)</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation>Mida de l&apos;historial</translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Tipus de lletra</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Mostra els números de línia</translation>\n    </message>\n    <message>\n        <location line=\"-866\"/>\n        <source>Interface</source>\n        <translation>Interfície</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Confirma abans de sortir</translation>\n    </message>\n    <message>\n        <location line=\"-72\"/>\n        <source>Graphic icons</source>\n        <translation>Icones gràfiques</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Mostra la barra d&apos;estat</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Text inactiu</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Actiu</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Background inactive</source>\n        <translation>Fons inactiu</translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation>Inici de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Explora</translation>\n    </message>\n    <message>\n        <location line=\"-1305\"/>\n        <source>Show whitespace</source>\n        <translation>Mostra els espais en blanc</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>No mostres l&apos;espai en blanc utilitzat per al sagnat</translation>\n    </message>\n    <message>\n        <location line=\"+1125\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Crea fitxers inexistents sense consultar</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>línia d&apos;ordres (%f=fitxer, %l=línia):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Tipus de cursor:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Utilitza el color de primer pla</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Mida de la lletra</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Explorador de fitxers</translation>\n    </message>\n    <message>\n        <location line=\"-2031\"/>\n        <source>Normal</source>\n        <translation>Normal</translation>\n    </message>\n    <message>\n        <location line=\"+359\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Aquestes configuracions s&apos;apliquen després del fitxer d&apos;inici &quot;.octaverc&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+540\"/>\n        <source>Show EOL characters</source>\n        <translation>Mostra el caràcter de fi de línia</translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation>Identificador de fi de línia per defecte</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Nombre de caràcters a partir del qual es mostra la llista: </translation>\n    </message>\n    <message>\n        <location line=\"-1812\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">Preferències</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Mida relativa respecte a la lletra de l&apos;editor </translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Ressalta totes les coincidències de la paraula seleccionada amb doble clic</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Comentaris (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Cadenes de text a tenir en compte en descomentar</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Cadena de text per comentar el text seleccionat</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Línies llargues</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Divideix les línies llargues a partir de la longitud de línia</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Només divideix les línies als comentaris</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Longitud de línia</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Marcador de línia llarga</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Línia</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Fons</translation>\n    </message>\n    <message>\n        <location line=\"+191\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Insereix automàticament després d&apos;un &quot;if&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Res</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Comportament dels fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Restaura les pestanyes de l&apos;editor de la sessió anterior</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Tanca tots els fitxers quan el plafó de l&apos;editor estigui tancat/ocult</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Selecciona el tipus de lletra, mida (relativa a la mida per defecte), estil (&lt;b&gt;n&lt;/b&gt;egreta, &lt;b&gt;c&lt;/b&gt;ursiva, &lt;b&gt;s&lt;/b&gt;ubrallat), color i color de fons (per al color de fons, el color magenta (255,0,255) és el marcador de posició per defecte).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Behavior</source>\n        <translation>Comportament</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Restaura l&apos;últim directori de la sessió prèvia</translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Extensions de fitxers per obrir a l&apos;editor de text per defecte (separades per &quot;;&quot;):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Espai de treball</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Colors per als atributs de variables</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Importa el conjunt de dreceres</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Exporta el conjunt de dreceres</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Restaura les dreceres als valors per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+232\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-227\"/>\n        <source>Actual</source>\n        <translation>Actual</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Xarxa</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Permet que l&apos;Octave s&apos;hi connecti al lloc web per mostrar més informació i notícies actualitzades</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Utilitza un servidor intermediari</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Alçada de fila per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Amplada de columna per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Colors de l&apos;editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Alterna els colors de les files</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Sincronitza el directori de treball de l&apos;Octave amb l&apos;explorador de fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+302\"/>\n        <source>Shortcuts</source>\n        <translation>Dreceres</translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation>Exporta</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importa</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Acció</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Nom del servidor:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Tipus de servidor intermediari:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Port:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Nom d&apos;usuari:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Contrasenya:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation type=\"unfinished\">Nou fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\">Nova funció</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">Nova figura</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation type=\"unfinished\">Obre fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\">Desa l&apos;espai de treball com a</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation type=\"unfinished\">Sortir de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Enganxa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Desfés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Selecciona-ho tot</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Neteja el porta-retalls</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation type=\"unfinished\">Cerca als fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Neteja l&apos;historial d&apos;ordres</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Neteja l&apos;espai de treball</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">Preferències</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">Pas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Pas entrant</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">Pas sortint</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Continua</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\">Atura la depuració</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">Mostra l&apos;historial d&apos;ordres</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Mostra l&apos;explorador de fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">Mostra l&apos;espai de treball</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">Mostra l&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">Mostra la documentació</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\">Mostra l&apos;editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Finestra del terminal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Historial d&apos;ordres</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Explorador de fitxers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Espai de treball</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Documentació</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\">Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\">Restaura el disseny de les finestres per defecte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation type=\"unfinished\">Mostra la documentació en línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Informa d&apos;un error</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Paquets de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation type=\"unfinished\">Contribueix a l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation type=\"unfinished\">Recursos de desenvolupador de l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Quant a l&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Notes de la versió</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Notícies de la comunitat</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation type=\"unfinished\">Tanca la pestanya</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation type=\"unfinished\">Tanca totes les pestanyes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation type=\"unfinished\">Tanca les altres pestanyes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation type=\"unfinished\">Canvia a la pestanya de l&apos;esquerra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation type=\"unfinished\">Canvia a la pestanya de la dreta</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation type=\"unfinished\">Mou la pestanya cap a l&apos;esquerra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation type=\"unfinished\">Mou la pestanya cap a la dreta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">Amplia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">Redueix</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation type=\"unfinished\">Ampliació normal</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation type=\"unfinished\">Edita la funció</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation type=\"unfinished\">Desa el fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation type=\"unfinished\">Desa el fitxer com a</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation type=\"unfinished\">Imprimeix</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation type=\"unfinished\">Refés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Talla</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation type=\"unfinished\">Cerca i substitueix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation type=\"unfinished\">Cerca el següent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation type=\"unfinished\">Cerca l&apos;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">Esborra fins l&apos;inici de la paraula</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">Esborra fins la fi de la paraula</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">Esborra fins l&apos;inici de la línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">Esborra fins la fi de la línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\">Esborra la línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">Copia la línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">Talla la línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">Duplica la selecció/línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">Intercanvia la línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation type=\"unfinished\">Mostra la llista de compleció</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation type=\"unfinished\">Comenta la selecció</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation type=\"unfinished\">Descomenta la selecció</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation type=\"unfinished\">Comenta la selecció (Seleccionant la cadena de text)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation type=\"unfinished\">Posa la selecció en majúscules</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation type=\"unfinished\">Posa la selecció en minúscules</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation type=\"unfinished\">Sagna la selecció</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\">Elimina el sagnat de la selecció</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\">Sagna el codi</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation type=\"unfinished\">Converteix la fi de línia a Windows</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation type=\"unfinished\">Converteix la fi de línia a Unix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation type=\"unfinished\">Converteix la fi de línia a Mac</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation type=\"unfinished\">Ves a la línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\">Desplaça&apos;t al parèntesi corresponent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\">Selecciona fins el parèntesi corresponent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation type=\"unfinished\">Commuta el marcador</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation type=\"unfinished\">Marcador següent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation type=\"unfinished\">Marcador anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation type=\"unfinished\">Elimina tots els marcadors</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation type=\"unfinished\">Preferències d&apos;estils</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation type=\"unfinished\">Mostra els números de línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation type=\"unfinished\">Mostra els espais en blanc</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation type=\"unfinished\">Mostra la fi de línia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation type=\"unfinished\">Mostra els marcadors de sagnat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation type=\"unfinished\">Mostra el marcador línia llarga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation type=\"unfinished\">Mostra la barra d&apos;eines</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation type=\"unfinished\">Mostra la barra d&apos;estat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation type=\"unfinished\">Mostra la barra de desplaçament horitzontal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation type=\"unfinished\">Commuta el punt d&apos;interrupció</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation type=\"unfinished\">Punt d&apos;interrupció següent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation type=\"unfinished\">Punt d&apos;interrupció anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation type=\"unfinished\">Eliminar tots els punts d&apos;interrupció</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation type=\"unfinished\">Executa el fitxer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\">Executa la selecció</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation type=\"unfinished\">Ajuda d&apos;una paraula clau</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation type=\"unfinished\">Documentació d&apos;una paraula clau</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/de_DE.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"de_DE\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Ungültiger Dateiname</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Differenz zur Standardgröße</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Hintergrundfarbe, Magenta (255,0,255) für Standard</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>f</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>k</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>u</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>Bearbeite &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Hilfe zu &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Dokumentation zu &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Einfügen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Alles auswählen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Auswahl ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>Auswahl bearbeiten</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>Hilfe zur Auswahl</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>Dokumentation zur Auswahl</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Alles löschen</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Bearbeite %1 in Zeile %2</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>Auswahl in die Zwischenablage kopiert</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Link öffnen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Link-Adresse kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>E-Mail senden an...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>E-Mail-Adresse kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%1 in Zeile %2 bearbeiten</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translatorcomment>Ich habe Annotation anstelle Anmerkung gewählt weil der Befehl auch &quot;annotation&quot; heißt, auch wenn der Begriff veraltet ist</translatorcomment>\n        <translation>Annotation</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Text</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translatorcomment>Laut Duden i.O. und kürzer als &quot;Zeichenkette&quot;</translatorcomment>\n        <translation>String</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Schriftart</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>fett</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>fett</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>kursiv</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translatorcomment>Das kann man wie &quot;fett&quot; für &quot;b&quot; hier eigentlich auch ausschreiben. Oder die Großbuchstaben &quot;F&quot; für &quot;b&quot; und &quot;K&quot; für &quot;i&quot; (so erkennt man es vielleicht aus den Office-Produkten wieder).</translatorcomment>\n        <translation>kursiv</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>Farbe</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>links</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>zentriert</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>rechts</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>Horizontale Ausrichtung</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>Vertikale Ausrichtung</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>oben</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>unten</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Position</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Breite</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Höhe</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>Einheiten</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalisiert</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>An Box anpassen</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Box</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Hintergrund</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translatorcomment>Hier wird eigentlich die Rahmenfarbe eingestellt. Vielleicht ist das englische &quot;edge&quot; hier auch nicht ganz passend, sondern es sollte besser &quot;border&quot; da stehen? </translatorcomment>\n        <translation>Rahmen</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Linienstil</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>keiner</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Linienbreite</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Alles auswählen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Pause</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Beenden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Fortfahren</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Befehlsfenster</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Neuigkeiten aus der Octave-Community</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>Standard</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Fehler</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>Eingabeaufforderung</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Octave Dokumentation</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>Hilfe-Sammlung konnte nicht in temporäre\nDatei kopiert werden. Suchfunktionen\nkönnten beeinträchtigt sein.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>Die für den Browser der Dokumentation\nerforderlichen Daten konnten nicht\neingerichtet werden. Möglicherweise fehlt\ndas Qt SQlite Modul.\nHilfetexte sind nur im Kommandofenster\nverfügbar.</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>Inhalt</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Texteingabe für die Suche im Funktions-Index</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Suchen</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>Funktions-Index</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Lesezeichen</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>Startseite</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Zurück</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Vorherige Seite</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>Vor</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Nächste Seite</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Suchen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Vergrößern</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Verkleinern</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Originalgröße</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>Lesezeichen für aktuelle Seite setzen</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>Hilfe-Datei %1 konnte nicht registriert werden.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nKeine Lesezeichen für Dokumentation geladen!</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: Lesezeichen für Dokumentation laden</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Text für Suche in Lesezeichen eingeben</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Filter</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Neuer Ordner</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>Ö&amp;ffnen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Umbenennen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>&amp;Löschen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>Ordner &amp;hinzufügen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>Filter &amp;ausblenden</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>Filter &amp;einblenden</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: Lesezeichen der Dokumentation speichern</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>Kann Datei &quot;%1&quot; nicht schreiben:\n%2.\n\nLesezeichen der Dokumentation wurde nicht gespeichert!\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>Kann Datei &quot;%1&quot; nicht lesen:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>Kein Anfangselement in %1 gefunden:\nUngültige Lesezeichendatei?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>Die Datei\n%1\nist keine gültige XBEL-Datei Version 1.0.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Unbekannter Titel</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Dokumentation</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Siehe Dokumentation für Hilfe.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>S&amp;chließen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>&amp;Alle Schließen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>S&amp;onstige schließen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>Zum &amp;linken Widget wechseln</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>Zum &amp;rechten Widget wechseln</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation>Geöffnete Editordateien</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation>Zum Auswählen der Datei im Editor anklicken</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>S&amp;chließen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>&amp;Alle Schließen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Octave &amp;Verzeichnis setzen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>Externer Editor kann nicht gestartet werden:\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Es wurde noch kein externer Editor konfiguriert.\nJetzt die Einstellungen öffnen?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Fortfahren</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Datei speichern und ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>Die Datei wurde nicht gespeichert!\nEine Datei mit dem Namen\n%1\nist bereits im Editor geöffnet.</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>Der zugehörige Editor-Reiter ist nicht mehr vorhanden.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>Die Datei\n%1\nkonnte nicht zum Lesen geöffnet werden:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Die Datei\n%1\nexistiert nicht. Soll sie erzeugt werden?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Erstellen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Abbrechen</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>Die Datei\n%1\nkonnte nicht zum Schreiben geöffnet werden:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Datei</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>&amp;Zuletzt bearbeitete Dateien</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>Funktion b&amp;earbeiten</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>Datei &amp;speichern</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>D&amp;atei speichern unter...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>S&amp;chließen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Alle schließen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Andere Dateien schließen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Drucken...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Bearbeiten</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Wiederherstellen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>&amp;Ausschneiden</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>&amp;Suchen und Ersetzen...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>&amp;Nächsten suchen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>&amp;Vorherigen suchen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>Befe&amp;hle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Zeile löschen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Zeile kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Zeile ausschneiden</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Bis zum Anfang des Wortes löschen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Bis zum Ende des Wortes löschen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Bis zum Anfang der Zeile löschen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Bis zum Ende der Zeile löschen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Zeile oder Auswahl duplizieren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Zeilen tauschen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>Vervoll&amp;ständigungsliste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Format</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>Auswahl zu Großb&amp;uchstaben</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>Auswahl zu K&amp;leinbuchstaben</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>&amp;Kommentieren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>Kommentar &amp;entfernen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Kommentieren (Syntax auswählen)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>Auswahl eine Ebene &amp;einrücken</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>Auswahl eine Ebene &amp;ausrücken</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Code automatisch einrücken</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Zeilenenden für &amp;Windows (CRLF) umwandeln</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Zeilenenden für &amp;Unix umwandeln (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Zeilenenden für Legacy &amp;Mac umwandeln (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>Navi&amp;gation</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>&amp;Gehe zu Zeile...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Zur zugehörigen Klammer springen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Bis zur zugehörigen Klammer auswählen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>&amp;Nächstes Lesezeichen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>&amp;Vorheriges Lesezeichen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>&amp;Lesezeichen umschalten</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>Alle Lesezeichen &amp;entfernen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Einstellungen...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>&amp;Stil-Einstellungen...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>An&amp;sicht</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>&amp;Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>Zei&amp;lennummern anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>Lee&amp;rzeichen anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Z&amp;eilenenden anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>E&amp;inrückungshinweise anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>&amp;Markierung langer Zeilen anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>&amp;Werkzeugleiste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>&amp;Statusleiste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>&amp;Horizontale Bildlaufleiste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>Ver&amp;größern</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>Ver&amp;kleinern</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>&amp;Normale Größe</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>Tabs alphabetisch &amp;sortieren</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Debuggen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>Haltepunkt &amp;umschalten</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>&amp;Nächster Haltepunkt</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>&amp;Vorheriger Haltepunkt</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>Alle Haltepunkte entfe&amp;rnen</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>&amp;Ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Datei speichern und aus- bzw. fortführen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>Markierten Quellcode au&amp;sführen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Datei speichern und alle &amp;Tests ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Datei speichern und alle &amp;Demos ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Hilfe</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>&amp;Hilfe zum Schlüsselwort</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>&amp;Dokumentation zum Schlüsselwort</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>Zuletzt bearbeitete Dateien</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Kopiere vollständigen Datei&amp;pfad</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>Zeile:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>Spalte:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>Kodierung:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>Zeilenende:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Bedingung für Haltepunkt</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>FEHLER: </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>Haltepunkte können nicht in geänderten oder unbenannten Dateien gesetzt werden.\nSpeichern und Haltepunkt setzen, oder abbrechen?</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Gehe zu Zeile</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Zeilennummer</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Markierten Text auskommentieren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Diese Zeichenkette verwenden:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;unbenannt&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>Änderungen verwerfen, speichern oder Schließen abrrechen?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>Die Datei\n\n  %1\n\nsoll geschlossen werden, wurde aber modifiziert.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>Die Datei\n%1\nkann mit der Zeichenkodierung\n%2: %3\nnicht geöffnet werden</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>Es gab Probleme beim Lesen der Datei\n%1\nmit der gewählten Zeichenkodierung %2.\n\nSpeichern der geänderten Datei könnte zu Datenverlust führen!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>Trotzdem b&amp;earbeiten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>&amp;Zeichenkodierung wechseln</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>S&amp;chließen</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Neue Standard-Zeichenkodierung wählen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Bitte wählen Sie eine Zeichenkodierung\num die aktuelle Datei neu zu laden.\n\nDie Standard-Zeichenkodierung wird dabei nicht geändert.\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Debug oder Speichern</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Diese Datei wird momentan ausgeführt.\nDebuggen abbrechen und speichern?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>Die Datei\n%1\nkann nicht zum Schreiben geöffnet werden:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>Die Änderungen konnten nicht in der Datei\n%1\ngespeichert werden</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Octave Dateien (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Alle Dateien (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>&quot;%1&quot;\nist kein gültiger Name.\n\nMit diesem Dateinamen kann das Skript nicht als\nOctave-Befehl aufgerufen werden.\n\nEinen anderen Namen wählen?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>Der Text im Editor kann mit der gewählten\nZeichenkodierung %1 nicht ohne Datenverlust\ngespeichert werden!\n\nBitte wählen Sie eine andere Zeichenkodierung!</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1\nexistiert bereits.\nÜberschreiben?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nAchtung: Der Inhalt des Editors wurde verändert!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>Die Datei &apos;%1&apos; wurde von einer anderen Anwendung verändert. Soll der neue Inhalt geladen werden?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>Die Datei\n%1\nwurde gelöscht oder umbenannt. Soll die Datei jetzt gespeichert werden?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Dateigröße</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Dateityp</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Änderungsdatum</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Versteckte Dateien anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Zeilen abwechselnd einfärben</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Pfad oder Dateinamen eingeben</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Ein Verzeichnis höher</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Aktuelles Octave Verzeichnis anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Zum aktuellen Octave Verzeichnis gehen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Octave Verzeichnis setzen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Setze Octave Verzeichnis zu aktuellem Browser Verzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Aktionen mit aktuellem Verzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Wechsle zum Heimatverzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Wechsle in Verzeichnis...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Dateien suchen...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Neue Datei...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Neues Verzeichnis...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Doppelklick zum Öffnen der Datei, Rechtsklick für weitere Optionen</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Umbenennen...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Öffnen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Im Dateimanager öffnen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Im Texteditor öffnen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Auswahl in die Zwischenablage kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Daten laden</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Aktuelles Verzeichnis setzen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Zum Pfad hinzufügen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Ausgewählte Verzeichnisse</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Ausgewählte Verzeichnisse und Unterverzeichnisse</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Vom Pfad entfernen</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Löschen...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Datei/Verzeichnis löschen</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>Sollen wirklich alle %1 ausgewählten Dateien gelöscht werden?\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>Folgende/s Datei/Verzeichnis wirklich löschen\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>Verzeichnis ist nicht leer und kann daher nicht gelöscht werden</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Fehler beim Löschen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>Datei &quot;%1&quot; kann nicht gelöscht werden.</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Datei-Browser Verzeichnis setzen</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Neue Datei</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Neue Datei in\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Neue Datei.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Fehler beim Erstellen der Datei</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>Die Datei\n&quot;%1&quot;\nkonnte nicht erstellt werden.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Neues Verzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Neues Verzeichnis in\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Neues Verzeichnis</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>Kann Datei &quot;%1&quot; nicht in &quot;%2&quot; umbenennen.</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Dateibrowser</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Dateien durchsuchen</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>Dateisystem</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>Editordateien</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>Viel Spaß!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Zurück</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Beenden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Abbrechen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Wir hoffen, dass Sie Octave nützlich finden.&lt;/p&gt;\n&lt;p&gt;Im Fall von Problemen exisitieren diverse Wege, um Hilfe zu erhalten, einschließlich einer kommerziellen Support-Option, einem Diskussionsforum, einem Wiki oder anderen Support-Kanälen der Community.\nZu jeder dieser Möglichkeiten sind detaillierte Informationen unter &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; zu finden (öffnet im externen Browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Weitere Informationsmöglichkeiten zu Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;&lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (öffnet im externen Browser)&lt;/li&gt;\n&lt;li&gt;Online-Dokumentation im &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML-&lt;/a&gt; oder &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF-&lt;/a&gt;Format (öffnet jeweils im externen Browser)&lt;/li&gt;\n&lt;li&gt;Documentationsfenster in der Octave GUI über das Hilfe-Menü&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Editor: Suchen und Ersetzen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Suchen:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Eingabe des Suchtexts</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>&amp;Ersetzen:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>Eingabe des neuen Texts</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>&amp;Groß-/Kleinschreibung beachten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>Suche vom &amp;Beginn</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>&amp;Umbruch beim Suchen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>&amp;Nächsten suchen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>&amp;Vorherigen suchen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>&amp;Ersetzen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>&amp;Alle ersetzen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>&amp;Mehr...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>&amp;Ganze Wörter</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>&amp;Regulärer Ausdruck</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>Rück&amp;wärts suchen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>In Auswah&amp;l suchen</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Vom Ende suchen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Vom Beginn suchen</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Ergebnis der Ersetzungen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 Vorkommnisse ersetzt</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Suchergebnis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>Keine weiteren Vorkommnisse gefunden</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Dateien suchen</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Name:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>Beginne in:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Verzeichnis, in dem die Suche beginnt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Durchsuchen...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Startverzeichnis auswählen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Aktuelles Verzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>Setze aktuelles Verzeichnis als Startverzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Unterverzeichnisse einschließen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Rekursive Dateisuche durch Unterverzeichnisse</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Verzeichnisnamen einschließen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Auch Verzeichnisse berücksichtigen, deren Namen die Suchanfrage erfüllen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Groß-/Kleinschreibung ignorieren</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>Auch Treffer mit unterschiedlicher Groß-/Kleinschreibung berücksichtigen</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>In Datei vorkommender Text:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>Nur Dateien berücksichtigen, die den angegebenen Text beinhalten</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Zu suchender Text</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Suchergebnisse: Doppelklick öffnet die Datei oder setzt das Verzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Suchergebnisse</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>Leerlauf.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Eingabe der Dateimuster für die Suche.\nVerschiedene Muster konnen mit &apos;;&apos;\ngetrennt werden, z.B. &apos;*.cc ; *.h&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>Suchen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Dateisuche beginnen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Beenden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Suche abbrechen</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>Dateiname/Verzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Dateiinhalt</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>Suche...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 Treffer</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Suchverzeichnis setzen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Dateiname</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Verzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Doppelklick öffnet die Datei</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Doppleklick setzt das Verzeichnis als aktuelles Verzeichnis</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Suchen nach:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>Nächsten suchen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Vorherigen suchen</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Schließen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Suchdialog schließen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Fehler %1 beim Erstellen der Einstellungsdatei\n%2\nLese- und Schreibrechte benötigt für den Ordner\n%3\n\nOctave GUI muss geschlossen werden.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Octave Kritischer Fehler</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Durchsuchen des Befehlsverlaufs.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Skript erzeugen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Filter ausblenden</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Filter anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Doppelklicken, um Befehle in das Befehlsfenster zu übertragen.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Suchbegriff eingeben, um den Befehlsverlauf zu filtern</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Filter</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Befehlsverlauf</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Willkommen bei Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Weiter</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Abbrechen</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Anscheinend wurde die grafische Benutzeroberfläche (GUI) zum ersten Mal auf diesem Computer gestartet.\nKlicken Sie auf &apos;Weiter&apos;, um eine Konfigurationsdatei anzulegen und Octave zu starten.&lt;/p&gt;\n&lt;p&gt;Die Konfigurationsdatei wird in&lt;br&gt;%1&lt;br&gt;gespeichert.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Fenster abkoppeln</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Fenster schließen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>Octave wirklich beenden?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Arbeitsumgebung speichern unter</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Arbeitsumgebung laden</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>Über Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Verzeichnisse durchsuchen</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Octave Dateien (*.m);;Alle Dateien (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Neue Funktion</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Neuer Funktionsname:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>%1 ist eine interne, kompilierte oder inline\ndefinierte Funktion und kann nicht bearbeitet werden.</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>Kann Funktion %1 nicht finden</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Datei</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Öffnen...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Eine vorhandene Datei im Editor öffnen</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Arbeitsumgebung laden...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Arbeitsumgebung speichern unter...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Beenden</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Neu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Neues Skript</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Neue Funktion...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Neue Abbildung</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Bearbeiten</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Rückgängig</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Einfügen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Alles auswählen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Zwischenablage leeren</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Dateien suchen...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Befehlsfenster leeren</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Befehlsverlauf leeren</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Arbeitsumgebung leeren</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Pfad setzen...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Einstellungen...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>De&amp;bug</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Einzelschritt</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Hineinspringen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Herausspringen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Fortfahren</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Debug-Modus beenden</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>&amp;Werkzeuge</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>Starte &amp;Profiler-Session</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>Profiler-Session wieder &amp;aufnehmen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>Profiler &amp;beenden</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>&amp;Daten des Profilers anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>&amp;Fenster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Befehlsfenster anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Befehlsverlauf anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Dateibrowser anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Arbeitsumgebung anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Editor anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Dokumentation anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Variableneditor anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Befehlsfenster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Befehlsverlauf</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Dateibrowser</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Arbeitsumgebung</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Dokumentation</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Variableneditor</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Vorheriges Fenster</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Fensterlayout auf Grundeinstellung zurücksetzen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Hilfe</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Fehler melden</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Octave Pakete</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>Sich beteiligen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Für Octave spenden</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>Auf der Festplatte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>Im Internet</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Neuigkeiten</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Versionshinweise</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Neuigkeiten aus der Community</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Werkzeugleiste</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Verzeichnisnamen eingeben</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Aktuelles Verzeichnis: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Ein Verzeichnis höher</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nDie Neuigkeiten aus der Octave-Community scheinen nicht erreichbar zu sein.\n&lt;/p&gt;\n&lt;p&gt;\nFür aktuelle Neuigkeiten (auf Englisch) besuchen Sie\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;,\nsobald Sie über eine Verbindung zum Internet verfügen (Link öffnet sich im externen Browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Die Entwickler von Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nWeb-Verbindungen zur Anzeige der neuesten Nachrichten aus der Octave Community sind deaktiviert.\n&lt;/p&gt;\n&lt;p&gt;\nFür die neuesten Nachrichten siehe\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;,\nwenn eine Verbindung zum Web besteht (öffnet im externen Browser)\noder Web-Verbindungen für Nachrichten müssen im Octave Einstellungsdialog, Reiter Netzwerkseinstellungen, aktiviert werden.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Die Octave-Entwickler, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Fenster ausblenden</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Fenster ankoppeln</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Fenster abkoppeln</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Hilfe zu &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Dokumentation zu &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>Bearbeite &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop wenn ...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>Temporäre Dateien konnten nicht angelegt werden.\nStellen Sie sicher, dass Sie Schreibrechte auf das temp. Verzeichnis\n%1\nhaben\n\n&quot;Auswahl ausführen&quot; benötigt temporäre Dateien.</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>&apos;%1&apos; drücken, um alle Vorkommnisse von &apos;%2&apos; mit &apos;%3&apos; zu ersetzen.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>Standard</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Erstellen</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>Abbrechen</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Die Datei\n%1\nexistiert nicht. Soll sie erzeugt werden?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>Die Datei %1 befindet sich nicht im Suchpfad. Um die momentan geöffnete Datei auszuführen oder zu debuggen, in das Verzeichnis %2 wechseln oder dieses Verzeichnis dem Suchpfad hinzufügen.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>Die Datei %1 wird von einer Datei gleichen Namens im Suchpfad verdeckt. Um die momentan geöffnete Funktion auszuführen oder zu debuggen, in das Verzeichnis %2 wechseln.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Verzeichnis wechseln oder zum Suchpfad hinzufügen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>Verzeichnis &amp;wechseln</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>Verzeichnis zum &amp;Suchpfad hinzufügen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>Die Datei &apos;%1&apos; mit Versionshinweisen ist leer.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>Die Datei &apos;%1&apos; mit Versionshinweisen kann nicht gelesen werden.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Versionshinweise zu Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Pfad setzen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Alle Änderungen werden sofort aktiv.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Verzeichnis hinzufügen...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Einzelnes Verzeichnis</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Verzeichnis mit Unterverzeichnissen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>An den Anfang verschieben</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>An das Ende verschieben</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Nach oben verschieben</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Nach unten verschieben</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Entfernen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Neu laden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Speichern</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Rückgängig</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Letzte Änderung rückgängig machen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Alle Änderungen rückgängig machen</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Verzeichnis öffnen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>Oben</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>Unten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>Links</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>Rechts</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Vordergrund</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Hintergrund</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Auswahl</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>Cursor</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Auswahl Vordergrund</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Auswahl Hintergrund</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Wechselnder Hintergrund</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>Argument</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>Global</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>persistent</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Umgebungsvariablen</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>Alternatives Farbschema (hell/dunkel)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>Zu einem zweiten Farbschema wechseln.\nHilfreich für helle/dunkle Farbschemas.\nVerwirft noch nicht angewendete aktuelle Änderungen!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>Standardfarben in Abhängigkeit des\naktuellen Farbschemas laden.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>Standardstile in Abhängigkeit des\naktuellen Schemas laden.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>Standard&amp;farben erneut laden</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>Standard&amp;styles erneut laden</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Lade aktuelle Einstellungen ... </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Systemeinstellung</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>Textpositions-Cursor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>Block-Cursor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>Unterstrich-Cursor</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>Farbe für hervorgehobene aktuelle Zeile (Magenta (255, 0, 255) für automatische Farbauswahl)</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Octave-Verzeichnis beim Programmstart festlegen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Dateibrowser-Verzeichnis beim Programmstart festlegen</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Einstellungen werden angewendet... </translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>Konnte %1 nicht als Octave-Tastenkürzel-Datei öffnen</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Attribut-Farben aktivieren</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Keine Tool-Tipps anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Tastenkürzel aus Datei importieren...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Octave Tastenkürzel-Dateien (*.osc);;Alle Dateien (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Tastenkürzel in Datei exportieren...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Tastenkürzel überschreiben</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Dies überschreibt alle Tastenkürzel.\nDie eingestellten Tastenkürzel speichern oder die Aktion abbrechen?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>Nicht speichern</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Octave GUI Einstellungen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Nachrichten aus der Community</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Zurück</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Weiter</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Abbrechen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Beim Start kann Octave optional die Octave-Webseite nach aktuellen Neuigkeiten und Informationen über die Octave-Community überprüfen.\nDie Überprüfung erfolgt höchstens einmal am Tag, und nur Neuigkeiten werden angezeigt, die noch nicht gezeigt wurden.&lt;/p&gt;\n&lt;p&gt;Die Neuigkeiten können auch über den Punkt &quot;Neuigkeiten der Community&quot; im &quot;Hilfe&quot;-Menü angezeigt oder auf dieser Webseite betrachtet werden:\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Octave erlauben, sich beim Start mit der Webseite von Octave zu verbinden, um die neuesten Nachrichten und Informationen aus der Octave Community anzuzeigen.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Neues Tastenkürzel eingeben</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Nutzerdefiniertes Tastenkürzel eingeben\nAktion: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Tastenkürzel durch Eintippen eingeben</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Umschalttaste hinzufügen\n(erlaubt die Eingabe mit Zifferntasten)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Aktuelles Tastenkürzel</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Standard Tastenkürzel</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Leeren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Auf Standardwert setzen</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Doppeltes Tastenkürzel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>Das ausgewählte Tastenkürzel\n  &quot;%1&quot;\nwird bereits für die Aktion\n  &quot;%2&quot;\nverwendet. Soll das Tastenkürzel trotzdem verwendet und für die\nbisherige Aktion deaktiviert werden?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Global</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Datei-Menü</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Bearbeiten-Menü</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Debug-Menü</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Werkzeug-Menü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Fenster-Menü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Hilfe-Menü</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Neuigkeiten-Menü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Handhabung andockbarer Fenster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Tabverhalten in andockbaren Bedienelementen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Suchen &amp; ersetzen in Widgets</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Zoomen in Editor und Dokumentationsanzeige</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Ansicht-Menü</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Ausführen-Menü</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Dokumentationsanzeige</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Browser</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>Element %1 konnte in den Einstellungen für die Tastenkürzel nicht gefunden werden</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Willkommen bei GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Willkommen bei Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Befehlsfenster</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Fenster ankoppeln</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Variablen Editor: </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Fenster abkoppeln</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Anordnung wiederherstellen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Wieder andocken</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Variableneditor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Variablen bearbeiten.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Werkzeugleiste des Variableneditors</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Speichern</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Variable in Datei speichern</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Speichere im Format ...</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Speichere Variable in anderem Format</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Ausschneiden</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Daten in Zwischenablage verschieben</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Daten in Zwischenablage kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Einfügen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Daten aus Zwischenablage in Variable einfügen</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Plotten</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Ausgewählte Daten plotten</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Ausgewählte Daten plotten</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Hoch</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>In der Variablenhierarchie eine Ebene nach oben gehen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>Variable %1 speichern unter</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Ausschneiden</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Einfügen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Leeren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Löschen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Variable aus Auswahl erstellen</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Transponieren</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> Spalten</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> Spalte</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> Zeilen</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> Zeile</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Willkommen bei GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>Name</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Klasse</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimension</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Wert</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Attribut</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Rechtsklick zum Kopieren, Umbenennen oder Anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>komplex</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Klasse</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimension</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Wert</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Attribut</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Arbeitsumgebung</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Variablen einsehen, die sich in der aktiven Arbeitsumgebung befinden.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Text eingeben, um die Arbeitsumgebung zu filtern</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Filter</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Anzeige der Variablen der aktiven Arbeitsumgebung.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Farben für Variablen-Attribute:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Im Variableneditor öffnen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Namen kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Wert kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Umbenennen</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Nur Symbole der obersten Ebene können umbenannt werden</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Filter ausblenden</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Filter anzeigen</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>Kann umgeleiteten Datenstrom mit Deskriptor %1 nicht öffnen.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>Kann das Puffern des Datenstrom mit Deskriptor %1 nicht ausschalten.</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>Kann umgeleiteten Datenstrom mit Deskriptor %1 nicht duplizieren.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>Kann keinePipe für den Datenstrom mit Deskriptor %1 erstellen:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>Kann umgeleiteten Datenstrom mit Deskriptor %1 nicht auf Pipe mit Deskriptor %2 duplizieren (dup2): %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Fehler beim lesen des umgeleiteten Datenstroms</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation>Fehler beim Lesen vom umgeleiteten Datenstrom mit Deskriptor %1.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\nAusgabeumleitung nach </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> wird nicht funktionieren.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\nFehler: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Allgemein</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Nur Octave Logo</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Icons mit Buchstaben</translation>\n    </message>\n    <message>\n        <location line=\"-334\"/>\n        <source>Dock widget title bar</source>\n        <translation>Titelleisten der Unterfenster</translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation>Klein</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Groß</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>Benutzerdefiniert</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation>3D</translation>\n    </message>\n    <message>\n        <location line=\"+565\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Funktioniert gut mit Schriftarten fester Breite.\nDie Position der angezeigten Linie basiert auf der Breite eines Leerzeichens der Standardschriftart.\nDies funktioniert möglicherweise nicht mit Stilen, die eine Schriftart variabler Breite verwenden\noder wenn unterschiedliche Schriftgrößen oder -stile (fett/kursiv/normal) verwendet werden.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Code-Faltung aktivieren</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation>Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Horizontale Bildlaufleiste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"-516\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Wenn ausgewählt, folgt der Fokus der im Hauptfenster verankerten Unterfenster dem Mauszeiger. Dies ermöglicht ein gleiches Verhalten innerhalb des Hauptfensters, wenn &amp;quot;Fokus folgt Mauszeiger&amp;quot; in der Desktop-Umgebung eingestellt ist.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>Fokus folgt dem Mauszeiger für Unterfenster, die im Hauptfenster verankert sind</translation>\n    </message>\n    <message>\n        <location line=\"+494\"/>\n        <source>Show tool bar</source>\n        <translation>Werkzeugleiste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+221\"/>\n        <source>Rotated tabs</source>\n        <translation>Gedrehte Reiter</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Position</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>Max. Breite von Reitern in Zeichen (0: keine Grenze)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. Breite der Reiter in Anzahl Zeichen (durchschnittl. Zeichenbreite). Insbesondere bei gedrehten Reitern hilfreich.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+275\"/>\n        <source>Indentation</source>\n        <translation>Einrückung</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation>Einrücken um</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Tabulator rückt ein</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Auto Einrückung</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Tabulatorweite</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Einrückregeln anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Rücktaste entfernt Einrückung</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Tabulator statt Leerzeichen</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation>Autovervollständigung</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>Schlüsselwörter berücksichtigen</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Groß-/Kleinschreibung beachten</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Wort durch Vorschlag ersetzen</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Wörter im Dokument berücksichtigen</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation>Mit internen Funktionen</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Mit Octave-Funktionen</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Liste von Vorschlägen automatisch anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Extern geänderte Dateien ohne Nachfrage neu laden</translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation>Externen Editor verwenden</translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Zum Öffnen und Speichern verwendete Zeichenkodierung</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation>Editor Stile</translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Ändern der Puffergröße löscht Historie)</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation>Puffergröße des Befehlsverlaufs</translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Schriftart</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Zeilennummern anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"-866\"/>\n        <source>Interface</source>\n        <translation>Benutzeroberfläche</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Vor dem Beenden nachfragen</translation>\n    </message>\n    <message>\n        <location line=\"-72\"/>\n        <source>Graphic icons</source>\n        <translation>Grafische Icons</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Statusleiste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Text inaktiv</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Aktiv</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Background inactive</source>\n        <translation>Hintergrund inaktiv</translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation>Start von Octave</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Auswählen</translation>\n    </message>\n    <message>\n        <location line=\"-1305\"/>\n        <source>Show whitespace</source>\n        <translation>Leerzeichen anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Leerzeichen der Einrückung nicht anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1125\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Nicht existierende Dateien ohne Nachfrage anlegen</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>Kommandozeile (%f=Datei, %l=Zeile):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Cursortyp:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Vordergrundfarbe verwenden</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Schriftgröße</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Dateibrowser</translation>\n    </message>\n    <message>\n        <location line=\"-2031\"/>\n        <source>Normal</source>\n        <translation>Normal</translation>\n    </message>\n    <message>\n        <location line=\"+359\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Diese Einstellungen werden nach dem Laden vorhandener .octaverc-Dateien angewendet.</translation>\n    </message>\n    <message>\n        <location line=\"+540\"/>\n        <source>Show EOL characters</source>\n        <translation>EOL-Steuerzeichen anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation>Standard-EOL-Modus</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Mindestanzahl Zeichen für Öffnen der Liste: </translation>\n    </message>\n    <message>\n        <location line=\"-1812\"/>\n        <source>Preferences</source>\n        <translation>Einstellungen</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(erfordert Neustart)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Native Dateidialoge verwenden</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Icons in der Werkzeugleiste</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Sprache</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Fenstericons der Dock-Widgets</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Stil</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Icon-Thema (erfordert Neustart)</translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation>Blinkender Cursor</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Startbildschirm beim Start anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Arbeitsverzeichnis des Octave Interpreters zum Programmstart</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Letztes Arbeitsverzeichnis der vorherigen Sitzung wiederherstellen</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Befehlsfenster</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Fokus zum Befehlsfenster wechseln, wenn ein Befehl aus einem anderen Widget ausgeführt wird</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Debugstelle zusätzlich zum Marker im Editor auch im Befehlsfenster anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Farben im Befehlsfenster</translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Differenz zur Schriftgröße der Zeilennummern</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Aktuelle Zeile hervorheben (Farbe kann unter &quot;Editor Stile&quot; angepasst werden)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Alle Vorkommnisse eines Wortes nach einem Doppelklick hervorheben</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Tabs</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Reiter drehen: Vertikal, wenn oben oder unten und horizontal, wenn links oder rechts. Die Schließen-Schaltfläche wird in gedrehten Reitern nicht angezeigt.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Kommentare (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Strings, die beim Entfernen von Kommentaren berücksichtigt werden</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>String, der zum Auskommentieren des ausgewählten Texts genutzt wird</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Lange Zeilen</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>bei Zeilenlänge umbrechen</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>nur in Kommentaren</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Zeilenlänge</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Markierung langer Zeilen</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Linie</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Hintergrund</translation>\n    </message>\n    <message>\n        <location line=\"+38\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Lange Zeilen an Fensterrand umbrechen</translation>\n    </message>\n    <message>\n        <location line=\"+153\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Automatisches schließen von &quot;if&quot; usw.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Nichts</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot; usw.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation>Debuggen</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Immer Debug-Haltepunkte und -Zeiger anzeigen (betroffene Datei öffnen)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Dateiverwaltung</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Editor-Tabs der vorherigen Sitzung oder nach dem Schließen des Editors wiederherstellen</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Alle Dateien beim Schließen des Editorfensters schließen</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>Erzwinge ein Leerzeile am Ende der Datei beim Speichern</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>Entferne Leerzeichen am Zeilenende beim Speichern</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>Das Verzeichnis des Dialogs zum Öffnen einer Datei folgt der aktuellen Editordatei statt des aktuellen Octave-Verzeichnisses </translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Wähle Schriftart, Schriftgröße (als Differenz zur Standard-Schriftgröße), Schriftstil (&lt;b&gt;f&lt;/b&gt;ett, &lt;b&gt;k&lt;/b&gt;ursiv, &lt;b&gt;u&lt;/b&gt;nterstrichen), Textfarbe und Hintergrundfarbe (bei letzterer ist Magenta (255,0,255) ein Platzhalter für die Standard-Hintergrundfarbe).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Behavior</source>\n        <translation>Verhalten</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Letztes Verzeichnis der vorherigen Sitzung wiederherstellen</translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Dateierweiterungen (durch &quot;;&quot; getrennt), für die der Standard-Texteditor verwendet werden soll:</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Arbeitsumgebung</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Farben für Variablen-Attribute</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Schriftart des Befehlfensters verwenden</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Tastenkürzel importieren</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Derzeitige Tastenkürzel exportieren</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Tastenkürzel auf Vorgaben zurücksetzen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Standard</translation>\n    </message>\n    <message>\n        <location line=\"+232\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - Dialog schließen und Einstellungen anwenden&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Anwenden - &lt;/span&gt;Einstellungen anwenden aber Dialog geöffnet lassen&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Abbrechen - &lt;/span&gt;Dialog schließen und noch nicht angewendete Änderungen verwerfen&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt;Einstellungen neu laden und bisherige Änderungen verwerfen&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-227\"/>\n        <source>Actual</source>\n        <translation>Gesetzt</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Netzwerk</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Octave erlauben, Neuigkeiten und Informationen von der Octave Webseite anzuzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Proxy-Server</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; oder &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. Mit der letztgenannten Auswahl wird der Proxy-Server durch die erste nicht leere Umgebungsvariable ALL_PROXY, HTTP_PROXY oder HTTPS_PROXY bestimmt.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Proxy-Server verwenden</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Variableneditor</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Standard-Zeilenhöhe</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Standard-Spaltenbreite</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Farben für Variableneditor</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Zeilen abwechselnd einfärben</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Deaktiviert globale Tastenkürzel, um\nÜberschneidungen mit den readline Tastenkürzeln\nzu vermeiden. Ausnahmen: Ctrl-C zur Unterbrechung\neiner Rechnung oder die Tastenkürzel zum Wechseln\nder aktiven Unterfenster.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Globale Tastenkürzel deaktivieren, wenn das Befehlsfenster den Fokus hat</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Octave-Arbeitsverzeichnis und Dateibrowser synchronisieren</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>Verzeichnis im Dateibrowser beim Programmstart (nur falls nicht mit dem Octave-Arbeitsverzeichnis synchronisiert)</translation>\n    </message>\n    <message>\n        <location line=\"+302\"/>\n        <source>Shortcuts</source>\n        <translation>Tastenkürzel</translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Deaktiviere Tastenkürzel zur Aktivierung\nvon Menüs, um Konflikte mit den readline\nTastenkürzeln zu vermeiden.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>Menü-Tastenkürzel der Hauptfenster-Menüs deaktivieren, wenn Fokus in der Befehlszeile</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation>Exportieren</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importieren</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Ändern eines Tastenkürzels durch Doppelklick der Spalte &quot;Gesetzt&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Aktion</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Hostname:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Proxy Typ:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Port:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Nutzername:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Passwort:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Fenster ab-/andocken</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Fenster schließen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Neue Datei</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Neue Funktion</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Neue Abbildung</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Datei öffnen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Arbeitsumgebung laden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Arbeitsumgebung speichern unter</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Octave beenden</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Einfügen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Rückgängig</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Alles auswählen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Zwischenablage leeren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>In Dateien suchen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Befehlsfenster leeren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Befehlsverlauf leeren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Arbeitsumgebung leeren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Pfad setzen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Einstellungen</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Einzelschritt</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>Hineinspringen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Herausspringen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Fortfahren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Debug-Modus beenden</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Starte/Beende Profiler-Session</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Profiler-Session wieder aufnehmen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Profiler-Daten anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Befehlsfenster anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Befehlsverlauf anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Dateibrowser anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Arbeitsumgebung anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Editor anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Dokumentation anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Variableneditor anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Befehlsfenster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Befehlsverlauf</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Dateibrowser</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Arbeitsumgebung</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Dokumentation</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Variableneditor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Vorheriges Fenster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Fensterlayout auf Grundeinstellung zurücksetzen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Offline-Dokumentation anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Online-Dokumentation anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Fehler melden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Octave Pakete</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Zu Octave beitragen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Ressourcen für Octave-Entwickler</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>Über Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Versionshinweise</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Nachrichten aus der Community</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Tab schließen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Alle Tabs schließen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Andere Tabs schließen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Zum linken Tab wechseln</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Zum rechten Tab wechseln</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Tab nach links verschieben</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Tab nach rechts verschieben</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Vergrößern</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Verkleinern</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Normale Größe</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Funktion bearbeiten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Datei speichern</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Datei speichern unter</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Drucken</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Wiederherstellen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Ausschneiden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Suchen und Ersetzen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Nächsten suchen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Vorherigen suchen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Bis zum Anfang des Wortes löschen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Bis zum Ende des Wortes löschen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Bis zum Anfang der Zeile löschen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Bis zum Ende der Zeile löschen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Zeile löschen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Zeile kopieren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Zeile ausschneiden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Zeile oder Auswahl duplizieren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Zeilen tauschen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Vervollständigungsliste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Auswahl kommentieren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Kommentar entfernen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Auswahl kommentieren (String auswählen)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Auswahl zu Großbuchstaben</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Auswahl zu Kleinbuchstaben</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Auswahl eine Ebene einrücken</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Auswahl eine Ebene ausrücken</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Code automatisch einrücken</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Zeilenenden für Windows umwandeln</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Zeilenenden für Linux umwandeln</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Zeilenenden für Mac umwandeln</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Gehe zu Zeile</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Zur zugehörigen Klammer springen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Bis zur zugehörigen Klammer auswählen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Lesezeichen umschalten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Nächstes Lesezeichen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Vorheriges Lesezeichen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Alle Lesezeichen entfernen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Stil-Einstellungen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Zeilennummern anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Leerzeichen anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Zeilenenden anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Einrückungshinweise anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Markierung für lange Zeilen anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Werkzeugleiste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Statusleiste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Horizontale Bildlaufleiste anzeigen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Tabs alphabetisch sortieren</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Haltepunkt umschalten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Nächster Haltepunkt</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Vorheriger Haltepunkt</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Alle Haltepunkte entfernen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Datei ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Auswahl ausführen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Ausführen der Tests</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Ausführen der Demos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Hilfe zum Schlüsselwort</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Dokumentation zum Schlüsselwort</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>Startseite</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>Seite zurück</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>Seite vor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Lesezeichen zur aktuellen Seite setzen</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/en_US.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-334\"/>\n        <source>Dock widget title bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+565\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-516\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+494\"/>\n        <source>Show tool bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+221\"/>\n        <source>Rotated tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+260\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Indentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-866\"/>\n        <source>Interface</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-72\"/>\n        <source>Graphic icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Background inactive</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1305\"/>\n        <source>Show whitespace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1125\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2031\"/>\n        <source>Normal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+359\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+540\"/>\n        <source>Show EOL characters</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1812\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+191\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Behavior</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+232\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-227\"/>\n        <source>Actual</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+302\"/>\n        <source>Shortcuts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/es_ES.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"es_ES\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Nombre de fichero no válido</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Diferencia con el tamaño predeterminado</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Color de fondo. Predeterminado a magenta (255,0,255)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translatorcomment>Abreviatura para caracteres en negrita</translatorcomment>\n        <translation>n</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translatorcomment>Abreviatura para caracteres en cursiva</translatorcomment>\n        <translation>c</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translatorcomment>Abreviatura para caracteres subrayados</translatorcomment>\n        <translation>s</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>Editar &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Ayuda de &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Documentación de &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Pegar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Seleccionar todo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Ejecutar selección</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>Editar selección</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>Ayuda de la selección</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>Documentación de la selección</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Limpiar ventana</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Editar %1 en línea %2</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>selección copiada al portapapeles</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Abrir enlace</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Copiar dirección de enlace</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Enviar un correo electrónico a...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>Copiar la dirección de correo electrónico</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Editar %1 en línea %2</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Anotación</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Texto</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translatorcomment>Cadena de texto/caracteres</translatorcomment>\n        <translation>Cadena de texto</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Tipo de fuente</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>negrita</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>n</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>cursiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>c</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>color</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>centro</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>derecha</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>Alineación horizontal</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>Alineación vertical</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>parte superior</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>parte inferior</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Posición</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Ancho</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Alto</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>Unidades</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalizado</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Ajustar a cuadro</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Cuadro</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translatorcomment>En este contexto es más adecuada la traducción &quot;fondo&quot; en lugar de &quot;segundo plano&quot;</translatorcomment>\n        <translation>Fondo</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translatorcomment>Borde u orilla</translatorcomment>\n        <translation>Borde</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Estilo de línea</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>ninguno</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Ancho de línea</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Seleccionar todo</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Pausa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Detener</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Continuar</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Widget de comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Noticias de la comunidad de Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>Valor predeterminado/por defecto</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Error</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>Entrada de órdenes</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Documentación de Octave</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>No se ha podido copiar la ayuda a un fichero temporal.\nLa capacidad de búsqueda puede verse afectada.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>No se han podido configurar los datos necesarios para el\nvisor de documentación. Es posible que el módulo SQlite de\nla biblioteca Qt no esté instalado.\nSólo estará disponible la ayuda a través de la ventana de comandos.</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>Contenido</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Introduzca el texto a buscar en el índice de funciones</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Buscar</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>Índice de funciones</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Favoritos</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>Ir al índice general</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Ir hacia atrás</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Páginas anteriores</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>Ir hacia delante</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Páginas siguientes</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Buscar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Ampliar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Reducir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Zoom original</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>Marcar la página actual como favorito</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>Imposible mostrar el fichero de ayuda %1.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nNo se han cargado favoritos de documentación</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: cargando favoritos de documentación</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Introduzca texto para buscar en favoritos</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Filtrar</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Nueva carpeta</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Abrir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Renombrar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>Elimin&amp;ar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>&amp;Añadir carpeta</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>Ocultar la ventana de &amp;búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>Mostrar la ventana de &amp;búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: guardando favoritos de documentación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>Imposible escribir el fichero %1:\n%2.\n\nNo se han guardado los favoritos de documentación.\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>Imposible leer el fichero %1:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>No se ha encontrado elemento de inicio en %1.\n¿Fichero de favoritos no válido?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>El fichero\n%1\nno es un fichero XBEL versión 1.0 válido.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Título desconocido</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Documentación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Consulte la documentación para obtener ayuda.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Cerrar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>Cerrar &amp;todo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>Cerrar los &amp;otros</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>Cambiar al widget de la &amp;izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>Cambiar al widget de la &amp;derecha</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation>Abrir el editor de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation>Hacer clic para poner el foco en el editor</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Cerrar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>Cerrar &amp;todo</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Ejecutar</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Asignar el &amp;directorio actual</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Editor de Octave</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>No se puede abrir el editor de texto personalizado\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Todavía no existe una configuración para el editor.\n¿Desea abrir las preferencias?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Continuar</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Guardar archivo y ejecutar</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Editor de Octave</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>Archivo no guardado. Hay abierto en el editor un archivo con el nombre seleccionado\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>La pestaña asociada del editor de texto ha desaparecido.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>No se puede abrir el archivo\n%1\npara leer: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>El archivo\n%1\nno existe. ¿Desea crearlo?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Crear</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>No se puede abrir el archivo\n%1\npara escribir: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Archivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>Archivos &amp;recientes del editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>&amp;Editar función</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>&amp;Guardar archivo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>Guardar archivo &amp;como...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Cerrar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Cerrar todo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Cerrar otros archivos</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Imprimir...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Editar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Rehacer</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>Cor&amp;tar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>&amp;Buscar y reemplazar...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>Buscar &amp;siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>Buscar &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>&amp;Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Eliminar línea</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Copiar línea</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Cortar línea</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Eliminar hasta el inicio de palabra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Eliminar hasta el fin de palabra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Eliminar hasta el inicio de línea</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Eliminar hasta el final de línea</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Duplicar selección/línea</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Intercambiar líneas</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>&amp;Mostrar lista de comandos coincidentes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Formato</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>Convertir selección a &amp;mayúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>Convertir selección a m&amp;inúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>&amp;Comentar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>&amp;Eliminar comentario</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Comentar (seleccionando cadena de texto)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>&amp;Sangría rigurosa de la selección</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>&amp;Eliminar sangría rigurosa de la selección</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Aplicar sangría a código</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Convertir caracteres de fin de línea a &amp;Windows (CR+LF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Convertir caracteres de fin de línea a &amp;Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Convertir caracteres de fin de línea a Legacy &amp;Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>&amp;Navegación</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>&amp;Ir a línea...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Mover a paréntesis correspondiente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Seleccionar a paréntesis correspondiente</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>Marcador &amp;siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>Marcador &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>&amp;Alternar marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>&amp;Eliminar todos los marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Preferencias...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>Preferencias de &amp;estilos...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>&amp;Ver</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>&amp;Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>Mostrar números de &amp;línea</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>Mostrar &amp;espacios en blanco</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Mostrar caracteres de &amp;fin de línea</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>Mostrar guías de &amp;sangría</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>Mostrar &amp;marcador de longitud de línea</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>Mostrar &amp;barra de herramientas</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>Mostrar barra de &amp;estado</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>Mostrar barra de &amp;desplazamiento horizontal</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>&amp;Ampliar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>&amp;Reducir</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>Tamaño &amp;normal</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>&amp;Ordenar pestañas alfabéticamente</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Depurar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>&amp;Alternar puntos de interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>Punto de interrupción &amp;siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>Punto de interrupción &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>&amp;Eliminar todos los puntos de interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>&amp;Ejecutar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Guardar y ejecutar/continuar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>Ejecutar &amp;selección</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Guardar fichero y ejecutar todos los &amp;tests</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Guardar fichero y ejecutar todas las &amp;demos</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Ayuda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>&amp;Ayuda de palabras clave</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>&amp;Documentación de palabras clave</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>Archivos recientes</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Copiar la &amp;ruta completa del archivo</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>Línea:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>Columna:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>Codificación:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>Fin de línea:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Condición de punto de interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>ERROR: </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Editor de Octave</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>No se puede añadir un punto de interrupción a un archivo modificado o sin nombre.\nPuede guardar el fichero y añadir el punto de interrupción o cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Ir a la línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Número de línea</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Comentar texto seleccionado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Comentar cadena de texto a utilizar:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;sin nombre&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>¿Desea cancelar el cierre, guardar o descartar los cambios?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>El archivo\n\n  %1\n\nestá a punto de ser cerrado, pero ha sido modificado.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>Imposible leer el archivo &apos;%1&apos;\ncon la codificación seleccionada &apos;%2&apos;: %3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>Hubo problemas en la lectura del archivo\n%1\ncon la codificación seleccionada %2.\n\nLa modificación y el almacenamiento del archivo podría significar pérdida de datos.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>&amp;Editar de todos modos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>Cambi&amp;ar codificación</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>C&amp;errar</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Seleccione una nueva codificación por defecto</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Por favor, seleccione una nueva codificación\npara la recarga del archivo actual.\n\nEsto no cambiará la codificación predeterminada.\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Depurar programa o guardar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Este archivo esta siendo ejecutado.\n¿Desea interrumpir la depuración y guardar?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>No se ha podido abrir el archivo %1 para escribir:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>Los cambios no se han podido guardar en el archivo\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Archivos de Octave (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Todos los archivos (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>&quot;%1&quot;\nno es un identificador válido.\n\nSi mantiene ese nombre de archivo no le será posible\nllamar a su script usando su nombre como comando de Octave.\n\n¿Desea seleccionar otro nombre?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>El contenido actual del editor no puede ser escrito\ncon la codificación seleccionada %1.\nSu utilización podría ocasionar una pérdida de datos.\n\nPor favor, seleccione otra codificación.</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1\n ya existe\n¿Desea sobrescribirlo?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nAviso: el contenido del editor ha sido modificado.</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>Parece que el archivo &apos;%1&apos; ha sido modificado por otra aplicación. ¿Desea recargarlo?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>Parece que el archivo\n%1\nha sido eliminado o renombrado. ¿Desea guardarlo ahora?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Tamaño del archivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Tipo de archivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Fecha de modificación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Mostrar ocultos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Alternar colores de filas</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Introduzca la ruta o el nombre del archivo</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Directorio superior</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Mostrar el directorio de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Ir al directorio actual de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Seleccionar el directorio de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Asignar el directorio actual del navegador como directorio de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Acciones en el directorio actual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Mostrar el directorio de inicio</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Asignar directorio del navegador...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Buscar archivos...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Nuevo archivo...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Nuevo directorio...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Doble clic para abrir el archivo o la carpeta; clic en el botón derecho para ver las alternativas</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Renombrar...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Abrir</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Abrir en explorador de archivos del sistema</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Abrir en el editor de texto</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Copiar selección al portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Ejecutar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Cargar datos</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Asignar directorio actual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Añadir a la ruta de trabajo (path)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Directorios seleccionados</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Directorios y subdirectorios seleccionados</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Eliminar de la ruta de trabajo (path)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Eliminar...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Eliminar archivo/directorio</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>¿Está seguro de que quiere eliminar los %1 ficheros seleccionados?\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>¿Está seguro de que quiere eliminar\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>No se puede eliminar un directorio que no esté vacío</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Error al borrar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>No se pudo eliminar el fichero &quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Seleccionar el directorio del explorador de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Crear archivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>¡Crear archivo en\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Nuevo archivo.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Error al crear el archivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>No se pudo crear el archivo\n&quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Crear directorio</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Crear carpeta en\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Nuevo directorio</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>No se puede renombrar el archivo &quot;%1&quot; a &quot;%2&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Explorador de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Explorar sus archivos</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>Sistema de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>Editor de archivos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>¡Disfrútelo!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Terminar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Deseamos que Octave le sea una herramienta útil.&lt;/p&gt;\n&lt;p&gt;Si encuentra algún problema existen una serie de vías para obtener ayuda, que incluyen opciones comerciales, un panel de discusión, una wiki y otros canales basados en la comunidad.\nPuede hallar más información al respecto visitando &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (abre una ventana externa del navegador).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Para obtener más información acerca de Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visite &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (abre una ventana externa del navegador)&lt;/li&gt;\n&lt;li&gt;Vea la documentación online en &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; o &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; (el enlace se abre en una ventana externa del navegador)&lt;/li&gt;\n&lt;li&gt;Abra el navegador de documentación con el menú de ayuda&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Editor: buscar y reemplazar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Buscar:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Introduzca el texto a buscar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>R&amp;eemplazar:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>Introduzca el texto de reemplazo</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>Distinguir &amp;mayúsculas/minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>Buscar desde el &amp;inicio</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>&amp;Marcar mientras se busca</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>Buscar &amp;siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>Buscar &amp;anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>&amp;Reemplazar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>Reemplazar &amp;todo</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>&amp;Más...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>Palabras &amp;completas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>&amp;Expresiones regulares</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>Buscar hacia &amp;atrás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>Buscar se&amp;lección</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Buscar desde el final</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Buscar desde el inicio</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Reemplazar resultado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 instancia(s) reemplazada(s)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Resultado de la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>No se han encontrado más coincidencias</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Buscar archivos</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Denominado:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>Empezar en:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Introduzca el directorio inicial de búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Explorar...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Explorar para seleccionar el directorio inicial de búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Directorio actual</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>Asignar el directorio actual como directorio de inicio de búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Buscar en subdirectorios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Buscar archivos de forma recursiva en los directorios</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Incluir nombres de directorios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Incluir directorios que coicidan en los resultados de la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Ignorar mayúsculas/minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>No tener en cuenta mayúsculas/minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>Que contenga el texto:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>Incluir en los resultados únicamente los ficheros que contengan el texto especificado</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Texto a coincidir</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Resultados: doble clic abre el fichero o asigna el directorio</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Resultados de la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>Inactivo.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Introduzca los patrones de búsqueda para el nombre del fichero.\nSe pueden asignar varios separados por punto y coma &apos;;&apos;.\nPor ejemplo, &apos;*.cc; *.h&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>Buscar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Empezar la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Detener</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Detener la búsqueda</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>Nombre del archivo/ubicación</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Contenido del archivo</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>Buscando...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 coincidencia(s)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Seleccionar el directorio de búsqueda</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Nombre del archivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Directorio</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Haga doble clic para abrir el archivo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Haga doble clic para asignar el directorio</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Buscar:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>Buscar hacia delante</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Buscar hacia atrás</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Cerrar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Cerrar el cuadro de búsqueda</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Error %1 al crear el fichero de configuración\n%2\nAsegúrese de que tiene permisos de lectura y escritura para\n%3\n\nEl entorno gráfico de Octave se cerrará.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Error crítico de Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Explorar y buscar en el historial de comandos.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Evaluar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Crear un guion (script)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Ocultar la ventana de filtrado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Mostrar el filtro</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Haga doble clic en un comando para introducirlo en la ventana de comandos.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Introduzca texto para filtrar el historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Filtrar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Historial de comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>¡Bienvenido a Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Parece que está utilizando la interfaz gráfica de Octave por primera vez en esta computadora.\nPulse &apos;Siguiente&apos; para crear un archivo de configuración e iniciar Octave.&lt;/p&gt;\n&lt;p&gt;El archivo de configuración se guardará en&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Desacoplar widget</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Cerrar widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Perfilado</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>¿Está seguro de que desea salir de Octave?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Guardar el espacio de trabajo como</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Cargar espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>Acerca de Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Explorar directorios</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Archivos de Octave (*.m);;Todos los archivos (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Nueva función</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Nombre para la nueva función:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>%1 es una función integrada (built-in), compilada o inline,\npor lo que no se puede editar.</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>No se encuentra la función %1</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Editor de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Archivo</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Abrir...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Abrir un archivo existente en el editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Cargar espacio de trabajo...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Guardar el espacio de trabajo como...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Salir</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Nuevo</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Nuevo guion (script)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Nueva función...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Nueva figura</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Editar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Deshacer</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Pegar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Seleccionar todo</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Limpiar el portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Buscar archivos...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Limpiar la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Limpiar el historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Limpiar el espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Asignar ruta de trabajo (path)...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Preferencias...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>&amp;Depurar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Salto individual</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Saltar a</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Salir de</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Continuar</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Salir del modo de depuración</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>&amp;Herramientas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>Iniciar sesión de &amp;perfilado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>&amp;Reanudar sesión de perfilado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>&amp;Detener sesión de perfilado</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>&amp;Mostrar los datos de perfilado</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>&amp;Ventana</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Mostrar la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Mostrar el historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Mostrar el explorador de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Mostrar el espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Mostrar editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Mostrar documentación</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Mostrar editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Explorador de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Documentación</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Widget anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Restablecer el esquema de ventana predeterminado</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Ayuda</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Informar de fallo (bug)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Paquetes de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>Involúcrese</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Donar a Octave</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>En disco</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>En línea</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Noticias</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Notas de la versión</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Noticias de la comunidad</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Barra de herramientas</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Introduzca el nombre del directorio</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Directorio actual: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Directorio superior</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nLas fuentes de noticias de la comunidad Octave parece que no están disponibles.\n&lt;/p&gt;\n&lt;p&gt;\nPara ver las últimas novedades visite\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\ncuando tenga conexión a la web (el enlace se abre en un navegador externo).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Los desarrolladores de Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nLa conexión a la web para mostrar las últimas noticias de la comunidad de Octave se ha deshabilitado.\n&lt;/p&gt;\n&lt;p&gt;\nPara ver las últimas noticias visite\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\ncuando tenga conexión a la red (el enlace se abre en un navegador externo)\no active en la ventana de configuración la opción para verlas.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Los desarrolladores de Octave, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Ocultar widget</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Acoplar widget</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Desacoplar widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>Ayuda sobre</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>Documentación sobre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>Editar</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop en caso de...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Editor de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>Falló la creación de archivos temporales.\nAsegúrese de que tiene permiso de escritura en el directorio\n%1\n\n&quot;Ejecutar selección&quot; requiere ficheros temporales.</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>Presione &apos;%1&apos; para reemplazar todos los casos de &apos;%2&apos; con &apos;%3&apos;.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>Valor predeterminado/por defecto</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Crear</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>El archivo\n%1\nno existe. ¿Desea crearlo?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Editor de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>El archivo %1 no existe en las rutas de trabajo (path). Para ejecutar o depurar la función que está editando tiene que cambiar al directorio %2 o agregarlo a las rutas de trabajo.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>Existe un archivo con el mismo nombre que %1 en la ruta de trabajo (path). Para ejecutar o depurar la función que se está editando cambie al directorio %2.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Cambiar directorio o agregar directorio a la ruta de trabajo (path)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>&amp;Cambiar directorio</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>&amp;Agregar directorio a ruta de trabajo (path)</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>El archivo de notas de la versión %1 está vacío.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>El archivo de notas de la versión %1 no se puede leer.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Notas de la versión de Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Asignar rutas de trabajo (path)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Todos los cambios tienen efecto inmediato.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Añadir directorio...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Directorio individual</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Directorio y subdirectorios</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>Mover al inicio</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>Mover al final</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Mover arriba</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Mover abajo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Eliminar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Recargar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Guardar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Deshacer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Deshacer el último cambio</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Deshacer todos los cambios</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Abrir directorio</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>Primero</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>Último</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>Izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>Derecha</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Primer plano</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Segundo plano</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Selección</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>Cursor</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Primer plano seleccionado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Segundo plano seleccionado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Fondo alternativo</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>argumento</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>global</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>persistente</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Variables de entorno</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>Modo de color secundario (claro/oscuro)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>Cambio a un conjunto de colores alternativo.\nÚtil para la definición de modos luminosos/oscuros.\nSe descartan los cambios no aplicados.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>La recarga de los colores por defecto\ndepende del modo seleccionado actual.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>La recarga de los valores de estilo por defecto\ndepende del modo seleccionado actual.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>&amp;Recargar colores por defecto</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>&amp;Recarga el estilo por defecto</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Cargando las preferencias actuales... </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Configuración del sistema</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>Cursor IBeam</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>Cursor de bloque</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>Cursor de subrayado</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>Color de la línea resaltada actual (por defecto, magenta (255,0,255))</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Ajuste del directorio de inicio de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Ajuste del directorio de inicio del explorador de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Aplicando preferencias... </translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>Fallo al abrir %1 como archivo de atajos de teclado de Octave</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Activar atributos de color</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Ocultar consejos de uso</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Importar atajos de teclado desde archivo...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Archivo de acceso directo de Octave (*.osc);;Todos los archivos (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Exportar atajos de teclado a archivo...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Sobrescribir atajos de teclado</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Está a punto de sobrescribir todos los atajos de teclado.\n¿Le gustaría guardar el conjunto actual o cancelar esta acción?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>No guardar</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Preferencias del entorno gráfico de Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Noticias de la comunidad</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;En el momento de iniciar Octave, de manera opcional se hará una revisón del sitio web del proyecto para buscar noticias e información acerca de la comunidad.\nEsto ocurrirá como máximo una vez al día y las noticias sólo serán desplegadas si existen cambios recientes desde la última visita al sitio web.&lt;/p&gt;\n&lt;p&gt;También se puede acceder a las noticias presionando &quot;Noticias de la comunidad&quot; en el menú &quot;Ayuda&quot;, o visitando\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Permitir a Octave conectarse a la web en el inicio para mostrar las últimas noticias e información de la comunidad.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Introduzca nuevo atajo de teclado</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Introduzca atajo de teclado\nAcción: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Introduzca el atajo tecleándolo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Añadir el modificador Shift\n(permite introducir teclas numéricas)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Atajo de teclado actual</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Atajo de teclado por defecto</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Limpiar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Establecer como por defecto</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Atajo de teclado doble</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>El atajo de teclado seleccionado\n  &quot;%1&quot;\nesta actualmente en uso para la acción\n  &quot;%2&quot;.\n¿Desea utilizarlo y eliminar la configuración anterior?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Global</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Menú archivo</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Menú editar</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Menú depuración</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Menú de herramientas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Menú ventana</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Menú ayuda</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Menú noticias</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Manejo de widgets acoplados</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Manejo de pestañas en widgets acoplados</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Buscar y reemplazar en widgets acoplados</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Zoom en el editor y documentación</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Menú ver</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Menú ejecutar</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Visor de documentación</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Explorador</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>el ítem %1 no ha sido encontrado en la configuración de los atajos de teclado</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Bienvenido a GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>¡Bienvenido a Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Ventana de comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Acoplar widget</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Editor de variables: </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Desacoplar widget</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Restablecer geometría</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Reacoplar</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Editar variables.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Barra de herramientas del editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Guardar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Guardar variable en un archivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Guardar en formato ...</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Guardar variable en un fichero en formato...</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Cortar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Cortar datos al portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Copiar datos al portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Pegar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Pegar portapapeles a variable de datos</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Dibujar</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Dibujar datos seleccionados</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Dibujar datos seleccionados</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Arriba</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>Ir un nivel hacia arriba en la jerarquía de variables</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>Guardar variable %1 como</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Cortar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Pegar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Limpiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Eliminar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Variable de la selección</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Trasponer</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> columnas</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> columna</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> filas</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> fila</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Bienvenido a GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>Nombre</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Clase</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensión</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Atributo</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Clic con el botón derecho para copiar, renombrar o mostrar</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>complejo</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Clase</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensión</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Atributo</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Ver variables en el espacio de trabajo activo.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Introduzca texto para filtrar el espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Filtrar</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Ver las variables del espacio de trabajo activo.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Colores para los atributos de variable:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Abrir en el editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Copiar nombre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Copiar valor</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Renombrar</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Sólo los símbolos de nivel superior pueden ser renombrados</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Ocultar la ventana de filtrado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Mostrar el filtro</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>No se puede abrir el flujo redirigido fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>No se puede desactivar el almacenamiento en buffer del flujo fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>No se puede aplicar la función dup() de la biblioteca estándar de C al flujo redirigido fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>No se puede crear la tubería para el flujo redirigido fd = %1:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>No se puede aplicar la función dup2() de la biblioteca estándar de C al flujo redirigido fd = %1\npara crear la tubería fd = %2: %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Error en la escucha de los flujos redirigidos</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation>Error en la lectura del flujo redirigido fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\nLa redirección de salida a </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> no funcionará.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\nError: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>General</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Sólo logo de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Iconos de texto</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Graphic icons</source>\n        <translation>Iconos gráficos</translation>\n    </message>\n    <message>\n        <location line=\"-341\"/>\n        <source>Dock widget title bar</source>\n        <translation>Widget de barra de título</translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation>Pequeño</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Grande</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>Estilo personalizado</translation>\n    </message>\n    <message>\n        <location line=\"+244\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Estas configuraciones se aplicarán después de la carga de cualquier archivo de inicio .octaverc.</translation>\n    </message>\n    <message>\n        <location line=\"+353\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+187\"/>\n        <source>Show EOL characters</source>\n        <translation>Mostrar caracteres de fin de línea</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Ajustar las líneas demasiado largas al tamaño de la ventana</translation>\n    </message>\n    <message>\n        <location line=\"+558\"/>\n        <source>Default EOL mode</source>\n        <translation>Carácter de fin de línea por defecto</translation>\n    </message>\n    <message>\n        <location line=\"-503\"/>\n        <source>Indent width</source>\n        <translation>Ancho de sangría</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Sangrar con tabulación</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Sangría automática</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Ancho del tabulador</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Mostrar guías de sangría</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>La tecla de retroceso quita sangría</translation>\n    </message>\n    <message>\n        <location line=\"+120\"/>\n        <source>Match keywords</source>\n        <translation>Coincidir en palabras clave</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Distinguir mayúsculas/minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Sustituir palabra con sugerencia</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Coincidir palabras en documento</translation>\n    </message>\n    <message>\n        <location line=\"-643\"/>\n        <source>Use custom file editor</source>\n        <translation>Utilizar editor de archivos personalizado</translation>\n    </message>\n    <message>\n        <location line=\"+1009\"/>\n        <source>Editor Styles</source>\n        <translation>Estilos del editor</translation>\n    </message>\n    <message>\n        <location line=\"-1485\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Tipo de fuente</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Mostrar números de línea</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Show whitespace</source>\n        <translation>Mostrar espacios en blanco</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>No mostrar los espacios usados para la sangría</translation>\n    </message>\n    <message>\n        <location line=\"+935\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Número de caracteres a escribir antes de mostrar la lista: </translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Crear archivos no existentes sin consultar</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>línea de comandos (%f=archivo, %l=línea):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Tipo de cursor:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Usar color de primer plano</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Tamaño de fuente</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Explorador de archivos</translation>\n    </message>\n    <message>\n        <location line=\"-2118\"/>\n        <source>Interface</source>\n        <translation>Interfaz</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Confirmar antes de salir</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Mostrar barra de estado</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Texto inactivo</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Activo</translation>\n    </message>\n    <message>\n        <location line=\"-89\"/>\n        <source>Normal</source>\n        <translation>Normal</translation>\n    </message>\n    <message>\n        <location line=\"+128\"/>\n        <source>Background inactive</source>\n        <translation>Fondo inactivo</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation>3D</translation>\n    </message>\n    <message>\n        <location line=\"+206\"/>\n        <source>Octave Startup</source>\n        <translation>Inicio de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Explorar</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Esto funciona correctamente con fuentes con espaciado fijo. Se dibuja la línea en una posición basada en la anchura de un carácter de la fuente por defecto. Esto podría no funcionar correctamente si los estilos utilizan fuentes proporcionales o si se utilizan fuentes de varios tamaños, negrita, cursiva y textos normales.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Activar plegado de código</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CR+LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translatorcomment>No sé cómo traducirlo exactamente</translatorcomment>\n        <translation>Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Mostrar barra de desplazamiento horizontal</translation>\n    </message>\n    <message>\n        <location line=\"-970\"/>\n        <source>Preferences</source>\n        <translation>Preferencias</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(requiere reinicio)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Usar selector de archivos nativo</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Iconos de la barra de herramientas</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Lenguaje</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Widgets de iconos de ventana</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Estilo</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Tema para los iconos (requiere reinicio)</translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation>Cursor parpadeante</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Mostrar la pantalla de bienvenida al inicio</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Directorio de trabajo de inicio del intérprete de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Restaurar el directorio de trabajo de la sesión anterior</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Establecer el foco en la ventana de comandos cuando se ejecute un comando en otro widget</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Mostrar el punto de depuración en la ventana de comandos además de en el editor</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Colores de la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Show tool bar</source>\n        <translation>Mostrar barra de herramientas</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Tamaño del número como diferencia con la fuente del editor</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Resaltado de la línea actual (color configurable en el editor de estilos)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Resaltar todas las apariciones de palabra seleccionada con doble clic</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Pestañas</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pestañas giradas: verticales cuando se sitúan arriba o abajo y horizontales cuando se configuran a la izquierda o a la derecha. El botón de cerrar no se muestra en las pestañas giradas.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Comentarios (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Cadenas consideradas para descomentar texto</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Cadena utilizada para comentar texto seleccionado</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Líneas largas</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Partir líneas largas a partir de longitud de línea</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Partir líneas sólo en comentarios</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Longitud de línea</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Marcador de línea larga</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Línea</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Fondo</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>Indentation</source>\n        <translation>Sangrado</translation>\n    </message>\n    <message>\n        <location line=\"+127\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Sangrado con tabulador</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Inserción automática después de &quot;if&quot;, etc.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>nada</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot;, etc.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Auto completion</source>\n        <translation>Completado automático</translation>\n    </message>\n    <message>\n        <location line=\"+101\"/>\n        <source>With Octave builtins</source>\n        <translation>Con funciones internas de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Con funciones de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Mostrar lista de comandos coincidentes automáticamente</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Debugging</source>\n        <translation>Depurado</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Mostrar siempre puntos de interrupción y punteros en el depurador (abrir el archivo relacionado si está cerrado)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Manejo de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Recargar los archivos modificados externamente sin consultar</translation>\n    </message>\n    <message>\n        <location line=\"-50\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Restaurar pestañas del editor de sesión anterior al inicio o cuando el editor se muestra de nuevo después del cierre</translation>\n    </message>\n    <message>\n        <location line=\"-31\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Codificación de texto usada para cargar y guardar</translation>\n    </message>\n    <message>\n        <location line=\"+71\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Cerrar todos los archivos cuando el widget del editor esté cerrado/oculto</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>Forzar nueva línea al final del fichero al guardarlo</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>Eliminar espacios extra al final de las líneas del archivo al guardarlo</translation>\n    </message>\n    <message>\n        <location line=\"+144\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Selección de fuente, tamaño (como diferencia con respecto al tamaño por defecto), estilo (&lt;b&gt;n&lt;/b&gt;egrita, &lt;b&gt;c&lt;/b&gt;ursiva, &lt;b&gt;s&lt;/b&gt;ubrayado), color y color de fondo (para el último caso, el magenta (255,0,255) es un sustituto para el color de fondo por defecto).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+848\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - cerrar el cuadro de diálogo y aplicar la configuración&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Aplicar - &lt;/span&gt;aplicar la configuración y mantener el cuadro de diálogo abierto&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancelar - &lt;/span&gt;cerrar el cuadro de diálogo y descartar los cambios que no se hayan aplicado previamente&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; recargar la configutación descartando los cambios que aún no se hayan aplicado&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-2254\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Cambiar el tamaño del buffer elimina el historial)</translation>\n    </message>\n    <message>\n        <location line=\"-260\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Si se selecciona, el foco en los widgets anclados en la ventana principal se activa según la posición del ratón. Esto persigue un comportamiento igual al del entorno de escritorio.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>El foco en los widgets anclados en la ventana principal se activa según la posición del ratón</translation>\n    </message>\n    <message>\n        <location line=\"+285\"/>\n        <source>History buffer Size</source>\n        <translation>Tamaño del buffer para el historial</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Rotated tabs</source>\n        <translation>Pestañas giradas</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Posición</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>Anchura máxima de las pestañas, en caracteres (0: ilimitada)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Anchura máxima de las pestañas, en caracteres. Útil especialmente para pestañas rotadas.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+871\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>El directorio del diálogo de apertura de fichero es el del fichero actual en lugar del directorio de trabajo de Octave </translation>\n    </message>\n    <message>\n        <location line=\"+98\"/>\n        <source>Behavior</source>\n        <translation>Comportamiento</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Restaurar último directorio de la sesión previa</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>Directorio inicial del explorador de archivos (sólo si no está sincronizado con el directorio inicial de Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Extensiones de archivo para abrir en el editor de texto predeterminado (separadas por &apos;;&apos;):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Colores para atributos de variables</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Usar la fuente de la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Importar conjunto de atajos de teclado</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Exportar conjunto de atajos de teclado</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Restablecer atajos de teclado a valores predeterminados</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Valor predeterminado/por defecto</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation>Actual</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Red</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Permitir a Octave la conexión al sitio web para mostrar las últimas noticias e información</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Proxy</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Seleccionar &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; o &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. La última opción indica que el tipo de proxy se tomará de la primera variable que contenga datos del conjunto ALL_PROXY, HTTP_PROXY y HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Utilizar servidor proxy</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Altura predeterminada de fila</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Ancho predeterminado de columna</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Colores del editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Usar colores de filas alternos</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Desactivar los atajos de teclado globales para evitar\nconflictos con las combinaciones de teclas para readline.\nExcepciones: Ctrl-C para la interrupción del intérprete\ny atajos para el cambio a otros widgets.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Desactivar los atajos de teclado globales cuando el foco esté en la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Sincronizar el directorio de trabajo de Octave con el explorador de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+348\"/>\n        <source>Shortcuts</source>\n        <translation>Atajos de teclado</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Export</source>\n        <translation>Exportar</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importar</translation>\n    </message>\n    <message>\n        <location line=\"-44\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Desactivar los atajos de teclado para evitar conflictos\ncon las combinaciones de teclas de readline.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>Desactivar los atajos de teclado de la ventana principal cuando la ventana de comandos está activa</translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Editar atajos de teclado haciendo doble clic en la columna &quot;Actual&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Acción</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Nombre del host:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Tipo de proxy:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Puerto:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Nombre de usuario:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Contraseña:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Desacoplar/acoplar widget</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Cerrar widget</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Nuevo archivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Nueva función</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Nueva figura</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Abrir archivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Cargar espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Guardar el espacio de trabajo como</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Salir de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Pegar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Deshacer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Seleccionar todo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Limpiar el portapapeles</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>Buscar en archivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Limpiar la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Limpiar el historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Limpiar el espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Asignar rutas de trabajo (path)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Preferencias</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Salto individual</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>Saltar a</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Salir de</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Continuar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Salir del modo de depuración</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Iniciar/detener sesión de perfilado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Continuar sesión de perfilado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Mostrar datos de perfilado</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Mostrar la ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Mostrar el historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Mostrar el explorador de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Mostrar el espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Mostrar editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Mostrar documentación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Mostrar editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Ventana de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Historial de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Explorador de archivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Espacio de trabajo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Documentación</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Widget anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Restablecer el esquema de ventana predeterminado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Ver la documentación almacenada en disco</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Mostrar la documentación en línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Informar de fallo (bug)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Paquetes de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Colaborar con Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Recursos para el desarrollador de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>Acerca de Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Notas de la versión</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Noticias de la comunidad</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Cerrar pestaña</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Cerrar todas las pestañas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Cerrar otras pestañas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Cambiar a pestaña izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Cambiar a pestaña derecha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Mover pestaña hacia la izquierda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Mover pestaña hacia la derecha</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Ampliar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Reducir</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Zoom normal</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Editar función</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Guardar archivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Guardar figura como</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Imprimir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Rehacer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Cortar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Buscar y reemplazar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Buscar siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Buscar anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Eliminar hasta el inicio de palabra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Eliminar hasta el fin de palabra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Eliminar hasta el inicio de línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Eliminar hasta el final de línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Eliminar línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Copiar línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Cortar línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Duplicar selección/línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Intercambiar líneas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Mostrar lista de comandos coincidentes</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Comentar la selección</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Descomentar la selección</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Comentar selección (seleccionando cadena de texto)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Convertir la selección a mayúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Convertir la selección a minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Sangría rigurosa de la selección</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Eliminar sangría rigurosa de la selección</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Aplicar sangría a código</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Convertir caracteres de fin de línea a Windows</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Convertir caracteres de fin de línea a Unix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Convertir caracteres de fin de línea a Mac</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Ir a la línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Mover a paréntesis correspondiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Seleccionar a paréntesis correspondiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Alternar marcador</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Marcador siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Marcador anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Eliminar todos los marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Preferencias de estilos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Mostrar números de línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Mostrar espacios en blanco</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Mostrar fines de línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Mostrar guías de sangría</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Mostrar marcador de longitud de línea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Mostrar barra de herramientas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Mostrar barra de estado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Mostrar barra de desplazamiento horizontal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Ordenar pestañas alfabéticamente</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Alternar puntos de interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Punto de interrupción siguiente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Punto de interrupción anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Eliminar todos los puntos de interrupción</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Ejecutar archivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Ejecutar selección</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Ejecutar los tests</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Ejecutar las demos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Ayuda de palabras clave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Documentación de palabras clave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>Ir a la página principal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>Una página hacia atrás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>Una página hacia delante</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Marcar esta página como favorita</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/eu_ES.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"eu_ES\">\n<context>\n    <name>QApplication</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qmessagebox.cpp\" line=\"+2902\"/>\n        <source>Application &quot;%1&quot; requires Qt %2, found Qt %3.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Incompatible Qt Library Error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QColorDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qcolordialog.cpp\" line=\"+1473\"/>\n        <source>Hu&amp;e:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Sat:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Val:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Red:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Green:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bl&amp;ue:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A&amp;lpha channel:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;HTML:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+184\"/>\n        <source>Cursor at %1, %2\nPress ESC to cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>Select Color</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+204\"/>\n        <source>&amp;Basic colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Custom colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add to Custom Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Pick Screen Color</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qdialog.cpp\" line=\"+677\"/>\n        <source>What&apos;s This?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QDialogButtonBox</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qmessagebox.cpp\" line=\"-793\"/>\n        <location line=\"+452\"/>\n        <source>OK</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QErrorMessage</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qerrormessage.cpp\" line=\"+86\"/>\n        <source>An error occurred</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+91\"/>\n        <source>Debug Message:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Warning:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Critical Error:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Fatal Error:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Information:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+256\"/>\n        <source>&amp;Show this message again</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;OK</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QFileDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfiledialog.cpp\" line=\"+582\"/>\n        <location filename=\"build_ts/octave-qt/qfiledialog_symbian.cpp\" line=\"+192\"/>\n        <source>Find Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">Ireki</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Save As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+85\"/>\n        <source>Show </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Delete</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show &amp;hidden files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;New Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-69\"/>\n        <source>Directory:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File &amp;name:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <location line=\"+12\"/>\n        <source>&amp;Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Save</source>\n        <translation type=\"unfinished\">&amp;Gorde</translation>\n    </message>\n    <message>\n        <location line=\"+895\"/>\n        <source>All files (*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+171\"/>\n        <source>Directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1886\"/>\n        <source>Are you sure you want to delete &apos;%1&apos;?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2958\"/>\n        <source>&amp;Choose</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2058\"/>\n        <location line=\"+1120\"/>\n        <source>%1\nDirectory not found.\nPlease verify the correct directory name was given.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1133\"/>\n        <source>%1 already exists.\nDo you want to replace it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>%1\nFile not found.\nPlease verify the correct file name was given.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+762\"/>\n        <source>New Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+130\"/>\n        <location line=\"+5\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\">Ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>&apos;%1&apos; is write protected.\nDo you want to delete it anyway?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Could not delete directory.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+441\"/>\n        <source>Recent Places</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfiledialog_win.cpp\" line=\"+131\"/>\n        <source>All Files (*.*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfilesystemmodel.cpp\" line=\"+964\"/>\n        <source>Name</source>\n        <translation type=\"unfinished\">Izena</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Kind</source>\n        <comment>Match OS X Finder</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Type</source>\n        <comment>All other platforms</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Date Modified</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QFontDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qfontdialog.cpp\" line=\"+141\"/>\n        <source>Select Font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+600\"/>\n        <source>&amp;Font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Font st&amp;yle</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Effects</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stri&amp;keout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Underline</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sample</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Wr&amp;iting System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QHelpSearchQueryWidget</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qhelpsearchquerywidget.cpp\" line=\"+62\"/>\n        <source>Search for:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Previous search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-3\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QInputDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qinputdialog.cpp\" line=\"+209\"/>\n        <source>Enter a value:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QMessageBox</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qmessagebox.cpp\" line=\"-2404\"/>\n        <source>Show Details...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source>Hide Details...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1815\"/>\n        <source>&lt;h3&gt;About Qt&lt;/h3&gt;&lt;p&gt;This program uses Qt version %1.&lt;/p&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&lt;p&gt;Qt is a C++ toolkit for cross-platform application development.&lt;/p&gt;&lt;p&gt;Qt provides single-source portability across all major desktop operating systems. It is also available for embedded Linux and other embedded and mobile operating systems.&lt;/p&gt;&lt;p&gt;Qt is available under multiple licensing options designed to accommodate the needs of our various users.&lt;/p&gt;&lt;p&gt;Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of GNU (L)GPL.&lt;/p&gt;&lt;p&gt;Qt licensed under GNU (L)GPL is appropriate for the development of Qt&amp;nbsp;applications provided you can comply with the terms and conditions of the respective licenses.&lt;/p&gt;&lt;p&gt;Please see &lt;a href=&quot;https://%2/&quot;&gt;%2&lt;/a&gt; for an overview of Qt licensing.&lt;/p&gt;&lt;p&gt;Copyright (C) The Qt Company Ltd. and other contributors.&lt;/p&gt;&lt;p&gt;Qt and the Qt logo are trademarks of The Qt Company Ltd.&lt;/p&gt;&lt;p&gt;Qt is The Qt Company Ltd. product developed as an open source project. See &lt;a href=&quot;https://%3/&quot;&gt;%3&lt;/a&gt; for more information.&lt;/p&gt;</source>\n        <extracomment>Leave this text untranslated or include a verbatim copy of it below and note that it is the authoritative version in case of doubt.</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+26\"/>\n        <source>About Qt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Lehenetsitako tamainarekiko aldea</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation type=\"unfinished\">Atzeko planoa, kolore magentak (255,0,255) lehenetsia esan nahi du {255, 0, 255)?}</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>l</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>e</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>a</translation>\n    </message>\n</context>\n<context>\n    <name>QPageSetupWidget</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_unix.cpp\" line=\"+260\"/>\n        <source>Millimeters (mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Inches (in)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Points (pt)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Pica (P̸)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Didot (DD)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cicero (CC)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <location line=\"+17\"/>\n        <source>Custom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>mm</source>\n        <extracomment>Unit &apos;Millimeter&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>pt</source>\n        <extracomment>Unit &apos;Points&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>in</source>\n        <extracomment>Unit &apos;Inch&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>P̸</source>\n        <extracomment>Unit &apos;Pica&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>DD</source>\n        <extracomment>Unit &apos;Didot&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>CC</source>\n        <extracomment>Unit &apos;Cicero&apos;</extracomment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QPlatformTheme</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qplatformtheme.cpp\" line=\"+793\"/>\n        <source>OK</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Save All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">Ireki</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Yes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Yes to &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;No</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>N&amp;o to All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Abort</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Retry</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Ignore</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\">Itxi</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Discard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Help</source>\n        <translation type=\"unfinished\">Laguntza</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Apply</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reset</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Restore Defaults</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QPrintDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qabstractprintdialog.cpp\" line=\"+61\"/>\n        <location line=\"+16\"/>\n        <location filename=\"build_ts/octave-qt/qprintdialog_win.cpp\" line=\"+239\"/>\n        <source>Print</source>\n        <translation type=\"unfinished\">Imprimatu</translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_qws.cpp\" line=\"+148\"/>\n        <source>File exists</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&lt;qt&gt;Do you want to overwrite it?&lt;/qt&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+184\"/>\n        <source>A0 (841 x 1189 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A1 (594 x 841 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A2 (420 x 594 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A3 (297 x 420 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A4 (210 x 297 mm, 8.26 x 11.7 inches)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A5 (148 x 210 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A6 (105 x 148 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A7 (74 x 105 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A8 (52 x 74 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>A9 (37 x 52 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B0 (1000 x 1414 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B1 (707 x 1000 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B2 (500 x 707 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B3 (353 x 500 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B4 (250 x 353 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B5 (176 x 250 mm, 6.93 x 9.84 inches)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B6 (125 x 176 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B7 (88 x 125 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B8 (62 x 88 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B9 (44 x 62 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>B10 (31 x 44 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>C5E (163 x 229 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>DLE (110 x 220 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Executive (7.5 x 10 inches, 191 x 254 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Folio (210 x 330 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Ledger (432 x 279 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Legal (8.5 x 14 inches, 216 x 356 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Letter (8.5 x 11 inches, 216 x 279 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Tabloid (279 x 432 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>US Common #10 Envelope (105 x 241 mm)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Print all</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print range</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print current page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_unix.cpp\" line=\"+608\"/>\n        <source>All Pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Odd Pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Even Pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <location line=\"+224\"/>\n        <source>&amp;Options &gt;&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>&amp;Print</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+223\"/>\n        <source>&amp;Options &lt;&lt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+148\"/>\n        <source>Invalid Pages Definition</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 does not follow the correct syntax. Please use &apos;,&apos; to separate ranges and pages, &apos;-&apos; to define ranges and make sure ranges do not intersect with each other.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Duplex Settings Conflicts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>There are conflicts in duplex settings. Do you want to fix them?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+76\"/>\n        <source>Print to File (PDF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+55\"/>\n        <source>Write PDF file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+100\"/>\n        <source>Options &apos;Pages Per Sheet&apos; and &apos;Page Set&apos; cannot be used together.\nPlease turn one of those options off.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-101\"/>\n        <source>Local file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>Print To File ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>%1 is a directory.\nPlease choose a different file name.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>File %1 is not writable.\nPlease choose a different file name.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>%1 already exists.\nDo you want to overwrite it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_win.cpp\" line=\"+1\"/>\n        <source>The &apos;From&apos; value cannot be greater than the &apos;To&apos; value.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_unix.cpp\" line=\"-155\"/>\n        <source>Left to Right, Top to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Left to Right, Bottom to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Right to Left, Bottom to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Right to Left, Top to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Bottom to Top, Left to Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Bottom to Top, Right to Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Top to Bottom, Left to Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Top to Bottom, Right to Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>1 (1x1)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>2 (2x1)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>4 (2x2)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>6 (2x3)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>9 (3x3)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>16 (4x4)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QPrintPreviewDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qabstractpagesetupdialog.cpp\" line=\"+68\"/>\n        <location line=\"+12\"/>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_unix.cpp\" line=\"+389\"/>\n        <location line=\"+8\"/>\n        <location filename=\"build_ts/octave-qt/qpagesetupdialog_win.cpp\" line=\"+18\"/>\n        <location line=\"+7\"/>\n        <source>Page Setup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QPrintPropertiesDialog</name>\n    <message>\n        <location filename=\"build_ts/octave-qt/qprintdialog_unix.cpp\" line=\"-964\"/>\n        <source>Printer Properties</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Job Options</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Page Setup Conflicts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>There are conflicts in page setup options. Do you want to fix them?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Advanced Option Conflicts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>There are conflicts in some advanced options. Do you want to fix them?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Itsatsi</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Hautatu dena</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\">Aukeraketa exekutatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Garbitu leihoa</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%1 editatu %2. lerroan</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>arbelean kopiatutako aukeraketa</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>Lehenetsia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Akatsa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Zenbakia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Hitz gakoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Katea kakotxa bikoitzarekin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Katea kakotxa bakarrarekin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Eragilea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identifikatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Eskalarra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>Parametro-hedapena</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Alderantzizko kakotxak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Mugatzailea hemen dokumentatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Kakotxa bakunak hemen dokumentatu</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>Lehenetsia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Hitz gakoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>Etiketa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>Ezkutatu karaktere-komandoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>Kanpoko komandoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Aldagaia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Eragilea</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>Lehenetsia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>Berez desaktibatuta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>C iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>Desaktibatuta C iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>C++ iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>Desaktibatuta C++ iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>JavaDoc estiloko C iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>Desaktibatuta JavaDoc estiloko C iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Zenbakia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Desaktibatuta zenbakia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Hitz gakoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Desaktibatuta hitz gakoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Katea kakotxa bikoitzarekin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>Desaktibatuta katea kakotxa bikoitzarekin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Katea kakotxa bakarrarekin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>Desaktibatuta katea kakotxa bakarrarekin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>Desaktibatuta IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>Aurreprozesadore-blokea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>Desaktibatuta aurreprozesadore-blokea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Eragilea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Desaktibatuta eragilea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identifikatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Desaktibatuta identifikatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>Itxi gabeko katea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>Desaktibatuta itxi gabeko katea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>C# kate literala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>Desaktibatuta C# kate literala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>JavaScript adierazpen erregularra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>Desaktibatuta JavaScript adierazpen erregularra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>JavaDoc estiloko C++ iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>Desaktibatuta JavaDoc estiloko C++ iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>Bigarren mailako hitz gakoak eta identifikatzaileak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Desaktibatuta bigarren mailako hitz gakoak eta identifikatzaileak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>JavaDoc hitz gakoak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>Desaktibatuta JavaDoc hitz gakoak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>JavaDoc hitz gako akatsa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>Desaktibatuta JavaDoc hitz gako akatsa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Klase orokorrak eta typedefak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Desaktibatuta klase orokorrak eta typedefak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>C++ kate gordina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>Desaktibatuta C++ kate gordina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>Lehenetsia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Komandoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>Goiburua</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Posizioa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Ezabatutako lerroa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Erantsitako lerroa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Aldatutako lerroa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>Lehenetsia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Komandoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Zenbakia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Hitz gakoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Katea kakotxa bakarrarekin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Eragilea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identifikatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Katea kakotxa bikoitzarekin</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>Lehenetsia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Akatsa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Iruzkina</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Zenbakia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Hitz gakoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Katea kakotxa bikoitzarekin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Katea kakotxa bakarrarekin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Eragilea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identifikatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Eskalarra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>Matrizea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>Traola</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Ikur-taula</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>Adierazpen erregularra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>Ordezkapena</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Alderantzizko kakotxak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>Datu-atala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Mugatzailea hemen dokumentatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Katea kakotxa bakarrarekin hemen dokumentatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>Katea kakotxa bikoitzarekin hemen dokumentatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>Alderantzizko kakotxak hemen dokumentatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>Katea kakotxekin (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>Katea kakotxekin (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>Katea kakotxekin (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>Katea kakotxekin (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>Katea kakotxekin (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>POD literala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>Azpirrutina-eredua</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>Formatu-identifikatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>Formatuaren gorputza</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>Katea kakotxa bikoitzarekin (interpolatutako aldagaia)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>Itzulpena</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>Adierazpen erregularra (interpolatutako aldagaia)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>Ordezkapena (interpolatutako aldagaia)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>Alderantzizko kakotxak (interpolatutako aldagaia)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>Katea kakotxa bikoitzarekin hemen dokumentatu (interpolatutako aldagaia)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>Alderantzizko kakotxak hemen dokumentatu (interpolatutako aldagaia)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>Katea kakotxekin (qq, interpolatutako aldagaia)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>Katea kakotxekin (qx, interpolatutako aldagaia)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>Katea kakotxekin (qr, interpolatutako aldagaia)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>&amp;Desegin</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Berregin</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>Eba&amp;ki</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>&amp;Itsatsi</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Hautatu dena</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation type=\"unfinished\">%1 editatu %2. lerroan</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Oharra</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Testua</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Katea</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Letra-tipoa</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>lodia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>l</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>etzana</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>e</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>kolorea</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>ezkerra</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>erdia</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>eskuma</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>goia</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>behea</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Posizioa</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Zabalera</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Altuera</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>unitateak</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalizatua</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Egokitu koadrora</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Koadroa</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Atzeko planoa</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Ertza</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Lerroaren estiloa</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>batere ez</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Lerroaren zabalera</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Hautatu dena</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Gelditu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Jarraitu</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation type=\"unfinished\">Octave komunitatearen berriak</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Lehenetsia</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\">Akatsa</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">Handitu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">Txikitu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Dokumentazioa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation type=\"unfinished\">Laguntzeko dokumentazioa ikusi.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">It&amp;xi</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">It&amp;xi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Exekutatu</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octaveren editorea</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation type=\"unfinished\">%1\npertsonalizatutako testu-editorea ezin da ireki</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Jarraitu</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation type=\"unfinished\">Fitxategia gorde eta exekutatu</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octaveren editorea</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation type=\"unfinished\">Atxikitako testu editorearen fitxa desagertu egin da.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">%1\nfitxategia ez dago. Sortu nahi duzu?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">Sortu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Fitxategia</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation type=\"unfinished\">&amp;Azken fitxategiak</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation type=\"unfinished\">&amp;Funtzioa editatu</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation type=\"unfinished\">&amp;Gorde fitxategia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation type=\"unfinished\">Gorde fitxategia &amp;honela...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">It&amp;xi</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation type=\"unfinished\">Itxi dena</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation type=\"unfinished\">Beste fitxategi batzuk itxi</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation type=\"unfinished\">Imprimatu...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Editatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\">&amp;Berregin</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\">Eba&amp;ki</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation type=\"unfinished\">&amp;Bilatu eta ordezkatu...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation type=\"unfinished\">&amp;Aurrekoa bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation type=\"unfinished\">&amp;Aginduak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\">Lerroa ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">Lerroa kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">Lerroa ebaki</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">Hitz hasieraraino ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">Hitz amaieraraino ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">Lerro hasieraraino ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">Lerro amaieraraino ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">Bikoiztu aukeraketa/lerroa</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">Txandakatu aurreko lerroarekin</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation type=\"unfinished\">&amp;Erakutsi bat datozen komandoen zerrenda</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation type=\"unfinished\">&amp;Formatua</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation type=\"unfinished\">Jarri aukeratutakoa m&amp;aiuskulan</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation type=\"unfinished\">Jarri aukeratutakoa m&amp;inuskulan</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation type=\"unfinished\">&amp;Iruzkindu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation type=\"unfinished\">&amp;Iruzkina ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation type=\"unfinished\">Lerro-amaiera &quot;&amp;Unix (LF)&quot;-era aldatu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation type=\"unfinished\">Lerro-amaiera &quot;Legacy &amp;Mac (CR)&quot;-era aldatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation type=\"unfinished\">&amp;Nabigazioa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation type=\"unfinished\">&amp;Lerrora joan...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\">Mugitu dagokion parentesira, kako zuzenera edo giltzara</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation type=\"unfinished\">Hurrengo &amp;markatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation type=\"unfinished\">Aurreko &amp;markatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation type=\"unfinished\">&amp;Markatzaileak txandatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation type=\"unfinished\">&amp;Markatzaile guztiak ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation type=\"unfinished\">&amp;Hobespenak...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation type=\"unfinished\">&amp;Estiloen hobespenak...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation type=\"unfinished\">&amp;Ikusi</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation type=\"unfinished\">&amp;Editorea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation type=\"unfinished\">Erakutsi &amp;lerroen zenbakiak</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation type=\"unfinished\">Erakutsi &amp;zuriuneak</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation type=\"unfinished\">Erakutsi lerro-&amp;amaierak</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation type=\"unfinished\">&amp;Koska-erakusleak bistaratu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation type=\"unfinished\">Erakutsi lerroen &amp;luzera-markatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation type=\"unfinished\">Erakutsi &amp;Tresna-barra</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation type=\"unfinished\">Erakutsi &amp;Egoera-barra</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation type=\"unfinished\">Erakusti &amp;Higitze-barra horizontala</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation type=\"unfinished\">&amp;Handitu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation type=\"unfinished\">&amp;Txikitu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation type=\"unfinished\">&amp;Ohiko neurria</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation type=\"unfinished\">&amp;Akasgabetu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation type=\"unfinished\">Geldiuneak &amp;txandatu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation type=\"unfinished\">&amp;Hurrengo geldiunea</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation type=\"unfinished\">&amp;Aurreko geldiunea</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation type=\"unfinished\">&amp;Ezabatu geldiune guztiak</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation type=\"unfinished\">&amp;Exekutatu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation type=\"unfinished\">Exekutatu &amp;aukeraketa</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Laguntza</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation type=\"unfinished\">&amp;Laguntza hitz gakoekin</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation type=\"unfinished\">&amp;Hitz gakoen dokumentazioa</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation type=\"unfinished\">Azken fitxategiak</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editorea</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation type=\"unfinished\">Lerroa:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation type=\"unfinished\">Zutabea:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation type=\"unfinished\">kodifikazioa:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation type=\"unfinished\">Lerro-amaiera:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation type=\"unfinished\">Etenune-baldintza</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octaveren editorea</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation type=\"unfinished\">Lerrora joan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation type=\"unfinished\">Lerro-zenbakia</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation type=\"unfinished\">&lt;izen gabe&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation type=\"unfinished\">%1\nfitxategia itxi egingo da, baina aldaketak izan dira.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">It&amp;xi</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation type=\"unfinished\">Akasgabetu edo Gorde</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation type=\"unfinished\">Fitxategi hau exekutatzen ari da.\nAkasgabetzea kendu eta gorde?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation type=\"unfinished\">Octaveren fitxategiak (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation type=\"unfinished\">Fitxategi guztiak (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation type=\"unfinished\">&quot;%1&quot;\nez da baliozko identifikazioa.\n\nIzena bere horretan uzten baduzu, scriptari ezin izango\nzaio Octaveren komando modura deitu.\n\nBeste izen bat aukeratu nahi duzu?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation type=\"unfinished\">\n\nOharra: editorean edukia aldatu egin da!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation type=\"unfinished\">Itxuraz &apos;%1&apos; fitxategia beste aplikazio batek aldatu du. Berriro kargatu nahi duzu?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation type=\"unfinished\">Antza denez,\n%1\nfitxategia ezebatu edo izenez aldatu da. Berreskuratu nahi duzu?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation type=\"unfinished\">Fitxategiaren tamaina</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation type=\"unfinished\">Fitxategi-mota</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation type=\"unfinished\">Aldatze-data</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation type=\"unfinished\">Erakutsi ezkutukoak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation type=\"unfinished\">Txandakatu lerroen koloreak</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation type=\"unfinished\">Sartu fitxategiaren kokagunea edo izena</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\">Gorengo direktorioa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation type=\"unfinished\">Octaveren direktorioa erakutsi</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation type=\"unfinished\">Joan Octaveren uneko direktoriora</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation type=\"unfinished\">Octaveren direktorioa hautatu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation type=\"unfinished\">Octaveren direktorioa fitxategi-arakatzailearen uneko direktorio egin</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation type=\"unfinished\">Ekintzak uneko direktorioan</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation type=\"unfinished\">Erakutsi hasiera-direktorioa</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation type=\"unfinished\">Nabigatzailearen direktorioa zehaztu...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation type=\"unfinished\">Beste fitxategi bat...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation type=\"unfinished\">Beste direktorio bat...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation type=\"unfinished\">Izena aldatu...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">Ireki</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation type=\"unfinished\">Zabaldu sistemaren fitxategi-arakatzailean</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation type=\"unfinished\">Zabaldu testu-editorean</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation type=\"unfinished\">Arbelean kopiatu aukeraketa</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Exekutatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation type=\"unfinished\">Datuak kargatu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation type=\"unfinished\">Uneko direktorioa aukeratu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation type=\"unfinished\">Ezabatu...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation type=\"unfinished\">Ezabatu fitxategia/direktorioa</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation type=\"unfinished\">Seguru ezabatu nahi duzula\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation type=\"unfinished\">Ezin dira hutsik ez dauden direktorioak ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation type=\"unfinished\">Fitxategi-arakatzailetik direktorioa aukeratu</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation type=\"unfinished\">Fitxategia sortu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Fitxategia sortu hemen\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation type=\"unfinished\">.txt beste fitxategi bat sortu</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation type=\"unfinished\">Direktorioa sortu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Karpeta sortu hemen\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation type=\"unfinished\">Direktorio berria</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Fitxategi-arakatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation type=\"unfinished\">Arakatu zure fitxategietan</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation type=\"unfinished\">Gozatu!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Aurrekoa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation type=\"unfinished\">Amaitu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation type=\"unfinished\">Bereizi &amp;maiuskulak/minuskulak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation type=\"unfinished\">&amp;Hasieratik bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation type=\"unfinished\">&amp;Markatu bilatzen den bitartean</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation type=\"unfinished\">&amp;Ordezkatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation type=\"unfinished\">Ordezkatu &amp;dena</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation type=\"unfinished\">&amp;Gehiago...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation type=\"unfinished\">Hitz &amp;osoak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation type=\"unfinished\">&amp;Atzerantz bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation type=\"unfinished\">Bilatu au&amp;keraketa</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation type=\"unfinished\">Azkenetik bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation type=\"unfinished\">Hasieratik bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation type=\"unfinished\">Emaitza ordezkatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation type=\"unfinished\">%1 hitz ordezkatuta</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation type=\"unfinished\">Bilaketaren emaitza</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation type=\"unfinished\">Ez dago bat etortze gehiago</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation type=\"unfinished\">Fitxategiak bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation type=\"unfinished\">Izena:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation type=\"unfinished\">Bilatu hemen:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation type=\"unfinished\">Sartu hasierako direktorioa</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation type=\"unfinished\">Arakatu...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation type=\"unfinished\">Arakatu hasiera-direktorioa hautatzeko</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation type=\"unfinished\">Bilatu azpidirektorioetan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation type=\"unfinished\">Arakatu direktorioak modu errekurtsiboan</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation type=\"unfinished\">Sartu direktorioen izenak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation type=\"unfinished\">Bat egiten duten direktorioak gehitu bilaketa-emaitzetan</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation type=\"unfinished\">Testu hau du barnean:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation type=\"unfinished\">Bilatzeko testua</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation type=\"unfinished\">Bilaketaren emaitzak</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation type=\"unfinished\">Ez aktibo.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation type=\"unfinished\">Bilaketa hasi</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Gelditu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation type=\"unfinished\">Fitxategiaren edukia</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation type=\"unfinished\">Bilatzen...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation type=\"unfinished\">Bilaketarako direktorioa hautatu</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation type=\"unfinished\">Fitxategiaren izena</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation type=\"unfinished\">Direktorioa</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\">Itxi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation type=\"unfinished\">Octaveren akats larria</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation type=\"unfinished\">Arakatu eta bilatu komandoen historialean.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation type=\"unfinished\">Ebaluatu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation type=\"unfinished\">Scripta sortu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\">Ezkutatu filtroa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\">Erakutsi filtroa</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation type=\"unfinished\">Testua idatzi komandoen historiala filtratzeko</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Komandoen historiala</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Ongi etorri Octavera!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">Hurrengoa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\">&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Badirudi Octaveren ingurune grafikoa lehen aldiz erabili dela ordenagailu honetan\nSakatu &apos;Hurrengoa&apos; konfigurazio-fitxategi bat sortzeko eta Octave abiarazteko.&lt;/p&gt;\n&lt;p&gt;Konfigurazio-fitxategia hemen gordeko da&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation type=\"unfinished\">Seguru zaude Octavetik irten nahi duzula?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">&quot;Octave&quot;-ri buruz</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation type=\"unfinished\">Direktorioak arakatu</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation type=\"unfinished\">Octaveren fitxategiak (*.m);;Fitxategi guztiak (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation type=\"unfinished\">Funtzio berriaren izena:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation type=\"unfinished\">Ezin da %1 funtzioa aurkitu</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octaveren editorea</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Fitxategia</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation type=\"unfinished\">Ireki...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation type=\"unfinished\">Ireki fitxategi bat editorean</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation type=\"unfinished\">Lan-eremua kargatu...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation type=\"unfinished\">Gorde honela lan-eremua...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation type=\"unfinished\">Irten</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation type=\"unfinished\">Beste bat sortu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation type=\"unfinished\">Beste script bat</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation type=\"unfinished\">Beste funtzio bat...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">Beste irudi bat</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Editatu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Desegin</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Itsatsi</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Hautatu dena</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Paper-zorroa garbitu</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">Komandoen leihoa garbitu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Komandoen historiala garbitu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Lan-eremua garbitu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation type=\"unfinished\">Hobespenak...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation type=\"unfinished\">&amp;Akasgabetu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Hasi</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Jarraitu</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation type=\"unfinished\">&amp;Leihoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\">Erakutsi komandoen leihoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">Erakutsi komandoen historiala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Erakutsi fitxategi-arakatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">Erakutsi lan-eremua</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">Erakutsi editorea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">Erakutsi dokumentazioa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Komandoen leihoa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Komandoen historiala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Fitxategi-arakatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Lan-eremua</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editorea</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Dokumentazioa</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\">Leihoen diseinu lehenetsia berrezarri</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Laguntza</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Akatsei buruz informatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation type=\"unfinished\">Octaveri dohaintza egin</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation type=\"unfinished\">Diskoan</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation type=\"unfinished\">Linean</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation type=\"unfinished\">&amp;Berriak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Bertsioaren oharrak</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation type=\"unfinished\">Tresna-barra</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation type=\"unfinished\">Sartu direktorioaren izena</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation type=\"unfinished\">Uneko direktorioa:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\">Gorengo direktorioa</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\">&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nBadirudi Octave komunitatearen berrien gaineko iturburuak ez daudela erabilgarri.\n&lt;/p&gt;\n&lt;p&gt;\nAzken berritasunak ezagutzeko, bisita ezazu\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nweb-konexioa duzunean (esteka nabigatzaile batean zabalduko da).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Octaveren garatzaileak,</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation type=\"unfinished\">Laguntza honi buruz</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation type=\"unfinished\">Dokumentazioa honi buruz</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation type=\"unfinished\">Editatu</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation type=\"unfinished\">etenuneak ezarri akasgabetzean bada ...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octaveren editorea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">Lehenetsia</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">Sortu</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">%1\nfitxategia ez dago. Sortu nahi duzu?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octaveren editorea</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation type=\"unfinished\">%1 fitxategia ez dago kargatze-helbidean. Editatzen ari zaren funtzioa akasgabetzeko, bi aukera dituzu: %2 direktoriora aldatzea edo direktorio hori kargatze-helbidera gehitzea.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation type=\"unfinished\">%1 fitxategia eta izen bereko beste fitxategi bat gainjarrita daude kargatze-helbidean. Editatzen ari zaren fitxategia akasgabetzeko, aldatu %2 direktoriora.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation type=\"unfinished\">Aldatu direktorioa edo gehitu direktorioa kargatze-helbidera</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation type=\"unfinished\">%1 bertsioaren noten fitxategia hutsik dago.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation type=\"unfinished\">&apos;%1&apos; bertsioaren noten fitxategia ezin da irakurri.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation type=\"unfinished\">Octave bertsioaren notak</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\">Atzeko planoa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation type=\"unfinished\">orokorra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation type=\"unfinished\">Sistemaren hobespena</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation type=\"unfinished\">IBeam kurtsorea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation type=\"unfinished\">Bloke-kurtsorea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation type=\"unfinished\">Azpimarra-kurtsorea</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation type=\"unfinished\">Octaveren hasiera-direktorioa ezarri</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation type=\"unfinished\">Fitxategi-arakatzailearen hasiera-direktorioa ezarri</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation type=\"unfinished\">Octavere lasterbide-fitxategiak (*.osc);;Fitxategi guztiak (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation type=\"unfinished\">Lasterbideak gainidatzi</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation type=\"unfinished\">Lasterbide guztiak gainidatziko dituzu.\nMomentuko lasterbideak gorde nahi dituzu edo ekintza ezeztatu nahi duzu?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation type=\"unfinished\">Ez gorde</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Aurrekoa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">Hurrengoa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation type=\"unfinished\">Ezarri lehenetsi gisa</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation type=\"unfinished\">Lasterbide bikoitza</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation type=\"unfinished\">Orokorra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editorea</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Ongi etorri GNU Octavera</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Ongi etorri Octavera!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Komandoen leihoa</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Ebaki</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Itsatsi</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Ebaki</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Itsatsi</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\">Ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Ongi etorri GNU Octavera</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation type=\"unfinished\">Izena</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Mota</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Dimentsioa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Balioa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">Atributua</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation type=\"unfinished\">Eskuin-klik kopiatzeko, izena aldatzeko edo erakusteko</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation type=\"unfinished\">Konplexua</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Mota</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Dimentsioa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Balioa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">Atributua</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Lan-eremua</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation type=\"unfinished\">Erakutsi aldagaiak lan-eremu aktiboan.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation type=\"unfinished\">Sartu testua lan-eremua iragazteko</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation type=\"unfinished\">Erakutsi aldagaiak lan-eremu aktiboan.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation type=\"unfinished\">Biltegiratze-mota bakoitzerako koloreak:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation type=\"unfinished\">Izena kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation type=\"unfinished\">Balioa kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation type=\"unfinished\">Izena aldatu</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation type=\"unfinished\">Maila goreneko sinboloak baino ezin dira berrizendatu</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\">Ezkutatu filtroa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\">Erakutsi filtroa</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Orokorra</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Octaveren logoa bakarrik</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Letradun ikonoak</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Graphic icons</source>\n        <translation>Ikono grafikoak</translation>\n    </message>\n    <message>\n        <location line=\"-341\"/>\n        <source>Dock widget title bar</source>\n        <translation>Akoplatu widgeta titulu-barrara</translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation>Txikia</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Handia</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>Pertsonalizatutako estiloa</translation>\n    </message>\n    <message>\n        <location line=\"+244\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Hobespenok .octavercse hasierako fitxategiak exekutatu ondoren izango dute eragina.</translation>\n    </message>\n    <message>\n        <location line=\"+353\"/>\n        <source>Editor</source>\n        <translation>Editorea</translation>\n    </message>\n    <message>\n        <location line=\"+187\"/>\n        <source>Show EOL characters</source>\n        <translation>Erakutsi lerro-bukaerako karaktereak</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+558\"/>\n        <source>Default EOL mode</source>\n        <translation>Lehenetsitako lerro-bukaera adierazlea</translation>\n    </message>\n    <message>\n        <location line=\"-503\"/>\n        <source>Indent width</source>\n        <translation>Koska zabalera</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Tabulazio bidez egin koska</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Koska automatikoa</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Tabuladorearen tamaina</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Erakutsi koska-erakusleak</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Atzera-egite teklak koska ezabatzen du</translation>\n    </message>\n    <message>\n        <location line=\"+120\"/>\n        <source>Match keywords</source>\n        <translation>Hitz gakoetan bat egin</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Maiskulak/minuskulak bereizi</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Gomendio bidez hitza ordeztu</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Dokumentuan hitzak bat etorri</translation>\n    </message>\n    <message>\n        <location line=\"-643\"/>\n        <source>Use custom file editor</source>\n        <translation>Fitxategi-editore pertsonalizatua erabili</translation>\n    </message>\n    <message>\n        <location line=\"+1009\"/>\n        <source>Editor Styles</source>\n        <translation>Editorearen estiloak</translation>\n    </message>\n    <message>\n        <location line=\"-1485\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Letra-tipo mota</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Erakutsi lerro-zenbakiak</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Show whitespace</source>\n        <translation>Erakutsi zuriuneak</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Ez erakutsi koskarako tarte-libreak</translation>\n    </message>\n    <message>\n        <location line=\"+935\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Idatzitako karaktere-kopurua bistaratutako lista bete baino lehen: </translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Ez dauden fitxategiak galdetu gabe sortu</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>komandoko lerroa (%f=fitxategia, %l=lerroa):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Kurtsore-mota:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Erabili lehenengo planoko kolorea</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Letra-tipoaren tamaina</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Fitxategi-arakatzailea</translation>\n    </message>\n    <message>\n        <location line=\"-2118\"/>\n        <source>Interface</source>\n        <translation>Interfazea</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Berretsi irten aurretik</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Erakutsi egoera-barra</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Testua ezgaituta</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Gaituta</translation>\n    </message>\n    <message>\n        <location line=\"-89\"/>\n        <source>Normal</source>\n        <translation>Normala</translation>\n    </message>\n    <message>\n        <location line=\"+128\"/>\n        <source>Background inactive</source>\n        <translation>Atzeko planoa ezgaituta</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation type=\"unfinished\">3D</translation>\n    </message>\n    <message>\n        <location line=\"+206\"/>\n        <source>Octave Startup</source>\n        <translation>Octaveren abiaraztea</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Arakatu</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Tarte finkodun letra-tipoekin ibiliko da zuzen.\nKaraktereen zabaleraren araberako kokapena hartzen du marraztutako lerroak, lehenetsitako\nletra-tipoaren arabera. Baliteke ongi ez funtzionatzea estiloek letra-tipo proportzionalak\nerabiltzen badituzte edo askotariko estiloak nahasten badira: askotariko tamainakoak edo\nletra lodiak, etzanak eta normalak.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Gaitu kodea azpiltzea</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation type=\"unfinished\">Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Erakutsi korritze-barra horizontala</translation>\n    </message>\n    <message>\n        <location line=\"-970\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">Hobespenak</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\">Komandoa</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Show tool bar</source>\n        <translation>Erakutsi Tresna-barra</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Number size as difference to editor font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\">Atzeko planoa</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>Indentation</source>\n        <translation>Koska</translation>\n    </message>\n    <message>\n        <location line=\"+127\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Koskak tabuladorea darabil</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Auto completion</source>\n        <translation>Osatze automatikoa</translation>\n    </message>\n    <message>\n        <location line=\"+101\"/>\n        <source>With Octave builtins</source>\n        <translation>Octaveren barne funtzioekin</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Octaveren funtzioekin</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Erakutsi automatikoki bat datozen komandoen zerrenda</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Debugging</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Fitxategien kudeaketa</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Birkargatu beste batzuek aldatu dituzten fitxategiak ohartarazpen gabe</translation>\n    </message>\n    <message>\n        <location line=\"-50\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-31\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Testu-kodifikatzailea kargatzeko eta gordetzeko erabiltzen da</translation>\n    </message>\n    <message>\n        <location line=\"+71\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+144\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Letra-tipoa aukeratu, tamaina (lehenetsitako tamainarekiko aldea), estiloa (&lt;b&gt;l&lt;/b&gt;odia, &lt;b&gt;e&lt;/b&gt;tzana, &lt;b&gt;a&lt;/b&gt;zpimarratua), testuaren kolorea eta atzeko planoaren kolorea (azken honetan, lehenetsitako kolorearentzat magenta kolorea (255,0,255) kokapen-marka da).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+848\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2254\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Bufferraren tamaina aldatzeak historiala ezabatzen du)</translation>\n    </message>\n    <message>\n        <location line=\"-260\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+285\"/>\n        <source>History buffer Size</source>\n        <translation>Historialarentzako bufferraren tamaina</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Rotated tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\">Posizioa</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+871\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+98\"/>\n        <source>Behavior</source>\n        <translation>Portaera</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Leheneratu azken direktorioa aurreko saiotik</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Lehenetsitako testu-editoren irekiko diren fitxategi-luzapenak (honakoagatik banatuta &quot;;&quot;)</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Lan-eremua</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Aldagaien atributuentzako koloreak</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Inportatu lasterbide-multzoa</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Esportatu momentuko lasterbide-multzoa</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Leheneratu lasterbideak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Lehenetsia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation>Momentukoa</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Sarea</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Octaveri baimena eman web-gunera konekta dadin azken berriak eta informazioa eskuratzeko</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Erabili &quot;proxy&quot; zerbitzaria</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Sinkronizatu Octaveren lan-direktorioa fitxategi-arakatzailearekin</translation>\n    </message>\n    <message>\n        <location line=\"+348\"/>\n        <source>Shortcuts</source>\n        <translation>Lasterbideak</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Export</source>\n        <translation>Esportatu</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Inportatu</translation>\n    </message>\n    <message>\n        <location line=\"-44\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Ekintza</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Ostalari-izena:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Proxy-mota:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Ataka:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Erabiltzaile-izena:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Pasahitza:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation type=\"unfinished\">Beste fitxategi bat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">Beste irudi bat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation type=\"unfinished\">Ireki fitxategia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation type=\"unfinished\">Octavetik irten</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Itsatsi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Desegin</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Hautatu dena</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Paper-zorroa garbitu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation type=\"unfinished\">Fitxategietan bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">Komandoen leihoa garbitu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Komandoen historiala garbitu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Lan-eremua garbitu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">Hobespenak</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Hasi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Jarraitu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\">Erakutsi komandoen leihoa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">Erakutsi komandoen historiala</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Erakutsi fitxategi-arakatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">Erakutsi lan-eremua</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">Erakutsi editorea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">Erakutsi dokumentazioa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Komandoen leihoa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Komandoen historiala</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Fitxategi-arakatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Lan-eremua</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editorea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Dokumentazioa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\">Leihoen diseinu lehenetsia berrezarri</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation type=\"unfinished\">Erakutsi dokumentazioa linean</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Akatsei buruz informatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation type=\"unfinished\">Octaverekin kolaboratu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation type=\"unfinished\">Octaveren garatzaileentzako baliabideak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">&quot;Octave&quot;-ri buruz</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Bertsioaren oharrak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation type=\"unfinished\">Aldatu ezkerreko tabuladorera</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation type=\"unfinished\">Aldatu eskumako tabuladorera</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation type=\"unfinished\">Mugitu tabuladorea ezkerrera</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation type=\"unfinished\">Mugitu tabuladorea eskumara</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">Handitu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">Txikitu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation type=\"unfinished\">Zoom normala</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation type=\"unfinished\">Funtzioa editatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation type=\"unfinished\">Gorde fitxategia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation type=\"unfinished\">Gorde fitxategia honela</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation type=\"unfinished\">Imprimatu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation type=\"unfinished\">Berregin</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Ebaki</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation type=\"unfinished\">Bilatu eta ordezkatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation type=\"unfinished\">Hurrengoa bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation type=\"unfinished\">Aurrekoa bilatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">Hitz hasieraraino ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">Hitz amaieraraino ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">Lerro hasieraraino ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">Lerro amaieraraino ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\">Lerroa ezabatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">Lerroa kopiatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">Lerroa ebaki</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">Bikoiztu aukeraketa/lerroa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">Txandakatu aurreko lerroarekin</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation type=\"unfinished\">Erakutsi bat datozen komandoen zerrenda</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation type=\"unfinished\">Aukeraketa iruzkindu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation type=\"unfinished\">Aukeraketaren iruzkina kendu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation type=\"unfinished\">Jarri aukeratutakoa maiuskulan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation type=\"unfinished\">Jarri aukeratutakoa minuskulan</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation type=\"unfinished\">Lerro-amaierak &quot;Windows&quot;-era aldatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation type=\"unfinished\">Lerro-amaierak &quot;Unix&quot;-era aldatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation type=\"unfinished\">Lerro-amaierak &quot;Mac&quot;-era aldatu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation type=\"unfinished\">Lerrora joan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\">Mugitu dagokion parentesira, kako zuzenera edo giltzara</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation type=\"unfinished\">Markatzaileak txandatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation type=\"unfinished\">Hurrengo markatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation type=\"unfinished\">Aurreko markatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation type=\"unfinished\">Ezabatu markatzaile guztiak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation type=\"unfinished\">Estiloen hobespenak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation type=\"unfinished\">Erakutsi lerro-zenbakiak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation type=\"unfinished\">Erakutsi zuriuneak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation type=\"unfinished\">Erakutsi lerro-amaierak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation type=\"unfinished\">Erakutsi koska-erakusleak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation type=\"unfinished\">Erakutsi lerro-luzera markatzailea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation type=\"unfinished\">Erakutsi Tresna-barra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation type=\"unfinished\">Erakutsi Egoera-barra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation type=\"unfinished\">Erakutsi Higitze-barra horizontala</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation type=\"unfinished\">Geldiuneak txandakatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation type=\"unfinished\">Hurrengo geldiunea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation type=\"unfinished\">Aurreko geldiunea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation type=\"unfinished\">Ezabatu geldiune guztiak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation type=\"unfinished\">Fitxategia exekutatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\">Aukeraketa exekutatu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation type=\"unfinished\">Laguntza hitz gakoekin</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation type=\"unfinished\">Hitz gakoen dokumentazioa</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/fr_FR.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"fr_FR\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Nom de fichier non valide</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Différence avec la taille par défaut</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Couleur de fond, magenta [255,0,255] désigne la valeur par défaut {255, 0, 255)?}</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>g</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>s</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>Éditer &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Aide pour &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Documentation pour &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Copier</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Coller</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Tout Sélectionner</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Exécuter la Sélection</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>Éditer la sélection</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>Aide à propos de la sélection</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>Documentation à propos de la sélection</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Nettoyer la Fenêtre de Commande</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Éditer %1 à la ligne %2</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>sélection copiée vers le presse-papiers</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Ouvrir le lien</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Copier l&apos;adresse du lien</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Envoyer un e-mail à...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>Copier l&apos;adresse e-mail</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Éditer %1 à la ligne %2</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Annotation</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Texte</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Texte</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Police</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>gras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>g</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>italique</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>couleur</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>gauche</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>milieu</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>droite</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>Alignement Vertical</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>Alignement Vertical</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>haut</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>bas</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Position</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Largeur</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Hauteur</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>unités</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalisée</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Adapter au texte</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Boîte</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Arrière plan</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Bord</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Style de ligne</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>aucune</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Épaisseur de ligne</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Tout Sélectionner</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Pause</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Arrêter</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Continuer</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Fenêtre de Commande</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Nouvelles de la communauté Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>Défaut</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Erreur</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translatorcomment>Aucune idée du contexte. Je tente ma chance avec &quot;Invite&quot; (de commande, comme &quot;command prompt&quot;)</translatorcomment>\n        <translation>Invite</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Documentation d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>Impossible de copier la collection d&apos;aide dans\nun fichier temporaire. Les fonctionnalités de\nrecherche pourraient être affectées.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>Impossible de préparer les données nécessaires\nau le navigateur de documentation. Peut être le module\nQt SQlite est-il absent?\nSeule l&apos;aide dans le fenêtre de commandes sera disponible.</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>Contenu</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Entrer le texte à rechercher dans la liste des fonctions</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Recherche</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>Index des Fonctions</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Marque Pages</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>Page d&apos;Accueil</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Reculer d&apos;une page</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Pages précédentes</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>Avancer d&apos;une page</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Pages suivantes</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Rechercher</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Agrandir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Réduire</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Taille Originale</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>Marquer la page actuelle</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>Impossible d&apos;ajouter le fichier d&apos;aide %1.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nAucun marque page de documentation chargé!</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: Chargement des Marque Pages de Documentation</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Entrer du texte pour chercher des marque pages</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Filtrer</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Nouveau Dossier</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Ouvrir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Renommer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>&amp;Supprimer</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>&amp;Ajouter un Dossier</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>Cacher le &amp;Filtre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>Afficher le &amp;Filtre</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: Enregistrement des Marque Pages de Documentation</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>Impossible d&apos;éditer le fichier %1:\n%2.\n\nLes marque pages de documentation ne sont pas enregistrés!\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>Impossible de lire le fichier %1:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>Aucun élément de départ trouvé dans %1.\nFichier de Marque Pages Invalide?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>Le fichier\n%1\nn&apos;est pas un fichier XBEL version 1 valide.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Titre inconnu</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Documentation</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Voir la documentation pour plus d&apos;aide.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Fermer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>&amp;Tout Fermer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>Fermer les &amp;Autres</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>Aller à la fenêtre de &amp;Gauche</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>Aller à la fenêtre de &amp;Droite</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation>Fichiers Ouverts</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation>Cliquer pour sélectionner le fichier dans l&apos;éditeur</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Fermer</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>&amp;Tout Fermer</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Exécuter</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Définir le Répertoire &amp;Courant</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Éditeur d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>Impossible de démarrer l&apos;éditeur\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Aucun éditeur externe n&apos;est configuré.\nVoulez vous ouvrir les préférences?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Continuer</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Enregistrer et Exécuter</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Éditeur d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>Fichier non sauvegardé! Un fichier du même nom,\n%1,\nest déjà ouvert dans l&apos;éditeur.</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>L&apos;onglet éditeur de fichier associé a disparu.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>Impossible d&apos;ouvrir le fichier\n%1\nen lecture : %2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Le fichier\n%1\nn&apos;existe pas. Voulez vous le créer?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Créer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annuler</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>Impossible d&apos;ouvrir le fichier\n%1\nen écriture : %2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Fichier</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>Fichiers &amp;Récents</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>&amp;Éditer la Fonction</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>&amp;Enregistrer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>Enregistrer &amp;Sous...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Fermer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Tout fermer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Fermer les autres fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Imprimer...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Éditer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Rétablir</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>Co&amp;uper</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>&amp;Rechercher et remplacer...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>Rechercher le Suiva&amp;nt</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>Rechercher le &amp;précédent</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>&amp;Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Effacer la ligne</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Copier la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Couper la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Effacer jusqu&apos;au Début du Mot</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Effacer jusqu&apos;à la Fin du Mot</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Effacer jusqu&apos;au Début de la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Effacer jusqu&apos;à la Fin de la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Dupliquer la Sélection/Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Transposer la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>&amp;Montrer la Liste de Suggestions</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Format</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>&amp;Sélection en Majuscules</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>Sé&amp;lection en Minuscules</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>&amp;Commenter</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>&amp;Dé-commenter</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Commenter (Après Sélection)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>&amp;Indenter la sélection en bloc</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>&amp;Désindenter la sélectionne en bloc</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Indenter</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Convertir les Fins de Lignes en &amp;Windows (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Convertir les Fins de Lignes en &amp;UNIX (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Convertir les Fins de Lignes en Legacy &amp;Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>Navi&amp;gation</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>&amp;Aller à la ligne...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Déplacer jusqu&apos;à la Parenthèse Correspondante</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Sélectionner jusqu&apos;à la Parenthèse Correspondante</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>Marque page &amp;Suivant</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>Marque page &amp;Précédent</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>Basculer &amp;marque page</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>&amp;Supprimer tout marque page</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Préférences...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>Préférences de &amp;Style...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>&amp;Affichage</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>Édit&amp;eur</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>Afficher les Numéros de &amp;Lignes</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>Afficher les E&amp;spaces</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Afficher les Fins de Lign&amp;es</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>Afficher les Guides d&apos;&amp;Indentation</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>Afficher le &amp;Repère de Longue Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>Afficher la barre d&apos;Ou&amp;tils</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>Afficher la barre de &amp;Statut</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>Afficher la barre de navigation &amp;horizontale</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>Agrand&amp;ir</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>Réd&amp;uire</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>Taille &amp;Normale</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>Trier les Onglet&amp;s Alphabétiquement</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Déboguer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>&amp;Ajouter/Retirer un point d&apos;arrêt</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>Point d&apos;arrêt suiva&amp;nt</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>Point d&apos;arrêt &amp;précédent</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>&amp;Retirer tous les points d&apos;arrêt</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>E&amp;xécuter</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Enregistrer le Fichier et l&apos;Exécuter/Continuer</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>Exécuter la &amp;Sélection</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Enregistrer le Fichier et Lancer tous les &amp;Tests</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Enregistrer le Fichier et Lancer toutes les &amp;Démos</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Aide</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>&amp;Aide sur le mot clé</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>&amp;Documentation sur le mot clé</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>Fichiers récents</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Copier le Chemin de Fichier Com&amp;plet</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Éditeur</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>ligne:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>col:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>encodage :</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>fin de ligne :</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Condition de point d&apos;arrêt</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>Erreur : </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Éditeur d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>Impossible d&apos;ajouter un point d&apos;arrêt à un fichier modifié ou sans nom.\nSauvegarder avant d&apos;ajouter le point d&apos;arrêt, ou annuler ?</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Aller à la ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Numéro de ligne</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Commenter le texte sélectionné</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Caractère(s) de commentaire à utiliser :\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;sans-nom&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>Voulez vous annuler la fermeture, enregistrer, ou abandonner les modifications?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>Le Fichier\n\n  %1\n\nest sur le point d&apos;être fermé mais a été modifié.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>Impossible de lire le fichier &apos;%1&apos;\navec l&apos;encodage sélectionné &apos;%2&apos; : %3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>Des problèmes ont été rencontrés lors de la lecture du fichier\n%1\navec l&apos;encodage sélectionné %2.\n\nModifier et sauvegarder ce fichier pourrait causer des pertes de données!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>Édit&amp;er malgré tout</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>Chan&amp;ger l&apos;encodage</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Fermer</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Sélectionner le nouvel encodage par défaut</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Veuillez choisir un nouvel encodage\npour recharger le fichier en courant.\n\nCeci ne change pas l&apos;encodage par défaut.\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Déboguer ou Enregistrer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Ce fichier est en cours d&apos;exécution.\nQuitter le mode débogage et sauver?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>Impossible d&apos;ouvrir le fichier %1 en écriture :\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>Les modification n&apos;ont pas pu être sauvegardées dans le fichier\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Fichiers Octave (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Tous les Fichiers (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>&quot;%1&quot;\nn&apos;est pas un nom valide.\n\nSi vous gardez ce nom de fichier, vous ne pourrez pas exécuter\nvotre script en utilisant son nom en guise de commande Octave.\n\nVoulez vous choisir un autre nom?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>Le contenu actuel de l&apos;éditeur ne peut être encodé\navec l&apos;encodage sélectionné %1.\nCela mènerai à des pertes de données!\n\nVeuillez choisir un autre encodage!</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1\nexiste déjà\nVoulez vous l&apos;écraser?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nAvertissement: Le contenu dans l&apos;éditeur est modifié!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>Il semblerait que &apos;%1&apos; a été modifié par une autre application. Voulez vous le recharger?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>Il semblerait que le fichier\n%1\na été supprimé ou renommé. Voulez vous l&apos;enregistrer maintenant ?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Taille du fichier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Type de fichier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Date de modification</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Afficher les fichiers cachés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Alterner les couleurs des lignes</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Entrez le chemin ou le nom du fichier</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Répertoire Parent</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Afficher répertoire d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Aller au répertoire courant d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Définir le Répertoire Courant d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Utiliser le répertoire du navigateur comme répertoire courant</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Actions sur le répertoire courant</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Aller au Répertoire Personnel</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Choisir le Répertoire du Navigateur...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Rechercher des Fichiers...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Nouveau Fichier...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Nouveau Répertoire...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Double cliquer pour ouvrir le fichier/dossier, cliquer droit pour les alternatives</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Renommer...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Ouvrir</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Ouvrir dans l&apos;Explorateur de Fichiers du Système</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Ouvrir dans l&apos;Éditeur de Texte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Copier la Sélection dans le Presse-Papiers</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Exécuter</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Charger les données</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Définir le Répertoire Courant</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Ajouter au Chemin</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Répertoires Sélectionnés</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Répertoires Sélectionnés incluant les Sous-Répertoires</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Retirer du Chemin</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Effacer...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Supprimer le fichier/répertoire</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>Êtes vous sûr de vouloir effacer les %1 fichiers sélectionnés?\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>Êtes-vous sûr de vouloir supprimer\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>Impossible de supprimer un répertoire qui n&apos;est pas vide</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Erreur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>Impossible d&apos;effacer le fichier &quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Définir le répertoire de l&apos;explorateur de fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Créer un Fichier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Créer un fichier dans\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Nouveau Fichier.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Erreur lors de la création du fichier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>Impossible de créer le fichier\n&quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Créer un Répertoire</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Créer un répertoire dans\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Nouveau Répertoire</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>Impossible de renommer le fichier &quot;%1&quot; en &quot;%2&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Explorateur de fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Examinez vos fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>Système de Fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>Fichiers Éditeur</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>Appréciez !</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Précédent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Terminer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annuler</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Nous espérons que vous trouvez Octave utile.&lt;/p&gt;\n&lt;p&gt;Si vous rencontrez des difficultés, il y a un certain nombre de moyen de trouver de l&apos;aide, parmi lesquels un support commercial, un forum de discussion, un wiki, et encore d&apos;autres communautés d&apos;aide.\nVous trouverez plus de détails en visitant &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (ouvert dans un navigateur externe).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Pour plus d&apos;informations concernant Octave :&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visitez &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (ouvert dans un navigateur externe)&lt;/li&gt;\n&lt;li&gt;Trouvez la documentation en ligne au format &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; ou &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; (liens ouverts dans un navigateur externe)&lt;/li&gt;\n&lt;li&gt;Ouvrez le navigateur de documentation de l&apos;interface graphique d&apos;Octave à l&apos;aide du menu Aide&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Éditeur :.Rechercher et Remplacer</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Rechercher :</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Entrer le texte à rechercher</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>Rem&amp;placer :</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>Entrer le texte de remplacement</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>Respecter &amp;la casse</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>Rechercher depuis &amp;le début</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>&amp;Reprendre la recherche au début du fichier</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>Trouver le &amp;Suivant</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>Trouver le &amp;Précédent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>&amp;Remplacer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>&amp;Tout remplacer</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>&amp;Plus d&apos;options...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>&amp;Mots entiers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>&amp;Expressions régulières</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>Recherche vers l&apos;&amp;arrière</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>Recherche dans la sé&amp;lection</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Rechercher depuis la fin</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Rechercher depuis le début</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Résultats du remplacement</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 instances remplacées</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Résultats de la recherche</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>Plus aucune correspondance trouvée</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Rechercher des fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Nommé:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>Démarrer dans :</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Répertoire de démarrage</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Naviguer...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Choisir le répertoire de démarrage</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Répertoire Courant</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>Utiliser le répertoire courant comme répertoire de démarrage</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Rechercher dans les sous dossiers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Rechercher les fichiers récursivement dans les sous-répertoires</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Inclure les noms de dossiers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Inclure les répertoires concordants dans des résultats de la recherche</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Ignorer la casse</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>Rechercher en ignorant la casse</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>Contenant le texte :</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>N&apos;inclure dans les résultats, que les fichiers contenant le texte spécifié</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Texte à rechercher</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Résultats : Double clicker ouvre le fichier ou change de répertoire</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Résultats de la recherche</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>Inoccupé.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Entrer le motif de rechreche de nom de fichier.\nIl est possible de spécifier plusieurs motifs différents\nséparés par des &apos;;&apos;,par exemple &apos;*.cc ; *.h&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>Rechercher</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Démarrer la recherche des fichiers concordants</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Arrêter</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Arrêter la recherche</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>Nom de Fichier/Emplacement</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Contenu du fichier</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>Recherche en cours...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 résultat(s)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Définir le répertoire de recherche</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Nom du fichier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Répertoire</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Double cliquer pour ouvrir le fichier</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Double cliquer pour changer de dossier</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Rechercher :</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>Rechercher le suivant</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Rechercher le précédent</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Fermer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Fermer la fenêtre de recherche</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Erreur %1 lors de la création du fichier de paramètres\n%2\nAssurez vous que vous avez les droits de lecture et d&apos;écriture dans\n%3\n\nLe GUI Octave doit maintenant être fermé.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Erreur Critique d&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Naviguer et Rechercher l&apos;historique des commandes.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Copier</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Évaluer</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Créer un fichier de script</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Cacher le filtre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Afficher le filtre</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Double cliquez une commande pour l&apos;exécuter dans la fenêtre de commande.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Entrer du texte pour filtrer l&apos;historique des commandes</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Filtrer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Historique des Commandes</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Bienvenue dans Octave !</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Suivant</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annuler</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Vous semblez utiliser l&apos;interface graphique d&apos;Octave pour la première fois sur cet ordinateur.\nCliquez &quot;Suivant&quot; pour créer un fichier de configuration et lancer Octave.&lt;/p&gt;\n&lt;p&gt;Le fichier de configuration est enregistré dans&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Détacher la Fenêtre</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Fermer l&apos;élément</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Profilage</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>Voulez vous vraiment quitter Octave ?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Enregistrer l&apos;Espace de Travail</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Charger un Espace de Travail</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>À propos d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Naviguer dans les Répertoires</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Fichiers Octave (*.m);;Tous les fichiers (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Nouvelle Fonction</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Nom de la nouvelle fonction :\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>%1 est une fonction interne compilée ou inline\net ne peut être éditée.</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>Impossible de trouver la fonction %1</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Éditeur d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Fichier</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Ouvrir...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Ouvrir un fichier existant dans l&apos;éditeur</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Charger un Espace de Travail...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Enregistrer l&apos;Espace de Travail sous...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Quitter</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Nouveau</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Nouveau Script</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Nouvelle Fonction...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Nouvelle Figure</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Éditer</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Annuler</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Copier</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Coller</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Tout Sélectionner</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Effacer le Presse-Papier</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Rechercher des fichiers...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Effacer la Fenêtre de Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Effacer l&apos;Historique des Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Effacer l&apos;Espace de Travail</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Gestion des Chemins...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Préférences...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>Dé&amp;boguer</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Avancer d&apos;un pas</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Avancer d&apos;un pas avec entrée</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Exécuter jusqu&apos;à l&apos;instruction de retour</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Continuer</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Quitter le mode Débogage</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>Ou&amp;tils</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>Démarrer une Session de &amp;Profilage</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>&amp;Reprendre une Session de Profilage</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>&amp;Arrêter le Profilage</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>&amp;Afficher les Données de Profilage</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>Fenê&amp;tre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Afficher la Fenêtre de Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Afficher l&apos;Historique des Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Afficher le Navigateur de Fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Afficher l&apos;Espace de Travail</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Afficher l&apos;Éditeur</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Afficher la Documentation</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Afficher l&apos;Éditeur de Variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Fenêtre de Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Historique des Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Explorateur de fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Espace de travail</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Éditeur</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Documentation</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Éditeur de Variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Fenêtre Précédente</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Restaurer l&apos;Agencement par Défaut</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Aide</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Déclarer un Bogue</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Paquets d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>S&apos;Impliquer</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Donner à Octave</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>Installée localement</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>En ligne</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Nouvelles</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Notes de Version</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Nouvelles de la Communauté</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Barre d&apos;Outils</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Entrez le nom du répertoire</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Répertoire Courant : </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Répertoire Parent</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nLes nouvelles de la communauté Octave ne semblent pas disponibles.\n&lt;/p&gt;\n&lt;p&gt;\nPour lire les nouvelles fraîches, visitez\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nlorsque vous aurez une connexion internet (lien ouvert dans un navigateur externe).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Les développeurs d&apos;Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nLes nouvelles de la communauté Octave ne semblent pas disponibles.\n&lt;/p&gt;\n&lt;p&gt;\nPour lire les nouvelles fraîches, visitez\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nlorsque vous aurez une connexion internet (lien ouvert dans un navigateur externe).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Les Développeurs d&apos;Octave, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Cacher la Fenêtre</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Attacher l&apos;Élément</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Détacher l&apos;Élément</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>Aide sur</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>Documentation sur</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>Éditer</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop si ...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Éditeur d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>Impossible de créer un fichier temporaire.\nAssurez vous d&apos;avoir accès en écriture au dossier temporaire\n%1\n\n&quot;Exécuter la Sélection&quot; nécessite l&apos;utilisation de fichiers temporaires.</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>Presser &apos;%1&apos; pour remplacer toutes les occurrences de &apos;%2&apos; par &apos;%3&apos;.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>Défaut</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Créer</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>Annuler</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Le fichier\n%1\nn&apos;existe pas. Voulez vous le créer?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Éditeur d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>Le fichier %1 ne se trouve pas dans les chemins accessibles.  Pour exécuter ou déboguer la fonction éditée, vous devez changer de dossier vers %2 ou ajouter ce dossier aux chemins accessibles.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>Le fichier %1 est masqué par un fichier du même nom dans les chemins accessibles.  Pour exécuter ou déboguer la fonction éditée, vous devez changer de dossier vers %2.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Changer de répertoire ou ajouter le répertoire aux chemins accessibles</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>&amp;Changer de Répertoire</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>&amp;Ajouter le répertoire aux Chemins Accessibles</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>Le fichier de notes de version &apos;%1&apos; est vide.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>Le fichier de notes de version &apos;%1&apos; est illisible.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Notes de la version d&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Gestion des Chemins</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Tous les changements prennent effet immédiatement.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Ajouter un Répertoire...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Répertoire Unique</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Répertoire et Sous-répertoires</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>Mettre en Tête</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>Mettre en Queue</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Monter</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Descendre</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Enlever</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Re-charger</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Enregistrer</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Annuler</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Annuler le changement précédent</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Annuler tous les changements</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Ouvrir le Dossier</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>Haut</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>Bas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>Gauche</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>Droite</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Premier plan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Arrière plan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Sélection</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>Curseur</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Premier plan sélectionné</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Arrière plan sélectionné</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Arrière Plan Alterné</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>argument</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>global</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>persistent</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Variables d&apos;Environnement</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>Second thème de couleur (clair/sombre)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>Utiliser un nouveau jeu de couleurs.\nUtile pour définir un mode clair/sombre.\nPerdre les modifications encore non appliquées !</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>Recharger les couleurs par défaut,\nen fonction du mode actuellement sélectionné.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>Recharger les valeurs du style par défaut,\nen fonction du mode actuellement sélectionné.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>&amp;Recharger les couleurs par défaut</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>&amp;Recharge les styles par défaut</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Chargement des paramètres courants ... </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Réglages système</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>Curseur Trait Vertical</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>Curseur Bloc</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>Curseur Tiret Bas</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>Couleur pour faire ressortir la ligne courante (magenta (255,0,255) par défaut)</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Choisir le répertoire de démarrage d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Choisir le répertoire de démarrage du navigateur de fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Application des préférences ... </translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>Impossible d&apos;ouvrir %1 en tant que fichier de raccourcis Octave</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Coloration des attributs</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Masquer les bulles d&apos;aide</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Importer des raccourcis depuis un fichier...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Fichier de Raccourcis Octave (*.osc);;Tous les fichiers (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Exporter les raccourcis vers un fichier...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Écrasement des Raccourcis</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Vous vous apprêtez à écraser tous le raccourcis.\nVoulez sauvegarder les raccourcis actuels ou annuler cette action ?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>Ne pas enregistrer</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Préférences de l&apos;Interface Graphique d&apos;Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Nouvelles de la Communauté</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Précédent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Suivant</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annuler</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Quand Octave démarrera il pourra, de manière optionnelle, interroger le site internet sur les nouveautés et informations de la communauté d&apos;Octave.\nCes interrogations se feront au plus une fois par jour et les nouvelles ne seront affichées que si nouvelle(s) il y a.&lt;/p&gt;\n&lt;p&gt;Vous pouvez afficher la fenêtre des nouvelles en sélectionnant &quot;Nouvelle de la communauté&quot; dans le menu &quot;Aide&quot;, ou en visitant\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Autoriser Octave à se connecter au site web au démarrage afin d&apos;afficher les nouveautés et informations de la communauté d&apos;Octave &lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Entrer un Nouveau Raccourci</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Action: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Entrer le raccourci en le tapant</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Ajouter la touche de modification Maj (permet d&apos;utiliser les touches de nombres)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Raccourci Courant</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Raccourci par Défaut</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Effacer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Revenir au défaut</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Raccourci en double</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>Le raccourci choisi\n  &quot;%1&quot;\nest déjà utilisé pour l&apos;action\n  &quot;%2&quot;.\nVoulez vous réaffecter ce raccourci ?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Global</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Menu Fichier</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Menu Éditer</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Menu Déboguer</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Menu Outils</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Menu Fenêtre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Menu Aide</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Menu Nouvelles</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Gestion des Éléments Amovibles</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Gestion des Onglets dans les Fenêtre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Rechercher &amp; Remplacer dans la Fenêtre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Zoom dans l&apos;Éditeur et le Navigateur de Documentation</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Éditeur</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Menu Afficher</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Menu Exécuter</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Navigateur de Documentation</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Navigateur</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>Impossible de trouver %1 dans le dialogue des raccourcis</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Bienvenu dans GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Bienvenue dans Octave !</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Fenêtre de Commandes</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Attacher l&apos;Élément</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Éditeur de Variables: </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Détacher l&apos;Élément</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Restaurer la géométrie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Rattacher</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Éditeur de Variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Éditer les Variables.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Barre d&apos;outils de l&apos;éditeur de variables</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Enregistrer</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Enregistrer la variable dans un fichier</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Enregistrer au format ...</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Enregistrer la variable dans un fichier dans un format différent</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Couper</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Couper les données vers le presse papier</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Copier</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Copier les données vers le presse-papiers</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Coller</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Coller le presse papier dans une variable</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Graphique</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Graphique des données sélectionnées</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Graphique des données sélectionnées</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Monter</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>Monter d&apos;un niveau dans la hiérarchie de la variable</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>Enregistrer la Variable %1 Sous</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Couper</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Copier</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Coller</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Effacer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Effacer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Variable à partir de la Sélection</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Transposer</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> colonnes</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> colonne</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> lignes</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> ligne</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Bienvenu dans GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>Nom</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensions</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valeur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Attribut</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Clic droit pour copier, renommer ou afficher</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>complexe</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensions</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valeur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Attribut</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Espace de travail</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Liste des variables dans l&apos;espace de travail.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Entrer du texte pour filtrer l&apos;espace de travail</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Filtrer</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Voir les variables dans l&apos;espace de travail.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Couleur pour les attributs des variables:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Ouvrir dans l&apos;Éditeur de Variables</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Copier le nom</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Copier la valeur</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Renommer</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Seuls les symboles du plus haut niveau peuvent être renommés</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Cacher le filtre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Afficher le filtre</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>Impossible d&apos;ouvrir le flux redirigé avec fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>Impossible de désactiver la mise en mémoire tampon avec fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>Impossible de dupliquer (dup) le flux redirigé avec fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>Impossible de créer un tunnel (pipe) redirigiger le flux avec fd = %1 :</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>Impossible de dupliquer (dup2) le flux redirigé avec fd = %1\npour le retransmettre (via pipe) avec fd = %2 : %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Erreur de réception de flux redirigés</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation>Erreur de lecture du flux redirigé fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\nÉcrire la redirection dans </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> ne fonctionnera pas.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\nErreur : </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Général</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Logo d&apos;Octave seulement</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Icônes textuelles</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Graphic icons</source>\n        <translation>Icônes graphiques</translation>\n    </message>\n    <message>\n        <location line=\"-341\"/>\n        <source>Dock widget title bar</source>\n        <translation>Barre de titre des fenêtres</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Normal</source>\n        <translation>Normal</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>Custom style</source>\n        <translation>Style personnalisé</translation>\n    </message>\n    <message>\n        <location line=\"+244\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Ces préférences sont appliquées après tout fichier de démarrage .octaverc.</translation>\n    </message>\n    <message>\n        <location line=\"+353\"/>\n        <source>Editor</source>\n        <translation>Éditeur</translation>\n    </message>\n    <message>\n        <location line=\"+187\"/>\n        <source>Show EOL characters</source>\n        <translation>Montrer les caractères de fin de ligne (EOL)</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Replier les lignes en bord de fenêtre</translation>\n    </message>\n    <message>\n        <location line=\"+558\"/>\n        <source>Default EOL mode</source>\n        <translation>Fin de ligne par défaut (EOL)</translation>\n    </message>\n    <message>\n        <location line=\"-503\"/>\n        <source>Indent width</source>\n        <translation>Largeur de l&apos;indentation</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Tab indente la ligne</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Indentation automatique</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Largeur de tabulation</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Afficher les guides d&apos;indentation</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Backspace supprime l&apos;indentation</translation>\n    </message>\n    <message>\n        <location line=\"+120\"/>\n        <source>Match keywords</source>\n        <translation>Inclure les mots clés</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Sensible à la casse</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Remplacer le mot par la suggestion</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Inclure les mots du document</translation>\n    </message>\n    <message>\n        <location line=\"-643\"/>\n        <source>Use custom file editor</source>\n        <translation>Utiliser un éditeur externe</translation>\n    </message>\n    <message>\n        <location line=\"+1009\"/>\n        <source>Editor Styles</source>\n        <translation>Affichage</translation>\n    </message>\n    <message>\n        <location line=\"-1485\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Police</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Afficher les numéros des lignes</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Show whitespace</source>\n        <translation>Afficher les espaces</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Ne pas afficher les espaces utilisés pour l&apos;indentation</translation>\n    </message>\n    <message>\n        <location line=\"+935\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Nombre de caractères avant affichage de la liste : </translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Créer les fichiers non existants sans prévenir</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>ligne de commande (%f=fichier, %l=ligne) :</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Type de curseur :</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Utiliser la couleur de l&apos;avant plan</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Taille de police</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Explorateur de fichiers</translation>\n    </message>\n    <message>\n        <location line=\"-2118\"/>\n        <source>Interface</source>\n        <translation>Interface Graphique</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Confirmer avant de quitter</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Montrer la barre de statut</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Texte inactif</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Actif</translation>\n    </message>\n    <message>\n        <location line=\"-96\"/>\n        <source>Small</source>\n        <translation>Petit</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Grand</translation>\n    </message>\n    <message>\n        <location line=\"+118\"/>\n        <source>Background inactive</source>\n        <translation>Arrière-plan inactif</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation>3-D</translation>\n    </message>\n    <message>\n        <location line=\"+206\"/>\n        <source>Octave Startup</source>\n        <translation>Démarrage d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Choisir</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Ceci fonctionne bien avec les polices typographiques (monospace). La ligne est dessinée tenant compte de la largeur d&apos;un caractère de la police par défaut. Cela peut dysfonctionner lors de l&apos;utilisation de polices à tailles variables ou de caractères gras et italiques.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Activer le masquage (repliage) de code</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation>Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>UNIX (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Montrer la barre de défilement horizontal</translation>\n    </message>\n    <message>\n        <location line=\"-970\"/>\n        <source>Preferences</source>\n        <translation>Préférences</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(redémarrage requis)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Utiliser le navigateur de fichiers natif du système</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Icônes de la Barre d&apos;Outils</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Langue</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Icône des fenêtres</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Style</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Thème d&apos;icônes (nécessite un redémarrage)</translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation>Curseur clignotant</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Afficher la fenêtre d&apos;accueil au démarrage</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Répertoire de travail initial de l&apos;interpréteur d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Restaurer le répertoire de travail de la précédente session</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Fenêtre de Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Donner le focus à la Fenêtre de Commandes après l&apos;exécution d&apos;une commande depuis une autre fenêtre</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Afficher les informations de débogage dans la Fenêtre de Commandes en plus du marqueur dans l&apos;éditeur</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Couleurs pour la Fenêtre de Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Show tool bar</source>\n        <translation>Afficher la barre d&apos;outils</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Incrément de taille de police par rapport au contenu</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Faire ressortir la ligne courante (couleur ajustable ci-dessous)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Marquer toutes les occurrences d&apos;un mot sélectionné par double clic</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Onglets</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pivoter les Onglets : verticaux quand il sont en haut et en bas, horizontaux à gauche et à droite. Le bouton de fermeture n&apos;est pas affiché sur les onglets pivotés.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Commentaires (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Caractère(s) valide(s) pour dé-commenter un texte</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Caractère(s) utilisé(s) pour commenter un texte sélectionné</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Longues lignes</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Couper les longues lignes à la longueur spécifiée</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Couper uniquement les lignes de commentaire</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Longueur</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Marqueur de longue ligne</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Arrière plan</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>Indentation</source>\n        <translation>Indentation</translation>\n    </message>\n    <message>\n        <location line=\"+127\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Indentation par tabulation</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Insertion automatique après &quot;if&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Aucune</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Auto completion</source>\n        <translation>Suggestions automatiques (complétion)</translation>\n    </message>\n    <message>\n        <location line=\"+101\"/>\n        <source>With Octave builtins</source>\n        <translation>Les commandes internes</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Les fonctions Octave</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Montrer la liste de suggestions automatiquement</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Debugging</source>\n        <translation>Débogage</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Toujours afficher les points d&apos;arrêt et pointeurs (ouvre les fichiers contenant des points d&apos;arrêt si nécessaire)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Gestion des fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Recharger automatiquement les fichiers modifiés depuis l&apos;extérieur d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"-50\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Restaurer les onglets de la session précédente au démarrage ou lorsque l&apos;éditeur est fermé puis rouvert</translation>\n    </message>\n    <message>\n        <location line=\"-31\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Encodage utilisé pour enregistrer et charger</translation>\n    </message>\n    <message>\n        <location line=\"+71\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Fermer tous les fichiers lorsque l&apos;éditeur est fermé ou caché</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>S&apos;assurer que les fichiers se terminent par un caractère de fin de ligne lors de la sauvegarde</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>Éliminer les espaces en fin de ligne lors de la sauvegarde</translation>\n    </message>\n    <message>\n        <location line=\"+144\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Sélectionner la taille de police (différence par rapport à la taille par défaut), son style (&lt;b&gt;g&lt;/b&gt;ras, &lt;b&gt;i&lt;/b&gt;talique, &lt;b&gt;s&lt;/b&gt;ouligné), sa couleur et la couleur de l&apos;arrière-plan (pour ce dernier, la couleur magenta (255,0,255) représente la couleur pas défaut).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+848\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - ferme le dialogue et applique les changements&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Appliquer - &lt;/span&gt;applique les changements mais laisse le dialogue ouvert&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Annuler - &lt;/span&gt;fermer le dialogue et annule les changements non appliqués&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Réinitialiser -&lt;/span&gt; recharge les paramètres en abandonnant les changements non appliqués&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-2254\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Changer la taille du tampon efface l&apos;historique)</translation>\n    </message>\n    <message>\n        <location line=\"-260\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Un fois coché, les sous-fenêtres attachées à la fenêtre principale récupèrent le focus clavier lorsque la sourie les survole. L&apos;objectif est d&apos;avoir le même comportement que dans la fenêtre principale lorsque l&apos;option &amp;quot;le focus suit la sourie&amp;quot; est utilisée dans l&apos;environnement de bureau.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>Le focus suit la sourie pour les fenêtres attachées à la fenêtre principale</translation>\n    </message>\n    <message>\n        <location line=\"+285\"/>\n        <source>History buffer Size</source>\n        <translation>Taille du tampon mémoire de l&apos;historique</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Rotated tabs</source>\n        <translation>Onglets Pivotés</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Position</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>Largeur maximale des onglets en caractères (0 : aucune limite)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Largeur maximale des onglets en caractères (largeur moyenne d&apos;un caractère). Particulièrement utile pour les onglets pivotés.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+871\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>La boîte de dialogue d&apos;ouverture des fichiers montre le répertoire du fichier en cours d&apos;édition plutôt que le répertoire courant d&apos;Octave </translation>\n    </message>\n    <message>\n        <location line=\"+98\"/>\n        <source>Behavior</source>\n        <translation>Comportement</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Revenir au répertoire de la session précédente</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>Répertoire initial du navigateur de fichiers (si non synchronisé avec le répertoire courant)</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Extensions des fichiers à ouvrir dans l&apos;éditeur de texte (séparées par &quot;;&quot;):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Espace de travail</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Couleurs pour les attributs de variables</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Utiliser la police de la Fenêtre de Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Importer un ensemble de raccourcis</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Exporter l&apos;ensemble des raccourcis</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Réinitialiser les raccourcis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Défaut</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation>Courant</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Réseau</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Autoriser Octave à se connecter à son site internet afin d&apos;afficher les informations et nouvelle fraîches</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Serveur Proxy</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Sélectionner &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; ou &lt;span style=&quot; font-style:italic;&quot;&gt;Variables d&apos;Environnement&lt;/span&gt;. Avec la dernière option, le proxy est déterminé par la première variable d&apos;environnement non vide parmi ALL_PROXY, HTTP_PROXY ou HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Utiliser un serveur proxy</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Éditeur de Variables</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Hauteur de ligne par défaut</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Largeur de colonne par défaut</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Couleurs</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Alterner les couleurs des lignes</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Désactiver les raccourcis globaux afin d&apos;éviter\nd&apos;interférer avec les raccourcis readline.\nExceptions : Ctrl-C pour interrompre l&apos;interpréteur\net les raccourcis pour ouvrir d&apos;autres fenêtres.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Désactiver les raccourcis globaux lorsque la Fenêtre de Commandes est active</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Synchroniser le répertoire de travail d&apos;Octave et le navigateur de fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+348\"/>\n        <source>Shortcuts</source>\n        <translation>Raccourcis</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Export</source>\n        <translation>Exporter</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importer</translation>\n    </message>\n    <message>\n        <location line=\"-44\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Désactiver les accélérateur de menus afin d&apos;éviter\nd&apos;interférer avec les raccourcis readline.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>Désactiver les accélérateurs de menus lorsque la Fenêtre de Commandes est active</translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Éditer le raccourci en double-cliquant dans la colonne &quot;Courant&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Action</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Nom de l&apos;hôte :</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Type de Proxy :</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Port :</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Nom d&apos;utilisateur :</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Mot de passe :</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Détacher/Attacher l&apos;élément</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Fermer l&apos;élément</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Nouveau Fichier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Nouvelle Fonction</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Nouvelle Figure</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Ouvrir un Fichier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Charger un Espace de Travail</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Enregistrer l&apos;Espace de Travail</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Quitter Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Copier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Coller</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Annuler</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Tout Sélectionner</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Effacer le Presse-Papier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>Rechercher dans les Fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Effacer la Fenêtre de Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Effacer l&apos;Historique des Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Effacer l&apos;Espace de Travail</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Gestion des Chemins</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Préférences</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Avancer d&apos;un pas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>Avancer d&apos;un pas avec entrée</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Exécuter jusqu&apos;à l&apos;instruction de retour</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Continuer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Quitter le mode Débogage</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Démarrer/Arrêter une Session de Profilage</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Reprendre la Session de Profilage</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Afficher les Résultats de Profilage</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Afficher la Fenêtre de Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Afficher l&apos;Historique des Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Afficher le Navigateur de Fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Afficher l&apos;Espace de Travail</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Afficher l&apos;Éditeur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Afficher la Documentation</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Afficher l&apos;Éditeur de Variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Fenêtre de Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Historique des Commandes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Explorateur de fichiers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Espace de travail</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Éditeur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Documentation</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Éditeur de Variables</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Fenêtre Précédente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Restaurer l&apos;Agencement par Défaut</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Afficher la Documentation Locale</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Afficher la Documentation en Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Déclarer un Bogue</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Paquets d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Contribuer à Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Ressources développeurs d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>À propos d&apos;Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Notes de Version</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Nouvelles de la Communauté</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Fermer l&apos;Onglet</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Fermer Tous les Onglets</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Fermer les Autres Onglets</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Ouvrir l&apos;Onglet de Gauche</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Ouvrir l&apos;Onglet de Droite</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Déplacer l&apos;Onglet à Gauche</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Déplacer l&apos;Onglet à Droite</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Agrandir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Réduire</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Taille Normale</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Éditer la Fonction</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Enregistrer un Fichier</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Enregistrer un Fichier Sous</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Imprimer</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Rétablir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Couper</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Rechercher et Remplacer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Trouver le Suivant</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Trouver le Précédent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Effacer jusqu&apos;au Début du Mot</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Effacer jusqu&apos;à la Fin du Mot</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Effacer jusqu&apos;au Début de la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Effacer jusqu&apos;à la Fin de la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Effacer la ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Copier la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Couper la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Dupliquer la Sélection/Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Transposer la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Montrer la liste de suggestions</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Commenter le texte sélectionné</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Dé-commenter la Sélection</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Commenter (Après Sélection)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Sélection en Majuscules</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Sélection en Minuscules</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Indenter la sélection en bloc</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Désindenter la sélectionne en bloc</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Indenter</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Convertir les caractères de fin de ligne en Windows</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Convertir les caractères de fin de ligne en UNIX</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Convertir les caractères de fin de ligne en Mac</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Aller à la Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Déplacer jusqu&apos;à la Parenthèse Correspondante</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Sélectionner jusqu&apos;à la Parenthèse Correspondante</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Ajouter/Supprimer un Marque Page</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Marque Page Suivant</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Marque Page Précédent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Retirer tous les Marque-Pages</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Préférences de Style</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Afficher les Numéros des Lignes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Afficher les Espaces</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Afficher les Fins de Lignes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Afficher les Guides d&apos;Indentation</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Afficher le Repère de Longue Ligne</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Afficher la barre d&apos;outils</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Afficher la barre de statut</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Afficher la barre de navigation horizontale</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Trier les Onglets Alphabétiquement</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Ajouter/Retirer un Point d&apos;Arrêt</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Point d&apos;Arrêt Suivant</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Point d&apos;Arrêt Précédent</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Retirer tous les Points d&apos;Arrêt</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Exécuter le Script</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Exécuter la Sélection</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Exécuter les Tests</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Exécuter les Démos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Aide sur le Mot de Clé</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Documentation sur le Mot de Clé</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>Aller à la page d&apos;Accueil</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>Reculer d&apos;une Page</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>Avancer d&apos;une Page</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Marquer cette Page</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/hu_HU.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"hu_HU\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Érvénytelen fáljnév</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Különbség az alapértelmezett mérethez képest</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>A háttérszín, rózsaszín (255, 0, 255) az alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>F</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>D</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>A</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>„%1” szerkesztése</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Segítség keresése a következőhöz: „%1”</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Dokumentáció keresése a következőhöz: „%1”</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Másolás</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Beillesztés</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Összes kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Kijelölés futtatása</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>Kijelölés szerkesztése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>Kijelölés a súgóban</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>Kijelölés a dokumentációban</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Ablak tartalom kiürítése</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%1 szerkesztése a(z) %2 sorban</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>Kijelölés vágólapra másolva</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>Alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Hiba</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Szám</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Kulcsszó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Kétszeres-idézett karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Egyszeres-idézett karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Művelet</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Azonosító</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Skalár</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>Paraméterbővítés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Fordított ékezetek</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Itteni dokumentum határoló</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Egyszeres-idézett itteni dokumentum</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>Alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Kulcsszó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>Címke</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>Parancskarakter elrejtése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>Külső parancs</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Változó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Művelet</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>Alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>Inaktív alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>C megjegyzése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>Inaktív C megjegyzése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>C++ megjegyzése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>Inaktív C++ megjegyzése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>JavaDoc stílusú C megjegyzése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>Inaktív JavaDoc stílusú C megjegyzése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Szám</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Inaktív szám</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Kulcsszó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Inaktív kulcsszó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Kétszeres-idézett karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>Inaktív kétszeres-idézett karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Egyszeres-idézett karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>Inaktív egyszeres-idézett karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID azonosító</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>Inaktív IDL UUID azonosító</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>Előfeldolgozó blokk</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>Inaktív előfeldolgozó blokk</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Művelet</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Inaktív művelet</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Azonosító</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Inaktív azonosító</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>Lezáratlan karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>Inaktív lezáratlan karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>C# szó szerinti karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>Inaktív C# szó szerinti karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>JavaScript szabványos kifejezése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>Inaktív JavaScript szabványos kifejezése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>JavaDoc stílusú C++ megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>Inaktív JavaDoc stílusú C++ megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>Másodlagos kulcsszavak és azonosítók</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Inaktív másodlagos kulcsszavak és azonosítók</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>JavaDoc kulcsszó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>Inaktív JavaDoc kulcsszó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>JavaDoc kulcsszóhiba</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>Inaktív JavaDoc kulcsszóhiba</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Globális osztályok és típusdefiníciók</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Inaktív globális osztályok és típusdefiníciók</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>C++ nyers karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>Inaktív C++ nyers karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation>Hármas-idézett szó szerinti Vala-karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation>Inaktív hármas-idézett szó szerinti Vala-karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation>Kettőskereszt-idézett Pike-karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation>Inaktív kettőskereszt-idézett Pike-karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation>Előfeldolgozó C megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation>Inaktív előfeldolgozó C megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation>Előfeldolgozó JavaDoc stílusú megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation>Inaktív előfeldolgozó JavaDoc stílusú megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation>Felhasználó által meghatározott szövegállandó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation>Inaktív felhasználó által meghatározott szövegállandó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation>Feladatjelölő</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation>Inaktív feladatjelölő</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation>Vezérlősorozat</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation>Inaktív vezérlősorozat</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>Alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Parancs</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>Fejléc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Szövegbeosztás</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Sor eltávolítva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Sor hozzáadva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Sor megváltozva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation>Javítókészlet hozzáadása hozzáadva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation>Javítókészlet hozzáadása eltávolítva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation>Javítókészlet eltávolítása hozzáadva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation>Javítókészlet eltávolítása eltávolítva</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>Alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Parancs</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Szám</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Kulcsszó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Egyszeres-idézett karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Művelet</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Azonosító</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Kétszeres-idézett karakterlánc</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>Alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Hiba</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Szám</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Kulcsszó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Kétszeres-idézett karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Egyszeres-idézett karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Művelet</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Azonosító</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Skalár</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>Tömb</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>Kettőskereszt</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Szimbólumtábla</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>Szabványos kifejezés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>Helyettesítés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Fordított ékezetek</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>Adatok szakasz</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Itteni dokumentum határoló</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Egyszeres-idézett itteni dokumentum</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>Kétszeres-idézett itteni dokumentum</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>Fordított ékezet itteni dokumentum</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>Idézett karakterlánc (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>Idézett karakterlánc (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>Idézett karakterlánc (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>Idézett karakterlánc (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>Idézett karakterlánc (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>POD szó szerint</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>Alprogram prototípusa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>Azonosító formázása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>Törzs formázása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>Kétszeres-idézett karakterlánc (interpolált változó)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>Fordítás</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>Szabványos kifejezés (interpolált változó)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>Helyettesítés (interpolált változó)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>Fordított ékezetek (interpolált változó)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>Kétszeres-idézett itteni dokumentum (interpolált változó)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>Fordított ékezet itteni dokumentum (interpolált változó)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>Idézett karakterlánc (qq, interpolált változó)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>Idézett karakterlánc (qx, interpolált változó)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>Idézett karakterlánc (qr, interpolált változó)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>&amp;Visszavonás</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Ismét</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>&amp;Kivágás</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Másolás</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>Beilles&amp;ztés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Törlés</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Összes kijelölése</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Hivatkozás megnyitása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Hivatkozás címének másolása</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>E-mail küldése…</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>E-mail-cím másolása</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%1 szerkesztése a(z) %2 sorban</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Szöveg</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Betűkészlet</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>Félkövér</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>F</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>Dőlt</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>D</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>Szín</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>Balra zárt</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>Középre igazítás</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>Jobbra zárt</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>Vízszintes igazítás</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>Függőleges igazítás</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>Fel</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>Le</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Szövegbeosztás</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Szélesség</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Magasság</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>Egység</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>Normalizált</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Mezőhöz igazítás</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Mező</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Háttér</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Él</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Vonalstílus</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>Nincs</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Vonalvastagság</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Összes kijelölése</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Szüneteltetés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Leállítás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Folytatás</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Parancsvezérlő</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Oktáv közösségi hírek</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>Alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Hiba</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>Kérdezés</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Oktáv-dokumentáció</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>Nem sikerült átmásolni a súgógyűjteményt az ideiglenes\nfájlba. Ez hatással lehet a keresési képességekre.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>Nem sikerült beállítani a dokumentációnézőhöz\nszükséges adatokat. Lehet, hogy a Qt SQLite\nmodul hiányzik?\nCsak a parancsablak súgószövege lesz elérhető.</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>Tartalom</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Szöveg megadása a függvénytárgymutatóban való kereséshez</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Keresés</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>Függvénytárgymutató</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Könyvjelzők</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>Kezdőoldal</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Vissza</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Előző oldalak</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>Előre</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Következő oldalak</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Keresés</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Nagyítás</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Kicsinyítés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Valóságos méret</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>A jelenlegi oldal megjelölése könyvjelzővel</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>Nem sikerült regisztrálni a(z) %1 súgófájlt.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nNincsenek betöltve dokumentációs könyvjelzők!</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Oktáv: Dokumentációs könyvjelzők betöltése</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Szöveg megadása a könyvjelzőkben való kereséshez</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Szűrő</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Új mappa</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Megnyitás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>Átne&amp;vezés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>&amp;Eltávolítás</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>Mappa &amp;hozzáadása</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>Szűrő &amp;elrejtése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>Szűrő &amp;megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Oktáv: Dokumentációs könyvjelzők mentése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>A(z) %1 fájl nem írható:\n%2.\n\nA dokumentációs könyvjelzők nem kerülnek mentésre!\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>A(z) %1 fájl nem olvasható:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>Nem található kezdőelem a következőben: %1.\nÉrvénytelen könyvjelzőfájl?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>A fájl\n%1\nnem érvényes XBEL-fájl 1.0-s verziója.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Ismeretlen cím</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Dokumentáció</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Segítségért tekintse meg a dokumentációt.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Bezárás</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>Az összes be&amp;zárása</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>&amp;Másik bezárása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>Váltás a &amp;bal oldali vezérlőre</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>Váltás a &amp;jobb oldali vezérlőre</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation>Szerkesztőfájlok megnyitása</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation>Kattintson a fájl fókuszba helyezéséhez a szerkesztőben</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Bezárás</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>Az összes be&amp;zárása</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Futtatás</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Jelenlegi &amp;könyvtár beállítása</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Oktáv-szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>Nem sikerült elindítani az egyéni fájlszerkesztőt\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Egyéni szerkesztő még nincs beállítva.\nSzeretné megnyitni a beállításokat?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Folytatás</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Fájl mentése és futtatása</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Oktáv-szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>A fájl nincs mentve! Egy fájl a kijelölt névvel\n%1\nmár meg van nyitva a szerkesztőben.</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>A hozzátartozó fájlszerkesztő lap eltűnt.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>Nem sikerült megnyitni a fájlt\n%1\nolvasáshoz: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Fájl\n%1\nnem létezik. Szeretné létrehozni?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Létrehozás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Mégse</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>Nem sikerült megnyitni a fájlt\n%1\níráshoz: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Fájl</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>Legutóbbi szerkesztő&amp;fájlok</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>Függvény s&amp;zerkesztése</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>Fájl m&amp;entése</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>Fájl me&amp;ntése másként…</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Bezárás</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Az összes bezárása</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Más fájlok bezárása</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Nyomtatás…</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>S&amp;zerkesztés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Ismét</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>&amp;Kivágás</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>Keresés és &amp;csere…</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>Kö&amp;vetkező találat</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>Elő&amp;ző találat</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>&amp;Parancsok</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Sor törlése</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Sor másolása</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Sor kivágása</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Törlés a szó elejére</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Törlés a szó végére</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Törlés a sor elejére</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Törlés a sor végére</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Kijelölés/sor megkettőzése</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Sor transzponálása</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>&amp;Befejezési lista megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Formátum</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>&amp;Nagybetűs kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>&amp;Kisbetűs kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>&amp;Megjegyzés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>Megjegyzés megs&amp;züntetése</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Megjegyzés (karakterlánc kijelölése)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>Kijelölés behúzásának &amp;növekedése rögzítettként</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>Kijelölés behúzásának &amp;csökkentése rögzítettként</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Kód behúzása</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Átalakítás a &amp;Windows (CR LF karakterpár) sorvégződésekre</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Átalakítás az &amp;Unix (LF karakter) sorvégződésekre</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Átalakítás az örökölt &amp;Mac (CR karakter) sorvégződésekre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>&amp;Navigáció</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>Ugrás &amp;sorra…</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Ugrás az egyező zárójelre</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Egyező zárójel kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>Kö&amp;vetkező könyvjelző</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>Elő&amp;ző könyvjelző</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>&amp;Könyvjelző kapcsolása</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>Összes könyvjelző &amp;eltávolítása</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Beállítások…</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>&amp;Stílusok beállításai…</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>&amp;Nézet</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>S&amp;zerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>&amp;Sorszámok megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>El&amp;választó karakterek (szóköz, sortörés vagy tabulátor) megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Sor&amp;végek megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>&amp;Behúzási segédvonalainak megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>Hosszú vonal &amp;jelölő megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>&amp;Eszköztár megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>Állapotsor me&amp;gjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>&amp;Vízszintes görgetősáv megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>&amp;Nagyítás</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>&amp;Kicsinyítés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>&amp;Tényleges méret</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>Lapok &amp;rendezése betűrendben</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Hibakeresés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>&amp;Töréspont kapcsolása</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>Kö&amp;vetkező töréspont</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>Elő&amp;ző töréspont</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>Összes töréspont &amp;eltávolítása</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>&amp;Futtatás</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Fájl mentése és futtatása/folytatása</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>&amp;Kijelölés futtatása</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Fájl mentése és az összes &amp;teszt futtatása</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Fájl mentése és az összes &amp;bemutató futtatása</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Súgó</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>Kulcsszó &amp;súgóban</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>Kulcsszó a &amp;dokumentációban</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>Legutóbbi fájlok</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Teljes fájl &amp;elérési út másolása</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Szerkesztő</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>sor:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>oszlop:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>kódolás:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>sorvég:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Töréspontfeltétel</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>HIBA: </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Oktáv-szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>Nem lehet töréspontot hozzáadni a módosított vagy névtelen fájlhoz.\nMenteni és hozzáadni a töréspontot, vagy megszakítani?</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Ugrás sorra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Sorszám</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Megjegyzés hozzáfűzése a kijelölt szöveghez</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Megjegyzés hozzáfűzése a használt karakterlánchoz:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;névtelen&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>Szeretné visszavonni a bezárást, menteni vagy elvetni a módosításokat?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>A fájl\n\n  %1\n\nbezárás előtt áll, de módosították.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>Nem sikerült beolvasni a(z) „%1” fájlt\n„%2” kijelölt kódolással: %3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>Problémák adódtak a fájl olvasásával\n%1\na kijelölt %2 kódolással.\n\nA fájl módosítása és mentése adatvesztést okozhat!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>S&amp;zerkesztés mégis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>Kódolás &amp;módosítása</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Bezárás</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Új alapértelmezett kódolás kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Kérjük, adjon meg új kódolást\na jelenlegi fájl újratöltéséhez.\n\nEz nem változtatja meg az alapértelmezett kódolást.\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Hibakeresés vagy mentés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Ez a fájl jelenleg végrehajtás alatt áll.\nKilép a hibakeresésből és menti?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>Nem sikerült megnyitni a(z) %1 fájlt írásra:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>A módosításokat nem sikerült elmenteni a fájlba\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Oktáv-fájlok (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Minden fájl (*)</translation>\n    </message>\n    <message>\n        <location line=\"+67\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>A(z) %1 fájl már létezik.\nSzeretné felülírni?</translation>\n    </message>\n    <message>\n        <location line=\"+38\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>„%1”\nnem érvényes azonosító.\n\nHa ezt a fájlnevet megtartja, a parancsfájl nem lesz\nhívható a nevét oktáv-parancsként használva.\n\nMás nevet szeretne választani?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>A jelenlegi szerkesztő tartalma nem kódolható a\n%1 kijelölt kódolással.\nHasználata adatvesztéshez vezet!\n\nKérjük, válasszon másikat!</translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nFigyelmeztetés: A szerkesztő tartalma módosult!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>Úgy tűnik, hogy a(z) &apos;%1&apos; fájlt egy másik alkalmazás módosította. Szeretné újratölteni?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>Úgy tűnik, hogy a fájl\n%1\ntörölve vagy átnevezve. Szeretné most menteni? %2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Fájlméret</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Fájltípus</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Módosítás dátuma</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Rejtettek megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Változó sorszínek</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Elérési út vagy fájlnév megadása</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Egy könyvtárral feljebb</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Oktáv-könyvtár megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Ugrás a jelenlegi Oktáv-könyvtárba</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Oktáv-könyvtár beállítása</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Oktáv-könyvtár beállítása a jelenlegi könyvtártallózóra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Műveletek a jelenlegi könyvtárban</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Kezdőkönyvtár megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Könyvtártallózó beállítása…</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Fájlok találása…</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Új fájl…</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Új könyvtár…</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Kattintson duplán a fájl/mappa megnyitásához, jobb gombbal kattintson az egyéb lehetőségekért</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Átnevezés…</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Megnyitás</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Megnyitás a rendszerfájlkezelőben</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Megnyitás a szövegszerkesztőben</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Kijelölés másolása a vágólapra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Futtatás</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Adatok betöltése</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Jelenlegi könyvtár beállítása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Hozzáadás az elérési úthoz</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Kijelölt könyvtárak</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Kijelölt könyvtárak és alkönyvtárak</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Eltávolítás az elérési útról</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Törlés…</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Fájl/könyvtár törlése</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>Biztosan törölni szeretné az összes (%1) kijelölt fájlt?\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>Biztosan törölni szeretné\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>Nem törölhető a nem üres könyvtár</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Törlési hiba</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>Nem sikerült törölni a(z) „%1” fájlt.</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Fájlböngésző könyvtárbeállítása</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Fájl létrehozása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Fájl létrehozása a következő helyen:\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Új fájl.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Fájl létrehozása hiba</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>Nem sikerült létrehozni a fájlt\n&quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Könyvtár létrehozása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Mappa létrehozása a következő helyen:\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Új könyvtár</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>Nem sikerült átnevezni a(z) „%1” fájlt a következőre: „%2”.</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Fájltallózó</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Fájlok tallózása</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>Fájlrendszer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>Szerkesztőfájlok</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>Készen áll a használatra!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Előző</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Befejezés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Mégse</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Reméljük, hogy hasznos eszköznek találja az Oktávot.&lt;/p&gt;\n&lt;p&gt;Ha hibákat tapasztal, számos módon kaphat segítséget, beleértve a kereskedelmi támogatási lehetőségeket, egy vitafórumot, egy wikit és más közösségi alapú támogatási csatornákat.\nEzekről további információkat találhat a &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; oldalon (külső böngészőben nyílik meg).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;További információ az Oktávról:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Látogassa meg a &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; webhelyet (külső böngészőben nyílik meg)&lt;/li&gt;\n&lt;li&gt;Szerezze be online a dokumentációt &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; vagy &lt;a href=&quot;https://www. gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; formátum (a hivatkozások külső böngészőben nyílnak meg)&lt;/li&gt;\n&lt;li&gt;Nyissa meg az Oktáv grafikus felhasználói felület dokumentációs böngészőjét a súgó menüvel&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Szerkesztő: Keresés és csere</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Keresés:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Keresési szöveg megadása</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>&amp;Csere:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>Csereszöveg megadása</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>Kis&amp;betűk és nagybetűk megkülönböztetése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>Keresés az &amp;elejétől</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>Keresés &amp;tördelése</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>Kö&amp;vetkező találat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>Elő&amp;ző találat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>&amp;Csere</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>&amp;Az összes cseréje</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>&amp;További lehetőségek…</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>Csak &amp;teljes szavak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>Szabványos ki&amp;fejezések</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>Keresés &amp;visszafelé</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>&amp;Kijelölés keresése</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Keresés a végétől</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Keresés az elejétől</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Eredmény csere</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 elem cserélve</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Keresés eredménye</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>Nincs több találat</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Fájlok keresése</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Elnevezett:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Adja meg a fájlnév-keresési mintákat.\nTöbbféle minta lehet\n„;”-vel elválasztva, pl. „*.cc ; *.h”</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Start in:</source>\n        <translation>Indítás helye:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Kezdőkönyvtár megadása</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Tallózás…</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Tallózás a kezdőkönyvtárért</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Jelenlegi könyvtár</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>A kezdőkönyvtár beállítása a jelenlegi könyvtárra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Alkönyvtárak keresése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Rekurzív keresése a fájlok egyeztetéséhez a könyvtárakban</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Könyvtárnevek tartalmazása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Tartalmazza könyvtárak egyeztetése a keresési eredményekbe</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Kis- és nagybetűk figyelmen kívül hagyása</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>Kis- és nagybetűk közötti egyezés végrehajtása</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>Szövegrészlet:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>Csak a megadott szöveget tartalmazó fájlokat jelenítse meg a keresési eredmények között</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Egyező szöveg</translation>\n    </message>\n    <message>\n        <location line=\"+38\"/>\n        <source>Idle.</source>\n        <translation>Tétlen.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find</source>\n        <translation>Keresés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Keresés indítása a fájlok egyeztetéséhez</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Leállítás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Keresés leállítása</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>Fájlnév/hely</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Fájl tartalma</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Eredmények: Dupla kattintással megnyitja a fájlt vagy beállítja a könyvtárat</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Keresés eredménye</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Searching...</source>\n        <translation>Keresés folyamatban van…</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 találat</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Keresési könyvtár beállítása</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Fájlnév</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Könyvtár</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Kattintson duplán a fájl megnyitásához</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Kattintson duplán a könyvtár beállításához</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Keresés:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>Keresés előre</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Keresés visszafelé</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Bezárás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Keresés párbeszédpanel bezárása</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Hiba %1 a beállítási fájl létrehozásakor\n%2\nGyőződjön meg arról, hogy rendelkezik olvasási és írási jogosultsággal\n%3\n\nAz Oktáv grafikus felhasználói felületét most be kell zárni.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Kritikus Oktáv-hiba</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Parancselőzmények tallózása és keresése.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Másolás</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Kiértékelés</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Parancsfájl létrehozása</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Szűrő elrejtése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Szűrő megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Kattintson duplán egy parancsra a parancsablakba való átvitelhez.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Szöveg megadása a parancselőzmények szűréséhez</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Szűrő</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Parancselőzmények</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Isten hozott az Oktávnál!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Tovább</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Mégse</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Úgy tűnik, először használja az Oktáv grafikus felhasználói felületét ezen az eszközén.\nKattintson a „Tovább” gombra a beállítási fájl létrehozásához és az Oktáv elindításához.&lt;/p&gt;\n&lt;p&gt;A beállítási fájl a található a következő címen:&lt;br&gt;%1&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Vezérlő rögzítésének feloldása</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Vezérlő bezárása</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Profilkészítő</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Oktáv</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>Biztosan kilép az Oktávból?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Munkaterület mentése másként</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Munkaterület megnyitása</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>Az Oktáv névjegye</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Könyvtárak tallózása</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Oktáv-fájlok (*.m);;Minden fájl (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Új függvény</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Új függvénynév:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>A(z) %1 egy beépített, lefordított vagy soron belüli\nfüggvény, és nem szerkeszthető.</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>Nem található a(z) %1 függvény</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Oktáv-szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Fájl</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Megnyitás…</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Meglévő fájl megnyitása a szerkesztőben</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Munkaterület megnyitása…</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Munkaterület mentése másként…</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Kilépés</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Új</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Új parancsfájl</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Új függvény…</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Új ábra</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>S&amp;zerkesztés</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Visszavonás</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Másolás</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Beillesztés</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Összes kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Vágólap kiürítése</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Fájlok keresése…</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Parancsablak kiürítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Parancselőzmények kiürítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Munkaterület kiürítése</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Elérési útvonal beállítása…</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Beállítások…</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>&amp;Hibakeresés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Lépés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Előrelépés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Visszalépés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Folytatás</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Hibakeresési mód kilépése</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>&amp;Eszközök</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>&amp;Profilkészítő munkamenet indítása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>Profilkészítő munkamenet &amp;folytatása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>Profilkészítő munkamenet &amp;leállítása</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>Profiladatok &amp;megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>&amp;Ablak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Parancsablak megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Parancselőzmények megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Fájltallózó megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Munkaterület megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Szerkesztő megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Dokumentáció megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Változószerkesztő megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Parancsablak</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Parancselőzmények</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Fájltallózó</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Munkaterület</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Dokumentáció</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Változószerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Előző vezérlő</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Alapértelmezett ablakelrendezés visszaállítása</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Súgó</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Hibabejelentés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Oktáv-csomagok</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>Vegyen részt</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Oktáv adományozása</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>Kapcsolat nélküli</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>Kapcsolatban van</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Hírek</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Kiadási megjegyzések</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Közösségi hírek</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Eszköztár</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Könyvtárnév megadása</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Jelenlegi könyvtár: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Egy könyvtárral feljebb</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nÚgy tűnik, hogy az Oktáv közösségi hírforrása nem érhető el.\n&lt;/p&gt;\n&lt;p&gt;\nA legfrissebb hírekért ellenőrizze\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\namikor csatlakozik az internethez (a hivatkozás külső böngészőben nyílik meg).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Az Oktáv fejlesztők, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nA legfrissebb Oktáv-közösségi hírek megjelenítéséhez való internetkapcsolat letiltásra került.\n&lt;/p&gt;\n&lt;p&gt;\nA legfrissebb hírekért kérjük, látogasson el a\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\noldalra, ha van kapcsolata a weben (a hivatkozás külső böngészőben nyílik meg),\nvagy engedélyezze a webkapcsolatokat a hírekhez az Oktáv hálózati beállítások lapján.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Az Oktáv fejlesztői, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Vezérlő elrejtése</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Vezérlő rögzítése</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Vezérlő rögzítésének feloldása</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>Segítség keresése a következőhöz:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>Dokumentáció keresése a következőhöz:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>Szerkesztés</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop ha…</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Oktáv-szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>Nem sikerült az ideiglenes fájlok létrehozása.\nGyőződjön meg arról, hogy rendelkezik írási jogosultsággal a(z) %1 ideiglenes könyvtárhoz.\n\nA „Kijelölés futtatása” ideiglenes fájlokat igényel.</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>Cserélése a(z) „%2” elem minden olyan előfordulását a(z) „%3” elemmel, a(z) „%1” gomb megnyomással.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>Alapértelmezett</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Létrehozás</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>Mégse</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Fájl\n%1\nnem létezik. Szeretné létrehozni?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Oktáv-szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>A(z) %1 fájl nem létezik a betöltési elérési úton. A szerkesztett függvény futtatásához vagy hibakereséséhez vagy át kell váltania a(z) %2 könyvtárba, vagy hozzá kell adnia a könyvtárat a betöltési útvonalhoz.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>A(z) %1 fájlt a betöltési útvonal azonos nevű fájlja árnyékolja. A szerkesztett függvény futtatásához vagy hibakereséséhez váltson a(z) %2 könyvtárba.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Könyvtár módosítása vagy könyvtár hozzáadása a betöltési útvonalhoz</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>Könyvtár &amp;módosítása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>Könyvtár &amp;hozzáadása a betöltési útvonalhoz</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>A kiadási megjegyzések fájlja „%1” üres.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>A kiadási megjegyzések fájlja „%1” nem olvasható.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Oktáv kiadási megjegyzések</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Elérési útvonal beállítása</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Összes módosítás azonnal érvénybe lép.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Könyvtár hozzáadása…</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Egyetlen könyvtár</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Könyvtár alkönyvtárakkal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>Áthelyezés felülre</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>Áthelyezés alulra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Áthelyezés felfelé</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Áthelyezés lefelé</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Eltávolítás</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Újratöltés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Mentés</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Visszaállítás</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Utolsó módosítás visszaállítása</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Minden módosítás visszaállítása</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Könyvtár megnyitása</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>Fel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>Le</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>Balra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>Jobbra</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Előtér</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Háttér</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Kijelölés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>Jelölő</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Kijelölt előtér</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Kijelölt háttér</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Változó háttér</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>Argumentum</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>Globális</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>tartós</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Környezeti változók</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>Második színmód (világos/sötét)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>Váltson egy második színkészletre.\nHasznos a világos/sötét módok meghatározásához.\nElveti a nem alkalmazott jelenlegi változtatásokat!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>Alapértelmezett színek újratöltése,\na jelenleg kijelölt módtól függ.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>Alapértelmezett stílusértékek újratöltése,\na jelenleg kijelölt módtól függ.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>Alapértelmezett színek új&amp;ratöltése</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>Alapértelmezett stílusok új&amp;ratöltése</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Jelenlegi beállítások betöltése … </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Rendszerbeállítás</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>IBeam-jelölő</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>Blokkjelölő</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>Aláhúzott jelölő</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>A kiemelt jelenlegi vonal színe (bíbor (255,0,255) az automatikus színhez)</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Oktáv indítási könyvtár beállítása</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Fájltallózó indítási könyvtár beállítása</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Beállítások alkalmazása folyamatban van…</translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>Nem sikerült megnyitni a(z) „%1” fájlt Oktáv gyorsítóparancsfájlként</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Attribútum színeinek engedélyezése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Eszköztippek elrejtése</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Gyorsítóparancsok importálása fájlból…</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Oktáv-gyorsítóparancsfájlok (*.osc);;Minden fájl (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Gyorsítóparancsok exportálása fájlba…</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Gyorsítóparancsok felülírása</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Az összes gyorsítóparancsok felülírása kerül.\nMenteni szeretné a jelenlegi gyorsítóparancs-készletet, vagy törölni szeretné a műveletet?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>Ne mentse</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Az Oktáv grafikus felhasználói felület beállításai</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Közösségi hírek</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Előző</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Tovább</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Mégse</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Amikor az Oktáv elkezdődik, opcionálisan ellenőrzi az oktáv honlapot, hogy megtalálja-e az Oktáv közösséggel kapcsolatos jelenlegi híreket és információkat.\nNaponta legfeljebb egyszer jelentkezik be, és a hírek csak akkor jelennek meg, ha valami új történt a legutóbbi hírnézés óta.&lt;/p&gt;\n&lt;p&gt; A híreket megtekintheti a „Közösségi hírek” kiválasztásával a „Súgó” menüben vagy a(z)\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt; címen.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Lehetővé teszi, hogy az Oktív az induláskor csatlakozzon az Oktív-weboldalhoz, hogy megjelenjen az Oktív-közösséggel kapcsolatos jelenlegi hírek és információk.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Új gyorsítóparancs megadása</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Egyéni gyorsítóparancs megadása\nMűvelet: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Billentyűparancs megadása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Shift módosító hozzáadása\n(lehetővé teszi a számbillentyűk beírását)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Jelenlegi gyorsítóparancs</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Alapértelmezett gyorsítóparancs</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Kiürítés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Alapértelmezettre beállítása</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Kettős gyorsítóparancs</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>A kijelölt gyorsítóparancs\n   „%1”\nmár használatban van a művelethez\n   „%2”.\nSzeretné használni a gyorsítóparancsot, és eltávolítani az előző műveletből?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Globális</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Fájl menü</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Szerkesztés menü</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Hibakeresés menü</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Eszközök menü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Ablak menü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Súgó menü</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Hírek menü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Vezérlők rögzítésének kezelése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Vezérlők rögzítésének lapkezelése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Keresés és csere a vezérlők rögzítésieben</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Szerkesztő és dokumentáció nagyítása</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Nézet menü</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Futtatás menü</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Dokumentációmegjelenítő</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Tallózó</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>%1 elem nem található a parancsbeállítások párbeszédpanelen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Isten hozott a GNU Oktávnál</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Isten hozott az Oktávnál!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Parancsablak</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Vezérlő rögzítése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Változószerkesztő: </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Vezérlő rögzítésének feloldása</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Geometria visszaállítása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Ismételt rögzítés</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Változószerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Változók szerkesztése.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Változószerkesztő eszköztár</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Mentés</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Változó mentése fájlba</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Exportálás másként…</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Változó exportálása különböző formátumú fájlba</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Kivágás</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Adatok kivágása a vágólapra</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Másolás</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Adatok másolása a vágólapra</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Beillesztés</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Beillesztés a vágólapot a változó adatokba</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Ábrázolás</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Kijelölt adatok ábrázolása</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Kijelölt adatok ábrázolása</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Felfelé</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>Egy szinttel feljebb lépése a változó hierarchiában</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>„%1” változó mentése másként</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Kivágás</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Másolás</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Beillesztés</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Kiürítés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Törlés</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Változó a kijelölésből</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Transzponálás</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> oszlop</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> oszlop</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> sor</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> sor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Isten hozott a GNU Oktávnál!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>Név</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Osztály</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Méret</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Érték</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Tulajdonság</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Másolás, átnevezés vagy megjelenítés érdekében kattintson jobb gombbal</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>összetett</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Osztály</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Méret</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Érték</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Tulajdonság</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Munkaterület</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Változók megtekintése a jelenlegi munkaterületen.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Szöveg megadása a munkaterület szűréséhez</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Szűrő</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Változók megtekintése a jelenlegi munkaterületen.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Változóattribútumok színei:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Változószerkesztő megnyitása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Név másolása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Érték másolása</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Átnevezés</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Csak a legfelső szintű szimbólumok átnevezhető</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Szűrő elrejtése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Szűrő megjelenítése</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>Nem sikerült megnyitni az fd = %1 adatfolyam átirányítását.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>Nem sikerült letiltani az fd = %1 adatfolyam pufferolását.</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>Nem sikerült másolni az fd = %1 adatfolyam átirányítását.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>Nem sikerült létrehozni az átirányítási csövet az fd = %1 adatfolyamhoz:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>Nem sikerült másolni az átirányított fd = %1 adatfolyamot az fd = %2 csőhöz: %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Hiba történt az átirányított adatfolyamok hallgatása közben</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation>Hiba történt az átirányított fd = %1 adatfolyam olvasása közben.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\nKimenet átirányítás: </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> nem fog működni.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\nHiba: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Oktáv</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Általános</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Kizárólag oktáv embléma</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Betű ikonok</translation>\n    </message>\n    <message>\n        <location line=\"-334\"/>\n        <source>Dock widget title bar</source>\n        <translation>Vezérlő rögzítőcímsora</translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation>Kicsi</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Nagy</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>Egyéni stílus</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation>Térhatás</translation>\n    </message>\n    <message>\n        <location line=\"+565\"/>\n        <source>Editor</source>\n        <translation>Szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Ez jól működik rögzített szélességű betűkészleteknél. A vonalat az alapértelmezett betűkészlet szóköz karaktereinek szélessége alapján kell megrajzolni. Előfordulhat, hogy nem működik jól, ha a stílusok arányos betűkészleteket használnak, vagy ha különböző betűméreteket vagy vastag, dőlt és normál szövegeket használnak.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Kódrészletek bezárásai engedélyezése</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CR LF karakterpár)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation>Örökölt Mac (CR karakter)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF karakter)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Vízszintes görgetősáv megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"-516\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ha be van állítva, a főablakhoz rögzített vezérlők fókusza az egérkurzort követi. Ennek célja ugyanaz a viselkedés a főablakon belül, amikor az asztali környezetben a „Fókusz követi az egeret” funkciót használjuk.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>Fókusz követi az egeret a vezérlők rögzítve a főablakba</translation>\n    </message>\n    <message>\n        <location line=\"+494\"/>\n        <source>Show tool bar</source>\n        <translation>Eszköztár megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+221\"/>\n        <source>Rotated tabs</source>\n        <translation>Elforgatott lapok</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Szövegbeosztás</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>A tabulátor legfeljebb szélessége karakterekben (0: korlátlan)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A tabulátor legfeljebb szélessége karakterekben (átlagos karakterszélesség). Különösen hasznos elforgatott lapok esetén.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+260\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Tekerjen hosszú sorokat a jelenlegi ablak határán</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Indentation</source>\n        <translation>Behúzás</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation>Behúzás szélessége</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Tabulátor behúzási segédvonala</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Automatikus behúzás</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Tabulátor szélessége</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Behúzási segédvonalainak megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Visszatörlés (backspace) eltávolítja a sor behúzását</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Behúzás tabulátorokat használ</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation>Automatikus kiegészítés</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>Kulcsszavak egyeztetése</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Kis- és nagybetűk megkülönböztetése</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Helyettesítse a szót a javasolt szöveggel</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Párosítsa a szavakat a dokumentumban</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation>Oktáv beépített elemekkel</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Oktáv függvényekkel</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Befejezési lista automatikus megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>A külsőleg módosított fájlok újratöltése felszólítás nélkül</translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation>Egyéni fájlszerkesztő használata</translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Betöltéshez és mentéshez használt szövegkódolás</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation>Szerkesztő stílusai</translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(A puffer méretének megváltoztatása törli az előzményeket)</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation>Előzménypuffer mérete</translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Betűkészlet</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Sorok számának megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"-866\"/>\n        <source>Interface</source>\n        <translation>Felület</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Megerősít kilépés előtt</translation>\n    </message>\n    <message>\n        <location line=\"-72\"/>\n        <source>Graphic icons</source>\n        <translation>Képikonok</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Állapotsor megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Tétlen szöveg</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Működő</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Background inactive</source>\n        <translation>Tétlen háttér</translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation>Oktáv indítás</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Tallózás</translation>\n    </message>\n    <message>\n        <location line=\"-1305\"/>\n        <source>Show whitespace</source>\n        <translation>Elválasztó karakterek megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Ne jelenjen meg elválasztó karakterek használt behúzáshoz</translation>\n    </message>\n    <message>\n        <location line=\"+1125\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Hozzon létre nem létező fájlokat kérés nélkül</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>Parancssor (%f=fájl, %l=sor):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Jelölőtípus:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Előtér színe használata</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Betűméret</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Fájltallózó</translation>\n    </message>\n    <message>\n        <location line=\"-2031\"/>\n        <source>Normal</source>\n        <translation>Normál</translation>\n    </message>\n    <message>\n        <location line=\"+359\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Ezeket a beállításokat minden .octaverc indítási fájl után alkalmazza.</translation>\n    </message>\n    <message>\n        <location line=\"+540\"/>\n        <source>Show EOL characters</source>\n        <translation>Sorvég (EOL) karakterek megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation>Alapértelmezett sorvég (EOL) üzemmód</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Karakterek száma a lista megjelenítése előtt: </translation>\n    </message>\n    <message>\n        <location line=\"-1812\"/>\n        <source>Preferences</source>\n        <translation>Beállítások</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(újraindítás szükséges)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Rendszer fájl párbeszédpanelek használata</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Eszköztár ikonok</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Nyelv</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Vezérlő rögzítésének ablakikonok</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Stílus</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Ikon téma (újraindítás szükséges)</translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation>Villogó jelölő</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Indításkor kezdőkép megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Oktáv-tolmács kezdeti munkakönyvtára</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Előző munkamenet utolsó munkakönyvtárának visszaállítása</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Parancs</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Fókusz beállítása a parancsablakhoz, amikor parancs futtatása egy másik vezérlőből</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Hibakeresési hely kinyomtatása a parancsablakban a szerkesztőben lévő jelölő mellett</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Parancsablakok színei</translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>A szám mérete a szerkesztő betűtípusától való eltérés</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Jelenlegi sor kiemelése (a szín alul állítható szerkesztőstílusokkal)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Dupla kattintással jelölje ki a szó összes előfordulását</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Lapok</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Lapok elforgatása: Függőleges, ha felül vagy alul van, és vízszintes, ha balra vagy jobbra van. A bezárás gomb nem jelenik meg az elforgatott lapokon.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Megjegyzések (Oktáv)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>A megjegyzés nélküli szöveg karakterláncai</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>A kiválasztott szöveg megjegyzéséhez használt karakterlánc</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Sorhosszúság</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Sor hasítása sorhosszon</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Sor hasítása csak megjegyzésekben</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Sorhossz</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Hosszú vonal jelölő</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Sor</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Háttér</translation>\n    </message>\n    <message>\n        <location line=\"+191\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Automatikus beszúrás az „if” (ha) után stb.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Semmi</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>„endif” (végeha) stb.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>„end” (vége)</translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation>Hibakeresés</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Mindig jelenítse meg a hibakeresési töréspontokat és mutatókat (bezárva megnyitja a kapcsolódó fájlt)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Fájlkezelés</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>A szerkesztő lapok visszaállítása az előző munkamenetből indításkor, vagy amikor a szerkesztő újra megjelenik a bezárás után</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Minden fájl bezárása, amikor a szerkesztővezérlő bezárásakor/elrejtésekor</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>Újsor kényszerítése a végére a fájl mentésekor</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>A fájl mentésekor távolítsa el a záró szóközöket</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>A megnyitott fájl párbeszédablak könyvtára a jelenlegi szerkesztőfájlt követi a jelenlegi Oktáv könyvtár helyett </translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Betűkészlet, betűméret (eltérés az alapértelmezett mérettől), betűstílus kijelölése (&lt;b&gt;f&lt;/b&gt;élkövér, &lt;b&gt;d&lt;/b&gt;őlt, &lt;b&gt;a&lt;/b&gt;láhúzott), szövegszín, and háttérszín (utóbbi esetében a bíbor szín (255,0,255) az alapértelmezett háttérszín helyőrzője).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Behavior</source>\n        <translation>Viselkedés</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Előző munkamenet utolsó könyvtárának visszaállítása</translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Alapértelmezett szövegszerkesztőben megnyitandó fájlkiterjesztések („;” elválasztva):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Munkaterület</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Változóattribútumok színei</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Parancsablak betűkészlet használata</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Gyorsítóparancskészlet importálása</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Jelenlegi gyorsítóparancskészlet exportálása</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Gyorsítóparancsok visszaállása az alapértelmezett értékekre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Alapértelmezett</translation>\n    </message>\n    <message>\n        <location line=\"+232\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Rendben&lt;/span&gt; - párbeszédpanel bezárása és a beállítások alkalmazása&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Alkalmazás - &lt;/span&gt;beállítások alkalmazása és a párbeszédpanel nyitva hagyása&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Mégse&lt;/span&gt; - párbeszédpanel bezárása és a még nem alkalmazott módosítások elvetése&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Visszaállítás&lt;/span&gt; - beállítások újratöltése a még nem alkalmazott módosítások elvetése&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-227\"/>\n        <source>Actual</source>\n        <translation>Tényleges</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Hálózat</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Engedélyezze az Oktávnak, hogy csatlakozzon az Oktáv honlaphoz, hogy megjelenítse a jelenlegi híreket és információkat</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Proxykiszolgáló</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Válassza ki &lt;span style=&quot; font-style:italic;&quot;&gt;HTTP-proxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; vagy &lt;span style=&quot; font-style:italic;&quot;&gt;Környezeti változók&lt;/span&gt;. Az utolsó kiválasztással a proxy az első nem üres környezeti változóból (ALL_PROXY, HTTP_PROXY vagy HTTPS_PROXY) kerül átvételre.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Proxykiszolgáló használata</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Változószerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Alapértelmezett sormagasság</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Alapértelmezett oszlopszélesség</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Változószerkesztő színek</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Változó sorszínek használata</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Globális billentyűparancsok letiltása a\nReadLine billentyűleütésekkel való zavar elkerülése érdekében.\nKivételek: Ctrl-C az értelmező megszakítására és a\nbillentyűparancsok más vezérlőkre való váltásra.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Globális gyorsítóparancsok letiltása, ha a Parancsablak fókuszba kerül</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Oktáv munkakönyvtár összehangolása a fájltallózóval</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>Kezdeti fájltallózókönyvtár (csak ha nincs összehangolva az Oktáv kezdeti munkakönyvtárával)</translation>\n    </message>\n    <message>\n        <location line=\"+302\"/>\n        <source>Shortcuts</source>\n        <translation>Gyorsítóparancs</translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Globális billentyűparancsok letiltása a\nReadLine billentyűleütésekkel való zavar elkerülése érdekében.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>A főablak menüinek menügyorsítóinak letiltása, ha a parancsablak fókuszban van</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation>Exportálás</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importálás</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Parancsikon szerkesztése dupla kattintással a Tényleges oszlopban</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Művelet</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Állomásnév:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Proxy típusa:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Kikötő:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Felhasználónév:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Jelszó:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Vezérlő rögzítése/rögzítésének feloldása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Vezérlő bezárása</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Új fájl</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Új függvény</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Új ábra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Fájl megnyitása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Munkaterület megnyitása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Munkaterület mentése másként</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Kilépés az Oktávból</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Másolás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Beillesztés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Visszavonás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Összes kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Vágólap kiürítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>Keresés a fájlokban</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Parancsablak kiürítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Parancselőzmények kiürítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Munkaterület kiürítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Elérési útvonal beállítása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Beállítások</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Lépés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>Előrelépés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Visszalépés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Folytatás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Hibakeresési mód kilépése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Profilkészítő munkamenet indítása/leállítása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Profilkészítő munkamenet folytatása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Profiladatok megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Parancsablak megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Parancselőzmények megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Fájltallózó megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Munkaterület megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Szerkesztő megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Dokumentáció megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Változószerkesztő megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Parancsablak</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Parancselőzmények</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Fájltallózó</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Munkaterület</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Szerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Dokumentáció</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Változószerkesztő</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Előző vezérlő</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Alapértelmezett ablakelrendezés visszaállítása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Lemezen lévő dokumentáció megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Online dokumentáció megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Hibabejelentés</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Oktáv-csomagok</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Oktáv hozzájárulása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Oktáv fejlesztői erőforrások</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>Az Oktáv névjegye</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Kiadási megjegyzések</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Közösségi hírek</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Lap bezárása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Az összes lap bezárása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Más lapok bezárása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Váltás a bal oldali lapra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Váltás a jobb oldali lapra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Lap mozgassa balra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Lap mozgassa jobbra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Nagyítás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Kicsinyítés</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Tényleges méret</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Függvény szerkesztése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Fájl mentése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Fájl mentése másként</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Nyomtatás</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Ismét</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Kivágás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Keresés és csere</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Következő találat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Előző találat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Törlés a szó elejéig</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Törlés a szó végéig</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Törlés a sor elejéig</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Törlés a sor végéig</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Sor törlése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Sor másolása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Sor kivágása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Kijelölés/sor megkettőzése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Sor transzponálása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Befejezési lista megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Megjegyzés hozzáfűzése a kijelölt részhez</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Kijelölt rész megjegyzésének törlése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Megjegyzés hozzáfűzése a kijelölt részhez (karakterlánc kijelölése)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Nagybetűs kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Kisbetűs kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Kijelölés behúzásának növekedése rögzítettként</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Kijelölés behúzásának csökkentése rögzítettként</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Kód behúzása</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Sorvégek átalakítása Windowsra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Sorvégek átalakítása Unix-ra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Sorvégek átalakítása Mac-re</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Ugrás sorra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Ugrás az egyező zárójelre</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Egyező zárójel kijelölése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Könyvjelző kapcsolása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Következő könyvjelző</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Előző könyvjelző</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Összes könyvjelző eltávolítása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Stílusok beállításai</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Sorok számának megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Elválasztó karakterek (szóköz, sortörés vagy tabulátor) megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Sorvégek megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Behúzási segédvonalainak megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Hosszú vonal jelölő megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Eszköztár megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Állapotsor megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Vízszintes görgetősáv megjelenítése</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Lapok rendezése betűrendben</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Töréspont kapcsolása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Következő töréspont</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Előző töréspont</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Összes töréspont eltávolítása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Fájl futtatása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Kijelölés futtatása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Tesztek futtatása</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Bemutatók futtatása</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Kulcsszó súgóban</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Kulcsszó a dokumentációban</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>Ugrás a kezdőlapra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>Vissza egy lappal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>Előre egy lappal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Oldal megjelölése könyvjelzővel</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/it_IT.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"it_IT\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Nome file invalido</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Differenza rispetto alla dimensione di default</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Colore dello sfondo; magenta (255,0,255) indica default</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translatorcomment>&apos;g&apos; is the initial of the translation of &apos;bold&apos;, but usually icons show B, I, and U, so it may be reasonable to just leave the English initials. </translatorcomment>\n        <translation>g</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translatorcomment>See &apos;b&apos;.</translatorcomment>\n        <translation>c</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translatorcomment>See &apos;b&apos;.</translatorcomment>\n        <translation>s</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>Modifica &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Aiuto su &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Documentazione su &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Copia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Incolla</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Seleziona tutto</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Esegui selezione</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>Modifica selezione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>Aiuto sulla selezione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>Documentazione sulla selezione</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Pulisci Finestra</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Modifica %1 alla riga %2</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>selezione copiata negli appunti</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>Default</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Errore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commento</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Numero</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Parola chiave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Stringa con apici doppi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Stringa con apici singoli</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificatore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Scalare</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>Espansione parametro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Apici inversi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Delimitatore di here document</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Here document con apici singoli</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>Default</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commento</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Parola chiave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>Etichetta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>Nascondi carattere comando</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>Comando esterno</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Variabile</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatore</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>Default</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>Default non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>Commento C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>Commento C non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>Commento C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>Commento C++ non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>Commento C in stile JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>Commento C in stile JavaDoc non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Numero</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Numero non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Parola chiave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Parola chiave non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Stringa con apici doppi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>Stringa con apici doppi non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Stringa con apici singoli</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>Stringa con apici singoli non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>IDL UUID non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>Blocco del preprocessore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>Blocco del preprocessore non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Operatore non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificatore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Identificatore non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>Stringa aperta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>Stringa aperta non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>Stringa verbatim C#</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>Stringa verbatim C# non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>Espressione regolare JavaScript</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>Espressione regolare JavaScript non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>Commento C++ in stile JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>Commento C++ non attivo in stile JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>Parole chiave e identificatori secondari</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Parole chiave e identificatori secondari non attivi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>Parola chiave JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>Parola chiave JavaDoc non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>Errore parola chiave JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>Errore parola chiave JavaDoc non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Classi e typedef globali</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Classi e typedef globali non attivi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>Stringa raw C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>Stringa raw C++ non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation>Stringa verbatim a triple virgolette di Vala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation>Stringa verbatim a triple virgolette di Vala non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation>Stringa tra virgolette con hash di Pike</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation>Stringa tra virgolette con hash di Pike non attiva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation>Commento preprocessore C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation>Commento preprocessore C non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation>Commento preprocessore stile JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation>Commento preprocessore stile JavaDoc non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation>Literal definito dall&apos;utente</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation>Literal definito dall&apos;utente non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation>Indicatore di task</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation>Indicatore di task non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation>Sequenza di escape</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation>Sequenza di escape non attiva</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>Default</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commento</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Comando</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>Intestazione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Posizione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Linea Rimossa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Linea aggiunta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Linea modificata</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation>Patch aggiuntiva aggiunta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation>Patch aggiuntiva rimossa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation>Patch di rimozione aggiunta</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation>Patch di rimozione rimossa</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>Default</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commento</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Comando</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Numero</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Parola chiave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Stringa con apici singoli</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificatore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Stringa con apici doppi</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>Default</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Errore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commento</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Numero</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Parola chiave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Stringa con apici doppi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Stringa con apici singoli</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificatore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Scalare</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>Vettore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>Hash</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Tabella dei simboli</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>Espressione regolare</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>Sostituzione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Apici inversi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>Sezione dati</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Delimitatore di here document</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Here document con apici singoli</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>Here document con apici doppi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>Here document con apici inversi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>Stringa con apici (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>Stringa con apici (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>Stringa con apici (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>Stringa con apici (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>Stringa con apici (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>POD verbatim</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>Prototipo subroutine</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>Formatta identificatore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>Formatta corpo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>Stringa con apici doppi (variabile interpolata)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>Traduzione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>Espressione regolare (variabile interpolata)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>Sostituzione (variabile interpolata)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>Apici inversi (variabile interpolata)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>Here document con apici doppi (variabile interpolata)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>Stringa con apici inversi (variabile interpolata)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>Stringa con apici (qq,variabile interpolata)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>Stringa con apici (qx,variabile interpolata)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>Stringa con apici (qr, variabile interpolata)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>&amp;Torna indietro</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Ripeti</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>&amp;Taglia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Copia</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>&amp;Incolla</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Elimina</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Seleziona tutto</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Apri collegamento</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Copia l&apos;indirizzo del collegamento</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Manda un&apos;email a...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>Copia l&apos;indirizzo email</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Modifica %1 alla riga %2</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Annotazione</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Testo</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Stringa</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Carattere</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>grassetto</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translatorcomment>See the comment on &apos;b&apos; in QObject.</translatorcomment>\n        <translation>g</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>corsivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translatorcomment>See the comment on &apos;b&apos; in QObject.</translatorcomment>\n        <translation>c</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>colore</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>sinistra</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>centro</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>destra</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>Allineamento orizzontale</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>Allineamento verticale</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>in alto</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>in basso</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Posizione</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Larghezza</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Altezza</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>unità</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalizzato</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Adatta al riquadro</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Riquadro</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Sfondo</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Bordo</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Stile linea</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>nessuno</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Ampiezza linea</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Seleziona Tutto</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Metti in Pausa</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Interrompi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Continua</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Widget dei Comandi</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Notizie dalla Comunità di Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>Default</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Errore</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>Prompt</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Documentazione di Octave</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>Impossibile copiare la collezione di aiuto in un file temporaneo.\nLe funzionalità di ricerca potrebbero risultarne compromesse.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>Impossibile impostare i dati richiesti per il\nvisualizzatore della documentazione. Forse manca il modulo\nQt SQlite?\nSarà disponibile solo il testo di aiuto\nnella Finestra dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>Contenuti</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Inserisci il testo da cercare nell&apos;indice delle funzioni</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Cerca</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>Indice Funzioni</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Segnalibri</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>Vai all&apos;inizio</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Vai indietro</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Pagine precedenti</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>Vai avanti</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Pagine successive</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Trova</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Ingrandisci</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Riduci</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Dimensione Normale</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>Aggiungi segnalibro alla pagina corrente</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>Impossibile registrare il file di aiuto %1.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nNessun segnalibro della documentazione caricato!</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: Caricamento dei Segnalibri della Documentazione in Corso </translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Inserisci testo da cercare nei segnalibri</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Filtra</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Nuova Cartella</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Apri</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Rinomina</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>&amp;Elimina</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>Aggiungi &amp;Cartella</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>&amp;Nascondi Filtro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>&amp;Mostra Filtro</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: Salvataggio dei Segnalibri della Documentazione in Corso</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>Impossible scrivere il file %1:\n%2.\n\nI segnalibri della documentazione non sono salvati!</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>Impossibile leggere il file %1:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>Nessun elemento di inizio trovato in %1.\nFile dei segnalibri invalido?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>Il file\n%1\nnon è una versione 1.0 di file XBEL</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Titolo sconosciuto</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Documentazione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Vedi la documentazione per maggiori informazioni.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Chiudi</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>Chiudi &amp;Tutto</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>Chiudi &amp;Altro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>Vai al Widget di &amp;Sinistra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>Vai al Widget di &amp;Destra</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation>Apri Editor File</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation>Clicca per selezionare un file nell&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Chiudi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>Chiudi &amp;Tutto</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Esegui</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Imposta la &amp;Cartella Corrente</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Editor di Octave</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>Impossibile avviare l&apos;editor di file personalizzato\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Non è sato ancora configurato nessun editor personalizzato.\nSi desidera aprire le preferenze?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Continua</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Salva il File ed Esegui</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Editor di Octave</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>File non salvato! Un file con il nome selezionato\n%1\nrisulta già aperto nell&apos;editor.</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>La scheda corrispondente nell&apos;editor è scomparsa.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>Impossibile aprire il file\n%1\nin lettura: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Il file\n%1\nnon esiste. Vuoi crearlo?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Crea</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annulla</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>Impossibile aprire il file\n%1\nin scrittura: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;File</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>&amp;Documenti Recenti</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>&amp;Modifica Function</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>&amp;Salva File</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>S&amp;alva Con Nome...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Chiudi</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Chiudi Tutto</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Chiudi gli Altri File</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Stampa...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Modifica</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Ripeti</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>&amp;Taglia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>&amp;Trova e Sostituisci...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>Trova &amp;Successivo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>Trova &amp;Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>&amp;Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Elimina Riga</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Copia Riga</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Taglia riga</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Cancella fino a Inizio Parola</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Cancella fino a Fine Parola</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Cancella fino a Inizio Riga</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Cancella fino a Fine Riga</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Duplica Selezione/Riga</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Trasponi Riga</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>Mostra &amp;Lista di Completamento</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Formattazione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>Rendi &amp;Maiuscola la Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>Rendi Mi&amp;nuscola la Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>&amp;Commenta</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>&amp;Decommenta</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Commenta (Scegliendo la Stringa)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>&amp;Indenta Rigidamente la Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>D&amp;eindenta Rigidamente la Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Indenta il Codice</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Converti gli A Capo in Formato &amp;Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Converti gli A Capo in Formato &amp;Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Converti gli A Capo in Formato Legacy &amp;Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>Navi&amp;gazione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>Vai &amp;alla Riga...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Vai alla Parentesi Corrispondente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Seleziona fino alla Parentesi Corrispondente</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>Segnalibro &amp;Successivo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>Segnalibro &amp;Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>Attiva/&amp;disattiva Segnalibro</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>&amp;Rimuovi Tutti i Segnalibri</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Preferenze...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>P&amp;referenze di Stile...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>&amp;Vista</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>&amp;Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>Mostra &amp;Numeri di Riga</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>Mostra Spazi &amp;Bianchi</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Mostra Fine &amp;Righe</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>Mostra Guide di &amp;Indentazione</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>Mostra &amp;Marcatori di Riga Lunga</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>Mostra Barra degli S&amp;trumenti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>Mostra Barra di &amp;Stato</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>Mostra Barra di Scorrimento &amp;Orizzontale</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>&amp;Ingrandisci</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>&amp;Riduci</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>Dimensione &amp;Normale</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>&amp;Schede in Ordine Alfabetico</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Debug</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>Attiva/disattiva &amp;Breakpoint</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>Breakpoint &amp;Successivo</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>Breakpoint &amp;Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>&amp;Rimuovi Tutti i Breakpoint</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>Ese&amp;gui</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Salva il File ed Esegui/Continua</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>Esegui la &amp;Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Salva File ed Esegui Tutto</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Salva File ed Esegui Tutto</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Aiuto</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>&amp;Aiuto sulla Parola Chiave</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>&amp;Documentazione sulla Parola Chiave</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>File Recenti</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Copia l&apos;Intero Percorso del File</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>riga:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>col:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>codifica:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>fine riga:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Condizione di breakpoint</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>ERRORE: </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Editor di Octave</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>Impossibile aggiungere breakpoint ad un file modificato o senza nome.\nSalvare e aggiungere un breakpoint o annullare?</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Vai alla riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Numero riga</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Commenta testo selezionato</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Stringa commento da utilizzare:</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;senza nome&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>Vuoi annullare la chiusura, tralasciare le modifiche\n        o salvarle?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>Il file\n\n  %1\n\nsta per essere chiuso ma è stato modificato.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>Impossibile leggere il file &apos;%1&apos;\ncon la codifica selezionata &apos;%2&apos;: %3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>Si sono riscontrati problemi nel leggere il file\n%1\ncon la codifica selezionata %2.\n\nModicare e salvare il file potrebbe causare perdita di dati!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>&amp;Modifica comunque</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>Cam&amp;bia codifica</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Chiudi</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Seleziona nuova codifica di default</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Seleziona una nuova codifica\nper ricaricare il file corrente.\n\nQuesto non cambierà la codifica di default.</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Debug o Salvataggio</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Questo file è in esecuzione.\nUscire dal debug e salvare?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>Impossibile aprire il fiel %1 in scrittura:\n%2. </translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>Le modifiche non possono essere salvate nel file\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>File di Octave (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Tutti i File (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>&quot;%1&quot;\nnon è un identificatore valido.\n\nSe mantieni questo nome del file, non sarai in grado di\nchiamare lo script usando il suo nome come comando Octave.\n\nVuoi scegliere un altro nome?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>I contenuti dell&apos;editor corrente non possono essere\ncodificati con la codifica selezionata %1.\nIl suo utilizzo comporterebbe perdita di dati!\n\nSelezionane un&apos;altra!</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1\nesiste già\nVuoi sovrascriverlo?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nAttenzione: il contenuto nell&apos;editor è modificato!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>Sembra che &apos;%1&apos; sia stato modificato da un&apos;altra applicazione. Si desidera ricaricarlo?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>Sembra che il file\n%1\nsia stato rinominato o rimosso. Si desidera salvarlo ora?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Dimensione file</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Tipo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Data ultima modifica</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Mostra file nascosti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Colori alternati per riga</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Inserisci percorso o nome del file</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Livello superiore</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Mostra la cartella di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Vai alla cartella corrente di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Imposta la cartella di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Imposta la cartella corrente come cartella di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Azioni sulla cartella corrente</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Mostra Cartella Personale</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Imposta Cartella del Gestore di File...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Trova File...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Nuovo File...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Nuova Cartella...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Doppio click per aprire il file/cartella, o click destro per le alternative.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Rinomina...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Apri</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Apri nel Gestore di File di Sistema</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Apri nell&apos;Editor di Testo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Copia Selezione negli Appunti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Esegui</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Carica Dati</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Imposta la cartella corrente</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Aggiungi al Percorso</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Cartelle Selezionate</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Cartelle e Sottocartelle Selezionate</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Rimuovi dal Percorso</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Elimina...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Elimina file/cartella</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>Sei sicuro di voler eliminare tutti i %1 file selezionati?</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>Sei sicuro di voler eliminare\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>Impossibile eliminare una cartella non vuota</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Errore durante l&apos;eliminazione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>Impossibile eliminare il file &quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Imposta la cartella del gestore di file</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Crea File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Crea file in\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Nuovo File.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Errore durante la creazione del file</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>Impossibile creare il file\n&quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Crea Cartella</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Crea cartella in\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Nuova Cartella</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>Impossibile rinominare il file &quot;%1&quot; in &quot;%2&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Gestore dei File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Gestisci file</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>Sistema di Gestione dei File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>Editor dei File</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>Buon lavoro!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Concludi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annulla</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>\n&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Speriamo che Octave sia una valido strumento per te.&lt;/p&gt;\n&lt;p&gt;Se incontri dei problemi, ci sono vari modi per avere aiuto, incluse opzioni di supporto commerciale, una tavola di discussione, un wiki, e altri canali di supporto da parte della comunità.\nPuoi trovare maggiori informazioni su ognuna di queste possibilità visitando &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (si apre in un browser esterno).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Per maggiori informazioni su Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visita &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (si apre in un browser esterno)&lt;/li&gt;\n&lt;li&gt;Ottieni la documentazione online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; o &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; formato (i link si aprono in un browser esterno)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Editor: Trova e Sostituisci</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Trova:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Inserisci testo da cercare</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>So&amp;stituisci</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>Inserisci testo da sostituire</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>Maiuscole/&amp;minuscole</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>Cerca dall&apos;i&amp;nizio</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>&amp;Vai a capo durante la ricerca</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>Trova &amp;Successivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>Trova &amp;Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>&amp;Sostituisci</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>S&amp;ostituisci Tutti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>&amp;Avanzate...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>Paro&amp;le intere</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>&amp;Espressioni regolari</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>Cerca &amp;indietro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>Cerca nella sele&amp;zione</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Cerca dalla fine</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Cerca dall&apos;inizio</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Sostituisci Risultato</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 occorrenze sostituite</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Trova Risultato</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>Nessun&apos;altra corrispondenza trovata</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Trova File</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Nome del file:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>Comincia da:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Inserisci la cartella di partenza</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Esplora...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Seleziona la cartella di partenza</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Cartella Corrente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>Imposta la cartella corrente come cartella iniziale</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Ricerca nelle sottocartelle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Cerca ricorsivamente file corrispondenti nelle cartelle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Includi nomi di cartelle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Includi cartelle corrispondenti nei risultati di ricerca</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Ignora maiuscole/minuscole</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>Cerca corrispondenza ignorando maiuscole/minuscole</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>Contiene il testo:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>Includi solo file contenenti il testo specificato nei risultati della ricerca</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Testo da trovare</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Risultato: Doppio click apre il file o imposta la cartella</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Risultati della ricerca</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>Non Attivo.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Inserisci il pattern di ricerca dei nomi dei file.\nPattern differenti possono essere\nseparati da &apos;;&apos;, per esempio &apos;*.cc ; *.h&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>Trova</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Inizia la ricerca dei file corrispondenti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Interrompi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Interrompi ricerca</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>Nome file/Posizione</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Contenuti</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>Ricerca in corso...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 corrispondenza(e)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Imposta la cartella di ricerca</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Nome del file</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Cartella</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Doppio click per aprire il file</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Doppio click per impostare la cartella</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Trova:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>Cerca avanti</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Cerca indietro</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Chiudi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Chiudi il dialogo di ricerca</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Errore %1 nella creazione del file delle impostazioni\n%2\nAssicurati di avere i permessi di lettura e scrittura per\n%3\n\nL&apos;interfaccia grafica di Octave ora verrà chiusa.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Errore Critico di Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Sfoglia e cerca nella cronologia dei comandi.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Copia</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Valuta</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Crea script</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Nascondi filtro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Mostra filtro</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Fai doppio click su un comando per trasferirlo alla Finestra dei Comandi.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Inserisci del testo per filtrare la cronologia dei comandi</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Filtra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Cronologia dei Comandi</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Benvenuto in Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Successivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annulla</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Sembra che si stia utilizzando l&apos;interfaccia grafica di Octave per la prima volta su questo computer.\nFare click su &apos;Successivo&apos; per creare un file di configurazione e lanciare Octave.&lt;/p&gt;\n&lt;p&gt;Il file di configurazione verrà salvato in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Libera Widget</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Chiudi Widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>Sei sicuro di voler uscire da Octave?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Salva lo Spazio di Lavoro con Nome</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Carica Spazio di Lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>A proposito di Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Sfoglia cartelle</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>File di Octave (*.m);;Tutti i File (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Nuova Function</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Nome della nuova function:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>%1 è una function interna, compilata, o inline\ne non può essere modificata.\n</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>Impossibile trovare la function %1</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Editor di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;File</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Apri...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Apri file esistente nell&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Carica Spazio di Lavoro...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Salva Spazio di Lavoro con Nome...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Esci</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Nuovo</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Nuovo script</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Nuova Function...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Nuova Figura</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Modifica</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Torna indietro</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Copia</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Incolla</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Seleziona Tutto</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Pulisci Appunti</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Trova File...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Pulisci Finestra dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Pulisci Cronologia dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Pulisci Spazio di lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Imposta Percorso...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Preferenze...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>De&amp;bug</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Un&apos;istruzione alla volta</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Entra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Esci</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Continua</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Esci dalla Modalità di Debug</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>&amp;Strumenti</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>Inizia Sessione del &amp;Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>&amp;Riprendi Sessione del Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>&amp;Termina Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>Mostra &amp;Dati del Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>Fines&amp;tra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Mostra Finestra dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Mostra Cronologia dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Mostra Gestore dei File</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Mostra Spazio di Lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Mostra &apos;Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Mostra Documentazione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Mostra Editor delle Variabili</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Finestra dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Cronologia dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Gestore dei File</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Spazio di Lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Documentazione</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Editor delle Variabili</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Widget Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Ripristina Layout della Finestra</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Aiuto</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Segnala un Problema</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Pacchetti Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>Lasciati Coinvolgere</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Fai una Donazione a Octave</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>Su Disco</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>Online</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Notizie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Note di Rilascio</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Notizie dalla Comunità</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Barra degli Strumenti</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Inserisci nome cartella</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Cartella Corrente:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Livello superiore</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nLe notizie dalla comunità di Octave non sembrano essere disponibili.\n&lt;/p&gt;\n&lt;p&gt;\nPer le ultime novità, si prega di controllare\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\navendo a disposizione una connesione ad internet (utilizza un browser esterno).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Gli Sviluppatori di Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nLa connesione a internet per mostrare le ultime notizie dalla Comunità di Octave è stata disabilitata\n&lt;/p&gt;\n&lt;p&gt;\nPer le ultime norizie, per favore controlla\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nquando hai una connessione attiva a internet (i link si aprono in un browser esterno)\no abilita le connessione a internet per le notizie nella scheda delle impostazioni di rete di Octave.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Gli Sviluppatori di Octave, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Nascondi Widget</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Àncora Widget</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Libera Widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>Aiuto su</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>Documentazione su</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>Modifica</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop se ...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Editor di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>La creazione dei file temporanei non è riuscita.\nAccertati di avere i permessi di scrittura alla cartella temporanea\n%1\n\n&quot;Lanciare la Selezione&quot; richiede file temporanei.\n        </translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>Premere &apos;%1&apos; per sostituire tutte le occorrenze di &apos;%2&apos; con &apos;%3&apos;.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>Default</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Crea</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>Annulla</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Il file\n%1\nnon esiste. Vuoi crearlo?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Editor di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>Il file %1 non esiste nelle cartelle di esecuzione.  Per lanciare o eseguire il debug della funzione in corso di modifica, è necessario passare alla cartella %2 o aggiungere tale cartella alle cartelle di esecuzione.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>Il file %1 è nascosto da un file con lo stesso nome presente nelle cartelle di esecuzione. Per lanciare o esguire il debug del file in corso di modifica, passare alla directory %2.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Cambia Cartella o Aggiungi Cartella al Percorso di Esecuzione</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>&amp;Cambia Cartella</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>&amp;Aggiungi Cartella al Percorso di Esecuzione</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>Il file delle note di rilascio &apos;%1&apos; è vuoto.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>Impossibile leggere il file delle note di rilascio &apos;%1&apos;.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Note di Rilascio di Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Imposta Percorso</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Tutti i cambiamenti sono immediati.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Aggiungi Cartella...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Cartella Singola</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Cartella con Sottocartelle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>Sposta in Cima</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>Sposta in Fondo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Sposta Su</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Sposta Giù</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Rimuovi</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Ricarica</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Salva</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Ripristina</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Riprista Ultima Modifica</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Ripristina Tutte le Modifiche</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Apri Cartella</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>In alto</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>In basso</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>A sinistra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>A destra</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Primo piano</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Sfondo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>Cursore</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Primo Piano Selezionato</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Sfondo Selezionato</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Sfondo Alternante</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>argomento</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>globale</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>persistente</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Variabili d&apos;Ambiente</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>Seconda modalità colore (chiaro/scuro)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>Cambia in un secondo set di colori.\nUtile per definire le modalità chiaro/scuro.\nAbbandona i cambiamenti non applicati.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>Ricarica i colori di default,\ndipende dalla modalità attualmente selezionata.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>Ricarica i valori di stile di default,\ndipende dalla modalità attualmente selezionata.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>&amp;Ricarica i colori di default</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>&amp;Ricarica gli stili di default</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Caricamento delle preferenze attuali...</translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Impostazioni di sistema</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>Cursore IBeam</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>Cursore Blocco</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>Cursore Testo Sottolineato</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>Colore della riga corrente evidenziata (magenta (255,0,255) come colore automatico)</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Imposta la cartella iniziale di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Imposta la cartella iniziale del gestore di file</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Applicazione delle preferenze...</translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>Impossibile aprire il file %1 come file di scorciatoie di Octave</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Attiva colori attibuti</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Nascondi lo strumento dei suggerimenti</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Importa scorciatoie da file...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>File di scorciatoie di Octave (*.osc);;Tutti i file (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Esporta scorciatoie su file...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Sovrascrittura Scorciatoie</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Stai per sovrascrivere tutte le scorciatoie.\nVorresti salvare le attuali scorciatoie o annullare l&apos;azione?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>Non salvare</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Preferenze dell&apos;intergaccia grafica di Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Notizie dalla Comunità</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Successivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annulla</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;All&apos;avvio, Octave può opzionalmente controllare la pagina web di Octave per ottenere notizie ed informazione recenti dalla comunità..\nQuesto controllo avviene non più di una volta al giorno e le notizie vengono mostrate soltanto se c&apos;è qualcosa di nuovo rispetto all&apos;ultima volta in cui sono state lette.&lt;/p&gt;\n&lt;p&gt;È possibile leggere le notizie anche selezionando &quot;Notizie dalla comunità&quot; dal menu &quot;Aiuto&quot; o visitando\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Permtetti a Octave di connettersi alla pagina web di Octave quando si avvia per mostrare le notizie attuali e le informazioni riguardanti la comunità di Octave.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Inserisci una Nuova Scorciatoia</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Inserisci la scorciatoia personalizzata\nAzione: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Inserisci la scorciatoria digitandola</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Aggiungi modificatore Shift\n(permette di inserire codici numerici)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Scorciatoia Attuale</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Scorciatoia di Default</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Pulisci</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Imposta al valore predefinito</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Doppia Scorciatoia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>La scorciatoria scelta\n  &quot;%1&quot;\nè già in uso per l&apos;azione\n  &quot;%2&quot;.\nVuoi usare la scorciatoria e rimuoverla dall&apos;azione precedente?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Globale</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Menu File</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Menu Modifica</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Menu Debug</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Menu Strumenti</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Menu Finestra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Menu Aiuto</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Menu Notizie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Gestione del Dock Widget</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Gestione Schede in Dock Widget</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Trova e Sostituisci in Dock Widget</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Zoom nell&apos;editor e nella documentazione</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Menu Vista</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Menu Esecuzione</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Visualizzatore Documentazione</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Browser</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>voce %1 non trovata nella finestra di dialogo delle impostazioni delle scorciatoie</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Benvenuto in GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Benvenuto in Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Finestra dei Comandi</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Dock Widget</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Editor di Variabili:</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Libera Widget</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Ripristina geometria</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Riancora</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Editor di Variabili</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Modifica variabili.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Barra degli Strumenti Editor di Variabili</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Salva</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Salva variabile su file</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Salva nel formato...</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Salva la variabile in un file di diverso formato</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Taglia</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Taglia e metti negli appunti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Copia</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Copia negli appunti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Incolla</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Incolla appunti nella variabile</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Traccia grafico</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Grafico Dati Selezionati</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Grafico dati selezionati</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Su</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>Sali un livello nella gerarchia delle variabili</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>Salva Variabile %1 Come</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Taglia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Copia</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Incolla</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Pulisci</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Elimina</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Variabile dalla Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Trasponi</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> colonne</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> colonna</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> righe</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> riga</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Benvenuto in GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>Nome</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valore</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Attributo</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Clicca con il tasto destro per copiare, rinominare o mostrare</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>complesso</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valore</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Attributo</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Spazio di Lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Mostra le variabili nello spazio di lavoro attivo.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Inserisci testo per filtrare l&apos;area di lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Filtra</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Mostra le variabili nello spazio di lavoro attivo.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Colori per gli attributi delle variabili:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Apri nell&apos;Editor delle Variabili</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Copia nome</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Copia valore</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Rinomina</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Si possono rinominare solo i simboli di primo livello</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Nascondi filtro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Mostra filtro</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>Impossibile aprire lo stream reindirizzato con fd = %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>Impossibile disabilitare il caricamento dello stream con fd = %1</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>Impossibile duplicare lo stream reindirizzato con dup e fd = %1</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>Impossibile creare il pipe per reindirizzare lo stream con fd = %1:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>Impossibile duplicare lo stream reindirizzato con fd = %1\nnel pipe con fd = %2: %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Errore durante l&apos;ascolto degli stream reindirizzati</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation>Errore di lettura dal flusso reindirizzato fd = %1</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>Redirezione dell&apos;output in</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation>non funzionerà.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>Errore: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Generale</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Logo di Octave solamente</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Icone testuali</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Graphic icons</source>\n        <translation>Icone grafiche</translation>\n    </message>\n    <message>\n        <location line=\"-341\"/>\n        <source>Dock widget title bar</source>\n        <translation>Barra del titolo degli widget</translation>\n    </message>\n    <message>\n        <location line=\"+413\"/>\n        <source>Confirm before exiting</source>\n        <translation>Chiedi conferma prima di uscire</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Custom style</source>\n        <translation>Stile personalizzato</translation>\n    </message>\n    <message>\n        <location line=\"+199\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Mostra barra di stato</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Testo non attivo</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Attivo</translation>\n    </message>\n    <message>\n        <location line=\"-89\"/>\n        <source>Normal</source>\n        <translation>Normale</translation>\n    </message>\n    <message>\n        <location line=\"+128\"/>\n        <source>Background inactive</source>\n        <translation>Sfondo non attivo</translation>\n    </message>\n    <message>\n        <location line=\"+231\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Queste preferenze vengono applicate dopo tutti i file di avvio .octaverc.</translation>\n    </message>\n    <message>\n        <location line=\"+353\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Questa impostazione è adatta a caratteri monospaced. La linea è posta in una posizione basata sulla larghezza di uno spazio bianco del tipo di carattere predefinito. Può non funzionare bene se gli stili usano caratteri proporzionali o se diverse dimensioni di carattere, grassetto o corsivo sono utilizzati.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Attiva espansione del codice</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation>Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Mostra barra di scorrimento orizzontale</translation>\n    </message>\n    <message>\n        <location line=\"+503\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Spezza righe lunghe al margine della finestra corrente</translation>\n    </message>\n    <message>\n        <location line=\"+55\"/>\n        <source>Indent width</source>\n        <translation>Ampiezza indentazione</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Tab indenta la riga</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Indentazione automatica</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Ampiezza tabulazione</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Mostra guide per l&apos;indentazione</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Backspace rimuove l&apos;indentazione</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Indenta con tabulazioni</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation>Completamento automatico</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>Abbina parole chiave</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Distinzione maiuscole/minuscole</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Sostituisci parola con quella suggerita</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Abbina parole nel documento</translation>\n    </message>\n    <message>\n        <location line=\"-643\"/>\n        <source>Use custom file editor</source>\n        <translation>Utilizza editor personalizzato</translation>\n    </message>\n    <message>\n        <location line=\"+1009\"/>\n        <source>Editor Styles</source>\n        <translation>Stili dell&apos;Editor</translation>\n    </message>\n    <message>\n        <location line=\"-1485\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Carattere</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Mostra numeri di riga</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Show whitespace</source>\n        <translation>Mostra spazi</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Non mostrare gli spazi utilizzati per l&apos;indentazione</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Show EOL characters</source>\n        <translation>Mostra carattere di fine riga</translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation>Modalità di default per i caratteri di fine riga</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Numero di caratteri prima che la lista sia mostrata: </translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Crea file inesistenti senza chiedere conferma</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>linea di comando (%f=file, %l=riga):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Tipo di cursore:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Usa colore di primo piano</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Dimensione carattere</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Gestore dei file</translation>\n    </message>\n    <message>\n        <location line=\"-2118\"/>\n        <source>Interface</source>\n        <translation>Interfaccia</translation>\n    </message>\n    <message>\n        <location line=\"+80\"/>\n        <source>Small</source>\n        <translation>Piccola</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Grande</translation>\n    </message>\n    <message>\n        <location line=\"+137\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation>3D</translation>\n    </message>\n    <message>\n        <location line=\"+206\"/>\n        <source>Octave Startup</source>\n        <translation>Avvio di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Naviga</translation>\n    </message>\n    <message>\n        <location line=\"-1276\"/>\n        <source>Show tool bar</source>\n        <translation>Mostra barra degli strumenti</translation>\n    </message>\n    <message>\n        <location line=\"-951\"/>\n        <source>Preferences</source>\n        <translation>Preferenze</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(richiede riavvio)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Usa selettore file di sistema</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Icone barra degli strumenti</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Lingua</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Icone della finestra di ancoraggio dei widget</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Stile</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Tema delle icone (richiede riavvio)</translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation>Cursore lampeggiante</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Mostra schermata di benvenuto all&apos;avvio</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Cartella iniziale dell&apos;interprete di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Ripristina l&apos;ultima cartella di lavoro della sessione precedente</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Comando</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Seleziona la Finestra dei Comandi quando esegui un comando da un altro widget</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Stampa punto di debug nella Finestra dei Comandi oltre al marker nell&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Colori della Finestra dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Numera dimensione come differenza rispetto al carattere dell&apos;editor</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Evidenzia la riga corrente (il colore è modificabile sotto negli stili dell&apos;editor)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Evidenzia tutte le occorrenze di una parola selezionata con doppio click</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Schede</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ruota schede: verticali quando sopra o sotto e orizzontali quando a sinistra o a destra. Il pulsante di chiusura non è mostrato nelle schede ruotate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Commenti (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Stringhe considerate per decommentare il testo</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Stringa utilizzata per commentare il testo selezionato</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Righe lunghe</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Spezza righe lunghe alla lunghezza di riga</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Spezza righe soltanto nei commenti</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Lunghezza riga</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Marcatore di riga lunga</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Riga</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Sfondo</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>Indentation</source>\n        <translation>Indentazione</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Inserimento automatico dopo &quot;if&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Nulla</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+130\"/>\n        <source>With Octave builtins</source>\n        <translation>Con comandi built-in di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Con funzioni di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Mostra lista di completamento automaticamente</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Debugging</source>\n        <translation>Debug</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Mostra sempre breakpoints di debug e puntatori (apre file corrispondenti se necessario)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Gestione file</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Ricarica file modificati esternamente senza chiedere</translation>\n    </message>\n    <message>\n        <location line=\"-50\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Ripristina schede della sessione precedente all&apos;avvio o quando l&apos;editor è riaperto dopo essere stato chiuso</translation>\n    </message>\n    <message>\n        <location line=\"-31\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Codifica testuale usata per caricare e salvare</translation>\n    </message>\n    <message>\n        <location line=\"+71\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Chiudi tutti i file quando l&apos;editor è chiuso/nascosto</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>Inserisci una nuova riga alla fine quando si salva un file</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>Rimuovi gli spazi finali quando si salva un file</translation>\n    </message>\n    <message>\n        <location line=\"+144\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Seleziona carattere, dimensione carattere (come differenza dispetto alla dimensione predefinita), stile di carattere (&lt;b&gt;g&lt;/b&gt;rassetto, &lt;b&gt;c&lt;/b&gt;orsivo, &lt;b&gt;s&lt;/b&gt;ottolineato), colore del testo, e colore dello sfondo (per quest&apos;ultimo, il colore magenta (255,0,255) indica il colore di default per lo sfondo).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+848\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - chiudi finestra di dialogo e applica le impostazione&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-2254\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Il cambio della dimensione della lista svuota la cronologia)</translation>\n    </message>\n    <message>\n        <location line=\"-260\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Se impostato, il fuoco dei widgets che sono ancorati alla finestra principale segue il cursore del mouse. Ciò è voluto per avere lo stesso comportamento all&apos;interno della finestra principale quando &amp;quot;fuoco segue il mouse&amp;quot; è usata per l&apos;ambiente desktop.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>Il fuoco segue il mouse per gli widget ancorati alla finestra principale</translation>\n    </message>\n    <message>\n        <location line=\"+285\"/>\n        <source>History buffer Size</source>\n        <translation>Dimensione Cronologia</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Rotated tabs</source>\n        <translation>Schede ruotate</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Posizione</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>Ampiezza massima delle schede in caratteri (0: nessun limite)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ampiezza massima di una scheda in caratteri (ampiezza media dei caratteri). Particolarmente utile per schede ruotate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+871\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>Apertura file nella cartella del file corrente nell&apos;editor invece che nella cartella corrente di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+98\"/>\n        <source>Behavior</source>\n        <translation>Comportamento</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Ripristina l&apos;ultima cartella della sessione precedente</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>Cartella iniziale dell&apos;esploratore file (solo se non sincronizzato con la cartella di lavoro di Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Estensioni dei file da aprire nell&apos;editor di testo di default (separate da &quot;;&quot;):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Spazio di lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Colori per gli attributi delle variabili</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Usa carattere della Finestra dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Importa scorciatoie</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Esporta le attuali scorciatoie</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Reimposta le scorciatoie ai valori predefiniti</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Default</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation>Attuale</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Rete</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Permetti all&apos;applicazione di connettersi al sito web di Octave per mostrare notizie ed informazioni aggiornate</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Server Proxy</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Seleziona &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Variabili di Ambiente&lt;/span&gt;. Con l&apos;ultima selezione, il proxy è preso dalla prima variabile di ambiente non vuota ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Usa server proxy</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Editor delle variabili</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Altezza di default riga</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Larghezza di default colonna</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Colori dell&apos;Editor delle Variabli</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Usa colori alternati per le righe</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Disattiva scorciatoie globali per prevenire\ninterferenze con le combinazioni di readline.\nEccezioni: Ctrl-C per interrompere l&apos;interprete\ne le scorciatoie per passare ad altri widgets.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Disattiva scorciatoie globali quando la Finestra dei Comandi è attiva</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Sincronizza la cartella di lavoro di Octave con il gestore dei file</translation>\n    </message>\n    <message>\n        <location line=\"+348\"/>\n        <source>Shortcuts</source>\n        <translation>Scorciatoie</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Export</source>\n        <translation>Esporta</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importa</translation>\n    </message>\n    <message>\n        <location line=\"-44\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Disattiva gli acceleratori di menu per prevenire\ninterferenze con le combinazioni di readline</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>Disattiva gli acceleratori di menu dei menu della finestra principale quando la Finestra dei Comandi è attiva</translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Modifica una scorciatoia facendo doppio click sulla colonna Attuale</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Azione</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Nome host:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Tipo di proxy:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Porta:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Nome utente:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Password:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Libera/Ancora Widget</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Chiudi Widget</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Nuovo File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Nuova Function</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Nuova Digura</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Apri File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Carica Spazio di Lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Salva Spazio di Lavoro con Nome</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Esci da Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Copia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Incolla</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Torna indietro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Seleziona tutto</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Pulisci Appunti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>Trova nei File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Pulisci Finestra dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Pulisci Cronologia dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Pulisci Spazio di Lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Imposta Percorso</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Preferenze</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Un&apos;istruzione alla volta</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>Entra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Esci</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Continua</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Esci dalla Modalità di Debug</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Inizia/Termina Sessione del Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Riprendi Sessione del Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Mostra Dati del Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Mostra Finestra dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Mostra Cronologia dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Mostra Gestore dei File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Mostra Spazio di Lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Mostra Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Mostra Documentazione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Mostra Editor delle Variabili</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Finestra dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Cronologia dei Comandi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Gestore dei File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Spazio di Lavoro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Documentazione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Editor delle Variabili</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Widget Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Ripristina Layout della Finestra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Mostra Documentazione su Disco</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Mostra Ddocumentazione Online</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Segnala un Problema</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Pacchetti Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Contribuisci a Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Risorse per Sviluppatori di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>A proposito di Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Note di Rilascio</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Notizie dalla Comunità</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Chiudi Scheda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Chiudi Tutte le Schede</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Chiudi le Altre Schede</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Vai alla Scheda a Sinistra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Vai alla Scheda a Destra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Sposta Scheda a Sinistra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Sposta Scheda a Destra</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Ingrandisci</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Riduci</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Dimensione Normale</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Modifica Function</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Salva File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Salva File con Nome</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Stampa</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Ripeti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Taglia</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Trova e Sostituisci</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Trova Successivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Trova Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Cancella fino a Inizio Parola</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Cancella fino a Fine Parola</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Cancella fino a Inizio Riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Cancella fino a Fine Riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Elimina Riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Copia Riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Taglia Riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Duplica Selezione/Riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Trasponi Riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Mostra Lista di Completamento</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Commenta Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Decommenta Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Commenta Selezione (Scegliendo la Stringa)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Rendi Maiuscola Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Rendi Minuscola Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Indenta Rigidamente Selezione</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Deindenta Rigidamente Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Indenta Codice</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Converti a Capo a Windows</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Converti a Capo a Unix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Converti a Capo a Mac</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Vai a Riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Vai a Parentesi Corrispondente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Seleziona fino a Parentesi Corrispondente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Attiva/disattiva Segnalibro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Segnalibro Successivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Segnalibro Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Rimuovi Tutti i Segnalibri</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Preferenze di stile</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Mostra Numeri di Riga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Mostra Spazi Bianchi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Mostra Fine delle Righe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Mostra Guide per l&apos;Indentazione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Mostra Marcatore di Riga Lunga</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Mostra Barra degli Strumenti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Mostra Barra di Stato</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Mostra Barra di Scorrimento Orizzontale</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Schede in Ordine Alfabetico</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Attiva/disattiva Breakpoint</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Breakpoint Successivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Breakpoint Precedente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Rimuovi Tutti i Breakpoint</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Esegui File</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Esegui Selezione</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Esegui i Test</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Esegui le Demo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Aiuto sulla Parola Chiave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Documentazione su Parola Chiave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>Vai alla Pagina Iniziale</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>Vai Indietro di una Pagina</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>Vai Avanti di una Pagina</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Aggiungi Segnalibro a questa Pagina</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/ja_JP.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"ja_JP\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>既定のサイズとの差</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>背景色，ピンク (255,0,255) が既定を意味する {255, 0, 255)?}</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>b</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>u</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>コピー</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>貼り付け</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>全てを選択</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>選択部を実行</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>ウィンドウをクリア</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%2 行目の %1 を編集</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>選択範囲をクリップボードにコピー</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>既定</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>エラー</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>コメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>数</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>キーワード</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>ダブルクォートで囲まれた文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>シングルクォートで囲まれた文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>演算子</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>スカラー</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>パラメータの展開</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>ヒアドキュメントのデリミタ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>シングルクォートで囲まれたヒアドキュメント</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>既定</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>コメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>キーワード</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>ラベル</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>コマンド文字を隠す</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>外部コマンド</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>変数</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>演算子</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>既定</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>既定をインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>C のコメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>C のコメントをインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>C++ のコメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>C++  のコメントをインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>JavaDoc スタイル C のコメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>JavaDoc スタイル C のコメントをインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>数</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>数をインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>キーワード</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>キーワードをインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>ダブルクォートで囲まれた文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>ダブルクォートで囲まれた文字列をインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>シングルクォートで囲まれた文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>シングルクォートで囲まれた文字列をインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>プリプロセッサブロック</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>演算子</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>演算子をインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>閉じられていない文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>閉じられていない文字列をインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>C# verbatim 文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>C# verbatim 文字列をインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>JavaScript の正規表現</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>JavaScript の正規表現をインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>JavaDoc スタイルのC++のコメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>JavaDoc スタイルのC++のコメントをインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>JavaDoc キーワード</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>JavaDoc キーワードをインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>JavaDoc キーワードエラー</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation type=\"unfinished\">JavaDoc キーワードエラーをインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>C++ raw 文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>C++ raw 文字列をインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>既定</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>コメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>コマンド</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>ヘッダ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>位置</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>削除された行</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>加えられた行</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>変更された行</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>既定</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>コメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>コマンド</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>数</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>キーワード</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>シングルクォートで囲まれた文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>演算子</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>ダブルクォートで囲まれた文字列</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>既定</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>エラー</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>コメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>数</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>キーワード</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>ダブルクォートで囲まれた文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>シングルクォートで囲まれた文字列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>演算子</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>スカラー</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>配列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>ハッシュ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>シンボルテーブル</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>正規表現</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>置換</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>データセクション</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>ヒアドキュメントのデリミタ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>シングルクォートで囲まれたヒアドキュメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>ダブルクォートで囲まれたヒアドキュメント</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>クォートされた文字列 (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>クォートされた文字列 (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>クォートされた文字列 (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>クォートされた文字列 (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>クォートされた文字列 (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>サブルーチンプロトタイプ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>フォーマットボディ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>ダブルクオートされた文字列（インターポレートされた変数）</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>翻訳</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>正規表現（インターポレートされた変数）</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>置換（インターポレートされた変数）</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>ダブルクォートされたヒヤドキュメント（インターポレートされた変数）</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>クォートされた文字列（qq, インターポレートされた変数）</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>クォートされた文字列（qx, インターポレートされた変数）</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>クォートされた文字列（qr, インターポレートされた変数）</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>元に戻す (&amp;U) </translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>やり直す (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>切り取り (&amp;T)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>コピー (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>貼り付け (&amp;P)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>削除</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>全てを選択</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>オープンリンク</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>リンクアドレスをコピー</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>E メールを...に送信</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>E メールアドレスをコピー</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%2 行目の %1 を編集</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>アノテーション</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>テキスト</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>文字列</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>フォント</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>ボールド</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>b</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>イタリック</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>色</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>左</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>中央</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>右</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>上</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>下</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>位置</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>幅</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>高さ</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>単位</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>箱にフィット</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>箱</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>背景</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>境界</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>線のスタイル</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>線の幅</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">全てを選択</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">停止</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">継続</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation type=\"unfinished\">Octave コミュニティーニュース</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">既定</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\">エラー</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation type=\"unfinished\">Octave ドキュメント</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation type=\"unfinished\">ヘルプコレクション一時ファイルびコピーできませんでした．\n検索機能に影響があるかもしれません．\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation type=\"unfinished\">コンテント</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\">検索</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation type=\"unfinished\">関数インデックス</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation type=\"unfinished\">前のページ</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation type=\"unfinished\">次のページ</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">検索</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">ズームイン</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">ズームアウト</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation type=\"unfinished\">ヘルプファイル %1 を登録できません．</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">フィルタ</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">ドキュメント</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation type=\"unfinished\">ヘルプとしてドキュメントを見る</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">閉じる (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\">全てを閉じる (&amp;A)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation type=\"unfinished\">他を閉じる (&amp;O)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">閉じる (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\">全てを閉じる (&amp;A)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">実行</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave エディタ</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation type=\"unfinished\">カスタムファイルエディタをスタートできません\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation type=\"unfinished\">設定されたカスタムエディタが存在しません．設定を開きますか?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">継続</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation type=\"unfinished\">ファイルを保存して実行</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave エディタ</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation type=\"unfinished\">関連づけられたエディタタブが消失しました</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">ファイル\n%1\nは存在しません．作成しますか?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">作成</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">キャンセル</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">ファイル (&amp;F)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation type=\"unfinished\">最近開いたファイル (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation type=\"unfinished\">関数の編集 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation type=\"unfinished\">ファイルの保存 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation type=\"unfinished\">ファイルを別名で保存 (&amp;A)...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">閉じる (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation type=\"unfinished\">他のファイルを閉じる</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation type=\"unfinished\">印刷...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\">やり直す (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\">切り取り (&amp;T)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation type=\"unfinished\">検索と置換 (&amp;F) ...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation type=\"unfinished\">前の検索 (&amp;P)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation type=\"unfinished\">コマンド (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\">行削除</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">行のコピー</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">行の切り取り</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">単語の始まりまで削除</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">単語の終わりまで削除</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">行の始まりまで削除</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">行末まで削除</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">選択部/行の複製</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">行の入れ替え</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation type=\"unfinished\">補完リストの表示 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation type=\"unfinished\">フォーマット (&amp;F)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation type=\"unfinished\">大文字を選択(&amp;U)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation type=\"unfinished\">小文字を選択(&amp;L)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation type=\"unfinished\">コメント (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation type=\"unfinished\">アンコメント (&amp;U)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation type=\"unfinished\">コメント (文字列を選択)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation type=\"unfinished\">リジッドにセクションをインデント</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\">リジッドにセクションをアンインデント</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation type=\"unfinished\">行末文字を Windows 仕様にする (CRLF) (&amp;W)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation type=\"unfinished\">行末文字を Unix 仕様にする (LF) (&amp;U)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation type=\"unfinished\">行末文字を Legacy Mac 仕様にする (CR) (&amp;M)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation type=\"unfinished\">ナビゲーション (&amp;G)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation type=\"unfinished\">指定行 (&amp;T) ... へ移動</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\">対応する括弧に移動</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\">対応する括弧を選択</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation type=\"unfinished\">次のブックマーク (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation type=\"unfinished\">前のブックマーク (&amp;V)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation type=\"unfinished\">ブックマークをトグル (&amp;B)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation type=\"unfinished\">全てのブックマークを取り除く (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation type=\"unfinished\">設定 (&amp;P) ...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation type=\"unfinished\">スタイルの設定 (&amp;S) ...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation type=\"unfinished\">表示 (&amp;V)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation type=\"unfinished\">エディタ (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation type=\"unfinished\">行番号の表示 (&amp;L)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation type=\"unfinished\">ホワイトスペースを表示 (&amp;W)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation type=\"unfinished\">行末の表示 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation type=\"unfinished\">インデンテーションガイドの表示 (&amp;I)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation type=\"unfinished\">長い行のマーカーを表示</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation type=\"unfinished\">ツールバーの表示(&amp;T)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation type=\"unfinished\">ステイタスバーの表示</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation type=\"unfinished\">横スクロールバーの表示</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation type=\"unfinished\">ズームイン (&amp;I)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation type=\"unfinished\">ズームアウト (&amp;O)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation type=\"unfinished\">通常サイズ (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation type=\"unfinished\">デバッグ (&amp;D)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation type=\"unfinished\">ブレークポイントをトグル (&amp;B)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation type=\"unfinished\">次のブレークポイント (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation type=\"unfinished\">前のブレークポイント (&amp;V)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation type=\"unfinished\">全てのブレークポイントを解除 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation type=\"unfinished\">実行 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation type=\"unfinished\">選択部を実行 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">ヘルプ (&amp;H)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation type=\"unfinished\">キーワードでヘルプ (&amp;H)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation type=\"unfinished\">キーワードでドキュメント (&amp;D)</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation type=\"unfinished\">最近使用したファイル</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">エディタ</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation type=\"unfinished\">行:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation type=\"unfinished\">列:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation type=\"unfinished\">エンコード</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation type=\"unfinished\">eol</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation type=\"unfinished\">ブレークポイントの状態</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave エディタ</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation type=\"unfinished\">指定行へ行く</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation type=\"unfinished\">行数</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation type=\"unfinished\">選択部をコメントにする</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation type=\"unfinished\">ファイル\n  %1\nが閉じられようとしていますが修正されています．%2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation type=\"unfinished\">選択されたエンコード %2 でファイル %1 を読み込む時に\n問題が生じました．\n\n修正して保存するをデータが失われるかもしれません !</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation type=\"unfinished\">編集を強行 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation type=\"unfinished\">エンコードの変更 (&amp;g)</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">閉じる (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation type=\"unfinished\">新しい既定を選択</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation type=\"unfinished\">現在のファイルをリロードするための新しいエンコード\n選択してください．\n\nこれは既定のエンコードに影響を与えません．</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation type=\"unfinished\">デバッグまたは保存</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation type=\"unfinished\">このファイルは現在実行中です．デバッグを終了して保存しますか?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation type=\"unfinished\">Octave のファイル (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation type=\"unfinished\">全てのファイル (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation type=\"unfinished\">&quot;%1&quot;\nは正しい identifier ではありません．\n\nもしこのファイル名のままにすれば, スクリプトをこの名前で\nOctave のコマンドとしてコールできません．.\n\n他の名前を選択しますか ?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation type=\"unfinished\">現在のエディタの内容は選択されたエンコード %1 ではエンコードできません．\nこのままではデータが消失します !\n他のエンコードを選択してください !</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation type=\"unfinished\">\n\n警告: エディタ内の内容は変更されています</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation type=\"unfinished\">&apos;%1&apos; は他のアプリケーションで変更されたいます．再読込しますか？%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation type=\"unfinished\">ファイル\n%1\n削除されたか名前が変更されています．ファイルを今保存しますか？%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation type=\"unfinished\">ファイルのサイズ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation type=\"unfinished\">ファイルのタイプ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation type=\"unfinished\">修正日付</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation type=\"unfinished\">列の色のオルタネーション</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation type=\"unfinished\">パスまたはファイル名の入力</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\">一つ上のディレクトリ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation type=\"unfinished\">Octave ディレクトリの表示</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation type=\"unfinished\">現在の Octave ディレクトリへ行く</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation type=\"unfinished\">Octave ディレクトリの設定</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation type=\"unfinished\">Octave ディレクトリを現在のブラウザディレクトリに設定</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation type=\"unfinished\">現在のディレクトリで実行</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation type=\"unfinished\">ホームディレクトリの表示</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation type=\"unfinished\">ブラウザディレクトリを設定</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation type=\"unfinished\">新規のファイル...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation type=\"unfinished\">新規のディレクトリ...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation type=\"unfinished\">ダブルクリックでファイル / フォルダを開く，右クリックでオルタナティブ</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation type=\"unfinished\">名前の変更 ...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">開く</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation type=\"unfinished\">システムファイルエクスローラーで開く</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation type=\"unfinished\">テキストエディタで開く</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation type=\"unfinished\">選択部をクリップボードにコピー</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">実行</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation type=\"unfinished\">データのロード</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation type=\"unfinished\">現在のディレクトリの設定</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation type=\"unfinished\">削除 ...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation type=\"unfinished\">ファイル／ディレクトリの削除</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation type=\"unfinished\">本当に削除しますか\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation type=\"unfinished\">空のディレクトリでないので削除できません</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation type=\"unfinished\">ディレクトリをファイルブラウザで設定</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation type=\"unfinished\">ファイルを</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation type=\"unfinished\">ディレクトリの作成</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation type=\"unfinished\">新しいディレクトリ</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">ファイルブラウザ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation type=\"unfinished\">ファイルをブラウズする</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation type=\"unfinished\">エンジョイ！</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation type=\"unfinished\">終了</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">キャンセル</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation type=\"unfinished\">大文字小文字のマッチ (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation type=\"unfinished\">始めから検索 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation type=\"unfinished\">置換 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation type=\"unfinished\">全てを置換 (&amp;A)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation type=\"unfinished\">全体のワード (&amp;W)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation type=\"unfinished\">逆方向へ検索 (&amp;B)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation type=\"unfinished\">選択部を検索 (&amp;L)</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation type=\"unfinished\">ファイルの終わりから検索</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation type=\"unfinished\">始めから検索</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation type=\"unfinished\">置換結果</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation type=\"unfinished\">%1 が置換されました</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation type=\"unfinished\">検索結果</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation type=\"unfinished\">これ以上マッチする対象はありません</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation type=\"unfinished\">複数のファイルで検索</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation type=\"unfinished\">名称: </translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation type=\"unfinished\">スタートイン:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation type=\"unfinished\">スタートディレクトリへ設定</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation type=\"unfinished\">ブラウズ ...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation type=\"unfinished\">スタートディレクトリをブラウズ</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation type=\"unfinished\">サブディレクトリを検索</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation type=\"unfinished\">マッチするファイルを再帰的に検索</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation type=\"unfinished\">ディレクトリ名を含める</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation type=\"unfinished\">検索結果にマッチしたディレクトリを含ませる</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation type=\"unfinished\">マッチするテキストへ</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation type=\"unfinished\">検索結果</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation type=\"unfinished\">アイドル</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">検索</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation type=\"unfinished\">マッチするファイルの検索を開始</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">停止</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation type=\"unfinished\">ファイルの内容</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation type=\"unfinished\">検索中 ...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation type=\"unfinished\">%1 マッチ</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation type=\"unfinished\">検索ディレクトリを設定</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation type=\"unfinished\">ファイル名</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation type=\"unfinished\">ディレクトリ</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation type=\"unfinished\">検索:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation type=\"unfinished\">前方検索</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation type=\"unfinished\">後方検索</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation type=\"unfinished\">Octave クリティカルエラー</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation type=\"unfinished\">コマンドヒストリのブラウズと検索</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">コピー</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation type=\"unfinished\">スクリプトの作成</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\">フィルタを隠す</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\">フィルタを表示</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation type=\"unfinished\">ダブルクリックでコマンドをコマンドウィンドウに移します．</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation type=\"unfinished\">コマンドヒストリをフィルタするためのテキストを入力</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">フィルタ</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">コマンドヒストリ</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Octaveへようこそ!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">次</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">キャンセル</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\">&lt;html&gt;&lt;body&gt;\n&lt;p&gt; このコンピュータでの Octave のグラフィカルインターフェースへの初めてのアクセスのようです\n&apos;次へ&apos; をクリックして，設定ファイルを作成し，Octave を起動してください.&lt;/p&gt;\n&lt;p&gt;設定ファイルは以下に置かれます&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation type=\"unfinished\">本当に Octave を終了しますか？</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\">ワークスペースを別名で保存</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">ワークスペースをロード</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Octave について</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation type=\"unfinished\">ディレクトリのブラウズ</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation type=\"unfinished\">Octave ファイル (*.m);;全てのファイル (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation type=\"unfinished\">新しい関数の名前:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation type=\"unfinished\">関数 %1 が見つかりません</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">ファイル (&amp;F)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation type=\"unfinished\">開く...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation type=\"unfinished\">エディタに存在するファイルを開く</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation type=\"unfinished\">ワークスペースのロード...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation type=\"unfinished\">ワークスペースを別名で保存...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation type=\"unfinished\">終了</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation type=\"unfinished\">新規</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation type=\"unfinished\">新規のスクリプト</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation type=\"unfinished\">新規の関数 ...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">新規のフィギュア</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">元に戻す</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">コピー</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">貼り付け</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">全てを選択</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">クリップボードをクリア</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">コマンドウィンドウのクリア</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">コマンドヒストリのクリア</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">ワークスペースのクリア</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation type=\"unfinished\">設定 ...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation type=\"unfinished\">デバッグ (&amp;b)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">ステップ</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">ステップイン</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">ステップアウト</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">継続</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\">デバッグモードの終了</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation type=\"unfinished\">ウィンドウ (&amp;W)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\">コマンドウィンドウの表示</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">コマンドヒストリの表示</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">ファイルブラウザの表示</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">ワークスペースの表示</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">エディタの表示</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">ドキュメントの表示</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\">変数エディタの表示</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">コマンドウィンドウ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">コマンドヒストリ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">ファイルブラウザ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">ワークスペース</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">ドキュメント</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\">変数エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">ヘルプ (&amp;H)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">バグの報告</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Octave パッケージ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation type=\"unfinished\">octave への寄付</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation type=\"unfinished\">ディスク上</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation type=\"unfinished\">オンライン</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation type=\"unfinished\">ニュース (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">リリースノート</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">コミュニティーニュース</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation type=\"unfinished\">ツールバー</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation type=\"unfinished\">ディレクトリ名を入力</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation type=\"unfinished\">現在のディレクトリ: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\">一つ上のディレクトリ</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\">&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctaveコミュニティニュースが入手できません。\n&lt;/p&gt;\n&lt;p&gt;\n最新のニュースは，以下をクリックしてください．\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\n(リンクは外部ブラウザで開きます．) .\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Octave 開発チーム</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation type=\"unfinished\">編集</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\">既定</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">作成</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">キャンセル</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">ファイル\n%1\nは存在しません．作成しますか?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation type=\"unfinished\">ファイル %1 がロードパスに存在しません．編集している関数を実行またはデバッグするためには，ディレクトリを変更するかロードパスにディレクトリを加えてください．</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation type=\"unfinished\">ファイル %1 がロードパスに存在する同名のファイルでシャドウされています．編集している関数を実行またはデバッグするためには，ディレクトリを %2 に変更してください．</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation type=\"unfinished\">ディレクトリの変更またはロードパスへのディレクトリの追加</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation type=\"unfinished\">ディレクトリの変更 (&amp;C) </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation type=\"unfinished\">ロードパスにディレクトリを追加 (&amp;A)</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation type=\"unfinished\">リリースノートファイル &apos;%1&apos; が空です．</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation type=\"unfinished\">リリースノートファイル &apos;%1&apos; が読み取れません．</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation type=\"unfinished\">Octave リリースノート</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\">保存</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\">背景</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation type=\"unfinished\">選択された前景</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation type=\"unfinished\">選択された後景</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation type=\"unfinished\">グローバル</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation type=\"unfinished\">システム設定</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation type=\"unfinished\">IBeam カーソル</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation type=\"unfinished\">ブロックカーソル</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation type=\"unfinished\">下線カーソル</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation type=\"unfinished\">Octave のスタートアップディレクトリの設定</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation type=\"unfinished\">ファイルブラウザのスタートアップディレクトリの設定</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation type=\"unfinished\">ファイルからショートカットをインポート</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation type=\"unfinished\">Octave ショートカットファイル (*.osc);;全てのファイル (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation type=\"unfinished\">ショートカットの上書き</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation type=\"unfinished\">すべてのショートカットを上書きしようとしています．\n現在のショートカットを保存しますか，キャンセルしますか?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation type=\"unfinished\">保存しない</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">コミュニティーニュース</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">次</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">キャンセル</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\">&lt;p&gt;Octave 起動時，Octave コミュニティの現在のニュースや情報をオプションで検索します．\nこのチェックは一日一回で最後のニュースをみた時点からなにかあたらしいニュースが存在する場合のみ表示されます．&lt;/p&gt;\n&lt;p&gt;ニュースは &quot;ヘルプ&quot; メニュー内の &quot;コミュニティ ニュース&quot; の項目を選択するかまたは in  \n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;&#x3000;を訪問したときに表示されます.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;\n</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\">クリア</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation type=\"unfinished\">既定に設定</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation type=\"unfinished\">ダブルショートカット</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation type=\"unfinished\">グローバル</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation type=\"unfinished\">ファイルメニュー</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation type=\"unfinished\">エディトメニュー</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation type=\"unfinished\">デバッグメニュー</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation type=\"unfinished\">ウィンドウメニュー</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation type=\"unfinished\">ヘルプメニュー</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation type=\"unfinished\">新しいメニュー</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation type=\"unfinished\">ドックウィジェットでタブの操作</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation type=\"unfinished\">ドックウィジェットで検索と置換</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation type=\"unfinished\">エディタとドキュメントでズーム</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation type=\"unfinished\">ビューメニュー</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation type=\"unfinished\">実行メニュー</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation type=\"unfinished\">ドキュメントビューワー</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation type=\"unfinished\">ブラウザ</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">GNU Octave へようこそ</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Octaveへようこそ!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">コマンドウィンドウ</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation type=\"unfinished\">ジオメトリをリストア</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation type=\"unfinished\">リドック</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\">変数エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation type=\"unfinished\">変数の編集</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation type=\"unfinished\">変数エディタのツールバー</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\">保存</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation type=\"unfinished\">変数をファイルに保存</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">切り取り</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation type=\"unfinished\">データを切り取ってクリップボードへ</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">コピー</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation type=\"unfinished\">クリップボードにデータをコピー</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">貼り付け</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation type=\"unfinished\">クリップボードを変数データに貼り付け</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation type=\"unfinished\">プロット</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation type=\"unfinished\">選択されたデータをプロット</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation type=\"unfinished\">選択されたデータをプロット</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation type=\"unfinished\">アップ</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation type=\"unfinished\">変数の階層を1レベルアップする</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation type=\"unfinished\">変数 %1 を別名で保存</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">切り取り</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">コピー</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">貼り付け</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\">クリア</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\">削除</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">GNU Octave へようこそ</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation type=\"unfinished\">名前</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">クラス</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">次元</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">値</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">属性</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation type=\"unfinished\">右クリックでコピー，名前の変更，または表示</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation type=\"unfinished\">複素数</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">クラス</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">次元</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">値</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">属性</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">ワークスペース</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation type=\"unfinished\">アクティブなワークスペースの表示．</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation type=\"unfinished\">ワークスペースをフィルタするためにテキストを入力</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">フィルタ</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation type=\"unfinished\">アクティブワークスペースの変数の表示&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation type=\"unfinished\">変数の属性のための色</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation type=\"unfinished\">変数エディタで開く</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation type=\"unfinished\">名前のコピー</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation type=\"unfinished\">値のコピー</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation type=\"unfinished\">名前の変更</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation type=\"unfinished\">トップレベルのシンボルのみの名前の変更</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\">フィルタを隠す</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\">フィルタを表示</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>一般</translation>\n    </message>\n    <message>\n        <location line=\"-2736\"/>\n        <source>Interface</source>\n        <translation>インターフェイス</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Dock widget title bar</source>\n        <translation>ドックウィジェットタイトルバー</translation>\n    </message>\n    <message>\n        <location line=\"+413\"/>\n        <source>Confirm before exiting</source>\n        <translation>終了する前に確認</translation>\n    </message>\n    <message>\n        <location line=\"-89\"/>\n        <source>Octave logo only</source>\n        <translation>Octave ロゴのみ</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>レターアイコン</translation>\n    </message>\n    <message>\n        <location line=\"+59\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>ステータスバーを表示</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>テキストをインアクティブ</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>アクティブ</translation>\n    </message>\n    <message>\n        <location line=\"-96\"/>\n        <source>Small</source>\n        <translation>小さい</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>大きい</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>カスタムスタイル</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Background inactive</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation type=\"unfinished\">3D</translation>\n    </message>\n    <message>\n        <location line=\"+206\"/>\n        <source>Octave Startup</source>\n        <translation>Octave スタートアップ</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>ブラウズ</translation>\n    </message>\n    <message>\n        <location line=\"-1385\"/>\n        <source>Editor</source>\n        <translation>エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>本機能は等幅フォントで正常動作します．既定フォントのスペースのキャラクターの幅で行は表示されます．スタイルがプロポーショナルフォントを使う場合や可変フォントサイズ，ボールド，イタリックフォントとノーマルテクストが使用された場合正常に動作しません．</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>コードの折りたたみを有効化</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation type=\"unfinished\">Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>横方向スクロールバーの表示</translation>\n    </message>\n    <message>\n        <location line=\"-19\"/>\n        <source>Show tool bar</source>\n        <translation>ツールバーの表示</translation>\n    </message>\n    <message>\n        <location line=\"+522\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>現在のウィンドウの境界で長い行をラップ</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Indentation</source>\n        <translation>インデント</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation>インデントの幅</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>タブインデントライン</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>自動インデント</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>タブの幅</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>インデントガイドの表示</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation>インデントにタブを使用</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation>オートコンプリート</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>キーワードのマッチ</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>大文字小文字を区別</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>指定された単語で単語の置換</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>文書中で検索</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>補完リストの自動表示</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>プロンプトなしで外部で操作されてファイルを再ロードする</translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation>外部エディタを使用する</translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>読込，保存に使用するテキストのエンコード</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation>エディタのスタイル</translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>（バッファサイズの変更はヒストリを消去します）</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation>ヒストリのバッファサイズ</translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>フォント</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>行番号の表示</translation>\n    </message>\n    <message>\n        <location line=\"-517\"/>\n        <source>Graphic icons</source>\n        <translation>グラフィクアイコン</translation>\n    </message>\n    <message>\n        <location line=\"+97\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>設定は .octaverc スタートアップファイルの後に適用されます</translation>\n    </message>\n    <message>\n        <location line=\"+433\"/>\n        <source>Show whitespace</source>\n        <translation>ホワイトスペースの表示</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>インデントに使用されたホワイトスペースを表示しない</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Show EOL characters</source>\n        <translation>文末文字を表示する</translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation>既定の文末文字モード</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>リストが表示される前の文字数</translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>プロンプトなしに現在存在しないファイルを作成</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>コマンドライン(%f=ファイル名, %l=行数): </translation>\n    </message>\n    <message>\n        <location line=\"+1015\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;フォントの種類, サイズ (既定のサイズからの差), フォントのスタイル (ボールド(&lt;b&gt;b&lt;/b&gt;), イタリック(&lt;b&gt;i&lt;/b&gt;), 下線(&lt;b&gt;u&lt;/b&gt;)), テキストの色, 背景色 (後者について, マジェンダ (255,0,255) は既定の背景色のプレースホルダー).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-1515\"/>\n        <source>Cursor type:</source>\n        <translation>カーソルのタイプ: </translation>\n    </message>\n    <message>\n        <location line=\"-605\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">設定</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(要再起動)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>ツールバーアイコン</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>言語</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>スタイル</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Octave インタープリタの初期された作業ディレクトリ</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>前のセッションの作業ディレクトリをリストア</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>コマンド</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>他のウィジェットからコマンドが操作中のコマンドウィンドウにフォーカスをセット</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>エディタ中のマーカーに加えたコマンドウィンドウ中にデバッグの位置を表示</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>コマンドウィンドウのカラー</translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>エディタのフォントとのサイズの違い</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>コメント (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>長い行</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>長い行を行の長さで分断</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>コメント内でのみ行の分断</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>行の長さ</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>長い行のマーカー</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>行</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>背景</translation>\n    </message>\n    <message>\n        <location line=\"+191\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>&quot;if&quot; などの後に自動挿入</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation>デバッグ</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+67\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>起動時またはエディタが閉じられ再び起動された際一つ前のセッションからエディタのタブをリストアする</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>エディタウィジェットが閉じられるまたは隠されたらすべてのファイルを閉じる</translation>\n    </message>\n    <message>\n        <location line=\"+75\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+884\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2374\"/>\n        <source>Use foreground color</source>\n        <translation>前景色を使う</translation>\n    </message>\n    <message>\n        <location line=\"-140\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+189\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>フォントサイズ</translation>\n    </message>\n    <message>\n        <location line=\"-1234\"/>\n        <source>Rotated tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\">位置</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+773\"/>\n        <source>Force newline at end when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>File Browser</source>\n        <translation>ファイルブラウザ</translation>\n    </message>\n    <message>\n        <location line=\"+75\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>初期のファイルブラウザのディレクトリ（Octave の初期作業ディレクトリとシンクロしないとき）</translation>\n    </message>\n    <message>\n        <location line=\"+75\"/>\n        <source>Workspace</source>\n        <translation>ワークスペース</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>変数の属性の色</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>ショートカットセットのインポート</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>ショートカットセットのエクスポート</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>ショートカットを既定に戻す</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>既定</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>ネットワーク</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>現在のニュースや情報を表示させるために Octave が Octave ウェブサイトに接続することを許可する</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>プロキシサーバーを使用する</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>変数エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>既定の行の幅</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>既定の列の幅</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>変数エディタの色</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>コマンドウィンドウフォーカス時大域的なショートカットを使用しない</translation>\n    </message>\n    <message>\n        <location line=\"-2452\"/>\n        <source>Normal</source>\n        <translation>標準</translation>\n    </message>\n    <message>\n        <location line=\"+1787\"/>\n        <source>File handling</source>\n        <translation>ファイル操作</translation>\n    </message>\n    <message>\n        <location line=\"+265\"/>\n        <source>Behavior</source>\n        <translation>挙動</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Octaveのワーキングディレクトリをファイルブラウザと同期させる</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>一つ前のセッションの最後のディレクトリを保存する</translation>\n    </message>\n    <message>\n        <location line=\"+334\"/>\n        <source>Shortcuts</source>\n        <translation>ショートカット</translation>\n    </message>\n    <message>\n        <location line=\"+38\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation>エクスポート</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>インポート</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>ホスト名: </translation>\n    </message>\n    <message>\n        <location line=\"-536\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>既定のテキストエディタで開くファイルの拡張子（&quot;;&quot; で区切る）</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Proxy type:</source>\n        <translation>プロキシのタイプ: </translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>ポート: </translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>ユーザー名: </translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>パスワード: </translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation type=\"unfinished\">新規ファイル</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">新規のフィギュア</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation type=\"unfinished\">ファイルを開く</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">ワークスペースをロード</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\">ワークスペースを別名で保存</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation type=\"unfinished\">Octave の終了</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">コピー</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">貼り付け</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">元に戻す</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">全てを選択</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">クリップボードをクリア</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation type=\"unfinished\">複数のファイルで検索</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">コマンドウィンドウのクリア</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">コマンドヒストリのクリア</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">ワークスペースのクリア</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">設定</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">ステップ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">ステップイン</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">ステップアウト</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">継続</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\">デバッグモードの終了</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\">コマンドウィンドウの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">コマンドヒストリの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">ファイルブラウザの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">ワークスペースの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">エディタの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">ドキュメントの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\">変数エディタの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">コマンドウィンドウ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">コマンドヒストリ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">ファイルブラウザ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">ワークスペース</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">ドキュメント</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\">変数エディタ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation type=\"unfinished\">オンラインドキュメントの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">バグの報告</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Octave パッケージ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation type=\"unfinished\">Octave への貢献</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation type=\"unfinished\">Octave 開発チーム</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Octave について</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">リリースノート</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">コミュニティーニュース</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation type=\"unfinished\">タブを閉じる</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation type=\"unfinished\">すべてのタブを閉じる</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation type=\"unfinished\">他のタブを閉じる</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation type=\"unfinished\">左タブに切替</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation type=\"unfinished\">右タブに切替</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation type=\"unfinished\">左タブに移動</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation type=\"unfinished\">右タブに移動</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">ズームイン</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">ズームアウト</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation type=\"unfinished\">ズームノーマル</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation type=\"unfinished\">関数の編集</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation type=\"unfinished\">ファイルの保存</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation type=\"unfinished\">ファイルを別名で保存</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation type=\"unfinished\">印刷</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation type=\"unfinished\">やり直し</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">切り取り</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation type=\"unfinished\">検索と置換</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation type=\"unfinished\">次を検索</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation type=\"unfinished\">前を検索</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">単語の始まりまで削除</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">単語の終わりまで削除</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">行の始まりまで削除</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">行末まで削除</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\">行削除</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">行のコピー</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">行の切り取り</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">選択部/行の複製</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">行の入れ替え</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation type=\"unfinished\">補完リストの表示</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation type=\"unfinished\">選択部をコメントにする</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation type=\"unfinished\">選択部をアンコメントする</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation type=\"unfinished\">選択部をコメントにする（文字列を選ぶ）</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation type=\"unfinished\">選択部を大文字にする</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation type=\"unfinished\">選択部を小文字にする</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation type=\"unfinished\">リジッドにセクションをインデント</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\">リジッドにセクションをアンインデント</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation type=\"unfinished\">行末を Windows 形式に変換</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation type=\"unfinished\">行末を Unix 形式に変換</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation type=\"unfinished\">行末を Mac 形式に変換</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation type=\"unfinished\">指定行に移動</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\">対応する括弧に移動</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\">対応する括弧を選択</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation type=\"unfinished\">ブックマークをトグル</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation type=\"unfinished\">次のブックマーク</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation type=\"unfinished\">前のブックマーク</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation type=\"unfinished\">すべてのブックマークの削除</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation type=\"unfinished\">スタイルの設定</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation type=\"unfinished\">行番号の表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation type=\"unfinished\">ホワイトスペースキャラクタの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation type=\"unfinished\">行末の表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation type=\"unfinished\">インデントガイドの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation type=\"unfinished\">長い行のマーカーを表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation type=\"unfinished\">ツールバーの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation type=\"unfinished\">ステータスバーの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation type=\"unfinished\">縦スクロールバーの表示</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation type=\"unfinished\">ブレークポイントをトグル</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation type=\"unfinished\">次のブレークポイント</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation type=\"unfinished\">前のブレークポイント</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation type=\"unfinished\">全てのブレークポイントを解除</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation type=\"unfinished\">ファイルを実行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\">選択部を実行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation type=\"unfinished\">キーワードでヘルプ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation type=\"unfinished\">キーワードでドキュメント</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation type=\"unfinished\">ホームページへ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation type=\"unfinished\">1 ページ戻る</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation type=\"unfinished\">1 ページ進む</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/lt_LT.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"lt_LT\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Skirtumas nuo numatyto dydžio</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Fono spalva; šviesi alyvinė spalva (255,0,255) nurodo, kad naudoti numatytąją spalvą</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation type=\"unfinished\">r</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation type=\"unfinished\">s</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation type=\"unfinished\">b</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Kopijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Įklijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Pažymėti viską</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\">Vykdyti pažymėtą kodą</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Išvalyti langą</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%2 eilutėje tvarkyti %1</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>pažymėta sritis nukopijuota į atminties mainų sritį (clipboard)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>Numatytasis teksas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Klaida</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Komentaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Skaičius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Raktinis žodis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>&quot;&quot; eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>&apos;&apos; eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Matematinis operatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Indentifikatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Skaliaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>Rodiklių išplėtimas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Atvirkščių kabučių eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>HEREDOC tipo eilutės aprašymo pradžios žymeklis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>HEREDOC tipo eilutė</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>Numatytasis teksas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Komentaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Raktinis žodis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>&quot;goto&quot; žymė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>Ženklas, nurodantis neišvesti komandų į ekraną</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>Išorinė komanda</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Kintamasis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Matematinis operatorius</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>Numatytasis tekstas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>Numatytasis tekstas, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>/* */ komentaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>/* */ komentaras, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>// komentaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>// komentaras esantis, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>/** */ (JavaDoc stiliaus) komentaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>/** */ (JavaDoc stiliaus) komentaras, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Skaičius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Skaičius esantis, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Raktinis žodis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Raktinis žodis, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>&quot;&quot; eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>&quot;&quot; eilutė, esanti # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>&apos;&apos; eilutė kabučių</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>&apos;&apos; eilutė, esanti # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>IDL UUID, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation># sakinys (prasideda &quot;#&quot; ženklu)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation># sakinys, esanti kitame # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Matematinis operatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Matematinis operatorius, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Indentifikatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Indentifikatorius, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>Eilutė neturinti &quot;uždarančios&quot; kabutės</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>&quot;Uždarančios&quot; kabutės neturinti eilutė, esanti # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>C# @&quot;&quot; tipo eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>C# @&quot;&quot; tipo eilutė, esanti # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>JavaScript reguliarioji išraiška</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>JavaScript reguliarioji išraiška, esanti # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>/// (JavaDoc stiliaus) komentaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>/// (JavaDoc stiliaus) komentaras, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>Antriniai raktiniai žodžiai ir indentifikatoriai</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Antriniai raktiniai žodžiai ir indentifikatoriai, esantys # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>JavaDoc raktinis žodis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>JavaDoc raktinis žodis, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>Neteisingas JavaDoc raktinis žodis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>Neteisingas JavaDoc raktinis žodis, esantis # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Visuotinos klasės ir tipų apibėžtys</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Visuotinos klasės ir tipų apibėžtys, esančios # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>C++ R&quot;&quot; tipo eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>C++ R&quot;&quot; tipo eilutė, esanti # sakinyje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>Numatytasis teksas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Komentaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Komanda</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>Antraštė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Padėtis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Panaikinta eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Pridėta eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Pakeista eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>Numatytasis teksas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Komentaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Komanda</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Skaičius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Raktinis žodis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>&apos;&apos; eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Matematinis operatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Kintamojo, komandos ar funkcijos pavadinimas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>&quot;&quot; eilutė</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>Numatytasis teksas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Klaida</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Komentaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD tipo eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Skaičius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Raktinis žodis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>&quot;&quot; eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>&apos;&apos; eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Matematinis operatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Kintamojo, funkcijos, klasės ar modulio pavadinimas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Skaliaras</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>Masyvas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>Asocijuotas masyvas arba žodynas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Ženklų lentelė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>Reguliarioji išraiška (&quot;m&quot; operatorius)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>Pakeitimas (&quot;s&quot; operatorius)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>`` eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>Datos sritis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>HEREDOC tipo eilutės aprašymo pradžios žymeklis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>&apos;&apos; HEREDOC tipo eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>&quot;&quot; HEREDOC tipo eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>`` HEREDOC tipo eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>&quot;q&quot; operatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>&quot;qq&quot; operatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>&quot;qx&quot; operatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>&quot;qr&quot; operatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>&quot;qw&quot; operatorius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>&quot;POD verbatim&quot; tipo eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>Paprogramės prototipas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>Formato pavadinimas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>Formato aprašas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>Kintamasis dvigubų kabučių eilutėje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>Vertimas (&quot;tr&quot; operatorius)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>Kintamasis reguliarioje išraiškoje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>Kintamasis &quot;s&quot; operatoriuje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>Kintamasis `` eilutėje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>Kintamsis &quot;&quot; HEREDOC tipo eilutėje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>Kintamsis `` HEREDOC tipo eilutėje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>Kintamasis &quot;qq&quot; operatoriuje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>Kintamasis &quot;qx&quot; operatoriuje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>Kintamasis &quot;qr&quot; operatoriuje</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>At&amp;šaukti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>At&amp;statyti</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>Iškirp&amp;ti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Kopijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>Įk&amp;lijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Pašalinti</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Pažymėti viską</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Atidaryti nuorodą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Kopijuoti nuorodos adresą</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Siųsti e-paštą...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>Kopijuoti e-pašto adresą</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%2 eilutėje tvarkyti %1</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Apibūdinimas</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Tekstas</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Ženklų eilutė</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Šriftas</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>paryškintas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>r</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>pasviręs</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>s</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>spalva</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>kairėje</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>viduryje</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>dešinėje</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>viršuje</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>apačioje</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Padėtis</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Plotis</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Aukštis</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>vienetai</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalizuoti</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Numatytasis teksto rėmelio dydis</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Rėmelis</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Fono spalva</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Linijų / kraštinių spalva</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Linijų tipas</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>joks</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Linijų storis</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Pažymėti viską</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Sustoti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Tęsti scenarijau vykdymą</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation type=\"unfinished\">Octave bendruomenės naujienos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\">Klaida</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation type=\"unfinished\">Octave dokumentacija</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation type=\"unfinished\">Nepavyko nukopijuoti pagalbos rinkinio į laikinąją\nbylą. Paieškos galimybės gali būti įtakotos.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation type=\"unfinished\">Turinys</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\">Paieška</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Ieškoti</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">Padidinti</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">Sumažinti</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation type=\"unfinished\">Nepavyksta užregistruoti pagalbos failo &quot;%1&quot;.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">Atranka</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Dokumentacija</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation type=\"unfinished\">Žiūrėkite dokumentaciją, kai reikia pagalbos.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Uždaryti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Uždaryti</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Vykdyti</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation type=\"unfinished\">Nepavyko paleisti vartotojo bylų tvarkyklės\n&quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation type=\"unfinished\">Dar nesutvarkyti vartotojo tvarkyklės nustatymai.\nAr norite atidaryti nustatymų langą?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Tęsti scenarijau vykdymą</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation type=\"unfinished\">Išsaugoti bylą ir vykdyti</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation type=\"unfinished\">Dingo susijusių bylų tvarkyklės kortelė.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">Nėra &quot;%1&quot;\nbylos. Ar norite tokią sukurti?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">Sukurti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Atšaukti</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Byla</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation type=\"unfinished\">&amp;Paskutinės tvarkytos bylos</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation type=\"unfinished\">&amp;Tvarkyti funkciją</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation type=\"unfinished\">Iš&amp;saugoti bylą</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation type=\"unfinished\">Išs&amp;augoti bylą kaip...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Uždaryti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation type=\"unfinished\">Uždaryti viską</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation type=\"unfinished\">Uždaryti kitas bylas</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation type=\"unfinished\">Spausdinti...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Tvarkyti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\">At&amp;statyti</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\">Iškirp&amp;ti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation type=\"unfinished\">&amp;Rasti ir pakeisti...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation type=\"unfinished\">Surasti &amp;ankstesnį</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation type=\"unfinished\">&amp;Komandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">Kopijuoti eilutę</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">Iškirpti eilutę</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">Trinti iki žodžio pradžios</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">Trinti iki žodžio pabaigos</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">Trinti iki eilutės pradžios</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">Trinti iki eilutės pabaigos</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">Dvigubinti pažymėtą sritį/eilutę</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">Sukeisti eilutes</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation type=\"unfinished\">Rodyti automatinio užbaigimo &amp;sąrašą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation type=\"unfinished\">&amp;Formatas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation type=\"unfinished\">Pažymėtos srities raides pakeisti &amp;didžiosiomis raidėmis</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation type=\"unfinished\">Pažymėtos srities raides pakeisti &amp;mažosiomis raidėmis</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation type=\"unfinished\">&amp;Užkomentuoti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation type=\"unfinished\">&amp;Atkomentuoti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation type=\"unfinished\">Užkomentuoti nurodant komentavimo ženklą</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation type=\"unfinished\">Pažymėtą sritį padaryti su &amp;įtraukomis</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\">&amp;Šalinti pažymėtos srities įtraukas</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\">Kodą padaryti su įtraukomis</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation type=\"unfinished\">Eilučių pabaigos ženklai pagal &amp;Windows OS (CR LF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation type=\"unfinished\">Eilučių pabaigos ženklai pagal &amp;Unix OS (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation type=\"unfinished\">Teksto ž&amp;ymeklio padėtys</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation type=\"unfinished\">Perei&amp;ti į eilutę...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\">Pereiti į priešingą skliaustelių poros pusę</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\">Pažymėti skliaustelių poros turinį</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation type=\"unfinished\">Seka&amp;nti eilutė su žymele</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation type=\"unfinished\">&amp;Ankstesnė eilutė su žymele</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation type=\"unfinished\">Pridėti/nuimti &amp;žymelę</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation type=\"unfinished\">&amp;Pašalinti visas žymeles</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation type=\"unfinished\">&amp;Nustatymai...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation type=\"unfinished\">&amp;Vaizdavimo nustatymai...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation type=\"unfinished\">&amp;Vaizdas</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation type=\"unfinished\">&amp;Tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation type=\"unfinished\">Rodyti eilučių &amp;numerius</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation type=\"unfinished\">Rodyti &amp;tarpo ženklus</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation type=\"unfinished\">Rodyti eilutės &amp;pabaigos ženklus</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation type=\"unfinished\">Rodyti įtraukų l&amp;inijas</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation type=\"unfinished\">Rodyti &amp;lapo pločio liniją</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation type=\"unfinished\">Rodyti į&amp;rankių juostą</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation type=\"unfinished\">Rodyti &amp;būvio eilutę</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation type=\"unfinished\">Rodyti &amp;horizontalią slinkties juostą</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation type=\"unfinished\">&amp;Didinti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation type=\"unfinished\">&amp;Mažinti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation type=\"unfinished\">&amp;Numatytasis priartinimas</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation type=\"unfinished\">&amp;Derinti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation type=\"unfinished\">Pridėti/nuimti sustojimo &amp;tašką</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation type=\"unfinished\">&amp;Sekantis sustojimo taškas</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation type=\"unfinished\">&amp;Ankstesnis sustojimo taškas</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation type=\"unfinished\">&amp;Pašalinti visus sustojimo taškus</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation type=\"unfinished\">&amp;Vykdyti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation type=\"unfinished\">Vykdyti &amp;pažymėtos srities kodą</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Pagalba</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation type=\"unfinished\">&amp;Pagalba pagal raktinį žodį</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation type=\"unfinished\">&amp;Dokumentacija apie raktinį žodį</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation type=\"unfinished\">Paskutinės atvertos bylos</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Tvarkyklė</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation type=\"unfinished\">eilutė:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation type=\"unfinished\">stulpelis:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation type=\"unfinished\">koduotė:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation type=\"unfinished\">eilutės pabaiga:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation type=\"unfinished\">Sustojimo taško būvis</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation type=\"unfinished\">Pereiti į eilutę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation type=\"unfinished\">Eilutės numeris</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation type=\"unfinished\">Užkomentuoti pažymėtą sritį</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation type=\"unfinished\">Komentavimui naudoti šiuos ženklus:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation type=\"unfinished\">&lt;bevardis&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation type=\"unfinished\">Jūs bandote uždaryti bylą\n&quot;%1&quot;,\nkurios turinys buvo pakeistas, bet neišsaugotas.\n%2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Uždaryti</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation type=\"unfinished\">Derinti ar saugoti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation type=\"unfinished\">Jūs esate bylos kodo derinimo režime.\nBaigti derinimą ir išsaugoti?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation type=\"unfinished\">Octave bylos (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation type=\"unfinished\">Visos bylos (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation type=\"unfinished\">Neteisingas bylos &quot;%1&quot; pavadinimas.\n\nJei palikstite tokį bylos pavadinimą, negalėsite bylos\npavadinimo naudoti kaip Octave komandos.\n\nAr norite pakeisti bylos pavadinimą?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation type=\"unfinished\">\n\nĮspėjimas: bylos turinys tvarkyklėje buvo pakeistas!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation type=\"unfinished\">Atrodo, kad bylos &quot;%1&quot; turinys buvo pakeistas naudojant kitą programą. Ar norite iš naujo įkleti bylos turinį?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation type=\"unfinished\">Atrodo, kad byla\n&quot;%1&quot;\nbuvo pervadinta ar ištrinta. Ar norite ją išsaugoti?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation type=\"unfinished\">Bylos dydis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation type=\"unfinished\">Bylos tipas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation type=\"unfinished\">Pakeitimo data</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation type=\"unfinished\">Rodyti paslėptas bylas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation type=\"unfinished\">Kitokia kas antros eilutės fono splava</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation type=\"unfinished\">Įveskite aplanko kelią arba bylos pavadinimą</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation type=\"unfinished\">Rodyti Octave aplanką</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation type=\"unfinished\">Pereiti į numatytąjį Octave darbo aplanką</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation type=\"unfinished\">Nustatyti Octave darbo aplanką</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation type=\"unfinished\">Einamąjį aplanką padaryti Octave darbo aplanku</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation type=\"unfinished\">Veiksmai einamajame aplanke</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation type=\"unfinished\">Rodyti namų aplanką</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation type=\"unfinished\">Parinkti naršyklės aplanką...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\">Rasti bylas...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation type=\"unfinished\">Nauja byla...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation type=\"unfinished\">Naujas aplankas...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation type=\"unfinished\">Pervadinti...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">Atidaryti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation type=\"unfinished\">Atidaryti OS bylų naršyklėje</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation type=\"unfinished\">Atidaryti Octave tvarkyklėje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation type=\"unfinished\">Pažymėtas bylas/aplankus kopijuoti į atminties mainų sritį (clipboard)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Vykdyti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation type=\"unfinished\">Įkelti duomenis</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation type=\"unfinished\">Parinkti einamąjį aplanką</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation type=\"unfinished\">Ištrinti...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation type=\"unfinished\">Ištrinti bylą/aplanką</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation type=\"unfinished\">Jūs įsitikinęs, kad norite ištrinti\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation type=\"unfinished\">Negaliu ištrinti netuščio aplanko</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation type=\"unfinished\">Aplanko parinkimas bylų naršyklei</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation type=\"unfinished\">Sukurti bylą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Byla bus sukurta\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation type=\"unfinished\">Nauja_byla.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation type=\"unfinished\">Sukurti aplanką</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Aplankas bus sukuras\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation type=\"unfinished\">Naujo aplanko pavadinimas</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Bylų naršyklė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation type=\"unfinished\">Naršykite</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation type=\"unfinished\">Mėgaukitės!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Ankstesnis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation type=\"unfinished\">Užbaigti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Atšaukti</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation type=\"unfinished\">Skirti didžiasias ir mažasias &amp;raides</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation type=\"unfinished\">Paiešką pradėti &amp;nuo bylos pradžios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation type=\"unfinished\">Paieška ra&amp;tu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation type=\"unfinished\">Pa&amp;keisti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation type=\"unfinished\">Pakeisti &amp;visus</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation type=\"unfinished\">&amp;Daugiau...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation type=\"unfinished\">Pilnas &amp;žodis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation type=\"unfinished\">Ieškoti atbuliniu &amp;eiliškumu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation type=\"unfinished\">Ieškoti pa&amp;žymėtoje srityje</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation type=\"unfinished\">Paiešką pradėti nuo bylos pabaigos</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation type=\"unfinished\">Paiešką pradėti nuo bylos pradžio</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation type=\"unfinished\">Pakeitimų duomenys</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation type=\"unfinished\">Atlikta %1 pakeitimų</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation type=\"unfinished\">Paieškos duomenys</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation type=\"unfinished\">Daugiau atitikmenų nerasta</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation type=\"unfinished\">Rasti bylas</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation type=\"unfinished\">Pavadinimas:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation type=\"unfinished\">Paiešką pradėti čia:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation type=\"unfinished\">Įveskite aplanko, kuriame bus ieškoma, pavadinimą</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation type=\"unfinished\">Naršyti...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation type=\"unfinished\">Parinkti aplanką, kuriame bus ieškoma</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation type=\"unfinished\">Vidiniai aplankai</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation type=\"unfinished\">Bylos(-ų) su tinkamu pavadinimu ieškoti pradžios aplanko vidiniuose aplankuose</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation type=\"unfinished\">Įtraukti aplankų pavadinimus</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation type=\"unfinished\">Į paiešką įtraukti vidinių aplankų pavadinimus</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation type=\"unfinished\">Bylos turinye yra:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation type=\"unfinished\">Paieškos tekstas</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation type=\"unfinished\">Paieškos suvestinė</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation type=\"unfinished\">Laukiama.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Ieškoti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation type=\"unfinished\">Pradėti paiešką</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Sustoti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation type=\"unfinished\">Bylos turinys</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation type=\"unfinished\">Vykdoma paieška...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation type=\"unfinished\">Rasta: %1</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation type=\"unfinished\">Parinkite paieškos aplanką</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation type=\"unfinished\">Bylos pavadinimas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation type=\"unfinished\">Aplankas</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation type=\"unfinished\">Rasti:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation type=\"unfinished\">Ieškoti &quot;einant&quot; pirmyn</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation type=\"unfinished\">Ieškoti &quot;einant&quot; atgal</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation type=\"unfinished\">Kritinė Octave klaida</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation type=\"unfinished\">Įvykdytų komandų peržiūra ir paieška.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation type=\"unfinished\">Įvykdyti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation type=\"unfinished\">Sukurti scenarijų (script&apos;ą)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\">Paslėpti atranką</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\">Rodyti atranką</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation type=\"unfinished\">Įveskite paieškos tekstą, pagal kurį bus atrinkti įrašai įvykdytų komandų sąraše</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">Atranka</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Įvykdytos komandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Malonu, kad naudojate Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Atšaukti</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\">&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Atrodo, kad šiame kompiuteryje Jūs pirmą kartą naudojate &quot;Octave&quot; grafikos sąsają.\nNuostatų bylos sukurimui ir &quot;Octave&quot; paleidimui paspauskite &quot;Toliau&quot; mygtuką.&lt;/p&gt;\n&lt;p&gt;Nuostatų bylos vieta: %1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation type=\"unfinished\">Ar tikrai norite uždaryti Octave?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">Įkelti aplinkos kintamuosius</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Apie Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation type=\"unfinished\">Parinkti aplanką</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation type=\"unfinished\">Octave bylos (*.m);;Visos bylos (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\">Nauja funkcija</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation type=\"unfinished\">Naujos funkcijos pavadinimas:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation type=\"unfinished\">Nepavyko rasti &quot;%1&quot; funkcijos</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Byla</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation type=\"unfinished\">Atidaryti...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation type=\"unfinished\">Atidaryti bylą tvarkyklėje</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation type=\"unfinished\">Įkelti aplinkos kintamuosius...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation type=\"unfinished\">Išsaugoti aplinkos kintamuosius kaip...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation type=\"unfinished\">Uždaryti</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation type=\"unfinished\">Naujas</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation type=\"unfinished\">Naujas scenarijus</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation type=\"unfinished\">Nauja funkcija...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">Naujas braižymo langas</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Tvarkyti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Atšaukti</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Įklijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Pažymėti viską</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Išvalyti atminties mainų sritį (clipboard)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\">Rasti bylas...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">Išvalyti komandų langą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Išvalyti įvykdytų komandų sąrašą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Ištrinti aplinkos kintamuosius</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation type=\"unfinished\">Nustatymai...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation type=\"unfinished\">&amp;Derinimas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">Žengti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Žengti į vidų</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">Žengti į išorę</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Tęsti scenarijau vykdymą</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\">Išeiti iš derinimo būvio</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation type=\"unfinished\">&amp;Langas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\">Rodyti komandų langą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">Rodyti įvykdytų komandų langą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Rodyti bylų naršyklę</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">Rodyti aplinkos kintamųjų langą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">Rodyti tvarkyklės langą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">Rodyti dokumentacijos langą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\">Rodyti kintamųjų tvarkyklės langą</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Komandų langas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Įvykdytos komandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Bylų naršyklė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Aplinkos kintamieji</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Dokumentacija</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\">Kintamųjų tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Pagalba</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Pranešti apie klaidą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Octave paketai</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation type=\"unfinished\">Paremti Octave</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation type=\"unfinished\">Diske</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation type=\"unfinished\">Octave tinklapyje</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation type=\"unfinished\">&amp;Naujienos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Octave laidos pastabos</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Bendruomenės naujienos</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation type=\"unfinished\">Įrankių juosta</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation type=\"unfinished\">Įveskite aplanko pavadinimą</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation type=\"unfinished\">Einamasis aplankas: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\">&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nNeprieinamas Octave bendruomenės naujienų šaltinis.\n&lt;/p&gt;\n&lt;p&gt;\nKai turėsite priėjimą prie interneto, paskutines naujienas galėsite paržiūrėti čia: \n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt; (nuoroda atsidaro išorinėje naršyklėje).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Octave kūrėjai, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation type=\"unfinished\">Pagalba apie</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation type=\"unfinished\">Dokumantacija apie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation type=\"unfinished\">Tvarkyti</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation type=\"unfinished\">dbstop() jei ...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation type=\"unfinished\">Norėdami pakeisti visus &quot;%2&quot;, esančius &quot;%3&quot;, paspauskite &quot;%1&quot;.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">Sukurti</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Atšaukti</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">Nėra &quot;%1&quot;\nbylos. Ar norite tokią sukurti?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Octave tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation type=\"unfinished\">Funkcijų aplankuose nėra &quot;%1&quot; bylos. Tvarkomos funkcijos įvykdymui ar derinimui reikia &quot;%2&quot; aplanaką padaryti darbiniu arba pridėti prie funkcijų aplankų sąrašo.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation type=\"unfinished\">Funkcijų aplankuose jau yra &quot;%1&quot; byla. Tvarkomos funkcijos įvykdymui ar derinimui reikia &quot;%2&quot; aplanaką padaryti darbiniu.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation type=\"unfinished\">Aplanaką padaryti darbiniu arba pridėti prie funkcijų aplankų sąrašo</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation type=\"unfinished\">&amp;Aplanką padaryti darbiniu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation type=\"unfinished\">&amp;Pridėti prie funkcijų aplankų sąrašo</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation type=\"unfinished\">Byla &quot;%1&quot;, kurioje saugomos Octave laidos pastabos, yra tuščia.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation type=\"unfinished\">Byla &quot;%1&quot;, kurioje saugomos Octave laidos pastabos, negali būti nustaitytas.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation type=\"unfinished\">Octave laidos pastabos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\">Išsaugoti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation type=\"unfinished\">Teksto spalva</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation type=\"unfinished\">Pažymėto teksto spalva</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation type=\"unfinished\">Pažymėto fono spalva</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation type=\"unfinished\">visuotinas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation type=\"unfinished\">Numatytieji</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation type=\"unfinished\">stačias brūkšnys</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation type=\"unfinished\">stačiakampis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation type=\"unfinished\">gulsčias brūkšnys</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation type=\"unfinished\">Nustatyti naujai paleistos Octave darbo aplanką</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation type=\"unfinished\">Nustatyti pradinį bylų naršyklės aplanką</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation type=\"unfinished\">Octave sparčiųjų klavišų rinkinių byla (*.osc);;Visos bylos (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation type=\"unfinished\">Perrašomi sparčiųjų klavišų rinkiniai</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation type=\"unfinished\">Jūs ruošiatės perrašyti visus sparčiųjų klavišų rinkinius.\nNorite išsaugoti esamus sparčiųjų klavišų rinkinius ar atšaukti veiksmą?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation type=\"unfinished\">Nesaugoti</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Bendruomenės naujienos</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Ankstesnis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Atšaukti</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\">&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Octave bendruomenės naujienos tikrinamos kaskart paleidus Octave.\nTikrinimas atliekamas ne daugiau kaip vieną kartą per dieną, o naujienos rodomos tik tada, jei nuo paskutinio naujienų peržiūrėjimo yra kažkas naujo.&lt;/p&gt;\n&lt;p&gt;Naujienas taip pat galite matyti pasirinkę menių punktą &quot;Pagalba =&gt; Bendruomenės naujienos&quot; arba apsilankius\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt; tinklapyje.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\">Išvalyti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation type=\"unfinished\">Padaryti numatytu</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation type=\"unfinished\">Pasikartojantis sparčiųjų klavišų rinkinys</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation type=\"unfinished\">Visuotinas</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation type=\"unfinished\">Koretelių tvarkymas &quot;prisegtuose&quot; languose</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Malonu, kad naudojate GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Malonu, kad naudojate Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Komandų langas</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation type=\"unfinished\">Atkurti geometriją</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation type=\"unfinished\">&quot;Persegti&quot; langą</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\">Kintamųjų tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation type=\"unfinished\">Tvarkyti kintamuosius.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation type=\"unfinished\">Kintamųjų tvarkyklės įrankių juosta</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\">Išsaugoti</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation type=\"unfinished\">Kintamąjį išsaugoti byloje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Iškirpti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation type=\"unfinished\">Iškirptus duomenis patalpinti į atminties mainų sritį (clipboard)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation type=\"unfinished\">Duomenų kopiją patalpinti į atminties mainų sritį (clipboard)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Įklijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation type=\"unfinished\">Į kintamojo vetę įrašyti atminties mainų srities (clipboard) duomenis</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation type=\"unfinished\">Atvaizduoti grafiškai</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation type=\"unfinished\">Pažymėtus duomenis atvaizduoti garfiškai</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation type=\"unfinished\">Pažymėtus duomenis atvaizduoti garfiškai</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation type=\"unfinished\">Vienu lygiu aukštyn</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation type=\"unfinished\">Kintamojo sandaroje pereiti vienu lygiu aukščiau</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation type=\"unfinished\">Kintamąjį &quot;%1&quot; išsaugoti kaip</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Iškirpti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Įklijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\">Išvalyti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\">Pašalinti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation type=\"unfinished\">Sukurti kintamąjį iš pažymėtų duomenų</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation type=\"unfinished\">Transponuoti</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Malonu, kad naudojate GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation type=\"unfinished\">Pavadinimas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Klasė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Išmatavimai</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Vertė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">Savybė</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation type=\"unfinished\">Kopijavimui, pervardinimui ar išvedimui spauskite dešinį pelės myguką</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation type=\"unfinished\">kompleksinis</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Klasė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Išmatavimai</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Vertė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">Savybė</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Aplinkos kintamieji</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation type=\"unfinished\">Aplinkos kintamųjų sąrašas.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation type=\"unfinished\">Įveskite tekstą pagal kurį bus atrinkti kintamieji</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">Atranka</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation type=\"unfinished\">Aplinkos kintamųjų sąrašas.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation type=\"unfinished\">Kintamųjų savybių spalvos paaiškinimai:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation type=\"unfinished\">Rodyti kintamųjų tvarkyklėje</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation type=\"unfinished\">Kopijuoti pavadinimą</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation type=\"unfinished\">Kopijuoti vertę</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation type=\"unfinished\">Pervadinti</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation type=\"unfinished\">Gali būti pervadinti tik aukščiausio lygmens ženklai</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\">Paslėpti atranką</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\">Rodyti atranką</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Pagrindiniai</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>tik Octave logotipas</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>logotipas su raide</translation>\n    </message>\n    <message>\n        <location line=\"-334\"/>\n        <source>Dock widget title bar</source>\n        <translation>&quot;Prisegto&quot; lango antraštė</translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation>mažas</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>didelis</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>Vartotojo stilius</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation type=\"unfinished\">Erdvinis vaizdas</translation>\n    </message>\n    <message>\n        <location line=\"+565\"/>\n        <source>Editor</source>\n        <translation>Tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Tinka tik &quot;monospaces&quot; šriftams. Linijos vieta priklauso nuo tarpo ženklo pločio.&lt;/br&gt;Linija gali nesutapti su tikrąja perkėlimo vieta, kai naudojami proporciniai šriftai arba jei naudojami įvairių dydžių ir stilių (pastorintas, pasviręs ir pan.) šriftai dydžiai.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Galimas kodo blokų sutraukimas</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Rodyti horizontalią slinkties juostą</translation>\n    </message>\n    <message>\n        <location line=\"-516\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+494\"/>\n        <source>Show tool bar</source>\n        <translation>Rodyti įrankių juostą</translation>\n    </message>\n    <message>\n        <location line=\"+221\"/>\n        <source>Rotated tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\">Padėtis</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+260\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Perkelti eilutės turinį į sekančią eilutę ties lango riba</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Indentation</source>\n        <translation>Įtraukos</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation>Įtraukų plotis</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Tab įtraukia liniją</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Savaiminis įtaukimas</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Ženklo &quot;TAB&quot; plotis</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Rodyti įtraukų linijas</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Klavišo &quot;BackSpace&quot; paspaudimas mažina įtrauką</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Įraukoms naudoti &quot;TAB&quot; ženklus</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation>Savaiminis užbaigimas</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>Raktiniai žodžiai</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Skirti didžiasas ir mažasias raides</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Pakeisti žodį siūlomu</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Žodžiai panaudoti byloje</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation>Į Octave &quot;įdėti&quot; žodžiai</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Octave funkcijos</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Savaime rodyti galimų užbaigimų sąrašą</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Be paklausimo iš naujo įkelti bylų turinį, kuris buvo pakeistas kitų programų</translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation>Naudoti išorinę bylų tvarkyklę</translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Naudojama koduotė įkeliant ir saugant bylas</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation>Vaizdavimas tvarkyklėje</translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(pakeitus dydį išvalomas atliktų komandų sąrašas)</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation>Atliktų komandų sąrašo dydis</translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Šriftas</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Rodyti eilučių numerius</translation>\n    </message>\n    <message>\n        <location line=\"-866\"/>\n        <source>Interface</source>\n        <translation>Aplinka</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Patvirtinti Octave uždarymą</translation>\n    </message>\n    <message>\n        <location line=\"-72\"/>\n        <source>Graphic icons</source>\n        <translation>išskirtinis</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Rodyti būvio juostą</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Tekstas: nesužadinto</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>einamojo</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Background inactive</source>\n        <translation>Fonas: nesužadinto</translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation>Octave paleisties nustatymai</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Naršyti</translation>\n    </message>\n    <message>\n        <location line=\"-1305\"/>\n        <source>Show whitespace</source>\n        <translation>Rodyti tarpo ženklus</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Nerodyti tarpo ženklų, kurie naudojami įtraukose</translation>\n    </message>\n    <message>\n        <location line=\"+1125\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Be paklausimo sukurti trūkstamas bylas</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>užklausos eilutė (%f=byla, %l=eilutė):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Žymeklio tipas:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Naudoti teksto spalvą</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Šrifto dydis</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Bylų naršyklė</translation>\n    </message>\n    <message>\n        <location line=\"-2031\"/>\n        <source>Normal</source>\n        <translation>įprastas</translation>\n    </message>\n    <message>\n        <location line=\"+359\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Šie nustatymai taikomi po bet kokių .octaverc nustatymo bylų paleisties.</translation>\n    </message>\n    <message>\n        <location line=\"+540\"/>\n        <source>Show EOL characters</source>\n        <translation>Rodyti eilutės pabaigos ženklą</translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation>Numatytasis eilutės pabaigos ženklas</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Sąrašą rodyti, jei žodį sudaro sekantis ženklų kiekis: </translation>\n    </message>\n    <message>\n        <location line=\"-1812\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">Nustatymai</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\">Komanda</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Numerių ir tvarkyklės šriftų dydžių skirtumas</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Paryškinti visus žodžio, kuris pažymėtas dvigubu pelės paspaudimu, pasikartojimus</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Komentarai (tik Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Ženklai, kurie bus pašalinti įvykdžius atkomentavimo veiksmą</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Ženklai naudojami pažymėtos srities užkomentavimui</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Ilgos eilutės</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Tęsti naujoje eilutėje, jei viršijamas eilutės ilgis</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Tęsti naujoje eilutėje tik komentarus</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Eilutės ilgis</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Rodyti ilgos eilutės pabaigos žymę</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>kaip linija</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>ypatinga fono spalva</translation>\n    </message>\n    <message>\n        <location line=\"+191\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Po &quot;if&quot; ir pan., savaime</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>nieko neįterpti</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>įterpti &quot;endif&quot; ir pan.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>įterpti &quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Darbas su bylomis</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Atkurti vėliausiai naudotas tvarkyklės korteles, kai Octave naujai paleidžiama arba kai tampa matomas tvarkyklės langas</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-47\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Uždaryti visas bylas, kai uždaroma/išjungiama tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pasirinkite šriftą, šrifto dydį (kaip skirtumą nuo numatytojo dydžio), šrifto stilių (pa&lt;b&gt;r&lt;/b&gt;yškintas, pa&lt;b&gt;s&lt;/b&gt;viręs, pa&lt;b&gt;b&lt;/b&gt;rauktas), teksto ir fono spalvą (šviesi alyvinė spalva (255,0,255) nurodo, kad naudoti numatytąją spalvą).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Behavior</source>\n        <translation>Elgsena</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Atkurti vėliausiai naudotą aplanką</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Bylų, kurios atveriamos numatytaja teksto tvarkykle, plėtiniai (atskiriami kabliataškiu, t.y. &quot;;&quot;):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Aplinkos kintamieji</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Kintamųjų savybių spalvos</translation>\n    </message>\n    <message>\n        <location line=\"+287\"/>\n        <source>Import shortcut set</source>\n        <translation>Įkelti sparčiųjų klavišų rinkinius</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Išsaugoti esamus sparčiųjų klavišų rinkinius</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Naudoti numatytuosius sparčiųjų klavišų rinkinius</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Numatytasis</translation>\n    </message>\n    <message>\n        <location line=\"+232\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-227\"/>\n        <source>Actual</source>\n        <translation>Einamasis</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Tinklas</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Leisti prisijungti prie Octave svetainės, kad gauti naujausius duomenis</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Naudoti proxy serverį</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Kintamųjų tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Numatytasis eilutės auktšis</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Numatytasis stulpelio plotis</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>Use Command Window font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Kintamųjų tvarkyklės spalvos</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Kas antrą eilutę vaizduoti su skirtinga fono spalva</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Visada suvienodinti Octave darbo aplanką su einamuoju bylų naršyklės aplanku</translation>\n    </message>\n    <message>\n        <location line=\"+348\"/>\n        <source>Shortcuts</source>\n        <translation>Sparčiųjų klavišų rinkiniai</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Export</source>\n        <translation>Išsaugoti</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Įkelti</translation>\n    </message>\n    <message>\n        <location line=\"-44\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Veiksmas</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Kompiuterio vardas:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Proxy tipas:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Portas:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Vartotojo vardas:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Slaptažodis:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation type=\"unfinished\">Nauja byla</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\">Nauja funkcija</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">Naujas braižymo langas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation type=\"unfinished\">Atidaryti bylą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">Įkelti aplinkos kintamuosius</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation type=\"unfinished\">Uždaryti Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Kopijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Įklijuoti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Atšaukti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\">Pažymėti viską</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Išvalyti atminties mainų sritį (clipboard)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation type=\"unfinished\">Bylose rasti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">Išvalyti komandų langą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Išvalyti įvykdytų komandų sąrašą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Ištrinti aplinkos kintamuosius</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">Nustatymai</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">Žengti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Žengti į vidų</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">Žengti į išorę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\">Tęsti scenarijau vykdymą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\">Išeiti iš derinimo būvio</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\">Rodyti komandų langą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\">Rodyti įvykdytų komandų langą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Rodyti bylų naršyklę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\">Rodyti aplinkos kintamųjų langą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\">Rodyti tvarkyklės langą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\">Rodyti dokumentacijos langą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\">Rodyti kintamųjų tvarkyklės langą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Komandų langas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Įvykdytos komandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Bylų naršyklė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Aplinkos kintamieji</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Dokumentacija</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\">Kintamųjų tvarkyklė</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation type=\"unfinished\">Rodyti internete esančią dokumentaciją</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Pranešti apie klaidą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Octave paketai</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation type=\"unfinished\">Prisidėti prie Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation type=\"unfinished\">Octave kūrėjų ištekliai</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Apie Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Octave laidos pastabos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Bendruomenės naujienos</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation type=\"unfinished\">Uždaryti kortelę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation type=\"unfinished\">Uždaryti visas korteles</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation type=\"unfinished\">Uždaryti kitas korteles</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation type=\"unfinished\">Pereiti į kairiąją kortelę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation type=\"unfinished\">Pereiti į dešiniąją kortelę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation type=\"unfinished\">Perstumti kortelę į kairę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation type=\"unfinished\">Perstumti kortelę į dešinę</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">Padidinti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">Sumažinti</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation type=\"unfinished\">Įprastas mastelis</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation type=\"unfinished\">Tvarkyti funkciją</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation type=\"unfinished\">Išsaugoti bylą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation type=\"unfinished\">Išsaugoti bylą kaip</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation type=\"unfinished\">Spausdinti</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation type=\"unfinished\">Naikinti atšaukimą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Iškirpti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation type=\"unfinished\">Surasti ir pakeisti</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation type=\"unfinished\">Surasti sekantį</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation type=\"unfinished\">Surasti ankstesnį</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">Trinti iki žodžio pradžios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">Trinti iki žodžio pabaigos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">Trinti iki eilutės pradžios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">Trinti iki eilutės pabaigos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">Kopijuoti eilutę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">Iškirpti eilutę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">Dvigubinti pažymėtą sritį/eilutę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">Sukeisti eilutes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation type=\"unfinished\">Rodyti automatinio užbaigimo sąrašą</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation type=\"unfinished\">Užkomentuoti pažymėtą sritį</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation type=\"unfinished\">Atkomentuoti pažymėtą sritį</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation type=\"unfinished\">Užkomentuoti pažymėtą sritį nurodant komentavimo ženklą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation type=\"unfinished\">Pažymėtos srities raides pakeisti didžiosiomis raidėmis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation type=\"unfinished\">Pažymėtos srities raides pakeisti mažosiomis raidėmis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation type=\"unfinished\">Pažymėtą sritį padaryti su įtraukomis</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\">Šalinti pažymėtos srities įtraukas</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\">Kodą padaryti su įtraukomis</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation type=\"unfinished\">Eilučių pabaigos ženklus perversti į Wondows formatą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation type=\"unfinished\">Eilučių pabaigos ženklus perversti į Unix formatą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation type=\"unfinished\">Eilučių pabaigos ženklus perversti į Mac formatą</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation type=\"unfinished\">Pereiti į eilutę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\">Pereiti į priešingą skliaustelių poros pusę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\">Pažymėti skliaustelių poros turinį</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation type=\"unfinished\">Pridėti/nuimti žymelę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation type=\"unfinished\">Sekanti eilutė su žymele</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation type=\"unfinished\">Ankstesnė eilutė su žymele</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation type=\"unfinished\">Pašalinti visas žymeles</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation type=\"unfinished\">Vaizdavimo nustatymai</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation type=\"unfinished\">Rodyti eilučių numerius</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation type=\"unfinished\">Rodyti tarpo ženklą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation type=\"unfinished\">Rodyti eilutės pabaigos ženklus</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation type=\"unfinished\">Rodyti įtraukų linijas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation type=\"unfinished\">Rodyti ilgos eilutės pabaigos žymę</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation type=\"unfinished\">Rodyti įrankių juostą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation type=\"unfinished\">Rodyti būvio juostą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation type=\"unfinished\">Rodyti horizontalią slinkties juostą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation type=\"unfinished\">Pridėti/nuimti sustojimo tašką</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation type=\"unfinished\">Sekantis sustojimo taškas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation type=\"unfinished\">Ankstesnis sustojimo taškas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation type=\"unfinished\">Pašalinti visus sustojimo taškus</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation type=\"unfinished\">Vykdyti bylą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\">Vykdyti pažymėtą kodą</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation type=\"unfinished\">Pagalba pagal raktinį žodį</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation type=\"unfinished\">Dokumentacija pagal raktinį žodį</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/nl_NL.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"nl_NL\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Ongeldige bestandsnaam</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Verschil met standaardgrootte</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Achtergrondkleur; roze (255,0,255) staat voor standaardkleur}</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>d</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>s</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>o</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>Bewerk &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Hulp over &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Documentatie over &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Kopiëer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Plak</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Selecteer Alles</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Voer selectie uit</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>Bewerk selectie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>Hulp over selectie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>Documentatie over selectie</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Veeg venster schoon</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Bewerk %1 op regel %2</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>selectie is naar klembord gekopieerd</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>Standaardfont</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Fout</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Getal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Trefwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Tekst tussen dubbele aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Tekst tussen aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operator</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identifier</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Scalair getal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>Geëxpandeerde parameter</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Backticks</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Here document scheidingsteken</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Here document tussen aanhalingstekens</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>Standaardfont</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Trefwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>Label</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>Verberg opdrachtteken</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>Externe opdracht</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Variabele</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operator</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>Standaardfont</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>Inactieve standaardfont</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>C commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>Inactief C commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>C++ commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>Inactief C++ commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>C commentaar in JavaDoc-stijl</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>Inactief C commentaar in JavaDoc-stijl</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Getal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Inactief getal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Trefwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Inactief trefwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Tekst tussen dubbele aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>Inactieve tekst tussen dubbele aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Tekst tussen aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>Inactieve tekst tussen aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>Inactieve IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>Preprocessor blok</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>Inactief preprocessor blok</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operator</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Inactieve operator</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identifier</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Inactieve identifier</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>Niet afgesloten tekst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>Inactieve niet afgesloten tekst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>C# letterlijke tekst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>Inactieve C# letterlijke tekst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>Javascript reguliere expressie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>Inactieve Javascript reguliere expressie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>C++ commentaar in JavaDoc-stijl</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>Inactief C++ commentaar in JavaDoc-stijl</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>Secundaire trefwoorden en identifiers</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Inactieve secundaire trefwoorden en identifiers</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>JavaDoc sleutelwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>Inactief JavaDoc sleutelwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>JavaDoc fout trefwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>Inactief fout JavaDoc trefwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Globale klassen en typedefs</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Inactieve globale klassen en typedefs</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>C++ ruwe tekst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>Inactieve C++ ruwe tekst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation>Vala tekst tussen driedubbele aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation>Inactieve Vala tekst tussen driedubbele aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation>Pike tekst tussen hashtekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation>Inactieve Pike tekst tussen hashtekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation>Pre-processor C-commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation>Inactief pre-processor C-commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation>Javadoc-stijl preprocessor-commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation>Inactief Javadoc-stijl preprocessor-commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation>Door gebruiker gedefinieerde tekst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation>Inactieve door gebruiker gedefinieerde tekst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation>Taakmarkering</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation>Inactieve taakmarkering</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation>Stuurcode</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation>Inactieve stuurcode</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>Standaardfont</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Opdracht</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>Koptekst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Positie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Verwijderde regel</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Toegevoegde regel</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Gewijzigde regel</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation>Toegevoegde uitbreidingspatch</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation>Verwijderde uitbreidingspatch</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation>Toegevoegde verwijderpatch</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation>Verwijderde verwijderpatch</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>Standaardfont</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Opdracht</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Getal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Trefwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Tekst tussen aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operator</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identifier</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Tekst tussen dubbele aanhalingstekens</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>Standaardfont</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Fout</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Getal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Trefwoord</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Tekst tussen dubbele aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Tekst tussen aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operator</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identifier</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Scalair getal</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>Array</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>Hash</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Symbooltabel</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>Reguliere expressie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>Vervanging</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Backticks</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>Data sectie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Here document scheidingsteken</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Here document tussen aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>Here document tussen dubbele aanhalingstekens</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>Backtick here document</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>Tekst tussen aanhalingstekens (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>Tekst tussen aanhalingstekens (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>Tekst tussen aanhalingstekens (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>Tekst tussen aanhalingstekens (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>Tekst tussen aanhalingstekens (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>POD letterlijk</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>Subroutine prototype</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>Sjabloon identifier</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>Sjabloon inhoud</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>Tekst tussen dubbele aanhalingstekens (geïnterpoleerde variabele)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>Vertaling</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>Reguliere expressie (geïnterpoleerde variabele)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>Vervanging (geïnterpoleerde variabele)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>Backticks (geïnterpoleerde variabele)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>Here document tussen dubbele aanhalingstekens (geïnterpoleerde variabele)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>Backtick here document (geïnterpoleerde variabele)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>Tekst tussen aanhalingstekens (qq, geïnterpoleerde variabele)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>Tekst tussen aanhalingstekens (qx, geïnterpoleerde variabele)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>Tekst tussen aanhalingstekens (qr, geïnterpoleerde variabele)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>&amp;Ongedaan maken</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>He&amp;rhalen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>Kni&amp;ppen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Kopiëren</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>&amp;Plakken</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Verwijderen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Selecteer Alles</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Open koppeling</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Kopieer koppelingadres</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Stuur email naar ...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>Kopieer emailadres</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Bewerk %1 op regel %2</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Annotatie</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Tekst</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>String</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Lettertype</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>vetgedrukt</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>v</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>schuin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>s</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>kleur</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>links</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>midden</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>rechts</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>horizontale uitlijning</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>verticale uitlijning</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>boven</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>onder</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Positie</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Breedte</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Hoogte</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>eenheden</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>genormeerd</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Pas in rechthoek</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Rechthoek</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Achtergrond</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Rand</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Lijnstijl</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>geen</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Lijnbreedte</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Selecteer Alles</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Pauzeer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Stop</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Hervatten</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Opdracht Widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Octave Community Nieuws</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>Standaardfont</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Fout</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>Prompt</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Octave Documentatie</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>Kon de help collectie niet naar een tijdelijk\nbestand kopiëren. De zoekfunctie kan beïnvloed zijn.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>kon de data voor documentatie browser niet\ninstalleren, misschien ontbreekt de Qt SQlite\nmodule?\nAlleen de hulptekst in het commando venster\nis beschikbaar.</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>Inhoud</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Geef tekst op om in functie-index te zoeken</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Zoek</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>Functie-index</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Bladwijzers</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>Naar begin</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Ga terug</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Voorgaande pagina&apos;s</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>Ga vooruit</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Volgende pagina&apos;s</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Zoek</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Vergroten</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Verkleinen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Naar begingrootte</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>Maak bladwijzer naar huidige pagina</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>Kan helpbestand %1 niet registreren.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nGeen documentatiebladwijzers geladen!</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: documentatie bladwijzers inlezen</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Geef zoektekst in bladwijzers op</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Filter</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Nieuwe map</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Open</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>He&amp;rnoem</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>&amp;Verwijder</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>M&amp;ap toevoegen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>Verberg &amp;filter</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>Toon &amp;filter</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: Documentatiebladwijzers bewaren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>Kan bestand %1 niet beschrijven:\n%2.\n\nDocumentatie bladwijzers niet opgeslagen!\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>Kan bestand %1 niet lezen:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>Geen beginelement gevonden in %1.\nOngeldig bladwijzerbestand?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>Het bestand \n%1\nis geen geldig XBEL versie 1.0 bestand.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Onbekende titel</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Documentatie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Kijk in de documentatie voor hulp.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Sluit bestand</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>Sluit &amp;Alle</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>Sluit &amp;Andere</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>Schakel naar &amp;Linker widget</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>Schakel naar &amp;Rechter widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation>Bestanden open in editor</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation>Klik voor focus op bestand in editor</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Sluit bestand</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>Sluit &amp;Alle</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Voer uit</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Kies huidige &amp; map</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>Kon externe editor niet starten\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Er is nog geen externe editor ingesteld.\nWilt u de voorkeursinstellingen aanpassen?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Doorgaan</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Sla Bestand op en Voer uit</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>Bestand niet opgeslagen! Een bestand met de geselecteerde naam\n%1\nis al geopend in the editor.</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>Het bijbehorende editortabblad is verdwenen.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>kon bestand\n%1\nniet openen voor lezen: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Bestand\n%1\nbestaat niet. Wilt u het aanmaken?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Maak nieuw</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annuleren</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>Kon bestand\n%1\nniet openen voor schrijven: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Bestand</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>&amp;Recent geopende bestanden</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>&amp;Pas Functie Aan</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>Op&amp;slaan</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>Opslaan &amp;als...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Sluit bestand</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Alle bestanden sluiten</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Andere bestanden sluiten</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Afdrukken...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>B&amp;ewerken</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>He&amp;rhalen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>Kni&amp;ppen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>&amp;Zoek en Vervang...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>Zoek &amp;volgende</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>zoek Vori&amp;ge</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>&amp;Opdrachten</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Verwijder regel</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Kopieer regel</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Knip regel</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Wis tot begin van woord</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Wis tot einde van woord</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Wis tot begin van regel</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Wis tot einde van regel</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Dubbele Selectie/Regel</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Transponeer regel</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>&amp;Toon aanvullijst</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Formaat</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>&amp;Hoofdletters</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>Kleine &amp;letters</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>Zet om naar &amp;commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>Zet om &amp;naar code</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Commentaar (kies string)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>Laat selectie &amp;inspringen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>Laat selectie &amp;terug inspringen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Code laten inspringen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Zet regeleindes om naar &amp;Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Zet regeleindes om naar &amp;Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Zet regeleindes om naar Legacy &amp;Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>Navi&amp;geer</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>Ga naar &amp;regel...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Spring naar bijbehorende accolade</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Selecteer tot bijbehorende accolade</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>Volge&amp;nde bladwijzer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>&amp;Vorige bladwijzer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>&amp;Bladwijzer invoegen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>Alle bladwijzers ve&amp;rwijderen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Voorkeuren...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>&amp;Stijlvoorkeuren...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>&amp;Weergave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>&amp;Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>Toon rege&amp;lnummers</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>Toon &amp;witruimte-tekens</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Toon &amp;regeleindes</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>Toon &amp;inspringraster</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>Toon lange-regel &amp;markering</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>Toon &amp;Taakbalk</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>Toon &amp;Statusbalk</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>Toon &amp;Horizontale Schuifbalk</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>&amp;Vergroten</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>&amp;Verkleinen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>&amp;Normale grootte</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>Tabs alfabetisch &amp;sorteren</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Debuggen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>Toggle &amp;onderbrekingspunt</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>Volge&amp;nd onderbrekingspunt</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>&amp;Vorig onderbrekingspunt</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>Verwijde&amp;r alle onderbrekingspunten</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>Uitvoe&amp;ren</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Sla bestand op en voer uit/ga door</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>Geselecteerde tekst &amp;uitvoeren</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Sla bestand op en voer alle &amp;tests uit</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Sla bestand op en voer alle &amp;Demos uit</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Hulp</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>&amp;Hulp bij sleutelwoord</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>&amp;Documentatie over sleutelwoord</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>Recente bestanden</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Volledig &amp;pad kopiëren</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>regel:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>kolom:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>codering:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>eol:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Onderbrekingspunt voorwaarde</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>FOUT: </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>Kan geen onderbrekingspunt instellen in een veranderd of nog niet benoemd bestand.\nOpslaan en onderbrekingspunt toevoegen, of Terug?</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Ga naar regel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Regelnummer</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Geselecteerde tekst omzetten naar commentaar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Te gebruiken commentaar string:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;naamloos&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>Wilt u het afsluiten afbreken, opslaan, of de wijzigingen negeren?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>Het bestand\n\n  %1\n\ndat zou worden gesloten is ondertussen gewijzigd.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>Kan bestand &apos;%1&apos;\nniet lezen met de geselecteerd karakter codering &apos;%2&apos;: %3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>Er was een probleem met het lezen van bestand\n\n%1\nmet de gekozen codering %2\n\nWijzigen en opslaan van het bestand kan leiden tot gegevensverlies!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>&amp;Bewerk evengoed</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>&amp;Verander codering</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Sluit bestand</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Kies nieuwe standaard codering</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Kies een andere codering\nom het bestand opnieuw mee te lezen.\n\nDit heeft geen invloed op de standaard codering.\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Debug of Opslaan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Dit bestand wordt momenteel uitgevoerd.\nDebuggen afsluiten en opslaan?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>kon bestand %1 niet openen voor schrijven:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>De wijzigingen konden niet worden opgeslagen in bestand\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Octave bestanden (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Alle bestanden (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>&quot;%1&quot;\nis geen geldige identifier.\n\nAls je deze bestandsnaam houdt, kan je dit script \nniet aanroepen met z&apos;n naam als Octave commando.\n\nWil je een andere naam kiezen?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>De huidige inhoud van de editor kan niet\nworden gecodeerd met de huidige codering %1.\nToch toepassen zou leiden tot gegevensverlies!\n\nKies s.v.p.een andere encoding!</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1\n bestaat al.\nWil je het overschrijven?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nOpgelet: Het bestand in de editor is gewijzigd!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>Het lijkt erop dat &apos;%1&apos; is gewijzigd door een ander programma. Wil je het opnieuw laden?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>Het lijkt er op dat bestand\n%1\nis gewist of hernoemd. Wil je het nu opslaan?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Bestandsgrootte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Bestandstype</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Laatst gewijzigd</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Toon verborgen bestanden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Alternerende regelkleuren</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Voer pad- of bestandsnaam in</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Eén mapniveau omhoog</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Toon Octave werkmap</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Ga naar huidige Octave map</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Stel Octave map in</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Stel huidige browsermap in als Octave map</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Bewerkingen op huidige map</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Toon home directory</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Stel browser map in...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Zoek bestanden...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Nieuw bestand...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Nieuwe map...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Dubbelklik om map te openen, rechts-klik voor andere opties</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Hernoemen...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Open</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Openen in Systeem Bestandsverkenner</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Openen in Tekstverwerker</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Kopieer selectie naar klembord</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Voer uit</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Lees data in</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Stel huidige map in</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Aan zoekpad toevoegen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Gekozen directories</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Gekozen directories en subdirectories</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Uit zoekpad verwijderen</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Weggooien...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Wis bestand/map</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>Weet je zeker dat je alle %1 bestanden wil wissen?\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>Weet u zeker dat u dit wilt verwijderen\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>Kan een niet-lege map niet wissen</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Fout bij verwijderen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>Kon bestand &quot;%1&quot; niet verwijderen.</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Stel file browser map in</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Maak nieuw bestand</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Maak nieuw bestand in\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Nieuw bestand.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Fout bij het aanmaken van bestand</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>Kan bestand\n“%1”\nniet maken.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Maak nieuwe map</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Maak nieuwe map in\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Nieuwe map</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>Kon bestand &quot;%1&quot; niet hernoemen naar &quot;%2&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Bestandsbrowser</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Verken bestanden</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>bestands systeem</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>editor bestanden</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>Veel plezier!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Vorige</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Voltooien</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annuleren</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hopen dat u Octave nuttig vindt.&lt;/p&gt;\n&lt;p&gt;Als u problemen ondervindt zijn er meerdere manieren om hulp te krijgen, waaronder commerciele opties, een discussiesite, een wiki en andere door de gebruikers gemeenschap ondersteunde platforms.\nU kunt meer informatie over elk van deze mogelijkheden vinden op &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opent in externe browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Voor meer informatie over Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Ga naar &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opent in externe browser)&lt;/li&gt;\n&lt;li&gt;Bekijk de documentatie online&lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; of &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; formaat (link opent in externe browser)&lt;/li&gt;\n&lt;li&gt;Open de documentatiebrowser van het Octave GUI in het help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Editor: Zoek en Vervang</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Zoek:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Geef zoektekst op</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>Ver&amp;vang:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>voer vervangende tekst in</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>&amp;Hoofdlettergevoelig</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>Zoek vanaf het &amp;begin</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>Na bestandseinde &amp;doorgaan vanaf begin</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>Zoek &amp;Volgende</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>Zoek Vo&amp;rige</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>Ve&amp;rvang</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>Vervang &amp;Alles</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>&amp;Meer...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>Hele &amp;woorden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>Reguliere &amp;expressies</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>&amp;Terug zoeken</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>In se&amp;lectie zoeken</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Vanaf einde terugzoeken</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Zoek vanaf begin</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Resultaat vervangen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 vervangingen</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Zoek Resultaat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>Geen overeenkomsten meer gevonden</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Zoek bestanden</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Genaamd:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>Begin in:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Geef startmap op</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Bladeren...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Blader naar begin map</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Huidige map</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>Stel huidige map in als startmap</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Zoek in submappen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Zoek ook in onderliggende mappen naar overeenkomende bestanden</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Inclusief submappen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Neem overeenkomende mappen mee in zoekresultaten</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Negeer hfd/kl. letters</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>Doe een case gevoelige match</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>Met tekst:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>Alleen bestanden waarin de gespecificeerde tekst zit in zoekresultaten meenemen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Overeen te komen tekst</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Resultaten: Dubbelklikken opent bestand of stelt de map in</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Zoekresultaten</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>Niet bezig.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Voer de zoekpatronen voor bestandsnamen in.\nMeerdere zoekpatronen kunnen gescheiden worden door\n&apos;;&apos;, b.v. &apos;*.cc ; *.h&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>Zoek</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Begin met zoeken naar overeenkomende bestanden</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Stop</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Stop met zoeken</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>bestandnaam/locatie</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Inhoud van bestand</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>Bezig met zoeken...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 overeenkomst(-en)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Stel zoekmap in</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Bestandsnaam</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Map</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Dubbel klik om bestand te openen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Dubbel klik om map te kiezen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Zoek:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>Zoek voorwaarts</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Zoek achterwaarts</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Sluit</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Sluit zoekdialoog</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Fout %1 bij aanmaken van settings file\n%2\nControleer dat je lees en schrijfpermissie hebt in\n%3\n\nOctave GUI moet nu gesloten worden.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Octave Kritieke Fout</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Bladeren en zoeken door opdrachtgeschiedenis.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Kopiëer</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Werk uit</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Nieuw script</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Verberg filter</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Toon filter</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Dubbelklik op een opdracht om het naar Opdrachtvenster te kopiëren.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Geef zoekpatroon voor filteren van opdrachtgeschiedenis</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Filter</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Opdrachtgeschiedenis</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Welkom bij Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Volgende</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annuleren</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Het lijkt erop dat je de grafische interface van Octave voor het eerst gebruikt op deze computer.\nKlik &apos;Volgende&apos; om een configuratiebestand aan te maken en Octave te starten.&lt;/p&gt;\n&lt;p&gt;Het configuratiebestand is opgeslagen in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Undock widget</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Sluit widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>Zeker weten dat je Octave wil afsluiten?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Sla Werkruimte Op Als</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Werkruimte laden</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>Over Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Blader door mappen</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Octave bestanden (*.m);;Alle bestanden (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Nieuwe Functie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Naam van nieuwe functie:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>%1 is een ingebouwde gecompileerde\nof inline functie en kan niet worden bewerkt.</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>Kan functie %1 niet vinden</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Bestand</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Open...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Open een bestaand bestand in de editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Werkruimte laden...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Sla Werkruimte Op Als...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Afsluiten</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Nieuw</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Nieuw script</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Nieuwe functie...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Nieuwe figuur</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>B&amp;ewerken</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Ongedaan maken</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Kopiëren</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Plakken</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Alles selecteren</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Wis klembord</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Zoek bestanden...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Veeg opdrachtvenster schoon</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Wis opdrachtgeschiedenis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Wis werkruimte</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Pas zoekpad aan ...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Voorkeuren...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>De&amp;buggen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Volgende opdracht</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Stap naar binnen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Stap naar buiten</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Doorgaan</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Verlaat debug modus</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>&amp;Gereedschappen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>Nieuwe &amp;Profilersessie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>Profilersessie he&amp;rvatten</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>Profiler &amp;stoppen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>&amp;Toon profiler data</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>&amp;Venster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Toon opdrachtvenster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Toon opdrachtgeschiedenis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Toon bestandsbrowser</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Toon werkruimte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Toon editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Toon documentatie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Toon Variable Editor</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Opdrachtvenster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Opdrachtgeschiedenis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Bestandsbrowser</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Werkruimte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Documentatie</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Variabele-Editor</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Voorgaande widget</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Herstel standaard window layout</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Help</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Probleem rapporteren</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Octave packages</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>Kom Erbij</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Doneer aan Octave</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>Op schijf</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>Online</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Nieuws</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Release notes</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Community Nieuws</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Werkbalk</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Geef mapnaam op</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Huidige map: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Eén mapniveau omhoog</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community nieuws lijkt niet beschikbaar te zijn.\n&lt;/p&gt;\n&lt;p&gt;\nKijk voor het laatste nieuws op\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nindien je een internetverbinding hebt (link opent in een nieuw scherm).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; De Octave Ontwikkelaars, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOn-line verbinding maken voor het laatste Octave community nieuws is uitgevinkt.\n&lt;/p&gt;\n&lt;p&gt;\nKijk voor het laatste nieuws op\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nindien je een internetverbinding hebt (link opent in een nieuw scherm).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; De Octave Ontwikkelaars, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Verberg Widget</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Dock Widget</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Undock Widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>Help over</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>Documentatie over</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>Edit</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop als ...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>Aanmaken van tijdelijke bestanden is mislukt.\nZorg dat je schrijfrechten hebt in tijdelijke (temp) map.\n%1\n\n%quot;Selectie uitvoeren&quot; gebruikt tijdelijke bestanden.</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>Druk op &apos;%1&apos; om alle voorkomens van &apos;%2&apos; te vervangen door &apos;%3&apos;.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>Standaardfont</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Maak nieuw</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>Annuleren</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Bestand\n%1\nbestaat niet. Wilt u het aanmaken?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Editor</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>Het bestand %1 bestaat niet in het zoekpad.  Om de functie uit te voeren of te debuggen moet je naar de map %2 of die map aan het zoekpad toevoegen.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>Het bestand %1 is afgedekt door een ander bestand met dezelfde naam in het zoekpad. Om de functie die je nu bewerkt uit te voeren of te debuggen moet je naar de map %2.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Ga naar andere map of Voeg map toe aan zoekpad</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>&amp;Ga naar andere map</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>&amp;Voeg map toe aan zoekpad</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>Bestand met release notes &apos;%1&apos; is leeg.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>Bestand met release notes &apos;%1&apos; kan niet worden gelezen.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Octave Release Notes</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Zet Pad</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Alle wijzigingen gaan direct in.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Voeg Map toe ...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Enkele Map</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Map met Submappen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>Verschuif naar bovenaan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>Verschuif naar onderaan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Verschuif omhoog</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Verschuif omlaag</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Verwijder</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Opnieuw laden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Bewaar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Ongedaan maken</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Laatste bewerking ongedaan maken</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Alle bewerkingen ongedaan maken</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Map openen</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>Bovenaan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>Onderaan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>Links</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>Rechts</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Voorgrond</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Achtergrond</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Selectie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>Cursor</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Gekozen, Voorgrond</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Gekozen, Achtergrond</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Alternerende Achtergrond</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>argument</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>globaal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>persistent</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Omgevingsvariabelen</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>Tweede kleurenmodus (licht/donker)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>Schakel naar een tweede kleuren palet.\nBruikbaar voor lichte/donkere modus.\nNiet opgeslagen veranderingen gaan verloren!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>Herlaadt de standaard kleuren,\nafhankelijk van de nu geselecteerde modus.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>Herlaad de standaard stijl waarden,\nafhankelijk van de nu geselecteerde modus.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>Standaard kleuren he&amp;rstellen</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>Standaard stijlen he&amp;rstellen</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Huidige instelling aan het laden ... </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Systeeminstelling</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>I-balkje</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>Blokje</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>Liggend streepje</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>Kleur van uitgelichte huidige regel (magenta (255,0,255) voor automatische kleur)</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Octave Opstartmap Instellen</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Stel bestandsbrowser opstartmap in</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Voorkeuren aan het toepassen ... </translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>Kon %1 niet openen als Octave snelkoppelingenbestand</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Zet attribuutkleuren aan</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Verberg tooltips</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Importeer snelkoppelingen uit bestand...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Octave Sneltoetsbestanden (*.osc);;Alle bestanden (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Exporteer snelkoppelingen naar bestand...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Sneltoetsen overschrijven</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Je staat op het punt om alle sneltoetsen te overschrijven.\nWil je de huidige sneltoetsen opslaan of de actie annuleren?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>Niet opslaan</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Octave GUI voorkeuren</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Community Nieuws</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Vorige</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Volgende</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Annuleren</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Wanneer Octave start zal het optioneel op de Octave web site kijken naar nieuws en informatie over de Octave community.\nDit zal hooguit eenmaal daags geschieden en nieuws wordt alleen weergegeven als er iets nieuws is sinds u voor het laatst het nieuws hebt gezien.&lt;/p&gt;\n&lt;p&gt;U kunt het nieuws ook bekijken door het &quot;Community News&quot; item in het &quot;Help&quot; Menu te selecteren, of door een bezoek te brengen aan\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Sta Octave toe bij het starten te verbinden met de Octave web site zodat actueel nieuws en informmatie over de Octave community getoond kan worden.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Voer nieuwe sneltoets in</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Voer aangepaste sneltoets in\nActie: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Voer sneltoets in door die te typen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Voeg Shift toe\n(kan cijfertoets mee worden aangegeven)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Huidige Sneltoets</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Standaard Sneltoets</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Wis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Maak standaard</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Verdubbel Sneltoets</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>The gekozen sneltoets\n  &quot;%1&quot;\nis al gebruikt voor de actie\n  &quot;%2&quot;.\nWil je de sneltoets toch gebruiken en loskoppelen van de vorige actie?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Globaal</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Bestandsmenu</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Edit menu</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Debug menu</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Gereedschappen Menu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Venster menu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Hulp menu</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Nieuws menu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Gebruik van Dock widgets</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Tabbladgebruik in gedockte widgets</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Zoek &amp; Vervang in dock widgets</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Inzoomen in Editor en Documentatie</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Weergave menu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Uitvoeren menu</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Documentatie browser</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Browser</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>item %1 niet gevonden in sneltoets instelling dialoog</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Welkom bij GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Welkom bij Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Opdrachtvenster</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Dock Widget</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Variabele-Editor: </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Undock Widget</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Herstel geometrie</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Terug docken</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Variabele-Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Variabelen bewerken.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Variabele-Editor Werkbalk</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Bewaar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Sla variabele in een bestand op</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Bewaar in format ...</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Bewaar variabele in bestand in andere indeling</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Knippen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Knip data naar klembord</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Kopiëren</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Kopieer data naar klembord</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Plakken</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Plak klembord in variabele</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Plot</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Plot geselecteerde gegevens</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Plot geselecteerde gegevens</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Omhoog</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>Ga een niveau omhoog in variabele hiërarchie</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>Sla variabele %1 op als</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Knippen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Kopiëren</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Plakken</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Wis</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Verwijderen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Variabele uit selectie</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Transponeren</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> kolommen</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> kolom</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> rijen</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> rij</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Welkom bij GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>Naam</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Klasse</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Waarde</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Eigenschap</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Klik rechts om te kopiëren, hernoemen of weergeven</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>complex</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Klasse</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Waarde</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Eigenschap</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Werkruimte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Bekijk de variabelen in de huidige werkruimte.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Geef patroon voor filteren van werkruimte</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Filter</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Bekijk variabelen in actieve werkruimte.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Kleuren voor eigenschappen van variabelen:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Toon in Variable Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Kopieer naam</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Kopieer waarde</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Hernoemen</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Alleen symbolen uit het bovenste niveau mogen hernoemd worden</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Verberg filter</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Toon filter</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>Kan omgeleide stream met fd = %1 niet openen.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>Kan bufferen op stream met fd = %1 niet uitzetten.</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>Kan &apos;dup&apos; niet op omgeleide stream met fd = %1 toepassen.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>Kan geen pipe maken voor omleiding van stream met fd = %1:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>Kan geen &apos;dup2&apos; toepassen op omgeleide stream met fd = %1\nnaar pipe met fd = %2: %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Fout tijdens luisteren naar omgeleide streams</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation>Fout bij lezen van omgeleide stream met fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\nUitvoer omleiding in </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> zal niet werken.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\nFout: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Algemeen</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Alleen Octave logo</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Letter iconen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Graphic icons</source>\n        <translation>Grafische iconen</translation>\n    </message>\n    <message>\n        <location line=\"-341\"/>\n        <source>Dock widget title bar</source>\n        <translation>Dock widget titelbalk</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Normal</source>\n        <translation>Normaal</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>Custom style</source>\n        <translation>Aangepaste stijl</translation>\n    </message>\n    <message>\n        <location line=\"+244\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Deze voorkeuren worden toegepast na verwerking van .octaverc opstartbestanden.</translation>\n    </message>\n    <message>\n        <location line=\"+353\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+187\"/>\n        <source>Show EOL characters</source>\n        <translation>Toon EOL tekens</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Breek lange regels af op huidige vensterrand</translation>\n    </message>\n    <message>\n        <location line=\"+558\"/>\n        <source>Default EOL mode</source>\n        <translation>Standaard EOL instelling</translation>\n    </message>\n    <message>\n        <location line=\"-503\"/>\n        <source>Indent width</source>\n        <translation>Inspringafstand</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Inspringen met tabtoets</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Automatisch inspringen</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Tab breedte</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Toon inspringraster</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Backspace doet terug inspringen</translation>\n    </message>\n    <message>\n        <location line=\"+120\"/>\n        <source>Match keywords</source>\n        <translation>Zoek overeenkomende sleutelwoorden</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Hoofdlettergevoelig</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Vervang woord door suggestie</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Zoek overeenkomende woorden in document</translation>\n    </message>\n    <message>\n        <location line=\"-643\"/>\n        <source>Use custom file editor</source>\n        <translation>Gebruik een andere editor</translation>\n    </message>\n    <message>\n        <location line=\"+1009\"/>\n        <source>Editor Styles</source>\n        <translation>Editorstijlen</translation>\n    </message>\n    <message>\n        <location line=\"-1485\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Lettertype</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Toon regelnummers</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Show whitespace</source>\n        <translation>Toon witruimte-tekens</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Verberg voor inspringen gebruikte witruimte</translation>\n    </message>\n    <message>\n        <location line=\"+935\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Aantal tekens voordat lijst wordt getoond: </translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Maak nog niet bestaande bestanden aan zonder bevestiging</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>command line (%f=bestand, %l=regel):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Type aanwijzer:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Gebruik voorgrondkleur</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Lettergrootte</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Bestandsbrowser</translation>\n    </message>\n    <message>\n        <location line=\"-2118\"/>\n        <source>Interface</source>\n        <translation>Interface</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Bevestigen voor afsluiten</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Toon statusbalk</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Inactieve tekst</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Actief</translation>\n    </message>\n    <message>\n        <location line=\"-96\"/>\n        <source>Small</source>\n        <translation>Klein</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Groot</translation>\n    </message>\n    <message>\n        <location line=\"+118\"/>\n        <source>Background inactive</source>\n        <translation>Inactieve achtergrond</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation>3D</translation>\n    </message>\n    <message>\n        <location line=\"+206\"/>\n        <source>Octave Startup</source>\n        <translation>Octave opstarten</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Bladeren</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Dit werkt goed met monospaced fonts. De regel wordt weergegeven op een positie gebaseerd op de breedte van een spatie in de standaard-font. Het werkt mogelijk minder goed bij een stijl met proportionele fonts of als vette, schuine en normale tekst met verschillende groottes worden gebruikt.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Te lange regels afbreken</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation>Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Toon horizontale schuifbalk</translation>\n    </message>\n    <message>\n        <location line=\"-970\"/>\n        <source>Preferences</source>\n        <translation>Voorkeuren</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(herstart van Octave nodig)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Gebruik standaard bestandsdialogen</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Werkbalk-iconen</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Taal</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Dock Widgets venster iconen</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Stijl</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Iconenthema (herstart noodzakelijk)</translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation>Knipperende cursor</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Toon welkomst scherm bij opstarten</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Begin-werkmap van Octave&apos;s interpretator</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Ga naar laatste werkmap van vorige sessie</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Opdrachtvenster</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Zet focus op Opdrachtvenster bij uitvoeren van een opdracht vanuit een ander widget</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Geef debuglocatie in Opdrachtvenster weer, evenals markering in editor</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Opdrachtvenster-kleuren</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Show tool bar</source>\n        <translation>Toon werkbalk</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Puntgrootte-verschil met editor font</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Licht huidige regel uit (kleur beneden bij Editorstijlen instelbaar)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Markeer alle voorkomens van een woord dat is geselecteerd met een dubbelklik</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Tabs</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Roteer tabs: Verticaal indien boven- of onderaan en Horizontaal indien links of rechts. De sluitknop wordt niet getoond in geroteerde tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Commentaar (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Beginkarakters voor &quot;uncommenting&quot; tekst</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Beginkarakters voor &quot;commenting&quot; tekst</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Lange regels</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Breek lange regels af op regellengte</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Breek alleen commentaarregels af</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Regellengte</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Lange-regelmarkering</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Verticale lijn</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Achtergrond</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>Indentation</source>\n        <translation>Inspringen</translation>\n    </message>\n    <message>\n        <location line=\"+127\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Inspringen o.b.v. tabs</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Automatisch invoegen na &quot;if&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Niets</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Auto completion</source>\n        <translation>Automatisch aanvullen</translation>\n    </message>\n    <message>\n        <location line=\"+101\"/>\n        <source>With Octave builtins</source>\n        <translation>Met Octave &quot;builtins&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Met Octave functies</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Toon aanvullijst automatisch</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Debugging</source>\n        <translation>Debuggen</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Altijd debug onderbreekpunten en aanwijzers tonen (opent zo nodig het betreffende bestand)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Bestandsbeheer</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Herlaad bestanden die van buitenaf zijn veranderd zonder bevestiging</translation>\n    </message>\n    <message>\n        <location line=\"-50\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Herstel editortabbladen uit vorige sessie bij opstarten of als editor weer getoond wordt na te zijn afgesloten</translation>\n    </message>\n    <message>\n        <location line=\"-31\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Tekst codering gebruikt voor laden en opslaan</translation>\n    </message>\n    <message>\n        <location line=\"+71\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Sluit alle bestanden af als het editorwidget wordt gesloten of verborgen</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>Forceer regeleinde aan eind van bestand bij opslaan</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>Verwijder spaties aan einde van regels bij opslaan bestand</translation>\n    </message>\n    <message>\n        <location line=\"+144\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Kies font, fontgrootte (als verschil met standaardgrootte), font stijl (&lt;b&gt;v&lt;/b&gt;et, &lt;b&gt;s&lt;/b&gt;chuin, &lt;b&gt;o&lt;/b&gt;nderstreept), tekstkleur en achtergrondkleur (magenta (255,0,255) is een opvuller voor de standaard achtergrondkleur).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+848\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - sluit dialoog and pas instellingen toe&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;pas instellingen toe, maar laat dialoog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;sluit dialoog en vergeet niet opgeslagen wijzigingen&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; herlaad de instellingen, niet opgeslagen wijzigingen gaan verloren&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-2254\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Bij aanpassen van de buffergrootte wordt de geschiedenis gewist)</translation>\n    </message>\n    <message>\n        <location line=\"-260\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Indien actief volgt focus van in het hoofdvenster gedockte widgets de muiscursor. Dit is bedoeld om binnen het hoofdvenster hetzelfde &amp;quot;focus follows mouse&amp;quot; gedrag te verkrijgen als in de desktopomgeving.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>Focus volgt muiscursor voor in hoofdvenster gedockte widgets</translation>\n    </message>\n    <message>\n        <location line=\"+285\"/>\n        <source>History buffer Size</source>\n        <translation>Grootte van geschiedenisbuffer</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Rotated tabs</source>\n        <translation>Geroteerde tabs</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Positie</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>Max. tabbreedte in karakters (0: ongelimiteerd)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. tabbreedte in karakters (gemiddelde kar. breedte). Vooral handig voor geroteerde tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+871\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>Bestand openen dialoog gebaseerd op map huidig te editen bestand in plaats van huidige Octave map&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+98\"/>\n        <source>Behavior</source>\n        <translation>Gedrag</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Herstel laatste map van vorige sessie</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>Initiële bestandsbrowser-map\n(alleen indien niet gesynchroniseerd met startmap van Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Bestandsextensies om in de standaard tekstverwerker te kunnen openen (gescheiden door &quot;;&quot;):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Werkruimte</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Kleuren voor eigenschappen van variabelen</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Gebruik font van Opdrachtvenster</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Importeer sneltoetsen</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Exporteer huidige sneltoetsen</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Herstel sneltoetsen naar standaardwaarden</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Standaardinstellingen</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation>Huidig</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Netwerk</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Sta Octave toe om naar de Octave website te gaan om recente informatie en nieuws weer te geven</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Proxy Server</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Kies &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; of &lt;span style=&quot; font-style:italic;&quot;&gt;Omgevingsvariaben&lt;/span&gt;. Ingeval van de laatste optie wordt de proxy overgenomen van de eerste niet-lege omgevingsvariabele ALL_PROXY, HTTP_PROXY of HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Gebruik proxyserver</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Variabele-Editor</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Standaard regelhoogte</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Standaard kolombreedte</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Variabele-Editor Kleuren</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Gebruik alternerende rijkleuren</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Schakel globale sneltoetsen uit om\ninterferentie met readline toetsen te voorkomen.\nUitzonderingen: Ctrl-C om de interpreter te onderbreken\nen de sneltoetsen om naar andere widgets te gaan.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Zet globale snelkoppelingen uit indien Opdrachtvenster focus heeft</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Synchroniseer Octave werkmap met bestandsverkenner</translation>\n    </message>\n    <message>\n        <location line=\"+348\"/>\n        <source>Shortcuts</source>\n        <translation>Sneltoetsen</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Export</source>\n        <translation>Exporteer</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importeer</translation>\n    </message>\n    <message>\n        <location line=\"-44\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Schakel globale sneltoetsen uit om\ninterferentie met readline toetsaanslagen te voorkomen.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>Schakel menutoetsen van hoofdvenster uit indien Opdrachtvenster focus heeft</translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Bewerk een sneltoets door te dubbelklikken in de kolom &apos;Huidig&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Actie</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Hostnaam:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Proxy type:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Poort:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Gebruikersnaam:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Wachtwoord:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Undock/Dock widget</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Sluit widget</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Nieuw bestand</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Nieuwe Functie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Nieuwe figuur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Open bestand</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Werkruimte laden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Sla Werkruimte Op Als</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Octave afsluiten</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Kopiëren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Plakken</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Ongedaan maken</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Alles selecteren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Wis klembord</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>Zoek in bestanden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Veeg opdrachtvenster schoon</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Wis opdrachtgeschiedenis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Wis werkruimte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Pas Zoekpad aan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Voorkeuren</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Volgende opdracht</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>Stap functie binnen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Stap functie uit</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Doorgaan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Verlaat Debug modus</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Profiler sessie starten / stoppen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Profiler sessie hervatten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Profiler resultaten tonen</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Toon opdrachtvenster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Toon opdrachtgeschiedenis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Toon bestandsbrowser</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Toon werkruimte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Toon editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Toon documentatie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Toon Variabele-Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Opdrachtvenster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Opdrachtgeschiedenis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Bestandsbrowser</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Werkruimte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Documentatie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Variabele-Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Vorige widget</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Herstel de standaard Window Layout</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Toon Documentatie op schijf</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Toon on-line documentatie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Probleem rapporteren</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Octave Packages</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Draag bij aan Octave project</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Octave Ontwikkelaars Resources</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>Over Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Release notes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Community Nieuws</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Tabblad sluiten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Alle tabbladen sluiten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Andere tabbladen sluiten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Wissel naar Linker Tabblad</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Wissel naar Rechter Tabblad</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Verplaats Tabblad naar Links</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Verplaats Tabblad naar Rechts</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Vergroten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Verkleinen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Zoomen naar standaard</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Bewerk functie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Bewaar bestand</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Bewaar bestand als</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Afdrukken</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Opnieuw</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Knippen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Zoek en vervang</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Volgende zoeken</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Vorige zoeken</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Wis tot begin van woord</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Wis tot einde van woord</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Wis tot begin van regel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Wis tot einde van regel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Verwijder regel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Kopieer regel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Knip regel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Dubbele Selectie/Regel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Transponeer regel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Toon aanvullijst</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Maak commentaar van selectie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Maak code van selectie</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Commentaar Selectie (String kiezen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Zet selectie om naar hoofdletters</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Zet selectie om naar kleine letters</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Selectie strak laten inspringen</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Selectie strak terug laten inspringen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Code laten inspringen</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Zet regeleindes om naar Windows</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Zet regeleindes om naar Unix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Zet regeleindes om naar Mac</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Ga naar regel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Ga naar bijbehorende accolade</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Selecteer tot bijbehorende accolade</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Schakel bladwijzer aan of uit</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Volgende bladwijzer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Vorige bladwijzer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Alle bladwijzers verwijderen</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Stijlvoorkeuren</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Toon regelnummers</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Toon witruimte-tekens</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Toon regeleindes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Toon inspringlijnen</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Toon lange-regelmarkering</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Toon Taakbalk</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Toon Statusbalk</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Toon Horizontale Schuifbalk</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Tabs alfabetisch sorteren</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Onderbrekingspunt aan/uitzetten</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Volgend onderbrekingspunt</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Vorig onderbrekingspunt</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Wis alle onderbrekingspunten</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Voer bestand uit</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Voer selectie uit</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Voer Tests uit</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Voer Demos uit</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Hulp voor sleutelwoorden</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Documentatie over Sleutelwoord</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>Ga naar Homepage</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>Ga een pagina terug</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>Ga een pagina vooruit</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Bladwijzer naar deze pagina</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/pt_BR.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"pt_BR\" sourcelanguage=\"en_US\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Nome de arquivo inválido</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Diferença com relação ao tamanho padrão</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Cor de fundo, rosa (255,0,255) significa padrão</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>n</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>s</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>Editar &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Ajuda sobre &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Documentação sobre &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Colar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Selecionar Tudo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Executar Seleção</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>Editar seleção</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>Ajuda sobre seleção</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>Documentação sobre seleção</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Limpar Tudo</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Editar %1 na linha %2</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>seleção copiada para a área de transferência</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Abrir Link</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Copiar Endereço do Link</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Enviar Email Para...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>Copiar Endereço de Email</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Editar %1 na linha %2</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Anotação</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Texto</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Texto</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Fonte</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>negrito</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>n</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>itálico</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>cor</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>esquerda</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>meio</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>direita</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>Alinhamento Horizontal</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>Alinhamento Vertical</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>superior</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>inferior</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Posição</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Largura</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Altura</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>unidade</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalizado</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Encaixar no quadro</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Quadro</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Segundo plano</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Borda</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Estilo de linha</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>nenhum</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Espessura de linha</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Selecionar Tudo</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Pausar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Parar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Prosseguir</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Widget de Comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Novidades da Comunidade</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>Padrão</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Erro</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>Prompt</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Documentação do Octave</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>Não foi possível copiar a coleção de ajuda para um arquivo \ntemporário. A funcionalidade de busca pode estar afetada.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>Não foi possível configurar os dados necessários para o\nvisualizador da documentação. Talvez o módulo Qt SQlite\nesteja faltando?\nApenas o texto de ajuda na Janela de Comando\nestará disponível.</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>Conteúdo</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Digite texto para buscar no índice de funções</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Buscar</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>Índice de Funções</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Favoritos</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>Ir para o início</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Ir para trás</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Páginas anteriores</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>Ir para frente</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Páginas seguintes</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Localizar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Mais Zoom</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Menos Zoom</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Zoom Original</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>Favoritar página atual</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>Não foi possível registrar o arquivo de ajuda %1.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nNenhuma documentação favorita carregada!</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: Carregando Documentação Favorita</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Digite os termos para busca nos favoritos</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Filtrar</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Nova pasta</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Abrir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Renomear</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>Remo&amp;ver</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>Adicionar &amp;Pasta</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>Ocultar &amp;Filtro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>Exibir &amp;Filtro</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: Salvando Favoritos da Documentação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>Não foi possível gravar o arquivo %1:\n%2.\n\nFavoritos da documentação não estão salvos!\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>Não foi possível ler o arquivo %1: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>Elemento inicial não encontrado em %1.\nArquivo de favoritos inválido?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>O arquivo %1 não é válido pelo formato XBEL versão 1.0.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Título desconhecido</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Documentação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Veja a documentação para obter ajuda.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Fechar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>Fechar &amp;Todos</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>Fechar as &amp;Demais Abas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>Alternar para Aba à &amp;Esquerda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>Alternar para Aba à &amp;Direita</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation>Abrir Arquivos do Editor</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation>Clique para focar no arquivo do editor</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Fechar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>Fechar &amp;Todos</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Executar</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Defina &amp;Diretório Atual</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>Não foi possível iniciar o editor de arquivo externo %1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Não há um editor de arquivos externo configurado ainda.\nGostaria de abrir a janela de preferências?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Prosseguir</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Salvar Arquivo e Executá-lo</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>Arquivo não foi salvo! Um arquivo com o nome %1 já está aberto no editor.</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>A aba do editor associada ao arquivo desapareceu.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>O arquivo \n%1\nnão pode ser aberto para leitura:%2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Arquivo\n%1\nnão existe. Deseja criá-lo?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Criar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>O arquivo\n%1\nnão pode ser aberto para escrita:%2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>Arquivos &amp;Recentes do Editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>&amp;Editar Função</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>&amp;Salvar Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>Salvar Arquivo &amp;Como...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Fechar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Fechar Todos</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Fechar Demais Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Imprimir...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Editar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Refazer</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>Recor&amp;tar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>&amp;Localizar e Substituir...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>Localizar &amp;Próxima</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>Localizar &amp;Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>&amp;Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Deletar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Copiar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Recortar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Deletar até Início da Palavra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Deletar até Final da Palavra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Deletar até Início da Linha</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Deletar até Final da Linha</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Duplicar Seleção/Linha</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Transpor Linha</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>&amp;Exibir Lista de Auto-preenchimento</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Formatar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>Seleção em M&amp;aiúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>Seleção em M&amp;inúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>&amp;Comentar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>&amp;Descomentar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Comentar (Escolhendo o Texto)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>&amp;Indentar Seleção Rigidamente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>&amp;Remover Indentação Rigidamente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Indentar Código</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Converter Finais de Linha para &amp;Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Converter Finais de Linha para &amp;Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Converter Finais de Linha para &amp;Mac Legado (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>Nave&amp;gação</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>Ir para &amp;Linha...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Mover para Parêntese/Chave/Colchete Correspondente</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Selecionar até Parêntese/Chave/Colchete Correspondente</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>Marcador &amp;Seguinte</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>Marcardor &amp;Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>Habilitar/desabilitar &amp;Marcador</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>&amp;Remover Todos os Marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Preferências...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>Preferências de &amp;Estilo...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>&amp;Visualizar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>&amp;Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>Exibir &amp;Números de Linha</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>Exibir Caracteres em &amp;Branco</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Exibir &amp;Finais de Linha</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>Exibir &amp;Guias de Indentação (à Esquerda)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>Exibir &amp;Guia de Linhas Longas (à Direita)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>Exibir Barra de &amp;Ferramentas</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>Exibir Barra de &amp;Estado</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>Exibir Barra de Rolagem &amp;Horizontal</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>M&amp;ais Zoom</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>M&amp;enos Zoom</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>Tamanho &amp;Normal</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>&amp;Ordenar Abas Alfabeticamente</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Depurar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>&amp;Ativar/desativar Ponto de Parada</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>Ponto de Parada &amp;Seguinte</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>Ponto de Parada &amp;Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>&amp;Remover Todos os Pontos de Parada</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>E&amp;xecutar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Salvar Arquivo e Executar/Continuar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>Executar &amp;Seleção</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Salvar Arquivo e Executar Todos os &amp;Testes</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Salvar Arquivo e Executar todas as &amp;Demonstrações</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>Aj&amp;uda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>&amp;Ajuda na Palavra-chave</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>&amp;Documentação da Palavra-chave</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>Arquivos Recentes</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Copiar Arquivo e Caminho &amp;Completos</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>linha:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>col:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>codificação:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>fdl:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Condição de parada</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>ERRO: </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>Não é possível adicionar o ponto de parada a arquivo modificado ou sem nome.\nSalvar e adicionar ponto de parada ou cancelar?</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Ir para linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Número da linha</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Comentar texto selecionado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Comentar texto a usar:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;sem_nome&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>Você deseja cancelar , fechar, salvar ou descartar as modificações?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>O arquivo\n\n  %1\n\nestá prestes a ser fechado mas foi modificado.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>Não foi possível ler o arquivo &apos;%1&apos;\ncom a codificação selecionada &apos;%2&apos;: %3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>Ocorreram problemas ao ler o arquivo\n%1\ncom a codificação selecionada %2.\n\nModificar e salvar o arquivo pode causar perda de dados!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>&amp;Editar mesmo assim</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>&amp;Mudar codificação</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Fechar</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Selecionar nova codificação padrão</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Favor selecionar uma nova codificação\npara recarregar o arquivo atual.\n\nIsso não altera a codificação padrão.\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Depurar ou Salvar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Este arquivo está sendo executado atualmente.\nAbandonar depuração e salvar?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>Não foi possível abrir o arquivo %1 para escrever:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>As mudanças não puderam ser salvas no arquivo\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Arquivos do Octave (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Todos os Arquivos (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>%1\nnão é um identificador válido.\n\nSe você mantiver esse nome de arquivo, não será possível\nexecutar seu script usando o nome dele como um comando no Octave.\n\nVocê deseja escolher outro nome?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>O conteúdo atual do editor não pode ser codificado\nusando a codificação selecionada %1.\nUsá-la resultaria em perda de dados!\n\nFavor selecionar outra!</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1 já existe. Você deseja sobrescrevê-lo?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nAlerta: O conteúdo aberto no editor foi modificado!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>O arquivo &apos;%1&apos; parece ter sido modificado por outra aplicação. Deseja recarregá-lo?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>O arquivo\n%1\nparece ter sido deletado ou renomeado. Gostaria de salvá-lo agora?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Tamanho do arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Tipo do arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Data de modificação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Exibir ocultos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Cores de linhas alternadas</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Digite o caminho ou nome de arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Um diretório para cima</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Exibir o diretório do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Ir para o diretório atual do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Definir diretório do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Definir diretório do Octave para o diretório atual no navegador</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Ações no diretório atual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Exibir Diretório Inicial</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Definir Diretório a Navegar...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Encontrar Arquivos...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Novo Arquivo...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Novo Diretório...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Duplo-clique para abrir arquivo/pasta, botão direito para alternativas</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Renomear...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Abrir</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Abrir no Navegador de Arquivos do Sistema</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Abrir no Editor de Texto</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Copiar Seleção para Área de Transferência</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Executar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Carregar Dados</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Definir Diretório Atual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Adicionar ao Caminho</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Pastas Selecionadas</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Pastas e Subpastas Selecionadas</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Remover do Caminho</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Deletar...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Deletar arquivo/diretório</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>Você tem certeza que deseja deletar todos os %1 arquivos selecionardos?\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>Você tem certeza que deseja deletar\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>Não é possível deletar um diretório que não está vázio</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Erro ao deletar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>Não foi possível deletar arquivo &quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Definir diretório do navegador de arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Criar Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Criar arquivo em\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Novo Arquivo.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Erro ao criar arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>Não foi possível criar o arquivo\n&quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Criar Diretório</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Criar pasta em\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Novo Diretório</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>Não foi possível renomear arquivo &quot;%1&quot; para &quot;%2&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Navegador de Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Navegar nos arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>Sistema de Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>Arquivos do Editor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>Aproveite!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Finalizar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Esperamos que você ache o Octave uma ferramenta útil.&lt;/p&gt;\n&lt;p&gt;Se você encontrar problemas, existem várias formas de obter ajuda, incluindo suporte comercial, quadro de discussões, uma wiki e outros canais de suporte baseado na comunidade.\nVocê pode encontrar mais informações sobre cada um destes visitando &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (abre em um navegador externo).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Para mais informações sobre o Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visite &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (abre em um navegador externo)&lt;/li&gt;\n&lt;li&gt;Veja a documentação online em &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; ou &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; (links abrem em um navegador externo)&lt;/li&gt;\n&lt;li&gt;Abra o navegador da documentação da Janela (GUI) do Octave com o menu ajuda&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Editor: Buscar e Substituir</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Localizar:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Digite texto de busca</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>Subs&amp;tituir:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>Digite texto da substituição</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>Considerar &amp;maiúsculas/minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>Localizar a partir do &amp;início</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>Retornar ao início se alcançar o &amp;final durante a busca</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>Localizar &amp;Próxima</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>Localizar &amp;Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>&amp;Substituir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>Substituir &amp;Todos(as)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>&amp;Mais opções...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>Palavras &amp;inteiras</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>&amp;Expressões Regulares</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>Localizar para &amp;trás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>Localizar no texto &amp;selecionado</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Localizar a partir do final</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Localizar a partir do início</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Substituir Resultado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 itens substituidos</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Localizar Resultado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>Sem mais ocorrências</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Localizar Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Nome:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>Diretório inicial:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Digite o diretório inicial</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Navegar...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Escolha o diretório inicial</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Diretório Atual</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>Definir diretório inicial como o diretório atual</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Procurar em subdiretórios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Buscar recursivamente nos subdiretórios por arquivos correspondentes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Incluir nomes de diretórios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Incluir diretórios encontrados no resultado da busca</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Ignorar maiúscula/minúscula</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>Não diferenciar maiúsuclas/minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>Contém texto:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>Incluir apenas arquivos contendo texto específico nos resultados da busca</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Texto a buscar</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Resultados: Clique-duplo abre o arquivo ou define o diretório</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Resultados da busca</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>Aguardando.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Digite o termo para buscar pelo nome do arquivo.\nDiferentes termos podem ser \nseparados por &apos;;&apos;, por exemplo, &apos;*.cc ; *.h&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>Localizar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Iniciar busca por arquivos correspondentes</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Parar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Parar busca</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>Nome do arquivo/Localização</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Conteúdo do arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>Buscando...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 encontrada(s)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Definir diretório de busca</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Nome do Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Diretório</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Clique-duplot para abrir o arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Clique-duplot para definir o diretório</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Localizar:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>Localizar para frente</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Localizar para trás</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Fechar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Fechar a caixa de busca</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Erro %1 ao criar o arquivo de configurações\n%2\nTenha certeza de ter permissão de leitura e gravação em\n%3\n\nOctave GUI deve ser fechado agora.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Erro Crítico no Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Navegar e buscar no histórico de comandos.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Executar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Criar script</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Ocultar filtro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Exibir filtro</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Dê clique-duplo sobre um comando para transferí-lo à Janela de Comandos.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Digite para filtrar o histórico de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Filtrar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Histórico de Comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Bem-vindo(a) ao Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Próximo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Parece que você está usando a interface gráfica do Octave pela primeira vez neste computador.\nClique em &apos;Avançar&apos; para criar um arquivo de configuração e iniciar o Octave.&lt;/p&gt;\n&lt;p&gt;O arquivo de configuração é armazenado em&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Desacoplar Widget</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Fechar Widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Perfilagem</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>Tem certeza que deseja sair do Octave?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Salvar Ambiente de Trabalho Como</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Carregar Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>Sobre o Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Navegar pelos diretórios</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Arquivos do Octave (*.m);;Todos os Arquivos (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Nova Função</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Nome da nova função:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>%1 é uma função interna, compilada, ou uma\nfunção inline e não pode ser editada.</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>Não foi possível encontrar a função %1</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Abrir...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Abrir um arquivo existente no editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Carregar Ambiente de Trabalho...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Salvar Ambiente de Trabalho Como...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Sair</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Novo</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Novo Script</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Nova Função...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Nova Figura</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Editar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Desfazer</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Colar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Selecionar Tudo</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Limpar Área de Transferência</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Localizar Arquivos...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Limpar Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Limpar Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Limpar Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Definir Caminho...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Preferências...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>De&amp;purar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Passo-a-passo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Passo adentro</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Passo afora</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Prosseguir</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Sair do modo de depuração</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>&amp;Ferramentas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>Iniciar Sessão de &amp;Perfilagem</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>&amp;Continuar Sessão de Perfilagem</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>&amp;Parar Perfilagem</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>&amp;Exibir dados da Perfilagem</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>&amp;Janela</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Exibir Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Exibir Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Exibir Navegador de Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Exibir Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Exibir Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Exibir Documentação</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Exibir Editor de Variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Navegador de Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Documentação</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de Variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Widget Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Restaurar Layout Padrão das Janelas</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>Aj&amp;uda</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Relatar Defeito</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Pacotes do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>Envolva-se</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Doações para o Octave</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>No Disco (Em Seu Computador)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>Online (na Internet)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Novidades</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Notas da Versão</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Novidades da Comunidade</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Barra de Ferramentas</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Digite o nome do diretório</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Diretório Atual: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Um diretório para cima</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nA fonte de novidades da comunidade Octave parece estar indisponível.\n&lt;/p&gt;\n&lt;p&gt;\nPara ver as últimas novidades, favor acessar\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nquando estiver conectado à Internet (abre em navegador externo).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Os Desenvolvdores do Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConectando à internet para exibir as últimas notícias da Comunidade do Octave foi desabilitada.\n&lt;/p&gt;\n&lt;p&gt;\nPara as últimas notícias , por favor verifique\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nquando você tiver uma conexão com a internet (link abre em um navegador externo)\nou ative conexão à internet para novidades na aba de configurações de rede do Octave.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Os Desenvolvedores do Octave, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Ocultar Widget</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Acoplar Widget</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Desacoplar Widget</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>Ajuda sobre</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>Documentação sobre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>Editar</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop se...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>Criação de arquivos temporários falhou.\nCertifique-se de que você tem acesso para escrita no diretório temp.\n%1\n&quot;Executar Seleção&quot; requer arquivos temporários.</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>Pressione %1 para substituir todas as ocorrências de &apos;%2&apos; por &apos;%3&apos;.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>Padrão</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Criar</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Arquivo\n%1\nnão existe. Deseja criá-lo?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>O arquivo %1 não existe no caminho de busca. Para executar ou depurar a função que você está editando, é preciso trocar o diretório atual para %2 ou adicioná-lo ao caminho de busca.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>O arquivo %1 é sobreposto por um arquivo com o mesmo nome no caminho de busca. Para executar ou deputar a função que você está editando, defina o diretório atual como %2.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Trocar Diretório Atual ou Adicionar Diretório ao Caminho de Busca</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>&amp;Trocar Diretório</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>&amp;Adicionar Diretório ao Caminho de Busca</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>O arquivo de notas da versão &apos;%1&apos; está vazio.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>O arquivo de notas da versão &apos;%1&apos; não pode ser lido.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Notas da Versão do Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Definir Caminho</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Todas as mudanças têm efeito imediatamente.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Adicionar Diretório...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Diretório Único</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Diretório Com Subdiretórios</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>Mover para o Topo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>Mover para a Base</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Mover Acima</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Mover Abaixo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Remover</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Recarregar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Salvar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Reverter</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Reverter Últma Alteração</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Reverter Todas as Alterações</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Abrir Diretório</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>Topo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>Base</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>Esquerda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>Direita</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Primeiro plano</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Segundo plano</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Seleção</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>Cursor</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Primeiro Plano Selecionado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Segundo Plano Selecionado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Segundo Plano Alternativo</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>argumento</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>global</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>persistente</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Variáveis de Ambiente</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>Modo de cor secundário (claro/escuro)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>Trocar para um segundo conjunto de cores.\nIdeal para definir modo claro/escuro.\nDescartar mudanças não aplicadas!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>Recarregar cores padrão, depende do atual modo selecionado.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>Recarregar valores padrão do estilo, depende do atual modo selecionado.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>&amp;Recarregar cores padrão</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>&amp;Recarregar estilos padrão</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Carregando prerências atuais ... </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Configuração do sistema</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>Cursor &quot;I&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>Cursor de Bloco</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>Cursor Sublinhado</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>Cor da linha atual ressaltada (use magenta (255,0,255) para cor automática)</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Definir Diretório de Inicialização do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Definir Diretório de Inicialização do Navegador de Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Aplicando preferências ... </translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>Falha ao abrir %1 como arquivo de teclas de atalho do Octave</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Habilitar cores para atributos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Ocultar dicas</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Importar teclas de atalho do arquivo...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Arquivos de Teclas de Atalho do Octave (*.osc);;Todos Arquivos (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Exportar teclas de atalho para arquivo...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Sobrescrever Teclas de Atalho</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Você está prestres a sobreescrever todas as teclas de atalho.\nGostaria de salvar o conjunto atual de teclas de atalho ou cancelar a ação?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>Não salvar</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Preferências da Janela (GUI) do Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Novidades da Comunidade</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Próximo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Quando o Octave inicia, opcionalmente ele tentará verificar no seu site por novidades e informações sobre a comunidade.\nA verificação ocorrerá no máximo uma vez por dia e as novidades só serão exibidas se houver algo de novo desde a última vez que você viu.&lt;/p&gt;\n&lt;p&gt;Você também pode ver as novidades selecionando esse item no menu &quot;Ajuda&quot; ou visitando\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Permitir que o Octave se conecte com o site do Octave na inicialização para exibir as novidades atuais sobre a comunidade do Octave.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Digite um Novo Atalho</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Digite o atalho customizado\nAção: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Digite o atalho pressionando-o</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Adicionar modificador Shift\n(permite a entrada de teclas numéricas)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Atalho Atual</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Atalho Padrão</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Limpar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Usar padrão</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Tecla de Atalho Dupla</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>O atalho escolhido\n  &quot;%1&quot;\njá está em uso para a ação\n  &quot;%2&quot;.\n\nVocê deseja usar este atalho e removê-lo da ação anterior?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Global</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Menu Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Menu Editar</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Menu de Depuração</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Menu de Ferramentas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Menu Janela</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Menu Ajuda</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Menu Novidades</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Manuseio de Widgets Acoplados</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Manuseio de Abas no Acoplamento de Widgets</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Localizar e Substituir em Widgets</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Zoom no Editor e na Documentação</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Menu Exibir</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Menu Executar</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Visualizador de Documentação</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Navegador</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>item %1 não encontrado nas configurações de atalhos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Bem-vindo ao GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Bem-vindo(a) ao Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Janela de Comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Acoplar Widget</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Editor de Variáveis: </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Desacoplar Widget</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Restaurar geometria</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Reacoplar</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de Variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Editar variáveis.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Barra de Ferramentas do Editor de Variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Salvar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Salvar variável para arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Salvar no formato...</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Salvar variável para um arquivo em um formato diferente</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Recortar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Recortar dados para área de transferência</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Copiar dados para área de transferência</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Colar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Colar área de transferência nos dados da variável</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Plotar</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Plotar Dados Selecionados</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Plotar dados selecionados</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Acima</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>Subir um nível na hierarquia de variáveis</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>Salvar Variável %1 Como</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Recortar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Colar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Limpar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Deletar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Variável a partir da Seleção</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Transpor</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> colunas</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> coluna</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> linhas</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> linha</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Bem-vindo ao GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>Nome</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensão</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Atributo</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Clique com botão direito para copiar, renomear ou exibir</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>complexo</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Dimensão</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Atributo</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Visualizar variáveis no Ambiente de Trabalho ativo.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Digite para filtrar o Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Filtrar</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Visualizar as variáveis no Ambiente de Trabalho ativo.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Cores de atributos de variáveis:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Abrir no Editor de Variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Copiar nome</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Copiar valor</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Renomear</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Somente símbolos de alto nível podem ser renomeados</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Ocultar filtro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Exibir filtro</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>Não é possível abrir o fluxo redirecionado com fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>Não é possível desabilitar o buffer do fluxo com fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>Não é possível duplicar o fluxo redirecionado com fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>Não é possível criar um pipe para redirecionar o fluxo com fd = %1:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>Não é possível duplicar o fluxo redirecionado com fd = %1\npara passar para fd = %2: %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Erro durante o monitoramento dos fluxos redirecionados</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation>Erro ao ler do fluxo redirecionado fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\nRedirecionamento de saída em </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> não vai funcionar.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\nErro: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Geral</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Apenas logotipo do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Ícones de texto</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Graphic icons</source>\n        <translation>Ícones gráficos</translation>\n    </message>\n    <message>\n        <location line=\"-341\"/>\n        <source>Dock widget title bar</source>\n        <translation>Barra de título do painel</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Normal</source>\n        <translation>Normal</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>Custom style</source>\n        <translation>Estilo personalizado</translation>\n    </message>\n    <message>\n        <location line=\"+244\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Essas preferências são aplicadas após os arquivos de inicialização (.octaverc).</translation>\n    </message>\n    <message>\n        <location line=\"+353\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+187\"/>\n        <source>Show EOL characters</source>\n        <translation>Exibir caracteres de final de linha</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Quebrar linhas longas na borda da janela atual</translation>\n    </message>\n    <message>\n        <location line=\"+558\"/>\n        <source>Default EOL mode</source>\n        <translation>Modo padrão para final de linha</translation>\n    </message>\n    <message>\n        <location line=\"-503\"/>\n        <source>Indent width</source>\n        <translation>Largura de indentação</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Tecla Tab causa indentação na linha</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Auto-indentação</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Largura do Tab</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Exibir guias de indentação</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Tecla Backspace remove indentação da linha</translation>\n    </message>\n    <message>\n        <location line=\"+120\"/>\n        <source>Match keywords</source>\n        <translation>Completar palavras-chave do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Diferenciar maiúsculas/minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Substituir palavra por aquela sugerida</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Preencher com palavras do documento</translation>\n    </message>\n    <message>\n        <location line=\"-643\"/>\n        <source>Use custom file editor</source>\n        <translation>Usar editor de texto externo</translation>\n    </message>\n    <message>\n        <location line=\"+1009\"/>\n        <source>Editor Styles</source>\n        <translation>Estilos de Edição</translation>\n    </message>\n    <message>\n        <location line=\"-1485\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Fonte</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Exibir números de linha</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Show whitespace</source>\n        <translation>Exibir espaços em branco</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Não exibir espaços em branco usados para indentação</translation>\n    </message>\n    <message>\n        <location line=\"+935\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Número de caracteres antes da lista ser exibida: </translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Criar arquivos não existentes sem confirmar</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>linha de comando (%f=arquivo, %l=linha):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Tipo de cursor:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Usar cor de primeiro plano</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Tamanho de fonte</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Navegador de Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"-2118\"/>\n        <source>Interface</source>\n        <translation>Interface</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Confirmar antes de sair</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Exibir barra de status</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Texto inativo</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Ativo</translation>\n    </message>\n    <message>\n        <location line=\"-96\"/>\n        <source>Small</source>\n        <translation>Pequeno</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Grande</translation>\n    </message>\n    <message>\n        <location line=\"+118\"/>\n        <source>Background inactive</source>\n        <translation>Segundo plano inativo</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation>3D</translation>\n    </message>\n    <message>\n        <location line=\"+206\"/>\n        <source>Octave Startup</source>\n        <translation>Inicialização do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Escolher</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Isso funciona bem para fontes mono-espaçadas. A guia é desenhada numa posição baseada no tamanho do caractere espaço na fonte padrão. Pode não funcionar muito bem se os estilos usarem fontes proporcionais ou, no caso de fontes de tamanho variável, se negrito, itálico e texto normal forem usados também.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Habilitar Células de Código</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation>Mac legado (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Exibir barra de rolagem horizontal</translation>\n    </message>\n    <message>\n        <location line=\"-970\"/>\n        <source>Preferences</source>\n        <translation>Preferências</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(requer reinicialização)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Usar caixas de diálogo de arquivos nativas</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Ícones da Barra de Ferramentas</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Idioma</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Ícones de janelas para acoplar componentes</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Estilo</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Tema para ícones (requer reinicialização)</translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation>Cursor piscante</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Exibir a tela de abertura na inicialização</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Diretório de trabalho inicial do interpretador do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Restaurar último diretório de trabalho da sessão anterior</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Comando</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Definir o foco na Janela de Comandos ao executar um comando de outro painel</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Imprimir localização de depuração na Janela de Comandos, além do marcador no editor</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Cores da Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Show tool bar</source>\n        <translation>Exibir barra de ferramentas</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Tamanho na forma de diferença com relação à fonte do editor</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Realçar linha atual (cor ajustável abaixo com estilos de edição)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Destacar todas as ocorrências de uma palavra selecionada com clique duplo</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Abas</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotacionar abas: Vertical quando no topo ou na base e horizontal quando à esquerda ou à direita. O botão fechar não é exibido em abas rotacionadas.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Comentários (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Textos a serem considerados quando descomentando texto</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Texto usado para comentar texto selecionado</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Linhas longas</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Quebrar linhas longas no comprimento</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Quebrar linhas apenas em comentários</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Comprimento de linha</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Guia de linhas longas</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Linha</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Segundo plano</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>Indentation</source>\n        <translation>Indentação</translation>\n    </message>\n    <message>\n        <location line=\"+127\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Indentar com caracteres tab</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Auto inserir após &quot;if&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Nada</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot; etc.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Auto completion</source>\n        <translation>Auto-completar</translation>\n    </message>\n    <message>\n        <location line=\"+101\"/>\n        <source>With Octave builtins</source>\n        <translation>Completar Octave builtins</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Completar funções Octave</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Exibir automaticamente lista de auto-completar</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Debugging</source>\n        <translation>Depuração</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Sempre exibir apontadores e pontos de parada na depuração (abrundo arquivos relacionados se estiverem fechados)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Manipulação de arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Recarregar arquivos alterados externamente sem confirmar</translation>\n    </message>\n    <message>\n        <location line=\"-50\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Restaurar abas no editor da sessão anterior durante a inicialização ou quando o editor é exibido novamente após ser fechado</translation>\n    </message>\n    <message>\n        <location line=\"-31\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Codificação de texto utilizada para carregar e salvar</translation>\n    </message>\n    <message>\n        <location line=\"+71\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Fechar todos os arquivos quando a janela do editor é fechada/ocultada</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>Forçar nova linha ao final quando salvar arquivo</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>Remover espaços em branco ao final quando salvar arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+144\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Selecione a fonte, seu tamanho (diferença com relacão ao tamanho padrão), estilo (&lt;b&gt;n&lt;/b&gt;egrito, &lt;b&gt;i&lt;/b&gt;tálico, &lt;b&gt;s&lt;/b&gt;ublinhado), cor do texto e cor de fundo (magenta (255,0,255) é a cor de fundo padrão).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+848\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - fechar caixa de diálogo e aplicar configurações&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Aplicar - &lt;/span&gt;aplicar configurações mas deixar a caixa de diálogo aberta&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancelar - &lt;/span&gt;fechar a caixa de diálogo e discartar as mudanças que não foram aplicadas&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Restaurar -&lt;/span&gt; recarregar configurações descartando as mudanças que não foram aplicadas&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-2254\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Alterar o tamanho do histório apagará o seu conteúdo atual)</translation>\n    </message>\n    <message>\n        <location line=\"-260\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Se definido, o foco dos componentes que estejam acoplados à janela principal seguirá o cursor do mouse. Projetado para ter o mesmo comportamento dentro da janela principal quando &amp;quot;foco segue o mouse&amp;quot; é usada no ambiente da área de trabalho.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>Foco seguirá o mouse para componentes acoplados à janela principal</translation>\n    </message>\n    <message>\n        <location line=\"+285\"/>\n        <source>History buffer Size</source>\n        <translation>Tamanho do Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Rotated tabs</source>\n        <translation>Abas rotacionadas</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Posição</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>Largura máxima da aba, em núm. de car. (0: sem limite)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Largura máxima de uma aba, em número de caracteres (de largura média). Útil especialmente para abas rotacionadas.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+871\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>O diretório da caixa de diálogo abrir arquivo segue o arquivo atual do editor em vez do diretório atual do Octave </translation>\n    </message>\n    <message>\n        <location line=\"+98\"/>\n        <source>Behavior</source>\n        <translation>Comportamento</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Restaurar diretório da sessão anterior</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>Diretório inicial do navegador de arquivos (somente se não estiver sincronizado com o diretório de trabalho inicial do Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Extensões de arquivos a serem abertas no editor de texto padrão (separadas por &quot;;&quot;):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Cores para atributos de variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Usar a fonte da Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Importar conjunto de teclas de atalho</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Exportar conjunto de atalhos atual</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Redefinir teclas de atalho para o padrão</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Padrão</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation>Real</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Rede</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Permitir Octave se conectar à Internet para exibir novidades e informações atuais</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Servidor Proxy</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Selecione &lt;span style=&quot; font-style:italic;&quot;&gt;Proxy HTTP&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Proxy Sock5&lt;/span&gt; ou &lt;span style=&quot; font-style:italic;&quot;&gt;Variáveis de Ambiente&lt;/span&gt;. Com a última seleção, o proxy é obtido da primeira variávei de ambiente que não estiver vazia: ALL_PROXY, HTTP_PROXY ou HTTPS_PROXY.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Usar servidor proxy</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de Variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Altura de linha padrão</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Largura de coluna padrão</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Cores do Editor de Variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Usar cores de linha alternadas</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Desabilita atalhos globais para evitar\nintereferência com teclas digitadas para o readline.\nExceções: Ctrl-C para interrupção do interpretador\ne os atalhos para alternar entre outros componentes.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Desativar teclas de atalho globais quando a Janela de Comando tiver foco</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Manter diretório de trabalho do Octave sincronizado com o Navegador de Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+348\"/>\n        <source>Shortcuts</source>\n        <translation>Teclas de Atalho</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Export</source>\n        <translation>Exportar</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importar</translation>\n    </message>\n    <message>\n        <location line=\"-44\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Desabilita atalhos para menus de forma a previnir\ninterferência com teclas entradas no readline.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>Desabilita atalhos para menus na janela principal quando a Janela de Comandos estiver em foco</translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Dê um duplo clique para editar o atalho na coluna Atual</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Ação</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Endereço do servidor:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Tipo de proxy:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Porta:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Nome de usuário:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Senha:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Desacoplar/Acoplar Widget</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Fechar Widget</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Novo Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Nova Função</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Nova Figura</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Abrir Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Carregar Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Salvar Ambiente de Trabalho Como</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Sair do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Colar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Desfazer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Selecionar Tudo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Limpar Área de Transferência</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>Localizar Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Limpar Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Limpar Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Limpar Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Definir Caminho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Preferências</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Passo-a-passo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>Passo adentro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Passo afora</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Prosseguir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Sair do modo de depuração</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Iniciar/Parar Sessão de Perfilamento</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Continuar Sessão de Perfilamento</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Exibir Dados de Perfilamento</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Exibir Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Exibir Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Exibir Navegador de Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Exibir Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Exibir Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Exibir Documentação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Exibir Editor de Variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Navegador de Arquivos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Documentação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Editor de Variáveis</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Widget Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Restaurar Layout Padrão das Janelas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Exibir Documentação no Disco</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Exibir Documentação Online (na Internet)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Relatar Defeito</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Pacotes do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Contribuir com o Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Recursos para Desenvolvedores</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>Sobre o Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Notas da Versão</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Novidades da Comunidade</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Fechar Aba</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Fechar Todas as Abas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Fechar as Demais Abas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Alternar para Aba à Esquerda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Alternar para Aba à Direita</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Mover Aba Esquerda</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Mover Aba Direita</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Mais Zoom</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Menos Zoom</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Zoom Normal</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Editar Função</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Salvar Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Salvar Arquivo Como</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Imprimir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Refazer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Recortar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Localizar e Substituir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Localizar Próximo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Localizar Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Deletar até Início da Palavra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Deletar até Final da Palavra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Deletar até Início da Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Deletar até Final da Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Deletar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Copiar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Recortar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Duplicar Seleção/Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Transpor Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Exibir Lista de Autopreenchimento</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Comentar Seleção</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Descomentar Seleção</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Comentar Seleção (Escolhendo o Texto)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Seleção em Maiúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Seleção em Minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Indentar Seleção Rigidamente</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Remover Indentação da Seleção Rigidamente</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Indentar Código</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Converter Finais de Linha para Windows</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Converter Finais de Linha para Unix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Converter Finais de Linha para Mac</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Ir para Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Mover para Parêntese/Chave/Colchete Correspondente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Selecionar até Parêntese/Chave/Colchete Correspondente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Habilitar/desabilitar Marcador</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Marcador Seguinte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Marcador Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Remover Todos os Marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Preferências de Estilo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Exibir Números de Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Exibir Caracteres em Branco</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Exibir Finais de Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Exibir Guias de Indentação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Exibir Guia de Linhas Longas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Exibir Barra de Ferramentas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Exibir Barra de Estado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Exibir Barra de Rolagem Horizontal</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Ordenar Abas Alfabeticamente</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Ativar/desativar Ponto de Parada</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Ponto de Parada Seguinte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Ponto de Parada Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Remover Todos Pontos de Parada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Executar Arquivo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Executar Seleção</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Executar Testes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Executar Demonstrações</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Ajuda na Palavra-chave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Documentação sobre Palavra-chave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>Ir para página inicial</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>Voltar uma Página</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>Avançar uma Página</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Salvar esta Página nos Favoritos</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/pt_PT.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"pt_PT\" sourcelanguage=\"en_US\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation type=\"unfinished\">Diferença em relação ao tamanho do tipo de letra default</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation type=\"unfinished\">Cor de fundo rosa (255,0,255) significa padrão {255, 0, 255)?}</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation type=\"unfinished\">n</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation type=\"unfinished\">i</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation type=\"unfinished\">s</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Colar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Seleccionar Tudo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\">Executar Selecção</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Limpar Tudo</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>selecção copiada para a área de transferência</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Erro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentário</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Número</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Palavra reservada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentário</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Palavra reservada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Variável</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>Comentário C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>Comentário C desactivado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>Comentário C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>Comentário C++ desactivado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>Comentário C estilo JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>Comentário C estilo JavaDoc desactivado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Número</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Número desactivado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Palavra reservada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Palavra reservada desactivada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>Double-quoted string desactivada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>Single-quoted string desactivada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>IDL UUID desactivado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>Bloco pre-processador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>Bloco pre-processador desactivado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Operador desactivado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Identificador desactivado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>Unclosed string desactivada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>C# verbatim string desactivada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>JavaScript regular expression desactivada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>C++ comentário estilo JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>C++ comentário estilo JavaDoc desactivado</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>Palavras reservadas e identificadores secundários</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Palavras reservadas e identificadores secundários desactivados</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>Palavra reservada JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>Palavra reservada JavaDoc desactivada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Classes e typedefs globais</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Classes e typedefs globais desactivadas</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>C++ raw string desactivada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentário</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Comando</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Posição</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Linha removida</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Linha adicionada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Linha modificada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentário</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Comando</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Número</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Palavra reservada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Erro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Comentário</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Número</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Palavra reservada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Identificador</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Tabela de símbolos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>Substituição</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation></translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>&amp;Desfazer</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Refazer</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>Cor&amp;tar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>&amp;Colar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Apagar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Selecionar Tudo</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation type=\"unfinished\">Tipo de letra</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation type=\"unfinished\">n</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation type=\"unfinished\">i</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\">Posição</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Parar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation type=\"unfinished\">Novidades da Comunidade</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\">Erro</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Localizar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">Ampliar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">Diminuir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">Filtrar</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Documentação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation type=\"unfinished\">Ver a documentação para obter ajuda.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Fechar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Fechar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Executar</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation type=\"unfinished\">Não foi possível iniciar o editor de ficheiro externo %1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation type=\"unfinished\">Guardar Ficheiro e Executá-lo</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation type=\"unfinished\">A aba do editor associada ao ficheiro desapareceu.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">Ficheiro\n%1\nnão existe. Deseja criá-lo?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">Criar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation type=\"unfinished\">Ficheiros &amp;Recentes</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation type=\"unfinished\">&amp;Editar Função</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation type=\"unfinished\">&amp;Guardar Ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation type=\"unfinished\">Guardar Ficheiro &amp;Como...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Fechar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation type=\"unfinished\">Fechar Todos</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation type=\"unfinished\">Fechar Outros Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation type=\"unfinished\">Imprimir...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Editar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\">&amp;Refazer</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\">Cor&amp;tar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation type=\"unfinished\">&amp;Localizar e Substituir...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation type=\"unfinished\">Localizar &amp;Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation type=\"unfinished\">&amp;Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\">Apagar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">Copiar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">Cortar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">Apagar até ao Início da Palavra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">Apagar até ao Fim da Palavra</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">Apagar até ao Início da Linha</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">Apagar até ao Fim da Linha</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">Duplicar Selecção/Linha</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">Transpor linha</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation type=\"unfinished\">&amp;Mostrar Lista de Auto-completar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation type=\"unfinished\">&amp;Formatar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation type=\"unfinished\">M&amp;AIÚSCULAS</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation type=\"unfinished\">M&amp;INÚSCULAS</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation type=\"unfinished\">&amp;Comentar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation type=\"unfinished\">&amp;Descomentar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation type=\"unfinished\">Converter Fins de Linha para &amp;Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation type=\"unfinished\">Converter Fins de Linha para Legacy &amp;Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation type=\"unfinished\">Nave&amp;gação</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation type=\"unfinished\">Ir para a &amp;Linha...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\">Selecionar até ao Parênteses Correspondente</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation type=\"unfinished\">Marcador &amp;Seguinte</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation type=\"unfinished\">Marcardor &amp;Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation type=\"unfinished\">Activar/Desactivar &amp;Marcador</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation type=\"unfinished\">&amp;Remover Todos os Marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation type=\"unfinished\">&amp;Preferências...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation type=\"unfinished\">Preferências de &amp;Estilo...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation type=\"unfinished\">&amp;Visualizar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation type=\"unfinished\">&amp;Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation type=\"unfinished\">Mostrar &amp;Números de Linha</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation type=\"unfinished\">Mostrar &amp;Whitespace</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation type=\"unfinished\">Mostrar &amp;Fins de Linha</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation type=\"unfinished\">Mostrar &amp;Guias de Indentação</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation type=\"unfinished\">Mostrar &amp;Guia de Linhas Longas</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation type=\"unfinished\">&amp;Aumentar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation type=\"unfinished\">&amp;Diminuir</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation type=\"unfinished\">Tamanho &amp;Normal</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation type=\"unfinished\">&amp;Debug</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation type=\"unfinished\">&amp;Activar/Desactivar Breakpoint</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation type=\"unfinished\">Breakpoint &amp;Seguinte</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation type=\"unfinished\">Breakpoint &amp;Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation type=\"unfinished\">&amp;Remover Todos os Breakpoints</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation type=\"unfinished\">&amp;Executar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation type=\"unfinished\">Executar &amp;Selecção</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Ajuda</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation type=\"unfinished\">&amp;Ajuda na Palavra Reservada</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation type=\"unfinished\">&amp;Documentação da Palavra Reservada</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editor</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation type=\"unfinished\">linha:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation type=\"unfinished\">col:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation type=\"unfinished\">eol:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation type=\"unfinished\">Ir para a linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation type=\"unfinished\">Número da linha</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation type=\"unfinished\">&lt;sem_nome&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation type=\"unfinished\">O ficheiro\n\n  %1\n\nvai ser fechado mas foi modificado.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">&amp;Fechar</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation type=\"unfinished\">Ficheiros Octave (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation type=\"unfinished\">Todos os Ficheiros (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation type=\"unfinished\">\n\nAlerta: O conteúdo aberto no editor foi modificado!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation type=\"unfinished\">Parece que o ficheiro &apos;%1&apos; foi modificado por outra aplicativo. Deseja recarregá-lo?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation type=\"unfinished\">Parece que o ficheiro\n%1\nfoi apagado ou movido. Gostaria de guardar agora?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation type=\"unfinished\">Tamanho do ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation type=\"unfinished\">Tipo do ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation type=\"unfinished\">Data de modificação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation type=\"unfinished\">Mostrar ocultos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation type=\"unfinished\">Alternar cor das linhas</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation type=\"unfinished\">Introduzir o local ou nome de ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation type=\"unfinished\">Exibir o directório do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation type=\"unfinished\">Ir para o directório actual do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation type=\"unfinished\">Definir directório do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation type=\"unfinished\">Ir para o directório do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation type=\"unfinished\">Acções no directório actual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation type=\"unfinished\">Mostrar Directório Pessoal</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation type=\"unfinished\">Ir para...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\">Localizar Ficheiros...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation type=\"unfinished\">Novo Ficheiro...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation type=\"unfinished\">Novo Directório...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation type=\"unfinished\">Mudar nome...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">Abrir</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation type=\"unfinished\">Copiar Selecção para Área de Transferência</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">Executar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation type=\"unfinished\">Carregar Dados</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation type=\"unfinished\">Definir como Directório Actual</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation type=\"unfinished\">Apagar...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation type=\"unfinished\">Apagar ficheiro/directório</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation type=\"unfinished\">Tem certeza que deseja apagar\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation type=\"unfinished\">Não é possível apagar um directório que não está vázio</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation type=\"unfinished\">Definir directório do nagevador de ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation type=\"unfinished\">Criar Ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Criar ficheiro em\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation type=\"unfinished\">Novo Ficheiro.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation type=\"unfinished\">Criar Directório</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">Criar directório em\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation type=\"unfinished\">Novo Directório</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Navegador de Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation type=\"unfinished\">Aproveite!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation type=\"unfinished\">Finalizar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation type=\"unfinished\">Considerar &amp;maiúsculas/minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation type=\"unfinished\">Localizar a partir do &amp;início</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation type=\"unfinished\">Retornar ao início se alcançar o &amp;final durante a busca</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation type=\"unfinished\">&amp;Substituir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation type=\"unfinished\">Substituir &amp;Todos(as)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation type=\"unfinished\">&amp;Mais opções...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation type=\"unfinished\">Palavras &amp;inteiras</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation type=\"unfinished\">Localizar para &amp;trás</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation type=\"unfinished\">Localizar dentro do texto &amp;selecionado</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation type=\"unfinished\">Localizar a partir do final</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation type=\"unfinished\">Localizar a partir do início</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation type=\"unfinished\">Substituir Resultado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation type=\"unfinished\">%1 itens substituidos</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation type=\"unfinished\">Localizar Resultado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation type=\"unfinished\">Sem mais ocorrências</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation type=\"unfinished\">Localizar Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation type=\"unfinished\">Nome de ficheiro:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation type=\"unfinished\">Directório inicial:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation type=\"unfinished\">Digite o directório inicial</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation type=\"unfinished\">Escolher...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation type=\"unfinished\">Escolha o directório inicial</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation type=\"unfinished\">Procurar em subdirectórios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation type=\"unfinished\">Buscar recursivamente nos sub-directórios por ficheiros correspondentes</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation type=\"unfinished\">Incluir nomes de directórios</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation type=\"unfinished\">Incluir directórios correspondentes no resultado da busca</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation type=\"unfinished\">Contém texto:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation type=\"unfinished\">Texto a procurar</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation type=\"unfinished\">Resultados da procura</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation type=\"unfinished\">Aguardando.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\">Localizar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation type=\"unfinished\">Iniciar procura por ficheiros correspondentes</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\">Parar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation type=\"unfinished\">Conteúdo do ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation type=\"unfinished\">A procurar...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation type=\"unfinished\">Definir directório de busca</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation type=\"unfinished\">Nome do Ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation type=\"unfinished\">Directório</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation type=\"unfinished\">Erro Crítico no Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation type=\"unfinished\">Navegar e buscar no histórico de comandos.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation type=\"unfinished\">Executar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation type=\"unfinished\">Criar script</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation type=\"unfinished\">Digite para filtrar o histórico de comandos</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">Filtrar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Histórico de Comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Bem-vindo(a) ao Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">Avançar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\">&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Parece que você está usando a interface gráfica do Octave pela primeira vez neste computador.\nClique em &apos;Avançar&apos; para criar um ficheiro de configuração e iniciar o Octave.&lt;/p&gt;\n&lt;p&gt;O ficheiro de configuração é armazenado em&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation type=\"unfinished\">Tem certeza que deseja sair do Octave?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\">Guardar Ambiente de Trabalho Como</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">Carregar Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Sobre o Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation type=\"unfinished\">Escolher directório</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation type=\"unfinished\">Ficheiros do Octave (*.m);;Todos os Ficheiros (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\">Nova Função</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation type=\"unfinished\">Nome da nova função:</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation type=\"unfinished\">Não foi possível encontrar função %1</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation type=\"unfinished\">Abrir...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation type=\"unfinished\">Abrir um ficheiro existente no editor</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation type=\"unfinished\">Carregar Ambiente de Trabalho...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation type=\"unfinished\">Guardar Ambiente de Trabalho Como...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation type=\"unfinished\">Sair</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation type=\"unfinished\">Novo</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation type=\"unfinished\">Novo Script</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation type=\"unfinished\">Nova Função...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">Nova Figura</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Editar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Desfazer</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Colar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Limpar Área de Transferência</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\">Localizar Ficheiros...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">Limpar Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Limpar Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Limpar Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation type=\"unfinished\">Preferências...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation type=\"unfinished\">De&amp;purar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">Passo-a-passo</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Passo adentro</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">Passo afora</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation type=\"unfinished\">&amp;Janela</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Mostrar Navegador de Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Navegador de Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editor</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Documentação</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\">&amp;Ajuda</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Reportar Problema</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Bibliotecas do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation type=\"unfinished\">No Disco (Em Seu Computador)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation type=\"unfinished\">Online (na Internet)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation type=\"unfinished\">&amp;Novidades</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Notas da Versão</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Novidades da Comunidade</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation type=\"unfinished\">Barra de Ferramentas</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation type=\"unfinished\">Digite o nome do directório</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation type=\"unfinished\">Directório Actual:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\">&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nA fonte de notícias da comunidade parece estar indisponível.\n&lt;/p&gt;\n&lt;p&gt;\nPara ver as novidades, vá a\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nquando tiver ligação com a Internet.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Os Programadores do Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation type=\"unfinished\">Ajuda sobre</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation type=\"unfinished\">Documentação sobre</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation type=\"unfinished\">Editar</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\">Criar</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\">Ficheiro\n%1\nnão existe. Deseja criá-lo?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\">Editor do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation type=\"unfinished\">O ficheiro %1 não existe no caminho de procura. Para executar ou depurar a função que você está editando, é preciso definir o directório actual como %2 ou adicionar aquele directório ao caminho de busca.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation type=\"unfinished\">O ficheiro %1 é sobreposto por um ficheiro com o mesmo nome no loadpath. Para executar ou fazer debug à função, mude o directório actual para %2.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation type=\"unfinished\">Mudar Directório Actual ou Adicionar Directório ao Load Path</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation type=\"unfinished\">O ficheiro de notas da versão &apos;%1&apos; está vazio.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation type=\"unfinished\">O ficheiro de notas da versão &apos;%1&apos; não pode ser lido.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation type=\"unfinished\">Notas da Versão do Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation type=\"unfinished\">global</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation type=\"unfinished\">Configuração do sistema</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation type=\"unfinished\">Cursor IBeam</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation type=\"unfinished\">Cursor de Bloco</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation type=\"unfinished\">Cursor Sublinhado</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation type=\"unfinished\">Definir Directório de Inicialização do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation type=\"unfinished\">Alterar Directório de Inicialização do Navegador de Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation type=\"unfinished\">Ficheiros de teclas de atalho do Octave (*.osc);; Todos Ficheiros (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Novidades da Comunidade</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\">Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\">Avançar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\">Cancelar</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation type=\"unfinished\">Usar default</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation type=\"unfinished\">Atalho Duplicado</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editor</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Bem-vindo ao GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">Bem-vindo(a) ao Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Janela de Comandos</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Cortar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Colar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Cortar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Colar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\">Apagar</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">Bem-vindo ao GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation type=\"unfinished\">Nome</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Dimensão</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">Atributo</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation type=\"unfinished\">Botão direito para copiar, mudar nome, ou mostrar</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation type=\"unfinished\">complexo</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\">Classe</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\">Dimensão</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Valor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\">Atributo</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation type=\"unfinished\">Ver variáveis no Ambiente de Trabalho activo.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation type=\"unfinished\">Introduzir texto para filtrar o Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\">Filtrar</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation type=\"unfinished\">Ver as variáveis no Ambiente de Trabalho activo.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation type=\"unfinished\">Cores de atributos de variáveis:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation type=\"unfinished\">Copiar nome</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation type=\"unfinished\">Copiar valor</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation type=\"unfinished\">Mudar nome</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\">Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Geral</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Apenas logotipo do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Ícones de texto</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Graphic icons</source>\n        <translation>Ícones gráficos</translation>\n    </message>\n    <message>\n        <location line=\"-341\"/>\n        <source>Dock widget title bar</source>\n        <translation>Barra de título do painel</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Normal</source>\n        <translation>Normal</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>Custom style</source>\n        <translation>Estilo personalizado</translation>\n    </message>\n    <message>\n        <location line=\"+244\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Estas preferências são aplicadas depois dos ficheiros de inicialização (.octaverc).</translation>\n    </message>\n    <message>\n        <location line=\"+353\"/>\n        <source>Editor</source>\n        <translation>Editor</translation>\n    </message>\n    <message>\n        <location line=\"+187\"/>\n        <source>Show EOL characters</source>\n        <translation>Mostrar caracteres de fins de linha</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+558\"/>\n        <source>Default EOL mode</source>\n        <translation>Modo padrão para final de linha</translation>\n    </message>\n    <message>\n        <location line=\"-503\"/>\n        <source>Indent width</source>\n        <translation>Largura de indentação</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Tecla Tab causa indentação na linha</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Auto-indentação</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Largura do Tab</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Exibir guias de indentação</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Tecla Backspace remove indentação da linha</translation>\n    </message>\n    <message>\n        <location line=\"+120\"/>\n        <source>Match keywords</source>\n        <translation>Completar palavras-chave do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Diferenciar maiúsculas/minúsculas</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Substituir palavra por aquela sugerida</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Preencher com palavras do documento</translation>\n    </message>\n    <message>\n        <location line=\"-643\"/>\n        <source>Use custom file editor</source>\n        <translation>Usar editor de texto externo</translation>\n    </message>\n    <message>\n        <location line=\"+1009\"/>\n        <source>Editor Styles</source>\n        <translation>Estilos do Editor</translation>\n    </message>\n    <message>\n        <location line=\"-1485\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Tipo de letra</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Mostrar números da linha</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Show whitespace</source>\n        <translation>Mostrar whitespace</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Não mostrar whitespace usados para indentação</translation>\n    </message>\n    <message>\n        <location line=\"+935\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Número de caracteres antes da lista ser exibida: </translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Criar ficheiros não existentes sem confirmar</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>linha de comando (%f=ficheiro, %l=linha):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Tipo de cursor:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Usar cor do primeiro plano</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Tamanho da letra</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Navegador de Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"-2118\"/>\n        <source>Interface</source>\n        <translation>Interface</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Confirmar antes de sair</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Mostrar barra de estado</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Texto inactivo</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Activo</translation>\n    </message>\n    <message>\n        <location line=\"-96\"/>\n        <source>Small</source>\n        <translation>Pequeno</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Grande</translation>\n    </message>\n    <message>\n        <location line=\"+118\"/>\n        <source>Background inactive</source>\n        <translation>Fundo inactivo</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation type=\"unfinished\">3D</translation>\n    </message>\n    <message>\n        <location line=\"+206\"/>\n        <source>Octave Startup</source>\n        <translation>Inicialização do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Navegar</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Isto funciona bem para tipos de letra monospace. A guia é desenhada numa posição baseada na largura do espaço do tipo de letra default. Pode não funcionar muito bem se os estilos usarem fontes não monospace, mistura de letras com diferentes tamanhos ou estilos.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Activar Células de Código</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation type=\"unfinished\">Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Exibir barra horizontal</translation>\n    </message>\n    <message>\n        <location line=\"-970\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">Preferências</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\">Comando</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Show tool bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Number size as difference to editor font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>Indentation</source>\n        <translation>Indentação</translation>\n    </message>\n    <message>\n        <location line=\"+127\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Indentar com caracteres tab</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Auto completion</source>\n        <translation>Auto-completar</translation>\n    </message>\n    <message>\n        <location line=\"+101\"/>\n        <source>With Octave builtins</source>\n        <translation>Completar Octave builtins</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Completar funções Octave</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Exibir automaticamente lista de auto-completar</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Debugging</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Manipulação de ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Recarregar ficheiros alterados externamente sem confirmar</translation>\n    </message>\n    <message>\n        <location line=\"-50\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-31\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+71\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+144\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Selecione a fonte: família, tamanho (variacão com relacão ao tamanho padrão), estilo (&lt;b&gt;n&lt;/b&gt;egrito, &lt;b&gt;i&lt;/b&gt;tálico, &lt;b&gt;s&lt;/b&gt;ublinhado), cor do texto e cor de fundo (a cor rosa (255,0,255) é a cor de fundo padrão).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+848\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2254\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Alterar o tamanho do histório apagará o seu conteúdo actual)</translation>\n    </message>\n    <message>\n        <location line=\"-260\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+285\"/>\n        <source>History buffer Size</source>\n        <translation>Tamanho do Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Rotated tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\">Posição</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+871\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+98\"/>\n        <source>Behavior</source>\n        <translation>Comportamento</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Restaurar directório da sessão anterior</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Rede</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Permitir Octave ligar-se à Internet para exibir novidades e informações</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Usar servidor proxy</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Manter directório de trabalho sincronizado com o Navegador de Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+348\"/>\n        <source>Shortcuts</source>\n        <translation>Teclas de Atalho</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Export</source>\n        <translation>Exportar</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Importar</translation>\n    </message>\n    <message>\n        <location line=\"-44\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Acção</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Endereço do servidor:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Tipo de proxy:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Porta:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Nome de usuário:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Palavra-chave:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation type=\"unfinished\">Novo Ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\">Nova Função</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\">Nova Figura</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation type=\"unfinished\">Abrir Ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">Carregar Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\">Guardar Ambiente de Trabalho Como</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation type=\"unfinished\">Sair do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\">Copiar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\">Colar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\">Desfazer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\">Limpar Área de Transferência</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation type=\"unfinished\">Localizar Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\">Limpar Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\">Limpar Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\">Limpar Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\">Preferências</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\">Passo-a-passo</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\">Passo adentro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\">Passo afora</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\">Mostrar Navegador de Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\">Janela de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Histórico de Comandos</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Navegador de Ficheiros</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Ambiente de Trabalho</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Editor</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Documentação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation type=\"unfinished\">Mostrar Documentação Online</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Reportar Problema</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\">Bibliotecas do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation type=\"unfinished\">Contribuir para o Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation type=\"unfinished\">Recursos para Programadores do Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Sobre o Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\">Notas da Versão</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\">Novidades da Comunidade</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\">Ampliar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\">Diminuir</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation type=\"unfinished\">Zoom Normal</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation type=\"unfinished\">Editar Função</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation type=\"unfinished\">Guardar Ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation type=\"unfinished\">Guardar Ficheiro Como</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation type=\"unfinished\">Imprimir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation type=\"unfinished\">Refazer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\">Cortar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation type=\"unfinished\">Localizar e Substituir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\">Apagar até ao Início da Palavra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\">Apagar até ao Fim da Palavra</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\">Apagar até ao Início da Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\">Apagar até ao Fim da Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\">Apagar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\">Copiar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\">Cortar Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\">Duplicar Selecção/Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\">Transpor linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation type=\"unfinished\">Mostrar Lista de Completação</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation type=\"unfinished\">Comentar Selecção</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation type=\"unfinished\">Descomentar Selecção</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation type=\"unfinished\">MAIÚSCULAS</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation type=\"unfinished\">MINÚSCULAS</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation type=\"unfinished\">Converter Fins de Linha para Windows</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation type=\"unfinished\">Converter Fins de Linha para Unix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation type=\"unfinished\">Converter Fins de Linha para Mac</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation type=\"unfinished\">Ir para Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\">Selecionar até ao Parênteses Correspondente</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation type=\"unfinished\">Activar/desactivar Marcador</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation type=\"unfinished\">Marcador Seguinte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation type=\"unfinished\">Marcador Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation type=\"unfinished\">Remover Todos os Marcadores</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation type=\"unfinished\">Preferências de Estilo</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation type=\"unfinished\">Mostrar Números de Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation type=\"unfinished\">Mostrar Whitespace</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation type=\"unfinished\">Mostrar Fins de Linha</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation type=\"unfinished\">Mostrar Guias de Indentação</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation type=\"unfinished\">Mostrar Guia de Linhas Longas</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation type=\"unfinished\">Ativar/desativar Breakpoint</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation type=\"unfinished\">Breakpoint Seguinte</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation type=\"unfinished\">Breakpoint Anterior</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation type=\"unfinished\">Remover Todos os Breakpoints</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation type=\"unfinished\">Executar Ficheiro</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\">Executar Selecção</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation type=\"unfinished\">Ajuda na Palavra-chave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation type=\"unfinished\">Documentação na Palavra-chave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/ru_RU.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"ru_RU\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Недопустимое имя файла</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Отличие от размера по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Цвет фона, по умолчанию розовый (255, 0, 255)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>ж</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>к</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>п</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>Изменить «%1»</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>Справка по «%1»</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>Документация по «%1»</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Копировать</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Вставить</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Выделить все</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Выполнить выделенное</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>Изменить выделенное</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>Справка по выделенному</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>Документация по выделенному</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Очистить окно</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Изменить строку %2 файла %1</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>выделенное скопировано в буфер обмена</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>По умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Ошибка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Комментарий</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Число</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключевое слово</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Строка в двойных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Строка в одинарных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Оператор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Идентификатор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Скаляр</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>Параметры разложения</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Обратные апострофы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Разделитель heredoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Heredoc в одинарных кавычках</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>По умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Комментарий</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключевое слово</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>Метка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>Скрыть командный символ</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>Внешеняя команда</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Переменная</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Оператор</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>По умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>Неактивный по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>Комментарий C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>Неактивный комментарий C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>Комментарий C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>Неактивный комментарий C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>Комментарий C в стиле JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>Неактивный комментарий C в стиле JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Число</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Неактивное число</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключевое слово</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Неактивное ключевое слово</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Строка в двойных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>Неактивная строка в двойных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Строка в одинарных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>Неактивная строка в одинарных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>Неактивный IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>Блок препроцессора</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>Неактивный блок препроцессора</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Оператор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Неактивный оператор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Идентификатор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Неактивный идентификатор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>Незавершённая строка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>Неактивная незавершённая строка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>Буквальная строка C#</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>Неактивная буквальная строка C#</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>Регулярное выражение JavaScript</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>Неактивное регулярное выражение JavaScript</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>Комментарий C++ в стиле JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>Неактивный комментарий C++ в стиле JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>Вторичные ключевые слова и идентификаторы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Неактивные вторичные ключевые слова и идентификаторы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>Ключевое слово JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>Неактивное ключевое слово JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>Ошибка ключевого слова JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>Неактивная ошибка ключевого слова JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Глобальные классы и определения типов</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Неактивные глобальные классы и определения типов</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>Неформатированная строка C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>Неактивная неформатированная строка C++</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation>Буквальная строка Vala в тройных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation>Неактивная буквальная строка Vala в тройных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation>Строка Pike в кавычках-решётках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation>Неактивная строка Pike в кавычках-решётках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation>Комментарий препроцессора C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation>Неактивный комментарий препроцессора C</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation>Комментарий препроцессора в стиле JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation>Неактивный комментарий препроцессора в стиле JavaDoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation>Определённый пользователем литерал</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation>Неактивный определённый пользователем литерал</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation>Метка задачи</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation>Неактивная метка задачи</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation>Управляющая последовательность</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation>Неактивная управляющая последовательность</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>По умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Комментарий</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Команда</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>Заголовок</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Положение</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Удалённая строка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Добавленная строка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Изменённая строка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation>Добавленное исправление с добавлениями</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation>Удалённое исправление с добавлениями</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation>Добавленное исправление с удалениями</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation>Удалённое исправление с удалениями</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>По умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Комментарий</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Команда</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Число</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключевое слово</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Строка в одинарных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Оператор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Идентификатор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Строка в двойных кавычках</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>По умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Ошибка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Комментарий</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Число</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Ключевое слово</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Строка в двойных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Строка в одинарных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Оператор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Идентификатор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Скаляр</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>Массив</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>Хэш</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Таблица символов</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>Регулярное выражение</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>Подстановка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Обратные апострофы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>Раздел данных</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Разделитель heredoc</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Heredoc в одинарных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>Heredoc в двойных кавычках</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>Heredoc в обратных апострофах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>Строка в кавычках (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>Строка в кавычках (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>Строка в кавычках (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>Строка в кавычках (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>Строка в кавычках (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>Буквальный POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>Прототип подпрограммы</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>Идентификатор формата</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>Тело формата</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>Строка в двойных кавычках (интерполированная переменная)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>Перевод</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>Регулярное выражение (интерполированная переменная)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>Подстановка (интерполированная переменная)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>Обратные апострофы (интерполированная переменная)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>Heredoc в двойных кавычках (интерполированная переменная)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>Heredoc в обратных апострофах (интерполированная переменная)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>Строка в кавычках (qq, интерполированная переменная)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>Строка в кавычках (qx, интерполированная переменная)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>Строка в кавычках (qr, интерполированная переменная)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>О&amp;тменить</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Повторить</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>Вы&amp;резать</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Копировать</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>&amp;Вставить</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Удалить</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Выделить все</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Открыть ссылку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Копировать адрес ссылки</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Отправить письмо...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>Копировать электронный адрес</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>Изменить строку %2 файла %1</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Комментарий</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Текст</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Строка</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Шрифт</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>полужирный</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>ж</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>курсив</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>к</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>цвет</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>слева</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>по центру</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>справа</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>Выравнивание по горизонтали</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>Выравнивание по вертикали</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>сверху</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>снизу</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Расположение</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Ширина</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Высота</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>единицы</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>нормализованный</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Вписать в рамку</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Обрамление</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Цвет фона</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Цвет контура</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Стиль линии</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>нет</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Толщина линии</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Выделить все</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Приостановить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Остановить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Продолжить</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Командный виджет</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Новости сообщества Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>По умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Ошибка</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>Запрос</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Документация Octave</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>Не удалось скопировать набор разделов справки\nво временный файл. Это может повлиять\nна возможности поиска.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>Не удалось получить данные, необходимые\nдля средства просмотра документации.\nВозможно, отсутствует модуль Qt SQlite.\nВ командном окне будет доступна только\nсправочная информация.</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>Содержание</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Введите текст для поиска индекса функций</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Поиск</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>Индекс функций</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Закладки</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>На главную</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Назад</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Предыдущие страницы</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>Вперёд</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Следующие страницы</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Найти</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Увеличить масштаб</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Уменьшить масштаб</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Сбросить масштаб</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>Текущая страница закладки</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>Не удаётся зарегистрировать файл справки %1.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nЗакладки документации не загружены!</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: загрузка закладок документации</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Введите текст для поиска по закладкам</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Фильтр</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Создать папку</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Открыть</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Переименовать</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>Удали&amp;ть</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>&amp;Добавить папку</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>Скрыть &amp;фильтр</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>Показать &amp;фильтр</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: сохранение закладок документации</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>Не удалось записать файл: %1:\n%2.\n\nЗакладки документации не сохранены!\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>Не удалось прочитать файл %1:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>Стартовый элемент не найден в %1.\nНедопустимый файл закладки?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>Файл\n%1\nне является допустимым файлом XBEL версии 1.0.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Неизвестный заголовок</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Документация</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Открыть документацию для получения справки.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Закрыть</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>Закрыть &amp;все</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>Закрыть &amp;остальные</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>Переключиться на &amp;левый виджет</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>Переключиться на &amp;правый виджет</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation>Открыть файлы редактора</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation>Щёлкните, чтобы выделить файл в редакторе</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Закрыть</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>Закрыть &amp;все</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Выполнить</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Установить текущий &amp;каталог</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Редактор Octave</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>Не удалось запустить пользовательский редактор файлов\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Пользовательский редактор файлов ещё не настроен.\nОткрыть параметры?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Продолжить</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Сохранить и выполнить</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Редактор Octave</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>Файл не сохранён. Файл с выбранным именем\n%1\nуже открыт в редакторе.</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>Вкладка связанного редактора файлов исчезла.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>Не удалось открыть файл\n%1\nдля чтения: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Файл\n%1\nне существует. Создать его?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Создать</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Отмена</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>Не удалось открыть файл\n%1\nдля записи: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Файл</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>По&amp;следние файлы</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>&amp;Изменить функцию</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>&amp;Сохранить</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>Сохранить &amp;как...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>З&amp;акрыть</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Закрыть все</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Закрыть другие файлы</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Печать...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Правка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Повторить</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>Вы&amp;резать</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>&amp;Найти и заменить...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>Найти &amp;далее</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>Найти &amp;ранее</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>&amp;Команды</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Удалить строку</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Копировать строку</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Вырезать строку</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Удалить до начала слова</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Удалить до конца слова</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Удалить до начала строки</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Удалить до конца строки</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Дублировать выделение/строку</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Переставить строку</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>Показать &amp;список завершения</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Формат</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>Перевести в &amp;верхний регистр</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>Перевести в &amp;нижний регистр</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>За&amp;комментировать</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>&amp;Раскомментировать</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Закомментировать (с выбором строки)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>&amp;Отступ для выделенного фрагмента</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>От&amp;менить отступ для выделенного фрагмента</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Расставить отступы для кода</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Преобразовать завершения строк в формат &amp;Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Преобразовать завершения строк в формат &amp;Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Преобразовать завершения строк в формат Legacy &amp;Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>Нави&amp;гация</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>&amp;Перейти к строке...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Перейти к парной скобке</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Выделить до парной скобки</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>С&amp;ледующая закладка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>Пр&amp;едыдущая закладка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>Пере&amp;ключить закладку</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>&amp;Удалить все закладки</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Параметры...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>Параметры &amp;стилей...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>&amp;Вид</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>&amp;Редактор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>Показывать &amp;номера строк</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>Показывать символ &amp;пробела</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Показывать символ &amp;конца строки</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>Показывать &amp;направляющие для отступов</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>Показывать &amp;метку длинных строк</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>Показывать панель &amp;инструментов</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>Показывать строку &amp;состояния</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>Показывать &amp;горизонтальную полосу прокрутки</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>У&amp;величить масштаб</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>У&amp;меньшить масштаб</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>&amp;Обычный масштаб</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>&amp;Упорядочить вкладки по алфавиту</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Отладка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>&amp;Переключить точку останова</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>&amp;Следующая точка останова</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>&amp;Предыдущая точка останова</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>&amp;Удалить все точки останова</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>&amp;Выполнение</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Сохранить и выполнить/продолжить</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>В&amp;ыполнить выделение</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Сохранить и выполнить все &amp;тесты</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Сохранить и выполнить все &amp;демо</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>С&amp;правка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>&amp;Найти справку по</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>Н&amp;айти документацию по</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>Последние файлы</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Копировать полный путь к &amp;файлу</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Редактор</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>строка:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>столбец:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>кодировка:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>конец строки:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Состояние точки останова</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>ОШИБКА: </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Редактор Octave</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>Не удалось добавить точку останова к изменённому или безымянному файлу.\nСохранить файл и добавить точку останова или отменить действие?</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Перейти к строке</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Номер строки</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Закомментировать выделенный текст</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Используемая строка комментария:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;без названия&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>Отменить закрытие, сохранить изменения или отклонить их?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>Файл\n\n  %1\n\nбыл изменён, но будет закрыт.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>Не удалось прочитать файл «%1»\nс выбранной кодировкой «%2»: %3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>При чтении файла\n%1\nвозникли проблемы с выбранной кодировкой %2.\n\nИзменение и сохранение файла может привести к потере данных!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>Всё равно &amp;изменить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>Изменить &amp;кодировку</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>З&amp;акрыть</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Выбор новой кодировки по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Выберите новую кодировку\nдля загрузки текущего файла.\n\nКодировка по умолчанию не будет изменена.\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Отладить или сохранить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Этот файл выполняется в данный момент.\nПрервать отладку и сохранить?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>Не удалось открыть файл %1 для записи:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>Не удалось сохранить изменения в файл\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Файлы Octave (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Все файлы (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>«%1»\nне является допустимым идентификатором.\n\nПри использовании данного имени файла\nвызов сценария путём использования его имени\nв качестве команды Octave будет недоступен.\n\nВыбрать другое имя?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>Выбранная кодировка %1 не позволяет закодировать\nтекущее содержимое редактора.\nЕё использование может привести к потере данных!\n\nИспользуйте другую кодировку!</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1\n уже существует\nПерезаписать его?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nПредупреждение: содержимое в редакторе было изменено!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>Похоже, файл «%1» был изменён другим приложением. Обновить его содержимое?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>Похоже, файл\n%1\nбыл удалён или переименован. Сохранить его?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Размер файла</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Тип файла</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Дата изменения</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Показывать скрытые файлы</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Чередующиеся цвета строк</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Введите путь или имя файла</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Перейти к папке уровнем выше</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Перейти к текущей рабочей папке Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Перейти к текущей рабочей папке Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Установить рабочую папку Octave</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Установить просматриваемую папку как рабочую папку Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Действия в текущей папке</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Показывать домашнюю папку</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Выбрать папку...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Найти файлы...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Создать файл...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Создать папку...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Дважды щёлкните для открытия файла/папки;\nщёлкните правой кнопкой мыши для других действий</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Переименовать...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Открыть</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Открыть в системном диспетчере файлов</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Открыть в текстовом редакторе</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Копировать выделение в буфер обмена</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Выполнить</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Загрузить данные</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Установить текущую директорию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Добавить к пути</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Выбранные каталоги</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Выбранные каталоги и подкаталоги</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Удалить из пути</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Удалить...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Удалить файл/каталог</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>Удалить все выбранные файлы (%1)?\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>Удалить\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>Невозможно удалить непустой каталог</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Ошибка удаления</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>Не удалось удалить файл «%1».</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Установить каталог диспетчера файлов</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Создать файл</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Создать файл в\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Новый файл.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Ошибка создания файла</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>Не удалось создать файл\n&quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Создать каталог</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>Создать каталог в\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Новый каталог</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>Не удалось переименовать файл «%1» в  «%2».</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Диспетчер файлов</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Обзор файлов</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>Файловая система</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>Файлы редактора</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>Удачной работы!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Назад</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Готово</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Отмена</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Мы надеемся, что вам понравится работать с Octave.&lt;/p&gt;\n&lt;p&gt;В случае возникновения проблем существует несколько путей их устранения, включая коммерческую поддержку, почтовые рассылки, wiki-сайт и другие варианты поддержки от сообщества.\nПолучить дополнительную информацию можно по адресу &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (открывается во внешнем браузере).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Для получения дополнительной информации об Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Посетите сайт &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (открывается во внешнем браузере)&lt;/li&gt;\n&lt;li&gt;Получите документацию в формате &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; или &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; (ссылки открываются во внешнем браузере)&lt;/li&gt;\n&lt;li&gt;Откройте браузер документации графического интерфейса Octave с помощью меню справки&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Редактор: поиск и замена</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Найти:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Введите текст поиска</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>За&amp;менить:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>Введите замещающий текст</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>&amp;Учитывать регистр</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>И&amp;скать с начала</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>Искать по &amp;кругу</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>Найти &amp;далее</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>Найти ра&amp;нее</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>&amp;Заменить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>Заменить &amp;все</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>Д&amp;ополнительно...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>Слово &amp;целиком</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>Регулярные &amp;выражения</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>Об&amp;ратный поиск</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>Поиск в &amp;выделенной области</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Искать с конца</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Искать с начала</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Результаты замены</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>Заменено элементов: %1</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Результаты поиска</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>Больше совпадений не найдено</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Поиск файлов</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Имя:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>Рабочая папка:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Укажите рабочую папку</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Обзор...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Выбор рабочей папки</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Текущая папка</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>Установить текущую папку как рабочую папку</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Поиск по подпапкам</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Рекурсивный поиск файлов по подпапкам</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Поиск в именах папок</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Включать подходящие папки в результаты поиска</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Без учёта регистра</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>Выполнять поиск без учёта регистра</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>Содержит текст:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>Включать в результаты поиска только файлы, содержащие указанный текст</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Текст для поиска</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Результаты: двойной щелчок открывает файл или устанавливает папку</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Результаты поиска</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>В режиме ожидания.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Введите шаблоны поиска имён файлов.\nНесколько разных шаблонов можно\nразделить символом «;», например «*.cc ; *.h»</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>Найти</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Начать поиск</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Остановить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Остановить поиск</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>Имя файла/расположение</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Содержимое файла</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>Поиск...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>Совпадений: %1</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Задание каталога для поиска</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Имя файла</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Каталог</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Щёлкните дважды, чтобы открыть файл</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Щёлкните дважды, чтобы установить каталог</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Найти:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>Найти далее</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Найти ранее</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Закрыть</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Закрыть диалоговое окно поиска</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Ошибка %1 при создании файла параметров\n%2\nУбедитесь, что у вас есть права на чтение и запись в\n%3\n\nГИП Octave должен быть закрыт.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Критическая ошибка Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Просмотр и поиск в журнале выполненных команд.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Копировать</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Выполнить</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Создать сценарий</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Скрыть фильтр</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Показать фильтр</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Дважды щёлкните команду для её перемещения в командное окно.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Введите текст для поиска по истории выполненных команд</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Фильтр</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Журнал выполненных команд</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Добро пожаловать в Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Далее</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Отмена</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Графическая оболочка Octave впервые используется на этом компьютере.\nНажмите «Далее» для создания файла конфигурации и запуска Octave.&lt;/p&gt;\n&lt;p&gt;Файл конфигурации хранится в &lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Открепить виджет</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Закрыть виджет</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>Выйти из Octave?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Сохранить область переменных как</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Загрузить область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>О программе Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Обзор каталогов</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Файлы Octave (*.m);;Все файлы (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Новая функция</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Имя новой функции:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>Функция %1 — встроенная, скомпилированная\nили подставляемая, поэтому не может быть изменена.</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>Не удаётся найти функцию %1</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Редактор Octave</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Файл</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Открыть...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Открыть существующий файл в редакторе</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Загрузить область переменных...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Сохранить область переменных как...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Выход</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Создать</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Создать сценарий</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Создать функцию...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Создать рисунок</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Правка</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Отменить</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Копировать</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Вставить</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Выделить все</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Очистить буфер обмена</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Найти файлы...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Очистить командное окно</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Очистить журнал выполненных команд</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Очистить область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Установить путь…</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Параметры...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>&amp;Отладка</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Шаг</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Шаг с заходом</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Шаг с выходом</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Продолжить</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Выйти из режима отладки</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>&amp;Сервис</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>Начать сеанс &amp;Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>&amp;Возобновить сеанс Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>&amp;Остановить Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>&amp;Показать данные Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>О&amp;кно</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Показывать командное окно</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Показывать журнал выполненных команд</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Показывать диспетчер файлов</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Показывать область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Показывать редактор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Показывать документацию</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Показывать редактор переменных</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Командное окно</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Журнал выполненных команд</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Диспетчер файлов</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Редактор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Документация</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Редактор переменных</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Предыдущий виджет</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Сбросить расположение окон</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Справка</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Сообщить об ошибке</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Пакеты Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>Принять участие</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Внести пожертвование</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>На диске</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>На веб-сайте Octave</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Новости</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Заметки о выпуске</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Новости сообщества</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Панель инструментов</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Введите имя папки</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Текущая папка: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Перейти к папке уровнем выше</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nНовости сообщества Octave недоступны.\n&lt;/p&gt;\n&lt;p&gt;\nДля получения информации о последних новостях посетите\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nпри наличии подключения к сети Интернет (ссылка открывается во внешнем браузере).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Разработчики Octave, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nПодключение к веб-сайту для отображения новостей сообщеста Octave запрещено.\n&lt;/p&gt;\n&lt;p&gt;\nДля получения информации о последних новостях посетите\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nпри наличии подключения к сети Интернет (ссылка открывается во внешнем браузере)\nили разрешите подключение к веб-сайту Octave в диалоговом окне параметров сети.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Разработчики Octave, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Скрыть виджет</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Закрепить виджет</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Открепить виджет</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>Справка по</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>Документация по</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>Изменить</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>Точка останова в случае...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Редактор Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>Ошибка при создании временных файлов.\nУбедитесь, что у вас есть доступ на запись во временный каталог\n%1\n\nДля выполнения операции «Выполнить выделение» необходимы временные файлы.</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>Нажмите «%1», чтобы заменить все вхождения «%2» на «%3».</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>По умолчанию</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Создать</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>Отмена</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Файл\n%1\nне существует. Создать его?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Редактор Octave</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>Файл %1 не существует по пути загрузки. Для выполнения или отладки редактируемой функции необходимо перейти в папку %2 или добавить её в путь загрузки.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>Файл %1 скрыт одноимённым файлом из пути загрузки. Для выполнения или отладки редактируемой функции перейдите в папку %2.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Перейти в папку или добавить её в путь загрузки</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>&amp;Перейти в папку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>Д&amp;обавить папку в путь загрузки</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>Файл «%1» с описанием изменений пуст.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>Файл «%1» с описанием изменений не может быть прочитан.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Описание изменений Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Установка пути</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Все изменения вступят в силу немедленно.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Добавить каталог…</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Одиночный каталог</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Каталог с вложенными каталогами</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>На самый верх</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>В самый низ</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Вверх</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Вниз</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Удалить</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Обновить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Сохранить</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Отменить изменения</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Отменить последнее изменение</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Отменить все изменения</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Открыть каталог</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>Сверху</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>Снизу</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>Слева</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>Справа</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Цвет текста</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Цвет фона</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Выделение</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>Курсор</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Цвет текста выделения</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Цвет фона выделения</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Чередующийся фон</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>аргумент</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>глобальная</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>постоянная</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Переменные окружения</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>Второй цветовой режим (светлый/тёмный)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>Переключение на второй набор цветов.\nПолезно для определения светлого/тёмного режимов.\nОтменяет не применённые текущие изменения!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>Перезагрузка цветов по умолчанию,\nзависит от выбранного в данный момент режима.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>Перезагрузка значений стилей по умолчанию,\nзависит от выбранного в данный момент режима.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>&amp;Перезагрузить цвета по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>&amp;Перезагрузить стили по умолчанию</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Загрузка текущих параметров … </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Используемый в системе</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>Вертикальная черта</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>Блок</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>Черта снизу</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>Цвет выделенной текущей строки (пурпурный (255,0,255) для автоматического цвета)</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Установить начальную папку для Octave</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Установить начальную папку для диспетчера файлов</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Применение параметров… </translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>Не удалось открыть %1 как файл сочетаний клавиш Octave</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Включить цветовое выделение свойств</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Скрывать всплывающие подсказки</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Импорт сочетаний клавиш из файла...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Файлы сочетаний клавиш Octave (*.osc);;Все файлы (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Экспорт сочетаний клавиш в файл...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Замена сочетаний клавиш</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Все сочетания клавиш будут заменены.\nСохранить текущий набор сочетаний клавиш или отменить действие?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>Не сохранять</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Параметры ГИП Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Новости сообщества</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Предыдущая</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Следующая</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>Отмена</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;При запуске Octave выборочно производится проверка веб-сайта Octave на предмет наличия новостей сообщества.\nПроверка производится не чаще раза в сутки, а новости отображаются только при их появлении с последнего просмотра.&lt;/p&gt;\n&lt;p&gt;Ознакомиться с новостями также можно, выбрав пункт «Новости сообщества» в меню «Справка» или перейдя по адресу\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Разрешить Octave проверять веб-сайт при запуске и оповещать о новостях сообщества.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Ввод нового сочетания клавиш</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Введите пользовательское сочетание клавиш\nДействие: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Введите сочетание клавиш, набрав его</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Добавить модификатор Shift\n(позволяет использовать клавиши с цифрами)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Текущее сочетание</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Сочетание по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Очистить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Установить по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Конфликт сочетаний клавиш</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>Выбранное сочетание клавиш\n  «%1»\nуже используется для действия\n  «%2».\nУдалить текущую привязку и использовать это сочетание?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Общие</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Меню «Файл»</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Меню «Правка»</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Меню «Отладка»</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Меню «Сервис»</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Меню «Окно»</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Меню «Справка»</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Меню «Новости»</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Поведение закрепляемых виджетов</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Поведение вкладок в закрепляемых виджетах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Поиск и замена в закрепляемых виджетах</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Изменение масштаба в редакторе и документации</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Редактор</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Меню «Вид»</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Меню «Выполнение»</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Средство просмотра документации</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Браузер</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>Элемент %1 не найден в диалоговом окне параметров сочетаний клавиш</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Добро пожаловать в GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Добро пожаловать в Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Командное окно</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Закрепить виджет</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Редактор переменных: </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Открепить виджет</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Восстановить размеры</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Закрепить снова</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Редактор переменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Изменение переменных.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Панель инструментов редактора переменных</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Сохранить</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Сохранить переменную в файл</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Сохранить в формате…</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Сохранить переменную в файл в другом формате</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Вырезать</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Вырезать данные в буфер обмена</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Копировать</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Копировать данные в буфер обмена</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Вставить</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Вставить данные из буфера обмена в переменную</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Отобразить</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Отобразить выделенные данные</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Отобразить выделенные данные</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Вверх</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>Перейти на уровень выше в иерархии переменных</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>Сохранить переменную %1 как</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Вырезать</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Копировать</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Вставить</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Очистить</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Удалить</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Создать переменную из выделения</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Транспонировать</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> столбцы</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> столбец</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> строки</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> строка</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>Добро пожаловать в GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>Имя</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Тип</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Размерность</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Значение</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Свойство</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Щёлкните правой кнопкой для копирования, переименования или отображения</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>комплексная</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Тип</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Размерность</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Значение</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Свойство</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Содержимое текущей области переменных.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Введите текст для поиска в области переменных</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Фильтр</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Содержимое текущей области переменных.&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Цветовое обозначение переменных:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Открыть в редакторе переменных</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Копировать имя</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Копировать значение</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Переименовать</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Переименование доступно только для символов верхнего уровня</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Скрыть фильтр</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Показать фильтр</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>Не удалось открыть перенаправленный поток с fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>Не удалось отключить буферизацию потока с fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>Не удалось дублировать перенаправленный поток с fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>Не удалось создать канал для перенаправления потока с fd = %1:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>Не удалось дублировать перенаправленный поток с fd = %1\nв канал с fd = %2: %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Ошибка при прослушивании перенаправленных потоков</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation>Ошибка при чтении из перенаправленного потока fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\nПеренаправление вывода в </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> не работает.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\nОшибка: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Основное</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Только логотип Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Значок с буквой</translation>\n    </message>\n    <message>\n        <location line=\"-334\"/>\n        <source>Dock widget title bar</source>\n        <translation>Заголовки виджетов</translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation>Маленькие</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Большие</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>Пользовательский стиль</translation>\n    </message>\n    <message>\n        <location line=\"+597\"/>\n        <source>Editor</source>\n        <translation>Редактор</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Хорошо работает для моноширинных шрифтов. Положение линии зависит от ширины символа пробела. В случае использования пропорционального шрифта линия может не совпадать с реальным положением переноса.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Включить сворачивание кода</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation>Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Показывать горизонтальную полосу прокрутки</translation>\n    </message>\n    <message>\n        <location line=\"-516\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Если установлено, фокус виджетов, привязанных к главному окну, следует за курсором мыши. Это предназначено для обеспечения одинакового поведения в главном окне, когда для рабочей среды используется «фокус следует за мышью».&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>Фокус следует за мышью для виджетов, прикреплённых к главному окну</translation>\n    </message>\n    <message>\n        <location line=\"+494\"/>\n        <source>Show tool bar</source>\n        <translation>Показывать панель инструментов</translation>\n    </message>\n    <message>\n        <location line=\"+221\"/>\n        <source>Rotated tabs</source>\n        <translation>Повёрнутые вкладки</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Положение</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>Макс. ширина вкладки в символах (0: без ограничений)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Макс. ширина вкладки в символах (средняя ширина символа). Особенно полезно для повёрнутых вкладок.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+260\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Переносить длинные строки у границы текущего окна</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Indentation</source>\n        <translation>Отступы</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation>Ширина отступа</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Показывать линии табуляции</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Автоматический отступ</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Интервал табуляции</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Показывать направляющие для отступов</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Уменьшение отступа клавишей Backspace</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Отступы табуляцией</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation>Автоматическое завершение</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>Совпадение по ключевым словам</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>С учётом регистра</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Заменять слово предложенным</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Совпадение по словам в документе</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation>Завершение встроенными\nсловами Octave</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Завершение функциями Octave</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Автоматически показывать список завершения</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Перезагружать файлы, изменённые другими программами без запроса</translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation>Использовать внешний редактор файлов</translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Кодировка по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation>Стили редактора</translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(изменение параметра очищает историю)</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation>Длина истории выполненных команд</translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Шрифт</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Показывать номера строк</translation>\n    </message>\n    <message>\n        <location line=\"-866\"/>\n        <source>Interface</source>\n        <translation>Внешний вид</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Подтверждать выход</translation>\n    </message>\n    <message>\n        <location line=\"-72\"/>\n        <source>Graphic icons</source>\n        <translation>Графический значок</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Показывать строку состояния</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Неактивный текст</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Активный</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Background inactive</source>\n        <translation>Неактивный фон</translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation>Запуск Octave</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Обзор</translation>\n    </message>\n    <message>\n        <location line=\"-1305\"/>\n        <source>Show whitespace</source>\n        <translation>Показывать символ пробела</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Не показывать пробелы, используемые для отступов</translation>\n    </message>\n    <message>\n        <location line=\"+1125\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Создавать отсутствующие файлы без запроса</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>команда (%f=файл, %l=строка):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>Тип курсора:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Использовать цвет текста</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Размер шрифта</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Диспетчер файлов</translation>\n    </message>\n    <message>\n        <location line=\"-2031\"/>\n        <source>Normal</source>\n        <translation>Обычные</translation>\n    </message>\n    <message>\n        <location line=\"+359\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Эти параметры применяются после загрузки конфигурационных файлов .octaverc.</translation>\n    </message>\n    <message>\n        <location line=\"+540\"/>\n        <source>Show EOL characters</source>\n        <translation>Показывать символ конца строки</translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation>Конец строки по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Минимальная длина слова до отображения списка: </translation>\n    </message>\n    <message>\n        <location line=\"-1812\"/>\n        <source>Preferences</source>\n        <translation>Параметры</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(требуется перезапуск)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Использовать встроенные\nдиалоги работы с файлами</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Значки панели инструментов</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Язык</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Значки окна закрепляемых виджетов</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Стиль</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Тема значков (требуется перезапуск)</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>3-D</source>\n        <translation>3D</translation>\n    </message>\n    <message>\n        <location line=\"+157\"/>\n        <source>Blinking cursor</source>\n        <translation>Мигающий курсор</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Показывать заставку при запуске</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Начальная рабочая папка интерпретатора Octave</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Восстанавливать последнюю рабочую папку предыдущего сеанса</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Команда</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Устанавливать фокус на командном окне при выполнении команды из другого виджета</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Выводить место отладки в командном окне помимо маркера в редакторе</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Цвета в командном окне</translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Нумеровать размер как отклонение от шрифта редактора</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Подсвечивать текущую строку (цвет настраивается ниже с помощью стилей редактора)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Подсвечивать все вхождения слова, выделенного двойным щелчком</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Вкладки</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Поворот вкладок: по вертикали, когда они находятся вверху или внизу, и по горизонтали, когда они находятся слева или справа. Кнопка закрытия не отображается в повёрнутых вкладках.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Комментарии (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Строки, учитываемые при раскомментировании текста</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Строка, используемая для комментирования выделенного текста</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Длинные строки</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Разрывать длинные строки</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Разрывать только строки комментариев</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Длина строк</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Метка длинных строк</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Линия</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Изменение фона</translation>\n    </message>\n    <message>\n        <location line=\"+191\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Автоматическая вставка после «if» и т. д.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Ничего</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>«endif» и т. д.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>«end»</translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation>Отладка</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Всегда показывать точки останова и указатели\n(приводит к открытию связанного файла)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Работа с файлами</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Восстанавливать вкладки редактора из предыдущего сеанса при запуске\nили при повторном отображении редактора после его закрытия</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Закрывать все файлы при закрытии/сокрытии виджета редактора</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>При сохранении файла вставлять символ новой строки в конце</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>При сохранении файла удалять конечные пробелы</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>Каталог диалогового окна открытия файла следует за текущим файлом редактора, а не за текущим каталогом Octave </translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Выберите шрифт, его размер (как разницу от размера по умолчанию), стиль шрифта (полу&lt;b&gt;ж&lt;/b&gt;ирный, &lt;b&gt;к&lt;/b&gt;урсив, &lt;b&gt;п&lt;/b&gt;одчёркнутый), цвет текста и фона (для фона пурпурный цвет (255,0,255) является цветом по умолчанию).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Behavior</source>\n        <translation>Поведение</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Восстанавливать последнюю папку предыдущего сеанса</translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Расширения файлов, котрые будут открываться в текстовом редакторе (разделённые «;»):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Цветовое обозначение переменных</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Использовать шрифт командного окна</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Импорт сочетаний клавиш</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Экспорт сочетаний клавиш</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Сбросить сочетания клавиш</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>По умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+232\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;OK&lt;/span&gt; — закрыть диалоговое окно и применить параметры&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Применить — &lt;/span&gt;применить параметры, но оставить диалоговое окно открытым&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Отмена — &lt;/span&gt;закрыть диалоговое окно и отменить ещё не применённые изменения&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Сбросить —&lt;/span&gt; перезагрузить параметры, сбросив ещё не применённые изменения&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-227\"/>\n        <source>Actual</source>\n        <translation>Текущее</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Сеть</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Разрешить подключаться к веб-сайту Octave для отображения новостей и другой информации</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Прокси-сервер</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Выберите &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; или &lt;span style=&quot; font-style:italic;&quot;&gt;Переменные окружения&lt;/span&gt;. При последнем выборе прокси берётся из первой непустой переменной окружения ALL_PROXY, HTTP_PROXY или HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Использовать прокси-сервер</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Редактор переменных</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Высота строк по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Ширина столбцов по умолчанию</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Цвета в редакторе переменных</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Использовать чередующиеся цвета строк</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Отключите общие сочетания клавиш, чтобы предотвратить\nконфликт с нажатиями системных клавиш.\nИсключения: Ctrl-C для прерывания интерпретатора\nи сочетания клавиш для переключения на другие виджеты.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Отключить глобальные сочетания клавиш при фокусе на командном окне</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Синхронизировать рабочую папку Octave с диспетчером файлов</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>Начальная папка диспетчера файлов (только при отсутствии синхронизации с рабочей папкой Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+302\"/>\n        <source>Shortcuts</source>\n        <translation>Сочетания клавиш</translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Отключите ускорители меню, чтобы предотвратить\nконфликт с нажатиями системных клавиш.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>Отключите ускорители меню главного окна, когда командное окно находится в фокусе</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation>Экспорт</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>Импорт</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Отредактируйте сочетание клавиш, дважды щёлкнув по столбцу «Текущее»</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Действие</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Имя узла:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Тип прокси-сервера:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Порт:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Имя пользователя:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Пароль:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Открепить/закрепить виджет</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Закрыть виджет</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Создать файл</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Создать функцию</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Создать рисунок</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Открыть файл</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Загрузить область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Сохранить область переменных как</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Выйти из Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Копировать</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Вставить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Отменить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Выделить все</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Очистить буфер обмена</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>Найти в файлах</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Очистить командное окно</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Очистить журнал выполненных команд</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Очистить область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Установить путь</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Параметры</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Шаг</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>Шаг с заходом</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Шаг с выходом</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Продолжить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Выйти из режима отладки</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Начать/остановить сеанс Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Возобновить сеанс Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Показать данные Profiler</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Показывать командное окно</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Показывать журнал выполненных команд</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Показывать диспетчер файлов</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Показывать область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Показывать редактор</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Показывать документацию</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Показывать редактор переменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Командное окно</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Журнал выполненных команд</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Диспетчер файлов</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Область переменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Редактор</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Документация</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Редактор переменных</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Предыдущий виджет</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Сбросить расположение окон</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Показать документацию на диске</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Показать документацию на веб-сайте Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Сообщить об ошибке</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Пакеты Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Внести вклад в Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Ресурсы разработчика Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>О программе Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Описание изменений</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Новости сообщества</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Закрыть вкладку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Закрыть все вкладки</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Закрыть остальные вкладки</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Переключиться на левую вкладку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Переключиться на правую вкладку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Переместить вкладку влево</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Переместить вкладку вправо</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Увеличить масштаб</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Уменьшить масштаб</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Обычный масштаб</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Изменить функцию</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Сохранить файл</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Сохранить файл как</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Печать</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Повторить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Вырезать</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Найти и заменить</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Найти далее</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Найти ранее</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Удалить до начала слова</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Удалить до конца слова</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Удалить до начала строки</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Удалить до конца строки</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Удалить строку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Копировать строку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Вырезать строку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Дублировать выделение/строку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Переставить строку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Показать список завершения</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Закомментировать выделенное</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Раскомментировать выделенное</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Закомментировать выделенное (с выбором строки)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Перевести в верхний регистр</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Перевести в нижний регистр</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Отступ для выделенного фрагмента</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Отменить отступ для выделенного фрагмента</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Расставить отступы для кода</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Преобразовать завершения строк в формат Windows</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Преобразовать завершения строк в формат Unix</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Преобразовать завершения строк в формат Mac</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Перейти к строке</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Перейти к парной скобке</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Выделить до парной скобки</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Переключить закладку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Следующая закладка</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Предыдущая закладка</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Удалить все закладки</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Параметры стиля</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Показывать номера строк</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Показывать символ пробела</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Показывать символ конца строки</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Показывать направляющие для отступов</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Показывать метку длинных строк</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Показывать панель инструментов</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Показывать строку состояния</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Показывать горизонтальную полосу прокрутки</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Упорядочить вкладки по алфавиту</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Переключить точку останова</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Следующая точка останова</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Предыдущая точка останова</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Удалить все точки останова</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Выполнить файл</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Выполнить выделенное</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Выполнить тесты</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Выполнить демо</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Найти справку по ключевому слову</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Найти документацию по ключевому слову</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>На домашнюю страницу</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>На предыдущую страницу</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>На следующую страницу</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Добавить эту страницу в закладки</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/sv_SE.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"sv_SE\" sourcelanguage=\"en_US\">\n    <context>\n        <name>QFileSystemModel</name>\n        <message>\n            <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n            <source>Invalid filename</source>\n            <translation>Ogiltigt filnamn</translation>\n        </message>\n    </context>\n    <context>\n        <name>QObject</name>\n        <message>\n            <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n            <source>Difference to the default size</source>\n            <translation>Skillnad mot standardstorleken</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Background color, magenta (255, 0, 255) means default</source>\n            <translation>Bakgrundsfärg, magenta (255, 0, 255) betyder standard</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>b</source>\n            <comment>short form for bold</comment>\n            <translation>b</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>i</source>\n            <comment>short form for italic</comment>\n            <translation>i</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>u</source>\n            <comment>short form for underlined</comment>\n            <translation>u</translation>\n        </message>\n    </context>\n    <context>\n        <name>QTerminal</name>\n        <message>\n            <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n            <source>Edit &quot;%1&quot;</source>\n            <translation>Redigera &quot;%1&quot;</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Help on &quot;%1&quot;</source>\n            <translation>Hjälp på &quot;%1&quot;</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>Documentation on &quot;%1&quot;</source>\n            <translation>Dokumentation på &quot;%1&quot;</translation>\n        </message>\n        <message>\n            <location line=\"+165\"/>\n            <source>Copy</source>\n            <translation>Kopiera</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Paste</source>\n            <translation>Klistra in</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Select All</source>\n            <translation>Markera allt</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Run Selection</source>\n            <translation>Kör markering</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Edit selection</source>\n            <translation>Redigera markering</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Help on selection</source>\n            <translation>Hjälp om markering</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Documentation on selection</source>\n            <translation>Dokumentation om markering</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Clear Window</source>\n            <translation>Rensa fönster</translation>\n        </message>\n        <message>\n            <location line=\"-233\"/>\n            <source>Edit %1 at line %2</source>\n            <translation>Redigera %1 på rad %2</translation>\n        </message>\n    </context>\n    <context>\n        <name>QWinTerminalImpl</name>\n        <message>\n            <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n            <source>copied selection to clipboard</source>\n            <translation>kopierade markeringen till urklipp</translation>\n        </message>\n    </context>\n    <context>\n        <name>UrlFilter</name>\n        <message>\n            <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n            <source>Open Link</source>\n            <translation>Öppna länk</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Copy Link Address</source>\n            <translation>Kopiera länkadress</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Send Email To...</source>\n            <translation>Skicka e-post till...</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Copy Email Address</source>\n            <translation>Kopiera e-postadress</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <location line=\"+12\"/>\n            <source>Edit %1 at line %2</source>\n            <translation>Redigera %1 på rad %2</translation>\n        </message>\n    </context>\n    <context>\n        <name>annotation_dialog</name>\n        <message>\n            <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n            <source>Annotation</source>\n            <translation>Annotation</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Text</source>\n            <translation>Text</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>String</source>\n            <translation>Sträng</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>Font</source>\n            <translation>Teckensnitt</translation>\n        </message>\n        <message>\n            <location line=\"+42\"/>\n            <source>bold</source>\n            <translation>fet</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>b</source>\n            <translation>b</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>italic</source>\n            <translation>kursiv</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>i</source>\n            <translation>i</translation>\n        </message>\n        <message>\n            <location line=\"+428\"/>\n            <source>color</source>\n            <translation>färg</translation>\n        </message>\n        <message>\n            <location line=\"+33\"/>\n            <source>left</source>\n            <translation>vänster</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <location line=\"+29\"/>\n            <source>middle</source>\n            <translation>mitten</translation>\n        </message>\n        <message>\n            <location line=\"-24\"/>\n            <source>right</source>\n            <translation>höger</translation>\n        </message>\n        <message>\n            <location line=\"-21\"/>\n            <source>Horizontal alignment</source>\n            <translation>Horisontell justering</translation>\n        </message>\n        <message>\n            <location line=\"+29\"/>\n            <source>Vertical alignment</source>\n            <translation>Vertikal justering</translation>\n        </message>\n        <message>\n            <location line=\"+11\"/>\n            <source>top</source>\n            <translation>överst</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>bottom</source>\n            <translation>nederst</translation>\n        </message>\n        <message>\n            <location line=\"+11\"/>\n            <source>Position</source>\n            <translation>Position</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>X</source>\n            <translation>X</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>Y</source>\n            <translation>Y</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>Width</source>\n            <translation>Bredd</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>Height</source>\n            <translation>Höjd</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>units</source>\n            <translation>enheter</translation>\n        </message>\n        <message>\n            <location line=\"+11\"/>\n            <source>normalized</source>\n            <translation>normaliserad</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Fit to box</source>\n            <translation>Anpassa till boxen</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>Box</source>\n            <translation>Box</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Background</source>\n            <translation>Bakgrund</translation>\n        </message>\n        <message>\n            <location line=\"+444\"/>\n            <source>Edge</source>\n            <translation>Edge</translation>\n        </message>\n        <message>\n            <location line=\"+133\"/>\n            <source>Line style</source>\n            <translation>Radstil</translation>\n        </message>\n        <message>\n            <location line=\"+11\"/>\n            <source>none</source>\n            <translation>ingen</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Line width</source>\n            <translation>Radbredd</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::ListDialog</name>\n        <message>\n            <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n            <source>Select All</source>\n            <translation>Markera allt</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::command_widget</name>\n        <message>\n            <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n            <source>Pause</source>\n            <translation>Pausa</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Stop</source>\n            <translation>Stopp</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Continue</source>\n            <translation>Fortsätt</translation>\n        </message>\n        <message>\n            <location line=\"+57\"/>\n            <source>Command Widget</source>\n            <translation>Kommando-gränssnittskomponent</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::community_news</name>\n        <message>\n            <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n            <source>Octave Community News</source>\n            <translation>Octave gemenskap-nyheter</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::console_lexer</name>\n        <message>\n            <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n            <source>Default</source>\n            <translation>Standard</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Error</source>\n            <translation>Fel</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Prompt</source>\n            <translation>Uppmaning</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::documentation</name>\n        <message>\n            <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n            <location line=\"+14\"/>\n            <location line=\"+721\"/>\n            <source>Octave Documentation</source>\n            <translation>Octave-dokumentation</translation>\n        </message>\n        <message>\n            <location line=\"-734\"/>\n            <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n            <translation>Kunde inte kopiera hjälpsamlingen till den tillfälliga\nfilen. Sökfunktionerna kan påverkas.\n%1</translation>\n        </message>\n        <message>\n            <location line=\"+14\"/>\n            <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n            <translation>Kunde inte konfigurera de data som krävs för\ndokumentationsvisaren. Kanske saknas\nQt SQlite-modulen?\nEndast hjälptext i kommandofönstret kommer\natt vara tillgänglig.</translation>\n        </message>\n        <message>\n            <location line=\"+63\"/>\n            <source>Contents</source>\n            <translation>Innehåll</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Enter text to search function index</source>\n            <translation>Ange text för att söka i funktionsindex</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <location line=\"+51\"/>\n            <source>Search</source>\n            <translation>Sök</translation>\n        </message>\n        <message>\n            <location line=\"-35\"/>\n            <source>Function Index</source>\n            <translation>Funktionsindex</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>Bookmarks</source>\n            <translation>Bokmärken</translation>\n        </message>\n        <message>\n            <location line=\"+92\"/>\n            <source>Go home</source>\n            <translation>Gå hem</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Go back</source>\n            <translation>Gå tillbaka</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Previous pages</source>\n            <translation>Föregående sidor</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Go forward</source>\n            <translation>Gå framåt</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Next pages</source>\n            <translation>Nästa sidor</translation>\n        </message>\n        <message>\n            <location line=\"+37\"/>\n            <source>Find</source>\n            <translation>Hitta</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Zoom In</source>\n            <translation>Zooma in</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Zoom Out</source>\n            <translation>Zooma ut</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Zoom Original</source>\n            <translation>Ursprunglig zoom</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Bookmark current page</source>\n            <translation>Bokmärk aktuell sida</translation>\n        </message>\n        <message>\n            <location line=\"+430\"/>\n            <source>Unable to register help file %1.</source>\n            <translation>Kunde inte registrera hjälpfilen %1.</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::documentation_bookmarks</name>\n        <message>\n            <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n            <source>\nNo documentation bookmarks loaded!</source>\n            <translation>\nInga dokumentationsbokmärken har lästs in!</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Octave: Loading Documentation Bookmarks</source>\n            <translation>Octave: Läsa in dokumentationsbokmärken</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Enter text to search the bookmarks</source>\n            <translation>Ange text för att söka i bokmärkena</translation>\n        </message>\n        <message>\n            <location line=\"+25\"/>\n            <source>Filter</source>\n            <translation>Filter</translation>\n        </message>\n        <message>\n            <location line=\"+86\"/>\n            <source>New Folder</source>\n            <translation>Ny mapp</translation>\n        </message>\n        <message>\n            <location line=\"+104\"/>\n            <source>&amp;Open</source>\n            <translation>&amp;Öppna</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>&amp;Rename</source>\n            <translation>&amp;Rename</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Remo&amp;ve</source>\n            <translation>&amp;Ta bort</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;Add Folder</source>\n            <translation>&amp;Lägg till mapp</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Hide &amp;Filter</source>\n            <translation>&amp;Dölj Filter</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show &amp;Filter</source>\n            <translation>Visa &amp;filter</translation>\n        </message>\n        <message>\n            <location line=\"+66\"/>\n            <source>Octave: Saving Documentation Bookmarks</source>\n            <translation>Octave: Spara dokumentationsbokmärken</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Unable to write file %1:\n%2.\nDocumentation bookmarks are not saved!\n</source>\n            <translation>Kunde inte skriva filen %1:\n%2.\nDokumentationsbokmärken sparas inte!\n</translation>\n        </message>\n        <message>\n            <location line=\"+57\"/>\n            <source>Unable to read file %1:\n%2.</source>\n            <translation>Kunde inte läsa filen %1:\n%2.</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>No start element found in %1.\nInvalid bookmark file?</source>\n            <translation>Inget startelement hittades i %1.\nOgiltig bokmärkesfil?</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n            <translation>Filen\n%1\när inte en giltig XBEL-fil version 1.0.</translation>\n        </message>\n        <message>\n            <location line=\"+27\"/>\n            <source>Unknown title</source>\n            <translation>Okänd titel</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::documentation_dock_widget</name>\n        <message>\n            <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n            <source>Documentation</source>\n            <translation>Dokumentation</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>See the documentation for help.</source>\n            <translation>Se dokumentationen för hjälp.</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::dw_main_window</name>\n        <message>\n            <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n            <source>&amp;Close</source>\n            <translation>&amp;Stäng</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Close &amp;All</source>\n            <translation>&amp;Stäng Alla</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Close &amp;Other</source>\n            <translation>Stäng &amp;annan</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Switch to &amp;Left Widget</source>\n            <translation>Växla till &amp;vänster gränssnittskomponent</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Switch to &amp;Right Widget</source>\n            <translation>Växla till &amp;höger gränssnittskomponent</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::editor_files_browser</name>\n        <message>\n            <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n            <source>Open Editor Files</source>\n            <translation>Öppna redigeringsfiler</translation>\n        </message>\n        <message>\n            <location line=\"+17\"/>\n            <source>Click to focus file in editor</source>\n            <translation>Klicka för att fokusera filen i redigeraren</translation>\n        </message>\n        <message>\n            <location line=\"+92\"/>\n            <source>&amp;Close</source>\n            <translation>&amp;Stäng</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Close &amp;All</source>\n            <translation>Stäng &amp;alla</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Run</source>\n            <translation>Kör</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Set Current &amp;Directory</source>\n            <translation>Ange aktuell &amp;katalog</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::external_editor_interface</name>\n        <message>\n            <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n            <location line=\"+50\"/>\n            <source>Octave Editor</source>\n            <translation>Octave-redigeraren</translation>\n        </message>\n        <message>\n            <location line=\"-49\"/>\n            <source>Could not start custom file editor\n%1</source>\n            <translation>Kunde inte starta den anpassade filredigeraren \n%1</translation>\n        </message>\n        <message>\n            <location line=\"+50\"/>\n            <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n            <translation>Det finns ingen anpassad redigerare konfigurerad ännu.\nVill du öppna inställningarna?</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::file_editor</name>\n        <message>\n            <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n            <source>Continue</source>\n            <translation>Fortsätt</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Save File and Run</source>\n            <translation>Spara fil och kör</translation>\n        </message>\n        <message>\n            <location line=\"+1018\"/>\n            <location line=\"+29\"/>\n            <location line=\"+566\"/>\n            <location line=\"+18\"/>\n            <location line=\"+25\"/>\n            <source>Octave Editor</source>\n            <translation>Octave-redigeraren</translation>\n        </message>\n        <message>\n            <location line=\"-637\"/>\n            <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n            <translation>Filen sparades inte! En fil med det valda namnet\n%1\när already öppna i redigerare.</translation>\n        </message>\n        <message>\n            <location line=\"+29\"/>\n            <source>The associated file editor tab has disappeared.</source>\n            <translation>Den associerade filredigerarfliken har försvunnit.</translation>\n        </message>\n        <message>\n            <location line=\"+566\"/>\n            <source>Could not open file\n%1\nfor reading: %2.</source>\n            <translation>Kunde inte öppna filen\n%1\nför reading: %2.</translation>\n        </message>\n        <message>\n            <location line=\"+18\"/>\n            <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n            <translation>Filen\n%1\nfinns inte. Vill du skapa den?</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Create</source>\n            <translation>Skapa</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Cancel</source>\n            <translation>Avbryt</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>Could not open file\n%1\nfor writing: %2.</source>\n            <translation>Kunde inte öppna filen\n%1\nför att skriva: %2.</translation>\n        </message>\n        <message>\n            <location line=\"+271\"/>\n            <source>&amp;File</source>\n            <translation>&amp;Fil</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>&amp;Recent Editor Files</source>\n            <translation>&amp;Senaste redigeringsfiler</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>&amp;Edit Function</source>\n            <translation>&amp;Redigera Funktion</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>&amp;Save File</source>\n            <translation>&amp;Spara Fil</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Save File &amp;As...</source>\n            <translation>Spara fil &amp;som...</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>&amp;Close</source>\n            <translation>&amp;Stäng</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Close All</source>\n            <translation>Stäng alla</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Close Other Files</source>\n            <translation>Stäng andra filer</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Print...</source>\n            <translation>Skriv ut...</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>&amp;Edit</source>\n            <translation>&amp;Redigera</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>&amp;Redo</source>\n            <translation>&amp;Gör om</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Cu&amp;t</source>\n            <translation>Klipp u&amp;t</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;Find and Replace...</source>\n            <translation>&amp;Sök och ersätt...</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Find &amp;Next</source>\n            <translation>Hitta &amp;nästa</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Find &amp;Previous</source>\n            <translation>Hitta &amp;föregående</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;Commands</source>\n            <translation>&amp;Kommandon</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Delete Line</source>\n            <translation>Ta bort rad</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Copy Line</source>\n            <translation>Kopiera rad</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Cut Line</source>\n            <translation>Klipp ut rad</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Delete to Start of Word</source>\n            <translation>Ta bort till början av ord</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Delete to End of Word</source>\n            <translation>Ta bort till slutet av ordet</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Delete to Start of Line</source>\n            <translation>Ta bort till början av raden</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Delete to End of Line</source>\n            <translation>Ta bort till slutet av raden</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Duplicate Selection/Line</source>\n            <translation>Duplicera markering/rad</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Transpose Line</source>\n            <translation>Transponera rad</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>&amp;Show Completion List</source>\n            <translation>&amp;Visa kompletteringslista</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>&amp;Format</source>\n            <translation>&amp;Format</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>&amp;Uppercase Selection</source>\n            <translation>&amp;Versaler-markering</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>&amp;Lowercase Selection</source>\n            <translation>&amp;Gemener-markering</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>&amp;Comment</source>\n            <translation>&amp;Kommentera</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>&amp;Uncomment</source>\n            <translation>&amp;Avkommentera</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Comment (Choosing String)</source>\n            <translation>Kommentara (välja sträng)</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>&amp;Indent Selection Rigidly</source>\n            <translation>&amp;Gör fast indrag markering</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>&amp;Unindent Selection Rigidly</source>\n            <translation>&amp;Ta bort fast indrag markering</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Indent Code</source>\n            <translation>Gör kodindrag</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n            <translation>Konvertera radavslutningar till &amp;Windows (CRLF)</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Convert Line Endings to &amp;Unix (LF)</source>\n            <translation>Konvertera radavslutningar till &amp;Unix (LF)</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n            <translation>Konvertera radavslutningar till äldre &amp;Mac (CR)</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Navi&amp;gation</source>\n            <translation>Navi&amp;gation</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Go &amp;to Line...</source>\n            <translation>Gå &amp;till rad...</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Move to Matching Brace</source>\n            <translation>Flytta till matchande klammerparentes</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Select to Matching Brace</source>\n            <translation>Markera till matchande klammerparentes</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>&amp;Next Bookmark</source>\n            <translation>&amp;Nästa bokmärke</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Pre&amp;vious Bookmark</source>\n            <translation>Föreg&amp;ående bokmärke</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Toggle &amp;Bookmark</source>\n            <translation>Växla &amp;bokmärke</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>&amp;Remove All Bookmarks</source>\n            <translation>&amp;Ta bort alla bokmärken</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>&amp;Preferences...</source>\n            <translation>&amp;Inställningar...</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;Styles Preferences...</source>\n            <translation>&amp;Stilinställningar...</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;View</source>\n            <translation>&amp;Visa</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>&amp;Editor</source>\n            <translation>&amp;Redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show &amp;Line Numbers</source>\n            <translation>Visa &amp;radnummer</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Show &amp;Whitespace Characters</source>\n            <translation>Visa &amp;blankstegstecken</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Show Line &amp;Endings</source>\n            <translation>Visa rad&amp;avslutningar</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Show &amp;Indentation Guides</source>\n            <translation>Visa &amp;indragningsstödlinjer</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Show Long Line &amp;Marker</source>\n            <translation>Visa lång rad&amp;markör</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Show &amp;Toolbar</source>\n            <translation>Visa &amp;verktygsfält</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Show &amp;Statusbar</source>\n            <translation>Visa &amp;statusfält</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Show &amp;Horizontal Scrollbar</source>\n            <translation>Visa &amp;horisontell rullningslist</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Zoom &amp;In</source>\n            <translation>Zooma &amp;in</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Zoom &amp;Out</source>\n            <translation>Zooma &amp;ut</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>&amp;Normal Size</source>\n            <translation>&amp;Normal storlek</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;Sort Tabs Alphabetically</source>\n            <translation>&amp;Sortera flikar alfabetiskt</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>&amp;Debug</source>\n            <translation>&amp;Felsök</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Toggle &amp;Breakpoint</source>\n            <translation>Växla &amp;brytpunkt</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;Next Breakpoint</source>\n            <translation>&amp;Nästa brytpunkt</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Pre&amp;vious Breakpoint</source>\n            <translation>Föregå&amp;ende brytpunkt</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;Remove All Breakpoints</source>\n            <translation>&amp;Ta bort alla brytpunkter</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>&amp;Run</source>\n            <translation>&amp;Kör</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Save File and Run/Continue</source>\n            <translation>Spara fil och kör/fortsätt</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Run &amp;Selection</source>\n            <translation>Kör &amp;markering</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Save File and Run All &amp;Tests</source>\n            <translation>Spara fil och kör alla &amp;tester</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Save File and Run All &amp;Demos</source>\n            <translation>Spara fil och kör alla &amp;demoversioner</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;Help</source>\n            <translation>&amp;Hjälp</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>&amp;Help on Keyword</source>\n            <translation>&amp;Hjälp med nyckelord</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&amp;Documentation on Keyword</source>\n            <translation>&amp;Dokumentation om nyckelord</translation>\n        </message>\n        <message>\n            <location line=\"+25\"/>\n            <source>Recent Files</source>\n            <translation>Senaste filer</translation>\n        </message>\n        <message>\n            <location line=\"+49\"/>\n            <source>Copy Full File &amp;Path</source>\n            <translation>Kopiera fullständig fil&amp;sökväg</translation>\n        </message>\n        <message>\n            <location line=\"+16\"/>\n            <source>Editor</source>\n            <translation>Redigerare</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::file_editor_tab</name>\n        <message>\n            <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n            <source>line:</source>\n            <translation>rad:</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>col:</source>\n            <translation>kol:</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>encoding:</source>\n            <translation>kodning:</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>eol:</source>\n            <translation>radavslut:</translation>\n        </message>\n        <message>\n            <location line=\"+259\"/>\n            <source>Breakpoint condition</source>\n            <translation>Brytpunktsvillkor</translation>\n        </message>\n        <message>\n            <location line=\"+70\"/>\n            <source>ERROR: </source>\n            <translation>FEL: </translation>\n        </message>\n        <message>\n            <location line=\"+87\"/>\n            <location line=\"+1260\"/>\n            <location line=\"+152\"/>\n            <location line=\"+20\"/>\n            <location line=\"+444\"/>\n            <location line=\"+110\"/>\n            <location line=\"+103\"/>\n            <location line=\"+38\"/>\n            <location line=\"+60\"/>\n            <location line=\"+59\"/>\n            <location line=\"+36\"/>\n            <source>Octave Editor</source>\n            <translation>Octave Redigeraeller</translation>\n        </message>\n        <message>\n            <location line=\"-2281\"/>\n            <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n            <translation>Kan inte lägga till brytpunkt till ändrad eller namnlös fil.\nSpara och lägga till brytpunkt, eller avbryt?</translation>\n        </message>\n        <message>\n            <location line=\"+924\"/>\n            <source>Goto line</source>\n            <translation>Gå till rad</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Line number</source>\n            <translation>Radnummer</translation>\n        </message>\n        <message>\n            <location line=\"+133\"/>\n            <source>Comment selected text</source>\n            <translation>Kommentera markerad text</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Comment string to use:\n</source>\n            <translation>Kommentarsträng att använda:\n</translation>\n        </message>\n        <message>\n            <location line=\"+140\"/>\n            <location line=\"+57\"/>\n            <source>&lt;unnamed&gt;</source>\n            <translation>&lt;namnlös&gt;</translation>\n        </message>\n        <message>\n            <location line=\"-6\"/>\n            <source>Do you want to cancel closing, save, or discard the changes?</source>\n            <translation>Vill du avbryta stängningen, spara eller ignorera ändringarna?</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>The file\n  %1\nis about to be closed but has been modified.  %2</source>\n            <translation>Filen\n  %1\nhåller på att stängas men har ändrats.  %2</translation>\n        </message>\n        <message>\n            <location line=\"+152\"/>\n            <source>Unable to read file '%1'\nwith selected encoding '%2': %3</source>\n            <translation>Kunde inte läsa filen '%1'\nmed markerad kodning '%2': %3</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>There were problems reading the file\n%1\nwith the selected encoding %2.\nModifying and saving the file might cause data loss!</source>\n            <translation>Det uppstod problem med att läsa filen\n%1\nmed markerad kodning %2.\nAtt ändra och spara filen kan orsaka dataförlust!</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>&amp;Edit anyway</source>\n            <translation>&amp;Redigera ändå</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <location line=\"+45\"/>\n            <source>Chan&amp;ge encoding</source>\n            <translation>Änd&amp;ra kodning</translation>\n        </message>\n        <message>\n            <location line=\"-43\"/>\n            <location line=\"+36\"/>\n            <source>&amp;Close</source>\n            <translation>&amp;Stäng</translation>\n        </message>\n        <message>\n            <location line=\"+11\"/>\n            <source>Select new default encoding</source>\n            <translation>Välj ny standardkodning</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Please select a new encoding\nfor reloading the current file.\nThis does not change the default encoding.\n</source>\n            <translation>Välj en ny kodning\nför att ladda om den aktuella filen.\nDetta ändrar inte standardkodningen.\n</translation>\n        </message>\n        <message>\n            <location line=\"+179\"/>\n            <source>Debug or Save</source>\n            <translation>Felsök eller spara</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>This file is currently being executed.\nQuit debugging and save?</source>\n            <translation>Den här filen körs för närvarande.\nAvsluta felsökningen och spara?</translation>\n        </message>\n        <message>\n            <location line=\"+211\"/>\n            <source>Could not open file %1 for writing:\n%2.</source>\n            <translation>Kunde inte öppna filen %1 för skrivning:\n%2.</translation>\n        </message>\n        <message>\n            <location line=\"+110\"/>\n            <source>The changes could not be saved to the file\n%1</source>\n            <translation>Ändringarna kunde inte sparas i filen\n%1</translation>\n        </message>\n        <message>\n            <location line=\"+35\"/>\n            <source>Octave Files (*.m)</source>\n            <translation>Octave-filer (*.m)</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>All Files (*)</source>\n            <translation>Alla filer (*)</translation>\n        </message>\n        <message>\n            <location line=\"+105\"/>\n            <source>&quot;%1&quot;\nis not a valid identifier.\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\nDo you want to choose another name?</source>\n            <translation>&quot;%1&quot;\när inte en giltig identifierare.\nOm du behåller detta filnamn kommer du inte att kunna\nanropa ditt skript med dess namn som ett Octave-kommando.\nVill du välja ett annat namn?</translation>\n        </message>\n        <message>\n            <location line=\"+60\"/>\n            <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\nPlease select another one!</source>\n            <translation>Innehållet i den aktuella redigeraren kan inte kodas\nmed den markerade kodningen %1.\nAtt använda den skulle resultera i dataförlust!\n Välj en annan!</translation>\n        </message>\n        <message>\n            <location line=\"-98\"/>\n            <source>%1\n already exists\nDo you want to overwrite it?</source>\n            <translation>%1\n finns redan\nVill du skriva över den?</translation>\n        </message>\n        <message>\n            <location line=\"+152\"/>\n            <location line=\"+34\"/>\n            <source>\nWarning: The contents in the editor is modified!</source>\n            <translation>\nVarning: innehållet i redigeraren är ändrat!</translation>\n        </message>\n        <message>\n            <location line=\"-29\"/>\n            <source>It seems that '%1' has been modified by another application. Do you want to reload it?%2</source>\n            <translation>Det verkar som att '%1' har ändrats av ett annat program. Vill du ladda om det?%2</translation>\n        </message>\n        <message>\n            <location line=\"+36\"/>\n            <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n            <translation>Det verkar som att filen\n%1\nhar tagits bort eller bytt namn. Vill du spara den nu?%2</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::file_system_browser</name>\n        <message>\n            <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n            <source>File size</source>\n            <translation>Filstorlek</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>File type</source>\n            <translation>Filtyp</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Date modified</source>\n            <translation>Ändringsdatum</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show hidden</source>\n            <translation>Visa dolda</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Alternating row colors</source>\n            <translation>Alternerande radfärger</translation>\n        </message>\n        <message>\n            <location line=\"+22\"/>\n            <source>Enter the path or filename</source>\n            <translation>Ange sökväg eller filnamn</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>One directory up</source>\n            <translation>En katalog upp</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show Octave directory</source>\n            <translation>Visa Octave-katalog</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Go to current Octave directory</source>\n            <translation>Gå till aktuell Octave-katalog</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Set Octave directory</source>\n            <translation>Ange in Octave-katalog</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Set Octave directory to current browser directory</source>\n            <translation>Ställ in Octave-katalogen till aktuell hanterarkatalog</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Actions on current directory</source>\n            <translation>Åtgärder i aktuell katalog</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show Home Directory</source>\n            <translation>Visa hemkatalog</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>Set Browser Directory...</source>\n            <translation>Ange hanterarkatalog...</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <location line=\"+433\"/>\n            <source>Find Files...</source>\n            <translation>Hitta filer...</translation>\n        </message>\n        <message>\n            <location line=\"-429\"/>\n            <location line=\"+441\"/>\n            <source>New File...</source>\n            <translation>Ny fil...</translation>\n        </message>\n        <message>\n            <location line=\"-438\"/>\n            <location line=\"+440\"/>\n            <source>New Directory...</source>\n            <translation>Ny katalog...</translation>\n        </message>\n        <message>\n            <location line=\"-385\"/>\n            <source>Double-click to open file/folder, right click for alternatives</source>\n            <translation>Dubbelklicka för att öppna fil/mapp, högerklicka för alternativ</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>Rename...</source>\n            <translation>Byt namn...</translation>\n        </message>\n        <message>\n            <location line=\"+312\"/>\n            <source>Open</source>\n            <translation>Öppna</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Open in System File Explorer</source>\n            <translation>Öppna i systemfilsutforskaren</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Open in Text Editor</source>\n            <translation>Öppna i textredigeraren</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Copy Selection to Clipboard</source>\n            <translation>Kopiera markering till urklipp</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Run</source>\n            <translation>Kör</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Load Data</source>\n            <translation>Ladda data</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Set Current Directory</source>\n            <translation>Ange aktuell katalog</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Add to Path</source>\n            <translation>Lägg till i sökväg</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <location line=\"+7\"/>\n            <source>Selected Directories</source>\n            <translation>Markerade kataloger</translation>\n        </message>\n        <message>\n            <location line=\"-5\"/>\n            <location line=\"+7\"/>\n            <source>Selected Directories and Subdirectories</source>\n            <translation>Markerade kataloger och underkataloger</translation>\n        </message>\n        <message>\n            <location line=\"-4\"/>\n            <source>Remove from Path</source>\n            <translation>Ta bort från sökväg</translation>\n        </message>\n        <message>\n            <location line=\"+15\"/>\n            <source>Delete...</source>\n            <translation>Ta bort...</translation>\n        </message>\n        <message>\n            <location line=\"+140\"/>\n            <location line=\"+11\"/>\n            <location line=\"+17\"/>\n            <source>Delete file/directory</source>\n            <translation>Ta bort fil/katalog</translation>\n        </message>\n        <message>\n            <location line=\"-27\"/>\n            <source>Are you sure you want to delete all %1 selected files?\n</source>\n            <translation>Är du säker på att du vill ta bort alla %1 markerade filer?\n</translation>\n        </message>\n        <message>\n            <location line=\"+11\"/>\n            <source>Are you sure you want to delete\n</source>\n            <translation>Är du säker på att du vill ta bort\n</translation>\n        </message>\n        <message>\n            <location line=\"+17\"/>\n            <source>Can not delete a directory that is not empty</source>\n            <translation>Kan inte ta bort en katalog som inte är tom</translation>\n        </message>\n        <message>\n            <location line=\"+12\"/>\n            <source>Deletion error</source>\n            <translation>Borttagningsfel</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Could not delete file &quot;%1&quot;.</source>\n            <translation>Kunde inte ta bort filen &quot;%1&quot;.</translation>\n        </message>\n        <message>\n            <location line=\"+216\"/>\n            <source>Set directory of file browser</source>\n            <translation>Ange filhanterarens katalog</translation>\n        </message>\n        <message>\n            <location line=\"+29\"/>\n            <source>Create File</source>\n            <translation>Skapa fil</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Create file in\n</source>\n            <comment>String ends with \n!</comment>\n            <translation>Skapa fil i\n</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>New File.txt</source>\n            <translation>Ny Fil.txt</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Create File error</source>\n            <translation>Fel vid skapande av fil</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Could not create file\n&quot;%1&quot;.</source>\n            <translation>Kunde inte skapa filen\n&quot;%1&quot;.</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>Create Directory</source>\n            <translation>Skapa katalog</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Create folder in\n</source>\n            <comment>String ends with \n!</comment>\n            <translation>Skapa mapp i\n</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>New Directory</source>\n            <translation>Ny katalog</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::files_dock_widget</name>\n        <message>\n            <location line=\"-1148\"/>\n            <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n            <translation>Kunde inte byta namn på filen &quot;%1&quot; till &quot;%2&quot;.</translation>\n        </message>\n        <message>\n            <location line=\"+107\"/>\n            <source>File Browser</source>\n            <translation>Filhanterare</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Browse your files</source>\n            <translation>Bläddra bland dina filer</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>File System</source>\n            <translation>Filsystem</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Editor Files</source>\n            <translation>Redigerarfiler</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::final_page</name>\n        <message>\n            <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n            <source>Enjoy!</source>\n            <translation>Ha det så kul!</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Previous</source>\n            <translation>Föregående</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Finish</source>\n            <translation>Avsluta</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Cancel</source>\n            <translation>Avbryt</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Vi hoppas att du tycker att Octave är ett användbart verktyg.&lt;/p&gt;\n&lt;p&gt;Om du stöter på problem finns det flera sätt att få hjälp, inklusive kommersiella supportalternativ, diskussionsforum, wiki och andra communityn-baserade supportkanaler.\nDu kan hitta mer information om var och en av dessa genom att besöka &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (öppnas i extern webbläsare).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n        <message>\n            <location line=\"+21\"/>\n            <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;För more information om Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Besök &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (öppnas i extern webbläsare)&lt;/li&gt;\n&lt;li&gt;Hämta dokumentationen på nätet i &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; eller &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (länkar öppnas i extern webbläsare)&lt;/li&gt;\n&lt;li&gt;Öppna dokumentationsläsaren för Octave GUI med hjälpmenyn&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::find_dialog</name>\n        <message>\n            <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n            <source>Editor: Find and Replace</source>\n            <translation>Redigerare: Hitta och ersätt</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>&amp;Find:</source>\n            <translation>&amp;Hitta:</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Enter search text</source>\n            <translation>Ange söktext</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Re&amp;place:</source>\n            <translation>Er&amp;sätt:</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Enter replacement text</source>\n            <translation>Ange ersättningstext</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Match case</source>\n            <translation>Matcha skiftläge</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Search from &amp;start</source>\n            <translation>Sök från &amp;början</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>&amp;Wrap while searching</source>\n            <translation>&amp;Sökning utan radbrytningar</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Find &amp;Next</source>\n            <translation>Hitta &amp;nästa</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Find Pre&amp;vious</source>\n            <translation>Hitta föreg&amp;ående</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>&amp;Replace</source>\n            <translation>&amp;Ersätt</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Replace &amp;All</source>\n            <translation>Ersätt &amp;alla</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>&amp;More...</source>\n            <translation>&amp;Mer...</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>&amp;Whole words</source>\n            <translation>&amp;Hela ord</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Regular &amp;expressions</source>\n            <translation>Reguljära &amp;uttryck</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Search &amp;backward</source>\n            <translation>Sök &amp;bakåt</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Search se&amp;lection</source>\n            <translation>Sök m&amp;arkering</translation>\n        </message>\n        <message>\n            <location line=\"+185\"/>\n            <source>Search from end</source>\n            <translation>Sök från slutet</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Search from start</source>\n            <translation>Sök från början</translation>\n        </message>\n        <message>\n            <location line=\"+290\"/>\n            <source>Replace Result</source>\n            <translation>Ersätt resultat</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>%1 items replaced</source>\n            <translation>%1 objekt ersatta</translation>\n        </message>\n        <message>\n            <location line=\"+15\"/>\n            <source>Find Result</source>\n            <translation>Sökresultat</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>No more matches found</source>\n            <translation>Inga fler träffar hittades</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::find_files_dialog</name>\n        <message>\n            <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n            <source>Find Files</source>\n            <translation>Hitta filer</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Named:</source>\n            <translation>Namngiven:</translation>\n        </message>\n        <message>\n            <location line=\"+16\"/>\n            <source>Start in:</source>\n            <translation>Starta i:</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Enter the start directory</source>\n            <translation>Ange startkatalogen</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Browse...</source>\n            <translation>Bläddra...</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Browse for start directory</source>\n            <translation>Bläddra efter startkatalogen</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Current Dir</source>\n            <translation>Aktuell katalog</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Set start directory to current directory</source>\n            <translation>Ställ in startkatalogen till aktuell katalog</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Search subdirectories</source>\n            <translation>Sök i underkataloger</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Search recursively through directories for matching files</source>\n            <translation>Sök rekursivt genom kataloger efter matchande filer</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Include directory names</source>\n            <translation>Inkludera katalognamn</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Include matching directories in search results</source>\n            <translation>Inkludera matchande kataloger i sökresultaten</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <location line=\"+18\"/>\n            <source>Ignore case</source>\n            <translation>Ignorera skiftläge</translation>\n        </message>\n        <message>\n            <location line=\"-17\"/>\n            <location line=\"+18\"/>\n            <source>Perform case insensitive match</source>\n            <translation>Utför matchning utan skiftlägeskänslighet</translation>\n        </message>\n        <message>\n            <location line=\"-15\"/>\n            <source>Contains text:</source>\n            <translation>Innehåller text:</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Include only files containing specified text in search results</source>\n            <translation>Inkludera endast filer som innehåller specificerad text i sökresultaten</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Text to match</source>\n            <translation>Text som ska matcha</translation>\n        </message>\n        <message>\n            <location line=\"+95\"/>\n            <source>Results: Double click opens the file or sets the directory</source>\n            <translation>Resultat: Dubbelklick öppnar filen eller ställer in katalogen</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Search results</source>\n            <translation>Sökresultat</translation>\n        </message>\n        <message>\n            <location line=\"-59\"/>\n            <source>Idle.</source>\n            <translation>Sysslolös.</translation>\n        </message>\n        <message>\n            <location line=\"-94\"/>\n            <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by ';', e.g. '*.cc ; *.h'</source>\n            <translation>Ange sökmönster för filnamn.\nFlera olika mönster kan\nsepareras med ';', t.ex. '*.cc ; *.h'</translation>\n        </message>\n        <message>\n            <location line=\"+96\"/>\n            <source>Find</source>\n            <translation>Hitta</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Start search for matching files</source>\n            <translation>Börja söka efter matchande filer</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Stop</source>\n            <translation>Stopp</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Stop search</source>\n            <translation>Stoppa sökningen</translation>\n        </message>\n        <message>\n            <location line=\"+17\"/>\n            <source>Filename/Location</source>\n            <translation>Filnamn/plats</translation>\n        </message>\n        <message>\n            <location line=\"+22\"/>\n            <source>File contents</source>\n            <translation>Filinnehåll</translation>\n        </message>\n        <message>\n            <location line=\"+143\"/>\n            <source>Searching...</source>\n            <translation>Sökande...</translation>\n        </message>\n        <message>\n            <location line=\"+28\"/>\n            <source>%1 match (es)</source>\n            <translation>%1 träffar</translation>\n        </message>\n        <message>\n            <location line=\"+17\"/>\n            <source>Set search directory</source>\n            <translation>Ange sökkatalog</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::find_files_model</name>\n        <message>\n            <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n            <source>Filename</source>\n            <translation>Filnam</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Directory</source>\n            <translation>Katalog</translation>\n        </message>\n        <message>\n            <location line=\"+87\"/>\n            <source>Double click to open the file</source>\n            <translation>Dubbelklicka för att öppna filen</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Double click to set the directory</source>\n            <translation>Dubbelklicka för att ställa in katalogen</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::find_widget</name>\n        <message>\n            <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n            <source>Find:</source>\n            <translation>Hitta:</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <location line=\"+1\"/>\n            <source>Search forward</source>\n            <translation>Sök framåt</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <location line=\"+1\"/>\n            <source>Search backward</source>\n            <translation>Sök bakåt</translation>\n        </message>\n        <message>\n            <location line=\"+14\"/>\n            <source>Close</source>\n            <translation>Stäng</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Close find dialog</source>\n            <translation>Stäng sökdialogrutan</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::gui_settings</name>\n        <message>\n            <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n            <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\nOctave GUI must be closed now.</source>\n            <translation>Fel %1 vid skapandet av inställningsfilen\n%2\nSe till att du har läs- och skrivbehörighet till\n%3\nOctave GUI måste stängas nu.</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Octave Critical Error</source>\n            <translation>Octave-kritiskt fel</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::history_dock_widget</name>\n        <message>\n            <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n            <source>Browse and search the command history.</source>\n            <translation>Bläddra och sök i kommandohistoriken.</translation>\n        </message>\n        <message>\n            <location line=\"+102\"/>\n            <source>Copy</source>\n            <translation>Kopiera</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Evaluate</source>\n            <translation>Utvärdera</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Create script</source>\n            <translation>Skapa skript</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Hide filter</source>\n            <translation>Dölj filter</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show filter</source>\n            <translation>Visa filter</translation>\n        </message>\n        <message>\n            <location line=\"+131\"/>\n            <source>Double-click a command to transfer it to the Command Window.</source>\n            <translation>Dubbelklicka på ett kommando för att överföra det till kommandofönstret.</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Enter text to filter the command history</source>\n            <translation>Ange text för att filtrera kommandohistoriken</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Filter</source>\n            <translation>Filter</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Command History</source>\n            <translation>Kommandohistorik</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::initial_page</name>\n        <message>\n            <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n            <source>Welcome to Octave!</source>\n            <translation>Välkommen till Octave!</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Next</source>\n            <translation>Nästa</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Cancel</source>\n            <translation>Avbryt</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick 'Next' to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Du verkar använda Octaves grafiska gränssnitt för första gången på den här datorn.\nKlicka på 'Nästa' för att skapa en konfigurationsfil och starta Octave.&lt;/p&gt;\n&lt;p&gt;Konfigurationsfilen är lagrad i i&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::label_dock_widget</name>\n        <message>\n            <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n            <source>Undock Widget</source>\n            <translation>Förandra inte gränssnittskomponenten</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Close Widget</source>\n            <translation>Stäng gränssnittskomponenten</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::main_window</name>\n        <message>\n            <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n            <source>Profiler</source>\n            <translation>Profiler</translation>\n        </message>\n        <message>\n            <location line=\"+381\"/>\n            <source>Octave</source>\n            <translation>Octave</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Are you sure you want to exit Octave?</source>\n            <translation>Är du säker på att du vill avsluta Octave?</translation>\n        </message>\n        <message>\n            <location line=\"+156\"/>\n            <source>Save Workspace As</source>\n            <translation>Spara arbetsyta som</translation>\n        </message>\n        <message>\n            <location line=\"+29\"/>\n            <source>Load Workspace</source>\n            <translation>Ladda arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+214\"/>\n            <location line=\"+1704\"/>\n            <source>About Octave</source>\n            <translation>Om Octave</translation>\n        </message>\n        <message>\n            <location line=\"-1570\"/>\n            <location line=\"+1645\"/>\n            <source>Browse directories</source>\n            <translation>Bläddra bland kataloger</translation>\n        </message>\n        <message>\n            <location line=\"-1340\"/>\n            <source>Octave Files (*.m);;All Files (*)</source>\n            <translation>Octave-filer (*.m);;Alla filer (*)</translation>\n        </message>\n        <message>\n            <location line=\"+48\"/>\n            <source>New Function</source>\n            <translation>Ny funktion</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>New function name:\n</source>\n            <translation>Ny funktion name:\n</translation>\n        </message>\n        <message>\n            <location line=\"+63\"/>\n            <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n            <translation>%1 är en inbyggd, kompilerad eller inline-\nfunktion och kan inte redigeras.</translation>\n        </message>\n        <message>\n            <location line=\"+41\"/>\n            <source>Can not find function %1</source>\n            <translation>Kan inte hitta funktionen %1</translation>\n        </message>\n        <message>\n            <location line=\"+22\"/>\n            <source>Octave Editor</source>\n            <translation>Octave-redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+735\"/>\n            <source>&amp;File</source>\n            <translation>&amp;Fil</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Open...</source>\n            <translation>Öppna...</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Open an existing file in editor</source>\n            <translation>Öppna en befintlig fil i redigeraren</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Load Workspace...</source>\n            <translation>Ladda arbetsyta...</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Save Workspace As...</source>\n            <translation>Spara arbetsyta som...</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Exit</source>\n            <translation>Avsluta</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>New</source>\n            <translation>Ny</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>New Script</source>\n            <translation>Nytt skript</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>New Function...</source>\n            <translation>Ny funktion...</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>New Figure</source>\n            <translation>Ny Figure</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>&amp;Edit</source>\n            <translation>&amp;Redigera</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Undo</source>\n            <translation>Ångra</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Copy</source>\n            <translation>Kopiera</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Paste</source>\n            <translation>Klistra in</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Select All</source>\n            <translation>Markera allt</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Clear Clipboard</source>\n            <translation>Rensa urklipp</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Find Files...</source>\n            <translation>Hitta filer...</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Clear Command Window</source>\n            <translation>Rensa kommandofönster</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Clear Command History</source>\n            <translation>Rensa kommandohistorik</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Clear Workspace</source>\n            <translation>Rensa arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Set Path...</source>\n            <translation>Ange sökväg...</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Preferences...</source>\n            <translation>Inställningar...</translation>\n        </message>\n        <message>\n            <location line=\"+56\"/>\n            <source>De&amp;bug</source>\n            <translation>Fel&amp;sök</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Step</source>\n            <translation>Steg</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Step In</source>\n            <translation>Step I</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Step Out</source>\n            <translation>Gå ut</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Continue</source>\n            <translation>Fortsätt</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Quit Debug Mode</source>\n            <translation>Avsluta felsökningsläge</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>&amp;Tools</source>\n            <translation>&amp;Verktyg</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Start &amp;Profiler Session</source>\n            <translation>Starta &amp;profileringssession</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>&amp;Resume Profiler Session</source>\n            <translation>&amp;Återuppta profileringssession</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>&amp;Stop Profiler</source>\n            <translation>&amp;Stoppa profileraren</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>&amp;Show Profiler Data</source>\n            <translation>&amp;Visa profileringsdata</translation>\n        </message>\n        <message>\n            <location line=\"+53\"/>\n            <source>&amp;Window</source>\n            <translation>&amp;Fönster</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show Command Window</source>\n            <translation>Visa kommandofönster</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show Command History</source>\n            <translation>Visa Kommandohistorik</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show File Browser</source>\n            <translation>Visa filhanterare</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show Workspace</source>\n            <translation>Visa arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show Editor</source>\n            <translation>Visa redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show Documentation</source>\n            <translation>Visa dokumentation</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show Variable Editor</source>\n            <translation>Visa variabelredigerare</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Command Window</source>\n            <translation>Kommandofönster</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Command History</source>\n            <translation>Kommandohistorik</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>File Browser</source>\n            <translation>Filhanterare</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Workspace</source>\n            <translation>Arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Editor</source>\n            <translation>Redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <location line=\"+46\"/>\n            <source>Documentation</source>\n            <translation>Dokumentation</translation>\n        </message>\n        <message>\n            <location line=\"-43\"/>\n            <source>Variable Editor</source>\n            <translation>Variabelredigerare</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Previous Widget</source>\n            <translation>Föregående gränssnittskomponent</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Reset Default Window Layout</source>\n            <translation>Återställ standardfönsterlayout</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>&amp;Help</source>\n            <translation>&amp;Hjälp</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Report Bug</source>\n            <translation>Rapportera fel</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Octave Packages</source>\n            <translation>Octave-paket</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Get Involved</source>\n            <translation>Engagera dig</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Donate to Octave</source>\n            <translation>Donera till Octave</translation>\n        </message>\n        <message>\n            <location line=\"+14\"/>\n            <source>On Disk</source>\n            <translation>På disk</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Online</source>\n            <translation>Online</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>&amp;News</source>\n            <translation>&amp;Nyheter</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Release Notes</source>\n            <translation>Versionsnyheter</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Community News</source>\n            <translation>Community-nyheter</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Toolbar</source>\n            <translation>Verktygsfält</translation>\n        </message>\n        <message>\n            <location line=\"+21\"/>\n            <source>Enter directory name</source>\n            <translation>Ange katalognamn</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Current Directory: </source>\n            <translation>Aktuell katalog: </translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>One directory up</source>\n            <translation>En katalog upp</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::news_reader</name>\n        <message>\n            <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n            <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave's community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n            <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctaves gemenskapsnyhetskälla verkar vara otillgänglig.\n&lt;/p&gt;\n&lt;p&gt;\nFör de senaste nyheterna, se\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nnär du har en anslutning till webben (länken öppnas i en extern webbläsare).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Octave-utvecklare, </translation>\n        </message>\n        <message>\n            <location line=\"+18\"/>\n            <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave's network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n            <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nAnslutning till webben för att visa de senaste nyheterna från Octave-gemenskapen har inaktiverats.\n&lt;/p&gt;\n&lt;p&gt;\nFör de senaste nyheterna, se\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nnär du har en anslutning till webben (länken öppnas i en extern webbläsare)\neller aktivera webbanslutningar för nyheter i Octaves flik för nätverksinställningar.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Octave-utvecklare, </translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::octave_dock_widget</name>\n        <message>\n            <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n            <source>Hide Widget</source>\n            <translation>Dölj gränssnittskomponent</translation>\n        </message>\n        <message>\n            <location line=\"+83\"/>\n            <source>Dock Widget</source>\n            <translation>Förankra gränssnittskomponent</translation>\n        </message>\n        <message>\n            <location line=\"+58\"/>\n            <source>Undock Widget</source>\n            <translation>Förankra inte gränssnittskomponent</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::octave_qscintilla</name>\n        <message>\n            <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n            <source>Help on</source>\n            <translation>Hjälp på</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Documentation on</source>\n            <translation>Dokumentation på</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Edit</source>\n            <translation>Redigera</translation>\n        </message>\n        <message>\n            <location line=\"+15\"/>\n            <source>dbstop if ...</source>\n            <translation>dbstop om ...</translation>\n        </message>\n        <message>\n            <location line=\"+545\"/>\n            <source>Octave Editor</source>\n            <translation>Octave-redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n&quot;Run Selection&quot; requires temporary files.</source>\n            <translation>Det gick inte att skapa temporära filer.\nKontrollera att du har skrivåtkomst till temporärkatalogen\n%1\n&quot;Kör markering&quot; kräver temporära filer.</translation>\n        </message>\n        <message>\n            <location line=\"+313\"/>\n            <source>Press '%1' to replace all occurrences of '%2' with '%3'.</source>\n            <translation>Tryck på '%1' för att ersätta alla förekomster av '%2' med '%3'.</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::octave_txt_lexer</name>\n        <message>\n            <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n            <source>Default</source>\n            <translation>Standard</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::qt_interpreter_events</name>\n        <message>\n            <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n            <location line=\"+5\"/>\n            <location line=\"+2\"/>\n            <source>Create</source>\n            <translation>Skapa</translation>\n        </message>\n        <message>\n            <location line=\"-7\"/>\n            <location line=\"+31\"/>\n            <source>Cancel</source>\n            <translation>Avbryt</translation>\n        </message>\n        <message>\n            <location line=\"-28\"/>\n            <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n            <translation>Filen\n%1\nfinns inte. Vill du skapa den?</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Octave Editor</source>\n            <translation>Octave-redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+19\"/>\n            <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n            <translation>Filen %1 finns inte i laddningssökvägen. För att köra eller felsöka funktionen du redigerar måste du antingen byta till katalogen %2 eller lägga till den katalogen i laddningssökvägen.</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n            <translation>Filen %1 skuggas av en fil med samma namn i laddningssökvägen. För att köra eller felsöka funktionen du redigerar, byt till katalogen %2.</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Change Directory or Add Directory to Load Path</source>\n            <translation>Ändra katalog eller lägg till katalog för att ladda sökvägen</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>&amp;Change Directory</source>\n            <translation>&amp;Ändra katalog</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>&amp;Add Directory to Load Path</source>\n            <translation>&amp;Lägg till katalog för att ladda sökvägen</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::release_notes</name>\n        <message>\n            <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n            <source>The release notes file '%1' is empty.</source>\n            <translation>Versionsnyhetsfilen '%1' är tom.</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>The release notes file '%1' cannot be read.</source>\n            <translation>Versionsnyhetsfilen '%1' kan inte läsas.</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Octave Release Notes</source>\n            <translation>Octave-versionsnyheter</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::set_path_dialog</name>\n        <message>\n            <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n            <source>Set Path</source>\n            <translation>Ange sökväg</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>All changes take effect immediately.</source>\n            <translation>Alla ändringar träder i kraft omedelbart.</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Add Directory...</source>\n            <translation>Lägg till katalog...</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Single Directory</source>\n            <translation>Enskild katalog</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Directory With Subdirectories</source>\n            <translation>Katalog med underkataloger</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Move to Top</source>\n            <translation>Flytta överst</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Move to Bottom</source>\n            <translation>Flytta nederst</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Move Up</source>\n            <translation>Flytta upp</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Move Down</source>\n            <translation>Flytta ner</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Remove</source>\n            <translation>Ta bort</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Reload</source>\n            <translation>Ladda om</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Save</source>\n            <translation>Spara</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Revert</source>\n            <translation>Återställ</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Revert Last Change</source>\n            <translation>Återställ senaste ändring</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Revert All Changes</source>\n            <translation>Återställ alla ändringar</translation>\n        </message>\n        <message>\n            <location line=\"+92\"/>\n            <source>Open Directory</source>\n            <translation>Öppna katalog</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::settings_dialog</name>\n        <message>\n            <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n            <source>Top</source>\n            <translation>Överst</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Bottom</source>\n            <translation>Nederst</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Left</source>\n            <translation>Vänster</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Right</source>\n            <translation>Höger</translation>\n        </message>\n        <message>\n            <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n            <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n            <source>Foreground</source>\n            <translation>Förgrund</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n            <source>Background</source>\n            <translation>Bakgrund</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Selection</source>\n            <translation>Markering</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Cursor</source>\n            <translation>Markör</translation>\n        </message>\n        <message>\n            <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n            <source>Selected Foreground</source>\n            <translation>Markerad förgrund</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Selected Background</source>\n            <translation>Markerad bakgrund</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Alternating Background</source>\n            <translation>Alternerande bakgrund</translation>\n        </message>\n        <message>\n            <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n            <source>argument</source>\n            <translation>argument</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>global</source>\n            <translation>global</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>persistent</source>\n            <translation>beständig</translation>\n        </message>\n        <message>\n            <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n            <source>Environment Variables</source>\n            <translation>Miljövariabler</translation>\n        </message>\n        <message>\n            <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n            <source>Second color mode (light/dark)</source>\n            <translation>Sekundärt färgläge (ljust/mörkt)</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n            <translation>Växla till en andra uppsättning färger.\nAnvändbart för att definiera ljusa/mörka lägen.\nIgnorerar aktuella ändringar som inte tillämpats!</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Reload the default colors,\ndepends on currently selected mode.</source>\n            <translation>Reload standard colors,\ndepends på currently markerad läge.</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Reload the default style values,\ndepends on currently selected mode.</source>\n            <translation>Ladda om standardfärgerna,\nberoende på markerat läge.</translation>\n        </message>\n        <message>\n            <location line=\"-13\"/>\n            <source>&amp;Reload default colors</source>\n            <translation>&amp;Ladda om standardfärgerna</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>&amp;Reload default styles</source>\n            <translation>&amp;Ladda om standardstilar</translation>\n        </message>\n        <message>\n            <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n            <source>Loading current preferences ... </source>\n            <translation>Läser in aktuella inställningar ... </translation>\n        </message>\n        <message>\n            <location line=\"+44\"/>\n            <location line=\"+6\"/>\n            <location line=\"+1092\"/>\n            <source>System setting</source>\n            <translation>Systeminställning</translation>\n        </message>\n        <message>\n            <location line=\"-834\"/>\n            <source>IBeam Cursor</source>\n            <translation>IBeam-markör</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Block Cursor</source>\n            <translation>Block-markör</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Underline Cursor</source>\n            <translation>Understruken markör</translation>\n        </message>\n        <message>\n            <location line=\"+176\"/>\n            <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n            <translation>Färg på markerad aktuell rad (magenta (255,0,255) för automatisk färg)</translation>\n        </message>\n        <message>\n            <location line=\"+70\"/>\n            <source>Set Octave Startup Directory</source>\n            <translation>Ange Octave-startkatalogen</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Set File Browser Startup Directory</source>\n            <translation>Ange startkatalog för filhanteraren</translation>\n        </message>\n        <message>\n            <location line=\"+32\"/>\n            <source>Applying preferences ... </source>\n            <translation>Tillämpar inställningar ... </translation>\n        </message>\n        <message>\n            <location line=\"+89\"/>\n            <location line=\"+22\"/>\n            <location line=\"+1124\"/>\n            <source>Failed to open %1 as Octave shortcut file</source>\n            <translation>Misslyckades med att öppna %1 som Octave-genvägsfil</translation>\n        </message>\n        <message>\n            <location line=\"-453\"/>\n            <source>Enable attribute colors</source>\n            <translation>Aktivera attributfärger</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Hide tool tips</source>\n            <translation>Dölj verktygstips</translation>\n        </message>\n        <message>\n            <location line=\"+384\"/>\n            <source>Import shortcuts from file...</source>\n            <translation>Importera genvägar från fil...</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <location line=\"+6\"/>\n            <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n            <translation>Oktave-genvägsfiler (*.osc);;Alla filer (*)</translation>\n        </message>\n        <message>\n            <location line=\"-1\"/>\n            <source>Export shortcuts to file...</source>\n            <translation>Exportera genvägar till fil...</translation>\n        </message>\n        <message>\n            <location line=\"+32\"/>\n            <source>Overwriting Shortcuts</source>\n            <translation>Överskrivning av genvägar</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n            <translation>Du håller på att skriva över alla genvägar.\nVill du spara den aktuella genvägsuppsättningen eller avbryta åtgärden?</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Don't save</source>\n            <translation>Spara inte</translation>\n        </message>\n        <message>\n            <location line=\"+34\"/>\n            <source>Octave GUI preferences</source>\n            <translation>Octave GUI-inställningar</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::setup_community_news</name>\n        <message>\n            <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n            <source>Community News</source>\n            <translation>Gemenskapsnyheter</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Previous</source>\n            <translation>Föregående</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Next</source>\n            <translation>Nästa</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Cancel</source>\n            <translation>Avbryt</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;När Octave startar kan den valfritt kontrollera Octaves webbplats för aktuella nyheter och information om Octave-gemenskapen.\nKontrollen sker högst en gång per dag och nyheter visas bara om det finns något nytt sedan du senast såg nyheterna.&lt;/p&gt;\n&lt;p&gt;Du kan också se nyheterna genom att välja alternativet &quot;Gemenskapsnyheter&quot; i &quot;Hjälp&quot;-menyn eller genom att besöka\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n        <message>\n            <location line=\"+30\"/>\n            <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Tillåt Octave att ansluta till Octaves webbplats när den startar för att visa aktuella nyheter och information om Octave-gemenskapen.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::shortcut_edit_dialog</name>\n        <message>\n            <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n            <source>Enter New Shortcut</source>\n            <translation>Ange ny genväg</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Enter custom shortcut\nAction: %1</source>\n            <translation>Ange anpassad genväg\nÅtgärd: %1</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Enter shortcut by typing it</source>\n            <translation>Ange genvägen genom att skriva den</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Add Shift modifier\n(allows one to enter number keys)</source>\n            <translation>Lägg till Shift-tangent\n(låter en använda siffertangenterna)</translation>\n        </message>\n        <message>\n            <location line=\"+17\"/>\n            <source>Actual Shortcut</source>\n            <translation>Faktisk genväg</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Default Shortcut</source>\n            <translation>Standardgenväg</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Clear</source>\n            <translation>Rensa</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Set to default</source>\n            <translation>Ange som standard</translation>\n        </message>\n        <message>\n            <location line=\"+125\"/>\n            <source>Double Shortcut</source>\n            <translation>Dubbel genväg</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n            <translation>Den valda genvägen\n &quot;%1&quot;\nanvänds redan för åtgärden\n &quot;%2&quot;.\nVill du använda genvägen och ta bort den från föregående åtgärd?</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::shortcuts_tree_widget</name>\n        <message>\n            <location line=\"+27\"/>\n            <source>Global</source>\n            <translation>Global</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <location line=\"+49\"/>\n            <source>File Menu</source>\n            <translation>Arkivmeny</translation>\n        </message>\n        <message>\n            <location line=\"-46\"/>\n            <location line=\"+49\"/>\n            <source>Edit Menu</source>\n            <translation>Redigeringsmeny</translation>\n        </message>\n        <message>\n            <location line=\"-46\"/>\n            <location line=\"+52\"/>\n            <source>Debug Menu</source>\n            <translation>Felsökningsmeny</translation>\n        </message>\n        <message>\n            <location line=\"-49\"/>\n            <source>Tools Menu</source>\n            <translation>Verktygsmeny</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Window Menu</source>\n            <translation>Fönstermeny</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <location line=\"+49\"/>\n            <source>Help Menu</source>\n            <translation>Hjälpmeny</translation>\n        </message>\n        <message>\n            <location line=\"-46\"/>\n            <source>News Menu</source>\n            <translation>Nyhetsmeny</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Handling of Dock Widgets</source>\n            <translation>Hantering av förankringsgränssnittsmoduler</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Tab Handling in Dock Widgets</source>\n            <translation>Flikhantering i förankringsgränssnittsmoduler</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Find &amp; Replace in Dock Widgets</source>\n            <translation>Hitta &amp; ersätt i förankringsgränssnittsmoduler</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Zooming in Editor and Documentation</source>\n            <translation>Zooma in i redigeraren och dokumentationen</translation>\n        </message>\n        <message>\n            <location line=\"+15\"/>\n            <source>Editor</source>\n            <translation>Redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>View Menu</source>\n            <translation>Visa meny</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Run Menu</source>\n            <translation>Kör-meny</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>Documentation Viewer</source>\n            <translation>Dokumentationsvisare</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Browser</source>\n            <translation>Hanterare</translation>\n        </message>\n        <message>\n            <location line=\"+115\"/>\n            <source>item %1 not found in shortcut settings dialog</source>\n            <translation>objekt %1 hittades inte i dialogrutan för genvägsinställningar</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::splash_screen</name>\n        <message>\n            <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n            <source>Welcome to GNU Octave</source>\n            <translation>Välkommen till GNU Octave</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Welcome to Octave!</source>\n            <translation>Välkommen till Octave!</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::terminal_dock_widget</name>\n        <message>\n            <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n            <source>Command Window</source>\n            <translation>Kommandofönster</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::variable_dock_widget</name>\n        <message>\n            <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n            <source>Dock Widget</source>\n            <translation>Förankringsgränssnittsmoduler</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Variable Editor: </source>\n            <translation>Variabelredigerare: </translation>\n        </message>\n        <message>\n            <location line=\"+15\"/>\n            <source>Undock Widget</source>\n            <translation>Förankra inte gränssnittskomponent</translation>\n        </message>\n        <message>\n            <location line=\"+22\"/>\n            <source>Restore geometry</source>\n            <translation>Återställ geometri</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Redock</source>\n            <translation>Förankra igen</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::variable_editor</name>\n        <message>\n            <location line=\"+922\"/>\n            <source>Variable Editor</source>\n            <translation>Variabelredigerare</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Edit variables.</source>\n            <translation>Redigera variabler.</translation>\n        </message>\n        <message>\n            <location line=\"+555\"/>\n            <source>Variable Editor Toolbar</source>\n            <translation>Variabelredigerarens verktygsfält</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Save</source>\n            <translation>Spara</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Save variable to a file</source>\n            <translation>Spara variabel till en fil</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <location line=\"+5\"/>\n            <location line=\"+6\"/>\n            <source>Save in format ...</source>\n            <translation>Spara i format ...</translation>\n        </message>\n        <message>\n            <location line=\"-5\"/>\n            <source>Save variable to a file in different format</source>\n            <translation>Spara variabel till en fil i ett annat format</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>Cut</source>\n            <translation>Klipp ut</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Cut data to clipboard</source>\n            <translation>Klipp ut data till urklipp</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Copy</source>\n            <translation>Kopiera</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Copy data to clipboard</source>\n            <translation>Kopiera data till urklipp</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Paste</source>\n            <translation>Klistra in</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Paste clipboard into variable data</source>\n            <translation>Klistra in urklipp i variabeldata</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <location line=\"+6\"/>\n            <location line=\"+7\"/>\n            <source>Plot</source>\n            <translation>Rita</translation>\n        </message>\n        <message>\n            <location line=\"-11\"/>\n            <source>Plot Selected Data</source>\n            <translation>Rita markerade data</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Plot selected data</source>\n            <translation>Rita markerade data</translation>\n        </message>\n        <message>\n            <location line=\"+17\"/>\n            <source>Up</source>\n            <translation>Upp</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Go one level up in variable hierarchy</source>\n            <translation>Gå en nivå upp i variabelhierarkin</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::variable_editor_stack</name>\n        <message>\n            <location line=\"-1265\"/>\n            <source>Save Variable %1 As</source>\n            <translation>Spara variabel %1 som</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::variable_editor_view</name>\n        <message>\n            <location line=\"+142\"/>\n            <source>Cut</source>\n            <translation>Klipp ut</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Copy</source>\n            <translation>Kopiera</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Paste</source>\n            <translation>Klistra in</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Clear</source>\n            <translation>Rensa</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Delete</source>\n            <translation>Ta bort</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Variable from Selection</source>\n            <translation>Variabel från markering</translation>\n        </message>\n        <message>\n            <location line=\"+18\"/>\n            <source>Transpose</source>\n            <translation>Transponera</translation>\n        </message>\n        <message>\n            <location line=\"+56\"/>\n            <source> columns</source>\n            <translation> kolumner</translation>\n        </message>\n        <message>\n            <location line=\"+0\"/>\n            <source> column</source>\n            <translation> kolumn</translation>\n        </message>\n        <message>\n            <location line=\"+52\"/>\n            <source> rows</source>\n            <translation> rader</translation>\n        </message>\n        <message>\n            <location line=\"+0\"/>\n            <source> row</source>\n            <translation> rad</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::welcome_wizard</name>\n        <message>\n            <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n            <source>Welcome to GNU Octave</source>\n            <translation>Välkommen till GNU Octave</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::workspace_model</name>\n        <message>\n            <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n            <source>Name</source>\n            <translation>Namn</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Class</source>\n            <translation>Klass</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Dimension</source>\n            <translation>Dimension</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Value</source>\n            <translation>Värde</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Attribute</source>\n            <translation>Attribut</translation>\n        </message>\n        <message>\n            <location line=\"+83\"/>\n            <source>Right click to copy, rename, or display</source>\n            <translation>Högerklicka för att kopiera, byta namn eller visa</translation>\n        </message>\n        <message>\n            <location line=\"+30\"/>\n            <location line=\"+2\"/>\n            <source>complex</source>\n            <translation>komplex</translation>\n        </message>\n    </context>\n    <context>\n        <name>octave::workspace_view</name>\n        <message>\n            <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n            <source>Class</source>\n            <translation>Klass</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Dimension</source>\n            <translation>Dimension</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Value</source>\n            <translation>Värde</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Attribute</source>\n            <translation>Attribut</translation>\n        </message>\n        <message>\n            <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n            <source>Workspace</source>\n            <translation>Arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>View the variables in the active workspace.</source>\n            <translation>Visa variablerna i den aktiva arbetsytan.</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Enter text to filter the workspace</source>\n            <translation>Ange text för att filtrera arbetsytan</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Filter</source>\n            <translation>Filter</translation>\n        </message>\n        <message>\n            <location line=\"+138\"/>\n            <source>View the variables in the active workspace.&lt;br&gt;</source>\n            <translation>Visa variablerna i den aktiva arbetsytan.&lt;br&gt;</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Colors for variable attributes:</source>\n            <translation>Färger för variabla attribut:</translation>\n        </message>\n        <message>\n            <location line=\"+139\"/>\n            <source>Open in Variable Editor</source>\n            <translation>Öppna i variabelredigeraren</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Copy name</source>\n            <translation>Kopiera namn</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Copy value</source>\n            <translation>Kopiera värde</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Rename</source>\n            <translation>Byt namn</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Only top-level symbols may be renamed</source>\n            <translation>Endast symboler på toppnivå kan byta namn</translation>\n        </message>\n        <message>\n            <location line=\"+22\"/>\n            <source>Hide filter</source>\n            <translation>Dölj filter</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show filter</source>\n            <translation>Visa filter</translation>\n        </message>\n    </context>\n    <context>\n        <name>self_listener</name>\n        <message>\n            <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n            <source>Can not open redirected stream with fd = %1.</source>\n            <translation>Kan inte öppna omdirigerad ström med fd = %1.</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Can not disable buffering of stream with fd = %1.</source>\n            <translation>Kan inte inaktivera buffring av ström med fd = %1.</translation>\n        </message>\n        <message>\n            <location line=\"+11\"/>\n            <source>Can not dup redirected stream with fd = %1.</source>\n            <translation>Kan inte dup-omdirigerad ström med fd = %1.</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n            <translation>Kan inte skapa rör för omdirigering av ström med fd = %1:</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n            <translation>Kan inte duplicera omdirigerad ström med fd = %1\ntill rör med fd = %2: %3</translation>\n        </message>\n        <message>\n            <location line=\"+57\"/>\n            <source>Error while listening to redirected streams</source>\n            <translation>Fel vid lyssnande på omdirigerade strömmar</translation>\n        </message>\n        <message>\n            <location line=\"+17\"/>\n            <source>Error reading from redirected stream fd = %1.</source>\n            <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n            <translation>Fel vid läsning från omdirigerad ström fd = %1.</translation>\n        </message>\n        <message>\n            <location line=\"+27\"/>\n            <source>\nOutput redirection in </source>\n            <translation>\nOmdirigering av utdata i </translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source> won't work.</source>\n            <translation> kommer inte att fungera.</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>\nError: </source>\n            <translation>\nFel: </translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Octave</source>\n            <translation>Octave</translation>\n        </message>\n    </context>\n    <context>\n        <name>settings_dialog</name>\n        <message>\n            <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n            <location line=\"+841\"/>\n            <location line=\"+1916\"/>\n            <source>General</source>\n            <translation>Allmän</translation>\n        </message>\n        <message>\n            <location line=\"-2404\"/>\n            <source>Octave logo only</source>\n            <translation>Endast Oktave-logotypen</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Letter icons</source>\n            <translation>Bokstavsikoner</translation>\n        </message>\n        <message>\n            <location line=\"-334\"/>\n            <source>Dock widget title bar</source>\n            <translation>Titelfält för förankringsgränssnittsmoduler</translation>\n        </message>\n        <message>\n            <location line=\"+72\"/>\n            <source>Small</source>\n            <translation>Liten</translation>\n        </message>\n        <message>\n            <location line=\"+17\"/>\n            <source>Large</source>\n            <translation>Stor</translation>\n        </message>\n        <message>\n            <location line=\"+105\"/>\n            <source>Custom style</source>\n            <translation>Anpassad stil</translation>\n        </message>\n        <message>\n            <location line=\"+32\"/>\n            <source>3-D</source>\n            <oldsource>3D</oldsource>\n            <translation>3D</translation>\n        </message>\n        <message>\n            <location line=\"+565\"/>\n            <source>Editor</source>\n            <translation>Redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+488\"/>\n            <location line=\"+140\"/>\n            <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n            <translation>Detta fungerar bra för teckensnitt med fast radavstånd. Raden ritas vid en position baserad på bredden på ett mellanslagstecken i standardteckensnittet. Det kanske inte fungerar särskilt bra om stilar använder proportionella teckensnitt eller om olika teckenstorlekar eller fetstil, kursiv och normal text används.</translation>\n        </message>\n        <message>\n            <location line=\"-535\"/>\n            <source>Enable Code Folding</source>\n            <translation>Aktivera kodvikning</translation>\n        </message>\n        <message>\n            <location line=\"+1116\"/>\n            <source>Windows (CRLF)</source>\n            <translation>Fönster (CRLF)</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Legacy Mac (CR)</source>\n            <translation>Äldre Mac (CR)</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>Unix (LF)</source>\n            <translation>Unix (LF)</translation>\n        </message>\n        <message>\n            <location line=\"-1091\"/>\n            <source>Show horizontal scroll bar</source>\n            <translation>Visa horisontell rullningslist</translation>\n        </message>\n        <message>\n            <location line=\"-516\"/>\n            <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Om detta är angivet följer fokus för widgetarna som är dockade till huvudfönstret muspekaren. Detta är avsett att ha samma beteende i huvudfönstret när \"fokus följer mus\" används för skrivbordsmiljön.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Focus follows mouse for widgets docked to the main window</source>\n            <translation>Fokus följer musen för gränssnittskomponenter förankrade till huvudfönstret</translation>\n        </message>\n        <message>\n            <location line=\"+494\"/>\n            <source>Show tool bar</source>\n            <translation>Visa verktygsfält</translation>\n        </message>\n        <message>\n            <location line=\"+221\"/>\n            <source>Rotated tabs</source>\n            <translation>Roterade flikar</translation>\n        </message>\n        <message>\n            <location line=\"+25\"/>\n            <source>Position</source>\n            <translation>Position</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Max. tab width in chars (0: no limit)</source>\n            <translation>Max. flikbredd i tecken (0: ingen gräns)</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Maxbredd på en flik i tecken (genomsnittlig teckenbredd). Särskilt användbart för roterade flikar.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n        <message>\n            <location line=\"+260\"/>\n            <source>Wrap long lines at current window border</source>\n            <translation>Radbryt långa rader vid aktuell fönsterkant</translation>\n        </message>\n        <message>\n            <location line=\"+15\"/>\n            <source>Indentation</source>\n            <translation>Indrag</translation>\n        </message>\n        <message>\n            <location line=\"+40\"/>\n            <source>Indent width</source>\n            <translation>Indragsbredd</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Tab indents line</source>\n            <translation>Tabb-indragslinjen</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>Auto indentation</source>\n            <translation>Automatisk indentering</translation>\n        </message>\n        <message>\n            <location line=\"+23\"/>\n            <source>Tab width</source>\n            <translation>Tabbredd</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Show indentation guides</source>\n            <translation>Visa indragningsstödlinjer</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Backspace unindents line</source>\n            <translation>Backsteg tar bort indragningslinjen</translation>\n        </message>\n        <message>\n            <location line=\"+23\"/>\n            <source>Indentation uses tabs</source>\n            <translation>Indragning använder tabbar</translation>\n        </message>\n        <message>\n            <location line=\"+70\"/>\n            <source>Auto completion</source>\n            <translation>Automatisk ifyllning</translation>\n        </message>\n        <message>\n            <location line=\"+27\"/>\n            <source>Match keywords</source>\n            <translation>Matcha nyckelord</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>Case sensitive</source>\n            <translation>Skiftlägeskänsligt</translation>\n        </message>\n        <message>\n            <location line=\"+23\"/>\n            <source>Replace word by suggested one</source>\n            <translation>Ersätt ordet med det föreslagna</translation>\n        </message>\n        <message>\n            <location line=\"-10\"/>\n            <source>Match words in document</source>\n            <translation>Matcha ord i dokumentet</translation>\n        </message>\n        <message>\n            <location line=\"+48\"/>\n            <source>With Octave builtins</source>\n            <translation>Med inbyggda Octave-funktioner</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>With Octave functions</source>\n            <translation>Med Octave-funktioner</translation>\n        </message>\n        <message>\n            <location line=\"+64\"/>\n            <source>Show completion list automatically</source>\n            <translation>Visa listan över ifyllda uppgifter automatiskt</translation>\n        </message>\n        <message>\n            <location line=\"+159\"/>\n            <source>Reload externally changed files without prompt</source>\n            <translation>Ladda om externt ändrade filer utan uppmaning</translation>\n        </message>\n        <message>\n            <location line=\"-924\"/>\n            <source>Use custom file editor</source>\n            <translation>Använd en anpassad filredigerare</translation>\n        </message>\n        <message>\n            <location line=\"+843\"/>\n            <source>Text encoding used for loading and saving</source>\n            <translation>Textkodning som används för att ladda och spara</translation>\n        </message>\n        <message>\n            <location line=\"+166\"/>\n            <source>Editor Styles</source>\n            <translation>Redigerarstilar</translation>\n        </message>\n        <message>\n            <location line=\"-1390\"/>\n            <source>(Changing buffer size clears history)</source>\n            <translation>(Ändring av buffertstorlek rensar historiken)</translation>\n        </message>\n        <message>\n            <location line=\"+28\"/>\n            <source>History buffer Size</source>\n            <translation>Historikbuffertens storlek</translation>\n        </message>\n        <message>\n            <location line=\"-123\"/>\n            <location line=\"+1870\"/>\n            <source>Font</source>\n            <translation>Teckensnitt</translation>\n        </message>\n        <message>\n            <location line=\"-1580\"/>\n            <source>Show line numbers</source>\n            <translation>Visa radnummer</translation>\n        </message>\n        <message>\n            <location line=\"-866\"/>\n            <source>Interface</source>\n            <translation>Gränssnitt</translation>\n        </message>\n        <message>\n            <location line=\"+421\"/>\n            <source>Confirm before exiting</source>\n            <translation>Bekräfta innan avslut</translation>\n        </message>\n        <message>\n            <location line=\"-72\"/>\n            <source>Graphic icons</source>\n            <translation>Grafiska ikoner</translation>\n        </message>\n        <message>\n            <location line=\"+52\"/>\n            <location line=\"+446\"/>\n            <source>Show status bar</source>\n            <translation>Visa statusfält</translation>\n        </message>\n        <message>\n            <location line=\"-684\"/>\n            <source>Text inactive</source>\n            <translation>Text inaktiv</translation>\n        </message>\n        <message>\n            <location line=\"-32\"/>\n            <location line=\"+45\"/>\n            <source>Active</source>\n            <translation>Aktiv</translation>\n        </message>\n        <message>\n            <location line=\"+39\"/>\n            <source>Background inactive</source>\n            <translation>Bakgrund inaktiv</translation>\n        </message>\n        <message>\n            <location line=\"+225\"/>\n            <source>Octave Startup</source>\n            <translation>Octave-uppstart</translation>\n        </message>\n        <message>\n            <location line=\"+46\"/>\n            <location line=\"+1698\"/>\n            <source>Browse</source>\n            <translation>Bläddra</translation>\n        </message>\n        <message>\n            <location line=\"-1305\"/>\n            <source>Show whitespace</source>\n            <translation>Visa blanksteg</translation>\n        </message>\n        <message>\n            <location line=\"-45\"/>\n            <source>Do not show whitespace used for indentation</source>\n            <translation>Visa inte blanksteg som används för indentering</translation>\n        </message>\n        <message>\n            <location line=\"+1125\"/>\n            <source>Create nonexistent files without prompting</source>\n            <translation>Skapa icke-existerande filer utan uppmaning</translation>\n        </message>\n        <message>\n            <location line=\"-897\"/>\n            <source>command line (%f=file, %l=line):</source>\n            <translation>kommandorad (%f=fil, %l=rad):</translation>\n        </message>\n        <message>\n            <location line=\"-500\"/>\n            <source>Cursor type:</source>\n            <translation>Markörtyp:</translation>\n        </message>\n        <message>\n            <location line=\"-11\"/>\n            <source>Use foreground color</source>\n            <translation>Använd förgrundsfärg</translation>\n        </message>\n        <message>\n            <location line=\"+52\"/>\n            <location line=\"+1760\"/>\n            <source>Font size</source>\n            <translation>Teckenstorlek</translation>\n        </message>\n        <message>\n            <location line=\"-245\"/>\n            <source>File Browser</source>\n            <translation>Filhanterare</translation>\n        </message>\n        <message>\n            <location line=\"-2031\"/>\n            <source>Normal</source>\n            <translation>Normal</translation>\n        </message>\n        <message>\n            <location line=\"+359\"/>\n            <source>These preferences are applied after any .octaverc startup files.</source>\n            <translation>Dessa inställningar tillämpas efter alla .octaverc-uppstartsfiler.</translation>\n        </message>\n        <message>\n            <location line=\"+540\"/>\n            <source>Show EOL characters</source>\n            <translation>Visa EOL-tecken</translation>\n        </message>\n        <message>\n            <location line=\"+1002\"/>\n            <source>Default EOL mode</source>\n            <translation>Standard EOL-läge</translation>\n        </message>\n        <message>\n            <location line=\"-219\"/>\n            <source>Number of characters before list is shown: </source>\n            <translation>Antal tecken innan listan visas: </translation>\n        </message>\n        <message>\n            <location line=\"-1812\"/>\n            <source>Preferences</source>\n            <translation>Inställningar</translation>\n        </message>\n        <message>\n            <location line=\"+351\"/>\n            <source>(requires restart)</source>\n            <translation>(kräver omstart)</translation>\n        </message>\n        <message>\n            <location line=\"+73\"/>\n            <source>Use native file dialogs</source>\n            <translation>Använd inbyggda fildialogrutor</translation>\n        </message>\n        <message>\n            <location line=\"-98\"/>\n            <source>Toolbar Icons</source>\n            <translation>Verktygsfältsikoner</translation>\n        </message>\n        <message>\n            <location line=\"-224\"/>\n            <source>Language</source>\n            <translation>Språk</translation>\n        </message>\n        <message>\n            <location line=\"-41\"/>\n            <source>Dock widgets window icons</source>\n            <translation>Ikoner för förankringsgränssnittskompnenters fönster</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Style</source>\n            <translation>Stil</translation>\n        </message>\n        <message>\n            <location line=\"+43\"/>\n            <source>Icon theme (requires restart)</source>\n            <translation>Ikontema (kräver omstart)</translation>\n        </message>\n        <message>\n            <location line=\"+323\"/>\n            <source>Blinking cursor</source>\n            <translation>Blinkande markör</translation>\n        </message>\n        <message>\n            <location line=\"+37\"/>\n            <source>Show splash screen at startup</source>\n            <translation>Visa startskärm vid uppstart</translation>\n        </message>\n        <message>\n            <location line=\"+27\"/>\n            <source>Initial working directory of Octave interpreter</source>\n            <translation>Initial arbetskatalog för Octave-tolken</translation>\n        </message>\n        <message>\n            <location line=\"+18\"/>\n            <source>Restore last working directory of previous session</source>\n            <translation>Återställ den senaste arbetskatalogen från föregående session</translation>\n        </message>\n        <message>\n            <location line=\"+45\"/>\n            <source>Command</source>\n            <translation>Kommando</translation>\n        </message>\n        <message>\n            <location line=\"+208\"/>\n            <source>Set focus to Command Window when running a command from within another widget</source>\n            <translation>Ställ fokus till kommandofönstret när du kör ett kommando från en annan widget</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Print debug location in Command Window in addition to the marker in the editor</source>\n            <translation>Skriv ut felsökningsplatsen i kommandofönstret utöver markören i redigeraren</translation>\n        </message>\n        <message>\n            <location line=\"+16\"/>\n            <source>Command Window Colors</source>\n            <translation>Färger på kommandofönstret</translation>\n        </message>\n        <message>\n            <location line=\"+190\"/>\n            <source>Number size as difference to editor font</source>\n            <translation>Nummerstorlek som skillnad från redigerarens teckensnitt</translation>\n        </message>\n        <message>\n            <location line=\"+79\"/>\n            <source>Highlight current line (color adjustable below with editor styles)</source>\n            <translation>Markera aktuell rad (färgen kan justeras nedan med redigeringsstilar)</translation>\n        </message>\n        <message>\n            <location line=\"+14\"/>\n            <source>Highlight all occurrences of a word selected by a double click</source>\n            <translation>Markera alla förekomster av ett ord som markerats med ett dubbelklick</translation>\n        </message>\n        <message>\n            <location line=\"+65\"/>\n            <source>Tabs</source>\n            <translation>Flikar</translation>\n        </message>\n        <message>\n            <location line=\"+29\"/>\n            <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotera flikar: Vertikalt när de är uppe eller nere och horisontellt när de är åt vänster eller höger. Stängningsknappen visas inte i roterade flikar.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n        <message>\n            <location line=\"+74\"/>\n            <source>Comments (Octave)</source>\n            <translation>Kommentarer (Octave)</translation>\n        </message>\n        <message>\n            <location line=\"+11\"/>\n            <source>Strings considered for uncommenting text</source>\n            <translation>Strängar som beaktas för avkommentering av text</translation>\n        </message>\n        <message>\n            <location line=\"+23\"/>\n            <source>String used for commenting selected text</source>\n            <translation>Sträng som används för att kommentera markerad text</translation>\n        </message>\n        <message>\n            <location line=\"+31\"/>\n            <source>Long lines</source>\n            <translation>Långa rader</translation>\n        </message>\n        <message>\n            <location line=\"+25\"/>\n            <source>Break long lines at line length</source>\n            <translation>Bryt långa rader vid radlängd</translation>\n        </message>\n        <message>\n            <location line=\"+13\"/>\n            <source>Break lines only in comments</source>\n            <translation>Bryt rader endast i kommentarer</translation>\n        </message>\n        <message>\n            <location line=\"+60\"/>\n            <source>Line length</source>\n            <translation>Radlängd</translation>\n        </message>\n        <message>\n            <location line=\"+9\"/>\n            <source>Long line marker</source>\n            <translation>Lång radmarkör</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Line</source>\n            <translation>Rad</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Background</source>\n            <translation>Bakgrund</translation>\n        </message>\n        <message>\n            <location line=\"+191\"/>\n            <source>Auto insert after &quot;if&quot; etc.</source>\n            <translation>Automatisk infogning efter &quot;if&quot; etc.</translation>\n        </message>\n        <message>\n            <location line=\"+20\"/>\n            <source>Nothing</source>\n            <translation>Ingenting</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&quot;endif&quot; etc.</source>\n            <translation>&quot;endif&quot; etc.</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>&quot;end&quot;</source>\n            <translation>&quot;end&quot;</translation>\n        </message>\n        <message>\n            <location line=\"+238\"/>\n            <source>Debugging</source>\n            <translation>Felsökning</translation>\n        </message>\n        <message>\n            <location line=\"+8\"/>\n            <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n            <translation>Visa alltid felsökningsbrytpunkter och pekare (öppnar relaterad fil om den stängs)</translation>\n        </message>\n        <message>\n            <location line=\"+15\"/>\n            <source>File handling</source>\n            <translation>Filhantering</translation>\n        </message>\n        <message>\n            <location line=\"+52\"/>\n            <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n            <translation>Återställ redigeringsflikar från föregående session vid start eller när redigeraren visas igen efter stängning</translation>\n        </message>\n        <message>\n            <location line=\"+40\"/>\n            <source>Close all files when the editor widget is closed/hidden</source>\n            <translation>Stäng alla filer när redigeringsgränssnittskomponenten är stängd/dold</translation>\n        </message>\n        <message>\n            <location line=\"-23\"/>\n            <source>Force newline at end when saving file</source>\n            <translation>Tvinga fram ny rad i slutet när filen sparas</translation>\n        </message>\n        <message>\n            <location line=\"-10\"/>\n            <source>Remove trailing spaces when saving file</source>\n            <translation>Ta bort efterföljande mellanslag när du sparar filen</translation>\n        </message>\n        <message>\n            <location line=\"+108\"/>\n            <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n            <translation>Katalogen för dialogrutan för öppen fil följer aktuell redigeringsfil istället för aktuell Octave-katalog </translation>\n        </message>\n        <message>\n            <location line=\"+36\"/>\n            <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Välj teckensnitt, teckenstorlek (som en skillnad från standardstorleken), teckensnittsstil (&lt;f&gt;b&lt;/b&gt;et, &lt;b&gt;i&lt;/k&gt;ursiv, &lt;b&gt;u&lt;/b&gt;nderstruken), textfärg och bakgrundsfärg (för den senare är färgen magenta (255,0,255) en platshållare för standardbakgrundsfärgen).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n        <message>\n            <location line=\"+62\"/>\n            <source>Behavior</source>\n            <translation>Beteende</translation>\n        </message>\n        <message>\n            <location line=\"+22\"/>\n            <source>Restore last directory of previous session</source>\n            <translation>Återställ den senaste katalogen från föregående session</translation>\n        </message>\n        <message>\n            <location line=\"+68\"/>\n            <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n            <translation>Filtillägg som ska öppnas i standardtextredigeraren (separerade med &quot;;&quot;):</translation>\n        </message>\n        <message>\n            <location line=\"+39\"/>\n            <source>Workspace</source>\n            <translation>Arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+35\"/>\n            <source>Colors for variable attributes</source>\n            <translation>Färger för variabla attribut</translation>\n        </message>\n        <message>\n            <location line=\"+133\"/>\n            <source>Use Command Window font</source>\n            <translation>Använd teckensnittet i kommandofönstret</translation>\n        </message>\n        <message>\n            <location line=\"+154\"/>\n            <source>Import shortcut set</source>\n            <translation>Importera genvägsuppsättning</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Export current shortcut set</source>\n            <translation>Exportera aktuell genvägsuppsättning</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Reset shortcuts to their defaults</source>\n            <translation>Återställ genvägar till standardinställningarna</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <location line=\"+80\"/>\n            <source>Default</source>\n            <translation>Standard</translation>\n        </message>\n        <message>\n            <location line=\"+232\"/>\n            <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - stäng dialogrutan och tillämpa inställningarna&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Tillämpa - &lt;/span&gt;tillämpa inställningar men lämna dialogrutan öppen&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Avbryt - &lt;/span&gt;stäng dialogrutan och ignorera ändringar som ännu inte tillämpats&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Återställ -&lt;/span&gt; ladda om inställningarna tar bort ändringar som ännu inte\ntillämpats&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n        <message>\n            <location line=\"-227\"/>\n            <source>Actual</source>\n            <translation>Faktisk</translation>\n        </message>\n        <message>\n            <location line=\"+17\"/>\n            <source>Network</source>\n            <translation>Nätverk</translation>\n        </message>\n        <message>\n            <location line=\"+27\"/>\n            <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n            <translation>Tillåt Octave att ansluta till Octaves webbplats för att visa aktuella nyheter och information</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Proxy Server</source>\n            <translation>Proxyserver</translation>\n        </message>\n        <message>\n            <location line=\"+23\"/>\n            <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n            <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Miljövariabler&lt;/span&gt;. Med det sista valet tas proxyn från den första icke-tomma miljövariabeln ALL_PROXY, HTTP_PROXY eller HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n        </message>\n        <message>\n            <location line=\"+78\"/>\n            <source>Use proxy server</source>\n            <translation>Använd proxyserver</translation>\n        </message>\n        <message>\n            <location line=\"-523\"/>\n            <source>Variable Editor</source>\n            <translation>Variabelredigerare</translation>\n        </message>\n        <message>\n            <location line=\"+43\"/>\n            <source>Default row height</source>\n            <translation>Standardradhöjd</translation>\n        </message>\n        <message>\n            <location line=\"+7\"/>\n            <source>Default column width</source>\n            <translation>Standardkolumnbredd</translation>\n        </message>\n        <message>\n            <location line=\"+78\"/>\n            <source>Variable Editor Colors</source>\n            <translation>Variabelredigerarens färger</translation>\n        </message>\n        <message>\n            <location line=\"+12\"/>\n            <source>Use alternating row colors</source>\n            <translation>Använd alternerande radfärger</translation>\n        </message>\n        <message>\n            <location line=\"+63\"/>\n            <source>Inaktivera globala genvägar för att förhindra\nstörningar vid tangenttryckningar på läslinjen.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n            <translation>Inaktivera global genvägar i för att till prevent\ninterference med readline key strokes.\nUndantag: Ctrl-C för att avbryta tolken\noch genvägarna för att växla till andra gränssnittskomponenter.</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Disable global shortcuts when Command Window has focus</source>\n            <translation>Inaktivera globala genvägar när kommandofönstret är i fokus</translation>\n        </message>\n        <message>\n            <location line=\"-392\"/>\n            <source>Synchronize Octave working directory with file browser</source>\n            <translation>Synkronisera Octaves arbetskatalog med filhanteraren</translation>\n        </message>\n        <message>\n            <location line=\"+46\"/>\n            <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n            <translation>Ursprunglig filbläddrarkatalog (endast om den inte är synkroniserad med den ursprungliga arbetskatalogen för Octave)</translation>\n        </message>\n        <message>\n            <location line=\"+302\"/>\n            <source>Shortcuts</source>\n            <translation>Genvägar</translation>\n        </message>\n        <message>\n            <location line=\"+54\"/>\n            <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n            <translation>Inaktivera menyacceleratorer för att förhindra\nstörningar vid tangenttryckningar på läslinjen.</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n            <translation>Inaktivera menyacceleratorerna i huvudfönstrets menyer när kommandofönstret är i fokus</translation>\n        </message>\n        <message>\n            <location line=\"+50\"/>\n            <source>Export</source>\n            <translation>Exportera</translation>\n        </message>\n        <message>\n            <location line=\"-10\"/>\n            <source>Import</source>\n            <translation>Importera</translation>\n        </message>\n        <message>\n            <location line=\"+29\"/>\n            <source>Edit a shortcut by double-clicking in Actual column</source>\n            <translation>Redigera en genväg genom att dubbelklicka i den faktiska kolumnen</translation>\n        </message>\n        <message>\n            <location line=\"+61\"/>\n            <source>Action</source>\n            <translation>Åtgärd</translation>\n        </message>\n        <message>\n            <location line=\"+82\"/>\n            <source>Hostname:</source>\n            <translation>Värdnamn:</translation>\n        </message>\n        <message>\n            <location line=\"+30\"/>\n            <source>Proxy type:</source>\n            <translation>Proxytyp:</translation>\n        </message>\n        <message>\n            <location line=\"+10\"/>\n            <source>Port:</source>\n            <translation>Port:</translation>\n        </message>\n        <message>\n            <location line=\"-20\"/>\n            <source>Username:</source>\n            <translation>Användarnamn:</translation>\n        </message>\n        <message>\n            <location line=\"+30\"/>\n            <source>Password:</source>\n            <translation>Lösenord:</translation>\n        </message>\n    </context>\n    <context>\n        <name>shortcuts</name>\n        <message>\n            <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n            <source>Undock/Dock Widget</source>\n            <translation>Förankra inte/förankra gränssnittskomponent</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Close Widget</source>\n            <translation>Stäng gränssnittskomponenten</translation>\n        </message>\n        <message>\n            <location line=\"+5\"/>\n            <source>New File</source>\n            <translation>Ny fil</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>New Function</source>\n            <translation>Ny funktion</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>New Figure</source>\n            <translation>Ny figur</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Open File</source>\n            <translation>Öppna fil</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Load Workspace</source>\n            <translation>Ladda arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Save Workspace As</source>\n            <translation>Spara arbetsyta som</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Exit Octave</source>\n            <translation>Avsluta Octave</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Copy</source>\n            <translation>Kopiera</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Paste</source>\n            <translation>Klistra in</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Undo</source>\n            <translation>Ångra</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Select All</source>\n            <translation>Markera allt</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Clear Clipboard</source>\n            <translation>Rensa urklipp</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Find in Files</source>\n            <translation>Hitta i filer</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Clear Command Window</source>\n            <translation>Rensa kommandofönster</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Clear Command History</source>\n            <translation>Rensa kommandohistorik</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Clear Workspace</source>\n            <translation>Rensa arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Set Path</source>\n            <translation>Ange sökväg</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <location line=\"+119\"/>\n            <source>Preferences</source>\n            <translation>Inställningar</translation>\n        </message>\n        <message>\n            <location line=\"-116\"/>\n            <source>Step</source>\n            <translation>Steg</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Step In</source>\n            <translation>Steg in</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Step Out</source>\n            <translation>Steg ut</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Continue</source>\n            <translation>Fortsätt</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Quit Debug Mode</source>\n            <translation>Avsluta felsökningsläge</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Start/Stop Profiler Session</source>\n            <translation>Starta/stoppa profileringssession</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Resume Profiler Session</source>\n            <translation>Återuppta profileringssessionen</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Profile Data</source>\n            <translation>Visa profildata</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Show Command Window</source>\n            <translation>Visa kommandofönstret</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Command History</source>\n            <translation>Visa kommandohistorik</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show File Browser</source>\n            <translation>Visa filhanterare</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Workspace</source>\n            <translation>Visa arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Editor</source>\n            <translation>Visa redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Documentation</source>\n            <translation>Visa dokumentation</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Variable Editor</source>\n            <translation>Visa variabelredigerare</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Command Window</source>\n            <translation>Kommandofönster</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Command History</source>\n            <translation>Kommandohistorik</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>File Browser</source>\n            <translation>Filhanterare</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Workspace</source>\n            <translation>Arbetsyta</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Editor</source>\n            <translation>Redigerare</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Documentation</source>\n            <translation>Dokumentation</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Variable Editor</source>\n            <translation>Variabelredigerare</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Previous Widget</source>\n            <translation>Föregående gränssnittskomponent</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Reset Default Window Layout</source>\n            <translation>Återställ standardfönsterlayout</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show On-disk Documentation</source>\n            <translation>Visa dokumentation på disk</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Online Documentation</source>\n            <translation>Visa online-dokumentation</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Report Bug</source>\n            <translation>Rapportera fel</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Octave Packages</source>\n            <translation>Octave-paket</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Contribute to Octave</source>\n            <translation>Bidra till Octave</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Octave Developer Resources</source>\n            <translation>Octave-utvecklarresurser</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>About Octave</source>\n            <translation>Om Octave</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Release Notes</source>\n            <translation>Versionsnyheter</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Community News</source>\n            <translation>Gemenskapsnyheter</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Close Tab</source>\n            <translation>Stäng flik</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Close All Tabs</source>\n            <translation>Stäng alla flikar</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Close Other Tabs</source>\n            <translation>Stäng andra flikar</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Switch to Left Tab</source>\n            <translation>Växla till vänster flik</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Switch to Right Tab</source>\n            <translation>Växla till höger flik</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Move Tab Left</source>\n            <translation>Flytta fliken åt vänster</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Move Tab Right</source>\n            <translation>Flytta fliken åt höger</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Zoom In</source>\n            <translation>Zooma in</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Zoom Out</source>\n            <translation>Zooma ut</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <location line=\"+2\"/>\n            <source>Zoom Normal</source>\n            <translation>Zooma normalt</translation>\n        </message>\n        <message>\n            <location line=\"+6\"/>\n            <source>Edit Function</source>\n            <translation>Redigera funktion</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Save File</source>\n            <translation>Spara fil</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Save File As</source>\n            <translation>Spara fil som</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Print</source>\n            <translation>Skriv ut</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Redo</source>\n            <translation>Gör om</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Cut</source>\n            <translation>Klipp ut</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Find and Replace</source>\n            <translation>Hitta och ersätt</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Find Next</source>\n            <translation>Hitta nästa</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Find Previous</source>\n            <translation>Hitta föregående</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Delete to Start of Word</source>\n            <translation>Ta bort till början av ord</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Delete to End of Word</source>\n            <translation>Ta bort till slutet av ordet</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Delete to Start of Line</source>\n            <translation>Ta bort till början av raden</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Delete to End of Line</source>\n            <translation>Ta bort till slutet av raden</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Delete Line</source>\n            <translation>Ta bort rad</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Copy Line</source>\n            <translation>Kopiera rad</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Cut Line</source>\n            <translation>Klipp ut rad</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Duplicate Selection/Line</source>\n            <translation>Duplicera markering/rad</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Transpose Line</source>\n            <translation>Transponera rad</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Completion List</source>\n            <translation>Visa kompletteringslista</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Comment Selection</source>\n            <translation>Kommentara markering</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Uncomment Selection</source>\n            <translation>Avkommentera markering</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Comment Selection (Choosing String)</source>\n            <translation>Kommentara markering (välja sträng)</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Uppercase Selection</source>\n            <translation>Versaler-markering</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Lowercase Selection</source>\n            <translation>Gemener-markering</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <location line=\"+3\"/>\n            <source>Indent Selection Rigidly</source>\n            <translation>Gör fast indrag markering</translation>\n        </message>\n        <message>\n            <location line=\"-2\"/>\n            <location line=\"+3\"/>\n            <source>Unindent Selection Rigidly</source>\n            <translation>Ta bort fast indrag markering</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Indent Code</source>\n            <translation>Indragskod</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Convert Line Endings to Windows</source>\n            <translation>Konvertera radavslutningar till fönster</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Convert Line Endings to Unix</source>\n            <translation>Convert Line Endings to Unix</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Convert Line Endings to Mac</source>\n            <translation>Konvertera radavslutningar till Mac</translation>\n        </message>\n        <message>\n            <location line=\"+2\"/>\n            <source>Goto Line</source>\n            <translation>Gå till rad</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Move to Matching Brace</source>\n            <translation>Flytta till matchande klammerparentes</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Select to Matching Brace</source>\n            <translation>Markera till matchande klammerparentes</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Toggle Bookmark</source>\n            <translation>Växla bokmärke</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Next Bookmark</source>\n            <translation>Nästa bokmärke</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Previous Bookmark</source>\n            <translation>Föregående bokmärke</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Remove All Bookmark</source>\n            <translation>Ta bort alla bokmärken</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Styles Preferences</source>\n            <translation>Stilinställningar</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Show Line Numbers</source>\n            <translation>Visa radnummer</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Whitespace Characters</source>\n            <translation>Visa blankstegstecken</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Line Endings</source>\n            <translation>Visa radavslut</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Indentation Guides</source>\n            <translation>Visa indragningsstödlinjer</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Long Line Marker</source>\n            <translation>Visa lång radmarkör</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Toolbar</source>\n            <translation>Visa verktygsfält</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Statusbar</source>\n            <translation>Visa statusfält</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Show Horizontal Scrollbar</source>\n            <translation>Visa horisontell rullningslist</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Sort Tabs Alphabetically</source>\n            <translation>Sortera flikar alfabetiskt</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Toggle Breakpoint</source>\n            <translation>Växla brytpunkt</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Next Breakpoint</source>\n            <translation>Nästa brytpunkt</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Previous Breakpoint</source>\n            <translation>Föregående brytpunkt</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Remove All Breakpoints</source>\n            <translation>Ta bort alla brytpunkter</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Run File</source>\n            <translation>Kör fil</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Run Selection</source>\n            <translation>Kör markering</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Run Tests</source>\n            <translation>Kör tester</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Run Demos</source>\n            <translation>Kör demovisningar</translation>\n        </message>\n        <message>\n            <location line=\"+3\"/>\n            <source>Help on Keyword</source>\n            <translation>Hjälp med nyckelord</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Document on Keyword</source>\n            <translation>Dokument om nyckelord</translation>\n        </message>\n        <message>\n            <location line=\"+4\"/>\n            <source>Go to Homepage</source>\n            <translation>Gå till hemsidan</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Go Back one Page</source>\n            <translation>Gå tillbaka en sida</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Go Forward one Page</source>\n            <translation>Gå framåt en sida</translation>\n        </message>\n        <message>\n            <location line=\"+1\"/>\n            <source>Bookmark this Page</source>\n            <translation>Bokmärk denna sida</translation>\n        </message>\n    </context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/tr_TR.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"tr_TR\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>Geçersiz dosya adı</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>Varsayılan boyut farkı</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>Arka plan rengi, pembe (255, 0, 255) varsayılan anlamına gelir</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>b</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>u</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>&quot;%1&quot; düzenle</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>&quot;%1&quot; hakkında yardım</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>&quot;%1&quot; ile ilgili belgeler</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Yapıştır</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>Tümünü Seç</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>Seçimi Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <oldsource>Print selection</oldsource>\n        <translation>Seçimi yazdır</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <oldsource>selection</oldsource>\n        <translation>Seçim yardımı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <oldsource>Documentation on</oldsource>\n        <translation>Seçimle ilgili belgeler</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>Pencereyi Temizle</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%1 &apos;i %2 satırında düzenleyin</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>seçim panoya kopyalandı</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>Varsayılan</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Hata</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Yorum</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Numara</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Anahtar kelime</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Çift tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Tek tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatör</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Tanımlayıcı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Basamaklı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>Parametre genişletme</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Ters tik</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Burada belge sınırlayıcı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Tek alıntı belge burada</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>Ön tanımlı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Yorum</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Anahtar kelime</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>Etiket</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>Komut karakterini gizle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>Harici komut</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>Değişken</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatör</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>Ön tanımlı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>Varsayılan pasif</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>C açıklaması</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>Pasif C yorumu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>C++ açıklaması</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>Pasif C++ açıklaması</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>JavaDoc tarzı C yorumu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>Pasif JavaDoc tarzı C yorumu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Numara</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>Pasif numara</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Anahtar kelime</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>Pasif anahtar kelime</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Çift tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>Pasif çift tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Tek tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>Pasif tek tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>Pasif IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>Ön işlemci bloğu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>Pasif ön işlemci bloğu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatör</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>Etkisiz işleç</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Tanımlayıcı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>Pasif tanımlayıcı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>Kapatılmamış dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>Pasif kapatılmamış dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>C# kelimesi kelimesine dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>Pasif C# kelimesi kelimesine dizesi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>JavaScript normal ifadesi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>Pasif JavaScript normal ifadesi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>JavaDoc tarzı C++ açıklaması</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>Pasif JavaDoc tarzı C++ açıklaması</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>İkincil anahtar kelimeler ve tanımlayıcılar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>Pasif ikincil anahtar kelimeler ve tanımlayıcılar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>JavaDoc anahtar sözcüğü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>Pasif JavaDoc anahtar sözcüğü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>JavaDoc anahtar kelime hatası</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>Pasif JavaDoc anahtar kelime hatası</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>Küresel sınıflar ve yazıtipleri</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>Pasif genel sınıflar ve türler</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>C++ ham dizi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>Pasif C++ ham dizesi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <oldsource>Inactive C# verbatim string</oldsource>\n        <translation>Vala üç tırnaklı harfi harfine dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <oldsource>Inactive single-quoted string</oldsource>\n        <translation>Pasif Vala üç tırnaklı harfi harfine dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <oldsource>Single-quoted string</oldsource>\n        <translation>Pike hash-tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <oldsource>Inactive single-quoted string</oldsource>\n        <translation>Pasif Pike hash-tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation>Ön işlemci bloğu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation>Pasif ön işlemci C yorumu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation>JavaDoc tarzı ön işlemci yorumu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation>Pasif JavaDoc tarzı ön işlemci yorumu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation>Kullanıcı tanımlı değişmez bilgi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation>Pasif kullanıcı tanımlı değişmez bilgi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation>Görev işaretçisi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation>Pasif görev işaretçisi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation>Kaçış dizisi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation>Pasif kaçış dizisi</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>Ön tanımlı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Yorum</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Komut</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>Başlık</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>Pozisyon</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>Satır kaldırıldı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>Satır eklendi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>Satır değiştirildi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation>Ekleme yaması eklendi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation>Yama ekleme kaldırıldı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation>Kaldırma yaması eklendi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation>Kaldırma yaması eklendi</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>Ön tanımlı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Yorum</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>Komut</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Numara</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Anahtar kelime</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Tek tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatör</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Tanımlayıcı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Çift tırnaklı dize</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>Varsayılan</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>Hata</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>Yorum</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>Numara</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>Anahtar kelime</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>Çift tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>Tek tırnaklı dize</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>Operatör</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>Tanımlayıcı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>Basamaklı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>Dizi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>Hash</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>Sembol tablosu</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>Düzenli ifade</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>İkame</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>Ters tik</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>Veri bölümü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>Burada belge sınırlayıcı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>Tek alıntı belge burada</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>Burada çift alıntı yapılan belge</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>Buraya geri dönüş belgesi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>Tırnaklı dize (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>Tırnaklı dize (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>Tırnaklı dize (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>Tırnaklı dize (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>Tırnaklı dize (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>POD kelimesi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>Alt rutin prototip</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>Biçim tanımlayıcı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>Gövde biçimlendir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>Çift tırnaklı dize (enterpolasyonlu değişken)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>Çeviri</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>Normal ifade (enterpolasyonlu değişken)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>Değiştirme (enterpolasyonlu değişken)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>Geri işaretleri (enterpolasyonlu değişken)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>Burada çift alıntı yapılan belge (enterpolasyonlu değişken)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>Buraya geri dönüş belgesi (enterpolasyonlu değişken)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>Alıntılanan dize (qq, enterpolasyonlu değişken)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>Alıntılanan dize (qx, enterpolasyonlu değişken)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>Alıntılanan dize (qr, enterpolasyonlu değişken)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>&amp;Geri Al</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Yinele</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>Ke&amp;s</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>&amp;Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>&amp;Yapıştır</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Sil</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>Hepsini Seç</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>Bağlantıyı Aç</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>Bağlantı Adresini Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>Email gönder...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>E-posta Adresini Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>%1 &apos;i %2 satırında düzenleyin</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>Açıklamalar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>Metin</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>Dize</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>Yazı Tipi</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>kalın</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>b</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>eğik</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>renk</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>sol</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>orta</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>sağ</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>Yatay hizalama</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>Dikey hizalama</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>üst</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>alt</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>Pozisyon</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>Genişlik</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>Yükseklik</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>birimler</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>normalleştirilmiş</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>Kutuya sığdır</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>Kutu</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>Arkaplan</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>Kenar</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>Çizgi stili</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>yok</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>Çizgi Kalınlığı</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>Tümünü Seç</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>Duraklat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>Durdur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Devam</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>Komut Araç&apos;ı</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Octave Topluluk Haberleri</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>Varsayılan</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>Hata</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>Çabuk</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Octave Belgelendirmeleri</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>Yardım koleksiyonu geçici olarak kopyalanamadı\ndosya. Arama yetenekleri etkilenebilir.\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>için gerekli veriler ayarlanamadı.\nbelge görüntüleyici. Belki Qt SQlite\nmodül eksik mi?\nYalnızca Komut Penceresindeki yardım metni\nkullanılabilir.</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>İçindekiler</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>Arama işlevi dizinine metin girin</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>Ara</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>İşlev Dizini</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>Yer İmleri</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>Ana sayfaya git</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>Geri git</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>Önceki sayfalar</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>İleri git</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>Sonraki sayfalar</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>Bul</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>Yaklaştır</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>Uzaklaştır</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>Orijinali Yakınlaştır</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>Geçerli sayfayı işaretle</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>%1 yardım dosyası kaydedilemiyor.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\nHiçbir belge yerimi yüklenmedi!</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: Dokümantasyon Yer İmlerini Yükleme</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>Yer imlerini aramak için metni girin</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>Süzgeç</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>Yeni Klasör</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>&amp;Aç</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>&amp;Yeniden Adlandır</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>Kald&amp;ır</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>&amp;Klasör Ekle</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>Filtreyi &amp;Gizle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>Filtreyi &amp;Göster</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: Dokümantasyon Yer İmlerini Kaydetme</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>%1 dosyası yazılamıyor:\n%2.\n\nDokümantasyon yer imleri kaydedilmez!\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>%1 dosyası okunamıyor:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>%1 içinde başlangıç öğesi bulunamadı.\nGeçersiz yer imi dosyası?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>Dosya\n%1\ngeçerli bir XBEL dosyası sürüm 1.0 değil.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>Bilinmeyen başlık</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>Belgelendirme</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>Yardım için belgelere bakın.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>&amp;Tümünü Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>&amp;Diğerlerini Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>&amp;Soldaki araca Geç</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>&amp;Sağdaki araca Geç</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation>&amp;Tümünü Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation>Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation>Geçerli &amp;Dizini Ayarla</translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>Özel dosya düzenleyicisi başlatılamadı\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>Henüz yapılandırılmış özel bir düzenleyici yok.\nTercihleri açmak istiyor musunuz?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>Devam</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>Dosyayı Kaydet ve Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>Dosya kaydedilmedi! Seçilen ada sahip bir dosya\n%1\ndüzenleyicide zaten açık.</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>İlişkili dosya düzenleyici sekmesi kayboldu.</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>Dosya açılamadı\n%1\nokumak için: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Dosya\n%1\nmevcut değil. Onu oluşturmak ister misin?</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>Oluştur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>İptal</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>Dosya açılamadı\n%1\nyazmak için: %2.</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Dosya</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>&amp;Son Düzenleyici Dosyaları</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>İşlevi &amp;Düzenle</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>Dosyayı &amp;Kaydet</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>Dosyayı &amp;Farklı Kaydet...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>Tümünü Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>Diğer Dosyaları Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>Yazdır...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Düzenle</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>&amp;Yinele</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>Ke&amp;s</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>&amp;Bul ve Değiştir...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>&amp;Sonraki Bul</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>&amp;Öncekini Bul</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>&amp;Komutlar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>Satırı Sil</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>Satırı Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>Satır Kes</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Kelimenin Başını Sil</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>Kelimenin Sonuna Kadar Sil</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Satırın Başına Kadar Sil</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>Satırın Sonuna Kadar Sil</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Yinelenen Seçim/Satır</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>Satırı Aktar</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>Tamamlama Listesini &amp;Göster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>&amp;Biçim</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>&amp;Büyük Harf Seçimi</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>&amp;Küçük Harf Seçimi</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>&amp;Açıklama</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>&amp;Açıklamayı geri al</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>Yorum (Dize Seçme)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>&amp;Seçimi Kesin Olarak Girintilendir</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>&amp;Seçimi Kesin olarak Girintiden Kaldır</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>Girinti Kodu</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>Satır Sonlarını &amp;Windows&apos;a (CRLF) Dönüştür</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>Satır Sonlarını &amp;Unix&apos;e (LF) Dönüştür</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>Satır Sonlarını Eski &amp;Mac&apos;e Dönüştür (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>Gezi&amp;nme</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>&amp;Satıra Git...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Eşleşen Ayraca Taşı</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Eşleşen Ayraç Seçin</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>&amp;Sonraki Yer İşareti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>&amp;Önceki Yer İşareti</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>&amp;Yer İşaretini Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>Tüm Yer İşaretlerini &amp;Kaldır</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>&amp;Tercihler...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>&amp;Stil Tercihleri...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>&amp;Görünüm</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>&amp;Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>&amp;Satır Numaralarını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>&amp;Boşluk Karakterlerini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>Satır &amp;Sonlarını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>Girinti &amp;Kılavuzlarını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>Uzun Çizgi &amp;İşaretleyiciyi Göster</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>&amp;Araç Çubuğunu Göster</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>&amp;Durum çubuğunu Göster</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>&amp;Yatay Kaydırma Çubuğunu Göster</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>&amp;Yaklaştır</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>&amp;Uzaklaş</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>&amp;Normal Boyut</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>Sekmeleri Alfabetik Olarak &amp;Sırala</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>&amp;Hata Ayıklama</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>&amp;Kesme Noktasını Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>&amp;Sonraki Kesme Noktası</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>Önc&amp;eki Kesme Noktası</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>Tüm Kesme Noktalarını &amp;Kaldır</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>&amp;Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>Dosyayı Kaydet ve Çalıştır/Devam Et</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>&amp;Seçimi Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>Dosyayı Kaydedin ve Tüm &amp;Testleri Çalıştırın</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>Dosyayı Kaydet ve Tüm &amp;Demoları Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Yardım</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>Anahtar Kelime &amp;Yardımı</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>Anahtar Kelime ile ilgili &amp;Belgeler</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>Son Dosyalar</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>Tam Dosya Yolunu &amp;Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>Düzenleyici</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>satır:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>col:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>kodlanıyor:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>eol:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>Kesme Noktası durumu</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>HATA: </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>Değiştirilmiş veya adlandırılmamış dosyaya kesme noktası eklenemez.\nKesme noktası kaydedip eklemek mi yoksa iptalmi edilsin?</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>Satıra git</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>Satır numarası</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>Seçili metni yorumla</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>Kullanılacak yorum dizesi:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;isimsiz&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>Kapatmayı iptal etmek, kaydetmek veya değişiklikleri silmek istiyor musunuz?</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>Dosya\n\n   %1\n\nkapatılmak üzere ancak değiştirildi.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>&apos;%1&apos; dosyası okunamıyor\nseçilen kodlama &apos;%2&apos; ile: %3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>Dosyayı okurken sorunlar oluştu\n%1\nseçilen kodlama %2 ile.\n\nDosyayı değiştirmek ve kaydetmek veri kaybına neden olabilir!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>Yine de &amp;düzenle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>Kodlamayı değiş&amp;tir</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>&amp;Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>Yeni varsayılan kodlamayı seçin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>Lütfen yeni bir kodlama seçin\nmevcut dosyayı yeniden yüklemek için.\n\nBu, varsayılan kodlamayı değiştirmez.\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>Hata Ayıklama veya Kaydetme</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>Bu dosya şu anda yürütülüyor.\nHata ayıklamadan çıkılsın ve kaydedilsin mi?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>%1 dosyası yazmak için açılamadı:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>Değişiklikler dosyaya kaydedilemedi\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Octave Dosyaları (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>Tüm Dosyalar (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>&quot;%1&quot;\ngeçerli bir tanımlayıcı değil.\n\nBu dosya adını saklarsanız, yapamazsınız\nadını Octave komutu olarak kullanarak betiğinizi çağırın.\n\nBaşka bir isim seçmek ister misin?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>Mevcut düzenleyici içeriği kodlanamaz\nseçilen kodlama %1 ile.\nBunu kullanmak veri kaybına neden olur!\n\nLütfen başka bir tane seçin!</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1\n  zaten var\nÜzerine yazmak istiyor musunuz?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\nUyarı: Düzenleyicideki içerik değiştirildi!</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation>Görünüşe göre &apos;%1&apos; başka bir uygulama tarafından değiştirilmiş. Yeniden yüklemek ister misin?%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>Görünüşe göre dosya\n%1\nsilindi veya yeniden adlandırıldı. Şimdi kaydetmek istiyor musunuz?%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation>Dosya boyutu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation>Dosya türü</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation>Değiştirilme tarihi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation>Gizlileri göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation>Alternatif satır renkleri</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation>Yolu veya dosya adını girin</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation>Bir dizin yukarı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation>Octave dizinini göster</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation>Mevcut Octave dizinine git</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation>Octave dizinini ayarla</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation>Octave dizinini mevcut tarayıcı dizinine ayarlayın</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation>Mevcut dizindeki eylemler</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation>Ana Dizini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation>Tarayıcı Dizini Ayarla...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation>Dosyaları Bul...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation>Yeni Dosya...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation>Yeni Dizin...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation>Dosya/klasörü açmak için çift tıklayın, alternatifler için sağ tıklayın</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation>Yeniden adlandır...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation>Aç</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation>Sistem Dosya Gezgini&apos;nde Aç</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation>Metin düzenleyicide aç</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation>Seçimi Panoya Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation>Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation>Veri Yükle</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation>Mevcut Dizini Ayarla</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation>Yola Ekle</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation>Seçilen Dizinler</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation>Seçilen Dizinler ve Alt Dizinler</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation>Yoldan Kaldır</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation>Sil...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation>Dosyayı/dizini sil</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation>Seçilen %1 dosyanın tümünü silmek istediğinizden emin misiniz?\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation>Silmek istediğine emin misin\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation>Boş olmayan bir dizin silinemez</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation>Silme hatası</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation>&quot;%1&quot; dosyası silinemedi.</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation>Dosya tarayıcısının dizinini ayarlayın</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation>Dosya Oluştur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>İçinde dosya oluştur\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation>Yeni Dosya.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation>Dosya oluşturma hatası</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation>Dosya oluşturulamadı\n&quot;%1&quot;.</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation>Dizin Oluşturun</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation>İçinde klasör oluştur\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation>Yeni Dizin</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>&quot;%1&quot; dosyası &quot;%2&quot; olarak yeniden adlandırılamadı.</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>Dosya Gezgini</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>Dosyalarınıza göz atın</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation>Dosya sistemi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation>Editör dosyaları</translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>Zevkli!</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>Önceki</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>Bitir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>İptal</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Octave&apos;i faydalı bir araç olarak bulacağınızı umuyoruz.&lt;/p&gt;\n&lt;p&gt;Sorunla karşılaşırsanız, ticari destek seçenekleri, tartışma panosu, wiki ve diğer topluluğa dayalı destek kanalları dahil olmak üzere yardım almanın çeşitli yolları vardır.\n&lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (harici tarayıcıda açılır) adresini ziyaret ederek bunların her biri hakkında daha fazla bilgi bulabilirsiniz. .&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Octav hakkında daha fazla bilgi için:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;&lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; adresini ziyaret edin (harici tarayıcıda açılır)&lt;/li&gt;\n&lt;li&gt;Belgeleri çevrimiçi olarak &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; veya &lt;a href=&quot;https:/ adresinden edinin /www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; biçimi (bağlantılar harici tarayıcıda açılır)&lt;/li&gt;\n&lt;li&gt;Yardım menüsünü kullanarak Octave GUI&apos;nin dokümantasyon tarayıcısını açın&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>Düzenleyici: Bul ve Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>&amp;Bul:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>Arama metnini girin</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>De&amp;ğiştir:</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>Değiştirme metnini girin</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>&amp;Büyük/küçük harf eşleştir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>&amp;Başlangıçta ara</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>&amp;Arama sırasında sarın</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>&amp;Sonraki Bul</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>&amp;Öncekini Bul</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>&amp;Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>&amp;Tümünü Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>&amp;Daha...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>&amp;Bütün kelimeler</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>Düzenli &amp;ifadeler</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>&amp;Geriye doğru ara</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>Arama se&amp;çimi</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>Sonundan ara</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>Baştan ara</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>Sonucu Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 öğe değiştirildi</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>Sonuç Bulundu</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>Başka eşleşme bulunamadı</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>Dosyaları Bul</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>Adlandırılmış:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>Başla:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>Başlangıç dizinini girin</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>Gözat...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>Başlangıç dizinine göz atın</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>Mevcut Dizin</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>Başlangıç ​​dizinini geçerli dizine ayarla</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>Alt dizinlerde ara</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>Eşleşen dosyalar için dizinlerde yinelemeli olarak arama yapın</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>Dizin adlarını dahil et</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>Eşleşen dizinleri arama sonuçlarına dahil et</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>Büyük/küçük harf durumunu yoksay</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>Büyük/küçük harfe duyarlı olmayan eşleşme gerçekleştirin</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>Metin içerir:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>Arama sonuçlarına yalnızca belirtilen metni içeren dosyaları dahil et</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>Eşleştirilecek metin</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>Sonuçlar: Çift tıklama dosyayı açar veya dizini ayarlar</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>Arama sonuçları</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>Boşta.</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>Dosya adı arama desenlerini girin.\nBirkaç farklı desen olabilir\n&apos;;&apos; ile ayrılmış, örneğin &apos;*.cc ; *.h&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>Bul</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>Eşleşen dosyaları aramaya başlayın</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>Durdur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>Aramayı durdur</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>Dosya adı/Konum</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>Dosya içeriği</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>Aranıyor...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 eşleşme</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>Arama dizinini ayarlayın</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>Dosya Adı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>Dizin</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>Dosyayı açmak için çift tıklayın</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>Dizin ayarlamak için çift tıklayın</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>Bul:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>İleriye doğru ara</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>Geriye doğru ara</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>Bulma iletişim kutusunu kapat</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>Ayarlar dosyasını oluştururken %1 hatası\n%2\nOkuma ve yazma izinlerine sahip olduğunuzdan emin olun.\n%3\n\nOctave GUI&apos;nin şimdi kapatılması gerekiyor.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Octave Kritik Hata</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>Komut geçmişine göz atın ve arayın.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>Değerlendirme</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>Komut dosyası oluştur</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>Filtreyi gizle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Filtreyi göster</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>Komut Penceresine aktarmak için bir komutu çift tıklayın.</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>Komut geçmişini filtrelemek için metin girin</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>Süzgeç</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>Komut Geçmişi</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Octave&apos;e hoş geldiniz!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>Sonraki</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>İptal</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Bu bilgisayarda Octave grafik arayüzünü ilk kez kullanıyor görünüyorsunuz.\nBir yapılandırma dosyası oluşturmak ve Octave&apos;ı başlatmak için &apos;İleri&apos;yi tıklayın.&lt;/p&gt;\n&lt;p&gt;Yapılandırma dosyası şurada saklanır:&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>Bağlantıyı Kaldırma Aracı</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>Aracı kapat</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>Profil oluşturucu</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>Octave&apos;den çıkmak istediğinizden emin misiniz?</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>Çalışma Alanını Farklı Kaydet</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>Çalışma Alanını Yükle</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>Octave Hakkında</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>Dizinlere göz atın</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Octave Dosyaları (*.m);;Tüm Dosyalar (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>Yeni İşlev</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>Yeni işlev adı:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>%1 yerleşik, derlenmiş veya satır içidir\nişlevdir ve düzenlenemez.</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>%1 işlevi bulunamıyor</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>&amp;Dosya</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>Aç...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>Düzenleyicide mevcut bir dosyayı açın</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>Çalışma Alanını Yükle...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>Çalışma Alanını Farklı Kaydet...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>Çık</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>Yeni</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>Yeni Komut Dosyası</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>Yeni İşlev...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>Yeni Şekil</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>&amp;Düzenle</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>Geri Al</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>Yapıştır</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>Tümünü Seç</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>Panoyu Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>Dosyaları Bul...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>Komut Penceresini Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>Komut Geçmişini Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>Çalışma Alanını Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>Yolu Ayarla...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>Tercihler...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>Hata &amp;Ayıklama</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>Adım</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>Adım Atın</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>Dışarı Çık</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>Devam</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Hata Ayıklama Modundan Çık</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>&amp;Araçlar</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>Profil &amp;Oluşturucu Oturumunu Başlatın</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>&amp;Profil Oturumunu Sürdür</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>&amp;Profil Oluşturucuyu Durdur</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>&amp;Profil Oluşturucu Verilerini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>&amp;Pencere</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>Komut Penceresini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>Komut Geçmişini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>Dosya Tarayıcısını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>Çalışma Alanını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>Düzenleyiciyi Göster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>Belgelendirmeyi Göster</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>Değişken Düzenleyiciyi Göster</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>Komut Penceresi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>Komut Geçmişi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>Dosya Gezgini</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>Çalışma Alanı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>Belgelendirme</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>Değişken Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>Önceki Araçlar</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Varsayılan Pencere Düzenini Sıfırla</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>&amp;Yardım</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>Hata Bildir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Octave Paketleri</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>Katılın</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>Octave&apos;a Bağış Yapın</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>Diskte</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>Çevrimiçi</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>&amp;Yenilikler</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Sürüm Notları</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>Topluluk Haberleri</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>Araç çubuğu</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>Dizin adını girin</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>Mevcut Dizin: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>Bir dizin yukarı</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;ın topluluk haber kaynağı kullanılamıyor gibi görünüyor.\n&lt;/p&gt;\n&lt;p&gt;\nEn son haberler için lütfen kontrol edin\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nweb bağlantınız olduğunda (bağlantı harici bir tarayıcıda açılır).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Octave Geliştiricileri, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nEn son Octave Topluluğu haberlerini görüntülemek için web&apos;e bağlanma devre dışı bırakıldı.\n&lt;/p&gt;\n&lt;p&gt;\nEn son haberler için lütfen kontrol edin\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nweb bağlantınız olduğunda (bağlantı harici bir tarayıcıda açılır)\nveya Octave&apos;ın ağ ayarları sekmesinden haberler için web bağlantılarını etkinleştirin.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Octave Geliştiricileri, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>Aracı Gizle</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>Panel Aracı</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>Bağlantıyı Kaldırma Aracı</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>Yardım açık</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>Belgelendirme açık</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>Düzenle</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop eğer ...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>Geçici dosyalar oluşturulamadı.\nTemp&apos;ye yazma erişiminiz olduğundan emin olun. dizin\n%1\n\n&quot;Seçimi Çalıştır&quot; geçici dosyalar gerektirir.</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>Tüm &apos;%2&apos; oluşumlarını &apos;%3&apos; ile değiştirmek için &apos;%1&apos; tuşuna basın.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>Varsayılan</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>Oluştur</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>İptal</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>Dosya\n%1\nmevcut değil. Onu oluşturmak ister misin?</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Octave Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>%1 dosyası yükleme yolunda mevcut değil.  Düzenlediğiniz işlevi çalıştırmak veya hatalarını ayıklamak için, %2 dizinine geçmelisiniz veya bu dizini yükleme yoluna eklemelisiniz.</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>%1 dosyası, yükleme yolunda aynı ada sahip bir dosya tarafından gölgeleniyor. Düzenlediğiniz işlevi çalıştırmak veya hata ayıklamak için %2 dizinine geçin.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>Dizini Değiştirin veya Yolu Yüklemek İçin Dizin Ekleyin</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>Dizini &amp;Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>Yükleme Yoluna Dizin &amp;Ekle</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>&apos;%1&apos; sürüm notları dosyası boş.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>&apos;%1&apos; sürüm notları dosyası okunamıyor.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Octave Sürüm Notları</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>Yolu Ayarla</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>Tüm değişiklikler anında geçerli olur.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>Dizin Ekle...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>Tek Dizin</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>Alt Dizinli Dizin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>Yukarı Taşı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>En Alta Taşı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>Yukarı Taşı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>Aşağı Taşı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>Kaldır</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>Tekrar Yükle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>Kaydet</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>Geri Al</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>Son Değişikliği Geri Al</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>Tüm Değişiklikleri Geri Al</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>Dizin Aç</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>Üst</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>Alt</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>Sol</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>Sağ</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>Ön plan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>Arkaplan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>Seçim</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>İmleç</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>Seçili Ön Plan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>Seçili Arka Plan</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>Alternatif Arka Plan</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>argüman</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>evrensel</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>ısrarcı</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>Ortam Değişkenleri</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>İkinci renk modu (açık/koyu)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>İkinci bir renk grubuna geçin.\nAçık/karanlık modlarını tanımlamak için kullanışlıdır.\nUygulanmayan mevcut değişiklikleri iptal eder!</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>Varsayılan renkleri yeniden yükleyin,\no anda seçili olan moda bağlıdır.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>Varsayılan renkleri yeniden yükleyin,\nŞu anda oluşan moda bağlıdır.</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>&amp;Varsayılan renkleri yeniden yükle</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>&amp;Varsayılan stilleri yeniden yükle</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>Mevcut tercihler yükleniyor ... </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>Sistem ayarları</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>Işınlama İmleci</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>İmleci Engelle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>İmleç Altı Çizili</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>Vurgulanan mevcut satırın rengi (otomatik renk için macenta (255,0,255)</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>Octave Başlangıç Dizinini Ayarla</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>Dosya Tarayıcı Başlangıç Dizinini Ayarlayın</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>Tercihler uygulanıyor ... </translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>%1 Octave kısayol dosyası olarak açılamadı</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>Öznitelik renklerini etkinleştir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>Araç ipuçlarını gizle</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>Kısayolları dosyadan içe aktar...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Octave Kısayol Dosyaları (*.osc);;Tüm Dosyalar (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>Kısayolları dosyaya aktar...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>Kısayolların Üzerine Yazma</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>Tüm kısayolların üzerine yazmak üzeresiniz.\nMevcut kısayol kümesini kaydetmek mi yoksa eylemi iptal etmek mi istersiniz?</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>Kaydetme</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Octave Arayüz tercihleri</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>Topluluk Haberleri</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>Önceki</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>Sonraki</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>İptal</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;Octave başladığında, Octave topluluğu hakkında güncel haberler ve bilgiler için isteğe bağlı olarak Octave web sitesini kontrol edecektir.\nKontrol her gün en fazla bir kez yapılacak ve haberler yalnızca haberleri son görüntülemenizden bu yana yeni bir şey olması durumunda gösterilecektir.&lt;/p&gt;\n&lt;p&gt;&quot;Yardım&quot; menüsünde &quot;Topluluk Haberleri&quot; öğesini seçerek veya şu adresi ziyaret ederek de haberleri görüntüleyebilirsiniz:\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Octave topluluğuyla ilgili güncel haberleri ve bilgileri görüntülemek için Octave&apos;in, başladığında Octave web sitesine bağlanmasına izin verin.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>Yeni Kısayolu Girin</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>Özel kısayolu girin\nEylem: %1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>Kısayolu yazarak girin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>Çalışma değiştirici ekle\n(sayı tuşlarını girmenize olanak sağlar)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>Güncel Kısayol</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>Varsayılan Kısayol</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>Varsayılan olarak ayarla</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>Çift Kısayol</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>Seçilen kısayol\n   &quot;%1&quot;\neylem için zaten kullanılıyor\n   &quot;%2&quot;.\nKısayolu kullanmak ve onu önceki eylemden kaldırmak istiyor musunuz?</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>Genel</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>Dosya menüsü</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>Düzenle Menüsü</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>Hata Ayıklama Menüsü</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>Araçlar Menüsü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>Pencere Menüsü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>Yardım Menüsü</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>Haber Menüsü</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>Panel Araçlarının Kullanımı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>Panel Araçların`da Sekme İşleme</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>Panel Araçların`da Bul ve Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>Yaklaştırma Düzenleyicisi ve Belgelendirmesi</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>Menüyü Görüntüle</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>Çalıştır Menüsü</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>Belge Görüntüleyici</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>Gözat</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>%1 öğesi kısayol ayarları iletişim kutusunda bulunamadı</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>GNU Octave&apos;e Hoş geldiniz</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation>Octave&apos;e hoş geldiniz!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>Komut Penceresi</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>Panel Aracı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>Değişken Düzenleyici: </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>Bağlantıyı Kaldırma Aracı</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>Geometriyi geri yükle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>Yineleme</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>Değişken Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>Değişkenleri düzenleyin.</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>Değişken Düzenleyici Araç Çubuğu</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>Kaydet</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>Değişkeni bir dosyaya kaydedin</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>Biçimde kaydet ...</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>Değişkeni farklı biçimde bir dosyaya kaydedin</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>Kes</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>Verileri panoya kesin</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>Verileri panoya kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>Yapıştır</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>Panoyu değişken verilere yapıştırın</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>Grafik</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>Seçilen Verilerin Grafiği</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>Seçilen Verilerin Grafiği</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>Yukarı</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>Değişken hiyerarşisinde bir seviye yukarı çıkın</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>%1 Değişkenini Farklı Kaydet</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>Kes</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>Yapıştır</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>Sil</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>Seçimden Değişken</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>Aktar</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> sütunlar</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> sütun</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> satırlar</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> satır</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>GNU Octave&apos;e Hoş geldiniz</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>İsim</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>Sınıf</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Boyut</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Değer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Öznitelik</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>Kopyalamak, yeniden adlandırmak veya görüntülemek için sağ tıklayın</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>karmaşık</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>Sınıf</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>Boyut</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>Değer</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>Öznitelik</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>Çalışma Alanı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>Etkin çalışma alanındaki değişkenleri görüntüleyin.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>Çalışma alanını filtrelemek için metin girin</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>Süzgeç</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>Etkin çalışma alanındaki değişkenleri görüntüleyin.&lt;b&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>Değişken nitelikler için renkler:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>Değişken Düzenleyicide Aç</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>Adını Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>Değeri kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>Yeniden adlandır</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>Yalnızca üst düzey semboller yeniden adlandırılabilir</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>Filtreyi gizle</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>Filtreyi göster</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>Yönlendirilen akış fd = %1 ile açılamıyor.</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>fd = %1 ile akışın arabelleğe alınması devre dışı bırakılamaz.</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>fd = %1 ile yönlendirilen akış kopyalanamıyor.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>fd = %1 ile akışı yeniden yönlendirmek için boru oluşturulamıyor:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>fd = %1 ile yönlendirilen akışın kopyası alınamıyor\nfd = %2 ile borulamak için: %3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>Yönlendirilen akışları dinlerken hata oluştu</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation>Yönlendirilen strem&apos;den okuma hatası fd = %1.</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\nÇıkış yönlendirmesi </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> işe yaramayacak.</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\nHata: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>Genel</translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation>Yalnızca Octave logosu</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>Mektup simgeleri</translation>\n    </message>\n    <message>\n        <location line=\"-334\"/>\n        <source>Dock widget title bar</source>\n        <translation>Panel aracı başlık çubuğu</translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation>Küçük</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>Büyük</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>Özel stil</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation>3B</translation>\n    </message>\n    <message>\n        <location line=\"+565\"/>\n        <source>Editor</source>\n        <translation>Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>Bu, tek aralıklı yazı tipleri için iyi çalışır. Çizgi, varsayılan yazı tipinde bir boşluk karakterinin genişliğine göre bir konumda çizilir. Stiller orantılı yazı tipi kullanırsa veya çeşitli yazı tipi boyutları veya kalın, italik ve normal metinler kullanılırsa çok iyi çalışmayabilir.</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>Kod Katlamayı Etkinleştir</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation>Eski Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>Yatay kaydırma çubuğunu göster</translation>\n    </message>\n    <message>\n        <location line=\"-516\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ayarlanırsa, ana pencereye sabitlenmiş widget&apos;ların odağı fare imlecini takip eder. Bu, &amp;quot;odak fareyi izler&amp;quot; masaüstü ortamı için kullanılır.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>Ana pencereye yerleştirilmiş araçlar için odak fareyi takip eder</translation>\n    </message>\n    <message>\n        <location line=\"+494\"/>\n        <source>Show tool bar</source>\n        <translation>Araç çubuğunu göster</translation>\n    </message>\n    <message>\n        <location line=\"+221\"/>\n        <source>Rotated tabs</source>\n        <translation>Döndürülmüş sekmeler</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>Pozisyon</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>Azami. karakter cinsinden sekme genişliği (0: sınır yok)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Azami. karakter cinsinden bir sekmenin genişliği (ortalama karakter genişliği). Döndürülmüş sekmeler için özellikle kullanışlıdır.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+260\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>Uzun çizgileri geçerli pencere kenarlığında kaydır</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Indentation</source>\n        <translation>Girinti</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation>Girinti genişliği</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Sekme girintileri satırı</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>Otomatik girinti</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Sekme genişliği</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>Girinti kılavuzlarını göster</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>Geri tuşu çizgiyi kaldırır</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation>Girinti sekmeleri kullanır</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation>Otomatik tamamlama</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>Anahtar kelimeleri eşleştir</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>Büyük küçük harf duyarlı</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>Kelimeyi önerilen bir kelimeyle değiştirin</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>Belgedeki kelimeleri eşleştir</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation>Octave yerleşikleri ile</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Octave fonksiyonları ile</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>Tamamlama listesini otomatik olarak göster</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>Harici olarak değiştirilen dosyaları istem olmadan yeniden yükleyin</translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation>Özel dosya düzenleyiciyi kullanın</translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>Yükleme ve kaydetme için kullanılan metin kodlaması</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation>Düzenleyici Stilleri</translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(Arabellek boyutunu değiştirmek geçmişi temizler)</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation>Geçmiş arabellek Boyutu</translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>Yazı Tipi</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>Satır numaralarını göster</translation>\n    </message>\n    <message>\n        <location line=\"-866\"/>\n        <source>Interface</source>\n        <translation>Arayüz</translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation>Çıkmadan önce onayla</translation>\n    </message>\n    <message>\n        <location line=\"-72\"/>\n        <source>Graphic icons</source>\n        <translation>Grafik simgeleri</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>Durum çubuğunu göster</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>Aktif olmayan metin</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>Aktif</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Background inactive</source>\n        <translation>Arka plan devre dışı</translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation>Octave Başlatma</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>Gözat</translation>\n    </message>\n    <message>\n        <location line=\"-1305\"/>\n        <source>Show whitespace</source>\n        <translation>Boşluğu göster</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>Girinti için kullanılan boşlukları gösterme</translation>\n    </message>\n    <message>\n        <location line=\"+1125\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>Var olmayan dosyaları sormadan oluşturun</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>komut satırı (%f=dosya,%l=satır):</translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation>İmleç türü:</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation>Ön plan rengini kullan</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>Yazı tipi boyutu</translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation>Dosya Gezgini</translation>\n    </message>\n    <message>\n        <location line=\"-2031\"/>\n        <source>Normal</source>\n        <translation>Normal</translation>\n    </message>\n    <message>\n        <location line=\"+359\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>Bu tercihler, herhangi bir .octaverc başlangıç dosyasından sonra uygulanır.</translation>\n    </message>\n    <message>\n        <location line=\"+540\"/>\n        <source>Show EOL characters</source>\n        <translation>EOL karakterlerini göster</translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation>Varsayılan EOL modu</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>Liste gösterilmeden önceki karakter sayısı: </translation>\n    </message>\n    <message>\n        <location line=\"-1812\"/>\n        <source>Preferences</source>\n        <translation>Seçenekler</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(yeniden başlatma gerekli)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>Yerel dosya diyaloglarını kullanın</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>Araç Çubuğu Simgeleri</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>Dil</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>Panel Araç&apos;ları pencere simgeleri</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>Stil</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>Simge teması (yeniden başlatma gerektirir)</translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation>Yanıp sönen imleç</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation>Başlangıçta açılış ekranını göster</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Octave yorumlayıcısının ilk çalışma dizini</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>Önceki oturumun son çalışma dizinini geri yükle</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>Komut</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>Başka bir widget&apos;tan bir komut çalıştırırken odağı Komut Penceresine ayarla</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>Düzenleyicideki işaretçiye ek olarak Komut Penceresinde hata ayıklama konumunu yazdırın</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>Komut Penceresi Renkleri</translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>Düzenleyici yazı tipine göre sayı boyutu</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>Geçerli satırı vurgula (renk aşağıda düzenleyici stilleriyle ayarlanabilir)</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>Çift tıklama ile seçilen bir kelimenin tüm tekrarlarını vurgulayın</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>Sekmeler</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Sekmeleri döndür: Üstte veya alttayken dikey, solda veya sağdayken yatay. Kapat düğmesi döndürülen sekmelerde gösterilmez.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>Yorumlar (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>Yorumsuz metin için dikkate alınan dizeler</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>Seçili metne yorum yapmak için kullanılan dize</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>Uzun çizgiler</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>Satır uzunluğunda uzun çizgileri kırın</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>Satırları yalnızca yorumlarda ayırın</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>Satır uzunluğu</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>Uzun çizgi işaretçisi</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>Satır</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>Arkaplan</translation>\n    </message>\n    <message>\n        <location line=\"+191\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>Sonrasına otomatik ekle &quot;Eğer&quot; vb.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>Hiç</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot; vb.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;son&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation>Hata Ayıklama</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>Her zaman hata ayıklama kesme noktalarını ve işaretçileri göster (kapatılırsa ilgili dosyayı açar)</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation>Dosya yönetimi</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>Başlangıçta veya düzenleyici kapattıktan sonra tekrar gösterildiğinde önceki oturumdan düzenleyici sekmelerini geri yükle</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>Düzenleyici widget&apos;ı kapatıldığında / gizlendiğinde tüm dosyaları kapat</translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>Dosyayı kaydederken sonunda yeni satırı zorla</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>Dosyayı kaydederken sondaki boşlukları kaldırın</translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation>Açık dosya iletişim kutusu dizini, geçerli Octave dizini yerine geçerli düzenleyici dosyasını takip eder </translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Yazı tipini, yazı tipi boyutunu (varsayılan boyuttan farklı olarak), yazı tipi stilini seçin (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;alt çizgi), metin rengi ve arka plan rengi (ikincisi için macenta rengi (255,0,255), varsayılan arka plan rengi için bir yer tutucudur).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Behavior</source>\n        <translation>Davranış</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>Önceki oturumun son dizinini geri yükle</translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>Varsayılan metin düzenleyicide açılacak dosya uzantıları (&quot;;&quot; ile ayrılmış):</translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation>Çalışma Alanı</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>Değişken nitelikler için renkler</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>Komut Penceresi yazı tipini kullan</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>Kısayol kümesini içe aktar</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>Mevcut kısayol kümesini dışa aktar</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>Kısayolları varsayılanlarına sıfırlayın</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>Öntanımlı</translation>\n    </message>\n    <message>\n        <location line=\"+232\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Tamam&lt;/span&gt; - iletişim kutusunu kapat ve ayarları uygula&lt;br&gt;&lt;span style=&quot; font-weight:600 ;&quot;&gt;Uygula - &lt;/span&gt;ayarları uygular ancak iletişim kutusunu açık bırakır&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;İptal - &lt;/span&gt;iletişim kutusunu kapatır ve henüz uygulanmamış değişiklikleri atar&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Sıfırla -&lt;/span&gt; henüz uygulanmamış değişiklikleri atarak ayarları yeniden yükleyin&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-227\"/>\n        <source>Actual</source>\n        <translation>Güncel</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>Ağ</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>Octave&apos;in güncel haberleri ve bilgileri görüntülemek için Octave web sitesine bağlanmasına izin verin</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>Proxy sunucu</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Seçim &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Ortam Değişkenleri&lt;/span&gt;. Son seçim ile proxy, boş olmayan ilk ortam değişkeni ALL_PROXY, HTTP_PROXY veya HTTPS_PROXY&apos;den alınır .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>Proxy sunucusu kullan</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>Değişken Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>Varsayılan satır yüksekliği</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>Varsayılan sütun genişliği</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>Değişken Düzenleyici Renkleri</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>Alternatif satır renkleri kullanın</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>Önlemek için genel kısayolları devre dışı bırakın.\nokuma satırı tuş vuruşlarına müdahale.\nİstisnalar: Tercümanı kesmek için Ctrl-C\nve diğer araçlara geçiş için kısayollar.</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>Komut Penceresinde odak olduğunda genel kısayolları devre dışı bırakın</translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>Octave çalışma dizinini dosya tarayıcısı ile senkronize edin</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>İlk dosya tarayıcı dizini (yalnızca Octave&apos;nin ilk çalışma dizini ile senkronize edilmemişse)</translation>\n    </message>\n    <message>\n        <location line=\"+302\"/>\n        <source>Shortcuts</source>\n        <translation>Kısayollar</translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>Önlemek için menü hızlandırıcılarını devre dışı bırakın.\nokuma satırı tuş vuruşlarına müdahale.</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>Komut Penceresi odaklandığında ana pencere menülerinin menü hızlandırıcılarını devre dışı bırak</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation>Dışa aktar</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>İçe aktar</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>Gerçek sütununa çift tıklayarak bir kısayolu düzenleyin</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>Eylem</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>Makine ismi:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation>Proxy türü:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>Port:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>Kullanıcı adı:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>Parola:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>Bağlantıyı Kaldırma/Yerleştirme Aracı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>Aracı kapat</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>Yeni Dosya</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>Yeni İşlev</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>Yeni Şekil</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>Dosya Aç</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>Çalışma Alanını Yükle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>Çalışma Alanını Farklı Kaydet</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>Octave`dan Çık</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>Yapıştır</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>Geri Al</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>Tümünü Seç</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>Panoyu Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>Dosyalarda Bul</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>Komut Penceresini Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>Komut Geçmişini Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>Çalışma Alanını Temizle</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>Yolu Ayarla</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>Seçenekler</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>Adım</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>İçeri Gir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>Dışarı Çık</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>Devam</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>Hata Ayıklama Modundan Çık</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>Profil Oluşturucu Oturumunu Başlat/Durdur</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>Profil Oluşturucu Oturumunu Sürdür</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>Profil Verilerini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>Komut Penceresini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>Komut Geçmişini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>Dosya Tarayıcısını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>Çalışma Alanını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>Düzenleyiciyi Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>Belgelendirmeyi Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>Değişken Düzenleyiciyi Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>Komut Penceresi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>Komut Geçmişi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>Dosya Gezgini</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>Çalışma Alanı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>Belgelendirme</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>Değişken Düzenleyici</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>Önceki Araçlar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>Varsayılan Pencere Düzenini Sıfırla</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>Disk Üzerindeki Belgeleri Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>Çevrimiçi Belgeleri Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>Hata Bildir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Octave Paketleri</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>Octave`ya Katkıda Bulun</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Octave Geliştirici Kaynakları</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>Octave Hakkında</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>Sürüm Notları</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>Topluluk Haberleri</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>Sekmeyi Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>Tüm Sekmeleri Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>Diğer Sekmeleri Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>Sol Sekmeye Geç</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>Sağ Sekmeye Geç</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>Sekmeyi Sola Taşı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>Sekmeyi Sağa Taşı</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>Yaklaştır</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>Uzaklaştır</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>Yaklaştırma Normal</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>Düzenleme İşlevi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>Dosyayı Kaydet</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>Dosyayı Farklı Kaydet</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>Yazdır</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>Yinele</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>Kes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>Bul ve Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>Sonraki Bul</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>Öncekini Bul</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>Kelimenin Başını Sil</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>Kelimenin Sonuna Kadar Sil</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>Satırın Başına Kadar Sil</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>Satırın Sonuna Kadar Sil</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>Satırı Sil</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>Satırı Kopyala</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>Satır Kes</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>Yinelenen Seçim/Satır</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>Satırı Aktar</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>Tamamlama Listesini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>Yorum Seçimi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>Seçimin Yorumunu Kaldır</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>Yorum Seçimi (Dize Seçme)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>Büyük Harf Seçimi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>Küçük Harf Seçimi</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>Seçimi Kesin Olarak Girintilendirin</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>Seçimi Kesin olarak Girintiden Kaldır</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>Girinti Kodu</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>Satır Sonlarını Windows&apos;a Dönüştür</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>Satır Sonlarını Unix&apos;e Dönüştür</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>Satır Sonlarını Mac&apos;e Dönüştür</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>Satıra Git</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>Eşleşen Ayraca Taşı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>Eşleşen Ayraç Seçin</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>Yer İşaretini Değiştir</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>Sonraki Yer İmi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>Önceki Yer İmi</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>Tüm Yer İşaretlerini Kaldır</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>Stil Tercihleri</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>Satır Numaralarını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>Boşluk Karakterlerini Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>Satır Sonlarını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>Girinti Kılavuzlarını Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>Uzun Çizgi İşaretleyiciyi Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>Araç Çubuğunu Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>Durum çubuğunu göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>Yatay Kaydırma Çubuğunu Göster</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>Sekmeleri Alfabetik Olarak Sırala</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>Kesme Noktasını Aç/Kapat</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>Sonraki Kesme Noktası</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>Önceki Kesme Noktası</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>Tüm Kesme Noktalarını Kaldır</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>Dosyayı Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>Seçimi Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>Testleri Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>Demoları Çalıştır</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>Anahtar Kelime Yardımı</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>Anahtar Kelime Belgesi</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>Ana sayfaya Git</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>Bir Sayfa Geriye Git</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>Bir Sayfa İleri Git</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>Bu sayfayı işaretle</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/translators",
    "content": "# Below Octave GUI translators are listed with their e-mails\n# to be able to inform them about generic translation file changes.\n# The generic file that can be used as a template for new\n# translation files is en_US.ts\n\nast_ES José Luis García Pallero <jgpallero@gmail.com>\nbe_BY\nca_ES  Salva Ardid <jsardid@gmail.com>\nde_DE  Andreas Weber <andy.weber.aw@googlemail.com>\nes_ES  José Luis García Pallero <jgpallero@gmail.com>\n       Valentin Ortega-Clavero <arcanos3030@gmail.com>\neu_ES  Ander Aurrekoetxea <zaurreko@gmail.com>\nfr_FR  David Bateman <dbateman@free.fr>\n       Catalin Codreanu <codreanu.catalin@gmail.com>\n       Pantxo Diribarne <pantxo.diribarne@gmail.com>\nhu_HU  Óvári <ovari123@zoho.com>\nit_IT  Marco Caliari <marco.caliari@univr.it>\n       Massimiliano Fasi <massimiliano.fasi@studio.unibo.it>\nja_JP  Tatsuro Matsuoka <tmacchant@yahoo.co.jp>\nlt_LT\nnl_NL  Philip Nienhuis <prnienhuis@users.sf.net>\npt_BR  Leonardo S. Borges <lsbplsb@yahoo.com>\n       Felipe G. Nievinski <fgnievinski@gmail.com>\npt_PT  Carnë Draug <carandraug@octave.org>\nru_RU  Andriy Shinkarchuck <adriano32.gnu@gmail.com>\n       Dmitry Astankov <mornie@basealt.ru>\n       Alevtina Karashokova <alevkarash@altlinux.org>\nsv_SE  Karl Jonatan Nyberg <jonatan.k.nyberg@gmail.com>\ntr_TR  Serkan Önder <serkanonder@outlook.com>\nuk_UA  Andriy Shinkarchuck <adriano32.gnu@gmail.com>\nzh_CN  Jeff Bai <aosc@members.fsf.org>\n       Jun Wang <jstzwj@aliyun.com>\n"
  },
  {
    "path": "libgui/languages/uk_UA.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"uk_UA\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation type=\"unfinished\">В&amp;ернути</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\">П&amp;овторити</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\">Виріза&amp;ти</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation type=\"unfinished\">&amp;Копіювати</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Документація</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Файл</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation type=\"unfinished\">&amp;Зберегти</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation type=\"unfinished\">Зберегти &amp;як...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Правка</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation type=\"unfinished\">П&amp;овторити</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation type=\"unfinished\">Виріза&amp;ти</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation type=\"unfinished\">До &amp;наступної закладки</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation type=\"unfinished\">До &amp;попередньої закладки</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation type=\"unfinished\">В&amp;становити/видалити закладку</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation type=\"unfinished\">&amp;Виконання</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Редактор</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation type=\"unfinished\">Чергувати колір рядків</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Файловий менеджер</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation type=\"unfinished\">Перегляд і пошук серед історії виконаних команд.</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Історія виконаних команд</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">Завантажити область змінних</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Про Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation type=\"unfinished\">&amp;Файл</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation type=\"unfinished\">Вийти</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation type=\"unfinished\">&amp;Правка</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Історія виконаних команд</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Файловий менеджер</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Область змінних</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Редактор</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Документація</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Повідомити про помилку</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Редактор</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation type=\"unfinished\">Ідентифікатор</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Значення</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation type=\"unfinished\">Значення</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Область змінних</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation type=\"unfinished\">Перегляд змісту поточної області змінних.</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2404\"/>\n        <source>Octave logo only</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-334\"/>\n        <source>Dock widget title bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+72\"/>\n        <source>Small</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+565\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Редактор</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-516\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+494\"/>\n        <source>Show tool bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+221\"/>\n        <source>Rotated tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+260\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Indentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-866\"/>\n        <source>Interface</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+421\"/>\n        <source>Confirm before exiting</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-72\"/>\n        <source>Graphic icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Background inactive</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+225\"/>\n        <source>Octave Startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1305\"/>\n        <source>Show whitespace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1125\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-500\"/>\n        <source>Cursor type:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Use foreground color</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-245\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Файловий менеджер</translation>\n    </message>\n    <message>\n        <location line=\"-2031\"/>\n        <source>Normal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+359\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+540\"/>\n        <source>Show EOL characters</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-1812\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+191\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>File handling</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-23\"/>\n        <source>Force newline at end when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+108\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+62\"/>\n        <source>Behavior</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore last directory of previous session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+68\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+39\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Область змінних</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+232\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-227\"/>\n        <source>Actual</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-392\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+302\"/>\n        <source>Shortcuts</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+54\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Proxy type:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation type=\"unfinished\">Пароль:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation type=\"unfinished\">Завантажити область змінних</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation type=\"unfinished\">Історія виконаних команд</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation type=\"unfinished\">Файловий менеджер</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation type=\"unfinished\">Область змінних</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation type=\"unfinished\">Редактор</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation type=\"unfinished\">Документація</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation type=\"unfinished\">Повідомити про помилку</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation type=\"unfinished\">Про Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/languages/zh_CN.ts",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"zh_CN\">\n<context>\n    <name>QFileSystemModel</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+149\"/>\n        <source>Invalid filename</source>\n        <translation>无效的文件名</translation>\n    </message>\n</context>\n<context>\n    <name>QObject</name>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"+1049\"/>\n        <source>Difference to the default size</source>\n        <translation>和默认大小的差值</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background color, magenta (255, 0, 255) means default</source>\n        <translation>背景颜色，粉红色 (255,0,255) 代表默认值</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>b</source>\n        <comment>short form for bold</comment>\n        <translation>b</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>i</source>\n        <comment>short form for italic</comment>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>u</source>\n        <comment>short form for underlined</comment>\n        <translation>u</translation>\n    </message>\n</context>\n<context>\n    <name>QTerminal</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/QTerminal.cc\" line=\"+119\"/>\n        <source>Edit &quot;%1&quot;</source>\n        <translation>编辑 &quot;%1&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Help on &quot;%1&quot;</source>\n        <translation>关于&quot;%1&quot;的帮助</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation on &quot;%1&quot;</source>\n        <translation>关于&quot;%1&quot;的文档</translation>\n    </message>\n    <message>\n        <location line=\"+165\"/>\n        <source>Copy</source>\n        <translation>复制</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>粘贴</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Select All</source>\n        <translation>全选</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run Selection</source>\n        <translation>运行所选</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Edit selection</source>\n        <translation>编辑所选</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on selection</source>\n        <translation>查看所选帮助</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Documentation on selection</source>\n        <translation>查看所选文档</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Clear Window</source>\n        <translation>清空窗口</translation>\n    </message>\n    <message>\n        <location line=\"-233\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>在 %2 行编辑 %1</translation>\n    </message>\n</context>\n<context>\n    <name>QWinTerminalImpl</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/win32/QWinTerminalImpl.cpp\" line=\"+1924\"/>\n        <source>copied selection to clipboard</source>\n        <translation>复制选定区域到剪贴板</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBash</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbash.cpp\" line=\"+203\"/>\n        <source>Default</source>\n        <translation>默认</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>错误</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>数字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>关键字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>双引号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>单引号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>操作符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>标识符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>标量</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Parameter expansion</source>\n        <translation>参数展开</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>反引号</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>here document分隔符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>单引号的here document</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerBatch</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerbatch.cpp\" line=\"+174\"/>\n        <source>Default</source>\n        <translation>默认</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>关键字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Label</source>\n        <translation>标签</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide command character</source>\n        <translation>隐藏命令字符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>External command</source>\n        <translation>外部命令</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable</source>\n        <translation>变量</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>操作符</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerCPP</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexercpp.cpp\" line=\"+364\"/>\n        <source>Default</source>\n        <translation>默认</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive default</source>\n        <translation>非活动默认</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C comment</source>\n        <translation>C 注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C comment</source>\n        <translation>非活动的 C 注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ comment</source>\n        <translation>C++ 注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ comment</source>\n        <translation>非活动的 C++ 注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C comment</source>\n        <translation>JavaDoc 风格的 C 注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C comment</source>\n        <translation>非活动的 JavaDoc 风格的 C 注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>数字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive number</source>\n        <translation>非活动的数字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>关键字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive keyword</source>\n        <translation>非活动的关键字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>双引号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive double-quoted string</source>\n        <translation>非活动的双引号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>单引号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive single-quoted string</source>\n        <translation>非活动的单引号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>IDL UUID</source>\n        <translation>IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive IDL UUID</source>\n        <translation>非活动的 IDL UUID</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor block</source>\n        <translation>预处理块</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor block</source>\n        <translation>非活动的预处理块</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>操作符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive operator</source>\n        <translation>非活动的操作符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>标识符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive identifier</source>\n        <translation>非活动的标识符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Unclosed string</source>\n        <translation>未闭合的字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive unclosed string</source>\n        <translation>非活动的未闭合字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C# verbatim string</source>\n        <translation>C# verbatim 字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C# verbatim string</source>\n        <translation>非活动的 C# verbatim 字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaScript regular expression</source>\n        <translation>JavaScript 正则表达式</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaScript regular expression</source>\n        <translation>非活动的 JavaScript 正则表达式</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style C++ comment</source>\n        <translation>JavaDoc 风格 C++ 注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style C++ comment</source>\n        <translation>非活动的 JavaDoc 风格 C++ 注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Secondary keywords and identifiers</source>\n        <translation>次要关键字和标识符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive secondary keywords and identifiers</source>\n        <translation>非活动的次要关键字和标识符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword</source>\n        <translation>JavaDoc 关键字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword</source>\n        <translation>非活动的 JavaDoc 关键字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc keyword error</source>\n        <translation>JavaDoc 关键字错误</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc keyword error</source>\n        <translation>非活动的 JavaDoc 关键字错误</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Global classes and typedefs</source>\n        <translation>全局的 class 和 typedef</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive global classes and typedefs</source>\n        <translation>非活动的全局 class 和 typedef</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>C++ raw string</source>\n        <translation>C++ raw string</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive C++ raw string</source>\n        <translation>非活动的 C++ raw string</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Vala triple-quoted verbatim string</source>\n        <translation>Vala 三引号 verbatim 字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Vala triple-quoted verbatim string</source>\n        <translation>非活动的 Vala 三引号 verbatim 字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pike hash-quoted string</source>\n        <translation>Pike 井号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive Pike hash-quoted string</source>\n        <translation>非活动的 Pike 井号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Pre-processor C comment</source>\n        <translation>预处理器 C 语言注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive pre-processor C comment</source>\n        <translation>非活动的预处理器 C 语言注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>JavaDoc style pre-processor comment</source>\n        <translation>JavaDoc 风格的预处理器注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive JavaDoc style pre-processor comment</source>\n        <translation>非活动的 JavaDoc 风格的预处理器注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>User-defined literal</source>\n        <translation>用户定义的字面量</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive user-defined literal</source>\n        <translation>非活动的用户定义字面量</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Task marker</source>\n        <translation>任务标记</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive task marker</source>\n        <translation>非活动的任务标记</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Escape sequence</source>\n        <translation>转义序列</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Inactive escape sequence</source>\n        <translation>非活动的转义序列</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerDiff</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerdiff.cpp\" line=\"+106\"/>\n        <source>Default</source>\n        <translation>默认</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>命令</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Header</source>\n        <translation>标头</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Position</source>\n        <translation>位置</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed line</source>\n        <translation>移除的行</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added line</source>\n        <translation>添加的行</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Changed line</source>\n        <translation>改变的行</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added adding patch</source>\n        <translation>已添加的新增补丁</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed adding patch</source>\n        <translation>已移除的新增补丁</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Added removing patch</source>\n        <translation>已添加的删除补丁</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Removed removing patch</source>\n        <translation>已移除的删除补丁</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerMatlab</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexermatlab.cpp\" line=\"+133\"/>\n        <source>Default</source>\n        <translation>默认</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command</source>\n        <translation>命令</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>数字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>关键字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>单引号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>操作符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>标识符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>双引号字符串</translation>\n    </message>\n</context>\n<context>\n    <name>QsciLexerPerl</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qscilexerperl.cpp\" line=\"+328\"/>\n        <source>Default</source>\n        <translation>默认</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Error</source>\n        <translation>错误</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Comment</source>\n        <translation>注释</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD</source>\n        <translation>POD</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Number</source>\n        <translation>数字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Keyword</source>\n        <translation>关键字</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string</source>\n        <translation>双引号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted string</source>\n        <translation>单引号字符串</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Operator</source>\n        <translation>操作符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Identifier</source>\n        <translation>标识符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Scalar</source>\n        <translation>标量</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Array</source>\n        <translation>数组</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hash</source>\n        <translation>哈希</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Symbol table</source>\n        <translation>符号表</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression</source>\n        <translation>正则表达式</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution</source>\n        <translation>替换</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks</source>\n        <translation>反引号</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Data section</source>\n        <translation>数据段</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Here document delimiter</source>\n        <translation>此处文档分隔符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Single-quoted here document</source>\n        <translation>单引号here document</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document</source>\n        <translation>双引号here document</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document</source>\n        <translation>反引号here document</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (q)</source>\n        <translation>引用的字符串 (q)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq)</source>\n        <translation>引用的字符串 (qq)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx)</source>\n        <translation>引用的字符串 (qx)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr)</source>\n        <translation>引用的字符串 (qr)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qw)</source>\n        <translation>引用的字符串 (qw)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>POD verbatim</source>\n        <translation>POD verbatim</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Subroutine prototype</source>\n        <translation>子程序原型</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format identifier</source>\n        <translation>格式标识符</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Format body</source>\n        <translation>格式正文</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted string (interpolated variable)</source>\n        <translation>双引号字符串 (插值的变量)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Translation</source>\n        <translation>翻译</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Regular expression (interpolated variable)</source>\n        <translation>正则表达式 (插值的变量)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Substitution (interpolated variable)</source>\n        <translation>替换 (插值的变量)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backticks (interpolated variable)</source>\n        <translation>反引号 (插值的变量)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Double-quoted here document (interpolated variable)</source>\n        <translation>此处双引号文档 (插值的变量)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Backtick here document (interpolated variable)</source>\n        <translation>此处反引号文档 (插值的变量)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qq, interpolated variable)</source>\n        <translation>引用的字符串 (qq, 插值的变量)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qx, interpolated variable)</source>\n        <translation>引用的字符串 (qx, 插值的变量)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Quoted string (qr, interpolated variable)</source>\n        <translation>引用的字符串 (qr, 插值的变量)</translation>\n    </message>\n</context>\n<context>\n    <name>QsciScintilla</name>\n    <message>\n        <location filename=\"build_ts/octave-qsci/qsciscintilla.cpp\" line=\"+4478\"/>\n        <source>&amp;Undo</source>\n        <translation>撤销 (&amp;U)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>重做 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Cu&amp;t</source>\n        <translation>剪切 (&amp;T)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Copy</source>\n        <translation>复制 (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Paste</source>\n        <translation>粘贴 (&amp;P)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>删除</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Select All</source>\n        <translation>全选</translation>\n    </message>\n</context>\n<context>\n    <name>UrlFilter</name>\n    <message>\n        <location filename=\"../qterminal/libqterminal/unix/Filter.cpp\" line=\"+630\"/>\n        <source>Open Link</source>\n        <translation>打开链接</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Link Address</source>\n        <translation>复制链接地址</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Send Email To...</source>\n        <translation>发送电子邮件给...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Email Address</source>\n        <translation>复制电子邮箱地址</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+12\"/>\n        <source>Edit %1 at line %2</source>\n        <translation>在 %2 行编辑 %1</translation>\n    </message>\n</context>\n<context>\n    <name>annotation_dialog</name>\n    <message>\n        <location filename=\"../graphics/annotation-dialog.ui\" line=\"+17\"/>\n        <source>Annotation</source>\n        <translation>注释</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text</source>\n        <translation>文本</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>String</source>\n        <translation>字符串</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Font</source>\n        <translation>字体</translation>\n    </message>\n    <message>\n        <location line=\"+42\"/>\n        <source>bold</source>\n        <translation>粗体</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>b</source>\n        <translation>b</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>italic</source>\n        <translation>斜体</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>i</source>\n        <translation>i</translation>\n    </message>\n    <message>\n        <location line=\"+428\"/>\n        <source>color</source>\n        <translation>颜色</translation>\n    </message>\n    <message>\n        <location line=\"+33\"/>\n        <source>left</source>\n        <translation>左</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <location line=\"+29\"/>\n        <source>middle</source>\n        <translation>中</translation>\n    </message>\n    <message>\n        <location line=\"-24\"/>\n        <source>right</source>\n        <translation>右</translation>\n    </message>\n    <message>\n        <location line=\"-21\"/>\n        <source>Horizontal alignment</source>\n        <translation>水平对齐</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Vertical alignment</source>\n        <translation>垂直对齐</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>top</source>\n        <translation>上</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>bottom</source>\n        <translation>下</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Position</source>\n        <translation>位置</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>X</source>\n        <translation>X</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Y</source>\n        <translation>Y</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Width</source>\n        <translation>宽</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Height</source>\n        <translation>高</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>units</source>\n        <translation>单位</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>normalized</source>\n        <translation>归一化</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Fit to box</source>\n        <translation>适应方框大小</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Box</source>\n        <translation>方框</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Background</source>\n        <translation>背景</translation>\n    </message>\n    <message>\n        <location line=\"+444\"/>\n        <source>Edge</source>\n        <translation>边</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Line style</source>\n        <translation>线条样式</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>none</source>\n        <translation>无</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Line width</source>\n        <translation>线条宽度</translation>\n    </message>\n</context>\n<context>\n    <name>octave::ListDialog</name>\n    <message>\n        <location filename=\"../src/dialog.cc\" line=\"+458\"/>\n        <source>Select All</source>\n        <translation>全选</translation>\n    </message>\n</context>\n<context>\n    <name>octave::command_widget</name>\n    <message>\n        <location filename=\"../src/command-widget.cc\" line=\"+76\"/>\n        <source>Pause</source>\n        <translation>暂停</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop</source>\n        <translation>停止</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>继续</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Command Widget</source>\n        <translation>命令组件</translation>\n    </message>\n</context>\n<context>\n    <name>octave::community_news</name>\n    <message>\n        <location filename=\"../src/community-news.cc\" line=\"+71\"/>\n        <source>Octave Community News</source>\n        <translation>Octave 社区新闻</translation>\n    </message>\n</context>\n<context>\n    <name>octave::console_lexer</name>\n    <message>\n        <location filename=\"../src/console-lexer.cc\" line=\"+48\"/>\n        <source>Default</source>\n        <translation>默认</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Error</source>\n        <translation>错误</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Prompt</source>\n        <translation>提示</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation</name>\n    <message>\n        <location filename=\"../src/documentation.cc\" line=\"+135\"/>\n        <location line=\"+14\"/>\n        <location line=\"+721\"/>\n        <source>Octave Documentation</source>\n        <translation>Octave文档</translation>\n    </message>\n    <message>\n        <location line=\"-734\"/>\n        <source>Could not copy help collection to temporary\nfile. Search capabilities may be affected.\n%1</source>\n        <translation>无法将帮助内容写入临时文件。\n搜索能力可能会受到影响。\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Could not setup the data required for the\ndocumentation viewer. Maybe the Qt SQlite\nmodule is missing?\nOnly help text in the Command Window will\nbe available.</source>\n        <translation>无法设置文档查看器所需的数据。\n可能是缺少 Qt SQlite模块？\n只有命令窗口中的帮助文本可用。</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>Contents</source>\n        <translation>内容</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search function index</source>\n        <translation>输入文本搜索函数目录</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <location line=\"+51\"/>\n        <source>Search</source>\n        <translation>搜索</translation>\n    </message>\n    <message>\n        <location line=\"-35\"/>\n        <source>Function Index</source>\n        <translation>函数目录</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Bookmarks</source>\n        <translation>书签</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Go home</source>\n        <translation>回主界面</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go back</source>\n        <translation>返回</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Previous pages</source>\n        <translation>之前页面</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Go forward</source>\n        <translation>前进</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Next pages</source>\n        <translation>之后页面</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Find</source>\n        <translation>查找</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Zoom In</source>\n        <translation>放大</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Out</source>\n        <translation>缩小</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom Original</source>\n        <translation>恢复原比例</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Bookmark current page</source>\n        <translation>为此页面添加书签</translation>\n    </message>\n    <message>\n        <location line=\"+430\"/>\n        <source>Unable to register help file %1.</source>\n        <translation>无法注册帮助文件 %1.</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_bookmarks</name>\n    <message>\n        <location filename=\"../src/documentation-bookmarks.cc\" line=\"+102\"/>\n        <source>\nNo documentation bookmarks loaded!</source>\n        <translation>\n没有文档书签被加载!</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave: Loading Documentation Bookmarks</source>\n        <translation>Octave: 载入文档书签中</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Enter text to search the bookmarks</source>\n        <translation>输入文本搜索书签</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Filter</source>\n        <translation>过滤器</translation>\n    </message>\n    <message>\n        <location line=\"+86\"/>\n        <source>New Folder</source>\n        <translation>新建文件夹</translation>\n    </message>\n    <message>\n        <location line=\"+104\"/>\n        <source>&amp;Open</source>\n        <translation>打开 (&amp;O)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Rename</source>\n        <translation>重命名 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remo&amp;ve</source>\n        <translation>删除 (&amp;V)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Add Folder</source>\n        <translation>添加文件夹 (&amp;A)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Hide &amp;Filter</source>\n        <translation>隐藏过滤器 (&amp;F)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Filter</source>\n        <translation>显示过滤器 (&amp;F)</translation>\n    </message>\n    <message>\n        <location line=\"+66\"/>\n        <source>Octave: Saving Documentation Bookmarks</source>\n        <translation>Octave: 保存文档书签</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Unable to write file %1:\n%2.\n\nDocumentation bookmarks are not saved!\n</source>\n        <translation>无法写入文件 %1:\n%2.\n\n文档书签未保存!\n</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Unable to read file %1:\n%2.</source>\n        <translation>无法读取文件 %1:\n%2.</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>No start element found in %1.\nInvalid bookmark file?</source>\n        <translation>文件 %1 中找不到起始元素。\n是否是无效的标签文件?</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>The file\n%1\nis not a valid XBEL file version 1.0.</source>\n        <translation>文件\n%1\n不是合法的XBEL 1.0版本文件。</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Unknown title</source>\n        <translation>未知标题</translation>\n    </message>\n</context>\n<context>\n    <name>octave::documentation_dock_widget</name>\n    <message>\n        <location filename=\"../src/documentation-dock-widget.cc\" line=\"+40\"/>\n        <source>Documentation</source>\n        <translation>文档</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>See the documentation for help.</source>\n        <translation>阅读文档以获取帮助。</translation>\n    </message>\n</context>\n<context>\n    <name>octave::dw_main_window</name>\n    <message>\n        <location filename=\"../src/dw-main-window.cc\" line=\"+53\"/>\n        <source>&amp;Close</source>\n        <translation>关闭 (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;All</source>\n        <translation>关闭全部 (&amp;A)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close &amp;Other</source>\n        <translation>关闭其他 (&amp;O)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Switch to &amp;Left Widget</source>\n        <translation>切换到左侧组件 (&amp;L)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to &amp;Right Widget</source>\n        <translation>切换到右侧组件 (&amp;R)</translation>\n    </message>\n</context>\n<context>\n    <name>octave::editor_files_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"+1220\"/>\n        <source>Open Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Click to focus file in editor</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>&amp;Close</source>\n        <translation type=\"unfinished\">关闭 (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Close &amp;All</source>\n        <translation type=\"unfinished\">关闭全部 (&amp;A)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">运行</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Set Current &amp;Directory</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::external_editor_interface</name>\n    <message>\n        <location filename=\"../src/external-editor-interface.cc\" line=\"+68\"/>\n        <location line=\"+50\"/>\n        <source>Octave Editor</source>\n        <translation>Octave 编辑器</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Could not start custom file editor\n%1</source>\n        <translation>无法启动自定义文件编辑器\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>There is no custom editor configured yet.\nDo you want to open the preferences?</source>\n        <translation>自定义文本编辑器尚未配置。是否打开首选项？</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor.cc\" line=\"+203\"/>\n        <source>Continue</source>\n        <translation>继续</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Save File and Run</source>\n        <translation>保存文件并运行</translation>\n    </message>\n    <message>\n        <location line=\"+1018\"/>\n        <location line=\"+29\"/>\n        <location line=\"+566\"/>\n        <location line=\"+18\"/>\n        <location line=\"+25\"/>\n        <source>Octave Editor</source>\n        <translation>Octave 编辑器</translation>\n    </message>\n    <message>\n        <location line=\"-637\"/>\n        <source>File not saved! A file with the selected name\n%1\nis already open in the editor.</source>\n        <translation>文件未保存！所选名称为\n%1\n的文件已在编辑器中打开。</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>The associated file editor tab has disappeared.</source>\n        <translation>关联文件的编辑标签消失了。</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Could not open file\n%1\nfor reading: %2.</source>\n        <translation>无法打开文件\n%1\n以读取： %2。</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>文件\n%1\n不存在。您想创建它吗？</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Create</source>\n        <translation>创建</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>取消</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Could not open file\n%1\nfor writing: %2.</source>\n        <translation>无法打开文件\n%1\n以写入： %2。</translation>\n    </message>\n    <message>\n        <location line=\"+271\"/>\n        <source>&amp;File</source>\n        <translation>文件 (&amp;F)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Recent Editor Files</source>\n        <translation>最近编辑器文件 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Edit Function</source>\n        <translation>编辑函数 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Save File</source>\n        <translation>保存文件 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save File &amp;As...</source>\n        <translation>文件另存为 (&amp;A)...</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Close</source>\n        <translation>关闭 (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close All</source>\n        <translation>关闭全部</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Close Other Files</source>\n        <translation>关闭其他文件</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print...</source>\n        <translation>打印...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Edit</source>\n        <translation>编辑 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Redo</source>\n        <translation>重做 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cu&amp;t</source>\n        <translation>剪切 (&amp;T)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Find and Replace...</source>\n        <translation>查找并替换 (&amp;F) ...</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp;Next</source>\n        <translation>查找下一处 (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Find &amp;Previous</source>\n        <translation>查找上一处 (&amp;P)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Commands</source>\n        <translation>命令 (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Delete Line</source>\n        <translation>删除行</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy Line</source>\n        <translation>复制行</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Cut Line</source>\n        <translation>剪切行</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Delete to Start of Word</source>\n        <translation>删除到单词开始</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Word</source>\n        <translation>删除到单词结尾</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to Start of Line</source>\n        <translation>删除到行的开始</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete to End of Line</source>\n        <translation>删除到行的结尾</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>重复所选文本/行</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Transpose Line</source>\n        <translation>交换行</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Show Completion List</source>\n        <translation>显示补全列表(&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Format</source>\n        <translation>格式化(&amp;F)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Uppercase Selection</source>\n        <translation>所选文本转大写 (&amp;U)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Lowercase Selection</source>\n        <translation>所选文本转小写 (&amp;L)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Comment</source>\n        <translation>注释 (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Uncomment</source>\n        <translation>取消注释 (&amp;U)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Comment (Choosing String)</source>\n        <translation>注释(正在选择字符串)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Indent Selection Rigidly</source>\n        <translation>向右严格缩进所选文本 (&amp;I)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Unindent Selection Rigidly</source>\n        <translation>向左严格缩进所选文本 (&amp;U)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Indent Code</source>\n        <translation>缩进代码</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Convert Line Endings to &amp;Windows (CRLF)</source>\n        <translation>将行尾转为 &amp;Windows 风格 (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Convert Line Endings to &amp;Unix (LF)</source>\n        <translation>将行尾转为 &amp;Unix 风格 (LF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Convert Line Endings to Legacy &amp;Mac (CR)</source>\n        <translation>将行尾转为 Legacy &amp;Mac 风格 (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Navi&amp;gation</source>\n        <translation>转到 (&amp;g)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Go &amp;to Line...</source>\n        <translation>跳至行 (&amp;T) ...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Move to Matching Brace</source>\n        <translation>移至匹配的括号</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Select to Matching Brace</source>\n        <translation>选择匹配的括号间的文本</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Next Bookmark</source>\n        <translation>下一个书签 (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Pre&amp;vious Bookmark</source>\n        <translation>上一个书签 (&amp;V)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Bookmark</source>\n        <translation>切换书签 (&amp;B)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Remove All Bookmarks</source>\n        <translation>移除所有书签 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Preferences...</source>\n        <translation>首选项 (&amp;P) ...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Styles Preferences...</source>\n        <translation>样式首选项 (&amp;S) ...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;View</source>\n        <translation>视图 (&amp;V)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Editor</source>\n        <translation>编辑器 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show &amp;Line Numbers</source>\n        <translation>显示行数 (&amp;L)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Whitespace Characters</source>\n        <translation>显示空白字符 (&amp;W)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Line &amp;Endings</source>\n        <translation>显示行尾 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Indentation Guides</source>\n        <translation>显示缩进对齐线 (&amp;I)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show Long Line &amp;Marker</source>\n        <translation>显示长文本行标记 (&amp;M)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show &amp;Toolbar</source>\n        <translation>显示工具栏 (&amp;T)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Statusbar</source>\n        <translation>显示状态栏 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Show &amp;Horizontal Scrollbar</source>\n        <translation>显示垂直滚动条 (&amp;H)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Zoom &amp;In</source>\n        <translation>放大 (&amp;I)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Zoom &amp;Out</source>\n        <translation>缩小 (&amp;O)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Normal Size</source>\n        <translation>正常大小 (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Sort Tabs Alphabetically</source>\n        <translation>以字母顺序排序标签页 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>&amp;Debug</source>\n        <translation>调试 (&amp;D)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Toggle &amp;Breakpoint</source>\n        <translation>开关断点 (&amp;B)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Next Breakpoint</source>\n        <translation>下一个断点 (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Pre&amp;vious Breakpoint</source>\n        <translation>上一个断点 (&amp;V)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Remove All Breakpoints</source>\n        <translation>移除所有断点 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Run</source>\n        <translation>运行 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run/Continue</source>\n        <translation>保存文件并运行/继续</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Run &amp;Selection</source>\n        <translation>运行选定部分 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Save File and Run All &amp;Tests</source>\n        <translation>保存文件并运行全部测试 (&amp;T)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save File and Run All &amp;Demos</source>\n        <translation>保存文件并运行全部演示 (&amp;D)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Help</source>\n        <translation>帮助 (&amp;H)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Help on Keyword</source>\n        <translation>关键字的帮助 (&amp;H)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&amp;Documentation on Keyword</source>\n        <translation>关键字的文档 (&amp;D)</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Recent Files</source>\n        <translation>最近文件</translation>\n    </message>\n    <message>\n        <location line=\"+49\"/>\n        <source>Copy Full File &amp;Path</source>\n        <translation>复制完整的文件路径 (&amp;P)</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Editor</source>\n        <translation>编辑器</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_editor_tab</name>\n    <message>\n        <location filename=\"../src/m-editor/file-editor-tab.cc\" line=\"+162\"/>\n        <source>line:</source>\n        <translation>行数:</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>col:</source>\n        <translation>列数:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>encoding:</source>\n        <translation>编码:</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>eol:</source>\n        <translation>行尾:</translation>\n    </message>\n    <message>\n        <location line=\"+259\"/>\n        <source>Breakpoint condition</source>\n        <translation>条件断点</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>ERROR: </source>\n        <translation>错误： </translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <location line=\"+1260\"/>\n        <location line=\"+152\"/>\n        <location line=\"+20\"/>\n        <location line=\"+444\"/>\n        <location line=\"+110\"/>\n        <location line=\"+103\"/>\n        <location line=\"+38\"/>\n        <location line=\"+60\"/>\n        <location line=\"+59\"/>\n        <location line=\"+36\"/>\n        <source>Octave Editor</source>\n        <translation>Octave 编辑器</translation>\n    </message>\n    <message>\n        <location line=\"-2281\"/>\n        <source>Cannot add breakpoint to modified or unnamed file.\nSave and add breakpoint, or cancel?</source>\n        <translation>无法将断点添加到已修改或未命名的文件。\n保存并添加断点，还是取消？</translation>\n    </message>\n    <message>\n        <location line=\"+924\"/>\n        <source>Goto line</source>\n        <translation>前往行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Line number</source>\n        <translation>行数</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Comment selected text</source>\n        <translation>注释所选文本</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment string to use:\n</source>\n        <translation>注释字符串以使用:\n</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+57\"/>\n        <source>&lt;unnamed&gt;</source>\n        <translation>&lt;未命名&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-6\"/>\n        <source>Do you want to cancel closing, save, or discard the changes?</source>\n        <translation>您想取消关闭、保存还是放弃更改？</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>The file\n\n  %1\n\nis about to be closed but has been modified.  %2</source>\n        <translation>文件\n\n  %1\n\n发生改动且将被关闭.  %2</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Unable to read file &apos;%1&apos;\nwith selected encoding &apos;%2&apos;: %3</source>\n        <translation>无法读取文件 &apos;%1&apos;\n所选编码为&apos;%2&apos;：%3</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>There were problems reading the file\n%1\nwith the selected encoding %2.\n\nModifying and saving the file might cause data loss!</source>\n        <translation>读取文件时出现问题\n%1\n使用所选的编码 %2。\n\n修改和保存文件可能会导致数据丢失！</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>&amp;Edit anyway</source>\n        <translation>强制编辑 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+45\"/>\n        <source>Chan&amp;ge encoding</source>\n        <translation>切换编码 (&amp;G)</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <location line=\"+36\"/>\n        <source>&amp;Close</source>\n        <translation>关闭 (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Select new default encoding</source>\n        <translation>选择新的默认编码</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Please select a new encoding\nfor reloading the current file.\n\nThis does not change the default encoding.\n</source>\n        <translation>请选择新的编码\n用于重新加载当前文件。\n\n这不会更改默认编码。\n</translation>\n    </message>\n    <message>\n        <location line=\"+179\"/>\n        <source>Debug or Save</source>\n        <translation>调试或保存</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>This file is currently being executed.\nQuit debugging and save?</source>\n        <translation>此文件正在运行。\n是否退出调试并保存?</translation>\n    </message>\n    <message>\n        <location line=\"+211\"/>\n        <source>Could not open file %1 for writing:\n%2.</source>\n        <translation>无法打开文件 %1 以进行写入：\n%2。</translation>\n    </message>\n    <message>\n        <location line=\"+110\"/>\n        <source>The changes could not be saved to the file\n%1</source>\n        <translation>改动无法保存到文件\n%1</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Octave Files (*.m)</source>\n        <translation>Octave 文件 (*.m)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>All Files (*)</source>\n        <translation>所有文件 (*)</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>&quot;%1&quot;\nis not a valid identifier.\n\nIf you keep this filename, you will not be able to\ncall your script using its name as an Octave command.\n\nDo you want to choose another name?</source>\n        <translation>&quot;%1&quot;\n不是有效的标识符。\n\n如果使用此文件名，您将无法将这个名字当作 Octave 命令来调用。\n\n是否选择其他文件名?</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>The current editor contents can not be encoded\nwith the selected encoding %1.\nUsing it would result in data loss!\n\nPlease select another one!</source>\n        <translation>当前编辑器内容无法\n使用所选编码 %1。\n使用它会导致数据丢失！\n\n请选择其他编码！</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>%1\n already exists\nDo you want to overwrite it?</source>\n        <translation>%1\n 已经存在\n您确定要覆盖它吗?</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <location line=\"+34\"/>\n        <source>\n\nWarning: The contents in the editor is modified!</source>\n        <translation>\n\n警告: 编辑器中内容已经被修改！</translation>\n    </message>\n    <message>\n        <location line=\"-29\"/>\n        <source>It seems that &apos;%1&apos; has been modified by another application. Do you want to reload it?%2</source>\n        <translation type=\"unfinished\">看起来 &apos;%1&apos; 已经被其他应用修改。您希望重新载入这个文件吗？%2</translation>\n    </message>\n    <message>\n        <location line=\"+36\"/>\n        <source>It seems that the file\n%1\nhas been deleted or renamed. Do you want to save it now?%2</source>\n        <translation>数据文件\n%1\n已经被修改或重命名。您希望现在保存这个文件吗？%2</translation>\n    </message>\n</context>\n<context>\n    <name>octave::file_system_browser</name>\n    <message>\n        <location filename=\"../src/files-dock-widget.cc\" line=\"-1171\"/>\n        <source>File size</source>\n        <translation type=\"unfinished\">文件大小</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File type</source>\n        <translation type=\"unfinished\">文件类型</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Date modified</source>\n        <translation type=\"unfinished\">修改日期</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show hidden</source>\n        <translation type=\"unfinished\">显示隐藏文件</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating row colors</source>\n        <translation type=\"unfinished\">备选列颜色</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Enter the path or filename</source>\n        <translation type=\"unfinished\">输入路径或文件名</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>One directory up</source>\n        <translation type=\"unfinished\">向上一级</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Octave directory</source>\n        <translation type=\"unfinished\">显示 Octave 目录</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go to current Octave directory</source>\n        <translation type=\"unfinished\">前往当前的 Octave 目录</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Set Octave directory</source>\n        <translation type=\"unfinished\">设置 Octave 目录</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Set Octave directory to current browser directory</source>\n        <translation type=\"unfinished\">设置 Octave 目录到当前浏览器目录</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Actions on current directory</source>\n        <translation type=\"unfinished\">在当前目录的操作</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Home Directory</source>\n        <translation type=\"unfinished\">显示主目录</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Set Browser Directory...</source>\n        <translation type=\"unfinished\">设置浏览器目录...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+433\"/>\n        <source>Find Files...</source>\n        <translation type=\"unfinished\">查找文件...</translation>\n    </message>\n    <message>\n        <location line=\"-429\"/>\n        <location line=\"+441\"/>\n        <source>New File...</source>\n        <translation type=\"unfinished\">新建文件...</translation>\n    </message>\n    <message>\n        <location line=\"-438\"/>\n        <location line=\"+440\"/>\n        <source>New Directory...</source>\n        <translation type=\"unfinished\">新建目录...</translation>\n    </message>\n    <message>\n        <location line=\"-385\"/>\n        <source>Double-click to open file/folder, right click for alternatives</source>\n        <translation type=\"unfinished\">双击打开文件/文件夹，右键单击以找到候选项</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Rename...</source>\n        <translation type=\"unfinished\">重命名...</translation>\n    </message>\n    <message>\n        <location line=\"+312\"/>\n        <source>Open</source>\n        <translation type=\"unfinished\">打开</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in System File Explorer</source>\n        <translation type=\"unfinished\">在系统文件浏览器中打开</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Open in Text Editor</source>\n        <translation type=\"unfinished\">在文本编辑器中打开</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy Selection to Clipboard</source>\n        <translation type=\"unfinished\">复制选中到剪贴板</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Run</source>\n        <translation type=\"unfinished\">运行</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Load Data</source>\n        <translation type=\"unfinished\">载入数据</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set Current Directory</source>\n        <translation type=\"unfinished\">设置当前目录</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add to Path</source>\n        <translation type=\"unfinished\">添加到路径</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories</source>\n        <translation type=\"unfinished\">所选目录</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <location line=\"+7\"/>\n        <source>Selected Directories and Subdirectories</source>\n        <translation type=\"unfinished\">所选目录和子目录</translation>\n    </message>\n    <message>\n        <location line=\"-4\"/>\n        <source>Remove from Path</source>\n        <translation type=\"unfinished\">从路径中移除</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Delete...</source>\n        <translation type=\"unfinished\">删除...</translation>\n    </message>\n    <message>\n        <location line=\"+140\"/>\n        <location line=\"+11\"/>\n        <location line=\"+17\"/>\n        <source>Delete file/directory</source>\n        <translation type=\"unfinished\">删除文件/目录</translation>\n    </message>\n    <message>\n        <location line=\"-27\"/>\n        <source>Are you sure you want to delete all %1 selected files?\n</source>\n        <translation type=\"unfinished\">您确定要删除所有 %1 选择的文件吗？\n</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Are you sure you want to delete\n</source>\n        <translation type=\"unfinished\">您确定要删除\n</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Can not delete a directory that is not empty</source>\n        <translation type=\"unfinished\">不能删除一个非空目录</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Deletion error</source>\n        <translation type=\"unfinished\">删除错误</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not delete file &quot;%1&quot;.</source>\n        <translation type=\"unfinished\">无法删除文件 &quot;%1&quot;。</translation>\n    </message>\n    <message>\n        <location line=\"+216\"/>\n        <source>Set directory of file browser</source>\n        <translation type=\"unfinished\">设置目录到文件浏览器</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Create File</source>\n        <translation type=\"unfinished\">创建文件</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create file in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">创建文件于\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New File.txt</source>\n        <translation type=\"unfinished\">新建文件.txt</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Create File error</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Could not create file\n&quot;%1&quot;.</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Create Directory</source>\n        <translation type=\"unfinished\">创建目录</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Create folder in\n</source>\n        <comment>String ends with \n!</comment>\n        <translation type=\"unfinished\">创建文件夹于\n</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>New Directory</source>\n        <translation type=\"unfinished\">新建目录</translation>\n    </message>\n</context>\n<context>\n    <name>octave::files_dock_widget</name>\n    <message>\n        <location line=\"-1148\"/>\n        <source>Could not rename file &quot;%1&quot; to &quot;%2&quot;.</source>\n        <translation>无法将文件 &quot;%1&quot; 重命名为 &quot;%2&quot;。</translation>\n    </message>\n    <message>\n        <location line=\"+107\"/>\n        <source>File Browser</source>\n        <translation>文件浏览器</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse your files</source>\n        <translation>浏览文件</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>File System</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor Files</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n</context>\n<context>\n    <name>octave::final_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+319\"/>\n        <source>Enjoy!</source>\n        <translation>尽情享受吧！</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Previous</source>\n        <translation>上一个</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Finish</source>\n        <translation>完成</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>取消</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;We hope you find Octave to be a useful tool.&lt;/p&gt;\n&lt;p&gt;If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\nYou can find more information about each of these by visiting &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; (opens in external browser).&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;希望 Octave 作为一款工具能对您有所帮助。&lt;/p&gt;\n&lt;p&gt;如果遇到问题，可以通过多种方式获得帮助，包括商业支持选项、讨论板、维基和其他基于社区的支持渠道。\n您可以访问 &lt;a href=&quot;https://octave.org/support.html&quot;&gt;https://octave.org/support.html&lt;/a&gt; 了解更多相关信息（在外部浏览器中打开）。&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;For more information about Octave:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Visit &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; (opens in external browser)&lt;/li&gt;\n&lt;li&gt;Get the documentation online in &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; or &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; format (links open in external browser)&lt;/li&gt;\n&lt;li&gt;Open the documentation browser of the Octave GUI with the help menu&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;有关 Octave 的更多信息&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;访问 &lt;a href=&quot;https://octave.org&quot;&gt;https://octave.org&lt;/a&gt; （在外部浏览器中打开）&lt;/li&gt;\n&lt;li&gt;获取在线文档 &lt;a href=&quot;https://www.gnu.org/software/octave/doc/interpreter/index.html&quot;&gt;HTML&lt;/a&gt; 或者 &lt;a href=&quot;https://www.gnu.org/software/octave/octave.pdf&quot;&gt;PDF&lt;/a&gt; 格式 （在外部浏览器中打开链接）&lt;/li&gt;\n&lt;li&gt;在帮助菜单中打开 Octave 图形用户界面的文档浏览器&lt;/li&gt;\n&lt;/ul&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_dialog</name>\n    <message>\n        <location filename=\"../src/m-editor/find-dialog.cc\" line=\"+93\"/>\n        <source>Editor: Find and Replace</source>\n        <translation>编辑器：查找和替换</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Find:</source>\n        <translation>查找 (&amp;F):</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter search text</source>\n        <translation>输入搜索文本</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Re&amp;place:</source>\n        <translation>替换 (&amp;P):</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter replacement text</source>\n        <translation>输入替换文本</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Match &amp;case</source>\n        <translation>匹配大小写 (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search from &amp;start</source>\n        <translation>从开头搜索 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Wrap while searching</source>\n        <translation>搜索时循环 (&amp;W)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Find &amp;Next</source>\n        <translation>查找下一处 (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Pre&amp;vious</source>\n        <translation>查找上一处 (&amp;V)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Replace</source>\n        <translation>替换 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Replace &amp;All</source>\n        <translation>替换全部 (&amp;A)</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;More...</source>\n        <translation>更多 (&amp;M) ...</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>&amp;Whole words</source>\n        <translation>整个单词 (&amp;W)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Regular &amp;expressions</source>\n        <translation>正则表达式 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search &amp;backward</source>\n        <translation>反向搜索 (&amp;B)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search se&amp;lection</source>\n        <translation>搜索选中 (&amp;L)</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>Search from end</source>\n        <translation>从后向前搜索</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search from start</source>\n        <translation>从前往后搜索</translation>\n    </message>\n    <message>\n        <location line=\"+290\"/>\n        <source>Replace Result</source>\n        <translation>替换结果</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>%1 items replaced</source>\n        <translation>%1 项已替换</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Find Result</source>\n        <translation>查找结果</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>No more matches found</source>\n        <translation>没有更多匹配项</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_dialog</name>\n    <message>\n        <location filename=\"../src/find-files-dialog.cc\" line=\"+61\"/>\n        <source>Find Files</source>\n        <translation>查找文件</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Named:</source>\n        <translation>名称:</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Start in:</source>\n        <translation>从:</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Enter the start directory</source>\n        <translation>进入初始目录</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Browse...</source>\n        <translation>浏览...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Browse for start directory</source>\n        <translation>从初始目录浏览</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Current Dir</source>\n        <translation>当前目录</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set start directory to current directory</source>\n        <translation>设置当前目录为开始目录</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Search subdirectories</source>\n        <translation>搜索子目录</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Search recursively through directories for matching files</source>\n        <translation>递归搜索目录以查找匹配文件</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Include directory names</source>\n        <translation>包含的目录名</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include matching directories in search results</source>\n        <translation>在搜索结果中包含匹配目录</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+18\"/>\n        <source>Ignore case</source>\n        <translation>忽略大小写</translation>\n    </message>\n    <message>\n        <location line=\"-17\"/>\n        <location line=\"+18\"/>\n        <source>Perform case insensitive match</source>\n        <translation>执行大小写不敏感匹配</translation>\n    </message>\n    <message>\n        <location line=\"-15\"/>\n        <source>Contains text:</source>\n        <translation>包含文本:</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Include only files containing specified text in search results</source>\n        <translation>在搜索结果中只显示包含指定文本的文件</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Text to match</source>\n        <translation>要匹配的文字</translation>\n    </message>\n    <message>\n        <location line=\"+95\"/>\n        <source>Results: Double click opens the file or sets the directory</source>\n        <translation>结果: 双击打开文件或设置目录</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Search results</source>\n        <translation>搜索结果</translation>\n    </message>\n    <message>\n        <location line=\"-59\"/>\n        <source>Idle.</source>\n        <translation>空闲。</translation>\n    </message>\n    <message>\n        <location line=\"-94\"/>\n        <source>Enter the filename search patterns.\nSeveral different patterns can be\nseparated by &apos;;&apos;, e.g. &apos;*.cc ; *.h&apos;</source>\n        <translation>输入文件名搜索模式。\n多个不同的模式可以用 &apos;;&apos; 分隔\n例如：&apos;*.cc ; *.h&apos;</translation>\n    </message>\n    <message>\n        <location line=\"+96\"/>\n        <source>Find</source>\n        <translation>查找</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Start search for matching files</source>\n        <translation>开始查找匹配文件</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Stop</source>\n        <translation>停止</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Stop search</source>\n        <translation>停止搜索</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Filename/Location</source>\n        <translation>文件名/位置</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>File contents</source>\n        <translation>文件内容</translation>\n    </message>\n    <message>\n        <location line=\"+143\"/>\n        <source>Searching...</source>\n        <translation>正在搜索...</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>%1 match (es)</source>\n        <translation>%1 个匹配</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Set search directory</source>\n        <translation>设置搜索目录</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_files_model</name>\n    <message>\n        <location filename=\"../src/find-files-model.cc\" line=\"+96\"/>\n        <source>Filename</source>\n        <translation>文件名</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Directory</source>\n        <translation>目录</translation>\n    </message>\n    <message>\n        <location line=\"+87\"/>\n        <source>Double click to open the file</source>\n        <translation>双击打开文件</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Double click to set the directory</source>\n        <translation>双击设置目录</translation>\n    </message>\n</context>\n<context>\n    <name>octave::find_widget</name>\n    <message>\n        <location filename=\"../src/find-widget.cc\" line=\"+48\"/>\n        <source>Find:</source>\n        <translation>查找:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <location line=\"+1\"/>\n        <source>Search forward</source>\n        <translation>下一条搜索结果</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <location line=\"+1\"/>\n        <source>Search backward</source>\n        <translation>上一条搜索结果</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Close</source>\n        <translation>关闭</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close find dialog</source>\n        <translation>关闭搜索对话框</translation>\n    </message>\n</context>\n<context>\n    <name>octave::gui_settings</name>\n    <message>\n        <location filename=\"../src/gui-settings.cc\" line=\"+827\"/>\n        <source>Error %1 creating the settings file\n%2\nMake sure you have read and write permissions to\n%3\n\nOctave GUI must be closed now.</source>\n        <translation>错误 %1 创建设置文件\n%2\n请确保您拥有以下文件的读写权限\n%3\n\n现在必须关闭 Octave GUI。</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Octave Critical Error</source>\n        <translation>Octave 严重错误</translation>\n    </message>\n</context>\n<context>\n    <name>octave::history_dock_widget</name>\n    <message>\n        <location filename=\"../src/history-dock-widget.cc\" line=\"+54\"/>\n        <source>Browse and search the command history.</source>\n        <translation>浏览并搜索命令历史。</translation>\n    </message>\n    <message>\n        <location line=\"+102\"/>\n        <source>Copy</source>\n        <translation>复制</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Evaluate</source>\n        <translation>评估</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Create script</source>\n        <translation>创建脚本</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Hide filter</source>\n        <translation>隐藏过滤器</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>显示过滤器</translation>\n    </message>\n    <message>\n        <location line=\"+131\"/>\n        <source>Double-click a command to transfer it to the Command Window.</source>\n        <translation>双击命令以将其移至命令窗口。</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter text to filter the command history</source>\n        <translation>输入文本以过滤命令历史记录</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Filter</source>\n        <translation>过滤器</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Command History</source>\n        <translation>命令历史</translation>\n    </message>\n</context>\n<context>\n    <name>octave::initial_page</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-190\"/>\n        <source>Welcome to Octave!</source>\n        <translation>欢迎来到 Octave!</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Next</source>\n        <translation>下一个</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>取消</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;You seem to be using the Octave graphical interface for the first time on this computer.\nClick &apos;Next&apos; to create a configuration file and launch Octave.&lt;/p&gt;\n&lt;p&gt;The configuration file is stored in&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;看起来这是你第一次在这台电脑上使用 Octave 图形界面。\n点击 &apos;下一步&apos; 以创建一个配置文件并启动 Octave .&lt;/p&gt;\n&lt;p&gt;配置文件存放于&lt;br&gt;%1.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::label_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+82\"/>\n        <source>Undock Widget</source>\n        <translation>悬浮组件</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Close Widget</source>\n        <translation>关闭组件</translation>\n    </message>\n</context>\n<context>\n    <name>octave::main_window</name>\n    <message>\n        <location filename=\"../src/main-window.cc\" line=\"+169\"/>\n        <source>Profiler</source>\n        <translation>性能探查器</translation>\n    </message>\n    <message>\n        <location line=\"+381\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Are you sure you want to exit Octave?</source>\n        <translation>确定要退出 Octave 吗？</translation>\n    </message>\n    <message>\n        <location line=\"+156\"/>\n        <source>Save Workspace As</source>\n        <translation>工作区另存为</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Load Workspace</source>\n        <translation>导入工作区</translation>\n    </message>\n    <message>\n        <location line=\"+214\"/>\n        <location line=\"+1704\"/>\n        <source>About Octave</source>\n        <translation>关于 Octave</translation>\n    </message>\n    <message>\n        <location line=\"-1570\"/>\n        <location line=\"+1645\"/>\n        <source>Browse directories</source>\n        <translation>浏览目录</translation>\n    </message>\n    <message>\n        <location line=\"-1340\"/>\n        <source>Octave Files (*.m);;All Files (*)</source>\n        <translation>Octave 文件 (*.m);;所有文件 (*)</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>New Function</source>\n        <translation>新建函数</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New function name:\n</source>\n        <translation>新建函数的名称:\n</translation>\n    </message>\n    <message>\n        <location line=\"+63\"/>\n        <source>%1 is a built-in, compiled, or inline\nfunction and can not be edited.</source>\n        <translation>%1 是内置的、编译的或\n内联的函数，因此不能编辑。</translation>\n    </message>\n    <message>\n        <location line=\"+41\"/>\n        <source>Can not find function %1</source>\n        <translation>找不到函数 %1</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Octave Editor</source>\n        <translation>Octave 编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+735\"/>\n        <source>&amp;File</source>\n        <translation>文件 (&amp;F)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Open...</source>\n        <translation>打开...</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Open an existing file in editor</source>\n        <translation>在编辑器中打开一个已存在的文件</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Load Workspace...</source>\n        <translation>导入工作区...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Save Workspace As...</source>\n        <translation>工作区另存为...</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Exit</source>\n        <translation>退出</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>New</source>\n        <translation>新建</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New Script</source>\n        <translation>新建脚本</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Function...</source>\n        <translation>新建函数...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>New Figure</source>\n        <translation>新建图表</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Edit</source>\n        <translation>编辑 (&amp;E)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Undo</source>\n        <translation>撤销</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Copy</source>\n        <translation>复制</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Paste</source>\n        <translation>粘贴</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Select All</source>\n        <translation>全选</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Clipboard</source>\n        <translation>清空剪贴板</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Find Files...</source>\n        <translation>查找文件...</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Clear Command Window</source>\n        <translation>清空命令窗口</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Command History</source>\n        <translation>清空命令历史</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Clear Workspace</source>\n        <translation>清空工作区</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Set Path...</source>\n        <translation>设置路径...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Preferences...</source>\n        <translation>首选项...</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source>De&amp;bug</source>\n        <translation>调试 (&amp;B)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Step</source>\n        <translation>单步跳过</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step In</source>\n        <translation>单步执行</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Step Out</source>\n        <translation>单步停止</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Continue</source>\n        <translation>继续</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Quit Debug Mode</source>\n        <translation>退出调试模式</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&amp;Tools</source>\n        <translation>工具 (&amp;T)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start &amp;Profiler Session</source>\n        <translation>启动性能分析会话 (&amp;P)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Resume Profiler Session</source>\n        <translation>恢复性能分析会话 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>&amp;Stop Profiler</source>\n        <translation>停止性能分析 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>&amp;Show Profiler Data</source>\n        <translation>显示性能分析数据 (&amp;S)</translation>\n    </message>\n    <message>\n        <location line=\"+53\"/>\n        <source>&amp;Window</source>\n        <translation>窗口 (&amp;W)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command Window</source>\n        <translation>显示命令窗口</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Command History</source>\n        <translation>显示命令历史</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show File Browser</source>\n        <translation>显示文件浏览器</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Workspace</source>\n        <translation>显示工作区</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Editor</source>\n        <translation>显示编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Documentation</source>\n        <translation>显示文档</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Variable Editor</source>\n        <translation>显示变量编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Command Window</source>\n        <translation>命令窗口</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Command History</source>\n        <translation>命令历史</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>File Browser</source>\n        <translation>文件浏览器</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Workspace</source>\n        <translation>工作区</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Editor</source>\n        <translation>编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+46\"/>\n        <source>Documentation</source>\n        <translation>文档</translation>\n    </message>\n    <message>\n        <location line=\"-43\"/>\n        <source>Variable Editor</source>\n        <translation>变量编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous Widget</source>\n        <translation>上一个组件</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>重置为默认窗口布局</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;Help</source>\n        <translation>帮助 (&amp;H)</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Report Bug</source>\n        <translation>缺陷报告</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave Packages</source>\n        <translation>Octave 软件包</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Get Involved</source>\n        <translation>参与 Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Donate to Octave</source>\n        <translation>捐赠 Octave</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>On Disk</source>\n        <translation>本地</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Online</source>\n        <translation>在线</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>&amp;News</source>\n        <translation>新闻 (&amp;N)</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>发行注记</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Community News</source>\n        <translation>社区新闻</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Toolbar</source>\n        <translation>工具栏</translation>\n    </message>\n    <message>\n        <location line=\"+21\"/>\n        <source>Enter directory name</source>\n        <translation>输入目录名</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Current Directory: </source>\n        <translation>当前目录: </translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>One directory up</source>\n        <translation>向上一级</translation>\n    </message>\n</context>\n<context>\n    <name>octave::news_reader</name>\n    <message>\n        <location filename=\"../src/news-reader.cc\" line=\"+106\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave&apos;s community news source seems to be unavailable.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser).\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nOctave的社区新闻源似乎无法连接。\n&lt;/p&gt;\n&lt;p&gt;\n当您连接到互联网时，请访问\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\n获取最新新闻(在外部浏览器中打开链接)。\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Octave开发者, </translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\nConnecting to the web to display the latest Octave Community news has been disabled.\n&lt;/p&gt;\n&lt;p&gt;\nFor the latest news, please check\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\nwhen you have a connection to the web (link opens in an external browser)\nor enable web connections for news in Octave&apos;s network settings tab.\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; The Octave Developers, </source>\n        <translation>&lt;html&gt;\n&lt;body&gt;\n&lt;p&gt;\n连接到网络以显示最新 Octave 社区新闻的功能已被禁用。\n&lt;/p&gt;\n&lt;p&gt;\n当您连接到互联网时，请访问\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;\n获取最新新闻(在外部浏览器中打开链接)\n或在 Octave 的网络设置选项卡中启用新闻的网络连接。\n&lt;/p&gt;\n&lt;p&gt;\n&lt;small&gt;&lt;em&gt;&amp;mdash; Octave 开发者, </translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_dock_widget</name>\n    <message>\n        <location filename=\"../src/octave-dock-widget.cc\" line=\"+144\"/>\n        <source>Hide Widget</source>\n        <translation>隐藏组件</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Dock Widget</source>\n        <translation>停靠组件</translation>\n    </message>\n    <message>\n        <location line=\"+58\"/>\n        <source>Undock Widget</source>\n        <translation>悬浮组件</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_qscintilla</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-qscintilla.cc\" line=\"+302\"/>\n        <source>Help on</source>\n        <translation>开启帮助</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Documentation on</source>\n        <translation>开启文档</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Edit</source>\n        <translation>编辑</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>dbstop if ...</source>\n        <translation>dbstop 如果 ...</translation>\n    </message>\n    <message>\n        <location line=\"+545\"/>\n        <source>Octave Editor</source>\n        <translation>Octave 编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Creating temporary files failed.\nMake sure you have write access to temp. directory\n%1\n\n&quot;Run Selection&quot; requires temporary files.</source>\n        <translation>创建临时文件失败。\n确保您具有对temp目录的写权限。目录\n%1\n\n“运行所选”需要写入临时文件。</translation>\n    </message>\n    <message>\n        <location line=\"+313\"/>\n        <source>Press &apos;%1&apos; to replace all occurrences of &apos;%2&apos; with &apos;%3&apos;.</source>\n        <translation>按&apos;%1将所有出现的&apos;%2&apos;替换为&apos;%3&apos;。</translation>\n    </message>\n</context>\n<context>\n    <name>octave::octave_txt_lexer</name>\n    <message>\n        <location filename=\"../src/m-editor/octave-txt-lexer.cc\" line=\"+41\"/>\n        <source>Default</source>\n        <translation>默认</translation>\n    </message>\n</context>\n<context>\n    <name>octave::qt_interpreter_events</name>\n    <message>\n        <location filename=\"../src/qt-interpreter-events.cc\" line=\"+357\"/>\n        <location line=\"+5\"/>\n        <location line=\"+2\"/>\n        <source>Create</source>\n        <translation>创建</translation>\n    </message>\n    <message>\n        <location line=\"-7\"/>\n        <location line=\"+31\"/>\n        <source>Cancel</source>\n        <translation>取消</translation>\n    </message>\n    <message>\n        <location line=\"-28\"/>\n        <source>File\n%1\ndoes not exist. Do you want to create it?</source>\n        <translation>文件\n%1\n不存在。您想创建它吗？</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Octave Editor</source>\n        <translation>Octave 编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.</source>\n        <translation>加载路径中文件 %1 不存在。如要运行或调试正在编辑的函数，请转到目录 %2 或添加其至加载路径。</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.</source>\n        <translation>文件 %1 被加载路径中同名文件隐藏。 如要运行或调试正在编辑的函数，请切换到目录 %2 。</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Change Directory or Add Directory to Load Path</source>\n        <translation>切换目录或添加目录到载入路径</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>&amp;Change Directory</source>\n        <translation>切换目录 (&amp;C)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>&amp;Add Directory to Load Path</source>\n        <translation>添加目录到载入路径 (&amp;A)</translation>\n    </message>\n</context>\n<context>\n    <name>octave::release_notes</name>\n    <message>\n        <location filename=\"../src/release-notes.cc\" line=\"+85\"/>\n        <source>The release notes file &apos;%1&apos; is empty.</source>\n        <translation>发行注记文件 &apos;%1&apos; 是空的。</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>The release notes file &apos;%1&apos; cannot be read.</source>\n        <translation>发行注记文件 &apos;%1&apos; 无法读取。</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Octave Release Notes</source>\n        <translation>Octave 发行注记</translation>\n    </message>\n</context>\n<context>\n    <name>octave::set_path_dialog</name>\n    <message>\n        <location filename=\"../src/set-path-dialog.cc\" line=\"+64\"/>\n        <source>Set Path</source>\n        <translation>设置路径</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>All changes take effect immediately.</source>\n        <translation>所有改动立即生效。</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Add Directory...</source>\n        <translation>添加目录...</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Single Directory</source>\n        <translation>单个目录</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Directory With Subdirectories</source>\n        <translation>目录及其子目录</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Move to Top</source>\n        <translation>置顶</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Bottom</source>\n        <translation>置底</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Up</source>\n        <translation>上移</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Down</source>\n        <translation>下移</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove</source>\n        <translation>移除</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Reload</source>\n        <translation>刷新</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save</source>\n        <translation>保存</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert</source>\n        <translation>撤销</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Revert Last Change</source>\n        <translation>撤销最后改动</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Revert All Changes</source>\n        <translation>撤销所有改动</translation>\n    </message>\n    <message>\n        <location line=\"+92\"/>\n        <source>Open Directory</source>\n        <translation>打开目录</translation>\n    </message>\n</context>\n<context>\n    <name>octave::settings_dialog</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ed.h\" line=\"+161\"/>\n        <source>Top</source>\n        <translation>上</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bottom</source>\n        <translation>下</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Left</source>\n        <translation>左</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Right</source>\n        <translation>右</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-cs.h\" line=\"+61\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+56\"/>\n        <source>Foreground</source>\n        <translation>前景色</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Background</source>\n        <translation>背景色</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selection</source>\n        <translation>选择</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cursor</source>\n        <translation>光标</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ve.h\" line=\"+1\"/>\n        <source>Selected Foreground</source>\n        <translation>所选前景色</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Selected Background</source>\n        <translation>所选背景色</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Alternating Background</source>\n        <translation>备选背景色</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"+70\"/>\n        <source>argument</source>\n        <translation>参数</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>global</source>\n        <translation>全局变量</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>persistent</source>\n        <translation>持久变量</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-global.h\" line=\"+192\"/>\n        <source>Environment Variables</source>\n        <translation>环境变量</translation>\n    </message>\n    <message>\n        <location filename=\"../src/gui-preferences-sd.h\" line=\"+41\"/>\n        <source>Second color mode (light/dark)</source>\n        <translation>第二颜色模式（浅色/深色）</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Switch to a second set of colors.\nUseful for defining light/dark modes.\nDiscards non-applied current changes!</source>\n        <translation>切换到第二组颜色。\n可用于定义明/暗模式。\n丢弃未应用的当前更改！</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reload the default colors,\ndepends on currently selected mode.</source>\n        <translation>重新载入默认颜色，\n取决于当前选择的模式。</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Reload the default style values,\ndepends on currently selected mode.</source>\n        <translation>重新载入默认样式值，\n取决于当前选择的模式。</translation>\n    </message>\n    <message>\n        <location line=\"-13\"/>\n        <source>&amp;Reload default colors</source>\n        <translation>重新导入默认颜色 (&amp;R)</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>&amp;Reload default styles</source>\n        <translation>重新导入默认样式 (&amp;R)</translation>\n    </message>\n    <message>\n        <location filename=\"../src/settings-dialog.cc\" line=\"-976\"/>\n        <source>Loading current preferences ... </source>\n        <translation>加载当前首选项 ... </translation>\n    </message>\n    <message>\n        <location line=\"+44\"/>\n        <location line=\"+6\"/>\n        <location line=\"+1092\"/>\n        <source>System setting</source>\n        <translation>系统设置</translation>\n    </message>\n    <message>\n        <location line=\"-834\"/>\n        <source>IBeam Cursor</source>\n        <translation>IBeam 光标</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Block Cursor</source>\n        <translation>块状光标</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Underline Cursor</source>\n        <translation>下划线光标</translation>\n    </message>\n    <message>\n        <location line=\"+176\"/>\n        <source>Color of highlighted current line (magenta (255,0,255) for automatic color)</source>\n        <translation>当前行高亮显示的颜色 （品红 （255,0,255） 为自动颜色）</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Set Octave Startup Directory</source>\n        <translation>设置 Octave 启动目录</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Set File Browser Startup Directory</source>\n        <translation>设置文件浏览器启动目录</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Applying preferences ... </source>\n        <translation>应用首选项 ... </translation>\n    </message>\n    <message>\n        <location line=\"+89\"/>\n        <location line=\"+22\"/>\n        <location line=\"+1124\"/>\n        <source>Failed to open %1 as Octave shortcut file</source>\n        <translation>无法将 %1 作为 Octave 快捷键文件打开</translation>\n    </message>\n    <message>\n        <location line=\"-453\"/>\n        <source>Enable attribute colors</source>\n        <translation>启用属性颜色</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Hide tool tips</source>\n        <translation>隐藏工具提示</translation>\n    </message>\n    <message>\n        <location line=\"+384\"/>\n        <source>Import shortcuts from file...</source>\n        <translation>从文件导入快捷键...</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+6\"/>\n        <source>Octave Shortcut Files (*.osc);;All Files (*)</source>\n        <translation>Octave 快捷键文件 (*.osc);;全部文件 (*)</translation>\n    </message>\n    <message>\n        <location line=\"-1\"/>\n        <source>Export shortcuts to file...</source>\n        <translation>导出快捷键到文件...</translation>\n    </message>\n    <message>\n        <location line=\"+32\"/>\n        <source>Overwriting Shortcuts</source>\n        <translation>覆盖快捷键</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>You are about to overwrite all shortcuts.\nWould you like to save the current shortcut set or cancel the action?</source>\n        <translation>您即将覆盖所有快捷键。\n你想保存当前的快捷键设置还是取消操作？</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Don&apos;t save</source>\n        <translation>不保存 (&apos;t)</translation>\n    </message>\n    <message>\n        <location line=\"+34\"/>\n        <source>Octave GUI preferences</source>\n        <translation>Octave 图形用户界面首选项</translation>\n    </message>\n</context>\n<context>\n    <name>octave::setup_community_news</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+45\"/>\n        <source>Community News</source>\n        <translation>社区新闻</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Previous</source>\n        <translation>上一个</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next</source>\n        <translation>下一个</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cancel</source>\n        <translation>取消</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\nThe check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.&lt;/p&gt;\n&lt;p&gt;You may also view the news by selecting the &quot;Community News&quot; item in the &quot;Help&quot; menu, or by visiting\n&lt;a href=&quot;https://octave.org/community-news.html&quot;&gt;https://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;body&gt;\n&lt;p&gt;当 Octave GUI 启动的时候，它会检查 Octave 站点上关于 Octave 社区的新闻和信息。\n每天会检查一次新闻消息，而只有在你上次阅读新闻起有新的新闻出现时才会弹出。&lt;/p&gt;\n&lt;p&gt;你也可以点选 GUI 上的 &quot;社区新闻&quot; 以直接阅读新闻，或直接访问:\n&lt;a href=&quot;http://octave.org/community-news.html&quot;&gt;http://octave.org/community-news.html&lt;/a&gt;.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head&gt;\n&lt;/head&gt;&lt;body&gt;\n&lt;p&gt;允许 Octave 在启动时连接到 Octave 网站，以便显示有关 Octave 社区的最新新闻和信息。&lt;/p&gt;\n&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcut_edit_dialog</name>\n    <message>\n        <location filename=\"../src/shortcuts-tree-widget.cc\" line=\"+172\"/>\n        <source>Enter New Shortcut</source>\n        <translation>输入新快捷键</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Enter custom shortcut\nAction: %1</source>\n        <translation>输入自定义快捷方式\n动作：%1</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Enter shortcut by typing it</source>\n        <translation>键盘键入来输入快捷键</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Add Shift modifier\n(allows one to enter number keys)</source>\n        <translation>添加Shift修改器\n(允许输入数字键)</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Actual Shortcut</source>\n        <translation>实际快捷键</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Default Shortcut</source>\n        <translation>默认快捷键</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Clear</source>\n        <translation>清空</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set to default</source>\n        <translation>设为默认值</translation>\n    </message>\n    <message>\n        <location line=\"+125\"/>\n        <source>Double Shortcut</source>\n        <translation>双快捷键</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>The chosen shortcut\n  &quot;%1&quot;\nis already used for the action\n  &quot;%2&quot;.\nDo you want to use the shortcut and remove it from the previous action?</source>\n        <translation>选择的快捷方式\n  &quot;%1&quot;\n已用于动作\n  &quot;%2&quot;.\n您想使用该快捷键并将其从之前的动作中删除吗？</translation>\n    </message>\n</context>\n<context>\n    <name>octave::shortcuts_tree_widget</name>\n    <message>\n        <location line=\"+27\"/>\n        <source>Global</source>\n        <translation>全局</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <location line=\"+49\"/>\n        <source>File Menu</source>\n        <translation>文件菜单</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+49\"/>\n        <source>Edit Menu</source>\n        <translation>编辑菜单</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <location line=\"+52\"/>\n        <source>Debug Menu</source>\n        <translation>调试菜单</translation>\n    </message>\n    <message>\n        <location line=\"-49\"/>\n        <source>Tools Menu</source>\n        <translation>工具菜单</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Window Menu</source>\n        <translation>窗口菜单</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+49\"/>\n        <source>Help Menu</source>\n        <translation>帮助目录</translation>\n    </message>\n    <message>\n        <location line=\"-46\"/>\n        <source>News Menu</source>\n        <translation>新闻目录</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Handling of Dock Widgets</source>\n        <translation>停靠组件相关操作</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Tab Handling in Dock Widgets</source>\n        <translation>停靠组件中标签页的相关操作</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Find &amp; Replace in Dock Widgets</source>\n        <translation>停靠组件中的查找和替换</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zooming in Editor and Documentation</source>\n        <translation>编辑器和文档的缩放</translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Editor</source>\n        <translation>编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>View Menu</source>\n        <translation>视图菜单</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Run Menu</source>\n        <translation>运行菜单</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Documentation Viewer</source>\n        <translation>文档浏览器</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Browser</source>\n        <translation>浏览</translation>\n    </message>\n    <message>\n        <location line=\"+115\"/>\n        <source>item %1 not found in shortcut settings dialog</source>\n        <translation>在快捷键设置对话框中找不到 %1 项</translation>\n    </message>\n</context>\n<context>\n    <name>octave::splash_screen</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"+135\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation type=\"unfinished\">欢迎使用 GNU Octave</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Welcome to Octave!</source>\n        <translation type=\"unfinished\">欢迎来到 Octave!</translation>\n    </message>\n</context>\n<context>\n    <name>octave::terminal_dock_widget</name>\n    <message>\n        <location filename=\"../src/terminal-dock-widget.cc\" line=\"+108\"/>\n        <source>Command Window</source>\n        <translation>命令窗口</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_dock_widget</name>\n    <message>\n        <location filename=\"../src/variable-editor.cc\" line=\"+177\"/>\n        <source>Dock Widget</source>\n        <translation>停靠组件</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Variable Editor: </source>\n        <translation>变量编辑器： </translation>\n    </message>\n    <message>\n        <location line=\"+15\"/>\n        <source>Undock Widget</source>\n        <translation>解除组件停靠</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Restore geometry</source>\n        <translation>恢复窗口几何形状</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redock</source>\n        <translation>重新停靠</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor</name>\n    <message>\n        <location line=\"+922\"/>\n        <source>Variable Editor</source>\n        <translation>变量编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Edit variables.</source>\n        <translation>编辑变量。</translation>\n    </message>\n    <message>\n        <location line=\"+555\"/>\n        <source>Variable Editor Toolbar</source>\n        <translation>变量编辑器工具栏</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Save</source>\n        <translation>保存</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Save variable to a file</source>\n        <translation>保存变量到文件</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+5\"/>\n        <location line=\"+6\"/>\n        <source>Save in format ...</source>\n        <translation>保存为格式...</translation>\n    </message>\n    <message>\n        <location line=\"-5\"/>\n        <source>Save variable to a file in different format</source>\n        <translation>以不同的格式保存变量到文件</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Cut</source>\n        <translation>剪切</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Cut data to clipboard</source>\n        <translation>剪切到剪切板</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy</source>\n        <translation>复制</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Copy data to clipboard</source>\n        <translation>复制到剪切板</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste</source>\n        <translation>粘贴</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Paste clipboard into variable data</source>\n        <translation>粘贴剪切板到变量</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <location line=\"+6\"/>\n        <location line=\"+7\"/>\n        <source>Plot</source>\n        <translation>绘制</translation>\n    </message>\n    <message>\n        <location line=\"-11\"/>\n        <source>Plot Selected Data</source>\n        <translation>绘制所选数据</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Plot selected data</source>\n        <translation>绘制所选数据</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Up</source>\n        <translation>上</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Go one level up in variable hierarchy</source>\n        <translation>前往变量的上一级节点</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_stack</name>\n    <message>\n        <location line=\"-1265\"/>\n        <source>Save Variable %1 As</source>\n        <translation>保存变量 %1 为</translation>\n    </message>\n</context>\n<context>\n    <name>octave::variable_editor_view</name>\n    <message>\n        <location line=\"+142\"/>\n        <source>Cut</source>\n        <translation>剪切</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Copy</source>\n        <translation>复制</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Paste</source>\n        <translation>粘贴</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Clear</source>\n        <translation>清空</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Delete</source>\n        <translation>删除</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Variable from Selection</source>\n        <translation>从所选区域创建变量</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Transpose</source>\n        <translation>转置</translation>\n    </message>\n    <message>\n        <location line=\"+56\"/>\n        <source> columns</source>\n        <translation> 列</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> column</source>\n        <translation> 列</translation>\n    </message>\n    <message>\n        <location line=\"+52\"/>\n        <source> rows</source>\n        <translation> 行</translation>\n    </message>\n    <message>\n        <location line=\"+0\"/>\n        <source> row</source>\n        <translation> 行</translation>\n    </message>\n</context>\n<context>\n    <name>octave::welcome_wizard</name>\n    <message>\n        <location filename=\"../src/welcome-wizard.cc\" line=\"-335\"/>\n        <source>Welcome to GNU Octave</source>\n        <translation>欢迎使用 GNU Octave</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_model</name>\n    <message>\n        <location filename=\"../src/workspace-model.cc\" line=\"+49\"/>\n        <source>Name</source>\n        <translation>名称</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Class</source>\n        <translation>类</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>维度</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>值</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>属性</translation>\n    </message>\n    <message>\n        <location line=\"+83\"/>\n        <source>Right click to copy, rename, or display</source>\n        <translation>右击以复制，重命名或显示</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <location line=\"+2\"/>\n        <source>complex</source>\n        <translation>复杂度</translation>\n    </message>\n</context>\n<context>\n    <name>octave::workspace_view</name>\n    <message>\n        <location filename=\"../src/gui-preferences-ws.h\" line=\"-21\"/>\n        <source>Class</source>\n        <translation>类</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Dimension</source>\n        <translation>维度</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Value</source>\n        <translation>值</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Attribute</source>\n        <translation>属性</translation>\n    </message>\n    <message>\n        <location filename=\"../src/workspace-view.cc\" line=\"+60\"/>\n        <source>Workspace</source>\n        <translation>工作区</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>View the variables in the active workspace.</source>\n        <translation>显示当前活动工作区的变量。</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Enter text to filter the workspace</source>\n        <translation>输入文本以筛选工作区</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Filter</source>\n        <translation>过滤器</translation>\n    </message>\n    <message>\n        <location line=\"+138\"/>\n        <source>View the variables in the active workspace.&lt;br&gt;</source>\n        <translation>显示当前活动工作区的变量。&lt;br&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Colors for variable attributes:</source>\n        <translation>变量属性的颜色:</translation>\n    </message>\n    <message>\n        <location line=\"+139\"/>\n        <source>Open in Variable Editor</source>\n        <translation>在变量编辑器中打开</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy name</source>\n        <translation>复制变量名</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy value</source>\n        <translation>复制变量值</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Rename</source>\n        <translation>重命名</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Only top-level symbols may be renamed</source>\n        <translation>只有顶级符号可能会被重命名</translation>\n    </message>\n    <message>\n        <location line=\"+22\"/>\n        <source>Hide filter</source>\n        <translation>隐藏过滤器</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show filter</source>\n        <translation>显示过滤器</translation>\n    </message>\n</context>\n<context>\n    <name>self_listener</name>\n    <message>\n        <location filename=\"../src/self-listener.cc\" line=\"+82\"/>\n        <source>Can not open redirected stream with fd = %1.</source>\n        <translation>无法打开重定向的流，文件描述符为 %1。</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Can not disable buffering of stream with fd = %1.</source>\n        <translation>无法禁用流的缓冲，文件描述符为 %1。</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Can not dup redirected stream with fd = %1.</source>\n        <translation>无法复制重定向的流，文件描述符为 %1。</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Cannot create pipe for redirecting stream with fd = %1:</source>\n        <translation>无法为重定向的流创建管道，文件描述符为 %1：</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Cannot dup2 redirected stream with fd = %1\nto pipe with fd = %2: %3</source>\n        <translation>无法将文件描述符为 %1 的重定向流\n复制到文件描述符为 %2 的管道：%3</translation>\n    </message>\n    <message>\n        <location line=\"+57\"/>\n        <source>Error while listening to redirected streams</source>\n        <translation>监听重定向流时出错</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Error reading from redirected stream fd = %1.</source>\n        <oldsource>Error reading from redirected strem fd = %1.</oldsource>\n        <translation type=\"unfinished\">从重定向流读取时出错，文件描述符为 %1。</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>\nOutput redirection in </source>\n        <translation>\n输出重定向到 </translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source> won&apos;t work.</source>\n        <translation> 无法正常工作。</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>\nError: </source>\n        <translation>\n错误: </translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Octave</source>\n        <translation>Octave</translation>\n    </message>\n</context>\n<context>\n    <name>settings_dialog</name>\n    <message>\n        <location filename=\"../src/settings-dialog.ui\" line=\"+45\"/>\n        <location line=\"+841\"/>\n        <location line=\"+1916\"/>\n        <source>General</source>\n        <translation>常规</translation>\n    </message>\n    <message>\n        <location line=\"-2736\"/>\n        <source>Interface</source>\n        <translation>界面</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Dock widget title bar</source>\n        <translation>停靠组件标题栏</translation>\n    </message>\n    <message>\n        <location line=\"+413\"/>\n        <source>Confirm before exiting</source>\n        <translation>退出前确认</translation>\n    </message>\n    <message>\n        <location line=\"-89\"/>\n        <source>Octave logo only</source>\n        <translation>仅 Octave logo</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Letter icons</source>\n        <translation>字母图标</translation>\n    </message>\n    <message>\n        <location line=\"+59\"/>\n        <location line=\"+446\"/>\n        <source>Show status bar</source>\n        <translation>显示状态栏</translation>\n    </message>\n    <message>\n        <location line=\"-684\"/>\n        <source>Text inactive</source>\n        <translation>不活动的文本颜色</translation>\n    </message>\n    <message>\n        <location line=\"-32\"/>\n        <location line=\"+45\"/>\n        <source>Active</source>\n        <translation>活动</translation>\n    </message>\n    <message>\n        <location line=\"-96\"/>\n        <source>Small</source>\n        <translation>小</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Large</source>\n        <translation>大</translation>\n    </message>\n    <message>\n        <location line=\"+105\"/>\n        <source>Custom style</source>\n        <translation>自定义样式</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Background inactive</source>\n        <translation>不活动的背景颜色</translation>\n    </message>\n    <message>\n        <location line=\"+19\"/>\n        <source>3-D</source>\n        <oldsource>3D</oldsource>\n        <translation type=\"unfinished\">3D</translation>\n    </message>\n    <message>\n        <location line=\"+206\"/>\n        <source>Octave Startup</source>\n        <translation>Octave 启动</translation>\n    </message>\n    <message>\n        <location line=\"+46\"/>\n        <location line=\"+1698\"/>\n        <source>Browse</source>\n        <translation>浏览</translation>\n    </message>\n    <message>\n        <location line=\"-1385\"/>\n        <source>Editor</source>\n        <translation>编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+488\"/>\n        <location line=\"+140\"/>\n        <source>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</source>\n        <translation>这适用于等宽字体。 该线根据默认字体中空格字符的宽度绘制。 如果样式使用比例字体，或者使用不同的字体大小或粗体，斜体和普通文本，它可能无法很好地工作。</translation>\n    </message>\n    <message>\n        <location line=\"-535\"/>\n        <source>Enable Code Folding</source>\n        <translation>启用代码折叠</translation>\n    </message>\n    <message>\n        <location line=\"+1116\"/>\n        <source>Windows (CRLF)</source>\n        <translation>Windows (CRLF)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Legacy Mac (CR)</source>\n        <translation>Legacy Mac (CR)</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Unix (LF)</source>\n        <translation>Unix (LF)</translation>\n    </message>\n    <message>\n        <location line=\"-1091\"/>\n        <source>Show horizontal scroll bar</source>\n        <translation>显示水平滚动条</translation>\n    </message>\n    <message>\n        <location line=\"-19\"/>\n        <source>Show tool bar</source>\n        <translation>显示工具栏</translation>\n    </message>\n    <message>\n        <location line=\"+537\"/>\n        <source>Indentation</source>\n        <translation>缩进</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Indent width</source>\n        <translation>缩进宽度</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Tab indents line</source>\n        <translation>Tab 键缩进行</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Auto indentation</source>\n        <translation>自动缩进</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Tab width</source>\n        <translation>Tab 键宽度</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Show indentation guides</source>\n        <translation>显示缩进参考线</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Backspace unindents line</source>\n        <translation>退格键删除缩进符</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Indentation uses tabs</source>\n        <translation>使用 tabs 缩进</translation>\n    </message>\n    <message>\n        <location line=\"+70\"/>\n        <source>Auto completion</source>\n        <translation>自动补全</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Match keywords</source>\n        <translation>匹配关键字</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Case sensitive</source>\n        <translation>大小写敏感</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>Replace word by suggested one</source>\n        <translation>使用建议的单词替换原单词</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Match words in document</source>\n        <translation>在文档中匹配单词</translation>\n    </message>\n    <message>\n        <location line=\"+48\"/>\n        <source>With Octave builtins</source>\n        <translation>Octave 内置</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>With Octave functions</source>\n        <translation>Octave 函数</translation>\n    </message>\n    <message>\n        <location line=\"+64\"/>\n        <source>Show completion list automatically</source>\n        <translation>自动显示补全列表</translation>\n    </message>\n    <message>\n        <location line=\"+159\"/>\n        <source>Reload externally changed files without prompt</source>\n        <translation>无需提示即可重新加载外部更改的文件</translation>\n    </message>\n    <message>\n        <location line=\"-924\"/>\n        <source>Use custom file editor</source>\n        <translation>使用自定义文件编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+843\"/>\n        <source>Text encoding used for loading and saving</source>\n        <translation>文本编码用于加载和保存</translation>\n    </message>\n    <message>\n        <location line=\"+166\"/>\n        <source>Editor Styles</source>\n        <translation>编辑器风格</translation>\n    </message>\n    <message>\n        <location line=\"-1390\"/>\n        <source>(Changing buffer size clears history)</source>\n        <translation>(更改缓冲区大小清除历史记录)</translation>\n    </message>\n    <message>\n        <location line=\"+28\"/>\n        <source>History buffer Size</source>\n        <translation>历史缓冲区大小</translation>\n    </message>\n    <message>\n        <location line=\"-123\"/>\n        <location line=\"+1870\"/>\n        <source>Font</source>\n        <translation>字体</translation>\n    </message>\n    <message>\n        <location line=\"-1580\"/>\n        <source>Show line numbers</source>\n        <translation>显示行数</translation>\n    </message>\n    <message>\n        <location line=\"-517\"/>\n        <source>Graphic icons</source>\n        <translation>图形图标</translation>\n    </message>\n    <message>\n        <location line=\"+97\"/>\n        <source>These preferences are applied after any .octaverc startup files.</source>\n        <translation>这些首选项在任何.octaverc启动文件之后应用。</translation>\n    </message>\n    <message>\n        <location line=\"+433\"/>\n        <source>Show whitespace</source>\n        <translation>显示空白字符</translation>\n    </message>\n    <message>\n        <location line=\"-45\"/>\n        <source>Do not show whitespace used for indentation</source>\n        <translation>不要显示缩进的空白空间</translation>\n    </message>\n    <message>\n        <location line=\"+152\"/>\n        <source>Show EOL characters</source>\n        <translation>显示 EOL 字符</translation>\n    </message>\n    <message>\n        <location line=\"+1002\"/>\n        <source>Default EOL mode</source>\n        <translation>默认 EOL 模式</translation>\n    </message>\n    <message>\n        <location line=\"-219\"/>\n        <source>Number of characters before list is shown: </source>\n        <translation>显示列表前的字符数: </translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Create nonexistent files without prompting</source>\n        <translation>在创建不存在的文件时不提示</translation>\n    </message>\n    <message>\n        <location line=\"-897\"/>\n        <source>command line (%f=file, %l=line):</source>\n        <translation>命令行 (%f=文件, %l=行数):</translation>\n    </message>\n    <message>\n        <location line=\"+1015\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;选择字体, 字体大小 (作为与默认大小的差异), 字体样式 (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), 文本颜色, 和背景颜色 (对于后者，颜色洋红色(255,0,255)是默认背景颜色的占位符).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-1515\"/>\n        <source>Cursor type:</source>\n        <translation>光标类型:</translation>\n    </message>\n    <message>\n        <location line=\"-605\"/>\n        <source>Preferences</source>\n        <translation>首选项</translation>\n    </message>\n    <message>\n        <location line=\"+351\"/>\n        <source>(requires restart)</source>\n        <translation>(需要重启软件)</translation>\n    </message>\n    <message>\n        <location line=\"+73\"/>\n        <source>Use native file dialogs</source>\n        <translation>使用系统原生文件对话框</translation>\n    </message>\n    <message>\n        <location line=\"-98\"/>\n        <source>Toolbar Icons</source>\n        <translation>工具栏图标</translation>\n    </message>\n    <message>\n        <location line=\"-224\"/>\n        <source>Language</source>\n        <translation>语言</translation>\n    </message>\n    <message>\n        <location line=\"-41\"/>\n        <source>Dock widgets window icons</source>\n        <translation>停靠组件窗口图标</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Style</source>\n        <translation>样式</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Icon theme (requires restart)</source>\n        <translation>图标样式（需要重启）</translation>\n    </message>\n    <message>\n        <location line=\"+323\"/>\n        <source>Blinking cursor</source>\n        <translation>闪烁光标</translation>\n    </message>\n    <message>\n        <location line=\"+37\"/>\n        <source>Show splash screen at startup</source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Initial working directory of Octave interpreter</source>\n        <translation>Octave 解释器的初始工作目录</translation>\n    </message>\n    <message>\n        <location line=\"+18\"/>\n        <source>Restore last working directory of previous session</source>\n        <translation>恢复前一个会话的工作目录</translation>\n    </message>\n    <message>\n        <location line=\"+45\"/>\n        <source>Command</source>\n        <translation>命令</translation>\n    </message>\n    <message>\n        <location line=\"+208\"/>\n        <source>Set focus to Command Window when running a command from within another widget</source>\n        <translation>从其他组件中运行命令时，将焦点设置在“命令窗口”上</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Print debug location in Command Window in addition to the marker in the editor</source>\n        <translation>除编辑器中的标记外，在命令窗口中打印调试位置</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Command Window Colors</source>\n        <translation>命令窗口颜色</translation>\n    </message>\n    <message>\n        <location line=\"+190\"/>\n        <source>Number size as difference to editor font</source>\n        <translation>行数字体大小(与编辑器字体不同)</translation>\n    </message>\n    <message>\n        <location line=\"+79\"/>\n        <source>Highlight current line (color adjustable below with editor styles)</source>\n        <translation>高亮当前行（颜色可用下方编辑器样式调整）</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Highlight all occurrences of a word selected by a double click</source>\n        <translation>双击高亮所选单词的所有出现处</translation>\n    </message>\n    <message>\n        <location line=\"+65\"/>\n        <source>Tabs</source>\n        <translation>标签页</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;旋转标签页：在顶部或底部时为垂直，在左侧或右侧时为水平。 关闭按钮在旋转后的标签页中不显示。&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+74\"/>\n        <source>Comments (Octave)</source>\n        <translation>注释 (Octave)</translation>\n    </message>\n    <message>\n        <location line=\"+11\"/>\n        <source>Strings considered for uncommenting text</source>\n        <translation>视为非注释的字符串</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>String used for commenting selected text</source>\n        <translation>用于注释的字符串</translation>\n    </message>\n    <message>\n        <location line=\"+31\"/>\n        <source>Long lines</source>\n        <translation>长代码行</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Break long lines at line length</source>\n        <translation>在代码行长度处断开超长代码</translation>\n    </message>\n    <message>\n        <location line=\"+13\"/>\n        <source>Break lines only in comments</source>\n        <translation>只在注释中断开代码行</translation>\n    </message>\n    <message>\n        <location line=\"+60\"/>\n        <source>Line length</source>\n        <translation>代码行长度</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Long line marker</source>\n        <translation>长代码行标记</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Line</source>\n        <translation>代码行</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Background</source>\n        <translation>背景</translation>\n    </message>\n    <message>\n        <location line=\"+38\"/>\n        <source>Wrap long lines at current window border</source>\n        <translation>在当前的窗口边框处换行</translation>\n    </message>\n    <message>\n        <location line=\"+153\"/>\n        <source>Auto insert after &quot;if&quot; etc.</source>\n        <translation>自动在&quot;if&quot;等后插入.</translation>\n    </message>\n    <message>\n        <location line=\"+20\"/>\n        <source>Nothing</source>\n        <translation>无</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;endif&quot; etc.</source>\n        <translation>&quot;endif&quot; 等.</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>&quot;end&quot;</source>\n        <translation>&quot;end&quot;</translation>\n    </message>\n    <message>\n        <location line=\"+238\"/>\n        <source>Debugging</source>\n        <translation>调试</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Always show debug breakpoints and pointers (opens related file if closed)</source>\n        <translation>始终显示调试断点和指针(如果关闭此选项则会打开相关文件)</translation>\n    </message>\n    <message>\n        <location line=\"+67\"/>\n        <source>Restore editor tabs from previous session on startup or when editor is shown again after closing</source>\n        <translation>在启动时或编辑器关闭后再次显示时，恢复上次会话的编辑器标签页</translation>\n    </message>\n    <message>\n        <location line=\"+40\"/>\n        <source>Close all files when the editor widget is closed/hidden</source>\n        <translation>当编辑器组件关闭/隐藏时关闭所有文件</translation>\n    </message>\n    <message>\n        <location line=\"+75\"/>\n        <source>Directory of open file dialog follows current editor file instead of current Octave directory </source>\n        <translation type=\"unfinished\"></translation>\n    </message>\n    <message>\n        <location line=\"+884\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;确定&lt;/span&gt; - 关闭对话框并应用设置&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;应用 - &lt;/span&gt;应用设置但保持对话框打开&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;取消 - &lt;/span&gt;关闭对话框并丢弃未应用的修改&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;重置 -&lt;/span&gt; 重新加载设置并丢弃未应用的修改&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"-2374\"/>\n        <source>Use foreground color</source>\n        <translation>使用前景色</translation>\n    </message>\n    <message>\n        <location line=\"-140\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;如果选中，则停靠到主窗口组件的焦点跟随鼠标光标。 这是为了在&amp;quot;焦点跟随鼠标&amp;quot;时在主窗口中具有相同的行为。 用于桌面环境。&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Focus follows mouse for widgets docked to the main window</source>\n        <translation>组件停靠到主窗口时焦点跟随鼠标</translation>\n    </message>\n    <message>\n        <location line=\"+189\"/>\n        <location line=\"+1760\"/>\n        <source>Font size</source>\n        <translation>字体大小</translation>\n    </message>\n    <message>\n        <location line=\"-1234\"/>\n        <source>Rotated tabs</source>\n        <translation>旋转标签页</translation>\n    </message>\n    <message>\n        <location line=\"+25\"/>\n        <source>Position</source>\n        <translation>位置</translation>\n    </message>\n    <message>\n        <location line=\"+9\"/>\n        <source>Max. tab width in chars (0: no limit)</source>\n        <translation>以字符为单位的最大标签页宽度（0：无限制）</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;以字符为单位的最大制表符宽度（平均字符宽度）。 特别是对旋转标签页有用。&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+773\"/>\n        <source>Force newline at end when saving file</source>\n        <translation>保存文件时强制在文件结尾换行</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Remove trailing spaces when saving file</source>\n        <translation>保存文件时删除末尾空格</translation>\n    </message>\n    <message>\n        <location line=\"+185\"/>\n        <source>File Browser</source>\n        <translation>文件浏览器</translation>\n    </message>\n    <message>\n        <location line=\"+75\"/>\n        <source>Initial file browser directory (only if not synchronized with initial working directory of Octave)</source>\n        <translation>初始文件浏览器目录（仅当未与Octave的初始工作目录同步时）</translation>\n    </message>\n    <message>\n        <location line=\"+75\"/>\n        <source>Workspace</source>\n        <translation>工作区</translation>\n    </message>\n    <message>\n        <location line=\"+35\"/>\n        <source>Colors for variable attributes</source>\n        <translation>变量属性的颜色</translation>\n    </message>\n    <message>\n        <location line=\"+133\"/>\n        <source>Use Command Window font</source>\n        <translation>使用命令窗口字体</translation>\n    </message>\n    <message>\n        <location line=\"+154\"/>\n        <source>Import shortcut set</source>\n        <translation>导入快捷键设置</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Export current shortcut set</source>\n        <translation>导出当前快捷键设置</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Reset shortcuts to their defaults</source>\n        <translation>将快捷方式重置为其默认值</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+80\"/>\n        <source>Default</source>\n        <translation>默认</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>Actual</source>\n        <translation>当前</translation>\n    </message>\n    <message>\n        <location line=\"+17\"/>\n        <source>Network</source>\n        <translation>网络</translation>\n    </message>\n    <message>\n        <location line=\"+27\"/>\n        <source>Allow Octave to connect to the Octave web site to display current news and information</source>\n        <translation>允许 Octave 连接到 Octave 站点以显示当前新闻和信息</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Proxy Server</source>\n        <translation>代理服务器</translation>\n    </message>\n    <message>\n        <location line=\"+23\"/>\n        <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>\n        <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;选择 &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; 或者 &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;。 选中最后一个选项时，代理取自第一个非空的环境变量 ALL_PROXY, HTTP_PROXY 或 HTTPS_PROXY 。&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Use proxy server</source>\n        <translation>使用代理服务器</translation>\n    </message>\n    <message>\n        <location line=\"-523\"/>\n        <source>Variable Editor</source>\n        <translation>变量编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+43\"/>\n        <source>Default row height</source>\n        <translation>默认行高</translation>\n    </message>\n    <message>\n        <location line=\"+7\"/>\n        <source>Default column width</source>\n        <translation>默认列宽</translation>\n    </message>\n    <message>\n        <location line=\"+78\"/>\n        <source>Variable Editor Colors</source>\n        <translation>变量编辑器颜色</translation>\n    </message>\n    <message>\n        <location line=\"+12\"/>\n        <source>Use alternating row colors</source>\n        <translation>使用颜色交替的行</translation>\n    </message>\n    <message>\n        <location line=\"+69\"/>\n        <source>Disable global shortcuts when Command Window has focus</source>\n        <translation>当聚焦于命令窗口时关闭全局快捷键</translation>\n    </message>\n    <message>\n        <location line=\"-2452\"/>\n        <source>Normal</source>\n        <translation>正常</translation>\n    </message>\n    <message>\n        <location line=\"+1787\"/>\n        <source>File handling</source>\n        <translation>文件处理</translation>\n    </message>\n    <message>\n        <location line=\"+265\"/>\n        <source>Behavior</source>\n        <translation>行为</translation>\n    </message>\n    <message>\n        <location line=\"+8\"/>\n        <source>Synchronize Octave working directory with file browser</source>\n        <translation>使用文件浏览器同步 Octave 工作目录</translation>\n    </message>\n    <message>\n        <location line=\"+14\"/>\n        <source>Restore last directory of previous session</source>\n        <translation>恢复前一个会话的最后一个目录</translation>\n    </message>\n    <message>\n        <location line=\"+334\"/>\n        <source>Shortcuts</source>\n        <translation>快捷键</translation>\n    </message>\n    <message>\n        <location line=\"+38\"/>\n        <source>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</source>\n        <translation>禁用全局快捷键以防止\n干扰 readline 快捷键。\n异常: Ctrl-C 用于中断解释器\n和切换到其他组件的快捷键。</translation>\n    </message>\n    <message>\n        <location line=\"+16\"/>\n        <source>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</source>\n        <translation>禁用菜单快捷键以防止\n干扰 readline 快捷键。</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Disable menu accelerators of main window menus when Command Window has focus</source>\n        <translation>当命令窗口获得焦点时，禁用主窗口的菜单快捷键</translation>\n    </message>\n    <message>\n        <location line=\"+50\"/>\n        <source>Export</source>\n        <translation>导出</translation>\n    </message>\n    <message>\n        <location line=\"-10\"/>\n        <source>Import</source>\n        <translation>导入</translation>\n    </message>\n    <message>\n        <location line=\"+29\"/>\n        <source>Edit a shortcut by double-clicking in Actual column</source>\n        <translation>双击“当前”列以编辑快捷方式</translation>\n    </message>\n    <message>\n        <location line=\"+61\"/>\n        <source>Action</source>\n        <translation>动作</translation>\n    </message>\n    <message>\n        <location line=\"+82\"/>\n        <source>Hostname:</source>\n        <translation>主机名:</translation>\n    </message>\n    <message>\n        <location line=\"-536\"/>\n        <source>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</source>\n        <translation>要在默认文本编辑器中打开的文件的扩展名 (以 &quot;;&quot; 分隔):</translation>\n    </message>\n    <message>\n        <location line=\"+566\"/>\n        <source>Proxy type:</source>\n        <translation>代理类型:</translation>\n    </message>\n    <message>\n        <location line=\"+10\"/>\n        <source>Port:</source>\n        <translation>端口:</translation>\n    </message>\n    <message>\n        <location line=\"-20\"/>\n        <source>Username:</source>\n        <translation>用户名:</translation>\n    </message>\n    <message>\n        <location line=\"+30\"/>\n        <source>Password:</source>\n        <translation>密码:</translation>\n    </message>\n</context>\n<context>\n    <name>shortcuts</name>\n    <message>\n        <location filename=\"../src/gui-preferences-sc.cc\" line=\"+227\"/>\n        <source>Undock/Dock Widget</source>\n        <translation>悬浮/停靠 组件</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Widget</source>\n        <translation>关闭组件</translation>\n    </message>\n    <message>\n        <location line=\"+5\"/>\n        <source>New File</source>\n        <translation>新建文件</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Function</source>\n        <translation>新建函数</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>New Figure</source>\n        <translation>新建图表</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Open File</source>\n        <translation>打开文件</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Load Workspace</source>\n        <translation>导入工作区</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save Workspace As</source>\n        <translation>工作区另存为</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Exit Octave</source>\n        <translation>退出 Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Copy</source>\n        <translation>复制</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Paste</source>\n        <translation>粘贴</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Undo</source>\n        <translation>撤销</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select All</source>\n        <translation>全选</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Clipboard</source>\n        <translation>清空剪贴板</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find in Files</source>\n        <translation>在文件中查找</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command Window</source>\n        <translation>清空命令窗口</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Command History</source>\n        <translation>清空命令历史</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Clear Workspace</source>\n        <translation>清空工作区</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Set Path</source>\n        <translation>设置路径</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <location line=\"+119\"/>\n        <source>Preferences</source>\n        <translation>首选项</translation>\n    </message>\n    <message>\n        <location line=\"-116\"/>\n        <source>Step</source>\n        <translation>单步跳过</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step In</source>\n        <translation>单步执行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Step Out</source>\n        <translation>单步停止</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Continue</source>\n        <translation>继续</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Quit Debug Mode</source>\n        <translation>退出调试模式</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Start/Stop Profiler Session</source>\n        <translation>启动/停止性能分析会话</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Resume Profiler Session</source>\n        <translation>恢复性能分析会话</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Profile Data</source>\n        <translation>显示性能分析数据</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Show Command Window</source>\n        <translation>显示命令窗口</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Command History</source>\n        <translation>显示命令历史</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show File Browser</source>\n        <translation>显示文件浏览器</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Workspace</source>\n        <translation>显示工作区</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Editor</source>\n        <translation>显示编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Documentation</source>\n        <translation>显示文档</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Variable Editor</source>\n        <translation>显示变量编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command Window</source>\n        <translation>命令窗口</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Command History</source>\n        <translation>命令历史</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>File Browser</source>\n        <translation>文件浏览器</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Workspace</source>\n        <translation>工作区</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Editor</source>\n        <translation>编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Documentation</source>\n        <translation>文档</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Variable Editor</source>\n        <translation>变量编辑器</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Widget</source>\n        <translation>上一个组件</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Reset Default Window Layout</source>\n        <translation>重置为默认窗口布局</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show On-disk Documentation</source>\n        <translation>显示磁盘中的文档</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Online Documentation</source>\n        <translation>显示在线文档</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Report Bug</source>\n        <translation>缺陷报告</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Packages</source>\n        <translation>Octave 软件包</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Contribute to Octave</source>\n        <translation>参与 Octave</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Octave Developer Resources</source>\n        <translation>Octave 开发者资源</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>About Octave</source>\n        <translation>关于 Octave</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Release Notes</source>\n        <translation>发行注记</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Community News</source>\n        <translation>社区新闻</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Close Tab</source>\n        <translation>关闭标签页</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close All Tabs</source>\n        <translation>关闭所有标签页</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Close Other Tabs</source>\n        <translation>关闭其他标签页</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Left Tab</source>\n        <translation>切换到左侧标签页</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Switch to Right Tab</source>\n        <translation>切换到右侧标签页</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Left</source>\n        <translation>向左移动标签页</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move Tab Right</source>\n        <translation>向右移动标签页</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Zoom In</source>\n        <translation>放大</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Zoom Out</source>\n        <translation>缩小</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <location line=\"+2\"/>\n        <source>Zoom Normal</source>\n        <translation>恢复缩放比例</translation>\n    </message>\n    <message>\n        <location line=\"+6\"/>\n        <source>Edit Function</source>\n        <translation>编辑函数</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File</source>\n        <translation>保存文件</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Save File As</source>\n        <translation>另存文件为</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Print</source>\n        <translation>打印</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Redo</source>\n        <translation>撤销</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut</source>\n        <translation>剪切</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find and Replace</source>\n        <translation>查找并替换</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Next</source>\n        <translation>查找下一个</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Find Previous</source>\n        <translation>查找上一个</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Word</source>\n        <translation>删除到单词开始</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Word</source>\n        <translation>删除到单词结尾</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to Start of Line</source>\n        <translation>删除到行的开始</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete to End of Line</source>\n        <translation>删除到行的结尾</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Delete Line</source>\n        <translation>删除行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Copy Line</source>\n        <translation>复制行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Cut Line</source>\n        <translation>剪切行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Duplicate Selection/Line</source>\n        <translation>重复选择的文本/行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Transpose Line</source>\n        <translation>交换行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Completion List</source>\n        <translation>显示补全列表</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Comment Selection</source>\n        <translation>注释选择的文本</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uncomment Selection</source>\n        <translation>取消选择的文本的注释</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Comment Selection (Choosing String)</source>\n        <translation>注释所选(正在选择字符串)</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Uppercase Selection</source>\n        <translation>将选择的文本大写</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Lowercase Selection</source>\n        <translation>将选择的文本小写</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <location line=\"+3\"/>\n        <source>Indent Selection Rigidly</source>\n        <translation>严格向右缩进所选</translation>\n    </message>\n    <message>\n        <location line=\"-2\"/>\n        <location line=\"+3\"/>\n        <source>Unindent Selection Rigidly</source>\n        <translation>严格向左缩进所选</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Indent Code</source>\n        <translation>缩进代码</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Convert Line Endings to Windows</source>\n        <translation>将行结束符转换为Windows样式</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Unix</source>\n        <translation>将行结束符转换为Unix样式</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Convert Line Endings to Mac</source>\n        <translation>将行结束符转换为Mac样式</translation>\n    </message>\n    <message>\n        <location line=\"+2\"/>\n        <source>Goto Line</source>\n        <translation>跳转到行</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Move to Matching Brace</source>\n        <translation>移至匹配的括号</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Select to Matching Brace</source>\n        <translation>选择匹配的括号间的文本</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Toggle Bookmark</source>\n        <translation>切换书签</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Bookmark</source>\n        <translation>下一个书签</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Bookmark</source>\n        <translation>上一个书签</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Bookmark</source>\n        <translation>移除所有书签</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Styles Preferences</source>\n        <translation>样式首选项</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Show Line Numbers</source>\n        <translation>显示行号</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Whitespace Characters</source>\n        <translation>显示空白字符</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Line Endings</source>\n        <translation>显示行结束符</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Indentation Guides</source>\n        <translation>显示缩进对齐线</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Long Line Marker</source>\n        <translation>显示长文本行标记</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Toolbar</source>\n        <translation>显示工具栏</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Statusbar</source>\n        <translation>显示状态栏</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Show Horizontal Scrollbar</source>\n        <translation>显示水平滚动条</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Sort Tabs Alphabetically</source>\n        <translation>按字母顺序排序标签页</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Toggle Breakpoint</source>\n        <translation>开关断点</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Next Breakpoint</source>\n        <translation>下一个断点</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Previous Breakpoint</source>\n        <translation>上一个断点</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Remove All Breakpoints</source>\n        <translation>移除所有断点</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Run File</source>\n        <translation>运行文件</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Selection</source>\n        <translation>运行所选</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Tests</source>\n        <translation>运行测试</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Run Demos</source>\n        <translation>运行演示</translation>\n    </message>\n    <message>\n        <location line=\"+3\"/>\n        <source>Help on Keyword</source>\n        <translation>关键字帮助</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Document on Keyword</source>\n        <translation>关键字文档</translation>\n    </message>\n    <message>\n        <location line=\"+4\"/>\n        <source>Go to Homepage</source>\n        <translation>回到主页</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Back one Page</source>\n        <translation>回退一页</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Go Forward one Page</source>\n        <translation>前进一页</translation>\n    </message>\n    <message>\n        <location line=\"+1\"/>\n        <source>Bookmark this Page</source>\n        <translation>为此标签页添加标签</translation>\n    </message>\n</context>\n</TS>\n"
  },
  {
    "path": "libgui/liboctgui-build-info.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_liboctgui_build_info_h)\n#define octave_liboctgui_build_info_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nextern OCTGUI_API std::string liboctgui_hg_id ();\n\n#endif\n"
  },
  {
    "path": "libgui/liboctgui-build-info.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"liboctgui-build-info.h\"\n\nstd::string\nliboctgui_hg_id ()\n{\n  return \"%OCTAVE_HG_ID%\";\n}\n"
  },
  {
    "path": "libgui/module.mk",
    "content": "if AMCOND_BUILD_QT_GUI\n\n%canon_reldir%_EXTRA_DIST =\n\n%canon_reldir%_CLEANFILES =\n%canon_reldir%_DISTCLEANFILES =\n%canon_reldir%_MAINTAINERCLEANFILES =\n\nMOC_CPPFLAGS =\n\n## Fix for bug #42839 where -mieee CFLAG option is added to CPPFLAGS by gnulib.\n## Users may also pass other options in CPPFLAGS that moc does not understand.\n## Only keep moc-compatible options -Idir, -Dmacro, and -Umacro.\nMOC_OCTAVE_CPPFLAGS = $(filter -I% -D% -U%, $(AM_CPPFLAGS) $(CPPFLAGS))\n\noctlib_LTLIBRARIES += %reldir%/liboctgui.la\n\nTRANSLATIONS = \\\n  %reldir%/languages/ast_ES.ts \\\n  %reldir%/languages/be_BY.ts \\\n  %reldir%/languages/ca_ES.ts \\\n  %reldir%/languages/de_DE.ts \\\n  %reldir%/languages/en_US.ts \\\n  %reldir%/languages/es_ES.ts \\\n  %reldir%/languages/eu_ES.ts \\\n  %reldir%/languages/fr_FR.ts \\\n  %reldir%/languages/hu_HU.ts \\\n  %reldir%/languages/it_IT.ts \\\n  %reldir%/languages/ja_JP.ts \\\n  %reldir%/languages/lt_LT.ts \\\n  %reldir%/languages/nl_NL.ts \\\n  %reldir%/languages/pt_BR.ts \\\n  %reldir%/languages/pt_PT.ts \\\n  %reldir%/languages/ru_RU.ts \\\n  %reldir%/languages/sv_SE.ts \\\n  %reldir%/languages/tr_TR.ts \\\n  %reldir%/languages/uk_UA.ts \\\n  %reldir%/languages/zh_CN.ts\n\nLOCALES = $(patsubst %reldir%/languages/%.ts, %reldir%/languages/%.qm, $(TRANSLATIONS))\n\nnoinst_HEADERS += \\\n  %reldir%/liboctgui-build-info.h\n\ninclude %reldir%/src/module.mk\ninclude %reldir%/graphics/module.mk\ninclude %reldir%/qterminal/module.mk\n\nnodist_%canon_reldir%_liboctgui_la_SOURCES = \\\n  %reldir%/liboctgui-build-info.cc\n\n%canon_reldir%_liboctgui_la_CPPFLAGS = \\\n  $(AM_CPPFLAGS) \\\n  @OCTGUI_DLL_DEFS@ \\\n  -I%reldir% -I$(srcdir)/%reldir%\n\n%canon_reldir%_liboctgui_la_LIBADD = \\\n  %reldir%/qterminal/libqterminal.la \\\n  %reldir%/graphics/libgraphics.la \\\n  %reldir%/src/libgui-src.la \\\n  libinterp/liboctinterp.la \\\n  liboctave/liboctave.la \\\n  $(LIBOCTGUI_LINK_DEPS)\n\n## Increment the following version numbers as needed and according\n## to the rules in the etc/HACKING.md file:\n\n%canon_reldir%_liboctgui_current = 14\n%canon_reldir%_liboctgui_revision = 0\n%canon_reldir%_liboctgui_age = 0\n\n%canon_reldir%_liboctgui_version_info = $(%canon_reldir%_liboctgui_current):$(%canon_reldir%_liboctgui_revision):$(%canon_reldir%_liboctgui_age)\n\n%canon_reldir%_liboctgui_la_LDFLAGS = \\\n  $(AM_LDFLAGS) \\\n  -version-info $(%canon_reldir%_liboctgui_version_info) \\\n  $(NO_UNDEFINED_LDFLAG) \\\n  -bindir $(bindir) \\\n  $(LIBOCTGUI_LINK_OPTS) \\\n  $(WARN_LDFLAGS)\n\noctlocale_DATA += $(LOCALES)\n\nDIRSTAMP_FILES += \\\n  %reldir%/$(octave_dirstamp)\n\ndefine moc-command\n  rm -f $@-t $@ && \\\n  ( echo \"#if defined (HAVE_CONFIG_H)\"; \\\n    echo '#  include \"config.h\"'; \\\n    echo \"#endif\"; \\\n    $(MOC) $(MOCFLAGS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(MOC_OCTAVE_CPPFLAGS) $(MOC_CPPFLAGS) $(%canon_reldir%_liboctgui_la_CPPFLAGS) $< ) > $@-t && \\\n  mv $@-t $@\nendef\n\ndefine moc-h-command\n$(SED) -e 's/OCTAVE_BEGIN_NAMESPACE *(\\([^)]*\\))/namespace \\1 {/' \\\n         -e 's/OCTAVE_END_NAMESPACE *([^)]*)/}/' $< > $@\nendef\n\ndefine rcc-command\n  rm -f $@-t $@ && \\\n  ( echo \"#if defined (HAVE_CONFIG_H)\"; \\\n    echo '#  include \"config.h\"'; \\\n    echo \"#endif\"; \\\n    echo \"// Ignore unused variable warnings in generated code.\"; \\\n    echo \"#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\"; \\\n    echo \"#pragma GCC diagnostic ignored \\\"-Wunused-variable\\\"\"; \\\n    echo \"#endif\"; \\\n    QT_HASH_SEED=0 $(RCC) $(RCCFLAGS) -name $(@D) $< ) > $@-t && \\\n  mv $@-t $@\nendef\n\n.PRECIOUS: moc-%.h\n\nmoc-%.h: %.h\n\t$(AM_V_GEN)$(moc-h-command)\n\nmoc-%.cc: moc-%.h\n\t$(AM_V_GEN)$(moc-command)\n\nui-%.h: %.ui\n\t$(AM_V_GEN)$(UIC) $(UICFLAGS) -o $@ $<\n\nqrc-%.cc: %.qrc\n\t$(AM_V_GEN)$(rcc-command)\n\nAM_V_lrelease = $(am__v_lrelease_$(V))\nam__v_lrelease_ = $(am__v_lrelease_$(AM_DEFAULT_VERBOSITY))\nam__v_lrelease_0 = -silent\nam__v_lrelease_1 =\n\n%.qm: %.ts | %reldir%/languages/$(octave_dirstamp)\n\t$(AM_V_GEN)$(LRELEASE) $(LRELEASEFLAGS) $(AM_V_lrelease) -qm $@ $<\n\nDIRSTAMP_FILES += \\\n  %reldir%/languages/$(octave_dirstamp)\n\n%canon_reldir%_EXTRA_DIST += \\\n  $(TRANSLATIONS) \\\n  %reldir%/liboctgui-build-info.in.cc\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n\n%canon_reldir%_CLEANFILES += \\\n  $(LOCALES) \\\n  %reldir%/liboctgui-build-info.cc\n\nCLEANFILES += $(%canon_reldir%_CLEANFILES)\nDISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)\nMAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)\n\nlibgui-clean:\n\trm -f $(%canon_reldir%_CLEANFILES)\n\nlibgui-distclean: libgui-clean\n\trm -f $(%canon_reldir%_DISTCLEANFILES)\n\nlibgui-maintainer-clean: libgui-distclean\n\trm -f $(%canon_reldir%_MAINTAINERCLEANFILES)\n\n%reldir%/liboctgui-build-info.cc: %reldir%/liboctgui-build-info.in.cc HG-ID | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(build-info-commands)\n\nendif\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/LineFont.src",
    "content": "#2500: single horizontal line\n2500\n     \n     \n-----\n     \n     \n\n#2501: triple horizontal line\n2501\n     \n-----\n-----\n-----\n     \n\n#2502: single vertical line\n2502\n  |  \n  |  \n  |  \n  |  \n  |  \n\n#2503: triple vertical line\n2503\n ||| \n ||| \n ||| \n ||| \n ||| \n\n#2504-250B are dashed - not handled\n\n#250C: top-left corner (lines on bottom + right)\n250C\n     \n     \n  .--\n  |  \n  |  \n\n#250D: as above, but top line triple-width\n250D\n     \n  .--\n  .--\n  |--\n  |  \n\n#250E: now the vert line triple-width\n250E\n     \n     \n ..--\n ||| \n ||| \n\n#250F: and now both lines triple-width\n250F\n     \n .___\n |.--\n ||._\n ||| \n\n#2510: top-right corner\n2510\n     \n     \n--.  \n  |  \n  |  \n\n2511\n     \n==.  \n==.  \n==|  \n  | \n\n2512\n     \n     \n==.. \n ||| \n ||| \n\n2513\n     \n===. \n==.| \n=.|| \n ||| \n\n#2514: bottom-left corner\n2514\n  |  \n  |  \n  .==\n     \n     \n\n2515\n  |  \n  |==\n  |==\n  ===\n     \n\n\n2516\n ||| \n ||| \n |.==\n     \n     \n\n2517\n ||| \n ||.=\n |.==\n .===\n     \n\n#2518: bottm-right corner\n2518\n  |  \n  |  \n==.  \n     \n     \n\n2519\n  |  \n==|  \n==|  \n===  \n     \n\n\n251A\n ||| \n ||| \n==== \n     \n     \n\n251B\n ||| \n=.|| \n==.| \n===. \n     \n\n#251C: Join of vertical line and one from the right\n251C\n  |  \n  |  \n  |==\n  |  \n  |  \n\n251D\n  |  \n  |==\n  |==\n  |==\n  |  \n\n251E\n ||| \n ||| \n ||==\n  |  \n  |  \n\n251F\n  |  \n  |  \n ||==\n ||| \n ||| \n\n\n2520\n ||| \n ||| \n ||==\n ||| \n ||| \n\n2521\n ||| \n |||=\n ||==\n .|==\n  |  \n\n2522\n  |  \n .|==\n ||==\n |||=\n ||| \n\n2523\n ||| \n ||.=\n ||==\n ||.=\n ||| \n\n#2524: Join of vertical line and one from the left\n2524\n  |  \n  |  \n==|  \n  |  \n  |  \n\n2525\n  |  \n==|  \n==|  \n==|  \n  |  \n\n2526\n ||| \n ||| \n==+| \n  |  \n  |  \n\n2527\n  |  \n  |  \n==+| \n ||| \n ||| \n\n2528\n ||| \n ||| \n==+| \n ||| \n ||| \n\n2529\n ||| \n=+|| \n==+| \n===+ \n  |  \n\n252A\n  |  \n=+|| \n==+| \n===+ \n ||| \n\n252B\n |||\n=+|| \n==+| \n=+|| \n |||\n\n#252C: horizontal line joined to from below\n252C\n     \n     \n=====\n  |  \n  |  \n\n252D\n     \n===  \n==|==\n==|  \n  |  \n\n252E\n     \n  ===\n==|==\n  |==\n  |  \n\n252F\n     \n==+==\n==|==\n==|==\n  |  \n\n2530\n     \n=====\n=====\n==|==\n  |  \n\n2531\n     \n===| \n==||=\n=||| \n ||| \n\n2532\n     \n |===\n=||==\n ||==\n ||  \n\n2533\n     \n=====\n==|==\n=+|+=\n ||| \n\n#2534: bottom line, connected to from top\n2534\n  |\n  |\n=====\n     \n     \n\n2535\n  |\n==|\n=====\n===  \n    \n\n2536\n  |\n  |==\n=====\n  ===\n     \n\n2537\n  |\n==|==\n=====\n=====\n     \n\n2538\n |||\n |||\n=====\n     \n     \n\n2539\n |||\n==||\n=====\n===| \n    \n\n\n253A\n |||\n ||==\n=|===\n |===\n     \n\n253B\n |||\n==|==\n=====\n=====\n     \n\n#253C: vertical + horizontal lines intersecting\n253C\n  |  \n  |  \n=====\n  |  \n  |\n\n253D\n  |  \n==|  \n=====\n==|  \n  |\n\n253E\n  |  \n  |==\n=====\n  |==\n  |\n\n253F\n  |  \n==|==\n=====\n==|==\n  |\n\n2540\n ||| \n ||| \n=====\n  |  \n  |\n\n2541\n  |  \n  |  \n=====\n ||| \n |||\n\n2542\n ||| \n ||| \n=====\n ||| \n |||\n\n2543\n ||| \n=|||\n=====\n==|+ \n  |\n\n2544\n ||| \n ||==\n=====\n  |==\n  |\n\n2545\n  |\n==|+ \n=====\n=|||\n ||| \n\n2546\n  |\n  |==\n=====\n ||==\n ||| \n\n2547\n ||| \n=|||=\n=====\n=|||=\n  | \n\n2548\n  |  \n=|||=\n=====\n=|||=\n |||\n\n2549\n ||| \n=||| \n=====\n=||| \n |||\n\n254A\n ||| \n |||=\n=====\n |||=\n |||\n\n254B\n ||| \n=|||=\n=====\n=|||=\n |||\n\n#254C-254F are dashed\n2550\n     \n_____\n     \n_____\n     \n\n2551\n | | \n | |\n | |\n | |\n | |\n\n2552\n     \n  |--\n  |\n  |--\n  |\n\n2553\n     \n     \n ----\n | | \n | | \n\n2554\n     \n +---\n |\n + +-\n | |\n\n2555\n     \n--+\n  |  \n--+  \n  |  \n\n2556\n    \n    \n-+-+\n | |\n | |\n\n2557\n     \n---+ \n   | \n-+ |\n | |\n\n2558\n  |\n  +--\n  |\n  +--\n\n2559\n | | \n | | \n +-+-\n     \n     \n\n255A\n | | \n | +-\n |   \n +---\n     \n\n255B\n  |  \n--+  \n  | \n--+  \n     \n\n255C\n | | \n | | \n-+-+ \n    \n\n255D\n | | \n-+ | \n   |\n---+\n    \n\n255E\n  |\n  +--\n  |\n  +--\n  |\n\n255F\n | |\n | |\n | +-\n | |\n | |\n\n2560\n | |\n | +-\n | |\n | +-\n | |\n\n2561\n  |\n--+\n  |\n--+\n  |\n\n2562\n | | \n | |\n-+ +\n | |\n | |\n\n2563\n | |\n-+ |\n   |\n-+ |\n | |\n\n2564\n     \n-----\n     \n--+--\n  |\n\n2565\n     \n     \n-+-+-\n | | \n | |\n\n2566\n     \n-----\n     \n-+ +-\n | |\n\n2567\n  |  \n--+--\n     \n-----\n     \n\n2568\n | | \n | | \n-+-+-\n     \n     \n\n2569\n | | \n-+ +-\n     \n-----\n     \n\n256A\n  |  \n--+--\n  |  \n--+--\n  |\n\n256B\n | | \n | | \n-+-+-\n | | \n | | \n\n256C\n | | \n-+ +-\n\n-+ +-\n | | \n\n#256F-2570 are curly,\n#2571-2573 are slashes and X\n\n2574\n     \n     \n___  \n     \n     \n\n2575\n  |  \n  |  \n  |  \n     \n    \n\n2576\n     \n     \n  ___\n     \n     \n\n2577\n     \n    \n  |  \n  |  \n  |  \n\n2578\n     \n___  \n___  \n___  \n     \n\n2579\n ||| \n ||| \n ||| \n     \n    \n\n257A\n     \n  ___\n  ___\n  ___\n     \n\n257B\n     \n    \n ||| \n ||| \n ||| \n\n257C\n     \n  ___\n_____\n  ___\n     \n\n257D\n  |  \n  |  \n ||| \n ||| \n ||| \n\n257E\n     \n___  \n_____\n___  \n     \n\n257F\n ||| \n ||| \n ||| \n  |  \n  |  \n"
  },
  {
    "path": "libgui/qterminal/libqterminal/QTerminal.cc",
    "content": "/*\n\nCopyright (C) 2012-2019 Michael Goffioul.\nCopyright (C) 2012-2019 Jacob Dawid.\n\nThis file is part of QTerminal.\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not,\nsee <https://www.gnu.org/licenses/>.\n\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QAction>\n#include <QApplication>\n#include <QClipboard>\n#include <QColor>\n#include <QKeySequence>\n#include <QList>\n#include <QMenu>\n#include <QRegularExpression>\n#include <QStringList>\n#include <QWidget>\n\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-cs.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-settings.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"interpreter.h\"\n\n#include \"QTerminal.h\"\n#if defined (Q_OS_WIN32)\n# include \"win32/QWinTerminalImpl.h\"\n#else\n# include \"unix/QUnixTerminalImpl.h\"\n#endif\n\nQTerminal *\nQTerminal::create (QWidget *p)\n{\n#if defined (Q_OS_WIN32)\n  QTerminal *terminal = new QWinTerminalImpl (p);\n#else\n  QTerminal *terminal = new QUnixTerminalImpl (p);\n#endif\n\n  // FIXME: this function should probably be called from or part of the\n  // QTerminal constructor?\n\n  terminal->construct ();\n\n  return terminal;\n}\n\n// slot for the terminal's context menu\nvoid\nQTerminal::handleCustomContextMenuRequested (const QPoint& at)\n  {\n    QClipboard * cb = QApplication::clipboard ();\n    QString selected_text = selectedText();\n    bool has_selected_text = ! selected_text.isEmpty ();\n\n    _edit_action->setVisible (false);\n    m_edit_selected_action->setVisible (false);\n    m_help_selected_action->setVisible (false);\n    m_doc_selected_action->setVisible (false);\n\n#if defined (Q_OS_WIN32)\n    // include this when in windows because there is no filter for\n    // detecting links and error messages yet\n    if (has_selected_text)\n      {\n        QRegularExpression file {\"(?:[ \\\\t]+)(\\\\S+) at line (\\\\d+) column (?:\\\\d+)\"};\n        QRegularExpressionMatch match = file.match (selected_text);\n\n        if (match.hasMatch ())\n          {\n            QString file_name = match.captured (1);\n            QString line = match.captured (2);\n\n            _edit_action->setVisible (true);\n            _edit_action->setText (tr (\"Edit %1 at line %2\")\n                                   .arg (file_name).arg (line));\n\n            QStringList data;\n            data << file_name << line;\n            _edit_action->setData (data);\n          }\n      }\n#endif\n\n    if (has_selected_text)\n      {\n        // Find first word in selected text, trim everything else\n        QRegularExpression expr {\"(\\\\w+)\"};\n        QRegularExpressionMatch match = expr.match (selected_text);\n\n        if (match.hasMatch ())\n          {\n            QString expr_found = match.captured (1);\n\n            m_edit_selected_action->setVisible (true);\n            m_edit_selected_action->setText (tr (\"Edit \\\"%1\\\"\").arg (expr_found));\n            m_edit_selected_action->setData (expr_found);\n\n            m_help_selected_action->setVisible (true);\n            m_help_selected_action->setText (tr (\"Help on \\\"%1\\\"\").arg (expr_found));\n            m_help_selected_action->setData (expr_found);\n          }\n\n        // Grab all of selected text, but trim leading non-word characters\n        // and trailing whitespace\n        expr.setPattern (\"(\\\\w.*)\\\\s*$\");\n        match = expr.match (selected_text);\n        if (match.hasMatch ())\n          {\n            QString expr_found = match.captured (1);\n\n            m_doc_selected_action->setVisible (true);\n            m_doc_selected_action->setText (tr (\"Documentation on \\\"%1\\\"\")\n                                            .arg (expr_found));\n            m_doc_selected_action->setData (expr_found);\n          }\n      }\n\n    _paste_action->setEnabled (cb->text().length() > 0);\n    _copy_action->setEnabled (has_selected_text);\n    _run_selection_action->setVisible (has_selected_text);\n\n    // Get the actions of any hotspots the filters may have found\n    QList<QAction*> actions = get_hotspot_actions (at);\n    if (actions.length ())\n      _contextMenu->addSeparator ();\n    for (int i = 0; i < actions.length (); i++)\n      _contextMenu->addAction (actions.at(i));\n\n    // Finally, show the context menu\n    _contextMenu->exec (mapToGlobal (at));\n\n    // Cleaning up, remove actions of the hotspot\n    for (int i = 0; i < actions.length (); i++)\n      _contextMenu->removeAction (actions.at(i));\n  }\n\n// slot for running the selected code\nvoid\nQTerminal::run_selection ()\n{\n  QStringList commands = selectedText ().split (QRegularExpression {\"[\\r\\n]\"},\n#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)\n                                                Qt::SkipEmptyParts);\n#else\n                                                QString::SkipEmptyParts);\n#endif\n  for (int i = 0; i < commands.size (); i++)\n    Q_EMIT execute_command_in_terminal_signal (commands.at (i));\n\n}\n\n// slot for edit files in error messages\nvoid\nQTerminal::edit_file ()\n{\n  QString file = _edit_action->data ().toStringList ().at (0);\n  int line = _edit_action->data ().toStringList ().at (1).toInt ();\n\n  Q_EMIT edit_mfile_request (file,line);\n}\n\n// slot for edit selected function names\nvoid QTerminal::edit_selected ()\n{\n  QString file = m_edit_selected_action->data ().toString ();\n\n  Q_EMIT edit_mfile_request (file,0);\n}\n\n// slot for showing help on selected epxression\nvoid QTerminal::help_on_expression ()\n{\n  QString expr = m_help_selected_action->data ().toString ();\n\n  Q_EMIT execute_command_in_terminal_signal (\"help \" + expr);\n}\n\n// slot for showing documentation on selected epxression\nvoid QTerminal::doc_on_expression ()\n{\n  std::string expr = m_doc_selected_action->data ().toString ().toStdString ();\n\n  Q_EMIT interpreter_event\n    ([expr] (octave::interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       octave::F__event_manager_show_documentation__ (interp, ovl (expr));\n     });\n}\n\nvoid\nQTerminal::notice_settings ()\n{\n  octave::gui_settings settings;\n\n  // Set terminal font:\n  QFont term_font = QFont ();\n  term_font.setStyleHint (QFont::TypeWriter);\n  QString default_font = settings.string_value (global_mono_font);\n  term_font.setFamily\n    (settings.value (cs_font.settings_key (), default_font).toString ());\n  term_font.setPointSize\n    (settings.int_value (cs_font_size));\n  setTerminalFont (term_font);\n\n  QFontMetrics metrics (term_font);\n  setMinimumSize (metrics.maxWidth ()*16, metrics.height ()*3);\n\n  QString cursor_type\n    = settings.string_value (cs_cursor);\n\n  bool cursor_blinking;\n  if (settings.contains (global_cursor_blinking.settings_key ()))\n    cursor_blinking = settings.bool_value (global_cursor_blinking);\n  else\n    cursor_blinking = settings.bool_value (cs_cursor_blinking);\n\n  for (int ct = IBeamCursor; ct <= UnderlineCursor; ct++)\n    {\n      if (cursor_type.toStdString () == cs_cursor_types[ct])\n        {\n          setCursorType ((CursorType) ct, cursor_blinking);\n          break;\n        }\n    }\n\n  bool cursorUseForegroundColor\n    = settings.bool_value (cs_cursor_use_fgcol);\n\n  int mode = settings.int_value (cs_color_mode);\n\n  setForegroundColor (settings.color_value (cs_colors[0], mode));\n\n  setBackgroundColor (settings.color_value (cs_colors[1], mode));\n\n  setSelectionColor (settings.color_value (cs_colors[2], mode));\n\n  setCursorColor (cursorUseForegroundColor,\n                  settings.color_value (cs_colors[3], mode));\n\n  setScrollBufferSize (settings.int_value (cs_hist_buffer));\n\n  // If the Copy shortcut is Ctrl+C, then the Copy action also emits\n  // a signal for interrupting the current code executed by the worker.\n  // If the Copy shortcut is not Ctrl+C, an extra interrupt action is\n  // set up for emitting the interrupt signal.\n\n  QString sc = settings.sc_value (sc_main_edit_copy);\n\n  //  Dis- or enable extra interrupt action: We need an extra option when\n  //  copy shortcut is not Ctrl-C or when global shortcuts (like copy) are\n  //  disabled.\n  bool extra_ir_action\n      = (sc != QKeySequence (Qt::ControlModifier | Qt::Key_C).toString ())\n        || settings.bool_value (sc_prevent_rl_conflicts);\n\n  _interrupt_action->setEnabled (extra_ir_action);\n  has_extra_interrupt (extra_ir_action);\n\n  // check whether shortcut Ctrl-D is in use by the main-window\n  bool ctrld = settings.bool_value (sc_main_ctrld);\n  _nop_action->setEnabled (! ctrld);\n}\n\nvoid\nQTerminal::construct ()\n{\n  octave::gui_settings settings;\n\n  // context menu\n  setContextMenuPolicy (Qt::CustomContextMenu);\n\n  _contextMenu = new QMenu (this);\n\n  _copy_action\n    = _contextMenu->addAction (settings.icon (\"edit-copy\"), tr (\"Copy\"), this,\n                               SLOT (copyClipboard ()));\n\n  _paste_action\n    = _contextMenu->addAction (settings.icon (\"edit-paste\"), tr (\"Paste\"), this,\n                               SLOT (pasteClipboard ()));\n\n  _contextMenu->addSeparator ();\n\n  _selectall_action\n    = _contextMenu->addAction (tr (\"Select All\"), this, SLOT (selectAll ()));\n\n  _run_selection_action\n    = _contextMenu->addAction (tr (\"Run Selection\"), this,\n                               SLOT (run_selection ()));\n\n  m_edit_selected_action\n    = _contextMenu->addAction (tr (\"Edit selection\"), this,\n                               SLOT (edit_selected ()));\n  m_help_selected_action\n    = _contextMenu->addAction (tr (\"Help on selection\"), this,\n                               SLOT (help_on_expression ()));\n  m_doc_selected_action\n    = _contextMenu->addAction (tr (\"Documentation on selection\"), this,\n                               SLOT (doc_on_expression ()));\n\n  _edit_action = _contextMenu->addAction (tr (\"\"), this, SLOT (edit_file ()));\n\n  _contextMenu->addSeparator ();\n\n  _contextMenu->addAction (tr (\"Clear Window\"), this,\n                           SIGNAL (clear_command_window_request ()));\n\n  connect (this, SIGNAL (customContextMenuRequested (QPoint)),\n           this, SLOT (handleCustomContextMenuRequested (QPoint)));\n\n  // extra interrupt action\n  _interrupt_action = new QAction (this);\n  addAction (_interrupt_action);\n\n  _interrupt_action->setShortcut\n    (QKeySequence (Qt::ControlModifier | Qt::Key_C));\n  _interrupt_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);\n\n  bool ok = connect (_interrupt_action, SIGNAL (triggered ()),\n           this, SLOT (terminal_interrupt ()));\n\n  // dummy (nop) action catching Ctrl-D in terminal, no connection\n  _nop_action = new QAction (this);\n  addAction (_nop_action);\n\n  _nop_action->setShortcut (QKeySequence (Qt::ControlModifier | Qt::Key_D));\n  _nop_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/QTerminal.h",
    "content": "/*\n\nCopyright (C) 2012-2019 Michael Goffioul.\nCopyright (C) 2012-2019 Jacob Dawid.\n\nThis file is part of QTerminal.\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not,\nsee <https://www.gnu.org/licenses/>.\n\n*/\n\n#ifndef QTERMINAL_H\n#define QTERMINAL_H\n\n#include \"octave-config.h\"\n\n#include <QColor>\n#include <QList>\n#include <QPoint>\n#include <QString>\n#include <QWidget>\n\n#include \"qt-interpreter-events.h\"\n\nclass QMenu;\nclass QAction;\n\nclass QTerminal : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  static QTerminal * create (QWidget *xparent);\n\n  virtual ~QTerminal () = default;\n\n  virtual void setTerminalFont (const QFont& font) = 0;\n\n  virtual void setSize (int h, int v) = 0;\n\n  virtual void sendText (const QString& text) = 0;\n\n  virtual QString selectedText () = 0;\n\n  virtual void has_extra_interrupt (bool extra) = 0;\n\n  virtual QList<QAction *> get_hotspot_actions (const QPoint&)\n  { return QList<QAction *> (); }\n\n  enum CursorType\n  {\n    IBeamCursor,\n    BlockCursor,\n    UnderlineCursor\n  };\n\n  virtual void setCursorType (CursorType type, bool blinking)\n  {\n    // Provide empty default impl in order to avoid conflicts with the\n    // win impl.\n\n    Q_UNUSED (type);\n    Q_UNUSED (blinking);\n  }\n\n  virtual void setBackgroundColor (const QColor& color) = 0;\n\n  virtual void setForegroundColor (const QColor& color) = 0;\n\n  virtual void setSelectionColor (const QColor& color) = 0;\n\n  virtual void setCursorColor (bool useForegroundColor,\n                               const QColor& color) = 0;\n\n  virtual void setScrollBufferSize(int value=1000) = 0;\n\nQ_SIGNALS:\n\n  void report_status_message (const QString&);\n\n  void interrupt_signal ();\n\n  void edit_mfile_request (const QString&, int);\n\n  void show_doc_signal (const QString&);\n\n  void execute_command_in_terminal_signal (const QString&);\n\n  void request_edit_mfile_signal (const QString&, int);\n\n  void request_open_file_signal (const QString&, const QString&, int);\n\n  void set_screen_size_signal (int, int);\n\n  void clear_command_window_request ();\n\n  void interpreter_event (const octave::fcn_callback& fcn);\n  void interpreter_event (const octave::meth_callback& meth);\n\npublic Q_SLOTS:\n\n  virtual void copyClipboard () = 0;\n\n  virtual void pasteClipboard () = 0;\n\n  virtual void selectAll () = 0;\n\n  virtual void handleCustomContextMenuRequested (const QPoint& at);\n\n  void notice_settings ();\n\n  virtual void init_terminal_size () { }\n\n  void terminal_interrupt () { Q_EMIT interrupt_signal (); }\n\n  void run_selection ();\n\n  void edit_file ();\n\n  void edit_selected ();\n\n  void help_on_expression ();\n\n  void doc_on_expression ();\n\n  virtual void handle_visibility_changed (bool) { }\n\nprotected:\n\n  QTerminal (QWidget *xparent = nullptr)\n    : QWidget (xparent)\n  { }\n\n  void construct ();\n\nprivate:\n\n  QMenu *_contextMenu;\n  QAction * _copy_action;\n  QAction * _paste_action;\n  QAction * _selectall_action;\n  QAction * _edit_action;\n  QAction * _run_selection_action;\n  QAction * m_edit_selected_action;\n  QAction * m_help_selected_action;\n  QAction * m_doc_selected_action;\n\n  QAction *_interrupt_action;\n  QAction *_nop_action;\n};\n\n#endif // QTERMINAL_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/README",
    "content": "lib.pro is a *.pro-file for qmake\n\nIt produces static lib (libqtermwidget.a) only.\nFor creating shared lib (*.so) uncomment \"dll\" in \"CONFIG\" line in *.pro-file\n\nLibrary was tested both with HAVE_POSIX_OPENPT and HAVE_GETPT precompiler directives,\ndefined in \"DEFINES\" line. You should select variant which would be correct for your system.\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/default.keytab",
    "content": "# [README.default.Keytab] Buildin Keyboard Table\n#\n# To customize your keyboard, copy this file to something\n# ending with .keytab and change it to meet you needs.\n# Please read the README.KeyTab and the README.keyboard\n# in this case.\n#\n# --------------------------------------------------------------\n\nkeyboard \"Default (XFree 4)\"\n\n# --------------------------------------------------------------\n#\n# Note that this particular table is a \"risc\" version made to\n# ease customization without bothering with obsolete details.\n# See VT100.keytab for the more hairy stuff.\n#\n# --------------------------------------------------------------\n\n# common keys\n\nkey Escape             : \"\\E\"\n\nkey Tab   -Shift       : \"\\t\"\nkey Tab   +Shift+Ansi  : \"\\E[Z\"\nkey Tab   +Shift-Ansi  : \"\\t\"\nkey Backtab     +Ansi  : \"\\E[Z\"\nkey Backtab     -Ansi  : \"\\t\"\n\nkey Return-Shift-NewLine : \"\\r\"\nkey Return-Shift+NewLine : \"\\r\\n\"\n\nkey Return+Shift         : \"\\EOM\"\n\n# Backspace and Delete codes are preserving CTRL-H.\n\nkey Backspace      : \"\\x7f\"\n\n# Arrow keys in VT52 mode\n# shift up/down are reserved for scrolling.\n# shift left/right are reserved for switching between tabs (this is hardcoded).\n\nkey Up   -Shift-Ansi : \"\\EA\"\nkey Down -Shift-Ansi : \"\\EB\"\nkey Right-Shift-Ansi : \"\\EC\"\nkey Left -Shift-Ansi : \"\\ED\"\n\n# Arrow keys in ANSI mode with Application - and Normal Cursor Mode)\n\nkey Up    -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOA\"\nkey Down  -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOB\"\nkey Right -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOC\"\nkey Left  -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOD\"\n\nkey Up    -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[A\"\nkey Down  -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[B\"\nkey Right -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[C\"\nkey Left  -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[D\"\n\nkey Up    -Shift+AnyMod+Ansi                     : \"\\E[1;*A\"\nkey Down  -Shift+AnyMod+Ansi                     : \"\\E[1;*B\"\nkey Right -Shift+AnyMod+Ansi                     : \"\\E[1;*C\"\nkey Left  -Shift+AnyMod+Ansi                     : \"\\E[1;*D\"\n\n# other grey PC keys\n\nkey Enter+NewLine : \"\\r\\n\"\nkey Enter-NewLine : \"\\r\"\n\nkey Home        -AnyMod     -AppCuKeys           : \"\\E[H\"  \nkey End         -AnyMod     -AppCuKeys           : \"\\E[F\"  \nkey Home        -AnyMod     +AppCuKeys           : \"\\EOH\"  \nkey End         -AnyMod     +AppCuKeys           : \"\\EOF\"  \nkey Home        +AnyMod                          : \"\\E[1;*H\"\nkey End         +AnyMod                          : \"\\E[1;*F\"\n\nkey Insert      -AnyMod                          : \"\\E[2~\"\nkey Delete      -AnyMod                          : \"\\E[3~\"\nkey Insert      +AnyMod                          : \"\\E[2;*~\"\nkey Delete      +AnyMod                          : \"\\E[3;*~\"\n\nkey Prior -Shift-AnyMod                          : \"\\E[5~\"\nkey Next  -Shift-AnyMod                          : \"\\E[6~\"\nkey Prior -Shift+AnyMod                          : \"\\E[5;*~\"\nkey Next  -Shift+AnyMod                          : \"\\E[6;*~\"\n\n# Function keys\nkey F1          -AnyMod                          : \"\\EOP\"\nkey F2          -AnyMod                          : \"\\EOQ\"\nkey F3          -AnyMod                          : \"\\EOR\"\nkey F4          -AnyMod                          : \"\\EOS\"\nkey F5          -AnyMod                          : \"\\E[15~\"\nkey F6          -AnyMod                          : \"\\E[17~\"\nkey F7          -AnyMod                          : \"\\E[18~\"\nkey F8          -AnyMod                          : \"\\E[19~\"\nkey F9          -AnyMod                          : \"\\E[20~\"\nkey F10         -AnyMod                          : \"\\E[21~\"\nkey F11         -AnyMod                          : \"\\E[23~\"\nkey F12         -AnyMod                          : \"\\E[24~\"\n\nkey F1          +AnyMod                          : \"\\EO*P\"\nkey F2          +AnyMod                          : \"\\EO*Q\"\nkey F3          +AnyMod                          : \"\\EO*R\"\nkey F4          +AnyMod                          : \"\\EO*S\"\nkey F5          +AnyMod                          : \"\\E[15;*~\"\nkey F6          +AnyMod                          : \"\\E[17;*~\"\nkey F7          +AnyMod                          : \"\\E[18;*~\"\nkey F8          +AnyMod                          : \"\\E[19;*~\"\nkey F9          +AnyMod                          : \"\\E[20;*~\"\nkey F10         +AnyMod                          : \"\\E[21;*~\"\nkey F11         +AnyMod                          : \"\\E[23;*~\"\nkey F12         +AnyMod                          : \"\\E[24;*~\"\n\n# Work around dead keys\n\nkey Space +Control : \"\\x00\"\n\n# Some keys are used by konsole to cause operations.\n# The scroll* operations refer to the history buffer.\n\nkey Up    +Shift-AppScreen  : scrollLineUp\nkey Prior +Shift-AppScreen  : scrollPageUp\nkey Down  +Shift-AppScreen  : scrollLineDown\nkey Next  +Shift-AppScreen  : scrollPageDown\n\nkey ScrollLock     : scrollLock\n\n# keypad characters are not offered differently by Qt.\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/kb-layouts/default.keytab",
    "content": "# [README.default.Keytab] Buildin Keyboard Table\n#\n# To customize your keyboard, copy this file to something\n# ending with .keytab and change it to meet you needs.\n# Please read the README.KeyTab and the README.keyboard\n# in this case.\n#\n# --------------------------------------------------------------\n\nkeyboard \"Default (XFree 4)\"\n\n# --------------------------------------------------------------\n#\n# Note that this particular table is a \"risc\" version made to\n# ease customization without bothering with obsolete details.\n# See VT100.keytab for the more hairy stuff.\n#\n# --------------------------------------------------------------\n\n# common keys\n\nkey Escape             : \"\\E\"\n\nkey Tab   -Shift       : \"\\t\"\nkey Tab   +Shift+Ansi  : \"\\E[Z\"\nkey Tab   +Shift-Ansi  : \"\\t\"\nkey Backtab     +Ansi  : \"\\E[Z\"\nkey Backtab     -Ansi  : \"\\t\"\n\nkey Return-Shift-NewLine : \"\\r\"\nkey Return-Shift+NewLine : \"\\r\\n\"\n\nkey Return+Shift         : \"\\EOM\"\n\n# Backspace and Delete codes are preserving CTRL-H.\n\nkey Backspace      : \"\\x7f\"\n\n# Arrow keys in VT52 mode\n# shift up/down are reserved for scrolling.\n# shift left/right are reserved for switching between tabs (this is hardcoded).\n\nkey Up   -Shift-Ansi : \"\\EA\"\nkey Down -Shift-Ansi : \"\\EB\"\nkey Right-Shift-Ansi : \"\\EC\"\nkey Left -Shift-Ansi : \"\\ED\"\n\n# Arrow keys in ANSI mode with Application - and Normal Cursor Mode)\n\nkey Up    -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOA\"\nkey Down  -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOB\"\nkey Right -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOC\"\nkey Left  -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOD\"\n\nkey Up    -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[A\"\nkey Down  -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[B\"\nkey Right -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[C\"\nkey Left  -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[D\"\n\nkey Up    -Shift+AnyMod+Ansi                     : \"\\E[1;*A\"\nkey Down  -Shift+AnyMod+Ansi                     : \"\\E[1;*B\"\nkey Right -Shift+AnyMod+Ansi                     : \"\\E[1;*C\"\nkey Left  -Shift+AnyMod+Ansi                     : \"\\E[1;*D\"\n\n# other grey PC keys\n\nkey Enter+NewLine : \"\\r\\n\"\nkey Enter-NewLine : \"\\r\"\n\nkey Home        -AnyMod     -AppCuKeys           : \"\\E[H\"  \nkey End         -AnyMod     -AppCuKeys           : \"\\E[F\"  \nkey Home        -AnyMod     +AppCuKeys           : \"\\EOH\"  \nkey End         -AnyMod     +AppCuKeys           : \"\\EOF\"  \nkey Home        +AnyMod                          : \"\\E[1;*H\"\nkey End         +AnyMod                          : \"\\E[1;*F\"\n\nkey Insert      -AnyMod                          : \"\\E[2~\"\nkey Delete      -AnyMod                          : \"\\E[3~\"\nkey Insert      +AnyMod                          : \"\\E[2;*~\"\nkey Delete      +AnyMod                          : \"\\E[3;*~\"\n\nkey Prior -Shift-AnyMod                          : \"\\E[5~\"\nkey Next  -Shift-AnyMod                          : \"\\E[6~\"\nkey Prior -Shift+AnyMod                          : \"\\E[5;*~\"\nkey Next  -Shift+AnyMod                          : \"\\E[6;*~\"\n\n# Function keys\nkey F1          -AnyMod                          : \"\\EOP\"\nkey F2          -AnyMod                          : \"\\EOQ\"\nkey F3          -AnyMod                          : \"\\EOR\"\nkey F4          -AnyMod                          : \"\\EOS\"\nkey F5          -AnyMod                          : \"\\E[15~\"\nkey F6          -AnyMod                          : \"\\E[17~\"\nkey F7          -AnyMod                          : \"\\E[18~\"\nkey F8          -AnyMod                          : \"\\E[19~\"\nkey F9          -AnyMod                          : \"\\E[20~\"\nkey F10         -AnyMod                          : \"\\E[21~\"\nkey F11         -AnyMod                          : \"\\E[23~\"\nkey F12         -AnyMod                          : \"\\E[24~\"\n\nkey F1          +AnyMod                          : \"\\EO*P\"\nkey F2          +AnyMod                          : \"\\EO*Q\"\nkey F3          +AnyMod                          : \"\\EO*R\"\nkey F4          +AnyMod                          : \"\\EO*S\"\nkey F5          +AnyMod                          : \"\\E[15;*~\"\nkey F6          +AnyMod                          : \"\\E[17;*~\"\nkey F7          +AnyMod                          : \"\\E[18;*~\"\nkey F8          +AnyMod                          : \"\\E[19;*~\"\nkey F9          +AnyMod                          : \"\\E[20;*~\"\nkey F10         +AnyMod                          : \"\\E[21;*~\"\nkey F11         +AnyMod                          : \"\\E[23;*~\"\nkey F12         +AnyMod                          : \"\\E[24;*~\"\n\n# Work around dead keys\n\nkey Space +Control : \"\\x00\"\n\n# Some keys are used by konsole to cause operations.\n# The scroll* operations refer to the history buffer.\n\nkey Up    +Shift-AppScreen  : scrollLineUp\nkey Prior +Shift-AppScreen  : scrollPageUp\nkey Down  +Shift-AppScreen  : scrollLineDown\nkey Next  +Shift-AppScreen  : scrollPageDown\n\n#key Up    +Shift  : scrollLineUp\n#key Prior +Shift  : scrollPageUp\n#key Down  +Shift  : scrollLineDown\n#key Next  +Shift  : scrollPageDown\n\nkey ScrollLock     : scrollLock\n\n# keypad characters are not offered differently by Qt.\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/kb-layouts/linux.keytab",
    "content": "# [linux.keytab] Konsole Keyboard Table (Linux console keys)\n#\n# --------------------------------------------------------------\n\n# NOT TESTED, MAY NEED SOME CLEANUPS\nkeyboard \"Linux console\"\n\n# --------------------------------------------------------------\n#\n# This configuration table allows to customize the\n# meaning of the keys.\n#\n# The syntax is that each entry has the form : \n#\n#   \"key\" Keyname { (\"+\"|\"-\") Modename } \":\" (String|Operation)\n#\n# Keynames are those defined in <qnamespace.h> with the\n# \"Qt::Key_\" removed. (We'd better insert the list here)\n#\n# Mode names are : \n#\n# - Shift\n# - Alt\n# - Control\n#\n#   The VT100 emulation has two modes that can affect the\n#   sequences emitted by certain keys. These modes are\n#   under control of the client program.\n#   \n# - Newline     : effects Return and Enter key.\n# - Application : effects Up and Down key.\n#\n# - Ansi        : effects Up and Down key (This is for VT52, really).\n#\n# Operations are\n#\n# - scrollUpLine\n# - scrollUpPage\n# - scrollDownLine\n# - scrollDownPage\n#\n# - emitSelection\n#\n# If the key is not found here, the text of the\n# key event as provided by QT is emitted, possibly\n# preceeded by ESC if the Alt key is pressed.\n#\n# --------------------------------------------------------------\n\nkey Escape : \"\\E\"\nkey Tab    : \"\\t\"\n\n# VT100 can add an extra \\n after return.\n# The NewLine mode is set by an escape sequence.\n\nkey Return-NewLine : \"\\r\"  \nkey Return+NewLine : \"\\r\\n\"\n\n# Some desperately try to save the ^H.\n\nkey Backspace : \"\\x7f\"\nkey Delete    : \"\\E[3~\"\n\n# These codes are for the VT52 mode of VT100\n# The Ansi mode (i.e. VT100 mode) is set by\n# an escape sequence\n\nkey Up   -Shift-Ansi : \"\\EA\"\nkey Down -Shift-Ansi : \"\\EB\"\nkey Right-Shift-Ansi : \"\\EC\"\nkey Left -Shift-Ansi : \"\\ED\"\n\n# VT100 emits a mode bit together\n# with the arrow keys.The AppCuKeys\n# mode is set by an escape sequence.\n\nkey Up   -Shift+Ansi+AppCuKeys : \"\\EOA\"\nkey Down -Shift+Ansi+AppCuKeys : \"\\EOB\"\nkey Right-Shift+Ansi+AppCuKeys : \"\\EOC\"\nkey Left -Shift+Ansi+AppCuKeys : \"\\EOD\"\n\nkey Up   -Shift+Ansi-AppCuKeys : \"\\E[A\"\nkey Down -Shift+Ansi-AppCuKeys : \"\\E[B\"\nkey Right-Shift+Ansi-AppCuKeys : \"\\E[C\"\nkey Left -Shift+Ansi-AppCuKeys : \"\\E[D\"\n\n# linux functions keys F1-F5 differ from xterm\n\nkey F1 : \"\\E[[A\" \nkey F2 : \"\\E[[B\" \nkey F3 : \"\\E[[C\" \nkey F4 : \"\\E[[D\" \nkey F5 : \"\\E[[E\" \n\nkey F6     : \"\\E[17~\" \nkey F7     : \"\\E[18~\" \nkey F8     : \"\\E[19~\" \nkey F9     : \"\\E[20~\" \nkey F10    : \"\\E[21~\" \nkey F11    : \"\\E[23~\" \nkey F12    : \"\\E[24~\" \n\nkey Home   : \"\\E[1~\"  \nkey End    : \"\\E[4~\"  \n\nkey Prior -Shift : \"\\E[5~\"  \nkey Next  -Shift : \"\\E[6~\"  \nkey Insert-Shift : \"\\E[2~\"  \n\n# Keypad-Enter. See comment on Return above.\n\nkey Enter+NewLine : \"\\r\\n\"\nkey Enter-NewLine : \"\\r\"  \n\nkey Space +Control : \"\\x00\"\n\n# some of keys are used by konsole.\n\nkey Up    +Shift   : scrollLineUp\nkey Prior +Shift   : scrollPageUp\nkey Down  +Shift   : scrollLineDown\nkey Next  +Shift   : scrollPageDown\n\nkey ScrollLock     : scrollLock\n\n#----------------------------------------------------------\n\n# keypad characters as offered by Qt\n# cannot be recognized as such.\n\n#----------------------------------------------------------\n\n# Following other strings as emitted by konsole.\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/kb-layouts/vt420pc.keytab",
    "content": "# [vt420pc.keytab] Konsole Keyboard Table (VT420pc keys)\n# adapted by ferdinand gassauer f.gassauer@aon.at\n# Nov 2000\n#\n################################################################\n#\n# The escape sequences emmited by the \n# keys Shift+F1 to Shift+F12 might not fit your needs\n#\n################# IMPORTANT NOTICE #############################\n# the key bindings (Kcontrol -> look and feel -> keybindgs) \n# overrule the settings in this file. The key bindings might be \n# changed by the user WITHOUT notification of the maintainer of\n# the keytab file. Konsole will not work as expected by \n# the maintainer of the keytab file.\n################################################################\n#\n# --------------------------------------------------------------\n\nkeyboard \"DEC VT420 Terminal\"\n\n# --------------------------------------------------------------\n#\n# This configuration table allows to customize the\n# meaning of the keys.\n#\n# The syntax is that each entry has the form : \n#\n#   \"key\" Keyname { (\"+\"|\"-\") Modename } \":\" (String|Operation)\n#\n# Keynames are those defined in <qnamespace.h> with the\n# \"Qt::Key_\" removed. (We'd better insert the list here)\n#\n# Mode names are : \n#\n# - Shift\n# - Alt\n# - Control\n#\n#   The VT100 emulation has two modes that can affect the\n#   sequences emitted by certain keys. These modes are\n#   under control of the client program.\n#   \n# - Newline     : effects Return and Enter key.\n# - Application : effects Up and Down key.\n#\n# - Ansi        : effects Up and Down key (This is for VT52, really).\n#\n# Operations are\n#\n# - scrollUpLine\n# - scrollUpPage\n# - scrollDownLine\n# - scrollDownPage\n#\n# - emitSelection\n#\n# If the key is not found here, the text of the\n# key event as provided by QT is emitted, possibly\n# preceeded by ESC if the Alt key is pressed.\n#\n# --------------------------------------------------------------\n\nkey Escape : \"\\E\"\nkey Tab    : \"\\t\"\nkey Backtab: \"\\E[Z\"\n\n# VT100 can add an extra \\n after return.\n# The NewLine mode is set by an escape sequence.\n\nkey Return-NewLine : \"\\r\"  \nkey Return+NewLine : \"\\r\\n\"\n\n# Some desperately try to save the ^H.\n# may be not everyone wants this\n\nkey Backspace : \"\\x08\"  # Control H\nkey Delete    : \"\\x7f\"\n\n# These codes are for the VT420pc\n# The Ansi mode (i.e. VT100 mode) is set by\n# an escape sequence\n\nkey Up   -Shift-Ansi : \"\\EA\"\nkey Down -Shift-Ansi : \"\\EB\"\nkey Right-Shift-Ansi : \"\\EC\"\nkey Left -Shift-Ansi : \"\\ED\"\n\n# VT100 emits a mode bit together\n# with the arrow keys.The AppCuKeys\n# mode is set by an escape sequence.\n\nkey Up   -Shift+Ansi+AppCuKeys : \"\\EOA\"\nkey Down -Shift+Ansi+AppCuKeys : \"\\EOB\"\nkey Right-Shift+Ansi+AppCuKeys : \"\\EOC\"\nkey Left -Shift+Ansi+AppCuKeys : \"\\EOD\"\n\nkey Up   -Shift+Ansi-AppCuKeys : \"\\E[A\"\nkey Down -Shift+Ansi-AppCuKeys : \"\\E[B\"\nkey Right-Shift+Ansi-AppCuKeys : \"\\E[C\"\nkey Left -Shift+Ansi-AppCuKeys : \"\\E[D\"\n\n# function keys \n\nkey F1 -Shift    : \"\\E[11~\"  \nkey F2 -Shift    : \"\\E[12~\"\nkey F3 -Shift    : \"\\E[13~\"\nkey F4 -Shift    : \"\\E[14~\"\nkey F5 -Shift    : \"\\E[15~\"\nkey F6 -Shift    : \"\\E[17~\"\nkey F7 -Shift    : \"\\E[18~\"\nkey F8 -Shift    : \"\\E[19~\"\nkey F9 -Shift    : \"\\E[20~\"\nkey F10-Shift    : \"\\E[21~\"\nkey F11-Shift    : \"\\E[23~\"\nkey F12-Shift    : \"\\E[24~\"  \n#\n# Shift F1-F12\n#\nkey F1 +Shift    : \"\\E[11;2~\"\nkey F2 +Shift    : \"\\E[12;2~\"\nkey F3 +Shift    : \"\\E[13;2~\"\nkey F4 +Shift    : \"\\E[14;2~\"\nkey F5 +Shift    : \"\\E[15;2~\"\nkey F6 +Shift    : \"\\E[17;2~\" \nkey F7 +Shift    : \"\\E[18;2~\" \nkey F8 +Shift    : \"\\E[19;2~\" \nkey F9 +Shift    : \"\\E[20;2~\" \nkey F10+Shift    : \"\\E[21;2~\" \nkey F11+Shift    : \"\\E[23;2~\" \nkey F12+Shift    : \"\\E[24;2~\" \n\nkey Home   : \"\\E[H\"  \nkey End    : \"\\E[F\"  \n\nkey Prior -Shift : \"\\E[5~\"  \nkey Next  -Shift : \"\\E[6~\"  \nkey Insert-Shift : \"\\E[2~\"  \n\n# Keypad-Enter. See comment on Return above.\n\nkey Enter+NewLine : \"\\r\\n\"\nkey Enter-NewLine : \"\\r\"  \n\nkey Space +Control : \"\\x00\"\n\n# some of keys are used by konsole.\n\nkey Up    +Shift   : scrollLineUp\nkey Prior +Shift   : scrollPageUp\nkey Down  +Shift   : scrollLineDown\nkey Next  +Shift   : scrollPageDown\n\nkey ScrollLock     : scrollLock\n\n#----------------------------------------------------------\n\n# keypad characters as offered by Qt\n# cannot be recognized as such.\n\n#----------------------------------------------------------\n\n# Following other strings as emitted by konsole.\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/BlockArray.cpp",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n    Copyright (C) 2000, 2013 by Stephan Kulow <coolo@kde.org>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n\n*/\n\n// Own\n#include \"unix/BlockArray.h\"\n\n#include <QtCore>\n\n// System\n#include <assert.h>\n#include <sys/mman.h>\n#include <sys/param.h>\n#include <unistd.h>\n#include <stdio.h>\n\n\nstatic int blocksize = 0;\n\nBlockArray::BlockArray()\n    : size(0),\n      current(size_t(-1)),\n      index(size_t(-1)),\n      lastmap(nullptr),\n      lastmap_index(size_t(-1)),\n      lastblock(nullptr), ion(-1),\n      length(0)\n{\n    // lastmap_index = index = current = size_t(-1);\n    if (blocksize == 0)\n        blocksize = ((sizeof(Block) / getpagesize()) + 1) * getpagesize();\n\n}\n\nBlockArray::~BlockArray()\n{\n    setHistorySize(0);\n    assert(!lastblock);\n}\n\nsize_t BlockArray::append(Block *block)\n{\n    if (!size)\n        return size_t(-1);\n\n    ++current;\n    if (current >= size) current = 0;\n\n    int rc;\n    rc = lseek(ion, current * blocksize, SEEK_SET); if (rc < 0) { perror(\"HistoryBuffer::add.seek\"); setHistorySize(0); return size_t(-1); }\n    rc = write(ion, block, blocksize); if (rc < 0) { perror(\"HistoryBuffer::add.write\"); setHistorySize(0); return size_t(-1); }\n\n    length++;\n    if (length > size) length = size;\n\n    ++index;\n\n    delete block;\n    return current;\n}\n\nsize_t BlockArray::newBlock()\n{\n    if (!size)\n        return size_t(-1);\n    append(lastblock);\n\n    lastblock = new Block();\n    return index + 1;\n}\n\nBlock *BlockArray::lastBlock() const\n{\n    return lastblock;\n}\n\nbool BlockArray::has(size_t i) const\n{\n    if (i == index + 1)\n        return true;\n\n    if (i > index)\n        return false;\n    if (index - i >= length)\n        return false;\n    return true;\n}\n\nconst Block* BlockArray::at(size_t i)\n{\n    if (i == index + 1)\n        return lastblock;\n\n    if (i == lastmap_index)\n        return lastmap;\n\n    if (i > index) {\n        qDebug() << \"BlockArray::at() i > index\\n\";\n        return nullptr;\n    }\n\n//     if (index - i >= length) {\n//         kDebug(1211) << \"BlockArray::at() index - i >= length\\n\";\n//         return 0;\n//     }\n\n    size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;\n\n    assert(j < size);\n    unmap();\n\n    Block *block = (Block*)mmap(nullptr, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize);\n\n    if (block == (Block*)-1) { perror(\"mmap\"); return nullptr; }\n\n    lastmap = block;\n    lastmap_index = i;\n\n    return block;\n}\n\nvoid BlockArray::unmap()\n{\n    if (lastmap) {\n        int res = munmap((char*)lastmap, blocksize);\n        if (res < 0) perror(\"munmap\");\n    }\n    lastmap = nullptr;\n    lastmap_index = size_t(-1);\n}\n\nbool BlockArray::setSize(size_t newsize)\n{\n    return setHistorySize(newsize * 1024 / blocksize);\n}\n\nbool BlockArray::setHistorySize(size_t newsize)\n{\n//    kDebug(1211) << \"setHistorySize \" << size << \" \" << newsize;\n\n    if (size == newsize)\n        return false;\n\n    unmap();\n\n    if (!newsize) {\n        delete lastblock;\n        lastblock = nullptr;\n        if (ion >= 0) close(ion);\n        ion = -1;\n        current = size_t(-1);\n        return true;\n    }\n\n    if (!size) {\n        FILE* tmp = tmpfile();\n        if (!tmp) {\n            perror(\"konsole: cannot open temp file.\\n\");\n        } else {\n            ion = dup(fileno(tmp));\n            if (ion<0) {\n                perror(\"konsole: cannot dup temp file.\\n\");\n                fclose(tmp);\n            }\n        }\n        if (ion < 0)\n            return false;\n\n        assert(!lastblock);\n\n        lastblock = new Block();\n        size = newsize;\n        return false;\n    }\n\n    if (newsize > size) {\n        increaseBuffer();\n        size = newsize;\n        return false;\n    } else {\n        decreaseBuffer(newsize);\n        if (ftruncate(ion, length*blocksize) == -1)\n\t\t  perror(\"ftruncate\");\n        size = newsize;\n\n        return true;\n    }\n}\n\nvoid moveBlock(FILE *fion, int cursor, int newpos, char *buffer2)\n{\n    int res = fseek(fion, static_cast<long int> (cursor) * blocksize, SEEK_SET);\n    if (res)\n        perror(\"fseek\");\n    res = fread(buffer2, blocksize, 1, fion);\n    if (res != 1)\n        perror(\"fread\");\n\n    res = fseek(fion, static_cast<long int> (newpos) * blocksize, SEEK_SET);\n    if (res)\n        perror(\"fseek\");\n    res = fwrite(buffer2, blocksize, 1, fion);\n    if (res != 1)\n        perror(\"fwrite\");\n    //    printf(\"moving block %d to %d\\n\", cursor, newpos);\n}\n\nvoid BlockArray::decreaseBuffer(size_t newsize)\n{\n    if (index < newsize) // still fits in whole\n        return;\n\n    int offset = (current - (newsize - 1) + size) % size;\n\n    if (!offset)\n        return;\n\n    // The Block constructor could do somthing in future...\n    char *buffer1 = new char[blocksize];\n\n    FILE *fion = fdopen(dup(ion), \"w+b\");\n    if (!fion) {\n        delete [] buffer1;\n        perror(\"fdopen/dup\");\n        return;\n    }\n\n    int firstblock;\n    if (current <= newsize) {\n        firstblock = current + 1;\n    } else {\n        firstblock = 0;\n    }\n\n    size_t oldpos;\n    for (size_t i = 0, cursor=firstblock; i < newsize; i++) {\n        oldpos = (size + cursor + offset) % size;\n        moveBlock(fion, oldpos, cursor, buffer1);\n        if (oldpos < newsize) {\n            cursor = oldpos;\n        } else\n            cursor++;\n    }\n\n    current = newsize - 1;\n    length = newsize;\n\n    delete [] buffer1;\n\n    fclose(fion);\n\n}\n\nvoid BlockArray::increaseBuffer()\n{\n    if (index < size) // not even wrapped once\n        return;\n\n    int offset = (current + size + 1) % size;\n    if (!offset) // no moving needed\n        return;\n\n    // The Block constructor could do somthing in future...\n    char *buffer1 = new char[blocksize];\n    char *buffer2 = new char[blocksize];\n\n    int runs = 1;\n    int bpr = size; // blocks per run\n\n    if (size % offset == 0) {\n        bpr = size / offset;\n        runs = offset;\n    }\n\n    FILE *fion = fdopen(dup(ion), \"w+b\");\n    if (!fion) {\n        perror(\"fdopen/dup\");\n\tdelete [] buffer1;\n\tdelete [] buffer2;\n        return;\n    }\n\n    int res;\n    for (int i = 0; i < runs; i++)\n    {\n        // free one block in chain\n        int firstblock = (offset + i) % size;\n        res = fseek(fion, static_cast<long int> (firstblock) * blocksize, SEEK_SET);\n        if (res)\n            perror(\"fseek\");\n        res = fread(buffer1, blocksize, 1, fion);\n        if (res != 1)\n            perror(\"fread\");\n        int newpos = 0;\n        for (int j = 1, cursor=firstblock; j < bpr; j++)\n        {\n            cursor = (cursor + offset) % size;\n            newpos = (cursor - offset + size) % size;\n            moveBlock(fion, cursor, newpos, buffer2);\n        }\n        res = fseek(fion, static_cast<long int> (i) * blocksize, SEEK_SET);\n        if (res)\n            perror(\"fseek\");\n        res = fwrite(buffer1, blocksize, 1, fion);\n        if (res != 1)\n            perror(\"fwrite\");\n    }\n    current = size - 1;\n    length = size;\n\n    delete [] buffer1;\n    delete [] buffer2;\n\n    fclose(fion);\n\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/BlockArray.h",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n    Copyright (C) 2000, 2013 by Stephan Kulow <coolo@kde.org>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef BLOCKARRAY_H\n#define BLOCKARRAY_H\n\n#include <unistd.h>\n\n#define BlockSize (1 << 12)\n#define ENTRIES   ((BlockSize - sizeof(size_t) ) / sizeof(unsigned char))\n\nstruct Block {\n    Block() { size = 0; }\n    unsigned char data[ENTRIES];\n    size_t size;\n};\n\n// ///////////////////////////////////////////////////////\n\nclass BlockArray {\npublic:\n    /**\n    * Creates a history file for holding\n    * maximal size blocks. If more blocks\n    * are requested, then it drops earlier\n    * added ones.\n    */\n    BlockArray();\n\n    /// destructor\n    ~BlockArray();\n\n    /**\n    * adds the Block at the end of history.\n    * This may drop other blocks.\n    *\n    * The ownership on the block is transfered.\n    * An unique index number is returned for accessing\n    * it later (if not yet dropped then)\n    *\n    * Note, that the block may be dropped completely\n    * if history is turned off.\n    */\n    size_t append(Block *block);\n\n    /**\n    * gets the block at the index. Function may return\n    * 0 if the block isn't available any more.\n    *\n    * The returned block is strictly readonly as only\n    * maped in memory - and will be invalid on the next\n    * operation on this class.\n    */\n    const Block *at(size_t index);\n\n    /**\n    * reorders blocks as needed. If newsize is null,\n    * the history is emptied completely. The indices\n    * returned on append won't change their semantic,\n    * but they may not be valid after this call.\n    */\n    bool setHistorySize(size_t newsize);\n\n    size_t newBlock();\n\n    Block *lastBlock() const;\n\n    /**\n    * Convenient function to set the size in KBytes\n    * instead of blocks\n    */\n    bool setSize(size_t newsize);\n\n    size_t len() const { return length; }\n\n    bool has(size_t index) const;\n\n    size_t getCurrent() const { return current; }\n\nprivate:\n    void unmap();\n    void increaseBuffer();\n    void decreaseBuffer(size_t newsize);\n\n    size_t size;\n    // current always shows to the last inserted block\n    size_t current;\n    size_t index;\n\n    Block *lastmap;\n    size_t lastmap_index;\n    Block *lastblock;\n\n    int ion;\n    size_t length;\n\n};\n\n#endif\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/Character.h",
    "content": "/*\n    This file is part of Konsole, KDE's terminal.\n\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef CHARACTER_H\n#define CHARACTER_H\n\n// Qt\n#include <QHash>\n\n// Local\n#include \"unix/CharacterColor.h\"\n\ntypedef unsigned char LineProperty;\n\nstatic const int LINE_DEFAULT\t\t= 0;\nstatic const int LINE_WRAPPED \t \t= (1 << 0);\nstatic const int LINE_DOUBLEWIDTH  \t= (1 << 1);\nstatic const int LINE_DOUBLEHEIGHT\t= (1 << 2);\n\n#define DEFAULT_RENDITION  0\n#define RE_BOLD            (1 << 0)\n#define RE_BLINK           (1 << 1)\n#define RE_UNDERLINE       (1 << 2)\n#define RE_REVERSE         (1 << 3) // Screen only\n#define RE_INTENSIVE       (1 << 3) // Widget only\n#define RE_CURSOR          (1 << 4)\n#define RE_EXTENDED_CHAR   (1 << 5)\n\n/**\n * A single character in the terminal which consists of a unicode character\n * value, foreground and background colors and a set of rendition attributes\n * which specify how it should be drawn.\n */\nclass Character\n{\npublic:\n  /**\n   * Constructs a new character.\n   *\n   * @param _c The unicode character value of this character.\n   * @param _f The foreground color used to draw the character.\n   * @param _b The color used to draw the character's background.\n   * @param _r A set of rendition flags which specify how this character is to be drawn.\n   */\n  inline Character(quint16 _c = ' ',\n            CharacterColor  _f = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR),\n            CharacterColor  _b = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR),\n            quint8  _r = DEFAULT_RENDITION)\n       : character(_c), rendition(_r), foregroundColor(_f), backgroundColor(_b) {}\n\n  union\n  {\n    /** The unicode character value for this character. */\n    quint16 character;\n    /**\n     * Experimental addition which allows a single Character instance to contain more than\n     * one unicode character.\n     *\n     * charSequence is a hash code which can be used to look up the unicode\n     * character sequence in the ExtendedCharTable used to create the sequence.\n     */\n    quint16 charSequence;\n  };\n\n  /** A combination of RENDITION flags which specify options for drawing the character. */\n  quint8  rendition;\n\n  /** The foreground color used to draw this character. */\n  CharacterColor  foregroundColor;\n  /** The color used to draw this character's background. */\n  CharacterColor  backgroundColor;\n\n  /**\n   * Returns true if this character has a transparent background when\n   * it is drawn with the specified @p palette.\n   */\n  bool   isTransparent(const ColorEntry* palette) const;\n  /**\n   * Returns true if this character should always be drawn in bold when\n   * it is drawn with the specified @p palette, independent of whether\n   * or not the character has the RE_BOLD rendition flag.\n   */\n  bool   isBold(const ColorEntry* base) const;\n\n  /**\n   * Compares two characters and returns true if they have the same unicode character value,\n   * rendition and colors.\n   */\n  friend bool operator == (const Character& a, const Character& b);\n  /**\n   * Compares two characters and returns true if they have different unicode character values,\n   * renditions or colors.\n   */\n  friend bool operator != (const Character& a, const Character& b);\n};\n\ninline bool operator == (const Character& a, const Character& b)\n{\n  return a.character == b.character &&\n         a.rendition == b.rendition &&\n         a.foregroundColor == b.foregroundColor &&\n         a.backgroundColor == b.backgroundColor;\n}\n\ninline bool operator != (const Character& a, const Character& b)\n{\n  return    a.character != b.character ||\n            a.rendition != b.rendition ||\n            a.foregroundColor != b.foregroundColor ||\n            a.backgroundColor != b.backgroundColor;\n}\n\ninline bool Character::isTransparent(const ColorEntry* base) const\n{\n  return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) &&\n          base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].transparent)\n      || ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) &&\n          base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].transparent);\n}\n\ninline bool Character::isBold(const ColorEntry* base) const\n{\n  return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) &&\n            base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].bold)\n      || ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) &&\n            base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].bold);\n}\n\nextern unsigned short vt100_graphics[32];\n\n\n/**\n * A table which stores sequences of unicode characters, referenced\n * by hash keys.  The hash key itself is the same size as a unicode\n * character ( ushort ) so that it can occupy the same space in\n * a structure.\n */\nclass ExtendedCharTable\n{\npublic:\n    /** Constructs a new character table. */\n    ExtendedCharTable();\n    ~ExtendedCharTable();\n\n    /**\n     * Adds a sequences of unicode characters to the table and returns\n     * a hash code which can be used later to look up the sequence\n     * using lookupExtendedChar()\n     *\n     * If the same sequence already exists in the table, the hash\n     * of the existing sequence will be returned.\n     *\n     * @param unicodePoints An array of unicode character points\n     * @param length Length of @p unicodePoints\n     */\n    ushort createExtendedChar(ushort* unicodePoints , ushort length);\n    /**\n     * Looks up and returns a pointer to a sequence of unicode characters\n     * which was added to the table using createExtendedChar().\n     *\n     * @param hash The hash key returned by createExtendedChar()\n     * @param length This variable is set to the length of the\n     * character sequence.\n     *\n     * @return A unicode character sequence of size @p length.\n     */\n    ushort* lookupExtendedChar(ushort hash , ushort& length) const;\n\n    /** The global ExtendedCharTable instance. */\n    static ExtendedCharTable instance;\nprivate:\n    // calculates the hash key of a sequence of unicode points of size 'length'\n    ushort extendedCharHash(ushort* unicodePoints , ushort length) const;\n    // tests whether the entry in the table specified by 'hash' matches the\n    // character sequence 'unicodePoints' of size 'length'\n    bool extendedCharMatch(ushort hash , ushort* unicodePoints , ushort length) const;\n    // internal, maps hash keys to character sequence buffers.  The first ushort\n    // in each value is the length of the buffer, followed by the ushorts in the buffer\n    // themselves.\n    QHash<ushort,ushort*> extendedCharTable;\n};\n\n#endif // CHARACTER_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/CharacterColor.h",
    "content": "/*\n    This file is part of Konsole, KDE's terminal.\n\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef CHARACTERCOLOR_H\n#define CHARACTERCOLOR_H\n\n// Qt\n#include <QColor>\n\n/**\n * An entry in a terminal display's color palette.\n *\n * A color palette is an array of 16 ColorEntry instances which map\n * system color indexes (from 0 to 15) into actual colors.\n *\n * Each entry can be set as bold, in which case any text\n * drawn using the color should be drawn in bold.\n *\n * Each entry can also be transparent, in which case the terminal\n * display should avoid drawing the background for any characters\n * using the entry as a background.\n */\nclass ColorEntry\n{\npublic:\n  /**\n   * Constructs a new color palette entry.\n   *\n   * @param c The color value for this entry.\n   * @param tr Specifies that the color should be transparent when used as a background color.\n   * @param b Specifies that text drawn with this color should be bold.\n   */\n  ColorEntry(QColor c, bool tr, bool b) : color(c), transparent(tr), bold(b) {}\n\n  /**\n   * Constructs a new color palette entry with an undefined color, and\n   * with the transparent and bold flags set to false.\n   */\n  ColorEntry() : transparent(false), bold(false) {}\n\n  /**\n   * Sets the color, transparency and boldness of this color to those of @p rhs.\n   */\n  void operator=(const ColorEntry& rhs)\n  {\n       color = rhs.color;\n       transparent = rhs.transparent;\n       bold = rhs.bold;\n  }\n\n  /** The color value of this entry for display. */\n  QColor color;\n\n  /**\n   * If true character backgrounds using this color should be transparent.\n   * This is not applicable when the color is used to render text.\n   */\n  bool   transparent;\n  /**\n   * If true characters drawn using this color should be bold.\n   * This is not applicable when the color is used to draw a character's background.\n   */\n  bool   bold;\n};\n\n\n// Attributed Character Representations ///////////////////////////////\n\n// Colors\n\n#define BASE_COLORS   (2+8)\n#define INTENSITIES   2\n#define TABLE_COLORS  (INTENSITIES*BASE_COLORS)\n\n#define DEFAULT_FORE_COLOR 0\n#define DEFAULT_BACK_COLOR 1\n\n//a standard set of colors using black text on a white background.\n//defined in TerminalDisplay.cpp\n\nstatic const ColorEntry base_color_table[TABLE_COLORS] =\n{\n    // normal\n    ColorEntry(QColor(0x00,0x00,0x00), 1, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 ), // Dfore, Dback\n    ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red\n    ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow\n    ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta\n    ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White\n    // intensiv\n    ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ),\n    ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ),\n    ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ),\n    ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0xFF), 0, 0 ),\n    ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 )\n};\n\n/* CharacterColor is a union of the various color spaces.\n\n   Assignment is as follows:\n\n   Type  - Space        - Values\n\n   0     - Undefined   - u:  0,      v:0        w:0\n   1     - Default     - u:  0..1    v:intense  w:0\n   2     - System      - u:  0..7    v:intense  w:0\n   3     - Index(256)  - u: 16..255  v:0        w:0\n   4     - RGB         - u:  0..255  v:0..256   w:0..256\n\n   Default colour space has two separate colours, namely\n   default foreground and default background colour.\n*/\n\n#define COLOR_SPACE_UNDEFINED   0\n#define COLOR_SPACE_DEFAULT     1\n#define COLOR_SPACE_SYSTEM      2\n#define COLOR_SPACE_256         3\n#define COLOR_SPACE_RGB         4\n\n/**\n * Describes the color of a single character in the terminal.\n */\nclass CharacterColor\n{\n    friend class Character;\n\npublic:\n  /** Constructs a new CharacterColor whoose color and color space are undefined. */\n  CharacterColor()\n      : _colorSpace(COLOR_SPACE_UNDEFINED),\n        _u(0),\n        _v(0),\n        _w(0)\n  {}\n\n  /**\n   * Constructs a new CharacterColor using the specified @p colorSpace and with\n   * color value @p co\n   *\n   * The meaning of @p co depends on the @p colorSpace used.\n   *\n   * TODO : Document how @p co relates to @p colorSpace\n   *\n   * TODO : Add documentation about available color spaces.\n   */\n  CharacterColor(quint8 colorSpace, int co)\n      : _colorSpace(colorSpace),\n        _u(0),\n        _v(0),\n        _w(0)\n  {\n    switch (colorSpace)\n    {\n        case COLOR_SPACE_DEFAULT:\n            _u = co & 1;\n            break;\n        case COLOR_SPACE_SYSTEM:\n            _u = co & 7;\n            _v = (co >> 3) & 1;\n            break;\n        case COLOR_SPACE_256:\n            _u = co & 255;\n            break;\n        case COLOR_SPACE_RGB:\n            _u = co >> 16;\n            _v = co >> 8;\n            _w = co;\n            break;\n        default:\n            _colorSpace = COLOR_SPACE_UNDEFINED;\n    }\n  }\n\n  /**\n   * Returns true if this character color entry is valid.\n   */\n  bool isValid()\n  {\n        return _colorSpace != COLOR_SPACE_UNDEFINED;\n  }\n\n  /**\n   * Toggles the value of this color between a normal system color and the corresponding intensive\n   * system color.\n   *\n   * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM\n   * color spaces.\n   */\n  void toggleIntensive();\n\n  /**\n   * Returns the color within the specified color @palette\n   *\n   * The @p palette is only used if this color is one of the 16 system colors, otherwise\n   * it is ignored.\n   */\n  QColor color(const ColorEntry* palette) const;\n\n  /**\n   * Compares two colors and returns true if they represent the same color value and\n   * use the same color space.\n   */\n  friend bool operator == (const CharacterColor& a, const CharacterColor& b);\n  /**\n   * Compares two colors and returns true if they represent different color values\n   * or use different color spaces.\n   */\n  friend bool operator != (const CharacterColor& a, const CharacterColor& b);\n\nprivate:\n  quint8 _colorSpace;\n\n  // bytes storing the character color\n  quint8 _u;\n  quint8 _v;\n  quint8 _w;\n};\n\ninline bool operator == (const CharacterColor& a, const CharacterColor& b)\n{\n    return a._colorSpace == b._colorSpace &&\n\t       a._u == b._u &&\n\t       a._v == b._v &&\n           a._w == b._w;\n}\n\ninline bool operator != (const CharacterColor& a, const CharacterColor& b)\n{\n    return !operator==(a,b);\n}\n\ninline const QColor color256(quint8 u, const ColorEntry* base)\n{\n  //   0.. 16: system colors\n  if (u <   8) return base[u+2            ].color; u -= 8;\n  if (u <   8) return base[u+2+BASE_COLORS].color; u -= 8;\n\n  //  16..231: 6x6x6 rgb color cube\n  if (u < 216) return QColor(255*((u/36)%6)/5,\n                             255*((u/ 6)%6)/5,\n                             255*((u/ 1)%6)/5); u -= 216;\n\n  // 232..255: gray, leaving out black and white\n  int gray = u*10+8; return QColor(gray,gray,gray);\n}\n\ninline QColor CharacterColor::color(const ColorEntry* base) const\n{\n  switch (_colorSpace)\n  {\n    case COLOR_SPACE_DEFAULT: return base[_u+0+(_v?BASE_COLORS:0)].color;\n    case COLOR_SPACE_SYSTEM: return base[_u+2+(_v?BASE_COLORS:0)].color;\n    case COLOR_SPACE_256: return color256(_u,base);\n    case COLOR_SPACE_RGB: return QColor(_u,_v,_w);\n    case COLOR_SPACE_UNDEFINED: return QColor();\n  }\n\n  Q_ASSERT(false); // invalid color space\n\n  return QColor();\n}\n\ninline void CharacterColor::toggleIntensive()\n{\n  if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT)\n  {\n    _v = !_v;\n  }\n}\n\n#endif // CHARACTERCOLOR_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/Emulation.cpp",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n\n    Copyright (C) 2007, 2013 Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n    Copyright (C) 1996, 2013 by Matthias Ettrich <ettrich@kde.org>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n// Own\n#include \"unix/Emulation.h\"\n\n// System\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n\n// Qt\n#include <QApplication>\n#include <QClipboard>\n#include <QHash>\n#include <QKeyEvent>\n#include <QTextStream>\n#include <QThread>\n#include <QTime>\n\n// Konsole\n#include \"unix/KeyboardTranslator.h\"\n#include \"unix/Screen.h\"\n#include \"unix/TerminalCharacterDecoder.h\"\n#include \"unix/ScreenWindow.h\"\n\nEmulation::Emulation() :\n  _currentScreen(nullptr),\n  _codec(nullptr),\n  _decoder(nullptr),\n  _keyTranslator(nullptr),\n  _usesMouse(false),\n  _bracketedPasteMode(false)\n{\n\n  // create screens with a default size\n  _screen[0] = new Screen(40,80);\n  _screen[1] = new Screen(40,80);\n  _currentScreen = _screen[0];\n\n  QObject::connect(&_bulkTimer1, SIGNAL(timeout()), this, SLOT(showBulk()) );\n  QObject::connect(&_bulkTimer2, SIGNAL(timeout()), this, SLOT(showBulk()) );\n\n  // listen for mouse status changes\n  connect( this , SIGNAL(programUsesMouseChanged(bool)) ,\n           SLOT(usesMouseChanged(bool)) );\n  connect(this , SIGNAL(programBracketedPasteModeChanged(bool)) ,\n           SLOT(bracketedPasteModeChanged(bool)));\n}\n\nbool Emulation::programUsesMouse() const\n{\n    return _usesMouse;\n}\n\nvoid Emulation::usesMouseChanged(bool usesMouse)\n{\n    _usesMouse = usesMouse;\n}\n\nbool Emulation::programBracketedPasteMode() const\n{\n    return _bracketedPasteMode;\n}\n\nvoid Emulation::bracketedPasteModeChanged(bool bracketedPasteMode)\n{\n    _bracketedPasteMode = bracketedPasteMode;\n}\n\nScreenWindow* Emulation::createWindow()\n{\n    ScreenWindow* window = new ScreenWindow();\n    window->setScreen(_currentScreen);\n    _windows << window;\n\n    connect(window , SIGNAL(selectionChanged()),\n            this , SLOT(bufferedUpdate()));\n\n    connect(this , SIGNAL(outputChanged()),\n            window , SLOT(notifyOutputChanged()) );\n    return window;\n}\n\n/*!\n*/\n\nEmulation::~Emulation()\n{\n  QListIterator<ScreenWindow*> windowIter(_windows);\n\n  while (windowIter.hasNext())\n  {\n    delete windowIter.next();\n  }\n\n  delete _screen[0];\n  delete _screen[1];\n  delete _decoder;\n}\n\n/*! change between primary and alternate _screen\n*/\n\nvoid Emulation::setScreen(int n)\n{\n  Screen *old = _currentScreen;\n  _currentScreen = _screen[n&1];\n  if (_currentScreen != old)\n  {\n     old->setBusySelecting(false);\n\n     // tell all windows onto this emulation to switch to the newly active _screen\n     QListIterator<ScreenWindow*> windowIter(_windows);\n     while ( windowIter.hasNext() )\n     {\n         windowIter.next()->setScreen(_currentScreen);\n     }\n  }\n}\n\nvoid Emulation::clearHistory()\n{\n    _screen[0]->setScroll( _screen[0]->getScroll() , false );\n}\nvoid Emulation::setHistory(const HistoryType& t)\n{\n  _screen[0]->setScroll(t);\n\n  showBulk();\n}\n\nconst HistoryType& Emulation::history()\n{\n  return _screen[0]->getScroll();\n}\n\nvoid Emulation::setCodec(const QTextCodec * qtc)\n{\n  Q_ASSERT( qtc );\n\n  _codec = qtc;\n  delete _decoder;\n  _decoder = _codec->makeDecoder();\n\n  Q_EMIT useUtf8Request(utf8());\n}\n\nvoid Emulation::setCodec(EmulationCodec codec)\n{\n    if ( codec == Utf8Codec )\n        setCodec( QTextCodec::codecForName(\"utf8\") );\n    else if ( codec == LocaleCodec )\n        setCodec( QTextCodec::codecForLocale() );\n}\n\nvoid Emulation::setKeyBindings(const QString& name)\n{\n  _keyTranslator = KeyboardTranslatorManager::instance()->findTranslator(name);\n}\n\nQString Emulation::keyBindings()\n{\n  return _keyTranslator->name();\n}\n\n\n// Interpreting Codes ---------------------------------------------------------\n\n/*\n   This section deals with decoding the incoming character stream.\n   Decoding means here, that the stream is first separated into `tokens'\n   which are then mapped to a `meaning' provided as operations by the\n   `Screen' class.\n*/\n\n/*!\n*/\n\nvoid Emulation::receiveChar(int c)\n// process application unicode input to terminal\n// this is a trivial scanner\n{\n  c &= 0xff;\n  switch (c)\n  {\n    case '\\b'      : _currentScreen->BackSpace();                 break;\n    case '\\t'      : _currentScreen->Tabulate();                  break;\n    case '\\n'      : _currentScreen->NewLine();                   break;\n    case '\\r'      : _currentScreen->Return();                    break;\n    case 0x07      : Q_EMIT stateSet(NOTIFYBELL);\n                     break;\n    default        : _currentScreen->ShowCharacter(c);            break;\n  };\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                             Keyboard Handling                             */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n/*!\n*/\n\nvoid Emulation::sendKeyEvent( QKeyEvent* ev )\n{\n  Q_EMIT stateSet(NOTIFYNORMAL);\n\n  if (!ev->text().isEmpty())\n  { // A block of text\n    // Note that the text is proper unicode.\n    // We should do a conversion here, but since this\n    // routine will never be used, we simply emit plain ascii.\n    //Q_EMIT sendBlock(ev->text().toAscii(),ev->text().length());\n    Q_EMIT sendData(ev->text().toUtf8(),ev->text().length());\n  }\n}\n\nvoid Emulation::sendString(const char*,int)\n{\n    // default implementation does nothing\n}\n\nvoid Emulation::sendMouseEvent(int /*buttons*/, int /*column*/, int /*row*/, int /*eventType*/)\n{\n    // default implementation does nothing\n}\n\n// Unblocking, Byte to Unicode translation --------------------------------- --\n\n/*\n   We are doing code conversion from locale to unicode first.\nTODO: Character composition from the old code.  See #96536\n*/\n\nvoid Emulation::receiveData(const char* text, int length)\n{\n\tQ_EMIT stateSet(NOTIFYACTIVITY);\n\n\tbufferedUpdate();\n    \t\n        QString unicodeText = _decoder->toUnicode(text,length);\n\n\t//send characters to terminal emulator\n        for (int i=0;i<unicodeText.length();i++)\n\t{\n                receiveChar(unicodeText[i].unicode());\n\t}\n}\n\n// Selection --------------------------------------------------------------- --\n\nvoid Emulation::writeToStream( TerminalCharacterDecoder* _decoder ,\n                               int startLine ,\n                               int endLine)\n{\n  _currentScreen->writeToStream(_decoder,startLine,endLine);\n}\n\nint Emulation::lineCount()\n{\n    // sum number of lines currently on _screen plus number of lines in history\n    return _currentScreen->getLines() + _currentScreen->getHistLines();\n}\n\n// Refreshing -------------------------------------------------------------- --\n\n#define BULK_TIMEOUT1 10\n#define BULK_TIMEOUT2 40\n\n/*!\n*/\nvoid Emulation::showBulk()\n{\n    _bulkTimer1.stop();\n    _bulkTimer2.stop();\n\n    Q_EMIT outputChanged();\n\n    _currentScreen->resetScrolledLines();\n    _currentScreen->resetDroppedLines();\n}\n\nvoid Emulation::bufferedUpdate()\n{\n   _bulkTimer1.setSingleShot(true);\n   _bulkTimer1.start(BULK_TIMEOUT1);\n   if (!_bulkTimer2.isActive())\n   {\n      _bulkTimer2.setSingleShot(true);\n      _bulkTimer2.start(BULK_TIMEOUT2);\n   }\n}\n\nchar Emulation::getErase() const\n{\n  return '\\b';\n}\n\nvoid Emulation::setImageSize(int lines, int columns)\n{\n  //kDebug() << \"Resizing image to: \" << lines << \"by\" << columns << QTime::currentTime().msec();\n  Q_ASSERT( lines > 0 );\n  Q_ASSERT( columns > 0 );\n\n  _screen[0]->resizeImage(lines,columns);\n  _screen[1]->resizeImage(lines,columns);\n\n  Q_EMIT imageSizeChanged(lines,columns);\n\n  bufferedUpdate();\n}\n\nQSize Emulation::imageSize()\n{\n  return QSize(_currentScreen->getColumns(), _currentScreen->getLines());\n}\n\nushort ExtendedCharTable::extendedCharHash(ushort* unicodePoints , ushort length) const\n{\n    ushort hash = 0;\n    for ( ushort i = 0 ; i < length ; i++ )\n    {\n        hash = 31*hash + unicodePoints[i];\n    }\n    return hash;\n}\nbool ExtendedCharTable::extendedCharMatch(ushort hash , ushort* unicodePoints , ushort length) const\n{\n    ushort* entry = extendedCharTable[hash];\n\n    // compare given length with stored sequence length ( given as the first ushort in the\n    // stored buffer )\n    if ( entry == nullptr || entry[0] != length )\n       return false;\n    // if the lengths match, each character must be checked.  the stored buffer starts at\n    // entry[1]\n    for ( int i = 0 ; i < length ; i++ )\n    {\n        if ( entry[i+1] != unicodePoints[i] )\n           return false;\n    }\n    return true;\n}\nushort ExtendedCharTable::createExtendedChar(ushort* unicodePoints , ushort length)\n{\n    // look for this sequence of points in the table\n    ushort hash = extendedCharHash(unicodePoints,length);\n\n    // check existing entry for match\n    while ( extendedCharTable.contains(hash) )\n    {\n        if ( extendedCharMatch(hash,unicodePoints,length) )\n        {\n            // this sequence already has an entry in the table,\n            // return its hash\n            return hash;\n        }\n        else\n        {\n            // if hash is already used by another, different sequence of unicode character\n            // points then try next hash\n            hash++;\n        }\n    }\n\n\n     // add the new sequence to the table and\n     // return that index\n    ushort* buffer = new ushort[length+1];\n    buffer[0] = length;\n    for ( int i = 0 ; i < length ; i++ )\n       buffer[i+1] = unicodePoints[i];\n\n    extendedCharTable.insert(hash,buffer);\n\n    return hash;\n}\n\nushort* ExtendedCharTable::lookupExtendedChar(ushort hash , ushort& length) const\n{\n    // lookup index in table and if found, set the length\n    // argument and return a pointer to the character sequence\n\n    ushort* buffer = extendedCharTable[hash];\n    if ( buffer )\n    {\n        length = buffer[0];\n        return buffer+1;\n    }\n    else\n    {\n        length = 0;\n        return nullptr;\n    }\n}\n\nExtendedCharTable::ExtendedCharTable()\n{\n}\nExtendedCharTable::~ExtendedCharTable()\n{\n    // free all allocated character buffers\n    QHashIterator<ushort,ushort*> iter(extendedCharTable);\n    while ( iter.hasNext() )\n    {\n        iter.next();\n        delete[] iter.value();\n    }\n}\n\n// global instance\nExtendedCharTable ExtendedCharTable::instance;\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/Emulation.h",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef EMULATION_H\n#define EMULATION_H\n\n// System\n#include <stdio.h>\n\n// Qt\n#include <QKeyEvent>\n#include <QTextCodec>\n#include <QTextStream>\n#include <QTimer>\n\nclass KeyboardTranslator;\nclass HistoryType;\nclass Screen;\nclass ScreenWindow;\nclass TerminalCharacterDecoder;\n\n/**\n * This enum describes the available states which\n * the terminal emulation may be set to.\n *\n * These are the values used by Emulation::stateChanged()\n */\nenum\n{\n    /** The emulation is currently receiving user input. */\n    NOTIFYNORMAL=0,\n    /**\n     * The terminal program has triggered a bell event\n     * to get the user's attention.\n     */\n    NOTIFYBELL=1,\n    /**\n     * The emulation is currently receiving data from its\n     * terminal input.\n     */\n    NOTIFYACTIVITY=2,\n\n    // unused here?\n    NOTIFYSILENCE=3\n};\n\n/**\n * Base class for terminal emulation back-ends.\n *\n * The back-end is responsible for decoding an incoming character stream and\n * producing an output image of characters.\n *\n * When input from the terminal is received, the receiveData() slot should be called with\n * the data which has arrived.  The emulation will process the data and update the\n * screen image accordingly.  The codec used to decode the incoming character stream\n * into the unicode characters used internally can be specified using setCodec()\n *\n * The size of the screen image can be specified by calling setImageSize() with the\n * desired number of lines and columns.  When new lines are added, old content\n * is moved into a history store, which can be set by calling setHistory().\n *\n * The screen image can be accessed by creating a ScreenWindow onto this emulation\n * by calling createWindow().  Screen windows provide access to a section of the\n * output.  Each screen window covers the same number of lines and columns as the\n * image size returned by imageSize().  The screen window can be moved up and down\n * and provides transparent access to both the current on-screen image and the\n * previous output.  The screen windows emit an outputChanged signal\n * when the section of the image they are looking at changes.\n * Graphical views can then render the contents of a screen window, listening for notifications\n * of output changes from the screen window which they are associated with and updating\n * accordingly.\n *\n * The emulation also is also responsible for converting input from the connected views such\n * as keypresses and mouse activity into a character string which can be sent\n * to the terminal program.  Key presses can be processed by calling the sendKeyEvent() slot,\n * while mouse events can be processed using the sendMouseEvent() slot.  When the character\n * stream has been produced, the emulation will emit a sendData() signal with a pointer\n * to the character buffer.  This data should be fed to the standard input of the terminal\n * process.  The translation of key presses into an output character stream is performed\n * using a lookup in a set of key bindings which map key sequences to output\n * character sequences.  The name of the key bindings set used can be specified using\n * setKeyBindings()\n *\n * The emulation maintains certain state information which changes depending on the\n * input received.  The emulation can be reset back to its starting state by calling\n * reset().\n *\n * The emulation also maintains an activity state, which specifies whether\n * terminal is currently active ( when data is received ), normal\n * ( when the terminal is idle or receiving user input ) or trying\n * to alert the user ( also known as a \"Bell\" event ).  The stateSet() signal\n * is emitted whenever the activity state is set.  This can be used to determine\n * how long the emulation has been active/idle for and also respond to\n * a 'bell' event in different ways.\n */\nclass Emulation : public QObject\n{\nQ_OBJECT\n\npublic:\n\n   /** Constructs a new terminal emulation */\n   Emulation();\n  ~Emulation();\n\n  /**\n   * Creates a new window onto the output from this emulation.  The contents\n   * of the window are then rendered by views which are set to use this window using the\n   * TerminalDisplay::setScreenWindow() method.\n   */\n  ScreenWindow* createWindow();\n\n  /** Returns the size of the screen image which the emulation produces */\n  QSize imageSize();\n\n  /**\n   * Returns the total number of lines, including those stored in the history.\n   */\n  int lineCount();\n\n\n  /**\n   * Sets the history store used by this emulation.  When new lines\n   * are added to the output, older lines at the top of the screen are transferred to a history\n   * store.\n   *\n   * The number of lines which are kept and the storage location depend on the\n   * type of store.\n   */\n  void setHistory(const HistoryType&);\n  /** Returns the history store used by this emulation.  See setHistory() */\n  const HistoryType& history();\n  /** Clears the history scroll. */\n  void clearHistory();\n\n  /**\n   * Copies the output history from @p startLine to @p endLine\n   * into @p stream, using @p decoder to convert the terminal\n   * characters into text.\n   *\n   * @param decoder A decoder which converts lines of terminal characters with\n   * appearance attributes into output text.  PlainTextDecoder is the most commonly\n   * used decoder.\n   * @param startLine The first\n   */\n  virtual void writeToStream(TerminalCharacterDecoder* decoder,int startLine,int endLine);\n\n\n  /** Returns the codec used to decode incoming characters.  See setCodec() */\n  const QTextCodec* codec() { return _codec; }\n  /** Sets the codec used to decode incoming characters.  */\n  void setCodec(const QTextCodec*);\n\n  /**\n   * Convenience method.\n   * Returns true if the current codec used to decode incoming\n   * characters is UTF-8\n   */\n  bool utf8() { Q_ASSERT(_codec); return _codec->mibEnum() == 106; }\n\n\n  /** TODO Document me */\n  virtual char getErase() const;\n\n  /**\n   * Sets the key bindings used to key events\n   * ( received through sendKeyEvent() ) into character\n   * streams to send to the terminal.\n   */\n  void setKeyBindings(const QString& name);\n  /**\n   * Returns the name of the emulation's current key bindings.\n   * See setKeyBindings()\n   */\n  QString keyBindings();\n\n  /**\n   * Copies the current image into the history and clears the screen.\n   */\n  virtual void clearEntireScreen() =0;\n\n  /** Resets the state of the terminal. */\n  virtual void reset() =0;\n\n  /**\n   * Returns true if the active terminal program wants\n   * mouse input events.\n   *\n   * The programUsesMouseChanged() signal is emitted when this\n   * changes.\n   */\n  bool programUsesMouse() const;\n\n  bool programBracketedPasteMode() const;\n\npublic Q_SLOTS:\n\n  /** Change the size of the emulation's image */\n  virtual void setImageSize(int lines, int columns);\n\n  /**\n   * Interprets a sequence of characters and sends the result to the terminal.\n   * This is equivalent to calling sendKeyEvent() for each character in @p text in succession.\n   */\n  virtual void sendText(const QString& text) = 0;\n\n  /**\n   * Interprets a key press event and emits the sendData() signal with\n   * the resulting character stream.\n   */\n  virtual void sendKeyEvent(QKeyEvent*);\n\n  /**\n   * Converts information about a mouse event into an xterm-compatible escape\n   * sequence and emits the character sequence via sendData()\n   */\n  virtual void sendMouseEvent(int buttons, int column, int line, int eventType);\n\n  /**\n   * Sends a string of characters to the foreground terminal process.\n   *\n   * @param string The characters to send.\n   * @param length Length of @p string or if set to a negative value, @p string will\n   * be treated as a null-terminated string and its length will be determined automatically.\n   */\n  virtual void sendString(const char* string, int length = -1) = 0;\n\n  /**\n   * Processes an incoming stream of characters.  receiveData() decodes the incoming\n   * character buffer using the current codec(), and then calls receiveChar() for\n   * each unicode character in the resulting buffer.\n   *\n   * receiveData() also starts a timer which causes the outputChanged() signal\n   * to be emitted when it expires.  The timer allows multiple updates in quick\n   * succession to be buffered into a single outputChanged() signal emission.\n   *\n   * @param buffer A string of characters received from the terminal program.\n   * @param len The length of @p buffer\n   */\n  void receiveData(const char* buffer,int len);\n\nQ_SIGNALS:\n\n  /**\n   * Emitted when a buffer of data is ready to send to the\n   * standard input of the terminal.\n   *\n   * @param data The buffer of data ready to be sent\n   * @paran len The length of @p data in bytes\n   */\n  void sendData(const char* data,int len);\n\n  /**\n   * Requests that sending of input to the emulation\n   * from the terminal process be suspended or resumed.\n   *\n   * @param suspend If true, requests that sending of\n   * input from the terminal process' stdout be\n   * suspended.  Otherwise requests that sending of\n   * input be resumed.\n   */\n  void lockPtyRequest(bool suspend);\n\n  /**\n   * Requests that the pty used by the terminal process\n   * be set to UTF 8 mode.\n   *\n   * TODO: More documentation\n   */\n  void useUtf8Request(bool);\n\n  /**\n   * Emitted when the activity state of the emulation is set.\n   *\n   * @param state The new activity state, one of NOTIFYNORMAL, NOTIFYACTIVITY\n   * or NOTIFYBELL\n   */\n  void stateSet(int state);\n\n\n  /**\n   * Requests that the color of the text used\n   * to represent the tabs associated with this\n   * emulation be changed.  This is a Konsole-specific\n   * extension from pre-KDE 4 times.\n   *\n   * TODO: Document how the parameter works.\n   */\n  void changeTabTextColorRequest(int color);\n\n  /**\n   * This is emitted when the program running in the shell indicates whether or\n   * not it is interested in mouse events.\n   *\n   * @param usesMouse This will be true if the program wants to be informed about\n   * mouse events or false otherwise.\n   */\n  void programUsesMouseChanged(bool usesMouse);\n\n  void programBracketedPasteModeChanged(bool bracketedPasteMode);\n\n  /**\n   * Emitted when the contents of the screen image change.\n   * The emulation buffers the updates from successive image changes,\n   * and only emits outputChanged() at sensible intervals when\n   * there is a lot of terminal activity.\n   *\n   * Normally there is no need for objects other than the screen windows\n   * created with createWindow() to listen for this signal.\n   *\n   * ScreenWindow objects created using createWindow() will emit their\n   * own outputChanged() signal in response to this signal.\n   */\n  void outputChanged();\n\n  /**\n   * Emitted when the program running in the terminal wishes to update the\n   * session's title.  This also allows terminal programs to customize other\n   * aspects of the terminal emulation display.\n   *\n   * This signal is emitted when the escape sequence \"\\033]ARG;VALUE\\007\"\n   * is received in the input string, where ARG is a number specifying what\n   * should change and VALUE is a string specifying the new value.\n   *\n   * TODO:  The name of this method is not very accurate since this method\n   * is used to perform a whole range of tasks besides just setting\n   * the user-title of the session.\n   *\n   * @param title Specifies what to change.\n   * <ul>\n   * <li>0 - Set window icon text and session title to @p newTitle</li>\n   * <li>1 - Set window icon text to @p newTitle</li>\n   * <li>2 - Set session title to @p newTitle</li>\n   * <li>11 - Set the session's default background color to @p newTitle,\n   *         where @p newTitle can be an HTML-style string (#RRGGBB) or a named\n   *         color (eg 'red', 'blue').\n   *         See http://doc.trolltech.com/4.2/qcolor.html#setNamedColor for more\n   *         details.\n   * </li>\n   * <li>31 - Supposedly treats @p newTitle as a URL and opens it (NOT IMPLEMENTED)</li>\n   * <li>32 - Sets the icon associated with the session.  @p newTitle is the name\n   *    of the icon to use, which can be the name of any icon in the current KDE icon\n   *    theme (eg: 'konsole', 'kate', 'folder_home')</li>\n   * </ul>\n   * @param newTitle Specifies the new title\n   */\n\n  void titleChanged(int title,const QString& newTitle);\n\n  /**\n   * Emitted when the program running in the terminal changes the\n   * screen size.\n   */\n  void imageSizeChanged(int lineCount , int columnCount);\n\n  /**\n   * Emitted when the terminal program requests to change various properties\n   * of the terminal display.\n   *\n   * A profile change command occurs when a special escape sequence, followed\n   * by a string containing a series of name and value pairs is received.\n   * This string can be parsed using a ProfileCommandParser instance.\n   *\n   * @param text A string expected to contain a series of key and value pairs in\n   * the form:  name=value;name2=value2 ...\n   */\n  void profileChangeCommandReceived(const QString& text);\n\nprotected:\n  virtual void setMode  (int mode) = 0;\n  virtual void resetMode(int mode) = 0;\n\n /**\n   * Processes an incoming character.  See receiveData()\n   * @p ch A unicode character code.\n   */\n  virtual void receiveChar(int ch);\n\n  /**\n   * Sets the active screen.  The terminal has two screens, primary and alternate.\n   * The primary screen is used by default.  When certain interactive programs such\n   * as Vim are run, they trigger a switch to the alternate screen.\n   *\n   * @param index 0 to switch to the primary screen, or 1 to switch to the alternate screen\n   */\n  void setScreen(int index);\n\n  enum EmulationCodec\n  {\n      LocaleCodec = 0,\n      Utf8Codec   = 1\n  };\n  void setCodec(EmulationCodec codec); // codec number, 0 = locale, 1=utf8\n\n\n  QList<ScreenWindow*> _windows;\n\n  Screen* _currentScreen;  // pointer to the screen which is currently active,\n                            // this is one of the elements in the screen[] array\n\n  Screen* _screen[2];      // 0 = primary screen ( used by most programs, including the shell\n                            //                      scrollbars are enabled in this mode )\n                            // 1 = alternate      ( used by vi , emacs etc.\n                            //                      scrollbars are not enabled in this mode )\n\n\n  //decodes an incoming C-style character stream into a unicode QString using\n  //the current text codec.  (this allows for rendering of non-ASCII characters in text files etc.)\n  const QTextCodec* _codec;\n  QTextDecoder* _decoder;\n\n  const KeyboardTranslator* _keyTranslator; // the keyboard layout\n\nprotected Q_SLOTS:\n  /**\n   * Schedules an update of attached views.\n   * Repeated calls to bufferedUpdate() in close succession will result in only a single update,\n   * much like the Qt buffered update of widgets.\n   */\n  void bufferedUpdate();\n\nprivate Q_SLOTS:\n\n  // triggered by timer, causes the emulation to send an updated screen image to each\n  // view\n  void showBulk();\n\n  void usesMouseChanged(bool usesMouse);\n\n  void bracketedPasteModeChanged(bool bracketedPasteMode);\n\nprivate:\n\n  bool _usesMouse;\n  bool _bracketedPasteMode;\n  QTimer _bulkTimer1;\n  QTimer _bulkTimer2;\n\n};\n\n#endif // ifndef EMULATION_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslator.h",
    "content": "\"keyboard \\\"Default (XFree 4)\\\"\"\n\"key Escape             : \\\"\\\\E\\\"\"\n\"key Tab   -Shift       : \\\"\\\\t\\\"\\n\"\n\"key Tab   +Shift+Ansi  : \\\"\\\\E[Z\\\"\\n\"\n\"key Tab   +Shift-Ansi  : \\\"\\\\t\\\"\\n\"\n\"key Backtab     +Ansi  : \\\"\\\\E[Z\\\"\\n\"\n\"key Backtab     -Ansi  : \\\"\\\\t\\\"\\n\"\n\"key Return-Shift-NewLine : \\\"\\\\r\\\"\\n\"\n\"key Return-Shift+NewLine : \\\"\\\\r\\\\n\\\"\\n\"\n\"key Return+Shift         : \\\"\\\\EOM\\\"\\n\"\n\"key Backspace      : \\\"\\\\x7f\\\"\\n\"\n\"key Up    -Shift-Ansi : \\\"\\\\EA\\\"\\n\"\n\"key Down  -Shift-Ansi : \\\"\\\\EB\\\"\\n\"\n\"key Right -Shift-Ansi : \\\"\\\\EC\\\"\\n\"\n\"key Left  -Shift-Ansi : \\\"\\\\ED\\\"\\n\"\n\"key Up    -Shift-AnyMod+Ansi+AppCuKeys           : \\\"\\\\EOA\\\"\\n\"\n\"key Down  -Shift-AnyMod+Ansi+AppCuKeys           : \\\"\\\\EOB\\\"\\n\"\n\"key Right -Shift-AnyMod+Ansi+AppCuKeys           : \\\"\\\\EOC\\\"\\n\"\n\"key Left  -Shift-AnyMod+Ansi+AppCuKeys           : \\\"\\\\EOD\\\"\\n\"\n\"key Up    -Shift-AnyMod+Ansi-AppCuKeys           : \\\"\\\\E[A\\\"\\n\"\n\"key Down  -Shift-AnyMod+Ansi-AppCuKeys           : \\\"\\\\E[B\\\"\\n\"\n\"key Right -Shift-AnyMod+Ansi-AppCuKeys           : \\\"\\\\E[C\\\"\\n\"\n\"key Left  -Shift-AnyMod+Ansi-AppCuKeys           : \\\"\\\\E[D\\\"\\n\"\n\"key Up    -Shift+AnyMod+Ansi                     : \\\"\\\\E[1;*A\\\"\\n\"\n\"key Down  -Shift+AnyMod+Ansi                     : \\\"\\\\E[1;*B\\\"\\n\"\n\"key Right -Shift+AnyMod+Ansi                     : \\\"\\\\E[1;*C\\\"\\n\"\n\"key Left  -Shift+AnyMod+Ansi                     : \\\"\\\\E[1;*D\\\"\\n\"\n\"key Enter+NewLine : \\\"\\\\r\\\\n\\\"\\n\"\n\"key Enter-NewLine : \\\"\\\\r\\\"\\n\"\n\"key Home        -AnyMod     -AppCuKeys           : \\\"\\\\E[H\\\"\\n\"\n\"key End         -AnyMod     -AppCuKeys           : \\\"\\\\E[F\\\"\\n\"\n\"key Home        -AnyMod     +AppCuKeys           : \\\"\\\\EOH\\\"\\n\"\n\"key End         -AnyMod     +AppCuKeys           : \\\"\\\\EOF\\\"\\n\"\n\"key Home        +AnyMod                          : \\\"\\\\E[1;*H\\\"\\n\"\n\"key End         +AnyMod                          : \\\"\\\\E[1;*F\\\"\\n\"\n\"key Insert      -AnyMod                          : \\\"\\\\E[2~\\\"\\n\"\n\"key Delete      -AnyMod                          : \\\"\\\\E[3~\\\"\\n\"\n\"key Insert      +AnyMod                          : \\\"\\\\E[2;*~\\\"\\n\"\n\"key Delete      +AnyMod                          : \\\"\\\\E[3;*~\\\"\\n\"\n\"key Prior -Shift-AnyMod                          : \\\"\\\\E[5~\\\"\\n\"\n\"key Next  -Shift-AnyMod                          : \\\"\\\\E[6~\\\"\\n\"\n\"key Prior -Shift+AnyMod                          : \\\"\\\\E[5;*~\\\"\\n\"\n\"key Next  -Shift+AnyMod                          : \\\"\\\\E[6;*~\\\"\\n\"\n\"key F1          -AnyMod                          : \\\"\\\\EOP\\\"\\n\"\n\"key F2          -AnyMod                          : \\\"\\\\EOQ\\\"\\n\"\n\"key F3          -AnyMod                          : \\\"\\\\EOR\\\"\\n\"\n\"key F4          -AnyMod                          : \\\"\\\\EOS\\\"\\n\"\n\"key F5          -AnyMod                          : \\\"\\\\E[15~\\\"\\n\"\n\"key F6          -AnyMod                          : \\\"\\\\E[17~\\\"\\n\"\n\"key F7          -AnyMod                          : \\\"\\\\E[18~\\\"\\n\"\n\"key F8          -AnyMod                          : \\\"\\\\E[19~\\\"\\n\"\n\"key F9          -AnyMod                          : \\\"\\\\E[20~\\\"\\n\"\n\"key F10         -AnyMod                          : \\\"\\\\E[21~\\\"\\n\"\n\"key F11         -AnyMod                          : \\\"\\\\E[23~\\\"\\n\"\n\"key F12         -AnyMod                          : \\\"\\\\E[24~\\\"\\n\"\n\"key F1          +AnyMod                          : \\\"\\\\EO*P\\\"\\n\"\n\"key F2          +AnyMod                          : \\\"\\\\EO*Q\\\"\\n\"\n\"key F3          +AnyMod                          : \\\"\\\\EO*R\\\"\\n\"\n\"key F4          +AnyMod                          : \\\"\\\\EO*S\\\"\\n\"\n\"key F5          +AnyMod                          : \\\"\\\\E[15;*~\\\"\\n\"\n\"key F6          +AnyMod                          : \\\"\\\\E[17;*~\\\"\\n\"\n\"key F7          +AnyMod                          : \\\"\\\\E[18;*~\\\"\\n\"\n\"key F8          +AnyMod                          : \\\"\\\\E[19;*~\\\"\\n\"\n\"key F9          +AnyMod                          : \\\"\\\\E[20;*~\\\"\\n\"\n\"key F10         +AnyMod                          : \\\"\\\\E[21;*~\\\"\\n\"\n\"key F11         +AnyMod                          : \\\"\\\\E[23;*~\\\"\\n\"\n\"key F12         +AnyMod                          : \\\"\\\\E[24;*~\\\"\\n\"\n\"key Space +Control          : \\\"\\\\x00\\\"\\n\"\n\"key Up    +Shift-AppScreen  : scrollLineUp\\n\"\n\"key Prior +Shift-AppScreen  : scrollPageUp\\n\"\n\"key Down  +Shift-AppScreen  : scrollLineDown\\n\"\n\"key Next  +Shift-AppScreen  : scrollPageDown\\n\"\n\"key ScrollLock              : scrollLock\\n\"\n\"\\0\"\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslatorMac.h",
    "content": "\"keyboard \\\"Default (XFree 4)\\\"\"\n\"key Escape             : \\\"\\\\x1b\\\"\"\n\"key Tab   -Shift       : \\\"\\\\t\\\"\\n\"\n\"key Tab   +Shift+Ansi  : \\\"\\\\E[Z\\\"\\n\"\n\"key Tab   +Shift-Ansi  : \\\"\\\\t\\\"\\n\"\n\"key Backtab     +Ansi  : \\\"\\\\E[Z\\\"\\n\"\n\"key Backtab     -Ansi  : \\\"\\\\t\\\"\\n\"\n\"key Return-Shift-NewLine : \\\"\\\\r\\\"\\n\"\n\"key Return-Shift+NewLine : \\\"\\\\r\\\\n\\\"\\n\"\n\"key Return+Shift         : \\\"\\\\EOM\\\"\\n\"\n\"key Backspace      : \\\"\\\\x7f\\\"\\n\"\n\"key Meta +C        : \\\"\\\\x03\\\"\\n\"\n\"key Up    -Shift+Ansi-AppCuKeys : \\\"\\\\E[A\\\"\\n\"\n\"key Down  -Shift+Ansi-AppCuKeys : \\\"\\\\E[B\\\"\\n\"\n\"key Right -Shift+Ansi-AppCuKeys : \\\"\\\\E[C\\\"\\n\"\n\"key Left  -Shift+Ansi-AppCuKeys : \\\"\\\\E[D\\\"\\n\"\n\"key Up          -Ansi                            : \\\"\\\\E[1;*A\\\"\\n\"\n\"key Down        -Ansi                            : \\\"\\\\E[1;*B\\\"\\n\"\n\"key Right       -Ansi                            : \\\"\\\\E[1;*C\\\"\\n\"\n\"key Left        -Ansi                            : \\\"\\\\E[1;*D\\\"\\n\"\n\"key Enter+NewLine : \\\"\\\\r\\\\n\\\"\\n\"\n\"key Enter-NewLine : \\\"\\\\r\\\"\\n\"\n\"key Home        -AnyMod     -AppCuKeys           : \\\"\\\\E[H\\\"\\n\"\n\"key End         -AnyMod     -AppCuKeys           : \\\"\\\\E[F\\\"\\n\"\n\"key Home        -AnyMod     +AppCuKeys           : \\\"\\\\EOH\\\"\\n\"\n\"key End         -AnyMod     +AppCuKeys           : \\\"\\\\EOF\\\"\\n\"\n\"key Home        +AnyMod                          : \\\"\\\\E[1;*H\\\"\\n\"\n\"key End         +AnyMod                          : \\\"\\\\E[1;*F\\\"\\n\"\n\"key Insert      -AnyMod                          : \\\"\\\\E[2~\\\"\\n\"\n\"key Delete      -AnyMod                          : \\\"\\\\E[3~\\\"\\n\"\n\"key Insert      +AnyMod                          : \\\"\\\\E[2;*~\\\"\\n\"\n\"key Delete      +AnyMod                          : \\\"\\\\E[3;*~\\\"\\n\"\n\"key Prior -Shift-AnyMod                          : \\\"\\\\E[5~\\\"\\n\"\n\"key Next  -Shift-AnyMod                          : \\\"\\\\E[6~\\\"\\n\"\n\"key Prior -Shift+AnyMod                          : \\\"\\\\E[5;*~\\\"\\n\"\n\"key Next  -Shift+AnyMod                          : \\\"\\\\E[6;*~\\\"\\n\"\n\"key F1          -AnyMod                          : \\\"\\\\EOP\\\"\\n\"\n\"key F2          -AnyMod                          : \\\"\\\\EOQ\\\"\\n\"\n\"key F3          -AnyMod                          : \\\"\\\\EOR\\\"\\n\"\n\"key F4          -AnyMod                          : \\\"\\\\EOS\\\"\\n\"\n\"key F5          -AnyMod                          : \\\"\\\\EOT\\\"\\n\"\n\"key F6          -AnyMod                          : \\\"\\\\EOU\\\"\\n\"\n\"key F7          -AnyMod                          : \\\"\\\\EOV\\\"\\n\"\n\"key F8          -AnyMod                          : \\\"\\\\EOW\\\"\\n\"\n\"key F9          -AnyMod                          : \\\"\\\\EOX\\\"\\n\"\n\"key F10         -AnyMod                          : \\\"\\\\EOY\\\"\\n\"\n\"key Space +Control          : \\\"\\\\x00\\\"\\n\"\n\"key Up    +Shift-AppScreen  : scrollLineUp\\n\"\n\"key Prior +Shift-AppScreen  : scrollPageUp\\n\"\n\"key Down  +Shift-AppScreen  : scrollLineDown\\n\"\n\"key Next  +Shift-AppScreen  : scrollPageDown\\n\"\n\"key ScrollLock              : scrollLock\\n\"\n\"\\0\"\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/Filter.cpp",
    "content": "/*\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n    Adoption to octave by Torsten <mttl@mailbox.org>, Copyright (c) 2017\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n// Own\n#include \"unix/Filter.h\"\n\n// Qt\n#include <QtCore>\n\n#include <QAction>\n#include <QApplication>\n#include <QClipboard>\n#include <QDesktopServices>\n#include <QSharedData>\n#include <QString>\n\n// Konsole\n#include \"unix/TerminalCharacterDecoder.h\"\n\nFilterChain::~FilterChain()\n{\n    QMutableListIterator<Filter*> iter(*this);\n\n    while ( iter.hasNext() )\n    {\n        Filter* filter = iter.next();\n        iter.remove();\n        delete filter;\n    }\n}\n\nvoid FilterChain::addFilter(Filter* filter)\n{\n    append(filter);\n}\nvoid FilterChain::removeFilter(Filter* filter)\n{\n    removeAll(filter);\n}\nbool FilterChain::containsFilter(Filter* filter)\n{\n    return contains(filter);\n}\nvoid FilterChain::reset()\n{\n    QListIterator<Filter*> iter(*this);\n    while (iter.hasNext())\n        iter.next()->reset();\n}\nvoid FilterChain::setBuffer(const QString* buffer , const QList<int>* linePositions)\n{\n    QListIterator<Filter*> iter(*this);\n    while (iter.hasNext())\n        iter.next()->setBuffer(buffer,linePositions);\n}\nvoid FilterChain::process()\n{\n    QListIterator<Filter*> iter(*this);\n    while (iter.hasNext())\n        iter.next()->process();\n}\nvoid FilterChain::clear()\n{\n    QList<Filter*>::clear();\n}\nFilter::HotSpot* FilterChain::hotSpotAt(int line , int column) const\n{\n    QListIterator<Filter*> iter(*this);\n    while (iter.hasNext())\n    {\n        Filter* filter = iter.next();\n        Filter::HotSpot* spot = filter->hotSpotAt(line,column);\n        if ( spot != nullptr )\n        {\n            return spot;\n        }\n    }\n\n    return nullptr;\n}\n\nQList<Filter::HotSpot*> FilterChain::hotSpots() const\n{\n    QList<Filter::HotSpot*> list;\n    QListIterator<Filter*> iter(*this);\n    while (iter.hasNext())\n    {\n        Filter* filter = iter.next();\n        list << filter->hotSpots();\n    }\n    return list;\n}\n\nTerminalImageFilterChain::TerminalImageFilterChain()\n: _buffer(nullptr)\n, _linePositions(nullptr)\n{\n}\n\nTerminalImageFilterChain::~TerminalImageFilterChain()\n{\n    delete _buffer;\n    delete _linePositions;\n}\n\nvoid TerminalImageFilterChain::setImage(const Character* const image , int lines , int columns, const QVector<LineProperty>& lineProperties)\n{\n//qDebug(\"%s %d\", __FILE__, __LINE__);\n    if (empty())\n        return;\n//qDebug(\"%s %d\", __FILE__, __LINE__);\n\n    // reset all filters and hotspots\n    reset();\n//qDebug(\"%s %d\", __FILE__, __LINE__);\n\n    PlainTextDecoder decoder;\n    decoder.setTrailingWhitespace(false);\n\n//qDebug(\"%s %d\", __FILE__, __LINE__);\n    // setup new shared buffers for the filters to process on\n    QString* newBuffer = new QString();\n    QList<int>* newLinePositions = new QList<int>();\n    setBuffer( newBuffer , newLinePositions );\n\n    // free the old buffers\n    delete _buffer;\n    delete _linePositions;\n\n    _buffer = newBuffer;\n    _linePositions = newLinePositions;\n\n    QTextStream lineStream(_buffer);\n    decoder.begin(&lineStream);\n\n    for (int i=0 ; i < lines ; i++)\n    {\n        _linePositions->append(_buffer->length());\n        decoder.decodeLine(image + i*columns,columns,LINE_DEFAULT);\n\n        // pretend that each line ends with a newline character.\n        // this prevents a link that occurs at the end of one line\n        // being treated as part of a link that occurs at the start of the next line\n        //\n        // the downside is that links which are spread over more than one line are not\n        // highlighted.\n        //\n        // TODO - Use the \"line wrapped\" attribute associated with lines in a\n        // terminal image to avoid adding this imaginary character for wrapped\n        // lines\n        if ( !(lineProperties.value(i,LINE_DEFAULT) & LINE_WRAPPED) )\n        \tlineStream << QChar('\\n');\n    }\n    decoder.end();\n//    qDebug(\"%s %d\", __FILE__, __LINE__);\n}\n\nFilter::Filter() :\n_linePositions(nullptr),\n_buffer(nullptr)\n{\n}\n\nFilter::~Filter()\n{\n    QListIterator<HotSpot*> iter(_hotspotList);\n    while (iter.hasNext())\n    {\n        delete iter.next();\n    }\n}\nvoid Filter::reset()\n{\n    _hotspots.clear();\n    _hotspotList.clear();\n}\n\nvoid Filter::setBuffer(const QString* buffer , const QList<int>* linePositions)\n{\n    _buffer = buffer;\n    _linePositions = linePositions;\n}\n\nvoid Filter::getLineColumn(int position , int& startLine , int& startColumn)\n{\n    Q_ASSERT( _linePositions );\n    Q_ASSERT( _buffer );\n\n\n    for (int i = 0 ; i < _linePositions->count() ; i++)\n    {\n        //kDebug() << \"line position at \" << i << \" = \" << _linePositions[i];\n        int nextLine = 0;\n\n        if ( i == _linePositions->count()-1 )\n        {\n            nextLine = _buffer->length() + 1;\n        }\n        else\n        {\n            nextLine = _linePositions->value(i+1);\n        }\n\n       // kDebug() << \"pos - \" << position << \" line pos(\" << i<< \") \" << _linePositions->value(i) <<\n       //     \" next = \" << nextLine << \" buffer len = \" << _buffer->length();\n\n        if ( _linePositions->value(i) <= position && position < nextLine )\n        {\n            startLine = i;\n            startColumn = position - _linePositions->value(i);\n            return;\n        }\n    }\n}\n\n\n/*void Filter::addLine(const QString& text)\n{\n    _linePositions << _buffer.length();\n    _buffer.append(text);\n}*/\n\nconst QString* Filter::buffer()\n{\n    return _buffer;\n}\nFilter::HotSpot::~HotSpot()\n{\n}\nvoid Filter::addHotSpot(HotSpot* spot)\n{\n    _hotspotList << spot;\n\n    for (int line = spot->startLine() ; line <= spot->endLine() ; line++)\n    {\n        _hotspots.insert(line,spot);\n    }\n}\nQList<Filter::HotSpot*> Filter::hotSpots() const\n{\n    return _hotspotList;\n}\nQList<Filter::HotSpot*> Filter::hotSpotsAtLine(int line) const\n{\n    return _hotspots.values(line);\n}\n\nFilter::HotSpot* Filter::hotSpotAt(int line , int column) const\n{\n    QListIterator<HotSpot*> spotIter(_hotspots.values(line));\n\n    while (spotIter.hasNext())\n    {\n        HotSpot* spot = spotIter.next();\n\n        if ( spot->startLine() == line && spot->startColumn() > column )\n            continue;\n        if ( spot->endLine() == line && spot->endColumn() < column )\n            continue;\n\n        return spot;\n    }\n\n    return nullptr;\n}\n\nFilter::HotSpot::HotSpot(int startLine , int startColumn , int endLine , int endColumn)\n    : _startLine(startLine)\n    , _startColumn(startColumn)\n    , _endLine(endLine)\n    , _endColumn(endColumn)\n    , _type(NotSpecified)\n{\n}\nQString Filter::HotSpot::tooltip() const\n{\n    return QString();\n}\nQList<QAction*> Filter::HotSpot::actions()\n{\n    return QList<QAction*>();\n}\nint Filter::HotSpot::startLine() const\n{\n    return _startLine;\n}\nint Filter::HotSpot::endLine() const\n{\n    return _endLine;\n}\nint Filter::HotSpot::startColumn() const\n{\n    return _startColumn;\n}\nint Filter::HotSpot::endColumn() const\n{\n    return _endColumn;\n}\nFilter::Type Filter::HotSpot::type() const\n{\n    return _type;\n}\nvoid Filter::HotSpot::setType(Filter::Type type)\n{\n    _type = type;\n}\n\nRegExpFilter::RegExpFilter(Type t)\n    : _type (t)\n{\n}\n\nRegExpFilter::HotSpot::HotSpot(int startLine,int startColumn,\n                               int endLine,int endColumn, Filter::Type t)\n    : Filter::HotSpot(startLine,startColumn,endLine,endColumn)\n{\n    setType(t);\n}\n\nvoid RegExpFilter::HotSpot::activate(QObject*)\n{\n}\n\nvoid RegExpFilter::HotSpot::setCapturedTexts(const QStringList& texts)\n{\n    _capturedTexts = texts;\n}\nQStringList RegExpFilter::HotSpot::capturedTexts() const\n{\n    return _capturedTexts;\n}\n\nvoid RegExpFilter::setRegExp (const QRegularExpression& regExp)\n{\n    _searchText = regExp;\n}\nQRegularExpression RegExpFilter::regExp () const\n{\n    return _searchText;\n}\n/*void RegExpFilter::reset(int)\n{\n    _buffer = QString();\n}*/\nvoid RegExpFilter::process ()\n{\n    int pos = 0;\n    const QString* text = buffer();\n\n    Q_ASSERT( text );\n\n    // ignore any regular expressions which match an empty string.\n    // otherwise the while loop below will run indefinitely\n    static const QString emptyString(\"\");\n    QRegularExpressionMatch match = _searchText.match (emptyString);\n    if ( match.hasMatch () )\n        return;\n\n    match = _searchText.match (*text, pos);\n    while (match.hasMatch ())\n    {\n        pos = match.capturedStart ();\n        int startLine = 0;\n        int endLine = 0;\n        int startColumn = 0;\n        int endColumn = 0;\n\n        //kDebug() << \"pos from \" << pos << \" to \" << pos + _searchText.matchedLength();\n\n        getLineColumn (match.capturedStart (), startLine, startColumn);\n        getLineColumn (match.capturedEnd (), endLine, endColumn);\n\n        RegExpFilter::HotSpot* spot = newHotSpot(startLine,startColumn,\n                                       endLine,endColumn,_type);\n        spot->setCapturedTexts (match.capturedTexts ());\n\n        addHotSpot( spot );\n        pos += match.capturedLength ();\n\n        // if matchedLength == 0, the program will get stuck in an infinite loop\n        Q_ASSERT( match.capturedLength () > 0 );\n\n        match = _searchText.match (*text, pos);\n    }\n}\n\nRegExpFilter::HotSpot* RegExpFilter::newHotSpot(int startLine,int startColumn,\n                                                int endLine,int endColumn,\n                                                Filter::Type t)\n{\n    return new RegExpFilter::HotSpot(startLine,startColumn,\n                                     endLine,endColumn, t);\n}\nUrlFilter::HotSpot* UrlFilter::newHotSpot(int startLine,int startColumn,int endLine,\n                                                    int endColumn, Filter::Type t)\n{\n    return new UrlFilter::HotSpot(startLine,startColumn,\n                                               endLine,endColumn,t);\n}\n\nvoid UrlFilter::process ()\n{\n    int pos = 0;\n    const QString* text = buffer();\n\n    Q_ASSERT( text );\n\n    // ignore any regular expressions which match an empty string.\n    // otherwise the while loop below will run indefinitely\n    static const QString emptyString(\"\");\n    QRegularExpressionMatch match = _searchText.match (emptyString);\n    if ( match.hasMatch () )\n        return;\n\n    match = _searchText.match (*text, pos);\n    while (match.hasMatch ())\n    {\n        int startLine = 0;\n        int endLine = 0;\n        int startColumn = 0;\n        int endColumn = 0;\n\n        //kDebug() << \"pos from \" << pos << \" to \" << pos + _searchText.matchedLength();\n\n        getLineColumn (match.capturedStart (), startLine, startColumn);\n        getLineColumn (match.capturedEnd (), endLine, endColumn);\n\n        UrlFilter::HotSpot* spot = newHotSpot(startLine,startColumn,\n                                              endLine,endColumn,_type);\n        spot->setCapturedTexts(match.capturedTexts ());\n\n        // Connect the signal of the urlobject to the slot of the filter;\n        // the filter is then signaling to the main window\n        connect (spot->get_urlObject (),\n                 SIGNAL (request_open_file_signal (const QString&, int)),\n                 this, SLOT (request_open_file (const QString&, int)));\n\n        addHotSpot( spot );\n        pos += match.capturedLength();\n\n        // if matchedLength == 0, the program will get stuck in an infinite loop\n        Q_ASSERT( match.capturedLength () > 0 );\n\n        match = _searchText.match (*text, pos);\n    }\n}\n\nUrlFilter::HotSpot::HotSpot(int startLine,int startColumn,\n                            int endLine,int endColumn,Type t)\n: RegExpFilter::HotSpot(startLine,startColumn,endLine,endColumn,t)\n, _urlObject(new FilterObject(this))\n{\n}\n\nQString UrlFilter::HotSpot::tooltip() const\n{\n    QString url = capturedTexts().first();\n\n    const UrlType kind = urlType();\n\n    if ( kind == StandardUrl )\n        return QString();\n    else if ( kind == Email )\n        return QString();\n    else\n        return QString();\n}\nUrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType () const\n{\n    QString url = capturedTexts().first();\n\n    QRegularExpressionMatch match = FullUrlRegExp.match (url);\n    if ( match.hasMatch () )\n        return StandardUrl;\n    match = EmailAddressRegExp.match (url);\n    if ( match.hasMatch () )\n        return Email;\n    match = ErrorLinkRegExp.match (url);\n    if ( match.hasMatch () )\n        return ErrorLink;\n    match = ParseErrorLinkRegExp.match (url);\n    if ( match.hasMatch () )\n        return ParseErrorLink;\n\n    return Unknown;\n}\n\nvoid UrlFilter::HotSpot::activate (QObject* object)\n{\n    QString url = capturedTexts().first();\n\n    const UrlType kind = urlType();\n\n    const QString& actionName = object ? object->objectName() : QString();\n\n    if ( actionName == \"copy-action\" )\n    {\n        //kDebug() << \"Copying url to clipboard:\" << url;\n\n        QApplication::clipboard()->setText(url);\n        return;\n    }\n\n    if ( !object || actionName == \"open-action\" )\n      {\n        if ( kind == StandardUrl )\n          {\n            // if the URL path does not include the protocol ( eg. \"www.kde.org\" ) then\n            // prepend http:// ( eg. \"www.kde.org\" --> \"http://www.kde.org\" )\n            if (!url.contains(\"://\"))\n              url.prepend(\"http://\");\n            QDesktopServices::openUrl (QUrl (url));\n          }\n        else if ( kind == Email )\n          {\n            url.prepend(\"mailto:\");\n            QDesktopServices::openUrl (QUrl (url));\n          }\n        else if (kind == ErrorLink)\n          {\n            QRegularExpressionMatch match = ErrorLinkRegExp.match (url);\n            if (match.hasMatch ())\n              {\n                QString file_name = match.captured (1);\n                QString line = match.captured (2);\n                // call the urlobject's method for opening a file; this\n                // method then signals to the filter\n                _urlObject->request_open_file (file_name, line.toInt ());\n              }\n          }\n        else if (kind == ParseErrorLink)\n          {\n            QRegularExpressionMatch match = ParseErrorLinkRegExp.match (url);\n            if (match.hasMatch ())\n              {\n                QString line = match.captured (1);\n                QString file_name = match.captured (2);\n                // call the urlobject's method for opening a file; this\n                // method then signals to the filter\n                _urlObject->request_open_file (file_name, line.toInt ());\n              }\n          }\n\n\n      }\n\n}\n\n// Note:  Altering these regular expressions can have a major effect on the performance of the filters\n// used for finding URLs in the text, especially if they are very general and could match very long\n// pieces of text.\n// Please be careful when altering them.\n\n//regexp matches:\n// full url:\n// protocolname:// or www. followed by anything other than whitespaces, <, >, ' or \", and ends before whitespaces, <, >, ', \", ], !, comma and dot\nconst QRegularExpression\nUrlFilter::FullUrlRegExp {\"(www\\\\.(?!\\\\.)|[a-z][a-z0-9+.-]*://)[^\\\\s<>'\\\"]+[^!,\\\\.\\\\s<>'\\\"\\\\]]\"};\n// email address:\n// [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]\nconst QRegularExpression\nUrlFilter::EmailAddressRegExp {\"\\\\b(\\\\w|\\\\.|-)+@(\\\\w|\\\\.|-)+\\\\.\\\\w+\\\\b\"};\n// matches full url or email address\nconst QRegularExpression\nUrlFilter::CompleteUrlRegExp {'(' + FullUrlRegExp.pattern() + '|' +\n                              EmailAddressRegExp.pattern() + ')'};\n// error link:\n//   normal error\nconst QRegularExpression\nUrlFilter::ErrorLinkRegExp {\"(\\\\S+) at line (\\\\d+) column (?:\\\\d+)\"};\n//   parse error\nconst QRegularExpression\nUrlFilter::ParseErrorLinkRegExp {\"parse error near line (\\\\d+) of file (\\\\S+)\"};\n//   complete regexp\nconst QRegularExpression\nUrlFilter::CompleteErrorLinkRegExp {'('+ErrorLinkRegExp.pattern ()+'|'+\n                                    ParseErrorLinkRegExp.pattern ()+')'};\n\n\nUrlFilter::UrlFilter (Type t)\n    : RegExpFilter (t)\n{\n    if (_type == ErrorLink)\n      setRegExp (CompleteErrorLinkRegExp);\n    else\n      setRegExp (CompleteUrlRegExp);\n}\nUrlFilter::HotSpot::~HotSpot()\n{\n    delete _urlObject;\n}\nvoid FilterObject::activated()\n{\n    _filter->activate(sender());\n}\nQList<QAction*> UrlFilter::HotSpot::actions ()\n{\n    QList<QAction*> list;\n\n    const UrlType kind = urlType();\n\n    QAction* openAction = new QAction(_urlObject);\n    QAction* copyAction = new QAction(_urlObject);\n\n    Q_ASSERT (kind == StandardUrl || kind == Email\n                                  || kind == ErrorLink\n                                  || kind == ParseErrorLink);\n\n    if ( kind == StandardUrl )\n    {\n        openAction->setText(tr (\"Open Link\"));\n        copyAction->setText(tr (\"Copy Link Address\"));\n    }\n    else if ( kind == Email )\n    {\n        openAction->setText(tr (\"Send Email To...\"));\n        copyAction->setText(tr (\"Copy Email Address\"));\n    }\n    else if ( kind == ErrorLink )\n    {\n      QString url = capturedTexts().first();\n      QRegularExpressionMatch match = ErrorLinkRegExp.match (url);\n      if (match.hasMatch ())\n        {\n          QString file_name = match.captured (1);\n          QString line = match.captured (2);\n          openAction->setText(tr (\"Edit %1 at line %2\")\n                              .arg (file_name).arg (line));\n        }\n    }\n    else if ( kind == ParseErrorLink )\n    {\n      QString url = capturedTexts().first();\n      QRegularExpressionMatch match = ParseErrorLinkRegExp.match (url);\n      if (match.hasMatch ())\n        {\n          QString line = match.captured (1);\n          QString file_name = match.captured (2);\n          openAction->setText(tr (\"Edit %1 at line %2\")\n                              .arg (file_name).arg (line));\n        }\n    }\n\n    // object names are set here so that the hotspot performs the\n    // correct action when activated() is called with the triggered\n    // action passed as a parameter.\n    openAction->setObjectName(\"open-action\");\n    copyAction->setObjectName(\"copy-action\");\n\n    QObject::connect( openAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );\n    list << openAction;\n\n    if (kind != ErrorLink && kind != ParseErrorLink)\n      {\n        QObject::connect ( copyAction , SIGNAL(triggered()) ,\n                           _urlObject , SLOT(activated()) );\n        list << copyAction;\n      }\n    return list;\n}\n\nvoid\nUrlFilter::request_open_file (const QString& file, int line)\n{\n  QFileInfo file_info = QFileInfo (file);\n\n  // We have to distinguish between a parse error, where we get the full\n  // path of the file or a general error in a script, where we only get\n  // the function name. depending on this we have to invoke different\n  // slots in main_window\n  if (file_info.isAbsolute () && file_info.exists ())\n    Q_EMIT request_open_file_signal (file, QString (), line);\n  else\n    Q_EMIT request_edit_mfile_signal (file, line);\n}\n\n//#include \"moc_Filter.cpp\"\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/Filter.h",
    "content": "/*\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n    Adoption to octave by Torsten <mttl@mailbox.org>, Copyright (c) 2017\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef FILTER_H\n#define FILTER_H\n\n// Qt\n#include <QAction>\n#include <QHash>\n#include <QList>\n#include <QObject>\n#include <QRegularExpression>\n#include <QStringList>\n\n// Local\n#include \"unix/Character.h\"\n\n/**\n * A filter processes blocks of text looking for certain patterns (such as URLs or keywords from a list)\n * and marks the areas which match the filter's patterns as 'hotspots'.\n *\n * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),\n * and an action.  When the user performs some activity such as a mouse-click in a hotspot area ( the exact\n * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's\n * activate() method should be called.  Depending on the type of hotspot this will trigger a suitable response.\n *\n * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser.\n * Hotspots may have more than one action, in which case the list of actions can be obtained using the\n * actions() method.\n *\n * Different subclasses of filter will return different types of hotspot.\n * Subclasses must reimplement the process() method to examine a block of text and identify sections of interest.\n * When processing the text they should create instances of Filter::HotSpot subclasses for sections of interest\n * and add them to the filter's list of hotspots using addHotSpot()\n */\nclass Filter : public QObject\n{\n\n   Q_OBJECT\n\npublic:\n    /**\n    * Represents an area of text which matched the pattern a particular filter has been looking for.\n    *\n    * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),\n    * and an action.  When the user performs some activity such as a mouse-click in a hotspot area ( the exact\n    * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's\n    * activate() method should be called.  Depending on the type of hotspot this will trigger a suitable response.\n    *\n    * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser.\n    * Hotspots may have more than one action, in which case the list of actions can be obtained using the\n    * actions() method.  These actions may then be displayed in a popup menu or toolbar for example.\n    */\n\n    enum Type\n    {\n      // the type of the hotspot is not specified\n      NotSpecified,\n      // this hotspot represents a clickable link\n      Link,\n      // this hotspot represents a marker\n      Marker,\n      // this hotspot represents a clickable link to an erroneous file\n      ErrorLink\n    };\n\n    class HotSpot : public QObject\n    {\n\n    public:\n       /**\n        * Constructs a new hotspot which covers the area from (@p startLine,@p startColumn) to (@p endLine,@p endColumn)\n        * in a block of text.\n        */\n       HotSpot(int startLine , int startColumn , int endLine , int endColumn);\n       virtual ~HotSpot();\n\n       /** Returns the line when the hotspot area starts */\n       int startLine() const;\n       /** Returns the line where the hotspot area ends */\n       int endLine() const;\n       /** Returns the column on startLine() where the hotspot area starts */\n       int startColumn() const;\n       /** Returns the column on endLine() where the hotspot area ends */\n       int endColumn() const;\n       /**\n        * Returns the type of the hotspot.  This is usually used as a hint for views on how to represent\n        * the hotspot graphically.  eg.  Link hotspots are typically underlined when the user mouses over them\n        */\n       Type type() const;\n       /**\n        * Causes the an action associated with a hotspot to be triggered.\n        *\n        * @param object The object which caused the hotspot to be triggered.  This is\n        * typically null ( in which case the default action should be performed ) or\n        * one of the objects from the actions() list.  In which case the associated\n        * action should be performed.\n        */\n       virtual void activate(QObject* object = nullptr) = 0;\n       /**\n        * Returns a list of actions associated with the hotspot which can be used in a\n        * menu or toolbar\n        */\n       virtual QList<QAction*> actions();\n\n       /**\n        * Returns the text of a tooltip to be shown when the mouse moves over the hotspot, or\n        * an empty string if there is no tooltip associated with this hotspot.\n        *\n        * The default implementation returns an empty string.\n        */\n       virtual QString tooltip() const;\n\n    protected:\n       /** Sets the type of a hotspot.  This should only be set once */\n       void setType(Type type);\n\n    private:\n       int    _startLine;\n       int    _startColumn;\n       int    _endLine;\n       int    _endColumn;\n       Type _type;\n\n    };\n\n    /** Constructs a new filter. */\n    Filter();\n    virtual ~Filter();\n\n    /** Causes the filter to process the block of text currently in its internal buffer */\n    virtual void process() = 0;\n\n    /**\n     * Empties the filters internal buffer and resets the line count back to 0.\n     * All hotspots are deleted.\n     */\n    void reset();\n\n    /** Adds a new line of text to the filter and increments the line count */\n    //void addLine(const QString& string);\n\n    /** Returns the hotspot which covers the given @p line and @p column, or 0 if no hotspot covers that area */\n    HotSpot* hotSpotAt(int line , int column) const;\n\n    /** Returns the list of hotspots identified by the filter */\n    QList<HotSpot*> hotSpots() const;\n\n    /** Returns the list of hotspots identified by the filter which occur on a given line */\n    QList<HotSpot*> hotSpotsAtLine(int line) const;\n\n    /**\n     * TODO: Document me\n     */\n    void setBuffer(const QString* buffer , const QList<int>* linePositions);\n\nprotected:\n    /** Adds a new hotspot to the list */\n    void addHotSpot(HotSpot*);\n    /** Returns the internal buffer */\n    const QString* buffer();\n    /** Converts a character position within buffer() to a line and column */\n    void getLineColumn(int position , int& startLine , int& startColumn);\n\nprivate:\n    QMultiHash<int,HotSpot*> _hotspots;\n    QList<HotSpot*> _hotspotList;\n\n    const QList<int>* _linePositions;\n    const QString* _buffer;\n};\n\n/**\n * A filter which searches for sections of text matching a regular expression and creates a new RegExpFilter::HotSpot\n * instance for them.\n *\n * Subclasses can reimplement newHotSpot() to return custom hotspot types when matches for the regular expression\n * are found.\n */\nclass RegExpFilter : public Filter\n{\n\n   Q_OBJECT\n\npublic:\n    /**\n     * Type of hotspot created by RegExpFilter.  The capturedTexts() method can be used to find the text\n     * matched by the filter's regular expression.\n     */\n    class HotSpot : public Filter::HotSpot\n    {\n    public:\n        HotSpot(int startLine, int startColumn,\n                int endLine , int endColumn, Filter::Type);\n        virtual void activate(QObject* object = nullptr);\n\n        /** Sets the captured texts associated with this hotspot */\n        void setCapturedTexts(const QStringList& texts);\n        /** Returns the texts found by the filter when matching the filter's regular expression */\n        QStringList capturedTexts() const;\n     private:\n        QStringList _capturedTexts;\n    };\n\n    /** Constructs a new regular expression filter */\n    RegExpFilter (Type);\n\n    /**\n     * Sets the regular expression which the filter searches for in blocks of text.\n     *\n     * Regular expressions which match the empty string are treated as not matching\n     * anything.\n     */\n    void setRegExp(const QRegularExpression& text);\n    /** Returns the regular expression which the filter searches for in blocks of text */\n    QRegularExpression regExp() const;\n\n    /**\n     * Reimplemented to search the filter's text buffer for text matching regExp()\n     *\n     * If regexp matches the empty string, then process() will return immediately\n     * without finding results.\n     */\n    virtual void process();\n\nQ_SIGNALS:\n\n    void request_edit_mfile_signal (const QString&, int);\n    void request_open_file_signal (const QString&, const QString&, int);\n\nprotected:\n    /**\n     * Called when a match for the regular expression is encountered.  Subclasses should reimplement this\n     * to return custom hotspot types\n     */\n    virtual RegExpFilter::HotSpot* newHotSpot(int startLine,int startColumn,\n                                    int endLine,int endColumn, Type);\n    Type _type;\n\n    QRegularExpression _searchText;\n};\n\nclass FilterObject;\n\n/** A filter which matches URLs in blocks of text */\nclass UrlFilter : public RegExpFilter\n{\n\n   Q_OBJECT\n\npublic:\n    /**\n     * Hotspot type created by UrlFilter instances.  The activate() method opens a web browser\n     * at the given URL when called.\n     */\n    class HotSpot : public RegExpFilter::HotSpot\n    {\n    public:\n        HotSpot(int startLine,int startColumn,int endLine,int endColumn,Type t);\n        virtual ~HotSpot();\n\n        virtual QList<QAction*> actions();\n\n        /**\n         * Open a web browser at the current URL.  The url itself can be determined using\n         * the capturedTexts() method.\n         */\n        virtual void activate(QObject* object = nullptr);\n\n        virtual QString tooltip() const;\n\n        FilterObject* get_urlObject () { return _urlObject; }\n\n    private:\n        enum UrlType\n        {\n            StandardUrl,\n            Email,\n            ErrorLink,\n            ParseErrorLink,\n            Unknown\n        };\n        UrlType urlType() const;\n\n        FilterObject* _urlObject;\n    };\n\n    UrlFilter (Type t = Link);\n\n    virtual void process();\n\npublic Q_SLOTS:\n    void request_open_file (const QString&, int);\n\nprotected:\n    virtual HotSpot* newHotSpot(int,int,int,int,Type);\n\nprivate:\n\n    static const QRegularExpression FullUrlRegExp;\n    static const QRegularExpression EmailAddressRegExp;\n    static const QRegularExpression ErrorLinkRegExp;\n    static const QRegularExpression ParseErrorLinkRegExp;\n    static const QRegularExpression CompleteErrorLinkRegExp;\n\n    // combined OR of FullUrlRegExp and EmailAddressRegExp\n    static const QRegularExpression CompleteUrlRegExp;\n};\n\nclass FilterObject : public QObject\n{\nQ_OBJECT\npublic:\n    FilterObject(Filter::HotSpot* filter) : _filter(filter) {}\n    void request_open_file (const QString& file, int line)\n      { Q_EMIT request_open_file_signal (file, line); }\nQ_SIGNALS:\n    void request_open_file_signal (const QString&, int);\nprivate Q_SLOTS:\n    void activated();\nprivate:\n    Filter::HotSpot* _filter;\n};\n\n/**\n * A chain which allows a group of filters to be processed as one.\n * The chain owns the filters added to it and deletes them when the chain itself is destroyed.\n *\n * Use addFilter() to add a new filter to the chain.\n * When new text to be filtered arrives, use addLine() to add each additional\n * line of text which needs to be processed and then after adding the last line, use\n * process() to cause each filter in the chain to process the text.\n *\n * After processing a block of text, the reset() method can be used to set the filter chain's\n * internal cursor back to the first line.\n *\n * The hotSpotAt() method will return the first hotspot which covers a given position.\n *\n * The hotSpots() and hotSpotsAtLine() method return all of the hotspots in the text and on\n * a given line respectively.\n */\nclass FilterChain : protected QList<Filter*>\n{\npublic:\n    virtual ~FilterChain();\n\n    /** Adds a new filter to the chain.  The chain will delete this filter when it is destroyed */\n    void addFilter(Filter* filter);\n    /** Removes a filter from the chain.  The chain will no longer delete the filter when destroyed */\n    void removeFilter(Filter* filter);\n    /** Returns true if the chain contains @p filter */\n    bool containsFilter(Filter* filter);\n    /** Removes all filters from the chain */\n    void clear();\n\n    /** Resets each filter in the chain */\n    void reset();\n    /**\n     * Processes each filter in the chain\n     */\n    void process();\n\n    /** Sets the buffer for each filter in the chain to process. */\n    void setBuffer(const QString* buffer , const QList<int>* linePositions);\n\n    /** Returns the first hotspot which occurs at @p line, @p column or 0 if no hotspot was found */\n    Filter::HotSpot* hotSpotAt(int line , int column) const;\n    /** Returns a list of all the hotspots in all the chain's filters */\n    QList<Filter::HotSpot*> hotSpots() const;\n    /** Returns a list of all hotspots at the given line in all the chain's filters */\n    QList<Filter::HotSpot> hotSpotsAtLine(int line) const;\n\n};\n\n/** A filter chain which processes character images from terminal displays */\nclass TerminalImageFilterChain : public FilterChain\n{\npublic:\n    TerminalImageFilterChain();\n    virtual ~TerminalImageFilterChain();\n\n    /**\n     * Set the current terminal image to @p image.\n     *\n     * @param image The terminal image\n     * @param lines The number of lines in the terminal image\n     * @param columns The number of columns in the terminal image\n     */\n    void setImage(const Character* const image , int lines , int columns,\n\t\t\t\t  const QVector<LineProperty>& lineProperties);\n\nprivate:\n    QString* _buffer;\n    QList<int>* _linePositions;\n};\n\n#endif //FILTER_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/History.cpp",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n    Copyright (C) 1997-1998, 2013 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#include <algorithm>\n\n// Own\n#include \"unix/History.h\"\n\n// System\n#include <stdlib.h>\n#include <assert.h>\n#include <stdio.h>\n#include <sys/types.h>\n#include <sys/mman.h>\n#include <unistd.h>\n#include <errno.h>\n\n\n// Reasonable line size\n#define LINE_SIZE\t1024\n\n/*\n   An arbitrary long scroll.\n\n   One can modify the scroll only by adding either cells\n   or newlines, but access it randomly.\n\n   The model is that of an arbitrary wide typewriter scroll\n   in that the scroll is a serie of lines and each line is\n   a serie of cells with no overwriting permitted.\n\n   The implementation provides arbitrary length and numbers\n   of cells and line/column indexed read access to the scroll\n   at constant costs.\n\nKDE4: Can we use QTemporaryFile here, instead of KTempFile?\n\nFIXME: some complain about the history buffer comsuming the\n       memory of their machines. This problem is critical\n       since the history does not behave gracefully in cases\n       where the memory is used up completely.\n\n       I put in a workaround that should handle it problem\n       now gracefully. I'm not satisfied with the solution.\n\nFIXME: Terminating the history is not properly indicated\n       in the menu. We should throw a signal.\n\nFIXME: There is noticeable decrease in speed, also. Perhaps,\n       there whole feature needs to be revisited therefore.\n       Disadvantage of a more elaborated, say block-oriented\n       scheme with wrap around would be it's complexity.\n*/\n\n//FIXME: tempory replacement for tmpfile\n//       this is here one for debugging purpose.\n\n//#define tmpfile xTmpFile\n\n// History File ///////////////////////////////////////////\n\n/*\n  A Row(X) data type which allows adding elements to the end.\n*/\n\nHistoryFile::HistoryFile()\n  : ion(-1),\n    length(0),\n\tfileMap(nullptr)\n{\n  if (tmpFile.open())\n  {\n    tmpFile.setAutoRemove(true);\n    ion = tmpFile.handle();\n  }\n}\n\nHistoryFile::~HistoryFile()\n{\n\tif (fileMap)\n\t\tunmap();\n}\n\n//TODO:  Mapping the entire file in will cause problems if the history file becomes exceedingly large,\n//(ie. larger than available memory).  HistoryFile::map() should only map in sections of the file at a time,\n//to avoid this.\nvoid HistoryFile::map()\n{\n\tassert( fileMap == nullptr );\n\n\tfileMap = (char*)mmap( nullptr , length , PROT_READ , MAP_PRIVATE , ion , 0 );\n\n    //if mmap'ing fails, fall back to the read-lseek combination\n    if ( fileMap == MAP_FAILED )\n    {\n            readWriteBalance = 0;\n            fileMap = nullptr;\n            qDebug() << \": mmap'ing history failed.  errno = \" << errno;\n    }\n}\n\nvoid HistoryFile::unmap()\n{\n\tint result = munmap( fileMap , length );\n\tassert( result == 0 );\n\n\tfileMap = nullptr;\n}\n\nbool HistoryFile::isMapped()\n{\n\treturn (fileMap != nullptr);\n}\n\nvoid HistoryFile::add(const unsigned char* bytes, int len)\n{\n  if ( fileMap )\n\t\t  unmap();\n\t\t\n  readWriteBalance++;\n\n  int rc = 0;\n\n  rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror(\"HistoryFile::add.seek\"); return; }\n  rc = write(ion,bytes,len);       if (rc < 0) { perror(\"HistoryFile::add.write\"); return; }\n  length += rc;\n}\n\nvoid HistoryFile::get(unsigned char* bytes, int len, int loc)\n{\n  //count number of get() calls vs. number of add() calls.\n  //If there are many more get() calls compared with add()\n  //calls (decided by using MAP_THRESHOLD) then mmap the log\n  //file to improve performance.\n  readWriteBalance--;\n  if ( !fileMap && readWriteBalance < MAP_THRESHOLD )\n\t\t  map();\n\n  if ( fileMap )\n  {\n\tfor (int i=0;i<len;i++)\n\t\t\tbytes[i]=fileMap[loc+i];\n  }\n  else\n  {\t\n  \tint rc = 0;\n\n  \tif (loc < 0 || len < 0 || loc + len > length)\n    \tfprintf(stderr,\"getHist(...,%d,%d): invalid args.\\n\",len,loc);\n  \trc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror(\"HistoryFile::get.seek\"); return; }\n  \trc = read(ion,bytes,len);     if (rc < 0) { perror(\"HistoryFile::get.read\"); return; }\n  }\n}\n\nint HistoryFile::len()\n{\n  return length;\n}\n\n\n// History Scroll abstract base class //////////////////////////////////////\n\n\nHistoryScroll::HistoryScroll(HistoryType* t)\n  : m_histType(t)\n{\n}\n\nHistoryScroll::~HistoryScroll()\n{\n  delete m_histType;\n}\n\nbool HistoryScroll::hasScroll()\n{\n  return true;\n}\n\n// History Scroll File //////////////////////////////////////\n\n/*\n   The history scroll makes a Row(Row(Cell)) from\n   two history buffers. The index buffer contains\n   start of line positions which refere to the cells\n   buffer.\n\n   Note that index[0] addresses the second line\n   (line #1), while the first line (line #0) starts\n   at 0 in cells.\n*/\n\nHistoryScrollFile::HistoryScrollFile(const QString &logFileName)\n  : HistoryScroll(new HistoryTypeFile(logFileName)),\n  m_logFileName(logFileName)\n{\n}\n\nHistoryScrollFile::~HistoryScrollFile()\n{\n}\n\nint HistoryScrollFile::getLines()\n{\n  return index.len() / sizeof(int);\n}\n\nint HistoryScrollFile::getLineLen(int lineno)\n{\n  return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(Character);\n}\n\nbool HistoryScrollFile::isWrappedLine(int lineno)\n{\n  if (lineno>=0 && lineno <= getLines()) {\n    unsigned char flag;\n    lineflags.get((unsigned char*)&flag,sizeof(unsigned char),(lineno)*sizeof(unsigned char));\n    return flag;\n  }\n  return false;\n}\n\nint HistoryScrollFile::startOfLine(int lineno)\n{\n  if (lineno <= 0) return 0;\n  if (lineno <= getLines())\n    {\n\t\n\tif (!index.isMapped())\n\t\t\tindex.map();\n\t\n\tint res = 0;\n    index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int));\n    return res;\n    }\n  return cells.len();\n}\n\nvoid HistoryScrollFile::getCells(int lineno, int colno, int count, Character res[])\n{\n  cells.get((unsigned char*)res,count*sizeof(Character),startOfLine(lineno)+colno*sizeof(Character));\n}\n\nvoid HistoryScrollFile::addCells(const Character text[], int count)\n{\n  cells.add((unsigned char*)text,count*sizeof(Character));\n}\n\nvoid HistoryScrollFile::addLine(bool previousWrapped)\n{\n  if (index.isMapped())\n\t\t  index.unmap();\n\n  int locn = cells.len();\n  index.add((unsigned char*)&locn,sizeof(int));\n  unsigned char flags = previousWrapped ? 0x01 : 0x00;\n  lineflags.add((unsigned char*)&flags,sizeof(unsigned char));\n}\n\n\n// History Scroll Buffer //////////////////////////////////////\nHistoryScrollBuffer::HistoryScrollBuffer(unsigned int maxLineCount)\n  : HistoryScroll(new HistoryTypeBuffer(maxLineCount))\n   ,_historyBuffer()\n   ,_maxLineCount(0)\n   ,_usedLines(0)\n   ,_head(0)\n{\n  setMaxNbLines(maxLineCount);\n}\n\nHistoryScrollBuffer::~HistoryScrollBuffer()\n{\n    delete[] _historyBuffer;\n}\n\nvoid HistoryScrollBuffer::addCellsVector(const QVector<Character>& cells)\n{\n    _head++;\n    if ( _usedLines < _maxLineCount )\n        _usedLines++;\n\n    if ( _head >= _maxLineCount )\n    {\n        _head = 0;\n    }\n\n    _historyBuffer[bufferIndex(_usedLines-1)] = cells;\n    _wrappedLine[bufferIndex(_usedLines-1)] = false;\n}\nvoid HistoryScrollBuffer::addCells(const Character a[], int count)\n{\n  HistoryLine newLine(count);\n  std::copy(a,a+count,newLine.begin());\n\n  addCellsVector(newLine);\n}\n\nvoid HistoryScrollBuffer::addLine(bool previousWrapped)\n{\n    _wrappedLine[bufferIndex(_usedLines-1)] = previousWrapped;\n}\n\nint HistoryScrollBuffer::getLines()\n{\n    return _usedLines;\n}\n\nint HistoryScrollBuffer::getLineLen(int lineNumber)\n{\n  Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount );\n\n  if ( lineNumber < _usedLines )\n  {\n    return _historyBuffer[bufferIndex(lineNumber)].size();\n  }\n  else\n  {\n    return 0;\n  }\n}\n\nbool HistoryScrollBuffer::isWrappedLine(int lineNumber)\n{\n  Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount );\n\n  if (lineNumber < _usedLines)\n  {\n    //kDebug() << \"Line\" << lineNumber << \"wrapped is\" << _wrappedLine[bufferIndex(lineNumber)];\n    return _wrappedLine[bufferIndex(lineNumber)];\n  }\n  else\n    return false;\n}\n\nvoid HistoryScrollBuffer::getCells(int lineNumber, int startColumn, int count, Character* buffer)\n{\n  if ( count == 0 ) return;\n\n  Q_ASSERT( lineNumber < _maxLineCount );\n\n  if (lineNumber >= _usedLines)\n  {\n    memset(buffer, 0, count * sizeof(Character));\n    return;\n  }\n\n  const HistoryLine& line = _historyBuffer[bufferIndex(lineNumber)];\n\n  //kDebug() << \"startCol \" << startColumn;\n  //kDebug() << \"line.size() \" << line.size();\n  //kDebug() << \"count \" << count;\n\n  Q_ASSERT( startColumn <= line.size() - count );\n\n  memcpy(buffer, line.constData() + startColumn , count * sizeof(Character));\n}\n\nvoid HistoryScrollBuffer::setMaxNbLines(unsigned int lineCount)\n{\n    HistoryLine* oldBuffer = _historyBuffer;\n    HistoryLine* newBuffer = new HistoryLine[lineCount];\n\n    for ( int i = 0 ; i < qMin(_usedLines,(int)lineCount) ; i++ )\n    {\n        newBuffer[i] = oldBuffer[bufferIndex(i)];\n    }\n\n    _usedLines = qMin(_usedLines,(int)lineCount);\n    _maxLineCount = lineCount;\n    _head = ( _usedLines == _maxLineCount ) ? 0 : _usedLines-1;\n\n    _historyBuffer = newBuffer;\n    delete[] oldBuffer;\n\n    _wrappedLine.resize(lineCount);\n}\n\nint HistoryScrollBuffer::bufferIndex(int lineNumber)\n{\n    Q_ASSERT( lineNumber >= 0 );\n    Q_ASSERT( lineNumber < _maxLineCount );\n    Q_ASSERT( (_usedLines == _maxLineCount) || lineNumber <= _head );\n\n    if ( _usedLines == _maxLineCount )\n    {\n        return (_head+lineNumber+1) % _maxLineCount;\n    }\n    else\n    {\n        return lineNumber;\n    }\n}\n\n\n// History Scroll None //////////////////////////////////////\n\nHistoryScrollNone::HistoryScrollNone()\n  : HistoryScroll(new HistoryTypeNone())\n{\n}\n\nHistoryScrollNone::~HistoryScrollNone()\n{\n}\n\nbool HistoryScrollNone::hasScroll()\n{\n  return false;\n}\n\nint  HistoryScrollNone::getLines()\n{\n  return 0;\n}\n\nint  HistoryScrollNone::getLineLen(int)\n{\n  return 0;\n}\n\nbool HistoryScrollNone::isWrappedLine(int /*lineno*/)\n{\n  return false;\n}\n\nvoid HistoryScrollNone::getCells(int, int, int, Character [])\n{\n}\n\nvoid HistoryScrollNone::addCells(const Character [], int)\n{\n}\n\nvoid HistoryScrollNone::addLine(bool)\n{\n}\n\n// History Scroll BlockArray //////////////////////////////////////\n\nHistoryScrollBlockArray::HistoryScrollBlockArray(size_t size)\n  : HistoryScroll(new HistoryTypeBlockArray(size))\n{\n  m_blockArray.setHistorySize(size); // nb. of lines.\n}\n\nHistoryScrollBlockArray::~HistoryScrollBlockArray()\n{\n}\n\nint  HistoryScrollBlockArray::getLines()\n{\n  return m_lineLengths.count();\n}\n\nint  HistoryScrollBlockArray::getLineLen(int lineno)\n{\n    if ( m_lineLengths.contains(lineno) )\n        return m_lineLengths[lineno];\n    else\n        return 0;\n}\n\nbool HistoryScrollBlockArray::isWrappedLine(int /*lineno*/)\n{\n  return false;\n}\n\nvoid HistoryScrollBlockArray::getCells(int lineno, int colno,\n                                       int count, Character res[])\n{\n  if (!count) return;\n\n  const Block *b = m_blockArray.at(lineno);\n\n  if (!b) {\n    memset(res, 0, count * sizeof(Character)); // still better than random data\n    return;\n  }\n\n  assert(((colno + count) * sizeof(Character)) < ENTRIES);\n  memcpy(res, b->data + (colno * sizeof(Character)), count * sizeof(Character));\n}\n\nvoid HistoryScrollBlockArray::addCells(const Character a[], int count)\n{\n  Block *b = m_blockArray.lastBlock();\n\n  if (!b) return;\n\n  // put cells in block's data\n  assert((count * sizeof(Character)) < ENTRIES);\n\n  memset(b->data, 0, ENTRIES);\n\n  memcpy(b->data, a, count * sizeof(Character));\n  b->size = count * sizeof(Character);\n\n  size_t res = m_blockArray.newBlock();\n  assert (res > 0);\n  Q_UNUSED( res );\n\n  m_lineLengths.insert(m_blockArray.getCurrent(), count);\n}\n\nvoid HistoryScrollBlockArray::addLine(bool)\n{\n}\n\n//////////////////////////////////////////////////////////////////////\n// History Types\n//////////////////////////////////////////////////////////////////////\n\nHistoryType::HistoryType()\n{\n}\n\nHistoryType::~HistoryType()\n{\n}\n\n//////////////////////////////\n\nHistoryTypeNone::HistoryTypeNone()\n{\n}\n\nbool HistoryTypeNone::isEnabled() const\n{\n  return false;\n}\n\nHistoryScroll* HistoryTypeNone::scroll(HistoryScroll *old) const\n{\n  delete old;\n  return new HistoryScrollNone();\n}\n\nint HistoryTypeNone::maximumLineCount() const\n{\n  return 0;\n}\n\n//////////////////////////////\n\nHistoryTypeBlockArray::HistoryTypeBlockArray(size_t size)\n  : m_size(size)\n{\n}\n\nbool HistoryTypeBlockArray::isEnabled() const\n{\n  return true;\n}\n\nint HistoryTypeBlockArray::maximumLineCount() const\n{\n  return m_size;\n}\n\nHistoryScroll* HistoryTypeBlockArray::scroll(HistoryScroll *old) const\n{\n  delete old;\n  return new HistoryScrollBlockArray(m_size);\n}\n\n\n//////////////////////////////\n\nHistoryTypeBuffer::HistoryTypeBuffer(unsigned int nbLines)\n  : m_nbLines(nbLines)\n{\n}\n\nbool HistoryTypeBuffer::isEnabled() const\n{\n  return true;\n}\n\nint HistoryTypeBuffer::maximumLineCount() const\n{\n  return m_nbLines;\n}\n\nHistoryScroll* HistoryTypeBuffer::scroll(HistoryScroll *old) const\n{\n  if (old)\n  {\n    HistoryScrollBuffer *oldBuffer = dynamic_cast<HistoryScrollBuffer*>(old);\n    if (oldBuffer)\n    {\n       oldBuffer->setMaxNbLines(m_nbLines);\n       return oldBuffer;\n    }\n\n    HistoryScroll *newScroll = new HistoryScrollBuffer(m_nbLines);\n    int lines = old->getLines();\n    int startLine = 0;\n    if (lines > (int) m_nbLines)\n       startLine = lines - m_nbLines;\n\n    Character line[LINE_SIZE];\n    for(int i = startLine; i < lines; i++)\n    {\n       int size = old->getLineLen(i);\n       if (size > LINE_SIZE)\n       {\n          Character *tmp_line = new Character[size];\n          old->getCells(i, 0, size, tmp_line);\n          newScroll->addCells(tmp_line, size);\n          newScroll->addLine(old->isWrappedLine(i));\n          delete [] tmp_line;\n       }\n       else\n       {\n          old->getCells(i, 0, size, line);\n          newScroll->addCells(line, size);\n          newScroll->addLine(old->isWrappedLine(i));\n       }\n    }\n    delete old;\n    return newScroll;\n  }\n  return new HistoryScrollBuffer(m_nbLines);\n}\n\n//////////////////////////////\n\nHistoryTypeFile::HistoryTypeFile(const QString& fileName)\n  : m_fileName(fileName)\n{\n}\n\nbool HistoryTypeFile::isEnabled() const\n{\n  return true;\n}\n\nconst QString& HistoryTypeFile::getFileName() const\n{\n  return m_fileName;\n}\n\nHistoryScroll* HistoryTypeFile::scroll(HistoryScroll *old) const\n{\n  if (dynamic_cast<HistoryFile *>(old))\n     return old; // Unchanged.\n\n  HistoryScroll *newScroll = new HistoryScrollFile(m_fileName);\n\n  Character line[LINE_SIZE];\n  int lines = (old != nullptr) ? old->getLines() : 0;\n  for(int i = 0; i < lines; i++)\n  {\n     int size = old->getLineLen(i);\n     if (size > LINE_SIZE)\n     {\n        Character *tmp_line = new Character[size];\n        old->getCells(i, 0, size, tmp_line);\n        newScroll->addCells(tmp_line, size);\n        newScroll->addLine(old->isWrappedLine(i));\n        delete [] tmp_line;\n     }\n     else\n     {\n        old->getCells(i, 0, size, line);\n        newScroll->addCells(line, size);\n        newScroll->addLine(old->isWrappedLine(i));\n     }\n  }\n\n  delete old;\n  return newScroll;\n}\n\nint HistoryTypeFile::maximumLineCount() const\n{\n  return 0;\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/History.h",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n    Copyright (C) 1997-1998, 2013 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef HISTORY_H\n#define HISTORY_H\n\n// Qt\n#include <QtCore>\n\n#include <QBitRef>\n#include <QHash>\n\n// Konsole\n#include \"unix/BlockArray.h\"\n#include \"unix/Character.h\"\n\n\nclass HistoryFile\n{\npublic:\n  HistoryFile();\n  virtual ~HistoryFile();\n\n  virtual void add(const unsigned char* bytes, int len);\n  virtual void get(unsigned char* bytes, int len, int loc);\n  virtual int  len();\n\n  //mmaps the file in read-only mode\n  void map();\n  //un-mmaps the file\n  void unmap();\n  //returns true if the file is mmap'ed\n  bool isMapped();\n\n\nprivate:\n  int  ion;\n  int  length;\n  QTemporaryFile tmpFile;\n\n  //pointer to start of mmap'ed file data, or 0 if the file is not mmap'ed\n  char* fileMap;\n\n  //incremented whenver 'add' is called and decremented whenever\n  //'get' is called.\n  //this is used to detect when a large number of lines are being read and processed from the history\n  //and automatically mmap the file for better performance (saves the overhead of many lseek-read calls).\n  int readWriteBalance;\n\n  //when readWriteBalance goes below this threshold, the file will be mmap'ed automatically\n  static const int MAP_THRESHOLD = -1000;\n};\n\n//////////////////////////////////////////////////////////////////////\n\n//////////////////////////////////////////////////////////////////////\n// Abstract base class for file and buffer versions\n//////////////////////////////////////////////////////////////////////\nclass HistoryType;\n\nclass HistoryScroll\n{\npublic:\n  HistoryScroll(HistoryType*);\n virtual ~HistoryScroll();\n\n  virtual bool hasScroll();\n\n  // access to history\n  virtual int  getLines() = 0;\n  virtual int  getLineLen(int lineno) = 0;\n  virtual void getCells(int lineno, int colno, int count, Character res[]) = 0;\n  virtual bool isWrappedLine(int lineno) = 0;\n\n  // backward compatibility (obsolete)\n  Character   getCell(int lineno, int colno) { Character res; getCells(lineno,colno,1,&res); return res; }\n\n  // adding lines.\n  virtual void addCells(const Character a[], int count) = 0;\n  // convenience method - this is virtual so that subclasses can take advantage\n  // of QVector's implicit copying\n  virtual void addCellsVector(const QVector<Character>& cells)\n  {\n    addCells(cells.data(),cells.size());\n  }\n\n  virtual void addLine(bool previousWrapped=false) = 0;\n\n  //\n  // FIXME:  Passing around constant references to HistoryType instances\n  // is very unsafe, because those references will no longer\n  // be valid if the history scroll is deleted.\n  //\n  const HistoryType& getType() { return *m_histType; }\n\nprotected:\n  HistoryType* m_histType;\n\n};\n\n\n//////////////////////////////////////////////////////////////////////\n// File-based history (e.g. file log, no limitation in length)\n//////////////////////////////////////////////////////////////////////\n\nclass HistoryScrollFile : public HistoryScroll\n{\npublic:\n  HistoryScrollFile(const QString &logFileName);\n  virtual ~HistoryScrollFile();\n\n  virtual int  getLines();\n  virtual int  getLineLen(int lineno);\n  virtual void getCells(int lineno, int colno, int count, Character res[]);\n  virtual bool isWrappedLine(int lineno);\n\n  virtual void addCells(const Character a[], int count);\n  virtual void addLine(bool previousWrapped=false);\n\nprivate:\n  int startOfLine(int lineno);\n\n  QString m_logFileName;\n  HistoryFile index; // lines Row(int)\n  HistoryFile cells; // text  Row(Character)\n  HistoryFile lineflags; // flags Row(unsigned char)\n};\n\n\n//////////////////////////////////////////////////////////////////////\n// Buffer-based history (limited to a fixed nb of lines)\n//////////////////////////////////////////////////////////////////////\nclass HistoryScrollBuffer : public HistoryScroll\n{\npublic:\n  typedef QVector<Character> HistoryLine;\n\n  HistoryScrollBuffer(unsigned int maxNbLines = 1000);\n  virtual ~HistoryScrollBuffer();\n\n  virtual int  getLines();\n  virtual int  getLineLen(int lineno);\n  virtual void getCells(int lineno, int colno, int count, Character res[]);\n  virtual bool isWrappedLine(int lineno);\n\n  virtual void addCells(const Character a[], int count);\n  virtual void addCellsVector(const QVector<Character>& cells);\n  virtual void addLine(bool previousWrapped=false);\n\n  void setMaxNbLines(unsigned int nbLines);\n  unsigned int maxNbLines() { return _maxLineCount; }\n\n\nprivate:\n  int bufferIndex(int lineNumber);\n\n  HistoryLine* _historyBuffer;\n  QBitArray _wrappedLine;\n  int _maxLineCount;\n  int _usedLines;\n  int _head;\n\n  //QVector<histline*> m_histBuffer;\n  //QBitArray m_wrappedLine;\n  //unsigned int m_maxNbLines;\n  //unsigned int m_nbLines;\n  //unsigned int m_arrayIndex;\n  //bool         m_buffFilled;\n};\n\n/*class HistoryScrollBufferV2 : public HistoryScroll\n{\npublic:\n  virtual int  getLines();\n  virtual int  getLineLen(int lineno);\n  virtual void getCells(int lineno, int colno, int count, Character res[]);\n  virtual bool isWrappedLine(int lineno);\n\n  virtual void addCells(const Character a[], int count);\n  virtual void addCells(const QVector<Character>& cells);\n  virtual void addLine(bool previousWrapped=false);\n\n};*/\n\n\n//////////////////////////////////////////////////////////////////////\n// Nothing-based history (no history :-)\n//////////////////////////////////////////////////////////////////////\nclass HistoryScrollNone : public HistoryScroll\n{\npublic:\n  HistoryScrollNone();\n  virtual ~HistoryScrollNone();\n\n  virtual bool hasScroll();\n\n  virtual int  getLines();\n  virtual int  getLineLen(int lineno);\n  virtual void getCells(int lineno, int colno, int count, Character res[]);\n  virtual bool isWrappedLine(int lineno);\n\n  virtual void addCells(const Character a[], int count);\n  virtual void addLine(bool previousWrapped=false);\n};\n\n//////////////////////////////////////////////////////////////////////\n// BlockArray-based history\n//////////////////////////////////////////////////////////////////////\nclass HistoryScrollBlockArray : public HistoryScroll\n{\npublic:\n  HistoryScrollBlockArray(size_t size);\n  virtual ~HistoryScrollBlockArray();\n\n  virtual int  getLines();\n  virtual int  getLineLen(int lineno);\n  virtual void getCells(int lineno, int colno, int count, Character res[]);\n  virtual bool isWrappedLine(int lineno);\n\n  virtual void addCells(const Character a[], int count);\n  virtual void addLine(bool previousWrapped=false);\n\nprotected:\n  BlockArray m_blockArray;\n  QHash<int,size_t> m_lineLengths;\n};\n\n//////////////////////////////////////////////////////////////////////\n// History type\n//////////////////////////////////////////////////////////////////////\n\nclass HistoryType\n{\npublic:\n  HistoryType();\n  virtual ~HistoryType();\n\n  /**\n   * Returns true if the history is enabled ( can store lines of output )\n   * or false otherwise.\n   */\n  virtual bool isEnabled()           const = 0;\n  /**\n   * Returns true if the history size is unlimited.\n   */\n  bool isUnlimited() const { return maximumLineCount() == 0; }\n  /**\n   * Returns the maximum number of lines which this history type\n   * can store or 0 if the history can store an unlimited number of lines.\n   */\n  virtual int maximumLineCount()    const = 0;\n\n  virtual HistoryScroll* scroll(HistoryScroll *) const = 0;\n};\n\nclass HistoryTypeNone : public HistoryType\n{\npublic:\n  HistoryTypeNone();\n\n  virtual bool isEnabled() const;\n  virtual int maximumLineCount() const;\n\n  virtual HistoryScroll* scroll(HistoryScroll *) const;\n};\n\nclass HistoryTypeBlockArray : public HistoryType\n{\npublic:\n  HistoryTypeBlockArray(size_t size);\n\n  virtual bool isEnabled() const;\n  virtual int maximumLineCount() const;\n\n  virtual HistoryScroll* scroll(HistoryScroll *) const;\n\nprotected:\n  size_t m_size;\n};\n\n\nclass HistoryTypeFile : public HistoryType\n{\npublic:\n  HistoryTypeFile(const QString& fileName=QString());\n\n  virtual bool isEnabled() const;\n  virtual const QString& getFileName() const;\n  virtual int maximumLineCount() const;\n\n  virtual HistoryScroll* scroll(HistoryScroll *) const;\n\nprotected:\n  QString m_fileName;\n};\n\n\nclass HistoryTypeBuffer : public HistoryType\n{\npublic:\n  HistoryTypeBuffer(unsigned int nbLines);\n\n  virtual bool isEnabled() const;\n  virtual int maximumLineCount() const;\n\n  virtual HistoryScroll* scroll(HistoryScroll *) const;\n\nprotected:\n  unsigned int m_nbLines;\n};\n\n#endif // HISTORY_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/KeyboardTranslator.cpp",
    "content": "/*\n    This source file was part of Konsole, a terminal emulator.\n\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n// Own\n#include \"unix/KeyboardTranslator.h\"\n\n// System\n#include <ctype.h>\n#include <stdio.h>\n\n// Qt\n#include <QtCore>\n#include <QtGui>\n\n#include <QBuffer>\n#include <QFile>\n#include <QFileInfo>\n#include <QRegularExpression>\n\n// FIXME: We should not have a special case for Mac here.  Instead, we\n// should be loading .keytab files at run time, and ideally, allowing\n// individual keys to be redefined from some preferences menu.\n\n//and this is default now translator - default.keytab from original Konsole\nconst char* KeyboardTranslatorManager::defaultTranslatorText =\n#if defined (Q_OS_MAC)\n#include \"ExtendedDefaultTranslatorMac.h\"\n#else\n#include \"ExtendedDefaultTranslator.h\"\n#endif\n;\n\nKeyboardTranslatorManager::KeyboardTranslatorManager()\n    : _haveLoadedAll(false)\n{\n}\nKeyboardTranslatorManager::~KeyboardTranslatorManager()\n{\n    qDeleteAll(_translators.values());\n}\nQString KeyboardTranslatorManager::findTranslatorPath(const QString& name)\n{\n    return QString(\"kb-layouts/\" + name + \".keytab\");\n}\nvoid KeyboardTranslatorManager::findTranslators()\n{\n    QDir dir(\"kb-layouts/\");\n    QStringList filters;\n    filters << \"*.keytab\";\n    dir.setNameFilters(filters);\n    QStringList list = dir.entryList(filters); //(\".keytab\"); // = KGlobal::dirs()->findAllResources(\"data\",\n    //                                 \"konsole/*.keytab\",\n    //                                 KStandardDirs::NoDuplicates);\n    list = dir.entryList(filters);\n    // add the name of each translator to the list and associated\n    // the name with a null pointer to indicate that the translator\n    // has not yet been loaded from disk\n    QStringListIterator listIter(list);\n    while (listIter.hasNext())\n    {\n        QString translatorPath = listIter.next();\n\n        QString name = QFileInfo(translatorPath).baseName();\n\n        if ( !_translators.contains(name) ) {\n            _translators.insert(name,nullptr);\n\t}\n    }\n    _haveLoadedAll = true;\n}\n\nconst KeyboardTranslator* KeyboardTranslatorManager::findTranslator(const QString& name)\n{\n    if ( name.isEmpty() )\n        return defaultTranslator();\n\n    //here was smth wrong in original Konsole source\n    findTranslators();\n\n    if ( _translators.contains(name) && _translators[name] != nullptr ) {\n        return _translators[name];\n    }\n\n    KeyboardTranslator* translator = loadTranslator(name);\n\n    if ( translator != nullptr )\n        _translators[name] = translator;\n    else if ( !name.isEmpty() )\n        qWarning() << \"Unable to load translator\" << name;\n\n    return translator;\n}\n\nbool KeyboardTranslatorManager::saveTranslator(const KeyboardTranslator* translator)\n{\n    const QString path = \".keytab\";// = KGlobal::dirs()->saveLocation(\"data\",\"konsole/\")+translator->name()\n    //           +\".keytab\";\n\n    qDebug() << \"Saving translator to\" << path;\n\n    QFile destination(path);\n\n    if (!destination.open(QIODevice::WriteOnly | QIODevice::Text))\n    {\n        qWarning() << \"Unable to save keyboard translation:\"\n                   << destination.errorString();\n\n        return false;\n    }\n\n    {\n        KeyboardTranslatorWriter writer(&destination);\n        writer.writeHeader(translator->description());\n\n        QListIterator<KeyboardTranslator::Entry> iter(translator->entries());\n        while ( iter.hasNext() )\n            writer.writeEntry(iter.next());\n    }\n\n    destination.close();\n\n    return true;\n}\n\nKeyboardTranslator* KeyboardTranslatorManager::loadTranslator(const QString& name)\n{\n    const QString& path = findTranslatorPath(name);\n\n    QFile source(path);\n\n    if (name.isEmpty() || !source.open(QIODevice::ReadOnly | QIODevice::Text))\n        return nullptr;\n\n    return loadTranslator(&source,name);\n}\n\nconst KeyboardTranslator* KeyboardTranslatorManager::defaultTranslator()\n{\n    QBuffer textBuffer;\n    textBuffer.setData(defaultTranslatorText,strlen(defaultTranslatorText));\n\n    if (!textBuffer.open(QIODevice::ReadOnly))\n        return nullptr;\n\n    return loadTranslator(&textBuffer,\"fallback\");\n}\n\nKeyboardTranslator* KeyboardTranslatorManager::loadTranslator(QIODevice* source,const QString& name)\n{\n    KeyboardTranslator* translator = new KeyboardTranslator(name);\n    KeyboardTranslatorReader reader(source);\n    translator->setDescription( reader.description() );\n\n    while ( reader.hasNextEntry() ) {\n        translator->addEntry(reader.nextEntry());\n    }\t\n\n    source->close();\n\n    if ( !reader.parseError() )\n    {\n        return translator;\n    }\n    else\n    {\n        delete translator;\n        return nullptr;\n    }\n}\n\nKeyboardTranslatorWriter::KeyboardTranslatorWriter(QIODevice* destination)\n    : _destination(destination)\n{\n    Q_ASSERT( destination && destination->isWritable() );\n\n    _writer = new QTextStream(_destination);\n}\nKeyboardTranslatorWriter::~KeyboardTranslatorWriter()\n{\n    delete _writer;\n}\nvoid KeyboardTranslatorWriter::writeHeader( const QString& description )\n{\n    *_writer << \"keyboard \\\"\" << description << '\\\"' << '\\n';\n}\nvoid KeyboardTranslatorWriter::writeEntry( const KeyboardTranslator::Entry& entry )\n{\n    QString result;\n\n    if ( entry.command() != KeyboardTranslator::NoCommand )\n        result = entry.resultToString();\n    else\n        result = '\\\"' + entry.resultToString() + '\\\"';\n\n    *_writer << \"key \" << entry.conditionToString() << \" : \" << result << '\\n';\n}\n\n\n// each line of the keyboard translation file is one of:\n//\n// - keyboard \"name\"\n// - key KeySequence : \"characters\"\n// - key KeySequence : CommandName\n//\n// KeySequence begins with the name of the key ( taken from the Qt::Key enum )\n// and is followed by the keyboard modifiers and state flags ( with + or - in front\n// of each modifier or flag to indicate whether it is required ).  All keyboard modifiers\n// and flags are optional, if a particular modifier or state is not specified it is\n// assumed not to be a part of the sequence.  The key sequence may contain whitespace\n//\n// eg:  \"key Up+Shift : scrollLineUp\"\n//      \"key Next-Shift : \"\\E[6~\"\n//\n// (lines containing only whitespace are ignored, parseLine assumes that comments have\n// already been removed)\n//\n\nKeyboardTranslatorReader::KeyboardTranslatorReader( QIODevice* source )\n    : _source(source)\n    , _hasNext(false)\n{\n    // read input until we find the description\n    while ( _description.isEmpty() && !source->atEnd() )\n    {\n        const QList<Token>& tokens = tokenize( QString(source->readLine()) );\n\n        if ( !tokens.isEmpty() && tokens.first().type == Token::TitleKeyword )\n        {\n            _description = (tokens[1].text.toUtf8());\n        }\n    }\n\n    readNext();\n}\nvoid KeyboardTranslatorReader::readNext()\n{\n    // find next entry\n    while ( !_source->atEnd() )\n    {\n        const QList<Token>& tokens = tokenize( QString(_source->readLine()) );\n        if ( !tokens.isEmpty() && tokens.first().type == Token::KeyKeyword )\n        {\n            KeyboardTranslator::States flags = KeyboardTranslator::NoState;\n            KeyboardTranslator::States flagMask = KeyboardTranslator::NoState;\n            Qt::KeyboardModifiers modifiers = Qt::NoModifier;\n            Qt::KeyboardModifiers modifierMask = Qt::NoModifier;\n\n            int keyCode = Qt::Key_unknown;\n\n            decodeSequence(tokens[1].text.toLower(),\n                           keyCode,\n                           modifiers,\n                           modifierMask,\n                           flags,\n                           flagMask);\n\n            KeyboardTranslator::Command command = KeyboardTranslator::NoCommand;\n            QByteArray text;\n\n            // get text or command\n            if ( tokens[2].type == Token::OutputText )\n            {\n                text = tokens[2].text.toLocal8Bit();\n            }\n            else if ( tokens[2].type == Token::Command )\n            {\n                // identify command\n                if (!parseAsCommand(tokens[2].text,command))\n                    qWarning() << \"Command\" << tokens[2].text << \"not understood.\";\n            }\n\n            KeyboardTranslator::Entry newEntry;\n            newEntry.setKeyCode( keyCode );\n            newEntry.setState( flags );\n            newEntry.setStateMask( flagMask );\n            newEntry.setModifiers( modifiers );\n            newEntry.setModifierMask( modifierMask );\n            newEntry.setText( text );\n            newEntry.setCommand( command );\n\n            _nextEntry = newEntry;\n\n            _hasNext = true;\n\n            return;\n        }\n    }\n\n    _hasNext = false;\n}\n\nbool KeyboardTranslatorReader::parseAsCommand(const QString& text,KeyboardTranslator::Command& command)\n{\n    if ( text.compare(\"erase\",Qt::CaseInsensitive) == 0 )\n        command = KeyboardTranslator::EraseCommand;\n    else if ( text.compare(\"scrollpageup\",Qt::CaseInsensitive) == 0 )\n        command = KeyboardTranslator::ScrollPageUpCommand;\n    else if ( text.compare(\"scrollpagedown\",Qt::CaseInsensitive) == 0 )\n        command = KeyboardTranslator::ScrollPageDownCommand;\n    else if ( text.compare(\"scrolllineup\",Qt::CaseInsensitive) == 0 )\n        command = KeyboardTranslator::ScrollLineUpCommand;\n    else if ( text.compare(\"scrolllinedown\",Qt::CaseInsensitive) == 0 )\n        command = KeyboardTranslator::ScrollLineDownCommand;\n    else if ( text.compare(\"scrolllock\",Qt::CaseInsensitive) == 0 )\n        command = KeyboardTranslator::ScrollLockCommand;\n    else\n    \treturn false;\n\n    return true;\n}\n\nbool KeyboardTranslatorReader::decodeSequence(const QString& text,\n                                              int& keyCode,\n                                              Qt::KeyboardModifiers& modifiers,\n                                              Qt::KeyboardModifiers& modifierMask,\n                                              KeyboardTranslator::States& flags,\n                                              KeyboardTranslator::States& flagMask)\n{\n    bool isWanted = true;\n    bool endOfItem = false;\n    QString buffer;\n\n    Qt::KeyboardModifiers tempModifiers = modifiers;\n    Qt::KeyboardModifiers tempModifierMask = modifierMask;\n    KeyboardTranslator::States tempFlags = flags;\n    KeyboardTranslator::States tempFlagMask = flagMask;\n\n    for ( int i = 0 ; i < text.size () ; i++ )\n    {\n        const QChar& ch = text[i];\n        bool isLastLetter = ( i == text.size ()-1 );\n\n        endOfItem = true;\n        if ( ch.isLetterOrNumber() )\n        {\n            endOfItem = false;\n            buffer.append(ch);\n        }\n\n        if ( (endOfItem || isLastLetter) && !buffer.isEmpty() )\n        {\n            Qt::KeyboardModifier itemModifier = Qt::NoModifier;\n            int itemKeyCode = 0;\n            KeyboardTranslator::State itemFlag = KeyboardTranslator::NoState;\n\n            if ( parseAsModifier(buffer,itemModifier) )\n            {\n                tempModifierMask |= itemModifier;\n\n                if ( isWanted )\n                    tempModifiers |= itemModifier;\n            }\n            else if ( parseAsStateFlag(buffer,itemFlag) )\n            {\n                tempFlagMask |= itemFlag;\n\n                if ( isWanted )\n                    tempFlags |= itemFlag;\n            }\n            else if ( parseAsKeyCode(buffer,itemKeyCode) )\n                keyCode = itemKeyCode;\n            else\n                qDebug() << \"Unable to parse key binding item:\" << buffer;\n\n            buffer.clear();\n        }\n\n        // check if this is a wanted / not-wanted flag and update the\n        // state ready for the next item\n        if ( ch == '+' )\n            isWanted = true;\n        else if ( ch == '-' )\n            isWanted = false;\n    }\n\n    modifiers = tempModifiers;\n    modifierMask = tempModifierMask;\n    flags = tempFlags;\n    flagMask = tempFlagMask;\n\n    return true;\n}\n\nbool KeyboardTranslatorReader::parseAsModifier(const QString& item , Qt::KeyboardModifier& modifier)\n{\n    if ( item == \"shift\" )\n        modifier = Qt::ShiftModifier;\n    else if ( item == \"ctrl\" || item == \"control\" )\n        modifier = Qt::ControlModifier;\n    else if ( item == \"alt\" )\n        modifier = Qt::AltModifier;\n    else if ( item == \"meta\" )\n        modifier = Qt::MetaModifier;\n    else if ( item == \"keypad\" )\n        modifier = Qt::KeypadModifier;\n    else\n        return false;\n\n    return true;\n}\nbool KeyboardTranslatorReader::parseAsStateFlag(const QString& item , KeyboardTranslator::State& flag)\n{\n    if ( item == \"appcukeys\" )\n        flag = KeyboardTranslator::CursorKeysState;\n    else if ( item == \"ansi\" )\n        flag = KeyboardTranslator::AnsiState;\n    else if ( item == \"newline\" )\n        flag = KeyboardTranslator::NewLineState;\n    else if ( item == \"appscreen\" )\n        flag = KeyboardTranslator::AlternateScreenState;\n    else if ( item == \"anymod\" )\n        flag = KeyboardTranslator::AnyModifierState;\n    else\n        return false;\n\n    return true;\n}\nbool KeyboardTranslatorReader::parseAsKeyCode(const QString& item , int& keyCode)\n{\n    QKeySequence sequence = QKeySequence::fromString(item);\n    if ( !sequence.isEmpty() )\n    {\n#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)\n        keyCode = sequence[0].toCombined ();\n#else\n        keyCode = sequence[0];\n#endif\n\n        if ( sequence.count() > 1 )\n        {\n            qDebug() << \"Unhandled key codes in sequence: \" << item;\n        }\n    }\n    // additional cases implemented for backwards compatibility with KDE 3\n    else if ( item == \"prior\" )\n        keyCode = Qt::Key_PageUp;\n    else if ( item == \"next\" )\n        keyCode = Qt::Key_PageDown;\n    else\n        return false;\n\n    return true;\n}\n\nQString KeyboardTranslatorReader::description() const\n{\n    return _description;\n}\nbool KeyboardTranslatorReader::hasNextEntry()\n{\n    return _hasNext;\n}\nKeyboardTranslator::Entry KeyboardTranslatorReader::createEntry( const QString& condition ,\n                                                                 const QString& result )\n{\n    QString entryString(\"keyboard \\\"temporary\\\"\\nkey \");\n    entryString.append(condition);\n    entryString.append(\" : \");\n\n    // if 'result' is the name of a command then the entry result will be that command,\n    // otherwise the result will be treated as a string to echo when the key sequence\n    // specified by 'condition' is pressed\n    KeyboardTranslator::Command command;\n    if (parseAsCommand(result,command))\n    \tentryString.append(result);\n    else\n        entryString.append('\\\"' + result + '\\\"');\n\n    QByteArray array = entryString.toUtf8();\n\n    KeyboardTranslator::Entry entry;\n\n    QBuffer buffer(&array);\n    buffer.open(QIODevice::ReadOnly);\n    KeyboardTranslatorReader reader(&buffer);\n\n    if ( reader.hasNextEntry() )\n        entry = reader.nextEntry();\n\n    return entry;\n}\n\nKeyboardTranslator::Entry KeyboardTranslatorReader::nextEntry()\n{\n    Q_ASSERT( _hasNext );\n\n\n    KeyboardTranslator::Entry entry = _nextEntry;\n\n    readNext();\n\n    return entry;\n}\nbool KeyboardTranslatorReader::parseError()\n{\n    return false;\n}\nQList<KeyboardTranslatorReader::Token>\nKeyboardTranslatorReader::tokenize (const QString& line)\n{\n    QString text = line.simplified();\n\n    // comment line: # comment\n    static QRegularExpression comment {\"\\\\#.*\"};\n    // title line: keyboard \"title\"\n    static QRegularExpression title {\"keyboard\\\\s+\\\"(.*)\\\"\"};\n    // key line: key KeySequence : \"output\"\n    // key line: key KeySequence : command\n    static QRegularExpression key {\"key\\\\s+([\\\\w\\\\+\\\\s\\\\-]+)\\\\s*:\\\\s*(\\\"(.*)\\\"|\\\\w+)\"};\n\n    QList<Token> list;\n\n    if ( text.isEmpty() || comment.match (text).hasMatch () )\n    {\n        return list;\n    }\n\n    QRegularExpressionMatch match;\n    if ((match = title.match (text)).hasMatch ())\n    {\n        Token titleToken = { Token::TitleKeyword , QString() };\n        Token textToken = { Token::TitleText , match.captured (1) };\n\n        list << titleToken << textToken;\n    }\n    else if  ((match = key.match (text)).hasMatch ())\n    {\n        Token keyToken = { Token::KeyKeyword , QString() };\n        Token sequenceToken = { Token::KeySequence,\n                                match.captured (1).remove (' ') };\n\n        list << keyToken << sequenceToken;\n\n        if ( match.captured (3).isEmpty () )\n        {\n            // capturedTexts()[2] is a command\n            Token commandToken = { Token::Command , match.captured (2) };\n            list << commandToken;\n        }\n        else\n        {\n            // capturedTexts()[3] is the output string\n            Token outputToken = { Token::OutputText , match.captured (3) };\n            list << outputToken;\n        }\n    }\n    else\n    {\n        qWarning() << \"Line in keyboard translator file could not be understood:\" << text;\n    }\n\n    return list;\n}\n\nQList<QString> KeyboardTranslatorManager::allTranslators()\n{\n    if ( !_haveLoadedAll )\n    {\n        findTranslators();\n    }\n\n    return _translators.keys();\n}\n\nKeyboardTranslator::Entry::Entry()\n    : _keyCode(0)\n    , _modifiers(Qt::NoModifier)\n    , _modifierMask(Qt::NoModifier)\n    , _state(NoState)\n    , _stateMask(NoState)\n    , _command(NoCommand)\n{\n}\n\nbool KeyboardTranslator::Entry::operator==(const Entry& rhs) const\n{\n    return _keyCode == rhs._keyCode &&\n            _modifiers == rhs._modifiers &&\n            _modifierMask == rhs._modifierMask &&\n            _state == rhs._state &&\n            _stateMask == rhs._stateMask &&\n            _command == rhs._command &&\n            _text == rhs._text;\n}\n\nbool KeyboardTranslator::Entry::matches(int keyCode ,\n                                        Qt::KeyboardModifiers modifiers,\n                                        States state) const\n{\n    if ( _keyCode != keyCode )\n        return false;\n\n    if ( (modifiers & _modifierMask) != (_modifiers & _modifierMask) )\n        return false;\n\n    // if modifiers is non-zero, the 'any modifier' state is implicit\n    if ( modifiers != 0 )\n        state |= AnyModifierState;\n\n    if ( (state & _stateMask) != (_state & _stateMask) )\n        return false;\n\n    // special handling for the 'Any Modifier' state, which checks for the presence of\n    // any or no modifiers.  In this context, the 'keypad' modifier does not count.\n    bool anyModifiersSet = modifiers != 0 && modifiers != Qt::KeypadModifier;\n    if ( _stateMask & KeyboardTranslator::AnyModifierState )\n    {\n        // test fails if any modifier is required but none are set\n        if ( (_state & KeyboardTranslator::AnyModifierState) && !anyModifiersSet )\n            return false;\n\n        // test fails if no modifier is allowed but one or more are set\n        if ( !(_state & KeyboardTranslator::AnyModifierState) && anyModifiersSet )\n            return false;\n    }\n\n    return true;\n}\nQByteArray KeyboardTranslator::Entry::escapedText(bool expandWildCards,Qt::KeyboardModifiers modifiers) const\n{\n    QByteArray result(text(expandWildCards,modifiers));\n\n    for ( int i = 0 ; i < result.size () ; i++ )\n    {\n        char ch = result[i];\n        char replacement = 0;\n\n        switch ( ch )\n        {\n        case 27 : replacement = 'E'; break;\n        case 8  : replacement = 'b'; break;\n        case 12 : replacement = 'f'; break;\n        case 9  : replacement = 't'; break;\n        case 13 : replacement = 'r'; break;\n        case 10 : replacement = 'n'; break;\n        default:\n            // any character which is not printable is replaced by an equivalent\n            // \\xhh escape sequence (where 'hh' are the corresponding hex digits)\n            if ( !QChar(ch).isPrint() )\n                replacement = 'x';\n        }\n\n        if ( replacement == 'x' )\n        {\n          result.replace(i,1,\"\\\\x\"+QByteArray::number(QByteArray(1,ch).toInt(nullptr, 16)));\n        } else if ( replacement != 0 )\n        {\n            result.remove(i,1);\n            result.insert(i,'\\\\');\n            result.insert(i+1,replacement);\n        }\n    }\n\n    return result;\n}\nQByteArray KeyboardTranslator::Entry::unescape(const QByteArray& input) const\n{\n    QByteArray result(input);\n\n    for ( int i = 0 ; i < result.size ()-1 ; i++ )\n    {\n\n        char ch = result[i];\n        if ( ch == '\\\\' )\n        {\n            char replacement[2] = {0,0};\n            int charsToRemove = 2;\n            bool escapedChar = true;\n\n            switch ( result[i+1] )\n            {\n            case 'E' : replacement[0] = 27; break;\n            case 'b' : replacement[0] = 8 ; break;\n            case 'f' : replacement[0] = 12; break;\n            case 't' : replacement[0] = 9 ; break;\n            case 'r' : replacement[0] = 13; break;\n            case 'n' : replacement[0] = 10; break;\n            case 'x' :\n            {\n                // format is \\xh or \\xhh where 'h' is a hexadecimal\n                // digit from 0-9 or A-F which should be replaced\n                // with the corresponding character value\n                char hexDigits[3] = {0};\n\n                if ( (i < result.size ()-2) && isxdigit(result[i+2]) )\n                    hexDigits[0] = result[i+2];\n                if ( (i < result.size ()-3) && isxdigit(result[i+3]) )\n                    hexDigits[1] = result[i+3];\n\n                int charValue = 0;\n                sscanf(hexDigits,\"%x\",&charValue);\n\n                replacement[0] = (char)charValue;\n\n                charsToRemove = 2 + strlen(hexDigits);\n            }\n            break;\n            default:\n                escapedChar = false;\n            }\n\n            if ( escapedChar )\n                result.replace(i,charsToRemove,replacement);\n        }\n    }\n\n    return result;\n}\n\nvoid KeyboardTranslator::Entry::insertModifier( QString& item , int modifier ) const\n{\n    if ( !(modifier & _modifierMask) )\n        return;\n\n    if ( modifier & _modifiers )\n        item += '+';\n    else\n        item += '-';\n\n    if ( modifier == Qt::ShiftModifier )\n        item += \"Shift\";\n    else if ( modifier == Qt::ControlModifier )\n        item += \"Ctrl\";\n    else if ( modifier == Qt::AltModifier )\n        item += \"Alt\";\n    else if ( modifier == Qt::MetaModifier )\n        item += \"Meta\";\n    else if ( modifier == Qt::KeypadModifier )\n        item += \"KeyPad\";\n}\nvoid KeyboardTranslator::Entry::insertState( QString& item , int state ) const\n{\n    if ( !(state & _stateMask) )\n        return;\n\n    if ( state & _state )\n        item += '+' ;\n    else\n        item += '-' ;\n\n    if ( state == KeyboardTranslator::AlternateScreenState )\n        item += \"AppScreen\";\n    else if ( state == KeyboardTranslator::NewLineState )\n        item += \"NewLine\";\n    else if ( state == KeyboardTranslator::AnsiState )\n        item += \"Ansi\";\n    else if ( state == KeyboardTranslator::CursorKeysState )\n        item += \"AppCuKeys\";\n    else if ( state == KeyboardTranslator::AnyModifierState )\n        item += \"AnyMod\";\n}\nQString KeyboardTranslator::Entry::resultToString(bool expandWildCards,Qt::KeyboardModifiers modifiers) const\n{\n    if ( !_text.isEmpty() )\n        return escapedText(expandWildCards,modifiers);\n    else if ( _command == EraseCommand )\n        return \"Erase\";\n    else if ( _command == ScrollPageUpCommand )\n        return \"ScrollPageUp\";\n    else if ( _command == ScrollPageDownCommand )\n        return \"ScrollPageDown\";\n    else if ( _command == ScrollLineUpCommand )\n        return \"ScrollLineUp\";\n    else if ( _command == ScrollLineDownCommand )\n        return \"ScrollLineDown\";\n    else if ( _command == ScrollLockCommand )\n        return \"ScrollLock\";\n\n    return QString();\n}\nQString KeyboardTranslator::Entry::conditionToString() const\n{\n    QString result = QKeySequence(_keyCode).toString();\n\n    // add modifiers\n    insertModifier( result , Qt::ShiftModifier );\n    insertModifier( result , Qt::ControlModifier );\n    insertModifier( result , Qt::AltModifier );\n    insertModifier( result , Qt::MetaModifier );\n\n    // add states\n    insertState( result , KeyboardTranslator::AlternateScreenState );\n    insertState( result , KeyboardTranslator::NewLineState );\n    insertState( result , KeyboardTranslator::AnsiState );\n    insertState( result , KeyboardTranslator::CursorKeysState );\n    insertState( result , KeyboardTranslator::AnyModifierState );\n\n    return result;\n}\n\nKeyboardTranslator::KeyboardTranslator(const QString& name)\n    : _name(name)\n{\n}\n\nvoid KeyboardTranslator::setDescription(const QString& description)\n{\n    _description = description;\n}\nQString KeyboardTranslator::description() const\n{\n    return _description;\n}\nvoid KeyboardTranslator::setName(const QString& name)\n{\n    _name = name;\n}\nQString KeyboardTranslator::name() const\n{\n    return _name;\n}\n\nQList<KeyboardTranslator::Entry> KeyboardTranslator::entries() const\n{\n    return _entries.values();\n}\n\nvoid KeyboardTranslator::addEntry(const Entry& entry)\n{\n    const int keyCode = entry.keyCode();\n    _entries.insert(keyCode,entry);\n}\nvoid KeyboardTranslator::replaceEntry(const Entry& existing , const Entry& replacement)\n{\n    if ( !existing.isNull() )\n        _entries.remove(existing.keyCode());\n    _entries.insert(replacement.keyCode(),replacement);\n}\nvoid KeyboardTranslator::removeEntry(const Entry& entry)\n{\n    _entries.remove(entry.keyCode());\n}\nKeyboardTranslator::Entry KeyboardTranslator::findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state) const\n{\n    if ( _entries.contains(keyCode) )\n    {\n        QList<Entry> entriesForKey = _entries.values(keyCode);\n\n        QListIterator<Entry> iter(entriesForKey);\n\n        while (iter.hasNext())\n        {\n            const Entry& next = iter.next();\n            if ( next.matches(keyCode,modifiers,state) )\n                return next;\n        }\n\n        return Entry(); // entry not found\n    }\n    else\n    {\n        return Entry();\n    }\n\n}\nvoid KeyboardTranslatorManager::addTranslator(KeyboardTranslator* translator)\n{\n    _translators.insert(translator->name(),translator);\n\n    if ( !saveTranslator(translator) )\n        qWarning() << \"Unable to save translator\" << translator->name()\n                   << \"to disk.\";\n}\nbool KeyboardTranslatorManager::deleteTranslator(const QString& name)\n{\n    Q_ASSERT( _translators.contains(name) );\n\n    // locate and delete\n    QString path = findTranslatorPath(name);\n    if ( QFile::remove(path) )\n    {\n        _translators.remove(name);\n        return true;\n    }\n    else\n    {\n        qWarning() << \"Failed to remove translator - \" << path;\n        return false;\n    }\n}\nK_GLOBAL_STATIC( KeyboardTranslatorManager , theKeyboardTranslatorManager )\nKeyboardTranslatorManager* KeyboardTranslatorManager::instance()\n{\n    return theKeyboardTranslatorManager;\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/KeyboardTranslator.h",
    "content": "/*\n    This source file is part of Konsole, a terminal emulator.\n\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef KEYBOARDTRANSLATOR_H\n#define KEYBOARDTRANSLATOR_H\n\n// Qt\n#include <QtCore>\n\n#include <QHash>\n#include <QKeySequence>\n#include <QList>\n#include <QMetaType>\n#include <QMultiHash>\n#include <QVarLengthArray>\n\n#if QT_VERSION >= 0x050100\n#  define K_GLOBAL_STATIC Q_GLOBAL_STATIC\n#else\n\ntypedef void (*CleanUpFunction)();\n\n/**\n * @internal\n *\n * Helper class for K_GLOBAL_STATIC to clean up the object on library unload or application\n * shutdown.\n */\nclass CleanUpGlobalStatic\n{\n    public:\n        CleanUpFunction func;\n\n        inline ~CleanUpGlobalStatic() { func(); }\n};\n\n\n//these directives are taken from the heart of kdecore\n\n# define K_GLOBAL_STATIC_STRUCT_NAME(NAME)\n\n#if QT_VERSION < 0x040400\n# define Q_BASIC_ATOMIC_INITIALIZER     Q_ATOMIC_INIT\n# define testAndSetOrdered              testAndSet\n#endif\n\n#define K_GLOBAL_STATIC(TYPE, NAME) K_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())\n\n#define K_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)                            \\\nstatic QBasicAtomicPointer<TYPE > _k_static_##NAME = Q_BASIC_ATOMIC_INITIALIZER(0); \\\nstatic bool _k_static_##NAME##_destroyed;                                      \\\nstatic struct K_GLOBAL_STATIC_STRUCT_NAME(NAME)                                \\\n{                                                                              \\\n    bool isDestroyed()                                                         \\\n    {                                                                          \\\n        return _k_static_##NAME##_destroyed;                                   \\\n    }                                                                          \\\n    inline operator TYPE*()                                                    \\\n    {                                                                          \\\n        return operator->();                                                   \\\n    }                                                                          \\\n    inline TYPE *operator->()                                                  \\\n    {                                                                          \\\n        if (!_k_static_##NAME) {                                               \\\n            if (isDestroyed()) {                                               \\\n            qFatal(\"Fatal Error: Accessed global static '%s *%s()' after destruction. \" \\\n             \"Defined at %s:%d\", #TYPE, #NAME, __FILE__, __LINE__);\t\t\\\n\t     }                                                                  \\\n\t     TYPE *x = new TYPE ARGS;                                           \\\n\t     if (!_k_static_##NAME.testAndSetOrdered(0, x)                      \\\n\t         && _k_static_##NAME != x ) {                                   \\\n\t         delete x;                                                      \\\n\t     } else { \t\t\t\t\t\t\t\t\\\n\t\tstatic CleanUpGlobalStatic cleanUpObject = { destroy };\t\\\n\t     }   \t\t\t\t\t\t\t\t\\\n\t }                                                                      \\\n         return _k_static_##NAME;                                               \\\n    }            \t\t\t\t\t\t\t\t\\\n    inline TYPE &operator*()                                                   \\\n    {                                                                          \\\n        return *operator->();                                                  \\\n    }                                                                          \\\n    static void destroy()                                                      \\\n    {                                                                          \\\n        _k_static_##NAME##_destroyed = true;                                   \\\n        TYPE *x = _k_static_##NAME;                                            \\\n        _k_static_##NAME = 0;                                                  \\\n        delete x;                                                              \\\n    }                                                                          \\\n} NAME;\n\n#endif\n\nclass QIODevice;\nclass QTextStream;\n\n/**\n * A convertor which maps between key sequences pressed by the user and the\n * character strings which should be sent to the terminal and commands\n * which should be invoked when those character sequences are pressed.\n *\n * Konsole supports multiple keyboard translators, allowing the user to\n * specify the character sequences which are sent to the terminal\n * when particular key sequences are pressed.\n *\n * A key sequence is defined as a key code, associated keyboard modifiers\n * (Shift,Ctrl,Alt,Meta etc.) and state flags which indicate the state\n * which the terminal must be in for the key sequence to apply.\n */\nclass KeyboardTranslator\n{\npublic:\n    /**\n     * The meaning of a particular key sequence may depend upon the state which\n     * the terminal emulation is in.  Therefore findEntry() may return a different\n     * Entry depending upon the state flags supplied.\n     *\n     * This enum describes the states which may be associated with with a particular\n     * entry in the keyboard translation entry.\n     */\n    enum State\n    {\n        /** Indicates that no special state is active */\n        NoState = 0,\n        /**\n         * TODO More documentation\n         */\n        NewLineState = 1,\n        /**\n         * Indicates that the terminal is in 'Ansi' mode.\n         * TODO: More documentation\n         */\n        AnsiState = 2,\n        /**\n         * TODO More documentation\n         */\n        CursorKeysState = 4,\n        /**\n         * Indicates that the alternate screen ( typically used by interactive programs\n         * such as screen or vim ) is active\n         */\n        AlternateScreenState = 8,\n        /** Indicates that any of the modifier keys is active. */\n        AnyModifierState = 16\n    };\n    Q_DECLARE_FLAGS(States,State)\n\n    /**\n     * This enum describes commands which are associated with particular key sequences.\n     */\n    enum Command\n    {\n        /** Indicates that no command is associated with this command sequence */\n        NoCommand = 0,\n        /** TODO Document me */\n        SendCommand = 1,\n        /** Scroll the terminal display up one page */\n        ScrollPageUpCommand = 2,\n        /** Scroll the terminal display down one page */\n        ScrollPageDownCommand = 4,\n        /** Scroll the terminal display up one line */\n        ScrollLineUpCommand = 8,\n        /** Scroll the terminal display down one line */\n        ScrollLineDownCommand = 16,\n        /** Toggles scroll lock mode */\n        ScrollLockCommand = 32,\n\t\t/** Echos the operating system specific erase character. */\n\t\tEraseCommand = 64\n    };\n    Q_DECLARE_FLAGS(Commands,Command)\n\n    /**\n     * Represents an association between a key sequence pressed by the user\n     * and the character sequence and commands associated with it for a particular\n     * KeyboardTranslator.\n     */\n    class Entry\n    {\n    public:\n        /**\n         * Constructs a new entry for a keyboard translator.\n         */\n        Entry();\n\n        /**\n         * Returns true if this entry is null.\n         * This is true for newly constructed entries which have no properties set.\n         */\n        bool isNull() const;\n\n        /** Returns the commands associated with this entry */\n        Command command() const;\n        /** Sets the command associated with this entry. */\n        void setCommand(Command command);\n\n        /**\n         * Returns the character sequence associated with this entry, optionally replacing\n         * wildcard '*' characters with numbers to indicate the keyboard modifiers being pressed.\n         *\n         * TODO: The numbers used to replace '*' characters are taken from the Konsole/KDE 3 code.\n         * Document them.\n         *\n         * @param expandWildCards Specifies whether wild cards (occurrences of the '*' character) in\n         * the entry should be replaced with a number to indicate the modifier keys being pressed.\n         *\n         * @param modifiers The keyboard modifiers being pressed.\n         */\n        QByteArray text(bool expandWildCards = false,\n                        Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;\n\n        /** Sets the character sequence associated with this entry */\n        void setText(const QByteArray& text);\n\n        /**\n         * Returns the character sequence associated with this entry,\n         * with any non-printable characters replaced with escape sequences.\n         *\n         * eg. \\\\E for Escape, \\\\t for tab, \\\\n for new line.\n         *\n         * @param expandWildCards See text()\n         * @param modifiers See text()\n         */\n        QByteArray escapedText(bool expandWildCards = false,\n                               Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;\n\n        /** Returns the character code ( from the Qt::Key enum ) associated with this entry */\n        int keyCode() const;\n        /** Sets the character code associated with this entry */\n        void setKeyCode(int keyCode);\n\n        /**\n         * Returns a bitwise-OR of the enabled keyboard modifiers associated with this entry.\n         * If a modifier is set in modifierMask() but not in modifiers(), this means that the entry\n         * only matches when that modifier is NOT pressed.\n         *\n         * If a modifier is not set in modifierMask() then the entry matches whether the modifier\n         * is pressed or not.\n         */\n        Qt::KeyboardModifiers modifiers() const;\n\n        /** Returns the keyboard modifiers which are valid in this entry.  See modifiers() */\n        Qt::KeyboardModifiers modifierMask() const;\n\n        /** See modifiers() */\n        void setModifiers( Qt::KeyboardModifiers modifiers );\n        /** See modifierMask() and modifiers() */\n        void setModifierMask( Qt::KeyboardModifiers modifiers );\n\n        /**\n         * Returns a bitwise-OR of the enabled state flags associated with this entry.\n         * If flag is set in stateMask() but not in state(), this means that the entry only\n         * matches when the terminal is NOT in that state.\n         *\n         * If a state is not set in stateMask() then the entry matches whether the terminal\n         * is in that state or not.\n         */\n        States state() const;\n\n        /** Returns the state flags which are valid in this entry.  See state() */\n        States stateMask() const;\n\n        /** See state() */\n        void setState( States state );\n        /** See stateMask() */\n        void setStateMask( States mask );\n\n        /**\n         * Returns the key code and modifiers associated with this entry\n         * as a QKeySequence\n         */\n        //QKeySequence keySequence() const;\n\n        /**\n         * Returns this entry's conditions ( ie. its key code, modifier and state criteria )\n         * as a string.\n         */\n        QString conditionToString() const;\n\n        /**\n         * Returns this entry's result ( ie. its command or character sequence )\n         * as a string.\n         *\n         * @param expandWildCards See text()\n         * @param modifiers See text()\n         */\n        QString resultToString(bool expandWildCards = false,\n                               Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;\n\n        /**\n         * Returns true if this entry matches the given key sequence, specified\n         * as a combination of @p keyCode , @p modifiers and @p state.\n         */\n        bool matches( int keyCode ,\n                      Qt::KeyboardModifiers modifiers ,\n                      States flags ) const;\n\n        bool operator==(const Entry& rhs) const;\n\n    private:\n        void insertModifier( QString& item , int modifier ) const;\n        void insertState( QString& item , int state ) const;\n        QByteArray unescape(const QByteArray& text) const;\n\n        int _keyCode;\n        Qt::KeyboardModifiers _modifiers;\n        Qt::KeyboardModifiers _modifierMask;\n        States _state;\n        States _stateMask;\n\n        Command _command;\n        QByteArray _text;\n    };\n\n    /** Constructs a new keyboard translator with the given @p name */\n    KeyboardTranslator(const QString& name);\n\n    //KeyboardTranslator(const KeyboardTranslator& other);\n\n    /** Returns the name of this keyboard translator */\n    QString name() const;\n\n    /** Sets the name of this keyboard translator */\n    void setName(const QString& name);\n\n    /** Returns the descriptive name of this keyboard translator */\n    QString description() const;\n\n    /** Sets the descriptive name of this keyboard translator */\n    void setDescription(const QString& description);\n\n    /**\n     * Looks for an entry in this keyboard translator which matches the given\n     * key code, keyboard modifiers and state flags.\n     *\n     * Returns the matching entry if found or a null Entry otherwise ( ie.\n     * entry.isNull() will return true )\n     *\n     * @param keyCode A key code from the Qt::Key enum\n     * @param modifiers A combination of modifiers\n     * @param state Optional flags which specify the current state of the terminal\n     */\n    Entry findEntry(int keyCode ,\n                    Qt::KeyboardModifiers modifiers ,\n                    States state = NoState) const;\n\n    /**\n     * Adds an entry to this keyboard translator's table.  Entries can be looked up according\n     * to their key sequence using findEntry()\n     */\n    void addEntry(const Entry& entry);\n\n    /**\n     * Replaces an entry in the translator.  If the @p existing entry is null,\n     * then this is equivalent to calling addEntry(@p replacement)\n     */\n    void replaceEntry(const Entry& existing , const Entry& replacement);\n\n    /**\n     * Removes an entry from the table.\n     */\n    void removeEntry(const Entry& entry);\n\n    /** Returns a list of all entries in the translator. */\n    QList<Entry> entries() const;\n\nprivate:\n\n    QMultiHash<int,Entry> _entries; // entries in this keyboard translation,\n                                                 // entries are indexed according to\n                                                 // their keycode\n    QString _name;\n    QString _description;\n};\nQ_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::States)\nQ_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::Commands)\n\n/**\n * Parses the contents of a Keyboard Translator (.keytab) file and\n * returns the entries found in it.\n *\n * Usage example:\n *\n * @code\n *  QFile source( \"/path/to/keytab\" );\n *  source.open( QIODevice::ReadOnly );\n *\n *  KeyboardTranslator* translator = new KeyboardTranslator( \"name-of-translator\" );\n *\n *  KeyboardTranslatorReader reader(source);\n *  while ( reader.hasNextEntry() )\n *      translator->addEntry(reader.nextEntry());\n *\n *  source.close();\n *\n *  if ( !reader.parseError() )\n *  {\n *      // parsing succeeded, do something with the translator\n *  }\n *  else\n *  {\n *      // parsing failed\n *  }\n * @endcode\n */\nclass KeyboardTranslatorReader\n{\npublic:\n    /** Constructs a new reader which parses the given @p source */\n    KeyboardTranslatorReader( QIODevice* source );\n\n    /**\n     * Returns the description text.\n     * TODO: More documentation\n     */\n    QString description() const;\n\n    /** Returns true if there is another entry in the source stream */\n    bool hasNextEntry();\n    /** Returns the next entry found in the source stream */\n    KeyboardTranslator::Entry nextEntry();\n\n    /**\n     * Returns true if an error occurred whilst parsing the input or\n     * false if no error occurred.\n     */\n    bool parseError();\n\n    /**\n     * Parses a condition and result string for a translator entry\n     * and produces a keyboard translator entry.\n     *\n     * The condition and result strings are in the same format as in\n     */\n    static KeyboardTranslator::Entry createEntry( const QString& condition ,\n                                                  const QString& result );\nprivate:\n    struct Token\n    {\n        enum Type\n        {\n            TitleKeyword,\n            TitleText,\n            KeyKeyword,\n            KeySequence,\n            Command,\n            OutputText\n        };\n        Type type;\n        QString text;\n    };\n    QList<Token> tokenize(const QString&);\n    void readNext();\n    bool decodeSequence(const QString& ,\n                                int& keyCode,\n                                Qt::KeyboardModifiers& modifiers,\n                                Qt::KeyboardModifiers& modifierMask,\n                                KeyboardTranslator::States& state,\n                                KeyboardTranslator::States& stateFlags);\n\n    static bool parseAsModifier(const QString& item , Qt::KeyboardModifier& modifier);\n    static bool parseAsStateFlag(const QString& item , KeyboardTranslator::State& state);\n    static bool parseAsKeyCode(const QString& item , int& keyCode);\n   \tstatic bool parseAsCommand(const QString& text , KeyboardTranslator::Command& command);\n\n    QIODevice* _source;\n    QString _description;\n    KeyboardTranslator::Entry _nextEntry;\n    bool _hasNext;\n};\n\n/** Writes a keyboard translation to disk. */\nclass KeyboardTranslatorWriter\n{\npublic:\n    /**\n     * Constructs a new writer which saves data into @p destination.\n     * The caller is responsible for closing the device when writing is complete.\n     */\n    KeyboardTranslatorWriter(QIODevice* destination);\n    ~KeyboardTranslatorWriter();\n\n    /**\n     * Writes the header for the keyboard translator.\n     * @param description Description of the keyboard translator.\n     */\n    void writeHeader( const QString& description );\n    /** Writes a translator entry. */\n    void writeEntry( const KeyboardTranslator::Entry& entry );\n\nprivate:\n    QIODevice* _destination;\n    QTextStream* _writer;\n};\n\n/**\n * Manages the keyboard translations available for use by terminal sessions,\n * see KeyboardTranslator.\n */\nclass KeyboardTranslatorManager\n{\npublic:\n    /**\n     * Constructs a new KeyboardTranslatorManager and loads the list of\n     * available keyboard translations.\n     *\n     * The keyboard translations themselves are not loaded until they are\n     * first requested via a call to findTranslator()\n     */\n    KeyboardTranslatorManager();\n    ~KeyboardTranslatorManager();\n\n    /**\n     * Adds a new translator.  If a translator with the same name\n     * already exists, it will be replaced by the new translator.\n     *\n     * TODO: More documentation.\n     */\n    void addTranslator(KeyboardTranslator* translator);\n\n    /**\n     * Deletes a translator.  Returns true on successful deletion or false otherwise.\n     *\n     * TODO: More documentation\n     */\n    bool deleteTranslator(const QString& name);\n\n    /** Returns the default translator for Konsole. */\n    const KeyboardTranslator* defaultTranslator();\n\n    /**\n     * Returns the keyboard translator with the given name or 0 if no translator\n     * with that name exists.\n     *\n     * The first time that a translator with a particular name is requested,\n     * the on-disk .keyboard file is loaded and parsed.\n     */\n    const KeyboardTranslator* findTranslator(const QString& name);\n    /**\n     * Returns a list of the names of available keyboard translators.\n     *\n     * The first time this is called, a search for available\n     * translators is started.\n     */\n    QList<QString> allTranslators();\n\n    /** Returns the global KeyboardTranslatorManager instance. */\n   static KeyboardTranslatorManager* instance();\n\nprivate:\n    static const char* defaultTranslatorText;\n\n    void findTranslators(); // locate the available translators\n    KeyboardTranslator* loadTranslator(const QString& name); // loads the translator\n                                                             // with the given name\n    KeyboardTranslator* loadTranslator(QIODevice* device,const QString& name);\n\n    bool saveTranslator(const KeyboardTranslator* translator);\n    QString findTranslatorPath(const QString& name);\n\n    QHash<QString,KeyboardTranslator*> _translators; // maps translator-name -> KeyboardTranslator\n                                                     // instance\n    bool _haveLoadedAll;\n};\n\ninline int KeyboardTranslator::Entry::keyCode() const { return _keyCode; }\ninline void KeyboardTranslator::Entry::setKeyCode(int keyCode) { _keyCode = keyCode; }\n\ninline void KeyboardTranslator::Entry::setModifiers( Qt::KeyboardModifiers modifier )\n{\n    _modifiers = modifier;\n}\ninline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifiers() const { return _modifiers; }\n\ninline void  KeyboardTranslator::Entry::setModifierMask( Qt::KeyboardModifiers mask )\n{\n   _modifierMask = mask;\n}\ninline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifierMask() const { return _modifierMask; }\n\ninline bool KeyboardTranslator::Entry::isNull() const\n{\n    return ( *this == Entry() );\n}\n\ninline void KeyboardTranslator::Entry::setCommand( Command command )\n{\n    _command = command;\n}\ninline KeyboardTranslator::Command KeyboardTranslator::Entry::command() const { return _command; }\n\ninline void KeyboardTranslator::Entry::setText( const QByteArray& text )\n{\n    _text = unescape(text);\n}\ninline int oneOrZero(int value)\n{\n    return value ? 1 : 0;\n}\ninline QByteArray KeyboardTranslator::Entry::text(bool expandWildCards,Qt::KeyboardModifiers modifiers) const\n{\n    QByteArray expandedText = _text;\n\n    if (expandWildCards)\n    {\n        int modifierValue = 1;\n        modifierValue += oneOrZero(modifiers & Qt::ShiftModifier);\n        modifierValue += oneOrZero(modifiers & Qt::AltModifier)     << 1;\n        modifierValue += oneOrZero(modifiers & Qt::ControlModifier) << 2;\n\n        for (int i=0;i<_text.length();i++)\n        {\n            if (expandedText[i] == '*')\n                expandedText[i] = '0' + modifierValue;\n        }\n    }\n\n    return expandedText;\n}\n\ninline void KeyboardTranslator::Entry::setState( States state )\n{\n    _state = state;\n}\ninline KeyboardTranslator::States KeyboardTranslator::Entry::state() const { return _state; }\n\ninline void KeyboardTranslator::Entry::setStateMask( States stateMask )\n{\n    _stateMask = stateMask;\n}\ninline KeyboardTranslator::States KeyboardTranslator::Entry::stateMask() const { return _stateMask; }\n\n\n#endif // KEYBOARDTRANSLATOR_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp",
    "content": "/*  Copyright (C) 2008 e_k (e_k@users.sourceforge.net)\n    Copyright (C) 2012-2019 Jacob Dawid <jacob.dawid@cybercatalyst.com>\n\n    This library is free software: you can redistribute it and/or\n    modify it under the terms of the GNU Library General Public\n    License as published by the Free Software Foundation; either\n    version 2 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Library General Public License for more details.\n\n    You should have received a copy of the GNU Library General Public License\n    along with this library; see the file COPYING.LIB.  If not, write to\n    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n    Boston, MA 02110-1301, USA.\n*/\n\n#include <QDebug>\n\n#include \"unix/QUnixTerminalImpl.h\"\n#include \"unix/kpty.h\"\n\n#include <termios.h>\n\nQUnixTerminalImpl::QUnixTerminalImpl(QWidget *p)\n    : QTerminal(p)\n{\n    initialize();\n}\n\nvoid QUnixTerminalImpl::initialize()\n{\n    m_terminalView = new TerminalView(this);\n    m_terminalView->setKeyboardCursorShape(TerminalView::UnderlineCursor);\n    m_terminalView->setBlinkingCursor(true);\n    m_terminalView->setBellMode(TerminalView::NotifyBell);\n    m_terminalView->setTerminalSizeHint(true);\n    m_terminalView->setContextMenuPolicy(Qt::CustomContextMenu);\n    m_terminalView->setTripleClickMode(TerminalView::SelectWholeLine);\n    m_terminalView->setTerminalSizeStartup(true);\n    m_terminalView->setSize(80, 40);\n    m_terminalView->setScrollBarPosition(TerminalView::ScrollBarRight);\n\n    UrlFilter *url_filter = new UrlFilter();\n    m_terminalView->filterChain ()->addFilter (url_filter);\n\n    UrlFilter *file_filter = new UrlFilter (Filter::Type::ErrorLink);\n    m_terminalView->filterChain ()->addFilter (file_filter);\n\n    connect (file_filter, SIGNAL (request_edit_mfile_signal (const QString&, int)),\n             this, SIGNAL (request_edit_mfile_signal (const QString&, int)));\n    connect (file_filter, SIGNAL (request_open_file_signal (const QString&, const QString&,int)),\n             this, SIGNAL (request_open_file_signal (const QString&, const QString&,int)));\n\n    connect(m_terminalView, SIGNAL(customContextMenuRequested(QPoint)),\n            this, SLOT(handleCustomContextMenuRequested(QPoint)));\n\n    connect (m_terminalView, SIGNAL (interrupt_signal ()),\n             this, SLOT (terminal_interrupt ()));\n\n#ifdef Q_OS_MAC\n    QFont font = QFont(\"Monaco\");\n    font.setStyleHint(QFont::TypeWriter);\n    font.setPointSize(11);\n#else\n    QFont font = QFont(\"Monospace\");\n    font.setStyleHint(QFont::TypeWriter);\n    font.setPointSize(10);\n#endif\n    setTerminalFont(font);\n    setFocusPolicy (Qt::StrongFocus);\n    setFocusProxy(m_terminalView);\n    setFocus(Qt::OtherFocusReason);\n\n    m_kpty = new KPty();\n    m_kpty->open();\n\n    m_terminalModel = new TerminalModel(m_kpty);\n    m_terminalModel->setAutoClose(true);\n    m_terminalModel->setCodec(QTextCodec::codecForName(\"UTF-8\"));\n    m_terminalModel->setHistoryType(HistoryTypeBuffer (1000));\n    m_terminalModel->setDarkBackground(true);\n    m_terminalModel->setKeyBindings(\"\");\n    m_terminalModel->run();\n    m_terminalModel->addView(m_terminalView);\n    connectToPty();\n}\nvoid QUnixTerminalImpl::setScrollBufferSize(int value)\n{\n  if (value > 0)\n    {\n      m_terminalModel->clearHistory ();\n      m_terminalModel->setHistoryType (HistoryTypeBuffer ( value ));\n    }\n  else\n    m_terminalModel->setHistoryType (HistoryTypeNone ());\n}\n\nQList<QAction*>\nQUnixTerminalImpl::get_hotspot_actions (const QPoint& at)\n{\n  return m_terminalView->filterActions (at);\n}\n\nvoid QUnixTerminalImpl::connectToPty()\n{\n    // Store the file descriptor associated with the STDIN, STDOUT, and\n    // STDERR streams onto another temporary file descriptor for\n    // reconnect in the destructor.\n\n    fdstdin = dup (STDIN_FILENO);\n    fdstdout = dup (STDOUT_FILENO);\n    fdstderr = dup (STDERR_FILENO);\n\n    int fds = m_kpty->slaveFd();\n\n    dup2 (fds, STDIN_FILENO);\n    dup2 (fds, STDOUT_FILENO);\n    dup2 (fds, STDERR_FILENO);\n\n    if(!isatty(STDIN_FILENO)) {\n        qDebug(\"Error: stdin is not a tty.\");\n    }\n\n    if(!isatty(STDOUT_FILENO)) {\n        qDebug(\"Error: stdout is not a tty.\");\n    }\n\n    if(!isatty(STDERR_FILENO)) {\n        qDebug(\"Error: stderr is not a tty.\");\n    }\n}\n\nQUnixTerminalImpl::~QUnixTerminalImpl()\n{\n    delete m_terminalModel;\n    delete m_kpty;\n    delete m_terminalView;\n\n    // Restore STDIN, STDOUT, and STDERR so that I/O at exit will work\n    // as expected.\n\n    dup2 (fdstdin, STDIN_FILENO);\n    dup2 (fdstdout, STDOUT_FILENO);\n    dup2 (fdstderr, STDERR_FILENO);\n\n    Q_EMIT destroyed();\n}\n\nvoid QUnixTerminalImpl::setTerminalFont(const QFont &font)\n{\n    if(!m_terminalView)\n        return;\n    m_terminalView->setVTFont(font);\n}\n\nvoid QUnixTerminalImpl::setSize(int h, int v)\n{\n    if(!m_terminalView)\n        return;\n    m_terminalView->setSize(h, v);\n}\n\nvoid QUnixTerminalImpl::sendText(const QString& text)\n{\n    m_terminalModel->sendText(text);\n}\n\nvoid QUnixTerminalImpl::setCursorType(CursorType type, bool blinking)\n{\n    switch(type) {\n        case UnderlineCursor: m_terminalView->setKeyboardCursorShape(TerminalView::UnderlineCursor); break;\n        case BlockCursor: m_terminalView->setKeyboardCursorShape(TerminalView::BlockCursor); break;\n        case IBeamCursor: m_terminalView->setKeyboardCursorShape(TerminalView::IBeamCursor); break;\n    }\n    m_terminalView->setBlinkingCursor(blinking);\n}\n\n// FIXME -- not sure how to make these work properly given the way the\n// Unix terminal handles colors.\nvoid QUnixTerminalImpl::setBackgroundColor (const QColor& color)\n  {\n    ColorEntry cols[TABLE_COLORS];\n\n    const ColorEntry * curr_cols = m_terminalView->colorTable();\n    for(int i=0;i<TABLE_COLORS;i++)\n    {\n     cols[i] = curr_cols[i];\n    }\n\n    cols[DEFAULT_BACK_COLOR].color = color;\n\n    m_terminalView->setColorTable(cols);\n\n    QString css = QString (\"TerminalView {\\n\"\n                           \"  background: %1;\\n\"\n                           \"}\\n\").arg (color.name ());\n    setStyleSheet (css);\n\n  }\nvoid QUnixTerminalImpl::setForegroundColor (const QColor& color)\n{\n    ColorEntry cols[TABLE_COLORS];\n\n    const ColorEntry * curr_cols = m_terminalView->colorTable();\n    for(int i=0;i<TABLE_COLORS;i++)\n    {\n     cols[i] = curr_cols[i];\n    }\n\n    cols[DEFAULT_FORE_COLOR].color = color;\n\n    m_terminalView->setColorTable(cols);\n\n\n}\nvoid QUnixTerminalImpl::setSelectionColor (const QColor& color) { }\n\nvoid QUnixTerminalImpl::setCursorColor (bool useForegroundColor,\n                                        const QColor& color)\n{\n  m_terminalView->setKeyboardCursorColor (useForegroundColor, color);\n}\n\nvoid QUnixTerminalImpl::showEvent(QShowEvent *)\n{\n    m_terminalView->updateImage();\n    m_terminalView->repaint();\n    m_terminalView->update();\n}\n\nvoid QUnixTerminalImpl::resizeEvent(QResizeEvent*)\n{\n    m_terminalView->resize(this->size());\n    m_terminalView->updateImage();\n    m_terminalView->repaint();\n    m_terminalView->update();\n}\n\nvoid QUnixTerminalImpl::copyClipboard()\n{\n    m_terminalView->copyClipboard (_extra_interrupt);\n}\n\nvoid QUnixTerminalImpl::pasteClipboard()\n{\n    m_terminalView->pasteClipboard();\n}\n\nvoid QUnixTerminalImpl::selectAll()\n{\n    m_terminalView->selectAll();\n}\n\n\nQString QUnixTerminalImpl::selectedText ()\n{\n  return m_terminalView->selectedText ();\n}\n\nvoid\nQUnixTerminalImpl::has_extra_interrupt (bool extra)\n{\n  _extra_interrupt = extra;\n}\n\nvoid\nQUnixTerminalImpl::handle_visibility_changed (bool visible)\n{\n  m_terminalView->visibility_changed (visible);\n};\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h",
    "content": "/*  Copyright (C) 2008 e_k (e_k@users.sourceforge.net)\n    Copyright (C) 2012-2019 Jacob Dawid <jacob.dawid@cybercatalyst.com>\n\n    This library is free software: you can redistribute it and/or\n    modify it under the terms of the GNU Library General Public\n    License as published by the Free Software Foundation; either\n    version 2 of the License, or (at your option) any later version.\n\t\t\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Library General Public License for more details.\n\t\t\t\n    You should have received a copy of the GNU Library General Public License\n    along with this library; see the file COPYING.LIB.  If not, write to\n    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n    Boston, MA 02110-1301, USA.\n*/\n\t\t\t\t\t\t\n\n#ifndef Q_UNIXTERMINALIMPL\n#define Q_UNIXTERMINALIMPL\n\n#include <QtGui>\n#include \"unix/kpty.h\"\n#include \"unix/TerminalModel.h\"\n#include \"unix/TerminalView.h\"\n#include \"QTerminal.h\"\n\nclass QUnixTerminalImpl : public QTerminal\n{\n    Q_OBJECT\n\n    int fdstdin;\n    int fdstdout;\n    int fdstderr;\n\npublic:\n    QUnixTerminalImpl(QWidget *parent);\n    virtual ~QUnixTerminalImpl();\n\n    void setTerminalFont(const QFont &font);\n    void setSize(int h, int v);\n    void sendText(const QString& text);\n\n    void setCursorType(CursorType type, bool blinking);\n\n    void setBackgroundColor (const QColor& color);\n    void setForegroundColor (const QColor& color);\n    void setSelectionColor (const QColor& color);\n    void setCursorColor (bool useForegroundColor, const QColor& color);\n    void setScrollBufferSize(int value);\n    QString selectedText();\n    void has_extra_interrupt (bool extra_interrupt);\n    QList<QAction*> get_hotspot_actions (const QPoint& at);\n\npublic Q_SLOTS:\n    void copyClipboard();\n    void pasteClipboard();\n    void selectAll();\n    virtual void handle_visibility_changed (bool visible);\n\nprotected:\n    void showEvent(QShowEvent *);\n    virtual void resizeEvent(QResizeEvent *);\n\nprivate:\n    void initialize ();\n    void connectToPty();\n\n    TerminalView *m_terminalView;\n    TerminalModel *m_terminalModel;\n    KPty *m_kpty;\n    bool _extra_interrupt;\n};\n\n#endif // Q_UNIXTERMINALIMPL\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/Screen.cpp",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n    Copyright (C) 1997-1998, 2013 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n// Own\n#include \"unix/Screen.h\"\n\n// Standard\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <assert.h>\n#include <string.h>\n#include <ctype.h>\n\n// Qt\n#include <QDate>\n#include <QTextStream>\n\n// Konsole\n#include \"unix/konsole_wcwidth.h\"\n#include \"unix/TerminalCharacterDecoder.h\"\n\n//FIXME: this is emulation specific. Use false for xterm, true for ANSI.\n//FIXME: see if we can get this from terminfo.\n#define BS_CLEARS false\n\n//Macro to convert x,y position on screen to position within an image.\n//\n//Originally the image was stored as one large contiguous block of\n//memory, so a position within the image could be represented as an\n//offset from the beginning of the block.  For efficiency reasons this\n//is no longer the case.\n//Many internal parts of this class still use this representation for parameters and so on,\n//notably moveImage() and clearImage().\n//This macro converts from an X,Y position into an image offset.\n#ifndef loc\n#define loc(X,Y) ((Y)*columns+(X))\n#endif\n\n\nCharacter Screen::defaultChar = Character(' ',\n\t\t\t\t\t  CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR),\n\t\t\t\t\t  CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR),\n\t\t\t\t\t  DEFAULT_RENDITION);\n\n//#define REVERSE_WRAPPED_LINES  // for wrapped line debug\n\nScreen::Screen(int l, int c)\n  : lines(l),\n    columns(c),\n    screenLines(new ImageLine[lines+1] ),\n    _scrolledLines(0),\n    _droppedLines(0),\n    hist(new HistoryScrollNone()),\n    cuX(0), cuY(0),\n    cu_re(0),\n    tmargin(0), bmargin(0),\n    tabstops(nullptr),\n    sel_begin(0), sel_TL(0), sel_BR(0),\n    sel_busy(false),\n    columnmode(false),\n    ef_fg(CharacterColor()), ef_bg(CharacterColor()), ef_re(0),\n    sa_cuX(0), sa_cuY(0),\n    sa_cu_re(0),\n    lastPos(-1)\n{\n  lineProperties.resize(lines+1);\n  for (int i=0;i<lines+1;i++)\n          lineProperties[i]=LINE_DEFAULT;\n\n  initTabStops();\n  clearSelection();\n  reset();\n}\n\n/*! Destructor\n*/\n\nScreen::~Screen()\n{\n  delete[] screenLines;\n  delete[] tabstops;\n  delete hist;\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/* Normalized                    Screen Operations                           */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n// Cursor Setting --------------------------------------------------------------\n\n/*! @section Cursor\n\n    The `cursor' is a location within the screen that is implicitely used in\n    many operations. The operations within this section allow to manipulate\n    the cursor explicitly and to obtain it's value.\n\n    The position of the cursor is guarantied to be between (including) 0 and\n    `columns-1' and `lines-1'.\n*/\n\n/*!\n    Move the cursor up.\n\n    The cursor will not be moved beyond the top margin.\n*/\n\nvoid Screen::cursorUp(int n)\n//=CUU\n{\n  if (n == 0) n = 1; // Default\n  int stop = cuY < tmargin ? 0 : tmargin;\n  cuX = qMin(columns-1,cuX); // nowrap!\n  cuY = qMax(stop,cuY-n);\n}\n\n/*!\n    Move the cursor down.\n\n    The cursor will not be moved beyond the bottom margin.\n*/\n\nvoid Screen::cursorDown(int n)\n//=CUD\n{\n  if (n == 0) n = 1; // Default\n  int stop = cuY > bmargin ? lines-1 : bmargin;\n  cuX = qMin(columns-1,cuX); // nowrap!\n  cuY = qMin(stop,cuY+n);\n}\n\n/*!\n    Move the cursor left.\n\n    The cursor will not move beyond the first column.\n*/\n\nvoid Screen::cursorLeft(int n)\n//=CUB\n{\n  if (n == 0) n = 1; // Default\n  cuX = qMin(columns-1,cuX); // nowrap!\n  cuX = qMax(0,cuX-n);\n}\n\n/*!\n    Move the cursor left.\n\n    The cursor will not move beyond the rightmost column.\n*/\n\nvoid Screen::cursorRight(int n)\n//=CUF\n{\n  if (n == 0) n = 1; // Default\n  cuX = qMin(columns-1,cuX+n);\n}\n\nvoid Screen::setMargins(int top, int bot)\n//=STBM\n{\n  if (top == 0) top = 1;      // Default\n  if (bot == 0) bot = lines;  // Default\n  top = top - 1;              // Adjust to internal lineno\n  bot = bot - 1;              // Adjust to internal lineno\n  if ( !( 0 <= top && top < bot && bot < lines ) )\n  { qDebug()<<\" setRegion(\"<<top<<\",\"<<bot<<\") : bad range.\";\n    return;                   // Default error action: ignore\n  }\n  tmargin = top;\n  bmargin = bot;\n  cuX = 0;\n  cuY = getMode(MODE_Origin) ? top : 0;\n\n}\n\nint Screen::topMargin() const\n{\n    return tmargin;\n}\nint Screen::bottomMargin() const\n{\n    return bmargin;\n}\n\nvoid Screen::index()\n//=IND\n{\n  if (cuY == bmargin)\n  {\n    scrollUp(1);\n  }\n  else if (cuY < lines-1)\n    cuY += 1;\n}\n\nvoid Screen::reverseIndex()\n//=RI\n{\n  if (cuY == tmargin)\n     scrollDown(tmargin,1);\n  else if (cuY > 0)\n    cuY -= 1;\n}\n\n/*!\n    Move the cursor to the begin of the next line.\n\n    If cursor is on bottom margin, the region between the\n    actual top and bottom margin is scrolled up.\n*/\n\nvoid Screen::NextLine()\n//=NEL\n{\n  Return(); index();\n}\n\nvoid Screen::eraseChars(int n)\n{\n  if (n == 0) n = 1; // Default\n  int p = qMax(0,qMin(cuX+n-1,columns-1));\n  clearImage(loc(cuX,cuY),loc(p,cuY),' ');\n}\n\nvoid Screen::deleteChars(int n)\n{\n  Q_ASSERT( n >= 0 );\n\n  // always delete at least one char\n  if (n == 0)\n      n = 1;\n\n  // if cursor is beyond the end of the line there is nothing to do\n  if ( cuX >= screenLines[cuY].count() )\n      return;\n\n  if ( cuX+n >= screenLines[cuY].count() )\n       n = screenLines[cuY].count() - 1 - cuX;\n\n  Q_ASSERT( n >= 0 );\n  Q_ASSERT( cuX+n < screenLines[cuY].count() );\n\n  screenLines[cuY].remove(cuX,n);\n}\n\nvoid Screen::insertChars(int n)\n{\n  if (n == 0) n = 1; // Default\n\n  if ( screenLines[cuY].size() < cuX )\n    screenLines[cuY].resize(cuX);\n\n  screenLines[cuY].insert(cuX,n,' ');\n\n  if ( screenLines[cuY].count() > columns )\n      screenLines[cuY].resize(columns);\n}\n\nvoid Screen::deleteLines(int n)\n{\n  if (n == 0) n = 1; // Default\n  scrollUp(cuY,n);\n}\n\n/*! insert `n' lines at the cursor position.\n\n    The cursor is not moved by the operation.\n*/\n\nvoid Screen::insertLines(int n)\n{\n  if (n == 0) n = 1; // Default\n  scrollDown(cuY,n);\n}\n\n// Mode Operations -----------------------------------------------------------\n\n/*! Set a specific mode. */\n\nvoid Screen::setMode(int m)\n{\n  currParm.mode[m] = true;\n  switch(m)\n  {\n    case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home\n  }\n}\n\n/*! Reset a specific mode. */\n\nvoid Screen::resetMode(int m)\n{\n  currParm.mode[m] = false;\n  switch(m)\n  {\n    case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home\n  }\n}\n\n/*! Save a specific mode. */\n\nvoid Screen::saveMode(int m)\n{\n  saveParm.mode[m] = currParm.mode[m];\n}\n\n/*! Restore a specific mode. */\n\nvoid Screen::restoreMode(int m)\n{\n  currParm.mode[m] = saveParm.mode[m];\n}\n\nbool Screen::getMode(int m) const\n{\n  return currParm.mode[m];\n}\n\nvoid Screen::saveCursor()\n{\n  sa_cuX     = cuX;\n  sa_cuY     = cuY;\n  sa_cu_re   = cu_re;\n  sa_cu_fg   = cu_fg;\n  sa_cu_bg   = cu_bg;\n}\n\nvoid Screen::restoreCursor()\n{\n  cuX     = qMin(sa_cuX,columns-1);\n  cuY     = qMin(sa_cuY,lines-1);\n  cu_re   = sa_cu_re;\n  cu_fg   = sa_cu_fg;\n  cu_bg   = sa_cu_bg;\n  effectiveRendition();\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                             Screen Operations                             */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n/*! Resize the screen image\n\n    The topmost left position is maintained, while lower lines\n    or right hand side columns might be removed or filled with\n    spaces to fit the new size.\n\n    The region setting is reset to the whole screen and the\n    tab positions reinitialized.\n\n    If the new image is narrower than the old image then text on lines\n    which extends past the end of the new image is preserved so that it becomes\n    visible again if the screen is later resized to make it larger.\n*/\n\nvoid Screen::resizeImage(int new_lines, int new_columns)\n{\n  if ((new_lines==lines) && (new_columns==columns)) return;\n\n  if (cuY > new_lines-1)\n  { // attempt to preserve focus and lines\n    bmargin = lines-1; //FIXME: margin lost\n    for (int i = 0; i < cuY-(new_lines-1); i++)\n    {\n      addHistLine(); scrollUp(0,1);\n    }\n  }\n\n  // create new screen lines and copy from old to new\n\n   ImageLine* newScreenLines = new ImageLine[new_lines+1];\n   for (int i=0; i < qMin(lines-1,new_lines+1) ;i++)\n           newScreenLines[i]=screenLines[i];\n   for (int i=lines;(i > 0) && (i<new_lines+1);i++)\n           newScreenLines[i].resize( new_columns );\n\n  lineProperties.resize(new_lines+1);\n  for (int i=lines;(i > 0) && (i<new_lines+1);i++)\n          lineProperties[i] = LINE_DEFAULT;\n\n  clearSelection();\n\n  delete[] screenLines;\n  screenLines = newScreenLines;\n\n  lines = new_lines;\n  columns = new_columns;\n  cuX = qMin(cuX,columns-1);\n  cuY = qMin(cuY,lines-1);\n\n  // FIXME: try to keep values, evtl.\n  tmargin=0;\n  bmargin=lines-1;\n  initTabStops();\n  clearSelection();\n}\n\nvoid Screen::setDefaultMargins()\n{\n\ttmargin = 0;\n\tbmargin = lines-1;\n}\n\n\n/*\n   Clarifying rendition here and in the display.\n\n   currently, the display's color table is\n     0       1       2 .. 9    10 .. 17\n     dft_fg, dft_bg, dim 0..7, intensive 0..7\n\n   cu_fg, cu_bg contain values 0..8;\n   - 0    = default color\n   - 1..8 = ansi specified color\n\n   re_fg, re_bg contain values 0..17\n   due to the TerminalDisplay's color table\n\n   rendition attributes are\n\n      attr           widget screen\n      -------------- ------ ------\n      RE_UNDERLINE     XX     XX    affects foreground only\n      RE_BLINK         XX     XX    affects foreground only\n      RE_BOLD          XX     XX    affects foreground only\n      RE_REVERSE       --     XX\n      RE_TRANSPARENT   XX     --    affects background only\n      RE_INTENSIVE     XX     --    affects foreground only\n\n   Note that RE_BOLD is used in both widget\n   and screen rendition. Since xterm/vt102\n   is to poor to distinguish between bold\n   (which is a font attribute) and intensive\n   (which is a color attribute), we translate\n   this and RE_BOLD in falls eventually appart\n   into RE_BOLD and RE_INTENSIVE.\n*/\n\nvoid Screen::reverseRendition(Character& p) const\n{\n\tCharacterColor f = p.foregroundColor;\n\tCharacterColor b = p.backgroundColor;\n  \t\n\tp.foregroundColor = b;\n\tp.backgroundColor = f; //p->r &= ~RE_TRANSPARENT;\n}\n\nvoid Screen::effectiveRendition()\n// calculate rendition\n{\n  //copy \"current rendition\" straight into \"effective rendition\", which is then later copied directly\n  //into the image[] array which holds the characters and their appearance properties.\n  //- The old version below filtered out all attributes other than underline and blink at this stage,\n  //so that they would not be copied into the image[] array and hence would not be visible by TerminalDisplay\n  //which actually paints the screen using the information from the image[] array.\n  //I don't know why it did this, but I'm fairly sure it was the wrong thing to do.  The net result\n  //was that bold text wasn't printed in bold by Konsole.\n  ef_re = cu_re;\n\n  //OLD VERSION:\n  //ef_re = cu_re & (RE_UNDERLINE | RE_BLINK);\n\n  if (cu_re & RE_REVERSE)\n  {\n    ef_fg = cu_bg;\n    ef_bg = cu_fg;\n  }\n  else\n  {\n    ef_fg = cu_fg;\n    ef_bg = cu_bg;\n  }\n\n  if (cu_re & RE_BOLD)\n    ef_fg.toggleIntensive();\n}\n\n/*!\n    returns the image.\n\n    Get the size of the image by @sa getLines and @sa getColumns.\n\n    NOTE that the image returned by this function must later be\n    freed.\n\n*/\n\nvoid Screen::copyFromHistory(Character* dest, int startLine, int count) const\n{\n  Q_ASSERT( startLine >= 0 && count > 0 && startLine + count <= hist->getLines() );\n\n  for (int line = startLine; line < startLine + count; line++)\n  {\n    const int length = qMin(columns,hist->getLineLen(line));\n    const int destLineOffset  = (line-startLine)*columns;\n\n    hist->getCells(line,0,length,dest + destLineOffset);\n\n    for (int column = length; column < columns; column++)\n\t\tdest[destLineOffset+column] = defaultChar;\n\n\t// invert selected text\n\tif (sel_begin !=-1)\n\t{\n    \tfor (int column = 0; column < columns; column++)\n    \t{\n        \tif (isSelected(column,line))\n\t\t\t{\n          \t\treverseRendition(dest[destLineOffset + column]);\n    \t\t}\n  \t\t}\n\t}\n  }\n}\n\nvoid Screen::copyFromScreen(Character* dest , int startLine , int count) const\n{\n\tQ_ASSERT( startLine >= 0 && count > 0 && startLine + count <= lines );\n\n    for (int line = startLine; line < (startLine+count) ; line++)\n    {\n       int srcLineStartIndex  = line*columns;\n\t   int destLineStartIndex = (line-startLine)*columns;\n\n       for (int column = 0; column < columns; column++)\n       {\n\t\t int srcIndex = srcLineStartIndex + column;\n\t\t int destIndex = destLineStartIndex + column;\n\n         dest[destIndex] = screenLines[srcIndex/columns].value(srcIndex%columns,defaultChar);\n\n\t     // invert selected text\n         if (sel_begin != -1 && isSelected(column,line + hist->getLines()))\n           reverseRendition(dest[destIndex]);\n       }\n\n    }\n}\n\nvoid Screen::getImage( Character* dest, int size, int startLine, int endLine ) const\n{\n  Q_ASSERT( startLine >= 0 );\n  Q_ASSERT( endLine >= startLine && endLine < hist->getLines() + lines );\n\n  const int mergedLines = endLine - startLine + 1;\n\n  Q_ASSERT( size >= mergedLines * columns );\n  Q_UNUSED( size );\n\n  const int linesInHistoryBuffer = qBound(0,hist->getLines()-startLine,mergedLines);\n  const int linesInScreenBuffer = mergedLines - linesInHistoryBuffer;\n\n  // copy lines from history buffer\n  if (linesInHistoryBuffer > 0) {\n  \tcopyFromHistory(dest,startLine,linesInHistoryBuffer);\n    }\n\n  // copy lines from screen buffer\n  if (linesInScreenBuffer > 0) {\n  \tcopyFromScreen(dest + linesInHistoryBuffer*columns,\n\t\t\t\t   startLine + linesInHistoryBuffer - hist->getLines(),\n\t\t\t\t   linesInScreenBuffer);\n    }\t\t\t\t\n\n  // invert display when in screen mode\n  if (getMode(MODE_Screen))\n  {\n    for (int i = 0; i < mergedLines*columns; i++)\n      reverseRendition(dest[i]); // for reverse display\n  }\n\n  // mark the character at the current cursor position\n  int cursorIndex = loc(cuX, cuY + linesInHistoryBuffer);\n  if(getMode(MODE_Cursor) && cursorIndex < columns*mergedLines)\n    dest[cursorIndex].rendition |= RE_CURSOR;\n}\n\nQVector<LineProperty> Screen::getLineProperties( int startLine , int endLine ) const\n{\n  Q_ASSERT( startLine >= 0 );\n  Q_ASSERT( endLine >= startLine && endLine < hist->getLines() + lines );\n\n\tconst int mergedLines = endLine-startLine+1;\n\tconst int linesInHistory = qBound(0,hist->getLines()-startLine,mergedLines);\n  const int linesInScreen = mergedLines - linesInHistory;\n\n  QVector<LineProperty> result(mergedLines);\n  int index = 0;\n\n  // copy properties for lines in history\n  for (int line = startLine; line < startLine + linesInHistory; line++)\n  {\n\t\t//TODO Support for line properties other than wrapped lines\n\t  if (hist->isWrappedLine(line))\n\t  {\n\t  \tresult[index] = (LineProperty)(result[index] | LINE_WRAPPED);\n\t  }\n    index++;\n  }\n\n  // copy properties for lines in screen buffer\n  const int firstScreenLine = startLine + linesInHistory - hist->getLines();\n  for (int line = firstScreenLine; line < firstScreenLine+linesInScreen; line++)\n\t{\n    result[index]=lineProperties[line];\n  \tindex++;\n\t}\n\n  return result;\n}\n\n/*!\n*/\n\nvoid Screen::reset(bool clearScreen)\n{\n    setMode(MODE_Wrap  ); saveMode(MODE_Wrap  );  // wrap at end of margin\n  resetMode(MODE_Origin); saveMode(MODE_Origin);  // position refere to [1,1]\n  resetMode(MODE_Insert); saveMode(MODE_Insert);  // overstroke\n    setMode(MODE_Cursor);                         // cursor visible\n  resetMode(MODE_Screen);                         // screen not inverse\n  resetMode(MODE_NewLine);\n\n  tmargin=0;\n  bmargin=lines-1;\n\n  setDefaultRendition();\n  saveCursor();\n\n  if ( clearScreen )\n    clear();\n}\n\n/*! Clear the entire screen and home the cursor.\n*/\n\nvoid Screen::clear()\n{\n  clearEntireScreen();\n  home();\n}\n\nvoid Screen::BackSpace()\n{\n  cuX = qMin(columns-1,cuX); // nowrap!\n  cuX = qMax(0,cuX-1);\n // if (BS_CLEARS) image[loc(cuX,cuY)].character = ' ';\n\n  if (screenLines[cuY].size() < cuX+1)\n          screenLines[cuY].resize(cuX+1);\n\n  if (BS_CLEARS) screenLines[cuY][cuX].character = ' ';\n}\n\nvoid Screen::Tabulate(int n)\n{\n  // note that TAB is a format effector (does not write ' ');\n  if (n == 0) n = 1;\n  while((n > 0) && (cuX < columns-1))\n  {\n    cursorRight(1); while((cuX < columns-1) && !tabstops[cuX]) cursorRight(1);\n    n--;\n  }\n}\n\nvoid Screen::backTabulate(int n)\n{\n  // note that TAB is a format effector (does not write ' ');\n  if (n == 0) n = 1;\n  while((n > 0) && (cuX > 0))\n  {\n     cursorLeft(1); while((cuX > 0) && !tabstops[cuX]) cursorLeft(1);\n     n--;\n  }\n}\n\nvoid Screen::clearTabStops()\n{\n  for (int i = 0; i < columns; i++) tabstops[i] = false;\n}\n\nvoid Screen::changeTabStop(bool set)\n{\n  if (cuX >= columns) return;\n  tabstops[cuX] = set;\n}\n\nvoid Screen::initTabStops()\n{\n  delete[] tabstops;\n  tabstops = new bool[columns];\n\n  // Arrg! The 1st tabstop has to be one longer than the other.\n  // i.e. the kids start counting from 0 instead of 1.\n  // Other programs might behave correctly. Be aware.\n  for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);\n}\n\n/*!\n   This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine)\n   depending on the NewLine Mode (LNM). This mode also\n   affects the key sequence returned for newline ([CR]LF).\n*/\n\nvoid Screen::NewLine()\n{\n  if (getMode(MODE_NewLine)) Return();\n  index();\n}\n\n/*! put `c' literally onto the screen at the current cursor position.\n\n    VT100 uses the convention to produce an automatic newline (am)\n    with the *first* character that would fall onto the next line (xenl).\n*/\n\nvoid Screen::checkSelection(int from, int to)\n{\n  if (sel_begin == -1) return;\n  int scr_TL = loc(0, hist->getLines());\n  //Clear entire selection if it overlaps region [from, to]\n  if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )\n  {\n    clearSelection();\n  }\n}\n\nvoid Screen::ShowCharacter(unsigned short c)\n{\n  // Note that VT100 does wrapping BEFORE putting the character.\n  // This has impact on the assumption of valid cursor positions.\n  // We indicate the fact that a newline has to be triggered by\n  // putting the cursor one right to the last column of the screen.\n\n  int w = konsole_wcwidth(c);\n\n  if (w <= 0)\n     return;\n\n  if (cuX+w > columns) {\n    if (getMode(MODE_Wrap)) {\n      lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | LINE_WRAPPED);\n      NextLine();\n    }\n    else\n      cuX = columns-w;\n  }\n\n  // ensure current line vector has enough elements\n  int size = screenLines[cuY].size();\n  if (size == 0 && cuY > 0)\n  {\n          screenLines[cuY].resize( qMax(screenLines[cuY-1].size() , cuX+w) );\n  }\n  else\n  {\n    if (size < cuX+w)\n    {\n          screenLines[cuY].resize(cuX+w);\n    }\n  }\n\n  if (getMode(MODE_Insert)) insertChars(w);\n\n  lastPos = loc(cuX,cuY);\n\n  // clear selection on text input\n  clearSelection ();\n\n  Character& currentChar = screenLines[cuY][cuX];\n\n  currentChar.character = c;\n  currentChar.foregroundColor = ef_fg;\n  currentChar.backgroundColor = ef_bg;\n  currentChar.rendition = ef_re;\n\n  int i = 0;\n  int newCursorX = cuX + w--;\n  while(w)\n  {\n     i++;\n\n     if ( screenLines[cuY].size() < cuX + i + 1 )\n         screenLines[cuY].resize(cuX+i+1);\n\n     Character& ch = screenLines[cuY][cuX + i];\n     ch.character = 0;\n     ch.foregroundColor = ef_fg;\n     ch.backgroundColor = ef_bg;\n     ch.rendition = ef_re;\n\n     w--;\n  }\n  cuX = newCursorX;\n}\n\nvoid Screen::compose(const QString& /*compose*/)\n{\n   Q_ASSERT( 0 /*Not implemented yet*/ );\n\n/*  if (lastPos == -1)\n     return;\n\n  QChar c(image[lastPos].character);\n  compose.prepend(c);\n  //compose.compose(); ### FIXME!\n  image[lastPos].character = compose[0].unicode();*/\n}\n\nint Screen::scrolledLines() const\n{\n        return _scrolledLines;\n}\nint Screen::droppedLines() const\n{\n    return _droppedLines;\n}\nvoid Screen::resetDroppedLines()\n{\n    _droppedLines = 0;\n}\nvoid Screen::resetScrolledLines()\n{\n    //kDebug() << \"scrolled lines reset\";\n\n    _scrolledLines = 0;\n}\n\n// Region commands -------------------------------------------------------------\n\nvoid Screen::scrollUp(int n)\n{\n   if (n == 0) n = 1; // Default\n   if (tmargin == 0) addHistLine(); // hist.history\n   scrollUp(tmargin, n);\n}\n\n/*! scroll up `n' lines within current region.\n    The `n' new lines are cleared.\n    @sa setRegion @sa scrollDown\n*/\n\nQRect Screen::lastScrolledRegion() const\n{\n    return _lastScrolledRegion;\n}\n\nvoid Screen::scrollUp(int from, int n)\n{\n  if (n <= 0 || from + n > bmargin) return;\n\n  _scrolledLines -= n;\n  _lastScrolledRegion = QRect(0,tmargin,columns-1,(bmargin-tmargin));\n\n  //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.\n  moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin));\n  clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' ');\n}\n\nvoid Screen::scrollDown(int n)\n{\n   if (n == 0) n = 1; // Default\n   scrollDown(tmargin, n);\n}\n\n/*! scroll down `n' lines within current region.\n    The `n' new lines are cleared.\n    @sa setRegion @sa scrollUp\n*/\n\nvoid Screen::scrollDown(int from, int n)\n{\n\n  //kDebug() << \"Screen::scrollDown( from: \" << from << \" , n: \" << n << \")\";\n\n  _scrolledLines += n;\n\n//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.\n  if (n <= 0) return;\n  if (from > bmargin) return;\n  if (from + n > bmargin) n = bmargin - from;\n  moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n));\n  clearImage(loc(0,from),loc(columns-1,from+n-1),' ');\n}\n\nvoid Screen::setCursorYX(int y, int x)\n{\n  setCursorY(y); setCursorX(x);\n}\n\nvoid Screen::setCursorX(int x)\n{\n  if (x == 0) x = 1; // Default\n  x -= 1; // Adjust\n  cuX = qMax(0,qMin(columns-1, x));\n}\n\nvoid Screen::setCursorY(int y)\n{\n  if (y == 0) y = 1; // Default\n  y -= 1; // Adjust\n  cuY = qMax(0,qMin(lines  -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));\n}\n\nvoid Screen::home()\n{\n  cuX = 0;\n  cuY = 0;\n}\n\nvoid Screen::Return()\n{\n  cuX = 0;\n}\n\nint Screen::getCursorX() const\n{\n  return cuX;\n}\n\nint Screen::getCursorY() const\n{\n  return cuY;\n}\n\n// Erasing ---------------------------------------------------------------------\n\n/*! @section Erasing\n\n    This group of operations erase parts of the screen contents by filling\n    it with spaces colored due to the current rendition settings.\n\n    Althought the cursor position is involved in most of these operations,\n    it is never modified by them.\n*/\n\n/*! fill screen between (including) `loca' (start) and `loce' (end) with spaces.\n\n    This is an internal helper functions. The parameter types are internal\n    addresses of within the screen image and make use of the way how the\n    screen matrix is mapped to the image vector.\n*/\n\nvoid Screen::clearImage(int loca, int loce, char c)\n{\n  int scr_TL=loc(0,hist->getLines());\n  //FIXME: check positions\n\n  //Clear entire selection if it overlaps region to be moved...\n  if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )\n  {\n    clearSelection();\n  }\n\n  int topLine = loca/columns;\n  int bottomLine = loce/columns;\n\n  Character clearCh(c,cu_fg,cu_bg,DEFAULT_RENDITION);\n\n  //if the character being used to clear the area is the same as the\n  //default character, the affected lines can simply be shrunk.\n  bool isDefaultCh = (clearCh == Character());\n\n  for (int y=topLine;y<=bottomLine;y++)\n  {\n        lineProperties[y] = 0;\n\n        int endCol = ( y == bottomLine) ? loce%columns : columns-1;\n        int startCol = ( y == topLine ) ? loca%columns : 0;\n\n        QVector<Character>& line = screenLines[y];\n\n        if ( isDefaultCh && endCol == columns-1 )\n        {\n            line.resize(startCol);\n        }\n        else\n        {\n            if (line.size() < endCol + 1)\n                line.resize(endCol+1);\n\n            Character* data = line.data();\n            for (int i=startCol;i<=endCol;i++)\n                data[i]=clearCh;\n        }\n  }\n}\n\n/*! move image between (including) `sourceBegin' and `sourceEnd' to 'dest'.\n\n    The 'dest', 'sourceBegin' and 'sourceEnd' parameters can be generated using\n    the loc(column,line) macro.\n\nNOTE:  moveImage() can only move whole lines.\n\n    This is an internal helper functions. The parameter types are internal\n    addresses of within the screen image and make use of the way how the\n    screen matrix is mapped to the image vector.\n*/\n\nvoid Screen::moveImage(int dest, int sourceBegin, int sourceEnd)\n{\n  //kDebug() << \"moving image from (\" << (sourceBegin/columns)\n  //    << \",\" << (sourceEnd/columns) << \") to \" <<\n  //    (dest/columns);\n\n  Q_ASSERT( sourceBegin <= sourceEnd );\n\n  int lines=(sourceEnd-sourceBegin)/columns;\n\n  //move screen image and line properties:\n  //the source and destination areas of the image may overlap,\n  //so it matters that we do the copy in the right order -\n  //forwards if dest < sourceBegin or backwards otherwise.\n  //(search the web for 'memmove implementation' for details)\n  if (dest < sourceBegin)\n  {\n    for (int i=0;i<=lines;i++)\n    {\n        screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ];\n        lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i];\n    }\n  }\n  else\n  {\n    for (int i=lines;i>=0;i--)\n    {\n        screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ];\n        lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i];\n    }\n  }\n\n  if (lastPos != -1)\n  {\n     int diff = dest - sourceBegin; // Scroll by this amount\n     lastPos += diff;\n     if ((lastPos < 0) || (lastPos >= (lines*columns)))\n        lastPos = -1;\n  }\n\n  // Adjust selection to follow scroll.\n  if (sel_begin != -1)\n  {\n     bool beginIsTL = (sel_begin == sel_TL);\n     int diff = dest - sourceBegin; // Scroll by this amount\n     int scr_TL=loc(0,hist->getLines());\n     int srca = sourceBegin+scr_TL; // Translate index from screen to global\n     int srce = sourceEnd+scr_TL; // Translate index from screen to global\n     int desta = srca+diff;\n     int deste = srce+diff;\n\n     if ((sel_TL >= srca) && (sel_TL <= srce))\n        sel_TL += diff;\n     else if ((sel_TL >= desta) && (sel_TL <= deste))\n        sel_BR = -1; // Clear selection (see below)\n\n     if ((sel_BR >= srca) && (sel_BR <= srce))\n        sel_BR += diff;\n     else if ((sel_BR >= desta) && (sel_BR <= deste))\n        sel_BR = -1; // Clear selection (see below)\n\n     if (sel_BR < 0)\n     {\n        clearSelection();\n     }\n     else\n     {\n        if (sel_TL < 0)\n           sel_TL = 0;\n     }\n\n     if (beginIsTL)\n        sel_begin = sel_TL;\n     else\n        sel_begin = sel_BR;\n  }\n}\n\nvoid Screen::clearToEndOfScreen()\n{\n  clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');\n}\n\nvoid Screen::clearToBeginOfScreen()\n{\n  clearImage(loc(0,0),loc(cuX,cuY),' ');\n}\n\nvoid Screen::clearEntireScreen()\n{\n  // Add entire screen to history\n  for (int i = 0; i < (lines-1); i++)\n  {\n    addHistLine(); scrollUp(0,1);\n  }\n\n  clearImage(loc(0,0),loc(columns-1,lines-1),' ');\n}\n\n/*! fill screen with 'E'\n    This is to aid screen alignment\n*/\n\nvoid Screen::helpAlign()\n{\n  clearImage(loc(0,0),loc(columns-1,lines-1),'E');\n}\n\nvoid Screen::clearToEndOfLine()\n{\n  clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');\n}\n\nvoid Screen::clearToBeginOfLine()\n{\n  clearImage(loc(0,cuY),loc(cuX,cuY),' ');\n}\n\nvoid Screen::clearEntireLine()\n{\n  clearImage(loc(0,cuY),loc(columns-1,cuY),' ');\n}\n\nvoid Screen::setRendition(int re)\n{\n  cu_re |= re;\n  effectiveRendition();\n}\n\nvoid Screen::resetRendition(int re)\n{\n  cu_re &= ~re;\n  effectiveRendition();\n}\n\nvoid Screen::setDefaultRendition()\n{\n  setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR);\n  setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR);\n  cu_re   = DEFAULT_RENDITION;\n  effectiveRendition();\n}\n\nvoid Screen::setForeColor(int space, int color)\n{\n  cu_fg = CharacterColor(space, color);\n\n  if ( cu_fg.isValid() )\n    effectiveRendition();\n  else\n    setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR);\n}\n\nvoid Screen::setBackColor(int space, int color)\n{\n  cu_bg = CharacterColor(space, color);\n\n  if ( cu_bg.isValid() )\n    effectiveRendition();\n  else\n    setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR);\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                            Marking & Selection                            */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\nvoid Screen::clearSelection()\n{\n  sel_BR = -1;\n  sel_TL = -1;\n  sel_begin = -1;\n}\n\nvoid Screen::getSelectionStart(int& column , int& line)\n{\n    if ( sel_TL != -1 )\n    {\n        column = sel_TL % columns;\n        line = sel_TL / columns;\n    }\n    else\n    {\n        column = cuX + getHistLines();\n        line = cuY + getHistLines();\n    }\n}\nvoid Screen::getSelectionEnd(int& column , int& line)\n{\n    if ( sel_BR != -1 )\n    {\n        column = sel_BR % columns;\n        line = sel_BR / columns;\n    }\n    else\n    {\n        column = cuX + getHistLines();\n        line = cuY + getHistLines();\n    }\n}\nvoid Screen::setSelectionStart(/*const ScreenCursor& viewCursor ,*/ const int x, const int y, const bool mode)\n{\n//  kDebug(1211) << \"setSelBeginXY(\" << x << \",\" << y << \")\";\n  sel_begin = loc(x,y); //+histCursor) ;\n\n  /* FIXME, HACK to correct for x too far to the right... */\n  if (x == columns) sel_begin--;\n\n  sel_BR = sel_begin;\n  sel_TL = sel_begin;\n  columnmode = mode;\n}\n\nvoid Screen::setSelectionEnd( const int x, const int y)\n{\n//  kDebug(1211) << \"setSelExtentXY(\" << x << \",\" << y << \")\";\n  if (sel_begin == -1) return;\n  int l =  loc(x,y); // + histCursor);\n\n  if (l < sel_begin)\n  {\n    sel_TL = l;\n    sel_BR = sel_begin;\n  }\n  else\n  {\n    /* FIXME, HACK to correct for x too far to the right... */\n    if (x == columns) l--;\n\n    sel_TL = sel_begin;\n    sel_BR = l;\n  }\n}\n\nbool Screen::isSelected( const int x,const int y) const\n{\n  if (columnmode) {\n    int sel_Left,sel_Right;\n    if ( sel_TL % columns < sel_BR % columns ) {\n      sel_Left = sel_TL; sel_Right = sel_BR;\n    } else {\n      sel_Left = sel_BR; sel_Right = sel_TL;\n    }\n    return ( x >= sel_Left % columns ) && ( x <= sel_Right % columns ) &&\n           ( y >= sel_TL / columns ) && ( y <= sel_BR / columns );\n            //( y+histCursor >= sel_TL / columns ) && ( y+histCursor <= sel_BR / columns );\n  }\n  else {\n  //int pos = loc(x,y+histCursor);\n  int pos = loc(x,y);\n  return ( pos >= sel_TL && pos <= sel_BR );\n  }\n}\n\nQString Screen::selectedText(bool preserveLineBreaks)\n{\n  QString result;\n  QTextStream stream(&result, QIODevice::ReadWrite);\n\n  PlainTextDecoder decoder;\n  decoder.begin(&stream);\n  writeSelectionToStream(&decoder , preserveLineBreaks);\n  decoder.end();\n\n  return result;\n}\n\nbool Screen::isSelectionValid() const\n{\n    return ( sel_TL >= 0 && sel_BR >= 0 );\n}\n\nvoid Screen::writeSelectionToStream(TerminalCharacterDecoder* decoder ,\n                                    bool preserveLineBreaks)\n{\n    // do nothing if selection is invalid\n    if ( !isSelectionValid() )\n        return;\n\n\tint top = sel_TL / columns;\t\n\tint left = sel_TL % columns;\n\n\tint bottom = sel_BR / columns;\n\tint right = sel_BR % columns;\n\n    Q_ASSERT( top >= 0 && left >= 0 && bottom >= 0 && right >= 0 );\n\n    //kDebug() << \"sel_TL = \" << sel_TL;\n    //kDebug() << \"columns = \" << columns;\n\n\tfor (int y=top;y<=bottom;y++)\n\t{\n\t\t\tint start = 0;\n\t\t\tif ( y == top || columnmode ) start = left;\n\t\t\n\t\t\tint count = -1;\n\t\t\tif ( y == bottom || columnmode ) count = right - start + 1;\n\n            const bool appendNewLine = ( y != bottom );\n\t\t\tcopyLineToStream( y,\n                              start,\n                              count,\n                              decoder,\n                              appendNewLine,\n                              preserveLineBreaks );\n\t}\t\n}\n\n\nvoid Screen::copyLineToStream(int line ,\n                              int start,\n                              int count,\n                              TerminalCharacterDecoder* decoder,\n                              bool appendNewLine,\n                              bool preserveLineBreaks)\n{\n\t\t//buffer to hold characters for decoding\n\t\t//the buffer is static to avoid initialising every\n        //element on each call to copyLineToStream\n\t\t//(which is unnecessary since all elements will be overwritten anyway)\n\t\tstatic const int MAX_CHARS = 1024;\n\t\tstatic Character characterBuffer[MAX_CHARS];\n\t\t\n\t\tassert( count < MAX_CHARS );\n\n        LineProperty currentLineProperties = 0;\n\n\t\t//determine if the line is in the history buffer or the screen image\n\t\tif (line < hist->getLines())\n\t\t{\n            const int lineLength = hist->getLineLen(line);\n\n            // ensure that start position is before end of line\n            start = qMin(start,qMax(0,lineLength-1));\n\n\t\t\t//retrieve line from history buffer\n\t\t\tif (count == -1)\n            {\n\t\t\t\t\tcount = lineLength-start;\n            }\n\t\t\telse\n            {\n\t\t\t\t\tcount = qMin(start+count,lineLength)-start;\n            }\n\n            // safety checks\n            assert( start >= 0 );\n            assert( count >= 0 );\n            assert( (start+count) <= hist->getLineLen(line) );\n\n\t\t\thist->getCells(line,start,count,characterBuffer);\n\n            if ( hist->isWrappedLine(line) )\n                currentLineProperties |= LINE_WRAPPED;\n\t\t}\n\t\telse\n\t\t{\n            if ( count == -1 )\n              count = columns - start;\n\n            assert( count >= 0 );\n\n            const int screenLine = line-hist->getLines();\n\n            Character* data = screenLines[screenLine].data();\n            int length = screenLines[screenLine].count();\n\n            //retrieve line from screen image\n            for (int i=start; i < qMin(start+count,length); i++)\n            {\n                characterBuffer[i-start] = data[i];\n            }\n\n            // count cannot be any greater than length\n            count = qBound (0, count, qMax (0, length-start));\n\n            Q_ASSERT( screenLine < lineProperties.count() );\n            currentLineProperties |= lineProperties[screenLine];\n\t\t}\n\n\t\t//do not decode trailing whitespace characters\n\t\tfor (int i=count-1 ; i >= 0; i--)\n\t\t\t\tif (QChar(characterBuffer[i].character).isSpace())\n\t\t\t\t\t\tcount--;\n\t\t\t\telse\n\t\t\t\t\t\tbreak;\n\n        // add new line character at end\n        const bool omitLineBreak = (currentLineProperties & LINE_WRAPPED) ||\n                                   !preserveLineBreaks;\n\n        if ( !omitLineBreak && appendNewLine && (count+1 < MAX_CHARS) )\n        {\n            characterBuffer[count] = '\\n';\n            count++;\n        }\n\n\t\t//decode line and write to text stream\t\n\t\tdecoder->decodeLine( (Character*) characterBuffer ,\n                             count, currentLineProperties );\n}\n\n// Method below has been removed because of its reliance on 'histCursor'\n// and I want to restrict the methods which have knowledge of the scroll position\n// to just those which deal with selection and supplying final screen images.\n//\n/*void Screen::writeToStream(QTextStream* stream , TerminalCharacterDecoder* decoder) {\n  sel_begin = 0;\n  sel_BR = sel_begin;\n  sel_TL = sel_begin;\n  setSelectionEnd(columns-1,lines-1+hist->getLines()-histCursor);\n\n  writeSelectionToStream(stream,decoder);\n\n  clearSelection();\n}*/\n\nvoid Screen::writeToStream(TerminalCharacterDecoder* decoder, int from, int to)\n{\n\tsel_begin = loc(0,from);\n\tsel_TL = sel_begin;\n\tsel_BR = loc(columns-1,to);\n\twriteSelectionToStream(decoder);\n\tclearSelection();\n}\n\nQString Screen::getHistoryLine(int no)\n{\n  sel_begin = loc(0,no);\n  sel_TL = sel_begin;\n  sel_BR = loc(columns-1,no);\n  return selectedText(false);\n}\n\nvoid Screen::addHistLine()\n{\n  // add line to history buffer\n  // we have to take care about scrolling, too...\n\n  if (hasScroll())\n  {\n    int oldHistLines = hist->getLines();\n\n    hist->addCellsVector(screenLines[0]);\n    hist->addLine( lineProperties[0] & LINE_WRAPPED );\n\n    int newHistLines = hist->getLines();\n\n    bool beginIsTL = (sel_begin == sel_TL);\n\n    // If the history is full, increment the count\n    // of dropped lines\n    if ( newHistLines == oldHistLines )\n        _droppedLines++;\n\n    // Adjust selection for the new point of reference\n    if (newHistLines > oldHistLines)\n    {\n       if (sel_begin != -1)\n       {\n          sel_TL += columns;\n          sel_BR += columns;\n       }\n    }\n\n    if (sel_begin != -1)\n    {\n       // Scroll selection in history up\n       int top_BR = loc(0, 1+newHistLines);\n\n       if (sel_TL < top_BR)\n          sel_TL -= columns;\n\n       if (sel_BR < top_BR)\n          sel_BR -= columns;\n\n       if (sel_BR < 0)\n       {\n          clearSelection();\n       }\n       else\n       {\n          if (sel_TL < 0)\n             sel_TL = 0;\n       }\n\n       if (beginIsTL)\n          sel_begin = sel_TL;\n       else\n          sel_begin = sel_BR;\n    }\n  }\n\n}\n\nint Screen::getHistLines()\n{\n  return hist->getLines();\n}\n\nvoid Screen::setScroll(const HistoryType& t , bool copyPreviousScroll)\n{\n  clearSelection();\n\n  if ( copyPreviousScroll )\n    hist = t.scroll(hist);\n  else\n  {\n      HistoryScroll* oldScroll = hist;\n      hist = t.scroll(nullptr);\n      delete oldScroll;\n  }\n}\n\nbool Screen::hasScroll()\n{\n  return hist->hasScroll();\n}\n\nconst HistoryType& Screen::getScroll()\n{\n  return hist->getType();\n}\n\nvoid Screen::setLineProperty(LineProperty property , bool enable)\n{\n\tif ( enable )\n\t{\n\t\tlineProperties[cuY] = (LineProperty)(lineProperties[cuY] | property);\n\t}\n\telse\n\t{\n\t\tlineProperties[cuY] = (LineProperty)(lineProperties[cuY] & ~property);\n\t}\n}\nvoid Screen::fillWithDefaultChar(Character* dest, int count)\n{\n\tfor (int i=0;i<count;i++)\n\t\tdest[i] = defaultChar;\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/Screen.h",
    "content": "/*\n    This file is part of Konsole, KDE's terminal.\n\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef SCREEN_H\n#define SCREEN_H\n\n// Qt\n#include <QRect>\n#include <QTextStream>\n#include <QVarLengthArray>\n\n// Konsole\n#include \"unix/Character.h\"\n#include \"unix/History.h\"\n\n#define MODE_Origin    0\n#define MODE_Wrap      1\n#define MODE_Insert    2\n#define MODE_Screen    3\n#define MODE_Cursor    4\n#define MODE_NewLine   5\n#define MODES_SCREEN   6\n\nstruct ScreenParm\n{\n  int mode[MODES_SCREEN];\n};\n\nclass TerminalCharacterDecoder;\n\n/**\n    @brief An image of characters with associated attributes.\n\n    The terminal emulation ( Emulation ) receives a serial stream of\n    characters from the program currently running in the terminal.\n    From this stream it creates an image of characters which is ultimately\n    rendered by the display widget ( TerminalDisplay ).  Some types of emulation\n    may have more than one screen image.\n\n    getImage() is used to retrieve the currently visible image\n    which is then used by the display widget to draw the output from the\n    terminal.\n\n    The number of lines of output history which are kept in addition to the current\n    screen image depends on the history scroll being used to store the output.\n    The scroll is specified using setScroll()\n    The output history can be retrieved using writeToStream()\n\n    The screen image has a selection associated with it, specified using\n    setSelectionStart() and setSelectionEnd().  The selected text can be retrieved\n    using selectedText().  When getImage() is used to retrieve the the visible image,\n    characters which are part of the selection have their colours inverted.\n*/\nclass Screen\n{\npublic:\n    /** Construct a new screen image of size @p lines by @p columns. */\n    Screen(int lines, int columns);\n    ~Screen();\n\n    // VT100/2 Operations\n    // Cursor Movement\n\n    /** Move the cursor up by @p n lines. */\n    void cursorUp    (int n);\n    /** Move the cursor down by @p n lines. */\n    void cursorDown  (int n);\n    /** Move the cursor to the left by @p n columns. */\n    void cursorLeft  (int n);\n    /** Move the cursor to the right by @p n columns. */\n    void cursorRight (int n);\n    /** Position the cursor on line @p y. */\n    void setCursorY  (int y);\n    /** Position the cursor at column @p x. */\n    void setCursorX  (int x);\n    /** Position the cursor at line @p y, column @p x. */\n    void setCursorYX (int y, int x);\n    /**\n     * Sets the margins for scrolling the screen.\n     *\n     * @param topLine The top line of the new scrolling margin.\n     * @param bottomLine The bottom line of the new scrolling margin.\n     */\n    void setMargins  (int topLine , int bottomLine);\n    /** Returns the top line of the scrolling region. */\n    int topMargin() const;\n    /** Returns the bottom line of the scrolling region. */\n    int bottomMargin() const;\n\n    /**\n     * Resets the scrolling margins back to the top and bottom lines\n     * of the screen.\n     */\n    void setDefaultMargins();\n\n    /**\n     * Moves the cursor down one line, if the MODE_NewLine mode\n     * flag is enabled then the cursor is returned to the leftmost\n     * column first.\n     *\n     * Equivalent to NextLine() if the MODE_NewLine flag is set\n     * or index() otherwise.\n     */\n    void NewLine     ();\n    /**\n     * Moves the cursor down one line and positions it at the beginning\n     * of the line.\n     */\n    void NextLine    ();\n\n    /**\n     * Move the cursor down one line.  If the cursor is on the bottom\n     * line of the scrolling region (as returned by bottomMargin()) the\n     * scrolling region is scrolled up by one line instead.\n     */\n    void index       ();\n    /**\n     * Move the cursor up one line.  If the cursor is on the top line\n     * of the scrolling region (as returned by topMargin()) the scrolling\n     * region is scrolled down by one line instead.\n     */\n    void reverseIndex();\n\n    /**\n     * Scroll the scrolling region of the screen up by @p n lines.\n     * The scrolling region is initially the whole screen, but can be changed\n     * using setMargins()\n     */\n    void scrollUp(int n);\n    /**\n     * Scroll the scrolling region of the screen down by @p n lines.\n     * The scrolling region is initially the whole screen, but can be changed\n     * using setMargins()\n     */\n    void scrollDown(int n);\n\n    /**\n     * Moves the cursor to the beginning of the current line.\n     * Equivalent to setCursorX(0)\n     */\n    void Return      ();\n    /**\n     * Moves the cursor one column to the left and erases the character\n     * at the new cursor position.\n     */\n    void BackSpace   ();\n    /**\n     * Moves the cursor @p n tab-stops to the right.\n     */\n    void Tabulate    (int n = 1);\n    /**\n     * Moves the cursor @p n tab-stops to the left.\n     */\n    void backTabulate(int n);\n\n    // Editing\n\n    /**\n     * Erase @p n characters beginning from the current cursor position.\n     * This is equivalent to over-writing @p n characters starting with the current\n     * cursor position with spaces.\n     * If @p n is 0 then one character is erased.\n     */\n    void eraseChars  (int n);\n    /**\n     * Delete @p n characters beginning from the current cursor position.\n     * If @p n is 0 then one character is deleted.\n     */\n    void deleteChars (int n);\n    /**\n     * Insert @p n blank characters beginning from the current cursor position.\n     * The position of the cursor is not altered.\n     * If @p n is 0 then one character is inserted.\n     */\n    void insertChars (int n);\n    /**\n     * Removes @p n lines beginning from the current cursor position.\n     * The position of the cursor is not altered.\n     * If @p n is 0 then one line is removed.\n     */\n    void deleteLines (int n);\n    /**\n     * Inserts @p lines beginning from the current cursor position.\n     * The position of the cursor is not altered.\n     * If @p n is 0 then one line is inserted.\n     */\n    void insertLines (int n);\n    /** Clears all the tab stops. */\n    void clearTabStops();\n    /**  Sets or removes a tab stop at the cursor's current column. */\n    void changeTabStop(bool set);\n\n    /** Resets (clears) the specified screen @p mode. */\n    void resetMode   (int mode);\n    /** Sets (enables) the specified screen @p mode. */\n    void setMode     (int mode);\n    /**\n     * Saves the state of the specified screen @p mode.  It can be restored\n     * using restoreMode()\n     */\n    void saveMode    (int mode);\n    /** Restores the state of a screen @p mode saved by calling saveMode() */\n    void restoreMode (int mode);\n    /** Returns whether the specified screen @p mode is enabled or not .*/\n    bool getMode     (int mode) const;\n\n    /**\n     * Saves the current position and appearence (text color and style) of the cursor.\n     * It can be restored by calling restoreCursor()\n     */\n    void saveCursor  ();\n    /** Restores the position and appearence of the cursor.  See saveCursor() */\n    void restoreCursor();\n\n    /** Clear the whole screen, moving the current screen contents into the history first. */\n    void clearEntireScreen();\n    /**\n     * Clear the area of the screen from the current cursor position to the end of\n     * the screen.\n     */\n    void clearToEndOfScreen();\n    /**\n     * Clear the area of the screen from the current cursor position to the start\n     * of the screen.\n     */\n    void clearToBeginOfScreen();\n    /** Clears the whole of the line on which the cursor is currently positioned. */\n    void clearEntireLine();\n    /** Clears from the current cursor position to the end of the line. */\n    void clearToEndOfLine();\n    /** Clears from the current cursor position to the beginning of the line. */\n    void clearToBeginOfLine();\n\n    /** Fills the entire screen with the letter 'E' */\n    void helpAlign   ();\n\n    /**\n     * Enables the given @p rendition flag.  Rendition flags control the appearence\n     * of characters on the screen.\n     *\n     * @see Character::rendition\n     */\n    void setRendition  (int rendition);\n    /**\n     * Disables the given @p rendition flag.  Rendition flags control the appearence\n     * of characters on the screen.\n     *\n     * @see Character::rendition\n     */\n    void resetRendition(int rendition);\n\n    /**\n     * Sets the cursor's foreground color.\n     * @param space The color space used by the @p color argument\n     * @param color The new foreground color.  The meaning of this depends on\n     * the color @p space used.\n     *\n     * @see CharacterColor\n     */\n    void setForeColor  (int space, int color);\n    /**\n     * Sets the cursor's background color.\n     * @param space The color space used by the @p color argumnet.\n     * @param color The new background color.  The meaning of this depends on\n     * the color @p space used.\n     *\n     * @see CharacterColor\n     */\n    void setBackColor  (int space, int color);\n    /**\n     * Resets the cursor's color back to the default and sets the\n     * character's rendition flags back to the default settings.\n     */\n    void setDefaultRendition();\n\n    /** Returns the column which the cursor is positioned at. */\n    int  getCursorX() const;\n    /** Returns the line which the cursor is positioned on. */\n    int  getCursorY() const;\n\n\t/** TODO Document me */\n\tvoid clear();\n    /**\n     * Sets the position of the cursor to the 'home' position at the top-left\n     * corner of the screen (0,0)\n     */\n    void home();\n    /**\n     * Resets the state of the screen.  This resets the various screen modes\n     * back to their default states.  The cursor style and colors are reset\n     * (as if setDefaultRendition() had been called)\n     *\n     * <ul>\n     * <li>Line wrapping is enabled.</li>\n     * <li>Origin mode is disabled.</li>\n     * <li>Insert mode is disabled.</li>\n     * <li>Cursor mode is enabled.  TODO Document me</li>\n     * <li>Screen mode is disabled. TODO Document me</li>\n     * <li>New line mode is disabled.  TODO Document me</li>\n     * </ul>\n     *\n     * If @p clearScreen is true then the screen contents are erased entirely,\n     * otherwise they are unaltered.\n     */\n    void reset(bool clearScreen = true);\n\n    /**\n     * Displays a new character at the current cursor position.\n     *\n     * If the cursor is currently positioned at the right-edge of the screen and\n     * line wrapping is enabled then the character is added at the start of a new\n     * line below the current one.\n     *\n     * If the MODE_Insert screen mode is currently enabled then the character\n     * is inserted at the current cursor position, otherwise it will replace the\n     * character already at the current cursor position.\n     */\n    void ShowCharacter(unsigned short c);\n\n    // Do composition with last shown character FIXME: Not implemented yet for KDE 4\n    void compose(const QString& compose);\n\n    /**\n     * Resizes the image to a new fixed size of @p new_lines by @p new_columns.\n     * In the case that @p new_columns is smaller than the current number of columns,\n     * existing lines are not truncated.  This prevents characters from being lost\n     * if the terminal display is resized smaller and then larger again.\n     *\n     * (note that in versions of Konsole prior to KDE 4, existing lines were\n     *  truncated when making the screen image smaller)\n     */\n    void resizeImage(int new_lines, int new_columns);\n\n    /**\n     * Returns the current screen image.\n     * The result is an array of Characters of size [getLines()][getColumns()] which\n     * must be freed by the caller after use.\n     *\n     * @param dest Buffer to copy the characters into\n     * @param size Size of @p dest in Characters\n     * @param startLine Index of first line to copy\n     * @param endLine Index of last line to copy\n     */\n    void getImage( Character* dest , int size , int startLine , int endLine ) const;\n\n    /**\n     * Returns the additional attributes associated with lines in the image.\n     * The most important attribute is LINE_WRAPPED which specifies that the\n     * line is wrapped,\n     * other attributes control the size of characters in the line.\n     */\n    QVector<LineProperty> getLineProperties( int startLine , int endLine ) const;\n\t\n\n    /** Return the number of lines. */\n    int  getLines()   { return lines; }\n    /** Return the number of columns. */\n    int  getColumns() { return columns; }\n    /** Return the number of lines in the history buffer. */\n    int  getHistLines ();\n    /**\n     * Sets the type of storage used to keep lines in the history.\n     * If @p copyPreviousScroll is true then the contents of the previous\n     * history buffer are copied into the new scroll.\n     */\n    void setScroll(const HistoryType& , bool copyPreviousScroll = true);\n    /** Returns the type of storage used to keep lines in the history. */\n    const HistoryType& getScroll();\n    /**\n     * Returns true if this screen keeps lines that are scrolled off the screen\n     * in a history buffer.\n     */\n    bool hasScroll();\n\n    /**\n     * Sets the start of the selection.\n     *\n     * @param column The column index of the first character in the selection.\n     * @param line The line index of the first character in the selection.\n     * @param columnmode True if the selection is in column mode.\n     */\n    void setSelectionStart(const int column, const int line, const bool columnmode);\n\n    /**\n     * Sets the end of the current selection.\n     *\n     * @param column The column index of the last character in the selection.\n     * @param line The line index of the last character in the selection.\n     */\n    void setSelectionEnd(const int column, const int line);\n\n    /**\n     * Retrieves the start of the selection or the cursor position if there\n     * is no selection.\n     */\n    void getSelectionStart(int& column , int& line);\n\n    /**\n     * Retrieves the end of the selection or the cursor position if there\n     * is no selection.\n     */\n    void getSelectionEnd(int& column , int& line);\n\n    /** Clears the current selection */\n    void clearSelection();\n\n    void setBusySelecting(bool busy) { sel_busy = busy; }\n\n    /**\n \t * \tReturns true if the character at (@p column, @p line) is part of the\n \t *  current selection.\n \t */\n    bool isSelected(const int column,const int line) const;\n\n    /**\n     * Convenience method.  Returns the currently selected text.\n     * @param preserveLineBreaks Specifies whether new line characters should\n     * be inserted into the returned text at the end of each terminal line.\n     */\n    QString selectedText(bool preserveLineBreaks);\n\t\n\t/**\n\t * Copies part of the output to a stream.\n\t *\n\t * @param decoder A decoder which coverts terminal characters into text\n\t * @param from The first line in the history to retrieve\n\t * @param to The last line in the history to retrieve\n\t */\n\tvoid writeToStream(TerminalCharacterDecoder* decoder, int from, int to);\n\n    /**\n     * Sets the selection to line @p no in the history and returns\n     * the text of that line from the history buffer.\n     */\n    QString getHistoryLine(int no);\n\n\t/**\n\t * Copies the selected characters, set using @see setSelBeginXY and @see setSelExtentXY\n\t * into a stream.\n\t *\n\t * @param decoder A decoder which converts terminal characters into text.\n\t * PlainTextDecoder is the most commonly used decoder which coverts characters\n\t * into plain text with no formatting.\n     * @param preserveLineBreaks Specifies whether new line characters should\n     * be inserted into the returned text at the end of each terminal line.\n\t */\n\tvoid writeSelectionToStream(TerminalCharacterDecoder* decoder , bool\n                                preserveLineBreaks = true);\n\n    /** TODO Document me */\n    void checkSelection(int from, int to);\n\n\t/**\n\t * Sets or clears an attribute of the current line.\n\t *\n\t * @param property The attribute to set or clear\n\t * Possible properties are:\n\t * LINE_WRAPPED:\t Specifies that the line is wrapped.\n\t * LINE_DOUBLEWIDTH: Specifies that the characters in the current line should be double the normal width.\n\t * LINE_DOUBLEHEIGHT:Specifies that the characters in the current line should be double the normal height.\n     *                   Double-height lines are formed of two lines containing the same characters,\n     *                   with both having the LINE_DOUBLEHEIGHT attribute.  This allows other parts of the\n     *                   code to work on the assumption that all lines are the same height.\n\t *\n\t * @param enable true to apply the attribute to the current line or false to remove it\n\t */\n\tvoid setLineProperty(LineProperty property , bool enable);\n\n\n    /**\n     * Returns the number of lines that the image has been scrolled up or down by,\n     * since the last call to resetScrolledLines().\n     *\n     * a positive return value indicates that the image has been scrolled up,\n     * a negative return value indicates that the image has been scrolled down.\n     */\n    int scrolledLines() const;\n\n    /**\n     * Returns the region of the image which was last scrolled.\n     *\n     * This is the area of the image from the top margin to the\n     * bottom margin when the last scroll occurred.\n     */\n    QRect lastScrolledRegion() const;\n\n    /**\n     * Resets the count of the number of lines that the image has been scrolled up or down by,\n     * see scrolledLines()\n     */\n    void resetScrolledLines();\n\n    /**\n     * Returns the number of lines of output which have been\n     * dropped from the history since the last call\n     * to resetDroppedLines()\n     *\n     * If the history is not unlimited then it will drop\n     * the oldest lines of output if new lines are added when\n     * it is full.\n     */\n    int droppedLines() const;\n\n    /**\n     * Resets the count of the number of lines dropped from\n     * the history.\n     */\n    void resetDroppedLines();\n\n\t/**\n \t * Fills the buffer @p dest with @p count instances of the default (ie. blank)\n \t * Character style.\n \t */\n\tstatic void fillWithDefaultChar(Character* dest, int count);\n\nprivate:\n\n\t//copies a line of text from the screen or history into a stream using a\n\t//specified character decoder\n\t//line - the line number to copy, from 0 (the earliest line in the history) up to\n\t//\t\t hist->getLines() + lines - 1\n\t//start - the first column on the line to copy\n\t//count - the number of characters on the line to copy\n\t//decoder - a decoder which coverts terminal characters (an Character array) into text\n    //appendNewLine - if true a new line character (\\n) is appended to the end of the line\n\tvoid copyLineToStream(int line,\n                          int start,\n                          int count,\n                          TerminalCharacterDecoder* decoder,\n                          bool appendNewLine,\n                          bool preserveLineBreaks);\n\t\n    //fills a section of the screen image with the character 'c'\n    //the parameters are specified as offsets from the start of the screen image.\n    //the loc(x,y) macro can be used to generate these values from a column,line pair.\n    void clearImage(int loca, int loce, char c);\n\n    //move screen image between 'sourceBegin' and 'sourceEnd' to 'dest'.\n    //the parameters are specified as offsets from the start of the screen image.\n    //the loc(x,y) macro can be used to generate these values from a column,line pair.\n    void moveImage(int dest, int sourceBegin, int sourceEnd);\n\n    void scrollUp(int from, int i);\n    void scrollDown(int from, int i);\n\n    void addHistLine();\n\n    void initTabStops();\n\n    void effectiveRendition();\n    void reverseRendition(Character& p) const;\n\n    bool isSelectionValid() const;\n\n\t// copies 'count' lines from the screen buffer into 'dest',\n\t// starting from 'startLine', where 0 is the first line in the screen buffer\n\tvoid copyFromScreen(Character* dest, int startLine, int count) const;\n\t// copies 'count' lines from the history buffer into 'dest',\n\t// starting from 'startLine', where 0 is the first line in the history\n\tvoid copyFromHistory(Character* dest, int startLine, int count) const;\n\n\n    // screen image ----------------\n    int lines;\n    int columns;\n\n    typedef QVector<Character> ImageLine;      // [0..columns]\n    ImageLine*          screenLines;    // [lines]\n\n    int _scrolledLines;\n    QRect _lastScrolledRegion;\n\n    int _droppedLines;\n\n    QVarLengthArray<LineProperty,64> lineProperties;\n\t\n    // history buffer ---------------\n    HistoryScroll *hist;\n\n    // cursor location\n    int cuX;\n    int cuY;\n\n    // cursor color and rendition info\n    CharacterColor cu_fg;      // foreground\n    CharacterColor cu_bg;      // background\n    quint8 cu_re;      // rendition\n\n    // margins ----------------\n    int tmargin;      // top margin\n    int bmargin;      // bottom margin\n\n    // states ----------------\n    ScreenParm currParm;\n\n    // ----------------------------\n\n    bool* tabstops;\n\n    // selection -------------------\n    int sel_begin; // The first location selected.\n    int sel_TL;    // TopLeft Location.\n    int sel_BR;    // Bottom Right Location.\n    bool sel_busy; // Busy making a selection.\n    bool columnmode;  // Column selection mode\n\n    // effective colors and rendition ------------\n    CharacterColor ef_fg;      // These are derived from\n    CharacterColor ef_bg;      // the cu_* variables above\n    quint8 ef_re;      // to speed up operation\n\n    //\n    // save cursor, rendition & states ------------\n    //\n\n    // cursor location\n    int sa_cuX;\n    int sa_cuY;\n\n    // rendition info\n    quint8 sa_cu_re;\n    CharacterColor sa_cu_fg;\n    CharacterColor sa_cu_bg;\n\n    // last position where we added a character\n    int lastPos;\n\n    // modes\n    ScreenParm saveParm;\n\n    static Character defaultChar;\n};\n\n#endif // SCREEN_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/ScreenWindow.cpp",
    "content": "/*\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n// Own\n#include \"unix/ScreenWindow.h\"\n\n// Qt\n#include <QtCore>\n\n// Konsole\n#include \"unix/Screen.h\"\n\nScreenWindow::ScreenWindow(QObject* parent)\n    : QObject(parent)\n\t, _windowBuffer(nullptr)\n\t, _windowBufferSize(0)\n\t, _bufferNeedsUpdate(true)\n\t, _windowLines(1)\n    , _currentLine(0)\n    , _trackOutput(true)\n    , _scrollCount(0)\n{\n}\n\nScreenWindow::~ScreenWindow()\n{\n\tdelete[] _windowBuffer;\n}\nvoid ScreenWindow::setScreen(Screen* screen)\n{\n    Q_ASSERT( screen );\n\n    _screen = screen;\n}\n\nScreen* ScreenWindow::screen() const\n{\n    return _screen;\n}\n\nCharacter* ScreenWindow::getImage()\n{\n\t// reallocate internal buffer if the window size has changed\n\tint size = windowLines() * windowColumns();\n\tif (_windowBuffer == nullptr || _windowBufferSize != size)\n\t{\n\t\tdelete[] _windowBuffer;\n\t\t_windowBufferSize = size;\n\t\t_windowBuffer = new Character[size];\n\t\t_bufferNeedsUpdate = true;\n\t}\n\n\t if (!_bufferNeedsUpdate)\n\t\treturn _windowBuffer;\n\n\t_screen->getImage(_windowBuffer,size,\n\t\t\t\t\t  currentLine(),endWindowLine());\n\n\t// this window may look beyond the end of the screen, in which\n\t// case there will be an unused area which needs to be filled\n\t// with blank characters\n\tfillUnusedArea();\n\n\t_bufferNeedsUpdate = false;\n\treturn _windowBuffer;\n}\n\nvoid ScreenWindow::fillUnusedArea()\n{\n\tint screenEndLine = _screen->getHistLines() + _screen->getLines() - 1;\n\tint windowEndLine = currentLine() + windowLines() - 1;\n\n\tint unusedLines = windowEndLine - screenEndLine;\n\tint charsToFill = unusedLines * windowColumns();\n\n\tScreen::fillWithDefaultChar(_windowBuffer + _windowBufferSize - charsToFill,charsToFill);\n}\n\n// return the index of the line at the end of this window, or if this window\n// goes beyond the end of the screen, the index of the line at the end\n// of the screen.\n//\n// when passing a line number to a Screen method, the line number should\n// never be more than endWindowLine()\n//\nint ScreenWindow::endWindowLine() const\n{\n\treturn qMin(currentLine() + windowLines() - 1,\n\t\t\t\tlineCount() - 1);\n}\nQVector<LineProperty> ScreenWindow::getLineProperties()\n{\n    QVector<LineProperty> result = _screen->getLineProperties(currentLine(),endWindowLine());\n\t\n\tif (result.count() != windowLines())\n\t\tresult.resize(windowLines());\n\n\treturn result;\n}\n\nQString ScreenWindow::selectedText( bool preserveLineBreaks ) const\n{\n    return _screen->selectedText( preserveLineBreaks );\n}\n\nvoid ScreenWindow::getSelectionStart( int& column , int& line )\n{\n    _screen->getSelectionStart(column,line);\n    line -= currentLine();\n}\nvoid ScreenWindow::getSelectionEnd( int& column , int& line )\n{\n    _screen->getSelectionEnd(column,line);\n    line -= currentLine();\n}\nvoid ScreenWindow::setSelectionStart( int column , int line , bool columnMode )\n{\n    _screen->setSelectionStart( column , qMin(line + currentLine(),endWindowLine())  , columnMode);\n\t\n\t_bufferNeedsUpdate = true;\n    Q_EMIT selectionChanged();\n}\n\nvoid ScreenWindow::setSelectionEnd( int column , int line )\n{\n    _screen->setSelectionEnd( column , qMin(line + currentLine(),endWindowLine()) );\n\n\t_bufferNeedsUpdate = true;\n    Q_EMIT selectionChanged();\n}\n\nbool ScreenWindow::isSelected( int column , int line )\n{\n    return _screen->isSelected( column , qMin(line + currentLine(),endWindowLine()) );\n}\n\nvoid ScreenWindow::clearSelection()\n{\n    _screen->clearSelection();\n\n    Q_EMIT selectionChanged();\n}\n\nvoid ScreenWindow::setWindowLines(int lines)\n{\n\tQ_ASSERT(lines > 0);\n\t_windowLines = lines;\n}\nint ScreenWindow::windowLines() const\n{\n\treturn _windowLines;\t\t\n}\n\nint ScreenWindow::windowColumns() const\n{\n    return _screen->getColumns();\n}\n\nint ScreenWindow::lineCount() const\n{\n    return _screen->getHistLines() + _screen->getLines();\n}\n\nint ScreenWindow::columnCount() const\n{\n    return _screen->getColumns();\n}\n\nQPoint ScreenWindow::cursorPosition() const\n{\n    QPoint position;\n\n    position.setX( _screen->getCursorX() );\n    position.setY( _screen->getCursorY() );\n\n    return position;\n}\n\nint ScreenWindow::currentLine() const\n{\n    return qBound(0,_currentLine,lineCount()-windowLines());\n}\n\nvoid ScreenWindow::scrollBy( RelativeScrollMode mode , int amount )\n{\n    if ( mode == ScrollLines )\n    {\n        scrollTo( currentLine() + amount );\n    }\n    else if ( mode == ScrollPages )\n    {\n        scrollTo( currentLine() + amount * ( windowLines() / 2 ) );\n    }\n}\n\nbool ScreenWindow::atEndOfOutput() const\n{\n    return currentLine() == (lineCount()-windowLines());\n}\n\nvoid ScreenWindow::scrollTo( int line )\n{\n\tint maxCurrentLineNumber = lineCount() - windowLines();\n\tline = qBound(0,line,maxCurrentLineNumber);\n\n    const int delta = line - _currentLine;\n    _currentLine = line;\n\n    // keep track of number of lines scrolled by,\n    // this can be reset by calling resetScrollCount()\n    _scrollCount += delta;\n\n    _bufferNeedsUpdate = true;\n\n    Q_EMIT scrolled(_currentLine);\n}\n\nvoid ScreenWindow::setTrackOutput(bool trackOutput)\n{\n    _trackOutput = trackOutput;\n}\n\nbool ScreenWindow::trackOutput() const\n{\n    return _trackOutput;\n}\n\nint ScreenWindow::scrollCount() const\n{\n    return _scrollCount;\n}\n\nvoid ScreenWindow::resetScrollCount()\n{\n    _scrollCount = 0;\n}\n\nQRect ScreenWindow::scrollRegion() const\n{\n\tbool equalToScreenSize = windowLines() == _screen->getLines();\n\n\tif ( atEndOfOutput() && equalToScreenSize )\n    \treturn _screen->lastScrolledRegion();\n\telse\n\t\treturn QRect(0,0,windowColumns(),windowLines());\n}\n\nvoid ScreenWindow::notifyOutputChanged()\n{\n    // move window to the bottom of the screen and update scroll count\n    // if this window is currently tracking the bottom of the screen\n    if ( _trackOutput )\n    {\n        _scrollCount -= _screen->scrolledLines();\n        _currentLine = qMax(0,_screen->getHistLines() - (windowLines()-_screen->getLines()));\n    }\n    else\n    {\n        // if the history is not unlimited then it may\n        // have run out of space and dropped the oldest\n        // lines of output - in this case the screen\n        // window's current line number will need to\n        // be adjusted - otherwise the output will scroll\n        _currentLine = qMax(0,_currentLine -\n                              _screen->droppedLines());\n\n        // ensure that the screen window's current position does\n        // not go beyond the bottom of the screen\n        _currentLine = qMin( _currentLine , _screen->getHistLines() );\n    }\n\n\t_bufferNeedsUpdate = true;\n\n    Q_EMIT outputChanged();\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/ScreenWindow.h",
    "content": "/*\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef SCREENWINDOW_H\n#define SCREENWINDOW_H\n\n// Qt\n#include <QObject>\n#include <QPoint>\n#include <QRect>\n\n// Konsole\n#include \"unix/Character.h\"\n\nclass Screen;\n\n/**\n * Provides a window onto a section of a terminal screen.\n * This window can then be rendered by a terminal display widget ( TerminalDisplay ).\n *\n * To use the screen window, create a new ScreenWindow() instance and associated it with\n * a terminal screen using setScreen().\n * Use the scrollTo() method to scroll the window up and down on the screen.\n * Call the getImage() method to retrieve the character image which is currently visible in the window.\n *\n * setTrackOutput() controls whether the window moves to the bottom of the associated screen when new\n * lines are added to it.\n *\n * Whenever the output from the underlying screen is changed, the notifyOutputChanged() slot should\n * be called.  This in turn will update the window's position and emit the outputChanged() signal\n * if necessary.\n */\nclass ScreenWindow : public QObject\n{\nQ_OBJECT\n\npublic:\n    /**\n     * Constructs a new screen window with the given parent.\n     * A screen must be specified by calling setScreen() before calling getImage() or getLineProperties().\n     *\n     * You should not call this constructor directly, instead use the Emulation::createWindow() method\n     * to create a window on the emulation which you wish to view.  This allows the emulation\n     * to notify the window when the associated screen has changed and synchronize selection updates\n     * between all views on a session.\n     */\n    ScreenWindow(QObject* parent = nullptr);\n\tvirtual ~ScreenWindow();\n\n    /** Sets the screen which this window looks onto */\n    void setScreen(Screen* screen);\n    /** Returns the screen which this window looks onto */\n    Screen* screen() const;\n\n    /**\n     * Returns the image of characters which are currently visible through this window\n     * onto the screen.\n     *\n     * The buffer is managed by the ScreenWindow instance and does not need to be\n     * deleted by the caller.\n     */\n    Character* getImage();\n\n    /**\n     * Returns the line attributes associated with the lines of characters which\n     * are currently visible through this window\n     */\n    QVector<LineProperty> getLineProperties();\n\n    /**\n     * Returns the number of lines which the region of the window\n     * specified by scrollRegion() has been scrolled by since the last call\n     * to resetScrollCount().  scrollRegion() is in most cases the\n     * whole window, but will be a smaller area in, for example, applications\n     * which provide split-screen facilities.\n     *\n     * This is not guaranteed to be accurate, but allows views to optimise\n     * rendering by reducing the amount of costly text rendering that\n     * needs to be done when the output is scrolled.\n     */\n    int scrollCount() const;\n\n    /**\n     * Resets the count of scrolled lines returned by scrollCount()\n     */\n    void resetScrollCount();\n\n    /**\n     * Returns the area of the window which was last scrolled, this is\n     * usually the whole window area.\n     *\n     * Like scrollCount(), this is not guaranteed to be accurate,\n     * but allows views to optimise rendering.\n     */\n    QRect scrollRegion() const;\n\n    /**\n     * Sets the start of the selection to the given @p line and @p column within\n     * the window.\n     */\n    void setSelectionStart( int column , int line , bool columnMode );\n    /**\n     * Sets the end of the selection to the given @p line and @p column within\n     * the window.\n     */\n    void setSelectionEnd( int column , int line );\n    /**\n     * Retrieves the start of the selection within the window.\n     */\n    void getSelectionStart( int& column , int& line );\n    /**\n     * Retrieves the end of the selection within the window.\n     */\n    void getSelectionEnd( int& column , int& line );\n    /**\n     * Returns true if the character at @p line , @p column is part of the selection.\n     */\n    bool isSelected( int column , int line );\n    /**\n     * Clears the current selection\n     */\n    void clearSelection();\n\n\t/** Sets the number of lines in the window */\n\tvoid setWindowLines(int lines);\n    /** Returns the number of lines in the window */\n    int windowLines() const;\n    /** Returns the number of columns in the window */\n    int windowColumns() const;\n\n    /** Returns the total number of lines in the screen */\n    int lineCount() const;\n    /** Returns the total number of columns in the screen */\n    int columnCount() const;\n\n    /** Returns the index of the line which is currently at the top of this window */\n    int currentLine() const;\n\n    /**\n     * Returns the position of the cursor\n     * within the window.\n     */\n    QPoint cursorPosition() const;\n\n    /**\n     * Convenience method. Returns true if the window is currently at the bottom\n     * of the screen.\n     */\n    bool atEndOfOutput() const;\n\n    /** Scrolls the window so that @p line is at the top of the window */\n    void scrollTo( int line );\n\n    enum RelativeScrollMode\n    {\n        ScrollLines,\n        ScrollPages\n    };\n\n    /**\n     * Scrolls the window relative to its current position on the screen.\n     *\n     * @param mode Specifies whether @p amount refers to the number of lines or the number\n     * of pages to scroll.\n     * @param amount The number of lines or pages ( depending on @p mode ) to scroll by.  If\n     * this number is positive, the view is scrolled down.  If this number is negative, the view\n     * is scrolled up.\n     */\n    void scrollBy( RelativeScrollMode mode , int amount );\n\n    /**\n     * Specifies whether the window should automatically move to the bottom\n     * of the screen when new output is added.\n     *\n     * If this is set to true, the window will be moved to the bottom of the associated screen ( see\n     * screen() ) when the notifyOutputChanged() method is called.\n     */\n    void setTrackOutput(bool trackOutput);\n    /**\n     * Returns whether the window automatically moves to the bottom of the screen as\n     * new output is added.  See setTrackOutput()\n     */\n    bool trackOutput() const;\n\n    /**\n     * Returns the text which is currently selected.\n     *\n     * @param preserveLineBreaks See Screen::selectedText()\n     */\n    QString selectedText( bool preserveLineBreaks ) const;\n\npublic Q_SLOTS:\n    /**\n     * Notifies the window that the contents of the associated terminal screen have changed.\n     * This moves the window to the bottom of the screen if trackOutput() is true and causes\n     * the outputChanged() signal to be emitted.\n     */\n    void notifyOutputChanged();\n\nQ_SIGNALS:\n    /**\n     * Emitted when the contents of the associated terminal screen ( see screen() ) changes.\n     */\n    void outputChanged();\n\n    /**\n     * Emitted when the screen window is scrolled to a different position.\n     *\n     * @param line The line which is now at the top of the window.\n     */\n    void scrolled(int line);\n\n    /**\n     * Emitted when the selection is changed.\n     */\n    void selectionChanged();\n\nprivate:\n\tint endWindowLine() const;\n\tvoid fillUnusedArea();\n\n    Screen* _screen; // see setScreen() , screen()\n\tCharacter* _windowBuffer;\n\tint _windowBufferSize;\n\tbool _bufferNeedsUpdate;\n\n\tint  _windowLines;\n    int  _currentLine; // see scrollTo() , currentLine()\n    bool _trackOutput; // see setTrackOutput() , trackOutput()\n    int  _scrollCount; // count of lines which the window has been scrolled by since\n                       // the last call to resetScrollCount()\n};\n\n#endif // SCREENWINDOW_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/SelfListener.cpp",
    "content": "/* qterminal - a terminal widget for Qt\n * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@cybercatalyst.com)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"unix/SelfListener.h\"\n\nSelfListener::SelfListener(int a, QObject *parent) :\n    QThread(parent) {\n    _a = a;\n}\n\nvoid SelfListener::run() {\n    char buf[4096 + 1];\n    int len;\n    bool running = true;\n    while(running) {\n         while((len = ::read(_a, buf, 4096)) > 0) {\n            buf[len] = 0; // Just in case.\n            Q_EMIT recvData(buf, len);\n            msleep(30);\n         }\n         if(len < 0)\n           running = false;\n    }\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/SelfListener.h",
    "content": "/* qterminal - a terminal widget for Qt\n * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@cybercatalyst.com)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef SELFLISTENER_H\n#define SELFLISTENER_H\n\n#include <QThread>\n#include <unistd.h>\n\nclass SelfListener : public QThread\n{\n    Q_OBJECT\npublic:\n    explicit SelfListener(int a, QObject *parent = nullptr);\n\nQ_SIGNALS:\n    void recvData(const char* stdOutBuffer, int stdOutlen);\n\npublic Q_SLOTS:\n\nprotected:\n    void run();\n    int _a;\n};\n\n#endif // SELFLISTENER_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/TerminalCharacterDecoder.cpp",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n\n    Copyright (C) 2006, 2013 by Robert Knight <robertknight@gmail.com>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n// Own\n#include \"unix/TerminalCharacterDecoder.h\"\n\n// Qt\n#include <QTextStream>\n\nPlainTextDecoder::PlainTextDecoder()\n : _output(nullptr)\n , _includeTrailingWhitespace(true)\n{\n\n}\nvoid PlainTextDecoder::setTrailingWhitespace(bool enable)\n{\n    _includeTrailingWhitespace = enable;\n}\nbool PlainTextDecoder::trailingWhitespace() const\n{\n    return _includeTrailingWhitespace;\n}\nvoid PlainTextDecoder::begin(QTextStream* output)\n{\n   _output = output;\n}\nvoid PlainTextDecoder::end()\n{\n    _output = nullptr;\n}\nvoid PlainTextDecoder::decodeLine(const Character* const characters, int count, LineProperty /*properties*/\n\t\t\t\t\t\t\t )\n{\n    Q_ASSERT( _output );\n\n\t//TODO should we ignore or respect the LINE_WRAPPED line property?\n\n\t//note:  we build up a QString and send it to the text stream rather writing into the text\n\t//stream a character at a time because it is more efficient.\n\t//(since QTextStream always deals with QStrings internally anyway)\n\tQString plainText;\n\tplainText.reserve(count);\n\n    int outputCount = count;\n\n    // if inclusion of trailing whitespace is disabled then find the end of the\n    // line\n    if ( !_includeTrailingWhitespace )\n    {\n        for (int i = count-1 ; i >= 0 ; i--)\n        {\n            if ( characters[i].character != ' '  )\n                break;\n            else\n                outputCount--;\n        }\n    }\n\n\tfor (int i=0;i<outputCount;i++)\n\t{\n\t\tplainText.append( QChar(characters[i].character) );\n\t}\n\n\t*_output << plainText;\n}\n\nHTMLDecoder::HTMLDecoder() :\n        _output(nullptr)\n       ,_colorTable(base_color_table)\n       ,_innerSpanOpen(false)\n       ,_lastRendition(DEFAULT_RENDITION)\n{\n\t\n}\n\nvoid HTMLDecoder::begin(QTextStream* output)\n{\n    _output = output;\n\n    QString text;\n\n\t//open monospace span\n    openSpan(text,\"font-family:monospace\");\n\n    *output << text;\n}\n\nvoid HTMLDecoder::end()\n{\n    Q_ASSERT( _output );\n\n    QString text;\n\n    closeSpan(text);\n\n    *_output << text;\n\n    _output = nullptr;\n\n}\n\n//TODO: Support for LineProperty (mainly double width , double height)\nvoid HTMLDecoder::decodeLine(const Character* const characters, int count, LineProperty /*properties*/\n\t\t\t\t\t\t\t)\n{\n    Q_ASSERT( _output );\n\n\tQString text;\n\n\tint spaceCount = 0;\n\t\t\n\tfor (int i=0;i<count;i++)\n\t{\n\t\tQChar ch(characters[i].character);\n\n\t\t//check if appearance of character is different from previous char\n\t\tif ( characters[i].rendition != _lastRendition  ||\n\t\t     characters[i].foregroundColor != _lastForeColor  ||\n\t\t\t characters[i].backgroundColor != _lastBackColor )\n\t\t{\n\t\t\tif ( _innerSpanOpen )\n\t\t\t\t\tcloseSpan(text);\n\n\t\t\t_lastRendition = characters[i].rendition;\n\t\t\t_lastForeColor = characters[i].foregroundColor;\n\t\t\t_lastBackColor = characters[i].backgroundColor;\n\t\t\t\n\t\t\t//build up style string\n\t\t\tQString style;\n\n\t\t\tif ( _lastRendition & RE_BOLD ||\n                             (_colorTable && characters[i].isBold(_colorTable)) )\n\t\t\t\t\tstyle.append(\"font-weight:bold;\");\n\n\n\t\t\tif ( _lastRendition & RE_UNDERLINE )\n\t\t\t\t\tstyle.append(\"font-decoration:underline;\");\n\t\t\n\t\t\t//colours - a colour table must have been defined first\n\t\t\tif ( _colorTable )\t\n\t\t\t{\n\t\t\t\tstyle.append( QString(\"color:%1;\").arg(_lastForeColor.color(_colorTable).name() ) );\n\n\t\t\t\tif (!characters[i].isTransparent(_colorTable))\n\t\t\t\t{\n\t\t\t\t\tstyle.append( QString(\"background-color:%1;\").arg(_lastBackColor.color(_colorTable).name() ) );\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\t//open the span with the current style\t\n\t\t\topenSpan(text,style);\n\t\t\t_innerSpanOpen = true;\n\t\t}\n\n\t\t//handle whitespace\n\t\tif (ch.isSpace())\n\t\t\tspaceCount++;\n\t\telse\n\t\t\tspaceCount = 0;\n\t\t\n\n\t\t//output current character\n\t\tif (spaceCount < 2)\n\t\t{\n\t\t\t//escape HTML tag characters and just display others as they are\n\t\t\tif ( ch == '<' )\n\t\t\t\ttext.append(\"&lt;\");\n\t\t\telse if (ch == '>')\n\t\t\t\t\ttext.append(\"&gt;\");\n\t\t\telse\t\n\t\t\t\t\ttext.append(ch);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttext.append(\"&nbsp;\"); //HTML truncates multiple spaces, so use a space marker instead\n\t\t}\n\t\t\n\t}\n\n\t//close any remaining open inner spans\n\tif ( _innerSpanOpen )\n\t\tcloseSpan(text);\n\n\t//start new line\n\ttext.append(\"<br>\");\n\t\n\t*_output << text;\n}\n\nvoid HTMLDecoder::openSpan(QString& text , const QString& style)\n{\n\ttext.append( QString(\"<span style=\\\"%1\\\">\").arg(style) );\n}\n\nvoid HTMLDecoder::closeSpan(QString& text)\n{\n\ttext.append(\"</span>\");\n}\n\nvoid HTMLDecoder::setColorTable(const ColorEntry* table)\n{\n\t_colorTable = table;\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/TerminalCharacterDecoder.h",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n\n    Copyright (C) 2006-2007, 2013 by Robert Knight <robertknight@gmail.com>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef TERMINAL_CHARACTER_DECODER_H\n#define TERMINAL_CHARACTER_DECODER_H\n\n#include \"unix/Character.h\"\n\nclass QTextStream;\n\n/**\n * Base class for terminal character decoders\n *\n * The decoder converts lines of terminal characters which consist of a unicode character, foreground\n * and background colours and other appearance-related properties into text strings.\n *\n * Derived classes may produce either plain text with no other colour or appearance information, or\n * they may produce text which incorporates these additional properties.\n */\nclass TerminalCharacterDecoder\n{\npublic:\n\tvirtual ~TerminalCharacterDecoder() {}\n\n    /** Begin decoding characters.  The resulting text is appended to @p output. */\n    virtual void begin(QTextStream* output) = 0;\n    /** End decoding. */\n    virtual void end() = 0;\n\n\t/**\n\t * Converts a line of terminal characters with associated properties into a text string\n\t * and writes the string into an output QTextStream.\n\t *\n\t * @param characters An array of characters of length @p count.\n\t * @param properties Additional properties which affect all characters in the line\n\t * @param output The output stream which receives the decoded text\n\t */\n\tvirtual void decodeLine(const Character* const characters,\n\t\t\t\t\t\t\tint count,\n\t\t\t\t\t\t\tLineProperty properties) = 0;\n};\n\n/**\n * A terminal character decoder which produces plain text, ignoring colours and other appearance-related\n * properties of the original characters.\n */\nclass PlainTextDecoder : public TerminalCharacterDecoder\n{\npublic:\n\tPlainTextDecoder();\n\n    /**\n     * Set whether trailing whitespace at the end of lines should be included\n     * in the output.\n     * Defaults to true.\n     */\n    void setTrailingWhitespace(bool enable);\n    /**\n     * Returns whether trailing whitespace at the end of lines is included\n     * in the output.\n     */\n    bool trailingWhitespace() const;\n\n    virtual void begin(QTextStream* output);\n    virtual void end();\n\n\tvirtual void decodeLine(const Character* const characters,\n\t\t\t\t\t\t\tint count,\n\t\t\t\t\t\t\tLineProperty properties);\t\n\n\nprivate:\n    QTextStream* _output;\n    bool _includeTrailingWhitespace;\n};\n\n/**\n * A terminal character decoder which produces pretty HTML markup\n */\nclass HTMLDecoder : public TerminalCharacterDecoder\n{\npublic:\n\t/**\n\t * Constructs an HTML decoder using a default black-on-white color scheme.\n\t */\n\tHTMLDecoder();\n\n\t/**\n\t * Sets the colour table which the decoder uses to produce the HTML colour codes in its\n\t * output\n\t */\n\tvoid setColorTable( const ColorEntry* table );\n\t\t\n\tvirtual void decodeLine(const Character* const characters,\n\t\t\t\t\t\t\tint count,\n\t\t\t\t\t\t\tLineProperty properties);\n\n    virtual void begin(QTextStream* output);\n    virtual void end();\n\nprivate:\n\tvoid openSpan(QString& text , const QString& style);\n\tvoid closeSpan(QString& text);\n\n    QTextStream* _output;\n\tconst ColorEntry* _colorTable;\n    bool _innerSpanOpen;\n\tquint8 _lastRendition;\n\tCharacterColor _lastForeColor;\n\tCharacterColor _lastBackColor;\n\n};\n\n#endif\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/TerminalModel.cpp",
    "content": "/*\n    This file is part of Konsole\n\n    Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n    Copyright (C) 2012-2019 Jacob Dawid <jacob.dawid@cybercatalyst.com>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n// Own\n#include \"unix/TerminalModel.h\"\n\n// Standard\n#include <assert.h>\n#include <stdlib.h>\n\n// Qt\n#include <QtCore>\n\n#include <QApplication>\n#include <QDir>\n#include <QFile>\n#include <QStringList>\n\n#include \"unix/TerminalView.h\"\n#include \"unix/Vt102Emulation.h\"\n\nTerminalModel::TerminalModel(KPty *kpty) :\n    _shellProcess(nullptr)\n  , _emulation(nullptr)\n  , _monitorActivity(false)\n  , _monitorSilence(false)\n  , _notifiedActivity(false)\n  , _autoClose(true)\n  , _wantedClose(false)\n  , _silenceSeconds(10)\n  , _addToUtmp(false)\n  , _fullScripting(false)\n  , _hasDarkBackground(false)\n{\n    _kpty = kpty;\n\n    //create emulation backend\n    _emulation = new Vt102Emulation();\n    connect( _emulation, SIGNAL( stateSet(int) ),\n             this, SLOT( activityStateSet(int) ) );\n    connect( _emulation, SIGNAL( changeTabTextColorRequest( int ) ),\n             this, SIGNAL( changeTabTextColorRequest( int ) ) );\n    connect( _emulation, SIGNAL(profileChangeCommandReceived(const QString&)),\n             this, SIGNAL( profileChangeCommandReceived(const QString&)) );\n    // TODO\n    // connect( _emulation,SIGNAL(imageSizeChanged(int,int)) , this ,\n    //        SLOT(onEmulationSizeChange(int,int)) );\n\n    _selfListener = new SelfListener(kpty->masterFd());\n    _selfListener->start();\n    connect( _selfListener, SIGNAL(recvData(const char*,int)),\n             this, SLOT(onReceiveBlock(const char*,int)), Qt::BlockingQueuedConnection);\n\n    connect( _emulation, SIGNAL(sendData(const char*,int))\n             ,this,SLOT(sendData(const char*,int)));\n\n    //connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) );\n    //connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) );\n\n\n    //connect( _shellProcess,SIGNAL(done(int)), this, SLOT(done(int)) );\n\n    //setup timer for monitoring session activity\n    _monitorTimer = new QTimer(this);\n    _monitorTimer->setSingleShot(true);\n    connect(_monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone()));\n}\n\nvoid TerminalModel::setDarkBackground(bool darkBackground)\n{\n    _hasDarkBackground = darkBackground;\n}\nbool TerminalModel::hasDarkBackground() const\n{\n    return _hasDarkBackground;\n}\n\nvoid TerminalModel::setCodec(QTextCodec* codec)\n{\n    emulation()->setCodec(codec);\n}\n\nQList<TerminalView*> TerminalModel::views() const\n{\n    return _views;\n}\n\nvoid TerminalModel::addView(TerminalView* widget)\n{\n    Q_ASSERT( !_views.contains(widget) );\n\n    _views.append(widget);\n\n    if ( _emulation != nullptr )\n    {\n        // connect emulation - view signals and slots\n        connect( widget , SIGNAL(keyPressedSignal(QKeyEvent*)) , _emulation ,\n                 SLOT(sendKeyEvent(QKeyEvent*)) );\n        connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation ,\n                 SLOT(sendMouseEvent(int,int,int,int)) );\n        connect( widget , SIGNAL(sendStringToEmu(const char*)) , _emulation ,\n                 SLOT(sendString(const char*)) );\n\n        // allow emulation to notify view when the foreground process\n        // indicates whether or not it is interested in mouse signals\n        connect( _emulation , SIGNAL(programUsesMouseChanged(bool)) , widget ,\n                 SLOT(setUsesMouse(bool)) );\n\n        widget->setUsesMouse( _emulation->programUsesMouse() );\n\n        connect( _emulation , SIGNAL(programBracketedPasteModeChanged(bool)) ,\n                 widget , SLOT(setBracketedPasteMode(bool)) );\n\n        widget->setBracketedPasteMode(_emulation->programBracketedPasteMode());\n\n        widget->setScreenWindow(_emulation->createWindow());\n    }\n\n    //connect view signals and slots\n    QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this,\n                      SLOT(onViewSizeChange(int,int)));\n\n    QObject::connect( widget ,SIGNAL(destroyed(QObject*)) , this ,\n                      SLOT(viewDestroyed(QObject*)) );\n    //slot for close\n    //QObject::connect(this, SIGNAL(finished()), widget, SLOT(close()));\n}\n\nvoid TerminalModel::viewDestroyed(QObject* view)\n{\n    TerminalView* display = (TerminalView*)view;\n\n    Q_ASSERT( _views.contains(display) );\n\n    removeView(display);\n}\n\nvoid TerminalModel::sendData(const char *buf, int len)\n{\n    ssize_t bytesWritten = ::write(_kpty->masterFd(), buf, len);\n    (void)bytesWritten;\n}\n\nvoid TerminalModel::removeView(TerminalView* widget)\n{\n    _views.removeAll(widget);\n\n    disconnect(widget,nullptr,this,nullptr);\n\n    if ( _emulation != nullptr )\n    {\n        // disconnect\n        //  - key presses signals from widget\n        //  - mouse activity signals from widget\n        //  - string sending signals from widget\n        //\n        //  ... and any other signals connected in addView()\n        disconnect( widget, nullptr, _emulation, nullptr);\n\n        // disconnect state change signals emitted by emulation\n        disconnect( _emulation , nullptr , widget , nullptr);\n    }\n\n    // close the session automatically when the last view is removed\n    if ( _views.count() == 0 )\n    {\n        close();\n    }\n}\n\nvoid TerminalModel::run()\n{\n    Q_EMIT started();\n}\n\nvoid TerminalModel::monitorTimerDone()\n{\n    //FIXME: The idea here is that the notification popup will appear to tell the user than output from\n    //the terminal has stopped and the popup will disappear when the user activates the session.\n    //\n    //This breaks with the addition of multiple views of a session.  The popup should disappear\n    //when any of the views of the session becomes active\n\n\n    //FIXME: Make message text for this notification and the activity notification more descriptive.\n    if (_monitorSilence) {\n        //    KNotification::event(\"Silence\", (\"Silence in session '%1'\", _nameTitle), QPixmap(),\n        //                    QApplication::activeWindow(),\n        //                    KNotification::CloseWhenWidgetActivated);\n        Q_EMIT stateChanged(NOTIFYSILENCE);\n    }\n    else\n    {\n        Q_EMIT stateChanged(NOTIFYNORMAL);\n    }\n\n    _notifiedActivity=false;\n}\n\nvoid TerminalModel::activityStateSet(int state)\n{\n    if (state==NOTIFYBELL)\n    {\n        Q_EMIT bellRequest(\"\");\n    }\n    else if (state==NOTIFYACTIVITY)\n    {\n        if (_monitorSilence) {\n            _monitorTimer->start(_silenceSeconds*1000);\n        }\n\n        if ( _monitorActivity ) {\n            //FIXME:  See comments in Session::monitorTimerDone()\n            if (!_notifiedActivity) {\n                //        KNotification::event(\"Activity\", (\"Activity in session '%1'\", _nameTitle), QPixmap(),\n                //                        QApplication::activeWindow(),\n                //        KNotification::CloseWhenWidgetActivated);\n                _notifiedActivity=true;\n            }\n        }\n    }\n\n    if ( state==NOTIFYACTIVITY && !_monitorActivity )\n        state = NOTIFYNORMAL;\n    if ( state==NOTIFYSILENCE && !_monitorSilence )\n        state = NOTIFYNORMAL;\n\n    Q_EMIT stateChanged(state);\n}\n\nvoid TerminalModel::onViewSizeChange(int /*height*/, int /*width*/)\n{\n    updateTerminalSize();\n}\nvoid TerminalModel::onEmulationSizeChange(int lines , int columns)\n{\n    setSize( QSize(lines,columns) );\n}\n\nvoid TerminalModel::updateTerminalSize()\n{\n    QListIterator<TerminalView*> viewIter(_views);\n\n    int minLines = -1;\n    int minColumns = -1;\n\n    // minimum number of lines and columns that views require for\n    // their size to be taken into consideration ( to avoid problems\n    // with new view widgets which haven't yet been set to their correct size )\n    const int VIEW_LINES_THRESHOLD = 2;\n    const int VIEW_COLUMNS_THRESHOLD = 2;\n\n    //select largest number of lines and columns that will fit in all visible views\n    while ( viewIter.hasNext() )\n    {\n        TerminalView* view = viewIter.next();\n        if ( view->isHidden() == false &&\n             view->lines() >= VIEW_LINES_THRESHOLD &&\n             view->columns() >= VIEW_COLUMNS_THRESHOLD )\n        {\n            minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() );\n            minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() );\n        }\n    }\n\n    // backend emulation must have a _terminal of at least 1 column x 1 line in size\n    if ( minLines > 0 && minColumns > 0 )\n    {\n        _emulation->setImageSize( minLines , minColumns );\n        _kpty->setWinSize (minLines, minColumns);\n        //_shellProcess->setWindowSize( minLines , minColumns );\n    }\n}\n\nvoid TerminalModel::refresh()\n{\n}\n\nvoid TerminalModel::close()\n{\n    _autoClose = true;\n    _wantedClose = true;\n}\n\nvoid TerminalModel::sendText(const QString &text) const\n{\n    _emulation->sendText(text);\n}\n\nTerminalModel::~TerminalModel()\n{\n    delete _emulation;\n}\n\nvoid TerminalModel::setProfileKey(const QString& key)\n{\n    _profileKey = key;\n    Q_EMIT profileChanged(key);\n}\nQString TerminalModel::profileKey() const { return _profileKey; }\n\nvoid TerminalModel::done(int)\n{\n    Q_EMIT finished();\n}\n\nEmulation* TerminalModel::emulation() const\n{\n    return _emulation;\n}\n\nQString TerminalModel::keyBindings() const\n{\n    return _emulation->keyBindings();\n}\n\nvoid TerminalModel::setKeyBindings(const QString &id)\n{\n    _emulation->setKeyBindings(id);\n}\n\nvoid TerminalModel::setHistoryType(const HistoryType &hType)\n{\n    _emulation->setHistory(hType);\n}\n\nconst HistoryType& TerminalModel::historyType() const\n{\n    return _emulation->history();\n}\n\nvoid TerminalModel::clearHistory()\n{\n    _emulation->clearHistory();\n}\n\n// unused currently\nbool TerminalModel::isMonitorActivity() const { return _monitorActivity; }\n// unused currently\nbool TerminalModel::isMonitorSilence()  const { return _monitorSilence; }\n\nvoid TerminalModel::setMonitorActivity(bool _monitor)\n{\n    _monitorActivity=_monitor;\n    _notifiedActivity=false;\n\n    activityStateSet(NOTIFYNORMAL);\n}\n\nvoid TerminalModel::setMonitorSilence(bool _monitor)\n{\n    if (_monitorSilence==_monitor)\n        return;\n\n    _monitorSilence=_monitor;\n    if (_monitorSilence)\n    {\n        _monitorTimer->start(_silenceSeconds*1000);\n    }\n    else\n        _monitorTimer->stop();\n\n    activityStateSet(NOTIFYNORMAL);\n}\n\nvoid TerminalModel::setMonitorSilenceSeconds(int seconds)\n{\n    _silenceSeconds=seconds;\n    if (_monitorSilence) {\n        _monitorTimer->start(_silenceSeconds*1000);\n    }\n}\n\nvoid TerminalModel::setAddToUtmp(bool set)\n{\n    _addToUtmp = set;\n}\n\nvoid TerminalModel::onReceiveBlock(const char* buf, int len )\n{\n    _emulation->receiveData( buf, len );\n    Q_EMIT receivedData( QString::fromLatin1( buf, len ) );\n}\n\nQSize TerminalModel::size()\n{\n    return _emulation->imageSize();\n}\n\nvoid TerminalModel::setSize(const QSize& size)\n{\n    if ((size.width() <= 1) || (size.height() <= 1))\n        return;\n\n    Q_EMIT resizeRequest(size);\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/TerminalModel.h",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n\n    Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n    Copyright (C) 2012-2019 Jacob Dawid <jacob.dawid@cybercatalyst.com>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef TERMINALMODEL_H\n#define TERMINALMODEL_H\n\n// Qt\n#include <QtCore>\n\n#include <QStringList>\n#include <QTextCodec>\n#include <QWidget>\n\n#include \"unix/SelfListener.h\"\n\n// Konsole\n#include \"unix/History.h\"\n#include \"unix/kpty.h\"\n\nclass KProcess;\n\nclass Emulation;\nclass PseudoTerminal;\nclass TerminalView;\n\n/**\n * Represents a terminal session consisting of a pseudo-teletype and a terminal emulation.\n * The pseudo-teletype (or PTY) handles I/O between the terminal process and Konsole.\n * The terminal emulation ( Emulation and subclasses ) processes the output stream from the\n * PTY and produces a character image which is then shown on views connected to the session.\n *\n * Each Session can be connected to one or more views by using the addView() method.\n * The attached views can then display output from the program running in the terminal\n * or send input to the program in the terminal in the form of keypresses and mouse\n * activity.\n */\nclass TerminalModel : public QObject {\nQ_OBJECT\n\npublic:\n  Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings)\n  Q_PROPERTY(QSize size READ size WRITE setSize)\n\n  /**\n   * Constructs a new session.\n   *\n   * To start the terminal process, call the run() method,\n   * after specifying the program and arguments\n   * using setProgram() and setArguments()\n   *\n   * If no program or arguments are specified explicitly, the Session\n   * falls back to using the program specified in the SHELL environment\n   * variable.\n   */\n  TerminalModel(KPty *kpty);\n  ~TerminalModel();\n\n\n  /**\n   * Sets the profile associated with this session.\n   *\n   * @param profileKey A key which can be used to obtain the current\n   * profile settings from the SessionManager\n   */\n  void setProfileKey(const QString& profileKey);\n  /**\n   * Returns the profile key associated with this session.\n   * This can be passed to the SessionManager to obtain the current\n   * profile settings.\n   */\n  QString profileKey() const;\n\n  /**\n   * Adds a new view for this session.\n   *\n   * The viewing widget will display the output from the terminal and\n   * input from the viewing widget (key presses, mouse activity etc.)\n   * will be sent to the terminal.\n   *\n   * Views can be removed using removeView().  The session is automatically\n   * closed when the last view is removed.\n   */\n  void addView(TerminalView* widget);\n  /**\n   * Removes a view from this session.  When the last view is removed,\n   * the session will be closed automatically.\n   *\n   * @p widget will no longer display output from or send input\n   * to the terminal\n   */\n  void removeView(TerminalView* widget);\n\n  /**\n   * Returns the views connected to this session\n   */\n  QList<TerminalView*> views() const;\n\n  /**\n   * Returns the terminal emulation instance being used to encode / decode\n   * characters to / from the process.\n   */\n  Emulation*  emulation() const;\n\n\n\n  /**\n   * Sets the type of history store used by this session.\n   * Lines of output produced by the terminal are added\n   * to the history store.  The type of history store\n   * used affects the number of lines which can be\n   * remembered before they are lost and the storage\n   * (in memory, on-disk etc.) used.\n   */\n  void setHistoryType(const HistoryType& type);\n  /**\n   * Returns the type of history store used by this session.\n   */\n  const HistoryType& historyType() const;\n  /**\n   * Clears the history store used by this session.\n   */\n  void clearHistory();\n\n  /**\n   * Enables monitoring for activity in the session.\n   * This will cause notifySessionState() to be emitted\n   * with the NOTIFYACTIVITY state flag when output is\n   * received from the terminal.\n   */\n  void setMonitorActivity(bool);\n  /** Returns true if monitoring for activity is enabled. */\n  bool isMonitorActivity() const;\n\n  /**\n   * Enables monitoring for silence in the session.\n   * This will cause notifySessionState() to be emitted\n   * with the NOTIFYSILENCE state flag when output is not\n   * received from the terminal for a certain period of\n   * time, specified with setMonitorSilenceSeconds()\n   */\n  void setMonitorSilence(bool);\n  /**\n   * Returns true if monitoring for inactivity (silence)\n   * in the session is enabled.\n   */\n  bool isMonitorSilence()  const;\n  /** See setMonitorSilence() */\n  void setMonitorSilenceSeconds(int seconds);\n\n  /**\n   * Sets the key bindings used by this session.  The bindings\n   * specify how input key sequences are translated into\n   * the character stream which is sent to the terminal.\n   *\n   * @param id The name of the key bindings to use.  The\n   * names of available key bindings can be determined using the\n   * KeyboardTranslatorManager class.\n   */\n  void setKeyBindings(const QString& id);\n  /** Returns the name of the key bindings used by this session. */\n  QString keyBindings() const;\n\n\n  /** Specifies whether a utmp entry should be created for the pty used by this session. */\n  void setAddToUtmp(bool);\n\n  /**\n   * Specifies whether to close the session automatically when the terminal\n   * process terminates.\n   */\n  void setAutoClose(bool b) { _autoClose = b; }\n\n  /**\n   * Sends @p text to the current foreground terminal program.\n   */\n  void sendText(const QString& text) const;\n\n\n  /** Returns the terminal session's window size in lines and columns. */\n  QSize size();\n  /**\n   * Emits a request to resize the session to accommodate\n   * the specified window size.\n   *\n   * @param size The size in lines and columns to request.\n   */\n  void setSize(const QSize& size);\n\n  /** Sets the text codec used by this session's terminal emulation. */\n  void setCodec(QTextCodec* codec);\n\n  /**\n   * Sets whether the session has a dark background or not.  The session\n   * uses this information to set the COLORFGBG variable in the process's\n   * environment, which allows the programs running in the terminal to determine\n   * whether the background is light or dark and use appropriate colors by default.\n   *\n   * This has no effect once the session is running.\n   */\n  void setDarkBackground(bool darkBackground);\n  /**\n   * Returns true if the session has a dark background.\n   * See setDarkBackground()\n   */\n  bool hasDarkBackground() const;\n\n  /**\n   * Attempts to get the shell program to redraw the current display area.\n   * This can be used after clearing the screen, for example, to get the\n   * shell to redraw the prompt line.\n   */\n  void refresh();\n\npublic Q_SLOTS:\n\n  /**\n   * Starts the terminal session.\n   *\n   * This creates the terminal process and connects the teletype to it.\n   */\n  void run();\n\n  /**\n   * Closes the terminal session.  This sends a hangup signal\n   * (SIGHUP) to the terminal process and causes the done(Session*)\n   * signal to be emitted.\n   */\n  void close();\n\nQ_SIGNALS:\n\n  /** Emitted when the terminal process starts. */\n  void started();\n\n  /**\n   * Emitted when the terminal process exits.\n   */\n  void finished();\n\n  /**\n   * Emitted when output is received from the terminal process.\n   */\n  void receivedData( const QString& text );\n\n  /** Emitted when the session's title has changed. */\n  void titleChanged();\n\n  /** Emitted when the session's profile has changed. */\n  void profileChanged(const QString& profile);\n\n  /**\n   * Emitted when the activity state of this session changes.\n   *\n   * @param state The new state of the session.  This may be one\n   * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY\n   */\n  void stateChanged(int state);\n\n  /** Emitted when a bell event occurs in the session. */\n  void bellRequest( const QString& message );\n\n  /**\n   * Requests that the color the text for any tabs associated with\n   * this session should be changed;\n   *\n   * TODO: Document what the parameter does\n   */\n  void changeTabTextColorRequest(int);\n\n  /**\n   * Requests that the background color of views on this session\n   * should be changed.\n   */\n  void changeBackgroundColorRequest(const QColor&);\n\n  /** TODO: Document me. */\n  void openUrlRequest(const QString& url);\n\n  /**\n   * Emitted when the terminal process requests a change\n   * in the size of the terminal window.\n   *\n   * @param size The requested window size in terms of lines and columns.\n   */\n  void resizeRequest(const QSize& size);\n\n  /**\n   * Emitted when a profile change command is received from the terminal.\n   *\n   * @param text The text of the command.  This is a string of the form\n   * \"PropertyName=Value;PropertyName=Value ...\"\n   */\n  void profileChangeCommandReceived(const QString& text);\n\nprivate Q_SLOTS:\n  void done(int);\n\n  void onReceiveBlock(const char* buffer, int len );\n  void monitorTimerDone();\n\n  void onViewSizeChange(int height, int width);\n  void onEmulationSizeChange(int lines , int columns);\n\n  void activityStateSet(int);\n\n  //automatically detach views from sessions when view is destroyed\n  void viewDestroyed(QObject* view);\n\n  void sendData(const char* buf, int len);\n\nprivate:\n\n  void updateTerminalSize();\n  WId windowId() const;\n\n  int            _uniqueIdentifier;\n\n  PseudoTerminal* _shellProcess;\n  Emulation*    _emulation;\n\n  QList<TerminalView*> _views;\n\n  bool           _monitorActivity;\n  bool           _monitorSilence;\n  bool           _notifiedActivity;\n  bool           _masterMode;\n  bool           _autoClose;\n  bool           _wantedClose;\n  QTimer*        _monitorTimer;\n\n  int            _silenceSeconds;\n\n  bool           _addToUtmp;\n  bool           _fullScripting;\n\n  int            _masterFd;\n  int            _slaveFd;\n\n  SelfListener  *_selfListener;\n  KPty         * _kpty;\n\n\n  QColor         _modifiedBackground; // as set by: echo -en '\\033]11;Color\\007\n\n  QString        _profileKey;\n\n  bool _hasDarkBackground;\n};\n\n\n#endif // TERMINALMODEL_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/TerminalView.cpp",
    "content": "/*\n    This file is part of Konsole, a terminal emulator for KDE.\n\n    Copyright (C) 2006-7 by Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n    Copyright (C) 2012-2019 Jacob Dawid <jacob.dawid@cybercatalyst.com>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"qt-utils.h\"\n\n// Own\n#include \"unix/TerminalView.h\"\n\n// Qt\n#include <QtCore>\n#include <QtGui>\n\n#include <QApplication>\n#include <QBoxLayout>\n#include <QClipboard>\n#include <QEvent>\n#include <QFile>\n#include <QGridLayout>\n#include <QKeyEvent>\n#include <QLabel>\n#include <QLayout>\n#include <QPainter>\n#include <QPixmap>\n#include <QScrollBar>\n#include <QStyle>\n#include <QTime>\n#include <QToolTip>\n\n#include \"unix/Filter.h\"\n#include \"unix/konsole_wcwidth.h\"\n#include \"unix/ScreenWindow.h\"\n#include \"unix/TerminalCharacterDecoder.h\"\n\n#include <signal.h>\n\n#ifndef loc\n#define loc(X,Y) ((Y)*_columns+(X))\n#endif\n\n#define yMouseScroll 1\n\n#define REPCHAR   \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" \\\n  \"abcdefgjijklmnopqrstuvwxyz\" \\\n  \"0123456789./+@\"\n\n// scroll increment used when dragging selection at top/bottom of window.\n\n// static\nbool TerminalView::_antialiasText = true;\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                                Colors                                     */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)\n\n   Code        0       1       2       3       4       5       6       7\n   ----------- ------- ------- ------- ------- ------- ------- ------- -------\n   ANSI  (bgr) Black   Red     Green   Yellow  Blue    Magenta Cyan    White\n   IBMPC (rgb) Black   Blue    Green   Cyan    Red     Magenta Yellow  White\n*/\n\nScreenWindow* TerminalView::screenWindow() const\n{\n  return _screenWindow;\n}\nvoid TerminalView::setScreenWindow(ScreenWindow* window)\n{\n  // disconnect existing screen window if any\n  if ( _screenWindow )\n    {\n      disconnect( _screenWindow , nullptr , this , nullptr );\n    }\n\n  _screenWindow = window;\n\n  if ( window )\n    {\n      //#warning \"The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?\"\n      connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) );\n      connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) );\n      window->setWindowLines(_lines);\n    }\n}\n\nconst ColorEntry* TerminalView::colorTable() const\n{\n  return _colorTable;\n}\n\nvoid TerminalView::setColorTable(const ColorEntry table[])\n{\n  for (int i = 0; i < TABLE_COLORS; i++)\n    _colorTable[i] = table[i];\n\n  QPalette p = palette();\n  p.setColor( backgroundRole(), _colorTable[DEFAULT_BACK_COLOR].color );\n  setPalette( p );\n\n  // Avoid propagating the palette change to the scroll bar\n  _scrollBar->setPalette( QApplication::palette() );\n\n  update();\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                                   Font                                    */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n/*\n   The VT100 has 32 special graphical characters. The usual vt100 extended\n   xterm fonts have these at 0x00..0x1f.\n\n   QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals\n   come in here as proper unicode characters.\n\n   We treat non-iso10646 fonts as VT100 extended and do the required mapping\n   from unicode to 0x00..0x1f. The remaining translation is then left to the\n   QCodec.\n*/\n\n// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.\n\nunsigned short vt100_graphics[32] =\n{ // 0/8     1/9    2/10    3/11    4/12    5/13    6/14    7/15\n  0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,\n  0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,\n  0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,\n  0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7\n};\n\nvoid TerminalView::fontChange(const QFont&)\n{\n  QFontMetrics fm(font());\n  _fontHeight = fm.height() + _lineSpacing;\n\n\n  // waba TerminalDisplay 1.123:\n  // \"Base character width on widest ASCII character. This prevents too wide\n  //  characters in the presence of double wide (e.g. Japanese) characters.\"\n  // Get the width from representative normal width characters\n  _fontWidth = ((double)octave::qt_fontmetrics_horizontal_advance(fm, REPCHAR)\n                / (double)strlen(REPCHAR));\n\n  _fixedFont = true;\n\n  int fw = octave::qt_fontmetrics_horizontal_advance(fm, REPCHAR[0]);\n  for(unsigned int i=1; i< strlen(REPCHAR); i++)\n    {\n      if (fw != octave::qt_fontmetrics_horizontal_advance(fm, REPCHAR[i]))\n        {\n          _fixedFont = false;\n          break;\n        }\n    }\n\n\n  if (_fontWidth < 1)\n    _fontWidth = 1;\n\n  _fontAscent = fm.ascent();\n\n  Q_EMIT changedFontMetricSignal( _fontHeight, _fontWidth );\n  //parentWidget()->setFixedWidth(_fontWidth * 80 + _leftMargin);\n  propagateSize();\n  update();\n}\n\nvoid TerminalView::setVTFont(const QFont& f)\n{\n  QFont font = f;\n\n  QFontMetrics metrics(font);\n\n  if ( metrics.height() < height() && metrics.maxWidth() < width() )\n    {\n      // hint that text should be drawn without anti-aliasing.\n      // depending on the user's font configuration, this may not be respected\n      if (!_antialiasText)\n        font.setStyleStrategy( QFont::NoAntialias );\n\n      // experimental optimization.  Konsole assumes that the terminal is using a\n      // mono-spaced font, in which case kerning information should have an effect.\n      // Disabling kerning saves some computation when rendering text.\n      // font.setKerning(false);\n\n      int strategy = font.styleStrategy();\n#if defined (HAVE_QFONT_FORCE_INTEGER_METRICS)\n      strategy |= QFont::ForceIntegerMetrics;\n#endif\n      font.setStyleStrategy(QFont::StyleStrategy(strategy));\n\n      QWidget::setFont(font);\n      fontChange(font);\n    }\n}\n\nvoid TerminalView::setFont(const QFont &)\n{\n  // ignore font change request if not coming from konsole itself\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                         Constructor / Destructor                          */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\nTerminalView::TerminalView(QWidget *parent)\n  :QWidget(parent)\n  ,_screenWindow(nullptr)\n  ,_allowBell(true)\n  ,_gridLayout(nullptr)\n  ,_fontHeight(1)\n  ,_fontWidth(1)\n  ,_fontAscent(1)\n  ,_lines(1)\n  ,_columns(1)\n  ,_usedLines(1)\n  ,_usedColumns(1)\n  ,_contentHeight(1)\n  ,_contentWidth(1)\n  ,_image(nullptr)\n  ,_randomSeed(0)\n  ,_resizing(false)\n  ,_terminalSizeHint(false)\n  ,_terminalSizeStartup(true)\n  ,_disabledBracketedPasteMode(false)\n  ,_actSel(0)\n  ,_wordSelectionMode(false)\n  ,_lineSelectionMode(false)\n  ,_preserveLineBreaks(false)\n  ,_columnSelectionMode(false)\n  ,_scrollbarLocation(NoScrollBar)\n  ,_wordCharacters(\":@-./_~\")\n  ,_bellMode(SystemBeepBell)\n  ,_blinking(false)\n  ,_cursorBlinking(false)\n  ,_hasBlinkingCursor(false)\n  ,_ctrlDrag(false)\n  ,_tripleClickMode(SelectWholeLine)\n  ,_isFixedSize(false)\n  ,_possibleTripleClick(false)\n  ,_resizeWidget(nullptr)\n  ,_resizeTimer(nullptr)\n  ,_outputSuspendedLabel(nullptr)\n  ,_lineSpacing(0)\n  ,_colorsInverted(false)\n  ,_blendColor(qRgba(0,0,0,0xff))\n  ,_filterChain(new TerminalImageFilterChain())\n  ,_cursorShape(BlockCursor)\n  ,_readonly(false)\n{\n  // terminal applications are not designed with Right-To-Left in mind,\n  // so the layout is forced to Left-To-Right\n  setLayoutDirection(Qt::LeftToRight);\n\n  // The offsets are not yet calculated.\n  // Do not calculate these too often to be more smoothly when resizing\n  // konsole in opaque mode.\n  _topMargin = DEFAULT_TOP_MARGIN;\n  _leftMargin = DEFAULT_LEFT_MARGIN;\n\n  // create scroll bar for scrolling output up and down\n  // set the scroll bar's slider to occupy the whole area of the scroll bar initially\n  _scrollBar = new QScrollBar(this);\n  setScroll(0,0);\n  _scrollBar->setCursor( Qt::ArrowCursor );\n  connect(_scrollBar, SIGNAL(valueChanged(int)), this,\n          SLOT(scrollBarPositionChanged(int)));\n\n  // setup timers for blinking cursor and text\n  _blinkTimer   = new QTimer(this);\n  connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent()));\n\n  _blinkCursorTimer   = new QTimer(this);\n  connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent()));\n\n  _process_filter_timer = new QTimer (this);\n  connect (_process_filter_timer, SIGNAL (timeout ()),\n           this, SLOT (processFilters ()));\n  _process_filter_timer->start (300);\n\n  //  QCursor::setAutoHideCursor( this, true );\n\n  setUsesMouse(true);\n  setBracketedPasteMode(false);\n  setColorTable(base_color_table);\n  setMouseTracking(true);\n\n  // Enable drag and drop\n  setAcceptDrops(true); // attempt\n  dragInfo.state = diNone;\n\n  setFocusPolicy( Qt::WheelFocus );\n\n  // enable input method support\n  setAttribute(Qt::WA_InputMethodEnabled, true);\n\n  // this is an important optimization, it tells Qt\n  // that TerminalDisplay will handle repainting its entire area.\n  setAttribute(Qt::WA_OpaquePaintEvent);\n\n  _gridLayout = new QGridLayout(this);\n  _gridLayout->setContentsMargins (0, 0, 0, 0);\n\n  setLayout( _gridLayout );\n}\n\nTerminalView::~TerminalView()\n{\n  qApp->removeEventFilter( this );\n\n  delete[] _image;\n\n  delete _gridLayout;\n  delete _outputSuspendedLabel;\n  delete _filterChain;\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                             Display Operations                            */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n/**\n A table for emulating the simple (single width) unicode drawing chars.\n It represents the 250x - 257x glyphs. If it's zero, we can't use it.\n if it's not, it's encoded as follows: imagine a 5x5 grid where the points are numbered\n 0 to 24 left to top, top to bottom. Each point is represented by the corresponding bit.\n\n Then, the pixels basically have the following interpretation:\n _|||_\n -...-\n -...-\n -...-\n _|||_\n\nwhere _ = none\n      | = vertical line.\n      - = horizontal line.\n */\n\n\nenum LineEncode\n{\n  TopL  = (1<<1),\n  TopC  = (1<<2),\n  TopR  = (1<<3),\n\n  LeftT = (1<<5),\n  Int11 = (1<<6),\n  Int12 = (1<<7),\n  Int13 = (1<<8),\n  RightT = (1<<9),\n\n  LeftC = (1<<10),\n  Int21 = (1<<11),\n  Int22 = (1<<12),\n  Int23 = (1<<13),\n  RightC = (1<<14),\n\n  LeftB = (1<<15),\n  Int31 = (1<<16),\n  Int32 = (1<<17),\n  Int33 = (1<<18),\n  RightB = (1<<19),\n\n  BotL  = (1<<21),\n  BotC  = (1<<22),\n  BotR  = (1<<23)\n};\n\nvoid TerminalView::setKeyboardCursorShape(KeyboardCursorShape shape)\n{\n  _cursorShape = shape;\n}\nTerminalView::KeyboardCursorShape TerminalView::keyboardCursorShape() const\n{\n  return _cursorShape;\n}\nvoid TerminalView::setKeyboardCursorColor(bool useForegroundColor, const QColor& color)\n{\n  if (useForegroundColor)\n    _cursorColor = QColor(); // an invalid color means that\n  // the foreground color of the\n  // current character should\n  // be used\n\n  else\n    _cursorColor = color;\n}\nQColor TerminalView::keyboardCursorColor() const\n{\n  return _cursorColor;\n}\n\nvoid TerminalView::drawBackground(QPainter& painter, const QRect& rect, const QColor& backgroundColor)\n{\n  // the area of the widget showing the contents of the terminal display is drawn\n  // using the background color from the color scheme set with setColorTable()\n  //\n  // the area of the widget behind the scroll-bar is drawn using the background\n  // brush from the scroll-bar's palette, to give the effect of the scroll-bar\n  // being outside of the terminal display and visual consistency with other KDE\n  // applications.\n  //\n  QRect scrollBarArea = _scrollBar->isVisible() ?\n        rect.intersected(_scrollBar->geometry()) :\n        QRect();\n\n  QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea);\n  QRect contentsRect = contentsRegion.boundingRect();\n\n  painter.fillRect(contentsRect, backgroundColor);\n  painter.fillRect(scrollBarArea,_scrollBar->palette().window());\n}\n\nvoid TerminalView::drawCursor(QPainter& painter,\n                              const QRect& rect,\n                              const QColor& foregroundColor,\n                              const QColor& /*backgroundColor*/,\n                              bool& invertCharacterColor)\n{\n  QRect cursorRect = rect;\n  cursorRect.setHeight(_fontHeight - _lineSpacing - 1);\n\n  if (!_cursorBlinking)\n    {\n      if ( _cursorColor.isValid() )\n        painter.setPen(_cursorColor);\n      else {\n          painter.setPen(foregroundColor);\n        }\n\n      if ( _cursorShape == BlockCursor )\n        {\n          // draw the cursor outline, adjusting the area so that\n          // it is draw entirely inside 'rect'\n          int penWidth = qMax(1,painter.pen().width());\n\n          painter.drawRect(cursorRect.adjusted(penWidth/2,\n                                               penWidth/2,\n                                               - penWidth/2 - penWidth%2,\n                                               - penWidth/2 - penWidth%2));\n          if ( hasFocus() )\n            {\n              painter.fillRect(cursorRect, _cursorColor.isValid() ? _cursorColor : foregroundColor);\n\n              if ( !_cursorColor.isValid() )\n                {\n                  // invert the colour used to draw the text to ensure that the character at\n                  // the cursor position is readable\n                  invertCharacterColor = true;\n                }\n            }\n        }\n      else if ( _cursorShape == UnderlineCursor )\n        painter.drawLine(cursorRect.left(),\n                         cursorRect.bottom(),\n                         cursorRect.right(),\n                         cursorRect.bottom());\n      else if ( _cursorShape == IBeamCursor )\n        painter.drawLine(cursorRect.left(),\n                         cursorRect.top(),\n                         cursorRect.left(),\n                         cursorRect.bottom());\n\n    }\n}\n\nvoid TerminalView::drawCharacters(QPainter& painter,\n                                  const QRect& rect,\n                                  const QString& text,\n                                  const Character* style,\n                                  bool invertCharacterColor)\n{\n  // don't draw text which is currently blinking\n  if ( _blinking && (style->rendition & RE_BLINK) )\n    return;\n\n  // setup bold and underline\n  bool useBold = style->rendition & RE_BOLD || style->isBold(_colorTable) || font().bold();\n  bool useUnderline = style->rendition & RE_UNDERLINE || font().underline();\n\n  QFont font = painter.font();\n  if (    font.bold() != useBold\n          || font.underline() != useUnderline )\n    {\n      font.setBold(useBold);\n      font.setUnderline(useUnderline);\n      painter.setFont(font);\n    }\n\n  const CharacterColor& textColor = ( invertCharacterColor ? style->backgroundColor : style->foregroundColor );\n  const QColor color = textColor.color(_colorTable);\n\n  QPen pen = painter.pen();\n  if ( pen.color() != color )\n    {\n      pen.setColor(color);\n      painter.setPen(color);\n    }\n  // draw text\n  // the drawText(rect,flags,string) overload is used here with null flags\n  // instead of drawText(rect,string) because the (rect,string) overload causes\n  // the application's default layout direction to be used instead of\n  // the widget-specific layout direction, which should always be\n  // Qt::LeftToRight for this widget\n  painter.drawText(rect,0,text);\n}\n\nvoid TerminalView::drawTextFragment(QPainter& painter ,\n                                    const QRect& rect,\n                                    const QString& text,\n                                    const Character* style)\n{\n  painter.save();\n\n  // setup painter\n  const QColor foregroundColor = style->foregroundColor.color(_colorTable);\n  const QColor backgroundColor = style->backgroundColor.color(_colorTable);\n\n  // draw background if different from the display's background color\n  if ( backgroundColor != palette().window().color() )\n    drawBackground(painter,rect,backgroundColor);\n\n  // draw cursor shape if the current character is the cursor\n  // this may alter the foreground and background colors\n  bool invertCharacterColor = false;\n\n  if ( style->rendition & RE_CURSOR )\n    drawCursor(painter,rect,foregroundColor,backgroundColor,invertCharacterColor);\n  // draw text\n  drawCharacters(painter,rect,text,style,invertCharacterColor);\n\n  painter.restore();\n}\n\nvoid TerminalView::setRandomSeed(uint randomSeed) { _randomSeed = randomSeed; }\nuint TerminalView::randomSeed() const { return _randomSeed; }\n\n// scrolls the image by 'lines', down if lines > 0 or up otherwise.\n//\n// the terminal emulation keeps track of the scrolling of the character\n// image as it receives input, and when the view is updated, it calls scrollImage()\n// with the final scroll amount.  this improves performance because scrolling the\n// display is much cheaper than re-rendering all the text for the\n// part of the image which has moved up or down.\n// Instead only new lines have to be drawn\n//\n// note:  it is important that the area of the display which is\n// scrolled aligns properly with the character grid -\n// which has a top left point at (_leftMargin,_topMargin) ,\n// a cell width of _fontWidth and a cell height of _fontHeight).\nvoid TerminalView::scrollImage(int lines , const QRect& screenWindowRegion)\n{\n  // if the flow control warning is enabled this will interfere with the\n  // scrolling optimisations and cause artifacts.  the simple solution here\n  // is to just disable the optimisation whilst it is visible\n  if ( _outputSuspendedLabel && _outputSuspendedLabel->isVisible() ) {\n      return;\n    }\n\n  // constrain the region to the display\n  // the bottom of the region is capped to the number of lines in the display's\n  // internal image - 2, so that the height of 'region' is strictly less\n  // than the height of the internal image.\n  QRect region = screenWindowRegion;\n  region.setBottom( qMin(region.bottom(),this->_lines-2) );\n\n  if (lines == 0\n      || _image == nullptr\n      || !region.isValid()\n      || (region.top() + abs(lines)) >= region.bottom()\n      || this->_lines <= region.height() )\n    return;\n\n  QRect scrollRect;\n\n  void* firstCharPos = &_image[ region.top() * this->_columns ];\n  void* lastCharPos = &_image[ (region.top() + abs(lines)) * this->_columns ];\n\n  int top = _topMargin + (region.top() * _fontHeight);\n  int linesToMove = region.height() - abs(lines);\n  int bytesToMove = linesToMove *\n      this->_columns *\n      sizeof(Character);\n\n  Q_ASSERT( linesToMove > 0 );\n  Q_ASSERT( bytesToMove > 0 );\n\n  //scroll internal image\n  if ( lines > 0 )\n    {\n      // check that the memory areas that we are going to move are valid\n      Q_ASSERT( (char*)lastCharPos + bytesToMove <\n                (char*)(_image + (this->_lines * this->_columns)) );\n\n      Q_ASSERT( (lines*this->_columns) < _imageSize );\n\n      //scroll internal image down\n      memmove( firstCharPos , lastCharPos , bytesToMove );\n\n      //set region of display to scroll, making sure that\n      //the region aligns correctly to the character grid\n      scrollRect = QRect( _leftMargin , top,\n                          this->_usedColumns * _fontWidth ,\n                          linesToMove * _fontHeight );\n    }\n  else\n    {\n      // check that the memory areas that we are going to move are valid\n      Q_ASSERT( (char*)firstCharPos + bytesToMove <\n                (char*)(_image + (this->_lines * this->_columns)) );\n\n      //scroll internal image up\n      memmove( lastCharPos , firstCharPos , bytesToMove );\n\n      //set region of the display to scroll, making sure that\n      //the region aligns correctly to the character grid\n      QPoint topPoint( _leftMargin , top + abs(lines)*_fontHeight );\n\n      scrollRect = QRect( topPoint ,\n                          QSize( this->_usedColumns*_fontWidth ,\n                                 linesToMove * _fontHeight ));\n    }\n\n  //scroll the display vertically to match internal _image\n  scroll( 0 , _fontHeight * (-lines) , scrollRect );\n}\n\nQRegion TerminalView::hotSpotRegion() const\n{\n  QRegion region;\n  for( Filter::HotSpot* hotSpot : _filterChain->hotSpots() )\n    {\n      QRect rect;\n      rect.setLeft(hotSpot->startColumn());\n      rect.setTop(hotSpot->startLine());\n      rect.setRight(hotSpot->endColumn());\n      rect.setBottom(hotSpot->endLine());\n\n      region |= imageToWidget(rect);\n    }\n  return region;\n}\n\nvoid TerminalView::processFilters()\n{\n  if (!_screenWindow)\n    return;\n\n  QRegion preUpdateHotSpots = hotSpotRegion();\n\n  // use _screenWindow->getImage() here rather than _image because\n  // other classes may call processFilters() when this display's\n  // ScreenWindow emits a scrolled() signal - which will happen before\n  // updateImage() is called on the display and therefore _image is\n  // out of date at this point\n  _filterChain->setImage( _screenWindow->getImage(),\n                          _screenWindow->windowLines(),\n                          _screenWindow->windowColumns(),\n                          _screenWindow->getLineProperties() );\n  _filterChain->process();\n\n  QRegion postUpdateHotSpots = hotSpotRegion();\n\n  update( preUpdateHotSpots | postUpdateHotSpots );\n}\n\nvoid TerminalView::updateImage()\n{\n  if ( !_screenWindow )\n    return;\n  updateLineProperties();\n\n  // optimization - scroll the existing image where possible and\n  // avoid expensive text drawing for parts of the image that\n  // can simply be moved up or down\n  scrollImage( _screenWindow->scrollCount() ,\n               _screenWindow->scrollRegion() );\n  _screenWindow->resetScrollCount();\n\n  Character* const newimg = _screenWindow->getImage();\n  int lines = _screenWindow->windowLines();\n  int columns = _screenWindow->windowColumns();\n\n  setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() );\n\n  if (!_image)\n    updateImageSize(); // Create _image\n\n  Q_ASSERT( this->_usedLines <= this->_lines );\n  Q_ASSERT( this->_usedColumns <= this->_columns );\n\n  int y,x,len;\n\n  QPoint tL  = contentsRect().topLeft();\n\n  int    tLx = tL.x();\n  int    tLy = tL.y();\n  _hasBlinker = false;\n\n  CharacterColor cf;       // undefined\n  CharacterColor _clipboard;       // undefined\n  int cr  = -1;   // undefined\n\n  const int linesToUpdate = qMin(this->_lines, qMax(0,lines  ));\n  const int columnsToUpdate = qMin(this->_columns,qMax(0,columns));\n\n  QChar *disstrU = new QChar[columnsToUpdate];\n  char *dirtyMask = new char[columnsToUpdate+2];\n  QRegion dirtyRegion;\n\n  // debugging variable, this records the number of lines that are found to\n  // be 'dirty' ( ie. have changed from the old _image to the new _image ) and\n  // which therefore need to be repainted\n  int dirtyLineCount = 0;\n\n  for (y = 0; y < linesToUpdate; y++)\n    {\n      const Character*       currentLine = &_image[y*this->_columns];\n      const Character* const newLine = &newimg[y*columns];\n\n      bool updateLine = false;\n\n      // The dirty mask indicates which characters need repainting. We also\n      // mark surrounding neighbours dirty, in case the character exceeds\n      // its cell boundaries\n      memset(dirtyMask, 0, columnsToUpdate+2);\n\n      for( x = 0 ; x < columnsToUpdate ; x++)\n        {\n          if ( newLine[x] != currentLine[x] )\n            {\n              dirtyMask[x] = true;\n            }\n        }\n\n      if (!_resizing) // not while _resizing, we're expecting a paintEvent\n        for (x = 0; x < columnsToUpdate; x++)\n          {\n            _hasBlinker |= (newLine[x].rendition & RE_BLINK);\n\n            // Start drawing if this character or the next one differs.\n            // We also take the next one into account to handle the situation\n            // where characters exceed their cell width.\n            if (dirtyMask[x])\n              {\n                quint16 c = newLine[x+0].character;\n                if ( !c )\n                  continue;\n                int p = 0;\n                disstrU[p++] = c; //fontMap(c);\n                bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0);\n                cr = newLine[x].rendition;\n                _clipboard = newLine[x].backgroundColor;\n                if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor;\n                int lln = columnsToUpdate - x;\n                for (len = 1; len < lln; len++)\n                  {\n                    const Character& ch = newLine[x+len];\n\n                    if (!ch.character)\n                      continue; // Skip trailing part of multi-col chars.\n\n                    bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ? false : (newLine[x+len+1].character == 0);\n\n                    if (  ch.foregroundColor != cf ||\n                          ch.backgroundColor != _clipboard ||\n                          ch.rendition != cr ||\n                          !dirtyMask[x+len] ||\n                          nextIsDoubleWidth != doubleWidth )\n                      break;\n\n                    disstrU[p++] = c; //fontMap(c);\n                  }\n\n                QString unistr(disstrU, p);\n\n                bool saveFixedFont = _fixedFont;\n                if (doubleWidth)\n                  _fixedFont = false;\n\n                updateLine = true;\n\n                _fixedFont = saveFixedFont;\n                x += len - 1;\n              }\n\n          }\n\n      //both the top and bottom halves of double height _lines must always be redrawn\n      //although both top and bottom halves contain the same characters, only\n      //the top one is actually\n      //drawn.\n      if (_lineProperties.count() > y)\n        updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT);\n\n      // if the characters on the line are different in the old and the new _image\n      // then this line must be repainted.\n      if (updateLine)\n        {\n          dirtyLineCount++;\n\n          // add the area occupied by this line to the region which needs to be\n          // repainted\n          QRect dirtyRect = QRect( _leftMargin+tLx ,\n                                   _topMargin+tLy+_fontHeight*y ,\n                                   _fontWidth * columnsToUpdate ,\n                                   _fontHeight );\n\n          dirtyRegion |= dirtyRect;\n        }\n\n      // replace the line of characters in the old _image with the\n      // current line of the new _image\n      memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character));\n    }\n\n  // if the new _image is smaller than the previous _image, then ensure that the area\n  // outside the new _image is cleared\n  if ( linesToUpdate < _usedLines )\n    {\n      dirtyRegion |= QRect(   _leftMargin+tLx ,\n                              _topMargin+tLy+_fontHeight*linesToUpdate ,\n                              _fontWidth * this->_columns ,\n                              _fontHeight * (_usedLines-linesToUpdate) );\n    }\n  _usedLines = linesToUpdate;\n\n  if ( columnsToUpdate < _usedColumns )\n    {\n      dirtyRegion |= QRect(   _leftMargin+tLx+columnsToUpdate*_fontWidth ,\n                              _topMargin+tLy ,\n                              _fontWidth * (_usedColumns-columnsToUpdate) ,\n                              _fontHeight * this->_lines );\n    }\n  _usedColumns = columnsToUpdate;\n\n  dirtyRegion |= _inputMethodData.previousPreeditRect;\n\n  // update the parts of the display which have changed\n  update(dirtyRegion);\n\n  if ( _hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start( BLINK_DELAY );\n  if (!_hasBlinker && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; }\n  delete[] dirtyMask;\n  delete[] disstrU;\n\n}\n\nvoid TerminalView::showResizeNotification()\n{\n  if (_terminalSizeHint && isVisible())\n    {\n      if (_terminalSizeStartup) {\n          _terminalSizeStartup=false;\n          return;\n        }\n      if (!_resizeWidget)\n        {\n          _resizeWidget = new QLabel((\"Size: XXX x XXX\"), this);\n          _resizeWidget->setMinimumWidth(octave::qt_fontmetrics_horizontal_advance(_resizeWidget->fontMetrics(), \"Size: XXX x XXX\"));\n          _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height());\n          _resizeWidget->setAlignment(Qt::AlignCenter);\n\n          _resizeWidget->setStyleSheet(\"background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)\");\n\n          _resizeTimer = new QTimer(this);\n          _resizeTimer->setSingleShot(true);\n          connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide()));\n\n        }\n      QString sizeStr = QString(\"Size: %1 x %2\").arg(_columns).arg(_lines);\n      _resizeWidget->setText(sizeStr);\n      _resizeWidget->move((width()-_resizeWidget->width())/2,\n                          (height()-_resizeWidget->height())/2+20);\n      _resizeWidget->show();\n      _resizeTimer->start(1000);\n    }\n}\n\nvoid TerminalView::setBlinkingCursor(bool blink)\n{\n  _hasBlinkingCursor=blink;\n\n  setBlinkingCursorState(blink);\n}\n\nvoid TerminalView::setBlinkingCursorState(bool blink)\n{\n  if (blink && !_blinkCursorTimer->isActive())\n    _blinkCursorTimer->start(BLINK_DELAY);\n\n  if (!blink && _blinkCursorTimer->isActive())\n    {\n      _blinkCursorTimer->stop();\n      if (_cursorBlinking)\n        blinkCursorEvent();\n    }\n}\n\nvoid TerminalView::paintEvent( QPaintEvent* pe )\n{\n  updateImage();\n  //qDebug(\"%s %d paintEvent\", __FILE__, __LINE__);\n  QPainter paint(this);\n  //qDebug(\"%s %d paintEvent %d %d\", __FILE__, __LINE__, paint.window().top(), paint.window().right());\n\n#if defined (HAVE_QREGION_ITERATORS)\n  for (QRect rect : (pe->region() & contentsRect()))\n#else\n  Q_FOREACH (QRect rect : (pe->region() & contentsRect()).rects())\n#endif\n    {\n      drawBackground(paint,rect,palette().window().color());\n      drawContents(paint, rect);\n    }\n  //    drawBackground(paint,contentsRect(),palette().background().color(),\ttrue /* use opacity setting */);\n  //    drawContents(paint, contentsRect());\n  drawInputMethodPreeditString(paint,preeditRect());\n  paintFilters(paint);\n  paint.end();\n}\n\nvoid TerminalView::focusInEvent(QFocusEvent *focusEvent)\n{\n  setBlinkingCursorState(true);\n  updateImage();\n  repaint();\n  update();\n\n  QWidget::focusInEvent(focusEvent);\n}\n\nvoid TerminalView::focusOutEvent(QFocusEvent *focusEvent)\n{\n  // Force the cursor to be redrawn.\n  _cursorBlinking = true;\n  setBlinkingCursorState(false);\n\n  QWidget::focusOutEvent(focusEvent);\n}\n\nQPoint TerminalView::cursorPosition() const\n{\n  if (_screenWindow)\n    return _screenWindow->cursorPosition();\n  else\n    return QPoint(0,0);\n}\n\nQRect TerminalView::preeditRect() const\n{\n  const int preeditLength = string_width(_inputMethodData.preeditString);\n\n  if ( preeditLength == 0 )\n    return QRect();\n\n  return QRect(_leftMargin + _fontWidth*cursorPosition().x(),\n               _topMargin + _fontHeight*cursorPosition().y(),\n               _fontWidth*preeditLength,\n               _fontHeight);\n}\n\nvoid TerminalView::drawInputMethodPreeditString(QPainter& painter , const QRect& rect)\n{\n  if ( _inputMethodData.preeditString.isEmpty() ) {\n      return;\n    }\n  const QPoint cursorPos = cursorPosition();\n\n  bool invertColors = false;\n  const QColor background = _colorTable[DEFAULT_BACK_COLOR].color;\n  const QColor foreground = _colorTable[DEFAULT_FORE_COLOR].color;\n  const Character* style = &_image[loc(cursorPos.x(),cursorPos.y())];\n\n  drawBackground(painter,rect,background);\n  drawCursor(painter,rect,foreground,background,invertColors);\n  drawCharacters(painter,rect,_inputMethodData.preeditString,style,invertColors);\n\n  _inputMethodData.previousPreeditRect = rect;\n}\n\nFilterChain* TerminalView::filterChain() const\n{\n  return _filterChain;\n}\n\nvoid TerminalView::paintFilters(QPainter& painter)\n{\n  //qDebug(\"%s %d paintFilters\", __FILE__, __LINE__);\n\n  // get color of character under mouse and use it to draw\n  // lines for filters\n  QPoint cursorPos = mapFromGlobal(QCursor::pos());\n  int cursorLine;\n  int cursorColumn;\n  getCharacterPosition( cursorPos , cursorLine , cursorColumn );\n  Character cursorCharacter = _image[loc(cursorColumn,cursorLine)];\n\n  painter.setPen( QPen(cursorCharacter.foregroundColor.color(colorTable())) );\n\n  // iterate over hotspots identified by the display's currently active filters\n  // and draw appropriate visuals to indicate the presence of the hotspot\n\n  QList<Filter::HotSpot*> spots = _filterChain->hotSpots();\n  QListIterator<Filter::HotSpot*> iter(spots);\n  while (iter.hasNext())\n    {\n      Filter::HotSpot* spot = iter.next();\n\n      for ( int line = spot->startLine() ; line <= spot->endLine() ; line++ )\n        {\n          int startColumn = 0;\n          int endColumn = _columns-1; // TODO use number of _columns which are actually\n          // occupied on this line rather than the width of the\n          // display in _columns\n\n          // ignore whitespace at the end of the lines\n          while ( QChar(_image[loc(endColumn,line)].character).isSpace() && endColumn > 0 )\n            endColumn--;\n\n          // increment here because the column which we want to set 'endColumn' to\n          // is the first whitespace character at the end of the line\n          endColumn++;\n\n          if ( line == spot->startLine() )\n            startColumn = spot->startColumn();\n          if ( line == spot->endLine() )\n            endColumn = spot->endColumn();\n\n          // subtract one pixel from\n          // the right and bottom so that\n          // we do not overdraw adjacent\n          // hotspots\n          //\n          // subtracting one pixel from all sides also prevents an edge case where\n          // moving the mouse outside a link could still leave it underlined\n          // because the check below for the position of the cursor\n          // finds it on the border of the target area\n          QRect r;\n          r.setCoords( startColumn*_fontWidth + 1, line*_fontHeight + 1,\n                       endColumn*_fontWidth - 1, (line+1)*_fontHeight - 1 );\n\n          // Underline link hotspots\n          if ( spot->type() == Filter::Link ||\n               spot->type() == Filter::ErrorLink)\n            {\n              QFontMetrics metrics(font());\n\n              // find the baseline (which is the invisible line that the\n              // characters in the font sit on\n              int baseline = r.bottom() + 1;\n              // find the position of the underline below that\n              int underlinePos = baseline + metrics.underlinePos();\n\n              if (r.contains (mapFromGlobal(QCursor::pos())))\n                {\n                  if (spot->type () == Filter::ErrorLink)\n                    painter.setPen (QColor (255,0,0));\n                  painter.drawLine (r.left(), underlinePos,\n                                    r.right() + 2, underlinePos);\n                }\n            }\n          // Marker hotspots simply have a transparent rectanglular shape\n          // drawn on top of them\n          else if ( spot->type() == Filter::Marker )\n            {\n              //TODO - Do not use a hardcoded colour for this\n              painter.fillRect(r,QBrush(QColor(255,0,0,120)));\n            }\n\n        }\n    }\n}\nvoid TerminalView::drawContents(QPainter &paint, const QRect &rect)\n{\n  //qDebug(\"%s %d drawContents and rect x=%d y=%d w=%d h=%d\", __FILE__, __LINE__, rect.x(), rect.y(),rect.width(),rect.height());\n\n  QPoint topLeft  = contentsRect().topLeft();\n  // Take the topmost vertical position for the view.\n  int topLeftY = topLeft.y();\n\n  // In Konsole, the view has been centered. Don't do that here, since there\n  // are strange hopping effects during a resize when the view does no match\n  // exactly the widget width.\n  // int topLeftX = (_contentWidth - _usedColumns * _fontWidth) / 2;\n  int topLeftX = 0;\n\n  int leftUpperX = qMin(_usedColumns-1, qMax(0, qFloor((rect.left()   - topLeftX - _leftMargin ) / _fontWidth)));\n  int leftUpperY = qMin(_usedLines-1,  qMax(0, qFloor((rect.top()    - topLeftY - _topMargin  ) / _fontHeight)));\n  int rightLowerX = qMin(_usedColumns-1, qMax(0, qFloor((rect.right()  - topLeftX - _leftMargin ) / _fontWidth)));\n  int rightLowerY = qMin(_usedLines-1,  qMax(0, qFloor((rect.bottom() - topLeftY - _topMargin  ) / _fontHeight)));\n\n  const int bufferSize = _usedColumns;\n  QChar *disstrU = new QChar[bufferSize];\n  for (int y = leftUpperY; y <= rightLowerY; y++)\n    {\n      quint16 c = _image[loc(leftUpperX,y)].character;\n      int x = leftUpperX;\n      if(!c && x)\n        x--; // Search for start of multi-column character\n      for (; x <= rightLowerX; x++)\n        {\n          int len = 1;\n          int p = 0;\n\n          // is this a single character or a sequence of characters ?\n          if ( _image[loc(x,y)].rendition & RE_EXTENDED_CHAR )\n            {\n              // sequence of characters\n              ushort extendedCharLength = 0;\n              ushort* chars = ExtendedCharTable::instance\n                  .lookupExtendedChar(_image[loc(x,y)].charSequence,extendedCharLength);\n              for ( int index = 0 ; index < extendedCharLength ; index++ )\n                {\n                  Q_ASSERT( p < bufferSize );\n                  disstrU[p++] = chars[index];\n                }\n            }\n          else\n            {\n              // single character\n              c = _image[loc(x,y)].character;\n              if (c)\n                {\n                  Q_ASSERT( p < bufferSize );\n                  disstrU[p++] = c; //fontMap(c);\n                }\n            }\n\n          bool doubleWidth = (_image[ qMin(loc(x,y)+1,_imageSize) ].character == 0);\n          CharacterColor currentForeground = _image[loc(x,y)].foregroundColor;\n          CharacterColor currentBackground = _image[loc(x,y)].backgroundColor;\n          quint8 currentRendition = _image[loc(x,y)].rendition;\n\n          while (x+len <= rightLowerX &&\n                 _image[loc(x+len,y)].foregroundColor == currentForeground &&\n                 _image[loc(x+len,y)].backgroundColor == currentBackground &&\n                 _image[loc(x+len,y)].rendition == currentRendition &&\n                 (_image[ qMin(loc(x+len,y)+1,_imageSize) ].character == 0) == doubleWidth)\n            {\n              c = _image[loc(x+len,y)].character;\n              if (c)\n                disstrU[p++] = c; //fontMap(c);\n              if (doubleWidth) // assert((_image[loc(x+len,y)+1].character == 0)), see above if condition\n                len++; // Skip trailing part of multi-column character\n              len++;\n            }\n          if ((x+len < _usedColumns) && (!_image[loc(x+len,y)].character))\n            len++; // Adjust for trailing part of multi-column character\n\n          bool save__fixedFont = _fixedFont;\n          if (doubleWidth)\n            _fixedFont = false;\n          QString unistr(disstrU,p);\n\n          if (y < _lineProperties.size())\n            {\n              if (_lineProperties[y] & LINE_DOUBLEWIDTH) {\n                  paint.scale(2,1);\n                }\n\n              if (_lineProperties[y] & LINE_DOUBLEHEIGHT) {\n                  paint.scale(1,2);\n                }\n            }\n\n          // calculate the area in which the text will be drawn\n          QRect textArea = QRect( _leftMargin+topLeftX+_fontWidth*x ,\n                                  _topMargin+topLeftY+_fontHeight*y ,\n                                  _fontWidth*len,\n                                  _fontHeight);\n\n          // move the calculated area to take account of scaling applied to the painter.\n          // the position of the area from the origin (0,0) is scaled\n          // by the opposite of whatever\n          // transformation has been applied to the painter.  this ensures that\n          // painting does actually start from textArea.topLeft()\n          // (instead of textArea.topLeft() * painter-scale)\n          QTransform inverted = paint.transform().inverted();\n          textArea.moveCenter( inverted.map(textArea.center()) );\n\n\n          //paint text fragment\n          drawTextFragment(\tpaint,\n                              textArea,\n                              unistr,\n                              &_image[loc(x,y)] );\n\n\n          _fixedFont = save__fixedFont;\n\n          //reset back to single-width, single-height _lines\n          paint.resetTransform();\n\n          if (y < _lineProperties.size()-1)\n            {\n              //double-height _lines are represented by two adjacent _lines\n              //containing the same characters\n              //both _lines will have the LINE_DOUBLEHEIGHT attribute.\n              //If the current line has the LINE_DOUBLEHEIGHT attribute,\n              //we can therefore skip the next line\n              if (_lineProperties[y] & LINE_DOUBLEHEIGHT)\n                y++;\n            }\n          x += len - 1;\n        } // for x\n    } // for y\n  delete [] disstrU;\n}\n\nvoid TerminalView::blinkEvent()\n{\n  _blinking = !_blinking;\n\n  //TODO:  Optimise to only repaint the areas of the widget\n  // where there is blinking text\n  // rather than repainting the whole widget.\n  update();\n}\n\nQRect TerminalView::imageToWidget(const QRect& imageArea) const\n{\n  //qDebug(\"%s %d imageToWidget\", __FILE__, __LINE__);\n  QRect result;\n  result.setLeft( _leftMargin + _fontWidth * imageArea.left() );\n  result.setTop( _topMargin + _fontHeight * imageArea.top() );\n  result.setWidth( _fontWidth * imageArea.width() );\n  result.setHeight( _fontHeight * imageArea.height() );\n\n  return result;\n}\n\nvoid TerminalView::blinkCursorEvent()\n{\n  if (_hasBlinkingCursor)\n    _cursorBlinking = !_cursorBlinking;\n  else\n    _cursorBlinking = false;\n\n  QRect cursorRect = imageToWidget( QRect(cursorPosition(),QSize(1,1)) );\n\n  update(cursorRect);\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                                  Resizing                                 */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\nvoid TerminalView::resizeEvent(QResizeEvent*)\n{\n  updateImageSize();\n}\n\nvoid TerminalView::propagateSize()\n{\n  if (_isFixedSize)\n    {\n      setSize(_columns, _lines);\n      QWidget::setFixedSize(sizeHint());\n      parentWidget()->adjustSize();\n      parentWidget()->setFixedSize(parentWidget()->sizeHint());\n      return;\n    }\n  if (_image)\n    updateImageSize();\n}\n\nvoid TerminalView::updateImageSize()\n{\n  //qDebug(\"%s %d updateImageSize\", __FILE__, __LINE__);\n  Character* oldimg = _image;\n  int oldlin = _lines;\n  int oldcol = _columns;\n\n  makeImage();\n\n\n  // copy the old image to reduce flicker\n  int lines = qMin(oldlin,_lines);\n  int columns = qMin(oldcol,_columns);\n\n  //qDebug(\"%s %d updateImageSize\", __FILE__, __LINE__);\n  if (oldimg)\n    {\n      for (int line = 0; line < lines; line++)\n        {\n          memcpy((void*)&_image[_columns*line],\n                 (void*)&oldimg[oldcol*line],columns*sizeof(Character));\n        }\n      delete[] oldimg;\n    }\n\n  //qDebug(\"%s %d updateImageSize\", __FILE__, __LINE__);\n  if (_screenWindow)\n    _screenWindow->setWindowLines(_lines);\n\n  _resizing = (oldlin!=_lines) || (oldcol!=_columns);\n\n  if ( _resizing )\n    {\n      //qDebug(\"%s %d updateImageSize\", __FILE__, __LINE__);\n      showResizeNotification();\n#if defined (SIGWINCH)\n      ::raise (SIGWINCH);\n#endif\n      Q_EMIT changedContentSizeSignal(_contentHeight, _contentWidth); // expose resizeEvent\n    }\n  //qDebug(\"%s %d updateImageSize\", __FILE__, __LINE__);\n\n  _resizing = false;\n}\n\n//showEvent and hideEvent are reimplemented here so that it appears to other classes that the\n//display has been resized when the display is hidden or shown.\n//\n//this allows\n//TODO: Perhaps it would be better to have separate signals for show and hide instead of using\n//the same signal as the one for a content size change\nvoid TerminalView::showEvent(QShowEvent*)\n{\n  Q_EMIT changedContentSizeSignal(_contentHeight,_contentWidth);\n}\nvoid TerminalView::hideEvent(QHideEvent*)\n{\n  Q_EMIT changedContentSizeSignal(_contentHeight,_contentWidth);\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                                Scrollbar                                  */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\nvoid TerminalView::scrollBarPositionChanged(int)\n{\n  if ( !_screenWindow )\n    return;\n\n  _screenWindow->scrollTo( _scrollBar->value() );\n\n  // if the thumb has been moved to the bottom of the _scrollBar then set\n  // the display to automatically track new output,\n  // that is, scroll down automatically\n  // to how new _lines as they are added\n  const bool atEndOfOutput = (_scrollBar->value() == _scrollBar->maximum());\n  _screenWindow->setTrackOutput( atEndOfOutput );\n\n  updateImage();\n}\n\nvoid TerminalView::setScroll(int cursor, int slines)\n{\n  //qDebug(\"%s %d setScroll\", __FILE__, __LINE__);\n  // update _scrollBar if the range or value has changed,\n  // otherwise return\n  //\n  // setting the range or value of a _scrollBar will always trigger\n  // a repaint, so it should be avoided if it is not necessary\n  if ( _scrollBar->minimum() == 0                 &&\n       _scrollBar->maximum() == (slines - _lines) &&\n       _scrollBar->value()   == cursor )\n    {\n      return;\n    }\n\n  disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));\n  _scrollBar->setRange(0,slines - _lines);\n  _scrollBar->setSingleStep(1);\n  _scrollBar->setPageStep(_lines);\n  _scrollBar->setValue(cursor);\n  connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));\n}\n\nvoid TerminalView::setScrollBarPosition(ScrollBarPosition position)\n{\n  if (_scrollbarLocation == position) {\n      //      return;\n    }\n\n  if ( position == NoScrollBar )\n    _scrollBar->hide();\n  else\n    _scrollBar->show();\n\n  _topMargin = _leftMargin = 1;\n  _scrollbarLocation = position;\n\n  propagateSize();\n  update();\n}\n\nvoid TerminalView::mousePressEvent(QMouseEvent* ev)\n{\n  if ( _possibleTripleClick && (ev->button()==Qt::LeftButton) ) {\n      mouseTripleClickEvent(ev);\n      return;\n    }\n\n  if ( !contentsRect().contains(ev->pos()) ) return;\n\n  if ( !_screenWindow ) return;\n\n  int charLine;\n  int charColumn;\n  getCharacterPosition(ev->pos(),charLine,charColumn);\n  QPoint pos = QPoint(charColumn,charLine);\n\n  if ( ev->button() == Qt::LeftButton)\n    {\n\n      Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);\n      if ( spot &&\n          (spot->type() == Filter::Link || spot->type() == Filter::ErrorLink))\n        {\n          QList<QAction*> actions = spot->actions ();\n          if (actions.length ())\n            actions.at (0)->activate (QAction::Trigger);\n          return;\n        }\n\n      _lineSelectionMode = false;\n      _wordSelectionMode = false;\n\n      Q_EMIT isBusySelecting(true); // Keep it steady...\n      // Drag only when the Control key is hold\n      bool selected = false;\n\n      // The receiver of the testIsSelected() signal will adjust\n      // 'selected' accordingly.\n      //Q_EMIT testIsSelected(pos.x(), pos.y(), selected);\n\n      selected =  _screenWindow->isSelected(pos.x(),pos.y());\n\n      if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected ) {\n          // The user clicked inside selected text\n          dragInfo.state = diPending;\n          dragInfo.start = ev->pos();\n        }\n      else {\n          // No reason to ever start a drag event\n          dragInfo.state = diNone;\n\n          _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) );\n          _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier);\n\n          if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier))\n            {\n              _screenWindow->clearSelection();\n\n              //Q_EMIT clearSelectionSignal();\n              pos.ry() += _scrollBar->value();\n              _iPntSel = _pntSel = pos;\n              _actSel = 1; // left mouse button pressed but nothing selected yet.\n\n            }\n          else\n            {\n              Q_EMIT mouseSignal( 0, charColumn + 1, charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0);\n            }\n        }\n    }\n  else if ( ev->button() == Qt::MiddleButton )\n    {\n      if ( _mouseMarks || (!_mouseMarks && (ev->modifiers() & Qt::ShiftModifier)) )\n        emitSelection(true,ev->modifiers() & Qt::ControlModifier);\n      else\n        Q_EMIT mouseSignal( 1, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0);\n    }\n  else if ( ev->button() == Qt::RightButton )\n    {\n      if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier))\n        {\n          Q_EMIT configureRequest( this,\n                                 ev->modifiers() & (Qt::ShiftModifier|Qt::ControlModifier),\n                                 ev->pos()\n                                 );\n        }\n      else\n        Q_EMIT mouseSignal( 2, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0);\n    }\n\n  QWidget::mousePressEvent (ev);\n}\n\nQList<QAction*> TerminalView::filterActions(const QPoint& position)\n{\n  int charLine, charColumn;\n  getCharacterPosition(position,charLine,charColumn);\n\n  Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);\n\n  return spot ? spot->actions() : QList<QAction*>();\n}\n\nvoid TerminalView::mouseMoveEvent(QMouseEvent* ev)\n{\n  int charLine = 0;\n  int charColumn = 0;\n\n  QPoint mouse_position = ev->pos ();\n  getCharacterPosition (mouse_position, charLine, charColumn);\n\n  // handle filters\n  // change link hot-spot appearance on mouse-over\n  Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);\n  if ( spot &&\n      (spot->type() == Filter::Link || spot->type() == Filter::ErrorLink))\n    {\n      // change mouse cursor when mouse is over links\n      if (! _mouseOverHotspotArea.isValid())\n        setCursor (Qt::PointingHandCursor);\n\n      QRect previousHotspotArea = _mouseOverHotspotArea;\n      _mouseOverHotspotArea.setCoords( qMin(spot->startColumn() , spot->endColumn()) * _fontWidth,\n                                       spot->startLine() * _fontHeight,\n                                       qMax(spot->startColumn() , spot->endColumn()) * _fontHeight,\n                                       (spot->endLine()+1) * _fontHeight );\n\n      // display tooltips when mousing over links\n      // TODO: Extend this to work with filter types other than links\n      const QString& tooltip = spot->tooltip();\n      if ( !tooltip.isEmpty() )\n        {\n          QToolTip::showText (mapToGlobal (mouse_position), tooltip, this,\n                              _mouseOverHotspotArea );\n        }\n\n      update( _mouseOverHotspotArea | previousHotspotArea );\n    }\n  else if ( _mouseOverHotspotArea.isValid() )\n    {\n      setUsesMouse (true);\n      update( _mouseOverHotspotArea );\n      // set hotspot area to an invalid rectangle\n      _mouseOverHotspotArea = QRect();\n    }\n\n  // for auto-hiding the cursor, we need mouseTracking\n  if (ev->buttons() == Qt::NoButton ) return;\n\n  // if the terminal is interested in mouse movements\n  // then emit a mouse movement signal, unless the shift\n  // key is being held down, which overrides this.\n  if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))\n    {\n      int button = 3;\n      if (ev->buttons() & Qt::LeftButton)\n        button = 0;\n      if (ev->buttons() & Qt::MiddleButton)\n        button = 1;\n      if (ev->buttons() & Qt::RightButton)\n        button = 2;\n\n\n      Q_EMIT mouseSignal( button,\n                        charColumn + 1,\n                        charLine + 1 +_scrollBar->value() -_scrollBar->maximum(),\n                        1 );\n\n      return;\n    }\n\n  if (dragInfo.state == diPending)\n    {\n      // we had a mouse down, but haven't confirmed a drag yet\n      // if the mouse has moved sufficiently, we will confirm\n\n      int distance = 10; //KGlobalSettings::dndEventDelay();\n      if (mouse_position.x () > dragInfo.start.x () + distance\n          || mouse_position.x () < dragInfo.start.x () - distance\n          || mouse_position.y () > dragInfo.start.y () + distance\n          || mouse_position.y () < dragInfo.start.y () - distance)\n        {\n          // we've left the drag square, we can start a real drag operation now\n          Q_EMIT isBusySelecting(false); // Ok.. we can breath again.\n\n          _screenWindow->clearSelection();\n          doDrag();\n        }\n      return;\n    }\n  else if (dragInfo.state == diDragging)\n    {\n      // this isn't technically needed because mouseMoveEvent is suppressed during\n      // Qt drag operations, replaced by dragMoveEvent\n      return;\n    }\n\n  if (_actSel == 0) return;\n\n  // don't extend selection while pasting\n  if (ev->buttons() & Qt::MiddleButton) return;\n\n  extendSelection( ev->pos() );\n}\n\nvoid TerminalView::extendSelection(const QPoint& position) {\n  QPoint pos = position;\n\n  if (!_screenWindow) {\n      return;\n    }\n\n  QPoint tL  = contentsRect().topLeft();\n  int    tLx = tL.x();\n  int    tLy = tL.y();\n  int    scroll = _scrollBar->value();\n\n  // we're in the process of moving the mouse with the left button pressed\n  // the mouse cursor will kept caught within the bounds of the text in\n  // this widget.\n\n  // Adjust position within text area bounds. See FIXME above.\n  if (pos.x() < tLx + _leftMargin) {\n      pos.setX(tLx + _leftMargin);\n    }\n  if (pos.x() > tLx + _leftMargin + _usedColumns * _fontWidth - 1) {\n      pos.setX(tLx + _leftMargin + _usedColumns * _fontWidth);\n    }\n  if (pos.y() < tLy + _topMargin) {\n      pos.setY(tLy + _topMargin);\n    }\n  if (pos.y() > tLy + _topMargin + _usedLines * _fontHeight - 1) {\n      pos.setY(tLy + _topMargin + _usedLines * _fontHeight - 1);\n    }\n\n  if (pos.y() == tLy + _topMargin + _usedLines * _fontHeight - 1) {\n      _scrollBar->setValue(_scrollBar->value() + yMouseScroll); // scrollforward\n    }\n  if (pos.y() == tLy + _topMargin) {\n      _scrollBar->setValue(_scrollBar->value() - yMouseScroll); // scrollback\n    }\n\n  int charColumn = 0;\n  int charLine = 0;\n  getCharacterPosition(pos, charLine, charColumn);\n\n  QPoint here = QPoint(charColumn, charLine);\n  QPoint ohere(here);\n  QPoint _iPntSelCorr = _iPntSel;\n  _iPntSelCorr.ry() -= _scrollBar->value();\n  QPoint _pntSelCorr = _pntSel;\n  _pntSelCorr.ry() -= _scrollBar->value();\n  bool swapping = false;\n\n  if (_wordSelectionMode) {\n      // Extend to word boundaries\n      int i = 0;\n      int selClass = 0;\n\n      bool left_not_right = (here.y() < _iPntSelCorr.y() ||\n                             (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));\n      bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||\n                                 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));\n      swapping = left_not_right != old_left_not_right;\n\n      // Find left (left_not_right ? from here : from start)\n      QPoint left = left_not_right ? here : _iPntSelCorr;\n      i = loc(left.x(), left.y());\n      if (i >= 0 && i <= _imageSize) {\n          selClass = charClass(_image[i].character);\n          while (((left.x() > 0) || (left.y() > 0 && (_lineProperties[left.y() - 1] & LINE_WRAPPED)))\n                 && charClass(_image[i - 1].character) == selClass) {\n              i--;\n              if (left.x() > 0) {\n                  left.rx()--;\n                } else {\n                  left.rx() = _usedColumns - 1;\n                  left.ry()--;\n                }\n            }\n        }\n\n      // Find left (left_not_right ? from start : from here)\n      QPoint right = left_not_right ? _iPntSelCorr : here;\n      i = loc(right.x(), right.y());\n      if (i >= 0 && i <= _imageSize) {\n          selClass = charClass(_image[i].character);\n          while (((right.x() < _usedColumns - 1) || (right.y() < _usedLines - 1 && (_lineProperties[right.y()] & LINE_WRAPPED)))\n                 && charClass(_image[i + 1].character) == selClass) {\n              i++;\n              if (right.x() < _usedColumns - 1) {\n                  right.rx()++;\n                } else {\n                  right.rx() = 0;\n                  right.ry()++;\n                }\n            }\n        }\n\n      // Pick which is start (ohere) and which is extension (here)\n      if (left_not_right) {\n          here = left;\n          ohere = right;\n        } else {\n          here = right;\n          ohere = left;\n        }\n      ohere.rx()++;\n    }\n\n  if (_lineSelectionMode) {\n      // Extend to complete line\n      bool above_not_below = (here.y() < _iPntSelCorr.y());\n\n      QPoint above = above_not_below ? here : _iPntSelCorr;\n      QPoint below = above_not_below ? _iPntSelCorr : here;\n\n      while (above.y() > 0 && (_lineProperties[above.y() - 1] & LINE_WRAPPED)) {\n          above.ry()--;\n        }\n      while (below.y() < _usedLines - 1 && (_lineProperties[below.y()] & LINE_WRAPPED)) {\n          below.ry()++;\n        }\n\n      above.setX(0);\n      below.setX(_usedColumns - 1);\n\n      // Pick which is start (ohere) and which is extension (here)\n      if (above_not_below) {\n          here = above;\n          ohere = below;\n        } else {\n          here = below;\n          ohere = above;\n        }\n\n      QPoint newSelBegin = QPoint(ohere.x(), ohere.y());\n      swapping = !(_tripleSelBegin == newSelBegin);\n      _tripleSelBegin = newSelBegin;\n\n      ohere.rx()++;\n    }\n\n  int offset = 0;\n  if (!_wordSelectionMode && !_lineSelectionMode) {\n      int i = 0;\n      int selClass = 0;\n\n      bool left_not_right = (here.y() < _iPntSelCorr.y() ||\n                             (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));\n      bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||\n                                 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));\n      swapping = left_not_right != old_left_not_right;\n\n      // Find left (left_not_right ? from here : from start)\n      QPoint left = left_not_right ? here : _iPntSelCorr;\n\n      // Find left (left_not_right ? from start : from here)\n      QPoint right = left_not_right ? _iPntSelCorr : here;\n      if (right.x() > 0 && !_columnSelectionMode) {\n          i = loc(right.x(), right.y());\n          if (i >= 0 && i <= _imageSize) {\n              selClass = charClass(_image[i - 1].character);\n              if (selClass == ' ') {\n                  while (right.x() < _usedColumns - 1 && charClass(_image[i + 1].character) == selClass && (right.y() < _usedLines - 1) &&\n                         !(_lineProperties[right.y()] & LINE_WRAPPED)) {\n                      i++;\n                      right.rx()++;\n                    }\n                  if (right.x() < _usedColumns - 1) {\n                      right = left_not_right ? _iPntSelCorr : here;\n                    } else {\n                      right.rx()++;  // will be balanced later because of offset=-1;\n                    }\n                }\n            }\n        }\n\n      // Pick which is start (ohere) and which is extension (here)\n      if (left_not_right) {\n          here = left;\n          ohere = right;\n          offset = 0;\n        } else {\n          here = right;\n          ohere = left;\n          offset = -1;\n        }\n    }\n\n  if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) {\n      return; // not moved\n    }\n\n  if (here == ohere) {\n      return; // It's not left, it's not right.\n    }\n\n  if (_actSel < 2 || swapping) {\n      if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) {\n          _screenWindow->setSelectionStart(ohere.x(), ohere.y(), true);\n        } else {\n          _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y(), false);\n        }\n\n    }\n\n  _actSel = 2; // within selection\n  _pntSel = here;\n  _pntSel.ry() += _scrollBar->value();\n\n  if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) {\n      _screenWindow->setSelectionEnd(here.x(), here.y());\n    } else {\n      _screenWindow->setSelectionEnd(here.x() + offset, here.y());\n    }\n}\n\nvoid TerminalView::mouseReleaseEvent(QMouseEvent* ev)\n{\n  if ( !_screenWindow )\n    return;\n\n  int charLine;\n  int charColumn;\n  getCharacterPosition(ev->pos(),charLine,charColumn);\n\n  if ( ev->button() == Qt::LeftButton)\n    {\n      Q_EMIT isBusySelecting(false);\n      if(dragInfo.state == diPending)\n        {\n          // We had a drag event pending but never confirmed.  Kill selection\n          _screenWindow->clearSelection();\n          //Q_EMIT clearSelectionSignal();\n        }\n      else\n        {\n          if ( _actSel > 1 )\n            {\n              setSelection(  _screenWindow->selectedText(_preserveLineBreaks)  );\n            }\n\n          _actSel = 0;\n\n          //FIXME: emits a release event even if the mouse is\n          //       outside the range. The procedure used in `mouseMoveEvent'\n          //       applies here, too.\n\n          if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))\n            Q_EMIT mouseSignal( 3, // release\n                              charColumn + 1,\n                              charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0);\n        }\n      dragInfo.state = diNone;\n    }\n\n\n  if ( !_mouseMarks &&\n       ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier))\n        || ev->button() == Qt::MiddleButton) )\n    {\n      Q_EMIT mouseSignal( 3,\n                        charColumn + 1,\n                        charLine + 1 +_scrollBar->value() -_scrollBar->maximum() ,\n                        0);\n    }\n\n  QWidget::mouseReleaseEvent(ev);\n}\n\nvoid TerminalView::getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const\n{\n\n  column = (widgetPoint.x() + _fontWidth/2 -contentsRect().left()-_leftMargin) / _fontWidth;\n  line = (widgetPoint.y()-contentsRect().top()-_topMargin) / _fontHeight;\n\n  if ( line < 0 )\n    line = 0;\n  if ( column < 0 )\n    column = 0;\n\n  if ( line >= _usedLines )\n    line = _usedLines-1;\n\n  // the column value returned can be equal to _usedColumns, which\n  // is the position just after the last character displayed in a line.\n  //\n  // this is required so that the user can select characters in the right-most\n  // column (or left-most for right-to-left input)\n  if ( column > _usedColumns )\n    column = _usedColumns;\n}\n\nvoid TerminalView::updateLineProperties()\n{\n  if ( !_screenWindow )\n    return;\n\n  _lineProperties = _screenWindow->getLineProperties();\n}\n\nvoid TerminalView::mouseDoubleClickEvent(QMouseEvent* ev)\n{\n  if ( ev->button() != Qt::LeftButton) return;\n  if ( !_screenWindow ) return;\n\n  int charLine = 0;\n  int charColumn = 0;\n\n  getCharacterPosition(ev->pos(),charLine,charColumn);\n\n  QPoint pos(charColumn,charLine);\n\n  // pass on double click as two clicks.\n  if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))\n    {\n      // Send just _ONE_ click event, since the first click of the double click\n      // was already sent by the click handler\n      Q_EMIT mouseSignal( 0,\n                        pos.x()+1,\n                        pos.y()+1 +_scrollBar->value() -_scrollBar->maximum(),\n                        0 ); // left button\n      return;\n    }\n\n  _screenWindow->clearSelection();\n  QPoint bgnSel = pos;\n  QPoint endSel = pos;\n  int i = loc(bgnSel.x(),bgnSel.y());\n  _iPntSel = bgnSel;\n  _iPntSel.ry() += _scrollBar->value();\n\n  _wordSelectionMode = true;\n\n  // find word boundaries...\n  int selClass = charClass(_image[i].character);\n  {\n    // find the start of the word\n    int x = bgnSel.x();\n    while ( ((x>0) || (bgnSel.y()>0 && (_lineProperties[bgnSel.y()-1] & LINE_WRAPPED) ))\n            && charClass(_image[i-1].character) == selClass )\n      {\n        i--;\n        if (x>0)\n          x--;\n        else\n          {\n            x=_usedColumns-1;\n            bgnSel.ry()--;\n          }\n      }\n\n    bgnSel.setX(x);\n    _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false );\n\n    // find the end of the word\n    i = loc( endSel.x(), endSel.y() );\n    x = endSel.x();\n    while( ((x<_usedColumns-1) || (endSel.y()<_usedLines-1 && (_lineProperties[endSel.y()] & LINE_WRAPPED) ))\n           && charClass(_image[i+1].character) == selClass )\n      {\n        i++;\n        if (x<_usedColumns-1)\n          x++;\n        else\n          {\n            x=0;\n            endSel.ry()++;\n          }\n      }\n\n    endSel.setX(x);\n\n    // In word selection mode don't select @ (64) if at end of word.\n    if ( ( QChar( _image[i].character ) == '@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) )\n      endSel.setX( x - 1 );\n\n\n    _actSel = 2; // within selection\n\n    _screenWindow->setSelectionEnd( endSel.x() , endSel.y() );\n\n    setSelection( _screenWindow->selectedText(_preserveLineBreaks) );\n  }\n\n  _possibleTripleClick=true;\n\n  QTimer::singleShot(QApplication::doubleClickInterval(),this,\n                     SLOT(tripleClickTimeout()));\n}\n\nvoid TerminalView::wheelEvent( QWheelEvent* ev )\n{\n  if (ev->angleDelta().y() == 0)\n    return;\n\n  if ( _mouseMarks )\n    _scrollBar->event(ev);\n  else\n    {\n      int charLine;\n      int charColumn;\n#if defined (HAVE_QWHEELEVENT_POSITION)\n      QPoint pos = ev->position().toPoint();\n#else\n      QPoint pos = ev->pos();\n#endif\n      getCharacterPosition( pos , charLine , charColumn );\n\n      int delta = ev->angleDelta().y();\n\n      Q_EMIT mouseSignal( delta > 0 ? 4 : 5,\n                        charColumn + 1,\n                        charLine + 1 +_scrollBar->value() -_scrollBar->maximum() ,\n                        0);\n    }\n}\n\nvoid TerminalView::tripleClickTimeout()\n{\n  _possibleTripleClick=false;\n}\n\nvoid TerminalView::mouseTripleClickEvent(QMouseEvent* ev)\n{\n  if ( !_screenWindow ) return;\n\n  int charLine;\n  int charColumn;\n  getCharacterPosition(ev->pos(),charLine,charColumn);\n  _iPntSel = QPoint(charColumn,charLine);\n\n  _screenWindow->clearSelection();\n\n  _lineSelectionMode = true;\n  _wordSelectionMode = false;\n\n  _actSel = 2; // within selection\n  Q_EMIT isBusySelecting(true); // Keep it steady...\n\n  while (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) )\n    _iPntSel.ry()--;\n\n  if (_tripleClickMode == SelectForwardsFromCursor) {\n      // find word boundary start\n      int i = loc(_iPntSel.x(),_iPntSel.y());\n      int selClass = charClass(_image[i].character);\n      int x = _iPntSel.x();\n\n      while ( ((x>0) ||\n               (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) )\n               )\n              && charClass(_image[i-1].character) == selClass )\n        {\n          i--;\n          if (x>0)\n            x--;\n          else\n            {\n              x=_columns-1;\n              _iPntSel.ry()--;\n            }\n        }\n\n      _screenWindow->setSelectionStart( x , _iPntSel.y() , false );\n      _tripleSelBegin = QPoint( x, _iPntSel.y() );\n    }\n  else if (_tripleClickMode == SelectWholeLine) {\n      _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false );\n      _tripleSelBegin = QPoint( 0, _iPntSel.y() );\n    }\n\n  while (_iPntSel.y()<_lines-1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED) )\n    _iPntSel.ry()++;\n\n  _screenWindow->setSelectionEnd( _columns - 1 , _iPntSel.y() );\n\n  setSelection(_screenWindow->selectedText(_preserveLineBreaks));\n\n  _iPntSel.ry() += _scrollBar->value();\n\n  Q_EMIT tripleClicked( _screenWindow->selectedText( _preserveLineBreaks ) );\n}\n\n\nbool TerminalView::focusNextPrevChild( bool next )\n{\n  if (next)\n    return false; // This disables changing the active part in konqueror\n  // when pressing Tab\n  return QWidget::focusNextPrevChild( next );\n}\n\n\nint TerminalView::charClass(quint16 ch) const\n{\n  QChar qch=QChar(ch);\n  if ( qch.isSpace() ) return ' ';\n\n  if ( qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive ) )\n    return 'a';\n\n  // Everything else is weird\n  return 1;\n}\n\nvoid TerminalView::setWordCharacters(const QString& wc)\n{\n  _wordCharacters = wc;\n}\n\nvoid TerminalView::setUsesMouse(bool on)\n{\n  _mouseMarks = on;\n  setCursor( _mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor );\n}\nbool TerminalView::usesMouse() const\n{\n  return _mouseMarks;\n}\n\nvoid TerminalView::setBracketedPasteMode(bool on)\n{\n  _bracketedPasteMode = on;\n}\nbool TerminalView::bracketedPasteMode() const\n{\n    return _bracketedPasteMode;\n}\n\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                               Clipboard                                   */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n#undef KeyPress\n\nvoid TerminalView::emitSelection(bool useXselection,bool appendReturn)\n{\n  if ( !_screenWindow )\n    return;\n\n  // Paste Clipboard by simulating keypress events\n  QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection :\n                                                                 QClipboard::Clipboard);\n  if(appendReturn)\n    text.append(\"\\r\");\n  if ( ! text.isEmpty() )\n    {\n      text.replace(\"\\n\", \"\\r\");\n      if (bracketedPasteMode() && !_disabledBracketedPasteMode)\n        bracketText(text);\n      else if (text.contains (\"\\t\"))\n        {\n          qWarning (\"converting TAB to SPC in pasted text before processing\");\n          text.replace (\"\\t\", \" \");\n        }\n      QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text);\n      Q_EMIT keyPressedSignal(&e); // expose as a big fat keypress event\n\n      _screenWindow->clearSelection();\n    }\n}\n\nvoid TerminalView::bracketText(QString& text)\n{\n    text.prepend(\"\\033[200~\");\n    text.append(\"\\033[201~\");\n}\n\nvoid TerminalView::setSelection(const QString& t)\n{\n  QApplication::clipboard()->setText(t, QClipboard::Selection);\n}\n\nvoid TerminalView::copyClipboard(bool extra_interrupt)\n{\n  if ( !_screenWindow || !hasFocus())\n    return;\n\n  QString text = _screenWindow->selectedText(_preserveLineBreaks);\n\n  if (text.isEmpty ())\n    {\n      if (! extra_interrupt)\n        Q_EMIT interrupt_signal ();\n    }\n  else\n    QApplication::clipboard()->setText(text);\n}\n\nvoid TerminalView::pasteClipboard()\n{\n  if(hasFocus ())\n    {\n      emitSelection(false,false);\n    }\n}\n\nvoid TerminalView::selectAll()\n{\n  if ( !_screenWindow || !hasFocus())\n    return;\n\n  _screenWindow->setSelectionStart(0,-_screenWindow->currentLine(), false);\n  //_screenWindow->setSelectionEnd(_screenWindow->windowColumns(),\n  //                               _screenWindow->windowLines());\n\n  _screenWindow->setSelectionEnd(_screenWindow->columnCount(),\n                                 _screenWindow->windowLines());\n}\n\n\nvoid TerminalView::pasteSelection()\n{\n  emitSelection(true,false);\n}\n\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                                Keyboard                                   */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\nvoid TerminalView::keyPressEvent( QKeyEvent* event )\n{\n  //qDebug(\"%s %d keyPressEvent and key is %d\", __FILE__, __LINE__, event->key());\n\n  bool emitKeyPressSignal = true;\n\n  // Keyboard-based navigation\n  if ( event->modifiers() == Qt::ShiftModifier )\n    {\n      bool update = true;\n\n      if ( event->key() == Qt::Key_PageUp )\n        {\n          //qDebug(\"%s %d pageup\", __FILE__, __LINE__);\n          _screenWindow->scrollBy( ScreenWindow::ScrollPages , -1 );\n        }\n      else if ( event->key() == Qt::Key_PageDown )\n        {\n          //qDebug(\"%s %d pagedown\", __FILE__, __LINE__);\n          _screenWindow->scrollBy( ScreenWindow::ScrollPages , 1 );\n        }\n      else if ( event->key() == Qt::Key_Up )\n        {\n          //qDebug(\"%s %d keyup\", __FILE__, __LINE__);\n          _screenWindow->scrollBy( ScreenWindow::ScrollLines , -1 );\n        }\n      else if ( event->key() == Qt::Key_Down )\n        {\n          //qDebug(\"%s %d keydown\", __FILE__, __LINE__);\n          _screenWindow->scrollBy( ScreenWindow::ScrollLines , 1 );\n        }\n      else {\n          update = false;\n        }\n\n      if ( update )\n        {\n          //qDebug(\"%s %d updating\", __FILE__, __LINE__);\n          _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() );\n\n          updateLineProperties();\n          updateImage();\n\n          // do not send key press to terminal\n          emitKeyPressSignal = false;\n        }\n    }\n\n  _screenWindow->setTrackOutput( true );\n\n  _actSel=0; // Key stroke implies a screen update, so TerminalDisplay won't\n  // know where the current selection is.\n\n  if (_hasBlinkingCursor)\n    {\n      _blinkCursorTimer->start(BLINK_DELAY);\n      if (_cursorBlinking)\n        blinkCursorEvent();\n      else\n        _cursorBlinking = false;\n    }\n\n  if ( emitKeyPressSignal && !_readonly )\n    Q_EMIT keyPressedSignal(event);\n\n  if (_readonly) {\n      event->ignore();\n    }\n  else {\n      event->accept();\n    }\n}\n\nvoid TerminalView::inputMethodEvent( QInputMethodEvent* event )\n{\n  QKeyEvent keyEvent(QEvent::KeyPress,0,Qt::NoModifier,event->commitString());\n  Q_EMIT keyPressedSignal(&keyEvent);\n\n  _inputMethodData.preeditString = event->preeditString();\n  update(preeditRect() | _inputMethodData.previousPreeditRect);\n\n  event->accept();\n}\nQVariant TerminalView::inputMethodQuery( Qt::InputMethodQuery query ) const\n{\n  const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0,0);\n  switch ( query )\n    {\n#if defined (HAVE_QT_IMCURSORRECTANGLE_ENUM_VALUE)\n    case Qt::ImCursorRectangle:\n#else\n    case Qt::ImMicroFocus:\n#endif\n      return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1));\n      break;\n    case Qt::ImFont:\n      return font();\n      break;\n    case Qt::ImCursorPosition:\n      // return the cursor position within the current line\n      return cursorPos.x();\n      break;\n    case Qt::ImSurroundingText:\n      {\n        // return the text from the current line\n        QString lineText;\n        QTextStream stream(&lineText);\n        PlainTextDecoder decoder;\n        decoder.begin(&stream);\n        decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]);\n        decoder.end();\n        return lineText;\n      }\n      break;\n    case Qt::ImCurrentSelection:\n      return QString();\n      break;\n    default:\n      break;\n    }\n\n  return QVariant();\n}\n\nvoid TerminalView::setBellMode(int mode)\n{\n  _bellMode=mode;\n}\n\nvoid TerminalView::enableBell()\n{\n  _allowBell = true;\n}\n\nvoid TerminalView::swapColorTable()\n{\n  ColorEntry color = _colorTable[1];\n  _colorTable[1]=_colorTable[0];\n  _colorTable[0]= color;\n  _colorsInverted = !_colorsInverted;\n  update();\n}\n\nvoid TerminalView::clearImage()\n{\n  // We initialize _image[_imageSize] too. See makeImage()\n  for (int i = 0; i <= _imageSize; i++)\n    {\n      _image[i].character = ' ';\n      _image[i].foregroundColor = CharacterColor(COLOR_SPACE_DEFAULT,\n                                                 DEFAULT_FORE_COLOR);\n      _image[i].backgroundColor = CharacterColor(COLOR_SPACE_DEFAULT,\n                                                 DEFAULT_BACK_COLOR);\n      _image[i].rendition = DEFAULT_RENDITION;\n    }\n}\n\nvoid TerminalView::calcGeometry()\n{\n  _scrollBar->resize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent),\n                     contentsRect().height());\n  switch(_scrollbarLocation)\n    {\n    case NoScrollBar :\n      _leftMargin = DEFAULT_LEFT_MARGIN;\n      _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN;\n      break;\n    case ScrollBarLeft :\n      _leftMargin = DEFAULT_LEFT_MARGIN + _scrollBar->width();\n      _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width();\n      _scrollBar->move(contentsRect().topLeft());\n      break;\n    case ScrollBarRight:\n      _leftMargin = DEFAULT_LEFT_MARGIN;\n      _contentWidth = contentsRect().width()  - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width();\n      _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width()-1,0));\n      break;\n    }\n\n  _topMargin = DEFAULT_TOP_MARGIN;\n  _contentHeight = contentsRect().height() - 2 * DEFAULT_TOP_MARGIN + /* mysterious */ 1;\n\n  if (!_isFixedSize)\n    {\n      // ensure that display is always at least one column wide\n      _columns = qMax(1,qFloor(_contentWidth / _fontWidth));\n      _usedColumns = qMin(_usedColumns,_columns);\n\n      // ensure that display is always at least one line high\n      _lines = qMax(1, qFloor(_contentHeight / _fontHeight));\n      _usedLines = qMin(_usedLines,_lines);\n    }\n}\n\nvoid TerminalView::makeImage()\n{\n  //qDebug(\"%s %d makeImage\", __FILE__, __LINE__);\n  calcGeometry();\n\n  // confirm that array will be of non-zero size, since the painting code\n  // assumes a non-zero array length\n  Q_ASSERT( _lines > 0 && _columns > 0 );\n  Q_ASSERT( _usedLines <= _lines && _usedColumns <= _columns );\n\n  _imageSize=_lines*_columns;\n\n  // We over-commit one character so that we can be more relaxed in dealing with\n  // certain boundary conditions: _image[_imageSize] is a valid but unused position\n  _image = new Character[_imageSize+1];\n\n  clearImage();\n}\n\n// calculate the needed size\nvoid TerminalView::setSize(int columns, int lines)\n{\n  //FIXME - Not quite correct, a small amount of additional space\n  // will be used for margins, the scrollbar etc.\n  // we need to allow for this so that '_size' does allow\n  // enough room for the specified number of columns and lines to fit\n\n  QSize newSize = QSize( columns * _fontWidth  ,\n                         lines * _fontHeight   );\n\n  if ( newSize != size() )\n    {\n      _size = newSize;\n      updateGeometry();\n    }\n}\n\nvoid TerminalView::setFixedSize(int cols, int lins)\n{\n  _isFixedSize = true;\n\n  //ensure that display is at least one line by one column in size\n  _columns = qMax(1,cols);\n  _lines = qMax(1,lins);\n  _usedColumns = qMin(_usedColumns,_columns);\n  _usedLines = qMin(_usedLines,_lines);\n\n  if (_image)\n    {\n      delete[] _image;\n      makeImage();\n    }\n  setSize(cols, lins);\n  QWidget::setFixedSize(_size);\n}\n\nQSize TerminalView::sizeHint() const\n{\n  return _size;\n}\n\n\n/* --------------------------------------------------------------------- */\n/*                                                                       */\n/* Drag & Drop                                                           */\n/*                                                                       */\n/* --------------------------------------------------------------------- */\n\nvoid TerminalView::dragEnterEvent(QDragEnterEvent* event)\n{\n  if (event->mimeData()->hasFormat(\"text/plain\"))\n    event->acceptProposedAction();\n}\n\nvoid TerminalView::dropEvent(QDropEvent* event)\n{\n  //  KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());\n\n  QString dropText;\n\n  if (event->mimeData ()->hasUrls ())\n  {\n    for (QUrl url : event->mimeData ()->urls ())\n    {\n      if(dropText.length () > 0)\n        dropText += '\\n';\n      dropText  += url.toLocalFile ();\n    }\n  }\n\n  /*  if (!urls.isEmpty())\n  {\n    for ( int i = 0 ; i < urls.count() ; i++ )\n    {\n        KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 );\n        QString urlText;\n\n        if (url.isLocalFile())\n            urlText = url.path();\n        else\n            urlText = url.url();\n\n        // in future it may be useful to be able to insert file names with drag-and-drop\n        // without quoting them (this only affects paths with spaces in)\n        urlText = KShell::quoteArg(urlText);\n\n        dropText += urlText;\n\n        if ( i != urls.count()-1 )\n            dropText += ' ';\n    }\n  }\n  else\n  {\n    dropText = event->mimeData()->text();\n  }\n*/\n  if(event->mimeData()->hasFormat(\"text/plain\"))\n    {\n      Q_EMIT sendStringToEmu(dropText.toLocal8Bit());\n    }\n}\n\nvoid TerminalView::doDrag()\n{\n  dragInfo.state = diDragging;\n  dragInfo.dragObject = new QDrag(this);\n  QMimeData *mimeData = new QMimeData;\n  mimeData->setText(QApplication::clipboard()->text(QClipboard::Selection));\n  dragInfo.dragObject->setMimeData(mimeData);\n  dragInfo.dragObject->exec(Qt::CopyAction);\n  // Don't delete the QTextDrag object.  Qt will delete it when it's done with it.\n}\n\nvoid TerminalView::outputSuspended(bool suspended)\n{\n  //create the label when this function is first called\n  if (!_outputSuspendedLabel)\n    {\n      //This label includes a link to an English language website\n      //describing the 'flow control' (Xon/Xoff) feature found in almost\n      //all terminal emulators.\n      //If there isn't a suitable article available in the target language the link\n      //can simply be removed.\n      _outputSuspendedLabel = new QLabel( (\"<qt>Output has been \"\n                                           \"<a href=\\\"http://en.wikipedia.org/wiki/XON\\\">suspended</a>\"\n                                           \" by pressing Ctrl+S.\"\n                                           \"  Press <b>Ctrl+Q</b> to resume.</qt>\"),\n                                          this );\n\n      QPalette palette(_outputSuspendedLabel->palette());\n\n      palette.setColor(QPalette::Normal, QPalette::WindowText, QColor(Qt::white));\n      palette.setColor(QPalette::Normal, QPalette::Window, QColor(Qt::black));\n      //            KColorScheme::adjustForeground(palette,KColorScheme::NeutralText);\n      //\t\tKColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground);\n      _outputSuspendedLabel->setPalette(palette);\n      _outputSuspendedLabel->setAutoFillBackground(true);\n      _outputSuspendedLabel->setBackgroundRole(QPalette::Base);\n      _outputSuspendedLabel->setFont(QApplication::font());\n      _outputSuspendedLabel->setMargin(5);\n\n      //enable activation of \"Xon/Xoff\" link in label\n      _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse |\n                                                     Qt::LinksAccessibleByKeyboard);\n      _outputSuspendedLabel->setOpenExternalLinks(true);\n      _outputSuspendedLabel->setVisible(false);\n\n      _gridLayout->addWidget(_outputSuspendedLabel);\n      _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding,\n                                            QSizePolicy::Expanding),\n                            1,0);\n\n    }\n\n  _outputSuspendedLabel->setVisible(suspended);\n}\n\nuint TerminalView::lineSpacing() const\n{\n  return _lineSpacing;\n}\n\nvoid TerminalView::setLineSpacing(uint i)\n{\n  _lineSpacing = i;\n  setVTFont(font()); // Trigger an update.\n}\n\nQString TerminalView::selectedText ()\n{\n  QString text = _screenWindow->selectedText (_preserveLineBreaks);\n  return text;\n}\n\nvoid\nTerminalView::visibility_changed (bool visible)\n{\n  // Disable the timer for processing the filter chain, since this might time\n  // consuming\n  if (visible)\n    _process_filter_timer->start (300);\n  else\n    _process_filter_timer->stop ();\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/TerminalView.h",
    "content": "/*\n    Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n    Copyright (C) 2012-2019 Jacob Dawid <jacob.dawid@cybercatalyst.com>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef TERMINALVIEW_H\n#define TERMINALVIEW_H\n\n// Qt\n#include <QColor>\n#include <QPointer>\n#include <QWidget>\n\n// Konsole\n#include \"unix/Filter.h\"\n#include \"unix/Character.h\"\n\nclass QDrag;\nclass QDragEnterEvent;\nclass QDropEvent;\nclass QLabel;\nclass QTimer;\nclass QEvent;\nclass QFrame;\nclass QGridLayout;\nclass QKeyEvent;\nclass QScrollBar;\nclass QShowEvent;\nclass QHideEvent;\nclass QWidget;\n\nextern unsigned short vt100_graphics[32];\n\nclass ScreenWindow;\n\n/**\n * A widget which displays output from a terminal emulation and sends input keypresses and mouse activity\n * to the terminal.\n *\n * When the terminal emulation receives new output from the program running in the terminal,\n * it will update the display by calling updateImage().\n *\n * TODO More documentation\n */\nclass TerminalView : public QWidget\n{\n   Q_OBJECT\n\npublic:\n    /** Constructs a new terminal display widget with the specified parent. */\n    TerminalView(QWidget *parent = nullptr);\n    virtual ~TerminalView();\n\n    /** Returns the terminal color palette used by the display. */\n    const ColorEntry* colorTable() const;\n    /** Sets the terminal color palette used by the display. */\n    void setColorTable(const ColorEntry table[]);\n    /**\n     * Sets the seed used to generate random colors for the display\n     * (in color schemes that support them).\n     */\n    void setRandomSeed(uint seed);\n    /**\n     * Returns the seed used to generate random colors for the display\n     * (in color schemes that support them).\n     */\n    uint randomSeed() const;\n\n\n    /**\n     * This enum describes the location where the scroll bar is positioned in the display widget.\n     */\n    enum ScrollBarPosition\n    {\n        /** Do not show the scroll bar. */\n        NoScrollBar=0,\n        /** Show the scroll bar on the left side of the display. */\n        ScrollBarLeft=1,\n        /** Show the scroll bar on the right side of the display. */\n        ScrollBarRight=2\n    };\n    /**\n     * Specifies whether the terminal display has a vertical scroll bar, and if so whether it\n     * is shown on the left or right side of the display.\n     */\n    void setScrollBarPosition(ScrollBarPosition position);\n\n    /**\n     * Sets the current position and range of the display's scroll bar.\n     *\n     * @param cursor The position of the scroll bar's thumb.\n     * @param lines The maximum value of the scroll bar.\n     */\n    void setScroll(int cursor, int lines);\n\n    /**\n     * Returns the display's filter chain.  When the image for the display is updated,\n     * the text is passed through each filter in the chain.  Each filter can define\n     * hotspots which correspond to certain strings (such as URLs or particular words).\n     * Depending on the type of the hotspots created by the filter ( returned by Filter::Hotspot::type() )\n     * the view will draw visual cues such as underlines on mouse-over for links or translucent\n     * rectangles for markers.\n     *\n     * To add a new filter to the view, call:\n     *      viewWidget->filterChain()->addFilter( filterObject );\n     */\n    FilterChain* filterChain() const;\n\n    /**\n     * Returns a list of menu actions created by the filters for the content\n     * at the given @p position.\n     */\n    QList<QAction*> filterActions(const QPoint& position);\n\n    /** Returns true if the cursor is set to blink or false otherwise. */\n    bool blinkingCursor() { return _hasBlinkingCursor; }\n    /** Specifies whether or not the cursor blinks. */\n    void setBlinkingCursor(bool blink);\n    void setBlinkingCursorState(bool blink);\n\n    void setCtrlDrag(bool enable) { _ctrlDrag=enable; }\n    bool ctrlDrag() { return _ctrlDrag; }\n\n   /**\n     *  This enum describes the methods for selecting text when\n    *  the user triple-clicks within the display.\n    */\n   enum TripleClickMode\n   {\n      /** Select the whole line underneath the cursor. */\n      SelectWholeLine,\n      /** Select from the current cursor position to the end of the line. */\n      SelectForwardsFromCursor\n   };\n    /** Sets how the text is selected when the user triple clicks within the display. */\n    void setTripleClickMode(TripleClickMode mode) { _tripleClickMode = mode; }\n   /** See setTripleClickSelectionMode() */\n    TripleClickMode tripleClickMode() { return _tripleClickMode; }\n\n    void setLineSpacing(uint);\n    uint lineSpacing() const;\n\n    void emitSelection(bool useXselection,bool appendReturn);\n\n    /** change and wrap text corresponding to paste mode **/\n    void bracketText(QString& text);\n\n    /**\n     * This enum describes the available shapes for the keyboard cursor.\n     * See setKeyboardCursorShape()\n     */\n    enum KeyboardCursorShape\n    {\n        /** A rectangular block which covers the entire area of the cursor character. */\n        BlockCursor,\n        /**\n         * A single flat line which occupies the space at the bottom of the cursor\n         * character's area.\n         */\n        UnderlineCursor,\n        /**\n         * An cursor shaped like the capital letter 'I', similar to the IBeam\n         * cursor used in Qt/KDE text editors.\n         */\n        IBeamCursor\n    };\n    /**\n     * Sets the shape of the keyboard cursor.  This is the cursor drawn\n     * at the position in the terminal where keyboard input will appear.\n     *\n     * In addition the terminal display widget also has a cursor for\n     * the mouse pointer, which can be set using the QWidget::setCursor()\n     * method.\n     *\n     * Defaults to BlockCursor\n     */\n    void setKeyboardCursorShape(KeyboardCursorShape shape);\n    /**\n     * Returns the shape of the keyboard cursor.  See setKeyboardCursorShape()\n     */\n    KeyboardCursorShape keyboardCursorShape() const;\n\n    /**\n     * Sets the color used to draw the keyboard cursor.\n     *\n     * The keyboard cursor defaults to using the foreground color of the character\n     * underneath it.\n     *\n     * @param useForegroundColor If true, the cursor color will change to match\n     * the foreground color of the character underneath it as it is moved, in this\n     * case, the @p color parameter is ignored and the color of the character\n     * under the cursor is inverted to ensure that it is still readable.\n     * @param color The color to use to draw the cursor.  This is only taken into\n     * account if @p useForegroundColor is false.\n     */\n    void setKeyboardCursorColor(bool useForegroundColor , const QColor& color);\n\n    /**\n     * Returns the color of the keyboard cursor, or an invalid color if the keyboard\n     * cursor color is set to change according to the foreground color of the character\n     * underneath it.\n     */\n    QColor keyboardCursorColor() const;\n\n    /**\n     * Returns the number of lines of text which can be displayed in the widget.\n     *\n     * This will depend upon the height of the widget and the current font.\n     * See fontHeight()\n     */\n    int  lines()   { return _lines;   }\n    /**\n     * Returns the number of characters of text which can be displayed on\n     * each line in the widget.\n     *\n     * This will depend upon the width of the widget and the current font.\n     * See fontWidth()\n     */\n    int  columns() { return _columns; }\n\n    /**\n     * Returns the height of the characters in the font used to draw the text in the display.\n     */\n    int  fontHeight()   { return _fontHeight;   }\n    /**\n     * Returns the width of the characters in the display.\n     * This assumes the use of a fixed-width font.\n     */\n    int  fontWidth()    { return _fontWidth; }\n\n    void setSize(int cols, int lins);\n    void setFixedSize(int cols, int lins);\n\n    // reimplemented\n    QSize sizeHint() const;\n\n    /**\n     * Sets which characters, in addition to letters and numbers,\n     * are regarded as being part of a word for the purposes\n     * of selecting words in the display by double clicking on them.\n     *\n     * The word boundaries occur at the first and last characters which\n     * are either a letter, number, or a character in @p wc\n     *\n     * @param wc An array of characters which are to be considered parts\n     * of a word ( in addition to letters and numbers ).\n     */\n    void setWordCharacters(const QString& wc);\n    /**\n     * Returns the characters which are considered part of a word for the\n     * purpose of selecting words in the display with the mouse.\n     *\n     * @see setWordCharacters()\n     */\n    QString wordCharacters() { return _wordCharacters; }\n\n    /**\n     * Sets the type of effect used to alert the user when a 'bell' occurs in the\n     * terminal session.\n     *\n     * The terminal session can trigger the bell effect by calling bell() with\n     * the alert message.\n     */\n    void setBellMode(int mode);\n    /**\n     * Returns the type of effect used to alert the user when a 'bell' occurs in\n     * the terminal session.\n     *\n     * See setBellMode()\n     */\n    int bellMode() { return _bellMode; }\n\n    /**\n     * This enum describes the different types of sounds and visual effects which\n     * can be used to alert the user when a 'bell' occurs in the terminal\n     * session.\n     */\n    enum BellMode\n    {\n        /** A system beep. */\n        SystemBeepBell=0,\n        /**\n         * KDE notification.  This may play a sound, show a passive popup\n         * or perform some other action depending on the user's settings.\n         */\n        NotifyBell=1,\n        /** A silent, visual bell (eg. inverting the display's colors briefly) */\n        VisualBell=2,\n        /** No bell effects */\n        NoBell=3\n    };\n\n    void setSelection(const QString &t);\n\n    QString selectedText ();\n\n    /**\n     * Reimplemented.  Has no effect.  Use setVTFont() to change the font\n     * used to draw characters in the display.\n     */\n    virtual void setFont(const QFont &);\n\n\n    /** Returns the font used to draw characters in the display */\n    QFont getVTFont() { return font(); }\n\n    /**\n     * Sets the font used to draw the display.  Has no effect if @p font\n     * is larger than the size of the display itself.\n     */\n    void setVTFont(const QFont& font);\n\n\n    /**\n     * Specified whether terminal widget should be at read-only mode\n     * Defaults to false.\n     */\n    void setReadOnly( bool readonly) { _readonly = readonly; }\n\n    /**\n     * Specified whether anti-aliasing of text in the terminal display\n     * is enabled or not.  Defaults to enabled.\n     */\n    static void setAntialias( bool antialias ) { _antialiasText = antialias; }\n    /**\n     * Returns true if anti-aliasing of text in the terminal is enabled.\n     */\n    static bool antialias()                 { return _antialiasText;   }\n\n    /**\n     * Sets whether or not the current height and width of the\n     * terminal in lines and columns is displayed whilst the widget\n     * is being resized.\n     */\n    void setTerminalSizeHint(bool on) { _terminalSizeHint=on; }\n    /**\n     * Returns whether or not the current height and width of\n     * the terminal in lines and columns is displayed whilst the widget\n     * is being resized.\n     */\n    bool terminalSizeHint() { return _terminalSizeHint; }\n    /**\n     * Sets whether the terminal size display is shown briefly\n     * after the widget is first shown.\n     *\n     * See setTerminalSizeHint() , isTerminalSizeHint()\n     */\n    void setTerminalSizeStartup(bool on) { _terminalSizeStartup=on; }\n\n    /**\n     * Sets the terminal screen section which is displayed in this widget.\n     * When updateImage() is called, the display fetches the latest character image from the\n     * the associated terminal screen window.\n     *\n     * In terms of the model-view paradigm, the ScreenWindow is the model which is rendered\n     * by the TerminalDisplay.\n     */\n    void setScreenWindow( ScreenWindow* window );\n    /** Returns the terminal screen section which is displayed in this widget.  See setScreenWindow() */\n    ScreenWindow* screenWindow() const;\n\n    /** Is called, when the terminal's visibility has changed in order to\n     *  stop orstart timers etc.\n     */\n    void visibility_changed (bool visible);\n\n    void disableBracketedPasteMode(bool disable) { _disabledBracketedPasteMode = disable; }\n    bool bracketedPasteModeIsDisabled() const { return _disabledBracketedPasteMode; }\n\npublic Q_SLOTS:\n\n    /**\n     * Updates the filters in the display's filter chain.  This will cause\n     * the hotspots to be updated to match the current image.\n     *\n     * WARNING:  This function can be expensive depending on the\n     * image size and number of filters in the filterChain()\n     *\n     * TODO - This API does not really allow efficient usage.  Revise it so\n     * that the processing can be done in a better way.\n     *\n     * eg:\n     *      - Area of interest may be known ( eg. mouse cursor hovering\n     *      over an area )\n     */\n    void processFilters();\n\n    /**\n     * Causes the terminal display to fetch the latest character image from the associated\n     * terminal screen ( see setScreenWindow() ) and redraw the display.\n     */\n    void updateImage();\n    /**\n     * Causes the terminal display to fetch the latest line status flags from the\n     * associated terminal screen ( see setScreenWindow() ).\n     */\n    void updateLineProperties();\n\n    /** Copies the selected text to the clipboard. */\n    void copyClipboard (bool extra_interrupt);\n    /**\n     * Pastes the content of the clipboard into the\n     * display.\n     */\n    void pasteClipboard();\n    /**\n     * Pastes the content of the selection into the\n     * display.\n     */\n    void pasteSelection();\n\n    /**\n     * selects all content\n     */\n    void selectAll();\n\n\t /**\n\t * Causes the widget to display or hide a message informing the user that terminal\n\t * output has been suspended (by using the flow control key combination Ctrl+S)\n\t *\n\t * @param suspended True if terminal output has been suspended and the warning message should\n\t *\t\t\t\t \tbe shown or false to indicate that terminal output has been resumed and that\n\t *\t\t\t\t \tthe warning message should disappear.\n\t */\n\tvoid outputSuspended(bool suspended);\n\n    /**\n     * Sets whether the program whoose output is being displayed in the view\n     * is interested in mouse events.\n     *\n     * If this is set to true, mouse signals will be emitted by the view when the user clicks, drags\n     * or otherwise moves the mouse inside the view.\n     * The user interaction needed to create selections will also change, and the user will be required\n     * to hold down the shift key to create a selection or perform other mouse activities inside the\n     * view area - since the program running in the terminal is being allowed to handle normal mouse\n     * events itself.\n     *\n     * @param usesMouse Set to true if the program running in the terminal is interested in mouse events\n     * or false otherwise.\n     */\n    void setUsesMouse(bool usesMouse);\n\n    /** See setUsesMouse() */\n    bool usesMouse() const;\n\n    void setBracketedPasteMode(bool bracketedPasteMode);\n    bool bracketedPasteMode() const;\n\nQ_SIGNALS:\n\n    void interrupt_signal ();\n\n    /**\n     * Emitted when the user presses a key whilst the terminal widget has focus.\n     */\n    void keyPressedSignal(QKeyEvent *e);\n\n    /**\n     * A mouse event occurred.\n     * @param button The mouse button (0 for left button, 1 for middle button, 2 for right button, 3 for release)\n     * @param column The character column where the event occurred\n     * @param line The character row where the event occurred\n     * @param eventType The type of event.  0 for a mouse press / release or 1 for mouse motion\n     */\n    void mouseSignal(int button, int column, int line, int eventType);\n    void changedFontMetricSignal(int height, int width);\n    void changedContentSizeSignal(int height, int width);\n\n    /**\n     * Emitted when the user right clicks on the display, or right-clicks with the Shift\n     * key held down if usesMouse() is true.\n     *\n     * This can be used to display a context menu.\n     */\n    void configureRequest( TerminalView*, int state, const QPoint& position );\n\n   void isBusySelecting(bool);\n   void sendStringToEmu(const char*);\n\n   void tripleClicked( const QString& text );\n\nprotected:\n    virtual void paintEvent( QPaintEvent * );\n\n    void focusInEvent(QFocusEvent *focusEvent);\n    void focusOutEvent(QFocusEvent *focusEvent);\n\n    virtual void showEvent(QShowEvent*);\n    virtual void hideEvent(QHideEvent*);\n    virtual void resizeEvent(QResizeEvent*);\n\n    virtual void fontChange(const QFont &font);\n\n    virtual void keyPressEvent(QKeyEvent* event);\n    virtual void mouseDoubleClickEvent(QMouseEvent* ev);\n    virtual void mousePressEvent( QMouseEvent* );\n    virtual void mouseReleaseEvent( QMouseEvent* );\n    virtual void mouseMoveEvent( QMouseEvent* );\n    virtual void extendSelection( const QPoint& pos );\n    virtual void wheelEvent( QWheelEvent* );\n\n    virtual bool focusNextPrevChild( bool next );\n\n    // drag and drop\n    virtual void dragEnterEvent(QDragEnterEvent* event);\n    virtual void dropEvent(QDropEvent* event);\n    void doDrag();\n    enum DragState { diNone, diPending, diDragging };\n\n    struct _dragInfo {\n      DragState       state;\n      QPoint          start;\n      QDrag           *dragObject;\n    } dragInfo;\n\n    virtual int charClass(quint16) const;\n\n    void clearImage();\n\n    void mouseTripleClickEvent(QMouseEvent* ev);\n\n    // reimplemented\n    virtual void inputMethodEvent ( QInputMethodEvent* event );\n    virtual QVariant inputMethodQuery( Qt::InputMethodQuery query ) const;\n\nprotected Q_SLOTS:\n\n    void scrollBarPositionChanged(int value);\n    void blinkEvent();\n    void blinkCursorEvent();\n\n    //Renables bell noises and visuals.  Used to disable further bells for a short period of time\n    //after emitting the first in a sequence of bell events.\n    void enableBell();\n\nprivate Q_SLOTS:\n\n    void swapColorTable();\n    void tripleClickTimeout();  // resets possibleTripleClick\n\nprivate:\n\n    // -- Drawing helpers --\n\n    // divides the part of the display specified by 'rect' into\n    // fragments according to their colors and styles and calls\n    // drawTextFragment() to draw the fragments\n    void drawContents(QPainter &paint, const QRect &rect);\n    // draws a section of text, all the text in this section\n    // has a common color and style\n    void drawTextFragment(QPainter& painter, const QRect& rect,\n                          const QString& text, const Character* style);\n    // draws the background for a text fragment\n    // if useOpacitySetting is true then the color's alpha value will be set to\n    // the display's transparency (set with setOpacity()), otherwise the background\n    // will be drawn fully opaque\n    void drawBackground(QPainter& painter, const QRect& rect, const QColor& color);\n    // draws the cursor character\n    void drawCursor(QPainter& painter, const QRect& rect , const QColor& foregroundColor,\n                                       const QColor& backgroundColor , bool& invertColors);\n    // draws the characters or line graphics in a text fragment\n    void drawCharacters(QPainter& painter, const QRect& rect,  const QString& text,\n                                           const Character* style, bool invertCharacterColor);\n\n    // draws the preedit string for input methods\n    void drawInputMethodPreeditString(QPainter& painter , const QRect& rect);\n\n    // --\n\n    // maps an area in the character image to an area on the widget\n    QRect imageToWidget(const QRect& imageArea) const;\n\n    // maps a point on the widget to the position ( ie. line and column )\n    // of the character at that point.\n    void getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const;\n\n    // the area where the preedit string for input methods will be draw\n    QRect preeditRect() const;\n\n    // shows a notification window in the middle of the widget indicating the terminal's\n    // current size in columns and lines\n    void showResizeNotification();\n\n    // scrolls the image by a number of lines.\n    // 'lines' may be positive ( to scroll the image down )\n    // or negative ( to scroll the image up )\n    // 'region' is the part of the image to scroll - currently only\n    // the top, bottom and height of 'region' are taken into account,\n    // the left and right are ignored.\n    void scrollImage(int lines , const QRect& region);\n\n    void calcGeometry();\n    void propagateSize();\n    void updateImageSize();\n    void makeImage();\n\n    void paintFilters(QPainter& painter);\n\n\t// returns a region covering all of the areas of the widget which contain\n\t// a hotspot\n\tQRegion hotSpotRegion() const;\n\n\t// returns the position of the cursor in columns and lines\n\tQPoint cursorPosition() const;\n\n    // the window onto the terminal screen which this display\n    // is currently showing.\n    QPointer<ScreenWindow> _screenWindow;\n\n    bool _allowBell;\n\n    QGridLayout* _gridLayout;\n\n    bool _fixedFont; // has fixed pitch\n\n    double  _fontHeight;     // height\n    double  _fontWidth;     // width\n    //type double to decrease rounding errors\n\n    int  _fontAscent;     // ascend\n\n    int _leftMargin;    // offset\n    int _topMargin;    // offset\n\n    int _lines;      // the number of lines that can be displayed in the widget\n    int _columns;    // the number of columns that can be displayed in the widget\n\n    int _usedLines;  // the number of lines that are actually being used, this will be less\n                    // than 'lines' if the character image provided with setImage() is smaller\n                    // than the maximum image size which can be displayed\n\n    int _usedColumns; // the number of columns that are actually being used, this will be less\n                     // than 'columns' if the character image provided with setImage() is smaller\n                     // than the maximum image size which can be displayed\n\n    int _contentHeight;\n    int _contentWidth;\n    Character* _image; // [lines][columns]\n               // only the area [usedLines][usedColumns] in the image contains valid data\n\n    int _imageSize;\n    QVector<LineProperty> _lineProperties;\n\n    ColorEntry _colorTable[TABLE_COLORS];\n    uint _randomSeed;\n\n    bool _resizing;\n    bool _terminalSizeHint;\n    bool _terminalSizeStartup;\n    bool _mouseMarks;\n    bool _bracketedPasteMode;\n    bool _disabledBracketedPasteMode;\n\n    QPoint  _iPntSel; // initial selection point\n    QPoint  _pntSel; // current selection point\n    QPoint  _tripleSelBegin; // help avoid flicker\n    int     _actSel; // selection state\n    bool    _wordSelectionMode;\n    bool    _lineSelectionMode;\n    bool    _preserveLineBreaks;\n    bool    _columnSelectionMode;\n\n    QClipboard*  _clipboard;\n    QScrollBar* _scrollBar;\n    ScrollBarPosition _scrollbarLocation;\n    QString     _wordCharacters;\n    int         _bellMode;\n\n    bool _blinking;   // hide text in paintEvent\n    bool _hasBlinker; // has characters to blink\n    bool _cursorBlinking;     // hide cursor in paintEvent\n    bool _hasBlinkingCursor;  // has blinking cursor enabled\n    bool _ctrlDrag;           // require Ctrl key for drag\n    TripleClickMode _tripleClickMode;\n    bool _isFixedSize; //Columns / lines are locked.\n    QTimer* _blinkTimer;  // active when hasBlinker\n    QTimer* _blinkCursorTimer;  // active when hasBlinkingCursor\n    QTimer* _process_filter_timer;  // active when visible, filter processing\n\n//    KMenu* _drop;\n    QString _dropText;\n    int _dndFileCount;\n\n    bool _possibleTripleClick;  // is set in mouseDoubleClickEvent and deleted\n                               // after QApplication::doubleClickInterval() delay\n\n\n    QLabel* _resizeWidget;\n    QTimer* _resizeTimer;\n\n   bool _flowControlWarningEnabled;\n\n    //widgets related to the warning message that appears when the user presses Ctrl+S to suspend\n    //terminal output - informing them what has happened and how to resume output\n    QLabel* _outputSuspendedLabel;\n\n    uint _lineSpacing;\n\n    bool _colorsInverted; // true during visual bell\n\n    QSize _size;\n\n    QRgb _blendColor;\n\n    // list of filters currently applied to the display.  used for links and\n    // search highlight\n    TerminalImageFilterChain* _filterChain;\n    QRect _mouseOverHotspotArea;\n\n    KeyboardCursorShape _cursorShape;\n\n    // custom cursor color.  if this is invalid then the foreground\n    // color of the character under the cursor is used\n    QColor _cursorColor;\n\n\n    struct InputMethodData\n    {\n        QString preeditString;\n        QRect previousPreeditRect;\n    };\n    InputMethodData _inputMethodData;\n\n    static bool _antialiasText;   // do we antialias or not\n\n    //the delay in milliseconds between redrawing blinking text\n    static const int BLINK_DELAY = 500;\n   static const int DEFAULT_LEFT_MARGIN = 2;\n   static const int DEFAULT_TOP_MARGIN = 2;\n\n    bool _readonly;\n};\n\n#endif // TERMINALVIEW_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/Vt102Emulation.cpp",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n    Copyright (C) 1997-1998, 2013 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n// Own\n#include \"unix/Vt102Emulation.h\"\n\n#if defined(__osf__) || defined(__APPLE__)\n#define AVOID_XKB\n#endif\n\n// this allows konsole to be compiled without XKB and XTEST extensions\n// even though it might be available on a particular system.\n#if defined(AVOID_XKB)\n#undef HAVE_XKB\n#endif\n\n// Standard\n#include <stdio.h>\n#include <unistd.h>\n#include <assert.h>\n\n// Qt\n#include <QEvent>\n#include <QKeyEvent>\n\n// Konsole\n#include \"unix/KeyboardTranslator.h\"\n#include \"unix/Screen.h\"\n\n#if defined(HAVE_XKB)\nvoid scrolllock_set_off();\nvoid scrolllock_set_on();\n#endif\n\n\n/* VT102 Terminal Emulation\n\n   This class puts together the screens, the pty and the widget to a\n   complete terminal emulation. Beside combining it's componentes, it\n   handles the emulations's protocol.\n\n   This module consists of the following sections:\n\n   - Constructor/Destructor\n   - Incoming Bytes Event pipeline\n   - Outgoing Bytes\n     - Mouse Events\n     - Keyboard Events\n   - Modes and Charset State\n   - Diagnostics\n*/\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                       Constructor / Destructor                            */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n\nVt102Emulation::Vt102Emulation()\n    : Emulation(),\n     _titleUpdateTimer(new QTimer(this))\n{\n  _titleUpdateTimer->setSingleShot(true);\n\n  QObject::connect(_titleUpdateTimer , SIGNAL(timeout()) , this , SLOT(updateTitle()));\n\n  initTokenizer();\n  reset();\n}\n\nVt102Emulation::~Vt102Emulation()\n{\n}\n\nvoid Vt102Emulation::clearEntireScreen()\n{\n  _currentScreen->clearEntireScreen();\n\n  bufferedUpdate();\n}\n\nvoid Vt102Emulation::reset()\n{\n  //kDebug(1211)<<\"Vt102Emulation::reset() resetToken()\";\n  resetToken();\n  //kDebug(1211)<<\"Vt102Emulation::reset() resetModes()\";\n  resetModes();\n  //kDebug(1211)<<\"Vt102Emulation::reset() resetCharSet()\";\n  resetCharset(0);\n  //kDebug(1211)<<\"Vt102Emulation::reset() reset screen0()\";\n  _screen[0]->reset();\n  //kDebug(1211)<<\"Vt102Emulation::reset() resetCharSet()\";\n  resetCharset(1);\n  //kDebug(1211)<<\"Vt102Emulation::reset() reset _screen 1\";\n  _screen[1]->reset();\n  //kDebug(1211)<<\"Vt102Emulation::reset() setCodec()\";\n  setCodec(LocaleCodec);\n  //kDebug(1211)<<\"Vt102Emulation::reset() done\";\n\n  bufferedUpdate();\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                     Processing the incoming byte stream                   */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n/* Incoming Bytes Event pipeline\n\n   This section deals with decoding the incoming character stream.\n   Decoding means here, that the stream is first separated into `tokens'\n   which are then mapped to a `meaning' provided as operations by the\n   `Screen' class or by the emulation class itself.\n\n   The pipeline proceeds as follows:\n\n   - Tokenizing the ESC codes (onReceiveChar)\n   - VT100 code page translation of plain characters (applyCharset)\n   - Interpretation of ESC codes (tau)\n\n   The escape codes and their meaning are described in the\n   technical reference of this program.\n*/\n\n// Tokens ------------------------------------------------------------------ --\n\n/*\n   Since the tokens are the central notion if this section, we've put them\n   in front. They provide the syntactical elements used to represent the\n   terminals operations as byte sequences.\n\n   They are encodes here into a single machine word, so that we can later\n   switch over them easily. Depending on the token itself, additional\n   argument variables are filled with parameter values.\n\n   The tokens are defined below:\n\n   - CHR        - Printable characters     (32..255 but DEL (=127))\n   - CTL        - Control characters       (0..31 but ESC (= 27), DEL)\n   - ESC        - Escape codes of the form <ESC><CHR but `[]()+*#'>\n   - ESC_DE     - Escape codes of the form <ESC><any of `()+*#%'> C\n   - CSI_PN     - Escape codes of the form <ESC>'['     {Pn} ';' {Pn} C\n   - CSI_PS     - Escape codes of the form <ESC>'['     {Pn} ';' ...  C\n   - CSI_PR     - Escape codes of the form <ESC>'[' '?' {Pn} ';' ...  C\n   - CSI_PE     - Escape codes of the form <ESC>'[' '!' {Pn} ';' ...  C\n   - VT52       - VT52 escape codes\n                  - <ESC><Chr>\n                  - <ESC>'Y'{Pc}{Pc}\n   - XTE_HA     - Xterm hacks              <ESC>`]' {Pn} `;' {Text} <BEL>\n                  note that this is handled differently\n\n   The last two forms allow list of arguments. Since the elements of\n   the lists are treated individually the same way, they are passed\n   as individual tokens to the interpretation. Further, because the\n   meaning of the parameters are names (althought represented as numbers),\n   they are includes within the token ('N').\n\n*/\n\n#define TY_CONSTR(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) )\n\n#define TY_CHR(   )     TY_CONSTR(0,0,0)\n#define TY_CTL(A  )     TY_CONSTR(1,A,0)\n#define TY_ESC(A  )     TY_CONSTR(2,A,0)\n#define TY_ESC_CS(A,B)  TY_CONSTR(3,A,B)\n#define TY_ESC_DE(A  )  TY_CONSTR(4,A,0)\n#define TY_CSI_PS(A,N)  TY_CONSTR(5,A,N)\n#define TY_CSI_PN(A  )  TY_CONSTR(6,A,0)\n#define TY_CSI_PR(A,N)  TY_CONSTR(7,A,N)\n\n#define TY_VT52(A  )    TY_CONSTR(8,A,0)\n\n#define TY_CSI_PG(A  )  TY_CONSTR(9,A,0)\n\n#define TY_CSI_PE(A  )  TY_CONSTR(10,A,0)\n\n// Tokenizer --------------------------------------------------------------- --\n\n/* The tokenizers state\n\n   The state is represented by the buffer (pbuf, ppos),\n   and accompanied by decoded arguments kept in (argv,argc).\n   Note that they are kept internal in the tokenizer.\n*/\n\nvoid Vt102Emulation::resetToken()\n{\n  ppos = 0; argc = 0; argv[0] = 0; argv[1] = 0;\n}\n\nvoid Vt102Emulation::addDigit(int dig)\n{\n  argv[argc] = 10*argv[argc] + dig;\n}\n\nvoid Vt102Emulation::addArgument()\n{\n  argc = qMin(argc+1,MAXARGS-1);\n  argv[argc] = 0;\n}\n\nvoid Vt102Emulation::pushToToken(int cc)\n{\n  pbuf[ppos] = cc;\n  ppos = qMin(ppos+1,MAXPBUF-1);\n}\n\n// Character Classes used while decoding\n\n#define CTL  1\n#define CHR  2\n#define CPN  4\n#define DIG  8\n#define SCS 16\n#define GRP 32\n#define CPS 64\n\nvoid Vt102Emulation::initTokenizer()\n{ int i; quint8* s;\n  for(i =  0;                      i < 256; i++) tbl[ i]  = 0;\n  for(i =  0;                      i <  32; i++) tbl[ i] |= CTL;\n  for(i = 32;                      i < 256; i++) tbl[ i] |= CHR;\n  for(s = (quint8*)\"@ABCDGHILMPSTXZcdfry\"; *s; s++) tbl[*s] |= CPN;\n// resize = \\e[8;<row>;<col>t\n  for(s = (quint8*)\"t\"; *s; s++) tbl[*s] |= CPS;\n  for(s = (quint8*)\"0123456789\"        ; *s; s++) tbl[*s] |= DIG;\n  for(s = (quint8*)\"()+*%\"             ; *s; s++) tbl[*s] |= SCS;\n  for(s = (quint8*)\"()+*#[]%\"          ; *s; s++) tbl[*s] |= GRP;\n  resetToken();\n}\n\n/* Ok, here comes the nasty part of the decoder.\n\n   Instead of keeping an explicit state, we deduce it from the\n   token scanned so far. It is then immediately combined with\n   the current character to form a scanning decision.\n\n   This is done by the following defines.\n\n   - P is the length of the token scanned so far.\n   - L (often P-1) is the position on which contents we base a decision.\n   - C is a character or a group of characters (taken from 'tbl').\n\n   Note that they need to applied in proper order.\n*/\n\n#define lec(P,L,C) (p == (P) &&                     s[(L)]         == (C))\n#define lun(     ) (p ==  1  &&                       cc           >= 32 )\n#define les(P,L,C) (p == (P) && s[L] < 256  && (tbl[s[(L)]] & (C)) == (C))\n#define eec(C)     (p >=  3  &&        cc                          == (C))\n#define ees(C)     (p >=  3  && cc < 256 &&    (tbl[  cc  ] & (C)) == (C))\n#define eps(C)     (p >=  3  && s[2] != '?' && s[2] != '!' && s[2] != '>' && cc < 256 && (tbl[  cc  ] & (C)) == (C))\n#define epp( )     (p >=  3  && s[2] == '?'                              )\n#define epe( )     (p >=  3  && s[2] == '!'                              )\n#define egt(     ) (p >=  3  && s[2] == '>'                              )\n#define Xpe        (ppos>=2  && pbuf[1] == ']'                           )\n#define Xte        (Xpe                        &&     cc           ==  7 )\n#define ces(C)     (            cc < 256 &&    (tbl[  cc  ] & (C)) == (C) && !Xte)\n\n#define ESC 27\n#define CNTL(c) ((c)-'@')\n\n// process an incoming unicode character\n\nvoid Vt102Emulation::receiveChar(int cc)\n{\n  int i;\n  if (cc == 127) return; //VT100: ignore.\n\n  if (ces(    CTL))\n  { // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100\n    // This means, they do neither a resetToken nor a pushToToken. Some of them, do\n    // of course. Guess this originates from a weakly layered handling of the X-on\n    // X-off protocol, which comes really below this level.\n    if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC) resetToken(); //VT100: CAN or SUB\n    if (cc != ESC)    { tau( TY_CTL(cc+'@' ),   0,  0); return; }\n  }\n\n  pushToToken(cc); // advance the state\n\n  int* s = pbuf;\n  int  p = ppos;\n\n  if (getMode(MODE_Ansi)) // decide on proper action\n  {\n    if (lec(1,0,ESC)) {                                                       return; }\n    if (lec(1,0,ESC+128)) { s[0] = ESC; receiveChar('[');                   return; }\n    if (les(2,1,GRP)) {                                                       return; }\n    if (Xte         ) { XtermHack();                            resetToken(); return; }\n    if (Xpe         ) {                                                       return; }\n    if (lec(3,2,'?')) {                                                       return; }\n    if (lec(3,2,'>')) {                                                       return; }\n    if (lec(3,2,'!')) {                                                       return; }\n    if (lun(       )) { tau( TY_CHR(), applyCharset(cc), 0); resetToken(); return; }\n    if (lec(2,0,ESC)) { tau( TY_ESC(s[1]),   0,  0);       resetToken(); return; }\n    if (les(3,1,SCS)) { tau( TY_ESC_CS(s[1],s[2]),   0,  0);  resetToken(); return; }\n    if (lec(3,1,'#')) { tau( TY_ESC_DE(s[2]),   0,  0);       resetToken(); return; }\n    if (eps(    CPN)) { tau( TY_CSI_PN(cc), argv[0],argv[1]);   resetToken(); return; }\n\n// resize = \\e[8;<row>;<col>t\n    if (eps(    CPS)) { tau( TY_CSI_PS(cc, argv[0]), argv[1], argv[2]);   resetToken(); return; }\n\n    if (epe(       )) { tau( TY_CSI_PE(cc),     0,  0);       resetToken(); return; }\n    if (ees(    DIG)) { addDigit(cc-'0');                                     return; }\n    if (eec(    ';')) { addArgument();                                        return; }\n    for (i=0;i<=argc;i++)\n    if ( epp(     ))  { tau( TY_CSI_PR(cc,argv[i]),   0,  0); }\n    else if(egt(    ))   { tau( TY_CSI_PG(cc     ),   0,  0); } // spec. case for ESC]>0c or ESC]>c\n    else if (cc == 'm' && argc - i >= 4 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 2)\n    { // ESC[ ... 48;2;<red>;<green>;<blue> ... m -or- ESC[ ... 38;2;<red>;<green>;<blue> ... m\n      i += 2;\n      tau( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_RGB, (argv[i] << 16) | (argv[i+1] << 8) | argv[i+2]);\n      i += 2;\n    }\n    else if (cc == 'm' && argc - i >= 2 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 5)\n    { // ESC[ ... 48;5;<index> ... m -or- ESC[ ... 38;5;<index> ... m\n      i += 2;\n      tau( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_256, argv[i]);\n    }\n    else              { tau( TY_CSI_PS(cc,argv[i]),   0,  0); }\n    resetToken();\n  }\n  else // mode VT52\n  {\n    if (lec(1,0,ESC))                                                      return;\n    if (les(1,0,CHR)) { tau( TY_CHR(       ), s[0],  0); resetToken(); return; }\n    if (lec(2,1,'Y'))                                                      return;\n    if (lec(3,1,'Y'))                                                      return;\n    if (p < 4)        { tau( TY_VT52(s[1]   ),   0,  0); resetToken(); return; }\n                        tau( TY_VT52(s[1]   ), s[2],s[3]); resetToken(); return;\n  }\n}\n\nvoid Vt102Emulation::XtermHack()\n{ int i,arg = 0;\n  for (i = 2; i < ppos && '0'<=pbuf[i] && pbuf[i]<'9' ; i++)\n    arg = 10*arg + (pbuf[i]-'0');\n  if (pbuf[i] != ';') { ReportErrorToken(); return; }\n  QChar *str = new QChar[ppos-i-2];\n  for (int j = 0; j < ppos-i-2; j++) str[j] = QChar {pbuf[i+1+j]};\n  QString unistr(str,ppos-i-2);\n\n  // arg == 1 doesn't change the title. In XTerm it only changes the icon name\n  // (btw: arg=0 changes title and icon, arg=1 only icon, arg=2 only title\n//  Q_EMIT changeTitle(arg,unistr);\n  _pendingTitleUpdates[arg] = unistr;\n  _titleUpdateTimer->start(20);\n\n  delete [] str;\n}\n\nvoid Vt102Emulation::updateTitle()\n{\n    QListIterator<int> iter( _pendingTitleUpdates.keys() );\n    while (iter.hasNext()) {\n        int arg = iter.next();\n        Q_EMIT titleChanged( arg , _pendingTitleUpdates[arg] );\n    }\n\n    _pendingTitleUpdates.clear();\n}\n\n// Interpreting Codes ---------------------------------------------------------\n\n/*\n   Now that the incoming character stream is properly tokenized,\n   meaning is assigned to them. These are either operations of\n   the current _screen, or of the emulation class itself.\n\n   The token to be interpreteted comes in as a machine word\n   possibly accompanied by two parameters.\n\n   Likewise, the operations assigned to, come with up to two\n   arguments. One could consider to make up a proper table\n   from the function below.\n\n   The technical reference manual provides more information\n   about this mapping.\n*/\n\nvoid Vt102Emulation::tau( int token, int p, int q )\n{\n  switch (token)\n  {\n\n    case TY_CHR(         ) : _currentScreen->ShowCharacter        (p         ); break; //UTF16\n\n    //             127 DEL    : ignored on input\n\n    case TY_CTL('@'      ) : /* NUL: ignored                      */ break;\n    case TY_CTL('A'      ) : /* SOH: ignored                      */ break;\n    case TY_CTL('B'      ) : /* STX: ignored                      */ break;\n    case TY_CTL('C'      ) : /* ETX: ignored                      */ break;\n    case TY_CTL('D'      ) : /* EOT: ignored                      */ break;\n    case TY_CTL('E'      ) :      reportAnswerBack     (          ); break; //VT100\n    case TY_CTL('F'      ) : /* ACK: ignored                      */ break;\n    case TY_CTL('G'      ) : Q_EMIT stateSet(NOTIFYBELL);\n                                break; //VT100\n    case TY_CTL('H'      ) : _currentScreen->BackSpace            (          ); break; //VT100\n    case TY_CTL('I'      ) : _currentScreen->Tabulate             (          ); break; //VT100\n    case TY_CTL('J'      ) : _currentScreen->NewLine              (          ); break; //VT100\n    case TY_CTL('K'      ) : _currentScreen->NewLine              (          ); break; //VT100\n    case TY_CTL('L'      ) : _currentScreen->NewLine              (          ); break; //VT100\n    case TY_CTL('M'      ) : _currentScreen->Return               (          ); break; //VT100\n\n    case TY_CTL('N'      ) :      useCharset           (         1); break; //VT100\n    case TY_CTL('O'      ) :      useCharset           (         0); break; //VT100\n\n    case TY_CTL('P'      ) : /* DLE: ignored                      */ break;\n    case TY_CTL('Q'      ) : /* DC1: XON continue                 */ break; //VT100\n    case TY_CTL('R'      ) : /* DC2: ignored                      */ break;\n    case TY_CTL('S'      ) : /* DC3: XOFF halt                    */ break; //VT100\n    case TY_CTL('T'      ) : /* DC4: ignored                      */ break;\n    case TY_CTL('U'      ) : /* NAK: ignored                      */ break;\n    case TY_CTL('V'      ) : /* SYN: ignored                      */ break;\n    case TY_CTL('W'      ) : /* ETB: ignored                      */ break;\n    case TY_CTL('X'      ) : _currentScreen->ShowCharacter        (    0x2592); break; //VT100\n    case TY_CTL('Y'      ) : /* EM : ignored                      */ break;\n    case TY_CTL('Z'      ) : _currentScreen->ShowCharacter        (    0x2592); break; //VT100\n    case TY_CTL('['      ) : /* ESC: cannot be seen here.         */ break;\n    case TY_CTL('\\\\'     ) : /* FS : ignored                      */ break;\n    case TY_CTL(']'      ) : /* GS : ignored                      */ break;\n    case TY_CTL('^'      ) : /* RS : ignored                      */ break;\n    case TY_CTL('_'      ) : /* US : ignored                      */ break;\n\n    case TY_ESC('D'      ) : _currentScreen->index                (          ); break; //VT100\n    case TY_ESC('E'      ) : _currentScreen->NextLine             (          ); break; //VT100\n    case TY_ESC('H'      ) : _currentScreen->changeTabStop        (true      ); break; //VT100\n    case TY_ESC('M'      ) : _currentScreen->reverseIndex         (          ); break; //VT100\n    case TY_ESC('Z'      ) :      reportTerminalType   (          ); break;\n    case TY_ESC('c'      ) :      reset                (          ); break;\n\n    case TY_ESC('n'      ) :      useCharset           (         2); break;\n    case TY_ESC('o'      ) :      useCharset           (         3); break;\n    case TY_ESC('7'      ) :      saveCursor           (          ); break;\n    case TY_ESC('8'      ) :      restoreCursor        (          ); break;\n\n    case TY_ESC('='      ) :          setMode      (MODE_AppKeyPad); break;\n    case TY_ESC('>'      ) :        resetMode      (MODE_AppKeyPad); break;\n    case TY_ESC('<'      ) :          setMode      (MODE_Ansi     ); break; //VT100\n\n    case TY_ESC_CS('(', '0') :      setCharset           (0,    '0'); break; //VT100\n    case TY_ESC_CS('(', 'A') :      setCharset           (0,    'A'); break; //VT100\n    case TY_ESC_CS('(', 'B') :      setCharset           (0,    'B'); break; //VT100\n\n    case TY_ESC_CS(')', '0') :      setCharset           (1,    '0'); break; //VT100\n    case TY_ESC_CS(')', 'A') :      setCharset           (1,    'A'); break; //VT100\n    case TY_ESC_CS(')', 'B') :      setCharset           (1,    'B'); break; //VT100\n\n    case TY_ESC_CS('*', '0') :      setCharset           (2,    '0'); break; //VT100\n    case TY_ESC_CS('*', 'A') :      setCharset           (2,    'A'); break; //VT100\n    case TY_ESC_CS('*', 'B') :      setCharset           (2,    'B'); break; //VT100\n\n    case TY_ESC_CS('+', '0') :      setCharset           (3,    '0'); break; //VT100\n    case TY_ESC_CS('+', 'A') :      setCharset           (3,    'A'); break; //VT100\n    case TY_ESC_CS('+', 'B') :      setCharset           (3,    'B'); break; //VT100\n\n    case TY_ESC_CS('%', 'G') :      setCodec             (Utf8Codec   ); break; //LINUX\n    case TY_ESC_CS('%', '@') :      setCodec             (LocaleCodec ); break; //LINUX\n\n    case TY_ESC_DE('3'      ) : /* Double height line, top half    */\n                                _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );\n                                _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );\n                                    break;\n    case TY_ESC_DE('4'      ) : /* Double height line, bottom half */\n                                _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );\n                                _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );\n                                    break;\n    case TY_ESC_DE('5'      ) : /* Single width, single height line*/\n                                _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , false);\n                                _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);\n                                break;\n    case TY_ESC_DE('6'      ) : /* Double width, single height line*/\n                                _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true);\n                                _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);\n                                break;\n    case TY_ESC_DE('8'      ) : _currentScreen->helpAlign            (          ); break;\n\n// resize = \\e[8;<row>;<col>t\n    case TY_CSI_PS('t',   8) : setImageSize( q /* colums */, p /* lines */ );    break;\n\n// change tab text color : \\e[28;<color>t  color: 0-16,777,215\n    case TY_CSI_PS('t',   28) : Q_EMIT changeTabTextColorRequest      ( p        );          break;\n\n    case TY_CSI_PS('K',   0) : _currentScreen->clearToEndOfLine     (          ); break;\n    case TY_CSI_PS('K',   1) : _currentScreen->clearToBeginOfLine   (          ); break;\n    case TY_CSI_PS('K',   2) : _currentScreen->clearEntireLine      (          ); break;\n    case TY_CSI_PS('J',   0) : _currentScreen->clearToEndOfScreen   (          ); break;\n    case TY_CSI_PS('J',   1) : _currentScreen->clearToBeginOfScreen (          ); break;\n    case TY_CSI_PS('J',   2) : _currentScreen->clearEntireScreen    (          ); break;\n    case TY_CSI_PS('g',   0) : _currentScreen->changeTabStop        (false     ); break; //VT100\n    case TY_CSI_PS('g',   3) : _currentScreen->clearTabStops        (          ); break; //VT100\n    case TY_CSI_PS('h',   4) : _currentScreen->    setMode      (MODE_Insert   ); break;\n    case TY_CSI_PS('h',  20) :          setMode      (MODE_NewLine  ); break;\n    case TY_CSI_PS('i',   0) : /* IGNORE: attached printer          */ break; //VT100\n    case TY_CSI_PS('l',   4) : _currentScreen->  resetMode      (MODE_Insert   ); break;\n    case TY_CSI_PS('l',  20) :        resetMode      (MODE_NewLine  ); break;\n    case TY_CSI_PS('s',   0) :      saveCursor           (          ); break;\n    case TY_CSI_PS('u',   0) :      restoreCursor        (          ); break;\n\n    case TY_CSI_PS('m',   0) : _currentScreen->setDefaultRendition  (          ); break;\n    case TY_CSI_PS('m',   1) : _currentScreen->  setRendition     (RE_BOLD     ); break; //VT100\n    case TY_CSI_PS('m',   4) : _currentScreen->  setRendition     (RE_UNDERLINE); break; //VT100\n    case TY_CSI_PS('m',   5) : _currentScreen->  setRendition     (RE_BLINK    ); break; //VT100\n    case TY_CSI_PS('m',   7) : _currentScreen->  setRendition     (RE_REVERSE  ); break;\n    case TY_CSI_PS('m',  10) : /* IGNORED: mapping related          */ break; //LINUX\n    case TY_CSI_PS('m',  11) : /* IGNORED: mapping related          */ break; //LINUX\n    case TY_CSI_PS('m',  12) : /* IGNORED: mapping related          */ break; //LINUX\n    case TY_CSI_PS('m',  22) : _currentScreen->resetRendition     (RE_BOLD     ); break;\n    case TY_CSI_PS('m',  24) : _currentScreen->resetRendition     (RE_UNDERLINE); break;\n    case TY_CSI_PS('m',  25) : _currentScreen->resetRendition     (RE_BLINK    ); break;\n    case TY_CSI_PS('m',  27) : _currentScreen->resetRendition     (RE_REVERSE  ); break;\n\n    case TY_CSI_PS('m',   30) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  0); break;\n    case TY_CSI_PS('m',   31) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  1); break;\n    case TY_CSI_PS('m',   32) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  2); break;\n    case TY_CSI_PS('m',   33) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  3); break;\n    case TY_CSI_PS('m',   34) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  4); break;\n    case TY_CSI_PS('m',   35) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  5); break;\n    case TY_CSI_PS('m',   36) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  6); break;\n    case TY_CSI_PS('m',   37) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  7); break;\n\n    case TY_CSI_PS('m',   38) : _currentScreen->setForeColor         (p,       q); break;\n\n    case TY_CSI_PS('m',   39) : _currentScreen->setForeColor         (COLOR_SPACE_DEFAULT,  0); break;\n\n    case TY_CSI_PS('m',   40) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  0); break;\n    case TY_CSI_PS('m',   41) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  1); break;\n    case TY_CSI_PS('m',   42) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  2); break;\n    case TY_CSI_PS('m',   43) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  3); break;\n    case TY_CSI_PS('m',   44) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  4); break;\n    case TY_CSI_PS('m',   45) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  5); break;\n    case TY_CSI_PS('m',   46) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  6); break;\n    case TY_CSI_PS('m',   47) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  7); break;\n\n    case TY_CSI_PS('m',   48) : _currentScreen->setBackColor         (p,       q); break;\n\n    case TY_CSI_PS('m',   49) : _currentScreen->setBackColor         (COLOR_SPACE_DEFAULT,  1); break;\n\n    case TY_CSI_PS('m',   90) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  8); break;\n    case TY_CSI_PS('m',   91) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM,  9); break;\n    case TY_CSI_PS('m',   92) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 10); break;\n    case TY_CSI_PS('m',   93) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 11); break;\n    case TY_CSI_PS('m',   94) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 12); break;\n    case TY_CSI_PS('m',   95) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 13); break;\n    case TY_CSI_PS('m',   96) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 14); break;\n    case TY_CSI_PS('m',   97) : _currentScreen->setForeColor         (COLOR_SPACE_SYSTEM, 15); break;\n\n    case TY_CSI_PS('m',  100) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  8); break;\n    case TY_CSI_PS('m',  101) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM,  9); break;\n    case TY_CSI_PS('m',  102) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 10); break;\n    case TY_CSI_PS('m',  103) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 11); break;\n    case TY_CSI_PS('m',  104) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 12); break;\n    case TY_CSI_PS('m',  105) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 13); break;\n    case TY_CSI_PS('m',  106) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 14); break;\n    case TY_CSI_PS('m',  107) : _currentScreen->setBackColor         (COLOR_SPACE_SYSTEM, 15); break;\n\n    case TY_CSI_PS('n',   5) :      reportStatus         (          ); break;\n    case TY_CSI_PS('n',   6) :      reportCursorPosition (          ); break;\n    case TY_CSI_PS('q',   0) : /* IGNORED: LEDs off                 */ break; //VT100\n    case TY_CSI_PS('q',   1) : /* IGNORED: LED1 on                  */ break; //VT100\n    case TY_CSI_PS('q',   2) : /* IGNORED: LED2 on                  */ break; //VT100\n    case TY_CSI_PS('q',   3) : /* IGNORED: LED3 on                  */ break; //VT100\n    case TY_CSI_PS('q',   4) : /* IGNORED: LED4 on                  */ break; //VT100\n    case TY_CSI_PS('x',   0) :      reportTerminalParms  (         2); break; //VT100\n    case TY_CSI_PS('x',   1) :      reportTerminalParms  (         3); break; //VT100\n\n    case TY_CSI_PN('@'      ) : _currentScreen->insertChars          (p         ); break;\n    case TY_CSI_PN('A'      ) : _currentScreen->cursorUp             (p         ); break; //VT100\n    case TY_CSI_PN('B'      ) : _currentScreen->cursorDown           (p         ); break; //VT100\n    case TY_CSI_PN('C'      ) : _currentScreen->cursorRight          (p         ); break; //VT100\n    case TY_CSI_PN('D'      ) : _currentScreen->cursorLeft           (p         ); break; //VT100\n    case TY_CSI_PN('G'      ) : _currentScreen->setCursorX           (p         ); break; //LINUX\n    case TY_CSI_PN('H'      ) : _currentScreen->setCursorYX          (p,      q); break; //VT100\n    case TY_CSI_PN('I'      ) : _currentScreen->Tabulate             (p         ); break;\n    case TY_CSI_PN('L'      ) : _currentScreen->insertLines          (p         ); break;\n    case TY_CSI_PN('M'      ) : _currentScreen->deleteLines          (p         ); break;\n    case TY_CSI_PN('P'      ) : _currentScreen->deleteChars          (p         ); break;\n    case TY_CSI_PN('S'      ) : _currentScreen->scrollUp             (p         ); break;\n    case TY_CSI_PN('T'      ) : _currentScreen->scrollDown           (p         ); break;\n    case TY_CSI_PN('X'      ) : _currentScreen->eraseChars           (p         ); break;\n    case TY_CSI_PN('Z'      ) : _currentScreen->backTabulate         (p         ); break;\n    case TY_CSI_PN('c'      ) :      reportTerminalType   (          ); break; //VT100\n    case TY_CSI_PN('d'      ) : _currentScreen->setCursorY           (p         ); break; //LINUX\n    case TY_CSI_PN('f'      ) : _currentScreen->setCursorYX          (p,      q); break; //VT100\n    case TY_CSI_PN('r'      ) :      setMargins           (p,      q); break; //VT100\n    case TY_CSI_PN('y'      ) : /* IGNORED: Confidence test          */ break; //VT100\n\n    case TY_CSI_PR('h',   1) :          setMode      (MODE_AppCuKeys); break; //VT100\n    case TY_CSI_PR('l',   1) :        resetMode      (MODE_AppCuKeys); break; //VT100\n    case TY_CSI_PR('s',   1) :         saveMode      (MODE_AppCuKeys); break; //FIXME\n    case TY_CSI_PR('r',   1) :      restoreMode      (MODE_AppCuKeys); break; //FIXME\n\n    case TY_CSI_PR('l',   2) :        resetMode      (MODE_Ansi     ); break; //VT100\n\n    case TY_CSI_PR('h',   3) : clearScreenAndSetColumns(132);          break; //VT100\n    case TY_CSI_PR('l',   3) : clearScreenAndSetColumns(80);           break; //VT100\n\n    case TY_CSI_PR('h',   4) : /* IGNORED: soft scrolling           */ break; //VT100\n    case TY_CSI_PR('l',   4) : /* IGNORED: soft scrolling           */ break; //VT100\n\n    case TY_CSI_PR('h',   5) : _currentScreen->    setMode      (MODE_Screen   ); break; //VT100\n    case TY_CSI_PR('l',   5) : _currentScreen->  resetMode      (MODE_Screen   ); break; //VT100\n\n    case TY_CSI_PR('h',   6) : _currentScreen->    setMode      (MODE_Origin   ); break; //VT100\n    case TY_CSI_PR('l',   6) : _currentScreen->  resetMode      (MODE_Origin   ); break; //VT100\n    case TY_CSI_PR('s',   6) : _currentScreen->   saveMode      (MODE_Origin   ); break; //FIXME\n    case TY_CSI_PR('r',   6) : _currentScreen->restoreMode      (MODE_Origin   ); break; //FIXME\n\n    case TY_CSI_PR('h',   7) : _currentScreen->    setMode      (MODE_Wrap     ); break; //VT100\n    case TY_CSI_PR('l',   7) : _currentScreen->  resetMode      (MODE_Wrap     ); break; //VT100\n    case TY_CSI_PR('s',   7) : _currentScreen->   saveMode      (MODE_Wrap     ); break; //FIXME\n    case TY_CSI_PR('r',   7) : _currentScreen->restoreMode      (MODE_Wrap     ); break; //FIXME\n\n    case TY_CSI_PR('h',   8) : /* IGNORED: autorepeat on            */ break; //VT100\n    case TY_CSI_PR('l',   8) : /* IGNORED: autorepeat off           */ break; //VT100\n    case TY_CSI_PR('s',   8) : /* IGNORED: autorepeat on            */ break; //VT100\n    case TY_CSI_PR('r',   8) : /* IGNORED: autorepeat off           */ break; //VT100\n\n    case TY_CSI_PR('h',   9) : /* IGNORED: interlace                */ break; //VT100\n    case TY_CSI_PR('l',   9) : /* IGNORED: interlace                */ break; //VT100\n    case TY_CSI_PR('s',   9) : /* IGNORED: interlace                */ break; //VT100\n    case TY_CSI_PR('r',   9) : /* IGNORED: interlace                */ break; //VT100\n\n    case TY_CSI_PR('h',  12) : /* IGNORED: Cursor blink             */ break; //att610\n    case TY_CSI_PR('l',  12) : /* IGNORED: Cursor blink             */ break; //att610\n    case TY_CSI_PR('s',  12) : /* IGNORED: Cursor blink             */ break; //att610\n    case TY_CSI_PR('r',  12) : /* IGNORED: Cursor blink             */ break; //att610\n\n    case TY_CSI_PR('h',  25) :          setMode      (MODE_Cursor   ); break; //VT100\n    case TY_CSI_PR('l',  25) :        resetMode      (MODE_Cursor   ); break; //VT100\n    case TY_CSI_PR('s',  25) :         saveMode      (MODE_Cursor   ); break; //VT100\n    case TY_CSI_PR('r',  25) :      restoreMode      (MODE_Cursor   ); break; //VT100\n\n    case TY_CSI_PR('h',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM\n    case TY_CSI_PR('l',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM\n    case TY_CSI_PR('s',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM\n    case TY_CSI_PR('r',  41) : /* IGNORED: obsolete more(1) fix     */ break; //XTERM\n\n    case TY_CSI_PR('h',  47) :          setMode      (MODE_AppScreen); break; //VT100\n    case TY_CSI_PR('l',  47) :        resetMode      (MODE_AppScreen); break; //VT100\n    case TY_CSI_PR('s',  47) :         saveMode      (MODE_AppScreen); break; //XTERM\n    case TY_CSI_PR('r',  47) :      restoreMode      (MODE_AppScreen); break; //XTERM\n\n    case TY_CSI_PR('h',  67) : /* IGNORED: DECBKM                   */ break; //XTERM\n    case TY_CSI_PR('l',  67) : /* IGNORED: DECBKM                   */ break; //XTERM\n    case TY_CSI_PR('s',  67) : /* IGNORED: DECBKM                   */ break; //XTERM\n    case TY_CSI_PR('r',  67) : /* IGNORED: DECBKM                   */ break; //XTERM\n\n    // XTerm defines the following modes:\n    // SET_VT200_MOUSE             1000\n    // SET_VT200_HIGHLIGHT_MOUSE   1001\n    // SET_BTN_EVENT_MOUSE         1002\n    // SET_ANY_EVENT_MOUSE         1003\n    //\n\n    //Note about mouse modes:\n    //There are four mouse modes which xterm-compatible terminals can support - 1000,1001,1002,1003\n    //Konsole currently supports mode 1000 (basic mouse press and release) and mode 1002 (dragging the mouse).\n    //TODO:  Implementation of mouse modes 1001 (something called hilight tracking) and\n    //1003 (a slight variation on dragging the mouse)\n    //\n\n    case TY_CSI_PR('h', 1000) :          setMode      (MODE_Mouse1000); break; //XTERM\n    case TY_CSI_PR('l', 1000) :        resetMode      (MODE_Mouse1000); break; //XTERM\n    case TY_CSI_PR('s', 1000) :         saveMode      (MODE_Mouse1000); break; //XTERM\n    case TY_CSI_PR('r', 1000) :      restoreMode      (MODE_Mouse1000); break; //XTERM\n\n    case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking    */ break; //XTERM\n    case TY_CSI_PR('l', 1001) :        resetMode      (MODE_Mouse1001); break; //XTERM\n    case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking    */ break; //XTERM\n    case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking    */ break; //XTERM\n\n    case TY_CSI_PR('h', 1002) :          setMode      (MODE_Mouse1002); break; //XTERM\n    case TY_CSI_PR('l', 1002) :        resetMode      (MODE_Mouse1002); break; //XTERM\n    case TY_CSI_PR('s', 1002) :         saveMode      (MODE_Mouse1002); break; //XTERM\n    case TY_CSI_PR('r', 1002) :      restoreMode      (MODE_Mouse1002); break; //XTERM\n\n    case TY_CSI_PR('h', 1003) :          setMode      (MODE_Mouse1003); break; //XTERM\n    case TY_CSI_PR('l', 1003) :        resetMode      (MODE_Mouse1003); break; //XTERM\n    case TY_CSI_PR('s', 1003) :         saveMode      (MODE_Mouse1003); break; //XTERM\n    case TY_CSI_PR('r', 1003) :      restoreMode      (MODE_Mouse1003); break; //XTERM\n    case TY_CSI_PR('h', 1034) : /* IGNORED: 8bitinput activation     */ break; //XTERM\n\n    case TY_CSI_PR('h', 1047) :          setMode      (MODE_AppScreen); break; //XTERM\n    case TY_CSI_PR('l', 1047) : _screen[1]->clearEntireScreen(); resetMode(MODE_AppScreen); break; //XTERM\n    case TY_CSI_PR('s', 1047) :         saveMode      (MODE_AppScreen); break; //XTERM\n    case TY_CSI_PR('r', 1047) :      restoreMode      (MODE_AppScreen); break; //XTERM\n\n    //FIXME: Unitoken: save translations\n    case TY_CSI_PR('h', 1048) :      saveCursor           (          ); break; //XTERM\n    case TY_CSI_PR('l', 1048) :      restoreCursor        (          ); break; //XTERM\n    case TY_CSI_PR('s', 1048) :      saveCursor           (          ); break; //XTERM\n    case TY_CSI_PR('r', 1048) :      restoreCursor        (          ); break; //XTERM\n\n    //FIXME: every once new sequences like this pop up in xterm.\n    //       Here's a guess of what they could mean.\n    case TY_CSI_PR('h', 1049) : saveCursor(); _screen[1]->clearEntireScreen(); setMode(MODE_AppScreen); break; //XTERM\n    case TY_CSI_PR('l', 1049) : resetMode(MODE_AppScreen); restoreCursor(); break; //XTERM\n\n    case TY_CSI_PR('h', 2004) :          setMode      (MODE_BracketedPaste); break; //XTERM\n    case TY_CSI_PR('l', 2004) :        resetMode      (MODE_BracketedPaste); break; //XTERM\n    case TY_CSI_PR('s', 2004) :         saveMode      (MODE_BracketedPaste); break; //XTERM\n    case TY_CSI_PR('r', 2004) :      restoreMode      (MODE_BracketedPaste); break; //XTERM\n\n    //FIXME: weird DEC reset sequence\n    case TY_CSI_PE('p'      ) : /* IGNORED: reset         (        ) */ break;\n\n    //FIXME: when changing between vt52 and ansi mode evtl do some resetting.\n    case TY_VT52('A'      ) : _currentScreen->cursorUp             (         1); break; //VT52\n    case TY_VT52('B'      ) : _currentScreen->cursorDown           (         1); break; //VT52\n    case TY_VT52('C'      ) : _currentScreen->cursorRight          (         1); break; //VT52\n    case TY_VT52('D'      ) : _currentScreen->cursorLeft           (         1); break; //VT52\n\n    case TY_VT52('F'      ) :      setAndUseCharset     (0,    '0'); break; //VT52\n    case TY_VT52('G'      ) :      setAndUseCharset     (0,    'B'); break; //VT52\n\n    case TY_VT52('H'      ) : _currentScreen->setCursorYX          (1,1       ); break; //VT52\n    case TY_VT52('I'      ) : _currentScreen->reverseIndex         (          ); break; //VT52\n    case TY_VT52('J'      ) : _currentScreen->clearToEndOfScreen   (          ); break; //VT52\n    case TY_VT52('K'      ) : _currentScreen->clearToEndOfLine     (          ); break; //VT52\n    case TY_VT52('Y'      ) : _currentScreen->setCursorYX          (p-31,q-31 ); break; //VT52\n    case TY_VT52('Z'      ) :      reportTerminalType   (           ); break; //VT52\n    case TY_VT52('<'      ) :          setMode      (MODE_Ansi     ); break; //VT52\n    case TY_VT52('='      ) :          setMode      (MODE_AppKeyPad); break; //VT52\n    case TY_VT52('>'      ) :        resetMode      (MODE_AppKeyPad); break; //VT52\n\n    case TY_CSI_PG('c'      ) :  reportSecondaryAttributes(          ); break; //VT100\n\n    default : ReportErrorToken();    break;\n  };\n}\n\nvoid Vt102Emulation::clearScreenAndSetColumns(int columnCount)\n{\n    setImageSize(_currentScreen->getLines(),columnCount);\n    clearEntireScreen();\n    setDefaultMargins();\n    _currentScreen->setCursorYX(0,0);\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                          Terminal to Host protocol                        */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n/*\n   Outgoing bytes originate from several sources:\n\n   - Replies to Enquieries.\n   - Mouse Events\n   - Keyboard Events\n*/\n\n/*!\n*/\n\nvoid Vt102Emulation::sendString(const char* s , int length)\n{\n  if ( length >= 0 )\n    Q_EMIT sendData(s,length);\n  else\n    Q_EMIT sendData(s,strlen(s));\n}\n\n// Replies ----------------------------------------------------------------- --\n\n// This section copes with replies send as response to an enquiery control code.\n\n/*!\n*/\n\nvoid Vt102Emulation::reportCursorPosition()\n{ char tmp[32];\n  sprintf(tmp,\"\\033[%d;%dR\",_currentScreen->getCursorY()+1,_currentScreen->getCursorX()+1);\n  sendString(tmp);\n}\n\n/*\n   What follows here is rather obsolete and faked stuff.\n   The correspondent enquieries are neverthenless issued.\n*/\n\n/*!\n*/\n\nvoid Vt102Emulation::reportTerminalType()\n{\n  // Primary device attribute response (Request was: ^[[0c or ^[[c (from TT321 Users Guide))\n  //   VT220:  ^[[?63;1;2;3;6;7;8c   (list deps on emul. capabilities)\n  //   VT100:  ^[[?1;2c\n  //   VT101:  ^[[?1;0c\n  //   VT102:  ^[[?6v\n  if (getMode(MODE_Ansi))\n    sendString(\"\\033[?1;2c\");     // I'm a VT100\n  else\n    sendString(\"\\033/Z\");         // I'm a VT52\n}\n\nvoid Vt102Emulation::reportSecondaryAttributes()\n{\n  // Seconday device attribute response (Request was: ^[[>0c or ^[[>c)\n  if (getMode(MODE_Ansi))\n    sendString(\"\\033[>0;115;0c\"); // Why 115?  ;)\n  else\n    sendString(\"\\033/Z\");         // FIXME I don't think VT52 knows about it but kept for\n                                  // konsoles backward compatibility.\n}\n\nvoid Vt102Emulation::reportTerminalParms(int p)\n// DECREPTPARM\n{ char tmp[100];\n  sprintf(tmp,\"\\033[%d;1;1;112;112;1;0x\",p); // not really true.\n  sendString(tmp);\n}\n\n/*!\n*/\n\nvoid Vt102Emulation::reportStatus()\n{\n  sendString(\"\\033[0n\"); //VT100. Device status report. 0 = Ready.\n}\n\n/*!\n*/\n\n#define ANSWER_BACK \"\" // This is really obsolete VT100 stuff.\n\nvoid Vt102Emulation::reportAnswerBack()\n{\n  sendString(ANSWER_BACK);\n}\n\n// Mouse Handling ---------------------------------------------------------- --\n\n/*!\n    Mouse clicks are possibly reported to the client\n    application if it has issued interest in them.\n    They are normally consumed by the widget for copy\n    and paste, but may be propagated from the widget\n    when gui->setMouseMarks is set via setMode(MODE_Mouse1000).\n\n    `x',`y' are 1-based.\n    `ev' (event) indicates the button pressed (0-2)\n                 or a general mouse release (3).\n\n    eventType represents the kind of mouse action that occurred:\n        0 = Mouse button press or release\n    1 = Mouse drag\n*/\n\nvoid Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType )\n{ char tmp[20];\n  if (  cx<1 || cy<1 ) return;\n  // normal buttons are passed as 0x20 + button,\n  // mouse wheel (buttons 4,5) as 0x5c + button\n  if (cb >= 4) cb += 0x3c;\n\n  //Mouse motion handling\n  if ( (getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1 )\n      cb += 0x20; //add 32 to signify motion event\n\n  sprintf(tmp,\"\\033[M%c%c%c\",cb+0x20,cx+0x20,cy+0x20);\n  sendString(tmp);\n}\n\n// Keyboard Handling ------------------------------------------------------- --\n\n#define encodeMode(M,B) BITS(B,getMode(M))\n#define encodeStat(M,B) BITS(B,((ev->modifiers() & (M)) == (M)))\n\nvoid Vt102Emulation::sendText( const QString& text )\n{\n  if (!text.isEmpty()) {\n    QKeyEvent event(QEvent::KeyPress,\n                    0,\n                    Qt::NoModifier,\n                    text);\n    sendKeyEvent(&event); // expose as a big fat keypress event\n  }\n\n}\n\nvoid Vt102Emulation::sendKeyEvent( QKeyEvent* event )\n{\n    Qt::KeyboardModifiers modifiers = event->modifiers();\n    KeyboardTranslator::States states = KeyboardTranslator::NoState;\n\n    // get current states\n    if ( getMode(MODE_NewLine)  ) states |= KeyboardTranslator::NewLineState;\n    if ( getMode(MODE_Ansi)     ) states |= KeyboardTranslator::AnsiState;\n    if ( getMode(MODE_AppCuKeys)) states |= KeyboardTranslator::CursorKeysState;\n    if ( getMode(MODE_AppScreen)) states |= KeyboardTranslator::AlternateScreenState;\n\n    // lookup key binding\n    if ( _keyTranslator )\n    {\n    KeyboardTranslator::Entry entry = _keyTranslator->findEntry(\n                                                event->key() ,\n                                                modifiers,\n                                                states );\n\n        // send result to terminal\n        QByteArray textToSend;\n\n        // special handling for the Alt (aka. Meta) modifier.  pressing\n        // Alt+[Character] results in Esc+[Character] being sent\n        // (unless there is an entry defined for this particular combination\n        //  in the keyboard modifier)\n        bool wantsAltModifier = entry.modifiers() & entry.modifierMask() & Qt::AltModifier;\n        bool wantsAnyModifier = entry.state() & entry.stateMask() & KeyboardTranslator::AnyModifierState;\n\n        if ( modifiers & Qt::AltModifier && !(wantsAltModifier || wantsAnyModifier)\n             && !event->text().isEmpty() )\n        {\n#if !defined(Q_OS_MAC)\n          textToSend.prepend(\"\\033\");\n#endif\n        }\n\n        if ( entry.command() != KeyboardTranslator::NoCommand )\n        {\n            if (entry.command() & KeyboardTranslator::EraseCommand)\n                textToSend += getErase();\n            // TODO command handling\n        }\n        else if ( !entry.text().isEmpty() )\n        {\n            textToSend += _codec->fromUnicode(entry.text(true,modifiers));\n        }\n        else if (event->key() == Qt::Key_PageUp)\n        {\n            textToSend += \"\\033[5~\";\n        }\n        else if (event->key() == Qt::Key_PageDown)\n        {\n            textToSend += \"\\033[6~\";\n        }\n        else\n            textToSend += _codec->fromUnicode(event->text());\n\n        sendData( textToSend.constData() , textToSend.length() );\n    }\n    else\n    {\n        // print an error message to the terminal if no key translator has been\n        // set\n        QString translatorError =  (\"No keyboard translator available.  \"\n                                         \"The information needed to convert key presses \"\n                                         \"into characters to send to the terminal \"\n                                         \"is missing.\");\n\n        reset();\n        receiveData( translatorError.toLatin1().constData() , translatorError.size () );\n    }\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                                VT100 Charsets                             */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n// Character Set Conversion ------------------------------------------------ --\n\n/*\n   The processing contains a VT100 specific code translation layer.\n   It's still in use and mainly responsible for the line drawing graphics.\n\n   These and some other glyphs are assigned to codes (0x5f-0xfe)\n   normally occupied by the latin letters. Since this codes also\n   appear within control sequences, the extra code conversion\n   does not permute with the tokenizer and is placed behind it\n   in the pipeline. It only applies to tokens, which represent\n   plain characters.\n\n   This conversion it eventually continued in TerminalDisplay.C, since\n   it might involve VT100 enhanced fonts, which have these\n   particular glyphs allocated in (0x00-0x1f) in their code page.\n*/\n\n#define CHARSET _charset[_currentScreen==_screen[1]]\n\n// Apply current character map.\n\nunsigned short Vt102Emulation::applyCharset(unsigned short c)\n{\n  if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];\n  if (CHARSET.pound                && c == '#' ) return 0xa3; //This mode is obsolete\n  return c;\n}\n\n/*\n   \"Charset\" related part of the emulation state.\n   This configures the VT100 _charset filter.\n\n   While most operation work on the current _screen,\n   the following two are different.\n*/\n\nvoid Vt102Emulation::resetCharset(int scrno)\n{\n  _charset[scrno].cu_cs   = 0;\n  strncpy(_charset[scrno].charset,\"BBBB\",4);\n  _charset[scrno].sa_graphic = false;\n  _charset[scrno].sa_pound   = false;\n  _charset[scrno].graphic = false;\n  _charset[scrno].pound   = false;\n}\n\nvoid Vt102Emulation::setCharset(int n, int cs) // on both screens.\n{\n  _charset[0].charset[n&3] = cs; useCharset(_charset[0].cu_cs);\n  _charset[1].charset[n&3] = cs; useCharset(_charset[1].cu_cs);\n}\n\nvoid Vt102Emulation::setAndUseCharset(int n, int cs)\n{\n  CHARSET.charset[n&3] = cs;\n  useCharset(n&3);\n}\n\nvoid Vt102Emulation::useCharset(int n)\n{\n  CHARSET.cu_cs   = n&3;\n  CHARSET.graphic = (CHARSET.charset[n&3] == '0');\n  CHARSET.pound   = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete\n}\n\nvoid Vt102Emulation::setDefaultMargins()\n{\n    _screen[0]->setDefaultMargins();\n    _screen[1]->setDefaultMargins();\n}\n\nvoid Vt102Emulation::setMargins(int t, int b)\n{\n  _screen[0]->setMargins(t, b);\n  _screen[1]->setMargins(t, b);\n}\n\n/*! Save the cursor position and the rendition attribute settings. */\n\nvoid Vt102Emulation::saveCursor()\n{\n  CHARSET.sa_graphic = CHARSET.graphic;\n  CHARSET.sa_pound   = CHARSET.pound; //This mode is obsolete\n  // we are not clear about these\n  //sa_charset = charsets[cScreen->_charset];\n  //sa_charset_num = cScreen->_charset;\n  _currentScreen->saveCursor();\n}\n\n/*! Restore the cursor position and the rendition attribute settings. */\n\nvoid Vt102Emulation::restoreCursor()\n{\n  CHARSET.graphic = CHARSET.sa_graphic;\n  CHARSET.pound   = CHARSET.sa_pound; //This mode is obsolete\n  _currentScreen->restoreCursor();\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                                Mode Operations                            */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n/*\n   Some of the emulations state is either added to the state of the screens.\n\n   This causes some scoping problems, since different emulations choose to\n   located the mode either to the current _screen or to both.\n\n   For strange reasons, the extend of the rendition attributes ranges over\n   all screens and not over the actual _screen.\n\n   We decided on the precise precise extend, somehow.\n*/\n\n// \"Mode\" related part of the state. These are all booleans.\n\nvoid Vt102Emulation::resetModes()\n{\n  resetMode(MODE_Mouse1000); saveMode(MODE_Mouse1000);\n  resetMode(MODE_Mouse1001); saveMode(MODE_Mouse1001);\n  resetMode(MODE_Mouse1002); saveMode(MODE_Mouse1002);\n  resetMode(MODE_Mouse1003); saveMode(MODE_Mouse1003);\n  resetMode(MODE_BracketedPaste);  saveMode(MODE_BracketedPaste);\n\n  resetMode(MODE_AppScreen); saveMode(MODE_AppScreen);\n  // here come obsolete modes\n  resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys);\n  resetMode(MODE_NewLine  );\n    setMode(MODE_Ansi     );\n}\n\nvoid Vt102Emulation::setMode(int m)\n{\n  _currParm.mode[m] = true;\n  switch (m)\n  {\n    case MODE_Mouse1000:\n    case MODE_Mouse1001:\n    case MODE_Mouse1002:\n    case MODE_Mouse1003:\n        Q_EMIT programUsesMouseChanged(false);\n    break;\n\n    case MODE_BracketedPaste:\n        Q_EMIT programBracketedPasteModeChanged(true);\n    break;\n\n    case MODE_AppScreen : _screen[1]->clearSelection();\n                          setScreen(1);\n    break;\n  }\n  if (m < MODES_SCREEN || m == MODE_NewLine)\n  {\n    _screen[0]->setMode(m);\n    _screen[1]->setMode(m);\n  }\n}\n\nvoid Vt102Emulation::resetMode(int m)\n{\n  _currParm.mode[m] = false;\n  switch (m)\n  {\n    case MODE_Mouse1000 :\n    case MODE_Mouse1001 :\n    case MODE_Mouse1002 :\n    case MODE_Mouse1003 :\n        Q_EMIT programUsesMouseChanged(true);\n    break;\n\n    case MODE_BracketedPaste:\n        Q_EMIT programBracketedPasteModeChanged(false);\n    break;\n\n    case MODE_AppScreen : _screen[0]->clearSelection();\n                          setScreen(0);\n    break;\n  }\n  if (m < MODES_SCREEN || m == MODE_NewLine)\n  {\n    _screen[0]->resetMode(m);\n    _screen[1]->resetMode(m);\n  }\n}\n\nvoid Vt102Emulation::saveMode(int m)\n{\n  _saveParm.mode[m] = _currParm.mode[m];\n}\n\nvoid Vt102Emulation::restoreMode(int m)\n{\n  if (_saveParm.mode[m])\n      setMode(m);\n  else\n      resetMode(m);\n}\n\nbool Vt102Emulation::getMode(int m)\n{\n  return _currParm.mode[m];\n}\n\nchar Vt102Emulation::getErase() const\n{\n  KeyboardTranslator::Entry entry = _keyTranslator->findEntry(\n                                            Qt::Key_Backspace,\n                                            Qt::NoModifier);\n\n  if ( entry.text ().size () > 0 )\n      return entry.text()[0];\n  else\n      return '\\b';\n}\n\n/* ------------------------------------------------------------------------- */\n/*                                                                           */\n/*                               Diagnostic                                  */\n/*                                                                           */\n/* ------------------------------------------------------------------------- */\n\n/*! shows the contents of the scan buffer.\n\n    This functions is used for diagnostics. It is called by @e ReportErrorToken\n    to inform about strings that cannot be decoded or handled by the emulation.\n\n    @sa ReportErrorToken\n*/\n\nstatic void hexdump(int* s, int len)\n{ int i;\n  for (i = 0; i < len; i++)\n  {\n    if (s[i] == '\\\\')\n      printf(\"\\\\\\\\\");\n    else\n    if ((s[i]) > 32 && s[i] < 127)\n      printf(\"%c\",s[i]);\n    else\n      printf(\"\\\\%04x(hex)\",s[i]);\n  }\n}\n\nvoid Vt102Emulation::scan_buffer_report() {\n  if (ppos == 0 || (ppos == 1 && (pbuf[0] & 0xff) >= 32)) {\n    return;\n  }\n  printf(\"token: \");\n  hexdump(pbuf,ppos);\n  printf(\"\\n\");\n}\n\n/*!\n*/\n\nvoid Vt102Emulation::ReportErrorToken()\n{\n  // #ifndef NDEBUG\n  //   printf(\"undecodable \"); scan_buffer_report();\n  // #endif\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/Vt102Emulation.h",
    "content": "/*\n    This file is part of Konsole, an X terminal.\n\n    Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>\n    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n    02110-1301  USA.\n*/\n\n#ifndef VT102EMULATION_H\n#define VT102EMULATION_H\n\n// Standard Library\n#include <stdio.h>\n\n// Qt\n#include <QHash>\n#include <QKeyEvent>\n#include <QTimer>\n\n// Konsole\n#include \"unix/Emulation.h\"\n#include \"unix/Screen.h\"\n\n#define MODE_AppScreen      (MODES_SCREEN+0)\n#define MODE_AppCuKeys      (MODES_SCREEN+1)\n#define MODE_AppKeyPad      (MODES_SCREEN+2)\n#define MODE_Mouse1000      (MODES_SCREEN+3)\n#define MODE_Mouse1001      (MODES_SCREEN+4)\n#define MODE_Mouse1002      (MODES_SCREEN+5)\n#define MODE_Mouse1003      (MODES_SCREEN+6)\n#define MODE_Ansi           (MODES_SCREEN+7)\n#define MODE_BracketedPaste (MODES_SCREEN+8)\n#define MODE_total          (MODES_SCREEN+9)\n\nstruct DECpar\n{\n  bool mode[MODE_total];\n};\n\nstruct CharCodes\n{\n  // coding info\n  char charset[4]; //\n  int  cu_cs;      // actual charset.\n  bool graphic;    // Some VT100 tricks\n  bool pound  ;    // Some VT100 tricks\n  bool sa_graphic; // saved graphic\n  bool sa_pound;   // saved pound\n};\n\n/**\n * Provides an xterm compatible terminal emulation based on the DEC VT102 terminal.\n * A full description of this terminal can be found at http://vt100.net/docs/vt102-ug/\n *\n * In addition, various additional xterm escape sequences are supported to provide\n * features such as mouse input handling.\n * See http://rtfm.etla.org/xterm/ctlseq.html for a description of xterm's escape\n * sequences.\n *\n */\nclass Vt102Emulation : public Emulation\n{\nQ_OBJECT\n\npublic:\n\n  /** Constructs a new emulation */\n  Vt102Emulation();\n  ~Vt102Emulation();\n\n  // reimplemented\n  virtual void clearEntireScreen();\n  virtual void reset();\n\n  // reimplemented\n  virtual char getErase() const;\n\npublic Q_SLOTS:\n\n  // reimplemented\n  virtual void sendString(const char*,int length = -1);\n  virtual void sendText(const QString& text);\n  virtual void sendKeyEvent(QKeyEvent*);\n  virtual void sendMouseEvent( int buttons, int column, int line , int eventType );\n\nprotected:\n  // reimplemented\n  virtual void setMode    (int mode);\n  virtual void resetMode  (int mode);\n\n  // reimplemented\n  virtual void receiveChar(int cc);\n\n\nprivate Q_SLOTS:\n\t\t\n  //causes changeTitle() to be emitted for each (int,QString) pair in pendingTitleUpdates\n  //used to buffer multiple title updates\n  void updateTitle();\n\n\nprivate:\n  unsigned short applyCharset(unsigned short c);\n  void setCharset(int n, int cs);\n  void useCharset(int n);\n  void setAndUseCharset(int n, int cs);\n  void saveCursor();\n  void restoreCursor();\n  void resetCharset(int scrno);\n\n  void setMargins(int top, int bottom);\n  //set margins for all screens back to their defaults\n  void setDefaultMargins();\n\n  // returns true if 'mode' is set or false otherwise\n  bool getMode    (int mode);\n  // saves the current boolean value of 'mode'\n  void saveMode   (int mode);\n  // restores the boolean value of 'mode'\n  void restoreMode(int mode);\n  // resets all modes\n  void resetModes();\n\n  void resetToken();\n#define MAXPBUF 80\n  void pushToToken(int cc);\n  int pbuf[MAXPBUF]; //FIXME: overflow?\n  int ppos;\n#define MAXARGS 15\n  void addDigit(int dig);\n  void addArgument();\n  int argv[MAXARGS];\n  int argc;\n  void initTokenizer();\n  int tbl[256];\n\n  void scan_buffer_report(); //FIXME: rename\n  void ReportErrorToken();   //FIXME: rename\n\n  void tau(int code, int p, int q);\n  void XtermHack();\n\n  void reportTerminalType();\n  void reportSecondaryAttributes();\n  void reportStatus();\n  void reportAnswerBack();\n  void reportCursorPosition();\n  void reportTerminalParms(int p);\n\n  void onScrollLock();\n  void scrollLock(const bool lock);\n\n  // clears the screen and resizes it to the specified\n  // number of columns\n  void clearScreenAndSetColumns(int columnCount);\n\n  CharCodes _charset[2];\n\n  DECpar _currParm;\n  DECpar _saveParm;\n\n  //hash table and timer for buffering calls to the session instance\n  //to update the name of the session\n  //or window title.\n  //these calls occur when certain escape sequences are seen in the\n  //output from the terminal\n  QHash<int,QString> _pendingTitleUpdates;\n  QTimer* _titleUpdateTimer;\n\n};\n\n#endif // VT102EMULATION_H\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/konsole_wcwidth.cpp",
    "content": "/* $XFree86: xc/programs/xterm/wcwidth.character,v 1.3 2001/07/29 22:08:16 tsi Exp $ */\n/*\n * This is an implementation of wcwidth() and wcswidth() as defined in\n * \"The Single UNIX Specification, Version 2, The Open Group, 1997\"\n * <http://www.UNIX-systems.org/online.html>\n *\n * Markus Kuhn -- 2001-01-12 -- public domain\n */\n\n#include \"unix/konsole_wcwidth.h\"\n\nstruct interval {\n  unsigned short first;\n  unsigned short last;\n};\n\n/* auxiliary function for binary search in interval table */\nstatic int bisearch(quint16 ucs, const struct interval *table, int max) {\n  int min = 0;\n  int mid;\n\n  if (ucs < table[0].first || ucs > table[max].last)\n    return 0;\n  while (max >= min) {\n    mid = (min + max) / 2;\n    if (ucs > table[mid].last)\n      min = mid + 1;\n    else if (ucs < table[mid].first)\n      max = mid - 1;\n    else\n      return 1;\n  }\n\n  return 0;\n}\n\n\n/* The following functions define the column width of an ISO 10646\n * character as follows:\n *\n *    - The null character (U+0000) has a column width of 0.\n *\n *    - Other C0/C1 control characters and DEL will lead to a return\n *      value of -1.\n *\n *    - Non-spacing and enclosing combining characters (general\n *      category code Mn or Me in the Unicode database) have a\n *      column width of 0.\n *\n *    - Other format characters (general category code Cf in the Unicode\n *      database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.\n *\n *    - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)\n *      have a column width of 0.\n *\n *    - Spacing characters in the East Asian Wide (W) or East Asian\n *      FullWidth (F) category as defined in Unicode Technical\n *      Report #11 have a column width of 2.\n *\n *    - All remaining characters (including all printable\n *      ISO 8859-1 and WGL4 characters, Unicode control characters,\n *      etc.) have a column width of 1.\n *\n * This implementation assumes that quint16 characters are encoded\n * in ISO 10646.\n */\n\nint konsole_wcwidth(quint16 ucs)\n{\n  /* sorted list of non-overlapping intervals of non-spacing characters */\n  static const struct interval combining[] = {\n    { 0x0300, 0x034E }, { 0x0360, 0x0362 }, { 0x0483, 0x0486 },\n    { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },\n    { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },\n    { 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 },\n    { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },\n    { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },\n    { 0x07A6, 0x07B0 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C },\n    { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 },\n    { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC },\n    { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 },\n    { 0x0A02, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 },\n    { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 },\n    { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 },\n    { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0B01, 0x0B01 },\n    { 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 },\n    { 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 },\n    { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 },\n    { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 },\n    { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },\n    { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA },\n    { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 },\n    { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 },\n    { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD },\n    { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 },\n    { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 },\n    { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC },\n    { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 },\n    { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 },\n    { 0x1160, 0x11FF }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 },\n    { 0x17C9, 0x17D3 }, { 0x180B, 0x180E }, { 0x18A9, 0x18A9 },\n    { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x206A, 0x206F },\n    { 0x20D0, 0x20E3 }, { 0x302A, 0x302F }, { 0x3099, 0x309A },\n    { 0xFB1E, 0xFB1E }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF },\n    { 0xFFF9, 0xFFFB }\n  };\n\n  /* test for 8-bit control characters */\n  if (ucs == 0)\n    return 0;\n  if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))\n    return -1;\n\n  /* binary search in table of non-spacing characters */\n  if (bisearch(ucs, combining,\n\t       sizeof(combining) / sizeof(struct interval) - 1))\n    return 0;\n\n  /* if we arrive here, ucs is not a combining or C0/C1 control character */\n\n  return 1 +\n    (ucs >= 0x1100 &&\n     (ucs <= 0x115f ||                    /* Hangul Jamo init. consonants */\n      (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&\n       ucs != 0x303f) ||                  /* CJK ... Yi */\n      (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */\n      (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */\n      (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */\n      (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */\n      (ucs >= 0xffe0 && ucs <= 0xffe6) /* do not compare UINT16 with 0x20000 ||\n      (ucs >= 0x20000 && ucs <= 0x2ffff) */));\n}\n\n// single byte char: +1, multi byte char: +2\nint string_width( const QString &txt )\n{\n  int w = 0;\n  for ( int i = 0; i < txt.length(); ++i )\n     w += konsole_wcwidth( txt[ i ].unicode() );\n return w;\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/konsole_wcwidth.h",
    "content": "/* $XFree86: xc/programs/xterm/wcwidth.h,v 1.2 2001/06/18 19:09:27 dickey Exp $ */\n\n/* Markus Kuhn -- 2001-01-12 -- public domain */\n/* Adaptions for KDE by Waldo Bastian <bastian@kde.org> */\n/*\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>\n*/\n\n\n#ifndef\t_KONSOLE_WCWIDTH_H_\n#define\t_KONSOLE_WCWIDTH_H_\n\n// Qt\n#include <QString>\n\nint konsole_wcwidth(quint16 ucs);\n\nint string_width( const QString &txt );\n\n#endif\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/kpty.cpp",
    "content": "/*\n\n   This file is part of the KDE libraries\n   Copyright (C) 2002, 2013 Waldo Bastian <bastian@kde.org>\n   Copyright (C) 2002-2003,2007 Oswald Buddenhagen <ossi@kde.org>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n   This library is free software: you can redistribute it and/or\n   modify it under the terms of the GNU Library General Public\n   License as published by the Free Software Foundation; either\n   version 2 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Library General Public License for more details.\n\n   You should have received a copy of the GNU Library General Public License\n   along with this library; see the file COPYING.LIB.  If not, write to\n   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n   Boston, MA 02110-1301, USA.\n*/\n\n#ifdef HAVE_CONFIG_H\n#  include \"config.h\"\n#endif\n\n#include \"unix/kpty_p.h\"\n\n#ifdef __sgi\n#define __svr4__\n#endif\n\n#ifdef __osf__\n#define _OSF_SOURCE\n#include <float.h>\n#endif\n\n#ifdef _AIX\n#define _ALL_SOURCE\n#endif\n\n// __USE_XOPEN isn't defined by default in ICC\n// (needed for ptsname(), grantpt() and unlockpt())\n#ifdef __INTEL_COMPILER\n#  ifndef __USE_XOPEN\n#    define __USE_XOPEN\n#  endif\n#endif\n\n#include <sys/types.h>\n#include <sys/ioctl.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n#include <sys/stat.h>\n#include <sys/param.h>\n\n#include <errno.h>\n#include <fcntl.h>\n#include <time.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <grp.h>\n\n#ifdef Q_OS_MAC\n# include <util.h>\n#else\n# if defined(HAVE_PTY_H)\n#  include <pty.h>\n# endif\n# ifdef HAVE_LIBUTIL_H\n#  include <libutil.h>\n# elif defined(HAVE_UTIL_H)\n#  include <util.h>\n# endif\n#endif\n\n/*\n#ifdef HAVE_UTEMPTER\nextern \"C\" {\n# include <utempter.h>\n}\n#else\n# include <utmp.h>\n# ifdef HAVE_UTMPX\n#  include <utmpx.h>\n# endif\n# if !defined(_PATH_UTMPX) && defined(_UTMPX_FILE)\n#  define _PATH_UTMPX _UTMPX_FILE\n# endif\n# if !defined(_PATH_WTMPX) && defined(_WTMPX_FILE)\n#  define _PATH_WTMPX _WTMPX_FILE\n# endif\n#endif\n*/\n\n/* for HP-UX (some versions) the extern C is needed, and for other\n   platforms it doesn't hurt */\nextern \"C\" {\n#include <termios.h>\n#if defined(HAVE_TERMIO_H)\n# include <termio.h> // struct winsize on some systems\n#endif\n}\n\n#if defined (_HPUX_SOURCE)\n# define _TERMIOS_INCLUDED\n# include <bsdtty.h>\n#endif\n\n#if defined (HAVE_STROPTS_H)\n# include <stropts.h>\t        // Defines I_PUSH\n# define _NEW_TTY_CTRL\n#elif defined (HAVE_SYS_STROPTS_H)\n# include <sys/stropts.h>\t// Defines I_PUSH\n# define _NEW_TTY_CTRL\n#endif\n\n#if defined(HAVE_TCGETATTR)\n# define _tcgetattr(fd, ttmode) tcgetattr(fd, ttmode)\n#elif defined(TIOCGETA)\n# define _tcgetattr(fd, ttmode) ioctl(fd, TIOCGETA, (char *)ttmode)\n#elif defined(TCGETS)\n# define _tcgetattr(fd, ttmode) ioctl(fd, TCGETS, (char *)ttmode)\n#else\n# error No method available to get terminal attributes\n#endif\n\n#if defined(HAVE_TCSETATTR) && defined(TCSANOW)\n# define _tcsetattr(fd, ttmode) tcsetattr(fd, TCSANOW, ttmode)\n#elif defined(TIOCSETA)\n# define _tcsetattr(fd, ttmode) ioctl(fd, TIOCSETA, (char *)ttmode)\n#elif defined(TCSETS)\n# define _tcsetattr(fd, ttmode) ioctl(fd, TCSETS, (char *)ttmode)\n#else\n# error No method available to set terminal attributes\n#endif\n\n#include <QtCore>\n\n// not defined on HP-UX for example\n#ifndef CTRL\n# define CTRL(x) ((x) & 037)\n#endif\n\n#define TTY_GROUP \"tty\"\n\n#ifndef PATH_MAX\n# ifdef MAXPATHLEN\n#  define PATH_MAX MAXPATHLEN\n# else\n#  define PATH_MAX 1024\n# endif\n#endif\n\n///////////////////////\n// private functions //\n///////////////////////\n\n//////////////////\n// private data //\n//////////////////\n\nKPtyPrivate::KPtyPrivate(KPty* parent) :\n    masterFd(-1), slaveFd(-1), ownMaster(true), q_ptr(parent)\n{\n}\n\nKPtyPrivate::KPtyPrivate(KPty *parent, int _masterFd, int _slaveFd):\n    masterFd(_masterFd), slaveFd(_slaveFd), ownMaster(true), q_ptr(parent)\n{\n}\n\n\nKPtyPrivate::~KPtyPrivate()\n{\n}\n\nbool KPtyPrivate::chownpty(bool)\n{\n//    return !QProcess::execute(KStandardDirs::findExe(\"kgrantpty\"),\n//        QStringList() << (grant?\"--grant\":\"--revoke\") << QString::number(masterFd));\n    return true;\n}\n\n/////////////////////////////\n// public member functions //\n/////////////////////////////\n\nKPty::KPty() :\n    d_ptr(new KPtyPrivate(this))\n{\n}\n\nKPty::KPty(int masterFd, int slaveFd) :\n    d_ptr(new KPtyPrivate(this, masterFd, slaveFd))\n{\n}\n\nKPty::KPty(KPtyPrivate *d) :\n    d_ptr(d)\n{\n    d_ptr->q_ptr = this;\n}\n\nKPty::~KPty()\n{\n    close();\n    delete d_ptr;\n}\n\nbool KPty::open()\n{\n  Q_D(KPty);\n\n  if (d->masterFd >= 0) {\n      return true;\n  }\n\n  d->ownMaster = true;\n\n  QByteArray ptyName;\n\n  // Find a master pty that we can open ////////////////////////////////\n\n  // Because not all the pty animals are created equal, they want to\n  // be opened by several different methods.\n\n  // We try, as we know them, one by one.\n\n#ifdef HAVE_OPENPTY\n\n  char ptsn[PATH_MAX];\n  if (::openpty( &d->masterFd, &d->slaveFd, ptsn, nullptr, nullptr))\n  {\n    d->masterFd = -1;\n    d->slaveFd = -1;\n    qWarning() << \"Can't open a pseudo teletype\";\n    return false;\n  }\n  d->ttyName = ptsn;\n\n#else\n\n#ifdef HAVE__GETPTY // irix\n\n  char *ptsn = _getpty(&d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0);\n  if (ptsn) {\n    d->ttyName = ptsn;\n    goto grantedpt;\n  }\n\n#elif defined(HAVE_PTSNAME) || defined(TIOCGPTN)\n\n#ifdef HAVE_POSIX_OPENPT\n  d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY);\n#elif defined(HAVE_GETPT)\n  d->masterFd = ::getpt();\n#elif defined(PTM_DEVICE)\n  d->masterFd = ::open(PTM_DEVICE, O_RDWR|O_NOCTTY);\n#else\n# error No method to open a PTY master detected.\n#endif\n  if (d->masterFd >= 0)\n  {\n#ifdef HAVE_PTSNAME\n    char *ptsn = ptsname(d->masterFd);\n    if (ptsn) {\n        d->ttyName = ptsn;\n#else\n    int ptyno;\n    if (!ioctl(d->masterFd, TIOCGPTN, &ptyno)) {\n        char buf[32];\n        sprintf(buf, \"/dev/pts/%d\", ptyno);\n        d->ttyName = buf;\n#endif\n#ifdef HAVE_GRANTPT\n        if (!grantpt(d->masterFd))\n           goto grantedpt;\n#else\n        goto gotpty;\n#endif\n    }\n    ::close(d->masterFd);\n    d->masterFd = -1;\n  }\n#endif // HAVE_PTSNAME || TIOCGPTN\n\n  // Linux device names, FIXME: Trouble on other systems?\n  for (const char* s3 = \"pqrstuvwxyzabcde\"; *s3; s3++)\n  {\n    for (const char* s4 = \"0123456789abcdef\"; *s4; s4++)\n    {\n      ptyName = QString().sprintf(\"/dev/pty%c%c\", *s3, *s4).toLatin1();\n      d->ttyName = QString().sprintf(\"/dev/tty%c%c\", *s3, *s4).toLatin1();\n\n      d->masterFd = ::open(ptyName.data(), O_RDWR);\n      if (d->masterFd >= 0)\n      {\n#ifdef Q_OS_SOLARIS\n        /* Need to check the process group of the pty.\n         * If it exists, then the slave pty is in use,\n         * and we need to get another one.\n         */\n        int pgrp_rtn;\n        if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {\n          ::close(d->masterFd);\n          d->masterFd = -1;\n          continue;\n        }\n#endif /* Q_OS_SOLARIS */\n        if (!access(d->ttyName.data(),R_OK|W_OK)) // checks availability based on permission bits\n        {\n          if (!geteuid())\n          {\n            struct group* p = getgrnam(TTY_GROUP);\n            if (!p)\n              p = getgrnam(\"wheel\");\n            gid_t gid = p ? p->gr_gid : getgid ();\n\n\t\t if (!chown(d->ttyName.data(), getuid(), gid)) {\n\t\t\tchmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);\n\t\t }\n\t  }\n\t  goto gotpty;\n\t}\n\t::close(d->masterFd);\n\td->masterFd = -1;\n\t\t}\n\t }\n  }\n\n  qWarning() << \"Can't open a pseudo teletype\";\n  return false;\n\n gotpty:\n  struct stat st;\n  if (stat(d->ttyName.data(), &st))\n    return false; // this just cannot happen ... *cough*  Yeah right, I just\n                  // had it happen when pty #349 was allocated.  I guess\n                  // there was some sort of leak?  I only had a few open.\n  if (((st.st_uid != getuid()) ||\n       (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&\n      !d->chownpty(true))\n  {\n    qWarning()\n      << \"chownpty failed for device \" << ptyName << \"::\" << d->ttyName\n      << \"\\nThis means the communication can be eavesdropped.\" << endl;\n  }\n\n#if defined(HAVE_GRANTPT) || defined(HAVE__GETPTY)\n grantedpt:\n#endif\n\n#ifdef HAVE_REVOKE\n  revoke(d->ttyName.data());\n#endif\n\n#ifdef HAVE_UNLOCKPT\n  unlockpt(d->masterFd);\n#elif defined(TIOCSPTLCK)\n  int flag = 0;\n  ioctl(d->masterFd, TIOCSPTLCK, &flag);\n#endif\n\n  d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY);\n  if (d->slaveFd < 0)\n  {\n    qWarning() << \"Can't open slave pseudo teletype\";\n    ::close(d->masterFd);\n    d->masterFd = -1;\n    return false;\n  }\n\n#if (defined(__svr4__) || defined(__sgi__))\n  // Solaris\n  ioctl(d->slaveFd, I_PUSH, \"ptem\");\n  ioctl(d->slaveFd, I_PUSH, \"ldterm\");\n#endif\n\n#endif /* HAVE_OPENPTY */\n  fcntl(d->masterFd, F_SETFD, FD_CLOEXEC);\n  fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC);\n\n  struct ::termios t;\n  tcGetAttr(&t);\n  t.c_iflag &= ~IXON;\n  t.c_lflag &= ~ECHOCTL;\n  tcSetAttr(&t);\n  return true;\n}\n\nvoid KPty::closeSlave()\n{\n    Q_D(KPty);\n\n    if (d->slaveFd < 0)\n        return;\n    ::close(d->slaveFd);\n    d->slaveFd = -1;\n}\n\nvoid KPty::close()\n{\n   Q_D(KPty);\n\n   if (d->masterFd < 0)\n      return;\n   closeSlave();\n   if (d->ownMaster) {\n#ifndef HAVE_OPENPTY\n   // don't bother resetting unix98 pty, it will go away after closing master anyway.\n   if (memcmp(d->ttyName.data(), \"/dev/pts/\", 9)) {\n      if (!geteuid()) {\n         struct stat st;\n         if (!stat(d->ttyName.data(), &st)) {\n            if (!chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1)) {\n              chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);\n            }\n         }\n      } else {\n         fcntl(d->masterFd, F_SETFD, 0);\n         d->chownpty(false);\n      }\n   }\n   #endif\n   }\n   ::close(d->masterFd);\n   d->masterFd = -1;\n}\n\n// XXX Supposedly, tc[gs]etattr do not work with the master on Solaris.\n// Please verify.\n\nbool KPty::tcGetAttr(struct ::termios *ttmode) const\n{\n    Q_D(const KPty);\n\n    return _tcgetattr(d->masterFd, ttmode) == 0;\n}\n\nbool KPty::tcSetAttr(struct ::termios *ttmode)\n{\n    Q_D(KPty);\n\n    return _tcsetattr(d->masterFd, ttmode) == 0;\n}\n\nbool KPty::setWinSize(int lines, int columns)\n{\n    Q_D(KPty);\n\n    struct winsize winSize;\n    memset(&winSize, 0, sizeof(winSize));\n    winSize.ws_row = (unsigned short)lines;\n    winSize.ws_col = (unsigned short)columns;\n    return ioctl(d->masterFd, TIOCSWINSZ, (char *)&winSize) == 0;\n}\n\nbool KPty::setEcho(bool echo)\n{\n    struct ::termios ttmode;\n    if (!tcGetAttr(&ttmode))\n        return false;\n    if (!echo)\n        ttmode.c_lflag &= ~ECHO;\n    else\n        ttmode.c_lflag |= ECHO;\n    return tcSetAttr(&ttmode);\n}\n\nconst char *KPty::ttyName() const\n{\n    Q_D(const KPty);\n\n    return d->ttyName.data();\n}\n\nint KPty::masterFd() const\n{\n    Q_D(const KPty);\n\n    return d->masterFd;\n}\n\nint KPty::slaveFd() const\n{\n    Q_D(const KPty);\n\n    return d->slaveFd;\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/kpty.h",
    "content": "/* This file is part of the KDE libraries\n\n    Copyright (C) 2003, 2007, 2013 Oswald Buddenhagen <ossi@kde.org>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This library is free software: you can redistribute it and/or\n    modify it under the terms of the GNU Library General Public\n    License as published by the Free Software Foundation; either\n    version 2 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Library General Public License for more details.\n\n    You should have received a copy of the GNU Library General Public License\n    along with this library; see the file COPYING.LIB.  If not, write to\n    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n    Boston, MA 02110-1301, USA.\n*/\n\n#ifndef kpty_h\n#define kpty_h\n\n#include <QtCore>\n\nstruct KPtyPrivate;\nstruct termios;\n\n/**\n * Provides primitives for opening & closing a pseudo TTY pair, assigning the\n * controlling TTY, utmp registration and setting various terminal attributes.\n */\nclass KPty {\n    Q_DECLARE_PRIVATE(KPty)\n\npublic:\n\n  /**\n   * Constructor\n   */\n  KPty();\n  KPty(int masterFd, int slaveFd);\n\n  /**\n   * Destructor:\n   *\n   *  If the pty is still open, it will be closed. Note, however, that\n   *  an utmp registration is @em not undone.\n  */\n  ~KPty();\n\n  /**\n   * Create a pty master/slave pair.\n   *\n   * @return true if a pty pair was successfully opened\n   */\n  bool open();\n\n  /**\n   * Close the pty master/slave pair.\n   */\n  void close();\n\n  /**\n   * Close the pty slave descriptor.\n   *\n   * When creating the pty, KPty also opens the slave and keeps it open.\n   * Consequently the master will never receive an EOF notification.\n   * Usually this is the desired behavior, as a closed pty slave can be\n   * reopened any time - unlike a pipe or socket. However, in some cases\n   * pipe-alike behavior might be desired.\n   *\n   * After this function was called, slaveFd() and setCTty() cannot be\n   * used.\n   */\n  void closeSlave();\n\n  /**\n   * Wrapper around tcgetattr(3).\n   *\n   * This function can be used only while the PTY is open.\n   * You will need an #include &lt;termios.h&gt; to do anything useful\n   * with it.\n   *\n   * @param ttmode a pointer to a termios structure.\n   *  Note: when declaring ttmode, @c struct @c ::termios must be used -\n   *  without the '::' some version of HP-UX thinks, this declares\n   *  the struct in your class, in your method.\n   * @return @c true on success, false otherwise\n   */\n  bool tcGetAttr(struct ::termios *ttmode) const;\n\n  /**\n   * Wrapper around tcsetattr(3) with mode TCSANOW.\n   *\n   * This function can be used only while the PTY is open.\n   *\n   * @param ttmode a pointer to a termios structure.\n   * @return @c true on success, false otherwise. Note that success means\n   *  that @em at @em least @em one attribute could be set.\n   */\n  bool tcSetAttr(struct ::termios *ttmode);\n\n  /**\n   * Change the logical (screen) size of the pty.\n   * The default is 24 lines by 80 columns.\n   *\n   * This function can be used only while the PTY is open.\n   *\n   * @param lines the number of rows\n   * @param columns the number of columns\n   * @return @c true on success, false otherwise\n   */\n  bool setWinSize(int lines, int columns);\n\n  /**\n   * Set whether the pty should echo input.\n   *\n   * Echo is on by default.\n   * If the output of automatically fed (non-interactive) PTY clients\n   * needs to be parsed, disabling echo often makes it much simpler.\n   *\n   * This function can be used only while the PTY is open.\n   *\n   * @param echo true if input should be echoed.\n   * @return @c true on success, false otherwise\n   */\n  bool setEcho(bool echo);\n\n  /**\n   * @return the name of the slave pty device.\n   *\n   * This function should be called only while the pty is open.\n   */\n  const char *ttyName() const;\n\n  /**\n   * @return the file descriptor of the master pty\n   *\n   * This function should be called only while the pty is open.\n   */\n  int masterFd() const;\n\n  /**\n   * @return the file descriptor of the slave pty\n   *\n   * This function should be called only while the pty slave is open.\n   */\n  int slaveFd() const;\n\nprotected:\n  /**\n   * @internal\n   */\n  KPty(KPtyPrivate *d);\n\n  /**\n   * @internal\n   */\n  KPtyPrivate * const d_ptr;\n};\n\n#endif\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/unix/kpty_p.h",
    "content": "/* This file is part of the KDE libraries\n\n    Copyright (C) 2003, 2007, 2013 Oswald Buddenhagen <ossi@kde.org>\n\n    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008\n\n    This library is free software: you can redistribute it and/or\n    modify it under the terms of the GNU Library General Public\n    License as published by the Free Software Foundation; either\n    version 2 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Library General Public License for more details.\n\n    You should have received a copy of the GNU Library General Public License\n    along with this library; see the file COPYING.LIB.  If not, write to\n    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n    Boston, MA 02110-1301, USA.\n*/\n\n#ifndef kpty_p_h\n#define kpty_p_h\n\n#include \"unix/kpty.h\"\n\n#include <QByteArray>\n\nstruct KPtyPrivate {\n    Q_DECLARE_PUBLIC(KPty)\n\n    KPtyPrivate(KPty* parent);\n    KPtyPrivate(KPty* parent, int masterFd, int slaveFd);\n\n    virtual ~KPtyPrivate();\n\n    bool chownpty(bool grant);\n\n    int masterFd;\n    int slaveFd;\n    bool ownMaster:1;\n\n    QByteArray ttyName;\n\n    KPty *q_ptr;\n};\n\n#endif\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/win32/QTerminalColors.cpp",
    "content": "/*\n\nCopyright (C) 2011-2019 Michael Goffioul\n\nThis file is part of QConsole.\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not,\nsee <https://www.gnu.org/licenses/>.\n\n*/\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n\n#include \"QTerminalColors.h\"\n\n//////////////////////////////////////////////////////////////////////////////\n\nQConsoleColors::QConsoleColors ()\n    : QMap<int, QColor> ()\n{\n  (*this)[0]  = Qt::white;\n  (*this)[1]  = Qt::blue;\n  (*this)[2]  = Qt::green;\n  (*this)[3]  = Qt::cyan;\n  (*this)[4]  = Qt::red;\n  (*this)[5]  = Qt::magenta;\n  (*this)[6]  = Qt::yellow;\n  (*this)[7]  = Qt::black;\n  (*this)[8]  = Qt::lightGray;\n  (*this)[9]  = Qt::darkBlue;\n  (*this)[10] = Qt::darkGreen;\n  (*this)[11] = Qt::darkCyan;\n  (*this)[12] = Qt::darkRed;\n  (*this)[13] = Qt::darkMagenta;\n  (*this)[14] = Qt::darkYellow;\n  (*this)[15] = Qt::darkGray;\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/win32/QTerminalColors.h",
    "content": "/*\n\nCopyright (C) 2011-2019 Michael Goffioul\n\nThis file is part of QConsole.\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not,\nsee <https://www.gnu.org/licenses/>.\n\n*/\n\n#ifndef __QConsoleColors_h__\n#define __QConsoleColors_h__ 1\n\n#include <QColor>\n#include <QMap>\n\n//////////////////////////////////////////////////////////////////////////////\n\nclass QConsoleColors : public QMap<int, QColor>\n{\npublic:\n  QConsoleColors ();\n};\n\n//////////////////////////////////////////////////////////////////////////////\n\n#endif // __QConsoleColors_h__\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp",
    "content": "/*\n\nCopyright (C) 2011-2026 The Octave Project Developers\n\nThis file is part of QConsole.\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not,\nsee <https://www.gnu.org/licenses/>.\n\n*/\n\n#include <algorithm>\n#include <cmath>\n#include <csignal>\n#include <cstdio>\n#include <cstdarg>\n#include <cstring>\n\n#define WIN32_LEAN_AND_MEAN\n#if ! defined (_WIN32_WINNT) && ! defined (NTDDI_VERSION)\n#  define _WIN32_WINNT 0x0500\n#endif\n#include <windows.h>\n#include <fcntl.h>\n#include <io.h>\n#include <versionhelpers.h>\n\n#include <QtDebug>\n#include <QApplication>\n#include <QClipboard>\n#include <QColor>\n#include <QFont>\n#include <QGridLayout>\n#include <QPaintEvent>\n#include <QPainter>\n#include <QResizeEvent>\n#include <QScrollBar>\n#include <QSize>\n#include <QSizeF>\n#include <QThread>\n#include <QTimer>\n#include <QToolTip>\n#include <QCursor>\n#include <QMessageBox>\n#include <QDragEnterEvent>\n#include <QDropEvent>\n#include <QUrl>\n#include <QMimeData>\n\n#include \"QWinTerminalImpl.h\"\n#include \"QTerminalColors.h\"\n\n#include \"oct-shlib.h\"\n\n// Uncomment to log activity to LOGFILENAME\n// #define DEBUG_QCONSOLE\n#define LOGFILENAME \"QConsole.log\"\n// Uncomment to create hidden console window\n#define HIDDEN_CONSOLE\n\n#ifdef _MSC_VER\n#  pragma warning(disable : 4996)\n#endif\n\n//////////////////////////////////////////////////////////////////////////////\n\nclass QConsoleView : public QWidget\n{\npublic:\n  QConsoleView (QWinTerminalImpl *parent = 0) : QWidget (parent), q (parent) { }\n  ~QConsoleView () { }\n\nprotected:\n  void paintEvent (QPaintEvent *event) { q->viewPaintEvent (this, event); }\n  void resizeEvent (QResizeEvent *event) { q->viewResizeEvent (this, event); }\n\nprivate:\n  QWinTerminalImpl *q;\n};\n\n//////////////////////////////////////////////////////////////////////////////\n\nclass QConsoleThread : public QThread\n{\npublic:\n  QConsoleThread (QWinTerminalImpl *console) : QThread (console), q (console) { }\n\nprotected:\n  void run ()\n    { q->start (); }\n\nprivate:\n  QWinTerminalImpl *q;\n};\n\n//////////////////////////////////////////////////////////////////////////////\n\nstatic QString translateKey (QKeyEvent *ev)\n{\n  QString esc = \"\\x1b\";\n  QString s;\n\n  if (ev->key () == Qt::Key_Delete)\n    s = esc + \"[C\\b\";\n  else if (!ev->text ().isEmpty ())\n    s = ev->text ();\n  else\n    {\n\n      switch (ev->key ())\n        {\n        case Qt::Key_Up:\n          s = esc + \"[A\";\n          break;\n\n        case Qt::Key_Down:\n          s = esc + \"[B\";\n          break;\n\n        case Qt::Key_Right:\n          s = esc + \"[C\";\n          break;\n\n        case Qt::Key_Left:\n          s = esc + \"[D\";\n          break;\n\n        case Qt::Key_Home:\n          s = esc + \"[H\";\n          break;\n\n        case Qt::Key_End:\n          s = esc + \"[F\";\n          break;\n\n        case Qt::Key_Insert:\n          s = esc + \"[2~\";\n          break;\n\n        case Qt::Key_PageUp:\n          s = esc + \"[5~\";\n          break;\n\n        case Qt::Key_PageDown:\n          s = esc + \"[6~\";\n          break;\n\n        case Qt::Key_Escape:\n          s = esc;\n          break;\n\n        default:\n          break;\n        }\n    }\n\n  return s;\n}\n\nclass QConsolePrivate\n{\n  friend class QWinTerminalImpl;\n\npublic:\n\n  enum KeyboardCursorType\n    {\n      BlockCursor,\n      UnderlineCursor,\n      IBeamCursor\n    };\n\n  QConsolePrivate (QWinTerminalImpl *parent, const QString& cmd = QString ());\n  ~QConsolePrivate ();\n\n  void updateConsoleSize (bool sync = false, bool allow_smaller_width = false);\n  void syncConsoleParameters ();\n  void grabConsoleBuffer (CHAR_INFO* buf = 0);\n  void updateHorizontalScrollBar ();\n  void updateVerticalScrollBar ();\n  void setHorizontalScrollValue (int value);\n  void setVerticalScrollValue (int value);\n  void updateConsoleView (bool grab = true);\n  void monitorConsole ();\n  void startCommand ();\n  void sendConsoleText (const QString& s);\n  QRect cursorRect ();\n  QRect boundingRect ();\n  void selectAll ();\n  void selectWord (const QPoint& cellPos);\n  void selectLine (const QPoint& cellPos);\n\n  void log (const char *fmt, ...);\n\n  void closeStandardIO (int fd, DWORD stdHandleId, const char *name);\n  void setupStandardIO (DWORD stdHandleId, int fd, const char *name,\n                        const char *devName);\n\n  QPoint posToCell (const QPoint& pt);\n  QString getSelection ();\n  void updateSelection ();\n  void clearSelection ();\n\n  QColor backgroundColor () const;\n  QColor foregroundColor () const;\n  QColor selectionColor () const;\n  QColor cursorColor () const;\n\n  void setBackgroundColor (const QColor& color);\n  void setForegroundColor (const QColor& color);\n  void setSelectionColor (const QColor& color);\n  void setCursorColor (bool useForegroundColor, const QColor& color);\n  void setScrollBufferSize (int value);\n\n  void drawTextBackground (QPainter& p, int cx1, int cy1, int cx2, int cy2,\n                           int ch);\n\n  void drawSelection (QPainter& p, int cx1, int cy1, int cx2, int cy2, int ch);\n\n  void drawCursor (QPainter& p);\n\n  void drawText (QPainter& p, int cx1, int cy1, int cx2, int cy2, int ch);\n\nprivate:\n  QWinTerminalImpl *q;\n\nprivate:\n  QFont m_font;\n  QString m_command;\n  QConsoleColors m_colors;\n  bool m_inWheelEvent;\n  QString m_title;\n\n  QSizeF m_charSize;\n  QSize m_bufferSize;\n  QRect m_consoleRect;\n  bool m_auto_scroll;\n  QPoint m_cursorPos;\n  bool m_cursorBlinking;\n  bool m_hasBlinkingCursor;\n  QTimer *m_blinkCursorTimer;\n  KeyboardCursorType m_cursorType;\n\n  QPoint m_beginSelection;\n  QPoint m_endSelection;\n  bool m_settingSelection;\n\n  QColor m_selectionColor;\n  QColor m_cursorColor;\n\n  HANDLE m_stdOut;\n  HWND m_consoleWindow;\n  CHAR_INFO *m_buffer;\n  CHAR_INFO *m_tmpBuffer;\n  HANDLE m_process;\n\n  QConsoleView *m_consoleView;\n  QScrollBar *m_horizontalScrollBar;\n  QScrollBar *m_verticalScrollBar;\n  QTimer *m_consoleWatcher;\n  QConsoleThread *m_consoleThread;\n\n  // The delay in milliseconds between redrawing blinking text.\n  static const int BLINK_DELAY = 500;\n};\n\nstatic void maybeSwapPoints (QPoint& begin, QPoint& end)\n{\n  if (end.y () < begin.y ()\n      || (end.y () == begin.y () && end.x () < begin.x ()))\n    std::swap (begin, end);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\n#ifdef HIDDEN_CONSOLE\n\n#  if ! defined (NTDDI_VERSION) || ! defined (NTDDI_WIN11_GE) \\\n      || (NTDDI_VERSION < NTDDI_WIN11_GE)\n\n// The necessary types are only defined when targeting Windows 11 24H2 or\n// later and in sufficiently recent versions of mingw-w64.\n// Copy the definition from the mingw-w64 headers here for these cases.\n\ntypedef enum ALLOC_CONSOLE_MODE\n{\n  ALLOC_CONSOLE_MODE_DEFAULT = 0,\n  ALLOC_CONSOLE_MODE_NEW_WINDOW = 1,\n  ALLOC_CONSOLE_MODE_NO_WINDOW = 2\n} ALLOC_CONSOLE_MODE;\n\ntypedef struct ALLOC_CONSOLE_OPTIONS\n{\n  ALLOC_CONSOLE_MODE mode;\n  WINBOOL useShowWindow;\n  WORD showWindow;\n} ALLOC_CONSOLE_OPTIONS, *PALLOC_CONSOLE_OPTIONS;\n\ntypedef enum ALLOC_CONSOLE_RESULT\n{\n  ALLOC_CONSOLE_RESULT_NO_CONSOLE = 0,\n  ALLOC_CONSOLE_RESULT_NEW_CONSOLE = 1,\n  ALLOC_CONSOLE_RESULT_EXISTING_CONSOLE = 2\n} ALLOC_CONSOLE_RESULT, *PALLOC_CONSOLE_RESULT;\n\n#  endif\n\ntypedef HRESULT (WINAPI *AllocConsoleWithOptions_t)\n    (ALLOC_CONSOLE_OPTIONS *allocOptions, ALLOC_CONSOLE_RESULT *result);\n#endif\n\n\nQConsolePrivate::QConsolePrivate (QWinTerminalImpl *parent, const QString& cmd)\n  : q (parent), m_command (cmd), m_auto_scroll (true), m_cursorBlinking (false),\n    m_hasBlinkingCursor (true), m_cursorType (BlockCursor),\n    m_beginSelection (0, 0), m_endSelection (0, 0), m_settingSelection (false),\n    m_process (nullptr), m_inWheelEvent (false)\n{\n  log (nullptr);\n\n  // Possibly detach from any existing console\n  log (\"Detaching from existing console (if any)...\\n\");\n  FreeConsole ();\n  log (\"Closing standard IO...\\n\");\n  closeStandardIO (0, STD_INPUT_HANDLE, \"STDIN\");\n  closeStandardIO (1, STD_OUTPUT_HANDLE, \"STDOUT\");\n  closeStandardIO (2, STD_ERROR_HANDLE, \"STDERR\");\n\n#ifdef HIDDEN_CONSOLE\n  octave::dynamic_library krnl32 (\"kernel32.dll\");\n  AllocConsoleWithOptions_t acwo = nullptr;\n  if (krnl32)\n    acwo = reinterpret_cast<AllocConsoleWithOptions_t>\n             (krnl32.search (\"AllocConsoleWithOptions\"));\n\n  if (acwo)\n    {\n      // Windows 11 24H2 and later provides this function\n      ALLOC_CONSOLE_OPTIONS options { ALLOC_CONSOLE_MODE_NEW_WINDOW, TRUE,\n                                      SW_HIDE };\n      ALLOC_CONSOLE_RESULT res;\n      if (acwo (&options, &res) != S_OK)\n        log (\"Failed to create new invisible console with result %u.\\n\", res);\n    }\n  else\n    {\n      // fallback for older versions of Windows\n\n      // This does not work properly if the Windows Terminal is set as the\n      // default console.\n\n      HWINSTA hOrigSta, hNewSta;\n\n      // Create new (hidden) console\n      hOrigSta = GetProcessWindowStation ();\n      hNewSta = CreateWindowStation (nullptr, 0, GENERIC_ALL, nullptr);\n      log (\"Current Windows station: %p.\\nNew Windows station: %p.\\n\",\n           hOrigSta, hNewSta);\n      if (! SetProcessWindowStation (hNewSta))\n        log (\"Failed to switch to new Windows station.\\n\");\n#endif\n\n      if (! AllocConsole ())\n        log (\"Failed to create new console.\\n\");\n\n#ifdef HIDDEN_CONSOLE\n      if (! SetProcessWindowStation (hOrigSta))\n        log (\"Failed to restore original Windows station.\\n\");\n      if (! CloseWindowStation (hNewSta))\n        log (\"Failed to close new Windows station.\\n\");\n    }\n#endif\n\n  log (\"New (hidden) console created.\\n\");\n\n  setupStandardIO (STD_INPUT_HANDLE,  0, \"STDIN\",  \"CONIN$\");\n  setupStandardIO (STD_OUTPUT_HANDLE, 1, \"STDOUT\", \"CONOUT$\");\n  setupStandardIO (STD_ERROR_HANDLE,  2, \"STDERR\", \"CONOUT$\");\n\n  log (\"Standard input/output/error set up.\\n\");\n\n  *stdin = *(fdopen (0, \"rb\"));\n  *stdout = *(fdopen (1, \"wb\"));\n  *stderr = *(fdopen (2, \"wb\"));\n\n  log (\"POSIX standard streams created.\\n\");\n\n  setvbuf (stdin, nullptr, _IONBF, 0);\n  setvbuf (stdout, nullptr, _IONBF, 0);\n  setvbuf (stderr, nullptr, _IONBF, 0);\n\n  log (\"POSIX standard stream buffers adjusted.\\n\");\n\n  HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE);\n\n  log (\"Console allocated: hStdOut: %p\\n\", hStdOut);\n\n  m_stdOut = hStdOut;\n  m_consoleWindow = GetConsoleWindow ();\n\n  // In case the console window hasn't been created hidden...\n#ifdef HIDDEN_CONSOLE\n  ShowWindow (m_consoleWindow, SW_HIDE);\n#endif\n\n  CONSOLE_SCREEN_BUFFER_INFO sbi;\n\n  GetConsoleScreenBufferInfo (hStdOut, &sbi);\n  m_bufferSize = QSize (sbi.dwSize.X,\n                        qMax (sbi.dwSize.Y, static_cast<SHORT> (500)));\n  m_consoleRect = QRect (sbi.srWindow.Left, sbi.srWindow.Top,\n                         sbi.srWindow.Right - sbi.srWindow.Left + 1,\n                         sbi.srWindow.Bottom - sbi.srWindow.Top + 1);\n  m_cursorPos = QPoint (sbi.dwCursorPosition.X, sbi.dwCursorPosition.Y);\n\n  log (\"Initial console parameters:\\n\");\n  log (\"  buffer size: %d x %d\\n\", m_bufferSize.width (),\n       m_bufferSize.height ());\n  log (\"  window: (%d, %d) -> (%d, %d) [%d x %d]\\n\",\n       m_consoleRect.left (), m_consoleRect.top (),\n       m_consoleRect.right (), m_consoleRect.bottom (),\n       m_consoleRect.width (), m_consoleRect.height ());\n\n  wchar_t titleBuf[260];\n  GetConsoleTitleW (titleBuf, sizeof (titleBuf));\n  q->setWindowTitle (QString::fromWCharArray (titleBuf));\n\n  m_font.setFamily (\"Lucida Console\");\n  m_font.setPointSize (9);\n  m_font.setStyleHint (QFont::TypeWriter);\n\n  m_buffer = nullptr;\n  m_tmpBuffer = nullptr;\n\n  m_consoleView = new QConsoleView (parent);\n  m_horizontalScrollBar = new QScrollBar (Qt::Horizontal, parent);\n  m_verticalScrollBar = new QScrollBar (Qt::Vertical, parent);\n\n  QGridLayout *l = new QGridLayout (parent);\n  l->setContentsMargins (0, 0, 0, 0);\n  l->setSpacing (0);\n  l->addWidget (m_consoleView, 0, 0);\n  l->addWidget (m_horizontalScrollBar, 1, 0);\n  l->addWidget (m_verticalScrollBar, 0, 1);\n\n  if (IsWindows7OrGreater ())\n    {\n      SetConsoleCP (65001);\n      SetConsoleOutputCP (65001);\n    }\n\n  // Choose 0 (0x0) as index into the Windows console color map for the\n  // background and 7 (0x7) as the index for the foreground.  This\n  // selection corresponds to the indices used in the foregroundColor,\n  // setForegroundColor, backgroundColor, and SetBackgroundColor\n  // functions.\n\n  SetConsoleTextAttribute (m_stdOut, 0x07);\n\n  // Defaults.\n  setBackgroundColor (Qt::white);\n  setForegroundColor (Qt::black);\n  setSelectionColor (Qt::lightGray);\n  setCursorColor (false, Qt::darkGray);\n\n  // FIXME -- should we set the palette?\n  QPalette palette (backgroundColor ());\n  m_consoleView->setPalette (palette);\n\n  m_consoleView->setFont (m_font);\n  parent->setFocusPolicy (Qt::StrongFocus);\n  parent->winId ();\n\n  updateHorizontalScrollBar ();\n  updateVerticalScrollBar ();\n\n  m_consoleWatcher = new QTimer (parent);\n  m_consoleWatcher->setInterval (10);\n  m_consoleWatcher->setSingleShot (false);\n\n  m_blinkCursorTimer = new QTimer (parent);\n  QObject::connect (m_blinkCursorTimer, SIGNAL (timeout()),\n                    q, SLOT (blinkCursorEvent ()));\n\n  QObject::connect (m_horizontalScrollBar, SIGNAL (valueChanged (int)),\n                    q, SLOT (horizontalScrollValueChanged (int)));\n\n  QObject::connect (m_verticalScrollBar, SIGNAL (valueChanged (int)),\n                    q, SLOT (verticalScrollValueChanged (int)));\n\n  QObject::connect (m_consoleWatcher, SIGNAL (timeout ()),\n                    q, SLOT (monitorConsole ()));\n\n  m_consoleWatcher->start ();\n\n  if (m_command.isEmpty ())\n    m_consoleThread = 0;\n  else\n    {\n      m_consoleThread = new QConsoleThread (q);\n      QObject::connect (m_consoleThread, SIGNAL (finished ()),\n                        q, SIGNAL (terminated ()));\n      m_consoleThread->start ();\n    }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nQConsolePrivate::~QConsolePrivate ()\n{\n  if (m_consoleThread && m_consoleThread->isRunning () && m_process)\n    {\n      TerminateProcess (m_process, static_cast<UINT> (-1));\n      m_consoleThread->wait ();\n    }\n\n  delete [] m_buffer;\n  delete [] m_tmpBuffer;\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::setupStandardIO (DWORD stdHandleId, int targetFd,\n                                       const char *name, const char *devName)\n{\n  log (\"Opening %s...\\n\", devName);\n\n  int fd = open (devName, _O_RDWR | _O_BINARY);\n\n  if (fd != -1)\n    {\n      if (fd != targetFd)\n        {\n          log (\"Opened %s is not at target file descriptor %d, \"\n               \"duplicating...\\n\", name, targetFd);\n          if (dup2 (fd, targetFd) == -1)\n            log (\"Failed to duplicate file descriptor: errno=%d.\\n\", errno);\n          if (close (fd) == -1)\n            log (\"Failed to close original file descriptor: errno=%d.\\n\",\n                 errno);\n        }\n      else\n        log (\"%s opened and assigned to file descriptor %d.\\n\", devName, fd);\n      if (! SetStdHandle (stdHandleId, (HANDLE) _get_osfhandle (targetFd)))\n        log (\"Failed to re-assign %s: error=%08x.\\n\", name, GetLastError ());\n    }\n  else\n    log (\"Failed to open %s: errno=%d.\\n\", devName, errno);\n}\n\nQPoint QConsolePrivate::posToCell (const QPoint& p)\n{\n  return QPoint (m_consoleRect.left ()\n                 + std::round (static_cast<qreal> (p.x ())\n                               / m_charSize.width ()),\n                 m_consoleRect.top ()\n                 + std::round (static_cast<qreal> (p.y ())\n                               / m_charSize.height ()));\n}\n\nQString QConsolePrivate::getSelection ()\n{\n  QString selection;\n\n  QPoint begin = m_beginSelection;\n  QPoint end = m_endSelection;\n\n  maybeSwapPoints (begin, end);\n\n  if (begin != end)\n    {\n      CHAR_INFO *buf;\n      COORD bufSize, bufCoord;\n      SMALL_RECT bufRect;\n      int nr;\n\n      nr = end.y () - begin.y () + 1;\n      buf =  new CHAR_INFO[m_bufferSize.width () * nr];\n      bufSize.X = m_bufferSize.width ();\n      bufSize.Y = nr;\n      bufCoord.X = 0;\n      bufCoord.Y = 0;\n\n      bufRect.Left = 0;\n      bufRect.Right = m_bufferSize.width ();\n      bufRect.Top = begin.y ();\n      bufRect.Bottom = end.y ();\n\n      if (ReadConsoleOutput (m_stdOut, buf, bufSize, bufCoord, &bufRect))\n        {\n          int start_pos = begin.x ();\n          int end_pos = (nr - 1) * m_bufferSize.width () + end.x ();\n          int lastNonSpace = -1;\n\n          for (int i = start_pos; i <= end_pos; i++)\n            {\n              if (i && (i % m_bufferSize.width ()) == 0)\n                {\n                  if (lastNonSpace >= 0)\n                    selection.truncate (lastNonSpace);\n                  selection.append ('\\n');\n                  lastNonSpace = selection.length ();\n                }\n\n              QChar c (buf[i].Char.UnicodeChar);\n              if (c.isNull ())\n                c = QChar (' ');\n\n              selection.append (c);\n              if (! c.isSpace ())\n                lastNonSpace = selection.length ();\n            }\n\n          if (lastNonSpace >= 0)\n            selection.truncate (lastNonSpace);\n        }\n    }\n\n  return selection;\n}\n\nvoid QConsolePrivate::updateSelection ()\n{\n  QPoint begin = m_beginSelection;\n  QPoint end = m_endSelection;\n\n  maybeSwapPoints (begin, end);\n\n  begin.rx () = 0;\n  end.rx () = m_consoleRect.width ();\n\n  m_consoleView->update ();\n}\n\nvoid QConsolePrivate::clearSelection ()\n{\n  m_beginSelection = m_endSelection = QPoint ();\n\n  m_consoleView->update ();\n}\n\nQColor QConsolePrivate::backgroundColor () const\n{\n  return m_colors[0];\n}\n\nQColor QConsolePrivate::foregroundColor () const\n{\n  return m_colors[7];\n}\n\nQColor QConsolePrivate::selectionColor () const\n{\n  return m_selectionColor;\n}\n\nQColor QConsolePrivate::cursorColor () const\n{\n  return m_cursorColor.isValid () ? m_cursorColor : foregroundColor ();\n}\n\nvoid QConsolePrivate::setBackgroundColor (const QColor& color)\n{\n  m_colors[0] = color;\n\n  QPalette palette (color);\n  palette.setColor(QPalette::Base, color);\n  m_consoleView->setPalette (palette);\n}\n\nvoid QConsolePrivate::setForegroundColor (const QColor& color)\n{\n  m_colors[7] = color;\n}\n\nvoid QConsolePrivate::setSelectionColor (const QColor& color)\n{\n  m_selectionColor = color;\n}\n\nvoid QConsolePrivate::setCursorColor (bool useForegroundColor,\n                                      const QColor& color)\n{\n  m_cursorColor = useForegroundColor ? QColor () : color;\n}\n\nvoid QConsolePrivate::setScrollBufferSize (int value)\n{\n  CONSOLE_SCREEN_BUFFER_INFO sbi;\n  GetConsoleScreenBufferInfo (m_stdOut, &sbi);\n\n  m_bufferSize = QSize (sbi.dwSize.X, static_cast<SHORT> (value));\n\n  updateConsoleSize (true);\n}\n\nvoid QConsolePrivate::drawTextBackground (QPainter& p, int cx1, int cy1,\n                                          int cx2, int cy2, int ch)\n{\n  p.save ();\n\n  QFontMetrics fm = p.fontMetrics ();\n  QString sample ('m');\n  sample = sample.repeated (cx2);\n\n  int ascent = fm.ascent ();\n  int stride = m_consoleRect.width ();\n  int y = ascent + cy1 * ch;\n\n  for (int j = cy1; j <= cy2; j++, y += ch)\n    {\n      int len = 0;\n      bool hasChar = false;\n      int x = fm.horizontalAdvance (sample, cx1);\n      WORD attr = 0;\n      int curr_cx1 = cx1;\n\n      for (int i = cx1; i <= cx2; i++)\n        {\n          CHAR_INFO *ci = &(m_buffer[stride*j+i]);\n\n          if ((ci->Attributes & 0x00ff) != attr)\n            {\n              // Character attributes changed\n              if (len != 0)\n                {\n                  // String buffer not empty -> draw it\n                  if (hasChar || (attr & 0x00f0))\n                    {\n                      if (attr & 0x00f0)\n                        // Try to not paint over parts of the preceeding\n                        // character.\n                        p.fillRect (x, y-ascent,\n                                    fm.horizontalAdvance (sample, len), ch,\n                                    p.brush ());\n                    }\n\n                  curr_cx1 += len;\n                  x = fm.horizontalAdvance (sample, curr_cx1);\n                  len = 0;\n                  hasChar = false;\n                }\n              // Update current brush and store current attributes\n              attr = (ci->Attributes & 0x00ff);\n              p.setBrush (m_colors[(attr >> 4) & 0x000f]);\n            }\n\n          // Append current character to the string buffer\n          len++;\n          if (ci->Char.UnicodeChar != L' ')\n            hasChar = true;\n        }\n\n      if (len != 0 && (hasChar || (attr & 0x00f0)))\n        {\n          // Line end reached, but string buffer not empty -> draw it\n          // No need to update s or x, they will be reset on the next\n          // for-loop iteration\n\n          if (attr & 0x00f0)\n            // Try to not paint over parts of the preceeding character.\n            p.fillRect (x, y-ascent,\n                        fm.horizontalAdvance (sample, len), ch, p.brush ());\n        }\n    }\n\n  p.restore ();\n}\n\nvoid QConsolePrivate::selectAll ()\n{\n  m_beginSelection = QPoint (0, 0);\n  m_endSelection = QPoint (m_bufferSize.width (), m_cursorPos.y ());\n  updateSelection();\n}\n\nvoid QConsolePrivate::selectWord (const QPoint& cellpos)\n{\n  QPoint begin = cellpos;\n  QPoint end = cellpos;\n\n  int stride = m_consoleRect.width ();\n\n  int verticalScrollOffset = m_consoleRect.top ();\n  int horizontalScrollOffset = m_consoleRect.left ();\n\n  // get begin, end in buffer offsets\n  begin.ry () -= verticalScrollOffset;\n  end.ry () -= verticalScrollOffset;\n\n  begin.rx () -= horizontalScrollOffset;\n  end.rx () -= horizontalScrollOffset;\n\n  // check currently clicked on character and determinate if it is whitespace\n  if (QChar (m_buffer[begin.y ()*stride\n                      + begin.x ()].Char.UnicodeChar).isSpace () == false)\n    {\n      // from current char, go back and fwd to find start and end of block\n      while (begin.x () > 0\n             && ! QChar (m_buffer[begin.y ()*stride\n                                  + begin.x () - 1].Char.UnicodeChar).isSpace ())\n        begin.rx () --;\n\n      while (end.x () < m_consoleRect.width ()\n             && ! QChar (m_buffer[end.y ()*stride\n                                  + end.x () + 1].Char.UnicodeChar).isSpace ())\n        end.rx () ++;\n    }\n    else\n    {\n      while (begin.x () > 0\n             && QChar (m_buffer[begin.y ()*stride\n                                + begin.x () - 1].Char.UnicodeChar).isSpace ())\n        begin.rx () --;\n\n      while (end.x () < m_consoleRect.width ()\n             && QChar (m_buffer[end.y ()*stride\n                                + end.x () + 1].Char.UnicodeChar).isSpace ())\n        end.rx () ++;\n    }\n\n  // convert console  offsets to absolute cell positions\n  begin.ry () += verticalScrollOffset;\n  end.ry () += verticalScrollOffset;\n\n  begin.rx () += horizontalScrollOffset;\n  end.rx () += horizontalScrollOffset;\n\n  m_beginSelection = begin;\n  m_endSelection = end;\n\n  updateSelection ();\n}\n\nvoid QConsolePrivate::selectLine (const QPoint& cellpos)\n{\n  m_beginSelection = QPoint (0, cellpos.y ());\n  m_endSelection = QPoint (m_bufferSize.width ()-1, cellpos.y ());\n  updateSelection ();\n}\n\n\nvoid QConsolePrivate::drawSelection (QPainter& p, int cx1, int cy1,\n                                     int cx2, int cy2, int ch)\n{\n  p.save ();\n\n  QPoint begin = m_beginSelection;\n  QPoint end = m_endSelection;\n\n  bool haveSelection = (begin != end);\n\n  if (haveSelection)\n    maybeSwapPoints (begin, end);\n\n  int verticalScrollOffset = m_consoleRect.top ();\n  int horizontalScrollOffset = m_consoleRect.left ();\n\n  begin.ry () -= verticalScrollOffset;\n  end.ry () -= verticalScrollOffset;\n\n  begin.rx () -= horizontalScrollOffset;\n  end.rx () -= horizontalScrollOffset;\n\n  QFontMetrics fm = p.fontMetrics ();\n  QString sample ('m');\n  sample = sample.repeated (cx2);\n\n  int ascent = fm.ascent ();\n  int stride = m_consoleRect.width ();\n\n  int y = ascent + cy1 * ch;\n  for (int j = cy1; j <= cy2; j++, y += ch)\n    {\n      int charsThisLine = 0;\n      int len = 0;\n      bool hasChar = false;\n      WORD attr = 0;\n\n      for (int i = cx1; i <= cx2; i++)\n        {\n          CHAR_INFO* ci = &(m_buffer[stride*j+i]);\n\n          if ((ci->Attributes & 0x00ff) != attr)\n            {\n              // Character attributes changed\n              if (len != 0)\n                {\n                  charsThisLine += len;\n                  len = 0;\n                  hasChar = false;\n                }\n\n              // Store current attributes\n              attr = (ci->Attributes & 0x00ff);\n            }\n\n          // Append current character to the string buffer\n          len++;\n          if (ci->Char.UnicodeChar != L' ')\n            hasChar = true;\n        }\n\n      if (len != 0 && (hasChar || (attr & 0x00f0)))\n        charsThisLine += len;\n\n      if (haveSelection && j >= begin.y () && j <= end.y ())\n        {\n          int selectionBegin = j == begin.y () ? begin.x (): 0;\n\n          int len = ((j == end.y () && end.x () < charsThisLine)\n                     ? end.x () - selectionBegin + 1\n                     : stride - selectionBegin);\n\n          p.fillRect (fm.horizontalAdvance (sample, selectionBegin),\n                      y-ascent, fm.horizontalAdvance (sample, len),\n                      ch, selectionColor ());\n        }\n    }\n\n  p.restore ();\n}\n\nvoid QConsolePrivate::drawCursor (QPainter& p)\n{\n  if (! m_cursorBlinking)\n    {\n      p.save ();\n\n      QRect rect = cursorRect ();\n      QColor color = cursorColor ();\n\n      p.setPen (color);\n\n      if (m_cursorType == QConsolePrivate::BlockCursor)\n        {\n          if (q->hasFocus ())\n            p.fillRect (rect, color);\n          else\n            {\n              // draw the cursor outline, adjusting the area so that\n              // it is draw entirely inside 'rect'\n\n              int penWidth = qMax (1, p.pen ().width ());\n\n              p.drawRect (rect.adjusted (penWidth/2, penWidth/2,\n                                         - penWidth/2 - penWidth%2,\n                                         - penWidth/2 - penWidth%2));\n            }\n        }\n      else if (m_cursorType == QConsolePrivate::UnderlineCursor)\n        {\n          p.drawLine (rect.left (), rect.bottom (),\n                      rect.right (), rect.bottom ());\n        }\n      else if (m_cursorType == QConsolePrivate::IBeamCursor)\n        {\n          p.drawLine (rect.left (), rect.top (),\n                      rect.left (), rect.bottom ());\n        }\n\n      p.restore ();\n    }\n}\n\nvoid QConsolePrivate::drawText (QPainter& p, int cx1, int cy1,\n                                int cx2, int cy2, int ch)\n{\n  p.save ();\n\n  p.setFont (m_font);\n  p.setPen (foregroundColor ());\n\n  QString s;\n  s.reserve (cx2 - cx1 + 1);\n\n  QFontMetrics fm = p.fontMetrics ();\n  QString sample ('m');\n  sample = sample.repeated (cx2);\n\n  int ascent = fm.ascent ();\n  int stride = m_consoleRect.width ();\n\n  int y = ascent + cy1 * ch;\n  for (int j = cy1; j <= cy2; j++, y += ch)\n    {\n      // Reset string buffer and starting X coordinate\n      s.clear ();\n      bool hasChar = false;\n      int x = fm.horizontalAdvance (sample, cx1);\n      WORD attr = 0;\n      int curr_cx1 = cx1;\n\n      for (int i = cx1; i <= cx2; i++)\n        {\n          CHAR_INFO* ci = &(m_buffer[stride*j+i]);\n\n          if ((ci->Attributes & 0x00ff) != attr)\n            {\n              // Character attributes changed\n              if (! s.isEmpty ())\n                {\n                  // String buffer not empty -> draw it\n                  if (hasChar || (attr & 0x00f0))\n                    p.drawText (x, y, s);\n\n                  curr_cx1 += s.length ();\n                  x = fm.horizontalAdvance (sample, curr_cx1);\n                  s.clear ();\n                  hasChar = false;\n                }\n              // Update current pen and store current attributes\n              attr = (ci->Attributes & 0x00ff);\n              p.setPen (m_colors[attr & 0x000f]);\n            }\n\n          // Append current character to the string buffer\n          s.append (ci->Char.UnicodeChar);\n          if (ci->Char.UnicodeChar != L' ')\n            hasChar = true;\n        }\n\n      if (! s.isEmpty () && (hasChar || (attr & 0x00f0)))\n        {\n          // Line end reached, but string buffer not empty -> draw it\n          // No need to update s or x, they will be reset on the next\n          // for-loop iteration\n\n          p.drawText (x, y, s);\n        }\n    }\n\n  p.restore ();\n}\n\n/////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::closeStandardIO (int fd, DWORD stdHandleId,\n                                       const char *name)\n{\n  if (close (fd) == -1)\n    log (\"Failed to close file descriptor %d: errno=%d.\\n\", fd, errno);\n  if (! CloseHandle (GetStdHandle (stdHandleId)))\n    log (\"Failed to close Win32 %s: error=%08x.\\n\", name, GetLastError ());\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::log (const char *fmt, ...)\n{\n#ifdef DEBUG_QCONSOLE\n  if (fmt)\n    {\n      va_list l;\n      FILE *flog = fopen (LOGFILENAME, \"ab\");\n\n      va_start (l, fmt);\n      vfprintf (flog, fmt, l);\n      va_end (l);\n      fclose (flog);\n    }\n  else\n    {\n      // Special case to re-initialize the log file\n      FILE *flog = fopen (LOGFILENAME, \"w\");\n      fclose (flog);\n    }\n#else\n  Q_UNUSED (fmt);\n#endif\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::updateConsoleSize (bool sync, bool allow_smaller_width)\n{\n  QFontMetrics fm = m_consoleView->fontMetrics ();\n  QSize winSize = m_consoleView->size ();\n\n  // QFontMetrics::averageCharWidth returns the average character width of the\n  // used font rounded(?) to the nearest integer.  However, the actual\n  // character width might be fractional on screens with non-scalar DPI\n  // scaling.  Take a large sample and divide by the number of characters in\n  // the sample to get a more accurate (fractional) average character width of\n  // the used font.\n  QString sample ('m');\n  sample = sample.repeated (160);  // Is 160 a large enough sample?\n  m_charSize.rwidth ()\n    = static_cast<qreal> (fm.horizontalAdvance (sample)) / 160.;\n  m_charSize.rheight () = fm.lineSpacing ();\n\n  m_consoleRect.setWidth (std::floor (static_cast<qreal> (winSize.width ())\n                                      / m_charSize.width ()));\n  m_consoleRect.setHeight (std::floor (static_cast<qreal> (winSize.height ())\n                                       / m_charSize.height ()));\n\n  // Don't shrink the size of the buffer.  That way wide lines won't be\n  // truncated and will reappear if the window is enlarged again later.\n\n  if (allow_smaller_width || m_consoleRect.width () > m_bufferSize.width ())\n    m_bufferSize.rwidth () = m_consoleRect.width ();\n\n  if (qMax (m_bufferSize.height (), m_consoleRect.height ())\n      > m_bufferSize.height ())\n    m_bufferSize.rheight () = qMax (m_bufferSize.height (),\n                                    m_consoleRect.height ());\n\n  // Store the terminal size in the environment.  When Octave is\n  // initialized, we ask the command editor (usually readline) to prefer\n  // using these values rather than querying the terminal so that the\n  // buffer size can be larger than the size of the window that the\n  // command editor will actually use.\n\n  qputenv (\"LINES\", QByteArray::number (m_consoleRect.height ()));\n  qputenv (\"COLUMNS\", QByteArray::number (m_consoleRect.width ()));\n\n  // Force the command line editor (usually readline) to notice the\n  // change in screen size as soon as possible.\n\n  q->setSize (m_consoleRect.height (), m_consoleRect.width ());\n\n  m_consoleRect.moveLeft (0);\n  if (m_consoleRect.bottom () >= m_bufferSize.height ())\n    m_consoleRect.moveTop (m_bufferSize.height () - m_consoleRect.height ());\n\n  log (\"Console resized:\\n\");\n  log (\"  widget size: %d x %d\\n\", winSize.width (), winSize.height ());\n  log (\"  buffer size: %d x %d\\n\", m_bufferSize.width (),\n       m_bufferSize.height ());\n  log (\"  window: (%d, %d) -> (%d, %d) [%d x %d]\\n\",\n       m_consoleRect.left (), m_consoleRect.top (),\n       m_consoleRect.right (), m_consoleRect.bottom (),\n       m_consoleRect.width (), m_consoleRect.height ());\n\n  if (sync)\n    syncConsoleParameters ();\n\n  updateHorizontalScrollBar ();\n  updateVerticalScrollBar ();\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::syncConsoleParameters ()\n{\n  CONSOLE_SCREEN_BUFFER_INFO sbi;\n  HANDLE hStdOut = m_stdOut;\n\n  GetConsoleScreenBufferInfo (hStdOut, &sbi);\n\n  COORD bs;\n  SMALL_RECT sr;\n\n  bs.X = m_bufferSize.width ();\n  bs.Y = m_bufferSize.height ();\n  sr.Left = m_consoleRect.left ();\n  sr.Right = m_consoleRect.right ();\n  sr.Top = m_consoleRect.top ();\n  sr.Bottom = m_consoleRect.bottom ();\n\n  if (bs.X * bs.Y > sbi.dwSize.X * sbi.dwSize.Y)\n    {\n      SetConsoleScreenBufferSize (hStdOut, bs);\n      SetConsoleWindowInfo (hStdOut, TRUE, &sr);\n    }\n  else\n    {\n      SetConsoleWindowInfo (hStdOut, TRUE, &sr);\n      SetConsoleScreenBufferSize (hStdOut, bs);\n    }\n\n  log (\"Sync'ing console parameters:\\n\");\n  log (\"  buffer size: %d x %d\\n\", bs.X, bs.Y);\n  log (\"  window: (%d, %d) -> (%d, %d)\\n\",\n       sr.Left, sr.Top, sr.Right, sr.Bottom);\n\n  delete [] m_buffer;\n  delete [] m_tmpBuffer;\n\n  std::size_t bufSize = static_cast<std::size_t> (m_consoleRect.width ())\n                        * static_cast<std::size_t> (m_consoleRect.height ());\n\n  m_buffer = new CHAR_INFO[bufSize];\n  m_tmpBuffer = new CHAR_INFO[bufSize];\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::grabConsoleBuffer (CHAR_INFO* buf)\n{\n  COORD bs, bc;\n  SMALL_RECT r;\n\n  bs.X = m_consoleRect.width ();\n  bs.Y = m_consoleRect.height ();\n  bc.X = 0;\n  bc.Y = 0;\n\n  r.Left   = m_consoleRect.left ();\n  r.Top    = m_consoleRect.top ();\n  r.Right  = m_consoleRect.right ();\n  r.Bottom = m_consoleRect.bottom ();\n\n  log (\"ReadConsoleOutput (%d,%d) -> (%d,%d)\\n\", r.Left, r.Top, r.Right, r.Bottom);\n  if (! ReadConsoleOutput (m_stdOut, (buf ? buf : m_buffer), bs, bc, &r))\n    qCritical (\"cannot read console output\");\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::updateHorizontalScrollBar ()\n{\n  m_horizontalScrollBar->setMinimum (0);\n  if (m_bufferSize.width () > m_consoleRect.width ())\n    m_horizontalScrollBar->setMaximum (m_bufferSize.width () - m_consoleRect.width ());\n  else\n    m_horizontalScrollBar->setMaximum (0);\n  m_horizontalScrollBar->setSingleStep (1);\n  m_horizontalScrollBar->setPageStep (m_consoleRect.width ());\n  m_horizontalScrollBar->setValue (m_consoleRect.left ());\n\n  log (\"Horizontal scrollbar parameters updated: %d/%d/%d/%d\\n\",\n       m_horizontalScrollBar->minimum (),\n       m_horizontalScrollBar->maximum (),\n       m_horizontalScrollBar->singleStep (),\n       m_horizontalScrollBar->pageStep ());\n}\n\nvoid QConsolePrivate::updateVerticalScrollBar ()\n{\n  m_verticalScrollBar->setMinimum (0);\n  if (m_bufferSize.height () > m_consoleRect.height ())\n    m_verticalScrollBar->setMaximum (m_bufferSize.height () - m_consoleRect.height ());\n  else\n    m_verticalScrollBar->setMaximum (0);\n  m_verticalScrollBar->setSingleStep (1);\n  m_verticalScrollBar->setPageStep (m_consoleRect.height ());\n  m_verticalScrollBar->setValue (m_consoleRect.top ());\n\n  log (\"Vertical scrollbar parameters updated: %d/%d/%d/%d\\n\",\n       m_verticalScrollBar->minimum (), m_verticalScrollBar->maximum (),\n       m_verticalScrollBar->singleStep (), m_verticalScrollBar->pageStep ());\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::setHorizontalScrollValue (int value)\n{\n  if (value == m_consoleRect.left ())\n    return;\n\n  SMALL_RECT r;\n  HANDLE hStdOut = m_stdOut;\n\n  if (value + m_consoleRect.width () > m_bufferSize.width ())\n    value = m_bufferSize.width () - m_consoleRect.width ();\n\n  r.Left = value;\n  r.Top = m_consoleRect.top ();\n  r.Right = value + m_consoleRect.width () - 1;\n  r.Bottom = m_consoleRect.bottom ();\n\n  log (\"Scrolling window horizontally: (%d, %d) -> (%d, %d) [%d x %d]\\n\",\n       r.Left, r.Top, r.Right, r.Bottom,\n       r.Right - r.Left + 1, r.Bottom - r.Top + 1);\n\n  if (SetConsoleWindowInfo (hStdOut, TRUE, &r))\n    {\n      m_consoleRect.moveLeft (value);\n      updateConsoleView ();\n    }\n}\n\nvoid QConsolePrivate::setVerticalScrollValue (int value)\n{\n  if (value == m_consoleRect.top ())\n    return;\n\n  SMALL_RECT r;\n  HANDLE hStdOut = m_stdOut;\n\n  if (value + m_consoleRect.height () > m_bufferSize.height ())\n    value = m_bufferSize.height () - m_consoleRect.height ();\n\n  r.Left = m_consoleRect.left ();\n  r.Top = value;\n  r.Right = m_consoleRect.right ();\n  r.Bottom = value + m_consoleRect.height () - 1;\n\n  log (\"Scrolling window vertically: (%d, %d) -> (%d, %d) [%d x %d]\\n\",\n       r.Left, r.Top, r.Right, r.Bottom,\n       r.Right - r.Left + 1, r.Bottom - r.Top + 1);\n\n  if (SetConsoleWindowInfo (hStdOut, TRUE, &r))\n    {\n      m_consoleRect.moveTop (value);\n\n      CONSOLE_SCREEN_BUFFER_INFO sbi;\n      if (GetConsoleScreenBufferInfo (hStdOut, &sbi))\n        {\n          if (sbi.dwCursorPosition.Y > m_consoleRect.bottom ())\n            m_auto_scroll = false;\n          else\n            m_auto_scroll = true;\n        }\n\n      updateConsoleView ();\n    }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::updateConsoleView (bool grab)\n{\n  if (grab)\n    grabConsoleBuffer ();\n  m_consoleView->update ();\n  m_consoleWatcher->start ();\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::monitorConsole ()\n{\n  CONSOLE_SCREEN_BUFFER_INFO sbi;\n  HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE);\n\n  static wchar_t titleBuf[260];\n\n  GetConsoleTitleW (titleBuf, sizeof (titleBuf));\n  QString title = QString::fromWCharArray (titleBuf);\n\n  if (title != m_title)\n    {\n      q->setWindowTitle (title);\n      Q_EMIT q->titleChanged (title);\n    }\n\n  if (GetConsoleScreenBufferInfo (hStdOut, &sbi))\n    {\n      bool need_console_sync = false;\n\n      if (m_bufferSize.width () != sbi.dwSize.X\n          || m_bufferSize.height () != sbi.dwSize.Y)\n        {\n          // Buffer size changed\n          m_bufferSize.rwidth () = sbi.dwSize.X;\n          m_bufferSize.rheight () = sbi.dwSize.Y;\n          updateHorizontalScrollBar ();\n          updateVerticalScrollBar ();\n          need_console_sync = true;\n        }\n\n      if (m_cursorPos.x () != sbi.dwCursorPosition.X\n          || m_cursorPos.y () != sbi.dwCursorPosition.Y)\n        {\n          // Cursor position changed\n          QFontMetrics fm = m_consoleView->fontMetrics ();\n          QString sample ('m');\n          sample = sample.repeated (m_bufferSize.width ());\n          // \"over-size\" update rectangle for fractional character widths\n          m_consoleView->update\n            (fm.horizontalAdvance (sample,\n                                   m_cursorPos.x () - sbi.srWindow.Left) - 1,\n             (m_cursorPos.y () - sbi.srWindow.Top) * m_charSize.height (),\n             m_charSize.width () + 2, m_charSize.height ());\n          m_cursorPos.rx () = sbi.dwCursorPosition.X;\n          m_cursorPos.ry () = sbi.dwCursorPosition.Y;\n          m_consoleView->update\n            (fm.horizontalAdvance (sample,\n                                   m_cursorPos.x () - sbi.srWindow.Left) - 1,\n             (m_cursorPos.y () - sbi.srWindow.Top) * m_charSize.height (),\n             m_charSize.width () + 2, m_charSize.height ());\n        }\n\n      if (m_consoleRect.left () != sbi.srWindow.Left\n          || m_consoleRect.right () != sbi.srWindow.Right\n          || (m_auto_scroll &&\n              (m_consoleRect.top () != sbi.srWindow.Top\n               || m_consoleRect.bottom () != sbi.srWindow.Bottom)))\n        {\n          // Console window changed\n          log (\"--> Console window changed\\n\");\n          m_consoleRect = QRect (sbi.srWindow.Left, sbi.srWindow.Top,\n                                 sbi.srWindow.Right - sbi.srWindow.Left + 1,\n                                 sbi.srWindow.Bottom - sbi.srWindow.Top + 1);\n          updateHorizontalScrollBar ();\n          updateVerticalScrollBar ();\n          syncConsoleParameters ();\n          updateConsoleView ();\n          return;\n        }\n\n      if (need_console_sync)\n      {\n        syncConsoleParameters ();\n        updateConsoleView ();\n        return;\n      }\n\n      if (m_tmpBuffer && m_buffer)\n        {\n          grabConsoleBuffer (m_tmpBuffer);\n          if (memcmp (m_tmpBuffer, m_buffer,\n                      sizeof (CHAR_INFO) * m_consoleRect.width ()\n                      * m_consoleRect.height ()))\n            {\n              // FIXME: compute the area to update based on the\n              // difference between the 2 buffers.\n              std::swap (m_buffer, m_tmpBuffer);\n              updateConsoleView (false);\n            }\n        }\n    }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::startCommand ()\n{\n  QString cmd = m_command;\n\n  if (cmd.isEmpty ())\n    cmd = qgetenv (\"COMSPEC\").constData ();\n\n  if (! cmd.isEmpty ())\n    {\n      STARTUPINFOW si;\n      PROCESS_INFORMATION pi;\n\n      ZeroMemory (&si, sizeof (si));\n      si.cb = sizeof (si);\n      ZeroMemory (&pi, sizeof (pi));\n\n      LPCWSTR wcmd = reinterpret_cast<LPCWSTR> (cmd.utf16 ());\n      if (CreateProcessW (nullptr,\n                          const_cast<LPWSTR> (wcmd),\n                          nullptr,\n                          nullptr,\n                          TRUE,\n                          0,\n                          nullptr,\n                          nullptr,\n                          &si,\n                          &pi))\n        {\n          CloseHandle (pi.hThread);\n          m_process = pi.hProcess;\n          WaitForSingleObject (m_process, INFINITE);\n          CloseHandle (m_process);\n          m_process = nullptr;\n        }\n    }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QConsolePrivate::sendConsoleText (const QString& s)\n{\n  // Send the string in chunks of 512 characters. Each character is\n  // translated into an equivalent keypress event.\n\n#define TEXT_CHUNK_SIZE 512\n\n  // clear any selection on inserting text\n  clearSelection();\n  // enable auto-scrolling\n  m_auto_scroll = true;\n\n  int len = s.length ();\n  INPUT_RECORD events[TEXT_CHUNK_SIZE];\n  DWORD nEvents = 0, written;\n  HANDLE hStdIn = GetStdHandle (STD_INPUT_HANDLE);\n\n  ZeroMemory (events, sizeof (events));\n\n  for (int i = 0; i < len; i++)\n    {\n      QChar c = s.at (i);\n\n      if (c == L'\\r' || c == L'\\n')\n        {\n          if (c == L'\\r' && i < (len - 1) && s.at (i+1) == L'\\n')\n            i++;\n\n          // add new line\n          events[nEvents].EventType                        = KEY_EVENT;\n          events[nEvents].Event.KeyEvent.bKeyDown          = TRUE;\n          events[nEvents].Event.KeyEvent.wRepeatCount      = 1;\n          events[nEvents].Event.KeyEvent.wVirtualKeyCode   =\n            VK_RETURN;\n          events[nEvents].Event.KeyEvent.wVirtualScanCode  = 0;\n          events[nEvents].Event.KeyEvent.uChar.UnicodeChar = c.unicode ();\n          events[nEvents].Event.KeyEvent.dwControlKeyState = 0;\n          nEvents++;\n\n          WriteConsoleInput (hStdIn, events, nEvents, &written);\n          nEvents = 0;\n          ZeroMemory (events, sizeof (events));\n\n        }\n      else\n        {\n          events[nEvents].EventType                        = KEY_EVENT;\n          events[nEvents].Event.KeyEvent.bKeyDown          = TRUE;\n          events[nEvents].Event.KeyEvent.wRepeatCount      = 1;\n          events[nEvents].Event.KeyEvent.wVirtualKeyCode   =\n            LOBYTE (VkKeyScan (c.unicode ()));\n          events[nEvents].Event.KeyEvent.wVirtualScanCode  = 0;\n          events[nEvents].Event.KeyEvent.uChar.UnicodeChar = c.unicode ();\n          events[nEvents].Event.KeyEvent.dwControlKeyState = 0;\n          nEvents++;\n        }\n\n      if (nEvents == TEXT_CHUNK_SIZE\n          || (nEvents > 0 && i == (len - 1)))\n        {\n          WriteConsoleInput (hStdIn, events, nEvents, &written);\n          nEvents = 0;\n          ZeroMemory (events, sizeof (events));\n        }\n    }\n}\n\nQRect\nQConsolePrivate::cursorRect ()\n{\n  // The actual character width might be fractional (with non-integer scaling -\n  // high DPI).  But m_charSize.width () is integer.\n  // Assume a fixed-width font and calculate cursor position by measuring the\n  // width of characters starting from the first column.\n\n  QFontMetrics fm = m_consoleView->fontMetrics ();\n  QString sample ('m');\n  sample = sample.repeated (m_cursorPos.x () - m_consoleRect.x ());\n\n  // Integer precision is good enough for the line height and for the\n  // dimensions of the marker.\n  qreal cw = m_charSize.width ();\n  qreal ch = m_charSize.height ();\n\n  // Make sure the cursor starts *right* of the previous character.\n  return QRect (fm.horizontalAdvance (sample),\n                (m_cursorPos.y () - m_consoleRect.y ()) * ch,\n                std::round (cw), ch);\n}\n\nQRect\nQConsolePrivate::boundingRect ()\n{\n  // This is slightly larger than cursorRect to make sure the entirety of a\n  // character is redrawn.\n\n  QFontMetrics fm = m_consoleView->fontMetrics ();\n  QString sample ('m');\n  sample = sample.repeated (m_cursorPos.x () - m_consoleRect.x ());\n\n  // Integer precision is good enough for the line height and for the\n  // dimensions of the marker.\n  qreal cw = m_charSize.width ();\n  qreal ch = m_charSize.height ();\n\n  return QRect (fm.horizontalAdvance (sample)-1,\n                (m_cursorPos.y () - m_consoleRect.y ()) * ch,\n                std::round (cw+2), ch);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nQWinTerminalImpl::QWinTerminalImpl (QWidget *parent)\n    : QTerminal (parent), d (new QConsolePrivate (this)),\n      allowTripleClick (false)\n{\n    installEventFilter (this);\n\n    setAcceptDrops (true);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nQWinTerminalImpl::~QWinTerminalImpl ()\n{\n  delete d;\n}\n\nvoid QWinTerminalImpl::mouseMoveEvent (QMouseEvent *event)\n{\n  if (d->m_settingSelection)\n    {\n      d->m_endSelection = d->posToCell (event->pos ());\n\n      updateSelection ();\n    }\n}\n\nvoid QWinTerminalImpl::mousePressEvent (QMouseEvent *event)\n{\n  if (allowTripleClick)\n    {\n      mouseTripleClickEvent (event);\n    }\n  else if (event->button () == Qt::LeftButton)\n    {\n      d->m_settingSelection = true;\n\n      d->m_beginSelection = d->posToCell (event->pos ());\n    }\n}\n\nvoid QWinTerminalImpl::mouseReleaseEvent (QMouseEvent *event)\n{\n  if (event->button () == Qt::LeftButton && d->m_settingSelection)\n    {\n      d->m_endSelection = d->posToCell (event->pos ());\n\n      updateSelection ();\n\n      d->m_settingSelection = false;\n    }\n}\n\nvoid QWinTerminalImpl::mouseDoubleClickEvent (QMouseEvent *event)\n{\n  if (event->button () == Qt::LeftButton)\n    {\n      // doubleclick - select word\n      d->m_settingSelection = false;\n\n      d->selectWord (d->posToCell (event->pos ()));\n\n      allowTripleClick = true;\n\n      QTimer::singleShot (QApplication::doubleClickInterval (), this,\n                          SLOT (tripleClickTimeout ()));\n\n    }\n}\n\nvoid QWinTerminalImpl::mouseTripleClickEvent (QMouseEvent *event)\n{\n  if (event->button () == Qt::LeftButton)\n    {\n      d->selectLine (d->posToCell (event->pos ()));\n    }\n}\n\nvoid QWinTerminalImpl::tripleClickTimeout ()\n{\n  allowTripleClick = false;\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::viewResizeEvent (QConsoleView *, QResizeEvent *)\n{\n  d->updateConsoleSize (true);\n  d->grabConsoleBuffer ();\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::viewPaintEvent (QConsoleView *w, QPaintEvent *event)\n{\n  QPainter p (w);\n\n  qreal cw = d->m_charSize.width ();\n  qreal ch = d->m_charSize.height ();\n\n  QRect updateRect = event->rect ();\n  p.fillRect (updateRect, QBrush (d->backgroundColor ()));\n\n  int cx1 = std::round (static_cast<qreal> (updateRect.left ()) / cw);\n  int cy1 = updateRect.top () / ch;\n  int cx2 = std::round (static_cast<qreal> (updateRect.right ()) / cw);\n  cx2 = qMin (d->m_consoleRect.width () - 1, cx2);\n  int cy2 = std::round (static_cast<qreal> (updateRect.bottom ()) / ch);\n  cy2 = qMin (d->m_consoleRect.height () - 1, cy2);\n\n  if (cx1 > d->m_consoleRect.width () - 1\n      || cy1 > d->m_consoleRect.height () - 1)\n    return;\n\n  d->drawTextBackground (p, cx1, cy1, cx2, cy2, ch);\n  d->drawSelection (p, cx1, cy1, cx2, cy2, ch);\n  d->drawCursor (p);\n  d->drawText (p, cx1, cy1, cx2, cy2, ch);\n}\n\nvoid QWinTerminalImpl::blinkCursorEvent ()\n{\n  if (d->m_hasBlinkingCursor)\n    d->m_cursorBlinking = ! d->m_cursorBlinking;\n  else\n    d->m_cursorBlinking = false;\n\n  d->m_consoleView->update (d->boundingRect ());\n}\n\nvoid QWinTerminalImpl::setBlinkingCursor (bool blink)\n{\n  d->m_hasBlinkingCursor = blink;\n\n  setBlinkingCursorState (blink);\n}\n\nvoid QWinTerminalImpl::setBlinkingCursorState (bool blink)\n{\n  if (blink && ! d->m_blinkCursorTimer->isActive ())\n    d->m_blinkCursorTimer->start (d->BLINK_DELAY);\n\n  if (! blink && d->m_blinkCursorTimer->isActive ())\n    {\n      d->m_blinkCursorTimer->stop ();\n\n      if (d->m_cursorBlinking)\n        blinkCursorEvent ();\n    }\n}\n\n// Reset width of console buffer and terminal window to be the same.\n\nvoid QWinTerminalImpl::init_terminal_size ()\n{\n  d->updateConsoleSize (true, true);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::wheelEvent (QWheelEvent *event)\n{\n  if (! d->m_inWheelEvent)\n    {\n      // Forward to the scrollbar (avoid recursion)\n      d->m_inWheelEvent = true;\n      QApplication::sendEvent (d->m_verticalScrollBar, event);\n      d->m_inWheelEvent = false;\n    }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::horizontalScrollValueChanged (int value)\n{\n  d->setHorizontalScrollValue (value);\n}\n\nvoid QWinTerminalImpl::verticalScrollValueChanged (int value)\n{\n  d->setVerticalScrollValue (value);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::monitorConsole ()\n{\n  d->monitorConsole ();\n}\n\nvoid QWinTerminalImpl::updateSelection ()\n{\n  d->updateSelection ();\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::focusInEvent (QFocusEvent *event)\n{\n  setBlinkingCursorState (true);\n\n  QWidget::focusInEvent (event);\n}\n\nvoid QWinTerminalImpl::focusOutEvent (QFocusEvent *event)\n{\n  // Force the cursor to be redrawn.\n  d->m_cursorBlinking = true;\n\n  setBlinkingCursorState (false);\n\n  QWidget::focusOutEvent (event);\n}\n\nbool QWinTerminalImpl::eventFilter (QObject *obj, QEvent *event)\n{\n  // if a keypress, filter out tab keys so that the next/prev tabbing is\n  // disabled - but we still need to pass along to the console .\n  if (event->type () == QEvent::KeyPress)\n  {\n    QKeyEvent *k = static_cast<QKeyEvent *> (event);\n    if (k->key () == Qt::Key_Tab)\n    {\n      sendText (\"\\t\");\n      return true;\n    }\n  }\n  return false;\n}\n\nvoid QWinTerminalImpl::keyPressEvent (QKeyEvent *event)\n{\n  QString s = translateKey (event);\n  if (!s.isEmpty ())\n    sendText (s);\n\n  if (d->m_hasBlinkingCursor)\n    {\n      d->m_blinkCursorTimer->start (d->BLINK_DELAY);\n\n      if (d->m_cursorBlinking)\n        blinkCursorEvent ();\n    }\n\n  QWidget::keyPressEvent (event);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::start ()\n{\n  d->startCommand ();\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::sendText (const QString& s)\n{\n  d->sendConsoleText (s);\n}\n\nvoid QWinTerminalImpl::setCursorType (CursorType type, bool blinking)\n{\n  switch (type)\n    {\n    case UnderlineCursor:\n      d->m_cursorType = QConsolePrivate::UnderlineCursor;\n      break;\n\n    case BlockCursor:\n      d->m_cursorType = QConsolePrivate::BlockCursor;\n      break;\n\n    case IBeamCursor:\n      d->m_cursorType = QConsolePrivate::IBeamCursor;\n      break;\n    }\n\n  setBlinkingCursor (blinking);\n}\n\nvoid QWinTerminalImpl::setBackgroundColor (const QColor& color)\n{\n  d->setBackgroundColor (color);\n}\n\nvoid QWinTerminalImpl::setForegroundColor (const QColor& color)\n{\n  d->setForegroundColor (color);\n}\n\nvoid QWinTerminalImpl::setSelectionColor (const QColor& color)\n{\n  d->setSelectionColor (color);\n}\n\nvoid QWinTerminalImpl::setCursorColor (bool useForegroundColor,\n                                       const QColor& color)\n{\n  d->setCursorColor (useForegroundColor, color);\n}\n\nvoid QWinTerminalImpl::setScrollBufferSize (int value)\n{\n  d->setScrollBufferSize (value);\n}\n\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::setTerminalFont (const QFont& f)\n{\n  d->m_font = f;\n  d->m_consoleView->setFont (f);\n  d->updateConsoleSize (true);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::setSize (int columns, int lines)\n{\n  d->log (\"Q_EMIT set_screen_size_signal (%d, %d)\\n\", columns, lines);\n\n  Q_EMIT set_screen_size_signal (columns, lines);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::copyClipboard ()\n{\n  if(!hasFocus()) return;\n\n  QClipboard *clipboard = QApplication::clipboard ();\n\n  QString selection = d->getSelection ();\n\n  if (selection.isEmpty ())\n    {\n      if (! _extra_interrupt)\n        terminal_interrupt ();\n    }\n  else\n    {\n      clipboard->setText (selection);\n      Q_EMIT report_status_message (tr (\"copied selection to clipboard\"));\n    }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::pasteClipboard ()\n{\n  if(!hasFocus()) return;\n\n  QString text = QApplication::clipboard()->text (QClipboard::Clipboard);\n\n  if (! text.isEmpty ())\n    {\n      if (text.contains (\"\\t\"))\n        {\n          qWarning (\"Tabs replaced with spaces in pasted text before processing\");\n          text.replace (\"\\t\", \"    \");\n        }\n\n    sendText (text);\n    }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::selectAll ()\n{\n  if(!hasFocus()) return;\n\n  d->selectAll();\n}\n\n\n\n//////////////////////////////////////////////////////////////////////////////\n\nQString QWinTerminalImpl::selectedText ()\n{\n  QString selection = d->getSelection ();\n  return selection;\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::dragEnterEvent (QDragEnterEvent *event)\n{\n   if (event->mimeData ()->hasUrls ())\n     {\n       event->acceptProposedAction();\n     }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::dropEvent (QDropEvent *event)\n{\n  QString dropText;\n\n  if (event->mimeData ()->hasUrls ())\n    {\n      for (QUrl url : event->mimeData ()->urls ())\n        {\n          if(dropText.length () > 0)\n            dropText += '\\n';\n          dropText  += url.toLocalFile ();\n        }\n      sendText (dropText);\n    }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nvoid QWinTerminalImpl::has_extra_interrupt (bool extra)\n{\n  _extra_interrupt = extra;\n}\n"
  },
  {
    "path": "libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h",
    "content": "/*\n\nCopyright (C) 2011-2026 The Octave Project Developers\n\nThis file is part of QConsole.\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not,\nsee <https://www.gnu.org/licenses/>.\n\n*/\n\n#ifndef __QConsole_h__\n#define __QConsole_h__ 1\n\n#include <QWidget>\n#include \"QTerminal.h\"\nclass QFocusEvent;\nclass QKeyEvent;\nclass QPainter;\nclass QPaintEvent;\nclass QResizeEvent;\nclass QWheelEvent;\nclass QPoint;\nclass QDragEnterEvent;\nclass QDropEvent;\n\nclass QConsolePrivate;\nclass QConsoleThread;\nclass QConsoleView;\n\n//////////////////////////////////////////////////////////////////////////////\n\nclass QWinTerminalImpl : public QTerminal\n{\n  Q_OBJECT\n  friend class QConsolePrivate;\n  friend class QConsoleThread;\n  friend class QConsoleView;\n\npublic:\n  QWinTerminalImpl (QWidget *parent);\n  ~QWinTerminalImpl ();\n\n  void setTerminalFont (const QFont& font);\n  void setSize (int columns, int lines);\n  void sendText (const QString& s);\n  void setCursorType (CursorType type, bool blinking);\n\n  void setBackgroundColor (const QColor& color);\n  void setForegroundColor (const QColor& color);\n  void setSelectionColor (const QColor& color);\n  void setCursorColor (bool useForegoundColor, const QColor& color);\n  void setScrollBufferSize (int value);\n\n  QString selectedText ();\n\n  void has_extra_interrupt (bool);\n\npublic Q_SLOTS:\n  void copyClipboard ();\n  void pasteClipboard ();\n  void selectAll ();\n  void blinkCursorEvent ();\n  void init_terminal_size ();\n\nQ_SIGNALS:\n  void terminated ();\n  void titleChanged (const QString&);\n\nprotected:\n  void viewPaintEvent (QConsoleView *, QPaintEvent *);\n  void setBlinkingCursor (bool blink);\n  void setBlinkingCursorState (bool blink);\n  void viewResizeEvent (QConsoleView *, QResizeEvent *);\n  void wheelEvent (QWheelEvent *);\n  void focusInEvent (QFocusEvent *);\n  void focusOutEvent (QFocusEvent *);\n  void keyPressEvent (QKeyEvent *);\n  virtual void start ();\n  void mouseMoveEvent (QMouseEvent *event);\n  void mousePressEvent (QMouseEvent *event);\n  void mouseReleaseEvent (QMouseEvent *event);\n  void mouseDoubleClickEvent (QMouseEvent *event);\n  void mouseTripleClickEvent (QMouseEvent *event);\n\n  bool eventFilter (QObject *obj, QEvent *ev);\n\n  void dragEnterEvent (QDragEnterEvent *event);\n  void dropEvent (QDropEvent *event);\n\nprivate Q_SLOTS:\n  void horizontalScrollValueChanged (int value);\n  void verticalScrollValueChanged (int value);\n  void monitorConsole ();\n  void updateSelection ();\n  void tripleClickTimeout ();\n\nprivate:\n  QConsolePrivate *d;\n  bool allowTripleClick;\n  bool _extra_interrupt;\n};\n\n//////////////////////////////////////////////////////////////////////////////\n\n#endif // __QConsole_h__\n"
  },
  {
    "path": "libgui/qterminal/module.mk",
    "content": "noinst_HEADERS += \\\n  %reldir%/libqterminal/QTerminal.h \\\n  %reldir%/libqterminal/win32/QTerminalColors.h \\\n  %reldir%/libqterminal/win32/QWinTerminalImpl.h \\\n  %reldir%/libqterminal/unix/BlockArray.h \\\n  %reldir%/libqterminal/unix/Character.h \\\n  %reldir%/libqterminal/unix/CharacterColor.h \\\n  %reldir%/libqterminal/unix/Emulation.h \\\n  %reldir%/libqterminal/unix/ExtendedDefaultTranslator.h \\\n  %reldir%/libqterminal/unix/ExtendedDefaultTranslatorMac.h \\\n  %reldir%/libqterminal/unix/Filter.h \\\n  %reldir%/libqterminal/unix/History.h \\\n  %reldir%/libqterminal/unix/KeyboardTranslator.h \\\n  %reldir%/libqterminal/unix/konsole_wcwidth.h \\\n  %reldir%/libqterminal/unix/kpty.h \\\n  %reldir%/libqterminal/unix/kpty_p.h \\\n  %reldir%/libqterminal/unix/QUnixTerminalImpl.h \\\n  %reldir%/libqterminal/unix/Screen.h \\\n  %reldir%/libqterminal/unix/ScreenWindow.h \\\n  %reldir%/libqterminal/unix/TerminalCharacterDecoder.h \\\n  %reldir%/libqterminal/unix/Vt102Emulation.h \\\n  %reldir%/libqterminal/unix/SelfListener.h \\\n  %reldir%/libqterminal/unix/TerminalModel.h \\\n  %reldir%/libqterminal/unix/TerminalView.h\n\nlibgui_qterminal_libqterminal_la_MOC =\n\nOCTAVE_GUI_QTERMINAL_LIBQTERMINAL_MOC = \\\n  %reldir%/libqterminal/moc-QTerminal.cc\n\n$(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_MOC): | %reldir%/libqterminal/$(octave_dirstamp)\n\nDIRSTAMP_FILES += \\\n  %reldir%/libqterminal/$(octave_dirstamp)\n\n%canon_reldir%_libqterminal_la_MOC += \\\n  $(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_MOC)\n\nnodist_%canon_reldir%_libqterminal_la_SOURCES = $(%canon_reldir%_libqterminal_la_MOC)\n\n%canon_reldir%_libqterminal_la_CPPFLAGS = \\\n  $(AM_CPPFLAGS) \\\n  @QT_CPPFLAGS@ \\\n  -I$(srcdir)/%reldir%/libqterminal \\\n  -I$(srcdir)/libgui/src \\\n  -Iliboctave \\\n  -I$(srcdir)/liboctave/array \\\n  -Iliboctave/numeric -I$(srcdir)/liboctave/numeric \\\n  -Iliboctave/operators -I$(srcdir)/liboctave/operators \\\n  -I$(srcdir)/liboctave/system \\\n  -I$(srcdir)/liboctave/util \\\n  -Ilibinterp -I$(srcdir)/libinterp \\\n  -I$(srcdir)/libinterp/template-inst \\\n  -Ilibinterp/parse-tree -I$(srcdir)/libinterp/parse-tree \\\n  -Ilibinterp/corefcn -I$(srcdir)/libinterp/corefcn \\\n  -I$(srcdir)/libinterp/octave-value \\\n  -I$(srcdir)/liboctave/wrappers\n\n%canon_reldir%_libqterminal_la_CFLAGS = ${CPICFLAG} ${XTRA_CFLAGS}\n\n%canon_reldir%_libqterminal_la_CXXFLAGS = ${CXXPICFLAG} ${XTRA_CXXFLAGS}\n\nif WIN32_TERMINAL\n\n%canon_reldir%_libqterminal_la_SOURCES = \\\n  %reldir%/libqterminal/win32/QTerminalColors.cpp \\\n  %reldir%/libqterminal/win32/QWinTerminalImpl.cpp \\\n  %reldir%/libqterminal/QTerminal.cc\n\nOCTAVE_GUI_QTERMINAL_LIBQTERMINAL_WIN32_MOC = \\\n  %reldir%/libqterminal/win32/moc-QWinTerminalImpl.cc\n\n%canon_reldir%_libqterminal_la_MOC += \\\n  $(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_WIN32_MOC)\n\n$(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_WIN32_MOC): | %reldir%/libqterminal/win32/$(octave_dirstamp)\n\nDIRSTAMP_FILES += \\\n  %reldir%/libqterminal/win32/$(octave_dirstamp)\n\n%canon_reldir%_libqterminal_la_CPPFLAGS += -DUNICODE\n\n# This flag is required to let MOC know about Q_OS_WIN32.\nMOC_CPPFLAGS += -DQ_OS_WIN32\n\nelse\n\n%canon_reldir%_libqterminal_la_SOURCES = \\\n  %reldir%/libqterminal/unix/BlockArray.cpp \\\n  %reldir%/libqterminal/unix/Emulation.cpp \\\n  %reldir%/libqterminal/unix/Filter.cpp \\\n  %reldir%/libqterminal/unix/History.cpp \\\n  %reldir%/libqterminal/unix/KeyboardTranslator.cpp \\\n  %reldir%/libqterminal/unix/konsole_wcwidth.cpp \\\n  %reldir%/libqterminal/unix/kpty.cpp \\\n  %reldir%/libqterminal/unix/QUnixTerminalImpl.cpp \\\n  %reldir%/libqterminal/unix/Screen.cpp \\\n  %reldir%/libqterminal/unix/ScreenWindow.cpp \\\n  %reldir%/libqterminal/unix/TerminalCharacterDecoder.cpp \\\n  %reldir%/libqterminal/unix/Vt102Emulation.cpp \\\n  %reldir%/libqterminal/unix/SelfListener.cpp \\\n  %reldir%/libqterminal/unix/TerminalModel.cpp \\\n  %reldir%/libqterminal/unix/TerminalView.cpp \\\n  %reldir%/libqterminal/QTerminal.cc\n\nOCTAVE_GUI_QTERMINAL_LIBQTERMINAL_UNIX_MOC = \\\n  %reldir%/libqterminal/unix/moc-Emulation.cc \\\n  %reldir%/libqterminal/unix/moc-Filter.cc \\\n  %reldir%/libqterminal/unix/moc-QUnixTerminalImpl.cc \\\n  %reldir%/libqterminal/unix/moc-ScreenWindow.cc \\\n  %reldir%/libqterminal/unix/moc-SelfListener.cc \\\n  %reldir%/libqterminal/unix/moc-TerminalModel.cc \\\n  %reldir%/libqterminal/unix/moc-TerminalView.cc \\\n  %reldir%/libqterminal/unix/moc-Vt102Emulation.cc\n\n%canon_reldir%_libqterminal_la_MOC += \\\n  $(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_UNIX_MOC)\n\n%canon_reldir%_libqterminal_la_MOC_H = \\\n  $(%canon_reldir%_libqterminal_la_MOC:.cc=.h)\n\n$(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_UNIX_MOC): | %reldir%/libqterminal/unix/$(octave_dirstamp)\n\nDIRSTAMP_FILES += \\\n  %reldir%/libqterminal/unix/$(octave_dirstamp)\n\nendif\n\nnoinst_LTLIBRARIES += %reldir%/libqterminal.la\n\nlibgui_CLEANFILES += \\\n  $(%canon_reldir%_libqterminal_la_MOC) \\\n  $(%canon_reldir%_libqterminal_la_MOC_H)\n"
  },
  {
    "path": "libgui/qterminal/msvc.pri",
    "content": "CONFIG += release\n\nQMAKE_CXXFLAGS += -MP\nLIBDIR_SUFFIX = release\n\nmsvc-debug {\n\tQMAKE_CXXFLAGS_RELEASE += -Zi\n\tQMAKE_CXXFLAGS_RELEASE -= -O2\n\tQMAKE_LFLAGS_RELEASE += -debug\n\tQMAKE_CLEAN += $(DESTDIR)$(QMAKE_TARGET).pdb\n}\n"
  },
  {
    "path": "libgui/qterminal/qterminal/README",
    "content": "here is sample program which uses QTermWidet for displaying a terminal\n"
  },
  {
    "path": "libgui/qterminal/qterminal/main.cpp",
    "content": "/*  Copyright (C) 2008, 2013 e_k (e_k@users.sourceforge.net)\n\n    This library is free software: you can redistribute it and/or\n    modify it under the terms of the GNU Library General Public\n    License as published by the Free Software Foundation; either\n    version 2 of the License, or (at your option) any later version.\n\t\t\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Library General Public License for more details.\n\t\t\t\t\n    You should have received a copy of the GNU Library General Public License\n    along with this library; see the file COPYING.LIB.  If not, write to\n    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n    Boston, MA 02110-1301, USA.\n*/\n\t\t\t\t\t\t\n\n#include <QtCore>\n#include <QtGui>\n#include <QApplication>\n\n#include \"QTerminal.h\"\n\nint main(int argc, char *argv[])\n{\n    QApplication app(argc, argv);\n    QMainWindow *mainWindow = new QMainWindow();\n\n    QTerminal *terminal = new QTerminal();\n\n    mainWindow->setCentralWidget(terminal);\n    mainWindow->resize(600, 400);\n\n    mainWindow->show();\n    return app.exec();\n}\n"
  },
  {
    "path": "libgui/src/color-picker.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// This class provides a simple color picker based on tQColorButton\n// by Harald Jedele, 23.03.01, GPL version 2 or any later version.\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"color-picker.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Constructor with initial color as parameter\ncolor_picker::color_picker (QColor old_color, QWidget *p)\n  : QPushButton (p)\n{\n  m_color = old_color;\n  setFlat (true);\n  setFocusPolicy (Qt::NoFocus);  // no focus, would change the color\n  update_button ();\n  connect (this, &color_picker::clicked, this, &color_picker::select_color);\n}\n\n// Slot for button clicked: select a new color using QColorDialog\nvoid\ncolor_picker::select_color ()\n{\n  QColor new_color = QColorDialog::getColor (m_color);\n\n  if (new_color.isValid () && new_color != m_color)\n    {\n      m_color = new_color;\n      update_button ();\n    }\n}\n\n// Set the color of the button\nvoid\ncolor_picker::set_color (QColor new_color)\n{\n  m_color = new_color;\n  update_button ();\n}\n\n// Draw the button with the actual color (using a stylesheet)\nvoid\ncolor_picker::update_button ()\n{\n  // Is this the right place to look for a \"foreground\" color that would\n  // provide a reasonable border for the color swatches?\n  QWidget *p = parentWidget ();\n\n  QString bordercolor\n    = (p ? p->palette ().text ().color ().name () : QString (\"#000000\"));\n\n  setStyleSheet (QString (\"background-color: %1; border: 1px solid %2;\")\n                 .arg (m_color.name ())\n                 .arg (bordercolor));\n\n  repaint ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/color-picker.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// This class provides a simple color picker based on tQColorButton\n// by Harald Jedele, 23.03.01, GPL version 2 or any later version.\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_color_picker_h)\n#define octave_color_picker_h 1\n\n#include <QColorDialog>\n#include <QPushButton>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass color_picker : public QPushButton\n{\n  Q_OBJECT\n\npublic:\n\n  color_picker (QColor color = QColor (0, 0, 0), QWidget *parent = nullptr);\n\n  QColor color () const { return m_color; }\n\n  void set_color (QColor new_color);\n\nprivate Q_SLOTS:\n\n  void select_color ();\n\nprivate:\n\n  virtual void update_button ();\n\n  QColor m_color;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/command-widget.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_QSCINTILLA)\n\n#include <QDir>\n#include <QGroupBox>\n#include <QHBoxLayout>\n#include <QLabel>\n#include <QLineEdit>\n#include <QMessageBox>\n#include <QPushButton>\n#include <QTextEdit>\n#include <QTextBlock>\n#include <QVBoxLayout>\n\n#include \"Qsci/qscistyle.h\"\n#include \"Qsci/qscistyledtext.h\"\n#include <Qsci/qscilexeroctave.h>\n\n#include \"unistd-wrappers.h\"\n\n#include \"command-widget.h\"\n#include \"self-listener.h\"\n\n#include \"cmd-edit.h\"\n#include \"event-manager.h\"\n#include \"gui-preferences-cs.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-settings.h\"\n#include \"gui-utils.h\"\n#include \"input.h\"\n#include \"interpreter.h\"\n#include \"oct-env.h\"\n#include \"version.h\"\n\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic const int stdout_fileno = octave_stdout_fileno ();\nstatic const int stderr_fileno = octave_stderr_fileno ();\n\ncommand_widget::command_widget (QWidget *p)\n  : QWidget (p), m_incomplete_parse (false),\n    m_prompt (QString ()),\n    m_console (new console (this)),\n    m_find_widget (new find_widget (false, this)),\n    m_find_shortcut (new QShortcut (this))\n{\n  QPushButton *pause_button = new QPushButton (tr(\"Pause\"), this);\n  QPushButton *stop_button = new QPushButton (tr(\"Stop\"), this);\n  QPushButton *resume_button = new QPushButton (tr(\"Continue\"), this);\n\n  connect (m_find_widget, &find_widget::find_signal,\n           m_console, &console::find);\n  connect (m_find_widget, &find_widget::find_incremental_signal,\n           m_console, &console::find_incremental);\n\n  QWidget *input_widget = new QWidget;\n  QHBoxLayout *input_layout = new QHBoxLayout;\n  input_layout->addWidget (pause_button);\n  input_layout->addWidget (stop_button);\n  input_layout->addWidget (resume_button);\n  input_layout->addStretch ();\n  input_layout->addWidget (m_find_widget);\n  input_layout->setContentsMargins (0, 0, 0, 0);\n  input_widget->setLayout (input_layout);\n  input_widget->setContentsMargins (0, 0, 0, 0);\n\n  QVBoxLayout *main_layout = new QVBoxLayout ();\n  main_layout->addWidget (m_console);\n  main_layout->addWidget (input_widget);\n  main_layout->setSpacing (0);\n  main_layout->setContentsMargins (2, 2, 2, 0);\n\n  setLayout (main_layout);\n\n  setFocusProxy (m_console);\n\n  connect (pause_button, &QPushButton::clicked,\n           this, &command_widget::interpreter_pause);\n\n  connect (resume_button, &QPushButton::clicked,\n           this, &command_widget::interpreter_resume);\n\n  connect (stop_button, &QPushButton::clicked,\n           this, &command_widget::interpreter_stop);\n\n  connect (this, &command_widget::update_prompt_signal,\n           this, &command_widget::update_prompt);\n\n  connect (this, &command_widget::new_command_line_signal,\n           m_console, &console::new_command_line);\n\n  connect (m_console, qOverload<const fcn_callback&> (&console::interpreter_event),\n           this, qOverload<const fcn_callback&> (&command_widget::interpreter_event));\n\n  connect (m_console, qOverload<const meth_callback&> (&console::interpreter_event),\n           this, qOverload<const meth_callback&> (&command_widget::interpreter_event));\n\n  m_find_shortcut->setContext (Qt::WidgetWithChildrenShortcut);\n  connect (m_find_shortcut, &QShortcut::activated,\n           m_find_widget, &find_widget::activate_find);\n\n  // The self_listener object executes in a separate thread.  It\n  // captures output and emits a Qt signal to provide access to the\n  // captured output.  See TODO comment in self-listener.cc\n  m_listener = new self_listener (std::vector<int> {stdout_fileno, stderr_fileno},\n                                  QString (tr (\"Command Widget\")));\n\n  // Connect the listener thread to the command widget function that\n  // inserts text into the command widget.\n  connect (m_listener, &self_listener::receive_data,\n           this, &command_widget::process_redirected_streams,\n           Qt::BlockingQueuedConnection);\n\n  m_listener->start ();\n\n  insert_interpreter_output (\n    QString::fromStdString (octave_startup_message () + \"\\n \"),\n    console_lexer::Default);\n}\n\ncommand_widget::~command_widget ()\n{\n  // m_listener is a guarded pointer and therefore null if already destroyed\n  if (m_listener && m_listener->isRunning ())\n    m_listener->terminate ();\n}\n\nvoid\ncommand_widget::process_redirected_streams (const char *buf, int len, int fd)\n{\n  int style;\n\n  if (fd == stderr_fileno)\n    style = console_lexer::Error;\n  else\n    style = console_lexer::Default;\n\n  m_console->append_string (\n    QString::fromStdString (std::string (buf, len)), style);\n}\n\nvoid\ncommand_widget::init_command_prompt ()\n{\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<command_widget> this_cw (this);\n\n  Q_EMIT interpreter_event\n  ([this, this_cw] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n\n    // We can skip the entire callback function because it does not\n    // make any changes to the interpreter state.\n\n    if (this_cw.isNull ())\n      return;\n\n    std::string prompt = interp.PS1 ();\n    std::string decoded_prompt\n      = command_editor::decode_prompt_string (prompt);\n\n    Q_EMIT update_prompt_signal (QString::fromStdString (decoded_prompt));\n\n    Q_EMIT new_command_line_signal ();\n  });\n}\n\nvoid\ncommand_widget::update_prompt (const QString& prompt)\n{\n  m_prompt = prompt;\n}\n\nQString\ncommand_widget::prompt ()\n{\n  return m_prompt;\n}\n\nvoid\ncommand_widget::insert_interpreter_output (const QString& msg, int style)\n{\n  m_console->append_string (msg, style);\n}\n\nvoid\ncommand_widget::process_input_line (const QString& input_line)\n{\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<command_widget> this_cw (this);\n\n  Q_EMIT interpreter_event\n  ([this, this_cw, input_line] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n\n    // If THIS_CW is no longer valid, we still want to parse and\n    // execute INPUT_LINE but we can't emit the signals associated\n    // with THIS_CW.\n\n    interp.parse_and_execute (input_line.toStdString (),\n                              m_incomplete_parse);\n\n    if (this_cw.isNull ())\n      return;\n\n    std::string prompt\n      = m_incomplete_parse ? interp.PS2 () : interp.PS1 ();\n\n    std::string decoded_prompt\n      = command_editor::decode_prompt_string (prompt);\n\n    Q_EMIT update_prompt_signal (QString::fromStdString (decoded_prompt));\n\n    Q_EMIT new_command_line_signal ();\n  });\n\n}\n\nvoid\ncommand_widget::notice_settings ()\n{\n  gui_settings settings;\n\n  // Set terminal font:\n  QFont term_font = QFont ();\n  term_font.setStyleHint (QFont::TypeWriter);\n  QString default_font = settings.string_value (global_mono_font);\n  term_font.setFamily\n    (settings.value (cs_font.settings_key (), default_font).toString ());\n  term_font.setPointSize\n    (settings.int_value (cs_font_size));\n\n  QsciLexer *lexer = m_console->lexer ();\n  lexer->setFont (term_font);\n\n  // Colors\n  int mode = settings.int_value (cs_color_mode);\n  QColor fgc = settings.color_value (cs_colors[0], mode);\n  QColor bgc = settings.color_value (cs_colors[1], mode);\n  QColor caret = settings.color_value (cs_colors[3], mode);\n\n  lexer->setColor (fgc, console_lexer::Default);\n  lexer->setColor (interpolate_color (fgc, bgc,\n                                      cs_prompt_interp[0], cs_prompt_interp[1]),\n                   console_lexer::Prompt);\n  lexer->setColor (interpolate_color (cs_error_color, fgc,\n                                      cs_error_interp[0], cs_error_interp[1]),\n                   console_lexer::Error);\n  lexer->setPaper (bgc);\n  m_console->setCaretForegroundColor (caret);\n\n  settings.shortcut (m_find_shortcut, sc_edit_edit_find_replace);\n\n  m_find_widget->notice_settings ();\n}\n\n// The console itself using QScintilla.\n// This implementation is partly based on the basic concept of\n// \"qpconsole\" as proposed by user \"DerManu\" in the Qt-forum thread\n// https://forum.qt.io/topic/28765/command-terminal-using-qtextedit\n\nconsole::console (command_widget *p)\n  : QsciScintilla (p),\n    m_command_position (-1),\n    m_cursor_position (0),\n    m_text_changed (false),\n    m_command_widget (p),\n    m_last_key_string (QString ()),\n    m_find_result_available (false),\n    m_find_direction (false),\n    m_last_find_inc_result (QString ()),\n    m_process_command (true)\n{\n  setMargins (0);\n  setWrapMode (QsciScintilla::WrapWord);\n\n  // The following three signal-slot connections must use the old syntax or\n  // they would fail to connect on Windows with warnings like this:\n  // qt.core.qobject.connect: QObject::connect: signal not found in octave::console\n\n  connect (this, SIGNAL (cursorPositionChanged (int, int)),\n           this, SLOT (cursor_position_changed (int, int)));\n\n  connect (this, SIGNAL (textChanged ()),\n           this, SLOT (text_changed ()));\n\n  connect (this, SIGNAL (modificationAttempted ()),\n           this, SLOT (move_cursor_to_end ()));\n\n  console_lexer *lexer = new console_lexer ();\n  setLexer (lexer);\n}\n\n// Prepare a new command line with the current prompt\nvoid\nconsole::new_command_line (const QString& command)\n{\n  if (! text (lines () -1).isEmpty ())\n    append (\"\\n\");\n\n  append_string (m_command_widget->prompt (), console_lexer::Prompt);\n\n  int line, index;\n  getCursorPosition (&line, &index);\n  m_command_position = positionFromLineIndex (line, index);\n\n  append_string (command);\n}\n\n// Accept the current command line (or block)\nvoid\nconsole::accept_command_line ()\n{\n  QString input_line = text (lines () - 1);\n\n  if (input_line.startsWith (m_command_widget->prompt ()))\n    input_line.remove (0, m_command_widget->prompt ().length ());\n\n  input_line = input_line.trimmed ();\n\n  append_string (\"\\n\");\n\n  if (input_line.isEmpty ())\n    new_command_line ();\n  else\n    m_command_widget->process_input_line (input_line);\n}\n\n// Execute a command\nvoid\nconsole::execute_command (const QString& command)\n{\n  if (command.trimmed ().isEmpty ())\n    return;\n\n  new_command_line (command);\n  accept_command_line ();\n}\n\n// Get user input from command line\nvoid\nconsole::get_input_from_terminal (const QString& prompt)\n{\n  m_process_command = false;\n  m_input_prompt = prompt;\n\n  if (! text (lines () - 1).isEmpty ())\n    append (\"\\n\");\n\n  append_string (prompt);\n}\n\nvoid\nconsole::finish_input_from_terminal ()\n{\n  QString input_line = text (lines () - 1);\n\n  if (input_line.startsWith (m_input_prompt))\n    input_line.remove (0, m_input_prompt.length ());\n\n  append_string (\"\\n\");\n\n  m_process_command = true;\n\n  Q_EMIT finished_input_from_terminal_signal (input_line);\n}\n\n// Append a string and update the cursor position\nvoid\nconsole::append_string (const QString& string, int style)\n{\n  size_t pos_begin = text ().length ();\n\n  setReadOnly (false);\n\n  append (string);\n\n  size_t pos_end = text ().length ();\n\n  SendScintilla (QsciScintillaBase::SCI_SETSTYLING, pos_end - pos_begin, style);\n\n  int line, index;\n  lineIndexFromPosition (pos_end, &line, &index);\n\n  setCursorPosition (line, index);\n}\n\n// Cursor position changed: Are we in the command line or not?\nvoid\nconsole::cursor_position_changed (int line, int col)\n{\n  m_cursor_position = positionFromLineIndex (line, col);\n  if (m_cursor_position < m_command_position)\n    {\n      // We are in the read only area\n      if (m_text_changed && (m_cursor_position == m_command_position - 1))\n        {\n          setReadOnly (false);\n          insert (m_command_widget->prompt ().right (1)); // And here we have tried to remove the prompt by Backspace\n          setCursorPosition (line+1, col);\n        }\n      setReadOnly (true);\n    }\n  else\n    setReadOnly (false);  // Writable area\n\n  m_text_changed = false;\n}\n\n// User attempted to type on read only mode: move cursor at end and allow\n// editing\nvoid\nconsole::move_cursor_to_end ()\n{\n  if ((! m_last_key_string.isEmpty ()) && (m_last_key_string.at (0).isPrint ()))\n    {\n      append_string (m_last_key_string);\n      setReadOnly (true); // Avoid that changing read only text is done afterwards\n    }\n}\n\n// Text has changed: is cursor still in \"writable\" area?\n// This signal seems to be emitted before cursor position changed.\nvoid\nconsole::text_changed ()\n{\n  m_text_changed = true;\n}\n\n// find incremental\nvoid\nconsole::find_incremental (const QString& text)\n{\n  int line = -1, col = -1;\n\n  // Go the start of last incremental find result avoiding that the next\n  // match is found instead of the current one\n  if (! m_last_find_inc_result.isEmpty ())\n    {\n      getCursorPosition (&line, &col);\n      int currpos = positionFromLineIndex (line, col);\n      currpos = currpos - (m_last_find_inc_result.length ());\n      lineIndexFromPosition (currpos, &line, &col);\n    }\n\n\n  if (findFirst (text, false, false, false, true, true, line, col))\n    m_last_find_inc_result = text;\n  else\n    m_last_find_inc_result.clear ();\n}\n\n// find\nvoid\nconsole::find (const QString& text, bool backward)\n{\n  bool direction_changed = m_find_direction != backward;\n\n  int line = -1, col = -1;\n\n  if (direction_changed)\n    {\n      // Direction changed\n      m_find_direction = backward;\n      if (m_find_result_available)\n        {\n          // Something was found but direction changed, go to start/end of selection\n          if (m_find_result_available)\n            {\n              getCursorPosition (&line, &col);\n              int currpos = positionFromLineIndex (line, col);\n              if (backward)\n                currpos = currpos - (text.length ());\n              else\n                currpos = currpos + (text.length ());\n              if (currpos < 0)\n                currpos = 0;\n              lineIndexFromPosition (currpos, &line, &col);\n            }\n        }\n    }\n  else\n    {\n      // Direction not changed\n      if (m_find_result_available)\n        {\n          m_find_result_available = findNext ();\n          return;\n        }\n    }\n\n  m_find_result_available =\n    findFirst (text, false, false, false, true, ! backward, line, col);\n}\n\n// Re-implement key event\nvoid\nconsole::keyPressEvent (QKeyEvent *e)\n{\n  if (e->key () == Qt::Key_Return)\n    {\n      if (m_process_command)\n        // On \"return\", accept the current command line\n        accept_command_line ();\n      else\n        // On \"return\", emit a signal that the input is finished\n        finish_input_from_terminal ();\n    }\n  else\n    {\n      // Otherwise, store text process the expected event\n      m_last_key_string = e->text ();\n      QsciScintilla::keyPressEvent (e);\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/command-widget.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_command_widget_h)\n#define octave_command_widget_h 1\n\n#include <QFileSystemWatcher>\n#include <QWidget>\n#include <Qsci/qsciscintilla.h>\n#include <QShortcut>\n#include <QTemporaryFile>\n\n#include \"find-widget.h\"\n#include \"gui-preferences-sc.h\"\n#include \"console-lexer.h\"\n\n// FIXME: We need the following header for the fcn_callback and\n// meth_callback typedefs.  Maybe it would be better to declare those in\n// a separate file because inclding \"event-manager.h\" pulls in a lot of\n// other unnecessary declarations.\n#include \"event-manager.h\"\n\nclass QsciScintilla;\nclass self_listener;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass command_widget;\n\nclass console : public QsciScintilla\n{\n  Q_OBJECT\n\npublic:\n\n  console (command_widget *p);\n\n  void append_string (const QString& string, int style = console_lexer::Default);\n\nQ_SIGNALS:\n\n  void finished_input_from_terminal_signal (const QString& input);\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  void cursor_position_changed (int line, int col);\n\n  void text_changed ();\n\n  void move_cursor_to_end ();\n\n  void new_command_line (const QString& command = QString ());\n\n  void execute_command (const QString& command);\n\n  void get_input_from_terminal (const QString& prompt);\n  void finish_input_from_terminal ();\n\n  void find_incremental (const QString&);\n\n  void find (const QString&, bool);\n\nprotected:\n\n  void keyPressEvent (QKeyEvent *e);\n\nprivate:\n\n  void accept_command_line ();\n\n  int m_command_position;\n  int m_cursor_position;\n  bool m_text_changed;\n  command_widget *m_command_widget;\n  QString m_last_key_string;\n  bool m_find_result_available;\n  bool m_find_direction;\n  QString m_last_find_inc_result;\n  bool m_process_command;\n  QString m_input_prompt;\n};\n\nclass command_widget : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  command_widget (QWidget *p);\n\n  ~command_widget (void);\n\n  console * get_console ( ) { return m_console; };\n\n  void init_command_prompt ();\n\n  QString prompt ();\n\nQ_SIGNALS:\n\n  void clear_line_edit ();\n\n  void interpreter_pause ();\n  void interpreter_resume ();\n  void interpreter_stop ();\n\n  void update_prompt_signal (const QString& prompt);\n  void new_command_line_signal (const QString& command = QString ());\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  void process_redirected_streams (const char *buf, int len, int fd);\n\n  void process_input_line (const QString& input_line);\n\n  void update_prompt (const QString& prompt);\n\n  void insert_interpreter_output (const QString& msg, int style);\n\n  void notice_settings ();\n\nprivate:\n\n  bool m_incomplete_parse;\n  QString m_prompt;\n  console *m_console;\n  QPointer<self_listener> m_listener;\n  find_widget *m_find_widget;\n  QShortcut *m_find_shortcut;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/community-news.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QLayout>\n#include <QTextBrowser>\n#include <QThread>\n\n#include \"community-news.h\"\n#include \"gui-utils.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-dw.h\"\n#include \"gui-preferences-nr.h\"\n#include \"gui-settings.h\"\n#include \"news-reader.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ncommunity_news::community_news (int serial)\n  : QWidget (nullptr), m_browser (nullptr)\n{\n  construct (\"https://octave.org\", \"community-news.html\", serial);\n}\n\ncommunity_news::community_news (QWidget *parent, const QString& base_url,\n                                const QString& page, int serial)\n  : QWidget (parent), m_browser (nullptr)\n{\n  construct (base_url, page, serial);\n}\n\nvoid\ncommunity_news::construct (const QString& base_url, const QString& page,\n                           int serial)\n{\n  m_browser = new QTextBrowser (this);\n\n  m_browser->setObjectName (\"OctaveNews\");\n  m_browser->setOpenExternalLinks (true);\n\n  QVBoxLayout *vlayout = new QVBoxLayout;\n\n  vlayout->addWidget (m_browser);\n\n  setLayout (vlayout);\n  setWindowTitle (tr (\"Octave Community News\"));\n\n  int win_x, win_y;\n  get_screen_geometry (win_x, win_y);\n\n  resize (win_x/2, win_y/2);\n  move ((win_x - width ())/2, (win_y - height ())/2);\n\n  gui_settings settings;\n\n  QString icon;\n  QString icon_set = settings.string_value (dw_icon_set);\n  if (icon_set != \"NONE\")\n    // No extra icon for Community news, take the one of the release notes\n    icon = dw_icon_set_names[icon_set] + \"ReleaseWidget\" + global_icon_extension;\n  else\n    icon = dw_icon_set_names[icon_set];\n\n  setWindowIcon (QIcon (icon));\n\n  // FIXME: This is a news reader preference, so shouldn't it be used\n  // in the news_reader object?\n\n  bool connect_to_web = settings.bool_value (nr_allow_connection);\n\n  QThread *worker_thread = new QThread;\n\n  news_reader *reader\n    = new news_reader (base_url, page, serial, connect_to_web);\n\n  reader->moveToThread (worker_thread);\n\n  connect (reader, &news_reader::display_news_signal,\n           this, &community_news::set_news);\n\n  connect (worker_thread, &QThread::started,\n           reader, &news_reader::process);\n\n  connect (reader, &news_reader::finished, worker_thread, &QThread::quit);\n\n  connect (reader, &news_reader::finished, reader, &news_reader::deleteLater);\n\n  connect (worker_thread, &QThread::finished,\n           worker_thread, &QThread::deleteLater);\n\n  worker_thread->start ();\n}\n\nvoid\ncommunity_news::set_news (const QString& news)\n{\n  m_browser->setHtml (news);\n}\n\nvoid\ncommunity_news::display ()\n{\n  if (! isVisible ())\n    show ();\n  else if (isMinimized ())\n    showNormal ();\n\n  raise ();\n  activateWindow ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/community-news.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_community_news_h)\n#define octave_community_news_h 1\n\n#include <QString>\n#include <QWidget>\n\nclass QTextBrowser;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass community_news : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  community_news (int serial);\n\n  community_news (QWidget *parent = nullptr,\n                  const QString& base_url = \"https://octave.org\",\n                  const QString& page = \"community-news.html\",\n                  int serial = -1);\n\n  ~community_news () = default;\n\npublic Q_SLOTS:\n\n  void set_news (const QString& news);\n\n  void display ();\n\nprivate:\n\n  void construct (const QString& base_url, const QString& page, int serial);\n\n  QTextBrowser *m_browser;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/console-lexer.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2014-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_QSCINTILLA)\n\n#include <Qsci/qscilexer.h>\n\n#include \"console-lexer.h\"\n#include \"gui-settings.h\"\n#include \"gui-preferences-cs.h\"\n#include \"gui-utils.h\"\n\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nQString\nconsole_lexer::description (int style) const\n{\n  switch (style)\n    {\n    case Default:\n      return tr (\"Default\");\n    case Error:\n      return tr (\"Error\");\n    case Prompt:\n      return tr (\"Prompt\");\n    default:\n      return QString ();\n    }\n};\n\nconst char *\nconsole_lexer::language () const\n{\n  return \"Console Output\";\n}\n\nconst char *\nconsole_lexer::lexer () const\n{\n  return \"console-output\";\n}\n\n// Returns the foreground colour of the text for a style.\nQColor\nconsole_lexer::defaultColor(int style) const\n{\n  gui_settings settings;\n\n  int mode = settings.int_value (cs_color_mode);\n  QColor fgc = settings.color_value (cs_colors[0], mode);\n  QColor bgc = settings.color_value (cs_colors[1], mode);\n\n  switch (style)\n    {\n    case Default:\n      return fgc;\n\n    case Error:\n      return interpolate_color (cs_error_color, fgc,\n                                cs_error_interp[0], cs_error_interp[1]);\n\n    case Prompt:\n      return interpolate_color (fgc, bgc,\n                                cs_prompt_interp[0], cs_prompt_interp[1]);\n\n    default:\n      return fgc;\n    }\n}\n\n\n// Returns the font of the text for a style.\nQFont\nconsole_lexer::defaultFont(int style) const\n{\n  gui_settings settings;\n  QFont f (settings.string_value (cs_font));\n\n  switch (style)\n    {\n    case Default:\n    case Error:\n    case Prompt:\n\n    default:\n      return f;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/console-lexer.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_console_lexer_h)\n#define octave_console_lexer_h 1\n\n#include <Qsci/qsciscintilla.h>\n#include <Qsci/qscilexer.h>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass console_lexer : public QsciLexer\n{\n  Q_OBJECT\n\npublic:\n\n  enum\n  {\n    Default = 0,\n    Error = 100,\n    Prompt = 101\n  };\n\n  virtual const char * language () const;\n\n  virtual const char * lexer () const;\n\n  virtual QString description (int style) const;\n\n  virtual QColor defaultColor (int style) const;\n\n  virtual QFont defaultFont (int style) const;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/dialog.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QFileInfo>\n#include <QListView>\n#include <QString>\n#include <QStringList>\n#include <QStringListModel>\n// Could replace most of these with #include <QtGui>\n#include <QGridLayout>\n#include <QGroupBox>\n#include <QHBoxLayout>\n#include <QLabel>\n#include <QMessageBox>\n#include <QPushButton>\n#include <QRegularExpression>\n#include <QVBoxLayout>\n\n#include \"dialog.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-settings.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nQUIWidgetCreator::QUIWidgetCreator ()\n  : QObject (), m_dialog_result (-1), m_dialog_button (),\n    m_string_list (), m_list_index (), m_path_name ()\n{\n  connect (this, &QUIWidgetCreator::create_dialog,\n           this, &QUIWidgetCreator::handle_create_dialog);\n\n  connect (this, &QUIWidgetCreator::create_listview,\n           this, &QUIWidgetCreator::handle_create_listview);\n\n  connect (this, &QUIWidgetCreator::create_inputlayout,\n           this, &QUIWidgetCreator::handle_create_inputlayout);\n\n  connect (this, &QUIWidgetCreator::create_filedialog,\n           this, &QUIWidgetCreator::handle_create_filedialog);\n}\n\nQString\nQUIWidgetCreator::rm_amp (const QString& text)\n{\n  QString text_wo_amp = text;\n  text_wo_amp.replace (QRegularExpression {\"&(\\\\w)\"}, \"\\\\1\");\n  return text_wo_amp;\n}\n\nQString\nQUIWidgetCreator::message_dialog (const QString& message,\n                                  const QString& title,\n                                  const QString& icon,\n                                  const QStringList& buttons,\n                                  const QString& defbutton,\n                                  const QStringList& role)\n{\n  QMutexLocker autolock (&m_mutex);\n\n  // Store button text before a window-manager adds accelerators.\n\n  m_button_list = buttons;\n\n  // Use the last button in the list as the reject result, i.e., when\n  // no button is pressed such as in the case of the upper right close\n  // tab.\n  if (! buttons.isEmpty ())\n    m_dialog_button = buttons.last ();\n\n  QString xicon = icon;\n  if (xicon.isEmpty ())\n    xicon = \"none\";\n\n  Q_EMIT create_dialog (message, title, xicon, buttons, defbutton, role);\n\n  // Wait while the user is responding to message box.\n  wait ();\n\n  // The GUI has sent a signal and the thread has been awakened.\n  return m_dialog_button;\n};\n\nQPair<QIntList, int>\nQUIWidgetCreator::list_dialog (const QStringList& list, const QString& mode,\n                               int wd, int ht, const QList<int>& initial,\n                               const QString& name,\n                               const QStringList& prompt,\n                               const QString& ok_string,\n                               const QString& cancel_string)\n{\n  if (list.isEmpty ())\n    return QPair<QIntList, int> ();\n\n  QMutexLocker autolock (&m_mutex);\n\n  Q_EMIT create_listview (list, mode, wd, ht, initial, name,\n                          prompt, ok_string, cancel_string);\n\n  // Wait while the user is responding to message box.\n  wait ();\n\n  // The GUI has sent a signal and the thread has been awakened.\n  return QPair<QIntList, int> (m_list_index, m_dialog_result);\n};\n\n// Create a message dialog with specified string, buttons and\n// decorative text.\n\nQStringList\nQUIWidgetCreator::input_dialog (const QStringList& prompt,\n                                const QString& title,\n                                const QFloatList& nr,\n                                const QFloatList& nc,\n                                const QStringList& defaults)\n{\n  if (prompt.isEmpty ())\n    return QStringList ();\n\n  QMutexLocker autolock (&m_mutex);\n\n  Q_EMIT create_inputlayout (prompt, title, nr, nc, defaults);\n\n  // Wait while the user is responding to message box.\n  wait ();\n\n  // The GUI has sent a signal and the thread has been awakened.\n  return m_string_list;\n};\n\nQStringList\nQUIWidgetCreator::file_dialog (const QStringList& filters,\n                               const QString& title,\n                               const QString& filename,\n                               const QString& dirname,\n                               const QString& multimode)\n{\n  QMutexLocker autolock (&m_mutex);\n\n  Q_EMIT create_filedialog (filters, title, filename, dirname, multimode);\n\n  // Wait while the user is responding to dialog.\n  wait ();\n\n  // The GUI has sent a signal and the thread has been awakened.\n  // Add all the file dialog results to a string list.\n  QStringList retval;\n  retval << m_string_list\n         << m_path_name\n         << QString::number (m_dialog_result);\n\n  return retval;\n}\n\nvoid\nQUIWidgetCreator::handle_create_dialog (const QString& message,\n                                        const QString& title,\n                                        const QString& icon,\n                                        const QStringList& button,\n                                        const QString& defbutton,\n                                        const QStringList& role)\n{\n  MessageDialog *message_dialog\n    = new MessageDialog (message, title, icon, button, defbutton, role);\n\n  connect (message_dialog, &MessageDialog::buttonClicked,\n           this, &QUIWidgetCreator::dialog_button_clicked);\n\n  message_dialog->setAttribute (Qt::WA_DeleteOnClose);\n  message_dialog->setModal (true);\n  message_dialog->show ();\n}\n\nvoid\nQUIWidgetCreator::dialog_button_clicked (QAbstractButton *button)\n{\n  // button is NULL when dialog is closed.\n  if (button)\n    {\n      // Check for a matching button text while ignoring accelerators\n      // because the window manager may have added one in the passed\n      // button.\n\n      QString text_clean = rm_amp (button->text ());\n\n      for (int i = 0; i < m_button_list.count (); i++)\n        {\n          if (rm_amp (m_button_list.at (i)) == text_clean)\n            {\n              // Text w/o extra accelerator.\n              m_dialog_button = m_button_list.at (i);\n              break;\n            }\n        }\n    }\n\n  // The value should always be 1 for the Octave functions.\n  m_dialog_result = 1;\n\n  // Wake up Octave process so that it continues.\n  wake_all ();\n}\n\n// Create a list dialog with specified list, initially selected, mode,\n// view size and decorative text.\n\nvoid\nQUIWidgetCreator::handle_create_listview (const QStringList& list,\n    const QString& mode,\n    int wd, int ht,\n    const QIntList& initial,\n    const QString& name,\n    const QStringList& prompt,\n    const QString& ok_string,\n    const QString& cancel_string)\n{\n  ListDialog *list_dialog\n    = new ListDialog (list, mode, wd, ht, initial,\n                      name, prompt, ok_string, cancel_string);\n\n  connect (list_dialog, &ListDialog::finish_selection,\n           this, &QUIWidgetCreator::list_select_finished);\n\n  list_dialog->setAttribute (Qt::WA_DeleteOnClose);\n  list_dialog->setModal (true);\n  list_dialog->show ();\n}\n\nvoid\nQUIWidgetCreator::list_select_finished (const QIntList& selected,\n                                        int button_pressed)\n{\n  // Store the value so that builtin functions can retrieve.\n\n  m_list_index = selected;\n  m_dialog_result = button_pressed;\n\n  // Wake up Octave process so that it continues.\n  wake_all ();\n}\n\n// Create an input dialog with specified prompts and defaults, title\n// and row/column size specifications.\n\nvoid\nQUIWidgetCreator::handle_create_inputlayout (const QStringList& prompt,\n    const QString& title,\n    const QFloatList& nr,\n    const QFloatList& nc,\n    const QStringList& defaults)\n{\n  InputDialog *input_dialog\n    = new InputDialog (prompt, title, nr, nc, defaults);\n\n  connect (input_dialog, &InputDialog::finish_input,\n           this, &QUIWidgetCreator::input_finished);\n\n  input_dialog->setAttribute (Qt::WA_DeleteOnClose);\n  input_dialog->setModal (true);\n  input_dialog->show ();\n}\n\nvoid\nQUIWidgetCreator::input_finished (const QStringList& input,\n                                  int button_pressed)\n{\n  // Store the value so that builtin functions can retrieve.\n\n  m_string_list = input;\n  m_dialog_result = button_pressed;\n\n  // Wake up Octave process so that it continues.\n  wake_all ();\n}\n\nvoid\nQUIWidgetCreator::handle_create_filedialog (const QStringList& filters,\n    const QString& title,\n    const QString& filename,\n    const QString& dirname,\n    const QString& multimode)\n{\n  FileDialog *file_dialog\n    = new FileDialog (filters, title, filename, dirname, multimode);\n\n  connect (file_dialog, &FileDialog::finish_input,\n           this, &QUIWidgetCreator::filedialog_finished);\n\n  file_dialog->setAttribute (Qt::WA_DeleteOnClose);\n  file_dialog->setModal (true);\n  file_dialog->show ();\n}\n\nvoid\nQUIWidgetCreator::filedialog_finished (const QStringList& files,\n                                       const QString& path,\n                                       int filterindex)\n{\n  // Store the value so that builtin functions can retrieve.\n\n  m_string_list = files;\n  m_dialog_result = filterindex;\n  m_path_name = path;\n\n  // Wake up Octave process so that it continues.\n  wake_all ();\n}\n\nMessageDialog::MessageDialog (const QString& message,\n                              const QString& title, const QString& qsicon,\n                              const QStringList& qsbutton,\n                              const QString& defbutton,\n                              const QStringList& role)\n  : QMessageBox (QMessageBox::NoIcon, title.isEmpty () ? \" \" : title,\n                 message)\n{\n  // Create a NonModal message.\n  setWindowModality (Qt::NonModal);\n\n  // Interpret the icon string, because enumeration QMessageBox::Icon can't\n  // easily be made to pass through a signal.\n\n  QMessageBox::Icon eicon = QMessageBox::NoIcon;\n\n  if (qsicon == \"error\")\n    eicon = QMessageBox::Critical;\n  else if (qsicon == \"warn\")\n    eicon = QMessageBox::Warning;\n  else if (qsicon == \"help\")\n    eicon = QMessageBox::Information;\n  else if (qsicon == \"quest\")\n    eicon = QMessageBox::Question;\n\n  setIcon (eicon);\n\n  int N = (qsbutton.size () < role.size () ? qsbutton.size () : role.size ());\n\n  if (N == 0)\n    addButton (QMessageBox::Ok);\n  else\n    {\n      for (int i = 0; i < N; i++)\n        {\n          // Interpret the button role string, because enumeration\n          // QMessageBox::ButtonRole can't be made to pass through a\n          // signal.\n\n          QString srole = role.at (i);\n          QMessageBox::ButtonRole erole = QMessageBox::InvalidRole;\n          if (srole == \"ResetRole\")\n            erole = QMessageBox::ResetRole;\n          else if (srole == \"YesRole\")\n            erole = QMessageBox::YesRole;\n          else if (srole == \"NoRole\")\n            erole = QMessageBox::NoRole;\n          else if (srole == \"RejectRole\")\n            erole = QMessageBox::RejectRole;\n          else if (srole == \"AcceptRole\")\n            erole = QMessageBox::AcceptRole;\n\n          QPushButton *pbutton = addButton (qsbutton.at (i), erole);\n          if (qsbutton.at (i) == defbutton)\n            setDefaultButton (pbutton);\n\n          // Make the last button the button pressed when <esc> key activated.\n          if (i == N-1)\n            {\n              // FIXME: Why define and then immediately test value?\n#define ACTIVE_ESCAPE 1\n#if ACTIVE_ESCAPE\n              setEscapeButton (pbutton);\n#else\n              setEscapeButton (0);\n#endif\n#undef ACTIVE_ESCAPE\n            }\n        }\n    }\n}\n\nListDialog::ListDialog (const QStringList& list,\n                        const QString& mode, int wd, int ht,\n                        const QList<int>& initial, const QString& title,\n                        const QStringList& prompt,\n                        const QString& ok_string,\n                        const QString& cancel_string)\n  : QDialog (), m_model (new QStringListModel (list, this))\n{\n  QListView *view = new QListView;\n  view->setModel (m_model);\n\n  if (mode == \"single\")\n    view->setSelectionMode (QAbstractItemView::SingleSelection);\n  else if (mode == \"multiple\")\n    view->setSelectionMode (QAbstractItemView::ExtendedSelection);\n  else\n    view->setSelectionMode (QAbstractItemView::NoSelection);\n\n  m_selector = view->selectionModel ();\n  for (int i = 0; i < initial.count (); i++)\n    {\n      QModelIndex idx = m_model->index (initial.value (i) - 1, 0,\n                                        QModelIndex ());\n      m_selector->select (idx, QItemSelectionModel::Select);\n    }\n\n  bool fixed_layout = false;\n  if (wd > 0 && ht > 0)\n    {\n      view->setFixedSize (wd, ht);\n      fixed_layout = true;\n    }\n\n  view->setEditTriggers (QAbstractItemView::NoEditTriggers);\n\n  QVBoxLayout *listLayout = new QVBoxLayout;\n  if (! prompt.isEmpty ())\n    {\n      // Note: Assume html-like Rich Text.\n      // Check for future incompatibilities if any.\n      QString prompt_string;\n      prompt_string.append (prompt.at (0));\n      for (int j = 1; j < prompt.length (); j++)\n        {\n          prompt_string.append (\"<br>\");\n          prompt_string.append (prompt.at (j));\n        }\n      QLabel *plabel = new QLabel (prompt_string);\n      plabel->setTextFormat (Qt::RichText);\n      listLayout->addWidget (plabel);\n    }\n  listLayout->addWidget (view);\n  QPushButton *select_all = new QPushButton (tr (\"Select All\"));\n  select_all->setVisible (mode == \"multiple\");\n  listLayout->addWidget (select_all);\n\n  QPushButton *buttonOk = new QPushButton (ok_string);\n  QPushButton *buttonCancel = new QPushButton (cancel_string);\n  QHBoxLayout *buttonsLayout = new QHBoxLayout;\n  buttonsLayout->addStretch (1);\n  buttonsLayout->addWidget (buttonOk);\n  buttonsLayout->addWidget (buttonCancel);\n  buttonOk->setDefault (true);\n\n  QVBoxLayout *mainLayout = new QVBoxLayout;\n  mainLayout->addLayout (listLayout);\n  mainLayout->addSpacing (12);\n  mainLayout->addLayout (buttonsLayout);\n  setLayout (mainLayout);\n  if (fixed_layout)\n    layout ()->setSizeConstraint (QLayout::SetFixedSize);\n\n  // If empty, make blank rather than use default OS behavior.\n  setWindowTitle (title.isEmpty () ? \" \" : title);\n\n  connect (select_all, &QPushButton::clicked,\n           view, &QListView::selectAll);\n\n  connect (buttonOk, &QPushButton::clicked,\n           this, &ListDialog::buttonOk_clicked);\n\n  connect (buttonCancel, &QPushButton::clicked,\n           this, &ListDialog::buttonCancel_clicked);\n\n  connect (view, &QListView::doubleClicked,\n           this, &ListDialog::item_double_clicked);\n}\n\nvoid\nListDialog::buttonOk_clicked ()\n{\n  // Store information about what button was pressed so that builtin\n  // functions can retrieve.\n\n  QModelIndexList selected_index = m_selector->selectedIndexes ();\n  QIntList selected_int;\n\n  for (int i = 0; i < selected_index.size (); i++)\n    selected_int << selected_index.at (i).row () + 1;\n\n  Q_EMIT finish_selection (selected_int, 1);\n\n  done (QDialog::Accepted);\n}\n\nvoid\nListDialog::buttonCancel_clicked ()\n{\n  // Store information about what button was pressed so that builtin\n  // functions can retrieve.\n\n  QIntList empty;\n\n  Q_EMIT finish_selection (empty, 0);\n\n  done (QDialog::Rejected);\n}\n\nvoid\nListDialog::reject ()\n{\n  buttonCancel_clicked ();\n}\n\nvoid\nListDialog::item_double_clicked (const QModelIndex&)\n{\n  buttonOk_clicked ();\n}\n\nInputDialog::InputDialog (const QStringList& prompt,\n                          const QString& title, const QFloatList& nr,\n                          const QFloatList& nc, const QStringList& defaults)\n  : QDialog ()\n{\n\n#define LINE_EDIT_FOLLOWS_PROMPT 0\n\n#if LINE_EDIT_FOLLOWS_PROMPT\n  // Prompt on left followed by input on right.\n  QGridLayout *promptInputLayout = new QGridLayout;\n#else\n  // Prompt aligned above input.\n  QVBoxLayout *promptInputLayout = new QVBoxLayout;\n#endif\n  int N_gridrows = prompt.size ();\n  for (int i = 0; i < N_gridrows; i++)\n    {\n      QLabel *label = new QLabel (prompt.at (i));\n      QLineEdit *line_edit = new QLineEdit ();\n      if (i < defaults.size ())\n        line_edit->setText (defaults.at (i));\n      if (i < nr.size () && nr.at (i) > 0)\n        {\n          QSize qsize = line_edit->sizeHint ();\n          int intval = qsize.height () * nr.at (i);\n          line_edit->setFixedHeight (intval);\n          if (i < nc.size () && nc.at (i) > 0)\n            {\n              intval = qsize.height () * nc.at (i) / 2;\n              line_edit->setFixedWidth (intval);\n            }\n        }\n      m_input_line << line_edit;\n#if LINE_EDIT_FOLLOWS_PROMPT\n      promptInputLayout->addWidget (label, i + 1, 0);\n      promptInputLayout->addWidget (line_edit, i + 1, 1);\n#else\n      promptInputLayout->addWidget (label);\n      promptInputLayout->addWidget (line_edit);\n#endif\n    }\n#undef LINE_EDIT_FOLLOWS_PROMPT\n\n  QPushButton *buttonOk = new QPushButton (\"OK\");\n  QPushButton *buttonCancel = new QPushButton (\"Cancel\");\n  QHBoxLayout *buttonsLayout = new QHBoxLayout;\n  buttonsLayout->addStretch (1);\n  buttonsLayout->addWidget (buttonOk);\n  buttonsLayout->addWidget (buttonCancel);\n\n  QVBoxLayout *mainLayout = new QVBoxLayout;\n  mainLayout->addLayout (promptInputLayout);\n  mainLayout->addSpacing (12);\n  mainLayout->addLayout (buttonsLayout);\n  setLayout (mainLayout);\n\n  // If empty, make blank rather than use default OS behavior.\n  setWindowTitle (title.isEmpty () ? \" \" : title);\n\n  connect (buttonOk, &QPushButton::clicked,\n           this, &InputDialog::buttonOk_clicked);\n\n  connect (buttonCancel, &QPushButton::clicked,\n           this, &InputDialog::buttonCancel_clicked);\n}\n\nvoid\nInputDialog::buttonOk_clicked ()\n{\n  // Store information about what button was pressed so that builtin\n  // functions can retrieve.\n\n  QStringList string_result;\n  for (int i = 0; i < m_input_line.size (); i++)\n    string_result << m_input_line.at (i)->text ();\n  Q_EMIT finish_input (string_result, 1);\n  done (QDialog::Accepted);\n}\n\nvoid\nInputDialog::buttonCancel_clicked ()\n{\n  // Store information about what button was pressed so that builtin\n  // functions can retrieve.\n\n  QStringList empty;\n  Q_EMIT finish_input (empty, 0);\n  done (QDialog::Rejected);\n}\n\nvoid\nInputDialog::reject ()\n{\n  buttonCancel_clicked ();\n}\n\nFileDialog::FileDialog (const QStringList& name_filters,\n                        const QString& title, const QString& filename,\n                        const QString& dirname, const QString& multimode)\n  : QFileDialog ()\n{\n  gui_settings settings;\n\n  // This should be set before any other dialog properties\n  if (! settings.bool_value (global_use_native_dialogs))\n    setOption (QFileDialog::DontUseNativeDialog);\n\n  // Create a NonModal message.\n  setWindowModality (Qt::NonModal);\n\n  setWindowTitle (title.isEmpty () ? \" \" : title);\n  setDirectory (dirname);\n\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n\n  if (multimode == \"on\")         // uigetfile multiselect=on\n    {\n      setFileMode (QFileDialog::ExistingFiles);\n      setAcceptMode (QFileDialog::AcceptOpen);\n    }\n  else if (multimode == \"create\") // uiputfile\n    {\n      setFileMode (QFileDialog::AnyFile);\n      setAcceptMode (QFileDialog::AcceptSave);\n      setOption (QFileDialog::DontConfirmOverwrite, false);\n    }\n  else if (multimode == \"dir\")    // uigetdir\n    {\n      setFileMode (QFileDialog::Directory);\n      setOption (QFileDialog::ShowDirsOnly, true);\n      setOption (QFileDialog::HideNameFilterDetails, true);\n      setAcceptMode (QFileDialog::AcceptOpen);\n    }\n  else                           // uigetfile multiselect=off\n    {\n      setFileMode (QFileDialog::ExistingFile);\n      setAcceptMode (QFileDialog::AcceptOpen);\n    }\n\n  setNameFilters (name_filters);\n\n  selectFile (filename);\n\n  connect (this, &FileDialog::accepted, this, &FileDialog::acceptSelection);\n\n  connect (this, &FileDialog::rejected, this, &FileDialog::rejectSelection);\n}\n\nvoid\nFileDialog::rejectSelection ()\n{\n  QStringList empty;\n  Q_EMIT finish_input (empty, \"\", 0);\n}\n\nvoid\nFileDialog::acceptSelection ()\n{\n  QStringList string_result;\n  QString path;\n  int idx = 1;\n\n  string_result = selectedFiles ();\n\n  if (testOption (QFileDialog::ShowDirsOnly) && string_result.size () > 0)\n    path = string_result[0];\n  else\n    path = directory ().absolutePath ();\n\n  // Matlab expects just the filename, whereas the file dialog gave us\n  // full path names, so fix it.\n\n  for (int i = 0; i < string_result.size (); i++)\n    string_result[i] = QFileInfo (string_result[i]).fileName ();\n\n  // If not showing only dirs, add end slash for the path component.\n  if (testOption (QFileDialog::ShowDirsOnly)  == false)\n    path += '/';\n\n  // Convert to native slashes.\n  path = QDir::toNativeSeparators (path);\n\n  QStringList name_filters = nameFilters ();\n  idx = name_filters.indexOf (selectedNameFilter ()) + 1;\n\n  // Send the selected info.\n  Q_EMIT finish_input (string_result, path, idx);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/dialog.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dialog_h)\n#define octave_dialog_h 1\n\n#include <QAbstractButton>\n#include <QDialog>\n#include <QFileDialog>\n#include <QItemSelectionModel>\n#include <QLineEdit>\n#include <QList>\n#include <QMessageBox>\n#include <QMutex>\n#include <QWaitCondition>\n\n// Defined for purposes of sending QList<int> as part of signal.\ntypedef QList<int> QIntList;\n\n// Defined for purposes of sending QList<float> as part of signal.\ntypedef QList<float> QFloatList;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass QUIWidgetCreator : public QObject\n{\n  Q_OBJECT\n\npublic:\n\n  QUIWidgetCreator ();\n\n  ~QUIWidgetCreator () = default;\n\npublic:\n\n  QString rm_amp (const QString& text);\n\n  QString message_dialog (const QString& message, const QString& title,\n                          const QString& icon, const QStringList& button,\n                          const QString& defbutton, const QStringList& role);\n\n  int get_dialog_result () { return m_dialog_result; }\n\n  QString get_dialog_button () { return m_dialog_button; }\n\n  QPair<QIntList, int> list_dialog (const QStringList& list,\n                                    const QString& mode,\n                                    int wd, int ht,\n                                    const QList<int>& initial,\n                                    const QString& name,\n                                    const QStringList& prompt,\n                                    const QString& ok_string,\n                                    const QString& cancel_string);\n\n  QIntList get_list_index () const { return m_list_index; }\n\n  QStringList input_dialog (const QStringList& prompt, const QString& title,\n                            const QFloatList& nr, const QFloatList& nc,\n                            const QStringList& defaults);\n\n  QStringList get_string_list () const { return m_string_list; }\n\n  QStringList file_dialog (const QStringList& filters, const QString& title,\n                           const QString& filename, const QString& dirname,\n                           const QString& multimode);\n\n  QString get_dialog_path () const { return m_path_name; }\n\n  void lock () { m_mutex.lock (); }\n  void wait () { m_waitcondition.wait (&m_mutex); }\n  void unlock () { m_mutex.unlock (); }\n  void wake_all () { m_waitcondition.wakeAll (); }\n\nQ_SIGNALS:\n\n  void create_dialog (const QString&, const QString&, const QString&,\n                      const QStringList&, const QString&, const QStringList&);\n\n  void create_listview (const QStringList&, const QString&, int, int,\n                        const QIntList&, const QString&, const QStringList&,\n                        const QString&, const QString&);\n\n  void create_inputlayout (const QStringList&, const QString&,\n                           const QFloatList&, const QFloatList&,\n                           const QStringList&);\n\n  void create_filedialog (const QStringList& filters, const QString& title,\n                          const QString& filename, const QString& dirname,\n                          const QString& multimode);\npublic Q_SLOTS:\n\n  void handle_create_dialog (const QString& message, const QString& title,\n                             const QString& icon, const QStringList& button,\n                             const QString& defbutton,\n                             const QStringList& role);\n\n  void dialog_button_clicked (QAbstractButton *button);\n\n  void handle_create_listview (const QStringList& list, const QString& mode,\n                               int width, int height,\n                               const QIntList& initial,\n                               const QString& name,\n                               const QStringList& prompt,\n                               const QString& ok_string,\n                               const QString& cancel_string);\n\n  void list_select_finished (const QIntList& selected, int button_pressed);\n\n  void handle_create_inputlayout (const QStringList&, const QString&,\n                                  const QFloatList&, const QFloatList&,\n                                  const QStringList&);\n\n  void input_finished (const QStringList& input, int button_pressed);\n\n  void handle_create_filedialog (const QStringList& filters,\n                                 const QString& title,\n                                 const QString& filename,\n                                 const QString& dirname,\n                                 const QString& multimode);\n\n  void filedialog_finished (const QStringList& files, const QString& path,\n                            int filterindex);\n\nprivate:\n\n  int m_dialog_result;\n  QString m_dialog_button;\n\n  // A copy of the dialogs button texts\n  QStringList m_button_list;\n\n  // The list could conceivably be big.  Not sure how things are\n  // stored internally, so keep off of the stack.\n  QStringList m_string_list;\n  QIntList m_list_index;\n\n  QString m_path_name;\n\n  // GUI objects cannot be accessed in the non-GUI thread.  However,\n  // signals can be sent to slots across threads with proper\n  // synchronization.  Hence, the use of QWaitCondition.\n  QMutex m_mutex;\n  QWaitCondition m_waitcondition;\n};\n\nclass MessageDialog : public QMessageBox\n{\n  Q_OBJECT\n\npublic:\n\n  MessageDialog (const QString& message,\n                 const QString& title, const QString& icon,\n                 const QStringList& button, const QString& defbutton,\n                 const QStringList& role);\n\n  ~MessageDialog () = default;\n\nprivate:\n\n  void closeEvent (QCloseEvent *)\n  {\n    // Reroute the close tab to a button click so there is only a single\n    // route to waking the wait condition.\n    Q_EMIT buttonClicked (nullptr);\n  }\n};\n\nclass ListDialog : public QDialog\n{\n  Q_OBJECT\n\npublic:\n\n  ListDialog (const QStringList& list,\n              const QString& mode, int width, int height,\n              const QList<int>& initial, const QString& name,\n              const QStringList& prompt, const QString& ok_string,\n              const QString& cancel_string);\n\n  ~ListDialog () = default;\n\nQ_SIGNALS:\n\n  void finish_selection (const QIntList&, int);\n\npublic Q_SLOTS:\n\n  void buttonOk_clicked ();\n\n  void buttonCancel_clicked ();\n\n  void reject ();\n\n  void item_double_clicked (const QModelIndex&);\n\nprivate:\n\n  QAbstractItemModel *m_model;\n  QItemSelectionModel *m_selector;\n};\n\nclass InputDialog : public QDialog\n{\n  Q_OBJECT\n\npublic:\n\n  InputDialog (const QStringList& prompt,\n               const QString& title, const QFloatList& nr,\n               const QFloatList& nc, const QStringList& defaults);\n\n  ~InputDialog () = default;\n\nQ_SIGNALS:\n\n  void finish_input (const QStringList&, int);\n\npublic Q_SLOTS:\n\n  void buttonOk_clicked ();\n\n  void buttonCancel_clicked ();\n\n  void reject ();\n\nprivate:\n\n  QList<QLineEdit *> m_input_line;\n};\n\nclass FileDialog : public QFileDialog\n{\n  Q_OBJECT\n\npublic:\n\n  FileDialog (const QStringList& filters,\n              const QString& title, const QString& filename,\n              const QString& dirname, const QString& multimode);\n\n  ~FileDialog () = default;\n\nQ_SIGNALS:\n\n  void finish_input (const QStringList&, const QString&, int);\n\nprivate Q_SLOTS:\n\n  void acceptSelection ();\n\n  void rejectSelection ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/documentation-bookmarks.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QCompleter>\n#include <QDir>\n#include <QFileInfo>\n#include <QLabel>\n#include <QLineEdit>\n#include <QMenu>\n#include <QMessageBox>\n#include <QVBoxLayout>\n#include <QWidget>\n\n#include \"documentation.h\"\n#include \"documentation-bookmarks.h\"\n\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-dc.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-settings.h\"\n#include \"gui-utils.h\"\n\n#include \"defaults.h\"\n#include \"file-ops.h\"\n#include \"oct-env.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ndocumentation_bookmarks::documentation_bookmarks (documentation *doc,\n                                                  documentation_browser *browser,\n                                                  QWidget *p)\n  : QWidget (p), m_doc (doc), m_browser (browser), m_ctx_menu_item (nullptr)\n{\n  setObjectName (\"documentation_tab_bookmarks\");\n\n  gui_settings settings;\n\n  // Setup the tree view with the bookmarks\n  m_tree = new QTreeWidget (p);\n\n  m_tree->setContextMenuPolicy (Qt::CustomContextMenu);\n  m_tree->setSelectionMode (QAbstractItemView::ExtendedSelection);\n  m_tree->setSortingEnabled (false);\n  m_tree->setDragEnabled (true);\n  m_tree->viewport ()->setAcceptDrops (true);\n  m_tree->setDropIndicatorShown (true);\n  m_tree->setDragDropMode (QAbstractItemView::InternalMove);\n  m_tree->setColumnCount (1);\n  m_tree->setHeaderHidden (true);\n  m_tree->setEditTriggers (QAbstractItemView::EditKeyPressed\n                           | QAbstractItemView::SelectedClicked);\n\n  connect (m_tree, &QTreeWidget::customContextMenuRequested,\n           this, &documentation_bookmarks::ctx_menu);\n  connect (m_tree, &QTreeWidget::itemDoubleClicked,\n           this, &documentation_bookmarks::handle_double_click);\n\n  // Define the icons for the tree view\n  m_icon_folder.addPixmap (style ()->standardPixmap (QStyle::SP_DirClosedIcon),\n                           QIcon::Normal, QIcon::Off);\n  m_icon_folder.addPixmap (style ()->standardPixmap (QStyle::SP_DirOpenIcon),\n                           QIcon::Normal, QIcon::On);\n  m_icon_bookmark.addPixmap (style ()->standardPixmap (QStyle::SP_FileIcon));\n\n  // Setup and read the bookmarkfile\n  QFileInfo f (settings.fileName ());\n  QString f_path = f.absolutePath ();\n  f.setFile (QDir (f_path), dc_bookmark_file);\n  m_xbel_file.setFileName (f.absoluteFilePath ());\n\n  if (m_xbel_file.exists ())\n    {\n      QString err = read_bookmarks ();\n      if ( !err.isEmpty ())\n        {\n          err.append (tr (\"\\nNo documentation bookmarks loaded!\"));\n          QMessageBox::warning (this,\n                                tr (\"Octave: Loading Documentation Bookmarks\"),\n                                err);\n          m_xbel_file.close ();\n        }\n    }\n\n  // Setup the filter widget\n  m_filter_widget = new QWidget (p);\n  m_filter = new QComboBox (m_filter_widget);\n\n  m_filter->setToolTip (tr (\"Enter text to search the bookmarks\"));\n  m_filter->setEditable (true);\n  m_filter->setInsertPolicy (QComboBox::NoInsert);\n  m_filter->setMaxCount (10);\n  m_filter->setMaxVisibleItems (10);\n  m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);\n  QSizePolicy size_pol (QSizePolicy::Expanding, QSizePolicy::Preferred);\n  m_filter->setSizePolicy (size_pol);\n  m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);\n\n  m_filter->addItems (settings.string_list_value (dc_bookmark_filter_mru));\n\n  connect (m_filter, &QComboBox::editTextChanged,\n           this, &documentation_bookmarks::filter_bookmarks);\n  connect (m_filter->lineEdit (), &QLineEdit::editingFinished,\n           this, &documentation_bookmarks::update_filter_history);\n\n  m_filter_checkbox = new QCheckBox (m_filter_widget);\n  bool filter_state = settings.bool_value (dc_bookmark_filter_active);\n  m_filter_checkbox->setChecked (filter_state);\n  filter_activate (filter_state);\n\n  connect (m_filter_checkbox, &QCheckBox::toggled,\n           this, &documentation_bookmarks::filter_activate);\n\n  QLabel *filter_label = new QLabel (tr (\"Filter\"), m_filter_widget);\n  QHBoxLayout *h_box_bm = new QHBoxLayout (m_filter_widget);\n  h_box_bm->addWidget (filter_label);\n  h_box_bm->addWidget (m_filter_checkbox);\n  h_box_bm->addWidget (m_filter);\n  h_box_bm->setContentsMargins (2, 2, 2, 2);\n  m_filter_widget->setLayout (h_box_bm);\n\n  m_filter_shown = settings.bool_value (dc_bookmark_filter_shown);\n  m_filter_widget->setVisible (m_filter_shown);\n\n  // Resulting Layout of this widget\n  QVBoxLayout *v_box_bm = new QVBoxLayout (this);\n  v_box_bm->addWidget (m_filter_widget);\n  v_box_bm->addWidget (m_tree);\n  setLayout (v_box_bm);\n}\n\n// Slot for adding the current page as a bookmark\nvoid\ndocumentation_bookmarks::add_bookmark ()\n{\n  QUrl url = m_browser->historyUrl (0);\n\n  // Check if bookmark already exists and select if yes\n  QTreeWidgetItemIterator it (m_tree);\n  while (*it)\n    {\n      QUrl url_i = (*it)->data (0, url_role).toUrl ();\n      if (url == url_i)\n        {\n          m_tree->setCurrentItem (*it);\n          (*it)->setExpanded (true);\n          return;\n        }\n      it++;\n    }\n\n  // Add the anchor name to the title of the page and add the bookmark\n  // as top-level-item\n  QString title = m_doc->title_and_anchor (m_browser->historyTitle (0), url);\n  add_bookmark (title, url.toString ());\n}\n\n// Function for actually adding a bookmark to the tree\nvoid\ndocumentation_bookmarks::add_bookmark (const QString& title,\n                                       const QString& url,\n                                       QTreeWidgetItem *item)\n{\n  // Create new bookmark\n  QTreeWidgetItem *new_item = new QTreeWidgetItem (QStringList (title));\n  new_item->setData (0, tag_role, QVariant (bookmark_tag));\n  new_item->setData (0, url_role, QVariant (url));\n  new_item->setFlags ((new_item->flags () & (~Qt::ItemIsDropEnabled))\n                      | Qt::ItemIsEditable\n                      | Qt::ItemIsDragEnabled);\n  new_item->setIcon (0, m_icon_bookmark);\n\n  // Insert as top level or child item\n  // TODO: Open dialog allowing to select a target folder if this\n  //       bookmark is added manually and not by reading a bookmark file\n  if (item)\n    item->addChild (new_item);\n  else\n    m_tree->addTopLevelItem (new_item);\n}\n\n// Slot for adding a folder from the context menu\nvoid\ndocumentation_bookmarks::add_folder (bool)\n{\n  QTreeWidgetItem *parent_item = nullptr;\n\n  if (m_ctx_menu_item)\n    {\n      if (m_ctx_menu_item->data (0, tag_role).toInt () == folder_tag)\n        parent_item = m_ctx_menu_item;\n      else\n        {\n          QTreeWidgetItem *p = m_ctx_menu_item->parent ();\n          if (p)\n            parent_item = p;\n        }\n    }\n\n  QTreeWidgetItem *new_folder = add_folder (tr (\"New Folder\"), parent_item);\n\n  m_tree->setCurrentItem (new_folder);\n  m_tree->editItem (new_folder);\n}\n\n// Function for actually adding a folder to the tree\nQTreeWidgetItem *\ndocumentation_bookmarks::add_folder (const QString& folder,\n                                     QTreeWidgetItem *item, bool expanded)\n{\n  QTreeWidgetItem *new_folder = new QTreeWidgetItem (QStringList (folder));\n  new_folder->setData (0, tag_role, QVariant (folder_tag));\n  new_folder->setFlags (new_folder->flags () | Qt::ItemIsEditable\n                        | Qt::ItemIsDragEnabled\n                        | Qt::ItemIsDropEnabled);\n  new_folder->setChildIndicatorPolicy (QTreeWidgetItem::DontShowIndicatorWhenChildless);\n  new_folder->setIcon (0, m_icon_folder);\n  new_folder->setExpanded (expanded);\n\n  // Insert as top level or child item\n  if (item)\n    item->addChild (new_folder);\n  else\n    m_tree->addTopLevelItem (new_folder);\n\n  return new_folder;\n}\n\nvoid\ndocumentation_bookmarks::filter_bookmarks (const QString& pattern)\n{\n  QTreeWidgetItemIterator it (m_tree);\n\n  while (*it)\n    {\n      if ((*it)->text (0).contains (pattern, Qt::CaseInsensitive))\n        {\n          (*it)->setHidden (false);\n          (*it)->setExpanded (true);\n          QTreeWidgetItem *p = (*it)->parent ();\n          while (p)\n            {\n              p->setHidden (false);\n              p->setExpanded (true);\n              p = p->parent ();\n            }\n        }\n      else\n        (*it)->setHidden (true);\n\n      it++;\n    }\n}\n\nvoid\ndocumentation_bookmarks::filter_activate (bool state)\n{\n  m_filter->setEnabled (state);\n\n  QString pattern;\n  if (state)\n    pattern = m_filter->currentText ();\n\n  filter_bookmarks (pattern);\n}\n\nvoid\ndocumentation_bookmarks::update_filter_history ()\n{\n  combobox_insert_current_item (m_filter, QString ());\n}\n\nvoid\ndocumentation_bookmarks::handle_double_click (QTreeWidgetItem *item, int)\n{\n  int tag = item->data (0, tag_role).toInt ();\n\n  if (tag == folder_tag)\n    {\n      item->setExpanded (! item->isExpanded ());\n      return;\n    }\n\n  if (tag == bookmark_tag)\n    {\n      QUrl url = item->data (0, url_role).toUrl ();\n      if (! url.isEmpty ())\n        m_browser->setSource (url);\n      return;\n    }\n}\n\nvoid\ndocumentation_bookmarks::ctx_menu (const QPoint& xpos)\n{\n  QMenu menu (this);\n\n  m_ctx_menu_item = m_tree->itemAt (xpos);\n\n  if (m_ctx_menu_item)\n    {\n      gui_settings settings;\n\n      menu.addAction (tr (\"&Open\"), this, &documentation_bookmarks::open);\n      menu.addAction (tr (\"&Rename\"), this, &documentation_bookmarks::edit);\n      menu.addAction (settings.icon (\"window-close\"), tr (\"Remo&ve\"),\n                      this, &documentation_bookmarks::remove);\n      menu.addSeparator ();\n    }\n\n  menu.addAction (tr (\"&Add Folder\"), this,\n                  qOverload<bool> (&documentation_bookmarks::add_folder));\n\n  menu.addSeparator ();\n\n  if (m_filter_shown)\n    menu.addAction (tr (\"Hide &Filter\"),\n                    this, &documentation_bookmarks::show_filter);\n  else\n    menu.addAction (tr (\"Show &Filter\"),\n                    this, &documentation_bookmarks::show_filter);\n\n  menu.exec (m_tree->mapToGlobal (xpos));\n}\n\nvoid\ndocumentation_bookmarks::open (bool)\n{\n  QList<QTreeWidgetItem *> items = m_tree->selectedItems ();\n\n  if (items.size () > 0)\n    handle_double_click (items.at (0));\n}\n\nvoid\ndocumentation_bookmarks::edit (bool)\n{\n  QList<QTreeWidgetItem *> items = m_tree->selectedItems ();\n\n  if (items.size () > 0)\n    m_tree->editItem (items.at (0));\n}\n\nvoid\ndocumentation_bookmarks::remove (bool)\n{\n  QList<QTreeWidgetItem *> items = m_tree->selectedItems ();\n\n  for (const auto& it : items)\n    if (it)\n      m_tree->takeTopLevelItem (m_tree->indexOfTopLevelItem (it));\n}\n\nvoid\ndocumentation_bookmarks::show_filter (bool)\n{\n  m_filter_shown = ! m_filter_shown;\n  m_filter_widget->setVisible (m_filter_shown);\n}\n\nvoid\ndocumentation_bookmarks::save_settings ()\n{\n  // Write the bookmarks to the xbel-file\n  write_bookmarks ();\n\n  // Store settings\n  gui_settings settings;\n\n  settings.setValue (dc_bookmark_filter_active.settings_key (), m_filter_checkbox->isChecked ());\n  settings.setValue (dc_bookmark_filter_shown.settings_key (), m_filter_shown);\n\n  QStringList mru;\n  for (int i = 0; i < m_filter->count (); i++)\n    mru.append (m_filter->itemText (i));\n  settings.setValue (dc_bookmark_filter_mru.settings_key (), mru);\n\n  settings.sync ();\n}\n\nvoid\ndocumentation_bookmarks::write_bookmarks ()\n{\n  if (! m_xbel_file.open (QFile::WriteOnly | QFile::Text))\n    {\n      QMessageBox::warning (this, tr(\"Octave: Saving Documentation Bookmarks\"),\n                            tr(\"Unable to write file %1:\\n%2.\\n\\n\"\n                               \"Documentation bookmarks are not saved!\\n\")\n                            .arg (m_xbel_file.fileName ())\n                            .arg (m_xbel_file.errorString ()));\n      return;\n    }\n\n  QXmlStreamWriter xml_writer (&m_xbel_file);\n  xml_writer.setAutoFormatting (true);\n\n  xml_writer.writeStartDocument ();\n  xml_writer.writeDTD (dc_xbel_doctype);\n  xml_writer.writeStartElement (dc_xbel_name_format);\n  xml_writer.writeAttribute (dc_xbel_attr_version, dc_xbel_value_version);\n\n  for (int i = 0; i < m_tree->topLevelItemCount (); i++)\n    write_tree_item (&xml_writer, m_tree->topLevelItem (i));\n\n  xml_writer.writeEndDocument ();\n\n  m_xbel_file.flush ();\n  m_xbel_file.close ();\n}\n\nvoid\ndocumentation_bookmarks::write_tree_item (QXmlStreamWriter *xml_writer,\n    const QTreeWidgetItem *item)\n{\n  switch (item->data (0, tag_role).toInt ())\n    {\n    case folder_tag:\n      xml_writer->writeStartElement (dc_xbel_name_folder);\n      xml_writer->writeAttribute (dc_xbel_attr_folded,\n                                  item->isExpanded () ? dc_xbel_value_no : dc_xbel_value_yes);\n      xml_writer->writeTextElement (dc_xbel_name_title, item->text(0));\n      for (int i = 0; i < item->childCount (); i++)\n        write_tree_item (xml_writer, item->child (i));\n      xml_writer->writeEndElement ();\n      break;\n\n    case bookmark_tag:\n      xml_writer->writeStartElement (dc_xbel_name_bookmark);\n      xml_writer->writeAttribute (dc_xbel_attr_href, item->data (0, url_role).toString ());\n      xml_writer->writeTextElement (dc_xbel_name_title, item->text (0));\n      xml_writer->writeEndElement ();\n      break;\n    }\n}\n\nQString\ndocumentation_bookmarks::read_bookmarks ()\n{\n  QString error_message;\n\n  // Check the file\n  if (! m_xbel_file.open (QFile::ReadOnly | QFile::Text))\n    {\n      error_message = tr (\"Unable to read file %1:\\n%2.\")\n                      .arg (m_xbel_file.fileName ())\n                      .arg (m_xbel_file.errorString ());\n      return error_message;\n    }\n\n  QXmlStreamReader xml_reader (&m_xbel_file);\n\n  if (! xml_reader.readNextStartElement ())\n    {\n      error_message = tr (\"No start element found in %1.\\n\"\n                          \"Invalid bookmark file?\")\n                      .arg (m_xbel_file.fileName ());\n      return error_message;\n    }\n\n  if (xml_reader.name () != dc_xbel_name_format\n      || xml_reader.attributes ().value (dc_xbel_attr_version) != dc_xbel_value_version)\n    {\n      error_message = tr (\"The file\\n\"\n                          \"%1\\n\"\n                          \"is not a valid XBEL file version 1.0.\")\n                      .arg (m_xbel_file.fileName ());\n      return error_message;\n    }\n\n  // Read the elements from the file\n  while (xml_reader.readNextStartElement ())\n    {\n      if (xml_reader.name () == dc_xbel_name_folder)\n        read_next_item (&xml_reader, folder_tag);\n      else if (xml_reader.name () == dc_xbel_name_bookmark)\n        read_next_item (&xml_reader, bookmark_tag);\n      else\n        xml_reader.skipCurrentElement ();\n    }\n\n  m_xbel_file.close ();\n\n  return error_message;\n}\n\nvoid\ndocumentation_bookmarks::read_next_item (QXmlStreamReader *xml_reader,\n    item_tag tag, QTreeWidgetItem *item)\n{\n  QString title (tr (\"Unknown title\"));\n  if (tag == folder_tag)\n    {\n      // Next item is a folder, which might also have children\n      bool expanded = (xml_reader->attributes ().value (dc_xbel_attr_folded) == dc_xbel_value_no);\n\n      QTreeWidgetItem *new_folder = add_folder (title, item, expanded);\n\n      // Check elements of this folder for title and for recursively\n      // adding sub-items\n      while (xml_reader->readNextStartElement ())\n        {\n          if (xml_reader->name () == dc_xbel_name_title)\n            {\n              title = xml_reader->readElementText ();\n              new_folder->setText (0, title);\n            }\n          else if (xml_reader->name () == dc_xbel_name_folder)\n            read_next_item (xml_reader, folder_tag, new_folder);\n          else if (xml_reader->name () == dc_xbel_name_bookmark)\n            read_next_item (xml_reader, bookmark_tag, new_folder);\n          else\n            xml_reader->skipCurrentElement ();\n        }\n    }\n  else if (tag == bookmark_tag)\n    {\n      // Next item is a bookmark, without children\n      QString url = xml_reader->attributes ().value (dc_xbel_attr_href).toString ();\n      while (xml_reader->readNextStartElement ())\n        {\n          if (xml_reader->name () == dc_xbel_name_title)\n            title = xml_reader->readElementText ();\n          else\n            xml_reader->skipCurrentElement ();\n        }\n      add_bookmark (title, url, item);\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/documentation-bookmarks.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WiTHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_documentation_bookmarks_h)\n#define octave_documentation_bookmarks_h 1\n\n#include <QCheckBox>\n#include <QComboBox>\n#include <QFile>\n#include <QTreeWidget>\n#include <QXmlStreamWriter>\n\n#include \"documentation.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass documentation;\n\nclass documentation_bookmarks : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  documentation_bookmarks (documentation *doc,\n                           documentation_browser *browser,\n                           QWidget *p = nullptr);\n\n  ~documentation_bookmarks () = default;\n\npublic Q_SLOTS:\n\n  void add_bookmark ();\n  void add_folder (bool);\n  void save_settings ();\n\nprivate Q_SLOTS:\n\n  void filter_bookmarks (const QString& pattern);\n  void filter_activate (bool state);\n  void update_filter_history ();\n  void handle_double_click (QTreeWidgetItem *item, int col = 0);\n  void ctx_menu (const QPoint& xpos);\n  void open (bool);\n  void edit (bool);\n  void remove (bool);\n  void show_filter (bool);\n\nprivate:\n\n  enum item_role\n  {\n    url_role = Qt::UserRole,\n    tag_role = Qt::UserRole + 1\n  };\n  enum item_tag\n  {\n    bookmark_tag,\n    folder_tag\n  };\n\n  void add_bookmark (const QString& title, const QString& url,\n                     QTreeWidgetItem *item = nullptr);\n  QTreeWidgetItem * add_folder (const QString& folder,\n                                QTreeWidgetItem *item = nullptr,\n                                bool expanded = true);\n\n  /*!\n      Writing to and reading bookmarks from an xbel-file as\n      proposed in the qt example\n      [QXmlStream Bookmarks Example](https://doc.qt.io/qt-5/qtxml-streambookmarks-example.html)\n  */\n  void write_bookmarks ();\n  void write_tree_item (QXmlStreamWriter *xml_writer,\n                        const QTreeWidgetItem *item);\n  QString read_bookmarks ();\n  void read_next_item (QXmlStreamReader *xml_writer, item_tag tag,\n                       QTreeWidgetItem *item = nullptr);\n\n  documentation *m_doc;\n  documentation_browser *m_browser;\n\n  QComboBox *m_filter;\n  QTreeWidget *m_tree;\n\n  QTreeWidgetItem *m_ctx_menu_item;\n\n  QIcon m_icon_folder;\n  QIcon m_icon_bookmark;\n\n  QWidget *m_filter_widget;\n  QCheckBox *m_filter_checkbox;\n  bool m_filter_shown;\n\n  QFile m_xbel_file;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/documentation-dock-widget.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"documentation-dock-widget.h\"\n\n#include \"help.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ndocumentation_dock_widget::documentation_dock_widget (QWidget *p)\n  : octave_dock_widget (\"DocumentationDockWidget\", p),\n    m_docs (new documentation (this))\n{\n  set_title (tr (\"Documentation\"));\n  setStatusTip (tr (\"See the documentation for help.\"));\n\n  setWidget (m_docs);\n\n  if (! p)\n    make_window ();\n}\n\nvoid\ndocumentation_dock_widget::notice_settings ()\n{\n  m_docs->notice_settings ();\n}\n\nvoid\ndocumentation_dock_widget::save_settings ()\n{\n  m_docs->save_settings ();\n  octave_dock_widget::save_settings ();\n}\n\nvoid\ndocumentation_dock_widget::copyClipboard ()\n{\n  m_docs->copyClipboard ();\n}\n\nvoid\ndocumentation_dock_widget::pasteClipboard ()\n{\n  m_docs->pasteClipboard ();\n}\n\nvoid\ndocumentation_dock_widget::selectAll ()\n{\n  m_docs->selectAll ();\n}\n\nvoid\ndocumentation_dock_widget::showDoc (const QString& name)\n{\n  // show the doc pane without focus for carrying on typing in the console\n  if (! isVisible ())\n    setVisible (true);\n\n  raise ();\n\n  m_docs->load_ref (name);\n}\n\nvoid\ndocumentation_dock_widget::registerDoc (const QString& name)\n{\n  m_docs->registerDoc (name);\n}\n\nvoid\ndocumentation_dock_widget::unregisterDoc (const QString& name)\n{\n  m_docs->unregisterDoc (name);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/documentation-dock-widget.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_documentation_dock_widget_h)\n#define octave_documentation_dock_widget_h 1\n\n#include \"documentation.h\"\n#include \"octave-dock-widget.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass documentation_dock_widget : public octave_dock_widget\n{\n  Q_OBJECT\n\npublic:\n\n  documentation_dock_widget (QWidget *parent);\n\n  ~documentation_dock_widget () = default;\n\npublic Q_SLOTS:\n\n  void notice_settings ();\n  void save_settings ();\n\n  void copyClipboard ();\n  void pasteClipboard ();\n  void selectAll ();\n\n  void showDoc (const QString& name);\n  void registerDoc (const QString& name);\n  void unregisterDoc (const QString& name);\n\nprivate:\n\n  documentation *m_docs;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/documentation.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QAction>\n#include <QApplication>\n#include <QCompleter>\n#include <QDesktopServices>\n#include <QDir>\n#include <QFile>\n#include <QFileInfo>\n#include <QFontDatabase>\n#include <QHelpContentWidget>\n#include <QHelpIndexWidget>\n#if defined (HAVE_NEW_QHELPINDEXWIDGET_API) \\\n  || defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)\n#  include <QHelpLink>\n#endif\n#include <QHelpSearchEngine>\n#include <QHelpSearchQueryWidget>\n#include <QHelpSearchResultWidget>\n#include <QLabel>\n#include <QLineEdit>\n#include <QMessageBox>\n#include <QRegularExpression>\n#include <QTabWidget>\n#include <QTimer>\n#include <QWheelEvent>\n#include <QVBoxLayout>\n#include <QWheelEvent>\n\n#include \"documentation.h\"\n#include \"documentation-bookmarks.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-dc.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-settings.h\"\n#include \"gui-utils.h\"\n\n#include \"defaults.h\"\n#include \"file-ops.h\"\n#include \"oct-env.h\"\n#include \"oct-sysdep.h\"\n#include \"octave-qt-features.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// The documentation splitter, which is the main widget\n// of the doc dock widget\ndocumentation::documentation (QWidget *p)\n  : QSplitter (Qt::Horizontal, p),\n    m_doc_widget (this),\n    m_tool_bar (new QToolBar (this)),\n    m_query_string (QString ()),\n    m_indexed (false),\n    m_current_ref_name (QString ()),\n    m_prev_pages_menu (new QMenu (this)),\n    m_next_pages_menu (new QMenu (this)),\n    m_prev_pages_count (0),\n    m_next_pages_count (0)\n{\n  // Get original collection\n  QString collection = getenv (\"OCTAVE_QTHELP_COLLECTION\");\n  if (collection.isEmpty ())\n    collection = QString::fromStdString (config::oct_doc_dir ()\n                                         + sys::file_ops::dir_sep_str ()\n                                         + \"octave_interpreter.qhc\");\n\n  // Setup the help engine with the original collection, use a writable copy\n  // of the original collection and load the help data\n  m_help_engine = new QHelpEngine (collection, this);\n\n  // Mark help as readonly to avoid error if collection file is stored in a\n  // readonly location\n#if defined (HAVE_QHELPENGINE_SETREADONLY)\n  m_help_engine->setReadOnly (true);\n#else\n  m_help_engine->setProperty (\"_q_readonly\",\n                              QVariant::fromValue<bool> (true));\n#endif\n\n  QString tmpdir = QString::fromStdString (sys::env::get_temp_directory ());\n  m_collection\n    = QString::fromStdString (sys::tempnam (tmpdir.toStdString (),\n                                            \"oct-qhelp-\"));\n\n  bool copy_ok = false;\n#if defined (HAVE_QHELPENGINE_COPYCOLLECTIONFILE_TRUNCATION_BUG)\n  // FIXME: Qt6: copyCollectionFile truncates the collection file.\n  // This workaround normally copies the file.  Since the relative\n  // link to the qch file is not updated then, the namespace and\n  // the original qch file are re-registered.\n  QStringList namespaces = m_help_engine->registeredDocumentations ();\n  QString qch_file;\n  if (! namespaces.isEmpty ())\n    qch_file = m_help_engine->documentationFileName (namespaces.at (0));\n  QFile collection_file (collection);\n  copy_ok = collection_file.copy (m_collection);\n#else\n  // Qt5: use copyCollectionFile\n  copy_ok = m_help_engine->copyCollectionFile (m_collection);\n#endif\n\n  if (copy_ok)\n    m_help_engine->setCollectionFile (m_collection);\n  else\n#if defined (ENABLE_DOCS)\n    // FIXME: Perhaps a better way to do this would be to keep a count\n    // in the GUI preferences file.  After issuing this warning 3 times\n    // it would be disabled.  The count would need to be reset when a new\n    // version of Octave is installed.\n    QMessageBox::warning (this, tr (\"Octave Documentation\"),\n                          tr (\"Could not copy help collection to temporary\\n\"\n                              \"file. Search capabilities may be affected.\\n\"\n                              \"%1\").arg (m_help_engine->error ()));\n#endif\n\n  connect(m_help_engine->searchEngine (), SIGNAL(indexingFinished ()),\n          this, SLOT(load_index ()));\n  connect(m_help_engine, SIGNAL(setupFinished ()),\n          m_help_engine->searchEngine (), SLOT(reindexDocumentation ()));\n\n  if (! m_help_engine->setupData ())\n    {\n#if defined (ENABLE_DOCS)\n      QMessageBox::warning (this, tr (\"Octave Documentation\"),\n                            tr (\"Could not setup the data required for the\\n\"\n                                \"documentation viewer. Maybe the Qt SQlite\\n\"\n                                \"module is missing?\\n\"\n                                \"Only help text in the Command Window will\\n\"\n                                \"be available.\"));\n#endif\n      disconnect (m_help_engine, 0, 0, 0);\n\n      delete m_help_engine;\n      m_help_engine = nullptr;\n    }\n  else\n    {\n#if defined (HAVE_QHELPENGINE_COPYCOLLECTIONFILE_TRUNCATION_BUG)\n      // Un- and re-register qch-file because copyCollectionFile with\n      // automatic path update was not used.\n      if (! namespaces.isEmpty ())\n        m_help_engine->unregisterDocumentation (namespaces.at (0));\n      m_help_engine->registerDocumentation (qch_file);\n#endif\n    }\n\n  // The browser\n  QWidget *browser_find = new QWidget (this);\n  m_doc_browser = new documentation_browser (m_help_engine, browser_find);\n  connect (m_doc_browser, &documentation_browser::cursorPositionChanged,\n           this, &documentation::handle_cursor_position_change);\n\n  // Find bar\n  m_find_widget = new find_widget (true, this);\n  connect (m_find_widget, &find_widget::find_signal,\n           this, &documentation::find);\n  connect (m_find_widget, &find_widget::find_incremental_signal,\n           this, &documentation::find_forward_from_anchor);\n\n  QVBoxLayout *v_box_browser_find = new QVBoxLayout (browser_find);\n  v_box_browser_find->addWidget (m_tool_bar);\n  v_box_browser_find->addWidget (m_doc_browser);\n  v_box_browser_find->addWidget (m_find_widget);\n  browser_find->setLayout (v_box_browser_find);\n\n  m_find_widget->hide ();\n  m_search_anchor_position = 0;\n\n  // Tool bar\n  construct_tool_bar ();\n\n  notice_settings ();\n\n  if (m_help_engine)\n    {\n#if defined (HAVE_NEW_QHELPINDEXWIDGET_API)\n      // Starting in Qt 5.15, help engine uses filters instead of old API\n      m_help_engine->setUsesFilterEngine (true);\n#endif\n      // Layout contents, index and search\n      QTabWidget *navi = new QTabWidget (this);\n      navi->setTabsClosable (false);\n      navi->setMovable (true);\n\n      // Contents\n      QHelpContentWidget *content = m_help_engine->contentWidget ();\n      content->setObjectName (\"documentation_tab_contents\");\n      navi->addTab (content, tr (\"Contents\"));\n\n      connect (m_help_engine->contentWidget (),\n               &QHelpContentWidget::linkActivated,\n               m_doc_browser, [this] (const QUrl& url) { m_doc_browser->handle_index_clicked (url); });\n\n      // Index\n      QHelpIndexWidget *index = m_help_engine->indexWidget ();\n\n      m_filter = new QComboBox (this);\n      m_filter->setToolTip (tr (\"Enter text to search function index\"));\n      m_filter->setEditable (true);\n      m_filter->setInsertPolicy (QComboBox::NoInsert);\n      m_filter->setMaxCount (10);\n      m_filter->setMaxVisibleItems (10);\n      m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);\n      QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);\n      m_filter->setSizePolicy (sizePol);\n      m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);\n      QLabel *filter_label = new QLabel (tr (\"Search\"));\n\n      QWidget *filter_all = new QWidget (navi);\n      QHBoxLayout *h_box_index = new QHBoxLayout (filter_all);\n      h_box_index->addWidget (filter_label);\n      h_box_index->addWidget (m_filter);\n      h_box_index->setContentsMargins (2, 2, 2, 2);\n      filter_all->setLayout (h_box_index);\n\n      QWidget *index_all = new QWidget (navi);\n      index_all->setObjectName (\"documentation_tab_index\");\n      QVBoxLayout *v_box_index = new QVBoxLayout (index_all);\n      v_box_index->addWidget (filter_all);\n      v_box_index->addWidget (index);\n      index_all->setLayout (v_box_index);\n\n      navi->addTab (index_all, tr (\"Function Index\"));\n\n#if defined (HAVE_NEW_QHELPINDEXWIDGET_API)\n      connect (m_help_engine->indexWidget (),\n               &QHelpIndexWidget::documentActivated,\n               this, [this] (const QHelpLink &link) { m_doc_browser->handle_index_clicked (link.url); });\n#else\n      connect (m_help_engine->indexWidget (),\n               &QHelpIndexWidget::linkActivated,\n               m_doc_browser, &documentation_browser::handle_index_clicked);\n#endif\n\n      connect (m_filter, &QComboBox::editTextChanged,\n               this, &documentation::filter_update);\n\n      connect (m_filter->lineEdit (), &QLineEdit::editingFinished,\n               this, &documentation::filter_update_history);\n\n      // Bookmarks (own class)\n      m_bookmarks = new documentation_bookmarks (this, m_doc_browser, navi);\n      navi->addTab (m_bookmarks, tr (\"Bookmarks\"));\n\n      connect (m_action_bookmark, &QAction::triggered,\n               m_bookmarks, [this] () { m_bookmarks->add_bookmark (); });\n\n      // Search\n      QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();\n      QHelpSearchQueryWidget *search = search_engine->queryWidget ();\n      QHelpSearchResultWidget *result = search_engine->resultWidget ();\n      QWidget *search_all = new QWidget (navi);\n      QVBoxLayout *v_box_search = new QVBoxLayout (search_all);\n      v_box_search->addWidget (search);\n      v_box_search->addWidget (result);\n      search_all->setLayout (v_box_search);\n      search_all->setObjectName (\"documentation_tab_search\");\n      navi->addTab (search_all, tr (\"Search\"));\n\n      connect (search, &QHelpSearchQueryWidget::search,\n               this, &documentation::global_search);\n\n      connect (search_engine, &QHelpSearchEngine::searchingStarted,\n               this, &documentation::global_search_started);\n      connect (search_engine, &QHelpSearchEngine::searchingFinished,\n               this, &documentation::global_search_finished);\n\n      connect (search_engine->resultWidget (),\n               &QHelpSearchResultWidget::requestShowLink,\n               this, &documentation::handle_search_result_clicked);\n\n      // Fill the splitter\n      insertWidget (0, navi);\n      insertWidget (1, browser_find);\n      setStretchFactor (1, 1);\n\n      gui_settings settings;\n      restoreState (settings.byte_array_value (dc_splitter_state));\n    }\n}\n\ndocumentation::~documentation ()\n{\n  // Cleanup temporary file and directory\n  QFile file (m_collection);\n  if (file.exists ())\n    {\n      QFileInfo finfo (file);\n      QString bname = finfo.fileName ();\n      QDir dir = finfo.absoluteDir ();\n      dir.setFilter (QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden);\n      QStringList namefilter;\n      namefilter.append (\"*\" + bname + \"*\");\n      for (const auto& fi : dir.entryInfoList (namefilter))\n        {\n          std::string file_name = fi.absoluteFilePath ().toStdString ();\n          sys::recursive_rmdir (file_name);\n        }\n\n      file.remove ();\n    }\n}\n\nQAction *\ndocumentation::add_action (const QIcon& icon, const QString& text,\n                           const char *member, QWidget *receiver,\n                           QToolBar *tool_bar)\n{\n  QAction *a;\n  QWidget *r = this;\n  if (receiver != nullptr)\n    r = receiver;\n\n  a = new QAction (icon, text, this);\n\n  if (member)\n    connect (a, SIGNAL (triggered ()), r, member);\n\n  if (tool_bar)\n    tool_bar->addAction (a);\n\n  m_doc_widget->addAction (a);  // important for shortcut context\n  a->setShortcutContext (Qt::WidgetWithChildrenShortcut);\n\n  return a;\n}\n\nvoid\ndocumentation::construct_tool_bar ()\n{\n  // Home, Previous, Next\n  gui_settings settings;\n\n  m_action_go_home\n    = add_action (settings.icon (\"go-home\"), tr (\"Go home\"), SLOT (home ()),\n                  m_doc_browser, m_tool_bar);\n\n  m_action_go_prev\n    = add_action (settings.icon (\"go-previous\"), tr (\"Go back\"),\n                  SLOT (backward ()), m_doc_browser, m_tool_bar);\n  m_action_go_prev->setEnabled (false);\n\n  // popdown menu with prev pages files\n  QToolButton *popdown_button_prev_pages = new QToolButton ();\n  popdown_button_prev_pages->setToolTip (tr (\"Previous pages\"));\n  popdown_button_prev_pages->setMenu (m_prev_pages_menu);\n  popdown_button_prev_pages->setPopupMode (QToolButton::InstantPopup);\n  popdown_button_prev_pages->setToolButtonStyle (Qt::ToolButtonTextOnly);\n  popdown_button_prev_pages->setCheckable (false);\n  popdown_button_prev_pages->setArrowType (Qt::DownArrow);\n  m_tool_bar->addWidget (popdown_button_prev_pages);\n\n  m_action_go_next\n    = add_action (settings.icon (\"go-next\"), tr (\"Go forward\"),\n                  SLOT (forward ()), m_doc_browser, m_tool_bar);\n  m_action_go_next->setEnabled (false);\n\n  // popdown menu with prev pages files\n  QToolButton *popdown_button_next_pages = new QToolButton ();\n  popdown_button_next_pages->setToolTip (tr (\"Next pages\"));\n  popdown_button_next_pages->setMenu (m_next_pages_menu);\n  popdown_button_next_pages->setPopupMode (QToolButton::InstantPopup);\n  popdown_button_next_pages->setToolButtonStyle (Qt::ToolButtonTextOnly);\n  popdown_button_next_pages->setArrowType (Qt::DownArrow);\n  m_tool_bar->addWidget (popdown_button_next_pages);\n\n  connect (m_doc_browser, &documentation_browser::backwardAvailable,\n           m_action_go_prev, &QAction::setEnabled);\n  connect (m_doc_browser, &documentation_browser::backwardAvailable,\n           popdown_button_prev_pages, &QToolButton::setEnabled);\n  connect (m_doc_browser, &documentation_browser::forwardAvailable,\n           m_action_go_next, &QAction::setEnabled);\n  connect (m_doc_browser, &documentation_browser::forwardAvailable,\n           popdown_button_next_pages, &QToolButton::setEnabled);\n  connect (m_doc_browser, &documentation_browser::historyChanged,\n           this, &documentation::update_history_menus);\n\n  // Init prev/next menus\n  for (int i = 0; i < max_history_entries; ++i)\n    {\n      m_prev_pages_actions[i] = new QAction (this);\n      m_prev_pages_actions[i]->setVisible (false);\n      m_next_pages_actions[i] = new QAction (this);\n      m_next_pages_actions[i]->setVisible (false);\n      m_prev_pages_menu->addAction (m_prev_pages_actions[i]);\n      m_next_pages_menu->addAction (m_next_pages_actions[i]);\n    }\n\n  connect (m_prev_pages_menu, &QMenu::triggered,\n           this, &documentation::open_hist_url);\n  connect (m_next_pages_menu, &QMenu::triggered,\n           this, &documentation::open_hist_url);\n\n  // Find\n  m_tool_bar->addSeparator ();\n  m_action_find\n    = add_action (settings.icon (\"edit-find\"), tr (\"Find\"),\n                  SLOT (activate_find ()), m_find_widget, m_tool_bar);\n\n  // Zoom\n  m_tool_bar->addSeparator ();\n  m_action_zoom_in\n    = add_action (settings.icon (\"view-zoom-in\"), tr (\"Zoom In\"),\n                  SLOT (zoom_in ()), m_doc_browser, m_tool_bar);\n  m_action_zoom_out\n    = add_action (settings.icon (\"view-zoom-out\"), tr (\"Zoom Out\"),\n                  SLOT (zoom_out ()), m_doc_browser, m_tool_bar);\n  m_action_zoom_original\n    = add_action (settings.icon (\"view-zoom-original\"), tr (\"Zoom Original\"),\n                  SLOT (zoom_original ()), m_doc_browser, m_tool_bar);\n\n  // Bookmarks (connect slots later)\n  m_tool_bar->addSeparator ();\n  m_action_bookmark\n    = add_action (settings.icon (\"bookmark-new\"),\n                  tr (\"Bookmark current page\"), nullptr, nullptr, m_tool_bar);\n}\n\nvoid\ndocumentation::global_search ()\n{\n  if (! m_help_engine)\n    return;\n\n  QString query_string;\n#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)\n  QString queries\n    = m_help_engine->searchEngine ()->queryWidget ()->searchInput ();\n  query_string = queries;\n#else\n  // FIXME: drop this part when support for Qt4 is dropped\n  QList<QHelpSearchQuery> queries\n    = m_help_engine->searchEngine ()->queryWidget ()->query ();\n  if (queries.count ())\n    query_string = queries.first ().wordList.join (\" \");\n  else\n    query_string = \"\";\n#endif\n\n  if (query_string.isEmpty ())\n    return;\n\n  // Get quoted search strings first, then take first string as fall back\n  QRegularExpression rx {\"\\\"([^\\\"]*)\\\"\"};\n  QRegularExpressionMatch match = rx.match (query_string);\n  if (match.hasMatch ())\n    m_internal_search = match.captured (1);\n  else\n    {\n      QStringList tmp;\n#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)\n      tmp = query_string.split (\" \", Qt::SkipEmptyParts);\n#else\n      tmp = query_string.split (\" \", QString::SkipEmptyParts);\n#endif\n      if (tmp.isEmpty ())\n        return;\n      m_internal_search = tmp.first ();\n    }\n\n  m_help_engine->searchEngine ()->search (queries);\n}\n\nvoid\ndocumentation::global_search_started ()\n{\n  qApp->setOverrideCursor (QCursor (Qt::WaitCursor));\n}\n\nvoid\ndocumentation::global_search_finished (int)\n{\n  if (! m_help_engine)\n    return;\n\n  if (! m_internal_search.isEmpty ())\n    {\n      m_query_string = m_internal_search;\n\n      QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();\n      if (search_engine)\n        {\n#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)\n          QVector<QHelpSearchResult> res\n            = search_engine->searchResults (0, search_engine->searchResultCount ());\n#else\n          QList< QPair<QString, QString> > res\n            = search_engine->hits (0, search_engine->hitCount ());\n#endif\n\n          if (res.count ())\n            {\n              QUrl url;\n\n              if (res.count () == 1)\n#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)\n                url = res.front ().url ();\n#else\n                url = res.front ().first;\n#endif\n              else\n                {\n                  // Remove the quotes we added\n                  QString search_string = m_internal_search;\n\n                  for (const auto& r : res)\n                    {\n#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)\n                      QString title = r.title ().toLower ();\n                      QUrl tmpurl = r.url ();\n#else\n                      QString title = r.second.toLower ();\n                      QUrl tmpurl = r.first;\n#endif\n                      if (title.contains (search_string.toLower ()))\n                        {\n                          if (title.indexOf (search_string.toLower ()) == 0)\n                            {\n                              url = tmpurl;\n                              break;\n                            }\n                          else if (url.isEmpty ())\n                            url = tmpurl;\n                        }\n                    }\n                }\n\n              if (! url.isEmpty ())\n                {\n                  connect (this, &documentation::show_single_result,\n                           this, &documentation::handle_search_result_clicked);\n\n                  Q_EMIT show_single_result (url);\n                }\n            }\n        }\n\n      m_internal_search = QString ();\n    }\n\n  qApp->restoreOverrideCursor ();\n}\n\nvoid\ndocumentation::handle_search_result_clicked (const QUrl& url)\n{\n  // Open url with matching text\n  m_doc_browser->handle_index_clicked (url);\n\n  // Select all occurrences of matching text\n  select_all_occurrences (m_query_string);\n\n  // Open search widget with matching text as search string\n  m_find_widget->set_text (m_query_string);\n  m_find_widget->show ();\n\n  // If no occurrence can be found go to the top of the page\n  if (! m_doc_browser->find (m_find_widget->text ()))\n    m_doc_browser->moveCursor (QTextCursor::Start);\n  else\n    {\n      // Go to first occurrence of search text.  Going to the end and then\n      // search backwards until the last occurrence ensures the search text\n      // is visible in the first line of the visible part of the text.\n      m_doc_browser->moveCursor (QTextCursor::End);\n      while (m_doc_browser->find (m_find_widget->text (),\n                                  QTextDocument::FindBackward));\n    }\n}\n\nvoid\ndocumentation::select_all_occurrences (const QString& text)\n{\n  // Get highlight background and text color\n  QPalette pal = QApplication::palette ();\n  QTextCharFormat format;\n  QColor col = pal.color (QPalette::Highlight);\n  col.setAlphaF (0.25);\n  format.setBackground (QBrush (col));\n  format.setForeground (QBrush (pal.color (QPalette::Text)));\n\n  // Create list for extra selected items\n  QList<QTextEdit::ExtraSelection> selected;\n  m_doc_browser->moveCursor (QTextCursor::Start);\n\n  // Find all occurrences and add them to the selection\n  while ( m_doc_browser->find (text) )\n    {\n      QTextEdit::ExtraSelection selected_item;\n      selected_item.cursor = m_doc_browser->textCursor ();\n      selected_item.format = format;\n      selected.append (selected_item);\n    }\n\n  // Apply selection and move back to the beginning\n  m_doc_browser->setExtraSelections (selected);\n  m_doc_browser->moveCursor (QTextCursor::Start);\n}\n\nvoid\ndocumentation::notice_settings ()\n{\n  gui_settings settings;\n\n  // If m_help_engine is not defined, the objects accessed by this method\n  // are not valid.  Thus, just return in this case.\n  if (! m_help_engine)\n    return;\n\n  // Icon size in the toolbar.\n  int size_idx = settings.int_value (global_icon_size);\n  size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2\n\n  QStyle *st = style ();\n  int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);\n  m_tool_bar->setIconSize (QSize (icon_size, icon_size));\n\n  // Shortcuts\n  settings.set_shortcut (m_action_find, sc_edit_edit_find_replace);\n  settings.set_shortcut (m_action_zoom_in, sc_edit_view_zoom_in);\n  settings.set_shortcut (m_action_zoom_out, sc_edit_view_zoom_out);\n  settings.set_shortcut (m_action_zoom_original, sc_edit_view_zoom_normal);\n  settings.set_shortcut (m_action_go_home, sc_doc_go_home);\n  settings.set_shortcut (m_action_go_prev, sc_doc_go_back);\n  settings.set_shortcut (m_action_go_next, sc_doc_go_next);\n  settings.set_shortcut (m_action_bookmark, sc_doc_bookmark);\n\n  // Settings for the browser\n  m_doc_browser->notice_settings ();\n  m_find_widget->notice_settings ();\n}\n\nvoid\ndocumentation::save_settings ()\n{\n  gui_settings settings;\n\n  settings.setValue (dc_splitter_state.settings_key (), saveState ());\n  m_doc_browser->save_settings ();\n  m_bookmarks->save_settings ();\n  m_find_widget->save_settings ();\n}\n\nvoid\ndocumentation::copyClipboard ()\n{\n  if (m_doc_browser->hasFocus ())\n    {\n      m_doc_browser->copy ();\n    }\n}\n\nvoid\ndocumentation::pasteClipboard () { }\n\nvoid\ndocumentation::selectAll () { }\n\nvoid\ndocumentation::load_index ()\n{\n  m_indexed = true;\n\n  // Show index if no other page is required.\n  if (m_current_ref_name.isEmpty ())\n    m_doc_browser->setSource\n      (QUrl (\"qthelp://org.octave.interpreter-1.0/doc/octave.qdoc.html/index.html\"));\n  else\n    load_ref (m_current_ref_name);\n\n  m_help_engine->contentWidget ()->expandToDepth (0);\n}\n\nvoid\ndocumentation::load_ref (const QString& ref_name)\n{\n  if (! m_help_engine || ref_name.isEmpty ())\n    return;\n\n  m_current_ref_name = ref_name;\n\n  if (! m_indexed)\n    return;\n\n#if defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)\n  QList<QHelpLink> found_links\n    = m_help_engine->documentsForIdentifier (ref_name);\n  // Depending on how the qch-file was generated, searching for an Id\n  // might not be successful and the full text search would be started\n  // next.  In order to still find an exisiting index entry, try searching\n  // for the keyword as well.\n  if (found_links.count () == 0)\n    found_links = m_help_engine->documentsForKeyword (ref_name);\n#else\n  QMap<QString, QUrl> found_links\n    = m_help_engine->linksForIdentifier (ref_name);\n#endif\n\n  QTabWidget *navi = static_cast<QTabWidget *> (widget (0));\n\n  if (found_links.count () > 0)\n    {\n      // First search in the function index\n#if defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)\n      QUrl first_url = found_links.constFirst ().url;\n#else\n      QUrl first_url = found_links.constBegin ().value ();\n#endif\n\n      m_doc_browser->setSource (first_url);\n\n      // Switch to function index tab\n      m_help_engine->indexWidget ()->filterIndices (ref_name);\n      QWidget *index_tab\n        = navi->findChild<QWidget *> (\"documentation_tab_index\");\n      navi->setCurrentWidget (index_tab);\n    }\n  else\n    {\n      // Use full text search to provide the best match\n      QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();\n      QHelpSearchQueryWidget *search_query = search_engine->queryWidget ();\n\n#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)\n      QString query = ref_name;\n      query.prepend (\"\\\"\").append (\"\\\"\");\n#else\n      QList<QHelpSearchQuery> query;\n      query << QHelpSearchQuery (QHelpSearchQuery::DEFAULT,\n                                 QStringList (QString (\"\\\"\") + ref_name + QString (\"\\\"\")));\n#endif\n      m_internal_search = ref_name;\n      search_engine->search (query);\n\n      // Switch to search tab\n#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)\n      search_query->setSearchInput (query);\n#else\n      search_query->setQuery (query);\n#endif\n      QWidget *search_tab\n        = navi->findChild<QWidget *> (\"documentation_tab_search\");\n      navi->setCurrentWidget (search_tab);\n    }\n}\n\nvoid\ndocumentation::filter_update (const QString& expression)\n{\n  if (! m_help_engine)\n    return;\n\n  QString search_term = expression.trimmed ();\n\n  QString wildcard;\n  if (expression.contains (QLatin1Char ('*')))\n    wildcard = expression;\n\n  m_help_engine->indexWidget ()->filterIndices (search_term, wildcard);\n}\n\nvoid\ndocumentation::filter_update_history ()\n{\n  combobox_insert_current_item (m_filter, QString ());\n}\n\nvoid\ndocumentation::find (const QString& text, bool backward)\n{\n  if (! m_help_engine)\n    return;\n\n  QTextDocument::FindFlags flags;\n    if (backward)\n      flags = QTextDocument::FindBackward;\n\n  if (! m_doc_browser->find (text, flags))\n    {\n      // Nothing was found, restart search from the begin or end of text\n      QTextCursor textcur = m_doc_browser->textCursor ();\n      if (backward)\n        textcur.movePosition (QTextCursor::End);\n      else\n        textcur.movePosition (QTextCursor::Start);\n      m_doc_browser->setTextCursor (textcur);\n      m_doc_browser->find (text, flags);\n    }\n\n  record_anchor_position ();\n}\n\nvoid\ndocumentation::find_forward_from_anchor (const QString& text)\n{\n  if (! m_help_engine)\n    return;\n\n  // Search from the current position\n  QTextCursor textcur = m_doc_browser->textCursor ();\n  textcur.setPosition (m_search_anchor_position);\n  m_doc_browser->setTextCursor (textcur);\n\n  if (! m_doc_browser->find (text))\n    {\n      // Nothing was found, restart search from the beginning\n      textcur.movePosition (QTextCursor::Start);\n      m_doc_browser->setTextCursor (textcur);\n      m_doc_browser->find (text);\n    }\n}\n\nvoid\ndocumentation::record_anchor_position ()\n{\n  if (! m_help_engine)\n    return;\n\n  m_search_anchor_position = m_doc_browser->textCursor ().position ();\n}\n\nvoid\ndocumentation::handle_cursor_position_change ()\n{\n  if (! m_help_engine)\n    return;\n\n  if (m_doc_browser->hasFocus ())\n    record_anchor_position ();\n}\n\nvoid\ndocumentation::registerDoc (const QString& qch)\n{\n  if (m_help_engine)\n    {\n      QString ns = m_help_engine->namespaceName (qch);\n      bool do_setup = true;\n      if (m_help_engine->registeredDocumentations ().contains (ns))\n        {\n          if (m_help_engine->documentationFileName (ns) == qch)\n            do_setup = false;\n          else\n            {\n              m_help_engine->unregisterDocumentation (ns);\n              m_help_engine->registerDocumentation (qch);\n            }\n        }\n      else if (! m_help_engine->registerDocumentation (qch))\n        {\n          QMessageBox::warning (this, tr (\"Octave Documentation\"),\n                                tr (\"Unable to register help file %1.\").\n                                arg (qch));\n          return;\n        }\n\n      if (do_setup)\n        m_help_engine->setupData ();\n    }\n}\n\nvoid\ndocumentation::unregisterDoc (const QString& qch)\n{\n  if (! m_help_engine)\n    return;\n\n  QString ns = m_help_engine->namespaceName (qch);\n  if (m_help_engine->registeredDocumentations ().contains (ns))\n    {\n      std::string ns_file = m_help_engine->documentationFileName (ns).toStdString ();\n      if (sys::same_file (ns_file, qch.toStdString ()))\n        {\n          m_help_engine->unregisterDocumentation (ns);\n          m_help_engine->setupData ();\n        }\n    }\n}\n\nvoid\ndocumentation::update_history_menus ()\n{\n  if (m_prev_pages_count != m_doc_browser->backwardHistoryCount ())\n    {\n      update_history (m_doc_browser->backwardHistoryCount (),\n                      m_prev_pages_actions);\n      m_prev_pages_count = m_doc_browser->backwardHistoryCount ();\n    }\n\n  if (m_next_pages_count != m_doc_browser->forwardHistoryCount ())\n    {\n      update_history (m_doc_browser->forwardHistoryCount (),\n                      m_next_pages_actions);\n      m_next_pages_count = m_doc_browser->forwardHistoryCount ();\n    }\n}\n\nvoid\ndocumentation::update_history (int new_count, QAction **actions)\n{\n  // Which menu has to be updated?\n  int prev_next = -1;\n  QAction *a = m_action_go_prev;\n  if (actions == m_next_pages_actions)\n    {\n      prev_next = 1;\n      a = m_action_go_next;\n    }\n\n  // Get maximal count limited by array size\n  int count = qMin (new_count, int (max_history_entries));\n\n  // Fill used menu entries\n  for (int i = 0; i < count; i++)\n    {\n      QString title\n        = title_and_anchor (m_doc_browser->historyTitle (prev_next*(i+1)),\n                            m_doc_browser->historyUrl (prev_next*(i+1)));\n\n      if (i == 0)\n        a->setText (title); // set tool tip for prev/next buttons\n\n      actions[i]->setText (title);\n      actions[i]->setData (m_doc_browser->historyUrl (prev_next*(i+1)));\n      actions[i]->setEnabled (true);\n      actions[i]->setVisible (true);\n    }\n\n  // Hide unused menu entries\n  for (int j = count; j < max_history_entries; j++)\n    {\n      actions[j]->setEnabled (false);\n      actions[j]->setVisible (false);\n    }\n}\n\nvoid\ndocumentation::open_hist_url (QAction *a)\n{\n  m_doc_browser->setSource (a->data ().toUrl ());\n}\n\n// Utility functions\n\nQString\ndocumentation::title_and_anchor (const QString& title, const QUrl& url)\n{\n  QString retval = title;\n  QString u = url.toString ();\n\n  retval.remove (QRegularExpression {\"\\\\s*\\\\(*GNU Octave \\\\(version [^\\\\)]*\\\\)[: \\\\)]*\"});\n\n  // Since the title only contains the section name and not the\n  // specific anchor, extract the latter from the url and append\n  // it to the title\n  if (u.contains ('#'))\n    {\n      // Get the anchor from the url\n      QString anchor = u.split ('#').last ();\n      // Remove internal string parts\n      anchor.remove (QRegularExpression {\"^index-\"});\n      anchor.remove (QRegularExpression {\"^SEC_\"});\n      anchor.remove (QRegularExpression {\"^XREF\"});\n      anchor.remove (\"Concept-Index_cp_letter-\");\n      anchor.replace (\"-\", \" \");\n\n      // replace encoded special chars by their unencoded versions\n      QRegularExpression rx {\"_00([0-7][0-9a-f])\"};\n      QRegularExpressionMatch match = rx.match (anchor, 0);\n      int pos = 0;\n      while (match.hasMatch ())\n        {\n          anchor.replace (\"_00\" + match.captured (1),\n                          QChar (match.captured (1).toInt (nullptr, 16)));\n          pos += match.capturedLength ();\n          match = rx.match (anchor, pos);\n        }\n\n      if (retval != anchor)\n        retval = retval + \": \" + anchor;\n    }\n\n  return retval;\n}\n\n//\n// The documentation browser\n//\n\ndocumentation_browser::documentation_browser (QHelpEngine *he, QWidget *p)\n  : QTextBrowser (p), m_help_engine (he), m_zoom_level (max_zoom_level+1)\n{\n  setOpenLinks (false);\n  connect (this, &documentation_browser::anchorClicked,\n           this, [this] (const QUrl& url) { handle_index_clicked (url); });\n\n  // Make sure we have access to one of the monospace fonts listed in\n  // octave.css for rendering formated code blocks\n  QStringList fonts = {\"Fantasque Sans Mono\", \"FreeMono\", \"Courier New\",\n                       \"Cousine\", \"Courier\"\n                      };\n\n  bool load_default_font = true;\n\n  for (int i = 0; i < fonts.size (); ++i)\n    {\n      QFont font (fonts.at (i));\n      if (font.exactMatch ())\n        {\n          load_default_font = false;\n          break;\n        }\n    }\n\n  if (load_default_font)\n    {\n      QString fonts_dir =\n        QString::fromStdString (sys::env::getenv (\"OCTAVE_FONTS_DIR\")\n                                + sys::file_ops::dir_sep_str ());\n\n      QStringList default_fonts = {\"FreeMono\", \"FreeMonoBold\",\n                                   \"FreeMonoBoldOblique\", \"FreeMonoOblique\"\n                                  };\n\n      for (int i = 0; i < default_fonts.size (); ++i)\n        {\n          QString fontpath =\n            fonts_dir + default_fonts.at (i) + QString (\".otf\");\n          QFontDatabase::addApplicationFont (fontpath);\n        }\n    }\n}\n\nvoid\ndocumentation_browser::handle_index_clicked (const QUrl& url, const QString&)\n{\n  if (url.scheme () == \"qthelp\")\n    setSource (QUrl (url));\n  else\n    QDesktopServices::openUrl (url);\n}\n\nvoid\ndocumentation_browser::notice_settings ()\n{\n  gui_settings settings;\n\n  // Zoom level only at startup, not when other settings have changed\n  if (m_zoom_level > max_zoom_level)\n    {\n      m_zoom_level = settings.int_value (dc_browser_zoom_level);\n      zoomIn (m_zoom_level);\n    }\n}\n\nQVariant\ndocumentation_browser::loadResource (int type, const QUrl& url)\n{\n  if (m_help_engine && url.scheme () == \"qthelp\")\n    return QVariant (m_help_engine->fileData (url));\n  else\n    return QTextBrowser::loadResource (type, url);\n}\n\nvoid\ndocumentation_browser::save_settings ()\n{\n  gui_settings settings;\n\n  settings.setValue (dc_browser_zoom_level.settings_key (), m_zoom_level);\n\n  settings.sync ();\n}\n\nvoid\ndocumentation_browser::zoom_in ()\n{\n  if (m_zoom_level < max_zoom_level)\n    {\n      zoomIn ();\n      m_zoom_level++;\n    }\n}\n\nvoid\ndocumentation_browser::zoom_out ()\n{\n  if (m_zoom_level > min_zoom_level)\n    {\n      zoomOut ();\n      m_zoom_level--;\n    }\n}\n\nvoid\ndocumentation_browser::zoom_original ()\n{\n  zoomIn (- m_zoom_level);\n  m_zoom_level = 0;\n}\n\nvoid\ndocumentation_browser::wheelEvent (QWheelEvent *we)\n{\n  if (we->modifiers () == Qt::ControlModifier)\n    {\n      if (we->angleDelta ().y () > 0)\n        zoom_in ();\n      else\n        zoom_out ();\n\n      we->accept ();\n    }\n  else\n    QTextEdit::wheelEvent (we);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/documentation.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_documentation_h)\n#define octave_documentation_h 1\n\n#include <QComboBox>\n#include <QMenu>\n#include <QShortcut>\n#include <QSplitter>\n#include <QTextBrowser>\n#include <QToolBar>\n#include <QListWidget>\n#include <QToolButton>\n#include <QWidget>\n#include <QtHelp/QHelpEngine>\n\n#include \"find-widget.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass documentation;\nclass documentation_bookmarks;\n\n//! Documentation browser derived from Textbrowser\n\nclass documentation_browser : public QTextBrowser\n{\n  Q_OBJECT\n\npublic:\n\n  documentation_browser (QHelpEngine *help_engine, QWidget *parent = nullptr);\n  ~documentation_browser () = default;\n\n  virtual QVariant loadResource (int type, const QUrl& url);\n\npublic Q_SLOTS:\n\n  void handle_index_clicked (const QUrl& url,\n                             const QString& keyword = QString ());\n  void notice_settings ();\n  void save_settings ();\n\n  //! Zooming in and out while taking care of the zoom level\n  //!@{\n  void zoom_in ();\n  void zoom_out ();\n  void zoom_original ();\n  //!@}\n\nprotected:\n\n  void wheelEvent (QWheelEvent *we);\n\nprivate:\n\n  QHelpEngine *m_help_engine;\n\n  //! Store the current zoom level\n  int m_zoom_level;\n\n  //! Minimal and maximal zoom level avoiding calling\n  //! zoom_in and zoom_out without actually zooming but\n  //! with changing the stored zoom level\n  enum\n  {\n    min_zoom_level = -5,\n    max_zoom_level = 10\n  };\n};\n\n//! The documentation main class derived from QSplitter\n\nclass documentation : public QSplitter\n{\n  Q_OBJECT\n\npublic:\n\n  documentation (QWidget *parent);\n  ~documentation ();\n\n  /*!\n      Generate a string with page name @p title and current anchor\n      from @p url for using in prev/next or bookmarks menu:\n\n        @param title current title of the page as QString\n        @param url   current url  as QUrl\n\n        @return QString \"title: anchor\"\n  */\n  QString title_and_anchor (const QString& title, const QUrl& url);\n\nQ_SIGNALS:\n\n  void show_single_result (const QUrl&);\n\npublic Q_SLOTS:\n\n  void notice_settings ();\n  void save_settings ();\n\n  void copyClipboard ();\n  void pasteClipboard ();\n  void selectAll ();\n\n  void load_index ();\n  void load_ref (const QString& name = QString ());\n  void registerDoc (const QString& name);\n  void unregisterDoc (const QString& name);\n\nprivate Q_SLOTS:\n\n  void global_search ();\n  void global_search_started ();\n  void global_search_finished (int hits);\n  void filter_update (const QString& expression);\n  void filter_update_history ();\n  void find (const QString&, bool);\n  void find_forward_from_anchor (const QString& text);\n  void record_anchor_position ();\n  void handle_cursor_position_change ();\n  void handle_search_result_clicked (const QUrl& url);\n\n  void update_history_menus ();\n  void open_hist_url (QAction *a);\n\nprivate:\n\n  void construct_tool_bar ();\n  QAction * add_action (const QIcon& icon, const QString& text,\n                        const char *member, QWidget *receiver = nullptr,\n                        QToolBar *tool_bar = nullptr);\n  void update_history (int new_count, QAction **actions);\n\n  //! Select all occurrences of a string in the doc browser\n  void select_all_occurrences (const QString& text);\n\n  QHelpEngine *m_help_engine;\n  QString m_internal_search;\n  documentation_browser *m_doc_browser;\n  documentation_bookmarks *m_bookmarks;\n  int m_search_anchor_position;\n  QComboBox *m_filter;\n  QString m_collection;\n\n  QWidget *m_doc_widget;\n  find_widget *m_find_widget;\n  QToolBar *m_tool_bar;\n  QString m_query_string;\n\n  bool m_indexed;\n  QString m_current_ref_name;\n\n  QAction *m_action_go_home;\n  QAction *m_action_go_prev;\n  QAction *m_action_go_next;\n  QMenu *m_prev_pages_menu;\n  QMenu *m_next_pages_menu;\n  int m_prev_pages_count;\n  int m_next_pages_count;\n\n  enum { max_history_entries = 10 };\n  QAction *m_prev_pages_actions[max_history_entries];\n  QAction *m_next_pages_actions[max_history_entries];\n\n  QAction *m_action_bookmark;\n  QAction *m_action_find;\n\n  QAction *m_action_zoom_in;\n  QAction *m_action_zoom_out;\n  QAction *m_action_zoom_original;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/dw-main-window.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/* This is the main window derived from QMainWindow for being used\n   as the main window in dock widgets like the variable editor or\n   the file editor\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QDockWidget>\n#include <QEvent>\n#include <QMenu>\n\n#include \"dw-main-window.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-settings.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ndw_main_window::dw_main_window (QWidget *p)\n  : QMainWindow (p)\n{\n  gui_settings settings;\n\n  // Adding the actions for closing the dock widgets\n  m_close_action\n    = add_action (nullptr, settings.icon (\"window-close\", false),\n                  tr (\"&Close\"), SLOT (request_close ()), this);\n\n  m_close_all_action\n    = add_action (nullptr, settings.icon (\"window-close\", false),\n                  tr (\"Close &All\"), SLOT (request_close_all ()), this);\n\n  m_close_others_action\n    = add_action (nullptr, settings.icon (\"window-close\", false),\n                  tr (\"Close &Other\"), SLOT (request_close_other ()), this);\n\n  m_switch_left_action\n    = add_action (nullptr, QIcon (), tr (\"Switch to &Left Widget\"),\n                  SLOT (request_switch_left ()), this);\n\n  m_switch_right_action\n    = add_action (nullptr, QIcon (), tr (\"Switch to &Right Widget\"),\n                  SLOT (request_switch_right ()), this);\n\n  // The list of actions for floating widgets\n  m_actions_list << m_close_action;\n  m_actions_list << m_close_others_action;\n  m_actions_list << m_close_all_action;\n  m_actions_list << m_switch_left_action;\n  m_actions_list << m_switch_right_action;\n\n  notice_settings ();\n}\n\n// Re-implementing the popup menu of the main window\nQMenu *\ndw_main_window::createPopupMenu ()\n{\n  QList<QAction *> new_actions = QList<QAction *> ();\n  new_actions.append (m_close_action);\n  new_actions.append (m_close_others_action);\n  new_actions.append (m_close_all_action);\n\n  QMenu *menu = QMainWindow::createPopupMenu ();\n  QList<QAction *> actions = menu->actions ();\n\n  if (actions.length () > 0)\n    {\n      QAction *sep = menu->insertSeparator (actions.at (0));\n      menu->insertActions (sep, new_actions);\n    }\n  else\n    menu->addActions (new_actions);\n\n  return menu;\n}\n\n// Adding an action to the main window\nQAction *\ndw_main_window::add_action (QMenu *menu, const QIcon& icon,\n                            const QString& text, const char *member,\n                            QWidget *receiver)\n{\n  QAction *a;\n  QWidget *r = this;\n\n  if (receiver != nullptr)\n    r = receiver;\n\n  if (menu)\n    a = menu->addAction (icon, text, r, member);\n  else\n    {\n      a = new QAction (icon, text, this);\n      a->setEnabled (true);\n      connect (a, SIGNAL (triggered ()), r, member);\n    }\n\n  addAction (a);  // important for shortcut context\n  a->setShortcutContext (Qt::WidgetWithChildrenShortcut);\n\n  return a;\n}\n\n// Update the settings\nvoid\ndw_main_window::notice_settings ()\n{\n  gui_settings settings;\n\n  settings.set_shortcut (m_close_action, sc_edit_file_close);\n  settings.set_shortcut (m_close_all_action, sc_edit_file_close_all);\n  settings.set_shortcut (m_close_others_action, sc_edit_file_close_other);\n\n  settings.set_shortcut (m_switch_left_action, sc_edit_tabs_switch_left_tab);\n  settings.set_shortcut (m_switch_right_action, sc_edit_tabs_switch_right_tab);\n}\n\n// Slots for handling actions\n\n// Close current widget\nvoid\ndw_main_window::request_close ()\n{\n  for (int i = 0; i < m_dw_list.length (); i++)\n    {\n      if (m_dw_list.at (i)->hasFocus ())\n        {\n          m_dw_list.at (i)->close ();\n          if (i > 0)\n            m_dw_list.at (i-1)->setFocus ();\n          break;\n        }\n    }\n}\n\n// Close other widgets\nvoid\ndw_main_window::request_close_other ()\n{\n  for (int i = m_dw_list.length () - 1; i >= 0; i--)\n    {\n      if (! m_dw_list.at (i)->hasFocus ())\n        m_dw_list.at (i)->close ();\n    }\n}\n\n// Close all widgets\nvoid\ndw_main_window::request_close_all ()\n{\n  for (int i = m_dw_list.length () - 1; i >= 0; i--)\n    m_dw_list.at (i)->close ();\n}\n\n// Switch to left widget\nvoid\ndw_main_window::request_switch_left ()\n{\n  request_switch (-1);\n}\n\n// Switch to right widget\nvoid\ndw_main_window::request_switch_right ()\n{\n  request_switch (1);\n}\n\n// Switch to left/right widget\nvoid\ndw_main_window::request_switch (int direction)\n{\n  int active = -1, next;\n\n  for (int i = m_dw_list.length () - 1; i >= 0; i--)\n    {\n      if (m_dw_list.at (i)->hasFocus ())\n        {\n          active = i;\n          break;\n        }\n    }\n\n  if (active == -1)\n    return;\n\n  if (direction == -1 && active == 0)\n    next = m_dw_list.length () - 1;\n  else if (direction == 1 && active == m_dw_list.length () - 1)\n    next = 0;\n  else\n    next = active + direction;\n\n  m_dw_list.at (next)->raise ();\n  m_dw_list.at (next)->activateWindow ();\n  m_dw_list.at (next)->setFocus ();\n}\n\n// Reimplemented Event\nbool\ndw_main_window::event (QEvent *ev)\n{\n  if (ev->type () == QEvent::ChildAdded\n      || ev->type () == QEvent::ChildRemoved)\n    {\n      // Adding or Removing a child indicates that a dock widget was\n      // created or removed.\n      // In all cases, the list of dock widgets has to be updated.\n      m_dw_list = findChildren<QDockWidget *>();\n    }\n\n  if (ev->type () == QEvent::StyleChange)\n    {\n      // This might indicate un- or re-docking a widget: Make sure\n      // floating widgets get a copy of our actions\n      for (int i = m_dw_list.length () - 1; i >= 0; i--)\n        {\n          // First remove possibly existing actions\n          for (int j = m_actions_list.length () - 1; j >0; j--)\n            m_dw_list.at (i)->removeAction (m_actions_list.at (j));\n\n          // Then add our actions for floating widgets\n          if (m_dw_list.at (i)->isFloating ())\n            m_dw_list.at (i)->addActions (m_actions_list);\n        }\n    }\n\n  return QMainWindow::event (ev);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/dw-main-window.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dw_main_window_h)\n#define octave_dw_main_window_h 1\n\n#include \"octave-config.h\"\n\n#include <QMainWindow>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass dw_main_window : public QMainWindow\n{\n  Q_OBJECT\n\npublic:\n\n  dw_main_window (QWidget *parent = nullptr);\n\n  ~dw_main_window () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (dw_main_window)\n\npublic Q_SLOTS:\n\n  void notice_settings ();\n\nprotected Q_SLOTS:\n\n  virtual QMenu * createPopupMenu ();\n\n  virtual bool event (QEvent *ev);\n\nprivate Q_SLOTS:\n\n  void request_close ();\n  void request_close_all ();\n  void request_close_other ();\n\n  void request_switch_left ();\n  void request_switch_right ();\n\nprivate:\n\n  void request_switch (int direction);\n\n  QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text,\n                        const char *member, QWidget *receiver);\n\n  QList<QDockWidget *> m_dw_list;\n\n  QAction *m_close_action;\n  QAction *m_close_all_action;\n  QAction *m_close_others_action;\n\n  QAction *m_switch_left_action;\n  QAction *m_switch_right_action;\n\n  QList<QAction *> m_actions_list;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/external-editor-interface.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QMessageBox>\n#include <QProcess>\n#include <QRegularExpression>\n\n#include \"external-editor-interface.h\"\n#include \"gui-settings.h\"\n#include \"gui-preferences-global.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nexternal_editor_interface::external_editor_interface (QWidget *p)\n  : QWidget (p)\n{ }\n\n// Calling the external editor\nbool\nexternal_editor_interface::call_custom_editor (const QString& file, int line)\n{\n  QString editor = external_editor ();\n  if (editor.isEmpty ())\n    return true;\n\n  if (line < 0)\n    line = 0;\n\n  // replace macros\n  editor.replace (\"%f\", file);\n  editor.replace (\"%l\", QString::number (line));\n\n  QStringList arguments = editor.split (QRegularExpression {\"\\\\s+\"});\n  editor = arguments.takeFirst ();\n\n  // start the process and check for success\n  bool started_ok = QProcess::startDetached (editor, arguments);\n\n  if (started_ok != true)\n    {\n      QMessageBox *msgBox = new QMessageBox (QMessageBox::Critical,\n                                             tr (\"Octave Editor\"),\n                                             tr (\"Could not start custom file editor\\n%1\").\n                                             arg (editor),\n                                             QMessageBox::Ok);\n\n      msgBox->setWindowModality (Qt::NonModal);\n      msgBox->setAttribute (Qt::WA_DeleteOnClose);\n      msgBox->show ();\n    }\n\n  return started_ok;\n}\n\n// Slots for the several signals for invoking the editor\n\nvoid\nexternal_editor_interface::request_new_file (const QString&)\n{\n  call_custom_editor ();\n}\n\nvoid\nexternal_editor_interface::request_open_file (const QString& file_name,\n                                              const QString&, int line,\n                                              bool, bool, bool,\n                                              const QString&)\n{\n  call_custom_editor (file_name, line);\n}\n\nvoid\nexternal_editor_interface::handle_edit_file_request (const QString& file)\n{\n  call_custom_editor (file);\n}\n\n// Get and verify the settings of the external editor program\nQString\nexternal_editor_interface::external_editor ()\n{\n  gui_settings settings;\n\n  QString editor = settings.value (global_custom_editor.settings_key (),\n                                   global_custom_editor.def ()).toString ();\n\n  // check the settings (avoid an empty string)\n  if (editor.trimmed ().isEmpty ())\n    {\n      QMessageBox *msgBox\n        = new QMessageBox (QMessageBox::Warning,\n                           tr (\"Octave Editor\"),\n                           tr (\"There is no custom editor configured yet.\\n\"\n                               \"Do you want to open the preferences?\"),\n                           QMessageBox::No | QMessageBox::Yes);\n      msgBox->setDefaultButton (QMessageBox::Yes);\n      msgBox->setAttribute (Qt::WA_DeleteOnClose);\n\n      int button = msgBox->exec ();\n\n      if (button == QMessageBox::Yes)\n        Q_EMIT request_settings_dialog (\"editor\");\n    }\n\n  return editor;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/external-editor-interface.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_external_editor_interface_h)\n#define octave_external_editor_interface_h 1\n\n#include <QString>\n#include <QWidget>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass external_editor_interface : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  external_editor_interface (QWidget *main_win);\n\n  ~external_editor_interface () = default;\n\nQ_SIGNALS:\n\n  void request_settings_dialog (const QString&);\n\npublic Q_SLOTS:\n\n  bool call_custom_editor (const QString& file = QString (), int line = -1);\n\n  void request_open_file (const QString& fileName,\n                          const QString& encoding = QString (),\n                          int line = -1, bool debug_pointer = false,\n                          bool breakpoint_marker = false, bool insert = true,\n                          const QString& cond = \"\");\n\n  void request_new_file (const QString&);\n\n  void handle_edit_file_request (const QString& file);\n\nprivate:\n\n  QString external_editor ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/files-dock-widget.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <map>\n\n#include <QApplication>\n#include <QClipboard>\n#include <QCompleter>\n#include <QDebug>\n#include <QDesktopServices>\n#include <QFileDialog>\n#include <QFileInfo>\n#include <QHeaderView>\n#include <QInputDialog>\n#include <QLineEdit>\n#include <QMenu>\n#include <QMessageBox>\n#include <QMimeDatabase>\n#include <QMimeType>\n#include <QProcess>\n#include <QSizePolicy>\n#include <QStyledItemDelegate>\n#include <QTimer>\n#include <QToolButton>\n#include <QUrl>\n\n#include \"files-dock-widget.h\"\n#include \"gui-preferences-fb.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-settings.h\"\n#include \"gui-utils.h\"\n#include \"octave-qt-features.h\"\n#include \"qt-interpreter-events.h\"\n\n#include \"oct-env.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// ----------------------------------------------------------------------\n//  Class file_tree_viewer\n\nclass FileTreeViewer : public QTreeView\n{\npublic:\n\n  FileTreeViewer (QWidget *p) : QTreeView (p) { }\n\n  ~FileTreeViewer () = default;\n\n  void mousePressEvent (QMouseEvent *e)\n  {\n    if (e->button () != Qt::RightButton)\n      QTreeView::mousePressEvent (e);\n  }\n};\n\n\n// ----------------------------------------------------------------------\n//  Class file_system_model\n\n// to have file renamed in the file tree, it has to be renamed in\n// QFileSystemModel::setData.\n// For the editor to behave correctly, some signals must be sent before\n// and after the rename\n\nclass file_system_model : public QFileSystemModel\n{\npublic:\n  file_system_model (file_system_browser *p) : QFileSystemModel (p) {}\n\n  ~file_system_model () = default;\n\n  bool setData (const QModelIndex& idx, const QVariant& value,\n                int role) override\n  {\n    if (!idx.isValid () || idx.column () != 0 || role != Qt::EditRole\n        || (flags (idx) & Qt::ItemIsEditable) == 0)\n      {\n        return false;\n      }\n\n    QString new_name = value.toString ();\n    QString old_name = idx.data ().toString ();\n    if (new_name == old_name)\n      return true;\n    if (new_name.isEmpty ()\n        || QDir::toNativeSeparators (new_name).contains (QDir::separator ()))\n      {\n        display_rename_failed_message (old_name, new_name);\n        return false;\n      }\n\n    auto parent_dir = QDir (filePath (parent (idx)));\n\n    file_system_browser *fsb = static_cast<file_system_browser *>(parent ());\n\n    fsb->file_remove_signal (parent_dir.filePath (old_name), parent_dir.filePath (new_name));\n\n    if (!parent_dir.rename (old_name, new_name))\n      {\n        display_rename_failed_message (old_name, new_name);\n        fsb->file_renamed_signal (false);\n        return false;\n      }\n\n    fsb->file_renamed_signal (true);\n\n    Q_EMIT fileRenamed (parent_dir.absolutePath (), old_name, new_name);\n    revert ();\n\n    return true;\n  }\n\nprivate:\n  void display_rename_failed_message (const QString& old_name,\n                                      const QString& new_name)\n  {\n    const QString message =\n\n      files_dock_widget::tr (\"Could not rename file \\\"%1\\\" to \\\"%2\\\".\")\n      .arg (old_name)\n      .arg (new_name);\n    QMessageBox::information (static_cast<QWidget *> (parent ()),\n                              QFileSystemModel::tr (\"Invalid filename\"),\n                              message, QMessageBox::Ok);\n  }\n};\n\n// Delegate to improve ergonomy of file renaming by pre-selecting the text\n// before the extension.\nclass RenameItemDelegate : public QStyledItemDelegate\n{\npublic:\n  RenameItemDelegate (QObject *parent = nullptr)\n    : QStyledItemDelegate { parent }\n  { }\n\n  void setEditorData (QWidget *editor,\n                      const QModelIndex& index) const override\n  {\n    QLineEdit *line_edit = qobject_cast<QLineEdit *> (editor);\n\n    if (!line_edit)\n      {\n        QStyledItemDelegate::setEditorData (editor, index);\n        return;\n      }\n\n    QString filename = index.data (Qt::EditRole).toString ();\n\n    int select_len = filename.indexOf (QChar ('.'));\n    if (select_len == -1)\n      select_len = filename.size ();\n\n    line_edit->setText (filename);\n\n    // Qt calls QLineEdit::selectAll after this function is called, so to\n    // actually restrict the selection, we have to post the modification at\n    // the end of the event loop.\n    // QTimer allows this easily with 0 as timeout.\n    QTimer::singleShot (0, [line_edit, select_len] () { line_edit->setSelection (0, select_len); });\n  }\n};\n\n\n// ----------------------------------------------------------------------\n//  Class cache_file_icon_provider\n\nclass cache_file_icon_provider : public QFileIconProvider\n{\npublic:\n  cache_file_icon_provider ()\n  {\n    m_null_icon = QIcon ();\n    m_file_icon = m_file_icon_provider.icon (QFileIconProvider::File);\n    m_folder_icon = m_file_icon_provider.icon (QFileIconProvider::Folder);\n  }\n\n  QIcon icon (IconType ict) const\n  {\n    if (ict == QFileIconProvider::File)\n      return m_file_icon;\n    else if (ict == QFileIconProvider::Folder)\n      return m_folder_icon;\n    else\n      return m_null_icon;\n  }\n\n  QIcon icon (const QFileInfo& fi) const\n  {\n    static bool no_platform_theme = QIcon::themeName ().isEmpty ();\n\n    if (no_platform_theme)\n      return m_file_icon_provider.icon (fi);\n\n    QMimeType mime_type = m_db.mimeTypeForFile (fi.absoluteFilePath ());\n    QString icon_name = mime_type.iconName ();\n    auto mime_type_iter = m_icon_cache.find (icon_name);\n    if (mime_type_iter != m_icon_cache.end ())\n      return mime_type_iter->second;\n\n    QIcon icon = QIcon::fromTheme (icon_name);\n    m_icon_cache.insert ({icon_name, icon});\n    return icon;\n  }\n\nprivate:\n  QIcon m_null_icon;\n  QIcon m_file_icon;\n  QIcon m_folder_icon;\n\n  QFileIconProvider m_file_icon_provider;\n  QMimeDatabase m_db;\n  static std::map<QString, QIcon> m_icon_cache;\n};\n\nstd::map<QString, QIcon> cache_file_icon_provider::m_icon_cache;\n\n\n// ----------------------------------------------------------------------\n//  Class file_dock_widget\n\nfiles_dock_widget::files_dock_widget (QWidget *p)\n  : octave_dock_widget (\"FilesDockWidget\", p)\n{\n  set_title (tr (\"File Browser\"));\n  setToolTip (tr (\"Browse your files\"));\n\n  QTabWidget *files_tab_widget = new QTabWidget (this);\n  files_tab_widget->setTabPosition (QTabWidget::South);\n\n  setWidget (files_tab_widget);\n\n  m_file_browser = new file_system_browser (files_tab_widget);\n  m_editor_files = new editor_files_browser (files_tab_widget);\n\n  files_tab_widget->addTab (m_file_browser, tr (\"File System\"));\n  files_tab_widget->addTab (m_editor_files, tr (\"Editor Files\"));\n\n#if ! defined (HAVE_QSCINTILLA)\n  files_tab_widget->tabBar ()->hide ();\n#endif\n\n  if (! p)\n    make_window ();\n}\n\nvoid\nfiles_dock_widget::save_settings ()\n{\n  m_file_browser->save_settings ();\n  m_editor_files->save_settings ();\n\n  gui_settings settings;\n\n  QTabWidget *tab_widget = findChild<QTabWidget *>();\n  if (tab_widget)\n    {\n      int tab = tab_widget->currentIndex ();\n      settings.setValue (fb_active_tab.settings_key (), tab);\n    }\n\n  octave_dock_widget::save_settings ();\n}\n\nvoid\nfiles_dock_widget::notice_settings ()\n{\n  gui_settings settings;\n\n  QTabWidget *tab_widget = findChild<QTabWidget *>();\n  if (tab_widget)\n    {\n#if defined (HAVE_QSCINTILLA)\n      int tab = settings.value (fb_active_tab.settings_key ()).toInt ();\n      tab_widget->setCurrentIndex (tab);\n#else\n      tab_widget->setCurrentIndex (tab_widget->indexOf (m_file_browser));\n#endif\n    }\n\n  m_file_browser->notice_settings ();\n  m_editor_files->notice_settings ();\n}\n\n\n\n// ----------------------------------------------------------------------\n//  Class file_system_browser\n\nfile_system_browser::file_system_browser (QWidget *p)\n  : QWidget (p),\n    m_first (true),\n    m_header_settings_only (false)\n{\n  m_sig_mapper = nullptr;\n\n  m_columns_shown = QStringList ();\n  m_columns_shown.append (tr (\"File size\"));\n  m_columns_shown.append (tr (\"File type\"));\n  m_columns_shown.append (tr (\"Date modified\"));\n  m_columns_shown.append (tr (\"Show hidden\"));\n  m_columns_shown.append (tr (\"Alternating row colors\"));\n\n  m_columns_shown_keys = QStringList ();\n  m_columns_shown_keys.append (fb_show_size.settings_key ());\n  m_columns_shown_keys.append (fb_show_type.settings_key ());\n  m_columns_shown_keys.append (fb_show_date.settings_key ());\n  m_columns_shown_keys.append (fb_show_hidden.settings_key ());\n  m_columns_shown_keys.append (fb_show_altcol.settings_key ());\n\n  m_columns_shown_defs = QList<QVariant> ();\n  m_columns_shown_defs.append (fb_show_size.def ());\n  m_columns_shown_defs.append (fb_show_type.def ());\n  m_columns_shown_defs.append (fb_show_date.def ());\n  m_columns_shown_defs.append (fb_show_hidden.def ());\n  m_columns_shown_defs.append (fb_show_altcol.def ());\n\n  // Create a toolbar\n  m_navigation_tool_bar = new QToolBar (\"\", this);\n  m_navigation_tool_bar->setAllowedAreas (Qt::TopToolBarArea);\n  m_navigation_tool_bar->setMovable (false);\n\n  m_current_directory = new QComboBox (m_navigation_tool_bar);\n  m_current_directory->setToolTip (tr (\"Enter the path or filename\"));\n  m_current_directory->setEditable (true);\n  m_current_directory->setMaxCount (MaxMRUDirs);\n  m_current_directory->setInsertPolicy (QComboBox::NoInsert);\n  m_current_directory->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);\n  QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);\n  m_current_directory->setSizePolicy (sizePol);\n\n  gui_settings settings;\n\n  QAction *directory_up_action\n    = new QAction (settings.icon (\"folder-up\", false, \"go-up\"), \"\",\n                   m_navigation_tool_bar);\n  directory_up_action->setToolTip (tr (\"One directory up\"));\n\n  m_sync_browser_directory_action\n    = new QAction (settings.icon (\"go-first\"), tr (\"Show Octave directory\"),\n                   m_navigation_tool_bar);\n  m_sync_browser_directory_action->setToolTip (tr (\"Go to current Octave directory\"));\n  m_sync_browser_directory_action->setEnabled (false);\n\n  m_sync_octave_directory_action\n    = new QAction (settings.icon (\"go-last\"), tr (\"Set Octave directory\"),\n                   m_navigation_tool_bar);\n  m_sync_octave_directory_action->setToolTip (tr (\"Set Octave directory to current browser directory\"));\n  m_sync_octave_directory_action->setEnabled (false);\n\n  QToolButton *popdown_button = new QToolButton ();\n  popdown_button->setToolTip (tr (\"Actions on current directory\"));\n  QMenu *popdown_menu = new QMenu ();\n  popdown_menu->addAction (settings.icon (\"user-home\"),\n                           tr (\"Show Home Directory\"), this,\n                           SLOT (popdownmenu_home (bool)));\n  popdown_menu->addAction (m_sync_browser_directory_action);\n  popdown_menu->addAction (m_sync_octave_directory_action);\n  popdown_button->setMenu (popdown_menu);\n  popdown_button->setPopupMode (QToolButton::InstantPopup);\n  popdown_button->setDefaultAction\n    (new QAction (settings.icon (\"folder-settings\", false,\n                                 \"applications-system\"),\n                  \"\", m_navigation_tool_bar));\n\n  popdown_menu->addSeparator ();\n  popdown_menu->addAction (settings.icon (\"folder\"),\n                           tr (\"Set Browser Directory...\"),\n                           this, &file_system_browser::popdownmenu_search_dir);\n  popdown_menu->addSeparator ();\n  popdown_menu->addAction (settings.icon (\"edit-find\"),\n                           tr (\"Find Files...\"),\n                           this, &file_system_browser::popdownmenu_findfiles);\n  popdown_menu->addSeparator ();\n  popdown_menu->addAction (settings.icon (\"document-new\"),\n                           tr (\"New File...\"),\n                           this, &file_system_browser::popdownmenu_newfile);\n  popdown_menu->addAction (settings.icon (\"folder-new\"),\n                           tr (\"New Directory...\"),\n                           this, &file_system_browser::popdownmenu_newdir);\n\n  m_navigation_tool_bar->addWidget (m_current_directory);\n  m_navigation_tool_bar->addAction (directory_up_action);\n  m_navigation_tool_bar->addWidget (popdown_button);\n\n  connect (directory_up_action, &QAction::triggered,\n           this, &file_system_browser::change_directory_up);\n  connect (m_sync_octave_directory_action, &QAction::triggered,\n           this, &file_system_browser::do_sync_octave_directory);\n  connect (m_sync_browser_directory_action, &QAction::triggered,\n           this, &file_system_browser::do_sync_browser_directory);\n\n  // Create the QFileSystemModel starting in the desired directory\n  QDir startup_dir;  // take current dir\n\n  if (settings.bool_value (fb_restore_last_dir))\n    {\n      // restore last dir from previous session\n      QStringList last_dirs\n        = settings.value (fb_mru_list.settings_key ()).toStringList ();\n      if (last_dirs.length () > 0)\n        startup_dir = QDir (last_dirs.at (0));  // last dir in previous session\n    }\n  else if (! settings.string_value (fb_startup_dir).isEmpty ())\n    {\n      // do not restore but there is a startup dir configured\n      startup_dir = QDir (settings.value (fb_startup_dir.settings_key ()).toString ());\n    }\n\n  if (! startup_dir.exists ())\n    {\n      // the configured startup dir does not exist, take actual one\n      startup_dir = QDir ();\n    }\n\n  m_file_system_model = new file_system_model (this);\n  m_file_system_model->setResolveSymlinks (false);\n  m_file_system_model->setFilter\n    (QDir::System | QDir::NoDotAndDotDot | QDir::AllEntries);\n  QModelIndex rootPathIndex\n    = m_file_system_model->setRootPath (startup_dir.absolutePath ());\n\n  m_file_icon_provider = new cache_file_icon_provider ();\n  m_file_system_model->setIconProvider (m_file_icon_provider);\n\n  // Attach the model to the QTreeView and set the root index\n  m_file_tree_view = new FileTreeViewer (this);\n  m_file_tree_view->setSelectionMode (QAbstractItemView::ExtendedSelection);\n  m_file_tree_view->setModel (m_file_system_model);\n  m_file_tree_view->setRootIndex (rootPathIndex);\n  m_file_tree_view->setSortingEnabled (true);\n  m_file_tree_view->setAlternatingRowColors (true);\n  m_file_tree_view->setAnimated (true);\n  m_file_tree_view->setToolTip (tr (\"Double-click to open file/folder, right click for alternatives\"));\n\n  // allow renaming directly in the tree view with\n  // m_file_tree_view->edit (index)\n  m_file_system_model->setReadOnly (false);\n  // delegate to improve rename ergonomy by pre-selecting text up to the\n  // extension\n  auto *rename_delegate = new RenameItemDelegate (this);\n  m_file_tree_view->setItemDelegateForColumn (0, rename_delegate);\n  // prevent the tree view to override Octave's double-click behavior\n  m_file_tree_view->setEditTriggers (QAbstractItemView::NoEditTriggers);\n  // create the rename action (that will be added to context menu)\n  // and associate to F2 key shortcut\n  m_rename_action = new QAction (tr (\"Rename...\"), this);\n  m_rename_action->setShortcut (Qt::Key_F2);\n  m_rename_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);\n  connect (m_rename_action, &QAction::triggered, this,\n           &file_system_browser::contextmenu_rename);\n  addAction (m_rename_action);\n\n  // get sort column and order as well as column state (order and width)\n\n  m_file_tree_view->sortByColumn\n    (settings.int_value (fb_sort_column),\n     // FIXME: use value<Qt::SortOrder> instead of static cast after\n     //        dropping support of Qt 5.4\n     static_cast<Qt::SortOrder> (settings.uint_value (fb_sort_order)));\n\n  // Set header properties for sorting\n  m_file_tree_view->header ()->setSectionsClickable (true);\n  m_file_tree_view->header ()->setSectionsMovable (true);\n  m_file_tree_view->header ()->setSortIndicatorShown (true);\n\n  QStringList mru_dirs =\n    settings.value (fb_mru_list.settings_key ()).toStringList ();\n  m_current_directory->addItems (mru_dirs);\n\n  m_current_directory->setEditText\n    (m_file_system_model->fileInfo (rootPathIndex). absoluteFilePath ());\n\n  connect (m_file_tree_view, &FileTreeViewer::activated,\n           this, &file_system_browser::item_double_clicked);\n\n  // add context menu to tree_view\n  m_file_tree_view->setContextMenuPolicy (Qt::CustomContextMenu);\n  connect (m_file_tree_view, &FileTreeViewer::customContextMenuRequested,\n           this, &file_system_browser::contextmenu_requested);\n\n  m_file_tree_view->header ()->setContextMenuPolicy (Qt::CustomContextMenu);\n  connect (m_file_tree_view->header (),\n           &QHeaderView::customContextMenuRequested,\n           this, &file_system_browser::headercontextmenu_requested);\n\n  // Layout the widgets vertically with the toolbar on top\n  QVBoxLayout *vbox_layout = new QVBoxLayout ();\n  vbox_layout->setSpacing (0);\n  vbox_layout->addWidget (m_navigation_tool_bar);\n  vbox_layout->addWidget (m_file_tree_view);\n  vbox_layout->setContentsMargins (1, 1, 1, 1);\n\n  setLayout (vbox_layout);\n\n  // FIXME: Add right-click contextual menus for copying, pasting,\n  //        deleting files (and others).\n\n  connect (m_current_directory->lineEdit (), &QLineEdit::returnPressed,\n           this, &file_system_browser::accept_directory_line_edit);\n\n#if defined (HAVE_QCOMBOBOX_TEXTACTIVATED)\n  connect (m_current_directory, &QComboBox::textActivated,\n           this, &file_system_browser::set_current_directory);\n#else\n  connect (m_current_directory, SIGNAL (activated (const QString&)),\n           this, SLOT (set_current_directory (const QString&)));\n#endif\n\n  QCompleter *completer = new QCompleter (m_file_system_model, this);\n  m_current_directory->setCompleter (completer);\n\n  setFocusProxy (m_current_directory);\n\n  m_sync_octave_dir = true;   // default, overwritten with notice_settings ()\n  m_octave_dir = \"\";\n}\n\nvoid\nfile_system_browser::restore_header_state ()\n{\n  gui_settings settings;\n\n  if (settings.contains (fb_column_state.settings_key ()))\n    m_file_tree_view->header ()->restoreState\n      (settings.value (fb_column_state.settings_key ()).toByteArray ());\n}\n\nvoid\nfile_system_browser::save_settings ()\n{\n  gui_settings settings;\n\n  int sort_column = m_file_tree_view->header ()->sortIndicatorSection ();\n  Qt::SortOrder sort_order = m_file_tree_view->header ()->sortIndicatorOrder ();\n  settings.setValue (fb_sort_column.settings_key (), sort_column);\n  settings.setValue (fb_sort_order.settings_key (), sort_order);\n  settings.setValue (fb_column_state.settings_key (),\n                     m_file_tree_view->header ()->saveState ());\n\n  QStringList dirs;\n  for (int i=0; i< m_current_directory->count (); i++)\n    {\n      dirs.append (m_current_directory->itemText (i));\n    }\n  settings.setValue (fb_mru_list.settings_key (), dirs);\n\n  settings.sync ();\n\n  if (m_sig_mapper)\n    delete m_sig_mapper;\n}\n\nvoid\nfile_system_browser::item_double_clicked (const QModelIndex& index)\n{\n  // Retrieve the file info associated with the model index.\n  QFileInfo fileInfo = m_file_system_model->fileInfo (index);\n  set_current_directory (fileInfo.absoluteFilePath ());\n}\n\nvoid\nfile_system_browser::set_current_directory (const QString& dir)\n{\n  display_directory (dir);\n}\n\nvoid\nfile_system_browser::accept_directory_line_edit ()\n{\n  display_directory (m_current_directory->currentText ());\n}\n\nvoid\nfile_system_browser::change_directory_up ()\n{\n  QDir dir\n    = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ()));\n\n  dir.cdUp ();\n  display_directory (dir.absolutePath ());\n}\n\nvoid\nfile_system_browser::do_sync_octave_directory ()\n{\n  QDir dir\n    = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ()));\n\n  Q_EMIT displayed_directory_changed (dir.absolutePath ());\n}\n\nvoid\nfile_system_browser::do_sync_browser_directory ()\n{\n  display_directory (m_octave_dir, false); // false: no sync of octave dir\n}\n\nvoid\nfile_system_browser::update_octave_directory (const QString& dir)\n{\n  m_octave_dir = dir;\n  if (m_sync_octave_dir)\n    display_directory (m_octave_dir, false); // false: no sync of octave dir\n}\n\nvoid\nfile_system_browser::display_directory (const QString& dir,\n                                      bool set_octave_dir)\n{\n  QFileInfo fileInfo (dir);\n  if (fileInfo.exists ())\n    {\n      if (fileInfo.isDir ())\n        {\n          m_file_tree_view->setRootIndex (m_file_system_model->\n                                          index (fileInfo.absoluteFilePath ()));\n          m_file_system_model->setRootPath (fileInfo.absoluteFilePath ());\n          if (m_sync_octave_dir && set_octave_dir)\n            process_set_current_dir (fileInfo.absoluteFilePath ());\n\n          // see if it's in the list, and if it is,\n          // remove it and then put at top of the list\n          combobox_insert_current_item (m_current_directory,\n                                        fileInfo.absoluteFilePath ());\n        }\n      else\n        {\n          QString abs_fname = fileInfo.absoluteFilePath ();\n\n          QString suffix = fileInfo.suffix ().toLower ();\n\n          gui_settings settings;\n\n          QString ext = settings.string_value (fb_txt_file_ext);\n#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)\n          QStringList extensions = ext.split (\";\", Qt::SkipEmptyParts);\n#else\n          QStringList extensions = ext.split (\";\", QString::SkipEmptyParts);\n#endif\n          if (QFile::exists (abs_fname))\n            {\n              if (extensions.contains (suffix))\n                Q_EMIT open_file (fileInfo.absoluteFilePath ());\n              else\n                Q_EMIT open_any_signal (abs_fname);\n            }\n        }\n    }\n}\n\nvoid\nfile_system_browser::open_item_in_app (const QModelIndex& index)\n{\n  // Retrieve the file info associated with the model index.\n  QFileInfo fileInfo = m_file_system_model->fileInfo (index);\n\n  QString file = fileInfo.absoluteFilePath ();\n\n  QDesktopServices::openUrl (QUrl::fromLocalFile (file));\n}\n\nvoid\nfile_system_browser::toggle_header (int col)\n{\n  gui_settings settings;\n\n  if (col <= 2)\n    {\n      // Toggle column visibility\n      m_file_tree_view->setColumnHidden (col + 1,\n                                         ! m_file_tree_view->isColumnHidden (col +1));\n    }\n  else\n    {\n      // Other actions depending on new settings\n      QString key = m_columns_shown_keys.at (col);\n      bool active = settings.value (key, false).toBool ();\n\n      // Toggle the settings in the settings file\n      settings.setValue (key, ! active);\n      settings.sync ();\n\n      // Reload header related settings only\n      m_header_settings_only = true;\n      notice_settings ();\n    }\n}\n\nvoid\nfile_system_browser::headercontextmenu_requested (const QPoint& mpos)\n{\n  QMenu menu (this);\n\n  if (m_sig_mapper)\n    delete m_sig_mapper;\n  m_sig_mapper = new QSignalMapper (this);\n\n  gui_settings settings;\n\n  for (int i = 0; i < m_columns_shown.size (); i++)\n    {\n      QAction *action = menu.addAction (m_columns_shown.at (i),\n                                        m_sig_mapper, SLOT (map ()));\n      m_sig_mapper->setMapping (action, i);\n      action->setCheckable (true);\n      if (i <= 2)\n        {\n          // Column visibility\n          action->setChecked (! m_file_tree_view->isColumnHidden (i +1));\n        }\n      else\n        {\n          // Other actions depending on settings\n          action->setChecked (settings.value (m_columns_shown_keys.at (i),\n                                              m_columns_shown_defs.at (i)).toBool ());\n        }\n    }\n\n#if defined (HAVE_QSIGNALMAPPER_MAPPEDINT)\n  connect (m_sig_mapper, &QSignalMapper::mappedInt,\n           this, &file_system_browser::toggle_header);\n#else\n  connect (m_sig_mapper, SIGNAL (mapped (int)),\n           this, SLOT (toggle_header (int)));\n#endif\n\n  menu.exec (m_file_tree_view->mapToGlobal (mpos));\n}\n\nvoid\nfile_system_browser::contextmenu_requested (const QPoint& mpos)\n{\n\n  QMenu menu (this);\n\n  QModelIndex index = m_file_tree_view->indexAt (mpos);\n\n  if (index.isValid ())\n    {\n      QFileInfo info = m_file_system_model->fileInfo (index);\n\n      QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n      QModelIndexList sel = m->selectedRows ();\n\n      // check if item at mouse position is seleccted\n      if (! sel.contains (index))\n        {\n          // is not selected -> clear actual selection and select this item\n          m->setCurrentIndex (index,\n                              QItemSelectionModel::Clear\n                              | QItemSelectionModel::Select\n                              | QItemSelectionModel::Rows);\n        }\n\n      gui_settings settings;\n\n      // construct the context menu depending on item\n      menu.addAction (settings.icon (\"document-open\"), tr (\"Open\"),\n                      this, &file_system_browser::contextmenu_open);\n\n      if (info.isDir ())\n        {\n          menu.addAction (tr (\"Open in System File Explorer\"),\n                          this, &file_system_browser::contextmenu_open_in_app);\n        }\n\n      if (info.isFile ())\n        menu.addAction (tr (\"Open in Text Editor\"),\n                        this, &file_system_browser::contextmenu_open_in_editor);\n\n      menu.addAction (tr (\"Copy Selection to Clipboard\"),\n                      this, &file_system_browser::contextmenu_copy_selection);\n\n      if (info.isFile () && info.suffix () == \"m\")\n        menu.addAction (settings.icon (\"system-run\"), tr (\"Run\"),\n                        this, &file_system_browser::contextmenu_run);\n\n      if (info.isFile ())\n        menu.addAction (tr (\"Load Data\"),\n                        this, &file_system_browser::contextmenu_load);\n\n      if (info.isDir ())\n        {\n          menu.addSeparator ();\n          menu.addAction (settings.icon (\"go-first\"), tr (\"Set Current Directory\"),\n                          this, &file_system_browser::contextmenu_setcurrentdir);\n\n          QMenu *add_path_menu = menu.addMenu (tr (\"Add to Path\"));\n\n          add_path_menu->addAction (tr (\"Selected Directories\"),\n                                    this, [this] (bool checked) { contextmenu_add_to_path (checked); });\n          add_path_menu->addAction (tr (\"Selected Directories and Subdirectories\"),\n                                    this, &file_system_browser::contextmenu_add_to_path_subdirs);\n\n          QMenu *rm_path_menu = menu.addMenu (tr (\"Remove from Path\"));\n\n          rm_path_menu->addAction (tr (\"Selected Directories\"),\n                                   this, &file_system_browser::contextmenu_rm_from_path);\n          rm_path_menu->addAction (tr (\"Selected Directories and Subdirectories\"),\n                                   this, &file_system_browser::contextmenu_rm_from_path_subdirs);\n\n          menu.addSeparator ();\n\n          menu.addAction (settings.icon (\"edit-find\"), tr (\"Find Files...\"),\n                          this, &file_system_browser::contextmenu_findfiles);\n        }\n\n      menu.addSeparator ();\n      menu.addAction (m_rename_action);\n      menu.addAction (settings.icon (\"edit-delete\"), tr (\"Delete...\"),\n                      this, &file_system_browser::contextmenu_delete);\n\n      if (info.isDir ())\n        {\n          menu.addSeparator ();\n          menu.addAction (settings.icon (\"document-new\"), tr (\"New File...\"),\n                          this, &file_system_browser::contextmenu_newfile);\n          menu.addAction (settings.icon (\"folder-new\"), tr (\"New Directory...\"),\n                          this, &file_system_browser::contextmenu_newdir);\n        }\n\n      // show the menu\n      menu.exec (m_file_tree_view->mapToGlobal (mpos));\n\n    }\n}\n\nvoid\nfile_system_browser::contextmenu_open (bool)\n{\n\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  for (const auto& it : rows)\n    {\n      QFileInfo file = m_file_system_model->fileInfo (it);\n      if (file.exists ())\n        display_directory (file.absoluteFilePath ());\n    }\n}\n\nvoid\nfile_system_browser::contextmenu_open_in_editor (bool)\n{\n\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  for (const auto& it : rows)\n    {\n      QFileInfo file = m_file_system_model->fileInfo (it);\n      if (file.exists ())\n        Q_EMIT open_file (file.absoluteFilePath ());\n    }\n}\n\nvoid\nfile_system_browser::contextmenu_open_in_app (bool)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  for (const auto& it : rows)\n    open_item_in_app (it);\n}\n\nvoid\nfile_system_browser::contextmenu_copy_selection (bool)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  QStringList selection;\n\n  for (const auto& it : rows)\n    {\n      QFileInfo info = m_file_system_model->fileInfo (it);\n      selection << info.fileName ();\n    }\n\n  QClipboard *clipboard = QApplication::clipboard ();\n\n  clipboard->setText (selection.join (\"\\n\"));\n}\n\nvoid\nfile_system_browser::contextmenu_load (bool)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  if (rows.size () > 0)\n    {\n      QModelIndex index = rows[0];\n\n      QFileInfo info = m_file_system_model->fileInfo (index);\n\n      Q_EMIT load_file_signal (info.fileName ());\n    }\n}\n\nvoid\nfile_system_browser::contextmenu_run (bool)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  if (rows.size () > 0)\n    {\n      QModelIndex index = rows[0];\n\n      QFileInfo info = m_file_system_model->fileInfo (index);\n      Q_EMIT run_file_signal (info, ED_RUN_FILE);\n    }\n}\n\nvoid\nfile_system_browser::contextmenu_rename (bool)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n  if (rows.size () > 0)\n    {\n      QModelIndex index = rows[0];\n      m_file_tree_view->edit (index);\n    }\n}\n\nvoid\nfile_system_browser::contextmenu_delete (bool)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  int file_cnt = rows.size ();\n  bool multiple_files = (file_cnt > 1);\n\n  for (auto it = rows.begin (); it != rows.end (); it++)\n    {\n      QModelIndex index = *it;\n\n      QFileInfo info = m_file_system_model->fileInfo (index);\n\n      QMessageBox::StandardButton dlg_answer;\n      if (multiple_files)\n        if (it == rows.begin ())\n          {\n            dlg_answer = QMessageBox::question (this,\n                                                tr (\"Delete file/directory\"),\n                                                tr (\"Are you sure you want to delete all %1 selected files?\\n\").arg (file_cnt),\n                                                QMessageBox::Yes | QMessageBox::No);\n            if (dlg_answer != QMessageBox::Yes)\n              return;\n          }\n        else\n          dlg_answer = QMessageBox::Yes;\n      else\n        {\n          dlg_answer = QMessageBox::question (this,\n                                              tr (\"Delete file/directory\"),\n                                              tr (\"Are you sure you want to delete\\n\")\n                                              + info.filePath (),\n                                              QMessageBox::Yes | QMessageBox::No);\n        }\n\n      if (dlg_answer == QMessageBox::Yes)\n        {\n          if (info.isDir ())\n            {\n              // see if directory is empty\n              QDir path (info.absoluteFilePath ());\n              QList<QFileInfo> fileLst\n                = path.entryInfoList (QDir::Hidden | QDir::AllEntries\n                                      | QDir::NoDotAndDotDot | QDir::System);\n\n              if (fileLst.count () != 0)\n                QMessageBox::warning (this, tr (\"Delete file/directory\"),\n                                      tr (\"Can not delete a directory that is not empty\"));\n              else\n                m_file_system_model->rmdir (index);\n            }\n          else\n            {\n              // Close the file in the editor if open\n              Q_EMIT file_remove_signal (info.filePath (), QString ());\n              // Remove the file.\n              bool st = m_file_system_model->remove (index);\n              if (! st)\n                {\n                  QMessageBox::warning (this, tr (\"Deletion error\"),\n                                        tr (\"Could not delete file \\\"%1\\\".\").\n                                        arg (info.filePath ()));\n                  // Reload the old file\n                }\n              Q_EMIT file_renamed_signal (st);\n            }\n\n          m_file_system_model->revert ();\n\n        }\n    }\n}\n\n// Get the currently selected files/dirs and return their file info\n// in a list.\nQList<QFileInfo>\nfile_system_browser::get_selected_items_info (bool dir)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  QList<QFileInfo> infos;\n\n  for (const auto& idx : rows)\n    {\n      QFileInfo info = m_file_system_model->fileInfo (idx);\n\n      if (info.exists () &&\n          ((dir & info.isDir ()) || (! dir && info.isFile ())))\n        infos.append (info);\n    }\n\n  return infos;\n}\n\nvoid\nfile_system_browser::contextmenu_newfile (bool)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  if (rows.size () > 0)\n    {\n      QModelIndex index = rows[0];\n\n      QFileInfo info = m_file_system_model->fileInfo (index);\n      QString parent_dir = info.filePath ();\n\n      process_new_file (parent_dir);\n    }\n}\n\nvoid\nfile_system_browser::contextmenu_newdir (bool)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  if (rows.size () > 0)\n    {\n      QModelIndex index = rows[0];\n\n      QFileInfo info = m_file_system_model->fileInfo (index);\n      QString parent_dir = info.filePath ();\n\n      process_new_dir (parent_dir);\n    }\n}\n\nvoid\nfile_system_browser::contextmenu_setcurrentdir (bool)\n{\n  QList<QFileInfo> infos = get_selected_items_info (true);\n\n  if (infos.length () > 0 && infos.first ().isDir ())\n    process_set_current_dir (infos.first ().absoluteFilePath ());\n}\n\nvoid\nfile_system_browser::contextmenu_add_to_path (bool, bool rm, bool subdirs)\n{\n  QList<QFileInfo> infos = get_selected_items_info (true);\n\n  QStringList dir_list;\n\n  for (int i = 0; i < infos.length (); i++)\n    dir_list.append (infos.at (i).absoluteFilePath ());\n\n  if (infos.length () > 0)\n    Q_EMIT modify_path_signal (dir_list, rm, subdirs);\n}\n\nvoid\nfile_system_browser::contextmenu_add_to_path_subdirs (bool)\n{\n  contextmenu_add_to_path (true, false, true);\n}\n\nvoid\nfile_system_browser::contextmenu_rm_from_path (bool)\n{\n  contextmenu_add_to_path (true, true, false);\n}\n\nvoid\nfile_system_browser::contextmenu_rm_from_path_subdirs (bool)\n{\n  contextmenu_add_to_path (true, true, true);\n}\n\nvoid\nfile_system_browser::contextmenu_findfiles (bool)\n{\n  QItemSelectionModel *m = m_file_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  if (rows.size () > 0)\n    {\n      QModelIndex index = rows[0];\n\n      QFileInfo info = m_file_system_model->fileInfo (index);\n\n      if (info.isDir ())\n        {\n          process_find_files (info.absoluteFilePath ());\n        }\n    }\n}\n\nvoid\nfile_system_browser::notice_settings ()\n{\n  gui_settings settings;\n\n  if (m_first)\n    m_first = false;\n  else\n    {\n      // Save current state in case some settings are messing up the state\n      settings.setValue (fb_column_state.settings_key (),\n                         m_file_tree_view->header ()->saveState ());\n      settings.sync ();\n    }\n\n  QDir::Filters current_filter = m_file_system_model->filter ();\n  if (settings.value (m_columns_shown_keys.at (3), false).toBool ())\n    m_file_system_model->setFilter (current_filter | QDir::Hidden);\n  else\n    m_file_system_model->setFilter (current_filter & (~QDir::Hidden));\n\n  m_file_tree_view->setAlternatingRowColors\n    (settings.value (m_columns_shown_keys.at (4), true).toBool ());\n  m_file_tree_view->setModel (m_file_system_model);\n\n  // Done if only settings changed by toggle:header were requested\n  if (m_header_settings_only)\n    {\n      m_header_settings_only = false;\n      return;\n    }\n\n  int size_idx = settings.int_value (global_icon_size);\n  size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2\n\n  QStyle *st = style ();\n  int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);\n  m_navigation_tool_bar->setIconSize (QSize (icon_size, icon_size));\n\n  // enable the buttons to sync octave/browser dir\n  // only if this is not done by default\n  m_sync_octave_dir\n    = settings.bool_value (fb_sync_octdir);\n  m_sync_octave_directory_action->setEnabled (! m_sync_octave_dir);\n  m_sync_browser_directory_action->setEnabled (! m_sync_octave_dir);\n\n  // If m_sync_octave_dir is enabled, then we want the file browser to\n  // update to match the current working directory of the\n  // interpreter.  We don't want to queue any signal to change the\n  // interpreter's current working directory.  In this case, we just\n  // want the GUI to match the state of the interpreter.\n\n  if (m_sync_octave_dir)\n    do_sync_browser_directory ();\n\n  // Initialize column order, visibility and width of the file browser.  From this post,\n  // https://www.qtcentre.org/threads/26675-QTableView-saving-restoring-columns-widths\n  // this might fail if done directly after other actions.  This effect shows\n  // up in the GUI since Qt 6.6.x.  As a solution, the following timer ensures\n  // that the header is restored when the event loop is idle.\n\n  QTimer::singleShot (0, this, SLOT(restore_header_state ()));\n}\n\nvoid\nfile_system_browser::popdownmenu_home (bool)\n{\n  QString dir = QString::fromStdString (sys::env::get_home_directory ());\n\n  if (dir.isEmpty ())\n    dir = QDir::homePath ();\n\n  set_current_directory (dir);\n}\n\nvoid\nfile_system_browser::popdownmenu_search_dir (bool)\n{\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n  int opts = QFileDialog::ShowDirsOnly;\n\n  gui_settings settings;\n\n  if (! settings.bool_value (global_use_native_dialogs))\n    opts |= QFileDialog::DontUseNativeDialog;\n\n  QString dir = QFileDialog::getExistingDirectory (this,\n                  tr (\"Set directory of file browser\"),\n                  m_file_system_model->rootPath (),\n                  QFileDialog::Option (opts));\n  set_current_directory (dir);\n}\n\nvoid\nfile_system_browser::popdownmenu_findfiles (bool)\n{\n  process_find_files (m_file_system_model->rootPath ());\n}\n\nvoid\nfile_system_browser::popdownmenu_newdir (bool)\n{\n  process_new_dir (m_file_system_model->rootPath ());\n}\n\nvoid\nfile_system_browser::popdownmenu_newfile (bool)\n{\n  process_new_file (m_file_system_model->rootPath ());\n}\n\nvoid\nfile_system_browser::process_new_file (const QString& parent_dir)\n{\n  bool ok;\n\n  QString name = QInputDialog::getText (this, tr (\"Create File\"),\n                                        tr (\"Create file in\\n\", \"String ends with \\\\n!\") + parent_dir,\n                                        QLineEdit::Normal,\n                                        tr (\"New File.txt\"), &ok);\n  if (ok && name.length () > 0)\n    {\n      name = parent_dir + '/' + name;\n\n      QFile file (name);\n      if (! file.open (QIODevice::ReadWrite))\n        {\n          QMessageBox::warning (this, tr (\"Create File error\"),\n                                tr (\"Could not create file\\n\\\"%1\\\".\").\n                                arg (name));\n        }\n\n      m_file_system_model->revert ();\n    }\n}\n\nvoid\nfile_system_browser::process_new_dir (const QString& parent_dir)\n{\n  bool ok;\n\n  QString name = QInputDialog::getText (this, tr (\"Create Directory\"),\n                                        tr (\"Create folder in\\n\", \"String ends with \\\\n!\") + parent_dir,\n                                        QLineEdit::Normal,\n                                        tr (\"New Directory\"), &ok);\n  if (ok && name.length () > 0)\n    {\n      QDir dir (parent_dir);\n      dir.mkdir (name);\n      m_file_system_model->revert ();\n    }\n}\n\nvoid\nfile_system_browser::process_set_current_dir (const QString& dir)\n{\n  Q_EMIT displayed_directory_changed (dir);\n}\n\nvoid\nfile_system_browser::process_find_files (const QString& dir)\n{\n  Q_EMIT find_files_signal (dir);\n}\n\nvoid\nfile_system_browser::copyClipboard ()\n{\n  if (m_file_tree_view->hasFocus ())\n    contextmenu_copy_selection (true);\n  if (m_current_directory->hasFocus ())\n    {\n      QClipboard *clipboard = QApplication::clipboard ();\n\n      QLineEdit *edit = m_current_directory->lineEdit ();\n      if (edit && edit->hasSelectedText ())\n        {\n          clipboard->setText (edit->selectedText ());\n        }\n    }\n}\n\nvoid\nfile_system_browser::pasteClipboard ()\n{\n  if (m_current_directory->hasFocus ())\n    {\n      QClipboard *clipboard = QApplication::clipboard ();\n      QString str = clipboard->text ();\n      QLineEdit *edit = m_current_directory->lineEdit ();\n      if (edit && str.length () > 0)\n        edit->insert (str);\n    }\n}\n\nvoid\nfile_system_browser::selectAll ()\n{\n  if (m_file_tree_view->hasFocus ())\n    m_file_tree_view->selectAll ();\n  if (m_current_directory->hasFocus ())\n    {\n      QLineEdit *edit = m_current_directory->lineEdit ();\n      if (edit)\n        {\n          edit->selectAll ();\n        }\n    }\n}\n\n\n\n// ----------------------------------------------------------------------\n//  Class for the editor files browser\n\neditor_files_browser::editor_files_browser (QWidget *p)\n  : QWidget (p)\n{\n  m_editor_files_model = new QStandardItemModel (this);\n  QStringList header_text;\n  header_text.append (tr (\"Open Editor Files\"));\n\n  m_editor_files_model->setHorizontalHeaderLabels (header_text);\n\n  m_file_icon_provider = new cache_file_icon_provider ();\n\n  m_parent_item = m_editor_files_model->invisibleRootItem();\n\n  m_home_dir = QString::fromStdString (sys::env::get_home_directory ());\n\n  // Attach the model to the QTreeView and set the root index\n  m_editor_tree_view = new QTreeView (this);\n  m_editor_tree_view->setModel (m_editor_files_model);\n  m_editor_tree_view->setTextElideMode (Qt::ElideMiddle);\n  m_editor_tree_view->setSortingEnabled (true);\n  m_editor_tree_view->setAlternatingRowColors (true);\n  m_editor_tree_view->setAnimated (false);\n  m_editor_tree_view->setToolTip (tr (\"Click to focus file in editor\"));\n\n  connect (m_editor_tree_view, &QTreeView::clicked, this,\n           &editor_files_browser::clicked);\n\n  // add context menu to tree_view\n  m_editor_tree_view->setContextMenuPolicy (Qt::CustomContextMenu);\n  connect (m_editor_tree_view, &editor_files_browser::customContextMenuRequested,\n           this, &editor_files_browser::contextmenu_requested);\n\n  // the layout\n  QVBoxLayout *vbox_layout = new QVBoxLayout ();\n  vbox_layout->setSpacing (0);\n  vbox_layout->addWidget (m_editor_tree_view);\n  vbox_layout->setContentsMargins (1, 1, 1, 1);\n\n  setLayout (vbox_layout);\n}\n\n\n// -------------------------------------------------------------------------\n\nQFileInfo editor_files_browser::get_file_info_from_item (QStandardItem *item)\n{\n  if (! item)\n    return QFileInfo ();\n\n  QString file;\n  QString dir = item->text ();\n\n  if (! item->hasChildren ())\n    {\n      // item is a file\n      file = dir;\n      dir = item->parent ()->text ();\n    }\n\n  dir.replace (QRegularExpression (\"^~\"), m_home_dir);\n\n  return QFileInfo (QDir (dir), file);\n}\n\n\n// -------------------------------------------------------------------------\n\nQStringList editor_files_browser::get_dir_file_from_string (const QString& path)\n{\n  QStringList dir_and_file;\n\n  if (! path.isEmpty ())\n    {\n      QFileInfo f_info (path);\n      QString dir = f_info.absoluteDir ().absolutePath ();\n      dir.replace (QRegularExpression (\"^\" + m_home_dir), \"~\");\n\n      dir_and_file.append (dir);\n      dir_and_file.append (f_info.fileName ());\n    }\n\n  return dir_and_file;\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::contextmenu_requested (const QPoint& mpos)\n{\n  QMenu menu (this);\n\n  QModelIndex index = m_editor_tree_view->indexAt (mpos);\n\n  if (index.isValid ())\n    {\n      QItemSelectionModel *m = m_editor_tree_view->selectionModel ();\n      QModelIndexList sel = m->selectedRows ();\n\n       m->setCurrentIndex (index,\n                           QItemSelectionModel::Clear\n                           | QItemSelectionModel::Select\n                           | QItemSelectionModel::Rows);\n\n      QModelIndexList rows = m->selectedRows ();\n\n      if (rows.isEmpty ())\n        return;\n\n      QStandardItem *item = m_editor_files_model->itemFromIndex (rows[0]);\n      QFileInfo info = get_file_info_from_item (item);\n\n      gui_settings settings;\n\n      // close actions\n      menu.addAction (settings.icon (\"window-close\"), tr (\"&Close\"),\n                      this, &editor_files_browser::ctx_menu_close);\n\n      menu.addAction (settings.icon (\"window-close\"), tr (\"Close &All\"),\n                      this, &editor_files_browser::ctx_menu_close_all);\n\n      // run action\n      if (info.isFile () && info.suffix () == \"m\")\n        {\n          menu.addSeparator ();\n          menu.addAction (settings.icon (\"system-run\"), tr (\"Run\"),\n                          this, &editor_files_browser::ctx_menu_run);\n        }\n\n      // set current dir, if directory\n      if (info.isDir ())\n        {\n          menu.addSeparator ();\n          menu.addAction (settings.icon (\"go-first\"), tr (\"Set Current &Directory\"),\n                          this, &editor_files_browser::ctx_menu_setcurrentdir);\n        }\n\n      menu.exec (m_editor_tree_view->mapToGlobal (mpos));\n    }\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::clicked (const QModelIndex& index)\n{\n  QStandardItem *item = m_editor_files_model->itemFromIndex (index);\n\n  if (item->hasChildren ())\n    return;     // directory clicked, nothing to do\n\n  QFileInfo file = get_file_info_from_item (item);\n  Q_EMIT focus_editor_file_signal (file.absoluteFilePath ());\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::add_editor_file (const QString& file)\n{\n  QStringList f = get_dir_file_from_string (file);\n\n  if (f.isEmpty ())\n    return;\n\n  QString dir_name = f[0];\n  QString file_name = f[1];\n\n  QStandardItem *dir_item;\n\n  QList<QStandardItem *> dir_items = m_editor_files_model->findItems (dir_name);\n  if (dir_items.isEmpty ())\n    {\n      // The directory does not yet exist\n      dir_item =\n          new QStandardItem (m_file_icon_provider->icon (QFileIconProvider::Folder), dir_name);\n      dir_item->setEditable (false);\n      m_parent_item->appendRow(dir_item);\n    }\n  else\n    dir_item = dir_items[0];  // The directory does already exist\n\n  m_editor_tree_view->expand (dir_item->index ());  // expand file's directory\n\n  QStandardItem *file_item =\n      new QStandardItem (m_file_icon_provider->icon (QFileIconProvider::File), file_name);\n  file_item->setEditable (false);\n  dir_item->appendRow(file_item);   // add file item\n\n  m_parent_item->sortChildren (0);\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::rename_editor_file (const QString& file,\n                                               const QString& newfile)\n{\n  if (file.isEmpty ())\n    {\n      add_editor_file (newfile);\n      return;\n    }\n\n  QStringList f = get_dir_file_from_string (file);\n\n  if (f.isEmpty ())\n    return;\n\n  QString dir_name = f[0];\n  QString file_name = f[1];\n\n  QStandardItem *dir_item;\n\n  QList<QStandardItem *> dir_items = m_editor_files_model->findItems (dir_name);\n    if (! dir_items.isEmpty ())\n    {\n      dir_item = dir_items[0];\n      int i = 0;\n      for (i = 0; i < dir_item->rowCount (); i++)\n        {\n          if (dir_item->child(i)->text () == file_name)\n            {\n              if (newfile.isEmpty())\n                {\n                  dir_item->removeRow (i);\n                  if (! dir_item->hasChildren ())\n                    {\n                      m_parent_item->removeRow (dir_item->row ());\n                      break;  // dir_item does point to a valid object anymore\n                    }\n                }\n              else\n                {\n                  QFileInfo new_f_info (newfile);\n                  dir_item->child(i)->setText (new_f_info.fileName ());\n                }\n            }\n        }\n    }\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::remove_editor_file (const QString& file)\n{\n  rename_editor_file (file, QString ());\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::ctx_menu_close (bool)\n{\n  QItemSelectionModel *m = m_editor_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  if (rows.isEmpty ())\n    return;\n\n  QStringList files_to_remove;\n\n  QStandardItem *item = m_editor_files_model->itemFromIndex (rows[0]);\n  if (item->hasChildren ())\n    {\n      for (int i = 0; i < item->rowCount (); i++)\n        {\n          files_to_remove.append (get_file_info_from_item (item->child (i)).\n                                  absoluteFilePath ());\n        }\n    }\n  else\n    {\n      files_to_remove.append (get_file_info_from_item (item).absoluteFilePath ());\n    }\n\n  Q_EMIT close_editor_file_signal (files_to_remove);\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::ctx_menu_close_all (bool)\n{\n  QStringList files_to_remove;\n  QStandardItem *item;\n\n  for (int i = 0; i < m_parent_item->rowCount (); i++)\n    {\n      item = m_parent_item->child (i);\n      for (int j = 0; j < item->rowCount (); j++)\n        {\n          files_to_remove.append (get_file_info_from_item (item->child (j)).\n                                  absoluteFilePath ());\n        }\n    }\n\n  Q_EMIT close_editor_file_signal (files_to_remove);\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::ctx_menu_run (bool)\n{\n  QItemSelectionModel *m = m_editor_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  if (rows.isEmpty ())\n    return;\n\n  QStandardItem *item = m_editor_files_model->itemFromIndex (rows[0]);\n  QFileInfo info = get_file_info_from_item (item);\n\n  Q_EMIT run_file_signal (info, ED_RUN_FILE);\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::ctx_menu_setcurrentdir (bool)\n{\n  QItemSelectionModel *m = m_editor_tree_view->selectionModel ();\n  QModelIndexList rows = m->selectedRows ();\n\n  if (rows.isEmpty ())\n    return;\n\n  QStandardItem *item = m_editor_files_model->itemFromIndex (rows[0]);\n  QFileInfo info = get_file_info_from_item (item);\n\n  if (info.isDir ())\n    Q_EMIT displayed_directory_changed (info.absoluteFilePath ());\n}\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::save_settings ()\n{ }\n\n\n// -------------------------------------------------------------------------\n\nvoid editor_files_browser::notice_settings ()\n{ }\n\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/files-dock-widget.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_files_dock_widget_h)\n#define octave_files_dock_widget_h 1\n\n#include <QAction>\n#include <QComboBox>\n#include <QDate>\n#include <QFileIconProvider>\n#include <QFileSystemModel>\n#include <QList>\n#include <QListView>\n#include <QListWidget>\n#include <QMouseEvent>\n#include <QObject>\n#include <QSignalMapper>\n#include <QStandardItemModel>\n#include <QToolBar>\n#include <QToolButton>\n#include <QTreeView>\n#include <QVBoxLayout>\n#include <QWidget>\n\n#include \"octave-dock-widget.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n\n\n//!  Tab widget for file system browser\n\nclass file_system_browser : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  file_system_browser (QWidget *parent);\n\n  ~file_system_browser () = default;\n\nQ_SIGNALS:\n\n  //! Emitted, whenever the user requested to open a file.\n\n  void open_file (const QString& fileName);\n\n  //! Emitted, whenever the currently displayed directory changed.\n\n  void displayed_directory_changed (const QString& dir);\n\n  //! Emitted, whenever the user requested to load a file in the text editor.\n\n  void load_file_signal (const QString& fileName);\n\n  //! Emitted, whenever the user requested to open an unknown type file.\n\n  void open_any_signal (const QString& fileName);\n\n  //! Emitted, whenever the user requested to run a file.\n\n  void run_file_signal (const QFileInfo& info, int ops);\n\n  //! Emitted, whenever wants to search for a file .\n\n  void find_files_signal (const QString& startdir);\n\n  //! Emitted, whenever the user removes or renames a file.\n\n  void file_remove_signal (const QString& old_name, const QString& new_name);\n\n  //! Emitted, when a file or directory is renamed.\n\n  void file_renamed_signal (bool);\n\n  //! Emitted, when the path has to be modified\n\n  void modify_path_signal (const QStringList& dir_list, bool rm,\n                           bool subdirs);\n\npublic Q_SLOTS:\n\n  //! Slot for handling a change in directory via double click.\n\n  void item_double_clicked (const QModelIndex& index);\n\n  //! Slot for handling the up-directory button in the toolbar.\n\n  void change_directory_up ();\n\n  //! Slot for handling the sync octave directory button in the toolbar.\n\n  void do_sync_octave_directory ();\n\n  //! Slot for handling the sync browser directory button in the toolbar.\n\n  void do_sync_browser_directory ();\n\n  //! Sets the current directory being displayed.\n\n  void set_current_directory (const QString& dir);\n\n  //! Accepts user input a the line edit for the current directory.\n\n  void accept_directory_line_edit ();\n\n  //! Set the internal variable that holds the actual octave variable.\n\n  void update_octave_directory (const QString& dir);\n\n  //! Tells the widget to react on changed settings.\n\n  void notice_settings ();\n\n  void save_settings ();\n\nprivate Q_SLOTS:\n\n  void restore_header_state ();\n  void headercontextmenu_requested (const QPoint& pos);\n  void toggle_header (int col);\n\n  //! Context menu wanted.\n\n  void contextmenu_requested (const QPoint& pos);\n\n  //! Context menu actions.\n  //!@{\n  void contextmenu_open (bool);\n  void contextmenu_open_in_editor (bool);\n  void contextmenu_open_in_app (bool);\n  void contextmenu_copy_selection (bool);\n  void contextmenu_run (bool);\n  void contextmenu_load (bool);\n  void contextmenu_rename (bool);\n  void contextmenu_delete (bool);\n  void contextmenu_newfile (bool);\n  void contextmenu_newdir (bool);\n  void contextmenu_setcurrentdir (bool);\n  void contextmenu_add_to_path (bool, bool rm=false, bool subdirs=false);\n  void contextmenu_add_to_path_subdirs (bool);\n  void contextmenu_rm_from_path (bool);\n  void contextmenu_rm_from_path_subdirs (bool);\n  void contextmenu_findfiles (bool);\n  //!@}\n\n  //! Popdown menu options.\n  //!@{\n  void popdownmenu_newfile (bool);\n  void popdownmenu_newdir (bool);\n  void popdownmenu_search_dir (bool);\n  void popdownmenu_findfiles (bool);\n  void popdownmenu_home (bool);\n  //!@}\n\n  //! Inherited from octave_doc_widget.\n  //!@{\n  void copyClipboard ();\n  void pasteClipboard ();\n  void selectAll ();\n  //!@}\n\nprivate:\n\n  bool m_first;\n  bool m_header_settings_only;\n\n  //! Get currently selected QFileInfo object.\n\n  QList<QFileInfo> get_selected_items_info (bool);\n\n  //! Process new file/directory actions\n\n  void process_new_file (const QString& parent_name);\n  void process_new_dir (const QString& parent_name);\n\n  //! Process setting current dir or find in files\n\n  void process_set_current_dir (const QString& parent_name);\n  void process_find_files (const QString& dir_name);\n\n  //! set a new directory or open a file\n\n  void display_directory (const QString& dir, bool set_octave_dir = true);\n\n  void open_item_in_app (const QModelIndex& index);\n\n  //! Variables for the actions\n\n  QToolBar *m_navigation_tool_bar;\n  QAction *m_sync_octave_directory_action;\n  QAction *m_sync_browser_directory_action;\n  QAction *m_rename_action;\n\n  //! The file system model.\n\n  QFileSystemModel *m_file_system_model;\n  QFileIconProvider *m_file_icon_provider;\n\n  //! The file system view.\n  //!@{\n  QTreeView *m_file_tree_view;\n  QComboBox *m_current_directory;\n  //!@}\n\n  //! Flag if syncing with Octave.\n\n  bool m_sync_octave_dir;\n\n  //! The actual Octave directory.\n\n  QString m_octave_dir;\n\n  enum { MaxMRUDirs = 10 };\n\n  QStringList m_columns_shown;\n  QStringList m_columns_shown_keys;\n  QList<QVariant> m_columns_shown_defs;\n  QSignalMapper *m_sig_mapper;\n};\n\n\n\n//!  Tab widget to display edtior files\n\nclass editor_files_browser : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  editor_files_browser (QWidget *parent);\n\n  ~editor_files_browser () = default;\n\nQ_SIGNALS:\n\n  void focus_editor_file_signal (const QString& file);\n\n  void close_editor_file_signal (const QStringList& files_to_remove);\n\n  void run_file_signal (const QFileInfo& info, int ops);\n\n  void displayed_directory_changed (const QString& dir);\n\npublic Q_SLOTS:\n\n  void rename_editor_file (const QString& old_file,\n                           const QString& new_file = QString ());\n  void remove_editor_file (const QString& fname);\n\n  void contextmenu_requested (const QPoint& pos);\n\n  void clicked (const QModelIndex &index);\n\n  void notice_settings ();\n  void save_settings ();\n\nprivate Q_SLOTS:\n\n  void ctx_menu_close (bool);\n  void ctx_menu_close_all (bool);\n  void ctx_menu_run (bool);\n  void ctx_menu_setcurrentdir (bool);\n\nprivate:\n\n  QFileInfo get_file_info_from_item (QStandardItem *item);\n\n  QStringList get_dir_file_from_string (const QString& path);\n\n  void add_editor_file (const QString& fname);\n\n  QString m_home_dir;\n  QStandardItemModel *m_editor_files_model;\n  QTreeView *m_editor_tree_view;\n  QStandardItem *m_parent_item;\n  QFileIconProvider *m_file_icon_provider;\n};\n\n\n\n//!  Dock widget to display files in the current directory\n//!  and/or opened in the edtor\n\nclass files_dock_widget : public octave_dock_widget\n{\n  Q_OBJECT\n\npublic:\n\n  files_dock_widget (QWidget *parent);\n\n  ~files_dock_widget () = default;\n\n  file_system_browser *get_file_system_browser (void) {return m_file_browser;};\n  editor_files_browser *get_editor_files_browser (void) {return m_editor_files;};\n\npublic Q_SLOTS:\n\n  //! Tells the widget to react on changed settings.\n\n  void notice_settings ();\n\n  void save_settings ();\n\nprivate:\n\n  file_system_browser *m_file_browser;\n  editor_files_browser *m_editor_files;\n};\n\n\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/find-files-dialog.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QCheckBox>\n#include <QDialogButtonBox>\n#include <QDirIterator>\n#include <QFileDialog>\n#include <QFileInfo>\n#include <QGridLayout>\n#include <QGroupBox>\n#include <QHeaderView>\n#include <QIcon>\n#include <QLabel>\n#include <QLineEdit>\n#include <QPushButton>\n#include <QStatusBar>\n#include <QTableView>\n#include <QTextStream>\n#include <QTimer>\n\n#include \"find-files-dialog.h\"\n#include \"find-files-model.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-ff.h\"\n#include \"gui-settings.h\"\n#include \"gui-utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nfind_files_dialog::find_files_dialog (QWidget *p)\n  : QDialog (p)\n{\n  gui_settings settings;\n\n  setWindowTitle (tr (\"Find Files\"));\n  setWindowIcon (settings.icon (\"edit-find\"));\n\n  m_dir_iterator = nullptr;\n\n  m_timer = new QTimer (this);\n  connect (m_timer, &QTimer::timeout,\n           this, &find_files_dialog::look_for_files);\n\n  QLabel *file_name_label = new QLabel (tr (\"Named:\"));\n  m_file_name_edit = new QComboBox;\n  m_file_name_edit->setToolTip (tr (\"Enter the filename search patterns.\\n\"\n                                    \"Several different patterns can be\\n\"\n                                    \"separated by ';', e.g., '*.cc ; *.h'\"));\n  m_file_name_edit->setEditable (true);\n  m_file_name_edit->setMaxCount (m_mru_length);\n\n//  m_file_name_edit->setItemText (0, settings.string_value (ff_file_name));\n  file_name_label->setBuddy (m_file_name_edit);\n\n  QStringList mru = settings.value (ff_file_name.settings_key ()).toStringList ();\n  while (mru.length () > m_mru_length)\n    mru.removeLast ();\n  m_file_name_edit->addItems (mru);\n\n  QLabel *start_dir_label = new QLabel (tr (\"Start in:\"));\n\n  m_start_dir_edit = new QComboBox;\n  m_start_dir_edit->setEditable (true);\n  m_start_dir_edit->setMaxCount (m_mru_length);\n  m_start_dir_edit->setToolTip (tr (\"Enter the start directory\"));\n  start_dir_label->setBuddy (m_start_dir_edit);\n\n  mru = settings.value (ff_start_dir.settings_key ()).toStringList ();\n  while (mru.length () > m_mru_length)\n    mru.removeLast ();\n  m_start_dir_edit->addItems (mru);\n\n  m_browse_button = new QPushButton (tr (\"Browse...\"));\n  m_browse_button->setToolTip (tr (\"Browse for start directory\"));\n  connect (m_browse_button, &QPushButton::clicked,\n           this, &find_files_dialog::browse_folders);\n\n  m_current_dir_button = new QPushButton (tr (\"Current Dir\"));\n  m_current_dir_button->setToolTip (tr (\"Set start directory to current directory\"));\n  connect (m_current_dir_button, &QPushButton::clicked,\n           this, &find_files_dialog::start_dir_to_cwd);\n\n  m_recurse_dirs_check = new QCheckBox (tr (\"Search subdirectories\"));\n  m_recurse_dirs_check->setToolTip (tr (\"Search recursively through directories for matching files\"));\n  m_recurse_dirs_check->setChecked (settings.bool_value (ff_recurse_dirs));\n\n  m_include_dirs_check = new QCheckBox (tr (\"Include directory names\"));\n  m_include_dirs_check->setToolTip (tr (\"Include matching directories in search results\"));\n  m_include_dirs_check->setChecked (settings.bool_value (ff_include_dirs));\n\n  m_name_case_check = new QCheckBox (tr (\"Ignore case\"));\n  m_name_case_check->setToolTip (tr (\"Perform case insensitive match\"));\n  m_name_case_check->setChecked (settings.bool_value (ff_name_case));\n\n  m_contains_text_check = new QCheckBox (tr (\"Contains text:\"));\n  m_contains_text_check->setToolTip (tr (\"Include only files containing specified text in search results\"));\n  m_contains_text_check->setChecked (settings.bool_value (ff_check_text));\n\n  m_contains_text_edit = new QComboBox ();\n  m_contains_text_edit->setEditable (true);\n  m_contains_text_edit->setMaxCount (m_mru_length);\n  m_contains_text_edit->setToolTip (tr (\"Text to match\"));\n\n  mru = settings.value (ff_contains_text.settings_key ()).toStringList ();\n  while (mru.length () > m_mru_length)\n    mru.removeLast ();\n  m_contains_text_edit->addItems (mru);\n\n  m_content_case_check = new QCheckBox (tr (\"Ignore case\"));\n  m_content_case_check->setToolTip (tr (\"Perform case insensitive match\"));\n  m_content_case_check->setChecked (settings.bool_value (ff_content_case));\n\n  find_files_model *model = new find_files_model (this);\n  connect (model, &find_files_model::rowsInserted,\n           this, &find_files_dialog::handle_rows_inserted);\n\n  m_file_list = new QTableView;\n  m_file_list->setWordWrap (false);\n  m_file_list->setModel (model);\n  m_file_list->setShowGrid (false);\n  m_file_list->setSelectionBehavior (QAbstractItemView::SelectRows);\n  m_file_list->setSelectionMode (QAbstractItemView::SingleSelection);\n  m_file_list->setAlternatingRowColors (true);\n  m_file_list->setSortingEnabled (true);\n  m_file_list->horizontalHeader ()->restoreState (settings.value (ff_column_state.settings_key ()).toByteArray ());\n  m_file_list->horizontalHeader ()->setSortIndicatorShown (true);\n  m_file_list->horizontalHeader ()->setSectionsClickable (true);\n  m_file_list->horizontalHeader ()->setStretchLastSection (true);\n  m_file_list->horizontalHeader ()->setSectionsMovable (true);\n  m_file_list->sortByColumn (settings.int_value (ff_sort_files_by_column),\n                             static_cast<Qt::SortOrder>\n                             (settings.uint_value (ff_sort_files_by_order)));\n  // FIXME: use value<Qt::SortOrder> instead of static cast after\n  //        dropping support of Qt 5.4\n\n  connect (m_file_list, &QTableView::doubleClicked,\n           this, &find_files_dialog::item_double_clicked);\n\n  m_status_bar = new QStatusBar;\n  m_status_bar->showMessage (tr (\"Idle.\"));\n\n  m_find_button = new QPushButton (tr (\"Find\"));\n  m_find_button->setToolTip (tr (\"Start search for matching files\"));\n  connect (m_find_button, &QPushButton::clicked,\n           this, &find_files_dialog::start_find);\n\n  m_stop_button = new QPushButton (tr (\"Stop\"));\n  m_stop_button->setToolTip (tr (\"Stop search\"));\n  m_stop_button->setEnabled (false);\n  connect (m_stop_button, &QPushButton::clicked,\n           this, &find_files_dialog::stop_find);\n\n  // layout everything\n  QDialogButtonBox *button_box = new QDialogButtonBox (Qt::Vertical);\n  button_box->addButton (m_find_button, QDialogButtonBox::ActionRole);\n  button_box->addButton (m_stop_button, QDialogButtonBox::ActionRole);\n\n  // add dialog close button\n  m_close_button = button_box->addButton (QDialogButtonBox::Close);\n  connect (button_box, &QDialogButtonBox::rejected,\n           this, &find_files_dialog::close);\n\n  // name options\n  const QString gbox_style_sheet (\"QGroupBox { font-weight: bold; } \");\n  QGroupBox *name_group = new QGroupBox (tr (\"Filename/Location\"));\n  name_group->setStyleSheet(gbox_style_sheet);\n  QGridLayout *name_layout = new QGridLayout;\n\n  name_group->setLayout (name_layout);\n\n  name_layout->addWidget (file_name_label, 0, 0, 1, 1);\n  name_layout->addWidget (m_file_name_edit, 0, 1, 1, 3);\n\n  name_layout->addWidget (start_dir_label, 1, 0);\n  name_layout->addWidget (m_start_dir_edit, 1, 1, 1, 2);\n  name_layout->addWidget (m_browse_button, 1, 3, 1, 1);\n  name_layout->addWidget (m_current_dir_button, 2, 3, 1, 1);\n  name_layout->setColumnStretch (1, 1);\n\n  QHBoxLayout *name_options_layout = new QHBoxLayout;\n  name_options_layout->addWidget (m_recurse_dirs_check);\n  name_options_layout->addWidget (m_include_dirs_check);\n  name_options_layout->addWidget (m_name_case_check);\n  name_layout->addLayout (name_options_layout, 2, 0, 1, 2);\n\n  // content options\n  QGroupBox *content_group = new QGroupBox (tr (\"File contents\"));\n  content_group->setStyleSheet(gbox_style_sheet);\n  QGridLayout *content_layout = new QGridLayout;\n  content_group->setLayout (content_layout);\n  content_layout->addWidget (m_contains_text_check, 0, 0, 1, 1);\n  content_layout->addWidget (m_contains_text_edit, 0, 1, 1, 1);\n  content_layout->setColumnStretch (1, 1);\n  content_layout->addWidget (m_content_case_check, 0, 2, 1, 1);\n\n  // results\n  QLabel *results_hint = new QLabel (tr (\"Results: Double click opens the file\"\n                                         \" or sets the directory\"));\n  QGroupBox *results_group = new QGroupBox (tr (\"Search results\"));\n  results_group->setStyleSheet(gbox_style_sheet);\n  QVBoxLayout *results_layout = new QVBoxLayout ();\n  results_group->setLayout (results_layout);\n  results_layout->addWidget (results_hint);\n  results_layout->addWidget (m_file_list);\n\n  // main layout\n  QGridLayout *main_layout = new QGridLayout;\n  main_layout->addWidget (name_group, 0, 0);\n  main_layout->addWidget (content_group, 1, 0);\n  main_layout->addWidget (button_box, 0, 1, 3, 1);\n  main_layout->addWidget (results_group, 2, 0);\n  main_layout->setRowStretch (2, 1);\n  main_layout->addWidget (m_status_bar, 3, 0, 1, -1);\n\n  setLayout (main_layout);\n\n  connect (this, &find_files_dialog::finished,\n           this, &find_files_dialog::handle_done);\n\n  m_find_button->setFocus(Qt::OtherFocusReason);\n\n  if (settings.contains (ff_geometry.settings_key ()))\n    restoreGeometry (settings.byte_array_value (ff_geometry));\n}\n\nfind_files_dialog::~find_files_dialog ()\n{\n  delete m_dir_iterator;\n}\n\nvoid\nfind_files_dialog::save_settings ()\n{\n  gui_settings settings;\n\n  int sort_column = m_file_list->horizontalHeader ()->sortIndicatorSection ();\n  Qt::SortOrder sort_order\n    = m_file_list->horizontalHeader ()->sortIndicatorOrder ();\n  settings.setValue (ff_sort_files_by_column.settings_key (), sort_column);\n  settings.setValue (ff_sort_files_by_order.settings_key (), sort_order);\n  settings.setValue (ff_column_state.settings_key (), m_file_list->horizontalHeader ()->saveState ());\n\n  settings.setValue (ff_geometry.settings_key (), saveGeometry ());\n\n  settings.setValue (ff_recurse_dirs.settings_key (), m_recurse_dirs_check->text ());\n  settings.setValue (ff_include_dirs.settings_key (), m_include_dirs_check->text ());\n  settings.setValue (ff_name_case.settings_key (), m_name_case_check->text ());\n\n  settings.setValue (ff_check_text.settings_key (), m_contains_text_check->isChecked ());\n  settings.setValue (ff_content_case.settings_key (), m_content_case_check->isChecked ());\n\n  combobox_update (m_file_name_edit, m_mru_length);\n  combobox_update (m_start_dir_edit, m_mru_length);\n  combobox_update (m_contains_text_edit, m_mru_length);\n\n  QStringList mru;\n  for (int i = 0; i < m_file_name_edit->count (); i++)\n    mru.append (m_file_name_edit->itemText (i));\n  settings.setValue (ff_file_name.settings_key (), mru);\n\n  mru.clear ();\n  for (int i = 0; i < m_start_dir_edit->count (); i++)\n    mru.append (m_start_dir_edit->itemText (i));\n  settings.setValue (ff_start_dir.settings_key (), mru);\n\n  mru.clear ();\n  for (int i = 0; i < m_contains_text_edit->count (); i++)\n    mru.append (m_contains_text_edit->itemText (i));\n  settings.setValue (ff_contains_text.settings_key (), mru);\n\n  settings.sync ();\n}\n\nvoid\nfind_files_dialog::set_search_dir (const QString& dir)\n{\n  stop_find ();\n  combobox_insert_current_item (m_start_dir_edit, dir);\n}\n\nvoid\nfind_files_dialog::start_find ()\n{\n  stop_find ();\n\n  combobox_update (m_file_name_edit, m_mru_length);\n  combobox_update (m_start_dir_edit, m_mru_length);\n  combobox_update (m_contains_text_edit, m_mru_length);\n\n  find_files_model *m = static_cast<find_files_model *> (m_file_list->model ());\n  m->clear ();\n\n  QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags;\n  if (m_recurse_dirs_check->isChecked ())\n    flags |= QDirIterator::Subdirectories;\n\n  QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files;\n  if (! m_name_case_check->isChecked ())\n    filters |= QDir::CaseSensitive;\n\n  const QStringList nameFilters =\n    m_file_name_edit->currentText ().split (QRegularExpression(\"\\\\s*;\\\\s*\"),\n#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)\n                                            Qt::SkipEmptyParts);\n#else\n                                            QString::SkipEmptyParts);\n#endif\n\n  if (m_dir_iterator)\n    delete m_dir_iterator;\n\n  m_dir_iterator = new QDirIterator (m_start_dir_edit->currentText (),\n                                     nameFilters, filters, flags);\n\n  // enable/disable widgets\n  m_find_button->setEnabled (false);\n  m_stop_button->setEnabled (true);\n  m_close_button->setEnabled (false);\n  m_browse_button->setEnabled (false);\n  m_current_dir_button->setEnabled (false);\n  m_start_dir_edit->setEnabled (false);\n  m_file_name_edit->setEnabled (false);\n  m_recurse_dirs_check->setEnabled (false);\n  m_include_dirs_check->setEnabled (false);\n  m_name_case_check->setEnabled (false);\n  m_contains_text_check->setEnabled (false);\n  m_content_case_check->setEnabled (false);\n  m_contains_text_edit->setEnabled (false);\n\n  // Fill the data structure with the curren settings, since check boxes and\n  // and search text might be changed afterwards and would not match the\n  // files in the list of matches anymore\n  m_find_files_data.find_in_files = m_contains_text_check->isChecked ();\n  m_find_files_data.case_sensitive = ! m_content_case_check->isChecked ();\n  m_find_files_data.search_text = m_contains_text_edit->currentText ();\n\n  // Start searching\n  m_status_bar->showMessage (tr (\"Searching...\"));\n  m_timer->start (0);\n}\n\nvoid\nfind_files_dialog::stop_find ()\n{\n  m_timer->stop ();\n\n  m_find_button->setEnabled (true);\n  m_stop_button->setEnabled (false);\n  m_close_button->setEnabled (true);\n  m_browse_button->setEnabled (true);\n  m_current_dir_button->setEnabled (true);\n  m_start_dir_edit->setEnabled (true);\n  m_file_name_edit->setEnabled (true);\n  m_recurse_dirs_check->setEnabled (true);\n  m_include_dirs_check->setEnabled (true);\n  m_name_case_check->setEnabled (true);\n  m_contains_text_check->setEnabled (true);\n  m_content_case_check->setEnabled (true);\n  m_contains_text_edit->setEnabled (true);\n\n  find_files_model *m = static_cast<find_files_model *> (m_file_list->model ());\n  int rows = m->rowCount ();\n\n  m_file_list->resizeRowToContents (rows-1);  // Resize last row\n\n  QString res_str = QString (tr (\"%1 match (es)\")).arg (rows);\n  m_status_bar->showMessage (res_str);\n}\n\nvoid\nfind_files_dialog::browse_folders ()\n{\n  int opts = 0;  // No options by default.\n\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n\n  gui_settings settings;\n\n  if (! settings.bool_value (global_use_native_dialogs))\n    opts = QFileDialog::DontUseNativeDialog;\n\n  QString dir =\n    QFileDialog::getExistingDirectory (this, tr (\"Set search directory\"),\n                                       m_start_dir_edit->itemText (0),\n                                       QFileDialog::Option (opts));\n\n  if (! dir.isEmpty ())\n    combobox_insert_current_item  (m_start_dir_edit, dir);\n}\n\nvoid\nfind_files_dialog::start_dir_to_cwd ()\n{\n  combobox_insert_current_item (m_start_dir_edit, QDir::currentPath ());\n}\n\nvoid\nfind_files_dialog::item_double_clicked (const QModelIndex& idx)\n{\n  find_files_model *m = static_cast<find_files_model *> (m_file_list->model ());\n\n  QFileInfo info = m->fileInfo (idx);\n\n  if (idx.column () == 1)\n    {\n      // clicked in directory part\n      Q_EMIT dir_selected (info.absolutePath ());\n    }\n  else\n    {\n      // clicked in filename part\n      if (info.isDir ())\n        Q_EMIT dir_selected (info.absoluteFilePath ());\n      else\n        Q_EMIT file_selected (info.absoluteFilePath (), m_find_files_data);\n    }\n}\n\nvoid\nfind_files_dialog::look_for_files ()\n{\n  if (m_dir_iterator && m_dir_iterator->hasNext ())\n    {\n      QFileInfo info (m_dir_iterator->next ());\n\n      find_files_model *m\n        = static_cast<find_files_model *> (m_file_list->model ());\n\n      if (is_match (info))\n        m->addFile (info);\n    }\n  else\n    {\n      stop_find ();\n    }\n}\n\nvoid\nfind_files_dialog::handle_done (int)\n{\n  // make sure we stopped processing\n  stop_find ();\n}\n\nbool\nfind_files_dialog::is_match (const QFileInfo& info)\n{\n  bool match = true;\n  if (info.isDir ())\n    {\n      if (! m_include_dirs_check->isChecked ()) match = false;\n      if (m_contains_text_check->isChecked ()) match = false;\n    }\n  else\n    {\n      // a file\n      if (m_contains_text_check->isChecked ())\n        {\n          match = false;\n\n          QFile file (info.absoluteFilePath ());\n          if (file.open (QIODevice::ReadOnly))\n            {\n              QTextStream stream (&file);\n\n              QString line;\n              QString match_str = m_contains_text_edit->itemText (0);\n\n              Qt::CaseSensitivity cs = m_content_case_check->isChecked ()\n                                       ? Qt::CaseInsensitive\n                                       : Qt::CaseSensitive;\n\n              do\n                {\n                  line = stream.readLine ();\n                  match = line.contains (match_str, cs);\n                }\n              while (! line.isNull () && match == false);\n            }\n\n        }\n    }\n\n  return match;\n}\n\nvoid find_files_dialog::handle_rows_inserted (const QModelIndex&, int first, int)\n{\n  // Only one row is inserted at a time: This signal is emitted directly after\n  // the (empty) row was inserted but before the row contents is inserted.\n  // The last row is resized after the find process stopped.\n  if (first > 0)\n    m_file_list->resizeRowToContents (first-1);\n}\n\nvoid find_files_dialog::closeEvent (QCloseEvent *e)\n{\n  save_settings ();\n  e->accept ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/find-files-dialog.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n#if ! defined (octave_find_files_dialog_h)\n#define octave_find_files_dialog_h 1\n\n#include <QCloseEvent>\n#include <QComboBox>\n#include <QDialog>\n#include <QFileInfo>\n#include <QModelIndex>\n\nclass QCheckBox;\nclass QDirIterator;\nclass QLineEdit;\nclass QPushButton;\nclass QStatusBar;\nclass QTableView;\nclass QTimer;\n\nstruct find_files_data\n{\n  bool find_in_files {false};\n  QString search_text {QString ()};\n  bool case_sensitive {true};\n};\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass find_files_dialog : public QDialog\n{\n  Q_OBJECT\n\npublic:\n\n  find_files_dialog (QWidget *parent);\n\n  virtual ~find_files_dialog ();\n\n  void save_settings ();\n\nQ_SIGNALS:\n\n  void file_selected (const QString& fileName, const find_files_data& ff_data);\n  void dir_selected (const QString& fileName);\n\npublic Q_SLOTS:\n\n  void set_search_dir (const QString& dir);\n\nprivate Q_SLOTS:\n\n  void start_find ();\n  void stop_find ();\n  void browse_folders ();\n  void start_dir_to_cwd ();\n  void look_for_files ();\n  void item_double_clicked (const QModelIndex&);\n  void handle_done (int);\n  void handle_rows_inserted (const QModelIndex& parent, int first, int last);\n\nprivate:\n\n  // Reimplemented close event\n  void closeEvent (QCloseEvent *e);\n\n  bool is_match (const QFileInfo& info);\n\n  find_files_data m_find_files_data;\n  QComboBox *m_start_dir_edit;\n  QComboBox *m_file_name_edit;\n  QPushButton *m_stop_button;\n  QPushButton *m_find_button;\n  QPushButton *m_close_button;\n  QPushButton *m_browse_button;\n  QPushButton *m_current_dir_button;\n  QTableView *m_file_list;\n  QTimer *m_timer;\n  QCheckBox *m_recurse_dirs_check;\n  QCheckBox *m_include_dirs_check;\n  QCheckBox *m_name_case_check;\n  QCheckBox *m_contains_text_check;\n  QCheckBox *m_content_case_check;\n  QComboBox *m_contains_text_edit;\n  QDirIterator *m_dir_iterator;\n  QStatusBar *m_status_bar;\n\n  const int m_mru_length = 12;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/find-files-model.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n\n#include <QFileIconProvider>\n#include <QtAlgorithms>\n\n#include \"find-files-model.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass find_file_less_than\n{\npublic:\n\n  find_file_less_than (int ord) { m_sortorder = ord; }\n\n  QVariant\n  getValue (const QFileInfo& f) const\n  {\n    QVariant val;\n\n    int col = (m_sortorder > 0) ? m_sortorder : -m_sortorder;\n\n    switch (col-1)\n      {\n      case 0:\n        val = QVariant (f.fileName ());\n        break;\n\n      case 1:\n        val = QVariant (f.absolutePath ());\n        break;\n\n      default:\n        break;\n      }\n\n    return val;\n  }\n\n  bool\n  lessThan (const QVariant& left, const QVariant& right) const\n  {\n    return\n      left.toString ().compare (right.toString (), Qt::CaseInsensitive) < 0;\n  }\n\n  bool\n  operator () (const QFileInfo& left, const QFileInfo& right) const\n  {\n    QVariant leftval = getValue (left);\n    QVariant rightval = getValue (right);\n\n    if (m_sortorder > 0)\n      return lessThan (leftval, rightval);\n    else\n      return ! lessThan (leftval, rightval);\n  }\n\nprivate:\n\n  int m_sortorder;\n};\n\nfind_files_model::find_files_model (QObject *p)\n  : QAbstractListModel (p)\n{\n  m_columnNames.append (tr (\"Filename\"));\n  m_columnNames.append (tr (\"Directory\"));\n  m_sortorder = 0;\n}\n\nvoid\nfind_files_model::clear ()\n{\n  beginResetModel ();\n\n  m_files.clear ();\n\n  endResetModel ();\n}\n\nvoid\nfind_files_model::addFile (const QFileInfo& info)\n{\n  beginInsertRows (QModelIndex (), m_files.size (), m_files.size ());\n\n  QList<QFileInfo>::Iterator it;\n  find_file_less_than less_than (m_sortorder);\n\n  // FIXME: This loop is trying to insert info in a sorted QList.\n  // Is there a library function or data structure\n  // that can do this without a loop?\n  for (it = m_files.begin (); it != m_files.end (); it++)\n    {\n      if (less_than (info, *it))\n        break;\n    }\n\n  m_files.insert (it, info);\n\n  endInsertRows ();\n}\n\nint\nfind_files_model::rowCount (const QModelIndex&) const\n{\n  return m_files.size ();\n}\n\nint\nfind_files_model::columnCount (const QModelIndex&) const\n{\n  return m_columnNames.size ();\n}\n\nQVariant\nfind_files_model::data (const QModelIndex& idx, int role) const\n{\n  QVariant retval;\n\n  if (idx.isValid ())\n    {\n      if (role == Qt::DisplayRole)\n        {\n          switch (idx.column ())\n            {\n            case 0:\n              retval = QVariant (m_files[idx.row ()].fileName ());\n              break;\n\n            case 1:\n              retval = QVariant (m_files[idx.row ()].absolutePath ());\n              break;\n\n            default:\n              break;\n            }\n        }\n      else if (role == Qt::DecorationRole)\n        {\n          switch (idx.column ())\n            {\n            case 0:\n              retval = fileIcon (idx);\n\n            default:\n              break;\n            }\n        }\n      else if (role ==  Qt::ToolTipRole)\n        {\n          switch (idx.column ())\n            {\n            case 0:\n              retval = tr (\"Double click to open the file\");\n              break;\n\n            case 1:\n              retval = tr (\"Double click to set the directory\");\n              break;\n\n            default:\n              break;\n            }\n        }\n\n    }\n\n  return retval;\n}\n\nQVariant\nfind_files_model::headerData (int section,\n                              Qt::Orientation orientation,\n                              int role) const\n{\n  return ((orientation == Qt::Horizontal && role == Qt::DisplayRole)\n          ? m_columnNames[section] : QVariant ());\n}\n\nvoid\nfind_files_model::sort (int column, Qt::SortOrder order)\n{\n  if (column >= 0)\n    {\n      if (order == Qt::DescendingOrder)\n        m_sortorder = -(column+1);\n      else\n        m_sortorder = column+1;\n    }\n  else\n    m_sortorder = 0;\n\n  if (m_sortorder != 0)\n    {\n      beginResetModel ();\n\n      std::sort (m_files.begin (), m_files.end (),\n                 find_file_less_than (m_sortorder));\n\n      endResetModel ();\n    }\n}\n\nQFileInfo\nfind_files_model::fileInfo (const QModelIndex& p) const\n{\n  return p.isValid () ? m_files[p.row ()] : QFileInfo ();\n}\n\nQIcon\nfind_files_model::fileIcon (const QModelIndex& p) const\n{\n  QFileIconProvider icon_provider;\n\n  return p.isValid () ? icon_provider.icon (m_files[p.row ()]) : QIcon ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/find-files-model.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n#if ! defined (octave_find_files_model_h)\n#define octave_find_files_model_h 1\n\n#include <QAbstractListModel>\n#include <QFileInfo>\n#include <QIcon>\n#include <QList>\n#include <QStringList>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass find_files_model : public QAbstractListModel\n{\n  Q_OBJECT\n\npublic:\n\n  find_files_model (QObject *p = nullptr);\n\n  ~find_files_model () = default;\n\n  void clear ();\n\n  void addFile (const QFileInfo& info);\n\n  int rowCount (const QModelIndex& p = QModelIndex ()) const;\n\n  int columnCount (const QModelIndex& p = QModelIndex ()) const;\n\n  QVariant data (const QModelIndex& idx, int role) const;\n\n  QVariant headerData (int section, Qt::Orientation orientation,\n                       int role = Qt::DisplayRole) const;\n\n  void sort (int column, Qt::SortOrder order = Qt::AscendingOrder);\n\n  QFileInfo fileInfo (const QModelIndex& p) const;\n\n  QIcon fileIcon (const QModelIndex& p) const;\n\nprivate:\n\n  QList<QFileInfo> m_files;\n  QStringList m_columnNames;\n  int m_sortorder;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/find-widget.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-settings.h\"\n#include \"gui-preferences-sc.h\"\n#include \"find-widget.h\"\n\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// The documentation splitter, which is the main widget\n// of the doc dock widget\nfind_widget::find_widget (bool x_button, QWidget *p)\n  : QWidget (p),\n    m_is_closeable (x_button),\n    m_find_line_edit (new QLineEdit (this)),\n    m_findnext_shortcut (new QShortcut (this)),\n    m_findprev_shortcut (new QShortcut (this))\n{\n  gui_settings settings;\n\n  QLabel *find_label = new QLabel (tr (\"Find:\"), this);\n\n  m_find_line_edit->setClearButtonEnabled (true);\n\n  connect (m_find_line_edit, &QLineEdit::returnPressed,\n           this, &find_widget::find);\n  connect (m_find_line_edit, &QLineEdit::textEdited,\n           this, &find_widget::find_incremental);\n\n  QToolButton *forward_button = new QToolButton (this);\n  forward_button->setText (tr (\"Search forward\"));\n  forward_button->setToolTip (tr (\"Search forward\"));\n  forward_button->setIcon (settings.icon (\"go-down\"));\n  connect (forward_button, &QToolButton::pressed,\n           this, &find_widget::find);\n\n  QToolButton *backward_button = new QToolButton (this);\n  backward_button->setText (tr (\"Search backward\"));\n  backward_button->setToolTip (tr (\"Search backward\"));\n  backward_button->setIcon (settings.icon (\"go-up\"));\n  connect (backward_button, &QToolButton::pressed,\n           this, &find_widget::find_backward);\n\n  QHBoxLayout *h_box_this = new QHBoxLayout (this);\n  h_box_this->addWidget (find_label);\n  h_box_this->addWidget (m_find_line_edit);\n  h_box_this->addWidget (forward_button);\n  h_box_this->addWidget (backward_button);\n\n  if (x_button)\n    {\n      QToolButton *close_button = new QToolButton (this);\n      close_button->setText (tr (\"Close\"));\n      close_button->setToolTip (tr (\"Close find dialog\"));\n      close_button->setIcon (settings.icon (\"window-close\"));\n      connect (close_button, &QToolButton::pressed,\n               this, [this] () { close (); });\n      h_box_this->addWidget (close_button);\n    }\n\n  h_box_this->setContentsMargins (2, 2, 2, 2);\n  this->setLayout (h_box_this);\n\n  notice_settings ();\n\n  m_findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut);\n  connect (m_findnext_shortcut, &QShortcut::activated,\n           this, &find_widget::find);\n\n  m_findprev_shortcut->setContext (Qt::WidgetWithChildrenShortcut);\n  connect (m_findprev_shortcut, &QShortcut::activated,\n           this, &find_widget::find_backward);\n}\n\nvoid\nfind_widget::activate_find ()\n{\n  if (m_is_closeable && isVisible ())\n    {\n      hide ();\n    }\n  else\n    {\n      show ();\n      m_find_line_edit->selectAll ();\n      m_find_line_edit->setFocus ();\n    }\n}\n\nvoid\nfind_widget::find ()\n{\n  Q_EMIT find_signal (m_find_line_edit->text (), false);\n}\n\nvoid\nfind_widget::find_backward ()\n{\n  Q_EMIT find_signal (m_find_line_edit->text (), true);\n}\n\nvoid\nfind_widget::find_incremental ()\n{\n  Q_EMIT find_incremental_signal (m_find_line_edit->text ());\n}\n\nvoid\nfind_widget::set_text (const QString& text)\n{\n  m_find_line_edit->setText (text);\n}\n\nQString\nfind_widget::text ()\n{\n  return m_find_line_edit->text ();\n}\n\nvoid\nfind_widget::notice_settings ()\n{\n  gui_settings settings;\n\n  settings.shortcut (m_findnext_shortcut, sc_edit_edit_find_next);\n  settings.shortcut (m_findprev_shortcut, sc_edit_edit_find_previous);\n}\n\nvoid\nfind_widget::save_settings ()\n{\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/find-widget.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// ---------------------------------------------------------------------\n//\n//  This class provides a horizontal layout containing a small\n//  find dialog.\n//\n//  Usage:\n//    1. Create widget and include it in the widget's layout\n//    2. Connect to the signals\n//         find_widget::find_signal (const QString& text, bool backward)\n//         find_widget::find_incremental_signal (const QString& text)\n//       for searching forward or backward for \"text\" and for providing\n//       an incremental search while typing\n//    3. Provide suitable actions in the slots of the signals above\n//    4. Call the find widget's methods notice_settings when settings\n//       are updated and save_settings when settings are saved\n//    5. Other methods or slots are\n//        - file_widget::activate_find (): slot for hiding/showing\n//                                         find widget\n//        - file_widget::text (): get current search text\n//        - file_widget::set_text (const QString& text): set search text\n//\n// ---------------------------------------------------------------------\n\n#if ! defined (octave_find_widget_h)\n#define octave_find_widget_h 1\n\n#include <QHBoxLayout>\n#include <QLabel>\n#include <QLineEdit>\n#include <QShortcut>\n#include <QString>\n#include <QToolButton>\n#include <QWidget>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass find_widget : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  // x_button: provide a close button for the widget or not\n  find_widget (bool x_button = true, QWidget *parent = nullptr);\n  ~find_widget () = default;\n\n  QString text (void);\n  void set_text (const QString& text);\n  void notice_settings (void);\n  void save_settings (void);\n\npublic Q_SLOTS:\n\n  void activate_find (void);\n\nprivate Q_SLOTS:\n\n  void find (void);\n  void find_backward (void);\n  void find_incremental (void);\n\nQ_SIGNALS:\n\n  void find_signal (const QString&, bool);\n  void find_incremental_signal (const QString&);\n\nprotected:\n\n\nprivate:\n\n  bool m_is_closeable;\n\n  QLineEdit *m_find_line_edit;\n\n  QShortcut *m_findnext_shortcut;\n  QShortcut *m_findprev_shortcut;\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/graphics-init.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QApplication>\n#include <QMetaType>\n#include <QThread>\n\n#include \"graphics-init.h\"\n#include \"qt-graphics-toolkit.h\"\n#include \"QtHandlesUtils.h\"\n\n#include \"graphics.h\"\n#include \"gtk-manager.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid graphics_init (interpreter& interp)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  autolock guard (gh_mgr.graphics_lock ());\n\n  qRegisterMetaType<graphics_object> (\"graphics_object\");\n\n  gh_mgr.enable_event_processing (true);\n\n  qt_graphics_toolkit *qt_gtk = new qt_graphics_toolkit (interp);\n\n  if (QThread::currentThread ()\n      != QApplication::instance ()->thread ())\n    qt_gtk->moveToThread (QApplication::instance ()->thread ());\n\n  graphics_toolkit tk (qt_gtk);\n\n  gtk_manager& gtk_mgr = interp.get_gtk_manager ();\n\n  gtk_mgr.register_toolkit (\"qt\");\n\n  gtk_mgr.load_toolkit (tk);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/graphics-init.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_graphics_init_h)\n#define octave_graphics_init_h 1\n\n#include <QObject>\n\n#include \"qt-interpreter-events.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nextern void graphics_init (interpreter& interp);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-all.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_all_h)\n#define octave_gui_preferences_all_h 1\n\n#include \"gui-preferences-cs.h\"\n#include \"gui-preferences-dw.h\"\n#include \"gui-preferences-ed.h\"\n#include \"gui-preferences-fb.h\"\n#include \"gui-preferences-ff.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-gp.h\"\n#include \"gui-preferences-hw.h\"\n#include \"gui-preferences-mw.h\"\n#include \"gui-preferences-nr.h\"\n#include \"gui-preferences-pd.h\"\n#include \"gui-preferences-ve.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-preferences-sd.h\"\n#include \"gui-preferences-ws.h\"\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-cs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QPalette>\n\n#include \"gui-preferences-cs.h\"\n#include \"gui-settings.h\"\n\n// Console preferences\n\ngui_pref\ncs_font (\"terminal/fontName\", QVariant ());\n\ngui_pref\ncs_font_size (\"terminal/fontSize\", QVariant (10));\n\ngui_pref\ncs_cursor (\"terminal/cursorType\", QVariant (\"ibeam\"));\n\ngui_pref\ncs_cursor_blinking (\"terminal/cursorBlinking\", QVariant (true));\n\ngui_pref\ncs_cursor_use_fgcol (\"terminal/cursorUseForegroundColor\", QVariant (true));\n\ngui_pref\ncs_hist_buffer (\"terminal/history_buffer\", QVariant (1000));\n\ngui_pref\ncs_color_mode (\"terminal/color_mode\", QVariant (0));\n\ngui_pref cs_colors[2*cs_colors_count] =\n{\n  {\"terminal/color_f\" + settings_color_modes_ext[0], QVariant (QPalette::WindowText)},\n  {\"terminal/color_b\" + settings_color_modes_ext[0], QVariant (QPalette::Base)},\n  {\"terminal/color_s\" + settings_color_modes_ext[0], QVariant (QPalette::Highlight)},\n  {\"terminal/color_c\" + settings_color_modes_ext[0], QVariant (QPalette::QPalette::WindowText)},\n  {\"terminal/color_f\" + settings_color_modes_ext[1], QVariant ()}, // Default colors for 2nd mode empty,\n  {\"terminal/color_b\" + settings_color_modes_ext[1], QVariant ()}, // since they are determined at runtime\n  {\"terminal/color_s\" + settings_color_modes_ext[1], QVariant ()}, // by inverting the lightness of the\n  {\"terminal/color_c\" + settings_color_modes_ext[1], QVariant ()}  // default colors in light mode\n};\n\ngui_pref\ncs_focus_cmd (\"terminal/focus_after_command\", QVariant (false));\n\ngui_pref\ncs_dbg_location (\"terminal/print_debug_location\", QVariant (false));\n"
  },
  {
    "path": "libgui/src/gui-preferences-cs.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_cs_h)\n#define octave_gui_preferences_cs_h 1\n\n#include \"gui-preferences.h\"\n\n// Console preferences\n\nextern gui_pref cs_font;\n\nextern gui_pref cs_font_size;\n\nconst std::vector<std::string> cs_cursor_types =\n{\n  \"ibeam\",\n  \"block\",\n  \"underline\"\n};\n\nextern gui_pref cs_cursor;\n\nextern gui_pref cs_cursor_blinking;\n\nextern gui_pref cs_cursor_use_fgcol;\n\nextern gui_pref cs_hist_buffer;\n\nextern gui_pref cs_color_mode;\n\nconst unsigned int cs_colors_count = 4;\n\nextern gui_pref cs_colors[];\n\nconst QStringList\ncs_color_names =\n{\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Foreground\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Background\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Selection\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Cursor\")\n};\n\nextern gui_pref cs_focus_cmd;\n\nextern gui_pref cs_dbg_location;\n\n// Some constants for the experimental console widget\nconst QColor cs_error_color (Qt::red);\nconst double cs_error_interp[2] = {1.0, 0.4};\nconst double cs_prompt_interp[2] = {0.8, 0.4};\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-dc.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-dc.h\"\n\n// documentation properties\n\ngui_pref\ndc_bookmark_filter_active (\"documentation_widget/filter_active\", QVariant (false));\n\ngui_pref\ndc_bookmark_filter_shown (\"documentation_widget/filter_shown\", QVariant (true));\n\ngui_pref\ndc_bookmark_filter_mru (\"documentation_widget/bookmark_filter_mru\", QVariant ());\n\n// Zoom level\ngui_pref\ndc_browser_zoom_level (\"documentation_widget/browser_zoom_level\", QVariant (0));\n\n// Splitter state\ngui_pref\ndc_splitter_state (\"documentation_widget/splitter_state\", QVariant (0));\n"
  },
  {
    "path": "libgui/src/gui-preferences-dc.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_dc_h)\n#define octave_gui_preferences_dc_h 1\n\n#include \"gui-preferences.h\"\n\n// documentation properties\n\nconst QString\ndc_bookmark_file (\"octave-doc-bookmarks.xbel\");\n\nextern gui_pref dc_bookmark_filter_active;\n\nextern gui_pref dc_bookmark_filter_shown;\n\nextern gui_pref dc_bookmark_filter_mru;\n\nextern gui_pref dc_splitter_state;\n\n// Constants for the xbel file format\nconst QLatin1String dc_xbel_doctype (\"<!DOCTYPE xbel>\");\nconst QLatin1String dc_xbel_attr_href (\"href\");\nconst QLatin1String dc_xbel_attr_folded (\"folded\");\nconst QLatin1String dc_xbel_attr_version (\"version\");\nconst QLatin1String dc_xbel_value_version (\"1.0\");\nconst QLatin1String dc_xbel_value_yes (\"yes\");\nconst QLatin1String dc_xbel_value_no (\"no\");\nconst QLatin1String dc_xbel_name_title (\"title\");\nconst QLatin1String dc_xbel_name_folder (\"folder\");\nconst QLatin1String dc_xbel_name_bookmark (\"bookmark\");\nconst QLatin1String dc_xbel_name_format (\"xbel\");\n\n// Zoom level\nextern gui_pref dc_browser_zoom_level;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-dw.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QColor>\n#include <QRect>\n\n#include \"gui-preferences-dw.h\"\n\ngui_pref\ndw_focus_follows_mouse (\"DockWidgets/focus_follows_mouse\", QVariant (false));\n\ngui_pref\ndw_title_custom_style (\"DockWidgets/widget_title_custom_style\",\n                       QVariant (true));\n\ngui_pref dw_title_3d (\"DockWidgets/widget_title_3d\", QVariant (20));\n\ngui_pref dw_title_fg_color (\"DockWidgets/title_fg_color\",\n                            QVariant (QColor (0, 0, 0)));\n\ngui_pref dw_title_fg_color_active (\"DockWidgets/title_fg_color_active\",\n                                   QVariant (QColor (255, 255, 255)));\n\ngui_pref dw_title_bg_color (\"DockWidgets/title_bg_color\",\n                            QVariant (QColor (192, 192, 192)));\n\ngui_pref dw_title_bg_color_active (\"DockWidgets/title_bg_color_active\",\n                                   QVariant (QColor (128, 128, 128)));\n\ngui_pref dw_icon_set (\"DockWidgets/widget_icon_set\", QVariant (\"NONE\"));\n\n// The following keys have to be used with .arg (objectName ())\ngui_pref dw_float_geometry (\"DockWidgets/%1_floating_geometry\",\n                            QVariant (QRect (50, 50, 480, 640)));\n\ngui_pref dw_dock_geometry (\"DockWidgets/%1\",\n                           QVariant (QRect (10, 10, 240, 320)));\n\ngui_pref dw_is_visible (\"DockWidgets/%1Visible\", QVariant (true));\n\ngui_pref dw_is_floating (\"DockWidgets/%1Floating\", QVariant (false));\n\ngui_pref dw_is_minimized (\"DockWidgets/%1_minimized\", QVariant (false));\n"
  },
  {
    "path": "libgui/src/gui-preferences-dw.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_dw_h)\n#define octave_gui_preferences_dw_h 1\n\n#include \"gui-preferences.h\"\n\nextern gui_pref dw_focus_follows_mouse;\n\nextern gui_pref dw_title_custom_style;\n\nextern gui_pref dw_title_3d;\n\nextern gui_pref dw_title_fg_color;\n\nextern gui_pref dw_title_fg_color_active;\n\nextern gui_pref dw_title_bg_color;\n\nextern gui_pref dw_title_bg_color_active;\n\nextern gui_pref dw_icon_set;\n\nconst QHash<QString, QString> dw_icon_set_names\n  = {\n      // array of possible icon sets (name, path (complete for NONE))\n      // the first entry here is the default!\n      {\"NONE\",    \":/icons/octave/scalable/logo.svg\"},\n      {\"GRAPHIC\", \":/icons/octave/scalable/graphic_logo_\"},\n      {\"LETTER\",  \":/icons/octave/scalable/letter_logo_\"}\n    };\n\n// The following keys have to be used with .arg (objectName ())\nextern gui_pref dw_float_geometry;\n\nextern gui_pref dw_dock_geometry;\n\nextern gui_pref dw_is_visible;\n\nextern gui_pref dw_is_floating;\n\nextern gui_pref dw_is_minimized;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-ed.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_QSCINTILLA)\n#include <Qsci/qsciscintilla.h>\n#endif\n\n#include \"gui-preferences-ed.h\"\n#include \"gui-settings.h\"\n#include \"localcharset-wrapper.h\"\n\n// Editor preferences\n\n// Lexer\n\ngui_pref\ned_color_mode (\"editor/color_mode\", QVariant (0));\n\n// Code completion\n\ngui_pref\ned_code_completion_octave_builtins (\"editor/codeCompletion_octave_builtins\",\n                                    QVariant (true));\n\ngui_pref\ned_code_completion_octave_functions (\"editor/codeCompletion_octave_functions\",\n                                     QVariant (true));\n\ngui_pref\ned_code_completion_keywords (\"editor/codeCompletion_keywords\", QVariant (true));\n\ngui_pref\ned_code_completion_document (\"editor/codeCompletion_document\", QVariant (true));\n\ngui_pref\ned_code_completion_replace (\"editor/codeCompletion_replace\", QVariant (false));\n\ngui_pref\ned_code_completion_case (\"editor/codeCompletion_case\", QVariant (true));\n\ngui_pref\ned_code_completion (\"editor/codeCompletion\", QVariant (true));\n\ngui_pref\ned_code_completion_threshold (\"editor/codeCompletion_threshold\", QVariant (3));\n\n// Code formatting\n\ngui_pref\ned_code_folding (\"editor/code_folding\", QVariant (true));\n\ngui_pref\ned_auto_indent (\"editor/auto_indent\", QVariant (true));\n\ngui_pref\ned_tab_indents_line (\"editor/tab_indents_line\", QVariant (false));\n\ngui_pref\ned_backspace_unindents_line (\"editor/backspace_unindents_line\",\n                             QVariant (false));\n\ngui_pref\ned_show_indent_guides (\"editor/show_indent_guides\", QVariant (false));\n\ngui_pref\ned_indent_uses_tabs (\"editor/indent_uses_tabs\", QVariant (false));\n\ngui_pref\ned_indent_width (\"editor/indent_width\", QVariant (2));\n\ngui_pref\ned_tab_width (\"editor/tab_width\", QVariant (2));\n\ngui_pref\ned_auto_endif (\"editor/auto_endif\", QVariant (1));\n\n// Long line handling\n\ngui_pref\ned_long_line_column (\"editor/long_line_column\", QVariant (80));\n\ngui_pref\ned_long_line_marker (\"editor/long_line_marker\", QVariant (true));\n\ngui_pref\ned_long_line_marker_line (\"editor/long_line_marker_line\", QVariant (true));\n\ngui_pref\ned_long_line_marker_background (\"editor/long_line_marker_background\",\n                                QVariant (false));\n\ngui_pref\ned_wrap_lines (\"editor/wrap_lines\", QVariant (false));\n\ngui_pref\ned_break_lines (\"editor/break_lines\", QVariant (false));\n\ngui_pref\ned_break_lines_comments (\"editor/break_lines_comments\", QVariant (false));\n\n// Other\n\ngui_pref\ned_highlight_all_occurrences (\"editor/highlight_all_occurrences\",\n                              QVariant (true));\n\ngui_pref\ned_show_Line_numbers (\"editor/showLineNumbers\", QVariant (true));\n\ngui_pref\ned_line_numbers_size (\"editor/line_numbers_size\", QVariant ( 0));\n\ngui_pref\ned_show_edit_status_bar (\"editor/show_edit_status_bar\", QVariant (true));\n\ngui_pref\ned_highlight_current_line (\"editor/highlightCurrentLine\", QVariant (true));\n\ngui_pref\ned_highlight_current_line_color (\"editor/highlightCurrentLineColor\",\n                                 QVariant (settings_color_no_change));\n\ngui_pref\ned_show_white_space (\"editor/show_white_space\", QVariant (false));\n\ngui_pref\ned_show_white_space_indent (\"editor/show_white_space_indent\", QVariant (false));\n\ngui_pref\ned_show_line_numbers (\"editor/showLineNumbers\", QVariant (true));\n\ngui_pref\ned_show_eol_chars (\"editor/show_eol_chars\", QVariant (false));\n\ngui_pref\ned_show_toolbar (\"editor/show_toolbar\", QVariant (true));\n\ngui_pref\ned_show_hscroll_bar (\"editor/show_hscroll_bar\", QVariant (true));\n\n// Octave comment strings\n\ngui_pref\ned_comment_str_old (\"editor/octave_comment_string\", QVariant (0));\n\ngui_pref\ned_comment_str (\"editor/oct_comment_str\", QVariant (0));\n\ngui_pref\ned_uncomment_str (\"editor/oct_uncomment_str\", QVariant (1 + 2 + 4 + 8));\n\n// Session data\n\ngui_pref\ned_restore_session (\"editor/restoreSession\", QVariant (true));\n\ngui_pref\ned_session_names (\"editor/savedSessionTabs\", QVariant (QStringList ()));\n\ngui_pref\ned_session_enc (\"editor/saved_session_encodings\", QVariant (QStringList ()));\n\ngui_pref\ned_session_ind (\"editor/saved_session_tab_index\", QVariant (QStringList ()));\n\ngui_pref\ned_session_lines (\"editor/saved_session_lines\", QVariant (QStringList ()));\n\ngui_pref\ned_session_bookmarks (\"editor/saved_session_bookmarks\", QVariant (QStringList ()));\n\n// Tabs\n\ngui_pref\ned_tab_position (\"editor/tab_position\", QVariant (QTabWidget::North));\n\ngui_pref\ned_tabs_rotated (\"editor/tabs_rotated\", QVariant (false));\n\ngui_pref\ned_tabs_max_width (\"editor/tabs_max_width\", QVariant (0));\n\n// File handling\n\n#if defined (HAVE_QSCINTILLA)\n#if defined (Q_OS_WIN32)\nconst int os_eol_mode = QsciScintilla::EolWindows;\n#else\nconst int os_eol_mode = QsciScintilla::EolUnix;\n#endif\n#else\nconst int os_eol_mode = 2;\n#endif\n\ngui_pref\ned_force_newline (\"editor/force_newline\", QVariant (true));\n\ngui_pref\ned_rm_trailing_spaces (\"editor/rm_trailing_spaces\", QVariant (true));\n\ngui_pref\ned_default_eol_mode (\"editor/default_eol_mode\", QVariant (os_eol_mode));\n\ngui_pref\ned_show_dbg_file (\"editor/show_dbg_file\", QVariant (true));\n\ngui_pref\ned_default_enc (\"editor/default_encoding\", QVariant (\"UTF-8\"));\n\ngui_pref\ned_create_new_file (\"editor/create_new_file\", QVariant (false));\n\ngui_pref\ned_hiding_closes_files (\"editor/hiding_closes_files\", QVariant (false));\n\ngui_pref\ned_always_reload_changed_files (\"editor/always_reload_changed_files\",\n                                QVariant (false));\n\ngui_pref\ned_run_selection_tmp_file (\"editor/run_selection_tmp_file\", QVariant (QString ()));\n\ngui_pref\ned_mru_file_list (\"editor/mru_file_list\", QVariant ());\n\ngui_pref\ned_mru_file_encodings (\"editor/mru_file_encodings\", QVariant ());\n\ngui_pref\ned_open_dlg_follows_file (\"open_dlg_follows_file\", QVariant (false));\n\n\n// The find dialog\n\n// Dialog position, the default will be calculated from the editor's geometry\ngui_pref\ned_fdlg_pos (\"editor/fdgl_pos\", QVariant (QPoint (0, 0)));\n\ngui_pref\ned_fdlg_opts (\"editor/fdgl_opts\", QVariant (FIND_DLG_WRAP));\n\ngui_pref\ned_fdlg_search (\"editor/fdgl_search\", QVariant ());\n\ngui_pref\ned_fdlg_replace (\"editor/fdgl_replace\", QVariant ());\n"
  },
  {
    "path": "libgui/src/gui-preferences-ed.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_ed_h)\n#define octave_gui_preferences_ed_h 1\n\n#include \"gui-settings.h\"\n\n// Editor preferences\n\n// Lexer\n\nextern gui_pref ed_color_mode;\n\nconst int ed_max_lexer_styles = 64;\nconst int ed_max_style_number = 128;\n\n// Code completion\n\nextern gui_pref ed_code_completion_octave_builtins;\n\nextern gui_pref ed_code_completion_octave_functions;\n\nextern gui_pref ed_code_completion_keywords;\n\nextern gui_pref ed_code_completion_document;\n\nextern gui_pref ed_code_completion_replace;\n\nextern gui_pref ed_code_completion_case;\n\nextern gui_pref ed_code_completion;\n\nextern gui_pref ed_code_completion_threshold;\n\n// Code formatting\n\nextern gui_pref ed_code_folding;\n\nextern gui_pref ed_auto_indent;\n\nextern gui_pref ed_tab_indents_line;\n\nextern gui_pref ed_backspace_unindents_line;\n\nextern gui_pref ed_show_indent_guides;\n\nextern gui_pref ed_indent_uses_tabs;\n\nextern gui_pref ed_indent_width;\n\nextern gui_pref ed_tab_width;\n\nextern gui_pref ed_auto_endif;\n\n// Long line handling\n\nextern gui_pref ed_long_line_column;\n\nextern gui_pref ed_long_line_marker;\n\nextern gui_pref ed_long_line_marker_line;\n\nextern gui_pref ed_long_line_marker_background;\n\nextern gui_pref ed_wrap_lines;\n\nextern gui_pref ed_break_lines;\n\nextern gui_pref ed_break_lines_comments;\n\n// Other\n\nextern gui_pref ed_highlight_all_occurrences;\n\nextern gui_pref ed_show_Line_numbers;\n\nextern gui_pref ed_line_numbers_size;\n\nextern gui_pref ed_show_edit_status_bar;\n\nextern gui_pref ed_highlight_current_line;\n\nextern gui_pref ed_highlight_current_line_color;\n\nextern gui_pref ed_show_white_space;\n\nextern gui_pref ed_show_white_space_indent;\n\nextern gui_pref ed_show_line_numbers;\n\nextern gui_pref ed_show_eol_chars;\n\nextern gui_pref ed_show_toolbar;\n\nextern gui_pref ed_show_hscroll_bar;\n\n// Octave comment strings\n\nextern gui_pref ed_comment_str_old;\n\nextern gui_pref ed_comment_str;\n\nextern gui_pref ed_uncomment_str;\n\nconst QString\ned_last_comment_str (\"editor/oct_last_comment_str\");\n\nconst QStringList\ned_comment_strings =\n{\n  \"##\",\n  \"#\",\n  \"%\",\n  \"%%\",\n  \"%!\"\n};\n\nconst int ed_comment_strings_count = 5;\n\n// Session data\n\nextern gui_pref ed_restore_session;\n\nextern gui_pref ed_session_names;\n\nextern gui_pref ed_session_enc;\n\nextern gui_pref ed_session_ind;\n\nextern gui_pref ed_session_lines;\n\nextern gui_pref ed_session_bookmarks;\n\n// Tabs\nconst QStringList\ned_tab_position_names =\n{\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Top\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Bottom\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Left\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Right\")\n};\n\nextern gui_pref ed_tab_position;\n\nextern gui_pref ed_tabs_rotated;\n\nextern gui_pref ed_tabs_max_width;\n\n// File handling\n\nextern gui_pref ed_force_newline;\n\nextern gui_pref ed_rm_trailing_spaces;\n\nextern gui_pref ed_default_eol_mode;\n\nextern gui_pref ed_show_dbg_file;\n\nextern gui_pref ed_default_enc;\n\nextern gui_pref ed_create_new_file;\n\nextern gui_pref ed_hiding_closes_files;\n\nextern gui_pref ed_always_reload_changed_files;\n\nextern gui_pref ed_run_selection_tmp_file;\n\nextern gui_pref ed_mru_file_list;\n\nextern gui_pref ed_mru_file_encodings;\n\nextern gui_pref ed_open_dlg_follows_file;\n\n// The find dialog\n\nenum find_dialog_options\n{\n  FIND_DLG_MORE  = 1,\n  FIND_DLG_CASE  = 2,\n  FIND_DLG_START = 4,\n  FIND_DLG_WRAP  = 8,\n  FIND_DLG_REGX  = 16,\n  FIND_DLG_WORDS = 32,\n  FIND_DLG_BACK  = 64,\n  FIND_DLG_SEL   = 128\n};\n\n// Dialog position, the default will be calculated from the editor's geometry\nextern gui_pref ed_fdlg_pos;\n\nextern gui_pref ed_fdlg_opts;\n\nextern gui_pref ed_fdlg_search;\n\nextern gui_pref ed_fdlg_replace;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-fb.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-fb.h\"\n\n// Files dock widget\n\ngui_pref\nfb_active_tab (\"filesdockwidget/active_tab\", QVariant (0));\n\ngui_pref\nfb_column_state (\"filesdockwidget/column_state\", QVariant ());\n\ngui_pref\nfb_mru_list (\"filesdockwidget/mru_dir_list\", QVariant (QStringList ()));\n\ngui_pref\nfb_show_size (\"filesdockwidget/showFileSize\", QVariant (false));\n\ngui_pref\nfb_show_type (\"filesdockwidget/showFileType\", QVariant (false));\n\ngui_pref\nfb_show_date (\"filesdockwidget/showLastModified\", QVariant (false));\n\ngui_pref\nfb_show_hidden (\"filesdockwidget/showHiddenFiles\", QVariant (false));\n\ngui_pref\nfb_show_altcol (\"filesdockwidget/useAlternatingRowColors\", QVariant (true));\n\ngui_pref\nfb_sort_column (\"filesdockwidget/sort_files_by_column\", QVariant (0));\n\ngui_pref\nfb_sort_order (\"filesdockwidget/sort_files_by_order\",\n               QVariant (Qt::AscendingOrder));\n\ngui_pref\nfb_sync_octdir (\"filesdockwidget/sync_octave_directory\", QVariant (true));\n\ngui_pref\nfb_restore_last_dir (\"filesdockwidget/restore_last_dir\", QVariant (false));\n\ngui_pref\nfb_startup_dir (\"filesdockwidget/startup_dir\", QVariant (QString ()));\n\ngui_pref\nfb_txt_file_ext (\"filesdockwidget/txt_file_extensions\",\n                 QVariant (\"m;c;cc;cpp;h;txt\"));\n"
  },
  {
    "path": "libgui/src/gui-preferences-fb.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_fb_h)\n#define octave_gui_preferences_fb_h 1\n\n#include \"gui-preferences.h\"\n\n// Files dock widget\n\nextern gui_pref fb_active_tab;\n\nextern gui_pref fb_column_state;\n\nextern gui_pref fb_mru_list;\n\nextern gui_pref fb_show_size;\n\nextern gui_pref fb_show_type;\n\nextern gui_pref fb_show_date;\n\nextern gui_pref fb_show_hidden;\n\nextern gui_pref fb_show_altcol;\n\nextern gui_pref fb_sort_column;\n\nextern gui_pref fb_sort_order;\n\nextern gui_pref fb_sync_octdir;\n\nextern gui_pref fb_restore_last_dir;\n\nextern gui_pref fb_startup_dir;\n\nextern gui_pref fb_txt_file_ext;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-ff.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-ff.h\"\n\n// Find files dialog preferences\n\ngui_pref\nff_geometry (\"findfiles/geometry\", QVariant ());\n\ngui_pref\nff_file_name (\"findfiles/file_name\", QVariant (\"*\"));\n\ngui_pref\nff_start_dir (\"findfiles/start_dir\", QVariant (\"\"));\n\ngui_pref\nff_recurse_dirs (\"findfiles/recurse_dirs\", QVariant (false));\n\ngui_pref\nff_include_dirs (\"findfiles/include_dirs\", QVariant (false));\n\ngui_pref\nff_name_case (\"findfiles/name_case\", QVariant (false));\n\ngui_pref\nff_check_text (\"findfiles/check_text\", QVariant (false));\n\ngui_pref\nff_contains_text (\"findfiles/contains_text\", QVariant (\"\"));\n\ngui_pref\nff_content_case (\"findfiles/content_case\", QVariant (false));\n\ngui_pref\nff_column_state (\"findfiles/column_state\", QVariant ());\n\ngui_pref\nff_sort_files_by_column (\"findfiles/sort_files_by_column\", QVariant (0));\n\ngui_pref\nff_sort_files_by_order (\"findfiles/sort_files_by_order\",\n                        QVariant (Qt::AscendingOrder));\n"
  },
  {
    "path": "libgui/src/gui-preferences-ff.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_ff_h)\n#define octave_gui_preferences_ff_h 1\n\n#include \"gui-preferences.h\"\n\n// Find files dialog preferences\n\nextern gui_pref ff_geometry;\n\nextern gui_pref ff_file_name;\n\nextern gui_pref ff_start_dir;\n\nextern gui_pref ff_recurse_dirs;\n\nextern gui_pref ff_include_dirs;\n\nextern gui_pref ff_name_case;\n\nextern gui_pref ff_check_text;\n\nextern gui_pref ff_contains_text;\n\nextern gui_pref ff_content_case;\n\nextern gui_pref ff_column_state;\n\nextern gui_pref ff_sort_files_by_column;\n\nextern gui_pref ff_sort_files_by_order;\n\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-global.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-global.h\"\n\n// Global preferences\n\ngui_pref\nglobal_skip_welcome_wizard (\"global_skip_welcome_wizard\", false);\n\ngui_pref\nglobal_show_splash_screen (\"global_show_splash_screen\", false);\n\ngui_pref\nglobal_mono_font (\"monospace_font\", global_font_family);\n\n// Style\n\ngui_pref\nglobal_style (\"style\", QVariant (\"default\"));\n\n// Icon size (in preferences: values -1, 0, 1)\n\ngui_pref\nglobal_icon_size (\"toolbar_icon_size\", QVariant (0));\n\ngui_pref\nglobal_icon_theme (\"use_system_icon_theme\", QVariant (false));\n\ngui_pref\nglobal_icon_theme_index (\"icon_theme\", QVariant (ICON_THEME_OCTAVE));\n\ngui_pref\nglobal_icon_fallbacks (\"icon_fallbacks\", QVariant (QStringList ()));\n\ngui_pref\nglobal_status_bar (\"show_status_bar\", QVariant (true));\n\n#if defined (Q_OS_MAC)\n// prevent native file dialogs on MAC by setting the default \"false\" and\n// setting the flag for ignoring the pref to \"true\" (3rd argument)\ngui_pref\nglobal_use_native_dialogs (\"use_native_file_dialogs\", QVariant (false), true);\n#elif defined (Q_OS_WIN32)\ngui_pref\nglobal_use_native_dialogs (\"use_native_file_dialogs\", QVariant (false));\n#else\ngui_pref\nglobal_use_native_dialogs (\"use_native_file_dialogs\", QVariant (true));\n#endif\n\ngui_pref\nglobal_cursor_blinking (\"cursor_blinking\", QVariant (true));\n\ngui_pref\nglobal_language (\"language\", QVariant (\"SYSTEM\"));\n\ngui_pref\nglobal_ov_startup_dir (\"octave_startup_dir\", QVariant (QString ()));\n\ngui_pref\nglobal_restore_ov_dir (\"restore_octave_dir\", QVariant (false));\n\ngui_pref\nglobal_use_custom_editor (\"useCustomFileEditor\", QVariant (false));\n\n#if defined (Q_OS_WIN32)\ngui_pref\nglobal_custom_editor (\"customFileEditor\", QVariant (\"notepad++ -n%l %f\"));\n#else\ngui_pref\nglobal_custom_editor (\"customFileEditor\", QVariant (\"emacs +%l %f\"));\n#endif\n\ngui_pref\nglobal_prompt_to_exit (\"prompt_to_exit\", QVariant (false));\n\n// Proxy\n\ngui_pref\nglobal_proxy_host (\"proxyHostName\", QVariant (QString ()));\n\ngui_pref\nglobal_use_proxy (\"useProxyServer\", QVariant (false));\n\ngui_pref\nglobal_proxy_type (\"proxyType\", QVariant (QString ()));\n\ngui_pref\nglobal_proxy_port (\"proxyPort\", QVariant (80));\n\ngui_pref\nglobal_proxy_user (\"proxyUserName\", QVariant (QString ()));\n\ngui_pref\nglobal_proxy_pass (\"proxyPassword\", QVariant (QString ()));\n"
  },
  {
    "path": "libgui/src/gui-preferences-global.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_global_h)\n#define octave_gui_preferences_global_h 1\n\n#include <QStyle>\n\n#include \"gui-preferences.h\"\n\n// Constants\n\nconst QString gui_obj_name_main_window = \"MainWindow\";\n\n// Global preferences\n\nextern gui_pref global_skip_welcome_wizard;\n\nextern gui_pref global_show_splash_screen;\n\n// Get the default monospaced font\n#if defined (Q_OS_WIN)\nconst QString global_font_family = \"Courier\";\n#elif defined (Q_OS_MAC)\nconst QString global_font_family = \"Monaco\";\n#else\nconst QString global_font_family = \"Monospace\";\n#endif\n\nextern gui_pref global_mono_font;\n\n// Style\n\nextern gui_pref global_style;\n\nconst QString\nglobal_toolbar_style (\"QToolBar {\"\n                      \"margin-top: 0px;\"\n                      \"margin-bottom: 0px;\"\n                      \"padding-top: 0px;\"\n                      \"padding-bottom: 0px;\"\n                      \"border-top: 0px;\"\n                      \"border-bottom: 0px;\"\n                      \"}\");\n\nconst QString\nglobal_menubar_style (\"QMenuBar {\"\n                      \"margin-top: 0px;\"\n                      \"margin-bottom: 0px;\"\n                      \"padding-top: 0px;\"\n                      \"padding-bottom: 0px;\"\n                      \"}\");\n\n// Icon size (in preferences: values -1, 0, 1)\nconst QStyle::PixelMetric global_icon_sizes[3] =\n{\n  QStyle::PM_SmallIconSize,\n  QStyle::PM_ToolBarIconSize,\n  QStyle::PM_LargeIconSize\n};\n\nextern gui_pref global_icon_size;\n\nextern gui_pref global_icon_theme;\n\nconst QString global_icon_extension (\".svg\");\n\nenum\n{\n  ICON_THEME_SYSTEM = 0,\n  ICON_THEME_OCTAVE,\n  ICON_THEME_TANGO,\n  ICON_THEME_CURSORS\n}  ;\n\nconst QStringList\nglobal_icon_paths =\n{\n  \"\",\n  \":/icons/octave/scalable/\",\n  \":/icons/tango/scalable/\",\n  \":/icons/cursors/\"\n};\n\nextern gui_pref global_icon_theme_index;\n\nconst QStringList\nglobal_all_icon_themes =\n{\n  \"\",\n  \"octave\",\n  \"tango\",\n  \"cursors\"\n};\n\nconst QStringList\nglobal_all_icon_theme_names =\n{\n  \"System\",\n  \"Octave\",\n  \"Tango\"\n};\n\nextern gui_pref global_icon_fallbacks;\n\nextern gui_pref global_status_bar;\n\nenum\n{\n  EXTRA_STYLE_FUSION_DARK = 0\n}  ;\nconst QStringList\nglobal_extra_styles =\n{\n  \"Fusion-Dark\"\n};\n\n// Different modes for running a file from editor\nenum\n{\n  ED_RUN_FILE = 0,\n  ED_STEP_INTO,\n  ED_RUN_TESTS,\n  ED_RUN_DEMOS\n};\n\n#if defined (Q_OS_MAC)\n// prevent native file dialogs on MAC by setting the default \"false\" and\n// setting the flag for ignoring the pref to \"true\" (3rd argument)\nextern gui_pref global_use_native_dialogs;\n#elif defined (Q_OS_WIN32)\nextern gui_pref global_use_native_dialogs;\n#else\nextern gui_pref global_use_native_dialogs;\n#endif\n\nextern gui_pref global_cursor_blinking;\n\nextern gui_pref global_language;\n\nextern gui_pref global_ov_startup_dir;\n\nextern gui_pref global_restore_ov_dir;\n\nextern gui_pref global_use_custom_editor;\n\nextern gui_pref global_custom_editor;\n\nextern gui_pref global_prompt_to_exit;\n\n// Proxy\n\nextern gui_pref global_proxy_host;\n\nextern gui_pref global_use_proxy;\n\nextern gui_pref global_proxy_type;\n\nextern gui_pref global_proxy_port;\n\nextern gui_pref global_proxy_user;\n\nextern gui_pref global_proxy_pass;\n\nconst QStringList\nglobal_proxy_all_types =\n{\n  \"HttpProxy\",\n  \"Socks5Proxy\",\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Environment Variables\")\n};\n\nconst QList<int> global_proxy_manual_types = { 0, 1 };\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-gp.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-gp.h\"\n\n// Graphics utilities\n\ngui_pref\ngp_annotation_geometry (\"annotation/geometry\", QVariant ());\n"
  },
  {
    "path": "libgui/src/gui-preferences-gp.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_gp_h)\n#define octave_gui_preferences_gp_h 1\n\n#include \"gui-preferences.h\"\n\n// Graphics utilities\n\nextern gui_pref gp_annotation_geometry;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-hw.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-hw.h\"\n\n// News Reader properties\n\ngui_pref\nhw_filter_active (\"history_dock_widget/filter_active\", QVariant (false));\n\ngui_pref\nhw_filter_shown (\"history_dock_widget/filter_shown\", QVariant (true));\n\ngui_pref\nhw_mru_list (\"history_dock_widget/mru_list\", QVariant ());\n"
  },
  {
    "path": "libgui/src/gui-preferences-hw.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_hw_h)\n#define octave_gui_preferences_hw_h 1\n\n#include \"gui-preferences.h\"\n\n// News Reader properties\n\nextern gui_pref hw_filter_active;\n\nextern gui_pref hw_filter_shown;\n\nextern gui_pref hw_mru_list;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-mw.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-mw.h\"\n\n// Main window preferences\n\n// Geometry wihtout default since default layout is built programmatically\ngui_pref\nmw_geometry (\"MainWindow/geometry\", QVariant (QByteArray ()));\n\n// State wihtout default since default layout is built programmatically\ngui_pref\nmw_state (\"MainWindow/windowState\", QVariant (QByteArray ()));\n\ngui_pref\nmw_dir_list (\"MainWindow/current_directory_list\", QVariant (QStringList ()));\n"
  },
  {
    "path": "libgui/src/gui-preferences-mw.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preference_mw_h)\n#define octave_gui_preference_mw_h 1\n\n#include \"gui-preferences.h\"\n\n// Main window preferences\n\n// Geometry wihtout default since default layout is built programmatically\nextern gui_pref mw_geometry;\n\n// State wihtout default since default layout is built programmatically\nextern gui_pref mw_state;\n\nextern gui_pref mw_dir_list;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-nr.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-nr.h\"\n#include <QDateTime>\n\n// News Reader properties\n\ngui_pref\nnr_last_time (\"news/last_time_checked\", QVariant (QDateTime ()));\n\ngui_pref\nnr_last_news (\"news/last_news_item\", QVariant (0));\n\ngui_pref\nnr_allow_connection (\"news/allow_web_connection\", QVariant (false));\n"
  },
  {
    "path": "libgui/src/gui-preferences-nr.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_nr_h)\n#define octave_gui_preferences_nr_h 1\n\n#include \"gui-preferences.h\"\n\n// News Reader properties\n\nextern gui_pref nr_last_time;\n\nextern gui_pref nr_last_news;\n\nextern gui_pref nr_allow_connection;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-pd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-pd.h\"\n\n// Path Dialog properties\n\ngui_pref\npd_geometry (\"path_dlg_geometry\", QVariant (QByteArray ()));\n"
  },
  {
    "path": "libgui/src/gui-preferences-pd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_pd_h)\n#define octave_gui_preferences_pd_h 1\n\n#include \"gui-preferences.h\"\n\n// Path Dialog properties\n\nextern gui_pref pd_geometry;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-sc.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QCoreApplication>\n#include <QSet>\n\n#include \"gui-preferences-sc.h\"\n\n// Note: Trying to shorten the uses of\n//\n//   QCoreApplication::translate (CONTEXT, STRING)\n//\n// by defining a macro won't work because lupdate won't know to look for\n// the macro.\n\n// The translations of the shortcut's descriptions require a more\n// complicated structure.  If already using the sc-pref constructor\n// with the description as argument, this description is added to\n// the hash \"all_shortcut_keys\" and the translation cannot be added\n// later on.  Therefore, all sc_pref objects are first declared with\n// the empty constructor and description, key and shortcut are added\n// later by calling init_all_shortcuts defined here.  This function\n// is called in the constructor of the base qobject directly after\n// loading the translators.\n\n// Dock widgets\nsc_pref sc_dock_widget_dock;\nsc_pref sc_dock_widget_close;\n\n// Main window menu\n\n// file\nsc_pref sc_main_file_new_file;\nsc_pref sc_main_file_new_function;\nsc_pref sc_main_file_new_figure;\nsc_pref sc_main_file_open_file;\nsc_pref sc_main_file_load_workspace;\nsc_pref sc_main_file_save_workspace;\nsc_pref sc_main_file_exit;\n\n// edit\nsc_pref sc_main_edit_copy;\nsc_pref sc_main_edit_paste;\nsc_pref sc_main_edit_undo;\nsc_pref sc_main_edit_select_all;\nsc_pref sc_main_edit_clear_clipboard;\nsc_pref sc_main_edit_find_in_files;\nsc_pref sc_main_edit_clear_command_window;\nsc_pref sc_main_edit_clear_history;\nsc_pref sc_main_edit_clear_workspace;\nsc_pref sc_main_edit_set_path;\nsc_pref sc_main_edit_preferences;\n\n// debug\nsc_pref sc_main_debug_step_over;\nsc_pref sc_main_debug_step_into;\nsc_pref sc_main_debug_step_out;\nsc_pref sc_main_debug_continue;\nsc_pref sc_main_debug_quit;\n\n// tools\nsc_pref sc_main_tools_start_profiler;\nsc_pref sc_main_tools_resume_profiler;\nsc_pref sc_main_tools_show_profiler;\n\n// window\nsc_pref sc_main_window_show_command;\nsc_pref sc_main_window_show_history;\nsc_pref sc_main_window_show_file_browser;\nsc_pref sc_main_window_show_workspace;\nsc_pref sc_main_window_show_editor;\nsc_pref sc_main_window_show_doc;\nsc_pref sc_main_window_show_variable_editor;\nsc_pref sc_main_window_command;\nsc_pref sc_main_window_history;\nsc_pref sc_main_window_file_browser;\nsc_pref sc_main_window_workspace;\nsc_pref sc_main_window_editor;\nsc_pref sc_main_window_doc;\nsc_pref sc_main_window_variable_editor;\nsc_pref sc_main_window_previous_dock;\nsc_pref sc_main_window_reset;\n\n// help\nsc_pref sc_main_help_ondisk_doc;\nsc_pref sc_main_help_online_doc;\nsc_pref sc_main_help_report_bug;\nsc_pref sc_main_help_packages;\nsc_pref sc_main_help_contribute;\nsc_pref sc_main_help_developer;\nsc_pref sc_main_help_about;\n\n// news\nsc_pref sc_main_news_release_notes;\nsc_pref sc_main_news_community_news;\n\n// Tab handling\n// The following shortcuts are placed in a menu item that is not displayed.\n// This still enables use of the defined shortcuts.  The key names were not\n// changed to preserve compatibility with older versions of Octave.\nsc_pref sc_edit_file_close;\nsc_pref sc_edit_file_close_all;\nsc_pref sc_edit_file_close_other;\nsc_pref sc_edit_tabs_switch_left_tab;\nsc_pref sc_edit_tabs_switch_right_tab;\nsc_pref sc_edit_tabs_move_tab_left;\nsc_pref sc_edit_tabs_move_tab_right;\n\n// Zooming\nsc_pref sc_edit_view_zoom_in;\nsc_pref sc_edit_view_zoom_out;\nsc_pref sc_edit_view_zoom_normal;\n\n// Actions of the editor\n\n// file\nsc_pref sc_edit_file_edit_function;\nsc_pref sc_edit_file_save;\nsc_pref sc_edit_file_save_as;\nsc_pref sc_edit_file_print;\n\n// edit\nsc_pref sc_edit_edit_redo;\nsc_pref sc_edit_edit_cut;\nsc_pref sc_edit_edit_find_replace;\nsc_pref sc_edit_edit_find_next;\nsc_pref sc_edit_edit_find_previous;\nsc_pref sc_edit_edit_delete_start_word;\nsc_pref sc_edit_edit_delete_end_word;\nsc_pref sc_edit_edit_delete_start_line;\nsc_pref sc_edit_edit_delete_end_line;\nsc_pref sc_edit_edit_delete_line;\nsc_pref sc_edit_edit_copy_line;\nsc_pref sc_edit_edit_cut_line;\nsc_pref sc_edit_edit_duplicate_selection;\nsc_pref sc_edit_edit_transpose_line;\nsc_pref sc_edit_edit_completion_list;\n\nsc_pref sc_edit_edit_comment_selection;\nsc_pref sc_edit_edit_uncomment_selection;\nsc_pref sc_edit_edit_comment_var_selection;\nsc_pref sc_edit_edit_upper_case;\nsc_pref sc_edit_edit_lower_case;\n\nsc_pref sc_edit_edit_indent_selection;\nsc_pref sc_edit_edit_unindent_selection;\nsc_pref sc_edit_edit_smart_indent_line_or_selection;\n\nsc_pref sc_edit_edit_conv_eol_winows;\nsc_pref sc_edit_edit_conv_eol_unix;\nsc_pref sc_edit_edit_conv_eol_mac;\n\nsc_pref sc_edit_edit_goto_line;\nsc_pref sc_edit_edit_move_to_brace;\nsc_pref sc_edit_edit_select_to_brace;\nsc_pref sc_edit_edit_toggle_bookmark;\nsc_pref sc_edit_edit_next_bookmark;\nsc_pref sc_edit_edit_previous_bookmark;\nsc_pref sc_edit_edit_remove_bookmark;\n\nsc_pref sc_edit_edit_preferences;\nsc_pref sc_edit_edit_styles_preferences;\n\n// view\nsc_pref sc_edit_view_show_line_numbers;\nsc_pref sc_edit_view_show_white_spaces;\nsc_pref sc_edit_view_show_eol_chars;\nsc_pref sc_edit_view_show_ind_guides;\nsc_pref sc_edit_view_show_long_line;\nsc_pref sc_edit_view_show_toolbar;\nsc_pref sc_edit_view_show_statusbar;\nsc_pref sc_edit_view_show_hscrollbar;\nsc_pref sc_edit_view_sort_tabs;\n\n// debug\nsc_pref sc_edit_debug_toggle_breakpoint;\nsc_pref sc_edit_debug_next_breakpoint;\nsc_pref sc_edit_debug_previous_breakpoint;\nsc_pref sc_edit_debug_remove_breakpoints;\n\n// run\nsc_pref sc_edit_run_run_file;\nsc_pref sc_edit_run_run_selection;\nsc_pref sc_edit_run_run_tests;\nsc_pref sc_edit_run_run_demos;\n\n// help\nsc_pref sc_edit_help_help_keyword;\nsc_pref sc_edit_help_doc_keyword;\n\n// Documentation browser\nsc_pref sc_doc_go_home;\nsc_pref sc_doc_go_back;\nsc_pref sc_doc_go_next;\nsc_pref sc_doc_bookmark;\n\n\nvoid init_all_shortcuts (void)\n{\n  // Dock widget\n  sc_dock_widget_dock = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Undock/Dock Widget\"), sc_dock_widget + \":dock\", OCTAVE_QT_KEYCOMBINATION (CTRL_ALT, Qt::Key_D));\n  sc_dock_widget_close = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Close Widget\"), sc_dock_widget + \":close\", OCTAVE_QT_KEYCOMBINATION (CTRL_ALT, Qt::Key_C));\n\n  // Main window menu\n\n  // file\n  sc_main_file_new_file = sc_pref (QCoreApplication::translate (\"shortcuts\", \"New File\"), sc_main_file + \":new_file\", QKeySequence::New);\n  sc_main_file_new_function = sc_pref (QCoreApplication::translate (\"shortcuts\", \"New Function\"), sc_main_file + \":new_function\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_N));\n  sc_main_file_new_figure = sc_pref (QCoreApplication::translate (\"shortcuts\", \"New Figure\"), sc_main_file + \":new_figure\", QKeySequence::UnknownKey);\n  sc_main_file_open_file = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Open File\"), sc_main_file + \":open_file\", QKeySequence::Open);\n  sc_main_file_load_workspace = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Load Workspace\"), sc_main_file + \":load_workspace\", QKeySequence::UnknownKey);\n  sc_main_file_save_workspace = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Save Workspace As\"), sc_main_file + \":save_workspace\", QKeySequence::UnknownKey);\n  sc_main_file_exit = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Exit Octave\"), sc_main_file + \":exit\", QKeySequence::Quit);\n\n  // edit\n  sc_main_edit_copy = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Copy\"), sc_main_edit + \":copy\", QKeySequence::Copy);\n  sc_main_edit_paste = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Paste\"), sc_main_edit + \":paste\", QKeySequence::Paste);\n  sc_main_edit_undo = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Undo\"), sc_main_edit + \":undo\", QKeySequence::Undo);\n  sc_main_edit_select_all = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Select All\"), sc_main_edit + \":select_all\", QKeySequence::SelectAll);\n  sc_main_edit_clear_clipboard = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Clear Clipboard\"), sc_main_edit + \":clear_clipboard\", QKeySequence::UnknownKey);\n  sc_main_edit_find_in_files = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Find in Files\"), sc_main_edit + \":find_in_files\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_F));\n  sc_main_edit_clear_command_window = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Clear Command Window\"), sc_main_edit + \":clear_command_window\", QKeySequence::UnknownKey);\n  sc_main_edit_clear_history = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Clear Command History\"), sc_main_edit + \":clear_history\", QKeySequence::UnknownKey);\n  sc_main_edit_clear_workspace = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Clear Workspace\"), sc_main_edit + \":clear_workspace\", QKeySequence::UnknownKey);\n  sc_main_edit_set_path = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Set Path\"), sc_main_edit + \":set_path\", QKeySequence::UnknownKey);\n  sc_main_edit_preferences = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Preferences\"), sc_main_edit + \":preferences\", QKeySequence::UnknownKey);\n\n  // debug\n  sc_main_debug_step_over = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Step\"), sc_main_debug + \":step_over\", OCTAVE_QT_KEYCOMBINATION (PRE, Qt::Key_F10));\n  sc_main_debug_step_into = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Step In\"), sc_main_debug + \":step_into\", OCTAVE_QT_KEYCOMBINATION (PRE, Qt::Key_F11));\n  sc_main_debug_step_out = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Step Out\"), sc_main_debug + \":step_out\", OCTAVE_QT_KEYCOMBINATION (PRE | Qt::ShiftModifier, Qt::Key_F11));\n  sc_main_debug_continue = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Continue\"), sc_main_debug + \":continue\", OCTAVE_QT_KEYCOMBINATION (PRE, Qt::Key_F5));\n  sc_main_debug_quit = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Quit Debug Mode\"), sc_main_debug + \":quit\", OCTAVE_QT_KEYCOMBINATION (PRE | Qt::ShiftModifier, Qt::Key_F5));\n\n  // tools\n  sc_main_tools_start_profiler = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Start/Stop Profiler Session\"), sc_main_tools + \":start_profiler\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_P));\n  sc_main_tools_resume_profiler = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Resume Profiler Session\"), sc_main_tools + \":resume_profiler\", QKeySequence::UnknownKey);\n  sc_main_tools_show_profiler = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Profile Data\"), sc_main_tools + \":show_profiler\", OCTAVE_QT_KEYCOMBINATION (Qt::AltModifier | Qt::ShiftModifier, Qt::Key_P));\n\n\n  // window\n  sc_main_window_show_command = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Command Window\"), sc_main_window + \":show_command\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL_SHIFT, Qt::Key_0));\n  sc_main_window_show_history = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Command History\"), sc_main_window + \":show_history\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL_SHIFT, Qt::Key_1));\n  sc_main_window_show_file_browser = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show File Browser\"), sc_main_window + \":show_file_browser\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL_SHIFT, Qt::Key_2));\n  sc_main_window_show_workspace = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Workspace\"), sc_main_window + \":show_workspace\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL_SHIFT, Qt::Key_3));\n  sc_main_window_show_editor = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Editor\"), sc_main_window + \":show_editor\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL_SHIFT, Qt::Key_4));\n  sc_main_window_show_doc = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Documentation\"), sc_main_window + \":show_doc\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL_SHIFT, Qt::Key_5));\n  sc_main_window_show_variable_editor = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Variable Editor\"), sc_main_window + \":show_variable_editor\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL_SHIFT, Qt::Key_6));\n  sc_main_window_command = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Command Window\"), sc_main_window + \":command\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL, Qt::Key_0));\n  sc_main_window_history = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Command History\"), sc_main_window + \":history\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL, Qt::Key_1));\n  sc_main_window_file_browser = sc_pref (QCoreApplication::translate (\"shortcuts\", \"File Browser\"), sc_main_window + \":file_browser\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL, Qt::Key_2));\n  sc_main_window_workspace = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Workspace\"), sc_main_window + \":workspace\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL, Qt::Key_3));\n  sc_main_window_editor = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Editor\"), sc_main_window + \":editor\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL, Qt::Key_4));\n  sc_main_window_doc = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Documentation\"), sc_main_window + \":doc\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL, Qt::Key_5));\n  sc_main_window_variable_editor = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Variable Editor\"), sc_main_window + \":variable_editor\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL, Qt::Key_6));\n  sc_main_window_previous_dock = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Previous Widget\"), sc_main_window + \":previous_widget\", OCTAVE_QT_KEYCOMBINATION (PRE | CTRL_ALT, Qt::Key_P));\n  sc_main_window_reset = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Reset Default Window Layout\"), sc_main_window + \":reset\", QKeySequence::UnknownKey);\n\n  // help\n  sc_main_help_ondisk_doc = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show On-disk Documentation\"), sc_main_help + \":ondisk_doc\", QKeySequence::UnknownKey);\n  sc_main_help_online_doc = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Online Documentation\"), sc_main_help + \":online_doc\", QKeySequence::UnknownKey);\n  sc_main_help_report_bug = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Report Bug\"), sc_main_help + \":report_bug\", QKeySequence::UnknownKey);\n  sc_main_help_packages = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Octave Packages\"), sc_main_help + \":packages\", QKeySequence::UnknownKey);\n  sc_main_help_contribute = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Contribute to Octave\"), sc_main_help + \":contribute\", QKeySequence::UnknownKey);\n  sc_main_help_developer = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Octave Developer Resources\"), sc_main_help + \":developer\", QKeySequence::UnknownKey);\n  sc_main_help_about = sc_pref (QCoreApplication::translate (\"shortcuts\", \"About Octave\"), sc_main_help + \":about\", QKeySequence::UnknownKey);\n\n  // news\n  sc_main_news_release_notes = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Release Notes\"), sc_main_news + \":release_notes\", QKeySequence::UnknownKey);\n  sc_main_news_community_news = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Community News\"), sc_main_news + \":community_news\", QKeySequence::UnknownKey);\n\n  // Tab handling\n  // The following shortcuts are placed in a menu item that is not displayed.\n  // This still enables use of the defined shortcuts.  The key names were not\n  // changed to preserve compatibility with older versions of Octave.\n  sc_edit_file_close = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Close Tab\"), sc_edit_file_cl, QKeySequence::Close);\n  sc_edit_file_close_all = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Close All Tabs\"), sc_edit_file_cl + \"_all\", QKeySequence::UnknownKey);\n  sc_edit_file_close_other = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Close Other Tabs\"), sc_edit_file_cl + \"_other\", QKeySequence::UnknownKey);\n  sc_edit_tabs_switch_left_tab = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Switch to Left Tab\"), sc_edit_tabs + \":switch_left_tab\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_PageUp));\n  sc_edit_tabs_switch_right_tab = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Switch to Right Tab\"), sc_edit_tabs + \":switch_right_tab\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_PageDown));\n  sc_edit_tabs_move_tab_left = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Move Tab Left\"), sc_edit_tabs + \":move_tab_left\", OCTAVE_QT_KEYCOMBINATION (Qt::AltModifier, Qt::Key_PageUp));\n  sc_edit_tabs_move_tab_right = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Move Tab Right\"), sc_edit_tabs + \":move_tab_right\", OCTAVE_QT_KEYCOMBINATION (Qt::AltModifier, Qt::Key_PageDown));\n\n  // Zooming\n  sc_edit_view_zoom_in = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Zoom In\"), sc_edit_view_zoom + \"_in\", QKeySequence::ZoomIn);\n  sc_edit_view_zoom_out = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Zoom Out\"), sc_edit_view_zoom + \"_out\", QKeySequence::ZoomOut);\n  #if defined (Q_OS_MAC)\n  sc_edit_view_zoom_normal = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Zoom Normal\"), sc_edit_view_zoom + \"_normal\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_Underscore));\n  #else\n  sc_edit_view_zoom_normal = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Zoom Normal\"), sc_edit_view_zoom + \"_normal\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_Period));\n  #endif\n\n  // Actions of the editor\n\n  // file\n  sc_edit_file_edit_function = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Edit Function\"), sc_edit_file + \":edit_function\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_E));\n  sc_edit_file_save = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Save File\"), sc_edit_file + \":save\", QKeySequence::Save);\n  sc_edit_file_save_as = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Save File As\"), sc_edit_file + \":save_as\", QKeySequence::SaveAs);\n  sc_edit_file_print = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Print\"), sc_edit_file + \":print\", QKeySequence::Print);\n\n  // edit\n  sc_edit_edit_redo = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Redo\"), sc_edit_edit + \":redo\", QKeySequence::Redo);\n  sc_edit_edit_cut = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Cut\"), sc_edit_edit + \":cut\", QKeySequence::Cut);\n  sc_edit_edit_find_replace = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Find and Replace\"), sc_edit_edit_find + \"_replace\", QKeySequence::Find);\n  sc_edit_edit_find_next = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Find Next\"), sc_edit_edit_find + \"_next\", QKeySequence::FindNext);\n  sc_edit_edit_find_previous = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Find Previous\"), sc_edit_edit_find + \"_previous\", QKeySequence::FindPrevious);\n  sc_edit_edit_delete_start_word = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Delete to Start of Word\"), sc_edit_edit + \":delete_start_word\", QKeySequence::DeleteStartOfWord);\n  sc_edit_edit_delete_end_word = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Delete to End of Word\"), sc_edit_edit + \":delete_end_word\", QKeySequence::DeleteEndOfWord);\n  sc_edit_edit_delete_start_line = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Delete to Start of Line\"), sc_edit_edit + \":delete_start_line\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_Backspace));\n  sc_edit_edit_delete_end_line = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Delete to End of Line\"), sc_edit_edit + \":delete_end_line\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_Delete));\n  sc_edit_edit_delete_line = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Delete Line\"), sc_edit_edit + \":delete_line\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_L));\n  sc_edit_edit_copy_line = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Copy Line\"), sc_edit_edit + \":copy_line\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_C));\n  sc_edit_edit_cut_line = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Cut Line\"), sc_edit_edit + \":cut_line\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_X));\n  sc_edit_edit_duplicate_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Duplicate Selection/Line\"), sc_edit_edit + \":duplicate_selection\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_D));\n  sc_edit_edit_transpose_line = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Transpose Line\"), sc_edit_edit + \":transpose_line\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_T));\n  sc_edit_edit_completion_list = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Completion List\"), sc_edit_edit + \":completion_list\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_Space));\n\n  sc_edit_edit_comment_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Comment Selection\"), sc_edit_edit + \":comment_selection\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_R));\n  sc_edit_edit_uncomment_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Uncomment Selection\"), sc_edit_edit + \":uncomment_selection\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_R));\n  sc_edit_edit_comment_var_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Comment Selection (Choosing String)\"), sc_edit_edit + \":comment_var_selection\", OCTAVE_QT_KEYCOMBINATION (CTRL_ALT, Qt::Key_R));\n  sc_edit_edit_upper_case = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Uppercase Selection\"), sc_edit_edit + \":upper_case\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_U));\n  sc_edit_edit_lower_case = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Lowercase Selection\"), sc_edit_edit + \":lower_case\", OCTAVE_QT_KEYCOMBINATION (CTRL_ALT, Qt::Key_U));\n\n  #if defined (Q_OS_MAC)\n  sc_edit_edit_indent_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Indent Selection Rigidly\"), sc_edit_edit + \":indent_selection\", OCTAVE_QT_KEYCOMBINATION (PRE, Qt::Key_Tab));\n  sc_edit_edit_unindent_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Unindent Selection Rigidly\"), sc_edit_edit + \":unindent_selection\", OCTAVE_QT_KEYCOMBINATION (PRE | Qt::ShiftModifier, Qt::Key_Tab));\n  #else\n  sc_edit_edit_indent_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Indent Selection Rigidly\"), sc_edit_edit + \":indent_selection\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_Tab));\n  sc_edit_edit_unindent_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Unindent Selection Rigidly\"), sc_edit_edit + \":unindent_selection\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_Tab));\n  #endif\n  sc_edit_edit_smart_indent_line_or_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Indent Code\"), sc_edit_edit + \":smart_indent_line_or_selection\", QKeySequence::UnknownKey);\n\n  sc_edit_edit_conv_eol_winows = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Convert Line Endings to Windows\"), sc_edit_edit + \":conv_eol_winows\", QKeySequence::UnknownKey);\n  sc_edit_edit_conv_eol_unix = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Convert Line Endings to Unix\"), sc_edit_edit + \":conv_eol_unix\", QKeySequence::UnknownKey);\n  sc_edit_edit_conv_eol_mac = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Convert Line Endings to Mac\"), sc_edit_edit + \":conv_eol_mac\", QKeySequence::UnknownKey);\n\n  sc_edit_edit_goto_line = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Goto Line\"), sc_edit_edit + \":goto_line\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_L));\n  sc_edit_edit_move_to_brace = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Move to Matching Brace\"), sc_edit_edit + \":move_to_brace\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_M));\n  sc_edit_edit_select_to_brace = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Select to Matching Brace\"), sc_edit_edit + \":select_to_brace\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_M));\n  sc_edit_edit_toggle_bookmark = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Toggle Bookmark\"), sc_edit_edit + \":toggle_bookmark\", OCTAVE_QT_KEYCOMBINATION (PRE, Qt::Key_F7));\n  sc_edit_edit_next_bookmark = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Next Bookmark\"), sc_edit_edit + \":next_bookmark\", OCTAVE_QT_KEYCOMBINATION (PRE, Qt::Key_F2));\n  sc_edit_edit_previous_bookmark = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Previous Bookmark\"), sc_edit_edit + \":previous_bookmark\", OCTAVE_QT_KEYCOMBINATION (PRE | Qt::ShiftModifier, Qt::Key_F2));\n  sc_edit_edit_remove_bookmark = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Remove All Bookmark\"), sc_edit_edit + \":remove_bookmark\", QKeySequence::UnknownKey);\n\n  sc_edit_edit_preferences = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Preferences\"), sc_edit_edit + \":preferences\", QKeySequence::UnknownKey);\n  sc_edit_edit_styles_preferences = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Styles Preferences\"), sc_edit_edit + \":styles_preferences\", QKeySequence::UnknownKey);\n\n  // view\n  sc_edit_view_show_line_numbers = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Line Numbers\"), sc_edit_view + \":show_line_numbers\", QKeySequence::UnknownKey);\n  sc_edit_view_show_white_spaces = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Whitespace Characters\"), sc_edit_view + \":show_white_spaces\", QKeySequence::UnknownKey);\n  sc_edit_view_show_eol_chars = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Line Endings\"), sc_edit_view + \":show_eol_chars\", QKeySequence::UnknownKey);\n  sc_edit_view_show_ind_guides = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Indentation Guides\"), sc_edit_view + \":show_ind_guides\", QKeySequence::UnknownKey);\n  sc_edit_view_show_long_line = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Long Line Marker\"), sc_edit_view + \":show_long_line\", QKeySequence::UnknownKey);\n  sc_edit_view_show_toolbar = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Toolbar\"), sc_edit_view + \":show_toolbar\", QKeySequence::UnknownKey);\n  sc_edit_view_show_statusbar = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Statusbar\"), sc_edit_view + \":show_statusbar\", QKeySequence::UnknownKey);\n  sc_edit_view_show_hscrollbar = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Show Horizontal Scrollbar\"), sc_edit_view + \":show_hscrollbar\", QKeySequence::UnknownKey);\n  sc_edit_view_sort_tabs = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Sort Tabs Alphabetically\"), sc_edit_view + \":sort_tabs\", QKeySequence::UnknownKey);\n\n  // debug\n  sc_edit_debug_toggle_breakpoint = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Toggle Breakpoint\"), sc_edit_debug + \":toggle_breakpoint\", QKeySequence::UnknownKey);\n  sc_edit_debug_next_breakpoint = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Next Breakpoint\"), sc_edit_debug + \":next_breakpoint\", QKeySequence::UnknownKey);\n  sc_edit_debug_previous_breakpoint = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Previous Breakpoint\"), sc_edit_debug + \":previous_breakpoint\", QKeySequence::UnknownKey);\n  sc_edit_debug_remove_breakpoints = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Remove All Breakpoints\"), sc_edit_debug + \":remove_breakpoints\", QKeySequence::UnknownKey);\n\n  // run\n  sc_edit_run_run_file = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Run File\"), sc_edit_run + \":run_file\", OCTAVE_QT_KEYCOMBINATION (PRE, Qt::Key_F5));\n  sc_edit_run_run_selection = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Run Selection\"), sc_edit_run + \":run_selection\", OCTAVE_QT_KEYCOMBINATION (PRE, Qt::Key_F9));\n  sc_edit_run_run_tests = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Run Tests\"), sc_edit_run + \":run_tests\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_F5));\n  sc_edit_run_run_demos = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Run Demos\"), sc_edit_run + \":run_demos\", OCTAVE_QT_KEYCOMBINATION (CTRL_SHIFT, Qt::Key_F5));\n\n  // help\n  sc_edit_help_help_keyword = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Help on Keyword\"), sc_edit_help + \":help_keyword\", QKeySequence::HelpContents);\n  sc_edit_help_doc_keyword = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Document on Keyword\"), sc_edit_help + \":doc_keyword\", OCTAVE_QT_KEYCOMBINATION (Qt::SHIFT, Qt::Key_F1));\n\n\n  // Documentation browser\n  sc_doc_go_home = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Go to Homepage\"), sc_doc + \":go_home\", OCTAVE_QT_KEYCOMBINATION (Qt::AltModifier, Qt::Key_Home));\n  sc_doc_go_back = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Go Back one Page\"), sc_doc + \":go_back\", QKeySequence::Back);\n  sc_doc_go_next = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Go Forward one Page\"), sc_doc + \":go_next\", QKeySequence::Forward);\n  sc_doc_bookmark = sc_pref (QCoreApplication::translate (\"shortcuts\", \"Bookmark this Page\"), sc_doc + \":bookmark\", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_D));\n}\n\n\nQString\nget_shortcut_section (const QString& key)\n{\n  QString section;\n\n  if (key.contains (':'))\n    section = key.section (':', 0, 0, QString::SectionSkipEmpty);\n\n  return section;\n}\n"
  },
  {
    "path": "libgui/src/gui-preferences-sc.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_sc_h)\n#define octave_gui_preferences_sc_h 1\n\n#include \"gui-preferences.h\"\n#include \"octave-qt-features.h\"\n\n// Define shortcuts\n\n// The shortcut's default values are given as QKeySequence for being able\n// to use platform independent standard keys (QKeySequence::StandardKey).\n// However, converting key sequences into QVariants does not seem to be\n// revertible.  In addition the related string (which is saved in the\n// preferences file) can not be determined during compile time since the\n// result depends on the platform (at least in case of standard key sequences\n// like, e.g., QKeySequence::Copy)\n// Therefore, these prefs for key sequences require a separate constant\n// definition and value method for the settings class.\n\n\n#if defined (HAVE_QKEYCOMBINATION_CLASS)\n#  include <QKeyCombination>\n#  define OCTAVE_QT_KEYCOMBINATION(mod, key) \\\n     QKeyCombination (mod, key).toCombined ()\n#else\n#  define OCTAVE_QT_KEYCOMBINATION(mod, key) \\\n     mod | key\n#endif\n\n#if defined (Q_OS_MAC)\n// Use CMD key as an equivalent of Ctrl key on other platforms\nconst Qt::KeyboardModifier CTRL = Qt::MetaModifier;\n// Some of octave default shortcuts on windows/linux are already defined\n// as system wide shortcuts on Mac Os X (almost all Function keys).\n// Prefix those with Option (Alt) modifier to avoid conflicts.\nconst Qt::KeyboardModifier PRE = Qt::AltModifier;\n#else\nconst Qt::KeyboardModifier CTRL = Qt::ControlModifier;\nconst Qt::KeyboardModifier PRE = Qt::NoModifier;\n#endif\n\nconst Qt::KeyboardModifiers CTRL_SHIFT = CTRL | Qt::ShiftModifier;\nconst Qt::KeyboardModifiers CTRL_ALT = CTRL | Qt::AltModifier;\n\nconst QString sc_group (\"shortcuts\");\n\n// Shortcuts not related to specific Menus\n\n// Dock widgets\nconst QString sc_dock_widget (\"dock_widget\");\nextern sc_pref sc_dock_widget_dock;\nextern sc_pref sc_dock_widget_close;\n\n// Main window menu\n\n// file\nconst QString sc_main_file (\"main_file\");\nextern sc_pref sc_main_file_new_file;\nextern sc_pref sc_main_file_new_function;\nextern sc_pref sc_main_file_new_figure;\nextern sc_pref sc_main_file_open_file;\nextern sc_pref sc_main_file_load_workspace;\nextern sc_pref sc_main_file_save_workspace;\nextern sc_pref sc_main_file_exit;\n\n// edit\nconst QString sc_main_edit (\"main_edit\");\nextern sc_pref sc_main_edit_copy;\nextern sc_pref sc_main_edit_paste;\nextern sc_pref sc_main_edit_undo;\nextern sc_pref sc_main_edit_select_all;\nextern sc_pref sc_main_edit_clear_clipboard;\nextern sc_pref sc_main_edit_find_in_files;\nextern sc_pref sc_main_edit_clear_command_window;\nextern sc_pref sc_main_edit_clear_history;\nextern sc_pref sc_main_edit_clear_workspace;\nextern sc_pref sc_main_edit_set_path;\nextern sc_pref sc_main_edit_preferences;\n\n// debug\nconst QString sc_main_debug (\"main_debug\");\nextern sc_pref sc_main_debug_step_over;\nextern sc_pref sc_main_debug_step_into;\nextern sc_pref sc_main_debug_step_out;\nextern sc_pref sc_main_debug_continue;\nextern sc_pref sc_main_debug_quit;\n\n// tools\nconst QString sc_main_tools (\"main_tools\");\nextern sc_pref sc_main_tools_start_profiler;\nextern sc_pref sc_main_tools_resume_profiler;\nextern sc_pref sc_main_tools_show_profiler;\n\n\n// window\nconst QString sc_main_window (\"main_window\");\nextern sc_pref sc_main_window_show_command;\nextern sc_pref sc_main_window_show_history;\nextern sc_pref sc_main_window_show_file_browser;\nextern sc_pref sc_main_window_show_workspace;\nextern sc_pref sc_main_window_show_editor;\nextern sc_pref sc_main_window_show_doc;\nextern sc_pref sc_main_window_show_variable_editor;\nextern sc_pref sc_main_window_command;\nextern sc_pref sc_main_window_history;\nextern sc_pref sc_main_window_file_browser;\nextern sc_pref sc_main_window_workspace;\nextern sc_pref sc_main_window_editor;\nextern sc_pref sc_main_window_doc;\nextern sc_pref sc_main_window_variable_editor;\nextern sc_pref sc_main_window_previous_dock;\nextern sc_pref sc_main_window_reset;\n\n// help\nconst QString sc_main_help (\"main_help\");\nextern sc_pref sc_main_help_ondisk_doc;\nextern sc_pref sc_main_help_online_doc;\nextern sc_pref sc_main_help_report_bug;\nextern sc_pref sc_main_help_packages;\nextern sc_pref sc_main_help_contribute;\nextern sc_pref sc_main_help_developer;\nextern sc_pref sc_main_help_about;\n\n// news\nconst QString sc_main_news (\"main_news\");\nextern sc_pref sc_main_news_release_notes;\nextern sc_pref sc_main_news_community_news;\n\n// Tab handling\n// The following shortcuts are moved into a separate tab.  The key names\n// are not change for preserving compatibility with older versions\nconst QString sc_edit_file (\"editor_file\");\nconst QString sc_edit_file_cl (sc_edit_file + \":close\");\nextern sc_pref sc_edit_file_close;\nextern sc_pref sc_edit_file_close_all;\nextern sc_pref sc_edit_file_close_other;\nconst QString sc_edit_tabs (\"editor_tabs\");\nextern sc_pref sc_edit_tabs_switch_left_tab;\nextern sc_pref sc_edit_tabs_switch_right_tab;\nextern sc_pref sc_edit_tabs_move_tab_left;\nextern sc_pref sc_edit_tabs_move_tab_right;\n\n// Zooming\nconst QString sc_edit_zoom (\"editor_zoom\"); // only a group name in the pref dialog\nconst QString sc_edit_view (\"editor_view\");\nconst QString sc_edit_view_zoom (sc_edit_view + \":zoom\");\nextern sc_pref sc_edit_view_zoom_in;\nextern sc_pref sc_edit_view_zoom_out;\n#if defined (Q_OS_MAC)\nextern sc_pref sc_edit_view_zoom_normal;\n#else\nextern sc_pref sc_edit_view_zoom_normal;\n#endif\n\n// Actions of the editor\n\n// file\nextern sc_pref sc_edit_file_edit_function;\nextern sc_pref sc_edit_file_save;\nextern sc_pref sc_edit_file_save_as;\nextern sc_pref sc_edit_file_print;\n\n// edit\nconst QString sc_edit_find (\"editor_find\"); // only a group name in the pref dialog\nconst QString sc_edit_edit (\"editor_edit\");\nconst QString sc_edit_edit_find (sc_edit_edit + \":find\");\nextern sc_pref sc_edit_edit_redo;\nextern sc_pref sc_edit_edit_cut;\nextern sc_pref sc_edit_edit_find_replace;\nextern sc_pref sc_edit_edit_find_next;\nextern sc_pref sc_edit_edit_find_previous;\nextern sc_pref sc_edit_edit_delete_start_word;\nextern sc_pref sc_edit_edit_delete_end_word;\nextern sc_pref sc_edit_edit_delete_start_line;\nextern sc_pref sc_edit_edit_delete_end_line;\nextern sc_pref sc_edit_edit_delete_line;\nextern sc_pref sc_edit_edit_copy_line;\nextern sc_pref sc_edit_edit_cut_line;\nextern sc_pref sc_edit_edit_duplicate_selection;\nextern sc_pref sc_edit_edit_transpose_line;\nextern sc_pref sc_edit_edit_completion_list;\n\nextern sc_pref sc_edit_edit_comment_selection;\nextern sc_pref sc_edit_edit_uncomment_selection;\nextern sc_pref sc_edit_edit_comment_var_selection;\nextern sc_pref sc_edit_edit_upper_case;\nextern sc_pref sc_edit_edit_lower_case;\n\n#if defined (Q_OS_MAC)\nextern sc_pref sc_edit_edit_indent_selection;\nextern sc_pref sc_edit_edit_unindent_selection;\n#else\nextern sc_pref sc_edit_edit_indent_selection;\nextern sc_pref sc_edit_edit_unindent_selection;\n#endif\nextern sc_pref sc_edit_edit_smart_indent_line_or_selection;\n\nextern sc_pref sc_edit_edit_conv_eol_winows;\nextern sc_pref sc_edit_edit_conv_eol_unix;\nextern sc_pref sc_edit_edit_conv_eol_mac;\n\nextern sc_pref sc_edit_edit_goto_line;\nextern sc_pref sc_edit_edit_move_to_brace;\nextern sc_pref sc_edit_edit_select_to_brace;\nextern sc_pref sc_edit_edit_toggle_bookmark;\nextern sc_pref sc_edit_edit_next_bookmark;\nextern sc_pref sc_edit_edit_previous_bookmark;\nextern sc_pref sc_edit_edit_remove_bookmark;\n\nextern sc_pref sc_edit_edit_preferences;\nextern sc_pref sc_edit_edit_styles_preferences;\n\n// view\nextern sc_pref sc_edit_view_show_line_numbers;\nextern sc_pref sc_edit_view_show_white_spaces;\nextern sc_pref sc_edit_view_show_eol_chars;\nextern sc_pref sc_edit_view_show_ind_guides;\nextern sc_pref sc_edit_view_show_long_line;\nextern sc_pref sc_edit_view_show_toolbar;\nextern sc_pref sc_edit_view_show_statusbar;\nextern sc_pref sc_edit_view_show_hscrollbar;\nextern sc_pref sc_edit_view_sort_tabs;\n\n// debug\nconst QString sc_edit_debug (\"editor_debug\");\nextern sc_pref sc_edit_debug_toggle_breakpoint;\nextern sc_pref sc_edit_debug_next_breakpoint;\nextern sc_pref sc_edit_debug_previous_breakpoint;\nextern sc_pref sc_edit_debug_remove_breakpoints;\n\n// run\nconst QString sc_edit_run (\"editor_run\");\nextern sc_pref sc_edit_run_run_file;\nextern sc_pref sc_edit_run_run_selection;\nextern sc_pref sc_edit_run_run_tests;\nextern sc_pref sc_edit_run_run_demos;\n\n// help\nconst QString sc_edit_help (\"editor_help\");\nextern sc_pref sc_edit_help_help_keyword;\nextern sc_pref sc_edit_help_doc_keyword;\n\n\n// Documentation browser\nconst QString sc_doc (\"doc_browser\");\nextern sc_pref sc_doc_go_home;\nextern sc_pref sc_doc_go_back;\nextern sc_pref sc_doc_go_next;\nextern sc_pref sc_doc_bookmark;\n\n\n// Other normal, shortcut related options\n\nconst gui_pref\nsc_main_ctrld (\"shortcuts/main_ctrld\", QVariant (false));\n\nconst gui_pref\nsc_prevent_rl_conflicts (\"shortcuts/prevent_readline_conflicts\", QVariant (false));\nconst gui_pref\nsc_prevent_rl_conflicts_menu (\"shortcuts/prevent_readline_conflicts_menu\", QVariant (false));\n\nextern void init_all_shortcuts (void);\nextern QString get_shortcut_section (const QString& key);\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-sd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-sd.h\"\n\n// Settings dialog\n\ngui_pref\nsd_geometry (\"settings/geometry\", QVariant ());\n\ngui_pref\nsd_last_tab (\"settings/last_tab\", QVariant (0));\n\ngui_pref\nsd_last_editor_styles_tab (\"settings/last_editor_styles_tab\", QVariant (0));\n"
  },
  {
    "path": "libgui/src/gui-preferences-sd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_sd_h)\n#define octave_gui_preferences_sd_h 1\n\n#include \"gui-preferences.h\"\n\n// Settings dialog\n\nextern gui_pref sd_geometry;\n\nextern gui_pref sd_last_tab;\n\nextern gui_pref sd_last_editor_styles_tab;\n\n// Textstrings for second color schemes\nconst QString settings_color_modes\n  = QT_TRANSLATE_NOOP (\"octave::settings_dialog\",\n                       \"Second color mode (light/dark)\");\n\nconst QString settings_color_modes_tooltip\n  = QT_TRANSLATE_NOOP (\"octave::settings_dialog\",\n                       \"Switch to a second set of colors.\\n\"\n                       \"Useful for defining light/dark modes.\\n\"\n                       \"Discards non-applied current changes!\");\n\nconst QString settings_reload_colors\n  = QT_TRANSLATE_NOOP (\"octave::settings_dialog\",\n                       \"&Reload default colors\");\n\nconst QString settings_reload_colors_tooltip\n  = QT_TRANSLATE_NOOP (\"octave::settings_dialog\",\n                       \"Reload the default colors,\\n\"\n                       \"depends on currently selected mode.\");\n\nconst QString settings_reload_styles\n  = QT_TRANSLATE_NOOP (\"octave::settings_dialog\",\n                       \"&Reload default styles\");\n\nconst QString settings_reload_styles_tooltip\n  = QT_TRANSLATE_NOOP (\"octave::settings_dialog\",\n                       \"Reload the default style values,\\n\"\n                       \"depends on currently selected mode.\");\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-ve.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-ve.h\"\n\n#include <QApplication>\n\n// Variable Editor preferences\n\ngui_pref\nve_use_terminal_font (\"variable_editor/use_terminal_font\", QVariant (true));\n\ngui_pref\nve_font_name (\"variable_editor/font_name\", QVariant ());\n\ngui_pref\nve_font_size (\"variable_editor/font_size\", QVariant (10));\n\ngui_pref\nve_column_width (\"variable_editor/column_width\", QVariant (100));\n\ngui_pref\nve_row_height (\"variable_editor/row_height\", QVariant (10));\n\ngui_pref\nve_alternate_rows (\"variable_editor/alternate_rows\", QVariant (false));\n\ngui_pref\nve_color_mode (\"variable_editor/color_mode\", QVariant (0));\n\ngui_pref ve_colors[2*ve_colors_count] =\n{\n  {\"variable_editor/color_f\" + settings_color_modes_ext[0], QVariant (QPalette::WindowText)},\n  {\"variable_editor/color_b\" + settings_color_modes_ext[0], QVariant (QPalette::Base)},\n  {\"variable_editor/color_s\" + settings_color_modes_ext[0], QVariant (QPalette::HighlightedText)},\n  {\"variable_editor/color_h\" + settings_color_modes_ext[0], QVariant (QPalette::Highlight)},\n  {\"variable_editor/color_a\" + settings_color_modes_ext[0], QVariant (QPalette::AlternateBase)},\n  {\"variable_editor/color_f\" + settings_color_modes_ext[1], QVariant ()},\n  {\"variable_editor/color_b\" + settings_color_modes_ext[1], QVariant ()},\n  {\"variable_editor/color_s\" + settings_color_modes_ext[1], QVariant ()},\n  {\"variable_editor/color_h\" + settings_color_modes_ext[1], QVariant ()},\n  {\"variable_editor/color_a\" + settings_color_modes_ext[1], QVariant ()}\n};\n"
  },
  {
    "path": "libgui/src/gui-preferences-ve.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_ve_h)\n#define octave_gui_preferences_ve_h 1\n\n#include \"gui-preferences.h\"\n#include \"gui-settings.h\"\n\n// Variable Editor preferences\n\nextern gui_pref ve_use_terminal_font;\n\nextern gui_pref ve_font_name;\n\nextern gui_pref ve_font_size;\n\nextern gui_pref ve_column_width;\n\nextern gui_pref ve_row_height;\n\nextern gui_pref ve_alternate_rows;\n\nextern gui_pref ve_color_mode;\n\nconst QString ve_color_chars (\"fbsha\");\n\nconst int ve_colors_count = 5;\n\nextern gui_pref ve_colors[];\n\nconst QStringList ve_color_names =\n{\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Foreground\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Background\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Selected Foreground\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Selected Background\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"Alternating Background\")\n};\n\nconst QStringList ve_save_formats =\n{\n  \"ascii\",\n  \"binary\",\n  \"float-binary\",\n  \"hdf5\",\n  \"float-hdf5\",\n  \"text\",\n  \"mat7-binary\",\n  \"mat-binary\",\n  \"mat4-binary\",\n  \"zip\"\n};\n\n// The following list is a relation between save format and fiel extension.\n// The format string are case insensitive.\nconst QStringList ve_save_formats_ext =\n{\n  \"-ascii\",       \"dat\",\n  \"-hdf5\",        \"h5\",\n  \"-text\",        \"txt\",\n  \"-v7.3\",        \"mat\",\n  \"-7.3\",         \"mat\",\n  \"-v7\",          \"mat\",\n  \"-7\",           \"mat\",\n  \"-mat7-binary\", \"mat\",\n  \"-v6\",          \"mat\",\n  \"-6\",           \"mat\",\n  \"-mat-binary\",  \"mat\",\n  \"-v4\",          \"mat\",\n  \"-4\",           \"mat\",\n  \"-mat4-binary\", \"mat\",\n  \"-binary\",      \"bin\",   // after other fmt incl. \"-binary\"\n  \"-z\",           \"txt.gz\" // gzipped -text\n};\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences-ws.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-ws.h\"\n#include \"gui-settings.h\"\n\n// Workspace view\n\ngui_pref\nws_enable_colors (\"workspaceview/enable_colors\", QVariant (false));\n\ngui_pref\nws_hide_tool_tips (\"workspaceview/hide_tools_tips\", QVariant (false));\n\ngui_pref\nws_filter_active (\"workspaceview/filter_active\", QVariant (false));\n\ngui_pref\nws_filter_shown (\"workspaceview/filter_shown\", QVariant (true));\n\ngui_pref\nws_column_state (\"workspaceview/column_state\", QVariant ());\n\ngui_pref\nws_sort_column (\"workspaceview/sort_by_column\", QVariant (0));\n\ngui_pref\nws_sort_order (\"workspaceview/sort_order\", QVariant (Qt::AscendingOrder));\n\ngui_pref\nws_mru_list (\"workspaceview/mru_list\", QVariant ());\n\ngui_pref\nws_max_filter_history (\"workspaceview/max_filter_history\", QVariant (10));\n\ngui_pref\nws_color_mode (\"workspaceview/color_mode\", QVariant (0));\n\ngui_pref ws_colors[2*ws_colors_count] =\n{\n  {\"workspaceview/color_a\" + settings_color_modes_ext[0], QVariant (QPalette::Highlight)},\n  {\"workspaceview/color_g\" + settings_color_modes_ext[0], QVariant (QPalette::Midlight)},\n  {\"workspaceview/color_p\" + settings_color_modes_ext[0], QVariant (QPalette::Dark)},\n  {\"workspaceview/color_a\" + settings_color_modes_ext[1], QVariant ()},\n  {\"workspaceview/color_g\" + settings_color_modes_ext[1], QVariant ()},\n  {\"workspaceview/color_p\" + settings_color_modes_ext[1], QVariant ()}\n};\n"
  },
  {
    "path": "libgui/src/gui-preferences-ws.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_ws_h)\n#define octave_gui_preferences_ws_h 1\n\n#include \"gui-preferences.h\"\n\n// Workspace view\n\nextern gui_pref ws_enable_colors;\n\nextern gui_pref ws_hide_tool_tips;\n\nextern gui_pref ws_filter_active;\n\nextern gui_pref ws_filter_shown;\n\nextern gui_pref ws_column_state;\n\nextern gui_pref ws_sort_column;\n\nextern gui_pref ws_sort_order;\n\nextern gui_pref ws_mru_list;\n\nconst QStringList ws_columns_shown =\n{\n  QT_TRANSLATE_NOOP (\"octave::workspace_view\", \"Class\"),\n  QT_TRANSLATE_NOOP (\"octave::workspace_view\", \"Dimension\"),\n  QT_TRANSLATE_NOOP (\"octave::workspace_view\", \"Value\"),\n  QT_TRANSLATE_NOOP (\"octave::workspace_view\", \"Attribute\")\n};\n\nextern gui_pref ws_max_filter_history;\n\nextern gui_pref ws_color_mode;\n\nconst int ws_colors_count = 3;\n\nextern gui_pref ws_colors[];\n\nconst QString ws_class_chars (\"agp\");\n\nconst QStringList\nws_color_names =\n{\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"argument\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"global\"),\n  QT_TRANSLATE_NOOP (\"octave::settings_dialog\", \"persistent\")\n};\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-preferences.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gui-preferences-sc.h\"\n#include \"gui-preferences.h\"\n\ngui_pref::gui_pref (const QString& settings_key, const QVariant& def,\n                    bool ignore)\n  : m_settings_key (settings_key), m_def (def), m_ignore (ignore)\n{\n  all_gui_preferences::insert (settings_key, *this);\n}\n\nall_gui_preferences *all_gui_preferences::s_instance = nullptr;\n\nvoid\nall_gui_preferences::insert (const QString& settings_key,\n                             const gui_pref& pref)\n{\n  ensure_instance ();\n\n  s_instance->do_insert (settings_key, pref);\n}\n\nconst gui_pref\nall_gui_preferences::value (const QString& settings_key)\n{\n  ensure_instance ();\n\n  return s_instance->do_value (settings_key);\n}\n\nQStringList\nall_gui_preferences::keys ()\n{\n  ensure_instance ();\n\n  return s_instance->do_keys ();\n}\n\nvoid\nall_gui_preferences::do_insert (const QString& settings_key,\n                                const gui_pref& pref)\n{\n  m_hash.insert (settings_key, pref);\n}\n\nconst gui_pref\nall_gui_preferences::do_value (const QString& settings_key) const\n{\n  return m_hash.value (settings_key);\n}\n\nQStringList\nall_gui_preferences::do_keys () const\n{\n  return m_hash.keys ();\n}\n\nvoid\nall_gui_preferences::ensure_instance ()\n{\n  if (! s_instance)\n    s_instance = new all_gui_preferences ();\n}\n\nsc_pref::sc_pref (const QString& description, const QString& settings_key,\n                  Qt::Key def)\n  : m_description (description), m_settings_key (settings_key), m_def (def),\n    m_def_std (QKeySequence::UnknownKey)\n{\n  all_shortcut_preferences::insert (settings_key, *this);\n}\n\nsc_pref::sc_pref (const QString& description, const QString& settings_key,\n                  unsigned int def)\n  : m_description (description), m_settings_key (settings_key), m_def (def),\n    m_def_std (QKeySequence::UnknownKey)\n{\n  all_shortcut_preferences::insert (settings_key, *this);\n}\n\nsc_pref::sc_pref (const QString& description, const QString& settings_key,\n                  QKeySequence::StandardKey def_std)\n  : m_description (description), m_settings_key (settings_key), m_def (0),\n    m_def_std (def_std)\n{\n  all_shortcut_preferences::insert (settings_key, *this);\n}\n\nQKeySequence\nsc_pref::def_value () const\n{\n  QKeySequence key_seq = QKeySequence ();\n\n  if (m_def)\n    key_seq = QKeySequence (m_def);\n  else if (m_def_std != QKeySequence::UnknownKey)\n    key_seq = QKeySequence (m_def_std);\n\n  return key_seq;\n}\n\nQString\nsc_pref::def_text () const\n{\n  return def_value ().toString (QKeySequence::NativeText);\n}\n\nall_shortcut_preferences *all_shortcut_preferences::s_instance = nullptr;\n\nvoid\nall_shortcut_preferences::insert (const QString& settings_key,\n                                  const sc_pref& scpref)\n{\n  ensure_instance ();\n\n  s_instance->do_insert (settings_key, scpref);\n}\n\nconst sc_pref\nall_shortcut_preferences::value (const QString& settings_key)\n{\n  ensure_instance ();\n\n  return s_instance->do_value (settings_key);\n}\n\nQStringList\nall_shortcut_preferences::keys ()\n{\n  ensure_instance ();\n\n  return s_instance->do_keys ();\n}\n\nvoid\nall_shortcut_preferences::do_insert (const QString& settings_key,\n                                     const sc_pref& scpref)\n{\n  m_hash.insert (settings_key, scpref);\n}\n\nconst sc_pref\nall_shortcut_preferences::do_value (const QString& settings_key) const\n{\n  return m_hash.value (settings_key);\n}\n\nQStringList\nall_shortcut_preferences::do_keys () const\n{\n  return m_hash.keys ();\n}\n\nvoid\nall_shortcut_preferences::ensure_instance ()\n{\n  if (! s_instance)\n    s_instance = new all_shortcut_preferences ();\n}\n"
  },
  {
    "path": "libgui/src/gui-preferences.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_preferences_h)\n#define octave_gui_preferences_h 1\n\n#include \"octave-config.h\"\n\n#include <QStringList>\n#include <QStyle>\n#include <QTabWidget>\n#include <QVariant>\n\n// FIXME: Would it be possible/make sense to merge gui_pref and sc_pref\n// into a single class or to at least have them derived from a common\n// base class so we could have one global hash table that contains all\n// of them?\n\n// Structure for the definition of pairs: key and default value\n\nclass gui_pref\n{\npublic:\n\n  // Default constructed gui_pref objects are invalid, but we need this\n  // to create QHash objects that contain gui_pref objects.  No invalid\n  // gui_pref objects should acutally be used.\n\n  gui_pref () = default;\n\n  gui_pref (const QString& settings_key, const QVariant& def,\n            bool ignore = false);\n\n  gui_pref (const gui_pref&) = default;\n\n  gui_pref& operator = (const gui_pref&) = default;\n\n  ~gui_pref () = default;\n\n  QString settings_key () const { return m_settings_key; }\n  QVariant def () const { return m_def; }\n  bool ignore () const { return m_ignore; }\n\nprivate:\n\n  // The settings key name.\n  QString m_settings_key;\n\n  // The default value.\n  QVariant m_def;\n\n  // TRUE means always take the default.\n  bool m_ignore;\n};\n\n// FIXME: Is there a better/more modern way to manage this data than to\n// have this style of singleton class?\n\n// Allow lookup of gui_pref objects when we don't know the name at\n// compile time.\n\nclass all_gui_preferences\n{\npublic:\n\n  all_gui_preferences () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (all_gui_preferences)\n\n  ~all_gui_preferences () = default;\n\n  static void insert (const QString& settings_key, const gui_pref& pref);\n\n  static const gui_pref value (const QString& settings_key);\n\n  static QStringList keys ();\n\nprivate:\n\n  // Map from shortcut identifier (settings key) to gui_pref object.\n  QHash<QString, gui_pref> m_hash;\n\n  void do_insert (const QString& settings_key, const gui_pref& pref);\n\n  const gui_pref do_value (const QString& settings_key) const;\n\n  QStringList do_keys () const;\n\n  static void ensure_instance ();\n\n  // Map from shortcut identifier (settings key) to sc_pref object.\n  static all_gui_preferences *s_instance;\n};\n\n// The version for shortcuts, where the default value is stored as a\n// combination of Qt:Keys (resutling in an unsigend int, when added)\n// or as one of the predefined standard key sequences.\n\nclass sc_pref\n{\npublic:\n\n  // Default constructed sc_pref objects are invalid, but we need this\n  // to create QHash objects that contain sc_pref objects.  No invalid\n  // sc_pref objects should acutally be used.\n\n  sc_pref () = default;\n\n  sc_pref (const QString& description, const QString& settings_key,\n           Qt::Key def);\n\n  sc_pref (const QString& description_arg, const QString& settings_key,\n           unsigned int def);\n\n  sc_pref (const QString& description_arg, const QString& settings_key,\n           QKeySequence::StandardKey def_std);\n\n  sc_pref (const sc_pref&) = default;\n\n  sc_pref& operator = (const sc_pref&) = default;\n\n  ~sc_pref () = default;\n\n  QString description () const { return m_description; }\n\n  QString settings_key () const { return m_settings_key; }\n\n  unsigned int def () const { return m_def; }\n\n  QKeySequence::StandardKey def_std () const { return m_def_std; }\n\n  QKeySequence def_value () const;\n\n  QString def_text () const;\n\nprivate:\n\n  // Description of the shortcut.\n  QString m_description;\n\n  // The settings key name.\n  QString m_settings_key;\n\n  // The default as key.\n  unsigned int m_def;\n\n  // The default as standard key.\n  QKeySequence::StandardKey m_def_std;\n};\n\n// FIXME: Is there a better/more modern way to manage this data than to\n// have this style of singleton class?\n\n// Allow lookup of sc_pref objects when we don't know the name at\n// compile time.\n\nclass all_shortcut_preferences\n{\npublic:\n\n  all_shortcut_preferences () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (all_shortcut_preferences)\n\n  ~all_shortcut_preferences () = default;\n\n  static void insert (const QString& settings_key, const sc_pref& scpref);\n\n  static const sc_pref value (const QString& settings_key);\n\n  static QStringList keys ();\n\nprivate:\n\n  // Map from shortcut identifier (settings key) to sc_pref object.\n  QHash<QString, sc_pref> m_hash;\n\n  void do_insert (const QString& settings_key, const sc_pref& scpref);\n\n  const sc_pref do_value (const QString& settings_key) const;\n\n  QStringList do_keys () const;\n\n  static void ensure_instance ();\n\n  // Map from shortcut identifier (settings key) to sc_pref object.\n  static all_shortcut_preferences *s_instance;\n};\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-settings.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <cstdlib>\n\n#include <algorithm>\n#include <array>\n#include <string>\n\n#include <QAction>\n#include <QApplication>\n#include <QByteArray>\n#include <QComboBox>\n#include <QDateTime>\n#include <QDebug>\n#include <QFile>\n#include <QFileInfo>\n#include <QFontDatabase>\n#include <QIcon>\n#include <QLibraryInfo>\n#include <QMessageBox>\n#include <QNetworkProxy>\n#include <QSettings>\n#include <QShortcut>\n#include <QString>\n#include <QStringList>\n#include <QTranslator>\n\n#if defined (HAVE_QSCINTILLA)\n#  include <Qsci/qscilexer.h>\n#endif\n\n#include \"gui-preferences-cs.h\"\n#include \"gui-preferences-ed.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-settings.h\"\n#include \"octave-qt-features.h\"\n\n#include \"localcharset-wrapper.h\"\n#include \"oct-env.h\"\n#include \"oct-string.h\"\n\n#include \"defaults.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nQString gui_settings::file_name () const\n{\n  return fileName ();\n}\n\nQString\ngui_settings::directory_name () const\n{\n  QFileInfo sfile (fileName ());\n\n  return sfile.absolutePath ();\n}\n\nbool\ngui_settings::bool_value (const gui_pref& pref) const\n{\n  return value (pref).toBool ();\n}\n\nQByteArray\ngui_settings::byte_array_value (const gui_pref& pref) const\n{\n  return value (pref).toByteArray ();\n}\n\nQColor\ngui_settings::color_value (const gui_pref& pref) const\n{\n  return value (pref).value<QColor> ();\n}\n\nQDateTime\ngui_settings::date_time_value (const gui_pref& pref) const\n{\n  return value (pref).toDateTime ();\n}\n\nint\ngui_settings::int_value (const gui_pref& pref) const\n{\n  return value (pref).toInt ();\n}\n\nQString\ngui_settings::string_value (const gui_pref& pref) const\n{\n  return value (pref).toString ();\n}\n\nQStringList\ngui_settings::string_list_value (const gui_pref& pref) const\n{\n  return value (pref).toStringList ();\n}\n\nuint\ngui_settings::uint_value (const gui_pref& pref) const\n{\n  return value (pref).toUInt ();\n}\n\nQColor\ngui_settings::get_color_value (const QVariant& def, int mode) const\n{\n  QColor default_color;\n\n  // Determine whether the default value in pref is given as\n  // QPalette::ColorRole or as QColor\n#if defined (QVARIANT_CANCONVERT_REQUIRES_QMETATYPE_ARGUMENT)\n  if (def.canConvert (QMetaType (QMetaType::QColor)))\n#else\n  if (def.canConvert (QMetaType::QColor))\n#endif\n    default_color = def.value<QColor> ();\n  else\n    {\n      // The default colors are given as color roles for\n      // the application's palette\n      default_color = QApplication::palette ().color\n                      (static_cast<QPalette::ColorRole> (def.toInt ()));\n      // FIXME: use value<QPalette::ColorRole> instead of static cast after\n      //        dropping support of Qt 5.4\n    }\n\n  if ((mode == 1) && (default_color != settings_color_no_change))\n    {\n      // In second mode, determine the default color from the first mode\n#if HAVE_QCOLOR_FLOAT_TYPE\n      float h, s, l, a;\n#else\n      qreal h, s, l, a;\n#endif\n      default_color.getHslF (&h, &s, &l, &a);\n      qreal l_new = 1.0-l*0.85;\n      if (l < 0.3)\n        l_new = 1.0-l*0.7;  // convert darker into lighter colors\n      default_color.setHslF (h, s, l_new, a);\n    }\n\n  return default_color;\n}\n\nQColor\ngui_settings::color_value (const gui_pref& pref, int mode) const\n{\n  QColor default_color = get_color_value (pref.def (), mode);\n\n  return value (pref.settings_key () + settings_color_modes_ext[mode],\n                QVariant (default_color)).value<QColor> ();\n}\n\nvoid\ngui_settings::set_color_value (const gui_pref& pref,\n                               const QColor& color, int mode)\n{\n  int m = mode;\n  if (m > 1)\n    m = 1;\n\n  setValue (pref.settings_key () + settings_color_modes_ext[m],\n            QVariant (color));\n}\n\nQString\ngui_settings::sc_value (const sc_pref& scpref) const\n{\n  QString full_settings_key = sc_group + \"/\" + scpref.settings_key ();\n\n  if (contains (full_settings_key))\n    {\n      QKeySequence key_seq = sc_def_value (scpref);\n\n      // Get the value from the settings where the key sequences are stored\n      // as strings\n      return value (full_settings_key, key_seq.toString (QKeySequence::NativeText)).toString ();\n    }\n  else\n    return scpref.def_text ();\n}\n\nQKeySequence\ngui_settings::sc_def_value (const sc_pref& scpref) const\n{\n  return scpref.def_value ();\n}\n\nvoid\ngui_settings::set_shortcut (QAction *action, const sc_pref& scpref, bool enable)\n{\n  if (! enable)\n    {\n      // Disable => remove existing shortcut from the action\n      action->setShortcut (QKeySequence ());\n      return;\n    }\n\n  QString shortcut = sc_value (scpref);\n  action->setShortcut (QKeySequence (shortcut));\n}\n\nvoid\ngui_settings::shortcut (QShortcut *sc, const sc_pref& scpref)\n{\n  QString shortcut = sc_value (scpref);\n  sc->setKey (QKeySequence (shortcut));\n}\n\nvoid\ngui_settings::config_icon_theme ()\n{\n  int theme_index;\n\n  if (contains (global_icon_theme_index.settings_key ()))\n    theme_index = int_value (global_icon_theme_index);\n  else\n    {\n      // New pref does not exist.  Use old if required.  Add new and\n      // remove deprecated key.\n\n      if (bool_value (global_icon_theme))\n        theme_index = ICON_THEME_SYSTEM;\n      else\n        theme_index = ICON_THEME_OCTAVE;\n\n      setValue (global_icon_theme_index.settings_key (), theme_index);\n      remove (global_icon_theme.settings_key ());\n    }\n\n  QIcon::setThemeName (global_all_icon_themes.at (theme_index));\n\n  QStringList icon_fallbacks;\n\n  // Set the required fallback search paths.\n\n  switch (theme_index)\n    {\n    case ICON_THEME_SYSTEM:\n      icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE);\n      icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO);\n      break;\n    case ICON_THEME_TANGO:\n      icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE);\n      break;\n    case ICON_THEME_OCTAVE:\n      icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO);\n      break;\n    }\n\n  icon_fallbacks << global_icon_paths.at (ICON_THEME_CURSORS);\n\n  setValue (global_icon_fallbacks.settings_key (), icon_fallbacks);\n}\n\nQIcon\ngui_settings::icon (const QString& icon_name, bool octave_only,\n                    const QString& icon_alt_name)\n{\n  if (octave_only)\n    return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE)\n                  + icon_name + global_icon_extension);\n\n  if (QIcon::hasThemeIcon (icon_name))\n    return QIcon (QIcon::fromTheme (icon_name));\n  else if ((! icon_alt_name.isEmpty ()) && QIcon::hasThemeIcon (icon_alt_name))\n    return QIcon (QIcon::fromTheme (icon_alt_name));\n\n  QStringList icon_fallbacks\n    = value (global_icon_fallbacks.settings_key ()).toStringList ();\n\n  for (int i = 0; i < icon_fallbacks.length (); i++ )\n    {\n      QString icon_file (icon_fallbacks.at (i)\n                         + icon_name + global_icon_extension);\n      if (QFile (icon_file).exists ())\n        return QIcon (icon_file);\n    }\n\n  //QIcon::setThemeName (current_theme);\n  return QIcon ();\n}\n\nQString\ngui_settings::get_default_font_family ()\n{\n  // Get all available fixed width fonts from the Qt font database.\n\n  QStringList fonts;\n\n#if defined (HAVE_QFONTDATABASE_STATIC_MEMBER_FUNCTIONS)\n  for (QString font : QFontDatabase::families ())\n    {\n      if (QFontDatabase::isFixedPitch (font))\n        fonts << font;\n    }\n#else\n  QFontDatabase font_database;\n\n  for (QString font : font_database.families ())\n    {\n      if (font_database.isFixedPitch (font))\n        fonts << font;\n    }\n#endif\n\n  QString default_family;\n\n#if defined (Q_OS_MAC)\n  // Use hard coded default on macOS, since selection of fixed width\n  // default font is unreliable (see bug #59128).\n  // Test for macOS default fixed width font\n  if (fonts.contains (global_mono_font.def ().toString ()))\n    default_family = global_mono_font.def ().toString ();\n#endif\n\n  // If default font is still empty (on all other platforms or\n  // if macOS default font is not available): use QFontDatabase\n  if (default_family.isEmpty ())\n    {\n      // Get the system's default monospaced font\n      QFont fixed_font = QFontDatabase::systemFont (QFontDatabase::FixedFont);\n      default_family = fixed_font.defaultFamily ();\n\n      // Since this might be unreliable, test all available fixed width fonts\n      if (! fonts.contains (default_family))\n        {\n          // Font returned by QFontDatabase is not in fixed fonts list.\n          // Fallback: take first from this list\n          default_family = fonts[0];\n        }\n    }\n\n  // Test env variable which has preference\n  std::string env_default_family = sys::env::getenv (\"OCTAVE_DEFAULT_FONT\");\n  if (! env_default_family.empty ())\n    default_family = QString::fromStdString (env_default_family);\n\n  return default_family;\n}\n\nQStringList\ngui_settings::get_default_font ()\n{\n  QString default_family = get_default_font_family ();\n\n  // determine the fefault font size of the system\n  // FIXME: QApplication::font () does not return the monospace font,\n  //        but the size should be probably near to the monospace font\n  QFont font = QApplication::font ();\n\n  int font_size = font.pointSize ();\n  if (font_size == -1)\n    font_size = static_cast<int> (std::floor (font.pointSizeF ()));\n\n  // check for valid font size, otherwise take default 10\n  QString default_font_size = \"10\";\n  if (font_size > 0)\n    default_font_size = QString::number (font_size);\n\n  std::string env_default_font_size\n    = sys::env::getenv (\"OCTAVE_DEFAULT_FONT_SIZE\");\n\n  if (! env_default_font_size.empty ())\n    default_font_size = QString::fromStdString (env_default_font_size);\n\n  QStringList result;\n  result << default_family;\n  result << default_font_size;\n  return result;\n}\n\nQString\ngui_settings::get_gui_translation_dir ()\n{\n  // get environment variable for the locale dir (e.g., from run-octave)\n  std::string dldir = sys::env::getenv (\"OCTAVE_LOCALE_DIR\");\n  if (dldir.empty ())\n    dldir = config::oct_locale_dir ();  // env-var empty, load the default location\n  return QString::fromStdString (dldir);\n}\n\nvoid\ngui_settings::load_translator (QTranslator *tr, const QLocale& locale, const QString& filename, const QString& prefix, const QString& directory) const\n{\n  if (! tr->load (locale, filename, prefix, directory))\n    qWarning () << \"failed to load translator for locale\" << locale.name () << \"from file\" << filename << \"with prefix\" << prefix << \"from directory\" << directory;\n}\n\nvoid\ngui_settings::load_translator (QTranslator *tr, const QString& prefix, const QString& language, const QString& directory) const\n{\n  if (! tr->load (prefix + language, directory))\n    if (! tr->load (prefix + language.toLower (), directory))\n      qWarning () << \"failed to load translator file\" << (prefix + language) << \"or\" << (prefix + language.toLower ()) << \"from directory\" << directory;\n}\n\nvoid\ngui_settings::config_translators (QTranslator *qt_tr,\n                                  QTranslator *qsci_tr,\n                                  QTranslator *gui_tr)\n{\n  QString qt_trans_dir\n#if defined (HAVE_QLIBRARYINFO_PATH)\n    = QLibraryInfo::path (QLibraryInfo::TranslationsPath);\n#else\n    = QLibraryInfo::location (QLibraryInfo::TranslationsPath);\n#endif\n\n  QString language = \"SYSTEM\";  // take system language per default\n\n  // FIXME: can we somehow ensure that the settings object will always\n  // be initialize and valid?\n\n  // get the locale from the settings if already available\n  language = string_value (global_language);\n\n  // load the translations depending on the settings\n  if (language == \"SYSTEM\")\n    {\n      // get the system locale and pass it to the translators for loading\n      // the suitable translation files\n      QLocale sys_locale = QLocale::system ();\n\n      load_translator (qt_tr, sys_locale, \"qt\", \"_\", qt_trans_dir);\n      load_translator (qsci_tr, sys_locale, \"qscintilla\", \"_\", qt_trans_dir);\n      load_translator (gui_tr, sys_locale, \"\", \"\", get_gui_translation_dir ());\n    }\n  else\n    {\n      // load the translation files depending on the given locale name\n      load_translator (qt_tr, \"qt_\", language, qt_trans_dir);\n      load_translator (qsci_tr, \"qscintilla_\", language, qt_trans_dir);\n      load_translator (gui_tr, \"\", language, get_gui_translation_dir ());\n    }\n}\n\nint\ngui_settings::get_valid_lexer_styles (QsciLexer *lexer, int *styles)\n{\n#if defined (HAVE_QSCINTILLA)\n  int max_style = 0;\n  int actual_style = 0;\n  while (actual_style < ed_max_style_number && max_style < ed_max_lexer_styles)\n    {\n      if ((lexer->description (actual_style)) != \"\")  // valid style\n        styles[max_style++] = actual_style;\n      actual_style++;\n    }\n\n  return max_style;\n#else\n  octave_unused_parameter (lexer);\n  octave_unused_parameter (styles);\n\n  return 0;\n#endif\n}\n\n#if defined (HAVE_QSCINTILLA)\n/*!\n * Copys the attributes bold, italic and underline from QFont\n * @p attr to the font @p base and returns the result without\n * changing @p base,\n * @param attr QFont with the desired attributes\n * @param base QFont with desired family and size\n */\nstatic QFont\ncopy_font_attributes (const QFont& attr, const QFont& base)\n{\n  QFont dest (base);\n\n  dest.setBold (attr.bold ());\n  dest.setItalic (attr.italic ());\n  dest.setUnderline (attr.underline ());\n\n  return dest;\n}\n#endif\n\nvoid\ngui_settings::read_lexer_settings (QsciLexer *lexer, int mode, int def)\n{\n#if defined (HAVE_QSCINTILLA)\n  // Test whether the settings for lexer is already contained in the\n  // given gui settings file.  If yes, load them, if not copy them from the\n  // default settings file.\n  // This is useful when a new language support is implemented and the\n  // existing settings file is used (which is of course the common case).\n  int m = mode;\n  if (m > 1)\n    m = 1;\n\n  QString group (\"Scintilla\" + settings_color_modes_ext[m]);\n\n  beginGroup (group);\n  beginGroup (lexer->language ());\n\n  QStringList lexer_keys = allKeys ();\n\n  endGroup ();\n  endGroup ();\n\n  if (def == settings_reload_default_colors_flag || lexer_keys.count () == 0)\n    {\n      // We have to reload the default values or no Lexer keys found:\n      // If mode == 0, take all settings except font from default lexer\n      // If Mode == 1, take all settings except font from default lexer\n      //               and convert the color by inverting the lightness\n\n      // Get the default font\n      QStringList def_font = get_default_font ();\n      QFont df (def_font[0], def_font[1].toInt ());\n      QFont dfa = copy_font_attributes (lexer->defaultFont (), df);\n      lexer->setDefaultFont (dfa);\n\n      QColor c, p;\n\n      int styles[ed_max_lexer_styles];  // array for saving valid styles\n      int max_style = get_valid_lexer_styles (lexer, styles);\n\n      for (int i = 0; i < max_style; i++)\n        {\n          c = get_color_value (QVariant (lexer->color (styles[i])), m);\n          lexer->setColor (c, styles[i]);\n          p = get_color_value (QVariant (lexer->paper (styles[i])), m);\n          lexer->setPaper (p, styles[i]);\n          dfa = copy_font_attributes (lexer->font (styles[i]), df);\n          lexer->setFont (dfa, styles[i]);\n        }\n      // Set defaults last for not changing the defaults of the styles\n      lexer->setDefaultColor (lexer->color (styles[0]));\n      lexer->setDefaultPaper (lexer->paper (styles[0]));\n\n      // Write settings if not just reload the default values\n      if (def != settings_reload_default_colors_flag)\n        {\n          const std::string group_str = group.toStdString ();\n          lexer->writeSettings (*this, group_str.c_str ());\n          sync ();\n        }\n    }\n  else\n    {\n      // Found lexer keys, read the settings\n      const std::string group_str = group.toStdString ();\n      lexer->readSettings (*this, group_str.c_str ());\n    }\n#else\n  octave_unused_parameter (lexer);\n  octave_unused_parameter (mode);\n  octave_unused_parameter (def);\n\n  return;\n#endif\n}\n\nbool\ngui_settings::update_settings_key (const QString& old_key,\n                                   const QString& new_key)\n{\n  if (contains (old_key))\n    {\n      QVariant preference = value (old_key);\n      setValue (new_key, preference);\n      remove (old_key);\n      return true;\n    }\n\n  return false;\n}\n\nvoid\ngui_settings::update_network_settings ()\n{\n  QNetworkProxy proxy;\n\n  // Assume no proxy and empty proxy data\n  QNetworkProxy::ProxyType proxy_type = QNetworkProxy::NoProxy;\n  QString scheme;\n  QString host;\n  int port = 0;\n  QString user;\n  QString pass;\n  QUrl proxy_url = QUrl ();\n\n  if (bool_value (global_use_proxy))\n    {\n      // Use a proxy, collect all required information\n      QString proxy_type_string = string_value (global_proxy_type);\n\n      // The proxy type for the Qt proxy settings\n      if (proxy_type_string == \"Socks5Proxy\")\n        proxy_type = QNetworkProxy::Socks5Proxy;\n      else if (proxy_type_string == \"HttpProxy\")\n        proxy_type = QNetworkProxy::HttpProxy;\n\n      // The proxy data from the settings\n      if (proxy_type_string == \"HttpProxy\"\n          || proxy_type_string == \"Socks5Proxy\")\n        {\n          host = string_value (global_proxy_host);\n          port = int_value (global_proxy_port);\n          user = string_value (global_proxy_user);\n          pass = string_value (global_proxy_pass);\n          if (proxy_type_string == \"HttpProxy\")\n            scheme = \"http\";\n          else if (proxy_type_string == \"Socks5Proxy\")\n            scheme = \"socks5\";\n\n          QUrl env_var_url = QUrl ();\n          proxy_url.setScheme (scheme);\n          proxy_url.setHost (host);\n          proxy_url.setPort (port);\n          if (! user.isEmpty ())\n            proxy_url.setUserName (user);\n          if (! pass.isEmpty ())\n            proxy_url.setPassword (pass);\n        }\n\n      // The proxy data from environment variables\n      if (proxy_type_string == global_proxy_all_types.at (2))\n        {\n          const std::array<std::string, 6> env_vars =\n          {\n            \"ALL_PROXY\", \"all_proxy\",\n            \"HTTP_PROXY\", \"http_proxy\",\n            \"HTTPS_PROXY\", \"https_proxy\"\n          };\n\n          unsigned int count = 0;\n          while (! proxy_url.isValid () && count < env_vars.size ())\n            {\n              proxy_url = QUrl (QString::fromStdString\n                                (sys::env::getenv (env_vars[count])));\n              count++;\n            }\n\n          if (proxy_url.isValid ())\n            {\n              // Found an entry, get the data from the string\n              scheme = proxy_url.scheme ();\n\n              if (scheme.contains (\"socks\", Qt::CaseInsensitive))\n                proxy_type = QNetworkProxy::Socks5Proxy;\n              else\n                proxy_type = QNetworkProxy::HttpProxy;\n\n              host = proxy_url.host ();\n              port = proxy_url.port ();\n              user = proxy_url.userName ();\n              pass = proxy_url.password ();\n            }\n        }\n    }\n\n  // Set proxy for Qt framework\n  proxy.setType (proxy_type);\n  proxy.setHostName (host);\n  proxy.setPort (port);\n  proxy.setUser (user);\n  proxy.setPassword (pass);\n\n  QNetworkProxy::setApplicationProxy (proxy);\n\n  // Set proxy for curl library if not based on environment variables\n  std::string proxy_url_str = proxy_url.toString ().toStdString ();\n  sys::env::putenv (\"http_proxy\", proxy_url_str);\n  sys::env::putenv (\"HTTP_PROXY\", proxy_url_str);\n  sys::env::putenv (\"https_proxy\", proxy_url_str);\n  sys::env::putenv (\"HTTPS_PROXY\", proxy_url_str);\n}\n\n// initialize a given combo box with available text encodings\nvoid\ngui_settings::combo_encoding (QComboBox *combo, const QString& current)\n{\n  std::vector<std::string> encoding_list {string::get_encoding_list ()};\n\n  // prepend SYSTEM\n  std::string locale_charset {octave_locale_charset_wrapper ()};\n  std::transform (locale_charset.begin (), locale_charset.end (),\n                  locale_charset.begin (), ::toupper);\n  locale_charset = \"SYSTEM (\" + locale_charset + \")\";\n  encoding_list.insert (encoding_list.begin (), locale_charset);\n\n  // get the value from the settings file if no current encoding is given\n  QString enc {current};\n\n  // Check for valid codec for the default.  If this fails, \"SYSTEM\" (i.e.,\n  // locale_charset) will be chosen.\n  // FIXME: The default is \"SYSTEM\" on all platforms.  So can this fallback\n  // logic be removed completely?\n  bool default_exists = false;\n  bool show_system = false;\n  if (ed_default_enc.def ().toString ().startsWith (\"SYSTEM\"))\n    show_system = true;\n  else if (std::find (encoding_list.begin (), encoding_list.end (),\n                      ed_default_enc.def ().toString ().toStdString ())\n           != encoding_list.end ())\n    default_exists = true;\n\n  QString default_enc = QString::fromStdString (locale_charset);\n\n  if (enc.isEmpty ())\n    {\n      enc = string_value (ed_default_enc);\n\n      if (enc.isEmpty ())  // still empty?\n        {\n          if (default_exists)\n            enc = ed_default_enc.def ().toString ();\n          else\n            enc = default_enc;\n        }\n    }\n\n  // fill the combo box\n  for (const auto& c : encoding_list)\n    combo->addItem (QString::fromStdString (c));\n\n  // prepend current encoding if not in list\n  if (combo->findText (enc, Qt::MatchExactly) < 0)\n    combo->insertItem (0, enc);\n\n  // prepend the default item\n  combo->insertSeparator (0);\n  if (show_system || ! default_exists)\n    combo->insertItem (0, default_enc);\n  else\n    combo->insertItem (0, ed_default_enc.def ().toString ());\n\n  // select the current encoding\n  combo->setCurrentIndex (combo->findText (enc, Qt::MatchExactly));\n\n  combo->setMaxVisibleItems (12);\n}\n\nvoid\ngui_settings::reload ()\n{\n  // Declare some empty options, which may be set at first startup for\n  // writing them into the newly created settings file\n  QString custom_editor;\n  QStringList def_font;\n\n  // Check whether the settings file does not yet exist\n  if (! QFile::exists (file_name ()))\n    {\n      // Get the default font (for terminal)\n      def_font = get_default_font ();\n\n      // Get a custom editor defined as env variable\n      std::string env_default_editor\n        = sys::env::getenv (\"OCTAVE_DEFAULT_EDITOR\");\n\n      if (! env_default_editor.empty ())\n        custom_editor = QString::fromStdString (env_default_editor);\n    }\n\n  check ();\n\n  // Write some settings that were dynamically determined at first startup\n\n  // Custom editor\n  if (! custom_editor.isEmpty ())\n    setValue (global_custom_editor.settings_key (), custom_editor);\n\n  // Default monospace font for the terminal\n  if (def_font.count () > 1)\n    {\n      setValue (cs_font.settings_key (), def_font[0]);\n      setValue (cs_font_size.settings_key (), def_font[1].toInt ());\n    }\n\n  // Write the default monospace font into the settings for later use by\n  // console and editor as fallbacks of their font preferences.\n  setValue (global_mono_font.settings_key (), get_default_font_family ());\n}\n\nvoid\ngui_settings::check ()\n{\n  if (status () == QSettings::NoError)\n    {\n      // Test usability (force file to be really created)\n      setValue (\"dummy\", 0);\n      sync ();\n    }\n\n  if (! (QFile::exists (file_name ())\n         && isWritable ()\n         && status () == QSettings::NoError))\n    {\n      QString msg\n        = QString (QT_TR_NOOP (\"Error %1 creating the settings file\\n%2\\n\"\n                               \"Make sure you have read and write permissions to\\n%3\\n\\n\"\n                               \"Octave GUI must be closed now.\"));\n\n      QMessageBox::critical (nullptr,\n                             QString (QT_TR_NOOP (\"Octave Critical Error\")),\n                             msg.arg (status ())\n                             .arg (file_name ())\n                             .arg (directory_name ()));\n\n      std::exit (EXIT_FAILURE);\n    }\n  else\n    remove (\"dummy\");  // Remove test entry\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/gui-settings.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_settings_h)\n#define octave_gui_settings_h 1\n\n#include <QColor>\n#include <QSettings>\n#include <QString>\n\nclass QByteArray;\nclass QComboBox;\nclass QDateTime;\nclass QIcon;\nclass QShortcut;\nclass QTranslator;\nclass QsciLexer;\n\n#include \"gui-preferences.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass gui_settings : public QSettings\n{\n  Q_OBJECT\n\npublic:\n\n  // Location, name, and format of settings file determined by\n  // settings in qt_application class construtor.\n\n  gui_settings (QObject *parent = nullptr)\n    : QSettings (parent)\n  { }\n\n  gui_settings (const QString& file_name, QSettings::Format format,\n                QObject *parent = nullptr)\n    : QSettings (file_name, format, parent)\n  { }\n\n  gui_settings (QSettings::Format format, QSettings::Scope scope,\n                const QString& organization,\n                const QString& application = QString (),\n                QObject *parent = nullptr)\n    : QSettings (format, scope, organization, application, parent)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (gui_settings)\n\n  ~gui_settings () = default;\n\n  QString file_name () const;\n\n  QString directory_name () const;\n\n  using QSettings::value;\n\n  QVariant value (const gui_pref& pref) const\n  {\n    if (pref.ignore ())\n      return pref.def ();  // ignore the current pref and always use default\n\n    return value (pref.settings_key (), pref.def ());\n  }\n\n  // Convenience functions to (slightly) reduce clutter by allowing us\n  // to write\n  //\n  //   settings.bool_value (gui_pref_name)\n  //\n  // instead of\n  //\n  //   settings.value (gui_pref_name).toBool ()\n\n  bool bool_value (const gui_pref& pref) const;\n\n  QByteArray byte_array_value (const gui_pref& pref) const;\n\n  QColor color_value (const gui_pref& pref) const;\n\n  QDateTime date_time_value (const gui_pref& pref) const;\n\n  int int_value (const gui_pref& pref) const;\n\n  QString string_value (const gui_pref& pref) const;\n\n  QStringList string_list_value (const gui_pref& pref) const;\n\n  uint uint_value (const gui_pref& pref) const;\n\n  /*!\n    Reading a color from the given QVariant @p def taking different\n    color modes into account.  The default value for a second color mode\n    @p mode=1 is deterimined from the standard default value @p mode=0\n    by inverting the lightness\n      \\f{eqnarray*}{\n         H_1 &=& H_0\\\\\n         S_1 &=& S_0\\\\\n         L_1 &=& 1.0 - 0.85 L_0    L_0 > 0.3\\\\\n         L_1 &=& 1.0 - 0.70 L_0    L_0 < 0.3\n      \\f}\n\n    @param def  Color default value given by a QVariant of QColor\n                or QPalette::ColorRole\n    @param mode Color mode (currently 0 or 1, default is 0)\n\n    @return Color as QColor\n  */\n  QColor get_color_value (const QVariant& def, int mode) const;\n\n  /*!\n    Reading a color from the gui_settings taking possible color modes\n    into account.  The default value for a second color mode @p mode=1 is\n    deterimined from the standard default value @p mode=0 by inverting\n    the lightness (see get_color_value ())\n\n    @param pref gui preference (key string, default value); the default\n                value can be given by QColor or QPalette::ColorRole\n    @param mode Color mode (currently 0 or 1, default is 0)\n\n    @return Color as QColor\n  */\n  QColor color_value (const gui_pref& pref, int mode) const;\n\n  /*!\n    Writing a color to the gui_settings taking possible color modes\n    into account.  When @p mode is not zero (standard mode), the\n    extension related to the mode is appended to the settings key string\n\n    @param pref gui preference where the color should be written\n    @param color QColor to write to the settings\n    @param mode Color mode (currently 0 or 1, default is 0)\n\n  */\n  void set_color_value (const gui_pref& pref, const QColor& color,\n                        int mode);\n\n  QString sc_value (const sc_pref& pref) const;\n\n  QKeySequence sc_def_value (const sc_pref& pref) const;\n\n  void set_shortcut (QAction *action, const sc_pref& scpref,\n                     bool enable = true);\n\n  void shortcut (QShortcut *sc, const sc_pref& scpref);\n\n  // config_icon_theme, icon, get_default_font_family,\n  // get_default_font, and possibly reload and check could be global\n  // functions instead of member functions.  But at least for the icon\n  // function, defining it as a member function means that we can\n  // create a single gui_settings object and access multiple icon\n  // objects rather than having to create a separate settings object\n  // each time that an icon is needed.  OTOH, creating the base\n  // QSettings object is supposed to be fast, so that may not matter.\n  // Hmm.\n\n  void config_icon_theme ();\n\n  QIcon icon (const QString& icon_name, bool octave_only = false,\n              const QString& icon_alt_name = QString ());\n\n  QString get_default_font_family ();\n\n  QStringList get_default_font ();\n\n  QString get_gui_translation_dir ();\n\n  void config_translators (QTranslator *qt_tr, QTranslator *qsci_tr,\n                           QTranslator *gui_tr);\n\n  int get_valid_lexer_styles (QsciLexer *lexer, int *styles);\n\n  void read_lexer_settings (QsciLexer *lexer, int mode = 0, int def = 0);\n\n  bool update_settings_key (const QString& new_key, const QString& old_key);\n\n  void update_network_settings ();\n\n  void combo_encoding (QComboBox *combo, const QString& current = QString ());\n\n  void reload ();\n\nprivate:\n\n  void load_translator (QTranslator *tr, const QLocale& locale, const QString& filename, const QString& prefix, const QString& directory) const;\n\n  void load_translator (QTranslator *tr, const QString& prefix, const QString& language, const QString& directory) const;\n\n  void check ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n// Some constants used in the preferences of several widgets and therefore\n// defined globally here\n\n// Constants for distinguishing between full GUI and dockwidgets initiated\n// from the command line\nconst QString settings_no_mainwin (\"__no_mainwin\");\n// Constants for handling different color schemes\nconst QColor settings_color_no_change (255, 0, 255);\nconst QStringList settings_color_modes_ext (QStringList () << \"\" << \"_2\");\nconst int settings_reload_default_colors_flag = -1;\n\n#endif\n"
  },
  {
    "path": "libgui/src/gui-utils.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QApplication>\n#include <QRect>\n#include <QScreen>\n\n#include \"gui-utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTGUI_API void\ncombobox_insert_current_item (QComboBox *cb, const QString& text)\n{\n  QString item_text = text;\n\n  if (item_text.isEmpty ())\n    item_text = cb->currentText ();\n\n  int idx;\n  while ((idx = cb->findText (item_text)) >= 0)\n    cb->removeItem (idx);\n\n  cb->insertItem (0, item_text);\n  cb->setCurrentIndex (0);\n}\n\nOCTGUI_API void\ncombobox_update (QComboBox *cb, const int cb_length)\n{\n  if (! cb || cb_length == 0)\n    return;\n\n  // Remove possible empty entries from the cb list\n  int index;\n  while ((index = cb->findText (QString ())) >= 0)\n    cb->removeItem (index);\n\n  // Get current text and return if it is empty\n  QString text = cb->currentText ();\n\n  if (text.isEmpty ())\n    return;\n\n  // Remove occurrences of the current text in the cb list\n  while ((index = cb->findText (text)) >= 0)\n    cb->removeItem (index);\n\n  // Remove the last entry from the end if the list is full\n  if (cb->count () == cb_length)\n    cb->removeItem (cb_length -1);\n\n  // Insert new item at the beginning and set it as current item\n  cb->insertItem (0, text);\n  cb->setCurrentIndex (0);\n}\n\nOCTGUI_API QColor\ninterpolate_color (const QColor& col1, const QColor& col2,\n                   double fs, double fv)\n{\n#if HAVE_QCOLOR_FLOAT_TYPE\n  float h1, s1, v1, h2, s2, v2;\n#else\n  qreal h1, s1, v1, h2, s2, v2;\n#endif\n\n  col1.getHsvF (&h1, &s1, &v1);\n  col2.getHsvF (&h2, &s2, &v2);\n\n  return QColor::fromHsvF (h1, s1*fs, v1 + fv*(v2 - v1));\n}\n\nOCTGUI_API void\nget_screen_geometry (int& width, int& height)\n{\n  QRect geom = QGuiApplication::primaryScreen ()->availableGeometry ();\n\n  width = geom.width ();\n  height = geom.height ();\n}\n\nOCTGUI_API void\nadjust_to_screen (QRect& actual_geometry, const QRect& default_geometry)\n{\n\n  // Get the screen that holds the largest part of the given actual geometry\n\n  const QScreen *actual_screen = nullptr;  // no screen found yet\n  QRect actual_screen_geom = QRect ();     // geometry of found screen\n  int intersected_area_max = 0;            // max. intersected area\n\n  const int area_actual_geometry\n    = actual_geometry.width () * actual_geometry.height ();\n  QRect intersection;\n\n  for (const QScreen *screen : QGuiApplication::screens ())\n    {\n      QRect screen_geom = screen->availableGeometry ();\n      intersection = screen_geom.intersected (actual_geometry);\n      if (! intersection.isEmpty ())\n        {\n          int area = intersection.width () * intersection.height ();\n          if (area > intersected_area_max)\n            {\n              actual_screen = screen;\n              actual_screen_geom = screen->availableGeometry ();\n              if (area == area_actual_geometry)\n                return;   // Actual geom is completely on a screen: return\n              intersected_area_max = area;\n            }\n        }\n    }\n\n  // If the actual geometry is on no screen, use deault geometry\n\n  if (actual_screen == nullptr)\n    {\n      actual_geometry = default_geometry;\n      return;\n    }\n\n  // There is a screen that holds a part of the actual geometry.\n  // Now adjust actual geometry to this screen\n\n  // Get some properties of the actual and intersected geometry\n  int agx1, agy1, agx2, agy2;\n  actual_geometry.getCoords (&agx1, &agy1, &agx2, &agy2);\n  int isx1, isy1, isx2, isy2;\n  intersection.getCoords (&isx1, &isy1, &isx2, &isy2);\n\n  // Make the intersection the same size as the actual geometry\n  if ((agx1 == isx1) && (agx2 != isx2))\n    isx1 = isx1 - agx2 + isx2;\n  if ((agx1 != isx1) && (agx2 == isx2))\n    isx2 = isx2 + agx2 - isx2;\n  if ((agy1 == isy1) && (agy2 != isy2))\n    isy1 = isy1 - agy2 + isy2;\n  if ((agy1 != isy1) && (agy2 == isy2))\n    isy2 = isy2 + agy2 - isy2;\n\n  // And compute again the intersection with the screen if this resizing\n  // led to corners outside the screen\n  actual_geometry\n    = actual_screen_geom.intersected (QRect (QPoint (isx1, isy1),\n                                             QPoint (isx2, isy2)));\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/gui-utils.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gui_utils_h)\n#define octave_gui_utils_h 1\n\n#include \"octave-config.h\"\n\n#include <QColor>\n#include <QComboBox>\n#include <QRect>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n/*!\n  Insert an item on top of a combobox list and remove it from the\n  list if it is in the list.\n\n  @param Pointer to the combo box\n  @param Qstring with the nee item text; if empty string,\n  the current text of the combobox is selected for updating\n*/\n\nextern OCTGUI_API void\ncombobox_insert_current_item  (QComboBox *cb, const QString& text);\n\n/*!\n  Update the most recently used list of a combo box.\n\n  @param Pointer to the combo box\n  @param Length of the mru list\n*/\n\nextern OCTGUI_API void\ncombobox_update (QComboBox *cb, const int cb_length);\n\n/*!\n  Determine an alternative color to @p col1 with less contrast\n  to @p col2.  The HSV representation of the new color is calculated by\n  \\f{eqnarray*}{\n  H &=& H_1\\\\\n  S &=& f_s S_1\\\\\n  V &=& V_1 + f_s (V_2 - V_1)\n  \\f}\n\n  @param col1 Base color to which the alternative has to be computed\n  @param col2 Color to which the new color should have less contrast\n  @param fs Factor for changing the saturation \\f$(0\\ldots\\infty)\\f$\n  @param fv Factor for interpolating the brightness \\f$(0\\ldots 1)\\f$.\n  For 0, \\f$V = V_1\\f$ and for 1, \\f$V = V_2\\f$.\n\n  @return New color as QColor\n*/\n\nextern OCTGUI_API QColor\ninterpolate_color (const QColor& col1, const QColor& col2,\n                   double fs, double fv);\n\n/*!\n  Get the screen geometry of the actual screen.\n\n  @param width integer variable for storing the screen width\n  @param height integer variable for storing the screen height\n*/\n\nextern OCTGUI_API void\nget_screen_geometry (int& width, int& height);\n\n/*!\n  Adjust geometry to be completely on a screen\n\n  @param actual_geometry QRect with actual widget geometry; this is\n  changed to the updated geometry which is on the screen.\n  @param default_geometry the default geometry that is used in case\n  the actual geometry os on no available screen.\n*/\nextern OCTGUI_API void\nadjust_to_screen (QRect& actual_geometry, const QRect& default_geometry);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/history-dock-widget.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QApplication>\n#include <QClipboard>\n#include <QCompleter>\n#include <QLabel>\n#include <QMenu>\n#include <QScrollBar>\n#include <QVBoxLayout>\n\n#include \"gui-preferences-cs.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-hw.h\"\n#include \"gui-settings.h\"\n#include \"gui-utils.h\"\n#include \"history-dock-widget.h\"\n\n#include \"cmd-hist.h\"\n\n#include \"error.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nhistory_dock_widget::history_dock_widget (QWidget *p)\n  : octave_dock_widget (\"HistoryDockWidget\", p)\n{\n  setStatusTip (tr (\"Browse and search the command history.\"));\n\n  construct ();\n\n  if (! p)\n    make_window ();\n}\n\nvoid\nhistory_dock_widget::set_history (const QStringList& hist)\n{\n  m_history_model->setStringList (hist);\n  m_history_list_view->scrollToBottom ();\n}\n\nvoid\nhistory_dock_widget::append_history (const QString& hist_entry)\n{\n  QStringList lst = m_history_model->stringList ();\n  lst.append (hist_entry);\n\n  QScrollBar *scroll_bar = m_history_list_view->verticalScrollBar ();\n\n  bool at_bottom = scroll_bar->maximum () - scroll_bar->value () < 1;\n\n  m_history_model->setStringList (lst);\n\n  // Scroll if slider position at bottom.\n  if (at_bottom)\n    m_history_list_view->scrollToBottom ();\n}\n\nvoid\nhistory_dock_widget::clear_history ()\n{\n  m_history_model->setStringList (QStringList ());\n}\n\nvoid\nhistory_dock_widget::save_settings ()\n{\n  gui_settings settings;\n\n  settings.setValue (hw_filter_active.settings_key (), m_filter_checkbox->isChecked ());\n  settings.setValue (hw_filter_shown.settings_key (), m_filter_shown);\n\n  QStringList mru;\n  for (int i = 0; i < m_filter->count (); i++)\n    mru.append (m_filter->itemText (i));\n  settings.setValue (hw_mru_list.settings_key (), mru);\n\n  settings.sync ();\n\n  octave_dock_widget::save_settings ();\n}\n\nvoid\nhistory_dock_widget::update_filter_history ()\n{\n  combobox_insert_current_item (m_filter, QString ());\n}\n\nvoid\nhistory_dock_widget::set_filter_focus (bool focus)\n{\n  if (focus)\n    {\n      m_filter->setFocus ();\n      setFocusProxy (m_filter);\n    }\n  else\n    {\n      m_history_list_view->setFocus ();\n      setFocusProxy (m_history_list_view);\n    }\n}\n\nvoid\nhistory_dock_widget::filter_activate (bool state)\n{\n  m_filter->setEnabled (state);\n  m_sort_filter_proxy_model.setDynamicSortFilter (state);\n\n  if (state)\n    m_sort_filter_proxy_model.setFilterWildcard (m_filter->currentText ());\n  else\n    m_sort_filter_proxy_model.setFilterWildcard (QString ());\n\n  set_filter_focus (state);\n}\n\nvoid\nhistory_dock_widget::ctxMenu (const QPoint& xpos)\n{\n  QMenu menu (this);\n\n  QModelIndex index = m_history_list_view->indexAt (xpos);\n\n  if (index.isValid () && index.column () == 0)\n    {\n      gui_settings settings;\n\n      menu.addAction (settings.icon (\"edit-copy\"), tr (\"Copy\"), this,\n                      &history_dock_widget::handle_contextmenu_copy);\n      menu.addAction (tr (\"Evaluate\"), this,\n                      &history_dock_widget::handle_contextmenu_evaluate);\n      menu.addAction (settings.icon (\"document-new\"), tr (\"Create script\"), this,\n                      &history_dock_widget::handle_contextmenu_create_script);\n      menu.addSeparator ();\n    }\n  if (m_filter_shown)\n    menu.addAction (tr (\"Hide filter\"), this,\n                    &history_dock_widget::handle_contextmenu_filter);\n  else\n    menu.addAction (tr (\"Show filter\"), this,\n                    &history_dock_widget::handle_contextmenu_filter);\n\n  menu.exec (m_history_list_view->mapToGlobal (xpos));\n}\n\nvoid\nhistory_dock_widget::handle_double_click (QModelIndex modelIndex)\n{\n  Q_EMIT command_double_clicked (modelIndex.data ().toString ());\n}\n\nvoid\nhistory_dock_widget::handle_contextmenu_copy (bool)\n{\n  QString text;\n  QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();\n  QModelIndexList rows = selectionModel->selectedRows ();\n  bool prev_valid_row = false;\n  for (const auto& it : rows)\n    {\n      if (it.isValid ())\n        {\n          if (prev_valid_row)\n            text += '\\n';\n          text += it.data ().toString ();\n          prev_valid_row = true;\n        }\n    }\n  QApplication::clipboard ()->setText (text);\n}\n\nvoid\nhistory_dock_widget::handle_contextmenu_evaluate (bool)\n{\n  QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();\n  QModelIndexList rows = selectionModel->selectedRows ();\n  for (const auto& it : rows)\n    if (it.isValid ())\n      Q_EMIT command_double_clicked (it.data ().toString ());\n}\n\nvoid\nhistory_dock_widget::handle_contextmenu_create_script (bool)\n{\n  QString text;\n  QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();\n  QModelIndexList rows = selectionModel->selectedRows ();\n\n  bool prev_valid_row = false;\n  for (const auto& it : rows)\n    {\n      if (it.isValid ())\n        {\n          if (prev_valid_row)\n            text += '\\n';\n          text += it.data ().toString ();\n          prev_valid_row = true;\n        }\n    }\n\n  if (text.length () > 0)\n    Q_EMIT command_create_script (text);\n}\n\nvoid\nhistory_dock_widget::handle_contextmenu_filter ()\n{\n  m_filter_shown = ! m_filter_shown;\n  m_filter_widget->setVisible (m_filter_shown);\n\n  set_filter_focus (m_filter_shown && m_filter_checkbox->isChecked ()) ;\n}\n\nvoid\nhistory_dock_widget::copyClipboard ()\n{\n  if (m_history_list_view->hasFocus ())\n    handle_contextmenu_copy (true);\n  if (m_filter->lineEdit ()->hasFocus ()\n      && m_filter->lineEdit ()->hasSelectedText ())\n    {\n      QClipboard *clipboard = QApplication::clipboard ();\n      clipboard->setText (m_filter->lineEdit ()->selectedText ());\n    }\n}\n\nvoid\nhistory_dock_widget::pasteClipboard ()\n{\n  if (m_filter->lineEdit ()->hasFocus ())\n    {\n      QClipboard *clipboard = QApplication::clipboard ();\n      QString str = clipboard->text ();\n      if (str.length () > 0)\n        m_filter->lineEdit ()->insert (str);\n    }\n}\n\nvoid\nhistory_dock_widget::selectAll ()\n{\n  if (m_filter->lineEdit ()->hasFocus ())\n    m_filter->lineEdit ()->selectAll ();\n\n  if (m_history_list_view->hasFocus ())\n    m_history_list_view->selectAll ();\n}\n\nvoid\nhistory_dock_widget::handle_visibility (bool visible)\n{\n  octave_dock_widget::handle_visibility (visible);\n\n  if (visible)\n    {\n      int filter_state = m_filter_checkbox->isChecked ();\n      filter_activate (filter_state);\n    }\n}\n\nvoid\nhistory_dock_widget::construct ()\n{\n  m_history_model = new QStringListModel ();\n  m_sort_filter_proxy_model.setSourceModel (m_history_model);\n  m_history_list_view = new QListView (this);\n  m_history_list_view->setModel (&m_sort_filter_proxy_model);\n  m_history_list_view->setAlternatingRowColors (true);\n  m_history_list_view->setEditTriggers (QAbstractItemView::NoEditTriggers);\n  m_history_list_view->setStatusTip\n    (tr (\"Double-click a command to transfer it to the Command Window.\"));\n  m_history_list_view->setSelectionMode (QAbstractItemView::ExtendedSelection);\n  m_history_list_view->setContextMenuPolicy (Qt::CustomContextMenu);\n  connect (m_history_list_view, &QListView::customContextMenuRequested,\n           this, &history_dock_widget::ctxMenu);\n\n  m_filter = new QComboBox (this);\n  m_filter->setToolTip (tr (\"Enter text to filter the command history\"));\n  m_filter->setEditable (true);\n  m_filter->setMaxCount (MaxFilterHistory);\n  m_filter->setInsertPolicy (QComboBox::NoInsert);\n  m_filter->setSizeAdjustPolicy\n    (QComboBox::AdjustToMinimumContentsLengthWithIcon);\n  QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);\n  m_filter->setSizePolicy (sizePol);\n  m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);\n\n  QLabel *filter_label = new QLabel (tr (\"Filter\"));\n\n  m_filter_checkbox = new QCheckBox ();\n\n  set_title (tr (\"Command History\"));\n  setWidget (new QWidget ());\n\n  m_filter_widget = new QWidget (this);\n  QHBoxLayout *filter_layout = new QHBoxLayout ();\n  filter_layout->addWidget (filter_label);\n  filter_layout->addWidget (m_filter_checkbox);\n  filter_layout->addWidget (m_filter);\n  filter_layout->setContentsMargins (0, 0, 0, 0);\n  m_filter_widget->setLayout (filter_layout);\n\n  QVBoxLayout *hist_layout = new QVBoxLayout ();\n  hist_layout->addWidget (m_filter_widget);\n  hist_layout->addWidget (m_history_list_view);\n\n  hist_layout->setContentsMargins (2, 2, 2, 2);\n  hist_layout->setSpacing (0);\n  widget ()->setLayout (hist_layout);\n\n  // Init state of the filter\n\n  gui_settings settings;\n\n  m_filter_shown = settings.bool_value (hw_filter_shown);\n  m_filter_widget->setVisible (m_filter_shown);\n\n  m_filter->addItems (settings.string_list_value (hw_mru_list));\n\n  bool filter_state = settings.bool_value (hw_filter_active);\n  m_filter_checkbox->setChecked (filter_state);\n  filter_activate (filter_state);\n\n  // Connect signals and slots\n  connect (m_filter, &QComboBox::editTextChanged,\n           &m_sort_filter_proxy_model,\n           &QSortFilterProxyModel::setFilterWildcard);\n  connect (m_filter_checkbox, &QCheckBox::toggled,\n           this, &history_dock_widget::filter_activate);\n  connect (m_filter->lineEdit (), &QLineEdit::editingFinished,\n           this, &history_dock_widget::update_filter_history);\n\n  connect (m_history_list_view, &QListView::doubleClicked,\n           this, &history_dock_widget::handle_double_click);\n\n  m_history_list_view->setTextElideMode (Qt::ElideRight);\n}\n\nvoid\nhistory_dock_widget::notice_settings ()\n{\n  gui_settings settings;\n\n  QFont font = QFont ();\n\n  font.setStyleHint (QFont::TypeWriter);\n  QString default_font = settings.string_value (global_mono_font);\n\n  font.setFamily (settings.value (cs_font.settings_key (), default_font).toString ());\n  font.setPointSize (settings.int_value (cs_font_size));\n\n  m_history_list_view->setFont (font);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/history-dock-widget.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_history_dock_widget_h)\n#define octave_history_dock_widget_h 1\n\n#include <QCheckBox>\n#include <QComboBox>\n#include <QLineEdit>\n#include <QListView>\n#include <QSortFilterProxyModel>\n#include <QStringListModel>\n\n#include \"octave-dock-widget.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass history_dock_widget : public octave_dock_widget\n{\n  Q_OBJECT\n\npublic:\n\n  history_dock_widget (QWidget *parent);\n\n  ~history_dock_widget () = default;\n\nQ_SIGNALS:\n\n  //! Signal emitted whenever the user double-clicks a command in the\n  //! history.\n\n  void command_double_clicked (const QString& command);\n\n  //! Signal emitted whenever the user selects commands and chooses\n  //! \"Create script\" from the popup menu.\n\n  void command_create_script (const QString& commands);\n\npublic Q_SLOTS:\n\n  void set_history (const QStringList& hist);\n  void append_history (const QString& hist_entry);\n  void clear_history ();\n  void save_settings ();\n  void notice_settings ();\n\nprivate Q_SLOTS:\n\n  void update_filter_history ();\n  void filter_activate (bool enable);\n\n  void ctxMenu (const QPoint& pos);\n  void handle_double_click (QModelIndex modelIndex);\n  void handle_contextmenu_copy (bool flag);\n  void handle_contextmenu_evaluate (bool flag);\n  void handle_contextmenu_create_script (bool flag);\n  void handle_contextmenu_filter ();\n\n  void copyClipboard ();\n  void pasteClipboard ();\n  void selectAll ();\n\n  virtual void handle_visibility (bool visible);\n\nprivate:\n\n  void construct ();\n  void set_filter_focus (bool focus);\n\n  QListView *m_history_list_view;\n  QSortFilterProxyModel m_sort_filter_proxy_model;\n\n  //! Stores the current history_model.\n\n  QStringListModel *m_history_model;\n\n  QCheckBox *m_filter_checkbox;\n  QComboBox *m_filter;\n  QWidget *m_filter_widget;\n  bool m_filter_shown;\n\n  enum { MaxFilterHistory = 10 };\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/icons/license.md",
    "content": "# Icons for Octave\n\n## Icons based on the Tango-Desktop-Project\n\nThe icons in the directory **tango** are taken from the Tango-Desktop-Projekt\n\n- [Tango-Desktop-Project](http://tango.freedesktop.org/Tango_Desktop_Project)\n- [Archive with base icon set](http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz)\n\nThe Tango base icon theme is released to the Public Domain.\n\nThe following icons excusively used by octave are created by the\nOctave developers using elements of the tango icon theme:\n\n- bp-next\n- bp-prev\n- bp-rm_all\n- bp-toggle\n- db-cont\n- db-step-in\n- db-step-out\n- db-step\n- db-stop\n- system-run\n\n\n## Icons by Octave developers\n\nThe icons in the directory **octave** are created by the Octave developers.\n\n### Icons by Luís Eduardo Ribeiro Guerra\n\nThe icons are maintained in this\n[repository on github](https://github.com/luisrguerra/cc0-fluent-icons)\nunder the CC0 1.0 Universal license.\n\n- applications-system\n- bookmark-new\n- bp-next\n- bp-prev\n- bp-rm-all\n- bp-toggle\n- db-cont\n- db-step-in\n- db-step-out\n- db-step\n- db-stop\n- dialog-error\n- dialog-information\n- document-new\n- document-open\n- document-print\n- document-save-as\n- document-save\n- edit-copy\n- edit-cut\n- edit-find-replace\n- edit-find\n- edit-paste\n- edit-redo\n- edit-undo\n- folder-new\n- figure-axes\n- figure-grid\n- figure-pan\n- figure-rotate\n- figure-text\n- figure-zoom-in\n- figure-zoom-original\n- figure-zoom-out\n- folder-settings\n- folder-up\n- folder\n- go-down\n- go-first\n- go-home\n- go-last\n- go-next\n- go-previous\n- go-up\n- system-run\n- user-home\n- view-zoom-in\n- view-zoom-out\n- view-zoom-original\n\n### Icons containing elements from the Tango theme\n\n- graphic_logo_DocumentationDockWidget\n- graphic_logo_Figure\n- graphic_logo_FileEditor\n- graphic_logo_FilesDockWidget\n- graphic_logo_HistoryDockWidget\n- graphic_logo_NewsDockWidget\n- graphic_logo_ReleaseWidget\n- graphic_logo_TerminalDockWidget\n- graphic_logo_WorkspaceView\n- letter_logo_DocumentationDockWidget\n- letter_logo_FileEditor\n- letter_logo_FilesDockWidget\n- letter_logo_HistoryDockWidget\n- letter_logo_NewsDockWidget\n- letter_logo_ReleaseWidget\n- letter_logo_TerminalDockWidget\n- letter_logo_WorkspaceView\n- plot-xy-curve\n\n### Icons created independently\n\n- logo\n- widget-close\n- widget-dock\n- widget-undock\n- window-close\n\n\n## Cursor icons\n\nThe directory **cursors** contains cursor icons required by Octave.\nThe following cursors are taken from the [standrad DMZ theme](https://github.com/GalliumOS/dmz-cursor-theme/tree/master/DMZ-White):\n\n- bottom_left_corner\n- bottom_right_corner\n- bottom_side\n- cross\n- fleur\n- hand2\n- left_side\n- right_side\n- top_left_corner\n- top_right_corner\n- top_side\n\n## Cursor created by the Octave developers\n\nThe following cursors are created by the Octave developers with elements from the DMZ theme:\n\n- circle\n"
  },
  {
    "path": "libgui/src/icons/octave/index.theme",
    "content": "[Icon Theme]\nName=Octave-icons\nComment=icon theme for octave\n\n# Directory list\nDirectories=scalable,128\n\n[scalable]\nSize=48\nMinSize=16\nMaxSize=512\nType=Scalable\n\n[128x128]\nSize=128\nMinSize=16\nMaxSize=512\nType=Scalable\n"
  },
  {
    "path": "libgui/src/icons/tango/index.theme",
    "content": "[Icon Theme]\nName=Tango-icons\nComment=icon theme tango\n\n# Directory list\nDirectories=scalable,128\n\n[scalable]\nSize=48\nMinSize=16\nMaxSize=512\nType=Scalable\n\n[128x128]\nSize=128\nMinSize=16\nMaxSize=512\nType=Scalable\n"
  },
  {
    "path": "libgui/src/interpreter-qobject.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"interpreter-qobject.h\"\n#include \"octave-qobject.h\"\n#include \"qt-application.h\"\n#include \"qt-interpreter-events.h\"\n\n#include \"graphics-init.h\"\n#include \"input.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ninterpreter_qobject::interpreter_qobject (base_qobject& oct_qobj)\n  : QObject (), m_octave_qobj (oct_qobj), m_interpreter (nullptr)\n{ }\n\nvoid\ninterpreter_qobject::execute ()\n{\n  // The Octave application context owns the interpreter.\n\n  qt_application& app_context = m_octave_qobj.app_context ();\n\n  interpreter& interp = app_context.create_interpreter ();\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.connect_link (m_octave_qobj.get_qt_interpreter_events ());\n  evmgr.install_qt_event_handlers (m_octave_qobj.get_qt_interpreter_events ());\n  evmgr.enable ();\n\n  int exit_status = 0;\n\n  try\n    {\n      // Final initialization.\n\n      interp.initialize ();\n\n      if (interp.is_initialized ())\n        {\n          // The interpreter should be completely ready at this point so let\n          // the GUI know.\n\n          m_interpreter = &interp;\n\n          Q_EMIT ready ();\n\n          graphics_init (interp);\n\n          // Start executing commands in the command window.\n\n          exit_status = interp.execute ();\n        }\n    }\n  catch (const exit_exception& xe)\n    {\n      exit_status = xe.exit_status ();\n    }\n\n  // FIXME: The following comment doesn't seem to make sense now.\n\n  // Signal that the interpreter is done executing code in the\n  // main REPL, from script files, or command line eval arguments.\n  // By using a signal here, we give the GUI a chance to process\n  // any pending events, then signal that it is safe to shutdown\n  // the interpreter.  Our notification here allows the GUI to\n  // insert the request to shutdown the interpreter in the event\n  // queue after any other pending signals.  The application\n  // context owns the interpreter and will be responsible for\n  // deleting it later, when the application object destructor is\n  // executed.\n\n  Q_EMIT shutdown_finished (exit_status);\n}\n\nvoid\ninterpreter_qobject::interpreter_event (const fcn_callback& fcn)\n{\n  if (! m_interpreter)\n    return;\n\n  event_manager& evmgr = m_interpreter->get_event_manager ();\n\n  evmgr.post_event (fcn);\n}\n\nvoid\ninterpreter_qobject::interpreter_event (const meth_callback& meth)\n{\n  if (! m_interpreter)\n    return;\n\n  event_manager& evmgr = m_interpreter->get_event_manager ();\n\n  evmgr.post_event (meth);\n}\n\nvoid\ninterpreter_qobject::interrupt ()\n{\n  if (! m_interpreter)\n    return;\n\n  // The following is a direct function call across threads.\n  // We need to ensure that it uses thread-safe functions.\n\n  m_interpreter->interrupt ();\n}\n\nvoid\ninterpreter_qobject::pause ()\n{\n  // FIXME: Should we make this action work with the old terminal\n  // widget?\n\n  if (m_octave_qobj.experimental_terminal_widget ())\n    {\n      if (! m_interpreter)\n        return;\n\n      // The following is a direct function call across threads.\n      // We need to ensure that it uses thread-safe functions.\n\n      m_interpreter->pause ();\n    }\n}\n\nvoid\ninterpreter_qobject::stop ()\n{\n  // FIXME: Should we make this action work with the old terminal\n  // widget?\n\n  if (m_octave_qobj.experimental_terminal_widget ())\n    {\n      if (! m_interpreter)\n        return;\n\n      // The following is a direct function call across threads.\n      // We need to ensure that it uses thread-safe functions.\n\n      m_interpreter->stop ();\n    }\n}\n\nvoid\ninterpreter_qobject::resume ()\n{\n  // FIXME: Should we make this action work with the old terminal\n  // widget?\n\n  if (m_octave_qobj.experimental_terminal_widget ())\n    {\n      // FIXME: This action should only be available when the\n      // interpreter is paused.\n\n      interpreter_event\n        ([] (interpreter& interp)\n        {\n          // INTERPRETER THREAD\n\n          interp.resume ();\n        });\n    }\n}\n\nqt_interpreter_events *\ninterpreter_qobject::qt_link ()\n{\n  return m_octave_qobj.qt_link ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/interpreter-qobject.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_interpreter_qobject_h)\n#define octave_interpreter_qobject_h 1\n\n#include <QObject>\n\n#include \"qt-interpreter-events.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass base_qobject;\n\nclass interpreter_qobject : public QObject\n{\n  Q_OBJECT\n\npublic:\n\n  interpreter_qobject (base_qobject& oct_qobj);\n\n  ~interpreter_qobject () = default;\n\n  qt_interpreter_events * qt_link ();\n\n  void interpreter_event (const fcn_callback& fcn);\n\n  void interpreter_event (const meth_callback& meth);\n\n  void interrupt ();\n\n  // Note: PAUSE, STOP, and RESUME are currently only used by the new\n  // experimental terminal widget.\n  void pause ();\n  void stop ();\n  void resume ();\n\nQ_SIGNALS:\n\n  void ready ();\n\n  void shutdown_finished (int);\n\npublic Q_SLOTS:\n\n  // Programming Note: With the current design of the interpreter,\n  // additional signals will not be noticed because the execute\n  // function starts the Octave interpreter and it doesn't return\n  // until the interpreter exits.  So the Qt event loop running in the\n  // thread where the interpreter_qobject object lives never has a\n  // chance to see another signal.  Changing the design of the\n  // terminal widget as proposed and discussed here:\n  //\n  //   https://lists.gnu.org/archive/html/octave-maintainers/2019-05/msg00115.html\n  //   https://lists.gnu.org/archive/html/octave-maintainers/2019-06/msg00009.html\n  //\n  // coulld solve that problem.  Briefly, instead of having the Octave\n  // interpreter block and wait for keyboard input, the terminal\n  // widget would be in charge of accepting keyboard events and use\n  // readline in callback mode.  Then the terminal widget and the\n  // interpreter will not block except when executing code.  Then we\n  // could have the interpreter qobject directly accept signals.\n\n  //! Initialize and execute the octave interpreter.\n\n  void execute ();\n\nprivate:\n\n  base_qobject& m_octave_qobj;\n\n  interpreter *m_interpreter;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/led-indicator.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QColor>\n\n#include \"gui-utils.h\"\n#include \"led-indicator.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nled_indicator::led_indicator (led_state initial_state, QWidget *p)\n  : QLabel (p)\n{\n  setFixedSize (12, 12);\n  set_state (initial_state);\n}\n\nvoid\nled_indicator::set_state (led_state state)\n{\n  QColor col (Qt::gray);\n\n  switch (state)\n    {\n    case LED_STATE_NO:\n      break;\n\n    case LED_STATE_INACTIVE:\n      col = QColor (Qt::darkGray);\n      col.setRedF (col.redF () * 1.25);\n      break;\n\n    case LED_STATE_ACTIVE:\n      col = QColor (Qt::red);\n      break;\n    }\n\n  setStyleSheet (style_sheet (col));\n}\n\nQString\nled_indicator::style_sheet (const QColor& col)\n{\n  QColor col_light = interpolate_color (col, QColor (Qt::white), 0.25, 0.9);\n\n  const QString style\n    = QString (\"border-radius: %1; background-color: \"\n               \"qlineargradient(spread:pad, x1:0.2, y1:0.2, x2:1, y2:1, stop:0 \"\n               \"%2, stop:1 %3);\").arg (width ()/2).arg (col_light.name ()).arg (col.name ());\n\n  return style;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/led-indicator.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (led_indicator_h)\n#define led_indicator_h 1\n\n#include <QLabel>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass led_indicator: public QLabel\n{\n  Q_OBJECT\n\npublic:\n\n  enum led_state\n  {\n    LED_STATE_NO = -1,\n    LED_STATE_INACTIVE,\n    LED_STATE_ACTIVE\n  };\n\n  led_indicator (led_state initial_state = LED_STATE_INACTIVE,\n                 QWidget *parent = 0);\n\npublic Q_SLOTS:\n\n  void set_state (led_state state);\n\nprivate:\n\n  QString style_sheet (const QColor& col);\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/file-editor-interface.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_file_editor_interface_h)\n#define octave_file_editor_interface_h 1\n\n#include <QMenu>\n#include <QMenuBar>\n#include <QToolBar>\n\n#include \"octave-dock-widget.h\"\n#include \"find-files-dialog.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass file_editor_interface : public octave_dock_widget\n{\n  Q_OBJECT\n\npublic:\n\n  file_editor_interface (QWidget *p)\n    : octave_dock_widget (\"FileEditor\", p)\n  { }\n\n  virtual ~file_editor_interface () = default;\n\n  virtual QMenu * get_mru_menu () = 0;\n  virtual QMenu * debug_menu () = 0;\n  virtual QToolBar * toolbar () = 0;\n  virtual QMenuBar * menubar () = 0;\n\n  virtual void insert_global_actions (QList<QAction *>) = 0;\n  virtual void handle_enter_debug_mode () = 0;\n  virtual void handle_exit_debug_mode () = 0;\n\n  virtual void\n  handle_insert_debugger_pointer_request (const QString& file, int line) = 0;\n\n  virtual void\n  handle_delete_debugger_pointer_request (const QString& file, int line) = 0;\n\n  virtual void\n  handle_update_breakpoint_marker_request (bool insert, const QString& file,\n      int line, const QString& cond) = 0;\n\n  virtual void handle_edit_file_request (const QString& file) = 0;\n\n  virtual bool check_closing () = 0;\n\n  virtual void empty_script (bool, bool) = 0;\n\n  virtual void restore_session (bool) = 0;\n\n  virtual void enable_menu_shortcuts (bool enable) = 0;\n\n  virtual const QString get_current_filename () = 0;\n\nQ_SIGNALS:\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  virtual void toplevel_change (bool) = 0;\n\n  virtual void handle_file_remove (const QString& o, const QString& n) = 0;\n\n  virtual void request_new_file (const QString& command = QString ()) = 0;\n\n  virtual void request_open_file (const QString& openFileName,\n                                  const QString& encoding = QString (),\n                                  int line = -1,\n                                  bool debug_pointer = false,\n                                  bool breakpoint_marker = false,\n                                  bool insert = true,\n                                  const QString& cond = \"\",\n                                  int index = -1,\n                                  const QString& bookmarks = QString (),\n                                  const find_files_data& ff_data = {}) = 0;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/file-editor-tab.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n//! @file file-editor-tab.cc A single GUI file tab.\n//!\n//! This interfaces QsciScintilla with the rest of Octave.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_QSCINTILLA)\n\n#include <QApplication>\n#include <QCheckBox>\n#include <QDateTime>\n#include <QDesktopServices>\n#include <QDialogButtonBox>\n#include <QFileDialog>\n#include <QInputDialog>\n#include <QLabel>\n#include <QMessageBox>\n#include <QPrintDialog>\n#include <QPushButton>\n#include <QRegularExpression>\n#include <QScrollBar>\n#include <QSaveFile>\n#include <QStandardPaths>\n#include <QStyle>\n#include <QTextBlock>\n#include <QTextStream>\n#include <QVBoxLayout>\n\n#if defined (HAVE_QSCI_QSCILEXEROCTAVE_H)\n#  define HAVE_LEXER_OCTAVE 1\n#  include <Qsci/qscilexeroctave.h>\n#elif defined (HAVE_QSCI_QSCILEXERMATLAB_H)\n#  define HAVE_LEXER_MATLAB 1\n#  include <Qsci/qscilexermatlab.h>\n#endif\n#include <Qsci/qscilexerbash.h>\n#include <Qsci/qscilexerbatch.h>\n#include <Qsci/qscilexercpp.h>\n#include <Qsci/qscilexerjava.h>\n#include <Qsci/qscilexerdiff.h>\n#include <Qsci/qscilexerperl.h>\n#include <Qsci/qsciprinter.h>\n\n#include \"gui-preferences-cs.h\"\n#include \"gui-preferences-ed.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-settings.h\"\n#include \"gui-utils.h\"\n#include \"main-window.h\"\n#include \"file-editor-tab.h\"\n#include \"file-editor.h\"\n#include \"marker.h\"\n#include \"octave-txt-lexer.h\"\n\n#include \"cmd-edit.h\"\n#include \"file-ops.h\"\n#include \"iconv-wrappers.h\"\n#include \"localcharset-wrapper.h\"\n#include \"uniconv-wrappers.h\"\n\n#include \"bp-table.h\"\n#include \"builtin-defun-decls.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"oct-map.h\"\n#include \"ov-usr-fcn.h\"\n#include \"qt-interpreter-events.h\"\n#include \"symtab.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"version.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n//! A file_editor_tab object consists of a text area and three left margins.\n//! The first holds breakpoints, bookmarks, and the debug program counter.\n//! The second holds line numbers.  The third holds \"fold\" marks, to hide\n//! sections of text.\n\n// Make parent null for the file editor tab so that warning WindowModal\n// messages don't affect grandparents.\nfile_editor_tab::file_editor_tab (const QString& directory_arg)\n{\n  m_lexer_apis = nullptr;\n  m_copy_available = false;\n  m_is_octave_file = true;\n  m_lines_changed = false;\n  m_autoc_active = false;\n\n  m_ced = directory_arg;\n\n  m_file_name = \"\";\n  m_file_system_watcher.setObjectName (\"_qt_autotest_force_engine_poller\");\n\n  m_edit_area = new octave_qscintilla (this);\n  m_line = 0;\n  m_col  = 0;\n\n  m_bp_lines.clear ();      // start with empty lists of breakpoints\n  m_bp_conditions.clear ();\n  m_bp_restore_count = 0;\n\n  m_breakpoint_info.remove_next = false;\n  m_breakpoint_info.remove_line = -1;\n\n  // Initialize last modification date to now\n  m_last_modified = QDateTime::currentDateTimeUtc ();\n\n  connect (m_edit_area, SIGNAL (cursorPositionChanged (int, int)),\n           this, SLOT (handle_cursor_moved (int, int)));\n\n  connect (m_edit_area, SIGNAL (SCN_CHARADDED (int)),\n           this, SLOT (handle_char_added (int)));\n\n  connect (m_edit_area, SIGNAL (SCN_DOUBLECLICK (int, int, int)),\n           this, SLOT (handle_double_click (int, int, int)));\n\n  connect (m_edit_area, SIGNAL (linesChanged ()),\n           this, SLOT (handle_lines_changed ()));\n\n  connect (m_edit_area, &octave_qscintilla::context_menu_edit_signal,\n           this, &file_editor_tab::handle_context_menu_edit);\n\n  connect (m_edit_area, &octave_qscintilla::update_rowcol_indicator_signal,\n           this, &file_editor_tab::update_rowcol_indicator);\n\n  // create statusbar for row/col indicator and eol mode\n  m_status_bar = new QStatusBar (this);\n\n  // row- and col-indicator\n  m_row_indicator = new QLabel (\"\", this);\n  QFontMetrics fm = m_row_indicator->fontMetrics ();\n  m_row_indicator->setMinimumSize (4.5*fm.averageCharWidth (), 0);\n  QLabel *row_label = new QLabel (tr (\"line:\"), this);\n  m_col_indicator = new QLabel (\"\", this);\n  m_col_indicator->setMinimumSize (4*fm.averageCharWidth (), 0);\n  QLabel *col_label = new QLabel (tr (\"col:\"), this);\n  m_status_bar->addWidget (row_label, 0);\n  m_status_bar->addWidget (m_row_indicator, 0);\n  m_status_bar->addWidget (col_label, 0);\n  m_status_bar->addWidget (m_col_indicator, 0);\n\n  // status bar: encoding\n  QLabel *enc_label = new QLabel (tr (\"encoding:\"), this);\n  m_enc_indicator = new QLabel (\"\", this);\n  m_status_bar->addWidget (enc_label, 0);\n  m_status_bar->addWidget (m_enc_indicator, 0);\n  m_status_bar->addWidget (new QLabel (\" \", this), 0);\n\n  // status bar: eol mode\n  QLabel *eol_label = new QLabel (tr (\"eol:\"), this);\n  m_eol_indicator = new QLabel (\"\", this);\n  m_status_bar->addWidget (eol_label, 0);\n  m_status_bar->addWidget (m_eol_indicator, 0);\n  m_status_bar->addWidget (new QLabel (\" \", this), 0);\n\n  // symbols\n  m_edit_area->setMarginType (1, QsciScintilla::SymbolMargin);\n  m_edit_area->setMarginSensitivity (1, true);\n  m_edit_area->markerDefine (QsciScintilla::RightTriangle, marker::bookmark);\n  m_edit_area->setMarkerBackgroundColor (QColor (0, 0, 232), marker::bookmark);\n  m_edit_area->markerDefine (QsciScintilla::Circle, marker::breakpoint);\n  m_edit_area->setMarkerBackgroundColor (QColor (192, 0, 0), marker::breakpoint);\n  m_edit_area->markerDefine (QsciScintilla::Circle, marker::cond_break);\n  m_edit_area->setMarkerBackgroundColor (QColor (255, 127, 0), marker::cond_break);\n  m_edit_area->markerDefine (QsciScintilla::RightArrow,\n                             marker::debugger_position);\n  m_edit_area->setMarkerBackgroundColor (QColor (255, 255, 0),\n                                         marker::debugger_position);\n  m_edit_area->markerDefine (QsciScintilla::RightArrow,\n                             marker::unsure_debugger_position);\n  m_edit_area->setMarkerBackgroundColor (QColor (192, 192, 192),\n                                         marker::unsure_debugger_position);\n\n  connect (m_edit_area, SIGNAL (marginClicked (int, int,\n                                Qt::KeyboardModifiers)),\n           this, SLOT (handle_margin_clicked (int, int,\n                       Qt::KeyboardModifiers)));\n\n  connect (m_edit_area, &octave_qscintilla::context_menu_break_condition_signal,\n           this, &file_editor_tab::handle_context_menu_break_condition);\n\n  // line numbers\n  m_edit_area->setMarginsForegroundColor (QColor (96, 96, 96));\n  m_edit_area->setMarginsBackgroundColor (QColor (232, 232, 220));\n  m_edit_area->setMarginType (2, QsciScintilla::TextMargin);\n\n  // other features\n  m_edit_area->setBraceMatching (QsciScintilla::StrictBraceMatch);\n  m_edit_area->setAutoIndent (true);\n  m_edit_area->setIndentationWidth (2);\n  m_edit_area->setIndentationsUseTabs (false);\n\n  m_edit_area->setUtf8 (true);\n\n  // auto completion\n  m_edit_area->SendScintilla (QsciScintillaBase::SCI_AUTOCSETCANCELATSTART, false);\n\n  QVBoxLayout *edit_area_layout = new QVBoxLayout ();\n  edit_area_layout->addWidget (m_edit_area);\n  edit_area_layout->addWidget (m_status_bar);\n  edit_area_layout->setContentsMargins (0, 0, 0, 0);\n  edit_area_layout->setSpacing (0);\n  setLayout (edit_area_layout);\n\n  // Any interpreter_event signal from a file_editor_tab_widget is\n  // handled the same as for the parent main_window object.\n\n  connect (m_edit_area, qOverload<const fcn_callback&> (&octave_qscintilla::interpreter_event),\n           this, qOverload<const fcn_callback&> (&file_editor_tab::interpreter_event));\n\n  connect (m_edit_area, qOverload<const meth_callback&> (&octave_qscintilla::interpreter_event),\n           this, qOverload<const meth_callback&> (&file_editor_tab::interpreter_event));\n\n  // connect modified signal\n  connect (m_edit_area, SIGNAL (modificationChanged (bool)),\n           this, SLOT (update_window_title (bool)));\n\n  connect (m_edit_area, SIGNAL (copyAvailable (bool)),\n           this, SLOT (handle_copy_available (bool)));\n\n  connect (&m_file_system_watcher, &QFileSystemWatcher::fileChanged,\n  this, [this] (const QString& path) { file_has_changed (path); });\n\n  connect (this, &file_editor_tab::maybe_remove_next,\n           this, &file_editor_tab::handle_remove_next);\n\n  connect (this, &file_editor_tab::dbstop_if,\n           this, &file_editor_tab::handle_dbstop_if);\n\n  connect (this, &file_editor_tab::request_add_breakpoint,\n           this, &file_editor_tab::handle_request_add_breakpoint);\n\n  connect (this, &file_editor_tab::api_entries_added,\n           this, &file_editor_tab::handle_api_entries_added);\n\n  connect (this, &file_editor_tab::confirm_dbquit_and_save_signal,\n           this, &file_editor_tab::confirm_dbquit_and_save);\n\n  connect (this, &file_editor_tab::do_save_file_signal,\n           this, &file_editor_tab::do_save_file);\n\n  notice_settings (true);\n\n  gui_settings settings;\n\n  // encoding, not updated with the settings\n  m_encoding = settings.value (ed_default_enc.settings_key (), \"UTF-8\").toString ();\n  m_enc_indicator->setText (m_encoding);\n  // no changes in encoding yet\n  m_new_encoding = m_encoding;\n}\n\nfile_editor_tab::~file_editor_tab ()\n{\n  // Tell all connected markers to self-destruct.\n  Q_EMIT remove_all_breakpoints_signal ();\n  Q_EMIT remove_all_positions ();\n\n  // Destroy lexer attached to m_edit_area, which is not the parent\n  // of lexer\n  QsciLexer *lexer = m_edit_area->lexer ();\n  if (lexer)\n    {\n      delete lexer;\n      m_edit_area->setLexer (nullptr);\n    }\n}\n\nvoid\nfile_editor_tab::set_encoding (const QString& new_encoding)\n{\n  if (new_encoding.isEmpty ())\n    return;\n\n  m_encoding = new_encoding;\n  m_enc_indicator->setText (m_encoding);\n  if (! m_edit_area->text ().isEmpty ())\n    set_modified (true);\n}\n\nvoid\nfile_editor_tab::closeEvent (QCloseEvent *e)\n{\n  int save_dialog = check_file_modified (true);\n  if ((save_dialog == QMessageBox::Cancel) ||\n      (save_dialog == QMessageBox::Save))\n    {\n      // Ignore close event if file is saved or user cancels\n      // closing this window.  In case of saving, tab is closed after\n      // successful saving.\n      e->ignore ();\n    }\n  else\n    {\n      e->accept ();\n      Q_EMIT tab_remove_request (m_file_name);\n    }\n}\n\nvoid\nfile_editor_tab::set_current_directory (const QString& dir)\n{\n  m_ced = dir;\n}\n\nvoid\nfile_editor_tab::handle_context_menu_edit (const QString& word_at_cursor)\n{\n  // Search for a function with that name in the current file\n  // This is done first because local functions and subfunctions have priority\n  // over other functions with the same name in the load path.\n  QRegularExpression rxfun1 {\"^[\\t ]*function[^=]+=[\\t ]*\"\n                             + word_at_cursor + \"[\\t ]*\\\\([^\\\\)]*\\\\)[\\t ]*$\"};\n  QRegularExpression rxfun2 {\"^[\\t ]*function[\\t ]+\"\n                             + word_at_cursor + \"[\\t ]*\\\\([^\\\\)]*\\\\)[\\t ]*$\"};\n  QRegularExpression rxfun3 {\"^[\\t ]*function[\\t ]+\"\n                             + word_at_cursor + \"[\\t ]*$\"};\n  QRegularExpression rxfun4 {\"^[\\t ]*function[^=]+=[\\t ]*\"\n                             + word_at_cursor + \"[\\t ]*$\"};\n\n  QRegularExpressionMatch match;\n  QStringList lines = m_edit_area->text ().split (\"\\n\");\n\n  int line;\n  for (line = 0; line < lines.count (); line++)\n    {\n      match = rxfun1.match (lines.at (line));\n      if (match.hasMatch ())\n        break;\n      match = rxfun2.match (lines.at (line));\n      if (match.hasMatch ())\n        break;\n      match = rxfun3.match (lines.at (line));\n      if (match.hasMatch ())\n        break;\n      match = rxfun4.match (lines.at (line));\n      if (match.hasMatch ())\n        break;\n    }\n\n  if (match.hasMatch ())\n    {\n      // reg expr. found: it is an internal function\n      m_edit_area->setCursorPosition (line, match.capturedStart ());\n      m_edit_area->SendScintilla (2232, line);     // SCI_ENSUREVISIBLE\n                                                   // SCI_VISIBLEFROMDOCLINE\n      int vis_line = m_edit_area->SendScintilla (2220, line);\n      m_edit_area->SendScintilla (2613, vis_line); // SCI_SETFIRSTVISIBLELINE\n      return;\n    }\n\n  Q_EMIT edit_mfile_request (word_at_cursor, m_file_name, m_ced, -1);\n}\n\n// If \"dbstop if ...\" selected from context menu, create a conditional\n// breakpoint.  The default condition is (a) the existing condition if there\n// is already a breakpoint, (b) any selected text, or (c) empty\nvoid\nfile_editor_tab::handle_context_menu_break_condition (int linenr)\n{\n  // Ensure editor line numbers match Octave core's line numbers.\n  // Give users the option to save modifications if necessary.\n  if (! unchanged_or_saved ())\n    return;\n\n  QString cond;\n\n  // Search for previous condition.  FIXME: is there a more direct way?\n  if (m_edit_area->markersAtLine (linenr) & (1 << marker::cond_break))\n    {\n      Q_EMIT report_marker_linenr (m_bp_lines, m_bp_conditions);\n      for (int i = 0; i < m_bp_lines.length (); i++)\n        if (m_bp_lines.value (i) == linenr)\n          {\n            cond = m_bp_conditions.value (i);\n            break;\n          }\n      m_bp_lines.clear ();\n      m_bp_conditions.clear ();\n    }\n\n  // If text selected by the mouse, default to that instead\n  // If both present, use the OR of them, to avoid accidental overwriting\n  // FIXME: If both are present, show old condition unselected and\n  //        the selection (in edit area) selected (in the dialog).\n  if (m_edit_area->hasSelectedText ())\n    {\n      if (cond == \"\")\n        cond = m_edit_area->selectedText ();\n      else\n        cond = '(' + cond + \") || (\" + m_edit_area->selectedText () + ')';\n    }\n\n  Q_EMIT dbstop_if (\"dbstop if\", linenr+1, cond);\n}\n\n// Display dialog in GUI thread to get condition, then emit\n// interpreter_event signal to check it in the interpreter thread.\n// If the dialog returns a valid condition, then either emit a signal\n// to add the breakpoint in the editor tab or a signal to display a\n// new dialog.\n\nvoid\nfile_editor_tab::handle_dbstop_if (const QString& prompt, int line,\n                                   const QString& cond)\n{\n  bool ok;\n  QString new_cond\n    = QInputDialog::getText (this, tr (\"Breakpoint condition\"),\n                             prompt, QLineEdit::Normal, cond, &ok);\n\n  // If cancel, don't change breakpoint condition.\n\n  if (ok && ! new_cond.isEmpty ())\n    {\n      // The interpreter_event callback function below emits a signal.\n      // Because we don't control when that happens, use a guarded\n      // pointer so that the callback can abort if this object is no\n      // longer valid.\n\n      QPointer<file_editor_tab> this_fetab (this);\n\n      Q_EMIT interpreter_event\n      ([this, this_fetab, line, new_cond] (interpreter& interp)\n      {\n        // INTERPRETER THREAD\n\n        // We are intentionally skipping any side effects that may\n        // occur in the evaluation of NEW_COND if THIS_FETAB is no\n        // longer valid.\n\n        if (this_fetab.isNull ())\n          return;\n\n        error_system& es = interp.get_error_system ();\n\n        unwind_protect frame;\n\n        // Prevent an error in the evaluation here from sending us\n        // into the debugger.\n\n        es.interpreter_try (frame);\n\n        bool eval_error = false;\n        std::string msg;\n\n        try\n          {\n            tree_evaluator& tw = interp.get_evaluator ();\n            bp_table& bptab = tw.get_bp_table ();\n\n            bptab.condition_valid (new_cond.toStdString ());\n\n            // The condition seems OK, so set the conditional\n            // breakpoint.\n\n            Q_EMIT request_add_breakpoint (line, new_cond);\n          }\n        catch (const execution_exception& ee)\n          {\n            interp.recover_from_exception ();\n\n            msg = ee.message ();\n            eval_error = true;\n          }\n        catch (const interrupt_exception&)\n          {\n            interp.recover_from_exception ();\n\n            msg = \"evaluation interrupted\";\n            eval_error = true;\n          }\n\n        if (eval_error)\n          {\n            // Try again with a prompt that indicates the last\n            // attempt was an error.\n\n            QString new_prompt = (tr (\"ERROR: \")\n                                  + QString::fromStdString (msg)\n                                  + \"\\n\\ndbstop if\");\n\n            Q_EMIT dbstop_if (new_prompt, line, \"\");\n          }\n      });\n    }\n}\n\nvoid\nfile_editor_tab::set_file_name (const QString& fileName)\n{\n  // update tracked file if we really have a file on disk\n  enable_file_watcher (false, m_file_name);\n  if (! fileName.isEmpty () && QFile::exists (fileName))\n    {\n      enable_file_watcher (true, fileName);\n      m_last_modified =  QFileInfo (fileName).lastModified ().toUTC ();\n    }\n\n  // update lexer and file name variable if file name changes\n  if (m_file_name != fileName)\n    {\n      Q_EMIT rename_editor_file_in_browser_signal (m_file_name, fileName);\n      m_file_name = fileName;\n      update_lexer ();\n    }\n\n  // set the window title to actual filename (not modified)\n  update_window_title (m_edit_area->isModified ());\n\n  // update the file editor with current editing directory\n  Q_EMIT editor_state_changed (m_copy_available, m_is_octave_file,\n                               m_edit_area->isModified ());\n\n  // add the new file to the most-recently-used list\n  Q_EMIT mru_add_file (m_file_name, m_encoding);\n}\n\n// valid_file_name (file): checks whether \"file\" names a file.\n// By default, \"file\" is empty; then m_file_name is checked\nbool\nfile_editor_tab::valid_file_name (const QString& file)\n{\n  if (file.isEmpty ())\n    {\n      if (m_file_name.isEmpty ())\n        return false;\n      else\n        return true;\n    }\n\n  return true;\n}\n\nvoid\nfile_editor_tab::enable_file_watcher (bool do_enable, const QString& fname)\n{\n  QString file_name = fname;\n  if (file_name.isEmpty ())\n    file_name = m_file_name;\n\n  QStringList trackedFiles = m_file_system_watcher.files ();\n  if (do_enable)\n    {\n      if (! trackedFiles.contains (file_name))\n        m_file_system_watcher.addPath (file_name);\n    }\n  else\n    {\n      if (trackedFiles.contains (file_name))\n        m_file_system_watcher.removePath (file_name);\n    }\n}\n\n// We cannot create a breakpoint when the file is modified\n// because the line number the editor is providing might\n// not match what Octave core is interpreting in the\n// file on disk.  This function gives the user the option\n// to save before creating the breakpoint.\nbool\nfile_editor_tab::unchanged_or_saved ()\n{\n  bool retval = true;\n  if (m_edit_area->isModified () || ! valid_file_name ())\n    {\n      int ans = QMessageBox::question (nullptr, tr (\"Octave Editor\"),\n                                       tr (\"Cannot add breakpoint to modified or unnamed file.\\n\"\n                                           \"Save and add breakpoint, or cancel?\"),\n                                       QMessageBox::Save | QMessageBox::Cancel, QMessageBox::Save);\n\n      if (ans == QMessageBox::Save)\n        save_file (m_file_name, false);\n      else\n        retval = false;\n    }\n\n  return retval;\n}\n\n// Toggle a breakpoint at the editor_linenr or, if this was called by\n// a click with CTRL pressed, toggle a bookmark at that point.\nvoid\nfile_editor_tab::handle_margin_clicked (int margin, int editor_linenr,\n                                        Qt::KeyboardModifiers state)\n{\n  if (margin == 1)\n    {\n      unsigned int markers_mask = m_edit_area->markersAtLine (editor_linenr);\n\n      if (state & Qt::ControlModifier)\n        {\n          if (markers_mask & (1 << marker::bookmark))\n            m_edit_area->markerDelete (editor_linenr, marker::bookmark);\n          else\n            m_edit_area->markerAdd (editor_linenr, marker::bookmark);\n        }\n      else\n        {\n          if (markers_mask & ((1 << marker::breakpoint)\n                              | (1 << marker::cond_break)))\n            handle_request_remove_breakpoint (editor_linenr + 1);\n          else\n            {\n              if (unchanged_or_saved ())\n                handle_request_add_breakpoint (editor_linenr + 1, \"\");\n            }\n        }\n    }\n}\n\nvoid\nfile_editor_tab::update_lexer ()\n{\n  // Create a new lexer\n  QsciLexer *lexer = nullptr;\n\n  m_is_octave_file = false;\n\n  // Find the required lexer from file extensions\n  if (m_file_name.endsWith (\".m\")\n      || m_file_name.endsWith (\"octaverc\")\n      || m_file_name.endsWith (\".cc-tst\"))\n    {\n#if defined (HAVE_LEXER_OCTAVE)\n      lexer = new QsciLexerOctave ();\n#elif defined (HAVE_LEXER_MATLAB)\n      lexer = new QsciLexerMatlab ();\n#else\n      lexer = new octave_txt_lexer ();\n#endif\n      m_is_octave_file = true;\n    }\n\n  if (! lexer)\n    {\n      if (m_file_name.endsWith (\".c\")\n          || m_file_name.endsWith (\".cc\")\n          || m_file_name.endsWith (\".cpp\")\n          || m_file_name.endsWith (\".cxx\")\n          || m_file_name.endsWith (\".c++\")\n          || m_file_name.endsWith (\".h\")\n          || m_file_name.endsWith (\".hh\")\n          || m_file_name.endsWith (\".hpp\")\n          || m_file_name.endsWith (\".h++\"))\n        {\n          lexer = new QsciLexerCPP ();\n        }\n      else if (m_file_name.endsWith (\".java\"))\n        {\n          lexer = new QsciLexerJava ();\n        }\n      else if (m_file_name.endsWith (\".pl\"))\n        {\n          lexer = new QsciLexerPerl ();\n        }\n      else if (m_file_name.endsWith (\".bat\"))\n        {\n          lexer = new QsciLexerBatch ();\n        }\n      else if (m_file_name.endsWith (\".diff\"))\n        {\n          lexer = new QsciLexerDiff ();\n        }\n      else if (m_file_name.endsWith (\".sh\"))\n        {\n          lexer = new QsciLexerBash ();\n        }\n      else if (! valid_file_name ())\n        {\n          // new, not yet named file: let us assume it is octave\n#if defined (HAVE_LEXER_OCTAVE)\n          lexer = new QsciLexerOctave ();\n          m_is_octave_file = true;\n#elif defined (HAVE_LEXER_MATLAB)\n          lexer = new QsciLexerMatlab ();\n          m_is_octave_file = true;\n#else\n          lexer = new octave_txt_lexer ();\n#endif\n        }\n      else\n        {\n          // other or no extension\n          lexer = new octave_txt_lexer ();\n        }\n    }\n\n  // Get any existing lexer\n  QsciLexer *old_lexer = m_edit_area->lexer ();\n\n  // If new file, no lexer, or lexer has changed,\n  // delete old one and set the newly created as current lexer\n  if (! old_lexer || ! valid_file_name ()\n      || QString (old_lexer->lexer ()) != QString (lexer->lexer ()))\n    {\n      // Delete and set new lexer\n      if (old_lexer)\n        delete old_lexer;\n      m_edit_area->setLexer (lexer);\n\n      // Build information for auto completion (APIs)\n      m_lexer_apis = new QsciAPIs (lexer);\n\n      connect (this, &file_editor_tab::request_add_octave_apis,\n               this, &file_editor_tab::handle_add_octave_apis);\n\n      // Get the settings for this new lexer\n      update_lexer_settings ();\n    }\n  else\n    {\n      // Otherwise, delete the newly created lexer and\n      // use the old, existing one.\n      delete lexer;\n    }\n}\n\n// Update settings, which are lexer related and have to be updated\n// when\n//    a) the lexer changes,\n//    b) the settings have changed, or\n//    c) a package was loaded/unloaded\nvoid\nfile_editor_tab::update_lexer_settings (bool update_apis_only)\n{\n  QsciLexer *lexer = m_edit_area->lexer ();\n\n  gui_settings settings;\n\n  if (m_lexer_apis)\n    {\n      m_lexer_apis->cancelPreparation ();  // stop preparing if apis exists\n\n      bool update_apis = false;  // flag, whether update of apis files\n\n      // Get path to prepared api info (cache).  Temporarily set the\n      // application name to 'octave' instead of 'GNU Octave' name for\n      // not having blanks in the path.\n      QString tmp_app_name = QCoreApplication::applicationName ();\n      QCoreApplication::setApplicationName (\"octave\");  // Set new name\n\n#if defined (HAVE_QSTANDARDPATHS)\n      QString local_data_path\n        = QStandardPaths::writableLocation (QStandardPaths::CacheLocation);\n#else\n      QString local_data_path\n        = QDesktopServices::storageLocation (QDesktopServices::CacheLocation);\n#endif\n\n      QCoreApplication::setApplicationName (\"octave\");  // Set temp. name\n\n      m_prep_apis_path\n        = local_data_path + \"/\" + QString (OCTAVE_VERSION) + \"/qsci/\";\n\n      // get settings which infos are used for octave\n      bool octave_builtins\n        = settings.bool_value (ed_code_completion_octave_builtins);\n      bool octave_functions\n        = settings.bool_value (ed_code_completion_octave_functions);\n\n      QCoreApplication::setApplicationName (tmp_app_name);  // Restore name\n\n      if (m_is_octave_file)\n        {\n          // Keywords and Builtins do not change, this information can be\n          // stored in prepared form in a file.  Information on function are\n          // changing frequently, then if functions should also be auto-\n          // completed, the date of any existing file is checked.\n\n          // Keywords are always used\n          m_prep_apis_file = m_prep_apis_path + lexer->lexer () + \"_k\";\n\n          // Builtins are only used if the user settings say so\n          if (octave_builtins)\n            m_prep_apis_file += 'b';\n\n          if (octave_functions)\n            m_prep_apis_file += 'f';\n\n          m_prep_apis_file += \".pap\"; // final name of apis file\n\n          // check whether the APIs info needs to be prepared and saved\n          QFileInfo apis_file = QFileInfo (m_prep_apis_file);\n\n          // flag whether apis file needs update\n          update_apis = ! apis_file.exists ();\n\n          if (octave_functions)\n            {\n              // Functions may change frequently.  Update the apis data\n              // if the file is older than a few minutes preventing from\n              // re-preparing data when the user opens several files.\n              QDateTime apis_time = apis_file.lastModified ();\n              if (update_apis_only\n                  || QDateTime::currentDateTime () > apis_time.addSecs (180))\n                update_apis = true;\n            }\n\n        }\n      else\n        {\n          // No octave file, just add extension.\n          m_prep_apis_file = m_prep_apis_path + lexer->lexer () + \".pap\";\n        }\n\n      // Make sure the apis file is usable, otherwise the gui might crash,\n      // e.g., in case of max. number of opened files\n      QFile f (m_prep_apis_file);\n\n      bool apis_usable = f.open (QIODevice::ReadOnly);\n      if (! apis_usable)\n        {\n          QDir ().mkpath (QFileInfo (f).absolutePath ());\n          apis_usable = f.open (QIODevice::WriteOnly);\n        }\n      if (apis_usable)\n        f.close ();\n\n      if (apis_usable\n          && (update_apis || ! m_lexer_apis->loadPrepared (m_prep_apis_file)))\n        {\n          // either we have decided to update the apis file or\n          // no prepared info was loaded, prepare and save if possible\n\n          // create raw apis info\n\n          m_lexer_apis->clear (); // Clear current contents\n\n          if (m_is_octave_file)\n            {\n              // The interpreter_event callback function below emits a\n              // signal.  Because we don't control when that happens,\n              // use a guarded pointer so that the callback can abort\n              // if this object is no longer valid.\n\n              QPointer<file_editor_tab> this_fetab (this);\n\n              Q_EMIT interpreter_event\n              ([this, this_fetab, octave_builtins, octave_functions] (interpreter& interp)\n              {\n                // INTERPRETER THREAD\n\n                // We can skip the entire callback function because\n                // it does not make any changes to the interpreter\n                // state.\n\n                if (this_fetab.isNull ())\n                  return;\n\n                QStringList api_entries;\n\n                octave_value_list tmp = Fiskeyword ();\n                const Cell ctmp = tmp(0).cell_value ();\n                for (octave_idx_type i = 0; i < ctmp.numel (); i++)\n                  {\n                    std::string kw = ctmp(i).string_value ();\n                    api_entries.append (QString::fromStdString (kw));\n                  }\n\n                if (octave_builtins)\n                  {\n                    symbol_table& symtab = interp.get_symbol_table ();\n\n                    string_vector bfl = symtab.built_in_function_names ();\n\n                    for (octave_idx_type i = 0; i < bfl.numel (); i++)\n                      api_entries.append (QString::fromStdString (bfl[i]));\n                  }\n\n                if (octave_functions)\n                  {\n                    load_path& lp = interp.get_load_path ();\n\n                    string_vector ffl = lp.fcn_names ();\n                    string_vector afl = interp.autoloaded_functions ();\n\n                    for (octave_idx_type i = 0; i < ffl.numel (); i++)\n                      api_entries.append (QString::fromStdString (ffl[i]));\n\n                    for (octave_idx_type i = 0; i < afl.numel (); i++)\n                      api_entries.append (QString::fromStdString (afl[i]));\n                  }\n\n                Q_EMIT request_add_octave_apis (api_entries);\n              });\n            }\n          else\n            {\n              for (int i = 1; i <= 3; i++)\n                {\n                  // Get list, split, and add to API.\n\n                  QString keyword = QString (lexer->keywords (i));\n\n                  QStringList keyword_list\n                    = keyword.split (QRegularExpression {R\"(\\s+)\"});\n\n                  for (int j = 0; j < keyword_list.size (); j++)\n                    m_lexer_apis->add (keyword_list.at (j));\n                }\n\n              Q_EMIT api_entries_added ();\n            }\n        }\n    }\n\n  if (update_apis_only)\n    return;   // We are done here\n\n  int mode = settings.int_value (ed_color_mode);\n  settings.read_lexer_settings (lexer, mode);\n\n  m_edit_area->setCaretForegroundColor (lexer->color (0));\n  m_edit_area->setIndentationGuidesForegroundColor (lexer->color (0));\n\n  // set some colors depending on selected background color of the lexer\n  QColor bg = lexer->paper (0);\n  QColor fg = lexer->color (0);\n\n  // margin and current line marker colors\n  QColor bgm, fgm;\n\n  bgm = interpolate_color (bg, fg, 0.5, 0.2);\n  m_edit_area->setEdgeColor (bgm);\n\n  m_edit_area->setMarkerForegroundColor (lexer->color (0));\n  m_edit_area->setMarginsForegroundColor (lexer->color (0));\n\n  bgm = interpolate_color (bg, fg, 0.5, 0.125);\n  fgm = interpolate_color (bg, fg, 0.5, 0.25);\n  m_edit_area->setMarginsBackgroundColor (bgm);\n  m_edit_area->setFoldMarginColors (bgm, fgm);\n\n  QColor current_line_bg\n    = settings.color_value (ed_highlight_current_line_color, mode);\n  if (current_line_bg == settings_color_no_change)\n    bgm = interpolate_color (bg, fg, 0.5, 0.1);  // It is the \"auto\" color\n  else\n    bgm = current_line_bg;  // Specific color given\n\n  m_edit_area->setCaretLineBackgroundColor (bgm);\n\n  // color indicator for highlighting all occurrences:\n  // applications highlight color with more transparency\n  QColor hg = QApplication::palette ().color (QPalette::Highlight);\n  m_edit_area->set_selection_marker_color (hg);\n\n  // fix line number width with respect to the font size of the lexer and\n  // set the line numbers font depending on the lexer's font\n  if (settings.bool_value (ed_show_line_numbers))\n    {\n      // Line numbers width\n      auto_margin_width ();\n\n      // Line numbers font\n      QFont line_numbers_font = lexer->defaultFont ();\n      int font_size = line_numbers_font.pointSize ();\n      font_size = font_size\n                  + settings.int_value (ed_line_numbers_size);\n      if (font_size < 4)\n        font_size = 4;\n      line_numbers_font.setPointSize (font_size);\n\n      m_edit_area->setMarginsFont (line_numbers_font);\n    }\n  else\n    m_edit_area->setMarginWidth (2, 0);\n}\n\n// function for adding entries to the octave lexer's APIs\nvoid\nfile_editor_tab::handle_add_octave_apis (const QStringList& api_entries)\n{\n  for (int idx = 0; idx < api_entries.size (); idx++)\n    m_lexer_apis->add (api_entries.at (idx));\n\n  Q_EMIT api_entries_added ();\n}\n\nvoid\nfile_editor_tab::handle_api_entries_added ()\n{\n  // The following signal-slot (dis)connections must use the old syntax or\n  // they would fail on Windows with warnings like this:\n  // qt.core.qobject.connect: QObject::disconnect: signal not found in QsciAPIs\n  // qt.core.qobject.connect: QObject::connect: signal not found in QsciAPIs\n\n  // disconnect slot for saving prepared info if already connected\n  disconnect (m_lexer_apis, SIGNAL (apiPreparationFinished ()),\n              nullptr, nullptr);\n\n  // check whether path for prepared info exists or can be created\n  if (QDir (\"/\").mkpath (m_prep_apis_path))\n    {\n      // path exists, apis info can be saved there\n      connect (m_lexer_apis, SIGNAL (apiPreparationFinished ()),\n               this, SLOT (save_apis_info ()));\n    }\n\n  m_lexer_apis->prepare ();  // prepare apis info\n}\n\nvoid\nfile_editor_tab::save_apis_info ()\n{\n  m_lexer_apis->savePrepared (m_prep_apis_file);\n}\n\n// slot for fetab_set_focus: sets the focus to the current edit area\nvoid\nfile_editor_tab::set_focus (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n  m_edit_area->setFocus ();\n  Q_EMIT edit_area_changed (m_edit_area);  // update the edit area in find dlg\n}\n\nvoid\nfile_editor_tab::context_help (const QWidget *ID, bool doc)\n{\n  if (ID != this)\n    return;\n\n  m_edit_area->context_help_doc (doc);\n}\n\nvoid\nfile_editor_tab::context_edit (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  m_edit_area->context_edit ();\n}\n\nvoid\nfile_editor_tab::save_file (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  save_file (m_file_name);\n}\n\nvoid\nfile_editor_tab::save_file (const QWidget *ID, const QString& fileName,\n                            bool remove_on_success)\n{\n  if (ID != this)\n    return;\n\n  save_file (fileName, remove_on_success);\n}\n\nvoid\nfile_editor_tab::save_file_as (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  save_file_as ();\n}\n\nvoid\nfile_editor_tab::print_file (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  QsciPrinter *printer = new QsciPrinter (QPrinter::HighResolution);\n\n  QPrintDialog printDlg (printer, this);\n\n  if (printDlg.exec () == QDialog::Accepted)\n    printer->printRange (m_edit_area);\n\n  delete printer;\n}\n\nvoid\nfile_editor_tab::run_file (const QWidget *ID, int opts)\n{\n  if (ID != this)\n    return;\n\n  if (m_edit_area->isModified () || ! valid_file_name ())\n    {\n      save_file (m_file_name);  // save file dialog\n\n      // Running a file is disabled for non-octave files.  But when saving\n      // a new file, an octave file is assumed but might actually saved\n      // as another file or with an invalid file name.\n      if (! (m_is_octave_file && valid_file_name ()))\n        return;\n    }\n\n  int actual_opts = opts;\n\n  if (opts == ED_STEP_INTO)\n    {\n      // Get current first breakpoint and set breakpoint waiting for\n      // the returned line number.  Store whether to remove this breakpoint\n      // afterwards.\n      int first_bp_line\n        = m_edit_area->markerFindNext (0, (1 << marker::breakpoint)) + 1;\n\n      // Set flag for storing the line number of the breakpoint\n      m_breakpoint_info.remove_next = true;\n      m_breakpoint_info.do_not_remove_line = first_bp_line;\n\n      // Add breakpoint, storing its line number\n      handle_request_add_breakpoint (1, QString ());\n      actual_opts = ED_RUN_FILE;\n    }\n\n  QFileInfo info (m_file_name);\n  Q_EMIT run_file_signal (info, actual_opts);\n}\n\nvoid\nfile_editor_tab::context_run (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  m_edit_area->context_run ();\n}\n\nvoid\nfile_editor_tab::toggle_bookmark (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  int line, cur;\n  m_edit_area->getCursorPosition (&line, &cur);\n\n  if (m_edit_area->markersAtLine (line) & (1 << marker::bookmark))\n    m_edit_area->markerDelete (line, marker::bookmark);\n  else\n    m_edit_area->markerAdd (line, marker::bookmark);\n}\n\n// Move the text cursor to the closest bookmark\n// after the current line.\nvoid\nfile_editor_tab::next_bookmark (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  int line, cur;\n  m_edit_area->getCursorPosition (&line, &cur);\n\n  line++; // Find bookmark strictly after the current line.\n\n  int nextline = m_edit_area->markerFindNext (line, (1 << marker::bookmark));\n\n  // Wrap.\n  if (nextline == -1)\n    nextline = m_edit_area->markerFindNext (1, (1 << marker::bookmark));\n\n  m_edit_area->setCursorPosition (nextline, 0);\n}\n\n// Move the text cursor to the closest bookmark\n// before the current line.\nvoid\nfile_editor_tab::previous_bookmark (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  int line, cur;\n  m_edit_area->getCursorPosition (&line, &cur);\n\n  line--; // Find bookmark strictly before the current line.\n\n  int prevline = m_edit_area->markerFindPrevious (line, (1 << marker::bookmark));\n\n  // Wrap.  Should use the last line of the file, not 1<<15\n  if (prevline == -1)\n    prevline = m_edit_area->markerFindPrevious (m_edit_area->lines (),\n               (1 << marker::bookmark));\n\n  m_edit_area->setCursorPosition (prevline, 0);\n}\n\nQString\nfile_editor_tab::get_all_bookmarks ()\n{\n  QString bmlist;\n  int line = 0;\n\n  while (line > -1)\n    {\n      line = m_edit_area->markerFindNext (line, (1 << marker::bookmark));\n      if (line > -1)\n        {\n          if (! bmlist.isEmpty ())\n            bmlist += \",\";\n          bmlist += QString::number (line);\n          line++;   // search from next line, otherwise same line found again\n        }\n    }\n\n  return bmlist;\n}\n\nvoid\nfile_editor_tab::remove_bookmark (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  m_edit_area->markerDeleteAll (marker::bookmark);\n}\n\nvoid\nfile_editor_tab::handle_request_add_breakpoint (int line,\n    const QString& condition)\n{\n  if (! m_is_octave_file)\n    return;\n\n  add_breakpoint_event (line, condition);\n}\n\nvoid\nfile_editor_tab::handle_request_remove_breakpoint (int line)\n{\n  Q_EMIT interpreter_event\n  ([this, line] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n\n    tree_evaluator& tw = interp.get_evaluator ();\n    bp_table& bptab = tw.get_bp_table ();\n\n    bptab.remove_breakpoint_from_file (m_file_name.toStdString (), line);\n  });\n}\n\nvoid\nfile_editor_tab::toggle_breakpoint (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  int editor_linenr, cur;\n  m_edit_area->getCursorPosition (&editor_linenr, &cur);\n\n  if (m_edit_area->markersAtLine (editor_linenr) & (1 << marker::breakpoint))\n    request_remove_breakpoint_via_editor_linenr (editor_linenr);\n  else\n    {\n      if (unchanged_or_saved ())\n        handle_request_add_breakpoint (editor_linenr + 1, \"\");\n    }\n}\n\n// Move the text cursor to the closest breakpoint (conditional or unconditional)\n// after the current line.\nvoid\nfile_editor_tab::next_breakpoint (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  int line, cur;\n  m_edit_area->getCursorPosition (&line, &cur);\n\n  line++; // Find breakpoint strictly after the current line.\n\n  int nextline = m_edit_area->markerFindNext (line, (1 << marker::breakpoint));\n  int nextcond = m_edit_area->markerFindNext (line, (1 << marker::cond_break));\n\n  // Check if the next conditional breakpoint is before next unconditional one.\n  if (nextcond != -1 && (nextcond < nextline || nextline == -1))\n    nextline = nextcond;\n\n  m_edit_area->setCursorPosition (nextline, 0);\n}\n\n// Move the text cursor to the closest breakpoint (conditional or unconditional)\n// before the current line.\nvoid\nfile_editor_tab::previous_breakpoint (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  int line, cur, prevline, prevcond;\n  m_edit_area->getCursorPosition (&line, &cur);\n\n  line--; // Find breakpoint strictly before the current line.\n\n  prevline = m_edit_area->markerFindPrevious (line, (1 << marker::breakpoint));\n  prevcond = m_edit_area->markerFindPrevious (line, (1 << marker::cond_break));\n\n  // Check if the prev conditional breakpoint is closer than the unconditional.\n  if (prevcond != -1 && prevcond > prevline)\n    prevline = prevcond;\n\n  m_edit_area->setCursorPosition (prevline, 0);\n}\n\nvoid\nfile_editor_tab::remove_all_breakpoints (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  Q_EMIT interpreter_event\n  ([this] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n\n    tree_evaluator& tw = interp.get_evaluator ();\n    bp_table& bptab = tw.get_bp_table ();\n\n    bptab.remove_all_breakpoints_from_file (m_file_name.toStdString (),\n                                            true);\n  });\n}\n\nvoid\nfile_editor_tab::scintilla_command (const QWidget *ID,\n                                    unsigned int sci_msg)\n{\n  if (ID != this)\n    return;\n\n  m_edit_area->SendScintilla (sci_msg);\n}\n\nvoid\nfile_editor_tab::comment_selected_text (const QWidget *ID,\n                                        bool input_str)\n{\n  if (ID != this)\n    return;\n\n  do_comment_selected_text (true, input_str);\n}\n\nvoid\nfile_editor_tab::uncomment_selected_text (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  do_comment_selected_text (false);\n}\n\nvoid\nfile_editor_tab::indent_selected_text (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  do_indent_selected_text (true);\n}\n\nvoid\nfile_editor_tab::unindent_selected_text (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  do_indent_selected_text (false);\n}\n\nvoid\nfile_editor_tab::smart_indent_line_or_selected_text (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  do_smart_indent_line_or_selected_text ();\n}\n\nvoid\nfile_editor_tab::convert_eol (const QWidget *ID,\n                              QsciScintilla::EolMode eol_mode)\n{\n  if (ID != this)\n    return;\n\n  m_edit_area->convertEols (eol_mode);\n  m_edit_area->setEolMode (eol_mode);\n  update_eol_indicator ();\n}\n\nvoid\nfile_editor_tab::zoom_in (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  m_edit_area->zoomIn (1);\n  auto_margin_width ();\n}\n\nvoid\nfile_editor_tab::zoom_out (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  m_edit_area->zoomOut (1);\n  auto_margin_width ();\n}\n\nvoid\nfile_editor_tab::zoom_normal (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  m_edit_area->zoomTo (0);\n  auto_margin_width ();\n}\n\nvoid\nfile_editor_tab::add_breakpoint_event (int line, const QString& cond)\n{\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<file_editor_tab> this_fetab (this);\n\n  Q_EMIT interpreter_event\n  ([this, this_fetab, line, cond] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n\n    // If THIS_FETAB is no longer valid, we still want to set the\n    // breakpoint in the interpreter but we can't emit the signal\n    // associated with THIS_FETAB.\n\n    // FIXME: note duplication with the code in\n    // handle_context_menu_break_condition.\n\n    tree_evaluator& tw = interp.get_evaluator ();\n    bp_table& bptab = tw.get_bp_table ();\n\n    int lineno = bptab.add_breakpoint_in_file (m_file_name.toStdString (),\n                 line, cond.toStdString ());\n\n    if (this_fetab.isNull ())\n      return;\n\n    if (lineno)\n      Q_EMIT maybe_remove_next (lineno);\n  });\n}\n\nvoid\nfile_editor_tab::handle_remove_next (int remove_line)\n{\n  // Store some info breakpoint\n  if (m_breakpoint_info.remove_next)\n    {\n      m_breakpoint_info.remove_line = remove_line;\n      m_breakpoint_info.remove_next = false;\n    }\n}\n\nvoid\nfile_editor_tab::goto_line (const QWidget *ID, int line)\n{\n  if (ID != this)\n    return;\n\n  if (m_bp_restore_count > 0)\n    {\n      // This goto-line request is invoked by restoring a breakpoint during\n      // saving the file, thus, do not go to the related line\n      m_bp_restore_count--;\n      return;\n    }\n\n  if (line <= 0)  // ask for desired line\n    {\n      bool ok = false;\n      int index;\n      m_edit_area->getCursorPosition (&line, &index);\n      line = QInputDialog::getInt (m_edit_area, tr (\"Goto line\"),\n                                   tr (\"Line number\"), line+1, 1,\n                                   m_edit_area->lines (), 1, &ok);\n      if (ok)\n        m_edit_area->setCursorPosition (line-1, 0);\n    }\n  else  // go to given line without dialog\n    m_edit_area->setCursorPosition (line-1, 0);\n\n  center_current_line (false);  // only center line if at top or bottom\n}\n\nvoid\nfile_editor_tab::move_match_brace (const QWidget *ID, bool select)\n{\n  if (ID != this)\n    return;\n\n  if (select)\n    m_edit_area->selectToMatchingBrace ();\n  else\n    m_edit_area->moveToMatchingBrace ();\n}\n\nvoid\nfile_editor_tab::show_auto_completion (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  m_autoc_active = true;\n\n  QsciScintilla::AutoCompletionSource s = m_edit_area->autoCompletionSource ();\n  switch (s)\n    {\n    case QsciScintilla::AcsAll:\n      m_edit_area->autoCompleteFromAll ();\n      break;\n\n    case QsciScintilla::AcsAPIs:\n      m_edit_area->autoCompleteFromAPIs ();\n      break;\n\n    case QsciScintilla::AcsDocument:\n      m_edit_area->autoCompleteFromDocument ();\n      break;\n\n    case QsciScintilla::AcsNone:\n      break;\n    }\n}\n\nvoid\nfile_editor_tab::do_indent_selected_text (bool indent)\n{\n  // FIXME:\n  m_edit_area->beginUndoAction ();\n\n  if (m_edit_area->hasSelectedText ())\n    {\n      int lineFrom, lineTo, colFrom, colTo;\n      m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo);\n\n      if (colTo == 0)  // the beginning of last line is not selected\n        lineTo--;        // stop at line above\n\n      for (int i = lineFrom; i <= lineTo; i++)\n        {\n          if (indent)\n            m_edit_area->indent (i);\n          else\n            m_edit_area->unindent (i);\n        }\n      //set selection on (un)indented section\n      m_edit_area->setSelection (lineFrom, 0, lineTo,\n                                 m_edit_area->text (lineTo).length ()-1);\n    }\n  else\n    {\n      int cpline, col;\n      m_edit_area->getCursorPosition (&cpline, &col);\n      if (indent)\n        m_edit_area->indent (cpline);\n      else\n        m_edit_area->unindent (cpline);\n    }\n\n  m_edit_area->endUndoAction ();\n}\n\nvoid\nfile_editor_tab::do_smart_indent_line_or_selected_text ()\n{\n  m_edit_area->beginUndoAction ();\n\n  int lineFrom, lineTo;\n\n  if (m_edit_area->hasSelectedText ())\n    {\n      int colFrom, colTo;\n      m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo);\n\n      if (colTo == 0)  // the beginning of last line is not selected\n        lineTo--;        // stop at line above\n    }\n  else\n    {\n      int col;\n      m_edit_area->getCursorPosition (&lineFrom, &col);\n\n      lineTo = lineFrom;\n    }\n\n  m_edit_area->smart_indent_line_or_selected_text (lineFrom, lineTo);\n\n  m_edit_area->endUndoAction ();\n}\n\nvoid\nfile_editor_tab::do_comment_selected_text (bool comment, bool input_str)\n{\n  QRegularExpression rxc;\n  QString ws = \"^(?:[ \\\\t]*)\";\n  QStringList comment_str = m_edit_area->comment_string (comment);\n  QString used_comment_str = comment_str.at (0);\n\n  if (comment)\n    {\n      if (input_str)\n        {\n          bool ok;\n          gui_settings settings;\n\n          used_comment_str\n            = QInputDialog::getText (this, tr (\"Comment selected text\"),\n                                     tr (\"Comment string to use:\\n\"),\n                                     QLineEdit::Normal,\n                                     settings.value (ed_last_comment_str, comment_str.at (0)).toString (),\n                                     &ok);\n\n          if ((! ok) || used_comment_str.isEmpty ())\n            return;  // No input, do nothing\n          else\n            settings.setValue (ed_last_comment_str, used_comment_str);  // Store last\n        }\n    }\n  else\n    {\n      // Uncommenting (several strings possible)\n\n      // Sort strings according their length\n      QStringList comment_str_sorted (comment_str.at (0));\n      bool inserted;\n\n      for (int i = 1; i < comment_str.length (); i++)\n        {\n          inserted = false;\n          for (int j = 0; j < comment_str_sorted.length (); j++)\n            {\n              if (comment_str.at (i).length () > comment_str_sorted.at (j).length ())\n                {\n                  comment_str_sorted.insert (j, comment_str.at (i));\n                  inserted = true;\n                  break;\n                }\n            }\n          if (! inserted)\n            comment_str_sorted << comment_str.at (i);\n        }\n\n      // Create regular expression\n      QString regexp;\n      for (int i = 0; i < comment_str_sorted.length (); i++)\n        {\n          if (i > 0)\n            regexp = regexp + QString (\"|\");\n          regexp = regexp + comment_str_sorted.at (i);\n        }\n      rxc = QRegularExpression {ws + \"(\" + regexp + \")\"};\n    }\n\n  // Do the commenting/uncommenting\n  int len = 0, lenc = 0;\n  m_edit_area->beginUndoAction ();\n\n  if (m_edit_area->hasSelectedText ())\n    {\n      int lineFrom, lineTo, colFrom, colTo;\n      int change_col_from = 1;\n      int change_col_to = 1;\n      bool removed = false;\n\n      m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo);\n\n      if (colTo == 0)  // the beginning of last line is not selected\n        lineTo--;        // stop at line above\n\n      for (int i = lineFrom; i <= lineTo; i++)\n        {\n          if (comment)\n            {\n              m_edit_area->insertAt (used_comment_str, i, 0);\n            }\n          else\n            {\n              QString line (m_edit_area->text (i));\n              QRegularExpressionMatch match = rxc.match (line);\n\n              if (match.hasMatch ())\n                {\n                  len = match.capturedLength ();   // complete length\n                  QString matched_text = match.captured (0);\n                  lenc = matched_text.remove (QRegularExpression {ws}).length ();  // only comment string\n                  m_edit_area->setSelection (i, len-lenc, i, len);\n                  m_edit_area->removeSelectedText ();\n                }\n\n              // handle case, where the selection remains unchanged\n              if (i == lineFrom && (colFrom < len-lenc || ! removed))\n                change_col_from = 0;  // do not change start of selection\n              if (i == lineTo && (colTo < len-lenc || ! removed))\n                change_col_to = 0;    // do not change end of selection\n            }\n        }\n\n      // update the selection area\n      if (comment)\n        {\n          colFrom = colFrom + lenc;   // shift start position by comment length\n          if (colTo > 0)\n            colTo = colTo + lenc;     // shift end position by comment length\n          else\n            lineTo++;                 // colTo == 0 , fully select previous line\n        }\n      else\n        {\n          if (colTo == 0)\n            lineTo++;                 // colTo == 0 , fully select previous line\n          colFrom = colFrom - change_col_from*lenc;\n          colTo = colTo - change_col_to*lenc;\n        }\n\n      // set updated selection area\n      m_edit_area->setSelection (lineFrom, colFrom, lineTo, colTo);\n    }\n  else\n    {\n      int cpline, col;\n      m_edit_area->getCursorPosition (&cpline, &col);\n      if (comment)\n        m_edit_area->insertAt (used_comment_str, cpline, 0);\n      else\n        {\n          QString line (m_edit_area->text (cpline));\n          QRegularExpressionMatch match = rxc.match (line);\n          if (match.hasMatch ())\n            {\n              len = match.capturedLength ();  // complete length\n              QString matched_text = match.captured (0);\n              lenc = matched_text.remove (QRegularExpression {ws}).length ();  // only comment string\n              m_edit_area->setSelection (cpline, len-lenc, cpline, len);\n              m_edit_area->removeSelectedText ();\n            }\n        }\n    }\n  m_edit_area->endUndoAction ();\n}\n\nvoid\nfile_editor_tab::update_window_title (bool modified)\n{\n  QString title (\"\");\n  QString tooltip (\"\");\n\n  if (! valid_file_name ())\n    title = tr (\"<unnamed>\");\n  else\n    {\n      QFileInfo file (m_file_name);\n      title = file.fileName ();\n      tooltip = m_file_name;\n    }\n\n  Q_EMIT file_name_changed (title, tooltip, modified);\n}\n\nvoid\nfile_editor_tab::handle_copy_available (bool enableCopy)\n{\n  m_copy_available = enableCopy;\n  Q_EMIT editor_state_changed (m_copy_available, m_is_octave_file,\n                               m_edit_area->isModified ());\n}\n\n// show_dialog: shows a modal or non modal dialog depending on input arg\nvoid\nfile_editor_tab::show_dialog (QDialog *dlg, bool modal)\n{\n  dlg->setAttribute (Qt::WA_DeleteOnClose);\n  if (modal)\n    dlg->exec ();\n  else\n    {\n      dlg->setWindowModality (Qt::NonModal);\n      dlg->show ();\n      dlg->raise ();\n    }\n}\n\nint\nfile_editor_tab::check_file_modified (bool remove)\n{\n  int decision = QMessageBox::Yes;\n  if (m_edit_area->isModified ())\n    {\n      // File is modified but not saved, ask user what to do.  The file\n      // editor tab can't be made parent because it may be deleted depending\n      // upon the response.  Instead, change the m_edit_area to read only.\n      QMessageBox::StandardButtons buttons = QMessageBox::Save |\n                                             QMessageBox::Discard |\n                                             QMessageBox::Cancel;\n\n      // For now, just a warning message about closing a tab that has been\n      // modified seems sufficient.  Exit-condition-specific messages could\n      // be achieved by making 'available_actions' a function input string.\n      QString available_actions =\n        tr (\"Do you want to cancel closing, save, or discard the changes?\");\n\n      QString file;\n      if (valid_file_name ())\n        file = m_file_name;\n      else\n        file = tr (\"<unnamed>\");\n\n      QMessageBox *msgBox\n        = new QMessageBox (QMessageBox::Warning, tr (\"Octave Editor\"),\n                           tr (\"The file\\n\\n\"\n                               \"  %1\\n\\n\"\n                               \"is about to be closed but has been modified.  \"\n                               \"%2\").\n                           arg (file). arg (available_actions),\n                           buttons, qobject_cast<QWidget *> (parent ()));\n\n      msgBox->setDefaultButton (QMessageBox::Save);\n      m_edit_area->setReadOnly (true);\n\n      decision = msgBox->exec (); // show_dialog (msgBox, true);\n\n      if (decision == QMessageBox::Cancel)\n        m_edit_area->setReadOnly (false);\n      else if (decision == QMessageBox::Save)\n        save_file (m_file_name, remove, false);\n      else\n        Q_EMIT tab_ready_to_close ();\n    }\n  else\n    {\n      Q_EMIT tab_ready_to_close ();\n    }\n\n  return decision;\n}\n\nvoid\nfile_editor_tab::set_modified (bool modified)\n{\n  m_edit_area->setModified (modified);\n}\n\nvoid\nfile_editor_tab::recover_from_exit ()\n{\n  // reset the possibly still existing read only state\n  m_edit_area->setReadOnly (false);\n\n  // if we are in this slot and the list of breakpoints is not empty,\n  // then this tab was saved during an exit of the applications (not\n  // restoring the breakpoints and not emptying the list) and the user\n  // canceled this closing late on.\n  check_restore_breakpoints ();\n}\n\nvoid\nfile_editor_tab::check_restore_breakpoints ()\n{\n  if (! m_bp_lines.isEmpty ())\n    {\n      // At least one breakpoint is present.\n      // Get rid of breakpoints at old (now possibly invalid) linenumbers\n      remove_all_breakpoints (this);\n\n      // and set breakpoints at the new linenumbers\n      m_bp_restore_count = m_bp_lines.length ();\n      for (int i = 0; i < m_bp_lines.length (); i++)\n        handle_request_add_breakpoint (m_bp_lines.value (i) + 1,\n                                       m_bp_conditions.value (i));\n\n      // Keep the list of breakpoints empty, except after explicit requests.\n      m_bp_lines.clear ();\n      m_bp_conditions.clear ();\n    }\n}\n\nQString\nfile_editor_tab::load_file (const QString& fileName)\n{\n  // get the absolute path\n  QFileInfo file_info = QFileInfo (fileName);\n  QString file_to_load;\n  if (file_info.exists ())\n    file_to_load = file_info.canonicalFilePath ();\n  else\n    file_to_load = fileName;\n  QFile file (file_to_load);\n  if (! file.open (QIODevice::ReadOnly))\n    return file.errorString ();\n\n  int col = 0, line = 0;\n  if (fileName == m_file_name)\n    {\n      // We have to reload the current file, thus get current cursor position\n      line = m_line;\n      col = m_col;\n    }\n\n  QApplication::setOverrideCursor (Qt::WaitCursor);\n  unwind_action reset_cursor ([] ()\n  { QApplication::restoreOverrideCursor (); });\n\n  // read the file binary, decoding later\n  QByteArray text_data = file.readAll ();\n\n  // remove newline at end of file if we add one again when saving\n\n  gui_settings settings;\n\n  if (settings.bool_value (ed_force_newline))\n    {\n      const QByteArray eol_lf = QByteArray (1, 0x0a);\n      const QByteArray eol_cr = QByteArray (1, 0x0d);\n\n      if (text_data.endsWith (eol_lf))\n        text_data.chop (1);   // remove LF\n\n      if (text_data.endsWith (eol_cr)) // remove CR (altogether CRLF, too)\n        text_data.chop (1);\n    }\n\n  // expected file encoding\n  std::string encoding = m_encoding.toStdString ();\n  if (encoding.compare (0, 6, \"SYSTEM\") == 0)\n    encoding = octave_locale_charset_wrapper ();\n\n  std::size_t srclen = text_data.length ();\n\n  if (srclen == 0)\n    m_edit_area->setText (QString ());\n  else\n    {\n      // check if the selected encoding can be used to decode the file\n\n      const char *src = text_data.constData ();\n\n      std::size_t length;\n      uint16_t *u16_str;\n\n      // try to convert encoding in strict mode\n      u16_str = octave_u16_conv_from_encoding_strict (encoding.c_str (),\n                src, srclen, &length);\n\n      // check for invalid characters in input file\n      if (! u16_str)\n        {\n          // Set read only\n          m_edit_area->setReadOnly (true);\n\n          // convert encoding allowing replacements\n          u16_str = octave_u16_conv_from_encoding (encoding.c_str (),\n                    src, srclen, &length);\n\n          if (! u16_str)\n            {\n              // FIXME: Can this ever happen?\n\n              // non-modal error message box\n              QMessageBox *msgBox\n                = new QMessageBox (QMessageBox::Critical,\n                                   tr (\"Octave Editor\"),\n                                   tr (\"Unable to read file '%1'\\n\"\n                                       \"with selected encoding '%2': %3\")\n                                   .arg (file_to_load).arg (m_encoding)\n                                   .arg (std::strerror (errno)),\n                                   QMessageBox::Ok, nullptr);\n              show_dialog (msgBox, false);\n              return QString ();\n            }\n\n          // Message box for user decision\n          QString msg = tr (\"There were problems reading the file\\n\"\n                            \"%1\\n\"\n                            \"with the selected encoding %2.\\n\\n\"\n                            \"Modifying and saving the file might \"\n                            \"cause data loss!\")\n                        .arg (file_to_load).arg (m_encoding);\n          QMessageBox *msg_box = new QMessageBox ();\n          msg_box->setIcon (QMessageBox::Warning);\n          msg_box->setText (msg);\n          msg_box->setWindowTitle (tr (\"Octave Editor\"));\n          msg_box->addButton (tr (\"&Edit anyway\"), QMessageBox::YesRole);\n          msg_box->addButton (tr (\"Chan&ge encoding\"),\n                              QMessageBox::AcceptRole);\n          msg_box->addButton (tr (\"&Close\"), QMessageBox::RejectRole);\n\n          connect (msg_box, &QMessageBox::buttonClicked,\n                   this, &file_editor_tab::handle_decode_warning_answer);\n\n          msg_box->setWindowModality (Qt::WindowModal);\n          msg_box->setAttribute (Qt::WA_DeleteOnClose);\n          msg_box->show ();\n        }\n\n      unwind_action free_u16_str ([u16_str] () { ::free (u16_str); });\n\n      QString text\n        = QString::fromUtf16 (reinterpret_cast<char16_t *> (u16_str), length);\n\n      m_edit_area->setText (text);\n    }\n\n  m_edit_area->setEolMode (detect_eol_mode ());\n\n  m_copy_available = false;  // no selection yet available\n  m_edit_area->setModified (false);  // loaded file is not modified yet\n  set_file_name (file_to_load);\n\n  update_eol_indicator ();\n\n  m_edit_area->setCursorPosition (line, col);\n\n  return QString ();\n}\n\nvoid\nfile_editor_tab::handle_decode_warning_answer (QAbstractButton *btn)\n{\n  QString txt = btn->text ();\n\n  if (txt == tr (\"&Close\"))\n    {\n      // Just close the file\n      close ();\n      return;\n    }\n\n  if (txt == tr (\"Chan&ge encoding\"))\n    {\n      // Dialog for reloading the file with another encoding\n      QDialog dlg;\n      dlg.setWindowTitle (tr (\"Select new default encoding\"));\n\n      QLabel *text\n        = new QLabel (tr (\"Please select a new encoding\\n\"\n                          \"for reloading the current file.\\n\\n\"\n                          \"This does not change the default encoding.\\n\"));\n\n      QComboBox *enc_combo = new QComboBox ();\n      gui_settings settings;\n      settings.combo_encoding (enc_combo);\n      m_new_encoding = enc_combo->currentText ();\n      connect (enc_combo, &QComboBox::currentTextChanged,\n               this, &file_editor_tab::handle_current_enc_changed);\n\n      QDialogButtonBox *buttons\n        = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel,\n                                Qt::Horizontal);\n      connect (buttons, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);\n      connect (buttons, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);\n\n      QGridLayout *main_layout = new QGridLayout;\n      main_layout->setSizeConstraint (QLayout::SetFixedSize);\n      main_layout->addWidget (text, 0, 0);\n      main_layout->addWidget (enc_combo, 1, 0);\n      main_layout->addWidget (buttons, 2, 0);\n      dlg.setLayout (main_layout);\n\n      int answer = dlg.exec ();\n\n      if (answer == QDialog::Accepted)\n        {\n          // Reload the file with new encoding but using the same tab\n          QString reload_file_name = m_file_name;  // store file name\n          m_file_name = \"\";  // force reuse of this tab when opening a new file\n          Q_EMIT request_open_file (reload_file_name, m_new_encoding);\n        }\n    }\n\n  // Continue editing, set writable again\n  m_edit_area->setReadOnly (false);\n}\n\nvoid\nfile_editor_tab::handle_current_enc_changed (const QString& enc)\n{\n  m_new_encoding = enc;\n}\n\nQsciScintilla::EolMode\nfile_editor_tab::detect_eol_mode ()\n{\n  QByteArray text = m_edit_area->text ().toLatin1 ();\n\n  QByteArray eol_lf = QByteArray (1, 0x0a);\n  QByteArray eol_cr = QByteArray (1, 0x0d);\n  QByteArray eol_crlf = eol_cr;\n  eol_crlf.append (eol_lf);\n\n  int count_crlf = text.count (eol_crlf);\n  int count_lf = text.count (eol_lf) - count_crlf;  // isolated lf\n  int count_cr = text.count (eol_cr) - count_crlf;  // isolated cr\n\n  gui_settings settings;\n\n  QsciScintilla::EolMode eol_mode\n    = static_cast<QsciScintilla::EolMode> (settings.int_value (ed_default_eol_mode));\n\n  int count_max = 0;\n\n  if (count_crlf > count_max)\n    {\n      eol_mode = QsciScintilla::EolWindows;\n      count_max = count_crlf;\n    }\n  if (count_lf > count_max)\n    {\n      eol_mode = QsciScintilla::EolUnix;\n      count_max = count_lf;\n    }\n  if (count_cr > count_max)\n    {\n      eol_mode = QsciScintilla::EolMac;\n    }\n\n  return eol_mode;\n}\n\nvoid\nfile_editor_tab::update_eol_indicator ()\n{\n  switch (m_edit_area->eolMode ())\n    {\n    case QsciScintilla::EolWindows:\n      m_eol_indicator->setText (\"CRLF\");\n      break;\n    case QsciScintilla::EolMac:\n      m_eol_indicator->setText (\"CR\");\n      break;\n    case QsciScintilla::EolUnix:\n      m_eol_indicator->setText (\"LF\");\n      break;\n    }\n}\n\nvoid\nfile_editor_tab::update_breakpoints ()\n{\n  if (m_file_name.isEmpty ())\n    return;\n\n  // Create and queue the command object.\n\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<file_editor_tab> this_fetab (this);\n\n  Q_EMIT interpreter_event\n  ([this, this_fetab] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n\n    // We can skip the entire callback function because it does not\n    // make any changes to the interpreter state.\n\n    if (this_fetab.isNull ())\n      return;\n\n    octave_value_list argout = Fdbstatus (interp, ovl (), 1);\n\n    connect (this, &file_editor_tab::update_breakpoints_signal,\n             this, &file_editor_tab::update_breakpoints_handler,\n             Qt::QueuedConnection);\n\n    Q_EMIT update_breakpoints_signal (argout);\n  });\n}\n\nvoid\nfile_editor_tab::update_breakpoints_handler (const octave_value_list& argout)\n{\n  octave_map dbg = argout(0).map_value ();\n  octave_idx_type n_dbg = dbg.numel ();\n\n  Cell file = dbg.contents (\"file\");\n  Cell line = dbg.contents (\"line\");\n  Cell cond = dbg.contents (\"cond\");\n\n  for (octave_idx_type i = 0; i < n_dbg; i++)\n    {\n      if (file (i).string_value () == m_file_name.toStdString ())\n        do_breakpoint_marker (true, this, line (i).int_value (),\n                              QString::fromStdString (cond (i).string_value ()));\n    }\n}\n\nvoid\nfile_editor_tab::new_file (const QString& commands)\n{\n  update_window_title (false); // window title (no modification)\n\n  gui_settings settings;\n\n  // set the eol mode from the settings or depending on the OS if the entry is\n  // missing in the settings\n  m_edit_area->setEolMode (static_cast<QsciScintilla::EolMode> (settings.int_value (ed_default_eol_mode)));\n\n  update_eol_indicator ();\n\n  update_lexer ();\n\n  m_edit_area->setText (commands);\n  m_edit_area->setModified (!commands.isEmpty ());\n}\n\nvoid\nfile_editor_tab::confirm_dbquit_and_save (const QString& file_to_save,\n    const QString& base_name,\n    bool remove_on_success,\n    bool restore_breakpoints)\n{\n  int ans = QMessageBox::question (nullptr, tr (\"Debug or Save\"),\n                                   tr (\"This file is currently being executed.\\n\"\n                                       \"Quit debugging and save?\"),\n                                   QMessageBox::Save | QMessageBox::Cancel);\n\n  if (ans == QMessageBox::Save)\n    {\n      // The interpreter_event callback function below emits a signal.\n      // Because we don't control when that happens, use a guarded\n      // pointer so that the callback can abort if this object is no\n      // longer valid.\n\n      QPointer<file_editor_tab> this_fetab (this);\n\n      Q_EMIT interpreter_event\n      ([this, this_fetab, base_name, file_to_save, remove_on_success, restore_breakpoints] (interpreter& interp)\n      {\n        // INTERPRETER THREAD\n\n        // If THIS_FETAB is no longer valid, we still want to\n        // perform the actions in the interpreter but we can't emit\n        // the signal associated with THIS_FETAB.\n\n        tree_evaluator& tw = interp.get_evaluator ();\n\n        tw.dbquit (true);\n\n        command_editor::interrupt (true);\n\n        std::string std_base_name = base_name.toStdString ();\n\n        symbol_table& symtab = interp.get_symbol_table ();\n\n        symtab.clear_user_function (std_base_name);\n\n        if (this_fetab.isNull ())\n          return;\n\n        Q_EMIT do_save_file_signal (file_to_save, remove_on_success,\n                                    restore_breakpoints);\n      });\n    }\n}\n\nvoid\nfile_editor_tab::save_file (const QString& saveFileName,\n                            bool remove_on_success,\n                            bool restore_breakpoints)\n{\n  // If it is a new file with no name, signal that saveFileAs\n  // should be performed.\n  if (! valid_file_name (saveFileName))\n    {\n      save_file_as (remove_on_success);\n      return;\n    }\n\n  m_encoding = m_new_encoding;    // consider a possible new encoding\n\n  // check if the selected encoding is suitable for the content\n  if (! check_valid_codec ())\n    return;   // No valid codec\n\n  // Get a list of breakpoint line numbers, before exiting debug mode\n  // and clearing function in interpreter_event action below.\n\n  Q_EMIT report_marker_linenr (m_bp_lines, m_bp_conditions);\n\n  // get the absolute path (if existing)\n  QFileInfo file_info = QFileInfo (saveFileName);\n  QString file_to_save;\n  if (file_info.exists ())\n    {\n      file_to_save = file_info.canonicalFilePath ();\n      QString base_name = file_info.baseName ();\n\n      // The interpreter_event callback function below emits a signal.\n      // Because we don't control when that happens, use a guarded\n      // pointer so that the callback can abort if this object is no\n      // longer valid.\n\n      QPointer<file_editor_tab> this_fetab (this);\n\n      Q_EMIT interpreter_event\n      ([this, this_fetab, base_name, file_to_save, remove_on_success, restore_breakpoints] (interpreter& interp)\n      {\n        // INTERPRETER THREAD\n\n        // We are intentionally skipping any side effects that may\n        // occur in the callback function if THIS_FETAB is no\n        // longer valid.  If the editor tab has disappeared, there\n        // is not much point in reloading the function to restore\n        // breakpoint info in the GUI.\n\n        if (this_fetab.isNull ())\n          return;\n\n        // Force reloading of a file after it is saved.\n        // This is needed to get the right line numbers for\n        // breakpoints (bug #46632).\n\n        tree_evaluator& tw = interp.get_evaluator ();\n\n        symbol_table& symtab = interp.get_symbol_table ();\n\n        std::string std_base_name = base_name.toStdString ();\n\n        if (tw.in_debug_repl ())\n          {\n            octave_value sym;\n            try\n              {\n                sym = symtab.find_user_function (std_base_name);\n              }\n            catch (const execution_exception&)\n              {\n                interp.recover_from_exception ();\n\n                // Ignore syntax error.  It was in the old file on disk;\n                // the user may have fixed it already.\n              }\n\n            // Return early if this file is not loaded in the symbol table\n            if (! sym.is_defined () || ! sym.is_user_code ())\n              {\n                Q_EMIT do_save_file_signal (file_to_save, remove_on_success,\n                                            restore_breakpoints);\n                return;\n              }\n\n            octave_user_code *fcn = sym.user_code_value ();\n\n            std::string full_name = file_to_save.toStdString ();\n\n            if (sys::canonicalize_file_name (full_name)\n                != sys::canonicalize_file_name (fcn->fcn_file_name ()))\n              {\n                Q_EMIT do_save_file_signal (file_to_save, remove_on_success,\n                                            restore_breakpoints);\n                return;\n              }\n\n            // If this file is loaded, check that we aren't currently\n            // running it.\n            // FIXME: is there a better way to get this info?\n\n            octave_idx_type curr_frame = -1;\n\n            octave_map stk = tw.backtrace (curr_frame, false);\n\n            Cell names = stk.contents (\"name\");\n\n            for (octave_idx_type i = names.numel () - 1; i >= 0; i--)\n              {\n                if (names(i).string_value () == std_base_name)\n                  {\n                    Q_EMIT confirm_dbquit_and_save_signal\n                    (file_to_save, base_name, remove_on_success,\n                     restore_breakpoints);\n                    return;\n                  }\n              }\n          }\n\n        symtab.clear_user_function (std_base_name);\n\n        Q_EMIT do_save_file_signal (file_to_save, remove_on_success,\n                                    restore_breakpoints);\n      });\n    }\n  else\n    Q_EMIT do_save_file_signal (saveFileName, remove_on_success,\n                                restore_breakpoints);\n}\n\nvoid\nfile_editor_tab::do_save_file (const QString& file_to_save,\n                               bool remove_on_success,\n                               bool restore_breakpoints)\n{\n  QSaveFile file (file_to_save);\n\n  // stop watching file\n  enable_file_watcher (false, file_to_save);\n\n  // Remove trailing white spaces if desired\n\n  gui_settings settings;\n\n  if (settings.bool_value (ed_rm_trailing_spaces))\n    {\n      // Replace trailing spaces, make sure edit area is writable,\n      // which is not the case when saving at exit or when closing\n      // the modified file.\n      bool ro = m_edit_area->isReadOnly ();\n      m_edit_area->setReadOnly (false); // allow writing for replace_all\n      m_edit_area->replace_all (\"[ \\\\t]+$\", \"\", true, false, false);\n      m_edit_area->setReadOnly (ro);    // recover read only state\n    }\n\n  // open the file for writing (use QIODevice::ReadWrite for avoiding\n  // truncating the previous file contents)\n  if (! file.open (QIODevice::WriteOnly))\n    {\n      // Unsuccessful, begin watching file again if it was being\n      // watched previously.\n      enable_file_watcher (true, file_to_save);\n\n      // Create a NonModal message about error.\n      QMessageBox *msgBox\n        = new QMessageBox (QMessageBox::Critical,\n                           tr (\"Octave Editor\"),\n                           tr (\"Could not open file %1 for writing:\\n%2.\").\n                           arg (file_to_save).arg (file.errorString ()),\n                           QMessageBox::Ok, nullptr);\n      show_dialog (msgBox, false);\n\n      return;\n    }\n\n  // target encoding\n  std::string encoding = m_encoding.toStdString ();\n  if (encoding.compare (0, 6, \"SYSTEM\") == 0)\n    encoding = octave_locale_charset_wrapper ();\n\n  // check if selected encoding is suitable for contents\n  if (! check_valid_codec ())\n    {\n      // begin watching file again if it was being watched previously\n      enable_file_watcher (true, file_to_save);\n\n      return;  // no valid codec\n    }\n\n  // save contents of editor in file\n\n  QApplication::setOverrideCursor (Qt::WaitCursor);\n\n  if (encoding == \"utf-8\" || encoding == \"UTF-8\")\n    {\n      // use Qt encoding conversion for UTF-8\n      QTextStream out (&file);\n\n#if HAVE_QTEXTSTREAM_SETENCODING\n      out.setEncoding (QStringConverter::Utf8);\n#else\n      out.setCodec (\"UTF-8\");\n#endif\n\n      out << m_edit_area->text ();\n\n      // add newline if desired\n      if (settings.bool_value (ed_force_newline)\n          && m_edit_area->text ().length ())\n        out << m_edit_area->eol_string ();\n\n      out.flush ();\n    }\n  else\n    {\n      // use iconv/gnulib for all other output encodings\n      QDataStream out (&file);\n\n      // get natively UTF-16 encoded content of the QString as STL type\n      std::u16string u16_string = m_edit_area->text ().toStdU16String ();\n\n      // convert to output encoding\n      std::string native_string\n        = string::u16_to_encoding (\"file editor\", u16_string, encoding);\n\n      // save file\n      out.writeRawData (native_string.c_str (), native_string.size ());\n\n      // add newline if desired\n      if (settings.bool_value (ed_force_newline)\n          && m_edit_area->text ().length ())\n        {\n          std::u16string u16_newline\n            = m_edit_area->eol_string ().toStdU16String ();\n          std::string newline\n            = string::u16_to_encoding (\"file editor\", u16_newline, encoding);\n          out.writeRawData (newline.c_str (), newline.size ());\n        }\n    }\n\n  QApplication::restoreOverrideCursor ();\n\n  // Finish writing by committing the changes to disk,\n  // where nothing is done when an error occurred while writing above\n  bool writing_ok = file.commit ();\n\n  if (writing_ok)\n    {\n      // Writing was successful: file exists now\n      QFileInfo file_info = QFileInfo (file.fileName ());\n      QString full_file_to_save = file_info.canonicalFilePath ();\n\n      // file is save -> not modified, update encoding in statusbar\n      m_edit_area->setModified (false);\n      m_enc_indicator->setText (m_encoding);\n\n      // save filename after closing file as set_file_name starts watching again\n      set_file_name (full_file_to_save);   // make absolute\n\n      Q_EMIT tab_ready_to_close ();\n\n      if (remove_on_success)\n        {\n          Q_EMIT tab_remove_request (m_file_name);\n          return;  // Don't touch member variables after removal\n        }\n\n      // Attempt to restore the breakpoints if that is desired.\n      // This is only allowed if the tab is not closing since changing\n      // breakpoints would reopen the tab in this case.\n      if (restore_breakpoints)\n        check_restore_breakpoints ();\n    }\n  else\n    {\n      QMessageBox::critical (nullptr,\n                             tr (\"Octave Editor\"),\n                             tr (\"The changes could not be saved to the file\\n\"\n                                 \"%1\")\n                             .arg (file.fileName ())\n                            );\n    }\n}\n\nvoid\nfile_editor_tab::save_file_as (bool remove_on_success)\n{\n  // Simply put up the file chooser dialog box with a slot connection\n  // then return control to the system waiting for a file selection.\n\n  // reset m_new_encoding\n  m_new_encoding = m_encoding;\n\n  QFileDialog fileDialog (this);\n\n  gui_settings settings;\n\n  if (! settings.bool_value (global_use_native_dialogs))\n    {\n      // Qt file dialogs\n      fileDialog.setOption (QFileDialog::DontUseNativeDialog);\n    }\n  else\n    {\n      // Native file dialogs: Test for already existing files is done manually\n      // since native file dialogs might not consider the automatically\n      // appended default extension when checking if the file already exists\n      fileDialog.setOption (QFileDialog::DontConfirmOverwrite);\n    }\n\n  // add the possible filters and the default suffix\n  QStringList filters;\n  filters << tr (\"Octave Files (*.m)\")\n          << tr (\"All Files (*)\");\n  fileDialog.setNameFilters (filters);\n\n  if (valid_file_name ())\n    {\n      fileDialog.selectFile (m_file_name);\n      QFileInfo file_info (m_file_name);\n      if (file_info.suffix () != \"m\")\n        fileDialog.selectNameFilter (filters.at (1));  // \"All Files\"\n    }\n  else\n    {\n      fileDialog.selectFile (\"\");\n      fileDialog.setDirectory (m_ced);\n\n      // propose a name corresponding to the function name\n      // if the new file contains a function\n      QString fname = get_function_name ();\n      if (! fname.isEmpty ())\n        fileDialog.selectFile (fname + \".m\");\n    }\n\n  fileDialog.setAcceptMode (QFileDialog::AcceptSave);\n  fileDialog.setViewMode (QFileDialog::Detail);\n  fileDialog.setOption (QFileDialog::HideNameFilterDetails, false);\n\n  if (fileDialog.exec ())     // Modal dialog\n    {\n      // Accepted file dialog, no actions required if rejected\n\n      QString save_file_name = fileDialog.selectedFiles ().at (0);\n\n      if (remove_on_success)\n        {\n          // Remove the tab after save\n          if (check_valid_identifier (save_file_name))\n            save_file_as (true);\n          else\n            Q_EMIT editor_check_conflict_save (save_file_name, true);\n        }\n      else\n        {\n          // Save the file under the selected name\n\n          QFileInfo file (save_file_name);\n\n          // Make sure that the file has the desire suffix\n          QString filter = fileDialog.selectedNameFilter ();\n          QRegularExpression rx {\"\\\\*\\\\.([^ ^\\\\)]*)[ \\\\)]\"};    // regexp for suffix in filter\n          QRegularExpressionMatch match = rx.match (filter);\n\n          bool file_name_changed = false;\n          if (match.hasMatch () && file.suffix ().isEmpty ())\n            {\n              save_file_name = save_file_name + \".\" + match.captured (1);\n              file_name_changed = true;\n            }\n\n          // Use final file name\n          file.setFile (save_file_name);\n\n          // Check if overwrite has to checked again\n          if ((file_name_changed || fileDialog.testOption (QFileDialog::DontConfirmOverwrite))\n              && file.exists ())\n            {\n              int ans = QMessageBox::question (this,\n                                               tr (\"Octave Editor\"),\n                                               tr (\"%1\\n already exists\\n\"\n                                                   \"Do you want to overwrite it?\").arg (save_file_name),\n                                               QMessageBox::Yes | QMessageBox::No);\n              if (ans != QMessageBox::Yes)\n                {\n                  // Try again, if edit area is read only, remove on success\n                  save_file_as (remove_on_success);\n                  return;\n                }\n            }\n\n          if (save_file_name == m_file_name)\n            {\n              save_file (save_file_name);\n            }\n          else\n            {\n              // Have editor check for conflict, do not delete tab after save.\n              if (check_valid_identifier (save_file_name))\n                save_file_as (false);\n              else\n                Q_EMIT editor_check_conflict_save (save_file_name, false);\n            }\n\n        }\n    }\n}\n\nbool\nfile_editor_tab::check_valid_identifier (QString file_name)\n{\n  QFileInfo file = QFileInfo (file_name);\n  QString base_name = file.baseName ();\n\n  if ((file.suffix () == \"m\")\n      && (! valid_identifier (base_name.toStdString ())))\n    {\n      int ans = QMessageBox::question (nullptr, tr (\"Octave Editor\"),\n                                       tr (\"\\\"%1\\\"\\n\"\n                                           \"is not a valid identifier.\\n\\n\"\n                                           \"If you keep this filename, you will not be able to\\n\"\n                                           \"call your script using its name as an Octave command.\\n\\n\"\n                                           \"Do you want to choose another name?\").arg (base_name),\n                                       QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);\n\n      if (ans == QMessageBox::Yes)\n        return true;\n    }\n\n  return false;\n}\n\nbool\nfile_editor_tab::check_valid_codec ()\n{\n  QString editor_text = m_edit_area->text ();\n\n  // target encoding\n  std::string encoding = m_encoding.toStdString ();\n  if (encoding.compare (0, 6, \"SYSTEM\") == 0)\n    encoding = octave_locale_charset_wrapper ();\n\n  if (encoding == \"UTF-8\" || encoding == \"utf-8\")\n    return true;\n\n  // check if encoding is valid\n  void *codec = octave_iconv_open_wrapper (encoding.c_str (), \"utf-8\");\n  if (codec == reinterpret_cast<void *> (-1))\n    {\n      if (errno == EINVAL)\n        return false;\n    }\n  else\n    octave_iconv_close_wrapper (codec);\n\n  // check if all characters in the editor can be encoded in the target encoding\n  bool can_encode = true;\n  std::u16string u16_str = editor_text.toStdU16String ();\n  const uint16_t *src = reinterpret_cast<const uint16_t *>\n                        (u16_str.c_str ());\n\n  std::size_t length;\n  char *res_str =\n    octave_u16_conv_to_encoding_strict (encoding.c_str (), src,\n                                        u16_str.size (), &length);\n  if (! res_str)\n    {\n      if (errno == EILSEQ)\n        can_encode = false;\n    }\n  else\n    ::free (static_cast<void *> (res_str));\n\n  if (! can_encode)\n    {\n      QMessageBox::StandardButton pressed_button\n        = QMessageBox::critical (nullptr,\n                                 tr (\"Octave Editor\"),\n                                 tr (\"The current editor contents can not be encoded\\n\"\n                                     \"with the selected encoding %1.\\n\"\n                                     \"Using it would result in data loss!\\n\\n\"\n                                     \"Please select another one!\").arg (m_encoding),\n                                 QMessageBox::Cancel | QMessageBox::Ignore,\n                                 QMessageBox::Cancel);\n\n      if (pressed_button == QMessageBox::Ignore)\n        can_encode = true;\n    }\n\n  return can_encode;\n}\n\nvoid\nfile_editor_tab::file_has_changed (const QString&, bool do_close)\n{\n  bool file_exists = QFile::exists (m_file_name);\n\n  if (file_exists && ! do_close)\n    {\n      // Test if file is really modified or if just the timezone has\n      // changed.  In the latter, just return without doing anything.\n      QDateTime modified = QFileInfo (m_file_name).lastModified ().toUTC ();\n\n      if (modified <= m_last_modified)\n        return;\n\n      m_last_modified = modified;\n    }\n\n  // Prevent popping up multiple message boxes when the file has\n  // been changed multiple times by temporarily removing from the\n  // file watcher.\n  enable_file_watcher (false, m_file_name);\n\n  if (file_exists && ! do_close)\n    {\n\n      // The file is modified outside of octave\n      if (m_always_reload_changed_files && ! m_edit_area->isModified ())\n        load_file (m_file_name);\n\n      else\n        {\n          // give editor and this tab the focus,\n          // possibly making the editor visible if it is hidden\n          Q_EMIT set_focus_editor_signal (this);\n          m_edit_area->setFocus ();\n\n          // Create a WindowModal message that blocks the edit area\n          // by making m_edit_area parent.\n          QString modified = \"\";\n          if (m_edit_area->isModified ())\n            modified = tr (\"\\n\\nWarning: The contents in the editor is modified!\");\n\n          QMessageBox *msgBox\n            = new QMessageBox (QMessageBox::Warning,\n                               tr (\"Octave Editor\"),\n                               tr (\"It seems that \\'%1\\' has been modified by another application. Do you want to reload it?%2\").\n                               arg (m_file_name).arg (modified),\n                               QMessageBox::Yes | QMessageBox::No, this);\n\n          connect (msgBox, &QMessageBox::finished,\n                   this, &file_editor_tab::handle_file_reload_answer);\n\n          msgBox->setWindowModality (Qt::WindowModal);\n          msgBox->setAttribute (Qt::WA_DeleteOnClose);\n          msgBox->show ();\n        }\n    }\n  else\n    {\n      // If desired and if file is not modified,\n      // close the file without any user interaction\n      if (do_close && ! m_edit_area->isModified ())\n        {\n          handle_file_resave_answer (QMessageBox::Cancel);\n          return;\n        }\n\n      // give editor and this tab the focus,\n      // possibly making the editor visible if it is hidden\n      Q_EMIT set_focus_editor_signal (this);\n      m_edit_area->setFocus ();\n\n      QString modified = \"\";\n      if (m_edit_area->isModified ())\n        modified = tr (\"\\n\\nWarning: The contents in the editor is modified!\");\n\n      // Create a WindowModal message.  The file editor tab can't be made\n      // parent because it may be deleted depending upon the response.\n      // Instead, change the m_edit_area to read only.\n      QMessageBox *msgBox\n        = new QMessageBox (QMessageBox::Warning, tr (\"Octave Editor\"),\n                           tr (\"It seems that the file\\n\"\n                               \"%1\\n\"\n                               \"has been deleted or renamed. Do you want to save it now?%2\").\n                           arg (m_file_name).arg (modified),\n                           QMessageBox::Save | QMessageBox::Close, nullptr);\n\n      m_edit_area->setReadOnly (true);\n\n      connect (msgBox, &QMessageBox::finished,\n               this, &file_editor_tab::handle_file_resave_answer);\n\n      msgBox->setWindowModality (Qt::WindowModal);\n      msgBox->setAttribute (Qt::WA_DeleteOnClose);\n      msgBox->show ();\n    }\n}\n\nvoid\nfile_editor_tab::notice_settings (bool init)\n{\n  gui_settings settings;\n\n  if (! init)\n    update_lexer_settings ();\n\n  // code folding\n  if (settings.bool_value (ed_code_folding))\n    {\n      m_edit_area->setMarginType (3, QsciScintilla::SymbolMargin);\n      m_edit_area->setFolding (QsciScintilla::BoxedTreeFoldStyle, 3);\n    }\n  else\n    {\n      m_edit_area->setFolding (QsciScintilla::NoFoldStyle, 3);\n    }\n\n  // status bar\n  if (settings.bool_value (ed_show_edit_status_bar))\n    m_status_bar->show ();\n  else\n    m_status_bar->hide ();\n\n  //highlight current line color\n  m_edit_area->setCaretLineVisible\n  (settings.bool_value (ed_highlight_current_line));\n\n  // auto completion\n  bool match_keywords = settings.bool_value (ed_code_completion_keywords);\n  bool match_document = settings.bool_value (ed_code_completion_document);\n\n  QsciScintilla::AutoCompletionSource source = QsciScintilla::AcsNone;\n  if (match_keywords)\n    if (match_document)\n      source = QsciScintilla::AcsAll;\n    else\n      source = QsciScintilla::AcsAPIs;\n  else if (match_document)\n    source = QsciScintilla::AcsDocument;\n  m_edit_area->setAutoCompletionSource (source);\n\n  m_edit_area->setAutoCompletionReplaceWord\n  (settings.bool_value (ed_code_completion_replace));\n  m_edit_area->setAutoCompletionCaseSensitivity\n  (settings.bool_value (ed_code_completion_case));\n\n  if (settings.bool_value (ed_code_completion))\n    m_edit_area->setAutoCompletionThreshold\n    (settings.int_value (ed_code_completion_threshold));\n  else\n    m_edit_area->setAutoCompletionThreshold (-1);\n\n  if (settings.bool_value (ed_show_white_space))\n    if (settings.bool_value (ed_show_white_space_indent))\n      m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisibleAfterIndent);\n    else\n      m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisible);\n  else\n    m_edit_area->setWhitespaceVisibility (QsciScintilla::WsInvisible);\n\n  m_edit_area->setEolVisibility (settings.bool_value (ed_show_eol_chars));\n\n  m_save_as_desired_eol = static_cast<QsciScintilla::EolMode>\n                          (settings.int_value (ed_default_eol_mode));\n\n  if (settings.bool_value (ed_show_line_numbers))\n    {\n      m_edit_area->setMarginLineNumbers (2, true);\n      auto_margin_width ();\n      connect (m_edit_area, SIGNAL (linesChanged ()),\n               this, SLOT (auto_margin_width ()));\n    }\n  else\n    {\n      m_edit_area->setMarginLineNumbers (2, false);\n      disconnect (m_edit_area, SIGNAL (linesChanged ()), nullptr, nullptr);\n    }\n\n  m_smart_indent = settings.bool_value (ed_auto_indent);\n  m_edit_area->setAutoIndent (m_smart_indent);\n  m_edit_area->setTabIndents\n  (settings.bool_value (ed_tab_indents_line));\n  m_edit_area->setBackspaceUnindents\n  (settings.bool_value (ed_backspace_unindents_line));\n  m_edit_area->setIndentationGuides\n  (settings.bool_value (ed_show_indent_guides));\n  m_edit_area->setIndentationsUseTabs\n  (settings.bool_value (ed_indent_uses_tabs));\n  m_edit_area->setIndentationWidth\n  (settings.int_value (ed_indent_width));\n\n  m_edit_area->setTabWidth\n  (settings.int_value (ed_tab_width));\n\n  m_ind_char_width = 1;\n  if (m_edit_area->indentationsUseTabs ())\n    m_ind_char_width = m_edit_area->tabWidth ();\n\n  m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETHSCROLLBAR,\n                              settings.bool_value (ed_show_hscroll_bar));\n  m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTH, -1);\n  m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTHTRACKING, true);\n\n  update_window_title (m_edit_area->isModified ());\n\n  m_auto_endif = settings.int_value (ed_auto_endif);\n\n  // long line marker\n  int line_length = settings.int_value (ed_long_line_column);\n  m_edit_area->setEdgeColumn (line_length);\n\n  if (settings.bool_value (ed_long_line_marker))\n    {\n      if (settings.bool_value (ed_long_line_marker_line))\n        m_edit_area->setEdgeMode (QsciScintilla::EdgeLine);\n      else\n        {\n          if (settings.bool_value (ed_long_line_marker_background))\n            m_edit_area->setEdgeMode (QsciScintilla::EdgeBackground);\n          else\n            m_edit_area->setEdgeMode (QsciScintilla::EdgeLine);\n        }\n    }\n  else\n    m_edit_area->setEdgeMode (QsciScintilla::EdgeNone);\n\n  // line wrapping and breaking\n  m_edit_area->setWrapVisualFlags (QsciScintilla::WrapFlagByBorder);\n  m_edit_area->setWrapIndentMode (QsciScintilla::WrapIndentSame);\n\n  if (settings.bool_value (ed_wrap_lines))\n    m_edit_area->setWrapMode (QsciScintilla::WrapWord);\n  else\n    m_edit_area->setWrapMode (QsciScintilla::WrapNone);\n\n  if (settings.bool_value (ed_break_lines))\n    m_line_break = line_length;\n  else\n    m_line_break = 0;\n\n  m_line_break_comments =\n    settings.bool_value (ed_break_lines_comments);\n\n  // highlight all occurrences of a word selected by a double click\n  m_highlight_all_occurrences =\n    settings.bool_value (ed_highlight_all_occurrences);\n\n  // reload changed files\n  m_always_reload_changed_files =\n    settings.bool_value (ed_always_reload_changed_files);\n\n  // Set cursor blinking depending on the settings.\n  // QScintilla ignores the application global settings, so some special\n  // handling is required\n  bool cursor_blinking;\n\n  if (settings.contains (global_cursor_blinking.settings_key ()))\n    cursor_blinking = settings.bool_value (global_cursor_blinking);\n  else\n    cursor_blinking = settings.bool_value (cs_cursor_blinking);\n\n  if (cursor_blinking)\n    m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETCARETPERIOD, 500);\n  else\n    m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETCARETPERIOD, 0);\n\n}\n\nvoid\nfile_editor_tab::auto_margin_width ()\n{\n  m_edit_area->setMarginWidth (2, \"1\" + QString::number (m_edit_area->lines ()));\n}\n\n// the following close request was changed from a signal slot into a\n// normal function because we need the return value from close whether\n// the tab really was closed (for canceling exiting octave).\n// When emitting a signal, only the return value from the last slot\n// goes back to the sender\nbool\nfile_editor_tab::conditional_close ()\n{\n  return close ();\n}\n\nvoid\nfile_editor_tab::change_editor_state (const QWidget *ID)\n{\n  if (ID != this)\n    return;\n\n  Q_EMIT editor_state_changed (m_copy_available, m_is_octave_file,\n                               m_edit_area->isModified ());\n}\n\nvoid\nfile_editor_tab::handle_file_reload_answer (int decision)\n{\n  if (decision == QMessageBox::Yes)\n    {\n      // reload: file is readded to the file watcher in set_file_name ()\n      load_file (m_file_name);\n    }\n  else\n    {\n      // do not reload: readd to the file watcher\n      enable_file_watcher (true, m_file_name);\n    }\n}\n\nvoid\nfile_editor_tab::handle_file_resave_answer (int decision)\n{\n  // check decision of user in dialog\n  if (decision == QMessageBox::Save)\n    {\n      save_file (m_file_name);  // readds file to watcher in set_file_name ()\n      m_edit_area->setReadOnly (false);  // delete read only flag\n    }\n  else\n    {\n      // Definitely close the file.\n      // Set modified to false to prevent the dialog box when the close event\n      // is posted.  If the user cancels the close in this dialog the tab is\n      // left open with a non-existing file.\n      m_edit_area->setModified (false);\n      close ();\n    }\n}\n\nvoid\nfile_editor_tab::insert_debugger_pointer (const QWidget *ID, int line)\n{\n  if (ID != this || ID == nullptr)\n    return;\n\n  Q_EMIT remove_all_positions ();  // debugger_position, unsure_debugger_position\n\n  if (line > 0)\n    {\n      marker *dp;\n\n      if (m_edit_area->isModified ())\n        {\n          // The best that can be done if the editor contents have been\n          // modified is to see if there is a match with the original\n          // line number of any existing breakpoints.  We can put a normal\n          // debugger pointer at that breakpoint position.  Otherwise, it\n          // isn't certain whether the original line number and current line\n          // number match.\n          int editor_linenr = -1;\n          marker *dummy;\n          Q_EMIT find_translated_line_number (line, editor_linenr, dummy);\n          if (editor_linenr != -1)\n            {\n              // Match with an existing breakpoint.\n              dp = new marker (m_edit_area, line,\n                               marker::debugger_position, editor_linenr);\n            }\n          else\n            {\n              int original_linenr = -1;\n              editor_linenr = -1;\n              Q_EMIT find_linenr_just_before (line, original_linenr, editor_linenr);\n              if (original_linenr >= 0)\n                {\n                  // Make a guess by using an offset from the breakpoint.\n                  int linenr_guess = editor_linenr + line - original_linenr;\n                  dp = new marker (m_edit_area, line,\n                                   marker::unsure_debugger_position,\n                                   linenr_guess);\n                }\n              else\n                {\n                  // Can't make a very good guess, so just use the debugger\n                  // line number.\n                  dp = new marker (m_edit_area, line,\n                                   marker::unsure_debugger_position);\n                }\n            }\n        }\n      else\n        {\n          dp = new marker (m_edit_area, line, marker::debugger_position);\n\n          // In case of a not modified file we might have to remove\n          // a breakpoint here if we have stepped into the file\n          if (line == m_breakpoint_info.remove_line)\n            {\n              m_breakpoint_info.remove_line = -1;\n              if (line != m_breakpoint_info.do_not_remove_line)\n                handle_request_remove_breakpoint (line);\n            }\n        }\n\n      connect (this, &file_editor_tab::remove_position_via_debugger_linenr,\n               dp, &marker::handle_remove_via_original_linenr);\n\n      connect (this, &file_editor_tab::remove_all_positions,\n               dp, &marker::handle_remove);\n\n      center_current_line (false);\n    }\n}\n\nvoid\nfile_editor_tab::delete_debugger_pointer (const QWidget *ID, int line)\n{\n  if (ID != this || ID == nullptr)\n    return;\n\n  if (line > 0)\n    Q_EMIT remove_position_via_debugger_linenr (line);\n}\n\nvoid\nfile_editor_tab::do_breakpoint_marker (bool insert,\n                                       const QWidget *ID, int line,\n                                       const QString& cond)\n{\n  if (ID != this || ID == nullptr)\n    return;\n\n  if (line > 0)\n    {\n      if (insert)\n        {\n          int editor_linenr = -1;\n          marker *bp = nullptr;\n\n          // If comes back indicating a nonzero breakpoint marker,\n          // reuse it if possible\n          Q_EMIT find_translated_line_number (line, editor_linenr, bp);\n          if (bp != nullptr)\n            {\n              if ((cond == \"\") != (bp->get_cond () == \"\"))\n                {\n                  // can only reuse conditional bp as conditional\n                  Q_EMIT remove_breakpoint_via_debugger_linenr (line);\n                  bp = nullptr;\n                }\n              else\n                bp->set_cond (cond);\n            }\n\n          if (bp == nullptr)\n            {\n              bp = new marker (m_edit_area, line,\n                               cond == \"\" ? marker::breakpoint\n                               : marker::cond_break, cond);\n\n              connect (this, &file_editor_tab::remove_breakpoint_via_debugger_linenr,\n                       bp, &marker::handle_remove_via_original_linenr);\n              connect (this, &file_editor_tab::request_remove_breakpoint_via_editor_linenr,\n                       bp, &marker::handle_request_remove_via_editor_linenr);\n              connect (this, &file_editor_tab::remove_all_breakpoints_signal,\n                       bp, &marker::handle_remove);\n              connect (this, &file_editor_tab::find_translated_line_number,\n                       bp, &marker::handle_find_translation);\n              connect (this, &file_editor_tab::find_linenr_just_before,\n                       bp, &marker::handle_find_just_before);\n              connect (this, &file_editor_tab::report_marker_linenr,\n                       bp, &marker::handle_report_editor_linenr);\n              connect (bp, &marker::request_remove,\n                       this, &file_editor_tab::handle_request_remove_breakpoint);\n            }\n        }\n      else\n        Q_EMIT remove_breakpoint_via_debugger_linenr (line);\n    }\n}\n\nvoid\nfile_editor_tab::center_current_line (bool always)\n{\n  long int visible_lines\n    = m_edit_area->SendScintilla (QsciScintillaBase::SCI_LINESONSCREEN);\n\n  if (visible_lines > 2)\n    {\n      int line, index;\n      m_edit_area->getCursorPosition (&line, &index);\n      // compensate for \"folding\":\n      // step 1: expand the current line, if it was folded\n      m_edit_area->SendScintilla (2232, line);   // SCI_ENSUREVISIBLE\n\n      // step 2: map file line num to \"visible\" one // SCI_VISIBLEFROMDOCLINE\n      int vis_line = m_edit_area->SendScintilla (2220, line);\n\n      int first_line = m_edit_area->firstVisibleLine ();\n\n      if (always || vis_line == first_line\n          || vis_line > first_line + visible_lines - 2)\n        {\n          first_line += (vis_line - first_line - (visible_lines - 1) / 2);\n          m_edit_area->SendScintilla (2613, first_line); // SCI_SETFIRSTVISIBLELINE\n        }\n    }\n}\n\nvoid\nfile_editor_tab::handle_lines_changed ()\n{\n  // the related signal is emitted before cursor-move-signal!\n  m_lines_changed = true;\n}\n\nvoid\nfile_editor_tab::handle_cursor_moved (int line, int col)\n{\n  // Cursor has moved, first check wether an autocompletion list\n  // is active or if it was closed.  Scintilla provides signals for\n  // completed or cancelled lists, but not for list that where hidden\n  // due to a new character not matching anymore with the list entries\n  if (m_edit_area->SendScintilla (QsciScintillaBase::SCI_AUTOCACTIVE))\n    m_autoc_active = true;\n  else if (m_autoc_active)\n    {\n      m_autoc_active = false;\n      Q_EMIT autoc_closed (); // Tell editor about closed list\n    }\n\n  // Lines changed? Take care of indentation!\n  bool do_smart_indent = m_lines_changed && m_is_octave_file\n                         && (line == m_line+1) && (col < m_col)\n                         && (m_smart_indent || m_auto_endif);\n  m_lines_changed = false;\n\n  // Update line and column indicator in the status bar\n  int o_line = m_line;\n  update_rowcol_indicator (line, col);\n\n  // Do smart indent after update of line indicator for having\n  // consistent indicator data\n  if (do_smart_indent)\n    m_edit_area->smart_indent (m_smart_indent, m_auto_endif,\n                               o_line, m_ind_char_width);\n}\n\nvoid\nfile_editor_tab::update_rowcol_indicator (int line, int col)\n{\n  m_line = line;\n  m_col  = col;\n  m_row_indicator->setNum (line+1);\n  m_col_indicator->setNum (col+1);\n}\n\n// Slot that is entered each time a new character was typed.\n// It is used for handling line breaking if this is desired.\n// The related signal is emitted after the signal for a moved cursor\n// such that m_col and m_line can not be used for current position.\nvoid\nfile_editor_tab::handle_char_added (int)\n{\n  if (m_line_break)\n    {\n      // If line breaking is desired, get the current line and column.\n      // For taking the tab width into consideration, use own function\n      int line, col, pos;\n      m_edit_area->get_current_position (&pos, &line, &col);\n\n      // immediately return if line has not reached the max. line length\n      if (col <= m_line_break)\n        return;\n\n      // If line breaking is only desired in comments,\n      // return if not in a comment\n      int style_comment = octave_qscintilla::ST_NONE;\n      if (m_line_break_comments)\n        {\n          // line breaking only in comments, check for comment style\n          style_comment = m_edit_area->is_style_comment ();\n          if (! style_comment)\n            return;       // no comment, return\n        }\n\n      // Here we go for breaking the current line by inserting a newline.\n      // For determining the position of a specific column, we have to get\n      // the column from the QScintilla function without taking tab lengths\n      // into account, since the calculation from line/col to position\n      // ignores this, too.\n      m_edit_area->getCursorPosition (&line, &col);\n      int c = 0;\n      int col_space = col;\n      int indentation = m_edit_area->indentation (line);\n\n      // Search the first occurrence of space or tab backwards starting from\n      // the current column (col_space).\n      while (c != ' ' && c != '\\t' && col_space > indentation)\n        {\n          pos = m_edit_area->positionFromLineIndex (line, col_space--);\n          c = m_edit_area->SendScintilla (QsciScintillaBase::SCI_GETCHARAT, pos);\n        }\n\n      // If a space or tab was found, break at this char,\n      // otherwise break at cursor position\n      int col_newline = col - 1;\n      if (c == ' ' || c == '\\t')\n        col_newline = col_space + 1;\n\n      // Insert a newline char for breaking the line possibly followed\n      // by a line comment string\n      QString newline = QString (\"\\n\");\n      style_comment = m_edit_area->is_style_comment ();\n      if (style_comment == octave_qscintilla::ST_LINE_COMMENT)\n        newline = newline + m_edit_area->comment_string ().at (0);\n      m_edit_area->insertAt (newline, line, col_newline);\n\n      // Automatically indent the new line to the indentation of previous line\n      // and set the cursor position to the end of the indentation.\n      m_edit_area->setIndentation (line + 1, indentation);\n      m_edit_area->SendScintilla (QsciScintillaBase::SCI_LINEEND);\n    }\n}\n\nvoid\nfile_editor_tab::select_all_occurrences (const find_files_data& ff_data,\n                                         bool goto_first_occurrence)\n{\n  // clear any existing indicators of this type\n  m_edit_area->clear_selection_markers ();\n\n  // get the resulting cursor position\n  int line, col;\n  m_edit_area->getCursorPosition (&line, &col);\n\n  QString word = ff_data.search_text;\n  bool whole_word = false;\n  if (word.isEmpty())\n    {\n      // get the word at the cursor (if any)\n      word = m_edit_area->wordAtLineIndex (line, col);\n      word = word.trimmed ();\n      whole_word = true;    // always whole word (selected by double click)\n    }\n\n  if (word.isEmpty())\n    return;\n\n  int first_line, first_col;\n  if (goto_first_occurrence)\n    {\n       // set first line very high, and update with search occurrances\n      first_line = 1000000;\n      first_col = 0;\n    }\n  else\n    {\n      // remember first visible line and x-offset for restoring the view afterwards\n      first_line = m_edit_area->firstVisibleLine ();\n    }\n\n  int x_offset = m_edit_area->SendScintilla (QsciScintillaBase::SCI_GETXOFFSET);\n\n  // search for first occurrence of the detected word\n  bool find_result_available\n    = m_edit_area->findFirst (word,\n                              false,   // no regexp\n                              ff_data.case_sensitive,   // case sensitive\n                              whole_word,               // whole words only\n                              false,   // do not wrap\n                              true,    // forward\n                              0, 0,    // from the beginning\n                              false\n#if defined (HAVE_QSCI_VERSION_2_6_0)\n                              , true\n#endif\n                             );\n\n  // loop over all occurrences and set the related indicator\n  int oline, ocol;\n  int wlen = word.length ();\n\n  while (find_result_available)\n    {\n      // get cursor position after having found an occurrence\n      m_edit_area->getCursorPosition (&oline, &ocol);\n      if (goto_first_occurrence && (oline < first_line))\n        {\n          // update varibales for first occurrance\n          first_line = oline;\n          first_col = ocol;\n        }\n      // mark the selection\n      m_edit_area->show_selection_markers (oline, ocol-wlen, oline, ocol);\n\n      // find next occurrence\n      find_result_available = m_edit_area->findNext ();\n    }\n\n  // restore the visible area of the file, the cursor position,\n  // and the selection\n  m_edit_area->setFirstVisibleLine (first_line);\n  m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETXOFFSET, x_offset);\n  if (goto_first_occurrence)\n    {\n      line = first_line;\n      col = first_col;\n    }\n   m_edit_area->setCursorPosition (line, col);\n   m_edit_area->setSelection (line, col - wlen, line, col);\n   m_edit_area->set_word_selection (word);\n}\n\n// Slot handling a double click into the text area\nvoid\nfile_editor_tab::handle_double_click (int, int, int modifier)\n{\n  if (! modifier)\n    {\n      // double clicks without modifier\n      if (m_highlight_all_occurrences)\n        {\n          m_edit_area->set_word_selection ();   // Clear any previous selection\n          select_all_occurrences ();            // Do search and selection\n        }\n    }\n}\n\nQString\nfile_editor_tab::get_function_name ()\n{\n  QRegularExpression rxfun1 {\"^[\\t ]*function[^=]+=([^\\\\(]+)\\\\([^\\\\)]*\\\\)[\\t ]*$\"};\n  QRegularExpression rxfun2 {\"^[\\t ]*function[\\t ]+([^\\\\(]+)\\\\([^\\\\)]*\\\\)[\\t ]*$\"};\n  QRegularExpression rxfun3 {\"^[\\t ]*function[^=]+=[\\t ]*([^\\\\s]+)[\\t ]*$\"};\n  QRegularExpression rxfun4 {\"^[\\t ]*function[\\t ]+([^\\\\s]+)[\\t ]*$\"};\n  QRegularExpression rxfun5 {\"^[\\t ]*classdef[\\t ]+([^\\\\s]+)[\\t ]*$\"};\n\n  QStringList lines = m_edit_area->text ().split (\"\\n\");\n\n  for (int i = 0; i < lines.count (); i++)\n    {\n      QRegularExpressionMatch match = rxfun1.match (lines.at (i));\n      if (match.hasMatch ())\n        return match.captured (1).remove (QRegularExpression {\"[ \\t]*\"});\n      match = rxfun2.match (lines.at (i));\n      if (match.hasMatch ())\n        return match.captured (1).remove (QRegularExpression {\"[ \\t]*\"});\n      match = rxfun3.match (lines.at (i));\n      if (match.hasMatch ())\n        return match.captured (1).remove (QRegularExpression {\"[ \\t]*\"});\n      match = rxfun4.match (lines.at (i));\n      if (match.hasMatch ())\n        return match.captured (1).remove (QRegularExpression {\"[ \\t]*\"});\n      match = rxfun5.match (lines.at (i));\n      if (match.hasMatch ())\n        return match.captured (1).remove (QRegularExpression {\"[ \\t]*\"});\n    }\n\n  return QString ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/file-editor-tab.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_file_editor_tab_h)\n#define octave_file_editor_tab_h 1\n\n#include <QAbstractButton>\n#include <QCloseEvent>\n#include <QDateTime>\n#include <QFileInfo>\n#include <QFileSystemWatcher>\n#include <QLabel>\n#include <QStatusBar>\n#include <QWidget>\n#include <Qsci/qsciapis.h>\n\n#include \"marker.h\"\n#include \"octave-qscintilla.h\"\n#include \"find-files-dialog.h\"\n#include \"qt-interpreter-events.h\"\n\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass file_editor;\n\nclass file_editor_tab : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  file_editor_tab (const QString& directory = \"\");\n\n  ~file_editor_tab ();\n\n  octave_qscintilla * qsci_edit_area () { return m_edit_area; }\n\n  // Will initiate close if associated with the identifier tag.\n  bool conditional_close ();\n\n  void update_breakpoints ();\n  void set_file_name (const QString& fileName);\n  void enable_file_watcher (bool do_enable, const QString& fname = QString ());\n\n  QString file_name () const { return m_file_name; }\n  QString encoding () const { return m_encoding; }\n\nQ_SIGNALS:\n\n  void tab_ready_to_close ();\n  void file_name_changed (const QString& fileName,\n                          const QString& toolTip,\n                          bool modified);\n  void editor_state_changed (bool copy_available, bool is_octave_file,\n                             bool is_modified);\n  void set_focus_editor_signal (QWidget *);\n  void edit_area_changed (octave_qscintilla *edit_area);\n  void tab_remove_request (const QString& file_name);\n  void mru_add_file (const QString& file_name, const QString& encoding);\n  void editor_check_conflict_save (const QString& saveFileName,\n                                   bool remove_on_success);\n  void run_file_signal (const QFileInfo& info, int opts);\n  void request_open_file (const QString&, const QString& = QString ());\n  void edit_mfile_request (const QString&, const QString&,\n                           const QString&, int);\n\n  void autoc_closed ();\n\n  void update_breakpoints_signal (const octave_value_list& args);\n  void remove_breakpoint_via_debugger_linenr (int debugger_linenr);\n  void request_remove_breakpoint_via_editor_linenr (int editor_linenr);\n  void remove_all_breakpoints_signal ();\n  void find_translated_line_number (int original_linenr,\n                                    int& translated_linenr, marker *&);\n  void find_linenr_just_before (int linenr, int& original_linenr,\n                                int& editor_linenr);\n  void report_marker_linenr (QIntList& lines, QStringList& conditions);\n  void remove_position_via_debugger_linenr (int debugger_linenr);\n  void remove_all_positions ();\n\n  void debug_quit_signal ();\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\n  void maybe_remove_next (int remove_line);\n\n  void dbstop_if (const QString& prompt, int line, const QString& cond);\n  void request_add_breakpoint (int line, const QString& cond);\n  void request_add_octave_apis (const QStringList&);\n  void api_entries_added ();\n\n  void do_save_file_signal (const QString& file_to_save,\n                            bool remove_on_success, bool restore_breakpoints);\n\n  void confirm_dbquit_and_save_signal (const QString& file_to_save,\n                                       const QString& base_name,\n                                       bool remove_on_success,\n                                       bool restore_breakpoints);\n\n  void remove_editor_file_in_browser_signal (const QString& file);\n  void rename_editor_file_in_browser_signal (const QString& old_file,\n                                             const QString& new_file);\n\n  // FIXME: The following is similar to \"process_octave_code\" signal.\n  // However, currently that signal is connected to something that simply\n  // focuses a window and does not actually communicate with Octave.\n  //\n  // void evaluate_octave_command (const QString& command);\n\npublic Q_SLOTS:\n\n  void update_window_title (bool modified);\n  void handle_copy_available (bool enableCopy);\n  void handle_margin_clicked (int line, int margin,\n                              Qt::KeyboardModifiers state);\n\n  // Tells the editor tab to react on changed settings.\n  void notice_settings (bool init = false);\n\n  // Change to a different editor tab by identifier tag.\n  void change_editor_state (const QWidget *ID);\n\n  void set_focus (const QWidget *ID);\n  void set_current_directory (const QString& dir);\n  void context_help (const QWidget *ID, bool);\n  void context_edit (const QWidget *ID);\n  void save_file (const QWidget *ID);\n  void save_file (const QWidget *ID, const QString& fileName,\n                  bool remove_on_success);\n  void save_file_as (const QWidget *ID);\n  void print_file (const QWidget *ID);\n  void run_file (const QWidget *ID, int opts);\n  void context_run (const QWidget *ID);\n  void toggle_bookmark (const QWidget *ID);\n  void next_bookmark (const QWidget *ID);\n  void previous_bookmark (const QWidget *ID);\n  void remove_bookmark (const QWidget *ID);\n\n  void toggle_breakpoint (const QWidget *ID);\n  void next_breakpoint (const QWidget *ID);\n  void previous_breakpoint (const QWidget *ID);\n  void remove_all_breakpoints (const QWidget *ID);\n\n  void scintilla_command (const QWidget *, unsigned int);\n\n  void comment_selected_text (const QWidget *ID, bool input_str);\n  void uncomment_selected_text (const QWidget *ID);\n\n  void indent_selected_text (const QWidget *ID);\n  void unindent_selected_text (const QWidget *ID);\n  void smart_indent_line_or_selected_text (const QWidget *ID);\n  void convert_eol (const QWidget *ID, QsciScintilla::EolMode);\n\n  void zoom_in (const QWidget *ID);\n  void zoom_out (const QWidget *ID);\n  void zoom_normal (const QWidget *ID);\n\n  void goto_line (const QWidget *ID, int line = -1);\n  void move_match_brace (const QWidget *ID, bool select);\n  void show_auto_completion (const QWidget *ID);\n\n  void select_all_occurrences (const find_files_data& ff_data = {false, QString (), true},\n                               bool goto_first_occurrence = false);\n\n  void insert_debugger_pointer (const QWidget *ID, int line = -1);\n  void delete_debugger_pointer (const QWidget *ID, int line = -1);\n\n  void do_breakpoint_marker (bool insert, const QWidget *ID, int line = -1,\n                             const QString& cond = \"\");\n\n  void recover_from_exit ();\n  void set_modified (bool modified = true);\n\n  void set_encoding (const QString& new_encoding);\n\n  QString load_file (const QString& fileName);\n\n  void new_file (const QString& commands = QString ());\n\n  void file_has_changed (const QString& path, bool do_close = false);\n\n  void handle_context_menu_edit (const QString&);\n  void handle_context_menu_break_condition (int linenr);\n\n  void handle_request_add_breakpoint (int line, const QString& cond);\n  void handle_request_remove_breakpoint (int line);\n\n  void update_breakpoints_handler (const octave_value_list& argout);\n  void update_rowcol_indicator (int line, int col);\n  void update_lexer_settings (bool update_apis_only = false);\n\nprivate Q_SLOTS:\n\n  // When user closes message box for decoding problems\n  void handle_decode_warning_answer (QAbstractButton *btn);\n\n  // When user closes message box for reload question.\n  void handle_file_reload_answer (int decision);\n\n  // When user closes message box for resave question.\n  void handle_file_resave_answer (int decision);\n\n  // When user changes encoding after decoding errors were found\n  void handle_current_enc_changed (const QString& enc);\n\n  // When apis preparation has finished and is ready to save\n  void save_apis_info ();\n\n  // When the numer of lines changes -> adapt width of margin\n  void auto_margin_width ();\n\n  void handle_cursor_moved (int line, int col);\n  void handle_char_added (int character);\n  void handle_double_click (int p, int l, int modifier);\n  void handle_lines_changed ();\n\n  void handle_remove_next (int remove_line);\n  void handle_dbstop_if (const QString& prompt, int line,\n                         const QString& cond);\n  void handle_add_octave_apis (const QStringList& api_entries);\n  void handle_api_entries_added ();\n\n  void do_save_file (const QString& file_to_save, bool remove_on_success,\n                     bool restore_breakpoints);\n\n  void confirm_dbquit_and_save (const QString& file_to_save,\n                                const QString& base_name,\n                                bool remove_on_success,\n                                bool restore_breakpoints);\n\nprotected:\n\n  void closeEvent (QCloseEvent *event);\n\nprivate:\n\n  void add_breakpoint_event (int line, const QString& cond);\n\n  bool valid_file_name (const QString& file = QString ());\n  void save_file (const QString& saveFileName, bool remove_on_success = false,\n                  bool restore_breakpoints = true);\n  void save_file_as (bool remove_on_success = false);\n  bool check_valid_identifier (QString file_name);\n  bool check_valid_codec ();\n\n  bool unchanged_or_saved ();\n\n  void update_lexer ();\n\n  void show_dialog (QDialog *dlg, bool modal);\n\npublic:\n\n  int check_file_modified (bool remove = false);\n  QString get_all_bookmarks ();\n\nprivate:\n  void do_comment_selected_text (bool comment, bool input_str = false);\n  void do_indent_selected_text (bool indent);\n  void do_smart_indent_line_or_selected_text ();\n\n  void check_restore_breakpoints ();\n  void center_current_line (bool always=true);\n\n  QString get_function_name ();\n\n  QsciScintilla::EolMode detect_eol_mode ();\n  void update_eol_indicator ();\n\n  octave_qscintilla *m_edit_area;\n\n  QStatusBar *m_status_bar;\n  QLabel *m_row_indicator;\n  QLabel *m_col_indicator;\n  QLabel *m_eol_indicator;\n  QLabel *m_enc_indicator;\n\n  QsciScintilla::EolMode m_save_as_desired_eol;\n\n  QString m_file_name;\n  QString m_file_name_short;\n  QString m_ced;\n  QString m_encoding;\n  QString m_new_encoding;\n  QDateTime m_last_modified;\n\n  bool m_autoc_active;\n  bool m_copy_available;\n  bool m_is_octave_file;\n  bool m_always_reload_changed_files;\n  bool m_smart_indent;\n  int m_auto_endif;\n  int m_ind_char_width;\n\n  QFileSystemWatcher m_file_system_watcher;\n\n  QIntList m_bp_lines;\n  QStringList m_bp_conditions;\n\n  QsciAPIs *m_lexer_apis;\n  QString m_prep_apis_path;\n  QString m_prep_apis_file;\n\n  int m_line_break;\n  bool m_line_break_comments;\n  int m_line;\n  int m_col;\n  bool m_lines_changed;\n  bool m_highlight_all_occurrences;\n  int m_bp_restore_count;\n\n  struct breakpoint_info\n  {\n    bool remove_next;\n    int remove_line;\n    int do_not_remove_line;\n  };\n\n  breakpoint_info m_breakpoint_info;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/file-editor.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_QSCINTILLA)\n\n#include <algorithm>\n\n#include <QApplication>\n#include <QClipboard>\n#include <QFile>\n#include <QFileDialog>\n#include <QFont>\n#include <QMessageBox>\n#include <QMimeData>\n#include <QProcess>\n#include <QPushButton>\n#include <QStyle>\n#include <QTabBar>\n#include <QTextStream>\n#include <QVBoxLayout>\n#include <Qsci/qscicommandset.h>\n\n#include \"gui-preferences-global.h\"\n#include \"file-editor.h\"\n#include \"gui-preferences-ed.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-settings.h\"\n#include \"main-window.h\"\n\n#include \"oct-env.h\"\n#include \"oct-sysdep.h\"\n\n#include \"event-manager.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"pt-eval.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Functions of the reimplemented tab widget\n\nfile_editor_tab_widget::file_editor_tab_widget (QWidget *p, file_editor *fe)\n  : QTabWidget (p)\n{\n  tab_bar *bar = new tab_bar (this);\n\n  connect (bar, &tab_bar::close_current_tab_signal,\n           fe, &file_editor::request_close_file);\n\n  this->setTabBar (bar);\n\n  setTabsClosable (true);\n  setUsesScrollButtons (true);\n  setMovable (true);\n}\n\ntab_bar *\nfile_editor_tab_widget::get_tab_bar () const\n{\n  return qobject_cast<tab_bar *> (tabBar ());\n}\n\nstd::list<file_editor_tab *>\nfile_editor_tab_widget::tab_list () const\n{\n  std::list<file_editor_tab *> retval;\n  for (int i = 0; i < count (); i++)\n    retval.push_back (static_cast<file_editor_tab *> (widget (i)));\n  return retval;\n}\n\n// File editor\n\nfile_editor::file_editor (QWidget *p)\n  : file_editor_interface (p)\n{\n  // Set current editing directory before construction because loaded\n  // files will change ced accordingly.\n  m_ced = QDir::currentPath ();\n\n  // Set actions that are later added by the main window to null,\n  // preventing access to them when they are still undefined.\n  m_undo_action = nullptr;\n  m_copy_action = nullptr;\n  m_paste_action = nullptr;\n  m_selectall_action = nullptr;\n\n  m_find_dialog = nullptr;\n\n  m_closed = true;\n  m_no_focus = false;\n  m_editor_ready = false;\n  m_is_octave_file = true;\n\n  m_copy_action_enabled = false;\n  m_undo_action_enabled = false;\n  m_current_tab_modified = false;\n\n  construct ();\n\n  setVisible (false);\n  setAcceptDrops (true);\n  setFocusPolicy (Qt::StrongFocus);\n}\n\nvoid\nfile_editor::focusInEvent (QFocusEvent *e)\n{\n  // The focus is transferred to the active tab and its edit\n  // area in this focus in event handler.  This is to avoid\n  // using focus proxies with conflicts in the proxy change\n  // presumably introduced by bug\n  // https://bugreports.qt.io/browse/QTBUG-61092\n  reset_focus (); // Make sure editor tab with edit area get focus\n\n  QDockWidget::focusInEvent (e);\n}\n\n// insert global actions, that should also be displayed in the editor window,\n// into the editor's menu and/or toolbar\nvoid\nfile_editor::insert_global_actions (QList<QAction *> shared_actions)\n{\n  // actions/menus that have to be added to the toolbar or the menu\n  QAction *open_action = shared_actions.at (OPEN_ACTION);\n  QAction *new_action = shared_actions.at (NEW_SCRIPT_ACTION);\n  QAction *new_fcn_action = shared_actions.at (NEW_FUNCTION_ACTION);\n  m_fileMenu->insertAction (m_mru_file_menu->menuAction (), open_action);\n  m_fileMenu->insertAction (open_action, new_fcn_action);\n  m_fileMenu->insertAction (new_fcn_action, new_action);\n  m_tool_bar->insertAction (m_popdown_mru_action, open_action);\n  m_tool_bar->insertAction (open_action, new_action);\n\n  // actions that are additionally enabled/disabled later by the editor\n  // undo\n  m_undo_action = shared_actions.at (UNDO_ACTION);\n  m_tool_bar->insertAction (m_redo_action, m_undo_action);\n  m_edit_menu->insertAction (m_redo_action, m_undo_action);\n  // select all\n  m_selectall_action = shared_actions.at (SELECTALL_ACTION);\n  m_edit_menu->insertAction (m_find_action, m_selectall_action);\n  m_edit_menu->insertSeparator (m_find_action);\n  // paste\n  m_paste_action = shared_actions.at (PASTE_ACTION);\n  m_tool_bar->insertAction (m_find_action, m_paste_action);\n  m_edit_menu->insertAction (m_selectall_action, m_paste_action);\n  m_edit_menu->insertSeparator (m_selectall_action);\n  // copy\n  m_copy_action = shared_actions.at (COPY_ACTION);\n  m_tool_bar->insertAction (m_paste_action, m_copy_action);\n  m_edit_menu->insertAction (m_paste_action, m_copy_action);\n  // find files\n  m_find_files_action = shared_actions.at (FIND_FILES_ACTION);\n  m_edit_menu->insertAction (m_find_action, m_find_files_action);\n}\n\nconst QString\nfile_editor::get_current_filename ()\n{\n  file_editor_tab *editor_tab\n    = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());\n  return editor_tab->file_name ();\n}\n\nvoid\nfile_editor::handle_enter_debug_mode ()\n{\n  gui_settings settings;\n\n  QString sc_run = settings.sc_value (sc_edit_run_run_file);\n  QString sc_cont = settings.sc_value (sc_main_debug_continue);\n\n  if (sc_run == sc_cont)\n    m_run_action->setShortcut (QKeySequence ());  // prevent ambiguous shortcuts\n\n  m_run_action->setToolTip (tr (\"Continue\"));   // update tool tip\n\n  Q_EMIT enter_debug_mode_signal ();\n}\n\nvoid\nfile_editor::handle_exit_debug_mode ()\n{\n  gui_settings settings;\n  settings.set_shortcut (m_run_action, sc_edit_run_run_file);\n  m_run_action->setToolTip (tr (\"Save File and Run\"));  // update tool tip\n\n  Q_EMIT exit_debug_mode_signal ();\n}\n\nvoid\nfile_editor::check_actions ()\n{\n  // Do not include shared actions not only related to the editor\n  bool have_tabs = m_tab_widget->count () > 0;\n\n  m_edit_cmd_menu->setEnabled (have_tabs);\n  m_edit_fmt_menu->setEnabled (have_tabs);\n  m_edit_nav_menu->setEnabled (have_tabs);\n\n  m_comment_selection_action->setEnabled (have_tabs);\n  m_uncomment_selection_action->setEnabled (have_tabs);\n  m_comment_var_selection_action->setEnabled (have_tabs);\n  m_indent_selection_action->setEnabled (have_tabs);\n  m_unindent_selection_action->setEnabled (have_tabs);\n  m_smart_indent_line_or_selection_action->setEnabled (have_tabs);\n\n  m_context_help_action->setEnabled (have_tabs);\n  m_context_doc_action->setEnabled (have_tabs);\n\n  m_view_editor_menu->setEnabled (have_tabs);\n  m_zoom_in_action->setEnabled (have_tabs);\n  m_zoom_out_action->setEnabled (have_tabs);\n  m_zoom_normal_action->setEnabled (have_tabs);\n\n  m_find_action->setEnabled (have_tabs);\n  m_find_next_action->setEnabled (have_tabs);\n  m_find_previous_action->setEnabled (have_tabs);\n  m_print_action->setEnabled (have_tabs);\n\n  m_run_action->setEnabled (have_tabs && m_is_octave_file);\n\n  m_toggle_breakpoint_action->setEnabled (have_tabs && m_is_octave_file);\n  m_next_breakpoint_action->setEnabled (have_tabs && m_is_octave_file);\n  m_previous_breakpoint_action->setEnabled (have_tabs && m_is_octave_file);\n  m_remove_all_breakpoints_action->setEnabled (have_tabs && m_is_octave_file);\n\n  m_edit_function_action->setEnabled (have_tabs);\n  m_save_action->setEnabled (have_tabs && m_current_tab_modified);\n  m_save_as_action->setEnabled (have_tabs);\n  m_close_action->setEnabled (have_tabs);\n  m_close_all_action->setEnabled (have_tabs);\n  m_close_others_action->setEnabled (have_tabs && m_tab_widget->count () > 1);\n  m_sort_tabs_action->setEnabled (have_tabs && m_tab_widget->count () > 1);\n\n  Q_EMIT editor_tabs_changed_signal (have_tabs, m_is_octave_file);\n}\n\n// empty_script determines whether we have to create an empty script\n// 1. At startup, when the editor has to be (really) visible\n//    (Here we can not use the visibility changed signal)\n// 2. When the editor becomes visible when octave is running\nvoid\nfile_editor::empty_script (bool startup, bool visible)\n{\n\n  if (startup)\n    m_editor_ready = true;\n  else\n    {\n      if (! m_editor_ready)\n        return;  // not yet ready but got visibility changed signals\n    }\n\n  gui_settings settings;\n\n  if (settings.value (global_use_custom_editor.settings_key (),\n                      global_use_custom_editor.def ()).toBool ())\n    return;  // do not open an empty script in the external editor\n\n  bool real_visible;\n\n  if (startup)\n    real_visible = isVisible ();\n  else\n    real_visible = visible;\n\n  if (! real_visible || m_tab_widget->count () > 0)\n    return;\n\n  if (startup && ! isFloating ())\n    {\n      // check if editor is really visible or hidden between tabbed widgets\n      QWidget *parent = parentWidget ();\n\n      if (parent)\n        {\n          QList<QTabBar *> tab_list = parent->findChildren<QTabBar *>();\n\n          bool in_tab = false;\n          int i = 0;\n          while ((i < tab_list.count ()) && (! in_tab))\n            {\n              QTabBar *tab = tab_list.at (i);\n              i++;\n\n              int j = 0;\n              while ((j < tab->count ()) && (! in_tab))\n                {\n                  // check all tabs for the editor\n                  if (tab->tabText (j) == windowTitle ())\n                    {\n                      // editor is in this tab widget\n                      in_tab = true;\n                      int top = tab->currentIndex ();\n                      if (! (top > -1 && tab->tabText (top) == windowTitle ()))\n                        return; // not current tab -> not visible\n                    }\n                  j++;\n                }\n            }\n        }\n    }\n\n  request_new_file (\"\");\n}\n\nvoid\nfile_editor::restore_session (bool visible)\n{\n\n  if (! visible)\n    return;\n\n  gui_settings settings;\n\n  //restore previous session\n  if (! settings.bool_value (ed_restore_session))\n    return;\n\n  // get the data from the settings file\n  QStringList sessionFileNames\n    = settings.string_list_value (ed_session_names);\n\n  QStringList session_encodings\n    = settings.string_list_value (ed_session_enc);\n\n  QStringList session_index\n    = settings.string_list_value (ed_session_ind);\n\n  QStringList session_lines\n    = settings.string_list_value (ed_session_lines);\n\n  QStringList session_bookmarks\n    = settings.string_list_value (ed_session_bookmarks);\n\n  // fill a list of the struct and sort it (depending on index)\n  QList<session_data> s_data;\n\n  bool do_encoding = (session_encodings.count () == sessionFileNames.count ());\n  bool do_index = (session_index.count () == sessionFileNames.count ());\n  bool do_lines = (session_lines.count () == sessionFileNames.count ());\n  bool do_bookmarks = (session_bookmarks.count () == sessionFileNames.count ());\n\n  for (int n = 0; n < sessionFileNames.count (); ++n)\n    {\n      QFileInfo file = QFileInfo (sessionFileNames.at (n));\n      if (! file.exists ())\n        continue;\n\n      session_data item = { 0, -1, sessionFileNames.at (n),\n                            QString (), QString (), QString ()\n                          };\n      if (do_lines)\n        item.line = session_lines.at (n).toInt ();\n      if (do_index)\n        item.index = session_index.at (n).toInt ();\n      if (do_encoding)\n        item.encoding = session_encodings.at (n);\n      if (do_bookmarks)\n        item.bookmarks = session_bookmarks.at (n);\n\n      s_data << item;\n    }\n\n  std::sort (s_data.begin (), s_data.end ());\n\n  // finally open the files with the desired encoding in the desired order\n  for (int n = 0; n < s_data.count (); ++n)\n    request_open_file (s_data.at (n).file_name, s_data.at (n).encoding,\n                       s_data.at (n).line, false, false, true, \"\", -1,\n                       s_data.at (n).bookmarks);\n}\n\nvoid\nfile_editor::activate ()\n{\n  if (m_no_focus)\n    return;  // No focus for the editor if external open/close request\n\n  octave_dock_widget::activate ();\n\n  // set focus to current tab\n  reset_focus ();\n}\n\nvoid\nfile_editor::set_focus (QWidget *fet)\n{\n  setFocus ();\n\n  // set focus to desired tab\n  if (fet)\n    m_tab_widget->setCurrentWidget (fet);\n}\n\n// function enabling/disabling the menu accelerators depending on the\n// focus of the editor\nvoid\nfile_editor::enable_menu_shortcuts (bool enable)\n{\n  // Hide or show the find dialog together with the focus of the\n  // editor widget depending on the overall visibility of the find dialog.\n  // Do not change internal visibility state.\n  if (m_find_dialog)\n    m_find_dialog->set_visible (enable);\n\n  // Take care of the shortcuts\n  QHash<QMenu *, QStringList>::const_iterator i = m_hash_menu_text.constBegin ();\n\n  while (i != m_hash_menu_text.constEnd ())\n    {\n      i.key ()->setTitle (i.value ().at (! enable));\n      ++i;\n    }\n\n  // when editor loses focus, enable the actions, which are always active\n  // in the main window due to missing info on selected text and undo actions\n  if (m_copy_action && m_undo_action)\n    {\n      if (enable)\n        {\n          m_copy_action->setEnabled (m_copy_action_enabled);\n          m_undo_action->setEnabled (m_undo_action_enabled);\n        }\n      else\n        {\n          m_copy_action_enabled = m_copy_action->isEnabled ();\n          m_undo_action_enabled = m_undo_action->isEnabled ();\n          m_copy_action->setEnabled (true);\n          m_undo_action->setEnabled (true);\n        }\n    }\n}\n\n// Save open files for restoring in next session\n// (even if last session will not be restored next time)\n// together with encoding and the tab index\nvoid\nfile_editor::save_session ()\n{\n  gui_settings settings;\n\n  QStringList fetFileNames;\n  QStringList fet_encodings;\n  QStringList fet_index;\n  QStringList fet_lines;\n  QStringList fet_bookmarks;\n\n  std::list<file_editor_tab *> editor_tab_lst = m_tab_widget->tab_list ();\n\n  for (auto editor_tab : editor_tab_lst)\n    {\n      QString file_name = editor_tab->file_name ();\n\n      // Don't append unnamed files.\n\n      if (! file_name.isEmpty ())\n        {\n          fetFileNames.append (file_name);\n          fet_encodings.append (editor_tab->encoding ());\n\n          QString index;\n          fet_index.append (index.setNum (m_tab_widget->indexOf (editor_tab)));\n\n          int l, c;\n          editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c);\n          fet_lines.append (index.setNum (l + 1));\n\n          fet_bookmarks.append (editor_tab->get_all_bookmarks ());\n        }\n    }\n\n  settings.setValue (ed_session_names.settings_key (), fetFileNames);\n  settings.setValue (ed_session_enc.settings_key (), fet_encodings);\n  settings.setValue (ed_session_ind.settings_key (), fet_index);\n  settings.setValue (ed_session_lines.settings_key (), fet_lines);\n  settings.setValue (ed_session_bookmarks.settings_key (), fet_bookmarks);\n\n  settings.sync ();\n}\n\nbool\nfile_editor::check_closing ()\n{\n  // When the application or the editor is closing and the user wants to\n  // close all files, in the latter case all editor tabs are checked whether\n  // they need to be saved.  During these checks tabs are not closed since\n  // the user might cancel closing Octave during one of these saving dialogs.\n  // Therefore, saving the session for restoring at next start is not done\n  // before the application is definitely closing.\n\n  // Save the session.  Even is closing is cancelled, this would be\n  // overwritten by the next attempt to close the editor\n  save_session ();\n\n  std::list<file_editor_tab *> fe_tab_lst = m_tab_widget->tab_list ();\n  m_number_of_tabs = fe_tab_lst.size ();\n\n  for (auto fe_tab : fe_tab_lst)\n    {\n      // Wait for all editor tabs to have saved their files if required\n\n      connect (fe_tab, &file_editor_tab::tab_ready_to_close,\n               this, &file_editor::handle_tab_ready_to_close,\n               Qt::UniqueConnection);\n    }\n\n  m_closing_canceled = false;\n\n  for (auto fe_tab : fe_tab_lst)\n    {\n      // If there was a cancellation, make the already saved/discarded tabs\n      // recover from the exit by removing the read-only state and by\n      // recovering the debugger breakpoints.  Finally return false in order\n      // to cancel closing the application or the editor.\n\n      if (fe_tab->check_file_modified (false) == QMessageBox::Cancel)\n        {\n          Q_EMIT fetab_recover_from_exit ();\n\n          m_closing_canceled = true;\n\n          for (auto fet : fe_tab_lst)\n            disconnect (fet, &file_editor_tab::tab_ready_to_close, 0, 0);\n\n          return false;\n        }\n    }\n\n  return true;\n}\n\nvoid\nfile_editor::handle_tab_ready_to_close ()\n{\n  if (m_closing_canceled)\n    return;\n\n  // FIXME: Why count down to zero here before doing anything?  Why\n  // not remove and delete each tab that is ready to be closed, one\n  // per invocation?\n\n  m_number_of_tabs--;\n\n  if (m_number_of_tabs > 0)\n    return;\n\n  // Here, the application or the editor will be closed -> store the session\n\n  // Take care of the find dialog\n  if (m_find_dialog)\n    m_find_dialog->close ();\n\n  // Finally close all the tabs and return indication that we can exit\n  // the application or close the editor.\n  // Closing and deleting the tabs makes the editor visible.  In case it was\n  // hidden before, this state has to be restored afterwards.\n  bool vis = isVisible ();\n\n  std::list<file_editor_tab *> editor_tab_lst = m_tab_widget->tab_list ();\n  for (auto editor_tab : editor_tab_lst)\n    editor_tab->deleteLater ();\n\n  m_tab_widget->clear ();\n\n  setVisible (vis);\n}\n\nvoid\nfile_editor::request_new_file (const QString& commands)\n{\n  // Custom editor? If yes, we can only call the editor without passing\n  // some initial contents and even without being sure a new file is opened\n  if (call_custom_editor ())\n    return;\n\n  // New file isn't a file_editor_tab function since the file\n  // editor tab has yet to be created and there is no object to\n  // pass a signal to.  Hence, functionality is here.\n\n  file_editor_tab *fileEditorTab = make_file_editor_tab (m_ced);\n  add_file_editor_tab (fileEditorTab, \"\");  // new tab with empty title\n  fileEditorTab->new_file (commands);       // title is updated here\n  activate ();                              // focus editor and new tab\n}\n\nvoid\nfile_editor::request_close_file (bool)\n{\n  file_editor_tab *editor_tab\n    = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());\n  editor_tab->conditional_close ();\n}\n\nvoid\nfile_editor::request_close_all_files (bool)\n{\n  file_editor_tab *editor_tab;\n\n  // loop over all tabs starting from last one otherwise deletion changes index\n  for (int index = m_tab_widget->count ()-1; index >= 0; index--)\n    {\n      editor_tab = static_cast<file_editor_tab *> (m_tab_widget->widget (index));\n      editor_tab->conditional_close ();\n    }\n}\n\nvoid\nfile_editor::request_close_other_files (bool)\n{\n  file_editor_tab *editor_tab;\n  QWidget *tabID = m_tab_widget->currentWidget ();\n\n  // loop over all tabs starting from last one otherwise deletion changes index\n  for (int index = m_tab_widget->count ()-1; index >= 0; index--)\n    {\n      if (tabID != m_tab_widget->widget (index))\n        {\n          editor_tab\n            = static_cast<file_editor_tab *> (m_tab_widget->widget (index));\n          editor_tab->conditional_close ();\n        }\n    }\n}\n\nvoid\nfile_editor::copy_full_file_path (bool)\n{\n  file_editor_tab *editor_tab\n    = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());\n\n  if (editor_tab)\n    QGuiApplication::clipboard ()->setText (editor_tab->file_name ());\n}\n\n// open a file from the mru list\nvoid\nfile_editor::request_mru_open_file (QAction *action)\n{\n  if (action)\n    {\n      show ();  // Make sure, the editor is shown.  In case the previous\n                // session has to be restored, all previous files are\n                // opened before the selected file from the mru list is\n                // opened.\n      request_open_file (action->data ().toStringList ().at (0),\n                         action->data ().toStringList ().at (1));\n    }\n}\n\nvoid\nfile_editor::request_print_file (bool)\n{\n  Q_EMIT fetab_print_file (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_redo (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_REDO);\n}\n\nvoid\nfile_editor::request_cut (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_CUT);\n}\n\nvoid\nfile_editor::request_context_help (bool)\n{\n  Q_EMIT fetab_context_help (m_tab_widget->currentWidget (), false);\n}\n\nvoid\nfile_editor::request_context_doc (bool)\n{\n  Q_EMIT fetab_context_help (m_tab_widget->currentWidget (), true);\n}\n\nvoid\nfile_editor::request_context_edit (bool)\n{\n  Q_EMIT fetab_context_edit (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_save_file (bool)\n{\n  Q_EMIT fetab_save_file (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_save_file_as (bool)\n{\n  Q_EMIT fetab_save_file_as (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::run_file (bool, int opts)\n{\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<file_editor> this_fe (this);\n\n  Q_EMIT interpreter_event\n  ([this, this_fe, opts] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n\n    // If THIS_FE is no longer valid, skip the entire callback\n    // function.  With the way things are implemented now, we can't\n    // run the contents of a file unless the file editor and the\n    // corresponding file editor tab are still valid.\n\n    if (this_fe.isNull ())\n      return;\n\n    // Act as though this action was entered at the command propmt\n    // so that the interpreter will check for updated file time\n    // stamps.\n    Vlast_prompt_time.stamp ();\n\n    tree_evaluator& tw = interp.get_evaluator ();\n\n    if (tw.in_debug_repl ())\n      Q_EMIT request_dbcont_signal ();\n    else\n      Q_EMIT fetab_run_file (m_tab_widget->currentWidget (), opts);\n  });\n}\n\nvoid\nfile_editor::request_run_file (bool)\n{\n  run_file (true, ED_RUN_FILE);\n}\n\nvoid\nfile_editor::request_run_tests (bool)\n{\n  run_file (true, ED_RUN_TESTS);\n}\n\nvoid\nfile_editor::request_run_demos (bool)\n{\n  run_file (true, ED_RUN_DEMOS);\n}\n\nvoid\nfile_editor::request_step_into_file ()\n{\n  Q_EMIT fetab_run_file (m_tab_widget->currentWidget (), ED_STEP_INTO);\n}\n\nvoid\nfile_editor::request_context_run (bool)\n{\n  Q_EMIT fetab_context_run (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_toggle_bookmark (bool)\n{\n  Q_EMIT fetab_toggle_bookmark (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_next_bookmark (bool)\n{\n  Q_EMIT fetab_next_bookmark (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_previous_bookmark (bool)\n{\n  Q_EMIT fetab_previous_bookmark (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_remove_bookmark (bool)\n{\n  Q_EMIT fetab_remove_bookmark (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_move_match_brace (bool)\n{\n  Q_EMIT fetab_move_match_brace (m_tab_widget->currentWidget (), false);\n}\n\nvoid\nfile_editor::request_sel_match_brace (bool)\n{\n  Q_EMIT fetab_move_match_brace (m_tab_widget->currentWidget (), true);\n}\n\n// FIXME: What should this do with conditional breakpoints?\nvoid\nfile_editor::request_toggle_breakpoint (bool)\n{\n  Q_EMIT fetab_toggle_breakpoint (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_next_breakpoint (bool)\n{\n  Q_EMIT fetab_next_breakpoint (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_previous_breakpoint (bool)\n{\n  Q_EMIT fetab_previous_breakpoint (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_remove_breakpoint (bool)\n{\n  Q_EMIT fetab_remove_all_breakpoints (m_tab_widget->currentWidget ());\n}\n\n// slots for Edit->Commands actions\nvoid\nfile_editor::request_delete_start_word (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_DELWORDLEFT);\n}\n\nvoid\nfile_editor::request_delete_end_word (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_DELWORDRIGHT);\n}\n\nvoid\nfile_editor::request_delete_start_line (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_DELLINELEFT);\n}\n\nvoid\nfile_editor::request_delete_end_line (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_DELLINERIGHT);\n}\n\nvoid\nfile_editor::request_delete_line (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_LINEDELETE);\n}\n\nvoid\nfile_editor::request_copy_line (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_LINECOPY);\n}\n\nvoid\nfile_editor::request_cut_line (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_LINECUT);\n}\n\nvoid\nfile_editor::request_duplicate_selection (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_SELECTIONDUPLICATE);\n}\n\nvoid\nfile_editor::request_transpose_line (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_LINETRANSPOSE);\n}\n\nvoid\nfile_editor::request_comment_selected_text (bool)\n{\n  Q_EMIT fetab_comment_selected_text (m_tab_widget->currentWidget (), false);\n}\n\nvoid\nfile_editor::request_uncomment_selected_text (bool)\n{\n  Q_EMIT fetab_uncomment_selected_text (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_comment_var_selected_text (bool)\n{\n  Q_EMIT fetab_comment_selected_text (m_tab_widget->currentWidget (), true);\n}\n\n// slots for Edit->Format actions\nvoid\nfile_editor::request_upper_case (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_UPPERCASE);\n}\n\nvoid\nfile_editor::request_lower_case (bool)\n{\n  Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                  QsciScintillaBase::SCI_LOWERCASE);\n}\n\nvoid\nfile_editor::request_indent_selected_text (bool)\n{\n  Q_EMIT fetab_indent_selected_text (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_unindent_selected_text (bool)\n{\n  Q_EMIT fetab_unindent_selected_text (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_smart_indent_line_or_selected_text ()\n{\n  Q_EMIT fetab_smart_indent_line_or_selected_text (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_conv_eol_windows (bool)\n{\n  Q_EMIT fetab_convert_eol (m_tab_widget->currentWidget (),\n                            QsciScintilla::EolWindows);\n}\nvoid\nfile_editor::request_conv_eol_unix (bool)\n{\n  Q_EMIT fetab_convert_eol (m_tab_widget->currentWidget (),\n                            QsciScintilla::EolUnix);\n}\n\nvoid\nfile_editor::request_conv_eol_mac (bool)\n{\n  Q_EMIT fetab_convert_eol (m_tab_widget->currentWidget (),\n                            QsciScintilla::EolMac);\n}\n\n// Slot for initially creating and showing the find dialog\nvoid\nfile_editor::request_find (bool)\n{\n  // Create the dialog\n  find_create ();\n\n  // Since find_create shows the dialog without activating the widget\n  // (which is reuqired in other cases) do this manually here\n  m_find_dialog->activateWindow ();\n\n  // Initiate search text from possible selection and save the initial\n  // data from the dialog on the defined structure\n  m_find_dialog->init_search_text ();\n}\n\n// This method creates the find dialog.\n\nvoid\nfile_editor::find_create ()\n{\n  if (m_find_dialog)\n    m_find_dialog->close ();\n\n  if (isFloating ())\n    m_find_dialog = new find_dialog (this, this);\n  else\n    m_find_dialog = new find_dialog (this, parentWidget ());\n\n  // Add required actions\n  m_find_dialog->addAction (m_find_next_action);\n  m_find_dialog->addAction (m_find_previous_action);\n\n  // Update edit area\n  file_editor_tab *fet\n    = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());\n  m_find_dialog->update_edit_area (fet->qsci_edit_area ());\n\n  // Icon is the same as the editor\n  m_find_dialog->setWindowIcon (windowIcon ());\n\n  // Position: lower right of editor's position\n  int xp = x () + frameGeometry ().width ();\n  int yp = y () + frameGeometry ().height ();\n\n  if (! isFloating ())\n    {\n      // Fix position if editor is docked\n\n      QWidget *parent = parentWidget ();\n\n      if  (parent)\n        {\n          xp = xp + parent->x ();\n          yp = yp + parent->y ();\n        }\n    }\n\n  if (yp < 0)\n    yp = 0;\n\n  // The size of the find dialog is considered in restore_settings\n  // since its size might change depending on the options\n  m_find_dialog->restore_settings (QPoint (xp, yp));\n\n  // Set visible\n  m_find_dialog->set_visible (true);\n}\n\nvoid\nfile_editor::request_find_next (bool)\n{\n  if (m_find_dialog)\n    m_find_dialog->find_next ();\n}\n\nvoid\nfile_editor::request_find_previous (bool)\n{\n  if (m_find_dialog)\n    m_find_dialog->find_prev ();\n}\n\nvoid\nfile_editor::request_goto_line (bool)\n{\n  Q_EMIT fetab_goto_line (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::request_completion (bool)\n{\n  Q_EMIT fetab_completion (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::handle_file_name_changed (const QString& fname,\n                                       const QString& tip,\n                                       bool modified)\n{\n  QObject *fileEditorTab = sender ();\n  if (fileEditorTab)\n    {\n      gui_settings settings;\n\n      for (int i = 0; i < m_tab_widget->count (); i++)\n        {\n          if (m_tab_widget->widget (i) == fileEditorTab)\n            {\n              m_tab_widget->setTabText (i, fname);\n              m_tab_widget->setTabToolTip (i, tip);\n\n              m_save_action->setEnabled (modified);\n              m_current_tab_modified = modified;\n\n              if (modified)\n                m_tab_widget->setTabIcon (i, settings.icon (\"document-save\"));\n              else\n                m_tab_widget->setTabIcon (i, QIcon ());\n            }\n        }\n    }\n}\n\nvoid\nfile_editor::handle_close_file_request (const QStringList& files_to_close)\n{\n  for (int i = 0; i < files_to_close.length (); i++)\n    {\n      file_editor_tab *tab = find_tab_widget (files_to_close.at (i));\n      if (tab)\n        tab->conditional_close ();\n    }\n}\n\nvoid\nfile_editor::handle_tab_close_request (int index)\n{\n  file_editor_tab *editor_tab\n    = static_cast<file_editor_tab *> (m_tab_widget->widget (index));\n  editor_tab->conditional_close ();\n}\n\nvoid\nfile_editor::handle_tab_remove_request (const QString& file_name)\n{\n  QObject *fileEditorTab = sender ();\n  if (fileEditorTab)\n    {\n      for (int i = 0; i < m_tab_widget->count (); i++)\n        {\n          if (m_tab_widget->widget (i) == fileEditorTab)\n            {\n              m_tab_widget->removeTab (i);\n              Q_EMIT remove_editor_file_in_browser_signal (file_name);\n\n              // Deleting the sender (even with deleteLater) seems a\n              // bit strange.  Is there a better way?\n              fileEditorTab->deleteLater ();\n              break;\n            }\n        }\n    }\n  check_actions ();\n\n  activate ();     // focus stays in editor when tab is closed\n\n}\n\n// context menu of edit area\nvoid\nfile_editor::active_tab_changed (int index)\n{\n  Q_EMIT fetab_change_request (m_tab_widget->widget (index));\n  activate ();\n}\n\nvoid\nfile_editor::handle_editor_state_changed (bool copy_available,\n    bool is_octave_file,\n    bool is_modified)\n{\n  // In case there is some scenario where traffic could be coming from\n  // all the file editor tabs, just process info from the current active tab.\n  if (sender () == m_tab_widget->currentWidget ())\n    {\n      m_save_action->setEnabled (is_modified);\n      m_current_tab_modified = is_modified;\n\n      if (m_copy_action)\n        m_copy_action->setEnabled (copy_available);\n\n      m_cut_action->setEnabled (copy_available);\n\n      m_run_selection_action->setEnabled (copy_available);\n      m_run_action->setEnabled (is_octave_file);\n      m_is_octave_file = is_octave_file;\n\n      Q_EMIT editor_tabs_changed_signal (true, m_is_octave_file);\n    }\n\n  m_copy_action_enabled = m_copy_action->isEnabled ();\n  m_undo_action_enabled = m_undo_action->isEnabled ();\n}\n\nvoid\nfile_editor::handle_mru_add_file (const QString& file_name,\n                                  const QString& encoding)\n{\n  int index;\n  while ((index = m_mru_files.indexOf (file_name)) >= 0)\n    {\n      m_mru_files.removeAt (index);\n      m_mru_files_encodings.removeAt (index);\n    }\n\n  m_mru_files.prepend (file_name);\n  m_mru_files_encodings.prepend (encoding);\n\n  mru_menu_update ();\n}\n\nvoid\nfile_editor::check_conflict_save (const QString& saveFileName,\n                                  bool remove_on_success)\n{\n  // Check whether this file is already open in the editor.\n  file_editor_tab *tab = find_tab_widget (saveFileName);\n\n  if (tab)\n    {\n      // Note: to overwrite the contents of some other file editor tab\n      // with the same name requires identifying which file editor tab\n      // that is (not too difficult) then closing that tab.  Of course,\n      // that could trigger another dialog box if the file editor tab\n      // with the same name has modifications in it.  This could become\n      // somewhat confusing to the user.  For now, opt to do nothing.\n\n      // Create a NonModal message about error.\n      QMessageBox *msgBox\n        = new QMessageBox (QMessageBox::Critical, tr (\"Octave Editor\"),\n                           tr (\"File not saved! A file with the selected name\\n%1\\n\"\n                               \"is already open in the editor.\").\n                           arg (saveFileName),\n                           QMessageBox::Ok, nullptr);\n\n      msgBox->setWindowModality (Qt::NonModal);\n      msgBox->setAttribute (Qt::WA_DeleteOnClose);\n      msgBox->show ();\n      msgBox->raise ();\n\n      return;\n    }\n\n  QObject *saveFileObject = sender ();\n  QWidget *saveFileWidget = nullptr;\n\n  for (int i = 0; i < m_tab_widget->count (); i++)\n    {\n      if (m_tab_widget->widget (i) == saveFileObject)\n        {\n          saveFileWidget = m_tab_widget->widget (i);\n          break;\n        }\n    }\n  if (! saveFileWidget)\n    {\n      // Create a NonModal message about error.\n      QMessageBox *msgBox\n        = new QMessageBox (QMessageBox::Critical, tr (\"Octave Editor\"),\n                           tr (\"The associated file editor tab has disappeared.\"),\n                           QMessageBox::Ok, nullptr);\n\n      msgBox->setWindowModality (Qt::NonModal);\n      msgBox->setAttribute (Qt::WA_DeleteOnClose);\n      msgBox->show ();\n      msgBox->raise ();\n\n      return;\n    }\n\n  // Can save without conflict, have the file editor tab do so.\n  Q_EMIT fetab_save_file (saveFileWidget, saveFileName, remove_on_success);\n}\n\nvoid\nfile_editor::handle_insert_debugger_pointer_request (const QString& file,\n    int line)\n{\n  request_open_file (file, QString (), line, true); // default encoding\n}\n\nvoid\nfile_editor::handle_delete_debugger_pointer_request (const QString& file,\n    int line)\n{\n  if (! file.isEmpty ())\n    {\n      // Check whether this file is already open in the editor.\n      file_editor_tab *tab = find_tab_widget (file);\n\n      if (tab)\n        {\n          m_tab_widget->setCurrentWidget (tab);\n\n          if (line > 0)\n            Q_EMIT fetab_delete_debugger_pointer (tab, line);\n\n          Q_EMIT fetab_set_focus (tab);\n        }\n    }\n}\n\nvoid\nfile_editor::handle_update_breakpoint_marker_request (bool insert,\n    const QString& file,\n    int line,\n    const QString& cond)\n{\n  request_open_file (file, QString (), line, false, true, insert, cond);\n}\n\nvoid\nfile_editor::handle_edit_file_request (const QString& file)\n{\n  request_open_file (file);\n}\n\n// Slot used for signals indicating that a file was changed/renamed or\n// is going to be deleted/renamed\nvoid\nfile_editor::handle_file_remove (const QString& old_name,\n                                 const QString& new_name)\n{\n  // Clear old list of file data and declare a structure for file data\n  m_tmp_closed_files.clear ();\n  removed_file_data f_data;\n\n  // Preprocessing old name(s)\n  QString old_name_clean = old_name.trimmed ();\n  int s = old_name_clean.size ();\n\n  if (s > 1 && old_name_clean.at (0) == QChar ('\\\"')\n      && old_name_clean.at (s - 1) == QChar ('\\\"'))\n    old_name_clean = old_name_clean.mid (1, s - 2);\n\n  QStringList old_names = old_name_clean.split (\"\\\" \\\"\");\n\n  // Check if new name is a file or directory\n  QFileInfo newf (new_name);\n  bool new_is_dir = newf.isDir ();\n\n  // Now loop over all old files/dirs (several files by movefile ())\n  for (int i = 0; i < old_names.count (); i++)\n    {\n      // Check if old name is a file or directory\n      QFileInfo old (old_names.at (i));\n\n      if (old.isDir ())\n        {\n          // Call the function which handles directories and return\n          handle_dir_remove (old_names.at (i), new_name);\n        }\n      else\n        {\n          // It is a single file.  Is it open?\n          file_editor_tab *editor_tab = find_tab_widget (old_names.at (i));\n\n          if (editor_tab)\n            {\n\n              editor_tab->enable_file_watcher (false);\n\n              // For re-enabling tracking if error while removing/renaming\n              f_data.editor_tab = editor_tab;\n              // For renaming into new file (if new_file is not empty)\n              if (new_is_dir)\n                {\n                  std::string ndir = new_name.toStdString ();\n                  std::string ofile = old.fileName ().toStdString ();\n                  f_data.new_file_name\n                    = QString::fromStdString (sys::env::make_absolute (ofile, ndir));\n                }\n              else\n                f_data.new_file_name = new_name;\n\n              // Add file data to list\n              m_tmp_closed_files << f_data;\n            }\n        }\n    }\n}\n\n// Slot for signal indicating that a file was renamed\nvoid\nfile_editor::handle_file_renamed (bool load_new)\n{\n  m_no_focus = true;  // Remember for not focussing editor\n\n  // Loop over all files that have to be handled.  Start at the end of the\n  // list, otherwise the stored indexes are not correct.\n  for (int i = m_tmp_closed_files.count () - 1; i >= 0; i--)\n    {\n      if (load_new)\n        {\n          // Close file (remove) or rename into new file (rename)\n          if (m_tmp_closed_files.at (i).new_file_name.isEmpty ())\n            m_tmp_closed_files.at (i).editor_tab->file_has_changed (QString (), true);\n          else\n            m_tmp_closed_files.at (i).editor_tab->set_file_name (m_tmp_closed_files.at (i).new_file_name);\n        }\n      else\n        {\n          // Something went wrong while renaming or removing:\n          // Leave everything as it is but reactivate tracking\n          m_tmp_closed_files.at (i).editor_tab->enable_file_watcher (true);\n        }\n\n    }\n\n  m_no_focus = false;  // Back to normal focus\n\n  // Clear the list of file data\n  m_tmp_closed_files.clear ();\n}\n\nvoid\nfile_editor::notice_settings ()\n{\n  gui_settings settings;\n\n  int size_idx = settings.int_value (global_icon_size);\n  size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2\n\n  QStyle *st = style ();\n  int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);\n  m_tool_bar->setIconSize (QSize (icon_size, icon_size));\n\n  // Tab position and rotation\n  QTabWidget::TabPosition pos\n    = static_cast<QTabWidget::TabPosition> (settings.int_value (ed_tab_position));\n  bool rotated = settings.bool_value (ed_tabs_rotated);\n\n  m_tab_widget->setTabPosition (pos);\n\n  if (rotated)\n    m_tab_widget->setTabsClosable (false);  // No close buttons\n                                            // FIXME: close buttons can not be correctly placed in rotated tabs\n\n  // Get the tab bar and set the rotation\n  int rotation = rotated;\n  if (pos == QTabWidget::West)\n    rotation = -rotation;\n\n  tab_bar *bar = m_tab_widget->get_tab_bar ();\n  bar->set_rotated (rotation);\n\n  // Get suitable height of a tab related to font and icon size\n  int height = 1.5* QFontMetrics (m_tab_widget->font ()).height ();\n  int is = 1.5*m_tab_widget->iconSize ().height ();\n  if (is > height)\n    height = is;\n\n  // Calculate possibly limited width and set the elide mode\n  int chars = settings.int_value (ed_tabs_max_width);\n  int width = 9999;\n  if (chars > 0)\n    width = chars * QFontMetrics (m_tab_widget->font ()).averageCharWidth ();\n\n  // Get tab bar size properties for style sheet depending on rotation\n  QString width_str (\"width\");\n  QString height_str (\"height\");\n  if ((pos == QTabWidget::West) || (pos == QTabWidget::East))\n    {\n      width_str = QString (\"height\");\n      height_str = QString (\"width\");\n    }\n\n  QString style_sheet\n    = QString (\"QTabBar::tab {max-\" + height_str + \": %1px;\\n\"\n               \"max-\" + width_str + \": %2px; }\")\n      .arg (height).arg (width);\n\n#if defined (Q_OS_MAC)\n  // FIXME: This is a workaround for missing tab close buttons on MacOS\n  // in several Qt versions (https://bugreports.qt.io/browse/QTBUG-61092)\n  if (! rotated)\n    {\n      QString icon = global_icon_paths.at (ICON_THEME_OCTAVE)\n                     + \"widget-close\" + global_icon_extension;\n\n      QString close_button_css_mac\n      (\"QTabBar::close-button\"\n       \" { image: url(\" + icon + \");\"\n       \" padding: 4px;\"\n       \"   subcontrol-position: bottom; }\\n\"\n       \"QTabBar::close-button:hover\"\n       \"  { background-color: #cccccc; }\");\n\n      style_sheet = style_sheet + close_button_css_mac;\n    }\n#endif\n\n  m_tab_widget->setStyleSheet (style_sheet);\n\n  bool show_it;\n  show_it = settings.bool_value (ed_show_line_numbers);\n  m_show_linenum_action->setChecked (show_it);\n  show_it = settings.bool_value (ed_show_white_space);\n  m_show_whitespace_action->setChecked (show_it);\n  show_it = settings.bool_value (ed_show_eol_chars);\n  m_show_eol_action->setChecked (show_it);\n  show_it = settings.bool_value (ed_show_indent_guides);\n  m_show_indguide_action->setChecked (show_it);\n  show_it = settings.bool_value (ed_long_line_marker);\n  m_show_longline_action->setChecked (show_it);\n\n  show_it = settings.bool_value (ed_show_toolbar);\n  m_show_toolbar_action->setChecked (show_it);\n  m_tool_bar->setVisible (show_it);\n  show_it = settings.bool_value (ed_show_edit_status_bar);\n  m_show_statusbar_action->setChecked (show_it);\n  show_it = settings.bool_value (ed_show_hscroll_bar);\n  m_show_hscrollbar_action->setChecked (show_it);\n\n  set_shortcuts ();\n\n  // Find dialog with the same icon as the editor\n  if (m_find_dialog)\n    m_find_dialog->setWindowIcon (windowIcon ());\n\n  // Relay signal to file editor tabs.\n  Q_EMIT fetab_settings_changed ();\n}\n\nvoid\nfile_editor::set_shortcuts ()\n{\n  // Shortcuts also available in the main window, as well as the related\n  // shortcuts, are defined in main_window and added to the editor\n\n  gui_settings settings;\n\n  // File menu\n  settings.set_shortcut (m_edit_function_action, sc_edit_file_edit_function);\n  settings.set_shortcut (m_save_action, sc_edit_file_save);\n  settings.set_shortcut (m_save_as_action, sc_edit_file_save_as);\n  settings.set_shortcut (m_close_action, sc_edit_file_close);\n  settings.set_shortcut (m_close_all_action, sc_edit_file_close_all);\n  settings.set_shortcut (m_close_others_action, sc_edit_file_close_other);\n  settings.set_shortcut (m_print_action, sc_edit_file_print);\n\n  // Edit menu\n  settings.set_shortcut (m_redo_action, sc_edit_edit_redo);\n  settings.set_shortcut (m_cut_action, sc_edit_edit_cut);\n  settings.set_shortcut (m_find_action, sc_edit_edit_find_replace);\n  settings.set_shortcut (m_find_next_action, sc_edit_edit_find_next);\n  settings.set_shortcut (m_find_previous_action, sc_edit_edit_find_previous);\n\n  settings.set_shortcut (m_delete_start_word_action, sc_edit_edit_delete_start_word);\n  settings.set_shortcut (m_delete_end_word_action, sc_edit_edit_delete_end_word);\n  settings.set_shortcut (m_delete_start_line_action, sc_edit_edit_delete_start_line);\n  settings.set_shortcut (m_delete_end_line_action, sc_edit_edit_delete_end_line);\n  settings.set_shortcut (m_delete_line_action, sc_edit_edit_delete_line);\n  settings.set_shortcut (m_copy_line_action, sc_edit_edit_copy_line);\n  settings.set_shortcut (m_cut_line_action, sc_edit_edit_cut_line);\n  settings.set_shortcut (m_duplicate_selection_action, sc_edit_edit_duplicate_selection);\n  settings.set_shortcut (m_transpose_line_action, sc_edit_edit_transpose_line);\n  settings.set_shortcut (m_comment_selection_action, sc_edit_edit_comment_selection);\n  settings.set_shortcut (m_uncomment_selection_action, sc_edit_edit_uncomment_selection);\n  settings.set_shortcut (m_comment_var_selection_action, sc_edit_edit_comment_var_selection);\n\n  settings.set_shortcut (m_upper_case_action, sc_edit_edit_upper_case);\n  settings.set_shortcut (m_lower_case_action, sc_edit_edit_lower_case);\n  settings.set_shortcut (m_indent_selection_action, sc_edit_edit_indent_selection);\n  settings.set_shortcut (m_unindent_selection_action, sc_edit_edit_unindent_selection);\n  settings.set_shortcut (m_smart_indent_line_or_selection_action, sc_edit_edit_smart_indent_line_or_selection);\n  settings.set_shortcut (m_completion_action, sc_edit_edit_completion_list);\n  settings.set_shortcut (m_goto_line_action, sc_edit_edit_goto_line);\n  settings.set_shortcut (m_move_to_matching_brace, sc_edit_edit_move_to_brace);\n  settings.set_shortcut (m_sel_to_matching_brace, sc_edit_edit_select_to_brace);\n  settings.set_shortcut (m_toggle_bookmark_action, sc_edit_edit_toggle_bookmark);\n  settings.set_shortcut (m_next_bookmark_action, sc_edit_edit_next_bookmark);\n  settings.set_shortcut (m_previous_bookmark_action, sc_edit_edit_previous_bookmark);\n  settings.set_shortcut (m_remove_bookmark_action, sc_edit_edit_remove_bookmark);\n  settings.set_shortcut (m_preferences_action, sc_edit_edit_preferences);\n  settings.set_shortcut (m_styles_preferences_action, sc_edit_edit_styles_preferences);\n\n  settings.set_shortcut (m_conv_eol_windows_action, sc_edit_edit_conv_eol_winows);\n  settings.set_shortcut (m_conv_eol_unix_action,    sc_edit_edit_conv_eol_unix);\n  settings.set_shortcut (m_conv_eol_mac_action,     sc_edit_edit_conv_eol_mac);\n\n  // View menu\n  settings.set_shortcut (m_show_linenum_action, sc_edit_view_show_line_numbers);\n  settings.set_shortcut (m_show_whitespace_action, sc_edit_view_show_white_spaces);\n  settings.set_shortcut (m_show_eol_action, sc_edit_view_show_eol_chars);\n  settings.set_shortcut (m_show_indguide_action, sc_edit_view_show_ind_guides);\n  settings.set_shortcut (m_show_longline_action, sc_edit_view_show_long_line);\n  settings.set_shortcut (m_show_toolbar_action, sc_edit_view_show_toolbar);\n  settings.set_shortcut (m_show_statusbar_action, sc_edit_view_show_statusbar);\n  settings.set_shortcut (m_show_hscrollbar_action, sc_edit_view_show_hscrollbar);\n  settings.set_shortcut (m_zoom_in_action, sc_edit_view_zoom_in);\n  settings.set_shortcut (m_zoom_out_action, sc_edit_view_zoom_out);\n  settings.set_shortcut (m_zoom_normal_action, sc_edit_view_zoom_normal);\n  settings.set_shortcut (m_sort_tabs_action, sc_edit_view_sort_tabs);\n\n  // Debug menu\n  settings.set_shortcut (m_toggle_breakpoint_action, sc_edit_debug_toggle_breakpoint);\n  settings.set_shortcut (m_next_breakpoint_action, sc_edit_debug_next_breakpoint);\n  settings.set_shortcut (m_previous_breakpoint_action, sc_edit_debug_previous_breakpoint);\n  settings.set_shortcut (m_remove_all_breakpoints_action, sc_edit_debug_remove_breakpoints);\n\n  // Run menu\n  settings.set_shortcut (m_run_action, sc_edit_run_run_file);\n  settings.set_shortcut (m_run_selection_action, sc_edit_run_run_selection);\n  settings.set_shortcut (m_run_tests_action, sc_edit_run_run_tests);\n  settings.set_shortcut (m_run_demos_action, sc_edit_run_run_demos);\n\n  // Help menu\n  settings.set_shortcut (m_context_help_action, sc_edit_help_help_keyword);\n  settings.set_shortcut (m_context_doc_action,  sc_edit_help_doc_keyword);\n\n  // Tab navigation (no menu, but allows for creation of shortcuts)\n  settings.set_shortcut (m_switch_left_tab_action, sc_edit_tabs_switch_left_tab);\n  settings.set_shortcut (m_switch_right_tab_action, sc_edit_tabs_switch_right_tab);\n  settings.set_shortcut (m_move_tab_left_action, sc_edit_tabs_move_tab_left);\n  settings.set_shortcut (m_move_tab_right_action, sc_edit_tabs_move_tab_right);\n}\n\n// This slot is a reimplementation of the virtual slot in octave_dock_widget.\n// We need this for creating an empty script when the editor has no open\n// files and is made visible.\nvoid\nfile_editor::handle_visibility (bool visible)\n{\n  octave_dock_widget::handle_visibility (visible);\n\n  if (! m_editor_ready)\n    return;\n\n  if (m_closed && visible)\n    {\n      m_closed = false;\n\n      restore_session (visible);\n    }\n\n  empty_script (false, visible);\n}\n\n// This slot is a reimplementation of the virtual slot in octave_dock_widget.\n// We need this for updating the parent of the find dialog\nvoid\nfile_editor::toplevel_change (bool toplevel)\n{\n  if (m_find_dialog)\n    {\n      // close current dialog\n      m_find_dialog->close ();\n\n      // re-create dialog with the new parent (editor or main-win)\n      find_create ();\n      m_find_dialog->activateWindow ();\n    }\n\n  octave_dock_widget::toplevel_change (toplevel);\n}\n\nvoid\nfile_editor::update_octave_directory (const QString& dir)\n{\n  m_ced = dir;\n  Q_EMIT fetab_set_directory (m_ced);  // for save dialog\n}\n\nvoid\nfile_editor::copyClipboard ()\n{\n  if (editor_tab_has_focus ())\n    Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                    QsciScintillaBase::SCI_COPY);\n}\n\nvoid\nfile_editor::pasteClipboard ()\n{\n  if (editor_tab_has_focus ())\n    Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                    QsciScintillaBase::SCI_PASTE);\n}\n\nvoid\nfile_editor::selectAll ()\n{\n  if (editor_tab_has_focus ())\n    Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                    QsciScintillaBase::SCI_SELECTALL);\n}\n\nvoid\nfile_editor::do_undo ()\n{\n  if (editor_tab_has_focus ())\n    Q_EMIT fetab_scintilla_command (m_tab_widget->currentWidget (),\n                                    QsciScintillaBase::SCI_UNDO);\n}\n\n// Open a file, if not already open, and mark the current execution location\n// and/or a breakpoint with condition cond.\nvoid\nfile_editor::request_open_file (const QString& openFileName,\n                                const QString& encoding,\n                                int line, bool debug_pointer,\n                                bool breakpoint_marker, bool insert,\n                                const QString& cond, int index,\n                                const QString& bookmarks,\n                                const find_files_data& ff_data)\n{\n  gui_settings settings;\n\n  if (settings.bool_value (global_use_custom_editor))\n    {\n      // Custom editor\n      if (debug_pointer || breakpoint_marker)\n        return;   // Do not call custom editor during debugging\n\n      if (call_custom_editor (openFileName, line))\n        return;   // Custom editor called\n    }\n\n  bool show_dbg_file = settings.bool_value (ed_show_dbg_file);\n\n  if (openFileName.isEmpty ())\n    {\n      // This happens if edit is called without an argument\n      // Open editor with empty edit area instead (as new file would do)\n      request_new_file (\"\");\n    }\n  else\n    {\n      // Check whether this file is already open in the editor.\n      file_editor_tab *fileEditorTab = find_tab_widget (openFileName);\n\n      if (fileEditorTab)\n        {\n          // File is already open\n\n          m_tab_widget->setCurrentWidget (fileEditorTab);\n\n          if (line > 0)\n            {\n              if (insert)\n                Q_EMIT fetab_goto_line (fileEditorTab, line);\n\n              if (debug_pointer)\n                Q_EMIT fetab_insert_debugger_pointer (fileEditorTab, line);\n\n              if (breakpoint_marker)\n                Q_EMIT fetab_do_breakpoint_marker (insert, fileEditorTab, line, cond);\n            }\n\n          if (show_dbg_file && ! ((breakpoint_marker || debug_pointer)\n                                  && is_editor_console_tabbed ()))\n            {\n              Q_EMIT fetab_set_focus (fileEditorTab);\n              activate ();\n            }\n        }\n      else\n        {\n          // File not yet open\n\n          if (! show_dbg_file && (breakpoint_marker || debug_pointer))\n            return;   // Do not open a file for showing dbg markers\n\n          if (breakpoint_marker && ! insert)\n            return;   // Never open a file when removing breakpoints\n\n          if ((breakpoint_marker || debug_pointer)\n              && (openFileName == settings.string_value (ed_run_selection_tmp_file)))\n            return;   // Never open tmp file when debugging while running selection\n\n          // Reuse <unnamed> tab if it hasn't yet been modified.\n          bool reusing = false;\n          file_editor_tab *tab = find_tab_widget (\"\");\n          if (tab)\n            {\n              fileEditorTab = tab;\n              if (fileEditorTab->qsci_edit_area ()->isModified ())\n                fileEditorTab = nullptr;\n              else\n                reusing = true;\n            }\n\n          // If <unnamed> was absent or modified, create a new tab.\n          if (! fileEditorTab)\n            fileEditorTab = make_file_editor_tab ();\n\n          fileEditorTab->set_encoding (encoding);\n          QString result = fileEditorTab->load_file (openFileName);\n          if (result == \"\")\n            {\n              // Supply empty title then have the file_editor_tab update\n              // with full or short name.\n              if (! reusing)\n                add_file_editor_tab (fileEditorTab, \"\", index);\n              fileEditorTab->update_window_title (false);\n              // file already loaded, add file to mru list here\n              QFileInfo file_info = QFileInfo (openFileName);\n              handle_mru_add_file (file_info.canonicalFilePath (),\n                                   encoding);\n\n              if (line > 0)\n                {\n                  if (insert)\n                    Q_EMIT fetab_goto_line (fileEditorTab, line);\n\n                  if (debug_pointer)\n                    Q_EMIT fetab_insert_debugger_pointer (fileEditorTab,\n                                                          line);\n                  if (breakpoint_marker)\n                    Q_EMIT fetab_do_breakpoint_marker (insert, fileEditorTab,\n                                                       line, cond);\n                }\n            }\n          else\n            {\n              if (! reusing)\n                {\n                  delete fileEditorTab;\n                  fileEditorTab = nullptr;\n                }\n\n              if (QFile::exists (openFileName))\n                {\n                  // File not readable:\n                  // create a NonModal message about error.\n                  QMessageBox *msgBox\n                    = new QMessageBox (QMessageBox::Critical,\n                                       tr (\"Octave Editor\"),\n                                       tr (\"Could not open file\\n%1\\nfor reading: %2.\").\n                                       arg (openFileName).arg (result),\n                                       QMessageBox::Ok, this);\n\n                  msgBox->setWindowModality (Qt::NonModal);\n                  msgBox->setAttribute (Qt::WA_DeleteOnClose);\n                  msgBox->show ();\n                }\n              else\n                {\n                  // File does not exist, should it be created?\n                  bool create_file = true;\n                  QMessageBox *msgBox;\n\n                  if (! settings.bool_value (ed_create_new_file))\n                    {\n                      msgBox = new QMessageBox (QMessageBox::Question,\n                                                tr (\"Octave Editor\"),\n                                                tr (\"File\\n%1\\ndoes not exist. \"\n                                                    \"Do you want to create it?\").arg (openFileName),\n                                                QMessageBox::NoButton, nullptr);\n                      QPushButton *create_button =\n                        msgBox->addButton (tr (\"Create\"), QMessageBox::YesRole);\n                      msgBox->addButton (tr (\"Cancel\"), QMessageBox::RejectRole);\n                      msgBox->setDefaultButton (create_button);\n                      msgBox->exec ();\n\n                      QAbstractButton *clicked_button = msgBox->clickedButton ();\n                      if (clicked_button != create_button)\n                        create_file = false;\n\n                      delete msgBox;\n                    }\n\n                  if (create_file)\n                    {\n                      // create the file and call the editor again\n                      QFile file (openFileName);\n                      if (! file.open (QIODevice::WriteOnly))\n                        {\n                          // error opening the file\n                          msgBox = new QMessageBox (QMessageBox::Critical,\n                                                    tr (\"Octave Editor\"),\n                                                    tr (\"Could not open file\\n%1\\nfor writing: %2.\").\n                                                    arg (openFileName).arg (file.errorString ()),\n                                                    QMessageBox::Ok, this);\n\n                          msgBox->setWindowModality (Qt::NonModal);\n                          msgBox->setAttribute (Qt::WA_DeleteOnClose);\n                          msgBox->show ();\n                          msgBox->raise ();\n                        }\n                      else\n                        {\n                          file.close ();\n                          request_open_file (openFileName);\n                        }\n                    }\n                }\n            }\n\n          if (! bookmarks.isEmpty ())\n            {\n              // Restore bookmarks\n              for (const auto& bms : bookmarks.split (','))\n                {\n                  int bm = bms.toInt ();\n                  if (fileEditorTab)\n                    fileEditorTab->qsci_edit_area ()->markerAdd (bm, marker::bookmark);\n                }\n            }\n\n          if (! ((breakpoint_marker || debug_pointer) && is_editor_console_tabbed ()))\n            {\n              // update breakpoint pointers, really show editor\n              // and the current editor tab\n              if (fileEditorTab)\n                fileEditorTab->update_breakpoints ();\n              activate ();\n              Q_EMIT file_loaded_signal ();\n            }\n\n        }  // if/else file already open\n\n        if (ff_data.find_in_files)\n          {\n            fileEditorTab->select_all_occurrences (ff_data, true);\n          }\n\n    }  // if/else openFileName empty\n}\n\nvoid\nfile_editor::request_preferences (bool)\n{\n  Q_EMIT request_settings_dialog (\"editor\");\n}\n\nvoid\nfile_editor::request_styles_preferences (bool)\n{\n  Q_EMIT request_settings_dialog (\"editor_styles\");\n}\n\nvoid\nfile_editor::show_line_numbers (bool)\n{\n  toggle_preference (ed_show_line_numbers);\n}\n\nvoid\nfile_editor::show_white_space (bool)\n{\n  toggle_preference (ed_show_white_space);\n}\n\nvoid\nfile_editor::show_eol_chars (bool)\n{\n  toggle_preference (ed_show_eol_chars);\n}\n\nvoid\nfile_editor::show_indent_guides (bool)\n{\n  toggle_preference (ed_show_indent_guides);\n}\n\nvoid\nfile_editor::show_long_line (bool)\n{\n  toggle_preference (ed_long_line_marker);\n}\n\nvoid\nfile_editor::show_toolbar (bool)\n{\n  toggle_preference (ed_show_toolbar);\n}\n\nvoid\nfile_editor::show_statusbar (bool)\n{\n  toggle_preference (ed_show_edit_status_bar);\n}\n\nvoid\nfile_editor::show_hscrollbar (bool)\n{\n  toggle_preference (ed_show_hscroll_bar);\n}\n\nvoid\nfile_editor::zoom_in (bool)\n{\n  Q_EMIT fetab_zoom_in (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::zoom_out (bool)\n{\n  Q_EMIT fetab_zoom_out (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::zoom_normal (bool)\n{\n  Q_EMIT fetab_zoom_normal (m_tab_widget->currentWidget ());\n}\n\nvoid\nfile_editor::create_context_menu (QMenu *menu)\n{\n  // remove all standard actions from scintilla\n  QList<QAction *> all_actions = menu->actions ();\n\n  for (auto *a : all_actions)\n    menu->removeAction (a);\n\n  // add editor's actions with icons and customized shortcuts\n  menu->addAction (m_cut_action);\n  menu->addAction (m_copy_action);\n  menu->addAction (m_paste_action);\n  menu->addSeparator ();\n  menu->addAction (m_selectall_action);\n  menu->addSeparator ();\n  menu->addAction (m_find_files_action);\n  menu->addAction (m_find_action);\n  menu->addAction (m_find_next_action);\n  menu->addAction (m_find_previous_action);\n  menu->addSeparator ();\n  menu->addMenu (m_edit_cmd_menu);\n  menu->addMenu (m_edit_fmt_menu);\n  menu->addMenu (m_edit_nav_menu);\n  menu->addSeparator ();\n  menu->addAction (m_run_selection_action);\n}\n\nvoid\nfile_editor::edit_status_update (bool undo, bool redo)\n{\n  if (m_undo_action)\n    m_undo_action->setEnabled (undo);\n  m_redo_action->setEnabled (redo);\n}\n\n// handler for the close event\nvoid\nfile_editor::closeEvent (QCloseEvent *e)\n{\n  gui_settings settings;\n\n  if (settings.bool_value (ed_hiding_closes_files))\n    {\n      if (check_closing ())\n        {\n          // All tabs are closed without cancelling,\n          // store closing state for restoring session when shown again.\n          // Editor is closing when session data is stored in preferences\n          m_closed = true;\n          e->ignore ();\n        }\n      else\n        {\n          e->ignore ();\n          return;\n        }\n    }\n  else\n    e->accept ();\n\n  octave_dock_widget::closeEvent (e);\n}\n\nvoid\nfile_editor::dragEnterEvent (QDragEnterEvent *e)\n{\n  if (e->mimeData ()->hasUrls ())\n    {\n      e->acceptProposedAction ();\n    }\n}\n\nvoid\nfile_editor::dropEvent (QDropEvent *e)\n{\n  if (e->mimeData ()->hasUrls ())\n    {\n      for (const auto& url : e->mimeData ()->urls ())\n        request_open_file (url.toLocalFile ());\n    }\n}\n\nbool\nfile_editor::is_editor_console_tabbed ()\n{\n  // FIXME: is there a way to do this job that doesn't require casting\n  // the parent to a main_window object?\n\n  main_window *w = dynamic_cast<main_window *> (parentWidget ());\n\n  if (w)\n    {\n      QList<QDockWidget *> w_list = w->tabifiedDockWidgets (this);\n      QDockWidget *console =\n        static_cast<QDockWidget *> (w->get_dock_widget_list ().at (0));\n\n      for (int i = 0; i < w_list.count (); i++)\n        {\n          if (w_list.at (i) == console)\n            return true;\n        }\n    }\n\n  return false;\n}\n\nvoid\nfile_editor::construct ()\n{\n  QWidget *editor_widget = new QWidget (this);\n\n  // FIXME: what was the intended purpose of this unused variable?\n  // QStyle *editor_style = QApplication::style ();\n\n  // Menu bar: do not set it native, required in macOS and Ubuntu Unity (Qt5)\n  // for a visible menu bar in the editor widget.  This property is ignored\n  // on other platforms.\n  m_menu_bar = new QMenuBar (editor_widget);\n  m_menu_bar->setNativeMenuBar (false);\n\n  m_tool_bar = new QToolBar (editor_widget);\n  m_tool_bar->setMovable (true);\n\n  m_tab_widget = new file_editor_tab_widget (editor_widget, this);\n\n  // the mru-list and an empty array of actions\n\n  gui_settings settings;\n\n  m_mru_files = settings.string_list_value (ed_mru_file_list);\n  m_mru_files_encodings = settings.string_list_value (ed_mru_file_encodings);\n\n  if (m_mru_files_encodings.count () != m_mru_files.count ())\n    {\n      // encodings don't have the same count -> do not use them!\n      m_mru_files_encodings = QStringList ();\n      for (int i = 0; i < m_mru_files.count (); i++)\n        m_mru_files_encodings << QString ();\n    }\n\n  for (int i = 0; i < MaxMRUFiles; ++i)\n    {\n      m_mru_file_actions[i] = new QAction (this);\n      m_mru_file_actions[i]->setVisible (false);\n    }\n\n  // menu bar\n\n  // file menu\n\n  m_fileMenu = add_menu (m_menu_bar, tr (\"&File\"));\n\n  // new and open menus are inserted later by the main window\n  m_mru_file_menu = new QMenu (tr (\"&Recent Editor Files\"), m_fileMenu);\n  for (int i = 0; i < MaxMRUFiles; ++i)\n    m_mru_file_menu->addAction (m_mru_file_actions[i]);\n  m_fileMenu->addMenu (m_mru_file_menu);\n\n  m_fileMenu->addSeparator ();\n\n  m_edit_function_action\n    = add_action (m_fileMenu,\n                  tr (\"&Edit Function\"),\n                  SLOT (request_context_edit (bool)));\n\n  m_fileMenu->addSeparator ();\n\n  m_save_action\n    = add_action (m_fileMenu, settings.icon (\"document-save\"),\n                  tr (\"&Save File\"), SLOT (request_save_file (bool)));\n\n  m_save_as_action\n    = add_action (m_fileMenu, settings.icon (\"document-save-as\"),\n                  tr (\"Save File &As...\"),\n                  SLOT (request_save_file_as (bool)));\n\n  m_fileMenu->addSeparator ();\n\n  m_close_action\n    = add_action (m_fileMenu, settings.icon (\"window-close\", false),\n                  tr (\"&Close\"), SLOT (request_close_file (bool)));\n\n  m_close_all_action\n    = add_action (m_fileMenu, settings.icon (\"window-close\", false),\n                  tr (\"Close All\"), SLOT (request_close_all_files (bool)));\n\n  m_close_others_action\n    = add_action (m_fileMenu, settings.icon (\"window-close\", false),\n                  tr (\"Close Other Files\"),\n                  SLOT (request_close_other_files (bool)));\n\n  m_fileMenu->addSeparator ();\n\n  m_print_action\n    = add_action (m_fileMenu, settings.icon (\"document-print\"),\n                  tr (\"Print...\"), SLOT (request_print_file (bool)));\n\n  // edit menu (undo, copy, paste and select all later via main window)\n\n  m_edit_menu = add_menu (m_menu_bar, tr (\"&Edit\"));\n\n  m_redo_action\n    = add_action (m_edit_menu, settings.icon (\"edit-redo\"),\n                  tr (\"&Redo\"), SLOT (request_redo (bool)));\n  m_redo_action->setEnabled (false);\n\n  m_edit_menu->addSeparator ();\n\n  m_cut_action\n    = add_action (m_edit_menu, settings.icon (\"edit-cut\"),\n                  tr (\"Cu&t\"), SLOT (request_cut (bool)));\n  m_cut_action->setEnabled (false);\n\n  m_find_action\n    = add_action (m_edit_menu, settings.icon (\"edit-find-replace\"),\n                  tr (\"&Find and Replace...\"), SLOT (request_find (bool)));\n\n  m_find_next_action\n    = add_action (m_edit_menu, tr (\"Find &Next\"),\n                  SLOT (request_find_next (bool)));\n\n  m_find_previous_action\n    = add_action (m_edit_menu, tr (\"Find &Previous\"),\n                  SLOT (request_find_previous (bool)));\n\n  m_edit_menu->addSeparator ();\n\n  m_edit_cmd_menu = m_edit_menu->addMenu (tr (\"&Commands\"));\n\n  m_delete_line_action\n    = add_action (m_edit_cmd_menu, tr (\"Delete Line\"),\n                  SLOT (request_delete_line (bool)));\n\n  m_copy_line_action\n    = add_action (m_edit_cmd_menu, tr (\"Copy Line\"),\n                  SLOT (request_copy_line (bool)));\n\n  m_cut_line_action\n    = add_action (m_edit_cmd_menu, tr (\"Cut Line\"),\n                  SLOT (request_cut_line (bool)));\n\n  m_edit_cmd_menu->addSeparator ();\n\n  m_delete_start_word_action\n    = add_action (m_edit_cmd_menu, tr (\"Delete to Start of Word\"),\n                  SLOT (request_delete_start_word (bool)));\n\n  m_delete_end_word_action\n    = add_action (m_edit_cmd_menu, tr (\"Delete to End of Word\"),\n                  SLOT (request_delete_end_word (bool)));\n\n  m_delete_start_line_action\n    = add_action (m_edit_cmd_menu, tr (\"Delete to Start of Line\"),\n                  SLOT (request_delete_start_line (bool)));\n\n  m_delete_end_line_action\n    = add_action (m_edit_cmd_menu, tr (\"Delete to End of Line\"),\n                  SLOT (request_delete_end_line (bool)));\n\n  m_edit_cmd_menu->addSeparator ();\n\n  m_duplicate_selection_action\n    = add_action (m_edit_cmd_menu, tr (\"Duplicate Selection/Line\"),\n                  SLOT (request_duplicate_selection (bool)));\n\n  m_transpose_line_action\n    = add_action (m_edit_cmd_menu, tr (\"Transpose Line\"),\n                  SLOT (request_transpose_line (bool)));\n\n  m_edit_cmd_menu->addSeparator ();\n\n  m_completion_action\n    = add_action (m_edit_cmd_menu, tr (\"&Show Completion List\"),\n                  SLOT (request_completion (bool)));\n\n  m_edit_fmt_menu = m_edit_menu->addMenu (tr (\"&Format\"));\n\n  m_upper_case_action\n    = add_action (m_edit_fmt_menu, tr (\"&Uppercase Selection\"),\n                  SLOT (request_upper_case (bool)));\n\n  m_lower_case_action\n    = add_action (m_edit_fmt_menu, tr (\"&Lowercase Selection\"),\n                  SLOT (request_lower_case (bool)));\n\n  m_edit_fmt_menu->addSeparator ();\n\n  m_comment_selection_action\n    = add_action (m_edit_fmt_menu, tr (\"&Comment\"),\n                  SLOT (request_comment_selected_text (bool)));\n\n  m_uncomment_selection_action\n    = add_action (m_edit_fmt_menu, tr (\"&Uncomment\"),\n                  SLOT (request_uncomment_selected_text (bool)));\n\n  m_comment_var_selection_action\n    = add_action (m_edit_fmt_menu, tr (\"Comment (Choosing String)\"),\n                  SLOT (request_comment_var_selected_text (bool)));\n\n  m_edit_fmt_menu->addSeparator ();\n\n  m_indent_selection_action\n    = add_action (m_edit_fmt_menu, tr (\"&Indent Selection Rigidly\"),\n                  SLOT (request_indent_selected_text (bool)));\n\n  m_unindent_selection_action\n    = add_action (m_edit_fmt_menu, tr (\"&Unindent Selection Rigidly\"),\n                  SLOT (request_unindent_selected_text (bool)));\n\n  m_smart_indent_line_or_selection_action\n    = add_action (m_edit_fmt_menu, tr (\"Indent Code\"),\n                  SLOT (request_smart_indent_line_or_selected_text ()));\n\n  m_edit_fmt_menu->addSeparator ();\n\n  m_conv_eol_windows_action\n    = add_action (m_edit_fmt_menu,\n                  tr (\"Convert Line Endings to &Windows (CRLF)\"),\n                  SLOT (request_conv_eol_windows (bool)));\n\n  m_conv_eol_unix_action\n    = add_action (m_edit_fmt_menu, tr (\"Convert Line Endings to &Unix (LF)\"),\n                  SLOT (request_conv_eol_unix (bool)));\n\n  m_conv_eol_mac_action\n    = add_action (m_edit_fmt_menu,\n                  tr (\"Convert Line Endings to Legacy &Mac (CR)\"),\n                  SLOT (request_conv_eol_mac (bool)));\n\n  m_edit_nav_menu = m_edit_menu->addMenu (tr (\"Navi&gation\"));\n\n  m_goto_line_action\n    = add_action (m_edit_nav_menu, tr (\"Go &to Line...\"),\n                  SLOT (request_goto_line (bool)));\n\n  m_edit_cmd_menu->addSeparator ();\n\n  m_move_to_matching_brace\n    = add_action (m_edit_nav_menu, tr (\"Move to Matching Brace\"),\n                  SLOT (request_move_match_brace (bool)));\n\n  m_sel_to_matching_brace\n    = add_action (m_edit_nav_menu, tr (\"Select to Matching Brace\"),\n                  SLOT (request_sel_match_brace (bool)));\n\n  m_edit_nav_menu->addSeparator ();\n\n  m_next_bookmark_action\n    = add_action (m_edit_nav_menu, tr (\"&Next Bookmark\"),\n                  SLOT (request_next_bookmark (bool)));\n\n  m_previous_bookmark_action\n    = add_action (m_edit_nav_menu, tr (\"Pre&vious Bookmark\"),\n                  SLOT (request_previous_bookmark (bool)));\n\n  m_toggle_bookmark_action\n    = add_action (m_edit_nav_menu, tr (\"Toggle &Bookmark\"),\n                  SLOT (request_toggle_bookmark (bool)));\n\n  m_remove_bookmark_action\n    = add_action (m_edit_nav_menu, tr (\"&Remove All Bookmarks\"),\n                  SLOT (request_remove_bookmark (bool)));\n\n  m_edit_menu->addSeparator ();\n\n  m_preferences_action\n    = add_action (m_edit_menu, settings.icon (\"preferences-system\"),\n                  tr (\"&Preferences...\"),\n                  SLOT (request_preferences (bool)));\n\n  m_styles_preferences_action\n    = add_action (m_edit_menu, settings.icon (\"preferences-system\"),\n                  tr (\"&Styles Preferences...\"),\n                  SLOT (request_styles_preferences (bool)));\n\n  // view menu\n\n  QMenu *view_menu = add_menu (m_menu_bar, tr (\"&View\"));\n\n  m_view_editor_menu = view_menu->addMenu (tr (\"&Editor\"));\n\n  m_show_linenum_action\n    = add_action (m_view_editor_menu, tr (\"Show &Line Numbers\"),\n                  SLOT (show_line_numbers (bool)));\n  m_show_linenum_action->setCheckable (true);\n\n  m_show_whitespace_action\n    = add_action (m_view_editor_menu, tr (\"Show &Whitespace Characters\"),\n                  SLOT (show_white_space (bool)));\n  m_show_whitespace_action->setCheckable (true);\n\n  m_show_eol_action\n    = add_action (m_view_editor_menu, tr (\"Show Line &Endings\"),\n                  SLOT (show_eol_chars (bool)));\n  m_show_eol_action->setCheckable (true);\n\n  m_show_indguide_action\n    = add_action (m_view_editor_menu, tr (\"Show &Indentation Guides\"),\n                  SLOT (show_indent_guides (bool)));\n  m_show_indguide_action->setCheckable (true);\n\n  m_show_longline_action\n    = add_action (m_view_editor_menu, tr (\"Show Long Line &Marker\"),\n                  SLOT (show_long_line (bool)));\n  m_show_longline_action->setCheckable (true);\n\n  m_view_editor_menu->addSeparator ();\n\n  m_show_toolbar_action\n    = add_action (m_view_editor_menu, tr (\"Show &Toolbar\"),\n                  SLOT (show_toolbar (bool)));\n  m_show_toolbar_action->setCheckable (true);\n\n  m_show_statusbar_action\n    = add_action (m_view_editor_menu, tr (\"Show &Statusbar\"),\n                  SLOT (show_statusbar (bool)));\n  m_show_statusbar_action->setCheckable (true);\n\n  m_show_hscrollbar_action\n    = add_action (m_view_editor_menu, tr (\"Show &Horizontal Scrollbar\"),\n                  SLOT (show_hscrollbar (bool)));\n  m_show_hscrollbar_action->setCheckable (true);\n\n  view_menu->addSeparator ();\n\n  m_zoom_in_action\n    = add_action (view_menu, settings.icon (\"view-zoom-in\"), tr (\"Zoom &In\"),\n                  SLOT (zoom_in (bool)));\n\n  m_zoom_out_action\n    = add_action (view_menu, settings.icon (\"view-zoom-out\"),\n                  tr (\"Zoom &Out\"), SLOT (zoom_out (bool)));\n\n  m_zoom_normal_action\n    = add_action (view_menu, settings.icon (\"view-zoom-original\"),\n                  tr (\"&Normal Size\"), SLOT (zoom_normal (bool)));\n\n  view_menu->addSeparator ();\n\n  m_sort_tabs_action\n    = add_action (view_menu, tr (\"&Sort Tabs Alphabetically\"),\n                  SLOT (sort_tabs_alph ()),\n                  m_tab_widget->get_tab_bar ());\n\n  m_menu_bar->addMenu (view_menu);\n\n  // debug menu\n\n  m_debug_menu = add_menu (m_menu_bar, tr (\"&Debug\"));\n\n  m_toggle_breakpoint_action\n    = add_action (m_debug_menu, settings.icon (\"bp-toggle\"),\n                  tr (\"Toggle &Breakpoint\"),\n                  SLOT (request_toggle_breakpoint (bool)));\n\n  m_next_breakpoint_action\n    = add_action (m_debug_menu, settings.icon (\"bp-next\"),\n                  tr (\"&Next Breakpoint\"),\n                  SLOT (request_next_breakpoint (bool)));\n\n  m_previous_breakpoint_action\n    = add_action (m_debug_menu, settings.icon (\"bp-prev\"),\n                  tr (\"Pre&vious Breakpoint\"),\n                  SLOT (request_previous_breakpoint (bool)));\n\n  m_remove_all_breakpoints_action\n    = add_action (m_debug_menu, settings.icon (\"bp-rm-all\"),\n                  tr (\"&Remove All Breakpoints\"),\n                  SLOT (request_remove_breakpoint (bool)));\n\n  m_debug_menu->addSeparator ();\n\n  // The other debug actions will be added by the main window.\n\n  // run menu\n\n  QMenu *_run_menu = add_menu (m_menu_bar, tr (\"&Run\"));\n\n  m_run_action\n    = add_action (_run_menu,\n                  settings.icon (\"system-run\"),\n                  tr (\"Save File and Run/Continue\"),\n                  SLOT (request_run_file (bool)));\n\n  m_run_selection_action\n    = add_action (_run_menu,\n                  tr (\"Run &Selection\"),\n                  SLOT (request_context_run (bool)));\n  m_run_selection_action->setEnabled (false);\n\n  m_run_tests_action\n    = add_action (_run_menu,\n                  tr (\"Save File and Run All &Tests\"),\n                  SLOT (request_run_tests (bool)));\n\n  m_run_demos_action\n    = add_action (_run_menu,\n                  tr (\"Save File and Run All &Demos\"),\n                  SLOT (request_run_demos (bool)));\n\n  // help menu\n\n  QMenu *_help_menu = add_menu (m_menu_bar, tr (\"&Help\"));\n\n  m_context_help_action\n    = add_action (_help_menu,\n                  tr (\"&Help on Keyword\"),\n                  SLOT (request_context_help (bool)));\n\n  m_context_doc_action\n    = add_action (_help_menu,\n                  tr (\"&Documentation on Keyword\"),\n                  SLOT (request_context_doc (bool)));\n\n  // tab navigation (no menu, only actions; slots in tab_bar)\n\n  m_switch_left_tab_action\n    = add_action (nullptr, \"\", SLOT (switch_left_tab ()),\n                  m_tab_widget->get_tab_bar ());\n\n  m_switch_right_tab_action\n    = add_action (nullptr, \"\", SLOT (switch_right_tab ()),\n                  m_tab_widget->get_tab_bar ());\n\n  m_move_tab_left_action\n    = add_action (nullptr, \"\", SLOT (move_tab_left ()),\n                  m_tab_widget->get_tab_bar ());\n\n  m_move_tab_right_action\n    = add_action (nullptr, \"\", SLOT (move_tab_right ()),\n                  m_tab_widget->get_tab_bar ());\n\n  // toolbar\n\n  // popdown menu with mru files\n  QToolButton *popdown_button = new QToolButton ();\n  popdown_button->setToolTip (tr (\"Recent Files\"));\n  popdown_button->setMenu (m_mru_file_menu);\n  popdown_button->setPopupMode (QToolButton::InstantPopup);\n  popdown_button->setArrowType (Qt::DownArrow);\n  popdown_button->setToolButtonStyle (Qt::ToolButtonTextOnly);\n\n  // new and open actions are inserted later from main window\n  m_popdown_mru_action = m_tool_bar->addWidget (popdown_button);\n  m_tool_bar->addAction (m_save_action);\n  m_tool_bar->addAction (m_save_as_action);\n  m_tool_bar->addAction (m_print_action);\n  m_tool_bar->addSeparator ();\n  // m_undo_action: later via main window\n  m_tool_bar->addAction (m_redo_action);\n  m_tool_bar->addSeparator ();\n  m_tool_bar->addAction (m_cut_action);\n  // m_copy_action: later via the main window\n  // m_paste_action: later via the main window\n  m_tool_bar->addAction (m_find_action);\n  //m_tool_bar->addAction (m_find_next_action);\n  //m_tool_bar->addAction (m_find_previous_action);\n  m_tool_bar->addSeparator ();\n  m_tool_bar->addAction (m_run_action);\n  m_tool_bar->addSeparator ();\n  m_tool_bar->addAction (m_toggle_breakpoint_action);\n  m_tool_bar->addAction (m_previous_breakpoint_action);\n  m_tool_bar->addAction (m_next_breakpoint_action);\n  m_tool_bar->addAction (m_remove_all_breakpoints_action);\n\n  // layout\n  QVBoxLayout *vbox_layout = new QVBoxLayout ();\n  vbox_layout->addWidget (m_menu_bar);\n  vbox_layout->addWidget (m_tool_bar);\n  vbox_layout->addWidget (m_tab_widget);\n  vbox_layout->setContentsMargins (0, 0, 0, 0);\n  vbox_layout->setSpacing (0);\n  editor_widget->setLayout (vbox_layout);\n  setWidget (editor_widget);\n\n  // Create the basic context menu of the tab bar with editor actions.\n  // Actions for selecting an tab are added when the menu is activated.\n  tab_bar *bar = m_tab_widget->get_tab_bar ();\n  QMenu *ctx_men = bar->get_context_menu ();\n  ctx_men->addSeparator ();\n  ctx_men->addAction (m_close_action);\n  ctx_men->addAction (m_close_all_action);\n  ctx_men->addAction (m_close_others_action);\n  ctx_men->addSeparator ();\n  ctx_men->addAction (m_sort_tabs_action);\n  add_action (ctx_men, tr (\"Copy Full File &Path\"),\n              SLOT (copy_full_file_path (bool)), this);\n\n  // signals\n  connect (m_mru_file_menu, &QMenu::triggered,\n           this, &file_editor::request_mru_open_file);\n\n  mru_menu_update ();\n\n  connect (m_tab_widget, &file_editor_tab_widget::tabCloseRequested,\n           this, &file_editor::handle_tab_close_request);\n\n  connect (m_tab_widget, &file_editor_tab_widget::currentChanged,\n           this, &file_editor::active_tab_changed);\n\n  resize (500, 400);\n  set_title (tr (\"Editor\"));\n\n  check_actions ();\n}\n\n// Slot when autocompletion list was cancelled\nvoid\nfile_editor::handle_autoc_cancelled ()\n{\n  // List was cancelled but somehow still active and blocking the\n  // edit area from accepting shortcuts.  Only after another keypress\n  // shortcuts and lists are working againnas expected.  This is\n  // probably caused by qt bug https://bugreports.qt.io/browse/QTBUG-83720\n  // Hack: Accept the list, which is hidden but still active\n  //       and undo the text insertion, if any\n\n  file_editor_tab *f = reset_focus ();\n  octave_qscintilla *qsci = f->qsci_edit_area ();\n\n  int line, col;\n  qsci->getCursorPosition (&line, &col);\n  int l1 = qsci->lineLength (line); // Current line length\n\n  // Accept autocompletion\n  qsci->SendScintilla (QsciScintillaBase::SCI_AUTOCCOMPLETE);\n\n  // Was text inserted? If yes, undo\n  if (qsci->text (line).length () - l1)\n    qsci->undo ();\n}\n\nfile_editor_tab *\nfile_editor::reset_focus ()\n{\n  // Reset the focus of the tab and the related edit area\n  file_editor_tab *f\n    = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());\n  Q_EMIT fetab_set_focus (f);\n  return f;\n}\n\nfile_editor_tab *\nfile_editor::make_file_editor_tab (const QString& directory)\n{\n  file_editor_tab *f = new file_editor_tab (directory);\n\n  // signals from the qscintilla edit area\n  connect (f->qsci_edit_area (), &octave_qscintilla::show_symbol_tooltip_signal,\n           this, &file_editor::show_symbol_tooltip_signal);\n\n  connect (f->qsci_edit_area (), &octave_qscintilla::status_update,\n           this, &file_editor::edit_status_update);\n\n  connect (f->qsci_edit_area (), &octave_qscintilla::create_context_menu_signal,\n           this, &file_editor::create_context_menu);\n\n  connect (f->qsci_edit_area (),\n           SIGNAL (SCN_AUTOCCOMPLETED (const char *, int, int, int)),\n           this, SLOT (reset_focus ()));\n\n  connect (f->qsci_edit_area (), SIGNAL (SCN_AUTOCCANCELLED ()),\n           this, SLOT (handle_autoc_cancelled ()));\n\n  // signals from the qscintilla edit area\n  connect (this, &file_editor::enter_debug_mode_signal,\n           f->qsci_edit_area (), &octave_qscintilla::handle_enter_debug_mode);\n\n  connect (this, &file_editor::exit_debug_mode_signal,\n           f->qsci_edit_area (), &octave_qscintilla::handle_exit_debug_mode);\n\n  // Signals from the file editor_tab\n  connect (f, &file_editor_tab::autoc_closed,\n           this, &file_editor::reset_focus);\n\n  connect (f, &file_editor_tab::file_name_changed,\n           this, &file_editor::handle_file_name_changed);\n\n  connect (f, &file_editor_tab::editor_state_changed,\n           this, &file_editor::handle_editor_state_changed);\n\n  connect (f, &file_editor_tab::tab_remove_request,\n           this, &file_editor::handle_tab_remove_request);\n\n  connect (f, &file_editor_tab::editor_check_conflict_save,\n           this, &file_editor::check_conflict_save);\n\n  connect (f, &file_editor_tab::mru_add_file,\n           this, &file_editor::handle_mru_add_file);\n\n  connect (f, &file_editor_tab::request_open_file,\n  this, [this] (const QString& fname, const QString& encoding) { request_open_file (fname, encoding); });\n\n  connect (f, &file_editor_tab::edit_area_changed,\n           this, &file_editor::edit_area_changed);\n\n  connect (f, &file_editor_tab::set_focus_editor_signal,\n           this, &file_editor::set_focus);\n\n  // Signals from the file_editor or main-win non-trivial operations\n  connect (this, &file_editor::fetab_settings_changed,\n  f, [f] () { f->notice_settings (); });\n\n  connect (this, &file_editor::fetab_change_request,\n           f, &file_editor_tab::change_editor_state);\n\n  connect (this, qOverload<const QWidget *, const QString&, bool> (&file_editor::fetab_save_file),\n           f, qOverload<const QWidget *, const QString&, bool> (&file_editor_tab::save_file));\n\n  // Signals from the file_editor trivial operations\n  connect (this, &file_editor::fetab_recover_from_exit,\n           f, &file_editor_tab::recover_from_exit);\n\n  connect (this, &file_editor::fetab_set_directory,\n           f, &file_editor_tab::set_current_directory);\n\n  connect (this, &file_editor::fetab_zoom_in,\n           f, &file_editor_tab::zoom_in);\n  connect (this, &file_editor::fetab_zoom_out,\n           f, &file_editor_tab::zoom_out);\n  connect (this, &file_editor::fetab_zoom_normal,\n           f, &file_editor_tab::zoom_normal);\n\n  connect (this, &file_editor::fetab_context_help,\n           f, &file_editor_tab::context_help);\n\n  connect (this, &file_editor::fetab_context_edit,\n           f, &file_editor_tab::context_edit);\n\n  connect (this, qOverload<const QWidget *> (&file_editor::fetab_save_file),\n           f, qOverload<const QWidget *> (&file_editor_tab::save_file));\n\n  connect (this, &file_editor::fetab_save_file_as,\n           f, qOverload<const QWidget *> (&file_editor_tab::save_file_as));\n\n  connect (this, &file_editor::fetab_print_file,\n           f, &file_editor_tab::print_file);\n\n  connect (this, &file_editor::fetab_run_file,\n           f, &file_editor_tab::run_file);\n\n  connect (this, &file_editor::fetab_context_run,\n           f, &file_editor_tab::context_run);\n\n  connect (this, &file_editor::fetab_toggle_bookmark,\n           f, &file_editor_tab::toggle_bookmark);\n\n  connect (this, &file_editor::fetab_next_bookmark,\n           f, &file_editor_tab::next_bookmark);\n\n  connect (this, &file_editor::fetab_previous_bookmark,\n           f, &file_editor_tab::previous_bookmark);\n\n  connect (this, &file_editor::fetab_remove_bookmark,\n           f, &file_editor_tab::remove_bookmark);\n\n  connect (this, &file_editor::fetab_toggle_breakpoint,\n           f, &file_editor_tab::toggle_breakpoint);\n\n  connect (this, &file_editor::fetab_next_breakpoint,\n           f, &file_editor_tab::next_breakpoint);\n\n  connect (this, &file_editor::fetab_previous_breakpoint,\n           f, &file_editor_tab::previous_breakpoint);\n\n  connect (this, &file_editor::fetab_remove_all_breakpoints,\n           f, &file_editor_tab::remove_all_breakpoints);\n\n  connect (this, &file_editor::fetab_scintilla_command,\n           f, &file_editor_tab::scintilla_command);\n\n  connect (this, &file_editor::fetab_comment_selected_text,\n           f, &file_editor_tab::comment_selected_text);\n\n  connect (this, &file_editor::fetab_uncomment_selected_text,\n           f, &file_editor_tab::uncomment_selected_text);\n\n  connect (this, &file_editor::fetab_indent_selected_text,\n           f, &file_editor_tab::indent_selected_text);\n\n  connect (this, &file_editor::fetab_unindent_selected_text,\n           f, &file_editor_tab::unindent_selected_text);\n\n  connect (this, &file_editor::fetab_smart_indent_line_or_selected_text,\n           f, &file_editor_tab::smart_indent_line_or_selected_text);\n\n  connect (this, &file_editor::fetab_convert_eol,\n           f, &file_editor_tab::convert_eol);\n\n  connect (this, &file_editor::fetab_goto_line,\n           f, &file_editor_tab::goto_line);\n\n  connect (this, &file_editor::fetab_move_match_brace,\n           f, &file_editor_tab::move_match_brace);\n\n  connect (this, &file_editor::fetab_completion,\n           f, &file_editor_tab::show_auto_completion);\n\n  connect (this, &file_editor::fetab_set_focus,\n           f, &file_editor_tab::set_focus);\n\n  connect (this, &file_editor::fetab_insert_debugger_pointer,\n           f, &file_editor_tab::insert_debugger_pointer);\n\n  connect (this, &file_editor::fetab_delete_debugger_pointer,\n           f, &file_editor_tab::delete_debugger_pointer);\n\n  connect (this, &file_editor::fetab_do_breakpoint_marker,\n           f, &file_editor_tab::do_breakpoint_marker);\n\n  connect (this, &file_editor::update_gui_lexer_signal,\n           f, &file_editor_tab::update_lexer_settings);\n\n  // Convert other signals from the edit area and tab to editor signals.\n\n  connect (f->qsci_edit_area (), &octave_qscintilla::execute_command_in_terminal_signal,\n           this, &file_editor::execute_command_in_terminal_signal);\n\n  connect (f->qsci_edit_area (), &octave_qscintilla::focus_console_after_command_signal,\n           this, &file_editor::focus_console_after_command_signal);\n\n  connect (f, &file_editor_tab::run_file_signal,\n           this, &file_editor::run_file_signal);\n\n  connect (f, &file_editor_tab::edit_mfile_request,\n           this, &file_editor::edit_mfile_request);\n\n  connect (f, &file_editor_tab::debug_quit_signal,\n           this, &file_editor::debug_quit_signal);\n\n  connect (f, &file_editor_tab::rename_editor_file_in_browser_signal,\n           this, &file_editor::rename_editor_file_in_browser_signal);\n\n  // Any interpreter_event signal from a file_editor_tab_widget is\n  // handled the same as for the parent main_window object.\n\n  connect (f, qOverload<const fcn_callback&> (&file_editor_tab::interpreter_event),\n           this, qOverload<const fcn_callback&> (&file_editor::interpreter_event));\n\n  connect (f, qOverload<const meth_callback&> (&file_editor_tab::interpreter_event),\n           this, qOverload<const meth_callback&> (&file_editor::interpreter_event));\n\n  return f;\n}\n\nvoid\nfile_editor::add_file_editor_tab (file_editor_tab *f, const QString& fn,\n                                  int index)\n{\n  if (index == -1)\n    m_tab_widget->addTab (f, fn);\n  else\n    m_tab_widget->insertTab (index, f, fn);\n\n  m_tab_widget->setCurrentWidget (f);\n\n  check_actions ();\n}\n\nvoid\nfile_editor::mru_menu_update ()\n{\n  int num_files = qMin (m_mru_files.size (), int (MaxMRUFiles));\n\n  // configure and show active actions of mru-menu\n  for (int i = 0; i < num_files; ++i)\n    {\n      QString text = QString (\"&%1 %2\").\n                     arg ((i+1) % int (MaxMRUFiles)).arg (m_mru_files.at (i));\n      m_mru_file_actions[i]->setText (text);\n\n      QStringList action_data;\n      action_data << m_mru_files.at (i) << m_mru_files_encodings.at (i);\n      m_mru_file_actions[i]->setData (action_data);\n\n      m_mru_file_actions[i]->setVisible (true);\n    }\n\n  // hide unused mru-menu entries\n  for (int j = num_files; j < MaxMRUFiles; ++j)\n    m_mru_file_actions[j]->setVisible (false);\n\n  // delete entries in string-list beyond MaxMRUFiles\n  while (m_mru_files.size () > MaxMRUFiles)\n    {\n      m_mru_files.removeLast ();\n      m_mru_files_encodings.removeLast ();\n    }\n\n  // save actual mru-list in settings\n\n  gui_settings settings;\n\n  settings.setValue (ed_mru_file_list.settings_key (), m_mru_files);\n  settings.setValue (ed_mru_file_encodings.settings_key (), m_mru_files_encodings);\n\n  settings.sync ();\n}\n\nbool\nfile_editor::call_custom_editor (const QString& file_name, int line)\n{\n  // Check if the user wants to use a custom file editor.\n\n  gui_settings settings;\n\n  if (settings.value (global_use_custom_editor.settings_key (),\n                      global_use_custom_editor.def ()).toBool ())\n    {\n      // use the external editor interface for handling the call\n      Q_EMIT request_open_file_external (file_name, line);\n\n      if (line < 0 && ! file_name.isEmpty ())\n        handle_mru_add_file (QFileInfo (file_name).canonicalFilePath (),\n                             QString ());\n\n      return true;\n    }\n\n  return false;\n}\n\nvoid\nfile_editor::toggle_preference (const gui_pref& preference)\n{\n  gui_settings settings;\n\n  bool old = settings.bool_value (preference);\n  settings.setValue (preference.settings_key (), ! old);\n  notice_settings ();\n}\n\n// Function for closing the files in a removed directory\nvoid\nfile_editor::handle_dir_remove (const QString& old_name,\n                                const QString& new_name)\n{\n  QDir old_dir (old_name);\n  removed_file_data f_data;\n\n  std::list<file_editor_tab *> editor_tab_lst = m_tab_widget->tab_list ();\n\n  for (auto editor_tab : editor_tab_lst)\n    {\n      QString file_name = editor_tab->file_name ();\n\n      if (file_name.isEmpty ())\n        continue;   // Nothing to do, no valid file name\n\n      // Get abs. file path and its path relative to the removed directory\n      QString rel_path_to_file = old_dir.relativeFilePath (file_name);\n      QString abs_path_to_file = old_dir.absoluteFilePath (file_name);\n\n      // Test whether the file is located within the directory that will\n      // be removed.  For this, two conditions must be met:\n      // 1. The path of the file rel. to the dir is not equal to the\n      //    its absolute one.\n      //    If both are equal, then there is no relative path and removed\n      //    directory and file are on different drives (e.g., on windows)\n      // 2. The (real) relative path does not start with \"../\", i.e.,\n      //    the file can be reached from the directory by descending only\n      if ((rel_path_to_file != abs_path_to_file)\n          && (rel_path_to_file.left (3) != QString (\"../\")))\n        {\n          // The currently considered file is included in the\n          // removed/renamed diectory: remeber it\n          if (editor_tab)\n            {\n              editor_tab->enable_file_watcher (false);\n              f_data.editor_tab = editor_tab;\n\n              // Add the new file path and the encoding for later reloading\n              // if new_name is given\n              if (! new_name.isEmpty ())\n                {\n                  QDir new_dir (new_name);\n                  QString append_to_new_dir;\n                  if (new_dir.exists ())\n                    {\n                      // The new directory already exists (movefile was used).\n                      // This means, we have to add the name (not the path)\n                      // of the old dir and the relative path to the file\n                      // to new dir.\n                      append_to_new_dir\n                        = old_dir.dirName () + \"/\" + rel_path_to_file;\n                    }\n                  else\n                    append_to_new_dir = rel_path_to_file;\n\n                  f_data.new_file_name\n                    = new_dir.absoluteFilePath (append_to_new_dir);\n                }\n              else\n                f_data.new_file_name = \"\"; // no new name, just removing this file\n\n              // Store data in list for later reloading\n              m_tmp_closed_files << f_data;\n            }\n        }\n    }\n}\n\nbool\nfile_editor::editor_tab_has_focus ()\n{\n  QWidget *foc_w = focusWidget ();\n  if (foc_w && foc_w->inherits (\"octave::octave_qscintilla\"))\n    return true;\n  return false;\n}\n\n// Check whether this file is already open in the editor.\nfile_editor_tab *\nfile_editor::find_tab_widget (const QString& file)\n{\n  std::string std_file = file.toStdString ();\n\n  std::list<file_editor_tab *> fe_tab_lst = m_tab_widget->tab_list ();\n\n  for (auto fe_tab : fe_tab_lst)\n    {\n      QString tab_file = fe_tab->file_name ();\n\n      // We check file == tab_file because\n      //\n      //   same_file (\"\", \"\")\n      //\n      // is false\n\n      if (sys::same_file (std_file, tab_file.toStdString ())\n          || file == tab_file)\n        return fe_tab;\n    }\n\n  return nullptr;\n}\n\nQAction *\nfile_editor::add_action (QMenu *menu, const QString& text,\n                         const char *member,\n                         QWidget *receiver)\n{\n  return add_action (menu, QIcon (), text, member, receiver);\n}\n\nQAction *\nfile_editor::add_action (QMenu *menu, const QIcon& icon,\n                         const QString& text, const char *member,\n                         QWidget *receiver)\n{\n  QAction *a;\n  QWidget *r = this;\n\n  if (receiver != nullptr)\n    r = receiver;\n\n  if (menu)\n    a = menu->addAction (icon, text, r, member);\n  else\n    {\n      a = new QAction (this);\n      connect (a, SIGNAL (triggered ()), r, member);\n    }\n\n  addAction (a);  // important for shortcut context\n  a->setShortcutContext (Qt::WidgetWithChildrenShortcut);\n\n  return a;\n}\n\nQMenu *\nfile_editor::add_menu (QMenuBar *p, QString name)\n{\n  QMenu *menu = p->addMenu (name);\n\n  QString base_name = name;  // get a copy\n                             // replace intended '&' (\"&&\") by a temp. string\n  base_name.replace (\"&&\", \"___octave_amp_replacement___\");\n  // remove single '&' (shortcut)\n  base_name.remove (\"&\");\n  // restore intended '&'\n  base_name.replace (\"___octave_amp_replacement___\", \"&&\");\n\n  // remember names with and without shortcut\n  m_hash_menu_text[menu] = QStringList () << name << base_name;\n\n  return menu;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/file-editor.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_file_editor_h)\n#define octave_file_editor_h 1\n\n#include <list>\n#include <map>\n\n#include <QAction>\n#include <QCloseEvent>\n#include <QDragEnterEvent>\n#include <QDropEvent>\n#include <QMenuBar>\n#include <QStackedWidget>\n#include <QStatusBar>\n#include <QTabWidget>\n#include <QToolBar>\n\n#include \"file-editor-interface.h\"\n#include \"file-editor-tab.h\"\n#include \"find-dialog.h\"\n#include \"tab-bar.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_qobject;\nclass file_editor;\n\n// subclassed QTabWidget for using custom tabbar\n\nclass file_editor_tab_widget : public QTabWidget\n{\n  Q_OBJECT\n\npublic:\n\n  file_editor_tab_widget (QWidget *p, file_editor *fe);\n\n  ~file_editor_tab_widget () = default;\n\n  tab_bar * get_tab_bar () const;\n\n  std::list<file_editor_tab *> tab_list () const;\n};\n\n// the class for the file editor\n\nclass file_editor : public file_editor_interface\n{\n  Q_OBJECT\n\npublic:\n\n  // struct that allows to sort with respect to the tab index\n  struct session_data\n  {\n    int index;\n    int line;\n    QString file_name;\n    QString new_file_name;\n    QString encoding;\n    QString bookmarks;\n\n    bool operator < (const session_data& other) const\n    {\n      return index < other.index;\n    }\n  };\n\n  struct removed_file_data\n  {\n    file_editor_tab *editor_tab;\n    QString new_file_name;\n  };\n\n  file_editor (QWidget *p);\n\n  ~file_editor () = default;\n\n  QMenu * get_mru_menu () { return m_mru_file_menu; }\n\n  QMenu * debug_menu () { return m_debug_menu; }\n\n  QToolBar * toolbar () { return m_tool_bar; }\n\n  QMenuBar * menubar () { return m_menu_bar; }\n\n  void insert_global_actions (QList<QAction *>);\n\n  enum shared_actions_idx\n  {\n    NEW_SCRIPT_ACTION = 0,\n    NEW_FUNCTION_ACTION,\n    OPEN_ACTION,\n    FIND_FILES_ACTION,\n    UNDO_ACTION,\n    COPY_ACTION,\n    PASTE_ACTION,\n    SELECTALL_ACTION\n  };\n\n  void check_actions ();\n  void empty_script (bool startup, bool visible);\n  void restore_session (bool visible = true);\n\n  const QString get_current_filename ();\n\nQ_SIGNALS:\n\n  void fetab_settings_changed ();\n  void fetab_change_request (const QWidget *ID);\n  // Save is a ping-pong type of communication\n  void fetab_save_file (const QWidget *ID, const QString& fileName,\n                        bool remove_on_success);\n  // No fetab_open, functionality in editor\n  // No fetab_new, functionality in editor\n  void fetab_context_help (const QWidget *ID, bool);\n  void fetab_context_edit (const QWidget *ID);\n  void fetab_save_file (const QWidget *ID);\n  void fetab_save_file_as (const QWidget *ID);\n  void fetab_print_file (const QWidget *ID);\n  void fetab_run_file (const QWidget *ID, int opts);\n  void fetab_context_run (const QWidget *ID);\n  void fetab_toggle_bookmark (const QWidget *ID);\n  void fetab_next_bookmark (const QWidget *ID);\n  void fetab_previous_bookmark (const QWidget *ID);\n  void fetab_remove_bookmark (const QWidget *ID);\n  void fetab_toggle_breakpoint (const QWidget *ID);\n  void fetab_next_breakpoint (const QWidget *ID);\n  void fetab_previous_breakpoint (const QWidget *ID);\n  void fetab_remove_all_breakpoints (const QWidget *ID);\n  void fetab_comment_selected_text (const QWidget *ID, bool);\n  void fetab_uncomment_selected_text (const QWidget *ID);\n  void fetab_indent_selected_text (const QWidget *ID);\n  void fetab_unindent_selected_text (const QWidget *ID);\n  void fetab_smart_indent_line_or_selected_text (const QWidget *ID);\n  void fetab_convert_eol (const QWidget *ID, QsciScintilla::EolMode eol_mode);\n  void fetab_goto_line (const QWidget *ID, int line = -1);\n  void fetab_move_match_brace (const QWidget *ID, bool select);\n  void fetab_completion (const QWidget *);\n  void fetab_insert_debugger_pointer (const QWidget *ID, int line = -1);\n  void fetab_delete_debugger_pointer (const QWidget *ID, int line = -1);\n  void fetab_do_breakpoint_marker (bool insert, const QWidget *ID,\n                                   int line = -1, const QString& = \"\");\n  void fetab_set_focus (const QWidget *ID);\n  void fetab_scintilla_command (const QWidget *ID, unsigned int sci_msg);\n\n  void fetab_zoom_in (const QWidget *ID);\n  void fetab_zoom_out (const QWidget *ID);\n  void fetab_zoom_normal (const QWidget *ID);\n\n  void fetab_set_directory (const QString& dir);\n  void fetab_recover_from_exit ();\n\n  void edit_area_changed (octave_qscintilla *edit_area);\n\n  void request_settings_dialog (const QString&);\n  void request_open_file_external (const QString& file_name, int line);\n  void file_loaded_signal ();\n\n  void editor_tabs_changed_signal (bool, bool);\n  void request_dbcont_signal ();\n\n  void enter_debug_mode_signal ();\n  void exit_debug_mode_signal ();\n\n  void update_gui_lexer_signal (bool);\n  void execute_command_in_terminal_signal (const QString&);\n  void focus_console_after_command_signal ();\n  void run_file_signal (const QFileInfo&, int opts);\n  void edit_mfile_request (const QString&, const QString&, const QString&, int);\n  void debug_quit_signal ();\n\n  void show_symbol_tooltip_signal (const QPoint&, const QString&);\n\n  void remove_editor_file_in_browser_signal (const QString& file);\n  void rename_editor_file_in_browser_signal (const QString& old_file,\n                                             const QString& new_file);\n\npublic Q_SLOTS:\n\n  void activate ();\n  void set_focus (QWidget *fet);\n  void enable_menu_shortcuts (bool);\n  void save_session ();\n  bool check_closing ();\n  void handle_tab_ready_to_close ();\n\n  void handle_enter_debug_mode ();\n  void handle_exit_debug_mode ();\n\n  void request_new_file (const QString& commands);\n  void request_close_file (bool);\n  void request_close_all_files (bool);\n  void request_close_other_files (bool);\n  void copy_full_file_path (bool);\n  void request_mru_open_file (QAction *action);\n  void request_print_file (bool);\n\n  void request_redo (bool);\n  void request_cut (bool);\n  void request_context_help (bool);\n  void request_context_doc (bool);\n  void request_context_edit (bool);\n  void request_save_file (bool);\n  void request_save_file_as (bool);\n  void request_run_file (bool);\n  void request_run_tests (bool);\n  void request_run_demos (bool);\n  void request_step_into_file ();\n  void request_context_run (bool);\n  void request_toggle_bookmark (bool);\n  void request_next_bookmark (bool);\n  void request_previous_bookmark (bool);\n  void request_remove_bookmark (bool);\n\n  void request_move_match_brace (bool);\n  void request_sel_match_brace (bool);\n  void request_toggle_breakpoint (bool);\n  void request_next_breakpoint (bool);\n  void request_previous_breakpoint (bool);\n  void request_remove_breakpoint (bool);\n\n  void request_delete_start_word (bool);\n  void request_delete_end_word (bool);\n  void request_delete_start_line (bool);\n  void request_delete_end_line (bool);\n  void request_delete_line (bool);\n  void request_copy_line (bool);\n  void request_cut_line (bool);\n  void request_duplicate_selection (bool);\n  void request_transpose_line (bool);\n\n  void request_comment_selected_text (bool);\n  void request_uncomment_selected_text (bool);\n  void request_comment_var_selected_text (bool);\n\n  void request_upper_case (bool);\n  void request_lower_case (bool);\n  void request_indent_selected_text (bool);\n  void request_unindent_selected_text (bool);\n  void request_smart_indent_line_or_selected_text ();\n  void request_conv_eol_windows (bool);\n  void request_conv_eol_unix (bool);\n  void request_conv_eol_mac (bool);\n\n  void request_find (bool);\n  void request_find_next (bool);\n  void request_find_previous (bool);\n\n  void request_goto_line (bool);\n  void request_completion (bool);\n\n  void handle_file_name_changed (const QString& fileName,\n                                 const QString& toolTip,\n                                 bool modified);\n  void handle_tab_close_request (int index);\n  void handle_tab_remove_request (const QString& file_name);\n  void active_tab_changed (int index);\n  void handle_editor_state_changed (bool enableCopy, bool is_octave_file,\n                                    bool is_modified);\n  void handle_mru_add_file (const QString& file_name, const QString& encoding);\n  void check_conflict_save (const QString& fileName, bool remove_on_success);\n\n  void handle_insert_debugger_pointer_request (const QString& file, int line);\n  void handle_delete_debugger_pointer_request (const QString& file, int line);\n  void handle_update_breakpoint_marker_request (bool insert,\n      const QString& file, int line,\n      const QString& cond);\n\n  void handle_edit_file_request (const QString& file);\n\n  void handle_file_remove (const QString&, const QString&);\n  void handle_file_renamed (bool load_new = true);\n\n  void handle_close_file_request (const QStringList& files_to_close);\n\n  // Tells the editor to react on changed settings.\n  void notice_settings ();\n\n  void set_shortcuts ();\n\n  void handle_visibility (bool visible);\n\n  void update_octave_directory (const QString& dir);\n\n  void toplevel_change (bool toplevel);\n\n  void handle_autoc_cancelled ();\n\n  file_editor_tab * reset_focus ();\n\nprotected Q_SLOTS:\n\n  void copyClipboard ();\n  void pasteClipboard ();\n  void selectAll ();\n  void do_undo ();\n\nprivate Q_SLOTS:\n\n  void request_open_file (const QString& fileName,\n                          const QString& encoding = QString (),\n                          int line = -1, bool debug_pointer = false,\n                          bool breakpoint_marker = false, bool insert = true,\n                          const QString& cond = \"\", int index = -1,\n                          const QString& bookmarks = QString (),\n                          const find_files_data& ff_data = {});\n  void request_preferences (bool);\n  void request_styles_preferences (bool);\n\n  void run_file (bool, int opts);\n\n  void show_line_numbers (bool);\n  void show_white_space (bool);\n  void show_eol_chars (bool);\n  void show_indent_guides (bool);\n  void show_long_line (bool);\n  void show_toolbar (bool);\n  void show_statusbar (bool);\n  void show_hscrollbar (bool);\n  void zoom_in (bool);\n  void zoom_out (bool);\n  void zoom_normal (bool);\n\n  void create_context_menu (QMenu *);\n  void edit_status_update (bool, bool);\n\nprotected:\n\n  void closeEvent (QCloseEvent *event);\n  void dragEnterEvent (QDragEnterEvent *event);\n  void dropEvent (QDropEvent *event);\n  void focusInEvent (QFocusEvent *e);\n\nprivate:\n\n  file_editor_tab * make_file_editor_tab (const QString& directory = \"\");\n\n  bool is_editor_console_tabbed ();\n  void construct ();\n  void add_file_editor_tab (file_editor_tab *f, const QString& fn,\n                            int index = -1);\n  void mru_menu_update ();\n  bool call_custom_editor (const QString& file_name = QString (), int line = -1);\n\n  void toggle_preference (const gui_pref& preference);\n\n  void handle_dir_remove (const QString& old_name, const QString& new_name);\n\n  bool editor_tab_has_focus ();\n\n  void find_create ();\n\n  file_editor_tab * find_tab_widget (const QString& openFileName);\n  QAction * add_action (QMenu *menu, const QString& text,\n                       const char *member, QWidget *receiver = nullptr);\n  QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text,\n                       const char *member, QWidget *receiver = nullptr);\n\n  QMenu * add_menu (QMenuBar *p, QString text);\n\n  int m_number_of_tabs;\n  QHash<QMenu *, QStringList> m_hash_menu_text;\n\n  QString m_ced;\n\n  QMenuBar *m_menu_bar;\n  QToolBar *m_tool_bar;\n  QMenu *m_debug_menu;\n\n  QAction *m_new_action;\n  QAction *m_new_function_action;\n  QAction *m_open_action;\n\n  QAction *m_upper_case_action;\n  QAction *m_lower_case_action;\n  QAction *m_comment_selection_action;\n  QAction *m_comment_var_selection_action;\n  QAction *m_uncomment_selection_action;\n  QAction *m_indent_selection_action;\n  QAction *m_unindent_selection_action;\n  QAction *m_smart_indent_line_or_selection_action;\n  QAction *m_conv_eol_windows_action;\n  QAction *m_conv_eol_unix_action;\n  QAction *m_conv_eol_mac_action;\n\n  QAction *m_copy_action;\n  QAction *m_cut_action;\n  QAction *m_paste_action;\n  QAction *m_selectall_action;\n  QAction *m_context_help_action;\n  QAction *m_context_doc_action;\n\n  QAction *m_show_linenum_action;\n  QAction *m_show_whitespace_action;\n  QAction *m_show_eol_action;\n  QAction *m_show_indguide_action;\n  QAction *m_show_longline_action;\n  QAction *m_show_toolbar_action;\n  QAction *m_show_statusbar_action;\n  QAction *m_show_hscrollbar_action;\n  QAction *m_zoom_in_action;\n  QAction *m_zoom_out_action;\n  QAction *m_zoom_normal_action;\n\n  QAction *m_delete_start_word_action;\n  QAction *m_delete_end_word_action;\n  QAction *m_delete_start_line_action;\n  QAction *m_delete_end_line_action;\n  QAction *m_delete_line_action;\n  QAction *m_copy_line_action;\n  QAction *m_cut_line_action;\n  QAction *m_duplicate_selection_action;\n  QAction *m_transpose_line_action;\n\n  QAction *m_find_action;\n  QAction *m_find_next_action;\n  QAction *m_find_previous_action;\n  QAction *m_find_files_action;\n  QAction *m_goto_line_action;\n  QAction *m_completion_action;\n\n  QAction *m_move_to_matching_brace;\n  QAction *m_sel_to_matching_brace;\n  QAction *m_next_bookmark_action;\n  QAction *m_previous_bookmark_action;\n  QAction *m_toggle_bookmark_action;\n  QAction *m_remove_bookmark_action;\n\n  QAction *m_print_action;\n  QAction *m_run_action;\n  QAction *m_run_selection_action;\n  QAction *m_run_tests_action;\n  QAction *m_run_demos_action;\n\n  QAction *m_edit_function_action;\n  QAction *m_popdown_mru_action;\n  QAction *m_save_action;\n  QAction *m_save_as_action;\n  QAction *m_close_action;\n  QAction *m_close_all_action;\n  QAction *m_close_others_action;\n\n  QAction *m_redo_action;\n  QAction *m_undo_action;\n\n  QAction *m_preferences_action;\n  QAction *m_styles_preferences_action;\n\n  QAction *m_switch_left_tab_action;\n  QAction *m_switch_right_tab_action;\n  QAction *m_move_tab_left_action;\n  QAction *m_move_tab_right_action;\n  QAction *m_sort_tabs_action;\n\n  QAction *m_toggle_breakpoint_action;\n  QAction *m_next_breakpoint_action;\n  QAction *m_previous_breakpoint_action;\n  QAction *m_remove_all_breakpoints_action;\n\n  bool m_copy_action_enabled;\n  bool m_undo_action_enabled;\n  bool m_is_octave_file;\n  bool m_current_tab_modified;\n\n  QMenu *m_edit_menu;\n  QMenu *m_edit_cmd_menu;\n  QMenu *m_edit_fmt_menu;\n  QMenu *m_edit_nav_menu;\n  QMenu *m_fileMenu;\n  QMenu *m_view_editor_menu;\n\n  file_editor_tab_widget *m_tab_widget;\n\n  int m_marker_breakpoint;\n\n  bool m_closing_canceled;\n  bool m_closed;\n  bool m_no_focus;\n  bool m_editor_ready;\n\n  enum { MaxMRUFiles = 10 };\n  QMenu *m_mru_file_menu;\n  QAction *m_mru_file_actions[MaxMRUFiles];\n  QStringList m_mru_files;\n  QStringList m_mru_files_encodings;\n\n  QPointer<find_dialog> m_find_dialog;\n\n  // List of data on temporarily closed files for later reloading.\n  QList<removed_file_data> m_tmp_closed_files;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/find-dialog.cc",
    "content": "// Find dialog derived from an example from Qt Toolkit (license below (**))\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// or <https://octave.org/copyright/>.\n//\n//  All rights reserved.\n//  Contact: Nokia Corporation (qt-info@nokia.com)\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n// ** This file is part of the examples of the Qt Toolkit.\n// **\n// ** $QT_BEGIN_LICENSE:LGPL$\n// ** Commercial Usage\n// ** Licensees holding valid Qt Commercial licenses may use this file in\n// ** accordance with the Qt Commercial License Agreement provided with the\n// ** Software or, alternatively, in accordance with the terms contained in\n// ** a written agreement between you and Nokia.\n// **\n// ** GNU Lesser General Public License Usage\n// ** Alternatively, this file may be used under the terms of the GNU Lesser\n// ** General Public License version 2.1 as published by the Free Software\n// ** Foundation and appearing in the file LICENSE.LGPL included in the\n// ** packaging of this file.  Please review the following information to\n// ** ensure the GNU Lesser General Public License version 2.1 requirements\n// ** will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n// **\n// ** In addition, as a special exception, Nokia gives you certain additional\n// ** rights.  These rights are described in the Nokia Qt LGPL Exception\n// ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n// **\n// ** GNU General Public License Usage\n// ** Alternatively, this file may be used under the terms of the GNU\n// ** General Public License version 3.0 as published by the Free Software\n// ** Foundation and appearing in the file LICENSE.GPL included in the\n// ** packaging of this file.  Please review the following information to\n// ** ensure the GNU General Public License version 3.0 requirements will be\n// ** met: https://www.gnu.org/copyleft/gpl.html.\n// **\n// ** If you have questions regarding the use of this file, please contact\n// ** Nokia at qt-info@nokia.com.\n// ** $QT_END_LICENSE$\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_QSCINTILLA)\n\n#include <QApplication>\n#include <QCheckBox>\n#include <QCheckBox>\n#include <QCompleter>\n#include <QDialogButtonBox>\n#include <QGridLayout>\n#include <QIcon>\n#include <QLabel>\n#include <QLineEdit>\n#include <QMessageBox>\n#include <QPushButton>\n#include <QVBoxLayout>\n\n#include \"find-dialog.h\"\n#include \"gui-preferences-ed.h\"\n#include \"gui-utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nfind_dialog::find_dialog (octave_dock_widget *ed, QWidget *p)\n  : QDialog (p), m_editor (ed), m_in_sel (false),\n    m_sel_beg (-1), m_sel_end (-1)\n{\n  setWindowTitle (tr (\"Editor: Find and Replace\"));\n\n  m_search_label = new QLabel (tr (\"&Find:\"));\n  m_search_line_edit = new QComboBox (this);\n  m_search_line_edit->setToolTip (tr (\"Enter search text\"));\n  m_search_line_edit->setEditable (true);\n  m_search_line_edit->setMaxCount (m_mru_length);\n  m_search_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive);\n  m_search_label->setBuddy (m_search_line_edit);\n\n  m_replace_label = new QLabel (tr (\"Re&place:\"));\n  m_replace_line_edit = new QComboBox (this);\n  m_replace_line_edit->setToolTip (tr (\"Enter replacement text\"));\n  m_replace_line_edit->setEditable (true);\n  m_replace_line_edit->setMaxCount (m_mru_length);\n  m_replace_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive);\n  m_replace_label->setBuddy (m_replace_line_edit);\n\n  int width = QFontMetrics (m_search_line_edit->font ()).averageCharWidth ();\n  m_search_line_edit->setFixedWidth (20*width);\n  m_replace_line_edit->setFixedWidth (20*width);\n\n  m_case_check_box = new QCheckBox (tr (\"Match &case\"));\n  m_from_start_check_box = new QCheckBox (tr (\"Search from &start\"));\n  m_wrap_check_box = new QCheckBox (tr (\"&Wrap while searching\"));\n  m_wrap_check_box->setChecked (true);\n  m_find_next_button = new QPushButton (tr (\"Find &Next\"));\n  m_find_prev_button = new QPushButton (tr (\"Find Pre&vious\"));\n  m_replace_button = new QPushButton (tr (\"&Replace\"));\n  m_replace_all_button = new QPushButton (tr (\"Replace &All\"));\n\n  m_more_button = new QPushButton (tr (\"&More...\"));\n  m_more_button->setCheckable (true);\n  m_more_button->setAutoDefault (false);\n\n  m_button_box = new QDialogButtonBox (Qt::Vertical);\n  m_button_box->addButton (m_find_next_button, QDialogButtonBox::ActionRole);\n  m_button_box->addButton (m_find_prev_button, QDialogButtonBox::ActionRole);\n  m_button_box->addButton (m_replace_button, QDialogButtonBox::ActionRole);\n  m_button_box->addButton (m_replace_all_button, QDialogButtonBox::ActionRole);\n  m_button_box->addButton (m_more_button, QDialogButtonBox::ActionRole);\n  m_button_box->addButton (QDialogButtonBox::Close);\n\n  m_extension = new QWidget (this);\n  m_whole_words_check_box = new QCheckBox (tr (\"&Whole words\"));\n  m_regex_check_box = new QCheckBox (tr (\"Regular &expressions\"));\n  m_backward_check_box = new QCheckBox (tr (\"Search &backward\"));\n  m_search_selection_check_box = new QCheckBox (tr (\"Search se&lection\"));\n  m_search_selection_check_box->setCheckable (true);\n\n  connect (m_find_next_button, &QPushButton::clicked,\n           this, &find_dialog::find_next);\n  connect (m_find_prev_button, &QPushButton::clicked,\n           this, &find_dialog::find_prev);\n  connect (m_more_button, &QPushButton::toggled,\n           m_extension, &QWidget::setVisible);\n  connect (m_replace_button, &QPushButton::clicked,\n           this, &find_dialog::replace);\n  connect (m_replace_all_button, &QPushButton::clicked,\n           this, &find_dialog::replace_all);\n  connect (m_backward_check_box,\n#if defined (HAVE_QCHECKBOX_CHECKSTATECHANGED)\n           &QCheckBox::checkStateChanged,\n#else\n           &QCheckBox::stateChanged,\n#endif\n           this, &find_dialog::handle_backward_search_changed);\n  connect (m_button_box, &QDialogButtonBox::rejected,\n           this, &find_dialog::close);\n\n  connect (m_search_selection_check_box,\n#if defined (HAVE_QCHECKBOX_CHECKSTATECHANGED)\n           &QCheckBox::checkStateChanged,\n#else\n           &QCheckBox::stateChanged,\n#endif\n           this, &find_dialog::handle_sel_search_changed);\n\n  QVBoxLayout *extension_layout = new QVBoxLayout ();\n  extension_layout->setContentsMargins (0, 0, 0, 0);\n  extension_layout->addWidget (m_whole_words_check_box);\n  extension_layout->addWidget (m_backward_check_box);\n  extension_layout->addWidget (m_search_selection_check_box);\n  m_extension->setLayout (extension_layout);\n\n  QGridLayout *top_left_layout = new QGridLayout;\n  top_left_layout->addWidget (m_search_label, 1, 1);\n  top_left_layout->addWidget (m_search_line_edit, 1, 2);\n  top_left_layout->addWidget (m_replace_label, 2, 1);\n  top_left_layout->addWidget (m_replace_line_edit, 2, 2);\n\n  QVBoxLayout *left_layout = new QVBoxLayout;\n  left_layout->addLayout (top_left_layout);\n  left_layout->insertStretch (1, 5);\n  left_layout->addWidget (m_case_check_box);\n  left_layout->addWidget (m_from_start_check_box);\n  left_layout->addWidget (m_wrap_check_box);\n  left_layout->addWidget (m_regex_check_box);\n\n  QGridLayout *main_layout = new QGridLayout;\n  main_layout->setSizeConstraint (QLayout::SetFixedSize);\n  main_layout->addLayout (left_layout, 0, 0);\n  main_layout->addWidget (m_button_box, 0, 1);\n  main_layout->addWidget (m_extension, 1, 0);\n  setLayout (main_layout);\n\n  m_extension->hide ();\n  m_find_next_button->setDefault (true);\n  m_find_result_available = false;\n  m_rep_all = 0;\n  m_rep_active = false;\n\n  // Connect required external signals\n  connect (ed, SIGNAL (edit_area_changed (octave_qscintilla *)),\n           this, SLOT (update_edit_area (octave_qscintilla *)));\n\n  setWindowModality (Qt::NonModal);\n\n  setAttribute (Qt::WA_ShowWithoutActivating);\n  setAttribute (Qt::WA_DeleteOnClose);\n}\n\n// The edit_area has changed: update relevant data of the file dialog\nvoid\nfind_dialog::update_edit_area (octave_qscintilla *edit_area)\n{\n  m_edit_area = edit_area;\n  m_search_selection_check_box->setEnabled (edit_area->hasSelectedText ());\n\n  connect (m_edit_area, SIGNAL (copyAvailable (bool)),\n           this,       SLOT (handle_selection_changed (bool)),\n           Qt::UniqueConnection);\n}\n\nvoid\nfind_dialog::save_settings ()\n{\n  gui_settings settings;\n\n  // Save position\n  QPoint dlg_pos = pos ();\n\n#if defined (Q_OS_WIN32)\n  int y = dlg_pos.y ();\n#else\n  int y = dlg_pos.y () - geometry ().height () + frameGeometry ().height ();\n#endif\n\n  m_last_position = QPoint (dlg_pos.x (), y);\n\n  settings.setValue (ed_fdlg_pos.settings_key (), m_last_position);\n\n  // Is current search/replace text in the mru list?\n  combobox_update (m_search_line_edit, m_mru_length);\n  combobox_update (m_replace_line_edit, m_mru_length);\n\n  // Store mru lists\n  QStringList mru;\n  for (int i = 0; i < m_search_line_edit->count (); i++)\n    mru.append (m_search_line_edit->itemText (i));\n  settings.setValue (ed_fdlg_search.settings_key (), mru);\n\n  mru.clear ();\n  for (int i = 0; i < m_replace_line_edit->count (); i++)\n    mru.append (m_replace_line_edit->itemText (i));\n  settings.setValue (ed_fdlg_replace.settings_key (), mru);\n\n  // Store dialog's options\n  int opts = 0\n             + m_extension->isVisible () * FIND_DLG_MORE\n             + m_case_check_box->isChecked () * FIND_DLG_CASE\n             + m_from_start_check_box->isChecked () * FIND_DLG_START\n             + m_wrap_check_box->isChecked () * FIND_DLG_WRAP\n             + m_regex_check_box->isChecked () * FIND_DLG_REGX\n             + m_whole_words_check_box->isChecked () * FIND_DLG_WORDS\n             + m_backward_check_box->isChecked () * FIND_DLG_BACK\n             + m_search_selection_check_box->isChecked () * FIND_DLG_SEL;\n  settings.setValue (ed_fdlg_opts.settings_key (), opts);\n\n  settings.sync ();\n}\n\nvoid\nfind_dialog::restore_settings (QPoint ed_bottom_right)\n{\n  gui_settings settings;\n\n  // Get mru lists for search and replace text\n  QStringList mru = settings.value (ed_fdlg_search.settings_key ()).toStringList ();\n  while (mru.length () > m_mru_length)\n    mru.removeLast ();\n  m_search_line_edit->addItems (mru);\n\n  mru = settings.value (ed_fdlg_replace.settings_key ()).toStringList ();\n  while (mru.length () > m_mru_length)\n    mru.removeLast ();\n  m_replace_line_edit->addItems (mru);\n\n  // Get the dialog's options\n  int opts = settings.int_value (ed_fdlg_opts);\n\n  m_extension->setVisible (FIND_DLG_MORE & opts);\n  m_case_check_box->setChecked (FIND_DLG_CASE & opts);\n  m_from_start_check_box->setChecked (FIND_DLG_START & opts);\n  m_wrap_check_box->setChecked (FIND_DLG_WRAP & opts);\n  m_regex_check_box->setChecked (FIND_DLG_REGX & opts);\n  m_whole_words_check_box->setChecked (FIND_DLG_WORDS & opts);\n  m_backward_check_box->setChecked (FIND_DLG_BACK & opts);\n  m_search_selection_check_box->setChecked (FIND_DLG_SEL & opts);\n\n  // Default position: lower right of editor's position\n  int xp = ed_bottom_right.x () - sizeHint ().width ();\n  int yp = ed_bottom_right.y () - sizeHint ().height ();\n  QRect default_geometry (xp, yp, sizeHint ().width (), sizeHint ().height ());\n\n  // Last position from settings\n  m_last_position = settings.value (ed_fdlg_pos.settings_key (), QPoint (xp, yp)).toPoint ();\n  QRect last_geometry (m_last_position,\n                       QSize (sizeHint ().width (), sizeHint ().height ()));\n\n  // Make sure we are on the screen\n  adjust_to_screen (last_geometry, default_geometry);\n  m_last_position = last_geometry.topLeft ();\n\n  move (m_last_position);\n}\n\n// set text of \"search from start\" depending on backward search\nvoid\nfind_dialog::handle_backward_search_changed (int backward)\n{\n  if (backward)\n    m_from_start_check_box->setText (tr (\"Search from end\"));\n  else\n    m_from_start_check_box->setText (tr (\"Search from start\"));\n}\n\n// search text has changed: reset the search\nvoid\nfind_dialog::handle_search_text_changed ()\n{\n  // Return if nothing has changed\n  if (m_search_line_edit->currentText () == m_search_line_edit->itemText (0))\n    return;\n\n  if (m_search_selection_check_box->isChecked ())\n    m_find_result_available = false;\n\n  combobox_update (m_search_line_edit, m_mru_length);\n}\n\n// replaced text has changed: reset the search\nvoid\nfind_dialog::handle_replace_text_changed ()\n{\n  // Return if nothing has changed\n  if (m_replace_line_edit->currentText () == m_replace_line_edit->itemText (0))\n    return;\n\n  combobox_update (m_replace_line_edit, m_mru_length);\n}\n\nvoid\nfind_dialog::handle_sel_search_changed (int selected)\n{\n  m_from_start_check_box->setEnabled (! selected);\n  m_find_result_available = false;\n}\n\nvoid\nfind_dialog::handle_selection_changed (bool has_selected)\n{\n  if (m_rep_active)\n    return;\n\n  m_search_selection_check_box->setEnabled (has_selected);\n  m_find_result_available = false;\n}\n\n// initialize search text with selected text if this is in one single line\nvoid\nfind_dialog::init_search_text ()\n{\n  if (m_edit_area && m_edit_area->hasSelectedText ())\n    {\n      int lbeg, lend, cbeg, cend;\n      m_edit_area->getSelection (&lbeg, &cbeg, &lend, &cend);\n      if (lbeg == lend)\n        m_search_line_edit->setCurrentText (m_edit_area->selectedText ());\n    }\n\n  // set focus to \"Find what\" and select all text\n  m_search_line_edit->setFocus ();\n  m_search_line_edit->lineEdit ()->selectAll ();\n\n  // Default to \"find\" next time.\n  // Otherwise, it defaults to the last action, which may be \"replace all\".\n  m_find_next_button->setDefault (true);\n}\n\nvoid\nfind_dialog::find_next ()\n{\n  find (! m_backward_check_box->isChecked ());\n}\n\nvoid\nfind_dialog::find_prev ()\n{\n  find (m_backward_check_box->isChecked ());\n}\n\nvoid\nfind_dialog::find (bool forward)\n{\n  if (! m_edit_area)\n    return;\n\n  handle_search_text_changed ();\n\n  // line adn col: -1 means search starts at current position\n  int line = -1, col = -1;\n\n  bool do_wrap = m_wrap_check_box->isChecked ();\n  bool do_forward = forward;\n\n  // Initialize the selection begin and end if it is the first search\n  if (! m_find_result_available)\n    {\n      if (m_search_selection_check_box->isChecked ()\n          && m_edit_area->hasSelectedText ())\n        {\n          int l1, c1, l2, c2;\n          m_edit_area->getSelection (&l1, &c1, &l2, &c2);\n\n          // Store the position of the selection\n          m_sel_beg = m_edit_area->positionFromLineIndex (l1, c1);\n          m_sel_end = m_edit_area->positionFromLineIndex (l2, c2);\n          m_in_sel = true;\n        }\n      else\n        m_in_sel = false;\n    }\n\n  // Get the correct line/col for beginning the search\n  if (m_rep_all)\n    {\n      // Replace All\n      if (m_rep_all == 1)\n        {\n          // Start at the beginning of file/sel if it is the first try\n          if (m_in_sel)\n            m_edit_area->lineIndexFromPosition (m_sel_beg, &line, &col);\n          else\n            {\n              line = 0;\n              col = 0;\n            }\n        }\n      do_wrap = false;  // Never wrap when replacing all\n    }\n  else\n    {\n      // Normal search (not replace all): calculate start position of\n      // search (in file or selection)\n      if (m_from_start_check_box->isChecked ()\n          || (m_in_sel && (! m_find_result_available)))\n        {\n          // From the beginning or the end of file/sel\n          if (do_forward)\n            {\n              // From the beginning\n              if (m_in_sel)\n                m_edit_area->lineIndexFromPosition (m_sel_beg, &line, &col);\n              else\n                {\n                  line = 0;\n                  col = 0;\n                }\n            }\n          else\n            {\n              // From the end\n              if (m_in_sel)\n                m_edit_area->lineIndexFromPosition (m_sel_end, &line, &col);\n              else\n                {\n                  line = m_edit_area->lines () - 1;\n                  col  = m_edit_area->text (line).length () - 1;\n                  if (col == -1)\n                    col = 0;\n                }\n            }\n        }\n      else if (! do_forward)\n        {\n          // Start from where the cursor is.  Fix QScintilla's cursor\n          // positioning\n          m_edit_area->getCursorPosition (&line, &col);\n          if (m_find_result_available && m_edit_area->hasSelectedText ())\n            {\n              int currpos = m_edit_area->positionFromLineIndex (line, col);\n              currpos -= (m_search_line_edit->currentText ().length ());\n              if (currpos < 0)\n                currpos = 0;\n              m_edit_area->lineIndexFromPosition (currpos, &line, &col);\n            }\n        }\n    }\n\n  // Do the search\n  m_find_result_available\n    = m_edit_area->findFirst (m_search_line_edit->currentText (),\n                              m_regex_check_box->isChecked (),\n                              m_case_check_box->isChecked (),\n                              m_whole_words_check_box->isChecked (),\n                              do_wrap,\n                              do_forward,\n                              line, col,\n                              true\n#if defined (HAVE_QSCI_VERSION_2_6_0)\n                              , true\n#endif\n                             );\n\n  if (m_find_result_available)\n    {\n      // Search successful: reset search-from-start box and check for\n      // the current selection\n      m_from_start_check_box->setChecked (0);\n\n      if (m_in_sel)\n        {\n          m_edit_area->getCursorPosition (&line, &col);\n          int pos = m_edit_area->positionFromLineIndex (line, col);\n\n          int l1, c1, l2, c2;\n          m_edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1);\n          m_edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2);\n          m_edit_area->show_selection_markers (l1, c1, l2, c2);\n\n          // Check if new start position is still within the selection\n          m_find_result_available =  pos >= m_sel_beg && pos <= m_sel_end;\n        }\n    }\n\n  // No more search hits\n  if (! m_find_result_available)\n    {\n      if (m_in_sel)\n        {\n          // Restore real selection and remove marker for selection\n          int l1, c1, l2, c2;\n          m_edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1);\n          m_edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2);\n          m_edit_area->setSelection (l1, c1, l2, c2);\n          m_edit_area->clear_selection_markers ();\n        }\n\n      // Display message if not replace all\n      if (! m_rep_all)\n        no_matches_message ();\n    }\n\n}\n\nvoid\nfind_dialog::do_replace ()\n{\n  if (m_edit_area)\n    {\n      m_rep_active = true;  // changes in selection not made by the user\n\n      m_edit_area->replace (m_replace_line_edit->currentText ());\n      if (m_in_sel)\n        {\n          // Update the length of the selection\n          m_sel_end = m_sel_end\n                      - m_search_line_edit->currentText ().toUtf8 ().size ()\n                      + m_replace_line_edit->currentText ().toUtf8 ().size ();\n        }\n\n      m_rep_active = false;\n    }\n}\n\nvoid\nfind_dialog::replace ()\n{\n  if (m_edit_area)\n    {\n      handle_replace_text_changed ();\n\n      // Do the replace if we have selected text\n      if (m_find_result_available && m_edit_area->hasSelectedText ())\n        do_replace ();\n\n      find_next ();\n    }\n}\n\nvoid\nfind_dialog::replace_all ()\n{\n  int line, col;\n\n  if (m_edit_area)\n    {\n      handle_replace_text_changed ();\n\n      m_edit_area->getCursorPosition (&line, &col);\n\n      m_rep_all = 1;\n      find_next ();  // find first occurrence (forward)\n\n      m_edit_area->beginUndoAction ();\n      while (m_find_result_available)   // while search string is found\n        {\n          do_replace ();\n          m_rep_all++;                                          // inc counter\n          find_next ();                                        // find next\n        }\n      m_edit_area->endUndoAction ();\n\n      QMessageBox msg_box (QMessageBox::Information, tr (\"Replace Result\"),\n                           tr (\"%1 items replaced\").arg (m_rep_all-1),\n                           QMessageBox::Ok, this);\n      msg_box.exec ();\n\n      m_rep_all = 0;\n      m_find_result_available = false;\n\n      if (! m_search_selection_check_box->isChecked ())\n        m_edit_area->setCursorPosition (line, col);\n    }\n}\n\nvoid\nfind_dialog::no_matches_message ()\n{\n  QMessageBox msg_box (QMessageBox::Information, tr (\"Find Result\"),\n                       tr (\"No more matches found\"), QMessageBox::Ok, this);\n  msg_box.exec ();\n}\n\nvoid\nfind_dialog::reject ()\n{\n  close ();\n}\n\nvoid\nfind_dialog::closeEvent (QCloseEvent *e)\n{\n  save_settings ();\n  e->accept ();\n}\n\n// Show and hide with (re-)storing position, otherwise there is always\n// a small shift each time the dialog is shown again\nvoid\nfind_dialog::set_visible (bool visible)\n{\n  if (visible)\n    {\n      show ();\n      move (m_last_position);\n    }\n  else\n    {\n      m_last_position = pos ();\n      hide ();\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/find-dialog.h",
    "content": "// Find dialog derived from an example from Qt Toolkit (license below (**))\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// or <https://octave.org/copyright/>.\n//\n//  All rights reserved.\n//  Contact: Nokia Corporation (qt-info@nokia.com)\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n// ** This file is part of the examples of the Qt Toolkit.\n// **\n// ** $QT_BEGIN_LICENSE:LGPL$\n// ** Commercial Usage\n// ** Licensees holding valid Qt Commercial licenses may use this file in\n// ** accordance with the Qt Commercial License Agreement provided with the\n// ** Software or, alternatively, in accordance with the terms contained in\n// ** a written agreement between you and Nokia.\n// **\n// ** GNU Lesser General Public License Usage\n// ** Alternatively, this file may be used under the terms of the GNU Lesser\n// ** General Public License version 2.1 as published by the Free Software\n// ** Foundation and appearing in the file LICENSE.LGPL included in the\n// ** packaging of this file.  Please review the following information to\n// ** ensure the GNU Lesser General Public License version 2.1 requirements\n// ** will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n// **\n// ** In addition, as a special exception, Nokia gives you certain additional\n// ** rights.  These rights are described in the Nokia Qt LGPL Exception\n// ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n// **\n// ** GNU General Public License Usage\n// ** Alternatively, this file may be used under the terms of the GNU\n// ** General Public License version 3.0 as published by the Free Software\n// ** Foundation and appearing in the file LICENSE.GPL included in the\n// ** packaging of this file.  Please review the following information to\n// ** ensure the GNU General Public License version 3.0 requirements will be\n// ** met: https://www.gnu.org/copyleft/gpl.html.\n// **\n// ** If you have questions regarding the use of this file, please contact\n// ** Nokia at qt-info@nokia.com.\n// ** $QT_END_LICENSE$\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_find_dialog_h)\n#define octave_find_dialog_h 1\n\n#include <QDialog>\n#include <QComboBox>\n\n#include \"octave-qscintilla.h\"\n#include \"octave-dock-widget.h\"\n\nclass QCheckBox;\nclass QDialogButtonBox;\nclass QGroupBox;\nclass QLabel;\nclass QLineEdit;\nclass QPushButton;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass file_editor;\n\nclass find_dialog : public QDialog\n{\n  Q_OBJECT\n\npublic:\n\n  find_dialog (octave_dock_widget *ed, QWidget *p);\n\n  //! Set dialog visible or not and storing the new visibility state\n  void set_visible (bool visible);\n\n  //! Init the search text with the selected text in the editor tab\n  void init_search_text ();\n\n  //! Restore position and the search options from the given settings\n  //! where def_pos is the default position suitable for the current\n  //! editor position\n  void restore_settings (QPoint def_pos);\n\npublic Q_SLOTS:\n\n  void find_next ();\n  void find_prev ();\n\n  //! Slot for updating the edit area when the active tab has changed\n  void update_edit_area (octave_qscintilla *);\n\nprivate Q_SLOTS:\n\n  void handle_sel_search_changed (int);\n  void handle_selection_changed (bool has_selected);\n\n  void handle_backward_search_changed (int);\n\n  void find (bool forward = true);\n  void replace ();\n  void replace_all ();\n\nprivate:\n\n  //! Save position and the search options in the given settings\n  void save_settings ();\n\n  //! Reimplemented slot: close instead of hiding\n  void reject ();\n\n  //! Reimplemented close event\n  void closeEvent (QCloseEvent *e);\n\n  void no_matches_message ();\n  void do_replace ();\n\n  void handle_search_text_changed ();\n  void handle_replace_text_changed ();\n\n  octave_dock_widget *m_editor;\n\n  QLabel *m_search_label;\n  QComboBox *m_search_line_edit;\n  QLabel *m_replace_label;\n  QComboBox *m_replace_line_edit;\n  QCheckBox *m_case_check_box;\n  QCheckBox *m_from_start_check_box;\n  QCheckBox *m_wrap_check_box;\n  QCheckBox *m_whole_words_check_box;\n  QCheckBox *m_regex_check_box;\n  QCheckBox *m_search_selection_check_box;\n  QCheckBox *m_backward_check_box;\n  QDialogButtonBox *m_button_box;\n  QPushButton *m_find_next_button;\n  QPushButton *m_find_prev_button;\n  QPushButton *m_replace_button;\n  QPushButton *m_replace_all_button;\n  QPushButton *m_more_button;\n  QWidget *m_extension;\n  octave_qscintilla *m_edit_area;\n  bool m_find_result_available;\n  int m_rep_all;\n  bool m_rep_active;\n\n  bool m_in_sel;\n  int m_sel_beg;\n  int m_sel_end;\n\n  QPoint m_last_position;\n\n  const int m_mru_length = 10;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/marker.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_QSCINTILLA)\n\n#include \"marker.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nmarker::marker (QsciScintilla *area, int original_linenr,\n                editor_markers type, int editor_linenr,\n                const QString& condition)\n  : QObject ()\n{\n  construct (area, original_linenr, type, editor_linenr, condition);\n}\n\nmarker::marker (QsciScintilla *area, int original_linenr,\n                editor_markers type, const QString& condition)\n  : QObject ()\n{\n  construct (area, original_linenr, type, original_linenr - 1, condition);\n}\n\nvoid\nmarker::construct (QsciScintilla *area, int original_linenr,\n                   editor_markers type, int editor_linenr,\n                   const QString& condition)\n{\n  m_edit_area = area;\n  m_original_linenr = original_linenr;\n  m_marker_type = type;\n  m_mhandle = m_edit_area->markerAdd (editor_linenr, m_marker_type);\n  m_condition = condition;\n}\n\nvoid\nmarker::handle_remove_via_original_linenr (int linenr)\n{\n  if (m_original_linenr == linenr)\n    {\n      m_edit_area->markerDeleteHandle (m_mhandle);\n      delete this;\n    }\n}\n\nvoid\nmarker::handle_request_remove_via_editor_linenr (int linenr)\n{\n  // Get line number from the edit area and if it matches\n  // the requested line number, remove.\n  if (m_edit_area->markerLine (m_mhandle) == linenr)\n    {\n      // Rather than delete editor marker directly, issue command\n      // to Octave core.  Octave core should signal back to remove\n      // this breakpoint via debugger line number.\n      Q_EMIT request_remove (m_original_linenr);\n    }\n}\n\nvoid\nmarker::handle_remove ()\n{\n  m_edit_area->markerDeleteHandle (m_mhandle);\n  delete this;\n}\n\nvoid\nmarker::handle_find_translation (int linenr, int& translation_linenr,\n                                 marker *&bp)\n{\n  if (m_original_linenr == linenr)\n    {\n      translation_linenr = m_edit_area->markerLine (m_mhandle);\n      bp = this;\n    }\n}\n\nvoid\nmarker::handle_find_just_before (int linenr, int& original_linenr,\n                                 int& editor_linenr)\n{\n  if (m_original_linenr < linenr && m_original_linenr >= original_linenr)\n    {\n      original_linenr = m_original_linenr;\n      editor_linenr = m_edit_area->markerLine (m_mhandle);\n    }\n}\n\nvoid\nmarker::handle_find_just_after (int linenr, int& original_linenr,\n                                int& editor_linenr)\n{\n  if (m_original_linenr > linenr && m_original_linenr <= original_linenr)\n    {\n      original_linenr = m_original_linenr;\n      editor_linenr = m_edit_area->markerLine (m_mhandle);\n    }\n}\n\nvoid\nmarker::handle_report_editor_linenr (QIntList& lines, QStringList& conditions)\n{\n  lines << m_edit_area->markerLine (m_mhandle);\n  conditions << m_condition;\n}\n\nvoid\nmarker::handle_marker_line_deleted (int mhandle)\n{\n  // FUTURE SUPPORT: There really should be a signal in QsciScintilla\n  // called markerLineDeleted (int mhandle) because there is no way\n  // of knowing this.  QsciScintilla will place the marker at a\n  // different line rather than remove it from the margin.  I (DJS) will\n  // lobby for such a signal.\n  if (m_mhandle == mhandle)\n    {\n      if (m_marker_type == breakpoint || m_marker_type == debugger_position)\n        {\n          int editor_linenr = m_edit_area->markerLine (m_mhandle);\n          m_edit_area->markerDeleteHandle (m_mhandle);\n          m_marker_type = (m_marker_type == breakpoint\n                           ? unsure_breakpoint : unsure_debugger_position);\n          m_mhandle = m_edit_area->markerAdd (editor_linenr, m_marker_type);\n        }\n    }\n}\n\nvoid\nmarker::handle_marker_line_undeleted (int mhandle)\n{\n  // FUTURE SUPPORT: There really should be a signal in QsciScintilla\n  // called markerLineUndeleted (int mhandle) because there is no way\n  // of knowing this.  QsciScintilla will place the marker at a\n  // different line rather than remove it from the margin.  I (DJS) will\n  // lobby for such a signal.\n  if (m_mhandle == mhandle)\n    {\n      if (m_marker_type == unsure_breakpoint\n          || m_marker_type == unsure_debugger_position)\n        {\n          int editor_linenr = m_edit_area->markerLine (m_mhandle);\n          m_edit_area->markerDeleteHandle (m_mhandle);\n          m_marker_type = (m_marker_type == unsure_breakpoint\n                           ? breakpoint : debugger_position);\n          m_mhandle = m_edit_area->markerAdd (editor_linenr, m_marker_type);\n        }\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/marker.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_marker_h)\n#define octave_marker_h 1\n\n#include <QObject>\n#include <Qsci/qsciscintilla.h>\n\n// Defined for purposes of sending QList<int> as part of signal.\n#include <QList>\ntypedef QList<int> QIntList;\n\n// The breakpoint class keeps track of the debug line number that Octave core\n// uses and the handle of the marker inside the editor file.  If the editor\n// contents is modified, the debug line number and editor line number can be\n// out of alignment.  The marker handle can be used to retrieve the editor\n// line.\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass marker : public QObject\n{\n  Q_OBJECT\n\npublic:\n\n  // List of all marker types\n  // If multiple markers are on the same line, the first one listed\n  // is drawn at the back, so big ones should be first.\n  enum editor_markers\n  {\n    breakpoint,\n    cond_break,\n    unsure_breakpoint,\n    bookmark,\n    debugger_position,\n    unsure_debugger_position,\n    selection\n  };\n\n  marker (QsciScintilla *edit_area, int original_linenr,\n          editor_markers marker_type, const QString& condition = \"\");\n\n  marker (QsciScintilla *edit_area, int original_linenr,\n          editor_markers marker_type, int editor_linenr,\n          const QString& condition = \"\");\n\n  ~marker () = default;\n\n  const QString& get_cond () const { return m_condition; }\n\n  void set_cond (const QString& cond) { m_condition = cond; }\n\nQ_SIGNALS:\n\n  void request_remove (int original_linenr);\n\npublic Q_SLOTS:\n\n  void handle_remove_via_original_linenr (int original_linenr);\n  void handle_request_remove_via_editor_linenr (int editor_linenr);\n  void handle_remove ();\n  void handle_find_translation (int original_linenr, int& editor_linenr,\n                                marker *&bp);\n  void handle_find_just_before (int linenr, int& original_linenr,\n                                int& editor_linenr);\n  void handle_find_just_after (int linenr, int& original_linenr,\n                               int& editor_linenr);\n  /*  void handle_lines_changed ();*/\n  void handle_marker_line_deleted (int mhandle);\n  void handle_marker_line_undeleted (int mhandle);\n  void handle_report_editor_linenr (QIntList& lines, QStringList& conditions);\n\nprivate:\n\n  void construct (QsciScintilla *edit_area, int original_linenr,\n                  editor_markers marker_type, int editor_linenr,\n                  const QString& condition);\n\n  QsciScintilla *m_edit_area;\n  int m_original_linenr;\n  editor_markers m_marker_type;\n  int m_mhandle;\n  QString m_condition;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/octave-qscintilla.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_QSCINTILLA)\n\n#include <Qsci/qscilexer.h>\n\n#include <QDir>\n#include <QKeySequence>\n#include <QMessageBox>\n#include <QMimeData>\n#include <QPointer>\n#include <QRegularExpression>\n#include <QTemporaryFile>\n#include <QToolTip>\n#include <QVBoxLayout>\n#if defined (HAVE_QSCI_QSCILEXEROCTAVE_H)\n#  define HAVE_LEXER_OCTAVE 1\n#  include <Qsci/qscilexeroctave.h>\n#elif defined (HAVE_QSCI_QSCILEXERMATLAB_H)\n#  define HAVE_LEXER_MATLAB 1\n#  include <Qsci/qscilexermatlab.h>\n#endif\n#include <Qsci/qscicommandset.h>\n#include <Qsci/qscilexerbash.h>\n#include <Qsci/qscilexerbatch.h>\n#include <Qsci/qscilexercpp.h>\n#include <Qsci/qscilexerdiff.h>\n#include <Qsci/qscilexerperl.h>\n\n#include \"file-editor-tab.h\"\n#include \"gui-preferences-ed.h\"\n#include \"gui-settings.h\"\n// FIXME: hardwired marker numbers?\n#include \"marker.h\"\n#include \"octave-qscintilla.h\"\n#include \"workspace-model.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"cmd-edit.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"oct-env.h\"\n\n// Return true if CANDIDATE is a \"closing\" that matches OPENING,\n// such as \"end\" or \"endif\" for \"if\", or \"catch\" for \"try\".\n// Used for testing the last word of an \"if\" etc. line,\n// or the first word of the following line.\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic bool\nis_end (const QString& candidate, const QString& opening)\n{\n  bool retval = false;\n\n  if (opening == \"do\")          // The only one that can't be ended by \"end\"\n    {\n      if (candidate == \"until\")\n        retval = true;\n    }\n  else\n    {\n      if (candidate == \"end\")\n        retval =  true;\n      else\n        {\n          if (opening == \"try\")\n            {\n              if (candidate == \"catch\" || candidate == \"end_try_catch\")\n                retval = true;\n            }\n          else if (opening == \"unwind_protect\")\n            {\n              if (candidate == \"unwind_protect_cleanup\"\n                  || candidate == \"end_unwind_protect\")\n                retval = true;\n            }\n          else if (candidate == \"end\" + opening)\n            retval = true;\n          else if (opening == \"if\" && candidate == \"else\")\n            retval = true;\n        }\n    }\n\n  return retval;\n}\n\noctave_qscintilla::octave_qscintilla (QWidget *p)\n  : QsciScintilla (p), m_debug_mode (false), m_word_at_cursor (),\n    m_selection (), m_selection_replacement (), m_selection_line (-1),\n    m_selection_col (-1), m_indicator_id (1)\n{\n  connect (this, SIGNAL (textChanged ()),\n           this, SLOT (text_changed ()));\n\n  connect (this, SIGNAL (cursorPositionChanged (int, int)),\n           this, SLOT (cursor_position_changed (int, int)));\n\n  connect (this, &octave_qscintilla::ctx_menu_run_finished_signal,\n           this, &octave_qscintilla::ctx_menu_run_finished,\n           Qt::QueuedConnection);\n\n  // clear scintilla edit shortcuts that are handled by the editor\n  QsciCommandSet *cmd_set = standardCommands ();\n\n  // Disable buffered drawing on all systems\n  SendScintilla (SCI_SETBUFFEREDDRAW, false);\n\n#if defined (HAVE_QSCI_VERSION_2_6_0)\n  // find () was added in QScintilla 2.6\n  cmd_set->find (QsciCommand::SelectionCopy)->setKey (0);\n  cmd_set->find (QsciCommand::SelectionCut)->setKey (0);\n  cmd_set->find (QsciCommand::Paste)->setKey (0);\n  cmd_set->find (QsciCommand::SelectAll)->setKey (0);\n  cmd_set->find (QsciCommand::SelectionDuplicate)->setKey (0);\n  cmd_set->find (QsciCommand::LineTranspose)->setKey (0);\n  cmd_set->find (QsciCommand::Undo)->setKey (0);\n  cmd_set->find (QsciCommand::Redo)->setKey (0);\n  cmd_set->find (QsciCommand::SelectionUpperCase)->setKey (0);\n  cmd_set->find (QsciCommand::SelectionLowerCase)->setKey (0);\n  cmd_set->find (QsciCommand::ZoomIn)->setKey (0);\n  cmd_set->find (QsciCommand::ZoomOut)->setKey (0);\n  cmd_set->find (QsciCommand::DeleteWordLeft)->setKey (0);\n  cmd_set->find (QsciCommand::DeleteWordRight)->setKey (0);\n  cmd_set->find (QsciCommand::DeleteLineLeft)->setKey (0);\n  cmd_set->find (QsciCommand::DeleteLineRight)->setKey (0);\n  cmd_set->find (QsciCommand::LineDelete)->setKey (0);\n  cmd_set->find (QsciCommand::LineCut)->setKey (0);\n  cmd_set->find (QsciCommand::LineCopy)->setKey (0);\n#else\n  // find commands via its default key (tricky way without find ())\n  QList< QsciCommand * > cmd_list = cmd_set->commands ();\n  for (int i = 0; i < cmd_list.length (); i++)\n    {\n      int cmd_key = cmd_list.at (i)->key ();\n      switch (cmd_key)\n        {\n        case Qt::Key_C | Qt::CTRL :               // SelectionCopy\n        case Qt::Key_X | Qt::CTRL :               // SelectionCut\n        case Qt::Key_V | Qt::CTRL :               // Paste\n        case Qt::Key_A | Qt::CTRL :               // SelectAll\n        case Qt::Key_D | Qt::CTRL :               // SelectionDuplicate\n        case Qt::Key_T | Qt::CTRL :               // LineTranspose\n        case Qt::Key_Z | Qt::CTRL :               // Undo\n        case Qt::Key_Y | Qt::CTRL :               // Redo\n        case Qt::Key_Z | Qt::CTRL | Qt::SHIFT :   // Redo\n        case Qt::Key_U | Qt::CTRL :               // SelectionLowerCase\n        case Qt::Key_U | Qt::CTRL | Qt::SHIFT :   // SelectionUpperCase\n        case Qt::Key_Plus | Qt::CTRL :            // ZoomIn\n        case Qt::Key_Minus | Qt::CTRL :           // ZoomOut\n        case Qt::Key_Backspace | Qt::CTRL | Qt::SHIFT :   // DeleteLineLeft\n        case Qt::Key_Delete | Qt::CTRL | Qt::SHIFT :      // DeleteLineRight\n        case Qt::Key_K | Qt::META :                       // DeleteLineRight\n        case Qt::Key_Backspace | Qt::CTRL :       // DeleteWordLeft\n        case Qt::Key_Delete | Qt::CTRL :          // DeleteWordRight\n        case Qt::Key_L | Qt::CTRL | Qt::SHIFT :   // LineDelete\n        case Qt::Key_L | Qt::CTRL :               // LineCut\n        case Qt::Key_T | Qt::CTRL | Qt::SHIFT :   // LineCopy\n          cmd_list.at (i)->setKey (0);\n        }\n    }\n#endif\n\n#if defined (Q_OS_MAC)\n  // Octave interprets Cmd key as Meta whereas Qscintilla interprets it\n  // as Ctrl.  We thus invert Meta/Ctrl in Qscintilla's shortcuts list.\n  QList< QsciCommand * > cmd_list_mac = cmd_set->commands ();\n  for (int i = 0; i < cmd_list_mac.length (); i++)\n    {\n      // Primary key\n      int key = cmd_list_mac.at (i)->key ();\n\n      if (static_cast<int> (key | Qt::META) == key\n          && static_cast<int> (key | Qt::CTRL) != key)\n        key = (key ^ Qt::META) | Qt::CTRL;\n      else if (static_cast<int> (key | Qt::CTRL) == key)\n        key = (key ^ Qt::CTRL) | Qt::META;\n\n      cmd_list_mac.at (i)->setKey (key);\n\n      // Alternate key\n      key = cmd_list_mac.at (i)->alternateKey ();\n\n      if (static_cast<int> (key | Qt::META) == key\n          && static_cast<int> (key | Qt::CTRL) != key)\n        key = (key ^ Qt::META) | Qt::CTRL;\n      else if (static_cast<int> (key | Qt::CTRL) == key)\n        key = (key ^ Qt::CTRL) | Qt::META;\n\n      cmd_list_mac.at (i)->setAlternateKey (key);\n    }\n#endif\n\n  // selection markers\n\n  m_indicator_id = indicatorDefine (QsciScintilla::StraightBoxIndicator);\n  if (m_indicator_id == -1)\n    m_indicator_id = 1;\n\n  setIndicatorDrawUnder (true, m_indicator_id);\n\n  markerDefine (QsciScintilla::Minus, marker::selection);\n\n  // init state of undo/redo action for this tab\n  Q_EMIT status_update (isUndoAvailable (), isRedoAvailable ());\n}\n\nvoid\noctave_qscintilla::setCursorPosition (int line, int col)\n{\n  QsciScintilla::setCursorPosition (line, col);\n  Q_EMIT update_rowcol_indicator_signal (line, col);\n}\n\nvoid\noctave_qscintilla::set_selection_marker_color (const QColor& c)\n{\n  QColor ic = c;\n  ic.setAlphaF (0.45);\n  setIndicatorForegroundColor (ic, m_indicator_id);\n  setIndicatorOutlineColor (ic, m_indicator_id);\n\n  setMarkerForegroundColor (c, marker::selection);\n  setMarkerBackgroundColor (c, marker::selection);\n}\n\n// context menu requested\nvoid\noctave_qscintilla::contextMenuEvent (QContextMenuEvent *e)\n{\n#if defined (HAVE_QSCI_VERSION_2_6_0)\n  QPoint global_pos, local_pos;                         // the menu's position\n  QMenu *context_menu = createStandardContextMenu ();  // standard menu\n\n  bool in_left_margin = false;\n\n  // determine position depending on mouse or keyboard event\n  if (e->reason () == QContextMenuEvent::Mouse)\n    {\n      // context menu by mouse\n      global_pos = e->globalPos ();            // global mouse position\n      local_pos  = e->pos ();                  // local mouse position\n      if (e->x () < marginWidth (1) + marginWidth (2))\n        in_left_margin = true;\n    }\n  else\n    {\n      // context menu by keyboard or other: get point of text cursor\n      get_global_textcursor_pos (&global_pos, &local_pos);\n      QRect editor_rect = geometry ();      // editor rect mapped to global\n      editor_rect.moveTopLeft\n      (parentWidget ()->mapToGlobal (editor_rect.topLeft ()));\n      if (! editor_rect.contains (global_pos))  // is cursor outside editor?\n        global_pos = editor_rect.topLeft ();   // yes, take top left corner\n    }\n\n#  if defined (HAVE_QSCI_VERSION_2_6_0)\n  if (! in_left_margin)\n#  endif\n    {\n      // fill context menu with editor's standard actions\n      Q_EMIT create_context_menu_signal (context_menu);\n\n      // additional custom entries of the context menu\n      context_menu->addSeparator ();   // separator before custom entries\n\n      // help menu: get the position of the mouse or the text cursor\n      // (only for octave files)\n      QString lexer_name = lexer ()->lexer ();\n      if (lexer_name == \"octave\" || lexer_name == \"matlab\")\n        {\n          m_word_at_cursor = wordAtPoint (local_pos);\n          if (! m_word_at_cursor.isEmpty ())\n            {\n              context_menu->addAction (tr (\"Help on \\\"%1\\\"\").arg(m_word_at_cursor),\n                                       this, &octave_qscintilla::contextmenu_help);\n              context_menu->addAction (tr (\"Documentation on \\\"%1\\\"\").arg(m_word_at_cursor),\n                                       this, &octave_qscintilla::contextmenu_doc);\n              context_menu->addAction (tr (\"Edit \\\"%1\\\"\").arg(m_word_at_cursor),\n                                       this, &octave_qscintilla::contextmenu_edit);\n            }\n        }\n    }\n#  if defined (HAVE_QSCI_VERSION_2_6_0)\n  else\n    {\n      // remove all standard actions from scintilla\n      QList<QAction *> all_actions = context_menu->actions ();\n\n      for (auto *a : all_actions)\n        context_menu->removeAction (a);\n\n      QAction *act\n        = context_menu->addAction (tr (\"dbstop if ...\"), this,\n                                   &octave_qscintilla::contextmenu_break_condition);\n      act->setData (local_pos);\n    }\n#  endif\n\n  // finally show the menu\n  context_menu->exec (global_pos);\n\n#else\n\n  octave_unused_parameter (e);\n\n#endif\n}\n\n// common function with flag for documentation\nvoid\noctave_qscintilla::contextmenu_help_doc (bool documentation)\n{\n  if (documentation)\n    {\n      std::string name = m_word_at_cursor.toStdString ();\n\n      Q_EMIT interpreter_event\n      ([name] (interpreter& interp)\n      {\n        // INTERPRETER THREAD\n\n        F__event_manager_show_documentation__ (interp, ovl (name));\n      });\n    }\n  else\n    Q_EMIT execute_command_in_terminal_signal (\"help \" + m_word_at_cursor);\n}\n\n// call edit the function related to the current word\nvoid\noctave_qscintilla::context_edit ()\n{\n  if (get_actual_word ())\n    contextmenu_edit (true);\n}\n\n// call edit the function related to the current word\nvoid\noctave_qscintilla::context_run ()\n{\n  if (hasSelectedText ())\n    {\n      contextmenu_run (true);\n\n      Q_EMIT interpreter_event\n      ([] (interpreter&)\n      { command_editor::erase_empty_line (false); });\n    }\n}\n\nvoid\noctave_qscintilla::get_global_textcursor_pos (QPoint *global_pos,\n    QPoint *local_pos)\n{\n  long position = SendScintilla (SCI_GETCURRENTPOS);\n  long point_x  = SendScintilla (SCI_POINTXFROMPOSITION, 0, position);\n  long point_y  = SendScintilla (SCI_POINTYFROMPOSITION, 0, position);\n  *local_pos = QPoint (point_x, point_y); // local cursor position\n  *global_pos = mapToGlobal (*local_pos); // global position of cursor\n}\n\n// determine the actual word and whether we are in an octave or matlab script\nbool\noctave_qscintilla::get_actual_word ()\n{\n  QPoint global_pos, local_pos;\n  get_global_textcursor_pos (&global_pos, &local_pos);\n  m_word_at_cursor = wordAtPoint (local_pos);\n  QString lexer_name = lexer ()->lexer ();\n  return ((lexer_name == \"octave\" || lexer_name == \"matlab\")\n          && ! m_word_at_cursor.isEmpty ());\n}\n\n// helper function for clearing all indicators of a specific style\nvoid\noctave_qscintilla::clear_selection_markers ()\n{\n  int end_pos = text ().length ();\n  int end_line, end_col;\n  lineIndexFromPosition (end_pos, &end_line, &end_col);\n  clearIndicatorRange (0, 0, end_line, end_col, m_indicator_id);\n\n  markerDeleteAll (marker::selection);\n}\n\nQString\noctave_qscintilla::eol_string ()\n{\n  switch (eolMode ())\n    {\n    case QsciScintilla::EolWindows:\n      return (\"\\r\\n\");\n    case QsciScintilla::EolMac:\n      return (\"\\r\");\n    case QsciScintilla::EolUnix:\n      return (\"\\n\");\n    }\n\n  // Last resort, if the above goes wrong (should never happen)\n  return (\"\\r\\n\");\n}\n\n// Function returning the true cursor position where the tab length\n// is taken into account.\nvoid\noctave_qscintilla::get_current_position (int *pos, int *line, int *col)\n{\n  *pos = SendScintilla (QsciScintillaBase::SCI_GETCURRENTPOS);\n  *line = SendScintilla (QsciScintillaBase::SCI_LINEFROMPOSITION, *pos);\n  *col = SendScintilla (QsciScintillaBase::SCI_GETCOLUMN, *pos);\n}\n\n// Function returning the comment string of the current lexer\nQStringList\noctave_qscintilla::comment_string (bool comment)\n{\n  int lexer = SendScintilla (SCI_GETLEXER);\n\n  switch (lexer)\n    {\n#if defined (HAVE_LEXER_OCTAVE) || defined (HAVE_LEXER_MATLAB)\n#if defined (HAVE_LEXER_OCTAVE)\n    case SCLEX_OCTAVE:\n#else\n    case SCLEX_MATLAB:\n#endif\n      {\n        gui_settings settings;\n\n        int comment_string;\n\n        if (comment)\n          {\n            // The commenting string is requested\n            if (settings.contains (ed_comment_str.settings_key ()))\n              // new version (radio buttons)\n              comment_string = settings.int_value (ed_comment_str);\n            else\n              // old version (combo box)\n              comment_string = settings.value (ed_comment_str_old.settings_key (),\n                                               ed_comment_str.def ()).toInt ();\n\n            return (QStringList (ed_comment_strings.at (comment_string)));\n          }\n        else\n          {\n            QStringList c_str;\n\n            // The possible uncommenting string(s) are requested\n            comment_string = settings.int_value (ed_uncomment_str);\n\n            for (int i = 0; i < ed_comment_strings_count; i++)\n              {\n                if (1 << i & comment_string)\n                  c_str.append (ed_comment_strings.at (i));\n              }\n\n            return c_str;\n          }\n\n      }\n#endif\n\n    case SCLEX_PERL:\n    case SCLEX_BASH:\n    case SCLEX_DIFF:\n      return QStringList (\"#\");\n\n    case SCLEX_CPP:\n      return QStringList (\"//\");\n\n    case SCLEX_BATCH:\n      return QStringList (\"REM \");\n    }\n\n  return QStringList (\"%\");  // should never happen\n}\n\n// provide the style at a specific position\nint\noctave_qscintilla::get_style (int pos)\n{\n  int position;\n  if (pos < 0)\n    // The positition has to be reduced by 2 for getting the real style (?)\n    position = SendScintilla (QsciScintillaBase::SCI_GETCURRENTPOS) - 2;\n  else\n    position = pos;\n\n  return SendScintilla (QsciScintillaBase::SCI_GETSTYLEAT, position);\n}\n\n// Is a specific cursor position in a line or block comment?\nint\noctave_qscintilla::is_style_comment (int pos)\n{\n  int lexer = SendScintilla (QsciScintillaBase::SCI_GETLEXER);\n  int style = get_style (pos);\n\n  switch (lexer)\n    {\n    case SCLEX_CPP:\n      return (ST_LINE_COMMENT * (style == QsciLexerCPP::CommentLine\n                                 || style == QsciLexerCPP::CommentLineDoc)\n              + ST_BLOCK_COMMENT * (style == QsciLexerCPP::Comment\n                                    || style == QsciLexerCPP::CommentDoc\n                                    || style == QsciLexerCPP::CommentDocKeyword\n                                    || style == QsciLexerCPP::CommentDocKeywordError));\n\n#if defined (HAVE_LEXER_MATLAB)\n    case SCLEX_MATLAB:\n      return (ST_LINE_COMMENT * (style == QsciLexerMatlab::Comment));\n#endif\n#if defined (HAVE_LEXER_OCTAVE)\n    case SCLEX_OCTAVE:\n      return (ST_LINE_COMMENT * (style == QsciLexerOctave::Comment));\n#endif\n\n    case SCLEX_PERL:\n      return (ST_LINE_COMMENT * (style == QsciLexerPerl::Comment));\n\n    case SCLEX_BATCH:\n      return (ST_LINE_COMMENT * (style == QsciLexerBatch::Comment));\n\n    case SCLEX_DIFF:\n      return (ST_LINE_COMMENT * (style == QsciLexerDiff::Comment));\n\n    case SCLEX_BASH:\n      return (ST_LINE_COMMENT * (style == QsciLexerBash::Comment));\n\n    }\n\n  return ST_NONE;\n}\n\n// Do smart indentation after if, for, ...\nvoid\noctave_qscintilla::smart_indent (bool do_smart_indent, int do_auto_close,\n                                 int line, int ind_char_width)\n{\n  QString prevline = text (line);\n\n  QRegularExpression bkey {\"^[\\t ]*(if|for|while|switch\"\n                           \"|do|function|properties|events|classdef\"\n                           \"|unwind_protect|try\"\n                           \"|parfor|methods)\"\n                           \"[\\r]?[\\n\\t #%]\"};\n  // last word except for comments, assuming no ' or \" in comment.\n  // rx_end = QRegExp (\"(\\\\w+)[ \\t;\\r\\n]*([%#][^\\\"']*)?$\");\n\n  // last word except for comments,\n  // allowing % and # in single or double quoted strings\n  // FIXME: This will get confused by transpose.\n  QRegularExpression ekey {\"(?:(?:['\\\"][^'\\\"]*['\\\"])?[^%#]*)*\"\n                           \"(\\\\w+)[ \\t;\\r\\n]*(?:[%#].*)?$\"};\n\n  QRegularExpressionMatch bmatch = bkey.match (prevline);\n\n  if (bmatch.hasMatch ())\n    {\n      // Found keyword after that indentation should be added\n\n      // Check for existing end statement in the same line\n      QRegularExpressionMatch ematch = ekey.match (prevline,\n                                       bmatch.capturedStart ());\n      QString first_word = bmatch.captured (1);\n      bool inline_end = ematch.hasMatch ()\n                        && is_end (ematch.captured (1), first_word);\n\n      if (do_smart_indent && ! inline_end)\n        {\n          // Do smart indent in the current line (line+1)\n          indent (line+1);\n          setCursorPosition (line+1, indentation (line+1) / ind_char_width);\n        }\n\n      if (do_auto_close\n          && ! inline_end\n          && ! first_word.contains\n          (QRegularExpression\n      {\"(?:case|otherwise|unwind_protect_cleanup)\"}))\n      {\n        // Do auto close\n        auto_close (do_auto_close, line, prevline, first_word);\n      }\n\n      return;\n    }\n\n  QRegularExpression mkey {\"^[\\t ]*(?:else|elseif|catch|unwind_protect_cleanup)\"\n                           \"[\\r]?[\\t #%\\n]\"};\n  if (prevline.contains (mkey))\n    {\n      int prev_ind = indentation (line-1);\n      int act_ind = indentation (line);\n\n      if (prev_ind == act_ind)\n        unindent (line);\n      else if (prev_ind > act_ind)\n        {\n          setIndentation (line+1, prev_ind);\n          setCursorPosition (line+1, prev_ind);\n        }\n      return;\n    }\n\n  QRegularExpression case_key {\"^[\\t ]*(?:case|otherwise)[\\r]?[\\t #%\\n]\"};\n  if (prevline.contains (case_key) && do_smart_indent)\n    {\n      QString last_line = text (line-1);\n      int prev_ind = indentation (line-1);\n      int act_ind = indentation (line);\n\n      if (last_line.contains (QRegularExpression {\"^[\\t ]*switch\"}))\n        {\n          indent (line+1);\n          act_ind = indentation (line+1);\n        }\n      else\n        {\n          if (prev_ind == act_ind)\n            unindent (line);\n          else if (prev_ind > act_ind)\n            act_ind = prev_ind;\n        }\n\n      setIndentation (line+1, act_ind);\n      setCursorPosition (line+1, act_ind);\n    }\n\n  ekey = QRegularExpression\n  {\n    \"^[\\t ]*(?:end|endif|endfor|endwhile|until|endfunction\"\n    \"|endswitch|end_try_catch|end_unwind_protect)[\\r]?[\\t #%\\n(;]\"};\n  if (prevline.contains (ekey))\n    {\n      if (indentation (line-1) <= indentation (line))\n        {\n          unindent (line+1);\n          unindent (line);\n          if (prevline.contains (\"endswitch\"))\n            {\n              // endswitch has to me unndented twice\n              unindent (line+1);\n              unindent (line);\n            }\n          setCursorPosition (line+1,\n                             indentation (line));\n        }\n      return;\n    }\n}\n\n// Do smart indentation of current selection or line.\nvoid\noctave_qscintilla::smart_indent_line_or_selected_text (int lineFrom,\n    int lineTo)\n{\n  QRegularExpression blank_line_regexp {\"^[\\t ]*$\"};\n\n  // end[xxxxx] [# comment] at end of a line\n  QRegularExpression\n  end_word_regexp {\"(?:(?:['\\\"][^'\\\"]*['\\\"])?[^%#]*)*\"\n                   \"(?:end\\\\w*)[\\r\\n\\t ;]*(?:[%#].*)?$\"};\n\n  QRegularExpression\n  begin_block_regexp {\"^[\\t ]*(?:if|elseif|else\"\n                      \"|for|while|do|parfor\"\n                      \"|switch|case|otherwise\"\n                      \"|function\"\n                      \"|classdef|properties|events|enumeration|methods\"\n                      \"|unwind_protect|unwind_protect_cleanup|try|catch)\"\n                      \"[\\r\\n\\t #%]\"};\n\n  QRegularExpression\n  mid_block_regexp {\"^[\\t ]*(?:elseif|else\"\n                    \"|unwind_protect_cleanup|catch)\"\n                    \"[\\r\\n\\t #%]\"};\n\n  QRegularExpression\n  end_block_regexp {\"^[\\t ]*(?:end\"\n                    \"|end(for|function|if|parfor|switch|while\"\n                    \"|classdef|enumeration|events|methods|properties)\"\n                    \"|end_(try_catch|unwind_protect)\"\n                    \"|until)\"\n                    \"[\\r\\n\\t #%]\"};\n\n  QRegularExpression\n  case_block_regexp {\"^[\\t ]*(?:case|otherwise)\"\n                     \"[\\r\\n\\t #%]\"};\n\n  QRegularExpressionMatch match;\n\n  int indent_column = -1;\n  int indent_increment = indentationWidth ();\n  bool in_switch = false;\n\n  for (int line = lineFrom-1; line >= 0; line--)\n    {\n      QString line_text = text (line);\n\n      match = blank_line_regexp.match (line_text);\n      if (! match.hasMatch ())\n        {\n          // Found first non-blank line above beginning of region or\n          // current line.  Base indentation from this line, increasing\n          // indentation by indentationWidth if it looks like the\n          // beginning of a code block.\n\n          indent_column = indentation (line);\n\n          match = begin_block_regexp.match (line_text);\n          if (match.hasMatch ())\n            {\n              indent_column += indent_increment;\n              if (line_text.contains (\"switch\"))\n                in_switch = true;\n            }\n\n          break;\n        }\n    }\n\n  if (indent_column < 0)\n    indent_column = indentation (lineFrom);\n\n  QString prev_line;\n  for (int line = lineFrom; line <= lineTo; line++)\n    {\n      QString line_text = text (line);\n\n      match = end_block_regexp.match (line_text);\n      if (match.hasMatch ())\n        {\n          indent_column -= indent_increment;\n          if (line_text.contains (\"endswitch\"))\n            {\n              // need a double de-indent for endswitch\n              if (in_switch)\n                indent_column -= indent_increment;\n              in_switch = false;\n            }\n        }\n\n      match = mid_block_regexp.match (line_text);\n      if (match.hasMatch ())\n        indent_column -= indent_increment;\n\n      match = case_block_regexp.match (line_text);\n      if (match.hasMatch ())\n        {\n          match = case_block_regexp.match (prev_line);\n          if (! match.hasMatch ()\n              && ! prev_line.contains (\"switch\"))\n            indent_column -= indent_increment;\n          in_switch = true;\n        }\n\n      setIndentation (line, indent_column);\n\n      match = begin_block_regexp.match (line_text);\n      if (match.hasMatch ())\n        {\n          // Check for existing end statement in the same line\n          match = end_word_regexp.match (line_text, match.capturedStart ());\n          if (! match.hasMatch ())\n            indent_column += indent_increment;\n          if (line_text.contains (\"switch\"))\n            in_switch = true;\n        }\n\n      match = blank_line_regexp.match (line_text);\n      if (! match.hasMatch ())\n        prev_line = line_text;\n    }\n}\n\nvoid\noctave_qscintilla::set_word_selection (const QString& word)\n{\n  m_selection = word;\n\n  if (word.isEmpty ())\n    {\n      m_selection_line = -1;\n      m_selection_col = -1;\n\n      m_selection_replacement = \"\";\n\n      clear_selection_markers ();\n\n      QToolTip::hideText ();\n    }\n  else\n    {\n      int pos;\n      get_current_position (&pos, &m_selection_line, &m_selection_col);\n    }\n}\n\nvoid\noctave_qscintilla::show_selection_markers (int l1, int c1, int l2, int c2)\n{\n  fillIndicatorRange (l1, c1, l2, c2, m_indicator_id);\n\n  if (l1 == l2)\n    markerAdd (l1, marker::selection);\n}\n\nvoid\noctave_qscintilla::contextmenu_help (bool)\n{\n  contextmenu_help_doc (false);\n}\n\nvoid\noctave_qscintilla::contextmenu_doc (bool)\n{\n  contextmenu_help_doc (true);\n}\n\nvoid\noctave_qscintilla::context_help_doc (bool documentation)\n{\n  if (get_actual_word ())\n    contextmenu_help_doc (documentation);\n}\n\nvoid\noctave_qscintilla::contextmenu_edit (bool)\n{\n  Q_EMIT context_menu_edit_signal (m_word_at_cursor);\n}\n\nvoid\noctave_qscintilla::contextmenu_run_temp_error ()\n{\n  QMessageBox::critical (this, tr (\"Octave Editor\"),\n                         tr (\"Creating temporary files failed.\\n\"\n                             \"Make sure you have write access to temp. directory\\n\"\n                             \"%1\\n\\n\"\n                             \"\\\"Run Selection\\\" requires temporary files.\").arg (QDir::tempPath ()));\n}\n\nvoid\noctave_qscintilla::contextmenu_run (bool)\n{\n  // Take selected code and extend it by commands for echoing each\n  // evaluated line and for adding the line to the history (use script)\n  QString code = QString ();\n  QString hist = QString ();\n\n  // Split contents into single lines and complete commands\n  QStringList lines = selectedText ().split (QRegularExpression {\"[\\r\\n]\"},\n#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)\n                      Qt::SkipEmptyParts);\n#else\n                      QString::SkipEmptyParts);\n#endif\n  for (int i = 0; i < lines.count (); i++)\n    {\n      QString line = lines.at (i);\n\n      if (line.trimmed ().isEmpty ())\n        continue;\n\n      if (line.startsWith (\"%!\"))   // Handle tests and demos\n        {\n          // Do not remove \"%!\" if keyword (e.g., \"test\", \"demo\", etc.) is\n          // directly following.  Exception is \"assert\".\n          // assert might be used without leading space\n          line.replace (QRegularExpression (\"^%!assert(\\\\s*)([^\\\\s]+)\"),\n                        \"assert\\\\1\\\\2\");\n          // Remove \"%! \" from body of test/demo block\n          line.replace (QRegularExpression (\"^%!\\\\s+\"), \"\");\n        }\n\n      QString line_escaped = line;\n      line_escaped.replace (QString (\"'\"), QString (\"''\"));\n      QString line_history = line;\n\n      // Add codeline\n      code += line + \"\\n\";\n      hist += line_history + \"\\n\";\n    }\n\n  octave_stdout << hist.toStdString ();\n\n  // Create tmp file with the code to be executed by the interpreter\n  QPointer<QTemporaryFile> tmp_file = create_tmp_file (\"m\", code);\n\n  if (tmp_file && tmp_file->open ())\n    tmp_file->close ();\n  else\n    {\n      // tmp files not working: use old way to run selection\n      contextmenu_run_temp_error ();\n      return;\n    }\n\n  // Store file in settings in order to avoid opening it in editor\n  gui_settings settings;\n  settings.setValue (ed_run_selection_tmp_file.settings_key (), tmp_file->fileName ());\n\n  // Create tmp file required for adding command to history\n  QPointer<QTemporaryFile> tmp_hist = create_tmp_file (\"\", hist);\n\n  if (tmp_hist && tmp_hist->open ())\n    tmp_hist->close ();\n  else\n    {\n      // tmp files not working: use old way to run selection\n      contextmenu_run_temp_error ();\n      return;\n    }\n\n  // Add commands to the history\n  Q_EMIT interpreter_event\n  ([tmp_hist] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n\n    if (tmp_hist.isNull ())\n      return;\n\n    std::string opt = \"-r\";\n    std::string path = tmp_hist->fileName ().toStdString ();\n\n    Fhistory (interp, ovl (opt, path));\n  });\n\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<octave_qscintilla> this_oq (this);\n\n  // Let the interpreter execute the tmp file\n  Q_EMIT interpreter_event\n  ([this, this_oq, tmp_file, tmp_hist] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n\n    // FIXME: For now, just skip the entire callback if THIS_OQ is\n    // no longer valid.  Maybe there is a better way to do this\n    // job?\n\n    if (this_oq.isNull ())\n      return;\n\n    std::string file = tmp_file->fileName ().toStdString ();\n\n    std::string pending_input = command_editor::get_current_line ();\n\n    int err_line = -1;   // For storing the line of a poss. error\n\n    // Get current state of auto command repeat in debug mode\n    octave_value_list ovl_dbg = Fisdebugmode (interp);\n    bool dbg = ovl_dbg(0).bool_value ();\n    octave_value_list ovl_auto_repeat = ovl (true);\n    if (dbg)\n      ovl_auto_repeat = Fauto_repeat_debug_command (interp, ovl (false), 1);\n    bool auto_repeat = ovl_auto_repeat(0).bool_value ();\n\n    try\n      {\n        // Do the job\n        interp.source_file (file);\n      }\n    catch (const execution_exception& ee)\n      {\n        // Catch errors otherwise the rest of the interpreter\n        // will not be executed (cleaning up).\n\n        // New error message and error stack\n        QString new_msg = QString::fromStdString (ee.message ());\n        std::list<frame_info> stack = ee.stack_info ();\n\n        // Remove line and column from first line of error message only\n        // if it is related to the tmp itself, i.e., only if\n        // the error stack size is 0, 1, or, if in debug mode, 2\n        size_t max_stack_size = 1;\n        if (dbg)\n          max_stack_size = 2;\n        if (stack.size () <= max_stack_size)\n          {\n            QRegularExpression rx {\"source: error sourcing file [^\\\\n\\\\:]*\"};\n            if (new_msg.contains (rx))\n              {\n                // Selected code has syntax errors\n                new_msg.replace (rx, \"error sourcing selected code\");\n                err_line = 0;  // Nothing into history?\n              }\n            else\n              {\n                // Normal error, detect line and remove file\n                // name from message\n                QStringList rx_list;\n                rx_list << \"near line (\\\\d+),[^\\n]*\\n\";\n                rx_list << \"near line (\\\\d+),[^\\n]*$\";\n\n                QStringList replace_list;\n                replace_list << \"\\n\";\n                replace_list << \"\";\n\n                for (int i = 0; i < rx_list.length (); i++)\n                  {\n                    rx = QRegularExpression {rx_list.at (i)};\n                    QRegularExpressionMatch match = rx.match (new_msg);\n                    if (match.hasMatch ())\n                      {\n                        err_line = match.captured (1).toInt ();\n                        new_msg = new_msg.replace (rx, replace_list.at (i));\n                      }\n                  }\n              }\n          }\n\n        // Drop first stack level, which is the temporary function file,\n        // or, if in debug mode, drop first two stack levels\n        if (stack.size () > 0)\n          stack.pop_back ();\n        if (dbg && (stack.size () > 0))\n          stack.pop_back ();\n\n        // Clean up before throwing the modified error.\n        Q_EMIT ctx_menu_run_finished_signal (err_line,\n                                             tmp_file, tmp_hist,\n                                             dbg, auto_repeat);\n\n        // New exception with updated message and stack\n        execution_exception nee (ee.err_type (), ee.identifier (),\n                                 new_msg.toStdString (), stack);\n\n        // Throw\n        throw (nee);\n      }\n\n    // Clean up\n\n    Q_EMIT ctx_menu_run_finished_signal (err_line,\n                                         tmp_file, tmp_hist,\n                                         dbg, auto_repeat);\n\n    command_editor::erase_empty_line (true);\n    command_editor::replace_line (\"\");\n    command_editor::set_initial_input (pending_input);\n    command_editor::redisplay ();\n    command_editor::interrupt_event_loop ();\n    command_editor::accept_line ();\n    command_editor::erase_empty_line (true);\n\n  });\n}\n\nvoid octave_qscintilla::ctx_menu_run_finished\n(int, QPointer<QTemporaryFile> tmp_file,\n QPointer<QTemporaryFile> tmp_hist, bool dbg, bool auto_repeat)\n{\n  Q_EMIT focus_console_after_command_signal ();\n\n  // TODO: Use line nr. (int argument) of possible error for removing\n  //       lines from history that were never executed.  For this,\n  //       possible lines from commands at a debug prompt must be\n  //       taken into consideration.\n\n  if (tmp_file && tmp_file->exists ())\n    {\n      tmp_file->remove ();\n      gui_settings settings;\n      settings.setValue (ed_run_selection_tmp_file.settings_key (), QString ());\n    }\n\n  if (tmp_hist && tmp_hist->exists ())\n    tmp_hist->remove ();\n\n  Q_EMIT interpreter_event\n  ([dbg, auto_repeat] (interpreter& interp)\n  {\n    // INTERPRETER THREAD\n    if (dbg)\n      Fauto_repeat_debug_command (interp, ovl (auto_repeat));\n  });\n}\n\n// wrappers for dbstop related context menu items\n\n// FIXME: Why can't the data be sent as the argument to the function???\nvoid\noctave_qscintilla::contextmenu_break_condition (bool)\n{\n#if defined (HAVE_QSCI_VERSION_2_6_0)\n  QAction *action = qobject_cast<QAction *>(sender ());\n  QPoint local_pos = action->data ().value<QPoint> ();\n\n  // pick point just right of margins, so lineAt doesn't give -1\n  int margins = marginWidth (1) + marginWidth (2) + marginWidth (3);\n  local_pos = QPoint (margins + 1, local_pos.y ());\n\n  Q_EMIT context_menu_break_condition_signal (lineAt (local_pos));\n#endif\n}\n\nvoid\noctave_qscintilla::contextmenu_break_once (const QPoint& local_pos)\n{\n#if defined (HAVE_QSCI_VERSION_2_6_0)\n  Q_EMIT context_menu_break_once (lineAt (local_pos));\n#else\n  octave_unused_parameter (local_pos);\n#endif\n}\n\nvoid\noctave_qscintilla::text_changed ()\n{\n  Q_EMIT status_update (isUndoAvailable (), isRedoAvailable ());\n}\n\nvoid\noctave_qscintilla::cursor_position_changed (int line, int col)\n{\n  // Clear the selection if we move away from it.  We have to check the\n  // position, because we allow entering text at the point of the\n  // selection to trigger a search and replace that does not clear the\n  // selection until it is complete.\n\n  if (! m_selection.isEmpty ()\n      && (line != m_selection_line || col != m_selection_col))\n    set_word_selection ();\n}\n\n// when edit area gets focus update information on undo/redo actions\nvoid\noctave_qscintilla::focusInEvent (QFocusEvent *focusEvent)\n{\n  Q_EMIT status_update (isUndoAvailable (), isRedoAvailable ());\n\n  QsciScintilla::focusInEvent (focusEvent);\n}\n\nvoid\noctave_qscintilla::show_replace_action_tooltip ()\n{\n  int pos;\n  get_current_position (&pos, &m_selection_line, &m_selection_col);\n\n  // Offer to replace other instances.\n\n  QKeySequence keyseq = Qt::SHIFT | Qt::Key_Return;\n\n  QString msg = (tr (\"Press '%1' to replace all occurrences of '%2' with '%3'.\")\n                 . arg (keyseq.toString ())\n                 . arg (m_selection)\n                 . arg (m_selection_replacement));\n\n  QPoint global_pos;\n  QPoint local_pos;\n\n  get_global_textcursor_pos (&global_pos, &local_pos);\n\n  QFontMetrics ttfm (QToolTip::font ());\n\n  // Try to avoid overlapping with the text completion dialog\n  // and the text that is currently being edited.\n\n  global_pos += QPoint (2*ttfm.maxWidth (), -3*ttfm.height ());\n\n  QToolTip::showText (global_pos, msg);\n}\n\nvoid\noctave_qscintilla::replace_all (const QString& o_str, const QString& n_str,\n                                bool re, bool cs, bool wo)\n{\n  // get the resulting cursor position\n  int pos, line, col, nline, ncol;\n  get_current_position (&pos, &line, &col);\n\n  // remember first visible line for restoring the view afterwards\n  int first_line = firstVisibleLine ();\n\n  // search for first occurrence of the detected word\n  bool find_result_available = findFirst (o_str, re, cs, wo,\n                                          false, true, 0, 0);\n  // replace and find more occurrences in a loop\n  beginUndoAction ();\n  while (find_result_available)\n    {\n      // findNext doesn't work properly if the length of the replacement\n      // text is different from the original\n      replace (n_str);\n      get_current_position (&pos, &nline, &ncol);\n\n      find_result_available = findFirst (o_str, re, cs, wo,\n                                         false, true, nline, ncol);\n    }\n  endUndoAction ();\n\n  // restore the visible area\n  setFirstVisibleLine (first_line);\n\n  // fix cursor column if outside of new line length\n  int eol_len = eol_string ().length ();\n  if (line == lines () - 1)\n    eol_len = 0;\n  const int col_max = text (line).length () - eol_len;\n  if (col_max < col)\n    col = col_max;\n\n  setCursorPosition (line, col);\n}\n\nbool\noctave_qscintilla::event (QEvent *e)\n{\n  if (m_debug_mode && e->type () == QEvent::ToolTip)\n    {\n      // FIXME: can we handle display of a tooltip using an\n      // interpreter event or a custom signal/slot connection?\n\n      QHelpEvent *help_e = static_cast<QHelpEvent *> (e);\n      QString symbol = wordAtPoint (help_e->pos ());\n\n      Q_EMIT show_symbol_tooltip_signal (help_e->globalPos (), symbol);\n\n      return true;\n    }\n\n  return QsciScintilla::event (e);\n}\n\nvoid\noctave_qscintilla::keyPressEvent (QKeyEvent *key_event)\n{\n  if (m_selection.isEmpty ())\n    QsciScintilla::keyPressEvent (key_event);\n  else\n    {\n      int key = key_event->key ();\n      Qt::KeyboardModifiers modifiers = key_event->modifiers ();\n\n      if (key == Qt::Key_Return && modifiers == Qt::ShiftModifier)\n        {\n          replace_all (m_selection, m_selection_replacement,\n                       false, true, true);\n\n          // Clear the selection.\n          set_word_selection ();\n        }\n      else\n        {\n          // The idea here is to allow backspace to remove the last\n          // character of the replacement text to allow minimal editing\n          // and to also end the selection replacement action if text is\n          // not valid as a word constituent (control characters,\n          // etc.).  Is there a better way than having special cases for\n          // DEL and ESC here?\n\n          QString text = key_event->text ();\n\n          bool cancel_replacement = false;\n\n          if (key == Qt::Key_Backspace)\n            {\n              if (m_selection_replacement.isEmpty ())\n                cancel_replacement = true;\n              else\n                m_selection_replacement.chop (1);\n            }\n          else if (key == Qt::Key_Delete || key == Qt::Key_Escape)\n            cancel_replacement = true;\n          else if (! text.isEmpty ())\n            m_selection_replacement += text;\n          else if (modifiers != Qt::ShiftModifier)\n            cancel_replacement = true;\n\n          // Perform default action.\n\n          QsciScintilla::keyPressEvent (key_event);\n\n          if (cancel_replacement)\n            set_word_selection ();\n\n          if (! m_selection_replacement.isEmpty ())\n            show_replace_action_tooltip ();\n        }\n    }\n}\n\nvoid\noctave_qscintilla::auto_close (int auto_endif, int linenr,\n                               const QString& line, QString& first_word)\n{\n  // Insert an \"end\" for an \"if\" etc., if needed.\n  // (Use of \"while\" allows \"return\" to skip the rest.\n  // It may be clearer to use \"if\" and \"goto\",\n  // but that violates the coding standards.)\n\n  bool autofill_simple_end = (auto_endif == 2);\n\n  std::size_t start = line.toStdString ().find_first_not_of (\" \\t\");\n\n  // Check if following line has the same or less indentation\n  // Check if the following line does not start with\n  //       end* (until) (catch)\n  if (linenr < lines () - 1)\n    {\n      int offset = 2;     // linenr is the old line, thus, linnr+1 is the\n                          // new one and can not be taken into account\n      std::size_t next_start;\n      QString next_line;\n\n      do                            // find next non-blank line\n        {\n          next_line = text (linenr + offset++);\n          next_start = next_line.toStdString ().find_first_not_of (\" \\t\\n\");\n        }\n      while (linenr + offset < lines ()\n             && next_start == std::string::npos);\n\n      if (next_start == std::string::npos)\n        next_start = 0;\n      if (start == 0 && next_start == 0)\n        return;                     // bug #56160, don't add at 0\n      if (next_start > start)       // more indented => don't add \"end\"\n        return;\n      if (next_start == start)      // same => check if already is \"end\"\n        {\n          QRegularExpression rx_start {R\"((\\w+))\"};\n          QRegularExpressionMatch match = rx_start.match (next_line, start);\n          if (match.hasMatch () && is_end (match.captured (1), first_word))\n            return;\n        }\n    }\n\n  // If all of the above, insert a new line, with matching indent\n  // and either 'end' or 'end...', depending on a flag.\n\n  // If we insert directly after the last line, the \"end\" is autoindented,\n  // so add a dummy line.\n  if (linenr + 2 == lines ())\n    insertAt (QString (\"\\n\"), linenr + 2, 0);\n\n  // For try/catch/end, fill \"end\" first, so \"catch\" is top of undo stack\n  if (first_word == \"try\")\n    insertAt (QString (start, ' ')\n              + (autofill_simple_end ? \"end\\n\" : \"end_try_catch\\n\"),\n              linenr + 2, 0);\n  else if (first_word == \"unwind_protect\")\n    insertAt (QString (start, ' ')\n              + (autofill_simple_end ? \"end\\n\" : \"end_unwind_protect\\n\"),\n              linenr + 2, 0);\n\n  QString next_line;\n  if (first_word == \"do\")\n    next_line = \"until\\n\";\n  else if (first_word == \"try\")\n    next_line = \"catch\\n\";\n  else if (first_word == \"unwind_protect\")\n    next_line = \"unwind_protect_cleanup\\n\";\n  else if (autofill_simple_end)\n    next_line = \"end\\n\";\n  else\n    {\n      if (first_word == \"unwind_protect\")\n        first_word = '_' + first_word;\n      next_line = \"end\" + first_word + \"\\n\";\n    }\n\n  //insertAt (QString (start, ' ') + next_line, linenr + 2, 0);\n  insertAt (next_line, linenr + 2, 0);\n  setIndentation (linenr + 2, indentation (linenr));\n}\n\nvoid\noctave_qscintilla::dragEnterEvent (QDragEnterEvent *e)\n{\n  // if is not dragging a url, pass to qscintilla to handle,\n  // otherwise ignore it so that it will be handled by\n  // the parent\n  if (!e->mimeData ()->hasUrls ())\n    {\n      QsciScintilla::dragEnterEvent (e);\n    }\n  else\n    {\n      e->ignore ();\n    }\n}\n\nvoid\noctave_qscintilla::handle_enter_debug_mode ()\n{\n  m_debug_mode = true;\n}\n\nvoid\noctave_qscintilla::handle_exit_debug_mode ()\n{\n  m_debug_mode = false;\n}\n\nQPointer<QTemporaryFile>\noctave_qscintilla::create_tmp_file (const QString& extension,\n                                    const QString& contents)\n{\n  QString ext = extension;\n  if ((! ext.isEmpty ()) && (! ext.startsWith ('.')))\n    ext = QString (\".\") + ext;\n\n  // Create octave dir within temp. dir\n  QString tmp_dir = QString::fromStdString (sys::env::get_temp_directory ());\n\n  QString tmp_name = tmp_dir + QDir::separator() + \"octave_XXXXXX\" + ext;\n\n  QPointer<QTemporaryFile> tmp_file (new QTemporaryFile (tmp_name, this));\n\n  if (! contents.isEmpty () && tmp_file && tmp_file->open ())\n    {\n      tmp_file->write (contents.toUtf8 ());\n      tmp_file->close ();\n    }\n\n  return tmp_file;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/octave-qscintilla.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_octave_qscintilla_h)\n#define octave_octave_qscintilla_h 1\n\n#include <QContextMenuEvent>\n#include <QKeyEvent>\n#include <QLabel>\n#include <QMenu>\n#include <QPointer>\n#include <QTemporaryFile>\n#include <Qsci/qsciscintilla.h>\n\n#include \"gui-settings.h\"\n#include \"qt-interpreter-events.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass octave_qscintilla : public QsciScintilla\n{\n  Q_OBJECT\n\npublic:\n\n  octave_qscintilla (QWidget *p);\n\n  ~octave_qscintilla () = default;\n\n  enum\n  {\n    ST_NONE = 0,\n    ST_LINE_COMMENT,\n    ST_BLOCK_COMMENT\n  };\n\n  virtual void contextMenuEvent (QContextMenuEvent *e);\n  virtual void setCursorPosition (int line, int col);\n\n  void context_help_doc (bool);\n  void context_edit ();\n  void context_run ();\n  void get_global_textcursor_pos (QPoint *global_pos, QPoint *local_pos);\n  bool get_actual_word ();\n  void clear_selection_markers ();\n  QString eol_string ();\n  void get_current_position (int *pos, int *line, int *col);\n  QStringList comment_string (bool comment = true);\n  int get_style (int pos = -1);\n  int is_style_comment (int pos = -1);\n  void smart_indent (bool do_smart_indent, int do_auto_close,\n                     int line, int ind_char_width);\n\n  void smart_indent_line_or_selected_text (int lineFrom, int lineTo);\n\n  void set_word_selection (const QString& word = QString ());\n\n  void show_selection_markers (int l1, int c1, int l2, int c2);\n\n  void set_selection_marker_color (const QColor& c);\n\n  void replace_all (const QString& o_str, const QString& n_str,\n                    bool re, bool cs, bool wo);\n\nQ_SIGNALS:\n\n  void update_rowcol_indicator_signal (int line, int col);\n  void execute_command_in_terminal_signal (const QString&);\n  void create_context_menu_signal (QMenu *);\n  void context_menu_edit_signal (const QString&);\n  void qsci_has_focus_signal (bool);\n  void status_update (bool, bool);\n  void show_doc_signal (const QString&);\n  void show_symbol_tooltip_signal (const QPoint&, const QString&);\n  void context_menu_break_condition_signal (int);\n  void context_menu_break_once (int);\n  void ctx_menu_run_finished_signal (int, QPointer<QTemporaryFile>,\n                                     QPointer<QTemporaryFile>, bool, bool);\n  void focus_console_after_command_signal ();\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  void handle_enter_debug_mode ();\n  void handle_exit_debug_mode ();\n\nprivate Q_SLOTS:\n\n  void ctx_menu_run_finished (int, QPointer<QTemporaryFile>,\n                              QPointer<QTemporaryFile>, bool, bool);\n\n  void contextmenu_help (bool);\n  void contextmenu_doc (bool);\n  void contextmenu_help_doc (bool);\n  void contextmenu_edit (bool);\n  void contextmenu_run (bool);\n  void contextmenu_run_temp_error ();\n\n  void contextmenu_break_condition (bool);\n  void contextmenu_break_once (const QPoint&);\n\n  void text_changed ();\n  void cursor_position_changed (int, int);\n\nprotected:\n\n  void focusInEvent (QFocusEvent *focusEvent);\n\n  void show_replace_action_tooltip ();\n\n  bool event (QEvent *e);\n\n  void keyPressEvent (QKeyEvent *e);\n\n  void dragEnterEvent (QDragEnterEvent *e);\n\nprivate:\n\n  void auto_close (int auto_endif, int l,\n                   const QString& line, QString& first_word);\n\n  QPointer<QTemporaryFile> create_tmp_file (const QString& extension,\n      const QString& contents);\n\n  bool m_debug_mode;\n\n  QString m_word_at_cursor;\n\n  QString m_selection;\n  QString m_selection_replacement;\n  int m_selection_line;\n  int m_selection_col;\n  int m_indicator_id;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/octave-txt-lexer.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2014-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_QSCINTILLA)\n\n#include <Qsci/qscilexer.h>\n\n#include \"octave-txt-lexer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nQString octave_txt_lexer::description (int style) const\n{\n  if (style == 0)\n    return tr (\"Default\");\n  else\n    return QString ();\n};\n\nconst char *\noctave_txt_lexer::language () const\n{\n  return \"Text\";\n}\n\nconst char *\noctave_txt_lexer::lexer () const\n{\n  return \"text\";\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/m-editor/octave-txt-lexer.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_octave_txt_lexer_h)\n#define octave_octave_txt_lexer_h 1\n\n#include <Qsci/qsciscintilla.h>\n#include <Qsci/qscilexer.h>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass octave_txt_lexer : public QsciLexer\n{\n  Q_OBJECT\n\npublic:\n\n  virtual const char * language () const;\n\n  virtual const char * lexer () const;\n\n  virtual QString description (int style) const;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/main-window.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n\n#include <QAction>\n#include <QApplication>\n#include <QClipboard>\n#include <QDateTime>\n#include <QDebug>\n#include <QDesktopServices>\n#include <QFileDialog>\n#include <QIcon>\n#include <QInputDialog>\n#include <QKeySequence>\n#include <QLabel>\n#include <QMenu>\n#include <QMenuBar>\n#include <QMessageBox>\n#include <QScreen>\n#include <QStyle>\n#include <QStyleFactory>\n#include <QTextBrowser>\n#include <QTextStream>\n#include <QThread>\n#include <QTimer>\n#include <QToolBar>\n#include <QWindow>\n\n// QTerminal includes\n#include \"QTerminal.h\"\n\n#include \"gui-preferences-cs.h\"\n#include \"gui-preferences-dw.h\"\n#include \"gui-preferences-ed.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-mw.h\"\n#include \"gui-preferences-nr.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-settings.h\"\n#if defined (HAVE_QSCINTILLA)\n#  include \"file-editor.h\"\n#  include \"command-widget.h\"\n#endif\n#include \"gui-utils.h\"\n#include \"interpreter-qobject.h\"\n#include \"main-window.h\"\n#include \"news-reader.h\"\n#include \"octave-qobject.h\"\n#include \"octave-qt-features.h\"\n#include \"settings-dialog.h\"\n#include \"welcome-wizard.h\"\n\n#include \"cmd-edit.h\"\n#include \"oct-env.h\"\n#include \"url-transfer.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"defaults.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"utils.h\"\n#include \"syminfo.h\"\n#include \"version.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nmain_window::main_window (base_qobject& oct_qobj)\n  : QMainWindow (), m_octave_qobj (oct_qobj),\n    m_status_bar (nullptr),\n    m_command_window (nullptr),\n    m_history_window (nullptr),\n    m_file_browser_window (nullptr),\n    m_editor_window (nullptr),\n    m_workspace_window (nullptr),\n    m_external_editor (new external_editor_interface (this)),\n    m_active_editor (m_external_editor), m_settings_dlg (nullptr),\n    m_find_files_dlg (nullptr), m_set_path_dlg (nullptr),\n    m_clipboard (QApplication::clipboard ()),\n    m_prevent_readline_conflicts (true),\n    m_prevent_readline_conflicts_menu (false),\n    m_suppress_dbg_location (true),\n    m_closing (false), m_file_encoding (QString ())\n{\n  gui_settings settings;\n\n  if (! settings.bool_value (global_skip_welcome_wizard))\n    {\n      // Before wizard.\n      m_octave_qobj.config_translators ();\n\n      welcome_wizard welcomeWizard;\n\n      if (welcomeWizard.exec () == QDialog::Rejected)\n        std::exit (EXIT_FAILURE);\n\n      settings.setValue (global_skip_welcome_wizard.settings_key (), QVariant (true));\n\n      // Install settings file.\n      settings.reload ();\n    }\n  else\n    {\n      // Get settings file.\n      settings.reload ();\n\n      // After settings.\n      m_octave_qobj.config_translators ();\n\n      if (settings.bool_value (global_show_splash_screen))\n        {\n          splash_screen *splash = new splash_screen ();\n          splash->setWindowFlags(Qt::SplashScreen);\n          QTimer::singleShot (1000, this, [splash] () { splash->close (); });\n          // FIXME: exec() stops execiton for 1s (see timer above)\n          //        show() or open() should be used instead, but then the\n          //        splash screen is empty until the main window shows up,\n          //        despite using repaint() and qApp::processEvents().\n          splash->exec ();\n        }\n    }\n\n  setObjectName (gui_obj_name_main_window);\n\n  settings.config_icon_theme ();\n\n  settings.update_network_settings ();\n\n  // We provide specific terminal capabilities, so ensure that\n  // TERM is always set appropriately.\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  sys::env::putenv (\"TERM\", \"cygwin\");\n#else\n  sys::env::putenv (\"TERM\", \"xterm\");\n#endif\n\n  construct_central_widget ();\n\n  m_status_bar = new QStatusBar (this);\n  m_profiler_status_indicator = new led_indicator ();\n  QLabel *text = new QLabel (tr (\"Profiler\"));\n  m_status_bar->addPermanentWidget (text);\n  m_status_bar->addPermanentWidget (m_profiler_status_indicator);\n\n  adopt_dock_widgets ();\n\n  QGuiApplication::setDesktopFileName (\"org.octave.Octave\");\n\n  bool connect_to_web = true;\n  QDateTime last_checked;\n  int serial = 0;\n  m_active_dock = nullptr;\n\n  connect_to_web = settings.bool_value (nr_allow_connection);\n  last_checked = settings.date_time_value (nr_last_time);\n  serial = settings.int_value (nr_last_news);\n  m_default_encoding = settings.string_value (ed_default_enc);\n\n  QDateTime current = QDateTime::currentDateTime ();\n  QDateTime one_day_ago = current.addDays (-1);\n\n  if (connect_to_web\n      && (! last_checked.isValid () || one_day_ago > last_checked))\n    Q_EMIT show_community_news_signal (serial);\n\n  construct_octave_qt_link ();\n\n  // We have to set up all our windows, before we finally launch\n  // octave.\n\n  construct ();\n\n  read_settings ();\n\n  init_terminal_size ();\n\n  Q_EMIT init_window_menu ();\n\n  // This only works reliably if the event loop is idle.s\n  QTimer::singleShot (0, this, SLOT (focus_command_window ()));\n}\n\nmain_window::~main_window () { }\n\nvoid\nmain_window::adopt_dock_widgets ()\n{\n  adopt_terminal_widget ();\n  adopt_documentation_widget ();\n  adopt_file_browser_widget ();\n  adopt_history_widget ();\n  adopt_workspace_widget ();\n  adopt_editor_widget ();\n  adopt_variable_editor_widget ();\n\n  m_previous_dock = m_command_window;\n}\n\nvoid\nmain_window::adopt_terminal_widget ()\n{\n  m_command_window = m_octave_qobj.terminal_widget (this);\n\n  make_dock_widget_connections (m_command_window);\n\n  connect (this, &main_window::settings_changed,\n           m_command_window, &terminal_dock_widget::notice_settings);\n\n  if (! m_octave_qobj.experimental_terminal_widget ())\n    {\n      QTerminal *cmd_widget = m_command_window->get_qterminal ();\n\n      // The following connections were previously made in\n      // QTerminal::construct, QWinTerminalImpl::QWinTerminalImpl, and\n      // QUnixTerminalImpl::QUnixTerminalImpl.  Similar actions should\n      // probably be possible for the new command widget.\n\n      connect (cmd_widget, &QTerminal::report_status_message,\n               this, &main_window::report_status_message);\n\n      connect (cmd_widget, &QTerminal::edit_mfile_request,\n               this, &main_window::edit_mfile);\n\n      connect (cmd_widget, &QTerminal::execute_command_in_terminal_signal,\n               this, &main_window::execute_command_in_terminal);\n\n      connect (this, &main_window::init_terminal_size_signal,\n               cmd_widget, &QTerminal::init_terminal_size);\n\n      connect (this, &main_window::copyClipboard_signal,\n               cmd_widget, &QTerminal::copyClipboard);\n\n      connect (this, &main_window::pasteClipboard_signal,\n               cmd_widget, &QTerminal::pasteClipboard);\n\n      connect (this, &main_window::selectAll_signal,\n               cmd_widget, &QTerminal::selectAll);\n\n      connect (cmd_widget, &QTerminal::request_edit_mfile_signal,\n               this, &main_window::edit_mfile);\n\n      connect (cmd_widget, &QTerminal::request_open_file_signal,\n               this, qOverload<const QString&, const QString&, int> (&main_window::open_file_signal));\n\n      connect (cmd_widget, &QTerminal::set_screen_size_signal,\n               this, &main_window::set_screen_size);\n\n      connect (cmd_widget, &QTerminal::clear_command_window_request,\n               this, &main_window::handle_clear_command_window_request);\n    }\n  else\n    {\n      connect (this, &main_window::execute_command_signal,\n               m_command_window, &terminal_dock_widget::execute_command_signal);\n\n      connect (this, &main_window::get_input_from_terminal_signal,\n               m_command_window, &terminal_dock_widget::get_input_from_terminal_signal);\n\n      connect (m_command_window, &terminal_dock_widget::finished_input_from_terminal_signal,\n               this, &main_window::finished_input_from_terminal_signal);\n\n    }\n}\n\nvoid\nmain_window::adopt_documentation_widget ()\n{\n  m_doc_browser_window = m_octave_qobj.documentation_widget (this);\n\n  make_dock_widget_connections (m_doc_browser_window);\n}\n\nvoid\nmain_window::adopt_file_browser_widget ()\n{\n  m_file_browser_window = m_octave_qobj.file_browser_widget (this);\n\n  m_file_browser = m_file_browser_window->get_file_system_browser ();\n  m_editor_files = m_file_browser_window->get_editor_files_browser ();\n\n  make_dock_widget_connections (m_file_browser_window);\n\n  connect (m_file_browser, &file_system_browser::open_file,\n           this, qOverload<const QString&> (&main_window::open_file_signal));\n  connect (m_file_browser,\n           &file_system_browser::displayed_directory_changed,\n           this, &main_window::set_current_working_directory);\n\n  connect (m_file_browser, &file_system_browser::modify_path_signal,\n           this, &main_window::modify_path);\n\n  connect (m_file_browser, &file_system_browser::run_file_signal,\n           this, &main_window::run_file_in_terminal);\n\n  connect (m_file_browser, &file_system_browser::load_file_signal,\n           this, &main_window::handle_load_workspace_request);\n\n  connect (m_file_browser, &file_system_browser::open_any_signal,\n           this, &main_window::handle_open_any_request);\n\n  connect (m_file_browser, &file_system_browser::find_files_signal,\n           this, &main_window::find_files);\n\n  connect (m_editor_files,\n           &editor_files_browser::displayed_directory_changed,\n           this, &main_window::set_current_working_directory);\n\n  connect (m_editor_files, &editor_files_browser::run_file_signal,\n           this, &main_window::run_file_in_terminal);\n}\n\nvoid\nmain_window::adopt_history_widget ()\n{\n  m_history_window = m_octave_qobj.history_widget (this);\n\n  make_dock_widget_connections (m_history_window);\n\n  connect (m_history_window, &history_dock_widget::command_create_script,\n           this, &main_window::new_file_signal);\n\n  connect (m_history_window, &history_dock_widget::command_double_clicked,\n           this, &main_window::execute_command_in_terminal);\n}\n\nvoid\nmain_window::adopt_workspace_widget ()\n{\n  m_workspace_window = m_octave_qobj.workspace_widget (this);\n\n  make_dock_widget_connections (m_workspace_window);\n\n  connect (m_workspace_window, &workspace_view::command_requested,\n           this, &main_window::execute_command_in_terminal);\n}\n\nvoid\nmain_window::adopt_editor_widget ()\n{\n  interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();\n\n  qt_interpreter_events *qt_link = interp_qobj->qt_link ();\n\n#if defined (HAVE_QSCINTILLA)\n  file_editor *editor = new file_editor (this);\n\n  make_dock_widget_connections (editor);\n\n  // The editor is currently different from other dock widgets.  Until\n  // those differences are resolved, make interpreter_event\n  // connections here instead of in base_qobject::editor_widget.\n  m_octave_qobj.connect_interpreter_events (editor);\n\n  connect (editor, &file_editor::show_symbol_tooltip_signal,\n           m_octave_qobj.get_workspace_model (),\n           &workspace_model::show_symbol_tooltip);\n\n  connect (editor, &file_editor::request_settings_dialog,\n           this, qOverload<const QString&> (&main_window::process_settings_dialog_request));\n\n  connect (editor, &file_editor::request_dbcont_signal,\n           this, &main_window::debug_continue);\n\n  connect (this, &main_window::update_gui_lexer_signal,\n           editor, &file_editor::update_gui_lexer_signal);\n\n  connect (editor, &file_editor::execute_command_in_terminal_signal,\n           this, &main_window::execute_command_in_terminal);\n\n  connect (editor, &file_editor::focus_console_after_command_signal,\n           this, &main_window::focus_console_after_command);\n\n  connect (editor, &file_editor::run_file_signal,\n           this, &main_window::run_file_in_terminal);\n\n  connect (editor, &file_editor::edit_mfile_request,\n           this, &main_window::handle_edit_mfile_request);\n\n  connect (editor, &file_editor::debug_quit_signal,\n           this, &main_window::debug_quit);\n\n  connect (this, &main_window::editor_focus_changed,\n           editor, &file_editor::enable_menu_shortcuts);\n\n  connect (this, &main_window::step_into_file_signal,\n           editor, &file_editor::request_step_into_file);\n\n  connect (editor, &file_editor::editor_tabs_changed_signal,\n           this, &main_window::editor_tabs_changed);\n\n  connect (editor, &file_editor::request_open_file_external,\n           m_external_editor, &external_editor_interface::call_custom_editor);\n\n  connect (m_external_editor, &external_editor_interface::request_settings_dialog,\n           this, &main_window::process_settings_dialog_request);\n\n  connect (this, &main_window::insert_debugger_pointer_signal,\n           editor, &file_editor::handle_insert_debugger_pointer_request);\n\n  connect (this, &main_window::delete_debugger_pointer_signal,\n           editor, &file_editor::handle_delete_debugger_pointer_request);\n\n  connect (this, &main_window::update_breakpoint_marker_signal,\n           editor, &file_editor::handle_update_breakpoint_marker_request);\n\n  // Signals for removing/renaming/open files/dirs in the file browser\n  connect (m_file_browser, &file_system_browser::file_remove_signal,\n           editor, &file_editor::handle_file_remove);\n\n  connect (m_file_browser, &file_system_browser::file_renamed_signal,\n           editor, &file_editor::handle_file_renamed);\n\n  // Signals for removing/renaming files/dirs in the terminal window\n  connect (qt_link, &qt_interpreter_events::file_renamed_signal,\n           editor, &file_editor::handle_file_renamed);\n\n  // Signals for entering/exiting debug mode\n  connect (qt_link, &qt_interpreter_events::enter_debugger_signal,\n           editor, &file_editor::handle_enter_debug_mode);\n\n  connect (qt_link, &qt_interpreter_events::exit_debugger_signal,\n           editor, &file_editor::handle_exit_debug_mode);\n\n  connect (qt_link, &qt_interpreter_events::directory_changed_signal,\n           editor, &file_editor::update_octave_directory);\n\n  // signal from/to the editor files browser\n  editor_files_browser *feb = m_file_browser_window->get_editor_files_browser ();\n\n  connect (editor, &file_editor::remove_editor_file_in_browser_signal,\n           feb, &editor_files_browser::remove_editor_file);\n\n  connect (editor, &file_editor::rename_editor_file_in_browser_signal,\n           feb, &editor_files_browser::rename_editor_file);\n\n  connect (feb, &editor_files_browser::focus_editor_file_signal,\n           editor, &file_editor::handle_edit_file_request);\n\n  connect (feb, &editor_files_browser::close_editor_file_signal,\n           editor, &file_editor::handle_close_file_request);\n\n  m_editor_window = editor;\n\n  m_editor_menubar = m_editor_window->menubar ();\n\n  m_active_editor = m_editor_window;\n\n  m_editor_window->enable_menu_shortcuts (false);\n#else\n  m_editor_window = nullptr;\n\n  m_editor_menubar = nullptr;\n\n  m_active_editor = m_external_editor;\n#endif\n\n  connect (qt_link, SIGNAL (edit_file_signal (const QString&)),\n           m_active_editor, SLOT (handle_edit_file_request (const QString&)));\n}\n\nvoid\nmain_window::adopt_variable_editor_widget ()\n{\n  m_variable_editor_window = m_octave_qobj.variable_editor_widget (this);\n\n  make_dock_widget_connections (m_variable_editor_window);\n}\n\nvoid\nmain_window::make_dock_widget_connections (octave_dock_widget *dw)\n{\n  connect (this, &main_window::init_window_menu,\n           dw, &octave_dock_widget::init_window_menu_entry);\n\n  connect (this, &main_window::settings_changed,\n           dw, &octave_dock_widget::handle_settings);\n\n  connect (this, &main_window::active_dock_changed,\n           dw, &octave_dock_widget::handle_active_dock_changed);\n\n  // FIXME: shouldn't this action should be associated with closing\n  // the main window, not with exiting the application?  At one time,\n  // those two actions happened together, but now it is possible to\n  // close the main window without exiting the application.\n  connect (qApp, &QApplication::aboutToQuit,\n           dw, &octave_dock_widget::save_settings);\n\n  // The following is required when the exp. terminal widget is used\n  // and the main window is closed (no exit via interpreter)\n  connect (this, &main_window::close_gui_signal,\n           dw, &octave_dock_widget::save_settings);\n}\n\nbool\nmain_window::command_window_has_focus () const\n{\n  return m_command_window->has_focus ();\n}\n\nvoid\nmain_window::focus_command_window ()\n{\n  m_command_window->activate ();\n}\n\nvoid\nmain_window::focus_window (const QString& win_name)\n{\n  if (win_name == \"command\")\n    m_command_window->activate ();\n  else if (win_name == \"history\")\n    m_history_window->activate ();\n  else if (win_name == \"workspace\")\n    m_workspace_window->activate ();\n  else if (win_name == \"filebrowser\")\n    m_file_browser_window->activate ();\n}\n\nbool\nmain_window::confirm_shutdown ()\n{\n  bool closenow = true;\n\n  gui_settings settings;\n\n  if (settings.value (global_prompt_to_exit.settings_key (),\n                      global_prompt_to_exit.def ()).toBool ())\n    {\n      int ans = QMessageBox::question (this, tr (\"Octave\"),\n                                       tr (\"Are you sure you want to exit Octave?\"),\n                                       (QMessageBox::Ok\n                                        | QMessageBox::Cancel),\n                                       QMessageBox::Ok);\n\n      if (ans != QMessageBox::Ok)\n        closenow = false;\n    }\n\n#if defined (HAVE_QSCINTILLA)\n  if (closenow)\n    closenow = m_editor_window->check_closing ();\n#endif\n\n  return closenow;\n}\n\n// catch focus changes and determine the active dock widget\nvoid\nmain_window::focus_changed (QWidget *, QWidget *new_widget)\n{\n  // If there is no new widget or the new widget is a menu bar\n  // (when pressing <alt>), we can return immediately and reset the\n  // focus to the previous widget\n  if (! new_widget\n      || (new_widget == menuBar ())\n      || (new_widget == m_editor_menubar))\n    {\n      if (m_active_dock)\n        m_active_dock->setFocus ();\n\n      return;\n    }\n\n  octave_dock_widget *dock = nullptr;\n  QWidget *w_new = new_widget;  // get a copy of new focus widget\n  QWidget *start = w_new;       // Save it as start of our search\n  int count = 0;                // fallback to prevent endless loop\n\n  QList<octave_dock_widget *> w_list = dock_widget_list ();\n\n  while (w_new && w_new != m_main_tool_bar && count < 100)\n    {\n      // Go through all dock widgets and check whether the current widget\n      // with focus is a child of one of them.\n      for (auto w : w_list)\n        {\n          if (w->isAncestorOf (w_new))\n            dock = w;\n        }\n\n      if (dock)\n        break;\n\n      // If not yet found (in case w_new is not a child of its dock widget),\n      // test next widget in the focus chain\n      w_new = qobject_cast<QWidget *> (w_new->previousInFocusChain ());\n\n      // Measures preventing an endless loop\n      if (w_new == start)\n        break;  // We have arrived where we began ==> exit loop\n      count++;  // Limited number of trials\n    }\n\n  // editor and terminal needs extra handling\n  octave_dock_widget *edit_dock_widget\n    = static_cast<octave_dock_widget *> (m_editor_window);\n  octave_dock_widget *cmd_dock_widget\n    = static_cast<octave_dock_widget *> (m_command_window);\n\n  // if new dock has focus, emit signal and store active focus\n  // except editor changes to a dialog (dock=0)\n  if ((dock || m_active_dock != edit_dock_widget) && (dock != m_active_dock))\n    {\n      // signal to all dock widgets for updating the style\n      Q_EMIT active_dock_changed (m_active_dock, dock);\n\n      if (dock)\n        {\n          QList<QDockWidget *> tabbed = tabifiedDockWidgets (dock);\n          if (tabbed.contains (m_active_dock))\n            dock->set_predecessor_widget (m_active_dock);\n        }\n\n      // Check whether editor loses or gains focus\n      int editor = 0;\n      if (edit_dock_widget == dock)\n        {\n          Q_EMIT editor_focus_changed (true);\n          editor = 1;\n        }\n      else if (edit_dock_widget == m_active_dock)\n        {\n          Q_EMIT editor_focus_changed (false);\n          editor = -1;\n        }\n\n      // Check whether terminal loses or gains focus\n      int cmd_involved = 0;\n      if (cmd_dock_widget == dock)\n        cmd_involved = 1;\n      else if (cmd_dock_widget == m_active_dock)\n        cmd_involved = -1;\n\n      // If we have to take care of Alt+? accelerators of the main\n      // window, take result of test for terminal widget above\n      int command = 0;\n      if (m_prevent_readline_conflicts_menu)\n        command = cmd_involved;\n\n      // If editor or command gets/looses focus, disable/enable\n      // main menu accelerators (Alt + ?)\n      if (editor || command)\n        {\n          int sum = editor + command;\n          if (sum > 0)\n            disable_menu_shortcuts (true);\n          else if (sum < 0)\n            disable_menu_shortcuts (false);\n        }\n\n      if (m_active_dock)\n        m_previous_dock = m_active_dock;\n      m_active_dock = dock;\n\n      // En-/disable global shortcuts (preventing conflicts with\n      // readline.  Do it here because it relies on m_active_dock\n      if (cmd_involved)\n        configure_shortcuts ();\n    }\n}\n\nvoid\nmain_window::request_reload_settings ()\n{\n  Q_EMIT settings_changed ();\n}\n\nvoid\nmain_window::report_status_message (const QString& statusMessage)\n{\n  m_status_bar->showMessage (statusMessage, 1000);\n}\n\nvoid\nmain_window::handle_save_workspace_request ()\n{\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n  int opts = 0;  // No options by default.\n\n  gui_settings settings;\n\n  if (! settings.bool_value (global_use_native_dialogs))\n    opts = QFileDialog::DontUseNativeDialog;\n\n  QString file\n    = QFileDialog::getSaveFileName (this, tr (\"Save Workspace As\"), \".\",\n                                    nullptr, nullptr, QFileDialog::Option (opts));\n\n  if (! file.isEmpty ())\n    {\n      Q_EMIT interpreter_event\n        ([file] (interpreter& interp)\n         {\n           // INTERPRETER THREAD\n\n           Fsave (interp, ovl (file.toStdString ()));\n         });\n    }\n}\n\nvoid\nmain_window::handle_load_workspace_request (const QString& file_arg)\n{\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n  int opts = 0;  // No options by default.\n\n  gui_settings settings;\n\n  if (! settings.bool_value (global_use_native_dialogs))\n    opts = QFileDialog::DontUseNativeDialog;\n\n  QString file = file_arg;\n\n  if (file.isEmpty ())\n    file = QFileDialog::getOpenFileName (this, tr (\"Load Workspace\"), \".\",\n                                         nullptr, nullptr, QFileDialog::Option (opts));\n\n  if (! file.isEmpty ())\n    {\n      Q_EMIT interpreter_event\n        ([file] (interpreter& interp)\n         {\n           // INTERPRETER THREAD\n\n           Fload (interp, ovl (file.toStdString ()));\n\n           tree_evaluator& tw = interp.get_evaluator ();\n\n           event_manager& xevmgr = interp.get_event_manager ();\n\n           xevmgr.set_workspace (true, tw.get_symbol_info ());\n         });\n    }\n}\n\nvoid\nmain_window::handle_open_any_request (const QString& file_arg)\n{\n  if (! file_arg.isEmpty ())\n    {\n      std::string file = file_arg.toStdString ();\n\n      Q_EMIT interpreter_event\n        ([file] (interpreter& interp)\n         {\n           // INTERPRETER THREAD\n\n           interp.feval (\"open\", ovl (file));\n\n           // Update the workspace since open.m may have loaded new\n           // variables.\n           tree_evaluator& tw = interp.get_evaluator ();\n\n           event_manager& xevmgr = interp.get_event_manager ();\n\n           xevmgr.set_workspace (true, tw.get_symbol_info ());\n         });\n    }\n}\n\nvoid\nmain_window::handle_clear_workspace_request ()\n{\n  Q_EMIT interpreter_event\n    ([] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       Fclear (interp);\n     });\n}\n\nvoid\nmain_window::handle_clear_command_window_request ()\n{\n  Q_EMIT interpreter_event\n    ([] ()\n     {\n       // INTERPRETER THREAD\n\n       command_editor::kill_full_line ();\n       command_editor::clear_screen ();\n     });\n}\n\nvoid\nmain_window::handle_clear_history_request ()\n{\n  Q_EMIT interpreter_event\n    ([] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       history_system& history_sys = interp.get_history_system ();\n\n       history_sys.do_history (ovl (\"-c\"));\n     });\n}\n\nvoid\nmain_window::handle_undo_request ()\n{\n  if (command_window_has_focus ())\n    {\n      Q_EMIT interpreter_event\n        ([] ()\n         {\n           // INTERPRETER THREAD\n\n           command_editor::undo ();\n           command_editor::redisplay ();\n         });\n    }\n  else\n    Q_EMIT undo_signal ();\n}\n\nvoid\nmain_window::modify_path (const QStringList& dir_list,\n                          bool rm, bool subdirs)\n{\n  Q_EMIT interpreter_event\n    ([dir_list, subdirs, rm] (interpreter& interp)\n    {\n      // INTERPRETER THREAD\n\n      octave_value_list paths;\n\n      // Loop over all directories in order to get all subdirs\n      for (octave_idx_type i = 0; i < dir_list.length (); i++)\n        {\n          std::string dir = dir_list.at (i).toStdString ();\n\n          if (subdirs)\n            paths.append (Fgenpath (ovl (dir)));\n          else\n            paths.append (dir);\n        }\n\n      if (rm)\n        Frmpath (interp, paths);\n      else\n        Faddpath (interp, paths);\n    });\n}\n\nvoid\nmain_window::edit_mfile (const QString& name, int line)\n{\n  handle_edit_mfile_request (name, QString (), QString (), line);\n}\n\nvoid\nmain_window::file_remove_proxy (const QString& o, const QString& n)\n{\n  interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();\n\n  qt_interpreter_events *qt_link = interp_qobj->qt_link ();\n\n  // Wait for worker to suspend\n  qt_link->lock ();\n  // Close the file if opened\n#if defined (HAVE_QSCINTILLA)\n  m_editor_window->handle_file_remove (o, n);\n#else\n  octave_unused_parameter (o);\n  octave_unused_parameter (n);\n#endif\n\n  // We are done: Unlock and wake the worker thread\n  qt_link->unlock ();\n  qt_link->wake_all ();\n}\n\nvoid\nmain_window::open_online_documentation_page ()\n{\n  QDesktopServices::openUrl\n    (QUrl (\"https://octave.org/doc/interpreter/index.html\"));\n}\n\nvoid\nmain_window::open_bug_tracker_page ()\n{\n  QDesktopServices::openUrl (QUrl (\"https://octave.org/bugs.html\"));\n}\n\nvoid\nmain_window::open_octave_packages_page ()\n{\n  QDesktopServices::openUrl (QUrl (\"https://packages.octave.org/index.html\"));\n}\n\nvoid\nmain_window::open_contribute_page ()\n{\n  QDesktopServices::openUrl (QUrl (\"https://octave.org/contribute.html\"));\n}\n\nvoid\nmain_window::open_donate_page ()\n{\n  QDesktopServices::openUrl (QUrl (\"https://octave.org/donate.html\"));\n}\n\nvoid\nmain_window::process_settings_dialog_request (const QString& desired_tab)\n{\n  if (m_settings_dlg)  // m_settings_dlg is a guarded pointer!\n    {\n      // here the dialog is still open and called once again\n      if (! desired_tab.isEmpty ())\n        m_settings_dlg->show_tab (desired_tab);\n      return;\n    }\n\n  m_settings_dlg = new settings_dialog (this, desired_tab);\n\n  connect (m_settings_dlg, &settings_dialog::apply_new_settings,\n           this, &main_window::request_reload_settings);\n}\n\nvoid\nmain_window::show_about_octave ()\n{\n  std::string message\n    = octave_name_version_copyright_license_copying_warranty_bugs (true);\n\n  QMessageBox::about (this, tr (\"About Octave\"),\n                      QString::fromStdString (message));\n}\n\nvoid\nmain_window::notice_settings (bool update_by_worker)\n{\n  m_octave_qobj.set_gui_style (true);\n\n  gui_settings settings;\n\n  // the widget's icons (when floating)\n  QString icon_set = settings.string_value (dw_icon_set);\n\n  QString icon;\n  for (auto *widget : dock_widget_list ())\n    {\n      QString name = widget->objectName ();\n      if (! name.isEmpty ())\n        {\n          // if child has a name\n          icon = dw_icon_set_names[icon_set];\n          if (icon_set != \"NONE\")\n            icon += name + global_icon_extension; // add widget name and ext.\n          widget->setWindowIcon (QIcon (icon));\n        }\n    }\n\n  int size_idx = settings.int_value (global_icon_size);\n  size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2\n\n  QStyle *st = style ();\n  int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);\n  m_main_tool_bar->setIconSize (QSize (icon_size, icon_size));\n\n  if (settings.bool_value (global_status_bar))\n    m_status_bar->show ();\n  else\n    m_status_bar->hide ();\n\n  m_prevent_readline_conflicts\n    = settings.bool_value (sc_prevent_rl_conflicts);\n\n  m_prevent_readline_conflicts_menu\n    = settings.bool_value (sc_prevent_rl_conflicts_menu);\n\n  m_suppress_dbg_location\n    = ! settings.bool_value (cs_dbg_location);\n\n  settings.update_network_settings ();\n\n  Q_EMIT active_dock_changed (nullptr, m_active_dock); // update dock widget styles\n\n  configure_shortcuts ();\n\n  bool do_disable_main_menu_shortcuts\n    = (m_active_dock == m_editor_window)\n      || (m_prevent_readline_conflicts_menu\n          && (m_active_dock == m_command_window));\n\n  disable_menu_shortcuts (do_disable_main_menu_shortcuts);\n\n  // Check whether some octave internal preferences have to be updated\n  QString new_default_encoding\n    = settings.string_value (ed_default_enc);\n  // Do not update internal pref only if a) this update was not initiated\n  // by the worker and b) the pref has really changes\n  if (! update_by_worker && (new_default_encoding != m_default_encoding))\n    update_default_encoding (new_default_encoding);\n\n  // Set cursor blinking depending on the settings\n  // Cursor blinking: consider old terminal related setting if not yet set\n  // TODO: This pref. can be deprecated / removed if Qt adds support for\n  //       getting the cursor blink preferences from all OS environments\n  bool cursor_blinking;\n\n  if (settings.contains (global_cursor_blinking.settings_key ()))\n    cursor_blinking = settings.bool_value (global_cursor_blinking);\n  else\n    cursor_blinking = settings.bool_value (cs_cursor_blinking);\n\n  if (cursor_blinking)\n    QApplication::setCursorFlashTime (1000);  // 1000 ms flash time\n  else\n    QApplication::setCursorFlashTime (0);  // no flashing\n\n}\n\nvoid\nmain_window::prepare_to_exit ()\n{\n  // Find files dialog is constructed dynamically, not at time of main_window\n  // construction.  Connecting it to qApp aboutToQuit signal would have\n  // caused it to run after gui_settings is deleted.\n  if (m_find_files_dlg)\n    m_find_files_dlg->save_settings ();\n\n  if (m_set_path_dlg)\n    m_set_path_dlg->save_settings ();\n\n  write_settings ();\n\n  // No more active dock, otherwise, focus_changed would try to set\n  // the focus to a dock widget that might not exist anymore\n  m_active_dock = nullptr;\n}\n\nvoid\nmain_window::go_to_previous_widget ()\n{\n  m_previous_dock->activate ();\n}\n\nvoid\nmain_window::update_octave_directory (const QString& dir)\n{\n  // Remove existing entry, if any, then add new directory at top and\n  // mark it as the current directory.  Finally, update the file list\n  // widget.\n  combobox_insert_current_item (m_current_directory_combo_box, dir);\n}\n\nvoid\nmain_window::browse_for_directory ()\n{\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n  int opts = QFileDialog::ShowDirsOnly;\n\n  gui_settings settings;\n\n  if (! settings.bool_value (global_use_native_dialogs))\n    opts = QFileDialog::DontUseNativeDialog;\n\n  QString dir\n    = QFileDialog::getExistingDirectory (this, tr (\"Browse directories\"), nullptr,\n                                         QFileDialog::Option (opts));\n\n  set_current_working_directory (dir);\n\n  // FIXME: on Windows systems, the command window freezes after the\n  // previous actions.  Forcing the focus appears to unstick it.\n\n  focus_command_window ();\n}\n\nvoid\nmain_window::set_current_working_directory (const QString& dir)\n{\n  // Change to dir if it is an existing directory.\n\n  QString xdir = (dir.isEmpty () ? \".\" : dir);\n\n  QFileInfo fileInfo (xdir);\n\n  if (fileInfo.exists () && fileInfo.isDir ())\n    {\n      Q_EMIT interpreter_event\n        ([xdir] (interpreter& interp)\n         {\n           // INTERPRETER THREAD\n\n           interp.chdir (xdir.toStdString ());\n         });\n    }\n}\n\nvoid\nmain_window::change_directory_up ()\n{\n  set_current_working_directory (\"..\");\n}\n\n// Slot that is called if return is pressed in the line edit of the\n// combobox to change to a new directory or a directory that is already\n// in the drop down list.\n\nvoid\nmain_window::accept_directory_line_edit ()\n{\n  // Get new directory name, and change to it if it is new.  Otherwise,\n  // the combo box will trigger the \"activated\" signal to change to the\n  // directory.\n\n  QString dir = m_current_directory_combo_box->currentText ();\n\n  int index = m_current_directory_combo_box->findText (dir);\n\n  if (index < 0)\n    set_current_working_directory (dir);\n}\n\nvoid\nmain_window::execute_command_in_terminal (const QString& command)\n{\n  if (m_octave_qobj.experimental_terminal_widget ())\n    {\n      Q_EMIT execute_command_signal (command);\n    }\n  else\n    {\n      Q_EMIT interpreter_event\n        ([command] ()\n         {\n           // INTERPRETER THREAD\n\n           std::string pending_input = command_editor::get_current_line ();\n\n           command_editor::set_initial_input (pending_input);\n           command_editor::replace_line (command.toStdString ());\n           command_editor::redisplay ();\n           command_editor::interrupt_event_loop ();\n           command_editor::accept_line ();\n         });\n    }\n\n  focus_console_after_command ();\n}\n\nvoid\nmain_window::run_file_in_terminal (const QFileInfo& info, int opts)\n{\n  Q_EMIT interpreter_event\n    ([this, opts, info] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       QString function_name = info.fileName ();\n       function_name.chop (info.suffix ().length () + 1);\n       std::string file_path = info.absoluteFilePath ().toStdString ();\n\n       std::string pending_input = command_editor::get_current_line ();\n\n       if (valid_identifier (function_name.toStdString ()))\n         {\n           // Valid identifier: call as function with possibility to\n           // debug.\n\n           load_path& lp = interp.get_load_path ();\n\n           // Rehashing the load path is only needed when executing new files\n           // in the built-in editor for the first time and the command line\n           // prompt hasn't been displayed yet again since this *new* file has\n           // been saved for the first time.\n           // FIXME: Is there a way to detect here that a file is new?\n           lp.rehash ();\n\n           std::string path = info.absolutePath ().toStdString ();\n\n           if (lp.contains_file_in_dir (file_path, path))\n             {\n               QString cmd;\n               if (opts == ED_RUN_TESTS)\n                 cmd = \"test \";\n               else if (opts == ED_RUN_DEMOS)\n                 cmd = \"demo \";\n               cmd = cmd + function_name;\n\n               if (m_octave_qobj.experimental_terminal_widget ())\n                 Q_EMIT execute_command_signal (cmd);\n               else\n                 command_editor::replace_line (cmd.toStdString ());\n             }\n         }\n       else\n         {\n           // No valid identifier: use equivalent of Fsource (), no\n           // debug possible.\n\n           if (opts == ED_RUN_FILE)\n             {\n               interp.source_file (file_path);\n               command_editor::replace_line (\"\");\n             }\n         }\n\n       if (! m_octave_qobj.experimental_terminal_widget ())\n         {\n           command_editor::set_initial_input (pending_input);\n           command_editor::redisplay ();\n           command_editor::interrupt_event_loop ();\n           command_editor::accept_line ();\n         }\n     });\n\n  focus_console_after_command ();\n}\n\nvoid\nmain_window::get_input_from_terminal (const QString& prompt)\n{\n  if (m_octave_qobj.experimental_terminal_widget ())\n    {\n      // move focus to command window widget for user input\n      focus_console_after_command ();\n\n      Q_EMIT get_input_from_terminal_signal (prompt);\n    }\n  else\n    {\n      // FIXME: Currently only implemented for experimental terminal widget.\n/*\n      Q_EMIT interpreter_event\n        ([prompt] ()\n         {\n           // INTERPRETER THREAD\n\n           std::string pending_input = command_editor::get_current_line ();\n\n           command_editor::set_initial_input (pending_input);\n           command_editor::replace_line (prompt.toStdString ());\n           command_editor::redisplay ();\n           command_editor::interrupt_event_loop ();\n           // command_editor::accept_line ();\n         });\n*/\n    }\n  focus_console_after_command ();\n}\n\nvoid\nmain_window::handle_new_figure_request ()\n{\n  Q_EMIT interpreter_event\n    ([] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       Fbuiltin (interp, ovl (\"figure\"));\n       Fdrawnow (interp);\n     });\n}\n\nvoid\nmain_window::handle_enter_debugger ()\n{\n  setWindowTitle (\"Octave (Debugging)\");\n\n  m_debug_continue->setEnabled (true);\n  m_debug_step_into->setEnabled (true);\n  m_debug_step_over->setEnabled (true);\n  m_debug_step_out->setEnabled (true);\n  m_debug_quit->setEnabled (true);\n}\n\nvoid\nmain_window::handle_exit_debugger ()\n{\n  setWindowTitle (\"Octave\");\n\n  m_debug_continue->setEnabled (false);\n  m_debug_step_into->setEnabled (false);\n  m_debug_step_over->setEnabled (m_editor_has_tabs && m_editor_is_octave_file);\n  m_debug_step_out->setEnabled (false);\n  m_debug_quit->setEnabled (false);\n}\n\nvoid\nmain_window::debug_continue ()\n{\n  Q_EMIT interpreter_event\n    ([this] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));\n       Fdbcont (interp);\n\n       command_editor::interrupt (true);\n     });\n}\n\nvoid\nmain_window::debug_step_into ()\n{\n  Q_EMIT interpreter_event\n    ([this] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));\n       Fdbstep (interp, ovl (\"in\"));\n\n       command_editor::interrupt (true);\n     });\n}\n\nvoid\nmain_window::debug_step_over ()\n{\n  if (m_debug_quit->isEnabled ())\n    {\n      // We are in debug mode, just call dbstep.\n\n      Q_EMIT interpreter_event\n        ([this] (interpreter& interp)\n         {\n           // INTERPRETER THREAD\n\n           F__db_next_breakpoint_quiet__ (interp,\n                                          ovl (m_suppress_dbg_location));\n           Fdbstep (interp);\n\n           command_editor::interrupt (true);\n         });\n    }\n  else\n    {\n      // Not in debug mode: \"step into\" the current editor file\n      Q_EMIT step_into_file_signal ();\n    }\n}\n\nvoid\nmain_window::debug_step_out ()\n{\n  Q_EMIT interpreter_event\n    ([this] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));\n       Fdbstep (interp, ovl (\"out\"));\n\n       command_editor::interrupt (true);\n     });\n}\n\nvoid\nmain_window::debug_quit ()\n{\n  Q_EMIT interpreter_event\n    ([] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       Fdbquit (interp);\n\n       command_editor::interrupt (true);\n     });\n}\n\n//\n// Functions related to file editing\n//\n// These are moved from editor to here for also using them when octave\n// is built without qscintilla\n//\nvoid\nmain_window::request_open_file ()\n{\n  // Open file isn't a file_editor_tab or editor function since the file\n  // might be opened in an external editor.  Hence, functionality is here.\n\n  gui_settings settings;\n\n  bool is_internal = m_editor_window\n                     && ! settings.value (global_use_custom_editor.settings_key (),\n                                          global_use_custom_editor.def ()).toBool ();\n\n  // Create a NonModal message.\n\n  QWidget *p = this;\n  if (is_internal)\n    p = m_editor_window;\n\n  QFileDialog fileDialog (p);\n\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n  if (! settings.bool_value (global_use_native_dialogs))\n    fileDialog.setOption (QFileDialog::DontUseNativeDialog);\n\n  fileDialog.setNameFilter (tr (\"Octave Files (*.m);;All Files (*)\"));\n\n  fileDialog.setAcceptMode (QFileDialog::AcceptOpen);\n  fileDialog.setViewMode (QFileDialog::Detail);\n  fileDialog.setFileMode (QFileDialog::ExistingFiles);\n\n  QString directory = m_current_directory_combo_box->itemText (0);\n  if (is_internal &&\n      settings.bool_value (ed_open_dlg_follows_file))\n    {\n      // Get directory of current editor file.  If it is still empty (new\n      // editor tab), the last directory is selected by the file dialog.\n      QFileInfo file_info (m_editor_window->get_current_filename ());\n      directory = file_info.canonicalPath ();\n    }\n\n  fileDialog.setDirectory (directory);\n\n  if (fileDialog.exec ())\n    {\n      QStringList open_file_names = fileDialog.selectedFiles ();\n      for (int i = 0; i < open_file_names.count (); i++)\n        Q_EMIT open_file_signal (open_file_names.at (i), m_file_encoding, -1);\n    }\n}\n\n// Create a new script\nvoid\nmain_window::request_new_script (const QString& commands)\n{\n  Q_EMIT new_file_signal (commands);\n}\n\n// Create a new function and open it\nvoid\nmain_window::request_new_function (bool)\n{\n  bool ok;\n  // Get the name of the new function: Parent of the input dialog is the\n  // editor window or the main window.  The latter is chosen, if a custom\n  // editor is used or qscintilla is not available\n  QWidget *p = m_editor_window;\n\n  gui_settings settings;\n\n  if (! p || settings.value (global_use_custom_editor.settings_key (),\n                             global_use_custom_editor.def ()).toBool ())\n    p = this;\n  QString new_name = QInputDialog::getText (p, tr (\"New Function\"),\n                                            tr (\"New function name:\\n\"), QLineEdit::Normal, \"\", &ok);\n\n  if (ok && new_name.length () > 0)\n    {\n      // append suffix if it does not already exist\n      if (new_name.right (2) != \".m\")\n        new_name.append (\".m\");\n      // check whether new files are created without prompt\n      if (! settings.bool_value (ed_create_new_file))\n        {\n          // no, so enable this settings and wait for end of new file loading\n          settings.setValue (ed_create_new_file.settings_key (), true);\n          connect (m_editor_window, SIGNAL (file_loaded_signal ()),\n                   this, SLOT (restore_create_file_setting ()));\n        }\n      // start the edit command\n      execute_command_in_terminal (\"edit \" + new_name);\n    }\n}\n\nvoid\nmain_window::handle_edit_mfile_request (const QString& fname,\n                                        const QString& ffile,\n                                        const QString& curr_dir,\n                                        int line)\n{\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<main_window> this_mw (this);\n\n  Q_EMIT interpreter_event\n    ([this, this_mw, fname, ffile, curr_dir, line] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       // We can skip the entire callback function because it does not\n       // make any changes to the interpreter state.\n\n       if (this_mw.isNull ())\n         return;\n\n       // Split possible subfunctions\n       QStringList fcn_list = fname.split ('>');\n       QString fcn_name = fcn_list.at (0) + \".m\";\n\n       // FIXME: could use symbol_exist directly, but we may also want\n       // to fix that to be a member function in the interpreter\n       // class?\n\n       // Is it a regular function within the search path? (Call Fexist)\n       octave_value_list fct = Fexist (interp, ovl (fname.toStdString ()),0);\n       int type = fct (0).int_value ();\n\n       QString message = QString ();\n       QString filename = QString ();\n\n       switch (type)\n         {\n         case 3:\n         case 5:\n         case 103:\n           message = tr (\"%1 is a built-in, compiled, or inline\\n\"\n                         \"function and can not be edited.\");\n           break;\n\n         case 2:\n           // FIXME: could use a load_path function directly.\n           octave_value_list file_path\n             = Ffile_in_loadpath (interp, ovl (fcn_name.toStdString ()), 0);\n           if (file_path.length () > 0)\n             filename = QString::fromStdString (file_path (0).string_value ());\n           break;\n         }\n\n       if (filename.isEmpty () && message.isEmpty ())\n         {\n           // No error so far, but function still not known\n           // -> try directory of edited file\n           // get directory\n           QDir dir;\n           if (ffile.isEmpty ())\n             {\n               if (curr_dir.isEmpty ())\n                 dir = QDir (m_current_directory_combo_box->itemText (0));\n               else\n                 dir = QDir (curr_dir);\n             }\n           else\n             dir = QDir (QFileInfo (ffile).canonicalPath ());\n\n           QFileInfo file = QFileInfo (dir, fcn_name);\n           if (file.exists ())\n             filename = file.canonicalFilePath (); // local file exists\n           else\n             {\n               // local file does not exist -> try private directory\n               file = QFileInfo (ffile);\n               file = QFileInfo (QDir (file.canonicalPath () + \"/private\"),\n                                 fcn_name);\n               if (file.exists ())\n                 filename = file.canonicalFilePath ();  // private function exists\n               else\n                 message = tr (\"Can not find function %1\");  // no file found\n             }\n         }\n\n       if (! message.isEmpty ())\n         {\n           Q_EMIT warning_function_not_found_signal (message.arg (fname));\n           return;\n         }\n\n       if (! filename.endsWith (\".m\"))\n         filename.append (\".m\");\n\n       // default encoding\n       Q_EMIT open_file_signal (filename, QString (), line);\n     });\n}\n\nvoid\nmain_window::warning_function_not_found (const QString& message)\n{\n  QMessageBox *msgBox = new QMessageBox (QMessageBox::Critical,\n                                         tr (\"Octave Editor\"),\n                                         message, QMessageBox::Ok, this);\n  msgBox->setWindowModality (Qt::NonModal);\n  msgBox->setAttribute (Qt::WA_DeleteOnClose);\n  msgBox->show ();\n}\n\nvoid\nmain_window::handle_insert_debugger_pointer_request (const QString& file,\n    int line)\n{\n  bool cmd_focus = command_window_has_focus ();\n\n  Q_EMIT insert_debugger_pointer_signal (file, line);\n\n  if (cmd_focus)\n    focus_command_window ();\n}\n\nvoid\nmain_window::handle_delete_debugger_pointer_request (const QString& file,\n    int line)\n{\n  bool cmd_focus = command_window_has_focus ();\n\n  Q_EMIT delete_debugger_pointer_signal (file, line);\n\n  if (cmd_focus)\n    focus_command_window ();\n}\n\nvoid\nmain_window::handle_update_breakpoint_marker_request (bool insert,\n    const QString& file,\n    int line,\n    const QString& cond)\n{\n  bool cmd_focus = command_window_has_focus ();\n\n  Q_EMIT update_breakpoint_marker_signal (insert, file, line, cond);\n\n  if (cmd_focus)\n    focus_command_window ();\n}\n\nvoid\nmain_window::read_settings ()\n{\n  gui_settings settings;\n\n  set_window_layout ();\n\n  // restore the list of the last directories\n  QStringList curr_dirs = settings.string_list_value (mw_dir_list);\n  for (int i=0; i < curr_dirs.size (); i++)\n    {\n      m_current_directory_combo_box->addItem (curr_dirs.at (i));\n    }\n\n  Q_EMIT settings_changed ();\n}\n\nvoid\nmain_window::init_terminal_size ()\n{\n  Q_EMIT init_terminal_size_signal ();\n}\n\nvoid\nmain_window::set_window_layout ()\n{\n  gui_settings settings;\n\n  // For resetting from some inconsistent state, first reset layout\n  // without saving or showing it\n  do_reset_windows (true, false);\n\n  // Restore main window state and geometry from settings file or, in case\n  // of an error (no pref values yet), from the default layout.\n  if (! restoreGeometry (settings.byte_array_value (mw_geometry)))\n    {\n      do_reset_windows (true);\n      return;\n    }\n\n  if (isMaximized ())\n    {\n      // If the window state is restored to maximized layout, the\n      // horizontal layout is not preserved.  This can be avoided by\n      // setting the geometry to the max. available geometry.  However, on\n      // X11, the available geometry (excluding task bar etc.) is equal to\n      // the total geometry leading to a full screen mode without window\n      // decorations.  This in turn can be avoided by explicitly adding\n      // a title bar in the window flags.\n\n      // Get available geometry for current screen and set this\n      // window's geometry to it.\n      QScreen *s = windowHandle ()->screen ();\n      QRect av_geom = s->availableGeometry ();\n      setGeometry (av_geom);  // Set (correct) available geometry\n\n      // Force full title bar\n      setWindowFlags (Qt::WindowTitleHint\n                      | Qt::WindowMinMaxButtonsHint\n                      | Qt::WindowSystemMenuHint\n                      | Qt::WindowCloseButtonHint);\n    }\n\n  if (! restoreState (settings.byte_array_value (mw_state)))\n    {\n      do_reset_windows (true);\n      return;\n    }\n\n  // Restore the geometry of all dock-widgets\n\n  for (auto *widget : dock_widget_list ())\n    {\n      // Leave any widgets that existed before main_window was created\n      // as they were.\n\n      if (widget->adopted ())\n        continue;\n\n      QString name = widget->objectName ();\n\n      if (! name.isEmpty ())\n        {\n          bool floating = false;\n          bool visible = true;\n\n          floating = settings.value\n            (dw_is_floating.settings_key ().arg (name), dw_is_floating.def ()).toBool ();\n          visible = settings.value\n            (dw_is_visible.settings_key ().arg (name), dw_is_visible.def ()).toBool ();\n\n          // If floating, make window from widget.\n          if (floating)\n            {\n              widget->make_window ();\n\n              if (visible)\n                {\n                  if (settings.value (dw_is_minimized.settings_key ().arg (name),\n                                      dw_is_minimized.def ()).toBool ())\n                    widget->showMinimized ();\n                  else\n                    widget->setVisible (true);\n                }\n              else\n                widget->setVisible (false);\n            }\n          else  // not floating\n            {\n              if (! widget->parent ())        // should not be floating but is\n                widget->make_widget (false);  // no docking, just reparent\n\n              widget->make_widget ();\n              widget->setVisible (visible);   // not floating -> show\n            }\n        }\n    }\n\n  show ();\n}\n\nvoid\nmain_window::write_settings ()\n{\n  gui_settings settings;\n\n  settings.setValue (mw_geometry.settings_key (), saveGeometry ());\n  settings.setValue (mw_state.settings_key (), saveState ());\n  // write the list of recently used directories\n  QStringList curr_dirs;\n  for (int i=0; i<m_current_directory_combo_box->count (); i++)\n    {\n      curr_dirs.append (m_current_directory_combo_box->itemText (i));\n    }\n  settings.setValue (mw_dir_list.settings_key (), curr_dirs);\n  settings.sync ();\n}\n\nvoid\nmain_window::copyClipboard ()\n{\n  if (m_current_directory_combo_box->hasFocus ())\n    {\n      QLineEdit *edit = m_current_directory_combo_box->lineEdit ();\n      if (edit && edit->hasSelectedText ())\n        {\n          QClipboard *clipboard = QApplication::clipboard ();\n          clipboard->setText (edit->selectedText ());\n        }\n    }\n  else\n    Q_EMIT copyClipboard_signal ();\n}\n\nvoid\nmain_window::pasteClipboard ()\n{\n  if (m_current_directory_combo_box->hasFocus ())\n    {\n      QLineEdit *edit = m_current_directory_combo_box->lineEdit ();\n      QClipboard *clipboard = QApplication::clipboard ();\n      QString str = clipboard->text ();\n      if (edit && str.length () > 0)\n        {\n          edit->insert (str);\n        }\n    }\n  else\n    Q_EMIT pasteClipboard_signal ();\n}\n\nvoid\nmain_window::selectAll ()\n{\n  if (m_current_directory_combo_box->hasFocus ())\n    {\n      QLineEdit *edit = m_current_directory_combo_box->lineEdit ();\n      if (edit)\n        {\n          edit->selectAll ();\n        }\n    }\n  else\n    Q_EMIT selectAll_signal ();\n}\n\nvoid\nmain_window::handle_gui_status_update (const QString& feature,\n                                       const QString& status)\n{\n  // Put actions that are required for updating a gui features here\n\n  // Profiler on/off\n  if (! feature.compare (\"profiler\"))\n    {\n      if (! status.compare (\"on\", Qt::CaseInsensitive))\n        handle_profiler_status_update (true);\n      else if (! status.compare (\"off\", Qt::CaseInsensitive))\n        handle_profiler_status_update (false);\n    }\n}\n\nvoid\nmain_window::handle_octave_ready ()\n{\n  // actions after the startup files are executed\n\n  gui_settings settings;\n\n  QDir startup_dir = QDir ();    // current octave dir after startup\n\n  if (settings.bool_value (global_restore_ov_dir))\n    {\n      // restore last dir from previous session\n      QStringList curr_dirs\n        = settings.string_list_value (mw_dir_list);\n      if (curr_dirs.length () > 0)\n        startup_dir = QDir (curr_dirs.at (0));  // last dir prev. session\n    }\n  else if (! settings.string_value (global_ov_startup_dir).isEmpty ())\n    {\n      // do not restore but there is a startup dir configured\n      startup_dir\n        = QDir (settings.string_value (global_ov_startup_dir));\n    }\n\n  update_default_encoding (settings.string_value (ed_default_enc));\n\n  if (! startup_dir.exists ())\n    {\n      // the configured startup dir does not exist, take actual one\n      startup_dir = QDir ();\n    }\n\n  set_current_working_directory (startup_dir.absolutePath ());\n\n  if (m_editor_window)\n    {\n#if defined (HAVE_QSCINTILLA)\n      // Octave ready, determine whether to create an empty script.\n      // This can not be done when the editor is created because all functions\n      // must be known for the lexer's auto completion information\n      m_editor_window->empty_script (true, false);\n      bool ed_visible =\n        settings.value (dw_is_visible.settings_key ().arg (m_editor_window->objectName ()),\n                        dw_is_visible.def ()).toBool ();\n      m_editor_window->restore_session (ed_visible);\n#endif\n    }\n\n  if (m_octave_qobj.experimental_terminal_widget ())\n    {\n      // Set initial prompt.\n\n      // The interpreter_event callback function below emits a\n      // signal.  Because we don't control when that happens, use a\n      // guarded pointer so that the callback can abort if this object\n      // is no longer valid.\n\n      QPointer<main_window> this_mw (this);\n\n      Q_EMIT interpreter_event\n        ([this, this_mw] (interpreter& interp)\n        {\n          // INTERPRETER_THREAD\n\n          // We can skip the entire callback function because it does\n          // not make any changes to the interpreter state.\n\n          if (this_mw.isNull ())\n            return;\n\n          std::string prompt = interp.PS1 ();\n\n          std::string decoded_prompt\n            = command_editor::decode_prompt_string (prompt);\n\n          Q_EMIT update_prompt_signal (QString::fromStdString (decoded_prompt));\n        });\n    }\n\n  m_command_window->init_command_prompt ();\n  focus_command_window ();  // make sure that the command window has focus\n}\n\nvoid\nmain_window::handle_set_path_dialog_request ()\n{\n  if (m_set_path_dlg)  // m_set_path_dlg is a guarded pointer!\n    return;\n\n  m_set_path_dlg = new set_path_dialog (this);\n\n  m_set_path_dlg->setModal (false);\n  m_set_path_dlg->setAttribute (Qt::WA_DeleteOnClose);\n  m_set_path_dlg->show ();\n\n  // Any interpreter_event signal from a set_path_dialog object is\n  // handled the same as for the main_window object.\n\n  connect (m_set_path_dlg, qOverload<const fcn_callback&> (&set_path_dialog::interpreter_event),\n           this, qOverload<const fcn_callback&> (&main_window::interpreter_event));\n\n  connect (m_set_path_dlg, qOverload<const meth_callback&> (&set_path_dialog::interpreter_event),\n           this, qOverload<const meth_callback&> (&main_window::interpreter_event));\n\n  connect (m_set_path_dlg, &set_path_dialog::modify_path_signal,\n           this, &main_window::modify_path);\n\n  interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();\n\n  qt_interpreter_events *qt_link = interp_qobj->qt_link ();\n\n  connect (qt_link, &qt_interpreter_events::update_path_dialog_signal,\n           m_set_path_dlg, &set_path_dialog::update_model);\n\n  // Now that all the signal connections are in place for the dialog\n  // we can set the initial value of the path in the model.\n\n  m_set_path_dlg->update_model ();\n}\n\nvoid\nmain_window::find_files (const QString& start_dir)\n{\n  if (! m_find_files_dlg)\n    {\n      m_find_files_dlg = new find_files_dialog (this);\n\n      connect (m_find_files_dlg, &find_files_dialog::finished,\n               this, &main_window::find_files_finished);\n\n      connect (m_find_files_dlg, &find_files_dialog::dir_selected,\n               m_file_browser, &file_system_browser::set_current_directory);\n\n      connect (m_find_files_dlg, &find_files_dialog::file_selected,\n#if defined (HAVE_QSCINTILLA)\n               [this](const QString& file_name, const find_files_data& ff_data)\n                    { m_editor_window->request_open_file (\n                                file_name, QString (), -1, false, false, true,\n                                \"\", -1, QString (), ff_data);\n                    });\n#else\n               this, qOverload<const QString&> (&main_window::open_file_signal));\n#endif\n      m_find_files_dlg->setWindowModality (Qt::NonModal);\n    }\n\n  if (! m_find_files_dlg->isVisible ())\n    {\n      m_find_files_dlg->show ();\n    }\n\n  if (! start_dir.isEmpty ())\n    m_find_files_dlg->set_search_dir (start_dir);\n\n  m_find_files_dlg->activateWindow ();\n}\n\nvoid\nmain_window::set_screen_size (int ht, int wd)\n{\n  Q_EMIT interpreter_event\n    ([ht, wd] ()\n     {\n       // INTERPRETER THREAD\n\n       command_editor::set_screen_size (ht, wd);\n     });\n}\n\nvoid\nmain_window::clipboard_has_changed ()\n{\n  if (m_clipboard->text ().isEmpty ())\n    {\n      m_paste_action->setEnabled (false);\n      m_clear_clipboard_action->setEnabled (false);\n    }\n  else\n    {\n      m_paste_action->setEnabled (true);\n      m_clear_clipboard_action->setEnabled (true);\n    }\n}\n\nvoid\nmain_window::clear_clipboard ()\n{\n  m_clipboard->clear (QClipboard::Clipboard);\n}\n\nvoid\nmain_window::disable_menu_shortcuts (bool disable)\n{\n  QHash<QMenu *, QStringList>::const_iterator i = m_hash_menu_text.constBegin ();\n\n  while (i != m_hash_menu_text.constEnd ())\n    {\n      i.key ()->setTitle (i.value ().at (disable));\n      ++i;\n    }\n}\n\nvoid\nmain_window::restore_create_file_setting ()\n{\n  // restore the new files creation setting\n\n  gui_settings settings;\n\n  settings.setValue (ed_create_new_file.settings_key (), false);\n  disconnect (m_editor_window, SIGNAL (file_loaded_signal ()),\n              this, SLOT (restore_create_file_setting ()));\n}\n\nvoid\nmain_window::set_file_encoding (const QString& new_encoding)\n{\n  m_file_encoding = new_encoding;\n}\n\nvoid\nmain_window::profiler_session ()\n{\n  Q_EMIT interpreter_event\n    ([] (interpreter& interp)\n      {\n        // INTERPRETER THREAD\n        F__profiler_enable__ (interp, ovl (true));\n      });\n}\n\nvoid\nmain_window::profiler_session_resume ()\n{\n  Q_EMIT interpreter_event\n    ([] (interpreter& interp)\n      {\n        // INTERPRETER THREAD\n        F__profiler_enable__ (interp, ovl (true));\n      });\n}\n\nvoid\nmain_window::profiler_stop ()\n{\n  Q_EMIT interpreter_event\n    ([] (interpreter& interp)\n      {\n        // INTERPRETER THREAD\n        F__profiler_enable__ (interp, ovl (false));\n      });\n}\n\nvoid\nmain_window::handle_profiler_status_update (bool active)\n{\n  m_profiler_start->setEnabled (! active);\n  m_profiler_resume->setEnabled (! active);\n  m_profiler_stop->setEnabled (active);\n\n  led_indicator::led_state state = led_indicator::LED_STATE_INACTIVE;\n  if (active)\n    state = led_indicator::LED_STATE_ACTIVE;\n  m_profiler_status_indicator->set_state (state);\n}\n\nvoid\nmain_window::profiler_show ()\n{\n  // Do not use a separate interpreter event as in the other\n  // profiler slots since the output of the command \"profshow\"\n  // would obscure the prompt and we do not need to emimt a signal\n  // for action that is required in the gui after rhe command\n  execute_command_in_terminal (\"profshow\");\n}\n\nvoid\nmain_window::closeEvent (QCloseEvent *e)\n{\n  write_settings ();\n\n  if (confirm_shutdown ())\n    {\n      // FIXME: Instead of ignoring the event and posting an\n      // interpreter event, should we just accept the event and\n      // shutdown and clean up the interpreter as part of closing the\n      // GUI?  Going that route might make it easier to close the GUI\n      // without having to stop the interpreter, for example, if the\n      // GUI is started from the interpreter command line.\n\n      e->ignore ();\n\n      if (m_octave_qobj.experimental_terminal_widget ()\n          && ! m_octave_qobj.is_gui_app ())\n        Q_EMIT close_gui_signal ();\n      else\n        {\n          Q_EMIT interpreter_event\n            ([] (interpreter& interp)\n             {\n               // INTERPRETER THREAD\n\n               interp.quit (0, false, false);\n             });\n        }\n    }\n  else\n    e->ignore ();\n}\n\nvoid\nmain_window::construct_central_widget ()\n{\n  // Create and set the central widget.  QMainWindow takes ownership of\n  // the widget (pointer) so there is no need to delete the object upon\n  // destroying this main_window.\n\n  QWidget *dummyWidget = new QWidget ();\n  dummyWidget->setObjectName (\"CentralDummyWidget\");\n  dummyWidget->resize (10, 10);\n  dummyWidget->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);\n  dummyWidget->hide ();\n  setCentralWidget (dummyWidget);\n}\n\n// Main subroutine of the constructor\n\nvoid\nmain_window::construct ()\n{\n  setWindowIcon (QIcon (dw_icon_set_names[\"NONE\"]));\n\n  interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();\n\n  qt_interpreter_events *qt_link = interp_qobj->qt_link ();\n\n  construct_menu_bar ();\n\n  construct_tool_bar ();\n\n  // FIXME: Is this action intended to be about quitting application\n  // or closing the main window?\n  connect (qApp, &QApplication::aboutToQuit,\n           this, &main_window::prepare_to_exit);\n\n  connect (qApp, &QApplication::focusChanged,\n           this, &main_window::focus_changed);\n\n  // Default argument requires wrapper.\n  connect (this, &main_window::settings_changed,\n           this, [this] () { notice_settings (); });\n\n  // Connections for signals from the interpreter thread where the slot\n  // should be executed by the gui thread\n\n  connect (this, &main_window::warning_function_not_found_signal,\n           this, &main_window::warning_function_not_found);\n\n  setWindowTitle (\"Octave\");\n\n  setStatusBar (m_status_bar);\n\n  // Signals for removing/renaming files/dirs in the temrinal window\n  connect (qt_link, &qt_interpreter_events::file_remove_signal,\n           this, &main_window::file_remove_proxy);\n\n  connect (this, qOverload<const fcn_callback&> (&main_window::interpreter_event),\n           &m_octave_qobj, qOverload<const fcn_callback&> (&base_qobject::interpreter_event));\n\n  connect (this, qOverload<const meth_callback&> (&main_window::interpreter_event),\n           &m_octave_qobj, qOverload<const meth_callback&> (&base_qobject::interpreter_event));\n\n  configure_shortcuts ();\n}\n\nvoid\nmain_window::construct_octave_qt_link ()\n{\n  interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();\n\n  qt_interpreter_events *qt_link = interp_qobj->qt_link ();\n\n  connect (qt_link, &qt_interpreter_events::settings_changed,\n           this, &main_window::notice_settings);\n\n  connect (qt_link, &qt_interpreter_events::apply_new_settings,\n           this, &main_window::request_reload_settings);\n\n  connect (qt_link, &qt_interpreter_events::directory_changed_signal,\n           this, &main_window::update_octave_directory);\n\n  connect (qt_link, &qt_interpreter_events::execute_command_in_terminal_signal,\n           this, &main_window::execute_command_in_terminal);\n\n  connect (qt_link, &qt_interpreter_events::get_input_from_terminal_signal,\n           this, &main_window::get_input_from_terminal);\n\n  connect (this, &main_window::finished_input_from_terminal_signal,\n           qt_link, &qt_interpreter_events::finished_input_from_terminal);\n\n  connect (qt_link, &qt_interpreter_events::enter_debugger_signal,\n           this, &main_window::handle_enter_debugger);\n\n  connect (qt_link, &qt_interpreter_events::exit_debugger_signal,\n           this, &main_window::handle_exit_debugger);\n\n  connect (qt_link, &qt_interpreter_events::show_preferences_signal,\n           this, [this] () { process_settings_dialog_request (); });\n\n  connect (qt_link, &qt_interpreter_events::insert_debugger_pointer_signal,\n           this, &main_window::handle_insert_debugger_pointer_request);\n\n  connect (qt_link, &qt_interpreter_events::delete_debugger_pointer_signal,\n           this, &main_window::handle_delete_debugger_pointer_request);\n\n  connect (qt_link, &qt_interpreter_events::update_breakpoint_marker_signal,\n           this, &main_window::handle_update_breakpoint_marker_request);\n\n  connect (qt_link, &qt_interpreter_events::gui_status_update_signal,\n           this, &main_window::handle_gui_status_update);\n\n  connect (qt_link, &qt_interpreter_events::update_gui_lexer_signal,\n           this, &main_window::update_gui_lexer_signal);\n}\n\nQAction *\nmain_window::add_action (QMenu *menu, const QIcon& icon,\n                         const QString& text, const char *member,\n                         const QWidget *receiver)\n{\n  QAction *a;\n\n  if (receiver)\n    a = menu->addAction (icon, text, receiver, member);\n  else\n    a = menu->addAction (icon, text, this, member);\n\n  addAction (a);  // important for shortcut context\n  a->setShortcutContext (Qt::ApplicationShortcut);\n  return a;\n}\n\nQMenu *\nmain_window::m_add_menu (QMenuBar *p, QString name)\n{\n  QMenu *menu = p->addMenu (name);\n\n  QString base_name = name;  // get a copy\n  // replace intended '&' (\"&&\") by a temp. string\n  base_name.replace (\"&&\", \"___octave_amp_replacement___\");\n  // remove single '&' (shortcut)\n  base_name.remove (\"&\");\n  // restore intended '&'\n  base_name.replace (\"___octave_amp_replacement___\", \"&&\");\n\n  // remember names with and without shortcut\n  m_hash_menu_text[menu] = QStringList ({ name, base_name });\n\n  return menu;\n}\n\nvoid\nmain_window::construct_menu_bar ()\n{\n  QMenuBar *menu_bar = menuBar ();\n\n  construct_file_menu (menu_bar);\n\n  construct_edit_menu (menu_bar);\n\n  construct_debug_menu (menu_bar);\n\n  construct_tools_menu (menu_bar);\n\n  construct_window_menu (menu_bar);\n\n  construct_help_menu (menu_bar);\n\n  construct_news_menu (menu_bar);\n\n#if defined (HAVE_QSCINTILLA)\n  // call the editor to add actions which should also be available in the\n  // editor's menu and tool bar\n  QList<QAction *> shared_actions =\n  {\n    m_new_script_action,\n    m_new_function_action,\n    m_open_action,\n    m_find_files_action,\n    m_undo_action,\n    m_copy_action,\n    m_paste_action,\n    m_select_all_action\n  };\n  m_editor_window->insert_global_actions (shared_actions);\n#endif\n}\n\nvoid\nmain_window::construct_file_menu (QMenuBar *p)\n{\n  QMenu *file_menu = m_add_menu (p, tr (\"&File\"));\n\n  construct_new_menu (file_menu);\n\n  gui_settings settings;\n\n  m_open_action\n    = add_action (file_menu, settings.icon (\"document-open\"), tr (\"Open...\"),\n                  SLOT (request_open_file ()), this);\n  m_open_action->setToolTip (tr (\"Open an existing file in editor\"));\n\n#if defined (HAVE_QSCINTILLA)\n  file_menu->addMenu (m_editor_window->get_mru_menu ());\n#endif\n\n  file_menu->addSeparator ();\n\n  m_load_workspace_action\n    = add_action (file_menu, QIcon (), tr (\"Load Workspace...\"),\n                  SLOT (handle_load_workspace_request ()), this);\n\n  m_save_workspace_action\n    = add_action (file_menu, QIcon (), tr (\"Save Workspace As...\"),\n                  SLOT (handle_save_workspace_request ()), this);\n\n  file_menu->addSeparator ();\n\n  m_exit_action\n    = add_action (file_menu, QIcon (), tr (\"Exit\"),\n                  SLOT (close ()), this);\n  m_exit_action->setMenuRole (QAction::QuitRole);\n\n  // Connect signal related to opening or creating editor files\n  connect (this, SIGNAL (new_file_signal (const QString&)),\n           m_active_editor, SLOT (request_new_file (const QString&)));\n\n  connect (this, SIGNAL (open_file_signal (const QString&)),\n           m_active_editor, SLOT (request_open_file (const QString&)));\n\n  connect (this,\n           SIGNAL (open_file_signal (const QString&, const QString&, int)),\n           m_active_editor,\n           SLOT (request_open_file (const QString&, const QString&, int)));\n}\n\nvoid\nmain_window::construct_new_menu (QMenu *p)\n{\n  QMenu *new_menu = p->addMenu (tr (\"New\"));\n\n  gui_settings settings;\n\n  m_new_script_action\n    = add_action (new_menu, settings.icon (\"document-new\"), tr (\"New Script\"),\n                  SLOT (request_new_script ()), this);\n\n  m_new_function_action\n    = add_action (new_menu, QIcon (), tr (\"New Function...\"),\n                  SLOT (request_new_function ()), this);\n\n  m_new_figure_action\n    = add_action (new_menu, QIcon (), tr (\"New Figure\"),\n                  SLOT (handle_new_figure_request ()), this);\n}\n\nvoid\nmain_window::construct_edit_menu (QMenuBar *p)\n{\n  QMenu *edit_menu = m_add_menu (p, tr (\"&Edit\"));\n\n  gui_settings settings;\n\n  m_undo_action\n    = edit_menu->addAction (settings.icon (\"edit-undo\"), tr (\"Undo\"));\n  m_undo_action->setShortcutContext (Qt::ApplicationShortcut);\n\n  edit_menu->addSeparator ();\n\n  m_copy_action\n    = edit_menu->addAction (settings.icon (\"edit-copy\"), tr (\"Copy\"), this,\n                            &main_window::copyClipboard);\n  m_copy_action->setShortcutContext (Qt::ApplicationShortcut);\n\n  m_paste_action\n    = edit_menu->addAction (settings.icon (\"edit-paste\"), tr (\"Paste\"), this,\n                            &main_window::pasteClipboard);\n  m_paste_action->setShortcutContext (Qt::ApplicationShortcut);\n\n  m_select_all_action\n    = edit_menu->addAction (tr (\"Select All\"), this,\n                            &main_window::selectAll);\n  m_select_all_action->setShortcutContext (Qt::ApplicationShortcut);\n\n  m_clear_clipboard_action\n    = edit_menu->addAction (tr (\"Clear Clipboard\"), this,\n                            &main_window::clear_clipboard);\n\n  edit_menu->addSeparator ();\n\n  m_find_files_action\n    = edit_menu->addAction (settings.icon (\"edit-find\"),\n                            tr (\"Find Files...\"));\n\n  edit_menu->addSeparator ();\n\n  m_clear_command_window_action\n    = edit_menu->addAction (tr (\"Clear Command Window\"));\n\n  m_clear_command_history_action\n    = edit_menu->addAction (tr (\"Clear Command History\"));\n\n  m_clear_workspace_action\n    = edit_menu->addAction (tr (\"Clear Workspace\"));\n\n  edit_menu->addSeparator ();\n\n  m_set_path_action\n    = edit_menu->addAction (tr (\"Set Path...\"));\n\n  m_preferences_action\n    = edit_menu->addAction (settings.icon (\"preferences-system\"),\n                            tr (\"Preferences...\"));\n\n  connect (m_find_files_action, &QAction::triggered,\n           this, [this] () { find_files (); });\n\n  connect (m_clear_command_window_action, &QAction::triggered,\n           this, &main_window::handle_clear_command_window_request);\n\n  connect (m_clear_command_history_action, &QAction::triggered,\n           this, &main_window::handle_clear_history_request);\n\n  connect (m_clear_workspace_action, &QAction::triggered,\n           this, &main_window::handle_clear_workspace_request);\n\n  connect (m_clipboard, &QClipboard::dataChanged,\n           this, &main_window::clipboard_has_changed);\n  clipboard_has_changed ();\n#if defined (Q_OS_WIN32)\n  // Always enable paste action (unreliable clipboard signals in windows)\n  // FIXME: This has to be removed, when the clipboard signals in windows\n  //        are working again\n  m_paste_action->setEnabled (true);\n  m_clear_clipboard_action->setEnabled (true);\n#endif\n\n  connect (m_preferences_action, &QAction::triggered,\n           this, [this] () { process_settings_dialog_request (); });\n\n  connect (m_set_path_action, &QAction::triggered,\n           this, &main_window::handle_set_path_dialog_request);\n\n}\n\nQAction *\nmain_window::construct_debug_menu_item (const char *icon,\n                                        const QString& item,\n                                        const char *member)\n{\n  gui_settings settings;\n\n  QAction *action = add_action (m_debug_menu, settings.icon (QString (icon)),\n                                item, member);\n\n  action->setEnabled (false);\n\n#if defined (HAVE_QSCINTILLA)\n  m_editor_window->debug_menu ()->addAction (action);\n  m_editor_window->toolbar ()->addAction (action);\n#endif\n\n  return action;\n}\n\nvoid\nmain_window::construct_debug_menu (QMenuBar *p)\n{\n  m_debug_menu = m_add_menu (p, tr (\"De&bug\"));\n\n  m_debug_step_over\n    = construct_debug_menu_item (\"db-step\", tr (\"Step\"),\n                                 SLOT (debug_step_over ()));\n\n  m_debug_step_into\n    = construct_debug_menu_item (\"db-step-in\", tr (\"Step In\"),\n                                 SLOT (debug_step_into ()));\n\n  m_debug_step_out\n    = construct_debug_menu_item (\"db-step-out\", tr (\"Step Out\"),\n                                 SLOT (debug_step_out ()));\n\n  m_debug_continue\n    = construct_debug_menu_item (\"db-cont\", tr (\"Continue\"),\n                                 SLOT (debug_continue ()));\n\n  m_debug_menu->addSeparator ();\n#if defined (HAVE_QSCINTILLA)\n  m_editor_window->debug_menu ()->addSeparator ();\n#endif\n\n  m_debug_quit\n    = construct_debug_menu_item (\"db-stop\", tr (\"Quit Debug Mode\"),\n                                 SLOT (debug_quit ()));\n}\n\nvoid\nmain_window::construct_tools_menu (QMenuBar *p)\n{\n  QMenu *tools_menu = m_add_menu (p, tr (\"&Tools\"));\n\n  m_profiler_start = add_action (tools_menu, QIcon (),\n                                 tr (\"Start &Profiler Session\"), SLOT (profiler_session ()));\n\n  m_profiler_resume = add_action (tools_menu, QIcon (),\n                                  tr (\"&Resume Profiler Session\"), SLOT (profiler_session_resume ()));\n\n  m_profiler_stop = add_action (tools_menu, QIcon (),\n                                tr (\"&Stop Profiler\"), SLOT (profiler_stop ()));\n  m_profiler_stop->setEnabled (false);\n\n  m_profiler_show = add_action (tools_menu, QIcon (),\n                                tr (\"&Show Profiler Data\"), SLOT (profiler_show ()));\n}\n\nvoid\nmain_window::editor_tabs_changed (bool have_tabs, bool is_octave)\n{\n  // Set state of actions which depend on the existence of editor tabs\n  m_editor_has_tabs = have_tabs;\n  m_editor_is_octave_file = is_octave;\n  m_debug_step_over->setEnabled (have_tabs && is_octave);\n}\n\nQAction *\nmain_window::construct_window_menu_item (QMenu *p,\n    const QString& item,\n    bool checkable,\n    QWidget *widget)\n{\n  QAction *action = p->addAction (QIcon (), item);\n\n  addAction (action);  // important for shortcut context\n  action->setCheckable (checkable);\n  action->setShortcutContext (Qt::ApplicationShortcut);\n\n  if (widget)  // might be zero for m_editor_window\n    {\n      if (checkable)\n        {\n          // action for visibility of dock widget\n          connect (action, SIGNAL (toggled (bool)),\n                   widget, SLOT (setVisible (bool)));\n\n          connect (widget, SIGNAL (active_changed (bool)),\n                   action, SLOT (setChecked (bool)));\n        }\n      else\n        {\n          // action for focus of dock widget\n          connect (action, SIGNAL (triggered ()),\n                   widget, SLOT (activate ()));\n        }\n    }\n  else\n    {\n      action->setEnabled (false);\n    }\n\n  return action;\n}\n\nvoid\nmain_window::construct_window_menu (QMenuBar *p)\n{\n  QMenu *window_menu = m_add_menu (p, tr (\"&Window\"));\n\n  m_show_command_window_action = construct_window_menu_item\n    (window_menu, tr (\"Show Command Window\"), true, m_command_window);\n\n  m_show_history_action = construct_window_menu_item\n    (window_menu, tr (\"Show Command History\"), true, m_history_window);\n\n  m_show_file_browser_action = construct_window_menu_item\n    (window_menu, tr (\"Show File Browser\"), true, m_file_browser_window);\n\n  m_show_workspace_action = construct_window_menu_item\n    (window_menu, tr (\"Show Workspace\"), true, m_workspace_window);\n\n  m_show_editor_action = construct_window_menu_item\n    (window_menu, tr (\"Show Editor\"), true, m_editor_window);\n\n  m_show_documentation_action = construct_window_menu_item\n    (window_menu, tr (\"Show Documentation\"), true, m_doc_browser_window);\n\n  m_show_variable_editor_action = construct_window_menu_item\n    (window_menu, tr (\"Show Variable Editor\"), true, m_variable_editor_window);\n\n  window_menu->addSeparator ();\n\n  m_command_window_action = construct_window_menu_item\n    (window_menu, tr (\"Command Window\"), false, m_command_window);\n\n  m_history_action = construct_window_menu_item\n    (window_menu, tr (\"Command History\"), false, m_history_window);\n\n  m_file_browser_action = construct_window_menu_item\n    (window_menu, tr (\"File Browser\"), false, m_file_browser_window);\n\n  m_workspace_action = construct_window_menu_item\n    (window_menu, tr (\"Workspace\"), false, m_workspace_window);\n\n  m_editor_action = construct_window_menu_item\n    (window_menu, tr (\"Editor\"), false, m_editor_window);\n\n  m_documentation_action = construct_window_menu_item\n    (window_menu, tr (\"Documentation\"), false, m_doc_browser_window);\n\n  m_variable_editor_action = construct_window_menu_item\n    (window_menu, tr (\"Variable Editor\"), false, m_variable_editor_window);\n\n  window_menu->addSeparator ();\n\n  m_previous_dock_action = add_action (window_menu, QIcon (),\n                                       tr (\"Previous Widget\"), SLOT (go_to_previous_widget ()));\n\n  window_menu->addSeparator ();\n\n  m_reset_windows_action = add_action (window_menu, QIcon (),\n                                       tr (\"Reset Default Window Layout\"), SLOT (reset_windows ()));\n}\n\nvoid\nmain_window::construct_help_menu (QMenuBar *p)\n{\n  QMenu *help_menu = m_add_menu (p, tr (\"&Help\"));\n\n  construct_documentation_menu (help_menu);\n\n  help_menu->addSeparator ();\n\n  m_report_bug_action = add_action (help_menu, QIcon (),\n                                    tr (\"Report Bug\"), SLOT (open_bug_tracker_page ()));\n\n  m_octave_packages_action = add_action (help_menu, QIcon (),\n                                         tr (\"Octave Packages\"), SLOT (open_octave_packages_page ()));\n\n  m_contribute_action = add_action (help_menu, QIcon (),\n                                    tr (\"Get Involved\"), SLOT (open_contribute_page ()));\n\n  m_developer_action = add_action (help_menu, QIcon (),\n                                   tr (\"Donate to Octave\"), SLOT (open_donate_page ()));\n\n  help_menu->addSeparator ();\n\n  m_about_octave_action = add_action (help_menu, QIcon (),\n                                      tr (\"About Octave\"), SLOT (show_about_octave ()));\n}\n\nvoid\nmain_window::construct_documentation_menu (QMenu *p)\n{\n  QMenu *doc_menu = p->addMenu (tr (\"Documentation\"));\n\n  m_ondisk_doc_action = add_action (doc_menu, QIcon (),\n                                    tr (\"On Disk\"), SLOT (activate ()), m_doc_browser_window);\n\n  m_online_doc_action = add_action (doc_menu, QIcon (),\n                                    tr (\"Online\"), SLOT (open_online_documentation_page ()));\n}\n\nvoid\nmain_window::construct_news_menu (QMenuBar *p)\n{\n  QMenu *news_menu = m_add_menu (p, tr (\"&News\"));\n\n  m_release_notes_action\n    = news_menu->addAction (QIcon (), tr (\"Release Notes\"),\n                            [this] () { Q_EMIT show_release_notes_signal (); });\n  addAction (m_release_notes_action);\n  m_release_notes_action->setShortcutContext (Qt::ApplicationShortcut);\n\n  m_current_news_action\n    = news_menu->addAction (QIcon (), tr (\"Community News\"),\n                            [this] () { Q_EMIT show_community_news_signal (-1); });\n  addAction (m_current_news_action);\n  m_current_news_action->setShortcutContext (Qt::ApplicationShortcut);\n}\n\nvoid\nmain_window::construct_tool_bar ()\n{\n  m_main_tool_bar = addToolBar (tr (\"Toolbar\"));\n  m_main_tool_bar->setStyleSheet (m_main_tool_bar->styleSheet ()\n                                  + global_toolbar_style);\n\n  m_main_tool_bar->setObjectName (\"MainToolBar\");\n  m_main_tool_bar->addAction (m_new_script_action);\n  m_main_tool_bar->addAction (m_open_action);\n\n  m_main_tool_bar->addSeparator ();\n\n  m_main_tool_bar->addAction (m_copy_action);\n  m_main_tool_bar->addAction (m_paste_action);\n  m_main_tool_bar->addAction (m_undo_action);\n\n  m_main_tool_bar->addSeparator ();\n\n  m_current_directory_combo_box = new QComboBox (this);\n  QFontMetrics fm = m_current_directory_combo_box->fontMetrics ();\n  m_current_directory_combo_box->setFixedWidth (48*fm.averageCharWidth ());\n  m_current_directory_combo_box->setEditable (true);\n  m_current_directory_combo_box->setInsertPolicy (QComboBox::NoInsert);\n  m_current_directory_combo_box->setToolTip (tr (\"Enter directory name\"));\n  m_current_directory_combo_box->setMaxVisibleItems (CURRENT_DIRECTORY_MAX_VISIBLE);\n  m_current_directory_combo_box->setMaxCount (CURRENT_DIRECTORY_MAX_COUNT);\n  QSizePolicy sizePol (QSizePolicy::Preferred, QSizePolicy::Preferred);\n  m_current_directory_combo_box->setSizePolicy (sizePol);\n\n  // addWidget takes ownership of the objects so there is no\n  // need to delete these upon destroying this main_window.\n  m_main_tool_bar->addWidget (new QLabel (tr (\"Current Directory: \")));\n  m_main_tool_bar->addWidget (m_current_directory_combo_box);\n\n  gui_settings settings;\n\n  QAction *current_dir_up\n    = m_main_tool_bar->addAction (settings.icon (\"folder-up\", false, \"go-up\"),\n                                  tr (\"One directory up\"));\n  QAction *current_dir_search\n    = m_main_tool_bar->addAction (settings.icon (\"folder\"),\n                                  tr (\"Browse directories\"));\n\n#if defined (HAVE_QCOMBOBOX_TEXTACTIVATED)\n  connect (m_current_directory_combo_box, &QComboBox::textActivated,\n           this, &main_window::set_current_working_directory);\n#else\n  connect (m_current_directory_combo_box, SIGNAL (activated (const QString&)),\n           this, SLOT (set_current_working_directory (const QString&)));\n#endif\n\n  connect (m_current_directory_combo_box->lineEdit (),\n           &QLineEdit::returnPressed,\n           this, &main_window::accept_directory_line_edit);\n\n  connect (current_dir_search, &QAction::triggered,\n           this, &main_window::browse_for_directory);\n\n  connect (current_dir_up, &QAction::triggered,\n           this, &main_window::change_directory_up);\n\n  connect (m_undo_action, &QAction::triggered,\n           this, &main_window::handle_undo_request);\n}\n\nvoid\nmain_window::focus_console_after_command ()\n{\n  gui_settings settings;\n\n  if (settings.bool_value (cs_focus_cmd))\n    focus_command_window ();\n}\n\nvoid\nmain_window::configure_shortcuts ()\n{\n  gui_settings settings;\n\n  bool enable\n    = ! ((m_active_dock == m_command_window) && m_prevent_readline_conflicts);\n\n  // file menu\n  settings.set_shortcut (m_open_action, sc_main_file_open_file, enable);\n  settings.set_shortcut (m_new_script_action, sc_main_file_new_file, enable);\n  settings.set_shortcut (m_new_function_action, sc_main_file_new_function, enable);\n  settings.set_shortcut (m_new_figure_action, sc_main_file_new_figure, enable);\n  settings.set_shortcut (m_load_workspace_action, sc_main_file_load_workspace, enable);\n  settings.set_shortcut (m_save_workspace_action, sc_main_file_save_workspace, enable);\n  settings.set_shortcut (m_exit_action, sc_main_file_exit, enable);\n\n  // edit menu\n  settings.set_shortcut (m_copy_action, sc_main_edit_copy, enable);\n  settings.set_shortcut (m_paste_action, sc_main_edit_paste, enable);\n  settings.set_shortcut (m_undo_action, sc_main_edit_undo, enable);\n  settings.set_shortcut (m_select_all_action, sc_main_edit_select_all, enable);\n  settings.set_shortcut (m_clear_clipboard_action, sc_main_edit_clear_clipboard, enable);\n  settings.set_shortcut (m_find_files_action, sc_main_edit_find_in_files, enable);\n  settings.set_shortcut (m_clear_command_history_action, sc_main_edit_clear_history, enable);\n  settings.set_shortcut (m_clear_command_window_action, sc_main_edit_clear_command_window, enable);\n  settings.set_shortcut (m_clear_workspace_action, sc_main_edit_clear_workspace, enable);\n  settings.set_shortcut (m_set_path_action, sc_main_edit_set_path, enable);\n  settings.set_shortcut (m_preferences_action, sc_main_edit_preferences, enable);\n\n  // debug menu\n  settings.set_shortcut (m_debug_step_over, sc_main_debug_step_over, enable);\n  settings.set_shortcut (m_debug_step_into, sc_main_debug_step_into, enable);\n  settings.set_shortcut (m_debug_step_out, sc_main_debug_step_out, enable);\n  settings.set_shortcut (m_debug_continue, sc_main_debug_continue, enable);\n  settings.set_shortcut (m_debug_quit, sc_main_debug_quit, enable);\n\n  // tools menu\n  settings.set_shortcut (m_profiler_start, sc_main_tools_start_profiler, enable);\n  settings.set_shortcut (m_profiler_resume, sc_main_tools_resume_profiler, enable);\n  settings.set_shortcut (m_profiler_stop, sc_main_tools_start_profiler, enable); // same, toggling\n  settings.set_shortcut (m_profiler_show, sc_main_tools_show_profiler, enable);\n\n  // window menu\n  settings.set_shortcut (m_show_command_window_action, sc_main_window_show_command, enable);\n  settings.set_shortcut (m_show_history_action, sc_main_window_show_history, enable);\n  settings.set_shortcut (m_show_workspace_action, sc_main_window_show_workspace, enable);\n  settings.set_shortcut (m_show_file_browser_action, sc_main_window_show_file_browser, enable);\n  settings.set_shortcut (m_show_editor_action, sc_main_window_show_editor, enable);\n  settings.set_shortcut (m_show_documentation_action, sc_main_window_show_doc, enable);\n  settings.set_shortcut (m_show_variable_editor_action, sc_main_window_show_variable_editor, enable);\n  settings.set_shortcut (m_reset_windows_action, sc_main_window_reset, enable);\n  settings.set_shortcut (m_command_window_action, sc_main_window_command, enable);\n  // Switching to the other widgets (including the previous one) is always enabled\n  settings.set_shortcut (m_history_action, sc_main_window_history, true);\n  settings.set_shortcut (m_workspace_action, sc_main_window_workspace, true);\n  settings.set_shortcut (m_file_browser_action, sc_main_window_file_browser, true);\n  settings.set_shortcut (m_editor_action, sc_main_window_editor, true);\n  settings.set_shortcut (m_documentation_action, sc_main_window_doc, true);\n  settings.set_shortcut (m_variable_editor_action, sc_main_window_variable_editor, true);\n  settings.set_shortcut (m_previous_dock_action, sc_main_window_previous_dock, true);\n\n  // help menu\n  settings.set_shortcut (m_ondisk_doc_action, sc_main_help_ondisk_doc, enable);\n  settings.set_shortcut (m_online_doc_action, sc_main_help_online_doc, enable);\n  settings.set_shortcut (m_report_bug_action, sc_main_help_report_bug, enable);\n  settings.set_shortcut (m_octave_packages_action, sc_main_help_packages, enable);\n  settings.set_shortcut (m_contribute_action, sc_main_help_contribute, enable);\n  settings.set_shortcut (m_developer_action, sc_main_help_developer, enable);\n  settings.set_shortcut (m_about_octave_action, sc_main_help_about, enable);\n\n  // news menu\n  settings.set_shortcut (m_release_notes_action, sc_main_news_release_notes, enable);\n  settings.set_shortcut (m_current_news_action, sc_main_news_community_news, enable);\n}\n\nQList<octave_dock_widget *>\nmain_window::dock_widget_list ()\n{\n  QList<octave_dock_widget *> list = QList<octave_dock_widget *> ();\n  list.append (static_cast<octave_dock_widget *> (m_command_window));\n  list.append (static_cast<octave_dock_widget *> (m_history_window));\n  list.append (static_cast<octave_dock_widget *> (m_file_browser_window));\n  list.append (static_cast<octave_dock_widget *> (m_doc_browser_window));\n#if defined (HAVE_QSCINTILLA)\n  list.append (static_cast<octave_dock_widget *> (m_editor_window));\n#endif\n  list.append (static_cast<octave_dock_widget *> (m_workspace_window));\n  list.append (static_cast<octave_dock_widget *> (m_variable_editor_window));\n  return list;\n}\n\nvoid\nmain_window::update_default_encoding (const QString& default_encoding)\n{\n  m_default_encoding = default_encoding;\n  std::string mfile_encoding = m_default_encoding.toStdString ();\n  if (m_default_encoding.startsWith (\"SYSTEM\", Qt::CaseInsensitive))\n    mfile_encoding = \"SYSTEM\";\n\n  Q_EMIT interpreter_event\n    ([mfile_encoding] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       Fmfile_encoding (interp, ovl (mfile_encoding));\n     });\n}\n\nvoid\nmain_window::resize_dock (QDockWidget *dw, int width, int height)\n{\n  // resizeDockWidget was added to Qt in Qt 5.6\n  if (width >= 0)\n    resizeDocks ({dw}, {width}, Qt::Horizontal);\n  if (height >= 0)\n    resizeDocks ({dw}, {height}, Qt::Vertical);\n}\n\n// The default main window size relative to the desktop size\nvoid\nmain_window::set_default_geometry ()\n{\n  int win_x, win_y;\n  get_screen_geometry (win_x, win_y);\n\n  move (0, 0);\n  resize (2*win_x/3, 7*win_y/8);\n}\n\nvoid\nmain_window::reset_windows ()\n{\n  // Slot for resetting the window layout to the default one\n  hide ();\n  showNormal ();              // Unmaximize\n  do_reset_windows (true, true, true);   // Add all widgets\n\n  // Re-add after giving time: This seems to be a reliable way to\n  // reset the main window's layout\n\n  // JWE says: The following also works for me with 0 delay, so I\n  // think the problem might just be that the event loop needs to run\n  // somewhere in the sequence of resizing and adding widgets.  Maybe\n  // some actions in do_reset_windows should be using signal/slot\n  // connections so that the event loop can do what it needs to do.\n  // But I haven't been able to find the magic sequence.\n\n  QTimer::singleShot (250, this, [this] () { do_reset_windows (true, true, true); });\n}\n\n// Create the default layout of the main window.  Do not use\n// restoreState () and restoreGeometry () with default values since\n// this might lead to problems when the Qt version changes\nvoid\nmain_window::do_reset_windows (bool show, bool save, bool force_all)\n{\n  // Set main window default geometry and store its width for\n  // later resizing the command window\n  set_default_geometry ();\n  int win_x = geometry ().width ();\n\n  // Resize command window (if docked),\n  //the important one in the default layout\n  if (dockWidgetArea (m_command_window) != Qt::NoDockWidgetArea)\n    resize_dock (m_command_window, 7*win_x/8, -1);\n\n#if defined (HAVE_QDOCKWIDGET_REORDERING_BUG)\n  setDockOptions (QMainWindow::AnimatedDocks\n                  | QMainWindow::AllowNestedDocks\n                  | QMainWindow::AllowTabbedDocks);\n#else\n  setDockNestingEnabled (true);\n#endif\n\n  // Add the dock widgets and show them\n  if (! m_file_browser_window->adopted () || force_all)\n    {\n      // FIXME: Maybe there should be a main_window::add_dock_widget\n      // function that combines both of these actions?\n\n      addDockWidget (Qt::LeftDockWidgetArea, m_file_browser_window);\n      m_file_browser_window->set_adopted (false);\n    }\n\n  if (! m_workspace_window->adopted () || force_all)\n    {\n      addDockWidget (Qt::LeftDockWidgetArea, m_workspace_window);\n      m_workspace_window->set_adopted (false);\n    }\n\n  if (! m_history_window->adopted () || force_all)\n    {\n      addDockWidget (Qt::LeftDockWidgetArea, m_history_window);\n      m_history_window->set_adopted (false);\n    }\n\n  if (! m_command_window->adopted () || force_all)\n    {\n      addDockWidget (Qt::RightDockWidgetArea, m_command_window);\n      m_command_window->set_adopted (false);\n    }\n\n  if (! m_doc_browser_window->adopted () || force_all)\n    {\n      addDockWidget (Qt::RightDockWidgetArea, m_doc_browser_window);\n      tabifyDockWidget (m_command_window, m_doc_browser_window);\n      m_doc_browser_window->set_adopted (false);\n    }\n\n  if (! m_variable_editor_window->adopted () || force_all)\n    {\n      addDockWidget (Qt::RightDockWidgetArea, m_variable_editor_window);\n      tabifyDockWidget (m_command_window, m_variable_editor_window);\n      m_variable_editor_window->set_adopted (false);\n    }\n\n#if defined (HAVE_QSCINTILLA)\n  addDockWidget (Qt::RightDockWidgetArea, m_editor_window);\n  tabifyDockWidget (m_command_window, m_editor_window);\n#endif\n\n  // Resize command window, the important one in the default layout\n  resize_dock (m_command_window, 2*win_x/3, -1);\n\n  // Show main wibdow, save state and geometry of main window and\n  // all dock widgets\n  if (show)\n    {\n      // Show all dock widgets\n      for (auto *widget : dock_widget_list ())\n        widget->show ();\n\n      // Show main window and store size and state\n      showNormal ();\n\n      if (save)\n        {\n          gui_settings settings;\n\n          settings.setValue (mw_geometry.settings_key (), saveGeometry ());\n          settings.setValue (mw_state.settings_key (), saveState ());\n        }\n\n      focus_command_window ();\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/main-window.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_main_window_h)\n#define octave_main_window_h 1\n\n// Qt includes\n#include <QCloseEvent>\n#include <QComboBox>\n#include <QMainWindow>\n#include <QPointer>\n#include <QQueue>\n#include <QStatusBar>\n#include <QTabWidget>\n#include <QThread>\n#include <QToolBar>\n#include <QToolButton>\n#include <QTranslator>\n\n// Editor includes\n#include \"external-editor-interface.h\"\n#include \"file-editor-interface.h\"\n\n// Own includes\n#include \"dialog.h\"\n#include \"documentation-dock-widget.h\"\n#include \"files-dock-widget.h\"\n#include \"find-files-dialog.h\"\n#include \"history-dock-widget.h\"\n#include \"interpreter-qobject.h\"\n#include \"led-indicator.h\"\n#include \"octave-dock-widget.h\"\n#include \"qt-interpreter-events.h\"\n#include \"set-path-dialog.h\"\n#include \"terminal-dock-widget.h\"\n#include \"variable-editor.h\"\n#include \"workspace-view.h\"\n\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass base_qobject;\nclass settings_dialog;\n\n//! Represents the main window.\n\nclass main_window : public QMainWindow\n{\n  Q_OBJECT\n\npublic:\n\n  typedef std::pair<std::string, std::string> name_pair;\n  typedef std::pair<int, int> int_pair;\n\n  main_window (base_qobject& oct_qobj);\n\n  ~main_window ();\n\n  void make_dock_widget_connections (octave_dock_widget *dw);\n\n  bool command_window_has_focus () const;\n\n  bool confirm_shutdown ();\n\nQ_SIGNALS:\n\n  // Note: CLOSE_GUI_SIGNAL is currently only used by the new\n  // experimental terminal widget.\n  void close_gui_signal ();\n\n  void active_dock_changed (octave_dock_widget *, octave_dock_widget *);\n  void editor_focus_changed (bool);\n\n  void settings_changed ();\n  void init_terminal_size_signal ();\n  void init_window_menu ();\n  void new_file_signal (const QString&);\n  void open_file_signal (const QString&);\n  void open_file_signal (const QString& file, const QString& enc, int line);\n  void step_into_file_signal ();\n\n  void show_community_news_signal (int serial);\n  void show_release_notes_signal ();\n\n  void update_gui_lexer_signal (bool);\n\n  void insert_debugger_pointer_signal (const QString& file, int line);\n  void delete_debugger_pointer_signal (const QString& file, int line);\n  void update_breakpoint_marker_signal (bool insert, const QString& file,\n                                        int line, const QString& cond);\n\n  void copyClipboard_signal ();\n  void pasteClipboard_signal ();\n  void selectAll_signal ();\n  void undo_signal ();\n\n  void add_actions_signal (QList<QAction *> action_list);\n\n  void warning_function_not_found_signal (const QString& message);\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\n  void execute_command_signal (const QString& command);\n\n  void get_input_from_terminal_signal (const QString& prompt);\n  void finished_input_from_terminal_signal (const QString& input);\n\n  void update_prompt_signal (const QString& prompt);\n\npublic Q_SLOTS:\n\n  void focus_command_window ();\n  void focus_changed (QWidget *w_old, QWidget *w_new);\n  void focus_window (const QString& win_name);\n  void request_reload_settings ();\n\n  void report_status_message (const QString& statusMessage);\n  void handle_save_workspace_request ();\n  void handle_load_workspace_request (const QString& file = QString ());\n  void handle_open_any_request (const QString& file = QString ());\n  void handle_clear_workspace_request ();\n  void handle_clear_command_window_request ();\n  void handle_clear_history_request ();\n  void handle_undo_request ();\n  void modify_path (const QStringList& dir_list, bool rm, bool subdirs);\n  void edit_mfile (const QString&, int);\n  void file_remove_proxy (const QString& o, const QString& n);\n  void open_online_documentation_page ();\n  void open_bug_tracker_page ();\n  void open_octave_packages_page ();\n  void open_contribute_page ();\n  void open_donate_page ();\n  void process_settings_dialog_request (const QString& desired_tab\n                                        = QString ());\n  void show_about_octave ();\n  void notice_settings (bool update_by_worker = false);\n  void prepare_to_exit ();\n  void go_to_previous_widget ();\n  void reset_windows ();\n  void do_reset_windows (bool show = true, bool save = true,\n                         bool force_all = false);\n\n  void update_octave_directory (const QString& dir);\n  void browse_for_directory ();\n  void set_current_working_directory (const QString& dir);\n  void change_directory_up ();\n  void accept_directory_line_edit ();\n\n  void execute_command_in_terminal (const QString& command);\n  void run_file_in_terminal (const QFileInfo& info, int opts);\n  void get_input_from_terminal (const QString& prompt);\n\n  void handle_new_figure_request ();\n\n  void handle_enter_debugger ();\n  void handle_exit_debugger ();\n  void debug_continue ();\n  void debug_step_into ();\n  void debug_step_over ();\n  void debug_step_out ();\n  void debug_quit ();\n  void editor_tabs_changed (bool, bool);\n\n  void request_open_file ();\n  void request_new_script (const QString& commands = QString ());\n  void request_new_function (bool triggered = true);\n  void handle_edit_mfile_request (const QString& name, const QString& file,\n                                  const QString& curr_dir, int line);\n\n  void handle_insert_debugger_pointer_request (const QString& file, int line);\n  void handle_delete_debugger_pointer_request (const QString& file, int line);\n  void handle_update_breakpoint_marker_request (bool insert,\n      const QString& file, int line,\n      const QString& cond);\n\n  void read_settings ();\n  void init_terminal_size ();\n  void set_window_layout ();\n  void write_settings ();\n\n  void copyClipboard ();\n  void pasteClipboard ();\n  void selectAll ();\n\n  void handle_gui_status_update (const QString& feature, const QString& status);\n\n  void focus_console_after_command ();\n\n  void profiler_session ();\n  void profiler_session_resume ();\n  void profiler_stop ();\n  void handle_profiler_status_update (bool);\n  void profiler_show ();\n\n  void handle_octave_ready ();\n\n  void handle_set_path_dialog_request ();\n\n  //! Find files dialog.\n  //!@{\n  void find_files (const QString& startdir = QString ());\n  void find_files_finished (int) { }\n  //!@}\n\n  void set_screen_size (int ht, int wd);\n\n  //! Handling the clipboard.\n  //!@{\n  void clipboard_has_changed ();\n  void clear_clipboard ();\n  //!@}\n\n  //! Returns a list of dock widgets.\n\n  QList<octave_dock_widget *> get_dock_widget_list ()\n  {\n    return dock_widget_list ();\n  }\n\nprivate Q_SLOTS:\n\n  void disable_menu_shortcuts (bool disable);\n  void restore_create_file_setting ();\n  void set_file_encoding (const QString& new_encoding);\n//  void request_open_files (const QStringList& open_file_names);\n\n  void warning_function_not_found (const QString& message);\n\nprotected:\n\n  void closeEvent (QCloseEvent *closeEvent);\n\nprivate:\n\n  void adopt_dock_widgets ();\n\n  void adopt_terminal_widget ();\n  void adopt_documentation_widget ();\n  void adopt_file_browser_widget ();\n  void adopt_history_widget ();\n  void adopt_workspace_widget ();\n  void adopt_editor_widget ();\n  void adopt_variable_editor_widget ();\n\n  void construct_central_widget ();\n\n  void construct ();\n\n  void construct_octave_qt_link ();\n\n  QAction * add_action (QMenu *menu, const QIcon& icon,\n                       const QString& text, const char *member,\n                       const QWidget *receiver = nullptr);\n\n  QMenu * m_add_menu (QMenuBar *p, QString text);\n  void construct_menu_bar ();\n  void construct_file_menu (QMenuBar *p);\n  void construct_new_menu (QMenu *p);\n  void construct_edit_menu (QMenuBar *p);\n  QAction * construct_debug_menu_item (const char *icon, const QString& item,\n                                      const char *member);\n  void construct_debug_menu (QMenuBar *p);\n  QAction * construct_window_menu_item (QMenu *p, const QString& item,\n                                       bool checkable, QWidget *);\n  void construct_tools_menu (QMenuBar *p);\n  void construct_window_menu (QMenuBar *p);\n  void construct_help_menu (QMenuBar *p);\n  void construct_documentation_menu (QMenu *p);\n\n  void construct_news_menu (QMenuBar *p);\n\n  void construct_tool_bar ();\n\n  void configure_shortcuts ();\n\n  QList<octave_dock_widget *> dock_widget_list ();\n\n  void update_default_encoding (const QString& default_encoding);\n\n  void set_default_geometry ();\n  void resize_dock (QDockWidget *dw, int width, int height);\n\n  base_qobject& m_octave_qobj;\n\n  QHash<QMenu *, QStringList> m_hash_menu_text;\n\n  QString m_default_encoding;\n\n  //! Toolbar.\n\n  QStatusBar *m_status_bar;\n  led_indicator *m_profiler_status_indicator;\n\n  //! Dock widgets.\n  //!@{\n  QPointer<terminal_dock_widget> m_command_window;\n  QPointer<history_dock_widget> m_history_window;\n  QPointer<files_dock_widget> m_file_browser_window;\n  QPointer<documentation_dock_widget> m_doc_browser_window;\n  QPointer<file_editor_interface> m_editor_window;\n  QPointer<workspace_view> m_workspace_window;\n  QPointer<variable_editor> m_variable_editor_window;\n  //!@}\n\n  file_system_browser *m_file_browser;\n  editor_files_browser *m_editor_files;\n\n  external_editor_interface *m_external_editor;\n  QWidget *m_active_editor;\n\n  octave_dock_widget *m_previous_dock;\n  octave_dock_widget *m_active_dock;\n\n  QToolBar *m_main_tool_bar;\n\n  QMenu *m_debug_menu;\n\n  QMenuBar *m_editor_menubar;\n\n  QAction *m_debug_continue;\n  QAction *m_debug_step_into;\n  QAction *m_debug_step_over;\n  QAction *m_debug_step_out;\n  QAction *m_debug_quit;\n\n  QAction *m_new_script_action;\n  QAction *m_new_function_action;\n  QAction *m_open_action;\n  QAction *m_new_figure_action;\n  QAction *m_load_workspace_action;\n  QAction *m_save_workspace_action;\n  QAction *m_set_path_action;\n  QAction *m_preferences_action;\n  QAction *m_exit_action;\n\n  QAction *m_copy_action;\n  QAction *m_paste_action;\n  QAction *m_clear_clipboard_action;\n  QAction *m_undo_action;\n  QAction *m_clear_command_window_action;\n  QAction *m_clear_command_history_action;\n  QAction *m_clear_workspace_action;\n  QAction *m_find_files_action;\n  QAction *m_select_all_action;\n\n  QAction *m_profiler_start;\n  QAction *m_profiler_resume;\n  QAction *m_profiler_stop;\n  QAction *m_profiler_show;\n\n  QAction *m_show_command_window_action;\n  QAction *m_show_history_action;\n  QAction *m_show_workspace_action;\n  QAction *m_show_file_browser_action;\n  QAction *m_show_editor_action;\n  QAction *m_show_documentation_action;\n  QAction *m_show_variable_editor_action;\n  QAction *m_command_window_action;\n  QAction *m_history_action;\n  QAction *m_workspace_action;\n  QAction *m_file_browser_action;\n  QAction *m_editor_action;\n  QAction *m_documentation_action;\n  QAction *m_variable_editor_action;\n  QAction *m_previous_dock_action;\n  QAction *m_reset_windows_action;\n\n  QAction *m_ondisk_doc_action;\n  QAction *m_online_doc_action;\n  QAction *m_report_bug_action;\n  QAction *m_octave_packages_action;\n  QAction *m_contribute_action;\n  QAction *m_developer_action;\n  QAction *m_about_octave_action;\n\n  QAction *m_release_notes_action;\n  QAction *m_current_news_action;\n\n  //! For Toolbars.\n  //!@{\n  QComboBox *m_current_directory_combo_box;\n  static const int CURRENT_DIRECTORY_MAX_VISIBLE = 16;\n  static const int CURRENT_DIRECTORY_MAX_COUNT = 16;\n  QLineEdit *m_current_directory_line_edit;\n  //!@}\n\n  //! Settings dialog as guarded pointer (set to 0 when deleted).\n\n  QPointer<settings_dialog> m_settings_dlg;\n\n  //! Find files dialog.\n\n  find_files_dialog *m_find_files_dlg;\n\n  //! Set path dialog\n  QPointer<set_path_dialog> m_set_path_dlg;\n\n  //! Release notes window.\n\n  QWidget *m_release_notes_window;\n\n  QClipboard *m_clipboard;\n\n  //! Some class global flags.\n  //!@{\n  bool m_prevent_readline_conflicts;\n  bool m_prevent_readline_conflicts_menu;\n  bool m_suppress_dbg_location;\n  bool m_editor_has_tabs;\n  bool m_editor_is_octave_file;\n\n  //! Flag for closing the whole application.\n\n  bool m_closing;\n  //!@}\n\n  QString m_file_encoding;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/module.mk",
    "content": "octave_gui_ICONS = \\\n  %reldir%/icons/license.md \\\n  %reldir%/icons/cursors/bottom_left_corner.png \\\n  %reldir%/icons/cursors/bottom_right_corner.png \\\n  %reldir%/icons/cursors/bottom_side.png \\\n  %reldir%/icons/cursors/circle.png \\\n  %reldir%/icons/cursors/cross.png \\\n  %reldir%/icons/cursors/fleur.png \\\n  %reldir%/icons/cursors/hand2.png \\\n  %reldir%/icons/cursors/left_side.png \\\n  %reldir%/icons/cursors/right_side.png \\\n  %reldir%/icons/cursors/top_left_corner.png \\\n  %reldir%/icons/cursors/top_right_corner.png \\\n  %reldir%/icons/cursors/top_side.png \\\n  %reldir%/icons/octave/index.theme \\\n  %reldir%/icons/octave/128x128/applications-system.png \\\n  %reldir%/icons/octave/128x128/bp-next.png \\\n  %reldir%/icons/octave/128x128/bp-prev.png \\\n  %reldir%/icons/octave/128x128/bp-rm-all.png \\\n  %reldir%/icons/octave/128x128/bp-toggle.png \\\n  %reldir%/icons/octave/128x128/bookmark-new.png \\\n  %reldir%/icons/octave/128x128/db-cont.png \\\n  %reldir%/icons/octave/128x128/db-step-in.png \\\n  %reldir%/icons/octave/128x128/db-step-out.png \\\n  %reldir%/icons/octave/128x128/db-step.png \\\n  %reldir%/icons/octave/128x128/db-stop.png \\\n  %reldir%/icons/octave/128x128/dialog-information.png \\\n  %reldir%/icons/octave/128x128/dialog-error.png \\\n  %reldir%/icons/octave/128x128/document-new.png \\\n  %reldir%/icons/octave/128x128/document-open.png \\\n  %reldir%/icons/octave/128x128/document-print.png \\\n  %reldir%/icons/octave/128x128/document-save-as.png \\\n  %reldir%/icons/octave/128x128/document-save.png \\\n  %reldir%/icons/octave/128x128/edit-copy.png \\\n  %reldir%/icons/octave/128x128/edit-cut.png \\\n  %reldir%/icons/octave/128x128/edit-find-replace.png \\\n  %reldir%/icons/octave/128x128/edit-find.png \\\n  %reldir%/icons/octave/128x128/edit-paste.png \\\n  %reldir%/icons/octave/128x128/edit-redo.png \\\n  %reldir%/icons/octave/128x128/edit-undo.png \\\n  %reldir%/icons/octave/128x128/figure-axes.png \\\n  %reldir%/icons/octave/128x128/figure-grid.png \\\n  %reldir%/icons/octave/128x128/figure-pan.png \\\n  %reldir%/icons/octave/128x128/figure-rotate.png \\\n  %reldir%/icons/octave/128x128/figure-text.png \\\n  %reldir%/icons/octave/128x128/figure-zoom-in.png \\\n  %reldir%/icons/octave/128x128/figure-zoom-original.png \\\n  %reldir%/icons/octave/128x128/figure-zoom-out.png \\\n  %reldir%/icons/octave/128x128/folder-new.png \\\n  %reldir%/icons/octave/128x128/folder-settings.png \\\n  %reldir%/icons/octave/128x128/folder-up.png \\\n  %reldir%/icons/octave/128x128/folder.png \\\n  %reldir%/icons/octave/128x128/go-down.png \\\n  %reldir%/icons/octave/128x128/go-first.png \\\n  %reldir%/icons/octave/128x128/go-home.png \\\n  %reldir%/icons/octave/128x128/go-last.png \\\n  %reldir%/icons/octave/128x128/go-next.png \\\n  %reldir%/icons/octave/128x128/go-previous.png \\\n  %reldir%/icons/octave/128x128/go-up.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_DocumentationDockWidget.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_Figure.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_FileEditor.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_FilesDockWidget.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_HistoryDockWidget.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_NewsDockWidget.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_ReleaseWidget.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_TerminalDockWidget.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_VariableEditor.png \\\n  %reldir%/icons/octave/128x128/graphic_logo_WorkspaceView.png \\\n  %reldir%/icons/octave/128x128/letter_logo_DocumentationDockWidget.png \\\n  %reldir%/icons/octave/128x128/letter_logo_FileEditor.png \\\n  %reldir%/icons/octave/128x128/letter_logo_FilesDockWidget.png \\\n  %reldir%/icons/octave/128x128/letter_logo_HistoryDockWidget.png \\\n  %reldir%/icons/octave/128x128/letter_logo_NewsDockWidget.png \\\n  %reldir%/icons/octave/128x128/letter_logo_ReleaseWidget.png \\\n  %reldir%/icons/octave/128x128/letter_logo_TerminalDockWidget.png \\\n  %reldir%/icons/octave/128x128/letter_logo_VariableEditor.png \\\n  %reldir%/icons/octave/128x128/letter_logo_WorkspaceView.png \\\n  %reldir%/icons/octave/128x128/logo.png \\\n  %reldir%/icons/octave/128x128/plot-xy-curve.png \\\n  %reldir%/icons/octave/128x128/system-run.png \\\n  %reldir%/icons/octave/128x128/user-home.png \\\n  %reldir%/icons/octave/128x128/view-zoom-in.png \\\n  %reldir%/icons/octave/128x128/view-zoom-original.png \\\n  %reldir%/icons/octave/128x128/view-zoom-out.png \\\n  %reldir%/icons/octave/128x128/widget-close-light.png \\\n  %reldir%/icons/octave/128x128/widget-close.png \\\n  %reldir%/icons/octave/128x128/widget-dock-light.png \\\n  %reldir%/icons/octave/128x128/widget-dock.png \\\n  %reldir%/icons/octave/128x128/widget-undock-light.png \\\n  %reldir%/icons/octave/128x128/widget-undock.png \\\n  %reldir%/icons/octave/128x128/window-close.png \\\n  %reldir%/icons/octave/scalable/applications-system.svg \\\n  %reldir%/icons/octave/scalable/bookmark-new.svg \\\n  %reldir%/icons/octave/scalable/bp-next.svg \\\n  %reldir%/icons/octave/scalable/bp-prev.svg \\\n  %reldir%/icons/octave/scalable/bp-rm-all.svg \\\n  %reldir%/icons/octave/scalable/bp-toggle.svg \\\n  %reldir%/icons/octave/scalable/db-cont.svg \\\n  %reldir%/icons/octave/scalable/db-step-in.svg \\\n  %reldir%/icons/octave/scalable/db-step-out.svg \\\n  %reldir%/icons/octave/scalable/db-step.svg \\\n  %reldir%/icons/octave/scalable/db-stop.svg \\\n  %reldir%/icons/octave/scalable/dialog-information.svg \\\n  %reldir%/icons/octave/scalable/dialog-error.svg \\\n  %reldir%/icons/octave/scalable/document-new.svg \\\n  %reldir%/icons/octave/scalable/document-open.svg \\\n  %reldir%/icons/octave/scalable/document-print.svg \\\n  %reldir%/icons/octave/scalable/document-save-as.svg \\\n  %reldir%/icons/octave/scalable/document-save.svg \\\n  %reldir%/icons/octave/scalable/edit-copy.svg \\\n  %reldir%/icons/octave/scalable/edit-cut.svg \\\n  %reldir%/icons/octave/scalable/edit-find-replace.svg \\\n  %reldir%/icons/octave/scalable/edit-find.svg \\\n  %reldir%/icons/octave/scalable/edit-paste.svg \\\n  %reldir%/icons/octave/scalable/edit-redo.svg \\\n  %reldir%/icons/octave/scalable/edit-undo.svg \\\n  %reldir%/icons/octave/scalable/figure-axes.svg \\\n  %reldir%/icons/octave/scalable/figure-grid.svg \\\n  %reldir%/icons/octave/scalable/figure-pan.svg \\\n  %reldir%/icons/octave/scalable/figure-rotate.svg \\\n  %reldir%/icons/octave/scalable/figure-text.svg \\\n  %reldir%/icons/octave/scalable/figure-zoom-in.svg \\\n  %reldir%/icons/octave/scalable/figure-zoom-original.svg \\\n  %reldir%/icons/octave/scalable/figure-zoom-out.svg \\\n  %reldir%/icons/octave/scalable/folder-new.svg \\\n  %reldir%/icons/octave/scalable/folder-settings.svg \\\n  %reldir%/icons/octave/scalable/folder-up.svg \\\n  %reldir%/icons/octave/scalable/folder.svg \\\n  %reldir%/icons/octave/scalable/go-down.svg \\\n  %reldir%/icons/octave/scalable/go-first.svg \\\n  %reldir%/icons/octave/scalable/go-home.svg \\\n  %reldir%/icons/octave/scalable/go-last.svg \\\n  %reldir%/icons/octave/scalable/go-next.svg \\\n  %reldir%/icons/octave/scalable/go-previous.svg \\\n  %reldir%/icons/octave/scalable/go-up.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_DocumentationDockWidget.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_Figure.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_FileEditor.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_FilesDockWidget.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_HistoryDockWidget.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_NewsDockWidget.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_ReleaseWidget.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_TerminalDockWidget.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_VariableEditor.svg \\\n  %reldir%/icons/octave/scalable/graphic_logo_WorkspaceView.svg \\\n  %reldir%/icons/octave/scalable/letter_logo_DocumentationDockWidget.svg \\\n  %reldir%/icons/octave/scalable/letter_logo_FileEditor.svg \\\n  %reldir%/icons/octave/scalable/letter_logo_FilesDockWidget.svg \\\n  %reldir%/icons/octave/scalable/letter_logo_HistoryDockWidget.svg \\\n  %reldir%/icons/octave/scalable/letter_logo_NewsDockWidget.svg \\\n  %reldir%/icons/octave/scalable/letter_logo_ReleaseWidget.svg \\\n  %reldir%/icons/octave/scalable/letter_logo_TerminalDockWidget.svg \\\n  %reldir%/icons/octave/scalable/letter_logo_VariableEditor.svg \\\n  %reldir%/icons/octave/scalable/letter_logo_WorkspaceView.svg \\\n  %reldir%/icons/octave/scalable/logo.svg \\\n  %reldir%/icons/octave/scalable/plot-xy-curve.svg \\\n  %reldir%/icons/octave/scalable/system-run.svg \\\n  %reldir%/icons/octave/scalable/user-home.svg \\\n  %reldir%/icons/octave/scalable/view-zoom-in.svg \\\n  %reldir%/icons/octave/scalable/view-zoom-original.svg \\\n  %reldir%/icons/octave/scalable/view-zoom-out.svg \\\n  %reldir%/icons/octave/scalable/widget-close-light.svg \\\n  %reldir%/icons/octave/scalable/widget-close.svg \\\n  %reldir%/icons/octave/scalable/widget-dock-light.svg \\\n  %reldir%/icons/octave/scalable/widget-dock.svg \\\n  %reldir%/icons/octave/scalable/widget-undock-light.svg \\\n  %reldir%/icons/octave/scalable/widget-undock.svg \\\n  %reldir%/icons/octave/scalable/window-close.svg \\\n  %reldir%/icons/tango/index.theme \\\n  %reldir%/icons/tango/128x128/applications-system.png \\\n  %reldir%/icons/tango/128x128/bookmark-new.png \\\n  %reldir%/icons/tango/128x128/bp-next.png \\\n  %reldir%/icons/tango/128x128/bp-prev.png \\\n  %reldir%/icons/tango/128x128/bp-rm-all.png \\\n  %reldir%/icons/tango/128x128/bp-toggle.png \\\n  %reldir%/icons/tango/128x128/db-cont.png \\\n  %reldir%/icons/tango/128x128/db-step-in.png \\\n  %reldir%/icons/tango/128x128/db-step-out.png \\\n  %reldir%/icons/tango/128x128/db-step.png \\\n  %reldir%/icons/tango/128x128/db-stop.png \\\n  %reldir%/icons/tango/128x128/dialog-error.png \\\n  %reldir%/icons/tango/128x128/dialog-information.png \\\n  %reldir%/icons/tango/128x128/dialog-warning.png \\\n  %reldir%/icons/tango/128x128/document-new.png \\\n  %reldir%/icons/tango/128x128/document-open.png \\\n  %reldir%/icons/tango/128x128/document-print.png \\\n  %reldir%/icons/tango/128x128/document-save.png \\\n  %reldir%/icons/tango/128x128/document-save-as.png \\\n  %reldir%/icons/tango/128x128/edit-copy.png \\\n  %reldir%/icons/tango/128x128/edit-cut.png \\\n  %reldir%/icons/tango/128x128/edit-delete.png \\\n  %reldir%/icons/tango/128x128/edit-find-replace.png \\\n  %reldir%/icons/tango/128x128/edit-find.png \\\n  %reldir%/icons/tango/128x128/edit-paste.png \\\n  %reldir%/icons/tango/128x128/edit-redo.png \\\n  %reldir%/icons/tango/128x128/edit-undo.png \\\n  %reldir%/icons/tango/128x128/folder-new.png \\\n  %reldir%/icons/tango/128x128/folder.png \\\n  %reldir%/icons/tango/128x128/go-down.png \\\n  %reldir%/icons/tango/128x128/go-first.png \\\n  %reldir%/icons/tango/128x128/go-home.png \\\n  %reldir%/icons/tango/128x128/go-last.png \\\n  %reldir%/icons/tango/128x128/go-next.png \\\n  %reldir%/icons/tango/128x128/go-previous.png \\\n  %reldir%/icons/tango/128x128/go-up.png \\\n  %reldir%/icons/tango/128x128/preferences-system.png \\\n  %reldir%/icons/tango/128x128/user-home.png \\\n  %reldir%/icons/tango/128x128/view-refresh.png \\\n  %reldir%/icons/tango/128x128/view-zoom-in.png \\\n  %reldir%/icons/tango/128x128/view-zoom-original.png \\\n  %reldir%/icons/tango/128x128/view-zoom-out.png \\\n  %reldir%/icons/tango/scalable/applications-system.svg \\\n  %reldir%/icons/tango/scalable/bookmark-new.svg \\\n  %reldir%/icons/tango/scalable/bp-next.svg \\\n  %reldir%/icons/tango/scalable/bp-prev.svg \\\n  %reldir%/icons/tango/scalable/bp-rm-all.svg \\\n  %reldir%/icons/tango/scalable/bp-toggle.svg \\\n  %reldir%/icons/tango/scalable/db-cont.svg \\\n  %reldir%/icons/tango/scalable/db-step-in.svg \\\n  %reldir%/icons/tango/scalable/db-step-out.svg \\\n  %reldir%/icons/tango/scalable/db-step.svg \\\n  %reldir%/icons/tango/scalable/db-stop.svg \\\n  %reldir%/icons/tango/scalable/dialog-error.svg \\\n  %reldir%/icons/tango/scalable/dialog-information.svg \\\n  %reldir%/icons/tango/scalable/dialog-warning.svg \\\n  %reldir%/icons/tango/scalable/document-new.svg \\\n  %reldir%/icons/tango/scalable/document-open.svg \\\n  %reldir%/icons/tango/scalable/document-print.svg \\\n  %reldir%/icons/tango/scalable/document-save.svg \\\n  %reldir%/icons/tango/scalable/document-save-as.svg \\\n  %reldir%/icons/tango/scalable/edit-copy.svg \\\n  %reldir%/icons/tango/scalable/edit-cut.svg \\\n  %reldir%/icons/tango/scalable/edit-delete.svg \\\n  %reldir%/icons/tango/scalable/edit-find-replace.svg \\\n  %reldir%/icons/tango/scalable/edit-find.svg \\\n  %reldir%/icons/tango/scalable/edit-paste.svg \\\n  %reldir%/icons/tango/scalable/edit-redo.svg \\\n  %reldir%/icons/tango/scalable/edit-undo.svg \\\n  %reldir%/icons/tango/scalable/folder-new.svg \\\n  %reldir%/icons/tango/scalable/folder.svg \\\n  %reldir%/icons/tango/scalable/go-down.svg \\\n  %reldir%/icons/tango/scalable/go-first.svg \\\n  %reldir%/icons/tango/scalable/go-home.svg \\\n  %reldir%/icons/tango/scalable/go-last.svg \\\n  %reldir%/icons/tango/scalable/go-next.svg \\\n  %reldir%/icons/tango/scalable/go-previous.svg \\\n  %reldir%/icons/tango/scalable/go-up.svg \\\n  %reldir%/icons/tango/scalable/preferences-system.svg \\\n  %reldir%/icons/tango/scalable/user-home.svg \\\n  %reldir%/icons/tango/scalable/view-refresh.svg \\\n  %reldir%/icons/tango/scalable/view-zoom-in.svg \\\n  %reldir%/icons/tango/scalable/view-zoom-original.svg \\\n  %reldir%/icons/tango/scalable/view-zoom-out.svg\n\noctave_gui_MOC =\n\nif AMCOND_HAVE_QSCINTILLA\n\nOCTAVE_GUI_SRC_M_EDITOR_MOC = \\\n  %reldir%/m-editor/moc-file-editor-interface.cc \\\n  %reldir%/m-editor/moc-file-editor-tab.cc \\\n  %reldir%/m-editor/moc-file-editor.cc \\\n  %reldir%/m-editor/moc-find-dialog.cc \\\n  %reldir%/m-editor/moc-octave-qscintilla.cc \\\n  %reldir%/m-editor/moc-octave-txt-lexer.cc \\\n  %reldir%/m-editor/moc-marker.cc\n\n$(OCTAVE_GUI_SRC_M_EDITOR_MOC): | %reldir%/m-editor/$(octave_dirstamp)\n\nOCTAVE_GUI_SRC_COMMAND_WIDGET_MOC = \\\n  %reldir%/moc-console-lexer.cc \\\n  %reldir%/moc-command-widget.cc\n\n$(OCTAVE_GUI_SRC_COMMAND_WIDGET_MOC): | %reldir%/$(octave_dirstamp)\n\noctave_gui_MOC += \\\n  $(OCTAVE_GUI_SRC_M_EDITOR_MOC) \\\n  $(OCTAVE_GUI_SRC_COMMAND_WIDGET_MOC)\n\nDIRSTAMP_FILES += \\\n  %reldir%/m-editor/$(octave_dirstamp)\n\nendif\n\nOCTAVE_GUI_SRC_MOC = \\\n  %reldir%/moc-external-editor-interface.cc \\\n  %reldir%/moc-community-news.cc \\\n  %reldir%/moc-dialog.cc \\\n  %reldir%/moc-documentation-dock-widget.cc \\\n  %reldir%/moc-documentation.cc \\\n  %reldir%/moc-documentation-bookmarks.cc \\\n  %reldir%/moc-dw-main-window.cc \\\n  %reldir%/moc-files-dock-widget.cc \\\n  %reldir%/moc-find-widget.cc \\\n  %reldir%/moc-gui-settings.cc \\\n  %reldir%/moc-history-dock-widget.cc \\\n  %reldir%/moc-interpreter-qobject.cc \\\n  %reldir%/moc-led-indicator.cc \\\n  %reldir%/moc-main-window.cc \\\n  %reldir%/moc-news-reader.cc \\\n  %reldir%/moc-octave-qobject.cc \\\n  %reldir%/moc-release-notes.cc \\\n  %reldir%/moc-self-listener.cc \\\n  %reldir%/moc-settings-dialog.cc \\\n  %reldir%/moc-terminal-dock-widget.cc \\\n  %reldir%/moc-color-picker.cc \\\n  %reldir%/moc-tab-bar.cc \\\n  %reldir%/moc-qt-interpreter-events.cc \\\n  %reldir%/moc-shortcuts-tree-widget.cc \\\n  %reldir%/moc-welcome-wizard.cc \\\n  %reldir%/moc-workspace-model.cc \\\n  %reldir%/moc-workspace-view.cc \\\n  %reldir%/moc-variable-editor.cc \\\n  %reldir%/moc-variable-editor-model.cc \\\n  %reldir%/moc-find-files-dialog.cc \\\n  %reldir%/moc-find-files-model.cc \\\n  %reldir%/moc-octave-dock-widget.cc \\\n  %reldir%/moc-set-path-dialog.cc \\\n  %reldir%/moc-set-path-model.cc\n\noctave_gui_MOC += \\\n  $(OCTAVE_GUI_SRC_MOC)\n\noctave_gui_RC = %reldir%/qrc-resource.cc\n\n$(octave_gui_RC): | %reldir%/$(octave_dirstamp)\n\nDIRSTAMP_FILES += \\\n  %reldir%/$(octave_dirstamp)\n\noctave_gui_UI = \\\n  %reldir%/settings-dialog.ui\n\noctave_gui_UI_H = $(patsubst %reldir%/%.ui, %reldir%/ui-%.h, $(octave_gui_UI))\n\n$(octave_gui_UI_H): | %reldir%/$(octave_dirstamp)\n\nBUILT_SOURCES += $(octave_gui_UI_H)\n\nnoinst_HEADERS += \\\n  %reldir%/command-widget.h \\\n  %reldir%/community-news.h \\\n  %reldir%/console-lexer.h \\\n  %reldir%/dialog.h \\\n  %reldir%/octave-dock-widget.h \\\n  %reldir%/documentation-dock-widget.h \\\n  %reldir%/documentation.h \\\n  %reldir%/documentation-bookmarks.h \\\n  %reldir%/dw-main-window.h \\\n  %reldir%/gui-preferences-all.h \\\n  %reldir%/gui-preferences-cs.h \\\n  %reldir%/gui-preferences-dc.h \\\n  %reldir%/gui-preferences-dw.h \\\n  %reldir%/gui-preferences-ed.h \\\n  %reldir%/gui-preferences-fb.h \\\n  %reldir%/gui-preferences-ff.h \\\n  %reldir%/gui-preferences-global.h \\\n  %reldir%/gui-preferences-gp.h \\\n  %reldir%/gui-preferences-hw.h \\\n  %reldir%/gui-preferences-mw.h \\\n  %reldir%/gui-preferences-nr.h \\\n  %reldir%/gui-preferences-pd.h \\\n  %reldir%/gui-preferences-sc.h \\\n  %reldir%/gui-preferences-sd.h \\\n  %reldir%/gui-preferences-ve.h \\\n  %reldir%/gui-preferences-ws.h \\\n  %reldir%/gui-preferences.h \\\n  %reldir%/gui-settings.h \\\n  %reldir%/external-editor-interface.h \\\n  %reldir%/files-dock-widget.h \\\n  %reldir%/find-widget.h \\\n  %reldir%/graphics-init.h \\\n  %reldir%/history-dock-widget.h \\\n  %reldir%/interpreter-qobject.h \\\n  %reldir%/led-indicator.h \\\n  %reldir%/m-editor/file-editor-interface.h \\\n  %reldir%/m-editor/file-editor-tab.h \\\n  %reldir%/m-editor/file-editor.h \\\n  %reldir%/m-editor/find-dialog.h \\\n  %reldir%/m-editor/octave-qscintilla.h \\\n  %reldir%/m-editor/octave-txt-lexer.h \\\n  %reldir%/m-editor/marker.h \\\n  %reldir%/main-window.h \\\n  %reldir%/news-reader.h \\\n  %reldir%/octave-qobject.h \\\n  %reldir%/octave-qt-features.h \\\n  %reldir%/qt-application.h \\\n  %reldir%/qt-interpreter-events.h \\\n  %reldir%/qt-utils.h \\\n  %reldir%/release-notes.h \\\n  %reldir%/self-listener.h \\\n  %reldir%/settings-dialog.h \\\n  %reldir%/shortcuts-tree-widget.h \\\n  %reldir%/tab-bar.h \\\n  %reldir%/terminal-dock-widget.h \\\n  %reldir%/color-picker.h \\\n  %reldir%/welcome-wizard.h \\\n  %reldir%/find-files-dialog.h \\\n  %reldir%/find-files-model.h \\\n  %reldir%/workspace-model.h \\\n  %reldir%/workspace-view.h \\\n  %reldir%/variable-editor.h \\\n  %reldir%/variable-editor-model.h \\\n  %reldir%/set-path-dialog.h \\\n  %reldir%/set-path-model.h \\\n  %reldir%/gui-utils.h\n\n\n%canon_reldir%_%canon_reldir%_la_SOURCES = \\\n  %reldir%/command-widget.cc \\\n  %reldir%/community-news.cc \\\n  %reldir%/console-lexer.cc \\\n  %reldir%/dialog.cc \\\n  %reldir%/documentation-dock-widget.cc \\\n  %reldir%/documentation.cc \\\n  %reldir%/documentation-bookmarks.cc \\\n  %reldir%/dw-main-window.cc \\\n  %reldir%/external-editor-interface.cc \\\n  %reldir%/files-dock-widget.cc \\\n  %reldir%/find-widget.cc \\\n  %reldir%/graphics-init.cc \\\n  %reldir%/gui-preferences-cs.cc \\\n  %reldir%/gui-preferences-dc.cc \\\n  %reldir%/gui-preferences-dw.cc \\\n  %reldir%/gui-preferences-ed.cc \\\n  %reldir%/gui-preferences-fb.cc \\\n  %reldir%/gui-preferences-ff.cc \\\n  %reldir%/gui-preferences-global.cc \\\n  %reldir%/gui-preferences-gp.cc \\\n  %reldir%/gui-preferences-hw.cc \\\n  %reldir%/gui-preferences-mw.cc \\\n  %reldir%/gui-preferences-nr.cc \\\n  %reldir%/gui-preferences-pd.cc \\\n  %reldir%/gui-preferences-sc.cc \\\n  %reldir%/gui-preferences-sd.cc \\\n  %reldir%/gui-preferences-ve.cc \\\n  %reldir%/gui-preferences-ws.cc \\\n  %reldir%/gui-preferences.cc \\\n  %reldir%/gui-settings.cc \\\n  %reldir%/history-dock-widget.cc \\\n  %reldir%/interpreter-qobject.cc \\\n  %reldir%/led-indicator.cc \\\n  %reldir%/m-editor/file-editor-tab.cc \\\n  %reldir%/m-editor/file-editor.cc \\\n  %reldir%/m-editor/find-dialog.cc \\\n  %reldir%/m-editor/octave-qscintilla.cc \\\n  %reldir%/m-editor/octave-txt-lexer.cc \\\n  %reldir%/m-editor/marker.cc \\\n  %reldir%/main-window.cc \\\n  %reldir%/news-reader.cc \\\n  %reldir%/octave-dock-widget.cc \\\n  %reldir%/octave-qobject.cc \\\n  %reldir%/qt-interpreter-events.cc \\\n  %reldir%/qt-application.cc \\\n  %reldir%/release-notes.cc \\\n  %reldir%/self-listener.cc \\\n  %reldir%/settings-dialog.cc \\\n  %reldir%/shortcuts-tree-widget.cc \\\n  %reldir%/tab-bar.cc \\\n  %reldir%/terminal-dock-widget.cc \\\n  %reldir%/color-picker.cc \\\n  %reldir%/welcome-wizard.cc \\\n  %reldir%/find-files-dialog.cc \\\n  %reldir%/find-files-model.cc \\\n  %reldir%/workspace-model.cc \\\n  %reldir%/workspace-view.cc \\\n  %reldir%/variable-editor.cc \\\n  %reldir%/variable-editor-model.cc \\\n  %reldir%/set-path-dialog.cc \\\n  %reldir%/set-path-model.cc \\\n  %reldir%/gui-utils.cc\n\nnodist_%canon_reldir%_%canon_reldir%_la_SOURCES = \\\n  $(octave_gui_MOC) \\\n  $(octave_gui_RC)\n\noctave_gui_MOC_H = $(octave_gui_MOC:.cc=.h)\n\n%canon_reldir%_%canon_reldir%_la_CPPFLAGS = \\\n  $(AM_CPPFLAGS) \\\n  $(FT2_CPPFLAGS) \\\n  $(FONTCONFIG_CPPFLAGS) \\\n  @OCTGUI_DLL_DEFS@ \\\n  @QT_CPPFLAGS@ \\\n  -I$(srcdir)/libgui/qterminal/libqterminal \\\n  -I%reldir% -I$(srcdir)/%reldir% \\\n  -Ilibgui/graphics -I$(srcdir)/libgui/graphics \\\n  -I$(srcdir)/%reldir%/m-editor \\\n  -Iliboctave \\\n  -I$(srcdir)/liboctave/array \\\n  -Iliboctave/numeric -I$(srcdir)/liboctave/numeric \\\n  -Iliboctave/operators -I$(srcdir)/liboctave/operators \\\n  -I$(srcdir)/liboctave/system \\\n  -I$(srcdir)/liboctave/util \\\n  -Ilibinterp -I$(srcdir)/libinterp \\\n  -I$(srcdir)/libinterp/template-inst \\\n  -Ilibinterp/parse-tree -I$(srcdir)/libinterp/parse-tree \\\n  -Ilibinterp/corefcn -I$(srcdir)/libinterp/corefcn \\\n  -I$(srcdir)/libinterp/octave-value \\\n  -I$(srcdir)/liboctave/wrappers\n\nnoinst_LTLIBRARIES += %reldir%/libgui-src.la\n\nlibgui_EXTRA_DIST += \\\n  %reldir%/resource.qrc \\\n  $(octave_gui_UI) \\\n  $(octave_gui_ICONS)\n\nlibgui_CLEANFILES += \\\n  $(octave_gui_MOC) \\\n  $(octave_gui_MOC_H) \\\n  $(octave_gui_UI_H) \\\n  $(octave_gui_RC)\n"
  },
  {
    "path": "libgui/src/news-reader.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include <QDateTime>\n#include <QString>\n\n#include \"news-reader.h\"\n#include \"gui-preferences-nr.h\"\n#include \"gui-settings.h\"\n\n#include \"url-transfer.h\"\n#include \"version.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid news_reader::process ()\n{\n  QString html_text;\n\n  if (m_connect_to_web)\n    {\n      // Run this part in a separate thread so Octave can continue to\n      // run while we wait for the page to load.  Then emit the signal\n      // to display it when we have the page contents.\n\n      QString url = m_base_url + '/' + m_page;\n      std::ostringstream buf;\n      url_transfer octave_dot_org (url.toStdString (), buf);\n\n      if (octave_dot_org.is_valid ())\n        {\n          Array<std::string> param;\n          octave_dot_org.http_get (param);\n\n          if (octave_dot_org.good ())\n            html_text = QString::fromStdString (buf.str ());\n        }\n\n      if (html_text.contains (\"this-is-the-gnu-octave-community-news-page\"))\n        {\n          if (m_serial >= 0)\n            {\n              gui_settings settings;\n\n              settings.setValue (nr_last_time.settings_key (),\n                                 QDateTime::currentDateTime ());\n\n              settings.sync ();\n\n              QString tag (\"community-news-page-serial=\");\n\n              int b = html_text.indexOf (tag);\n\n              if (b)\n                {\n                  b += tag.length ();\n\n                  int e = html_text.indexOf (\"\\n\", b);\n\n                  QString tmp = html_text.mid (b, e-b);\n\n                  int curr_page_serial = tmp.toInt ();\n\n                  if (curr_page_serial > m_serial)\n                    {\n                      settings.setValue (nr_last_news.settings_key (), curr_page_serial);\n                      settings.sync ();\n                    }\n                  else\n                    return;\n                }\n              else\n                return;\n            }\n        }\n      else\n        html_text = QString\n                    (tr (\"<html>\\n\"\n                         \"<body>\\n\"\n                         \"<p>\\n\"\n                         \"Octave's community news source seems to be unavailable.\\n\"\n                         \"</p>\\n\"\n                         \"<p>\\n\"\n                         \"For the latest news, please check\\n\"\n                         \"<a href=\\\"https://octave.org/community-news.html\\\">https://octave.org/community-news.html</a>\\n\"\n                         \"when you have a connection to the web (link opens in an external browser).\\n\"\n                         \"</p>\\n\"\n                         \"<p>\\n\"\n                         \"<small><em>&mdash; The Octave Developers, \") + OCTAVE_RELEASE_DATE + \"</em></small>\\n\"\n                     \"</p>\\n\"\n                     \"</body>\\n\"\n                     \"</html>\\n\");\n    }\n  else\n    html_text = QString\n                (tr (\"<html>\\n\"\n                     \"<body>\\n\"\n                     \"<p>\\n\"\n                     \"Connecting to the web to display the latest Octave Community news has been disabled.\\n\"\n                     \"</p>\\n\"\n                     \"<p>\\n\"\n                     \"For the latest news, please check\\n\"\n                     \"<a href=\\\"https://octave.org/community-news.html\\\">https://octave.org/community-news.html</a>\\n\"\n                     \"when you have a connection to the web (link opens in an external browser)\\n\"\n                     \"or enable web connections for news in Octave's network settings tab.\\n\"\n                     \"</p>\\n\"\n                     \"<p>\\n\"\n                     \"<small><em>&mdash; The Octave Developers, \") + OCTAVE_RELEASE_DATE + \"</em></small>\\n\"\n                 \"</p>\\n\"\n                 \"</body>\\n\"\n                 \"</html>\\n\");\n\n  Q_EMIT display_news_signal (html_text);\n\n  Q_EMIT finished ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/news-reader.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_news_reader_h)\n#define octave_news_reader_h 1\n\n#include <QObject>\n#include <QString>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass news_reader : public QObject\n{\n  Q_OBJECT\n\npublic:\n\n  news_reader (const QString& base_url, const QString& page,\n               int serial = -1, bool connect_to_web = false)\n    : QObject (), m_base_url (base_url),\n      m_page (page), m_serial (serial), m_connect_to_web (connect_to_web)\n  { }\n\nQ_SIGNALS:\n\n  void display_news_signal (const QString& news);\n\n  void finished ();\n\npublic Q_SLOTS:\n\n  void process ();\n\nprivate:\n\n  QString m_base_url;\n  QString m_page;\n  int m_serial;\n  bool m_connect_to_web;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/octave-dock-widget.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QAction>\n#include <QApplication>\n#include <QHBoxLayout>\n#include <QLabel>\n#include <QScreen>\n#include <QStyle>\n#include <QToolBar>\n#include <QMenuBar>\n#include <QWindow>\n\n#include \"gui-preferences-dw.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-mw.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-settings.h\"\n#include \"gui-utils.h\"\n#include \"main-window.h\"\n#include \"octave-dock-widget.h\"\n#include \"octave-qt-features.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nlabel_dock_widget::label_dock_widget (QWidget *p)\n  : QDockWidget (p), m_default_float_button (nullptr),\n    m_default_close_button (nullptr)\n{\n  QStyle *st = style ();\n  m_icon_size = 0.75*st->pixelMetric (QStyle::PM_SmallIconSize);\n\n  // keep track of the original buttons on the default title bar,\n  // the button further left is considered \"float\"\n  QList<QAbstractButton *> buttonlist = findChildren<QAbstractButton *> ();\n  if (buttonlist.size () == 2)\n    {\n      if (buttonlist.at (0)->x () < buttonlist.at (1)->x ())\n        {\n          m_default_float_button = buttonlist.at (0);\n          m_default_close_button = buttonlist.at (1);\n        }\n      else\n        {\n          m_default_float_button = buttonlist.at (1);\n          m_default_close_button = buttonlist.at (0);\n        }\n    }\n\n  gui_settings settings;\n\n  // the custom (extra) title bar of the widget\n  m_title_widget = new QWidget ();\n\n  m_dock_action = new QAction\n  (settings.icon (\"widget-undock\", true), \"\", this);\n  m_dock_action->setToolTip (tr (\"Undock Widget\"));\n  m_dock_button = new QToolButton (m_title_widget);\n  m_dock_button->setDefaultAction (m_dock_action);\n  m_dock_button->setFocusPolicy (Qt::NoFocus);\n  m_dock_button->setIconSize (QSize (m_icon_size, m_icon_size));\n\n  m_close_action = new QAction\n  (settings.icon (\"widget-close\", true), \"\", this);\n  m_close_action->setToolTip (tr (\"Close Widget\"));\n  m_close_button = new QToolButton (m_title_widget);\n  m_close_button->setDefaultAction (m_close_action);\n  m_close_button->setFocusPolicy (Qt::NoFocus);\n  m_close_button->setIconSize (QSize (m_icon_size, m_icon_size));\n\n  QString css_button = QString (\"QToolButton {background: transparent; border: 0px;}\");\n  m_dock_button->setStyleSheet (css_button);\n  m_close_button->setStyleSheet (css_button);\n\n  QHBoxLayout *h_layout = new QHBoxLayout ();\n  h_layout->addStretch (100);\n  h_layout->addWidget (m_dock_button);\n  h_layout->addWidget (m_close_button);\n  h_layout->setSpacing (10);\n  h_layout->setContentsMargins (5, 2, 2, 2);\n\n  m_title_widget->setLayout (h_layout);\n\n  if (p && (p->objectName () == gui_obj_name_main_window))\n    {\n      // Only connect the when a parent (main window) is given\n      // copy & paste handling\n      connect (p, SIGNAL (copyClipboard_signal ()),\n               this, SLOT (copyClipboard ()));\n      connect (p, SIGNAL (pasteClipboard_signal ()),\n               this, SLOT (pasteClipboard ()));\n      connect (p, SIGNAL (selectAll_signal ()),\n               this, SLOT (selectAll ()));\n\n      // undo handling\n      connect (p, SIGNAL (undo_signal ()), this, SLOT (do_undo ()));\n    }\n}\n\n// set the title in the dockwidgets title bar\nvoid\nlabel_dock_widget::set_title (const QString& title)\n{\n  QHBoxLayout *h_layout\n    = static_cast<QHBoxLayout *> (m_title_widget->layout ());\n  QLabel *label = new QLabel (title, m_title_widget);\n  label->setStyleSheet (\"background-color: transparent;\");\n  h_layout->insertWidget (0, label);\n  setTitleBarWidget (m_title_widget);\n  setWindowTitle (title);\n}\n\nstatic QString\nqdockwidget_css (const QString& close_icon, const QString& close_tooltip,\n                 const QString& float_icon, const QString& float_tooltip,\n                 int icon_size, const QString& titlebar_foreground,\n                 const QString& titlebar_background)\n{\n  return QString (\"QDockWidget\\n\"\n                  \"{\\n\"\n                  \"%6\"\n                  \"  border: none;\\n\"\n                  \"  titlebar-close-icon: url(%1);\\n\"\n                  \"  titlebar-normal-icon: url(%2);\\n\"\n                  \"}\\n\"\n                  \"\\n\"\n                  \"QDockWidget::close-button, QDockWidget::float-button\\n\"\n                  \"{\\n\"\n                  \"  border: none;\\n\"\n                  \"  icon-size: %3px;\\n\"\n                  \"}\\n\"\n                  \"\\n\"\n                  \"QAbstractButton#qt_dockwidget_closebutton\\n\"\n                  \"{\\n\"\n                  \"  qproperty-toolTip: \\\"%4\\\";\\n\"\n                  \"}\\n\"\n                  \"\\n\"\n                  \"QAbstractButton#qt_dockwidget_floatbutton\\n\"\n                  \"{\\n\"\n                  \"  qproperty-toolTip: \\\"%5\\\";\\n\"\n                  \"}\\n\"\n                  \"\\n\"\n                  \"QDockWidget::title {\\n\"\n                  \"  text-align: left;\\n\"\n                  \"%7\"\n                  \"  padding-left: 1px;\\n\"\n                  \"}\\n\"\n                  \"\\n\"\n                  \"QDockWidget::close-button\\n\"\n                  \"{\\n\"\n                  \"  right: %8px;\\n\"\n                  \"  top: 3px;\\n\"\n                  \"}\\n\"\n                  \"\\n\"\n                  \"QDockWidget::float-button\\n\"\n                  \"{\\n\"\n                  \"  right: %9px;\\n\"\n                  \"  top: 3px;\\n\"\n                  \"}\\n\"\n                 ).arg (close_icon).arg (float_icon).arg (icon_size)\n         .arg (close_tooltip).arg (float_tooltip)\n         .arg (titlebar_foreground).arg (titlebar_background)\n         .arg ((icon_size*2)/3).arg ((icon_size*7)/3);\n}\n\noctave_dock_widget::octave_dock_widget (const QString& obj_name, QWidget *p)\n  : label_dock_widget (p), m_main_window (nullptr), m_adopted (false),\n    m_custom_style (false), m_focus_follows_mouse (false),\n    m_recent_float_geom (), m_recent_dock_geom (),\n    m_waiting_for_mouse_button_release (false)\n{\n  setObjectName (obj_name);\n\n  // FIXME: Can we avoid the cast here?\n  m_main_window = dynamic_cast<main_window *> (p);\n\n  m_predecessor_widget = nullptr;\n\n  connect (this, &octave_dock_widget::topLevelChanged,\n           this, &octave_dock_widget::toplevel_change);\n  connect (this, &octave_dock_widget::visibilityChanged,\n           this, &octave_dock_widget::handle_visibility);\n\n  if (m_default_float_button != nullptr)\n    {\n      disconnect (m_default_float_button, 0, 0, 0);\n      connect (m_default_float_button, &QAbstractButton::clicked,\n               this, &octave_dock_widget::make_window);\n    }\n  connect (this, &octave_dock_widget::queue_make_window,\n           this, &octave_dock_widget::make_window, Qt::QueuedConnection);\n  connect (this, &octave_dock_widget::queue_make_widget,\n  this, [this] () { make_widget (); }, Qt::QueuedConnection);\n\n  gui_settings settings;\n\n  settings.set_shortcut (m_dock_action, sc_dock_widget_dock);\n  m_dock_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);\n  addAction (m_dock_action);\n  connect (m_dock_action, &QAction::triggered,\n           this, &octave_dock_widget::make_window);\n\n  settings.set_shortcut (m_close_action, sc_dock_widget_close);\n  m_close_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);\n  addAction (m_close_action);\n  connect (m_close_action, &QAction::triggered,\n           this, &octave_dock_widget::change_visibility);\n\n  m_close_action->setToolTip (tr (\"Hide Widget\"));\n\n  setStyleSheet (qdockwidget_css\n                 (global_icon_paths.at (ICON_THEME_OCTAVE)\n                    + \"widget-close\" + global_icon_extension,\n                  QString (\"Close Widget\"),\n                  global_icon_paths.at (ICON_THEME_OCTAVE)\n                    + \"widget-undock\" + global_icon_extension,\n                  QString (\"Undock Widget\"), m_icon_size, \"\", \"\"));\n\n  if (widget ())\n    widget ()->setToolTip (\"\");\n\n  m_icon_color = \"\";\n  m_title_3d = 50;\n\n  installEventFilter (this);\n\n  setFocusPolicy (Qt::StrongFocus);\n\n  setFeatures (QDockWidget::DockWidgetClosable\n               | QDockWidget::DockWidgetMovable\n               | QDockWidget::DockWidgetFloatable);\n\n  handle_settings ();\n}\n\nvoid\noctave_dock_widget::init_window_menu_entry ()\n{\n  Q_EMIT active_changed (isVisible ());  // emit once for init of window menu\n}\n\n// make the widget floating\nvoid\noctave_dock_widget::make_window (bool widget_was_dragged)\n{\n  bool vis = isVisible ();\n\n  // prevent follow-up calls by clearing state variable\n  m_waiting_for_mouse_button_release = false;\n\n  set_focus_predecessor ();  // set focus previously active widget if tabbed\n\n  // Before unparenting, get current geometry for restoring if dragged\n  QRect geom = geometry ();\n\n  // the widget has to be reparented (parent = 0), preferably\n  // from a non-toplevel widget otherwise may not have full\n  // decorations, e.g., no taskbar icon and always in front\n  if (isFloating ())\n    setFloating (false);\n\n  if (m_main_window)\n    {\n      // Before making it a separate (no more parent) floating widget,\n      // remove the dock widget from the main window.  This ensures\n      // that tabbed widgets keep their focus when it is re-docked\n      // later\n      m_main_window->removeDockWidget (this);\n    }\n\n  setParent (0, Qt::CustomizeWindowHint | Qt::WindowTitleHint |\n             Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::Window);\n\n  // restore the last geometry when floating only if we have not dragged\n  // the window outside the main window\n  if (! widget_was_dragged)\n    geom = m_recent_float_geom.isNull () ? QRect (50, 100, 480, 480)\n           : m_recent_float_geom;\n  setGeometry (geom);\n\n  // adjust the (un)dock action\n  disconnect (m_dock_action, 0, this, 0);\n  connect (m_dock_action, &QAction::triggered,\n           this, &octave_dock_widget::make_widget);\n\n  // adjust the (un)dock icon\n  if (titleBarWidget ())\n    {\n      gui_settings settings;\n\n      m_dock_action->setIcon (settings.icon (\"widget-dock\" + m_icon_color, true));\n      m_dock_action->setToolTip (tr (\"Dock Widget\"));\n    }\n  else\n    {\n      disconnect (m_default_float_button, 0, this, 0);\n      connect (m_default_float_button, &QAbstractButton::clicked,\n               this, &octave_dock_widget::make_widget);\n    }\n\n  raise ();\n  activateWindow ();\n\n  if (vis)\n    {\n      show ();\n      setFocus ();\n      set_style (true);\n    }\n\n  Q_EMIT topLevelChanged (true);  // Be sure signal is emitted\n}\n\n// dock the widget\nvoid\noctave_dock_widget::make_widget (bool)\n{\n  gui_settings settings;\n\n  bool vis = isVisible ();\n\n  // Since floating widget has no parent, we have to read it\n\n  if (m_main_window)\n    {\n      settings.setValue (mw_state.settings_key (), m_main_window->saveState ());\n\n      // Stay window, otherwise will bounce back to window by default\n      // because there is no layout information for this widget in the\n      // saved settings.\n      setParent (m_main_window, Qt::Window);\n      m_main_window->addDockWidget (Qt::BottomDockWidgetArea, this);\n      m_adopted = false;\n      // recover old window states, hide and re-show new added widget\n      m_main_window->restoreState (settings.value (mw_state.settings_key ()).toByteArray ());\n      setFloating (false);\n      // restore size using setGeometry instead of restoreGeometry\n      // following this post:\n      // https://forum.qt.io/topic/79326/qdockwidget-restoregeometry-not-working-correctly-when-qmainwindow-is-maximized/5\n      setGeometry (m_recent_dock_geom);\n    }\n\n  // adjust the (un)dock icon\n  disconnect (m_dock_action, 0, this, 0);\n  connect (m_dock_action, &QAction::triggered,\n           this, &octave_dock_widget::make_window);\n  if (titleBarWidget ())\n    {\n      m_dock_action->setIcon (settings.icon (\"widget-undock\" + m_icon_color, true));\n      m_dock_action->setToolTip (tr (\"Undock Widget\"));\n    }\n  else\n    {\n      disconnect (m_default_float_button, 0, this, 0);\n      connect (m_default_float_button, &QAbstractButton::clicked,\n               this, &octave_dock_widget::make_window);\n    }\n\n  raise ();\n  activateWindow ();\n\n  if (vis)\n    {\n      show ();\n      setFocus ();\n      set_style (true);\n    }\n}\n\n// dock the widget\nvoid\noctave_dock_widget::default_dock (bool)\n{\n  setFloating (false);\n}\n\n// set the widget which previously had focus when tabified\nvoid\noctave_dock_widget::set_predecessor_widget (octave_dock_widget *prev_widget)\n{\n  m_predecessor_widget = prev_widget;\n}\n\nvoid\noctave_dock_widget::set_main_window (main_window *mw)\n{\n  m_main_window = mw;\n\n  if (m_main_window)\n    {\n      connect (m_main_window, &main_window::copyClipboard_signal,\n               this, &octave_dock_widget::copyClipboard);\n\n      connect (m_main_window, &main_window::pasteClipboard_signal,\n               this, &octave_dock_widget::pasteClipboard);\n\n      connect (m_main_window, &main_window::selectAll_signal,\n               this, &octave_dock_widget::selectAll);\n\n      connect (m_main_window, &main_window::undo_signal,\n               this, &octave_dock_widget::do_undo);\n    }\n}\n\n// close event\nvoid\noctave_dock_widget::closeEvent (QCloseEvent *e)\n{\n  Q_EMIT active_changed (false);\n  set_focus_predecessor ();\n  save_settings ();\n\n  QDockWidget::closeEvent (e);\n}\n\n// get focus widget\nQWidget *\noctave_dock_widget::focusWidget ()\n{\n  QWidget *w = QApplication::focusWidget ();\n  if (w && w->focusProxy ()) w = w->focusProxy ();\n  return w;\n}\n\nbool\noctave_dock_widget::event (QEvent *event)\n{\n  // low-level check of whether docked-widget became a window via\n  // double-click or via drag-and-drop\n  if ( (event->type () == QEvent::MouseButtonDblClick && ! isFloating ())\n       || (event->type () == QEvent::ActivationChange\n           && m_waiting_for_mouse_button_release))\n    {\n      bool retval = QDockWidget::event (event);\n      if (isFloating () && parent () != 0)\n        {\n          m_waiting_for_mouse_button_release = false;\n          Q_EMIT queue_make_window (event->type () != QEvent::MouseButtonDblClick);\n        }\n      return retval;\n    }\n\n  return QDockWidget::event (event);\n}\n\nvoid\noctave_dock_widget::handle_settings ()\n{\n  gui_settings settings;\n\n  m_focus_follows_mouse = settings.bool_value (dw_focus_follows_mouse);\n\n  m_custom_style\n    = settings.bool_value (dw_title_custom_style);\n\n  m_title_3d = settings.int_value (dw_title_3d);\n\n  m_fg_color = settings.color_value (dw_title_fg_color);\n\n  m_fg_color_active = settings.color_value (dw_title_fg_color_active);\n\n  m_bg_color = settings.color_value (dw_title_bg_color);\n\n  m_bg_color_active = settings.color_value (dw_title_bg_color_active);\n\n  QColor bcol (m_bg_color);\n  QColor bcola (m_bg_color_active);\n\n  if (! m_custom_style)\n    {\n      bcol = QWidget::palette ().color (m_title_widget->backgroundRole ());\n      bcola = bcol;\n    }\n\n  int r, g, b;\n  bcol.getRgb (&r, &g, &b);\n  if (r+g+b < 400)\n    m_icon_color = \"-light\";\n  else\n    m_icon_color = \"\";\n\n  bcola.getRgb (&r, &g, &b);\n  if (r+g+b < 400)\n    m_icon_color_active = \"-light\";\n  else\n    m_icon_color_active = \"\";\n\n  int x, y, w, h;\n  QGuiApplication::primaryScreen ()->availableGeometry ().getRect (&x, &y, &w, &h);\n  QRect default_floating_size = QRect (x+16, y+32, w/3, h/2);\n\n  QRect default_dock_size;\n  QString key_ext;\n  if (m_main_window)\n    {\n      // We have a main window, dock size depends on size of main window\n      m_main_window->geometry ().getRect (&x, &y, &w, &h);\n      default_dock_size = QRect (x+16, y+32, w/3, h/3);\n    }\n  else\n    {\n      // No main window, default dock size should never be used\n      default_dock_size = QRect (0, 0, w/10, h/10);\n      key_ext = settings_no_mainwin;\n    }\n\n  m_recent_float_geom\n    = settings.value (dw_float_geometry.settings_key ().arg (objectName ()) + key_ext,\n                      default_floating_size).toRect ();\n\n  adjust_to_screen (m_recent_float_geom, default_floating_size);\n\n  // The following is required for ensure smooth transition from old\n  // saveGeomety to new QRect setting (see comment for restoring size\n  // of docked widgets)\n  QVariant dock_geom\n    = settings.value (dw_dock_geometry.settings_key ().arg (objectName ()) + key_ext,\n                      default_dock_size);\n#if defined (QVARIANT_CANCONVERT_REQUIRES_QMETATYPE_ARGUMENT)\n  if (dock_geom.canConvert (QMetaType (QMetaType::QRect)))\n#else\n  if (dock_geom.canConvert (QMetaType::QRect))\n#endif\n    m_recent_dock_geom = dock_geom.toRect ();\n  else\n    m_recent_dock_geom = dw_dock_geometry.def ().toRect ();\n\n  notice_settings ();  // call individual handler\n\n  set_style (false);\n\n  // Compacter design\n  QToolBar *toolbar = findChild<QToolBar *> ();\n  if (toolbar)\n    toolbar->setStyleSheet (toolbar->styleSheet () + global_toolbar_style);\n\n  QMenuBar *menubar = findChild<QMenuBar *> ();\n  if (menubar)\n    menubar->setStyleSheet (menubar->styleSheet () + global_menubar_style);\n\n}\n\nvoid\noctave_dock_widget::handle_active_dock_changed (octave_dock_widget *w_old,\n    octave_dock_widget *w_new)\n{\n  if (m_custom_style && this == w_old)\n    {\n      set_style (false);\n      update ();\n    }\n\n  if (m_custom_style && this == w_new)\n    {\n      set_style (true);\n      update ();\n    }\n}\n\nvoid\noctave_dock_widget::save_settings ()\n{\n  gui_settings settings;\n\n  // save state of this dock-widget\n  QString name = objectName ();\n\n  store_geometry ();\n\n  QString key_ext;\n  if (! m_main_window)\n    key_ext = settings_no_mainwin;\n\n  // conditional needed?\n  if (! m_recent_float_geom.isNull ())\n    settings.setValue (dw_float_geometry.settings_key ().arg (name) + key_ext, m_recent_float_geom);\n\n  if (! m_recent_dock_geom.isEmpty ())\n    settings.setValue (dw_dock_geometry.settings_key ().arg (name) + key_ext, m_recent_dock_geom);\n  settings.setValue (dw_is_visible.settings_key ().arg (name) + key_ext, isVisible ()); // store visibility\n  settings.setValue (dw_is_floating.settings_key ().arg (name) + key_ext, isFloating ()); // store floating\n  settings.setValue (dw_is_minimized.settings_key ().arg (name) + key_ext, isMinimized ()); // store minimized\n\n  settings.sync ();\n}\n\nbool\noctave_dock_widget::eventFilter (QObject *obj, QEvent *e)\n{\n  // Ignore double clicks into window decoration elements\n  if (e->type () == QEvent::NonClientAreaMouseButtonDblClick)\n    {\n      e->ignore ();\n      return true;\n    }\n\n  // Detect mouse enter events if \"focus follows mouse\" is desired\n  // for widgets docked to the main window (non floating) and activate\n  // the widget currently under the mouse\n  if (m_focus_follows_mouse && ! isFloating () && (e->type () == QEvent::Enter))\n    setFocus ();\n\n  return QDockWidget::eventFilter (obj, e);\n}\n\nvoid\noctave_dock_widget::store_geometry ()\n{\n  if (isFloating ())\n    {\n      if (! parent ())\n        m_recent_float_geom = geometry ();\n    }\n  else\n    {\n      m_recent_dock_geom = geometry ();\n    }\n}\n\nvoid\noctave_dock_widget::moveEvent (QMoveEvent *event)\n{\n  store_geometry ();\n\n  QDockWidget::moveEvent (event);\n}\n\nvoid\noctave_dock_widget::resizeEvent (QResizeEvent *event)\n{\n  store_geometry ();\n\n  QDockWidget::resizeEvent (event);\n}\n\n// slot for hiding the widget\nvoid\noctave_dock_widget::change_visibility (bool)\n{\n  setVisible (false);\n  Q_EMIT active_changed (false);\n}\n\nvoid\noctave_dock_widget::activate ()\n{\n  if (! isVisible ())\n    setVisible (true);\n\n  setFocus ();\n  activateWindow ();\n  raise ();\n}\n\nvoid\noctave_dock_widget::handle_visibility (bool visible)\n{\n  if (visible)\n    {\n      Q_EMIT active_changed (true);\n      if (! isFloating ())\n        setFocus ();\n    }\n}\n\nvoid\noctave_dock_widget::toplevel_change (bool toplevel)\n{\n  QObject *dockobj;\n  const char *docksig;\n\n  if (titleBarWidget ())\n    {\n      dockobj = m_dock_action;\n      docksig = SIGNAL (triggered (bool));\n    }\n  else\n    {\n      dockobj = m_default_float_button;\n      docksig = SIGNAL (clicked (bool));\n    }\n\n  if (toplevel)\n    {\n      // This is a fallback in case the attempt to create a floated\n      // top-level window fails and the QDockWidget remains a child\n      // of the QMainWindow.\n      connect (dockobj, docksig, this, SLOT (default_dock (bool)));\n\n      // Could be dragging window, so must wait until there is a\n      // change in focus.\n      if (parent () != 0)\n        m_waiting_for_mouse_button_release = true;\n    }\n  else\n    {\n      // If a drag-and-drop within the QMainWindow occurred, want to remain a widget.\n      m_waiting_for_mouse_button_release = false;\n\n      // Making into a widget immediately will mangle the double-click\n      // status and cause problems on followup button clicks.\n      if (parent () == 0)\n        Q_EMIT queue_make_widget ();\n    }\n}\n\nvoid\noctave_dock_widget::set_style (bool active)\n{\n  QString css_foreground;\n  QString css_background;\n  QString css_button;\n  QString dock_icon;\n\n  QString icon_col = m_icon_color;\n\n  QString close_tooltip = \"Close Widget\";\n  QString dock_tooltip;\n\n  if (isFloating ())\n    {\n      dock_icon = \"widget-dock\";\n      dock_tooltip = \"Dock Widget\";\n    }\n  else\n    {\n      dock_icon = \"widget-undock\";\n      dock_tooltip = \"Undock Widget\";\n    }\n\n#if defined (Q_OS_MAC)\n  QString alignment = \"center\";\n#else\n  QString alignment = \"center left\";\n#endif\n  if (m_custom_style)\n    {\n\n      QColor bg_col, fg_col;\n\n      if (active)\n        {\n          bg_col = m_bg_color_active;\n          fg_col = m_fg_color_active;\n          icon_col = m_icon_color_active;\n        }\n      else\n        {\n          bg_col = m_bg_color;\n          fg_col = m_fg_color;\n          icon_col = m_icon_color;\n        }\n\n      QColor bg_col_top, bg_col_bottom;\n      if (m_title_3d > 0)\n        {\n          bg_col_top = bg_col.lighter (100 + m_title_3d);\n          bg_col_bottom = bg_col.darker (100 + m_title_3d);\n        }\n      else\n        {\n          bg_col_top = bg_col.darker (100 - m_title_3d);\n          bg_col_bottom = bg_col.lighter (100 - m_title_3d);\n        }\n\n      css_foreground = QString (\"  color: %1;\\n\").arg (fg_col.name ());\n\n      css_background =\n        QString (\"  background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,\"\n                 \" stop: 0 %1, stop: 0.60 %2, stop: 0.95 %2 stop: 1.0 %3);\\n\").\n        arg (bg_col_top.name ()).\n        arg (bg_col.name ()).\n        arg (bg_col_bottom.name ());\n    }\n  else\n    {\n      css_foreground = \"\";\n      css_background = \"\";\n    }\n\n  QString full_dock_icon = dock_icon + icon_col;\n  QString full_close_icon = \"widget-close\" + icon_col;\n  if (titleBarWidget ())\n    {\n      gui_settings settings;\n\n      titleBarWidget ()->setStyleSheet (css_foreground + css_background);\n      css_button = QString (\"QToolButton {background: transparent; border: 0px;}\");\n      m_dock_button->setStyleSheet (css_button);\n      m_close_button->setStyleSheet (css_button);\n      m_dock_action->setIcon (settings.icon (full_dock_icon, true));\n      m_close_action->setIcon (settings.icon (full_close_icon, true));\n    }\n  else\n    {\n      setStyleSheet (qdockwidget_css (global_icon_paths.at (ICON_THEME_OCTAVE)\n                                        + full_close_icon + global_icon_extension,\n                                      close_tooltip,\n                                      global_icon_paths.at (ICON_THEME_OCTAVE)\n                                        + full_dock_icon + global_icon_extension,\n                                      dock_tooltip,\n                                      m_icon_size,\n                                      css_foreground,\n                                      css_background));\n    }\n}\n\n// set focus to previously active widget in tabbed widget stack\nvoid\noctave_dock_widget::set_focus_predecessor ()\n{\n  // only != 0 if widget was tabbed\n  if (m_predecessor_widget && m_predecessor_widget->isVisible ())\n    m_predecessor_widget->setFocus ();\n\n  m_predecessor_widget = nullptr;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/octave-dock-widget.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_octave_dock_widget_h)\n#define octave_octave_dock_widget_h 1\n\n#include <QDockWidget>\n#include <QIcon>\n#include <QMouseEvent>\n#include <QToolButton>\n\n#include \"qt-interpreter-events.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass main_window;\n\n// The few decoration items common to both main window and variable editor.\n\nclass label_dock_widget : public QDockWidget\n{\n  Q_OBJECT\n\npublic:\n\n  label_dock_widget (QWidget *p);\n\n  ~label_dock_widget () = default;\n\n  // set_title() uses the custom title bar while setWindowTitle() uses\n  // the default title bar (with style sheets)\n  void set_title (const QString&);\n\nprotected Q_SLOTS:\n\n  //! Slots to handle copy & paste.\n  //!@{\n  virtual void copyClipboard () { }\n  virtual void pasteClipboard () { }\n  virtual void selectAll () { }\n  //!@}\n\n  //! Slot to handle undo.\n\n  virtual void do_undo () { }\n\nprotected:\n\n  int m_icon_size;\n  QWidget *m_title_widget;\n  QToolButton *m_dock_button;\n  QToolButton *m_close_button;\n  QAction *m_dock_action;\n  QAction *m_close_action;\n\n  QAbstractButton *m_default_float_button;\n  QAbstractButton *m_default_close_button;\n};\n\nclass octave_dock_widget : public label_dock_widget\n{\n  Q_OBJECT\n\npublic:\n\n  octave_dock_widget (const QString& obj_name, QWidget *p);\n\n  ~octave_dock_widget () = default;\n\n  void set_predecessor_widget (octave_dock_widget *prev_widget);\n\n  void set_main_window (main_window *mw);\n\n  void set_adopted (bool adopted = true) { m_adopted = adopted; }\n  bool adopted () const { return m_adopted; }\n\nQ_SIGNALS:\n\n  //! Custom signal that tells whether a user has clicked away that dock\n  //! widget, i.e., the active dock widget has changed.\n\n  void active_changed (bool active);\n\n  void queue_make_window (bool widget_was_dragged);\n\n  void queue_make_widget ();\n\nprotected:\n\n  virtual void closeEvent (QCloseEvent *e);\n\n  QWidget * focusWidget ();\n\n  bool event (QEvent *event);\n\npublic Q_SLOTS:\n\n  virtual void activate ();\n\n  virtual void handle_visibility (bool visible);\n\n  virtual void notice_settings () { }\n\n  virtual void save_settings ();\n\n  void init_window_menu_entry ();\n\n  void handle_settings ();\n\n  void handle_active_dock_changed (octave_dock_widget *, octave_dock_widget *);\n\n  void moveEvent (QMoveEvent *event);\n\n  void resizeEvent (QResizeEvent *event);\n\n  void make_window (bool widget_was_dragged = false);\n\n  void make_widget (bool not_used = false);\n\n  void default_dock (bool not_used = false);\n\nprotected Q_SLOTS:\n\n  virtual void toplevel_change (bool);\n\n  //! Event filter for double clicks into the window decoration elements.\n\n  bool eventFilter (QObject *obj, QEvent *e);\n\nprivate Q_SLOTS:\n\n  void change_visibility (bool);\n\nprivate:\n\n  void set_style (bool active);\n  void set_focus_predecessor ();\n  void store_geometry ();\n\nprivate:\n\n  //! Stores the parent, since we are reparenting to 0.\n\n  main_window *m_main_window;\n\n  bool m_adopted;\n  bool m_custom_style;\n  bool m_focus_follows_mouse;\n  int m_title_3d;\n  QColor m_bg_color;\n  QColor m_bg_color_active;\n  QColor m_fg_color;\n  QColor m_fg_color_active;\n  QString m_icon_color;\n  QString m_icon_color_active;\n  octave_dock_widget *m_predecessor_widget;\n  QRect m_recent_float_geom;\n  QRect m_recent_dock_geom;\n  bool m_waiting_for_mouse_button_release;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/octave-qobject.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QApplication>\n#include <QClipboard>\n#include <QFile>\n#include <QFontDatabase>\n#include <QStyleFactory>\n#include <QSurfaceFormat>\n#if ! defined (Q_OS_WIN32)\n#  include <QTextCodec>\n#endif\n#include <QThread>\n#include <QTimer>\n#include <QTranslator>\n\n// QTerminal includes\n#include \"QTerminal.h\"\n\n#if defined (HAVE_QSCINTILLA)\n#  include \"command-widget.h\"\n#endif\n#include \"community-news.h\"\n#include \"documentation-dock-widget.h\"\n#include \"files-dock-widget.h\"\n#include \"gui-settings.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-sc.h\"\n#include \"history-dock-widget.h\"\n#include \"interpreter-qobject.h\"\n#include \"main-window.h\"\n#include \"octave-qobject.h\"\n#include \"qt-application.h\"\n#include \"qt-interpreter-events.h\"\n#include \"release-notes.h\"\n#include \"terminal-dock-widget.h\"\n#include \"variable-editor.h\"\n#include \"workspace-model.h\"\n#include \"workspace-view.h\"\n\n// Bug #55940 (Disable App Nap on Mac)\n#if defined (Q_OS_MAC)\n#  include <objc/runtime.h>\n#  include <objc/message.h>\n#endif\n\n#include \"interpreter.h\"\n#include \"oct-env.h\"\n#include \"version.h\"\n\n#include \"ovl.h\"\n\n// Bug #55940 (Disable App Nap on Mac)\n#if defined (Q_OS_MAC)\nstatic void\ndisable_app_nap ()\n{\n  Class process_info_class;\n  SEL process_info_selector;\n  SEL begin_activity_with_options_selector;\n  id process_info;\n  id reason_string;\n  id osx_latencycritical_activity;\n\n  // Option codes found at https://stackoverflow.com/questions/22784886/what-can-make-nanosleep-drift-with-exactly-10-sec-on-mac-os-x-10-9/32729281#32729281\n  unsigned long long NSActivityUserInitiatedAllowingIdleSystemSleep = 0x00FFFFFFULL;\n  unsigned long long NSActivityLatencyCritical = 0xFF00000000ULL;\n\n  // Avoid errors on older versions of OS X\n  process_info_class = reinterpret_cast<Class> (objc_getClass (\"NSProcessInfo\"));\n  if (process_info_class == nil)\n    return;\n\n  process_info_selector = sel_getUid (\"processInfo\");\n  if (class_getClassMethod (process_info_class, process_info_selector)\n      == nullptr)\n    return;\n\n  begin_activity_with_options_selector = sel_getUid (\"beginActivityWithOptions:reason:\");\n  if (class_getInstanceMethod (process_info_class,\n                               begin_activity_with_options_selector)\n      == nullptr)\n    return;\n\n  process_info = reinterpret_cast<id (*) (id, SEL)> (objc_msgSend)\n                   (reinterpret_cast<id> (process_info_class),\n                    process_info_selector);\n  if (process_info == nil)\n    return;\n\n  reason_string = reinterpret_cast<id (*) (id, SEL)> (objc_msgSend)\n                    (reinterpret_cast<id> (objc_getClass (\"NSString\")),\n                     sel_getUid (\"alloc\"));\n  reason_string = reinterpret_cast<id (*) (id, SEL, const char *)> (objc_msgSend)\n                    (reason_string, sel_getUid (\"initWithUTF8String:\"),\n                     \"App Nap causes pause() malfunction\");\n\n  // Start an Activity that suppresses App Nap.  This Activity will run for\n  // the entire duration of the Octave process.  This is intentional,\n  // not a leak.\n  osx_latencycritical_activity =\n    reinterpret_cast<id (*) (id, SEL, unsigned long long, id)> (objc_msgSend)\n      (process_info,\n       begin_activity_with_options_selector,\n       NSActivityUserInitiatedAllowingIdleSystemSleep\n       | NSActivityLatencyCritical,\n       reason_string);\n}\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Disable all Qt messages by default.\n\nstatic void\nmessage_handler (QtMsgType, const QMessageLogContext&, const QString&)\n{ }\n\n//! Reimplement QApplication::notify.  Octave's own exceptions are\n//! caught and rethrown in the interpreter thread.\n\nbool\noctave_qapplication::notify (QObject *receiver, QEvent *ev)\n{\n  try\n    {\n      return QApplication::notify (receiver, ev);\n    }\n  catch (execution_exception& ee)\n    {\n      Q_EMIT interpreter_event\n        ([ee] ()\n         {\n           // INTERPRETER THREAD\n           throw ee;\n         });\n    }\n\n  return false;\n}\n\n// We will create a QApplication object, even if START_GUI is false,\n// so that we can use Qt widgets for plot windows when running in\n// command-line mode.  Note that we are creating an\n// octave_qapplication object but handling it as a QApplication object\n// because the octave_qapplication should behave identically to a\n// QApplication object except that it overrides the notify method so\n// we can handle forward Octave interpreter exceptions from the GUI\n// thread to the interpreter thread.\n\nbase_qobject::base_qobject (qt_application& app_context, bool gui_app)\n  : QObject (),\n    m_app_context (app_context),\n    m_argc (m_app_context.sys_argc ()),\n    m_argv (m_app_context.sys_argv ()),\n    m_qapplication (new octave_qapplication (m_argc, m_argv)),\n    m_qt_tr (new QTranslator ()),\n    m_gui_tr (new QTranslator ()),\n    m_qsci_tr (new QTranslator ()),\n    m_translators_installed (false),\n    m_qt_interpreter_events (new qt_interpreter_events (*this)),\n    m_interpreter_qobj (new interpreter_qobject (*this)),\n    m_main_thread (new QThread ()),\n    m_gui_app (gui_app),\n    m_interpreter_ready (false),\n    m_workspace_model (new workspace_model ()),\n    m_documentation_widget (),\n    m_file_browser_widget (),\n    m_history_widget (),\n    m_workspace_widget (),\n    m_editor_widget (),\n    m_variable_editor_widget (),\n    m_main_window (nullptr),\n    m_style_set (false)\n{\n  std::string show_gui_msgs = sys::env::getenv (\"OCTAVE_SHOW_GUI_MESSAGES\");\n\n  // Installing our handler suppresses the messages.\n  if (show_gui_msgs.empty ())\n    qInstallMessageHandler (message_handler);\n\n#if ! defined (Q_OS_WIN32)\n  // Set the codec for all strings (before wizard or any GUI object)\n  QTextCodec::setCodecForLocale (QTextCodec::codecForName (\"UTF-8\"));\n#endif\n\n  // Register octave_value_list for connecting thread crossing signals.\n\n  qRegisterMetaType<octave_value_list> (\"octave_value_list\");\n\n  // Bug #55940 (Disable App Nap on Mac)\n#if defined (Q_OS_MAC)\n  // Mac App Nap feature causes pause() and sleep() to misbehave.\n  // Disable it for the entire program run.\n  disable_app_nap ();\n\n  // Don't let Qt interpret CMD key (\"Meta\" in Qt terminology) as Ctrl.\n  QCoreApplication::setAttribute (Qt::AA_MacDontSwapCtrlAndMeta, true);\n#endif\n\n  // Force left-to-right alignment (see bug #46204)\n  m_qapplication->setLayoutDirection (Qt::LeftToRight);\n\n  // Make sure Qt picks a full OpenGL context (including deprecated\n  // functions, see bug #67974)\n#if defined (HAVE_QSURFACEFORMAT_SETDEFAULTFORMAT)\n  QSurfaceFormat fmt;\n\n  fmt.setRenderableType (QSurfaceFormat::OpenGL);\n  fmt.setProfile (QSurfaceFormat::CompatibilityProfile);\n  fmt.setOption (QSurfaceFormat::DeprecatedFunctions, true);\n\n  QSurfaceFormat::setDefaultFormat (fmt);\n#endif\n\n  // Qt docs recommend using Qt::QueuedConnection when connecting to\n  // the QCoreApplication::exit slot.\n  connect (m_interpreter_qobj, &interpreter_qobject::shutdown_finished,\n           m_qapplication, &octave_qapplication::exit,\n           Qt::QueuedConnection);\n\n  connect (m_interpreter_qobj, &interpreter_qobject::ready,\n           this, &base_qobject::interpreter_ready);\n\n  connect (m_main_thread, &QThread::finished,\n           m_main_thread, &QThread::deleteLater);\n\n  // Handle any interpreter_event signal from the octave_qapplication\n  // object here.\n\n  connect (m_qapplication, qOverload<const fcn_callback&> (&octave_qapplication::interpreter_event),\n           this, qOverload<const fcn_callback&> (&base_qobject::interpreter_event));\n\n  connect (m_qapplication, qOverload<const meth_callback&> (&octave_qapplication::interpreter_event),\n           this, qOverload<const meth_callback&> (&base_qobject::interpreter_event));\n\n  if (m_app_context.experimental_terminal_widget ())\n    {\n      connect (qt_link (), &qt_interpreter_events::start_gui_signal,\n               this, &base_qobject::start_gui);\n\n      connect (qt_link (), &qt_interpreter_events::show_terminal_window_signal,\n               this, &base_qobject::show_terminal_window);\n    }\n\n  connect (qt_link (), &qt_interpreter_events::copy_image_to_clipboard_signal,\n           this, &base_qobject::copy_image_to_clipboard);\n\n  connect (qt_link (), &qt_interpreter_events::show_documentation_signal,\n           this, &base_qobject::show_documentation_window);\n\n  connect (qt_link (), &qt_interpreter_events::show_file_browser_signal,\n           this, &base_qobject::show_file_browser_window);\n\n  connect (qt_link (), &qt_interpreter_events::show_command_history_signal,\n           this, &base_qobject::show_command_history_window);\n\n  connect (qt_link (), &qt_interpreter_events::show_workspace_signal,\n           this, &base_qobject::show_workspace_window);\n\n  connect (qt_link (), &qt_interpreter_events::edit_variable_signal,\n           this, &base_qobject::show_variable_editor_window);\n\n  connect (qt_link (), &qt_interpreter_events::show_community_news_signal,\n           this, &base_qobject::show_community_news);\n\n  connect (qt_link (), &qt_interpreter_events::show_release_notes_signal,\n           this, &base_qobject::show_release_notes);\n\n  if (m_app_context.experimental_terminal_widget ())\n    {\n      m_qapplication->setQuitOnLastWindowClosed (false);\n    }\n  else\n    {\n      if (gui_app)\n        {\n          m_main_window = new main_window (*this);\n\n          connect (m_main_window, &main_window::show_community_news_signal,\n                   this, &base_qobject::show_community_news);\n\n          connect (m_main_window, &main_window::show_release_notes_signal,\n                   this, &base_qobject::show_release_notes);\n\n          if (m_interpreter_ready)\n            m_main_window->handle_octave_ready ();\n          else\n            connect (m_interpreter_qobj, &interpreter_qobject::ready,\n                     m_main_window, &main_window::handle_octave_ready);\n\n          connect (qt_link (), &qt_interpreter_events::focus_window_signal,\n                   m_main_window, &main_window::focus_window);\n\n          m_app_context.gui_running (true);\n        }\n      else\n        {\n          // Access font db first, otherwise gui widgets have a monospace font\n          QFontDatabase::systemFont (QFontDatabase::GeneralFont);\n\n          // Get settings file.\n          gui_settings settings;\n\n          settings.reload ();\n\n          // After settings.\n          config_translators ();\n\n          settings.config_icon_theme ();\n\n          m_qapplication->setQuitOnLastWindowClosed (false);\n        }\n    }\n\n  start_main_thread ();\n}\n\nbase_qobject::~base_qobject ()\n{\n  // Note that we don't delete m_main_thread here.  That is handled by\n  // deleteLater slot that is called when the m_main_thread issues a\n  // finished signal.\n\n  // Prevent Qt from delivering signals to widgets during destruction\n  if (m_qapplication)\n    disconnect(m_qapplication, &QApplication::focusChanged, nullptr, nullptr);\n\n  // FIXME: Why are dock widget settings and/or the main window\n  // configuration not saved correctly if the main window is deleted\n  // after the dock widgets?\n\n  // Calling close will cause settings to be saved.\n  // If m_main_window exists, the widgets are closed by the main window\n\n  if (! m_main_window)\n    {\n      if (m_terminal_widget)\n        {\n          disconnect(m_terminal_widget, nullptr, nullptr, nullptr);\n          m_terminal_widget->close ();\n\t}\n\n      if (m_documentation_widget)\n        {\n          disconnect(m_documentation_widget, nullptr, nullptr, nullptr);\n          m_documentation_widget->close ();\n\t}\n\n      if (m_file_browser_widget)\n        {\n          disconnect(m_file_browser_widget, nullptr, nullptr, nullptr);\n          m_file_browser_widget->close ();\n        }\n\n      if (m_history_widget)\n        {\n          disconnect(m_history_widget, nullptr, nullptr, nullptr);\n          m_history_widget->close ();\n        }\n\n      if (m_workspace_widget)\n        {\n          disconnect(m_workspace_widget, nullptr, nullptr, nullptr);\n          m_workspace_widget->close ();\n        }\n\n      if (m_editor_widget)\n        {\n          disconnect(m_editor_widget, nullptr, nullptr, nullptr);\n          m_editor_widget->close ();\n        }\n\n      if (m_variable_editor_widget)\n        {\n          disconnect(m_variable_editor_widget, nullptr, nullptr, nullptr);\n          m_variable_editor_widget->close ();\n        }\n\n      if (m_community_news)\n        {\n          disconnect(m_community_news, nullptr, nullptr, nullptr);\n          m_community_news->close ();\n\t}\n    }\n  else\n    {\n      if (m_main_window)\n        disconnect(m_main_window, nullptr, nullptr, nullptr);\n\n      m_main_window->deleteLater ();\n    }\n\n  delete m_terminal_widget;\n  delete m_documentation_widget;\n  delete m_file_browser_widget;\n  delete m_history_widget;\n  delete m_workspace_widget;\n  delete m_editor_widget;\n  delete m_variable_editor_widget;\n  delete m_community_news;\n\n  // Disconnect interpreter signals before deletion\n  if (m_interpreter_qobj)\n    disconnect(m_interpreter_qobj, nullptr, nullptr, nullptr);\n\n  delete m_interpreter_qobj;\n  delete m_qsci_tr;\n  delete m_gui_tr;\n  delete m_qt_tr;\n  delete m_workspace_model;\n\n  delete m_qapplication;\n\n  string_vector::delete_c_str_vec (m_argv);\n}\n\nvoid\nbase_qobject::config_translators ()\n{\n  if (m_translators_installed)\n    return;\n\n  gui_settings settings;\n\n  settings.config_translators (m_qt_tr, m_qsci_tr, m_gui_tr);\n\n  m_qapplication->installTranslator (m_qt_tr);\n  m_qapplication->installTranslator (m_gui_tr);\n  m_qapplication->installTranslator (m_qsci_tr);\n\n  m_translators_installed = true;\n\n  init_all_shortcuts ();  // after translators are loaded\n}\n\nvoid\nbase_qobject::start_main_thread ()\n{\n  // Note: if using the new experimental terminal widget, we defer\n  // initializing and executing the interpreter until the main event\n  // loop begins executing.\n\n  // With the old terminal widget, we defer initializing and executing\n  // the interpreter until after the main window and QApplication are\n  // running to prevent race conditions.\n\n#if defined (QTIMER_SINGLESHOT_ACCEPTS_POINTER_TO_MEMBER_FUNCTION)\n  QTimer::singleShot (0, m_interpreter_qobj, &interpreter_qobject::execute);\n#else\n  QTimer::singleShot (0, m_interpreter_qobj, SLOT (execute ()));\n#endif\n\n  m_interpreter_qobj->moveToThread (m_main_thread);\n\n  m_main_thread->start ();\n}\n\nint\nbase_qobject::exec ()\n{\n  int status = m_qapplication->exec ();\n\n#if defined (Q_OS_MAC)\n  // fprintf to stderr is needed by macOS, for poorly-understood reasons.\n  fprintf (stderr, \"\\n\");\n#endif\n\n  m_main_thread->quit ();\n  m_main_thread->wait ();\n\n  return status;\n}\n\n// Provided for convenience.  Will be removed once we eliminate the\n// old terminal widget.\nbool\nbase_qobject::experimental_terminal_widget () const\n{\n  return m_app_context.experimental_terminal_widget ();\n}\n\nbool\nbase_qobject::gui_running () const\n{\n  return m_app_context.gui_running ();\n}\n\nQPointer<terminal_dock_widget>\nbase_qobject::terminal_widget (main_window *mw)\n{\n  if (m_terminal_widget && mw)\n    {\n      m_terminal_widget->set_main_window (mw);\n      m_terminal_widget->set_adopted (true);\n    }\n  else if (! m_terminal_widget)\n    {\n      bool etw = m_app_context.experimental_terminal_widget ();\n\n      m_terminal_widget\n        = QPointer<terminal_dock_widget> (new terminal_dock_widget (mw, etw));\n\n      if (etw)\n        {\n#if defined (HAVE_QSCINTILLA)\n          command_widget *cmd_widget\n            = m_terminal_widget->get_command_widget ();\n\n          connect (cmd_widget, &command_widget::interpreter_pause,\n                   this, &base_qobject::interpreter_pause);\n\n          connect (cmd_widget, &command_widget::interpreter_resume,\n                   this, &base_qobject::interpreter_resume);\n\n          connect (cmd_widget, &command_widget::interpreter_stop,\n                   this, &base_qobject::interpreter_stop);\n\n          connect (qt_link (), &qt_interpreter_events::interpreter_output_signal,\n                   m_terminal_widget, &terminal_dock_widget::interpreter_output_signal);\n\n          connect (qt_link (), &qt_interpreter_events::update_prompt_signal,\n                   m_terminal_widget, &terminal_dock_widget::update_prompt_signal);\n\n          connect (qt_link (), &qt_interpreter_events::new_command_line_signal,\n                   m_terminal_widget, &terminal_dock_widget::new_command_line_signal);\n\n          connect (mw, &main_window::update_prompt_signal,\n                   m_terminal_widget, &terminal_dock_widget::update_prompt_signal);\n\n          connect_interpreter_events (cmd_widget);\n#endif\n        }\n      else\n        {\n          QTerminal *cmd_widget = m_terminal_widget->get_qterminal ();\n\n          // Connect the interrupt signal (emitted by Ctrl-C)\n          connect (cmd_widget, &QTerminal::interrupt_signal,\n                   this, &base_qobject::interpreter_interrupt);\n\n          connect_interpreter_events (cmd_widget);\n        }\n\n      set_gui_style ();\n    }\n\n  return m_terminal_widget;\n}\n\nQPointer<documentation_dock_widget>\nbase_qobject::documentation_widget (main_window *mw)\n{\n  if (m_documentation_widget && mw)\n    {\n      m_documentation_widget->set_main_window (mw);\n      m_documentation_widget->set_adopted (true);\n    }\n  else if (! m_documentation_widget)\n    {\n      m_documentation_widget\n        = QPointer<documentation_dock_widget> (new documentation_dock_widget (mw));\n\n      connect (qt_link (),\n               &qt_interpreter_events::register_documentation_signal,\n               m_documentation_widget,\n               &documentation_dock_widget::registerDoc);\n\n      connect (qt_link (),\n               &qt_interpreter_events::unregister_documentation_signal,\n               m_documentation_widget,\n               &documentation_dock_widget::unregisterDoc);\n\n      set_gui_style ();\n    }\n\n  return m_documentation_widget;\n}\n\nQPointer<files_dock_widget>\nbase_qobject::file_browser_widget (main_window *mw)\n{\n  if (m_file_browser_widget)\n    {\n      m_file_browser_widget->set_main_window (mw);\n      m_file_browser_widget->set_adopted (true);\n    }\n  else if (! m_file_browser_widget)\n     {\n       m_file_browser_widget\n         = QPointer<files_dock_widget> (new files_dock_widget (mw));\n       set_gui_style ();\n     }\n\n  connect (qt_link (), &qt_interpreter_events::directory_changed_signal,\n           m_file_browser_widget->get_file_system_browser (),\n           &file_system_browser::update_octave_directory);\n\n  return m_file_browser_widget;\n}\n\nQPointer<history_dock_widget>\nbase_qobject::history_widget (main_window *mw)\n{\n  if (m_history_widget)\n    {\n      m_history_widget->set_main_window (mw);\n      m_history_widget->set_adopted (true);\n    }\n  else if (! m_history_widget)\n    {\n      m_history_widget\n        = QPointer<history_dock_widget> (new history_dock_widget (mw));\n\n      connect (qt_link (), &qt_interpreter_events::set_history_signal,\n               m_history_widget, &history_dock_widget::set_history);\n\n      connect (qt_link (), &qt_interpreter_events::append_history_signal,\n               m_history_widget, &history_dock_widget::append_history);\n\n      connect (qt_link (), &qt_interpreter_events::clear_history_signal,\n               m_history_widget, &history_dock_widget::clear_history);\n\n      Q_EMIT interpreter_event\n        ([] (interpreter& interp) {\n          // INTERPRETER THREAD\n\n          event_manager& xevmgr = interp.get_event_manager ();\n\n          xevmgr.set_history ();\n        });\n\n       set_gui_style ();\n    }\n\n  return m_history_widget;\n}\n\nQPointer<workspace_view>\nbase_qobject::workspace_widget (main_window *mw)\n{\n  if (m_workspace_widget)\n    {\n      m_workspace_widget->set_main_window (mw);\n      m_workspace_widget->set_adopted (true);\n    }\n  else if (! m_workspace_widget)\n    {\n      m_workspace_widget\n        = QPointer<workspace_view> (new workspace_view (mw));\n\n      m_workspace_widget->setModel (m_workspace_model);\n\n      connect (m_workspace_model, &workspace_model::model_changed,\n               m_workspace_widget, &workspace_view::handle_model_changed);\n\n      connect (qt_link (), &qt_interpreter_events::set_workspace_signal,\n               m_workspace_model, &workspace_model::set_workspace);\n\n      connect (qt_link (), &qt_interpreter_events::clear_workspace_signal,\n               m_workspace_model, &workspace_model::clear_workspace);\n\n      connect (m_workspace_widget,\n               &workspace_view::copy_variable_value_to_clipboard,\n               [this] (const QString& var_name) {\n                 Q_EMIT interpreter_event\n                   ([var_name] (interpreter& interp)\n                    {\n                      // INTERPRETER THREAD\n\n                      octave_value val = interp.varval (var_name.toStdString ());\n\n                      if (val.is_undefined ())\n                        val = 0;\n\n                      std::ostringstream buf;\n                      val.print_raw (buf, true);\n\n                      // FIXME: is the following operation thread safe or should\n                      // it be done with a signal/slot connection?\n\n                      QClipboard *clipboard = QApplication::clipboard ();\n                      clipboard->setText (QString::fromStdString (buf.str ()));\n                    });\n               });\n\n      connect (m_workspace_widget, &workspace_view::rename_variable_signal,\n               [this] (const QString& old_name, const QString& new_name) {\n                 Q_EMIT interpreter_event\n                   ([old_name, new_name] (interpreter& interp) {\n                     // INTERPRETER THREAD\n\n                     symbol_scope scope = interp.get_current_scope ();\n\n                     if (scope)\n                       {\n                         scope.rename (old_name.toStdString (),\n                                       new_name.toStdString ());\n\n                         tree_evaluator& tw = interp.get_evaluator ();\n\n                         event_manager& xevmgr = interp.get_event_manager ();\n\n                         xevmgr.set_workspace (true, tw.get_symbol_info ());\n                       }\n\n                     // FIXME: if this action fails, do we need a way to\n                     // display that info in the GUI?\n                   });\n               });\n\n      connect (m_workspace_widget, &workspace_view::edit_variable_signal,\n               [this] (const QString& var_name) {\n                 Q_EMIT interpreter_event\n                   ([var_name] (interpreter& interp) {\n                     // INTERPRETER THREAD\n\n                     std::string name = var_name.toStdString ();\n                     octave_value val = interp.varval (name);\n\n                     event_manager& xevmgr = interp.get_event_manager ();\n\n                     xevmgr.edit_variable (name, val);\n                   });\n               });\n\n      Q_EMIT interpreter_event\n        ([] (interpreter& interp) {\n          // INTERPRETER THREAD\n\n          event_manager& xevmgr = interp.get_event_manager ();\n\n          xevmgr.set_workspace ();\n        });\n\n      set_gui_style ();\n    }\n\n  return m_workspace_widget;\n}\n\nQPointer<file_editor_interface>\nbase_qobject::editor_widget (main_window */*mw*/)\n{\n  return m_editor_widget;\n}\n\nQPointer<variable_editor>\nbase_qobject::variable_editor_widget (main_window *mw)\n{\n  if (m_variable_editor_widget && mw)\n    {\n      m_variable_editor_widget->set_main_window (mw);\n      m_variable_editor_widget->set_adopted (true);\n    }\n  else if (! m_variable_editor_widget)\n    {\n      m_variable_editor_widget\n        = QPointer<variable_editor> (new variable_editor (mw));\n\n      connect (m_variable_editor_widget, &variable_editor::updated,\n               this, &base_qobject::handle_variable_editor_update);\n\n      connect (m_variable_editor_widget, &variable_editor::command_signal,\n               this, &base_qobject::execute_command);\n\n      connect (qt_link (),\n               &qt_interpreter_events::refresh_variable_editor_signal,\n               m_variable_editor_widget, &variable_editor::refresh);\n\n      connect_interpreter_events<variable_editor> (m_variable_editor_widget);\n\n      set_gui_style ();\n    }\n\n  return m_variable_editor_widget;\n}\n\nQPointer<community_news>\nbase_qobject::community_news_widget (int serial)\n{\n  if (! m_community_news)\n    {\n      m_community_news\n        = QPointer<community_news> (new community_news (serial));\n      set_gui_style ();\n    }\n\n  return m_community_news;\n}\n\nQPointer<release_notes>\nbase_qobject::release_notes_widget ()\n{\n  if (! m_release_notes)\n    {\n      m_release_notes = QPointer<release_notes> (new release_notes ());\n      set_gui_style ();\n    }\n\n  return m_release_notes;\n}\n\nQPalette\nbase_qobject::getFusionDarkPalette ()\n{\n  QPalette darkPalette;\n  darkPalette.setColor (QPalette::Window, QColor (53, 53, 53));\n  darkPalette.setColor (QPalette::WindowText, Qt::white);\n  darkPalette.setColor (QPalette::Disabled, QPalette::WindowText, QColor (127, 127, 127));\n  darkPalette.setColor (QPalette::Base, QColor (42, 42, 42));\n  darkPalette.setColor (QPalette::AlternateBase, QColor (66, 66, 66));\n  darkPalette.setColor (QPalette::ToolTipBase, Qt::white);\n  darkPalette.setColor (QPalette::ToolTipText, Qt::white);\n  darkPalette.setColor (QPalette::Text, Qt::white);\n  darkPalette.setColor (QPalette::Disabled, QPalette::Text, QColor (127, 127, 127));\n  darkPalette.setColor (QPalette::Dark, QColor (35, 35, 35));\n  darkPalette.setColor (QPalette::Shadow, QColor (20, 20, 20));\n  darkPalette.setColor (QPalette::Button, QColor (53, 53, 53));\n  darkPalette.setColor (QPalette::ButtonText, Qt::white);\n  darkPalette.setColor (QPalette::Disabled, QPalette::ButtonText, QColor (127, 127, 127));\n  darkPalette.setColor (QPalette::BrightText, Qt::red);\n  darkPalette.setColor (QPalette::Link, QColor (42, 130, 218));\n  darkPalette.setColor (QPalette::Highlight, QColor (42, 130, 218));\n  darkPalette.setColor (QPalette::Disabled, QPalette::Highlight, QColor (80, 80, 80));\n  darkPalette.setColor (QPalette::HighlightedText, Qt::white);\n  darkPalette.setColor (QPalette::Disabled, QPalette::HighlightedText, QColor (127, 127, 127));\n\n  return darkPalette;\n}\n\nvoid\nbase_qobject::set_gui_style (bool called_from_main_window)\n{\n  if (! called_from_main_window)\n    {\n      // called internally, not from main window\n      if (m_style_set)\n        return;\n\n      m_style_set = false;\n    }\n\n  QApplication *qapp = qapplication ();\n\n  gui_settings settings;\n  QString default_style = qapp->style ()->objectName ();\n  QPalette default_palette = qapp->palette ();\n\n  // Get desired style from preferences or take the default one if\n  // the desired one is not found\n  QString preferred_style = settings.string_value (global_style);\n\n  if (preferred_style == global_style.def ().toString ())\n    preferred_style = default_style;\n\n  if (preferred_style == global_extra_styles.at (EXTRA_STYLE_FUSION_DARK))\n    {\n      QStyle *new_style = QStyleFactory::create (QStringLiteral (\"Fusion\"));\n      if (new_style)\n        qapp->setStyle (new_style);\n      qapp->setPalette (getFusionDarkPalette ());\n      qapp->setStyleSheet (\"QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }\");\n    }\n  else\n    {\n      QStyle *new_style = QStyleFactory::create (preferred_style);\n      if (new_style)\n        {\n          qapp->setPalette (default_palette);\n          qapp->setStyle (new_style);\n        }\n    }\n}\n\n\nbool\nbase_qobject::confirm_shutdown ()\n{\n  // Currently, we forward to main_window::confirm_shutdown instead of\n  // just displaying a dialog box here because the main_window also\n  // knows about and is responsible for notifying the editor.\n\n  return m_main_window ? m_main_window->confirm_shutdown () : true;\n}\n\nvoid\nbase_qobject::start_gui (bool gui_app)\n{\n  if (m_app_context.experimental_terminal_widget ())\n    {\n      if (m_main_window)\n        return;\n\n      m_gui_app = gui_app;\n\n      m_main_window = new main_window (*this);\n\n      connect (qt_link (), &qt_interpreter_events::focus_window_signal,\n               m_main_window, &main_window::focus_window);\n\n      connect (qt_link (), &qt_interpreter_events::close_gui_signal,\n               this, &base_qobject::close_gui);\n\n      connect (m_main_window, &main_window::close_gui_signal,\n               this, &base_qobject::close_gui);\n\n      connect (m_main_window, &main_window::show_community_news_signal,\n               this, &base_qobject::show_community_news);\n\n      connect (m_main_window, &main_window::show_release_notes_signal,\n               this, &base_qobject::show_release_notes);\n\n      if (m_interpreter_ready)\n        m_main_window->handle_octave_ready ();\n      else\n        connect (m_interpreter_qobj, &interpreter_qobject::ready,\n                 m_main_window, &main_window::handle_octave_ready);\n\n      if (m_gui_app)\n        m_qapplication->setQuitOnLastWindowClosed (true);\n      else\n        {\n          // FIXME: Save current values of PS1 and PS2 so they can be\n          // restored when we return to the command line?\n        }\n\n      m_app_context.gui_running (true);\n    }\n}\n\nvoid\nbase_qobject::show_terminal_window ()\n{\n  terminal_dock_widget *widget\n    = (m_terminal_widget\n       ? m_terminal_widget : terminal_widget ());\n\n  if (! widget->isVisible ())\n    {\n      widget->show ();\n      widget->raise ();\n    }\n}\n\nvoid\nbase_qobject::show_documentation_window (const QString& file)\n{\n  documentation_dock_widget *widget\n    = (m_documentation_widget\n       ? m_documentation_widget : documentation_widget ());\n\n  widget->showDoc (file);\n\n  if (! widget->isVisible ())\n    {\n      widget->show ();\n      widget->raise ();\n    }\n}\n\nvoid\nbase_qobject::show_file_browser_window ()\n{\n  files_dock_widget *widget\n    = m_file_browser_widget ? m_file_browser_widget : file_browser_widget ();\n\n  if (! widget->isVisible ())\n    {\n      widget->show ();\n      widget->raise ();\n    }\n}\n\nvoid\nbase_qobject::show_command_history_window ()\n{\n  history_dock_widget *widget\n    = m_history_widget ? m_history_widget : history_widget ();\n\n  if (! widget->isVisible ())\n    {\n      widget->show ();\n      widget->raise ();\n    }\n}\n\nvoid\nbase_qobject::show_workspace_window ()\n{\n  workspace_view *widget\n    = m_workspace_widget ? m_workspace_widget : workspace_widget ();\n\n  if (! widget->isVisible ())\n    {\n      widget->show ();\n      widget->raise ();\n    }\n}\n\nvoid\nbase_qobject::show_variable_editor_window (const QString& name,\n    const octave_value& value)\n{\n  variable_editor *widget\n    = (m_variable_editor_widget\n       ? m_variable_editor_widget : variable_editor_widget ());\n\n  if (! widget->isVisible ())\n    {\n      widget->show ();\n      widget->raise ();\n    }\n\n  // FIXME: Should this be done with a signal/slot connection?\n  widget->edit_variable (name, value);\n}\n\nvoid\nbase_qobject::handle_variable_editor_update ()\n{\n  // Called when the variable editor emits the updated signal.  The size\n  // of a variable may have changed, so we refresh the workspace in the\n  // interpreter.  That will eventually cause the workspace view in the\n  // GUI to be updated.\n\n  interpreter_event\n    ([] (interpreter& interp)\n     {\n       // INTERPRETER THREAD\n\n       tree_evaluator& tw = interp.get_evaluator ();\n\n       event_manager& xevmgr = interp.get_event_manager ();\n\n       xevmgr.set_workspace (true, tw.get_symbol_info (), false);\n     });\n}\n\nvoid\nbase_qobject::show_community_news (int serial)\n{\n  // Ensure widget exists.\n  community_news_widget (serial);\n\n  m_community_news->display ();\n}\n\nvoid\nbase_qobject::show_release_notes ()\n{\n  // Ensure widget exists.\n  release_notes_widget ();\n\n  m_release_notes->display ();\n}\n\nvoid\nbase_qobject::execute_command (const QString& command)\n{\n  Q_EMIT interpreter_event\n    ([command] (interpreter& interp)\n    {\n      // INTERPRETER THREAD\n\n      // FIXME: Do we need to do anything special about errors here?\n      // Currently the eval function will just call error() in the\n      // interpreter event loop and throw an execution error.  It will\n      // be caught, so shouldn't crash the interpreter, but the\n      // message may not go anywhere useful depending on how the GUI\n      // is being used or if Octave running server mode.\n\n      interp.eval (command.toStdString (), 0);\n    });\n}\n\nvoid\nbase_qobject::close_gui ()\n{\n  if (m_app_context.experimental_terminal_widget ())\n    {\n      if (! m_main_window)\n        return;\n\n      // FIXME: Restore previous values of PS1 and PS2 if we are\n      // returning to the command line?\n\n      interpreter_event\n        ([] (interpreter& interp)\n        {\n          // INTERPRETER THREAD\n\n          application *app = interp.get_app_context ();\n\n          cmdline_options opts = app->options ();\n\n          if (opts.gui ())\n            interp.quit (0, false, false);\n        });\n\n      m_app_context.gui_running (false);\n    }\n}\n\nvoid\nbase_qobject::interpreter_ready ()\n{\n  m_interpreter_ready = true;\n}\n\nvoid\nbase_qobject::interpreter_event (const fcn_callback& fcn)\n{\n  // The following is a direct function call across threads.  It works\n  // because it is accessing a thread-safe queue of events that\n  // are later executed by the Octave interpreter in the other thread.\n\n  // See also the comments in interpreter-qobject.h about\n  // interpreter_qobject slots.\n\n  m_interpreter_qobj->interpreter_event (fcn);\n}\n\nvoid\nbase_qobject::interpreter_event (const meth_callback& meth)\n{\n  // The following is a direct function call across threads.  It works\n  // because it is accessing a thread-safe queue of events that\n  // are later executed by the Octave interpreter in the other thread.\n\n  // See also the comments in interpreter-qobject.h about\n  // interpreter_qobject slots.\n\n  m_interpreter_qobj->interpreter_event (meth);\n}\n\nvoid\nbase_qobject::interpreter_interrupt ()\n{\n  m_interpreter_qobj->interrupt ();\n}\n\n// FIXME: Should we try to make the pause, stop, and resume actions\n// work for both the old and new terminal widget?\n\nvoid\nbase_qobject::interpreter_pause ()\n{\n  if (m_app_context.experimental_terminal_widget ())\n    m_interpreter_qobj->pause ();\n}\n\nvoid\nbase_qobject::interpreter_stop ()\n{\n  if (m_app_context.experimental_terminal_widget ())\n    m_interpreter_qobj->stop ();\n}\n\nvoid\nbase_qobject::interpreter_resume ()\n{\n  if (m_app_context.experimental_terminal_widget ())\n    m_interpreter_qobj->resume ();\n}\n\nvoid\nbase_qobject::copy_image_to_clipboard (const QString& file,\n                                       bool remove_file)\n{\n  QClipboard *clipboard = QApplication::clipboard ();\n\n  QImage img (file);\n\n  if (img.isNull ())\n    {\n      // Report error?\n      return;\n    }\n\n  clipboard->setImage (img);\n\n  if (remove_file)\n    QFile::remove (file);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/octave-qobject.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_octave_qobject_h)\n#define octave_octave_qobject_h 1\n\n#include <memory>\n\n#include <QApplication>\n#include <QList>\n#include <QObject>\n#include <QPointer>\n#include <QString>\n#include <QStringList>\n\n#include \"interpreter-qobject.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass community_news;\nclass main_window;\nclass qt_application;\nclass qt_interpreter_events;\nclass release_notes;\n\n//! This class is a simple wrapper around QApplication so that we can\n//! reimplement QApplication::notify.  The octave_qapplication object\n//! should behave identically to a QApplication object except that it\n//! overrides the notify method so we can handle forward Octave\n//! execution_exception exceptions from the GUI thread to the\n//! interpreter thread.\n\nclass octave_qapplication : public QApplication\n{\n  Q_OBJECT\n\npublic:\n\n  octave_qapplication (int& argc, char **argv)\n    : QApplication (argc, argv)\n  { }\n\n  virtual bool notify (QObject *receiver, QEvent *e) override;\n\n  ~octave_qapplication () { }\n\nQ_SIGNALS:\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n};\n\n//! Container for windows that may be created from the command line or\n//! docked with the main GUI window.  Any of these windows that are\n//! created in command line mode will be adopted by the main window if\n//! it is opened from the command line.  Any that are undocked from\n//! the main window will remain open if control returns to the command\n//! line.\n\nclass base_qobject;\nclass documentation_dock_widget;\nclass file_editor_interface;\nclass files_dock_widget;\nclass history_dock_widget;\nclass terminal_dock_widget;\nclass variable_editor;\nclass workspace_model;\nclass workspace_view;\n\n//! Base class for Octave interfaces that use Qt.  There are two\n//! classes derived from this one.  One provides a command-line\n//! interface that may use Qt graphics and another provides the\n//! full GUI experience.\n\nclass base_qobject : public QObject\n{\n  Q_OBJECT\n\npublic:\n\n  // Note: the GUI_APP argument is not needed with the new\n  // experimental terminal widget.\n  base_qobject (qt_application& app_context, bool gui_app = false);\n\n  ~base_qobject ();\n\n  void config_translators ();\n\n  void start_main_thread ();\n\n  int exec ();\n\n  // The Octave application context.\n  qt_application& app_context () { return m_app_context; }\n\n  // The Qt QApplication.\n  QApplication * qapplication () { return m_qapplication; };\n\n  // Provided for convenience.  Will be removed once we eliminate the\n  // old terminal widget.\n  bool experimental_terminal_widget () const;\n\n  // Provided for convenience.\n  bool gui_running () const;\n\n  bool have_terminal_window () const\n  {\n    return ! m_terminal_widget.isNull ();\n  }\n\n  main_window * get_main_window ()\n  {\n    return m_main_window;\n  }\n\n  std::shared_ptr<qt_interpreter_events> get_qt_interpreter_events ()\n  {\n    return m_qt_interpreter_events;\n  }\n\n  qt_interpreter_events * qt_link ()\n  {\n    return m_qt_interpreter_events.get ();\n  }\n\n  interpreter_qobject * interpreter_qobj ()\n  {\n    return m_interpreter_qobj;\n  }\n\n  workspace_model * get_workspace_model ()\n  {\n    return m_workspace_model;\n  }\n\n  QPointer<terminal_dock_widget>\n  terminal_widget (main_window *mw = nullptr);\n\n  QPointer<documentation_dock_widget>\n  documentation_widget (main_window *mw = nullptr);\n\n  QPointer<files_dock_widget>\n  file_browser_widget (main_window *mw = nullptr);\n\n  QPointer<history_dock_widget>\n  history_widget (main_window *mw = nullptr);\n\n  QPointer<workspace_view>\n  workspace_widget (main_window *mw = nullptr);\n\n  // FIXME: The file_editor_interface needs to be a proper generic\n  // interface for all editors (internal and external) for this to\n  // work properly.\n  QPointer<file_editor_interface>\n  editor_widget (main_window *mw = nullptr);\n\n  QPointer<variable_editor>\n  variable_editor_widget (main_window *mw = nullptr);\n\n  QPointer<community_news> community_news_widget (int serial = -1);\n\n  QPointer<release_notes> release_notes_widget ();\n\n  QThread * main_thread () { return m_main_thread; }\n\n  // Declared virtual so that a derived class may redefine this\n  // method.\n\n  virtual bool confirm_shutdown ();\n\n  bool is_gui_app () const { return m_gui_app; }\n\n  template <typename T> void connect_interpreter_events (T *widget)\n  {\n    connect (widget, qOverload<const fcn_callback&> (&T::interpreter_event),\n             this, qOverload<const fcn_callback&> (&base_qobject::interpreter_event));\n\n    connect (widget, qOverload<const meth_callback&> (&T::interpreter_event),\n             this, qOverload<const meth_callback&> (&base_qobject::interpreter_event));\n  }\n\npublic Q_SLOTS:\n\n  void execute_command (const QString& command);\n\n  // Note: START_GUI and CLOSE_GUI don't currently perform any work\n  // with the old terminal widget.\n  void start_gui (bool gui_app);\n  void close_gui ();\n\n  void show_terminal_window ();\n\n  void show_documentation_window (const QString& file);\n\n  void show_file_browser_window ();\n\n  void show_command_history_window ();\n\n  void show_workspace_window ();\n\n  void show_variable_editor_window (const QString& name,\n                                    const octave_value& value);\n\n  void handle_variable_editor_update ();\n\n  void show_community_news (int serial);\n\n  void show_release_notes ();\n\n  void interpreter_ready ();\n\n  void interpreter_event (const fcn_callback& fcn);\n\n  void interpreter_event (const meth_callback& meth);\n\n  void interpreter_interrupt ();\n\n  // Note: these currently only work with the new experimental\n  // terminal widget.\n  void interpreter_pause ();\n  void interpreter_stop ();\n  void interpreter_resume ();\n\n  void copy_image_to_clipboard (const QString& file, bool remove_file);\n\n  QPalette getFusionDarkPalette ();\n  void set_gui_style (bool called_from_main_window = false);\n\nprotected:\n\n  qt_application& m_app_context;\n\n  // Use these to ensure that argc and argv exist for as long as the\n  // QApplication object.\n\n  int m_argc;\n  char **m_argv;\n\n  octave_qapplication *m_qapplication;\n\n  QTranslator *m_qt_tr;\n  QTranslator *m_gui_tr;\n  QTranslator *m_qsci_tr;\n\n  bool m_translators_installed;\n\n  std::shared_ptr<qt_interpreter_events> m_qt_interpreter_events;\n\n  interpreter_qobject *m_interpreter_qobj;\n\n  QThread *m_main_thread;\n\n  bool m_gui_app;\n\n  bool m_interpreter_ready;\n\n  workspace_model *m_workspace_model;\n\n  // Dock widgets that may be used from the command line.  They are\n  // adopted by the desktop (main window) if it is also started from\n  // the command line.\n\n  QPointer<terminal_dock_widget> m_terminal_widget;\n\n  QPointer<documentation_dock_widget> m_documentation_widget;\n\n  QPointer<files_dock_widget> m_file_browser_widget;\n\n  QPointer<history_dock_widget> m_history_widget;\n\n  QPointer<workspace_view> m_workspace_widget;\n\n  QPointer<file_editor_interface> m_editor_widget;\n\n  QPointer<variable_editor> m_variable_editor_widget;\n\n  QPointer<community_news> m_community_news;\n\n  QPointer<release_notes> m_release_notes;\n\n  main_window *m_main_window;\n\n  bool m_style_set;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/octave-qt-features.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_qt_features_h)\n#define octave_qt_features_h 1\n\n// GUI header files are not installed and this file is always included\n// after <config.h> so using the following macro without first including\n// <config.h> in this file should be OK.  Some changes may be required\n// if we ever decide to install GUI header files.\n\n#if defined (HAVE_QTVERSIONCHECKS)\n#  include <QtVersionChecks>\n#else\n#  include <QtGlobal>\n#endif\n\n// See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813\n#define QTBUG_44813_FIX_VERSION QT_VERSION_CHECK (0xff, 0xff, 0xff)\n#if (QT_VERSION > QT_VERSION_CHECK (5, 3, 2)) && (QT_VERSION < QTBUG_44813_FIX_VERSION)\n#  define HAVE_FLOATING_QDOCKWIDGET_UNSELECTABLE_BUG 1\n#endif\n\n#if (QT_VERSION >= QT_VERSION_CHECK (5, 4, 0))\n#  define HAVE_QSURFACEFORMAT_SETDEFAULTFORMAT 1\n#  define QTIMER_SINGLESHOT_ACCEPTS_POINTER_TO_MEMBER_FUNCTION 1\n#endif\n\n#if (QT_VERSION >= QT_VERSION_CHECK (5, 14, 0))\n#  define HAVE_QCOMBOBOX_TEXTACTIVATED 1\n#endif\n\n#if (QT_VERSION >= QT_VERSION_CHECK (5, 15, 0))\n#  define HAVE_QSIGNALMAPPER_MAPPEDINT 1\n#  define HAVE_QSIGNALMAPPER_MAPPEDSTRING 1\n#endif\n\n#if (QT_VERSION >= QT_VERSION_CHECK (6, 0, 0))\n#  define HAVE_QFONTDATABASE_STATIC_MEMBER_FUNCTIONS 1\n#  define HAVE_QHELPENGINE_COPYCOLLECTIONFILE_TRUNCATION_BUG 1\n#  define HAVE_QHELPENGINE_SETREADONLY 1\n#  define HAVE_QKEYCOMBINATION_CLASS 1\n#  define HAVE_QLIBRARYINFO_PATH 1\n#  define HAVE_QSINGLEPOINTEVENT_CLASS 1\n#  define QVARIANT_CANCONVERT_REQUIRES_QMETATYPE_ARGUMENT 1\n#endif\n\n  // See Octave bug #53409 and https://bugreports.qt.io/browse/QTBUG-55357\n#if (QT_VERSION == QT_VERSION_CHECK (5, 6, 1)) || (QT_VERSION == QT_VERSION_CHECK (5, 7, 0))\n#  define HAVE_QDOCKWIDGET_REORDERING_BUG 1\n#endif\n\n#endif\n\n"
  },
  {
    "path": "libgui/src/qt-application.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QCoreApplication>\n#include <QSettings>\n#include <QString>\n\n#include \"main-window.h\"\n#include \"octave-qobject.h\"\n#include \"qt-application.h\"\n\n#include \"lo-utils.h\"\n#include \"oct-env.h\"\n#include \"oct-syscalls.h\"\n#include \"signal-wrappers.h\"\n\n#include \"display.h\"\n#include \"octave.h\"\n#include \"sysdep.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nqt_application::qt_application (const std::string& organization_name,\n                                const std::string& application_name,\n                                const std::string& application_version,\n                                int argc, char **argv)\n  : application (argc, argv)\n{\n  if (! organization_name.empty ())\n    QCoreApplication::setOrganizationName\n      (QString::fromStdString (organization_name));\n\n  if (! application_name.empty ())\n    QCoreApplication::setApplicationName\n      (QString::fromStdString (application_name));\n\n  if (! application_version.empty ())\n    QCoreApplication::setApplicationVersion\n      (QString::fromStdString (application_version));\n\n  // FIXME: Is there a better place for this?\n  QSettings::setDefaultFormat (QSettings::IniFormat);\n}\n\nqt_application::qt_application (int argc, char **argv)\n  : application (argc, argv)\n{\n}\n\nbool\nqt_application::start_gui_p () const\n{\n  // Note: this function is not needed if using the experimental\n  // terminal widget, so return a dummy value of false in that case.\n\n  return experimental_terminal_widget () ? false : m_options.gui ();\n}\n\nint\nqt_application::execute ()\n{\n  octave_block_interrupt_signal ();\n\n  set_application_id ();\n\n  // Create and show main window.\n\n  // Note: the second argument is ignored if using the new terminal\n  // widget.\n\n  base_qobject qt_interface (*this, start_gui_p ());\n\n  return qt_interface.exec ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/qt-application.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_qt_application_h)\n#define octave_qt_application_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"octave.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Programming Note: This file must not include any Qt headers.  Any\n// Qt header files required by the qt_application::execute function\n// must be included only in the corresponding .cc file.\n\n//! This class inherits from the pure-virtual base class\n//! application and provides an implementation of the\n//! application::execute method that starts an interface to Octave\n//! that is based on Qt.  It may start a command-line interface that\n//! allows Qt graphics to be used or it may start an interface that\n//! provides the full GUI experience.\n\nclass OCTGUI_API qt_application  : public application\n{\npublic:\n\n  qt_application (const std::string& organization_name,\n                  const std::string& application_name,\n                  const std::string& application_version,\n                  int argc, char **argv);\n\n  qt_application (int argc, char **argv);\n\n  OCTAVE_DISABLE_COPY_MOVE (qt_application)\n\n  ~qt_application () = default;\n\n  // Should we start the GUI or fall back to the CLI?\n  bool start_gui_p () const;\n\n  int execute ();\n\n  bool gui_running () const { return m_gui_running; }\n  void gui_running (bool arg) { m_gui_running = arg; }\n\n  bool multi_threaded () const { return true; }\n\nprivate:\n\n  // If TRUE, the GUI should be started.\n  bool m_gui_running = false;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/qt-interpreter-events.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n#include <sstream>\n\n#include <QDialog>\n#include <QDir>\n#include <QIcon>\n#include <QMetaType>\n#include <QPushButton>\n#include <QRegularExpression>\n#include <QStringList>\n\n#include \"dialog.h\"\n#include \"gui-preferences-ed.h\"\n#include \"gui-settings.h\"\n#include \"octave-qobject.h\"\n#include \"qt-interpreter-events.h\"\n#include \"qt-utils.h\"\n#if defined (HAVE_QSCINTILLA)\n#  include \"console-lexer.h\"\n#endif\n\n#include \"localcharset-wrapper.h\"\n#include \"oct-env.h\"\n#include \"str-vec.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"load-path.h\"\n#include \"oct-map.h\"\n#include \"octave.h\"\n#include \"ov.h\"\n#include \"syminfo.h\"\n#include \"utils.h\"\n\nQ_DECLARE_METATYPE (octave_value)\nQ_DECLARE_METATYPE (octave::symbol_info_list)\nQ_DECLARE_METATYPE (octave::fcn_callback)\nQ_DECLARE_METATYPE (octave::meth_callback)\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic QStringList\nmake_qstring_list (const std::list<std::string>& lst)\n{\n  QStringList retval;\n\n  for (const auto& s : lst)\n    retval.append (QString::fromStdString (s));\n\n  return retval;\n}\n\nstatic QStringList\nmake_filter_list (const event_manager::filter_list& lst)\n{\n  QStringList retval;\n\n  // We have pairs of data, first being the list of extensions\n  // exta;exb;extc etc second the name to use as filter name\n  // (optional).  Qt wants a list of filters in the format of\n  // 'FilterName (space separated exts)'.\n\n  for (const auto& ext_name : lst)\n    {\n      QString ext = QString::fromStdString (ext_name.first);\n      QString name = QString::fromStdString (ext_name.second);\n\n      // Strip out extensions from name and replace ';' with spaces in list.\n\n      name.replace (QRegularExpression {R\"(\\(.*\\))\"}, \"\");\n      ext.replace (\";\", \" \");\n\n      if (name.isEmpty ())\n        {\n          // No name field.  Build one from the extensions.\n          name = ext.toUpper () + \" Files\";\n        }\n\n      retval.append (name + \" (\" + ext + ')');\n    }\n\n  return retval;\n}\n\nqt_interpreter_events::qt_interpreter_events (base_qobject& oct_qobj)\n  : interpreter_events (), m_octave_qobj (oct_qobj),\n    m_uiwidget_creator (), m_result (), m_mutex (),\n    m_waitcondition ()\n{\n  qRegisterMetaType<QIntList> (\"QIntList\");\n  qRegisterMetaType<QFloatList> (\"QFloatList\");\n\n  qRegisterMetaType<octave_value> (\"octave_value\");\n  qRegisterMetaType<symbol_info_list> (\"symbol_info_list\");\n\n  qRegisterMetaType<fcn_callback> (\"fcn_callback\");\n  qRegisterMetaType<meth_callback> (\"meth_callback\");\n\n  connect (this, &qt_interpreter_events::confirm_shutdown_signal,\n           this, &qt_interpreter_events::confirm_shutdown_octave);\n\n  connect (this, &qt_interpreter_events::get_named_icon_signal,\n           this, &qt_interpreter_events::get_named_icon_slot);\n\n  connect (this, &qt_interpreter_events::gui_preference_signal,\n           this, &qt_interpreter_events::gui_preference_slot);\n}\n\nvoid\nqt_interpreter_events::start_gui (bool gui_app)\n{\n  if (m_octave_qobj.experimental_terminal_widget ())\n    Q_EMIT start_gui_signal (gui_app);\n}\n\nvoid\nqt_interpreter_events::close_gui ()\n{\n  if (m_octave_qobj.experimental_terminal_widget ())\n    Q_EMIT close_gui_signal ();\n}\n\nstd::list<std::string>\nqt_interpreter_events::file_dialog (const filter_list& filter,\n                                    const std::string& title,\n                                    const std::string& filename,\n                                    const std::string& dirname,\n                                    const std::string& multimode)\n{\n  QStringList lst\n    = m_uiwidget_creator.file_dialog (make_filter_list (filter),\n                                      QString::fromStdString (title),\n                                      QString::fromStdString (filename),\n                                      QString::fromStdString (dirname),\n                                      QString::fromStdString (multimode));\n\n  std::list<std::string> retval;\n\n  for (const auto& s : lst)\n    retval.push_back (s.toStdString ());\n\n  return retval;\n}\n\nstd::list<std::string>\nqt_interpreter_events::input_dialog (const std::list<std::string>& prompt,\n                                     const std::string& title,\n                                     const std::list<float>& nr,\n                                     const std::list<float>& nc,\n                                     const std::list<std::string>& defaults)\n{\n  QStringList lst\n    = m_uiwidget_creator.input_dialog (make_qstring_list (prompt),\n                                       QString::fromStdString (title),\n                                       std_list_to_qt_list<float> (nr),\n                                       std_list_to_qt_list<float> (nc),\n                                       make_qstring_list (defaults));\n  std::list<std::string> retval;\n\n  for (const auto& s : lst)\n    retval.push_back (s.toStdString ());\n\n  return retval;\n}\n\nstd::pair<std::list<int>, int>\nqt_interpreter_events::list_dialog (const std::list<std::string>& list,\n                                    const std::string& mode,\n                                    int width, int height,\n                                    const std::list<int>& initial,\n                                    const std::string& name,\n                                    const std::list<std::string>& prompt,\n                                    const std::string& ok_string,\n                                    const std::string& cancel_string)\n{\n  QPair<QIntList, int> result\n    = m_uiwidget_creator.list_dialog (make_qstring_list (list),\n                                      QString::fromStdString (mode),\n                                      width, height,\n                                      std_list_to_qt_list<int> (initial),\n                                      QString::fromStdString (name),\n                                      make_qstring_list (prompt),\n                                      QString::fromStdString (ok_string),\n                                      QString::fromStdString (cancel_string));\n\n  QIntList& lst = result.first;\n  return std::pair<std::list<int>, int> (std::list<int> (lst.begin (),\n                                                         lst.end ()),\n                                         result.second);\n}\n\nstd::string\nqt_interpreter_events::question_dialog (const std::string& msg,\n                                        const std::string& title,\n                                        const std::string& btn1,\n                                        const std::string& btn2,\n                                        const std::string& btn3,\n                                        const std::string& btndef)\n{\n  QString icon = \"quest\";\n  QStringList buttons;\n  QStringList role;\n\n  // Must use ResetRole which is left-aligned for all OS and WM.\n  role << \"ResetRole\" << \"ResetRole\" << \"ResetRole\";\n\n  buttons << QString::fromStdString (btn1);\n  if (btn2 == \"\")\n    role.removeAt (0);\n  else\n    buttons << QString::fromStdString (btn2);\n  buttons << QString::fromStdString (btn3);\n\n  QString answer\n    = m_uiwidget_creator.message_dialog (QString::fromStdString (msg),\n                                         QString::fromStdString (title),\n                                         icon, buttons,\n                                         QString::fromStdString (btndef),\n                                         role);\n\n  return answer.toStdString ();\n}\n\nvoid\nqt_interpreter_events::update_path_dialog ()\n{\n  Q_EMIT update_path_dialog_signal ();\n}\n\nvoid\nqt_interpreter_events::show_preferences ()\n{\n  Q_EMIT show_preferences_signal ();\n}\n\nvoid\nqt_interpreter_events::apply_preferences ()\n{\n  Q_EMIT apply_new_settings ();\n}\n\nvoid\nqt_interpreter_events::show_terminal_window ()\n{\n  Q_EMIT show_terminal_window_signal ();\n}\n\nbool\nqt_interpreter_events::show_documentation (const std::string& file)\n{\n  Q_EMIT show_documentation_signal (QString::fromStdString (file));\n\n  return true;\n}\n\nvoid\nqt_interpreter_events::show_file_browser ()\n{\n  Q_EMIT show_file_browser_signal ();\n}\n\nvoid\nqt_interpreter_events::show_command_history ()\n{\n  Q_EMIT show_command_history_signal ();\n}\n\nvoid\nqt_interpreter_events::show_workspace ()\n{\n  Q_EMIT show_workspace_signal ();\n}\n\nvoid\nqt_interpreter_events::show_community_news (int serial)\n{\n  Q_EMIT show_community_news_signal (serial);\n}\n\nvoid\nqt_interpreter_events::show_release_notes ()\n{\n  Q_EMIT show_release_notes_signal ();\n}\n\nbool\nqt_interpreter_events::edit_file (const std::string& file)\n{\n  Q_EMIT edit_file_signal (QString::fromStdString (file));\n\n  return true;\n}\n\nvoid\nqt_interpreter_events::edit_variable (const std::string& expr,\n                                      const octave_value& val)\n{\n  Q_EMIT edit_variable_signal (QString::fromStdString (expr), val);\n}\n\nbool\nqt_interpreter_events::confirm_shutdown ()\n{\n  QMutexLocker autolock (&m_mutex);\n\n  Q_EMIT confirm_shutdown_signal ();\n\n  // Wait for result.\n  wait ();\n\n  return m_result.toBool ();\n}\n\nbool\nqt_interpreter_events::prompt_new_edit_file (const std::string& file)\n{\n  gui_settings settings;\n\n  if (settings.bool_value (ed_create_new_file))\n    return true;\n\n  std::string abs_fname = sys::env::make_absolute (file);\n\n  QStringList btn;\n  QStringList role;\n  role << \"YesRole\" << \"RejectRole\";\n  btn << tr (\"Create\") << tr (\"Cancel\");\n\n  QString answer = m_uiwidget_creator.message_dialog\n    (tr (\"File\\n%1\\ndoes not exist. Do you want to create it?\").\n     arg (QString::fromStdString (abs_fname)),\n     tr (\"Octave Editor\"), \"quest\", btn, tr (\"Create\"), role);\n\n  return (answer == tr (\"Create\"));\n}\n\n// Prompt to allow file to be run by setting cwd (or if\n// addpath_option==true, alternatively setting the path).\n\nint\nqt_interpreter_events::debug_cd_or_addpath_error (const std::string& file,\n                                                  const std::string& dir,\n                                                  bool addpath_option)\n{\n  int retval = -1;\n\n  QString qdir = QString::fromStdString (dir);\n  QString qfile = QString::fromStdString (file);\n  QString msg\n    = (addpath_option\n       ? tr (\"The file %1 does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.\").arg (qfile).arg (qdir)\n       : tr (\"The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.\").arg (qfile).arg (qdir));\n\n  QString title = tr (\"Change Directory or Add Directory to Load Path\");\n\n  QString cd_txt = tr (\"&Change Directory\");\n  QString addpath_txt = tr (\"&Add Directory to Load Path\");\n  QString cancel_txt = tr (\"Cancel\");\n\n  QStringList btn;\n  QStringList role;\n  btn << cd_txt;\n  role << \"YesRole\";\n  if (addpath_option)\n    {\n      btn << addpath_txt;\n      role << \"AcceptRole\";\n    }\n  btn << cancel_txt;\n  role << \"RejectRole\";\n\n  QString result\n    = m_uiwidget_creator.message_dialog (msg, title, \"quest\", btn,\n                                         cancel_txt, role);\n\n  if (result == cd_txt)\n    retval = 1;\n  else if (result == addpath_txt)\n    retval = 2;\n\n  return retval;\n}\n\nuint8NDArray\nqt_interpreter_events::get_named_icon (const std::string& name)\n{\n  QMutexLocker autolock (&m_mutex);\n\n  Q_EMIT get_named_icon_signal (QString::fromStdString (name));\n\n  // Wait for result.\n  wait ();\n\n  uint8NDArray empty_img;\n\n  QIcon icon = m_result.value<QIcon> ();\n\n  if (icon.isNull ())\n    return empty_img;\n\n  QImage img = icon.pixmap (QSize (32, 32)).toImage ();\n\n  if (img.format () != QImage::Format_ARGB32_Premultiplied)\n    return empty_img;\n\n  dim_vector dims (img.height (), img.width (), 4);\n\n  uint8NDArray retval (dims, 0);\n\n  uint8_t *bits = img.bits ();\n\n  for (int i = 0; i < img.height (); i++)\n    {\n      for (int j = 0; j < img.width (); j++)\n        {\n          retval(i, j, 2) = bits[0];\n          retval(i, j, 1) = bits[1];\n          retval(i, j, 0) = bits[2];\n          retval(i, j, 3) = bits[3];\n\n          bits += 4;\n        }\n    }\n\n  return retval;\n}\n\nvoid\nqt_interpreter_events::get_named_icon_slot (const QString& name)\n{\n  QMutexLocker autolock (&m_mutex);\n\n  gui_settings settings;\n\n  m_result = QVariant::fromValue (settings.icon (name));\n\n  wake_all ();\n}\n\nstd::string\nqt_interpreter_events::gui_preference (const std::string& key,\n                                       const std::string& value)\n{\n  QString pref_value;\n\n  QMutexLocker autolock (&m_mutex);\n\n  // Emit the signal for changing or getting a preference\n  Q_EMIT gui_preference_signal (QString::fromStdString (key),\n                                QString::fromStdString (value));\n\n  // Wait for response (pref_value).\n  wait ();\n\n  QString pref = m_result.toString ();\n\n  return pref.toStdString ();\n}\n\nbool\nqt_interpreter_events::copy_image_to_clipboard (const std::string& file)\n{\n  Q_EMIT copy_image_to_clipboard_signal (QString::fromStdString (file), true);\n\n  return true;\n}\n\nvoid\nqt_interpreter_events::focus_window (const std::string win_name)\n{\n  Q_EMIT focus_window_signal (QString::fromStdString (win_name));\n}\n\nvoid\nqt_interpreter_events::execute_command_in_terminal (const std::string& command)\n{\n  Q_EMIT execute_command_in_terminal_signal (QString::fromStdString (command));\n}\n\nstd::string\nqt_interpreter_events::get_input_from_terminal (const std::string& prompt)\n{\n  std::string retval;\n\n  if (m_octave_qobj.experimental_terminal_widget ()\n      && m_octave_qobj.have_terminal_window ())\n    {\n      // currently only works with experimental terminal widget\n      QMutexLocker autolock (&m_mutex);\n\n      Q_EMIT get_input_from_terminal_signal (QString::fromStdString (prompt));\n\n      // Wait for user input\n      wait ();\n\n      QString input_line = m_result.toString ();\n\n      return input_line.toStdString ();\n    }\n\n  return retval;\n}\n\nvoid qt_interpreter_events::finished_input_from_terminal (const QString& input)\n{\n  m_result = input;\n  wake_all ();\n}\n\nvoid\nqt_interpreter_events::register_documentation (const std::string& file)\n{\n  Q_EMIT register_documentation_signal (QString::fromStdString (file));\n}\n\nvoid\nqt_interpreter_events::unregister_documentation (const std::string& file)\n{\n  Q_EMIT unregister_documentation_signal (QString::fromStdString (file));\n}\n\nvoid\nqt_interpreter_events::interpreter_output (const std::string& msg)\n{\n  if (m_octave_qobj.experimental_terminal_widget ()\n      && m_octave_qobj.have_terminal_window ())\n    Q_EMIT interpreter_output_signal (QString::fromStdString (msg));\n  else\n    {\n      // FIXME: is this the correct thing to do?\n      std::cout << msg;\n    }\n}\n\nvoid\nqt_interpreter_events::display_exception (const execution_exception& ee,\n    bool beep)\n{\n  if (m_octave_qobj.experimental_terminal_widget ()\n      && m_octave_qobj.have_terminal_window ())\n    {\n      // Output the exception message\n      std::ostringstream buf;\n      ee.display (buf);\n      Q_EMIT interpreter_output_signal (QString::fromStdString (buf.str ()),\n#if defined (HAVE_QSCINTILLA)\n                                        console_lexer::Error);\n#else\n                                        100);\n#endif\n      // Create w new command line\n      Q_EMIT new_command_line_signal ();\n    }\n  else\n    {\n      if (beep)\n        std::cerr << \"\\a\";\n\n      ee.display (std::cerr);\n    }\n}\n\nvoid\nqt_interpreter_events::gui_status_update (const std::string& feature,\n    const std::string& status)\n{\n  Q_EMIT gui_status_update_signal (QString::fromStdString (feature),\n                                   QString::fromStdString (status));\n}\n\nvoid\nqt_interpreter_events::update_gui_lexer ()\n{\n  Q_EMIT update_gui_lexer_signal (true);\n}\n\nvoid\nqt_interpreter_events::directory_changed (const std::string& dir)\n{\n  Q_EMIT directory_changed_signal (QString::fromStdString (dir));\n}\n\nvoid\nqt_interpreter_events::file_remove (const std::string& old_name,\n                                    const std::string& new_name)\n{\n  QMutexLocker autolock (&m_mutex);\n\n  // Emit the signal for the editor for closing the file if it is open\n  Q_EMIT file_remove_signal (QString::fromStdString (old_name),\n                             QString::fromStdString (new_name));\n\n  // Wait for file removal to complete before continuing.\n  wait ();\n}\n\nvoid\nqt_interpreter_events::file_renamed (bool load_new)\n{\n  Q_EMIT file_renamed_signal (load_new);\n}\n\nvoid\nqt_interpreter_events::set_workspace (bool top_level, bool debug,\n                                      const symbol_info_list& syminfo,\n                                      bool update_variable_editor)\n{\n  if (! top_level && ! debug)\n    return;\n\n  Q_EMIT set_workspace_signal (top_level, debug, syminfo);\n\n  if (update_variable_editor)\n    Q_EMIT refresh_variable_editor_signal ();\n}\n\nvoid\nqt_interpreter_events::clear_workspace ()\n{\n  Q_EMIT clear_workspace_signal ();\n}\n\nvoid\nqt_interpreter_events::update_prompt (const std::string& prompt)\n{\n  Q_EMIT update_prompt_signal (QString::fromStdString (prompt));\n}\n\nvoid\nqt_interpreter_events::set_history (const string_vector& hist)\n{\n  QStringList qt_hist;\n\n  for (octave_idx_type i = 0; i < hist.numel (); i++)\n    qt_hist.append (QString::fromStdString (hist[i]));\n\n  Q_EMIT set_history_signal (qt_hist);\n}\n\nvoid\nqt_interpreter_events::append_history (const std::string& hist_entry)\n{\n  Q_EMIT append_history_signal (QString::fromStdString (hist_entry));\n}\n\nvoid\nqt_interpreter_events::clear_history ()\n{\n  Q_EMIT clear_history_signal ();\n}\n\nvoid\nqt_interpreter_events::pre_input_event ()\n{ }\n\nvoid\nqt_interpreter_events::post_input_event ()\n{ }\n\nvoid\nqt_interpreter_events::enter_debugger_event (const std::string& /*fcn_name*/,\n    const std::string& fcn_file_name,\n    int line)\n{\n  if (fcn_file_name.empty ())\n    return;\n\n  insert_debugger_pointer (fcn_file_name, line);\n\n  Q_EMIT enter_debugger_signal ();\n}\n\nvoid\nqt_interpreter_events::execute_in_debugger_event (const std::string& file,\n                                                  int line)\n{\n  delete_debugger_pointer (file, line);\n}\n\nvoid\nqt_interpreter_events::exit_debugger_event ()\n{\n  Q_EMIT exit_debugger_signal ();\n}\n\n//! Display (if @c insert true) or remove the appropriate symbol for a\n//! breakpoint in @c file at @c line with condition @c cond.\n\nvoid\nqt_interpreter_events::update_breakpoint (bool insert,\n                                          const std::string& file,\n                                          int line,\n                                          const std::string& cond)\n{\n  Q_EMIT update_breakpoint_marker_signal (insert, QString::fromStdString (file),\n                                          line, QString::fromStdString (cond));\n}\n\nvoid\nqt_interpreter_events::insert_debugger_pointer (const std::string& file,\n                                                int line)\n{\n  Q_EMIT insert_debugger_pointer_signal (QString::fromStdString (file), line);\n}\n\nvoid\nqt_interpreter_events::delete_debugger_pointer (const std::string& file,\n                                                int line)\n{\n  Q_EMIT delete_debugger_pointer_signal (QString::fromStdString (file), line);\n}\n\nvoid\nqt_interpreter_events::confirm_shutdown_octave ()\n{\n  QMutexLocker autolock (&m_mutex);\n\n  m_result = m_octave_qobj.confirm_shutdown ();\n\n  wake_all ();\n}\n\n// If VALUE is empty, return current value of preference named by KEY.\n//\n// If VALUE is not empty, set preference named by KEY to VALUE return\n// previous value.\n//\n// FIXME: should we have separate get and set functions?  With only\n// one, we don't allow a preference value to be set to the empty\n// string.\n\nvoid\nqt_interpreter_events::gui_preference_slot (const QString& key,\n                                            const QString& value)\n{\n  QMutexLocker autolock (&m_mutex);\n\n  gui_settings settings;\n\n  // We don't want to apply default value here.\n  QString read_value = settings.value (key).toString ();\n\n  // Some preferences need extra handling\n  QString adjusted_value = gui_preference_adjust (key, value);\n\n  if (! adjusted_value.isEmpty () && (read_value != adjusted_value))\n    {\n      // Change settings only for new, non-empty values\n      settings.setValue (key, QVariant (adjusted_value));\n\n      Q_EMIT settings_changed (true);   // true: changed by worker\n    }\n\n  m_result = read_value;\n\n  wake_all ();\n}\n\nQString\nqt_interpreter_events::gui_preference_adjust (const QString& key,\n                                              const QString& value)\n{\n  // Immediately return if no new value is given.\n\n  if (value.isEmpty ())\n    return value;\n\n  QString adjusted_value = value;\n\n  if (key == ed_default_enc.settings_key ())\n    {\n      adjusted_value = adjusted_value.toUpper ();\n\n      if (adjusted_value == \"SYSTEM\")\n        adjusted_value =\n          QString (\"SYSTEM (\") +\n          QString (octave_locale_charset_wrapper ()).toUpper () +\n          QString (\")\");\n    }\n\n  return adjusted_value;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/qt-interpreter-events.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_qt_interpreter_events_h)\n#define octave_qt_interpreter_events_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n\n#include <QList>\n#include <QMutex>\n#include <QObject>\n#include <QString>\n#include <QWaitCondition>\n\n#include \"dialog.h\"\n\n#include \"event-manager.h\"\n\n// Defined for purposes of sending QList<int> as part of signal.\ntypedef QList<int> QIntList;\n\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_qobject;\n\n// The functions in this class are not normally called directly, but\n// are invoked from the Octave interpreter thead by methods in the\n// event_manager class.  In most cases, they should only translate\n// data from the types typically used in the interpreter to whatever\n// is required by the GUI (for example, std::string to QString) and\n// emit a Qt signal.\n//\n// The use of Qt signals provides a thread-safe way for the Octave\n// interpreter to notify the GUI of events (directory or workspace has\n// changed, for example) or to request that the GUI perform actions\n// (display a dialog, for example).\n//\n// By using this class as a wrapper around the Qt signals, we maintain\n// a separation between the Octave interpreter and any specific GUI\n// toolkit (no Qt headers are used in the Octave interpreter sources).\n\nclass qt_interpreter_events : public QObject, public interpreter_events\n{\n  Q_OBJECT\n\npublic:\n\n  qt_interpreter_events (base_qobject& oct_qobj);\n\n  OCTAVE_DISABLE_COPY_MOVE (qt_interpreter_events)\n\n  ~qt_interpreter_events () = default;\n\n  // Note: these functions currently do nothing with the old terminal\n  // widget.\n  void start_gui (bool gui_app = false);\n  void close_gui ();\n\n  bool have_dialogs () const { return true; }\n\n  std::list<std::string>\n  file_dialog (const filter_list& filter, const std::string& title,\n               const std::string& filename, const std::string& pathname,\n               const std::string& multimode);\n\n  std::list<std::string>\n  input_dialog (const std::list<std::string>& prompt,\n                const std::string& title, const std::list<float>& nr,\n                const std::list<float>& nc,\n                const std::list<std::string>& defaults);\n\n  std::pair<std::list<int>, int>\n  list_dialog (const std::list<std::string>& list,\n               const std::string& mode, int width, int height,\n               const std::list<int>& initial_value,\n               const std::string& name,\n               const std::list<std::string>& prompt,\n               const std::string& ok_string,\n               const std::string& cancel_string);\n\n  std::string\n  question_dialog (const std::string& msg, const std::string& title,\n                   const std::string& btn1, const std::string& btn2,\n                   const std::string& btn3, const std::string& btndef);\n\n  void update_path_dialog ();\n\n  void show_preferences ();\n\n  void apply_preferences ();\n\n  void show_terminal_window ();\n\n  bool show_documentation (const std::string& file);\n\n  void show_file_browser ();\n\n  void show_command_history ();\n\n  void show_workspace ();\n\n  void show_community_news (int serial);\n  void show_release_notes ();\n\n  bool edit_file (const std::string& file);\n\n  void edit_variable (const std::string& name, const octave_value& val);\n\n  bool confirm_shutdown ();\n\n  bool prompt_new_edit_file (const std::string& file);\n\n  int debug_cd_or_addpath_error (const std::string& file,\n                                 const std::string& dir,\n                                 bool addpath_option);\n\n  uint8NDArray get_named_icon (const std::string& icon_name);\n\n  std::string gui_preference (const std::string& key,\n                              const std::string& value);\n\n  bool copy_image_to_clipboard (const std::string& file);\n\n  void focus_window (const std::string win_name);\n\n  void execute_command_in_terminal (const std::string& command);\n\n  // Note: this function currently does nothing with the old terminal\n  // widget.\n  std::string get_input_from_terminal (const std::string& prompt);\n\n  void register_documentation (const std::string& file);\n\n  void unregister_documentation (const std::string& file);\n\n  // Note: this function currently does nothing with the old terminal\n  // widget.\n  void interpreter_output (const std::string& msg);\n\n  void display_exception (const execution_exception& ee, bool beep);\n\n  void gui_status_update (const std::string& feature, const std::string& status);\n\n  void update_gui_lexer ();\n\n  void directory_changed (const std::string& dir);\n\n  void file_remove (const std::string& old_name,\n                    const std::string& new_name);\n\n  void file_renamed (bool load_new = true);\n\n  void set_workspace (bool top_level, bool debug,\n                      const symbol_info_list& syminfo,\n                      bool update_variable_editor);\n\n  void clear_workspace ();\n\n  void update_prompt (const std::string& prompt);\n\n  void set_history (const string_vector& hist);\n\n  void append_history (const std::string& hist_entry);\n\n  void clear_history ();\n\n  void pre_input_event ();\n\n  void post_input_event ();\n\n  void enter_debugger_event (const std::string& fcn_name,\n                             const std::string& fcn_file_name, int line);\n\n  void execute_in_debugger_event (const std::string& file, int line);\n\n  void exit_debugger_event ();\n\n  void update_breakpoint (bool insert, const std::string& file, int line,\n                          const std::string& cond);\n\n  void lock () { m_mutex.lock (); }\n\n  void wait () { m_waitcondition.wait (&m_mutex); }\n\n  void unlock () { m_mutex.unlock (); }\n\n  void wake_all () { m_waitcondition.wakeAll (); }\n\npublic Q_SLOTS:\n\n  void confirm_shutdown_octave ();\n\n  void get_named_icon_slot (const QString& name);\n\n  void gui_preference_slot (const QString& key, const QString& value);\n\n  void finished_input_from_terminal (const QString& input);\n\nQ_SIGNALS:\n\n  // Note: these signals are not currently used by the old terminal widget.\n  void start_gui_signal (bool gui_app);\n  void close_gui_signal ();\n\n  void copy_image_to_clipboard_signal (const QString& file, bool remove_file);\n\n  void focus_window_signal (const QString& win_name);\n\n  void edit_file_signal (const QString& file);\n\n  void directory_changed_signal (const QString& dir);\n\n  void update_path_dialog_signal ();\n\n  void file_remove_signal (const QString& old_name, const QString& new_name);\n\n  void file_renamed_signal (bool load_new);\n\n  void execute_command_in_terminal_signal (const QString& command);\n\n  void get_input_from_terminal_signal (const QString& prompt);\n\n  void set_workspace_signal (bool top_level, bool debug,\n                             const symbol_info_list& syminfo);\n\n  void clear_workspace_signal ();\n\n  void update_prompt_signal (const QString& prompt);\n\n  void set_history_signal (const QStringList& hist);\n\n  void append_history_signal (const QString& hist_entry);\n\n  void clear_history_signal ();\n\n  void enter_debugger_signal ();\n\n  void exit_debugger_signal ();\n\n  void update_breakpoint_marker_signal (bool insert, const QString& file,\n                                        int line, const QString& cond);\n\n  void insert_debugger_pointer_signal (const QString&, int);\n\n  void delete_debugger_pointer_signal (const QString&, int);\n\n  void show_preferences_signal ();\n\n  void gui_preference_signal (const QString& key, const QString& value);\n\n  void show_terminal_window_signal ();\n\n  void show_documentation_signal (const QString& file);\n\n  void register_documentation_signal (const QString& file);\n\n  void unregister_documentation_signal (const QString& file);\n\n  void show_file_browser_signal ();\n\n  void show_command_history_signal ();\n\n  void show_workspace_signal ();\n\n  void show_community_news_signal (int serial);\n  void show_release_notes_signal ();\n\n  // Note: the next two signals are currently not used by the old terminal widget.\n  void interpreter_output_signal (const QString& msg, int style = 0);\n  void new_command_line_signal (const QString& msg = QString ());\n\n  void gui_status_update_signal (const QString& feature, const QString& status);\n\n  void update_gui_lexer_signal (bool update_apis_only);\n\n  void edit_variable_signal (const QString& name, const octave_value& val);\n\n  void refresh_variable_editor_signal ();\n\n  void confirm_shutdown_signal ();\n\n  void get_named_icon_signal (const QString& name);\n\n  void settings_changed (bool);\n\n  void apply_new_settings ();\n\nprivate:\n\n  QString gui_preference_adjust (const QString& key, const QString& value);\n\n  void insert_debugger_pointer (const std::string& file, int line);\n\n  void delete_debugger_pointer (const std::string& file, int line);\n\n  base_qobject& m_octave_qobj;\n\n  QUIWidgetCreator m_uiwidget_creator;\n\n  QVariant m_result;\n\n  QMutex m_mutex;\n\n  QWaitCondition m_waitcondition;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/qt-utils.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_qt_utils_h)\n#define octave_qt_utils_h 1\n\n#include <list>\n\n#include <QFontMetrics>\n#include <QList>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T>\ninline QList<T>\nstd_list_to_qt_list (const std::list<T>& lst)\n{\n#if defined (HAVE_QLIST_ITERATOR_CONSTRUCTOR)\n  return QList<T> (lst.begin (), lst.end ());\n#else\n  return QList<T>::fromStdList (lst);\n#endif\n}\n\ninline int\nqt_fontmetrics_horizontal_advance (const QFontMetrics& fm, QChar ch)\n{\n#if defined (HAVE_QFONTMETRICS_HORIZONTAL_ADVANCE)\n  return fm.horizontalAdvance (ch);\n#else\n  return fm.width (ch);\n#endif\n}\n\ninline int\nqt_fontmetrics_horizontal_advance (const QFontMetrics& fm,\n                                   const QString& text, int len = -1)\n{\n#if defined (HAVE_QFONTMETRICS_HORIZONTAL_ADVANCE)\n  return fm.horizontalAdvance (text, len);\n#else\n  return fm.width (text, len);\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/release-notes.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QApplication>\n#include <QFile>\n#include <QIcon>\n#include <QLayout>\n#include <QScreen>\n#include <QTextBrowser>\n#include <QTextStream>\n#include <QThread>\n\n#include \"release-notes.h\"\n#include \"gui-utils.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-dw.h\"\n#include \"gui-preferences-nr.h\"\n#include \"gui-settings.h\"\n#include \"news-reader.h\"\n\n#include \"defaults.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nrelease_notes::release_notes ()\n  : QWidget (nullptr), m_browser (nullptr)\n{\n\n  gui_settings settings;\n\n  // The icon\n  QString icon_set = settings.string_value (dw_icon_set);\n\n  if (icon_set != \"NONE\")\n    m_release_notes_icon = dw_icon_set_names[icon_set]\n                             + \"ReleaseWidget\" + global_icon_extension;\n  else\n    m_release_notes_icon = dw_icon_set_names[icon_set];\n\n  std::string news_file = config::oct_etc_dir () + \"/NEWS\";\n\n  QString news;\n\n  QFile *file = new QFile (QString::fromStdString (news_file));\n  if (file->open (QFile::ReadOnly))\n    {\n      QTextStream *stream = new QTextStream (file);\n      news = stream->readAll ();\n      if (! news.isEmpty ())\n        {\n          // Convert '<', '>' which would be interpreted as HTML\n          news.replace (\"<\", \"&lt;\");\n          news.replace (\">\", \"&gt;\");\n          // Add HTML tags for pre-formatted text\n          news.prepend (\"<pre>\");\n          news.append (\"</pre>\");\n        }\n      else\n        news = (tr (\"The release notes file '%1' is empty.\")\n                . arg (QString::fromStdString (news_file)));\n    }\n  else\n    news = (tr (\"The release notes file '%1' cannot be read.\")\n            . arg (QString::fromStdString (news_file)));\n\n  m_browser = new QTextBrowser (this);\n  m_browser->setText (news);\n\n  QVBoxLayout *vlayout = new QVBoxLayout;\n  vlayout->addWidget (m_browser);\n\n  setLayout (vlayout);\n  setWindowTitle (tr (\"Octave Release Notes\"));\n\n  m_browser->document ()->adjustSize ();\n\n  int win_x, win_y;\n  get_screen_geometry (win_x, win_y);\n\n  resize (win_x*2/5, win_y*2/3);\n  move (20, 20);  // move to the top left corner\n}\n\nvoid\nrelease_notes::display ()\n{\n  if (! isVisible ())\n    show ();\n  else if (isMinimized ())\n    showNormal ();\n\n  setWindowIcon (QIcon (m_release_notes_icon));\n\n  raise ();\n  activateWindow ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/release-notes.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_release_notes_h)\n#define octave_release_notes_h 1\n\n#include <QString>\n#include <QWidget>\n\nclass QTextBrowser;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass release_notes : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  release_notes ();\n\n  ~release_notes () = default;\n\npublic Q_SLOTS:\n\n  void display ();\n\nprivate:\n\n  QTextBrowser *m_browser;\n  QString m_release_notes_icon;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/resource.qrc",
    "content": "<RCC>\n    <qresource prefix=\"/\">\n        <file>icons/cursors/bottom_left_corner.png</file>\n        <file>icons/cursors/bottom_right_corner.png</file>\n        <file>icons/cursors/bottom_side.png</file>\n        <file>icons/cursors/circle.png</file>\n        <file>icons/cursors/cross.png</file>\n        <file>icons/cursors/fleur.png</file>\n        <file>icons/cursors/hand2.png</file>\n        <file>icons/cursors/left_side.png</file>\n        <file>icons/cursors/right_side.png</file>\n        <file>icons/cursors/top_left_corner.png</file>\n        <file>icons/cursors/top_right_corner.png</file>\n        <file>icons/cursors/top_side.png</file>\n        <file>icons/octave/scalable/applications-system.svg</file>\n        <file>icons/octave/scalable/bookmark-new.svg</file>\n        <file>icons/octave/scalable/bp-toggle.svg</file>\n        <file>icons/octave/scalable/bp-rm-all.svg</file>\n        <file>icons/octave/scalable/bp-prev.svg</file>\n        <file>icons/octave/scalable/bp-next.svg</file>\n        <file>icons/octave/scalable/db-cont.svg</file>\n        <file>icons/octave/scalable/db-step.svg</file>\n        <file>icons/octave/scalable/db-step-in.svg</file>\n        <file>icons/octave/scalable/db-step-out.svg</file>\n        <file>icons/octave/scalable/db-stop.svg</file>\n        <file>icons/octave/scalable/dialog-information.svg</file>\n        <file>icons/octave/scalable/dialog-error.svg</file>\n        <file>icons/octave/scalable/document-new.svg</file>\n        <file>icons/octave/scalable/document-open.svg</file>\n        <file>icons/octave/scalable/document-print.svg</file>\n        <file>icons/octave/scalable/document-save-as.svg</file>\n        <file>icons/octave/scalable/document-save.svg</file>\n        <file>icons/octave/scalable/edit-copy.svg</file>\n        <file>icons/octave/scalable/edit-cut.svg</file>\n        <file>icons/octave/scalable/edit-find-replace.svg</file>\n        <file>icons/octave/scalable/edit-find.svg</file>\n        <file>icons/octave/scalable/edit-paste.svg</file>\n        <file>icons/octave/scalable/edit-redo.svg</file>\n        <file>icons/octave/scalable/edit-undo.svg</file>\n        <file>icons/octave/scalable/figure-axes.svg</file>\n        <file>icons/octave/scalable/figure-grid.svg</file>\n        <file>icons/octave/scalable/figure-pan.svg</file>\n        <file>icons/octave/scalable/figure-rotate.svg</file>\n        <file>icons/octave/scalable/figure-text.svg</file>\n        <file>icons/octave/scalable/figure-zoom-in.svg</file>\n        <file>icons/octave/scalable/figure-zoom-original.svg</file>\n        <file>icons/octave/scalable/figure-zoom-out.svg</file>\n        <file>icons/octave/scalable/folder.svg</file>\n        <file>icons/octave/scalable/folder-new.svg</file>\n        <file>icons/octave/scalable/folder-settings.svg</file>\n        <file>icons/octave/scalable/folder-up.svg</file>\n        <file>icons/octave/scalable/go-down.svg</file>\n        <file>icons/octave/scalable/go-first.svg</file>\n        <file>icons/octave/scalable/go-home.svg</file>\n        <file>icons/octave/scalable/go-last.svg</file>\n        <file>icons/octave/scalable/go-next.svg</file>\n        <file>icons/octave/scalable/go-previous.svg</file>\n        <file>icons/octave/scalable/go-up.svg</file>\n        <file>icons/octave/scalable/graphic_logo_FilesDockWidget.svg</file>\n        <file>icons/octave/scalable/graphic_logo_Figure.svg</file>\n        <file>icons/octave/scalable/graphic_logo_FileEditor.svg</file>\n        <file>icons/octave/scalable/graphic_logo_NewsDockWidget.svg</file>\n        <file>icons/octave/scalable/graphic_logo_TerminalDockWidget.svg</file>\n        <file>icons/octave/scalable/graphic_logo_HistoryDockWidget.svg</file>\n        <file>icons/octave/scalable/graphic_logo_WorkspaceView.svg</file>\n        <file>icons/octave/scalable/graphic_logo_DocumentationDockWidget.svg</file>\n        <file>icons/octave/scalable/graphic_logo_ReleaseWidget.svg</file>\n        <file>icons/octave/scalable/graphic_logo_VariableEditor.svg</file>\n        <file>icons/octave/scalable/letter_logo_FilesDockWidget.svg</file>\n        <file>icons/octave/scalable/letter_logo_FileEditor.svg</file>\n        <file>icons/octave/scalable/letter_logo_NewsDockWidget.svg</file>\n        <file>icons/octave/scalable/letter_logo_TerminalDockWidget.svg</file>\n        <file>icons/octave/scalable/letter_logo_HistoryDockWidget.svg</file>\n        <file>icons/octave/scalable/letter_logo_WorkspaceView.svg</file>\n        <file>icons/octave/scalable/letter_logo_DocumentationDockWidget.svg</file>\n        <file>icons/octave/scalable/letter_logo_ReleaseWidget.svg</file>\n        <file>icons/octave/scalable/letter_logo_VariableEditor.svg</file>\n        <file>icons/octave/scalable/logo.svg</file>\n        <file>icons/octave/scalable/plot-xy-curve.svg</file>\n        <file>icons/octave/scalable/system-run.svg</file>\n        <file>icons/octave/scalable/user-home.svg</file>\n        <file>icons/octave/scalable/view-zoom-in.svg</file>\n        <file>icons/octave/scalable/view-zoom-original.svg</file>\n        <file>icons/octave/scalable/view-zoom-out.svg</file>\n        <file>icons/octave/scalable/widget-close.svg</file>\n        <file>icons/octave/scalable/widget-dock.svg</file>\n        <file>icons/octave/scalable/widget-undock.svg</file>\n        <file>icons/octave/scalable/widget-close-light.svg</file>\n        <file>icons/octave/scalable/widget-dock-light.svg</file>\n        <file>icons/octave/scalable/widget-undock-light.svg</file>\n        <file>icons/octave/scalable/window-close.svg</file>\n        <file>icons/octave/index.theme</file>\n        <file>icons/tango/scalable/applications-system.svg</file>\n        <file>icons/tango/scalable/bookmark-new.svg</file>\n        <file>icons/tango/scalable/bp-toggle.svg</file>\n        <file>icons/tango/scalable/bp-rm-all.svg</file>\n        <file>icons/tango/scalable/bp-prev.svg</file>\n        <file>icons/tango/scalable/bp-next.svg</file>\n        <file>icons/tango/scalable/db-cont.svg</file>\n        <file>icons/tango/scalable/db-step.svg</file>\n        <file>icons/tango/scalable/db-step-in.svg</file>\n        <file>icons/tango/scalable/db-step-out.svg</file>\n        <file>icons/tango/scalable/db-stop.svg</file>\n        <file>icons/tango/scalable/dialog-error.svg</file>\n        <file>icons/tango/scalable/dialog-information.svg</file>\n        <file>icons/tango/scalable/dialog-warning.svg</file>\n        <file>icons/tango/scalable/document-new.svg</file>\n        <file>icons/tango/scalable/document-open.svg</file>\n        <file>icons/tango/scalable/document-print.svg</file>\n        <file>icons/tango/scalable/document-save.svg</file>\n        <file>icons/tango/scalable/document-save-as.svg</file>\n        <file>icons/tango/scalable/edit-copy.svg</file>\n        <file>icons/tango/scalable/edit-cut.svg</file>\n        <file>icons/tango/scalable/edit-delete.svg</file>\n        <file>icons/tango/scalable/edit-find.svg</file>\n        <file>icons/tango/scalable/edit-find-replace.svg</file>\n        <file>icons/tango/scalable/edit-paste.svg</file>\n        <file>icons/tango/scalable/edit-redo.svg</file>\n        <file>icons/tango/scalable/edit-undo.svg</file>\n        <file>icons/tango/scalable/folder.svg</file>\n        <file>icons/tango/scalable/folder-new.svg</file>\n        <file>icons/tango/scalable/go-down.svg</file>\n        <file>icons/tango/scalable/go-first.svg</file>\n        <file>icons/tango/scalable/go-home.svg</file>\n        <file>icons/tango/scalable/go-last.svg</file>\n        <file>icons/tango/scalable/go-next.svg</file>\n        <file>icons/tango/scalable/go-previous.svg</file>\n        <file>icons/tango/scalable/go-up.svg</file>\n        <file>icons/tango/scalable/preferences-system.svg</file>\n        <file>icons/tango/scalable/user-home.svg</file>\n        <file>icons/tango/scalable/view-refresh.svg</file>\n        <file>icons/tango/scalable/view-zoom-in.svg</file>\n        <file>icons/tango/scalable/view-zoom-original.svg</file>\n        <file>icons/tango/scalable/view-zoom-out.svg</file>\n        <file>icons/tango/index.theme</file>\n    </qresource>\n</RCC>\n"
  },
  {
    "path": "libgui/src/self-listener.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// self-listener: redirection of output streams\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n////////////////////////////////////////////////////////////////////////\n//\n// TODO:\n//    * We might want to filter output so that terminal escape sequences\n//      are processed (see the Unix version of the old terminal widget)\n//    * Maybe the self_listener could use a QString object instead\n//      of a character array + length buffer?\n//    * See also https://github.com/dmikushin/stdcapture and the stack\n//      overflow discussion linked there.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstring>\n\n// include headers for 'fd_set' type\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <winsock2.h>\n#else\n#  include <sys/select.h>\n#endif\n\n#include <QMessageBox>\n\n#include \"self-listener.h\"\n\n#include \"oct-syscalls.h\"\n#include \"select-wrappers.h\"\n\nself_listener::self_listener (const std::vector<int>& fds,\n                              const QString& caller,\n                              QObject *parent)\n  : QThread (parent),\n    m_caller (caller),\n    m_redir_streams ()\n{\n  m_num_fds = fds.size ();\n\n  // Get all fd that should be redirected\n  m_redir_streams.resize (m_num_fds);\n  for (int i = 0; i < m_num_fds; i++)\n    m_redir_streams.at (i).fd = fds.at (i);\n\n  int pipe_fd[2];\n\n  // Initialize all required data for redirection with pipes and select\n  for (auto& rs : m_redir_streams)\n    {\n      if (! (rs.stream = fdopen (rs.fd, \"wb\")))\n        {\n          error_msg (\n            QString (tr (\"Can not open redirected stream with fd = %1.\"))\n            .arg (rs.fd));\n          return;\n        }\n\n      // No buffering.\n      if (::setvbuf (rs.stream, nullptr, _IONBF, 0))\n        {\n          error_msg (\n            QString (tr (\"Can not disable buffering of stream with fd = %1.\"))\n            .arg (rs.fd));\n          return;\n        }\n\n      // m_old_fds should be used to restore the original output stream\n      // when the command widget and the self listener are destroyed.\n      rs.old_fd = ::dup (rs.fd);\n      if (rs.old_fd == -1)\n        {\n          error_msg (\n            QString (tr (\"Can not dup redirected stream with fd = %1.\"))\n            .arg (rs.fd));\n          return;\n        }\n\n      // Hook up the existing streams to a pipe that we can read from.\n      std::string error_str;\n      if (octave::sys::pipe (pipe_fd, error_str) < 0)\n        {\n          error_msg (\n            QString (tr (\"Cannot create pipe for redirecting stream with fd = %1:\"))\n            .arg (rs.fd), error_str);\n          return;\n        }\n      if (octave::sys::dup2 (pipe_fd[1], rs.fd, error_str) < 0)\n        {\n          error_msg (\n            QString (tr (\"Cannot dup2 redirected stream with fd = %1\\n\"\n                         \"to pipe with fd = %2: %3\"))\n            .arg (rs.fd).arg (pipe_fd[1]), error_str);\n          return;\n        }\n\n      rs.pipe_fd = pipe_fd[0];\n    }\n\n  // Make sure that the thread is deleted after usage\n  // but restores the streams before\n  connect (this, &self_listener::finished,\n           this, &self_listener::restore_streams);\n\n  connect (this, &self_listener::finished,\n           this, &self_listener::deleteLater);\n}\n\nself_listener::~self_listener (void)\n{\n  restore_streams ();\n}\n\nvoid self_listener::run ()\n{\n  // Initialize structure required by select\n  fd_set redir_fds;\n  octave_fd_zero (&redir_fds);\n\n  // Required variables\n  char buf[4096 + 1];\n  int len = 0;\n  int pipes_with_data;\n  bool running = true;\n\n  // Value of highest fd tracked by select (+1, see man select)\n  int fdmax = 0;\n  for (auto& rs : m_redir_streams)\n    fdmax = (rs.pipe_fd > fdmax) ? rs.pipe_fd : fdmax;\n  fdmax++;\n\n  // The main loop for tracking the pipes\n  while (running)\n    {\n      // Set the fds that should be scanned by select\n      for (auto& rs : m_redir_streams)\n        octave_fd_set (rs.pipe_fd, &redir_fds);\n\n      // Pipes with data ready for being read.  No timeout, wait\n      // until a file descriptor is ready.\n      pipes_with_data = octave_select (fdmax, &redir_fds, nullptr, nullptr, nullptr);\n\n      if (pipes_with_data == 0)\n        continue;  // timeout reached (not used here)\n\n      if (pipes_with_data < 0)\n        {\n          error_msg (QString (tr (\"Error while listening to redirected streams\")));\n          running = false;\n          continue;\n        }\n\n      for (auto& rs : m_redir_streams)\n        {\n          if (octave_fd_isset (rs.pipe_fd, &redir_fds))\n            {\n              if ((len = ::read (rs.pipe_fd, buf, 4096)) > 0)\n                {\n                  buf[len] = 0;  // Just in case.\n                  Q_EMIT receive_data (buf, len, rs.fd);\n                }\n              else if  (len < 0)\n                {\n                  error_msg (\n                    QString (tr (\"Error reading from redirected stream fd = %1.\"))\n                    .arg (rs.fd));\n                  running = false;\n                  break;\n                }\n            }\n        }\n\n    }\n}\n\nvoid\nself_listener::restore_streams (void)\n{\n  for (auto& rs : m_redir_streams)\n    octave::sys::dup2 (rs.old_fd, rs.fd);\n}\n\nvoid\nself_listener::error_msg (const QString& msg, const std::string& err_str)\n{\n  QString title = QString (\"Octave\");\n  QString info = QString ();\n\n  if (! m_caller.isEmpty ())\n    {\n      title = title + QString (\" \") + m_caller;\n      info = QString (tr (\"\\nOutput redirection in \")) +\n             m_caller + QString (tr (\" won't work.\"));\n    }\n\n  std::string err_msg = err_str;\n  if (err_msg.empty ())\n    err_msg = std::strerror (errno);\n\n  QString error_message = msg + info +\n                          QString (tr (\"\\nError: \")) +\n                          QString::fromStdString (err_msg);\n\n  QMessageBox msg_box (QMessageBox::Critical, QString (tr (\"Octave\")),\n                       error_message, QMessageBox::Ok);\n  msg_box.exec ();\n}\n"
  },
  {
    "path": "libgui/src/self-listener.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// self-listener: redirection of output streams\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_self_listener_h)\n#define octave_self_listener_h 1\n\n#include <QThread>\n#include <unistd.h>\n\nclass self_listener : public QThread\n{\n  Q_OBJECT\n\npublic:\n\n  explicit self_listener (const std::vector<int>& fds,\n                          const QString& caller = QString (),\n                          QObject *parent = nullptr);\n\n  ~self_listener (void);\n\nQ_SIGNALS:\n\n  void receive_data (const char *buf_stdout, int len_stdout, int fd);\n\npublic Q_SLOTS:\n\nprivate Q_SLOTS:\n\n  void restore_streams (void);\n\nprotected:\n\n  void run ();\n\nprivate:\n\n  void error_msg (const QString& msg, const std::string& err_str = std::string ());\n\n  QString m_caller;\n\n  struct redir_stream\n  {\n    FILE *stream;   // Stream to be redirected\n    int fd;         // File descriptor of stream\n    int old_fd;     // Store file descriptor for restore later\n    int pipe_fd;    // file descriptor of pipe used for redirection\n  };\n\n  std::vector<redir_stream> m_redir_streams;\n  int m_num_fds;\n};\n\n#endif\n"
  },
  {
    "path": "libgui/src/set-path-dialog.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QCheckBox>\n#include <QComboBox>\n#include <QDialogButtonBox>\n#include <QDirIterator>\n#include <QFileDialog>\n#include <QFileDialog>\n#include <QFileInfo>\n#include <QGridLayout>\n#include <QGroupBox>\n#include <QHBoxLayout>\n#include <QHeaderView>\n#include <QIcon>\n#include <QLabel>\n#include <QLineEdit>\n#include <QListView>\n#include <QMenu>\n#include <QPushButton>\n#include <QStatusBar>\n#include <QTextStream>\n#include <QTimer>\n#include <QVBoxLayout>\n\n#include \"gui-preferences-pd.h\"\n#include \"gui-settings.h\"\n#include \"set-path-dialog.h\"\n#include \"set-path-model.h\"\n\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nset_path_dialog::set_path_dialog (QWidget *parent)\n  : QDialog (parent)\n{\n  setWindowTitle (tr (\"Set Path\"));\n\n  set_path_model *model = new set_path_model (this);\n\n  m_info_label = new QLabel (tr (\"All changes take effect immediately.\"));\n\n  m_add_folder_button = new QPushButton (tr (\"Add Directory...\"));\n\n  QMenu *add_dir_menu = new QMenu ();\n  m_add_folder_button->setMenu (add_dir_menu);\n  add_dir_menu->addAction (tr (\"Single Directory\"),\n                           this, &set_path_dialog::add_dir);\n  add_dir_menu->addAction (tr (\"Directory With Subdirectories\"),\n                           this, &set_path_dialog::add_dir_subdirs);\n\n  m_move_to_top_button = new QPushButton (tr (\"Move to Top\"));\n  m_move_to_bottom_button = new QPushButton (tr (\"Move to Bottom\"));\n  m_move_up_button = new QPushButton (tr (\"Move Up\"));\n  m_move_down_button = new QPushButton (tr (\"Move Down\"));\n  m_remove_button = new QPushButton (tr (\"Remove\"));\n\n  m_reload_button = new QPushButton (tr (\"Reload\"));\n  m_save_button = new QPushButton (tr (\"Save\"));\n\n  m_revert_button = new QPushButton (tr (\"Revert\"));\n\n  QMenu *revert_menu = new QMenu ();\n  m_revert_button->setMenu (revert_menu);\n  revert_menu->addAction (tr (\"Revert Last Change\"),\n                          model, &set_path_model::revert_last);\n  revert_menu->addAction (tr (\"Revert All Changes\"),\n                          model, &set_path_model::revert);\n\n  m_save_button->setFocus ();\n\n  connect (m_remove_button, &QPushButton::clicked,\n           this, &set_path_dialog::rm_dir);\n\n  connect (m_move_to_top_button, &QPushButton::clicked,\n           this, &set_path_dialog::move_dir_top);\n\n  connect (m_move_to_bottom_button, &QPushButton::clicked,\n           this, &set_path_dialog::move_dir_bottom);\n\n  connect (m_move_up_button, &QPushButton::clicked,\n           this, &set_path_dialog::move_dir_up);\n\n  connect (m_move_down_button, &QPushButton::clicked,\n           this, &set_path_dialog::move_dir_down);\n\n  connect (m_reload_button, &QPushButton::clicked,\n           model, &set_path_model::path_to_model);\n\n  connect (m_save_button, &QPushButton::clicked,\n           model, &set_path_model::save);\n\n  // Any interpreter_event signal from a set_path_model object is\n  // handled the same as for the parent set_path_dialog object.\n\n  connect (model, qOverload<const fcn_callback&> (&set_path_model::interpreter_event),\n           this, qOverload<const fcn_callback&> (&set_path_dialog::interpreter_event));\n\n  connect (model, qOverload<const meth_callback&> (&set_path_model::interpreter_event),\n           this, qOverload<const meth_callback&> (&set_path_dialog::interpreter_event));\n\n  m_path_list = new QListView (this);\n  m_path_list->setWordWrap (false);\n  m_path_list->setModel (model);\n  m_path_list->setSelectionBehavior (QAbstractItemView::SelectRows);\n  m_path_list->setSelectionMode (QAbstractItemView::ExtendedSelection);\n  m_path_list->setAlternatingRowColors (true);\n  m_path_list->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);\n\n  // layout everything\n  QDialogButtonBox *button_box = new QDialogButtonBox (Qt::Horizontal);\n  button_box->addButton (m_save_button, QDialogButtonBox::ActionRole);\n  button_box->addButton (m_reload_button, QDialogButtonBox::ActionRole);\n\n  // add dialog close button\n  m_close_button = button_box->addButton (QDialogButtonBox::Close);\n  connect (button_box, &QDialogButtonBox::rejected,\n           this, &set_path_dialog::close);\n\n  button_box->addButton (m_revert_button, QDialogButtonBox::ActionRole);\n\n  // path edit options\n  QDialogButtonBox *path_edit_layout = new QDialogButtonBox (Qt::Vertical);\n  path_edit_layout->addButton (m_add_folder_button, QDialogButtonBox::ActionRole);\n  path_edit_layout->addButton (m_move_to_top_button, QDialogButtonBox::ActionRole);\n  path_edit_layout->addButton (m_move_up_button, QDialogButtonBox::ActionRole);\n  path_edit_layout->addButton (m_move_down_button, QDialogButtonBox::ActionRole);\n  path_edit_layout->addButton (m_move_to_bottom_button, QDialogButtonBox::ActionRole);\n  path_edit_layout->addButton (m_remove_button, QDialogButtonBox::ActionRole);\n\n  // main layout\n  QHBoxLayout *main_hboxlayout = new QHBoxLayout;\n  main_hboxlayout->addWidget (path_edit_layout);\n  main_hboxlayout->addWidget (m_path_list);\n\n  QGridLayout *main_layout = new QGridLayout;\n  main_layout->addWidget (m_info_label, 0, 0);\n  main_layout->addLayout (main_hboxlayout, 1, 0);\n  main_layout->addWidget (button_box, 2, 0);\n\n  setLayout (main_layout);\n\n  gui_settings settings;\n\n  restoreGeometry (settings.value (pd_geometry.settings_key ()).toByteArray ());\n}\n\nvoid\nset_path_dialog::update_model ()\n{\n  set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());\n  m->path_to_model ();\n}\n\nvoid\nset_path_dialog::add_dir_common (bool subdirs)\n{\n  QString dir\n    = QFileDialog::getExistingDirectory (this, tr (\"Open Directory\"),\n                                         \"\",\n                                         (QFileDialog::ShowDirsOnly\n                                          | QFileDialog::DontResolveSymlinks));\n\n  if (! dir.isEmpty ())\n    {\n      if (subdirs)\n        {\n          // Use existing method mofifying load path and updating dialog\n          // instead of adding string and updating load path\n          Q_EMIT modify_path_signal (QStringList (dir), false, true);\n        }\n      else\n        {\n          set_path_model *m\n            = static_cast<set_path_model *> (m_path_list->model ());\n          m->add_dir (dir);\n        }\n    }\n}\n\nvoid\nset_path_dialog::add_dir ()\n{\n  add_dir_common (false);\n}\n\nvoid\nset_path_dialog::add_dir_subdirs ()\n{\n  add_dir_common (true);\n}\n\nvoid\nset_path_dialog::rm_dir ()\n{\n  set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());\n  QItemSelectionModel *selmodel = m_path_list->selectionModel ();\n  QModelIndexList indexlist = selmodel->selectedIndexes ();\n  m->rm_dir (indexlist);\n\n  selmodel->clearSelection ();\n}\n\nvoid\nset_path_dialog::move_dir_up ()\n{\n  set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());\n  QItemSelectionModel *selmodel = m_path_list->selectionModel ();\n  QModelIndexList indexlist = selmodel->selectedIndexes ();\n  m->move_dir_up (indexlist);\n\n  // Update selection and view\n  selmodel->clearSelection ();\n  int min_row = m->rowCount () - 1;\n  for (int i = 0; i < indexlist.length (); i++)\n    {\n      int new_row = std::max (indexlist.at (i).row () - 1, 0);\n      min_row = std::min (min_row, new_row);\n      selmodel->select (m->index (new_row), QItemSelectionModel::Select);\n    }\n\n  m_path_list->scrollTo (m->index (min_row));\n}\n\nvoid\nset_path_dialog::move_dir_down ()\n{\n  set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());\n  QItemSelectionModel *selmodel = m_path_list->selectionModel ();\n  QModelIndexList indexlist = selmodel->selectedIndexes ();\n  m->move_dir_down (indexlist);\n\n  // Update selection and view\n  selmodel->clearSelection ();\n  int max_row = 0;\n  for (int i = 0; i < indexlist.length (); i++)\n    {\n      int new_row = std::min (indexlist.at (i).row () + 1, m->rowCount () - 1);\n      max_row = std::max (max_row, new_row);\n      selmodel->select (m->index (new_row), QItemSelectionModel::Select);\n    }\n\n  m_path_list->scrollTo (m->index (max_row));\n}\n\nvoid\nset_path_dialog::move_dir_top ()\n{\n  set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());\n  QItemSelectionModel *selmodel = m_path_list->selectionModel ();\n  QModelIndexList indexlist = selmodel->selectedIndexes ();\n  m->move_dir_top (indexlist);\n\n  // Update selection and view\n  selmodel->clearSelection ();\n  for (int i = 0; i < indexlist.length (); i++)\n    selmodel->select (m->index (i), QItemSelectionModel::Select);\n\n  m_path_list->scrollTo (m->index (0));\n}\n\nvoid\nset_path_dialog::move_dir_bottom ()\n{\n  set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());\n  QItemSelectionModel *selmodel = m_path_list->selectionModel ();\n  QModelIndexList indexlist = selmodel->selectedIndexes ();\n  m->move_dir_bottom (indexlist);\n\n  // Update selection and view\n  selmodel->clearSelection ();\n  int row_count = m->rowCount ();\n  for (int i = 0; i < indexlist.length (); i++)\n    selmodel->select (m->index (row_count - 1 - i),\n                      QItemSelectionModel::Select);\n\n  m_path_list->scrollTo (m->index (row_count - 1));\n}\n\nvoid\nset_path_dialog::save_settings ()\n{\n  gui_settings settings;\n\n  settings.setValue (pd_geometry.settings_key (), saveGeometry ());\n}\n\nvoid\nset_path_dialog::closeEvent (QCloseEvent *e)\n{\n  save_settings ();\n\n  QWidget::closeEvent (e);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/set-path-dialog.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n#if ! defined (octave_set_path_dialog_h)\n#define octave_set_path_dialog_h 1\n\n#include <QDialog>\n#include <QFileInfo>\n#include <QModelIndex>\n\n#include \"qt-interpreter-events.h\"\n\nclass octave_value_list;\n\nclass QLabel;\nclass QPushButton;\nclass QListView;\nclass QVBoxLayout;\nclass QHBoxLayout;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass set_path_dialog : public QDialog\n{\n  Q_OBJECT\n\npublic:\n\n  // You must call update_model to fully initialize the path displayed\n  // in the dialog.  That may only be done after the intepreter_event\n  // signal connections are made to the Octave interpreter.\n\n  set_path_dialog (QWidget *parent);\n\n  virtual ~set_path_dialog () = default;\n\n  void save_settings ();\n\nQ_SIGNALS:\n\n  //! Emitted, when the path has to be modified\n\n  void modify_path_signal (const QStringList& dir_list, bool rm,\n                           bool subdirs);\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  void update_model ();\n\nprotected:\n\n  void closeEvent (QCloseEvent *e);\n\nprivate Q_SLOTS:\n\n  void add_dir ();\n  void add_dir_subdirs ();\n\n  void rm_dir ();\n\n  void move_dir_up ();\n\n  void move_dir_down ();\n\n  void move_dir_top ();\n\n  void move_dir_bottom ();\n\nprivate:\n\n  void add_dir_common (bool subdirs);\n\n  QLabel *m_info_label;\n  QPushButton *m_reload_button;\n  QPushButton *m_save_button;\n  QPushButton *m_close_button;\n  QPushButton *m_revert_button;\n  QPushButton *m_revert_last_button;\n\n  QListView *m_path_list;\n\n  QPushButton *m_add_folder_button;\n  QPushButton *m_move_to_top_button;\n  QPushButton *m_move_to_bottom_button;\n  QPushButton *m_move_up_button;\n  QPushButton *m_move_down_button;\n  QPushButton *m_remove_button;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/set-path-model.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include <QFileIconProvider>\n#include <QMessageBox>\n#include <QPointer>\n#include <QtAlgorithms>\n\n#include \"qt-interpreter-events.h\"\n#include \"set-path-model.h\"\n\n#include \"pathsearch.h\"\n\n#include \"interpreter.h\"\n#include \"load-path.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nset_path_model::set_path_model (QObject *p)\n  : QAbstractListModel (p)\n{\n  connect (this, &set_path_model::update_data_signal,\n           this, &set_path_model::update_data);\n\n  m_revertible = false;\n}\n\nstd::string\nset_path_model::to_string ()\n{\n  std::string path_sep = directory_path::path_sep_str ();\n\n  std::string path_str;\n\n  QStringList::iterator it = m_dirs.begin ();\n\n  while (it < m_dirs.end ())\n    {\n      if (it != m_dirs.begin ())\n        path_str += path_sep;\n      path_str += it->toStdString ();\n      ++it;\n    }\n\n  return path_str;\n}\n\nvoid\nset_path_model::model_to_path ()\n{\n  std::string path_str = to_string ();\n\n  Q_EMIT interpreter_event\n    ([path_str] (interpreter& interp)\n    {\n      // INTERPRETER THREAD\n\n      load_path& lp = interp.get_load_path ();\n\n      lp.set (path_str);\n    });\n}\n\nvoid\nset_path_model::clear ()\n{\n  beginResetModel ();\n\n  m_dirs.clear ();\n\n  endResetModel ();\n}\n\nvoid\nset_path_model::save ()\n{\n  model_to_path ();\n\n  Q_EMIT interpreter_event\n    ([] (interpreter& interp)\n    {\n      // INTERPRETER THREAD\n\n      interp.feval (\"savepath\");\n    });\n}\n\nvoid\nset_path_model::revert ()\n{\n  clear ();\n\n  beginInsertRows (QModelIndex (), 0, m_orig_dirs.size () - 1);\n  m_dirs = m_orig_dirs;\n  endInsertRows ();\n\n  model_to_path ();\n}\n\nvoid\nset_path_model::revert_last ()\n{\n  clear ();\n\n  beginInsertRows (QModelIndex (), 0, m_last_dirs.size () - 1);\n  m_dirs = m_last_dirs;\n  endInsertRows ();\n\n  model_to_path ();\n}\n\nvoid\nset_path_model::add_dir (const QString& p)\n{\n  m_last_dirs = m_dirs;\n\n  beginInsertRows (QModelIndex (), m_dirs.size (), m_dirs.size ());\n\n  QList<QString>::Iterator it = m_dirs.begin ();\n\n  m_dirs.insert (it, p);\n\n  endInsertRows ();\n\n  model_to_path ();\n}\n\nvoid\nset_path_model::rm_dir (const QModelIndexList& indices)\n{\n  m_last_dirs = m_dirs;\n\n  for (int i = indices.size () - 1; i >= 0; i--)\n    {\n      const QModelIndex& idx = indices.at (i);\n\n      beginRemoveRows (idx, idx.row (), idx.row ());\n      m_dirs.removeAt (idx.row ());\n      endRemoveRows ();\n    }\n\n  model_to_path ();\n}\n\nvoid\nset_path_model::move_dir_up (const QModelIndexList& indices)\n{\n  m_last_dirs = m_dirs;\n\n  for (int i = 0; i < indices.size (); i++)\n    {\n      const QModelIndex& idx = indices.at (i);\n\n      if (idx.row () == 0 )\n        continue; //  already at top position\n\n      beginMoveRows (idx, idx.row (), idx.row (),\n                     this->index (idx.row () - 1), idx.row () - 1);\n\n      m_dirs.move (idx.row (), idx.row () - 1);\n\n      endMoveRows ();\n    }\n\n  model_to_path ();\n}\n\nvoid\nset_path_model::move_dir_down (const QModelIndexList& indices)\n{\n  m_last_dirs = m_dirs;\n\n  for (int i = indices.size () - 1; i >= 0; i--)\n    {\n      const QModelIndex& idx = indices.at (i);\n      int bottom = m_dirs.size () - 1;\n\n      if (idx.row () >= bottom)\n        continue; //  already at bottom position\n\n      beginMoveRows (idx, idx.row (), idx.row (),\n                     this->index (idx.row () + 1), idx.row () + 1);\n\n      m_dirs.move (idx.row (), idx.row () + 1);\n\n      endMoveRows ();\n    }\n\n  model_to_path ();\n}\n\nvoid\nset_path_model::move_dir_top (const QModelIndexList& indices)\n{\n  m_last_dirs = m_dirs;\n\n  for (int i = 0; i < indices.size (); i++)\n    {\n      const QModelIndex& idx = indices.at (i);\n\n      if (idx.row () == i)\n        continue; //  already at target position\n\n      beginMoveRows (idx, idx.row (), idx.row (), this->index (i), i);\n\n      m_dirs.move (idx.row (), i);\n\n      endMoveRows ();\n    }\n\n  model_to_path ();\n}\n\nvoid\nset_path_model::move_dir_bottom (const QModelIndexList& indices)\n{\n  m_last_dirs = m_dirs;\n\n  for (int i = 0; i < indices.size (); i++)\n    {\n      const QModelIndex& idx = indices.at (i);\n      int target = m_dirs.size () - 1 - i;\n\n      if (idx.row () == target)\n        continue; //  already at target position\n\n      beginMoveRows (idx, idx.row (), idx.row (),\n                     this->index (target), target);\n\n      m_dirs.move (idx.row (), target);\n\n      endMoveRows ();\n    }\n\n  model_to_path ();\n}\n\nint\nset_path_model::rowCount (const QModelIndex&) const\n{\n  return m_dirs.size ();\n}\n\nQVariant\nset_path_model::data (const QModelIndex& idx, int role) const\n{\n  QVariant retval;\n  if (idx.isValid ())\n    {\n      switch (role)\n        {\n        case Qt::DisplayRole:\n          retval = QVariant (m_dirs[idx.row ()]);\n          break;\n\n        case Qt::DecorationRole:\n          retval = QVariant (QIcon ());\n          break;\n\n        case Qt::SizeHintRole:\n          retval = QVariant (QSize (10, 20));\n          break;\n        }\n    }\n\n  return retval;\n}\n\nvoid\nset_path_model::path_to_model ()\n{\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<set_path_model> this_spm (this);\n\n  Q_EMIT interpreter_event\n    ([this, this_spm] (interpreter& interp)\n    {\n      // INTERPRETER THREAD\n\n      // We can skip the entire callback function because it does not\n      // make any changes to the interpreter state.\n\n      if (this_spm.isNull ())\n        return;\n\n      load_path& lp = interp.get_load_path ();\n\n      std::list<std::string> dir_list = lp.dir_list ();\n\n      QStringList qs_dir_list;\n\n      for (const auto& dir : dir_list)\n        qs_dir_list << QString::fromStdString (dir);\n\n      Q_EMIT update_data_signal (qs_dir_list);\n    });\n\n  m_revertible = false;\n}\n\nvoid\nset_path_model::update_data (const QStringList& dirs)\n{\n  m_dirs = dirs;\n\n  m_dirs.removeAll (\".\");\n\n  if (! m_revertible)\n    {\n      // first time update\n      m_orig_dirs = m_dirs;\n      m_last_dirs = m_dirs;\n\n      m_revertible = true;\n    }\n\n  int numel = m_dirs.size ();\n\n  Q_EMIT dataChanged (QAbstractListModel::index (0, 0),\n                      QAbstractListModel::index (numel-1, 0));\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/set-path-model.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_set_path_model_h)\n#define octave_set_path_model_h 1\n\n#include <QAbstractListModel>\n#include <QFileInfo>\n#include <QIcon>\n#include <QList>\n#include <QStringList>\n\n#include \"qt-interpreter-events.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass set_path_model : public QAbstractListModel\n{\n  Q_OBJECT\n\npublic:\n\n  set_path_model (QObject *p = nullptr);\n\n  ~set_path_model () = default;\n\n  void clear ();\n\n  void add_dir (const QString& p);\n\n  void rm_dir (const QModelIndexList& indices);\n\n  void move_dir_up (const QModelIndexList& indices);\n\n  void move_dir_down (const QModelIndexList& indices);\n\n  void move_dir_top (const QModelIndexList& indices);\n\n  void move_dir_bottom (const QModelIndexList& indices);\n\n  std::string to_string ();\n\n  // Overloaded Qt methods\n\n  void model_to_path ();\n\n  int rowCount (const QModelIndex& p = QModelIndex ()) const;\n\n  QVariant data (const QModelIndex& idx, int role) const;\n\nQ_SIGNALS:\n\n  void update_data_signal (const QStringList& dirs);\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  void path_to_model ();\n\n  void save ();\n\n  void revert ();\n\n  void revert_last ();\n\nprivate Q_SLOTS:\n\n  void update_data (const QStringList& dirs);\n\nprivate:\n\n  QStringList m_dirs;\n\n  QStringList m_orig_dirs;\n\n  QStringList m_last_dirs;\n\n  bool m_revertible;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/settings-dialog.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Programming Note: this file has many lines longer than 80 characters\n// due to long function, variable, and property names.  Please don't\n// break those lines as it tends to make this code even harder to read.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QButtonGroup>\n#include <QDir>\n#include <QFileDialog>\n#include <QFileInfo>\n#include <QHash>\n#include <QMessageBox>\n#include <QScrollBar>\n#include <QStyleFactory>\n#include <QThread>\n#include <QVector>\n\n#if defined (HAVE_QSCINTILLA)\n#  include <Qsci/qscilexer.h>\n\n#  include \"octave-qscintilla.h\"\n#  include \"octave-txt-lexer.h\"\n#  include <QScrollArea>\n\n#  if defined (HAVE_QSCI_QSCILEXEROCTAVE_H)\n#    define HAVE_LEXER_OCTAVE 1\n#    include <Qsci/qscilexeroctave.h>\n#  elif defined (HAVE_QSCI_QSCILEXERMATLAB_H)\n#    define HAVE_LEXER_MATLAB 1\n#    include <Qsci/qscilexermatlab.h>\n#  endif\n\n#  include <Qsci/qscilexercpp.h>\n#  include <Qsci/qscilexerjava.h>\n#  include <Qsci/qscilexerbash.h>\n#  include <Qsci/qscilexerperl.h>\n#  include <Qsci/qscilexerbatch.h>\n#  include <Qsci/qscilexerdiff.h>\n#endif\n\n#include \"gui-preferences-all.h\"\n#include \"gui-settings.h\"\n#include \"settings-dialog.h\"\n#include \"shortcuts-tree-widget.h\"\n#include \"variable-editor.h\"\n#include \"workspace-model.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nsettings_dialog::settings_dialog (QWidget *p, const QString& desired_tab)\n  : QDialog (p), Ui::settings_dialog ()\n{\n  setupUi (this);\n\n  QMessageBox *info = wait_message_box (\n                        tr (\"Loading current preferences ... \"), this);\n\n  read_settings (true);  // it's the first read, prepare everything\n\n  close_wait_message_box (info);\n\n  // which tab is the desired one?\n  show_tab (desired_tab);\n\n  // connect button box signal\n  connect (button_box, &QDialogButtonBox::clicked,\n           this, &settings_dialog::button_clicked);\n\n  // restore last geometry\n  gui_settings settings;\n\n  if (settings.contains (sd_geometry.settings_key ()))\n    restoreGeometry (settings.byte_array_value (sd_geometry));\n  else\n    setGeometry (QRect (10, 50, 1000, 600));\n\n  // show as non-modal dialog\n  setModal (false);\n  setAttribute (Qt::WA_DeleteOnClose);\n  show ();\n}\n\nvoid\nsettings_dialog::read_settings (bool first)\n{\n  gui_settings settings;\n\n  if (first)\n    {\n      // look for available language files and the actual settings\n      QString qm_dir_name = settings.get_gui_translation_dir ();\n\n      QDir qm_dir (qm_dir_name);\n      QFileInfoList qm_files = qm_dir.entryInfoList (QStringList (\"*.qm\"),\n                               QDir::Files | QDir::Readable, QDir::Name);\n\n      for (int i = 0; i < qm_files.length (); i++)   // insert available languages\n        comboBox_language->addItem (qm_files.at (i).baseName ());\n      // System at beginning\n      comboBox_language->insertItem (0, tr (\"System setting\"));\n      comboBox_language->insertSeparator (1);    // separator after System\n    }\n\n  QString language = settings.string_value (global_language);\n  if (language == global_language.def ().toString ())\n    language = tr (\"System setting\");\n  int selected = comboBox_language->findText (language);\n  if (selected >= 0)\n    comboBox_language->setCurrentIndex (selected);\n  else\n    comboBox_language->setCurrentIndex (0);  // System is default\n\n  if (first)\n    {\n      // Global style\n      QStringList styles = QStyleFactory::keys ();\n      styles.append (global_extra_styles);\n      combo_styles->addItems (styles);\n      combo_styles->insertItem (0, global_style.def ().toString ());\n      combo_styles->insertSeparator (1);\n    }\n\n  QString current_style = settings.string_value (global_style);\n  if (current_style == global_style.def ().toString ())\n    current_style = global_style.def ().toString ();\n  selected = combo_styles->findText (current_style);\n  if (selected >= 0)\n    combo_styles->setCurrentIndex (selected);\n  else\n    combo_styles->setCurrentIndex (0);\n\n  if (first)\n    {\n      // icon size and theme\n      QButtonGroup *icon_size_group = new QButtonGroup (this);\n      icon_size_group->addButton (icon_size_small);\n      icon_size_group->addButton (icon_size_normal);\n      icon_size_group->addButton (icon_size_large);\n    }\n  int icon_size = settings.int_value (global_icon_size);\n  icon_size_normal->setChecked (true);  // the default\n  icon_size_small->setChecked (icon_size < 0);\n  icon_size_large->setChecked (icon_size > 0);\n\n  if (first)\n    combo_box_icon_theme->addItems (global_all_icon_theme_names);\n  int theme = settings.value (global_icon_theme_index.settings_key ()).toInt ();\n  combo_box_icon_theme->setCurrentIndex (theme);\n\n  if (first)\n    {\n      // which icon has to be selected\n      QButtonGroup *icon_group = new QButtonGroup (this);\n      icon_group->addButton (general_icon_octave);\n      icon_group->addButton (general_icon_graphic);\n      icon_group->addButton (general_icon_letter);\n    }\n  QString widget_icon_set =\n    settings.string_value (dw_icon_set);\n  general_icon_octave->setChecked (true);  // the default (if invalid set)\n  general_icon_octave->setChecked (widget_icon_set == \"NONE\");\n  general_icon_graphic->setChecked (widget_icon_set == \"GRAPHIC\");\n  general_icon_letter->setChecked (widget_icon_set == \"LETTER\");\n\n  if (first)\n    {\n      // custom title bar of dock widget\n      m_widget_title_bg_color = new color_picker ();\n      m_widget_title_bg_color->setEnabled (false);\n      layout_widget_bgtitle->addWidget (m_widget_title_bg_color, 0);\n\n      connect (cb_widget_custom_style, &QCheckBox::toggled,\n               m_widget_title_bg_color, &color_picker::setEnabled);\n\n      m_widget_title_bg_color_active = new color_picker ();\n      m_widget_title_bg_color_active->setEnabled (false);\n      layout_widget_bgtitle_active->addWidget (m_widget_title_bg_color_active, 0);\n\n      connect (cb_widget_custom_style, &QCheckBox::toggled,\n               m_widget_title_bg_color_active, &color_picker::setEnabled);\n\n      m_widget_title_fg_color = new color_picker ();\n      m_widget_title_fg_color->setEnabled (false);\n      layout_widget_fgtitle->addWidget (m_widget_title_fg_color, 0);\n\n      connect (cb_widget_custom_style, &QCheckBox::toggled,\n               m_widget_title_fg_color, &color_picker::setEnabled);\n\n      m_widget_title_fg_color_active = new color_picker ();\n      m_widget_title_fg_color_active->setEnabled (false);\n      layout_widget_fgtitle_active->addWidget (m_widget_title_fg_color_active, 0);\n\n      connect (cb_widget_custom_style, &QCheckBox::toggled,\n               m_widget_title_fg_color_active, &color_picker::setEnabled);\n    }\n\n  m_widget_title_bg_color->set_color (settings.color_value (dw_title_bg_color));\n  m_widget_title_bg_color_active->set_color (settings.color_value (dw_title_bg_color_active));\n  m_widget_title_fg_color->set_color (settings.color_value (dw_title_fg_color));\n  m_widget_title_fg_color_active->set_color (settings.color_value (dw_title_fg_color_active));\n\n  sb_3d_title->setValue (settings.int_value (dw_title_3d));\n  cb_widget_custom_style->setChecked (settings.bool_value (dw_title_custom_style));\n\n  // Native file dialogs.\n  // FIXME: This preference can be deprecated / removed if all display\n  //       managers, especially KDE, run those dialogs without hangs or\n  //       delays from the start (bug #54607).\n  cb_use_native_file_dialogs->setChecked (settings.bool_value (global_use_native_dialogs));\n\n  // Cursor blinking: consider old terminal related setting if not yet set\n  // FIXME: This pref. can be deprecated / removed if Qt adds support for\n  //       getting the cursor blink preferences from all OS environments\n  if (settings.contains (global_cursor_blinking.settings_key ()))\n    {\n      // Preference exists, read its value\n      cb_cursor_blinking->setChecked (settings.bool_value (global_cursor_blinking));\n    }\n  else\n    {\n      // Pref. does not exist, so take old terminal related pref.\n      cb_cursor_blinking->setChecked (settings.bool_value (cs_cursor_blinking));\n    }\n\n  // focus follows mouse\n  cb_focus_follows_mouse->setChecked (settings.bool_value (dw_focus_follows_mouse));\n\n  // prompt on exit\n  cb_prompt_to_exit->setChecked (settings.bool_value (global_prompt_to_exit));\n\n  // show splash screen\n  cb_show_splash_screen->setChecked (settings.bool_value (global_show_splash_screen));\n\n  // Main status bar\n  cb_status_bar->setChecked (settings.bool_value (global_status_bar));\n\n  // Octave startup\n  cb_restore_octave_dir->setChecked (settings.bool_value (global_restore_ov_dir));\n  le_octave_dir->setText (settings.string_value (global_ov_startup_dir));\n\n  if (first)\n    connect (pb_octave_dir, &QPushButton::pressed,\n             this, &settings_dialog::get_octave_dir);\n\n  //\n  // editor\n  //\n  useCustomFileEditor->setChecked (settings.bool_value (global_use_custom_editor));\n  customFileEditor->setText (settings.string_value (global_custom_editor));\n  editor_showLineNumbers->setChecked (settings.bool_value (ed_show_line_numbers));\n  editor_linenr_size->setValue (settings.int_value (ed_line_numbers_size));\n\n  settings.combo_encoding (editor_combo_encoding);\n\n  editor_highlightCurrentLine->setChecked (settings.bool_value (ed_highlight_current_line));\n  editor_long_line_marker->setChecked (settings.bool_value (ed_long_line_marker));\n  bool long_line =\n    settings.bool_value (ed_long_line_marker_line);\n  editor_long_line_marker_line->setChecked (long_line);\n  bool long_back =\n    settings.bool_value (ed_long_line_marker_background);\n  editor_long_line_marker_background->setChecked (long_back);\n  if (! (long_line || long_back))\n    editor_long_line_marker_line->setChecked (true);\n  editor_long_line_column->setValue (settings.int_value (ed_long_line_column));\n  editor_break_checkbox->setChecked (settings.bool_value (ed_break_lines));\n  editor_break_comments_checkbox->setChecked (settings.bool_value (ed_break_lines_comments));\n  editor_wrap_checkbox->setChecked (settings.bool_value (ed_wrap_lines));\n  cb_edit_status_bar->setChecked (settings.bool_value (ed_show_edit_status_bar));\n  cb_edit_tool_bar->setChecked (settings.bool_value (ed_show_toolbar));\n  cb_code_folding->setChecked (settings.bool_value (ed_code_folding));\n  editor_highlight_all_occurrences->setChecked (settings.bool_value (ed_highlight_all_occurrences));\n\n  editor_auto_endif->setCurrentIndex (settings.int_value (ed_auto_endif) );\n  editor_codeCompletion->setChecked (settings.bool_value (ed_code_completion));\n  editor_spinbox_ac_threshold->setValue (settings.int_value (ed_code_completion_threshold));\n  editor_checkbox_ac_keywords->setChecked (settings.bool_value (ed_code_completion_keywords));\n  editor_checkbox_ac_builtins->setEnabled (editor_checkbox_ac_keywords->isChecked ());\n  editor_checkbox_ac_functions->setEnabled (editor_checkbox_ac_keywords->isChecked ());\n  editor_checkbox_ac_builtins->setChecked (settings.bool_value (ed_code_completion_octave_builtins));\n  editor_checkbox_ac_functions->setChecked (settings.bool_value (ed_code_completion_octave_functions));\n  editor_checkbox_ac_document->setChecked (settings.bool_value (ed_code_completion_document));\n  editor_checkbox_ac_case->setChecked (settings.bool_value (ed_code_completion_case));\n  editor_checkbox_ac_replace->setChecked (settings.bool_value (ed_code_completion_replace));\n  editor_ws_checkbox->setChecked (settings.bool_value (ed_show_white_space));\n  editor_ws_indent_checkbox->setChecked (settings.bool_value (ed_show_white_space_indent));\n  cb_show_eol->setChecked (settings.bool_value (ed_show_eol_chars));\n  cb_show_hscrollbar->setChecked (settings.bool_value (ed_show_hscroll_bar));\n\n  if (first)\n    {\n      for (int i = 0; i < ed_tab_position_names.length (); i++)\n        editor_combox_tab_pos->insertItem (i,\n                tr (ed_tab_position_names.at (i).toStdString ().data ()));\n    }\n  editor_combox_tab_pos->setCurrentIndex (settings.int_value (ed_tab_position));\n\n  editor_cb_tabs_rotated->setChecked (settings.bool_value (ed_tabs_rotated));\n  editor_sb_tabs_max_width->setValue (settings.int_value (ed_tabs_max_width));\n\n  int selected_comment_string, selected_uncomment_string;\n\n  if (settings.contains (ed_comment_str.settings_key ()))   // new version (radio buttons)\n    selected_comment_string = settings.int_value (ed_comment_str);\n  else                                         // old version (combo box)\n    selected_comment_string = settings.value (ed_comment_str_old.settings_key (),                                                 ed_comment_str.def ()).toInt ();\n\n  selected_uncomment_string = settings.int_value (ed_uncomment_str);\n\n  for (int i = 0; i < ed_comment_strings_count; i++)\n    {\n      if (first)\n        {\n          m_rb_comment_strings[i] = new QRadioButton ();\n          m_rb_uncomment_strings[i] = new QCheckBox ();\n          layout_comment_strings->addWidget (m_rb_comment_strings[i]);\n          layout_uncomment_strings->addWidget (m_rb_uncomment_strings[i]);\n\n          connect (m_rb_comment_strings[i], &QRadioButton::clicked,\n                   m_rb_uncomment_strings[i], &QCheckBox::setChecked);\n          connect (m_rb_comment_strings[i], &QRadioButton::toggled,\n                   m_rb_uncomment_strings[i], &QCheckBox::setDisabled);\n        }\n\n      m_rb_comment_strings[i]->setText (ed_comment_strings.at (i));\n      m_rb_comment_strings[i]->setChecked (i == selected_comment_string);\n\n      m_rb_uncomment_strings[i]->setText (ed_comment_strings.at (i));\n      m_rb_uncomment_strings[i]->setAutoExclusive (false);\n      m_rb_uncomment_strings[i]->setChecked ( 1 << i & selected_uncomment_string);\n    }\n\n  combo_eol_mode->setCurrentIndex (settings.int_value (ed_default_eol_mode));\n  editor_auto_ind_checkbox->setChecked (settings.bool_value (ed_auto_indent));\n  editor_tab_ind_checkbox->setChecked (settings.bool_value (ed_tab_indents_line));\n  editor_bs_unind_checkbox->setChecked (settings.bool_value (ed_backspace_unindents_line));\n  editor_ind_guides_checkbox->setChecked (settings.bool_value (ed_show_indent_guides));\n  editor_ind_width_spinbox->setValue (settings.int_value (ed_indent_width));\n  editor_ind_uses_tabs_checkbox->setChecked (settings.bool_value (ed_indent_uses_tabs));\n  editor_tab_width_spinbox->setValue (settings.int_value (ed_tab_width));\n  editor_restoreSession->setChecked (settings.bool_value (ed_restore_session));\n  editor_create_new_file->setChecked (settings.bool_value (ed_create_new_file));\n  editor_reload_changed_files->setChecked (settings.bool_value (ed_always_reload_changed_files));\n  editor_open_dlg_follows_file->setChecked (settings.bool_value (ed_open_dlg_follows_file));\n  editor_force_newline->setChecked (settings.bool_value (ed_force_newline));\n  editor_remove_trailing_spaces->setChecked (settings.bool_value (ed_rm_trailing_spaces));\n  editor_hiding_closes_files->setChecked (settings.bool_value (ed_hiding_closes_files));\n  editor_show_dbg_file->setChecked (settings.bool_value (ed_show_dbg_file));\n\n  // terminal\n  QString default_font = settings.string_value (global_mono_font);\n  terminal_fontName->setCurrentFont (QFont (settings.value (cs_font.settings_key (), default_font).toString ()));\n  terminal_fontSize->setValue (settings.int_value (cs_font_size));\n  terminal_history_buffer->setValue (settings.int_value (cs_hist_buffer));\n  terminal_cursorUseForegroundColor->setChecked (settings.bool_value (cs_cursor_use_fgcol));\n  terminal_focus_command->setChecked (settings.bool_value (cs_focus_cmd));\n  terminal_print_dbg_location->setChecked (settings.bool_value (cs_dbg_location));\n\n  QString cursor_type = settings.string_value (cs_cursor);\n\n  QStringList items;\n  items << QString (\"0\") << QString (\"1\") << QString (\"2\");\n  terminal_cursorType->addItems (items);\n  terminal_cursorType->setItemText (0, tr (\"IBeam Cursor\"));\n  terminal_cursorType->setItemText (1, tr (\"Block Cursor\"));\n  terminal_cursorType->setItemText (2, tr (\"Underline Cursor\"));\n\n  for (unsigned int i = 0; i < cs_cursor_types.size (); i++)\n    {\n      if (cursor_type.toStdString () == cs_cursor_types[i])\n        {\n          terminal_cursorType->setCurrentIndex (i);\n          break;\n        }\n    }\n\n  if (first)\n    read_terminal_colors ();\n  else\n    {\n      QCheckBox *cb_color_mode\n        = terminal_colors_box->findChild<QCheckBox *> (cs_color_mode.settings_key ());\n      bool sec_color_mode = settings.bool_value (cs_color_mode);\n      if (cb_color_mode->isChecked () == sec_color_mode)\n        {\n          // color mode does not change, update colors manually\n          update_terminal_colors ();\n        }\n      else\n        {\n          // toggling check-state calls related slot updating colors\n          cb_color_mode->setChecked (sec_color_mode);\n        }\n    }\n\n  // file browser\n  if (first)\n    {\n      connect (sync_octave_directory, &QCheckBox::toggled,\n               this, &settings_dialog::set_disabled_pref_file_browser_dir);\n      connect (pb_file_browser_dir, &QPushButton::pressed,\n               this, &settings_dialog::get_file_browser_dir);\n    }\n\n  sync_octave_directory->setChecked (settings.bool_value (fb_sync_octdir));\n  cb_restore_file_browser_dir->setChecked (settings.bool_value (fb_restore_last_dir));\n  le_file_browser_dir->setText (settings.value (fb_startup_dir.settings_key ()).toString ());\n  le_file_browser_extensions->setText (settings.string_value (fb_txt_file_ext));\n  checkbox_allow_web_connect->setChecked (settings.bool_value (nr_allow_connection));\n\n  // Proxy\n  bool use_proxy = settings.bool_value (global_use_proxy);\n  use_proxy_server->setChecked (use_proxy);\n  // Fill combo box and activate current one\n  if (first)\n    {\n      proxy_type->addItems (global_proxy_all_types);\n      // Connect relevant signals for dis-/enabling some elements\n      connect (proxy_type, qOverload<int> (&QComboBox::currentIndexChanged),\n               this, &settings_dialog::proxy_items_update);\n      connect (use_proxy_server, &QCheckBox::toggled,\n               this, &settings_dialog::proxy_items_update);\n    }\n  QString proxy_type_string = settings.string_value (global_proxy_type);\n  for (int i = 0; i < global_proxy_all_types.length (); i++)\n    {\n      if (proxy_type->itemText (i) == proxy_type_string)\n        {\n          proxy_type->setCurrentIndex (i);\n          break;\n        }\n    }\n  // Fill all line edits\n  proxy_host_name->setText (settings.string_value (global_proxy_host));\n  proxy_port->setText (settings.string_value (global_proxy_port));\n  proxy_username->setText (settings.string_value (global_proxy_user));\n  proxy_password->setText (settings.string_value (global_proxy_pass));\n  // Check whehter line edits have to be enabled\n  proxy_items_update ();\n\n  // Workspace\n  if (first)\n    read_workspace_colors ();\n  else\n    {\n      m_ws_enable_colors->setChecked (settings.bool_value (ws_enable_colors));\n      QCheckBox *cb_color_mode\n        = workspace_colors_box->findChild<QCheckBox *> (ws_color_mode.settings_key ());\n      bool sec_color_mode = settings.bool_value (ws_color_mode);\n      if (cb_color_mode->isChecked () == sec_color_mode)\n        {\n          // color mode does not change, update colors manually\n          update_workspace_colors ();\n        }\n      else\n        {\n          // toggling check-state calls related slot updating colors\n          cb_color_mode->setChecked (sec_color_mode);\n        }\n    }\n\n  // variable editor\n  if (first)\n    {\n      connect (varedit_useTerminalFont, &QCheckBox::toggled,\n               varedit_font, &QFontComboBox::setDisabled);\n      connect (varedit_useTerminalFont, &QCheckBox::toggled,\n               varedit_fontSize, &QSpinBox::setDisabled);\n    }\n  varedit_columnWidth->setValue (settings.int_value (ve_column_width));\n  varedit_rowHeight->setValue (settings.int_value (ve_row_height));\n  varedit_font->setCurrentFont (QFont (settings.value (ve_font_name.settings_key (),\n                                       settings.value (cs_font.settings_key (), default_font)).toString ()));\n  varedit_fontSize->setValue (settings.int_value (ve_font_size));\n  varedit_useTerminalFont->setChecked (settings.bool_value (ve_use_terminal_font));\n  varedit_font->setDisabled (varedit_useTerminalFont->isChecked ());\n  varedit_fontSize->setDisabled (varedit_useTerminalFont->isChecked ());\n  varedit_alternate->setChecked (settings.bool_value (ve_alternate_rows));\n\n  // variable editor colors\n  if (first)\n    read_varedit_colors ();\n  else\n    {\n      QCheckBox *cb_color_mode\n        = varedit_colors_box->findChild<QCheckBox *> (ve_color_mode.settings_key ());\n      bool sec_color_mode = settings.bool_value (ve_color_mode);\n      if (cb_color_mode->isChecked () == sec_color_mode)\n        {\n          // color mode does not change, update colors manually\n          update_varedit_colors ();\n        }\n      else\n        {\n          // toggling check-state calls related slot updating colors\n          cb_color_mode->setChecked (sec_color_mode);\n        }\n    }\n\n  // shortcuts\n\n  cb_prevent_readline_conflicts->setChecked (settings.bool_value (sc_prevent_rl_conflicts));\n  cb_prevent_readline_conflicts_menu->setChecked (settings.bool_value (sc_prevent_rl_conflicts_menu));\n\n  // connect the buttons for import/export of the shortcut sets\n  // FIXME: Should there also be a button to discard changes?\n\n  if (first)\n    {\n      connect (btn_import_shortcut_set, &QPushButton::clicked,\n               this, &settings_dialog::import_shortcut_set);\n\n      connect (btn_export_shortcut_set, &QPushButton::clicked,\n               this, &settings_dialog::export_shortcut_set);\n\n      connect (btn_default_shortcut_set, &QPushButton::clicked,\n               this, &settings_dialog::default_shortcut_set);\n    }\n\n#if defined (HAVE_QSCINTILLA)\n\n  if (first)\n    {\n      int mode = settings.int_value (ed_color_mode);\n\n      QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()),\n                                                group_box_editor_styles);\n      cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ()));\n      cb_color_mode->setChecked (mode > 0);\n      cb_color_mode->setObjectName (ed_color_mode.settings_key ());\n\n      QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_styles.toStdString ().data ()));\n      pb_reload_default_colors->setToolTip (tr (settings_reload_styles_tooltip.toStdString ().data ()));\n\n      color_picker *current_line_color = new color_picker (\n        settings.value (ed_highlight_current_line_color.settings_key ()\n                        + settings_color_modes_ext[mode],\n                        ed_highlight_current_line_color.def ()).value<QColor> ());\n      current_line_color->setObjectName (ed_highlight_current_line_color.settings_key ());\n\n      QLabel *current_line_color_label\n        = new QLabel (tr(\"Color of highlighted current line (magenta (255,0,255) for automatic color)\"));\n\n      QHBoxLayout *color_mode = new QHBoxLayout ();\n      color_mode->addWidget (cb_color_mode);\n      color_mode->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding));\n      color_mode->addWidget (pb_reload_default_colors);\n\n      QHBoxLayout *current_line = new QHBoxLayout ();\n      current_line->addWidget (current_line_color_label);\n      current_line->addWidget (current_line_color);\n      current_line->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding));\n\n      editor_styles_layout->addLayout (color_mode);\n      editor_styles_layout->addLayout (current_line);\n\n      // update colors depending on second theme selection\n      connect (cb_color_mode,\n#if defined (HAVE_QCHECKBOX_CHECKSTATECHANGED)\n               &QCheckBox::checkStateChanged,\n#else\n               &QCheckBox::stateChanged,\n#endif\n               this, &settings_dialog::update_editor_lexers);\n      connect (pb_reload_default_colors, &QPushButton::clicked,\n               [this] () { update_editor_lexers (settings_reload_default_colors_flag); });\n\n      // finally read the lexer colors using the update slot\n      update_editor_lexers ();\n    }\n  else\n    {\n      QCheckBox *cb_color_mode\n        = group_box_editor_styles->findChild<QCheckBox *> (ed_color_mode.settings_key ());\n      bool sec_color_mode = settings.bool_value (ed_color_mode);\n      if (cb_color_mode->isChecked () == sec_color_mode)\n        {\n          // color mode does not change, update colors manually\n          update_editor_lexers ();\n        }\n      else\n        {\n          // toggling check-state calls related slot updating colors\n          cb_color_mode->setChecked (sec_color_mode);\n        }\n    }\n\n#endif\n}\n\nvoid\nsettings_dialog::show_tab (const QString& tab)\n{\n  gui_settings settings;\n\n  if (tab.isEmpty ())\n    tabWidget->setCurrentIndex (settings.int_value (sd_last_tab));\n  else\n    {\n      QHash<QString, QWidget *> tab_hash;\n      tab_hash[\"editor\"] = tab_editor;\n      tab_hash[\"editor_styles\"] = tab_editor;\n      tabWidget->setCurrentIndex (tabWidget->indexOf (tab_hash.value (tab)));\n      if (tab == \"editor_styles\")\n        tab_editor_scroll_area->ensureWidgetVisible (group_box_editor_styles);\n    }\n}\n\nvoid\nsettings_dialog::get_octave_dir ()\n{\n  get_dir (le_octave_dir, tr (\"Set Octave Startup Directory\"));\n}\n\nvoid\nsettings_dialog::get_file_browser_dir ()\n{\n  get_dir (le_file_browser_dir, tr (\"Set File Browser Startup Directory\"));\n}\n\nvoid\nsettings_dialog::get_dir (QLineEdit *line_edit, const QString& title)\n{\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n  int opts = QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks;\n\n  gui_settings settings;\n\n  if (! settings.bool_value (global_use_native_dialogs))\n    opts |= QFileDialog::DontUseNativeDialog;\n\n  QString dir = QFileDialog::getExistingDirectory\n    (this, title, line_edit->text (), QFileDialog::Option (opts));\n\n  line_edit->setText (dir);\n}\n\nvoid\nsettings_dialog::button_clicked (QAbstractButton *button)\n{\n  QDialogButtonBox::ButtonRole button_role = button_box->buttonRole (button);\n\n  if (button_role == QDialogButtonBox::ApplyRole\n      || button_role == QDialogButtonBox::AcceptRole)\n    {\n      write_changed_settings ();\n      if (button_role == QDialogButtonBox::AcceptRole)\n        hide ();  // already hide here, reloading settings takes some time\n\n      QMessageBox *info = wait_message_box (tr (\"Applying preferences ... \"), this);\n      Q_EMIT apply_new_settings ();\n      close_wait_message_box (info);\n    }\n\n  if (button_role == QDialogButtonBox::RejectRole\n      || button_role == QDialogButtonBox::AcceptRole)\n    {\n      // save last settings dialog's geometry and close\n\n      gui_settings settings;\n\n      settings.setValue (sd_last_tab.settings_key (), tabWidget->currentIndex ());\n      settings.setValue (sd_geometry.settings_key (), saveGeometry ());\n      settings.sync ();\n\n      close ();\n    }\n\n  if (button_role == QDialogButtonBox::ResetRole)\n    {\n      read_settings (false);  // not the first read, only update existing items\n    }\n}\n\nvoid\nsettings_dialog::set_disabled_pref_file_browser_dir (bool disable)\n{\n  cb_restore_file_browser_dir->setDisabled (disable);\n\n  if (! disable)\n    {\n      le_file_browser_dir->setDisabled (cb_restore_file_browser_dir->isChecked ());\n      pb_file_browser_dir->setDisabled (cb_restore_file_browser_dir->isChecked ());\n    }\n  else\n    {\n      le_file_browser_dir->setDisabled (disable);\n      pb_file_browser_dir->setDisabled (disable);\n    }\n}\n\n// slot for updating enabled state of proxy settings\nvoid\nsettings_dialog::proxy_items_update ()\n{\n  bool use_proxy = use_proxy_server->isChecked ();\n\n  bool manual = false;\n  for (int i = 0; i < global_proxy_manual_types.length (); i++)\n    {\n      if (proxy_type->currentIndex () == global_proxy_manual_types.at (i))\n        {\n          manual = true;\n          break;\n        }\n    }\n\n  proxy_type->setEnabled (use_proxy);\n  proxy_host_name_label->setEnabled (use_proxy && manual);\n  proxy_host_name->setEnabled (use_proxy && manual);\n  proxy_port_label->setEnabled (use_proxy && manual);\n  proxy_port->setEnabled (use_proxy && manual);\n  proxy_username_label->setEnabled (use_proxy && manual);\n  proxy_username->setEnabled (use_proxy && manual);\n  proxy_password_label->setEnabled (use_proxy && manual);\n  proxy_password->setEnabled (use_proxy && manual);\n}\n\n// slots for import/export of shortcut sets\n\n// Prompt for file name and import shortcuts from it.  Importing will\n// change values in tree view but does not apply values to\n// gui_settings_object so that the user may choose to apply or cancel\n// the action.\n\nvoid\nsettings_dialog::import_shortcut_set ()\n{\n  if (! overwrite_all_shortcuts ())\n    return;\n\n  QString file = get_shortcuts_file_name (OSC_IMPORT);\n\n  gui_settings osc_settings (file, QSettings::IniFormat);\n\n  if (osc_settings.status () ==  QSettings::NoError)\n    shortcuts_treewidget->import_shortcuts (osc_settings);\n  else\n    qWarning () << (tr (\"Failed to open %1 as Octave shortcut file\")\n                    .arg (file));\n}\n\n// Prompt for file name and export shortcuts to it.\n\n// FIXME: Should exported settings values come from the gui_settings\n// object or the tree view?  If modified values in the tree view have\n// not been applied, should we offer to apply them first?  Offer a\n// choice to save current application settings or the modified values\n// in the dialog?\n\nvoid\nsettings_dialog::export_shortcut_set ()\n{\n  QString file = get_shortcuts_file_name (OSC_EXPORT);\n\n  gui_settings osc_settings (file, QSettings::IniFormat);\n\n  if (osc_settings.status () ==  QSettings::NoError)\n    shortcuts_treewidget->export_shortcuts (osc_settings);\n  else\n    qWarning () << (tr (\"Failed to open %1 as Octave shortcut file\")\n                    .arg (file));\n}\n\n// Reset the tree view to default values.  Does not apply values to\n// gui_settings object so that the user may choose to apply or cancel\n// the action.\n\nvoid\nsettings_dialog::default_shortcut_set ()\n{\n  if (! overwrite_all_shortcuts ())\n    return;\n\n  shortcuts_treewidget->set_default_shortcuts ();\n}\n\nvoid\nsettings_dialog::update_editor_lexers (int def)\n{\n#if defined (HAVE_QSCINTILLA)\n\n  QCheckBox *cb_color_mode\n    = group_box_editor_styles->findChild<QCheckBox *> (ed_color_mode.settings_key ());\n\n  int m = 0;\n  if (cb_color_mode && cb_color_mode->isChecked ())\n    m = 1;\n\n  color_picker *c_picker = findChild<color_picker *> (ed_highlight_current_line_color.settings_key ());\n  if (c_picker)\n    {\n      gui_settings settings;\n\n      if (def != settings_reload_default_colors_flag)\n        {\n          // Get current value from settings or the default\n          c_picker->set_color (settings.color_value (ed_highlight_current_line_color, m));\n        }\n      else\n        {\n          // Get the default value\n          c_picker->set_color (settings.get_color_value (ed_highlight_current_line_color.def (), m));\n        }\n    }\n\n  // editor styles: create lexer, read settings, and\n  // create or update dialog elements\n  QsciLexer *lexer;\n\n#  if defined (HAVE_LEXER_OCTAVE)\n  lexer = new QsciLexerOctave ();\n  update_lexer (lexer, m, def);\n  delete lexer;\n#  elif defined (HAVE_LEXER_MATLAB)\n  lexer = new QsciLexerMatlab ();\n  update_lexer (lexer, m, def);\n  delete lexer;\n#  endif\n\n  lexer = new QsciLexerCPP ();\n  update_lexer (lexer, m, def);\n  delete lexer;\n\n  lexer = new QsciLexerJava ();\n  update_lexer (lexer, m, def);\n  delete lexer;\n\n  lexer = new QsciLexerPerl ();\n  update_lexer (lexer, m, def);\n  delete lexer;\n\n  lexer = new QsciLexerBatch ();\n  update_lexer (lexer, m, def);\n  delete lexer;\n\n  lexer = new QsciLexerDiff ();\n  update_lexer (lexer, m, def);\n  delete lexer;\n\n  lexer = new QsciLexerBash ();\n  update_lexer (lexer, m, def);\n  delete lexer;\n\n  lexer = new octave_txt_lexer ();\n  update_lexer (lexer, m, def);\n  delete lexer;\n\n#else\n\n  octave_unused_parameter (def);\n\n#endif\n}\n\n\nvoid\nsettings_dialog::update_lexer (QsciLexer *lexer, int mode, int def)\n{\n#if defined (HAVE_QSCINTILLA)\n  // Get lexer settings and copy from default settings if not yet\n  // available in normal settings file\n  gui_settings settings;\n  settings.read_lexer_settings (lexer, mode, def);\n\n  // When reloading default styles, the style tabs do already exists.\n  // Otherwise, check if they exist or not.\n  QString lexer_name = lexer->language ();\n\n  int index = -1;\n  for (int i = 0; i < tabs_editor_lexers->count (); i++)\n    {\n      if (tabs_editor_lexers->tabText (i) == lexer_name)\n        {\n          index = i;\n          break;\n        }\n    }\n\n  if (index == -1)\n    {\n      // This is not an update, call get_lexer_settings for building\n      // the settings tab\n      get_lexer_settings (lexer);\n      return;\n    }\n\n  // Update the styles elements in all styles\n  int styles[ed_max_lexer_styles];  // array for saving valid styles\n  int max_style = settings.get_valid_lexer_styles (lexer, styles);\n  QWidget *tab = tabs_editor_lexers->widget (index);\n  int default_size = 0;\n  QString default_family;\n\n  for (int i = 0; i < max_style; i++)  // create dialog elements for all styles\n    {\n      QString actual_name = lexer->description (styles[i]);\n      color_picker *bg_color\n        = tab->findChild<color_picker *> (actual_name + \"_bg_color\");\n      if (bg_color)\n        {\n          // Update\n          if (styles[i] == 0)\n            bg_color->set_color (lexer->defaultPaper ());\n          else\n            {\n              if (lexer->paper (styles[i]) == lexer->defaultPaper ())\n                bg_color->set_color (settings_color_no_change);\n              else\n                bg_color->set_color (lexer->paper (styles[i]));\n            }\n        }\n\n      color_picker *color = tab->findChild<color_picker *> (actual_name + \"_color\");\n      if (color)\n        color->set_color (lexer->color (styles[i]));\n\n      QFont font = lexer->font (styles[i]);\n\n      QCheckBox *cb = tab->findChild<QCheckBox *> (actual_name + \"_bold\");\n      if (cb)\n        cb->setChecked (font.bold ());\n      cb = tab->findChild<QCheckBox *> (actual_name + \"_italic\");\n      if (cb)\n        cb->setChecked (font.italic ());\n      cb = tab->findChild<QCheckBox *> (actual_name + \"_underline\");\n      if (cb)\n        cb->setChecked (font.underline ());\n\n      QFontComboBox *fcb = tab->findChild<QFontComboBox *> (actual_name + \"_font\");\n      if (fcb)\n        {\n          if (styles[i] == 0)\n            {\n              default_family = font.family ();\n              fcb->setEditText (default_family);\n            }\n          else\n            {\n              if (font.family () == default_family)\n                fcb->setEditText (lexer->description (0));\n              else\n                fcb->setEditText (font.family ());\n            }\n        }\n      QSpinBox *fs = tab->findChild<QSpinBox *> (actual_name + \"_size\");\n      if (fs)\n        {\n          if (styles[i] == 0)\n            {\n              default_size = font.pointSize ();\n              fs->setValue (default_size);\n            }\n          else\n            fs->setValue (font.pointSize () - default_size);\n        }\n    }\n\n#else\n  octave_unused_parameter (lexer);\n  octave_unused_parameter (mode);\n  octave_unused_parameter (def);\n\n  return;\n#endif\n}\n\nvoid\nsettings_dialog::get_lexer_settings (QsciLexer *lexer)\n{\n#if defined (HAVE_QSCINTILLA)\n  gui_settings settings;\n\n  int styles[ed_max_lexer_styles];  // array for saving valid styles\n                                    // (enum is not continuous)\n  int max_style = settings.get_valid_lexer_styles (lexer, styles);\n  QGridLayout *style_grid = new QGridLayout ();\n  QVector<QLabel *> description (max_style);\n  QVector<QFontComboBox *> select_font (max_style);\n  QVector<QSpinBox *> font_size (max_style);\n  QVector<QCheckBox *> attrib_font (3 * max_style);\n  QVector<color_picker *> color (max_style);\n  QVector<color_picker *> bg_color (max_style);\n  int default_size = 10;\n  QFont default_font = QFont ();\n  int label_width;\n  QColor default_color = QColor ();\n\n  for (int i = 0; i < max_style; i++)  // create dialog elements for all styles\n    {\n      QString actual_name = lexer->description (styles[i]);\n      QFont   actual_font = lexer->font (styles[i]);\n      description[i] = new QLabel (actual_name);\n      description[i]->setWordWrap (true);\n      label_width = 24*description[i]->fontMetrics ().averageCharWidth ();\n      description[i]->setMaximumSize (label_width, QWIDGETSIZE_MAX);\n      description[i]->setMinimumSize (label_width, 1);\n      select_font[i] = new QFontComboBox ();\n      select_font[i]->setObjectName (actual_name + \"_font\");\n      select_font[i]->setMaximumSize (label_width, QWIDGETSIZE_MAX);\n      select_font[i]->setMinimumSize (label_width, 1);\n      select_font[i]->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);\n      font_size[i] = new QSpinBox ();\n      font_size[i]->setObjectName (actual_name + \"_size\");\n      if (styles[i] == 0) // the default\n        {\n          select_font[i]->setCurrentFont (actual_font);\n          default_font = actual_font;\n          font_size[i]->setRange (6, 24);\n          default_size = actual_font.pointSize ();\n          font_size[i]->setValue (default_size);\n          default_color = lexer->defaultPaper ();\n          bg_color[i] = new color_picker (default_color);\n        }\n      else   // other styles\n        {\n          select_font[i]->setCurrentFont (actual_font);\n          if (actual_font.family () == default_font.family ())\n            select_font[i]->setEditText (lexer->description (0));\n          font_size[i]->setRange (-4, 4);\n          font_size[i]->setValue (actual_font.pointSize ()-default_size);\n          font_size[i]->setToolTip (QObject::tr (\"Difference to the default size\"));\n          if (lexer->paper (styles[i]) == default_color)\n            bg_color[i] = new color_picker (settings_color_no_change);\n          else\n            bg_color[i] = new color_picker (lexer->paper (styles[i]));\n          bg_color[i]->setToolTip\n            (QObject::tr (\"Background color, magenta (255, 0, 255) means default\"));\n        }\n      attrib_font[0+3*i] = new QCheckBox (QObject::tr (\"b\", \"short form for bold\"));\n      attrib_font[1+3*i] = new QCheckBox (QObject::tr (\"i\", \"short form for italic\"));\n      attrib_font[2+3*i] = new QCheckBox (QObject::tr (\"u\", \"short form for underlined\"));\n      attrib_font[0+3*i]->setChecked (actual_font.bold ());\n      attrib_font[0+3*i]->setObjectName (actual_name + \"_bold\");\n      attrib_font[1+3*i]->setChecked (actual_font.italic ());\n      attrib_font[1+3*i]->setObjectName (actual_name + \"_italic\");\n      attrib_font[2+3*i]->setChecked (actual_font.underline ());\n      attrib_font[2+3*i]->setObjectName (actual_name + \"_underline\");\n      color[i] = new color_picker (lexer->color (styles[i]));\n      color[i]->setObjectName (actual_name + \"_color\");\n      bg_color[i]->setObjectName (actual_name + \"_bg_color\");\n      int column = 1;\n      style_grid->addWidget (description[i], i, column++);\n      style_grid->addWidget (select_font[i], i, column++);\n      style_grid->addWidget (font_size[i], i, column++);\n      style_grid->addWidget (attrib_font[0+3*i], i, column++);\n      style_grid->addWidget (attrib_font[1+3*i], i, column++);\n      style_grid->addWidget (attrib_font[2+3*i], i, column++);\n      style_grid->addWidget (color[i], i, column++);\n      style_grid->addWidget (bg_color[i], i, column++);\n    }\n\n  // place grid with elements into the tab\n  QScrollArea *scroll_area = new QScrollArea ();\n  QWidget *scroll_area_contents = new QWidget ();\n  scroll_area_contents->setObjectName (QString (lexer->language ()) + \"_styles\");\n  scroll_area_contents->setLayout (style_grid);\n  scroll_area->setWidget (scroll_area_contents);\n  tabs_editor_lexers->addTab (scroll_area, lexer->language ());\n\n  tabs_editor_lexers->setCurrentIndex (settings.int_value (sd_last_editor_styles_tab));\n\n#else\n  octave_unused_parameter (lexer);\n\n  return;\n#endif\n}\n\nvoid\nsettings_dialog::write_lexer_settings (QsciLexer *lexer)\n{\n#if defined (HAVE_QSCINTILLA)\n  gui_settings settings;\n\n  QCheckBox *cb_color_mode\n    = group_box_editor_styles->findChild<QCheckBox *> (ed_color_mode.settings_key ());\n  int mode = 0;\n  if (cb_color_mode && cb_color_mode->isChecked ())\n    mode = 1;\n\n  settings.setValue (ed_color_mode.settings_key (), mode);\n\n  QWidget *tab = tabs_editor_lexers->\n    findChild<QWidget *> (QString (lexer->language ()) + \"_styles\");\n  int styles[ed_max_lexer_styles];  // array for saving valid styles\n                                    // (enum is not continuous)\n\n  int max_style = settings.get_valid_lexer_styles (lexer, styles);\n\n  QFontComboBox *select_font;\n  QSpinBox *font_size;\n  QCheckBox *attrib_font[3];\n  color_picker *color;\n  color_picker *bg_color;\n  int default_size = 10;\n\n  color = findChild<color_picker *> (ed_highlight_current_line_color.settings_key ());\n  if (color)\n    settings.setValue (ed_highlight_current_line_color.settings_key ()\n                       + settings_color_modes_ext[mode], color->color ());\n\n  QString default_font_name\n    = settings.string_value (global_mono_font);\n  QFont default_font = QFont (default_font_name, 10, -1, 0);\n  QColor default_color = QColor ();\n\n  for (int i = 0; i < max_style; i++)  // get dialog elements and their contents\n    {\n      QString actual_name = lexer->description (styles[i]);\n      select_font = tab->findChild<QFontComboBox *> (actual_name + \"_font\");\n      font_size = tab->findChild<QSpinBox *> (actual_name + \"_size\");\n      attrib_font[0] = tab->findChild<QCheckBox *> (actual_name + \"_bold\");\n      attrib_font[1] = tab->findChild<QCheckBox *> (actual_name + \"_italic\");\n      attrib_font[2] = tab->findChild<QCheckBox *> (actual_name + \"_underline\");\n      color = tab->findChild<color_picker *> (actual_name + \"_color\");\n      bg_color = tab->findChild<color_picker *> (actual_name + \"_bg_color\");\n      QFont new_font = default_font;\n      if (select_font)\n        {\n          new_font = select_font->currentFont ();\n          if (styles[i] == 0)\n            default_font = new_font;\n          else if (select_font->currentText () == lexer->description (0))\n            new_font = default_font;\n        }\n      if (font_size)\n        {\n          if (styles[i] == 0)\n            {\n              default_size = font_size->value ();\n              new_font.setPointSize (font_size->value ());\n            }\n          else\n            new_font.setPointSize (font_size->value ()+default_size);\n        }\n      if (attrib_font[0])\n        new_font.setBold (attrib_font[0]->isChecked ());\n      if (attrib_font[1])\n        new_font.setItalic (attrib_font[1]->isChecked ());\n      if (attrib_font[2])\n        new_font.setUnderline (attrib_font[2]->isChecked ());\n      lexer->setFont (new_font, styles[i]);\n      if (styles[i] == 0)\n        lexer->setDefaultFont (new_font);\n      if (color)\n        lexer->setColor (color->color (), styles[i]);\n      if (bg_color)\n        {\n          if (styles[i] == 0)\n            {\n              default_color = bg_color->color ();\n              lexer->setPaper (default_color, styles[i]);\n              lexer->setDefaultPaper (default_color);\n            }\n          else\n            {\n              if (bg_color->color () == settings_color_no_change)\n                lexer->setPaper (default_color, styles[i]);\n              else\n                lexer->setPaper (bg_color->color (), styles[i]);\n            }\n        }\n    }\n\n  const std::string group =\n    QString (\"Scintilla\" + settings_color_modes_ext[mode]).toStdString ();\n\n  lexer->writeSettings (settings, group.c_str ());\n\n  settings.setValue (sd_last_editor_styles_tab.settings_key (),\n                     tabs_editor_lexers->currentIndex ());\n  settings.sync ();\n\n#else\n  octave_unused_parameter (lexer);\n\n  return;\n#endif\n}\n\nvoid\nsettings_dialog::write_changed_settings ()\n{\n\n  gui_settings settings;\n\n  // the icon set\n  QString widget_icon_set = \"NONE\";\n  if (general_icon_letter->isChecked ())\n    widget_icon_set = \"LETTER\";\n  else if (general_icon_graphic->isChecked ())\n    widget_icon_set = \"GRAPHIC\";\n  settings.setValue (dw_icon_set.settings_key (), widget_icon_set);\n\n  // language\n  QString language = comboBox_language->currentText ();\n  if (language == tr (\"System setting\"))\n    language = global_language.def ().toString ();\n  settings.setValue (global_language.settings_key (), language);\n\n  // style\n  QString selected_style = combo_styles->currentText ();\n  if (selected_style == global_style.def ().toString ())\n    selected_style = global_style.def ().toString ();\n  settings.setValue (global_style.settings_key (), selected_style);\n\n  // dock widget title bar\n  settings.setValue (dw_title_custom_style.settings_key (), cb_widget_custom_style->isChecked ());\n  settings.setValue (dw_title_3d.settings_key (), sb_3d_title->value ());\n  settings.setValue (dw_title_bg_color.settings_key (), m_widget_title_bg_color->color ());\n  settings.setValue (dw_title_bg_color_active.settings_key (), m_widget_title_bg_color_active->color ());\n  settings.setValue (dw_title_fg_color.settings_key (), m_widget_title_fg_color->color ());\n  settings.setValue (dw_title_fg_color_active.settings_key (), m_widget_title_fg_color_active->color ());\n\n  // icon size and theme\n  int icon_size = icon_size_large->isChecked () - icon_size_small->isChecked ();\n  settings.setValue (global_icon_size.settings_key (), icon_size);\n  settings.setValue (global_icon_theme_index.settings_key (), combo_box_icon_theme->currentIndex ());\n\n  // native file dialogs\n  settings.setValue (global_use_native_dialogs.settings_key (), cb_use_native_file_dialogs->isChecked ());\n\n  // cursor blinking\n  settings.setValue (global_cursor_blinking.settings_key (), cb_cursor_blinking->isChecked ());\n\n  // focus follows mouse\n  settings.setValue (dw_focus_follows_mouse.settings_key (), cb_focus_follows_mouse->isChecked ());\n\n  // promp to exit\n  settings.setValue (global_prompt_to_exit.settings_key (), cb_prompt_to_exit->isChecked ());\n\n  // show splash screen\n  settings.setValue (global_show_splash_screen.settings_key (), cb_show_splash_screen->isChecked ());\n\n  // status bar\n  settings.setValue (global_status_bar.settings_key (), cb_status_bar->isChecked ());\n\n  // Octave startup\n  settings.setValue (global_restore_ov_dir.settings_key (), cb_restore_octave_dir->isChecked ());\n  settings.setValue (global_ov_startup_dir.settings_key (), le_octave_dir->text ());\n\n  //editor\n  settings.setValue (global_use_custom_editor.settings_key (), useCustomFileEditor->isChecked ());\n  settings.setValue (global_custom_editor.settings_key (), customFileEditor->text ());\n  settings.setValue (ed_show_line_numbers.settings_key (), editor_showLineNumbers->isChecked ());\n  settings.setValue (ed_line_numbers_size.settings_key (), editor_linenr_size->value ());\n  settings.setValue (ed_highlight_current_line.settings_key (), editor_highlightCurrentLine->isChecked ());\n  settings.setValue (ed_long_line_marker.settings_key (), editor_long_line_marker->isChecked ());\n  settings.setValue (ed_long_line_marker_line.settings_key (), editor_long_line_marker_line->isChecked ());\n  settings.setValue (ed_long_line_marker_background.settings_key (), editor_long_line_marker_background->isChecked ());\n  settings.setValue (ed_long_line_column.settings_key (), editor_long_line_column->value ());\n  settings.setValue (ed_break_lines.settings_key (), editor_break_checkbox->isChecked ());\n  settings.setValue (ed_break_lines_comments.settings_key (), editor_break_comments_checkbox->isChecked ());\n  settings.setValue (ed_wrap_lines.settings_key (), editor_wrap_checkbox->isChecked ());\n  settings.setValue (ed_code_folding.settings_key (), cb_code_folding->isChecked ());\n  settings.setValue (ed_show_edit_status_bar.settings_key (), cb_edit_status_bar->isChecked ());\n  settings.setValue (ed_show_toolbar.settings_key (), cb_edit_tool_bar->isChecked ());\n  settings.setValue (ed_highlight_all_occurrences.settings_key (), editor_highlight_all_occurrences->isChecked ());\n  settings.setValue (ed_code_completion.settings_key (), editor_codeCompletion->isChecked ());\n  settings.setValue (ed_code_completion_threshold.settings_key (), editor_spinbox_ac_threshold->value ());\n  settings.setValue (ed_code_completion_keywords.settings_key (), editor_checkbox_ac_keywords->isChecked ());\n  settings.setValue (ed_code_completion_octave_builtins.settings_key (), editor_checkbox_ac_builtins->isChecked ());\n  settings.setValue (ed_code_completion_octave_functions.settings_key (), editor_checkbox_ac_functions->isChecked ());\n  settings.setValue (ed_code_completion_document.settings_key (), editor_checkbox_ac_document->isChecked ());\n  settings.setValue (ed_code_completion_case.settings_key (), editor_checkbox_ac_case->isChecked ());\n  settings.setValue (ed_code_completion_replace.settings_key (), editor_checkbox_ac_replace->isChecked ());\n  settings.setValue (ed_auto_endif.settings_key (), editor_auto_endif->currentIndex ());\n  settings.setValue (ed_show_white_space.settings_key (), editor_ws_checkbox->isChecked ());\n  settings.setValue (ed_show_white_space_indent.settings_key (), editor_ws_indent_checkbox->isChecked ());\n  settings.setValue (ed_show_eol_chars.settings_key (), cb_show_eol->isChecked ());\n  settings.setValue (ed_show_hscroll_bar.settings_key (), cb_show_hscrollbar->isChecked ());\n  settings.setValue (ed_default_eol_mode.settings_key (), combo_eol_mode->currentIndex ());\n\n  settings.setValue (ed_tab_position.settings_key (), editor_combox_tab_pos->currentIndex ());\n  settings.setValue (ed_tabs_rotated.settings_key (), editor_cb_tabs_rotated->isChecked ());\n  settings.setValue (ed_tabs_max_width.settings_key (), editor_sb_tabs_max_width->value ());\n\n  // Comment strings\n  int rb_uncomment = 0;\n  for (int i = 0; i < ed_comment_strings_count; i++)\n    {\n      if (m_rb_comment_strings[i]->isChecked ())\n        {\n          settings.setValue (ed_comment_str.settings_key (), i);\n          if (i < 3)\n            settings.setValue (ed_comment_str_old.settings_key (), i);\n          else\n            settings.setValue (ed_comment_str_old.settings_key (), ed_comment_str.def ());\n        }\n      if (m_rb_uncomment_strings[i]->isChecked ())\n        rb_uncomment = rb_uncomment + (1 << i);\n    }\n  settings.setValue (ed_uncomment_str.settings_key (), rb_uncomment);\n\n  settings.setValue (ed_default_enc.settings_key (), editor_combo_encoding->currentText ());\n  settings.setValue (ed_auto_indent.settings_key (), editor_auto_ind_checkbox->isChecked ());\n  settings.setValue (ed_tab_indents_line.settings_key (), editor_tab_ind_checkbox->isChecked ());\n  settings.setValue (ed_backspace_unindents_line.settings_key (), editor_bs_unind_checkbox->isChecked ());\n  settings.setValue (ed_show_indent_guides.settings_key (), editor_ind_guides_checkbox->isChecked ());\n  settings.setValue (ed_indent_width.settings_key (), editor_ind_width_spinbox->value ());\n  settings.setValue (ed_indent_uses_tabs.settings_key (), editor_ind_uses_tabs_checkbox->isChecked ());\n  settings.setValue (ed_tab_width.settings_key (), editor_tab_width_spinbox->value ());\n  settings.setValue (ed_restore_session.settings_key (), editor_restoreSession->isChecked ());\n  settings.setValue (ed_create_new_file.settings_key (), editor_create_new_file->isChecked ());\n  settings.setValue (ed_hiding_closes_files.settings_key (), editor_hiding_closes_files->isChecked ());\n  settings.setValue (ed_always_reload_changed_files.settings_key (), editor_reload_changed_files->isChecked ());\n  settings.setValue (ed_open_dlg_follows_file.settings_key (), editor_open_dlg_follows_file->isChecked ());\n  settings.setValue (ed_force_newline.settings_key (), editor_force_newline->isChecked ());\n  settings.setValue (ed_rm_trailing_spaces.settings_key (), editor_remove_trailing_spaces->isChecked ());\n  settings.setValue (ed_show_dbg_file.settings_key (), editor_show_dbg_file->isChecked ());\n\n  // file browser\n  settings.setValue (fb_sync_octdir.settings_key (), sync_octave_directory->isChecked ());\n  settings.setValue (fb_restore_last_dir.settings_key (), cb_restore_file_browser_dir->isChecked ());\n  settings.setValue (fb_startup_dir.settings_key (), le_file_browser_dir->text ());\n  settings.setValue (fb_txt_file_ext.settings_key (), le_file_browser_extensions->text ());\n\n  // network\n  settings.setValue (nr_allow_connection.settings_key (), checkbox_allow_web_connect->isChecked ());\n  settings.setValue (global_use_proxy.settings_key (), use_proxy_server->isChecked ());\n  settings.setValue (global_proxy_type.settings_key (), proxy_type->currentText ());\n  settings.setValue (global_proxy_host.settings_key (), proxy_host_name->text ());\n  settings.setValue (global_proxy_port.settings_key (), proxy_port->text ());\n  settings.setValue (global_proxy_user.settings_key (), proxy_username->text ());\n  settings.setValue (global_proxy_pass.settings_key (), proxy_password->text ());\n\n  // command window\n  settings.setValue (cs_font_size.settings_key (), terminal_fontSize->value ());\n  settings.setValue (cs_font.settings_key (), terminal_fontName->currentFont ().family ());\n  settings.setValue (cs_cursor_use_fgcol.settings_key (), terminal_cursorUseForegroundColor->isChecked ());\n  settings.setValue (cs_focus_cmd.settings_key (), terminal_focus_command->isChecked ());\n  settings.setValue (cs_dbg_location.settings_key (), terminal_print_dbg_location->isChecked ());\n  settings.setValue (cs_hist_buffer.settings_key (), terminal_history_buffer->value ());\n  write_terminal_colors ();\n\n  // the cursor\n  QString cursor_type;\n  unsigned int cursor_int = terminal_cursorType->currentIndex ();\n  if ((cursor_int > 0) && (cursor_int < cs_cursor_types.size ()))\n    cursor_type = QString (cs_cursor_types[cursor_int].data ());\n  else\n    cursor_type = cs_cursor.def ().toString ();\n\n  settings.setValue (cs_cursor.settings_key (), cursor_type);\n\n#if defined (HAVE_QSCINTILLA)\n  // editor styles: create lexer, get dialog contents, and write settings\n  QsciLexer *lexer;\n\n#if defined (HAVE_LEXER_OCTAVE)\n\n  lexer = new QsciLexerOctave ();\n  write_lexer_settings (lexer);\n  delete lexer;\n\n#elif defined (HAVE_LEXER_MATLAB)\n\n  lexer = new QsciLexerMatlab ();\n  write_lexer_settings (lexer);\n  delete lexer;\n\n#endif\n\n  lexer = new QsciLexerCPP ();\n  write_lexer_settings (lexer);\n  delete lexer;\n\n  lexer = new QsciLexerJava ();\n  write_lexer_settings (lexer);\n  delete lexer;\n\n  lexer = new QsciLexerPerl ();\n  write_lexer_settings (lexer);\n  delete lexer;\n\n  lexer = new QsciLexerBatch ();\n  write_lexer_settings (lexer);\n  delete lexer;\n\n  lexer = new QsciLexerDiff ();\n  write_lexer_settings (lexer);\n  delete lexer;\n\n  lexer = new QsciLexerBash ();\n  write_lexer_settings (lexer);\n  delete lexer;\n\n  lexer = new octave_txt_lexer ();\n  write_lexer_settings (lexer);\n  delete lexer;\n\n#endif\n\n  // Workspace\n  write_workspace_colors ();\n\n  // Variable editor\n  settings.setValue (ve_column_width.settings_key (), varedit_columnWidth->value ());\n  settings.setValue (ve_row_height.settings_key (), varedit_rowHeight->value ());\n  settings.setValue (ve_use_terminal_font.settings_key (), varedit_useTerminalFont->isChecked ());\n  settings.setValue (ve_alternate_rows.settings_key (), varedit_alternate->isChecked ());\n  settings.setValue (ve_font_name.settings_key (), varedit_font->currentFont ().family ());\n  settings.setValue (ve_font_size.settings_key (), varedit_fontSize->value ());\n  write_varedit_colors ();\n\n  // shortcuts\n\n  settings.setValue (sc_prevent_rl_conflicts.settings_key (), cb_prevent_readline_conflicts->isChecked ());\n  settings.setValue (sc_prevent_rl_conflicts_menu.settings_key (), cb_prevent_readline_conflicts_menu->isChecked ());\n\n  shortcuts_treewidget->write_settings ();\n\n  settings.sync ();\n}\n\nvoid\nsettings_dialog::read_workspace_colors ()\n{\n  gui_settings settings;\n\n  // Construct the grid with all color related settings\n  QGridLayout *style_grid = new QGridLayout ();\n  QVector<QLabel *> description (ws_colors_count);\n  QVector<color_picker *> color (ws_colors_count);\n\n  int column = 0;\n  const int color_columns = 3;  // place colors in so many columns\n  int row = 0;\n  int mode = settings.int_value (ws_color_mode);\n\n  m_ws_enable_colors = new QCheckBox (tr (\"Enable attribute colors\"));\n  style_grid->addWidget (m_ws_enable_colors, row++, column, 1, 4);\n\n  m_ws_hide_tool_tips = new QCheckBox (tr (\"Hide tool tips\"));\n  style_grid->addWidget (m_ws_hide_tool_tips, row++, column, 1, 4);\n  connect (m_ws_enable_colors, &QCheckBox::toggled,\n           m_ws_hide_tool_tips, &QCheckBox::setEnabled);\n  m_ws_hide_tool_tips->setChecked\n    (settings.bool_value (ws_hide_tool_tips));\n\n  QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()));\n  cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ()));\n  cb_color_mode->setChecked (mode == 1);\n  cb_color_mode->setObjectName (ws_color_mode.settings_key ());\n  connect (m_ws_enable_colors, &QCheckBox::toggled,\n           cb_color_mode, &QCheckBox::setEnabled);\n  style_grid->addWidget (cb_color_mode, row, column);\n\n  QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ()));\n  pb_reload_default_colors->setToolTip (tr (settings_reload_colors_tooltip.toStdString ().data ()));\n  connect (m_ws_enable_colors, &QCheckBox::toggled,\n           pb_reload_default_colors, &QPushButton::setEnabled);\n  style_grid->addWidget (pb_reload_default_colors, row+1, column++);\n\n  bool colors_enabled = settings.bool_value (ws_enable_colors);\n\n  for (int i = 0; i < ws_colors_count; i++)\n    {\n      description[i] = new QLabel (\"    \"\n                                   + tr (ws_color_names.at (i).toStdString ().data ()));\n      description[i]->setAlignment (Qt::AlignRight);\n      description[i]->setEnabled (colors_enabled);\n      connect (m_ws_enable_colors, &QCheckBox::toggled,\n               description[i], &QLabel::setEnabled);\n\n      QColor setting_color = settings.color_value (ws_colors[i], mode);\n      color[i] = new color_picker (setting_color);\n      color[i]->setObjectName (ws_colors[i].settings_key ());\n      color[i]->setMinimumSize (30, 10);\n      color[i]->setEnabled (colors_enabled);\n      connect (m_ws_enable_colors, &QCheckBox::toggled,\n               color[i], &color_picker::setEnabled);\n\n      style_grid->addWidget (description[i], row, 3*column);\n      style_grid->addWidget (color[i], row, 3*column+1);\n      if (++column > color_columns)\n        {\n          style_grid->setColumnStretch (4*column, 10);\n          row++;\n          column = 1;\n        }\n    }\n\n  // Load enable settings at the end for having signals already connected\n  m_ws_enable_colors->setChecked (colors_enabled);\n  m_ws_hide_tool_tips->setEnabled (colors_enabled);\n  cb_color_mode->setEnabled (colors_enabled);\n  pb_reload_default_colors->setEnabled (colors_enabled);\n\n  // place grid with elements into the tab\n  workspace_colors_box->setLayout (style_grid);\n\n  // update colors depending on second theme selection or reloading\n  // the dfault values\n  connect (cb_color_mode,\n#if defined (HAVE_QCHECKBOX_CHECKSTATECHANGED)\n           &QCheckBox::checkStateChanged,\n#else\n           &QCheckBox::stateChanged,\n#endif\n           this, &settings_dialog::update_workspace_colors);\n  connect (pb_reload_default_colors, &QPushButton::clicked,\n           [this] () { update_workspace_colors (settings_reload_default_colors_flag); });\n}\n\nvoid\nsettings_dialog::update_workspace_colors (int def)\n{\n  QCheckBox *cb_color_mode\n    = workspace_colors_box->findChild<QCheckBox *> (ws_color_mode.settings_key ());\n\n  int m = 0;\n  if (cb_color_mode && cb_color_mode->isChecked ())\n    m = 1;\n\n  gui_settings settings;\n\n  color_picker *c_picker;\n\n  for (unsigned int i = 0; i < ws_colors_count; i++)\n    {\n      c_picker = workspace_colors_box->findChild<color_picker *> (ws_colors[i].settings_key ());\n      if (c_picker)\n        {\n          if (def != settings_reload_default_colors_flag)\n            {\n              // Get current value from settings or the default\n              c_picker->set_color (settings.color_value (ws_colors[i], m));\n            }\n          else\n            {\n              // Get the default value\n              c_picker->set_color (settings.get_color_value (ws_colors[i].def (), m));\n            }\n        }\n    }\n}\n\nvoid\nsettings_dialog::write_workspace_colors ()\n{\n  gui_settings settings;\n\n  settings.setValue (ws_enable_colors.settings_key (), m_ws_enable_colors->isChecked ());\n  settings.setValue (ws_hide_tool_tips.settings_key (), m_ws_hide_tool_tips->isChecked ());\n\n  QCheckBox *cb_color_mode\n    = workspace_colors_box->findChild<QCheckBox *> (ws_color_mode.settings_key ());\n\n  int mode = 0;\n  if (cb_color_mode && cb_color_mode->isChecked ())\n    mode = 1;\n\n  color_picker *color;\n\n  for (int i = 0; i < ws_colors_count; i++)\n    {\n      color = workspace_colors_box->findChild<color_picker *> (ws_colors[i].settings_key ());\n      if (color)\n        settings.set_color_value (ws_colors[i], color->color (), mode);\n    }\n\n  settings.setValue (ws_color_mode.settings_key (), mode);\n\n  settings.sync ();\n}\n\nvoid\nsettings_dialog::read_terminal_colors ()\n{\n  gui_settings settings;\n\n  QGridLayout *style_grid = new QGridLayout ();\n  QVector<QLabel *> description (cs_colors_count);\n  QVector<color_picker *> color (cs_colors_count);\n\n  int mode = settings.int_value (cs_color_mode);\n\n  QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()));\n  cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ()));\n  cb_color_mode->setChecked (mode == 1);\n  cb_color_mode->setObjectName (cs_color_mode.settings_key ());\n  style_grid->addWidget (cb_color_mode, 0, 0);\n\n  QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ()));\n  pb_reload_default_colors->setToolTip (tr (settings_reload_colors_tooltip.toStdString ().data ()));\n  style_grid->addWidget (pb_reload_default_colors, 1, 0);\n\n  int column = 1;               // column 0 is for the color mode checkbox\n  const int color_columns = 2;  // place colors in so many columns\n  int row = 0;\n  for (unsigned int i = 0; i < cs_colors_count; i++)\n    {\n      description[i] = new QLabel (\"    \"\n                                   + tr (cs_color_names.at (i).toStdString ().data ()));\n      description[i]->setAlignment (Qt::AlignRight);\n      QColor setting_color = settings.color_value (cs_colors[i], mode);\n      color[i] = new color_picker (setting_color);\n      color[i]->setObjectName (cs_colors[i].settings_key ());\n      color[i]->setMinimumSize (30, 10);\n      style_grid->addWidget (description[i], row, 2*column);\n      style_grid->addWidget (color[i], row, 2*column+1);\n      if (++column > color_columns)\n        {\n          style_grid->setColumnStretch (3*column, 10);\n          row++;\n          column = 1;\n        }\n    }\n\n  // place grid with elements into the tab\n  terminal_colors_box->setLayout (style_grid);\n\n  // update colors depending on second theme selection\n  connect (cb_color_mode,\n#if defined (HAVE_QCHECKBOX_CHECKSTATECHANGED)\n           &QCheckBox::checkStateChanged,\n#else\n           &QCheckBox::stateChanged,\n#endif\n           this, &settings_dialog::update_terminal_colors);\n  connect (pb_reload_default_colors, &QPushButton::clicked,\n           [this] () { update_terminal_colors (settings_reload_default_colors_flag); });\n}\n\nvoid\nsettings_dialog::update_terminal_colors (int def)\n{\n  QCheckBox *cb_color_mode\n    = terminal_colors_box->findChild<QCheckBox *> (cs_color_mode.settings_key ());\n\n  int m = 0;\n  if (cb_color_mode && cb_color_mode->isChecked ())\n    m = 1;\n\n  gui_settings settings;\n\n  color_picker *c_picker;\n\n  for (unsigned int i = 0; i < cs_colors_count; i++)\n    {\n      c_picker = terminal_colors_box->findChild<color_picker *> (cs_colors[i].settings_key ());\n      if (c_picker)\n        {\n          if (def != settings_reload_default_colors_flag)\n            {\n              // Get current value from settings or the default\n              c_picker->set_color (settings.color_value (cs_colors[i], m));\n            }\n          else\n            {\n              // Get the default value\n              c_picker->set_color (settings.get_color_value (cs_colors[i].def (), m));\n            }\n        }\n    }\n}\n\nvoid\nsettings_dialog::write_terminal_colors ()\n{\n  QCheckBox *cb_color_mode\n    = terminal_colors_box->findChild<QCheckBox *> (cs_color_mode.settings_key ());\n\n  int mode = 0;\n  if (cb_color_mode && cb_color_mode->isChecked ())\n    mode = 1;\n\n  gui_settings settings;\n\n  color_picker *color;\n\n  for (int i = 0; i < cs_color_names.size (); i++)\n    {\n      color = terminal_colors_box->findChild<color_picker *> (cs_colors[i].settings_key ());\n      if (color)\n        settings.set_color_value (cs_colors[i], color->color (), mode);\n    }\n\n  settings.setValue (cs_color_mode.settings_key (), mode);\n\n  settings.sync ();\n}\n\nvoid\nsettings_dialog::read_varedit_colors ()\n{\n  gui_settings settings;\n\n  QGridLayout *style_grid = new QGridLayout ();\n  QVector<QLabel *> description (ve_colors_count);\n  QVector<color_picker *> color (ve_colors_count);\n\n  int mode = settings.int_value (ve_color_mode);\n\n  QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()));\n  cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ()));\n  cb_color_mode->setChecked (mode == 1);\n  cb_color_mode->setObjectName (ve_color_mode.settings_key ());\n  style_grid->addWidget (cb_color_mode, 0, 0);\n\n  QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ()));\n  pb_reload_default_colors->setToolTip (tr (settings_reload_colors_tooltip.toStdString ().data ()));\n  style_grid->addWidget (pb_reload_default_colors, 1, 0);\n\n  int column = 1;\n  int color_columns = 2;\n  int row = 0;\n  for (int i = 0; i < ve_colors_count; i++)\n    {\n      description[i] = new QLabel (\"    \"\n                                   + tr (ve_color_names.at (i).toStdString ().data ()));\n      description[i]->setAlignment (Qt::AlignRight);\n\n      QColor setting_color = settings.color_value (ve_colors[i], mode);\n      color[i] = new color_picker (setting_color);\n      color[i]->setObjectName (ve_colors[i].settings_key ());\n      color[i]->setMinimumSize (30, 10);\n      style_grid->addWidget (description[i], row, 2*column);\n      style_grid->addWidget (color[i], row, 2*column+1);\n      if (++column > color_columns)\n        {\n          style_grid->setColumnStretch (3*column, 10);\n          row++;\n          column = 1;\n        }\n    }\n\n  // place grid with elements into the tab\n  varedit_colors_box->setLayout (style_grid);\n\n  // update colors depending on second theme selection\n  connect (cb_color_mode,\n#if defined (HAVE_QCHECKBOX_CHECKSTATECHANGED)\n           &QCheckBox::checkStateChanged,\n#else\n           &QCheckBox::stateChanged,\n#endif\n           this, &settings_dialog::update_varedit_colors);\n  connect (pb_reload_default_colors, &QPushButton::clicked,\n           [this] () { update_varedit_colors (settings_reload_default_colors_flag); });\n}\n\nvoid\nsettings_dialog::update_varedit_colors (int def)\n{\n  QCheckBox *cb_color_mode\n    = varedit_colors_box->findChild<QCheckBox *> (ve_color_mode.settings_key ());\n\n  int m = 0;\n  if (cb_color_mode && cb_color_mode->isChecked ())\n    m = 1;\n\n  gui_settings settings;\n\n  color_picker *c_picker;\n\n  for (unsigned int i = 0; i < ve_colors_count; i++)\n    {\n      c_picker = varedit_colors_box->findChild<color_picker *> (ve_colors[i].settings_key ());\n      if (c_picker)\n        {\n          if (def != settings_reload_default_colors_flag)\n            {\n              // Get current value from settings or the default\n              c_picker->set_color (settings.color_value (ve_colors[i], m));\n            }\n          else\n            {\n              // Get the default value\n              c_picker->set_color (settings.get_color_value (ve_colors[i].def (), m));\n            }\n        }\n    }\n}\n\nvoid\nsettings_dialog::write_varedit_colors ()\n{\n  QCheckBox *cb_color_mode\n    = varedit_colors_box->findChild<QCheckBox *> (ve_color_mode.settings_key ());\n\n  int mode = 0;\n  if (cb_color_mode && cb_color_mode->isChecked ())\n    mode = 1;\n\n  gui_settings settings;\n\n  color_picker *color;\n\n  for (int i = 0; i < ve_colors_count; i++)\n    {\n      color = varedit_colors_box->findChild<color_picker *> (ve_colors[i].settings_key ());\n      if (color)\n        settings.set_color_value (ve_colors[i], color->color (), mode);\n    }\n\n  settings.setValue (ve_color_mode.settings_key (), mode);\n\n  settings.sync ();\n}\n\nQString\nsettings_dialog::get_shortcuts_file_name (import_export_action action)\n{\n  QString file;\n\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n  int opts = 0;  // No options by default.\n\n  gui_settings settings;\n\n  if (! settings.bool_value (global_use_native_dialogs))\n    opts = QFileDialog::DontUseNativeDialog;\n\n  if (action == OSC_IMPORT)\n    file = QFileDialog::getOpenFileName\n      (this, tr (\"Import shortcuts from file...\"), QString (),\n       tr (\"Octave Shortcut Files (*.osc);;All Files (*)\"),\n       nullptr, QFileDialog::Option (opts));\n\n  else\n    file = QFileDialog::getSaveFileName\n      (this, tr (\"Export shortcuts to file...\"), QString (),\n       tr (\"Octave Shortcut Files (*.osc);;All Files (*)\"),\n       nullptr, QFileDialog::Option (opts));\n\n  return file;\n}\n\n// Ask whether to overwrite current shortcuts with settings from an\n// imported file.  Optionally allow current shortcuts to be saved to a\n// file.\n\n// FIXME: If the tree view contains changes that have not yet been\n//        saved to the application settings object, should we\n//\n//   * allow the user to choose whether to\n//     - cancel the operation (X)\n//     - save the modified settings (X)\n//     - save the current application settings (XX)\n//\n//   * unconditionally display an error dialog and cancel the\n//     export operation\n//\n//   (X) - already an option, but not based on whether the tree view\n//         contains unsaved changes\n//   (XX) - already possible (cancel operation, cancel settings\n//          dialog, re-open settings dialog and export changes).\n\nbool\nsettings_dialog::overwrite_all_shortcuts ()\n{\n  QMessageBox msg_box;\n\n  msg_box.setWindowTitle (tr (\"Overwriting Shortcuts\"));\n  msg_box.setIcon (QMessageBox::Warning);\n  msg_box.setText (tr (\"You are about to overwrite all shortcuts.\\n\"\n                       \"Would you like to save the current shortcut set or cancel the action?\"));\n  msg_box.setStandardButtons (QMessageBox::Save | QMessageBox::Cancel);\n\n  QPushButton *discard\n    = msg_box.addButton (tr (\"Don't save\"), QMessageBox::DestructiveRole);\n\n  msg_box.setDefaultButton (QMessageBox::Save);\n\n  int ret = msg_box.exec ();\n\n  if (msg_box.clickedButton () == discard)\n    return true;\n\n  if (ret == QMessageBox::Save)\n    {\n      QString file = get_shortcuts_file_name (OSC_EXPORT);\n\n      gui_settings osc_settings (file, QSettings::IniFormat);\n\n      if (osc_settings.status () ==  QSettings::NoError)\n        {\n          shortcuts_treewidget->export_shortcuts (osc_settings);\n          return true;\n        }\n      else\n        qWarning () << (tr (\"Failed to open %1 as Octave shortcut file\")\n                        .arg (file));\n    }\n\n  return false;\n}\n\nQMessageBox *\nsettings_dialog::wait_message_box (const QString& text, QWidget *p)\n{\n  QMessageBox *info = new QMessageBox (p);\n\n  info->setIcon (QMessageBox::Information);\n  info->setWindowTitle (tr (\"Octave GUI preferences\"));\n  info->setText (text);\n  info->setStandardButtons (QMessageBox::Ok);\n  info->setAttribute (Qt::WA_DeleteOnClose);\n  info->setWindowModality (Qt::NonModal);\n\n  info->show ();\n  QThread::msleep (100);\n  QCoreApplication::processEvents ();\n\n  QApplication::setOverrideCursor (Qt::WaitCursor);\n\n  return info;\n}\n\nvoid\nsettings_dialog::close_wait_message_box (QMessageBox *mbox)\n{\n  QApplication::restoreOverrideCursor ();\n  mbox->close ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/settings-dialog.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_settings_dialog_h)\n#define octave_settings_dialog_h 1\n\n#include <QCheckBox>\n#include <QDialog>\n#include <QLineEdit>\n#include <QMessageBox>\n#include <QRadioButton>\n\n#include \"color-picker.h\"\n#include \"gui-preferences-ed.h\"\n#include \"ui-settings-dialog.h\"\n\nclass QsciLexer;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Ui::settings_dialog is a generated class.\n\nclass settings_dialog : public QDialog, private Ui::settings_dialog\n{\n  Q_OBJECT\n\npublic:\n\n  explicit settings_dialog (QWidget *parent,\n                            const QString& desired_tab = QString ());\n\n  ~settings_dialog () = default;\n\n  void show_tab (const QString&);\n\nQ_SIGNALS:\n\n  void apply_new_settings ();\n\nprivate Q_SLOTS:\n\n  void get_octave_dir ();\n  void get_file_browser_dir ();\n  void get_dir (QLineEdit *, const QString&);\n  void set_disabled_pref_file_browser_dir (bool disable);\n  void proxy_items_update ();\n\n  // slots updating colors depending on theme\n  void update_terminal_colors (int def = 0);\n  void update_workspace_colors (int def = 0);\n  void update_varedit_colors (int def = 0);\n  void update_editor_lexers (int def = 0);\n\n  // slots for dialog's buttons\n  void button_clicked (QAbstractButton *button);\n\n  // slots for import/export-buttons of shortcut sets\n  void import_shortcut_set ();\n  void export_shortcut_set ();\n  void default_shortcut_set ();\n\nprivate:\n\n  enum import_export_action\n  {\n    OSC_IMPORT,\n    OSC_EXPORT\n  };\n\n  void update_lexer (QsciLexer *lexer, int mode, int def = 0);\n  void get_lexer_settings (QsciLexer *lexer);\n  void write_lexer_settings (QsciLexer *lexer);\n\n  void read_settings (bool first);\n\n  void write_changed_settings ();\n\n  void read_workspace_colors ();\n  void write_workspace_colors ();\n\n  void read_terminal_colors ();\n  void write_terminal_colors ();\n\n  void read_varedit_colors ();\n  void write_varedit_colors ();\n\n  QString get_shortcuts_file_name (import_export_action action);\n\n  QMessageBox * wait_message_box (const QString& test, QWidget *p);\n  void close_wait_message_box (QMessageBox *mbox);\n\n  bool overwrite_all_shortcuts ();\n\n  color_picker *m_widget_title_bg_color;\n  color_picker *m_widget_title_bg_color_active;\n  color_picker *m_widget_title_fg_color;\n  color_picker *m_widget_title_fg_color_active;\n\n  QRadioButton *m_rb_comment_strings[ed_comment_strings_count];\n  QCheckBox *m_rb_uncomment_strings[ed_comment_strings_count];\n\n  QCheckBox *m_ws_enable_colors;\n  QCheckBox *m_ws_hide_tool_tips;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/settings-dialog.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>settings_dialog</class>\n <widget class=\"QDialog\" name=\"settings_dialog\">\n  <property name=\"windowModality\">\n   <enum>Qt::ApplicationModal</enum>\n  </property>\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>1077</width>\n    <height>673</height>\n   </rect>\n  </property>\n  <property name=\"minimumSize\">\n   <size>\n    <width>400</width>\n    <height>400</height>\n   </size>\n  </property>\n  <property name=\"windowTitle\">\n   <string>Preferences</string>\n  </property>\n  <layout class=\"QVBoxLayout\" name=\"verticalLayout_2\">\n   <item>\n    <widget class=\"QTabWidget\" name=\"tabWidget\">\n     <property name=\"minimumSize\">\n      <size>\n       <width>0</width>\n       <height>0</height>\n      </size>\n     </property>\n     <property name=\"toolTip\">\n      <string/>\n     </property>\n     <property name=\"currentIndex\">\n      <number>2</number>\n     </property>\n     <widget class=\"QWidget\" name=\"tab_general\">\n      <property name=\"enabled\">\n       <bool>true</bool>\n      </property>\n      <attribute name=\"title\">\n       <string>General</string>\n      </attribute>\n      <layout class=\"QVBoxLayout\" name=\"verticalLayout_10\">\n       <item>\n        <widget class=\"QScrollArea\" name=\"scrollArea_2\">\n         <property name=\"widgetResizable\">\n          <bool>true</bool>\n         </property>\n         <widget class=\"QWidget\" name=\"scrollAreaWidgetContents_2\">\n          <property name=\"geometry\">\n           <rect>\n            <x>0</x>\n            <y>0</y>\n            <width>1021</width>\n            <height>643</height>\n           </rect>\n          </property>\n          <layout class=\"QVBoxLayout\" name=\"verticalLayout_17\">\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox\">\n             <property name=\"title\">\n              <string>Interface</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_21\">\n              <item>\n               <layout class=\"QGridLayout\" name=\"gridLayout\">\n                <item row=\"7\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_15\">\n                  <property name=\"text\">\n                   <string>Dock widget title bar</string>\n                  </property>\n                  <property name=\"alignment\">\n                   <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"5\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_9\">\n                  <property name=\"text\">\n                   <string>Dock widgets window icons</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_29\">\n                  <property name=\"text\">\n                   <string>Style</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"1\">\n                 <layout class=\"QHBoxLayout\" name=\"horizontalLayout_17\">\n                  <item>\n                   <widget class=\"QComboBox\" name=\"combo_styles\">\n                    <property name=\"minimumSize\">\n                     <size>\n                      <width>135</width>\n                      <height>0</height>\n                     </size>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <spacer name=\"horizontalSpacer\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>40</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n                <item row=\"1\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_2\">\n                  <property name=\"text\">\n                   <string>Language</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"3\" column=\"1\">\n                 <layout class=\"QGridLayout\" name=\"gridLayout_16\">\n                  <item row=\"1\" column=\"0\">\n                   <widget class=\"QLabel\" name=\"label_4\">\n                    <property name=\"text\">\n                     <string>Icon theme (requires restart)</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"1\" column=\"1\">\n                   <widget class=\"QComboBox\" name=\"combo_box_icon_theme\"/>\n                  </item>\n                  <item row=\"0\" column=\"0\">\n                   <layout class=\"QHBoxLayout\" name=\"horizontalLayout_6\">\n                    <item>\n                     <widget class=\"QRadioButton\" name=\"icon_size_small\">\n                      <property name=\"text\">\n                       <string>Small</string>\n                      </property>\n                     </widget>\n                    </item>\n                    <item>\n                     <widget class=\"QRadioButton\" name=\"icon_size_normal\">\n                      <property name=\"text\">\n                       <string>Normal</string>\n                      </property>\n                      <property name=\"checked\">\n                       <bool>true</bool>\n                      </property>\n                     </widget>\n                    </item>\n                    <item>\n                     <widget class=\"QRadioButton\" name=\"icon_size_large\">\n                      <property name=\"text\">\n                       <string>Large</string>\n                      </property>\n                     </widget>\n                    </item>\n                   </layout>\n                  </item>\n                  <item row=\"1\" column=\"2\">\n                   <spacer name=\"horizontalSpacer_5\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>40</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n                <item row=\"7\" column=\"1\">\n                 <layout class=\"QHBoxLayout\" name=\"horizontalLayout_4\">\n                  <item>\n                   <layout class=\"QGridLayout\" name=\"gridLayout_13\">\n                    <property name=\"rightMargin\">\n                     <number>0</number>\n                    </property>\n                    <item row=\"0\" column=\"9\">\n                     <widget class=\"QLabel\" name=\"label_bgtitle_active\">\n                      <property name=\"enabled\">\n                       <bool>false</bool>\n                      </property>\n                      <property name=\"text\">\n                       <string>Active</string>\n                      </property>\n                      <property name=\"alignment\">\n                       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n                      </property>\n                     </widget>\n                    </item>\n                    <item row=\"1\" column=\"4\">\n                     <layout class=\"QHBoxLayout\" name=\"layout_widget_fgtitle\"/>\n                    </item>\n                    <item row=\"0\" column=\"1\">\n                     <spacer name=\"horizontalSpacer_22\">\n                      <property name=\"orientation\">\n                       <enum>Qt::Horizontal</enum>\n                      </property>\n                      <property name=\"sizeType\">\n                       <enum>QSizePolicy::Fixed</enum>\n                      </property>\n                      <property name=\"sizeHint\" stdset=\"0\">\n                       <size>\n                        <width>40</width>\n                        <height>20</height>\n                       </size>\n                      </property>\n                     </spacer>\n                    </item>\n                    <item row=\"1\" column=\"2\">\n                     <widget class=\"QLabel\" name=\"label_fgtitle\">\n                      <property name=\"enabled\">\n                       <bool>false</bool>\n                      </property>\n                      <property name=\"text\">\n                       <string>Text inactive</string>\n                      </property>\n                      <property name=\"alignment\">\n                       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n                      </property>\n                     </widget>\n                    </item>\n                    <item row=\"1\" column=\"9\">\n                     <widget class=\"QLabel\" name=\"label_fgtitle_active\">\n                      <property name=\"enabled\">\n                       <bool>false</bool>\n                      </property>\n                      <property name=\"text\">\n                       <string>Active</string>\n                      </property>\n                      <property name=\"alignment\">\n                       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n                      </property>\n                     </widget>\n                    </item>\n                    <item row=\"0\" column=\"7\">\n                     <spacer name=\"horizontalSpacer_23\">\n                      <property name=\"orientation\">\n                       <enum>Qt::Horizontal</enum>\n                      </property>\n                      <property name=\"sizeType\">\n                       <enum>QSizePolicy::Fixed</enum>\n                      </property>\n                      <property name=\"sizeHint\" stdset=\"0\">\n                       <size>\n                        <width>12</width>\n                        <height>20</height>\n                       </size>\n                      </property>\n                     </spacer>\n                    </item>\n                    <item row=\"0\" column=\"0\">\n                     <widget class=\"QCheckBox\" name=\"cb_widget_custom_style\">\n                      <property name=\"text\">\n                       <string>Custom style</string>\n                      </property>\n                     </widget>\n                    </item>\n                    <item row=\"0\" column=\"4\">\n                     <layout class=\"QHBoxLayout\" name=\"layout_widget_bgtitle\"/>\n                    </item>\n                    <item row=\"0\" column=\"2\">\n                     <widget class=\"QLabel\" name=\"label_bgtitle\">\n                      <property name=\"enabled\">\n                       <bool>false</bool>\n                      </property>\n                      <property name=\"text\">\n                       <string>Background inactive</string>\n                      </property>\n                      <property name=\"alignment\">\n                       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n                      </property>\n                     </widget>\n                    </item>\n                    <item row=\"0\" column=\"10\">\n                     <layout class=\"QHBoxLayout\" name=\"layout_widget_bgtitle_active\"/>\n                    </item>\n                    <item row=\"1\" column=\"10\">\n                     <layout class=\"QHBoxLayout\" name=\"layout_widget_fgtitle_active\"/>\n                    </item>\n                    <item row=\"1\" column=\"0\">\n                     <widget class=\"QLabel\" name=\"label_3d_title\">\n                      <property name=\"enabled\">\n                       <bool>false</bool>\n                      </property>\n                      <property name=\"text\">\n                       <string>3-D</string>\n                      </property>\n                      <property name=\"alignment\">\n                       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n                      </property>\n                     </widget>\n                    </item>\n                    <item row=\"1\" column=\"1\">\n                     <widget class=\"QSpinBox\" name=\"sb_3d_title\">\n                      <property name=\"enabled\">\n                       <bool>false</bool>\n                      </property>\n                      <property name=\"sizePolicy\">\n                       <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                        <horstretch>0</horstretch>\n                        <verstretch>0</verstretch>\n                       </sizepolicy>\n                      </property>\n                      <property name=\"minimum\">\n                       <number>-80</number>\n                      </property>\n                      <property name=\"maximum\">\n                       <number>80</number>\n                      </property>\n                      <property name=\"value\">\n                       <number>50</number>\n                      </property>\n                     </widget>\n                    </item>\n                   </layout>\n                  </item>\n                  <item>\n                   <spacer name=\"horizontalSpacer_21\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>40</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n                <item row=\"3\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_8\">\n                  <property name=\"text\">\n                   <string>Toolbar Icons</string>\n                  </property>\n                  <property name=\"alignment\">\n                   <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"1\" column=\"1\">\n                 <layout class=\"QHBoxLayout\" name=\"horizontalLayout_8\">\n                  <item>\n                   <widget class=\"QComboBox\" name=\"comboBox_language\">\n                    <property name=\"minimumSize\">\n                     <size>\n                      <width>135</width>\n                      <height>0</height>\n                     </size>\n                    </property>\n                    <property name=\"insertPolicy\">\n                     <enum>QComboBox::InsertAtBottom</enum>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <widget class=\"QLabel\" name=\"label_10\">\n                    <property name=\"text\">\n                     <string>(requires restart)</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <spacer name=\"horizontalSpacer_3\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>40</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n                <item row=\"5\" column=\"1\">\n                 <layout class=\"QHBoxLayout\" name=\"horizontalLayout_9\">\n                  <item>\n                   <widget class=\"QRadioButton\" name=\"general_icon_octave\">\n                    <property name=\"text\">\n                     <string>Octave logo only</string>\n                    </property>\n                    <property name=\"checked\">\n                     <bool>true</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <widget class=\"QRadioButton\" name=\"general_icon_letter\">\n                    <property name=\"text\">\n                     <string>Letter icons</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <widget class=\"QRadioButton\" name=\"general_icon_graphic\">\n                    <property name=\"text\">\n                     <string>Graphic icons</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <spacer name=\"horizontalSpacer_6\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>40</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n               </layout>\n              </item>\n              <item>\n               <layout class=\"QVBoxLayout\" name=\"verticalLayout_35\">\n                <property name=\"spacing\">\n                 <number>0</number>\n                </property>\n                <property name=\"topMargin\">\n                 <number>0</number>\n                </property>\n                <item>\n                 <widget class=\"QCheckBox\" name=\"cb_use_native_file_dialogs\">\n                  <property name=\"text\">\n                   <string>Use native file dialogs</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <widget class=\"QCheckBox\" name=\"cb_cursor_blinking\">\n                  <property name=\"text\">\n                   <string>Blinking cursor</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <widget class=\"QCheckBox\" name=\"cb_status_bar\">\n                  <property name=\"text\">\n                   <string>Show status bar</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <widget class=\"QCheckBox\" name=\"cb_focus_follows_mouse\">\n                  <property name=\"toolTip\">\n                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If set, the focus of the widgets that are docked to the main window follows the mouse cursor. This is intended for having the same behavior within the main window when &amp;quot;focus follows mouse&amp;quot; is used for the desktop environment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>\n                  </property>\n                  <property name=\"text\">\n                   <string>Focus follows mouse for widgets docked to the main window</string>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <widget class=\"QCheckBox\" name=\"cb_prompt_to_exit\">\n                  <property name=\"text\">\n                   <string>Confirm before exiting</string>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <widget class=\"QCheckBox\" name=\"cb_show_splash_screen\">\n                  <property name=\"text\">\n                   <string>Show splash screen at startup</string>\n                  </property>\n                 </widget>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_2\">\n             <property name=\"title\">\n              <string>Octave Startup</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_22\">\n              <item>\n               <widget class=\"QLabel\" name=\"label_18\">\n                <property name=\"text\">\n                 <string>These preferences are applied after any .octaverc startup files.</string>\n                </property>\n               </widget>\n              </item>\n              <item>\n               <layout class=\"QGridLayout\" name=\"gridLayout_9\">\n                <item row=\"0\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_17\">\n                  <property name=\"text\">\n                   <string>Initial working directory of Octave interpreter</string>\n                  </property>\n                  <property name=\"alignment\">\n                   <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>\n                  </property>\n                  <property name=\"wordWrap\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"1\">\n                 <layout class=\"QGridLayout\" name=\"gridLayout_20\">\n                  <item row=\"1\" column=\"0\">\n                   <widget class=\"QLineEdit\" name=\"le_octave_dir\"/>\n                  </item>\n                  <item row=\"0\" column=\"0\">\n                   <widget class=\"QCheckBox\" name=\"cb_restore_octave_dir\">\n                    <property name=\"text\">\n                     <string>Restore last working directory of previous session</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"1\" column=\"1\">\n                   <widget class=\"QPushButton\" name=\"pb_octave_dir\">\n                    <property name=\"sizePolicy\">\n                     <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n                      <horstretch>0</horstretch>\n                      <verstretch>0</verstretch>\n                     </sizepolicy>\n                    </property>\n                    <property name=\"text\">\n                     <string>Browse</string>\n                    </property>\n                   </widget>\n                  </item>\n                 </layout>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <spacer name=\"verticalSpacer\">\n             <property name=\"orientation\">\n              <enum>Qt::Vertical</enum>\n             </property>\n             <property name=\"sizeHint\" stdset=\"0\">\n              <size>\n               <width>20</width>\n               <height>40</height>\n              </size>\n             </property>\n            </spacer>\n           </item>\n          </layout>\n         </widget>\n        </widget>\n       </item>\n      </layout>\n     </widget>\n     <widget class=\"QWidget\" name=\"tab_terminal\">\n      <attribute name=\"title\">\n       <string>Command</string>\n      </attribute>\n      <layout class=\"QVBoxLayout\" name=\"verticalLayout_14\">\n       <item>\n        <widget class=\"QScrollArea\" name=\"scrollArea_3\">\n         <property name=\"widgetResizable\">\n          <bool>true</bool>\n         </property>\n         <widget class=\"QWidget\" name=\"scrollAreaWidgetContents_4\">\n          <property name=\"geometry\">\n           <rect>\n            <x>0</x>\n            <y>0</y>\n            <width>1035</width>\n            <height>567</height>\n           </rect>\n          </property>\n          <layout class=\"QVBoxLayout\" name=\"verticalLayout_7\">\n           <item>\n            <layout class=\"QVBoxLayout\" name=\"verticalLayout_8\">\n             <item>\n              <layout class=\"QGridLayout\" name=\"gridLayout_7\">\n               <property name=\"sizeHint\" stdset=\"0\">\n                <size>\n                 <width>40</width>\n                 <height>20</height>\n                </size>\n               </property>\n               <item row=\"1\" column=\"2\">\n                <layout class=\"QHBoxLayout\" name=\"horizontalLayout_13\">\n                 <item>\n                  <widget class=\"QCheckBox\" name=\"terminal_cursorUseForegroundColor\">\n                   <property name=\"text\">\n                    <string>Use foreground color</string>\n                   </property>\n                  </widget>\n                 </item>\n                </layout>\n               </item>\n               <item row=\"1\" column=\"0\">\n                <layout class=\"QHBoxLayout\" name=\"horizontalLayout_7\">\n                 <item>\n                  <widget class=\"QLabel\" name=\"label\">\n                   <property name=\"text\">\n                    <string>Cursor type:</string>\n                   </property>\n                  </widget>\n                 </item>\n                 <item>\n                  <widget class=\"QComboBox\" name=\"terminal_cursorType\"/>\n                 </item>\n                </layout>\n               </item>\n               <item row=\"0\" column=\"0\">\n                <layout class=\"QHBoxLayout\" name=\"horizontalLayout_11\">\n                 <item>\n                  <widget class=\"QLabel\" name=\"label_11\">\n                   <property name=\"text\">\n                    <string>Font</string>\n                   </property>\n                  </widget>\n                 </item>\n                 <item>\n                  <widget class=\"QFontComboBox\" name=\"terminal_fontName\">\n                   <property name=\"sizePolicy\">\n                    <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                     <horstretch>0</horstretch>\n                     <verstretch>0</verstretch>\n                    </sizepolicy>\n                   </property>\n                   <property name=\"editable\">\n                    <bool>false</bool>\n                   </property>\n                   <property name=\"fontFilters\">\n                    <set>QFontComboBox::MonospacedFonts</set>\n                   </property>\n                  </widget>\n                 </item>\n                </layout>\n               </item>\n               <item row=\"0\" column=\"2\">\n                <layout class=\"QHBoxLayout\" name=\"horizontalLayout_12\">\n                 <item>\n                  <widget class=\"QLabel\" name=\"label_12\">\n                   <property name=\"text\">\n                    <string>Font size</string>\n                   </property>\n                  </widget>\n                 </item>\n                 <item>\n                  <widget class=\"QSpinBox\" name=\"terminal_fontSize\">\n                   <property name=\"sizePolicy\">\n                    <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                     <horstretch>0</horstretch>\n                     <verstretch>0</verstretch>\n                    </sizepolicy>\n                   </property>\n                   <property name=\"minimum\">\n                    <number>2</number>\n                   </property>\n                   <property name=\"maximum\">\n                    <number>96</number>\n                   </property>\n                   <property name=\"value\">\n                    <number>10</number>\n                   </property>\n                  </widget>\n                 </item>\n                 <item>\n                  <spacer name=\"horizontalSpacer_27\">\n                   <property name=\"orientation\">\n                    <enum>Qt::Horizontal</enum>\n                   </property>\n                   <property name=\"sizeHint\" stdset=\"0\">\n                    <size>\n                     <width>40</width>\n                     <height>20</height>\n                    </size>\n                   </property>\n                  </spacer>\n                 </item>\n                </layout>\n               </item>\n               <item row=\"2\" column=\"2\">\n                <layout class=\"QHBoxLayout\" name=\"horizontalLayout_5\">\n                 <property name=\"topMargin\">\n                  <number>0</number>\n                 </property>\n                 <item>\n                  <widget class=\"QSpinBox\" name=\"terminal_history_buffer\">\n                   <property name=\"sizePolicy\">\n                    <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                     <horstretch>0</horstretch>\n                     <verstretch>0</verstretch>\n                    </sizepolicy>\n                   </property>\n                   <property name=\"minimum\">\n                    <number>0</number>\n                   </property>\n                   <property name=\"maximum\">\n                    <number>5000</number>\n                   </property>\n                   <property name=\"singleStep\">\n                    <number>20</number>\n                   </property>\n                   <property name=\"value\">\n                    <number>1000</number>\n                   </property>\n                  </widget>\n                 </item>\n                 <item>\n                  <widget class=\"QLabel\" name=\"label_20\">\n                   <property name=\"text\">\n                    <string>(Changing buffer size clears history)</string>\n                   </property>\n                  </widget>\n                 </item>\n                 <item>\n                  <spacer name=\"horizontalSpacer_16\">\n                   <property name=\"orientation\">\n                    <enum>Qt::Horizontal</enum>\n                   </property>\n                   <property name=\"sizeHint\" stdset=\"0\">\n                    <size>\n                     <width>40</width>\n                     <height>20</height>\n                    </size>\n                   </property>\n                  </spacer>\n                 </item>\n                </layout>\n               </item>\n               <item row=\"2\" column=\"0\">\n                <widget class=\"QLabel\" name=\"label_19\">\n                 <property name=\"minimumSize\">\n                  <size>\n                   <width>100</width>\n                   <height>20</height>\n                  </size>\n                 </property>\n                 <property name=\"text\">\n                  <string>History buffer Size</string>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"0\" column=\"1\">\n                <spacer name=\"horizontalSpacer_28\">\n                 <property name=\"orientation\">\n                  <enum>Qt::Horizontal</enum>\n                 </property>\n                 <property name=\"sizeType\">\n                  <enum>QSizePolicy::Fixed</enum>\n                 </property>\n                 <property name=\"sizeHint\" stdset=\"0\">\n                  <size>\n                   <width>20</width>\n                   <height>20</height>\n                  </size>\n                 </property>\n                </spacer>\n               </item>\n              </layout>\n             </item>\n             <item>\n              <layout class=\"QGridLayout\" name=\"gridLayout_15\">\n               <item row=\"0\" column=\"0\">\n                <widget class=\"QCheckBox\" name=\"terminal_focus_command\">\n                 <property name=\"text\">\n                  <string>Set focus to Command Window when running a command from within another widget</string>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"1\" column=\"0\">\n                <widget class=\"QCheckBox\" name=\"terminal_print_dbg_location\">\n                 <property name=\"text\">\n                  <string>Print debug location in Command Window in addition to the marker in the editor</string>\n                 </property>\n                </widget>\n               </item>\n              </layout>\n             </item>\n             <item>\n              <widget class=\"Line\" name=\"line_7\">\n               <property name=\"orientation\">\n                <enum>Qt::Horizontal</enum>\n               </property>\n              </widget>\n             </item>\n             <item>\n              <widget class=\"QGroupBox\" name=\"terminal_colors_box\">\n               <property name=\"title\">\n                <string>Command Window Colors</string>\n               </property>\n              </widget>\n             </item>\n             <item>\n              <widget class=\"Line\" name=\"line_5\">\n               <property name=\"minimumSize\">\n                <size>\n                 <width>0</width>\n                 <height>0</height>\n                </size>\n               </property>\n               <property name=\"orientation\">\n                <enum>Qt::Horizontal</enum>\n               </property>\n              </widget>\n             </item>\n             <item>\n              <widget class=\"Line\" name=\"line_6\">\n               <property name=\"orientation\">\n                <enum>Qt::Horizontal</enum>\n               </property>\n              </widget>\n             </item>\n            </layout>\n           </item>\n           <item>\n            <spacer name=\"verticalSpacer_3\">\n             <property name=\"orientation\">\n              <enum>Qt::Vertical</enum>\n             </property>\n             <property name=\"sizeType\">\n              <enum>QSizePolicy::Expanding</enum>\n             </property>\n             <property name=\"sizeHint\" stdset=\"0\">\n              <size>\n               <width>20</width>\n               <height>40</height>\n              </size>\n             </property>\n            </spacer>\n           </item>\n          </layout>\n         </widget>\n        </widget>\n       </item>\n      </layout>\n     </widget>\n     <widget class=\"QWidget\" name=\"tab_editor\">\n      <attribute name=\"title\">\n       <string>Editor</string>\n      </attribute>\n      <layout class=\"QVBoxLayout\" name=\"verticalLayout_6\">\n       <item>\n        <widget class=\"QScrollArea\" name=\"tab_editor_scroll_area\">\n         <property name=\"widgetResizable\">\n          <bool>true</bool>\n         </property>\n         <widget class=\"QWidget\" name=\"scrollAreaWidgetContents\">\n          <property name=\"geometry\">\n           <rect>\n            <x>0</x>\n            <y>-828</y>\n            <width>1021</width>\n            <height>1535</height>\n           </rect>\n          </property>\n          <layout class=\"QVBoxLayout\" name=\"verticalLayout_16\">\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_5\">\n             <property name=\"title\">\n              <string>General</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_13\">\n              <item>\n               <layout class=\"QGridLayout\" name=\"editor_common_settings_grid\">\n                <property name=\"topMargin\">\n                 <number>0</number>\n                </property>\n                <item row=\"2\" column=\"2\">\n                 <widget class=\"QCheckBox\" name=\"editor_ws_indent_checkbox\">\n                  <property name=\"enabled\">\n                   <bool>false</bool>\n                  </property>\n                  <property name=\"text\">\n                   <string>Do not show whitespace used for indentation</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"9\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"cb_edit_status_bar\">\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"text\">\n                   <string>Show status bar</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"1\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"editor_showLineNumbers\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"text\">\n                   <string>Show line numbers</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"editor_ws_checkbox\">\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"text\">\n                   <string>Show whitespace</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"8\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"cb_code_folding\">\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"text\">\n                   <string>Enable Code Folding</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"9\" column=\"2\">\n                 <widget class=\"QCheckBox\" name=\"cb_edit_tool_bar\">\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"text\">\n                   <string>Show tool bar</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"8\" column=\"2\">\n                 <widget class=\"QCheckBox\" name=\"cb_show_hscrollbar\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"text\">\n                   <string>Show horizontal scroll bar</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"1\" column=\"2\">\n                 <layout class=\"QGridLayout\" name=\"gridLayout_17\">\n                  <item row=\"0\" column=\"0\">\n                   <widget class=\"QLabel\" name=\"editor_linenr_size_label\">\n                    <property name=\"text\">\n                     <string>Number size as difference to editor font</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"0\" column=\"1\">\n                   <widget class=\"QSpinBox\" name=\"editor_linenr_size\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                    <property name=\"sizePolicy\">\n                     <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                      <horstretch>0</horstretch>\n                      <verstretch>0</verstretch>\n                     </sizepolicy>\n                    </property>\n                    <property name=\"minimum\">\n                     <number>-6</number>\n                    </property>\n                    <property name=\"maximum\">\n                     <number>6</number>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"0\" column=\"2\">\n                   <spacer name=\"horizontalSpacer_9\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>40</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n                <item row=\"3\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"cb_show_eol\">\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"text\">\n                   <string>Show EOL characters</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"1\" column=\"1\">\n                 <spacer name=\"horizontalSpacer_36\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeType\">\n                   <enum>QSizePolicy::Fixed</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>10</width>\n                    <height>0</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"3\" column=\"2\">\n                 <widget class=\"QCheckBox\" name=\"editor_highlightCurrentLine\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"text\">\n                   <string>Highlight current line (color adjustable below with editor styles)</string>\n                  </property>\n                 </widget>\n                </item>\n               </layout>\n              </item>\n              <item>\n               <layout class=\"QHBoxLayout\" name=\"horizontalLayout_22\">\n                <property name=\"topMargin\">\n                 <number>0</number>\n                </property>\n                <item>\n                 <widget class=\"QCheckBox\" name=\"editor_highlight_all_occurrences\">\n                  <property name=\"text\">\n                   <string>Highlight all occurrences of a word selected by a double click</string>\n                  </property>\n                 </widget>\n                </item>\n               </layout>\n              </item>\n              <item>\n               <layout class=\"QHBoxLayout\" name=\"horizontalLayout\">\n                <item>\n                 <widget class=\"QCheckBox\" name=\"useCustomFileEditor\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Fixed\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"text\">\n                   <string>Use custom file editor</string>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <widget class=\"QLabel\" name=\"customEditorLabel\">\n                  <property name=\"enabled\">\n                   <bool>false</bool>\n                  </property>\n                  <property name=\"text\">\n                   <string>command line (%f=file, %l=line):</string>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <widget class=\"QLineEdit\" name=\"customFileEditor\">\n                  <property name=\"enabled\">\n                   <bool>false</bool>\n                  </property>\n                  <property name=\"text\">\n                   <string/>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <spacer name=\"horizontalSpacer_12\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>40</width>\n                    <height>20</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_11\">\n             <property name=\"title\">\n              <string>Tabs</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_32\">\n              <item>\n               <layout class=\"QGridLayout\" name=\"gridLayout_23\">\n                <item row=\"0\" column=\"1\">\n                 <layout class=\"QHBoxLayout\" name=\"horizontalLayout_21\">\n                  <item>\n                   <widget class=\"QComboBox\" name=\"editor_combox_tab_pos\"/>\n                  </item>\n                  <item>\n                   <spacer name=\"horizontalSpacer_25\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeType\">\n                     <enum>QSizePolicy::Fixed</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>20</width>\n                      <height>10</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                  <item>\n                   <widget class=\"QCheckBox\" name=\"editor_cb_tabs_rotated\">\n                    <property name=\"toolTip\">\n                     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rotate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>\n                    </property>\n                    <property name=\"text\">\n                     <string>Rotated tabs</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <spacer name=\"horizontalSpacer_33\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeType\">\n                     <enum>QSizePolicy::Fixed</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>20</width>\n                      <height>10</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n                <item row=\"0\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_30\">\n                  <property name=\"text\">\n                   <string>Position</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"2\">\n                 <layout class=\"QHBoxLayout\" name=\"horizontalLayout_15\">\n                  <item>\n                   <widget class=\"QLabel\" name=\"label_3\">\n                    <property name=\"text\">\n                     <string>Max. tab width in chars (0: no limit)</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <widget class=\"QSpinBox\" name=\"editor_sb_tabs_max_width\">\n                    <property name=\"toolTip\">\n                     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>\n                    </property>\n                    <property name=\"maximum\">\n                     <number>64</number>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <spacer name=\"horizontalSpacer_38\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>40</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_9\">\n             <property name=\"title\">\n              <string>Comments (Octave)</string>\n             </property>\n             <property name=\"checked\">\n              <bool>false</bool>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_24\">\n              <item>\n               <layout class=\"QGridLayout\" name=\"gridLayout_18\">\n                <item row=\"1\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_28\">\n                  <property name=\"text\">\n                   <string>Strings considered for uncommenting text</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"1\">\n                 <spacer name=\"horizontalSpacer_35\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeType\">\n                   <enum>QSizePolicy::Fixed</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>10</width>\n                    <height>10</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"0\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_24\">\n                  <property name=\"text\">\n                   <string>String used for commenting selected text</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"2\">\n                 <layout class=\"QHBoxLayout\" name=\"layout_comment_strings\"/>\n                </item>\n                <item row=\"1\" column=\"2\">\n                 <layout class=\"QHBoxLayout\" name=\"layout_uncomment_strings\"/>\n                </item>\n                <item row=\"0\" column=\"8\">\n                 <spacer name=\"horizontalSpacer_34\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>40</width>\n                    <height>10</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_3\">\n             <property name=\"title\">\n              <string>Long lines</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_23\">\n              <item>\n               <layout class=\"QGridLayout\" name=\"gridLayout_21\">\n                <property name=\"topMargin\">\n                 <number>0</number>\n                </property>\n                <item row=\"2\" column=\"5\">\n                 <layout class=\"QHBoxLayout\" name=\"horizontalLayout_18\">\n                  <item>\n                   <widget class=\"QCheckBox\" name=\"editor_break_checkbox\">\n                    <property name=\"enabled\">\n                     <bool>true</bool>\n                    </property>\n                    <property name=\"sizePolicy\">\n                     <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                      <horstretch>0</horstretch>\n                      <verstretch>0</verstretch>\n                     </sizepolicy>\n                    </property>\n                    <property name=\"toolTip\">\n                     <string>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</string>\n                    </property>\n                    <property name=\"text\">\n                     <string>Break long lines at line length</string>\n                    </property>\n                    <property name=\"checked\">\n                     <bool>false</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <widget class=\"QCheckBox\" name=\"editor_break_comments_checkbox\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                    <property name=\"text\">\n                     <string>Break lines only in comments</string>\n                    </property>\n                    <property name=\"checked\">\n                     <bool>false</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <spacer name=\"horizontalSpacer_17\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>40</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n                <item row=\"0\" column=\"3\">\n                 <spacer name=\"horizontalSpacer_37\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeType\">\n                   <enum>QSizePolicy::Fixed</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>10</width>\n                    <height>0</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"0\" column=\"2\">\n                 <widget class=\"QSpinBox\" name=\"editor_long_line_column\">\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"minimum\">\n                   <number>2</number>\n                  </property>\n                  <property name=\"maximum\">\n                   <number>256</number>\n                  </property>\n                  <property name=\"value\">\n                   <number>80</number>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"1\">\n                 <widget class=\"QLabel\" name=\"editor_long_line_column_text\">\n                  <property name=\"text\">\n                   <string>Line length</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"5\">\n                 <layout class=\"QHBoxLayout\" name=\"horizontalLayout_3\">\n                  <item>\n                   <widget class=\"QCheckBox\" name=\"editor_long_line_marker\">\n                    <property name=\"text\">\n                     <string>Long line marker</string>\n                    </property>\n                    <property name=\"checked\">\n                     <bool>true</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <widget class=\"QRadioButton\" name=\"editor_long_line_marker_line\">\n                    <property name=\"text\">\n                     <string>Line</string>\n                    </property>\n                    <property name=\"checked\">\n                     <bool>true</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <widget class=\"QRadioButton\" name=\"editor_long_line_marker_background\">\n                    <property name=\"text\">\n                     <string>Background</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <spacer name=\"horizontalSpacer_7\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>40</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n               </layout>\n              </item>\n              <item>\n               <layout class=\"QHBoxLayout\" name=\"horizontalLayout_19\">\n                <item>\n                 <widget class=\"QCheckBox\" name=\"editor_wrap_checkbox\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"toolTip\">\n                   <string>This works well for monospaced fonts. The line is drawn at a position based on the width of a space character in the default font. It may not work very well if styles use proportional fonts or if varied font sizes or bold, italic and normal texts are used.</string>\n                  </property>\n                  <property name=\"text\">\n                   <string>Wrap long lines at current window border</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>false</bool>\n                  </property>\n                 </widget>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_6\">\n             <property name=\"title\">\n              <string>Indentation</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_28\">\n              <item>\n               <layout class=\"QGridLayout\" name=\"gridLayout_4\">\n                <item row=\"0\" column=\"2\">\n                 <widget class=\"QSpinBox\" name=\"editor_ind_width_spinbox\">\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"minimum\">\n                   <number>1</number>\n                  </property>\n                  <property name=\"maximum\">\n                   <number>32</number>\n                  </property>\n                  <property name=\"value\">\n                   <number>2</number>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"10\">\n                 <spacer name=\"horizontalSpacer_20\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>40</width>\n                    <height>20</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"0\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_13\">\n                  <property name=\"text\">\n                   <string>Indent width</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"4\">\n                 <widget class=\"QCheckBox\" name=\"editor_tab_ind_checkbox\">\n                  <property name=\"text\">\n                   <string>Tab indents line</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"10\">\n                 <spacer name=\"horizontalSpacer_13\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>40</width>\n                    <height>20</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"0\" column=\"4\">\n                 <widget class=\"QCheckBox\" name=\"editor_auto_ind_checkbox\">\n                  <property name=\"text\">\n                   <string>Auto indentation</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"2\">\n                 <widget class=\"QSpinBox\" name=\"editor_tab_width_spinbox\">\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"minimum\">\n                   <number>1</number>\n                  </property>\n                  <property name=\"maximum\">\n                   <number>32</number>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"0\">\n                 <widget class=\"QLabel\" name=\"label_14\">\n                  <property name=\"text\">\n                   <string>Tab width</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"6\">\n                 <widget class=\"QCheckBox\" name=\"editor_ind_guides_checkbox\">\n                  <property name=\"text\">\n                   <string>Show indentation guides</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"6\">\n                 <widget class=\"QCheckBox\" name=\"editor_bs_unind_checkbox\">\n                  <property name=\"text\">\n                   <string>Backspace unindents line</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"3\">\n                 <spacer name=\"horizontalSpacer_10\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeType\">\n                   <enum>QSizePolicy::Fixed</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>10</width>\n                    <height>0</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"3\" column=\"4\">\n                 <widget class=\"QCheckBox\" name=\"editor_ind_uses_tabs_checkbox\">\n                  <property name=\"text\">\n                   <string>Indentation uses tabs</string>\n                  </property>\n                 </widget>\n                </item>\n               </layout>\n              </item>\n              <item>\n               <layout class=\"QHBoxLayout\" name=\"horizontalLayout_autoclose\">\n                <item>\n                 <widget class=\"QLabel\" name=\"label_auto_endif\">\n                  <property name=\"text\">\n                   <string>Auto insert after &quot;if&quot; etc.</string>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <widget class=\"QComboBox\" name=\"editor_auto_endif\">\n                  <property name=\"sizePolicy\">\n                   <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                    <horstretch>0</horstretch>\n                    <verstretch>0</verstretch>\n                   </sizepolicy>\n                  </property>\n                  <property name=\"sizeAdjustPolicy\">\n                   <enum>QComboBox::AdjustToContents</enum>\n                  </property>\n                  <property name=\"minimumContentsLength\">\n                   <number>5</number>\n                  </property>\n                  <item>\n                   <property name=\"text\">\n                    <string>Nothing</string>\n                   </property>\n                  </item>\n                  <item>\n                   <property name=\"text\">\n                    <string>&quot;endif&quot; etc.</string>\n                   </property>\n                  </item>\n                  <item>\n                   <property name=\"text\">\n                    <string>&quot;end&quot;</string>\n                   </property>\n                  </item>\n                 </widget>\n                </item>\n                <item>\n                 <spacer name=\"horizontalSpacer_autoclose\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeType\">\n                   <enum>QSizePolicy::Expanding</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>10</width>\n                    <height>0</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_7\">\n             <property name=\"title\">\n              <string>Auto completion</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_29\">\n              <item>\n               <layout class=\"QGridLayout\" name=\"gridLayout_3\">\n                <item row=\"0\" column=\"1\">\n                 <spacer name=\"horizontalSpacer_15\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeType\">\n                   <enum>QSizePolicy::Fixed</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>10</width>\n                    <height>0</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"0\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"editor_checkbox_ac_keywords\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"text\">\n                   <string>Match keywords</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"editor_checkbox_ac_case\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"text\">\n                   <string>Case sensitive</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"1\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"editor_checkbox_ac_document\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"text\">\n                   <string>Match words in document</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"2\" column=\"2\">\n                 <widget class=\"QCheckBox\" name=\"editor_checkbox_ac_replace\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"text\">\n                   <string>Replace word by suggested one</string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"3\">\n                 <spacer name=\"horizontalSpacer_8\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>40</width>\n                    <height>20</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"2\" column=\"3\">\n                 <spacer name=\"horizontalSpacer_19\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>40</width>\n                    <height>20</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"0\" column=\"2\">\n                 <layout class=\"QHBoxLayout\" name=\"horizontalLayout_14\">\n                  <item>\n                   <widget class=\"QCheckBox\" name=\"editor_checkbox_ac_builtins\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                    <property name=\"text\">\n                     <string>With Octave builtins</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <widget class=\"QCheckBox\" name=\"editor_checkbox_ac_functions\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                    <property name=\"text\">\n                     <string>With Octave functions</string>\n                    </property>\n                   </widget>\n                  </item>\n                 </layout>\n                </item>\n               </layout>\n              </item>\n              <item>\n               <layout class=\"QGridLayout\" name=\"gridLayout_10\">\n                <item row=\"0\" column=\"2\">\n                 <widget class=\"QLabel\" name=\"editor_label_ac_threshold\">\n                  <property name=\"enabled\">\n                   <bool>false</bool>\n                  </property>\n                  <property name=\"text\">\n                   <string>Number of characters before list is shown: </string>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"3\">\n                 <widget class=\"QSpinBox\" name=\"editor_spinbox_ac_threshold\">\n                  <property name=\"enabled\">\n                   <bool>false</bool>\n                  </property>\n                  <property name=\"toolTip\">\n                   <string/>\n                  </property>\n                  <property name=\"whatsThis\">\n                   <string/>\n                  </property>\n                  <property name=\"suffix\">\n                   <string/>\n                  </property>\n                  <property name=\"minimum\">\n                   <number>1</number>\n                  </property>\n                  <property name=\"maximum\">\n                   <number>6</number>\n                  </property>\n                  <property name=\"value\">\n                   <number>2</number>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"4\">\n                 <spacer name=\"horizontalSpacer_2\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>40</width>\n                    <height>20</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n                <item row=\"0\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"editor_codeCompletion\">\n                  <property name=\"enabled\">\n                   <bool>true</bool>\n                  </property>\n                  <property name=\"text\">\n                   <string>Show completion list automatically</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>false</bool>\n                  </property>\n                 </widget>\n                </item>\n                <item row=\"0\" column=\"1\">\n                 <spacer name=\"horizontalSpacer_31\">\n                  <property name=\"orientation\">\n                   <enum>Qt::Horizontal</enum>\n                  </property>\n                  <property name=\"sizeType\">\n                   <enum>QSizePolicy::Fixed</enum>\n                  </property>\n                  <property name=\"sizeHint\" stdset=\"0\">\n                   <size>\n                    <width>10</width>\n                    <height>0</height>\n                   </size>\n                  </property>\n                 </spacer>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_10\">\n             <property name=\"enabled\">\n              <bool>true</bool>\n             </property>\n             <property name=\"title\">\n              <string>Debugging</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_12\">\n              <item>\n               <layout class=\"QGridLayout\" name=\"gridLayout_19\">\n                <item row=\"0\" column=\"0\">\n                 <widget class=\"QCheckBox\" name=\"editor_show_dbg_file\">\n                  <property name=\"text\">\n                   <string>Always show debug breakpoints and pointers (opens related file if closed)</string>\n                  </property>\n                  <property name=\"checked\">\n                   <bool>true</bool>\n                  </property>\n                 </widget>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_8\">\n             <property name=\"title\">\n              <string>File handling</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_30\">\n              <item>\n               <layout class=\"QVBoxLayout\" name=\"verticalLayout_11\">\n                <property name=\"topMargin\">\n                 <number>0</number>\n                </property>\n                <property name=\"bottomMargin\">\n                 <number>0</number>\n                </property>\n                <item>\n                 <layout class=\"QGridLayout\" name=\"gridLayout_11\">\n                  <property name=\"topMargin\">\n                   <number>0</number>\n                  </property>\n                  <item row=\"13\" column=\"0\">\n                   <layout class=\"QHBoxLayout\" name=\"horizontalLayout_16\">\n                    <item>\n                     <widget class=\"QLabel\" name=\"label_16\">\n                      <property name=\"text\">\n                       <string>Text encoding used for loading and saving</string>\n                      </property>\n                     </widget>\n                    </item>\n                    <item>\n                     <widget class=\"QComboBox\" name=\"editor_combo_encoding\"/>\n                    </item>\n                    <item>\n                     <spacer name=\"horizontalSpacer_32\">\n                      <property name=\"orientation\">\n                       <enum>Qt::Horizontal</enum>\n                      </property>\n                      <property name=\"sizeHint\" stdset=\"0\">\n                       <size>\n                        <width>40</width>\n                        <height>20</height>\n                       </size>\n                      </property>\n                     </spacer>\n                    </item>\n                   </layout>\n                  </item>\n                  <item row=\"1\" column=\"0\">\n                   <widget class=\"QCheckBox\" name=\"editor_restoreSession\">\n                    <property name=\"sizePolicy\">\n                     <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Fixed\">\n                      <horstretch>0</horstretch>\n                      <verstretch>0</verstretch>\n                     </sizepolicy>\n                    </property>\n                    <property name=\"text\">\n                     <string>Restore editor tabs from previous session on startup or when editor is shown again after closing</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"7\" column=\"0\">\n                   <widget class=\"QCheckBox\" name=\"editor_remove_trailing_spaces\">\n                    <property name=\"text\">\n                     <string>Remove trailing spaces when saving file</string>\n                    </property>\n                    <property name=\"checked\">\n                     <bool>true</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"6\" column=\"0\">\n                   <widget class=\"QCheckBox\" name=\"editor_force_newline\">\n                    <property name=\"text\">\n                     <string>Force newline at end when saving file</string>\n                    </property>\n                    <property name=\"checked\">\n                     <bool>true</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"3\" column=\"0\">\n                   <widget class=\"QCheckBox\" name=\"editor_create_new file\">\n                    <property name=\"sizePolicy\">\n                     <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Fixed\">\n                      <horstretch>0</horstretch>\n                      <verstretch>0</verstretch>\n                     </sizepolicy>\n                    </property>\n                    <property name=\"text\">\n                     <string>Create nonexistent files without prompting</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"10\" column=\"0\">\n                   <widget class=\"QCheckBox\" name=\"editor_hiding_closes_files\">\n                    <property name=\"text\">\n                     <string>Close all files when the editor widget is closed/hidden</string>\n                    </property>\n                    <property name=\"checked\">\n                     <bool>true</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"4\" column=\"0\">\n                   <widget class=\"QCheckBox\" name=\"editor_reload_changed_files\">\n                    <property name=\"text\">\n                     <string>Reload externally changed files without prompt</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"11\" column=\"0\">\n                   <layout class=\"QHBoxLayout\" name=\"horizontalLayout_2\">\n                    <property name=\"topMargin\">\n                     <number>0</number>\n                    </property>\n                    <item>\n                     <widget class=\"QLabel\" name=\"label_22\">\n                      <property name=\"text\">\n                       <string>Default EOL mode</string>\n                      </property>\n                     </widget>\n                    </item>\n                    <item>\n                     <widget class=\"QComboBox\" name=\"combo_eol_mode\">\n                      <property name=\"sizePolicy\">\n                       <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                        <horstretch>0</horstretch>\n                        <verstretch>0</verstretch>\n                       </sizepolicy>\n                      </property>\n                      <property name=\"sizeAdjustPolicy\">\n                       <enum>QComboBox::AdjustToContents</enum>\n                      </property>\n                      <property name=\"minimumContentsLength\">\n                       <number>7</number>\n                      </property>\n                      <item>\n                       <property name=\"text\">\n                        <string>Windows (CRLF)</string>\n                       </property>\n                      </item>\n                      <item>\n                       <property name=\"text\">\n                        <string>Legacy Mac (CR)</string>\n                       </property>\n                      </item>\n                      <item>\n                       <property name=\"text\">\n                        <string>Unix (LF)</string>\n                       </property>\n                      </item>\n                     </widget>\n                    </item>\n                    <item>\n                     <spacer name=\"horizontalSpacer_18\">\n                      <property name=\"orientation\">\n                       <enum>Qt::Horizontal</enum>\n                      </property>\n                      <property name=\"sizeHint\" stdset=\"0\">\n                       <size>\n                        <width>40</width>\n                        <height>20</height>\n                       </size>\n                      </property>\n                     </spacer>\n                    </item>\n                   </layout>\n                  </item>\n                  <item row=\"5\" column=\"0\">\n                   <widget class=\"QCheckBox\" name=\"editor_open_dlg_follows_file\">\n                    <property name=\"text\">\n                     <string>Directory of open file dialog follows current editor file instead of current Octave directory </string>\n                    </property>\n                   </widget>\n                  </item>\n                 </layout>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"group_box_editor_styles\">\n             <property name=\"enabled\">\n              <bool>true</bool>\n             </property>\n             <property name=\"autoFillBackground\">\n              <bool>false</bool>\n             </property>\n             <property name=\"title\">\n              <string>Editor Styles</string>\n             </property>\n             <property name=\"alignment\">\n              <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_31\">\n              <item>\n               <layout class=\"QVBoxLayout\" name=\"editor_styles_layout\">\n                <property name=\"bottomMargin\">\n                 <number>8</number>\n                </property>\n               </layout>\n              </item>\n              <item>\n               <widget class=\"QLabel\" name=\"label_23\">\n                <property name=\"text\">\n                 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>\n                </property>\n                <property name=\"wordWrap\">\n                 <bool>true</bool>\n                </property>\n               </widget>\n              </item>\n              <item>\n               <widget class=\"QTabWidget\" name=\"tabs_editor_lexers\">\n                <property name=\"sizePolicy\">\n                 <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Expanding\">\n                  <horstretch>0</horstretch>\n                  <verstretch>0</verstretch>\n                 </sizepolicy>\n                </property>\n               </widget>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <spacer name=\"verticalSpacer_7\">\n             <property name=\"orientation\">\n              <enum>Qt::Vertical</enum>\n             </property>\n             <property name=\"sizeHint\" stdset=\"0\">\n              <size>\n               <width>20</width>\n               <height>20</height>\n              </size>\n             </property>\n            </spacer>\n           </item>\n          </layout>\n         </widget>\n        </widget>\n       </item>\n      </layout>\n     </widget>\n     <widget class=\"QWidget\" name=\"tab_file_browser\">\n      <attribute name=\"title\">\n       <string>File Browser</string>\n      </attribute>\n      <layout class=\"QVBoxLayout\" name=\"verticalLayout_3\">\n       <item>\n        <widget class=\"QScrollArea\" name=\"scrollArea_4\">\n         <property name=\"widgetResizable\">\n          <bool>true</bool>\n         </property>\n         <widget class=\"QWidget\" name=\"scrollAreaWidgetContents_5\">\n          <property name=\"geometry\">\n           <rect>\n            <x>0</x>\n            <y>0</y>\n            <width>1035</width>\n            <height>567</height>\n           </rect>\n          </property>\n          <layout class=\"QGridLayout\" name=\"gridLayout_8\">\n           <item row=\"0\" column=\"0\">\n            <widget class=\"QGroupBox\" name=\"groupBox_4\">\n             <property name=\"title\">\n              <string>Behavior</string>\n             </property>\n             <layout class=\"QGridLayout\" name=\"gridLayout_2\">\n              <item row=\"0\" column=\"0\">\n               <layout class=\"QVBoxLayout\" name=\"verticalLayout_18\">\n                <item>\n                 <widget class=\"QCheckBox\" name=\"sync_octave_directory\">\n                  <property name=\"text\">\n                   <string>Synchronize Octave working directory with file browser</string>\n                  </property>\n                 </widget>\n                </item>\n                <item>\n                 <layout class=\"QGridLayout\" name=\"lo_file_browser_startup\">\n                  <item row=\"0\" column=\"1\">\n                   <layout class=\"QGridLayout\" name=\"gridLayout_22\">\n                    <property name=\"topMargin\">\n                     <number>0</number>\n                    </property>\n                    <item row=\"0\" column=\"0\">\n                     <widget class=\"QCheckBox\" name=\"cb_restore_file_browser_dir\">\n                      <property name=\"text\">\n                       <string>Restore last directory of previous session</string>\n                      </property>\n                     </widget>\n                    </item>\n                    <item row=\"1\" column=\"0\">\n                     <widget class=\"QLineEdit\" name=\"le_file_browser_dir\">\n                      <property name=\"sizePolicy\">\n                       <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Preferred\">\n                        <horstretch>0</horstretch>\n                        <verstretch>0</verstretch>\n                       </sizepolicy>\n                      </property>\n                     </widget>\n                    </item>\n                    <item row=\"1\" column=\"1\">\n                     <widget class=\"QPushButton\" name=\"pb_file_browser_dir\">\n                      <property name=\"sizePolicy\">\n                       <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Fixed\">\n                        <horstretch>0</horstretch>\n                        <verstretch>0</verstretch>\n                       </sizepolicy>\n                      </property>\n                      <property name=\"text\">\n                       <string>Browse</string>\n                      </property>\n                     </widget>\n                    </item>\n                   </layout>\n                  </item>\n                  <item row=\"0\" column=\"0\">\n                   <widget class=\"QLabel\" name=\"lbl_file_browser_dir\">\n                    <property name=\"text\">\n                     <string>Initial file browser directory (only if not synchronized with initial working directory of Octave)</string>\n                    </property>\n                    <property name=\"alignment\">\n                     <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>\n                    </property>\n                    <property name=\"wordWrap\">\n                     <bool>true</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"0\" column=\"3\">\n                   <spacer name=\"horizontalSpacer_29\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>20</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n                <item>\n                 <layout class=\"QVBoxLayout\" name=\"verticalLayout_9\">\n                  <item alignment=\"Qt::AlignTop\">\n                   <widget class=\"QLabel\" name=\"lbl_file_browser_extensions\">\n                    <property name=\"sizePolicy\">\n                     <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                      <horstretch>0</horstretch>\n                      <verstretch>0</verstretch>\n                     </sizepolicy>\n                    </property>\n                    <property name=\"text\">\n                     <string>Extensions of files to be opened in the default text editor (separated by &quot;;&quot;):</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item>\n                   <widget class=\"QLineEdit\" name=\"le_file_browser_extensions\">\n                    <property name=\"text\">\n                     <string/>\n                    </property>\n                   </widget>\n                  </item>\n                 </layout>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item row=\"1\" column=\"0\">\n            <spacer name=\"verticalSpacer_2\">\n             <property name=\"orientation\">\n              <enum>Qt::Vertical</enum>\n             </property>\n             <property name=\"sizeHint\" stdset=\"0\">\n              <size>\n               <width>20</width>\n               <height>100</height>\n              </size>\n             </property>\n            </spacer>\n           </item>\n          </layout>\n         </widget>\n        </widget>\n       </item>\n      </layout>\n     </widget>\n     <widget class=\"QWidget\" name=\"tab_workspace\">\n      <attribute name=\"title\">\n       <string>Workspace</string>\n      </attribute>\n      <layout class=\"QVBoxLayout\" name=\"verticalLayout_15\">\n       <item>\n        <widget class=\"QScrollArea\" name=\"scrollArea_5\">\n         <property name=\"widgetResizable\">\n          <bool>true</bool>\n         </property>\n         <widget class=\"QWidget\" name=\"scrollAreaWidgetContents_6\">\n          <property name=\"geometry\">\n           <rect>\n            <x>0</x>\n            <y>0</y>\n            <width>1035</width>\n            <height>567</height>\n           </rect>\n          </property>\n          <layout class=\"QVBoxLayout\" name=\"verticalLayout_19\">\n           <item>\n            <layout class=\"QGridLayout\" name=\"gridLayout_14\">\n             <property name=\"topMargin\">\n              <number>0</number>\n             </property>\n             <item row=\"0\" column=\"0\">\n              <widget class=\"QGroupBox\" name=\"workspace_colors_box\">\n               <property name=\"enabled\">\n                <bool>true</bool>\n               </property>\n               <property name=\"sizePolicy\">\n                <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n                 <horstretch>0</horstretch>\n                 <verstretch>0</verstretch>\n                </sizepolicy>\n               </property>\n               <property name=\"title\">\n                <string>Colors for variable attributes</string>\n               </property>\n              </widget>\n             </item>\n            </layout>\n           </item>\n           <item>\n            <spacer name=\"verticalSpacer_6\">\n             <property name=\"orientation\">\n              <enum>Qt::Vertical</enum>\n             </property>\n             <property name=\"sizeHint\" stdset=\"0\">\n              <size>\n               <width>20</width>\n               <height>40</height>\n              </size>\n             </property>\n            </spacer>\n           </item>\n          </layout>\n         </widget>\n        </widget>\n       </item>\n      </layout>\n     </widget>\n     <widget class=\"QWidget\" name=\"tab_varedit\">\n      <attribute name=\"title\">\n       <string>Variable Editor</string>\n      </attribute>\n      <layout class=\"QVBoxLayout\" name=\"verticalLayout_ve_manual\">\n       <item>\n        <widget class=\"QScrollArea\" name=\"scrollArea_8\">\n         <property name=\"widgetResizable\">\n          <bool>true</bool>\n         </property>\n         <widget class=\"QWidget\" name=\"scrollAreaWidgetContents_3\">\n          <property name=\"geometry\">\n           <rect>\n            <x>0</x>\n            <y>0</y>\n            <width>1035</width>\n            <height>567</height>\n           </rect>\n          </property>\n          <layout class=\"QVBoxLayout\" name=\"verticalLayout_vesc_manual\">\n           <property name=\"geometry\" stdset=\"0\">\n            <rect>\n             <x>0</x>\n             <y>0</y>\n             <width>678</width>\n             <height>384</height>\n            </rect>\n           </property>\n           <item>\n            <layout class=\"QVBoxLayout\" name=\"verticalLayout_ve\">\n             <item>\n              <layout class=\"QGridLayout\" name=\"gridLayout_ve\">\n               <item row=\"1\" column=\"3\">\n                <widget class=\"QLabel\" name=\"label_26\">\n                 <property name=\"text\">\n                  <string>Font size</string>\n                 </property>\n                 <property name=\"alignment\">\n                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"4\" column=\"0\">\n                <widget class=\"QLabel\" name=\"label_27\">\n                 <property name=\"text\">\n                  <string>Default row height</string>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"3\" column=\"0\">\n                <widget class=\"QLabel\" name=\"label_ve_colwidth\">\n                 <property name=\"text\">\n                  <string>Default column width</string>\n                 </property>\n                 <property name=\"alignment\">\n                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"1\" column=\"4\">\n                <widget class=\"QSpinBox\" name=\"varedit_fontSize\">\n                 <property name=\"value\">\n                  <number>10</number>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"1\" column=\"1\" colspan=\"2\">\n                <widget class=\"QFontComboBox\" name=\"varedit_font\">\n                 <property name=\"currentFont\">\n                  <font>\n                   <family>Liberation Mono</family>\n                  </font>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"4\" column=\"6\">\n                <spacer name=\"horizontalSpacer_ve\">\n                 <property name=\"orientation\">\n                  <enum>Qt::Horizontal</enum>\n                 </property>\n                 <property name=\"sizeHint\" stdset=\"0\">\n                  <size>\n                   <width>40</width>\n                   <height>20</height>\n                  </size>\n                 </property>\n                </spacer>\n               </item>\n               <item row=\"4\" column=\"1\">\n                <widget class=\"QSpinBox\" name=\"varedit_rowHeight\">\n                 <property name=\"value\">\n                  <number>10</number>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"3\" column=\"1\">\n                <widget class=\"QSpinBox\" name=\"varedit_columnWidth\">\n                 <property name=\"maximum\">\n                  <number>500</number>\n                 </property>\n                 <property name=\"value\">\n                  <number>100</number>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"0\" column=\"1\">\n                <widget class=\"QCheckBox\" name=\"varedit_useTerminalFont\">\n                 <property name=\"text\">\n                  <string>Use Command Window font</string>\n                 </property>\n                 <property name=\"checked\">\n                  <bool>true</bool>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"0\" column=\"0\">\n                <widget class=\"QLabel\" name=\"label_25\">\n                 <property name=\"text\">\n                  <string>Font</string>\n                 </property>\n                 <property name=\"alignment\">\n                  <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>\n                 </property>\n                </widget>\n               </item>\n              </layout>\n             </item>\n             <item>\n              <widget class=\"QGroupBox\" name=\"varedit_colors_box\">\n               <property name=\"title\">\n                <string>Variable Editor Colors</string>\n               </property>\n              </widget>\n             </item>\n            </layout>\n           </item>\n           <item>\n            <widget class=\"QCheckBox\" name=\"varedit_alternate\">\n             <property name=\"enabled\">\n              <bool>true</bool>\n             </property>\n             <property name=\"text\">\n              <string>Use alternating row colors</string>\n             </property>\n            </widget>\n           </item>\n           <item>\n            <spacer name=\"verticalSpacer_4\">\n             <property name=\"orientation\">\n              <enum>Qt::Vertical</enum>\n             </property>\n             <property name=\"sizeHint\" stdset=\"0\">\n              <size>\n               <width>20</width>\n               <height>40</height>\n              </size>\n             </property>\n            </spacer>\n           </item>\n          </layout>\n         </widget>\n        </widget>\n       </item>\n      </layout>\n     </widget>\n     <widget class=\"QWidget\" name=\"tab_shortcuts\">\n      <attribute name=\"title\">\n       <string>Shortcuts</string>\n      </attribute>\n      <layout class=\"QVBoxLayout\" name=\"verticalLayout_27\">\n       <item>\n        <widget class=\"QScrollArea\" name=\"scrollArea_7\">\n         <property name=\"widgetResizable\">\n          <bool>true</bool>\n         </property>\n         <widget class=\"QWidget\" name=\"scrollAreaWidgetContents_8\">\n          <property name=\"geometry\">\n           <rect>\n            <x>0</x>\n            <y>0</y>\n            <width>1035</width>\n            <height>567</height>\n           </rect>\n          </property>\n          <layout class=\"QVBoxLayout\" name=\"verticalLayout_25\">\n           <item>\n            <layout class=\"QVBoxLayout\" name=\"verticalLayout_26\">\n             <property name=\"sizeConstraint\">\n              <enum>QLayout::SetDefaultConstraint</enum>\n             </property>\n             <property name=\"topMargin\">\n              <number>0</number>\n             </property>\n             <item>\n              <layout class=\"QVBoxLayout\" name=\"verticalLayout_36\">\n               <property name=\"topMargin\">\n                <number>6</number>\n               </property>\n              </layout>\n             </item>\n             <item>\n              <layout class=\"QGridLayout\" name=\"gridLayout_6\">\n               <item row=\"0\" column=\"0\">\n                <widget class=\"QCheckBox\" name=\"cb_prevent_readline_conflicts\">\n                 <property name=\"toolTip\">\n                  <string>Disable global shortcuts in order to prevent\ninterference with readline key strokes.\nExceptions: Ctrl-C for interrupting the interpreter\nand the shortcuts for switching to other widgets.</string>\n                 </property>\n                 <property name=\"text\">\n                  <string>Disable global shortcuts when Command Window has focus</string>\n                 </property>\n                 <property name=\"checked\">\n                  <bool>true</bool>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"1\" column=\"0\">\n                <widget class=\"QCheckBox\" name=\"cb_prevent_readline_conflicts_menu\">\n                 <property name=\"toolTip\">\n                  <string>Disable menu accelerators in order to prevent\ninterference with readline key strokes.</string>\n                 </property>\n                 <property name=\"text\">\n                  <string>Disable menu accelerators of main window menus when Command Window has focus</string>\n                 </property>\n                </widget>\n               </item>\n              </layout>\n             </item>\n             <item>\n              <widget class=\"Line\" name=\"line_9\">\n               <property name=\"orientation\">\n                <enum>Qt::Horizontal</enum>\n               </property>\n              </widget>\n             </item>\n             <item>\n              <layout class=\"QGridLayout\" name=\"gridLayout_12\">\n               <property name=\"topMargin\">\n                <number>10</number>\n               </property>\n               <property name=\"bottomMargin\">\n                <number>10</number>\n               </property>\n               <item row=\"0\" column=\"3\">\n                <spacer name=\"horizontalSpacer_26\">\n                 <property name=\"orientation\">\n                  <enum>Qt::Horizontal</enum>\n                 </property>\n                 <property name=\"sizeHint\" stdset=\"0\">\n                  <size>\n                   <width>40</width>\n                   <height>20</height>\n                  </size>\n                 </property>\n                </spacer>\n               </item>\n               <item row=\"0\" column=\"0\">\n                <widget class=\"QPushButton\" name=\"btn_import_shortcut_set\">\n                 <property name=\"toolTip\">\n                  <string>Import shortcut set</string>\n                 </property>\n                 <property name=\"text\">\n                  <string>Import</string>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"0\" column=\"1\">\n                <widget class=\"QPushButton\" name=\"btn_export_shortcut_set\">\n                 <property name=\"toolTip\">\n                  <string>Export current shortcut set</string>\n                 </property>\n                 <property name=\"text\">\n                  <string>Export</string>\n                 </property>\n                </widget>\n               </item>\n               <item row=\"0\" column=\"2\">\n                <widget class=\"QPushButton\" name=\"btn_default_shortcut_set\">\n                 <property name=\"toolTip\">\n                  <string>Reset shortcuts to their defaults</string>\n                 </property>\n                 <property name=\"text\">\n                  <string>Default</string>\n                 </property>\n                </widget>\n               </item>\n              </layout>\n             </item>\n             <item>\n              <widget class=\"QLabel\" name=\"label_21\">\n               <property name=\"text\">\n                <string>Edit a shortcut by double-clicking in Actual column</string>\n               </property>\n              </widget>\n             </item>\n             <item>\n              <layout class=\"QHBoxLayout\" name=\"horizontalLayout_10\">\n               <property name=\"topMargin\">\n                <number>0</number>\n               </property>\n               <item>\n                <widget class=\"octave::shortcuts_tree_widget\" name=\"shortcuts_treewidget\">\n                 <property name=\"sizePolicy\">\n                  <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Expanding\">\n                   <horstretch>0</horstretch>\n                   <verstretch>0</verstretch>\n                  </sizepolicy>\n                 </property>\n                 <property name=\"sizeIncrement\">\n                  <size>\n                   <width>0</width>\n                   <height>0</height>\n                  </size>\n                 </property>\n                 <property name=\"baseSize\">\n                  <size>\n                   <width>0</width>\n                   <height>0</height>\n                  </size>\n                 </property>\n                 <property name=\"alternatingRowColors\">\n                  <bool>true</bool>\n                 </property>\n                 <property name=\"animated\">\n                  <bool>false</bool>\n                 </property>\n                 <property name=\"allColumnsShowFocus\">\n                  <bool>false</bool>\n                 </property>\n                 <property name=\"headerHidden\">\n                  <bool>false</bool>\n                 </property>\n                 <property name=\"columnCount\">\n                  <number>3</number>\n                 </property>\n                 <attribute name=\"headerCascadingSectionResizes\">\n                  <bool>false</bool>\n                 </attribute>\n                 <attribute name=\"headerMinimumSectionSize\">\n                  <number>64</number>\n                 </attribute>\n                 <attribute name=\"headerDefaultSectionSize\">\n                  <number>120</number>\n                 </attribute>\n                 <attribute name=\"headerHighlightSections\">\n                  <bool>false</bool>\n                 </attribute>\n                 <attribute name=\"headerStretchLastSection\">\n                  <bool>true</bool>\n                 </attribute>\n                 <column>\n                  <property name=\"text\">\n                   <string>Action</string>\n                  </property>\n                  <property name=\"font\">\n                   <font>\n                    <italic>false</italic>\n                   </font>\n                  </property>\n                 </column>\n                 <column>\n                  <property name=\"text\">\n                   <string>Default</string>\n                  </property>\n                 </column>\n                 <column>\n                  <property name=\"text\">\n                   <string>Actual</string>\n                  </property>\n                 </column>\n                </widget>\n               </item>\n              </layout>\n             </item>\n            </layout>\n           </item>\n          </layout>\n         </widget>\n        </widget>\n       </item>\n      </layout>\n     </widget>\n     <widget class=\"QWidget\" name=\"tab_network\">\n      <attribute name=\"title\">\n       <string>Network</string>\n      </attribute>\n      <layout class=\"QVBoxLayout\" name=\"verticalLayout_4\">\n       <item>\n        <widget class=\"QScrollArea\" name=\"scrollArea_6\">\n         <property name=\"widgetResizable\">\n          <bool>true</bool>\n         </property>\n         <widget class=\"QWidget\" name=\"scrollAreaWidgetContents_7\">\n          <property name=\"geometry\">\n           <rect>\n            <x>0</x>\n            <y>0</y>\n            <width>1035</width>\n            <height>567</height>\n           </rect>\n          </property>\n          <layout class=\"QVBoxLayout\" name=\"verticalLayout_20\">\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_12\">\n             <property name=\"title\">\n              <string>General</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_33\">\n              <item>\n               <widget class=\"QCheckBox\" name=\"checkbox_allow_web_connect\">\n                <property name=\"text\">\n                 <string>Allow Octave to connect to the Octave web site to display current news and information</string>\n                </property>\n               </widget>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <widget class=\"QGroupBox\" name=\"groupBox_13\">\n             <property name=\"title\">\n              <string>Proxy Server</string>\n             </property>\n             <layout class=\"QVBoxLayout\" name=\"verticalLayout_34\">\n              <item>\n               <layout class=\"QVBoxLayout\" name=\"verticalLayout\">\n                <item>\n                 <layout class=\"QGridLayout\" name=\"gridLayout_5\">\n                  <item row=\"1\" column=\"2\">\n                   <widget class=\"QLabel\" name=\"proxy_host_name_label\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                    <property name=\"text\">\n                     <string>Hostname:</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"0\" column=\"3\">\n                   <widget class=\"QComboBox\" name=\"proxy_type\">\n                    <property name=\"enabled\">\n                     <bool>true</bool>\n                    </property>\n                    <property name=\"toolTip\">\n                     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"3\" column=\"2\">\n                   <widget class=\"QLabel\" name=\"proxy_username_label\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                    <property name=\"text\">\n                     <string>Username:</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"0\" column=\"2\">\n                   <widget class=\"QLabel\" name=\"proxy_type_label\">\n                    <property name=\"enabled\">\n                     <bool>true</bool>\n                    </property>\n                    <property name=\"text\">\n                     <string>Proxy type:</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"2\" column=\"2\">\n                   <widget class=\"QLabel\" name=\"proxy_port_label\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                    <property name=\"text\">\n                     <string>Port:</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"4\" column=\"2\">\n                   <widget class=\"QLabel\" name=\"proxy_password_label\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                    <property name=\"text\">\n                     <string>Password:</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"1\" column=\"3\">\n                   <widget class=\"QLineEdit\" name=\"proxy_host_name\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"2\" column=\"3\">\n                   <widget class=\"QLineEdit\" name=\"proxy_port\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"3\" column=\"3\">\n                   <widget class=\"QLineEdit\" name=\"proxy_username\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"4\" column=\"3\">\n                   <widget class=\"QLineEdit\" name=\"proxy_password\">\n                    <property name=\"enabled\">\n                     <bool>false</bool>\n                    </property>\n                    <property name=\"echoMode\">\n                     <enum>QLineEdit::Password</enum>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"0\" column=\"0\">\n                   <widget class=\"QCheckBox\" name=\"use_proxy_server\">\n                    <property name=\"text\">\n                     <string>Use proxy server</string>\n                    </property>\n                   </widget>\n                  </item>\n                  <item row=\"0\" column=\"1\">\n                   <spacer name=\"horizontalSpacer_30\">\n                    <property name=\"orientation\">\n                     <enum>Qt::Horizontal</enum>\n                    </property>\n                    <property name=\"sizeType\">\n                     <enum>QSizePolicy::Fixed</enum>\n                    </property>\n                    <property name=\"sizeHint\" stdset=\"0\">\n                     <size>\n                      <width>20</width>\n                      <height>20</height>\n                     </size>\n                    </property>\n                   </spacer>\n                  </item>\n                 </layout>\n                </item>\n               </layout>\n              </item>\n             </layout>\n            </widget>\n           </item>\n           <item>\n            <spacer name=\"verticalSpacer_5\">\n             <property name=\"orientation\">\n              <enum>Qt::Vertical</enum>\n             </property>\n             <property name=\"sizeHint\" stdset=\"0\">\n              <size>\n               <width>20</width>\n               <height>40</height>\n              </size>\n             </property>\n            </spacer>\n           </item>\n          </layout>\n         </widget>\n        </widget>\n       </item>\n      </layout>\n     </widget>\n    </widget>\n   </item>\n   <item>\n    <layout class=\"QHBoxLayout\" name=\"horizontalLayout_20\">\n     <item>\n      <spacer name=\"horizontalSpacer_4\">\n       <property name=\"orientation\">\n        <enum>Qt::Horizontal</enum>\n       </property>\n       <property name=\"sizeHint\" stdset=\"0\">\n        <size>\n         <width>40</width>\n         <height>20</height>\n        </size>\n       </property>\n      </spacer>\n     </item>\n     <item>\n      <widget class=\"QDialogButtonBox\" name=\"button_box\">\n       <property name=\"sizePolicy\">\n        <sizepolicy hsizetype=\"Maximum\" vsizetype=\"Fixed\">\n         <horstretch>0</horstretch>\n         <verstretch>0</verstretch>\n        </sizepolicy>\n       </property>\n       <property name=\"toolTip\">\n        <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</string>\n       </property>\n       <property name=\"standardButtons\">\n        <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>\n       </property>\n      </widget>\n     </item>\n    </layout>\n   </item>\n  </layout>\n </widget>\n <customwidgets>\n  <customwidget>\n   <class>octave::shortcuts_tree_widget</class>\n   <extends>QTreeWidget</extends>\n   <header>shortcuts-tree-widget.h</header>\n  </customwidget>\n </customwidgets>\n <resources/>\n <connections>\n  <connection>\n   <sender>useCustomFileEditor</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>customFileEditor</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>111</x>\n     <y>62</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>343</x>\n     <y>63</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>useCustomFileEditor</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>customEditorLabel</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>349</x>\n     <y>383</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>111</x>\n     <y>413</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_ws_checkbox</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_ws_indent_checkbox</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>85</x>\n     <y>119</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>282</x>\n     <y>119</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_widget_custom_style</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>label_bgtitle</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>228</x>\n     <y>156</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>380</x>\n     <y>156</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_codeCompletion</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_spinbox_ac_threshold</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>83</x>\n     <y>223</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>412</x>\n     <y>223</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_codeCompletion</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_label_ac_threshold</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>83</x>\n     <y>223</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>288</x>\n     <y>223</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_widget_custom_style</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>label_fgtitle</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>228</x>\n     <y>156</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>496</x>\n     <y>156</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_restore_octave_dir</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>le_octave_dir</receiver>\n   <slot>setDisabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>270</x>\n     <y>255</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>270</x>\n     <y>285</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_restore_octave_dir</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>pb_octave_dir</receiver>\n   <slot>setDisabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>270</x>\n     <y>255</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>467</x>\n     <y>285</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_restore_file_browser_dir</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>le_file_browser_dir</receiver>\n   <slot>setDisabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>250</x>\n     <y>294</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>250</x>\n     <y>324</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_restore_file_browser_dir</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>pb_file_browser_dir</receiver>\n   <slot>setDisabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>250</x>\n     <y>294</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>426</x>\n     <y>324</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_checkbox_ac_keywords</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_checkbox_ac_builtins</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>118</x>\n     <y>231</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>296</x>\n     <y>231</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_checkbox_ac_keywords</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_checkbox_ac_functions</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>118</x>\n     <y>231</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>446</x>\n     <y>231</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_widget_custom_style</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>label_3d_title</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>260</x>\n     <y>186</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>419</x>\n     <y>236</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_widget_custom_style</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>label_fgtitle_active</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>260</x>\n     <y>190</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>533</x>\n     <y>214</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_widget_custom_style</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>label_bgtitle_active</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>260</x>\n     <y>190</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>525</x>\n     <y>190</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>cb_widget_custom_style</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>sb_3d_title</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>260</x>\n     <y>186</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>507</x>\n     <y>236</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_break_checkbox</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_break_comments_checkbox</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>286</x>\n     <y>446</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>483</x>\n     <y>446</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_showLineNumbers</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_linenr_size_label</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>161</x>\n     <y>124</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>377</x>\n     <y>124</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_showLineNumbers</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_linenr_size</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>161</x>\n     <y>124</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>488</x>\n     <y>124</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_long_line_marker</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_long_line_marker_line</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>252</x>\n     <y>397</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>346</x>\n     <y>397</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>editor_long_line_marker</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>editor_long_line_marker_background</receiver>\n   <slot>setEnabled(bool)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>252</x>\n     <y>397</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>428</x>\n     <y>397</y>\n    </hint>\n   </hints>\n  </connection>\n </connections>\n</ui>\n"
  },
  {
    "path": "libgui/src/shortcuts-tree-widget.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2014-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QApplication>\n#include <QDialog>\n#include <QDialogButtonBox>\n#include <QGridLayout>\n#include <QHeaderView>\n#include <QKeyEvent>\n#include <QLabel>\n#include <QMessageBox>\n#include <QPushButton>\n#include <QVBoxLayout>\n\n#include \"gui-preferences-sc.h\"\n#include \"gui-settings.h\"\n#include \"shortcuts-tree-widget.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// enter_shortcut:\n// class derived from QLineEdit for directly entering key sequences which\n\nenter_shortcut::enter_shortcut (QWidget *p) : QLineEdit (p)\n{\n  m_direct_shortcut = true;      // the shortcut is directly entered\n  m_shift_modifier = false;      // the shift modifier is not added\n}\n\n// new keyPressEvent\nvoid\nenter_shortcut::keyPressEvent (QKeyEvent *e)\n{\n  if (! m_direct_shortcut)\n    {\n      QLineEdit::keyPressEvent (e);\n      return;\n    }\n\n  if (e->type () == QEvent::KeyPress)\n    {\n      int key = e->key ();\n\n      if (key == Qt::Key_unknown || key == 0)\n        return;\n\n      Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers (); //e->modifiers ();\n\n      if (m_shift_modifier || (modifiers & Qt::ShiftModifier))\n        key |= Qt::SHIFT;\n      if (modifiers & Qt::ControlModifier)\n        key |= Qt::CTRL;\n      if (modifiers & Qt::AltModifier)\n        key |= Qt::ALT;\n      if (modifiers & Qt::MetaModifier)\n        key |= Qt::META;\n\n      setText (QKeySequence (key).toString (QKeySequence::NativeText));\n    }\n}\n\n// slot for checkbox whether the shortcut is directly entered or not\nvoid\nenter_shortcut::handle_direct_shortcut (int state)\n{\n  if (state)\n    m_direct_shortcut = true;  // the shortcut is directly entered\n  else\n    m_direct_shortcut = false; // the shortcut has to be written as text\n}\n\n// slot for checkbox whether the shift modifier should be added\nvoid\nenter_shortcut::handle_shift_modifier (int state)\n{\n  if (state)\n    m_shift_modifier = true;  // the shortcut is directly entered\n  else\n    m_shift_modifier = false; // the shortcut has to be written as text\n}\n\ntree_widget_shortcut_item::tree_widget_shortcut_item\n(QTreeWidgetItem *parent, const sc_pref& scpref, const QString& actual_text)\n  : QTreeWidgetItem (parent), m_settings_key (scpref.settings_key ())\n{\n  // set a slightly transparent foreground for default columns\n  QColor fg = QColor (foreground (DEFAULT_COLUMN).color ());\n  fg.setAlpha (128);\n  setForeground (DEFAULT_COLUMN, QBrush (fg));\n\n  // write the shortcuts\n  set_description (scpref.description ());\n  set_default_text (scpref.def_text ());\n  set_actual_text (actual_text);\n}\n\nQString\ntree_widget_shortcut_item::settings_key () const\n{\n  return m_settings_key;\n}\n\nQString\ntree_widget_shortcut_item::description () const\n{\n  return text (DESCRIPTION_COLUMN);\n}\n\nvoid\ntree_widget_shortcut_item::set_description (const QString& text)\n{\n  setText (DESCRIPTION_COLUMN, text);\n}\n\nQString\ntree_widget_shortcut_item::default_text () const\n{\n  return text (DEFAULT_COLUMN);\n}\n\nvoid\ntree_widget_shortcut_item::set_default_text (const QString& text)\n{\n  setText (DEFAULT_COLUMN, text);\n}\n\nQString\ntree_widget_shortcut_item::actual_text () const\n{\n  return text (ACTUAL_COLUMN);\n}\n\nvoid\ntree_widget_shortcut_item::set_actual_text (const QString& text)\n{\n  setText (ACTUAL_COLUMN, text);\n}\n\nshortcut_edit_dialog::shortcut_edit_dialog\n  (tree_widget_shortcut_item *shortcut_item, QWidget *parent)\n  : QDialog (parent), m_shortcut_item (shortcut_item),\n    m_settings_key (shortcut_item->settings_key ())\n{\n  setAttribute (Qt::WA_DeleteOnClose);\n\n  setWindowTitle (tr (\"Enter New Shortcut\"));\n\n  QVBoxLayout *box = new QVBoxLayout (this);\n\n  box->setSpacing (2);\n  box->setContentsMargins (12, 12, 12, 12);\n\n  QLabel *help = new QLabel (tr (\"Enter custom shortcut\\n\"\n                                 \"Action: %1\")\n                             .arg (m_settings_key));\n\n  help->setWordWrap (true);\n\n  box->addWidget (help);\n\n  QCheckBox *direct\n    = new QCheckBox (tr (\"Enter shortcut by typing it\"));\n\n  QCheckBox *shift\n    = new QCheckBox (tr (\"Add Shift modifier\\n\"\n                         \"(allows one to enter number keys)\"));\n\n  shift->setStyleSheet\n    (\"QCheckBox::indicator { subcontrol-position: left top; }\");\n\n  connect (direct, &QCheckBox::clicked, shift, &QCheckBox::setEnabled);\n\n  direct->setCheckState (Qt::Checked);\n\n  box->addWidget (direct);\n  box->addWidget (shift);\n\n  box->addSpacing (15);\n\n  QGridLayout *grid = new QGridLayout ();\n\n  QLabel *actual = new QLabel (tr (\"Actual Shortcut\"));\n\n  m_edit_actual = new enter_shortcut (this);\n  m_edit_actual->setAlignment (Qt::AlignHCenter);\n\n  grid->addWidget (actual, 0, 0);\n  grid->addWidget (m_edit_actual, 0, 1);\n\n  QLabel *def = new QLabel (tr (\"Default Shortcut\"));\n\n  QLabel *label_default = new QLabel (this);\n  label_default->setAlignment (Qt::AlignHCenter);\n\n  grid->addWidget (def, 1, 0);\n  grid->addWidget (label_default, 1, 1);\n\n  QPushButton *clear_text = new QPushButton (tr (\"Clear\"));\n  QPushButton *set_default = new QPushButton (tr (\"Set to default\"));\n\n  grid->addWidget (clear_text, 0, 2);\n  grid->addWidget (set_default, 0, 3);\n\n  box->addLayout (grid);\n  box->addSpacing (18);\n\n  QDialogButtonBox *button_box = new QDialogButtonBox (QDialogButtonBox::Ok\n                                                       | QDialogButtonBox::Cancel);\n  QList<QAbstractButton *> buttons = button_box->buttons ();\n  for (int i = 0; i < buttons.count (); i++)\n    buttons.at (i)->setShortcut (QKeySequence ());\n\n  connect (button_box, &QDialogButtonBox::accepted,\n           this, &QDialog::accept);\n\n  connect (button_box, &QDialogButtonBox::rejected,\n           this, &QDialog::reject);\n\n  box->addWidget (button_box);\n\n  setLayout (box);\n\n  connect (direct,\n#if defined (HAVE_QCHECKBOX_CHECKSTATECHANGED)\n           &QCheckBox::checkStateChanged,\n#else\n           &QCheckBox::stateChanged,\n#endif\n           m_edit_actual, &enter_shortcut::handle_direct_shortcut);\n\n  connect (shift,\n#if defined (HAVE_QCHECKBOX_CHECKSTATECHANGED)\n           &QCheckBox::checkStateChanged,\n#else\n           &QCheckBox::stateChanged,\n#endif\n           m_edit_actual, &enter_shortcut::handle_shift_modifier);\n\n  connect (this, &QDialog::finished,\n           this, &shortcut_edit_dialog::finished);\n\n  gui_settings settings;\n\n  const sc_pref scpref = all_shortcut_preferences::value (m_settings_key);\n\n  m_default_text = scpref.def_text ();\n  label_default->setText (m_default_text);\n\n  QString actual_text = shortcut_item->actual_text ();\n  m_edit_actual->setText (actual_text);\n\n  connect (clear_text, &QPushButton::clicked,\n           [this] () { m_edit_actual->setText (QString ()); });\n  connect (set_default, &QPushButton::clicked,\n           [this] () { m_edit_actual->setText (m_default_text); });\n\n  m_edit_actual->setFocus ();\n\n  setFocusProxy (m_edit_actual);\n}\n\nvoid\nshortcut_edit_dialog::finished (int result)\n{\n  if (result == QDialog::Rejected)\n    return;\n\n  // Check whether the chosen shortcut is already in use either in the\n  // current context (section of the shortcut settings) or as a global\n  // (main_) shortcut.  This job might have been easier if we had\n  // organized the sections as child groups instead of using a colon in\n  // the settings key to separate the section from the shortcut name.\n\n  // Note that m_settings_key doesn't begin with the sc_group prefix.\n\n  QString my_section = get_shortcut_section (m_settings_key);\n  if (my_section.contains ('_'))    // get top level section\n    my_section = my_section.section ('_', 0, 0, QString::SectionSkipEmpty);\n\n  QString actual_text = m_edit_actual->text ();\n\n  bool conflict = false;\n  QString other_settings_key;\n\n  gui_settings settings;\n\n  settings.beginGroup (sc_group);\n  const QStringList shortcut_settings_keys = all_shortcut_preferences::keys ();\n  settings.endGroup ();\n\n  for (const auto& settings_key : shortcut_settings_keys)\n    {\n      if (settings_key == m_settings_key)\n        continue;\n\n      QString section = get_shortcut_section (settings_key);\n      if (section.contains ('_'))   // get top level section\n        section = section.section ('_', 0, 0, QString::SectionSkipEmpty);\n\n      if (section == my_section || section == \"main\")\n        {\n          const sc_pref scpref = all_shortcut_preferences::value (settings_key);\n          QString shortcut_text = settings.sc_value (scpref);\n\n          if (shortcut_text.isEmpty ())\n            continue;\n\n          if (shortcut_text == actual_text)\n            {\n              other_settings_key = settings_key;\n              conflict = true;\n            }\n        }\n    }\n\n  if (conflict)\n    {\n      // We only need the description of the other shortcut, not the\n      // complete sc_pref info.\n\n      const sc_pref other_scpref\n        = all_shortcut_preferences::value (other_settings_key);\n\n      int ret = QMessageBox::warning (this, tr (\"Double Shortcut\"),\n                                      tr (\"The chosen shortcut\\n  \\\"%1\\\"\\n\"\n                                          \"is already used for the action\\n  \\\"%2\\\".\\n\"\n                                          \"Do you want to use the shortcut and remove it \"\n                                          \"from the previous action?\")\n                                      .arg (actual_text)\n                                      .arg (other_scpref.description ()),\n                                      QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);\n\n      if (ret == QMessageBox::Yes)\n        Q_EMIT set_shortcut (other_settings_key, \"\");\n      else\n        return;\n    }\n\n  m_shortcut_item->set_actual_text (actual_text);\n}\n\nshortcuts_tree_widget::shortcuts_tree_widget (QWidget *parent)\n  : QTreeWidget (parent)\n{\n  QHash<QString, QTreeWidgetItem *> level_hash;\n\n  header ()->setSectionResizeMode (QHeaderView::ResizeToContents);\n\n  int dsc_col = tree_widget_shortcut_item::DESCRIPTION_COLUMN;\n\n  QTreeWidgetItem *main = new QTreeWidgetItem (this);\n  main->setText (dsc_col, tr (\"Global\"));\n  main->setExpanded (true);\n\n  QTreeWidgetItem *main_file = new QTreeWidgetItem (main);\n  main_file->setText (dsc_col, tr (\"File Menu\"));\n\n  QTreeWidgetItem *main_edit = new QTreeWidgetItem (main);\n  main_edit->setText (dsc_col, tr (\"Edit Menu\"));\n\n  QTreeWidgetItem *main_debug = new QTreeWidgetItem (main);\n  main_debug->setText (dsc_col, tr (\"Debug Menu\"));\n\n  QTreeWidgetItem *main_tools = new QTreeWidgetItem (main);\n  main_tools->setText (dsc_col, tr (\"Tools Menu\"));\n\n  QTreeWidgetItem *main_window = new QTreeWidgetItem (main);\n  main_window->setText (dsc_col, tr (\"Window Menu\"));\n\n  QTreeWidgetItem *main_help = new QTreeWidgetItem (main);\n  main_help->setText (dsc_col, tr (\"Help Menu\"));\n\n  QTreeWidgetItem *main_news = new QTreeWidgetItem (main);\n  main_news->setText (dsc_col, tr (\"News Menu\"));\n\n  QTreeWidgetItem *main_dock_widgets = new QTreeWidgetItem (main);\n  main_dock_widgets->setText (dsc_col, tr (\"Handling of Dock Widgets\"));\n\n  QTreeWidgetItem *main_tabs = new QTreeWidgetItem (main);\n  main_tabs->setText (dsc_col, tr (\"Tab Handling in Dock Widgets\"));\n\n  QTreeWidgetItem *main_find = new QTreeWidgetItem (main);\n  main_find->setText (dsc_col, tr (\"Find & Replace in Dock Widgets\"));\n\n  QTreeWidgetItem *main_zoom = new QTreeWidgetItem (main);\n  main_zoom->setText (dsc_col, tr (\"Zooming in Editor and Documentation\"));\n\n  level_hash[sc_main_file] = main_file;\n  level_hash[sc_main_edit] = main_edit;\n  level_hash[sc_main_debug] = main_debug;\n  level_hash[sc_main_tools] = main_tools;\n  level_hash[sc_main_window] = main_window;\n  level_hash[sc_main_help] = main_help;\n  level_hash[sc_main_news] = main_news;\n  level_hash[sc_dock_widget] = main_dock_widgets;\n  level_hash[sc_edit_tabs] = main_tabs;\n  level_hash[sc_edit_find] = main_find;\n  level_hash[sc_edit_zoom] = main_zoom;\n\n  QTreeWidgetItem *editor = new QTreeWidgetItem (this);\n  editor->setText (dsc_col, tr (\"Editor\"));\n  editor->setExpanded (true);\n\n  QTreeWidgetItem *editor_file = new QTreeWidgetItem (editor);\n  editor_file->setText (dsc_col, tr (\"File Menu\"));\n\n  QTreeWidgetItem *editor_edit = new QTreeWidgetItem (editor);\n  editor_edit->setText (dsc_col, tr (\"Edit Menu\"));\n\n  QTreeWidgetItem *editor_view = new QTreeWidgetItem (editor);\n  editor_view->setText (dsc_col, tr (\"View Menu\"));\n\n  QTreeWidgetItem *editor_debug = new QTreeWidgetItem (editor);\n  editor_debug->setText (dsc_col, tr (\"Debug Menu\"));\n\n  QTreeWidgetItem *editor_run = new QTreeWidgetItem (editor);\n  editor_run->setText (dsc_col, tr (\"Run Menu\"));\n\n  QTreeWidgetItem *editor_help = new QTreeWidgetItem (editor);\n  editor_help->setText (dsc_col, tr (\"Help Menu\"));\n\n  level_hash[sc_edit_file] = editor_file;\n  level_hash[sc_edit_edit] = editor_edit;\n  level_hash[sc_edit_view] = editor_view;\n  level_hash[sc_edit_debug] = editor_debug;\n  level_hash[sc_edit_run] = editor_run;\n  level_hash[sc_edit_help] = editor_help;\n\n  QTreeWidgetItem *doc = new QTreeWidgetItem (this);\n  doc->setText (dsc_col, tr (\"Documentation Viewer\"));\n  doc->setExpanded (true);\n\n  QTreeWidgetItem *doc_browser = new QTreeWidgetItem (doc);\n  doc_browser->setText (dsc_col, tr (\"Browser\"));\n\n  level_hash[sc_doc] = doc_browser;\n\n  connect (this, &QTreeWidget::itemDoubleClicked,\n           this, &shortcuts_tree_widget::edit_selection);\n\n  QList<QString> shortcut_settings_keys\n    = all_shortcut_preferences::keys ();\n\n  // Sort the keys with respect to the description, by adding\n  // descriptions as keys and the settings keys as values to a map.\n  // Use QMultiMap since descriptions might not be unique.\n  QMultiMap<QString, QString> shortcut_settings_map;\n  for (const auto& settings_key : shortcut_settings_keys)\n    {\n      const sc_pref scpref = all_shortcut_preferences::value (settings_key);\n      shortcut_settings_map.insert (scpref.description (), settings_key);\n    }\n  shortcut_settings_keys = shortcut_settings_map.values ();\n\n  gui_settings settings;\n\n  for (const auto& settings_key : shortcut_settings_keys)\n    {\n      QTreeWidgetItem *section = level_hash[settings_key.section (':', 0, 0)];\n\n      // handle sections which have changed and do not correspond to the\n      // previously defined keyname\n      if (section == editor_file)\n        {\n          // Closing tabs now in global tab handling section\n          if (settings_key.contains (sc_edit_file_cl))\n            section = main_tabs;\n        }\n      else if (section == editor_edit)\n        {\n          // Find & replace now in global file & replace handling section\n          if (settings_key.contains (sc_edit_edit_find))\n            section = main_find;\n        }\n      else if (section == editor_view)\n        {\n          // Zooming now in global zoom handling section\n          if (settings_key.contains (sc_edit_view_zoom))\n            section = main_zoom;\n        }\n\n      const sc_pref scpref = all_shortcut_preferences::value (settings_key);\n\n      // Inserts itself in the tree widget in SECTION.  The parent\n      // object will delete it.\n      QString actual_text = settings.sc_value (scpref);\n      new tree_widget_shortcut_item (section, scpref, actual_text);\n    }\n}\n\nvoid\nshortcuts_tree_widget::edit_selection (QTreeWidgetItem *item, int col)\n{\n  if (col != 2)\n    return;\n\n  tree_widget_shortcut_item *shortcut_item\n    = dynamic_cast<tree_widget_shortcut_item *> (item);\n\n  if (! shortcut_item)\n    return;  // top-level-item clicked\n\n  shortcut_edit_dialog *dialog\n    = new shortcut_edit_dialog (shortcut_item);\n\n  connect (dialog, &shortcut_edit_dialog::set_shortcut,\n           this, &shortcuts_tree_widget::update_widget_value);\n\n  dialog->show ();\n}\n\nvoid\nshortcuts_tree_widget::update_widget_value (const QString& settings_key,\n    const QString& sc_text)\n{\n  tree_widget_shortcut_item *item = get_item (settings_key);\n\n  if (item)\n    item->set_actual_text (sc_text);\n}\n\ntree_widget_shortcut_item *\nshortcuts_tree_widget::get_item (const QString& settings_key)\n{\n  // There aren't many shortcuts so iterating over all of them to find\n  // an individual item isn't a big performance issue.  If we had many\n  // more items we could use a QHash<settings_key, sc_pref> data member.\n\n  tree_widget_shortcut_item *item = nullptr;\n\n  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);\n  while (*it)\n    {\n      tree_widget_shortcut_item *shortcut_item\n        = dynamic_cast<tree_widget_shortcut_item *> (*it);\n\n      if (settings_key == shortcut_item->settings_key ())\n        {\n          item = shortcut_item;\n          break;\n        }\n\n      it++;\n    }\n\n  // FIXME: Should it be an error to not find a match?\n\n  if (! item)\n    qWarning () << (tr (\"item %1 not found in shortcut settings dialog\")\n                    .arg (settings_key));\n\n  return item;\n}\n\nvoid\nshortcuts_tree_widget::update_settings_value (gui_settings& settings,\n    const QString& settings_key)\n{\n  tree_widget_shortcut_item *item = get_item (settings_key);\n\n  if (item)\n    settings.setValue (settings_key, item->actual_text ());\n}\n\n// Refresh the tree view with values from the settings object.\n\nvoid\nshortcuts_tree_widget::import_shortcuts (gui_settings& settings)\n{\n  settings.beginGroup (sc_group);\n\n  const QStringList shortcut_settings_keys = settings.allKeys ();\n\n  for (const auto& settings_key : shortcut_settings_keys)\n    {\n      // We don't want to apply default value here.\n      QString sc_text = settings.value (settings_key).toString ();\n\n      update_widget_value (settings_key, sc_text);\n    }\n\n  settings.endGroup ();\n\n  bool sc_ctrld = false;\n\n  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);\n  while (*it)\n    {\n      tree_widget_shortcut_item *shortcut_item\n        = dynamic_cast<tree_widget_shortcut_item *> (*it);\n\n      if (! shortcut_item)\n        continue;\n\n      QString settings_key = shortcut_item->settings_key ();\n      QString sc_text = shortcut_item->actual_text ();\n\n      if (sc_text.isEmpty ())\n        sc_text = shortcut_item->default_text ();\n\n      QString section = get_shortcut_section (settings_key);\n\n      // special: check main-window for Ctrl-D (Terminal)\n      if (section.startsWith (\"main_\")\n          && QKeySequence (sc_text)\n             == QKeySequence (Qt::ControlModifier | Qt::Key_D))\n\n        sc_ctrld = true;\n\n      it++;\n    }\n\n  settings.setValue (sc_main_ctrld.settings_key (), sc_ctrld);\n\n  settings.sync ();\n}\n\n// Export all shortcuts from the tree view to the settings object.\n\nvoid\nshortcuts_tree_widget::export_shortcuts (gui_settings& settings, bool full)\n{\n  settings.beginGroup (sc_group);\n\n  bool sc_ctrld = false;\n\n  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);\n  while (*it)\n    {\n      tree_widget_shortcut_item *shortcut_item\n        = dynamic_cast<tree_widget_shortcut_item *> (*it);\n\n      if (! shortcut_item)\n        continue;\n\n      QString settings_key = shortcut_item->settings_key ();\n      QString sc_text = shortcut_item->actual_text ();\n\n      if (full || sc_text != shortcut_item->default_text ())\n        {\n          // Only write the shortcut to the settings file if it is\n          // different to its default value or if an export into a\n          // custom file is desired by the user.\n          settings.setValue (settings_key, sc_text);\n        }\n      else\n        {\n          // Remove the key otherwise, the default value will be\n          // chosen for non existing shortcut keys.\n          settings.remove (settings_key);\n        }\n\n      QString section = get_shortcut_section (settings_key);\n\n      // special: check main-window for Ctrl-D (Terminal)\n      if (section.startsWith (\"main_\")\n          && QKeySequence (sc_text)\n             == QKeySequence (Qt::ControlModifier | Qt::Key_D))\n\n        sc_ctrld = true;\n\n      it++;\n    }\n\n  settings.endGroup ();\n\n  settings.setValue (sc_main_ctrld.settings_key (), sc_ctrld);\n\n  settings.sync ();\n}\n\n// Clear all user-defined settings from the tree widget and the\n// application settings.\n\nvoid\nshortcuts_tree_widget::set_default_shortcuts ()\n{\n  gui_settings settings;\n\n  settings.beginGroup (sc_group);\n\n  settings.remove (\"\");\n\n  settings.endGroup ();\n\n  bool sc_ctrld = false;\n\n  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);\n  while (*it)\n    {\n      tree_widget_shortcut_item *shortcut_item\n        = dynamic_cast<tree_widget_shortcut_item *> (*it);\n\n      if (! shortcut_item)\n        continue;\n\n      QString settings_key = shortcut_item->settings_key ();\n\n      shortcut_item->set_actual_text (\"\");\n\n      QString sc_text = shortcut_item->default_text ();\n\n      QString section = get_shortcut_section (settings_key);\n\n      // special: check main-window for Ctrl-D (Terminal)\n      if (section.startsWith (\"main_\")\n          && QKeySequence (sc_text)\n             == QKeySequence (Qt::ControlModifier | Qt::Key_D))\n\n        sc_ctrld = true;\n\n      it++;\n    }\n\n  settings.setValue (sc_main_ctrld.settings_key (), sc_ctrld);\n\n  settings.sync ();\n}\n\n// For each key found in application settings object, transfer\n// corresponding setting to the application settings object.\n\nvoid\nshortcuts_tree_widget::write_settings ()\n{\n  gui_settings settings;\n\n  export_shortcuts (settings, false); // false: omit values identical to the default\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/shortcuts-tree-widget.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2014-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_shortcuts_tree_widget_h)\n#define octave_shortcuts_tree_widget_h 1\n\n#include <QCheckBox>\n#include <QDialog>\n#include <QKeyEvent>\n#include <QLineEdit>\n#include <QString>\n#include <QTreeWidget>\n#include <QtCore>\n\n#include \"gui-preferences.h\"\n#include \"gui-settings.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass enter_shortcut : public QLineEdit\n{\n  Q_OBJECT\n\npublic:\n\n  enter_shortcut (QWidget *p = nullptr);\n\n  ~enter_shortcut () = default;\n\n  virtual void keyPressEvent (QKeyEvent *e);\n\npublic Q_SLOTS:\n\n  void handle_direct_shortcut (int);\n  void handle_shift_modifier (int);\n\nprivate:\n\n  bool m_direct_shortcut;\n  bool m_shift_modifier;\n};\n\nclass tree_widget_shortcut_item : public QTreeWidgetItem\n{\npublic:\n\n  enum\n  {\n    DESCRIPTION_COLUMN = 0,\n    DEFAULT_COLUMN,\n    ACTUAL_COLUMN\n  };\n\n  tree_widget_shortcut_item (QTreeWidgetItem *parent, const sc_pref& scpref,\n                             const QString& actual_text);\n\n  QString settings_key () const;\n\n  QString description () const;\n  void set_description (const QString& text);\n\n  QString default_text () const;\n  void set_default_text (const QString& text);\n\n  QString actual_text () const;\n  void set_actual_text (const QString& text);\n\nprivate:\n\n  QString m_settings_key;\n};\n\nclass shortcut_edit_dialog : public QDialog\n{\n  Q_OBJECT\n\npublic:\n\n  shortcut_edit_dialog (tree_widget_shortcut_item *shortcut_item,\n                        QWidget *parent = nullptr);\n\npublic Q_SLOTS:\n\n  void finished (int result);\n\nQ_SIGNALS:\n\n  void set_shortcut (const QString& settings_key,\n                     const QString& settings_value);\n\nprivate:\n\n  tree_widget_shortcut_item *m_shortcut_item;\n\n  enter_shortcut *m_edit_actual;\n\n  QString m_settings_key;\n  QString m_default_text;\n};\n\nclass shortcuts_tree_widget : public QTreeWidget\n{\n  Q_OBJECT\n\npublic:\n\n  shortcuts_tree_widget (QWidget *parent);\n\n  void import_shortcuts (gui_settings& settings);\n\n  void export_shortcuts (gui_settings& settings, bool full = true);\n\n  void set_default_shortcuts ();\n\n  void write_settings ();\n\npublic Q_SLOTS:\n\n  void edit_selection (QTreeWidgetItem *item, int col);\n\n  void update_widget_value (const QString& settings_key,\n                            const QString& sc_text);\n\nprivate:\n\n  tree_widget_shortcut_item * get_item (const QString& settings_key);\n\n  void update_settings_value (gui_settings& settings,\n                              const QString& settings_key);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/tab-bar.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file implements a tab bar derived from QTabBar with a contextmenu\n// and possibility to close a tab via double-left or middle mouse click.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"tab-bar.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n//\n// Reimplemented QTabbar\n//\n\ntab_bar::tab_bar (QWidget *p)\n  : QTabBar (p), m_context_menu (new QMenu (this))\n{ }\n\nvoid\ntab_bar::set_rotated (int rotated)\n{\n  m_rotated = rotated;\n}\n\n// slots for tab navigation\nvoid\ntab_bar::switch_left_tab ()\n{\n  switch_tab (-1);\n}\n\nvoid\ntab_bar::switch_right_tab ()\n{\n  switch_tab (1);\n}\n\nvoid\ntab_bar::move_tab_left ()\n{\n  switch_tab (-1, true);\n}\n\nvoid\ntab_bar::move_tab_right ()\n{\n  switch_tab (1, true);\n}\n\nvoid\ntab_bar::switch_tab (int direction, bool movetab)\n{\n  int tabs = count ();\n\n  if (tabs < 2)\n    return;\n\n  int old_pos = currentIndex ();\n  int new_pos = currentIndex () + direction;\n\n  if (new_pos < 0 || new_pos >= tabs)\n    new_pos = new_pos - direction*tabs;\n\n  if (movetab)\n    {\n      moveTab (old_pos, new_pos);\n      setCurrentIndex (old_pos);\n      setCurrentIndex (new_pos);\n    }\n  else\n    setCurrentIndex (new_pos);\n}\n\nvoid\ntab_bar::sort_tabs_alph ()\n{\n  QString current_title = tabText (currentIndex ());\n  int tab_with_focus = 0;\n\n  // Get all tab title and sort\n  QStringList tab_texts;\n\n  for (int i = 0; i < count (); i++)\n    tab_texts.append (tabText (i));\n\n  tab_texts.sort ();\n\n  // Move tab into the order of the generated string list\n  for (int title = 0; title < tab_texts.count (); title++)\n    {\n      // Target tab is same as place of title in QStringList.\n      // Find index of next title in string list, leaving out the\n      // tabs (or titles) that were already moved.\n      for (int tab = title; tab < count (); tab++)\n        {\n          if (tabText (tab) == tab_texts.at (title))\n            {\n              // Index of next tile found, so move tab into next position\n              moveTab (tab, title);\n\n              if (tab_texts.at (title) == current_title)\n                tab_with_focus = title;\n\n              break;\n            }\n        }\n    }\n\n  setCurrentIndex (tab_with_focus);\n}\n\n// The following two functions are reimplemented for allowing rotated\n// tabs and are based on this answer on stack overflow:\n// https://stackoverflow.com/a/50579369\n\n// Reimplemented size hint allowing rotated tabs\nQSize\ntab_bar::tabSizeHint (int idx) const\n{\n  QSize s = QTabBar::tabSizeHint (idx);\n  if (m_rotated)\n    s.transpose ();\n\n  return s;\n}\n\n// Reimplemented paint event allowing rotated tabs\nvoid\ntab_bar::paintEvent (QPaintEvent *e)\n{\n  // Just process the original event if not rotated\n  if (! m_rotated)\n    return QTabBar::paintEvent (e);\n\n  // Process the event for rotated tabs\n  QStylePainter painter (this);\n  QStyleOptionTab opt;\n\n  for (int idx = 0; idx < count (); idx++)\n    {\n      initStyleOption (&opt, idx);\n      painter.drawControl (QStyle::CE_TabBarTabShape, opt);\n      painter.save ();\n\n      QSize s = opt.rect.size ();\n      s.transpose ();\n      QRect rect (QPoint (), s);\n      rect.moveCenter (opt.rect.center ());\n      opt.rect = rect;\n\n      QPoint p = tabRect (idx).center ();\n      painter.translate (p);\n      painter.rotate (-m_rotated*90);\n      painter.translate (-p);\n      painter.drawControl (QStyle::CE_TabBarTabLabel, opt);\n      painter.restore ();\n    }\n}\n\n// Reimplement mouse event for filtering out the desired mouse clicks\nvoid\ntab_bar::mousePressEvent (QMouseEvent *me)\n{\n  QPoint click_pos;\n  int clicked_idx = -1;\n\n  // detect the tab where the click occurred\n  for (int i = 0; i < count (); i++)\n    {\n      click_pos = mapToGlobal (me->pos ());\n      if (tabRect (i).contains (mapFromGlobal (click_pos)))\n        {\n          clicked_idx = i;\n          break;\n        }\n    }\n\n  // If a tab was clicked\n  if (clicked_idx >= 0)\n    {\n      int current_idx = currentIndex ();\n      int current_count = count ();\n\n      // detect the mouse click\n      if ((me->type () == QEvent::MouseButtonDblClick\n           && me->button () == Qt::LeftButton)\n          || (me->type () != QEvent::MouseButtonDblClick\n              && me->button () == Qt::MiddleButton))\n        {\n          // Middle click or double click -> close the tab\n          // Make the clicked tab the current one and close it\n          setCurrentIndex (clicked_idx);\n          Q_EMIT close_current_tab_signal (true);\n          // Was the closed tab before or after the previously current tab?\n          // According to the result, use previous index or reduce it by one\n          if (current_idx - clicked_idx > 0)\n            setCurrentIndex (current_idx - 1);\n          else if (current_idx - clicked_idx < 0)\n            setCurrentIndex (current_idx);\n        }\n      else if (me->type () != QEvent::MouseButtonDblClick\n               && me->button () == Qt::RightButton)\n        {\n          // Right click, show context menu\n          setCurrentIndex (clicked_idx);\n\n          // Fill context menu with actions for selecting current tabs\n          m_ctx_actions = m_context_menu->actions (); // Copy of basic actions\n          QMenu ctx_menu;                             // The menu actually used\n          connect (&ctx_menu, &QMenu::triggered,\n                   this, &tab_bar::ctx_menu_activated);\n\n          for (int i = count () - 1; i >= 0; i--)\n            {\n              // Prepend an action for each tab\n              QAction *a = new QAction (tabIcon (i), tabText (i), &ctx_menu);\n              m_ctx_actions.prepend (a);\n            }\n          // Add all actions to our menu\n          ctx_menu.insertActions (nullptr, m_ctx_actions);\n\n          if (! ctx_menu.exec (click_pos))\n            {\n              // No action selected, back to previous tab\n              setCurrentIndex (current_idx);\n            }\n          else if (count () < current_count)\n            {\n              // A tab was closed:\n              // Was the possibly only closed tab before or after the\n              // previously current tab? According to the result, use previous\n              // index or reduce it by one.  Also prevent using a too large\n              // index if other or all files were closed.\n              int new_idx = count () - 1;\n              if (new_idx > 0)\n                {\n                  if (current_idx - clicked_idx > 0)\n                    new_idx = current_idx - 1;\n                  else if (current_idx - clicked_idx < 0)\n                    new_idx = current_idx;\n                }\n              if (new_idx >= 0)\n                setCurrentIndex (new_idx);\n            }\n        }\n      else\n        {\n          // regular handling of the mouse event\n          QTabBar::mousePressEvent (me);\n        }\n    }\n  else\n    {\n      // regular handling of the mouse event\n      QTabBar::mousePressEvent (me);\n    }\n}\n\n// Slot if a menu entry in the context menu is activated\nvoid\ntab_bar::ctx_menu_activated (QAction *a)\n{\n  // If the index of the activated action is in the range of\n  // the current tabs, set the related current tab.  The basic actions\n  // are handled by the editor\n  int i = m_ctx_actions.indexOf (a);\n  if ((i > -1) && (i < count ()))\n    setCurrentIndex (i);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/tab-bar.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file implements a tab bar derived from QTabBar with a contextmenu\n// and possibility to close a tab via double-left or middle mouse click.\n\n#if ! defined (octave_tab_bar_h)\n#define octave_tab_bar_h 1\n\n#include <QMenu>\n#include <QMouseEvent>\n#include <QSize>\n#include <QStyleOptionTab>\n#include <QStylePainter>\n#include <QTabBar>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Subclassed QTabBar for usable tab-bar, rotated tabs and\n// reimplemented mouse event\n\nclass tab_bar : public QTabBar\n{\n  Q_OBJECT\n\npublic:\n\n  tab_bar (QWidget *p);\n\n  ~tab_bar () = default;\n\n  void set_rotated (int rotated);\n  QMenu * get_context_menu () { return m_context_menu; };\n  QSize tabSizeHint (int idx) const;\n\nQ_SIGNALS:\n\n  void close_current_tab_signal (bool);\n\npublic Q_SLOTS:\n\n  void switch_left_tab ();\n  void switch_right_tab ();\n  void move_tab_left ();\n  void move_tab_right ();\n  void sort_tabs_alph ();\n\nprivate Q_SLOTS:\n\n  void ctx_menu_activated (QAction *a);\n\nprotected:\n\n  void paintEvent (QPaintEvent *e);\n  void mousePressEvent (QMouseEvent *event);\n\nprivate:\n\n  void switch_tab (int direction, bool movetab = false);\n\n  QMenu *m_context_menu;\n  QList<QAction *> m_ctx_actions;\n  int m_rotated;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/terminal-dock-widget.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QGuiApplication>\n#include <QScreen>\n\n// This header is only needed for the new terminal widget, and\n// can only be included if Qscintilla is available.\n#if defined (HAVE_QSCINTILLA)\n#  include \"command-widget.h\"\n#endif\n\n// This header is only needed for the old terminal widget.\n#include \"QTerminal.h\"\n\n#include \"gui-preferences-cs.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-settings.h\"\n\n#include \"terminal-dock-widget.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nterminal_dock_widget::terminal_dock_widget (QWidget *p,\n                                            bool experimental_terminal_widget)\n  : octave_dock_widget (\"TerminalDockWidget\", p),\n    m_experimental_terminal_widget (experimental_terminal_widget)\n{\n  init_control_d_shortcut_behavior ();\n\n  // FIXME: we could do this in a better way, but improving it doesn't\n  // matter much if we will eventually be removing the old terminal.\n  if (m_experimental_terminal_widget)\n    {\n#if defined (HAVE_QSCINTILLA)\n      command_widget *widget = new command_widget (this);\n      console *con = widget->get_console ();\n\n      connect (this, &terminal_dock_widget::settings_changed,\n               widget, &command_widget::notice_settings);\n\n      connect (this, &terminal_dock_widget::update_prompt_signal,\n               widget, &command_widget::update_prompt);\n\n      connect (this, &terminal_dock_widget::interpreter_output_signal,\n               widget, &command_widget::insert_interpreter_output);\n\n      connect (this, &terminal_dock_widget::execute_command_signal,\n               con, &console::execute_command);\n\n      connect (this, &terminal_dock_widget::get_input_from_terminal_signal,\n               con, &console::get_input_from_terminal);\n\n      connect (con, &console::finished_input_from_terminal_signal,\n               this, &terminal_dock_widget::finished_input_from_terminal_signal);\n\n      connect (this, &terminal_dock_widget::new_command_line_signal,\n               con, &console::new_command_line);\n\n      m_terminal = widget;\n#endif\n    }\n  else\n    {\n      QTerminal *widget = QTerminal::create (this);\n\n      connect (this, &terminal_dock_widget::settings_changed,\n               widget, &QTerminal::notice_settings);\n\n      // Connect the visibility signal to the terminal for\n      // dis-/enabling timers.\n      connect (this, &terminal_dock_widget::visibilityChanged,\n               widget, &QTerminal::handle_visibility_changed);\n\n      connect (widget, qOverload<const fcn_callback&> (&QTerminal::interpreter_event),\n               this, qOverload<const fcn_callback&> (&terminal_dock_widget::interpreter_event));\n\n      connect (widget, qOverload<const meth_callback&> (&QTerminal::interpreter_event),\n               this, qOverload<const meth_callback&> (&terminal_dock_widget::interpreter_event));\n\n      m_terminal = widget;\n    }\n\n  m_terminal->setObjectName (\"OctaveTerminal\");\n  m_terminal->setFocusPolicy (Qt::StrongFocus);\n\n  set_title (tr (\"Command Window\"));\n\n  setWidget (m_terminal);\n  setFocusProxy (m_terminal);\n\n  // Chose a reasonable size at startup in order to avoid truncated\n  // startup messages\n\n  gui_settings settings;\n\n  QFont font = QFont ();\n  font.setStyleHint (QFont::TypeWriter);\n  QString default_font = settings.string_value (global_mono_font);\n  font.setFamily\n    (settings.value (cs_font.settings_key (), default_font).toString ());\n  font.setPointSize\n    (settings.int_value (cs_font_size));\n\n  QFontMetrics metrics (font);\n\n  int win_x =  metrics.maxWidth ()*80;\n  int win_y =  metrics.height ()*25;\n\n  int max_x = QGuiApplication::primaryScreen ()->availableGeometry ().width ();\n  int max_y = QGuiApplication::primaryScreen ()->availableGeometry ().height ();\n\n  if (win_x > max_x)\n    win_x = max_x;\n  if (win_y > max_y)\n    win_y = max_y;\n\n  setGeometry (0, 0, win_x, win_y);\n\n  if (! p)\n    make_window ();\n}\n\nbool\nterminal_dock_widget::has_focus () const\n{\n  QWidget *w = widget ();\n  return w->hasFocus ();\n}\n\nQTerminal *\nterminal_dock_widget::get_qterminal ()\n{\n  return (m_experimental_terminal_widget\n          ? nullptr : dynamic_cast<QTerminal *> (m_terminal));\n}\n\ncommand_widget *\nterminal_dock_widget::get_command_widget ()\n{\n#if defined (HAVE_QSCINTILLA)\n  return (m_experimental_terminal_widget\n          ? dynamic_cast<command_widget *> (m_terminal) : nullptr);\n#else\n  return nullptr;\n#endif\n}\n\nvoid\nterminal_dock_widget::notice_settings ()\n{\n  Q_EMIT settings_changed ();\n}\n\nvoid\nterminal_dock_widget::init_command_prompt ()\n{\n  if (m_experimental_terminal_widget)\n    {\n#if defined (HAVE_QSCINTILLA)\n      command_widget *cmd = get_command_widget ();\n      if (cmd)\n        cmd->init_command_prompt ();\n#endif\n    }\n}\n\nvoid\nterminal_dock_widget::init_control_d_shortcut_behavior ()\n{\n  gui_settings settings;\n\n  // Reset use of Ctrl-D.  Do this before the call to beginGroup\n  // because sc_main_ctrld.key already begins with the sc_group\n  // prefix.\n  settings.setValue (sc_main_ctrld.settings_key (), false);\n\n  settings.beginGroup (sc_group);\n  const QStringList shortcut_settings_keys = settings.allKeys ();\n  settings.endGroup ();\n\n  for (const auto& settings_key : shortcut_settings_keys)\n    {\n      // Check whether Ctrl+D is used from main window, i.e., is a\n      // global shortcut.\n\n      QString section = get_shortcut_section (settings_key);\n\n      if (section.startsWith (\"main_\"))\n        {\n          sc_pref scpref = all_shortcut_preferences::value (settings_key);\n\n          QKeySequence actual = QKeySequence (settings.sc_value (scpref));\n\n          if (actual == QKeySequence (Qt::ControlModifier | Qt::Key_D))\n            {\n              settings.setValue (sc_main_ctrld.settings_key (), true);\n              break;\n            }\n        }\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/terminal-dock-widget.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_terminal_dock_widget_h)\n#define octave_terminal_dock_widget_h 1\n\n#include <QString>\n\n#include \"octave-dock-widget.h\"\n\nclass QTerminal;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass command_widget;\n\nclass terminal_dock_widget : public octave_dock_widget\n{\n  Q_OBJECT\n\npublic:\n\n  terminal_dock_widget (QWidget *parent,\n                        bool experimental_terminal_widget = false);\n\n  ~terminal_dock_widget () = default;\n\n  bool has_focus () const;\n\n  void init_command_prompt ();\n\n  void init_control_d_shortcut_behavior ();\n\n  // FIXME: The next two functions could be eliminated (or combined)\n  // if we had a common interface for the old and new terminal\n  // widgets.\n\n  // Only valid if using the old terminal widget.\n  QTerminal * get_qterminal ();\n\n  // Only valid if using the new terminal widget.\n  command_widget * get_command_widget ();\n\nQ_SIGNALS:\n\n  void settings_changed ();\n\n  // Note: the following four signals are\n  // currently only used by the new experimental terminal widget.\n\n  void update_prompt_signal (const QString&);\n\n  void interpreter_output_signal (const QString&, int style = 0);\n\n  void new_command_line_signal (const QString& = QString ());\n\n  void execute_command_signal (const QString&);\n\n  void get_input_from_terminal_signal (const QString& prompt);\n  void finished_input_from_terminal_signal (const QString& input);\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  void notice_settings ();\n\nprivate:\n\n  bool m_experimental_terminal_widget;\n\n  // FIXME!!!  Maybe my_term should just be derived from QTerminal?\n  QWidget *m_terminal;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/variable-editor-model.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n\n#include <QDebug>\n#include <QLabel>\n#include <QMap>\n#include <QMessageBox>\n#include <QPointer>\n#include <QString>\n#include <QTableView>\n\n#include \"octave-qt-features.h\"\n#include \"qt-interpreter-events.h\"\n#include \"variable-editor-model.h\"\n\n#include \"Cell.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"parse.h\"\n#include \"pr-flt-fmt.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic bool\ncell_is_editable (const octave_value& val)\n{\n  if ((val.isnumeric () || val.islogical ()) && val.numel () == 1)\n    return true;\n\n  if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ()))\n    return true;\n\n  return false;\n}\n\nstatic char\nget_quote_char (const octave_value& val)\n{\n  if (val.is_sq_string ())\n    return '\\'';\n\n  if (val.is_dq_string ())\n    return '\"';\n\n  return 0;\n}\n\nstatic float_display_format\nget_edit_display_format (const octave_value& val)\n{\n  // FIXME: make this limit configurable.\n\n  return (val.numel () > 250000\n          ? float_display_format () : val.get_edit_display_format ());\n}\n\nstatic bool\ndo_requires_sub_editor_sub (const octave_value& elt)\n{\n  return (! ((elt.numel () == 1 && (elt.isnumeric () || elt.islogical ()))\n             || (elt.is_string () && (elt.rows () == 1 || elt.isempty ()))));\n}\n\nbase_ve_model::base_ve_model (const QString& expr, const octave_value& val)\n  : m_name (expr.toStdString ()),\n    m_value (val),\n    m_data_rows (m_value.rows ()),\n    m_data_cols (m_value.columns ()),\n    m_display_rows (m_data_rows),\n    m_display_cols (m_data_cols),\n    m_update_pending (),\n    m_valid (m_value.is_defined ()),\n    m_display_fmt (get_edit_display_format (m_value))\n{ }\n\nstd::string\nbase_ve_model::name () const\n{\n  return m_name;\n}\n\nbool\nbase_ve_model::index_ok (const QModelIndex& idx, int& row, int& col) const\n{\n  row = 0;\n  col = 0;\n\n  if (! idx.isValid ())\n    return false;\n\n  row = idx.row ();\n  col = idx.column ();\n\n  return (row < data_rows () && col < data_columns ());\n}\n\nint\nbase_ve_model::column_width () const\n{\n  int width = 0;\n\n  float_format r_fmt = m_display_fmt.real_format ();\n  float_format i_fmt = m_display_fmt.imag_format ();\n\n  int rw = r_fmt.width ();\n  int iw = i_fmt.width ();\n\n  if (rw > 0)\n    {\n      if (m_value.iscomplex ())\n        {\n          if (iw > 0)\n            width = rw + iw + 5;\n        }\n      else\n        width = rw + 2;\n    }\n\n  return width;\n}\n\nint\nbase_ve_model::rowCount (const QModelIndex&) const\n{\n  return m_valid ? m_display_rows : 1;\n}\n\nint\nbase_ve_model::columnCount (const QModelIndex&) const\n{\n  return m_valid ? m_display_cols : 1;\n}\n\nQString\nbase_ve_model::edit_display_sub (const octave_value& elt, int role) const\n{\n  std::string str;\n\n  if (cell_is_editable (elt))\n    {\n      float_display_format fmt;\n\n      if (role == Qt::DisplayRole)\n        fmt = get_edit_display_format (elt);\n      else\n        fmt.set_precision (elt.is_single_type () ? 8 : 16);\n\n      str = elt.edit_display (fmt, 0, 0);\n    }\n  else\n    {\n      const dim_vector& dv = elt.dims ();\n      str = \"[\" + dv.str () + \" \" + elt.class_name () + \"]\";\n    }\n\n  return QString::fromStdString (str);\n}\n\nQVariant\nbase_ve_model::edit_display (const QModelIndex& idx, int role) const\n{\n  int row;\n  int col;\n\n  if (! index_ok (idx, row, col))\n    return QVariant ();\n\n  float_display_format fmt;\n  if (role == Qt::DisplayRole)\n    fmt = m_display_fmt;\n  else\n    fmt.set_precision (m_value.is_single_type () ? 8 : 16);\n\n  std::string str = m_value.edit_display (fmt, row, col);\n\n  return QString::fromStdString (str);\n}\n\nQVariant\nbase_ve_model::data (const QModelIndex& idx, int role) const\n{\n  if (idx.isValid () && role == Qt::DisplayRole && update_pending (idx))\n    return QVariant (update_pending_data (idx));\n\n  if (! m_valid)\n    {\n      if (role == Qt::DisplayRole)\n        return QVariant (QString (\"Variable %1 not found or value can't be edited\")\n                         .arg (QString::fromStdString (m_name)));\n\n      return QVariant (QString (\"x\"));\n    }\n\n  switch (role)\n    {\n    case Qt::DisplayRole:\n    case Qt::EditRole:\n      return edit_display (idx, role);\n    }\n\n  // Invalid.\n  return QVariant ();\n}\n\nbool\nbase_ve_model::requires_sub_editor (const QModelIndex&) const\n{\n  return false;\n}\n\nvoid\nbase_ve_model::set_update_pending (const QModelIndex& idx, const QString& str)\n{\n  m_update_pending[idx] = str;\n}\n\nbool\nbase_ve_model::update_pending (const QModelIndex& idx) const\n{\n  return m_update_pending.contains (idx);\n}\n\nQString\nbase_ve_model::update_pending_data (const QModelIndex& idx) const\n{\n  return m_update_pending[idx];\n}\n\nvoid\nbase_ve_model::clear_update_pending ()\n{\n  return m_update_pending.clear ();\n}\n\nchar\nbase_ve_model::quote_char (const QModelIndex&) const\n{\n  return 0;\n}\n\nQVariant\nbase_ve_model::header_data (int section, Qt::Orientation, int role) const\n{\n\n  if (role != Qt::DisplayRole)\n    return QVariant ();\n\n  return QString::number (section+1);\n}\n\nQString\nbase_ve_model::subscript_expression (const QModelIndex&) const\n{\n  return \"\";\n}\n\nQString\nbase_ve_model::make_description_text () const\n{\n  QString lbl_txt = QString::fromStdString (m_name);\n\n  if (m_value.is_defined ())\n    {\n      if (! lbl_txt.isEmpty ())\n        lbl_txt += \" \";\n\n      const dim_vector& dv = m_value.dims ();\n\n      lbl_txt += (\"[\"\n                  + QString::fromStdString (dv.str ())\n                  + \" \"\n                  + QString::fromStdString (m_value.class_name ())\n                  + \"]\");\n    }\n  else\n    lbl_txt += \" [undefined]\";\n\n  return lbl_txt;\n}\n\n// Private slots.\n\noctave_value\nbase_ve_model::value_at (const QModelIndex&) const\n{\n  return octave_value ();\n}\n\nclass numeric_model : public base_ve_model\n{\npublic:\n\n  numeric_model (const QString& expr, const octave_value& val)\n    : base_ve_model (expr, val)\n  {\n    // FIXME: should fill the window and expand on scrolling or\n    // resizing.\n\n    maybe_resize_rows (m_data_rows + 16);\n    maybe_resize_columns (m_data_cols + 16);\n  }\n\n  ~numeric_model () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (numeric_model)\n\n  void maybe_resize_rows (int rows)\n  {\n    if (rows > m_display_rows)\n      m_display_rows = rows;\n  }\n\n  void maybe_resize_columns (int cols)\n  {\n    if (cols > m_display_cols)\n      m_display_cols = cols;\n  }\n\n  QVariant edit_display (const QModelIndex& idx, int role) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return QVariant ();\n\n    float_display_format fmt;\n    if (role == Qt::DisplayRole)\n      fmt = m_display_fmt;\n    else\n      fmt.set_precision (m_value.is_single_type () ? 8 : 16);\n\n    std::string str = m_value.edit_display (fmt, row, col);\n\n    return QString::fromStdString (str);\n  }\n\n  QString subscript_expression (const QModelIndex& idx) const\n  {\n    if (! idx.isValid ())\n      return \"\";\n\n    return (QString (\"(%1,%2)\")\n            .arg (idx.row () + 1)\n            .arg (idx.column () + 1));\n  }\n};\n\nclass string_model : public base_ve_model\n{\npublic:\n\n  string_model (const QString& expr, const octave_value& val)\n    : base_ve_model (expr, val)\n  {\n    m_data_rows = 1;\n    m_data_cols = 1;\n\n    m_display_rows = 1;\n    m_display_cols = 1;\n  }\n\n  ~string_model () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (string_model)\n\n  QVariant edit_display (const QModelIndex&, int) const\n  {\n    // There isn't really a format for strings...\n\n    std::string str = m_value.edit_display (float_display_format (), 0, 0);\n\n    return QString::fromStdString (str);\n  }\n\n  char quote_char (const QModelIndex&) const\n  {\n    return get_quote_char (m_value);\n  }\n};\n\nclass cell_model : public base_ve_model\n{\npublic:\n\n  cell_model (const QString& expr, const octave_value& val)\n    : base_ve_model (expr, val)\n  {\n    // FIXME: should fill the window and expand on scrolling or\n    // resizing.\n\n    maybe_resize_rows (m_data_rows + 16);\n    maybe_resize_columns (m_data_cols + 16);\n  }\n\n  ~cell_model () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (cell_model)\n\n  void maybe_resize_rows (int rows)\n  {\n    if (rows > m_display_rows)\n      m_display_rows = rows;\n  }\n\n  void maybe_resize_columns (int cols)\n  {\n    if (cols > m_display_cols)\n      m_display_cols = cols;\n  }\n\n  QVariant edit_display (const QModelIndex& idx, int role) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return QVariant ();\n\n    Cell cval = m_value.cell_value ();\n\n    return edit_display_sub (cval(row, col), role);\n  }\n\n  bool requires_sub_editor (const QModelIndex& idx) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return false;\n\n    Cell cval = m_value.cell_value ();\n\n    return do_requires_sub_editor_sub (cval(row, col));\n  }\n\n  char quote_char (const QModelIndex& idx) const\n  {\n    octave_value ov = value_at (idx);\n\n    if (ov.is_string ())\n      return get_quote_char (ov);\n\n    return 0;\n  }\n\n  QString subscript_expression (const QModelIndex& idx) const\n  {\n    if (! idx.isValid ())\n      return \"\";\n\n    return (QString (\"{%1,%2}\")\n            .arg (idx.row () + 1)\n            .arg (idx.column () + 1));\n  }\n\n  octave_value value_at (const QModelIndex& idx) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return octave_value ();\n\n    Cell cval = m_value.cell_value ();\n\n    return cval(row, col);\n  }\n};\n\n// Scalar struct.  Rows are fields, single column for values.\n\nclass scalar_struct_model : public base_ve_model\n{\npublic:\n\n  scalar_struct_model (const QString& expr, const octave_value& val)\n    : base_ve_model (expr, val)\n  {\n    // No extra cells.  We currently don't allow new fields or\n    // additional values to be inserted.  If we allow additional values,\n    // then the object becomes a vector structure and the display flips\n    // (see the vector struct model below).  Do we want that?\n\n    m_data_rows = val.nfields ();\n    m_data_cols = 1;\n\n    m_display_rows = m_data_rows;\n    m_display_cols = 1;\n  }\n\n  ~scalar_struct_model () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (scalar_struct_model)\n\n  QVariant edit_display (const QModelIndex& idx, int role) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return QVariant ();\n\n    octave_scalar_map m = m_value.scalar_map_value ();\n\n    return edit_display_sub (m.contents (row), role);\n  }\n\n  bool requires_sub_editor (const QModelIndex& idx) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return false;\n\n    octave_scalar_map m = m_value.scalar_map_value ();\n\n    return do_requires_sub_editor_sub (m.contents (row));\n  }\n\n  char quote_char (const QModelIndex& idx) const\n  {\n    octave_value ov = value_at (idx);\n\n    if (ov.is_string ())\n      return get_quote_char (ov);\n\n    return 0;\n  }\n\n  QVariant header_data (int section, Qt::Orientation orientation,\n                        int role) const\n  {\n    if (role != Qt::DisplayRole)\n      return QVariant ();\n\n    switch (orientation)\n      {\n      case Qt::Horizontal:\n        if (section < data_columns ())\n          return QString (\"Values\");\n        else\n          break;\n\n      case Qt::Vertical:\n        if (section < data_rows ())\n          {\n            octave_scalar_map m = m_value.scalar_map_value ();\n\n            string_vector fields = m.fieldnames ();\n\n            return QString::fromStdString (fields(section));\n          }\n        else\n          break;\n\n      default:\n        break;\n      }\n\n    return QVariant ();\n  }\n\n  QString subscript_expression (const QModelIndex& idx) const\n  {\n    // Display size and data size match, so all valid indices should\n    // also be valid indices for the existing struct.\n\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return \"\";\n\n    octave_scalar_map m = m_value.scalar_map_value ();\n\n    string_vector fields = m.fieldnames ();\n\n    return QString (\".%1\").arg (QString::fromStdString (fields(row)));\n  }\n\n  octave_value value_at (const QModelIndex& idx) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return octave_value ();\n\n    octave_scalar_map m = m_value.scalar_map_value ();\n\n    return m.contents (row);\n  }\n};\n\nclass display_only_model : public base_ve_model\n{\npublic:\n\n  display_only_model (const QString& expr, const octave_value& val)\n    : base_ve_model (expr, val)\n  {\n    m_data_rows = 1;\n    m_data_cols = 1;\n\n    m_display_rows = m_data_rows;\n    m_display_cols = m_data_cols;\n  }\n\n  ~display_only_model () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (display_only_model)\n\n  bool is_editable () const { return false; }\n\n  QVariant edit_display (const QModelIndex&, int) const\n  {\n    if (m_value.is_undefined ())\n      return QVariant ();\n\n    std::ostringstream buf;\n\n    octave_value tval = m_value;\n\n    tval.print_with_name (buf, m_name);\n\n    return QString::fromStdString (buf.str ());\n  }\n\n  QString make_description_text () const\n  {\n    return (QString (\"unable to edit %1\")\n            .arg (base_ve_model::make_description_text ()));\n  }\n};\n\n// Vector struct.  Columns are fields, rows are values.\n\nclass vector_struct_model : public base_ve_model\n{\npublic:\n\n  vector_struct_model (const QString& expr, const octave_value& val)\n    : base_ve_model (expr, val)\n  {\n    // FIXME: should fill the window vertically and expand on scrolling\n    // or resizing.  No extra cells horizontally.  New fields must be\n    // added specially.\n\n    m_data_rows = val.numel ();\n    m_data_cols = val.nfields ();\n\n    maybe_resize_rows (m_data_rows + 16);\n    m_display_cols = m_data_cols;\n  }\n\n  ~vector_struct_model () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (vector_struct_model)\n\n  void maybe_resize_rows (int rows)\n  {\n    if (rows > m_display_rows)\n      m_display_rows = rows;\n  }\n\n  QVariant edit_display (const QModelIndex& idx, int role) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return QVariant ();\n\n    octave_map m = m_value.map_value ();\n\n    Cell cval = m.contents (col);\n\n    return edit_display_sub (cval(row), role);\n  }\n\n  bool requires_sub_editor (const QModelIndex& idx) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return false;\n\n    octave_map m = m_value.map_value ();\n\n    Cell cval = m.contents (col);\n\n    return do_requires_sub_editor_sub (cval(row));\n  }\n\n  char quote_char (const QModelIndex& idx) const\n  {\n    octave_value ov = value_at (idx);\n\n    if (ov.is_string ())\n      return get_quote_char (ov);\n\n    return 0;\n  }\n\n  QVariant header_data (int section, Qt::Orientation orientation,\n                        int role) const\n  {\n    if (role != Qt::DisplayRole)\n      return QVariant ();\n\n    switch (orientation)\n      {\n      case Qt::Horizontal:\n        if (section < data_columns ())\n          {\n            octave_map m = m_value.map_value ();\n\n            string_vector fields = m.fieldnames ();\n\n            return QString::fromStdString (fields(section));\n          }\n        else\n          break;\n\n      case Qt::Vertical:\n        if (section < data_rows ())\n          return QString::number (section+1);\n        else\n          break;\n\n      default:\n        break;\n      }\n\n    return QVariant ();\n  }\n\n  QString subscript_expression (const QModelIndex& idx) const\n  {\n    if (! idx.isValid ())\n      return \"\";\n\n    octave_map m = m_value.map_value ();\n\n    string_vector fields = m.fieldnames ();\n\n    return (QString (\"(%1).%2\")\n            .arg (idx.row () + 1)\n            .arg (QString::fromStdString (fields(idx.column ()))));\n  }\n\n  octave_value value_at (const QModelIndex& idx) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return octave_value ();\n\n    octave_map m = m_value.map_value ();\n\n    Cell cval = m.contents (col);\n\n    return cval(row);\n  }\n};\n\n// 2-D struct array.  Rows and columns index individual scalar structs.\n\nclass struct_model : public base_ve_model\n{\npublic:\n\n  struct_model (const QString& expr, const octave_value& val)\n    : base_ve_model (expr, val)\n  {\n    // FIXME: should fill the window and expand on scrolling or\n    // resizing.\n\n    maybe_resize_rows (m_data_rows + 16);\n    maybe_resize_columns (m_data_cols + 16);\n  }\n\n  ~struct_model () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (struct_model)\n\n  void maybe_resize_rows (int rows)\n  {\n    if (rows > m_display_rows)\n      m_display_rows = rows;\n  }\n\n  void maybe_resize_columns (int cols)\n  {\n    if (cols > m_display_cols)\n      m_display_cols = cols;\n  }\n\n  QVariant edit_display (const QModelIndex& idx, int) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return QVariant ();\n\n    std::string str = m_value.edit_display (m_display_fmt, row, col);\n    return QString::fromStdString (str);\n  }\n\n  bool requires_sub_editor (const QModelIndex& idx) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return false;\n\n    octave_map m = m_value.map_value ();\n\n    return do_requires_sub_editor_sub (m(row, col));\n  }\n\n  char quote_char (const QModelIndex& idx) const\n  {\n    octave_value ov = value_at (idx);\n\n    if (ov.is_string ())\n      return get_quote_char (ov);\n\n    return 0;\n  }\n\n  QString subscript_expression (const QModelIndex& idx) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return \"\";\n\n    return (QString (\"(%1,%2)\")\n            .arg (row + 1)\n            .arg (col + 1));\n  }\n\n  octave_value value_at (const QModelIndex& idx) const\n  {\n    int row;\n    int col;\n\n    if (! index_ok (idx, row, col))\n      return octave_value ();\n\n    octave_map m = m_value.map_value ();\n\n    return m(row, col);\n  }\n};\n\nbase_ve_model *\nvariable_editor_model::create (const QString& expr, const octave_value& val)\n{\n  // Choose specific model based on type of val.\n\n  if ((val.isnumeric () || val.islogical ()) && val.ndims () == 2)\n    return new numeric_model (expr, val);\n  else if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ()))\n    return new string_model (expr, val);\n  else if (val.iscell ())\n    return new cell_model (expr, val);\n  else if (val.isstruct ())\n    {\n      if (val.numel () == 1)\n        return new scalar_struct_model (expr, val);\n      else if (val.ndims () == 2)\n        {\n          if (val.rows () == 1 || val.columns () == 1)\n            return new vector_struct_model (expr, val);\n          else\n            return new struct_model (expr, val);\n        }\n    }\n\n  return new display_only_model (expr, val);\n}\n\nvariable_editor_model::variable_editor_model (const QString& expr,\n                                              const octave_value& val,\n                                              QObject *parent)\n  : QAbstractTableModel (parent), m_rep (create (expr, val))\n{\n  update_description ();\n\n  connect (this, &variable_editor_model::user_error_signal,\n           this, &variable_editor_model::user_error);\n\n  connect (this, &variable_editor_model::update_data_signal,\n           this, &variable_editor_model::update_data);\n\n  connect (this, &variable_editor_model::data_error_signal,\n           this, &variable_editor_model::data_error);\n\n  if (is_editable ())\n    {\n      int new_rows = display_rows ();\n\n      if (new_rows > 0)\n        {\n          beginInsertRows (QModelIndex (), 0, new_rows-1);\n          endInsertRows ();\n        }\n\n      int new_cols = display_columns ();\n\n      if (new_cols > 0)\n        {\n          beginInsertColumns (QModelIndex (), 0, new_cols-1);\n          endInsertColumns ();\n        }\n    }\n}\n\nbool\nvariable_editor_model::setData (const QModelIndex& idx,\n                                const QVariant& v_user_input, int role)\n{\n#if defined (QVARIANT_CANCONVERT_REQUIRES_QMETATYPE_ARGUMENT)\n  if (role != Qt::EditRole || ! v_user_input.canConvert (QMetaType (QMetaType::QString))\n      || ! idx.isValid ())\n#else\n  if (role != Qt::EditRole || ! v_user_input.canConvert (QMetaType::QString)\n      || ! idx.isValid ())\n#endif\n    return false;\n\n  // Initially, set value to whatever the user entered.\n\n  QString user_input = v_user_input.toString ();\n\n  char qc = quote_char (idx);\n\n  // FIXME: maybe we need a better way to ask whether empty input is\n  // valid than to rely on whether there is a quote character (meaning\n  // we are editing a character string)?\n  if (user_input.isEmpty () && ! qc)\n    return false;\n\n  set_update_pending (idx, user_input);\n\n  std::ostringstream os;\n\n  std::string nm = name ();\n  os << nm;\n\n  QString tmp = subscript_expression (idx);\n  os << tmp.toStdString () << \"=\";\n\n  if (qc)\n    os << qc;\n\n  os << user_input.toStdString ();\n\n  if (qc)\n    os << qc;\n\n  std::string expr = os.str ();\n\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<variable_editor_model> this_vem (this);\n\n  Q_EMIT interpreter_event\n    ([this, this_vem, expr, nm, idx] (interpreter& interp)\n    {\n      // INTERPRETER THREAD\n\n      // We are intentionally skipping any side effects that may occur\n      // in the evaluation of EXPR if THIS_VEM is no longer valid.\n\n      if (this_vem.isNull ())\n        return;\n\n      try\n        {\n          int parse_status = 0;\n          interp.eval_string (expr, true, parse_status);\n\n          octave_value val = retrieve_variable (interp, nm);\n\n          Q_EMIT update_data_signal (val);\n        }\n      catch (const execution_exception&)\n        {\n          clear_update_pending ();\n\n          evaluation_error (expr);\n\n          // This will cause the data in the cell to be reset\n          // from the cached octave_value object.\n\n          Q_EMIT dataChanged (idx, idx);\n        }\n    });\n\n  return true;\n}\n\nbool\nvariable_editor_model::clear_content (const QModelIndex& idx)\n{\n  int row = idx.row ();\n  int col = idx.column ();\n\n  if (row < data_rows () && col < data_columns ())\n    return setData (idx, QVariant (\"0\"));\n\n  return false;\n}\n\nQt::ItemFlags\nvariable_editor_model::flags (const QModelIndex& idx) const\n{\n  if (! is_valid ())\n    return Qt::NoItemFlags;\n\n  Qt::ItemFlags retval = QAbstractTableModel::flags (idx);\n\n  if (! requires_sub_editor (idx))\n    retval |= Qt::ItemIsEditable;\n\n  return retval;\n}\n\nbool\nvariable_editor_model::insertRows (int row, int count, const QModelIndex&)\n{\n  // FIXME: cells?\n\n  eval_expr_event\n    (QString (\"%1 = [%1(1:%2,:); zeros(%3,columns(%1)); %1(%2+%3:end,:)]\")\n     .arg (QString::fromStdString (name ()))\n     .arg (row)\n     .arg (count));\n\n  return true;\n}\n\nbool\nvariable_editor_model::removeRows (int row, int count, const QModelIndex&)\n{\n  if (row + count > data_rows ())\n    {\n      qDebug () << \"Tried to remove too many rows \"\n                << data_rows () << \" \"\n                << count << \" (\" << row << \")\";\n      return false;\n    }\n\n  eval_expr_event\n    (QString (\"%1(%2:%3,:) = []\")\n     .arg (QString::fromStdString (name ()))\n     .arg (row)\n     .arg (row + count));\n\n  return true;\n}\n\nbool\nvariable_editor_model::insertColumns (int col, int count, const QModelIndex&)\n{\n  eval_expr_event\n    (QString (\"%1 = [%1(:,1:%2); zeros(rows(%1),%3) %1(:,%2+%3:end)]\")\n     .arg (QString::fromStdString (name ()))\n     .arg (col)\n     .arg (count));\n\n  return true;\n}\n\nbool\nvariable_editor_model::removeColumns (int col, int count, const QModelIndex&)\n{\n  if (col + count > data_columns ())\n    {\n      qDebug () << \"Tried to remove too many cols \"\n                << data_columns () << \" \"\n                << count << \" (\" << col << \")\";\n      return false;\n    }\n\n  eval_expr_event\n    (QString (\"%1(:,%2:%3) = []\")\n     .arg (QString::fromStdString (name ()))\n     .arg (col)\n     .arg (col + count));\n\n  return true;\n}\n\nvoid\nvariable_editor_model::init_from_oct (interpreter& interp)\n{\n  // INTERPRETER THREAD\n\n  std::string nm = name ();\n\n  try\n    {\n      octave_value val = retrieve_variable (interp, nm);\n\n      Q_EMIT update_data_signal (val);\n    }\n  catch (const execution_exception&)\n    {\n      QString msg = (QString (\"variable '%1' is invalid or undefined\")\n                     .arg (QString::fromStdString (nm)));\n\n      Q_EMIT data_error_signal (msg);\n    }\n}\n\nvoid\nvariable_editor_model::eval_expr_event (const QString& expr_arg)\n{\n  std::string expr = expr_arg.toStdString ();\n\n  Q_EMIT interpreter_event\n    ([this, expr] (interpreter& interp)\n    {\n      // INTERPRETER THREAD\n\n      try\n        {\n          int parse_status = 0;\n          interp.eval_string (expr, true, parse_status);\n\n          init_from_oct (interp);\n        }\n      catch (const execution_exception&)\n        {\n          evaluation_error (expr);\n        }\n    });\n}\n\n// If the variable exists, load it into the data model.  If it doesn't\n// exist, flag the data model as referring to a nonexistent variable.\n// This allows the variable to be opened before it is created.\n\n// This function should only be called within other functions that\n// execute in the interpreter thread.  It should also be called in a\n// try-catch block that catches execution exceptions.\n\noctave_value\nvariable_editor_model::retrieve_variable (interpreter& interp,\n                                          const std::string& x)\n{\n  // INTERPRETER THREAD\n\n  std::string name = x;\n\n  name = name.substr (0, name.find (\".\"));\n\n  if (name.back () == ')' || name.back () == '}')\n    name = name.substr (0, name.find (name.back () == ')' ? \"(\" : \"{\"));\n\n  if (symbol_exist (name, \"var\") > 0)\n    {\n      int parse_status = 0;\n\n      octave_value result = interp.eval_string (x, true, parse_status);\n\n      if (result.is_cs_list ())\n        error (\"evaluation produced c-s list\");\n\n      return result;\n    }\n\n  return octave_value ();\n}\n\nvoid\nvariable_editor_model::evaluation_error (const std::string& expr) const\n{\n  Q_EMIT user_error_signal (\"Evaluation failed\",\n                            QString (\"failed to evaluate expression: '%1' or result can't be edited\")\n                            .arg (QString::fromStdString (expr)));\n}\n\nvoid\nvariable_editor_model::user_error (const QString& title, const QString& msg)\n{\n  QMessageBox::critical (nullptr, title, msg);\n}\n\nvoid\nvariable_editor_model::update_data_cache ()\n{\n  Q_EMIT interpreter_event\n    ([this] (interpreter& interp)\n    {\n      // INTERPRETER_THREAD\n\n      init_from_oct (interp);\n    });\n}\n\nvoid\nvariable_editor_model::update_data (const octave_value& val)\n{\n  if (val.is_undefined ())\n    {\n      QString msg = (QString (\"variable '%1' is invalid or undefined\")\n                     .arg (QString::fromStdString (name ())));\n\n      Q_EMIT data_error_signal (msg);\n\n      return;\n    }\n\n  // Add or remove rows and columns when the size changes.\n\n  int old_rows = display_rows ();\n  int old_cols = display_columns ();\n\n  reset (val);\n\n  int new_rows = display_rows ();\n  int new_cols = display_columns ();\n\n  if (new_rows != old_rows || new_cols != old_cols)\n    change_display_size (old_rows, old_cols, new_rows, new_cols);\n\n  // Even if the size doesn't change, we still need to update here\n  // because the data may have changed.  But only if we have some data\n  // to display.\n\n  if (new_rows > 0 && new_cols > 0)\n    Q_EMIT dataChanged (QAbstractTableModel::index (0, 0),\n                        QAbstractTableModel::index (new_rows-1, new_cols-1));\n\n  clear_update_pending ();\n}\n\nvoid\nvariable_editor_model::change_display_size (int old_rows, int old_cols,\n                                            int new_rows, int new_cols)\n{\n  if (new_rows < old_rows)\n    {\n      beginRemoveRows (QModelIndex (), new_rows, old_rows-1);\n      endRemoveRows ();\n    }\n  else if (new_rows > old_rows)\n    {\n      beginInsertRows (QModelIndex (), old_rows, new_rows-1);\n      endInsertRows ();\n    }\n\n  if (new_cols < old_cols)\n    {\n      beginRemoveColumns (QModelIndex (), new_cols, old_cols-1);\n      endRemoveColumns ();\n    }\n  else if (new_cols > old_cols)\n    {\n      beginInsertColumns (QModelIndex (), old_cols, new_cols-1);\n      endInsertColumns ();\n    }\n}\n\nvoid\nvariable_editor_model::maybe_resize_rows (int rows)\n{\n  int old_rows = display_rows ();\n  int old_cols = display_columns ();\n\n  m_rep->maybe_resize_rows (rows);\n\n  int new_rows = display_rows ();\n  int new_cols = display_columns ();\n\n  if (new_rows != old_rows)\n    change_display_size (old_rows, old_cols, new_rows, new_cols);\n}\n\nvoid\nvariable_editor_model::maybe_resize_columns (int cols)\n{\n  int old_rows = display_rows ();\n  int old_cols = display_columns ();\n\n  m_rep->maybe_resize_columns (cols);\n\n  int new_rows = display_rows ();\n  int new_cols = display_columns ();\n\n  if (new_cols != old_cols)\n    change_display_size (old_rows, old_cols, new_rows, new_cols);\n}\n\nvoid\nvariable_editor_model::data_error (const QString& msg)\n{\n  invalidate ();\n\n  update_description (msg);\n}\n\nvoid\nvariable_editor_model::reset (const octave_value& val)\n{\n  base_ve_model *old_rep = m_rep;\n\n  m_rep = create (QString::fromStdString (name ()), val);\n\n  delete old_rep;\n\n  update_description ();\n\n  Q_EMIT set_editable_signal (is_editable ());\n}\n\nvoid\nvariable_editor_model::invalidate ()\n{\n  beginResetModel ();\n\n  reset (octave_value ());\n\n  endResetModel ();\n}\n\nvoid\nvariable_editor_model::update_description (const QString& description)\n{\n  Q_EMIT description_changed (description.isEmpty ()\n                              ? make_description_text () : description);\n}\n\nvoid\nvariable_editor_model::double_click (const QModelIndex& idx)\n{\n  if (requires_sub_editor (idx))\n    {\n      QString name = QString::fromStdString (m_rep->name ());\n      Q_EMIT edit_variable_signal (name + subscript_expression (idx),\n                                   value_at (idx));\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/variable-editor-model.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_variable_editor_model_h)\n#define octave_variable_editor_model_h 1\n\n#include \"octave-config.h\"\n\n#include <QAbstractTableModel>\n#include <QMap>\n#include <QString>\n\n#include \"qt-interpreter-events.h\"\n\n#include \"ov.h\"\n#include \"pr-flt-fmt.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass base_ve_model\n{\npublic:\n\n  base_ve_model (const QString& expr, const octave_value& val);\n\n  virtual ~base_ve_model () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (base_ve_model)\n\n  virtual void maybe_resize_rows (int) { }\n\n  virtual void maybe_resize_columns (int) { }\n\n  std::string name () const;\n\n  bool index_ok (const QModelIndex& idx, int& row, int& col) const;\n\n  virtual bool is_editable () const { return true; }\n\n  virtual octave_value value_at (const QModelIndex& idx) const;\n\n  int column_width () const;\n\n  int rowCount (const QModelIndex& = QModelIndex ()) const;\n\n  int columnCount (const QModelIndex& = QModelIndex ()) const;\n\n  QString edit_display_sub (const octave_value& elt, int role) const;\n\n  virtual QVariant edit_display (const QModelIndex& idx, int role) const;\n\n  QVariant data (const QModelIndex& idx, int role = Qt::DisplayRole) const;\n\n  virtual bool requires_sub_editor (const QModelIndex& idx) const;\n\n  void set_update_pending (const QModelIndex& idx, const QString& str);\n\n  bool update_pending (const QModelIndex& idx) const;\n\n  QString update_pending_data (const QModelIndex& idx) const;\n\n  void clear_update_pending ();\n\n  virtual char quote_char (const QModelIndex& idx) const;\n\n  virtual QVariant\n  header_data (int section, Qt::Orientation orientation, int role) const;\n\n  // Return a subscript expression as a string that can be used to\n  // access a sub-element of a data structure.  For example \"{1,3}\"\n  // for cell array element {1,3} or \"(2,4)\" for array element (2,4).\n\n  virtual QString subscript_expression (const QModelIndex& idx) const;\n\n  bool is_valid () const { return m_valid; }\n\n  octave_idx_type data_rows () const { return m_data_rows; }\n\n  octave_idx_type data_columns () const { return m_data_cols; }\n\n  int display_rows () const { return m_display_rows; }\n\n  int display_columns () const { return m_display_cols; }\n\n  virtual QString make_description_text () const;\n\n  void reset (const octave_value& val);\n\nprotected:\n\n  std::string m_name;\n\n  octave_value m_value;\n\n  octave_idx_type m_data_rows;\n  octave_idx_type m_data_cols;\n\n  // Qt table widget limits the size to int.\n  int m_display_rows;\n  int m_display_cols;\n\n  QMap<QModelIndex, QString> m_update_pending;\n\n  bool m_valid;\n\n  float_display_format m_display_fmt;\n};\n\nclass variable_editor_model : public QAbstractTableModel\n{\n  Q_OBJECT\n\nprivate:\n\n  static base_ve_model * create (const QString& expr, const octave_value& val);\n\npublic:\n\n  variable_editor_model (const QString& expr, const octave_value& val,\n                         QObject *parent = nullptr);\n\n  ~variable_editor_model ()\n  {\n    delete m_rep;\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (variable_editor_model)\n\n  std::string name () const\n  {\n    return m_rep->name ();\n  }\n\n  bool is_editable () const\n  {\n    return m_rep->is_editable ();\n  }\n\n  octave_value value_at (const QModelIndex& idx) const\n  {\n    return m_rep->value_at (idx);\n  }\n\n  int column_width () const\n  {\n    return m_rep->column_width ();\n  }\n\n  int rowCount (const QModelIndex& idx = QModelIndex ()) const\n  {\n    return m_rep->rowCount (idx);\n  }\n\n  int columnCount (const QModelIndex& idx = QModelIndex ()) const\n  {\n    return m_rep->columnCount (idx);\n  }\n\n  QVariant data (const QModelIndex& idx = QModelIndex (),\n                 int role = Qt::DisplayRole) const\n  {\n    return m_rep->data (idx, role);\n  }\n\n  bool setData (const QModelIndex& idx, const QVariant& v,\n                int role = Qt::EditRole);\n\n  bool clear_content (const QModelIndex& idx);\n\n  Qt::ItemFlags flags (const QModelIndex& idx) const;\n\n  bool insertRows (int row, int count,\n                   const QModelIndex& parent = QModelIndex ());\n\n  bool removeRows (int row, int count,\n                   const QModelIndex& parent = QModelIndex ());\n\n  bool insertColumns (int column, int count,\n                      const QModelIndex& parent = QModelIndex ());\n\n  bool removeColumns (int column, int count,\n                      const QModelIndex& parent = QModelIndex ());\n\n  // Is cell at idx complex enough to require a sub editor?\n\n  bool requires_sub_editor (const QModelIndex& idx) const\n  {\n    return m_rep->requires_sub_editor (idx);\n  }\n\n  void set_update_pending (const QModelIndex& idx, const QString& str)\n  {\n    m_rep->set_update_pending (idx, str);\n  }\n\n  bool update_pending (const QModelIndex& idx) const\n  {\n    return m_rep->update_pending (idx);\n  }\n\n  QString update_pending_data (const QModelIndex& idx) const\n  {\n    return m_rep->update_pending_data (idx);\n  }\n\n  void clear_update_pending ()\n  {\n    m_rep->clear_update_pending ();\n  }\n\n  char quote_char (const QModelIndex& idx) const\n  {\n    return m_rep->quote_char (idx);\n  }\n\n  QVariant\n  headerData (int section, Qt::Orientation orientation, int role) const\n  {\n    return m_rep->header_data (section, orientation, role);\n  }\n\n  // Return a subscript expression as a string that can be used to\n  // access a sub-element of a data structure.  For example \"{1,3}\"\n  // for cell array element {1,3} or \"(2,4)\" for array element (2,4).\n\n  QString subscript_expression (const QModelIndex& idx) const\n  {\n    return m_rep->subscript_expression (idx);\n  }\n\n  int display_rows () const\n  {\n    return m_rep->display_rows ();\n  }\n\n  octave_idx_type data_rows () const\n  {\n    return m_rep->data_rows ();\n  }\n\n  int display_columns () const\n  {\n    return m_rep->display_columns ();\n  }\n\n  octave_idx_type data_columns () const\n  {\n    return m_rep->data_columns ();\n  }\n\n  void maybe_resize_rows (int rows);\n\n  void maybe_resize_columns (int cols);\n\nQ_SIGNALS:\n\n  void update_data_signal (const octave_value& val);\n\n  void data_error_signal (const QString& name) const;\n\n  void user_error_signal (const QString& title, const QString& msg) const;\n\n  void set_editable_signal (bool);\n\n  void description_changed (const QString& description);\n\n  void edit_variable_signal (const QString& name, const octave_value& val);\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  void update_data (const octave_value& val);\n\n  void update_data_cache ();\n\n  void double_click (const QModelIndex& idx);\n\nprivate Q_SLOTS:\n\n  void data_error (const QString& msg);\n\n  void user_error (const QString& title, const QString& msg);\n\nprivate:\n\n  base_ve_model *m_rep;\n\n  void init_from_oct (interpreter& interp);\n\n  void eval_expr_event (const QString& expr);\n\n  octave_value retrieve_variable (interpreter&, const std::string& name);\n\n  bool is_valid () const\n  {\n    return m_rep->is_valid ();\n  }\n\n  void change_display_size (int old_rows, int old_cols,\n                            int new_rows, int new_cols);\n\n  QString make_description_text () const\n  {\n    return m_rep->make_description_text ();\n  }\n\n  void reset (const octave_value& val);\n\n  void invalidate ();\n\n  void update_description (const QString& description = QString ());\n\n  void evaluation_error (const std::string& expr) const;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/variable-editor.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <limits>\n\n#include <QApplication>\n#include <QClipboard>\n#include <QFileDialog>\n#include <QHeaderView>\n#include <QLabel>\n#include <QMdiArea>\n#include <QMenu>\n#include <QPalette>\n#include <QPointer>\n#include <QRegularExpression>\n#include <QScreen>\n#include <QScrollBar>\n#include <QStackedWidget>\n#include <QTabWidget>\n#include <QTableView>\n#include <QTextEdit>\n#include <QToolBar>\n#include <QToolButton>\n#include <QVBoxLayout>\n\n#include \"builtin-defun-decls.h\"\n#include \"dw-main-window.h\"\n#include \"gui-preferences-cs.h\"\n#include \"gui-preferences-dw.h\"\n#include \"gui-preferences-global.h\"\n#include \"gui-preferences-sc.h\"\n#include \"gui-preferences-ve.h\"\n#include \"gui-settings.h\"\n#include \"octave-qt-features.h\"\n#include \"ovl.h\"\n#include \"qt-utils.h\"\n#include \"variable-editor-model.h\"\n#include \"variable-editor.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Code reuse functions\n\nstatic QSignalMapper *\nmake_plot_mapper (QMenu *menu)\n{\n  QList<QString> list;\n  list << \"plot\" << \"bar\" << \"stem\" << \"stairs\" << \"area\" << \"pie\" << \"hist\";\n\n  QSignalMapper *plot_mapper = new QSignalMapper (menu);\n\n  for (int i = 0; i < list.size (); ++i)\n    plot_mapper->setMapping\n      (menu->addAction (list.at (i), plot_mapper, SLOT (map ())), list.at (i));\n\n  return plot_mapper;\n}\n\n// Variable dock widget\n\nvariable_dock_widget::variable_dock_widget (QWidget *p)\n  : label_dock_widget (p)\n#if defined (HAVE_FLOATING_QDOCKWIDGET_UNSELECTABLE_BUG)\n    , m_waiting_for_mouse_move (false)\n    , m_waiting_for_mouse_button_release (false)\n#endif\n{\n  setFocusPolicy (Qt::StrongFocus);\n  setAttribute (Qt::WA_DeleteOnClose);\n\n  connect (m_dock_action, &QAction::triggered,\n           this, &variable_dock_widget::change_floating);\n  connect (m_close_action, &QAction::triggered,\n           this, &variable_dock_widget::change_existence);\n  connect (this, &variable_dock_widget::topLevelChanged,\n           this, &variable_dock_widget::toplevel_change);\n\n#define DOCKED_FULLSCREEN_BUTTON_TOOLTIP \"Fullscreen undock\"\n#define UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP \"Fullscreen\"\n  // Add a fullscreen button\n\n  m_fullscreen_action = nullptr;\n  m_full_screen = false;\n  m_prev_floating = false;\n  m_prev_geom = QRect (0, 0, 0, 0);\n\n  QHBoxLayout *h_layout = m_title_widget->findChild<QHBoxLayout *> ();\n\n  gui_settings settings;\n  m_fullscreen_action\n    = new QAction (settings.icon (\"view-fullscreen\", false), \"\", this);\n  m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP));\n  QToolButton *fullscreen_button = new QToolButton (m_title_widget);\n  fullscreen_button->setDefaultAction (m_fullscreen_action);\n  fullscreen_button->setFocusPolicy (Qt::NoFocus);\n  fullscreen_button->setIconSize (QSize (m_icon_size, m_icon_size));\n  QString css_button = QString (\"QToolButton {background: transparent; border: 0px;}\");\n  fullscreen_button->setStyleSheet (css_button);\n\n  connect (m_fullscreen_action, &QAction::triggered,\n           this, &variable_dock_widget::change_fullscreen);\n\n  int index = -1;\n  QToolButton *first = m_title_widget->findChild<QToolButton *> ();\n  if (first != nullptr)\n    index = h_layout->indexOf (first);\n  h_layout->insertWidget (index, fullscreen_button);\n\n  // Custom title bars cause loss of decorations, add a frame\n  m_frame = new QFrame (this);\n  m_frame->setFrameStyle (QFrame::Box | QFrame::Sunken);\n  m_frame->setAttribute (Qt::WA_TransparentForMouseEvents);\n}\n\n// slot for (un)dock action\nvoid\nvariable_dock_widget::change_floating (bool)\n{\n  if (isFloating ())\n    {\n      if (m_full_screen)\n        {\n          setGeometry (m_prev_geom);\n          gui_settings settings;\n          m_fullscreen_action->setIcon (settings.icon (\"view-fullscreen\", false));\n          m_full_screen = false;\n        }\n      m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP));\n    }\n  else\n    m_fullscreen_action->setToolTip (tr (UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP));\n\n  setFloating (! isFloating ());\n}\n\n// slot for hiding the widget\nvoid\nvariable_dock_widget::change_existence (bool)\n{\n  close ();\n}\n\nvoid\nvariable_dock_widget::toplevel_change (bool toplevel)\n{\n  if (toplevel)\n    {\n      m_dock_action->setIcon (QIcon (global_icon_paths.at (ICON_THEME_OCTAVE)\n                                     + \"widget-dock\" + global_icon_extension));\n      m_dock_action->setToolTip (tr (\"Dock Widget\"));\n\n      setWindowFlags (Qt::Window);\n      setWindowTitle (tr (\"Variable Editor: \") + objectName ());\n\n      show ();\n      activateWindow ();\n      setFocus ();\n\n#if defined (HAVE_FLOATING_QDOCKWIDGET_UNSELECTABLE_BUG)\n      m_waiting_for_mouse_move = true;\n#endif\n    }\n  else\n    {\n      m_dock_action->setIcon (QIcon (global_icon_paths.at (ICON_THEME_OCTAVE)\n                                     + \"widget-undock\" + global_icon_extension));\n      m_dock_action->setToolTip (tr (\"Undock Widget\"));\n\n      setFocus ();\n\n#if defined (HAVE_FLOATING_QDOCKWIDGET_UNSELECTABLE_BUG)\n      m_waiting_for_mouse_move = false;\n      m_waiting_for_mouse_button_release = false;\n#endif\n    }\n}\n\nvoid\nvariable_dock_widget::change_fullscreen ()\n{\n  gui_settings settings;\n\n  if (! m_full_screen)\n    {\n      m_prev_floating = isFloating ();\n      m_fullscreen_action->setIcon (settings.icon (\"view-restore\", false));\n      if (m_prev_floating)\n        m_fullscreen_action->setToolTip (tr (\"Restore geometry\"));\n      else\n        {\n          m_fullscreen_action->setToolTip (tr (\"Redock\"));\n          setFloating (true);\n        }\n      m_prev_geom = geometry ();\n\n      // showFullscreen() and setWindowState() only work for QWindow objects.\n      QScreen *pscreen = QGuiApplication::primaryScreen ();\n      QRect rect (0, 0, 0, 0);\n      rect = pscreen->availableGeometry ();\n      setGeometry (rect);\n\n      m_full_screen = true;\n    }\n  else\n    {\n      m_fullscreen_action->setIcon (settings.icon (\"view-fullscreen\", false));\n      setGeometry (m_prev_geom);\n      if (m_prev_floating)\n        m_fullscreen_action->setToolTip (tr (UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP));\n      else\n        {\n          setFloating (false);\n          m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP));\n        }\n\n      m_full_screen = false;\n    }\n#undef DOCKED_FULLSCREEN_BUTTON_TOOLTIP\n#undef UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP\n}\n\nvoid\nvariable_dock_widget::closeEvent (QCloseEvent *e)\n{\n  QDockWidget::closeEvent (e);\n}\n\nvoid\nvariable_dock_widget::handle_focus_change (QWidget *old, QWidget *now)\n{\n  octave_unused_parameter (now);\n\n  // This is a proxied test\n  if (hasFocus ())\n    {\n      if (old == this)\n        return;\n\n      if (titleBarWidget () != nullptr)\n        {\n          QLabel *label = titleBarWidget ()->findChild<QLabel *> ();\n          if (label != nullptr)\n            {\n              label->setBackgroundRole (QPalette::Highlight);\n              label->setStyleSheet (\"background-color: palette(highlight); color: palette(highlightedText);\");\n            }\n        }\n\n      Q_EMIT variable_focused_signal (objectName ());\n    }\n  else if (old == focusWidget ())\n    {\n      if (titleBarWidget () != nullptr)\n        {\n          QLabel *label = titleBarWidget ()->findChild<QLabel *> ();\n          if (label != nullptr)\n            {\n              label->setBackgroundRole (QPalette::NoRole);\n              label->setStyleSheet (\";\");\n            }\n        }\n    }\n}\n\nvoid\nvariable_dock_widget::resizeEvent (QResizeEvent *)\n{\n  if (m_frame)\n    m_frame->resize (size ());\n}\n\n#if defined (HAVE_FLOATING_QDOCKWIDGET_UNSELECTABLE_BUG)\n\nbool\nvariable_dock_widget::event (QEvent *event)\n{\n  // low-level check of whether docked-widget became a window via\n  // via drag-and-drop\n  if (event->type () == QEvent::MouseButtonPress)\n    {\n      m_waiting_for_mouse_move = false;\n      m_waiting_for_mouse_button_release = false;\n    }\n  if (event->type () == QEvent::MouseMove && m_waiting_for_mouse_move)\n    {\n      m_waiting_for_mouse_move = false;\n      m_waiting_for_mouse_button_release = true;\n    }\n  if (event->type () == QEvent::MouseButtonRelease\n      && m_waiting_for_mouse_button_release)\n    {\n      m_waiting_for_mouse_button_release = false;\n      bool retval = QDockWidget::event (event);\n      if (isFloating ())\n        Q_EMIT queue_unfloat_float ();\n      return retval;\n    }\n\n  return QDockWidget::event (event);\n}\n\nvoid\nvariable_dock_widget::unfloat_float ()\n{\n  hide ();\n  setFloating (false);\n  // Avoid a Ubunty Unity issue by queuing this rather than direct.\n  Q_EMIT queue_float ();\n  m_waiting_for_mouse_move = false;\n  m_waiting_for_mouse_button_release = false;\n}\n\nvoid\nvariable_dock_widget::refloat ()\n{\n  setFloating (true);\n  m_waiting_for_mouse_move = false;\n  m_waiting_for_mouse_button_release = false;\n  show ();\n  activateWindow ();\n  setFocus ();\n}\n\n#else\n\nvoid\nvariable_dock_widget::unfloat_float ()\n{ }\n\nvoid\nvariable_dock_widget::refloat ()\n{ }\n\n#endif\n\n// Variable editor stack\n\nvariable_editor_stack::variable_editor_stack (QWidget *p)\n  : QStackedWidget (p), m_edit_view (new variable_editor_view (this))\n{\n  setFocusPolicy (Qt::StrongFocus);\n\n  m_disp_view = make_disp_view (this);\n\n  addWidget (m_edit_view);\n  addWidget (m_disp_view);\n}\n\nQTextEdit *\nvariable_editor_stack::make_disp_view (QWidget *parent)\n{\n  QTextEdit *viewer = new QTextEdit (parent);\n\n  viewer->setLineWrapMode (QTextEdit::NoWrap);\n  viewer->setReadOnly (true);\n\n  return viewer;\n}\n\nvoid\nvariable_editor_stack::set_editable (bool editable)\n{\n  // The QTableView is for editable data models\n  // and the QTextEdit is for non-editable models.\n\n  if (editable)\n    {\n      if (m_edit_view != nullptr)\n        {\n          setCurrentWidget (m_edit_view);\n          setFocusProxy (m_edit_view);\n          m_edit_view->setFocusPolicy (Qt::StrongFocus);\n        }\n\n      if (m_disp_view != nullptr)\n        m_disp_view->setFocusPolicy (Qt::NoFocus);\n    }\n  else\n    {\n      if (m_disp_view != nullptr)\n        {\n          setCurrentWidget (m_disp_view);\n          setFocusProxy (m_disp_view);\n\n          QAbstractTableModel *model = findChild<QAbstractTableModel *> ();\n          if (model != nullptr)\n            m_disp_view->setPlainText (model->data (QModelIndex ()).toString ());\n          else\n            m_disp_view->setPlainText (\"\");\n        }\n\n      if (m_edit_view != nullptr)\n        m_edit_view->setFocusPolicy (Qt::NoFocus);\n    }\n}\n\nvoid\nvariable_editor_stack::levelUp ()\n{\n  if (! hasFocus ())\n    return;\n\n  QString name = objectName ();\n\n  // FIXME: Is there a better way?\n\n  if (name.endsWith (')') || name.endsWith ('}'))\n    {\n      name.remove (QRegularExpression {\"[({][^({]*[)}]$)\"});\n      Q_EMIT edit_variable_signal (name, octave_value ());\n    }\n}\n\n// Slot for saving a variable into a file\nvoid\nvariable_editor_stack::save (const QString& format)\n{\n  if (! hasFocus ())\n    return;\n\n  // Check whether a format for saving the variable is given\n  QString format_string;\n  if (! format.isEmpty ())\n    {\n      format_string = \"-\" + format;\n      do_save (format_string, format_string);\n      return;\n    }\n\n  // The interpreter_event callback function below emits a signal.\n  // Because we don't control when that happens, use a guarded pointer\n  // so that the callback can abort if this object is no longer valid.\n\n  QPointer<variable_editor_stack> this_ves (this);\n\n  // No format given, test save default options\n  Q_EMIT interpreter_event\n    ([this, this_ves, format_string] (interpreter& interp)\n      {\n        // INTERPRETER THREAD\n\n        // We can skip the entire callback function because it does\n        // not make any changes to the interpreter state.\n\n        if (this_ves.isNull ())\n          return;\n\n        octave_value_list argout\n          = Fsave_default_options (interp, octave_value_list (), 1);\n        QString save_opts = QString::fromStdString (argout(0).string_value ());\n\n        connect (this, &variable_editor_stack::do_save_signal,\n                 this, &variable_editor_stack::do_save);\n\n        Q_EMIT do_save_signal (format_string, save_opts);\n      });\n}\n\n// Perform saving the variable after desired format is determined\nvoid\nvariable_editor_stack::do_save (const QString& format, const QString& save_opts)\n{\n  QString file_ext = \"txt\";\n  for (int i = 0; i < ve_save_formats_ext.length ()/2; i++)\n    {\n      if (save_opts.contains (ve_save_formats_ext.at (2*i), Qt::CaseInsensitive))\n        {\n          file_ext = ve_save_formats_ext.at (2*i + 1);\n          break;\n        }\n    }\n\n  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.\n  int opts = 0;  // No options by default.\n\n  gui_settings settings;\n\n  if (! settings.bool_value (global_use_native_dialogs))\n    opts = QFileDialog::DontUseNativeDialog;\n\n  QString name = objectName ();\n  QString file\n    = QFileDialog::getSaveFileName (this,\n                                    tr (\"Save Variable %1 As\").arg (name),\n                                    QString (\"./%1.%2\").arg (name).arg (file_ext),\n                                    0, 0, QFileDialog::Option (opts));\n\n  if (file.isEmpty ())\n    return; // No file selected: Just return\n\n  // Let the interpreter thread do the saving\n  Q_EMIT interpreter_event\n    ([file, name, format] (interpreter& interp)\n      {\n        // INTERPRETER THREAD\n\n        octave_value_list ovl;\n        std::list<octave_value> str_list\n                            = {octave_value (file.toStdString ()),\n                               octave_value (name.toStdString ())};\n        if (! format.isEmpty ())\n          str_list.push_front (octave_value (format.toStdString ()));\n\n        Fsave (interp, octave_value_list (str_list));\n      });\n}\n\n// Custom editable variable table view\n\nvariable_editor_view::variable_editor_view (QWidget *p)\n  : QTableView (p), m_var_model (nullptr)\n{\n  setWordWrap (false);\n  setContextMenuPolicy (Qt::CustomContextMenu);\n  setSelectionMode (QAbstractItemView::ContiguousSelection);\n\n  horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu);\n  verticalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu);\n\n  setHorizontalScrollMode (QAbstractItemView::ScrollPerPixel);\n  setVerticalScrollMode (QAbstractItemView::ScrollPerPixel);\n\n  verticalHeader ()->setSectionResizeMode (QHeaderView::Interactive);\n}\n\nvoid\nvariable_editor_view::setModel (QAbstractItemModel *model)\n{\n  QTableView::setModel (model);\n\n  horizontalHeader ()->setSectionResizeMode (QHeaderView::Interactive);\n\n  m_var_model = parent ()->findChild<variable_editor_model *> ();\n\n  if (m_var_model != nullptr && m_var_model->column_width () > 0)\n    {\n      // col_width is in characters.  The font should be a fixed-width\n      // font, so any character will do.  If not, you lose!\n\n      QFontMetrics fm (font ());\n      int w = (m_var_model->column_width ()\n               * qt_fontmetrics_horizontal_advance (fm, '0'));\n      horizontalHeader ()->setDefaultSectionSize (w);\n    }\n}\n\nQList<int>\nvariable_editor_view::range_selected ()\n{\n  QItemSelectionModel *sel = selectionModel ();\n\n  // Return early if nothing selected.\n  if (! sel->hasSelection ())\n    return QList<int> ();\n\n  QList<QModelIndex> indices = sel->selectedIndexes ();\n\n  // FIXME: Shouldn't this be keyed to octave_idx_type?\n\n  int32_t from_row = std::numeric_limits<int32_t>::max ();\n  int32_t to_row = 0;\n  int32_t from_col = std::numeric_limits<int32_t>::max ();\n  int32_t to_col = 0;\n\n  for (const auto& idx : indices)\n    {\n      from_row = std::min (from_row, idx.row ());\n      to_row = std::max (to_row, idx.row ());\n      from_col = std::min (from_col, idx.column ());\n      to_col = std::max (to_col, idx.column ());\n    }\n\n  QVector<int> vect;\n  vect << from_row + 1 << to_row + 1 << from_col + 1 << to_col + 1;\n  QList<int> range = QList<int>::fromVector (vect);\n\n  return range;\n}\n\nvoid\nvariable_editor_view::selected_command_requested (const QString& cmd)\n{\n  if (! hasFocus ())\n    return;\n\n  QList<int> range = range_selected ();\n  if (range.isEmpty ())\n    {\n      // Nothing selected, apply print command to all data\n      range << 1 << m_var_model->data_rows ()\n            << 1 << m_var_model->data_columns ();\n    }\n\n  int s1 = m_var_model->data_rows ();\n  int s2 = m_var_model->data_columns ();\n  if (s1 < range.at (0) || s2 < range.at (2))\n    return; // Selected range does not contain data\n\n  s1 = std::min (s1, range.at (1));\n  s2 = std::min (s2, range.at (3));\n\n  // Variable with desired range as string\n  QString variable = QString (\"%1(%2:%3,%4:%5)\")\n                     .arg (objectName ())\n                     .arg (range.at (0)).arg (s1)\n                     .arg (range.at (2)).arg (s2);\n\n  // Desired command as string\n  QString command;\n  if (cmd == \"create\")\n    command = QString (\"unnamed = %1;\").arg (variable);\n  else\n    command = QString (\"figure (); %1 (%2); title ('%2');\")\n              .arg (cmd).arg (variable);\n\n  Q_EMIT command_signal (command);\n}\n\nvoid\nvariable_editor_view::add_edit_actions (QMenu *menu,\n                                        const QString& qualifier_string)\n{\n  gui_settings settings;\n\n  menu->addAction (settings.icon (\"edit-cut\"),\n                   tr (\"Cut\") + qualifier_string,\n                   this, &variable_editor_view::cutClipboard);\n\n  menu->addAction (settings.icon (\"edit-copy\"),\n                   tr (\"Copy\") + qualifier_string,\n                   this, &variable_editor_view::copyClipboard);\n\n  menu->addAction (settings.icon (\"edit-paste\"),\n                   tr (\"Paste\"),\n                   this, &variable_editor_view::pasteClipboard);\n\n  menu->addSeparator ();\n\n  menu->addAction (settings.icon (\"edit-delete\"),\n                   tr (\"Clear\") + qualifier_string,\n                   this, &variable_editor_view::clearContent);\n\n  menu->addAction (settings.icon (\"edit-delete\"),\n                   tr (\"Delete\") + qualifier_string,\n                   this, &variable_editor_view::delete_selected);\n\n  menu->addAction (settings.icon (\"document-new\"),\n                   tr (\"Variable from Selection\"),\n                   this, &variable_editor_view::createVariable);\n}\n\nvoid\nvariable_editor_view::createContextMenu (const QPoint& qpos)\n{\n  QModelIndex index = indexAt (qpos);\n\n  if (index.isValid ())\n    {\n      QMenu *menu = new QMenu (this);\n\n      add_edit_actions (menu, tr (\"\"));\n\n      // FIXME: addAction for sort?\n      // FIXME: Add icon for transpose.\n\n      menu->addAction (tr (\"Transpose\"),\n                       this, &variable_editor_view::transposeContent);\n\n      QItemSelectionModel *sel = selectionModel ();\n\n      QList<QModelIndex> indices = sel->selectedIndexes ();\n\n      if (! indices.isEmpty ())\n        {\n          menu->addSeparator ();\n\n          QSignalMapper *plot_mapper = make_plot_mapper (menu);\n\n#if defined (HAVE_QSIGNALMAPPER_MAPPEDSTRING)\n          connect (plot_mapper, SIGNAL (mappedString (const QString&)),\n                   this, SLOT (selected_command_requested (const QString&)));\n#else\n          connect (plot_mapper, SIGNAL (mapped (const QString&)),\n                   this, SLOT (selected_command_requested (const QString&)));\n#endif\n        }\n\n      menu->exec (mapToGlobal (qpos));\n    }\n}\n\nvoid\nvariable_editor_view::createColumnMenu (const QPoint& pt)\n{\n  int index = horizontalHeader ()->logicalIndexAt (pt);\n\n  if (index < 0 || index > model ()->columnCount ())\n    return;\n\n  QList<int> coords = range_selected ();\n\n  bool nothingSelected = coords.isEmpty ();\n\n  bool whole_columns_selected\n    =  (nothingSelected\n        ? false\n        : (coords[0] == 1 && coords[1] == model ()->rowCount ()));\n\n  bool current_column_selected\n    = nothingSelected ? false : (coords[2] <= index+1 && coords[3] > index);\n\n  int column_selection_count\n    = nothingSelected ? 0 : (coords[3] - coords[2] + 1);\n\n  if (! whole_columns_selected || ! current_column_selected)\n    {\n      selectColumn (index);\n      column_selection_count = 1;\n    }\n\n  QString column_string\n    = column_selection_count > 1 ? tr (\" columns\") : tr (\" column\");\n\n  QMenu *menu = new QMenu (this);\n\n  add_edit_actions (menu, column_string);\n\n  menu->addSeparator ();\n\n  QSignalMapper *plot_mapper = make_plot_mapper (menu);\n\n#if defined (HAVE_QSIGNALMAPPER_MAPPEDSTRING)\n  connect (plot_mapper, SIGNAL (mappedString (const QString&)),\n           this, SLOT (selected_command_requested (const QString&)));\n#else\n  connect (plot_mapper, SIGNAL (mapped (const QString&)),\n           this, SLOT (selected_command_requested (const QString&)));\n#endif\n\n  QPoint menupos = pt;\n  menupos.setY (horizontalHeader ()->height ());\n\n  menu->exec (mapToGlobal (menupos));\n}\n\nvoid\nvariable_editor_view::createRowMenu (const QPoint& pt)\n{\n  int index = verticalHeader ()->logicalIndexAt (pt);\n\n  if (index < 0 || index > model ()->columnCount ())\n    return;\n\n  QList<int> coords = range_selected ();\n\n  bool nothingSelected = coords.isEmpty ();\n\n  bool whole_rows_selected\n    = (nothingSelected\n       ? false\n       : (coords[2] == 1 && coords[3] == model ()->columnCount ()));\n\n  bool current_row_selected\n    = (nothingSelected ? false : (coords[0] <= index+1 && coords[1] > index));\n\n  int rowselection_count = nothingSelected ? 0 : (coords[3] - coords[2] + 1);\n\n  if (! whole_rows_selected || ! current_row_selected)\n    {\n      selectRow (index);\n      rowselection_count = 1;\n    }\n\n  QString row_string = rowselection_count > 1 ? tr (\" rows\") : tr (\" row\");\n\n  QMenu *menu = new QMenu (this);\n\n  add_edit_actions (menu, row_string);\n\n  menu->addSeparator ();\n\n  QSignalMapper *plot_mapper = make_plot_mapper (menu);\n\n#if defined (HAVE_QSIGNALMAPPER_MAPPEDSTRING)\n  connect (plot_mapper, SIGNAL (mappedString (const QString&)),\n           this, SLOT (selected_command_requested (const QString&)));\n#else\n  connect (plot_mapper, SIGNAL (mapped (const QString&)),\n           this, SLOT (selected_command_requested (const QString&)));\n#endif\n  QPoint menupos = pt;\n  menupos.setX (verticalHeader ()->width ());\n\n  // FIXME: What was the intent here?\n  // setY (verticalHeader ()->sectionPosition (index+1) +\n  //       verticalHeader ()->sectionSize (index));\n\n  menu->exec (mapToGlobal (menupos));\n}\n\nvoid\nvariable_editor_view::createVariable ()\n{\n  // FIXME: Create unnamed1..n if exist ('unnamed', 'var') is true.\n\n  selected_command_requested (\"create\");\n}\n\nvoid\nvariable_editor_view::transposeContent ()\n{\n  if (! hasFocus ())\n    return;\n\n  Q_EMIT command_signal (QString (\"%1 = %1';\").arg (objectName ()));\n}\n\nvoid\nvariable_editor_view::delete_selected ()\n{\n  if (! hasFocus ())\n    return;\n\n  QAbstractItemModel *mod = model ();\n  QList<int> coords = range_selected ();\n\n  if (coords.isEmpty ())\n    return;\n\n  bool whole_columns_selected\n    = coords[0] == 1 && coords[1] == mod->rowCount ();\n\n  bool whole_rows_selected\n    = coords[2] == 1 && coords[3] == mod->columnCount ();\n\n  // Must be deleting whole columns or whole rows, and not the whole thing.\n\n  if (whole_columns_selected == whole_rows_selected)\n    return;\n\n  if (whole_rows_selected)\n    mod->removeRows (coords[0], coords[1] - coords[0]);\n\n  if (whole_columns_selected)\n    mod->removeColumns (coords[2], coords[3] - coords[2]);\n}\n\nvoid\nvariable_editor_view::clearContent ()\n{\n  if (! hasFocus ())\n    return;\n\n  if (m_var_model == nullptr)\n    return;\n\n  QItemSelectionModel *sel = selectionModel ();\n  QList<QModelIndex> indices = sel->selectedIndexes ();\n\n  // FIXME: Use [] for empty cells?\n\n  for (const auto& idx : indices)\n    m_var_model->clear_content (idx);\n}\n\nvoid\nvariable_editor_view::cutClipboard ()\n{\n  copyClipboard ();\n\n  clearContent ();\n}\n\nvoid\nvariable_editor_view::copyClipboard ()\n{\n  if (! hasFocus ())\n    return;\n\n  QItemSelectionModel *sel = selectionModel ();\n  QList<QModelIndex> indices = sel->selectedIndexes ();\n  std::sort (indices.begin (), indices.end ());\n\n  if (indices.isEmpty ())\n    return;\n\n  // Convert selected items into TSV format and copy that.\n  // Spreadsheet tools should understand that.\n\n  QAbstractItemModel *mod = model ();\n  QModelIndex previous = indices.first ();\n  QString copy = mod->data (previous).toString ();\n  indices.removeFirst ();\n  for (auto idx : indices)\n    {\n      copy.push_back (previous.row () != idx.row () ? '\\n' : '\\t');\n      copy.append (mod->data (idx).toString ());\n      previous = idx;\n    }\n\n  QClipboard *clipboard = QApplication::clipboard ();\n  clipboard->setText (copy);\n}\n\nvoid\nvariable_editor_view::pasteClipboard ()\n{\n  if (! hasFocus ())\n    return;\n\n  QAbstractItemModel *mod = model ();\n  QItemSelectionModel *sel = selectionModel ();\n  QList<QModelIndex> indices = sel->selectedIndexes ();\n\n  QClipboard *clipboard = QApplication::clipboard ();\n  QString text = clipboard->text ();\n\n  QPoint start, end;\n\n  QPoint tabsize = QPoint (mod->rowCount (), mod->columnCount ());\n\n  if (indices.isEmpty ())\n    {\n      start = QPoint (0, 0);\n      end = tabsize;\n    }\n  else if (indices.size () == 1)\n    {\n      start = QPoint (indices[0].row (), indices[0].column ());\n      end = tabsize;\n    }\n  else\n    {\n      end = QPoint (0, 0);\n      start = tabsize;\n\n      for (int i = 0; i < indices.size (); i++)\n        {\n          if (indices[i].column () < start.y ())\n            start.setY (indices[i].column ());\n\n          if (indices[i].column () > end.y ())\n            end.setY (indices[i].column ());\n\n          if (indices[i].row () < start.x ())\n            start.setX (indices[i].column ());\n\n          if (indices[i].row () > end.x ())\n            end.setX (indices[i].column ());\n        }\n    }\n\n  int rownum = 0;\n  int colnum = 0;\n\n  QStringList rows = text.split ('\\n');\n  for (const auto& row : rows)\n    {\n      if (rownum > end.x () - start.x ())\n        continue;\n\n      QStringList cols = row.split ('\\t');\n      if (cols.isEmpty ())\n        continue;\n\n      for (const auto& col : cols)\n        {\n          if (col.isEmpty ())\n            continue;\n          if (colnum > end.y () - start.y () )\n            continue;\n\n          mod->setData (mod->index (rownum + start.x (),\n                                    colnum + start.y ()),\n                        QVariant (col));\n\n          colnum++;\n        }\n\n      colnum = 0;\n      rownum++;\n    }\n}\n\nvoid\nvariable_editor_view::handle_horizontal_scroll_action (int action)\n{\n  if (action == QAbstractSlider::SliderSingleStepAdd\n      || action == QAbstractSlider::SliderPageStepAdd\n      || action == QAbstractSlider::SliderToMaximum\n      || action == QAbstractSlider::SliderMove)\n    {\n      if (m_var_model != nullptr)\n        {\n          QScrollBar *sb = horizontalScrollBar ();\n\n          if (sb && sb->value () == sb->maximum ())\n            {\n              int new_cols = m_var_model->display_columns () + 16;\n\n              m_var_model->maybe_resize_columns (new_cols);\n            }\n        }\n    }\n}\n\nvoid\nvariable_editor_view::handle_vertical_scroll_action (int action)\n{\n  if (action == QAbstractSlider::SliderSingleStepAdd\n      || action == QAbstractSlider::SliderPageStepAdd\n      || action == QAbstractSlider::SliderToMaximum\n      || action == QAbstractSlider::SliderMove)\n    {\n      if (m_var_model != nullptr)\n        {\n          QScrollBar *sb = verticalScrollBar ();\n\n          if (sb && sb->value () == sb->maximum ())\n            {\n              int new_rows = m_var_model->display_rows () + 16;\n\n              m_var_model->maybe_resize_rows (new_rows);\n            }\n        }\n    }\n}\n\n// Gadgets for focus restoration\n\nHoverToolButton::HoverToolButton (QWidget *parent)\n  : QToolButton (parent)\n{\n  installEventFilter (this);\n}\n\nbool\nHoverToolButton::eventFilter (QObject *obj, QEvent *ev)\n{\n  if (ev->type () == QEvent::HoverEnter)\n    Q_EMIT hovered_signal ();\n  else if (ev->type () == QEvent::MouseButtonPress)\n    Q_EMIT popup_shown_signal ();\n\n  return QToolButton::eventFilter (obj, ev);\n}\n\nReturnFocusToolButton::ReturnFocusToolButton (QWidget *parent)\n  : HoverToolButton (parent)\n{\n  installEventFilter (this);\n}\n\nbool\nReturnFocusToolButton::eventFilter (QObject *obj, QEvent *ev)\n{\n\n  if (ev->type () == QEvent::MouseButtonRelease && isDown ())\n    {\n      Q_EMIT about_to_activate ();\n\n      setDown (false);\n      QAction *action = defaultAction ();\n      if (action != nullptr)\n        action->activate (QAction::Trigger);\n\n      return true;\n    }\n\n  return HoverToolButton::eventFilter (obj, ev);\n}\n\nReturnFocusMenu::ReturnFocusMenu (QWidget *parent)\n  : QMenu (parent)\n{\n  installEventFilter (this);\n}\n\nbool\nReturnFocusMenu::eventFilter (QObject *obj, QEvent *ev)\n{\n  if (ev->type () == QEvent::MouseButtonRelease && underMouse ())\n    {\n      Q_EMIT about_to_activate ();\n    }\n\n  return QMenu::eventFilter (obj, ev);\n}\n\n// Variable editor.\n\nvariable_editor::variable_editor (QWidget *p)\n  : octave_dock_widget (\"VariableEditor\", p),\n    m_main (new dw_main_window ()),\n    m_tool_bar (new QToolBar (m_main)),\n    m_default_width (30),\n    m_default_height (100),\n    m_add_font_height (0),\n    m_use_terminal_font (true),\n    m_alternate_rows (true),\n    m_stylesheet (\"\"),\n    m_font (),\n    m_sel_font (),\n    m_table_colors (),\n    m_variables (QList<variable_dock_widget*>  ()),\n    m_current_focus_vname (\"\"),\n    m_hovered_focus_vname (\"\"),\n    m_plot_mapper (nullptr),\n    m_focus_widget (nullptr),\n    m_focus_widget_vdw (nullptr)\n{\n  set_title (tr (\"Variable Editor\"));\n  setStatusTip (tr (\"Edit variables.\"));\n  setAttribute (Qt::WA_AlwaysShowToolTips);\n\n  m_main->setParent (this);\n#if defined (HAVE_QDOCKWIDGET_REORDERING_BUG)\n  m_main->setDockOptions (QMainWindow::AnimatedDocks |\n                          QMainWindow::AllowNestedDocks |\n                          QMainWindow::VerticalTabs);\n#else\n  m_main->setDockNestingEnabled (true);\n#endif\n\n  // Tool Bar.\n\n  construct_tool_bar ();\n  m_main->addToolBar (m_tool_bar);\n\n  // Colors.\n\n  for (int i = 0; i < ve_colors_count; i++)\n    m_table_colors.append (QColor (Qt::white));\n\n  // Use an MDI area that is shrunk to nothing as the central widget.\n  // Future feature might be to switch to MDI mode in which the dock\n  // area is shrunk to nothing and the widgets live in the MDI window.\n\n  QMdiArea *central_mdiarea = new QMdiArea (m_main);\n  central_mdiarea->setMinimumSize (QSize (0, 0));\n  central_mdiarea->setMaximumSize (QSize (0, 0));\n  central_mdiarea->resize (QSize (0, 0));\n  m_main->setCentralWidget (central_mdiarea);\n\n  setWidget (m_main);\n\n  if (! p)\n    make_window ();\n}\n\nvoid\nvariable_editor::focusInEvent (QFocusEvent *ev)\n{\n  octave_dock_widget::focusInEvent (ev);\n\n  // set focus to the current variable or most recent if still valid\n  if (m_focus_widget != nullptr)\n    {\n      // Activating a floating window causes problems.\n      if (! m_focus_widget_vdw->isFloating ())\n        activateWindow ();\n      m_focus_widget->setFocus ();\n    }\n  else\n    {\n      QWidget *fw = m_main->focusWidget ();\n      if (fw != nullptr)\n        {\n          activateWindow ();\n          fw->setFocus ();\n        }\n      else\n        {\n          bool focus_set = false;\n          for (long long int i = 0; i < m_variables.size (); i++)\n            {\n              if (m_variables.at (i) != nullptr)\n                {\n                  activateWindow ();\n                  m_variables.at (i)->setFocus ();\n                  focus_set = true;\n                  break;\n                }\n            }\n          if (! focus_set)\n            setFocus ();\n        }\n    }\n}\n\nvariable_editor::~variable_editor ()\n{\n  // Disconnect the destroyed() signals from all variable_dock_widget\n  // other wise the non existing slot in variable_editor seems to be\n  // accessed in Qt6 leading to a crash (signal 6).\n  for (long long int i = 0; i < m_variables.size (); i++)\n    {\n      if (m_variables.at (i) != nullptr)\n        disconnect (m_variables.at (i), SIGNAL (destroyed (QObject *)), 0, 0);\n    }\n}\n\nvoid\nvariable_editor::edit_variable (const QString& name, const octave_value& val)\n{\n  if (m_stylesheet.isEmpty ())\n    notice_settings ();\n\n  QDockWidget *existing_qdw = m_main->findChild<QDockWidget *> (name);\n  if (existing_qdw)\n    {\n      // Already open.\n\n      // Put current focused variable out of focus\n      if (m_main->focusWidget () != nullptr)\n        {\n          QFocusEvent event (QEvent::FocusOut, Qt::OtherFocusReason);\n          QApplication::sendEvent (m_main->focusWidget (), &event);\n        }\n\n      // Put existing variable in focus and raise\n      m_main->parentWidget ()->show ();\n      existing_qdw->show ();\n      existing_qdw->raise ();\n      existing_qdw->activateWindow ();\n      tab_to_front ();\n      existing_qdw->setFocus ();\n\n      return;\n    }\n\n  variable_dock_widget *page = new variable_dock_widget (this);\n\n  m_variables << page;\n\n  page->setObjectName (name);\n  m_main->addDockWidget (Qt::LeftDockWidgetArea, page);\n\n  // The old-style signal/slot connection appears to be needed here to\n  // prevent a crash when closing a variable_dock_widget object.\n  connect (qApp, SIGNAL (focusChanged (QWidget *, QWidget *)),\n           page, SLOT (handle_focus_change (QWidget *, QWidget *)));\n\n  connect (this, &variable_editor::visibilityChanged,\n           page, &variable_dock_widget::setVisible);\n\n  // Notify the variable editor for page actions.\n  connect (page, &variable_dock_widget::destroyed,\n           this, &variable_editor::variable_destroyed);\n  connect (page, &variable_dock_widget::variable_focused_signal,\n           this, &variable_editor::variable_focused);\n\n#if defined (HAVE_FLOATING_QDOCKWIDGET_UNSELECTABLE_BUG)\n  connect (page, SIGNAL (queue_unfloat_float ()),\n           page, SLOT (unfloat_float ()), Qt::QueuedConnection);\n  connect (page, SIGNAL (queue_float ()),\n           page, SLOT (refloat ()), Qt::QueuedConnection);\n#endif\n\n  variable_editor_stack *stack = new variable_editor_stack (page);\n\n  stack->setObjectName (name);\n  page->setWidget (stack);\n  page->setFocusProxy (stack);\n\n  // Any interpreter_event signal from a variable_editor_stack object is\n  // handled the same as for the parent variable_editor object.\n  connect (stack, qOverload<const fcn_callback&> (&variable_editor_stack::interpreter_event),\n           this, qOverload<const fcn_callback&> (&variable_editor::interpreter_event));\n\n  connect (stack, qOverload<const meth_callback&> (&variable_editor_stack::interpreter_event),\n           this, qOverload<const meth_callback&> (&variable_editor::interpreter_event));\n\n  connect (stack, &variable_editor_stack::edit_variable_signal,\n           this, &variable_editor::edit_variable);\n  connect (this, &variable_editor::level_up_signal,\n           stack, &variable_editor_stack::levelUp);\n  connect (this, &variable_editor::save_signal,\n           stack, [stack] () { stack->save (); });\n\n  variable_editor_view *edit_view = stack->edit_view ();\n\n  edit_view->setObjectName (name);\n  edit_view->setFont (m_font);\n  edit_view->setStyleSheet (m_stylesheet);\n  edit_view->setAlternatingRowColors (m_alternate_rows);\n  edit_view->verticalHeader ()->setDefaultSectionSize (m_default_height\n                                                       + m_add_font_height);\n\n#if defined (HAVE_QSIGNALMAPPER_MAPPEDSTRING)\n  connect (m_plot_mapper, SIGNAL (mappedString (const QString&)),\n           edit_view, SLOT (selected_command_requested (const QString&)));\n  connect (m_save_mapper, SIGNAL (mappedString (const QString&)),\n           stack, SLOT (save (const QString&)));\n#else\n  connect (m_plot_mapper, SIGNAL (mapped (const QString&)),\n           edit_view, SLOT (selected_command_requested (const QString&)));\n  connect (m_save_mapper, SIGNAL (mapped (const QString&)),\n           stack, SLOT (save (const QString&)));\n#endif\n\n  connect (edit_view, &variable_editor_view::command_signal,\n           this, &variable_editor::command_signal);\n  connect (this, &variable_editor::delete_selected_signal,\n           edit_view, &variable_editor_view::delete_selected);\n  connect (this, &variable_editor::clear_content_signal,\n           edit_view, &variable_editor_view::clearContent);\n  connect (this, &variable_editor::copy_clipboard_signal,\n           edit_view, &variable_editor_view::copyClipboard);\n  connect (this, &variable_editor::paste_clipboard_signal,\n           edit_view, &variable_editor_view::pasteClipboard);\n  connect (edit_view->horizontalHeader (),\n           &QHeaderView::customContextMenuRequested,\n           edit_view, &variable_editor_view::createColumnMenu);\n  connect (edit_view->verticalHeader (),\n           &QHeaderView::customContextMenuRequested,\n           edit_view, &variable_editor_view::createRowMenu);\n  connect (edit_view, &variable_editor_view::customContextMenuRequested,\n           edit_view, &variable_editor_view::createContextMenu);\n  connect (edit_view->horizontalScrollBar (), &QScrollBar::actionTriggered,\n           edit_view, &variable_editor_view::handle_horizontal_scroll_action);\n  connect (edit_view->verticalScrollBar (), &QScrollBar::actionTriggered,\n           edit_view, &variable_editor_view::handle_vertical_scroll_action);\n\n  variable_editor_model *model =\n    new variable_editor_model (name, val, stack);\n\n  connect (model, &variable_editor_model::edit_variable_signal,\n           this, &variable_editor::edit_variable);\n  connect (model, &variable_editor_model::dataChanged,\n           this, &variable_editor::callUpdate);\n  connect (this, &variable_editor::refresh_signal,\n           model, &variable_editor_model::update_data_cache);\n  connect (model, &variable_editor_model::set_editable_signal,\n           stack, &variable_editor_stack::set_editable);\n\n  edit_view->setModel (model);\n  connect (edit_view, &variable_editor_view::doubleClicked,\n           model, &variable_editor_model::double_click);\n\n  // Any interpreter_event signal from a variable_editor_model object is\n  // handled the same as for the parent variable_editor object.\n\n  connect (model, qOverload<const fcn_callback&> (&variable_editor_model::interpreter_event),\n           this, qOverload<const fcn_callback&> (&variable_editor::interpreter_event));\n\n  connect (model, qOverload<const meth_callback&> (&variable_editor_model::interpreter_event),\n           this, qOverload<const meth_callback&> (&variable_editor::interpreter_event));\n\n  // Must supply a title for a QLabel to be created.  Calling set_title()\n  // more than once will add more QLabels.  Could change octave_dock_widget\n  // to always supply a QLabel (initially empty) and then simply update its\n  // contents.\n  page->set_title (name);\n  if (page->titleBarWidget () != nullptr)\n    {\n      QLabel *existing_ql = page->titleBarWidget ()->findChild<QLabel *> ();\n\n      // FIXME: What was the intent here?  update_label_signal does\n      // not seem to exist now.\n      connect (model, SIGNAL (description_changed (const QString&)),\n               existing_ql, SLOT (setText (const QString&)));\n      existing_ql->setMargin (2);\n    }\n\n  model->update_data (val);\n\n  if (m_tool_bar)\n    {\n      QList<QTableView *> viewlist = findChildren<QTableView *> ();\n      if (viewlist.size () == 1 && m_tool_bar)\n        m_tool_bar->setEnabled (true);\n    }\n\n  show ();\n  page->show ();\n  page->raise ();\n  page->activateWindow ();\n  tab_to_front ();\n  page->setFocus ();\n}\n\nvoid\nvariable_editor::tab_to_front ()\n{\n  QWidget *parent = parentWidget ();\n\n  if (parent)\n    {\n      QList<QTabBar *> barlist = parent->findChildren<QTabBar *> ();\n\n      QVariant this_value (reinterpret_cast<quintptr> (this));\n\n      for (auto *tbar : barlist)\n        {\n          for (int i = 0; i < tbar->count (); i++)\n            {\n              if (tbar->tabData (i) == this_value)\n                {\n                  tbar->setCurrentIndex (i);\n                  return;\n                }\n            }\n        }\n    }\n}\n\nvoid\nvariable_editor::refresh ()\n{\n  Q_EMIT refresh_signal ();\n}\n\nvoid\nvariable_editor::callUpdate (const QModelIndex&, const QModelIndex&)\n{\n  Q_EMIT updated ();\n}\n\nvoid\nvariable_editor::notice_settings ()\n{\n  gui_settings settings;\n\n  m_main->notice_settings (); // update settings in parent main win\n\n  m_default_width = settings.int_value (ve_column_width);\n\n  m_default_height = settings.int_value (ve_row_height);\n\n  m_alternate_rows = settings.bool_value (ve_alternate_rows);\n\n  m_use_terminal_font = settings.bool_value (ve_use_terminal_font);\n\n  QString font_name;\n  int font_size;\n  QString default_font = settings.string_value (global_mono_font);\n\n  if (m_use_terminal_font)\n    {\n      font_name = settings.value (cs_font.settings_key (), default_font).toString ();\n      font_size = settings.int_value (cs_font_size);\n    }\n  else\n    {\n      font_name = settings.value (ve_font_name.settings_key (), default_font).toString ();\n      font_size = settings.int_value (ve_font_size);\n    }\n\n  m_font = QFont (font_name, font_size);\n\n  QFontMetrics fm (m_font);\n\n  m_add_font_height = fm.height ();\n\n  int mode = settings.int_value (ve_color_mode);\n\n  for (int i = 0; i < ve_colors_count; i++)\n    {\n      QColor setting_color = settings.color_value (ve_colors[i], mode);\n      m_table_colors.replace (i, setting_color);\n    }\n\n  update_colors ();\n\n  // Icon size in the toolbar.\n\n  if (m_tool_bar)\n    {\n      int size_idx = settings.int_value (global_icon_size);\n      size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2\n\n      QStyle *st = style ();\n      int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);\n      m_tool_bar->setIconSize (QSize (icon_size, icon_size));\n    }\n\n  // Shortcuts (same as file editor)\n  settings.set_shortcut (m_save_action, sc_edit_file_save);\n}\n\nvoid\nvariable_editor::closeEvent (QCloseEvent *e)\n{\n  Q_EMIT finished ();\n\n  octave_dock_widget::closeEvent (e);\n}\n\nvoid\nvariable_editor::variable_destroyed (QObject *obj)\n{\n  // Invalidate the focus-restoring widget pointer if currently active.\n  if (m_focus_widget_vdw == obj)\n    {\n      m_focus_widget = nullptr;\n      m_focus_widget_vdw = nullptr;\n    }\n\n  for (long long int i = 0; i < m_variables.size (); i++)\n    {\n      if (m_variables.at (i) == obj)\n        {\n          m_variables.removeAt (i);\n          break;\n        }\n    }\n\n  if (m_tool_bar && m_variables.isEmpty ())\n    m_tool_bar->setEnabled (false);\n\n  QFocusEvent ev (QEvent::FocusIn);\n  focusInEvent (&ev);\n}\n\nvoid\nvariable_editor::variable_focused (const QString& name)\n{\n  m_current_focus_vname = name;\n\n  // focusWidget() appears lost in transition to/from main window\n  // so keep a record of the widget.\n\n  QWidget *current = QApplication::focusWidget ();\n  m_focus_widget = nullptr;\n  m_focus_widget_vdw = nullptr;\n  if (current != nullptr)\n    {\n      for (long long int i = 0; i < m_variables.size (); i++)\n        {\n          if (m_variables.at (i)->isAncestorOf (current))\n            {\n              m_focus_widget = current;\n              m_focus_widget_vdw = m_variables.at (i);\n              break;\n            }\n        }\n    }\n}\n\nvoid\nvariable_editor::record_hovered_focus_variable ()\n{\n  m_hovered_focus_vname = m_current_focus_vname;\n}\n\nvoid\nvariable_editor::restore_hovered_focus_variable ()\n{\n  variable_dock_widget *tofocus\n    = findChild<variable_dock_widget *> (m_hovered_focus_vname);\n  if (tofocus)\n    {\n      tofocus->raise ();\n      tofocus->activateWindow ();\n      tofocus->setFocus (Qt::OtherFocusReason);\n    }\n}\n\nvoid\nvariable_editor::save ()\n{\n  Q_EMIT save_signal ();\n}\n\nvoid\nvariable_editor::cutClipboard ()\n{\n  copyClipboard ();\n\n  Q_EMIT clear_content_signal ();\n}\n\nvoid\nvariable_editor::copyClipboard ()\n{\n  Q_EMIT copy_clipboard_signal ();\n}\n\nvoid\nvariable_editor::pasteClipboard ()\n{\n  Q_EMIT paste_clipboard_signal ();\n\n  Q_EMIT updated ();\n}\n\nvoid\nvariable_editor::levelUp ()\n{\n  Q_EMIT level_up_signal ();\n}\n\n// Also updates the font.\n\nvoid\nvariable_editor::update_colors ()\n{\n  m_stylesheet = \"\";\n\n  if (m_table_colors.length () > 0)\n    m_stylesheet += \"QTableView::item{ color: \"\n                    + m_table_colors[0].name () +\" }\";\n\n  if (m_table_colors.length () > 1)\n    m_stylesheet += \"QTableView::item{ background-color: \"\n                    + m_table_colors[1].name () +\" }\";\n\n  if (m_table_colors.length () > 2)\n    m_stylesheet += \"QTableView::item{ selection-color: \"\n                    + m_table_colors[2].name () +\" }\";\n\n  if (m_table_colors.length () > 3)\n    m_stylesheet += \"QTableView::item:selected{ background-color: \"\n                    + m_table_colors[3].name () +\" }\";\n\n  if (m_table_colors.length () > 4 && m_alternate_rows)\n    {\n      m_stylesheet += \"QTableView::item:alternate{ background-color: \"\n                      + m_table_colors[4].name () +\" }\";\n\n      m_stylesheet += \"QTableView::item:alternate:selected{ background-color: \"\n                      + m_table_colors[3].name () +\" }\";\n    }\n\n  QList<QTableView *> viewlist = findChildren<QTableView *> ();\n  for (int i = 0; i < viewlist.size (); i++)\n    {\n      QTableView *view = viewlist.at (i);\n\n      if (! view)\n        continue;\n\n      view->setAlternatingRowColors (m_alternate_rows);\n      view->setStyleSheet (m_stylesheet);\n      view->setFont (m_font);\n    }\n\n}\n\nQAction *\nvariable_editor::add_tool_bar_button (const QIcon& icon,\n                                      const QString& text,\n                                      const QObject *receiver,\n                                      const char *member)\n{\n  QAction *action = new QAction (icon, text, this);\n  connect (action, SIGNAL (triggered ()), receiver, member);\n  QToolButton *button = new ReturnFocusToolButton (m_tool_bar);\n  button->setDefaultAction (action);\n  button->setText (text);\n  button->setToolTip (text);\n  button->setIcon (icon);\n  m_tool_bar->addWidget (button);\n\n  return action;\n}\n\nvoid\nvariable_editor::construct_tool_bar ()\n{\n  m_tool_bar->setAllowedAreas (Qt::TopToolBarArea);\n\n  m_tool_bar->setObjectName (\"VariableEditorToolBar\");\n\n  m_tool_bar->setWindowTitle (tr (\"Variable Editor Toolbar\"));\n\n  gui_settings settings;\n\n  m_save_action = add_tool_bar_button (settings.icon (\"document-save\"),\n                                       tr (\"Save\"), this, SLOT (save ()));\n  addAction (m_save_action);\n  m_save_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);\n  m_save_action->setStatusTip (tr(\"Save variable to a file\"));\n\n  QAction *action = new QAction (settings.icon (\"document-save-as\"),\n                                 tr (\"Save in format ...\"), m_tool_bar);\n\n  QToolButton *save_tool_button = new HoverToolButton (m_tool_bar);\n  save_tool_button->setDefaultAction (action);\n\n  save_tool_button->setText (tr (\"Save in format ...\"));\n  save_tool_button->setToolTip (tr(\"Save variable to a file in different format\"));\n  save_tool_button->setIcon (settings.icon (\"document-save-as\"));\n  save_tool_button->setPopupMode (QToolButton::InstantPopup);\n\n  QMenu *save_menu = new ReturnFocusMenu (save_tool_button);\n  save_menu->setTitle (tr (\"Save in format ...\"));\n  save_menu->setSeparatorsCollapsible (false);\n\n  m_save_mapper = new QSignalMapper (save_menu);\n  for (int i = 0; i < ve_save_formats.length (); i++)\n    m_save_mapper->setMapping\n      (save_menu->addAction (ve_save_formats.at (i),\n                             m_save_mapper, SLOT (map ())),\n                             ve_save_formats.at (i));\n\n  save_tool_button->setMenu (save_menu);\n  m_tool_bar->addWidget (save_tool_button);\n\n  m_tool_bar->addSeparator ();\n\n  action = add_tool_bar_button (settings.icon (\"edit-cut\"), tr (\"Cut\"),\n                                this, SLOT (cutClipboard ()));\n  action->setStatusTip (tr(\"Cut data to clipboard\"));\n\n  action = add_tool_bar_button (settings.icon (\"edit-copy\"), tr (\"Copy\"),\n                                this, SLOT (copyClipboard ()));\n  action->setStatusTip (tr(\"Copy data to clipboard\"));\n\n  action = add_tool_bar_button (settings.icon (\"edit-paste\"), tr (\"Paste\"),\n                                this, SLOT (pasteClipboard ()));\n  action->setStatusTip (tr(\"Paste clipboard into variable data\"));\n\n  m_tool_bar->addSeparator ();\n\n  // FIXME: Add a print item?\n  // QAction *print_action; /icons/fileprint.png\n  // m_tool_bar->addSeparator ();\n\n  action = new QAction (settings.icon (\"plot-xy-curve\"), tr (\"Plot\"),\n                        m_tool_bar);\n  action->setToolTip (tr (\"Plot Selected Data\"));\n  QToolButton *plot_tool_button = new HoverToolButton (m_tool_bar);\n  plot_tool_button->setDefaultAction (action);\n\n  plot_tool_button->setText (tr (\"Plot\"));\n  plot_tool_button->setToolTip (tr (\"Plot selected data\"));\n  plot_tool_button->setIcon (settings.icon (\"plot-xy-curve\"));\n\n  plot_tool_button->setPopupMode (QToolButton::InstantPopup);\n\n  QMenu *plot_menu = new ReturnFocusMenu (plot_tool_button);\n  plot_menu->setTitle (tr (\"Plot\"));\n  plot_menu->setSeparatorsCollapsible (false);\n\n  m_plot_mapper = make_plot_mapper (plot_menu);\n\n  plot_tool_button->setMenu (plot_menu);\n\n  m_tool_bar->addWidget (plot_tool_button);\n\n  m_tool_bar->addSeparator ();\n\n  action = add_tool_bar_button (settings.icon (\"go-up\"), tr (\"Up\"), this,\n                                SLOT (levelUp ()));\n  action->setStatusTip (tr(\"Go one level up in variable hierarchy\"));\n\n  // The QToolButton mouse-clicks change active window, so connect all\n  // HoverToolButton and ReturnFocusToolButton objects to the mechanism\n  // that restores active window and focus before acting.\n  QList<HoverToolButton *> hbuttonlist\n    = m_tool_bar->findChildren<HoverToolButton *> (\"\"\n                                                   , Qt::FindDirectChildrenOnly\n                                                  );\n  for (int i = 0; i < hbuttonlist.size (); i++)\n    {\n      connect (hbuttonlist.at (i), &HoverToolButton::hovered_signal,\n               this, &variable_editor::record_hovered_focus_variable);\n      connect (hbuttonlist.at (i), &HoverToolButton::popup_shown_signal,\n               this, &variable_editor::restore_hovered_focus_variable);\n    }\n\n  QList<ReturnFocusToolButton *> rfbuttonlist\n    = m_tool_bar->findChildren<ReturnFocusToolButton *> (\"\"\n                                                         , Qt::FindDirectChildrenOnly\n                                                        );\n  for (int i = 0; i < rfbuttonlist.size (); i++)\n    {\n      connect (rfbuttonlist.at (i), &ReturnFocusToolButton::about_to_activate,\n               this, &variable_editor::restore_hovered_focus_variable);\n    }\n\n  // Same for QMenu\n  QList<ReturnFocusMenu *> menulist\n    = m_tool_bar->findChildren<ReturnFocusMenu *> ();\n  for (int i = 0; i < menulist.size (); i++)\n    {\n      connect (menulist.at (i), &ReturnFocusMenu::about_to_activate,\n               this, &variable_editor::restore_hovered_focus_variable);\n    }\n\n  m_tool_bar->setAttribute (Qt::WA_ShowWithoutActivating);\n  m_tool_bar->setFocusPolicy (Qt::NoFocus);\n\n  // Disabled when no tab is present.\n\n  m_tool_bar->setEnabled (false);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/variable-editor.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_variable_editor_h)\n#define octave_variable_editor_h 1\n\n#include \"octave-config.h\"\n\n#include <QHeaderView>\n#include <QSignalMapper>\n#include <QStackedWidget>\n#include <QTableView>\n\n#include \"dw-main-window.h\"\n#include \"octave-dock-widget.h\"\n#include \"octave-qt-features.h\"\n#include \"qt-interpreter-events.h\"\n#include \"tab-bar.h\"\n\nclass octave_value;\n\nclass QModelIndex;\nclass QTextEdit;\nclass QToolBar;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass variable_editor_model;\nclass variable_editor_view;\n\n// The individual variable subwindow class\n\nclass variable_dock_widget : public label_dock_widget\n{\n  Q_OBJECT\n\npublic:\n\n  variable_dock_widget (QWidget *p);\n\n  ~variable_dock_widget () = default;\n\nQ_SIGNALS:\n\n  void variable_focused_signal (const QString& name);\n\nprotected:\n\n  virtual void closeEvent (QCloseEvent *e);\n\n  void resizeEvent (QResizeEvent *event);\n\npublic Q_SLOTS:\n\n  void handle_focus_change (QWidget *old, QWidget *now);\n\nprivate Q_SLOTS:\n\n  void change_floating (bool);\n\n  void change_existence (bool);\n\n  void toplevel_change (bool);\n\n  void change_fullscreen ();\n\nprotected:\n\n  QFrame *m_frame;\n\n  QAction *m_fullscreen_action;\n\n  bool m_full_screen;\n\n  bool m_prev_floating;\n\n  QRect m_prev_geom;\n\nQ_SIGNALS:\n\n  void queue_unfloat_float ();\n\n  void queue_float ();\n\nprotected Q_SLOTS:\n\n  void unfloat_float ();\n\n  void refloat ();\n\n#if defined (HAVE_FLOATING_QDOCKWIDGET_UNSELECTABLE_BUG)\nprotected:\n\n  bool event (QEvent *event);\n\nprivate:\n\n  bool m_waiting_for_mouse_move;\n\n  bool m_waiting_for_mouse_button_release;\n#endif\n};\n\nclass variable_editor_stack : public QStackedWidget\n{\n  Q_OBJECT\n\npublic:\n\n  variable_editor_stack (QWidget *p);\n\n  ~variable_editor_stack () = default;\n\n  variable_editor_view * edit_view () {return m_edit_view;};\n\n  QTextEdit * disp_view () {return m_disp_view;};\n\nQ_SIGNALS:\n\n  void edit_variable_signal (const QString& name, const octave_value& val);\n\n  void do_save_signal (const QString& format, const QString& save_opts);\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  void set_editable (bool editable);\n\n  void levelUp ();\n\n  void save (const QString& format = QString ());\n\n  void do_save (const QString& format, const QString& save_opts);\n\nprivate:\n\n  QTextEdit * make_disp_view (QWidget *parent);\n\n  variable_editor_view *m_edit_view;\n\n  QTextEdit *m_disp_view;\n};\n\nclass variable_editor_view : public QTableView\n{\n  Q_OBJECT\n\npublic:\n\n  variable_editor_view (QWidget *p);\n\n  ~variable_editor_view () = default;\n\n  void setModel (QAbstractItemModel *model);\n\nQ_SIGNALS:\n\n  void command_signal (const QString& cmd);\n\n  void add_edit_actions_signal (QMenu *menu, const QString& qualifier_string);\n\npublic Q_SLOTS:\n\n  void createVariable ();\n\n  void transposeContent ();\n\n  QList<int> range_selected ();\n\n  void delete_selected ();\n\n  void clearContent ();\n\n  void cutClipboard ();\n\n  void copyClipboard ();\n\n  void pasteClipboard ();\n\n  void handle_horizontal_scroll_action (int action);\n\n  void handle_vertical_scroll_action (int action);\n\n  void createContextMenu (const QPoint& pt);\n\n  void createColumnMenu (const QPoint& pt);\n\n  void createRowMenu (const QPoint& pt);\n\n  void selected_command_requested (const QString& cmd);\n\nprivate:\n\n  void add_edit_actions (QMenu *menu, const QString& qualifier_string);\n\n  variable_editor_model *m_var_model;\n};\n\n// Gadgets to keep track of and restore what variable window was in focus\n// just prior to selecting something on the menu bar.\n\nclass HoverToolButton : public QToolButton\n{\n  Q_OBJECT\n\npublic:\n\n  HoverToolButton (QWidget *parent = nullptr);\n\n  ~HoverToolButton () = default;\n\nQ_SIGNALS:\n\n  void hovered_signal ();\n\n  void popup_shown_signal ();\n\nprotected:\n\n  bool eventFilter (QObject *obj, QEvent *ev);\n};\n\nclass ReturnFocusToolButton : public HoverToolButton\n{\n  Q_OBJECT\n\npublic:\n\n  ReturnFocusToolButton (QWidget *parent = nullptr);\n\n  ~ReturnFocusToolButton () = default;\n\nQ_SIGNALS:\n\n  void about_to_activate ();\n\nprotected:\n\n  bool eventFilter (QObject *obj, QEvent *ev);\n};\n\nclass ReturnFocusMenu : public QMenu\n{\n  Q_OBJECT\n\npublic:\n\n  ReturnFocusMenu (QWidget *parent = nullptr);\n\n  ~ReturnFocusMenu () = default;\n\nQ_SIGNALS:\n\n  void about_to_activate ();\n\nprotected:\n\n  bool eventFilter (QObject *obj, QEvent *ev);\n};\n\n// The variable editor class\n\nclass variable_editor : public octave_dock_widget\n{\n  Q_OBJECT\n\npublic:\n\n  variable_editor (QWidget *parent);\n\n  ~variable_editor ();\n\n  OCTAVE_DISABLE_COPY_MOVE (variable_editor)\n\n  void refresh ();\n\n  void tab_to_front ();\n\nQ_SIGNALS:\n\n  void updated ();\n\n  void finished ();\n\n  void command_signal (const QString& cmd);\n\n  void refresh_signal ();\n\n  void clear_content_signal ();\n\n  void copy_clipboard_signal ();\n\n  void paste_clipboard_signal ();\n\n  void level_up_signal ();\n\n  void save_signal ();\n\n  void delete_selected_signal ();\n\n  void interpreter_event (const fcn_callback& fcn);\n  void interpreter_event (const meth_callback& meth);\n\npublic Q_SLOTS:\n\n  void callUpdate (const QModelIndex&, const QModelIndex&);\n\n  void notice_settings ();\n\n  void edit_variable (const QString& name, const octave_value& val);\n\n  void variable_destroyed (QObject *obj);\n\n  void variable_focused (const QString& name);\n\n  void record_hovered_focus_variable ();\n\n  void restore_hovered_focus_variable ();\n\nprotected Q_SLOTS:\n\n  void closeEvent (QCloseEvent *);\n\n  void save ();\n\n  void cutClipboard ();\n\n  void copyClipboard ();\n\n  void pasteClipboard ();\n\n  void levelUp ();\n\nprotected:\n\n  void focusInEvent (QFocusEvent *ev);\n\nprivate:\n\n  dw_main_window *m_main;\n\n  QToolBar *m_tool_bar;\n  QAction *m_save_action;\n\n  int m_default_width;\n\n  int m_default_height;\n\n  int m_add_font_height;\n\n  bool m_use_terminal_font;\n\n  bool m_alternate_rows;\n\n  QString m_stylesheet;\n\n  QFont m_font;\n\n  // If use_terminal_font is true then this will be different since\n  // \"font\" will contain the terminal font.\n  QFont m_sel_font;\n\n  QList<QColor> m_table_colors;\n\n  void update_colors ();\n\n  QAction * add_tool_bar_button (const QIcon& icon, const QString& text,\n                                 const QObject *receiver, const char *member);\n\n  void construct_tool_bar ();\n\n  QList<variable_dock_widget *> m_variables;\n\n  QString m_current_focus_vname;\n\n  QString m_hovered_focus_vname;\n\n  QSignalMapper *m_plot_mapper;\n  QSignalMapper *m_save_mapper;\n\n  QWidget *m_focus_widget;\n\n  variable_dock_widget *m_focus_widget_vdw;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/welcome-wizard.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QApplication>\n#include <QHBoxLayout>\n#include <QPushButton>\n#include <QVBoxLayout>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#endif\n\n#include \"gui-preferences-dw.h\"\n#include \"gui-preferences-nr.h\"\n#include \"gui-settings.h\"\n#include \"welcome-wizard.h\"\n#include \"version.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic QLabel *\nmake_octave_logo (QWidget *p = nullptr, int height = 100)\n{\n  QLabel *logo = new QLabel (p);\n  QPixmap logo_pixmap (dw_icon_set_names[\"NONE\"]);\n  logo->setPixmap (logo_pixmap.scaledToHeight (height));\n  return logo;\n};\n\nwelcome_wizard::welcome_wizard (QWidget *p)\n  : QDialog (p), m_page_ctor_list (), m_page_list_iterator (),\n    m_current_page (initial_page::create (this)),\n    m_allow_web_connect_state (false),\n    m_max_height (0), m_max_width (0)\n{\n  m_page_ctor_list.push_back (initial_page::create);\n  m_page_ctor_list.push_back (setup_community_news::create);\n  m_page_ctor_list.push_back (final_page::create);\n\n  m_page_list_iterator = m_page_ctor_list.begin ();\n\n  setWindowTitle (tr (\"Welcome to GNU Octave\"));\n\n  setEnabled (true);\n\n  setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);\n\n  // Create all pages for pre-setting the minimal required size for all pages\n  show_page ();\n  adjust_size ();\n  next_page ();\n  adjust_size ();\n  next_page ();\n  adjust_size ();\n  // now go back to the first page\n  previous_page ();\n  previous_page ();\n\n  // Set the size determined above\n  resize (m_max_width, m_max_height);\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  // HACK to forceshow of dialog if started minimized\n  ShowWindow (reinterpret_cast<HWND> (winId ()), SW_SHOWNORMAL);\n#endif\n}\n\nvoid\nwelcome_wizard::adjust_size ()\n{\n  // Get adjusted size for the current page\n  adjustSize ();\n  QSize sz = size ();\n\n  // Update the max. size of the three pages if required\n\n  if (sz.height () > m_max_height)\n    m_max_height = sz.height ();\n\n  if (sz.width () > m_max_width)\n    m_max_width = sz.width ();\n}\n\nvoid\nwelcome_wizard::handle_web_connect_option (int state)\n{\n  m_allow_web_connect_state = state == Qt::Checked;\n}\n\nvoid\nwelcome_wizard::show_page ()\n{\n  delete m_current_page;\n  delete layout ();\n\n  m_current_page = (*m_page_list_iterator) (this);\n\n  QVBoxLayout *new_layout = new QVBoxLayout ();\n  setLayout (new_layout);\n\n  new_layout->addWidget (m_current_page);\n}\n\nvoid\nwelcome_wizard::previous_page ()\n{\n  --m_page_list_iterator;\n\n  show_page ();\n}\n\nvoid\nwelcome_wizard::next_page ()\n{\n  ++m_page_list_iterator;\n\n  show_page ();\n}\n\nvoid\nwelcome_wizard::accept ()\n{\n  // Create default settings file.\n\n  gui_settings settings;\n\n  settings.setValue (nr_allow_connection.settings_key (), m_allow_web_connect_state);\n\n  settings.sync ();\n\n  QDialog::accept ();\n}\n\ninitial_page::initial_page (welcome_wizard *wizard)\n  : QWidget (wizard),\n    m_title (new QLabel (tr (\"Welcome to Octave!\"), this)),\n    m_message (new QLabel (this)),\n    m_logo (make_octave_logo (this)),\n    m_next (new QPushButton (tr (\"Next\"), this)),\n    m_cancel (new QPushButton (tr (\"Cancel\"), this))\n{\n  QFont ft;\n  ft.setPointSize (20);\n  m_title->setFont (ft);\n\n  gui_settings settings;\n\n  m_message->setText\n    (tr (\"<html><body>\\n\"\n         \"<p>You seem to be using the Octave graphical interface for the first time on this computer.\\n\"\n         \"Click 'Next' to create a configuration file and launch Octave.</p>\\n\"\n         \"<p>The configuration file is stored in<br>%1.</p>\\n\"\n         \"</body></html>\").\n     arg (settings.file_name ()));\n  m_message->setWordWrap (true);\n  m_message->setMinimumWidth (400);\n\n  QVBoxLayout *message_layout = new QVBoxLayout;\n\n  message_layout->addWidget (m_title);\n  message_layout->addWidget (m_message);\n\n  QHBoxLayout *message_and_logo = new QHBoxLayout;\n\n  message_and_logo->addLayout (message_layout);\n  message_and_logo->addStretch (10);\n  message_and_logo->addWidget (m_logo, 0, Qt::AlignTop);\n\n  QHBoxLayout *button_bar = new QHBoxLayout;\n\n  button_bar->addStretch (10);\n  button_bar->addWidget (m_next);\n  button_bar->addWidget (m_cancel);\n\n  QVBoxLayout *page_layout = new QVBoxLayout (this);\n  setLayout (page_layout);\n\n  page_layout->addLayout (message_and_logo);\n  page_layout->addStretch (10);\n  page_layout->addSpacing (20);\n  page_layout->addLayout (button_bar);\n\n  setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);\n\n  m_next->setDefault (true);\n  m_next->setFocus ();\n\n  connect (m_next, &QPushButton::clicked, wizard, &welcome_wizard::next_page);\n  connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject);\n}\n\nsetup_community_news::setup_community_news (welcome_wizard *wizard)\n  : QWidget (wizard),\n    m_title (new QLabel (tr (\"Community News\"), this)),\n    m_message (new QLabel (this)),\n    m_checkbox (new QCheckBox (this)),\n    m_checkbox_message (new QLabel (this)),\n    m_logo (make_octave_logo (this)),\n    m_previous (new QPushButton (tr (\"Previous\"), this)),\n    m_next (new QPushButton (tr (\"Next\"), this)),\n    m_cancel (new QPushButton (tr (\"Cancel\"), this))\n{\n  QFont ft;\n  ft.setPointSize (20);\n  m_title->setFont (ft);\n\n  m_message->setText\n    (tr (\"<html><body>\\n\"\n         \"<p>When Octave starts, it will optionally check the Octave web site for current news and information about the Octave community.\\n\"\n         \"The check will happen at most once each day and news will only be displayed if there is something new since the last time you viewed the news.</p>\\n\"\n         \"<p>You may also view the news by selecting the \\\"Community News\\\" item in the \\\"Help\\\" menu, or by visiting\\n\"\n         \"<a href=\\\"https://octave.org/community-news.html\\\">https://octave.org/community-news.html</a>.</p>\\n\"\n         \"</body></html>\"));\n  m_message->setWordWrap (true);\n  m_message->setMinimumWidth (400);\n  m_message->setOpenExternalLinks (true);\n\n  QVBoxLayout *message_layout = new QVBoxLayout;\n\n  message_layout->addWidget (m_title);\n  message_layout->addWidget (m_message);\n\n  QHBoxLayout *message_and_logo = new QHBoxLayout;\n\n  message_and_logo->addLayout (message_layout);\n  message_and_logo->addStretch (10);\n  message_and_logo->addWidget (m_logo, 0, Qt::AlignTop);\n\n  QHBoxLayout *checkbox_layout = new QHBoxLayout;\n\n  bool allow_connection = nr_allow_connection.def ().toBool ();\n  if (allow_connection)\n    m_checkbox->setCheckState (Qt::Checked);\n  else\n    m_checkbox->setCheckState (Qt::Unchecked);\n\n  m_checkbox_message->setText\n    (tr (\"<html><head>\\n\"\n         \"</head><body>\\n\"\n         \"<p>Allow Octave to connect to the Octave web site when it starts in order to display current news and information about the Octave community.</p>\\n\"\n         \"</body></html>\"));\n  m_checkbox_message->setWordWrap (true);\n  m_checkbox_message->setOpenExternalLinks (true);\n  m_checkbox_message->setMinimumWidth (500);\n\n  checkbox_layout->addWidget (m_checkbox, 0, Qt::AlignTop);\n  checkbox_layout->addSpacing (20);\n  checkbox_layout->addWidget (m_checkbox_message, 0, Qt::AlignTop);\n  checkbox_layout->addStretch (10);\n\n  QVBoxLayout *message_logo_and_checkbox = new QVBoxLayout;\n\n  message_logo_and_checkbox->addLayout (message_and_logo);\n  message_logo_and_checkbox->addSpacing (20);\n  message_logo_and_checkbox->addLayout (checkbox_layout);\n\n  QHBoxLayout *button_bar = new QHBoxLayout;\n\n  button_bar->addStretch (10);\n  button_bar->addWidget (m_previous);\n  button_bar->addWidget (m_next);\n  button_bar->addWidget (m_cancel);\n\n  QVBoxLayout *page_layout = new QVBoxLayout (this);\n  setLayout (page_layout);\n\n  page_layout->addLayout (message_logo_and_checkbox);\n  page_layout->addStretch (10);\n  page_layout->addSpacing (20);\n  page_layout->addLayout (button_bar);\n\n  setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);\n\n  m_next->setDefault (true);\n  m_next->setFocus ();\n\n  connect (m_checkbox,\n#if defined (HAVE_QCHECKBOX_CHECKSTATECHANGED)\n           &QCheckBox::checkStateChanged,\n#else\n           &QCheckBox::stateChanged,\n#endif\n           wizard, &welcome_wizard::handle_web_connect_option);\n\n  connect (m_previous, &QPushButton::clicked, wizard, &welcome_wizard::previous_page);\n  connect (m_next, &QPushButton::clicked, wizard, &welcome_wizard::next_page);\n  connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject);\n}\n\nfinal_page::final_page (welcome_wizard *wizard)\n  : QWidget (wizard),\n    m_title (new QLabel (tr (\"Enjoy!\"), this)),\n    m_message (new QLabel (this)),\n    m_logo (make_octave_logo (this)),\n    m_links (new QLabel (this)),\n    m_previous (new QPushButton (tr (\"Previous\"), this)),\n    m_finish (new QPushButton (tr (\"Finish\"), this)),\n    m_cancel (new QPushButton (tr (\"Cancel\"), this))\n{\n  QFont ft;\n  ft.setPointSize (20);\n  m_title->setFont (ft);\n\n  m_message->setText\n    (tr (\"<html><body>\\n\"\n         \"<p>We hope you find Octave to be a useful tool.</p>\\n\"\n         \"<p>If you encounter problems, there are a number of ways to get help, including commercial support options, a discussion board, a wiki, and other community-based support channels.\\n\"\n         \"You can find more information about each of these by visiting <a href=\\\"https://octave.org/support.html\\\">https://octave.org/support.html</a> (opens in external browser).</p>\\n\"\n         \"</body></html>\"));\n  m_message->setWordWrap (true);\n  m_message->setMinimumWidth (400);\n  m_message->setOpenExternalLinks (true);\n\n  QVBoxLayout *message_layout = new QVBoxLayout;\n\n  message_layout->addWidget (m_title);\n  message_layout->addWidget (m_message);\n\n  QHBoxLayout *message_and_logo = new QHBoxLayout;\n\n  message_and_logo->addLayout (message_layout);\n  message_and_logo->addStretch (10);\n  message_and_logo->addWidget (m_logo, 0, Qt::AlignTop);\n\n  m_links->setText\n    (tr (\"<html><head>\\n\"\n         \"</head><body>\\n\"\n         \"<p>For more information about Octave:</p>\\n\"\n         \"<ul>\\n\"\n         \"<li>Visit <a href=\\\"https://octave.org\\\">https://octave.org</a> (opens in external browser)</li>\\n\"\n         \"<li>Get the documentation online in <a href=\\\"https://www.gnu.org/software/octave/doc/interpreter/index.html\\\">HTML</a> or <a href=\\\"https://www.gnu.org/software/octave/octave.pdf\\\">PDF</a> format (links open in external browser)</li>\\n\"\n         \"<li>Open the documentation browser of the Octave GUI with the help menu</li>\\n\"\n         \"</ul>\\n\"\n         \"</body></html>\"));\n  m_links->setWordWrap (true);\n  m_links->setOpenExternalLinks (true);\n\n  QHBoxLayout *button_bar = new QHBoxLayout;\n\n  button_bar->addStretch (10);\n  button_bar->addWidget (m_previous);\n  button_bar->addWidget (m_finish);\n  button_bar->addWidget (m_cancel);\n\n  QVBoxLayout *page_layout = new QVBoxLayout (this);\n  setLayout (page_layout);\n\n  page_layout->addLayout (message_and_logo);\n  page_layout->addSpacing (20);\n  page_layout->addWidget (m_links);\n  page_layout->addStretch (10);\n  page_layout->addSpacing (20);\n  page_layout->addLayout (button_bar);\n\n  setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);\n\n  m_finish->setDefault (true);\n  m_finish->setFocus ();\n\n  connect (m_previous, &QPushButton::clicked,\n           wizard, &welcome_wizard::previous_page);\n  connect (m_finish, &QPushButton::clicked, wizard, &welcome_wizard::accept);\n  connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject);\n}\n\n\n\n// Splash Screen\n\nsplash_screen::splash_screen (QWidget *p)\n  : QDialog (p)\n{\n  setWindowTitle (tr (\"Welcome to GNU Octave\"));\n\n  setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);\n\n  QLabel *title = new QLabel (tr (\"Welcome to Octave!\"), this);\n  QFont ft;\n  ft.setPointSize (18);\n  title->setFont (ft);\n\n  gui_settings settings;\n\n  time_t timestamp = time(&timestamp);\n  struct tm datetime = *localtime(&timestamp);\n  QLabel *message = new QLabel (\n       QString ( \"<html><body>\\n\"\n            \"<p><b>GNU Octave, version %1</b><br><br>\\n\"\n            \"<p>Copyright (C) 1993-%2 The Octave Project Developers</p>\\n\"\n            \"</body></html>\" ).arg (OCTAVE_VERSION).arg (datetime.tm_year + 1900) );\n  ft.setPointSize (10);\n  message->setFont (ft);\n\n  QVBoxLayout *message_layout = new QVBoxLayout;\n\n  int left, top, right, bottom;\n  message_layout->getContentsMargins (&left, &top, &right, &bottom);\n  left = std::max (6, left);\n  top = std::max (6, top);\n  right = std::max (6, right);\n  bottom = std::max (6, bottom);\n  message_layout->setContentsMargins (left, 0*top, right, 0*bottom);\n  message_layout->addWidget (title);\n  message_layout->addSpacing (top);\n  message_layout->addWidget (message);\n\n  QHBoxLayout *message_and_logo = new QHBoxLayout;\n\n  message_and_logo->setContentsMargins (left, top, right, bottom);\n  message_and_logo->addLayout (message_layout);\n  message_and_logo->addSpacing (2*left);\n  message_and_logo->addWidget (make_octave_logo (this), 0, Qt::AlignTop);\n\n  QVBoxLayout *page_layout = new QVBoxLayout (this);\n  setLayout (page_layout);\n\n  page_layout->addLayout (message_and_logo);\n\n  setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  // HACK to forceshow of dialog if started minimized\n  ShowWindow (reinterpret_cast<HWND> (winId ()), SW_SHOWNORMAL);\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/welcome-wizard.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_welcome_wizard_h)\n#define octave_welcome_wizard_h 1\n\n#include <QCheckBox>\n#include <QDialog>\n#include <QLabel>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass welcome_wizard : public QDialog\n{\n  Q_OBJECT\n\npublic:\n\n  typedef QWidget *(*page_creator_fptr) (welcome_wizard *);\n\n  welcome_wizard (QWidget *parent = nullptr);\n\n  ~welcome_wizard () = default;\n\n  void adjust_size ();\n\nprivate:\n\n  QList<page_creator_fptr> m_page_ctor_list;\n  QList<page_creator_fptr>::iterator m_page_list_iterator;\n  QWidget *m_current_page;\n  bool m_allow_web_connect_state;\n  int m_max_height;\n  int m_max_width;\n\npublic Q_SLOTS:\n\n  void handle_web_connect_option (int state);\n\n  void show_page ();\n  void previous_page ();\n  void next_page ();\n\n  void accept ();\n};\n\nclass initial_page : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  initial_page (welcome_wizard *wizard);\n\n  ~initial_page () = default;\n\n  static QWidget *\n  create (welcome_wizard *wizard)\n  {\n    return new initial_page (wizard);\n  }\n\nprivate:\n\n  QLabel *m_title;\n  QLabel *m_message;\n  QLabel *m_logo;\n  QPushButton *m_next;\n  QPushButton *m_cancel;\n};\n\nclass setup_community_news : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  setup_community_news (welcome_wizard *wizard);\n\n  ~setup_community_news () = default;\n\n  static QWidget *\n  create (welcome_wizard *wizard)\n  {\n    return new setup_community_news (wizard);\n  }\n\nprivate:\n\n  QLabel *m_title;\n  QLabel *m_message;\n  QCheckBox *m_checkbox;\n  QLabel *m_checkbox_message;\n  QLabel *m_logo;\n  QPushButton *m_previous;\n  QPushButton *m_next;\n  QPushButton *m_cancel;\n};\n\nclass final_page : public QWidget\n{\n  Q_OBJECT\n\npublic:\n\n  final_page (welcome_wizard *wizard);\n\n  ~final_page () = default;\n\n  static QWidget *\n  create (welcome_wizard *wizard)\n  {\n    return new final_page (wizard);\n  }\n\nprivate:\n\n  QLabel *m_title;\n  QLabel *m_message;\n  QLabel *m_logo;\n  QLabel *m_links;\n  QPushButton *m_previous;\n  QPushButton *m_finish;\n  QPushButton *m_cancel;\n};\n\n\n\nclass splash_screen : public QDialog\n{\n  Q_OBJECT\n\npublic:\n\n  splash_screen (QWidget *parent = nullptr);\n\n  ~splash_screen () = default;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/workspace-model.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n\n#include <QTreeWidget>\n#include <QToolTip>\n\n#include \"gui-preferences-ws.h\"\n#include \"gui-settings.h\"\n#include \"workspace-model.h\"\n\n#include \"syminfo.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nworkspace_model::workspace_model (QObject *p)\n  : QAbstractTableModel (p)\n{\n  // The header names.  Use tr () again when accessing them since\n  // the translator si not yet initialized when this ctor is called\n  m_columnNames.append (tr (\"Name\"));\n  m_columnNames.append (tr (\"Class\"));\n  m_columnNames.append (tr (\"Dimension\"));\n  m_columnNames.append (tr (\"Value\"));\n  m_columnNames.append (tr (\"Attribute\"));\n\n  // Initialize the background and foreground colors of special\n  // classes in the workspace view.  The structure is\n  // m_storage_class_colors(1,2,...,colors):        background colors\n  // m_storage_class_colors(colors+1,...,2*colors): foreground colors\n  for (unsigned int i = 0; i < 2*ws_colors_count; i++)\n    m_storage_class_colors.append (QColor (Qt::white));\n\n}\n\nint\nworkspace_model::rowCount (const QModelIndex&) const\n{\n  return m_symbols.size ();\n}\n\nint\nworkspace_model::columnCount (const QModelIndex&) const\n{\n  return m_columnNames.size ();\n}\n\nQt::ItemFlags\nworkspace_model::flags (const QModelIndex& idx) const\n{\n  Qt::ItemFlags retval = Qt::NoItemFlags;\n\n  if (idx.isValid ())\n    {\n      retval |= Qt::ItemIsEnabled;\n\n      if (m_top_level && idx.column () == 0)\n        retval |= Qt::ItemIsSelectable;\n    }\n\n  return retval;\n}\n\nQVariant\nworkspace_model::headerData (int section, Qt::Orientation orientation,\n                             int role) const\n{\n  if (orientation == Qt::Horizontal && role == Qt::DisplayRole)\n    return tr (m_columnNames[section].toStdString ().data ());\n  else\n    return QVariant ();\n}\n\nQVariant\nworkspace_model::data (const QModelIndex& idx, int role) const\n{\n  QVariant retval;\n\n  if (idx.isValid ())\n    {\n      if ((role == Qt::BackgroundRole || role == Qt::ForegroundRole)\n          && m_enable_colors)\n        {\n          int actual_class\n            = ws_class_chars.indexOf (m_scopes[idx.row ()].toLatin1 ());\n          if (actual_class >= 0)\n            {\n              // Valid class: Get background (normal indexes) or foreground\n              // color (indexes with offset)\n              if (role == Qt::ForegroundRole)\n                actual_class += ws_colors_count;\n\n              return QVariant (m_storage_class_colors.at (actual_class));\n            }\n          else\n            return retval;\n        }\n\n      if (role == Qt::DisplayRole\n          || (idx.column () == 0 && role == Qt::EditRole)\n          || (idx.column () == 0 && role == Qt::ToolTipRole))\n        {\n          switch (idx.column ())\n            {\n            case 0:\n              if (role == Qt::ToolTipRole)\n                retval\n                  = QVariant (tr (\"Right click to copy, rename, or display\"));\n              else\n                retval = QVariant (m_symbols[idx.row ()]);\n              break;\n\n            case 1:\n              retval = QVariant (m_class_names[idx.row ()]);\n              break;\n\n            case 2:\n              retval = QVariant (m_dimensions[idx.row ()]);\n              break;\n\n            case 3:\n              retval = QVariant (m_values[idx.row ()]);\n              break;\n\n            case 4:\n              {\n                QString sclass;\n\n                int actual_class\n                  = ws_class_chars.indexOf (m_scopes[idx.row ()].toLatin1 ());\n\n                if (actual_class >= 0)\n                  sclass = ws_color_names.at (actual_class);\n\n                if (m_complex_flags[idx.row ()])\n                  {\n                    if (sclass.isEmpty ())\n                      sclass = tr (\"complex\");\n                    else\n                      sclass += \", \" + tr (\"complex\");\n                  }\n\n                retval = QVariant (sclass);\n              }\n              break;\n            }\n        }\n    }\n\n  return retval;\n}\n\nvoid\nworkspace_model::set_workspace (bool top_level, bool /* debug */,\n                                const symbol_info_list& syminfo)\n{\n  clear_data ();\n\n  m_top_level = top_level;\n  m_syminfo_list = syminfo;\n\n  update_table ();\n}\n\nvoid\nworkspace_model::clear_workspace ()\n{\n  clear_data ();\n  update_table ();\n}\n\nvoid\nworkspace_model::notice_settings ()\n{\n  gui_settings settings;\n\n  m_enable_colors = settings.bool_value (ws_enable_colors);\n\n  int mode = settings.int_value (ws_color_mode);\n\n  for (int i = 0; i < ws_colors_count; i++)\n    {\n      QColor setting_color = settings.color_value (ws_colors[i], mode);\n\n      QPalette p (setting_color);\n      m_storage_class_colors.replace (i, setting_color);\n\n      QColor fg_color = p.color (QPalette::WindowText);\n      m_storage_class_colors.replace (i + ws_colors_count, fg_color);\n\n    }\n}\n\nvoid\nworkspace_model::show_symbol_tooltip (const QPoint& pos,\n                                      const QString& symbol)\n{\n  int symbol_idx = m_symbols.indexOf (symbol);\n\n  if (symbol_idx > -1)\n    QToolTip::showText (pos, symbol + \" = \" + m_values.at (symbol_idx));\n  else\n    QToolTip::hideText ();\n}\n\nvoid\nworkspace_model::clear_data ()\n{\n  m_top_level = false;\n  m_syminfo_list = symbol_info_list ();\n  m_scopes = QString ();\n  m_symbols = QStringList ();\n  m_class_names = QStringList ();\n  m_dimensions = QStringList ();\n  m_values = QStringList ();\n  m_complex_flags = QIntList ();\n}\n\nvoid\nworkspace_model::update_table ()\n{\n  beginResetModel ();\n\n  for (const auto& syminfo : m_syminfo_list)\n    {\n      std::string nm = syminfo.name ();\n\n      octave_value val = syminfo.value ();\n\n      // FIXME: fix size for objects, see kluge in ov.cc\n      Matrix sz = val.size ();\n      dim_vector dv = dim_vector::alloc (sz.numel ());\n      for (octave_idx_type i = 0; i < dv.ndims (); i++)\n        dv(i) = sz(i);\n\n      char storage = ' ';\n      if (syminfo.is_formal ())\n        storage = 'a';\n      else if (syminfo.is_global ())\n        storage = 'g';\n      else if (syminfo.is_persistent ())\n        storage = 'p';\n\n      std::ostringstream buf;\n      val.short_disp (buf);\n      std::string short_disp_str = buf.str ();\n\n      m_scopes.append (storage);\n      m_symbols.append (QString::fromStdString (nm));\n      m_class_names.append (QString::fromStdString (val.class_name ()));\n      m_dimensions.append (QString::fromStdString (dv.str ()));\n      m_values.append (QString::fromStdString (short_disp_str));\n      m_complex_flags.append (val.iscomplex ());\n    }\n\n  endResetModel ();\n\n  Q_EMIT model_changed ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/workspace-model.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_workspace_model_h)\n#define octave_workspace_model_h 1\n\n#include <QAbstractTableModel>\n#include <QChar>\n#include <QColor>\n#include <QList>\n#include <QSemaphore>\n#include <QStringList>\n#include <QVector>\n\n#include \"syminfo.h\"\n\n// Defined for purposes of sending QList<int> as part of signal.\ntypedef QList<int> QIntList;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass workspace_model : public QAbstractTableModel\n{\n  Q_OBJECT\n\npublic:\n\n  workspace_model (QObject *parent = nullptr);\n\n  ~workspace_model () = default;\n\n  int rowCount (const QModelIndex& parent = QModelIndex ()) const;\n\n  int columnCount (const QModelIndex& parent = QModelIndex ()) const;\n\n  Qt::ItemFlags flags (const QModelIndex& index) const;\n\n  QVariant headerData (int section, Qt::Orientation orientation,\n                       int role = Qt::DisplayRole) const;\n\n  QVariant data (const QModelIndex& index, int role) const;\n\n  bool is_top_level () const { return m_top_level; }\n\n  QColor storage_class_color (int s_class)\n  {\n    return m_storage_class_colors.at (s_class);\n  }\n\n  symbol_info_list get_symbol_info () const { return m_syminfo_list; }\n\n  QStringList get_symbol_names () const { return m_symbols; }\n  QStringList get_symbol_values () const { return m_values; }\n\nQ_SIGNALS:\n\n  void model_changed ();\n  void prompt_variable_editor ();\n\npublic Q_SLOTS:\n\n  void set_workspace (bool top_level, bool debug,\n                      const symbol_info_list& syminfo);\n\n  void clear_workspace ();\n\n  void notice_settings ();\n\n  void show_symbol_tooltip (const QPoint& pos, const QString& symbol);\n\nprivate:\n\n  void clear_data ();\n  void update_table ();\n\n  bool m_top_level;\n  symbol_info_list m_syminfo_list;\n  QString m_scopes;\n  QStringList m_symbols;\n  QStringList m_class_names;\n  QStringList m_dimensions;\n  QStringList m_values;\n  QIntList m_complex_flags;\n\n  QStringList m_columnNames;\n\n  QList<QColor>  m_storage_class_colors;\n  bool m_enable_colors;\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libgui/src/workspace-view.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <QApplication>\n#include <QClipboard>\n#include <QCompleter>\n#include <QHBoxLayout>\n#include <QHeaderView>\n#include <QInputDialog>\n#include <QLabel>\n#include <QLineEdit>\n#include <QMenu>\n#include <QMessageBox>\n#include <QPushButton>\n#include <QSignalMapper>\n#include <QTimer>\n#include <QVBoxLayout>\n\n#include \"gui-preferences-ws.h\"\n#include \"gui-settings.h\"\n#include \"gui-utils.h\"\n#include \"octave-qt-features.h\"\n#include \"workspace-view.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nworkspace_view::workspace_view (QWidget *p)\n  : octave_dock_widget (\"WorkspaceView\", p),\n    m_view (new QTableView (this)),\n    m_filter_checkbox (new QCheckBox ()),\n    m_filter (new QComboBox (this)),\n    m_filter_widget (new QWidget (this)),\n    m_first (true)\n{\n  set_title (tr (\"Workspace\"));\n  setStatusTip (tr (\"View the variables in the active workspace.\"));\n\n  m_filter->setToolTip (tr (\"Enter text to filter the workspace\"));\n  m_filter->setEditable (true);\n  m_filter->setMaxCount (ws_max_filter_history.def ().toInt ());\n  m_filter->setInsertPolicy (QComboBox::NoInsert);\n  m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);\n  QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);\n  m_filter->setSizePolicy (sizePol);\n  m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);\n\n  QLabel *filter_label = new QLabel (tr (\"Filter\"));\n\n  m_view->setWordWrap (false);\n  m_view->setContextMenuPolicy (Qt::CustomContextMenu);\n  m_view->setShowGrid (false);\n  (m_view->verticalHeader) ()->hide ();\n  m_view->verticalHeader ()->setMinimumSectionSize(1);  // allow smaller row sizes\n  m_view->setAlternatingRowColors (true);\n  m_view_previous_row_count = 0;\n\n  // Set an empty widget, so we can assign a layout to it.\n  setWidget (new QWidget (this));\n\n  // Create the layouts\n  QHBoxLayout *filter_layout = new QHBoxLayout ();\n\n  filter_layout->addWidget (filter_label);\n  filter_layout->addWidget (m_filter_checkbox);\n  filter_layout->addWidget (m_filter);\n  filter_layout->setContentsMargins (0, 0, 0, 0);\n\n  m_filter_widget->setLayout (filter_layout);\n\n  QVBoxLayout *ws_layout = new QVBoxLayout ();\n  ws_layout->addWidget (m_filter_widget);\n  ws_layout->addWidget (m_view);\n  ws_layout->setSpacing (0);\n\n  gui_settings settings;\n\n  m_filter_shown = settings.bool_value (ws_filter_shown);\n  m_filter_widget->setVisible (m_filter_shown);\n\n  ws_layout->setContentsMargins (2, 2, 2, 2);\n\n  // Set the empty widget to have our layout.\n  widget ()->setLayout (ws_layout);\n\n  // Initialize collapse/expand state of the workspace subcategories.\n\n  //enable sorting (setting column and order after model was set)\n  m_view->setSortingEnabled (true);\n\n  // Set header properties for sorting\n  m_view->horizontalHeader ()->setSectionsClickable (true);\n  m_view->horizontalHeader ()->setSectionsMovable (true);\n  m_view->horizontalHeader ()->setSortIndicator\n    (settings.int_value (ws_sort_column),\n     static_cast<Qt::SortOrder> (settings.uint_value (ws_sort_order)));\n  // FIXME: use value<Qt::SortOrder> instead of static cast after\n  //        dropping support of Qt 5.4\n\n  m_view->horizontalHeader ()->setSortIndicatorShown (true);\n\n  m_view->horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu);\n  connect (m_view->horizontalHeader (),\n           &QTableView::customContextMenuRequested,\n           this, &workspace_view::header_contextmenu_requested);\n\n  // Init state of the filter\n  m_filter->addItems (settings.value (ws_mru_list.settings_key ()).toStringList ());\n\n  bool filter_state = settings.bool_value (ws_filter_active);\n  m_filter_checkbox->setChecked (filter_state);\n  filter_activate (filter_state);\n\n  // Connect signals and slots.\n\n  connect (m_filter, &QComboBox::editTextChanged,\n           this, &workspace_view::filter_update);\n  connect (m_filter_checkbox, &QCheckBox::toggled,\n           this, &workspace_view::filter_activate);\n  connect (m_filter->lineEdit (), &QLineEdit::editingFinished,\n           this, &workspace_view::update_filter_history);\n\n  connect (m_view, &QTableView::customContextMenuRequested,\n           this, &workspace_view::contextmenu_requested);\n\n  connect (m_view, &QTableView::activated,\n           this, &workspace_view::handle_contextmenu_edit);\n\n  if (! p)\n    make_window ();\n}\n\nvoid\nworkspace_view::restore_header_state ()\n{\n  gui_settings settings;\n\n  if (settings.contains (ws_column_state.settings_key ()))\n    m_view->horizontalHeader ()->restoreState\n      (settings.value (ws_column_state.settings_key ()).toByteArray ());\n}\n\nvoid\nworkspace_view::setModel (workspace_model *model)\n{\n  m_filter_model.setSourceModel (model);\n  m_filter_model.setFilterKeyColumn (0);\n\n  m_view->setModel (&m_filter_model);\n\n  // set the sorting after the model is set, it would be ignored otherwise\n\n  gui_settings settings;\n\n  m_view->sortByColumn\n    (settings.int_value (ws_sort_column),\n     // FIXME: use value<Qt::SortOrder> instead of static cast after\n     //        dropping support of Qt 5.4\n     static_cast<Qt::SortOrder> (settings.uint_value (ws_sort_order)));\n\n  m_model = model;\n}\n\nvoid\nworkspace_view::notice_settings ()\n{\n  gui_settings settings;\n\n  if (m_first)\n    m_first = false;\n  else\n    {\n      // Save current state in case some settings are messing up the state\n      settings.setValue (ws_column_state.settings_key (),\n                         m_view->horizontalHeader ()->saveState ());\n      settings.sync ();\n    }\n\n  m_model->notice_settings (); // update colors of model first\n\n  QString tool_tip;\n\n  if (settings.bool_value (ws_enable_colors)\n      && ! settings.bool_value (ws_hide_tool_tips))\n    {\n      tool_tip  = QString (tr (\"View the variables in the active workspace.<br>\"));\n      tool_tip += QString (tr (\"Colors for variable attributes:\"));\n\n      for (int i = 0; i < ws_colors_count; i++)\n        {\n          tool_tip +=\n            QString (R\"(<div style=\"background-color:%1;color:%2\">%3</div>)\")\n            .arg (m_model->storage_class_color (i).name ())\n            .arg (m_model->storage_class_color (i + ws_colors_count).name ())\n            .arg (QCoreApplication::translate (\"octave::settings_dialog\",\n                                               ws_color_names.at (i).toStdString ().data ()));\n        }\n    }\n\n  setToolTip (tool_tip);\n\n  // Initialize column order, visibility and width of the file browser.\n  // From this post:\n  // https://www.qtcentre.org/threads/26675-QTableView-saving-restoring-columns-widths\n  // This might fail if done directly after other actions.  This effect shows\n  // up in the GUI since Qt 6.6.x.  As a solution, the following timer ensures\n  // that the header is restored when the event loop is idle.\n\n  QTimer::singleShot (0, this, SLOT(restore_header_state ()));\n}\n\nvoid\nworkspace_view::save_settings ()\n{\n  gui_settings settings;\n\n  settings.setValue (ws_column_state.settings_key (),\n                     m_view->horizontalHeader ()->saveState ());\n\n  int sort_column = m_view->horizontalHeader ()->sortIndicatorSection ();\n  Qt::SortOrder sort_order = m_view->horizontalHeader ()->sortIndicatorOrder ();\n  settings.setValue (ws_sort_column.settings_key (), sort_column);\n  settings.setValue (ws_sort_order.settings_key (), sort_order);\n\n  settings.setValue (ws_filter_active.settings_key (), m_filter_checkbox->isChecked ());\n  settings.setValue (ws_filter_shown.settings_key (), m_filter_shown);\n\n  QStringList mru;\n  for (int i = 0; i < m_filter->count (); i++)\n    mru.append (m_filter->itemText (i));\n  settings.setValue (ws_mru_list.settings_key (), mru);\n\n  settings.sync ();\n\n  octave_dock_widget::save_settings ();\n}\n\nvoid\nworkspace_view::set_filter_focus (bool focus)\n{\n  if (focus)\n    {\n      m_filter->setFocus ();\n      setFocusProxy (m_filter);\n    }\n  else\n    {\n      m_view->setFocus ();\n      setFocusProxy (m_view);\n    }\n}\n\nvoid\nworkspace_view::filter_update (const QString& expression)\n{\n  m_filter_model.setFilterWildcard (expression);\n  handle_model_changed ();\n}\n\nvoid\nworkspace_view::filter_activate (bool state)\n{\n  m_filter->setEnabled (state);\n  m_filter_model.setDynamicSortFilter (state);\n\n  if (state)\n    filter_update (m_filter->currentText ());\n  else\n    filter_update (QString ());\n\n  set_filter_focus (state);\n}\n\nvoid\nworkspace_view::update_filter_history ()\n{\n  combobox_insert_current_item (m_filter, QString ());\n}\n\nvoid\nworkspace_view::header_contextmenu_requested (const QPoint& mpos)\n{\n  QMenu menu (this);\n  QSignalMapper sig_mapper (this);\n\n  gui_settings settings;\n\n  for (int i = 0; i < ws_columns_shown.length (); i++)\n    {\n      QAction *action\n        = menu.addAction (tr (ws_columns_shown.at (i).toStdString ().data ()),\n                          &sig_mapper, SLOT (map ()));\n      sig_mapper.setMapping (action, i);\n      action->setCheckable (true);\n      action->setChecked (! m_view->isColumnHidden (i+1));\n    }\n\n#if defined (HAVE_QSIGNALMAPPER_MAPPEDINT)\n  connect (&sig_mapper, &QSignalMapper::mappedInt,\n           this, &workspace_view::toggle_header);\n#else\n  connect (&sig_mapper, SIGNAL (mapped (int)),\n           this, SLOT (toggle_header (int)));\n#endif\n\n  menu.exec (m_view->mapToGlobal (mpos));\n}\n\nvoid\nworkspace_view::toggle_header (int col)\n{\n  m_view->setColumnHidden (col + 1, ! m_view->isColumnHidden (col + 1));\n}\n\nvoid\nworkspace_view::contextmenu_requested (const QPoint& qpos)\n{\n  QMenu menu (this);\n\n  QModelIndex index = m_view->indexAt (qpos);\n\n  // if it isn't Local, Global etc, allow the ctx menu\n  if (index.isValid () && index.column () == 0)\n    {\n      QString var_name = get_var_name (index);\n\n      menu.addAction (tr (\"Open in Variable Editor\"), this,\n                      &workspace_view::handle_contextmenu_edit);\n\n      menu.addAction (tr (\"Copy name\"), this,\n                      &workspace_view::handle_contextmenu_copy);\n\n      menu.addAction (tr (\"Copy value\"), this,\n                      &workspace_view::handle_contextmenu_copy_value);\n\n      QAction *rename\n        = menu.addAction (tr (\"Rename\"), this,\n                          &workspace_view::handle_contextmenu_rename);\n\n      // Use m_model here instead of using \"m_view->model ()\" because\n      // that points to the proxy model.\n      if (! m_model->is_top_level ())\n        {\n          rename->setDisabled (true);\n          rename->setToolTip (tr (\"Only top-level symbols may be renamed\"));\n        }\n\n      menu.addAction (\"Clear \" + var_name, this,\n                      &workspace_view::handle_contextmenu_clear);\n\n      menu.addSeparator ();\n\n      menu.addAction (\"disp (\" + var_name + ')', this,\n                      &workspace_view::handle_contextmenu_disp);\n\n      menu.addAction (\"plot (\" + var_name + ')', this,\n                      &workspace_view::handle_contextmenu_plot);\n\n      menu.addAction (\"stem (\" + var_name + ')', this,\n                      &workspace_view::handle_contextmenu_stem);\n\n      menu.addSeparator ();\n\n    }\n\n  if (m_filter_shown)\n    menu.addAction (tr (\"Hide filter\"), this,\n                    &workspace_view::handle_contextmenu_filter);\n  else\n    menu.addAction (tr (\"Show filter\"), this,\n                    &workspace_view::handle_contextmenu_filter);\n\n  menu.exec (m_view->mapToGlobal (qpos));\n}\n\nvoid\nworkspace_view::handle_contextmenu_copy ()\n{\n  QModelIndex index = m_view->currentIndex ();\n\n  if (index.isValid ())\n    {\n      QString var_name = get_var_name (index);\n\n      QClipboard *clipboard = QApplication::clipboard ();\n\n      clipboard->setText (var_name);\n    }\n}\n\nvoid\nworkspace_view::handle_contextmenu_copy_value ()\n{\n  QModelIndex index = m_view->currentIndex ();\n\n  if (index.isValid ())\n    Q_EMIT copy_variable_value_to_clipboard (get_var_name (index));\n}\n\nvoid\nworkspace_view::handle_contextmenu_rename ()\n{\n  QModelIndex index = m_view->currentIndex ();\n\n  if (index.isValid ())\n    {\n      QString var_name = get_var_name (index);\n\n      QInputDialog *inputDialog = new QInputDialog ();\n\n      inputDialog->setOptions (QInputDialog::NoButtons);\n\n      bool ok = false;\n\n      QString new_name\n        = inputDialog->getText (nullptr, \"Rename Variable\", \"New name:\",\n                                QLineEdit::Normal, var_name, &ok);\n\n      if (ok && ! new_name.isEmpty ())\n        Q_EMIT rename_variable_signal (var_name, new_name);\n    }\n}\n\nvoid\nworkspace_view::handle_contextmenu_edit ()\n{\n  QModelIndex index = m_view->currentIndex ();\n\n  if (index.isValid ())\n    Q_EMIT edit_variable_signal (get_var_name (index));\n}\n\nvoid\nworkspace_view::handle_contextmenu_clear ()\n{\n  relay_contextmenu_command (\"clear\", true);\n}\n\nvoid\nworkspace_view::handle_contextmenu_disp ()\n{\n  relay_contextmenu_command (\"disp\");\n}\n\nvoid\nworkspace_view::handle_contextmenu_plot ()\n{\n  relay_contextmenu_command (\"figure (); plot\");\n}\n\nvoid\nworkspace_view::handle_contextmenu_stem ()\n{\n  relay_contextmenu_command (\"figure (); stem\");\n}\n\nvoid\nworkspace_view::handle_contextmenu_filter ()\n{\n  m_filter_shown = ! m_filter_shown;\n  m_filter_widget->setVisible (m_filter_shown);\n\n  set_filter_focus (m_filter_shown && m_filter_checkbox->isChecked ());\n}\n\nvoid\nworkspace_view::handle_model_changed ()\n{\n  // m_view->resizeRowsToContents ();\n  // Just modify those rows that have been added rather than go through\n  // the whole list.  For-loop test will handle when number of rows reduced.\n  QFontMetrics fm = m_view->fontMetrics ();\n  int row_height = fm.height ();\n  int new_row_count = m_filter_model.rowCount ();\n  for (int i = m_view_previous_row_count; i < new_row_count; i++)\n    m_view->setRowHeight (i, row_height);\n  m_view_previous_row_count = new_row_count;\n}\n\nvoid\nworkspace_view::copyClipboard ()\n{\n  if (m_view->hasFocus ())\n    handle_contextmenu_copy ();\n}\n\nvoid\nworkspace_view::selectAll ()\n{\n  if (m_view->hasFocus ())\n    m_view->selectAll ();\n}\n\nvoid\nworkspace_view::relay_contextmenu_command (const QString& cmdname, bool str)\n{\n  QModelIndex index = m_view->currentIndex ();\n\n  if (index.isValid ())\n    {\n      QString var_name;\n\n      if (str)\n        var_name = \"\\'\" + get_var_name (index) + \"\\'\";\n      else\n        var_name = get_var_name (index);\n\n      Q_EMIT command_requested (cmdname + \" (\" + var_name + \");\");\n    }\n}\n\nQString\nworkspace_view::get_var_name (const QModelIndex& index)\n{\n  // We are using a sort model proxy so m_model won't provide the\n  // correct ordering.\n\n  QAbstractItemModel *m = m_view->model ();\n\n  QMap<int, QVariant> item_data\n    = m->itemData (index.sibling (index.row (), 0));\n\n  return item_data[0].toString ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libgui/src/workspace-view.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_workspace_view_h)\n#define octave_workspace_view_h 1\n\n#include <QCheckBox>\n#include <QComboBox>\n#include <QItemDelegate>\n#include <QSemaphore>\n#include <QSignalMapper>\n#include <QSortFilterProxyModel>\n#include <QTableView>\n\n#include \"octave-dock-widget.h\"\n#include \"workspace-model.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass workspace_view : public octave_dock_widget\n{\n  Q_OBJECT\n\npublic:\n\n  workspace_view (QWidget *parent);\n\n  ~workspace_view () = default;\n\nQ_SIGNALS:\n\n  //! Signal that user had requested a command on a variable.\n\n  void command_requested (const QString& cmd);\n\n  //! Signal that user wnats to copy a variable value to the\n  //! clipboard.\n\n  void copy_variable_value_to_clipboard (const QString&);\n\n  //! Signal that user wants to rename a variable.\n\n  void rename_variable_signal (const QString&, const QString&);\n\n  //! Signal that user wants to edit a variable.\n\n  void edit_variable_signal (const QString&);\n\npublic Q_SLOTS:\n\n  void setModel (workspace_model *model);\n\n  void notice_settings ();\n\n  void save_settings ();\n\nprotected Q_SLOTS:\n\n  void restore_header_state ();\n  void filter_update (const QString& expression);\n  void filter_activate (bool enable);\n  void update_filter_history ();\n\n  void header_contextmenu_requested (const QPoint& mpos);\n\n  void toggle_header (int column);\n\n  void contextmenu_requested (const QPoint& pos);\n\n  void handle_contextmenu_copy ();\n  void handle_contextmenu_copy_value ();\n  void handle_contextmenu_rename ();\n  void handle_contextmenu_edit ();\n  void handle_contextmenu_clear ();\n  void handle_contextmenu_disp ();\n  void handle_contextmenu_plot ();\n  void handle_contextmenu_stem ();\n  void handle_contextmenu_filter ();\n\npublic Q_SLOTS:\n\n  void handle_model_changed ();\n\n  void copyClipboard ();\n  void selectAll ();\n\nprivate:\n\n  void relay_contextmenu_command (const QString& cmdname, bool str = false);\n  void set_filter_focus (bool focus);\n\n  QString get_var_name (const QModelIndex& index);\n\n  QTableView *m_view;\n  int m_view_previous_row_count;\n\n  // We are using a sort model proxy so m_model won't provide the\n  // correct ordering.  It is still OK to use this pointer to access\n  // other info attached to the model, for example the scope or colors.\n  workspace_model *m_model;\n\n  QSortFilterProxyModel m_filter_model;\n  QCheckBox *m_filter_checkbox;\n  QComboBox *m_filter;\n  QWidget *m_filter_widget;\n  bool m_filter_shown;\n  bool m_first;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/build-env.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_build_env_h)\n#define octave_build_env_h 1\n\n#include \"octave-config.h\"\n\n#include \"oct-map.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(build_env)\n\nextern OCTINTERP_API octave_scalar_map features ();\n\nextern OCTINTERP_API const char *AMD_CPPFLAGS;\nextern OCTINTERP_API const char *AMD_LDFLAGS;\nextern OCTINTERP_API const char *AMD_LIBS;\nextern OCTINTERP_API const char *ARFLAGS;\nextern OCTINTERP_API const char *AR;\nextern OCTINTERP_API const char *ARPACK_CPPFLAGS;\nextern OCTINTERP_API const char *ARPACK_LDFLAGS;\nextern OCTINTERP_API const char *ARPACK_LIBS;\nextern OCTINTERP_API const char *BLAS_LIBS;\nextern OCTINTERP_API const char *CAMD_CPPFLAGS;\nextern OCTINTERP_API const char *CAMD_LDFLAGS;\nextern OCTINTERP_API const char *CAMD_LIBS;\nextern OCTINTERP_API const char *CARBON_LIBS;\nextern OCTINTERP_API const char *CC;\nextern OCTINTERP_API const char *CCOLAMD_CPPFLAGS;\nextern OCTINTERP_API const char *CCOLAMD_LDFLAGS;\nextern OCTINTERP_API const char *CCOLAMD_LIBS;\nextern OCTINTERP_API const char *CFLAGS;\nextern OCTINTERP_API const char *CHOLMOD_CPPFLAGS;\nextern OCTINTERP_API const char *CHOLMOD_LDFLAGS;\nextern OCTINTERP_API const char *CHOLMOD_LIBS;\nextern OCTINTERP_API const char *COLAMD_CPPFLAGS;\nextern OCTINTERP_API const char *COLAMD_LDFLAGS;\nextern OCTINTERP_API const char *COLAMD_LIBS;\nextern OCTINTERP_API const char *CPICFLAG;\nextern OCTINTERP_API const char *CPPFLAGS;\nextern OCTINTERP_API const char *CURL_CPPFLAGS;\nextern OCTINTERP_API const char *CURL_LDFLAGS;\nextern OCTINTERP_API const char *CURL_LIBS;\nextern OCTINTERP_API const char *CXSPARSE_CPPFLAGS;\nextern OCTINTERP_API const char *CXSPARSE_LDFLAGS;\nextern OCTINTERP_API const char *CXSPARSE_LIBS;\nextern OCTINTERP_API const char *CXXCPP;\nextern OCTINTERP_API const char *CXXFLAGS;\nextern OCTINTERP_API const char *CXXPICFLAG;\nextern OCTINTERP_API const char *CXX;\nextern OCTINTERP_API const char *DEFAULT_PAGER;\nextern OCTINTERP_API const char *DEFS;\nextern OCTINTERP_API const char *DL_LDFLAGS;\nextern OCTINTERP_API const char *EXEEXT;\nextern OCTINTERP_API const char *GCC_VERSION;\nextern OCTINTERP_API const char *GXX_VERSION;\nextern OCTINTERP_API const char *F77;\nextern OCTINTERP_API const char *F77_FLOAT_STORE_FLAG;\nextern OCTINTERP_API const char *F77_INTEGER_8_FLAG;\nextern OCTINTERP_API const char *FFLAGS;\nextern OCTINTERP_API const char *FFTW3_CPPFLAGS;\nextern OCTINTERP_API const char *FFTW3_LDFLAGS;\nextern OCTINTERP_API const char *FFTW3_LIBS;\nextern OCTINTERP_API const char *FFTW3F_CPPFLAGS;\nextern OCTINTERP_API const char *FFTW3F_LDFLAGS;\nextern OCTINTERP_API const char *FFTW3F_LIBS;\nextern OCTINTERP_API const char *FLIBS;\nextern OCTINTERP_API const char *FLTK_CPPFLAGS;\nextern OCTINTERP_API const char *FLTK_LDFLAGS;\nextern OCTINTERP_API const char *FLTK_LIBS;\nextern OCTINTERP_API const char *FONTCONFIG_CPPFLAGS;\nextern OCTINTERP_API const char *FONTCONFIG_LIBS;\nextern OCTINTERP_API const char *FPICFLAG;\nextern OCTINTERP_API const char *FT2_CPPFLAGS;\nextern OCTINTERP_API const char *FT2_LIBS;\nextern OCTINTERP_API const char *GLPK_CPPFLAGS;\nextern OCTINTERP_API const char *GLPK_LDFLAGS;\nextern OCTINTERP_API const char *GLPK_LIBS;\nextern OCTINTERP_API const char *GNUPLOT;\nextern OCTINTERP_API const char *HDF5_CPPFLAGS;\nextern OCTINTERP_API const char *HDF5_LDFLAGS;\nextern OCTINTERP_API const char *HDF5_LIBS;\nextern OCTINTERP_API const char *INCLUDEDIR;\nextern OCTINTERP_API const char *KLU_CPPFLAGS;\nextern OCTINTERP_API const char *KLU_LDFLAGS;\nextern OCTINTERP_API const char *KLU_LIBS;\nextern OCTINTERP_API const char *LAPACK_LIBS;\nextern OCTINTERP_API const char *LDFLAGS;\nextern OCTINTERP_API const char *LD_STATIC_FLAG;\nextern OCTINTERP_API const char *LEXLIB;\nextern OCTINTERP_API const char *LEX;\nextern OCTINTERP_API const char *LFLAGS;\nextern OCTINTERP_API const char *LIBOCTAVE;\nextern OCTINTERP_API const char *LIBOCTINTERP;\nextern OCTINTERP_API const char *LIBS;\nextern OCTINTERP_API const char *LN_S;\nextern OCTINTERP_API const char *MAGICK_CPPFLAGS;\nextern OCTINTERP_API const char *MAGICK_LDFLAGS;\nextern OCTINTERP_API const char *MAGICK_LIBS;\nextern OCTINTERP_API const char *MKOCTFILE_DL_LDFLAGS;\nextern OCTINTERP_API const char *OCTAVE_LINK_DEPS;\nextern OCTINTERP_API const char *OCTAVE_LINK_OPTS;\nextern OCTINTERP_API const char *OCTINCLUDEDIR;\nextern OCTINTERP_API const char *OCTLIBDIR;\nextern OCTINTERP_API const char *OCT_LINK_DEPS;\nextern OCTINTERP_API const char *OCT_LINK_OPTS;\nextern OCTINTERP_API const char *OPENGL_LIBS;\nextern OCTINTERP_API const char *PCRE_CPPFLAGS;\nextern OCTINTERP_API const char *PCRE_LDFLAGS;\nextern OCTINTERP_API const char *PCRE_LIBS;\nextern OCTINTERP_API const char *PREFIX;\nextern OCTINTERP_API const char *PTHREAD_CFLAGS;\nextern OCTINTERP_API const char *PTHREAD_LIBS;\nextern OCTINTERP_API const char *QHULL_CPPFLAGS;\nextern OCTINTERP_API const char *QHULL_LDFLAGS;\nextern OCTINTERP_API const char *QHULL_LIBS;\nextern OCTINTERP_API const char *QRUPDATE_CPPFLAGS;\nextern OCTINTERP_API const char *QRUPDATE_LDFLAGS;\nextern OCTINTERP_API const char *QRUPDATE_LIBS;\nextern OCTINTERP_API const char *QT_CPPFLAGS;\nextern OCTINTERP_API const char *QT_LDFLAGS;\nextern OCTINTERP_API const char *QT_LIBS;\nextern OCTINTERP_API const char *RANLIB;\nextern OCTINTERP_API const char *RDYNAMIC_FLAG;\nextern OCTINTERP_API const char *READLINE_LIBS;\nextern OCTINTERP_API const char *SHARED_LIBS;\nextern OCTINTERP_API const char *SH_LDFLAGS;\nextern OCTINTERP_API const char *STATIC_LIBS;\nextern OCTINTERP_API const char *SUITESPARSECONFIG_LIBS;\nextern OCTINTERP_API const char *SUNDIALS_IDA_CPPFLAGS;\nextern OCTINTERP_API const char *SUNDIALS_IDA_LDFLAGS;\nextern OCTINTERP_API const char *SUNDIALS_IDA_LIBS;\nextern OCTINTERP_API const char *SUNDIALS_NVECSERIAL_CPPFLAGS;\nextern OCTINTERP_API const char *SUNDIALS_NVECSERIAL_LDFLAGS;\nextern OCTINTERP_API const char *SUNDIALS_NVECSERIAL_LIBS;\nextern OCTINTERP_API const char *SUNDIALS_SUNLINSOLKLU_CPPFLAGS;\nextern OCTINTERP_API const char *SUNDIALS_SUNLINSOLKLU_LDFLAGS;\nextern OCTINTERP_API const char *SUNDIALS_SUNLINSOLKLU_LIBS;\nextern OCTINTERP_API const char *UMFPACK_CPPFLAGS;\nextern OCTINTERP_API const char *UMFPACK_LDFLAGS;\nextern OCTINTERP_API const char *UMFPACK_LIBS;\nextern OCTINTERP_API const char *WARN_CFLAGS;\nextern OCTINTERP_API const char *WARN_CXXFLAGS;\nextern OCTINTERP_API const char *X11_INCFLAGS;\nextern OCTINTERP_API const char *X11_LIBS;\nextern OCTINTERP_API const char *XTRA_CFLAGS;\nextern OCTINTERP_API const char *XTRA_CXXFLAGS;\nextern OCTINTERP_API const char *YACC;\nextern OCTINTERP_API const char *YFLAGS;\nextern OCTINTERP_API const char *Z_CPPFLAGS;\nextern OCTINTERP_API const char *Z_LDFLAGS;\nextern OCTINTERP_API const char *Z_LIBS;\nextern OCTINTERP_API const char *config_opts;\n\nOCTAVE_END_NAMESPACE(build_env)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/build-env.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"build-env.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(build_env)\n\nconst char *AMD_CPPFLAGS = %OCTAVE_CONF_AMD_CPPFLAGS%;\n\nconst char *AMD_LDFLAGS = %OCTAVE_CONF_AMD_LDFLAGS%;\n\nconst char *AMD_LIBS = %OCTAVE_CONF_AMD_LIBS%;\n\nconst char *ARFLAGS = %OCTAVE_CONF_ARFLAGS%;\n\nconst char *AR = %OCTAVE_CONF_AR%;\n\nconst char *ARPACK_CPPFLAGS = %OCTAVE_CONF_ARPACK_CPPFLAGS%;\n\nconst char *ARPACK_LDFLAGS = %OCTAVE_CONF_ARPACK_LDFLAGS%;\n\nconst char *ARPACK_LIBS = %OCTAVE_CONF_ARPACK_LIBS%;\n\nconst char *BLAS_LIBS = %OCTAVE_CONF_BLAS_LIBS%;\n\nconst char *CAMD_CPPFLAGS = %OCTAVE_CONF_CAMD_CPPFLAGS%;\n\nconst char *CAMD_LDFLAGS = %OCTAVE_CONF_CAMD_LDFLAGS%;\n\nconst char *CAMD_LIBS = %OCTAVE_CONF_CAMD_LIBS%;\n\nconst char *CARBON_LIBS = %OCTAVE_CONF_CARBON_LIBS%;\n\nconst char *CC = %OCTAVE_CONF_CC%;\n\nconst char *CCOLAMD_CPPFLAGS = %OCTAVE_CONF_CCOLAMD_CPPFLAGS%;\n\nconst char *CCOLAMD_LDFLAGS = %OCTAVE_CONF_CCOLAMD_LDFLAGS%;\n\nconst char *CCOLAMD_LIBS = %OCTAVE_CONF_CCOLAMD_LIBS%;\n\nconst char *CFLAGS = %OCTAVE_CONF_CFLAGS%;\n\nconst char *CHOLMOD_CPPFLAGS = %OCTAVE_CONF_CHOLMOD_CPPFLAGS%;\n\nconst char *CHOLMOD_LDFLAGS = %OCTAVE_CONF_CHOLMOD_LDFLAGS%;\n\nconst char *CHOLMOD_LIBS = %OCTAVE_CONF_CHOLMOD_LIBS%;\n\nconst char *COLAMD_CPPFLAGS = %OCTAVE_CONF_COLAMD_CPPFLAGS%;\n\nconst char *COLAMD_LDFLAGS = %OCTAVE_CONF_COLAMD_LDFLAGS%;\n\nconst char *COLAMD_LIBS = %OCTAVE_CONF_COLAMD_LIBS%;\n\nconst char *CPICFLAG = %OCTAVE_CONF_CPICFLAG%;\n\nconst char *CPPFLAGS = %OCTAVE_CONF_CPPFLAGS%;\n\nconst char *CURL_CPPFLAGS = %OCTAVE_CONF_CURL_CPPFLAGS%;\n\nconst char *CURL_LDFLAGS = %OCTAVE_CONF_CURL_LDFLAGS%;\n\nconst char *CURL_LIBS = %OCTAVE_CONF_CURL_LIBS%;\n\nconst char *CXSPARSE_CPPFLAGS = %OCTAVE_CONF_CXSPARSE_CPPFLAGS%;\n\nconst char *CXSPARSE_LDFLAGS = %OCTAVE_CONF_CXSPARSE_LDFLAGS%;\n\nconst char *CXSPARSE_LIBS = %OCTAVE_CONF_CXSPARSE_LIBS%;\n\nconst char *CXXCPP = %OCTAVE_CONF_CXXCPP%;\n\nconst char *CXXFLAGS = %OCTAVE_CONF_CXXFLAGS%;\n\nconst char *CXXPICFLAG = %OCTAVE_CONF_CXXPICFLAG%;\n\nconst char *CXX = %OCTAVE_CONF_CXX%;\n\nconst char *DEFAULT_PAGER = %OCTAVE_CONF_DEFAULT_PAGER%;\n\nconst char *DEFS = %OCTAVE_CONF_DEFS%;\n\nconst char *DL_LDFLAGS = %OCTAVE_CONF_DL_LDFLAGS%;\n\nconst char *EXEEXT = %OCTAVE_CONF_EXEEXT%;\n\nconst char *GCC_VERSION = %OCTAVE_CONF_GCC_VERSION%;\n\nconst char *GXX_VERSION = %OCTAVE_CONF_GXX_VERSION%;\n\nconst char *F77 = %OCTAVE_CONF_F77%;\n\nconst char *F77_FLOAT_STORE_FLAG = %OCTAVE_CONF_F77_FLOAT_STORE_FLAG%;\n\nconst char *F77_INTEGER_8_FLAG = %OCTAVE_CONF_F77_INTEGER_8_FLAG%;\n\nconst char *FFLAGS = %OCTAVE_CONF_FFLAGS%;\n\nconst char *FFTW3_CPPFLAGS = %OCTAVE_CONF_FFTW3_CPPFLAGS%;\n\nconst char *FFTW3_LDFLAGS = %OCTAVE_CONF_FFTW3_LDFLAGS%;\n\nconst char *FFTW3_LIBS = %OCTAVE_CONF_FFTW3_LIBS%;\n\nconst char *FFTW3F_CPPFLAGS = %OCTAVE_CONF_FFTW3F_CPPFLAGS%;\n\nconst char *FFTW3F_LDFLAGS = %OCTAVE_CONF_FFTW3F_LDFLAGS%;\n\nconst char *FFTW3F_LIBS = %OCTAVE_CONF_FFTW3F_LIBS%;\n\nconst char *FLIBS = %OCTAVE_CONF_FLIBS%;\n\nconst char *FLTK_CPPFLAGS = %OCTAVE_CONF_FLTK_CPPFLAGS%;\n\nconst char *FLTK_LDFLAGS = %OCTAVE_CONF_FLTK_LDFLAGS%;\n\nconst char *FLTK_LIBS = %OCTAVE_CONF_FLTK_LIBS%;\n\nconst char *FONTCONFIG_CPPFLAGS = %OCTAVE_CONF_FONTCONFIG_CPPFLAGS%;\n\nconst char *FONTCONFIG_LIBS = %OCTAVE_CONF_FONTCONFIG_LIBS%;\n\nconst char *FPICFLAG = %OCTAVE_CONF_FPICFLAG%;\n\nconst char *FT2_CPPFLAGS = %OCTAVE_CONF_FT2_CPPFLAGS%;\n\nconst char *FT2_LIBS = %OCTAVE_CONF_FT2_LIBS%;\n\nconst char *GLPK_CPPFLAGS = %OCTAVE_CONF_GLPK_CPPFLAGS%;\n\nconst char *GLPK_LDFLAGS = %OCTAVE_CONF_GLPK_LDFLAGS%;\n\nconst char *GLPK_LIBS = %OCTAVE_CONF_GLPK_LIBS%;\n\nconst char *GNUPLOT = %OCTAVE_CONF_GNUPLOT%;\n\nconst char *HDF5_CPPFLAGS = %OCTAVE_CONF_HDF5_CPPFLAGS%;\n\nconst char *HDF5_LDFLAGS = %OCTAVE_CONF_HDF5_LDFLAGS%;\n\nconst char *HDF5_LIBS = %OCTAVE_CONF_HDF5_LIBS%;\n\nconst char *INCLUDEDIR = %OCTAVE_CONF_INCLUDEDIR%;\n\nconst char *KLU_CPPFLAGS = %OCTAVE_CONF_KLU_CPPFLAGS%;\n\nconst char *KLU_LDFLAGS = %OCTAVE_CONF_KLU_LDFLAGS%;\n\nconst char *KLU_LIBS = %OCTAVE_CONF_KLU_LIBS%;\n\nconst char *LAPACK_LIBS = %OCTAVE_CONF_LAPACK_LIBS%;\n\nconst char *LDFLAGS = %OCTAVE_CONF_LDFLAGS%;\n\nconst char *LD_STATIC_FLAG = %OCTAVE_CONF_LD_STATIC_FLAG%;\n\nconst char *LEXLIB = %OCTAVE_CONF_LEXLIB%;\n\nconst char *LEX = %OCTAVE_CONF_LEX%;\n\nconst char *LFLAGS = %OCTAVE_CONF_LFLAGS%;\n\nconst char *LIBOCTAVE = %OCTAVE_CONF_LIBOCTAVE%;\n\nconst char *LIBOCTINTERP = %OCTAVE_CONF_LIBOCTINTERP%;\n\nconst char *LIBS = %OCTAVE_CONF_LIBS%;\n\nconst char *LN_S = %OCTAVE_CONF_LN_S%;\n\nconst char *MAGICK_CPPFLAGS = %OCTAVE_CONF_MAGICK_CPPFLAGS%;\n\nconst char *MAGICK_LDFLAGS = %OCTAVE_CONF_MAGICK_LDFLAGS%;\n\nconst char *MAGICK_LIBS = %OCTAVE_CONF_MAGICK_LIBS%;\n\nconst char *MKOCTFILE_DL_LDFLAGS = %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%;\n\nconst char *OCTAVE_LINK_DEPS = %OCTAVE_CONF_OCTAVE_LINK_DEPS%;\n\nconst char *OCTAVE_LINK_OPTS = %OCTAVE_CONF_OCTAVE_LINK_OPTS%;\n\nconst char *OCTINCLUDEDIR = %OCTAVE_CONF_OCTINCLUDEDIR%;\n\nconst char *OCTLIBDIR = %OCTAVE_CONF_OCTLIBDIR%;\n\nconst char *OCT_LINK_DEPS = %OCTAVE_CONF_OCT_LINK_DEPS%;\n\nconst char *OCT_LINK_OPTS = %OCTAVE_CONF_OCT_LINK_OPTS%;\n\nconst char *OPENGL_LIBS = %OCTAVE_CONF_OPENGL_LIBS%;\n\nconst char *PCRE_CPPFLAGS = %OCTAVE_CONF_PCRE_CPPFLAGS%;\n\nconst char *PCRE_LDFLAGS = %OCTAVE_CONF_PCRE_LDFLAGS%;\n\nconst char *PCRE_LIBS = %OCTAVE_CONF_PCRE_LIBS%;\n\nconst char *PREFIX = %OCTAVE_CONF_PREFIX%;\n\nconst char *PTHREAD_CFLAGS = %OCTAVE_CONF_PTHREAD_CFLAGS%;\n\nconst char *PTHREAD_LIBS = %OCTAVE_CONF_PTHREAD_LIBS%;\n\nconst char *QHULL_CPPFLAGS = %OCTAVE_CONF_QHULL_CPPFLAGS%;\n\nconst char *QHULL_LDFLAGS = %OCTAVE_CONF_QHULL_LDFLAGS%;\n\nconst char *QHULL_LIBS = %OCTAVE_CONF_QHULL_LIBS%;\n\nconst char *QRUPDATE_CPPFLAGS = %OCTAVE_CONF_QRUPDATE_CPPFLAGS%;\n\nconst char *QRUPDATE_LDFLAGS = %OCTAVE_CONF_QRUPDATE_LDFLAGS%;\n\nconst char *QRUPDATE_LIBS = %OCTAVE_CONF_QRUPDATE_LIBS%;\n\nconst char *QT_CPPFLAGS = %OCTAVE_CONF_QT_CPPFLAGS%;\n\nconst char *QT_LDFLAGS = %OCTAVE_CONF_QT_LDFLAGS%;\n\nconst char *QT_LIBS = %OCTAVE_CONF_QT_LIBS%;\n\nconst char *RANLIB = %OCTAVE_CONF_RANLIB%;\n\nconst char *RDYNAMIC_FLAG = %OCTAVE_CONF_RDYNAMIC_FLAG%;\n\nconst char *READLINE_LIBS = %OCTAVE_CONF_READLINE_LIBS%;\n\nconst char *SHARED_LIBS = %OCTAVE_CONF_SHARED_LIBS%;\n\nconst char *SH_LDFLAGS = %OCTAVE_CONF_SH_LDFLAGS%;\n\nconst char *STATIC_LIBS = %OCTAVE_CONF_STATIC_LIBS%;\n\nconst char *SUITESPARSECONFIG_LIBS = %OCTAVE_CONF_SUITESPARSECONFIG_LIBS%;\n\nconst char *SUNDIALS_IDA_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_IDA_CPPFLAGS%;\n\nconst char *SUNDIALS_IDA_LDFLAGS = %OCTAVE_CONF_SUNDIALS_IDA_LDFLAGS%;\n\nconst char *SUNDIALS_IDA_LIBS = %OCTAVE_CONF_SUNDIALS_IDA_LIBS%;\n\nconst char *SUNDIALS_NVECSERIAL_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_CPPFLAGS%;\n\nconst char *SUNDIALS_NVECSERIAL_LDFLAGS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_LDFLAGS%;\n\nconst char *SUNDIALS_NVECSERIAL_LIBS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_LIBS%;\n\nconst char *SUNDIALS_SUNLINSOLKLU_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_CPPFLAGS%;\n\nconst char *SUNDIALS_SUNLINSOLKLU_LDFLAGS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LDFLAGS%;\n\nconst char *SUNDIALS_SUNLINSOLKLU_LIBS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LIBS%;\n\nconst char *UMFPACK_CPPFLAGS = %OCTAVE_CONF_UMFPACK_CPPFLAGS%;\n\nconst char *UMFPACK_LDFLAGS = %OCTAVE_CONF_UMFPACK_LDFLAGS%;\n\nconst char *UMFPACK_LIBS = %OCTAVE_CONF_UMFPACK_LIBS%;\n\nconst char *WARN_CFLAGS = %OCTAVE_CONF_WARN_CFLAGS%;\n\nconst char *WARN_CXXFLAGS = %OCTAVE_CONF_WARN_CXXFLAGS%;\n\nconst char *X11_INCFLAGS = %OCTAVE_CONF_X11_INCFLAGS%;\n\nconst char *X11_LIBS = %OCTAVE_CONF_X11_LIBS%;\n\nconst char *XTRA_CFLAGS = %OCTAVE_CONF_XTRA_CFLAGS%;\n\nconst char *XTRA_CXXFLAGS = %OCTAVE_CONF_XTRA_CXXFLAGS%;\n\nconst char *YACC = %OCTAVE_CONF_YACC%;\n\nconst char *YFLAGS = %OCTAVE_CONF_YFLAGS%;\n\nconst char *Z_CPPFLAGS = %OCTAVE_CONF_Z_CPPFLAGS%;\n\nconst char *Z_LDFLAGS = %OCTAVE_CONF_Z_LDFLAGS%;\n\nconst char *Z_LIBS = %OCTAVE_CONF_Z_LIBS%;\n\nconst char *config_opts = %OCTAVE_CONF_config_opts%;\n\nOCTAVE_END_NAMESPACE(build_env)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/Cell.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"idx-vector.h\"\n\n#include \"Cell.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\nCell::Cell (const octave_value_list& ovl)\n  : Array<octave_value> (ovl.cell_value ())\n{ }\n\nCell::Cell (const string_vector& sv, bool trim)\n  : Array<octave_value> ()\n{\n  octave_idx_type n = sv.numel ();\n\n  if (n > 0)\n    {\n      resize (dim_vector (n, 1));\n\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          std::string s = sv[i];\n\n          if (trim)\n            {\n              std::size_t pos = s.find_last_not_of (' ');\n\n              s = (pos == std::string::npos) ? \"\" : s.substr (0, pos+1);\n            }\n\n          elem (i, 0) = s;\n        }\n    }\n}\n\nCell::Cell (const std::list<std::string>& sl)\n  : Array<octave_value> ()\n{\n  octave_idx_type n = sl.size ();\n\n  if (n > 0)\n    {\n      resize (dim_vector (n, 1));\n\n      octave_value *dst = rwdata ();\n      auto p = sl.begin ();\n\n      for (octave_idx_type i = 0; i < n; i++)\n        dst[i] = *p++;\n    }\n}\n\nCell::Cell (const Array<std::string>& sa)\n  : Array<octave_value> (sa.dims ())\n{\n  octave_idx_type n = sa.numel ();\n\n  octave_value *dst = rwdata ();\n  const std::string *src = sa.data ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    dst[i] = src[i];\n}\n\n// Set size to DV, filling with [].  Then fill with as many elements of\n// SV as possible.\n\nCell::Cell (const dim_vector& dv, const string_vector& sv, bool trim)\n  : Array<octave_value> (dv, Matrix ())\n{\n  octave_idx_type n = sv.numel ();\n\n  if (n > 0)\n    {\n      octave_idx_type m = numel ();\n\n      octave_idx_type len = (n > m ? m : n);\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          std::string s = sv[i];\n\n          if (trim)\n            {\n              std::size_t pos = s.find_last_not_of (' ');\n\n              s = (pos == std::string::npos) ? \"\" : s.substr (0, pos+1);\n            }\n\n          elem(i) = s;\n        }\n    }\n}\n\nbool\nCell::iscellstr () const\n{\n  bool retval = true;\n\n  octave_idx_type n = numel ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      if (! elem(i).is_string ())\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nArray<std::string>\nCell::cellstr_value () const\n{\n  Array<std::string> retval (dims ());\n\n  octave_idx_type n = numel ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    retval.xelem (i) = elem (i).string_value ();\n\n  return retval;\n}\n\nstring_vector\nCell::string_vector_value () const\n{\n  octave_idx_type n = numel ();\n\n  string_vector retval (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    retval.xelem (i) = elem (i).string_value ();\n\n  return retval;\n}\n\nCell\nCell::index (const octave_value_list& idx_arg, bool resize_ok) const\n{\n  Cell retval;\n\n  octave_idx_type n = idx_arg.length ();\n\n  // If we catch an indexing error in index_vector, we flag an error\n  // in index k.  Ensure it is the right value before each idx_vector\n  // call.  Same variable as used in for loop in default case.\n\n  octave_idx_type k = 0;\n\n  try\n    {\n      switch (n)\n        {\n        case 0:\n          warn_empty_index (\"cell array\");\n          retval = *this;\n          break;\n\n        case 1:\n          {\n            octave::idx_vector i = idx_arg(0).index_vector ();\n\n            retval = Array<octave_value>::index (i, resize_ok, Matrix ());\n          }\n          break;\n\n        case 2:\n          {\n            octave::idx_vector i = idx_arg(0).index_vector ();\n\n            k = 1;\n            octave::idx_vector j = idx_arg(1).index_vector ();\n\n            retval = Array<octave_value>::index (i, j, resize_ok, Matrix ());\n          }\n          break;\n\n        default:\n          {\n            Array<octave::idx_vector> iv (dim_vector (n, 1));\n\n            for (k = 0; k < n; k++)\n              iv(k) = idx_arg(k).index_vector ();\n\n            retval = Array<octave_value>::index (iv, resize_ok, Matrix ());\n          }\n          break;\n        }\n    }\n  catch (octave::index_exception& ie)\n    {\n      // Rethrow to allow more info to be reported later.\n      ie.set_pos_if_unset (n, k+1);\n      throw;\n    }\n\n  return retval;\n}\n\n/*\n%% This behavior is required for Matlab compatibility.\n%!shared a\n%! a = {\"foo\", \"bar\"};\n%!assert (a(), a)\n%!error <invalid empty index expression> a{}\n*/\n\nvoid\nCell::assign (const octave_value_list& idx_arg, const Cell& rhs,\n              const octave_value& fill_val)\n\n{\n  octave_idx_type len = idx_arg.length ();\n\n  Array<octave::idx_vector> ra_idx (dim_vector (len, 1));\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      try\n        {\n          ra_idx(i) = idx_arg(i).index_vector ();\n        }\n      catch (octave::index_exception& ie)\n        {\n          // Rethrow to allow more info to be reported later.\n          ie.set_pos (len, i+1);\n          throw;\n        }\n    }\n\n  Array<octave_value>::assign (ra_idx, rhs, fill_val);\n}\n\nvoid\nCell::delete_elements (const octave_value_list& idx_arg)\n\n{\n  octave_idx_type len = idx_arg.length ();\n\n  Array<octave::idx_vector> ra_idx (dim_vector (len, 1));\n\n  for (octave_idx_type i = 0; i < len; i++)\n    try\n      {\n        ra_idx.xelem (i) = idx_arg(i).index_vector ();\n      }\n    catch (octave::index_exception& ie)\n      {\n        // Rethrow to allow more info to be reported later.\n        ie.set_pos (len, i+1);\n        throw;\n      }\n\n  Array<octave_value>::delete_elements (ra_idx);\n}\n\noctave_idx_type\nCell::nnz () const\n{\n  err_wrong_type_arg (\"nnz\", \"cell array\");\n}\n\n/*\n%!error <wrong type argument 'cell array'> nnz ({0, 1, 2})\n%!error <wrong type argument 'cell array'> nnz (cell ())\n%!error <wrong type argument 'cell array'> nnz ({\"foo\", \"bar\"})\n*/\n\nCell\nCell::column (octave_idx_type i) const\n{\n  Cell retval;\n\n  if (ndims () > 2)\n    error (\"Cell::column: requires 2-D cell array\");\n\n  if (i < 0 || i >= cols ())\n    error (\"invalid column selection\");\n\n  octave_idx_type nr = rows ();\n\n  retval.resize (dim_vector (nr, 1));\n\n  for (octave_idx_type j = 0; j < nr; j++)\n    retval.xelem (j) = elem (j, i);\n\n  return retval;\n}\n\nCell\nCell::concat (const Cell& rb, const Array<octave_idx_type>& ra_idx)\n{\n  return insert (rb, ra_idx);\n}\n\nCell&\nCell::insert (const Cell& a, octave_idx_type r, octave_idx_type c)\n{\n  Array<octave_value>::insert (a, r, c);\n  return *this;\n}\n\nCell&\nCell::insert (const Cell& a, const Array<octave_idx_type>& ra_idx)\n{\n  Array<octave_value>::insert (a, ra_idx);\n  return *this;\n}\n\nCell\nCell::map (ctype_mapper fcn) const\n{\n  Cell retval (dims ());\n  octave_value *r = retval.rwdata ();\n\n  const octave_value *p = data ();\n\n  for (octave_idx_type i = 0; i < numel (); i++)\n    r[i] = ((p++)->*fcn) ();\n\n  return retval;\n}\n\noctave_value\nCell::resize_fill_value () const\n{\n  static octave_value rfv = octave_value (Matrix ());\n  return rfv;\n}\n\nCell\nCell::diag (octave_idx_type k) const\n{\n  return Array<octave_value>::diag (k);\n}\n\nCell\nCell::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return Array<octave_value>::diag (m, n);\n}\n"
  },
  {
    "path": "libinterp/corefcn/Cell.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Cell_h)\n#define octave_Cell_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n\n#include \"Array.h\"\n#include \"str-vec.h\"\n#include \"ov.h\"\n\nclass octave_value_list;\n\nclass OCTINTERP_API Cell : public Array<octave_value>\n{\npublic:\n\n  Cell () = default;\n\n  Cell (const Cell& c) = default;\n\n  Cell& operator = (const Cell& c) = default;\n\n  ~Cell () = default;\n\n  Cell (const octave_value& val)\n    : Array<octave_value> (dim_vector (1, 1), val) { }\n\n  Cell (const octave_value_list& ovl);\n\n  Cell (octave_idx_type n, octave_idx_type m,\n        const octave_value& val = Matrix ())\n    : Array<octave_value> (dim_vector (n, m), val) { }\n\n  Cell (const dim_vector& dv, const octave_value& val = Matrix ())\n    : Array<octave_value> (dv, val) { }\n\n  Cell (const Array<octave_value>& c)\n    : Array<octave_value> (c) { }\n\n  Cell (const Array<octave_value>& c, octave_idx_type nr, octave_idx_type nc)\n    : Array<octave_value> (c, dim_vector (nr, nc)) { }\n\n  Cell (const string_vector& sv, bool trim = false);\n\n  // Constructor for standard containers.  V must be convertible to an\n  // octave_value object.\n  template <typename V, template <typename...> class C>\n  explicit\n  Cell (const C<V>& container)\n    : Array<octave_value> ()\n  {\n    std::size_t n = container.size ();\n\n    if (n > 0)\n      {\n        resize (dim_vector (n, 1));\n\n        octave_idx_type i = 0;\n\n        for (const auto& val : container)\n          elem(i++, 0) = val;\n      }\n  }\n\n  Cell (const std::list<std::string>& sl);\n\n  Cell (const Array<std::string>& sa);\n\n  Cell (const dim_vector& dv, const string_vector& sv, bool trim = false);\n\n  bool iscellstr () const;\n\n  Array<std::string> cellstr_value () const;\n\n  string_vector string_vector_value () const;\n\n  using Array<octave_value>::index;\n\n  Cell index (const octave_value_list& idx, bool resize_ok = false) const;\n\n  using Array<octave_value>::delete_elements;\n\n  void delete_elements (const octave_value_list& idx);\n\n  using Array<octave_value>::assign;\n\n  void assign (const octave_value_list& idx, const Cell& rhs,\n               const octave_value& fill_val = Matrix ());\n\n  Cell reshape (const dim_vector& new_dims) const\n  { return Array<octave_value>::reshape (new_dims); }\n\n  octave_idx_type nnz () const;\n\n  Cell column (octave_idx_type i) const;\n\n  // FIXME\n  boolMatrix all (int /* dim */ = 0) const { return boolMatrix (); }\n\n  // FIXME\n  boolMatrix any (int /* dim */ = 0) const { return boolMatrix (); }\n\n  Cell concat (const Cell& rb, const Array<octave_idx_type>& ra_idx);\n\n  Cell& insert (const Cell& a, octave_idx_type r, octave_idx_type c);\n  Cell& insert (const Cell& a, const Array<octave_idx_type>& ra_idx);\n\n  // FIXME\n  bool any_element_is_nan () const { return false; }\n  bool is_true () const { return false; }\n\n  octave_value resize_fill_value () const;\n\n  Cell diag (octave_idx_type k = 0) const;\n\n  Cell diag (octave_idx_type m, octave_idx_type n) const;\n\n  Cell xisalnum () const { return map (&octave_value::xisalnum); }\n  Cell xisalpha () const { return map (&octave_value::xisalpha); }\n  Cell xisascii () const { return map (&octave_value::xisascii); }\n  Cell xiscntrl () const { return map (&octave_value::xiscntrl); }\n  Cell xisdigit () const { return map (&octave_value::xisdigit); }\n  Cell xisgraph () const { return map (&octave_value::xisgraph); }\n  Cell xislower () const { return map (&octave_value::xislower); }\n  Cell xisprint () const { return map (&octave_value::xisprint); }\n  Cell xispunct () const { return map (&octave_value::xispunct); }\n  Cell xisspace () const { return map (&octave_value::xisspace); }\n  Cell xisupper () const { return map (&octave_value::xisupper); }\n  Cell xisxdigit () const { return map (&octave_value::xisxdigit); }\n  Cell xtolower () const { return map (&octave_value::xtolower); }\n  Cell xtoupper () const { return map (&octave_value::xtoupper); }\n\nprivate:\n\n  typedef octave_value (octave_value::*ctype_mapper) () const;\n\n  Cell map (ctype_mapper) const;\n};\n\ntemplate <>\ninline Cell octave_value_extract<Cell> (const octave_value& v)\n{ return v.cell_value (); }\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/__magick_read__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"file-stat.h\"\n#include \"oct-env.h\"\n#include \"oct-sysdep.h\"\n#include \"oct-time.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ov-struct.h\"\n\n#include \"errwarn.h\"\n\n#if defined (HAVE_MAGICK)\n#  include <Magick++.h>\n#  include <clocale>\n// FIXME: The following using declaration may be needed to build with\n// ImageMagick.  It doesn't appear to be needed for GraphicsMagick but\n// it also doesn't seem to cause trouble.  A configure test would be\n// helpful.\nusing Magick::Quantum;\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_MAGICK)\n\n// In theory, it should be enough to check the class:\n// Magick::ClassType\n// PseudoClass:\n// Image is composed of pixels which specify an index in a color palette.\n// DirectClass:\n// Image is composed of pixels which represent literal color values.\n//\n//  GraphicsMagick does not really distinguishes between indexed and\n//  normal images.  After reading a file, it decides itself the optimal\n//  way to store the image in memory, independently of the how the\n//  image was stored in the file.  That's what ClassType returns.  While\n//  it seems to match the original file most of the times, this is\n//  not necessarily true all the times.  See\n//    https://sourceforge.net/mailarchive/message.php?msg_id=31180507\n//  In addition to the ClassType, there is also ImageType which has a\n//  type for indexed images (PaletteType and PaletteMatteType).  However,\n//  they also don't represent the original image.  Not only does DirectClass\n//  can have a PaletteType, but also does a PseudoClass have non Palette\n//  types.\n//\n//        We can't do better without having format specific code which is\n//        what we are trying to avoid by using a library such as GM.  We at\n//        least create workarounds for the most common problems.\n//\n// 1) A grayscale jpeg image can report being indexed even though the\n//    JPEG format has no support for indexed images.  We can at least\n//    fix this one.\n// 2) A PNG file is only an indexed image if color type orig is 3 (value comes\n//    from libpng)\nstatic bool\nis_indexed (const Magick::Image& img)\n{\n  bool indexed = (img.classType () == Magick::PseudoClass);\n  // Our problem until now is non-indexed images, being represented as indexed\n  // by GM.  The following attempts educated guesses to undo this optimization.\n  if (indexed)\n    {\n      const std::string fmt = img.magick ();\n      if (fmt == \"JPEG\")\n        // The JPEG format does not support indexed images, but GM sometimes\n        // reports grayscale JPEG as indexed.  Always false for JPEG.\n        indexed = false;\n      else if (fmt == \"PNG\")\n        {\n          // Newer versions of GM (at least does not happens with 1.3.16) will\n          // store values from the underlying library as image attributes.  In\n          // the case of PNG files, this is libpng where an indexed image will\n          // always have a value of 3 for \"color-type-orig\".  This property\n          // always has a value in libpng so if we get nothing, we assume this\n          // GM version does not store them and we have to go with whatever\n          // GM PseudoClass says.\n          const std::string color_type\n            = const_cast<Magick::Image&> (img).attribute (\"PNG:IHDR.color-type-orig\");\n          if (! color_type.empty () && color_type != \"3\")\n            indexed = false;\n        }\n    }\n  return indexed;\n}\n\n//  The depth from depth() is not always correct for us but seems to be the\n//  best value we can get.  For example, a grayscale png image with 1 bit\n//  per channel should return a depth of 1 but instead we get 8.\n//  We could check channelDepth() but then, which channel has the data\n//  is not straightforward.  So we'd have to check all\n//  the channels and select the highest value.  But then, I also\n//  have a 16bit TIFF whose depth returns 16 (correct), but all of the\n//  channels gives 8 (wrong).  No idea why, maybe a bug in GM?\n//  Anyway, using depth() seems that only causes problems for binary\n//  images, and the problem with channelDepth() is not making set them\n//  all to 1.  So we will guess that if all channels have depth of 1,\n//  then we must have a binary image.\n//  Note that we can't use AllChannels it doesn't work for this.\n//  We also can't check only one from RGB, one from CMYK, and grayscale\n// and transparency, we really need to check all of the channels (bug #41584).\nstatic octave_idx_type\nget_depth (Magick::Image& img)\n{\n  octave_idx_type depth = img.depth ();\n  if (depth == 8\n      && img.channelDepth (Magick::RedChannel)     == 1\n      && img.channelDepth (Magick::GreenChannel)   == 1\n      && img.channelDepth (Magick::BlueChannel)    == 1\n      && img.channelDepth (Magick::CyanChannel)    == 1\n      && img.channelDepth (Magick::MagentaChannel) == 1\n      && img.channelDepth (Magick::YellowChannel)  == 1\n      && img.channelDepth (Magick::BlackChannel)   == 1\n      && img.channelDepth (Magick::OpacityChannel) == 1\n      && img.channelDepth (Magick::GrayChannel)    == 1)\n    depth = 1;\n\n  return depth;\n}\n\n// We need this in case one of the sides of the image being read has\n// width 1.  In those cases, the type will come as scalar instead of range\n// since that's the behavior of the colon operator (1:1:1 will be a scalar,\n// not a range).\nstatic range<double>\nget_region_range (const octave_value& region)\n{\n  range<double> output;\n\n  if (region.is_range ())\n    output = region.range_value ();\n  else if (region.is_scalar_type ())\n    {\n      double value = region.scalar_value ();\n      output = range<double> (value, value);\n    }\n  else if (region.is_matrix_type ())\n    {\n      NDArray array = region.array_value ();\n      double base = array(0);\n      double limit = array(array.numel () - 1);\n      double incr = array(1) - base;\n      output = range<double> (base, incr, limit);\n    }\n  else\n    error (\"__magick_read__: unknown datatype for Region option\");\n\n  return output;\n}\n\nclass image_region\n{\npublic:\n\n  image_region () = delete;\n\n  image_region (const octave_scalar_map& options)\n  {\n    // FIXME: should we have better checking on the input map and values\n    // or is that expected to be done elsewhere?\n\n    const Cell pixel_region = options.getfield (\"region\").cell_value ();\n\n    // Subtract 1 to account for 0 indexing.\n\n    const range<double> rows = get_region_range (pixel_region (0));\n    const range<double> cols = get_region_range (pixel_region (1));\n\n    m_row_start = rows.base () - 1;\n    m_col_start = cols.base () - 1;\n    m_row_end = rows.max () - 1;\n    m_col_end = cols.max () - 1;\n\n    m_row_cache = m_row_end - m_row_start + 1;\n    m_col_cache = m_col_end - m_col_start + 1;\n\n    m_row_shift = m_col_cache * rows.increment ();\n    m_col_shift = m_col_cache * (m_row_cache + rows.increment () - 1) - cols.increment ();\n\n    m_row_out = rows.numel ();\n    m_col_out = cols.numel ();\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (image_region)\n\n  octave_idx_type row_start () const { return m_row_start; }\n  octave_idx_type col_start () const { return m_col_start; }\n  octave_idx_type row_end () const { return m_row_end; }\n  octave_idx_type col_end () const { return m_col_end; }\n\n  // Length of the area to load into the Image Pixel Cache.  We use max and\n  // min to account for cases where last element of range is the range limit.\n\n  octave_idx_type row_cache () const { return m_row_cache; }\n  octave_idx_type col_cache () const { return m_col_cache; }\n\n  // How much we have to shift in the memory when doing the loops.\n\n  octave_idx_type row_shift () const { return m_row_shift; }\n  octave_idx_type col_shift () const { return m_col_shift; }\n\n  // The actual height and width of the output image\n\n  octave_idx_type row_out () const { return m_row_out; }\n  octave_idx_type col_out () const { return m_col_out; }\n\nprivate:\n\n  octave_idx_type m_row_start;\n  octave_idx_type m_col_start;\n  octave_idx_type m_row_end;\n  octave_idx_type m_col_end;\n\n  // Length of the area to load into the Image Pixel Cache.  We use max and\n  // min to account for cases where last element of range is the range limit.\n\n  octave_idx_type m_row_cache;\n  octave_idx_type m_col_cache;\n\n  // How much we have to shift in the memory when doing the loops.\n\n  octave_idx_type m_row_shift;\n  octave_idx_type m_col_shift;\n\n  // The actual height and width of the output image\n\n  octave_idx_type m_row_out;\n  octave_idx_type m_col_out;\n};\n\nstatic octave_value_list\nread_maps (Magick::Image& img)\n{\n  // can't call colorMapSize on const Magick::Image\n  const octave_idx_type mapsize = img.colorMapSize ();\n  Matrix cmap                   = Matrix (mapsize, 3); // colormap\n  ColumnVector amap             = ColumnVector (mapsize); // alpha map\n  for (octave_idx_type i = 0; i < mapsize; i++)\n    {\n      const Magick::ColorRGB c = img.colorMap (i);\n      cmap(i, 0) = c.red   ();\n      cmap(i, 1) = c.green ();\n      cmap(i, 2) = c.blue  ();\n      amap(i)   = c.alpha ();\n    }\n  octave_value_list maps;\n  maps(0) = cmap;\n  maps(1) = amap;\n  return maps;\n}\n\ntemplate <typename T>\nstatic octave_value_list\nread_indexed_images (const std::vector<Magick::Image>& imvec,\n                     const Array<octave_idx_type>& frameidx,\n                     const octave_idx_type& nargout,\n                     const octave_scalar_map& options)\n{\n  typedef typename T::element_type P;\n\n  octave_value_list retval (1);\n\n  image_region region (options);\n\n  const octave_idx_type nFrames = frameidx.numel ();\n  const octave_idx_type nRows = region.row_out ();\n  const octave_idx_type nCols = region.col_out ();\n\n  // imvec has all of the pages of a file, even the ones we are not\n  // interested in.  We will use the first image that we will be actually\n  // reading to get information about the image.\n  const octave_idx_type def_elem = frameidx(0);\n\n  T img       = T (dim_vector (nRows, nCols, 1, nFrames));\n  P *img_fvec = img.rwdata ();\n\n  const octave_idx_type row_start = region.row_start ();\n  const octave_idx_type col_start = region.col_start ();\n  const octave_idx_type row_shift = region.row_shift ();\n  const octave_idx_type col_shift = region.col_shift ();\n  const octave_idx_type row_cache = region.row_cache ();\n  const octave_idx_type col_cache = region.col_cache ();\n\n  // When reading PixelPackets from the Image Pixel Cache, they come in\n  // row major order.  So we keep moving back and forth there so we can\n  // write the image in column major order.\n  octave_idx_type idx = 0;\n  for (octave_idx_type frame = 0; frame < nFrames; frame++)\n    {\n      octave_quit ();\n\n      imvec[frameidx(frame)].getConstPixels (col_start, row_start,\n                                             col_cache, row_cache);\n\n      const Magick::IndexPacket *pix\n        = imvec[frameidx(frame)].getConstIndexes ();\n\n      for (octave_idx_type col = 0; col < nCols; col++)\n        {\n          for (octave_idx_type row = 0; row < nRows; row++)\n            {\n              img_fvec[idx++] = static_cast<P> (*pix);\n              pix += row_shift;\n            }\n          pix -= col_shift;\n        }\n    }\n  retval(0) = octave_value (img);\n\n  // Only bother reading the colormap if it was requested as output.\n  if (nargout >= 2)\n    {\n      // In theory, it should be possible for each frame of an image to\n      // have different colormaps but for Matlab compatibility, we only\n      // return the colormap of the first frame.  To obtain the colormaps\n      // of different frames, one needs can either use imfinfo or a for\n      // loop around imread.\n      const octave_value_list maps\n        = read_maps (const_cast<Magick::Image&> (imvec[frameidx(def_elem)]));\n\n      retval(1) = maps(0);\n\n      // only interpret alpha channel if it was requested as output\n      if (nargout >= 3)\n        {\n          if (imvec[def_elem].matte ())\n            {\n              // Alpha channel exists.\n              const Matrix amap = maps(1).matrix_value ();\n              const double *amap_fvec = amap.data ();\n\n              NDArray alpha (dim_vector (nRows, nCols, 1, nFrames));\n              double *alpha_fvec = alpha.rwdata ();\n\n              // GraphicsMagick stores the alpha values inverted, i.e.,\n              // 1 for transparent and 0 for opaque so we fix that here.\n              const octave_idx_type nPixels = alpha.numel ();\n              for (octave_idx_type pix = 0; pix < nPixels; pix++)\n                alpha_fvec[pix] = 1 - amap_fvec[static_cast<octave_idx_type> (img_fvec[pix])];\n\n              retval(2) = alpha;\n            }\n          else\n            {\n              // No alpha channel.  Return empty matrix.\n              retval(2) = Matrix ();\n            }\n        }\n    }\n\n  return retval;\n}\n\n// This function is highly repetitive, a bunch of for loops that are\n// very similar to account for different image types.  They are different\n// enough that trying to reduce the copy and paste would decrease its\n// readability too much.\ntemplate <typename T>\noctave_value_list\nread_images (std::vector<Magick::Image>& imvec,\n             const Array<octave_idx_type>& frameidx,\n             const octave_idx_type& nargout,\n             const octave_scalar_map& options)\n{\n  typedef typename T::element_type P;\n\n  octave_value_list retval (3, Matrix ());\n\n  image_region region (options);\n\n  const octave_idx_type nFrames = frameidx.numel ();\n  const octave_idx_type nRows = region.row_out ();\n  const octave_idx_type nCols = region.col_out ();\n  T img;\n\n  // imvec has all of the pages of a file, even the ones we are not\n  // interested in.  We will use the first image that we will be actually\n  // reading to get information about the image.\n  const octave_idx_type def_elem = frameidx(0);\n\n  const octave_idx_type row_start = region.row_start ();\n  const octave_idx_type col_start = region.col_start ();\n  const octave_idx_type row_shift = region.row_shift ();\n  const octave_idx_type col_shift = region.col_shift ();\n  const octave_idx_type row_cache = region.row_cache ();\n  const octave_idx_type col_cache = region.col_cache ();\n\n  // GraphicsMagick (GM) keeps the image values in memory using whatever\n  // QuantumDepth it was built with independently of the original image\n  // bitdepth.  Basically this means that if GM was built with quantum 16\n  // all values are scaled in the uint16 range.  If the original image\n  // had an 8 bit depth, we need to rescale it for that range.\n  // However, if the image had a bitdepth of 32, then we will be returning\n  // a floating point image.  In this case, the values need to be rescaled\n  // for the range [0 1] (this is what Matlab has documented on the page\n  // about image types but in some cases seems to be doing something else.\n  // See bug #39249).\n  // Finally, we must do the division ourselves (set a divisor) instead of\n  // using quantumOperator for the cases where we will be returning floating\n  // point and want things in the range [0 1].  This is the same reason why\n  // the divisor is of type double.\n  // uint64_t is used in expression because default 32-bit value overflows\n  // when depth() is 32.\n  // FIXME: in the next release of GraphicsMagick, MaxRGB should be replaced\n  //        with QuantumRange since MaxRGB is already deprecated in ImageMagick.\n  double divisor;\n  if (imvec[def_elem].depth () == 32)\n    divisor = std::numeric_limits<uint32_t>::max ();\n  else\n    divisor = MaxRGB / ((uint64_t (1) << imvec[def_elem].depth ()) - 1);\n\n  // FIXME: this workaround should probably be fixed in GM by creating a\n  //        new ImageType BilevelMatteType\n  // Despite what GM documentation claims, opacity is not only on the types\n  // with Matte on the name.  It is possible that an image is completely\n  // black (1 color), and have a second channel set for transparency (2nd\n  // color).  Its type will be bilevel since there is no BilevelMatte.  The\n  // only way to check for this seems to be by checking matte ().\n  Magick::ImageType type = imvec[def_elem].type ();\n  if (type == Magick::BilevelType && imvec[def_elem].matte ())\n    type = Magick::GrayscaleMatteType;\n\n  // FIXME: ImageType is the type being used to represent the image in memory\n  // by GM.  The real type may be different (see among others bug #36820).  For\n  // example, a png file where all channels are equal may report being\n  // grayscale or even bilevel.  But we must always return the real image in\n  // file.  In some cases, the original image attributes are stored in the\n  // attributes but this is undocumented.  This should be fixed in GM so that\n  // a method such as original_type returns an actual Magick::ImageType\n  if (imvec[0].magick () == \"PNG\")\n    {\n      // These values come from libpng, not GM:\n      //      Grayscale         = 0\n      //      Palette           = 2 + 1\n      //      RGB               = 2\n      //      RGB + Alpha       = 2 + 4\n      //      Grayscale + Alpha = 4\n      // We won't bother with case 3 (palette) since those should be\n      // read by the function to read indexed images\n      const std::string type_str\n        = imvec[0].attribute (\"PNG:IHDR.color-type-orig\");\n\n      if (type_str == \"0\")\n        type = Magick::GrayscaleType;\n      else if (type_str == \"2\")\n        type = Magick::TrueColorType;\n      else if (type_str == \"6\")\n        type = Magick::TrueColorMatteType;\n      else if (type_str == \"4\")\n        type = Magick::GrayscaleMatteType;\n      // Color types 0, 2, and 3 can also have alpha channel, conveyed\n      // via the \"tRNS\" chunk.  For 0 and 2, it's limited to GIF-style\n      // binary transparency, while 3 can have any level of alpha per\n      // palette entry.  We thus must check matte() to see if the image\n      // really doesn't have an alpha channel.\n      if (imvec[0].matte ())\n        {\n          if (type == Magick::GrayscaleType)\n            type = Magick::GrayscaleMatteType;\n          else if (type == Magick::TrueColorType)\n            type = Magick::TrueColorMatteType;\n        }\n    }\n\n  // If the alpha channel was not requested, treat images as if\n  // it doesn't exist.\n  if (nargout < 3)\n    {\n      switch (type)\n        {\n        case Magick::GrayscaleMatteType:\n          type = Magick::GrayscaleType;\n          break;\n\n        case Magick::PaletteMatteType:\n          type = Magick::PaletteType;\n          break;\n\n        case Magick::TrueColorMatteType:\n          type = Magick::TrueColorType;\n          break;\n\n        case Magick::ColorSeparationMatteType:\n          type = Magick::ColorSeparationType;\n          break;\n\n        default:\n          // Do nothing other than silencing warnings about enumeration\n          // values not being handled in switch.\n          ;\n        }\n    }\n\n  const octave_idx_type color_stride = nRows * nCols;\n  switch (type)\n    {\n    case Magick::BilevelType:           // Monochrome bi-level image\n    case Magick::GrayscaleType:         // Grayscale image\n      {\n        img = T (dim_vector (nRows, nCols, 1, nFrames));\n        P *img_fvec = img.rwdata ();\n\n        octave_idx_type idx = 0;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            const Magick::PixelPacket *pix\n              = imvec[frameidx(frame)].getConstPixels (col_start, row_start,\n                  col_cache, row_cache);\n\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    img_fvec[idx++] = pix->red / divisor;\n                    pix += row_shift;\n                  }\n                pix -= col_shift;\n              }\n          }\n        break;\n      }\n\n    case Magick::GrayscaleMatteType:    // Grayscale image with opacity\n      {\n        img = T (dim_vector (nRows, nCols, 1, nFrames));\n        T alpha (dim_vector (nRows, nCols, 1, nFrames));\n        P *img_fvec = img.rwdata ();\n        P *a_fvec   = alpha.rwdata ();\n\n        octave_idx_type idx = 0;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            const Magick::PixelPacket *pix\n              = imvec[frameidx(frame)].getConstPixels (col_start, row_start,\n                  col_cache, row_cache);\n\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    img_fvec[idx] = pix->red / divisor;\n                    a_fvec[idx]   = (MaxRGB - pix->opacity) / divisor;\n                    pix += row_shift;\n                    idx++;\n                  }\n                pix -= col_shift;\n              }\n          }\n        retval(2) = alpha;\n        break;\n      }\n\n    case Magick::PaletteType:           // Indexed color (palette) image\n    case Magick::TrueColorType:         // Truecolor image\n      {\n        img = T (dim_vector (nRows, nCols, 3, nFrames));\n        P *img_fvec = img.rwdata ();\n\n        const octave_idx_type frame_stride = color_stride * 3;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            const Magick::PixelPacket *pix\n              = imvec[frameidx(frame)].getConstPixels (col_start, row_start,\n                  col_cache, row_cache);\n\n            octave_idx_type idx = 0;\n            P *rbuf = img_fvec;\n            P *gbuf = img_fvec + color_stride;\n            P *bbuf = img_fvec + color_stride * 2;\n\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    rbuf[idx] = pix->red   / divisor;\n                    gbuf[idx] = pix->green / divisor;\n                    bbuf[idx] = pix->blue  / divisor;\n                    pix += row_shift;\n                    idx++;\n                  }\n                pix -= col_shift;\n              }\n            img_fvec += frame_stride;\n          }\n        break;\n      }\n\n    case Magick::PaletteMatteType:    // Indexed color image with opacity\n    case Magick::TrueColorMatteType:  // Truecolor image with opacity\n      {\n        img = T (dim_vector (nRows, nCols, 3, nFrames));\n        T alpha (dim_vector (nRows, nCols, 1, nFrames));\n        P *img_fvec = img.rwdata ();\n        P *a_fvec   = alpha.rwdata ();\n\n        const octave_idx_type frame_stride = color_stride * 3;\n\n        // Unlike the index for the other channels, this one won't need\n        // to be reset on each frame since it's a separate matrix.\n        octave_idx_type a_idx = 0;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            const Magick::PixelPacket *pix\n              = imvec[frameidx(frame)].getConstPixels (col_start, row_start,\n                  col_cache, row_cache);\n\n            octave_idx_type idx = 0;\n            P *rbuf = img_fvec;\n            P *gbuf = img_fvec + color_stride;\n            P *bbuf = img_fvec + color_stride * 2;\n\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    rbuf[idx]     = pix->red     / divisor;\n                    gbuf[idx]     = pix->green   / divisor;\n                    bbuf[idx]     = pix->blue    / divisor;\n                    a_fvec[a_idx++] = (MaxRGB - pix->opacity) / divisor;\n                    pix += row_shift;\n                    idx++;\n                  }\n                pix -= col_shift;\n              }\n            img_fvec += frame_stride;\n          }\n        retval(2) = alpha;\n        break;\n      }\n\n    case Magick::ColorSeparationType:  // Cyan/Magenta/Yellow/Black (CMYK) image\n      {\n        img = T (dim_vector (nRows, nCols, 4, nFrames));\n        P *img_fvec = img.rwdata ();\n\n        const octave_idx_type frame_stride = color_stride * 4;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            const Magick::PixelPacket *pix\n              = imvec[frameidx(frame)].getConstPixels (col_start, row_start,\n                  col_cache, row_cache);\n\n            octave_idx_type idx = 0;\n            P *cbuf = img_fvec;\n            P *mbuf = img_fvec + color_stride;\n            P *ybuf = img_fvec + color_stride * 2;\n            P *kbuf = img_fvec + color_stride * 3;\n\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    cbuf[idx] = pix->red     / divisor;\n                    mbuf[idx] = pix->green   / divisor;\n                    ybuf[idx] = pix->blue    / divisor;\n                    kbuf[idx] = pix->opacity / divisor;\n                    pix += row_shift;\n                    idx++;\n                  }\n                pix -= col_shift;\n              }\n            img_fvec += frame_stride;\n          }\n        break;\n      }\n\n    // Cyan, magenta, yellow, and black with alpha (opacity) channel\n    case Magick::ColorSeparationMatteType:\n      {\n        img = T (dim_vector (nRows, nCols, 4, nFrames));\n        T alpha (dim_vector (nRows, nCols, 1, nFrames));\n        P *img_fvec = img.rwdata ();\n        P *a_fvec   = alpha.rwdata ();\n\n        const octave_idx_type frame_stride = color_stride * 4;\n\n        // Unlike the index for the other channels, this one won't need\n        // to be reset on each frame since it's a separate matrix.\n        octave_idx_type a_idx = 0;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            const Magick::PixelPacket *pix\n              = imvec[frameidx(frame)].getConstPixels (col_start, row_start,\n                  col_cache, row_cache);\n            // Note that for CMYKColorspace + matte (CMYKA), the opacity is\n            // stored in the associated IndexPacket.\n            const Magick::IndexPacket *apix\n              = imvec[frameidx(frame)].getConstIndexes ();\n\n            octave_idx_type idx = 0;\n            P *cbuf = img_fvec;\n            P *mbuf = img_fvec + color_stride;\n            P *ybuf = img_fvec + color_stride * 2;\n            P *kbuf = img_fvec + color_stride * 3;\n\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    cbuf[idx]     = pix->red     / divisor;\n                    mbuf[idx]     = pix->green   / divisor;\n                    ybuf[idx]     = pix->blue    / divisor;\n                    kbuf[idx]     = pix->opacity / divisor;\n                    a_fvec[a_idx++] = (MaxRGB - *apix) / divisor;\n                    pix += row_shift;\n                    idx++;\n                  }\n                pix -= col_shift;\n              }\n            img_fvec += frame_stride;\n          }\n        retval(2) = alpha;\n        break;\n      }\n\n    default:\n      error (\"__magick_read__: unknown Magick++ image type\");\n    }\n\n  retval(0) = img;\n\n  return retval;\n}\n\n// Read a file into vector of image objects.\nvoid static\nread_file (const std::string& filename, std::vector<Magick::Image>& imvec)\n{\n  // FIXME: We need this on Windows because GraphicsMagick uses the ANSI API\n  // to open files on disc.  In contrast, the API of ImageMagick uses UTF-8\n  // encoded strings.  Should we somehow detect which is used on runtime and\n  // pass the file names accordingly? (See also bug #58493.)\n  std::string ascii_fname = sys::get_ASCII_filename (filename, true);\n\n  try\n    {\n      Magick::readImages (&imvec, ascii_fname);\n    }\n  catch (const Magick::Warning& w)\n    {\n      warning (\"Magick++ warning: %s\", w.what ());\n    }\n  catch (const Magick::Exception& e)\n    {\n      error (\"Magick++ exception: %s\", e.what ());\n    }\n}\n\nstatic void\nmaybe_initialize_magick ()\n{\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n      // Save locale as GraphicsMagick might change this (fixed in\n      // GraphicsMagick since version 1.3.13 released on December 24, 2011)\n      const char *static_locale = setlocale (LC_ALL, nullptr);\n      const std::string locale = (static_locale ? static_locale : \"\");\n\n      const std::string program_name\n        = sys::env::get_program_invocation_name ();\n      Magick::InitializeMagick (program_name.c_str ());\n\n      // Restore locale from before GraphicsMagick initialisation\n      setlocale (LC_ALL, locale.c_str ());\n\n      // Why should we give a warning?\n      // Magick does not tell us the real bitdepth of the image in file.\n      // The best we can have is the minimum between the bitdepth of the\n      // file and the quantum depth.  So we never know if the file will\n      // actually be read correctly so we warn the user that it might\n      // be limited.\n      //\n      // Why we warn if < 16 instead of < 32 ?\n      // The reasons for < 32 is simply that it's the maximum quantum\n      // depth they support.  However, very few people would actually\n      // need such support while being a major inconvenience to anyone\n      // else (8 bit images suddenly taking 4x more space will be\n      // critical for multi page images).  It would also suggests that\n      // it covers all images which does not (it still does not support\n      // float point and signed integer images).\n      // On the other hand, 16bit images are much more common.  If quantum\n      // depth is 8, there's a good chance that we will be limited.  It\n      // is also the GraphicsMagick recommended setting and the default\n      // for ImageMagick.\n      if (QuantumDepth < 16)\n        warning_with_id (\"Octave:GraphicsMagick-Quantum-Depth\",\n                         \"your version of %s limits images to %d bits per pixel\\n\",\n                         MagickPackageName, QuantumDepth);\n\n      initialized = true;\n    }\n}\n\n#endif\n\nDEFUN (__magick_read__, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{img}, @var{map}, @var{alpha}] =} __magick_read__ (@var{fname}, @var{options})\nRead image with GraphicsMagick or ImageMagick.\n\nThis is a private internal function not intended for direct use.\nUse @code{imread} instead.\n\n@seealso{imfinfo, imformats, imread, imwrite}\n@end deftypefn */)\n{\n#if defined (HAVE_MAGICK)\n\n  if (args.length () != 2 || ! args(0).is_string ())\n    print_usage ();\n\n  maybe_initialize_magick ();\n\n  const octave_scalar_map options\n    = args(1).xscalar_map_value (\"__magick_read__: OPTIONS must be a struct\");\n\n  octave_value_list output;\n\n  std::vector<Magick::Image> imvec;\n  read_file (args(0).string_value (), imvec);\n\n  // Prepare an Array with the indexes for the requested frames.\n  const octave_idx_type nFrames = imvec.size ();\n  Array<octave_idx_type> frameidx;\n  const octave_value indexes = options.getfield (\"index\");\n  if (indexes.is_string () && indexes.string_value () == \"all\")\n    {\n      frameidx.resize (dim_vector (1, nFrames));\n      for (octave_idx_type i = 0; i < nFrames; i++)\n        frameidx(i) = i;\n    }\n  else\n    {\n      frameidx = indexes.xint_vector_value (\"__magick_read__: invalid value for Index/Frame\");\n\n      // Fix indexes from base 1 to base 0, and at the same time, make\n      // sure none of the indexes is outside the range of image number.\n      const octave_idx_type n = frameidx.numel ();\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          frameidx(i)--;\n          if (frameidx(i) < 0 || frameidx(i) > nFrames - 1)\n            {\n              // We do this check inside the loop because frameidx does not\n              // need to be ordered (this is a feature and even allows for\n              // some frames to be read multiple times).\n              error (\"imread: index/frames specified are outside the number of images\");\n            }\n        }\n    }\n\n  // Check that all frames have the same size.  We don't do this at the same\n  // time we decode the image because that's done in many different places,\n  // to cover the different types of images which would lead to a lot of\n  // copy and paste.\n  {\n    const unsigned int nRows = imvec[frameidx(0)].rows ();\n    const unsigned int nCols = imvec[frameidx(0)].columns ();\n    const octave_idx_type n = frameidx.numel ();\n    for (octave_idx_type frame = 0; frame < n; frame++)\n      {\n        if (nRows != imvec[frameidx(frame)].rows ()\n            || nCols != imvec[frameidx(frame)].columns ())\n          {\n            error (\"imread: all frames must have the same size but frame \"\n                   \"%\" OCTAVE_IDX_TYPE_FORMAT \" is different\",\n                   frameidx(frame) +1);\n          }\n      }\n  }\n\n  const octave_idx_type depth = get_depth (imvec[frameidx(0)]);\n  if (is_indexed (imvec[frameidx(0)]))\n    {\n      if (depth <= 1)\n        output = read_indexed_images<boolNDArray>   (imvec, frameidx,\n                 nargout, options);\n      else if (depth <= 8)\n        output = read_indexed_images<uint8NDArray>  (imvec, frameidx,\n                 nargout, options);\n      else if (depth <= 16)\n        output = read_indexed_images<uint16NDArray> (imvec, frameidx,\n                 nargout, options);\n      else\n        error (\"imread: indexed images with depths greater than 16-bit are not supported\");\n    }\n\n  else\n    {\n      if (depth <= 1)\n        output = read_images<boolNDArray>   (imvec, frameidx, nargout, options);\n      else if (depth <= 8)\n        output = read_images<uint8NDArray>  (imvec, frameidx, nargout, options);\n      else if (depth <= 16)\n        output = read_images<uint16NDArray> (imvec, frameidx, nargout, options);\n      else if (depth <= 32)\n        output = read_images<FloatNDArray>  (imvec, frameidx, nargout, options);\n      else\n        error (\"imread: reading of images with %\" OCTAVE_IDX_TYPE_FORMAT\n               \"-bit depth is not supported\", depth);\n    }\n\n  return output;\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"imread\", \"Image IO\");\n\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\n#if defined (HAVE_MAGICK)\n\ntemplate <typename T>\nstatic uint32NDArray\nimg_float2uint (const T& img)\n{\n  typedef typename T::element_type P;\n  uint32NDArray out (img.dims ());\n\n  octave_uint32 *out_fvec = out.rwdata ();\n  const P       *img_fvec = img.data ();\n\n  const octave_uint32 max = octave_uint32::max ();\n  const octave_idx_type numel = img.numel ();\n  for (octave_idx_type idx = 0; idx < numel; idx++)\n    out_fvec[idx] = img_fvec[idx] * max;\n\n  return out;\n}\n\n// Gets the bitdepth to be used for an Octave class, i.e, returns 8 for\n// uint8, 16 for uint16, and 32 for uint32\ntemplate <typename T>\nstatic octave_idx_type\nbitdepth_from_class ()\n{\n  typedef typename T::element_type P;\n  const octave_idx_type bitdepth\n    = sizeof (P) * std::numeric_limits<unsigned char>::digits;\n  return bitdepth;\n}\n\nstatic Magick::Image\ninit_enconde_image (const octave_idx_type& nCols, const octave_idx_type& nRows,\n                    const octave_idx_type& bitdepth,\n                    const Magick::ImageType& type,\n                    const Magick::ClassType& klass)\n{\n  Magick::Image img (Magick::Geometry (nCols, nRows), \"black\");\n  // Ensure that there are no other references to this image.\n  img.modifyImage ();\n\n  img.classType (klass);\n  img.type (type);\n  // FIXME: for some reason, setting bitdepth doesn't seem to work for\n  //        indexed images.\n  img.depth (bitdepth);\n  switch (type)\n    {\n    case Magick::GrayscaleMatteType:\n    case Magick::TrueColorMatteType:\n    case Magick::ColorSeparationMatteType:\n    case Magick::PaletteMatteType:\n      img.matte (true);\n      break;\n\n    default:\n      img.matte (false);\n    }\n\n  return img;\n}\n\ntemplate <typename T>\nstatic void\nencode_indexed_images (std::vector<Magick::Image>& imvec,\n                       const T& img,\n                       const Matrix& cmap)\n{\n  typedef typename T::element_type P;\n  const octave_idx_type nFrames   = (img.ndims () < 4 ? 1 : img.dims ()(3));\n  const octave_idx_type nRows     = img.rows ();\n  const octave_idx_type nCols     = img.columns ();\n  const octave_idx_type cmap_size = cmap.rows ();\n  const octave_idx_type bitdepth  = bitdepth_from_class<T> ();\n\n  // There is no colormap object, we need to build a new one for each frame,\n  // even if it's always the same.  We can least get a vector for the Colors.\n  std::vector<Magick::ColorRGB> colormap;\n  {\n    const double *cmap_fvec = cmap.data ();\n    const octave_idx_type G_offset = cmap_size;\n    const octave_idx_type B_offset = cmap_size * 2;\n    for (octave_idx_type map_idx = 0; map_idx < cmap_size; map_idx++)\n      colormap.push_back (Magick::ColorRGB (cmap_fvec[map_idx],\n                                            cmap_fvec[map_idx + G_offset],\n                                            cmap_fvec[map_idx + B_offset]));\n  }\n\n  for (octave_idx_type frame = 0; frame < nFrames; frame++)\n    {\n      octave_quit ();\n\n      Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,\n                            Magick::PaletteType,\n                            Magick::PseudoClass);\n\n      // Insert colormap.\n      m_img.colorMapSize (cmap_size);\n      for (octave_idx_type map_idx = 0; map_idx < cmap_size; map_idx++)\n        m_img.colorMap (map_idx, colormap[map_idx]);\n\n      // Why are we also setting the pixel values instead of only the\n      // index values? We don't know if a file format supports indexed\n      // images.  If we only set the indexes and then try to save the\n      // image as JPEG for example, the indexed values get discarded,\n      // there is no conversion from the indexes, it's the initial values\n      // that get used.  An alternative would be to only set the pixel\n      // values (no indexes), then set the image as PseudoClass and GM\n      // would create a colormap for us.  However, we wouldn't have control\n      // over the order of that colormap.  And that's why we set both.\n      Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);\n      Magick::IndexPacket *ind = m_img.getIndexes ();\n      const P *img_fvec        = img.data ();\n\n      octave_idx_type GM_idx = 0;\n      for (octave_idx_type column = 0; column < nCols; column++)\n        {\n          for (octave_idx_type row = 0; row < nRows; row++)\n            {\n              ind[GM_idx] = double (*img_fvec);\n              pix[GM_idx] = m_img.colorMap (double (*img_fvec));\n              img_fvec++;\n              GM_idx += nCols;\n            }\n          GM_idx -= nCols * nRows - 1;\n        }\n\n      // Save changes to underlying image.\n      m_img.syncPixels ();\n      imvec.push_back (m_img);\n    }\n}\n\nstatic void\nencode_bool_image (std::vector<Magick::Image>& imvec, const boolNDArray& img)\n{\n  const octave_idx_type nFrames = (img.ndims () < 4 ? 1 : img.dims ()(3));\n  const octave_idx_type nRows   = img.rows ();\n  const octave_idx_type nCols   = img.columns ();\n\n  // The initialized image will be black, this is for the other pixels\n  const Magick::Color white (\"white\");\n\n  const bool *img_fvec = img.data ();\n  octave_idx_type img_idx = 0;\n  for (octave_idx_type frame = 0; frame < nFrames; frame++)\n    {\n      octave_quit ();\n\n      // For some reason, we can't set the type to Magick::BilevelType or\n      // the output image will be black, changing to white has no effect.\n      // However, this will still work fine and a binary image will be\n      // saved because we are setting the bitdepth to 1.\n      Magick::Image m_img = init_enconde_image (nCols, nRows, 1,\n                            Magick::GrayscaleType,\n                            Magick::DirectClass);\n\n      Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);\n      octave_idx_type GM_idx = 0;\n      for (octave_idx_type col = 0; col < nCols; col++)\n        {\n          for (octave_idx_type row = 0; row < nRows; row++)\n            {\n              if (img_fvec[img_idx])\n                pix[GM_idx] = white;\n\n              img_idx++;\n              GM_idx += nCols;\n            }\n          GM_idx -= nCols * nRows - 1;\n        }\n      // Save changes to underlying image.\n      m_img.syncPixels ();\n      // While we could not set it to Bilevel at the start, we can do it\n      // here otherwise some coders won't save it as binary.\n      m_img.type (Magick::BilevelType);\n      imvec.push_back (m_img);\n    }\n}\n\ntemplate <typename T>\nstatic void\nencode_uint_image (std::vector<Magick::Image>& imvec,\n                   const T& img, const T& alpha)\n{\n  typedef typename T::element_type P;\n  const octave_idx_type channels = (img.ndims () < 3 ? 1 : img.dims ()(2));\n  const octave_idx_type nFrames  = (img.ndims () < 4 ? 1 : img.dims ()(3));\n  const octave_idx_type nRows    = img.rows ();\n  const octave_idx_type nCols    = img.columns ();\n  const octave_idx_type bitdepth = bitdepth_from_class<T> ();\n\n  Magick::ImageType type;\n  const bool has_alpha = ! alpha.isempty ();\n  switch (channels)\n    {\n    case 1:\n      if (has_alpha)\n        type = Magick::GrayscaleMatteType;\n      else\n        type = Magick::GrayscaleType;\n      break;\n\n    case 3:\n      if (has_alpha)\n        type = Magick::TrueColorMatteType;\n      else\n        type = Magick::TrueColorType;\n      break;\n\n    case 4:\n      if (has_alpha)\n        type = Magick::ColorSeparationMatteType;\n      else\n        type = Magick::ColorSeparationType;\n      break;\n\n    default:\n      // __imwrite should have already filtered this cases\n      error (\"__magick_write__: wrong size on 3rd dimension\");\n    }\n\n  // We will be passing the values as integers with depth as specified\n  // by QuantumDepth (maximum value specified by MaxRGB).  This is independent\n  // of the actual depth of the image.  GM will then convert the values but\n  // while in memory, it always keeps the values as specified by QuantumDepth.\n  // From GM documentation:\n  //  Color arguments are must be scaled to fit the Quantum size according to\n  //  the range of MaxRGB\n  const double divisor = static_cast<double> ((uint64_t (1) << bitdepth) - 1)\n                         / MaxRGB;\n\n  const P *img_fvec = img.data ();\n  const P *a_fvec   = alpha.data ();\n  switch (type)\n    {\n    case Magick::GrayscaleType:\n      {\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,\n                                  type,\n                                  Magick::DirectClass);\n\n            Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);\n            octave_idx_type GM_idx = 0;\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    const double grey = math::round (double (*img_fvec) / divisor);\n                    Magick::Color c (grey, grey, grey);\n                    pix[GM_idx] = c;\n                    img_fvec++;\n                    GM_idx += nCols;\n                  }\n                GM_idx -= nCols * nRows - 1;\n              }\n            // Save changes to underlying image.\n            m_img.syncPixels ();\n            imvec.push_back (m_img);\n          }\n        break;\n      }\n\n    case Magick::GrayscaleMatteType:\n      {\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,\n                                  type,\n                                  Magick::DirectClass);\n\n            Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);\n            octave_idx_type GM_idx = 0;\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    double grey = math::round (double (*img_fvec) / divisor);\n                    Magick::Color c (grey, grey, grey,\n                                     MaxRGB - math::round (double (*a_fvec) / divisor));\n                    pix[GM_idx] = c;\n                    img_fvec++;\n                    a_fvec++;\n                    GM_idx += nCols;\n                  }\n                GM_idx -= nCols * nRows - 1;\n              }\n            // Save changes to underlying image.\n            m_img.syncPixels ();\n            imvec.push_back (m_img);\n          }\n        break;\n      }\n\n    case Magick::TrueColorType:\n      {\n        // The data offset for the green and blue channels\n        const octave_idx_type G_offset = nCols * nRows;\n        const octave_idx_type B_offset = nCols * nRows * 2;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,\n                                  type,\n                                  Magick::DirectClass);\n\n            Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);\n            octave_idx_type GM_idx = 0;\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    Magick::Color c (math::round (double (*img_fvec)          / divisor),\n                                     math::round (double (img_fvec[G_offset]) / divisor),\n                                     math::round (double (img_fvec[B_offset]) / divisor));\n                    pix[GM_idx] = c;\n                    img_fvec++;\n                    GM_idx += nCols;\n                  }\n                GM_idx -= nCols * nRows - 1;\n              }\n            // Save changes to underlying image.\n            m_img.syncPixels ();\n            imvec.push_back (m_img);\n            img_fvec += B_offset;\n          }\n        break;\n      }\n\n    case Magick::TrueColorMatteType:\n      {\n        // The data offset for the green and blue channels\n        const octave_idx_type G_offset = nCols * nRows;\n        const octave_idx_type B_offset = nCols * nRows * 2;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,\n                                  type,\n                                  Magick::DirectClass);\n\n            Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);\n            octave_idx_type GM_idx = 0;\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    Magick::Color c (math::round (double (*img_fvec)          / divisor),\n                                     math::round (double (img_fvec[G_offset]) / divisor),\n                                     math::round (double (img_fvec[B_offset]) / divisor),\n                                     MaxRGB - math::round (double (*a_fvec) / divisor));\n                    pix[GM_idx] = c;\n                    img_fvec++;\n                    a_fvec++;\n                    GM_idx += nCols;\n                  }\n                GM_idx -= nCols * nRows - 1;\n              }\n            // Save changes to underlying image.\n            m_img.syncPixels ();\n            imvec.push_back (m_img);\n            img_fvec += B_offset;\n          }\n        break;\n      }\n\n    case Magick::ColorSeparationType:\n      {\n        // The data offset for the Magenta, Yellow, and blacK channels\n        const octave_idx_type M_offset = nCols * nRows;\n        const octave_idx_type Y_offset = nCols * nRows * 2;\n        const octave_idx_type K_offset = nCols * nRows * 3;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,\n                                  type,\n                                  Magick::DirectClass);\n\n            Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);\n            octave_idx_type GM_idx = 0;\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    Magick::Color c (math::round (double (*img_fvec)          / divisor),\n                                     math::round (double (img_fvec[M_offset]) / divisor),\n                                     math::round (double (img_fvec[Y_offset]) / divisor),\n                                     math::round (double (img_fvec[K_offset]) / divisor));\n                    pix[GM_idx] = c;\n                    img_fvec++;\n                    GM_idx += nCols;\n                  }\n                GM_idx -= nCols * nRows - 1;\n              }\n            // Save changes to underlying image.\n            m_img.syncPixels ();\n            imvec.push_back (m_img);\n            img_fvec += K_offset;\n          }\n        break;\n      }\n\n    case Magick::ColorSeparationMatteType:\n      {\n        // The data offset for the Magenta, Yellow, and blacK channels\n        const octave_idx_type M_offset = nCols * nRows;\n        const octave_idx_type Y_offset = nCols * nRows * 2;\n        const octave_idx_type K_offset = nCols * nRows * 3;\n        for (octave_idx_type frame = 0; frame < nFrames; frame++)\n          {\n            octave_quit ();\n\n            Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,\n                                  type,\n                                  Magick::DirectClass);\n\n            Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);\n            Magick::IndexPacket *ind = m_img.getIndexes ();\n            octave_idx_type GM_idx = 0;\n            for (octave_idx_type col = 0; col < nCols; col++)\n              {\n                for (octave_idx_type row = 0; row < nRows; row++)\n                  {\n                    Magick::Color c (math::round (double (*img_fvec)          / divisor),\n                                     math::round (double (img_fvec[M_offset]) / divisor),\n                                     math::round (double (img_fvec[Y_offset]) / divisor),\n                                     math::round (double (img_fvec[K_offset]) / divisor));\n                    pix[GM_idx] = c;\n                    ind[GM_idx] = MaxRGB - math::round (double (*a_fvec) / divisor);\n                    img_fvec++;\n                    a_fvec++;\n                    GM_idx += nCols;\n                  }\n                GM_idx -= nCols * nRows - 1;\n              }\n            // Save changes to underlying image.\n            m_img.syncPixels ();\n            imvec.push_back (m_img);\n            img_fvec += K_offset;\n          }\n        break;\n      }\n\n    default:\n      error (\"__magick_write__: unrecognized Magick::ImageType\");\n    }\n\n  return;\n}\n\n// Meant to be shared with both imfinfo and imwrite.\nstatic std::map<octave_idx_type, std::string>\ninit_disposal_methods ()\n{\n  //  GIF Specifications:\n  //\n  // Disposal Method - Indicates the way in which the graphic is to\n  //                    be treated after being displayed.\n  //\n  //  0 -   No disposal specified.  The decoder is\n  //        not required to take any action.\n  //  1 -   Do not dispose.  The graphic is to be left\n  //        in place.\n  //  2 -   Restore to background color.  The area used by the\n  //        graphic must be restored to the background color.\n  //  3 -   Restore to previous.  The decoder is required to\n  //        restore the area overwritten by the graphic with\n  //        what was there prior to rendering the graphic.\n  //  4-7 - To be defined.\n  static std::map<octave_idx_type, std::string> methods;\n  if (methods.empty ())\n    {\n      methods[0] = \"doNotSpecify\";\n      methods[1] = \"leaveInPlace\";\n      methods[2] = \"restoreBG\";\n      methods[3] = \"restorePrevious\";\n    }\n  return methods;\n}\nstatic std::map<std::string, octave_idx_type>\ninit_reverse_disposal_methods ()\n{\n  static std::map<std::string, octave_idx_type> methods;\n  if (methods.empty ())\n    {\n      methods[\"donotspecify\"]     = 0;\n      methods[\"leaveinplace\"]     = 1;\n      methods[\"restorebg\"]        = 2;\n      methods[\"restoreprevious\"]  = 3;\n    }\n  return methods;\n}\n\nvoid static\nwrite_file (const std::string& filename,\n            const std::string& ext,\n            std::vector<Magick::Image>& imvec)\n{\n  try\n    {\n      Magick::writeImages (imvec.begin (), imvec.end (), ext + ':' + filename);\n    }\n  catch (const Magick::Warning& w)\n    {\n      warning (\"Magick++ warning: %s\", w.what ());\n    }\n  catch (const Magick::ErrorCoder& e)\n    {\n      warning (\"Magick++ coder error: %s\", e.what ());\n    }\n  catch (const Magick::Exception& e)\n    {\n      error (\"Magick++ exception: %s\", e.what ());\n    }\n}\n\n#endif\n\nDEFUN (__magick_write__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {} __magick_write__ (@var{fname}, @var{fmt}, @var{img}, @var{map}, @var{options})\nWrite image with GraphicsMagick or ImageMagick.\n\nThis is a private internal function not intended for direct use.\nUse @code{imwrite} instead.\n\n@seealso{imfinfo, imformats, imread, imwrite}\n@end deftypefn */)\n{\n#if defined (HAVE_MAGICK)\n\n  if (args.length () != 5 || ! args(0).is_string () || ! args(1).is_string ())\n    print_usage ();\n\n  maybe_initialize_magick ();\n\n  const std::string filename = args(0).string_value ();\n  const std::string ext = args(1).string_value ();\n\n  const octave_scalar_map options\n    = args(4).xscalar_map_value (\"__magick_write__: OPTIONS must be a struct\");\n\n  const octave_value img = args(2);\n  const Matrix cmap = args(3).xmatrix_value (\"__magick_write__: invalid MAP\");\n\n  std::vector<Magick::Image> imvec;\n\n  if (cmap.isempty ())\n    {\n      const octave_value alpha = options.getfield (\"alpha\");\n      if (img.islogical ())\n        encode_bool_image (imvec, img.bool_array_value ());\n      else if (img.is_uint8_type ())\n        encode_uint_image<uint8NDArray>  (imvec, img.uint8_array_value (),\n                                          alpha.uint8_array_value ());\n      else if (img.is_uint16_type ())\n        encode_uint_image<uint16NDArray> (imvec, img.uint16_array_value (),\n                                          alpha.uint16_array_value ());\n      else if (img.is_uint32_type ())\n        encode_uint_image<uint32NDArray> (imvec, img.uint32_array_value (),\n                                          alpha.uint32_array_value ());\n      else if (img.isfloat ())\n        {\n          // For image formats that support floating point values, we write\n          // the actual values.  For those who don't, we only use the values\n          // on the range [0 1] and save integer values.\n          // But here, even for formats that would support floating point\n          // values, GM seems unable to do that so we at least make them uint32.\n          uint32NDArray clip_img;\n          uint32NDArray clip_alpha;\n          if (img.is_single_type ())\n            {\n              clip_img   = img_float2uint<FloatNDArray>\n                           (img.float_array_value ());\n              clip_alpha = img_float2uint<FloatNDArray>\n                           (alpha.float_array_value ());\n            }\n          else\n            {\n              clip_img   = img_float2uint<NDArray> (img.array_value ());\n              clip_alpha = img_float2uint<NDArray> (alpha.array_value ());\n            }\n          encode_uint_image<uint32NDArray> (imvec, clip_img, clip_alpha);\n        }\n      else\n        error (\"__magick_write__: image type not supported\");\n    }\n  else\n    {\n      // We should not get floating point indexed images here because we\n      // converted them in __imwrite__.m.  We should probably do it here\n      // but it would look much messier.\n      if (img.is_uint8_type ())\n        encode_indexed_images<uint8NDArray>  (imvec, img.uint8_array_value (),\n                                              cmap);\n      else if (img.is_uint16_type ())\n        encode_indexed_images<uint16NDArray> (imvec, img.uint16_array_value (),\n                                              cmap);\n      else\n        error (\"__magick_write__: indexed image must be uint8, uint16 or float\");\n    }\n  static std::map<std::string, octave_idx_type> disposal_methods\n    = init_reverse_disposal_methods ();\n\n  const octave_idx_type nFrames = imvec.size ();\n\n  const octave_idx_type quality = options.getfield (\"quality\").int_value ();\n  const ColumnVector delaytime\n    = options.getfield (\"delaytime\").column_vector_value ();\n  const Array<std::string> disposalmethod\n    = options.getfield (\"disposalmethod\").cellstr_value ();\n  for (octave_idx_type i = 0; i < nFrames; i++)\n    {\n      imvec[i].quality (quality);\n      imvec[i].animationDelay (delaytime(i));\n      imvec[i].gifDisposeMethod (disposal_methods[disposalmethod(i)]);\n    }\n\n  // If writemode is set to append, read the image and append to it.  Even\n  // if set to append, make sure that something was read at all.\n  const std::string writemode = options.getfield (\"writemode\").string_value ();\n  if (writemode == \"append\" && sys::file_exists (filename))\n    {\n      std::vector<Magick::Image> ini_imvec;\n      read_file (filename, ini_imvec);\n\n      if (ini_imvec.size () > 0)\n        {\n          ini_imvec.insert (ini_imvec.end (), imvec.begin (), imvec.end ());\n          ini_imvec.swap (imvec);\n        }\n    }\n\n  // FIXME: LoopCount or animationIterations\n  //  How it should work:\n  //\n  // This value is only set for the first image in the sequence.  Trying\n  // to set this value with the append mode should have no effect, the\n  // value used with the first image is the one that counts (that would\n  // also be Matlab compatible).  Thus, the right way to do this would be\n  // to have an else block on the condition above, and set this only\n  // when creating a new file.  Since Matlab does not interpret a 4-D\n  // matrix as sequence of images to write, its users need to use a for\n  // loop and set LoopCount only on the first iteration (it actually\n  // throws warnings otherwise)\n  //\n  //  Why is this not done the right way:\n  //\n  // When GM saves a single image, it discards the value if there is only\n  // a single image and sets it to \"no loop\".  Since our default is an\n  // infinite loop, if the user tries to do it the Matlab way (setting\n  // LoopCount only on the first image) that value will go nowhere.\n  // See https://sourceforge.net/p/graphicsmagick/bugs/248/\n  // Because of this, we document to set LoopCount on every iteration\n  // (in Matlab will cause a lot of warnings), or pass a 4-D matrix with\n  // all frames (won't work in Matlab at all).\n  // Note that this only needs to be set on the first frame\n  imvec[0].animationIterations (options.getfield (\"loopcount\").uint_value ());\n\n  const std::string compression\n    = options.getfield (\"compression\").string_value ();\n\n#define COMPRESS_MAGICK_IMAGE_VECTOR(GM_TYPE)                           \\\n  for (std::vector<Magick::Image>::size_type i = 0; i < imvec.size (); i++) \\\n    imvec[i].compressType (GM_TYPE)\n\n  if (compression == \"none\")\n    COMPRESS_MAGICK_IMAGE_VECTOR (Magick::NoCompression);\n  else if (compression == \"bzip\")\n    COMPRESS_MAGICK_IMAGE_VECTOR (Magick::BZipCompression);\n  else if (compression == \"fax3\")\n    COMPRESS_MAGICK_IMAGE_VECTOR (Magick::FaxCompression);\n  else if (compression == \"fax4\")\n    COMPRESS_MAGICK_IMAGE_VECTOR (Magick::Group4Compression);\n  else if (compression == \"jpeg\")\n    COMPRESS_MAGICK_IMAGE_VECTOR (Magick::JPEGCompression);\n  else if (compression == \"lzw\")\n    COMPRESS_MAGICK_IMAGE_VECTOR (Magick::LZWCompression);\n  else if (compression == \"rle\")\n    COMPRESS_MAGICK_IMAGE_VECTOR (Magick::RLECompression);\n  else if (compression == \"deflate\")\n    COMPRESS_MAGICK_IMAGE_VECTOR (Magick::ZipCompression);\n\n#undef COMPRESS_MAGICK_IMAGE_VECTOR\n\n  write_file (filename, ext, imvec);\n\n  return ovl ();\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"imwrite\", \"Image IO\");\n\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\n// Gets the minimum information from images such as its size and format.  Much\n// faster than using imfinfo, which slows down a lot since.  Note than without\n// this, we need to read the image once for imfinfo to set defaults (which is\n// done in Octave language), and then again for the actual reading.\nDEFUN (__magick_ping__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fmt} =} __magick_ping__ (@var{fname}, @var{idx})\nPing image information with GraphicsMagick or ImageMagick.\n\nThis is a private internal function not intended for direct use.\n\n@seealso{imfinfo}\n@end deftypefn */)\n{\n#if defined (HAVE_MAGICK)\n\n  if (args.length () < 1 || ! args(0).is_string ())\n    print_usage ();\n\n  maybe_initialize_magick ();\n\n  const std::string filename = args(0).string_value ();\n\n  int idx;\n  if (args.length () > 1)\n    idx = args(1).int_value () -1;\n  else\n    idx = 0;\n\n  Magick::Image img;\n  img.subImage (idx); // start ping from this image (in case of multi-page)\n  img.subRange (1);   // ping only one of them\n\n  // FIXME: We need this on Windows because GraphicsMagick uses the ANSI API\n  // to open files on disc.  In contrast, the API of ImageMagick uses UTF-8\n  // encoded strings.  Should we somehow detect which is used on runtime and\n  // pass the file names accordingly? (See also bug #58493.)\n  std::string ascii_fname = sys::get_ASCII_filename (filename, true);\n\n  try\n    {\n      img.ping (ascii_fname);\n    }\n  catch (const Magick::Warning& w)\n    {\n      warning (\"Magick++ warning: %s\", w.what ());\n    }\n  catch (const Magick::Exception& e)\n    {\n      error (\"Magick++ exception: %s\", e.what ());\n    }\n\n  static const char *fields[] = {\"rows\", \"columns\", \"format\", nullptr};\n  octave_scalar_map ping = octave_scalar_map (string_vector (fields));\n  ping.setfield (\"rows\",    octave_value (img.rows ()));\n  ping.setfield (\"columns\", octave_value (img.columns ()));\n  ping.setfield (\"format\",  octave_value (img.magick ()));\n\n  return ovl (ping);\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"imfinfo\", \"Image IO\");\n\n#endif\n}\n\n#if defined (HAVE_MAGICK)\n\nstatic octave_value\nmagick_to_octave_value (const Magick::CompressionType& magick)\n{\n  switch (magick)\n    {\n    case Magick::NoCompression:\n      return octave_value (\"none\");\n    case Magick::BZipCompression:\n      return octave_value (\"bzip\");\n    case Magick::FaxCompression:\n      return octave_value (\"fax3\");\n    case Magick::Group4Compression:\n      return octave_value (\"fax4\");\n    case Magick::JPEGCompression:\n      return octave_value (\"jpeg\");\n    case Magick::LZWCompression:\n      return octave_value (\"lzw\");\n    case Magick::RLECompression:\n      // This is named \"rle\" for the HDF, but the same thing is named\n      // \"ccitt\" and \"PackBits\" for binary and non-binary images in TIFF.\n      return octave_value (\"rle\");\n    case Magick::ZipCompression:\n      return octave_value (\"deflate\");\n\n    // The following are present only in recent versions of GraphicsMagick.\n    // At the moment the only use of this would be to have imfinfo report\n    // the compression method.  In the future, someone could implement\n    // the Compression option for imwrite in which case a macro in\n    // configure.ac will have to check for their presence of this.\n    // See bug #39913\n    //      case Magick::LZMACompression:\n    //        return octave_value (\"lzma\");\n    //      case Magick::JPEG2000Compression:\n    //        return octave_value (\"jpeg2000\");\n    //      case Magick::JBIG1Compression:\n    //        return octave_value (\"jbig1\");\n    //      case Magick::JBIG2Compression:\n    //        return octave_value (\"jbig2\");\n\n    default:\n      return octave_value (\"undefined\");\n    }\n}\n\nstatic octave_value\nmagick_to_octave_value (const Magick::EndianType& magick)\n{\n  switch (magick)\n    {\n    case Magick::LSBEndian:\n      return octave_value (\"little-endian\");\n    case Magick::MSBEndian:\n      return octave_value (\"big-endian\");\n    default:\n      return octave_value (\"undefined\");\n    }\n}\n\nstatic octave_value\nmagick_to_octave_value (const Magick::OrientationType& magick)\n{\n  switch (magick)\n    {\n    // Values come from the TIFF6 spec\n    case Magick::TopLeftOrientation:\n      return octave_value (1);\n    case Magick::TopRightOrientation:\n      return octave_value (2);\n    case Magick::BottomRightOrientation:\n      return octave_value (3);\n    case Magick::BottomLeftOrientation:\n      return octave_value (4);\n    case Magick::LeftTopOrientation:\n      return octave_value (5);\n    case Magick::RightTopOrientation:\n      return octave_value (6);\n    case Magick::RightBottomOrientation:\n      return octave_value (7);\n    case Magick::LeftBottomOrientation:\n      return octave_value (8);\n    default:\n      return octave_value (1);\n    }\n}\n\nstatic octave_value\nmagick_to_octave_value (const Magick::ResolutionType& magick)\n{\n  switch (magick)\n    {\n    case Magick::PixelsPerInchResolution:\n      return octave_value (\"Inch\");\n    case Magick::PixelsPerCentimeterResolution:\n      return octave_value (\"Centimeter\");\n    default:\n      return octave_value (\"undefined\");\n    }\n}\n\nstatic bool\nis_valid_exif (const std::string& val)\n{\n  // Sometimes GM will return the string \"unknown\" instead of empty\n  // for an empty value.\n  return (! val.empty () && val != \"unknown\");\n}\n\nstatic void\nfill_exif (octave_scalar_map& map, Magick::Image& img,\n           const std::string& key)\n{\n  const std::string attr = img.attribute (\"EXIF:\" + key);\n  if (is_valid_exif (attr))\n    map.setfield (key, octave_value (attr));\n  return;\n}\n\nstatic void\nfill_exif_ints (octave_scalar_map& map, Magick::Image& img,\n                const std::string& key)\n{\n  const std::string attr = img.attribute (\"EXIF:\" + key);\n  if (is_valid_exif (attr))\n    {\n      // string of the type \"float,float,float.....\"\n      float number;\n      ColumnVector values (std::count (attr.begin (), attr.end (), ',') +1);\n      std::string sub;\n      std::istringstream sstream (attr);\n      octave_idx_type n = 0;\n      while (std::getline (sstream, sub, char (',')))\n        {\n          if (sscanf (sub.c_str (), \"%f\", &number) != 1)\n            error (\"fill_exif_ints: failed to read EXIF value as float\");\n\n          values(n++) = number;\n        }\n      map.setfield (key, octave_value (values));\n    }\n  return;\n}\n\nstatic void\nfill_exif_floats (octave_scalar_map& map, Magick::Image& img,\n                  const std::string& key)\n{\n  const std::string attr = img.attribute (\"EXIF:\" + key);\n  if (is_valid_exif (attr))\n    {\n      // string of the type \"int/int,int/int,int/int.....\"\n      int numerator;\n      int denominator;\n      ColumnVector values (std::count (attr.begin (), attr.end (), ',') +1);\n      std::string sub;\n      std::istringstream sstream (attr);\n      octave_idx_type n = 0;\n      while (std::getline (sstream, sub, ','))\n        {\n          if (sscanf (sub.c_str (), \"%i/%i\", &numerator, &denominator) != 2)\n            error (\"fill_exif_floats: failed to read EXIF numerator/demoninator pair\");\n\n          values(n++) = double (numerator) / double (denominator);\n        }\n      map.setfield (key, octave_value (values));\n    }\n  return;\n}\n\n#endif\n\nDEFUN (__magick_finfo__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{infostruct} =} __magick_finfo__ (@var{fname})\nRead image information with GraphicsMagick or ImageMagick.\n\nThis is a private internal function not intended for direct use.\nUse @code{imfinfo} instead.\n\n@seealso{imfinfo, imformats, imread, imwrite}\n@end deftypefn */)\n{\n#if defined (HAVE_MAGICK)\n\n  if (args.length () < 1 || ! args(0).is_string ())\n    print_usage ();\n\n  maybe_initialize_magick ();\n\n  const std::string filename = args(0).string_value ();\n\n  std::vector<Magick::Image> imvec;\n  read_file (filename, imvec);\n\n  const octave_idx_type nFrames = imvec.size ();\n  const std::string format = imvec[0].magick ();\n\n  // Here's how this function works.  We need to return a struct array, one\n  // struct for each image in the file (remember, there are image\n  // that allow for multiple images in the same file).  Now, Matlab seems\n  // to have format specific code so the fields on the struct are different\n  // for each format.  It only has a small subset that is common to all\n  // of them, the others are undocumented.  Because we try to abstract from\n  // the formats we always return the same list of fields (note that with\n  // GM we support more than 88 formats.  That's way more than Matlab, and\n  // I don't want to write specific code for each of them).\n  //\n  // So what we do is we create an octave_scalar_map, fill it with the\n  // information for that image, and then insert it into an octave_map.\n  // Because in the same file, different images may have values for\n  // different fields, we can't create a field only if there's a value.\n  // Bad things happen if we merge octave_scalar_maps with different\n  // fields from the others (suppose for example a TIFF file with 4 images,\n  // where only the third image has a colormap.\n\n  static const char *fields[] =\n  {\n    // These are fields that must always appear for Matlab.\n    \"Filename\",\n    \"FileModDate\",\n    \"FileSize\",\n    \"Format\",\n    \"FormatVersion\",\n    \"Width\",\n    \"Height\",\n    \"BitDepth\",\n    \"ColorType\",\n\n    // These are format specific or not existent in Matlab.  The most\n    // annoying thing is that Matlab may have different names for the\n    // same thing in different formats.\n    \"DelayTime\",\n    \"DisposalMethod\",\n    \"LoopCount\",\n    \"ByteOrder\",\n    \"Gamma\",\n    \"Chromaticities\",\n    \"Comment\",\n    \"Quality\",\n    \"Compression\",        // same as CompressionType\n    \"Colormap\",           // same as ColorTable (in PNG)\n    \"Orientation\",\n    \"ResolutionUnit\",\n    \"XResolution\",\n    \"YResolution\",\n    \"Software\",           // sometimes is an Exif tag\n    \"Make\",               // actually an Exif tag\n    \"Model\",              // actually an Exif tag\n    \"DateTime\",           // actually an Exif tag\n    \"ImageDescription\",   // actually an Exif tag\n    \"Artist\",             // actually an Exif tag\n    \"Copyright\",          // actually an Exif tag\n    \"DigitalCamera\",\n    \"GPSInfo\",\n    // Notes for the future: GM allows one to get many attributes, and even has\n    // attribute() to obtain arbitrary ones, that may exist in only some\n    // cases.  The following is a list of some methods and into what possible\n    // Matlab compatible values they may be converted.\n    //\n    //  colorSpace()      -> PhotometricInterpretation\n    //  backgroundColor() -> BackgroundColor\n    //  interlaceType()   -> Interlaced, InterlaceType, and PlanarConfiguration\n    //  label()           -> Title\n    nullptr\n  };\n\n  // The one we will return at the end\n  octave_map info (dim_vector (nFrames, 1), string_vector (fields));\n\n  // Some of the fields in the struct are about file information and will be\n  // the same for all images in the file.  So we create a template, fill in\n  // those values, and make a copy of the template for each image.\n  octave_scalar_map template_info = (string_vector (fields));\n\n  template_info.setfield (\"Format\", octave_value (format));\n  // We can't actually get FormatVersion but even Matlab sometimes can't.\n  template_info.setfield (\"FormatVersion\", octave_value (\"\"));\n\n  const sys::file_stat fs (filename);\n  if (! fs)\n    error (\"imfinfo: error reading '%s': %s\", filename.c_str (),\n           fs.error ().c_str ());\n\n  const sys::localtime mtime (fs.mtime ());\n  const std::string filetime = mtime.strftime (\"%e-%b-%Y %H:%M:%S\");\n  template_info.setfield (\"Filename\",    octave_value (filename));\n  template_info.setfield (\"FileModDate\", octave_value (filetime));\n  template_info.setfield (\"FileSize\",    octave_value (fs.size ()));\n\n  for (octave_idx_type frame = 0; frame < nFrames; frame++)\n    {\n      octave_quit ();\n\n      octave_scalar_map info_frame (template_info);\n      const Magick::Image img = imvec[frame];\n\n      info_frame.setfield (\"Width\",  octave_value (img.columns ()));\n      info_frame.setfield (\"Height\", octave_value (img.rows ()));\n      info_frame.setfield (\"BitDepth\",\n                           octave_value (get_depth (const_cast<Magick::Image&> (img))));\n\n      // Stuff related to colormap, image class and type\n      // Because GM is too smart for us...  Read the comments in is_indexed()\n      {\n        std::string color_type;\n        Matrix cmap;\n        if (is_indexed (img))\n          {\n            color_type = \"indexed\";\n            cmap = read_maps (const_cast<Magick::Image&> (img))(0).matrix_value ();\n          }\n        else\n          {\n            switch (img.type ())\n              {\n              case Magick::BilevelType:\n              case Magick::GrayscaleType:\n              case Magick::GrayscaleMatteType:\n                color_type = \"grayscale\";\n                break;\n\n              case Magick::TrueColorType:\n              case Magick::TrueColorMatteType:\n                color_type = \"truecolor\";\n                break;\n\n              case Magick::PaletteType:\n              case Magick::PaletteMatteType:\n                // we should never get here or is_indexed needs to be fixed\n                color_type = \"indexed\";\n                break;\n\n              case Magick::ColorSeparationType:\n              case Magick::ColorSeparationMatteType:\n                color_type = \"CMYK\";\n                break;\n\n              default:\n                color_type = \"undefined\";\n              }\n          }\n        info_frame.setfield (\"ColorType\", octave_value (color_type));\n        info_frame.setfield (\"Colormap\",  octave_value (cmap));\n      }\n\n      {\n        // Not all images have chroma values.  In such cases, they'll\n        // be all zeros.  So rather than send a matrix of zeros, we will\n        // check for that, and send an empty vector instead.\n        RowVector chromaticities (8);\n        double *chroma_fvec = chromaticities.rwdata ();\n        img.chromaWhitePoint    (&chroma_fvec[0], &chroma_fvec[1]);\n        img.chromaRedPrimary    (&chroma_fvec[2], &chroma_fvec[3]);\n        img.chromaGreenPrimary  (&chroma_fvec[4], &chroma_fvec[5]);\n        img.chromaBluePrimary   (&chroma_fvec[6], &chroma_fvec[7]);\n        if (chromaticities.nnz () == 0)\n          chromaticities = RowVector (0);\n        info_frame.setfield (\"Chromaticities\", octave_value (chromaticities));\n      }\n\n      info_frame.setfield (\"Gamma\",       octave_value (img.gamma ()));\n      info_frame.setfield (\"XResolution\", octave_value (img.xResolution ()));\n      info_frame.setfield (\"YResolution\", octave_value (img.yResolution ()));\n      info_frame.setfield (\"DelayTime\",   octave_value (img.animationDelay ()));\n      info_frame.setfield (\"LoopCount\",\n                           octave_value (img.animationIterations ()));\n      info_frame.setfield (\"Quality\",     octave_value (img.quality ()));\n      info_frame.setfield (\"Comment\",     octave_value (img.comment ()));\n\n      info_frame.setfield (\"Compression\",\n                           magick_to_octave_value (img.compressType ()));\n      info_frame.setfield (\"Orientation\",\n                           magick_to_octave_value (img.orientation ()));\n      info_frame.setfield (\"ResolutionUnit\",\n                           magick_to_octave_value (img.resolutionUnits ()));\n      info_frame.setfield (\"ByteOrder\",\n                           magick_to_octave_value (img.endian ()));\n\n      // It is not possible to know if there's an Exif field so we just\n      // check for the Exif Version value.  If it does exists, then we\n      // bother about looking for specific fields.\n      {\n        Magick::Image& cimg = const_cast<Magick::Image&> (img);\n\n        // These will be in Exif tags but must appear as fields in the\n        // base struct array, not as another struct in one of its fields.\n        // This is likely because they belong to the Baseline TIFF specs\n        // and may appear out of the Exif tag.  So first we check if it\n        // exists outside the Exif tag.\n        // See Section 4.6.4, table 4, page 28 of Exif specs version 2.3\n        // (CIPA DC- 008-Translation- 2010)\n        static const char *base_exif_str_fields[] =\n        {\n          \"DateTime\",\n          \"ImageDescription\",\n          \"Make\",\n          \"Model\",\n          \"Software\",\n          \"Artist\",\n          \"Copyright\",\n          nullptr,\n        };\n        static const string_vector base_exif_str (base_exif_str_fields);\n        static const octave_idx_type n_base_exif_str = base_exif_str.numel ();\n        for (octave_idx_type field = 0; field < n_base_exif_str; field++)\n          {\n            info_frame.setfield (base_exif_str[field],\n                                 octave_value (cimg.attribute (base_exif_str[field])));\n            fill_exif (info_frame, cimg, base_exif_str[field]);\n          }\n\n        octave_scalar_map camera;\n        octave_scalar_map gps;\n        if (! cimg.attribute (\"EXIF:ExifVersion\").empty ())\n          {\n            // See Section 4.6.5, table 7 and 8, over pages page 42 to 43\n            // of Exif specs version 2.3 (CIPA DC- 008-Translation- 2010)\n\n            // Listed on the Exif specs as being of type ASCII.\n            static const char *exif_str_fields[] =\n            {\n              \"RelatedSoundFile\",\n              \"DateTimeOriginal\",\n              \"DateTimeDigitized\",\n              \"SubSecTime\",\n              \"DateTimeOriginal\",\n              \"SubSecTimeOriginal\",\n              \"SubSecTimeDigitized\",\n              \"ImageUniqueID\",\n              \"CameraOwnerName\",\n              \"BodySerialNumber\",\n              \"LensMake\",\n              \"LensModel\",\n              \"LensSerialNumber\",\n              \"SpectralSensitivity\",\n              // These last two are of type undefined but most likely will\n              // be strings.  Even if they're not GM returns a string anyway.\n              \"UserComment\",\n              \"MakerComment\",\n              nullptr\n            };\n            static const string_vector exif_str (exif_str_fields);\n            static const octave_idx_type n_exif_str = exif_str.numel ();\n            for (octave_idx_type field = 0; field < n_exif_str; field++)\n              fill_exif (camera, cimg, exif_str[field]);\n\n            // Listed on the Exif specs as being of type SHORT or LONG.\n            static const char *exif_int_fields[] =\n            {\n              \"ColorSpace\",\n              \"ExifImageWidth\",  // PixelXDimension (CPixelXDimension in Matlab)\n              \"ExifImageHeight\", // PixelYDimension (CPixelYDimension in Matlab)\n              \"PhotographicSensitivity\",\n              \"StandardOutputSensitivity\",\n              \"RecommendedExposureIndex\",\n              \"ISOSpeed\",\n              \"ISOSpeedLatitudeyyy\",\n              \"ISOSpeedLatitudezzz\",\n              \"FocalPlaneResolutionUnit\",\n              \"FocalLengthIn35mmFilm\",\n              // Listed as SHORT or LONG but with more than 1 count.\n              \"SubjectArea\",\n              \"SubjectLocation\",\n              // While the following are an integer, their value have a meaning\n              // that must be represented as a string for Matlab compatibility.\n              // For example, a 3 on ExposureProgram, would return\n              // \"Aperture priority\" as defined on the Exif specs.\n              \"ExposureProgram\",\n              \"SensitivityType\",\n              \"MeteringMode\",\n              \"LightSource\",\n              \"Flash\",\n              \"SensingMethod\",\n              \"FileSource\",\n              \"CustomRendered\",\n              \"ExposureMode\",\n              \"WhiteBalance\",\n              \"SceneCaptureType\",\n              \"GainControl\",\n              \"Contrast\",\n              \"Saturation\",\n              \"Sharpness\",\n              \"SubjectDistanceRange\",\n              nullptr\n            };\n            static const string_vector exif_int (exif_int_fields);\n            static const octave_idx_type n_exif_int = exif_int.numel ();\n            for (octave_idx_type field = 0; field < n_exif_int; field++)\n              fill_exif_ints (camera, cimg, exif_int[field]);\n\n            // Listed as RATIONAL or SRATIONAL\n            static const char *exif_float_fields[] =\n            {\n              \"Gamma\",\n              \"CompressedBitsPerPixel\",\n              \"ExposureTime\",\n              \"FNumber\",\n              \"ShutterSpeedValue\",  // SRATIONAL\n              \"ApertureValue\",\n              \"BrightnessValue\",    // SRATIONAL\n              \"ExposureBiasValue\",  // SRATIONAL\n              \"MaxApertureValue\",\n              \"SubjectDistance\",\n              \"FocalLength\",\n              \"FlashEnergy\",\n              \"FocalPlaneXResolution\",\n              \"FocalPlaneYResolution\",\n              \"ExposureIndex\",\n              \"DigitalZoomRatio\",\n              // Listed as RATIONAL or SRATIONAL with more than 1 count.\n              \"LensSpecification\",\n              nullptr\n            };\n            static const string_vector exif_float (exif_float_fields);\n            static const octave_idx_type n_exif_float = exif_float.numel ();\n            for (octave_idx_type field = 0; field < n_exif_float; field++)\n              fill_exif_floats (camera, cimg, exif_float[field]);\n\n            // Inside a Exif field, it is possible that there is also a\n            // GPS field.  This is not the same as ExifVersion but seems\n            // to be how we have to check for it.\n            if (cimg.attribute (\"EXIF:GPSInfo\") != \"unknown\")\n              {\n                // The story here is the same as with Exif.\n                // See Section 4.6.6, table 15 on page 68 of Exif specs\n                // version 2.3 (CIPA DC- 008-Translation- 2010)\n\n                static const char *gps_str_fields[] =\n                {\n                  \"GPSLatitudeRef\",\n                  \"GPSLongitudeRef\",\n                  \"GPSAltitudeRef\",\n                  \"GPSSatellites\",\n                  \"GPSStatus\",\n                  \"GPSMeasureMode\",\n                  \"GPSSpeedRef\",\n                  \"GPSTrackRef\",\n                  \"GPSImgDirectionRef\",\n                  \"GPSMapDatum\",\n                  \"GPSDestLatitudeRef\",\n                  \"GPSDestLongitudeRef\",\n                  \"GPSDestBearingRef\",\n                  \"GPSDestDistanceRef\",\n                  \"GPSDateStamp\",\n                  nullptr\n                };\n                static const string_vector gps_str (gps_str_fields);\n                static const octave_idx_type n_gps_str = gps_str.numel ();\n                for (octave_idx_type field = 0; field < n_gps_str; field++)\n                  fill_exif (gps, cimg, gps_str[field]);\n\n                static const char *gps_int_fields[] =\n                {\n                  \"GPSDifferential\",\n                  nullptr\n                };\n                static const string_vector gps_int (gps_int_fields);\n                static const octave_idx_type n_gps_int = gps_int.numel ();\n                for (octave_idx_type field = 0; field < n_gps_int; field++)\n                  fill_exif_ints (gps, cimg, gps_int[field]);\n\n                static const char *gps_float_fields[] =\n                {\n                  \"GPSAltitude\",\n                  \"GPSDOP\",\n                  \"GPSSpeed\",\n                  \"GPSTrack\",\n                  \"GPSImgDirection\",\n                  \"GPSDestBearing\",\n                  \"GPSDestDistance\",\n                  \"GPSHPositioningError\",\n                  // Listed as RATIONAL or SRATIONAL with more than 1 count.\n                  \"GPSLatitude\",\n                  \"GPSLongitude\",\n                  \"GPSTimeStamp\",\n                  \"GPSDestLatitude\",\n                  \"GPSDestLongitude\",\n                  nullptr\n                };\n                static const string_vector gps_float (gps_float_fields);\n                static const octave_idx_type n_gps_float = gps_float.numel ();\n                for (octave_idx_type field = 0; field < n_gps_float; field++)\n                  fill_exif_floats (gps, cimg, gps_float[field]);\n\n              }\n          }\n        info_frame.setfield (\"DigitalCamera\", octave_value (camera));\n        info_frame.setfield (\"GPSInfo\",       octave_value (gps));\n      }\n\n      info.fast_elem_insert (frame, info_frame);\n    }\n\n  if (format == \"GIF\")\n    {\n      static std::map<octave_idx_type, std::string> disposal_methods\n        = init_disposal_methods ();\n      string_vector methods (nFrames);\n      for (octave_idx_type frame = 0; frame < nFrames; frame++)\n        methods[frame] = disposal_methods[imvec[frame].gifDisposeMethod ()];\n      info.setfield (\"DisposalMethod\", Cell (methods));\n    }\n  else\n    info.setfield (\"DisposalMethod\",\n                   Cell (dim_vector (nFrames, 1), octave_value (\"\")));\n\n  return ovl (info);\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"imfinfo\", \"Image IO\");\n\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nDEFUN (__magick_formats__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fmt_struct} =} __magick_imformats__ (@var{formats})\nFill formats info with GraphicsMagick CoderInfo.\n\n@seealso{imfinfo, imformats, imread, imwrite}\n@end deftypefn */)\n{\n  if (args.length () != 1 || ! args(0).isstruct ())\n    print_usage ();\n\n  octave_map formats = args(0).map_value ();\n\n#if defined (HAVE_MAGICK)\n\n  maybe_initialize_magick ();\n\n  for (octave_idx_type idx = 0; idx < formats.numel (); idx++)\n    {\n      try\n        {\n          octave_scalar_map fmt = formats.checkelem (idx);\n          Magick::CoderInfo coder (fmt.getfield (\"coder\").string_value ());\n\n          fmt.setfield (\"description\", octave_value (coder.description ()));\n          fmt.setfield (\"multipage\", coder.isMultiFrame () ? true : false);\n          // default for read and write is a function handle.  If we can't\n          // read or write them, them set it to an empty value\n          if (! coder.isReadable ())\n            fmt.setfield (\"read\",  Matrix ());\n          if (! coder.isWritable ())\n            fmt.setfield (\"write\", Matrix ());\n          formats.fast_elem_insert (idx, fmt);\n        }\n      catch (const Magick::Exception&)\n        {\n          // Exception here are missing formats.  So we remove the format\n          // from the structure and reduce idx.\n          formats.delete_elements (idx);\n          idx--;\n        }\n    }\n\n#else\n\n  formats = octave_map (dim_vector (1, 0), formats.fieldnames ());\n\n#endif\n\n  return ovl (formats);\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/auto-shlib.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2022-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"octave-config.h\"\n\n#include \"auto-shlib.h\"\n#include \"defun-int.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nauto_shlib::auto_shlib ()\n  : dynamic_library (get_current_shlib ())\n{ }\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/auto-shlib.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2022-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_auto_shlib_h)\n#define octave_auto_shlib_h 1\n\n#include \"octave-config.h\"\n\n#include \"oct-shlib.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// This is a convenience class that calls the\n// octave::get_dynamic_library function automatically at construction\n// time.  When deriving new classes, you can either use it as a field or\n// as a parent (with multiple inheritance).\n\nclass OCTINTERP_API auto_shlib : public dynamic_library\n{\npublic:\n\n  auto_shlib ();\n\n  ~auto_shlib () = default;\n\n  auto_shlib (const auto_shlib&) = default;\n\n  auto_shlib& operator = (const auto_shlib&) = default;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/base-text-renderer.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"base-text-renderer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\nbase_text_renderer::rotate_pixels (uint8NDArray& pixels, int rot_mode) const\n{\n  switch (rot_mode)\n    {\n    case ROTATION_0:\n      break;\n\n    case ROTATION_90:\n      {\n        Array<octave_idx_type> perm (dim_vector (3, 1));\n        perm(0) = 0;\n        perm(1) = 2;\n        perm(2) = 1;\n        pixels = pixels.permute (perm);\n\n        Array<idx_vector> idx (dim_vector (3, 1));\n        idx(0) = idx_vector (':');\n        idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1);\n        idx(2) = idx_vector (':');\n        pixels = uint8NDArray (pixels.index (idx));\n      }\n      break;\n\n    case ROTATION_180:\n      {\n        Array<idx_vector> idx (dim_vector (3, 1));\n        idx(0) = idx_vector (':');\n        idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1);\n        idx(2) = idx_vector (pixels.dim3 ()-1, -1, -1);\n        pixels = uint8NDArray (pixels.index (idx));\n      }\n      break;\n\n    case ROTATION_270:\n      {\n        Array<octave_idx_type> perm (dim_vector (3, 1));\n        perm(0) = 0;\n        perm(1) = 2;\n        perm(2) = 1;\n        pixels = pixels.permute (perm);\n\n        Array<idx_vector> idx (dim_vector (3, 1));\n        idx(0) = idx_vector (':');\n        idx(1) = idx_vector (':');\n        idx(2) = idx_vector (pixels.dim3 ()-1, -1, -1);\n        pixels = uint8NDArray (pixels.index (idx));\n      }\n      break;\n\n    }\n}\n\nint\nbase_text_renderer::rotation_to_mode (double rotation) const\n{\n  // Wrap rotation to range [0, 360]\n  while (rotation < 0)\n    rotation += 360.0;\n  while (rotation > 360.0)\n    rotation -= 360.0;\n\n  if (rotation == 0.0)\n    return ROTATION_0;\n  else if (rotation == 90.0)\n    return ROTATION_90;\n  else if (rotation == 180.0)\n    return ROTATION_180;\n  else if (rotation == 270.0)\n    return ROTATION_270;\n  else\n    return ROTATION_0;\n}\n\nvoid\nbase_text_renderer::fix_bbox_anchor (Matrix& bbox, int halign,\n                                     int valign, int rot_mode,\n                                     bool handle_rotation) const\n{\n  switch (halign)\n    {\n    case 1:\n      bbox(0) = -bbox(2)/2;\n      break;\n\n    case 2:\n      bbox(0) = -bbox(2);\n      break;\n\n    default:\n      bbox(0) = 0;\n      break;\n    }\n\n  switch (valign)\n    {\n    case 1:\n      bbox(1) = -bbox(3)/2;\n      break;\n\n    case 2:\n      bbox(1) = -bbox(3);\n      break;\n\n    case 3:\n      break;\n\n    case 4:\n      bbox(1) = -bbox(3)-bbox(1);\n      break;\n\n    default:\n      bbox(1) = 0;\n      break;\n    }\n\n  if (handle_rotation)\n    {\n      switch (rot_mode)\n        {\n        case ROTATION_90:\n          std::swap (bbox(0), bbox(1));\n          std::swap (bbox(2), bbox(3));\n          bbox(0) = -bbox(0)-bbox(2);\n          break;\n\n        case ROTATION_180:\n          bbox(0) = -bbox(0)-bbox(2);\n          bbox(1) = -bbox(1)-bbox(3);\n          break;\n\n        case ROTATION_270:\n          std::swap (bbox(0), bbox(1));\n          std::swap (bbox(2), bbox(3));\n          bbox(1) = -bbox(1)-bbox(3);\n          break;\n        }\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/base-text-renderer.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_base_text_renderer_h)\n#define octave_base_text_renderer_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n\n#include \"dMatrix.h\"\n#include \"oct-map.h\"\n#include \"uint8NDArray.h\"\n\n#include \"text-engine.h\"\n#include \"text-renderer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_text_renderer : public text_processor\n{\npublic:\n\n  enum\n  {\n    ROTATION_0   = 0,\n    ROTATION_90  = 1,\n    ROTATION_180 = 2,\n    ROTATION_270 = 3\n  };\n\n  base_text_renderer () : text_processor () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (base_text_renderer)\n\n  virtual ~base_text_renderer () = default;\n\n  virtual void\n  set_anti_aliasing (bool val) = 0;\n\n  virtual Matrix\n  get_extent (text_element *elt, double rotation) = 0;\n\n  virtual Matrix\n  get_extent (const std::string& txt, double rotation,\n              const caseless_str& interpreter) = 0;\n\n  virtual void\n  set_font (const std::string& name, const std::string& weight,\n            const std::string& angle, double size) = 0;\n\n  virtual bool\n  ok () { return true; };\n\n  virtual octave_map\n  get_system_fonts () = 0;\n\n  virtual void set_color (const Matrix& c) = 0;\n\n  virtual void\n  text_to_pixels (const std::string& txt, uint8NDArray& pxls,\n                  Matrix& bbox, int halign, int valign, double rotation,\n                  const caseless_str& interpreter,\n                  bool handle_rotation) = 0;\n\n  virtual void\n  text_to_strlist (const std::string& txt,\n                   std::list<text_renderer::string>& lst,\n                   Matrix& box, int halign, int valign, double rotation,\n                   const caseless_str& interpreter = \"tex\") = 0;\n\n  void rotate_pixels (uint8NDArray& pixels, int rot_mode) const;\n\n  int rotation_to_mode (double rotation) const;\n\n  void fix_bbox_anchor (Matrix& bbox, int halign,\n                        int valign, int rot_mode,\n                        bool handle_rotation) const;\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/c-file-ptr-stream.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"filepos-wrappers.h\"\n\n#include \"c-file-ptr-stream.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if ! defined (SEEK_SET)\n#  define SEEK_SET 0\n#endif\n\n#if ! defined (SEEK_CUR)\n#  define SEEK_CUR 1\n#endif\n\n#if ! defined (SEEK_END)\n#  define SEEK_END 2\n#endif\n\nc_file_ptr_buf::~c_file_ptr_buf ()\n{\n  buf_close ();\n}\n\n// FIXME: I'm sure there is room for improvement here...\n\nc_file_ptr_buf::int_type\nc_file_ptr_buf::overflow (int_type c)\n{\n  if (m_f)\n    return (c != traits_type::eof ()) ? std::fputc (c, m_f) : flush ();\n  else\n    return traits_type::not_eof (c);\n}\n\nc_file_ptr_buf::int_type\nc_file_ptr_buf::underflow_common (bool bump)\n{\n  if (m_f)\n    {\n      int_type c = std::fgetc (m_f);\n\n      if (! bump && c != traits_type::eof ())\n        ungetc (c, m_f);\n\n      return c;\n    }\n  else\n    return traits_type::eof ();\n}\n\nc_file_ptr_buf::int_type\nc_file_ptr_buf::pbackfail (int_type c)\n{\n  return ((c != traits_type::eof () && m_f)\n          ? ungetc (c, m_f) : traits_type::not_eof (c));\n}\n\nstd::streamsize\nc_file_ptr_buf::xsputn (const char *s, std::streamsize n)\n{\n  if (m_f)\n    return std::fwrite (s, 1, n, m_f);\n  else\n    return 0;\n}\n\nstd::streamsize\nc_file_ptr_buf::xsgetn (char *s, std::streamsize n)\n{\n  if (m_f)\n    return std::fread (s, 1, n, m_f);\n  else\n    return 0;\n}\n\nstatic inline int\nseekdir_to_whence (std::ios::seekdir dir)\n{\n  return (dir == std::ios::beg\n          ? SEEK_SET : (dir == std::ios::cur\n                        ? SEEK_CUR : (dir == std::ios::end\n                                      ? SEEK_END : dir)));\n}\n\nstd::streampos\nc_file_ptr_buf::seekoff (std::streamoff offset,\n                         std::ios::seekdir dir,\n                         std::ios::openmode)\n{\n  if (m_f)\n    {\n      octave_fseeko_wrapper (m_f, offset, seekdir_to_whence (dir));\n\n      return octave_ftello_wrapper (m_f);\n    }\n  else\n    return 0;\n}\n\nstd::streampos\nc_file_ptr_buf::seekpos (std::streampos offset, std::ios::openmode)\n{\n  if (m_f)\n    {\n      octave_fseeko_wrapper (m_f, offset, SEEK_SET);\n\n      return octave_ftello_wrapper (m_f);\n    }\n  else\n    return 0;\n}\n\nint\nc_file_ptr_buf::sync ()\n{\n  flush ();\n\n  return 0;\n}\n\nint\nc_file_ptr_buf::flush ()\n{\n  return m_f ? std::fflush (m_f) : traits_type::eof ();\n}\n\nint\nc_file_ptr_buf::buf_close ()\n{\n  int retval = -1;\n\n  flush ();\n\n  if (m_f)\n    {\n      retval = m_cf (m_f);\n      m_f = nullptr;\n    }\n\n  return retval;\n}\n\nint\nc_file_ptr_buf::seek (off_t offset, int origin)\n{\n  return m_f ? octave_fseeko_wrapper (m_f, offset, origin) : -1;\n}\n\noff_t\nc_file_ptr_buf::tell ()\n{\n  return m_f ? octave_ftello_wrapper (m_f) : -1;\n}\n\nint\nc_file_ptr_buf::file_close (FILE *m_f)\n{\n  return std::fclose (m_f);\n}\n\n#if defined (HAVE_ZLIB)\n\nc_zfile_ptr_buf::~c_zfile_ptr_buf ()\n{\n  buf_close ();\n}\n\n// FIXME: I'm sure there is room for improvement here...\n\nc_zfile_ptr_buf::int_type\nc_zfile_ptr_buf::overflow (int_type c)\n{\n  if (m_f)\n    return (c != traits_type::eof ()) ? gzputc (m_f, c) : flush ();\n  else\n    return traits_type::not_eof (c);\n}\n\nc_zfile_ptr_buf::int_type\nc_zfile_ptr_buf::underflow_common (bool bump)\n{\n  if (m_f)\n    {\n      int_type c = gzgetc (m_f);\n\n      if (! bump && c != traits_type::eof ())\n        gzungetc (c, m_f);\n\n      return c;\n    }\n  else\n    return traits_type::eof ();\n}\n\nc_zfile_ptr_buf::int_type\nc_zfile_ptr_buf::pbackfail (int_type c)\n{\n  return ((c != traits_type::eof () && m_f)\n          ? gzungetc (c, m_f) : traits_type::not_eof (c));\n}\n\nstd::streamsize\nc_zfile_ptr_buf::xsputn (const char *s, std::streamsize n)\n{\n  if (m_f)\n    return gzwrite (m_f, s, n);\n  else\n    return 0;\n}\n\nstd::streamsize\nc_zfile_ptr_buf::xsgetn (char *s, std::streamsize n)\n{\n  if (m_f)\n    return gzread (m_f, s, n);\n  else\n    return 0;\n}\n\nstd::streampos\nc_zfile_ptr_buf::seekoff (std::streamoff /* offset */,\n                          std::ios::seekdir /* dir */,\n                          std::ios::openmode)\n{\n  return -1;\n}\n\nstd::streampos\nc_zfile_ptr_buf::seekpos (std::streampos /* offset */, std::ios::openmode)\n{\n  return -1;\n}\n\nint\nc_zfile_ptr_buf::sync ()\n{\n  flush ();\n\n  return 0;\n}\n\nint\nc_zfile_ptr_buf::flush ()\n{\n  // FIXME: do we need something more complex here, passing\n  // something other than 0 for the second argument to gzflush and\n  // checking the return value, etc.?\n\n  return m_f ? gzflush (m_f, 0) : traits_type::eof ();\n}\n\nint\nc_zfile_ptr_buf::buf_close ()\n{\n  int retval = -1;\n\n  flush ();\n\n  if (m_f)\n    {\n      retval = m_cf (m_f);\n      m_f = nullptr;\n    }\n\n  return retval;\n}\n\n#endif\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/c-file-ptr-stream.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_c_file_ptr_stream_h)\n#define octave_c_file_ptr_stream_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdio>\n#include <istream>\n\n#if defined (HAVE_ZLIB_H)\n#  include <zlib.h>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass c_file_ptr_buf : public std::streambuf\n{\npublic:\n\n  typedef std::streambuf::int_type int_type;\n\n  typedef int (*close_fcn) (FILE *);\n\n  FILE * stdiofile () { return m_f; }\n\n  c_file_ptr_buf () = delete;\n\n  c_file_ptr_buf (FILE *f, close_fcn cf = file_close)\n    : std::streambuf (), m_f (f), m_cf (cf)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (c_file_ptr_buf)\n\n  ~c_file_ptr_buf ();\n\n  int_type overflow (int_type);\n\n  int_type underflow () { return underflow_common (false); }\n\n  int_type uflow () { return underflow_common (true); }\n\n  int_type pbackfail (int_type);\n\n  std::streamsize xsputn (const char *, std::streamsize);\n\n  std::streamsize xsgetn (char *, std::streamsize);\n\n  std::streampos seekoff (std::streamoff, std::ios::seekdir,\n                          std::ios::openmode = std::ios::in | std::ios::out);\n\n  std::streampos seekpos (std::streampos,\n                          std::ios::openmode = std::ios::in | std::ios::out);\n\n  int sync ();\n\n  int flush ();\n\n  int buf_close ();\n\n  int file_number () const { return m_f ? fileno (m_f) : -1; }\n\n  int seek (off_t offset, int origin);\n\n  off_t tell ();\n\n  void clear () { if (m_f) clearerr (m_f); }\n\n  static int file_close (FILE *m_f);\n\nprotected:\n\n  FILE *m_f;\n\n  close_fcn m_cf;\n\nprivate:\n\n  int_type underflow_common (bool);\n};\n\n// FIXME: the following three classes could probably share some code...\n\ntemplate <typename STREAM_T, typename FILE_T, typename BUF_T>\nclass c_file_ptr_stream : public STREAM_T\n{\npublic:\n\n  c_file_ptr_stream () = delete;\n\n  c_file_ptr_stream (FILE_T m_f,\n                     typename BUF_T::close_fcn m_cf = BUF_T::file_close)\n    : STREAM_T (nullptr), m_buf (new BUF_T (m_f, m_cf))\n  { STREAM_T::init (m_buf); }\n\n  OCTAVE_DISABLE_COPY_MOVE (c_file_ptr_stream)\n\n  ~c_file_ptr_stream () { delete m_buf; m_buf = nullptr; }\n\n  BUF_T * rdbuf () { return m_buf; }\n\n  void stream_close () { if (m_buf) m_buf->buf_close (); }\n\n  int seek (off_t offset, int origin)\n  { return m_buf ? m_buf->seek (offset, origin) : -1; }\n\n  off_t tell () { return m_buf ? m_buf->tell () : -1; }\n\n  void clear () { if (m_buf) m_buf->clear (); STREAM_T::clear (); }\n\nprivate:\n\n  BUF_T *m_buf;\n};\n\ntypedef c_file_ptr_stream<std::istream, FILE *, c_file_ptr_buf>\n  i_c_file_ptr_stream;\ntypedef c_file_ptr_stream<std::ostream, FILE *, c_file_ptr_buf>\n  o_c_file_ptr_stream;\ntypedef c_file_ptr_stream<std::iostream, FILE *, c_file_ptr_buf>\n  io_c_file_ptr_stream;\n\n\n#if defined (HAVE_ZLIB)\n\nclass c_zfile_ptr_buf : public std::streambuf\n{\npublic:\n\n  typedef std::streambuf::int_type int_type;\n\n  typedef int (*close_fcn) (gzFile);\n\n  gzFile stdiofile () { return m_f; }\n\n  c_zfile_ptr_buf () = delete;\n\n  c_zfile_ptr_buf (gzFile f, close_fcn cf = file_close)\n    : std::streambuf (), m_f (f), m_cf (cf)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (c_zfile_ptr_buf)\n\n  ~c_zfile_ptr_buf ();\n\n  int_type overflow (int_type);\n\n  int_type underflow () { return underflow_common (false); }\n\n  int_type uflow () { return underflow_common (true); }\n\n  int_type pbackfail (int_type);\n\n  std::streamsize xsputn (const char *, std::streamsize);\n\n  std::streamsize xsgetn (char *, std::streamsize);\n\n  std::streampos seekoff (std::streamoff, std::ios::seekdir,\n                          std::ios::openmode = std::ios::in | std::ios::out);\n\n  std::streampos seekpos (std::streampos,\n                          std::ios::openmode = std::ios::in | std::ios::out);\n\n  int sync ();\n\n  int flush ();\n\n  int buf_close ();\n\n  int file_number () const { return -1; }\n\n  int seek (off_t offset, int origin)\n  { return m_f ? gzseek (m_f, offset, origin) >= 0 : -1; }\n\n  off_t tell () { return m_f ? gztell (m_f) : -1; }\n\n  void clear () { if (m_f) gzclearerr (m_f); }\n\n  static int file_close (gzFile m_f) { return ::gzclose (m_f); }\n\nprotected:\n\n  gzFile m_f;\n\n  close_fcn m_cf;\n\nprivate:\n\n  int_type underflow_common (bool);\n};\n\ntypedef c_file_ptr_stream<std::istream, gzFile, c_zfile_ptr_buf>\n  i_c_zfile_ptr_stream;\ntypedef c_file_ptr_stream<std::ostream, gzFile, c_zfile_ptr_buf>\n  o_c_zfile_ptr_stream;\ntypedef c_file_ptr_stream<std::iostream, gzFile, c_zfile_ptr_buf>\n  io_c_zfile_ptr_stream;\n\n#endif\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/call-stack.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-regexp.h\"\n#include \"str-vec.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"call-stack.h\"\n#include \"cmd-edit.h\"\n#include \"defun.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"stack-frame.h\"\n#include \"syminfo.h\"\n#include \"symrec.h\"\n#include \"symscope.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Use static fields for the best efficiency.\n// NOTE: C++0x will allow these two to be merged into one.\nstatic const char *bt_fieldnames[] =\n{ \"file\", \"name\", \"line\", \"column\", nullptr };\n\nstatic const octave_fields bt_fields (bt_fieldnames);\n\ncall_stack::call_stack (tree_evaluator& evaluator)\n  : m_evaluator (evaluator), m_cs (), m_curr_frame (0),\n    m_max_stack_depth (1024), m_global_values ()\n{\n  push (symbol_scope (\"top scope\"));\n}\n\noctave_function *\ncall_stack::current_function (bool skip_first) const\n{\n  if (m_cs.empty ())\n    error (\"current_function: call stack is empty\");\n\n  octave_function *fcn = nullptr;\n\n  std::size_t idx = m_curr_frame;\n\n  if (idx > 0 && skip_first)\n    --idx;\n\n  while (true)\n    {\n      fcn = m_cs[idx]->function ();\n\n      if (fcn || idx == 0)\n        break;\n\n      --idx;\n    }\n\n  return fcn;\n}\n\nint\ncall_stack::current_line () const\n{\n  int retval = -1;\n\n  if (! m_cs.empty ())\n    {\n      const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame];\n      retval = elt->line ();\n    }\n\n  return retval;\n}\n\nint\ncall_stack::current_column () const\n{\n  int retval = -1;\n\n  if (! m_cs.empty ())\n    {\n      const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame];\n      retval = elt->column ();\n    }\n\n  return retval;\n}\n\noctave_user_code *\ncall_stack::current_user_code () const\n{\n  // Start at current frame.\n\n  std::size_t xframe = find_current_user_frame ();\n\n  if (xframe > 0)\n    {\n      const std::shared_ptr<stack_frame> elt = m_cs[xframe];\n\n      octave_function *f = elt->function ();\n\n      if (f && f->is_user_code ())\n        return dynamic_cast<octave_user_code *> (f);\n    }\n\n  return nullptr;\n}\n\nint\ncall_stack::current_user_code_line () const\n{\n  // Start at current frame.\n\n  std::size_t xframe = find_current_user_frame ();\n\n  if (xframe > 0)\n    {\n      const std::shared_ptr<stack_frame> elt = m_cs[xframe];\n\n      octave_function *f = elt->function ();\n\n      if (f && f->is_user_code ())\n        {\n          int line = elt->line ();\n\n          if (line > 0)\n            return line;\n        }\n    }\n\n  return -1;\n}\n\nint\ncall_stack::current_user_code_column () const\n{\n  // Start at current frame.\n\n  std::size_t xframe = find_current_user_frame ();\n\n  if (xframe > 0)\n    {\n      const std::shared_ptr<stack_frame> elt = m_cs[xframe];\n\n      octave_function *f = elt->function ();\n\n      if (f && f->is_user_code ())\n        {\n          int column = elt->column ();\n\n          if (column > 0)\n            return column;\n        }\n    }\n\n  return -1;\n}\n\nunwind_protect *\ncall_stack::curr_fcn_unwind_protect_frame ()\n{\n  // Start at current frame.\n\n  std::size_t xframe = find_current_user_frame ();\n\n  if (xframe > 0)\n    {\n      const std::shared_ptr<stack_frame> elt = m_cs[xframe];\n\n      octave_function *f = elt->function ();\n\n      if (f && f->is_user_code ())\n        return elt->unwind_protect_frame ();\n    }\n\n  return nullptr;\n}\n\noctave_user_code *\ncall_stack::debug_user_code () const\n{\n  octave_user_code *retval = nullptr;\n\n  // This should never happen...\n  if (m_curr_frame == 0)\n    return retval;\n\n  std::size_t i = m_curr_frame;\n\n  while (i != 0)\n    {\n      const std::shared_ptr<stack_frame> elt = m_cs[i--];\n\n      octave_function *f = elt->function ();\n\n      if (f && f->is_user_code ())\n        {\n          retval = dynamic_cast<octave_user_code *> (f);\n          break;\n        }\n    }\n\n  return retval;\n}\n\nint\ncall_stack::debug_user_code_line () const\n{\n  int retval = -1;\n\n  // This should never happen...\n  if (m_curr_frame == 0)\n    return retval;\n\n  std::size_t i = m_curr_frame;\n\n  while (i != 0)\n    {\n      const std::shared_ptr<stack_frame> elt = m_cs[i--];\n\n      octave_function *f = elt->function ();\n\n      if (f && f->is_user_code ())\n        {\n          if (elt->line ())\n            {\n              retval = elt->line ();\n              break;\n            }\n        }\n    }\n\n  return retval;\n}\n\nint\ncall_stack::debug_user_code_column () const\n{\n  int retval = -1;\n\n  // This should never happen...\n  if (m_curr_frame == 0)\n    return retval;\n\n  // Start looking with the caller of the calling debug function.\n  std::size_t i = m_curr_frame;\n\n  while (i != 0)\n    {\n      const std::shared_ptr<stack_frame> elt = m_cs[i--];\n\n      octave_function *f = elt->function ();\n\n      if (f && f->is_user_code ())\n        {\n          if (elt->column ())\n            {\n              retval = elt->column ();\n              break;\n            }\n        }\n    }\n\n  return retval;\n}\n\nstd::string\ncall_stack::get_dispatch_class () const\n{\n  return m_cs[m_curr_frame]->get_dispatch_class ();\n}\n\nvoid\ncall_stack::set_dispatch_class (const std::string& class_name)\n{\n  m_cs[m_curr_frame]->set_dispatch_class (class_name);\n}\n\nbool\ncall_stack::is_class_method_executing (std::string& dispatch_class) const\n{\n  dispatch_class = \"\";\n\n  octave_function *f = current_function ();\n\n  bool retval = (f && f->is_class_method ());\n\n  if (retval)\n    dispatch_class = f->dispatch_class ();\n\n  return retval;\n}\n\nbool\ncall_stack::is_class_constructor_executing (std::string& dispatch_class) const\n{\n  dispatch_class = \"\";\n\n  octave_function *f = current_function ();\n\n  bool retval = (f && f->is_class_constructor ());\n\n  if (retval)\n    dispatch_class = f->dispatch_class ();\n\n  return retval;\n}\n\nbool\ncall_stack::all_scripts () const\n{\n  bool retval = true;\n\n  auto p = m_cs.cend ();\n\n  while (p != m_cs.cbegin ())\n    {\n      const std::shared_ptr<stack_frame> elt = *(--p);\n\n      octave_function *f = elt->function ();\n\n      if (f && ! f->is_user_script ())\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nvoid call_stack::get_new_frame_index_and_links\n(std::size_t& new_frame_idx, std::shared_ptr<stack_frame>& parent_link,\n std::shared_ptr<stack_frame>& static_link) const\n{\n  // FIXME: is there a better way?\n\n  std::size_t prev_frame_idx = m_curr_frame;\n\n  new_frame_idx = m_cs.size ();\n\n  // m_max_stack_depth should never be less than zero.\n  if (new_frame_idx > static_cast<std::size_t> (m_max_stack_depth))\n    error (\"max_stack_depth exceeded\");\n\n  // There can't be any links to previous frames if this is the first\n  // frame on the stack.\n\n  if (new_frame_idx == 0)\n    return;\n\n  parent_link = m_cs[prev_frame_idx];\n\n  octave_function *t_fcn = parent_link->function ();\n\n  static_link = (t_fcn\n                 ? (t_fcn->is_user_code ()\n                    ? parent_link : parent_link->static_link ())\n                 : parent_link);\n}\n\nvoid\ncall_stack::push (const symbol_scope& scope)\n{\n  std::size_t new_frame_idx;\n  std::shared_ptr<stack_frame> parent_link;\n  std::shared_ptr<stack_frame> static_link;\n\n  get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);\n\n  std::shared_ptr<stack_frame>\n  new_frame (stack_frame::create (m_evaluator, scope, new_frame_idx,\n                                  parent_link, static_link));\n\n  m_cs.push_back (new_frame);\n\n  m_curr_frame = new_frame_idx;\n}\n\nvoid\ncall_stack::push (octave_user_function *fcn,\n                  const std::shared_ptr<stack_frame>& closure_frames)\n{\n  std::size_t new_frame_idx;\n  std::shared_ptr<stack_frame> parent_link;\n  std::shared_ptr<stack_frame> static_link;\n\n  get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);\n\n  std::shared_ptr<stack_frame>\n  new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,\n                                  parent_link, static_link,\n                                  closure_frames));\n\n  m_cs.push_back (new_frame);\n\n  m_curr_frame = new_frame_idx;\n}\n\nvoid\ncall_stack::push (octave_user_function *fcn,\n                  const stack_frame::local_vars_map& local_vars,\n                  const std::shared_ptr<stack_frame>& closure_frames)\n{\n  std::size_t new_frame_idx;\n  std::shared_ptr<stack_frame> parent_link;\n  std::shared_ptr<stack_frame> static_link;\n\n  get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);\n\n  std::shared_ptr<stack_frame>\n  new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,\n                                  parent_link, static_link, local_vars,\n                                  closure_frames));\n\n  m_cs.push_back (new_frame);\n\n  m_curr_frame = new_frame_idx;\n}\n\nvoid\ncall_stack::push (octave_user_script *script)\n{\n  std::size_t new_frame_idx;\n  std::shared_ptr<stack_frame> parent_link;\n  std::shared_ptr<stack_frame> static_link;\n\n  get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);\n\n  std::shared_ptr<stack_frame>\n  new_frame (stack_frame::create (m_evaluator, script, new_frame_idx,\n                                  parent_link, static_link));\n\n  m_cs.push_back (new_frame);\n\n  m_curr_frame = new_frame_idx;\n}\n\nvoid\ncall_stack::push (octave_function *fcn)\n{\n  std::size_t new_frame_idx;\n  std::shared_ptr<stack_frame> parent_link;\n  std::shared_ptr<stack_frame> static_link;\n\n  get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);\n\n  std::shared_ptr<stack_frame>\n  new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,\n                                  parent_link, static_link));\n\n  m_cs.push_back (new_frame);\n\n  m_curr_frame = new_frame_idx;\n}\n\nbool\ncall_stack::goto_frame (std::size_t n, bool verbose)\n{\n  bool retval = false;\n\n  if (n < m_cs.size ())\n    {\n      retval = true;\n\n      m_curr_frame = n;\n\n      if (verbose)\n        {\n          const std::shared_ptr<stack_frame> elt = m_cs[n];\n\n          elt->display_stopped_in_message (octave_stdout);\n        }\n    }\n\n  return retval;\n}\n\nstd::size_t\ncall_stack::find_current_user_frame () const\n{\n  std::size_t user_frame = m_curr_frame;\n\n  std::shared_ptr<stack_frame> frm = m_cs[user_frame];\n\n  if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame ()\n         || frm->is_scope_frame ()))\n    {\n      frm = frm->static_link ();\n\n      user_frame = frm->index ();\n    }\n\n  return user_frame;\n}\n\nstd::shared_ptr<stack_frame>\ncall_stack::current_user_frame () const\n{\n  std::size_t frame = find_current_user_frame ();\n\n  return m_cs[frame];\n}\n\n// Go to the Nth frame (up if N is negative or down if positive) in\n// the call stack that corresponds to a script, function, or scope\n// beginning with the frame indexed by START.\n\nstd::size_t\ncall_stack::dbupdown (std::size_t start, int n, bool verbose)\n{\n  if (start >= m_cs.size ())\n    error (\"invalid stack frame\");\n\n  // Can't go up from here.\n\n  if (start == 0 && n < 0)\n    {\n      if (verbose)\n        m_cs[start]->display_stopped_in_message (octave_stdout);\n\n      return start;\n    }\n\n  std::shared_ptr<stack_frame> frm = m_cs[start];\n\n  if (! (frm && (frm->is_user_fcn_frame ()\n                 || frm->is_user_script_frame ()\n                 || frm->is_scope_frame ())))\n    error (\"call_stack::dbupdown: invalid initial frame in call stack!\");\n\n  // Use index into the call stack to begin the search.  At this point\n  // we iterate up or down using indexing instead of static links\n  // because ... FIXME: it's a bit complicated, but deserves\n  // explanation.  May be easiest with some pictures of the call stack\n  // for an example or two.\n\n  std::size_t xframe = frm->index ();\n\n  if (n == 0)\n    {\n      if (verbose)\n        frm->display_stopped_in_message (octave_stdout);\n\n      return xframe;\n    }\n\n  int incr = 0;\n\n  if (n < 0)\n    {\n      incr = -1;\n      n = -n;\n    }\n  else if (n > 0)\n    incr = 1;\n\n  std::size_t last_good_frame = 0;\n\n  while (true)\n    {\n      frm = m_cs[xframe];\n\n      if (frm->is_user_fcn_frame () || frm->is_user_script_frame ()\n          || frm->is_scope_frame ())\n        {\n          last_good_frame = xframe;\n\n          if (n == 0)\n            break;\n\n          n--;\n        }\n\n      xframe += incr;\n\n      if (xframe == 0)\n        {\n          last_good_frame = 0;\n          break;\n        }\n\n      if (xframe == m_cs.size ())\n        break;\n    }\n\n  if (verbose)\n    m_cs[last_good_frame]->display_stopped_in_message (octave_stdout);\n\n  return last_good_frame;\n}\n\n// Like dbupdown above but find the starting frame automatically from\n// the current frame.  If the current frame is already a user\n// function, script, or scope frame, use that.  Otherwise, follow\n// the static link for the current frame.  If that is not a user\n// function, script or scope frame then there is an error in the\n// implementation.\n\nstd::size_t\ncall_stack::dbupdown (int n, bool verbose)\n{\n  std::size_t start = find_current_user_frame ();\n\n  return dbupdown (start, n, verbose);\n}\n\n// May be used to temporarily change the value ov m_curr_frame inside\n// a function like evalin.  If used in a function like dbup, the new\n// value of m_curr_frame would be wiped out when dbup returns and the\n// stack frame for dbup is popped.\n\nvoid\ncall_stack::goto_caller_frame ()\n{\n  std::size_t start = find_current_user_frame ();\n\n  std::shared_ptr<stack_frame> caller_frame = m_cs[start]->static_link ();\n\n  // Allow evalin ('caller', ...) to work when called from the\n  // top-level prompt.\n\n  m_curr_frame = caller_frame ? caller_frame->index () : 0;\n}\n\nvoid\ncall_stack::goto_base_frame ()\n{\n  if (m_curr_frame > 0)\n    m_curr_frame = 0;\n}\n\nstd::list<std::shared_ptr<stack_frame>>\n                                     call_stack::backtrace_frames (octave_idx_type& curr_user_frame) const\n{\n  std::list<std::shared_ptr<stack_frame>> frames;\n\n  // curr_frame is the index to the current frame in the overall call\n  // stack, which includes any compiled function frames and scope\n  // frames.  The curr_user_frame value we set is the index into the\n  // subset of frames returned in the octave_map object.\n\n  std::size_t curr_frame = find_current_user_frame ();\n\n  // Don't include top-level stack frame in the list.\n\n  for (std::size_t n = m_cs.size () - 1; n > 0; n--)\n    {\n      std::shared_ptr<stack_frame> frm = m_cs[n];\n\n      if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()\n          || frm->is_scope_frame ())\n        {\n          if (frm->index () == curr_frame)\n            curr_user_frame = frames.size ();\n\n          frames.push_back (frm);\n        }\n\n      if (n == 0)\n        break;\n    }\n\n  return frames;\n}\n\nstd::list<std::shared_ptr<stack_frame>>\n                                     call_stack::backtrace_frames () const\n{\n  octave_idx_type curr_user_frame = -1;\n\n  return backtrace_frames (curr_user_frame);\n}\n\nstd::list<frame_info>\ncall_stack::backtrace_info (octave_idx_type& curr_user_frame,\n                            bool print_subfn) const\n{\n  std::list<std::shared_ptr<stack_frame>> frames\n                                       = backtrace_frames (curr_user_frame);\n\n  std::list<frame_info> retval;\n\n  for (const auto& frm : frames)\n    {\n      if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()\n          || frm->is_scope_frame ())\n        {\n          retval.push_back (frame_info (frm->fcn_file_name (),\n                                        frm->fcn_name (print_subfn),\n                                        frm->line (), frm->column ()));\n        }\n    }\n\n  return retval;\n}\n\nstd::list<frame_info>\ncall_stack::backtrace_info () const\n{\n  octave_idx_type curr_user_frame = -1;\n\n  return backtrace_info (curr_user_frame, true);\n}\n\noctave_map\ncall_stack::backtrace (octave_idx_type& curr_user_frame,\n                       bool print_subfn) const\n{\n  std::list<std::shared_ptr<stack_frame>> frames\n                                       = backtrace_frames (curr_user_frame);\n\n  std::size_t nframes = frames.size ();\n\n  octave_map retval (dim_vector (nframes, 1), bt_fields);\n\n  Cell& file = retval.contents (0);\n  Cell& name = retval.contents (1);\n  Cell& line = retval.contents (2);\n  Cell& column = retval.contents (3);\n\n  octave_idx_type k = 0;\n\n  for (const auto& frm : frames)\n    {\n      if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()\n          || frm->is_scope_frame ())\n        {\n          file(k) = frm->fcn_file_name ();\n          name(k) = frm->fcn_name (print_subfn);\n          line(k) = frm->line ();\n          column(k) = frm->column ();\n\n          k++;\n        }\n    }\n\n  return retval;\n}\n\noctave_map\ncall_stack::backtrace () const\n{\n  octave_idx_type curr_user_frame = -1;\n\n  return backtrace (curr_user_frame, true);\n}\n\noctave_map\ncall_stack::empty_backtrace () const\n{\n  return octave_map (dim_vector (0, 1), bt_fields);\n}\n\nvoid\ncall_stack::pop ()\n{\n  // Never pop top scope.\n  // FIXME: is it possible for this case to happen?\n\n  if (m_cs.size () > 1)\n    {\n      std::shared_ptr<stack_frame> elt = m_cs.back ();\n\n      std::shared_ptr<stack_frame> caller = elt->parent_link ();\n\n      m_curr_frame = caller->index ();\n\n      if (elt->is_closure_context ())\n        elt->break_closure_cycles (elt);\n\n      elt->clear_parent_static_link ();\n\n      m_cs.pop_back ();\n    }\n}\n\nstd::shared_ptr<stack_frame>\ncall_stack::pop_return ()\n{\n  if (!m_cs.empty ())\n    {\n      std::shared_ptr<stack_frame> elt = std::move (m_cs.back ());\n      m_cs.pop_back ();\n\n      m_curr_frame = elt->parent_frame_index ();\n\n      if (elt->is_closure_context ())\n        elt->break_closure_cycles (elt);\n\n      elt->clear_parent_static_link ();\n\n      return elt;\n    }\n\n  return nullptr;\n}\n\nvoid\ncall_stack::clear ()\n{\n  while (! m_cs.empty ())\n    pop ();\n}\n\nsymbol_info_list\ncall_stack::all_variables ()\n{\n  return m_cs[m_curr_frame]->all_variables ();\n}\n\nstd::list<std::string>\ncall_stack::global_variable_names () const\n{\n  std::list<std::string> retval;\n\n  for (const auto& nm_ov : m_global_values)\n    {\n      if (nm_ov.second.is_defined ())\n        retval.push_back (nm_ov.first);\n    }\n\n  retval.sort ();\n\n  return retval;\n}\n\nstd::list<std::string>\ncall_stack::top_level_variable_names () const\n{\n  return m_cs[0]->variable_names ();\n}\n\nstd::list<std::string>\ncall_stack::variable_names () const\n{\n  return m_cs[m_curr_frame]->variable_names ();\n}\n\nvoid\ncall_stack::clear_global_variable (const std::string& name)\n{\n  auto p = m_global_values.find (name);\n\n  if (p != m_global_values.end ())\n    p->second = octave_value ();\n}\n\nvoid\ncall_stack::clear_global_variable_pattern (const std::string& pattern)\n{\n  symbol_match pat (pattern);\n\n  for (auto& nm_ov : m_global_values)\n    {\n      if (pat.match (nm_ov.first))\n        nm_ov.second = octave_value ();\n    }\n}\n\nvoid\ncall_stack::clear_global_variable_regexp (const std::string& pattern)\n{\n  regexp pat (pattern);\n\n  for (auto& nm_ov : m_global_values)\n    {\n      if (pat.is_match (nm_ov.first))\n        nm_ov.second = octave_value ();\n    }\n}\n\nvoid\ncall_stack::clear_global_variables ()\n{\n  for (auto& nm_ov : m_global_values)\n    nm_ov.second = octave_value ();\n}\n\nsymbol_info_list\ncall_stack::glob_symbol_info (const std::string& pattern) const\n{\n  return m_cs[m_curr_frame]->glob_symbol_info (pattern);\n}\n\nsymbol_info_list\ncall_stack::regexp_symbol_info (const std::string& pattern) const\n{\n  return m_cs[m_curr_frame]->regexp_symbol_info (pattern);\n}\n\nsymbol_info_list\ncall_stack::get_symbol_info ()\n{\n  return m_cs[m_curr_frame]->get_symbol_info ();\n}\n\nsymbol_info_list\ncall_stack::top_scope_symbol_info () const\n{\n  return m_cs[0]->get_symbol_info ();\n}\n\noctave_value\ncall_stack::max_stack_depth (const octave_value_list& args,\n                             int nargout)\n{\n  return set_internal_variable (m_max_stack_depth, args, nargout,\n                                \"max_stack_depth\", 0);\n}\n\nvoid\ncall_stack::make_persistent (const symbol_record& sym)\n{\n  m_cs[m_curr_frame]->make_persistent (sym);\n}\n\nvoid\ncall_stack::make_global (const symbol_record& sym)\n{\n  m_cs[m_curr_frame]->make_global (sym);\n}\n\noctave_value\ncall_stack::global_varval (const std::string& name) const\n{\n  auto p = m_global_values.find (name);\n\n  return p == m_global_values.end () ? octave_value () : p->second;\n}\n\noctave_value&\ncall_stack::global_varref (const std::string& name)\n{\n  return m_global_values[name];\n}\n\noctave_value\ncall_stack::get_top_level_value (const std::string& name) const\n{\n  return m_cs[0]->varval (name);\n}\n\nvoid\ncall_stack::set_top_level_value (const std::string& name,\n                                 const octave_value& value)\n{\n  m_cs[0]->assign (name, value);\n}\n\noctave_value\ncall_stack::do_who (int argc, const string_vector& argv,\n                    bool return_list, bool verbose)\n{\n  octave_value retval;\n\n  std::string my_name = argv[0];\n\n  std::string file_name;\n\n  bool from_file = false;\n  bool global_only = false;\n  bool have_regexp = false;\n\n  int i = 1;\n  while (i < argc)\n    {\n      if (argv[i] == \"-file\")\n        {\n          if (from_file)\n            error (\"%s: -file option may only be specified once\",\n                   my_name.c_str ());\n\n          from_file = true;\n\n          if (i == argc - 1)\n            error (\"%s: -file argument must be followed by a filename\",\n                   my_name.c_str ());\n\n          file_name = argv[++i];\n        }\n      else if (argv[i] == \"-regexp\")\n        {\n          have_regexp = true;\n        }\n      else if (argv[i] == \"global\")\n        global_only = true;\n      else if (argv[i][0] == '-')\n        warning (\"%s: unrecognized option '%s'\", my_name.c_str (),\n                 argv[i].c_str ());\n      else\n        break;\n\n      i++;\n    }\n\n  int npatterns = argc - i;\n  string_vector patterns;\n  if (npatterns > 0)\n    {\n      patterns.resize (npatterns);\n      for (int j = 0; j < npatterns; j++)\n        patterns[j] = argv[i+j];\n    }\n  else\n    {\n      patterns.resize (1);\n      patterns[0] = \"*\";\n    }\n\n  if (from_file)\n    {\n      // FIXME: This is an inefficient manner to implement this as the\n      // variables are loaded in to a temporary context and then treated.\n      // It would be better to refactor symbol_info_list to not store the\n      // symbol records and then use it in load-save.cc (do_load) to\n      // implement this option there so that the variables are never\n      // stored at all.\n\n      // Set up temporary scope.\n\n      symbol_scope tmp_scope (file_name);\n\n      push (tmp_scope);\n\n      unwind_action restore_scope ([this] () { pop (); });\n\n      interpreter& interp = m_evaluator.get_interpreter ();\n\n      Fload (interp, ovl (file_name));\n\n      std::string newmsg = \"Variables in the file \" + file_name + \":\\n\";\n\n      if (global_only)\n        return do_global_who_two (patterns, have_regexp, return_list,\n                                  verbose, newmsg);\n      else\n        return do_who_two (patterns, have_regexp, return_list, verbose,\n                           newmsg);\n    }\n  else\n    {\n      if (global_only)\n        return do_global_who_two (patterns, have_regexp, return_list,\n                                  verbose);\n      else\n        return do_who_two (patterns, have_regexp, return_list, verbose);\n    }\n}\n\noctave_value\ncall_stack::do_who_two (const string_vector& patterns,\n                        bool have_regexp, bool return_list,\n                        bool verbose, const std::string& msg)\n{\n  return m_cs[m_curr_frame]->who (patterns, have_regexp, return_list,\n                                  verbose, m_evaluator.whos_line_format (),\n                                  msg);\n}\n\noctave_value\ncall_stack::do_global_who_two (const string_vector& patterns,\n                               bool have_regexp,\n                               bool return_list, bool verbose,\n                               const std::string& msg)\n{\n  symbol_info_list symbol_stats;\n  std::list<std::string> symbol_names;\n\n  octave_idx_type npatterns = patterns.numel ();\n\n  for (octave_idx_type j = 0; j < npatterns; j++)\n    {\n      std::string pattern = patterns[j];\n\n      std::list<std::string> tmp;\n\n      if (have_regexp)\n        {\n          regexp pat (pattern);\n\n          for (auto& nm_ov : m_global_values)\n            {\n              if (pat.is_match (nm_ov.first))\n                tmp.push_back (nm_ov.first);\n            }\n        }\n      else\n        {\n          symbol_match pat (pattern);\n\n          for (auto& nm_ov : m_global_values)\n            {\n              if (pat.match (nm_ov.first))\n                tmp.push_back (nm_ov.first);\n            }\n        }\n\n      for (const auto& nm : tmp)\n        {\n          octave_value value = m_global_values[nm];\n\n          if (value.is_defined ())\n            {\n              if (verbose)\n                {\n                  bool is_formal = false;\n                  bool is_global = true;\n                  bool is_persistent = false;\n\n                  symbol_info syminf (nm, value, is_formal, is_global,\n                                      is_persistent);\n\n                  symbol_stats.push_back (syminf);\n                }\n              else\n                symbol_names.push_back (nm);\n            }\n        }\n    }\n\n  if (return_list)\n    {\n      if (verbose)\n        {\n          std::string caller_fcn_name;\n          octave_function *caller_fcn = caller_function ();\n          if (caller_fcn)\n            caller_fcn_name = caller_fcn->name ();\n\n          return symbol_stats.map_value (caller_fcn_name, 1);\n        }\n      else\n        return Cell (string_vector (symbol_names));\n    }\n  else if (! (symbol_stats.empty () && symbol_names.empty ()))\n    {\n      if (msg.empty ())\n        octave_stdout << \"Global variables:\\n\\n\";\n      else\n        octave_stdout << msg;\n\n      if (verbose)\n        symbol_stats.display (octave_stdout,\n                              m_evaluator.whos_line_format ());\n      else\n        {\n          string_vector names (symbol_names);\n          const int width = command_editor::terminal_cols ();\n          names.list_in_columns (octave_stdout, width);\n        }\n\n      octave_stdout << \"\\n\";\n    }\n\n  return octave_value ();\n}\n\nvoid\ncall_stack::display () const\n{\n  std::ostream& os = octave_stdout;\n\n  std::size_t nframes = size ();\n\n  for (std::size_t i = 0; i < nframes; i++)\n    {\n      m_cs[i]->display (false);\n      if (i < nframes - 1)\n        os << std::endl;\n    }\n}\n\nvoid\ncall_stack::set_auto_fcn_var (stack_frame::auto_var_type avt,\n                              const octave_value& val)\n{\n  m_cs[m_curr_frame]->set_auto_fcn_var (avt, val);\n}\n\nvoid\ncall_stack::set_nargin (int nargin)\n{\n  m_cs[m_curr_frame]->set_nargin (nargin);\n}\n\nvoid\ncall_stack::set_nargout (int nargout)\n{\n  m_cs[m_curr_frame]->set_nargout (nargout);\n}\n\noctave_value\ncall_stack::get_auto_fcn_var (stack_frame::auto_var_type avt) const\n{\n  return m_cs[m_curr_frame]->get_auto_fcn_var (avt);\n}\n\nDEFMETHOD (max_stack_depth, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} max_stack_depth ()\n@deftypefnx {} {@var{old_val} =} max_stack_depth (@var{new_val})\n@deftypefnx {} {@var{old_val} =} max_stack_depth (@var{new_val}, \"local\")\nQuery or set the internal limit on the number of times a function may\nbe called recursively.\n\nIf the limit is exceeded, an error message is printed and control returns to\nthe top level.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n\n@seealso{max_recursion_depth}\n@end deftypefn */)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.max_stack_depth (args, nargout);\n}\n\n/*\n%!test\n%! orig_val = max_stack_depth ();\n%! old_val = max_stack_depth (2*orig_val);\n%! assert (orig_val, old_val);\n%! assert (max_stack_depth (), 2*orig_val);\n%! max_stack_depth (orig_val);\n%! assert (max_stack_depth (), orig_val);\n\n%!error max_stack_depth (1, 2)\n*/\n\nDEFMETHOD (who, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} who\n@deftypefnx {} {} who pattern @dots{}\n@deftypefnx {} {} who option pattern @dots{}\n@deftypefnx {} {C =} who (@dots{})\nList currently defined variables matching the given patterns.\n\nValid pattern syntax is the same as described for the @code{clear} command.\nIf no patterns are supplied, all variables are listed.\n\nBy default, only variables visible in the local scope are displayed.\n\nThe following are valid options, but may not be combined.\n\n@table @code\n@item global\nList variables in the global scope rather than the current scope.\n\n@item -regexp\nThe patterns are considered to be regular expressions when matching the\nvariables to display.  The same pattern syntax accepted by the @code{regexp}\nfunction is used.\n\n@item -file\nThe next argument is treated as a filename.  All variables found within the\nspecified file are listed.  No patterns are accepted when reading variables\nfrom a file.\n@end table\n\nIf called as a function, return a cell array of defined variable names\nmatching the given patterns.\n@seealso{whos, isglobal, isvarname, exist, regexp}\n@end deftypefn */)\n{\n  int argc = args.length () + 1;\n\n  string_vector argv = args.make_argv (\"who\");\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.do_who (argc, argv, nargout == 1);\n}\n\n/*\n%!test\n%! avar = magic (4);\n%! ftmp = [tempname() \".mat\"];\n%! save_default_options (\"-binary\", \"local\");\n%! unwind_protect\n%!   save (ftmp, \"avar\");\n%!   vars = whos (\"-file\", ftmp);\n%!   assert (numel (vars), 1);\n%!   assert (isstruct (vars));\n%!   assert (vars.name, \"avar\");\n%!   assert (vars.size, [4, 4]);\n%!   assert (vars.class, \"double\");\n%!   assert (vars.bytes, 128);\n%! unwind_protect_cleanup\n%!   delete ([ftmp, '*']);\n%! end_unwind_protect\n*/\n\nDEFMETHOD (whos, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} whos\n@deftypefnx {} {} whos pattern @dots{}\n@deftypefnx {} {} whos option pattern @dots{}\n@deftypefnx {} {S =} whos (\"pattern\", @dots{})\nProvide detailed information on currently defined variables matching the\ngiven patterns.\n\nOptions and pattern syntax are the same as for the @code{who} command.\n\nExtended information about each variable is summarized in a table with the\nfollowing default entries.\n\n@table @asis\n@item Attr\nAttributes of the listed variable.  Possible attributes are:\n\n@table @asis\n@item blank\nVariable in local scope\n\n@item @code{c}\nVariable of complex type.\n\n@item @code{f}\nFormal parameter (function argument).\n\n@item @code{g}\nVariable with global scope.\n\n@item @code{p}\nPersistent variable.\n@end table\n\n@item Name\nThe name of the variable.\n\n@item Size\nThe logical size of the variable.  A scalar is 1x1, a vector is\n@nospell{1xN} or @nospell{Nx1}, a 2-D matrix is @nospell{MxN}.\n\n@item Bytes\nThe amount of memory currently used to store the variable.\n\n@item Class\nThe class of the variable.  Examples include double, single, char, uint16,\ncell, and struct.\n@end table\n\nThe table can be customized to display more or less information through\nthe function @code{whos_line_format}.\n\nIf @code{whos} is called as a function, return a struct array of defined\nvariable names matching the given patterns.  Fields in the structure\ndescribing each variable are: name, size, bytes, class, global, sparse,\ncomplex, nesting, persistent.\n@seealso{who, whos_line_format}\n@end deftypefn */)\n{\n  int argc = args.length () + 1;\n\n  string_vector argv = args.make_argv (\"whos\");\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.do_who (argc, argv, nargout == 1, true);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/call-stack.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_call_stack_h)\n#define octave_call_stack_h 1\n\n#include \"octave-config.h\"\n\n#include <deque>\n#include <memory>\n#include <string>\n\nclass octave_function;\nclass octave_map;\nclass octave_user_code;\nclass octave_user_script;\nclass octave_value;\nclass octave_value_list;\n\n#include \"quit.h\"\n\n#include \"stack-frame.h\"\n#include \"symscope.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_evaluator;\nclass symbol_info_list;\nclass unwind_protect;\n\nclass OCTINTERP_API call_stack\n{\npublic:\n\n  typedef std::deque<std::shared_ptr<stack_frame>> stack_frames;\n\n  typedef stack_frames::iterator iterator;\n  typedef stack_frames::const_iterator const_iterator;\n\n  typedef stack_frames::reverse_iterator reverse_iterator;\n  typedef stack_frames::const_reverse_iterator const_reverse_iterator;\n\n  call_stack (tree_evaluator& evaluator);\n\n  // Lock current function.  Look for the first stack frame that is\n  // a function.  If SKIP_FIST is true, then skip the first frame.\n  // That allows functions like Fmlock to find and lock the calling\n  // function instead of locking Fmlock itself.\n\n  octave_function * current_function (bool skip_first = false) const;\n\n  octave_function * caller_function () const\n  {\n    return current_function (true);\n  }\n\n  // Current line in current function.\n  int current_line () const;\n\n  // Current column in current function.\n  int current_column () const;\n\n  std::size_t current_frame () const { return m_curr_frame; }\n\n  std::size_t size () const { return m_cs.size (); }\n\n  std::shared_ptr<stack_frame> get_current_stack_frame () const\n  {\n    return m_cs[m_curr_frame];\n  }\n\n  symbol_scope top_scope () const\n  {\n    return m_cs[0]->get_scope ();\n  }\n\n  symbol_scope current_scope () const\n  {\n    // FIXME: Can m_curr_frame ever be invalid?\n    return (m_curr_frame < m_cs.size ()\n            ? m_cs[m_curr_frame]->get_scope () : symbol_scope::invalid ());\n  }\n\n  bool at_top_level () const\n  {\n    return current_scope () == top_scope ();\n  }\n\n  // Function at location N on the call stack (N == 0 is current), may\n  // be built-in.\n  octave_function * element (std::size_t n)\n  {\n    octave_function *retval = nullptr;\n\n    if (m_cs.size () > n)\n      retval = m_cs[n]->function ();\n\n    return retval;\n  }\n\n  // User code caller.\n  octave_user_code * current_user_code () const;\n\n  unwind_protect * curr_fcn_unwind_protect_frame ();\n\n  // Line in user code caller.\n  int current_user_code_line () const;\n\n  // Column in user code caller.\n  int current_user_code_column () const;\n\n  // Current function that we are debugging.\n  octave_user_code * debug_user_code () const;\n\n  // Line number in current function that we are debugging.\n  int debug_user_code_line () const;\n\n  // Column number in current function that we are debugging.\n  int debug_user_code_column () const;\n\n  std::string get_dispatch_class () const;\n\n  void set_dispatch_class (const std::string& class_name);\n\n  bool is_class_method_executing (std::string& dispatch_class) const;\n\n  bool is_class_constructor_executing (std::string& dispatch_class) const;\n\n  // Return TRUE if all elements on the call stack are scripts.\n  bool all_scripts () const;\n\n  void push (const symbol_scope& scope);\n\n  void push (octave_user_function *fcn,\n             const std::shared_ptr<stack_frame>& closure_frames = std::shared_ptr<stack_frame> ());\n\n  void push (octave_user_function *fcn,\n             const stack_frame::local_vars_map& local_vars,\n             const std::shared_ptr<stack_frame>& closure_frames = std::shared_ptr<stack_frame> ());\n\n  void push (octave_user_script *script);\n\n  void push (octave_function *fcn);\n\n  void set_location (int l, int c)\n  {\n    if (! m_cs.empty ())\n      {\n        std::shared_ptr<stack_frame> elt = m_cs.back ();\n\n        elt->line (l);\n        elt->column (c);\n      }\n  }\n\n  void set_line (int l)\n  {\n    if (! m_cs.empty ())\n      {\n        std::shared_ptr<stack_frame> elt = m_cs.back ();\n\n        elt->line (l);\n      }\n  }\n\n  void set_column (int c)\n  {\n    if (! m_cs.empty ())\n      {\n        std::shared_ptr<stack_frame> elt = m_cs.back ();\n\n        elt->column (c);\n      }\n  }\n\n  bool goto_frame (std::size_t n = 0, bool verbose = false);\n\n  void restore_frame (std::size_t n)\n  {\n    goto_frame (n);\n  }\n\n  std::size_t find_current_user_frame () const;\n\n  std::shared_ptr<stack_frame> current_user_frame () const;\n\n  std::size_t dbupdown (std::size_t start, int n, bool verbose);\n  std::size_t dbupdown (int n = -1, bool verbose = false);\n\n  void goto_caller_frame ();\n\n  void goto_base_frame ();\n\n  std::list<std::shared_ptr<stack_frame>>\n                                       backtrace_frames (octave_idx_type& curr_user_frame) const;\n\n  // List of raw stack frames.\n\n  std::list<std::shared_ptr<stack_frame>> backtrace_frames () const;\n\n  // List of stack_info objects that can be used in liboctave and\n  // stored in the execution_exception object.\n\n  std::list<frame_info> backtrace_info (octave_idx_type& curr_user_frame,\n                                        bool print_subfn = true) const;\n\n  std::list<frame_info> backtrace_info () const;\n\n  // The same as backtrace_info but in the form of a struct array\n  // object that may be used in the interpreter.\n\n  octave_map backtrace (octave_idx_type& curr_user_frame,\n                        bool print_subfn = true) const;\n\n  octave_map backtrace () const;\n\n  octave_map empty_backtrace () const;\n\n  void pop ();\n\n  std::shared_ptr<stack_frame> pop_return ();\n\n  void clear ();\n\n  symbol_info_list all_variables ();\n\n  std::list<std::string> global_variable_names () const;\n\n  std::list<std::string> top_level_variable_names () const;\n\n  std::list<std::string> variable_names () const;\n\n  void clear_global_variable (const std::string& name);\n\n  void clear_global_variable_pattern (const std::string& pattern);\n\n  void clear_global_variable_regexp(const std::string& pattern);\n\n  void clear_global_variables ();\n\n  symbol_info_list glob_symbol_info (const std::string& pattern) const;\n\n  symbol_info_list regexp_symbol_info (const std::string& pattern) const;\n\n  symbol_info_list get_symbol_info ();\n\n  symbol_info_list top_scope_symbol_info () const;\n\n  octave_value max_stack_depth (const octave_value_list& args, int nargout);\n\n  void make_persistent (const symbol_record& sym);\n\n  void make_global (const symbol_record& sym);\n\n  octave_value global_varval (const std::string& name) const;\n\n  octave_value& global_varref (const std::string& name);\n\n  octave_value get_top_level_value (const std::string& name) const;\n\n  void set_top_level_value (const std::string& name,\n                            const octave_value& value);\n\n  octave_value do_who (int argc, const string_vector& argv,\n                       bool return_list, bool verbose = false);\n\n  octave_value do_who_two (const string_vector& patterns, bool have_regexp,\n                           bool return_list, bool verbose,\n                           const std::string& msg = \"\");\n\n  octave_value do_global_who_two (const string_vector& patterns,\n                                  bool have_regexp, bool return_list,\n                                  bool verbose, const std::string& msg = \"\");\n\n  void display () const;\n\n  void set_auto_fcn_var (stack_frame::auto_var_type avt,\n                         const octave_value& val);\n\n  void set_nargin (int nargin);\n  void set_nargout (int nargout);\n\n  octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const;\n\nprivate:\n\n  void get_new_frame_index_and_links\n  (std::size_t& new_frame_idx, std::shared_ptr<stack_frame>& parent_link,\n   std::shared_ptr<stack_frame>& static_link) const;\n\n  tree_evaluator& m_evaluator;\n\n  // The list of stack frames.\n  stack_frames m_cs;\n\n  // The current frame.  When a new frame is pushed, m_curr_frame\n  // moves to the end of the list of stack frames (also referred to as\n  // the top of the call stack) but may be temporarily moved to\n  // another location by evalin or debugging functions.\n\n  // FIXME: should the current frame be managed by the evaluator\n  // instead?\n  std::size_t m_curr_frame;\n\n  int m_max_stack_depth;\n\n  std::map<std::string, octave_value> m_global_values;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/cdisplay.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdlib.h>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <windows.h>\n#elif defined (HAVE_FRAMEWORK_CARBON)\n#  include <Carbon/Carbon.h>\n#else\n#  if defined (HAVE_X_WINDOWS)\n#    include <X11/Xlib.h>\n#  endif\n#  if defined (HAVE_WAYLAND_CLIENT)\n#    include <string.h>\n#    include <wayland-client.h>\n#  endif\n#endif\n\n#include \"cdisplay.h\"\n\n// Programming Note: This file exists so that we can hide system\n// header files that make heavy use of macros and C-style casts in a C\n// language file and avoid warnings about using old-style casts in C++.\n// Additionally, on OS X systems, including the Carbon.h header file\n// results in the declaration of a \"panic\" function that conflicts with\n// Octave's global panic function, so Carbon.h can't be included in any\n// file that also includes Octave's error.h header file.\n\n// Please do NOT eliminate this file and move code from here to\n// display.cc.\n\n#if defined (HAVE_WAYLAND_CLIENT)\n\n// struct to store display information\nstruct s_display_info {\n    int ht;\n    int wd;\n    int ht_mm;\n    int wd_mm;\n    int scale;\n    int avail;\n};\n\n// set up Wayland output event listener to capture the relevant information\n\nstatic void\noct_wl_geometry (void *data, struct wl_output *output, int x, int y,\n                 int physical_width, int physical_height, int subpixel,\n                 const char *make, const char *model, int transform)\n{\n  struct s_display_info *info = data;\n  info->ht_mm = physical_height;\n  info->wd_mm = physical_width;\n\n  octave_unused_parameter (output);\n  octave_unused_parameter (x);\n  octave_unused_parameter (y);\n  octave_unused_parameter (subpixel);\n  octave_unused_parameter (make);\n  octave_unused_parameter (model);\n  octave_unused_parameter (transform);\n}\n\nstatic void\noct_wl_mode (void *data, struct wl_output *output, unsigned int flags,\n             int width, int height, int refresh)\n{\n  struct s_display_info *info = data;\n\n  if (flags & WL_OUTPUT_MODE_CURRENT)\n    {\n      info->wd = width;\n      info->ht = height;\n      info->avail = 1;\n    }\n\n  octave_unused_parameter (output);\n  octave_unused_parameter (refresh);\n}\n\nstatic void oct_wl_done (void *data, struct wl_output *output)\n{\n  octave_unused_parameter (data);\n  octave_unused_parameter (output);\n}\n\nstatic void\noct_wl_scale (void *data, struct wl_output *output, int32_t factor)\n{\n  struct s_display_info *info = data;\n  info->scale = factor;\n\n  octave_unused_parameter (output);\n}\n\nstatic const struct wl_output_listener output_listener = {\n    .geometry = oct_wl_geometry,\n    .mode = oct_wl_mode,\n    .done = oct_wl_done,\n    .scale = oct_wl_scale\n};\n\n// register above output listener\n\nstatic void\noct_wl_global (void *data, struct wl_registry *registry, uint32_t name,\n               const char *interface, uint32_t version)\n{\n  struct s_display_info *info = data;\n\n  // collect info only for output device\n  if (strcmp (interface, wl_output_interface.name) == 0)\n    {\n      // bind wl_output interface\n      struct wl_output *output = wl_registry_bind (registry, name,\n                                                   &wl_output_interface, 1);\n      // set up event listener\n      wl_output_add_listener (output, &output_listener, info);\n    }\n\n  octave_unused_parameter (version);\n}\n\nstatic void\noct_wl_global_remove (void *data, struct wl_registry *registry, uint32_t name)\n{\n  octave_unused_parameter (data);\n  octave_unused_parameter (registry);\n  octave_unused_parameter (name);\n}\n\nstatic const struct wl_registry_listener registry_listener = {\n    .global = oct_wl_global,\n    .global_remove = oct_wl_global_remove\n};\n\n#endif\n\nconst char *\noctave_get_display_info (const char *dpy_name, int *ht, int *wd, int *dp,\n                         double *rx, double *ry, int *dpy_avail)\n{\n  const char *msg = NULL;\n\n  *dpy_avail = 0;\n\n  double ht_mm = 0.0;\n  double wd_mm = 0.0;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  octave_unused_parameter (dpy_name);\n\n  HDC hdc = GetDC (0);\n\n  if (hdc)\n    {\n      *dp = GetDeviceCaps (hdc, BITSPIXEL);\n\n      *ht = GetDeviceCaps (hdc, VERTRES);\n      *wd = GetDeviceCaps (hdc, HORZRES);\n\n      ht_mm = GetDeviceCaps (hdc, VERTSIZE);\n      wd_mm = GetDeviceCaps (hdc, HORZSIZE);\n\n      *dpy_avail = 1;\n    }\n  else\n    msg = \"no graphical display found\";\n\n#elif defined (HAVE_FRAMEWORK_CARBON)\n\n  octave_unused_parameter (dpy_name);\n\n  CGDirectDisplayID display = CGMainDisplayID ();\n\n  if (display)\n    {\n#if defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL)\n\n      *dp = CGDisplayBitsPerPixel (display);\n\n#else\n\n      /* FIXME: This will only work for MacOS > 10.5.  For earlier versions\n         this code is not needed (use CGDisplayBitsPerPixel instead).  */\n\n      CGDisplayModeRef mode = CGDisplayCopyDisplayMode (display);\n      CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding (mode);\n\n      if (CFStringCompare (pixelEncoding, CFSTR (IO32BitDirectPixels), 0) == 0)\n        *dp = 32;\n      else if (CFStringCompare (pixelEncoding,\n                                CFSTR (IO16BitDirectPixels), 0) == 0)\n        *dp = 16;\n      else\n        *dp = 8;\n\n#endif\n\n      *ht = CGDisplayPixelsHigh (display);\n      *wd = CGDisplayPixelsWide (display);\n\n      CGSize sz_mm = CGDisplayScreenSize (display);\n\n      /* For MacOS >= 10.6, CGSize is a struct keeping 2 CGFloat\n         values, but the CGFloat typedef is not present on older\n         systems, so use double instead.  */\n\n      ht_mm = sz_mm.height;\n      wd_mm = sz_mm.width;\n\n      *dpy_avail = 1;\n    }\n  else\n    msg = \"no graphical display found\";\n\n#elif defined (HAVE_X_WINDOWS) || defined (HAVE_WAYLAND_CLIENT)\n\n#  if defined (HAVE_X_WINDOWS)\n\n  /* If dpy_name is NULL, XopenDisplay will look for DISPLAY in the\n     environment.  */\n\n  Display *display = XOpenDisplay (dpy_name);\n\n  if (display)\n    {\n      Screen *screen = DefaultScreenOfDisplay (display);\n\n      if (screen)\n        {\n          *dp = DefaultDepthOfScreen (screen);\n\n          *ht = HeightOfScreen (screen);\n          *wd = WidthOfScreen (screen);\n\n          int screen_number = XScreenNumberOfScreen (screen);\n\n          ht_mm = DisplayHeightMM (display, screen_number);\n          wd_mm = DisplayWidthMM (display, screen_number);\n\n          *dpy_avail = 1;\n        }\n#    if ! defined (HAVE_WAYLAND_CLIENT)\n      else\n        msg = \"X11 display has no default screen\";\n#    endif\n\n      XCloseDisplay (display);\n    }\n#    if ! defined (HAVE_WAYLAND_CLIENT)\n  else\n    msg = \"unable to open X11 DISPLAY\";\n#    endif\n#  endif\n\n#  if defined (HAVE_WAYLAND_CLIENT)\n  if (*dpy_avail == 0)\n    {\n      // try to connect to Wayland display\n      struct wl_display *wldisplay = wl_display_connect (dpy_name);\n\n      if (wldisplay)\n        {\n         struct s_display_info info = {0};\n\n          // set up Wayland registry\n          struct wl_registry *registry = wl_display_get_registry (wldisplay);\n          // add output listener\n          wl_registry_add_listener (registry, &registry_listener, &info);\n          // process display events\n          // first roundtrip to get registry events\n          wl_display_roundtrip (wldisplay);\n          // second roundtrip to get output events\n          wl_display_roundtrip (wldisplay);\n          // disconnect display\n          wl_display_disconnect (wldisplay);\n\n          if (info.avail)\n            {\n              // FIXME: There is no easy way to query the pixel depth using\n              //        Wayland.  The closest might be to query the used buffer\n              //        format and to try and defer the pixel depth from that.\n              //        But that is not easily done.  So, just assume a pixel\n              //        depth of 32 bits.\n              *dp = 32;\n\n              *ht = info.ht;\n              *wd = info.wd;\n\n              ht_mm = info.ht_mm;\n              wd_mm = info.wd_mm;\n\n              *dpy_avail = 1;\n            }\n          else\n#    if defined (HAVE_X_WINDOWS)\n            msg = \"no Wayland or X11 display available\";\n#    else\n            msg = \"no Wayland display available\";\n#    endif\n        }\n      else\n#    if defined (HAVE_X_WINDOWS)\n        msg = \"unable to open Wayland or X11 display\";\n#    else\n        msg = \"unable to open Wayland display\";\n#    endif\n    }\n#  endif\n\n#else\n\n  octave_unused_parameter (dpy_name);\n  octave_unused_parameter (ht);\n  octave_unused_parameter (wd);\n  octave_unused_parameter (dp);\n  octave_unused_parameter (rx);\n  octave_unused_parameter (ry);\n\n  msg = \"no graphical display found\";\n\n#endif\n\n  if (*dpy_avail)\n    {\n      if (wd_mm == 0 || ht_mm == 0)\n        {\n          msg = \"screen width or height reported to be zero\";\n\n          // Sizes reported as zero have been found on some systems.\n          // For example, X/Wayland running inside virtualbox.\n\n          // Guess a DPI.\n\n          *rx = 96.0;\n          *ry = 96.0;\n        }\n      else\n        {\n          *rx = *wd * 25.4 / wd_mm;\n          *ry = *ht * 25.4 / ht_mm;\n        }\n    }\n\n  return msg;\n}\n"
  },
  {
    "path": "libinterp/corefcn/cdisplay.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2014-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cdisplay_h)\n#define octave_cdisplay_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTINTERP_API const char *\noctave_get_display_info (const char *dpy_name, int *ht, int *wd, int *dp,\n                         double *rx, double *ry, int *dpy_avail);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/cmd-edit.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n#include <cstring>\n\n#include <string>\n\n#include \"cmd-edit.h\"\n#include \"cmd-hist.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"lo-utils.h\"\n#include \"oct-env.h\"\n#include \"oct-error.h\"\n#include \"oct-mutex.h\"\n#include \"oct-sysdep.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n#include \"singleton-cleanup.h\"\n#include \"strdup-wrapper.h\"\n#include \"unistd-wrappers.h\"\n\n#if defined (USE_READLINE)\n#include <cstdio>\n\n#include \"oct-rl-edit.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nchar * do_completer_word_break_hook ();\n\ncommand_editor *command_editor::s_instance = nullptr;\n\nstd::set<command_editor::startup_hook_fcn> command_editor::s_startup_hook_set;\n\nstd::set<command_editor::pre_input_hook_fcn> command_editor::s_pre_input_hook_set;\n\nstd::set<command_editor::event_hook_fcn> command_editor::s_event_hook_set;\n\nstatic mutex event_hook_lock;\n\n#if defined (USE_READLINE)\n\nclass gnu_readline : public command_editor\n{\npublic:\n\n  typedef command_editor::startup_hook_fcn startup_hook_fcn;\n\n  typedef command_editor::pre_input_hook_fcn pre_input_hook_fcn;\n\n  typedef command_editor::event_hook_fcn event_hook_fcn;\n\n  typedef command_editor::completion_fcn completion_fcn;\n\n  gnu_readline ();\n\n  OCTAVE_DISABLE_COPY_MOVE (gnu_readline)\n\n  ~gnu_readline () = default;\n\n  void do_set_name (const std::string& n);\n\n  std::string do_readline (const std::string& prompt, bool& eof);\n\n  void do_set_input_stream (FILE *f);\n\n  FILE * do_get_input_stream ();\n\n  void do_set_output_stream (FILE *f);\n\n  FILE * do_get_output_stream ();\n\n  void do_redisplay ();\n\n  int do_terminal_rows ();\n\n  int do_terminal_cols ();\n\n  void do_clear_screen (bool skip_redisplay);\n\n  void do_resize_terminal ();\n\n  void do_set_screen_size (int ht, int wd);\n\n  std::string newline_chars ();\n\n  void do_restore_terminal_state ();\n\n  void do_blink_matching_paren (bool flag);\n\n  bool do_erase_empty_line (bool flag);\n\n  void do_set_basic_word_break_characters (const std::string& s);\n\n  void do_set_completer_word_break_characters (const std::string& s);\n\n  void do_set_basic_quote_characters (const std::string& s);\n\n  void do_set_filename_quote_characters (const std::string& s);\n\n  void do_set_completer_quote_characters (const std::string& s);\n\n  void do_set_completion_append_character (char c);\n\n  void do_set_completion_function (completion_fcn f);\n\n  void do_set_quoting_function (quoting_fcn f);\n\n  void do_set_dequoting_function (dequoting_fcn f);\n\n  void do_set_char_is_quoted_function (char_is_quoted_fcn f);\n\n  void do_set_user_accept_line_function (user_accept_line_fcn f);\n\n  completion_fcn do_get_completion_function () const;\n\n  quoting_fcn do_get_quoting_function () const;\n\n  dequoting_fcn do_get_dequoting_function () const;\n\n  char_is_quoted_fcn do_get_char_is_quoted_function () const;\n\n  user_accept_line_fcn do_get_user_accept_line_function () const;\n\n  string_vector\n  do_generate_filename_completions (const std::string& text);\n\n  std::string do_get_line_buffer () const;\n\n  std::string do_get_current_line () const;\n\n  char do_get_prev_char (int) const;\n\n  void do_replace_line (const std::string& text, bool clear_undo);\n\n  void do_kill_full_line ();\n\n  void do_insert_text (const std::string& text);\n\n  void do_newline ();\n\n  void do_accept_line ();\n\n  bool do_undo ();\n\n  void do_clear_undo_list ();\n\n  void set_startup_hook (startup_hook_fcn f);\n\n  void restore_startup_hook ();\n\n  void set_pre_input_hook (pre_input_hook_fcn f);\n\n  void restore_pre_input_hook ();\n\n  void set_event_hook (event_hook_fcn f);\n\n  void restore_event_hook ();\n\n  void do_restore_event_hook ();\n\n  void do_read_init_file (const std::string& file);\n\n  void do_re_read_init_file ();\n\n  bool do_filename_completion_desired (bool);\n\n  bool do_filename_quoting_desired (bool);\n\n  bool do_prefer_env_winsize (bool);\n\n  void do_interrupt (bool);\n\n  void do_handle_interrupt_signal ();\n\n  static int operate_and_get_next (int, int);\n\n  static int history_search_backward (int, int);\n\n  static int history_search_forward (int, int);\n\nprivate:\n\n  static char * command_generator (const char *text, int state);\n\n  static char * command_quoter (char *text, int match_type,\n                               char *quote_pointer);\n\n  static char * command_dequoter (char *text, int match_type);\n\n  static int command_char_is_quoted (char *text, int index);\n\n  static int command_accept_line (int count, int key);\n\n  static char ** command_completer (const char *text, int start, int end);\n\n  static char * do_completer_word_break_hook ();\n\n  startup_hook_fcn m_previous_startup_hook;\n\n  pre_input_hook_fcn m_previous_pre_input_hook;\n\n  event_hook_fcn m_previous_event_hook;\n\n  completion_fcn m_completion_function;\n\n  quoting_fcn m_quoting_function;\n\n  dequoting_fcn m_dequoting_function;\n\n  char_is_quoted_fcn m_char_is_quoted_function;\n\n  user_accept_line_fcn m_user_accept_line_function;\n\n  static std::string s_completer_quote_characters;\n};\n\nstd::string gnu_readline::s_completer_quote_characters = \"\";\n\ngnu_readline::gnu_readline ()\n  : command_editor (), m_previous_startup_hook (nullptr),\n    m_previous_pre_input_hook (nullptr),\n    m_previous_event_hook (nullptr), m_completion_function (nullptr),\n    m_quoting_function (nullptr), m_dequoting_function (nullptr),\n    m_char_is_quoted_function (nullptr), m_user_accept_line_function (nullptr)\n{\n  // FIXME: need interface to rl_add_defun, rl_initialize, and\n  // a function to set rl_terminal_name\n\n  std::string term = sys::env::getenv (\"TERM\");\n\n  octave_rl_set_terminal_name (term.c_str ());\n\n  octave_rl_initialize ();\n\n  do_blink_matching_paren (true);\n\n  // Bind operate-and-get-next.\n\n  octave_rl_add_defun (\"operate-and-get-next\",\n                       gnu_readline::operate_and_get_next,\n                       octave_rl_ctrl ('O'));\n}\n\nvoid\ngnu_readline::do_set_name (const std::string& nm)\n{\n  ::octave_rl_set_name (nm.c_str ());\n}\n\nstd::string\ngnu_readline::do_readline (const std::string& prompt, bool& eof)\n{\n  std::string retval;\n\n  eof = false;\n\n  const char *p = prompt.c_str ();\n\n  char *line = ::octave_rl_readline (p);\n\n  if (line)\n    {\n      retval = line;\n\n      free (line);\n    }\n  else\n    eof = true;\n\n  return retval;\n}\n\nvoid\ngnu_readline::do_set_input_stream (FILE *f)\n{\n  ::octave_rl_set_input_stream (f);\n}\n\nFILE *\ngnu_readline::do_get_input_stream ()\n{\n  return ::octave_rl_get_input_stream ();\n}\n\nvoid\ngnu_readline::do_set_output_stream (FILE *f)\n{\n  ::octave_rl_set_output_stream (f);\n}\n\nFILE *\ngnu_readline::do_get_output_stream ()\n{\n  return ::octave_rl_get_output_stream ();\n}\n\nvoid\ngnu_readline::do_redisplay ()\n{\n  ::octave_rl_redisplay ();\n}\n\n// GNU readline handles SIGWINCH, so these values have a good chance\n// of being correct even if the window changes size (they may be\n// wrong if, for example, the luser changes the window size while the\n// pager is running, and the signal is handled by the pager instead of\n// us.\n\nint\ngnu_readline::do_terminal_rows ()\n{\n  int sh = ::octave_rl_screen_height ();\n\n  return sh > 0 ? sh : 24;\n}\n\nint\ngnu_readline::do_terminal_cols ()\n{\n  int sw = ::octave_rl_screen_width ();\n\n  return sw > 0 ? sw : 80;\n}\n\nvoid\ngnu_readline::do_clear_screen (bool skip_redisplay)\n{\n  ::octave_rl_clear_screen (skip_redisplay);\n}\n\nvoid\ngnu_readline::do_resize_terminal ()\n{\n  ::octave_rl_resize_terminal ();\n}\n\nvoid\ngnu_readline::do_set_screen_size (int ht, int wd)\n{\n  ::octave_rl_set_screen_size (ht, wd);\n}\n\nstd::string\ngnu_readline::newline_chars ()\n{\n  return \"\\r\\n\";\n}\n\nvoid\ngnu_readline::do_restore_terminal_state ()\n{\n  ::octave_rl_restore_terminal_state ();\n}\n\nvoid\ngnu_readline::do_blink_matching_paren (bool flag)\n{\n  ::octave_rl_enable_paren_matching (flag ? 1 : 0);\n}\n\nbool\ngnu_readline::do_erase_empty_line (bool flag)\n{\n  return ::octave_rl_erase_empty_line (flag ? 1 : 0);\n}\n\nvoid\ngnu_readline::do_set_basic_word_break_characters (const std::string& s)\n{\n  ::octave_rl_set_basic_word_break_characters (s.c_str ());\n}\n\nvoid\ngnu_readline::do_set_completer_word_break_characters (const std::string& s)\n{\n  ::octave_rl_set_completer_word_break_characters (s.c_str ());\n\n  ::octave_rl_set_completion_word_break_hook\n  (gnu_readline::do_completer_word_break_hook);\n\n}\n\nvoid\ngnu_readline::do_set_basic_quote_characters (const std::string& s)\n{\n  ::octave_rl_set_basic_quote_characters (s.c_str ());\n}\n\nvoid\ngnu_readline::do_set_filename_quote_characters (const std::string& s)\n{\n  ::octave_rl_set_filename_quote_characters (s.c_str ());\n}\n\nvoid\ngnu_readline::do_set_completer_quote_characters (const std::string& s)\n{\n  s_completer_quote_characters = s;\n}\n\nvoid\ngnu_readline::do_set_completion_append_character (char c)\n{\n  ::octave_rl_set_completion_append_character (c);\n}\n\nvoid\ngnu_readline::do_set_completion_function (completion_fcn f)\n{\n  m_completion_function = f;\n\n  rl_attempted_completion_fcn_ptr fp\n    = (f ? gnu_readline::command_completer : nullptr);\n\n  ::octave_rl_set_completion_function (fp);\n}\n\nvoid\ngnu_readline::do_set_quoting_function (quoting_fcn f)\n{\n  m_quoting_function = f;\n\n  rl_quoting_fcn_ptr fp\n    = (f ? gnu_readline::command_quoter : nullptr);\n\n  ::octave_rl_set_quoting_function (fp);\n}\n\nvoid\ngnu_readline::do_set_dequoting_function (dequoting_fcn f)\n{\n  m_dequoting_function = f;\n\n  rl_dequoting_fcn_ptr fp\n    = (f ? gnu_readline::command_dequoter : nullptr);\n\n  ::octave_rl_set_dequoting_function (fp);\n}\n\nvoid\ngnu_readline::do_set_char_is_quoted_function (char_is_quoted_fcn f)\n{\n  m_char_is_quoted_function = f;\n\n  rl_char_is_quoted_fcn_ptr fp\n    = (f ? gnu_readline::command_char_is_quoted : nullptr);\n\n  ::octave_rl_set_char_is_quoted_function (fp);\n}\n\nvoid\ngnu_readline::do_set_user_accept_line_function (user_accept_line_fcn f)\n{\n  m_user_accept_line_function = f;\n\n  if (f)\n    octave_rl_add_defun (\"accept-line\", gnu_readline::command_accept_line,\n                         ::octave_rl_ctrl ('M'));\n  else\n    octave_rl_add_defun (\"accept-line\", ::octave_rl_newline,\n                         ::octave_rl_ctrl ('M'));\n}\n\ngnu_readline::completion_fcn\ngnu_readline::do_get_completion_function () const\n{\n  return m_completion_function;\n}\n\ngnu_readline::quoting_fcn\ngnu_readline::do_get_quoting_function () const\n{\n  return m_quoting_function;\n}\n\ngnu_readline::dequoting_fcn\ngnu_readline::do_get_dequoting_function () const\n{\n  return m_dequoting_function;\n}\n\ngnu_readline::char_is_quoted_fcn\ngnu_readline::do_get_char_is_quoted_function () const\n{\n  return m_char_is_quoted_function;\n}\n\ngnu_readline::user_accept_line_fcn\ngnu_readline::do_get_user_accept_line_function () const\n{\n  return m_user_accept_line_function;\n}\n\n// True if the last \"word\" of the string line (delimited by delim) is\n// an existing directory.  Used by do_completer_word_break_hook.\n\nstatic bool\nlooks_like_filename (const char *line, char delim)\n{\n  bool retval = false;\n\n  const char *s = strrchr (line, delim);\n\n  if (s)\n    {\n      // Remove incomplete component.\n      const char *f = strrchr (line, sys::file_ops::dir_sep_char ());\n\n      if (f && (s[1] == '~' || f != s))\n        {\n          // For something like \"A /b\", f==s; don't assume a file.\n\n          std::string candidate_filename = s+1;\n\n          candidate_filename = candidate_filename.substr (0, f - s);\n\n          // Handles any complete ~<username>, but doesn't expand usernames.\n\n          if (candidate_filename[0] == '~')\n            candidate_filename\n              = sys::file_ops::tilde_expand (candidate_filename);\n\n          retval = sys::dir_exists (candidate_filename);\n        }\n    }\n\n  return retval;\n}\n\n// Decide whether to interpret partial commands like \"abc/def\" as a\n// filename or division.  Return the set of delimiters appropriate for\n// the decision.\n\nchar *\ngnu_readline::do_completer_word_break_hook ()\n{\n  static char *dir_sep = octave_strdup_wrapper (R\"( '\")\");\n\n  std::string word;\n  std::string line = get_line_buffer ();\n\n  // For now, assume space or quote delimiter for file names.\n  const char *l = line.c_str ();\n\n  if (looks_like_filename (l, ' ') || looks_like_filename (l, '\\'')\n      || looks_like_filename (l, '\"'))\n    {\n      ::octave_rl_set_completer_quote_characters\n      (s_completer_quote_characters.c_str ());\n\n      return dir_sep;\n    }\n  else\n    {\n      static char *word_break_chars = nullptr;\n\n      ::octave_rl_set_completer_quote_characters (\"\");\n\n      free (word_break_chars);\n\n      word_break_chars\n        = octave_strdup_wrapper (octave_rl_get_completer_word_break_characters ());\n\n      return word_break_chars;\n    }\n}\n\nstring_vector\ngnu_readline::do_generate_filename_completions (const std::string& text)\n{\n  string_vector retval;\n\n  int n = 0;\n  int count = 0;\n\n  char *fn = nullptr;\n\n  while (1)\n    {\n      fn = ::octave_rl_filename_completion_function (text.c_str (), count);\n\n      if (fn)\n        {\n          if (count == n)\n            {\n              // Famous last words: Most large directories will not\n              // have more than a few hundred files, so we should not\n              // resize too many times even if the growth is linear...\n              n += 100;\n              retval.resize (n);\n            }\n\n          retval[count++] = fn;\n\n          free (fn);\n        }\n      else\n        break;\n    }\n\n  retval.resize (count);\n\n  return retval;\n}\n\nstd::string\ngnu_readline::do_get_line_buffer () const\n{\n  return ::octave_rl_line_buffer ();\n}\n\nstd::string\ngnu_readline::do_get_current_line () const\n{\n  std::string retval;\n  char *buf = ::octave_rl_copy_line ();\n  retval = buf;\n  free (buf);\n  return retval;\n}\n\n// Return the character (offset+1) to the left of the cursor,\n// or '\\0' if the cursor is at the start of the line.\nchar\ngnu_readline::do_get_prev_char (int offset) const\n{\n  const char *buf = ::octave_rl_line_buffer ();\n  int p = ::octave_rl_point ();\n\n  return p > offset ? buf[p - offset - 1] : '\\0';\n}\n\nvoid\ngnu_readline::do_replace_line (const std::string& text, bool clear_undo)\n{\n  ::octave_rl_replace_line (text.c_str (), clear_undo);\n}\n\nvoid\ngnu_readline::do_kill_full_line ()\n{\n  ::octave_rl_kill_full_line ();\n}\n\nvoid\ngnu_readline::do_insert_text (const std::string& text)\n{\n  ::octave_rl_insert_text (text.c_str ());\n}\n\nvoid\ngnu_readline::do_newline ()\n{\n  ::octave_rl_newline (1, '\\n');\n}\n\nvoid\ngnu_readline::do_accept_line ()\n{\n  command_accept_line (1, '\\n');\n}\n\nbool\ngnu_readline::do_undo ()\n{\n  return ::octave_rl_do_undo ();\n}\n\nvoid\ngnu_readline::do_clear_undo_list ()\n{\n  ::octave_rl_clear_undo_list ();\n}\n\nvoid\ngnu_readline::set_startup_hook (startup_hook_fcn f)\n{\n  m_previous_startup_hook = ::octave_rl_get_startup_hook ();\n\n  if (f != m_previous_startup_hook)\n    ::octave_rl_set_startup_hook (f);\n}\n\nvoid\ngnu_readline::restore_startup_hook ()\n{\n  ::octave_rl_set_startup_hook (m_previous_startup_hook);\n}\n\nvoid\ngnu_readline::set_pre_input_hook (pre_input_hook_fcn f)\n{\n  m_previous_pre_input_hook = ::octave_rl_get_pre_input_hook ();\n\n  if (f != m_previous_pre_input_hook)\n    ::octave_rl_set_pre_input_hook (f);\n}\n\nvoid\ngnu_readline::restore_pre_input_hook ()\n{\n  ::octave_rl_set_pre_input_hook (m_previous_pre_input_hook);\n}\n\nvoid\ngnu_readline::set_event_hook (event_hook_fcn f)\n{\n  m_previous_event_hook = octave_rl_get_event_hook ();\n\n  ::octave_rl_set_event_hook (f);\n}\n\nvoid\ngnu_readline::restore_event_hook ()\n{\n  ::octave_rl_set_event_hook (m_previous_event_hook);\n}\n\nvoid\ngnu_readline::do_read_init_file (const std::string& file)\n{\n  ::octave_rl_read_init_file (file.c_str ());\n}\n\nvoid\ngnu_readline::do_re_read_init_file ()\n{\n  ::octave_rl_re_read_init_file ();\n}\n\nbool\ngnu_readline::do_filename_completion_desired (bool arg)\n{\n  return ::octave_rl_filename_completion_desired (arg);\n}\n\nbool\ngnu_readline::do_filename_quoting_desired (bool arg)\n{\n  return ::octave_rl_filename_quoting_desired (arg);\n}\n\nbool\ngnu_readline::do_prefer_env_winsize (bool arg)\n{\n  return ::octave_rl_prefer_env_winsize (arg);\n}\n\nvoid\ngnu_readline::do_interrupt (bool arg)\n{\n  ::octave_rl_done (arg);\n}\n\nvoid\ngnu_readline::do_handle_interrupt_signal ()\n{\n  octave_signal_caught = false;\n  octave_interrupt_state = 0;\n\n  ::octave_rl_recover_from_interrupt ();\n\n  throw interrupt_exception ();\n}\n\nint\ngnu_readline::operate_and_get_next (int /* count */, int /* c */)\n{\n  // Accept the current line.\n\n  command_editor::accept_line ();\n\n  // Find the current line, and find the next line to use.\n\n  int x_where = command_history::where ();\n\n  int x_length = command_history::length ();\n\n  if ((command_history::is_stifled ()\n       && (x_length >= command_history::max_input_history ()))\n      || (x_where >= x_length - 1))\n    command_history::set_mark (x_where);\n  else\n    command_history::set_mark (x_where + 1);\n\n  command_editor::add_startup_hook (command_history::goto_mark);\n\n  return 0;\n}\n\nint\ngnu_readline::history_search_backward (int count, int c)\n{\n  return octave_rl_history_search_backward (count, c);\n}\n\nint\ngnu_readline::history_search_forward (int count, int c)\n{\n  return octave_rl_history_search_forward (count, c);\n}\n\nchar *\ngnu_readline::command_generator (const char *text, int state)\n{\n  char *retval = nullptr;\n\n  completion_fcn f = command_editor::get_completion_function ();\n\n  std::string tmp = f (text, state);\n\n  std::size_t len = tmp.length ();\n\n  if (len > 0)\n    {\n      retval = static_cast<char *> (std::malloc (len+1));\n\n      if (retval)\n        strcpy (retval, tmp.c_str ());\n    }\n\n  return retval;\n}\n\nchar *\ngnu_readline::command_quoter (char *text, int matches, char *qcp)\n{\n  char *retval = nullptr;\n\n  quoting_fcn f = command_editor::get_quoting_function ();\n\n  std::string tmp = f (text, matches, *qcp);\n\n  std::size_t len = tmp.length ();\n\n  if (len > 0)\n    {\n      retval = static_cast<char *> (std::malloc (len+1));\n\n      if (retval)\n        strcpy (retval, tmp.c_str ());\n    }\n\n  return retval;\n}\n\nchar *\ngnu_readline::command_dequoter (char *text, int quote)\n{\n  char *retval = nullptr;\n\n  dequoting_fcn f = command_editor::get_dequoting_function ();\n\n  std::string tmp = f (text, quote);\n\n  std::size_t len = tmp.length ();\n\n  if (len > 0)\n    {\n      retval = static_cast<char *> (std::malloc (len+1));\n\n      if (retval)\n        strcpy (retval, tmp.c_str ());\n    }\n\n  return retval;\n}\n\nint\ngnu_readline::command_char_is_quoted (char *text, int quote)\n{\n  char_is_quoted_fcn f = command_editor::get_char_is_quoted_function ();\n\n  return f (text, quote);\n}\n\nint\ngnu_readline::command_accept_line (int count, int key)\n{\n  user_accept_line_fcn f = command_editor::get_user_accept_line_function ();\n\n  if (f)\n    f (::octave_rl_line_buffer ());\n\n  ::octave_rl_redisplay ();\n\n  return ::octave_rl_newline (count, key);\n}\n\nchar **\ngnu_readline::command_completer (const char *text, int, int)\n{\n  char **matches\n    = ::octave_rl_completion_matches (text, gnu_readline::command_generator);\n\n  return matches;\n}\n\n#endif\n\nclass default_command_editor : public command_editor\n{\npublic:\n\n  default_command_editor ()\n    : command_editor (), m_input_stream (stdin), m_output_stream (stdout) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (default_command_editor)\n\n  ~default_command_editor () = default;\n\n  std::string do_readline (const std::string& prompt, bool& eof);\n\n  void do_set_input_stream (FILE *f);\n\n  FILE * do_get_input_stream ();\n\n  void do_set_output_stream (FILE *f);\n\n  FILE * do_get_output_stream ();\n\n  string_vector do_generate_filename_completions (const std::string& text);\n\n  std::string do_get_line_buffer () const;\n\n  std::string do_get_current_line () const;\n\n  char do_get_prev_char (int) const;\n\n  void do_replace_line (const std::string& text, bool clear_undo);\n\n  void do_kill_full_line ();\n\n  void do_insert_text (const std::string& text);\n\n  void do_newline ();\n\n  void do_accept_line ();\n\nprivate:\n\n  FILE *m_input_stream;\n\n  FILE *m_output_stream;\n};\n\nstd::string\ndefault_command_editor::do_readline (const std::string& prompt, bool& eof)\n{\n  std::fputs (prompt.c_str (), m_output_stream);\n  std::fflush (m_output_stream);\n\n  return fgetl (m_input_stream, eof);\n}\n\nvoid\ndefault_command_editor::do_set_input_stream (FILE *f)\n{\n  m_input_stream = f;\n}\n\nFILE *\ndefault_command_editor::do_get_input_stream ()\n{\n  return m_input_stream;\n}\n\nvoid\ndefault_command_editor::do_set_output_stream (FILE *f)\n{\n  m_output_stream = f;\n}\n\nFILE *\ndefault_command_editor::do_get_output_stream ()\n{\n  return m_output_stream;\n}\n\nstring_vector\ndefault_command_editor::do_generate_filename_completions (const std::string&)\n{\n  // FIXME\n  return string_vector ();\n}\n\nstd::string\ndefault_command_editor::do_get_line_buffer () const\n{\n  return \"\";\n}\n\nstd::string\ndefault_command_editor::do_get_current_line () const\n{\n  // FIXME\n  return \"\";\n}\n\nchar\ndefault_command_editor::do_get_prev_char (int) const\n{\n  return '\\0';\n}\n\nvoid\ndefault_command_editor::do_replace_line (const std::string&, bool)\n{\n  // FIXME\n}\n\nvoid\ndefault_command_editor::do_kill_full_line ()\n{\n  // FIXME\n}\n\nvoid\ndefault_command_editor::do_insert_text (const std::string&)\n{\n  // FIXME\n}\n\nvoid\ndefault_command_editor::do_newline ()\n{\n  // FIXME\n}\n\nvoid\ndefault_command_editor::do_accept_line ()\n{\n  // FIXME\n}\n\nbool\ncommand_editor::instance_ok ()\n{\n  bool retval = true;\n\n  if (! s_instance)\n    {\n      make_command_editor ();\n\n      if (s_instance)\n        {\n          s_instance->set_event_hook (event_handler);\n\n          singleton_cleanup_list::add (cleanup_instance);\n        }\n    }\n\n  if (! s_instance)\n    (*current_liboctave_error_handler)\n      (\"unable to create command history object!\");\n\n  return retval;\n}\n\nvoid\ncommand_editor::make_command_editor ()\n{\n#if defined (USE_READLINE)\n  s_instance = new gnu_readline ();\n#else\n  s_instance = new default_command_editor ();\n#endif\n}\n\nvoid\ncommand_editor::force_default_editor ()\n{\n  delete s_instance;\n  s_instance = new default_command_editor ();\n}\n\nvoid\ncommand_editor::set_initial_input (const std::string& text)\n{\n  if (instance_ok ())\n    s_instance->m_initial_input = text;\n}\n\nint\ncommand_editor::insert_initial_input ()\n{\n  return instance_ok () ? s_instance->do_insert_initial_input () : 0;\n}\n\nint\ncommand_editor::startup_handler ()\n{\n  // Iterate over a copy of the set to avoid problems if a hook\n  // function attempts to remove itself from the startup_hook_set.\n\n  std::set<startup_hook_fcn> hook_set = s_startup_hook_set;\n\n  for (startup_hook_fcn f : hook_set)\n    {\n      if (f)\n        f ();\n    }\n\n  return 0;\n}\n\nint\ncommand_editor::pre_input_handler ()\n{\n  // Iterate over copy of the set to avoid problems if a hook function\n  // attempts to remove itself from the pre_input_hook_set.\n\n  std::set<pre_input_hook_fcn> hook_set = s_pre_input_hook_set;\n\n  for (pre_input_hook_fcn f : hook_set)\n    {\n      if (f)\n        f ();\n    }\n\n  return 0;\n}\n\nint\ncommand_editor::event_handler ()\n{\n  if (octave_interrupt_state)\n    handle_interrupt_signal ();\n\n  event_hook_lock.lock ();\n\n  std::set<event_hook_fcn> hook_set (s_event_hook_set);\n\n  event_hook_lock.unlock ();\n\n  for (event_hook_fcn f : hook_set)\n    {\n      if (f)\n        f ();\n    }\n\n  return 0;\n}\n\nvoid\ncommand_editor::set_name (const std::string& n)\n{\n  if (instance_ok ())\n    s_instance->do_set_name (n);\n}\n\nstd::string\ncommand_editor::readline (const std::string& prompt)\n{\n  bool eof;\n\n  return readline (prompt, eof);\n}\n\nstd::string\ncommand_editor::readline (const std::string& prompt, bool& eof)\n{\n  std::string retval;\n\n  if (instance_ok ())\n    {\n      if (! s_instance->m_initial_input.empty ())\n        add_pre_input_hook (command_editor::insert_initial_input);\n\n      retval = s_instance->do_readline (prompt, eof);\n    }\n\n  return retval;\n}\n\nvoid\ncommand_editor::set_input_stream (FILE *f)\n{\n  if (instance_ok ())\n    s_instance->do_set_input_stream (f);\n}\n\nFILE *\ncommand_editor::get_input_stream ()\n{\n  return instance_ok () ? s_instance->do_get_input_stream () : nullptr;\n}\n\nvoid\ncommand_editor::set_output_stream (FILE *f)\n{\n  if (instance_ok ())\n    s_instance->do_set_output_stream (f);\n}\n\nFILE *\ncommand_editor::get_output_stream ()\n{\n  return instance_ok () ? s_instance->do_get_output_stream () : nullptr;\n}\n\nvoid\ncommand_editor::redisplay ()\n{\n  if (instance_ok ())\n    s_instance->do_redisplay ();\n}\n\nint\ncommand_editor::terminal_rows ()\n{\n  return instance_ok () ? s_instance->do_terminal_rows () : -1;\n}\n\nint\ncommand_editor::terminal_cols ()\n{\n  return instance_ok () ? s_instance->do_terminal_cols () : -1;\n}\n\nvoid\ncommand_editor::clear_screen (bool skip_redisplay)\n{\n  if (instance_ok ())\n    s_instance->do_clear_screen (skip_redisplay);\n}\n\nvoid\ncommand_editor::resize_terminal ()\n{\n  if (instance_ok ())\n    s_instance->do_resize_terminal ();\n}\n\nvoid\ncommand_editor::set_screen_size (int ht, int wd)\n{\n  if (instance_ok ())\n    s_instance->do_set_screen_size (ht, wd);\n}\n\nstd::string\ncommand_editor::decode_prompt_string (const std::string& s)\n{\n  return instance_ok () ? s_instance->do_decode_prompt_string (s) : \"\";\n}\n\nint\ncommand_editor::current_command_number ()\n{\n  return instance_ok () ? s_instance->m_command_number : 0;\n}\n\nvoid\ncommand_editor::reset_current_command_number (int n)\n{\n  if (instance_ok ())\n    s_instance->m_command_number = n;\n}\n\nvoid\ncommand_editor::increment_current_command_number ()\n{\n  if (instance_ok ())\n    s_instance->m_command_number++;\n}\n\nvoid\ncommand_editor::restore_terminal_state ()\n{\n  if (instance_ok ())\n    s_instance->do_restore_terminal_state ();\n}\n\nvoid\ncommand_editor::blink_matching_paren (bool flag)\n{\n  if (instance_ok ())\n    s_instance->do_blink_matching_paren (flag);\n}\n\nbool\ncommand_editor::erase_empty_line (bool flag)\n{\n  return instance_ok () ? s_instance->do_erase_empty_line (flag) : false;\n}\n\nvoid\ncommand_editor::set_basic_word_break_characters (const std::string& s)\n{\n  if (instance_ok ())\n    s_instance->do_set_basic_word_break_characters (s);\n}\n\nvoid\ncommand_editor::set_completer_word_break_characters (const std::string& s)\n{\n  if (instance_ok ())\n    s_instance->do_set_completer_word_break_characters (s);\n}\n\nvoid\ncommand_editor::set_basic_quote_characters (const std::string& s)\n{\n  if (instance_ok ())\n    s_instance->do_set_basic_quote_characters (s);\n}\n\nvoid\ncommand_editor::set_filename_quote_characters (const std::string& s)\n{\n  if (instance_ok ())\n    s_instance->do_set_filename_quote_characters (s);\n}\n\nvoid\ncommand_editor::set_completer_quote_characters (const std::string& s)\n{\n  if (instance_ok ())\n    s_instance->do_set_completer_quote_characters (s);\n}\n\nvoid\ncommand_editor::set_completion_append_character (char c)\n{\n  if (instance_ok ())\n    s_instance->do_set_completion_append_character (c);\n}\n\nvoid\ncommand_editor::set_completion_function (completion_fcn f)\n{\n  if (instance_ok ())\n    s_instance->do_set_completion_function (f);\n}\n\nvoid\ncommand_editor::set_quoting_function (quoting_fcn f)\n{\n  if (instance_ok ())\n    s_instance->do_set_quoting_function (f);\n}\n\nvoid\ncommand_editor::set_dequoting_function (dequoting_fcn f)\n{\n  if (instance_ok ())\n    s_instance->do_set_dequoting_function (f);\n}\n\nvoid\ncommand_editor::set_char_is_quoted_function (char_is_quoted_fcn f)\n{\n  if (instance_ok ())\n    s_instance->do_set_char_is_quoted_function (f);\n}\n\nvoid\ncommand_editor::set_user_accept_line_function (user_accept_line_fcn f)\n{\n  if (instance_ok ())\n    s_instance->do_set_user_accept_line_function (f);\n}\n\ncommand_editor::completion_fcn\ncommand_editor::get_completion_function ()\n{\n  return instance_ok () ? s_instance->do_get_completion_function () : nullptr;\n}\n\ncommand_editor::quoting_fcn\ncommand_editor::get_quoting_function ()\n{\n  return instance_ok () ? s_instance->do_get_quoting_function () : nullptr;\n}\n\ncommand_editor::dequoting_fcn\ncommand_editor::get_dequoting_function ()\n{\n  return instance_ok () ? s_instance->do_get_dequoting_function () : nullptr;\n}\n\ncommand_editor::char_is_quoted_fcn\ncommand_editor::get_char_is_quoted_function ()\n{\n  return (instance_ok ()\n          ? s_instance->do_get_char_is_quoted_function () : nullptr);\n}\n\ncommand_editor::user_accept_line_fcn\ncommand_editor::get_user_accept_line_function ()\n{\n  return (instance_ok ()\n          ? s_instance->do_get_user_accept_line_function () : nullptr);\n}\n\nstring_vector\ncommand_editor::generate_filename_completions (const std::string& text)\n{\n  return (instance_ok ()\n          ? s_instance->do_generate_filename_completions (text)\n          : string_vector ());\n}\n\nstd::string\ncommand_editor::get_line_buffer ()\n{\n  return instance_ok () ? s_instance->do_get_line_buffer () : \"\";\n}\n\nstd::string\ncommand_editor::get_current_line ()\n{\n  return instance_ok () ? s_instance->do_get_current_line () : \"\";\n}\n\n// Return the character (offset+1) to the left of the cursor,\n// or '\\0' if the cursor is at the start of the line.\nchar\ncommand_editor::get_prev_char (int offset)\n{\n  return instance_ok () ? s_instance->do_get_prev_char (offset) : '\\0';\n}\n\nvoid\ncommand_editor::replace_line (const std::string& text, bool clear_undo)\n{\n  if (instance_ok ())\n    s_instance->do_replace_line (text, clear_undo);\n}\n\nvoid\ncommand_editor::kill_full_line ()\n{\n  if (instance_ok ())\n    s_instance->do_kill_full_line ();\n}\n\nvoid\ncommand_editor::insert_text (const std::string& text)\n{\n  if (instance_ok ())\n    s_instance->do_insert_text (text);\n}\n\nvoid\ncommand_editor::newline ()\n{\n  if (instance_ok ())\n    s_instance->do_newline ();\n}\n\nvoid\ncommand_editor::accept_line ()\n{\n  if (instance_ok ())\n    s_instance->do_accept_line ();\n}\n\nbool\ncommand_editor::undo ()\n{\n  return instance_ok () ? s_instance->do_undo () : false;\n}\n\nvoid\ncommand_editor::clear_undo_list ()\n{\n  if (instance_ok ())\n    s_instance->do_clear_undo_list ();\n}\n\nvoid\ncommand_editor::add_startup_hook (startup_hook_fcn f)\n{\n  if (instance_ok ())\n    {\n      s_startup_hook_set.insert (f);\n\n      s_instance->set_startup_hook (startup_handler);\n    }\n}\n\nvoid\ncommand_editor::remove_startup_hook (startup_hook_fcn f)\n{\n  if (instance_ok ())\n    {\n      auto p = s_startup_hook_set.find (f);\n\n      if (p != s_startup_hook_set.end ())\n        s_startup_hook_set.erase (p);\n\n      if (s_startup_hook_set.empty ())\n        s_instance->restore_startup_hook ();\n    }\n}\n\nvoid\ncommand_editor::add_pre_input_hook (pre_input_hook_fcn f)\n{\n  if (instance_ok ())\n    {\n      s_pre_input_hook_set.insert (f);\n\n      s_instance->set_pre_input_hook (pre_input_handler);\n    }\n}\n\nvoid\ncommand_editor::remove_pre_input_hook (pre_input_hook_fcn f)\n{\n  if (instance_ok ())\n    {\n      auto p = s_pre_input_hook_set.find (f);\n\n      if (p != s_pre_input_hook_set.end ())\n        s_pre_input_hook_set.erase (p);\n\n      if (s_pre_input_hook_set.empty ())\n        s_instance->restore_pre_input_hook ();\n    }\n}\n\nvoid\ncommand_editor::add_event_hook (event_hook_fcn f)\n{\n  autolock guard (event_hook_lock);\n\n  s_event_hook_set.insert (f);\n}\n\nvoid\ncommand_editor::remove_event_hook (event_hook_fcn f)\n{\n  autolock guard (event_hook_lock);\n\n  auto p = s_event_hook_set.find (f);\n\n  if (p != s_event_hook_set.end ())\n    s_event_hook_set.erase (p);\n\n}\n\nvoid\ncommand_editor::run_event_hooks ()\n{\n  event_handler ();\n}\n\nvoid\ncommand_editor::read_init_file (const std::string& file_arg)\n{\n  if (instance_ok ())\n    {\n      std::string file = sys::file_ops::tilde_expand (file_arg);\n\n      s_instance->do_read_init_file (file);\n    }\n}\n\nvoid\ncommand_editor::re_read_init_file ()\n{\n  if (instance_ok ())\n    s_instance->do_re_read_init_file ();\n}\n\nbool\ncommand_editor::filename_completion_desired (bool arg)\n{\n  return (instance_ok ()\n          ? s_instance->do_filename_completion_desired (arg) : false);\n}\n\nbool\ncommand_editor::filename_quoting_desired (bool arg)\n{\n  return (instance_ok ())\n         ? s_instance->do_filename_quoting_desired (arg) : false;\n}\n\nbool\ncommand_editor::prefer_env_winsize (bool arg)\n{\n  return instance_ok () ? s_instance->do_prefer_env_winsize (arg) : false;\n}\n\nbool\ncommand_editor::interrupt (bool arg)\n{\n  bool retval;\n\n  if (instance_ok ())\n    {\n      // Return the current interrupt state.\n      retval = s_instance->m_interrupted;\n\n      s_instance->do_interrupt (arg);\n\n      s_instance->m_interrupted = arg;\n    }\n  else\n    retval = false;\n\n  return retval;\n}\n\nvoid\ncommand_editor::interrupt_event_loop (bool arg)\n{\n  if (instance_ok ())\n    s_instance->do_interrupt_event_loop (arg);\n}\n\nbool\ncommand_editor::event_loop_interrupted ()\n{\n  return instance_ok () ? s_instance->do_event_loop_interrupted  () : false;\n}\n\nvoid\ncommand_editor::handle_interrupt_signal ()\n{\n  if (instance_ok ())\n    s_instance->do_handle_interrupt_signal ();\n}\n\n// Return a string which will be printed as a prompt.  The string may\n// contain special characters which are decoded as follows:\n//\n//      \\a      bell (ascii 07)\n//      \\d      the date\n//      \\e      escape (ascii 033)\n//      \\h      the hostname up to the first '.'\n//      \\H      the hostname\n//      \\n      CRLF\n//      \\r      CR\n//      \\s      the name of the shell (program)\n//      \\t      the time\n//      \\T      the time in 12-hour hh:mm:ss format\n//      \\@      the time in 12-hour hh:mm am/pm format\n//      \\A      the time in 24-hour hh:mm format\n//      \\u      your username\n//      \\w      the current working directory\n//      \\W      the last element of PWD\n//      \\!      the history number of this command\n//      \\#      the command number of this command\n//      \\$      a $ or a # if you are root\n//      \\nnn    character code nnn in octal\n//      \\\\      a backslash\n//      \\[      begin a sequence of non-printing chars\n//      \\]      end a sequence of non-printing chars\n\nstd::string\ncommand_editor::do_decode_prompt_string (const std::string& s)\n{\n  std::string retval;\n  std::string tmpstr;\n  std::size_t i = 0;\n  std::size_t slen = s.length ();\n  int c;\n\n  while (i < slen)\n    {\n      c = s[i];\n\n      i++;\n\n      if (c == '\\\\')\n        {\n          c = s[i];\n\n          switch (c)\n            {\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n              // Maybe convert an octal number.\n              {\n                int n = read_octal (s.substr (i, 3));\n\n                tmpstr = '\\\\';\n\n                if (n != -1)\n                  {\n                    tmpstr[0] = n;\n                    i += 2;   // i++ makes this += 3 later\n                  }\n\n                break;\n              }\n\n            case 'a':\n              {\n                tmpstr = '\\a';\n\n                break;\n              }\n\n            case 'd':\n            case 't':\n            case 'T':\n            case '@':\n            case 'A':\n              // Make the current time/date into a string.\n              {\n                sys::localtime now;\n\n                if (c == 'd')\n                  tmpstr = now.strftime (\"%a %b %d\");\n                else if (c == 't')\n                  tmpstr = now.strftime (\"%H:%M:%S\");\n                else if (c == 'T')\n                  tmpstr = now.strftime (\"%I:%M:%S\");\n                else if (c == '@')\n                  tmpstr = now.strftime (\"%I:%M %p\");\n                else // (c == 'A')\n                  tmpstr = now.strftime (\"%H:%M\");\n\n                break;\n              }\n\n            case 'e':\n              {\n                tmpstr = '\\033';\n\n                break;\n              }\n\n            case 'h':\n              {\n                tmpstr = sys::env::get_host_name ();\n\n                std::size_t pos = tmpstr.find ('.');\n\n                if (pos != std::string::npos)\n                  tmpstr.resize (pos);\n\n                break;\n              }\n\n            case 'H':\n              {\n                tmpstr = sys::env::get_host_name ();\n\n                break;\n              }\n\n            case 'n':\n              {\n                tmpstr = newline_chars ();\n\n                break;\n              }\n\n            case 'r':\n              {\n                tmpstr = '\\r';\n\n                break;\n              }\n\n            case 's':\n              {\n                tmpstr = sys::env::get_program_name ();\n                tmpstr = sys::env::base_pathname (tmpstr);\n\n                break;\n              }\n\n            case 'u':\n              {\n                tmpstr = sys::env::get_user_name ();\n\n                break;\n              }\n\n            case 'w':\n            case 'W':\n              {\n                try\n                  {\n                    tmpstr = sys::env::get_current_directory ();\n                  }\n                catch (const execution_exception&)\n                  {\n                    tmpstr = \"\";\n                  }\n\n                std::string home_dir = sys::env::get_home_directory ();\n\n                if (c == 'W' && (home_dir.empty () || tmpstr != home_dir))\n                  {\n                    if (tmpstr != \"/\" && tmpstr != \"//\")\n                      {\n                        std::size_t pos = tmpstr.rfind ('/');\n\n                        if (pos != std::string::npos && pos != 0)\n                          tmpstr = tmpstr.substr (pos + 1);\n                      }\n                  }\n                else\n                  tmpstr = sys::env::polite_directory_format (tmpstr);\n\n                break;\n              }\n\n            case '!':\n              {\n                char number_buffer[32];\n                int num = command_history::current_number ();\n                if (num > 0)\n                  snprintf (number_buffer, 32, \"%d\", num);\n                else\n                  strcpy (number_buffer, \"!\");\n                tmpstr = number_buffer;\n\n                break;\n              }\n\n            case '#':\n              {\n                char number_buffer[32];\n                snprintf (number_buffer, 32, \"%d\", m_command_number);\n                tmpstr = number_buffer;\n\n                break;\n              }\n\n            case '$':\n              {\n                tmpstr = (octave_geteuid_wrapper () == 0 ? '#' : '$');\n                break;\n              }\n\n#if defined (USE_READLINE)\n            case '[':\n            case ']':\n              {\n                tmpstr.resize (1);\n\n                tmpstr[0] = ((c == '[')\n                             ? ::octave_rl_prompt_start_ignore ()\n                             : ::octave_rl_prompt_end_ignore ());\n\n                break;\n              }\n#endif\n\n            case '\\\\':\n              {\n                tmpstr = '\\\\';\n\n                break;\n              }\n\n            default:\n              {\n                tmpstr = \"\\\\ \";\n                tmpstr[1] = c;\n\n                break;\n              }\n            }\n\n          retval.append (tmpstr);\n          i++;   // Move past processed escape character\n        }\n      else\n        retval += c;\n    }\n\n  return retval;\n}\n\nint\ncommand_editor::do_insert_initial_input ()\n{\n  std::string input = m_initial_input;\n\n  m_initial_input = \"\";\n\n  do_insert_text (input);\n\n  // Is it really right to redisplay here?\n  do_redisplay ();\n\n  return 0;\n}\n\n// Return the octal number parsed from STRING, or -1 to indicate that\n// the string contained a bad number.\n\nint\ncommand_editor::read_octal (const std::string& s)\n{\n  int result = 0;\n  int digits = 0;\n\n  std::size_t i = 0;\n  std::size_t slen = s.length ();\n\n  while (i < slen && s[i] >= '0' && s[i] < '8')\n    {\n      digits++;\n      result = (result * 8) + s[i] - '0';\n      i++;\n    }\n\n  if (! digits || result > 0777 || i < slen)\n    result = -1;\n\n  return result;\n}\n\nvoid\ncommand_editor::error (int err_num)\n{\n  (*current_liboctave_error_handler) (\"%s\", std::strerror (err_num));\n}\n\nvoid\ncommand_editor::error (const std::string& s)\n{\n  (*current_liboctave_error_handler) (\"%s\", s.c_str ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/cmd-edit.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cmd_edit_h)\n#define octave_cmd_edit_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdio>\n\n#include <set>\n#include <string>\n\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API command_editor\n{\nprotected:\n\n  command_editor ()\n    : m_command_number (1), m_rows (24), m_cols (80), m_interrupted (false),\n      m_interrupt_event_loop (false), m_initial_input ()\n  { }\n\npublic:\n\n  typedef int (*startup_hook_fcn) ();\n\n  typedef int (*pre_input_hook_fcn) ();\n\n  typedef int (*event_hook_fcn) ();\n\n  typedef std::string (*completion_fcn) (const std::string&, int);\n\n  typedef char *(*completion_hook_fcn) ();\n\n  typedef std::string (*quoting_fcn) (const std::string&, int, char);\n\n  typedef std::string (*dequoting_fcn) (const std::string&, int);\n\n  typedef int (*char_is_quoted_fcn) (const std::string&, int);\n\n  typedef void (*user_accept_line_fcn) (const std::string&);\n\n  OCTAVE_DISABLE_COPY_MOVE (command_editor)\n\n  virtual ~command_editor () = default;\n\n  static void set_name (const std::string& n);\n\n  static std::string readline (const std::string& prompt);\n\n  static std::string readline (const std::string& prompt, bool& eof);\n\n  static void set_input_stream (FILE *f);\n\n  static FILE * get_input_stream ();\n\n  static void set_output_stream (FILE *f);\n\n  static FILE * get_output_stream ();\n\n  static void redisplay ();\n\n  static int terminal_rows ();\n\n  static int terminal_cols ();\n\n  static void clear_screen (bool skip_redisplay = false);\n\n  static void resize_terminal ();\n\n  static void set_screen_size (int ht, int wd);\n\n  static std::string decode_prompt_string (const std::string& s);\n\n  static void restore_terminal_state ();\n\n  static void blink_matching_paren (bool flag);\n\n  static bool erase_empty_line (bool flag);\n\n  static void set_basic_word_break_characters (const std::string& s);\n\n  static void set_completer_word_break_characters (const std::string& s);\n\n  static void set_basic_quote_characters (const std::string& s);\n\n  static void set_filename_quote_characters (const std::string& s);\n\n  static void set_completer_quote_characters (const std::string& s);\n\n  static void set_completion_append_character (char c);\n\n  static void set_completion_function (completion_fcn f);\n\n  static void set_quoting_function (quoting_fcn f);\n\n  static void set_dequoting_function (dequoting_fcn f);\n\n  static void set_char_is_quoted_function (char_is_quoted_fcn f);\n\n  static void set_user_accept_line_function (user_accept_line_fcn f);\n\n  static completion_fcn get_completion_function ();\n\n  static quoting_fcn get_quoting_function ();\n\n  static dequoting_fcn get_dequoting_function ();\n\n  static char_is_quoted_fcn get_char_is_quoted_function ();\n\n  static user_accept_line_fcn get_user_accept_line_function ();\n\n  static string_vector\n  generate_filename_completions (const std::string& text);\n\n  static std::string get_line_buffer ();\n\n  static std::string get_current_line ();\n\n  static char get_prev_char (int);\n\n  static void replace_line (const std::string& text, bool clear_undo = true);\n\n  static void kill_full_line ();\n\n  static void insert_text (const std::string& text);\n\n  static void newline ();\n\n  static void accept_line ();\n\n  static bool undo ();\n\n  static void clear_undo_list ();\n\n  static void add_startup_hook (startup_hook_fcn f);\n\n  static void remove_startup_hook (startup_hook_fcn f);\n\n  static void add_pre_input_hook (pre_input_hook_fcn f);\n\n  static void remove_pre_input_hook (pre_input_hook_fcn f);\n\n  static void add_event_hook (event_hook_fcn f);\n\n  static void remove_event_hook (event_hook_fcn f);\n\n  static void run_event_hooks ();\n\n  static void read_init_file (const std::string& file = \"\");\n\n  static void re_read_init_file ();\n\n  static bool filename_completion_desired (bool);\n\n  static bool filename_quoting_desired (bool);\n\n  static bool prefer_env_winsize (bool);\n\n  static bool interrupt (bool = true);\n\n  static void interrupt_event_loop (bool flag = true);\n\n  static bool event_loop_interrupted ();\n\n  static int current_command_number ();\n\n  static void reset_current_command_number (int n);\n\n  static void increment_current_command_number ();\n\n  static void force_default_editor ();\n\n  static void set_initial_input (const std::string& text);\n\n  static int insert_initial_input ();\n\nprivate:\n\n  static bool instance_ok ();\n\n  static void make_command_editor ();\n\n  static int startup_handler ();\n\n  static int pre_input_handler ();\n\n  static int event_handler ();\n\n  static void cleanup_instance ()\n  {\n    delete s_instance;\n    s_instance = nullptr;\n  }\n\n  static void handle_interrupt_signal ();\n\n  //--------\n\n  static command_editor *s_instance;  // the real thing.\n\n  static std::set<startup_hook_fcn> s_startup_hook_set;\n  static std::set<pre_input_hook_fcn> s_pre_input_hook_set;\n  static std::set<event_hook_fcn> s_event_hook_set;\n\nprotected:\n\n  // To use something other than the GNU readline library, derive a new\n  // class from command_editor, overload these functions as\n  // necessary, and make instance point to the new class.\n\n  virtual void do_set_name (const std::string&) { }\n\n  std::string do_readline (const std::string& prompt)\n  {\n    bool eof;\n\n    return do_readline (prompt, eof);\n  }\n\n  virtual std::string do_readline (const std::string&, bool&) = 0;\n\n  virtual void do_set_input_stream (FILE *) = 0;\n\n  virtual FILE * do_get_input_stream () = 0;\n\n  virtual void do_set_output_stream (FILE *) = 0;\n\n  virtual FILE * do_get_output_stream () = 0;\n\n  virtual void do_redisplay () { }\n\n  virtual int do_terminal_rows () { return m_rows; }\n\n  virtual int do_terminal_cols () { return m_cols; }\n\n  virtual void do_clear_screen (bool) { }\n\n  virtual void do_resize_terminal () { }\n\n  virtual void do_set_screen_size (int ht, int wd)\n  {\n    m_rows = ht;\n    m_cols = wd;\n  }\n\n  virtual std::string do_decode_prompt_string (const std::string&);\n\n  virtual std::string newline_chars () { return \"\\n\"; }\n\n  virtual void do_restore_terminal_state () { }\n\n  virtual void do_blink_matching_paren (bool) { }\n\n  virtual bool do_erase_empty_line (bool) { return false; }\n\n  virtual void do_set_basic_word_break_characters (const std::string&) { }\n\n  virtual void do_set_completer_word_break_characters (const std::string&) { }\n\n  virtual void do_set_completer_word_break_hook (completion_hook_fcn) { }\n\n  virtual void do_set_basic_quote_characters (const std::string&) { }\n\n  virtual void do_set_filename_quote_characters (const std::string&) { }\n\n  virtual void do_set_completer_quote_characters (const std::string&) { }\n\n  virtual void do_set_completion_append_character (char) { }\n\n  virtual void do_set_completion_function (completion_fcn) { }\n\n  virtual void do_set_quoting_function (quoting_fcn) { }\n\n  virtual void do_set_dequoting_function (dequoting_fcn) { }\n\n  virtual void do_set_char_is_quoted_function (char_is_quoted_fcn) { }\n\n  virtual void do_set_user_accept_line_function (user_accept_line_fcn) { }\n\n  virtual completion_fcn do_get_completion_function () const\n  { return nullptr; }\n\n  virtual quoting_fcn do_get_quoting_function () const\n  { return nullptr; }\n\n  virtual dequoting_fcn do_get_dequoting_function () const\n  { return nullptr; }\n\n  virtual char_is_quoted_fcn do_get_char_is_quoted_function () const\n  { return nullptr; }\n\n  virtual user_accept_line_fcn do_get_user_accept_line_function () const\n  { return nullptr; }\n\n  virtual string_vector\n  do_generate_filename_completions (const std::string& text) = 0;\n\n  virtual std::string do_get_line_buffer () const = 0;\n\n  virtual std::string do_get_current_line () const = 0;\n\n  virtual char do_get_prev_char (int) const = 0;\n\n  virtual void\n  do_replace_line (const std::string& text, bool clear_undo) = 0;\n\n  virtual void do_kill_full_line () = 0;\n\n  virtual void do_insert_text (const std::string& text) = 0;\n\n  virtual void do_newline () = 0;\n\n  virtual void do_accept_line () = 0;\n\n  virtual bool do_undo () { return false; }\n\n  virtual void do_clear_undo_list () { }\n\n  virtual void set_startup_hook (startup_hook_fcn) { }\n\n  virtual void restore_startup_hook () { }\n\n  virtual void set_pre_input_hook (pre_input_hook_fcn) { }\n\n  virtual void restore_pre_input_hook () { }\n\n  virtual void set_event_hook (event_hook_fcn) { }\n\n  virtual void restore_event_hook () { }\n\n  virtual void do_read_init_file (const std::string&) { }\n\n  virtual void do_re_read_init_file () { }\n\n  virtual bool do_filename_completion_desired (bool) { return false; }\n\n  virtual bool do_filename_quoting_desired (bool) { return false; }\n\n  virtual bool do_prefer_env_winsize (bool) { return false; }\n\n  virtual void do_interrupt (bool) { }\n\n  virtual void do_handle_interrupt_signal () { }\n\n  void do_interrupt_event_loop (bool arg) { m_interrupt_event_loop = arg; }\n\n  bool do_event_loop_interrupted () const\n  { return m_interrupt_event_loop; }\n\n  int do_insert_initial_input ();\n\n  int read_octal (const std::string& s);\n\n  void error (int);\n\n  void error (const std::string&);\n\n  // The current command number.\n  int m_command_number;\n\n  int m_rows;\n  int m_cols;\n\n  bool m_interrupted;\n\n  bool m_interrupt_event_loop;\n\n  std::string m_initial_input;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/cmd-hist.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstring>\n\n#include <fstream>\n#include <sstream>\n#include <string>\n\n#include \"cmd-edit.h\"\n#include \"cmd-hist.h\"\n#include \"file-ops.h\"\n#include \"oct-error.h\"\n#include \"oct-sysdep.h\"\n#include \"singleton-cleanup.h\"\n#include \"str-vec.h\"\n\n#if defined (USE_READLINE)\n#include <cstdlib>\n\n#include \"oct-rl-hist.h\"\n\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ncommand_history *command_history::s_instance = nullptr;\n\n#if defined (USE_READLINE)\n\nclass gnu_history : public command_history\n{\npublic:\n\n  gnu_history ()\n    : command_history (), m_mark (0) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (gnu_history)\n\n  ~gnu_history () = default;\n\n  void do_process_histcontrol (const std::string&);\n\n  std::string do_histcontrol () const;\n\n  bool do_add (const std::string&);\n\n  void do_remove (int);\n\n  void do_clear ();\n\n  int do_where () const;\n\n  int do_length () const;\n\n  int do_max_input_history () const;\n\n  int do_base () const;\n\n  int do_current_number () const;\n\n  void do_stifle (int);\n\n  int do_unstifle ();\n\n  int do_is_stifled () const;\n\n  void do_set_mark (int);\n\n  int do_goto_mark ();\n\n  void do_read (const std::string&, bool);\n\n  void do_read_range (const std::string&, int, int, bool);\n\n  void do_write (const std::string&) const;\n\n  void do_append (const std::string&);\n\n  void do_truncate_file (const std::string&, int) const;\n\n  string_vector do_list (int, bool) const;\n\n  std::string do_get_entry (int) const;\n\n  void do_replace_entry (int, const std::string&);\n\n  void do_clean_up_and_save (const std::string&, int);\n\nprivate:\n\n  int m_mark;\n};\n\nvoid\ngnu_history::do_process_histcontrol (const std::string& control_arg)\n{\n  m_history_control = 0;\n\n  std::size_t len = control_arg.length ();\n  std::size_t beg = 0;\n\n  while (beg < len)\n    {\n      if (control_arg[beg] == ':')\n        beg++;\n      else\n        {\n          std::size_t end = control_arg.find (':', beg);\n\n          if (end == std::string::npos)\n            end = len;\n\n          std::string tmp = control_arg.substr (beg, end-beg);\n\n          if (tmp == \"erasedups\")\n            m_history_control |= HC_ERASEDUPS;\n          else if (tmp == \"ignoreboth\")\n            m_history_control |= (HC_IGNDUPS | HC_IGNSPACE);\n          else if (tmp == \"ignoredups\")\n            m_history_control |= HC_IGNDUPS;\n          else if (tmp == \"ignorespace\")\n            m_history_control |= HC_IGNSPACE;\n          else\n            (*current_liboctave_warning_with_id_handler)\n              (\"Octave:history-control\",\n               \"unknown histcontrol directive %s\", tmp.c_str ());\n\n          if (end != std::string::npos)\n            beg = end + 1;\n        }\n    }\n}\n\nstd::string\ngnu_history::do_histcontrol () const\n{\n  // FIXME: instead of reconstructing this value, should we just save\n  // the string we were given when constructing the command_history object?\n\n  std::string retval;\n\n  if (m_history_control & HC_IGNSPACE)\n    retval.append (\"ignorespace\");\n\n  if (m_history_control & HC_IGNDUPS)\n    {\n      if (retval.length () > 0)\n        retval += ':';\n\n      retval.append (\"ignoredups\");\n    }\n\n  if (m_history_control & HC_ERASEDUPS)\n    {\n      if (retval.length () > 0)\n        retval += ':';\n\n      retval.append (\"erasedups\");\n    }\n\n  return retval;\n}\n\nbool\ngnu_history::do_add (const std::string& s)\n{\n  if (! do_ignoring_entries ())\n    {\n      if (s.empty ()\n          || (s.length () == 1 && (s[0] == '\\r' || s[0] == '\\n')))\n        return false;\n\n      // Strip newline before adding to list\n      std::string stmp = s;\n      if (stmp.back () == '\\n')\n        stmp.pop_back ();\n\n      int added = ::octave_add_history (stmp.c_str (), m_history_control);\n      m_lines_this_session += added;\n      return added > 0 ? true : false;\n    }\n  return false;\n}\n\nvoid\ngnu_history::do_remove (int n)\n{\n  ::octave_remove_history (n);\n}\n\nvoid\ngnu_history::do_clear ()\n{\n  ::octave_clear_history ();\n}\n\nint\ngnu_history::do_where () const\n{\n  return ::octave_where_history ();\n}\n\nint\ngnu_history::do_length () const\n{\n  return ::octave_history_length ();\n}\n\nint\ngnu_history::do_max_input_history () const\n{\n  return ::octave_max_input_history ();\n}\n\nint\ngnu_history::do_base () const\n{\n  return ::octave_history_base ();\n}\n\nint\ngnu_history::do_current_number () const\n{\n  return m_size > 0 ? do_base () + do_where () : -1;\n}\n\nvoid\ngnu_history::do_stifle (int n)\n{\n  ::octave_stifle_history (n);\n}\n\nint\ngnu_history::do_unstifle ()\n{\n  return ::octave_unstifle_history ();\n}\n\nint\ngnu_history::do_is_stifled () const\n{\n  return ::octave_history_is_stifled ();\n}\n\nvoid\ngnu_history::do_set_mark (int n)\n{\n  m_mark = n;\n}\n\nint\ngnu_history::do_goto_mark ()\n{\n  if (m_mark)\n    {\n      char *line = ::octave_history_goto_mark (m_mark);\n\n      if (line)\n        {\n          command_editor::insert_text (line);\n\n          command_editor::clear_undo_list ();\n        }\n    }\n\n  m_mark = 0;\n\n  // FIXME: for operate_and_get_next.\n  command_editor::remove_startup_hook (command_history::goto_mark);\n\n  return 0;\n}\n\nvoid\ngnu_history::do_read (const std::string& f, bool must_exist)\n{\n  if (! f.empty ())\n    {\n      int status = ::octave_read_history (f.c_str ());\n\n      if (status != 0 && must_exist)\n        {\n          std::string msg = \"reading file '\" + f + \"'\";\n\n          error (status, msg);\n        }\n      else\n        {\n          m_lines_in_file = do_where ();\n\n          ::octave_using_history ();\n        }\n    }\n  else\n    error (\"gnu_history::read: missing filename\");\n}\n\nvoid\ngnu_history::do_read_range (const std::string& f, int from, int to,\n                            bool must_exist)\n{\n  if (from < 0)\n    from = m_lines_in_file;\n\n  if (! f.empty ())\n    {\n      int status = ::octave_read_history_range (f.c_str (), from, to);\n\n      if (status != 0 && must_exist)\n        {\n          std::ostringstream buf;\n          buf << \"reading lines \" << from << \" to \" << to\n              << \" from file '\" << f << \"'\";\n\n          error (status, buf.str ());\n        }\n      else\n        {\n          m_lines_in_file = do_where ();\n\n          ::octave_using_history ();\n        }\n    }\n  else\n    error (\"gnu_history::read_range: missing filename\");\n}\n\nvoid\ngnu_history::do_write (const std::string& f_arg) const\n{\n  if (m_initialized)\n    {\n      std::string f = f_arg;\n\n      if (f.empty ())\n        f = m_file;\n\n      if (! f.empty ())\n        {\n          // Try to create the folder if it does not exist\n          std::string hist_dir = sys::file_ops::dirname (f);\n          if (! hist_dir.empty ())\n            {\n              if (! sys::dir_exists (hist_dir)\n                  && (sys::recursive_mkdir (hist_dir, 0777) < 0))\n                (*current_liboctave_error_handler)\n                  (\"%s: Could not create directory \\\"%s\\\" for history\",\n                   \"gnu_history::do_write\", hist_dir.c_str ());\n            }\n\n          int status = ::octave_write_history (f.c_str ());\n\n          if (status != 0)\n            {\n              std::string msg = \"writing file '\" + f + \"'\";\n\n              error (status, msg);\n            }\n        }\n      else\n        error (\"gnu_history::write: missing filename\");\n    }\n}\n\nvoid\ngnu_history::do_append (const std::string& f_arg)\n{\n  if (m_initialized)\n    {\n      if (m_lines_this_session)\n        {\n          if (m_lines_this_session < do_where ())\n            {\n              // Create file if it doesn't already exist.\n\n              std::string f = f_arg;\n\n              if (f.empty ())\n                f = m_file;\n\n              if (! f.empty ())\n                {\n                  if (! sys::file_exists (f))\n                    {\n                      std::ofstream tmp = sys::ofstream (f, std::ios::out);\n                      tmp.close ();\n                    }\n\n                  int status\n                    = ::octave_append_history (m_lines_this_session, f.c_str ());\n\n                  if (status != 0)\n                    {\n                      std::string msg = \"appending to file '\" + f_arg + \"'\";\n\n                      error (status, msg);\n                    }\n                  else\n                    m_lines_in_file += m_lines_this_session;\n\n                  m_lines_this_session = 0;\n                }\n              else\n                error (\"gnu_history::append: missing filename\");\n            }\n        }\n    }\n}\n\nvoid\ngnu_history::do_truncate_file (const std::string& f_arg, int n) const\n{\n  if (m_initialized)\n    {\n      std::string f = f_arg;\n\n      if (f.empty ())\n        f = m_file;\n\n      if (! f.empty ())\n        ::octave_history_truncate_file (f.c_str (), n);\n      else\n        error (\"gnu_history::truncate_file: missing filename\");\n    }\n}\n\nstring_vector\ngnu_history::do_list (int limit, bool number_lines) const\n{\n  string_vector retval;\n\n  if (limit)\n    retval = ::octave_history_list (limit, number_lines);\n\n  return retval;\n}\n\nstd::string\ngnu_history::do_get_entry (int n) const\n{\n  std::string retval;\n\n  char *line = ::octave_history_get (do_base () + n);\n\n  if (line)\n    retval = line;\n\n  return retval;\n}\n\nvoid\ngnu_history::do_replace_entry (int which, const std::string& line)\n{\n  ::octave_replace_history_entry (which, line.c_str ());\n}\n\nvoid\ngnu_history::do_clean_up_and_save (const std::string& f_arg, int n)\n{\n  if (m_initialized)\n    {\n      std::string f = f_arg;\n\n      if (f.empty ())\n        f = m_file;\n\n      if (! f.empty ())\n        {\n          if (n < 0)\n            n = m_size;\n\n          stifle (n);\n\n          do_write (f.c_str ());\n        }\n      else\n        error (\"gnu_history::clean_up_and_save: missing filename\");\n    }\n}\n\n#endif\n\nbool\ncommand_history::instance_ok ()\n{\n  bool retval = true;\n\n  if (! s_instance)\n    {\n      make_command_history ();\n\n      if (s_instance)\n        singleton_cleanup_list::add (cleanup_instance);\n    }\n\n  if (! s_instance)\n    (*current_liboctave_error_handler)\n      (\"unable to create command history object!\");\n\n  return retval;\n}\n\nvoid\ncommand_history::make_command_history ()\n{\n#if defined (USE_READLINE)\n  s_instance = new gnu_history ();\n#else\n  s_instance = new command_history ();\n#endif\n}\n\nvoid\ncommand_history::initialize (bool read_history_file,\n                             const std::string& f_arg, int sz,\n                             const std::string& control_arg)\n{\n  if (instance_ok ())\n    s_instance->do_initialize (read_history_file, f_arg, sz, control_arg);\n}\n\nbool\ncommand_history::is_initialized ()\n{\n  // We just want to check the status of an existing instance, not\n  // create one.\n  return s_instance && s_instance->do_is_initialized ();\n}\n\nvoid\ncommand_history::set_file (const std::string& f_arg)\n{\n  if (instance_ok ())\n    {\n      std::string f = sys::file_ops::tilde_expand (f_arg);\n\n      s_instance->do_set_file (f);\n    }\n}\n\nstd::string\ncommand_history::file ()\n{\n  return instance_ok () ? s_instance->do_file () : \"\";\n}\n\nvoid\ncommand_history::process_histcontrol (const std::string& control_arg)\n{\n  if (instance_ok ())\n    s_instance->do_process_histcontrol (control_arg);\n}\n\nstd::string\ncommand_history::histcontrol ()\n{\n  return instance_ok () ? s_instance->do_histcontrol () : \"\";\n}\n\nvoid\ncommand_history::set_size (int n)\n{\n  if (instance_ok ())\n    s_instance->do_set_size (n);\n}\n\nint\ncommand_history::size ()\n{\n  return instance_ok () ? s_instance->do_size () : 0;\n}\n\nvoid\ncommand_history::ignore_entries (bool flag)\n{\n  if (instance_ok ())\n    s_instance->do_ignore_entries (flag);\n}\n\nbool\ncommand_history::ignoring_entries ()\n{\n  return instance_ok () ? s_instance->do_ignoring_entries () : false;\n}\n\nbool\ncommand_history::add (const std::string& s)\n{\n  if (instance_ok ())\n    return s_instance->do_add (s);\n  return false;\n}\n\nvoid\ncommand_history::remove (int n)\n{\n  if (instance_ok ())\n    s_instance->do_remove (n);\n}\n\nvoid\ncommand_history::clear ()\n{\n  if (instance_ok ())\n    s_instance->do_clear ();\n}\n\nint\ncommand_history::where ()\n{\n  return instance_ok () ? s_instance->do_where () : 0;\n}\n\nint\ncommand_history::length ()\n{\n  return instance_ok () ? s_instance->do_length () : 0;\n}\n\nint\ncommand_history::max_input_history ()\n{\n  return instance_ok () ? s_instance->do_max_input_history () : 0;\n}\n\nint\ncommand_history::base ()\n{\n  return instance_ok () ? s_instance->do_base () : 0;\n}\n\nint\ncommand_history::current_number ()\n{\n  return instance_ok () ? s_instance->do_current_number () : 0;\n}\n\nvoid\ncommand_history::stifle (int n)\n{\n  if (instance_ok ())\n    s_instance->do_stifle (n);\n}\n\nint\ncommand_history::unstifle ()\n{\n  return instance_ok () ? s_instance->do_unstifle () : 0;\n}\n\nint\ncommand_history::is_stifled ()\n{\n  return instance_ok () ? s_instance->do_is_stifled () : 0;\n}\n\nvoid\ncommand_history::set_mark (int n)\n{\n  if (instance_ok ())\n    s_instance->do_set_mark (n);\n}\n\nint\ncommand_history::goto_mark ()\n{\n  return instance_ok () ? s_instance->do_goto_mark () : 0;\n}\n\nvoid\ncommand_history::read (bool must_exist)\n{\n  read (file (), must_exist);\n}\n\nvoid\ncommand_history::read (const std::string& f, bool must_exist)\n{\n  if (instance_ok ())\n    s_instance->do_read (f, must_exist);\n}\n\nvoid\ncommand_history::read_range (int from, int to, bool must_exist)\n{\n  read_range (file (), from, to, must_exist);\n}\n\nvoid\ncommand_history::read_range (const std::string& f, int from, int to,\n                             bool must_exist)\n{\n  if (instance_ok ())\n    s_instance->do_read_range (f, from, to, must_exist);\n}\n\nvoid\ncommand_history::write (const std::string& f)\n{\n  if (instance_ok ())\n    s_instance->do_write (f);\n}\n\nvoid\ncommand_history::append (const std::string& f)\n{\n  if (instance_ok ())\n    s_instance->do_append (f);\n}\n\nvoid\ncommand_history::truncate_file (const std::string& f, int n)\n{\n  if (instance_ok ())\n    s_instance->do_truncate_file (f, n);\n}\n\nstring_vector\ncommand_history::list (int limit, bool number_lines)\n{\n  return (instance_ok ()\n          ? s_instance->do_list (limit, number_lines) : string_vector ());\n}\n\nstd::string\ncommand_history::get_entry (int n)\n{\n  return instance_ok () ? s_instance->do_get_entry (n) : \"\";\n}\n\nvoid\ncommand_history::replace_entry (int which, const std::string& line)\n{\n  if (instance_ok ())\n    s_instance->do_replace_entry (which, line);\n}\n\nvoid\ncommand_history::clean_up_and_save (const std::string& f, int n)\n{\n  if (instance_ok ())\n    s_instance->do_clean_up_and_save (f, n);\n}\n\nvoid\ncommand_history::do_process_histcontrol (const std::string&)\n{ }\n\nvoid\ncommand_history::do_initialize (bool read_history_file,\n                                const std::string& f_arg, int sz,\n                                const std::string& control_arg)\n{\n  command_history::set_file (f_arg);\n  command_history::set_size (sz);\n  command_history::process_histcontrol (control_arg);\n\n  if (read_history_file)\n    command_history::read (false);\n\n  m_initialized = true;\n}\n\nbool\ncommand_history::do_is_initialized () const\n{\n  return m_initialized;\n}\n\nvoid\ncommand_history::do_set_file (const std::string& f)\n{\n  m_file = f;\n}\n\nstd::string\ncommand_history::do_file ()\n{\n  return m_file;\n}\n\nvoid\ncommand_history::do_set_size (int n)\n{\n  m_size = n;\n}\n\nint\ncommand_history::do_size () const\n{\n  return m_size;\n}\n\nvoid\ncommand_history::do_ignore_entries (bool flag)\n{\n  m_ignoring_additions = flag;\n}\n\nbool\ncommand_history::do_ignoring_entries () const\n{\n  return m_ignoring_additions;\n}\n\nbool\ncommand_history::do_add (const std::string&)\n{\n  return false;\n}\n\nvoid\ncommand_history::do_remove (int)\n{ }\n\nvoid\ncommand_history::do_clear ()\n{ }\n\nint\ncommand_history::do_where () const\n{\n  return 0;\n}\n\nint\ncommand_history::do_length () const\n{\n  return 0;\n}\n\nint\ncommand_history::do_max_input_history () const\n{\n  return 0;\n}\n\nint\ncommand_history::do_base () const\n{\n  return 0;\n}\n\nint\ncommand_history::do_current_number () const\n{\n  return m_size > 0 ? do_base () + do_where () : -1;\n}\n\nvoid\ncommand_history::do_stifle (int)\n{ }\n\nint\ncommand_history::do_unstifle ()\n{\n  return -1;\n}\n\nint\ncommand_history::do_is_stifled () const\n{\n  return 0;\n}\n\nvoid\ncommand_history::do_set_mark (int)\n{ }\n\nint\ncommand_history::do_goto_mark ()\n{\n  return 0;\n}\n\nvoid\ncommand_history::do_read (const std::string& f, bool)\n{\n  if (f.empty ())\n    error (\"command_history::read: missing filename\");\n}\n\nvoid\ncommand_history::do_read_range (const std::string& f, int, int, bool)\n{\n  if (f.empty ())\n    error (\"command_history::read_range: missing filename\");\n}\n\nvoid\ncommand_history::do_write (const std::string& f_arg) const\n{\n  if (m_initialized)\n    {\n      std::string f = f_arg;\n\n      if (f.empty ())\n        f = m_file;\n\n      if (f.empty ())\n        error (\"command_history::write: missing filename\");\n    }\n}\n\nvoid\ncommand_history::do_append (const std::string& f_arg)\n{\n  if (m_initialized)\n    {\n      if (m_lines_this_session)\n        {\n          if (m_lines_this_session < do_where ())\n            {\n              // Create file if it doesn't already exist.\n\n              std::string f = f_arg;\n\n              if (f.empty ())\n                f = m_file;\n\n              if (f.empty ())\n                error (\"command_history::append: missing filename\");\n            }\n        }\n    }\n}\n\nvoid\ncommand_history::do_truncate_file (const std::string& f_arg, int) const\n{\n  if (m_initialized)\n    {\n      std::string f = f_arg;\n\n      if (f.empty ())\n        f = m_file;\n\n      if (f.empty ())\n        error (\"command_history::truncate_file: missing filename\");\n    }\n}\n\nstring_vector\ncommand_history::do_list (int, bool) const\n{\n  return string_vector ();\n}\n\nstd::string\ncommand_history::do_get_entry (int) const\n{\n  return \"\";\n}\n\nvoid\ncommand_history::do_replace_entry (int, const std::string&)\n{ }\n\nvoid\ncommand_history::do_clean_up_and_save (const std::string& f_arg, int)\n{\n  if (m_initialized)\n    {\n      std::string f = f_arg;\n\n      if (f.empty ())\n        f = m_file;\n\n      if (f.empty ())\n        error (\"command_history::clean_up_and_save: missing filename\");\n    }\n}\n\nvoid\ncommand_history::error (int err_num, const std::string& msg) const\n{\n  if (msg.empty ())\n    (*current_liboctave_error_handler) (\"%s\", std::strerror (err_num));\n  else\n    (*current_liboctave_error_handler) (\"%s: %s\", msg.c_str (),\n                                        std::strerror (err_num));\n}\n\nvoid\ncommand_history::error (const std::string& s) const\n{\n  (*current_liboctave_error_handler) (\"%s\", s.c_str ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/cmd-hist.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cmd_hist_h)\n#define octave_cmd_hist_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API command_history\n{\nprotected:\n\n  command_history ()\n    : m_initialized (false), m_ignoring_additions (false),\n      m_history_control (0), m_lines_in_file (0),\n      m_lines_this_session (0), m_file (), m_size (-1)\n  { }\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (command_history)\n\n  virtual ~command_history () = default;\n\n  static void initialize (bool, const std::string&, int, const std::string&);\n\n  static bool is_initialized ();\n\n  static void set_file (const std::string&);\n\n  static std::string file ();\n\n  static void process_histcontrol (const std::string&);\n\n  static std::string histcontrol ();\n\n  static void set_size (int);\n\n  static int size ();\n\n  static void ignore_entries (bool = true);\n\n  static bool ignoring_entries ();\n\n  static bool add (const std::string&);\n\n  static void remove (int);\n\n  static void clear ();\n\n  static int where ();\n\n  static int length ();\n\n  static int max_input_history ();\n\n  static int base ();\n\n  static int current_number ();\n\n  static void stifle (int);\n\n  static int unstifle ();\n\n  static int is_stifled ();\n\n  static void set_mark (int n);\n\n  // Gag.  This declaration has to match the Function typedef in\n  // readline.h.\n\n  static int goto_mark ();\n\n  static void read (bool = true);\n\n  static void read (const std::string&, bool = true);\n\n  static void read_range (int = -1, int = -1, bool = true);\n\n  static void read_range (const std::string&, int = -1, int = -1,\n                          bool = true);\n\n  static void write (const std::string& = \"\");\n\n  static void append (const std::string& = \"\");\n\n  static void truncate_file (const std::string& = \"\", int = -1);\n\n  static string_vector list (int = -1, bool = false);\n\n  static std::string get_entry (int);\n\n  static void replace_entry (int, const std::string&);\n\n  static void clean_up_and_save (const std::string& = \"\", int = -1);\n\nprivate:\n\n  static bool instance_ok ();\n\n  static void make_command_history ();\n\n  // The real thing.\n  static command_history *s_instance;\n\n  static void cleanup_instance ()\n  {\n    delete s_instance;\n    s_instance = nullptr;\n  }\n\nprotected:\n\n  // To use something other than the GNU history library, derive a new\n  // class from command_history, overload these functions as\n  // necessary, and make instance point to the new class.\n\n  virtual void do_set_file (const std::string&);\n\n  virtual std::string do_file ();\n\n  virtual void do_process_histcontrol (const std::string&);\n\n  virtual std::string do_histcontrol () const { return \"\"; }\n\n  virtual void do_initialize (bool, const std::string&, int,\n                              const std::string&);\n\n  virtual bool do_is_initialized () const;\n\n  virtual void do_set_size (int);\n\n  virtual int do_size () const;\n\n  virtual void do_ignore_entries (bool);\n\n  virtual bool do_ignoring_entries () const;\n\n  virtual bool do_add (const std::string&);\n\n  virtual void do_remove (int);\n\n  virtual void do_clear ();\n\n  virtual int do_where () const;\n\n  virtual int do_length () const;\n\n  virtual int do_max_input_history () const;\n\n  virtual int do_base () const;\n\n  virtual int do_current_number () const;\n\n  virtual void do_stifle (int);\n\n  virtual int do_unstifle ();\n\n  virtual int do_is_stifled () const;\n\n  virtual void do_set_mark (int);\n\n  virtual int do_goto_mark ();\n\n  virtual void do_read (const std::string&, bool);\n\n  virtual void do_read_range (const std::string&, int, int, bool);\n\n  virtual void do_write (const std::string&) const;\n\n  virtual void do_append (const std::string&);\n\n  virtual void do_truncate_file (const std::string&, int) const;\n\n  virtual string_vector do_list (int, bool) const;\n\n  virtual std::string do_get_entry (int) const;\n\n  virtual void do_replace_entry (int, const std::string&);\n\n  virtual void do_clean_up_and_save (const std::string&, int);\n\n  void error (int, const std::string& msg = \"\") const;\n\n  void error (const std::string&) const;\n\n  // TRUE means we have initialized the history filename and number of\n  // lines to save.\n  bool m_initialized;\n\n  // TRUE means we are ignoring new additions.\n  bool m_ignoring_additions;\n\n  // Bitmask for history control options.  See oct-rl-hist.h.\n  int m_history_control;\n\n  // The number of history lines we read from the history file.\n  int m_lines_in_file;\n\n  // The number of history lines we've saved so far.\n  int m_lines_this_session;\n\n  // The default history file.\n  std::string m_file;\n\n  // The number of lines of history to save.\n  int m_size;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/coct-hdf5-types.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-hdf5.h\"\n\n// Programming Note: This file exists so that we can hide the use\n// of macros and C-style casts in a C warnings about using old-style\n// casts in C++.\n\n// Please do NOT eliminate this file and move code from here to\n// oct-hdf5-types.cc\n\n#if defined (HAVE_HDF5)\n\nconst octave_hdf5_id octave_H5E_DEFAULT = H5E_DEFAULT;\nconst octave_hdf5_id octave_H5P_DEFAULT = H5P_DEFAULT;\nconst octave_hdf5_id octave_H5S_ALL = H5S_ALL;\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/data.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <ctime>\n\n#include <algorithm>\n#include <limits>\n#include <string>\n\n#include \"lo-ieee.h\"\n#include \"mx-base.h\"\n#include \"oct-base64.h\"\n#include \"oct-binmap.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n\n#include \"cdef-utils.h\"\n#include \"Cell.h\"\n#include \"data.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"ov-class.h\"\n#include \"ov-classdef.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-cx-sparse.h\"\n#include \"ov-float.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"pt-mat.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"xnorm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic void\nget_dim_vecdim_all (const octave_value& dimarg, octave_value& arg,\n                    int& dim, Array<int>& perm_vec, bool& do_perm,\n                    bool& allflag, const char *fcn)\n{\n  if (dimarg.is_scalar_type ())\n    {\n      dim = dimarg.int_value () - 1;\n      if (dim < 0)\n        error (\"%s: invalid dimension DIM = %d\", fcn, dim + 1);\n    }\n  else\n    {\n      Array<int> vec = dimarg.int_vector_value ();\n      std::vector<int> vecdim;\n      dim_vector sz = arg.dims ();\n      int ndims = arg.ndims ();\n      // Check for invalid dims and ignore any dims larger than actual ndims\n      for (int i = 0; i < vec.numel (); i++)\n        {\n          vec(i)--;\n          if (vec(i) < 0)\n            error (\"%s: invalid dimension in VECDIM = %d\", fcn, vec(i)+1);\n          if (vec(i) < ndims)\n            vecdim.push_back (vec(i));\n        }\n      int n = vecdim.size ();\n      // If no dimensions left, set DIM = ndims to return input as is\n      if (n == 0)\n        {\n          dim = ndims;\n          return;\n        }\n      octave_idx_type szvecdim = 1;\n      // Check for duplicate dims and add VECDIM to permutation vector\n      perm_vec.resize (dim_vector (1, ndims));\n      std::sort (vecdim.begin (), vecdim.end ());\n      // Check for duplicates FIRST before any array writes\n      auto dup = std::adjacent_find (vecdim.begin (), vecdim.end ());\n      if (dup != vecdim.end ())\n        error (\"%s: duplicate dimension in VECDIM = %d\", fcn, *dup + 1);\n\n       // Verified vecdim has unique entries in [0, ndims-1], hence n <= ndims\n       int out_pos = ndims - n;\n       for (int d : vecdim)\n         {\n           szvecdim *= sz (d);\n           perm_vec(out_pos++) = d;\n         }\n\n      // Parse vecdim\n      if (n == 1)\n        // Only one dimension given, treat as if dim were specified instead\n        dim = vecdim[0];\n      else if (ndims == n)\n        // vecdim contains all dimensions, treat as if \"all\" flag given.\n        allflag = true;\n      else\n        {\n          dim_vector new_sz;\n          new_sz.resize (ndims - n + 1);\n          int idx = 0;\n          // Add remaining dims to permutation vector\n          for (int i = 0; i < ndims; i++)\n            {\n              if (std::find (vecdim.begin (), vecdim.end (), i)\n                  == vecdim.end ())\n                {\n                  perm_vec(idx) = i;\n                  new_sz(idx) = sz(i);\n                  idx++;\n                }\n            }\n          new_sz(idx) = szvecdim;\n          arg = arg.permute (perm_vec, false);\n          arg = arg.reshape (new_sz);\n          do_perm = true;\n          dim = idx;\n        }\n    }\n}\n\nDEFUN (all, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{tf} =} all (@var{x})\n@deftypefnx {} {@var{tf} =} all (@var{x}, @var{dim})\n@deftypefnx {} {@var{tf} =} all (@var{x}, @var{vecdim})\n@deftypefnx {} {@var{tf} =} all (@var{x}, \"all\")\nReturn true (logical 1) if all elements are nonzero or true.\n\nIf @var{x} is a vector, then @code{all (@var{x})} returns true (logical 1) if\nall elements of the vector are nonzero.\n\nIf @var{x} is a matrix, then @code{all (@var{x})} returns a row vector of\nlogical ones and zeros where each element indicates whether all of the elements\nof the corresponding column of the matrix are nonzero.\n\nIf @var{x} is an array, then @code{all(@var{x})} operates along the first\nnon-singleton dimension of @var{x} and returns a logical array, whose size is\nequal to @var{x} except for the operating dimension which becomes 1.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension in @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.  The size of the dimensions specified\nby @var{vecdim} become 1 in the returned logical array.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{all} to operate on\nall elements of @var{x}, and is equivalent to @code{all (@var{x}(:))}.\n@seealso{any}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  bool do_perm = false;\n  bool allflag = false;\n\n  while (nargin > 1 && args(nargin - 1).is_string ())\n    {\n      std::string str = args(nargin - 1).string_value ();\n\n      if (str == \"all\")\n        allflag = true;\n      else\n        error (\"all: unrecognized optional argument '%s'\", str.c_str ());\n\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  if (allflag && nargin > 1)\n    error (\"all: cannot set DIM or VECDIM with 'all' flag\");\n\n  octave_value arg = args(0);\n\n  // Handle DIM, VECDIM\n  int dim = -1;\n  Array<int> perm_vec;\n  if (nargin == 2)\n    {\n      octave_value dimarg = args(1);\n      get_dim_vecdim_all (dimarg, arg, dim, perm_vec, do_perm, allflag, \"all\");\n    }\n\n  // Handle allflag\n  if (allflag)\n    arg = arg.reshape (dim_vector (arg.numel (), 1));\n\n  octave_value retval = arg.all (dim);\n\n  if (do_perm)\n    retval = retval.permute (perm_vec, true);\n\n  return retval;\n}\n\n/*\n%!test\n%! x = ones (3);\n%! x(1,1) = 0;\n%! assert (all (all (rand (3) + 1) == [1, 1, 1]) == 1);\n%! assert (all (all (x) == [0, 1, 1]) == 1);\n%! assert (all (x, 1) == [0, 1, 1]);\n%! assert (all (x, 2) == [0; 1; 1]);\n\n%!test\n%! x = ones (3, \"single\");\n%! x(1,1) = 0;\n%! assert (all (all (single (rand (3) + 1)) == [1, 1, 1]) == 1);\n%! assert (all (all (x) == [0, 1, 1]) == 1);\n%! assert (all (x, 1) == [0, 1, 1]);\n%! assert (all (x, 2) == [0; 1; 1]);\n\n%!test\n%! x = ones (3, 3, 3);\n%! x(3) = 0;\n%! y = all (x);\n%! assert (y(:,:,1), logical ([0, 1, 1]));\n%! assert (y(:,:,2), logical ([1, 1, 1]));\n%! assert (y(:,:,3), logical ([1, 1, 1]));\n%! y = all (x, [1, 2]);\n%! assert (y(:,:,1), false);\n%! assert (y(:,:,2), true);\n%! assert (y(:,:,3), true);\n%! assert (all (x, [1, 3]), logical ([0, 1, 1]));\n%! assert (all (x, [2, 3]), logical ([1; 1; 0]));\n%! assert (all (x, \"all\"), false);\n\n%!assert (all (ones (2), 3), logical (ones (2)))\n%!assert (all (ones (2), [3, 5]), logical (ones (2)))\n\n## Test empty matrices\n%!assert (all ([]), true)\n%!assert (all ([], 1), true (1, 0))\n%!assert (all ([], 2), true (0, 1))\n%!assert (all ([], 3), true (0, 0))\n%!assert (all (ones (1,0)), true)\n%!assert (all (ones (1,0), 1), true (1, 0))\n%!assert (all (ones (1,0), 2), true)\n%!assert (all (ones (1,0), 3), true (1, 0))\n%!assert (all (ones (0,1)), true)\n%!assert (all (ones (0,1), 1), true)\n%!assert (all (ones (0,1), 2), true (0, 1))\n%!assert (all (ones (0,1), 3), true (0, 1))\n\n## Test sparse matrices\n%!assert (all (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 0, NaN]), 2),\n%!        sparse ([true; false]))\n%!assert (all (sparse ([NaN, 0, 1, 4, 2; 1, 2, 1, 2, NaN]), 2),\n%!        sparse ([false; true]))\n\n## Test empty sparse matrices\n%!assert (all (sparse ([])), sparse (true))\n%!assert (all (sparse ([]), 1), sparse (true (1, 0)))\n%!assert (all (sparse ([]), 2), sparse (true (0, 1)))\n%!assert (all (sparse ([]), 3), sparse (true (0, 0)))\n%!assert (all (sparse (ones (1,0))), sparse (true))\n%!assert (all (sparse (ones (1,0)), 1), sparse (true (1, 0)))\n%!assert (all (sparse (ones (1,0)), 2), sparse (true))\n%!assert (all (sparse (ones (1,0)), 3), sparse (true (1, 0)))\n%!assert (all (sparse (ones (0,1))), sparse (true))\n%!assert (all (sparse (ones (0,1)), 1), sparse (true))\n%!assert (all (sparse (ones (0,1)), 2), sparse (true (0, 1)))\n%!assert (all (sparse (ones (0,1)), 3), sparse (true (0, 1)))\n\n## Test on complex matrices\n%!assert (all (1 + 2i), true)\n%!assert (all (ones (1, 2) + 2i), true)\n%!assert (all (ones (2, 2) + 2i), [true, true])\n%!assert (all (zeros (1, 2) + 2i), true)\n%!assert (all (zeros (2, 2) + 2i), [true, true])\n%!assert (all (zeros (1, 2) + 0i), false)\n%!assert (all (zeros (2, 2) + 0i), [false, false])\n%!assert (all (cat (2, zeros (2, 1) + 1i, zeros (2, 1) + 0i)), [true, false])\n\n## Test on uint* types\n%!assert (all (uint8 (1)), true)\n%!assert (all (uint8 (ones (1, 2))), true)\n%!assert (all (uint8 (zeros (1, 2))), false)\n%!assert (all (uint8 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (all (uint16 (1)), true)\n%!assert (all (uint16 (ones (1, 2))), true)\n%!assert (all (uint16 (zeros (1, 2))), false)\n%!assert (all (uint16 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (all (uint32 (1)), true)\n%!assert (all (uint32 (ones (1, 2))), true)\n%!assert (all (uint32 (zeros (1, 2))), false)\n%!assert (all (uint32 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (all (uint64 (1)), true)\n%!assert (all (uint64 (ones (1, 2))), true)\n%!assert (all (uint64 (zeros (1, 2))), false)\n%!assert (all (uint64 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n\n## Test on int* types\n%!assert (all (int8 (1)), true)\n%!assert (all (int8 (ones (1, 2))), true)\n%!assert (all (int8 (zeros (1, 2))), false)\n%!assert (all (int8 (cat (2, ones(2, 1), zeros(2, 1)))), [true, false])\n%!assert (all (int16 (1)), true)\n%!assert (all (int16 (ones (1, 2))), true)\n%!assert (all (int16 (zeros (1, 2))), false)\n%!assert (all (int16 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (all (int32 (1)), true)\n%!assert (all (int32 (ones (1, 2))), true)\n%!assert (all (int32 (zeros (1, 2))), false)\n%!assert (all (int32 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (all (int64 (1)), true)\n%!assert (all (int64 (ones (1, 2))), true)\n%!assert (all (int64 (zeros (1, 2))), false)\n%!assert (all (int64 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n\n## Test on char types\n%!assert (all (char (1)), true)\n%!assert (all (char (0)), false)\n%!assert (all (char (ones (2, 2))), [true, true])\n%!assert (all (char (zeros (2, 2))), [false, false])\n%!assert (all (char (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n\n## Test rejection of invalid types\n%!error <wrong type argument 'cell'> all ({})\n%!error <wrong type argument 'cell'> all ({1, 2, 3})\n%!error <wrong type argument 'scalar struct'> all (struct ())\n%!error <wrong type argument 'struct'> all ([struct('a', 1), struct('a', 1)])\n%!error <wrong type argument 'function handle'> all (@disp)\n\n## Test input validation\n%!error <Invalid call> all ()\n%!error <Invalid call> all (1,2,3)\n%!error <unrecognized optional argument 'foobar'> all (1, \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! all (ones (3,3), 1, \"all\");\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! all (ones (3,3), [1, 2], \"all\");\n%!error <invalid dimension DIM = 0> all (ones (3,3), 0)\n%!error <invalid dimension DIM = -1> all (ones (3,3), -1)\n%!error <invalid dimension in VECDIM = -2> all (ones (3,3), [1 -2])\n%!error <duplicate dimension in VECDIM = 2> all (ones (3,3), [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> all (ones (3,3), [1 1 2])\n*/\n\nDEFUN (any, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{tf} =} any (@var{x})\n@deftypefnx {} {@var{tf} =} any (@var{x}, @var{dim})\n@deftypefnx {} {@var{tf} =} any (@var{x}, @var{vecdim})\n@deftypefnx {} {@var{tf} =} any (@var{x}, \"all\")\nReturn true (logical 1) if any elements are nonzero or true.\n\nIf @var{x} is a vector, then @code{any (@var{x})} returns true (logical 1) if\nany elements of the vector are nonzero.\n\nIf @var{x} is a matrix, then @code{any (@var{x})} returns a row vector of\nlogical ones and zeros where each element indicates whether any of the elements\nof the corresponding column of the matrix are nonzero.\n\nIf @var{x} is an array, then @code{any(@var{x})} operates along the first\nnon-singleton dimension of @var{x} and returns a logical array, whose size is\nequal to @var{x} except for the operating dimension which becomes 1.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension in @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.  The size of the dimensions specified\nby @var{vecdim} become 1 in the returned logical array.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{any} to operate on\nall elements of @var{x}, and is equivalent to @code{any (@var{x}(:))}.\n@seealso{all}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  bool do_perm = false;\n  bool allflag = false;\n\n  while (nargin > 1 && args(nargin - 1).is_string ())\n    {\n      std::string str = args(nargin - 1).string_value ();\n\n      if (str == \"all\")\n        allflag = true;\n      else\n        error (\"any: unrecognized optional argument '%s'\", str.c_str ());\n\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  if (allflag && nargin > 1)\n    error (\"any: cannot set DIM or VECDIM with 'all' flag\");\n\n  octave_value arg = args(0);\n\n  // Handle DIM, VECDIM\n  int dim = -1;\n  Array<int> perm_vec;\n  if (nargin == 2)\n    {\n      octave_value dimarg = args(1);\n      get_dim_vecdim_all (dimarg, arg, dim, perm_vec, do_perm, allflag, \"any\");\n    }\n\n  // Handle allflag\n  if (allflag)\n    arg = arg.reshape (dim_vector (arg.numel (), 1));\n\n  octave_value retval = arg.any (dim);\n\n  if (do_perm)\n    retval = retval.permute (perm_vec, true);\n\n  return retval;\n}\n\n/*\n%!test\n%! x = zeros (3);\n%! x(3,3) = 1;\n%! assert (all (any (x) == [0, 0, 1]) == 1);\n%! assert (all (any (ones (3)) == [1, 1, 1]) == 1);\n%! assert (any (x, 1) == [0, 0, 1]);\n%! assert (any (x, 2) == [0; 0; 1]);\n\n%!test\n%! x = zeros (3, \"single\");\n%! x(3,3) = 1;\n%! assert (all (any (x) == [0, 0, 1]) == 1);\n%! assert (all (any (ones (3, \"single\")) == [1, 1, 1]) == 1);\n%! assert (any (x, 1) == [0, 0, 1]);\n%! assert (any (x, 2) == [0; 0; 1]);\n\n%!test\n%! x = zeros (3, 3, 3);\n%! x(3) = 1;\n%! y = any (x);\n%! assert (y(:,:,1), logical ([1, 0, 0]));\n%! assert (y(:,:,2), logical ([0, 0, 0]));\n%! assert (y(:,:,3), logical ([0, 0, 0]));\n%! y = any (x, [1, 2]);\n%! assert (y(:,:,1), true);\n%! assert (y(:,:,2), false);\n%! assert (y(:,:,3), false);\n%! assert (any (x, [1, 3]), logical ([1, 0, 0]));\n%! assert (any (x, [2, 3]), logical ([0; 0; 1]));\n%! assert (any (x, \"all\"), true);\n\n## Test empty matrices\n%!assert (any ([]), false)\n%!assert (any ([], 1), false (1, 0))\n%!assert (any ([], 2), false (0, 1))\n%!assert (any ([], 3), false (0, 0))\n%!assert (any (ones (1,0)), false)\n%!assert (any (ones (1,0), 1), false (1, 0))\n%!assert (any (ones (1,0), 2), false)\n%!assert (any (ones (1,0), 3), false (1, 0))\n%!assert (any (ones (0,1)), false)\n%!assert (any (ones (0,1), 1), false)\n%!assert (any (ones (0,1), 2), false (0, 1))\n%!assert (any (ones (0,1), 3), false (0, 1))\n\n## Test sparse matrices\n%!assert (any (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 0, NaN]), 2),\n%!        sparse ([true; true]))\n%!assert (any (sparse ([0, 0, 0, 0, 0; 1, 2, 1, 2, NaN]), 2),\n%!        sparse ([false; true]))\n%!assert (any (sparse ([0, 0, 0, 0i, 0; 1, 2, 1, 2, NaN]), 2),\n%!        sparse ([false; true]))\n%!assert (any (sparse ([0, 0, 0, 0+i, 0; 1, 2, 1, 2, NaN]), 2),\n%!        sparse ([true; true]))\n\n## Test empty sparse matrices\n%!assert (any (sparse ([])), sparse (false))\n%!assert (any (sparse ([]), 1), sparse (false (1, 0)))\n%!assert (any (sparse ([]), 2), sparse (false (0, 1)))\n%!assert (any (sparse ([]), 3), sparse (false (0, 0)))\n%!assert (any (sparse (ones (1,0))), sparse (false))\n%!assert (any (sparse (ones (1,0)), 1), sparse (false (1, 0)))\n%!assert (any (sparse (ones (1,0)), 2), sparse (false))\n%!assert (any (sparse (ones (1,0)), 3), sparse (false (1, 0)))\n%!assert (any (sparse (ones (0,1))), sparse (false))\n%!assert (any (sparse (ones (0,1)), 1), sparse (false))\n%!assert (any (sparse (ones (0,1)), 2), sparse (false (0, 1)))\n%!assert (any (sparse (ones (0,1)), 3), sparse (false (0, 1)))\n\n## Test on complex matrices\n%!assert (any (1 + 2i), true)\n%!assert (any (ones (1, 2) + 2i), true)\n%!assert (any (ones (2, 2) + 2i), [true, true])\n%!assert (any (zeros (1, 2) + 2i), true)\n%!assert (any (zeros (2, 2) + 2i), [true, true])\n%!assert (any (zeros (1, 2) + 0i), false)\n%!assert (any (zeros (2, 2) + 0i), [false, false])\n%!assert (any (cat (2, zeros (2, 1) + 1i, zeros (2, 1) + 0i)), [true, false])\n\n## Test on uint* types\n%!assert (any (uint8 (1)), true)\n%!assert (any (uint8 (ones (1, 2))), true)\n%!assert (any (uint8 (zeros (1, 2))), false)\n%!assert (any (uint8 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (any (uint16 (1)), true)\n%!assert (any (uint16 (ones (1, 2))), true)\n%!assert (any (uint16 (zeros (1, 2))), false)\n%!assert (any (uint16 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (any (uint32 (1)), true)\n%!assert (any (uint32 (ones (1, 2))), true)\n%!assert (any (uint32 (zeros (1, 2))), false)\n%!assert (any (uint32 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (any (uint64 (1)), true)\n%!assert (any (uint64 (ones (1, 2))), true)\n%!assert (any (uint64 (zeros (1, 2))), false)\n%!assert (any (uint64 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n\n## Test on int* types\n%!assert (any (int8 (1)), true)\n%!assert (any (int8 (ones (1, 2))), true)\n%!assert (any (int8 (zeros (1, 2))), false)\n%!assert (any (int8 (cat (2, ones(2, 1), zeros(2, 1)))), [true, false])\n%!assert (any (int16 (1)), true)\n%!assert (any (int16 (ones (1, 2))), true)\n%!assert (any (int16 (zeros (1, 2))), false)\n%!assert (any (int16 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (any (int32 (1)), true)\n%!assert (any (int32 (ones (1, 2))), true)\n%!assert (any (int32 (zeros (1, 2))), false)\n%!assert (any (int32 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n%!assert (any (int64 (1)), true)\n%!assert (any (int64 (ones (1, 2))), true)\n%!assert (any (int64 (zeros (1, 2))), false)\n%!assert (any (int64 (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n\n## Test on char types\n%!assert (any (char (1)), true)\n%!assert (any (char (0)), false)\n%!assert (any (char (ones (2, 2))), [true, true])\n%!assert (any (char (zeros (2, 2))), [false, false])\n%!assert (any (char (cat (2, ones (2, 1), zeros (2, 1)))), [true, false])\n\n## Test rejection of invalid types\n%!error <wrong type argument 'cell'> any ({})\n%!error <wrong type argument 'cell'> any ({1, 2, 3})\n%!error <wrong type argument 'scalar struct'> any (struct ())\n%!error <wrong type argument 'struct'> any ([struct('a', 1), struct('a', 1)])\n%!error <wrong type argument 'function handle'> any (@disp)\n\n## Test input validation\n%!error <Invalid call> any ()\n%!error <Invalid call> any (1,2,3)\n%!error <unrecognized optional argument 'foobar'> any (1, \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! any (ones (3,3), 1, \"all\");\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! any (ones (3,3), [1, 2], \"all\");\n%!error <invalid dimension DIM = 0> any (ones (3,3), 0)\n%!error <invalid dimension DIM = -1> any (ones (3,3), -1)\n%!error <invalid dimension in VECDIM = -2> any (ones (3,3), [1 -2])\n%!error <duplicate dimension in VECDIM = 2> any (ones (3,3), [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> any (ones (3,3), [1 1 2])\n*/\n\n// These mapping functions may also be useful in other places, eh?\n\nDEFUN (atan2, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{angle} =} atan2 (@var{y}, @var{x})\nCompute atan (@var{y} / @var{x}) for corresponding elements of @var{y} and\n@var{x}.\n\n@var{y} and @var{x} must match in size and orientation.  The signs of elements\nof @var{y} and @var{x} are used to determine the quadrants of each resulting\nvalue.\n\nThis function is equivalent to @code{arg (complex (@var{x}, @var{y}))}.\n@seealso{tan, tand, tanh, atanh}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value retval;\n\n  if (! args(0).isnumeric ())\n    err_wrong_type_arg (\"atan2\", args(0));\n\n  if (! args(1).isnumeric ())\n    err_wrong_type_arg (\"atan2\", args(1));\n\n  if (args(0).iscomplex () || args(1).iscomplex ())\n    error (\"atan2: not defined for complex numbers\");\n\n  if (args(0).is_single_type () || args(1).is_single_type ())\n    {\n      if (args(0).is_scalar_type () && args(1).is_scalar_type ())\n        retval = atan2f (args(0).float_value (), args(1).float_value ());\n      else\n        {\n          FloatNDArray a0 = args(0).float_array_value ();\n          FloatNDArray a1 = args(1).float_array_value ();\n          retval = binmap<float> (a0, a1, std::atan2, \"atan2\");\n        }\n    }\n  else\n    {\n      if (args(0).is_scalar_type () && args(1).is_scalar_type ())\n        retval = atan2 (args(0).scalar_value (), args(1).scalar_value ());\n      else if (args(0).issparse ())\n        {\n          SparseMatrix m0 = args(0).sparse_matrix_value ();\n          SparseMatrix m1 = args(1).sparse_matrix_value ();\n          retval = binmap<double> (m0, m1, std::atan2, \"atan2\");\n        }\n      else\n        {\n          NDArray a0 = args(0).array_value ();\n          NDArray a1 = args(1).array_value ();\n          retval = binmap<double> (a0, a1, std::atan2, \"atan2\");\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!assert (size (atan2 (zeros (0, 2), zeros (0, 2))), [0, 2])\n%!assert (size (atan2 (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])\n%!assert (size (atan2 (rand (2, 3, 4), 1)), [2, 3, 4])\n%!assert (size (atan2 (1, rand (2, 3, 4))), [2, 3, 4])\n%!assert (size (atan2 (1, 2)), [1, 1])\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! v = [0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0];\n%! y = [0, rt3, 1, rt3, -rt3, -1, -rt3, 0];\n%! x = [1, 3, 1, 1, 1, 1, 3, 1];\n%! assert (atan2 (y, x), v, sqrt (eps));\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! v = single ([0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0]);\n%! y = single ([0, rt3, 1, rt3, -rt3, -1, -rt3, 0]);\n%! x = single ([1, 3, 1, 1, 1, 1, 3, 1]);\n%! assert (atan2 (y, x), v, sqrt (eps (\"single\")));\n\n%!assert (any (ones (2), 3), logical (ones (2)))\n%!assert (any (ones (2), [3, 5]), logical (ones (2)))\n\n## Test sparse implementations\n%!shared xs\n%! xs = sparse (0:3);\n%!test\n%! y = atan2 (1, xs);\n%! assert (issparse (y), false);\n%! assert (nnz (y), 4);\n%! assert (y, atan2 (1, 0:3));\n%!test\n%! y = atan2 (0, xs);\n%! assert (issparse (y), false);\n%! assert (nnz (y), 0);\n%! assert (y, zeros (1,4));\n%!test\n%! y = atan2 (xs, 1);\n%! assert (issparse (y));\n%! assert (nnz (y), 3);\n%! assert (y, sparse (atan2 (0:3, 1)));\n%!test\n%! y = atan2 (xs, 0);\n%! assert (issparse (y));\n%! assert (nnz (y), 3);\n%! assert (y, sparse (atan2 (0:3, 0)));\n%!test\n%! y = atan2 (xs, sparse (ones (1, 4)));\n%! assert (issparse (y));\n%! assert (nnz (y), 3);\n%! assert (y, sparse (atan2 (0:3, ones (1,4))));\n%!test\n%! y = atan2 (xs, sparse (zeros (1,4)));\n%! assert (issparse (y));\n%! assert (nnz (y), 3);\n%! assert (y, sparse (atan2 (0:3, zeros (1,4))));\n\n%!error atan2 ()\n%!error atan2 (1, 2, 3)\n*/\n\nstatic octave_value\ndo_hypot (const octave_value& x, const octave_value& y)\n{\n  octave_value retval;\n\n  octave_value arg0 = x;\n  octave_value arg1 = y;\n  if (! arg0.isnumeric ())\n    err_wrong_type_arg (\"hypot\", arg0);\n  if (! arg1.isnumeric ())\n    err_wrong_type_arg (\"hypot\", arg1);\n\n  if (arg0.iscomplex ())\n    arg0 = arg0.abs ();\n  if (arg1.iscomplex ())\n    arg1 = arg1.abs ();\n\n  if (arg0.is_single_type () || arg1.is_single_type ())\n    {\n      if (arg0.is_scalar_type () && arg1.is_scalar_type ())\n        retval = hypotf (arg0.float_value (), arg1.float_value ());\n      else\n        {\n          FloatNDArray a0 = arg0.float_array_value ();\n          FloatNDArray a1 = arg1.float_array_value ();\n          retval = binmap<float> (a0, a1, std::hypot, \"hypot\");\n        }\n    }\n  else\n    {\n      if (arg0.is_scalar_type () && arg1.is_scalar_type ())\n        retval = hypot (arg0.scalar_value (), arg1.scalar_value ());\n      else if (arg0.issparse () || arg1.issparse ())\n        {\n          SparseMatrix m0 = arg0.sparse_matrix_value ();\n          SparseMatrix m1 = arg1.sparse_matrix_value ();\n          retval = binmap<double> (m0, m1, std::hypot, \"hypot\");\n        }\n      else\n        {\n          NDArray a0 = arg0.array_value ();\n          NDArray a1 = arg1.array_value ();\n          retval = binmap<double> (a0, a1, std::hypot, \"hypot\");\n        }\n    }\n\n  return retval;\n}\n\nDEFUN (hypot, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{h} =} hypot (@var{x}, @var{y})\n@deftypefnx {} {@var{h} =} hypot (@var{x}, @var{y}, @var{z}, @dots{})\nCompute the element-by-element square root of the sum of the squares of\n@var{x} and @var{y}.\n\nThis is equivalent to\n@code{sqrt (@var{x}.^2 + @var{y}.^2)}, but is calculated in a manner that\navoids overflows for large values of @var{x} or @var{y}.\n\n@code{hypot} can also be called with more than 2 arguments; in this case,\nthe arguments are accumulated from left to right:\n\n@example\n@group\nhypot (hypot (@var{x}, @var{y}), @var{z})\nhypot (hypot (hypot (@var{x}, @var{y}), @var{z}), @var{w}), etc.\n@end group\n@end example\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 2)\n    retval = do_hypot (args(0), args(1));\n  else\n    {\n      retval = args(0);\n\n      for (int i = 1; i < nargin; i++)\n        retval = do_hypot (retval, args(i));\n    }\n\n  return retval;\n}\n\n/*\n%!assert (size (hypot (zeros (0, 2), zeros (0, 2))), [0, 2])\n%!assert (size (hypot (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])\n%!assert (size (hypot (rand (2, 3, 4), 1)), [2, 3, 4])\n%!assert (size (hypot (1, rand (2, 3, 4))), [2, 3, 4])\n%!assert (size (hypot (1, 2)), [1, 1])\n%!assert (hypot (1:10, 1:10), sqrt (2) * [1:10], 16*eps)\n%!assert (hypot (single (1:10), single (1:10)), single (sqrt (2) * [1:10]))\n\n## Test sparse implementations\n%!shared xs\n%! xs = sparse (0:3);\n%!test\n%! y = hypot (1, xs);\n%! assert (nnz (y), 4);\n%! assert (y, sparse (hypot (1, 0:3)));\n%!test\n%! y = hypot (0, xs);\n%! assert (nnz (y), 3);\n%! assert (y, xs);\n%!test\n%! y = hypot (xs, 1);\n%! assert (nnz (y), 4);\n%! assert (y, sparse (hypot (0:3, 1)));\n%!test\n%! y = hypot (xs, 0);\n%! assert (nnz (y), 3);\n%! assert (y, xs);\n%!test\n%! y = hypot (sparse ([0 0]), sparse ([0 1]));\n%! assert (nnz (y), 1);\n%! assert (y, sparse ([0 1]));\n%!test\n%! y = hypot (sparse ([0 1]), sparse ([0 0]));\n%! assert (nnz (y), 1);\n%! assert (y, sparse ([0 1]));\n\n*/\n\ntemplate <typename T, typename ET>\nvoid\nmap_2_xlog2 (const Array<T>& x, Array<T>& f, Array<ET>& e)\n{\n  f = Array<T> (x.dims ());\n  e = Array<ET> (x.dims ());\n  for (octave_idx_type i = 0; i < x.numel (); i++)\n    {\n      int exp;\n      f.xelem (i) = math::log2 (x(i), exp);\n      e.xelem (i) = exp;\n    }\n}\n\nDEFUN (log2, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} log2 (@var{x})\n@deftypefnx {} {[@var{f}, @var{e}] =} log2 (@var{x})\nCompute the base-2 logarithm of each element of @var{x}.\n\nIf called with one output, compute the base-2 logarithm such that\n@tex\n$2^y = x$.\n@end tex\n@ifnottex\n@code{2^@var{y} = @var{x}}.\n@end ifnottex\n\nIf called with two output arguments, split @var{x} into binary mantissa\n(@var{f}) and exponent (@var{e}) such that\n@tex\n$x = f \\cdot 2^e$\n@end tex\n@ifnottex\n@code{@var{x} = @var{f} * 2^@var{e}}\n@end ifnottex\nwhere\n@tex\n${1 \\over 2} \\le \\left| f \\right| < 1$\n@end tex\n@ifnottex\n@w{@code{1/2 <= abs (@var{f}) < 1}}\n@end ifnottex\nand @var{e} is an integer.  If\n@tex\n$x = 0$, $f = e = 0$.\n@end tex\n@ifnottex\n@w{@code{x = 0}}, @w{@code{f = e = 0}}.\n@end ifnottex\n@seealso{pow2, log, log10, exp}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value_list retval;\n\n  if (nargout < 2)\n    retval = ovl (args(0).log2 ());\n  else if (args(0).is_single_type ())\n    {\n      if (args(0).isreal ())\n        {\n          FloatNDArray f;\n          FloatNDArray x = args(0).float_array_value ();\n          // FIXME: should E be an int value?\n          FloatMatrix e;\n          map_2_xlog2 (x, f, e);\n          retval = ovl (f, e);\n        }\n      else if (args(0).iscomplex ())\n        {\n          FloatComplexNDArray f;\n          FloatComplexNDArray x = args(0).float_complex_array_value ();\n          // FIXME: should E be an int value?\n          FloatNDArray e;\n          map_2_xlog2 (x, f, e);\n          retval = ovl (f, e);\n        }\n    }\n  else if (args(0).isreal ())\n    {\n      NDArray f;\n      NDArray x = args(0).array_value ();\n      // FIXME: should E be an int value?\n      Matrix e;\n      map_2_xlog2 (x, f, e);\n      retval = ovl (f, e);\n    }\n  else if (args(0).iscomplex ())\n    {\n      ComplexNDArray f;\n      ComplexNDArray x = args(0).complex_array_value ();\n      // FIXME: should E be an int value?\n      NDArray e;\n      map_2_xlog2 (x, f, e);\n      retval = ovl (f, e);\n    }\n  else\n    err_wrong_type_arg (\"log2\", args(0));\n\n  return retval;\n}\n\n/*\n%!assert (log2 ([1/4, 1/2, 1, 2, 4]), [-2, -1, 0, 1, 2])\n%!assert (log2 (Inf), Inf)\n%!assert (isnan (log2 (NaN)))\n%!assert (log2 (4*i), 2 + log2 (1*i))\n%!assert (log2 (complex (0,Inf)), Inf + log2 (i))\n\n%!test\n%! [f, e] = log2 ([0,-1; 2,-4; Inf,-Inf]);\n%! assert (f, [0,-0.5; 0.5,-0.5; Inf,-Inf]);\n%! assert (e(1:2,:), [0,1;2,3]);\n\n%!test\n%! [f, e] = log2 (complex (zeros (3, 2), [0,-1; 2,-4; Inf,-Inf]));\n%! assert (f, complex (zeros (3, 2), [0,-0.5; 0.5,-0.5; Inf,-Inf]));\n%! assert (e(1:2,:), [0,1; 2,3]);\n\n%!assert <*42583> (all (log2 (pow2 (-1074:1023)) == -1074:1023))\n*/\n\nDEFUN (rem, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{r} =} rem (@var{x}, @var{y})\nReturn the remainder of the division @code{@var{x} / @var{y}}.\n\nThe remainder is computed using the expression\n\n@example\nx - y .* fix (x ./ y)\n@end example\n\nAn error message is printed if the dimensions of the arguments do not agree,\nor if either argument is complex.\n\nProgramming Notes: When calculating with floating point numbers (double,\nsingle), values within a few eps of an integer will be rounded to that\ninteger before computation for compatibility with @sc{matlab}.  Any floating\npoint integers greater than @code{flintmax} (2^53 for double) will not compute\ncorrectly.  For larger integer values convert the input to @code{uint64} before\ncalling this function.\n\nBy convention,\n\n@example\n@group\nrem (@var{x}, 0) = NaN  if @var{x} is a floating point variable\nrem (@var{x}, 0) = 0    if @var{x} is an integer variable\nrem (@var{x}, @var{y})  returns a value with the signbit from @var{x}\n@end group\n@end example\n\nFor the opposite conventions see the @code{mod} function.  In general,\n@code{rem} is best when computing the remainder after division of two\n@emph{positive} numbers.  For negative numbers, or when the values are\nperiodic, @code{mod} is a better choice.\n@seealso{mod}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value retval;\n\n  if (! args(0).isnumeric ())\n    err_wrong_type_arg (\"rem\", args(0));\n\n  if (! args(1).isnumeric ())\n    err_wrong_type_arg (\"rem\", args(1));\n\n  if (args(0).iscomplex () || args(1).iscomplex ())\n    error (\"rem: not defined for complex numbers\");\n\n  if (args(0).isinteger () || args(1).isinteger ())\n    {\n      builtin_type_t btyp0 = args(0).builtin_type ();\n      builtin_type_t btyp1 = args(1).builtin_type ();\n      if (btyp0 == btyp_double || btyp0 == btyp_float)\n        btyp0 = btyp1;\n      if (btyp1 == btyp_double || btyp1 == btyp_float)\n        btyp1 = btyp0;\n\n      if (btyp0 != btyp1)\n        error (\"rem: cannot combine %s and %s\",\n               args(0).class_name ().c_str (),\n               args(1).class_name ().c_str ());\n\n      switch (btyp0)\n        {\n#define MAKE_INT_BRANCH(X)                                              \\\n          case btyp_ ## X:                                              \\\n            {                                                           \\\n              X##NDArray a0 = args(0).X##_array_value ();               \\\n              X##NDArray a1 = args(1).X##_array_value ();               \\\n              retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, rem, \"rem\"); \\\n            }                                                           \\\n            break\n\n          MAKE_INT_BRANCH (int8);\n          MAKE_INT_BRANCH (int16);\n          MAKE_INT_BRANCH (int32);\n          MAKE_INT_BRANCH (int64);\n          MAKE_INT_BRANCH (uint8);\n          MAKE_INT_BRANCH (uint16);\n          MAKE_INT_BRANCH (uint32);\n          MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n          case btyp_double:\n          case btyp_float:\n          case btyp_complex:\n          case btyp_float_complex:\n          case btyp_bool:\n          case btyp_char:\n          case btyp_struct:\n          case btyp_cell:\n          case btyp_func_handle:\n          case btyp_unknown:\n            error (\"rem: unexpected: found %s instead of integer - please report this bug\", btyp_class_name[btyp0].c_str ());\n            break;\n\n          // We should have handled all possible enum values above.\n          // Rely on compiler diagnostics to warn if we haven't.  For\n          // example, GCC's -Wswitch option, enabled by -Wall, will\n          // provide a warning.\n        }\n    }\n  else if (args(0).is_single_type () || args(1).is_single_type ())\n    {\n      if (args(0).is_scalar_type () && args(1).is_scalar_type ())\n        retval = math::rem (args(0).float_value (), args(1).float_value ());\n      else\n        {\n          FloatNDArray a0 = args(0).float_array_value ();\n          FloatNDArray a1 = args(1).float_array_value ();\n          retval = binmap<float> (a0, a1, math::rem<float>, \"rem\");\n        }\n    }\n  else\n    {\n      if (args(0).is_scalar_type () && args(1).is_scalar_type ())\n        retval = math::rem (args(0).scalar_value (), args(1).scalar_value ());\n      else if (args(0).issparse () || args(1).issparse ())\n        {\n          SparseMatrix m0 = args(0).sparse_matrix_value ();\n          SparseMatrix m1 = args(1).sparse_matrix_value ();\n          retval = binmap<double> (m0, m1, math::rem<double>, \"rem\");\n        }\n      else\n        {\n          NDArray a0 = args(0).array_value ();\n          NDArray a1 = args(1).array_value ();\n          retval = binmap<double> (a0, a1, math::rem<double>, \"rem\");\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!assert (size (rem (zeros (0, 2), zeros (0, 2))), [0, 2])\n%!assert (size (rem (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])\n%!assert (size (rem (rand (2, 3, 4), 1)), [2, 3, 4])\n%!assert (size (rem (1, rand (2, 3, 4))), [2, 3, 4])\n%!assert (size (rem (1, 2)), [1, 1])\n\n%!assert (rem ([1, 2, 3; -1, -2, -3], 2), [1, 0, 1; -1, 0, -1])\n%!assert (rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3)),[1, 0, 1; -1, 0, -1])\n%!assert (rem ([0, 1, 2], [0, 0, 1]), [NaN, NaN, 0])\n%!assert (rem (uint8 ([1, 2, 3; -1, -2, -3]), uint8 (2)),\n%!        uint8 ([1, 0, 1; -1, 0, -1]))\n%!assert (uint8 (rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3))),\n%!        uint8 ([1, 0, 1; -1, 0, -1]))\n%!assert (rem (uint8 ([0, 1, 2]), [0, 0, 1]), uint8 ([0, 0, 0]))\n\n## Test sparse implementations\n%!shared xs\n%! xs = sparse (0:3);\n%!test\n%! y = rem (11, xs);\n%! assert (isnan (y(1)));\n%! assert (y, sparse (rem (11, 0:3)));\n%!test\n%! y = rem (0, xs);\n%! assert (nnz (y), 1);\n%! assert (y, sparse ([NaN 0 0 0]));\n%!test\n%! y = rem (xs, 2);\n%! assert (nnz (y), 2);\n%! assert (y, sparse (rem (0:3, 2)));\n%!test\n%! y = rem (xs, 1);\n%! assert (nnz (y), 0);\n%! assert (y, sparse (rem (0:3, 1)));\n%!test\n%! y = rem (sparse ([11 11 11 11]), xs);\n%! assert (nnz (y), 3);\n%! assert (y, sparse (rem (11, 0:3)));\n%!test\n%! y = rem (sparse ([0 0 0 0]), xs);\n%! assert (nnz (y), 1);\n%! assert (y, sparse ([NaN 0 0 0]));\n\n%!assert <*45587> (signbit (rem (-0, 1)))\n%!assert <*45587> (! signbit (rem (0, 1)))\n\n%!assert <*42627> (rem (0.94, 0.01), 0.0)\n\n## Test rem (x-1, x) for x close to flintmax.  Should return x-1 and not zero.\n%!test <*67339>\n%! x = flintmax - (10:-1:1);\n%! assert (rem (x-1, x), x-1);\n%! x = flintmax (\"single\") - (10:-1:1);\n%! assert (rem (x-1, x), x-1);\n\n%!error rem (uint (8), int8 (5))\n%!error rem (uint8 ([1, 2]), uint8 ([3, 4, 5]))\n%!error rem ()\n%!error rem (1, 2, 3)\n%!error rem ([1, 2], [3, 4, 5])\n%!error rem (i, 1)\n*/\n\nDEFUN (mod, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{m} =} mod (@var{x}, @var{y})\nCompute the modulo of @var{x} and @var{y}.\n\nConceptually this is given by\n\n@example\nx - y .* floor (x ./ y)\n@end example\n\n@noindent\nand is written such that the correct modulus is returned for integer types.\nThis function handles negative values correctly.  That is,\n@w{@code{mod (-1, 3)}}@ is 2, not -1, as @w{@code{rem (-1, 3)}}@ returns.\n\nAn error results if the dimensions of the arguments do not agree, or if\neither of the arguments is complex.\n\nProgramming Notes: When calculating with floating point numbers (double,\nsingle), values within a few eps of an integer will be rounded to that\ninteger before computation for compatibility with @sc{matlab}.  Any floating\npoint integers greater than @code{flintmax} (2^53 for double) will not compute\ncorrectly.  For larger integer values convert the input to @code{uint64} before\ncalling this function.\n\nBy convention,\n\n@example\n@group\nmod (@var{x}, 0) = @var{x}\nmod (@var{x}, @var{y})      returns a value with the signbit from @var{y}\n@end group\n@end example\n\nFor the opposite conventions see the @code{rem} function.  In general,\n@code{mod} is a better choice than @code{rem} when any of the inputs are\nnegative numbers or when the values are periodic.\n@seealso{rem}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value retval;\n\n  if (! args(0).isnumeric ())\n    err_wrong_type_arg (\"mod\", args(0));\n\n  if (! args(1).isnumeric ())\n    err_wrong_type_arg (\"mod\", args(1));\n\n  if (args(0).iscomplex () || args(1).iscomplex ())\n    error (\"mod: not defined for complex numbers\");\n\n  if (args(0).isinteger () || args(1).isinteger ())\n    {\n      builtin_type_t btyp0 = args(0).builtin_type ();\n      builtin_type_t btyp1 = args(1).builtin_type ();\n      if (btyp0 == btyp_double || btyp0 == btyp_float)\n        btyp0 = btyp1;\n      if (btyp1 == btyp_double || btyp1 == btyp_float)\n        btyp1 = btyp0;\n\n      if (btyp0 != btyp1)\n        error (\"mod: cannot combine %s and %s\",\n               args(0).class_name ().c_str (),\n               args(1).class_name ().c_str ());\n\n      switch (btyp0)\n        {\n#define MAKE_INT_BRANCH(X)                                              \\\n          case btyp_ ## X:                                              \\\n            {                                                           \\\n              X##NDArray a0 = args(0).X##_array_value ();               \\\n              X##NDArray a1 = args(1).X##_array_value ();               \\\n              retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, mod, \"mod\"); \\\n            }                                                           \\\n            break\n\n          MAKE_INT_BRANCH (int8);\n          MAKE_INT_BRANCH (int16);\n          MAKE_INT_BRANCH (int32);\n          MAKE_INT_BRANCH (int64);\n          MAKE_INT_BRANCH (uint8);\n          MAKE_INT_BRANCH (uint16);\n          MAKE_INT_BRANCH (uint32);\n          MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n          case btyp_double:\n          case btyp_float:\n          case btyp_complex:\n          case btyp_float_complex:\n          case btyp_bool:\n          case btyp_char:\n          case btyp_struct:\n          case btyp_cell:\n          case btyp_func_handle:\n          case btyp_unknown:\n            error (\"mod: unexpected: found %s instead of integer - please report this bug\", btyp_class_name[btyp0].c_str ());\n            break;\n\n          // We should have handled all possible enum values above.\n          // Rely on compiler diagnostics to warn if we haven't.  For\n          // example, GCC's -Wswitch option, enabled by -Wall, will\n          // provide a warning.\n        }\n    }\n  else if (args(0).is_single_type () || args(1).is_single_type ())\n    {\n      if (args(0).is_scalar_type () && args(1).is_scalar_type ())\n        retval = math::mod (args(0).float_value (), args(1).float_value ());\n      else\n        {\n          FloatNDArray a0 = args(0).float_array_value ();\n          FloatNDArray a1 = args(1).float_array_value ();\n          retval = binmap<float> (a0, a1, math::mod<float>, \"mod\");\n        }\n    }\n  else\n    {\n      if (args(0).is_scalar_type () && args(1).is_scalar_type ())\n        retval = math::mod (args(0).scalar_value (), args(1).scalar_value ());\n      else if (args(0).issparse () || args(1).issparse ())\n        {\n          SparseMatrix m0 = args(0).sparse_matrix_value ();\n          SparseMatrix m1 = args(1).sparse_matrix_value ();\n          retval = binmap<double> (m0, m1, math::mod<double>, \"mod\");\n        }\n      else\n        {\n          NDArray a0 = args(0).array_value ();\n          NDArray a1 = args(1).array_value ();\n          retval = binmap<double> (a0, a1, math::mod<double>, \"mod\");\n        }\n    }\n\n  return retval;\n}\n\n/*\n## empty input test\n%!assert (isempty (mod ([], [])))\n\n## x mod y, y != 0 tests\n%!assert (mod (5, 3), 2)\n%!assert (mod (-5, 3), 1)\n%!assert (mod (0, 3), 0)\n%!assert (mod ([-5, 5, 0], [3, 3, 3]), [1, 2, 0])\n%!assert (mod ([-5; 5; 0], [3; 3; 3]), [1; 2; 0])\n%!assert (mod ([-5, 5; 0, 3], [3, 3 ; 3, 1]), [1, 2 ; 0, 0])\n\n## x mod 0 tests\n%!assert (mod (5, 0), 5)\n%!assert (mod (-5, 0), -5)\n%!assert (mod ([-5, 5, 0], [3, 0, 3]), [1, 5, 0])\n%!assert (mod ([-5; 5; 0], [3; 0; 3]), [1; 5; 0])\n%!assert (mod ([-5, 5; 0, 3], [3, 0 ; 3, 1]), [1, 5 ; 0, 0])\n%!assert (mod ([-5, 5; 0, 3], [0, 0 ; 0, 0]), [-5, 5; 0, 3])\n\n## mixed scalar/matrix tests\n%!assert (mod ([-5, 5; 0, 3], 0), [-5, 5; 0, 3])\n%!assert (mod ([-5, 5; 0, 3], 3), [1, 2; 0, 0])\n%!assert (mod (-5, [0,0; 0,0]), [-5, -5; -5, -5])\n%!assert (mod (-5, [3,0; 3,1]), [1, -5; 1, 0])\n%!assert (mod (-5, [3,2; 3,1]), [1, 1; 1, 0])\n\n## integer types\n%!assert (mod (uint8 (5), uint8 (4)), uint8 (1))\n%!assert (mod (uint8 ([1:5]), uint8 (4)), uint8 ([1,2,3,0,1]))\n%!assert (mod (uint8 ([1:5]), uint8 (0)), uint8 ([1:5]))\n%!error mod (uint8 (5), int8 (4))\n\n## mixed integer/real types\n%!assert (mod (uint8 (5), 4), uint8 (1))\n%!assert (mod (5, uint8 (4)), uint8 (1))\n%!assert (mod (uint8 ([1:5]), 4), uint8 ([1,2,3,0,1]))\n\n## non-integer real numbers\n%!assert (mod (2.1, 0.1), 0)\n%!assert (mod (2.1, 0.2), 0.1, eps)\n\n%!assert <*45587> (signbit (mod (-0, 0)))\n%!assert <*45587> (! signbit (mod (0, -0)))\n\n%!assert <*42627> (mod (0.94, 0.01), 0.0)\n\n%!assert <*54602> (mod (int8 (125), int8 (-25)), int8 (0))\n%!assert <*54602> (mod (int8 (-125), int8 (-25)), int8 (0))\n%!assert <*54602> (mod (int8 (-125), int8 (0)), int8 (-125))\n%!assert <*54602> (mod (int8 (0), int8 (-25)), int8 (0))\n\n## Test mod (x-1, x) for x close to flintmax.  Should return x-1 and not zero.\n%!test <*67339>\n%! x = flintmax - (10:-1:1);\n%! assert (mod (x-1, x), x-1);\n%! x = flintmax (\"single\") - (10:-1:1);\n%! assert (mod (x-1, x), x-1);\n*/\n\nDEFUN (cumprod, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} cumprod (@var{x})\n@deftypefnx {} {@var{y} =} cumprod (@var{x}, @var{dim})\n@deftypefnx {} {@var{y} =} cumprod (@var{x}, @var{vecdim})\n@deftypefnx {} {@var{y} =} cumprod (@dots{}, \"all\")\n@deftypefnx {} {@var{y} =} cumprod (@dots{}, @var{direction})\n@deftypefnx {} {@var{y} =} cumprod (@dots{}, @var{nanflag})\nCompute the cumulative product of elements in @var{x}.\n\nIf @var{x} is a vector, then @code{cumprod (@var{x})} returns a vector of the\nsame size with the cumulative product of @var{x}.\n\nIf @var{x} is a matrix, then @code{cumprod (@var{x})} returns a matrix of the\nsame size with the cumulative product along each column of @var{x}.\n\nIf @var{x} is an array, then @code{cumprod(@var{x})} returns an array of the\nsame size with the cumulative product along the first non-singleton dimension\nof @var{x}.\n\nThe class of output @var{y} is the same as the class of input @var{x}, unless\n@var{x} is logical, in which case @var{y} is double.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension in @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{cumprod} to operate\non all elements of @var{x}, and is equivalent to @code{cumprod (@var{x}(:))}.\n\nThe optional input @var{direction} specifies how the operating dimension is\ntraversed and can take the following values:\n\n@table @asis\n@item @qcode{\"forward\"} (default)\n\nThe cumulative product is computed from beginning (index 1) to end along the\noperating dimension.\n\n@item @qcode{\"reverse\"}\n\nThe cumulative product is computed from end to beginning along the operating\ndimension.\n@end table\n\nThe optional variable @var{nanflag} specifies whether to include or exclude\nNaN values from the calculation using any of the previously specified input\nargument combinations.  The default value for @var{nanflag} is\n@qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\nNaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\nwill still contain NaN values if @var{x} consists of all NaN values in the\noperating dimension.\n@seealso{prod, cumsum}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  bool direction = false;\n  bool do_perm = false;\n  bool allflag = false;\n  bool nanflag = false;\n\n  while (nargin > 1 && args(nargin - 1).is_string ())\n    {\n      std::string str = args(nargin - 1).string_value ();\n\n      if (str == \"forward\")\n        direction = false;\n      else if (str == \"reverse\")\n        direction = true;\n      else if (str == \"all\")\n        allflag = true;\n      else if (str == \"omitnan\" || str == \"omitmissing\")\n        {\n          if (args(0).is_double_type () || args(0).is_single_type ())\n            nanflag = true;\n        }\n      else if (str == \"includenan\" || str == \"includemissing\")\n        nanflag = false;\n      else\n        error (\"cumprod: unrecognized optional argument '%s'\", str.c_str ());\n\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  if (allflag && nargin > 1)\n    error (\"cumprod: cannot set DIM or VECDIM with 'all' flag\");\n\n  octave_value arg = args(0);\n\n  // Handle DIM, VECDIM\n  int dim = -1;\n  Array<int> perm_vec;\n  if (nargin == 2)\n    {\n      octave_value dimarg = args(1);\n      get_dim_vecdim_all (dimarg, arg, dim, perm_vec, do_perm, allflag, \"cumprod\");\n    }\n\n  // Handle allflag\n  if (allflag)\n    arg = arg.reshape (dim_vector (arg.numel (), 1));\n\n  octave_value retval;\n\n  switch (arg.builtin_type ())\n    {\n    case btyp_double:\n      if (arg.issparse ())\n        {\n          if (direction)\n            error (\"cumprod: DIRECTION is not supported for sparse matrices\");\n          else\n            retval = arg.sparse_matrix_value ().cumprod (dim, nanflag);\n        }\n      else\n        {\n          if (direction)\n            retval = arg.array_value ().flip (dim).cumprod (dim, nanflag).flip (dim);\n          else\n            retval = arg.array_value ().cumprod (dim, nanflag);\n        }\n      break;\n\n    case btyp_complex:\n      if (arg.issparse ())\n        {\n          if (direction)\n            error (\"cumprod: DIRECTION is not supported for sparse matrices\");\n          else\n            retval = arg.sparse_complex_matrix_value ().cumprod (dim, nanflag);\n        }\n      else\n        {\n          if (direction)\n            retval = arg.complex_array_value ().flip (dim).cumprod (dim, nanflag).flip (dim);\n          else\n            retval = arg.complex_array_value ().cumprod (dim, nanflag);\n        }\n      break;\n\n    case btyp_float:\n      if (direction)\n        retval = arg.float_array_value ().flip (dim).cumprod (dim, nanflag).flip (dim);\n      else\n        retval = arg.float_array_value ().cumprod (dim, nanflag);\n      break;\n\n    case btyp_float_complex:\n      if (direction)\n        retval = arg.float_complex_array_value ().flip (dim).cumprod (dim, nanflag).flip (dim);\n      else\n        retval = arg.float_complex_array_value ().cumprod (dim, nanflag);\n      break;\n\n#define MAKE_INT_BRANCH(X)                                            \\\n      case btyp_ ## X:                                                \\\n        if (direction)                                                \\\n          retval = arg.X ## _array_value ().flip (dim).cumprod (dim).flip (dim);  \\\n        else                                                          \\\n          retval = arg.X ## _array_value ().cumprod (dim);            \\\n        break;\n\n      MAKE_INT_BRANCH (int8);\n      MAKE_INT_BRANCH (int16);\n      MAKE_INT_BRANCH (int32);\n      MAKE_INT_BRANCH (int64);\n      MAKE_INT_BRANCH (uint8);\n      MAKE_INT_BRANCH (uint16);\n      MAKE_INT_BRANCH (uint32);\n      MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n    case btyp_bool:\n      if (arg.issparse ())\n        {\n          if (direction)\n            error (\"cumprod: DIRECTION is not supported for sparse matrices\");\n          retval = arg.sparse_matrix_value ().cumprod (dim);\n        }\n      else\n        {\n          if (direction)\n            retval = arg.array_value ().flip (dim).cumprod (dim).flip (dim);\n          else\n            retval = arg.array_value ().cumprod (dim);\n        }\n      break;\n\n    default:\n      err_wrong_type_arg (\"cumprod\", arg);\n    }\n\n  if (do_perm)\n    retval = retval.permute (perm_vec, true);\n\n  return retval;\n}\n\n/*\n%!assert (cumprod ([1, 2, 3]), [1, 2, 6])\n%!assert (cumprod ([-1; -2; -3]), [-1; 2; -6])\n%!assert (cumprod ([i, 2+i, -3+2i, 4]), [i, -1+2i, -1-8i, -4-32i])\n%!assert (cumprod ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]),\n%!        [1, 2, 3; i, 4i, 9i; -1+i, -8+8i, -27+27i])\n\n%!assert (cumprod (single ([1, 2, 3])), single ([1, 2, 6]))\n%!assert (cumprod (single ([-1; -2; -3])), single ([-1; 2; -6]))\n%!assert (cumprod (single ([i, 2+i, -3+2i, 4])),\n%!        single ([i, -1+2i, -1-8i, -4-32i]))\n%!assert (cumprod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])),\n%!        single ([1, 2, 3; i, 4i, 9i; -1+i, -8+8i, -27+27i]))\n\n%!assert (cumprod ([2, 3; 4, 5], 1), [2, 3; 8, 15])\n%!assert (cumprod ([2, 3; 4, 5], 2), [2, 6; 4, 20])\n\n%!assert (cumprod (single ([2, 3; 4, 5]), 1), single ([2, 3; 8, 15]))\n%!assert (cumprod (single ([2, 3; 4, 5]), 2), single ([2, 6; 4, 20]))\n\n%!test\n%! x = reshape ([1:8], 2, 2, 2);\n%! y = cumprod (x);\n%! assert (y(:,:,1), [1, 3; 2, 12]);\n%! assert (y(:,:,2), [5, 7; 30, 56]);\n%! assert (flip (cumprod (flip (x))), cumprod (x, \"reverse\"));\n%! y = cumprod (x, 2);\n%! assert (y(:,:,1), [1, 3; 2, 8]);\n%! assert (y(:,:,2), [5, 35; 6, 48]);\n%! y = cumprod (x, 2, \"reverse\");\n%! assert (y(:,:,1), [3, 3; 8, 4]);\n%! assert (y(:,:,2), [35, 7; 48, 8]);\n%! assert (flip (cumprod (flip (x, 2), 2), 2), cumprod (x, 2, \"reverse\"));\n%! y = cumprod (x, [1, 2]);\n%! assert (y(:,:,1), [1; 2; 6; 24]);\n%! assert (y(:,:,2), [5; 30; 210; 1680]);\n%! y = cumprod (x, [1, 3]);\n%! assert (y(:,1), [1; 2; 10; 60]);\n%! assert (y(:,2), [3; 12; 84; 672]);\n%! y = cumprod (x, [2, 3]);\n%! assert (y(1,:), [1, 3, 15, 105]);\n%! assert (y(2,:), [2, 8, 48, 384]);\n%! assert (cumprod (x, [1, 2, 3]), cumprod (x, \"all\"));\n\n## Test exceeding dimensions\n%!test\n%! x = reshape ([1:8], 2, 2, 2);\n%! x(3) = NaN;\n%! y = cumprod (x);\n%! assert (y(:,:,1), [1, NaN; 2, NaN]);\n%! y = cumprod (x, \"omitnan\");\n%! assert (y(:,:,1), [1, 1; 2, 4]);\n%! assert (flip (cumprod (flip (x))), cumprod (x, \"reverse\"));\n%! assert (flip (cumprod (flip (x), \"omitnan\")),\n%!         cumprod (x, \"reverse\", \"omitnan\"));\n%! y = cumprod (x, 2);\n%! assert (y(:,:,1), [1, NaN; 2, 8]);\n%! y = cumprod (x, 2, \"omitnan\");\n%! assert (y(:,:,1), [1, 1; 2, 8]);\n%! y = cumprod (x, 2, \"reverse\");\n%! assert (y(:,:,1), [NaN, NaN; 8, 4]);\n%! y = cumprod (x, 2, \"reverse\", \"omitnan\");\n%! assert (y(:,:,1), [1, 1; 8, 4]);\n%! assert (flip (cumprod (flip (x, 3), 3), 3), cumprod (x, 3, \"reverse\"));\n%! assert (flip (cumprod (flip (x, 3), 3, \"omitnan\"), 3),\n%!         cumprod (x, 3, \"reverse\", \"omitnan\"));\n%! y = cumprod (x, [1, 2]);\n%! assert (y(:,:,1), [1; 2; NaN; NaN]);\n%! y = cumprod (x, [1, 2], \"omitnan\");\n%! assert (y(:,:,1), [1; 2; 2; 8]);\n%! y = cumprod (x, [1, 2], \"reverse\");\n%! assert (y(:,:,1), [NaN; NaN; NaN; 4]);\n%! assert (y(:,:,2), [1680; 336; 56; 8]);\n%! y = cumprod (x, [1, 2], \"reverse\", \"omitnan\");\n%! assert (y(:,:,1), [8; 8; 4; 4]);\n%! y = cumprod (x, [1, 3]);\n%! assert (y(:,1), [1; 2; 10; 60]);\n%! assert (y(:,2), nan (4, 1));\n%! y = cumprod (x, [1, 3], \"omitnan\");\n%! assert (y(:,2), [1; 4; 28; 224]);\n%! y = cumprod (x, [1, 3], \"omitnan\", \"reverse\");\n%! assert (y(:,1), [60; 60; 30; 6]);\n%! assert (y(:,2), [224; 224; 56; 8]);\n%! y = cumprod (x, [2, 3], \"omitnan\");\n%! assert (y(1,:), [1, 1, 5, 35]);\n%! y = cumprod (x, [2, 3], \"omitnan\", \"reverse\");\n%! assert (y(1,:), [35, 35, 35, 7]);\n%! assert (y(2,:), [384, 192, 48, 8]);\n%! assert (cumprod (x, [1, 2, 3]), cumprod (x, \"all\"));\n\n## Test exceeding dimensions\n%!test\n%! x = reshape ([1:8], 2, 2, 2);\n%! assert (cumprod (x, 4), x);\n%! assert (cumprod (x, 2), cumprod (x, [2, 4]));\n%! assert (cumprod (x, 2, \"reverse\"), cumprod (x, [2, 4], \"reverse\"));\n%! x(3) = NaN;\n%! assert (cumprod (x, 4), x);\n%! y = x;\n%! y(3) = 1;\n%! assert (cumprod (x, 4, \"omitnan\"), y);\n%! assert (cumprod (x, 2, \"omitnan\"), cumprod (x, [2, 4], \"omitnan\"));\n%! assert (cumprod (x, 2, \"reverse\", \"omitnan\"),\n%!         cumprod (x, [2, 4], \"reverse\", \"omitnan\"));\n%!assert (cumprod (sparse ([1, 2; 3, 4]), 3), sparse ([1, 2; 3, 4]))\n%!assert (cumprod (sparse ([1, 2i; 3, 4]), 3), sparse ([1, 2i; 3, 4]))\n\n%!test\n%! x = ones (3);\n%! assert (class (cumprod (uint8 (x))), \"uint8\");\n%! assert (cumprod (x), cumprod (x, \"omitnan\"));\n%! assert (class (cumprod (uint16 (x))), \"uint16\");\n%! assert (class (cumprod (uint32 (x))), \"uint32\");\n%! assert (class (cumprod (uint64 (x))), \"uint64\");\n%! assert (class (cumprod (int8 (x))), \"int8\");\n%! assert (class (cumprod (int16 (x))), \"int16\");\n%! assert (class (cumprod (int32 (x))), \"int32\");\n%! assert (class (cumprod (int64 (x))), \"int64\");\n%!assert (class (cumprod ([true, false])), \"double\")\n%!assert (cumprod ([true, false]), [1, 0])\n%!assert (cumprod ([true, false], \"reverse\"), [0, 0])\n\n%!assert (cumprod (ones (2), 4), ones (2))\n%!assert (cumprod (ones (2), [4, 5]), ones (2))\n%!assert (cumprod (single (ones (2)), 4),single (ones (2)))\n%!assert (cumprod (single (ones (2)), [4, 5]),single (ones (2)))\n\n%!assert (cumprod ([NaN, NaN], \"omitnan\"), [1, 1])\n\n## Test sparse matrices\n%!assert (cumprod (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN])),\n%!        sparse ([NaN, NaN, 1, 4, 2; NaN, NaN, 1, 8, NaN]))\n%!assert (cumprod (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), \"omitnan\"),\n%!        sparse ([1, 1, 1, 4, 2; 1, 2, 1, 8, 2]))\n%!assert (cumprod (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2),\n%!        sparse ([NaN, NaN, NaN, NaN, NaN; 1, 2, 2, 4, NaN]))\n%!assert (cumprod (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([1, 1, 1, 4, 8; 1, 2, 2, 4, 4]))\n%!assert (cumprod (sparse ([NaN, NaN, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([1, 1, 1i, 4i, 8i; 1, 2, 2, 4, 4]))\n%!assert (cumprod (sparse ([NaN, 0i, 1, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([1, 0, 0, 0, 0; 1, 2, 2, 4, 4]))\n\n## Test input validation\n%!error <Invalid call> cumprod ()\n%!error <Invalid call> cumprod (1,2,3)\n%!error <unrecognized optional argument 'foobar'> cumprod (1, \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! cumprod (ones (3,3), 1, \"all\");\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! cumprod (ones (3,3), [1, 2], \"all\");\n%!error <invalid dimension DIM = 0> cumprod (ones (3,3), 0)\n%!error <invalid dimension DIM = -1> cumprod (ones (3,3), -1)\n%!error <invalid dimension in VECDIM = -2> cumprod (ones (3), [1 -2])\n%!error <duplicate dimension in VECDIM = 2> cumprod (ones (3), [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> cumprod (ones (3), [1 1 2])\n%!error <DIRECTION is not supported for sparse matrices>\n%! cumprod (sparse (ones (3,3)), \"reverse\");\n*/\n\nDEFUN (cumsum, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} cumsum (@var{x})\n@deftypefnx {} {@var{y} =} cumsum (@var{x}, @var{dim})\n@deftypefnx {} {@var{y} =} cumsum (@var{x}, @var{vecdim})\n@deftypefnx {} {@var{y} =} cumsum (@dots{}, \"all\")\n@deftypefnx {} {@var{y} =} cumsum (@dots{}, @var{direction})\n@deftypefnx {} {@var{y} =} cumsum (@dots{}, @var{nanflag})\nCompute the cumulative sum of elements in @var{x}.\n\nIf @var{x} is a vector, then @code{cumsum (@var{x})} returns a vector of the\nsame size with the cumulative sum of @var{x}.\n\nIf @var{x} is a matrix, then @code{cumsum (@var{x})} returns a matrix of the\nsame size with the cumulative sum along each column of @var{x}.\n\nIf @var{x} is an array, then @code{cumsum(@var{x})} returns an array of the\nsame size with the cumulative sum along the first non-singleton dimension of\n@var{x}.\n\nThe class of output @var{y} is the same as the class of input @var{x}, unless\n@var{x} is logical, in which case @var{y} is double.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension in @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{cumsum} to operate\non all elements of @var{x}, and is equivalent to @code{cumsum (@var{x}(:))}.\n\nThe optional input @var{direction} specifies how the operating dimension is\ntraversed and can take the following values:\n\n@table @asis\n@item @qcode{\"forward\"} (default)\n\nThe cumulative sum is computed from beginning (index 1) to end along the\noperating dimension.\n\n@item @qcode{\"reverse\"}\n\nThe cumulative sum is computed from end to beginning along the operating\ndimension.\n@end table\n\nThe optional variable @var{nanflag} specifies whether to include or exclude\nNaN values from the calculation using any of the previously specified input\nargument combinations.  The default value for @var{nanflag} is\n@qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\nNaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\nwill still contain NaN values if @var{x} consists of all NaN values in the\noperating dimension.\n@seealso{sum, cumprod}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  bool direction = false;\n  bool do_perm = false;\n  bool allflag = false;\n  bool nanflag = false;\n\n  while (nargin > 1 && args(nargin - 1).is_string ())\n    {\n      std::string str = args(nargin - 1).string_value ();\n\n      if (str == \"forward\")\n        direction = false;\n      else if (str == \"reverse\")\n        direction = true;\n      else if (str == \"all\")\n        allflag = true;\n      else if (str == \"omitnan\" || str == \"omitmissing\")\n        {\n          if (args(0).is_double_type () || args(0).is_single_type ())\n            nanflag = true;\n        }\n      else if (str == \"includenan\" || str == \"includemissing\")\n        nanflag = false;\n      else\n        error (\"cumsum: unrecognized optional argument '%s'\", str.c_str ());\n\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  if (allflag && nargin > 1)\n    error (\"cumsum: cannot set DIM or VECDIM with 'all' flag\");\n\n  octave_value arg = args(0);\n\n  // Handle DIM, VECDIM\n  int dim = -1;\n  Array<int> perm_vec;\n  if (nargin == 2)\n    {\n      octave_value dimarg = args(1);\n      get_dim_vecdim_all (dimarg, arg, dim, perm_vec, do_perm, allflag, \"cumsum\");\n    }\n\n  // Handle allflag\n  if (allflag)\n    arg = arg.reshape (dim_vector (arg.numel (), 1));\n\n  octave_value retval;\n\n  switch (arg.builtin_type ())\n    {\n    case btyp_double:\n      if (arg.issparse ())\n        {\n          if (direction)\n            error (\"cumsum: DIRECTION is not supported for sparse matrices\");\n          else\n            retval = arg.sparse_matrix_value ().cumsum (dim, nanflag);\n        }\n      else\n        {\n          if (direction)\n            retval = arg.array_value ().flip (dim).cumsum (dim, nanflag).flip (dim);\n          else\n            retval = arg.array_value ().cumsum (dim, nanflag);\n        }\n      break;\n\n    case btyp_complex:\n      if (arg.issparse ())\n        {\n          if (direction)\n            error (\"cumsum: DIRECTION is not supported for sparse matrices\");\n          else\n            retval = arg.sparse_complex_matrix_value ().cumsum (dim, nanflag);\n        }\n      else\n        {\n          if (direction)\n            retval = arg.complex_array_value ().flip (dim).cumsum (dim, nanflag).flip (dim);\n          else\n            retval = arg.complex_array_value ().cumsum (dim, nanflag);\n        }\n      break;\n\n    case btyp_float:\n      if (direction)\n        retval = arg.float_array_value ().flip (dim).cumsum (dim, nanflag).flip (dim);\n      else\n        retval = arg.float_array_value ().cumsum (dim, nanflag);\n      break;\n\n    case btyp_float_complex:\n      if (direction)\n        retval = arg.float_complex_array_value ().flip (dim).cumsum (dim, nanflag).flip (dim);\n      else\n        retval = arg.float_complex_array_value ().cumsum (dim, nanflag);\n      break;\n\n#define MAKE_INT_BRANCH(X)                                            \\\n      case btyp_ ## X:                                                \\\n        if (direction)                                                \\\n          retval = arg.X ## _array_value ().flip (dim).cumsum (dim).flip (dim);  \\\n        else                                                          \\\n          retval = arg.X ## _array_value ().cumsum (dim);             \\\n        break;\n\n      MAKE_INT_BRANCH (int8);\n      MAKE_INT_BRANCH (int16);\n      MAKE_INT_BRANCH (int32);\n      MAKE_INT_BRANCH (int64);\n      MAKE_INT_BRANCH (uint8);\n      MAKE_INT_BRANCH (uint16);\n      MAKE_INT_BRANCH (uint32);\n      MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n    case btyp_bool:\n      if (arg.issparse ())\n        {\n          if (direction)\n            error (\"cumsum: DIRECTION is not supported for sparse matrices\");\n          retval = arg.sparse_matrix_value ().cumsum (dim);\n        }\n      else\n        {\n          // OPTIMIZED: Direct boolean cumulative count\n          boolNDArray m = arg.bool_array_value ();\n\n          if (dim < 0)\n            dim = m.dims ().first_non_singleton ();\n\n          if (dim >= m.ndims ())\n            {\n              retval = NDArray (m);\n              break;\n            }\n\n          // Calculate extent triplet (l, n, u) for column-major indexing\n          dim_vector dv = m.dims ();\n          octave_idx_type l = 1;\n          for (int i = 0; i < dim; i++)\n            l *= dv(i);\n\n          octave_idx_type n = dv(dim);\n\n          octave_idx_type u = 1;\n          for (int i = dim + 1; i < dv.ndims (); i++)\n            u *= dv(i);\n\n          NDArray result (dv);\n          const bool *data = m.data ();\n          double *r = result.rwdata ();\n\n          if (direction)\n            {\n              // Reverse direction\n              for (octave_idx_type outer = 0; outer < u; outer++)\n                {\n                  const octave_idx_type outer_base = outer * n * l;\n                  for (octave_idx_type inner = 0; inner < l; inner++)\n                    {\n                      double cumval = 0.0;\n                      octave_idx_type base = outer_base + inner;\n\n                      // walk from last to first\n                      for (octave_idx_type j = n - 1; j >= 0; j--)\n                        {\n                          octave_idx_type idx = base + j * l;\n                          cumval += data[idx];\n                          r[idx] = cumval;\n                        }\n                    }\n                }\n            }\n          else\n            {\n              // Forward direction\n              for (octave_idx_type outer = 0; outer < u; outer++)\n                {\n                  const octave_idx_type outer_base = outer * n * l;\n                  for (octave_idx_type inner = 0; inner < l; inner++)\n                    {\n                      double cumval = 0.0;\n                      octave_idx_type base = outer_base + inner;\n                      for (octave_idx_type j = 0; j < n; j++)\n                        {\n                          octave_idx_type idx = base + j * l;\n                          cumval += data[idx];\n                          r[idx] = cumval;\n                        }\n                    }\n                }\n            }\n\n          retval = result;\n        }\n      break;\n\n    default:\n      err_wrong_type_arg (\"cumsum\", arg);\n    }\n\n  if (do_perm)\n    retval = retval.permute (perm_vec, true);\n\n  return retval;\n}\n\n/*\n%!assert (cumsum ([1, 2, 3]), [1, 3, 6])\n%!assert (cumsum ([-1; -2; -3]), [-1; -3; -6])\n%!assert (cumsum ([i, 2+i, -3+2i, 4]), [i, 2+2i, -1+4i, 3+4i])\n%!assert (cumsum ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]),\n%!        [1, 2, 3; 1+i, 2+2i, 3+3i; 2+2i, 4+4i, 6+6i])\n\n%!assert (cumsum (single ([1, 2, 3])), single ([1, 3, 6]))\n%!assert (cumsum (single ([-1; -2; -3])), single ([-1; -3; -6]))\n%!assert (cumsum (single ([i, 2+i, -3+2i, 4])),\n%!        single ([i, 2+2i, -1+4i, 3+4i]))\n%!assert (cumsum (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])),\n%!        single ([1, 2, 3; 1+i, 2+2i, 3+3i; 2+2i, 4+4i, 6+6i]))\n\n%!assert (cumsum ([1, 2; 3, 4], 1), [1, 2; 4, 6])\n%!assert (cumsum ([1, 2; 3, 4], 2), [1, 3; 3, 7])\n\n%!assert (cumsum (single ([1, 2; 3, 4]), 1), single ([1, 2; 4, 6]))\n%!assert (cumsum (single ([1, 2; 3, 4]), 2), single ([1, 3; 3, 7]))\n\n%!test\n%! x = reshape ([1:8], 2, 2, 2);\n%! y = cumsum (x);\n%! assert (y(:,:,1), [1, 3; 3, 7]);\n%! assert (y(:,:,2), [5, 7; 11, 15]);\n%! assert (flip (cumsum (flip (x))), cumsum (x, \"reverse\"));\n%! y = cumsum (x, 2);\n%! assert (y(:,:,1), [1, 4; 2, 6]);\n%! assert (y(:,:,2), [5, 12; 6, 14]);\n%! y = cumsum (x, 2, \"reverse\");\n%! assert (y(:,:,1), [4, 3; 6, 4]);\n%! assert (y(:,:,2), [12, 7; 14, 8]);\n%! assert (flip (cumsum (flip (x, 2), 2), 2), cumsum (x, 2, \"reverse\"));\n%! y = cumsum (x, [1, 2]);\n%! assert (y(:,:,1), [1; 3; 6; 10]);\n%! assert (y(:,:,2), [5; 11; 18; 26]);\n%! y = cumsum (x, [1, 3]);\n%! assert (y(:,1), [1; 3; 8; 14]);\n%! assert (y(:,2), [3; 7; 14; 22]);\n%! y = cumsum (x, [2, 3]);\n%! assert (y(1,:), [1, 4, 9, 16]);\n%! assert (y(2,:), [2, 6, 12, 20]);\n%! assert (cumsum (x, [1, 2, 3]), cumsum (x, \"all\"));\n\n## Test exceeding dimensions\n%!test\n%! x = reshape ([1:8], 2, 2, 2);\n%! x(3) = NaN;\n%! y = cumsum (x);\n%! assert (y(:,:,1), [1, NaN; 3, NaN]);\n%! y = cumsum (x, \"omitnan\");\n%! assert (y(:,:,1), [1, 0; 3, 4]);\n%! assert (flip (cumsum (flip (x))), cumsum (x, \"reverse\"));\n%! assert (flip (cumsum (flip (x), \"omitnan\")),\n%!         cumsum (x, \"reverse\", \"omitnan\"));\n%! y = cumsum (x, 2);\n%! assert (y(:,:,1), [1, NaN; 2, 6]);\n%! y = cumsum (x, 2, \"omitnan\");\n%! assert (y(:,:,1), [1, 1; 2, 6]);\n%! y = cumsum (x, 2, \"reverse\");\n%! assert (y(:,:,1), [NaN, NaN; 6, 4]);\n%! y = cumsum (x, 2, \"reverse\", \"omitnan\");\n%! assert (y(:,:,1), [1, 0; 6, 4]);\n%! assert (flip (cumsum (flip (x, 3), 3), 3), cumsum (x, 3, \"reverse\"));\n%! assert (flip (cumsum (flip (x, 3), 3, \"omitnan\"), 3),\n%!         cumsum (x, 3, \"reverse\", \"omitnan\"));\n%! y = cumsum (x, [1, 2]);\n%! assert (y(:,:,1), [1; 3; NaN; NaN]);\n%! y = cumsum (x, [1, 2], \"omitnan\");\n%! assert (y(:,:,1), [1; 3; 3; 7]);\n%! y = cumsum (x, [1, 2], \"reverse\");\n%! assert (y(:,:,1), [NaN; NaN; NaN; 4]);\n%! assert (y(:,:,2), [26; 21; 15; 8]);\n%! y = cumsum (x, [1, 2], \"reverse\", \"omitnan\");\n%! assert (y(:,:,1), [7; 6; 4; 4]);\n%! assert (y(:,:,2), [26; 21; 15; 8]);\n%! y = cumsum (x, [1, 3]);\n%! assert (y(:,1), [1; 3; 8; 14]);\n%! assert (y(:,2), nan (4, 1));\n%! y = cumsum (x, [1, 3], \"omitnan\");\n%! assert (y(:,2), [0; 4; 11; 19]);\n%! y = cumsum (x, [1, 3], \"omitnan\", \"reverse\");\n%! assert (y(:,1), [14; 13; 11; 6]);\n%! assert (y(:,2), [19; 19; 15; 8]);\n%! y = cumsum (x, [2, 3], \"omitnan\");\n%! assert (y(1,:), [1, 1, 6, 13]);\n%! y = cumsum (x, [2, 3], \"omitnan\", \"reverse\");\n%! assert (y(1,:), [13, 12, 12, 7]);\n%! assert (y(2,:), [20, 18, 14, 8]);\n%! assert (cumsum (x, [1, 2, 3]), cumsum (x, \"all\"));\n\n## Test exceeding dimensions\n%!test\n%! x = reshape ([1:8], 2, 2, 2);\n%! assert (cumsum (x, 4), x);\n%! assert (cumsum (x, 2), cumsum (x, [2, 4]));\n%! assert (cumsum (x, 2, \"reverse\"), cumsum (x, [2, 4], \"reverse\"));\n%! x(3) = NaN;\n%! assert (cumsum (x, 4), x);\n%! y = x;\n%! y(3) = 0;\n%! assert (cumsum (x, 4, \"omitnan\"), y);\n%! assert (cumsum (x, 2, \"omitnan\"), cumsum (x, [2, 4], \"omitnan\"));\n%! assert (cumsum (x, 2, \"reverse\", \"omitnan\"),\n%!         cumsum (x, [2, 4], \"reverse\", \"omitnan\"));\n%!assert (cumsum (sparse ([1, 2; 3, 4]), 3), sparse ([1, 2; 3, 4]))\n%!assert (cumsum (sparse ([1, 2i; 3, 4]), 3), sparse ([1, 2i; 3, 4]))\n\n%!test\n%! x = ones (3);\n%! assert (class (cumsum (uint8 (x))), \"uint8\");\n%! assert (cumsum (x), cumsum (x, \"omitnan\"));\n%! assert (class (cumsum (uint16 (x))), \"uint16\");\n%! assert (class (cumsum (uint32 (x))), \"uint32\");\n%! assert (class (cumsum (uint64 (x))), \"uint64\");\n%! assert (class (cumsum (int8 (x))), \"int8\");\n%! assert (class (cumsum (int16 (x))), \"int16\");\n%! assert (class (cumsum (int32 (x))), \"int32\");\n%! assert (class (cumsum (int64 (x))), \"int64\");\n%!assert (class (cumsum ([true, false])), \"double\")\n%!assert (cumsum ([true, false]), [1, 1])\n%!assert (cumsum ([true, false], \"reverse\"), [1, 0])\n\n%!assert (cumsum (ones (2), 4), ones (2))\n%!assert (cumsum (ones (2), [4, 5]), ones (2))\n%!assert (cumsum (single (ones (2)), 4),single (ones (2)))\n%!assert (cumsum (single (ones (2)), [4, 5]),single (ones (2)))\n\n%!assert (cumsum ([NaN, NaN], \"omitnan\"), [0, 0])\n\n## Test sparse matrices\n%!assert (cumsum (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN])),\n%!        sparse ([NaN, NaN, 1, 4, 2; NaN, NaN, 2, 6, NaN]))\n%!assert (cumsum (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), \"omitnan\"),\n%!        sparse ([0, 0, 1, 4, 2; 1, 2, 2, 6, 2]))\n%!assert (cumsum (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2),\n%!        sparse ([NaN, NaN, NaN, NaN, NaN; 1, 3, 4, 6, NaN]))\n%!assert (cumsum (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([0, 0, 1, 5, 7; 1, 3, 4, 6, 6]))\n%!assert (cumsum (sparse ([NaN, NaN, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([0, 0, 1i, 4+i, 6+i; 1, 3, 4, 6, 6]))\n%!assert (cumsum (sparse ([NaN, 0i, 1, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([0, 0, 1, 5, 7; 1, 3, 4, 6, 6]))\n\n## Test input validation\n%!error <Invalid call> cumsum ()\n%!error <Invalid call> cumsum (1,2,3)\n%!error <unrecognized optional argument 'foobar'> cumsum (1, \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag> ...\n%!      cumsum (ones (3,3), 1, \"all\")\n%!error <cannot set DIM or VECDIM with 'all' flag> ...\n%!      cumsum (ones (3,3), [1, 2], \"all\")\n%!error <invalid dimension DIM = 0> cumsum (ones (3,3), 0)\n%!error <invalid dimension DIM = -1> cumsum (ones (3,3), -1)\n%!error <invalid dimension in VECDIM = -2> cumsum (ones (3), [1 -2])\n%!error <duplicate dimension in VECDIM = 2> cumsum (ones (3), [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> cumsum (ones (3), [1 1 2])\n%!error <DIRECTION is not supported for sparse matrices> ...\n%!      cumsum (sparse (ones (3,3)), \"reverse\")\n*/\n\n/* Additional cumsum boolean tests\n%!test\n%! x = [true, false, true; false, true, false];\n%! assert (cumsum (x, 1), [1, 0, 1; 1, 1, 1]);\n%! assert (cumsum (x, 2), [1, 1, 2; 0, 1, 1]);\n\n%!test\n%! x = rand (100, 100) > 0.5;\n%! assert (cumsum (x, 2), cumsum (double (x), 2));\n*/\n\nDEFUN (diag, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{M} =} diag (@var{v})\n@deftypefnx {} {@var{M} =} diag (@var{v}, @var{k})\n@deftypefnx {} {@var{M} =} diag (@var{v}, @var{m}, @var{n})\n@deftypefnx {} {@var{v} =} diag (@var{M})\n@deftypefnx {} {@var{v} =} diag (@var{M}, @var{k})\nReturn a diagonal matrix with vector @var{v} on diagonal @var{k}.\n\nThe second argument is optional.  If it is positive, the vector is placed on\nthe @var{k}-th superdiagonal.  If it is negative, it is placed on the\n@var{-k}-th subdiagonal.  The default value of @var{k} is 0, and the vector\nis placed on the main diagonal.  For example:\n\n@example\n@group\ndiag ([1, 2, 3], 1)\n   @xresult{}  0  1  0  0\n       0  0  2  0\n       0  0  0  3\n       0  0  0  0\n@end group\n@end example\n\n@noindent\nThe 3-input form returns a diagonal matrix with vector @var{v} on the main\ndiagonal and the resulting matrix being of size @var{m} rows x @var{n}\ncolumns.\n\nGiven a matrix argument, instead of a vector, @code{diag} extracts the\n@var{k}-th diagonal of the matrix.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 1)\n    retval = args(0).diag ();\n  else if (nargin == 2)\n    {\n      octave_idx_type k = args(1).strict_idx_type_value (\"diag: invalid argument K\");\n\n      retval = args(0).diag (k);\n    }\n  else\n    {\n      octave_value arg0 = args(0);\n\n      if (arg0.ndims () != 2 || (arg0.rows () != 1 && arg0.columns () != 1))\n        error (\"diag: V must be a vector\");\n\n      octave_idx_type m = args(1).strict_idx_type_value (\"diag: invalid dimension M\");\n      octave_idx_type n = args(2).strict_idx_type_value (\"diag: invalid dimension N\");\n\n      retval = arg0.diag (m, n);\n    }\n\n  return retval;\n}\n\n/*\n\n%!assert (full (diag ([1; 2; 3])), [1, 0, 0; 0, 2, 0; 0, 0, 3])\n%!assert (diag ([1; 2; 3], 1),\n%!        [0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0])\n%!assert (diag ([1; 2; 3], 2),\n%!        [0 0 1 0 0; 0 0 0 2 0; 0 0 0 0 3; 0 0 0 0 0; 0 0 0 0 0])\n%!assert (diag ([1; 2; 3],-1),\n%!       [0 0 0 0; 1 0 0 0; 0 2 0 0; 0 0 3 0])\n%!assert (diag ([1; 2; 3],-2),\n%!        [0 0 0 0 0; 0 0 0 0 0; 1 0 0 0 0; 0 2 0 0 0; 0 0 3 0 0])\n\n%!assert (diag ([1, 0, 0; 0, 2, 0; 0, 0, 3]), [1; 2; 3])\n%!assert (diag ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0], 1),\n%!        [1; 2; 3])\n%!assert (diag ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0], -1),\n%!        [1; 2; 3])\n%!assert (diag (ones (1, 0), 2), zeros (2))\n%!assert (diag (1:3, 4, 2), [1, 0; 0, 2; 0, 0; 0, 0])\n\n%!assert (full (diag (single ([1; 2; 3]))),\n%!        single ([1, 0, 0; 0, 2, 0; 0, 0, 3]))\n%!assert (diag (single ([1; 2; 3]), 1),\n%!        single ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]))\n%!assert (diag (single ([1; 2; 3]), 2),\n%!        single ([0 0 1 0 0; 0 0 0 2 0; 0 0 0 0 3; 0 0 0 0 0; 0 0 0 0 0]))\n%!assert (diag (single ([1; 2; 3]),-1),\n%!        single ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]))\n%!assert (diag (single ([1; 2; 3]),-2),\n%!        single ([0 0 0 0 0; 0 0 0 0 0; 1 0 0 0 0; 0 2 0 0 0; 0 0 3 0 0]))\n\n%!assert (diag (single ([1, 0, 0; 0, 2, 0; 0, 0, 3])), single ([1; 2; 3]))\n%!assert (diag (single ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1),\n%!        single ([1; 2; 3]))\n%!assert (diag (single ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1),\n%!        single ([1; 2; 3]))\n\n%!assert (diag (int8 ([1; 2; 3])), int8 ([1, 0, 0; 0, 2, 0; 0, 0, 3]))\n%!assert (diag (int8 ([1; 2; 3]), 1),\n%!        int8 ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]))\n%!assert (diag (int8 ([1; 2; 3]), 2),\n%!        int8 ([0 0 1 0 0; 0 0 0 2 0; 0 0 0 0 3; 0 0 0 0 0; 0 0 0 0 0]))\n%!assert (diag (int8 ([1; 2; 3]),-1),\n%!        int8 ([0 0 0 0; 1 0 0 0; 0 2 0 0; 0 0 3 0]))\n%!assert (diag (int8 ([1; 2; 3]),-2),\n%!        int8 ([0 0 0 0 0; 0 0 0 0 0; 1 0 0 0 0; 0 2 0 0 0; 0 0 3 0 0]))\n\n%!assert (diag (int8 ([1, 0, 0; 0, 2, 0; 0, 0, 3])), int8 ([1; 2; 3]))\n%!assert (diag (int8 ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1),\n%!        int8 ([1; 2; 3]))\n%!assert (diag (int8 ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1),\n%!        int8 ([1; 2; 3]))\n\n%!assert (diag (1, 3, 3), diag ([1, 0, 0]))\n%!assert (diag (i, 3, 3), diag ([i, 0, 0]))\n%!assert (diag (single (1), 3, 3), diag ([single(1), 0, 0]))\n%!assert (diag (single (i), 3, 3), diag ([single(i), 0, 0]))\n%!assert (diag ([1, 2], 3, 3), diag ([1, 2, 0]))\n%!assert (diag ([1, 2]*i, 3, 3), diag ([1, 2, 0]*i))\n%!assert (diag (single ([1, 2]), 3, 3), diag (single ([1, 2, 0])))\n%!assert (diag (single ([1, 2]*i), 3, 3), diag (single ([1, 2, 0]*i)))\n\n%!assert <*37411> (diag (diag ([5, 2, 3])(:,1)), diag([5 0 0 ]))\n%!assert <*37411> (diag (diag ([5, 2, 3])(:,1), 2),  [0 0 5 0 0; zeros(4, 5)])\n%!assert <*37411> (diag (diag ([5, 2, 3])(:,1), -2),\n%!                 [[0 0 5 0 0]', zeros(5, 4)])\n\n## Test non-square size\n%!assert (diag ([1,2,3], 6, 3), [1 0 0; 0 2 0; 0 0 3; 0 0 0; 0 0 0; 0 0 0])\n%!assert (diag (1, 2, 3), [1,0,0; 0,0,0])\n%!assert (diag ({1}, 2, 3), {1,[],[]; [],[],[]})\n%!assert (diag ({1,2}, 3, 4), {1,[],[],[]; [],2,[],[]; [],[],[],[]})\n%!assert <*56711> (diag ({1,2,3}, 2, 1), {1; []})\n\n## Test out-of-range diagonals\n%!assert (diag (ones (3,3), 4), zeros (0, 1))\n%!assert (diag (cell (3,3), 4), cell (0, 1))\n%!assert (diag (sparse (ones (3,3)), 4), sparse (zeros (0, 1)))\n\n## Test input validation\n%!error <Invalid call to diag> diag ()\n%!error <Invalid call to diag> diag (1,2,3,4)\n%!error <V must be a vector> diag (ones (2), 3, 3)\n%!error diag (1:3, -4, 3)\n%!error diag (1:3, 4, -3)\n\n*/\n\nDEFUN (prod, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} prod (@var{x})\n@deftypefnx {} {@var{y} =} prod (@var{x}, @var{dim})\n@deftypefnx {} {@var{y} =} prod (@var{x}, @var{vecdim})\n@deftypefnx {} {@var{y} =} prod (@var{x}, \"all\")\n@deftypefnx {} {@var{y} =} prod (@dots{}, @var{outtype})\n@deftypefnx {} {@var{y} =} prod (@dots{}, @var{nanflag})\nCompute the product of the elements of @var{x}.\n\nIf @var{x} is a vector, then @code{prod (@var{x})} returns the product of the\nelements in @var{x}.\n\nIf @var{x} is a matrix, then @code{prod (@var{x})} returns a row vector with\neach element containing the product of the corresponding column in @var{x}.\n\nIf @var{x} is an array, then @code{prod(@var{x})} computes the product along\nthe first non-singleton dimension of @var{x}.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension in @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{prod} to operate on\nall elements of @var{x}, and is equivalent to @code{prod (@var{x}(:))}.\n\nThe optional input @var{outtype} specifies the data type that is returned as\nwell as the class of the variable used for calculations.\n@var{outtype} can take the following values:\n\n@table @asis\n@item @qcode{\"default\"}\nOperations on floating point inputs (double or single) are performed in their\nnative data type; while operations on integer, logical, and character data\ntypes are performed using doubles.  Output is of type double, unless the input\nis single in which case the output is of type single.\n\n@item @qcode{\"double\"}\nOperations are performed in double precision even for single precision inputs.\nOutput is of type double.\n\n@item @qcode{\"native\"}\nOperations are performed in their native data types and output is of the same\ntype as the input as reported by (@code{class (@var{x})}).  When the input is\nlogical, @code{prod (@var{x}, \"native\")} is equivalent to @code{all (@var{x})}.\n@end table\n\nThe optional variable @var{nanflag} specifies whether to include or exclude\nNaN values from the calculation using any of the previously specified input\nargument combinations.  The default value for @var{nanflag} is\n@qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\nNaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\nwill be @var{1}, if @var{x} consists of all NaN values in the\noperating dimension.\n@seealso{cumprod, sum}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  bool isnative = false;\n  bool isdouble = false;\n  bool do_perm = false;\n  bool allflag = false;\n  bool nanflag = false;\n\n  while (nargin > 1 && args(nargin - 1).is_string ())\n    {\n      std::string str = args(nargin - 1).string_value ();\n\n      if (str == \"native\")\n        isnative = true;\n      else if (str == \"double\")\n        isdouble = true;\n      else if (str == \"all\")\n        allflag = true;\n      else if (str == \"omitnan\" || str == \"omitmissing\")\n        {\n          if (args(0).is_double_type () || args(0).is_single_type ())\n            nanflag = true;\n        }\n      else if (str == \"includenan\" || str == \"includemissing\")\n        nanflag = false;\n      else if (str != \"default\")\n        error (\"prod: unrecognized optional argument '%s'\", str.c_str ());\n\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  if (allflag && nargin > 1)\n    error (\"prod: cannot set DIM or VECDIM with 'all' flag\");\n\n  octave_value arg = args(0);\n\n  // Handle DIM, VECDIM\n  int dim = -1;\n  Array<int> perm_vec;\n  if (nargin == 2)\n    {\n      octave_value dimarg = args(1);\n      get_dim_vecdim_all (dimarg, arg, dim, perm_vec, do_perm, allflag, \"prod\");\n    }\n\n  // Handle allflag\n  if (allflag)\n    arg = arg.reshape (dim_vector (arg.numel (), 1));\n\n  octave_value retval;\n\n  switch (arg.builtin_type ())\n    {\n    case btyp_double:\n      if (arg.issparse ())\n        retval = arg.sparse_matrix_value ().prod (dim, nanflag);\n      else\n        retval = arg.array_value ().prod (dim, nanflag);\n      break;\n\n    case btyp_complex:\n      if (arg.issparse ())\n        retval = arg.sparse_complex_matrix_value ().prod (dim, nanflag);\n      else\n        retval = arg.complex_array_value ().prod (dim, nanflag);\n      break;\n\n    case btyp_float:\n      if (isdouble)\n        retval = arg.float_array_value ().dprod (dim, nanflag);\n      else\n        retval = arg.float_array_value ().prod (dim, nanflag);\n      break;\n\n    case btyp_float_complex:\n      if (isdouble)\n        retval = arg.float_complex_array_value ().dprod (dim, nanflag);\n      else\n        retval = arg.float_complex_array_value ().prod (dim, nanflag);\n      break;\n\n#define MAKE_INT_BRANCH(X)                              \\\n      case btyp_ ## X:                                  \\\n        if (isnative)                                   \\\n          retval = arg.X ## _array_value ().prod (dim); \\\n        else                                            \\\n          retval = arg.array_value ().prod (dim);       \\\n        break;\n\n      MAKE_INT_BRANCH (int8);\n      MAKE_INT_BRANCH (int16);\n      MAKE_INT_BRANCH (int32);\n      MAKE_INT_BRANCH (int64);\n      MAKE_INT_BRANCH (uint8);\n      MAKE_INT_BRANCH (uint16);\n      MAKE_INT_BRANCH (uint32);\n      MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n    // GAGME: Accursed Matlab compatibility...\n    case btyp_char:\n      retval = arg.array_value (true).prod (dim);\n      break;\n\n    case btyp_bool:\n      if (arg.issparse ())\n        {\n          if (isnative)\n            retval = arg.sparse_bool_matrix_value ().all (dim);\n          else\n            retval = arg.sparse_matrix_value ().prod (dim);\n        }\n      else if (isnative)\n        retval = arg.bool_array_value ().all (dim);\n      else\n        retval = NDArray (arg.bool_array_value ().all (dim));\n      break;\n\n    default:\n      err_wrong_type_arg (\"prod\", arg);\n    }\n\n  if (do_perm)\n    retval = retval.permute (perm_vec, true);\n\n  return retval;\n}\n\n/*\n%!assert (prod ([1, 2, 3]), 6)\n%!assert (prod ([-1; -2; -3]), -6)\n%!assert (prod ([i, 2+i, -3+2i, 4]), -4 - 32i)\n%!assert (prod ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [-1+i, -8+8i, -27+27i])\n\n%!assert (prod (single ([1, 2, 3])), single (6))\n%!assert (prod (single ([-1; -2; -3])), single (-6))\n%!assert (prod (single ([i, 2+i, -3+2i, 4])), single (-4 - 32i))\n%!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])),\n%!        single ([-1+i, -8+8i, -27+27i]))\n\n## Test sparse\n%!assert (prod (sparse ([1, 2, 3])), sparse (6))\n%!assert (prod (sparse ([-1; -2; -3])), sparse (-6))\n## Commented out until bug #42290 is fixed\n#%!assert (prod (sparse ([i, 2+i, -3+2i, 4])), sparse (-4 - 32i))\n#%!assert (prod (sparse ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])),\n#%!         sparse ([-1+i, -8+8i, -27+27i]))\n\n%!assert (prod ([1, 2; 3, 4], 1), [3, 8])\n%!assert (prod ([1, 2; 3, 4], 2), [2; 12])\n%!assert (prod (single ([1, 2; 3, 4]), 1), single ([3, 8]))\n%!assert (prod (single ([1, 2; 3, 4]), 2), single ([2; 12]))\n\n## Test empty matrices\n%!assert (prod ([]), 1)\n%!assert (prod ([], 1), zeros (1, 0))\n%!assert (prod ([], 2), zeros (0, 1))\n%!assert (prod ([], 3), zeros (0, 0))\n%!assert (prod (zeros (1, 0)), 1)\n%!assert (prod (zeros (1, 0), 1), zeros (1, 0))\n%!assert (prod (zeros (1, 0), 2), 1)\n%!assert (prod (zeros (0, 1)), 1)\n%!assert (prod (zeros (0, 1), 1), 1)\n%!assert (prod (zeros (0, 1), 2), zeros (0, 1))\n%!assert (prod (zeros (2, 0)), zeros (1, 0))\n%!assert (prod (zeros (2, 0), 1), zeros (1, 0))\n%!assert (prod (zeros (2, 0), 2), [1; 1])\n%!assert (prod (zeros (0, 2)), [1, 1])\n%!assert (prod (zeros (0, 2), 1), [1, 1])\n%!assert (prod (zeros (0, 2), 2), zeros (0, 1))\n\n%!assert (prod (single ([])), single (1))\n%!assert (prod (single ([]), 1), single (zeros (1, 0)))\n%!assert (prod (single ([]), 2), single (zeros (0, 1)))\n%!assert (prod (single ([]), 3), single (zeros (0, 0)))\n%!assert (prod (zeros (1, 0, \"single\")), single (1))\n%!assert (prod (zeros (1, 0, \"single\"), 1), zeros (1, 0, \"single\"))\n%!assert (prod (zeros (1, 0, \"single\"), 2), single (1))\n%!assert (prod (zeros (0, 1, \"single\")), single (1))\n%!assert (prod (zeros (0, 1, \"single\"), 1), single (1))\n%!assert (prod (zeros (0, 1, \"single\"), 2), zeros (0, 1, \"single\"))\n%!assert (prod (zeros (2, 0, \"single\")), zeros (1, 0, \"single\"))\n%!assert (prod (zeros (2, 0, \"single\"), 1), zeros (1, 0, \"single\"))\n%!assert (prod (zeros (2, 0, \"single\"), 2), single ([1; 1]))\n%!assert (prod (zeros (0, 2, \"single\")), single ([1, 1]))\n%!assert (prod (zeros (0, 2, \"single\"), 1), single ([1, 1]))\n%!assert (prod (zeros (0, 2, \"single\"), 2), zeros (0, 1, \"single\"))\n\n## Test \"double\" type argument\n%!assert (prod (single ([1, 2, 3]), \"double\"), 6)\n%!assert (prod (single ([-1; -2; -3]), \"double\"), -6)\n%!assert (prod (single ([i, 2+i, -3+2i, 4]), \"double\"), -4 - 32i)\n%!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), \"double\"),\n%!        [-1+i, -8+8i, -27+27i])\n\n## Test \"native\" type argument\n%!assert (prod (uint8 ([1, 2, 3]), \"native\"), uint8 (6))\n%!assert (prod (uint8 ([-1; -2; -3]), \"native\"), uint8 (0))\n%!assert (prod (int8 ([1, 2, 3]), \"native\"), int8 (6))\n%!assert (prod (int8 ([-1; -2; -3]), \"native\"), int8 (-6))\n%!assert (prod ([true false; true true], \"native\"), [true false])\n%!assert (prod ([true false; true true], 2, \"native\"), [false; true])\n\n## Test \"default\"\n%!assert (prod (single (1)), prod (single (1), \"default\"))\n%!assert (prod ([true true], \"default\"), double (1))\n%!assert (prod (uint8 (1), \"default\"), double (1))\n\n## Test character arrays\n%!assert (prod ([\"aa\";\"aa\"])', prod ([\"aa\";\"aa\"], 2))\n%!assert (prod (\"aa\"), sum (\"a\") * sum (\"a\"))\n%!assert (prod (\"a\", 3), 97)\n%!assert (prod ([\"a\";\"a\"], 3), [97; 97])\n%!assert (prod ([\"a\";\"a\"], [1, 3]), sum (\"a\") * sum (\"a\"))\n%!assert (prod ([\"a\";\"a\"], [2, 3]), [97; 97])\n\n## Test dimension indexing with vecdim in N-dimensional arrays\n%!test\n%! x = repmat ([1:20;6:25], [5 2 6 3]);\n%! assert (size (prod (x, [3 2])), [10 1 1 3]);\n%! assert (size (prod (x, [1 2])), [1 1 6 3]);\n%! assert (size (prod (x, [1 2 4])), [1 1 6]);\n%! assert (size (prod (x, [1 4 3])), [1 40]);\n%! assert (size (prod (x, [1 2 3 4])), [1 1]);\n\n## Test exceeding dimensions\n%!assert (prod (ones (2,2), 3), ones (2,2))\n%!assert (prod (ones (2,2,2), 99), ones (2,2,2))\n%!assert (prod (magic (3), 3), magic (3))\n%!assert (prod (magic (3), [1 3]), prod (magic (3)))\n%!assert (prod (magic (3), [2 99]), prod (magic (3), 2))\n%!assert (prod (ones (2), 4), ones (2))\n%!assert (prod (ones (2), [4, 5]), ones (2))\n%!assert (prod (single (ones (2)), 4),single (ones (2)))\n%!assert (prod (single (ones (2)), [4, 5]),single (ones (2)))\n%!assert (prod (sparse ([1, 2; 3, 4]), 3), sparse ([1, 2; 3, 4]))\n%!assert (prod (sparse ([1, 2i; 3, 4]), 3), sparse ([1, 2i; 3, 4]))\n\n## Test nanflag\n%!test\n%! x = ones (3,4,5);\n%! x(1) = NaN;\n%! assert (prod (x)(:,:,1), [NaN, 1, 1, 1]);\n%! assert (prod (x, \"includenan\")(:,:,1), [NaN, 1, 1, 1]);\n%! assert (prod (x, \"omitnan\")(:,:,1), [1, 1, 1, 1]);\n%! assert (prod (x, \"omitmissing\")(:,:,1), [1, 1, 1, 1]);\n%! assert (prod (x, [2 3]), [NaN; 1; 1]);\n%! assert (prod (x, [2 3], \"omitnan\"), [1; 1; 1]);\n\n## Test cases for \"omitnan\"\n%!test\n%! A = [2, NaN; 3, NaN; 4, NaN];\n%! assert (prod (A, 2, \"omitnan\"), [2; 3; 4]);\n%!test\n%! A = [NaN, NaN, NaN];\n%! assert (prod (A, \"omitnan\"), 1);\n%!test\n%! A = [2, 3, NaN; 4, 5, NaN; 1, 2, NaN];\n%! assert (prod (A, 2, \"omitnan\"), [6; 20; 2]);\n%!test\n%! A = [2, NaN, 3; 3, NaN, 2; 2, NaN, 4];\n%! assert (prod (A, 1, \"omitnan\"), [12, 1, 24]);\n%!test\n%! A = [1+i, NaN; 2+2i, NaN];\n%! assert (prod (A, 2, \"omitnan\"), [1+i; 2+2i]);\n%!test\n%! A = single ([NaN, NaN, NaN]);\n%! assert (prod (A, \"omitnan\"), single (1));\n\n## Test sparse matrices\n%!assert (prod (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN])),\n%!        sparse ([NaN, NaN, 1, 8, NaN]))\n%!assert (prod (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), \"omitnan\"),\n%!        sparse ([1, 2, 1, 8, 2]))\n%!assert (prod (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2),\n%!        sparse ([NaN; NaN]))\n%!assert (prod (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([8; 4]))\n%!assert (prod (sparse ([NaN, NaN, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([8i; 4]))\n%!assert (prod (sparse ([NaN, 0i, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([0; 4]))\n%!assert (prod (sparse ([NaN, 1+i, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([-8+8i; 4]))\n%!assert (prod (sparse ([NaN, NaN, NaN])), sparse (NaN))\n%!assert (prod (sparse ([0, 0, 0, NaN, NaN, NaN])), sparse (NaN))\n%!assert (prod (sparse ([NaN, NaN, NaN]), \"omitnan\"), sparse (1))\n%!assert (prod (sparse ([0, 0, 0, NaN, NaN, NaN]), \"omitnan\"), sparse (0))\n\n## Test empty sparse matrices\n%!assert (prod (sparse (ones(1, 0))), sparse (1))\n%!assert (size (prod (sparse (ones(1, 0)), 1)), [1, 0])\n%!assert (size (prod (sparse (ones(1, 0)), 2)), [1, 1])\n%!assert (prod (sparse (ones(0, 1))), sparse (1))\n%!assert (size (prod (sparse (ones(0, 1)), 1)), [1, 1])\n%!assert (size (prod (sparse (ones(0, 1)), 1)), [1, 1])\n%!assert (size (prod (sparse (ones(0, 1)), 2)), [0, 1])\n%!assert (prod (sparse (ones(0, 0))), sparse (1))\n%!assert (size (prod (sparse (ones(0, 0)), 1)), [1, 0])\n%!assert (size (prod (sparse (ones(0, 0)), 2)), [0, 1])\n%!assert (size (prod (sparse (ones(0, 0)), 3)), [0, 0])\n\n## Test input validation\n%!error <Invalid call> prod ()\n%!error <Invalid call> prod (1,2,3)\n%!error <unrecognized optional argument 'foobar'> prod (1, \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! prod (ones (3,3), 1, \"all\");\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! prod (ones (3,3), [1, 2], \"all\");\n%!error <invalid dimension DIM = 0> prod (ones (3,3), 0)\n%!error <invalid dimension DIM = -1> prod (ones (3,3), -1)\n%!error <invalid dimension in VECDIM = -2> prod (ones (3,3), [1 -2])\n%!error <duplicate dimension in VECDIM = 2> prod (ones (3,3), [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> prod (ones (3,3), [1 1 2])\n*/\n\nstatic bool\nall_scalar_1x1 (const octave_value_list& args)\n{\n  int n_args = args.length ();\n  for (int i = 0; i < n_args; i++)\n    if (args(i).numel () != 1)\n      return false;\n\n  return true;\n}\n\ntemplate <typename TYPE, typename T>\nstatic void\nsingle_type_concat (Array<T>& result,\n                    const octave_value_list& args,\n                    int dim)\n{\n  int n_args = args.length ();\n  if (! (equal_types<T, char>::value\n         || equal_types<T, octave_value>::value)\n      && all_scalar_1x1 (args))\n    {\n      // Optimize all scalars case.\n      dim_vector dv (1, 1);\n      if (dim == -1 || dim == -2)\n        dim = -dim - 1;\n      else if (dim >= 2)\n        dv.resize (dim+1, 1);\n      dv(dim) = n_args;\n\n      result.clear (dv);\n\n      for (int j = 0; j < n_args; j++)\n        {\n          octave_quit ();\n\n          result(j) = octave_value_extract<T> (args(j));\n        }\n    }\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (Array<T>, array_list, n_args);\n\n      for (int j = 0; j < n_args; j++)\n        {\n          octave_quit ();\n\n          array_list[j] = octave_value_extract<TYPE> (args(j));\n        }\n\n      result = Array<T>::cat (dim, n_args, array_list);\n    }\n}\n\ntemplate <typename TYPE, typename T>\nstatic void\nsingle_type_concat (Sparse<T>& result,\n                    const octave_value_list& args,\n                    int dim)\n{\n  octave_idx_type n_args = args.length ();\n  OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_list, n_args);\n\n  for (octave_idx_type j = 0; j < n_args; j++)\n    {\n      octave_quit ();\n\n      sparse_list[j] = octave_value_extract<TYPE> (args(j));\n    }\n\n  result = Sparse<T>::cat (dim, n_args, sparse_list);\n}\n\n// Dispatcher.\ntemplate <typename TYPE>\nstatic TYPE\ndo_single_type_concat (const octave_value_list& args, int dim)\n{\n  TYPE result;\n\n  single_type_concat<TYPE, typename TYPE::element_type> (result, args, dim);\n\n  return result;\n}\n\ntemplate <typename MAP>\nstatic void\nsingle_type_concat_map (octave_map& result,\n                        const octave_value_list& args,\n                        int dim)\n{\n  int n_args = args.length ();\n  OCTAVE_LOCAL_BUFFER (MAP, map_list, n_args);\n\n  for (int j = 0; j < n_args; j++)\n    {\n      octave_quit ();\n\n      map_list[j] = octave_value_extract<MAP> (args(j));\n    }\n\n  result = octave_map::cat (dim, n_args, map_list);\n}\n\nstatic octave_map\ndo_single_type_concat_map (const octave_value_list& args,\n                           int dim)\n{\n  octave_map result;\n  if (all_scalar_1x1 (args)) // optimize all scalars case.\n    single_type_concat_map<octave_scalar_map> (result, args, dim);\n  else\n    single_type_concat_map<octave_map> (result, args, dim);\n\n  return result;\n}\n\nstatic octave_value\ndo_single_type_concat_cdef (const octave_value_list& args, int dim)\n{\n  // Concatenate a list of octave_classdef values of the same\n  // class along dimension dim\n\n  Array<cdef_object> arr;\n  int n_args = args.length ();\n\n  if (all_scalar_1x1 (args))\n    {\n      // Optimize all scalars case.\n      dim_vector dv (1, 1);\n      if (dim == -1 || dim == -2)\n        dim = -dim - 1;\n      else if (dim >= 2)\n        dv.resize (dim+1, 1);\n      dv(dim) = n_args;\n\n      arr.clear (dv);\n\n      for (int j = 0; j < n_args; j++)\n        {\n          octave_quit ();\n\n          arr(j) = args(j).classdef_object_value ()->get_object ();\n        }\n    }\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (Array<cdef_object>, array_list, n_args);\n\n      for (int j = 0; j < n_args; j++)\n        {\n          octave_quit ();\n\n          cdef_object obj = args(j).classdef_object_value ()->get_object ();\n          if (obj.is_array ())\n            array_list[j] = obj.array_value ();\n          else\n            array_list[j] = Array<cdef_object> (dim_vector (1,1), obj);\n        }\n\n      arr = Array<cdef_object>::cat (dim, n_args, array_list);\n    }\n\n  cdef_object obj_result = cdef_object (new cdef_object_array (arr));\n  obj_result.set_class (arr(0).get_class ());\n\n  return to_ov (obj_result);\n}\n\nstatic octave_value\nattempt_type_conversion (const octave_value& ov, std::string dtype)\n{\n  octave_value retval;\n\n  // First try to find function in the class of OV that can convert to\n  // the dispatch type dtype.  It will have the name of the dispatch\n  // type.\n\n  std::string cname = ov.class_name ();\n\n  interpreter& interp = __get_interpreter__ ();\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  cdef_manager& cdef_mgr = interp.get_cdef_manager ();\n\n  auto fcn = cdef_mgr.find_method_symbol (dtype, cname);\n  if (! fcn.is_defined ())\n    fcn = symtab.find_method (dtype, cname);\n\n  if (fcn.is_defined ())\n    {\n      octave_value_list result;\n\n      try\n        {\n          result = interp.feval (fcn, ovl (ov), 1);\n        }\n      catch (execution_exception& ee)\n        {\n          error (ee, \"conversion from %s to %s failed\", dtype.c_str (),\n                 cname.c_str ());\n        }\n\n      if (result.empty ())\n        error (\"conversion from %s to %s failed\", dtype.c_str (),\n               cname.c_str ());\n\n      retval = result(0);\n    }\n  else\n    {\n      // No conversion function available.  Try the constructor for the\n      // dispatch type.\n      // We can't go purely through the symbol table here, we have to\n      // check the classdef manager as well for classdef methods\n      auto ctor = cdef_mgr.find_method_symbol (dtype, dtype);\n\n      if (! ctor.is_defined ())\n        ctor = symtab.find_method (dtype, dtype);\n\n      octave_value_list result;\n\n      // The following code looks fairly ugly because we have to handle\n      // old-style classes and classdef constructors separately\n      if (ctor.is_defined () && ctor.is_function ())\n        {\n          octave_function *ctor_fcn = ctor.function_value ();\n\n            if (ctor_fcn->is_legacy_constructor ())\n              {\n                // Old-style class constructor\n                octave::unwind_protect frame;\n\n                octave::interpreter_try (frame);\n\n                try\n                  {\n                   result = interp.feval (ctor, ovl (ov), 1);\n                  }\n                catch (const octave::execution_exception&)\n                  {\n                    interp.recover_from_exception ();\n                  }\n              }\n            else\n              // Classdef constructor\n              {\n                auto cls = lookup_class (dtype, false, false);\n\n                try\n                  {\n                    result = cls.construct (ovl (ov));\n                  }\n                catch (execution_exception& ee)\n                  {\n                    error (ee, \"%s constructor failed for %s argument\",\n                           dtype.c_str (), cname.c_str ());\n                  }\n\n              }\n        }\n\n       retval = result(0);\n    }\n\n  return retval;\n}\n\noctave_value\ndo_class_concat (const octave_value_list& ovl,\n                 const std::string& cattype, int dim)\n{\n  octave_value retval;\n\n  // Get dominant type for list\n\n  std::string dtype = get_dispatch_type (ovl);\n\n  interpreter& interp = __get_interpreter__ ();\n\n  cdef_manager& cdef_mgr = __get_cdef_manager__ ();\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value ov_fcn = symtab.find_method (cattype, dtype);\n\n  if (ov_fcn.is_defined ())\n    {\n      // Have method for dominant type.  Call it and let it handle conversions.\n\n      octave_value_list tmp2;\n\n      try\n        {\n          tmp2 = interp.feval (ov_fcn, ovl, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          error (ee, \"cat: %s/%s method failed\", dtype.c_str (), cattype.c_str ());\n        }\n\n      if (tmp2.empty ())\n        error (\"cat: %s/%s method did not return a value\", dtype.c_str (),\n               cattype.c_str ());\n\n      retval = tmp2(0);\n    }\n  else\n    {\n      // No method for dominant type, so attempt type conversions for\n      // all elements that are not of the dominant type, then do the\n      // default operation for octave_class values.\n\n      octave_idx_type j = 0;\n      octave_idx_type len = ovl.length ();\n      octave_value_list tmp (len, octave_value ());\n      for (octave_idx_type k = 0; k < len; k++)\n        {\n          octave_value elt = ovl(k);\n\n          std::string t1_type = elt.class_name ();\n\n          if (t1_type == dtype)\n            tmp(j++) = elt;\n          else if (elt.isobject () || ! elt.isempty ())\n            {\n              auto ov = attempt_type_conversion (elt, dtype);\n              // Abort concatenation if type cannot be converted\n              if ( ! ov.is_defined ())\n                error (\"cat: cannot convert from type \\\"%s\\\" to type \\\"%s\\\"\",\n                       t1_type.c_str (), dtype.c_str ());\n              tmp(j++) = ov;\n            }\n        }\n\n      tmp.resize (j);\n\n      // See if dominant type is a classdef\n      cdef_class cdef = cdef_mgr.find_class (dtype, false);\n\n      if (cdef.ok ())\n        // Default classdef concat\n        retval = do_single_type_concat_cdef (tmp, dim);\n      else\n        {\n          // Default struct-based class concat\n          octave_map m = do_single_type_concat_map (tmp, dim);\n\n          std::string cname = tmp(0).class_name ();\n          std::list<std::string> parents = tmp(0).parent_class_name_list ();\n\n          retval = octave_value (new octave_class (m, cname, parents));\n        }\n    }\n\n  return retval;\n}\n\nstatic octave_value\ndo_cat (const octave_value_list& xargs, int dim, std::string fname)\n{\n  octave_value retval;\n\n  // We may need to convert elements of the list to cells, so make a copy.\n  // This should be efficient, it is done mostly by incrementing reference\n  // counts.\n  octave_value_list args = xargs;\n\n  int n_args = args.length ();\n\n  if (n_args == 0)\n    retval = Matrix ();\n  else if (n_args == 1)\n    retval = args(0);\n  else if (n_args > 1)\n    {\n      std::string result_type;\n\n      bool all_strings_p = true;\n      bool all_sq_strings_p = true;\n      bool all_dq_strings_p = true;\n      bool all_real_p = true;\n      bool all_cmplx_p = true;\n      bool any_sparse_p = false;\n      bool any_cell_p = false;\n      bool any_class_p = false;\n\n      bool first_elem_is_struct = false;\n\n      for (int i = 0; i < n_args; i++)\n        {\n          if (i == 0)\n            {\n              result_type = args(i).class_name ();\n\n              first_elem_is_struct = args(i).isstruct ();\n            }\n          else\n            result_type = get_concat_class (result_type, args(i).class_name ());\n\n          if (all_strings_p && ! args(i).is_string ())\n            all_strings_p = false;\n          if (all_sq_strings_p && ! args(i).is_sq_string ())\n            all_sq_strings_p = false;\n          if (all_dq_strings_p && ! args(i).is_dq_string ())\n            all_dq_strings_p = false;\n          if (all_real_p && ! args(i).isreal ())\n            all_real_p = false;\n          if (all_cmplx_p && ! (args(i).iscomplex ()\n                                || args(i).isreal ()))\n            all_cmplx_p = false;\n          if (! any_sparse_p && args(i).issparse ())\n            any_sparse_p = true;\n          if (! any_cell_p && args(i).iscell ())\n            any_cell_p = true;\n          if (! any_class_p && args(i).isobject ())\n            any_class_p = true;\n        }\n\n      if (any_cell_p && ! any_class_p && ! first_elem_is_struct)\n        {\n          int j = 0;\n          for (int i = 0; i < n_args; i++)\n            {\n              if (args(i).iscell ())\n                args(j++) = args(i);\n              else\n                {\n                  if (args(i).isempty ())\n                    continue;  // Delete empty non-cell arg\n                  else\n                    args(j++) = Cell (args(i));\n                }\n            }\n          n_args = j;\n          args.resize (n_args);\n        }\n\n      if (any_class_p)\n        retval = do_class_concat (args, fname, dim);\n      else if (result_type == \"double\")\n        {\n          if (any_sparse_p)\n            {\n              if (all_real_p)\n                retval = do_single_type_concat<SparseMatrix> (args, dim);\n              else\n                retval = do_single_type_concat<SparseComplexMatrix> (args, dim);\n            }\n          else\n            {\n              if (all_real_p)\n                retval = do_single_type_concat<NDArray> (args, dim);\n              else\n                retval = do_single_type_concat<ComplexNDArray> (args, dim);\n            }\n        }\n      else if (result_type == \"single\")\n        {\n          if (all_real_p)\n            retval = do_single_type_concat<FloatNDArray> (args, dim);\n          else\n            retval = do_single_type_concat<FloatComplexNDArray> (args, dim);\n        }\n      else if (result_type == \"char\")\n        {\n          char type = (all_dq_strings_p ? '\"' : '\\'');\n\n          if (! all_strings_p)\n            warn_implicit_conversion (\"Octave:num-to-str\",\n                                      \"numeric\", result_type);\n          else\n            maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);\n\n          charNDArray result = do_single_type_concat<charNDArray> (args, dim);\n\n          retval = octave_value (result, type);\n        }\n      else if (result_type == \"logical\")\n        {\n          if (any_sparse_p)\n            retval = do_single_type_concat<SparseBoolMatrix> (args, dim);\n          else\n            retval = do_single_type_concat<boolNDArray> (args, dim);\n        }\n      else if (result_type == \"int8\")\n        retval = do_single_type_concat<int8NDArray> (args, dim);\n      else if (result_type == \"int16\")\n        retval = do_single_type_concat<int16NDArray> (args, dim);\n      else if (result_type == \"int32\")\n        retval = do_single_type_concat<int32NDArray> (args, dim);\n      else if (result_type == \"int64\")\n        retval = do_single_type_concat<int64NDArray> (args, dim);\n      else if (result_type == \"uint8\")\n        retval = do_single_type_concat<uint8NDArray> (args, dim);\n      else if (result_type == \"uint16\")\n        retval = do_single_type_concat<uint16NDArray> (args, dim);\n      else if (result_type == \"uint32\")\n        retval = do_single_type_concat<uint32NDArray> (args, dim);\n      else if (result_type == \"uint64\")\n        retval = do_single_type_concat<uint64NDArray> (args, dim);\n      else if (result_type == \"cell\")\n        retval = do_single_type_concat<Cell> (args, dim);\n      else if (result_type == \"struct\")\n        retval = do_single_type_concat_map (args, dim);\n      else\n        {\n          dim_vector dv = args(0).dims ();\n\n          // Default concatenation.\n          bool (dim_vector::*concat_rule) (const dim_vector&, int)\n            = &dim_vector::concat;\n\n          if (dim == -1 || dim == -2)\n            {\n              concat_rule = &dim_vector::hvcat;\n              dim = -dim - 1;\n            }\n\n          for (int i = 1; i < args.length (); i++)\n            {\n              if (! (dv.*concat_rule) (args(i).dims (), dim))\n                error (\"cat: dimension mismatch\");\n            }\n\n          // The lines below might seem crazy, since we take a copy\n          // of the first argument, resize it to be empty and then resize\n          // it to be full.  This is done since it means that there is no\n          // recopying of data, as would happen if we used a single resize.\n          // It should be noted that resize operation is also significantly\n          // slower than the do_cat_op function, so it makes sense to have\n          // an empty matrix and copy all data.\n          //\n          // We might also start with a empty octave_value using\n          //\n          //   tmp = type_info::lookup_type (args(1).type_name());\n          //\n          // and then directly resize.  However, for some types there might\n          // be some additional setup needed, and so this should be avoided.\n\n          octave_value tmp = args(0);\n          tmp = tmp.resize (dim_vector (0, 0)).resize (dv);\n\n          int dv_len = dv.ndims ();\n          Array<octave_idx_type> ra_idx (dim_vector (dv_len, 1), 0);\n\n          for (int j = 0; j < n_args; j++)\n            {\n              // Can't fast return here to skip empty matrices as something\n              // like cat (1,[],single ([])) must return an empty matrix of\n              // the right type.\n              tmp = cat_op (tmp, args(j), ra_idx);\n\n              const dim_vector& dv_tmp = args(j).dims ();\n\n              if (dim >= dv_len)\n                {\n                  if (j > 1)\n                    error (\"%s: indexing error\", fname.c_str ());\n\n                  break;\n                }\n              else\n                ra_idx(dim) += (dim < dv_tmp.ndims () ? dv_tmp(dim) : 1);\n            }\n          retval = tmp;\n        }\n    }\n  else\n    print_usage ();\n\n  return retval;\n}\n\nDEFUN (horzcat, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{A} =} horzcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\nReturn the horizontal concatenation of N-D array objects, @var{array1},\n@var{array2}, @dots{}, @var{arrayN} along dimension 2.\n\nArrays may also be concatenated horizontally using the syntax for creating\nnew matrices.  For example:\n\n@example\n@var{A} = [ @var{array1}, @var{array2}, @dots{} ]\n@end example\n\nThis syntax is slightly more efficient because the Octave parser can\nconcatenate the arrays without the overhead of a function call.\n@seealso{cat, vertcat}\n@end deftypefn */)\n{\n  return do_cat (args, -2, \"horzcat\");\n}\n\n/*\n## Test concatenation with all zero matrices\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (horzcat (\"\", 65* ones (1,10)), \"AAAAAAAAAA\");\n%! assert (horzcat (65* ones (1,10), \"\"), \"AAAAAAAAAA\");\n\n%!assert (class (horzcat (int64 (1), int64 (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), int32 (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), int16 (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), int8 (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), uint64 (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), uint32 (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), uint16 (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), uint8 (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), single (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), double (1))), \"int64\")\n%!assert (class (horzcat (int64 (1), cell (1))), \"cell\")\n%!assert (class (horzcat (int64 (1), true)), \"int64\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (int64 (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (int32 (1), int64 (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), int32 (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), int16 (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), int8 (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), uint64 (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), uint32 (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), uint16 (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), uint8 (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), single (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), double (1))), \"int32\")\n%!assert (class (horzcat (int32 (1), cell (1))), \"cell\")\n%!assert (class (horzcat (int32 (1), true)), \"int32\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (int32 (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (int16 (1), int64 (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), int32 (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), int16 (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), int8 (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), uint64 (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), uint32 (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), uint16 (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), uint8 (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), single (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), double (1))), \"int16\")\n%!assert (class (horzcat (int16 (1), cell (1))), \"cell\")\n%!assert (class (horzcat (int16 (1), true)), \"int16\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (int16 (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (int8 (1), int64 (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), int32 (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), int16 (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), int8 (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), uint64 (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), uint32 (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), uint16 (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), uint8 (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), single (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), double (1))), \"int8\")\n%!assert (class (horzcat (int8 (1), cell (1))), \"cell\")\n%!assert (class (horzcat (int8 (1), true)), \"int8\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (int8 (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (uint64 (1), int64 (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), int32 (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), int16 (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), int8 (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), uint64 (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), uint32 (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), uint16 (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), uint8 (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), single (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), double (1))), \"uint64\")\n%!assert (class (horzcat (uint64 (1), cell (1))), \"cell\")\n%!assert (class (horzcat (uint64 (1), true)), \"uint64\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (uint64 (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (uint32 (1), int64 (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), int32 (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), int16 (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), int8 (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), uint64 (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), uint32 (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), uint16 (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), uint8 (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), single (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), double (1))), \"uint32\")\n%!assert (class (horzcat (uint32 (1), cell (1))), \"cell\")\n%!assert (class (horzcat (uint32 (1), true)), \"uint32\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (uint32 (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (uint16 (1), int64 (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), int32 (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), int16 (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), int8 (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), uint64 (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), uint32 (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), uint16 (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), uint8 (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), single (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), double (1))), \"uint16\")\n%!assert (class (horzcat (uint16 (1), cell (1))), \"cell\")\n%!assert (class (horzcat (uint16 (1), true)), \"uint16\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (uint16 (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (uint8 (1), int64 (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), int32 (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), int16 (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), int8 (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), uint64 (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), uint32 (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), uint16 (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), uint8 (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), single (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), double (1))), \"uint8\")\n%!assert (class (horzcat (uint8 (1), cell (1))), \"cell\")\n%!assert (class (horzcat (uint8 (1), true)), \"uint8\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (uint8 (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (single (1), int64 (1))), \"int64\")\n%!assert (class (horzcat (single (1), int32 (1))), \"int32\")\n%!assert (class (horzcat (single (1), int16 (1))), \"int16\")\n%!assert (class (horzcat (single (1), int8 (1))), \"int8\")\n%!assert (class (horzcat (single (1), uint64 (1))), \"uint64\")\n%!assert (class (horzcat (single (1), uint32 (1))), \"uint32\")\n%!assert (class (horzcat (single (1), uint16 (1))), \"uint16\")\n%!assert (class (horzcat (single (1), uint8 (1))), \"uint8\")\n%!assert (class (horzcat (single (1), single (1))), \"single\")\n%!assert (class (horzcat (single (1), double (1))), \"single\")\n%!assert (class (horzcat (single (1), cell (1))), \"cell\")\n%!assert (class (horzcat (single (1), true)), \"single\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (single (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (double (1), int64 (1))), \"int64\")\n%!assert (class (horzcat (double (1), int32 (1))), \"int32\")\n%!assert (class (horzcat (double (1), int16 (1))), \"int16\")\n%!assert (class (horzcat (double (1), int8 (1))), \"int8\")\n%!assert (class (horzcat (double (1), uint64 (1))), \"uint64\")\n%!assert (class (horzcat (double (1), uint32 (1))), \"uint32\")\n%!assert (class (horzcat (double (1), uint16 (1))), \"uint16\")\n%!assert (class (horzcat (double (1), uint8 (1))), \"uint8\")\n%!assert (class (horzcat (double (1), single (1))), \"single\")\n%!assert (class (horzcat (double (1), double (1))), \"double\")\n%!assert (class (horzcat (double (1), cell (1))), \"cell\")\n%!assert (class (horzcat (double (1), true)), \"double\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (double (1), \"a\")), \"char\");\n\n%!assert (class (horzcat (cell (1), int64 (1))), \"cell\")\n%!assert (class (horzcat (cell (1), int32 (1))), \"cell\")\n%!assert (class (horzcat (cell (1), int16 (1))), \"cell\")\n%!assert (class (horzcat (cell (1), int8 (1))), \"cell\")\n%!assert (class (horzcat (cell (1), uint64 (1))), \"cell\")\n%!assert (class (horzcat (cell (1), uint32 (1))), \"cell\")\n%!assert (class (horzcat (cell (1), uint16 (1))), \"cell\")\n%!assert (class (horzcat (cell (1), uint8 (1))), \"cell\")\n%!assert (class (horzcat (cell (1), single (1))), \"cell\")\n%!assert (class (horzcat (cell (1), double (1))), \"cell\")\n%!assert (class (horzcat (cell (1), cell (1))), \"cell\")\n%!assert (class (horzcat (cell (1), true)), \"cell\")\n%!assert (class (horzcat (cell (1), \"a\")), \"cell\")\n\n%!assert (class (horzcat (true, int64 (1))), \"int64\")\n%!assert (class (horzcat (true, int32 (1))), \"int32\")\n%!assert (class (horzcat (true, int16 (1))), \"int16\")\n%!assert (class (horzcat (true, int8 (1))), \"int8\")\n%!assert (class (horzcat (true, uint64 (1))), \"uint64\")\n%!assert (class (horzcat (true, uint32 (1))), \"uint32\")\n%!assert (class (horzcat (true, uint16 (1))), \"uint16\")\n%!assert (class (horzcat (true, uint8 (1))), \"uint8\")\n%!assert (class (horzcat (true, single (1))), \"single\")\n%!assert (class (horzcat (true, double (1))), \"double\")\n%!assert (class (horzcat (true, cell (1))), \"cell\")\n%!assert (class (horzcat (true, true)), \"logical\")\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (true, \"a\")), \"char\");\n\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! assert (class (horzcat (\"a\", int64 (1))), \"char\");\n%! assert (class (horzcat (\"a\", int32 (1))), \"char\");\n%! assert (class (horzcat (\"a\", int16 (1))), \"char\");\n%! assert (class (horzcat (\"a\", int8 (1))), \"char\");\n%! assert (class (horzcat (\"a\", int64 (1))), \"char\");\n%! assert (class (horzcat (\"a\", int32 (1))), \"char\");\n%! assert (class (horzcat (\"a\", int16 (1))), \"char\");\n%! assert (class (horzcat (\"a\", int8 (1))), \"char\");\n%! assert (class (horzcat (\"a\", single (1))), \"char\");\n%! assert (class (horzcat (\"a\", double (1))), \"char\");\n%! assert (class (horzcat (\"a\", cell (1))), \"cell\");\n%! assert (class (horzcat (\"a\", true)), \"char\");\n%! assert (class (horzcat (\"a\", \"a\")), \"char\");\n\n%!assert (class (horzcat (cell (1), struct (\"foo\", \"bar\"))), \"cell\")\n\n%!error horzcat (struct (\"foo\", \"bar\"), cell (1))\n\n%!test <*39041> assert (class (horzcat (cell (0), struct ())), \"cell\")\n%!test <51086> assert (class (horzcat (struct (), cell (0))), \"struct\")\n*/\n\nDEFUN (vertcat, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{A} =} vertcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\nReturn the vertical concatenation of N-D array objects, @var{array1},\n@var{array2}, @dots{}, @var{arrayN} along dimension 1.\n\nArrays may also be concatenated vertically using the syntax for creating\nnew matrices.  For example:\n\n@example\n@var{A} = [ @var{array1}; @var{array2}; @dots{} ]\n@end example\n\nThis syntax is slightly more efficient because the Octave parser can\nconcatenate the arrays without the overhead of a function call.\n@seealso{cat, horzcat}\n@end deftypefn */)\n{\n  return do_cat (args, -1, \"vertcat\");\n}\n\n/*\n%!test\n%! c = {\"foo\"; \"bar\"; \"bazoloa\"};\n%! assert (vertcat (c, \"a\", \"bc\", \"def\"),\n%!         {\"foo\"; \"bar\"; \"bazoloa\"; \"a\"; \"bc\"; \"def\"});\n*/\n\nDEFUN (cat, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{A} =} cat (@var{dim}, @var{array1}, @var{array2}, @dots{}, @var{arrayN})\nReturn the concatenation of N-D array objects, @var{array1}, @var{array2},\n@dots{}, @var{arrayN} along dimension @var{dim}.\n\n@example\n@group\nA = ones (2, 2);\nB = zeros (2, 2);\ncat (2, A, B)\n  @xresult{} 1 1 0 0\n     1 1 0 0\n@end group\n@end example\n\nAlternatively, we can concatenate @var{A} and @var{B} along the second\ndimension in the following way:\n\n@example\n@group\n[A, B]\n@end group\n@end example\n\n@var{dim} can be larger than the dimensions of the N-D array objects and the\nresult will thus have @var{dim} dimensions as the following example shows:\n\n@example\n@group\ncat (4, ones (2, 2), zeros (2, 2))\n  @xresult{} ans(:,:,1,1) =\n\n       1 1\n       1 1\n\n     ans(:,:,1,2) =\n\n       0 0\n       0 0\n@end group\n@end example\n@seealso{horzcat, vertcat}\n@end deftypefn */)\n{\n  if (args.length () == 0)\n    print_usage ();\n\n  int dim = args(0).strict_int_value (\"cat: DIM must be an integer\") - 1;\n\n  if (dim < 0)\n    error (\"cat: DIM must be a valid dimension\");\n\n  return ovl (do_cat (args.slice (1, args.length () - 1), dim, \"cat\"));\n}\n\n/*\n%!function ret = __testcat (t1, t2, tr, cmplx)\n%!  assert (cat (1, cast ([], t1), cast ([], t2)), cast ([], tr));\n%!\n%!  assert (cat (1, cast (1, t1), cast (2, t2)), cast ([1; 2], tr));\n%!  assert (cat (1, cast (1, t1), cast ([2; 3], t2)), cast ([1; 2; 3], tr));\n%!  assert (cat (1, cast ([1; 2], t1), cast (3, t2)), cast ([1; 2; 3], tr));\n%!  assert (cat (1, cast ([1; 2], t1), cast ([3; 4], t2)),\n%!          cast ([1; 2; 3; 4], tr));\n%!  assert (cat (2, cast (1, t1), cast (2, t2)), cast ([1, 2], tr));\n%!  assert (cat (2, cast (1, t1), cast ([2, 3], t2)), cast ([1, 2, 3], tr));\n%!  assert (cat (2, cast ([1, 2], t1), cast (3, t2)), cast ([1, 2, 3], tr));\n%!  assert (cat (2, cast ([1, 2], t1), cast ([3, 4], t2)),\n%!          cast ([1, 2, 3, 4], tr));\n%!\n%!  assert ([cast(1, t1); cast(2, t2)], cast ([1; 2], tr));\n%!  assert ([cast(1, t1); cast([2; 3], t2)], cast ([1; 2; 3], tr));\n%!  assert ([cast([1; 2], t1); cast(3, t2)], cast ([1; 2; 3], tr));\n%!  assert ([cast([1; 2], t1); cast([3; 4], t2)], cast ([1; 2; 3; 4], tr));\n%!  assert ([cast(1, t1), cast(2, t2)], cast ([1, 2], tr));\n%!  assert ([cast(1, t1), cast([2, 3], t2)], cast ([1, 2, 3], tr));\n%!  assert ([cast([1, 2], t1), cast(3, t2)], cast ([1, 2, 3], tr));\n%!  assert ([cast([1, 2], t1), cast([3, 4], t2)], cast ([1, 2, 3, 4], tr));\n%!\n%!  if (nargin == 3 || cmplx)\n%!    assert (cat (1, cast (1i, t1), cast (2, t2)), cast ([1i; 2], tr));\n%!    assert (cat (1, cast (1i, t1), cast ([2; 3], t2)), cast ([1i; 2; 3], tr));\n%!    assert (cat (1, cast ([1i; 2], t1), cast (3, t2)), cast ([1i; 2; 3], tr));\n%!    assert (cat (1, cast ([1i; 2], t1), cast ([3; 4], t2)),\n%!            cast ([1i; 2; 3; 4], tr));\n%!    assert (cat (2, cast (1i, t1), cast (2, t2)), cast ([1i, 2], tr));\n%!    assert (cat (2, cast (1i, t1), cast ([2, 3], t2)), cast ([1i, 2, 3], tr));\n%!    assert (cat (2, cast ([1i, 2], t1), cast (3, t2)), cast ([1i, 2, 3], tr));\n%!    assert (cat (2, cast ([1i, 2], t1), cast ([3, 4], t2)),\n%!            cast ([1i, 2, 3, 4], tr));\n%!    assert ([cast(1i, t1); cast(2, t2)], cast ([1i; 2], tr));\n%!    assert ([cast(1i, t1); cast([2; 3], t2)], cast ([1i; 2; 3], tr));\n%!    assert ([cast([1i; 2], t1); cast(3, t2)], cast ([1i; 2; 3], tr));\n%!    assert ([cast([1i; 2], t1); cast([3; 4], t2)], cast ([1i; 2; 3; 4], tr));\n%!    assert ([cast(1i, t1), cast(2, t2)], cast ([1i, 2], tr));\n%!    assert ([cast(1i, t1), cast([2, 3], t2)], cast ([1i, 2, 3], tr));\n%!    assert ([cast([1i, 2], t1), cast(3, t2)], cast ([1i, 2, 3], tr));\n%!    assert ([cast([1i, 2], t1), cast([3, 4], t2)], cast ([1i, 2, 3, 4], tr));\n%!\n%!    assert (cat (1, cast (1, t1), cast (2i, t2)), cast ([1; 2i], tr));\n%!    assert (cat (1, cast (1, t1), cast ([2i; 3], t2)), cast ([1; 2i; 3], tr));\n%!    assert (cat (1, cast ([1; 2], t1), cast (3i, t2)), cast ([1; 2; 3i], tr));\n%!    assert (cat (1, cast ([1; 2], t1), cast ([3i; 4], t2)),\n%!            cast ([1; 2; 3i; 4], tr));\n%!    assert (cat (2, cast (1, t1), cast (2i, t2)), cast ([1, 2i], tr));\n%!    assert (cat (2, cast (1, t1), cast ([2i, 3], t2)), cast ([1, 2i, 3], tr));\n%!    assert (cat (2, cast ([1, 2], t1), cast (3i, t2)), cast ([1, 2, 3i], tr));\n%!    assert (cat (2, cast ([1, 2], t1), cast ([3i, 4], t2)),\n%!            cast ([1, 2, 3i, 4], tr));\n%!    assert ([cast(1, t1); cast(2i, t2)], cast ([1; 2i], tr));\n%!    assert ([cast(1, t1); cast([2i; 3], t2)], cast ([1; 2i; 3], tr));\n%!    assert ([cast([1; 2], t1); cast(3i, t2)], cast ([1; 2; 3i], tr));\n%!    assert ([cast([1; 2], t1); cast([3i; 4], t2)], cast ([1; 2; 3i; 4], tr));\n%!    assert ([cast(1, t1), cast(2i, t2)], cast ([1, 2i], tr));\n%!    assert ([cast(1, t1), cast([2i, 3], t2)], cast ([1, 2i, 3], tr));\n%!    assert ([cast([1, 2], t1), cast(3i, t2)], cast ([1, 2, 3i], tr));\n%!    assert ([cast([1, 2], t1), cast([3i, 4], t2)], cast ([1, 2, 3i, 4], tr));\n%!\n%!    assert (cat (1, cast (1i, t1), cast (2i, t2)), cast ([1i; 2i], tr));\n%!    assert (cat (1, cast (1i, t1), cast ([2i; 3], t2)),\n%!            cast ([1i; 2i; 3], tr));\n%!    assert (cat (1, cast ([1i; 2], t1), cast (3i, t2)),\n%!            cast ([1i; 2; 3i], tr));\n%!    assert (cat (1, cast ([1i; 2], t1), cast ([3i; 4], t2)),\n%!            cast ([1i; 2; 3i; 4], tr));\n%!    assert (cat (2, cast (1i, t1), cast (2i, t2)), cast ([1i, 2i], tr));\n%!    assert (cat (2, cast (1i, t1), cast ([2i, 3], t2)),\n%!            cast ([1i, 2i, 3], tr));\n%!    assert (cat (2, cast ([1i, 2], t1), cast (3i, t2)),\n%!            cast ([1i, 2, 3i], tr));\n%!    assert (cat (2, cast ([1i, 2], t1), cast ([3i, 4], t2)),\n%!            cast ([1i, 2, 3i, 4], tr));\n%!\n%!    assert ([cast(1i, t1); cast(2i, t2)], cast ([1i; 2i], tr));\n%!    assert ([cast(1i, t1); cast([2i; 3], t2)], cast ([1i; 2i; 3], tr));\n%!    assert ([cast([1i; 2], t1); cast(3i, t2)], cast ([1i; 2; 3i], tr));\n%!    assert ([cast([1i; 2], t1); cast([3i; 4], t2)],\n%!            cast ([1i; 2; 3i; 4], tr));\n%!    assert ([cast(1i, t1), cast(2i, t2)], cast ([1i, 2i], tr));\n%!    assert ([cast(1i, t1), cast([2i, 3], t2)], cast ([1i, 2i, 3], tr));\n%!    assert ([cast([1i, 2], t1), cast(3i, t2)], cast ([1i, 2, 3i], tr));\n%!    assert ([cast([1i, 2], t1), cast([3i, 4], t2)],\n%!            cast ([1i, 2, 3i, 4], tr));\n%!  endif\n%!  ret = true;\n%!endfunction\n\n%!assert (__testcat (\"double\", \"double\", \"double\"))\n%!assert (__testcat (\"single\", \"double\", \"single\"))\n%!assert (__testcat (\"double\", \"single\", \"single\"))\n%!assert (__testcat (\"single\", \"single\", \"single\"))\n\n%!assert (__testcat (\"double\", \"int8\", \"int8\", false))\n%!assert (__testcat (\"int8\", \"double\", \"int8\", false))\n%!assert (__testcat (\"single\", \"int8\", \"int8\", false))\n%!assert (__testcat (\"int8\", \"single\", \"int8\", false))\n%!assert (__testcat (\"int8\", \"int8\", \"int8\", false))\n%!assert (__testcat (\"double\", \"int16\", \"int16\", false))\n%!assert (__testcat (\"int16\", \"double\", \"int16\", false))\n%!assert (__testcat (\"single\", \"int16\", \"int16\", false))\n%!assert (__testcat (\"int16\", \"single\", \"int16\", false))\n%!assert (__testcat (\"int16\", \"int16\", \"int16\", false))\n%!assert (__testcat (\"double\", \"int32\", \"int32\", false))\n%!assert (__testcat (\"int32\", \"double\", \"int32\", false))\n%!assert (__testcat (\"single\", \"int32\", \"int32\", false))\n%!assert (__testcat (\"int32\", \"single\", \"int32\", false))\n%!assert (__testcat (\"int32\", \"int32\", \"int32\", false))\n%!assert (__testcat (\"double\", \"int64\", \"int64\", false))\n%!assert (__testcat (\"int64\", \"double\", \"int64\", false))\n%!assert (__testcat (\"single\", \"int64\", \"int64\", false))\n%!assert (__testcat (\"int64\", \"single\", \"int64\", false))\n%!assert (__testcat (\"int64\", \"int64\", \"int64\", false))\n\n%!assert (__testcat (\"double\", \"uint8\", \"uint8\", false))\n%!assert (__testcat (\"uint8\", \"double\", \"uint8\", false))\n%!assert (__testcat (\"single\", \"uint8\", \"uint8\", false))\n%!assert (__testcat (\"uint8\", \"single\", \"uint8\", false))\n%!assert (__testcat (\"uint8\", \"uint8\", \"uint8\", false))\n%!assert (__testcat (\"double\", \"uint16\", \"uint16\", false))\n%!assert (__testcat (\"uint16\", \"double\", \"uint16\", false))\n%!assert (__testcat (\"single\", \"uint16\", \"uint16\", false))\n%!assert (__testcat (\"uint16\", \"single\", \"uint16\", false))\n%!assert (__testcat (\"uint16\", \"uint16\", \"uint16\", false))\n%!assert (__testcat (\"double\", \"uint32\", \"uint32\", false))\n%!assert (__testcat (\"uint32\", \"double\", \"uint32\", false))\n%!assert (__testcat (\"single\", \"uint32\", \"uint32\", false))\n%!assert (__testcat (\"uint32\", \"single\", \"uint32\", false))\n%!assert (__testcat (\"uint32\", \"uint32\", \"uint32\", false))\n%!assert (__testcat (\"double\", \"uint64\", \"uint64\", false))\n%!assert (__testcat (\"uint64\", \"double\", \"uint64\", false))\n%!assert (__testcat (\"single\", \"uint64\", \"uint64\", false))\n%!assert (__testcat (\"uint64\", \"single\", \"uint64\", false))\n%!assert (__testcat (\"uint64\", \"uint64\", \"uint64\", false))\n\n%!assert (cat (3, [], [1,2;3,4]), [1,2;3,4])\n%!assert (cat (3, [1,2;3,4], []), [1,2;3,4])\n%!assert (cat (3, [], [1,2;3,4], []), [1,2;3,4])\n%!assert (cat (3, [], [], []), zeros (0, 0, 3))\n\n%!assert (cat (3, [], [], 1, 2), cat (3, 1, 2))\n%!assert (cat (3, [], [], [1,2;3,4]), [1,2;3,4])\n%!assert (cat (4, [], [], [1,2;3,4]), [1,2;3,4])\n\n%!assert ([zeros(3,2,2); ones(1,2,2)], repmat ([0;0;0;1],[1,2,2]))\n%!assert ([zeros(3,2,2); ones(1,2,2)], vertcat (zeros (3,2,2), ones (1,2,2)))\n\n%!test <*49759>\n%! A = [];\n%! B = {1; 2};\n%! assert (cat (1, A, B), {1; 2});\n%! assert (cat (2, A, B), {1; 2});\n\n%!error <dimension mismatch> cat (3, cat (3, [], []), [1,2;3,4])\n%!error <dimension mismatch> cat (3, zeros (0, 0, 2), [1,2;3,4])\n*/\n\nstatic octave_value\ndo_permute (const octave_value_list& args, bool inv)\n{\n  if (args.length () != 2 || args(1).length () < args(1).ndims ())\n    print_usage ();\n\n  Array<int> vec = args(1).int_vector_value ();\n\n  // FIXME: maybe we should create an idx_vector object here\n  //        and pass that to permute?\n  int n = vec.numel ();\n  for (int i = 0; i < n; i++)\n    vec(i)--;\n\n  return octave_value (args(0).permute (vec, inv));\n}\n\nDEFUN (permute, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{B} =} permute (@var{A}, @var{perm})\nReturn the generalized transpose for an N-D array object @var{A}.\n\nThe permutation vector @var{perm} must contain the elements\n@w{@code{1:ndims (A)}}@ (in any order, but each element must appear only\nonce).  The @var{N}th dimension of @var{A} gets remapped to dimension\n@code{@var{PERM}(@var{N})}.  For example:\n\n@example\n@group\n@var{x} = zeros ([2, 3, 5, 7]);\nsize (@var{x})\n   @xresult{}  2   3   5   7\n\nsize (permute (@var{x}, [2, 1, 3, 4]))\n   @xresult{}  3   2   5   7\n\nsize (permute (@var{x}, [1, 3, 4, 2]))\n   @xresult{}  2   5   7   3\n\n## The identity permutation\nsize (permute (@var{x}, [1, 2, 3, 4]))\n   @xresult{}  2   3   5   7\n@end group\n@end example\n@seealso{ipermute}\n@end deftypefn */)\n{\n  return do_permute (args, false);\n}\n\nDEFUN (ipermute, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{A} =} ipermute (@var{B}, @var{iperm})\nThe inverse of the @code{permute} function.\n\nThe expression\n\n@example\nipermute (permute (A, perm), perm)\n@end example\n\n@noindent\nreturns the original array @var{A}.\n@seealso{permute}\n@end deftypefn */)\n{\n  return do_permute (args, true);\n}\n\nDEFUN (length, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} length (@var{A})\nReturn the length of the object @var{A}.\n\nThe length is 0 for empty objects, 1 for scalars, and the number of elements\nfor vectors.  For matrix or N-dimensional objects, the length is the number\nof elements along the largest dimension\n(equivalent to @w{@code{max (size (@var{A}))}}).\n@seealso{numel, size}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).length ());\n}\n\nDEFUN (ndims, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} ndims (@var{A})\nReturn the number of dimensions of @var{A}.\n\nFor any array, the result will always be greater than or equal to 2.\nTrailing singleton dimensions are not counted, i.e., trailing dimensions\n@var{d} greater than 2 for which @code{size (@var{A}, @var{d}) = 1}.\n\n@example\n@group\nndims (ones (4, 1, 2, 1))\n    @xresult{} 3\n@end group\n@end example\n@seealso{size}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function *must* use size() to determine the desired values to be\n  // compatible with Matlab and to allow user-defined class overloading.\n  Matrix sz = octave_value (args(0)).size ();\n\n  octave_idx_type ndims = sz.numel ();\n\n  // Don't count trailing ones.  Trailing zeros are *not* singleton dimension.\n  while ((ndims > 2) && (sz(ndims - 1) == 1))\n    ndims--;\n\n  return ovl (ndims);\n}\n\n/*\n%!assert (ndims (1:5), 2)\n%!assert (ndims (ones (4, 1, 2, 1)), 3)\n%!assert (ndims (ones (4, 1, 2, 0)), 4)\n*/\n\nDEFUN (numel, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{n} =} numel (@var{A})\n@deftypefnx {} {@var{n} =} numel (@var{A}, @var{idx1}, @var{idx2}, @dots{})\nReturn the number of elements in the object @var{A}.\n\nOptionally, if indices @var{idx1}, @var{idx2}, @dots{} are supplied,\nreturn the number of elements that would result from the indexing\n\n@example\n@var{A}(@var{idx1}, @var{idx2}, @dots{})\n@end example\n\nNote that the indices do not have to be scalar numbers.  For example,\n\n@example\n@group\n@var{a} = 1;\n@var{b} = ones (2, 3);\nnumel (@var{a}, @var{b})\n@end group\n@end example\n\n@noindent\nwill return 6, as this is the number of ways to index with @var{b}.\nOr the index could be the string @qcode{\":\"} which represents the colon\noperator.  For example,\n\n@example\n@group\n@var{A} = ones (5, 3);\nnumel (@var{A}, 2, \":\")\n@end group\n@end example\n\n@noindent\nwill return 3 as the second row has three column entries.\n\nThis method is also called when an object appears as lvalue with cs-list\nindexing, i.e., @code{object@{@dots{}@}} or @code{object(@dots{}).field}.\n@seealso{size, length, ndims}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 1)\n    retval = args(0).numel ();\n  else if (nargin > 1)\n    {\n      // Don't use numel (const octave_value_list&) here as that corresponds to\n      // an overloaded call, not to builtin!\n      retval = dims_to_numel (args(0).dims (), args.slice (1, nargin-1));\n    }\n\n  return retval;\n}\n\nDEFUN (size, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{sz} =} size (@var{A})\n@deftypefnx {} {@var{dim_sz} =} size (@var{A}, @var{dim})\n@deftypefnx {} {@var{dim_sz} =} size (@var{A}, @var{d1}, @var{d2}, @dots{})\n@deftypefnx {} {[@var{rows}, @var{cols}, @dots{}, @var{dim_N_sz}] =} size (@dots{})\nReturn a row vector with the size (number of elements) of each dimension for\nthe object @var{A}.\n\nWhen given a second argument, @var{dim}, return the size of the corresponding\ndimension.  If @var{dim} is a vector, return each of the corresponding\ndimensions.  Multiple dimensions may also be specified as separate arguments.\n\nWith a single output argument, @code{size} returns a row vector.  When called\nwith multiple output arguments, @code{size} returns the size of dimension N\nin the Nth argument.  The number of rows, dimension 1, is returned in the\nfirst argument, the number of columns, dimension 2, is returned in the\nsecond argument, etc.  If there are more dimensions in @var{A} than there are\noutput arguments, @code{size} returns the total number of elements in the\nremaining dimensions in the final output argument.  If the requested dimension\n@var{dim} is greater than the number of dimensions in @var{A}, @code{size}\nreturns 1 (not 0).\n\nExample 1: single row vector output\n\n@example\n@group\nsize ([1, 2; 3, 4; 5, 6])\n   @xresult{} [ 3, 2 ]\n@end group\n@end example\n\nExample 2: number of elements in 2nd dimension (columns)\n\n@example\n@group\nsize ([1, 2; 3, 4; 5, 6], 2)\n    @xresult{} 2\n@end group\n@end example\n\nExample 3: number of output arguments == number of dimensions\n\n@example\n@group\n[nr, nc] = size ([1, 2; 3, 4; 5, 6])\n    @xresult{} nr = 3\n    @xresult{} nc = 2\n@end group\n@end example\n\nExample 4: number of output arguments < number of dimensions\n\n@example\n@group\n[nr, remainder] = size (ones (2, 3, 4, 5))\n    @xresult{} nr = 2\n    @xresult{} remainder = 60\n@end group\n@end example\n\nExample 5: number of elements in dimension > number of actual dimensions\n\n@example\n@group\nsz4 = size (ones (2, 3), 4)\n    @xresult{} sz4 = 1\n@end group\n@end example\n\n@seealso{numel, ndims, length, rows, columns, size_equal, common_size}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  // For compatibility with Matlab, size returns dimensions as doubles.\n\n  Matrix m;\n\n  dim_vector dimensions = args(0).dims ();\n  int ndims = dimensions.ndims ();\n\n  if (nargin == 1)\n    {\n      if (nargout > 1)\n        {\n          dimensions = dimensions.redim (nargout);\n          ndims = dimensions.ndims ();\n        }\n\n      m.resize (1, ndims);\n\n      for (octave_idx_type i = 0; i < ndims; i++)\n        m(i) = dimensions(i);\n    }\n  else\n    {\n      Array<octave_idx_type> query_dims;\n\n      if (nargin > 2)\n        {\n          query_dims.resize (dim_vector (1, nargin-1));\n\n          for (octave_idx_type i = 0; i < nargin-1; i++)\n            query_dims(i) = args(i+1).idx_type_value (true);\n        }\n      else\n        query_dims = args(1).octave_idx_type_vector_value (true);\n\n      if (nargout > 1 && nargout != query_dims.numel ())\n        error (\"size: nargout > 1 but does not match number of requested dimensions\");\n\n      octave_idx_type nidx = query_dims.numel ();\n\n      m.resize (1, nidx);\n\n      for (octave_idx_type i = 0; i < nidx; i++)\n        {\n          octave_idx_type nd = query_dims.xelem (i);\n\n          if (nd < 1)\n            error (\"size: requested dimension DIM (= %\"\n                   OCTAVE_IDX_TYPE_FORMAT \") out of range\", nd);\n\n          m(i) = nd <= ndims ? dimensions (nd-1) : 1;\n        }\n    }\n\n  if (nargout > 1)\n    {\n      octave_value_list retval (nargout);\n\n      for (octave_idx_type i = 0; i < nargout; i++)\n        retval(i) = m(i);\n\n      return retval;\n    }\n\n  return ovl (m);\n}\n\n/*\n## Plain call\n\n%!assert (size ([1, 2; 3, 4; 5, 6]), [3, 2])\n\n%!test\n%! [nr, nc] = size ([1, 2; 3, 4; 5, 6]);\n%! assert (nr, 3);\n%! assert (nc, 2);\n\n%!test\n%! [nr, remainder] = size (ones (2, 3, 4, 5));\n%! assert (nr, 2);\n%! assert (remainder, 60);\n\n## Call for single existing dimension\n\n%!assert (size ([1, 2; 3, 4; 5, 6], 1), 3)\n%!assert (size ([1, 2; 3, 4; 5, 6], 2), 2)\n\n## Call for single non-existing dimension\n\n%!assert (size ([1, 2; 3, 4; 5, 6], 3), 1)\n%!assert (size ([1, 2; 3, 4; 5, 6], 4), 1)\n\n## Call for more than existing dimensions\n\n%!test\n%! [nr, nc, e1, e2] = size ([1, 2; 3, 4; 5, 6]);\n%! assert (nr, 3);\n%! assert (nc, 2);\n%! assert (e1, 1);\n%! assert (e2, 1);\n\n## Call for two arbitrary dimensions\n\n%!test\n%! dim = [3, 2, 1, 1, 1];\n%! for i = 1:5\n%!   for j = 1:5\n%!     assert (size ([1, 2; 3, 4; 5, 6], i, j), [dim(i), dim(j)]);\n%!     assert (size ([1, 2; 3, 4; 5, 6], [i, j]), [dim(i), dim(j)]);\n%!     [a, b] = size ([1, 2; 3, 4; 5, 6], i, j);\n%!     assert (a, dim(i));\n%!     assert (b, dim(j));\n%!     [a, b] = size ([1, 2; 3, 4; 5, 6], [i, j]);\n%!     assert (a, dim(i));\n%!     assert (b, dim(j));\n%!   endfor\n%! endfor\n\n## Call for three arbitrary dimensions\n\n%!test\n%! dim = [3, 2, 1, 1, 1];\n%! for i = 1:5\n%!   for j = 1:5\n%!     for k = 1:5\n%!       assert (size ([1, 2; 3, 4; 5, 6], i, j, k), [dim(i), dim(j), dim(k)]);\n%!       assert (size ([1, 2; 3, 4; 5, 6], [i, j, k]),\n%!               [dim(i), dim(j), dim(k)]);\n%!       [a, b, c] = size ([1, 2; 3, 4; 5, 6], i, j, k);\n%!       assert (a, dim(i));\n%!       assert (b, dim(j));\n%!       assert (c, dim(k));\n%!       [a, b, c] = size ([1, 2; 3, 4; 5, 6], [i, j, k]);\n%!       assert (a, dim(i));\n%!       assert (b, dim(j));\n%!       assert (c, dim(k));\n%!     endfor\n%!   endfor\n%! endfor\n\n%!error <does not match number of requested dimensions>\n%! [a, b, c] = size ([1, 2; 3, 4; 5, 6], 1:4)\n*/\n\nDEFUN (size_equal, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{TF} =} size_equal (@var{A}, @var{B})\n@deftypefnx {} {@var{TF} =} size_equal (@var{A}, @var{B}, @dots{})\nReturn true if the dimensions of all arguments agree.\n\nTrailing singleton dimensions are ignored.  When called with a single argument,\nor no argument, @code{size_equal} returns true.\n@seealso{size, numel, ndims, common_size}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin >= 1)\n    {\n      const dim_vector& a_dims = args(0).dims ();\n\n      for (int i = 1; i < nargin; ++i)\n        {\n          const dim_vector& b_dims = args(i).dims ();\n\n          if (a_dims != b_dims)\n            return ovl (false);\n        }\n    }\n\n  return ovl (true);\n}\n\nDEFUN (nnz, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} nnz (@var{A})\nReturn the number of nonzero elements in @var{A}.\n@seealso{nzmax, nonzeros, find}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).nnz ());\n}\n\n/*\n%!assert (nnz (1:5), 5)\n%!assert (nnz (-5:-1), 5)\n%!assert (nnz (0:5), 5)\n%!assert (nnz (-5:0), 5)\n%!assert (nnz (-5:5), 10)\n%!assert (nnz (-2:1:2), 4)\n%!assert (nnz (-2+eps (2):1:2), 5)\n%!assert (nnz (-2-eps (2):1:2), 5)\n%!assert (nnz (-2:1+eps (1):2), 5)\n%!assert (nnz (-2:1-eps (1):2), 5)\n%!assert (nnz ([1:5] * 0), 0)\n%!assert (nnz ([-5:-1] * 0), 0)\n%!assert (nnz ([-1:1] * 0), 0)\n*/\n\nDEFUN (nzmax, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} nzmax (@var{SM})\nReturn the amount of storage allocated to the sparse matrix @var{SM}.\n\nProgramming Note: Octave tends to crop unused memory at the first opportunity\nfor sparse objects.  Thus, in general the value of @code{nzmax} will be the\nsame as @code{nnz}, except for some cases of user-created sparse objects.\n\nAlso, note that Octave always reserves storage for at least one value.  Thus,\nfor empty matrices @code{nnz} will report 0, but @code{nzmax} will report 1.\n@seealso{nnz, spalloc, sparse}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).nzmax ());\n}\n\nDEFUN (rows, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{nr} =} rows (@var{A})\n@deftypefnx {} {@var{nr} =} height (@var{A})\nReturn the number of rows of @var{A}.\n\nThis is equivalent to @code{size (@var{A}, 1)}.\n\nProgramming Note: @code{height} is an alias for @code{rows} and can be\nused interchangeably.\n\n@seealso{columns, size, length, numel, isscalar, isvector, ismatrix}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function *must* use size() to determine the desired values to\n  // allow user-defined class overloading.\n\n  return ovl ((octave_value (args(0)).size ())(0));\n}\n\nDEFALIAS (height, rows);\n\n/*\n%!assert (rows (ones (2,5)), 2)\n%!assert (rows (ones (5,2)), 5)\n%!assert (rows (ones (5,4,3,2)), 5)\n%!assert (rows (ones (3,4,5,2)), 3)\n\n%!assert (rows (cell (2,5)), 2)\n%!assert (rows (cell (5,2)), 5)\n%!assert (rows (cell (5,4,3,2)), 5)\n%!assert (rows (cell (3,4,5,2)), 3)\n\n%!test\n%! x(2,5,3).a = 1;\n%! assert (rows (x), 2);\n%! y(5,4,3).b = 2;\n%! assert (rows (y), 5);\n\n%!assert (rows (\"Hello World\"), 1)\n\n%!assert (rows ([]), 0)\n%!assert (rows (zeros (2,0)), 2)\n\n## Test input validation\n%!error rows ()\n%!error rows (1,2)\n*/\n\nDEFUN (columns, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{nc} =} columns (@var{A})\n@deftypefnx {} {@var{nc} =} width (@var{A})\nReturn the number of columns of @var{A}.\n\nThis is equivalent to @code{size (@var{A}, 2)}.\n\nProgramming Note: @code{width} is an alias for @code{columns} and can be\nused interchangeably.\n\n@seealso{rows, size, length, numel, isscalar, isvector, ismatrix}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function *must* use size() to determine the desired values to\n  // allow user-defined class overloading.\n\n  return ovl ((octave_value (args(0)).size ())(1));\n}\n\nDEFALIAS (width, columns);\n\nDEFUN (sum, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} sum (@var{x})\n@deftypefnx {} {@var{y} =} sum (@var{x}, @var{dim})\n@deftypefnx {} {@var{y} =} sum (@var{x}, @var{vecdim})\n@deftypefnx {} {@var{y} =} sum (@var{x}, \"all\")\n@deftypefnx {} {@var{y} =} sum (@dots{}, @var{outtype})\n@deftypefnx {} {@var{y} =} sum (@dots{}, @var{nanflag})\nCompute the sum of the elements of @var{x}.\n\nIf @var{x} is a vector, then @code{sum (@var{x})} returns the sum of the\nelements in @var{x}.\n\nIf @var{x} is a matrix, then @code{sum (@var{x})} returns a row vector with\neach element containing the sum of the corresponding column in @var{x}.\n\nIf @var{x} is an array, then @code{sum(@var{x})} computes the sum along the\nfirst non-singleton dimension of @var{x}.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension in @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{sum} to operate\non all elements of @var{x}, and is equivalent to @code{cumsum (@var{x}(:))}.\n\nThe optional input @var{outtype} specifies the data type that is returned as\nwell as the class of the variable used for calculations.\n@var{outtype} can take the following values:\n\n@table @asis\n@item @qcode{\"default\"}\nOperations on floating point inputs (double or single) are performed in their\nnative data type, while operations on integer, logical, and character data\ntypes are performed using doubles.  Output is of type double, unless the input\nis single in which case the output is of type single.\n\n@item @qcode{\"double\"}\nOperations are performed in double precision even for single precision inputs.\nOutput is of type double.\n\n@item @qcode{\"extra\"}\nFor double precision inputs, @code{sum} will use a more accurate algorithm than\nstraightforward summation.  For single precision inputs, @qcode{\"extra\"} is the\nsame as @qcode{\"double\"}.  For all other data types, @qcode{\"extra\"} has no\neffect.\n\n@item @qcode{\"native\"}\nOperations are performed in their native data types and output is of the same\ntype as the input as reported by (@code{class (@var{x})}).  When the input is\nlogical, @code{sum (@var{x}, \"native\")} is equivalent to @code{any (@var{x})}.\n@end table\n\nThe optional variable @var{nanflag} specifies whether to include or exclude\nNaN values from the calculation using any of the previously specified input\nargument combinations.  The default value for @var{nanflag} is\n@qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\nNaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\nwill be @var{0}, if @var{x} consists of all NaN values in the\noperating dimension.\n@seealso{cumsum, sumsq, prod}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  bool isnative = false;\n  bool isdouble = false;\n  bool isextra = false;\n  bool do_perm = false;\n  bool allflag = false;\n  bool nanflag = false;\n\n  while (nargin > 1 && args(nargin - 1).is_string ())\n    {\n      std::string str = args(nargin - 1).string_value ();\n\n      if (str == \"native\")\n        isnative = true;\n      else if (str == \"double\")\n        isdouble = true;\n      else if (str == \"extra\")\n        isextra = true;\n      else if (str == \"all\")\n        allflag = true;\n      else if (str == \"omitnan\" || str == \"omitmissing\")\n        {\n          if (args(0).is_double_type () || args(0).is_single_type ())\n            nanflag = true;\n        }\n      else if (str == \"includenan\" || str == \"includemissing\")\n        nanflag = false;\n      else if (str != \"default\")\n        error (\"sum: unrecognized optional argument '%s'\", str.c_str ());\n\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  if (allflag && nargin > 1)\n    error (\"sum: cannot set DIM or VECDIM with 'all' flag\");\n\n  octave_value arg = args(0);\n\n  // Handle DIM, VECDIM\n  int dim = -1;\n  Array<int> perm_vec;\n  if (nargin == 2)\n    {\n      octave_value dimarg = args(1);\n      get_dim_vecdim_all (dimarg, arg, dim, perm_vec, do_perm, allflag, \"sum\");\n    }\n\n  // Handle allflag\n  if (allflag)\n    arg = arg.reshape (dim_vector (arg.numel (), 1));\n\n  octave_value retval;\n\n  switch (arg.builtin_type ())\n    {\n    case btyp_double:\n      if (arg.issparse ())\n        {\n          if (isextra)\n            retval = arg.sparse_matrix_value ().xsum (dim, nanflag);\n          else\n            retval = arg.sparse_matrix_value ().sum (dim, nanflag);\n        }\n      else\n        {\n          if (isextra)\n            retval = arg.array_value ().xsum (dim, nanflag);\n          else\n            retval = arg.array_value ().sum (dim, nanflag);\n        }\n      break;\n\n    case btyp_complex:\n      if (arg.issparse ())\n        {\n          if (isextra)\n            retval = arg.sparse_complex_matrix_value ().xsum (dim, nanflag);\n          else\n            retval = arg.sparse_complex_matrix_value ().sum (dim, nanflag);\n        }\n      else\n        {\n          if (isextra)\n            retval = arg.complex_array_value ().xsum (dim, nanflag);\n          else\n            retval = arg.complex_array_value ().sum (dim, nanflag);\n        }\n      break;\n\n    case btyp_float:\n      if (isdouble || isextra)\n        retval = arg.float_array_value ().dsum (dim, nanflag);\n      else\n        retval = arg.float_array_value ().sum (dim, nanflag);\n      break;\n\n    case btyp_float_complex:\n      if (isdouble || isextra)\n        retval = arg.float_complex_array_value ().dsum (dim, nanflag);\n      else\n        retval = arg.float_complex_array_value ().sum (dim, nanflag);\n      break;\n\n#define MAKE_INT_BRANCH(X)                              \\\n      case btyp_ ## X:                                  \\\n        if (isnative)                                   \\\n          retval = arg.X ## _array_value ().sum (dim);  \\\n        else                                            \\\n          retval = arg.X ## _array_value ().dsum (dim); \\\n        break;\n\n      MAKE_INT_BRANCH (int8);\n      MAKE_INT_BRANCH (int16);\n      MAKE_INT_BRANCH (int32);\n      MAKE_INT_BRANCH (int64);\n      MAKE_INT_BRANCH (uint8);\n      MAKE_INT_BRANCH (uint16);\n      MAKE_INT_BRANCH (uint32);\n      MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n    // GAGME: Accursed Matlab compatibility...\n    case btyp_char:\n      if (isextra)\n        retval = arg.array_value (true).xsum (dim);\n      else\n        retval = arg.array_value (true).sum (dim);\n      break;\n\n    case btyp_bool:\n      if (arg.issparse ())\n        {\n          if (isnative)\n            retval = arg.sparse_bool_matrix_value ().any (dim);\n          else\n            retval = arg.sparse_bool_matrix_value ().sum (dim);\n        }\n      else if (isnative)\n        retval = arg.bool_array_value ().any (dim);\n      else\n        {\n          boolNDArray m = arg.bool_array_value ();\n          retval = do_mx_red_op<double, bool> (m, dim, mx_inline_count);\n         }\n      break;\n\n    default:\n      err_wrong_type_arg (\"sum\", arg);\n    }\n\n  if (do_perm)\n    retval = retval.permute (perm_vec, true);\n\n  return retval;\n}\n\n/*\n%!assert (sum ([1, 2, 3]), 6)\n%!assert (sum ([-1; -2; -3]), -6)\n%!assert (sum ([i, 2+i, -3+2i, 4]), 3+4i)\n%!assert (sum ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [2+2i, 4+4i, 6+6i])\n\n%!assert (sum (single ([1, 2, 3])), single (6))\n%!assert (sum (single ([-1; -2; -3])), single (-6))\n%!assert (sum (single ([i, 2+i, -3+2i, 4])), single (3+4i))\n%!assert (sum (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])),\n%!        single ([2+2i, 4+4i, 6+6i]))\n\n%!assert (sum ([1, 2; 3, 4], 1), [4, 6])\n%!assert (sum ([1, 2; 3, 4], 2), [3; 7])\n%!assert (sum (single ([1, 2; 3, 4]), 1), single ([4, 6]))\n%!assert (sum (single ([1, 2; 3, 4]), 2), single ([3; 7]))\n\n## Test empty matrices\n%!assert (sum ([]), 0)\n%!assert (sum ([], 1), zeros (1, 0))\n%!assert (sum ([], 2), zeros (0, 1))\n%!assert (sum ([], 3), zeros (0, 0))\n%!assert (sum (zeros (1, 0)), 0)\n%!assert (sum (zeros (1, 0), 1), zeros (1, 0))\n%!assert (sum (zeros (1, 0), 2), 0)\n%!assert (sum (zeros (0, 1)), 0)\n%!assert (sum (zeros (0, 1), 1), 0)\n%!assert (sum (zeros (0, 1), 2), zeros (0, 1))\n%!assert (sum (zeros (2, 0)), zeros (1, 0))\n%!assert (sum (zeros (2, 0), 1), zeros (1, 0))\n%!assert (sum (zeros (2, 0), 2),  [0; 0])\n%!assert (sum (zeros (0, 2)), [0, 0])\n%!assert (sum (zeros (0, 2), 1), [0, 0])\n%!assert (sum (zeros (0, 2), 2), zeros (0, 1))\n%!assert (sum (zeros (2, 2, 0, 3)), zeros (1, 2, 0, 3))\n%!assert (sum (zeros (2, 2, 0, 3), 2), zeros (2, 1, 0, 3))\n%!assert (sum (zeros (2, 2, 0, 3), 3), zeros (2, 2, 1, 3))\n%!assert (sum (zeros (2, 2, 0, 3), 4), zeros (2, 2, 0))\n%!assert (sum (zeros (2, 2, 0, 3), 7), zeros (2, 2, 0, 3))\n\n%!assert (sum (single ([])), single (0))\n%!assert (sum (single ([]), 1), single (zeros (1, 0)))\n%!assert (sum (single ([]), 2), single (zeros (0, 1)))\n%!assert (sum (single ([]), 3), single (zeros (0, 0)))\n%!assert (sum (zeros (1, 0, \"single\")), single (0))\n%!assert (sum (zeros (1, 0, \"single\"), 1), zeros (1, 0, \"single\"))\n%!assert (sum (zeros (1, 0, \"single\"), 2), single (0))\n%!assert (sum (zeros (0, 1, \"single\")), single (0))\n%!assert (sum (zeros (0, 1, \"single\"), 1), single (0))\n%!assert (sum (zeros (0, 1, \"single\"), 2), zeros (0, 1, \"single\"))\n%!assert (sum (zeros (2, 0, \"single\")), zeros (1, 0, \"single\"))\n%!assert (sum (zeros (2, 0, \"single\"), 1), zeros (1, 0, \"single\"))\n%!assert (sum (zeros (2, 0, \"single\"), 2), single ([0; 0]))\n%!assert (sum (zeros (0, 2, \"single\")), single ([0, 0]))\n%!assert (sum (zeros (0, 2, \"single\"), 1), single ([0, 0]))\n%!assert (sum (zeros (0, 2, \"single\"), 2), zeros (0, 1, \"single\"))\n%!assert (sum (zeros (2, 2, 0, 3, \"single\")), zeros (1, 2, 0, 3, \"single\"))\n%!assert (sum (zeros (2, 2, 0, 3, \"single\"), 2), zeros (2, 1, 0, 3, \"single\"))\n%!assert (sum (zeros (2, 2, 0, 3, \"single\"), 3), zeros (2, 2, 1, 3, \"single\"))\n%!assert (sum (zeros (2, 2, 0, 3, \"single\"), 4), zeros (2, 2, 0, \"single\"))\n%!assert (sum (zeros (2, 2, 0, 3, \"single\"), 7), zeros (2, 2, 0, 3, \"single\"))\n\n## Test \"default\"\n%!assert (sum (single (1)), sum (single (1), \"default\"))\n%!assert (sum ([true true], \"default\"), double (2))\n%!assert (sum (uint8 (1), \"default\"), double (1))\n\n## Test \"double\" and \"extra\"\n%!assert (sum (single ([1 2 3]), \"double\"), double (6))\n%!assert (sum (single ([1 2 3]), \"extra\"), double (6))\n%!assert (sum ([true,true], \"double\"), double (2))\n\n## Test \"native\"\n%!assert (sum ([true,true]), 2)\n%!assert (sum ([true,true], \"native\"), true)\n%!assert (sum (int8 ([127,10,-20])), 117)\n%!assert (sum (int8 ([127,10,-20]), \"native\"), int8 (107))\n\n## Test character arrays\n%!assert (sum (\"Octave\") + \"8\", sumsq (primes (17)))\n%!assert (sum (repmat (\"Octave\", [2,1,3]), [1, 3]), [474 594 696 582 708 606])\n%!assert (sum (repmat (\"Octave\", [2,1,3]), [1, 2, 3]), 3660)\n%!assert (sum (repmat (\"Octave\", [2,1,3]), 'all'), 3660)\n\n## Test dimension indexing with vecdim in N-dimensional arrays\n%!test\n%! x = repmat ([1:20;6:25], [5 2 6 3]);\n%! assert (size (sum (x, [3 2])), [10 1 1 3]);\n%! assert (size (sum (x, [1 2])), [1 1 6 3]);\n%! assert (size (sum (x, [1 2 4])), [1 1 6]);\n%! assert (size (sum (x, [1 4 3])), [1 40]);\n%! assert (size (sum (x, [1 2 3 4])), [1 1]);\n\n## Test exceeding dimensions\n%!assert (sum (ones (2,2), 3), ones (2,2))\n%!assert (sum (ones (2,2,2), 99), ones (2,2,2))\n%!assert (sum (magic (3), 3), magic (3))\n%!assert (sum (magic (3), [1 3]), [15, 15, 15])\n%!assert (sum (magic (3), [1 99]), [15, 15, 15])\n%!assert (sum (ones (2), 4), ones (2))\n%!assert (sum (ones (2), [4, 5]), ones (2))\n%!assert (sum (single (ones (2)), 4),single (ones (2)))\n%!assert (sum (single (ones (2)), [4, 5]),single (ones (2)))\n%!assert (sum (sparse ([1, 2; 3, 4]), 3), sparse ([1, 2; 3, 4]))\n%!assert (sum (sparse ([1, 2; 3, 4]), 3, 'extra'), sparse ([1, 2; 3, 4]))\n%!assert (sum (sparse ([1, 2i; 3, 4]), 3), sparse ([1, 2i; 3, 4]))\n%!assert (sum (sparse ([1, 2i; 3, 4]), 3, 'extra'), sparse ([1, 2i; 3, 4]))\n\n## Test nanflag\n%!test\n%! x = ones (3,4,5);\n%! x(1) = NaN;\n%! assert (sum (x)(:,:,1), [NaN, 3, 3, 3]);\n%! assert (sum (x, \"includenan\")(:,:,1), [NaN, 3, 3, 3]);\n%! assert (sum (x, \"omitnan\")(:,:,1), [2, 3, 3, 3]);\n%! assert (sum (x, \"omitmissing\")(:,:,1), [2, 3, 3, 3]);\n%! assert (sum (x, [2 3]), [NaN; 20; 20]);\n%! assert (sum (x, [2 3], \"omitnan\"), [19; 20; 20]);\n\n## Test sparse matrices\n%!assert (sum (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN])),\n%!        sparse ([NaN, NaN, 2, 6, NaN]))\n%!assert (sum (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), \"omitnan\"),\n%!        sparse ([1, 2, 2, 6, 2]))\n%!assert (sum (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2),\n%!        sparse ([NaN; NaN]))\n%!assert (sum (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([7; 6]))\n%!assert (sum (sparse ([NaN, NaN, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([6+i; 6]))\n%!assert (sum (sparse ([NaN, 0i, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([6+i; 6]))\n%!assert (sum (sparse ([NaN, 1+i, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([7+2i; 6]))\n%!assert (sum (sparse ([NaN, NaN, NaN]), \"omitnan\"), sparse (0))\n%!assert (sum (sparse ([0, 0, 0, NaN, NaN, NaN]), \"omitnan\"), sparse (0))\n\n## Test empty sparse matrices\n%!assert (sum (sparse (ones(1, 0))), sparse (0))\n%!assert (size (sum (sparse (ones(1, 0)), 1)), [1, 0])\n%!assert (size (sum (sparse (ones(1, 0)), 2)), [1, 1])\n%!assert (sum (sparse (ones(0, 1))), sparse (0))\n%!assert (size (sum (sparse (ones(0, 1)), 1)), [1, 1])\n%!assert (size (sum (sparse (ones(0, 1)), 1)), [1, 1])\n%!assert (size (sum (sparse (ones(0, 1)), 2)), [0, 1])\n%!assert (sum (sparse (ones(0, 0))), sparse (0))\n%!assert (size (sum (sparse (ones(0, 0)), 1)), [1, 0])\n%!assert (size (sum (sparse (ones(0, 0)), 2)), [0, 1])\n%!assert (size (sum (sparse (ones(0, 0)), 3)), [0, 0])\n\n## Test empty sparse matrices with 'extra' option\n%!assert (sum (sparse (ones(1, 0)), 'extra'), sparse (0))\n%!assert (size (sum (sparse (ones(1, 0)), 1, 'extra')), [1, 0])\n%!assert (size (sum (sparse (ones(1, 0)), 2, 'extra')), [1, 1])\n%!assert (sum (sparse (ones(0, 1)), 'extra'), sparse (0))\n%!assert (size (sum (sparse (ones(0, 1)), 1, 'extra')), [1, 1])\n%!assert (size (sum (sparse (ones(0, 1)), 1, 'extra')), [1, 1])\n%!assert (size (sum (sparse (ones(0, 1)), 2, 'extra')), [0, 1])\n%!assert (sum (sparse (ones(0, 0)), 'extra'), sparse (0))\n%!assert (size (sum (sparse (ones(0, 0)), 1, 'extra')), [1, 0])\n%!assert (size (sum (sparse (ones(0, 0)), 2, 'extra')), [0, 1])\n%!assert (size (sum (sparse (ones(0, 0)), 3, 'extra')), [0, 0])\n\n## Test 'extra' option\n%!assert (sum ([1, Inf], \"extra\"), Inf)\n%!assert (sum ([1, -Inf], \"extra\"), -Inf)\n%!assert (sum ([Inf, -Inf], \"extra\"), NaN)\n%!assert (sum ([realmax, 1e300], \"extra\"), Inf)\n%!assert (sum ([realmax/2, realmax/2, 1e300], \"extra\"), Inf)\n%!assert (sum ([realmax/2, (2 * (realmax/3))], \"extra\"), Inf)\n%!assert (sum (sparse ([1, Inf]), \"extra\"), sparse (Inf))\n%!assert (sum (sparse ([1, -Inf]), \"extra\"), sparse (-Inf))\n%!assert (sum (sparse ([Inf, -Inf]), \"extra\"), sparse (NaN))\n%!test\n%! x = [flintmax(\"double\"), 1, -1];\n%! assert (sum (x, \"extra\") - flintmax (\"double\"), 0);\n%! assert (sum (x) - flintmax (\"double\"), -1);\n%!test\n%! x = sparse ([flintmax(\"double\"), 1, -1]);\n%! assert (sum (x, \"extra\") - sparse (flintmax (\"double\")), sparse (0));\n%! assert (sum (x) - sparse (flintmax (\"double\")), sparse (-1));\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, -2; Inf, -4];\n%! s = sum (F, 1, \"extra\");\n%! assert (s(:,:,1), [2, 7]);\n%! assert (s(:,:,2), [Inf, -6]);\n%! s = sum (F, 2, \"extra\");\n%! assert (s(:,:,1), [8; 1]);\n%! assert (s(:,:,2), [2; Inf]);\n%! s = sum (F, 3, \"extra\");\n%! assert (s, [7, 3; Inf, -2]);\n%!test\n%! F(:,:,1) = [NaN, 5; -1, 2];\n%! F(:,:,2) = [4, -2; Inf, -4];\n%! s = sum (F, 1, \"extra\");\n%! assert (s(:,:,1), [NaN, 7]);\n%! assert (s(:,:,2), [Inf, -6]);\n%! s = sum (F, 2, \"extra\");\n%! assert (s(:,:,1), [NaN; 1]);\n%! assert (s(:,:,2), [2; Inf]);\n%! s = sum (F, 3, \"extra\");\n%! assert (s, [NaN, 3; Inf, -2]);\n%!test\n%! F(:,:,1) = [NaN, 5; -1, 2];\n%! F(:,:,2) = [4, -2; -Inf, -4];\n%! s = sum (F, 1, \"extra\");\n%! assert (s(:,:,1), [NaN, 7]);\n%! assert (s(:,:,2), [-Inf, -6]);\n%! s = sum (F, 2, \"extra\");\n%! assert (s(:,:,1), [NaN; 1]);\n%! assert (s(:,:,2), [2; -Inf]);\n%! s = sum (F, 3, \"extra\");\n%! assert (s, [NaN, 3; -Inf, -2]);\n%!test\n%! F(:,:,1) = [NaN, 5; -1, 2];\n%! F(:,:,2) = [Inf, -2; -Inf, -4];\n%! s = sum (F, 1, \"extra\");\n%! assert (s(:,:,1), [NaN, 7]);\n%! assert (s(:,:,2), [NaN, -6]);\n%! s = sum (F, 2, \"extra\");\n%! assert (s(:,:,1), [NaN; 1]);\n%! assert (s(:,:,2), [Inf; -Inf]);\n%! s = sum (F, 3, \"extra\");\n%! assert (s, [NaN, 3; -Inf, -2]);\n%!test\n%! F(:,:,1) = [NaN, 5; -1, 2];\n%! F(:,:,2) = [4, -2; Inf, -4];\n%! assert (sum (F, 1, \"omitnan\", \"extra\"), sum (F, 1, \"omitnan\"));\n%! assert (sum (F, 2, \"omitnan\", \"extra\"), sum (F, 2, \"omitnan\"));\n%! assert (sum (F, 3, \"omitnan\", \"extra\"), sum (F, 3, \"omitnan\"));\n%! assert (sum (F, [1, 2], \"omitnan\", \"extra\"), sum (F, [1, 2], \"omitnan\"));\n%! assert (sum (F, [1, 3], \"omitnan\", \"extra\"), sum (F, [1, 3], \"omitnan\"));\n%! assert (sum (F, [2, 3], \"omitnan\", \"extra\"), sum (F, [2, 3], \"omitnan\"));\n%! assert (sum (F, \"all\", \"omitnan\", \"extra\"), sum (F, [1, 2, 3], \"omitnan\"));\n\n## Test 'extra' option with sparse matrices\n%!assert (sum (sparse ([2; 3; 4; 5; 6]), \"extra\"), sparse (20))\n%!assert (sum (sparse ([2; 3; 0; 5; 6]), \"extra\"), sparse (16))\n%!assert (sum (sparse ([2; 3; 4; 5; 6]'), \"extra\"), sparse (20))\n%!assert (sum (sparse ([2; 3; 0; 5; 6]'), \"extra\"), sparse (16))\n%!assert (sum (speye (3), \"extra\"), sparse ([1, 1, 1]))\n%!assert (sum (speye (3), 1, \"extra\"), sparse ([1, 1, 1]))\n%!assert (sum (speye (3), 2, \"extra\"), sparse ([1; 1; 1]))\n%!assert (sum (speye (3), 3, \"extra\"), speye (3))\n%!assert (sum (sparse ([2; 3; 4; 5; 6] * i), \"extra\"), sparse (20i))\n%!assert (sum (sparse ([2; 3; 0; 5; 6] * i), \"extra\"), sparse (16i))\n%!assert (sum (sparse ([2; 3; 4; 5; 6]' * i), \"extra\"), sparse (20i))\n%!assert (sum (sparse ([2; 3; 0; 5; 6]' * i), \"extra\"), sparse (16i))\n%!assert (sum (speye (3) * i, \"extra\"), sparse ([1, 1, 1]*i))\n%!assert (sum (speye (3) * i, 1, \"extra\"), sparse ([1, 1, 1]*i))\n%!assert (sum (speye (3) * i, 2, \"extra\"), sparse ([1; 1; 1]*i))\n%!assert (sum (speye (3) * i, 3, \"extra\"), speye (3) * i)\n\n## Test 'extra' option with sparse matrices\n%!assert (sum (sparse ([2; 3; 4; 5; 6]), \"extra\"), sparse (20))\n%!assert (sum (sparse ([2; 3; 0; 5; 6]), \"extra\"), sparse (16))\n%!assert (sum (sparse ([2; 3; 4; 5; 6]'), \"extra\"), sparse (20))\n%!assert (sum (sparse ([2; 3; 0; 5; 6]'), \"extra\"), sparse (16))\n%!assert (sum (speye (3), \"extra\"), sparse ([1, 1, 1]))\n%!assert (sum (speye (3), 1, \"extra\"), sparse ([1, 1, 1]))\n%!assert (sum (speye (3), 2, \"extra\"), sparse ([1; 1; 1]))\n%!assert (sum (speye (3), 3, \"extra\"), speye (3))\n%!assert (sum (sparse ([2; 3; 4; 5; 6] * i), \"extra\"), sparse (20i))\n%!assert (sum (sparse ([2; 3; 0; 5; 6] * i), \"extra\"), sparse (16i))\n%!assert (sum (sparse ([2; 3; 4; 5; 6]' * i), \"extra\"), sparse (20i))\n%!assert (sum (sparse ([2; 3; 0; 5; 6]' * i), \"extra\"), sparse (16i))\n%!assert (sum (speye (3) * i, \"extra\"), sparse ([1, 1, 1]*i))\n%!assert (sum (speye (3) * i, 1, \"extra\"), sparse ([1, 1, 1]*i))\n%!assert (sum (speye (3) * i, 2, \"extra\"), sparse ([1; 1; 1]*i))\n%!assert (sum (speye (3) * i, 3, \"extra\"), speye (3) * i)\n\n## Test cases for \"omitnan\"\n%!test\n%! A = [1, NaN; 2, NaN; 3, NaN];\n%! assert (sum (A, 2, \"omitnan\"), [1; 2; 3]);\n%!test\n%! A = [1, 2, 3; NaN, NaN, NaN];\n%! assert (sum (A, 1, \"omitnan\"), [1, 2, 3]);\n%!test\n%! A = [NaN, NaN, NaN];\n%! assert (sum (A, \"omitnan\"), 0);\n%!test\n%! A = [1, NaN, 3; 2, NaN, 4; 5, NaN, 6];\n%! assert (sum (A, 1, \"omitnan\"), [8, 0, 13]);\n%!test\n%! A = [1, 2, NaN; 3, 4, NaN; 5, 6, NaN];\n%! assert (sum (A, 2, \"omitnan\"), [3; 7; 11]);\n%!test\n%! A = [2, NaN, NaN, 3; 4, NaN, NaN, 5; 1, NaN, NaN, 6];\n%! assert (sum (A, 1, \"omitnan\"), [7, 0, 0, 14]);\n%!test\n%! A = [1, NaN, 3, NaN, 5; 2, NaN, 4, NaN, 6; 3, NaN, 5, NaN, 7];\n%! assert (sum (A, 1, \"omitnan\"), [6, 0, 12, 0, 18]);\n%!test\n%! A = [1+2i, NaN; 3+4i, NaN; 5+6i, NaN];\n%! assert (sum (A, 2, \"omitnan\"), [1+2i; 3+4i; 5+6i]);\n%!test\n%! A = single ([1, NaN; 2, NaN; 3, NaN]);\n%! assert (sum (A, 2, \"omitnan\"), single ([1; 2; 3]));\n%!test\n%! A = single ([NaN, NaN, NaN]);\n%! assert (sum (A, \"omitnan\"), single (0));\n\n## Test boolean sum optimization\n%!test\n%! x = [true, false, true; false, true, false];\n%! assert (sum (x, 1), [1, 1, 1]);\n%! assert (sum (x, 2), [2; 1]);\n\n%!test\n%! x = rand (100, 100) > 0.5;\n%! assert (sum (x), sum (double (x)));\n%! assert (sum (x, 2), sum (double (x), 2));\n\n%!assert (sum (true), 1)\n%!assert (sum (false), 0)\n%!assert (class (sum ([true, false])), \"double\")\n\n## Test input validation\n%!error <Invalid call> sum ()\n%!error <Invalid call> sum (1,2,3)\n%!error <unrecognized optional argument 'foobar'> sum (1, \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! sum (ones (3,3), 1, \"all\");\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! sum (ones (3,3), [1, 2], \"all\");\n%!error <invalid dimension DIM = 0> sum (ones (3,3), 0)\n%!error <invalid dimension DIM = -1> sum (ones (3,3), -1)\n%!error <invalid dimension in VECDIM = -2> sum (ones (3,3), [1 -2])\n%!error <duplicate dimension in VECDIM = 2> sum (ones (3,3), [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> sum (ones (3,3), [1 1 2])\n*/\n\nDEFUN (sumsq, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} sumsq (@var{x})\n@deftypefnx {} {@var{y} =} sumsq (@var{x}, @var{dim})\n@deftypefnx {} {@var{y} =} sumsq (@var{x}, @var{vecdim})\n@deftypefnx {} {@var{y} =} sumsq (@var{x}, \"all\")\n@deftypefnx {} {@var{y} =} sumsq (@dots{}, @var{outtype})\n@deftypefnx {} {@var{y} =} sumsq (@dots{}, @var{nanflag})\nCompute the sum of squares of the elements of @var{x}.\n\nIf @var{x} is a vector, then @code{sumsq (@var{x})} returns the sum of the\nsquares of the elements in @var{x}.\n\nIf @var{x} is a matrix, then @code{sumsq (@var{x})} returns a row vector with\neach element containing the sum of squares of the corresponding column in\n@var{x}.\n\nIf @var{x} is an array, then @code{sumsq(@var{x})} computes the sum of squares\nalong the first non-singleton dimension of @var{x}.\n\nThis function is conceptually equivalent to computing\n\n@example\nsum (x .* conj (x))\n@end example\n\n@noindent\nbut it uses less memory and avoids calling @code{conj} if @var{x} is real.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension in @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return a sum of squares\nequal to @code{@var{x}.^2}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{prod} to operate on\nall elements of @var{x}, and is equivalent to @code{sumsq (@var{x}(:))}.\n\nThe optional input @var{outtype} specifies the data type that is returned as\nwell as the class of the variable used for calculations.\n@var{outtype} can take the following values:\n\n@table @asis\n@item @qcode{\"default\"}\nOperations on floating point inputs (double or single) are performed in their\nnative data type; while operations on integer, logical, and character data\ntypes are performed using doubles.  Output is of type double, unless the input\nis single in which case the output is of type single.\n\n@item @qcode{\"double\"}\nOperations are performed in double precision even for single precision inputs.\nOutput is of type double.\n\n@item @qcode{\"native\"}\nOperations are performed in their native data types and output is of the same\ntype as the input as reported by (@code{class (@var{x})}).  When the input is\nlogical, @code{sumsq (@var{x}, \"native\")} is equivalent to\n@code{all (@var{x})}.\n@end table\n\nThe optional variable @var{nanflag} specifies whether to include or exclude\nNaN values from the calculation using any of the previously specified input\nargument combinations.  The default value for @var{nanflag} is\n@qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\nNaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\nwill be @var{0}, if @var{x} consists of all NaN values in the\noperating dimension.\n@seealso{sum, prod}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  bool isnative = false;\n  bool isdouble = false;\n  bool do_perm = false;\n  bool allflag = false;\n  bool nanflag = false;\n\n  while (nargin > 1 && args(nargin - 1).is_string ())\n    {\n      std::string str = args(nargin - 1).string_value ();\n\n      if (str == \"native\")\n        isnative = true;\n      else if (str == \"double\")\n        isdouble = true;\n      else if (str == \"all\")\n        allflag = true;\n      else if (str == \"omitnan\" || str == \"omitmissing\")\n        {\n          if (args(0).is_double_type () || args(0).is_single_type ())\n            nanflag = true;\n        }\n      else if (str == \"includenan\" || str == \"includemissing\")\n        nanflag = false;\n      else if (str != \"default\")\n        error (\"sumsq: unrecognized optional argument '%s'\", str.c_str ());\n\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  if (allflag && nargin > 1)\n    error (\"sumsq: cannot set DIM or VECDIM with 'all' flag\");\n\n  octave_value arg = args(0);\n\n  // Handle DIM, VECDIM\n  int dim = -1;\n  Array<int> perm_vec;\n  if (nargin == 2)\n    {\n      octave_value dimarg = args(1);\n      get_dim_vecdim_all (dimarg, arg, dim, perm_vec, do_perm, allflag, \"sumsq\");\n    }\n\n  // Handle allflag\n  if (allflag)\n    arg = arg.reshape (dim_vector (arg.numel (), 1));\n\n  octave_value retval;\n\n  switch (arg.builtin_type ())\n    {\n    case btyp_double:\n      if (arg.issparse ())\n        retval = arg.sparse_matrix_value ().sumsq (dim, nanflag);\n      else\n        retval = arg.array_value ().sumsq (dim, nanflag);\n      break;\n\n    case btyp_complex:\n      if (arg.issparse ())\n        retval = arg.sparse_complex_matrix_value ().sumsq (dim, nanflag);\n      else\n        retval = arg.complex_array_value ().sumsq (dim, nanflag);\n      break;\n\n    case btyp_float:\n      if (isdouble)\n        retval = arg.float_array_value ().dsumsq (dim, nanflag);\n      else\n        retval = arg.float_array_value ().sumsq (dim, nanflag);\n      break;\n\n    case btyp_float_complex:\n      if (isdouble)\n        retval = arg.float_complex_array_value ().dsumsq (dim, nanflag);\n      else\n        retval = arg.float_complex_array_value ().sumsq (dim, nanflag);\n      break;\n\n#define MAKE_INT_BRANCH(X)                               \\\n      case btyp_ ## X:                                   \\\n        if (isnative)                                    \\\n          retval = arg.X ## _array_value ().sumsq (dim); \\\n        else                                             \\\n          retval = arg.array_value ().sumsq (dim);       \\\n        break;\n\n      MAKE_INT_BRANCH (int8);\n      MAKE_INT_BRANCH (int16);\n      MAKE_INT_BRANCH (int32);\n      MAKE_INT_BRANCH (int64);\n      MAKE_INT_BRANCH (uint8);\n      MAKE_INT_BRANCH (uint16);\n      MAKE_INT_BRANCH (uint32);\n      MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n    // GAGME: Accursed Matlab compatibility...\n    case btyp_char:\n      retval = arg.array_value (true).sumsq (dim);\n      break;\n\n    case btyp_bool:\n      if (arg.issparse ())\n        {\n          if (isnative)\n            retval = arg.sparse_bool_matrix_value ().all (dim);\n          else\n            retval = arg.sparse_matrix_value ().sumsq (dim);\n        }\n      else if (isnative)\n        retval = arg.bool_array_value ().all (dim);\n      else\n        {\n          // For booleans: sumsq (x) = sum (x), since 0^2=0, 1^2=1\n          boolNDArray m = arg.bool_array_value ();\n          retval = do_mx_red_op<double, bool> (m, dim, mx_inline_count);\n        }\n      break;\n\n    default:\n      err_wrong_type_arg (\"sumsq\", arg);\n    }\n\n  if (do_perm)\n    retval = retval.permute (perm_vec, true);\n\n  return retval;\n}\n\n/*\n%!assert (sumsq ([1, 2, 3]), 14)\n%!assert (sumsq ([-1; -2; 4i]), 21)\n%!assert (sumsq ([1, 2, 3; 2, 3, 4; 4i, 6i, 2]), [21, 49, 29])\n\n%!assert (sumsq (single ([1, 2, 3])), single (14))\n%!assert (sumsq (single ([-1; -2; 4i])), single (21))\n%!assert (sumsq (single ([1, 2, 3; 2, 3, 4; 4i, 6i, 2])),\n%!        single ([21, 49, 29]))\n\n%!assert (sumsq ([1, 2; 3, 4], 1), [10, 20])\n%!assert (sumsq ([1, 2; 3, 4], 2), [5; 25])\n\n%!assert (sumsq (single ([1, 2; 3, 4]), 1), single ([10, 20]))\n%!assert (sumsq (single ([1, 2; 3, 4]), 2), single ([5; 25]))\n\n## Test empty matrices\n%!assert (sumsq ([]), 0)\n%!assert (sumsq ([], 1), zeros (1, 0))\n%!assert (sumsq ([], 2), zeros (0, 1))\n%!assert (sumsq ([], 3), zeros (0, 0))\n%!assert (sumsq (zeros (1, 0)), 0)\n%!assert (sumsq (zeros (1, 0), 1), zeros (1, 0))\n%!assert (sumsq (zeros (1, 0), 2), 0)\n%!assert (sumsq (zeros (0, 1)), 0)\n%!assert (sumsq (zeros (0, 1), 1), 0)\n%!assert (sumsq (zeros (0, 1), 2), zeros (0, 1))\n%!assert (sumsq (zeros (2, 0)), zeros (1, 0))\n%!assert (sumsq (zeros (2, 0), 1), zeros (1, 0))\n%!assert (sumsq (zeros (2, 0), 2), [0; 0])\n%!assert (sumsq (zeros (0, 2)), [0, 0])\n%!assert (sumsq (zeros (0, 2), 1), [0, 0])\n%!assert (sumsq (zeros (0, 2), 2), zeros (0, 1))\n%!assert (sumsq (zeros (2, 2, 0, 3)), zeros (1, 2, 0, 3))\n%!assert (sumsq (zeros (2, 2, 0, 3), 2), zeros (2, 1, 0, 3))\n%!assert (sumsq (zeros (2, 2, 0, 3), 3), zeros (2, 2, 1, 3))\n%!assert (sumsq (zeros (2, 2, 0, 3), 4), zeros (2, 2, 0))\n%!assert (sumsq (zeros (2, 2, 0, 3), 7), zeros (2, 2, 0, 3))\n\n%!assert (sumsq (single ([])), single (0))\n%!assert (sumsq (single ([]), 1), single (zeros (1, 0)))\n%!assert (sumsq (single ([]), 2), single (zeros (0, 1)))\n%!assert (sumsq (single ([]), 3), single (zeros (0, 0)))\n%!assert (sumsq (zeros (1, 0, \"single\")), single (0))\n%!assert (sumsq (zeros (1, 0, \"single\"), 1), zeros (1, 0, \"single\"))\n%!assert (sumsq (zeros (1, 0, \"single\"), 2), single (0))\n%!assert (sumsq (zeros (0, 1, \"single\")), single (0))\n%!assert (sumsq (zeros (0, 1, \"single\"), 1), single (0))\n%!assert (sumsq (zeros (0, 1, \"single\"), 2), zeros (0, 1, \"single\"))\n%!assert (sumsq (zeros (2, 0, \"single\")), zeros (1, 0, \"single\"))\n%!assert (sumsq (zeros (2, 0, \"single\"), 1), zeros (1, 0, \"single\"))\n%!assert (sumsq (zeros (2, 0, \"single\"), 2), single ([0; 0]))\n%!assert (sumsq (zeros (0, 2, \"single\")), single ([0, 0]))\n%!assert (sumsq (zeros (0, 2, \"single\"), 1), single ([0, 0]))\n%!assert (sumsq (zeros (0, 2, \"single\"), 2), zeros (0, 1, \"single\"))\n%!assert (sumsq (zeros (2, 2, 0, 3, \"single\")), zeros (1, 2, 0, 3, \"single\"))\n%!assert (sumsq (zeros (2, 2, 0, 3, \"single\"), 2), zeros (2, 1, 0, 3, \"single\"))\n%!assert (sumsq (zeros (2, 2, 0, 3, \"single\"), 3), zeros (2, 2, 1, 3, \"single\"))\n%!assert (sumsq (zeros (2, 2, 0, 3, \"single\"), 4), zeros (2, 2, 0, \"single\"))\n%!assert (sumsq (zeros (2, 2, 0, 3, \"single\"), 7), zeros (2, 2, 0, 3, \"single\"))\n\n## Test dimension indexing with vecdim in N-dimensional arrays\n%!test\n%! x = repmat ([1:20;6:25], [5 2 6 3]);\n%! assert (size (sumsq (x, [3 2])), [10 1 1 3]);\n%! assert (size (sumsq (x, [1 2])), [1 1 6 3]);\n%! assert (size (sumsq (x, [1 2 4])), [1 1 6]);\n%! assert (size (sumsq (x, [1 4 3])), [1 40]);\n%! assert (size (sumsq (x, [1 2 3 4])), [1 1]);\n\n## Test exceeding dimensions\n%!assert (sumsq (ones (2), 3), ones (2))\n%!assert (sumsq (ones (2, 2, 2), 99), ones (2, 2, 2))\n%!assert (sumsq (magic (3), 3), magic (3) .^ 2)\n%!assert (sumsq (magic (3), [3, 5]), magic (3) .^ 2)\n%!assert (sumsq (magic (3), [1 3]), sum (magic (3) .^ 2))\n%!assert (sumsq (magic (3), [2 99]), sum (magic (3) .^ 2, 2))\n%!assert (sumsq (single (ones (2)), 4),single (ones (2)))\n%!assert (sumsq (single (ones (2)), [4, 5]),single (ones (2)))\n%!assert (sumsq (sparse ([1, 2; 3, 4]), 3), sparse ([1, 2; 3, 4].^2))\n%!assert (sumsq (sparse ([1, 2i; 3, 4]), 3), sparse ([1, 4; 9, 16]))\n\n## Test nanflag\n%!test\n%! x = ones (3,4,5);\n%! x(1) = NaN;\n%! assert (sumsq (x)(:,:,1), [NaN, 3, 3, 3]);\n%! assert (sumsq (x, \"includenan\")(:,:,1), [NaN, 3, 3, 3]);\n%! assert (sumsq (x, \"omitnan\")(:,:,1), [2, 3, 3, 3]);\n%! assert (sumsq (x, \"omitmissing\")(:,:,1), [2, 3, 3, 3]);\n%! assert (sumsq (x, [2 3]), [NaN; 20; 20]);\n%! assert (sumsq (x, [2 3], \"omitnan\"), [19; 20; 20]);\n\n## Test cases for \"omitnan\"\n%!test\n%! A = [1, NaN; 2, NaN; 3, NaN];\n%! assert (sumsq (A, 2, \"omitnan\"), [1; 4; 9]);\n%!test\n%! A = [NaN, NaN, NaN];\n%! assert (sumsq (A, \"omitnan\"), 0);\n%!test\n%! A = [2, 3, NaN; 4, 5, NaN; 1, 2, NaN];\n%! assert (sumsq (A, 2, \"omitnan\"), [13; 41; 5]);\n%!test\n%! A = [2, NaN, 3; 3, NaN, 4; 1, NaN, 2];\n%! assert (sumsq (A, 1, \"omitnan\"), [14, 0, 29]);\n%!test\n%! A = [1+2i, NaN; 3+4i, NaN];\n%! assert (sumsq (A, 2, \"omitnan\"), [5; 25]);\n%!test\n%! A = single ([NaN, NaN, NaN]);\n%! assert (sumsq (A, \"omitnan\"), single (0));\n\n## Test sparse matrices\n%!assert (sumsq (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN])),\n%!        sparse ([NaN, NaN, 2, 20, NaN]))\n%!assert (sumsq (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), \"omitnan\"),\n%!        sparse ([1, 4, 2, 20, 4]))\n%!assert (sumsq (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2),\n%!        sparse ([NaN; NaN]))\n%!assert (sumsq (sparse ([NaN, NaN, 1, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([21; 10]))\n%!assert (sumsq (sparse ([NaN, NaN, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([21; 10]))\n%!assert (sumsq (sparse ([NaN, 0i, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([21; 10]))\n%!assert (sumsq (sparse ([NaN, 1+i, 1i, 4, 2; 1, 2, 1, 2, NaN]), 2, \"omitnan\"),\n%!        sparse ([23; 10]))\n%!assert (sumsq (sparse ([NaN, NaN, NaN]), \"omitnan\"), sparse (0))\n%!assert (sumsq (sparse ([0, 0, 0, NaN, NaN, NaN]), \"omitnan\"), sparse (0))\n\n## Test empty sparse matrices\n%!assert (sumsq (sparse (ones(1, 0))), sparse (0))\n%!assert (size (sumsq (sparse (ones(1, 0)), 1)), [1, 0])\n%!assert (size (sumsq (sparse (ones(1, 0)), 2)), [1, 1])\n%!assert (sumsq (sparse (ones(0, 1))), sparse (0))\n%!assert (size (sumsq (sparse (ones(0, 1)), 1)), [1, 1])\n%!assert (size (sumsq (sparse (ones(0, 1)), 1)), [1, 1])\n%!assert (size (sumsq (sparse (ones(0, 1)), 2)), [0, 1])\n%!assert (sumsq (sparse (ones(0, 0))), sparse (0))\n%!assert (size (sumsq (sparse (ones(0, 0)), 1)), [1, 0])\n%!assert (size (sumsq (sparse (ones(0, 0)), 2)), [0, 1])\n%!assert (size (sumsq (sparse (ones(0, 0)), 3)), [0, 0])\n\n## Test boolean sumsq (must be equal to sum)\n%!test\n%! x = [true, false, true; false, true, false];\n%! assert (sumsq (x), sum (x));\n%! assert (sumsq (x, 1), [1, 1, 1]);\n%! assert (sumsq (x, 2), [2; 1]);\n\n%!test\n%! x = rand (100, 100) > 0.5;\n%! assert (sumsq (x), sum (x));\n\n%!assert (sumsq (true), 1)\n%!assert (sumsq (false), 0)\n%!assert (class (sumsq ([true, false])), \"double\")\n\n## Test input validation\n%!error <Invalid call> sumsq ()\n%!error <Invalid call> sumsq (1,2,3)\n%!error <unrecognized optional argument 'foobar'> sumsq (1, \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! sumsq (ones (3,3), 1, \"all\");\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! sumsq (ones (3,3), [1, 2], \"all\");\n%!error <invalid dimension DIM = 0> sumsq (ones (3,3), 0)\n%!error <invalid dimension DIM = -1> sumsq (ones (3,3), -1)\n%!error <invalid dimension in VECDIM = -2> sumsq (ones (3,3), [1 -2])\n%!error <duplicate dimension in VECDIM = 2> sumsq (ones (3,3), [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> sumsq (ones (3,3), [1 1 2])\n*/\n\nDEFUN (islogical, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{tf} =} islogical (@var{x})\n@deftypefnx {} {@var{tf} =} isbool (@var{x})\nReturn true if @var{x} is a logical object.\n\nProgramming Note: @code{isbool} is an alias for @code{islogical} and can be\nused interchangeably.\n@seealso{ischar, isfloat, isinteger, isstring, isnumeric, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).islogical ());\n}\n\nDEFALIAS (isbool, islogical);\n\n/*\n%!assert (islogical (true), true)\n%!assert (islogical (false), true)\n%!assert (islogical ([true, false]), true)\n%!assert (islogical (1), false)\n%!assert (islogical (1i), false)\n%!assert (islogical ([1,1]), false)\n%!assert (islogical (single (1)), false)\n%!assert (islogical (single (1i)), false)\n%!assert (islogical (single ([1,1])), false)\n%!assert (islogical (sparse ([true, false])), true)\n%!assert (islogical (sparse ([1, 0])), false)\n*/\n\nDEFUN (isinteger, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isinteger (@var{x})\nReturn true if @var{x} is an integer object (int8, uint8, int16, etc.).\n\nNote that @w{@code{isinteger (14)}}@ is false because numeric constants in\nOctave are double precision floating point values.\n@seealso{isfloat, ischar, islogical, isstring, isnumeric, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isinteger ());\n}\n\n/*\n%!assert (isinteger (int8 (16)))\n%!assert (isinteger (int16 (16)))\n%!assert (isinteger (int32 (16)))\n%!assert (isinteger (int64 (16)))\n\n%!assert (isinteger (uint8 (16)))\n%!assert (isinteger (uint16 (16)))\n%!assert (isinteger (uint32 (16)))\n%!assert (isinteger (uint64 (16)))\n\n%!assert (isinteger (intmax (\"int8\")))\n%!assert (isinteger (intmax (\"int16\")))\n%!assert (isinteger (intmax (\"int32\")))\n%!assert (isinteger (intmax (\"int64\")))\n\n%!assert (isinteger (intmax (\"uint8\")))\n%!assert (isinteger (intmax (\"uint16\")))\n%!assert (isinteger (intmax (\"uint32\")))\n%!assert (isinteger (intmax (\"uint64\")))\n\n%!assert (isinteger (intmin (\"int8\")))\n%!assert (isinteger (intmin (\"int16\")))\n%!assert (isinteger (intmin (\"int32\")))\n%!assert (isinteger (intmin (\"int64\")))\n\n%!assert (isinteger (intmin (\"uint8\")))\n%!assert (isinteger (intmin (\"uint16\")))\n%!assert (isinteger (intmin (\"uint32\")))\n%!assert (isinteger (intmin (\"uint64\")))\n\n%!assert (isinteger (uint8 ([1:10])))\n%!assert (isinteger (uint8 ([1:10; 1:10])))\n\n%!assert (! isinteger (16))\n%!assert (! isinteger (\"parrot\"))\n%!assert (! isinteger ([1, 2, 3]))\n\n%!error isinteger ()\n%!error isinteger (\"multiple\", \"parameters\")\n*/\n\nDEFUN (iscomplex, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} iscomplex (@var{x})\nReturn true if @var{x} is a complex-valued numeric object.\n@seealso{isreal, isnumeric, ischar, isfloat, islogical, isstring, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).iscomplex ());\n}\n\n/*\n%!assert (iscomplex (4), false)\n%!assert (iscomplex (i), true)\n%!assert (iscomplex (4+3i), true)\n%!assert (iscomplex ([1, 2, 3]), false)\n%!assert (iscomplex ([1, 2i, 3]), true)\n\n%!assert (iscomplex (0j), false)\n%!assert (iscomplex (complex (0,0)), true)\n%!assert (iscomplex (\"4\"), false)\n%!assert (iscomplex ({i}), false)\n\n## Test input validation\n%!error iscomplex ()\n%!error iscomplex (1, 2)\n*/\n\nDEFUN (isfloat, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isfloat (@var{x})\nReturn true if @var{x} is a floating-point numeric object.\n\nObjects of class double or single are floating-point objects.\n@seealso{isinteger, ischar, islogical, isnumeric, isstring, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isfloat ());\n}\n\n// FIXME: perhaps this should be implemented with an\n// octave_value member function?\n\nDEFUN (complex, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{z} =} complex (@var{x})\n@deftypefnx {} {@var{z} =} complex (@var{re}, @var{im})\nReturn a complex value from real arguments.\n\nWith 1 real argument @var{x}, return the complex result\n@w{@code{@var{x} + 0i}}.\n\nWith 2 real arguments, return the complex result\n@w{@code{@var{re} + @var{im}i}}.\n@code{complex} can often be more convenient than expressions such as\n@w{@code{a + b*i}}.\nFor example:\n\n@example\n@group\ncomplex ([1, 2], [3, 4])\n  @xresult{} [ 1 + 3i   2 + 4i ]\n@end group\n@end example\n@seealso{real, imag, iscomplex, abs, arg}\n@end deftypefn */)\n// Programming Note: Throughout this function the coding pattern\n// octave_value (new XXX)) is used.  This is done specifically because the\n// default octave_value constructor would otherwise perform automatic narrowing\n// (i.e., complex values with 0 for the imaginary part would be converted\n// to real values).  The complex() function *must* return a complex value\n// even when the imaginary part is 0.\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 1)\n    {\n      octave_value arg = args(0);\n\n      if (arg.iscomplex ())\n        retval = arg;\n      else\n        {\n          if (arg.issparse ())\n            {\n              SparseComplexMatrix val = arg.xsparse_complex_matrix_value (\"complex: invalid conversion\");\n\n              retval = octave_value (new octave_sparse_complex_matrix (val));\n            }\n          else if (arg.is_single_type ())\n            {\n              if (arg.numel () == 1)\n                {\n                  FloatComplex val = arg.xfloat_complex_value (\"complex: invalid conversion\");\n\n                  retval = octave_value (new octave_float_complex (val));\n                }\n              else\n                {\n                  FloatComplexNDArray val = arg.xfloat_complex_array_value (\"complex: invalid conversion\");\n\n                  retval = octave_value (new octave_float_complex_matrix (val));\n                }\n            }\n          else\n            {\n              if (arg.numel () == 1)\n                {\n                  Complex val = arg.xcomplex_value (\"complex: invalid conversion\");\n\n                  retval = octave_value (new octave_complex (val));\n                }\n              else\n                {\n                  ComplexNDArray val = arg.xcomplex_array_value (\"complex: invalid conversion\");\n\n                  retval = octave_value (new octave_complex_matrix (val));\n                }\n            }\n        }\n    }\n  else\n    {\n      octave_value re = args(0);\n      octave_value im = args(1);\n\n      if (re.issparse () && im.issparse ())\n        {\n          const SparseMatrix re_val = re.sparse_matrix_value ();\n          const SparseMatrix im_val = im.sparse_matrix_value ();\n\n          if (re.numel () == 1)\n            {\n              SparseComplexMatrix result;\n              if (re_val.nnz () == 0)\n                result = Complex (0, 1) * SparseComplexMatrix (im_val);\n              else\n                {\n                  octave_idx_type nr = im_val.rows ();\n                  octave_idx_type nc = im_val.cols ();\n                  result = SparseComplexMatrix (nr, nc, re_val(0));\n\n                  for (octave_idx_type j = 0; j < nc; j++)\n                    {\n                      octave_idx_type off = j * nr;\n                      for (octave_idx_type i = im_val.cidx (j);\n                           i < im_val.cidx (j + 1); i++)\n                        result.data (im_val.ridx (i) + off)\n                        += Complex (0, im_val.data (i));\n                    }\n                }\n              retval = octave_value (new octave_sparse_complex_matrix (result));\n            }\n          else if (im.numel () == 1)\n            {\n              SparseComplexMatrix result;\n              if (im_val.nnz () == 0)\n                result = SparseComplexMatrix (re_val);\n              else\n                {\n                  octave_idx_type nr = re_val.rows ();\n                  octave_idx_type nc = re_val.cols ();\n                  result = SparseComplexMatrix (nr, nc,\n                                                Complex (0, im_val(0)));\n\n                  for (octave_idx_type j = 0; j < nc; j++)\n                    {\n                      octave_idx_type off = j * nr;\n                      for (octave_idx_type i = re_val.cidx (j);\n                           i < re_val.cidx (j + 1); i++)\n                        result.data (re_val.ridx (i) + off)\n                        += re_val.data (i);\n                    }\n                }\n              retval = octave_value (new octave_sparse_complex_matrix (result));\n            }\n          else\n            {\n              if (re_val.dims () != im_val.dims ())\n                error (\"complex: dimension mismatch\");\n\n              SparseComplexMatrix result;\n              result = SparseComplexMatrix (re_val)\n                       + Complex (0, 1) * SparseComplexMatrix (im_val);\n              retval = octave_value (new octave_sparse_complex_matrix (result));\n            }\n        }\n      else if (re.is_single_type () || im.is_single_type ())\n        {\n          if (re.numel () == 1)\n            {\n              float re_val = re.float_value ();\n\n              if (im.numel () == 1)\n                {\n                  float im_val = im.double_value ();\n\n                  retval = octave_value (new octave_float_complex\n                                         (FloatComplex (re_val, im_val)));\n                }\n              else\n                {\n                  const FloatNDArray im_val = im.float_array_value ();\n\n                  FloatComplexNDArray result (im_val.dims ());\n\n                  for (octave_idx_type i = 0; i < im_val.numel (); i++)\n                    result.xelem (i) = FloatComplex (re_val, im_val.xelem (i));\n\n                  retval = octave_value (new octave_float_complex_matrix\n                                         (result));\n                }\n            }\n          else\n            {\n              const FloatNDArray re_val = re.float_array_value ();\n\n              if (im.numel () == 1)\n                {\n                  float im_val = im.float_value ();\n\n                  FloatComplexNDArray result (re_val.dims ());\n\n                  for (octave_idx_type i = 0; i < re_val.numel (); i++)\n                    result.xelem (i) = FloatComplex (re_val.xelem (i), im_val);\n\n                  retval = octave_value (new octave_float_complex_matrix\n                                         (result));\n                }\n              else\n                {\n                  const FloatNDArray im_val = im.float_array_value ();\n\n                  if (re_val.dims () != im_val.dims ())\n                    error (\"complex: dimension mismatch\");\n\n                  FloatComplexNDArray result (re_val.dims ());\n\n                  for (octave_idx_type i = 0; i < re_val.numel (); i++)\n                    result.xelem (i) = FloatComplex (re_val.xelem (i),\n                                                     im_val.xelem (i));\n\n                  retval = octave_value (new octave_float_complex_matrix\n                                         (result));\n                }\n            }\n        }\n      else if (re.numel () == 1)\n        {\n          double re_val = re.double_value ();\n\n          if (im.numel () == 1)\n            {\n              double im_val = im.double_value ();\n\n              retval = octave_value (new octave_complex\n                                     (Complex (re_val, im_val)));\n            }\n          else\n            {\n              const NDArray im_val = im.array_value ();\n\n              ComplexNDArray result (im_val.dims ());\n\n              for (octave_idx_type i = 0; i < im_val.numel (); i++)\n                result.xelem (i) = Complex (re_val, im_val.xelem (i));\n\n              retval = octave_value (new octave_complex_matrix (result));\n            }\n        }\n      else\n        {\n          const NDArray re_val = re.array_value ();\n\n          if (im.numel () == 1)\n            {\n              double im_val = im.double_value ();\n\n              ComplexNDArray result (re_val.dims ());\n\n              for (octave_idx_type i = 0; i < re_val.numel (); i++)\n                result.xelem (i) = Complex (re_val.xelem (i), im_val);\n\n              retval = octave_value (new octave_complex_matrix (result));\n            }\n          else\n            {\n              const NDArray im_val = im.array_value ();\n\n              if (re_val.dims () != im_val.dims ())\n                error (\"complex: dimension mismatch\");\n\n              ComplexNDArray result (re_val.dims (), Complex ());\n\n              for (octave_idx_type i = 0; i < re_val.numel (); i++)\n                result.xelem (i) = Complex (re_val.xelem (i),\n                                            im_val.xelem (i));\n\n              retval = octave_value (new octave_complex_matrix (result));\n            }\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!error <undefined> 1+Infj\n%!error <undefined> 1+Infi\n\n%!test <31974>\n%! assert (Inf + Inf*i, complex (Inf, Inf));\n%!\n%! assert (1 + Inf*i, complex (1, Inf));\n%! assert (1 + Inf*j, complex (1, Inf));\n%!\n%! ## whitespace should not affect parsing\n%! assert (1+Inf*i, complex (1, Inf));\n%! assert (1+Inf*j, complex (1, Inf));\n%!\n%! assert (NaN*j, complex (0, NaN));\n%!\n%! assert (Inf * 4j, complex (0, Inf));\n\n%!test <31974>\n%! x = Inf;\n%! assert (x * j, complex (0, Inf));\n%! j = complex (0, 1);\n%! assert (Inf * j, complex (0, Inf));\n\n%!test <31974>\n%! exp = complex (zeros (2, 2), Inf (2, 2));\n%! assert (Inf (2, 2) * j, exp);\n%! assert (Inf (2, 2) .* j, exp);\n%! assert (Inf * (ones (2, 2) * j), exp);\n%! assert (Inf (2, 2) .* (ones (2, 2) * j), exp);\n\n%!test <31974>\n%! assert ([Inf; 0] * [i, 0], complex ([NaN NaN; 0 0], [Inf NaN; 0 0]));\n%! assert ([Inf, 0] * [i; 0], complex (NaN, Inf));\n%! assert ([Inf, 0] .* [i, 0], complex ([0 0], [Inf 0]));\n\n%!test <31974>\n%! m = @(x, y) x * y;\n%! d = @(x, y) x / y;\n%! assert (m (Inf, i), complex (0, +Inf));\n%! assert (d (Inf, i), complex (0, -Inf));\n*/\n\nDEFUN (isreal, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isreal (@var{x})\nReturn true if @var{x} is a non-complex matrix or scalar.\n\nFor compatibility with @sc{matlab}, this includes logical and character\nmatrices.\n@seealso{iscomplex, isnumeric, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isreal ());\n}\n\nDEFUN (isempty, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isempty (@var{A})\nReturn true if @var{A} is an empty object (any one of its dimensions is\nzero).\n@seealso{isnull, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isempty ());\n}\n\n/*\n## Debian bug #706376\n%!assert (isempty (speye (2^16)), false)\n*/\n\nDEFUN (isnumeric, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isnumeric (@var{x})\nReturn true if @var{x} is a numeric object, i.e., an integer, real, or\ncomplex array.\n\nLogical and character arrays are not considered to be numeric.\n@seealso{isinteger, isfloat, isreal, iscomplex, ischar, islogical, isstring,\niscell, isstruct, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isnumeric ());\n}\n\n/*\n%!assert (isnumeric (1), true)\n%!assert (isnumeric (1i), true)\n%!assert (isnumeric ([1,1]), true)\n%!assert (isnumeric (single (1)), true)\n%!assert (isnumeric (single (1i)), true)\n%!assert (isnumeric (single ([1,1])), true)\n%!assert (isnumeric (int8 (1)), true)\n%!assert (isnumeric (uint8 ([1,1])), true)\n%!assert (isnumeric (\"Hello World\"), false)\n%!assert (isnumeric (true), false)\n%!assert (isnumeric (false), false)\n%!assert (isnumeric ([true, false]), false)\n%!assert (isnumeric (sparse ([true, false])), false)\n*/\n\nDEFUN (isscalar, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isscalar (@var{x})\nReturn true if @var{x} is a scalar.\n\nA scalar is a single-element object of any type for which @code{size (@var{x})}\nreturns @w{@code{[1, 1]}}.\n@seealso{isvector, ismatrix, size}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function *must* use size() to determine the desired values to be\n  // compatible with Matlab and to allow user-defined class overloading.\n  Matrix sz = octave_value (args(0)).size ();\n\n  return ovl (sz.numel () == 2 && sz(0) == 1 && sz(1) == 1);\n}\n\n/*\n%!assert (isscalar (1))\n%!assert (isscalar ([1, 2]), false)\n%!assert (isscalar ([]), false)\n%!assert (isscalar ([1, 2; 3, 4]), false)\n\n%!assert (isscalar (\"t\"))\n%!assert (isscalar (\"test\"), false)\n%!assert (isscalar ([\"test\"; \"ing\"]), false)\n\n%!test\n%! s.a = 1;\n%! assert (isscalar (s));\n\n## Test input validation\n%!error isscalar ()\n%!error isscalar (1, 2)\n*/\n\nDEFUN (isvector, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isvector (@var{x})\nReturn true if @var{x} is a vector.\n\nA vector is a 2-D array of any type where one of the dimensions is equal to 1\n(either @nospell{1xN} or @nospell{Nx1}).  As a consequence of this definition,\na 1x1 object (a scalar) is also a vector.\n@seealso{isscalar, ismatrix, iscolumn, isrow, size}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function *must* use size() to determine the desired values to be\n  // compatible with Matlab and to allow user-defined class overloading.\n  Matrix sz = octave_value (args(0)).size ();\n\n  return ovl (sz.numel () == 2 && (sz(0) == 1 || sz(1) == 1));\n}\n\n/*\n%!assert (isvector (1), true)\n%!assert (isvector ([1; 2; 3]), true)\n%!assert (isvector ([1, 2, 3]), true)\n%!assert (isvector ([]), false)\n%!assert (isvector ([1, 2; 3, 4]), false)\n\n%!assert (isvector (\"t\"), true)\n%!assert (isvector (\"test\"), true)\n%!assert (isvector ([\"test\"; \"ing\"]), false)\n\n%!test\n%! s.a = 1;\n%! assert (isvector (s), true);\n\n## Test input validation\n%!error isvector ()\n%!error isvector ([1, 2], 2)\n*/\n\nDEFUN (isrow, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isrow (@var{x})\nReturn true if @var{x} is a row vector.\n\nA row vector is a 2-D array of any type for which @code{size (@var{x})} returns\n@w{@code{[1, N]}}@ with non-negative N.\n@seealso{iscolumn, isscalar, isvector, ismatrix, size}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function *must* use size() to determine the desired values to be\n  // compatible with Matlab and to allow user-defined class overloading.\n  Matrix sz = octave_value (args(0)).size ();\n\n  return ovl (sz.numel () == 2 && sz(0) == 1);\n}\n\n/*\n%!assert (isrow ([1, 2, 3]))\n%!assert (isrow ([1; 2; 3]), false)\n%!assert (isrow (1))\n%!assert (isrow ([]), false)\n%!assert (isrow ([1, 2; 3, 4]), false)\n\n%!assert (isrow (ones (1, 0)), true)\n%!assert (isrow (ones (1, 1)), true)\n%!assert (isrow (ones (1, 2)), true)\n%!assert (isrow (ones (1, 1, 1)), true)\n%!assert (isrow (ones (1, 1, 1, 1)), true)\n\n%!assert (isrow (ones (0, 0)), false)\n%!assert (isrow (ones (1, 1, 0)), false)\n\n%!assert (isrow (\"t\"), true)\n%!assert (isrow (\"test\"), true)\n%!assert (isrow ([\"test\"; \"ing\"]), false)\n\n%!test\n%! s.a = 1;\n%! assert (isrow (s), true);\n\n## Test input validation\n%!error isrow ()\n%!error isrow ([1, 2], 2)\n*/\n\nDEFUN (iscolumn, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} iscolumn (@var{x})\nReturn true if @var{x} is a column vector.\n\nA column vector is a 2-D array of any type for which @code{size (@var{x})}\nreturns @w{@code{[N, 1]}}@ with non-negative N.\n@seealso{isrow, isscalar, isvector, ismatrix, size}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function *must* use size() to determine the desired values to be\n  // compatible with Matlab and to allow user-defined class overloading.\n  Matrix sz = octave_value (args(0)).size ();\n\n  return ovl (sz.numel () == 2 && sz(1) == 1);\n}\n\n/*\n%!assert (iscolumn ([1, 2, 3]), false)\n%!assert (iscolumn ([1; 2; 3]), true)\n%!assert (iscolumn (1), true)\n%!assert (iscolumn ([]), false)\n%!assert (iscolumn ([1, 2; 3, 4]), false)\n\n%!assert (iscolumn (\"t\"), true)\n%!assert (iscolumn (\"test\"), false)\n%!assert (iscolumn ([\"test\"; \"ing\"]), false)\n\n%!assert (iscolumn (ones (0, 1)), true)\n%!assert (iscolumn (ones (1, 1)), true)\n%!assert (iscolumn (ones (2, 1)), true)\n%!assert (iscolumn (ones (1, 1, 1)), true)\n%!assert (iscolumn (ones (1, 1, 1, 1)), true)\n\n%!assert (iscolumn (ones (0, 0)), false)\n%!assert (iscolumn (ones (0, 1, 0)), false)\n\n%!test\n%! s.a = 1;\n%! assert (iscolumn (s));\n\n## Test input validation\n%!error iscolumn ()\n%!error iscolumn ([1, 2], 2)\n*/\n\nDEFUN (ismatrix, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} ismatrix (@var{x})\nReturn true if @var{x} is a 2-D array.\n\nA matrix is an array of any type where @code{ndims (@var{x}) == 2} and for\nwhich @code{size (@var{x})} returns @w{@code{[M, N]}}@ with non-negative M and\nN.\n@seealso{isscalar, isvector, iscell, isstruct, issparse, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function *must* use size() to determine the desired values to be\n  // compatible with Matlab and to allow user-defined class overloading.\n  Matrix sz = octave_value (args(0)).size ();\n\n  return ovl (sz.numel () == 2 && sz(0) >= 0 && sz(1) >= 0);\n}\n\n/*\n%!assert (ismatrix ([]), true)\n%!assert (ismatrix (1), true)\n%!assert (ismatrix ([1, 2, 3]), true)\n%!assert (ismatrix ([1, 2; 3, 4]), true)\n\n%!assert (ismatrix (zeros (0)), true)\n%!assert (ismatrix (zeros (0, 0)), true)\n%!assert (ismatrix (zeros (0, 0, 0)), false)\n%!assert (ismatrix (zeros (3, 2, 4)), false)\n\n%!assert (ismatrix (single ([])), true)\n%!assert (ismatrix (single (1)), true)\n%!assert (ismatrix (single ([1, 2, 3])), true)\n%!assert (ismatrix (single ([1, 2; 3, 4])), true)\n\n%!assert (ismatrix (\"t\"), true)\n%!assert (ismatrix (\"test\"), true)\n%!assert (ismatrix ([\"test\"; \"ing\"]), true)\n\n%!test\n%! s.a = 1;\n%! assert (ismatrix (s), true);\n\n%!error ismatrix ()\n%!error ismatrix ([1, 2; 3, 4], 2)\n*/\n\nDEFUN (issquare, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} issquare (@var{x})\nReturn true if @var{x} is a 2-D square array.\n\nA square array is a 2-D array of any type for which @code{size (@var{x})}\nreturns @w{@code{[N, N]}}@ where N is a non-negative integer.\n@seealso{isscalar, isvector, ismatrix, size}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function *must* use size() to determine the desired values to\n  // allow user-defined class overloading.\n  Matrix sz = octave_value (args(0)).size ();\n\n  return ovl (sz.numel () == 2 && sz(0) == sz(1));\n}\n\n/*\n%!assert (issquare ([]))\n%!assert (issquare (1))\n%!assert (! issquare ([1, 2]))\n%!assert (issquare ([1, 2; 3, 4]))\n%!assert (! issquare ([1, 2; 3, 4; 5, 6]))\n%!assert (! issquare (ones (3,3,3)))\n%!assert (issquare (\"t\"))\n%!assert (! issquare (\"test\"))\n%!assert (issquare ([\"test\"; \"ing\"; \"1\"; \"2\"]))\n%!test\n%! s.a = 1;\n%! assert (issquare (s));\n%!assert (issquare ({1, 2; 3, 4}))\n%!assert (sparse (([1, 2; 3, 4])))\n\n## Test input validation\n%!error issquare ()\n%!error issquare ([1, 2; 3, 4], 2)\n*/\n\nstatic octave_value\nfill_matrix (const octave_value_list& args, int val, const char *fcn)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  oct_data_conv::data_type dt = oct_data_conv::dt_double;\n\n  dim_vector dims (1, 1);\n  bool issparse = false;\n  bool iscomplex = false;\n\n  if (nargin > 0 && args(nargin-1).is_string ())\n    {\n      std::string nm = args(nargin-1).string_value ();\n      nargin--;\n\n      dt = oct_data_conv::string_to_data_type (nm);\n    }\n\n  if (nargin > 1 && args(nargin-2).is_string ()\n      && args(nargin-2).string_value () == \"like\")\n    {\n      std::string nm = args(nargin-1).class_name ();\n      issparse = args(nargin-1).issparse ();\n      iscomplex = args(nargin-1).iscomplex ();\n      nargin -= 2;\n      dt = oct_data_conv::string_to_data_type (nm);\n    }\n\n  switch (nargin)\n    {\n    case 0:\n      break;\n\n    case 1:\n      get_dimensions (args(0), fcn, dims);\n      break;\n\n    default:\n      {\n        dims.resize (nargin);\n\n        for (int i = 0; i < nargin; i++)\n          {\n            if (args(i).numel () > 1)\n              error (\"%s: dimensions must be scalars.\", fcn);\n\n            dims(i) = (args(i).isempty () ? 0 : args(i).idx_type_value (true));\n          }\n      }\n      break;\n    }\n\n  dims.chop_trailing_singletons ();\n\n  check_dimensions (dims, fcn);\n\n  // FIXME: Perhaps this should be made extensible by using the class name\n  //        to lookup a function to call to create the new value.\n\n  // Note that automatic narrowing will handle conversion from\n  // NDArray to scalar.\n\n  if (issparse)\n    {\n      if (dims.ndims () > 2)\n        error (\"%s: sparse N-D arrays not supported.\", fcn);\n\n      switch (dt)\n        {\n        case oct_data_conv::dt_double:\n          if (iscomplex)\n            retval = SparseComplexMatrix (dims(0), dims(1), Complex (val, 0));\n          else\n            retval = SparseMatrix (dims(0), dims(1), static_cast<double> (val));\n          break;\n\n        case oct_data_conv::dt_logical:\n          retval = SparseBoolMatrix (dims(0), dims(1), static_cast<bool> (val));\n          break;\n\n        default:\n          // FIXME: It shouldn't be possible to ever reach this.\n          error (\"%s: invalid class name for sparse\", fcn);\n        }\n\n      return retval;\n    }\n\n  switch (dt)\n    {\n    case oct_data_conv::dt_int8:\n      retval = int8NDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_uint8:\n      retval = uint8NDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_int16:\n      retval = int16NDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_uint16:\n      retval = uint16NDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_int32:\n      retval = int32NDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_uint32:\n      retval = uint32NDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_int64:\n      retval = int64NDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_uint64:\n      retval = uint64NDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_single:\n      if (iscomplex)\n        retval = FloatComplexNDArray (dims, val);\n      else\n        retval = FloatNDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_double:\n      if (iscomplex)\n        retval = ComplexNDArray (dims, Complex (val, 0));\n      else\n        retval = NDArray (dims, val);\n      break;\n\n    case oct_data_conv::dt_logical:\n      retval = boolNDArray (dims, val);\n      break;\n\n    default:\n      error (\"%s: invalid class name\", fcn);\n      break;\n    }\n\n  return retval;\n}\n\nstatic octave_value\nfill_matrix (const octave_value_list& args, double val, float fval,\n             const char *fcn)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  oct_data_conv::data_type dt = oct_data_conv::dt_double;\n\n  dim_vector dims (1, 1);\n  bool issparse = false;\n  bool iscomplex = false;\n\n  if (nargin > 0 && args(nargin-1).is_string ())\n    {\n      std::string nm = args(nargin-1).string_value ();\n      nargin--;\n\n      dt = oct_data_conv::string_to_data_type (nm);\n    }\n\n  if (nargin > 1 && args(nargin-2).is_string ()\n      && args(nargin-2).string_value () == \"like\"\n      && (std::string(fcn) ==  \"Inf\"\n          || std::string(fcn) == \"NaN\" || std::string(fcn) == \"NA\"))\n    {\n      if (! args(nargin-1).isfloat ())\n        error (\"%s: input followed by 'like' must be floating point\", fcn);\n      std::string nm = args(nargin-1).class_name ();\n      issparse = args(nargin-1).issparse ();\n      iscomplex = args(nargin-1).iscomplex ();\n      nargin -= 2;\n      dt = oct_data_conv::string_to_data_type (nm);\n    }\n\n  switch (nargin)\n    {\n    case 0:\n      break;\n\n    case 1:\n      get_dimensions (args(0), fcn, dims);\n      break;\n\n    default:\n      {\n        dims.resize (nargin);\n\n        for (int i = 0; i < nargin; i++)\n          {\n            if (args(i).numel () > 1)\n              error (\"%s: dimensions must be scalars.\", fcn);\n\n            dims(i) = (args(i).isempty () ? 0 : args(i).idx_type_value (true));\n          }\n      }\n      break;\n    }\n\n  dims.chop_trailing_singletons ();\n\n  check_dimensions (dims, fcn);\n\n  // Note that automatic narrowing will handle conversion from\n  // NDArray to scalar.\n\n  if (issparse)\n    {\n      if (dims.ndims () > 2)\n        error (\"%s: sparse N-D arrays not supported\", fcn);\n\n      if (iscomplex)\n        retval = SparseComplexMatrix (dims(0), dims(1), Complex (val, 0));\n      else\n        retval = SparseMatrix (dims(0), dims(1), static_cast<double> (val));\n\n      return retval;\n    }\n\n  switch (dt)\n    {\n    case oct_data_conv::dt_single:\n      if (iscomplex)\n        retval = FloatComplexNDArray (dims, fval);\n      else\n        retval = FloatNDArray (dims, fval);\n      break;\n\n    case oct_data_conv::dt_double:\n      if (iscomplex)\n        retval = ComplexNDArray (dims, Complex (val, 0));\n      else\n        retval = NDArray (dims, val);\n      break;\n\n    default:\n      error (\"%s: invalid class name\", fcn);\n      break;\n    }\n\n  return retval;\n}\n\nstatic octave_value\nfill_matrix (const octave_value_list& args, double val, const char *fcn)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  oct_data_conv::data_type dt = oct_data_conv::dt_double;\n\n  dim_vector dims (1, 1);\n\n  if (nargin > 0 && args(nargin-1).is_string ())\n    {\n      std::string nm = args(nargin-1).string_value ();\n      nargin--;\n\n      dt = oct_data_conv::string_to_data_type (nm);\n    }\n\n  switch (nargin)\n    {\n    case 0:\n      break;\n\n    case 1:\n      get_dimensions (args(0), fcn, dims);\n      break;\n\n    default:\n      {\n        dims.resize (nargin);\n\n        for (int i = 0; i < nargin; i++)\n          {\n            if (args(i).numel () > 1)\n              error (\"%s: dimensions must be scalars.\", fcn);\n\n            dims(i) = (args(i).isempty () ? 0 : args(i).idx_type_value (true));\n          }\n      }\n      break;\n    }\n\n  dims.chop_trailing_singletons ();\n\n  check_dimensions (dims, fcn);\n\n  // Note that automatic narrowing will handle conversion from\n  // NDArray to scalar.\n\n  switch (dt)\n    {\n    case oct_data_conv::dt_single:\n      retval = FloatNDArray (dims, static_cast<float> (val));\n      break;\n\n    case oct_data_conv::dt_double:\n      retval = NDArray (dims, val);\n      break;\n\n    default:\n      error (\"%s: invalid class name\", fcn);\n      break;\n    }\n\n  return retval;\n}\n\nstatic octave_value\nfill_matrix (const octave_value_list& args, const Complex& val,\n             const char *fcn)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  oct_data_conv::data_type dt = oct_data_conv::dt_double;\n\n  dim_vector dims (1, 1);\n\n  if (nargin > 0 && args(nargin-1).is_string ())\n    {\n      std::string nm = args(nargin-1).string_value ();\n      nargin--;\n\n      dt = oct_data_conv::string_to_data_type (nm);\n    }\n\n  switch (nargin)\n    {\n    case 0:\n      break;\n\n    case 1:\n      get_dimensions (args(0), fcn, dims);\n      break;\n\n    default:\n      {\n        dims.resize (nargin);\n\n        for (int i = 0; i < nargin; i++)\n          {\n            if (args(i).numel () > 1)\n              error (\"%s: dimensions must be scalars.\", fcn);\n\n            dims(i) = (args(i).isempty () ? 0 : args(i).idx_type_value (true));\n          }\n      }\n      break;\n    }\n\n  dims.chop_trailing_singletons ();\n\n  check_dimensions (dims, fcn);\n\n  // Note that automatic narrowing will handle conversion from\n  // NDArray to scalar.\n\n  switch (dt)\n    {\n    case oct_data_conv::dt_single:\n      retval = FloatComplexNDArray (dims,\n                                    static_cast<FloatComplex> (val));\n      break;\n\n    case oct_data_conv::dt_double:\n      retval = ComplexNDArray (dims, val);\n      break;\n\n    default:\n      error (\"%s: invalid class name\", fcn);\n      break;\n    }\n\n  return retval;\n}\n\nstatic octave_value\nfill_matrix (const octave_value_list& args, bool val, const char *fcn)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  dim_vector dims (1, 1);\n\n  // The TYPE argument is required to be \"logical\" if present.  This\n  // feature appears to be undocumented in Matlab.\n\n  if (nargin > 0 && args(nargin-1).is_string ())\n    {\n      std::string nm = args(nargin-1).string_value ();\n      nargin--;\n\n      if (oct_data_conv::string_to_data_type (nm) != oct_data_conv::dt_logical)\n        error (\"%s: invalid data type '%s'\", fcn, nm.c_str ());\n    }\n\n  bool issparse = false;\n\n  if (nargin > 1 && args(nargin-2).is_string ()\n      && args(nargin-2).string_value () == \"like\")\n    {\n      if (! args(nargin-1).islogical ())\n        error (R\"(%s: input followed by \"like\" must be logical)\", fcn);\n\n      issparse = args(nargin-1).issparse ();\n      nargin -= 2;\n    }\n\n  switch (nargin)\n    {\n    case 0:\n      break;\n\n    case 1:\n      get_dimensions (args(0), fcn, dims);\n      break;\n\n    default:\n      {\n        dims.resize (nargin);\n\n        for (int i = 0; i < nargin; i++)\n          {\n            if (args(i).numel () > 1)\n              error (\"%s: dimensions must be scalars.\", fcn);\n\n            dims(i) = (args(i).isempty () ? 0 : args(i).idx_type_value (true));\n          }\n      }\n      break;\n    }\n\n  dims.chop_trailing_singletons ();\n\n  check_dimensions (dims, fcn);\n\n  // Note that automatic narrowing will handle conversion from\n  // NDArray to scalar.\n\n  if (issparse)\n    {\n      if (dims.ndims () > 2)\n        error (\"%s: sparse N-D arrays not supported\", fcn);\n\n      retval = SparseBoolMatrix (dims(0), dims(1), val);\n    }\n  else\n    retval = boolNDArray (dims, val);\n\n  return retval;\n}\n\nDEFUN (ones, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} ones ()\n@deftypefnx {} {@var{x} =} ones (@var{n})\n@deftypefnx {} {@var{x} =} ones (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} ones ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} ones (@dots{}, @var{class})\n@deftypefnx {} {@var{x} =} ones (@dots{}, \"like\", @var{var})\nReturn a scalar, matrix, or N-dimensional array whose elements are all\n@code{1}.\n\nIf called with no arguments, return the scalar value @code{1}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array\nand defaults to @qcode{\"double\"}.\n\nIf a variable @var{var} is specified after @qcode{\"like\"}, the output @var{val}\nwill have the same data type, complexity, and sparsity as @var{var}.\n\nExample 1 : @nospell{MxN} matrix of constant value @var{val}\n\n@example\n@var{C} = @var{val} * ones (@var{m}, @var{n})\n@end example\n\nExample 2 : @nospell{MxN} matrix of uint8\n\n@example\n@var{C} = ones (@var{m}, @var{n}, \"uint8\")\n@end example\n\nProgramming Note: Any negative dimensions are treated as zero, and any zero\ndimensions will result in an empty matrix.  This odd behavior is for\n@sc{matlab} compatibility.\n@seealso{zeros, true, false}\n@end deftypefn */)\n{\n  return fill_matrix (args, 1, \"ones\");\n}\n\n/*\n%!assert (ones (), 1)\n%!assert (ones (3), [1, 1, 1; 1, 1, 1; 1, 1, 1])\n%!assert (ones (2, 3), [1, 1, 1; 1, 1, 1])\n%!assert (ones (3, 2), [1, 1; 1, 1; 1, 1])\n%!assert (size (ones (3, 4, 5)), [3, 4, 5])\n\n%!assert (ones (\"single\"), single (1))\n%!assert (ones (3, \"single\"), single ([1, 1, 1; 1, 1, 1; 1, 1, 1]))\n%!assert (ones (2, 3, \"single\"), single ([1, 1, 1; 1, 1, 1]))\n%!assert (ones (3, 2, \"single\"), single ([1, 1; 1, 1; 1, 1]))\n%!assert (size (ones (3, 4, 5, \"single\")), [3, 4, 5])\n\n%!assert (ones (\"int8\"), int8 (1))\n%!assert (ones (3, \"int8\"), int8 ([1, 1, 1; 1, 1, 1; 1, 1, 1]))\n%!assert (ones (2, 3, \"int8\"), int8 ([1, 1, 1; 1, 1, 1]))\n%!assert (ones (3, 2, \"int8\"), int8 ([1, 1; 1, 1; 1, 1]))\n%!assert (size (ones (3, 4, 5, \"int8\")), [3, 4, 5])\n\n%!assert (ones (2, 2, \"like\", double (1)), double ([1, 1; 1, 1]))\n%!assert (ones (2, 2, \"like\", complex (ones (2, 2))), [1, 1; 1, 1])\n%!assert (ones (1, 2, \"like\", single (1)), single ([1, 1]))\n%!assert (ones (1, \"like\", single (1i)), single (1))\n%!assert (ones (2, 2, \"like\", uint8 (8)), uint8 ([1, 1; 1, 1]))\n%!assert (ones (2, \"like\", speye (2)), sparse ([1, 1; 1, 1]))\n%!assert (ones (2, \"like\", sparse (1i)), sparse (complex ([1, 1; 1, 1])))\n\n## Note: Matlab compatibility requires using 0 for negative dimensions.\n%!assert (size (ones (1, -2, 2)), [1, 0, 2])\n\n## Test input validation\n%!error <invalid data type specified> ones (1, 1, \"foobar\")\n%!error <conversion of 1.1 .*failed> ones (1.1)\n%!error <conversion of 1.1 .*failed> ones (1, 1.1)\n%!error <conversion of 1.1 .*failed> ones ([1, 1.1])\n%!error <sparse N-D .* not supported> ones (3, 3, 3, \"like\", speye (1))\n%!error <must be scalar> ones (1:3, 1)\n%!error <must be scalar> ones (1, 1:3)\n%!error <must be scalar> ones (1, 2, 1:3)\n%!error <must be scalar> ones (1:3, 1, \"like\", single (1))\n*/\n\n/*\n## Tests for bug #47298\n## Matlab requires the size to be a row vector.  In that logic, it supports\n## n to be a 1x0 vector (returns 0x0) but not a 0x1 vector.  Octave supports\n## row and column vectors and therefore must support 0x1, 1x0, and 0x1x1.\n## Also any empty input results in a 0x0 output.\n%!test <*47298>\n%! fcns = {@zeros, @ones, @inf, @nan, @NA, @i, @pi, @e};\n%! for idx = 1:numel (fcns)\n%!   fcn = fcns{idx};\n%!   assert (fcn (zeros (1, 0)), zeros (0, 0));\n%!   assert (fcn (zeros (0, 1)), zeros (0, 0));\n%!   assert (fcn (zeros (0, 1, 1)), zeros (0, 0));\n%!   assert (fcn (zeros ([])), zeros (0, 0));\n%!   assert (fcn (zeros (0, 0, 1)), zeros (0, 0));\n%! endfor\n*/\n\nDEFUN (zeros, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} zeros ()\n@deftypefnx {} {@var{x} =} zeros (@var{n})\n@deftypefnx {} {@var{x} =} zeros (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} zeros ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} zeros (@dots{}, @var{class})\n@deftypefnx {} {@var{x} =} zeros (@dots{}, \"like\", @var{var})\nReturn a scalar, matrix, or N-dimensional array whose elements are all\n@code{0}.\n\nIf called with no arguments, return the scalar value @code{0}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array\nand defaults to @qcode{\"double\"}.\n\nIf a variable @var{var} is specified after @qcode{\"like\"}, the output @var{val}\nwill have the same data type, complexity, and sparsity as @var{var}.\n\nExample : @nospell{MxN} matrix of uint8\n\n@example\n@var{C} = ones (@var{m}, @var{n}, \"uint8\")\n@end example\n\nProgramming Note: Any negative dimensions are treated as zero, and any zero\ndimensions will result in an empty matrix.  This odd behavior is for\n@sc{matlab} compatibility.\n@seealso{ones, true, false}\n@end deftypefn */)\n{\n  return fill_matrix (args, 0, \"zeros\");\n}\n\n/*\n%!assert (zeros (), 0)\n%!assert (zeros (3), [0, 0, 0; 0, 0, 0; 0, 0, 0])\n%!assert (zeros (2, 3), [0, 0, 0; 0, 0, 0])\n%!assert (zeros (3, 2), [0, 0; 0, 0; 0, 0])\n%!assert (size (zeros (3, 4, 5)), [3, 4, 5])\n\n%!assert (zeros (\"single\"), single (0))\n%!assert (zeros (3, \"single\"), single ([0, 0, 0; 0, 0, 0; 0, 0, 0]))\n%!assert (zeros (2, 3, \"single\"), single ([0, 0, 0; 0, 0, 0]))\n%!assert (zeros (3, 2, \"single\"), single ([0, 0; 0, 0; 0, 0]))\n%!assert (size (zeros (3, 4, 5, \"single\")), [3, 4, 5])\n\n%!assert (zeros (\"int8\"), int8 (0))\n%!assert (zeros (3, \"int8\"), int8 ([0, 0, 0; 0, 0, 0; 0, 0, 0]))\n%!assert (zeros (2, 3, \"int8\"), int8 ([0, 0, 0; 0, 0, 0]))\n%!assert (zeros (3, 2, \"int8\"), int8 ([0, 0; 0, 0; 0, 0]))\n%!assert (size (zeros (3, 4, 5, \"int8\")), [3, 4, 5])\n\n%!assert (zeros (2, 2, \"like\", double (1)), double ([0, 0; 0, 0]))\n%!assert (zeros (2, 2, \"like\", complex (ones (2, 2))), [0, 0; 0, 0])\n%!assert (zeros (1, 2, \"like\", single (1)), single ([0, 0]))\n%!assert (zeros (1, 2, \"like\", single (1i)), single ([0, 0]))\n%!assert (zeros (2, 2, \"like\", uint8 (8)), uint8 ([0, 0; 0, 0]))\n%!assert (zeros (2, \"like\", speye (2)), sparse ([0, 0; 0, 0]))\n\n## Test input validation\n%!error <invalid data type specified> zeros (1, 1, \"foobar\")\n%!error <conversion of 1.1 .*failed> zeros (1.1)\n%!error <conversion of 1.1 .*failed> zeros (1, 1.1)\n%!error <conversion of 1.1 .*failed> zeros ([1, 1.1])\n%!error <sparse N-D .* not supported> zeros (3, 3, 3, \"like\", speye (1))\n%!error <must be scalar> zeros (1:3, 1)\n%!error <must be scalar> zeros (1, 1:3)\n%!error <must be scalar> zeros (1, 2, 1:3)\n%!error <must be scalar> zeros (1:3, 1, \"like\", single (1))\n*/\n\nDEFUN (Inf, args, ,\n       doc: /* -*- texinfo -*-\n@c List other form of function in documentation index\n@findex inf\n\n@deftypefn  {} {@var{x} =} Inf\n@deftypefnx {} {@var{x} =} Inf (@var{n})\n@deftypefnx {} {@var{x} =} Inf (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} Inf ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} Inf (@dots{}, @var{class})\n@deftypefnx {} {@var{x} =} Inf (@dots{}, \"like\", @var{var})\nReturn a scalar, matrix or N-dimensional array whose elements are all equal\nto the IEEE@tie{}754 representation for positive infinity.\n\nInfinity is produced when results are too large to be represented using the\nIEEE@tie{}754 floating point format for numbers.  Two common examples which\nproduce infinity are division by zero and overflow.\n\n@example\n@group\n[ 1/0 e^800 ]\n@xresult{} Inf   Inf\n@end group\n@end example\n\nIf called with no arguments, return the scalar value @code{Inf}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nIf a variable @var{var} is specified after @qcode{\"like\"}, the output @var{x}\nwill have the same data type, complexity, and sparsity as @var{var}.\n@seealso{isinf, NaN}\n@end deftypefn */)\n{\n  return fill_matrix (args, lo_ieee_inf_value (),\n                      lo_ieee_float_inf_value (), \"Inf\");\n}\n\nDEFALIAS (inf, Inf);\n\n/*\n%!assert (Inf (3), [Inf, Inf, Inf; Inf, Inf, Inf; Inf, Inf, Inf])\n%!assert (Inf (2, 3), [Inf, Inf, Inf; Inf, Inf, Inf])\n%!assert (Inf (3, 2), [Inf, Inf; Inf, Inf; Inf, Inf])\n%!assert (size (Inf (3, 4, 5)), [3, 4, 5])\n\n%!assert (Inf (3, \"single\"),\n%!        single ([Inf, Inf, Inf; Inf, Inf, Inf; Inf, Inf, Inf]))\n%!assert (Inf (2, 3, \"single\"), single ([Inf, Inf, Inf; Inf, Inf, Inf]))\n%!assert (Inf (3, 2, \"single\"), single ([Inf, Inf; Inf, Inf; Inf, Inf]))\n%!assert (size (inf (3, 4, 5, \"single\")), [3, 4, 5])\n\n## Note: Matlab compatibility requires using 0 for negative dimensions.\n%!assert (size (Inf (2, -3, 2)), [2, 0, 2])\n\n%!assert (Inf (2, 2, \"like\", speye (2)), sparse ([Inf, Inf; Inf, Inf]))\n%!assert (Inf (2, 2, \"like\", complex (ones (2, 2))), [Inf, Inf; Inf, Inf])\n%!assert (Inf (2, 2, \"like\", double (1)), double ([Inf, Inf; Inf, Inf]))\n%!assert (Inf (3, 3, \"like\", single (1)),\n%!        single ([Inf, Inf, Inf; Inf, Inf, Inf; Inf, Inf, Inf]))\n%!assert (Inf (2, \"like\", single (1i)), single ([Inf, Inf; Inf, Inf]))\n\n%!error Inf (3, \"like\", int8 (1))\n\n%!error Inf (3, \"int8\")\n%!error Inf (2, 3, \"int8\")\n%!error Inf (3, 2, \"int8\")\n%!error Inf (3, 4, 5, \"int8\")\n%!error <input .* floating> Inf (3, 3, \"like\", true)\n%!error <input .* floating> Inf (2, \"like\", uint8 (1))\n%!error <must be scalar> Inf (1:3, 1)\n%!error <must be scalar> Inf (1, 1:3)\n%!error <must be scalar> Inf (1, 2, 1:3)\n%!error <must be scalar> Inf (1:3, 1, \"like\", single (1))\n*/\n\nDEFUN (NaN, args, ,\n       doc: /* -*- texinfo -*-\n@c List other form of function in documentation index\n@findex nan\n\n@deftypefn  {} {@var{x} =} NaN\n@deftypefnx {} {@var{x} =} NaN (@var{n})\n@deftypefnx {} {@var{x} =} NaN (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} NaN ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} NaN (@dots{}, @var{class})\n@deftypefnx {} {@var{x} =} NaN (@dots{}, \"like\", @var{var})\nReturn a scalar, matrix, or N-dimensional array whose elements are all equal\nto the IEEE@tie{}754 symbol NaN (Not a Number).\n\n@code{NaN} is the result of operations which do not produce a well defined\nnumerical result.  Common operations which produce a @code{NaN} are arithmetic\nwith infinity\n@tex\n($\\infty - \\infty$), zero divided by zero ($0/0$),\n@end tex\n@ifnottex\n(Inf - Inf), zero divided by zero (0/0),\n@end ifnottex\nand any operation involving another @code{NaN} value (5 + @code{NaN}).\n\nNote that @code{NaN} always compares not equal to @code{NaN}\n(@code{NaN != NaN}).  This behavior is specified by the IEEE@tie{}754 standard\nfor floating point arithmetic.  To find @code{NaN} values, use the @code{isnan}\nfunction.\n\nIf called with no arguments, return the scalar value @code{NaN}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nIf a variable @var{var} is specified after @qcode{\"like\"}, the output @var{x}\nwill have the same data type, complexity, and sparsity as @var{var}.\n@seealso{isnan, Inf}\n@end deftypefn */)\n{\n  return fill_matrix (args, lo_ieee_nan_value (),\n                      lo_ieee_float_nan_value (), \"NaN\");\n}\n\nDEFALIAS (nan, NaN);\n\n/*\n%!assert (NaN (3), [NaN, NaN, NaN; NaN, NaN, NaN; NaN, NaN, NaN])\n%!assert (NaN (2, 3), [NaN, NaN, NaN; NaN, NaN, NaN])\n%!assert (NaN (3, 2), [NaN, NaN; NaN, NaN; NaN, NaN])\n%!assert (size (NaN (3, 4, 5)), [3, 4, 5])\n\n%!assert (NaN (3, \"single\"),\n%!        single ([NaN, NaN, NaN; NaN, NaN, NaN; NaN, NaN, NaN]))\n%!assert (NaN (2, 3, \"single\"), single ([NaN, NaN, NaN; NaN, NaN, NaN]))\n%!assert (NaN (3, 2, \"single\"), single ([NaN, NaN; NaN, NaN; NaN, NaN]))\n%!assert (size (NaN (3, 4, 5, \"single\")), [3, 4, 5])\n\n%!assert (NaN (2, 2, \"like\", double (1)), double ([NaN, NaN; NaN, NaN]))\n%!assert (NaN (2, 2, \"like\", complex (ones(2, 2))), [NaN, NaN; NaN, NaN])\n%!assert (NaN (3, 3, \"like\", single (1)),\n%!        single ([NaN, NaN, NaN; NaN, NaN, NaN; NaN, NaN, NaN]))\n%!assert (NaN (2, \"like\", single (1i)), single ([NaN, NaN; NaN, NaN]))\n%!assert (NaN (2, 2, \"like\", speye (2)), sparse ([NaN, NaN; NaN, NaN]))\n\n%!error NaN (3, 'like', int8 (1))\n\n%!error NaN (3, \"int8\")\n%!error NaN (2, 3, \"int8\")\n%!error NaN (3, 2, \"int8\")\n%!error NaN (3, 4, 5, \"int8\")\n%!error <input .* floating> NaN (3, 3, \"like\", true)\n%!error <input .* floating> NaN (2, \"like\", uint8 (1))\n%!error <must be scalar> NaN (1:3, 1)\n%!error <must be scalar> NaN (1, 1:3)\n%!error <must be scalar> NaN (1, 2, 1:3)\n%!error <must be scalar> NaN (1:3, 1, \"like\", single (1))\n*/\n\nDEFUN (e, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} e\n@deftypefnx {} {@var{x} =} e (@var{n})\n@deftypefnx {} {@var{x} =} e (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} e ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} e (@dots{}, @var{class})\nReturn a scalar, matrix, or N-dimensional array whose elements are all equal\nto the base of natural logarithms.\n\nThe constant\n@tex\n$e$ satisfies the equation $\\log (e) = 1$.\n@end tex\n@ifnottex\n@samp{e} satisfies the equation @code{log} (e) = 1.\n@end ifnottex\n\nIf called with no arguments, return the scalar value @math{e}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n@seealso{log, exp, pi, I}\n@end deftypefn */)\n{\n#if defined (M_E)\n  constexpr double e_val = M_E;\n#else\n  constexpr double e_val = exp (1.0);\n#endif\n\n  return fill_matrix (args, e_val, \"e\");\n}\n\ntemplate <typename T>\nT\neps (const T& x)\n{\n  T epsval = x.abs ();\n  typedef typename T::value_type P;\n  for (octave_idx_type i = 0; i < x.numel (); i++)\n    {\n      P val = epsval.xelem (i);\n      if (math::isnan (val) || math::isinf (val))\n        epsval(i) = numeric_limits<P>::NaN ();\n      else if (val < std::numeric_limits<P>::min ())\n        epsval(i) = std::numeric_limits<P>::denorm_min ();\n      else\n        {\n          int exponent;\n          math::frexp (val, &exponent);\n          const P digits = std::numeric_limits<P>::digits;\n          epsval(i) = std::pow (static_cast<P> (2.0),\n                                static_cast<P> (exponent - digits));\n        }\n    }\n  return epsval;\n}\n\nDEFUN (eps, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{d} =} eps\n@deftypefnx {} {@var{d} =} eps (@var{x})\n@deftypefnx {} {@var{d} =} eps (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{d} =} eps ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{d} =} eps (@dots{}, @var{class})\nReturn a scalar, matrix or N-dimensional array whose elements are eps,\nthe machine precision.\n\nMore precisely, @code{eps} is the relative spacing between any two adjacent\nnumbers in the machine's floating point system.  This number depends both on\nthe system and where the number lies in the range representable by the floating\npoint system.  On machines that support IEEE@tie{}754 floating point\narithmetic, @w{@code{eps (1.0)}} is approximately\n@tex\n$2.2204\\times10^{-16}$ for double precision and $1.1921\\times10^{-7}$\n@end tex\n@ifnottex\n2.2204e-16 for double precision and 1.1921e-07\n@end ifnottex\nfor single precision.\n\nIf called with no arguments, return the scalar value @w{@code{eps (1.0)}}.\n\nGiven a floating point argument @var{x}, return an array @var{d} of the same\nsize where each element is the distance between the element of @var{x} and\nthe next largest value.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions whose elements are all the\nscalar value @code{eps}.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n@seealso{realmax, realmin, intmax, flintmax}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  if (args.length () == 1 && ! args(0).is_string ())\n    {\n      octave_value arg0 = args(0);\n      if (arg0.is_single_type ())\n        {\n          FloatNDArray epsval = eps (arg0.float_array_value ());\n          retval = epsval;\n        }\n      else if (arg0.is_double_type ())\n        {\n          NDArray epsval = eps (arg0.array_value ());\n          retval = epsval;\n        }\n      else\n        error (\"eps: X must be of a floating point type\");\n    }\n  else\n    retval = fill_matrix (args, std::numeric_limits<double>::epsilon (),\n                          std::numeric_limits<float>::epsilon (), \"eps\");\n\n  return retval;\n}\n\n/*\n%!assert (eps (1/2), 2^(-53))\n%!assert (eps (1), 2^(-52))\n%!assert (eps (2), 2^(-51))\n%!assert (eps (realmax), 2^971)\n%!assert (eps (0), 2^(-1074))\n%!assert (eps (realmin/2), 2^(-1074))\n%!assert (eps (realmin/16), 2^(-1074))\n%!assert (eps (Inf), NaN)\n%!assert (eps (NaN), NaN)\n%!assert (eps ([1/2 1 2 realmax 0 realmin/2 realmin/16 Inf NaN]),\n%!        [2^-53 2^-52 2^-51 2^971 2^-1074 2^-1074 2^-1074 NaN NaN])\n%!assert (eps (single (1/2)), single (2^(-24)))\n%!assert (eps (single (1)), single (2^(-23)))\n%!assert (eps (single (2)), single (2^(-22)))\n%!assert (eps (realmax (\"single\")), single (2^104))\n%!assert (eps (single (0)), single (2^(-149)))\n%!assert (eps (realmin (\"single\")/2), single (2^(-149)))\n%!assert (eps (realmin (\"single\")/16), single (2^(-149)))\n%!assert (eps (single (Inf)), single (NaN))\n%!assert (eps (single (NaN)), single (NaN))\n%!assert (eps (single ([1/2 1 2 realmax(\"single\") 0 realmin(\"single\")/2 realmin(\"single\")/16 Inf NaN])),\n%!        single ([2^-24 2^-23 2^-22 2^104 2^-149 2^-149 2^-149 NaN NaN]))\n\n## Note: Matlab compatibility requires using 0 for negative dimensions.\n%!assert (size (eps (2, -3, 2)), [2, 0, 2])\n\n%!error <X must be of a floating point type> eps (uint8 ([0 1 2]))\n%!error <must be scalar> eps (1:3, 1)\n%!error <must be scalar> eps (1, 1:3)\n%!error <must be scalar> eps (1, 2, 1:3)\n%!error <must be scalar> eps (1:3, 1, \"single\")\n*/\n\nDEFUN (pi, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{p} =} pi\n@deftypefnx {} {@var{p} =} pi (@var{n})\n@deftypefnx {} {@var{p} =} pi (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{p} =} pi ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{p} =} pi (@dots{}, @var{class})\nReturn a scalar, matrix, or N-dimensional array whose elements are all equal\nto the ratio of the circumference of a circle to its\n@tex\ndiameter($\\pi$).\n@end tex\n@ifnottex\ndiameter.\n@end ifnottex\n\nIf called with no arguments, return the scalar value\n@tex\n$\\pi$.\n@end tex\n@ifnottex\npi.\n@end ifnottex\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n@seealso{e, I}\n@end deftypefn */)\n{\n#if defined (M_PI)\n  constexpr double pi_val = M_PI;\n#else\n  constexpr double pi_val = 4.0 * atan (1.0);\n#endif\n\n  return fill_matrix (args, pi_val, \"pi\");\n}\n\nDEFUN (realmax, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{Rmax} =} realmax\n@deftypefnx {} {@var{Rmax} =} realmax (@var{n})\n@deftypefnx {} {@var{Rmax} =} realmax (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{Rmax} =} realmax ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{Rmax} =} realmax (@dots{}, @var{class})\n@deftypefnx {} {@var{Rmax} =} realmax (@dots{}, \"like\", @var{var})\nReturn a scalar, matrix, or N-dimensional array whose elements are all equal\nto the largest floating point number that is representable.\n\nThe actual value is system-dependent.  On machines that support IEEE@tie{}754\nfloating point arithmetic, @code{realmax} is approximately\n@tex\n$1.7977\\times10^{308}$ for double precision and $3.4028\\times10^{38}$\n@end tex\n@ifnottex\n1.7977e+308 for double precision and 3.4028e+38\n@end ifnottex\nfor single precision.\n\nIf called with no arguments, return the scalar value\n@code{realmax (@qcode{\"double\"})}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nIf a variable @var{var} is specified after @qcode{\"like\"}, the output\n@var{Rmax} will have the same data type, complexity, and sparsity as @var{var}.\n@seealso{realmin, intmax, flintmax, eps}\n@end deftypefn */)\n{\n  return fill_matrix (args, std::numeric_limits<double>::max (),\n                      std::numeric_limits<float>::max (), \"realmax\");\n}\n\nDEFUN (realmin, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{Rmin} =} realmin\n@deftypefnx {} {@var{Rmin} =} realmin (@var{n})\n@deftypefnx {} {@var{Rmin} =} realmin (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{Rmin} =} realmin ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{Rmin} =} realmin (@dots{}, @var{class})\n@deftypefnx {} {@var{Rmin} =} realmin (@dots{}, \"like\", @var{var})\nReturn a scalar, matrix, or N-dimensional array whose elements are all equal\nto the smallest normalized floating point number that is representable.\n\nThe actual value is system-dependent.  On machines that support IEEE@tie{}754\nfloating point arithmetic, @code{realmin} is approximately\n@tex\n$2.2251\\times10^{-308}$ for double precision and $1.1755\\times10^{-38}$\n@end tex\n@ifnottex\n2.2251e-308 for double precision and 1.1755e-38\n@end ifnottex\nfor single precision.\n\nIf called with no arguments, return the scalar value\n@code{realmin (@qcode{\"double\"})}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nIf a variable @var{var} is specified after @qcode{\"like\"}, the output\n@var{Rmin} will have the same data type, complexity, and sparsity as @var{var}.\n@seealso{realmax, intmin, eps}\n@end deftypefn */)\n{\n  return fill_matrix (args, std::numeric_limits<double>::min (),\n                      std::numeric_limits<float>::min (), \"realmin\");\n}\n\nDEFUN (I, args, ,\n       doc: /* -*- texinfo -*-\n@c List other forms of function in documentation index\n@findex i\n@findex j\n@findex J\n\n@deftypefn  {} {@var{x} =} I\n@deftypefnx {} {@var{x} =} I (@var{n})\n@deftypefnx {} {@var{x} =} I (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} I ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} I (@dots{}, @var{class})\nReturn a scalar, matrix, or N-dimensional array whose elements are all equal\nto the pure imaginary unit, defined as\n@tex\n$\\sqrt{-1}$.\n@end tex\n@ifnottex\n@w{@code{sqrt (-1)}}.\n@end ifnottex\n\n@code{I}, and its equivalents @code{i}, @code{j}, and @code{J}, are functions\nso any of the names may be reused for other purposes (such as @code{i} for a\ncounter variable).\n\nIf called with no arguments, return the scalar value @code{complex (0, 1)}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n@seealso{e, pi, log, exp}\n@end deftypefn */)\n{\n  return fill_matrix (args, Complex (0.0, 1.0), \"I\");\n}\n\nDEFALIAS (i, I);\nDEFALIAS (J, I);\nDEFALIAS (j, I);\n\nDEFUN (NA, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} NA\n@deftypefnx {} {@var{x} =} NA (@var{n})\n@deftypefnx {} {@var{x} =} NA (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} NA ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} NA (@dots{}, @var{class})\n@deftypefnx {} {@var{x} =} NA (@dots{}, \"like\", @var{var})\nReturn a scalar, matrix, or N-dimensional array whose elements are all equal\nto the special constant NA (Not Available) used to designate missing values.\n\nNote that @code{NA} always compares not equal to @code{NA} (@code{NA != NA}).\nTo find @code{NA} values, use the @code{isna} function.\n\nIf called with no arguments, return the scalar value @code{NA}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nProgramming Note: The missing data marker @code{NA} is a special case of the\nrepresentation of @code{NaN}.  Numerical calculations with @code{NA} will\ngenerally \"poison\" the results and conclude with an output of @code{NA}.\nHowever, this can not be guaranteed on all platforms and @code{NA} may be\nreplaced by @code{NaN}.  @xref{Missing Data}.\n@seealso{isna}\n@end deftypefn */)\n{\n  return fill_matrix (args, lo_ieee_na_value (),\n                      lo_ieee_float_na_value (), \"NA\");\n}\n\n/*\n%!testif HAVE_QNAN_WITH_PAYLOAD\n%! assert (single (NA (\"double\")), NA (\"single\"));\n%!testif HAVE_QNAN_WITH_PAYLOAD\n%! assert (double (NA (\"single\")), NA (\"double\"));\n// Duplicate from above.  Only for test statistics\n%!testif ; ! __have_feature__ (\"QNAN_WITH_PAYLOAD\") <59830>\n%! assert (single (NA (\"double\")), NA (\"single\"));\n%!testif ; ! __have_feature__ (\"QNAN_WITH_PAYLOAD\") <59830>\n%! assert (double (NA (\"single\")), NA (\"double\"));\n*/\n\nDEFUN (false, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{F} =} false\n@deftypefnx {} {@var{F} =} false (@var{n})\n@deftypefnx {} {@var{F} =} false (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{F} =} false ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{F} =} false (@dots{}, \"like\", @var{var})\nReturn a scalar, matrix, or N-dimensional array whose elements are all logical\n@code{0}.\n\nIf called with no arguments, return the scalar value logical @code{0}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nIf a logical variable @var{var} is specified after @qcode{\"like\"}, the output\n@var{F} will have the same sparsity as @var{var}.\n\nProgramming Note: The code @code{false (@dots{})} is faster (30X) and more\nmemory efficient than @code{logical (zeros (@dots{}))}.\n\nAny negative dimensions are treated as zero, and any zero dimensions will\nresult in an empty matrix.  This odd behavior is for @sc{matlab} compatibility.\n@seealso{true, logical, ones, zeros}\n@end deftypefn */)\n{\n  return fill_matrix (args, false, \"false\");\n}\n\n/*\n%!assert (false, logical (0))\n%!assert (false (3), logical ([0, 0, 0; 0, 0, 0; 0, 0, 0]))\n%!assert (false (2, 3), logical ([0, 0, 0; 0, 0, 0]))\n%!assert (false (3, 2), logical ([0, 0; 0, 0; 0, 0]))\n%!assert (size (false (3, 4, 5)), [3, 4, 5])\n%!assert (false (2, 3, \"logical\"), logical (zeros (2, 3)))\n%!assert (false (2, 1, \"like\", true), [false; false])\n%!assert (false (2, 1, \"like\", sparse (true)), sparse ([false; false]))\n\n## Test input validation\n%!error false (2, 3, \"double\")\n%!error <input .* must be logical> false (2, 1, \"like\", double (1))\n%!error <must be scalar> false (1:3, 1)\n%!error <must be scalar> false (1, 1:3)\n%!error <must be scalar> false (1, 2, 1:3)\n*/\n\nDEFUN (true, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{T} =} true\n@deftypefnx {} {@var{T} =} true (@var{n})\n@deftypefnx {} {@var{T} =} true (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{T} =} true ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{T} =} true (@dots{}, \"like\", @var{var})\nReturn a scalar, matrix, or N-dimensional array whose elements are all logical\n@code{1}.\n\nIf called with no arguments, return the scalar value logical @code{1}.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nIf a logical variable @var{var} is specified after @qcode{\"like\"}, the output\n@var{T} will have the same sparsity as @var{var}.\n\nProgramming Notes: The code @code{true (@dots{})} is faster (30X) and more\nmemory efficient than @code{logical (ones (@dots{}))}.\n\nAny negative dimensions are treated as zero, and any zero dimensions will\nresult in an empty matrix.  This odd behavior is for @sc{matlab} compatibility.\n@seealso{false, logical, ones, zeros}\n@end deftypefn */)\n{\n  return fill_matrix (args, true, \"true\");\n}\n\n/*\n\n%!assert (true, logical (1))\n%!assert (true (3), logical ([1, 1, 1; 1, 1, 1; 1, 1, 1]))\n%!assert (true (2, 3), logical ([1, 1, 1; 1, 1, 1]))\n%!assert (true (3, 2), logical ([1, 1; 1, 1; 1, 1]))\n%!assert (size (true (3, 4, 5)), [3, 4, 5])\n%!assert (true (2, 3, \"logical\"), logical (ones (2, 3)))\n%!assert (true (2, 1, \"like\", false), [true; true])\n%!assert (true (2, 1, \"like\", sparse (true)), sparse ([true; true]))\n\n## Test input validation\n%!error true (2, 3, \"double\")\n%!error <input .* must be logical> true (2, 1, \"like\", double (1))\n%!error <must be scalar> true (1:3, 1)\n%!error <must be scalar> true (1, 1:3)\n%!error <must be scalar> true (1, 2, 1:3)\n*/\n\ntemplate <typename MT>\noctave_value\nidentity_matrix (int nr, int nc)\n{\n  octave_value retval;\n\n  typename MT::element_type one (1);\n\n  if (nr == 1 && nc == 1)\n    retval = one;\n  else\n    {\n      dim_vector dims (nr, nc);\n\n      typename MT::element_type zero (0);\n\n      MT m (dims, zero);\n\n      if (nr > 0 && nc > 0)\n        {\n          int n = std::min (nr, nc);\n\n          for (int i = 0; i < n; i++)\n            m(i, i) = one;\n        }\n\n      retval = m;\n    }\n\n  return retval;\n}\n\n#define INSTANTIATE_EYE(T)                              \\\n  template octave_value identity_matrix<T> (int, int)\n\nINSTANTIATE_EYE (int8NDArray);\nINSTANTIATE_EYE (uint8NDArray);\nINSTANTIATE_EYE (int16NDArray);\nINSTANTIATE_EYE (uint16NDArray);\nINSTANTIATE_EYE (int32NDArray);\nINSTANTIATE_EYE (uint32NDArray);\nINSTANTIATE_EYE (int64NDArray);\nINSTANTIATE_EYE (uint64NDArray);\nINSTANTIATE_EYE (FloatNDArray);\nINSTANTIATE_EYE (NDArray);\nINSTANTIATE_EYE (boolNDArray);\n\nstatic octave_value\nidentity_matrix (int nr, int nc, oct_data_conv::data_type dt)\n{\n  octave_value retval;\n\n  // FIXME: Perhaps this should be made extensible by using the class name\n  //        to lookup a function to call to create the new value.\n\n  switch (dt)\n    {\n    case oct_data_conv::dt_int8:\n      retval = identity_matrix<int8NDArray> (nr, nc);\n      break;\n\n    case oct_data_conv::dt_uint8:\n      retval = identity_matrix<uint8NDArray> (nr, nc);\n      break;\n\n    case oct_data_conv::dt_int16:\n      retval = identity_matrix<int16NDArray> (nr, nc);\n      break;\n\n    case oct_data_conv::dt_uint16:\n      retval = identity_matrix<uint16NDArray> (nr, nc);\n      break;\n\n    case oct_data_conv::dt_int32:\n      retval = identity_matrix<int32NDArray> (nr, nc);\n      break;\n\n    case oct_data_conv::dt_uint32:\n      retval = identity_matrix<uint32NDArray> (nr, nc);\n      break;\n\n    case oct_data_conv::dt_int64:\n      retval = identity_matrix<int64NDArray> (nr, nc);\n      break;\n\n    case oct_data_conv::dt_uint64:\n      retval = identity_matrix<uint64NDArray> (nr, nc);\n      break;\n\n    case oct_data_conv::dt_single:\n      retval = FloatDiagMatrix (nr, nc, 1.0f);\n      break;\n\n    case oct_data_conv::dt_double:\n      retval = DiagMatrix (nr, nc, 1.0);\n      break;\n\n    case oct_data_conv::dt_logical:\n      retval = identity_matrix<boolNDArray> (nr, nc);\n      break;\n\n    default:\n      error (\"eye: invalid class name\");\n      break;\n    }\n\n  return retval;\n}\n\n#undef INT_EYE_MATRIX\n\nDEFUN (eye, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{I} =} eye ()\n@deftypefnx {} {@var{I} =} eye (@var{n})\n@deftypefnx {} {@var{I} =} eye (@var{m}, @var{n})\n@deftypefnx {} {@var{I} =} eye ([@var{m}, @var{n}])\n@deftypefnx {} {@var{I} =} eye (@dots{}, @var{class})\nReturn an identity matrix.\n\nIf called with no arguments, return the scalar value @code{1}.\n\nIf invoked with a single scalar argument @var{n}, return a square @nospell{NxN}\nidentity matrix.\n\nIf supplied two scalar arguments (@var{m}, @var{n}), or a 2-element vector\n@w{@code{[@var{m}, @var{n}]}}, return an @nospell{MxN} identity matrix with\n@var{m} rows and @var{n} columns.\n\nThe optional argument @var{class} specifies the return type of the matrix and\ndefaults to @qcode{\"double\"}.\n\nExample 1 : 1-input, square identity matrix\n\n@example\n@group\neye (3)\n @xresult{}  1  0  0\n     0  1  0\n     0  0  1\n@end group\n@end example\n\nExample 2 : following expressions all produce 2x2 identity matrix\n\n@example\n@group\neye (2) @equiv{} eye (2, 2) @equiv{} eye (size ([1, 2; 3, 4]))\n @xresult{}  1  0\n     0  1\n@end group\n@end example\n\nExample 3 : 2x2 uint8 identity matrix\n\n@example\nI = eye (2, \"uint8\")\n@end example\n\nProgramming Note: Calling @code{eye} with no arguments is equivalent to calling\nit with an argument of @code{1}.  Any negative dimensions are treated as zero.\nThese odd definitions are for compatibility with @sc{matlab}.\n@seealso{speye, ones, zeros}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  oct_data_conv::data_type dt = oct_data_conv::dt_double;\n\n  // Check for type information.\n\n  if (nargin > 0 && args(nargin-1).is_string ())\n    {\n      std::string nm = args(nargin-1).string_value ();\n      nargin--;\n\n      dt = oct_data_conv::string_to_data_type (nm);\n    }\n\n  if (nargin > 2)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 0)\n    retval = identity_matrix (1, 1, dt);\n  else if (nargin == 1)\n    {\n      octave_idx_type nr, nc;\n      get_dimensions (args(0), \"eye\", nr, nc);\n\n      retval = identity_matrix (nr, nc, dt);\n    }\n  else\n    {\n      octave_idx_type nr, nc;\n      get_dimensions (args(0), args(1), \"eye\", nr, nc);\n\n      retval = identity_matrix (nr, nc, dt);\n    }\n\n  return retval;\n}\n\n/*\n%!assert (full (eye (3)), [1, 0, 0; 0, 1, 0; 0, 0, 1])\n%!assert (full (eye (2, 3)), [1, 0, 0; 0, 1, 0])\n\n%!assert (full (eye (3, \"single\")), single ([1, 0, 0; 0, 1, 0; 0, 0, 1]))\n%!assert (full (eye (2, 3, \"single\")), single ([1, 0, 0; 0, 1, 0]))\n\n%!assert (eye (3, \"int8\"), int8 ([1, 0, 0; 0, 1, 0; 0, 0, 1]))\n%!assert (eye (2, 3, \"int8\"), int8 ([1, 0, 0; 0, 1, 0]))\n\n## Note: Matlab compatibility requires using 0 for negative dimensions.\n%!assert (size (eye (2, -3)), [2, 0])\n\n## Test input validation\n%!error eye (1, 2, 3)\n%!error <conversion of 1.1 .*failed> eye (1.1)\n%!error <conversion of 1.1 .*failed> eye (1, 1.1)\n%!error <conversion of 1.1 .*failed> eye ([1, 1.1])\n*/\n\ntemplate <typename MT>\nstatic octave_value\ndo_linspace (const octave_value& base, const octave_value& limit,\n             octave_idx_type n)\n{\n  typedef typename MT::column_vector_type CVT;\n  typedef typename MT::element_type T;\n\n  octave_value retval;\n\n  if (base.is_scalar_type ())\n    {\n      T bs = octave_value_extract<T> (base);\n      if (limit.is_scalar_type ())\n        {\n          T ls = octave_value_extract<T> (limit);\n          retval = linspace (bs, ls, n);\n        }\n      else\n        {\n          CVT lv = octave_value_extract<CVT> (limit);\n          CVT bv (lv.numel (), bs);\n          retval = linspace (bv, lv, n);\n        }\n    }\n  else\n    {\n      CVT bv = octave_value_extract<CVT> (base);\n      if (limit.is_scalar_type ())\n        {\n          T ls = octave_value_extract<T> (limit);\n          CVT lv (bv.numel (), ls);\n          retval = linspace (bv, lv, n);\n        }\n      else\n        {\n          CVT lv = octave_value_extract<CVT> (limit);\n          retval = linspace (bv, lv, n);\n        }\n    }\n\n  return retval;\n}\n\nDEFUN (linspace, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} linspace (@var{start}, @var{end})\n@deftypefnx {} {@var{y} =} linspace (@var{start}, @var{end}, @var{n})\nReturn a row vector with @var{n} linearly spaced elements between @var{start}\nand @var{end}.\n\nIf the number of elements @var{n} is greater than one, then the endpoints\n@var{start} and @var{end} are always included in the range.  If @var{start} is\ngreater than @var{end}, the elements are stored in decreasing order.  If the\nnumber of points @var{n} is not specified, a value of 100 is used.\n\nThe @code{linspace} function returns a row vector when both @var{start} and\n@var{end} are scalars.  If one, or both, inputs are vectors, then\n@code{linspace} transforms them to column vectors and returns a matrix where\neach row is an independent sequence between\n@w{@code{@var{start}(@var{row_n}), @var{end}(@var{row_n})}}.\n\nProgramming Notes: For compatibility with @sc{matlab}, return the second\nargument (@var{end}) when a single value (@var{n} = 1) is requested.  If\n@var{n} is not an integer then @code{floor (@var{n})} is used to round the\nnumber of elements.  If @var{n} is zero or negative then an empty 1x0 matrix\nis returned.\n@seealso{colon, logspace}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin != 2 && nargin != 3)\n    print_usage ();\n\n  octave_idx_type npoints = 100;\n  if (nargin == 3)\n    {\n      // Apparently undocumented Matlab.  If the third arg is an empty\n      // numeric value, the number of points defaults to 1.\n      octave_value arg_3 = args(2);\n\n      if (arg_3.isnumeric () && arg_3.isempty ())\n        npoints = 1;\n      else if (! arg_3.is_scalar_type ())\n        error (\"linspace: N must be a scalar\");\n      else\n        // Even if third arg is not an integer, it must be cast to int\n        npoints = arg_3.idx_type_value ();\n    }\n\n  octave_value arg_1 = args(0);\n  octave_value arg_2 = args(1);\n\n  const dim_vector& sz1 = arg_1.dims ();\n  bool isvector1 = sz1.ndims () == 2 && (sz1(0) == 1 || sz1(1) == 1);\n  const dim_vector& sz2 = arg_2.dims ();\n  bool isvector2 = sz2.ndims () == 2 && (sz2(0) == 1 || sz2(1) == 1);\n\n  if (! isvector1 || ! isvector2)\n    error (\"linspace: START, END must be scalars or vectors\");\n\n  octave_value retval;\n\n  if (arg_1.is_single_type () || arg_2.is_single_type ())\n    {\n      if (arg_1.iscomplex () || arg_2.iscomplex ())\n        retval = do_linspace<FloatComplexMatrix> (arg_1, arg_2, npoints);\n      else\n        retval = do_linspace<FloatMatrix> (arg_1, arg_2, npoints);\n    }\n  else\n    {\n      if (arg_1.iscomplex () || arg_2.iscomplex ())\n        retval = do_linspace<ComplexMatrix> (arg_1, arg_2, npoints);\n      else\n        retval = do_linspace<Matrix> (arg_1, arg_2, npoints);\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! x1 = linspace (1, 2);\n%! x2 = linspace (1, 2, 10);\n%! x3 = linspace (1, -2, 10);\n%! assert (size (x1) == [1, 100] && x1(1) == 1 && x1(100) == 2);\n%! assert (x1(2) - x1(1), (2 - 1)/ (100 - 1), eps);\n%! assert (size (x2) == [1, 10] && x2(1) == 1 && x2(10) == 2);\n%! assert (x2(2) - x2(1), (2 - 1)/ (10 - 1), eps);\n%! assert (size (x3) == [1, 10] && x3(1) == 1 && x3(10) == -2);\n%! assert (x3(2) - x3(1), (-2 - 1)/ (10 - 1), eps);\n\n## Test complex values\n%!test\n%! exp = [1+0i, 2-1.25i, 3-2.5i, 4-3.75i, 5-5i];\n%! obs = linspace (1, 5-5i, 5);\n%! assert (obs, exp);\n\n## Test support for vectors in START and END\n%!assert (linspace ([1 2 3], [7 8 9]),\n%!        [linspace(1, 7); linspace(2, 8); linspace(3, 9)], 10*eps)\n%!assert (linspace ([1 2 3]', [7 8 9]'),\n%!        [linspace(1, 7); linspace(2, 8); linspace(3, 9)], 10*eps)\n%!assert (linspace ([1 2 3], 9),\n%!        [linspace(1, 9); linspace(2, 9); linspace(3, 9)], 10*eps)\n%!assert (linspace ([1 2 3]', 9),\n%!        [linspace(1, 9); linspace(2, 9); linspace(3, 9)], 10*eps)\n%!assert (linspace (1, [7 8 9]),\n%!        [linspace(1, 7); linspace(1, 8); linspace(1, 9)], 10*eps)\n%!assert (linspace (1, [7 8 9]'),\n%!        [linspace(1, 7); linspace(1, 8); linspace(1, 9)], 10*eps)\n\n## Test class of output\n%!assert (class (linspace (1, 2)), \"double\")\n%!assert (class (linspace (single (1), 2)), \"single\")\n%!assert (class (linspace (1, single (2))), \"single\")\n\n## Test symmetry\n%!test <*56659>\n%! x = linspace (-1, 1, 10);\n%! assert (all (x == -fliplr (x)));\n%! x = linspace (-1, 1, 11);\n%! assert (all (x == -fliplr (x)));\n\n%!test <*56659>\n%! x = linspace (-1-1i, 1+1i, 10);\n%! assert (all (x == -fliplr (x)));\n%! x = linspace (-1-1i, 1+1i, 11);\n%! assert (all (x == -fliplr (x)));\n\n%!test <*56659>\n%! x = linspace (single (-1), 1, 10);\n%! assert (all (x == -fliplr (x)));\n%! x = linspace (single (-1), 1, 11);\n%! assert (all (x == -fliplr (x)));\n\n%!test <*56659>\n%! x = linspace (single (-1-1i), 1+1i, 10);\n%! assert (all (x == -fliplr (x)));\n%! x = linspace (single (-1-1i), 1+1i, 11);\n%! assert (all (x == -fliplr (x)));\n\n## Test obscure Matlab compatibility options\n%!assert (linspace (0, 1, []), 1)\n%!assert (linspace (10, 20, 2), [10 20])\n%!assert (linspace (10, 20, 1), [20])\n%!assert (linspace (10, 20, 0), zeros (1, 0))\n%!assert (linspace (10, 20, -1), zeros (1, 0))\n%!assert (numel (linspace (0, 1, 2+eps)), 2)\n%!assert (numel (linspace (0, 1, 2-eps)), 1)\n%!assert (linspace (10, 20, 2.1), [10 20])\n%!assert (linspace (10, 20, 2.9), [10 20])\n%!assert (linspace (Inf, Inf, 3), [Inf, Inf, Inf])\n%!assert (linspace (-Inf, -Inf, 3), [-Inf, -Inf, -Inf])\n%!assert (linspace (-Inf, Inf, 3), [-Inf, 0, Inf])\n## Octave prefers to return NaN which indicates failure of algorithm.\n%!assert (linspace (-Inf, Inf, 4), [-Inf, NaN, NaN, Inf])\n%!assert (linspace (-Inf, 0, 3), [-Inf, NaN, 0])\n%!assert (linspace (-Inf, 0, 4), [-Inf, NaN, NaN, 0])\n%!assert (linspace (Inf + 1i, Inf + 1i, 3), [Inf + 1i, Inf + 1i, Inf + 1i])\n%!assert (linspace (-Inf - 1i, Inf + 1i, 3), [-Inf - 1i, 0 + 0i, Inf + 1i])\n%!assert (linspace (-Inf - 1i, Inf + 2i, 3), [-Inf - 1i, NaN + 0.5i, Inf + 2i])\n%!assert (linspace (-Inf - 3i, Inf + 0i, 4),\n%!        [-Inf - 3i, NaN - 2i, NaN - 1i, Inf + 0i])\n%!assert (linspace (complex (-1, -Inf), complex (1, Inf), 3),\n%!          [complex(-1, -Inf), 0 + 0i, complex(1, Inf)])\n%!assert (linspace (complex (-1, -Inf), complex (2, Inf), 3),\n%!          [complex(-1, -Inf), complex(0.5, NaN), complex(2, Inf)])\n%!assert (linspace (complex (-3, -Inf), complex (0, Inf), 4),\n%!        [complex(-3, -Inf) complex(-2, NaN) complex(-1, NaN) complex(0, Inf)])\n\n## FIXME: Octave is not fully Matlab-compatible for some combinations of\n##        Inf/-Inf endpoints.  See bug #56933.  This was dubbed \"Won't Fix\"\n##        as Octave prefers to return NaN for some of these conditions to\n##        better reflect that the algorithm has failed.  If the behavior in\n##        the future is made compatible these tests can be re-instated.\n##%!assert <56933> (linspace (-Inf, Inf, 4), [-Inf, -Inf, Inf, Inf])\n##%!assert <56933> (linspace (-Inf, Inf, 5), [-Inf, -Inf, 0, Inf, Inf])\n##%!assert <56933> (linspace (0, Inf, 4), [0, Inf, Inf, Inf])\n##%!assert <56933> (linspace (0, -Inf, 4), [0, -Inf, -Inf, -Inf])\n##%!assert <56933> (linspace (-Inf, 0, 4), [-Inf, NaN, NaN, 0])\n##%!assert <56933> (linspace (Inf, 0, 4), [Inf, NaN, NaN, 0])\n##%!assert (1 ./ linspace (-0, 0, 4), [-Inf, Inf, Inf, Inf])\n\n## Test input validation\n%!error <Invalid call> linspace ()\n%!error <Invalid call> linspace (1, 2, 3, 4)\n%!error <N must be a scalar> linspace (1, 2, [3, 4])\n%!error <START, END must be scalars or vectors> linspace (ones (2,2), 2, 3)\n%!error <START, END must be scalars or vectors> linspace (2, ones (2,2), 3)\n%!error <START, END must be scalars or vectors> linspace (1, [], 3)\n*/\n\n// FIXME: should accept dimensions as separate args for N-D\n// arrays as well as 1-D and 2-D arrays.\n\nDEFUN (resize, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{B} =} resize (@var{A}, @var{m})\n@deftypefnx {} {@var{B} =} resize (@var{A}, @var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{B} =} resize (@var{A}, [@var{m} @var{n} @dots{}])\nResize @var{A} cutting off elements as necessary.\n\nIn the result, element with certain indices is equal to the corresponding\nelement of @var{A} if the indices are within the bounds of @var{A}; otherwise,\nthe element is set to zero.\n\nIn other words, the statement\n\n@example\nB = resize (A, dv)\n@end example\n\n@noindent\nis equivalent to the following code:\n\n@example\n@group\nB = zeros (dv, class (A));\nsz = min (dv, size (A));\nfor i = 1:length (sz)\n  idx@{i@} = 1:sz(i);\nendfor\nB(idx@{:@}) = A(idx@{:@});\n@end group\n@end example\n\n@noindent\nbut is performed more efficiently.\n\nIf only @var{m} is supplied, and it is a scalar, the dimension of the result is\n@var{m}-by-@var{m}.  If @var{m}, @var{n}, @dots{} are all scalars, then the\ndimensions of the result are @var{m}-by-@var{n}-by-@enddots{}  If given a\nvector as input, then the dimensions of the result are given by the elements of\nthat vector.\n\nAn object can be resized to more dimensions than it has; in such case the\nmissing dimensions are assumed to be 1.  Resizing an object to fewer dimensions\nis not possible.\n@seealso{reshape, postpad, prepad, cat}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 2)\n    {\n      Array<double> vec = args(1).vector_value ();\n      int ndim = vec.numel ();\n      if (ndim == 1)\n        {\n          octave_idx_type m = static_cast<octave_idx_type> (vec(0));\n          retval = args(0);\n          retval = retval.resize (dim_vector (m, m), true);\n        }\n      else\n        {\n          dim_vector dv;\n          dv.resize (ndim);\n          for (int i = 0; i < ndim; i++)\n            dv(i) = static_cast<octave_idx_type> (vec(i));\n          retval = args(0);\n          retval = retval.resize (dv, true);\n        }\n    }\n  else\n    {\n      dim_vector dv;\n      dv.resize (nargin - 1);\n      for (octave_idx_type i = 1; i < nargin; i++)\n        dv(i-1) = static_cast<octave_idx_type> (args(i).scalar_value ());\n\n      retval = args(0);\n      retval = retval.resize (dv, true);\n    }\n\n  return retval;\n}\n\n// FIXME: should use octave_idx_type for dimensions.\n\nDEFUN (reshape, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{B} =} reshape (@var{A}, @var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{B} =} reshape (@var{A}, [@var{m} @var{n} @dots{}])\n@deftypefnx {} {@var{B} =} reshape (@var{A}, @dots{}, [], @dots{})\n@deftypefnx {} {@var{B} =} reshape (@var{A}, @var{size})\nReturn a matrix with the specified dimensions (@var{m}, @var{n}, @dots{})\nwhose elements are taken from the matrix @var{A}.\n\nThe elements of the matrix are accessed in column-major order (like Fortran\narrays are stored).\n\nThe following code demonstrates reshaping a 1x4 row vector into a 2x2 square\nmatrix.\n\n@example\n@group\nreshape ([1, 2, 3, 4], 2, 2)\n      @xresult{}  1  3\n          2  4\n@end group\n@end example\n\n@noindent\nNote that the total number of elements in the original matrix\n(@code{prod (size (@var{A}))}) must match the total number of elements\nin the new matrix (@code{prod ([@var{m} @var{n} @dots{}])}).\n\nA single dimension of the return matrix may be left unspecified and Octave\nwill determine its size automatically.  An empty matrix ([]) is used to flag\nthe unspecified dimension.\n@seealso{resize, vec, postpad, cat, squeeze}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  octave_value retval;\n\n  dim_vector new_dims;\n\n  if (nargin == 2)\n    {\n      Array<octave_idx_type> new_size = args(1).octave_idx_type_vector_value ();\n\n      if (new_size.numel () < 2)\n        error (\"reshape: SIZE must have 2 or more dimensions\");\n\n      new_dims = dim_vector::alloc (new_size.numel ());\n\n      for (octave_idx_type i = 0; i < new_size.numel (); i++)\n        {\n          if (new_size(i) < 0)\n            error (\"reshape: SIZE must be non-negative\");\n\n          new_dims(i) = new_size(i);\n        }\n    }\n  else\n    {\n      new_dims = dim_vector::alloc (nargin-1);\n      int empty_dim = -1;\n\n      for (int i = 1; i < nargin; i++)\n        {\n          if (args(i).isempty ())\n            {\n              if (empty_dim > 0)\n                error (\"reshape: only a single dimension can be unknown\");\n\n              empty_dim = i;\n              new_dims(i-1) = 1;\n            }\n          else\n            {\n              new_dims(i-1) = args(i).idx_type_value ();\n\n              if (new_dims(i-1) < 0)\n                error (\"reshape: SIZE must be non-negative\");\n            }\n        }\n\n      if (empty_dim > 0)\n        {\n          octave_idx_type nel = new_dims.numel ();\n\n          if (nel == 0)\n            new_dims(empty_dim-1) = 0;\n          else\n            {\n              octave_idx_type a_nel = args(0).numel ();\n              octave_idx_type size_empty_dim = a_nel / nel;\n\n              if (a_nel != size_empty_dim * nel)\n                error (\"reshape: SIZE is not divisible by the product of \"\n                       \"known dimensions (= %\" OCTAVE_IDX_TYPE_FORMAT \")\",\n                       nel);\n\n              new_dims(empty_dim-1) = size_empty_dim;\n            }\n        }\n    }\n\n  retval = args(0).reshape (new_dims);\n\n  return retval;\n}\n\n/*\n%!assert (size (reshape (ones (4, 4), 2, 8)), [2, 8])\n%!assert (size (reshape (ones (4, 4), 8, 2)), [8, 2])\n%!assert (size (reshape (ones (15, 4), 1, 60)), [1, 60])\n%!assert (size (reshape (ones (15, 4), 60, 1)), [60, 1])\n\n%!assert (size (reshape (ones (4, 4, \"single\"), 2, 8)), [2, 8])\n%!assert (size (reshape (ones (4, 4, \"single\"), 8, 2)), [8, 2])\n%!assert (size (reshape (ones (15, 4, \"single\"), 1, 60)), [1, 60])\n%!assert (size (reshape (ones (15, 4, \"single\"), 60, 1)), [60, 1])\n\n%!assert <*64080> (size (reshape (sparse (0, 1), 0, 0)), [0, 0])\n\n%!test\n%! s.a = 1;\n%! fail (\"reshape (s, 2, 3)\", \"can't reshape 1x1 array to 2x3 array\");\n\n%!error reshape ()\n%!error reshape (1, 2, 3, 4)\n%!error <SIZE must have 2 or more dimensions> reshape (1:3, 3)\n%!error <SIZE must be non-negative> reshape (1:3, [3 -1])\n%!error <only a single dimension can be unknown> reshape (1:3, 1,[],[],3)\n%!error <SIZE must be non-negative> reshape (1:3, 3, -1)\n%!error <SIZE is not divisible> reshape (1:3, 3, [], 2)\n*/\n\nDEFUN (vec, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{v} =} vec (@var{x})\n@deftypefnx {} {@var{v} =} vec (@var{x}, @var{dim})\nReturn the vector obtained by stacking the columns of the matrix @var{x}\none above the other.\n\nWithout @var{dim} this is equivalent to @code{@var{x}(:)}.\n\nIf @var{dim} is supplied, the dimensions of @var{v} are set to @var{dim}\nwith all elements along the last dimension.  This is equivalent to\n@code{shiftdim (@var{x}(:), 1-@var{dim})}.\n@seealso{vech, resize, cat}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  int dim = 1;\n  if (nargin == 2)\n    {\n      dim = args(1).idx_type_value ();\n\n      if (dim < 1)\n        error (\"vec: DIM must be greater than zero\");\n    }\n\n  octave_value colon (octave_value::magic_colon_t);\n  octave_value arg = args(0);\n\n  octave_value retval = arg.single_subsref (\"(\", colon);\n\n  if (dim > 1)\n    {\n      dim_vector new_dims = dim_vector::alloc (dim);\n\n      for (int i = 0; i < dim-1; i++)\n        new_dims(i) = 1;\n\n      new_dims(dim-1) = retval.numel ();\n\n      retval = retval.reshape (new_dims);\n    }\n\n  return retval;\n}\n\n/*\n%!assert (vec ([1, 2; 3, 4]), [1; 3; 2; 4])\n%!assert (vec ([1, 3, 2, 4]), [1; 3; 2; 4])\n%!assert (vec ([1, 2, 3, 4], 2), [1, 2, 3, 4])\n%!assert (vec ([1, 2; 3, 4]), vec ([1, 2; 3, 4], 1))\n%!assert (vec ([1, 2; 3, 4], 1), [1; 3; 2; 4])\n%!assert (vec ([1, 2; 3, 4], 2), [1, 3, 2, 4])\n%!assert (vec ([1, 3; 2, 4], 3), reshape ([1, 2, 3, 4], 1, 1, 4))\n%!assert (vec ([1, 3; 2, 4], 3), shiftdim (vec ([1, 3; 2, 4]), -2))\n\n%!error vec ()\n%!error vec (1, 2, 3)\n%!error vec ([1, 2; 3, 4], 0)\n*/\n\nDEFUN (squeeze, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{B} =} squeeze (@var{A})\nRemove singleton dimensions from @var{A} and return the result.\n\nNote that for compatibility with @sc{matlab}, all objects have\na minimum of two dimensions and row vectors are left unchanged.\n@seealso{reshape}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).squeeze ());\n}\n\nDEFUN (full, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{FM} =} full (@var{SM})\nReturn a full storage matrix from a sparse, diagonal, or permutation matrix,\nor from a range.\n@seealso{sparse, issparse}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).full_value ());\n}\n\n// Compute various norms of the vector X.\n\nDEFUN (norm, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{n} =} norm (@var{A})\n@deftypefnx {} {@var{n} =} norm (@var{A}, @var{p})\n@deftypefnx {} {@var{n} =} norm (@var{A}, @var{p}, @var{opt})\nCompute the p-norm of the matrix @var{A}.\n\nIf the second argument is not given, @w{@code{p = 2}}@ is used.\n\nIf @var{A} is a matrix (or sparse matrix):\n\n@table @asis\n@item @var{p} = @code{1}\n1-norm, the largest column sum of the absolute values of @var{A}.\n\n@item @var{p} = @code{2}\nLargest singular value of @var{A}.\n\n@item @var{p} = @code{Inf} or @qcode{\"inf\"}\n@cindex infinity norm\nInfinity norm, the largest row sum of the absolute values of @var{A}.\n\n@item @var{p} = @qcode{\"fro\"}\n@cindex @nospell{Frobenius} norm\n@nospell{Frobenius} norm of @var{A},\n@code{sqrt (sum (diag (@var{A}' * @var{A})))}.\n\n@item other @var{p}, @code{@var{p} > 1}\n@cindex general p-norm\nmaximum @code{norm (A*x, p)} such that @code{norm (x, p) == 1}\n@end table\n\nIf @var{A} is a vector or a scalar:\n\n@table @asis\n@item @var{p} = @code{Inf} or @qcode{\"inf\"}\n@code{max (abs (@var{A}))}.\n\n@item @var{p} = @code{-Inf}\n@code{min (abs (@var{A}))}.\n\n@item @var{p} = @qcode{\"fro\"}\n@nospell{Frobenius} norm of @var{A}, @code{sqrt (sumsq (abs (A)))}.\n\n@item @var{p} = 0\nHamming norm---the number of nonzero elements.\n\n@item other @var{p}, @code{@var{p} > 1}\np-norm of @var{A}, @code{(sum (abs (@var{A}) .^ @var{p})) ^ (1/@var{p})}.\n\n@item other @var{p} @code{@var{p} < 1}\nthe p-pseudonorm defined as above.\n@end table\n\nIf @var{opt} is the value @qcode{\"rows\"}, treat each row as a vector and\ncompute its norm.  The result is returned as a column vector.\nSimilarly, if @var{opt} is @qcode{\"columns\"} or @qcode{\"cols\"} then\ncompute the norms of each column and return a row vector.\n@seealso{normest, normest1, vecnorm, cond, svd}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  octave_value x_arg = args(0);\n\n  if (x_arg.ndims () != 2)\n    error (\"norm: only valid for 2-D objects\");\n\n  enum {sfmatrix, sfcols, sfrows, sffrob, sfinf, sfneginf} strflag = sfmatrix;\n  if (nargin > 1 && args(nargin-1).is_string ())\n    {\n      std::string str = args(nargin-1).string_value ();\n      std::transform (str.begin (), str.end (), str.begin (), tolower);\n      if (str == \"cols\" || str == \"columns\")\n        strflag = sfcols;\n      else if (str == \"rows\")\n        strflag = sfrows;\n      else if (str == \"fro\")\n        strflag = sffrob;\n      else if (str == \"inf\")\n        strflag = sfinf;\n      else if (str == \"-inf\")\n        strflag = sfneginf;\n      else\n        error (\"norm: unrecognized option: %s\", str.c_str ());\n\n      // we've handled the last parameter, so act as if it was removed\n      nargin--;\n    }\n\n  octave_value p_arg = (nargin > 1) ? args(1) : octave_value (2);\n\n  if (p_arg.isempty ())\n    p_arg = octave_value (2);\n  else if (p_arg.is_string ())\n    {\n      std::string str = p_arg.string_value ();\n      std::transform (str.begin (), str.end (), str.begin (), tolower);\n      if (strflag != sfcols && strflag != sfrows)\n        error (\"norm: invalid combination of options\");\n\n      if (str == \"cols\" || str == \"columns\" || str == \"rows\")\n        error (\"norm: invalid combination of options\");\n\n      if (str == \"fro\")\n        p_arg = octave_value (2);\n      else if (str == \"inf\")\n        p_arg = numeric_limits<double>::Inf ();\n      else if (str == \"-inf\")\n        p_arg = -numeric_limits<double>::Inf ();\n      else\n        error (\"norm: unrecognized option: %s\", str.c_str ());\n    }\n  else if (! p_arg.is_scalar_type ())\n    err_wrong_type_arg (\"norm\", p_arg);\n\n  octave_value retval;\n\n  switch (strflag)\n    {\n    case sfmatrix:\n      retval = xnorm (x_arg, p_arg);\n      break;\n\n    case sfcols:\n      retval = xcolnorms (x_arg, p_arg);\n      break;\n\n    case sfrows:\n      retval = xrownorms (x_arg, p_arg);\n      break;\n\n    case sffrob:\n      retval = xfrobnorm (x_arg);\n      break;\n\n    case sfinf:\n      retval = xnorm (x_arg, numeric_limits<double>::Inf ());\n      break;\n\n    case sfneginf:\n      retval = xnorm (x_arg, -numeric_limits<double>::Inf ());\n      break;\n    }\n\n  return retval;\n}\n\n/*\n%!shared x\n%! x = [1, -3, 4, 5, -7];\n%!assert (norm (x,0), 5)\n%!assert (norm (x,1), 20)\n%!assert (norm (x,2), 10)\n%!assert (norm (x,3), 8.24257059961711, -4*eps)\n%!assert (norm (x,Inf), 7)\n%!assert (norm (x,-Inf), 1)\n%!assert (norm (x,\"inf\"), 7)\n%!assert (norm (x,\"-Inf\"), 1)\n%!assert (norm (x,\"fro\"), 10, -eps)\n%!assert (norm (x), 10)\n%!assert (norm ([1e200, 1]), 1e200)\n%!assert (norm ([3+4i, 3-4i, sqrt(31)]), 9, -4*eps)\n%!shared m\n%! m = magic (4);\n%!assert (norm (m,1), 34)\n%!assert (norm (m,2), 34, -eps)\n%!assert (norm (m,3), 34, -sqrt (eps))\n%!assert (norm (m,Inf), 34)\n%!assert (norm (m,\"inf\"), 34)\n%!shared m2, flo, fhi\n%! m2 = [1,2;3,4];\n%! flo = 1e-300;\n%! fhi = 1e+300;\n%!assert (norm (flo*m2,\"fro\"), sqrt (30)*flo, -eps)\n%!assert (norm (fhi*m2,\"fro\"), sqrt (30)*fhi, -eps)\n\n%!shared x\n%! x = single ([1, -3, 4, 5, -7]);\n%!assert (norm (x,0), single (5))\n%!assert (norm (x,1), single (20))\n%!assert (norm (x,2), single (10))\n%!assert (norm (x,3), single (8.24257059961711), -4* eps (\"single\"))\n%!assert (norm (x,Inf), single (7))\n%!assert (norm (x,-Inf), single (1))\n%!assert (norm (x,\"inf\"), single (7))\n%!assert (norm (x,\"-Inf\"), single (1))\n%!assert (norm (x,\"fro\"), single (10), -eps (\"single\"))\n%!assert (norm (x), single (10))\n\n%!test <67918>\n%! ## fails with reference BLAS 3.10.0\n%! assert (norm (single ([1e38, 1])), single (1e38));\n\n%!assert (norm (single ([3+4i, 3-4i, sqrt(31)])),\n%!        single (9), -4* eps (\"single\"))\n%!shared m\n%! m = single (magic (4));\n%!assert (norm (m,1), single (34))\n%!assert (norm (m,2), single (34), -eps (\"single\"))\n%!assert (norm (m,3), single (34), -sqrt (eps (\"single\")))\n%!assert (norm (m,Inf), single (34))\n%!assert (norm (m,\"inf\"), single (34))\n%!shared m2, flo, fhi\n%! m2 = single ([1,2;3,4]);\n%! flo = single (1e-300);\n%! fhi = single (1e+300);\n%!assert (norm (flo*m2,\"fro\"), single (sqrt (30)*flo), -eps (\"single\"))\n%!assert (norm (fhi*m2,\"fro\"), single (sqrt (30)*fhi), -eps (\"single\"))\n\n## Hamming norm (p == 0)\n%!assert (norm ([1, 0, 0, 0, 1], 0), 2)\n\n%!shared q\n%! q = rand (1e3, 3);\n%!assert (norm (q, 3, \"rows\"), sum (q.^3, 2).^(1/3), sqrt (eps))\n%!assert (norm (q, \"fro\", \"rows\"), sum (q.^2, 2).^(1/2), sqrt (eps))\n%!assert (norm (q, \"fro\", \"rows\"), sqrt (sumsq (q, 2)), sqrt (eps))\n%!assert (norm (q, \"fro\", \"cols\"), sqrt (sumsq (q, 1)), sqrt (eps))\n%!assert (norm (q, 3, \"cols\"), sum (q.^3, 1).^(1/3), sqrt (eps))\n%!assert (norm (q, \"inf\", \"rows\"), norm (q, Inf, \"rows\"))\n%!assert (norm (q, \"inf\", \"cols\"), norm (q, Inf, \"cols\"))\n%!assert (norm (q, [], \"rows\"), norm (q, 2, \"rows\"))\n%!assert (norm (q, [], \"cols\"), norm (q, 2, \"cols\"))\n\n%!test <30631>\n%! ## Test for norm returning NaN on sparse matrix\n%! A = sparse (2,2);\n%! A(2,1) = 1;\n%! assert (norm (A), 1);\n\n## Tests for single precision norm calculations.\n## Verify that float norms accumulated in double do not overflow\n## near float maximum.\n##\n## We need values where val^2 overflows float (~3.4e38) but\n## the final norm sqrt(n*val^2) = sqrt(n)*val still fits in float.\n## Using val = 1e19: val^2 = 1e38 (near float max), sqrt(1000)*1e19 ~ 3.2e20 (OK)\n\n%!test <67610>\n%! ## Test 2-norm with values where val^2 would overflow float output\n%! ## val = 1e19, val^2 = 1e38 (would overflow float), but result fits\n%! x = single (1e19) * ones (1000, 1, \"single\");\n%! result = norm (x, 2);\n%! assert (isfinite (result));\n%! xd = double (x);\n%! expected = norm (xd, 2);\n%! assert (double (result), expected, eps (\"single\") * expected);\n\n%!test <67610>\n%! ## Test 1-norm - straightforward sum\n%! ## Use moderately large values\n%! x = single (1e30) * ones (1000, 1, \"single\");\n%! result = norm (x, 1);\n%! assert (isfinite (result));\n%! xd = double (x);\n%! expected = norm (xd, 1);\n%! assert (double (result), expected, eps (\"single\") * expected);\n\n%!test <67610>\n%! ## Test p-norm (p=1.5) with large values\n%! x = single (1e20) * ones (1000, 1, \"single\");\n%! result = norm (x, 1.5);\n%! assert (isfinite (result));\n%! xd = double (x);\n%! expected = norm (xd, 1.5);\n%! assert (double (result), expected, eps (\"single\") * expected);\n\n%!test <67610>\n%! ## Test p-norm (p=0.5) - terms are val^0.5, no overflow concern\n%! x = single (1e30) * ones (1000, 1, \"single\");\n%! result = norm (x, 0.5);\n%! assert (isfinite (result));\n%! xd = double (x);\n%! expected = norm (xd, 0.5);\n%! assert (double (result), expected, eps (\"single\") * expected);\n\n%!test <67610>\n%! ## Test p-norm (p=3) with values where val^3 overflows float\n%! ## val = 1e12, val^3 = 1e36 (near float max in accumulator)\n%! x = single (1e12) * ones (1000, 1, \"single\");\n%! result = norm (x, 3);\n%! assert (isfinite (result));\n%! xd = double (x);\n%! expected = norm (xd, 3);\n%! assert (double (result), expected, eps (\"single\") * expected);\n\n%!test <67610>\n%! ## Test complex single precision 2-norm\n%! ## |z|^2 = re^2 + im^2, use values where this would overflow float\n%! x = single (1e19) * complex (ones (1000, 1, \"single\"), ones (1000, 1, \"single\"));\n%! result = norm (x, 2);\n%! assert (isfinite (result));\n%! xd = double (x);\n%! expected = norm (xd, 2);\n%! assert (double (result), expected, eps (\"single\") * expected);\n\n%!test <67610>\n%! ## Test that single and double give consistent results for normal values\n%! x = single (randn (1000, 1));\n%! xd = double (x);\n%! for p = [0.5, 1, 1.5, 2, 3, Inf]\n%!   rs = norm (x, p);\n%!   rd = norm (xd, p);\n%!   assert (double (rs), rd, eps (\"single\") * rd);\n%! endfor\n\n%!test <67610>\n%! ## Test inf-norm (no accumulation, just max)\n%! fmax = realmax (\"single\");\n%! x = (fmax / 2) * ones (1000, 1, \"single\");\n%! x(500) = fmax - 1;\n%! result = norm (x, Inf);\n%! assert (result, fmax - 1);\n\n%!test <67610>\n%! ## Test -inf norm (min absolute value)\n%! x = single ([1, 2, 0.5, 3]);\n%! result = norm (x, -Inf);\n%! assert (result, single (0.5));\n*/\n\n/*\n## Test input validation\n%!error norm ()\n%!error norm (1,2,3,4)\n%!error <unrecognized option> norm (1, \"invalid\")\n%!error <unrecognized option> norm (1, \"rows\", \"invalid\")\n%!error <unrecognized option> norm (1, \"invalid\", \"rows\")\n%!error <invalid combination of options> norm (1, \"cols\", \"rows\")\n%!error <invalid combination of options> norm (1, \"rows\", \"rows\")\n%!error <p must be .= 1> norm (ones (2,2), -Inf)\n*/\n\nstatic octave_value\nunary_op_defun_body (octave_value::unary_op op,\n                     const octave_value_list& args)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return unary_op (op, args(0));\n}\n\nDEFUN (not, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{z} =} not (@var{x})\nReturn the logical NOT of @var{x}.\n\nThis function is equivalent to the operator syntax @w{@code{! @var{x}}}.\n@seealso{and, or, xor}\n@end deftypefn */)\n{\n  return unary_op_defun_body (octave_value::op_not, args);\n}\n\nDEFUN (uplus, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{B} =} uplus (@var{A})\nThis function and @w{@tcode{+ @var{A}}}@ are equivalent.\n@seealso{uminus, plus}\n@end deftypefn */)\n{\n  return unary_op_defun_body (octave_value::op_uplus, args);\n}\n\nDEFUN (uminus, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{B} =} uminus (@var{A})\nThis function and @w{@tcode{- @var{A}}}@ are equivalent.\n@seealso{uplus, minus}\n@end deftypefn */)\n{\n  return unary_op_defun_body (octave_value::op_uminus, args);\n}\n\nDEFUN (transpose, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{B} =} transpose (@var{A})\nReturn the transpose of @var{A}.\n\nThis function and @tcode{@var{A}.'@:}@ are equivalent.\n@seealso{ctranspose}\n@end deftypefn */)\n{\n  return unary_op_defun_body (octave_value::op_transpose, args);\n}\n\n/*\n%!assert (2.', 2)\n%!assert (2i.', 2i)\n%!assert ([1:4].', [1;2;3;4])\n%!assert ([1;2;3;4].', [1:4])\n%!assert ([1,2;3,4].', [1,3;2,4])\n%!assert ([1,2i;3,4].', [1,3;2i,4])\n\n%!assert (transpose ([1,2;3,4]), [1,3;2,4])\n\n%!assert (single (2).', single (2))\n%!assert (single (2i).', single (2i))\n%!assert (single ([1:4]).', single ([1;2;3;4]))\n%!assert (single ([1;2;3;4]).', single ([1:4]))\n%!assert (single ([1,2;3,4]).', single ([1,3;2,4]))\n%!assert (single ([1,2i;3,4]).', single ([1,3;2i,4]))\n\n%!assert (transpose (single ([1,2;3,4])), single ([1,3;2,4]))\n*/\n\nDEFUN (ctranspose, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{B} =} ctranspose (@var{A})\nReturn the complex conjugate transpose of @var{A}.\n\nThis function and @tcode{@var{A}'}@ are equivalent.\n@seealso{transpose}\n@end deftypefn */)\n{\n  return unary_op_defun_body (octave_value::op_hermitian, args);\n}\n\n/*\n%!assert (2', 2)\n%!assert (2i', -2i)\n%!assert ([1:4]', [1;2;3;4])\n%!assert ([1;2;3;4]', [1:4])\n%!assert ([1,2;3,4]', [1,3;2,4])\n%!assert ([1,2i;3,4]', [1,3;-2i,4])\n\n%!assert (ctranspose ([1,2i;3,4]), [1,3;-2i,4])\n\n%!assert (single (2)', single (2))\n%!assert (single (2i)', single (-2i))\n%!assert (single ([1:4])', single ([1;2;3;4]))\n%!assert (single ([1;2;3;4])', single ([1:4]))\n%!assert (single ([1,2;3,4])', single ([1,3;2,4]))\n%!assert (single ([1,2i;3,4])', single ([1,3;-2i,4]))\n\n%!assert (ctranspose (single ([1,2i;3,4])), single ([1,3;-2i,4]))\n*/\n\nstatic octave_value\nbinary_op_defun_body (octave_value::binary_op op,\n                      const octave_value_list& args)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  return binary_op (op, args(0), args(1));\n}\n\nstatic octave_value\nbinary_assoc_op_defun_body (octave_value::binary_op op,\n                            octave_value::assign_op aop,\n                            const octave_value_list& args)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 2)\n    retval = binary_op (op, args(0), args(1));\n  else\n    {\n      retval = binary_op (op, args(0), args(1));\n\n      for (int i = 2; i < nargin; i++)\n        retval.assign (aop, args(i));\n    }\n\n  return retval;\n}\n\nDEFUN (plus, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} plus (@var{A}, @var{B})\n@deftypefnx {} {@var{C} =} plus (@var{A1}, @var{A2}, @dots{})\nThis function and @w{@tcode{@var{A} + @var{B}}}@ are equivalent.\n\nIf more arguments are given, the summation is applied\ncumulatively from left to right:\n\n@example\n(@dots{}((@var{A1} + @var{A2}) + @var{A3}) + @dots{})\n@end example\n\n@seealso{minus, uplus}\n@end deftypefn */)\n{\n  return binary_assoc_op_defun_body (octave_value::op_add,\n                                     octave_value::op_add_eq, args);\n}\n\n/*\n%!assert (plus (1,1), 2)\n%!assert (plus (1:3, 1), 2:4)\n%!assert (plus (1:3, 1, 3), 5:7)\n%!assert (plus (1,2,3,4,5,6,7,8,9), sum (1:9))\n\n## Test input validation for all functions which use binary_assoc_op_defun_body\n%!error plus ()\n%!error plus (1)\n*/\n\nDEFUN (minus, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} minus (@var{A}, @var{B})\nThis function and @w{@tcode{@var{A} - @var{B}}}@ are equivalent.\n@seealso{plus, uminus}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_sub, args);\n}\n\nDEFUN (mtimes, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} mtimes (@var{A}, @var{B})\n@deftypefnx {} {@var{C} =} mtimes (@var{A1}, @var{A2}, @dots{})\nReturn the matrix multiplication product of inputs.\n\nThis function and @w{@tcode{@var{A} * @var{B}}}@ are equivalent.\nIf more arguments are given, the multiplication is applied\ncumulatively from left to right:\n\n@example\n(@dots{}((@var{A1} * @var{A2}) * @var{A3}) * @dots{})\n@end example\n\n@seealso{times, plus, minus, rdivide, mrdivide, mldivide, mpower, tensorprod}\n@end deftypefn */)\n{\n  return binary_assoc_op_defun_body (octave_value::op_mul,\n                                     octave_value::op_mul_eq, args);\n}\n\nDEFUN (mrdivide, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} mrdivide (@var{A}, @var{B})\nReturn the matrix right division of @var{A} and @var{B}.\n\nThis function and @w{@tcode{@var{A} / @var{B}}}@ are equivalent.\n\nIf the system is not square, or if the coefficient matrix is singular, a\nminimum norm solution is computed.\n@seealso{mldivide, rdivide, plus, minus}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_div, args);\n}\n\nDEFUN (mpower, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} mpower (@var{A}, @var{B})\nReturn the matrix power operation of @var{A} raised to the @var{B} power.\n\nThis function and @w{@tcode{@var{A} ^ @var{B}}}@ are equivalent.\n@seealso{power, mtimes, plus, minus}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_pow, args);\n}\n/*\n%!assert (complex (realmin, realmin) ^ realmax, 0)\n*/\n\nDEFUN (mldivide, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} mldivide (@var{A}, @var{B})\nReturn the matrix left division of @var{A} and @var{B}.\n\nThis function and @w{@tcode{@var{A} @backslashchar{} @var{B}}}@ are equivalent.\n\nIf the system is not square, or if the coefficient matrix is singular, a\nminimum norm solution is computed.\n@seealso{mrdivide, ldivide, rdivide, linsolve}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_ldiv, args);\n}\n\nDEFUN (lt, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{TF} =} lt (@var{A}, @var{B})\nThis function is equivalent to @w{@code{@var{A} < @var{B}}}.\n@seealso{le, eq, ge, gt, ne}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_lt, args);\n}\n\nDEFUN (le, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{TF} =} le (@var{A}, @var{B})\nThis function is equivalent to @w{@code{@var{A} <= @var{B}}}.\n@seealso{eq, ge, gt, ne, lt}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_le, args);\n}\n\nDEFUN (eq, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{TF} =} eq (@var{A}, @var{B})\nReturn true if the two inputs are equal.\n\nThis function is equivalent to @w{@code{@var{A} == @var{B}}}.\n@seealso{ne, isequal, le, ge, gt, ne, lt}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_eq, args);\n}\n\nDEFUN (ge, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{TF} =} ge (@var{A}, @var{B})\nThis function is equivalent to @w{@code{@var{A} >= @var{B}}}.\n@seealso{le, eq, gt, ne, lt}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_ge, args);\n}\n\nDEFUN (gt, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{TF} =} gt (@var{A}, @var{B})\nThis function is equivalent to @w{@code{@var{A} > @var{B}}}.\n@seealso{le, eq, ge, ne, lt}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_gt, args);\n}\n\nDEFUN (ne, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{TF} =} ne (@var{A}, @var{B})\nReturn true if the two inputs are not equal.\n\nThis function is equivalent to @w{@code{@var{A} != @var{B}}}.\n@seealso{eq, isequal, le, ge, lt}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_ne, args);\n}\n\nDEFUN (times, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} times (@var{A}, @var{B})\n@deftypefnx {} {@var{C} =} times (@var{A1}, @var{A2}, @dots{})\nReturn the element-by-element multiplication product of inputs.\n\nThis function and @w{@tcode{@var{A} .* @var{B}}}@ are equivalent.\nIf more arguments are given, the multiplication is applied\ncumulatively from left to right:\n\n@example\n(@dots{}((@var{A1} .* @var{A2}) .* @var{A3}) .* @dots{})\n@end example\n\n@seealso{mtimes, rdivide}\n@end deftypefn */)\n{\n  return binary_assoc_op_defun_body (octave_value::op_el_mul,\n                                     octave_value::op_el_mul_eq, args);\n}\n\nDEFUN (rdivide, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} rdivide (@var{A}, @var{B})\nReturn the element-by-element right division of @var{A} and @var{B}.\n\nThis function and @w{@tcode{@var{A} ./ @var{B}}}@ are equivalent.\n@seealso{ldivide, mrdivide, times, plus}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_el_div, args);\n}\n\nDEFUN (power, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} power (@var{A}, @var{B})\nReturn the element-by-element operation of @var{A} raised to the\n@var{B} power.\n\nThis function and @w{@tcode{@var{A} .^ @var{B}}}@ are equivalent.\n\nIf several complex results are possible, returns the one with smallest\nnon-negative argument (angle).  Use @code{realpow}, @code{realsqrt},\n@code{cbrt}, or @code{nthroot} if a real result is preferred.\n\n@seealso{mpower, realpow, realsqrt, cbrt, nthroot}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_el_pow, args);\n}\n/*\n%!assert (complex (realmin, realmin) .^ realmax, 0)\n*/\n\nDEFUN (ldivide, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} ldivide (@var{A}, @var{B})\nReturn the element-by-element left division of @var{A} and @var{B}.\n\nThis function and @w{@tcode{@var{A} .@backslashchar{} @var{B}}}@ are\nequivalent.\n@seealso{rdivide, mldivide, times, plus}\n@end deftypefn */)\n{\n  return binary_op_defun_body (octave_value::op_el_ldiv, args);\n}\n\nDEFUN (and, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{TF} =} and (@var{x}, @var{y})\n@deftypefnx {} {@var{TF} =} and (@var{x1}, @var{x2}, @dots{})\nReturn the logical AND of @var{x} and @var{y}.\n\nThis function is equivalent to the operator syntax\n@w{@code{@var{x} & @var{y}}}.  If more than two arguments are given, the\nlogical AND is applied cumulatively from left to right:\n\n@example\n(@dots{}((@var{x1} & @var{x2}) & @var{x3}) & @dots{})\n@end example\n\n@seealso{or, not, xor}\n@end deftypefn */)\n{\n  return binary_assoc_op_defun_body (octave_value::op_el_and,\n                                     octave_value::op_el_and_eq, args);\n}\n\nDEFUN (or, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{TF} =} or (@var{x}, @var{y})\n@deftypefnx {} {@var{TF} =} or (@var{x1}, @var{x2}, @dots{})\nReturn the logical OR of @var{x} and @var{y}.\n\nThis function is equivalent to the operator syntax\n@w{@code{@var{x} | @var{y}}}.  If more than two arguments are given, the\nlogical OR is applied cumulatively from left to right:\n\n@example\n(@dots{}((@var{x1} | @var{x2}) | @var{x3}) | @dots{})\n@end example\n\n@seealso{and, not, xor}\n@end deftypefn */)\n{\n  return binary_assoc_op_defun_body (octave_value::op_el_or,\n                                     octave_value::op_el_or_eq, args);\n}\n\nDEFUN (colon, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{r} =} colon (@var{base}, @var{limit})\n@deftypefnx {} {@var{r} =} colon (@var{base}, @var{increment}, @var{limit})\nReturn the result of the colon expression corresponding to @var{base},\n@var{limit}, and optionally, @var{increment}.\n\nThis function is equivalent to the operator syntax\n@w{@code{@var{base} : @var{limit}}}@ or\n@w{@code{@var{base} : @var{increment} : @var{limit}}}.\n@seealso{linspace}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  return (nargin == 2\n          ? colon_op (args(0), args(1))\n          : colon_op (args(0), args(1), args(2)));\n}\n\nstatic double tic_toc_timestamp = -1.0;\n\nDEFUN (tic, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} tic ()\n@deftypefnx {} {@var{id} =} tic ()\nInitialize a wall-clock timer.\n\nCalling @code{tic} without an output argument resets the internal timer.\nSubsequent calls to @code{toc} return the number of seconds since the timer was\nset.\n\nIf called with one output argument, @code{tic} creates a new timer instance and\nreturns a timer identifier @var{id}.  The @var{id} is a scalar of type\n@code{uint64} that may be passed to @code{toc} to check elapsed time on this\ntimer, rather than the default internal timer.\n\nExample 1 : benchmarking code with internal timer\n\n@example\n@group\ntic;\n# many computations later@dots{}\nelapsed_time = toc;\n@end group\n@end example\n\nExample 2 : mixed timer id and internal timer\n\n@example\n@group\ntic;\npause (1);\ntoc\n@xresult{} Elapsed time is 1.0089 seconds.\nid = tic;\npause (2);\ntoc (id)\n@xresult{} Elapsed time is 2.01142 seconds.\ntoc\nElapsed time is 3.02308 seconds.\n@end group\n@end example\n\n@noindent\nCalling @code{tic} and @code{toc} in this way allows nested timing calls.\n\nIf you are more interested in the CPU time that your process used, you should\nuse the @code{cputime} function instead.  The @code{tic} and @code{toc}\nfunctions report the actual wall clock time that elapsed between the calls.\nThis may include time spent processing other jobs or doing nothing at all.\n@seealso{toc, cputime}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    warning (\"tic: ignoring extra arguments\");\n\n  octave_value retval;\n  sys::time now;\n  double tmp = now.double_value ();\n\n  if (nargout > 0)\n    {\n      double ip = 0.0;\n      double frac = std::modf (tmp, &ip);\n      uint64_t microsecs = static_cast<uint64_t> (CLOCKS_PER_SEC * frac);\n      microsecs += CLOCKS_PER_SEC * static_cast<uint64_t> (ip);\n      retval = octave_uint64 (microsecs);\n    }\n  else\n    tic_toc_timestamp = tmp;\n\n  return retval;\n}\n\nDEFUN (toc, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} toc ()\n@deftypefnx {} {} toc (@var{id})\n@deftypefnx {} {@var{elapsed_time} =} toc (@dots{})\nMeasure elapsed time on a wall-clock timer.\n\nWith no arguments, return the number of seconds elapsed on the internal timer\nsince the last call to @code{tic}.\n\nWhen given the identifier @var{id} of a specific timer, return the number of\nseconds elapsed since the timer @var{id} was initialized.\n\n@xref{XREFtic,,tic}, for examples of the use of @code{tic}/@code{toc}.\n\n@seealso{tic, cputime}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  double start_time = tic_toc_timestamp;\n\n  if (nargin == 1)\n    {\n      octave_uint64 id = args(0).xuint64_scalar_value (\"toc: invalid ID\");\n\n      uint64_t val = id.value ();\n\n      start_time\n        = (static_cast<double> (val / CLOCKS_PER_SEC)\n           + static_cast<double> (val % CLOCKS_PER_SEC)\n           / CLOCKS_PER_SEC);\n\n      // FIXME: should we also check to see whether the start\n      //        time is after the beginning of this Octave session?\n    }\n\n  if (start_time < 0)\n    error (\"toc: function called before timer initialization with tic()\");\n\n  sys::time now;\n\n  double etime = now.double_value () - start_time;\n\n  octave_value retval;\n  if (nargout > 0)\n    retval = etime;\n  else\n    octave_stdout << \"Elapsed time is \" << etime << \" seconds.\\n\";\n\n  return retval;\n}\n\n/*\n%!shared id\n%! id = tic ();\n%!assert (isa (id, \"uint64\"))\n%!assert (isa (toc (id), \"double\"))\n*/\n\nDEFUN (cputime, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{total}, @var{user}, @var{system}] =} cputime ();\nReturn the CPU time used by your Octave session.\n\nThe first output is the total time spent executing your process and is equal\nto the sum of second and third outputs, which are the number of CPU seconds\nspent executing in user mode and the number of CPU seconds spent executing\nin system mode, respectively.\n\nIf your system does not have a way to report CPU time usage, @code{cputime}\nreturns 0 for each of its output values.\n\nNote that because Octave used some CPU time to start, it is reasonable\nto check to see if @code{cputime} works by checking to see if the total\nCPU time used is nonzero.\n@seealso{tic, toc}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  sys::cpu_time cpu_tm;\n\n  double usr = cpu_tm.user ();\n  double sys = cpu_tm.system ();\n\n  return ovl (usr + sys, usr, sys);\n}\n\nDEFUN (sort, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{s}, @var{i}] =} sort (@var{x})\n@deftypefnx {} {[@var{s}, @var{i}] =} sort (@var{x}, @var{dim})\n@deftypefnx {} {[@var{s}, @var{i}] =} sort (@var{x}, @var{mode})\n@deftypefnx {} {[@var{s}, @var{i}] =} sort (@var{x}, @var{dim}, @var{mode})\nReturn a copy of @var{x} with the elements arranged in increasing order.\n\nFor matrices, @code{sort} orders the elements within columns\n\nFor example:\n\n@example\n@group\nsort ([1, 2; 2, 3; 3, 1])\n   @xresult{}  1  1\n       2  2\n       3  3\n@end group\n@end example\n\nIf the optional argument @var{dim} is given, then the matrix is sorted\nalong the dimension defined by @var{dim}.  The optional argument @var{mode}\ndefines the order in which the values will be sorted.  Valid values of\n@var{mode} are @qcode{\"ascend\"} or @qcode{\"descend\"}.\n\nThe @code{sort} function may also be used to produce a matrix\ncontaining the original row indices of the elements in the sorted\nmatrix.  For example:\n\n@example\n@group\n[s, i] = sort ([1, 2; 2, 3; 3, 1])\n  @xresult{} s = 1  1\n         2  2\n         3  3\n  @xresult{} i = 1  3\n         2  1\n         3  2\n@end group\n@end example\n\nFor equal elements, the indices are such that equal elements are listed\nin the order in which they appeared in the original list.\n\nSorting of complex entries is done first by magnitude\n(@w{@code{abs (@var{z})}})@ and for any ties by phase angle\n(@w{@code{angle (z)}}).  For example:\n\n@example\n@group\nsort ([1+i; 1; 1-i])\n    @xresult{} 1 + 0i\n       1 - 1i\n       1 + 1i\n@end group\n@end example\n\nNaN values are treated as being greater than any other value and are sorted\nto the end of the list.\n\nThe @code{sort} function may also be used to sort strings and cell arrays\nof strings, in which case ASCII dictionary order (uppercase 'A' precedes\nlowercase 'a') of the strings is used.\n\nThe algorithm used in @code{sort} is optimized for the sorting of partially\nordered lists.\n@seealso{sortrows, issorted}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  sortmode smode = ASCENDING;\n  bool return_idx = (nargout > 1);\n  bool have_sortmode = (nargin > 1 && args(1).is_string ());\n  octave_value arg = args(0);\n\n  int dim = 0;\n  if (nargin > 1)\n    {\n      if (have_sortmode)\n        {\n          std::string mode = args(1).string_value ();\n          if (mode == \"ascend\")\n            smode = ASCENDING;\n          else if (mode == \"descend\")\n            smode = DESCENDING;\n          else\n            error (R\"(sort: MODE must be either \"ascend\" or \"descend\")\");\n        }\n      else\n        {\n          // Require dim to be positive real scalar.\n          if (! args(1).is_scalar_type () || args(1).iscomplex ()\n              || args(1).double_value () <= 0)\n            error (\"sort: DIM must be a positive scalar integer\");\n\n          // Forbid fractional value input, also NaN input.\n          dim = args(1).strict_int_value (\"sort: DIM must be a positive scalar integer\") - 1;\n        }\n    }\n\n  if (nargin > 2)\n    {\n      if (have_sortmode)\n        error (\"sort: DIM argument must precede MODE argument\");\n\n      std::string mode = args(2).xstring_value (\"sort: MODE must be a string\");\n\n      if (mode == \"ascend\")\n        smode = ASCENDING;\n      else if (mode == \"descend\")\n        smode = DESCENDING;\n      else\n        error (R\"(sort: MODE must be either \"ascend\" or \"descend\")\");\n    }\n\n  const dim_vector dv = arg.dims ();\n  if (nargin == 1 || have_sortmode)\n    {\n      dim = dv.first_non_singleton ();\n    }\n\n  octave_value_list retval (return_idx ? 2 : 1);\n\n  if (return_idx)\n    {\n      Array<octave_idx_type> sidx;\n\n      // NOTE: Can not change this to ovl() call because arg.sort changes sidx\n      //       and objects are declared const in ovl prototype.\n      retval(0) = arg.sort (sidx, dim, smode);\n      // Check for index dimension extent.  Set to 1 for dimension >= ndims ()\n      retval(1) = idx_vector (sidx, (dim < arg.ndims ()) ? dv(dim) : 1);\n    }\n  else\n    retval = ovl (arg.sort (dim, smode));\n\n  return retval;\n}\n\n/*\n## Double\n%!assert (sort ([NaN, 1, -1, 2, Inf]), [-1, 1, 2, Inf, NaN])\n%!assert (sort ([NaN, 1, -1, 2, Inf], 1), [NaN, 1, -1, 2, Inf])\n%!assert (sort ([NaN, 1, -1, 2, Inf], 2), [-1, 1, 2, Inf, NaN])\n%!assert (sort ([NaN, 1, -1, 2, Inf], 3), [NaN, 1, -1, 2, Inf])\n%!assert (sort ([NaN, 1, -1, 2, Inf], \"ascend\"), [-1, 1, 2, Inf, NaN])\n%!assert (sort ([NaN, 1, -1, 2, Inf], 2, \"ascend\"), [-1, 1, 2, Inf, NaN])\n%!assert (sort ([NaN, 1, -1, 2, Inf], \"descend\"), [NaN, Inf, 2, 1, -1])\n%!assert (sort ([NaN, 1, -1, 2, Inf], 2, \"descend\"), [NaN, Inf, 2, 1, -1])\n%!assert (sort ([3, 1, 7, 5; 8, 2, 6, 4]), [3, 1, 6, 4; 8, 2, 7, 5])\n%!assert (sort ([3, 1, 7, 5; 8, 2, 6, 4], 1), [3, 1, 6, 4; 8, 2, 7, 5])\n%!assert (sort ([3, 1, 7, 5; 8, 2, 6, 4], 2), [1, 3, 5, 7; 2, 4, 6, 8])\n%!assert (sort (1), 1)\n\n%!test\n%! [v, i] = sort ([NaN, 1, -1, Inf, 1]);\n%! assert (v, [-1, 1, 1, Inf, NaN]);\n%! assert (i, [3, 2, 5, 4, 1]);\n\n## Complex\n%!assert (sort ([NaN, 1i, -1, 2, Inf]), [1i, -1, 2, Inf, NaN])\n%!assert (sort ([NaN, 1i, -1, 2, Inf], 1), [NaN, 1i, -1, 2, Inf])\n%!assert (sort ([NaN, 1i, -1, 2, Inf], 2), [1i, -1, 2, Inf, NaN])\n%!assert (sort ([NaN, 1i, -1, 2, Inf], 3), [NaN, 1i, -1, 2, Inf])\n%!assert (sort ([NaN, 1i, -1, 2, Inf], \"ascend\"), [1i, -1, 2, Inf, NaN])\n%!assert (sort ([NaN, 1i, -1, 2, Inf], 2, \"ascend\"), [1i, -1, 2, Inf, NaN])\n%!assert (sort ([NaN, 1i, -1, 2, Inf], \"descend\"), [NaN, Inf, 2, -1, 1i])\n%!assert (sort ([NaN, 1i, -1, 2, Inf], 2, \"descend\"), [NaN, Inf, 2, -1, 1i])\n%!assert (sort ([3, 1i, 7, 5; 8, 2, 6, 4]), [3, 1i, 6, 4; 8, 2, 7, 5])\n%!assert (sort ([3, 1i, 7, 5; 8, 2, 6, 4], 1), [3, 1i, 6, 4; 8, 2, 7, 5])\n%!assert (sort ([3, 1i, 7, 5; 8, 2, 6, 4], 2), [1i, 3, 5, 7; 2, 4, 6, 8])\n%!assert (sort (1i), 1i)\n\n%!test\n%! [v, i] = sort ([NaN, 1i, -1, Inf, 1, 1i]);\n%! assert (v, [1, 1i, 1i, -1, Inf, NaN]);\n%! assert (i, [5, 2, 6, 3, 4, 1]);\n\n## Single\n%!assert (sort (single ([NaN, 1, -1, 2, Inf])), single ([-1, 1, 2, Inf, NaN]))\n%!assert (sort (single ([NaN, 1, -1, 2, Inf]), 1),\n%!        single ([NaN, 1, -1, 2, Inf]))\n%!assert (sort (single ([NaN, 1, -1, 2, Inf]), 2),\n%!        single ([-1, 1, 2, Inf, NaN]))\n%!assert (sort (single ([NaN, 1, -1, 2, Inf]), 3),\n%!        single ([NaN, 1, -1, 2, Inf]))\n%!assert (sort (single ([NaN, 1, -1, 2, Inf]), \"ascend\"),\n%!        single ([-1, 1, 2, Inf, NaN]))\n%!assert (sort (single ([NaN, 1, -1, 2, Inf]), 2, \"ascend\"),\n%!        single ([-1, 1, 2, Inf, NaN]))\n%!assert (sort (single ([NaN, 1, -1, 2, Inf]), \"descend\"),\n%!        single ([NaN, Inf, 2, 1, -1]))\n%!assert (sort (single ([NaN, 1, -1, 2, Inf]), 2, \"descend\"),\n%!        single ([NaN, Inf, 2, 1, -1]))\n%!assert (sort (single ([3, 1, 7, 5; 8, 2, 6, 4])),\n%!        single ([3, 1, 6, 4; 8, 2, 7, 5]))\n%!assert (sort (single ([3, 1, 7, 5; 8, 2, 6, 4]), 1),\n%!        single ([3, 1, 6, 4; 8, 2, 7, 5]))\n%!assert (sort (single ([3, 1, 7, 5; 8, 2, 6, 4]), 2),\n%!        single ([1, 3, 5, 7; 2, 4, 6, 8]))\n%!assert (sort (single (1)), single (1))\n\n%!test\n%! [v, i] = sort (single ([NaN, 1, -1, Inf, 1]));\n%! assert (v, single ([-1, 1, 1, Inf, NaN]));\n%! assert (i, [3, 2, 5, 4, 1]);\n\n## Single Complex\n%!assert (sort (single ([NaN, 1i, -1, 2, Inf])),\n%!        single ([1i, -1, 2, Inf, NaN]))\n%!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 1),\n%!        single ([NaN, 1i, -1, 2, Inf]))\n%!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 2),\n%!        single ([1i, -1, 2, Inf, NaN]))\n%!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 3),\n%!        single ([NaN, 1i, -1, 2, Inf]))\n%!assert (sort (single ([NaN, 1i, -1, 2, Inf]), \"ascend\"),\n%!        single ([1i, -1, 2, Inf, NaN]))\n%!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 2, \"ascend\"),\n%!        single ([1i, -1, 2, Inf, NaN]))\n%!assert (sort (single ([NaN, 1i, -1, 2, Inf]), \"descend\"),\n%!        single ([NaN, Inf, 2, -1, 1i]))\n%!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 2, \"descend\"),\n%!        single ([NaN, Inf, 2, -1, 1i]))\n%!assert (sort (single ([3, 1i, 7, 5; 8, 2, 6, 4])),\n%!        single ([3, 1i, 6, 4; 8, 2, 7, 5]))\n%!assert (sort (single ([3, 1i, 7, 5; 8, 2, 6, 4]), 1),\n%!        single ([3, 1i, 6, 4; 8, 2, 7, 5]))\n%!assert (sort (single ([3, 1i, 7, 5; 8, 2, 6, 4]), 2),\n%!        single ([1i, 3, 5, 7; 2, 4, 6, 8]))\n%!assert (sort (single (1i)), single (1i))\n\n%!test\n%! [v, i] = sort (single ([NaN, 1i, -1, Inf, 1, 1i]));\n%! assert (v, single ([1, 1i, 1i, -1, Inf, NaN]));\n%! assert (i, [5, 2, 6, 3, 4, 1]);\n\n## Bool\n%!assert (sort ([true, false, true, false]), [false, false, true, true])\n%!assert (sort ([true, false, true, false], 1), [true, false, true, false])\n%!assert (sort ([true, false, true, false], 2), [false, false, true, true])\n%!assert (sort ([true, false, true, false], 3), [true, false, true, false])\n%!assert (sort ([true, false, true, false], \"ascend\"),\n%!        [false, false, true, true])\n%!assert (sort ([true, false, true, false], 2, \"ascend\"),\n%!        [false, false, true, true])\n%!assert (sort ([true, false, true, false], \"descend\"),\n%!        [true, true, false, false])\n%!assert (sort ([true, false, true, false], 2, \"descend\"),\n%!        [true, true, false, false])\n%!assert (sort (true), true)\n\n%!test\n%! [v, i] = sort ([true, false, true, false]);\n%! assert (v, [false, false, true, true]);\n%! assert (i, [2, 4, 1, 3]);\n\n## Sparse Double\n%!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf])),\n%!        sparse ([-1, 0, 0, 1, 2, Inf, NaN]))\n%!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 1),\n%!        sparse ([0, NaN, 1, 0, -1, 2, Inf]))\n%!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 2),\n%!        sparse ([-1, 0, 0, 1, 2, Inf, NaN]))\n%!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 3),\n%!        sparse ([0, NaN, 1, 0, -1, 2, Inf]))\n%!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), \"ascend\"),\n%!        sparse ([-1, 0, 0, 1, 2, Inf, NaN]))\n%!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 2, \"ascend\"),\n%!        sparse ([-1, 0, 0, 1, 2, Inf, NaN]))\n%!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), \"descend\"),\n%!        sparse ([NaN, Inf, 2, 1, 0, 0, -1]))\n%!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 2, \"descend\"),\n%!        sparse ([NaN, Inf, 2, 1, 0, 0, -1]))\n\n%!shared a\n%! a = randn (10, 10);\n%! a(a < 0) = 0;\n%!assert (sort (sparse (a)), sparse (sort (a)))\n%!assert (sort (sparse (a), 1), sparse (sort (a, 1)))\n%!assert (sort (sparse (a), 2), sparse (sort (a, 2)))\n%!test\n%! [v, i] = sort (a);\n%! [vs, is] = sort (sparse (a));\n%! assert (vs, sparse (v));\n%! assert (is, i);\n\n## Sparse Complex\n%!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf])),\n%!        sparse ([0, 0, 1i, -1, 2, Inf, NaN]))\n%!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 1),\n%!        sparse ([0, NaN, 1i, 0, -1, 2, Inf]))\n%!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 2),\n%!        sparse ([0, 0, 1i, -1, 2, Inf, NaN]))\n%!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 3),\n%!        sparse ([0, NaN, 1i, 0, -1, 2, Inf]))\n%!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), \"ascend\"),\n%!        sparse ([0, 0, 1i, -1, 2, Inf, NaN]))\n%!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 2, \"ascend\"),\n%!        sparse ([0, 0, 1i, -1, 2, Inf, NaN]))\n%!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), \"descend\"),\n%!        sparse ([NaN, Inf, 2, -1, 1i, 0, 0]))\n%!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 2, \"descend\"),\n%!        sparse ([NaN, Inf, 2, -1, 1i, 0, 0]))\n\n%!shared a\n%! a = randn (10, 10);\n%! a(a < 0) = 0;\n%! a = 1i * a;\n%!assert (sort (sparse (a)), sparse (sort (a)))\n%!assert (sort (sparse (a), 1), sparse (sort (a, 1)))\n%!assert (sort (sparse (a), 2), sparse (sort (a, 2)))\n%!test\n%! [v, i] = sort (a);\n%! [vs, is] = sort (sparse (a));\n%! assert (vs, sparse (v));\n%! assert (is, i);\n\n## Sparse Bool\n%!assert (sort (sparse ([true, false, true, false])),\n%!        sparse ([false, false, true, true]))\n%!assert (sort (sparse ([true, false, true, false]), 1),\n%!        sparse ([true, false, true, false]))\n%!assert (sort (sparse ([true, false, true, false]), 2),\n%!        sparse ([false, false, true, true]))\n%!assert (sort (sparse ([true, false, true, false]), 3),\n%!        sparse ([true, false, true, false]))\n%!assert (sort (sparse ([true, false, true, false]), \"ascend\"),\n%!        sparse ([false, false, true, true]))\n%!assert (sort (sparse ([true, false, true, false]), 2, \"ascend\"),\n%!        sparse ([false, false, true, true]))\n%!assert (sort (sparse ([true, false, true, false]), \"descend\"),\n%!        sparse ([true, true, false, false]))\n%!assert (sort (sparse ([true, false, true, false]), 2, \"descend\"),\n%!        sparse ([true, true, false, false]))\n\n%!test\n%! [v, i] = sort (sparse ([true, false, true, false]));\n%! assert (v, sparse ([false, false, true, true]));\n%! assert (i, [2, 4, 1, 3]);\n\n## Cell string array\n%!shared a, b, c\n%! a = {\"Alice\", \"Cecile\", \"Eric\", \"Barry\", \"David\"};\n%! b = {\"Alice\", \"Barry\", \"Cecile\", \"David\", \"Eric\"};\n%! c = {\"Eric\", \"David\", \"Cecile\", \"Barry\", \"Alice\"};\n%!assert (sort (a), b)\n%!assert (sort (a, 1), a)\n%!assert (sort (a, 2), b)\n%!assert (sort (a, 3), a)\n%!assert (sort (a, \"ascend\"), b)\n%!assert (sort (a, 2, \"ascend\"), b)\n%!assert (sort (a, \"descend\"), c)\n%!assert (sort (a, 2, \"descend\"), c)\n\n%!test\n%! [v, i] = sort (a);\n%! assert (i, [1, 4, 2, 5, 3]);\n\n## Test sort dimension being very large\n%!test <*65712>\n%! A = [1 2; 3 4];\n%! assert (sort (A, 100), A);\n%! assert (sort (A, inf), A);\n%! [B, idx] = sort (A, 100);\n%! assert (B, A);\n%! assert (idx, ones (2));\n%! [B, idx] = sort (A, inf);\n%! assert (B, A);\n%! assert (idx, ones (2));\n\n%!error <Invalid call> sort ()\n%!error <Invalid call> sort (1, 2, 3, 4)\n%!error <MODE must be either \"ascend\" or \"descend\"> sort (1, \"foobar\")\n%!error <DIM must be a positive scalar integer> sort (1, [1 2 3])\n%!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], -inf)\n%!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], 0)\n%!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], 1+i)\n%!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], 1.234)\n%!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], NaN)\n%!error <DIM argument must precede MODE argument> sort (1, \"ascend\", 1)\n%!error <MODE must be a string> sort (1, 1, 1)\n%!error <MODE must be either \"ascend\" or \"descend\"> sort (1, 1, \"foobar\")\n%!error <DIM must be a positive scalar integer> sort (1, 0)\n\n*/\n\n// Sort the rows of the matrix @var{a} according to the order\n// specified by @var{mode}, which can either be 'ascend' or 'descend'\n// and return the index vector corresponding to the sort order.\n//\n// FIXME: This function does not yet support sparse matrices.\n\nDEFUN (__sort_rows_idx__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{idx} =} __sort_rows_idx__ (@var{A}, @var{mode})\nCalled internally from @file{sortrows.m}.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  if (nargin == 2 && ! args(1).is_string ())\n    error (\"__sort_rows_idx__: second argument must be a string\");\n\n  sortmode smode = ASCENDING;\n  if (nargin > 1)\n    {\n      std::string mode = args(1).string_value ();\n      if (mode == \"ascend\")\n        smode = ASCENDING;\n      else if (mode == \"descend\")\n        smode = DESCENDING;\n      else\n        error (R\"(__sort_rows_idx__: MODE must be either \"ascend\" or \"descend\")\");\n    }\n\n  octave_value arg = args(0);\n\n  if (arg.issparse ())\n    error (\"__sort_rows_idx__: sparse matrices not yet supported\");\n\n  if (arg.ndims () != 2)\n    error (\"__sort_rows_idx__: needs a 2-D object\");\n\n  Array<octave_idx_type> idx = arg.sort_rows_idx (smode);\n\n  // This cannot be ovl(), relies on special overloaded octave_value call.\n  return octave_value (idx, true, true);\n}\n\nstatic sortmode\nget_sort_mode_option (const octave_value& arg)\n{\n  // FIXME: we initialize to UNSORTED here to avoid a GCC warning\n  //        about possibly using sortmode uninitialized.\n  // FIXME: shouldn't these modes be scoped inside a class?\n  sortmode smode = UNSORTED;\n\n  std::string mode = arg.xstring_value (\"issorted: MODE must be a string\");\n\n  if (mode == \"ascend\")\n    smode = ASCENDING;\n  else if (mode == \"descend\")\n    smode = DESCENDING;\n  else if (mode == \"either\" || mode == \"monotonic\")\n    smode = UNSORTED;\n  else\n    error (R\"(issorted: MODE must be \"ascend\", \"descend\", \"monotonic\", or \"either\")\");\n\n  return smode;\n}\n\nDEFUN (issorted, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{tf} =} issorted (@var{A})\n@deftypefnx {} {@var{tf} =} issorted (@var{A}, @var{mode})\n@deftypefnx {} {@var{tf} =} issorted (@var{A}, \"rows\", @var{mode})\nReturn true if the vector @var{A} is sorted according to @var{mode}, which may\nbe either @qcode{\"ascend\"}, @qcode{\"descend\"}, @qcode{\"either\"}, or\n@qcode{\"monotonic\"} (@qcode{\"either\"} and @qcode{\"monotonic\"} are equivalent).\n\nBy default, @var{mode} is @qcode{\"ascend\"}.  NaNs are treated in the same manner\nas @code{sort}.\n\nIf the optional argument @qcode{\"rows\"} is supplied, check whether the matrix\nis sorted by rows as output by the function @code{sortrows} (with no options).\n@emph{Note:} the @qcode{\"rows\"} argument can not be used with sparse matrices.\n\n@seealso{sort, sortrows}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  bool by_rows = false;\n\n  sortmode smode = ASCENDING;\n\n  if (nargin > 1)\n    {\n      if (nargin == 3)\n        smode = get_sort_mode_option (args(2));\n\n      std::string tmp = args(1).xstring_value (\"issorted: second argument must be a string\");\n      if (tmp == \"rows\")\n        by_rows = true;\n      else\n        smode = get_sort_mode_option (args(1));\n    }\n\n  octave_value retval;\n\n  octave_value arg = args(0);\n\n  if (arg.isempty ())\n    retval = true;\n  else if (by_rows)\n    {\n      if (arg.issparse ())\n        error (\"issorted: sparse matrices not yet supported\");\n\n      if (arg.ndims () != 2)\n        error (\"issorted: A must be a 2-D object\");\n\n      retval = arg.is_sorted_rows (smode) != UNSORTED;\n    }\n  else\n    {\n      if (! arg.dims ().isvector ())\n        error (\"issorted: needs a vector\");\n\n      retval = args(0).issorted (smode) != UNSORTED;\n    }\n\n  return retval;\n}\n\n/*\n%!shared sm, um, sv, uv\n%! sm = [1, 2; 3, 4];\n%! um = [3, 1; 2, 4];\n%! sv = [1, 2, 3, 4];\n%! uv = [2, 1, 4, 3];\n\n%!assert (issorted (sm, \"rows\"))\n%!assert (! issorted (um, \"rows\"))\n%!assert (issorted (sv))\n%!assert (! issorted (uv))\n%!assert (issorted (sv'))\n%!assert (! issorted (uv'))\n%!assert (issorted (sm, \"rows\", \"ascend\"))\n%!assert (! issorted (um, \"rows\", \"ascend\"))\n%!assert (issorted (sv, \"ascend\"))\n%!assert (! issorted (uv, \"ascend\"))\n%!assert (issorted (sv', \"ascend\"))\n%!assert (! issorted (uv', \"ascend\"))\n%!assert (! issorted (sm, \"rows\", \"descend\"))\n%!assert (issorted (flipud (sm), \"rows\", \"descend\"))\n%!assert (! issorted (sv, \"descend\"))\n%!assert (issorted (fliplr (sv), \"descend\"))\n%!assert (! issorted (sv', \"descend\"))\n%!assert (issorted (fliplr (sv)', \"descend\"))\n%!assert (! issorted (um, \"rows\", \"either\"))\n%!assert (! issorted (uv, \"either\"))\n%!assert (issorted (sm, \"rows\", \"either\"))\n%!assert (issorted (flipud (sm), \"rows\", \"either\"))\n%!assert (issorted (sv, \"either\"))\n%!assert (issorted (fliplr (sv), \"either\"))\n%!assert (issorted (sv', \"either\"))\n%!assert (issorted (fliplr (sv)', \"either\"))\n%!assert (issorted (sm, \"rows\", \"monotonic\"))\n%!assert (issorted (flipud (sm), \"rows\", \"monotonic\"))\n%!assert (issorted (sv, \"either\"))\n%!assert (issorted (fliplr (sv), \"monotonic\"))\n%!assert (issorted (sv', \"either\"))\n%!assert (issorted (fliplr (sv)', \"monotonic\"))\n\n%!assert (issorted ([]))\n%!assert (issorted ([], \"rows\"))\n%!assert (issorted ([], \"ascend\"))\n%!assert (issorted ([], \"rows\", \"ascend\"))\n%!assert (issorted ([], \"descend\"))\n%!assert (issorted ([], \"rows\", \"descend\"))\n%!assert (issorted ({}))\n%!assert (issorted ({}, \"rows\"))\n%!assert (issorted ({}, \"ascend\"))\n%!assert (issorted ({}, \"rows\", \"ascend\"))\n%!assert (issorted ({}, \"descend\"))\n%!assert (issorted ({}, \"rows\", \"descend\"))\n%!assert (issorted (\"\"))\n%!assert (issorted (\"\", \"rows\"))\n%!assert (issorted (\"\", \"ascend\"))\n%!assert (issorted (\"\", \"rows\", \"ascend\"))\n%!assert (issorted (\"\", \"descend\"))\n%!assert (issorted (\"\", \"rows\", \"descend\"))\n\n## Test input validation\n%!error issorted ()\n%!error issorted (1,2,3,4)\n%!error <second argument must be a string> issorted (1, 2)\n%!error <second argument must be a string> issorted (1, {\"rows\"})\n%!error <sparse matrices not yet supported> issorted (sparse ([1 2 3]), \"rows\")\n%!error <A must be a 2-D object> issorted (rand (2,2,2), \"rows\")\n%!error <needs a vector> issorted (ones (2,2))\n*/\n\nDEFUN (nth_element, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{nel} =} nth_element (@var{x}, @var{n})\n@deftypefnx {} {@var{nel} =} nth_element (@var{x}, @var{n}, @var{dim})\nSelect the n-th smallest element of a vector, using the ordering defined by\n@code{sort}.\n\nThe result is equivalent to @code{sort(@var{x})(@var{n})}.\n\n@var{n} can also be a contiguous range, either ascending @code{l:u}\nor descending @code{u:-1:l}, in which case a range of elements is returned.\n\nIf @var{x} is an array, @code{nth_element} operates along the dimension\ndefined by @var{dim}, or the first non-singleton dimension if @var{dim} is\nnot given.\n\nProgramming Note: nth_element encapsulates the C++ standard library\nalgorithms nth_element and partial_sort.  On average, the complexity of the\noperation is O(M*log(K)), where @w{@code{M = size (@var{x}, @var{dim})}}@ and\n@w{@code{K = length (@var{n})}}.  This function is intended for cases where\nthe ratio K/M is small; otherwise, it may be better to use @code{sort}.\n@seealso{sort, min, max}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  int dim = -1;\n  if (nargin == 3)\n    {\n      dim = args(2).int_value (true) - 1;\n      if (dim < 0)\n        error (\"nth_element: DIM must be a valid dimension\");\n    }\n\n  octave_value argx = args(0);\n  if (dim < 0)\n    dim = argx.dims ().first_non_singleton ();\n\n  octave_value retval;\n\n  try\n    {\n      idx_vector n = args(1).index_vector ();\n\n      switch (argx.builtin_type ())\n        {\n        case btyp_double:\n          retval = argx.array_value ().nth_element (n, dim);\n          break;\n        case btyp_float:\n          retval = argx.float_array_value ().nth_element (n, dim);\n          break;\n        case btyp_complex:\n          retval = argx.complex_array_value ().nth_element (n, dim);\n          break;\n        case btyp_float_complex:\n          retval = argx.float_complex_array_value ().nth_element (n, dim);\n          break;\n\n#define MAKE_INT_BRANCH(X)                                              \\\n          case btyp_ ## X:                                              \\\n            retval = argx.X ## _array_value ().nth_element (n, dim);    \\\n            break;\n\n          MAKE_INT_BRANCH (int8);\n          MAKE_INT_BRANCH (int16);\n          MAKE_INT_BRANCH (int32);\n          MAKE_INT_BRANCH (int64);\n          MAKE_INT_BRANCH (uint8);\n          MAKE_INT_BRANCH (uint16);\n          MAKE_INT_BRANCH (uint32);\n          MAKE_INT_BRANCH (uint64);\n          MAKE_INT_BRANCH (bool);\n\n#undef MAKE_INT_BRANCH\n\n        default:\n          if (argx.iscellstr ())\n            retval = argx.cellstr_value ().nth_element (n, dim);\n          else\n            err_wrong_type_arg (\"nth_element\", argx);\n        }\n    }\n  catch (const index_exception& ie)\n    {\n      error (\"nth_element: invalid index %s\", ie.what ());\n    }\n\n  return retval;\n}\n\n/*\n%!assert (nth_element ([1:10], 1), 1)\n%!assert (nth_element ([1:10], 10), 10)\n%!assert (nth_element ([1:10], 1:3), [1 2 3])\n%!assert (nth_element ([1:10], 1:10), [1:10])\n\n%!assert <*51329> (nth_element ([1:10], [1:10]), [1:10])\n\n%!error nth_element ()\n%!error nth_element (1)\n%!error nth_element (1, 1.5)\n%!error nth_element (1, 2, 3, 4)\n%!error nth_element (\"abcd\", 3)\n*/\n\ntemplate <typename NDT>\nstatic NDT\ndo_accumarray_sum (const idx_vector& idx, const NDT& vals,\n                   octave_idx_type n = -1)\n{\n  typedef typename NDT::element_type T;\n  if (n < 0)\n    n = idx.extent (0);\n  else if (idx.extent (n) > n)\n    error (\"accumarray: index out of range\");\n\n  NDT retval (dim_vector (n, 1), T ());\n\n  if (vals.numel () == 1)\n    retval.idx_add (idx, vals (0));\n  else if (vals.numel () == idx.length (n))\n    retval.idx_add (idx, vals);\n  else\n    error (\"accumarray: dimensions mismatch\");\n\n  return retval;\n}\n\nDEFUN (__accumarray_sum__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {} __accumarray_sum__ (@var{idx}, @var{vals}, @var{n})\nUndocumented internal function.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  if (! args(0).isnumeric ())\n    error (\"__accumarray_sum__: first argument must be numeric\");\n\n  octave_value retval;\n\n  try\n    {\n      idx_vector idx = args(0).index_vector ();\n      octave_idx_type n = -1;\n      if (nargin == 3)\n        n = args(2).idx_type_value (true);\n\n      octave_value vals = args(1);\n\n      if (vals.is_range ())\n        {\n          range<double> r = vals.range_value ();\n          if (r.increment () == 0)\n            vals = r.base ();\n        }\n\n      if (vals.is_single_type ())\n        {\n          if (vals.iscomplex ())\n            retval = do_accumarray_sum (idx,\n                                        vals.float_complex_array_value (),\n                                        n);\n          else\n            retval = do_accumarray_sum (idx, vals.float_array_value (), n);\n        }\n      else if (vals.isnumeric () || vals.islogical ())\n        {\n          if (vals.iscomplex ())\n            retval = do_accumarray_sum (idx,\n                                        vals.complex_array_value (),\n                                        n);\n          else\n            retval = do_accumarray_sum (idx, vals.array_value (), n);\n        }\n      else\n        err_wrong_type_arg (\"accumarray\", vals);\n    }\n  catch (const index_exception& ie)\n    {\n      error (\"__accumarray_sum__: invalid index %s\", ie.what ());\n    }\n\n  return retval;\n}\n\ntemplate <typename NDT>\nstatic NDT\ndo_accumarray_minmax (const idx_vector& idx, const NDT& vals,\n                      octave_idx_type n, bool ismin,\n                      const typename NDT::element_type& zero_val)\n{\n  typedef typename NDT::element_type T;\n  if (n < 0)\n    n = idx.extent (0);\n  else if (idx.extent (n) > n)\n    error (\"accumarray: index out of range\");\n\n  NDT retval (dim_vector (n, 1), zero_val);\n\n  // Pick minimizer or maximizer.\n  void (MArray<T>::*op) (const idx_vector&, const MArray<T>&)\n    = ismin ? (&MArray<T>::idx_min) : (&MArray<T>::idx_max);\n\n  octave_idx_type l = idx.length (n);\n  if (vals.numel () == 1)\n    (retval.*op) (idx, NDT (dim_vector (l, 1), vals(0)));\n  else if (vals.numel () == l)\n    (retval.*op) (idx, vals);\n  else\n    error (\"accumarray: dimensions mismatch\");\n\n  return retval;\n}\n\nstatic octave_value_list\ndo_accumarray_minmax_fcn (const octave_value_list& args,\n                          bool ismin)\n{\n  int nargin = args.length ();\n\n  if (nargin < 3 || nargin > 4)\n    print_usage ();\n\n  if (! args(0).isnumeric ())\n    error (\"accumarray: first argument must be numeric\");\n\n  octave_value retval;\n\n  try\n    {\n      idx_vector idx = args(0).index_vector ();\n      octave_idx_type n = -1;\n      if (nargin == 4)\n        n = args(3).idx_type_value (true);\n\n      octave_value vals = args(1);\n      octave_value zero = args(2);\n\n      switch (vals.builtin_type ())\n        {\n        case btyp_double:\n          retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin,\n                                         zero.double_value ());\n          break;\n\n        case btyp_float:\n          retval = do_accumarray_minmax (idx, vals.float_array_value (), n,\n                                         ismin, zero.float_value ());\n          break;\n\n        case btyp_complex:\n          retval = do_accumarray_minmax (idx, vals.complex_array_value (),\n                                         n, ismin, zero.complex_value ());\n          break;\n\n        case btyp_float_complex:\n          retval = do_accumarray_minmax (idx,\n                                         vals.float_complex_array_value (),\n                                         n, ismin,\n                                         zero.float_complex_value ());\n          break;\n\n#define MAKE_INT_BRANCH(X)                                              \\\n          case btyp_ ## X:                                              \\\n            retval = do_accumarray_minmax (idx, vals.X ## _array_value (), \\\n                                           n, ismin, zero.X ## _scalar_value ()); \\\n            break;\n\n          MAKE_INT_BRANCH (int8);\n          MAKE_INT_BRANCH (int16);\n          MAKE_INT_BRANCH (int32);\n          MAKE_INT_BRANCH (int64);\n          MAKE_INT_BRANCH (uint8);\n          MAKE_INT_BRANCH (uint16);\n          MAKE_INT_BRANCH (uint32);\n          MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n        case btyp_bool:\n          retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin,\n                                         zero.bool_value ());\n          break;\n\n        default:\n          err_wrong_type_arg (\"accumarray\", vals);\n        }\n    }\n  catch (const index_exception& ie)\n    {\n      error (\"do_accumarray_minmax_fcn: invalid index %s\", ie.what ());\n    }\n\n  return retval;\n}\n\nDEFUN (__accumarray_min__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {} __accumarray_min__ (@var{idx}, @var{vals}, @var{zero}, @var{n})\nUndocumented internal function.\n@end deftypefn */)\n{\n  return do_accumarray_minmax_fcn (args, true);\n}\n\nDEFUN (__accumarray_max__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {} __accumarray_max__ (@var{idx}, @var{vals}, @var{zero}, @var{n})\nUndocumented internal function.\n@end deftypefn */)\n{\n  return do_accumarray_minmax_fcn (args, false);\n}\n\ntemplate <typename NDT>\nstatic NDT\ndo_accumdim_sum (const idx_vector& idx, const NDT& vals,\n                 int dim = -1, octave_idx_type n = -1)\n{\n  typedef typename NDT::element_type T;\n  if (n < 0)\n    n = idx.extent (0);\n  else if (idx.extent (n) > n)\n    error (\"accumdim: index out of range\");\n\n  const dim_vector& vals_dim = vals.dims ();\n  dim_vector rdv = vals_dim;\n\n  if (dim < 0)\n    dim = vals.dims ().first_non_singleton ();\n  else if (dim >= rdv.ndims ())\n    rdv.resize (dim+1, 1);\n\n  rdv(dim) = n;\n\n  NDT retval (rdv, T ());\n\n  if (idx.length () != vals_dim(dim))\n    error (\"accumdim: dimension mismatch\");\n\n  retval.idx_add_nd (idx, vals, dim);\n\n  return retval;\n}\n\nDEFUN (__accumdim_sum__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {} __accumdim_sum__ (@var{idx}, @var{vals}, @var{dim}, @var{n})\nUndocumented internal function.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n\n  if (! args(0).isnumeric ())\n    error (\"__accumdim_sum__: first argument must be numeric\");\n\n  octave_value retval;\n\n  try\n    {\n      idx_vector idx = args(0).index_vector ();\n      int dim = -1;\n      if (nargin >= 3)\n        dim = args(2).int_value () - 1;\n\n      octave_idx_type n = -1;\n      if (nargin == 4)\n        n = args(3).idx_type_value (true);\n\n      octave_value vals = args(1);\n\n      if (vals.is_single_type ())\n        {\n          if (vals.iscomplex ())\n            retval = do_accumdim_sum (idx,\n                                      vals.float_complex_array_value (),\n                                      dim, n);\n          else\n            retval = do_accumdim_sum (idx, vals.float_array_value (),\n                                      dim, n);\n        }\n      else if (vals.isnumeric () || vals.islogical ())\n        {\n          if (vals.iscomplex ())\n            retval = do_accumdim_sum (idx, vals.complex_array_value (),\n                                      dim, n);\n          else\n            retval = do_accumdim_sum (idx, vals.array_value (), dim, n);\n        }\n      else\n        err_wrong_type_arg (\"accumdim\", vals);\n    }\n  catch (const index_exception& ie)\n    {\n      error (\"__accumdim_sum__: invalid index %s\", ie.what ());\n    }\n\n  return retval;\n}\n\ntemplate <typename NDT>\nstatic NDT\ndo_merge (const Array<bool>& mask,\n          const NDT& tval, const NDT& fval)\n{\n  typedef typename NDT::element_type T;\n  const dim_vector& dv = mask.dims ();\n  NDT retval (dv);\n\n  bool tscl = tval.numel () == 1;\n  bool fscl = fval.numel () == 1;\n\n  if ((! tscl && tval.dims () != dv) || (! fscl && fval.dims () != dv))\n    error (\"merge: MASK, TVAL, and FVAL dimensions must match\");\n\n  T *rv = retval.rwdata ();\n  octave_idx_type n = retval.numel ();\n\n  const T *tv = tval.data ();\n  const T *fv = fval.data ();\n  const bool *mv = mask.data ();\n\n  if (tscl)\n    {\n      if (fscl)\n        {\n          T ts = tv[0];\n          T fs = fv[0];\n          for (octave_idx_type i = 0; i < n; i++)\n            rv[i] = (mv[i] ? ts : fs);\n        }\n      else\n        {\n          T ts = tv[0];\n          for (octave_idx_type i = 0; i < n; i++)\n            rv[i] = (mv[i] ? ts : fv[i]);\n        }\n    }\n  else\n    {\n      if (fscl)\n        {\n          T fs = fv[0];\n          for (octave_idx_type i = 0; i < n; i++)\n            rv[i] = (mv[i] ? tv[i] : fs);\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < n; i++)\n            rv[i] = (mv[i] ? tv[i] : fv[i]);\n        }\n    }\n\n  return retval;\n}\n\n#define MAKE_INT_BRANCH(INTX)                                           \\\n  else if (tval.is_ ## INTX ## _type () && fval.is_ ## INTX ## _type ()) \\\n    {                                                                   \\\n      retval = do_merge (mask,                                          \\\n                         tval.INTX ## _array_value (),                  \\\n                         fval.INTX ## _array_value ());                 \\\n    }\n\nDEFUN (merge, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{M} =} merge (@var{mask}, @var{tval}, @var{fval})\n@deftypefnx {} {@var{M} =} ifelse (@var{mask}, @var{tval}, @var{fval})\nMerge elements of @var{true_val} and @var{false_val}, depending on the\nvalue of @var{mask}.\n\nIf @var{mask} is a logical scalar, the other two arguments can be arbitrary\nvalues.  Otherwise, @var{mask} must be a logical array, and @var{tval},\n@var{fval} should be arrays of matching class, or cell arrays.  In the\nscalar mask case, @var{tval} is returned if @var{mask} is true, otherwise\n@var{fval} is returned.\n\nIn the array mask case, both @var{tval} and @var{fval} must be either\nscalars or arrays with dimensions equal to @var{mask}.  The result is\nconstructed as follows:\n\n@example\n@group\nresult(mask) = tval(mask);\nresult(! mask) = fval(! mask);\n@end group\n@end example\n\n@var{mask} can also be arbitrary numeric type, in which case it is first\nconverted to logical.\n\nProgramming Note: @code{ifelse} is an alias for @code{merge} and can be used\ninterchangeably.\n@seealso{logical, diff}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  if (! (args(0).islogical () || args(0).isnumeric ()))\n    error (\"merge: first argument must be logical or numeric\");\n\n  octave_value retval;\n\n  octave_value mask_val = args(0);\n\n  if (mask_val.is_scalar_type ())\n    retval = (mask_val.is_true () ? args(1) : args(2));\n  else\n    {\n      boolNDArray mask = mask_val.bool_array_value ();\n\n      octave_value tval = args(1);\n      octave_value fval = args(2);\n\n      if (tval.is_double_type () && fval.is_double_type ())\n        {\n          if (tval.iscomplex () || fval.iscomplex ())\n            retval = do_merge (mask,\n                               tval.complex_array_value (),\n                               fval.complex_array_value ());\n          else\n            retval = do_merge (mask,\n                               tval.array_value (),\n                               fval.array_value ());\n        }\n      else if (tval.is_single_type () && fval.is_single_type ())\n        {\n          if (tval.iscomplex () || fval.iscomplex ())\n            retval = do_merge (mask,\n                               tval.float_complex_array_value (),\n                               fval.float_complex_array_value ());\n          else\n            retval = do_merge (mask,\n                               tval.float_array_value (),\n                               fval.float_array_value ());\n        }\n      else if (tval.is_string () && fval.is_string ())\n        {\n          bool sq_string = tval.is_sq_string () || fval.is_sq_string ();\n          retval = octave_value (do_merge (mask,\n                                           tval.char_array_value (),\n                                           fval.char_array_value ()),\n                                 sq_string ? '\\'' : '\"');\n        }\n      else if (tval.iscell () && fval.iscell ())\n        {\n          retval = do_merge (mask,\n                             tval.cell_value (),\n                             fval.cell_value ());\n        }\n\n      MAKE_INT_BRANCH (int8)\n      MAKE_INT_BRANCH (int16)\n      MAKE_INT_BRANCH (int32)\n      MAKE_INT_BRANCH (int64)\n      MAKE_INT_BRANCH (uint8)\n      MAKE_INT_BRANCH (uint16)\n      MAKE_INT_BRANCH (uint32)\n      MAKE_INT_BRANCH (uint64)\n\n      else\n        error (\"merge: cannot merge %s with %s with array mask\",\n               tval.class_name ().c_str (),\n               fval.class_name ().c_str ());\n    }\n\n  return retval;\n}\n\nDEFALIAS (ifelse, merge);\n\n#undef MAKE_INT_BRANCH\n\ntemplate <typename SparseT>\nstatic SparseT\ndo_sparse_diff (const SparseT& array, octave_idx_type order,\n                int dim)\n{\n  SparseT retval = array;\n  if (dim == 1)\n    {\n      octave_idx_type k = retval.columns ();\n      while (order > 0 && k > 0)\n        {\n          idx_vector col1 (':'), col2 (':'), sl1 (1, k), sl2 (0, k-1);\n          retval = SparseT (retval.index (col1, sl1))\n                   - SparseT (retval.index (col2, sl2));\n          panic_unless (retval.columns () == k-1);\n          order--;\n          k--;\n        }\n    }\n  else\n    {\n      octave_idx_type k = retval.rows ();\n      while (order > 0 && k > 0)\n        {\n          idx_vector col1 (':'), col2 (':'), sl1 (1, k), sl2 (0, k-1);\n          retval = SparseT (retval.index (sl1, col1))\n                   - SparseT (retval.index (sl2, col2));\n          panic_unless (retval.rows () == k-1);\n          order--;\n          k--;\n        }\n    }\n\n  return retval;\n}\n\nstatic octave_value\ndo_diff (const octave_value& array, octave_idx_type order,\n         int dim = -1)\n{\n  octave_value retval;\n\n  const dim_vector& dv = array.dims ();\n  if (dim == -1)\n    {\n      dim = array.dims ().first_non_singleton ();\n\n      // Bother Matlab.  This behavior is really wicked.\n      if (dv(dim) <= order)\n        {\n          if (dv(dim) == 1)\n            retval = array.resize (dim_vector (0, 0));\n          else\n            {\n              retval = array;\n              while (order > 0)\n                {\n                  if (dim == dv.ndims ())\n                    {\n                      retval = do_diff (array, order, dim - 1);\n                      order = 0;\n                    }\n                  else if (dv(dim) == 1)\n                    dim++;\n                  else\n                    {\n                      retval = do_diff (array, dv(dim) - 1, dim);\n                      order -= dv(dim) - 1;\n                      dim++;\n                    }\n                }\n            }\n\n          return retval;\n        }\n    }\n\n  if (array.isinteger ())\n    {\n      if (array.is_int8_type ())\n        retval = array.int8_array_value ().diff (order, dim);\n      else if (array.is_int16_type ())\n        retval = array.int16_array_value ().diff (order, dim);\n      else if (array.is_int32_type ())\n        retval = array.int32_array_value ().diff (order, dim);\n      else if (array.is_int64_type ())\n        retval = array.int64_array_value ().diff (order, dim);\n      else if (array.is_uint8_type ())\n        retval = array.uint8_array_value ().diff (order, dim);\n      else if (array.is_uint16_type ())\n        retval = array.uint16_array_value ().diff (order, dim);\n      else if (array.is_uint32_type ())\n        retval = array.uint32_array_value ().diff (order, dim);\n      else if (array.is_uint64_type ())\n        retval = array.uint64_array_value ().diff (order, dim);\n      else\n        error (\"diff: unexpected integer type - please report this bug\");\n    }\n  else if (array.issparse ())\n    {\n      if (array.iscomplex ())\n        retval = do_sparse_diff (array.sparse_complex_matrix_value (),\n                                 order, dim);\n      else\n        retval = do_sparse_diff (array.sparse_matrix_value (), order, dim);\n    }\n  else if (array.is_single_type ())\n    {\n      if (array.iscomplex ())\n        retval = array.float_complex_array_value ().diff (order, dim);\n      else\n        retval = array.float_array_value ().diff (order, dim);\n    }\n  else\n    {\n      if (array.iscomplex ())\n        retval = array.complex_array_value ().diff (order, dim);\n      else\n        retval = array.array_value ().diff (order, dim);\n    }\n\n  return retval;\n}\n\nDEFUN (diff, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} diff (@var{x})\n@deftypefnx {} {@var{y} =} diff (@var{x}, @var{k})\n@deftypefnx {} {@var{y} =} diff (@var{x}, @var{k}, @var{dim})\nIf @var{x} is a vector of length @math{n}, @w{@code{diff (@var{x})}}@ is the\nvector of first differences\n@tex\n $x_2 - x_1, \\ldots{}, x_n - x_{n-1}$.\n@end tex\n@ifnottex\n @var{x}(2) - @var{x}(1), @dots{}, @var{x}(n) - @var{x}(n-1).\n@end ifnottex\n\nIf @var{x} is a matrix, @w{@code{diff (@var{x})}}@ is the matrix of column\ndifferences along the first non-singleton dimension.\n\nThe second argument is optional.  If supplied,\n@w{@code{diff (@var{x}, @var{k})}}, where @var{k} is a non-negative integer,\nreturns the @var{k}-th differences.  It is possible that @var{k} is larger than\nthe first non-singleton dimension of the matrix.  In this case, @code{diff}\ncontinues to take the differences along the next non-singleton dimension.\n\nThe dimension along which to take the difference can be explicitly stated with\nthe optional variable @var{dim}.  In this case the @var{k}-th order differences\nare calculated along this dimension.  In the case where @var{k} exceeds\n@w{@code{size (@var{x}, @var{dim})}}@ an empty matrix is returned.\n@seealso{sort, merge}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  if (! (args(0).isnumeric () || args(0).islogical ()))\n    error (\"diff: X must be numeric or logical\");\n\n  int dim = -1;\n  octave_idx_type order = 1;\n  if (nargin > 1)\n    {\n      if (args(1).is_scalar_type ())\n        order = args(1).idx_type_value (true, false);\n      else if (! args(1).is_zero_by_zero ())\n        error (\"diff: order K must be a scalar or []\");\n      if (order < 0)\n        error (\"diff: order K must be non-negative\");\n    }\n\n  if (nargin > 2)\n    {\n      dim = args(2).int_value (true, false);\n      if (dim < 1 || dim > args(0).ndims ())\n        error (\"diff: DIM must be a valid dimension\");\n\n      dim -= 1;\n    }\n\n  return do_diff (args(0), order, dim);\n}\n\n/*\n%!assert (diff ([1, 2, 3, 4]), [1, 1, 1])\n%!assert (diff ([1, 3, 7, 19], 2), [2, 8])\n%!assert (diff ([1, 2; 5, 4; 8, 7; 9, 6; 3, 1]), [4, 2; 3, 3; 1, -1; -6, -5])\n%!assert (diff ([1, 2; 5, 4; 8, 7; 9, 6; 3, 1], 3), [-1, -5; -5, 0])\n%!assert (isempty (diff (1)))\n\n%!error diff ()\n%!error diff (1, 2, 3, 4)\n%!error diff (\"foo\")\n%!error diff ([1, 2; 3, 4], -1)\n*/\n\ntemplate <typename T>\nstatic Array<T>\ndo_repelems (const Array<T>& src, const Array<octave_idx_type>& rep)\n{\n  Array<T> retval;\n\n  if (rep.ndims () != 2 || rep.rows () != 2)\n    error (\"repelems: R must be a 2-row, N-column matrix of integers\");\n\n  octave_idx_type n = rep.columns ();\n  octave_idx_type l = 0;\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      octave_idx_type k = rep(1, i);\n      if (k < 0)\n        error (\"repelems: second row must contain non-negative numbers\");\n\n      l += k;\n    }\n\n  retval.clear (1, l);\n  T *dest = retval.rwdata ();\n  l = 0;\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      octave_idx_type k = rep(1, i);\n      std::fill_n (dest, k, src.checkelem (rep(0, i) - 1));\n      dest += k;\n    }\n\n  return retval;\n}\n\nDEFUN (repelems, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} repelems (@var{x}, @var{r})\nConstruct a vector of repeated elements from @var{x}.\n\n@var{r} is a 2x@var{N} integer matrix specifying which elements to repeat\nand how often to repeat each element.  Entries in the first row,\n@var{r}(1,j), select an element to repeat.  The corresponding entry in the\nsecond row, @var{r}(2,j), specifies the repeat count.  If @var{x} is a\nmatrix then the columns of @var{x} are imagined to be stacked on top of\neach other for purposes of the selection index.  A row vector is always\nreturned.\n\nConceptually the result is calculated as follows:\n\n@example\n@group\ny = [];\nfor i = 1:columns (@var{r})\n  y = [y, @var{x}(@var{r}(1,i)*ones(1, @var{r}(2,i)))];\nendfor\n@end group\n@end example\n@seealso{repmat, cat}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value retval;\n\n  const Matrix rm = args(1).matrix_value ();\n\n  if (rm.rows () != 2 || rm.ndims () != 2)\n    error (\"repelems: R must be a matrix with two rows\");\n\n  octave_value x = args(0);\n\n  Array<octave_idx_type> r (rm.dims ());\n\n  for (octave_idx_type i = 0; i < rm.numel (); i++)\n    {\n      octave_idx_type rx = rm(i);\n      if (static_cast<double> (rx) != rm(i))\n        error (\"repelems: R must be a matrix of integers\");\n\n      r.xelem (i) = rx;\n    }\n\n  switch (x.builtin_type ())\n    {\n#define BTYP_BRANCH(X, EX)                              \\\n      case btyp_ ## X:                                  \\\n        retval = do_repelems (x.EX ## _value (), r);    \\\n        break;\n\n      BTYP_BRANCH (double, array);\n      BTYP_BRANCH (float, float_array);\n      BTYP_BRANCH (complex, complex_array);\n      BTYP_BRANCH (float_complex, float_complex_array);\n      BTYP_BRANCH (bool, bool_array);\n      BTYP_BRANCH (char, char_array);\n\n      BTYP_BRANCH (int8,  int8_array);\n      BTYP_BRANCH (int16, int16_array);\n      BTYP_BRANCH (int32, int32_array);\n      BTYP_BRANCH (int64, int64_array);\n      BTYP_BRANCH (uint8,  uint8_array);\n      BTYP_BRANCH (uint16, uint16_array);\n      BTYP_BRANCH (uint32, uint32_array);\n      BTYP_BRANCH (uint64, uint64_array);\n\n      case btyp_cell:\n        retval = Cell (do_repelems (x.cell_value (), r));\n        break;\n\n      //BTYP_BRANCH (struct, map);//FIXME\n\n#undef BTYP_BRANCH\n\n    default:\n      err_wrong_type_arg (\"repelems\", x);\n    }\n\n  return retval;\n}\n\nDEFUN (base64_encode, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{s} =} base64_encode (@var{x})\nEncode a double matrix or array @var{x} into the base64 format string\n@var{s}.\n\n@seealso{base64_decode, matlab.net.base64decode, matlab.net.base64encode}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  if (! args(0).isnumeric ())\n    error (\"base64_encode: encoding is supported only for numeric arrays\");\n\n  if (args(0).iscomplex () || args(0).issparse ())\n    error (\"base64_encode: encoding complex or sparse data is not supported\");\n\n  octave_value_list retval;\n\n  if (args(0).isinteger ())\n    {\n#define MAKE_INT_BRANCH(X)                                              \\\n      if (args(0).is_ ## X ## _type ())                                 \\\n        {                                                               \\\n          const X##NDArray in = args(0).  X## _array_value ();          \\\n          std::size_t inlen = in.numel () * sizeof (X## _t) / sizeof (char); \\\n          const char *inc = reinterpret_cast<const char *> (in.data ()); \\\n          char *out;                                                    \\\n          if (base64_encode (inc, inlen, &out))                         \\\n            {                                                           \\\n              retval(0) = octave_value (out);                           \\\n              ::free (out);                                             \\\n            }                                                           \\\n        }\n\n      MAKE_INT_BRANCH(int8)\n      else MAKE_INT_BRANCH(int16)\n        else MAKE_INT_BRANCH(int32)\n          else MAKE_INT_BRANCH(int64)\n            else MAKE_INT_BRANCH(uint8)\n              else MAKE_INT_BRANCH(uint16)\n                else MAKE_INT_BRANCH(uint32)\n                  else MAKE_INT_BRANCH(uint64)\n\n#undef MAKE_INT_BRANCH\n\n                    else\n                      error (\"base_64_decode: unexpected integer type - please report this bug\");\n    }\n  else if (args(0).is_single_type ())\n    {\n      const Array<float> in = args(0).float_array_value ();\n      std::size_t inlen;\n      inlen = in.numel () * sizeof (float) / sizeof (char);\n      const char *inc;\n      inc = reinterpret_cast<const char *> (in.data ());\n      char *out;\n      if (base64_encode (inc, inlen, &out))\n        {\n          retval(0) = octave_value (out);\n          ::free (out);\n        }\n    }\n  else  // double_type\n    {\n      const Array<double> in = args(0).array_value ();\n      std::size_t inlen;\n      inlen = in.numel () * sizeof (double) / sizeof (char);\n      const char *inc;\n      inc = reinterpret_cast<const char *> (in.data ());\n      char *out;\n      if (base64_encode (inc, inlen, &out))\n        {\n          retval(0) = octave_value (out);\n          ::free (out);\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! ## FIXME: better test for endianness?\n%! if (bitunpack (uint16 (1))(1) == 1)\n%!   expected = \"2w9JQA==\";\n%! else\n%!   expected = \"QEkP2w==\";\n%! endif\n%! assert (base64_encode (single (pi)), expected);\n\n%!assert (base64_encode (uint8 ([0 0 0])), \"AAAA\")\n%!assert (base64_encode (uint16 ([0 0 0])), \"AAAAAAAA\")\n%!assert (base64_encode (uint32 ([0 0 0])), \"AAAAAAAAAAAAAAAA\")\n%!assert (base64_encode (uint64 ([0 0 0])), \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\")\n%!assert (base64_encode (uint8 ([255 255 255])), \"////\")\n\n%!error base64_encode ()\n%!error base64_encode (1,2)\n%!error base64_encode (\"A string\")\n%!error base64_encode ({\"A cell array\"})\n%!error base64_encode (struct ())\n*/\n\nDEFUN (base64_decode, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} base64_decode (@var{s})\n@deftypefnx {} {@var{x} =} base64_decode (@var{s}, @var{dims})\nDecode the double matrix or array @var{x} from the base64 encoded string\n@var{s}.\n\nThe optional input parameter @var{dims} should be a vector containing the\ndimensions of the decoded array.\n@seealso{base64_encode, matlab.net.base64decode, matlab.net.base64encode}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string str = args(0).xstring_value (\"base64_decode: first argument must be a character array\");\n\n  Array<double> retval = base64_decode (str);\n\n  if (nargin == 2)\n    {\n      dim_vector dims;\n\n      const Array<octave_idx_type> size\n        = args(1).octave_idx_type_vector_value ();\n\n      dims = dim_vector::alloc (size.numel ());\n      for (octave_idx_type i = 0; i < size.numel (); i++)\n        dims(i) = size(i);\n\n      retval = retval.reshape (dims);\n    }\n\n  return ovl (retval);\n}\n\n/*\n%!assert (base64_decode (base64_encode (pi)), pi)\n%!\n%!test\n%! in   = randn (10);\n%! outv = base64_decode (base64_encode (in));\n%! outm = base64_decode (base64_encode (in), size (in));\n%! assert (outv, in(:).');\n%! assert (outm, in);\n\n%!error base64_decode ()\n%!error base64_decode (1,2,3)\n%!error base64_decode (1, \"this is not a valid set of dimensions\")\n%!error <first argument must be a character array> base64_decode (1)\n%!error <input was not valid base64> base64_decode (\"AQ=\")\n%!error <incorrect input size> base64_decode (\"AQ==\")\n*/\n\nDEFUN (__base64_decode_bytes__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} base64_decode_bytes (@var{s})\n@deftypefnx {} {@var{x} =} base64_decode_bytes (@var{s}, @var{dims})\nDecode the uint8 matrix or array @var{x} from the base64 encoded string\n@var{s}.\n\nThe optional input parameter @var{dims} should be a vector containing the\ndimensions of the decoded array.\n@seealso{base64_decode}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string str = args(0).xstring_value (\"__base64_decode_bytes__: first argument must be a character array\");\n\n  intNDArray<octave_uint8> retval = base64_decode_bytes (str);\n\n  if (nargin == 2)\n    {\n      dim_vector dims;\n\n      const Array<octave_idx_type> size\n        = args(1).octave_idx_type_vector_value ();\n\n      dims = dim_vector::alloc (size.numel ());\n      for (octave_idx_type i = 0; i < size.numel (); i++)\n        dims(i) = size(i);\n\n      retval = retval.reshape (dims);\n    }\n\n  return ovl (retval);\n}\n\n/*\n%!assert (__base64_decode_bytes__ (base64_encode (uint8 (1))), uint8 (1))\n\n%!test\n%! in   = uint8 (rand (10)*255);\n%! outv = __base64_decode_bytes__ (base64_encode (in));\n%! outm = __base64_decode_bytes__ (base64_encode (in), size (in));\n%! assert (outv, in(:).');\n%! assert (outm, in);\n\n%!error __base64_decode_bytes__ ()\n%!error __base64_decode_bytes__ (1,2,3)\n%!error __base64_decode_bytes__ (1, \"this is not a valid set of dimensions\")\n%!error <first argument must be a character array> __base64_decode_bytes__ (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/data.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_data_h)\n#define octave_data_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API octave_value\ndo_class_concat (const octave_value_list& ovl, const std::string& cattype,\n                 int dim);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/debug.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iomanip>\n#include <iostream>\n#include <limits>\n#include <string>\n\n#include \"dNDArray.h\"\n\n#include \"bp-table.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"file-ops.h\"\n#include \"help.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"oct-sysdep.h\"\n#include \"octave-preserve-stream-state.h\"\n#include \"ov-usr-fcn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"pt-eval.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic octave_value\nbp_lines_to_ov (const octave::bp_table::bp_lines& lines)\n{\n  int idx = 0;\n\n  NDArray retval (dim_vector (1, lines.size ()));\n\n  for (const auto& lineno : lines)\n    retval(idx++) = lineno;\n\n  retval.resize (dim_vector (1, idx));\n\n  return retval;\n}\n\nDEFMETHOD (dbstop, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dbstop @var{fcn}\n@deftypefnx {} {} dbstop @var{fcn} @var{line}\n@deftypefnx {} {} dbstop @var{fcn} @var{line1} @var{line2} @dots{}\n@deftypefnx {} {} dbstop @var{line1} @dots{}\n@deftypefnx {} {} dbstop in @var{fcn}\n@deftypefnx {} {} dbstop in @var{fcn} at @var{line}\n@deftypefnx {} {} dbstop in @var{fcn} at @var{line} if \"@var{condition}\"\n@deftypefnx {} {} dbstop in @var{class} at @var{method}\n@deftypefnx {} {} dbstop if @var{event}\n@deftypefnx {} {} dbstop if @var{event} @var{ID}\n@deftypefnx {} {} dbstop (@var{bp_struct})\n@deftypefnx {} {@var{rline} =} dbstop (@dots{})\n\nSet breakpoints for the built-in debugger.\n\n@var{fcn} is the name of a function on the current @code{path}.  When\nalready in debug mode the @var{fcn} argument can be omitted and the current\nfunction will be used.  Breakpoints at subfunctions are set with the scope\noperator @samp{>}.  For example, If @file{file.m} has a subfunction\n@code{fcn2}, then a breakpoint in @code{fcn2} can be specified by\n@code{file>fcn2}.\n\n@var{line} is the line number at which to break.  If @var{line} is not\nspecified, it defaults to the first executable line in the file\n@file{fcn.m}.  Multiple lines can be specified in a single command; when\nfunction syntax is used, the lines may also be passed as a single vector\nargument (@code{[@var{line1}, @var{line2}, @dots{}]}).\n\n@var{condition} is any Octave expression that can be evaluated in the code\ncontext that exists at the breakpoint.  When the breakpoint is encountered,\n@var{condition} will be evaluated, and execution will stop if\n@var{condition} is true.  If @var{condition} cannot be evaluated, for\nexample because it refers to an undefined variable, an error will be thrown.\nExpressions with side effects (such as @code{y++ > 1}) will alter variables,\nand should generally be avoided.  Conditions containing quotes (@samp{\"},\n@samp{'}) or comment characters (@samp{#}, @samp{%}) must be enclosed in\nquotes.  (This does not apply to conditions entered from the editor's context\nmenu.)  For example:\n\n@example\ndbstop in axis at 246 if 'any (opt == \"x\")'\n@end example\n\nThe form specifying @var{event} does not cause a specific breakpoint at a given\nfunction and line number.  Instead it causes debug mode to be entered when\ncertain unexpected events are encountered.  Possible values are\n\n@table @code\n@item error\nStop when an error is reported.  This is equivalent to specifying both\n@code{debug_on_error (true)} and @code{debug_on_interrupt (true)}.\n\n@item caught error\nStop when an error is caught by a try-catch block (not yet implemented).\n\n@item interrupt\nStop when an interrupt (@kbd{Ctrl-C}) occurs.\n\n@item naninf\nStop when code returns a non-finite value (not yet implemented).\n\n@item warning\nStop when a warning is reported.  This is equivalent to specifying\n@code{debug_on_warning (true)}.\n@end table\n\nThe events @code{error}, @code{caught error}, and @code{warning} can all be\nfollowed by a string specifying an error ID or warning ID@.  If that is done,\nonly errors with the specified ID will cause execution to stop.  To stop on one\nof a set of IDs, multiple @code{dbstop} commands must be issued.\n\nBreakpoints and events can be removed using the @code{dbclear} command with\nthe same syntax.\n\nIt is possible to save all breakpoints and restore them at once by issuing\nthe commands @code{bp_state = dbstatus; @dots{}; dbstop (bp_state)}.\n\nThe optional output @var{rline} is the real line number where the breakpoint\nwas set.  This can differ from the specified line if the line is not\nexecutable.  For example, if a breakpoint attempted on a blank line then Octave\nwill set the real breakpoint at the next executable line.\n\nWhen a file is re-parsed, such as when it is modified outside the GUI, all\nbreakpoints within the file are cleared.\n\n@seealso{dbclear, dbstatus, dbstep, debug_on_error, debug_on_warning,\ndebug_on_interrupt}\n@end deftypefn */)\n{\n  octave::bp_table::bp_lines retmap;\n  std::string symbol_name = \"\";  // stays empty for \"dbstop if error\" etc\n  std::string class_name = \"\";\n  octave::bp_table::bp_lines lines;\n  std::string condition = \"\";\n  octave_value retval;\n\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  octave::bp_table& bptab = tw.get_bp_table ();\n\n  if (args.length() >= 1 && ! args(0).isstruct ())\n    {\n      // explicit function / line / condition\n      bptab.parse_dbfunction_params (\"dbstop\", args, symbol_name,\n                                     class_name, lines, condition);\n\n      if (lines.size () == 0)\n        lines.insert (-1);\n\n      if (symbol_name != \"\")\n        {\n          std::string fcn_ident;\n          if (class_name.empty ())\n            fcn_ident = symbol_name;\n          else\n            fcn_ident = \"@\" + class_name + \"/\" + symbol_name;\n\n          retmap = bptab.add_breakpoints_in_function (fcn_ident, lines,\n                                                      condition);\n          retval = bp_lines_to_ov (retmap);\n        }\n    }\n  else if (args.length () != 1)\n    {\n      print_usage ();\n    }\n  else  // structure of the form output by dbstatus\n    {\n      octave_map mv = args(0).map_value ();\n      if (mv.isfield (\"bkpt\") || mv.isfield (\"errs\") || mv.isfield (\"warn\")\n          || mv.isfield (\"intr\"))\n        {\n          bptab.dbstop_process_map_args (mv);\n\n          // Replace mv by \"bkpt\", to use the processing below.\n          octave_value bkpt = mv.getfield (\"bkpt\");\n          if (bkpt.isempty ())\n            mv = octave_map ();\n          else\n            {\n              if (bkpt.iscell () && bkpt.cell_value ().numel () > 0\n                  && bkpt.cell_value () (0).isstruct ())\n                mv = bkpt.cell_value () (0).map_value ();\n              else\n                error (\"dbstop: invalid 'bkpt' field\");\n            }\n        }\n      if (mv.isempty ())\n        {\n          // no changes requested.  Occurs if \"errs\" non-empty but \"bkpt\" empty\n        }\n      else if (! mv.isfield (\"name\") || ! mv.isfield (\"line\"))\n        {\n          error (\"dbstop: Cell array must contain fields 'name' and 'line'\");\n        }\n      else\n        {\n          bool use_cond = mv.isfield (\"cond\");\n          Cell name = mv.getfield (\"name\");\n          Cell line = mv.getfield (\"line\");\n          Cell cond = (use_cond ? mv.getfield (\"cond\") : Cell ());\n          std::string unconditional = \"\";\n          for (octave_idx_type i = 0; i < line.numel (); i++)\n            {\n              // FIXME: This isn't very clear, but add_breakpoints_in_function\n              // requires this argument to be of type bp_table::bp_lines type\n              // which is std::set<int>.\n              lines.clear ();\n              lines.insert (line(i).int_value ());\n              bptab.add_breakpoints_in_function (name(i).string_value (),\n                                                 lines,\n                                                 (use_cond\n                                                  ? cond(i).string_value ()\n                                                  : unconditional));\n            }\n          retval = octave_value (line.numel ());\n        }\n    }\n\n  // If we add a breakpoint, we also need to reset debug_mode.\n  tw.reset_debug_state ();\n\n  return retval;\n}\n\nDEFMETHOD (dbclear, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dbclear @var{fcn}\n@deftypefnx {} {} dbclear @var{fcn} @var{line}\n@deftypefnx {} {} dbclear @var{fcn} @var{line1} @var{line2} @dots{}\n@deftypefnx {} {} dbclear @var{line} @dots{}\n@deftypefnx {} {} dbclear all\n@deftypefnx {} {} dbclear in @var{fcn}\n@deftypefnx {} {} dbclear in @var{fcn} at @var{line}\n@deftypefnx {} {} dbclear if @var{event}\n@deftypefnx {} {} dbclear (\"@var{fcn}\")\n@deftypefnx {} {} dbclear (\"@var{fcn}\", @var{line})\n@deftypefnx {} {} dbclear (\"@var{fcn}\", @var{line1}, @var{line2}, @dots{})\n@deftypefnx {} {} dbclear (\"@var{fcn}\", @var{line1}, @dots{})\n@deftypefnx {} {} dbclear (@var{line}, @dots{})\n@deftypefnx {} {} dbclear (\"all\")\nDelete a breakpoint at line number @var{line} in the function @var{fcn}.\n\nArguments are\n\n@table @var\n@item fcn\nFunction name as a string variable.  When already in debug mode this\nargument can be omitted and the current function will be used.\n\n@item line\nLine number from which to remove a breakpoint.  Multiple lines may be given\nas separate arguments or as a vector.\n\n@item event\nAn event such as @code{error}, @code{interrupt}, or @code{warning}\n(@pxref{XREFdbstop,,@code{dbstop}} for details).\n@end table\n\nWhen called without a line number specification all breakpoints in the named\nfunction are cleared.\n\nIf the requested line is not a breakpoint no action is performed.\n\nThe special keyword @qcode{\"all\"} will clear all breakpoints from all\nfiles.\n@seealso{dbstop, dbstatus, dbwhere}\n@end deftypefn */)\n{\n  std::string symbol_name = \"\";  // stays empty for \"dbclear if error\" etc\n  std::string class_name = \"\";\n  octave::bp_table::bp_lines lines;\n  std::string dummy;             // \"if\" condition -- only used for dbstop\n\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  octave::bp_table& bptab = tw.get_bp_table ();\n\n  bptab.parse_dbfunction_params (\"dbclear\", args, symbol_name, class_name,\n                                 lines, dummy);\n\n  if (args.length () == 1 && symbol_name == \"all\")\n    {\n      bptab.remove_all_breakpoints ();\n      bptab.dbclear_all_signals ();\n    }\n  else if (symbol_name != \"\")\n    {\n      std::string fcn_ident;\n      if (class_name.empty ())\n        fcn_ident = symbol_name;\n      else\n        fcn_ident = \"@\" + class_name + \"/\" + symbol_name;\n\n      bptab.remove_breakpoints_from_function (fcn_ident, lines);\n    }\n\n  // If we remove a breakpoint, we also need to reset debug_mode.\n  tw.reset_debug_state ();\n\n  return ovl ();\n}\n\nDEFMETHOD (dbstatus, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dbstatus\n@deftypefnx {} {} dbstatus @var{fcn}\n@deftypefnx {} {@var{bp_list} =} dbstatus ()\n@deftypefnx {} {@var{bp_list} =} dbstatus (@var{fcn})\nReport the location of active breakpoints.\n\nWhen called with no input or output arguments, print the list of all\nfunctions with breakpoints and the line numbers where those breakpoints are\nset.\n\nIf a function name @var{fcn} is specified then only report breakpoints\nfor the named function and its subfunctions.\n\nThe optional return argument @var{bp_list} is a struct array with the\nfollowing fields:\n\n@table @asis\n@item name\nThe name of the function with a breakpoint.  A subfunction, say @code{fcn2}\nwithin an m-file, say @file{file.m}, is specified as @code{file>fcn2}.\n\n@item file\nThe name of the m-file where the function code is located.\n\n@item line\nThe line number with the breakpoint.\n\n@item cond\nThe condition that must be satisfied for the breakpoint to be active, or\nthe empty string for unconditional breakpoints.\n@end table\n\n@c Note: When @code{dbstatus} is called from the debug prompt within a function,\n@c the list of breakpoints is automatically trimmed to the breakpoints in the\n@c current function.\nIf @code{dbstop if error} is true but no explicit IDs are specified, the\nreturn value will have an empty field called @qcode{\"errs\"}.  If IDs are\nspecified, the @code{errs} field will have one row per ID@.  If\n@code{dbstop if error} is false, there is no @qcode{\"errs\"} field.\nThe @qcode{\"warn\"} field is set similarly by @code{dbstop if warning}.\n\n@seealso{dbstop, dbclear, dbwhere, dblist, dbstack}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin != 0 && nargin != 1)\n    error (\"dbstatus: only zero or one arguments accepted\\n\");\n\n  octave_value_list fcn_list;\n  octave::bp_table::fname_bp_map bp_list;\n  std::string symbol_name;\n\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  octave::bp_table& bptab = tw.get_bp_table ();\n\n  if (nargin == 1)\n    {\n      if (! args(0).is_string ())\n        err_wrong_type_arg (\"dbstatus\", args(0));\n\n      symbol_name = args(0).string_value ();\n      fcn_list(0) = symbol_name;\n      bp_list = bptab.get_breakpoint_list (fcn_list);\n    }\n  else\n    {\n      /*\n            if (tw.in_debug_repl ())\n              {\n                octave_user_code *dbg_fcn = tw.get_user_code ();\n                if (dbg_fcn)\n                  {\n                    symbol_name = dbg_fcn->name ();\n                    fcn_list(0) = symbol_name;\n                  }\n              }\n      */\n\n      bp_list = bptab.get_breakpoint_list (fcn_list);\n    }\n\n  if (nargout == 0)\n    {\n      // Print out the breakpoint information.\n\n      for (auto& fnm_bp_p: bp_list)\n        {\n          std::list<octave::bp_type> m = fnm_bp_p.second;\n\n          // print unconditional breakpoints, if any, on a single line\n\n          // first, check to see if there are any\n          int have_unconditional = 0;\n          for (const auto& bp : m)\n            {\n              if (bp.cond == \"\")\n                {\n                  if (have_unconditional++)\n                    break;                   // stop once we know its plural\n                }\n            }\n          // If we actually have some, print line numbers only\n          if (have_unconditional)\n            {\n              const char *_s_ = (have_unconditional > 1) ? \"s\" : \"\";\n              octave_stdout << \"breakpoint\" << _s_ << \" in \" << fnm_bp_p.first\n                            << \" at line\" << _s_ << ' ';\n\n              for (const auto& bp : m)\n                {\n                  if (bp.cond == \"\")\n                    octave_stdout << bp.line << ' ';\n                }\n              octave_stdout << std::endl;\n            }\n\n          // print conditional breakpoints, one per line, with conditions\n          for (const auto& bp : m)\n            {\n              if (bp.cond != \"\")\n                octave_stdout << \"breakpoint in \" << fnm_bp_p.first\n                              << \" at line \" << bp.line\n                              << \" if \" << bp.cond << \"\\n\";\n            }\n        }\n\n      bptab.stop_on_err_warn_status (true);\n\n      return ovl ();\n    }\n  else\n    {\n      octave::help_system& help_sys = interp.get_help_system ();\n\n      // Fill in an array for return.\n      int i = 0;\n      octave_map retmap;\n      octave_value retval;\n\n      // count the number of breakpoints in all files\n      int count = 0;\n      for (const auto& fnm_bp_p : bp_list)\n        count += fnm_bp_p.second.size ();\n\n      Cell names (dim_vector (count, 1));\n      Cell file  (dim_vector (count, 1));\n      Cell line  (dim_vector (count, 1));\n      Cell cond  (dim_vector (count, 1));\n\n      for (const auto& fnm_bp_p : bp_list)\n        {\n          std::string filename = fnm_bp_p.first;\n          const char *sub_fcn = strchr (filename.c_str (), '>');\n          if (sub_fcn)\n            filename = filename.substr(0, sub_fcn - filename.c_str ());\n          octave_value path_name;\n          path_name\n            = octave::sys::canonicalize_file_name (help_sys.which (filename));\n\n          for (const auto& bp : fnm_bp_p.second)\n            {\n              names(i) = fnm_bp_p.first;\n              file(i) = path_name;\n              line(i) = octave_value (bp.line);\n              cond(i) = octave_value (bp.cond);\n              i++;\n            }\n        }\n\n      retmap.assign (\"name\", names);\n      retmap.assign (\"file\", file);\n      retmap.assign (\"line\", line);\n      retmap.assign (\"cond\", cond);\n\n      const octave_map ew = bptab.stop_on_err_warn_status (false);\n      if (ew.isempty ())\n        {\n          retval = octave_value (retmap);\n        }\n      else\n        {\n          octave_map outer (dim_vector (3, 1));\n          outer.assign (\"bkpt\", Cell (retmap));\n          for (auto f = ew.begin (); f != ew.end (); f++)\n            outer.setfield (f->first, ew.contents (f));\n\n          retval = octave_value (outer);\n        }\n\n      return retval;\n    }\n}\n\n/*\n%!test\n%! if (isguirunning ())\n%!   orig_show_dbg = __event_manager_gui_preference__ (\"editor/show_dbg_file\",\n%!                                                     \"false\");\n%! endif\n%! unwind_protect\n%!   dbclear all;   # Clear out breakpoints before test\n%!   dbstop @ftp/dir;\n%!   dbstop @audioplayer/set 75;\n%!   dbstop quantile>__quantile__;\n%!   dbstop ls;\n%!   dbstop in inputParser at addOptional;\n%!   dbstop in inputParser at 286;\n%!   s = dbstatus ();\n%!   dbclear all;\n%!   ## For Matlab compatibility, the following name should be:\n%!   ## audioplayer.set>setproperty\n%!   assert (s(1).name, \"@audioplayer/set>setproperty\");\n%!   ## For Matlab compatibility, the following name should be:\n%!   ## ftp.dir\n%!   assert (s(2).name, \"@ftp/dir\");\n%!   assert (s(2).file(end-10:end), [filesep \"@ftp\" filesep \"dir.m\"]);\n%!   ## For Matlab compatibility, the following two names should be:\n%!   ## inputParser.inputParser>inputParser.addOptional\n%!   assert (s(3).name, \"@inputParser/addOptional\");\n%!   assert (s(3).line, 280);\n%!   assert (s(4).name, \"@inputParser/addOptional\");\n%!   assert (s(4).line, 286);\n%!   assert (s(5).name, \"ls\");\n%!   assert (s(6).name, \"quantile>__quantile__\");\n%!   s = dbstatus ();\n%!   assert (isempty (s));\n%! unwind_protect_cleanup\n%!   if (isguirunning ())\n%!     __event_manager_gui_preference__ (\"editor/show_dbg_file\", orig_show_dbg);\n%!   endif\n%! end_unwind_protect\n*/\n\nDEFMETHOD (dbwhere, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} dbwhere\nIn debugging mode, report the current file and line number where execution\nis stopped.\n@seealso{dbstack, dblist, dbstatus, dbcont, dbstep, dbup, dbdown}\n@end deftypefn */)\n{\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  tw.debug_where (octave_stdout);\n\n  return ovl ();\n}\n\nstatic bool\nparse_start_end (const std::string& arg, int& start, int& end, const char *who)\n{\n  std::size_t idx = arg.find (':');\n\n  if (idx != std::string::npos)  // (start:end)\n    {\n      std::string start_str = arg.substr (0, idx);\n      std::string end_str = arg.substr (idx+1);\n\n      try\n        {\n          start = std::stoi (start_str);\n\n          if (end_str == \"end\")\n            end = std::numeric_limits<int>::max ();\n          else\n            end = std::stoi (end_str);\n        }\n      catch (const std::invalid_argument&)\n        {\n          error (\"%s: invalid integer conversion while parsing range '%s'\", who, arg.c_str ());\n        }\n      catch (const std::out_of_range&)\n        {\n          error (\"%s: integer value out of bounds while parsing range '%s'\", who, arg.c_str ());\n        }\n\n      if (std::min (start, end) <= 0)\n        error (\"%s: start and end lines must be >= 1\\n\", who);\n\n      if (start > end)\n        error (\"%s: start line must be less than end line\\n\", who);\n    }\n  else  // (dbtype lineno)\n    {\n      try\n        {\n          int line = std::stoi (arg);\n\n          if (line <= 0)\n            error (\"%s: start and end lines must be >= 1\\n\", who);\n\n          start = end = line;\n        }\n      catch (const std::invalid_argument&)\n        {\n          // May be a name instead of a number.\n          return false;\n        }\n      catch (const std::out_of_range&)\n        {\n          error (\"%s: integer value out of bounds while parsing '%s'\", who, arg.c_str ());\n        }\n    }\n\n  return true;\n}\n\nDEFMETHOD (dbtype, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dbtype\n@deftypefnx {} {} dbtype @var{lineno}\n@deftypefnx {} {} dbtype @var{startl:endl}\n@deftypefnx {} {} dbtype @var{startl}:end\n@deftypefnx {} {} dbtype @var{fcn}\n@deftypefnx {} {} dbtype @var{fcn} @var{lineno}\n@deftypefnx {} {} dbtype @var{fcn} @var{startl:endl}\n@deftypefnx {} {} dbtype @var{fcn} @var{startl}:end\nDisplay a script file with line numbers.\n\nWhen called with no arguments in debugging mode, display the script file\ncurrently being debugged.\n\nAn optional range specification can be used to list only a portion of the\nfile.  The special keyword @qcode{\"end\"} is a valid line number specification\nfor the last line of the file.\n\nWhen called with the name of a function, list that script file with line\nnumbers.\n@seealso{dblist, dbwhere, dbstatus, dbstop}\n@end deftypefn */)\n{\n  string_vector argv = args.make_argv (\"dbtype\");\n\n  // Empty means current function on call stack.\n  std::string fcn_name;\n\n  int start = 0;\n  int end = std::numeric_limits<int>::max ();\n\n  switch (args.length ())\n    {\n    case 0:  // dbtype\n      break;\n\n    case 1:  // (dbtype start:end) || (dbtype fcn) || (dbtype lineno)\n      {\n        std::string arg = argv[1];\n\n        if (! parse_start_end (arg, start, end, \"dbtype\"))\n          fcn_name = arg;\n      }\n      break;\n\n    case 2:  // (dbtype fcn start:end) || (dbtype fcn start)\n      {\n        fcn_name = argv[1];\n\n        if (! parse_start_end (argv[2], start, end, \"dbtype\"))\n          error (\"dbtype: expecting start:end or location argument, found '%s'\", argv[2].c_str ());\n      }\n      break;\n\n    default:\n      error (\"dbtype: expecting zero, one, or two arguments\\n\");\n    }\n\n  if (fcn_name.empty ())\n    {\n      octave::tree_evaluator& tw = interp.get_evaluator ();\n\n      tw.debug_type (octave_stdout, start, end);\n    }\n  else\n    {\n      std::string file_name = octave::fcn_file_in_path (fcn_name);\n\n      if (file_name.empty ())\n        error (\"dbtype: unknown function '%s'\", fcn_name.c_str ());\n\n      octave::display_file_lines (octave_stdout, file_name, start, end, -1, \"\", \"dbtype\");\n    }\n\n  return ovl ();\n}\n\nstatic int\nparse_integer_argument (const std::string& arg, const char *who)\n{\n  int n = 0;\n\n  try\n    {\n      n = std::stoi (arg);\n    }\n  catch (const std::invalid_argument&)\n    {\n      error (\"%s: invalid value of N, found '%s'\", arg.c_str (), who);\n    }\n  catch (const std::out_of_range&)\n    {\n      error (\"%s: value of N ('%s') is out of range\", arg.c_str (), who);\n    }\n\n  return n;\n}\n\nDEFMETHOD (dblist, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dblist\n@deftypefnx {} {} dblist @var{n}\nIn debugging mode, list @var{n} lines of the function being debugged\ncentered around the current line to be executed.\n\nIf unspecified @var{n} defaults to 10 (+/- 5 lines)\n@seealso{dbwhere, dbtype, dbstack}\n@end deftypefn */)\n{\n  int n = 10;\n\n  int numel = args.length ();\n\n  if (numel > 1)\n    print_usage ();\n\n  if (numel == 1)\n    {\n      octave_value arg = args(0);\n\n      if (arg.is_string ())\n        n = parse_integer_argument (arg.string_value (), \"dblist\");\n      else\n        n = args(0).int_value ();\n\n      if (n < 0)\n        error (\"dblist: N must be a non-negative integer\");\n    }\n\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  tw.debug_list (octave_stdout, n);\n\n  return ovl ();\n}\n\nstatic octave_value_list\ndo_dbstack (octave::interpreter& interp, const octave_value_list& args,\n            int nargout, std::ostream& os)\n{\n  int nargin = args.length ();\n\n  if (nargin > 2)\n    print_usage ();\n\n  octave_value_list retval;\n\n  octave_idx_type curr_frame = -1;\n\n  octave_idx_type nskip = 0;\n\n  if (nargin == 1 || nargin == 2)\n    {\n      int n = 0;\n\n      for (octave_idx_type i = 0; i < nargin; i++)\n        {\n          octave_value arg = args(i);\n\n          if (arg.is_string ())\n            {\n              std::string s_arg = arg.string_value ();\n\n              // Skip \"-completenames\", octave returns full names anyway.\n              if (s_arg == \"-completenames\")\n                continue;\n\n              n = parse_integer_argument (s_arg, \"dbstack\");\n            }\n          else\n            n = arg.int_value ();\n\n          if (n < 0)\n            error (\"dbstack: N must be a non-negative integer\");\n        }\n\n      if (n > 0)\n        nskip = n;\n    }\n\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  if (nargout == 0)\n    {\n      octave_map stk = tw.backtrace (curr_frame);\n      octave_idx_type nframes = stk.numel ();\n\n      if (nframes > 0)\n        {\n          octave::preserve_stream_state stream_state (os);\n\n          os << \"stopped in:\\n\\n\";\n\n          Cell names = stk.contents (\"name\");\n          Cell files = stk.contents (\"file\");\n          Cell lines = stk.contents (\"line\");\n\n          bool show_top_level = true;\n\n          std::size_t max_name_len = 0;\n\n          for (octave_idx_type i = nskip; i < nframes; i++)\n            {\n              std::string name = names(i).string_value ();\n\n              max_name_len = std::max (name.length (), max_name_len);\n            }\n\n          for (octave_idx_type i = nskip; i < nframes; i++)\n            {\n              std::string name = names(i).string_value ();\n              std::string file = files(i).string_value ();\n              int line = lines(i).int_value ();\n\n              if (show_top_level && i == curr_frame)\n                show_top_level = false;\n\n              os << (i == curr_frame ? \"  --> \" : \"      \")\n                 << std::setw (max_name_len) << name\n                 << \" at line \" << line\n                 << \" [\" << file << ']'\n                 << std::endl;\n            }\n\n          if (tw.at_top_level () && show_top_level)\n            os << \"  --> top level\" << std::endl;\n        }\n    }\n  else\n    {\n      octave_map stk = tw.backtrace (curr_frame, false);\n\n      octave_idx_type num_skip = std::min (nskip, stk.numel ());\n\n      idx_vector first = idx_vector (0);\n\n      for (octave_idx_type i = 0; i < num_skip; i++)\n        stk.delete_elements (first);\n\n      curr_frame -= num_skip;\n      curr_frame = (curr_frame < 0 ? 0 : curr_frame + 1);\n\n      retval = ovl (stk, curr_frame);\n    }\n\n  return retval;\n}\n\n// A function that can be easily called from a debugger print the Octave stack.\n// This can be useful for finding what line of code the interpreter is\n// currently executing when the debugger is stopped in some C++ function,\n// for example.\n\nvoid\nshow_octave_dbstack ()\n{\n  do_dbstack (octave::__get_interpreter__ (),\n              octave_value_list (), 0, std::cerr);\n}\n\nDEFMETHOD (dbstack, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dbstack\n@deftypefnx {} {} dbstack @var{n}\n@deftypefnx {} {} dbstack -completenames\n@deftypefnx {} {[@var{stack}, @var{idx}] =} dbstack (@dots{})\nDisplay or return current debugging function stack information.\n\nWith optional argument @var{n}, omit the @var{n} innermost stack frames.\n\nAlthough accepted, the argument @option{-completenames} is silently ignored.\nOctave always returns absolute filenames.\n\nThe arguments @var{n} and @option{-completenames} can both be specified and may\nappear in any order.\n\nThe optional return argument @var{stack} is a struct array with the\nfollowing fields:\n\n@table @asis\n@item file\nThe name of the m-file where the function code is located.\n\n@item name\nThe name of the function with a breakpoint.\n\n@item line\nThe line number of an active breakpoint.\n\n@item column\nThe column number of the line where the breakpoint begins.\n\n@end table\n\nThe return argument @var{idx} specifies which element of the @var{stack}\nstruct array is currently active.\n@seealso{dbup, dbdown, dbwhere, dblist, dbstatus}\n@end deftypefn */)\n{\n  return do_dbstack (interp, args, nargout, octave_stdout);\n}\n\nstatic void\ndo_dbupdown (octave::interpreter& interp, const octave_value_list& args,\n             const std::string& who)\n{\n  int n = 1;\n\n  if (args.length () == 1)\n    {\n      octave_value arg = args(0);\n\n      if (arg.is_string ())\n        n = parse_integer_argument (arg.string_value (), who.c_str ());\n      else\n        n = args(0).int_value ();\n    }\n\n  if (who == \"dbup\")\n    n = -n;\n\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  tw.dbupdown (n, true);\n}\n\nDEFMETHOD (dbup, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dbup\n@deftypefnx {} {} dbup @var{n}\nIn debugging mode, move up the execution stack @var{n} frames.\n\nIf @var{n} is omitted, move up one frame.\n@seealso{dbstack, dbdown}\n@end deftypefn */)\n{\n  do_dbupdown (interp, args, \"dbup\");\n\n  return ovl ();\n}\n\nDEFMETHOD (dbdown, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dbdown\n@deftypefnx {} {} dbdown @var{n}\nIn debugging mode, move down the execution stack @var{n} frames.\n\nIf @var{n} is omitted, move down one frame.\n@seealso{dbstack, dbup}\n@end deftypefn */)\n{\n  do_dbupdown (interp, args, \"dbdown\");\n\n  return ovl ();\n}\n\nDEFMETHOD (dbstep, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dbstep\n@deftypefnx {} {} dbstep @var{n}\n@deftypefnx {} {} dbstep in\n@deftypefnx {} {} dbstep out\n@deftypefnx {} {} dbnext @dots{}\nIn debugging mode, execute the next @var{n} lines of code.\n\nIf @var{n} is omitted, execute the next single line of code.  If the next\nline of code is itself defined in terms of an m-file remain in the existing\nfunction.\n\nUsing @code{dbstep in} will cause execution of the next line to step into\nany m-files defined on the next line.\n\nUsing @code{dbstep out} will cause execution to continue until the current\nfunction returns.\n\nProgramming Note: @code{dbnext} is an alias for @code{dbstep} and can be used\ninterchangeably.\n@seealso{dbcont, dbquit}\n@end deftypefn */)\n{\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  if (! tw.in_debug_repl ())\n    error (\"dbstep: can only be called in debug mode\");\n\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  int n = 0;\n\n  if (nargin == 1)\n    {\n      std::string arg\n        = args(0).xstring_value (\"dbstep: input argument must be a string\");\n\n      if (arg == \"in\")\n        n = -1;\n      else if (arg == \"out\")\n        n = -2;\n      else\n        {\n          n = parse_integer_argument (arg, \"dbstep\");\n\n          if (n < 1)\n            error (\"dbstep: N must be greater than zero\");\n        }\n    }\n  else\n    n = 1;\n\n  if (n != 0)\n    {\n      tw.set_dbstep_flag (n);\n\n      // If we set the dbstep flag, we also need to reset debug_mode.\n      tw.reset_debug_state ();\n\n    }\n\n  return ovl ();\n}\n\nDEFALIAS (dbnext, dbstep);\n\nDEFMETHOD (dbcont, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} dbcont\nLeave command-line debugging mode and continue code execution normally.\n@seealso{dbstep, dbquit}\n@end deftypefn */)\n{\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  if (! tw.in_debug_repl ())\n    error (\"dbcont: can only be called in debug mode\");\n\n  if (args.length () != 0)\n    print_usage ();\n\n  tw.dbcont ();\n\n  return ovl ();\n}\n\nDEFMETHOD (dbquit, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} dbquit\n@deftypefnx {} {} dbquit all\nQuit debugging mode immediately without further code execution.\n\nWith no arguments, exit the current debugging level.  With argument @code{all},\nexit all debugging levels and return to the Octave prompt.\n@seealso{dbcont, dbstep}\n@end deftypefn */)\n{\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  if (! tw.in_debug_repl ())\n    error (\"dbquit: can only be called in debug mode\");\n\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      std::string arg\n        = args(0).xstring_value (\"dbquit: input argument must be a string\");\n\n      if (arg == \"all\")\n        tw.dbquit (true);\n      else\n        error (\"dbquit: unrecognized argument '%s'\", arg.c_str ());\n    }\n  else\n    tw.dbquit ();\n\n  return ovl ();\n}\n\nDEFMETHOD (isdebugmode, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isdebugmode ()\nReturn true if in debugging mode, otherwise false.\n@seealso{dbwhere, dbstack, dbstatus}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  return ovl (tw.in_debug_repl ());\n}\n\nDEFMETHOD (__db_next_breakpoint_quiet__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __db_next_breakpoint_quiet__ ()\n@deftypefnx {} {} __db_next_breakpoint_quiet__ (@var{flag})\nDisable line info printing at the next breakpoint.\n\nWith a logical argument @var{flag}, set the state on or off.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  bool state = true;\n\n  if (nargin == 1)\n    state = args(0).bool_value ();\n\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  tw.quiet_breakpoint_flag (state);\n\n  return ovl ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/default-defs.in.h",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These are used by functions declared in defaults.h and defined in\n// defaults.cc.\n\n#if ! defined (OCTAVE_RELEASE)\n#  define OCTAVE_RELEASE %OCTAVE_RELEASE%\n#endif\n\n#if ! defined (OCTAVE_DEFAULT_PAGER)\n#  define OCTAVE_DEFAULT_PAGER %OCTAVE_DEFAULT_PAGER%\n#endif\n\n#if ! defined (OCTAVE_PREFIX)\n#  define OCTAVE_PREFIX %OCTAVE_PREFIX%\n#endif\n\n#if ! defined (OCTAVE_EXEC_PREFIX)\n#  define OCTAVE_EXEC_PREFIX %OCTAVE_EXEC_PREFIX%\n#endif\n\n#if ! defined (OCTAVE_BINDIR)\n#  define OCTAVE_BINDIR %OCTAVE_BINDIR%\n#endif\n\n#if ! defined (OCTAVE_DATADIR)\n#  define OCTAVE_DATADIR %OCTAVE_DATADIR%\n#endif\n\n#if ! defined (OCTAVE_DATAROOTDIR)\n#  define OCTAVE_DATAROOTDIR %OCTAVE_DATAROOTDIR%\n#endif\n\n#if ! defined (OCTAVE_INCLUDEDIR)\n#  define OCTAVE_INCLUDEDIR %OCTAVE_INCLUDEDIR%\n#endif\n\n#if ! defined (OCTAVE_LIBDIR)\n#  define OCTAVE_LIBDIR %OCTAVE_LIBDIR%\n#endif\n\n#if ! defined (OCTAVE_LIBEXECDIR)\n#  define OCTAVE_LIBEXECDIR %OCTAVE_LIBEXECDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALVERARCHLIBDIR)\n#  define OCTAVE_LOCALVERARCHLIBDIR %OCTAVE_LOCALVERARCHLIBDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALAPIARCHLIBDIR)\n#  define OCTAVE_LOCALAPIARCHLIBDIR %OCTAVE_LOCALAPIARCHLIBDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALARCHLIBDIR)\n#  define OCTAVE_LOCALARCHLIBDIR %OCTAVE_LOCALARCHLIBDIR%\n#endif\n\n#if ! defined (OCTAVE_ARCHLIBDIR)\n#  define OCTAVE_ARCHLIBDIR %OCTAVE_ARCHLIBDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALVEROCTFILEDIR)\n#  define OCTAVE_LOCALVEROCTFILEDIR %OCTAVE_LOCALVEROCTFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALAPIOCTFILEDIR)\n#  define OCTAVE_LOCALAPIOCTFILEDIR %OCTAVE_LOCALAPIOCTFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALOCTFILEDIR)\n#  define OCTAVE_LOCALOCTFILEDIR %OCTAVE_LOCALOCTFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_OCTFILEDIR)\n#  define OCTAVE_OCTFILEDIR %OCTAVE_OCTFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALVERFCNFILEDIR)\n#  define OCTAVE_LOCALVERFCNFILEDIR %OCTAVE_LOCALVERFCNFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALAPIFCNFILEDIR)\n#  define OCTAVE_LOCALAPIFCNFILEDIR %OCTAVE_LOCALAPIFCNFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALFCNFILEDIR)\n#  define OCTAVE_LOCALFCNFILEDIR %OCTAVE_LOCALFCNFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_FCNFILEDIR)\n#  define OCTAVE_FCNFILEDIR %OCTAVE_FCNFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_OCTDATADIR)\n#  define OCTAVE_OCTDATADIR %OCTAVE_OCTDATADIR%\n#endif\n\n#if ! defined (OCTAVE_OCTDOCDIR)\n#  define OCTAVE_OCTDOCDIR %OCTAVE_OCTDOCDIR%\n#endif\n\n#if ! defined (OCTAVE_OCTETCDIR)\n#  define OCTAVE_OCTETCDIR %OCTAVE_OCTETCDIR%\n#endif\n\n#if ! defined (OCTAVE_OCTFONTSDIR)\n#  define OCTAVE_OCTFONTSDIR %OCTAVE_OCTFONTSDIR%\n#endif\n\n#if ! defined (OCTAVE_OCTINCLUDEDIR)\n#  define OCTAVE_OCTINCLUDEDIR %OCTAVE_OCTINCLUDEDIR%\n#endif\n\n#if ! defined (OCTAVE_OCTLIBDIR)\n#  define OCTAVE_OCTLIBDIR %OCTAVE_OCTLIBDIR%\n#endif\n\n#if ! defined (OCTAVE_OCTLOCALEDIR)\n#  define OCTAVE_OCTLOCALEDIR %OCTAVE_OCTLOCALEDIR%\n#endif\n\n#if ! defined (OCTAVE_OCTTESTSDIR)\n#  define OCTAVE_OCTTESTSDIR %OCTAVE_OCTTESTSDIR%\n#endif\n\n#if ! defined (OCTAVE_INFODIR)\n#  define OCTAVE_INFODIR %OCTAVE_INFODIR%\n#endif\n\n#if ! defined (OCTAVE_MANDIR)\n#  define OCTAVE_MANDIR %OCTAVE_MANDIR%\n#endif\n\n#if ! defined (OCTAVE_MAN1DIR)\n#  define OCTAVE_MAN1DIR %OCTAVE_MAN1DIR%\n#endif\n\n#if ! defined (OCTAVE_MAN1EXT)\n#  define OCTAVE_MAN1EXT %OCTAVE_MAN1EXT%\n#endif\n\n#if ! defined (OCTAVE_IMAGEDIR)\n#  define OCTAVE_IMAGEDIR %OCTAVE_IMAGEDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALSTARTUPFILEDIR)\n#  define OCTAVE_LOCALSTARTUPFILEDIR %OCTAVE_LOCALSTARTUPFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_STARTUPFILEDIR)\n#  define OCTAVE_STARTUPFILEDIR %OCTAVE_STARTUPFILEDIR%\n#endif\n\n#if ! defined (OCTAVE_LOCALAPIPKGDIR)\n#  define OCTAVE_LOCALAPIPKGDIR %OCTAVE_LOCALAPIPKGDIR%\n#endif\n\n#if ! defined (OCTAVE_INFOFILE)\n#  define OCTAVE_INFOFILE %OCTAVE_INFOFILE%\n#endif\n\n#if ! defined (OCTAVE_TEXI_MACROS_FILE)\n#  define OCTAVE_TEXI_MACROS_FILE %OCTAVE_TEXI_MACROS_FILE%\n#endif\n\n#if ! defined (OCTAVE_DOC_CACHE_FILE)\n#  define OCTAVE_DOC_CACHE_FILE %OCTAVE_DOC_CACHE_FILE%\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/defaults.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <string>\n\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"oct-env.h\"\n\n#include \"defaults.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"file-ops.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"variables.h\"\n#include \"version.h\"\n\n#include \"default-defs.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(config)\n\n// Variables that name directories or files are substituted into source\n// files with \"${prefix}/\" stripped from the beginning of the string.\n\n// All configure variables of this form should be specified as absolute\n// directory names.  The only ones that should not be absolute here are\n// ones that have had \"${prefix}/\" or \"${exec_prefix} stripped.\n\nstatic std::string\nprepend_home_dir (const std::string& hd, const std::string& s)\n{\n  std::string retval = s;\n\n  char dir_sep_char = sys::file_ops::dir_sep_char ();\n\n  if (! sys::env::absolute_pathname (retval))\n    retval = hd + dir_sep_char + s;\n\n  if (dir_sep_char != '/')\n    std::replace (retval.begin (), retval.end (), '/', dir_sep_char);\n\n  return retval;\n}\n\nstatic std::string\nget_octave_home ()\n{\n  std::string op = OCTAVE_PREFIX;\n\n  std::string oh = sys::env::getenv (\"OCTAVE_HOME\");\n\n  // If OCTAVE_HOME is set in the environment, use that.  Otherwise,\n  // default to ${prefix} from configure.\n\n  return oh.empty () ? op : oh;\n}\n\nstatic std::string\nget_octave_exec_home ()\n{\n  std::string op = OCTAVE_PREFIX;\n  std::string oep = OCTAVE_EXEC_PREFIX;\n\n  std::string oh = sys::env::getenv (\"OCTAVE_HOME\");\n  std::string oeh = sys::env::getenv (\"OCTAVE_EXEC_HOME\");\n\n  // If OCTAVE_EXEC_HOME is set in the environment, use that.\n  // Otherwise, if ${prefix} and ${exec_prefix} from configure are set\n  // to the same value, use OCTAVE_HOME from the environment if it is set.\n  // Otherwise, default to ${exec_prefix} from configure.\n\n  if (! oeh.empty ())\n    return oeh;\n\n  if (op == oep && ! oh.empty ())\n    return oh;\n\n  return oep;\n}\n\nstatic std::string\nget_local_site_defaults_file ()\n{\n  std::string lsf = sys::env::getenv (\"OCTAVE_SITE_INITFILE\");\n\n  return lsf.empty () ? local_startupfile_dir () + \"/octaverc\" : lsf;\n}\n\nstatic std::string\nget_site_defaults_file ()\n{\n  std::string sf = sys::env::getenv (\"OCTAVE_VERSION_INITFILE\");\n\n  return sf.empty () ? startupfile_dir () + \"/octaverc\" : sf;\n}\n\nstd::string\nprepend_octave_home (const std::string& s)\n{\n  return prepend_home_dir (octave_home (), s);\n}\n\nstd::string\nprepend_octave_exec_home (const std::string& s)\n{\n  return prepend_home_dir (octave_exec_home (), s);\n}\n\nstd::string\ncanonical_host_type ()\n{\n  static const std::string s_canonical_host_type\n    = OCTAVE_CANONICAL_HOST_TYPE;\n\n  return s_canonical_host_type;\n}\n\nstd::string\nrelease ()\n{\n  static const std::string s_octave_release = OCTAVE_RELEASE;\n\n  return s_octave_release;\n}\n\nstd::string\ndefault_pager ()\n{\n  static const std::string s_default_pager = OCTAVE_DEFAULT_PAGER;\n\n  return s_default_pager;\n}\n\nstd::string\noctave_home ()\n{\n  static const std::string s_octave_home = get_octave_home ();\n\n  return s_octave_home;\n}\n\nstd::string\noctave_exec_home ()\n{\n  static const std::string s_octave_exec_home = get_octave_exec_home ();\n\n  return s_octave_exec_home;\n}\n\nstd::string\nbin_dir ()\n{\n  static const std::string s_bin_dir\n    = prepend_octave_exec_home (OCTAVE_BINDIR);\n\n  return s_bin_dir;\n}\n\nstd::string\ndata_dir ()\n{\n  static const std::string s_data_dir\n    = prepend_octave_home (OCTAVE_DATADIR);\n\n  return s_data_dir;\n}\n\nstd::string\ndataroot_dir ()\n{\n  static const std::string s_dataroot_dir\n    = prepend_octave_home (OCTAVE_DATAROOTDIR);\n\n  return s_dataroot_dir;\n}\n\nstd::string\ninclude_dir ()\n{\n  static const std::string s_include_dir\n    = prepend_octave_home (OCTAVE_INCLUDEDIR);\n\n  return s_include_dir;\n}\n\nstd::string\nlib_dir ()\n{\n  static const std::string s_lib_dir\n    = prepend_octave_exec_home (OCTAVE_LIBDIR);\n\n  return s_lib_dir;\n}\n\nstd::string\nlibexec_dir ()\n{\n  static const std::string s_libexec_dir\n    = prepend_octave_exec_home (OCTAVE_LIBEXECDIR);\n\n  return s_libexec_dir;\n}\n\nstd::string\narch_lib_dir ()\n{\n  static const std::string s_arch_lib_dir\n    = prepend_octave_exec_home (OCTAVE_ARCHLIBDIR);\n\n  return s_arch_lib_dir;\n}\n\nstd::string\ninfo_dir ()\n{\n  static const std::string s_info_dir\n    = prepend_octave_exec_home (OCTAVE_INFODIR);\n\n  return s_info_dir;\n}\n\nstd::string\nlocal_ver_arch_lib_dir ()\n{\n  static const std::string s_local_ver_arch_lib_dir\n    = prepend_octave_exec_home (OCTAVE_LOCALVERARCHLIBDIR);\n\n  return s_local_ver_arch_lib_dir;\n}\n\nstd::string\nlocal_api_arch_lib_dir ()\n{\n  static const std::string s_local_api_arch_lib_dir\n    = prepend_octave_exec_home (OCTAVE_LOCALAPIARCHLIBDIR);\n\n  return s_local_api_arch_lib_dir;\n}\n\nstd::string\nlocal_arch_lib_dir ()\n{\n  static const std::string s_local_arch_lib_dir\n    = prepend_octave_exec_home (OCTAVE_LOCALARCHLIBDIR);\n\n  return s_local_arch_lib_dir;\n}\n\nstd::string\nlocal_ver_oct_file_dir ()\n{\n  static const std::string s_local_ver_oct_file_dir\n    = prepend_octave_exec_home (OCTAVE_LOCALVEROCTFILEDIR);\n\n  return s_local_ver_oct_file_dir;\n}\n\nstd::string\nlocal_api_oct_file_dir ()\n{\n  static const std::string s_local_api_oct_file_dir\n    = prepend_octave_exec_home (OCTAVE_LOCALAPIOCTFILEDIR);\n\n  return s_local_api_oct_file_dir;\n}\n\nstd::string\nlocal_oct_file_dir ()\n{\n  static const std::string s_local_oct_file_dir\n    = prepend_octave_exec_home (OCTAVE_LOCALOCTFILEDIR);\n\n  return s_local_oct_file_dir;\n}\n\nstd::string\noct_file_dir ()\n{\n  static const std::string s_oct_file_dir\n    = prepend_octave_exec_home (OCTAVE_OCTFILEDIR);\n\n  return s_oct_file_dir;\n}\n\nstd::string\nlocal_ver_fcn_file_dir ()\n{\n  static const std::string s_local_ver_fcn_file_dir\n    = prepend_octave_home (OCTAVE_LOCALVERFCNFILEDIR);\n\n  return s_local_ver_fcn_file_dir;\n}\n\nstd::string\nlocal_api_fcn_file_dir ()\n{\n  static const std::string s_local_api_fcn_file_dir\n    = prepend_octave_home (OCTAVE_LOCALAPIFCNFILEDIR);\n\n  return s_local_api_fcn_file_dir;\n}\n\nstd::string\nlocal_fcn_file_dir ()\n{\n  static const std::string s_local_fcn_file_dir\n    = prepend_octave_home (OCTAVE_LOCALFCNFILEDIR);\n\n  return s_local_fcn_file_dir;\n}\n\nstd::string\nfcn_file_dir ()\n{\n  static const std::string s_fcn_file_dir\n    = prepend_octave_home (OCTAVE_FCNFILEDIR);\n\n  return s_fcn_file_dir;\n}\n\nstd::string\noct_data_dir ()\n{\n  static const std::string s_oct_data_dir\n    = prepend_octave_home (OCTAVE_OCTDATADIR);\n\n  return s_oct_data_dir;\n}\n\nstd::string\noct_doc_dir ()\n{\n  static const std::string s_oct_doc_dir\n    = prepend_octave_home (OCTAVE_OCTDOCDIR);\n\n  return s_oct_doc_dir;\n}\n\nstd::string\noct_etc_dir ()\n{\n  static const std::string s_oct_etc_dir\n    = prepend_octave_home (OCTAVE_OCTETCDIR);\n\n  return s_oct_etc_dir;\n}\n\nstd::string\noct_fonts_dir ()\n{\n  static const std::string s_oct_fonts_dir\n    = prepend_octave_home (OCTAVE_OCTFONTSDIR);\n\n  return s_oct_fonts_dir;\n}\n\nstd::string\noct_include_dir ()\n{\n  static const std::string s_oct_include_dir\n    = prepend_octave_home (OCTAVE_OCTINCLUDEDIR);\n\n  return s_oct_include_dir;\n}\n\nstd::string\noct_lib_dir ()\n{\n  static const std::string s_oct_lib_dir\n    = prepend_octave_exec_home (OCTAVE_OCTLIBDIR);\n\n  return s_oct_lib_dir;\n}\n\nstd::string\noct_locale_dir ()\n{\n  static const std::string s_oct_locale_dir\n    = prepend_octave_home (OCTAVE_OCTLOCALEDIR);\n\n  return s_oct_locale_dir;\n}\n\nstd::string\noct_tests_dir ()\n{\n  static const std::string s_oct_tests_dir\n    = prepend_octave_home (OCTAVE_OCTTESTSDIR);\n\n  return s_oct_tests_dir;\n}\n\nstd::string\nman_dir ()\n{\n  static const std::string s_man_dir\n    = prepend_octave_home (OCTAVE_MANDIR);\n\n  return s_man_dir;\n}\n\nstd::string\nman1_dir ()\n{\n  static const std::string s_man1_dir\n    = prepend_octave_home (OCTAVE_MAN1DIR);\n\n  return s_man1_dir;\n}\n\nstd::string\nman1_ext ()\n{\n  static const std::string s_man1_ext = OCTAVE_MAN1EXT;\n\n  return s_man1_ext;\n}\n\nstd::string\nimage_dir ()\n{\n  static const std::string s_image_dir\n    = prepend_octave_home (OCTAVE_IMAGEDIR);\n\n  return s_image_dir;\n}\n\nstd::string\nlocal_startupfile_dir ()\n{\n  static const std::string s_local_startupfile_dir\n    = prepend_octave_home (OCTAVE_LOCALSTARTUPFILEDIR);\n\n  return s_local_startupfile_dir;\n}\n\nstd::string\nstartupfile_dir ()\n{\n  static const std::string s_startupfile_dir\n    = prepend_octave_home (OCTAVE_STARTUPFILEDIR);\n\n  return s_startupfile_dir;\n}\n\nstd::string\nlocal_api_pkg_dir ()\n{\n  static const std::string s_local_api_pkg_dir\n    = prepend_octave_home (OCTAVE_LOCALAPIPKGDIR);\n\n  return s_local_api_pkg_dir;\n}\n\nstd::string\nlocal_site_defaults_file ()\n{\n  static const std::string s_local_site_defaults_file\n    = get_local_site_defaults_file ();\n\n  return s_local_site_defaults_file;\n}\n\nstd::string\nsite_defaults_file ()\n{\n  static const std::string s_site_defaults_file\n    = get_site_defaults_file ();\n\n  return s_site_defaults_file;\n}\n\nOCTAVE_END_NAMESPACE(config)\n\nDEFUN (OCTAVE_HOME, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{dir} =} OCTAVE_HOME ()\nReturn the name of the top-level Octave installation directory.\n\nOCTAVE_HOME corresponds to the configuration variable @var{prefix}.\n@seealso{EXEC_PATH, IMAGE_PATH, OCTAVE_EXEC_HOME}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (config::octave_home ());\n}\n\n/*\n%!assert (ischar (OCTAVE_HOME ()))\n%!error OCTAVE_HOME (1)\n*/\n\nDEFUN (OCTAVE_EXEC_HOME, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{dir} =} OCTAVE_EXEC_HOME ()\nReturn the name of the top-level Octave installation directory for\narchitecture-dependent files.\n\nIf not specified separately, the value is the same as OCTAVE_HOME@.\nOCTAVE_EXEC_HOME corresponds to the configuration variable @var{exec_prefix}.\n@seealso{EXEC_PATH, IMAGE_PATH, OCTAVE_HOME}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (config::octave_exec_home ());\n}\n\n/*\n%!assert (ischar (OCTAVE_EXEC_HOME ()))\n%!error OCTAVE_EXEC_HOME (1)\n*/\n\nDEFUNX (\"OCTAVE_VERSION\", FOCTAVE_VERSION, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{verstr} =} OCTAVE_VERSION ()\nReturn the version number of Octave as a string.\n@seealso{ver, version}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (OCTAVE_VERSION);\n}\n\n/*\n%!assert (ischar (OCTAVE_VERSION ()))\n%!error OCTAVE_VERSION (1)\n*/\n\nDEFUN (user_config_dir, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {cfg_dir =} user_config_dir ()\nReturn the (platform-specific) directory for user configuration.\n@seealso{user_data_dir}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::env::get_user_config_directory ());\n}\n\n/*\n%!assert (ischar (user_config_dir ()))\n%!error user_config_dir (1)\n*/\n\nDEFUN (user_data_dir, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {data_dir =} user_data_dir ()\nReturn the (platform-specific) directory for user data.\n@seealso{user_config_dir}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::env::get_user_data_directory ());\n}\n\n/*\n%!assert (ischar (user_data_dir ()))\n%!error user_data_dir (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/defaults.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_defaults_h)\n#define octave_defaults_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"pathsearch.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(config)\n\nextern OCTINTERP_API std::string\nprepend_octave_home (const std::string& s);\n\nextern OCTINTERP_API std::string\nprepend_octave_exec_home (const std::string& s);\n\n// These could be defined as pure constants, but we'll use\n// functions to be consistent with the values that require\n// initialization.\n\nextern OCTINTERP_API std::string canonical_host_type ();\nextern OCTINTERP_API std::string release ();\nextern OCTINTERP_API std::string default_pager ();\n\n// These require initialization, so can't be defined as pure\n// constants.  We use functions to access these values so that\n// they can't be modified by users.\n\nextern OCTINTERP_API std::string octave_home ();\nextern OCTINTERP_API std::string octave_exec_home ();\n\nextern OCTINTERP_API std::string bin_dir ();\nextern OCTINTERP_API std::string data_dir ();\nextern OCTINTERP_API std::string dataroot_dir ();\nextern OCTINTERP_API std::string include_dir ();\nextern OCTINTERP_API std::string lib_dir ();\nextern OCTINTERP_API std::string libexec_dir ();\n\nextern OCTINTERP_API std::string local_ver_arch_lib_dir ();\nextern OCTINTERP_API std::string local_api_arch_lib_dir ();\nextern OCTINTERP_API std::string local_arch_lib_dir ();\nextern OCTINTERP_API std::string arch_lib_dir ();\n\nextern OCTINTERP_API std::string local_ver_oct_file_dir ();\nextern OCTINTERP_API std::string local_api_oct_file_dir ();\nextern OCTINTERP_API std::string local_oct_file_dir ();\nextern OCTINTERP_API std::string oct_file_dir ();\n\nextern OCTINTERP_API std::string local_ver_fcn_file_dir ();\nextern OCTINTERP_API std::string local_api_fcn_file_dir ();\nextern OCTINTERP_API std::string local_fcn_file_dir ();\nextern OCTINTERP_API std::string fcn_file_dir ();\n\nextern OCTINTERP_API std::string oct_data_dir ();\nextern OCTINTERP_API std::string oct_doc_dir ();\nextern OCTINTERP_API std::string oct_etc_dir ();\nextern OCTINTERP_API std::string oct_fonts_dir ();\nextern OCTINTERP_API std::string oct_include_dir ();\nextern OCTINTERP_API std::string oct_lib_dir ();\nextern OCTINTERP_API std::string oct_locale_dir ();\nextern OCTINTERP_API std::string oct_tests_dir ();\n\nextern OCTINTERP_API std::string local_api_pkg_dir ();\n\nextern OCTINTERP_API std::string info_dir ();\n\nextern OCTINTERP_API std::string man_dir ();\nextern OCTINTERP_API std::string man1_dir ();\nextern OCTINTERP_API std::string man1_ext ();\n\nextern OCTINTERP_API std::string image_dir ();\n\nextern OCTINTERP_API std::string local_startupfile_dir ();\nextern OCTINTERP_API std::string startupfile_dir ();\n\nextern OCTINTERP_API std::string local_site_defaults_file ();\nextern OCTINTERP_API std::string site_defaults_file ();\n\nOCTAVE_END_NAMESPACE(config)\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/defun-dld.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_defun_dld_h)\n#define octave_defun_dld_h 1\n\n#include \"octave-config.h\"\n\n#if defined (octave_defun_h)\n#  error defun.h and defun-dld.h both included in same file!\n#endif\n\n#include \"defun-int.h\"\n\n//! Macro to define an at run time dynamically loadable builtin function.\n//!\n//! For detailed information, see \\ref Macros.\n//!\n//! @param name The **unquoted** name of the function that should be installed\n//!             on the 'octave::symbol_table' and can be called by the\n//!             interpreter.  Internally, the function name is prepended by an\n//!             'F'.\n//! @param args_name The name of the octave_value_list variable used to pass\n//!                  the argument list to this function.  If this value is\n//!                  omitted, the function cannot access the argument list.\n//! @param nargout_name The name of the 'int' variable used to pass the number\n//!                     of output arguments this function is expected to\n//!                     produce from the caller.  If this value is\n//!                     omitted, the function cannot access this number.\n//! @param doc Texinfo help text (docstring) for the function.\n//!\n//! @see DEFMETHOD_DLD\n\n// The order of this macro for name = foo is:\n// 1. Forward declaration of Ffoo.\n// 2. Definition of installation function Gfoo.\n// 3. Definition of Ffoo.\n\n#define DEFUN_DLD(name, args_name, nargout_name, doc)   \\\n  FORWARD_DECLARE_FUN (name);                           \\\n  DEFINE_FUN_INSTALLER_FUN (name, doc)                  \\\n  DECLARE_FUN (name, args_name, nargout_name)\n\n#define DEFUNX_DLD(name, fname, gname, args_name, nargout_name, doc)    \\\n  FORWARD_DECLARE_FUNX (fname);                                         \\\n  DEFINE_FUNX_INSTALLER_FUN (name, fname, gname, doc)                   \\\n  DECLARE_FUNX (fname, args_name, nargout_name)\n\n//! Macro to define an at run time dynamically loadable builtin method.\n//!\n//! For detailed information, see \\ref Macros.\n//!\n//! @param name The **unquoted** name of the method that should be installed\n//!             on the 'octave::symbol_table' and can be called by the\n//!             interpreter.  Internally, the method name is prepended by an\n//!             'F'.\n//! @param interp_name The name of the 'octave::interpreter' reference that can\n//!                    be used by this method.  If this value is omitted,\n//!                    there is no access to the interpreter and one should\n//!                    use #DEFUN to define a function instead.\n//! @param args_name The name of the octave_value_list variable used to pass\n//!                  the argument list to this method.  If this value is\n//!                  omitted, the method cannot access the argument list.\n//! @param nargout_name The name of the 'int' variable used to pass the number\n//!                     of output arguments this method is expected to\n//!                     produce from the caller.  If this value is\n//!                     omitted, the method cannot access this number.\n//! @param doc Texinfo help text (docstring) for the method.\n//!\n//! @see DEFUN_DLD\n\n// The order of this macro for name = foo is again:\n// 1. Forward declaration of Ffoo.\n// 2. Definition of installation function Gfoo.\n// 3. Definition of Ffoo.\n\n#define DEFMETHOD_DLD(name, interp_name, args_name, nargout_name, doc)  \\\n  FORWARD_DECLARE_METHOD (name);                                        \\\n  DEFINE_FUN_INSTALLER_FUN (name, doc)                                  \\\n  DECLARE_METHOD (name, interp_name, args_name, nargout_name)\n\n#define DEFMETHODX_DLD(name, fname, gname, interp_name, args_name,      \\\n                       nargout_name, doc)                               \\\n  FORWARD_DECLARE_METHODX (fname);                                      \\\n  DEFINE_FUNX_INSTALLER_FUN (name, fname, gname, doc)                   \\\n  DECLARE_METHODX (fname, interp_name, args_name, nargout_name)\n\n// The same as the above, but declare the functions as static.\n// NOTE: These macros should not be used directly.\n\n#define DEFUN_STATIC_DLD(name, args_name, nargout_name, doc)    \\\n  FORWARD_DECLARE_STATIC_FUN (name);                            \\\n  DEFINE_FUN_INSTALLER_FUN (name, doc)                          \\\n  DECLARE_STATIC_FUN (name, args_name, nargout_name)\n\n#define DEFUNX_STATIC_DLD(name, fname, gname, args_name,        \\\n                          nargout_name, doc)                    \\\n  FORWARD_DECLARE_STATIC_FUNX (fname);                          \\\n  DEFINE_FUNX_INSTALLER_FUN (name, fname, gname, doc)           \\\n  DECLARE_STATIC_FUNX (fname, args_name, nargout_name)\n\n#define DEFMETHOD_STATIC_DLD(name, interp_name, args_name,              \\\n                             nargout_name, doc)                         \\\n  FORWARD_DECLARE_STATIC_METHOD (name);                                 \\\n  DEFINE_FUN_INSTALLER_FUN (name, doc)                                  \\\n  DECLARE_STATIC_METHOD (name, interp_name, args_name, nargout_name)\n\n#define DEFMETHODX_STATIC_DLD(name, fname, gname, interp_name,          \\\n                              args_name, nargout_name, doc)             \\\n  FORWARD_DECLARE_STATIC_METHODX (fname);                               \\\n  DEFINE_FUNX_INSTALLER_FUN (name, fname, gname, doc)                   \\\n  DECLARE_STATIC_METHODX (fname, interp_name, args_name, nargout_name)\n\n// The oct-conf-post.h file defines OCTAVE_USE_STATIC_DEFUN to force all\n// dynamically loaded interpreter functions and methods to be static.\n\n#if defined (OCTAVE_USE_STATIC_DEFUN)\n#  undef DEFUN_DLD\n#  undef DEFUNX_DLD\n#  undef DEFMETHOD_DLD\n#  undef DEFMETHODX_DLD\n\n#  define DEFUN_DLD DEFUN_STATIC_DLD\n#  define DEFUNX_DLD DEFUNX_STATIC_DLD\n#  define DEFMETHOD_DLD DEFMETHOD_STATIC_DLD\n#  define DEFMETHODX_DLD DEFMETHODX_STATIC_DLD\n#endif\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/defun-int.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_defun_int_h)\n#define octave_defun_int_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"ov-builtin.h\"\n#include \"ov-dld-fcn.h\"\n#include \"version.h\"\n\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nOCTAVE_NORETURN extern OCTINTERP_API void print_usage ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void print_usage (const std::string&);\n\nextern OCTINTERP_API void check_version (const std::string& version,\n                                         const std::string& fcn);\n\nextern OCTINTERP_API void\ninstall_dld_function (octave_dld_function::fcn f, const std::string& name,\n                      const dynamic_library& shl, const std::string& doc,\n                      bool relative = false);\n\nextern OCTINTERP_API void\ninstall_dld_function (octave_dld_function::meth m, const std::string& name,\n                      const dynamic_library& shl, const std::string& doc,\n                      bool relative = false);\n\nextern OCTINTERP_API void\ninstall_mex_function (void *fptr, bool fmex, const std::string& name,\n                      const dynamic_library& shl, bool relative = false);\n\n// Gets the shlib of the currently executing DLD function, if any.\nextern OCTINTERP_API dynamic_library get_current_shlib ();\n\nOCTAVE_END_NAMESPACE(octave)\n\n// Some of these functions are widely used, so maybe we should avoid\n// deprecating them for now?\n\nOCTAVE_NORETURN inline void print_usage ()\n{\n  octave::print_usage ();\n}\n\nOCTAVE_NORETURN inline void print_usage (const std::string& name)\n{\n  octave::print_usage (name);\n}\n\ninline void\ncheck_version (const std::string& version, const std::string& fcn)\n{\n  octave::check_version (version, fcn);\n}\n\ninline void\ninstall_dld_function (octave_dld_function::fcn f, const std::string& name,\n                      const octave::dynamic_library& shl,\n                      const std::string& doc, bool relative = false)\n{\n  octave::install_dld_function (f, name, shl, doc, relative);\n}\n\ninline void\ninstall_dld_function (octave_dld_function::meth m, const std::string& name,\n                      const octave::dynamic_library& shl,\n                      const std::string& doc, bool relative = false)\n{\n  octave::install_dld_function (m, name, shl, doc, relative);\n}\n\ninline void\ninstall_mex_function (void *fptr, bool fmex, const std::string& name,\n                      const octave::dynamic_library& shl,\n                      bool relative = false)\n{\n  octave::install_mex_function (fptr, fmex, name, shl, relative);\n}\n\n// Gets the shlib of the currently executing DLD function, if any.\ninline octave::dynamic_library get_current_shlib ()\n{\n  return octave::get_current_shlib ();\n}\n\n#define FORWARD_DECLARE_FUNX(name)              \\\n  extern OCTAVE_EXPORT octave_value_list        \\\n  name (const octave_value_list&, int)\n\n#define FORWARD_DECLARE_METHODX(name)                           \\\n  extern OCTAVE_EXPORT octave_value_list                        \\\n  name (octave::interpreter&, const octave_value_list&, int)\n\n#define FORWARD_DECLARE_FUN(name)               \\\n  FORWARD_DECLARE_FUNX (F ## name)\n\n#define FORWARD_DECLARE_METHOD(name)            \\\n  FORWARD_DECLARE_METHODX (F ## name)\n\n#define DECLARE_FUNX(name, args_name, nargout_name)             \\\n  OCTAVE_EXPORT octave_value_list                               \\\n  name (const octave_value_list& args_name, int nargout_name)\n\n#define DECLARE_METHODX(name, interp_name, args_name, nargout_name)     \\\n  OCTAVE_EXPORT octave_value_list                                       \\\n  name (octave::interpreter& interp_name,                               \\\n        const octave_value_list& args_name, int nargout_name)\n\n#define DECLARE_FUN(name, args_name, nargout_name)      \\\n  DECLARE_FUNX (F ## name, args_name, nargout_name)\n\n#define DECLARE_METHOD(name, interp_name, args_name, nargout_name)      \\\n  DECLARE_METHODX (F ## name, interp_name, args_name, nargout_name)\n\n#define FORWARD_DECLARE_STATIC_FUNX(name)       \\\n  static octave_value_list                      \\\n  name (const octave_value_list&, int)\n\n#define FORWARD_DECLARE_STATIC_METHODX(name)                    \\\n  static octave_value_list                                      \\\n  name (octave::interpreter&, const octave_value_list&, int)\n\n#define FORWARD_DECLARE_STATIC_FUN(name)        \\\n  FORWARD_DECLARE_STATIC_FUNX (F ## name)\n\n#define FORWARD_DECLARE_STATIC_METHOD(name)     \\\n  FORWARD_DECLARE_STATIC_METHODX (F ## name)\n\n#define DECLARE_STATIC_FUNX(name, args_name, nargout_name)      \\\n  static octave_value_list                                      \\\n  name (const octave_value_list& args_name, int nargout_name)\n\n#define DECLARE_STATIC_METHODX(name, interp_name, args_name, nargout_name) \\\n  static octave_value_list                                              \\\n  name (octave::interpreter& interp_name,                               \\\n        const octave_value_list& args_name, int nargout_name)\n\n#define DECLARE_STATIC_FUN(name, args_name, nargout_name)       \\\n  DECLARE_STATIC_FUNX (F ## name, args_name, nargout_name)\n\n#define DECLARE_STATIC_METHOD(name, interp_name, args_name, nargout_name) \\\n  DECLARE_STATIC_METHODX (F ## name, interp_name, args_name, nargout_name)\n\n// Define the code that will be used to insert the new function into\n// the symbol table.  We look for this name instead of the actual\n// function so that we can easily install the doc std::string too.\n\ntypedef bool (*octave_dld_fcn_installer) (const octave::dynamic_library&, bool relative);\n\ntypedef octave_function *\n  (*octave_dld_fcn_getter) (const octave::dynamic_library&, bool relative);\n\n#if defined (OCTAVE_SOURCE)\n#  define DEFINE_FUN_INSTALLER_FUN(name, doc)                           \\\n  DEFINE_FUNX_INSTALLER_FUN(#name, F ## name, G ## name, \"external-doc\")\n#else\n#  define DEFINE_FUN_INSTALLER_FUN(name, doc)                   \\\n  DEFINE_FUNX_INSTALLER_FUN(#name, F ## name, G ## name, doc)\n#endif\n\n#define DEFINE_FUNX_INSTALLER_FUN(name, fname, gname, doc)              \\\n  extern \"C\"                                                            \\\n  OCTAVE_EXPORT                                                         \\\n  octave_function *                                                     \\\n  gname (const octave::dynamic_library& shl, bool relative)             \\\n  {                                                                     \\\n    check_version (OCTAVE_API_VERSION, name);                           \\\n                                                                        \\\n    octave_dld_function *fcn                                            \\\n      = octave_dld_function::create (fname, shl, name, doc);            \\\n                                                                        \\\n    if (relative)                                                       \\\n      fcn->mark_relative ();                                            \\\n                                                                        \\\n    return fcn;                                                         \\\n  }\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/defun.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"defun.h\"\n#include \"dynamic-ld.h\"\n#include \"error.h\"\n#include \"help.h\"\n#include \"ov.h\"\n#include \"ov-builtin.h\"\n#include \"ov-dld-fcn.h\"\n#include \"ov-fcn.h\"\n#include \"ov-mex-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"ovl.h\"\n#include \"oct-lvalue.h\"\n#include \"pager.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"symtab.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Print the usage part of the doc string of FCN (user-defined or DEFUN).\nOCTAVE_NORETURN void\nprint_usage ()\n{\n  tree_evaluator& tw = __get_evaluator__ ();\n\n  const octave_function *cur = tw.current_function ();\n\n  if (cur)\n    print_usage (cur->name ());\n  else\n    error (\"print_usage: invalid function\");\n}\n\nOCTAVE_NORETURN void\nprint_usage (const std::string& name)\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  interp.feval (\"print_usage\", octave_value (name), 0);\n\n  // This code is unreachable as print_usage.m will never return.\n  // Let the compiler know that by using a call to error() which never returns.\n  error (\"print_usage: Internal error, please report.\");\n}\n\nvoid\ncheck_version (const std::string& version, const std::string& fcn)\n{\n  if (version != OCTAVE_API_VERSION)\n    {\n      error (\"API version %s found in .oct file function '%s'\\n\"\n             \"       does not match the running Octave (API version %s)\\n\"\n             \"       this can lead to incorrect results or other failures\\n\"\n             \"       you can fix this problem by recompiling this .oct file\",\n             version.c_str (), fcn.c_str (), OCTAVE_API_VERSION);\n    }\n}\n\n// Install variables and functions in the symbol tables.\n\nvoid\ninstall_dld_function (octave_dld_function::fcn f, const std::string& name,\n                      const dynamic_library& shl, const std::string& doc,\n                      bool relative)\n{\n  octave_dld_function *fcn = new octave_dld_function (f, shl, name, doc);\n\n  if (relative)\n    fcn->mark_relative ();\n\n  octave_value fval (fcn);\n\n  symbol_table& symtab = __get_symbol_table__ ();\n\n  symtab.install_built_in_function (name, fval);\n}\n\nvoid\ninstall_dld_function (octave_dld_function::meth m, const std::string& name,\n                      const dynamic_library& shl, const std::string& doc,\n                      bool relative)\n{\n  octave_dld_function *fcn = new octave_dld_function (m, shl, name, doc);\n\n  if (relative)\n    fcn->mark_relative ();\n\n  octave_value fval (fcn);\n\n  symbol_table& symtab = __get_symbol_table__ ();\n\n  symtab.install_built_in_function (name, fval);\n}\n\nvoid\ninstall_mex_function (void *fptr, bool fmex, const std::string& name,\n                      const dynamic_library& shl, bool relative)\n{\n  octave_mex_function *fcn = new octave_mex_function (fptr, fmex, shl, name);\n\n  if (relative)\n    fcn->mark_relative ();\n\n  octave_value fval (fcn);\n\n  symbol_table& symtab = __get_symbol_table__ ();\n\n  symtab.install_built_in_function (name, fval);\n}\n\ndynamic_library\nget_current_shlib ()\n{\n  dynamic_library retval;\n\n  tree_evaluator& tw = __get_evaluator__ ();\n\n  octave_function *curr_fcn = tw.current_function ();\n\n  if (curr_fcn)\n    {\n      if (curr_fcn->is_dld_function ())\n        {\n          octave_dld_function *dld\n            = dynamic_cast<octave_dld_function *> (curr_fcn);\n          retval = dld->get_shlib ();\n        }\n      else if (curr_fcn->is_mex_function ())\n        {\n          octave_mex_function *mex\n            = dynamic_cast<octave_mex_function *> (curr_fcn);\n          retval = mex->get_shlib ();\n        }\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/defun.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_defun_h)\n#define octave_defun_h 1\n\n#include \"octave-config.h\"\n\n#if defined (octave_defun_dld_h)\n#  error defun.h and defun-dld.h both included in same file!\n#endif\n\n#include \"defun-int.h\"\n\n//! Macro to define a builtin function.\n//!\n//! For detailed information, see \\ref Macros.\n//!\n//! @param name The **unquoted** name of the function that should be installed\n//!             on the 'octave::symbol_table' and can be called by the\n//!             interpreter.  Internally, the function name is prepended by an\n//!             'F'.\n//! @param args_name The name of the octave_value_list variable used to pass\n//!                  the argument list to this function.  If this value is\n//!                  omitted, the function cannot access the argument list.\n//! @param nargout_name The name of the 'int' variable used to pass the number\n//!                     of output arguments this function is expected to\n//!                     produce from the caller.  If this value is\n//!                     omitted, the function cannot access this number.\n//! @param doc Texinfo help text (docstring) for the function.\n//!\n//! @see DEFUNX\n\n#define DEFUN(name, args_name, nargout_name, doc)       \\\n  DECLARE_FUN (name, args_name, nargout_name)\n\n//! Macro to define a builtin function with certain internal name.\n//!\n//! @warning Consider to use #DEFUN, unless you have good reason.\n//!\n//! For detailed information, see \\ref Macros.\n//!\n//! This macro can be used when @p name cannot be used directly (for example if\n//! it is already defined as a macro).  In that case, @p name is already a\n//! quoted string (thus unaffected by macros), and the internal name of the\n//! function is given by @p fname.\n//!\n//! @param name The **quoted** name of the function that should be callable\n//!             by the interpreter.\n//! @param fname The internal **unquoted** name of the function.  This internal\n//!              name is by convention prepended by an 'F'.\n//! @param args_name The name of the octave_value_list variable used to pass\n//!                  the argument list to this function.  If this value is\n//!                  omitted, the function cannot access the argument list.\n//! @param nargout_name The name of the 'int' variable used to pass the number\n//!                     of output arguments this function is expected to\n//!                     produce from the caller.  If this value is\n//!                     omitted, the function cannot access this number.\n//! @param doc Texinfo help text (docstring) for the function.\n//!\n//! @see DEFUN\n\n#define DEFUNX(name, fname, args_name, nargout_name, doc)       \\\n  DECLARE_FUNX (fname, args_name, nargout_name)\n\n//! Macro to define a builtin method.\n//!\n//! For detailed information, see \\ref Macros.\n//!\n//! @param name The **unquoted** name of the method that should be installed\n//!             on the 'octave::symbol_table' and can be called by the\n//!             interpreter.  Internally, the method name is prepended by an\n//!             'F'.\n//! @param interp_name The name of the 'octave::interpreter' reference that can\n//!                    be used by this method.  If this value is omitted,\n//!                    there is no access to the interpreter and one should\n//!                    use #DEFUN to define a function instead.\n//! @param args_name The name of the octave_value_list variable used to pass\n//!                  the argument list to this method.  If this value is\n//!                  omitted, the method cannot access the argument list.\n//! @param nargout_name The name of the 'int' variable used to pass the number\n//!                     of output arguments this method is expected to\n//!                     produce from the caller.  If this value is\n//!                     omitted, the method cannot access this number.\n//! @param doc Texinfo help text (docstring) for the method.\n//!\n//! @see DEFMETHODX\n\n#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)      \\\n  DECLARE_METHOD (name, interp_name, args_name, nargout_name)\n\n//! Macro to define a builtin method with certain internal name.\n//!\n//! @warning Consider to use #DEFMETHOD, unless you have good reason.\n//!\n//! For detailed information, see \\ref Macros.\n//!\n//! This macro can be used when @p name cannot be used directly (for example if\n//! it is already defined as a macro).  In that case, @p name is already a\n//! quoted string (thus unaffected by macros), and the internal name of the\n//! method is given by @p fname.\n//!\n//! @param name The **quoted** name of the method that should be callable\n//!             by the interpreter.\n//! @param fname The internal **unquoted** name of the method.  This internal\n//!              name is by convention prepended by an 'F'.\n//! @param interp_name The name of the 'octave::interpreter' reference that can\n//!                    be used by this method.  If this value is omitted,\n//!                    there is no access to the interpreter and one should\n//!                    use #DEFUNX to define a function instead.\n//! @param args_name The name of the octave_value_list variable used to pass\n//!                  the argument list to this method.  If this value is\n//!                  omitted, the method cannot access the argument list.\n//! @param nargout_name The name of the 'int' variable used to pass the number\n//!                     of output arguments this method is expected to\n//!                     produce from the caller.  If this value is\n//!                     omitted, the method cannot access this number.\n//! @param doc Texinfo help text (docstring) for the method.\n//!\n//! @see DEFMETHOD\n\n#define DEFMETHODX(name, fname, interp_name, args_name, nargout_name, doc) \\\n  DECLARE_METHODX (fname, interp_name, args_name, nargout_name)\n\n// These macros are obsolete but provided for backward compatibility.\n#define DEFCONSTFUN DEFUN\n#define DEFCONSTMETHOD DEFMETHOD\n\n//! Macro to define an alias for another existing function name.\n//!\n//! For detailed information, see \\ref Macros.\n//!\n//! @param alias For another existing function name.\n//! @param name The name of the other existing function.\n//!\n//! @see DEFUN\n\n#define DEFALIAS(alias, name)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/display.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"singleton-cleanup.h\"\n\n#include \"cdisplay.h\"\n#include \"defun.h\"\n#include \"display.h\"\n#include \"error.h\"\n#include \"interpreter.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid display_info::initialize ()\n{\n  int avail = 0;\n\n  const char *msg\n    = octave_get_display_info (nullptr, &m_ht, &m_wd, &m_dp,\n                               &m_rx, &m_ry, &avail);\n\n  m_dpy_avail = avail;\n\n  if (msg)\n    m_msg = msg;\n}\n\nDEFMETHOD (have_window_system, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} have_window_system ()\nReturn true if a window system is available (X11, Windows, or Apple OS X)\nand false otherwise.\n@seealso{isguirunning}\n@end deftypefn */)\n{\n  display_info& dpy_info = interp.get_display_info ();\n\n  return ovl (dpy_info.display_available ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/display.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_display_h)\n#define octave_display_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nclass Matrix;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass display_info\n{\npublic:\n\n  // Create object with default values.  To be useful, you must call\n  // initialize to find the actual system parameters for the given\n  // display.\n\n  display_info ()\n    : m_rx (72), m_ry (72), m_ht (1), m_wd (1), m_dp (0),\n      m_dpy_avail (false), m_msg ()\n  { }\n\n  ~display_info () = default;\n\n  display_info (const display_info&) = default;\n\n  display_info& operator = (const display_info&) = default;\n\n  void initialize ();\n\n  double x_dpi () const { return m_rx; }\n\n  double y_dpi () const { return m_ry; }\n\n  int height () const { return m_ht; }\n\n  int width () const { return m_wd; }\n\n  int depth () const { return m_dp; }\n\n  bool display_available () const { return m_dpy_avail; }\n\n  std::string message () const { return m_msg; }\n\nprivate:\n\n  // X- and Y- Resolution of the display in dots (pixels) per inch.\n  double m_rx;\n  double m_ry;\n\n  // Height, width, and depth of the display.\n  int m_ht;\n  int m_wd;\n  int m_dp;\n\n  bool m_dpy_avail;\n\n  // Message associated with any initiailization failure.  Set if\n  // m_dpy_avail is false.\n  std::string m_msg;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/dynamic-ld.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n#include <list>\n\n#include \"file-stat.h\"\n#include \"oct-env.h\"\n#include \"oct-time.h\"\n\n#include \"defun.h\"\n#include \"dynamic-ld.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ov-fcn.h\"\n#include \"ov-dld-fcn.h\"\n#include \"ov-mex-fcn.h\"\n#include \"parse.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n#define STRINGIFY(s) STRINGIFY1(s)\n#define STRINGIFY1(s) #s\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\ndynamic_loader::shlibs_list::append (const dynamic_library& shl)\n{\n  m_lib_list.push_back (shl);\n}\n\nstd::list<std::string>\ndynamic_loader::shlibs_list::remove (dynamic_library& shl)\n{\n  std::list<std::string> removed_fcns;\n\n  for (auto p = m_lib_list.begin (); p != m_lib_list.end (); p++)\n    {\n      if (*p == shl)\n        {\n          m_lib_list.erase (p);\n\n          removed_fcns = shl.close ();\n\n          break;\n        }\n    }\n\n  return removed_fcns;\n}\n\ndynamic_library\ndynamic_loader::shlibs_list::find_file (const std::string& file_name) const\n{\n  dynamic_library retval;\n\n  for (const auto& lib : m_lib_list)\n    {\n      if (lib.file_name () == file_name)\n        {\n          retval = lib;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nvoid\ndynamic_loader::shlibs_list::display () const\n{\n  std::cerr << \"current shared libraries:\" << std::endl;\n  for (const auto& lib : m_lib_list)\n    std::cerr << \"  \" << lib.file_name () << std::endl;\n}\n\nvoid\ndynamic_loader::clear_function (const std::string& fcn_name)\n{\n  warning_with_id (\"Octave:reload-forces-clear\", \"  %s\", fcn_name.c_str ());\n\n  // FIXME: is there a way to avoid this?  Can we manage the list of\n  // functions that are loaded in the symbol table completely outside\n  // of the dynamic_loader class?\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  symtab.clear_dld_function (fcn_name);\n}\n\nvoid\ndynamic_loader::clear (dynamic_library& oct_file)\n{\n  if (oct_file.number_of_functions_loaded () > 1)\n    {\n      warning_with_id (\"Octave:reload-forces-clear\",\n                       \"reloading %s clears the following functions:\",\n                       oct_file.file_name ().c_str ());\n\n      std::list<std::string> removed_fcns = m_loaded_shlibs.remove (oct_file);\n\n      for (const auto& fcn_name : removed_fcns)\n        clear_function (fcn_name);\n    }\n  else\n    {\n      std::list<std::string> removed_fcns = m_loaded_shlibs.remove (oct_file);\n\n      // FIXME: is there a way to avoid this?  Can we manage the list\n      // of functions that are loaded in the symbol table completely\n      // outside of the dynamic_loader class?\n\n      symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n      for (const auto& fcn_name : removed_fcns)\n        symtab.clear_dld_function (fcn_name);\n    }\n}\n\noctave_function *\ndynamic_loader::load_oct (const std::string& fcn_name,\n                          const std::string& file_name,\n                          bool relative)\n{\n  octave_function *retval = nullptr;\n\n  unwind_protect_var<bool> restore_var (m_doing_load, true);\n\n  dynamic_library oct_file = m_loaded_shlibs.find_file (file_name);\n\n  if (oct_file && oct_file.is_out_of_date ())\n    clear (oct_file);\n\n  if (! oct_file)\n    {\n      oct_file.open (file_name);\n\n      if (oct_file)\n        m_loaded_shlibs.append (oct_file);\n    }\n\n  if (! oct_file)\n    error (\"%s is not a valid shared library\", file_name.c_str ());\n\n  void *function = oct_file.search (fcn_name, name_mangler);\n\n  if (! function)\n    {\n      // FIXME: can we determine this C mangling scheme\n      // automatically at run time or configure time?\n\n      function = oct_file.search (fcn_name, name_uscore_mangler);\n    }\n\n  if (function)\n    {\n      octave_dld_fcn_getter f\n        = reinterpret_cast<octave_dld_fcn_getter> (function);\n\n      retval = f (oct_file, relative);\n\n      if (! retval)\n        error (\"failed to install .oct file function '%s'\",\n               fcn_name.c_str ());\n    }\n\n  return retval;\n}\n\nvoid *\ndynamic_loader::try_load_mex (dynamic_library& mex_file,\n                              const std::string& fcn_name)\n{\n  // FCN_NAME is not used here, the mangler functions always return\n  // some form of \"mexFunction\".\n\n  void *function = mex_file.search (fcn_name, mex_mangler);\n\n  if (! function)\n    {\n      // FIXME: Can we determine this C mangling scheme\n      //        automatically at run time or configure time?\n\n      function = mex_file.search (fcn_name, mex_uscore_mangler);\n    }\n\n  return function;\n}\n\noctave_function *\ndynamic_loader::load_mex (const std::string& fcn_name,\n                          const std::string& file_name,\n                          bool /*relative*/)\n{\n  unwind_protect_var<bool> restore_var (m_doing_load, true);\n\n  dynamic_library mex_file = m_loaded_shlibs.find_file (file_name);\n\n  if (mex_file && mex_file.is_out_of_date ())\n    clear (mex_file);\n\n  if (! mex_file)\n    {\n      mex_file.open (file_name);\n\n      if (mex_file)\n        m_loaded_shlibs.append (mex_file);\n    }\n\n  if (! mex_file)\n    error (\"%s is not a valid shared library\", file_name.c_str ());\n\n  void *function = try_load_mex (mex_file, fcn_name);\n\n  if (! function)\n    error (\"failed to install .mex file function '%s'\", fcn_name.c_str ());\n\n  void *symbol = mex_file.search (\"__mx_has_interleaved_complex__\");\n\n  bool interleaved = symbol != nullptr;\n\n  if (symbol)\n    mex_file.remove (\"__mx_has_interleaved_complex__\");\n\n  int *mex_soversion =\n    reinterpret_cast<int *> (mex_file.search (\"__octave_mex_soversion__\"));\n\n  if (! mex_soversion)\n    error (\"No SOVERSION found in .mex file function '%s'.\\n\"\n           \"       This can lead to incorrect results or other failures.\\n\"\n           \"       You can fix this problem by recompiling this .mex file\",\n           fcn_name.c_str ());\n\n  unwind_action unload_mex_soversion\n    ([&mex_file] () { mex_file.remove (\"__octave_mex_soversion__\"); });\n\n  if (*mex_soversion != OCTAVE_MEX_SOVERSION)\n    error (\"SOVERSION %d found in .mex file function '%s'\\n\"\n           \"       does not match the running Octave (SOVERSION %d).\\n\"\n           \"       This can lead to incorrect results or other failures.\\n\"\n           \"       You can fix this problem by recompiling this .mex file\",\n           *mex_soversion, fcn_name.c_str (), OCTAVE_MEX_SOVERSION);\n\n  return new octave_mex_function (function, interleaved, mex_file, fcn_name);\n}\n\nbool\ndynamic_loader::remove_oct (const std::string& fcn_name,\n                            dynamic_library& shl)\n{\n  bool retval = false;\n\n  // We don't need to do anything if this is called because we are in\n  // the process of reloading a .oct file that has changed.\n\n  if (! m_doing_load)\n    {\n      retval = shl.remove (fcn_name);\n\n      if (shl.number_of_functions_loaded () == 0)\n        m_loaded_shlibs.remove (shl);\n    }\n\n  return retval;\n}\n\nbool\ndynamic_loader::remove_mex (const std::string& fcn_name,\n                            dynamic_library& shl)\n{\n  // Use the same procedure as for oct files.\n  return remove_oct (fcn_name, shl);\n}\n\nstd::string\ndynamic_loader::name_mangler (const std::string& name)\n{\n  return 'G' + name;\n}\n\nstd::string\ndynamic_loader::name_uscore_mangler (const std::string& name)\n{\n  return \"_G\" + name;\n}\n\nstd::string\ndynamic_loader::mex_mangler (const std::string&)\n{\n  return \"mexFunction\";\n}\n\nstd::string\ndynamic_loader::mex_uscore_mangler (const std::string&)\n{\n  return \"_mexFunction\";\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/dynamic-ld.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dynamic_ld_h)\n#define octave_dynamic_ld_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n\n#include \"oct-shlib.h\"\n\nclass octave_function;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass dynamic_loader\n{\nprivate:\n\n  class shlibs_list\n  {\n  public:\n\n    typedef std::list<dynamic_library>::iterator iterator;\n    typedef std::list<dynamic_library>::const_iterator const_iterator;\n\n    shlibs_list () : m_lib_list () { }\n\n    OCTAVE_DISABLE_COPY_MOVE (shlibs_list)\n\n    ~shlibs_list () = default;\n\n    void append (const dynamic_library& shl);\n\n    std::list<std::string> remove (dynamic_library& shl);\n\n    dynamic_library find_file (const std::string& file_name) const;\n\n    void display () const;\n\n  private:\n\n    // List of libraries we have loaded.\n    std::list<dynamic_library> m_lib_list;\n  };\n\n\npublic:\n\n  dynamic_loader () = delete;\n\n  dynamic_loader (interpreter& interp)\n    : m_interpreter (interp), m_loaded_shlibs (), m_doing_load (false)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (dynamic_loader)\n\n  virtual ~dynamic_loader () = default;\n\n  octave_function *\n  load_oct (const std::string& fcn_name,\n            const std::string& file_name = \"\",\n            bool relative = false);\n\n  octave_function *\n  load_mex (const std::string& fcn_name,\n            const std::string& file_name = \"\",\n            bool relative = false);\n\n  bool remove_oct (const std::string& fcn_name,\n                   dynamic_library& shl);\n\n  bool remove_mex (const std::string& fcn_name,\n                   dynamic_library& shl);\n\nprivate:\n\n  void clear_function (const std::string& fcn_name);\n\n  void clear (dynamic_library& oct_file);\n\n  interpreter& m_interpreter;\n\n  shlibs_list m_loaded_shlibs;\n\n  bool m_doing_load;\n\n  static std::string name_mangler (const std::string& name);\n\n  static std::string name_uscore_mangler (const std::string& name);\n\n  static std::string mex_mangler (const std::string& name);\n\n  static std::string mex_uscore_mangler (const std::string& name);\n\n  static void * try_load_mex (dynamic_library& mex_file, const std::string& fcn_name);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/environment.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"dir-ops.h\"\n#include \"oct-env.h\"\n#include \"file-stat.h\"\n#include \"pathsearch.h\"\n#include \"str-vec.h\"\n\n#include \"defaults.h\"\n#include \"defun.h\"\n#include \"environment.h\"\n#include \"interpreter.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic void append_to_shell_path (const std::string& exec_path)\n{\n  // FIXME: should there be a way to remove a previous setting from\n  // PATH?\n\n  if (exec_path.empty ())\n    return;\n\n  // FIXME: should we really be modifying PATH in the environment?\n\n  std::string shell_path = sys::env::getenv (\"PATH\");\n\n  if (shell_path.empty ())\n    sys::env::putenv (\"PATH\", exec_path);\n  else\n    {\n      // If PATH doesn't already have exec_path, append it.\n      // FIXME: should we search for the elements individually, and\n      // only append those that are missing?\n\n      std::string path_sep = directory_path::path_sep_str ();\n\n      if (shell_path.find (exec_path) == std::string::npos)\n        sys::env::putenv (\"PATH\", shell_path + path_sep + exec_path);\n    }\n}\n\noctave_value\nenvironment::editor (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_editor, args, nargout, \"EDITOR\", false);\n}\n\n\noctave_value\nenvironment::exec_path (const octave_value_list& args, int nargout)\n{\n  octave_value retval\n    = set_internal_variable (m_exec_path, args, nargout, \"EXEC_PATH\", false);\n\n  append_to_shell_path (m_exec_path);\n\n  return retval;\n}\n\nstd::string\nenvironment::exec_path (const std::string& path)\n{\n  std::string old_val = set (m_exec_path, path);\n\n  append_to_shell_path (m_exec_path);\n\n  return old_val;\n}\n\noctave_value\nenvironment::image_path (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_image_path, args, nargout, \"IMAGE_PATH\",\n                                false);\n}\n\nstd::string\nenvironment::init_editor ()\n{\n  std::string retval = \"emacs\";\n\n  std::string env_editor = sys::env::getenv (\"EDITOR\");\n\n  if (! env_editor.empty ())\n    retval = env_editor;\n\n  return retval;\n}\n\nstd::string\nenvironment::init_exec_path ()\n{\n  std::string exec_path = sys::env::getenv (\"OCTAVE_EXEC_PATH\");\n\n  std::string path_sep = directory_path::path_sep_str ();\n\n  if (exec_path.empty ())\n    exec_path = (config::local_ver_arch_lib_dir () + path_sep\n                 + config::local_api_arch_lib_dir () + path_sep\n                 + config::local_arch_lib_dir () + path_sep\n                 + config::arch_lib_dir () + path_sep\n                 + config::bin_dir ());\n\n  append_to_shell_path (exec_path);\n\n  return exec_path;\n}\n\nstd::string\nenvironment::init_image_path ()\n{\n  std::string image_path = \".\";\n\n  std::string path_sep = directory_path::path_sep_str ();\n\n  std::string env_path = sys::env::getenv (\"OCTAVE_IMAGE_PATH\");\n\n  if (! env_path.empty ())\n    image_path += path_sep + env_path;\n\n  std::string gen_path = genpath (config::image_dir (), \"\");\n\n  if (! gen_path.empty ())\n    image_path += path_sep + gen_path;\n\n  return image_path;\n}\n\nDEFMETHOD (EDITOR, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} EDITOR ()\n@deftypefnx {} {@var{old_val} =} EDITOR (@var{new_val})\n@deftypefnx {} {@var{old_val} =} EDITOR (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the default text editor when\nusing the CLI.\n\nThe default value is taken from the environment variable\n@w{@env{EDITOR}}@ when Octave starts.  If the environment variable is not\ninitialized, @w{@env{EDITOR}}@ will be set to @qcode{\"emacs\"}.\n\n@emph{Note:} This setting applies when running the CLI@.  When using the\nOctave GUI the default editor is specified in the Editor tab of Preferences.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n\n@seealso{edit, edit_history}\n@end deftypefn */)\n{\n  environment& env = interp.get_environment ();\n\n  return env.editor (args, nargout);\n}\n\n/*\n%!test\n%! orig_val = EDITOR ();\n%! old_val = EDITOR (\"X\");\n%! assert (orig_val, old_val);\n%! assert (EDITOR (), \"X\");\n%! EDITOR (orig_val);\n%! assert (EDITOR (), orig_val);\n\n%!error EDITOR (1, 2)\n*/\n\nDEFMETHOD (EXEC_PATH, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} EXEC_PATH ()\n@deftypefnx {} {@var{old_val} =} EXEC_PATH (@var{new_val})\n@deftypefnx {} {@var{old_val} =} EXEC_PATH (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies a colon separated\nlist of directories to append to the shell PATH when executing external\nprograms.\n\nThe initial value of is taken from the environment variable\n@w{@env{OCTAVE_EXEC_PATH}}, but that value can be overridden by the command\nline argument @option{--exec-path PATH}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n\n@seealso{IMAGE_PATH, OCTAVE_HOME, OCTAVE_EXEC_HOME}\n@end deftypefn */)\n{\n  environment& env = interp.get_environment ();\n\n  return env.exec_path (args, nargout);\n}\n\n/*\n%!test\n%! orig_val = EXEC_PATH ();\n%! old_val = EXEC_PATH (\"X\");\n%! assert (orig_val, old_val);\n%! assert (EXEC_PATH (), \"X\");\n%! EXEC_PATH (orig_val);\n%! assert (EXEC_PATH (), orig_val);\n\n%!error EXEC_PATH (1, 2)\n*/\n\nDEFMETHOD (IMAGE_PATH, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} IMAGE_PATH ()\n@deftypefnx {} {@var{old_val} =} IMAGE_PATH (@var{new_val})\n@deftypefnx {} {@var{old_val} =} IMAGE_PATH (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies a colon separated\nlist of directories in which to search for image files.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n\n@seealso{EXEC_PATH, OCTAVE_HOME, OCTAVE_EXEC_HOME}\n@end deftypefn */)\n{\n  environment& env = interp.get_environment ();\n\n  return env.image_path (args, nargout);\n}\n\n/*\n%!test\n%! orig_val = IMAGE_PATH ();\n%! old_val = IMAGE_PATH (\"X\");\n%! assert (orig_val, old_val);\n%! assert (IMAGE_PATH (), \"X\");\n%! IMAGE_PATH (orig_val);\n%! assert (IMAGE_PATH (), orig_val);\n\n%!error IMAGE_PATH (1, 2)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/environment.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_environment_h)\n#define octave_environment_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass environment\n{\npublic:\n\n  environment ()\n    : m_editor (init_editor ()),\n      m_exec_path (init_exec_path ()),\n      m_image_path (init_image_path ())\n  { }\n\n  OCTAVE_DEFAULT_COPY_DELETE (environment)\n\n  octave_value editor (const octave_value_list& args, int nargout);\n\n  std::string editor () const { return m_editor; }\n\n  std::string editor (const std::string& ed)\n  {\n    return set (m_editor, ed);\n  }\n\n  octave_value exec_path (const octave_value_list& args, int nargout);\n\n  std::string exec_path () const { return m_exec_path; }\n\n  std::string exec_path (const std::string& path);\n\n  octave_value image_path (const octave_value_list& args, int nargout);\n\n  std::string image_path () const { return m_image_path; }\n\n  std::string image_path (const std::string& path)\n  {\n    return set (m_image_path, path);\n  }\n\nprivate:\n\n  std::string m_editor;\n\n  std::string m_exec_path;\n\n  std::string m_image_path;\n\n  static std::string init_editor ();\n\n  static std::string init_exec_path ();\n\n  static std::string init_image_path ();\n\n  std::string set (std::string& var, const std::string& new_val)\n  {\n    std::string old_val = var;\n    var = new_val;\n    return old_val;\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/error.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdarg>\n#include <cstdlib>\n#include <cstring>\n\n#include <algorithm>\n#include <iomanip>\n#include <iostream>\n#include <sstream>\n#include <string>\n\n#include \"quit.h\"\n\n#include \"bp-table.h\"\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"event-manager.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"octave.h\"\n#include \"ov-usr-fcn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"pt-eval.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nstatic std::string\nformat_message (const char *fmt, va_list args)\n{\n  if (! fmt)\n    return \"\";\n\n  std::ostringstream output_buf;\n\n  octave::vformat (output_buf, fmt, args);\n\n  return output_buf.str ();\n}\n\nOCTAVE_NORETURN\nstatic void\nerror_1 (octave::execution_exception& ee, const char *id, const char *fmt,\n         va_list args)\n{\n  octave::error_system& es = octave::__get_error_system__ ();\n\n  es.error_1 (ee, id, fmt, args);\n}\n\nOCTAVE_NORETURN\nstatic void\nerror_1 (const char *id, const char *fmt, va_list args)\n{\n  octave::error_system& es = octave::__get_error_system__ ();\n\n  es.error_1 (id, fmt, args);\n}\n\nstatic int\ncheck_state (const std::string& state)\n{\n  // -1: not found\n  //  0: found, \"off\"\n  //  1: found, \"on\"\n  //  2: found, \"error\"\n\n  if (state == \"off\")\n    return 0;\n  else if (state == \"on\")\n    return 1;\n  else if (state == \"error\")\n    return 2;\n  else\n    return -1;\n}\n\nstatic void\nvwarning (const char *id, const char *fmt, va_list args)\n{\n  octave::error_system& es = octave::__get_error_system__ ();\n\n  es.vwarning (id, fmt, args);\n}\n\nstatic void\ndefun_usage_message (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  error_1 (\"\", fmt, args);\n  va_end (args);\n}\n\ntypedef void (*error_fcn)(const char *, const char *, ...);\n\nstatic std::string\nhandle_message (error_fcn f, const char *id, const char *msg,\n                const octave_value_list& args, bool have_fmt)\n{\n  std::string retval;\n\n  std::string tmpstr;\n\n  if (args.length () > 0)\n    {\n      octave_value arg;\n\n      if (have_fmt)\n        {\n          octave_value_list tmp = octave::Fsprintf (args, 1);\n          arg = tmp(0);\n        }\n      else\n        arg = args(0);\n\n      if (arg.is_defined ())\n        {\n          if (arg.isempty ())\n            return retval;\n          else if (arg.is_string ())\n            {\n              tmpstr = arg.string_value ();  // 2-stage assignment required\n              msg = tmpstr.c_str ();         // in order to generate pointer\n                                             // to valid memory.\n            }\n        }\n    }\n\n  // Ugh.\n\n  std::size_t len = strlen (msg);\n\n  if (len > 0)\n    {\n      if (msg[len - 1] == '\\n')\n        {\n          if (len > 1)\n            {\n              std::string tmp_msg (msg, len - 1);\n              f (id, \"%s\\n\", tmp_msg.c_str ());\n              retval = tmp_msg;\n            }\n        }\n      else\n        {\n          f (id, \"%s\", msg);\n          retval = msg;\n        }\n    }\n\n  return retval;\n}\n\n// Determine whether the first argument to error or warning function\n// should be handled as the message identifier or as the format string.\n\nstatic bool\nmaybe_extract_message_id (const std::string& caller,\n                          const octave_value_list& args,\n                          octave_value_list& nargs,\n                          std::string& id)\n{\n  nargs = args;\n  id = \"\";\n\n  int nargin = args.length ();\n\n  bool have_fmt = nargin > 1;\n\n  if (nargin > 0)\n    {\n      std::string arg1 = args(0).xstring_value (\"%s: MESSAGE must be a string\",\n                                                caller.c_str ());\n\n      // For compatibility with Matlab, an identifier must contain ':',\n      // but not at the beginning or the end, and it must not contain '%'\n      // (even if it is not a valid conversion operator) or whitespace.\n\n      if (arg1.find_first_of (\"% \\f\\n\\r\\t\\v\") == std::string::npos\n          && arg1.find (':') != std::string::npos\n          && arg1[0] != ':'\n          && arg1.back () != ':')\n        {\n          if (nargin > 1)\n            {\n              id = arg1;\n\n              nargs.resize (nargin-1);\n\n              for (int i = 1; i < nargin; i++)\n                nargs(i-1) = args(i);\n            }\n          else\n            nargs(0) = \"call to \" + caller\n                       + \" with message identifier '\" + arg1\n                       + \"' requires message\";\n        }\n    }\n\n  return have_fmt;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic octave_scalar_map\ninit_warning_options (const std::string& state)\n{\n  octave_scalar_map initw;\n\n  initw.setfield (\"identifier\", \"all\");\n  initw.setfield (\"state\", state);\n\n  return initw;\n}\n\nstatic octave_map\ninit_error_stack (interpreter& interp)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.empty_backtrace ();\n}\n\nerror_system::error_system (interpreter& interp)\n  : m_interpreter (interp),\n    m_debug_on_error (false),\n    m_debug_on_caught (false),\n    m_debug_on_warning (false),\n    m_discard_warning_messages (false),\n    m_beep_on_error (false),\n    m_backtrace_on_warning (true),\n    m_verbose_warning (false),\n    m_quiet_warning (false),\n    m_warning_options (init_warning_options (\"on\")),\n    m_last_error_message (),\n    m_last_warning_message (),\n    m_last_warning_id (),\n    m_last_error_id (),\n    m_last_error_stack (init_error_stack (interp))\n{\n  initialize_default_warning_state ();\n}\n\noctave_value\nerror_system::debug_on_error (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_debug_on_error, args, nargout,\n                                \"debug_on_error\");\n}\n\noctave_value\nerror_system::debug_on_caught (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_debug_on_caught, args, nargout,\n                                \"debug_on_caught\");\n}\n\noctave_value\nerror_system::debug_on_warning (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_debug_on_warning, args, nargout,\n                                \"debug_on_warning\");\n}\n\noctave_value\nerror_system::discard_warning_messages (const octave_value_list& args,\n                                        int nargout)\n{\n  return set_internal_variable (m_discard_warning_messages, args, nargout,\n                                \"discard_warning_messages\");\n}\n\noctave_value\nerror_system::beep_on_error (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_beep_on_error, args, nargout,\n                                \"beep_on_error\");\n}\n\noctave_value\nerror_system::backtrace_on_warning (const octave_value_list& args,\n                                    int nargout)\n{\n  return set_internal_variable (m_backtrace_on_warning, args, nargout,\n                                \"backtrace_on_warning\");\n}\n\noctave_value\nerror_system::verbose_warning (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_verbose_warning, args, nargout,\n                                \"verbose_warning\");\n}\n\noctave_value\nerror_system::quiet_warning (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_quiet_warning, args, nargout,\n                                \"quiet_warning\");\n}\n\noctave_value\nerror_system::last_error_message (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_last_error_message, args, nargout,\n                                \"last_error_message\");\n}\n\noctave_value\nerror_system::last_warning_message (const octave_value_list& args,\n                                    int nargout)\n{\n  return set_internal_variable (m_last_warning_message, args, nargout,\n                                \"last_warning_message\");\n}\n\noctave_value\nerror_system::last_warning_id (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_last_warning_id, args, nargout,\n                                \"last_warning_id\");\n}\n\noctave_value\nerror_system::last_error_id (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_last_error_id, args, nargout,\n                                \"last_error_id\");\n}\n\n// Use static fields for the best efficiency.\n// NOTE: C++0x will allow these two to be merged into one.\nstatic const char *bt_fieldnames[] =\n{ \"file\", \"name\", \"line\", \"column\", nullptr };\n\nstatic const octave_fields bt_fields (bt_fieldnames);\n\noctave_map\nerror_system::make_stack_map (const std::list<frame_info>& frames)\n{\n  std::size_t nframes = frames.size ();\n\n  octave_map retval (dim_vector (nframes, 1), bt_fields);\n\n  Cell& file = retval.contents (0);\n  Cell& name = retval.contents (1);\n  Cell& line = retval.contents (2);\n  Cell& column = retval.contents (3);\n\n  octave_idx_type k = 0;\n\n  for (const auto& frm : frames)\n    {\n      file(k) = frm.file_name ();\n      name(k) = frm.fcn_name ();\n      line(k) = frm.line ();\n      column(k) = frm.column ();\n\n      k++;\n    }\n\n  return retval;\n}\n\nstatic std::list<frame_info>\nmake_stack_frame_list_intern (const octave_map& stack)\n{\n  std::list<frame_info> frames;\n\n  Cell file = stack.contents (\"file\");\n  Cell name = stack.contents (\"name\");\n  Cell line = stack.contents (\"line\");\n  Cell column = stack.contents (\"column\");\n\n  octave_idx_type nel = name.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    frames.push_back (frame_info (file(i).string_value (),\n                                  name(i).string_value (),\n                                  line(i).int_value (),\n                                  column(i).int_value ()));\n\n  return frames;\n}\n\nstd::list<frame_info>\nerror_system::make_stack_frame_list (const octave_map& stack,\n                                     const std::string& who)\n{\n  if (! (stack.contains (\"file\") && stack.contains (\"name\")\n         && stack.contains (\"line\")))\n    error (\"%s: STACK struct must contain the fields 'file', 'name', and 'line'\",\n           who.c_str ());\n\n  if (! stack.contains (\"column\"))\n    {\n      octave_map stack1 (stack);  // copy before modification\n      stack1.setfield (\"column\", Cell (octave_value (-1)));\n      return make_stack_frame_list_intern (stack1);\n    }\n  else\n    return make_stack_frame_list_intern (stack);\n}\n\n// For given warning ID, return 0 if warnings are disabled, 1 if\n// enabled, and 2 if the given ID should be an error instead of a\n// warning.\n\nint\nerror_system::warning_enabled (const std::string& id)\n{\n  int retval = 0;\n\n  int all_state = -1;\n  int id_state = -1;\n\n  octave_map opts = warning_options ();\n\n  octave_idx_type nel = opts.numel ();\n\n  if (nel > 0)\n    {\n      Cell identifier = opts.contents (\"identifier\");\n      Cell state = opts.contents (\"state\");\n\n      bool all_found = false;\n      bool id_found = false;\n\n      for (octave_idx_type i = 0; i < nel; i++)\n        {\n          octave_value ov = identifier(i);\n          std::string ovs = ov.string_value ();\n\n          if (! all_found && ovs == \"all\")\n            {\n              all_state = check_state (state(i).string_value ());\n\n              if (all_state >= 0)\n                all_found = true;\n            }\n\n          if (! id_found && ovs == id)\n            {\n              id_state = check_state (state(i).string_value ());\n\n              if (id_state >= 0)\n                id_found = true;\n            }\n\n          if (all_found && id_found)\n            break;\n        }\n    }\n\n  // If \"all\" is not present, assume warnings are enabled.\n  if (all_state == -1)\n    all_state = 1;\n\n  if (all_state == 0)\n    {\n      if (id_state >= 0)\n        retval = id_state;\n    }\n  else if (all_state == 1)\n    {\n      if (id_state == 0 || id_state == 2)\n        retval = id_state;\n      else\n        retval = all_state;\n    }\n  else if (all_state == 2)\n    {\n      if (id_state == 0)\n        retval= id_state;\n      else\n        retval = all_state;\n    }\n\n  return retval;\n}\n\nvoid\nerror_system::vusage (const char *id, const char *fmt, va_list args)\n{\n  std::string str_id = id ? id : \"\";\n  std::string message = format_message (fmt, args);\n\n  throw_error (\"usage\", str_id, message);\n}\n\nvoid\nerror_system::vwarning (const char *name, const char *id,\n                        const char *fmt, va_list args)\n{\n  int warn_opt = warning_enabled (id);\n\n  if (warn_opt == 2)\n    {\n      // Handle this warning as an error.  ERROR_1 won't return.\n      error_1 (id, fmt, args);\n    }\n\n  std::string base_msg = format_message (fmt, args);\n  std::string msg_string;\n\n  if (name)\n    msg_string = std::string (name) + \": \";\n\n  msg_string += base_msg;\n\n  // Set LAST_WARNING_MESSAGE independent on whether the WARN_OPT is 0 unless\n  // warnings are quiet.  In that case, only set LAST_WARNING_MESSAGE if the\n  // warning is not disabled.  Quiet warnings are used, e.g., for the \"warning\"\n  // mode of the \"test\" function.\n  if (! quiet_warning () || warn_opt != 0)\n    {\n      last_warning_id (id);\n      last_warning_message (base_msg);\n    }\n\n  // If WARN_OPT is 0, then the warning is disabled.\n  if (discard_warning_messages () || warn_opt == 0)\n    return;\n\n  bool fmt_suppresses_backtrace = false;\n  std::size_t fmt_len = (fmt ? strlen (fmt) : 0);\n  fmt_suppresses_backtrace = (fmt_len > 0 && fmt[fmt_len-1] == '\\n');\n\n  if (! fmt_suppresses_backtrace)\n    msg_string += '\\n';\n\n  tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n  bool in_user_code = tw.in_user_code ();\n\n  flush_stdout ();\n\n  if (! quiet_warning ())\n    {\n      octave_diary << msg_string;\n      std::cerr << msg_string;\n\n      if (! fmt_suppresses_backtrace && in_user_code\n          && backtrace_on_warning ()\n          && ! discard_warning_messages ())\n        {\n          std::string bt_msg = tw.backtrace_message ();\n\n          if (! bt_msg.empty ())\n            bt_msg = \"warning: called from\\n\" + bt_msg;\n\n          octave_diary << bt_msg << std::endl;\n          std::cerr << bt_msg << std::endl;\n        }\n    }\n\n  bp_table& bptab = tw.get_bp_table ();\n\n  if ((m_interpreter.interactive ()\n       || application::forced_interactive ())\n      && debug_on_warning () && in_user_code && bptab.debug_on_warn (id))\n    {\n      unwind_protect_var<bool> restore_var (m_debug_on_warning, false);\n\n      tw.enter_debugger ();\n    }\n}\n\nvoid\nerror_system::error_1 (execution_exception& ee, const char *id,\n                       const char *fmt, va_list args)\n{\n  ee.set_identifier (id);\n  ee.set_message (format_message (fmt, args));\n\n  throw_error (ee);\n}\n\nvoid\nerror_system::error_1 (const char *id, const char *fmt,\n                       va_list args)\n{\n  std::string message = format_message (fmt, args);\n\n  std::list<frame_info> stack_info;\n\n  throw_error (\"error\", id, message);\n}\n\nvoid\nerror_system::vwarning (const char *id, const char *fmt, va_list args)\n{\n  // OK, this probably seems strange now, but there is a version of\n  // vwarning that takes the \"name\" of the warning as an argument,\n  // possibly because \"usage\" was previously handled as a warning?\n  // For consistent behavior, that function will deal with all the\n  // ON/OFF/ERROR warning state options.\n  vwarning (\"warning\", id, fmt, args);\n}\n\nvoid\nerror_system::rethrow_error (const std::string& id,\n                             const std::string& msg,\n                             const octave_map& stack)\n{\n  std::list<frame_info> stack_info;\n\n  execution_exception ee (\"error\", id, msg, stack_info);\n\n  if (! stack.isempty ())\n    ee.set_stack_info (make_stack_frame_list (stack, \"rethrow\"));\n\n  throw_error (ee);\n}\n\nvoid\nerror_system::vpanic (const char *fmt, va_list args)\n{\n  // Earlier versions of Octave printed a message directly to std::cerr\n  // and called abort.  That might be acceptable behavior for some\n  // programs but for an interactive application like Octave, aborting\n  // the entire program when an internal programming error has been\n  // detected seems unnecessary and certainly provides a much worse user\n  // experience than simply generating an ordinary error message and\n  // attempting to return to the command prompt.\n\n  ::verror (fmt, args);\n}\n\nvoid\nerror_system::panic (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  vpanic (fmt, args);\n  va_end (args);\n}\n\noctave_scalar_map\nerror_system::warning_query (const std::string& id_arg)\n{\n  octave_scalar_map retval;\n\n  std::string id = id_arg;\n\n  if (id == \"last\")\n    id = last_warning_id ();\n\n  octave_map opts = warning_options ();\n\n  Cell ident = opts.contents (\"identifier\");\n  Cell state = opts.contents (\"state\");\n\n  octave_idx_type nel = ident.numel ();\n\n  panic_if (nel == 0);\n\n  bool found = false;\n\n  std::string val;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      if (ident(i).string_value () == id)\n        {\n          val = state(i).string_value ();\n          found = true;\n          break;\n        }\n    }\n\n  if (! found)\n    {\n      for (octave_idx_type i = 0; i < nel; i++)\n        {\n          if (ident(i).string_value () == \"all\")\n            {\n              val = state(i).string_value ();\n              found = true;\n              break;\n            }\n        }\n    }\n\n  // The warning state \"all\" is always supposed to remain in the list,\n  // so we should always find a state, either explicitly or by using the\n  // state for \"all\".\n  panic_unless (found);\n\n  retval.assign (\"identifier\", id);\n  retval.assign (\"state\", val);\n\n  return retval;\n}\n\nstd::string\nerror_system::default_warning_state ()\n{\n  std::string retval = \"on\";\n\n  octave_map opts = warning_options ();\n\n  Cell ident = opts.contents (\"identifier\");\n  Cell state = opts.contents (\"state\");\n\n  octave_idx_type nel = ident.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      if (ident(i).string_value () == \"all\")\n        {\n          retval = state(i).string_value ();\n          break;\n        }\n    }\n\n  return retval;\n}\n\nvoid\nerror_system::display_warning_options (std::ostream& os)\n{\n  octave_map opts = warning_options ();\n\n  Cell ident = opts.contents (\"identifier\");\n  Cell state = opts.contents (\"state\");\n\n  octave_idx_type nel = ident.numel ();\n\n  std::string all_state = default_warning_state ();\n\n  if (all_state == \"on\")\n    os << \"By default, warnings are enabled.\";\n  else if (all_state == \"off\")\n    os << \"By default, warnings are disabled.\";\n  else if (all_state == \"error\")\n    os << \"By default, warnings are treated as errors.\";\n  else\n    error (\"unexpected default warning state '%s' - please report this bug\", all_state.c_str ());\n\n  if (nel > 1)\n    {\n      os << \"\\n\";\n      os << \"Non-default warning states are:\\n\\n\";\n      os << \"  State  Warning ID\\n\";\n    }\n\n  // The state for \"all\" is always supposed to be first in the list.\n\n  for (octave_idx_type i = 1; i < nel; i++)\n    {\n      std::string tid = ident(i).string_value ();\n      std::string tst = state(i).string_value ();\n\n      os << std::setw (7) << tst << \"  \" << tid << \"\\n\";\n    }\n\n  os << std::endl;\n}\n\nvoid\nerror_system::set_warning_option (const std::string& state,\n                                  const std::string& ident)\n{\n  std::string all_state = default_warning_state ();\n\n  if (state != \"on\" && state != \"off\" && state != \"error\")\n    error (\"invalid warning state: %s\", state.c_str ());\n\n  octave_map opts = warning_options ();\n\n  Cell tid = opts.contents (\"identifier\");\n  Cell tst = opts.contents (\"state\");\n\n  octave_idx_type nel = tid.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      if (tid(i).string_value () == ident)\n        {\n          // We found it in the current list of options.  If the state\n          // for \"all\" is same as arg1, we can simply remove the item\n          // from the list.\n\n          if (state == all_state && ident != \"all\")\n            {\n              for (i = i + 1; i < nel; i++)\n                {\n                  tid(i-1) = tid(i);\n                  tst(i-1) = tst(i);\n                }\n\n              tid.resize (dim_vector (1, nel-1));\n              tst.resize (dim_vector (1, nel-1));\n            }\n          else\n            tst(i) = state;\n\n          opts.clear ();\n\n          opts.assign (\"identifier\", tid);\n          opts.assign (\"state\", tst);\n\n          warning_options (opts);\n\n          return;\n        }\n    }\n\n  // The option wasn't already in the list.  Append it.\n\n  tid.resize (dim_vector (1, nel+1));\n  tst.resize (dim_vector (1, nel+1));\n\n  tid(nel) = ident;\n  tst(nel) = state;\n\n  opts.clear ();\n\n  opts.assign (\"identifier\", tid);\n  opts.assign (\"state\", tst);\n\n  warning_options (opts);\n}\n\nvoid\nerror_system::disable_warning (const std::string& id)\n{\n  set_warning_option (\"off\", id);\n}\n\nvoid\nerror_system::initialize_default_warning_state ()\n{\n  warning_options (init_warning_options (\"on\"));\n\n  // Most people will want to have the following disabled.\n\n  disable_warning (\"Octave:array-as-logical\");\n  disable_warning (\"Octave:array-to-scalar\");\n  disable_warning (\"Octave:array-to-vector\");\n  disable_warning (\"Octave:imag-to-real\");\n  disable_warning (\"Octave:language-extension\");\n  disable_warning (\"Octave:missing-semicolon\");\n  disable_warning (\"Octave:neg-dim-as-zero\");\n  disable_warning (\"Octave:separator-insert\");\n  disable_warning (\"Octave:single-quote-string\");\n  disable_warning (\"Octave:str-to-num\");\n  disable_warning (\"Octave:mixed-string-concat\");\n  disable_warning (\"Octave:variable-switch-label\");\n}\n\nvoid\nerror_system::interpreter_try (unwind_protect& frame)\n{\n  frame.protect_var (m_debug_on_error);\n  m_debug_on_error = false;\n\n  frame.protect_var (m_debug_on_warning);\n  m_debug_on_warning = false;\n\n  // Leave debug_on_caught as it was, so errors in try/catch are still\n  // caught.\n}\n\nvoid\nerror_system::throw_error (const std::string& err_type,\n                           const std::string& id,\n                           const std::string& message,\n                           const std::list<frame_info>& stack_info_arg)\n{\n  std::list<frame_info> stack_info = stack_info_arg;\n\n  if (stack_info.empty ())\n    {\n      tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n      stack_info = tw.backtrace_info ();\n\n      // Print the error message only if it is different from the\n      // previous one; makes the output more concise and readable.\n\n      stack_info.unique ();\n    }\n\n  execution_exception ex (err_type, id, message, stack_info);\n\n  throw_error (ex);\n}\n\nvoid\nerror_system::throw_error (execution_exception& ex)\n{\n  throw ex;\n}\n\nvoid\nerror_system::save_exception (const execution_exception& ee)\n{\n  last_error_id (ee.identifier ());\n  std::string message = ee.message ();\n  std::string xmsg\n    = (message.size () > 0 && message.back () == '\\n'\n       ? message.substr (0, message.size () - 1) : message);\n  last_error_message (xmsg);\n  last_error_stack (make_stack_map (ee.stack_info ()));\n}\n\nvoid\nerror_system::display_exception (const execution_exception& ee) const\n{\n  // FIXME: How should we handle beep_on_error?\n\n  ee.display (octave_diary);\n\n  // FIXME: Handle display using an event manager message so that the\n  // GUI or other client can receive error messages without needing to\n  // capture them from std::cerr or some other stream.\n\n  event_manager& evmgr = m_interpreter.get_event_manager ();\n\n  evmgr.display_exception (ee, m_beep_on_error);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\nvoid\nvmessage (const char *name, const char *fmt, va_list args)\n{\n  std::string message;\n\n  if (name)\n    message = std::string (name) + \": \";\n\n  message += format_message (fmt, args);\n\n  octave_diary << message << std::endl;\n  std::cerr << message << std::endl;\n}\n\nvoid\nmessage (const char *name, const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  vmessage (name, fmt, args);\n  va_end (args);\n}\n\nvoid\nvusage_with_id (const char *id, const char *fmt, va_list args)\n{\n  octave::error_system& es = octave::__get_error_system__ ();\n\n  es.vusage (id, fmt, args);\n}\n\nvoid\nusage_with_id (const char *id, const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  vusage_with_id (id, fmt, args);\n  va_end (args);\n}\n\nvoid\nverror (const char *fmt, va_list args)\n{\n  error_1 (\"\", fmt, args);\n}\n\nvoid\nerror (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  verror (fmt, args);\n  va_end (args);\n}\n\nvoid\nverror (octave::execution_exception& ee, const char *fmt, va_list args)\n{\n  error_1 (ee, \"\", fmt, args);\n}\n\nvoid\nerror (octave::execution_exception& ee, const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  verror (ee, fmt, args);\n  va_end (args);\n}\n\nvoid\nverror_with_cfn (const char *fmt, va_list args)\n{\n  error_1 (\"\", fmt, args);\n}\n\nvoid\nerror_with_cfn (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  verror_with_cfn (fmt, args);\n  va_end (args);\n}\n\nvoid\nverror_with_id (const char *id, const char *fmt, va_list args)\n{\n  error_1 (id, fmt, args);\n}\n\nvoid\nerror_with_id (const char *id, const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  verror_with_id (id, fmt, args);\n  va_end (args);\n}\n\nvoid\nverror_with_id_cfn (const char *id, const char *fmt, va_list args)\n{\n  error_1 (id, fmt, args);\n}\n\nvoid\nerror_with_id_cfn (const char *id, const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  verror_with_id_cfn (id, fmt, args);\n  va_end (args);\n}\n\nvoid\nvwarning (const char *fmt, va_list args)\n{\n  vwarning (\"\", fmt, args);\n}\n\nvoid\nwarning (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  vwarning (fmt, args);\n  va_end (args);\n}\n\nvoid\nvwarning_with_id (const char *id, const char *fmt, va_list args)\n{\n  vwarning (id, fmt, args);\n}\n\nvoid\nwarning_with_id (const char *id, const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  vwarning (id, fmt, args);\n  va_end (args);\n}\n\nvoid\nvparse_error (const char *fmt, va_list args)\n{\n  error_1 (\"\", fmt, args);\n}\n\nvoid\nparse_error (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  vparse_error (fmt, args);\n  va_end (args);\n}\n\nvoid\nvparse_error_with_id (const char *id, const char *fmt, va_list args)\n{\n  error_1 (id, fmt, args);\n}\n\nvoid\nparse_error_with_id (const char *id, const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  vparse_error_with_id (id, fmt, args);\n  va_end (args);\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\ndefun_usage_message (const std::string& msg)\n{\n  ::defun_usage_message (\"%s\", msg.c_str ());\n}\n\nDEFMETHOD (rethrow, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} rethrow (@var{err})\nReissue a previous error as defined by @var{err}.\n\n@var{err} is a structure that must contain at least the @qcode{\"message\"}\nand @qcode{\"identifier\"} fields.  @var{err} can also contain a field\n@qcode{\"stack\"} that gives information on the assumed location of the\nerror.  Typically @var{err} is returned from @code{lasterror}.\n@seealso{lasterror, lasterr, error}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  const octave_scalar_map err = args(0).scalar_map_value ();\n\n  if (! (err.contains (\"message\") && err.contains (\"identifier\")))\n    error (\"rethrow: ERR struct must contain the fields 'message' and 'identifier'\");\n\n  std::string msg = err.contents (\"message\").string_value ();\n  std::string id = err.contents (\"identifier\").string_value ();\n\n  octave_map err_stack = init_error_stack (interp);\n\n  if (err.contains (\"stack\"))\n    err_stack = err.contents (\"stack\").xmap_value (\"ERR.STACK must be a struct\");\n\n  error_system& es = interp.get_error_system ();\n\n  es.rethrow_error (id, msg, err_stack);\n\n  return ovl ();\n}\n\nDEFMETHOD (error, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} error (@var{msg})\n@deftypefnx {} {} error (@var{template}, @dots{})\n@deftypefnx {} {} error (@var{id}, @var{template}, @dots{})\n@deftypefnx {} {} error (@var{errstruct})\nDisplay an error message and stop m-file execution.\n\nThe input @var{msg} is a simple string to which the text @samp{error: } is\nprepended.  The resulting message is printed on the @code{stderr} stream.\nAlternatively, the first input may be a template string @var{template} which\nuses the same rules as the @code{printf} family of functions\n(@pxref{Formatted Output}).  Formatting is only done for single-quoted\ncharacter vectors if there are additional arguments following the template\nstring.  If there are no additional arguments, the template string is used\nliterally (i.e., without interpreting any escape sequences in single-quoted\ncharacter vectors).\n\nThe optional @var{id} argument allows programmers to tag an error\nwith a specific identifier so that users can later retrieve it (using\n@code{lasterr} or @code{lasterror}) and know the origin of the error.\nThe identifier must contain at least one colon character (@qcode{':'})\nand must not contain any whitespace characters.  It should be a string of\nthe form @qcode{\"NAMESPACE:ERROR-NAME\"}@.  Octave's own errors use the\n@qcode{\"Octave\"} namespace (@pxref{XREFerror_ids,,@code{error_ids}}).\nFor example:\n\n@example\n@group\nerror (\"MyNameSpace:wrong-type-argument\",\n       \"fcn_name: argument should be numeric\");\n@end group\n@end example\n\nCalling @code{error} also sets Octave's internal error state such that\ncontrol will return to the top level without evaluating any further\ncommands.  This is useful for aborting from functions or scripts.\n\nIf the error message does not end with a newline character, Octave will\nprint a traceback of all the function calls leading to the error.  For\nexample, given the following function definitions:\n\n@example\n@group\nfunction f () g (); end\nfunction g () h (); end\nfunction h () nargin == 1 || error (\"nargin != 1\"); end\n@end group\n@end example\n\n@noindent\ncalling the function @code{f} will result in a list of messages that\ncan help you to quickly find the exact location of the error:\n\n@example\n@group\nf ()\nerror: nargin != 1\nerror: called from:\nerror:   h at line 1, column 27\nerror:   g at line 1, column 15\nerror:   f at line 1, column 15\n@end group\n@end example\n\nIf the error message ends in a newline character, Octave will print the\nmessage but will not display any traceback messages as it returns\ncontrol to the top level.  For example, modifying the error message\nin the previous example to end in a newline causes Octave to only print\na single message:\n\n@example\n@group\nfunction h () nargin == 1 || error (\"nargin != 1\\n\"); end\nf ()\nerror: nargin != 1\n@end group\n@end example\n\nA null string (\"\") input to @code{error} will be ignored and the code\nwill continue running as if the statement were a NOP@.  This is for\ncompatibility with @sc{matlab}.  It also makes it possible to write code\nsuch as\n\n@example\n@group\nerr_msg = \"\";\nif (CONDITION 1)\n  err_msg = \"CONDITION 1 found\";\nelseif (CONDITION2)\n  err_msg = \"CONDITION 2 found\";\n@dots{}\nendif\nerror (err_msg);\n@end group\n@end example\n\n@noindent\nwhich will only stop execution if an error has been found.\n\nThe function may also be called with an error structure such as that returned\nfrom @code{lasterror}.  The @var{errstruct} argument must contain fields\n@code{message}, @code{identifier}, and @code{stack}.  The first two fields are\nstrings with the meanings discussed above.  The @code{stack} field must be a\nstructure or structure array with fields @code{file}, @code{name}, and\n@code{line}.\n\nImplementation Note: For compatibility with @sc{matlab}, escape\nsequences in @var{template} (e.g., @qcode{\"@backslashchar{}n\"} =>\nnewline) are processed regardless of whether @var{template} has been defined\nwith single quotes, as long as there are two or more input arguments.  To\ndisable escape sequence expansion use a second backslash before the sequence\n(e.g., @qcode{\"@backslashchar{}@backslashchar{}n\"}) or use the\n@code{regexptranslate} function.\n@seealso{warning, lasterror}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  octave_value retval;\n\n  std::string id;\n  std::string message;\n  std::list<frame_info> stack_info;\n\n  bool have_fmt = false;\n\n  if (nargin == 1 && args(0).isstruct ())\n    {\n      // empty struct is not an error.  return and resume calling function.\n      if (args(0).isempty ())\n        return retval;\n\n      octave_scalar_map m = args(0).xscalar_map_value (\"ERRSTRUCT must be a scalar structure with fields 'message' and 'identifier'\");\n\n      // empty struct is not an error.  return and resume calling function.\n      if (m.nfields () == 0)\n        return retval;\n\n      if (! m.contains (\"message\"))\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"error: ERRSTRUCT must have field 'message'\");\n      else\n        {\n          octave_value c = m.getfield (\"message\");\n\n          if (! c.isempty ())\n            message = c.xstring_value (\"error: MESSAGE must be a string\");\n        }\n\n      if (! m.contains (\"identifier\"))\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"error: ERRSTRUCT must have field 'identifier'\");\n      else\n        {\n          octave_value c = m.getfield (\"identifier\");\n\n          if (! c.isempty ())\n            id = c.xstring_value (\"error: IDENTIFIER must be a string\");\n        }\n\n      if (m.contains (\"stack\"))\n        {\n          octave_value c = m.getfield (\"stack\");\n\n          if (! c.isempty ())\n            {\n              octave_map stack = c.xmap_value (\"error: STACK must be a structure\");\n              stack_info = error_system::make_stack_frame_list (stack,\n                                                                \"error\");\n            }\n        }\n    }\n  else\n    {\n      octave_value_list nargs = args;\n\n      have_fmt = maybe_extract_message_id (\"error\", args, nargs, id);\n\n      if (nargs.length () == 0)\n        message = \"unspecified error\";\n      else\n        {\n          octave_value arg;\n\n          if (have_fmt)\n            {\n              octave_value_list tmp = Fsprintf (nargs, 1);\n              arg = tmp(0);\n            }\n          else\n            arg = nargs(0);\n\n          if (arg.is_defined ())\n            {\n              if (arg.isempty ())\n                message = \"\";\n              else if (arg.is_string ())\n                message = arg.string_value ();\n            }\n        }\n    }\n\n  if (message.empty ())\n    return retval;\n\n  error_system& es = interp.get_error_system ();\n\n  es.throw_error (\"error\", id, message, stack_info);\n\n  return retval;\n}\n\n/*\n%!error <error message 1>\n%! error ('error message 1');\n\n%!error <error message 2>\n%! error ('my:error_id_2', 'error message 2');\n\n%!error id=my:error_id_3\n%! error ('my:error_id_3', 'error message 3');\n\n%!error <error message 4>\n%! serr.message = 'error message 4';\n%! serr.identifier = 'my:error_id_4';\n%! error (serr);\n\n%!error id=my:error_id_5\n%! serr.message = 'error message 5';\n%! serr.identifier = 'my:error_id_5';\n%! error (serr);\n\n## bug #67143\n%!error <error message 6>\n%! serr.identifier = 'my:error_id_6';\n%! serr.message = 'error message 6';\n%! serr.stack = struct ('file', 'myfile', 'name', 'myfcn', 'line', 0);\n%! error (serr);\n\n%!error id=my:error_id_7\n%! serr.identifier = 'my:error_id_7';\n%! serr.message = 'error message 7';\n%! serr.stack = struct ('file', 'myfile', 'name', 'myfcn', 'line', 0, ...\n%!                      'column', 0);\n%! error (serr);\n\n## Test input validation\n############################################################\n%!error <Invalid call> error ()\n\n%!error <ERRSTRUCT must be a scalar structure>\n%! serr(1).message = 'msg1';\n%! serr(1).identifier = 'id1';\n%! serr(2).message = 'msg2';\n%! serr(2).identifier = 'id2';\n%! error (serr);\n\n%!error <ERRSTRUCT must have field 'message'>\n%! serr.identifier = 'id';\n%! error (serr);\n\n%!error <MESSAGE must be a string>\n%! serr.message = {1};\n%! error (serr);\n\n%!error <ERRSTRUCT must have field 'identifier'>\n%! serr.message = 'msg';\n%! error (serr);\n\n%!error <IDENTIFIER must be a string>\n%! serr.message = 'msg';\n%! serr.identifier = {1};\n%! error (serr);\n\n%!error <STACK must be a structure>\n%! serr.message = 'msg';\n%! serr.identifier = 'id';\n%! serr.stack = 5;\n%! error (serr);\n\n%!error <STACK struct must contain the fields 'file'>\n%! serr.message = 'msg';\n%! serr.identifier = 'id';\n%! serr.stack = struct ('name', 'myfcn', 'line', 0);\n%! error (serr);\n\n%!error <STACK struct must contain the fields .* 'name'>\n%! serr.message = 'msg';\n%! serr.identifier = 'id';\n%! serr.stack = struct ('file', 'myfile', 'line', 0);\n%! error (serr);\n\n%!error <STACK struct must contain the fields .* 'line'>\n%! serr.message = 'msg';\n%! serr.identifier = 'id';\n%! serr.stack = struct ('file', 'myfile', 'name', 'myfcn');\n%! error (serr);\n\n%!error <MESSAGE must be a string> error ({1});\n\n*/\n\nDEFMETHOD (warning, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} warning (@var{template}, @dots{})\n@deftypefnx {} {} warning (@var{id}, @var{template}, @dots{})\n@deftypefnx {} {} warning (\"on\", @var{id})\n@deftypefnx {} {} warning (\"off\", @var{id})\n@deftypefnx {} {} warning (\"error\", @var{id})\n@deftypefnx {} {} warning (\"query\", @var{id})\n@deftypefnx {} {} warning (@var{state}, @var{id}, \"local\")\n@deftypefnx {} {} warning (@var{warning_struct})\n@deftypefnx {} {@var{warning_struct} =} warning (@dots{})\n@deftypefnx {} {} warning (@var{state}, @var{mode})\n\nDisplay a warning message or control the behavior of Octave's warning system.\n\nThe first call form uses a template @var{template} and optional additional\narguments to display a message on the @code{stderr} stream.  The message is\nformatted using the same rules as the @code{printf} family of functions\n(@pxref{Formatted Output}) and prefixed by the character string\n@w{@samp{warning: }}.  You should use this function when you want to notify the\nuser of an unusual condition, but only when it makes sense for your program to\ngo on.  For example:\n\n@example\n@group\nwarning (\"foo: maybe something wrong here\");\n@end group\n@end example\n\nIf the warning message does not end with a newline character, Octave will\nprint a traceback of all the function calls leading to the warning.  If the\nwarning message does end in a newline character, Octave will suppress the\ntraceback messages as it returns control to the top level.  For more details\nand examples, @pxref{XREFerror,,@code{error}}.\n\nThe optional warning identifier @var{id} allows users to enable or disable\nwarnings tagged by this identifier.  A message identifier is a string of the\nform @qcode{\"NAMESPACE:WARNING-NAME\"}.  Octave's own warnings use the\n@qcode{\"Octave\"} namespace (@pxref{XREFwarning_ids,,@code{warning_ids}}).  For\nexample:\n\n@example\n@group\nwarning (\"MyNameSpace:check-something\",\n         \"foo: maybe something wrong here\");\n@end group\n@end example\n\nThe second call form is meant to change and/or query the state of warnings.\nThe first input argument must be a string @var{state} (@qcode{\"on\"},\n@qcode{\"off\"}, @qcode{\"error\"}, or @qcode{\"query\"}) followed by an optional\nwarning identifier @var{id} or @qcode{\"all\"} (default).\n\nThe optional output argument @var{warning_struct} is a structure or structure\narray with fields @qcode{\"state\"} and @qcode{\"identifier\"}.  The @var{state}\nargument may have the following values:\n\n@table @asis\n@item @qcode{\"on\"}|@qcode{\"off\"}:\nEnable or disable the display of warnings identified by @var{id} and optionally\nreturn their previous state @var{stout}.\n\n@item @qcode{\"error\"}:\nTurn warnings identified by @var{id} into errors and optionally return their\nprevious state @var{stout}.\n\n@item @qcode{\"query\"}:\nReturn the current state of warnings identified by @var{id}.\n@end table\n\nA structure or structure array @var{warning_struct}, with fields\n@qcode{\"state\"} and @qcode{\"identifier\"}, may be given as an input to achieve\nequivalent results.  The following example shows how to temporarily disable a\nwarning and then restore its original state:\n\n@example\n@group\nloglog (-1:10);\n## Disable the previous warning and save its original state\n[~, id] = lastwarn ();\nwarnstate = warning (\"off\", id);\nloglog (-1:10);\n## Restore its original state\nwarning (warnstate);\n@end group\n@end example\n\nIf a final argument @qcode{\"local\"} is provided then the warning state will be\nset temporarily until the end of the current function.  Changes to warning\nstates that are set locally affect the current function and all functions\ncalled from the current scope.  The previous warning state is restored on\nreturn from the current function.  The @qcode{\"local\"} option is ignored if\nused in the top-level workspace.\n\nWith no input argument @code{warning ()} is equivalent to\n@code{warning (\"query\", \"all\")} except that in the absence of an output\nargument, the state of warnings is displayed on @code{stderr}.\n\nThe level of verbosity of the warning system may also be controlled by two\nmodes @var{mode}:\n\n@table @asis\n@item @qcode{\"backtrace\"}:\nenable/disable the display of the stack trace after the warning message\n\n@item @qcode{\"verbose\"}:\nenable/disable the display of additional information after the warning message\n@end table\n\nIn this case the @var{state} argument may only be @qcode{\"on\"} or\n@qcode{\"off\"}.\n\nImplementation Note: For compatibility with @sc{matlab}, escape sequences in\n@var{template} (e.g., @qcode{\"@backslashchar{}n\"} => newline) are processed\nregardless of whether @var{template} has been defined with single quotes, as\nlong as there are two or more input arguments.  To disable escape sequence\nexpansion use a second backslash before the sequence (e.g.,\n@qcode{\"@backslashchar{}@backslashchar{}n\"}) or use the\n@code{regexptranslate} function.\n@seealso{warning_ids, lastwarn, error}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n  bool done = false;\n\n  error_system& es = interp.get_error_system ();\n\n  if (nargin > 0 && args.all_strings_p ())\n    {\n      string_vector argv = args.make_argv (\"warning\");\n\n      std::string arg1 = argv[1];\n      std::transform (arg1.begin (), arg1.end (), arg1.begin (), tolower);\n      std::string arg2 = \"all\";\n      std::string arg2_lc = \"all\";\n\n      if (nargin >= 2)\n        {\n          arg2 = argv[2];\n          arg2_lc = arg2;\n          std::transform (arg2_lc.begin (), arg2_lc.end (), arg2_lc.begin (),\n                          tolower);\n        }\n\n      if (arg1 == \"on\" || arg1 == \"off\" || arg1 == \"error\")\n        {\n          // Prepare output structure\n          octave_map old_warning_options;\n          if (arg2_lc == \"all\")\n            old_warning_options = es.warning_options ();\n          else\n            old_warning_options = octave_map (es.warning_query (arg2));\n\n          if (nargin == 3)\n            {\n              std::string arg3_lc = argv[3];\n              std::transform (arg3_lc.begin (), arg3_lc.end (),\n                              arg3_lc.begin (), tolower);\n              if (arg3_lc == \"local\" && ! interp.at_top_level ())\n                {\n                  octave_scalar_map val = es.warning_query (arg2);\n\n                  octave_value curr_state = val.contents (\"state\");\n\n                  // FIXME: this might be better with a dictionary object.\n                  tree_evaluator& tw = interp.get_evaluator ();\n\n                  octave_value curr_warning_states\n                    = tw.get_auto_fcn_var (stack_frame::SAVED_WARNING_STATES);\n\n                  octave_map m;\n\n                  if (curr_warning_states.is_defined ())\n                    m = curr_warning_states.map_value ();\n                  else\n                    {\n                      string_vector fields (2);\n\n                      fields(0) = \"identifier\";\n                      fields(1) = \"state\";\n\n                      m = octave_map (dim_vector (0, 1), fields);\n                    }\n\n                  Cell ids = m.contents (\"identifier\");\n                  Cell states = m.contents (\"state\");\n\n                  octave_idx_type nel = states.numel ();\n                  bool found = false;\n                  octave_idx_type i;\n                  for (i = 0; i < nel; i++)\n                    {\n                      std::string id = ids(i).string_value ();\n\n                      if (id == arg2)\n                        {\n                          states(i) = curr_state;\n                          found = true;\n                          break;\n                        }\n                    }\n\n                  if (! found)\n                    {\n                      m.resize (dim_vector (nel+1, 1));\n\n                      ids.resize (dim_vector (nel+1, 1));\n                      states.resize (dim_vector (nel+1, 1));\n\n                      ids(nel) = arg2;\n                      states(nel) = curr_state;\n                    }\n\n                  m.contents (\"identifier\") = ids;\n                  m.contents (\"state\") = states;\n\n                  tw.set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, m);\n\n                  // Now ignore the \"local\" argument,\n                  // and continue to handle the current setting.\n                  nargin--;\n                }\n            }\n\n          if ((nargin == 1\n               && (arg1 == \"on\" || arg1 == \"off\" || arg1 == \"error\"))\n              || (nargin >= 2 && arg2_lc == \"all\"))\n            {\n              // If \"all\" is given implicitly or explicitly as ID.\n              if (arg1 == \"error\")\n                error (R\"(warning: cannot specify \"all\" warning ID with state \"error\")\");\n\n              octave_map tmp;\n\n              Cell id (1, 1);\n              Cell st (1, 1);\n\n              id(0) = \"all\";\n              st(0) = arg1;\n\n              tmp.assign (\"identifier\", id);\n              tmp.assign (\"state\", st);\n\n              es.warning_options (tmp);\n\n              done = true;\n            }\n          else if (arg2_lc == \"backtrace\")\n            {\n              if (arg1 != \"error\")\n                {\n                  es.backtrace_on_warning (arg1 == \"on\");\n                  done = true;\n                }\n            }\n          else if (arg2_lc == \"debug\")\n            {\n              if (arg1 != \"error\")\n                {\n                  es.debug_on_warning (arg1 == \"on\");\n                  done = true;\n                }\n            }\n          else if (arg2_lc == \"verbose\")\n            {\n              if (arg1 != \"error\")\n                {\n                  es.verbose_warning (arg1 == \"on\");\n                  done = true;\n                }\n            }\n          else if (arg2_lc == \"quiet\")\n            {\n              if (arg1 != \"error\")\n                {\n                  es.quiet_warning (arg1 == \"on\");\n                  done = true;\n                }\n            }\n          else\n            {\n              if (arg2_lc == \"last\")\n                arg2 = es.last_warning_id ();\n\n              es.set_warning_option (arg1, arg2);\n\n              done = true;\n            }\n\n          if (done && nargout > 0)\n            retval = old_warning_options;\n        }\n      else if (arg1 == \"query\")\n        {\n          if (arg2_lc == \"all\")\n            {\n              if (nargout > 0)\n                retval = es.warning_options ();\n              else\n                es.display_warning_options (octave_stdout);\n            }\n          else if (arg2_lc == \"backtrace\" || arg2_lc == \"debug\"\n                   || arg2_lc == \"verbose\" || arg2_lc == \"quiet\")\n            {\n              if (nargout > 0)\n                {\n                  octave_scalar_map tmp;\n                  tmp.assign (\"identifier\", arg2_lc);\n                  if (arg2_lc == \"backtrace\")\n                    tmp.assign (\"state\", es.backtrace_on_warning () ? \"on\" : \"off\");\n                  else if (arg2_lc == \"debug\")\n                    tmp.assign (\"state\", es.debug_on_warning () ? \"on\" : \"off\");\n                  else if (arg2_lc == \"verbose\")\n                    tmp.assign (\"state\", es.verbose_warning () ? \"on\" : \"off\");\n                  else\n                    tmp.assign (\"state\", es.quiet_warning () ? \"on\" : \"off\");\n\n                  retval = tmp;\n                }\n              else\n                {\n                  if (arg2_lc == \"backtrace\")\n                    octave_stdout << R\"(\"backtrace\" warning state is \")\" <<\n                                  (es.backtrace_on_warning () ? \"on\" : \"off\") <<\n                                  \"\\\"\\n\";\n                  else if (arg2_lc == \"debug\")\n                    octave_stdout << R\"(\"debug\" warning state is \")\" <<\n                                  (es.debug_on_warning () ? \"on\" : \"off\") <<\n                                  \"\\\"\\n\";\n                  else if (arg2_lc == \"verbose\")\n                    octave_stdout << R\"(\"verbose\" warning state is \")\" <<\n                                  (es.verbose_warning () ? \"on\" : \"off\") <<\n                                  \"\\\"\\n\";\n                  else\n                    octave_stdout << R\"(\"quiet\" warning state is \")\" <<\n                                  (es.quiet_warning () ? \"on\" : \"off\") <<\n                                  \"\\\"\\n\";\n                }\n            }\n          else\n            {\n              if (nargout > 0)\n                retval = es.warning_query (arg2);\n              else\n                {\n                  octave_scalar_map tmp = es.warning_query (arg2);\n\n                  octave_stdout << '\"' << arg2 << R\"(\" warning state is \")\" <<\n                                tmp.getfield (\"state\").string_value () <<\n                                \"\\\"\\n\";\n                }\n            }\n\n          done = true;\n        }\n    }\n  else if (nargin == 0)\n    {\n      if (nargout > 0)\n        retval = es.warning_options ();\n      else\n        es.display_warning_options (octave_stdout);\n\n      done = true;\n    }\n  else if (nargin == 1)\n    {\n      octave_value arg = args(0);\n\n      octave_map old_warning_options;\n\n      if (arg.isstruct ())\n        {\n          octave_map m = arg.map_value ();\n\n          if (! m.contains (\"identifier\") || ! m.contains (\"state\"))\n            error (\"warning: STATE structure must have fields 'identifier' and 'state'\");\n\n          // Simply step through the struct elements one at a time.\n\n          Cell ident = m.contents (\"identifier\");\n          Cell state = m.contents (\"state\");\n\n          octave_idx_type nel = ident.numel ();\n\n          // Prepare output structure\n          old_warning_options = octave_map (m);\n          Cell oldstate (state);\n\n          for (octave_idx_type i = 0; i < nel; i++)\n            {\n              std::string tid = ident(i).string_value ();\n              oldstate(i) = es.warning_query (tid).getfield (\"state\");\n            }\n          old_warning_options.setfield (\"state\", oldstate);\n\n          // Set new values\n          for (octave_idx_type i = 0; i < nel; i++)\n            {\n              std::string tst = state(i).string_value ();\n              std::string tid = ident(i).string_value ();\n\n              es.set_warning_option (tst, tid);\n            }\n\n          done = true;\n\n          if (nargout > 0)\n            retval = old_warning_options;\n        }\n    }\n\n  if (! done)\n    {\n      octave_value_list nargs = args;\n\n      std::string id;\n\n      bool have_fmt = maybe_extract_message_id (\"warning\", args, nargs, id);\n\n      std::string prev_msg = es.last_warning_message ();\n\n      std::string curr_msg = handle_message (warning_with_id, id.c_str (),\n                                             \"unspecified warning\", nargs,\n                                             have_fmt);\n\n      if (nargout > 0)\n        retval = prev_msg;\n    }\n\n  return retval;\n}\n\n/*\n\n%!test <*51997>\n%! id = \"Octave:logical-conversion\";\n%! current = warning (\"query\", id);\n%! current_all = warning ();\n%! previous = warning (current_all);\n%! assert (previous, current_all);\n%! previous = warning (current);\n%! assert (previous, current);\n%! previous = warning (current.state, id);\n%! assert (previous, current);\n\n%!test <*57290>\n%! warning (\"oN\", \"Octave:test-57290-ID\");\n%! warnst = warning (\"QUery\", \"Octave:test-57290-ID\");\n%! assert (warnst.state, \"on\");\n%! assert (warnst.identifier, \"Octave:test-57290-ID\");\n%! warning (\"OFF\", \"Octave:test-57290-ID\");\n%! warnst = warning (\"QUery\", \"ALL\");\n%! idx = strcmp ({warnst.identifier}, \"Octave:test-57290-ID\");\n%! assert (warnst(idx).state, \"off\");\n\n%!error <cannot specify \"all\" warning ID> warning (\"error\")\n\n*/\n\noctave_value_list\nset_warning_state (const std::string& id, const std::string& state)\n{\n  octave_value_list args (2);\n\n  args(0) = state;\n  args(1) = id;\n\n  interpreter& interp = __get_interpreter__ ();\n\n  return Fwarning (interp, args, 1);\n}\n\noctave_value_list\nset_warning_state (const octave_value_list& args)\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return Fwarning (interp, args, 1);\n}\n\nint\nwarning_enabled (const std::string& id)\n{\n  error_system& es = __get_error_system__ ();\n\n  return es.warning_enabled (id);\n}\n\nvoid\ndisable_warning (const std::string& id)\n{\n  error_system& es = __get_error_system__ ();\n\n  es.disable_warning (id);\n}\n\nDEFMETHOD (lasterror, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{lasterr} =} lasterror ()\n@deftypefnx {} {} lasterror (@var{err})\n@deftypefnx {} {} lasterror (\"reset\")\nQuery or set the last error message structure.\n\nWhen called without arguments, return a structure containing the last error\nmessage and other information related to this error.  The elements of the\nstructure are:\n\n@table @code\n@item message\nThe text of the last error message\n\n@item identifier\nThe message identifier of this error message\n\n@item stack\nA structure containing information on where the message occurred.  This may\nbe an empty structure if the information cannot be obtained.  The fields of\nthe structure are:\n\n@table @code\n@item file\nThe name of the file where the error occurred\n\n@item name\nThe name of function in which the error occurred\n\n@item line\nThe line number at which the error occurred\n\n@item column\nAn optional field with the column number at which the error occurred\n@end table\n@end table\n\nThe last error structure may be set by passing a scalar structure,\n@var{err}, as input.  Any fields of @var{err} that match those above are\nset while any unspecified fields are initialized with default values.\n\nIf @code{lasterror} is called with the argument @qcode{\"reset\"}, all\nfields are set to their default values.\n@seealso{lasterr, error, lastwarn}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  error_system& es = interp.get_error_system ();\n\n  octave_scalar_map err;\n\n  err.assign (\"message\", es.last_error_message ());\n  err.assign (\"identifier\", es.last_error_id ());\n\n  err.assign (\"stack\", octave_value (es.last_error_stack ()));\n\n  if (nargin == 1)\n    {\n      tree_evaluator& tw = interp.get_evaluator ();\n\n      if (args(0).is_string ())\n        {\n          if (args(0).string_value () != \"reset\")\n            error (\"lasterror: unrecognized string argument\");\n\n          es.last_error_message (\"\");\n          es.last_error_id (\"\");\n\n          es.last_error_stack (tw.empty_backtrace ());\n        }\n      else if (args(0).isstruct ())\n        {\n          octave_scalar_map new_err = args(0).scalar_map_value ();\n          octave_scalar_map new_err_stack;\n          std::string new_error_message;\n          std::string new_error_id;\n          std::string new_error_file;\n          std::string new_error_name;\n          int new_error_line = -1;\n          int new_error_column = -1;\n          bool initialize_stack = false;\n\n          if (new_err.contains (\"message\"))\n            {\n              const std::string tmp\n                = new_err.getfield (\"message\").string_value ();\n              new_error_message = tmp;\n            }\n\n          if (new_err.contains (\"identifier\"))\n            {\n              const std::string tmp\n                = new_err.getfield (\"identifier\").string_value ();\n              new_error_id = tmp;\n            }\n\n          if (new_err.contains (\"stack\"))\n            {\n              if (new_err.getfield (\"stack\").isempty ())\n                initialize_stack = true;\n              else\n                {\n                  new_err_stack\n                    = new_err.getfield (\"stack\").scalar_map_value ();\n\n                  if (new_err_stack.contains (\"file\"))\n                    {\n                      const std::string tmp\n                        = new_err_stack.getfield (\"file\").string_value ();\n                      new_error_file = tmp;\n                    }\n\n                  if (new_err_stack.contains (\"name\"))\n                    {\n                      const std::string tmp\n                        = new_err_stack.getfield (\"name\").string_value ();\n                      new_error_name = tmp;\n                    }\n\n                  if (new_err_stack.contains (\"line\"))\n                    {\n                      const int tmp\n                        = new_err_stack.getfield (\"line\").nint_value ();\n                      new_error_line = tmp;\n                    }\n\n                  if (new_err_stack.contains (\"column\"))\n                    {\n                      const int tmp\n                        = new_err_stack.getfield (\"column\").nint_value ();\n                      new_error_column = tmp;\n                    }\n                }\n            }\n\n          es.last_error_message (new_error_message);\n          es.last_error_id (new_error_id);\n\n          if (initialize_stack)\n            es.last_error_stack (tw.empty_backtrace ());\n          else if (new_err.contains (\"stack\"))\n            {\n              new_err_stack.setfield (\"file\", new_error_file);\n              new_err_stack.setfield (\"name\", new_error_name);\n              new_err_stack.setfield (\"line\", new_error_line);\n              new_err_stack.setfield (\"column\", new_error_column);\n\n              es.last_error_stack (new_err_stack);\n            }\n          else\n            es.last_error_stack (tw.backtrace ());\n        }\n      else\n        error (\"lasterror: argument must be a structure or a string\");\n    }\n\n  return ovl (err);\n}\n\n/*\n## Test lasterror with empty error state\n%!test\n%! lasterror (\"reset\");\n%! x = lasterror ();\n%! assert (x.identifier, \"\");\n%! assert (x.message, \"\");\n%! assert (isempty (x.stack));\n%! lasterror (x);\n%! y = lasterror ();\n%! assert (y, x);\n*/\n\nDEFMETHOD (lasterr, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{msg}, @var{msgid}] =} lasterr ()\n@deftypefnx {} {} lasterr (@var{msg})\n@deftypefnx {} {} lasterr (@var{msg}, @var{msgid})\nQuery or set the last error message.\n\nWhen called without input arguments, return the last error message and\nmessage identifier.\n\nWith one argument, set the last error message to @var{msg}.\n\nWith two arguments, also set the last message identifier.\n@seealso{lasterror, error, lastwarn}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 2)\n    print_usage ();\n\n  error_system& es = interp.get_error_system ();\n\n  string_vector argv = args.make_argv (\"lasterr\");\n\n  std::string prev_error_id = es.last_error_id ();\n  std::string prev_error_message = es.last_error_message ();\n\n  if (nargin == 2)\n    {\n      es.last_error_id (argv[2]);\n      es.last_error_message (argv[1]);\n    }\n  else if (nargin == 1)\n    {\n      es.last_error_id (\"\");\n      es.last_error_message (argv[1]);\n    }\n\n  if (nargin == 0 || nargout > 0)\n    return ovl (prev_error_message, prev_error_id);\n  else\n    return ovl ();\n}\n\nDEFMETHOD (lastwarn, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{msg}, @var{msgid}] =} lastwarn ()\n@deftypefnx {} {} lastwarn (@var{msg})\n@deftypefnx {} {} lastwarn (@var{msg}, @var{msgid})\nQuery or set the last warning message.\n\nWhen called without input arguments, return the last warning message and\nmessage identifier.\n\nWith one argument, set the last warning message to @var{msg}.\n\nWith two arguments, also set the last message identifier to @var{msgid}.\n@seealso{warning, lasterror, lasterr}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 2)\n    print_usage ();\n\n  error_system& es = interp.get_error_system ();\n\n  string_vector argv = args.make_argv (\"lastwarn\");\n\n  std::string prev_warning_id = es.last_warning_id ();\n  std::string prev_warning_message = es.last_warning_message ();\n\n  if (nargin == 2)\n    {\n      es.last_warning_id (argv[2]);\n      es.last_warning_message (argv[1]);\n    }\n  else if (nargin == 1)\n    {\n      es.last_warning_id (\"\");\n      es.last_warning_message (argv[1]);\n    }\n\n  if (nargin == 0 || nargout > 0)\n    return ovl (prev_warning_message, prev_warning_id);\n  else\n    return ovl ();\n}\n\nDEFMETHOD (beep_on_error, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} beep_on_error ()\n@deftypefnx {} {@var{old_val} =} beep_on_error (@var{new_val})\n@deftypefnx {} {@var{old_val} =} beep_on_error (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave will try\nto ring the terminal bell before printing an error message.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  error_system& es = interp.get_error_system ();\n\n  return es.beep_on_error (args, nargout);\n}\n\nDEFMETHOD (debug_on_error, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} debug_on_error ()\n@deftypefnx {} {@var{old_val} =} debug_on_error (@var{new_val})\n@deftypefnx {} {@var{old_val} =} debug_on_error (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave will try\nto enter the debugger when an error is encountered.\n\nThis will also inhibit printing of the normal traceback message (you will\nonly see the top-level error message).\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{debug_on_warning, debug_on_interrupt}\n@end deftypefn */)\n{\n  error_system& es = interp.get_error_system ();\n\n  return es.debug_on_error (args, nargout);\n}\n\nDEFMETHOD (debug_on_warning, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} debug_on_warning ()\n@deftypefnx {} {@var{old_val} =} debug_on_warning (@var{new_val})\n@deftypefnx {} {@var{old_val} =} debug_on_warning (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave will try\nto enter the debugger when a warning is encountered.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{debug_on_error, debug_on_interrupt}\n@end deftypefn */)\n{\n  error_system& es = interp.get_error_system ();\n\n  return es.debug_on_warning (args, nargout);\n}\n\nvoid\ninterpreter_try (unwind_protect& frame)\n{\n  error_system& es = __get_error_system__ ();\n\n  es.interpreter_try (frame);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/error.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_error_h)\n#define octave_error_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdarg>\n#include <cinttypes>\n#include <string>\n\n#include \"unwind-prot.h\"\n\n#include \"oct-map.h\"\n// Include panic.h here for backward compatibility with previous\n// versions of Octave that declared the global panic functions and\n// macros here.\n#include \"panic.h\"\n\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass execution_exception;\n\nclass error_system\n{\npublic:\n\n  OCTINTERP_API error_system (interpreter& interp);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (error_system)\n\n  ~error_system () = default;\n\n  OCTINTERP_API octave_value\n  debug_on_error (const octave_value_list& args, int nargout);\n\n  void set_debug_on_error (bool flag) { m_debug_on_error = flag; }\n\n  bool debug_on_error () const { return m_debug_on_error; }\n\n  bool debug_on_error (bool flag)\n  {\n    bool val = m_debug_on_error;\n    m_debug_on_error = flag;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  debug_on_caught (const octave_value_list& args, int nargout);\n\n  void set_debug_on_caught (bool flag) { m_debug_on_caught = flag; }\n\n  bool debug_on_caught () const { return m_debug_on_caught; }\n\n  bool debug_on_caught (bool flag)\n  {\n    bool val = m_debug_on_caught;\n    m_debug_on_caught = flag;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  debug_on_warning (const octave_value_list& args, int nargout);\n\n  void set_debug_on_warning (bool flag) { m_debug_on_warning = flag; }\n\n  bool debug_on_warning () const { return m_debug_on_warning; }\n\n  bool debug_on_warning (bool flag)\n  {\n    bool val = m_debug_on_warning;\n    m_debug_on_warning = flag;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  discard_warning_messages (const octave_value_list& args, int nargout);\n\n  void set_discard_warning_messages (bool flag)\n  {\n    m_discard_warning_messages = flag;\n  }\n\n  bool discard_warning_messages () const\n  {\n    return m_discard_warning_messages;\n  }\n\n  bool discard_warning_messages (bool flag)\n  {\n    bool val = m_discard_warning_messages;\n    m_discard_warning_messages = flag;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  beep_on_error (const octave_value_list& args, int nargout);\n\n  void set_beep_on_error (bool flag) { m_beep_on_error = flag; }\n\n  bool beep_on_error () const { return m_beep_on_error; }\n\n  bool beep_on_error (bool flag)\n  {\n    bool val = m_beep_on_error;\n    m_beep_on_error = flag;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  backtrace_on_warning (const octave_value_list& args, int nargout);\n\n  void set_backtrace_on_warning (bool flag) { m_backtrace_on_warning = flag; }\n\n  bool backtrace_on_warning () const { return m_backtrace_on_warning; }\n\n  bool backtrace_on_warning (bool flag)\n  {\n    bool val = m_backtrace_on_warning;\n    m_backtrace_on_warning = flag;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  verbose_warning (const octave_value_list& args, int nargout);\n\n  void set_verbose_warning (bool flag) { m_verbose_warning = flag; }\n\n  bool verbose_warning () const { return m_verbose_warning; }\n\n  bool verbose_warning (bool flag)\n  {\n    bool val = m_verbose_warning;\n    m_verbose_warning = flag;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  quiet_warning (const octave_value_list& args, int nargout);\n\n  void set_quiet_warning (bool flag) { m_quiet_warning = flag; }\n\n  bool quiet_warning () const { return m_quiet_warning; }\n\n  bool quiet_warning (bool flag)\n  {\n    bool val = m_quiet_warning;\n    m_quiet_warning = flag;\n    return val;\n  }\n\n  octave_map warning_options () const { return m_warning_options; }\n\n  void set_warning_options (const octave_map& val)\n  { m_warning_options = val; }\n\n  octave_map warning_options (const octave_map& new_val)\n  {\n    octave_map val = m_warning_options;\n    m_warning_options = new_val;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  last_error_message (const octave_value_list& args, int nargout);\n\n  void set_last_error_message (const std::string& val)\n  { m_last_error_message = val; }\n\n  std::string last_error_message () const { return m_last_error_message; }\n\n  std::string last_error_message (const std::string& s)\n  {\n    std::string val = m_last_error_message;\n    m_last_error_message = s;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  last_warning_message (const octave_value_list& args, int nargout);\n\n  void set_last_warning_message (const std::string& val)\n  { m_last_warning_message = val; }\n\n  std::string last_warning_message () const\n  { return m_last_warning_message; }\n\n  std::string last_warning_message (const std::string& s)\n  {\n    std::string val = m_last_warning_message;\n    m_last_warning_message = s;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  last_warning_id (const octave_value_list& args, int nargout);\n\n  void set_last_warning_id (const std::string& val)\n  { m_last_warning_id = val; }\n\n  std::string last_warning_id () const { return m_last_warning_id; }\n\n  std::string last_warning_id (const std::string& s)\n  {\n    std::string val = m_last_warning_id;\n    m_last_warning_id = s;\n    return val;\n  }\n\n  OCTINTERP_API octave_value\n  last_error_id (const octave_value_list& args, int nargout);\n\n  void set_last_error_id (const std::string& val) { m_last_error_id = val; }\n\n  std::string last_error_id () const { return m_last_error_id; }\n\n  std::string last_error_id (const std::string& s)\n  {\n    std::string val = m_last_error_id;\n    m_last_error_id = s;\n    return val;\n  }\n\n  void set_last_error_stack (const octave_map& val)\n  {\n    m_last_error_stack = val;\n  }\n\n  octave_map last_error_stack () const { return m_last_error_stack; }\n\n  octave_map last_error_stack (const octave_map& new_val)\n  {\n    octave_map val = m_last_error_stack;\n    m_last_error_stack = new_val;\n    return val;\n  }\n\n  static OCTINTERP_API octave_map\n  make_stack_map (const std::list<frame_info>& frames);\n\n  static OCTINTERP_API std::list<frame_info>\n  make_stack_frame_list (const octave_map& stack,\n                         const std::string& who = \"error\");\n\n  //! For given warning ID, return 0 if warnings are disabled, 1 if\n  //! enabled, and 2 if the given ID should be an error instead of a\n  //! warning.\n\n  OCTINTERP_API int warning_enabled (const std::string& id);\n\n  OCTINTERP_API void\n  verror (bool save_last_error, std::ostream& os, const char *name,\n          const char *id, const char *fmt, va_list args,\n          bool with_cfn = false);\n\n  OCTINTERP_API void\n  vwarning (const char *name, const char *id, const char *fmt,\n            va_list args);\n\n  OCTAVE_NORETURN\n  OCTINTERP_API void\n  error_1 (execution_exception& ee, const char *id, const char *fmt,\n           va_list args);\n\n  OCTAVE_NORETURN\n  OCTINTERP_API void error_1 (const char *id, const char *fmt, va_list args);\n\n  OCTAVE_NORETURN\n  OCTINTERP_API void vusage (const char *id, const char *fmt, va_list args);\n\n  OCTINTERP_API void vwarning (const char *id, const char *fmt, va_list args);\n\n  OCTAVE_NORETURN\n  OCTINTERP_API void\n  rethrow_error (const std::string& id, const std::string& msg,\n                 const octave_map& stack);\n\n  OCTAVE_NORETURN\n  OCTINTERP_API void vpanic (const char *fmt, va_list args);\n\n  OCTAVE_NORETURN\n  OCTINTERP_API void panic (const char *fmt, ...);\n\n  OCTINTERP_API octave_scalar_map warning_query (const std::string& id_arg);\n\n  OCTINTERP_API std::string default_warning_state ();\n\n  OCTINTERP_API void display_warning_options (std::ostream& os);\n\n  OCTINTERP_API void\n  set_warning_option (const std::string& state, const std::string& id);\n\n  OCTINTERP_API void disable_warning (const std::string& id);\n\n  OCTINTERP_API void initialize_default_warning_state ();\n\n  OCTINTERP_API void interpreter_try (unwind_protect& frame);\n\n  // Throw execution_exception or, if debug_on_error is TRUE, enter\n  // debugger.  If stack_info is empty, use current call stack.\n\n  OCTAVE_NORETURN\n  OCTINTERP_API void\n  throw_error (const std::string& err_type,\n               const std::string& id,\n               const std::string& message,\n               const std::list<frame_info>& stack_info\n               = std::list<frame_info> ());\n\n  OCTAVE_NORETURN\n  OCTINTERP_API void throw_error (execution_exception& ee);\n\n  OCTINTERP_API void save_exception (const execution_exception& ee);\n\n  OCTINTERP_API void display_exception (const execution_exception& ee) const;\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  //! TRUE means that Octave will try to enter the debugger when an error\n  //! is encountered.  This will also inhibit printing of the normal\n  //! traceback message (you will only see the top-level error message).\n\n  bool m_debug_on_error;\n\n  //! TRUE means that Octave will try to enter the debugger when an error\n  //! is encountered within the 'try' section of a 'try' / 'catch' block.\n\n  bool m_debug_on_caught;\n\n  //! TRUE means that Octave will try to enter the debugger when a warning\n  //! is encountered.\n\n  bool m_debug_on_warning;\n\n  //! TRUE means warning messages are turned off.\n\n  bool m_discard_warning_messages;\n\n  //! TRUE means that Octave will try to beep obnoxiously before\n  //! printing error messages.\n  bool m_beep_on_error;\n\n  //! TRUE means that Octave will try to display a stack trace when a\n  //! warning is encountered.\n  bool m_backtrace_on_warning;\n\n  //! TRUE means that Octave will print a verbose warning.  Currently\n  //! unused.\n  bool m_verbose_warning;\n\n  //! TRUE means that Octave will print no warnings, but lastwarn will\n  //! be updated\n  bool m_quiet_warning;\n\n  //! A structure containing (most of) the current state of warnings.\n  octave_map m_warning_options;\n\n  //! The text of the last error message.\n  std::string m_last_error_message;\n\n  //! The text of the last warning message.\n  std::string m_last_warning_message;\n\n  //! The last warning message id.\n  std::string m_last_warning_id;\n\n  //! The last error message id.\n  std::string m_last_error_id;\n\n  //! The last file in which an error occurred.\n  octave_map m_last_error_stack;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n// FIXME: should we move the following functions inside the octave\n// namespace?  If so, should the functions outside of the namespace be\n// deprecated?  Doing that might cause a lot of trouble...  If they are\n// not deprecated and eventually removed, does it make sense to also\n// define them inside the octave namespace?\n\nextern OCTINTERP_API void\nvmessage (const char *name, const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (2, 3)\nextern OCTINTERP_API void message (const char *name, const char *fmt, ...);\n\nextern OCTINTERP_API void vwarning (const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (1, 2)\nextern OCTINTERP_API void warning (const char *fmt, ...);\n\nOCTAVE_NORETURN\nextern OCTINTERP_API void verror (const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (1, 2)\nOCTAVE_NORETURN\nextern OCTINTERP_API void error (const char *fmt, ...);\n\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nverror (octave::execution_exception&, const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (2, 3)\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nerror (octave::execution_exception&, const char *fmt, ...);\n\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nverror_with_cfn (const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (1, 2)\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nerror_with_cfn (const char *fmt, ...);\n\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nvparse_error (const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (1, 2)\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nparse_error (const char *fmt, ...);\n\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nvusage_with_id (const char *id, const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (2, 3)\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nusage_with_id (const char *id, const char *fmt, ...);\n\nextern OCTINTERP_API void\nvwarning_with_id (const char *id, const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (2, 3)\nextern OCTINTERP_API void\nwarning_with_id (const char *id, const char *fmt, ...);\n\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nverror_with_id (const char *id, const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (2, 3)\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nerror_with_id (const char *id, const char *fmt, ...);\n\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nverror_with_id_cfn (const char *id, const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (2, 3)\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nerror_with_id_cfn (const char *id, const char *fmt, ...);\n\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nvparse_error_with_id (const char *id, const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (2, 3)\nOCTAVE_NORETURN\nextern OCTINTERP_API void\nparse_error_with_id (const char *id, const char *fmt, ...);\n\n// Use of the following macros (error_impossible, error_if, and\n// error_unless) is discouraged.  All of these will only display a\n// generic error of the form\n//\n//   impossible state reached in file 'FILE' at line 'N'\n//\n// If the state really is \"impossible\" to reach, then it is better to\n// use one of the corresponding panic* functions instead (see panic.h).\n//\n// See also the discussion here: https://octave.discourse.group/t/assert-panic-error-and-ndebug/5409\n\n#define error_impossible()                                              \\\n  ::error (\"impossible state reached in file '%s' at line %d\", __FILE__, __LINE__)\n\n#define error_if(cond) do { if (cond) error_impossible (); } while (0)\n\n#define error_unless(cond) error_if (! (cond))\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n//! Helper function for print_usage defined in defun.cc.\n\nextern OCTINTERP_API void defun_usage_message (const std::string& msg);\n\n// Convenience functions.\n\nextern OCTINTERP_API octave_value_list\nset_warning_state (const std::string& id, const std::string& state);\n\nextern OCTINTERP_API octave_value_list\nset_warning_state (const octave_value_list& args);\n\nextern OCTINTERP_API int warning_enabled (const std::string& id);\n\nextern OCTINTERP_API void disable_warning (const std::string& id);\n\nextern OCTINTERP_API void interpreter_try (octave::unwind_protect&);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/errwarn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\n////////////////////////////////////////////////////////////////////////////////\n// Alphabetized list of common errors and warnings.\n////////////////////////////////////////////////////////////////////////////////\n\nvoid\nerr_2_or_3_dim_plot ()\n{\n  error (\"plot: can only plot in 2 or 3 dimensions\");\n}\n\nvoid\nerr_data_conversion (const char *from, const char *to)\n{\n  error (\"unable to convert from %s to %s format\", from, to);\n}\n\nvoid\nerr_disabled_feature (const std::string& fcn, const std::string& feature,\n                      const std::string& pkg /* =\"Octave\" */)\n{\n  if (! fcn.empty ())\n    error (\"%s: support for %s was unavailable or disabled when %s was built\",\n           fcn.c_str (), feature.c_str (), pkg.c_str ());\n  else\n    error (\"support for %s was unavailable or disabled when %s was built\",\n           feature.c_str (), pkg.c_str ());\n}\n\nvoid\nerr_indexed_cs_list ()\n{\n  error (\"a cs-list cannot be further indexed\");\n}\n\nvoid\nerr_invalid_conversion (const std::string& from, const std::string& to)\n{\n  error (\"invalid conversion from %s to %s\", from.c_str (), to.c_str ());\n}\n\nvoid\nerr_invalid_inquiry_subscript ()\n{\n  error (\"invalid dimension inquiry of a non-existent value\");\n}\n\nvoid\nerr_invalid_structure_assignment ()\n{\n  error (\"invalid dot name structure assignment because the structure array is empty.  Specify a subscript on the structure array to resolve.\");\n}\n\nvoid\nerr_nonbraced_cs_list_assignment ()\n{\n  error (\"invalid assignment to cs-list outside multiple assignment\");\n}\n\nvoid\nerr_nonconformant ()\n{\n  error (\"nonconformant matrices\");\n}\n\nvoid\nerr_nonconformant (octave_idx_type r1, octave_idx_type c1,\n                   octave_idx_type r2, octave_idx_type c2)\n{\n  error (\"nonconformant matrices (op1 is %\" OCTAVE_IDX_TYPE_FORMAT\n         \"x%\" OCTAVE_IDX_TYPE_FORMAT \", op2 is %\" OCTAVE_IDX_TYPE_FORMAT\n         \"x%\" OCTAVE_IDX_TYPE_FORMAT \")\", r1, c1, r2, c2);\n}\n\nvoid\nerr_not_implemented (const char *fcn)\n{\n  error (\"%s: not implemented\", fcn);\n}\n\nvoid\nerr_range_invalid ()\n{\n  error (\"range constant used in invalid context\");\n}\n\nvoid\nerr_square_matrix_required (const char *fcn, const char *name)\n{\n  error (\"%s: %s must be a square matrix\", fcn, name);\n}\n\nvoid\nerr_string_invalid ()\n{\n  error (\"std::string constant used in invalid context\");\n}\n\nvoid\nerr_unrecognized_data_fmt (const char *name)\n{\n  error (\"%s: unrecognized data format requested\", name);\n}\n\nvoid\nerr_unrecognized_float_fmt ()\n{\n  error (\"unrecognized floating point format requested\");\n}\n\nvoid\nerr_user_returned_invalid (const char *name)\n{\n  error (\"%s: user-supplied function returned invalid value\", name);\n}\n\nvoid\nerr_user_supplied_eval (const char *name)\n{\n  octave::execution_exception ee;\n\n  err_user_supplied_eval (ee, name);\n}\n\nvoid\nerr_user_supplied_eval (octave::execution_exception& ee, const char *name)\n{\n  error (ee, \"%s: evaluation of user-supplied function failed\", name);\n}\n\nvoid\nerr_wrong_type_arg (const char *name, const char *s)\n{\n  octave::execution_exception ee;\n\n  err_wrong_type_arg (ee, name, s);\n}\n\nvoid\nerr_wrong_type_arg (octave::execution_exception& ee,\n                    const char *name, const char *s)\n{\n  error (ee, \"%s: wrong type argument '%s'\", name, s);\n}\n\nvoid\nerr_wrong_type_arg (const char *name, const std::string& s)\n{\n  octave::execution_exception ee;\n\n  err_wrong_type_arg (ee, name, s.c_str ());\n}\n\nvoid\nerr_wrong_type_arg (octave::execution_exception& ee,\n                    const char *name, const std::string& s)\n{\n  err_wrong_type_arg (ee, name, s.c_str ());\n}\n\nvoid\nerr_wrong_type_arg (const char *name, const octave_value& tc)\n{\n  octave::execution_exception ee;\n\n  err_wrong_type_arg (ee, name, tc);\n}\n\nvoid\nerr_wrong_type_arg (octave::execution_exception& ee,\n                    const char *name, const octave_value& tc)\n{\n  std::string type = tc.type_name ();\n\n  err_wrong_type_arg (ee, name, type);\n}\n\nvoid\nerr_wrong_type_arg (const std::string& name, const octave_value& tc)\n{\n  octave::execution_exception ee;\n\n  err_wrong_type_arg (ee, name, tc);\n}\n\nvoid\nerr_wrong_type_arg (octave::execution_exception& ee,\n                    const std::string& name, const octave_value& tc)\n{\n  err_wrong_type_arg (ee, name.c_str (), tc);\n}\n\nvoid\nerr_wrong_type_arg (const char *s)\n{\n  octave::execution_exception ee;\n\n  err_wrong_type_arg (ee, s);\n}\n\nvoid\nerr_wrong_type_arg (octave::execution_exception& ee, const char *s)\n{\n  error (ee, \"wrong type argument '%s'\", s);\n}\n\nvoid\nerr_wrong_type_arg (const std::string& s)\n{\n  octave::execution_exception ee;\n\n  err_wrong_type_arg (ee, s);\n}\n\nvoid\nerr_wrong_type_arg (octave::execution_exception& ee, const std::string& s)\n{\n  err_wrong_type_arg (ee, s.c_str ());\n}\n\nvoid\nerr_wrong_type_arg (const octave_value& tc)\n{\n  octave::execution_exception ee;\n\n  err_wrong_type_arg (ee, tc);\n}\n\nvoid\nerr_wrong_type_arg (octave::execution_exception& ee, const octave_value& tc)\n{\n  std::string type = tc.type_name ();\n\n  err_wrong_type_arg (ee, type);\n}\n\nvoid\nerr_wrong_type_arg_for_binary_op (const octave_value& op)\n{\n  std::string type = op.type_name ();\n  error (\"invalid operand '%s' for binary operator\", type.c_str ());\n}\n\nvoid\nerr_wrong_type_arg_for_unary_op (const octave_value& op)\n{\n  std::string type = op.type_name ();\n  error (\"invalid operand '%s' for unary operator\", type.c_str ());\n}\n\nvoid\nwarn_array_as_logical (const dim_vector& dv)\n{\n  warning_with_id (\"Octave:array-as-logical\",\n                   \"Using an object of size %s as \"\n                   \"a boolean value implies all().\",\n                   dv.str ().c_str ());\n}\n\n/*\n%!warning <boolean value implies all>\n%! warning (\"on\", \"Octave:array-as-logical\");\n%! if ([1 1 0])\n%!   assert (false);\n%! endif\n*/\n\nvoid\nwarn_complex_cmp ()\n{\n  warning_with_id (\"Octave:language-extension\",\n                   \"comparing the complex part of complex numbers is not\"\n                   \" supported in Matlab\");\n}\n\nvoid\nwarn_data_file_in_path (const std::string& fcn, const std::string& file)\n{\n  warning_with_id (\"Octave:data-file-in-path\",\n                   \"%s: '%s' found by searching load path\",\n                   fcn.c_str (), file.c_str ());\n}\n\nvoid\nwarn_disabled_feature (const std::string& fcn, const std::string& feature,\n                       const std::string& pkg /*=\"Octave\"*/)\n{\n  if (! fcn.empty ())\n    warning (\"%s: support for %s was unavailable or disabled when %s was built\",\n             fcn.c_str (), feature.c_str (), pkg.c_str ());\n  else\n    warning (\"support for %s was unavailable or disabled when %s was built\",\n             feature.c_str (), pkg.c_str ());\n}\n\nvoid\nwarn_empty_arg (const char *name)\n{\n  warning (\"%s: argument is empty matrix\", name);\n}\n\nvoid\nwarn_empty_index (const std::string& type_name)\n{\n  warning_with_id (\"Octave:empty-index\",\n                   \"'%s' object indexed with empty index list\",\n                   type_name.c_str ());\n}\n\nvoid\nwarn_implicit_conversion (const char *id, const char *from, const char *to)\n{\n  warning_with_id (id, \"implicit conversion from %s to %s\", from, to);\n}\n\nvoid\nwarn_implicit_conversion (const std::string& id,\n                          const std::string& from, const std::string& to)\n{\n  warning_with_id (id.c_str (),\n                   \"implicit conversion from %s to %s\",\n                   from.c_str (), to.c_str ());\n}\n\nvoid\nwarn_invalid_value_specified (const char *name)\n{\n  warning (\"invalid value specified for '%s'\", name);\n}\n\nvoid\nwarn_logical_conversion ()\n{\n  warning_with_id (\"Octave:logical-conversion\",\n                   \"value not equal to 1 or 0 converted to logical 1\");\n}\n\nvoid\nwarn_wrong_type_arg (const char *name, const octave_value& tc)\n{\n  std::string type = tc.type_name ();\n\n  warning (\"%s: wrong type argument '%s'\", name, type.c_str ());\n}\n"
  },
  {
    "path": "libinterp/corefcn/errwarn.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_errwarn_h)\n#define octave_errwarn_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"lo-array-errwarn.h\"\n\nclass octave_value;\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass execution_exception;\n\nOCTAVE_END_NAMESPACE(octave)\n\n////////////////////////////////////////////////////////////////////////////////\n// Alphabetized list of common errors and warnings.\n////////////////////////////////////////////////////////////////////////////////\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_2_or_3_dim_plot ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_data_conversion (const char *from, const char *to);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_disabled_feature (const std::string& fcn, const std::string& feature,\n                      const std::string& pkg = \"Octave\");\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_indexed_cs_list ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_invalid_conversion (const std::string& from, const std::string& to);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_invalid_inquiry_subscript ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_invalid_structure_assignment ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_nonbraced_cs_list_assignment ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_nonconformant ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_nonconformant (octave_idx_type r1, octave_idx_type c1,\n                   octave_idx_type r2, octave_idx_type c2);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_not_implemented (const char *);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_range_invalid ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_square_matrix_required (const char *fcn, const char *name);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_string_invalid ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_unrecognized_data_fmt (const char *name);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_unrecognized_float_fmt ();\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_user_returned_invalid (const char *name);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_user_supplied_eval (const char *name);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_user_supplied_eval (octave::execution_exception& ee, const char *name);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (const char *name, const char *s);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (octave::execution_exception& ee, const char *name,\n                    const char *s);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (const char *name, const std::string& s);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (octave::execution_exception& ee, const char *name,\n                    const std::string& s);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (const char *name, const octave_value& tc);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (octave::execution_exception& ee, const char *name,\n                    const octave_value& tc);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (const std::string& name, const octave_value& tc);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (octave::execution_exception& ee, const std::string& name,\n                    const octave_value& tc);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (const char *s);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (octave::execution_exception& ee, const char *s);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (const std::string& s);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (octave::execution_exception& ee, const std::string& s);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (const octave_value& tc);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg (octave::execution_exception& ee, const octave_value& tc);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg_for_binary_op (const octave_value& op);\n\nOCTAVE_NORETURN extern OCTINTERP_API void\nerr_wrong_type_arg_for_unary_op (const octave_value& op);\n\nextern OCTINTERP_API void\nwarn_array_as_logical (const dim_vector& dv);\n\nextern OCTINTERP_API void\nwarn_complex_cmp ();\n\nextern OCTINTERP_API void\nwarn_data_file_in_path (const std::string& fcn, const std::string& file);\n\nextern OCTINTERP_API void\nwarn_disabled_feature (const std::string& fcn, const std::string& feature,\n                       const std::string& pkg = \"Octave\");\n\nextern OCTINTERP_API void\nwarn_empty_arg (const char *name);\n\nextern OCTINTERP_API void\nwarn_empty_index (const std::string& type_name);\n\nextern OCTINTERP_API void\nwarn_implicit_conversion (const char *id, const char *from, const char *to);\n\nextern OCTINTERP_API void\nwarn_implicit_conversion (const std::string& id, const std::string& from,\n                          const std::string& to);\n\nextern OCTINTERP_API void\nwarn_invalid_value_specified (const char *name);\n\nextern OCTINTERP_API void\nwarn_logical_conversion ();\n\nextern OCTINTERP_API void\nwarn_wrong_type_arg (const char *name, const octave_value& tc);\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/event-manager.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n\n#include \"builtin-defun-decls.h\"\n#include \"cmd-edit.h\"\n#include \"cmd-hist.h\"\n#include \"defun.h\"\n#include \"event-manager.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"oct-env.h\"\n#include \"oct-mutex.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"syminfo.h\"\n\n#include \"quit.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic int readline_event_hook ()\n{\n  event_manager& evmgr = __get_event_manager__ ();\n\n  evmgr.process_events ();\n\n  return 0;\n}\n\nvoid\ninterpreter_events::display_exception (const execution_exception& ee,\n                                       bool beep)\n{\n  if (beep)\n    std::cerr << \"\\a\";\n\n  ee.display (std::cerr);\n}\n\nevent_manager::event_manager (interpreter& interp)\n  : m_event_queue_mutex (new mutex ()), m_gui_event_queue (),\n    m_debugging (false), m_link_enabled (true),\n    m_interpreter (interp), m_instance (new interpreter_events ()),\n    m_qt_event_handlers ()\n{\n  push_event_queue ();\n  command_editor::add_event_hook (readline_event_hook);\n}\n\nevent_manager::~event_manager ()\n{\n  delete m_event_queue_mutex;\n}\n\n// Programming Note: It is possible to disable the link without deleting\n// the connection.  This allows it to be temporarily disabled.  But if\n// the link is removed, we also set the link_enabled flag to false\n// because if there is no link, it can't be enabled.  Also, access to\n// instance is only protected by a check on the link_enabled flag.\n\nvoid\nevent_manager::connect_link (const std::shared_ptr<interpreter_events>& obj)\n{\n  if (! obj)\n    disable ();\n\n  m_instance = obj;\n}\n\nbool\nevent_manager::enable ()\n{\n  bool retval = m_link_enabled;\n\n  if (m_instance)\n    m_link_enabled = true;\n  else\n    warning (\"event_manager: must have connected link to enable\");\n\n  return retval;\n}\n\nvoid\nevent_manager::process_events (bool disable_flag)\n{\n  if (enabled ())\n    {\n      if (disable_flag)\n        disable ();\n\n      m_event_queue_mutex->lock ();\n      std::shared_ptr<event_queue> evq = m_gui_event_queue.top ();\n      m_event_queue_mutex->unlock ();\n\n      evq->run ();\n    }\n}\n\nvoid\nevent_manager::discard_events ()\n{\n  if (enabled ())\n    {\n      m_event_queue_mutex->lock ();\n      std::shared_ptr<event_queue> evq = m_gui_event_queue.top ();\n      m_event_queue_mutex->unlock ();\n\n      evq->discard ();\n    }\n}\n\nvoid\nevent_manager::push_event_queue ()\n{\n  std::shared_ptr<event_queue> evq (new event_queue ());\n  m_gui_event_queue.push (evq);\n}\n\nvoid\nevent_manager::pop_event_queue ()\n{\n  // FIXME: Should we worry about the possibility of events remaining\n  // in the queue when we pop back to the previous queue?  If so, then\n  // we will probably want to push them on to the front of the\n  // previous queue so they will be executed before any other events\n  // that were in the previous queue.  This case could happen if\n  // graphics callback functions were added to the event queue during a\n  // debug session just after a dbcont command was added but before it\n  // executed and brought us here, for example.\n\n  std::shared_ptr<event_queue> evq = m_gui_event_queue.top ();\n  m_gui_event_queue.pop ();\n}\n\nvoid\nevent_manager::post_event (const fcn_callback& fcn)\n{\n  if (enabled ())\n    {\n      std::shared_ptr<event_queue> evq = m_gui_event_queue.top ();\n      evq->add (fcn);\n    }\n}\n\nvoid\nevent_manager::post_event (const meth_callback& meth)\n{\n  if (enabled ())\n    {\n      std::shared_ptr<event_queue> evq = m_gui_event_queue.top ();\n      evq->add (std::bind (meth, std::ref (m_interpreter)));\n    }\n}\n\nvoid\nevent_manager::set_workspace ()\n{\n  if (enabled ())\n    {\n      tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n      m_instance->set_workspace (tw.at_top_level (), m_debugging,\n                                 tw.get_symbol_info (), true);\n    }\n}\n\nvoid\nevent_manager::set_history ()\n{\n  if (enabled ())\n    m_instance->set_history (command_history::list ());\n}\n\n// FIXME: Should the following function be __event_manager_desktop__\n// with the desktop function implemented in a .m file, similar to the\n// way the UI* functions work?\n\nDEFMETHOD (desktop, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} desktop ()\nIf running in command-line mode, start the GUI desktop.\n@end deftypefn */)\n{\n  if (interp.experimental_terminal_widget ())\n    {\n      if (! application::is_gui_running ())\n        {\n          // FIXME: Currently, the following action is queued and\n          // executed in a Qt event loop and we return immediately to\n          // the command prompt where additional commands may be\n          // executed.  Is that what should happen?  Or should we be\n          // waiting until the GUI exits to return to the command\n          // prompt, similar to the way the UI* functions work?\n\n          event_manager& evmgr = interp.get_event_manager ();\n\n          evmgr.start_gui ();\n        }\n      else\n        warning (\"GUI desktop is already running\");\n    }\n  else\n    error (\"desktop function requires new experimental terminal widget\");\n\n  return ovl ();\n}\n\nDEFMETHOD (__event_manager_enabled__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} __event_manager_enabled__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  return ovl (evmgr.enabled ());\n}\n\nDEFMETHOD (__event_manager_have_dialogs__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} __event_manager_have_dialogs__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  return ovl (evmgr.have_dialogs ());\n}\n\nDEFMETHOD (__event_manager_edit_file__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __event_manager_edit_file__ (@var{file})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  if (args.length () == 1)\n    {\n      std::string file\n        = args(0).xstring_value (\"first argument must be filename\");\n\n      flush_stdout ();\n\n      retval = evmgr.edit_file (file);\n    }\n  else if (args.length () == 2)\n    {\n      std::string file\n        = args(0).xstring_value (\"first argument must be filename\");\n\n      flush_stdout ();\n\n      retval = evmgr.prompt_new_edit_file (file);\n    }\n\n  return retval;\n}\n\nDEFMETHOD (__event_manager_question_dialog__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{btn_val} =} __event_manager_question_dialog__ (@var{msg}, @var{title}, @var{btn1}, @var{btn2}, @var{btn3}, @var{default})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n  if (args.length () == 6)\n    {\n      std::string msg = args(0).xstring_value (\"invalid arguments\");\n      std::string title = args(1).xstring_value (\"invalid arguments\");\n      std::string btn1 = args(2).xstring_value (\"invalid arguments\");\n      std::string btn2 = args(3).xstring_value (\"invalid arguments\");\n      std::string btn3 = args(4).xstring_value (\"invalid arguments\");\n      std::string btndef = args(5).xstring_value (\"invalid arguments\");\n\n      flush_stdout ();\n\n      event_manager& evmgr = interp.get_event_manager ();\n\n      retval = evmgr.question_dialog (msg, title, btn1, btn2, btn3, btndef);\n    }\n\n  return retval;\n}\n\nDEFMETHOD (__event_manager_file_dialog__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} __event_manager_file_dialog__ (@var{filterlist}, @var{title}, @var{filename}, @var{multiselect}, @var{pathname})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 5)\n    return ovl ();\n\n  octave_value_list retval (3);\n\n  const Array<std::string> flist = args(0).cellstr_value ();\n  std::string title = args(1).string_value ();\n  std::string filename = args(2).string_value ();\n  std::string multi_on = args(3).string_value (); // on, off, create\n  std::string pathname = args(4).string_value ();\n\n  octave_idx_type nel;\n\n  event_manager::filter_list filter_lst;\n\n  for (octave_idx_type i = 0; i < flist.rows (); i++)\n    filter_lst.push_back (std::make_pair (flist(i, 0),\n                                          (flist.columns () > 1\n                                           ? flist(i, 1) : \"\")));\n\n  flush_stdout ();\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  std::list<std::string> items_lst\n    = evmgr.file_dialog (filter_lst, title, filename, pathname, multi_on);\n\n  nel = items_lst.size ();\n\n  // If 3, then retval is filename, directory, and selected index.\n  if (nel <= 3)\n    {\n      if (items_lst.front ().empty ())\n        retval = ovl (octave_value (0.), octave_value (0.), octave_value (0.));\n      else\n        {\n          int idx = 0;\n          for (auto& str : items_lst)\n            {\n              if (idx != 2)\n                retval(idx++) = str;\n              else\n                {\n                  // FIXME: Should we warn or error on invalid or out of\n                  // range values in STR?  When atoi was used for\n                  // conversion instead of std::stoi we did not.  Was\n                  // that intentional?\n\n                  try\n                    {\n                      retval(idx++) = std::stoi (str);\n                    }\n                  catch (const std::invalid_argument&) { }\n                  catch (const std::out_of_range&) { }\n                }\n            }\n        }\n    }\n  else\n    {\n      // Multiple files.\n      nel -= 2;\n      Cell items (dim_vector (1, nel));\n\n      auto it = items_lst.begin ();\n\n      for (int idx = 0; idx < nel; idx++, it++)\n        items.xelem (idx) = *it;\n\n      auto fpath = *it++;\n\n      int idx = 0;\n\n      // FIXME: Should we warn or error on invalid or out of range\n      // values in *IT?  When atoi was used for conversion instead of\n      // std::stoi we did not.  Was that intentional?\n\n      try\n        {\n          idx = std::stoi (*it);\n        }\n      catch (const std::invalid_argument&) { }\n      catch (const std::out_of_range&) { }\n\n      retval = ovl (items, fpath, idx);\n    }\n\n  return retval;\n}\n\nDEFMETHOD (__event_manager_list_dialog__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{sel}, @var{ok}] =} __event_manager_list_dialog__ (@var{list}, @var{mode}, @var{size}, @var{initial}, @var{name}, @var{prompt}, @var{ok_string}, @var{cancel_string})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 8)\n    return ovl ();\n\n  Cell list = args(0).cell_value ();\n  const Array<std::string> tlist = list.cellstr_value ();\n  octave_idx_type nel = tlist.numel ();\n  std::list<std::string> list_lst;\n  for (octave_idx_type i = 0; i < nel; i++)\n    list_lst.push_back (tlist(i));\n\n  std::string mode = args(1).string_value ();\n\n  Matrix size_matrix = args(2).matrix_value ();\n  int width = size_matrix(0);\n  int height = size_matrix(1);\n\n  Matrix initial_matrix = args(3).matrix_value ();\n  nel = initial_matrix.numel ();\n  std::list<int> initial_lst;\n  for (octave_idx_type i = 0; i < nel; i++)\n    initial_lst.push_back (initial_matrix(i));\n\n  std::string name = args(4).string_value ();\n  list = args(5).cell_value ();\n  const Array<std::string> plist = list.cellstr_value ();\n  nel = plist.numel ();\n  std::list<std::string> prompt_lst;\n  for (octave_idx_type i = 0; i < nel; i++)\n    prompt_lst.push_back (plist(i));\n  std::string ok_string = args(6).string_value ();\n  std::string cancel_string = args(7).string_value ();\n\n  flush_stdout ();\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  std::pair<std::list<int>, int> result\n    = evmgr.list_dialog (list_lst, mode, width, height, initial_lst,\n                         name, prompt_lst, ok_string, cancel_string);\n\n  std::list<int> items_lst = result.first;\n  nel = items_lst.size ();\n  Matrix items (dim_vector (1, nel));\n  octave_idx_type i = 0;\n  for (const auto& int_el : items_lst)\n    items.xelem(i++) = int_el;\n\n  return ovl (items, result.second);\n}\n\nDEFMETHOD (__event_manager_input_dialog__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{cstr} =} __event_manager_input_dialog__ (@var{prompt}, @var{title}, @var{rowscols}, @var{defaults})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 4)\n    return ovl ();\n\n  Cell prompt = args(0).cell_value ();\n  Array<std::string> tmp = prompt.cellstr_value ();\n  octave_idx_type nel = tmp.numel ();\n  std::list<std::string> prompt_lst;\n  for (octave_idx_type i = 0; i < nel; i++)\n    prompt_lst.push_back (tmp(i));\n\n  std::string title = args(1).string_value ();\n\n  Matrix rc = args(2).matrix_value ();\n  nel = rc.rows ();\n  std::list<float> nr;\n  std::list<float> nc;\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      nr.push_back (rc(i, 0));\n      nc.push_back (rc(i, 1));\n    }\n\n  Cell defaults = args(3).cell_value ();\n  tmp = defaults.cellstr_value ();\n  nel = tmp.numel ();\n  std::list<std::string> defaults_lst;\n  for (octave_idx_type i = 0; i < nel; i++)\n    defaults_lst.push_back (tmp(i));\n\n  flush_stdout ();\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  std::list<std::string> items_lst\n    = evmgr.input_dialog (prompt_lst, title, nr, nc, defaults_lst);\n\n  nel = items_lst.size ();\n  Cell items (dim_vector (nel, 1));\n  octave_idx_type i = 0;\n  for (const auto& str_el : items_lst)\n    items.xelem(i++) = str_el;\n\n  return ovl (items);\n}\n\n\nDEFMETHOD (__event_manager_named_icon__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{icon} =} __event_manager_dialog_icons__ (@var{icon_name})\nUndocumented internal function.\n@end deftypefn */)\n{\n  uint8NDArray retval;\n\n  if (args.length () > 0)\n    {\n      std::string icon_name = args(0).xstring_value (\"invalid arguments\");\n\n      event_manager& evmgr = interp.get_event_manager ();\n\n      retval = evmgr.get_named_icon (icon_name);\n    }\n\n  return ovl (retval);\n}\n\n// FIXME: Why does this function return any value at all?\nDEFMETHOD (__event_manager_show_preferences__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __event_manager_show_preferences__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  return ovl (evmgr.show_preferences ());\n}\n\nDEFMETHOD (__event_manager_apply_preferences__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __event_manager_apply_preferences__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  return ovl (evmgr.apply_preferences ());\n}\n\nDEFMETHOD (__event_manager_gui_preference__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{prefval} =} __event_manager_gui_preference__ (@var{key})\n@deftypefnx {} {@var{prefval} =} __event_manager_gui_preference__ (@var{key}, @var{value})\nUndocumented internal function.\n@end deftypefn */)\n{\n  std::string key;\n  std::string value = \"\";\n\n  if (args.length () >= 1)\n    key = args(0).string_value();\n  else\n    error (\"__event_manager_gui_preference__: \"\n           \"first argument must be the preference key\");\n\n  if (args.length () >= 2)\n    value = args(1).string_value();\n\n  if (application::is_gui_running ())\n    {\n      event_manager& evmgr = interp.get_event_manager ();\n\n      return ovl (evmgr.gui_preference (key, value));\n    }\n  else\n    return ovl (value);\n}\n\nDEFMETHOD (__event_manager_file_remove__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __event_manager_file_remove__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  std::string old_name, new_name;\n\n  if (args.length () == 2)\n    {\n      old_name = args(0).string_value();\n      new_name = args(1).string_value();\n    }\n  else\n    error (\"__event_manager_file_remove__: \"\n           \"old and new name expected as arguments\");\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.file_remove (old_name, new_name);\n\n  return ovl ();\n}\n\nDEFMETHOD (__event_manager_file_renamed__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __event_manager_file_renamed__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  bool load_new;\n\n  if (args.length () == 1)\n    load_new = args(0).bool_value();\n  else\n    error (\"__event_manager_file_renamed__: \"\n           \"first argument must be boolean for reload new named file\");\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.file_renamed (load_new);\n\n  return ovl ();\n}\n\nDEFMETHOD (openvar, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} openvar (@var{name})\nOpen the variable @var{name} in the graphical Variable Editor.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  if (! args(0).is_string ())\n    error (\"openvar: NAME must be a string\");\n\n  std::string name = args(0).string_value ();\n\n  octave_value val = interp.varval (name);\n\n  if (val.is_undefined ())\n    error (\"openvar: '%s' is not a variable\", name.c_str ());\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.edit_variable (name, val);\n\n  return ovl ();\n}\n\n/*\n%!error openvar ()\n%!error openvar (\"a\", \"b\")\n%!error <NAME must be a string> openvar (1:10)\n*/\n\nDEFMETHOD (__event_manager_show_terminal_window__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __event_manager_show_terminal_window__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  std::string file;\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.show_terminal_window ();\n\n  return ovl ();\n}\n\nDEFMETHOD (__event_manager_show_documentation__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __event_manager_show_documentation__ (@var{filename})\nUndocumented internal function.\n@end deftypefn */)\n{\n  std::string file;\n\n  if (args.length () >= 1)\n    file = args(0).string_value();\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  return ovl (evmgr.show_documentation (file));\n}\n\nDEFMETHOD (__event_manager_register_documentation__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __event_manager_register_documentation__ (@var{filename})\nUndocumented internal function.\n@end deftypefn */)\n{\n  std::string file;\n\n  if (args.length () >= 1)\n    file = args(0).string_value();\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  return ovl (evmgr.register_documentation (file));\n}\n\nDEFMETHOD (__event_manager_unregister_documentation__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __event_manager_unregister_documentation__ (@var{filename})\nUndocumented internal function.\n@end deftypefn */)\n{\n  std::string file;\n\n  if (args.length () >= 1)\n    file = args(0).string_value();\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  return ovl (evmgr.unregister_documentation (file));\n}\n\nDEFMETHOD (__event_manager_show_file_browser__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __event_manager_show_file_browser__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.show_file_browser ();\n\n  return ovl ();\n}\n\nDEFMETHOD (__event_manager_show_command_history__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __event_manager_show_command_history__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.show_command_history ();\n\n  return ovl ();\n}\n\nDEFMETHOD (__event_manager_show_workspace__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __event_manager_show_workspace__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.show_workspace ();\n\n  return ovl ();\n}\n\nDEFMETHOD (__event_manager_show_community_news__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __event_manager_show_community_news__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.show_community_news ();\n\n  return ovl ();\n}\n\nDEFMETHOD (__event_manager_show_release_notes__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __event_manager_show_release_notes__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.show_release_notes ();\n\n  return ovl ();\n}\n\nDEFMETHOD (__event_manager_gui_status_update__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __event_manager_gui_status_update__ (@var{feature}, @var{status})\nInternal function for updating the status of some features in the GUI.\n@end deftypefn */)\n{\n  // This is currently a stub and should only be activated some\n  // interpreter action only implemented in m-files requires to update\n  // a status indicator in the gui.  BUT: This internal function can\n  // be activated by the user leading to gui indicators not reflecting\n  // the real state of the related feature.\n  return ovl ();\n\n  std::string feature;\n  std::string status;\n\n  if (! (Fisguirunning ())(0).is_true ())\n    return ovl ();\n\n  if (args.length () < 2)\n    error (\"__event_manager_gui_status_update__: two parameters required\");\n  if (! (args(0).is_string ()))\n    error (\"__event_manager_gui_status_update__: FEATURE must be a string\");\n  if (! (args(1).is_string ()))\n    error (\"__event_manager_gui_status_update__: STATUS must be a string\");\n\n  feature = args(0).string_value ();\n  status = args(1).string_value ();\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  return ovl (evmgr.gui_status_update (feature, status));\n}\n\nDEFMETHOD (__event_manager_update_gui_lexer__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __event_manager_update_gui_lexer__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  event_manager& evmgr = interp.get_event_manager ();\n\n  return ovl (evmgr.update_gui_lexer ());\n}\n\nDEFMETHOD (__event_manager_copy_image_to_clipboard__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __event_manager_copy_image_to_clipboard__ (@var{filename})\nUndocumented internal function.\n@end deftypefn */)\n{\n  std::string file;\n\n  if (args.length () >= 1)\n    file = args(0).string_value();\n\n  event_manager& evmgr = interp.get_event_manager ();\n  evmgr.copy_image_to_clipboard (file);\n  return ovl ();\n}\n\nDEFMETHOD (commandhistory, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} commandhistory ()\nShow the GUI command history window and give it the keyboard focus.\n@seealso{commandwindow, filebrowser, workspace}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  event_manager& evmgr = interp.get_event_manager ();\n  evmgr.focus_window (\"history\");\n  return ovl ();\n}\n\nDEFMETHOD (commandwindow, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} commandwindow ()\nShow the GUI command window and give it the keyboard focus.\n@seealso{commandhistory, filebrowser, workspace}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  event_manager& evmgr = interp.get_event_manager ();\n  evmgr.focus_window (\"command\");\n  return ovl ();\n}\n\nDEFMETHOD (filebrowser, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} filebrowser ()\nShow the GUI file browser window and give it the keyboard focus.\n@seealso{commandwindow, commandhistory, workspace}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  event_manager& evmgr = interp.get_event_manager ();\n  evmgr.focus_window (\"filebrowser\");\n  return ovl ();\n}\n\nDEFMETHOD (workspace, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} workspace ()\nShow the GUI workspace window and give it the keyboard focus.\n@seealso{commandwindow, commandhistory, filebrowser}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  event_manager& evmgr = interp.get_event_manager ();\n  evmgr.focus_window (\"workspace\");\n  return ovl ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/event-manager.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_event_manager_h)\n#define octave_event_manager_h 1\n\n#include \"octave-config.h\"\n\n#include <functional>\n#include <list>\n#include <memory>\n#include <stack>\n#include <string>\n\n#include \"oct-mutex.h\"\n#include \"octave.h\"\n#include \"event-queue.h\"\n#include \"uint8NDArray.h\"\n\nclass octave_value;\nclass string_vector;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntypedef std::function<void ()> fcn_callback;\ntypedef std::function<void (interpreter&)> meth_callback;\n\nclass execution_exception;\nclass symbol_info_list;\n\n// The methods in this class provide a way to pass signals to the GUI\n// thread.  A GUI that wishes to act on these events should derive\n// from this class and perform actions in a thread-safe way.  In\n// Octave's Qt-based GUI, for example, these functions are all\n// implemented as wrappers around Qt signals that trigger actions in\n// the GUI.  The Qt signal/slot mechanism ensures that the actions are\n// properly queued for execution when the objects corresponding to the\n// signal and slot belong to different threads.\n//\n// These functions should not be called directly.  Instead all\n// requests from the interpreter for GUI actions should be done\n// through the event_manager class.  That class checks to ensure that\n// the GUI is connected and enabled before calling these virtual\n// functions.\n\n// FIXME: it would be nice if instead of requiring the GUI to derive\n// from this class, it could subscribe to individual events, possibly\n// multiple times.  In that way, it would be more flexible and\n// decentralized, similar to the Qt signal/slot connection mechanism\n// and would allow the GUI to connect multiple signals to a single\n// action or multiple actions to a single signal.\n\n// FIXME: audit this list of functions and determine whether they are\n// all necessary and whether there might be better names for them.\n\nclass OCTINTERP_API interpreter_events\n{\npublic:\n\n  interpreter_events () = default;\n\n  interpreter_events (const interpreter_events&) = default;\n\n  interpreter_events& operator = (const interpreter_events&) = default;\n\n  virtual ~interpreter_events () = default;\n\n  // Note: START_GUI and CLOSE_GUI currently only work with the new\n  // experimental terminal widget.\n\n  // Set GUI_APP to true when starting Octave as a gui application\n  // (invoked with the --gui option) and false when starting the GUI\n  // from the Octave prompt when Octave is already running as a\n  // command line application.\n\n  virtual void start_gui (bool /*gui_app*/ = false) { }\n  virtual void close_gui () { }\n\n  // Dialogs.\n\n  virtual bool have_dialogs () const { return false; }\n\n  typedef std::list<std::pair<std::string, std::string>> filter_list;\n\n  virtual std::list<std::string>\n  file_dialog (const filter_list& /*filter*/,\n               const std::string& /*title*/,\n               const std::string& /*filename*/,\n               const std::string& /*dirname*/,\n               const std::string& /*multimode*/)\n  {\n    return std::list<std::string> ();\n  }\n\n  virtual std::list<std::string>\n  input_dialog (const std::list<std::string>& /*prompt*/,\n                const std::string& /*title*/,\n                const std::list<float>& /*nr*/,\n                const std::list<float>& /*nc*/,\n                const std::list<std::string>& /*defaults*/)\n  {\n    return std::list<std::string> ();\n  }\n\n  virtual std::pair<std::list<int>, int>\n  list_dialog (const std::list<std::string>& /*list*/,\n               const std::string& /*mode*/, int /*width*/, int /*height*/,\n               const std::list<int>& /*initial_value*/,\n               const std::string& /*name*/,\n               const std::list<std::string>& /*prompt*/,\n               const std::string& /*ok_string*/,\n               const std::string& /*cancel_string*/)\n  {\n    return std::pair<std::list<int>, int> ();\n  }\n\n  virtual std::string\n  question_dialog (const std::string& /*msg*/, const std::string& /*title*/,\n                   const std::string& /*btn1*/, const std::string& /*btn2*/,\n                   const std::string& /*btn3*/, const std::string& /*btndef*/)\n  {\n    return \"\";\n  }\n\n  virtual void update_path_dialog () {  }\n\n  virtual void show_preferences () { }\n\n  virtual void apply_preferences () { }\n\n  virtual void show_terminal_window () { }\n\n  virtual bool show_documentation (const std::string& /*file*/)\n  {\n    return false;\n  }\n\n  virtual void show_file_browser () { }\n\n  virtual void show_command_history () { }\n\n  virtual void show_workspace () { }\n\n  virtual void show_community_news (int /*serial*/) { }\n  virtual void show_release_notes () { }\n\n  virtual bool edit_file (const std::string& /*file*/) { return false; }\n\n  virtual void\n  edit_variable (const std::string& /*name*/, const octave_value& /*val*/)\n  { }\n\n  // Other requests for user interaction, usually some kind of\n  // confirmation before another action.  Could these be reformulated\n  // using the question_dialog action?\n\n  virtual bool confirm_shutdown () { return true; }\n\n  virtual bool prompt_new_edit_file (const std::string& /*file*/)\n  {\n    return false;\n  }\n\n  virtual int\n  debug_cd_or_addpath_error (const std::string& /*file*/,\n                             const std::string& /*dir*/,\n                             bool /*addpath_option*/)\n  {\n    return -1;\n  }\n\n  // Requests for information normally stored in the GUI.\n\n  virtual uint8NDArray get_named_icon (const std::string& /*icon_name*/)\n  {\n    return uint8NDArray ();\n  }\n\n  virtual std::string gui_preference (const std::string& /*key*/,\n                                      const std::string& /*value*/)\n  {\n    return \"\";\n  }\n\n  // Requests for GUI action that do not require user interaction.\n  // These are different from other notifications in that they are not\n  // associated with changes in the interpreter state (like a change\n  // in the current working directory or command history).\n\n  virtual bool copy_image_to_clipboard (const std::string& /*file*/)\n  {\n    return false;\n  }\n\n  virtual void focus_window (const std::string /*win_name*/)\n  { }\n\n  virtual void\n  execute_command_in_terminal (const std::string& /*command*/) { }\n\n  virtual std::string\n  get_input_from_terminal (const std::string& /*prompt*/)\n  {\n    return \"\";\n  }\n\n  virtual void register_documentation (const std::string& /*file*/) { }\n\n  virtual void unregister_documentation (const std::string& /*file*/) { }\n\n  virtual void interpreter_output (const std::string& /*msg*/) { }\n\n  virtual void display_exception (const execution_exception& ee, bool beep);\n\n  virtual void gui_status_update (const std::string& /*feature*/,\n                                  const std::string& /*status*/) { }\n\n  virtual void update_gui_lexer () { }\n\n  // Notifications of events in the interpreter that a GUI will\n  // normally wish to respond to.\n\n  virtual void directory_changed (const std::string& /*dir*/) { }\n\n  virtual void\n  file_remove (const std::string& /*old_nm*/, const std::string& /*new_nm*/)\n  { }\n\n  virtual void file_renamed (bool) { }\n\n  virtual void\n  set_workspace (bool /*top_level*/, bool /*debug*/,\n                 const symbol_info_list& /*syminfo*/,\n                 bool /*update_variable_editor*/)\n  { }\n\n  virtual void clear_workspace () { }\n\n  virtual void update_prompt (const std::string& /*prompt*/) { }\n\n  virtual void set_history (const string_vector& /*hist*/) { }\n\n  virtual void append_history (const std::string& /*hist_entry*/) { }\n\n  virtual void clear_history () { }\n\n  virtual void pre_input_event () { }\n\n  virtual void post_input_event () { }\n\n  virtual void\n  enter_debugger_event (const std::string& /*fcn_name*/,\n                        const std::string& /*fcn_file_name*/,\n                        int /*line*/)\n  { }\n\n  virtual void\n  execute_in_debugger_event (const std::string& /*file*/, int /*line*/) { }\n\n  virtual void exit_debugger_event () { }\n\n  virtual void\n  update_breakpoint (bool /*insert*/, const std::string& /*file*/,\n                     int /*line*/, const std::string& /*cond*/)\n  { }\n\n  virtual void interpreter_interrupted () { }\n};\n\n//! Provides threadsafe access to octave.\n//!\n//! This class provides thread-safe communication between the\n//! interpreter and a GUI.\n\nclass OCTINTERP_API event_manager\n{\npublic:\n\n  OCTINTERP_API event_manager (interpreter& interp);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (event_manager)\n\n  virtual ~event_manager ();\n\n  // OBJ should be an object of a class that is derived from the base\n  // class interpreter_events, or nullptr to disconnect and delete the\n  // previous link.\n\n  OCTINTERP_API void\n  connect_link (const std::shared_ptr<interpreter_events>& obj);\n\n  OCTINTERP_API bool enable ();\n\n  bool disable ()\n  {\n    bool retval = m_link_enabled;\n    m_link_enabled = false;\n    return retval;\n  }\n\n  bool enabled () const\n  {\n    return m_link_enabled;\n  }\n\n  // Make the Qt actions available for others.  This is a temporary\n  // solution to allow Qt actions like opening the documentation\n  // browser when the primary interpreter_events object is not the one\n  // defined for the Qt GUI.\n  void\n  install_qt_event_handlers (const std::shared_ptr<interpreter_events>& obj)\n  {\n    m_qt_event_handlers = obj;\n  }\n\n  std::shared_ptr<interpreter_events>\n  qt_event_handlers () const { return m_qt_event_handlers; }\n\n  // If disable is TRUE, then no additional events will be processed\n  // other than exit.\n\n  OCTINTERP_API void process_events (bool disable = false);\n\n  OCTINTERP_API void discard_events ();\n\n  // The post_event and post_exception functions provide a thread-safe\n  // way for the GUI to queue interpreter functions for execution.\n  // The queued functions are executed when the interpreter is\n  // otherwise idle.\n\n  void push_event_queue ();\n  void pop_event_queue ();\n\n  OCTINTERP_API void post_event (const fcn_callback& fcn);\n  OCTINTERP_API void post_event (const meth_callback& meth);\n\n  // The following functions correspond to the virtual fuunctions in\n  // the interpreter_events class.  They provide a way for the\n  // interpreter to notify the GUI that some event has occurred\n  // (directory or workspace changed, for example) or to request the\n  // GUI to perform some action (display a dialog, for example).\n\n  // Please keep this list of declarations in the same order as the\n  // ones above in the interpreter_events class.\n\n\n  // Note: START_GUI and CLOSE_GUI currently only work with the new\n  // experimental terminal object.\n\n  void start_gui (bool gui_app = false)\n  {\n    if (enabled ())\n      m_instance->start_gui (gui_app);\n  }\n\n  void close_gui ()\n  {\n    if (enabled ())\n      m_instance->close_gui ();\n  }\n\n  // Dialogs\n\n  bool have_dialogs () const\n  {\n    return m_qt_event_handlers && m_qt_event_handlers->have_dialogs ();\n  }\n\n  typedef std::list<std::pair<std::string, std::string>> filter_list;\n\n  std::list<std::string>\n  file_dialog (const filter_list& filter, const std::string& title,\n               const std::string& filename, const std::string& dirname,\n               const std::string& multimode)\n  {\n    return (enabled () && have_dialogs ()\n            ? m_instance->file_dialog (filter, title, filename, dirname,\n                                       multimode)\n            : std::list<std::string> ());\n  }\n\n  std::list<std::string>\n  input_dialog (const std::list<std::string>& prompt,\n                const std::string& title,\n                const std::list<float>& nr,\n                const std::list<float>& nc,\n                const std::list<std::string>& defaults)\n  {\n    return (enabled () && have_dialogs ()\n            ? m_instance->input_dialog (prompt, title, nr, nc, defaults)\n            : std::list<std::string> ());\n  }\n\n  std::pair<std::list<int>, int>\n  list_dialog (const std::list<std::string>& list,\n               const std::string& mode,\n               int width, int height,\n               const std::list<int>& initial_value,\n               const std::string& name,\n               const std::list<std::string>& prompt,\n               const std::string& ok_string,\n               const std::string& cancel_string)\n  {\n    return (enabled () && have_dialogs ()\n            ? m_instance->list_dialog (list, mode, width, height,\n                                       initial_value, name, prompt,\n                                       ok_string, cancel_string)\n            : std::pair<std::list<int>, int> ());\n  }\n\n  std::string\n  question_dialog (const std::string& msg, const std::string& title,\n                   const std::string& btn1, const std::string& btn2,\n                   const std::string& btn3, const std::string& btndef)\n  {\n    return (enabled () && have_dialogs ()\n            ? m_instance->question_dialog (msg, title, btn1,\n                                           btn2, btn3, btndef)\n            : \"\");\n  }\n\n  void update_path_dialog ()\n  {\n    if (application::is_gui_running () && enabled ())\n      m_instance->update_path_dialog ();\n  }\n\n  bool show_preferences ()\n  {\n    if (enabled ())\n      {\n        m_instance->show_preferences ();\n        return true;\n      }\n    else\n      return false;\n  }\n\n  bool apply_preferences ()\n  {\n    if (enabled ())\n      {\n        m_instance->apply_preferences ();\n        return true;\n      }\n    else\n      return false;\n  }\n\n  void show_terminal_window ()\n  {\n    if (enabled ())\n      m_instance->show_terminal_window ();\n  }\n\n  bool show_documentation (const std::string& file)\n  {\n    return enabled () ? m_instance->show_documentation (file) : false;\n  }\n\n  void show_file_browser ()\n  {\n    if (enabled ())\n      m_instance->show_file_browser ();\n  }\n\n  void show_command_history ()\n  {\n    if (enabled ())\n      m_instance->show_command_history ();\n  }\n\n  void show_workspace ()\n  {\n    if (enabled ())\n      m_instance->show_workspace ();\n  }\n\n  void show_community_news (int serial = -1)\n  {\n    if (enabled ())\n      m_instance->show_community_news (serial);\n  }\n\n  void show_release_notes ()\n  {\n    if (enabled ())\n      m_instance->show_release_notes ();\n  }\n\n  bool edit_file (const std::string& file)\n  {\n    return enabled () ? m_instance->edit_file (file) : false;\n  }\n\n  bool edit_variable (const std::string& name, const octave_value& val)\n  {\n    if (enabled ())\n      {\n        m_instance->edit_variable (name, val);\n        return true;\n      }\n    else\n      return false;\n  }\n\n  bool confirm_shutdown ()\n  {\n    bool retval = true;\n\n    if (enabled ())\n      retval = m_instance->confirm_shutdown ();\n\n    return retval;\n  }\n\n  bool prompt_new_edit_file (const std::string& file)\n  {\n    return enabled () ? m_instance->prompt_new_edit_file (file) : false;\n  }\n\n  int debug_cd_or_addpath_error (const std::string& file,\n                                 const std::string& dir, bool addpath_option)\n  {\n    return (enabled ()\n            ? m_instance->debug_cd_or_addpath_error (file, dir,\n                addpath_option)\n            : 0);\n  }\n\n  uint8NDArray get_named_icon (const std::string& icon_name)\n  {\n    return (enabled ()\n            ? m_instance->get_named_icon (icon_name) : uint8NDArray ());\n  }\n\n  std::string gui_preference (const std::string& key,\n                              const std::string& value)\n  {\n    return enabled () ? m_instance->gui_preference (key, value) : \"\";\n  }\n\n  bool copy_image_to_clipboard (const std::string& file)\n  {\n    return enabled () ? m_instance->copy_image_to_clipboard (file) : false;\n  }\n\n  virtual void focus_window (const std::string win_name)\n  {\n    if (enabled ())\n      m_instance->focus_window (win_name);\n  }\n\n  // Preserves pending input.\n  void execute_command_in_terminal (const std::string& command)\n  {\n    if (enabled ())\n      m_instance->execute_command_in_terminal (command);\n  }\n\n  std::string get_input_from_terminal (const std::string& prompt)\n  {\n    if (enabled ())\n      return m_instance->get_input_from_terminal (prompt);\n    else\n      return \"\";\n  }\n\n  bool register_documentation (const std::string& file)\n  {\n    if (enabled ())\n      {\n        m_instance->register_documentation (file);\n        return true;\n      }\n    else\n      return false;\n  }\n\n  bool unregister_documentation (const std::string& file)\n  {\n    if (enabled ())\n      {\n        m_instance->unregister_documentation (file);\n        return true;\n      }\n    else\n      return false;\n  }\n\n  bool interpreter_output (const std::string& msg)\n  {\n    if (enabled ())\n      {\n        m_instance->interpreter_output (msg);\n        return true;\n      }\n    else\n      return false;\n  }\n\n  bool display_exception (const execution_exception& ee, bool beep = false)\n  {\n    if (enabled ())\n      {\n        m_instance->display_exception (ee, beep);\n        return true;\n      }\n    else\n      return false;\n  }\n\n  bool gui_status_update (const std::string& feature,\n                          const std::string& status)\n  {\n    if (enabled ())\n      {\n        m_instance->gui_status_update (feature, status);\n        return true;\n      }\n    else\n      return false;\n  }\n\n  bool update_gui_lexer ()\n  {\n    if (enabled ())\n      {\n        m_instance->update_gui_lexer ();\n        return true;\n      }\n    else\n      return false;\n  }\n\n  void directory_changed (const std::string& dir)\n  {\n    if (enabled ())\n      m_instance->directory_changed (dir);\n  }\n\n  // Methods for removing/renaming files which might be open in editor\n  void file_remove (const std::string& old_name, const std::string& new_name)\n  {\n    if (application::is_gui_running () && enabled ())\n      m_instance->file_remove (old_name, new_name);\n  }\n\n  void file_renamed (bool load_new)\n  {\n    if (application::is_gui_running () && enabled ())\n      m_instance->file_renamed (load_new);\n  }\n\n  OCTINTERP_API void set_workspace ();\n\n  void set_workspace (bool top_level, const symbol_info_list& syminfo,\n                      bool update_variable_editor = true)\n  {\n    if (enabled ())\n      m_instance->set_workspace (top_level, m_debugging, syminfo,\n                                 update_variable_editor);\n  }\n\n  void clear_workspace ()\n  {\n    if (enabled ())\n      m_instance->clear_workspace ();\n  }\n\n  void update_prompt (const std::string& prompt)\n  {\n    if (enabled ())\n      m_instance->update_prompt (prompt);\n  }\n\n  OCTINTERP_API void set_history ();\n\n  void set_history (const string_vector& hist)\n  {\n    if (enabled ())\n      m_instance->set_history (hist);\n  }\n\n  void append_history (const std::string& hist_entry)\n  {\n    if (enabled ())\n      m_instance->append_history (hist_entry);\n  }\n\n  void clear_history ()\n  {\n    if (enabled ())\n      m_instance->clear_history ();\n  }\n\n  void pre_input_event ()\n  {\n    if (enabled ())\n      m_instance->pre_input_event ();\n  }\n\n  void post_input_event ()\n  {\n    if (enabled ())\n      m_instance->post_input_event ();\n  }\n\n  void enter_debugger_event (const std::string& fcn_name,\n                             const std::string& fcn_file_name, int line)\n  {\n    if (enabled ())\n      {\n        m_debugging = true;\n\n        m_instance->enter_debugger_event (fcn_name, fcn_file_name, line);\n      }\n  }\n\n  void execute_in_debugger_event (const std::string& file, int line)\n  {\n    if (enabled ())\n      m_instance->execute_in_debugger_event (file, line);\n  }\n\n  void exit_debugger_event ()\n  {\n    if (enabled () && m_debugging)\n      {\n        m_debugging = false;\n\n        m_instance->exit_debugger_event ();\n      }\n  }\n\n  void update_breakpoint (bool insert, const std::string& file,\n                          int line, const std::string& cond = \"\")\n  {\n    if (enabled ())\n      m_instance->update_breakpoint (insert, file, line, cond);\n  }\n\n  void interpreter_interrupted ()\n  {\n    if (enabled ())\n      m_instance->interpreter_interrupted ();\n  }\n\nprotected:\n\n  // Semaphore to lock access to the event queue.\n  mutex *m_event_queue_mutex;\n\n  // Event Queue.  We use a stack so that we can handle evaluation in\n  // the debugger when we are executing in server mode.  In server\n  // mode, code is evaluated from inside the event queue.  So when the\n  // evaluator reaches a breakpoint, the queue is already locked and\n  // executing an event function.  We can't just add a new command to the\n  // existing queue, so we need another one that can process new\n  // events generated at the debug prompt.  When execution continues\n  // (dbcont or dbstep, for example) we pop the queue and return to\n  // the previous point of execution.\n\n  std::stack<std::shared_ptr<event_queue>> m_gui_event_queue;\n\n  bool m_debugging;\n  bool m_link_enabled;\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  // Using a shared_ptr to manage the link_events object ensures that it\n  // will be valid until it is no longer needed.\n\n  std::shared_ptr<interpreter_events> m_instance;\n\n  std::shared_ptr<interpreter_events> m_qt_event_handlers;\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/event-queue.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"cmd-edit.h\"\n\n#include \"error.h\"\n#include \"event-queue.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid event_queue::run (std::size_t num)\n{\n  if (num > size ())\n    num = size ();\n\n  for (std::size_t i = 0; i < num; i++)\n    {\n      run_first ();\n\n      // If event_loop_interrupted is TRUE, a user callback event has requested\n      // that we break out of the readline event handler to process a command\n      // or other action.\n\n      if (command_editor::event_loop_interrupted ())\n        {\n          command_editor::interrupt_event_loop (false);\n          break;\n        }\n    }\n}\n\nvoid\nevent_queue_safe::warn_unhandled_exception () const\n{\n  warning (\"unhandled exception in event_queue_safe handler.  \"\n           \"It is a bug in Octave for this to happen.  \"\n           \"Please help improve Octave by reporting it.\");\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/event-queue.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_event_queue_h)\n#define octave_event_queue_h 1\n\n#include \"octave-config.h\"\n\n#include <queue>\n#include <memory>\n\n#include \"action-container.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass event_queue : public action_container\n{\npublic:\n\n  event_queue () : m_fifo () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (event_queue)\n\n  // Destructor should not raise an exception, so all actions registered\n  // should be exception-safe.  If you're not sure, see event_queue_safe.\n\n  ~event_queue () { run (); }\n\n  void run_first ()\n  {\n    if (! empty ())\n      {\n        // No leak on exception!\n        std::unique_ptr<elem> ptr (m_fifo.front ());\n        m_fifo.pop ();\n        ptr->run ();\n      }\n  }\n\n  // Overload functions from action-container\n  OCTINTERP_API void run (std::size_t num);\n\n  void run () { run (size ()); }\n\n  void discard_first ()\n  {\n    if (! empty ())\n      {\n        elem *ptr = m_fifo.front ();\n        m_fifo.pop ();\n        delete ptr;\n      }\n  }\n\n  std::size_t size () const { return m_fifo.size (); }\n\nprotected:\n\n  void add_action (elem *new_elem)\n  {\n    m_fifo.push (new_elem);\n  }\n\n  //--------\n\n  std::queue<elem *> m_fifo;\n};\n\n// Like event_queue, but this one will guard against the\n// possibility of seeing an exception (or interrupt) in the cleanup actions.\n// Not that we can do much about it, but at least we won't crash.\n\nclass event_queue_safe : public event_queue\n{\npublic:\n\n  event_queue_safe () : event_queue () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (event_queue_safe)\n\n  ~event_queue_safe ()\n  {\n    while (! empty ())\n      {\n        try\n          {\n            run_first ();\n          }\n        catch (...) // Yes, the black hole.  Remember we're in a dtor.\n          {\n            warn_unhandled_exception ();\n          }\n      }\n  }\n\nprivate:\n\n  void warn_unhandled_exception () const;\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/fcn-info.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"oct-env.h\"\n#include \"oct-sysdep.h\"\n\n#include \"defun.h\"\n#include \"fcn-info.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ov-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"parse.h\"\n#include \"symscope.h\"\n#include \"symtab.h\"\n#include \"utils.h\"\n\n// Should Octave always check to see if function files have changed\n// since they were last compiled?\nstatic int Vignore_function_time_stamp = 1;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\noctave_value\nfcn_info::fcn_info_rep::load_private_function (const std::string& dir_name)\n{\n  octave_value retval;\n\n  load_path& lp = __get_load_path__ ();\n\n  std::string file_name = lp.find_private_fcn (dir_name, name);\n\n  if (file_name.empty ())\n    return retval;\n\n  octave_value ov_fcn = load_fcn_from_file (file_name, dir_name);\n\n  if (ov_fcn.is_undefined ())\n    return retval;\n\n  octave_function *tmpfcn = ov_fcn.function_value ();\n\n  if (! tmpfcn)\n    return retval;\n\n  std::string class_name;\n\n  std::size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ());\n\n  if (pos != std::string::npos)\n    {\n      std::string tmp = dir_name.substr (pos+1);\n\n      if (tmp[0] == '@')\n        class_name = tmp.substr (1);\n    }\n\n  tmpfcn->mark_as_private_function (class_name);\n\n  private_functions[sys::canonicalize_file_name (dir_name)] = ov_fcn;\n\n  return ov_fcn;\n}\n\noctave_value\nfcn_info::fcn_info_rep::load_class_constructor ()\n{\n  octave_value retval;\n\n  std::string dir_name;\n\n  load_path& lp = __get_load_path__ ();\n\n  std::string file_name = lp.find_method (name, name, dir_name, package_name);\n\n  if (! file_name.empty ())\n    {\n      octave_value ov_fcn\n        = load_fcn_from_file (file_name, dir_name, name,\n                              package_name);\n\n      if (ov_fcn.is_defined ())\n        {\n          // Note: ov_fcn may be an octave_classdef_meta object instead\n          // of the actual constructor function.\n\n          retval = ov_fcn;\n\n          class_constructors[name] = retval;\n          class_methods[name] = retval;\n        }\n    }\n  else\n    {\n      // Classdef constructors can be defined anywhere in the path, not\n      // necessarily in @-folders.  Look for a normal function and load it.\n      // If the loaded function is a classdef constructor, store it as such\n      // and restore function_on_path to its previous value.\n\n      octave_value old_function_on_path = function_on_path;\n\n      octave_value maybe_cdef_ctor = find_user_function ();\n\n      if (maybe_cdef_ctor.is_defined ())\n        {\n          octave_function *fcn = maybe_cdef_ctor.function_value (true);\n\n          if (fcn && fcn->is_classdef_constructor ())\n            {\n              retval = maybe_cdef_ctor;\n\n              class_constructors[name] = retval;\n              class_methods[name] = retval;\n\n              function_on_path = old_function_on_path;\n            }\n        }\n    }\n\n  return retval;\n}\n\noctave_value\nfcn_info::fcn_info_rep::load_class_method (const std::string& dispatch_type)\n{\n  octave_value retval;\n\n  if (full_name () == dispatch_type)\n    retval = load_class_constructor ();\n  else\n    {\n      cdef_manager& cdm = __get_cdef_manager__ ();\n\n      retval = cdm.find_method_symbol (name, dispatch_type);\n\n      if (! retval.is_defined ())\n        {\n          std::string dir_name;\n\n          load_path& lp = __get_load_path__ ();\n\n          std::string file_name = lp.find_method (dispatch_type, name,\n                                                  dir_name);\n\n          if (! file_name.empty ())\n            {\n              octave_value ov_fcn\n                = load_fcn_from_file (file_name, dir_name,\n                                      dispatch_type);\n\n              if (ov_fcn.is_defined ())\n                {\n                  octave_function *tmpfcn = ov_fcn.function_value ();\n\n                  if (tmpfcn && tmpfcn->is_class_method (dispatch_type))\n                    {\n                      retval = ov_fcn;\n\n                      class_methods[dispatch_type] = retval;\n                    }\n                }\n            }\n\n          if (retval.is_undefined ())\n            {\n              // Search parent classes\n\n              symbol_table& symtab = __get_symbol_table__ ();\n\n              const std::list<std::string>& plist\n                = symtab.parent_classes (dispatch_type);\n\n              auto it = plist.begin ();\n\n              while (it != plist.end ())\n                {\n                  retval = find_method (*it);\n\n                  if (retval.is_defined ())\n                    {\n                      class_methods[dispatch_type] = retval;\n                      break;\n                    }\n\n                  it++;\n                }\n            }\n\n          if (retval.is_undefined ())\n            {\n              // Search for built-in functions that are declared to\n              // handle specific types.\n\n              if (built_in_function.is_defined ())\n                {\n                  octave_function *fcn = built_in_function.function_value ();\n\n                  if (fcn && fcn->handles_dispatch_class (dispatch_type))\n                    {\n                      retval = built_in_function;\n\n                      class_methods[dispatch_type] = retval;\n                    }\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\n// :-) JWE, can you parse this? Returns a 2-D array with second dimension equal\n// to btyp_num_types (static constant).  Only the leftmost dimension can be\n// variable in C/C++.  Typedefs are boring.\n\nstatic builtin_type_t (* build_sup_table ())[btyp_num_types]\n{\n  static builtin_type_t sup_table[btyp_num_types][btyp_num_types];\n  for (int i = 0; i < btyp_num_types; i++)\n    for (int j = 0; j < btyp_num_types; j++)\n      {\n        builtin_type_t ityp = static_cast<builtin_type_t> (i);\n        builtin_type_t jtyp = static_cast<builtin_type_t> (j);\n        // FIXME: Is this really right?\n        bool use_j\n        = (jtyp == btyp_func_handle || ityp == btyp_bool\n           || (btyp_isarray (ityp)\n               && (! btyp_isarray (jtyp)\n                   || (btyp_isinteger (jtyp) && ! btyp_isinteger (ityp))\n                   || ((ityp == btyp_double || ityp == btyp_complex\n                        || ityp == btyp_char)\n                       && (jtyp == btyp_float\n                           || jtyp == btyp_float_complex)))));\n\n        sup_table[i][j] = (use_j ? jtyp : ityp);\n      }\n\n  return sup_table;\n}\n\nstd::string\nget_dispatch_type (const octave_value_list& args,\n                   builtin_type_t& builtin_type)\n{\n  static builtin_type_t (*sup_table)[btyp_num_types] = build_sup_table ();\n  std::string dispatch_type;\n\n  int n = args.length ();\n\n  if (n > 0)\n    {\n      int i = 0;\n      builtin_type = args(0).builtin_type ();\n      if (builtin_type != btyp_unknown)\n        {\n          for (i = 1; i < n; i++)\n            {\n              builtin_type_t bti = args(i).builtin_type ();\n              if (bti != btyp_unknown)\n                builtin_type = sup_table[builtin_type][bti];\n              else\n                {\n                  builtin_type = btyp_unknown;\n                  break;\n                }\n            }\n        }\n\n      if (builtin_type == btyp_unknown)\n        {\n          // There's a non-builtin class in the argument list.\n          dispatch_type = args(i).class_name ();\n\n          symbol_table& symtab = __get_symbol_table__ ();\n\n          for (int j = i+1; j < n; j++)\n            {\n              octave_value arg = args(j);\n\n              if (arg.builtin_type () == btyp_unknown)\n                {\n                  std::string cname = arg.class_name ();\n\n                  // Only switch to type of ARG if it is marked superior\n                  // to the current DISPATCH_TYPE.\n                  if (! symtab.is_superiorto (dispatch_type, cname)\n                      && symtab.is_superiorto (cname, dispatch_type))\n                    dispatch_type = cname;\n                }\n            }\n        }\n      else\n        dispatch_type = btyp_class_name[builtin_type];\n    }\n  else\n    builtin_type = btyp_unknown;\n\n  return dispatch_type;\n}\n\nstd::string\nget_dispatch_type (const octave_value_list& args)\n{\n  builtin_type_t builtin_type;\n  return get_dispatch_type (args, builtin_type);\n}\n\n// Find function definition according to the following precedence list:\n//\n//   nested functions (and subfunctions)\n//   local functions in the current file\n//   private function\n//   class method\n//   class constructor\n//   command-line function\n//   autoload function\n//   functions on the load_path (current directory is always first)\n//   package (FIXME: does this belong here?)\n//   built-in function\n\noctave_value\nfcn_info::fcn_info_rep::find (const symbol_scope& scope,\n                              const octave_value_list& args)\n{\n  symbol_scope search_scope\n    = (scope\n       ? scope : __get_current_scope__ ());\n\n  octave_value retval = xfind (search_scope, args);\n\n  if (retval.is_undefined ())\n    {\n      // It is possible that the user created a file on the fly since\n      // the last prompt or chdir, so try updating the load path and\n      // searching again.\n\n      load_path& lp = __get_load_path__ ();\n\n      lp.update ();\n\n      retval = xfind (search_scope, args);\n    }\n\n  return retval;\n}\n\n\nstatic void\nsplit_name_with_package (const std::string& name, std::string& fname,\n                         std::string& pname)\n{\n  std::size_t pos = name.rfind ('.');\n\n  fname.clear ();\n  pname.clear ();\n\n  if (pos != std::string::npos)\n    {\n      fname = name.substr (pos + 1);\n      pname = name.substr (0, pos);\n    }\n  else\n    fname = name;\n}\n\n// Check the load path to see if file that defined this is still\n// visible.  If the file is no longer visible, then erase the\n// definition and move on.  If the file is visible, then we also\n// need to check to see whether the file has changed since the\n// function was loaded/parsed.  However, this check should only\n// happen once per prompt (for files found from relative path\n// elements, we also check if the working directory has changed\n// since the last time the function was loaded/parsed).\n//\n// FIXME: perhaps this should be done for all loaded functions when\n// the prompt is printed or the directory has changed, and then we\n// would not check for it when finding symbol definitions.\n\nstatic inline bool\nload_out_of_date_fcn (const std::string& file_name,\n                      const std::string& dir_name_arg,\n                      octave_value& function,\n                      const std::string& dispatch_type = \"\",\n                      const std::string& package_name = \"\")\n{\n  bool retval = false;\n\n  std::string dir_name = dir_name_arg;\n\n  if (dir_name.empty ())\n    {\n      std::size_t pos = file_name.find_last_of (sys::file_ops::dir_sep_chars ());\n\n      dir_name = file_name.substr (0, pos);\n    }\n\n  // FIXME: do the following job of determining private status and\n  // class membership in a separate function?\n\n  std::size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ());\n\n  bool is_private_fcn\n    = pos != std::string::npos && dir_name.substr (pos+1) == \"private\";\n\n  if (is_private_fcn)\n    dir_name = dir_name.substr (0, pos);\n\n  std::string class_name;\n\n  pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ());\n\n  if (pos != std::string::npos)\n    {\n      std::string tmp = dir_name.substr (pos+1);\n\n      if (tmp[0] == '@')\n        class_name = tmp.substr (1);\n    }\n\n  octave_value ov_fcn\n    = load_fcn_from_file (file_name, dir_name, dispatch_type,\n                          package_name);\n\n  if (ov_fcn.is_defined ())\n    {\n      retval = true;\n\n      octave_function *fcn = ov_fcn.function_value ();\n\n      if (is_private_fcn)\n        fcn->mark_as_private_function (class_name);\n\n      function = ov_fcn;\n    }\n  else\n    function = octave_value ();\n\n  return retval;\n}\n\nstatic bool\nout_of_date_check (octave_value& function,\n                   const std::string& dispatch_type = \"\",\n                   bool check_relative = true)\n{\n  bool retval = false;\n\n  octave_function *fcn = function.function_value (true);\n\n  if (fcn)\n    {\n      // FIXME: we need to handle subfunctions properly here.\n\n      if (! (fcn->is_subfunction () || fcn->is_anonymous_function ()))\n        {\n          std::string ff = fcn->fcn_file_name ();\n\n          if (! ff.empty ())\n            {\n              sys::time tc = fcn->time_checked ();\n\n              bool relative = check_relative && fcn->is_relative ();\n\n              if (tc <= Vlast_prompt_time\n                  || (relative && tc < Vlast_chdir_time))\n                {\n                  bool clear_breakpoints = false;\n                  std::string nm = fcn->name ();\n                  std::string pack = fcn->package_name ();\n                  std::string canonical_nm = fcn->canonical_name ();\n\n                  bool is_same_file = false;\n\n                  // check whether function is defined in a .m file\n                  bool is_user_code = fcn->is_user_code ();\n\n                  std::string file;\n                  std::string dir_name;\n\n                  if (check_relative)\n                    {\n                      int nm_len = nm.length ();\n\n                      if (sys::env::absolute_pathname (nm)\n                          && ((nm_len > 4\n                               && (nm.substr (nm_len-4) == \".oct\"\n                                   || nm.substr (nm_len-4) == \".mex\"))\n                              || (nm_len > 2\n                                  && nm.substr (nm_len-2) == \".m\")))\n                        file = nm;\n                      else\n                        {\n                          // We don't want to make this an absolute name,\n                          // because load_fcn_file looks at the name to\n                          // decide whether it came from a relative lookup.\n\n                          if (! dispatch_type.empty ())\n                            {\n                              load_path& lp = __get_load_path__ ();\n\n                              file = lp.find_method (dispatch_type, nm,\n                                                     dir_name, pack);\n\n                              if (file.empty ())\n                                {\n                                  std::string s_name;\n                                  std::string s_pack;\n\n                                  symbol_table& symtab = __get_symbol_table__ ();\n\n                                  const std::list<std::string>& plist\n                                    = symtab.parent_classes (dispatch_type);\n\n                                  std::list<std::string>::const_iterator it\n                                    = plist.begin ();\n\n                                  while (it != plist.end ())\n                                    {\n                                      split_name_with_package (*it, s_name,\n                                                               s_pack);\n\n                                      file = lp.find_method (*it, nm, dir_name,\n                                                             s_pack);\n                                      if (! file.empty ())\n                                        {\n                                          pack = s_pack;\n                                          break;\n                                        }\n\n                                      it++;\n                                    }\n                                }\n                            }\n\n                          // Maybe it's an autoload?\n                          if (file.empty ())\n                            {\n                              tree_evaluator& tw = __get_evaluator__ ();\n\n                              file = tw.lookup_autoload (nm);\n                            }\n\n                          if (file.empty ())\n                            {\n                              load_path& lp = __get_load_path__ ();\n                              file = lp.find_fcn (nm, dir_name, pack);\n                            }\n                        }\n\n                      if (! file.empty ())\n                        is_same_file = sys::same_file (file, ff);\n                    }\n                  else\n                    {\n                      is_same_file = true;\n                      file = ff;\n                    }\n\n                  if (file.empty ())\n                    {\n                      // Can't see this function from current\n                      // directory, so we should clear it.\n\n                      function = octave_value ();\n\n                      clear_breakpoints = true;\n                    }\n                  else if (is_same_file)\n                    {\n                      // Same file.  If it is out of date, then reload it.\n\n                      sys::time ottp = fcn->time_parsed ();\n                      OCTAVE_TIME_T tp = ottp.unix_time ();\n\n                      fcn->mark_fcn_file_up_to_date (sys::time ());\n\n                      if (! (Vignore_function_time_stamp == 2\n                             || (Vignore_function_time_stamp\n                                 && fcn->is_system_fcn_file ())))\n                        {\n                          sys::file_stat fs (ff);\n\n                          if (fs)\n                            {\n                              if (fs.is_newer (tp))\n                                {\n                                  retval = load_out_of_date_fcn (ff, dir_name,\n                                                                 function,\n                                                                 dispatch_type,\n                                                                 pack);\n\n                                  clear_breakpoints = true;\n                                }\n                            }\n                          else\n                            {\n                              function = octave_value ();\n\n                              clear_breakpoints = true;\n                            }\n                        }\n                    }\n                  else\n                    {\n                      // Not the same file, so load the new file in\n                      // place of the old.\n\n                      retval = load_out_of_date_fcn (file, dir_name, function,\n                                                     dispatch_type, pack);\n\n                      clear_breakpoints = true;\n                    }\n\n                  // If the function has been replaced then clear any\n                  // breakpoints associated with it\n                  if (clear_breakpoints && is_user_code)\n                    {\n                      bp_table& bptab = __get_bp_table__ ();\n\n                      bptab.remove_all_breakpoints_from_function (canonical_nm,\n                                                                  true);\n                    }\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\noctave_value\nfcn_info::fcn_info_rep::find_scoped_function (const symbol_scope& search_scope)\n{\n  if (search_scope)\n    {\n      // Subfunction.\n\n      octave_value fcn = search_scope.find_subfunction (name);\n\n      if (fcn.is_defined ())\n        return fcn;\n\n      // Local function.\n\n      std::string fcn_file = search_scope.fcn_file_name ();\n\n      // For anonymous functions we look at the parent scope so that if\n      // they were defined within class methods and use local functions\n      // (helper functions) we can still use those anonymous functions\n\n      if (! fcn_file.empty ())\n        {\n          auto r = local_functions.find (fcn_file);\n\n          if (r != local_functions.end ())\n            {\n              // We shouldn't need an out-of-date check here since\n              // local functions may ultimately be called only from\n              // a primary function or method defined in the same\n              // file.\n\n              return r->second;\n            }\n        }\n\n      // Private function.\n\n      return find_private_function (search_scope.dir_name ());\n    }\n\n  return octave_value ();\n}\n\noctave_value\nfcn_info::fcn_info_rep::find_private_function (const std::string& dir_name)\n{\n  if (! dir_name.empty ())\n    {\n      auto q = private_functions.find (dir_name);\n\n      if (q == private_functions.end ())\n        {\n          octave_value val = load_private_function (dir_name);\n\n          if (val.is_defined ())\n            return val;\n        }\n      else\n        {\n          octave_value& fval = q->second;\n\n          if (fval.is_defined ())\n            out_of_date_check (fval, \"\", false);\n\n          if (fval.is_defined ())\n            return fval;\n          else\n            {\n              octave_value val = load_private_function (dir_name);\n\n              if (val.is_defined ())\n                return val;\n            }\n        }\n    }\n\n  return octave_value ();\n}\n\noctave_value\nfcn_info::fcn_info_rep::find_method (const octave_value_list& args)\n{\n  if (! args.empty ())\n    {\n      std::string dispatch_type = get_dispatch_type (args);\n\n      return find_method (dispatch_type);\n    }\n\n  return octave_value ();\n}\n\noctave_value\nfcn_info::fcn_info_rep::xfind (const symbol_scope& search_scope,\n                               const octave_value_list& args)\n{\n  // Subfunction, local function, or private function.\n\n  octave_value fcn;\n\n  fcn = find_scoped_function (search_scope);\n\n  if (fcn.is_defined ())\n    return fcn;\n\n  // Class methods.\n\n  fcn = find_method (args);\n\n  if (fcn.is_defined ())\n    return fcn;\n\n  // Class constructors.  The class name and function name are the same.\n\n  auto q = class_constructors.find (name);\n\n  if (q == class_constructors.end ())\n    {\n      octave_value val = load_class_constructor ();\n\n      if (val.is_defined ())\n        return val;\n    }\n  else\n    {\n      octave_value& fval = q->second;\n\n      if (fval.is_defined ())\n        out_of_date_check (fval, name);\n\n      if (fval.is_defined ())\n        return fval;\n      else\n        {\n          octave_value val = load_class_constructor ();\n\n          if (val.is_defined ())\n            return val;\n        }\n    }\n\n  // Command-line function.\n\n  if (cmdline_function.is_defined ())\n    return cmdline_function;\n\n  // Autoload?\n\n  fcn = find_autoload ();\n\n  if (fcn.is_defined ())\n    return fcn;\n\n  // Function on the path.\n\n  fcn = find_user_function ();\n\n  if (fcn.is_defined ())\n    return fcn;\n\n  // Package\n\n  fcn = find_package ();\n\n  if (fcn.is_defined ())\n    return fcn;\n\n  // Built-in function (might be undefined).\n\n  return built_in_function;\n}\n\n// Find the definition of NAME according to the following precedence\n// list:\n//\n//   built-in function\n//   function on the path\n//   autoload function\n//   command-line function\n//   private function\n//   subfunction\n\n// This function is used to implement the \"builtin\" function, which\n// searches for \"built-in\" functions.  In Matlab, \"builtin\" only\n// returns functions that are actually built-in to the interpreter.\n// But since the list of built-in functions is different in Octave and\n// Matlab, we also search up the precedence list until we find\n// something that matches.  Note that we are only searching by name,\n// so class methods and constructors are skipped.\n\noctave_value\nfcn_info::fcn_info_rep::builtin_find (const symbol_scope& scope)\n{\n  symbol_scope search_scope\n    = (scope\n       ? scope : __get_current_scope__ ());\n\n  octave_value retval = x_builtin_find (search_scope);\n\n  if (! retval.is_defined ())\n    {\n      // It is possible that the user created a file on the fly since\n      // the last prompt or chdir, so try updating the load path and\n      // searching again.\n\n      load_path& lp = __get_load_path__ ();\n\n      lp.update ();\n\n      retval = x_builtin_find (search_scope);\n    }\n\n  return retval;\n}\n\noctave_value\nfcn_info::fcn_info_rep::x_builtin_find (const symbol_scope& search_scope)\n{\n  // Built-in function.\n  if (built_in_function.is_defined ())\n    return built_in_function;\n\n  // Function on the path.\n\n  octave_value fcn = find_user_function ();\n\n  if (fcn.is_defined ())\n    return fcn;\n\n  // Autoload?\n\n  fcn = find_autoload ();\n\n  if (fcn.is_defined ())\n    return fcn;\n\n  // Command-line function.\n\n  if (cmdline_function.is_defined ())\n    return cmdline_function;\n\n  // Private function, local function, or subfunction.\n\n  if (search_scope)\n    {\n      // Private function.\n\n      std::string dir_name = search_scope.dir_name ();\n\n      if (! dir_name.empty ())\n        {\n          auto q = private_functions.find (dir_name);\n\n          if (q == private_functions.end ())\n            {\n              octave_value val = load_private_function (dir_name);\n\n              if (val.is_defined ())\n                return val;\n            }\n          else\n            {\n              octave_value& fval = q->second;\n\n              if (fval.is_defined ())\n                out_of_date_check (fval);\n\n              if (fval.is_defined ())\n                return fval;\n              else\n                {\n                  octave_value val = load_private_function (dir_name);\n\n                  if (val.is_defined ())\n                    return val;\n                }\n            }\n        }\n\n      // Local function.\n\n      std::string fcn_file = search_scope.fcn_file_name ();\n\n      if (! fcn_file.empty ())\n        {\n          auto r = local_functions.find (fcn_file);\n\n          if (r != local_functions.end ())\n            {\n              // We shouldn't need an out-of-date check here since local\n              // functions may ultimately be called only from a primary\n              // function or method defined in the same file.\n\n              return r->second;\n            }\n        }\n\n      // Subfunction.  I think it only makes sense to check for\n      // subfunctions if we are currently executing a function defined\n      // from a .m file.\n\n      octave_value val = search_scope.find_subfunction (name);\n\n      if (val.is_defined ())\n        return val;\n    }\n\n  return octave_value ();\n}\n\noctave_value\nfcn_info::fcn_info_rep::find_method (const std::string& dispatch_type)\n{\n  octave_value retval;\n\n  auto q = class_methods.find (dispatch_type);\n\n  if (q == class_methods.end ())\n    retval = load_class_method (dispatch_type);\n  else\n    {\n      retval = q->second;\n\n      if (retval.is_defined ())\n        out_of_date_check (retval, dispatch_type);\n\n      if (! retval.is_defined ())\n        retval = load_class_method (dispatch_type);\n    }\n\n  // Ignore any classdef constructors that were found by\n  // load_class_method above, either for dispatch_type or any\n  // superclasses of that class.\n\n  // FIXME: Maybe there is a better way of managing classdef\n  // constructors (which may actually be octave_classdef_meta objects)\n  // so they don't appear in both the class_methods and\n  // class_constructors maps?\n\n  if (retval.is_classdef_meta ())\n    {\n      octave_function *fcn = retval.function_value ();\n\n      if (fcn && fcn->is_classdef_constructor (dispatch_type))\n        retval = octave_value ();\n    }\n\n  return retval;\n}\n\noctave_value\nfcn_info::fcn_info_rep::find_autoload ()\n{\n  // Autoloaded function.\n\n  if (autoload_function.is_defined ())\n    out_of_date_check (autoload_function);\n\n  if (! autoload_function.is_defined ())\n    {\n      tree_evaluator& tw = __get_evaluator__ ();\n\n      std::string file_name = tw.lookup_autoload (name);\n\n      if (! file_name.empty ())\n        {\n          std::size_t pos = file_name.find_last_of (sys::file_ops::dir_sep_chars ());\n\n          std::string dir_name = file_name.substr (0, pos);\n\n          octave_value ov_fcn\n            = load_fcn_from_file (file_name, dir_name, \"\", \"\", name, true);\n\n          if (ov_fcn.is_defined ())\n            autoload_function = octave_value (ov_fcn);\n        }\n    }\n\n  return autoload_function;\n}\n\noctave_value\nfcn_info::fcn_info_rep::find_user_function ()\n{\n  // Function on the path.\n\n  if (function_on_path.is_defined ())\n    out_of_date_check (function_on_path);\n\n  if (function_on_path.is_undefined ())\n    {\n      std::string dir_name;\n\n      load_path& lp = __get_load_path__ ();\n\n\n      std::string file_name = lp.find_fcn (name, dir_name, package_name);\n\n      if (! file_name.empty ())\n        {\n          octave_value ov_fcn\n            = load_fcn_from_file (file_name, dir_name, \"\", package_name);\n\n          if (ov_fcn.is_defined ())\n            function_on_path = ov_fcn;\n        }\n    }\n\n  return function_on_path;\n}\n\noctave_value\nfcn_info::fcn_info_rep::find_package ()\n{\n  // FIXME: implement correct way to check out of date package\n  //if (package.is_defined ())\n  //  out_of_date_check (package);\n\n  if (package.is_undefined ())\n    {\n      cdef_manager& cdm = __get_cdef_manager__ ();\n\n      package = cdm.find_package_symbol (full_name ());\n    }\n\n  return package;\n}\n\nvoid\nfcn_info::fcn_info_rep::install_built_in_dispatch (const std::string& klass)\n{\n  if (built_in_function.is_defined ())\n    {\n      octave_function *fcn = built_in_function.function_value ();\n\n      if (fcn)\n        {\n          if (fcn->handles_dispatch_class (klass))\n            warning (\"install_built_in_dispatch: '%s' already defined for class '%s'\",\n                     name.c_str (), klass.c_str ());\n          else\n            fcn->push_dispatch_class (klass);\n        }\n    }\n  else\n    error (\"install_built_in_dispatch: '%s' is not a built-in function\",\n           name.c_str ());\n}\n\noctave_value\nfcn_info::fcn_info_rep::dump () const\n{\n  std::map<std::string, octave_value> m\n  = {{ \"name\", full_name () },\n    { \"package\", package.dump () },\n    { \"local_functions\", dump_function_map (local_functions) },\n    { \"private_functions\", dump_function_map (private_functions) },\n    { \"class_methods\", dump_function_map (class_methods) },\n    { \"class_constructors\", dump_function_map (class_constructors) },\n    { \"cmdline_function\", cmdline_function.dump () },\n    { \"autoload_function\", autoload_function.dump () },\n    { \"function_on_path\", function_on_path.dump () },\n    { \"built_in_function\", built_in_function.dump () }\n  };\n\n  return octave_value (m);\n}\n\noctave_value\ndump_function_map (const std::map<std::string, octave_value>& fcn_map)\n{\n  if (fcn_map.empty ())\n    return octave_value (Matrix ());\n\n  std::map<std::string, octave_value> info_map;\n\n  for (const auto& nm_fcn : fcn_map)\n    {\n      std::string nm = nm_fcn.first;\n      const octave_value& fcn = nm_fcn.second;\n      info_map[nm] = fcn.dump ();\n    }\n\n  return octave_value (info_map);\n}\n\nDEFUN (ignore_function_time_stamp, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} ignore_function_time_stamp ()\n@deftypefnx {} {@var{old_val} =} ignore_function_time_stamp (@var{new_val})\nQuery or set the internal variable that controls whether Octave checks\nthe time stamp on files each time it looks up functions defined in\nfunction files.\n\nIf the internal variable is set to @qcode{\"system\"}, Octave will not\nautomatically recompile function files in subdirectories of\n@file{@var{octave-home}/share/@var{version}/m} if they have changed since\nthey were last compiled, but will recompile other function files in the\nsearch path if they change.\n\nIf set to @qcode{\"all\"}, Octave will not recompile any function files\nunless their definitions are removed with @code{clear}.\n\nIf set to @qcode{\"none\"}, Octave will always check time stamps on files\nto determine whether functions defined in function files need to\nrecompiled.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargout > 0 || nargin == 0)\n    {\n      switch (Vignore_function_time_stamp)\n        {\n        case 1:\n          retval = \"system\";\n          break;\n\n        case 2:\n          retval = \"all\";\n          break;\n\n        default:\n          retval = \"none\";\n          break;\n        }\n    }\n\n  if (nargin == 1)\n    {\n      std::string sval = args(0).xstring_value (\"ignore_function_time_stamp: first argument must be a string\");\n\n      if (sval == \"all\")\n        Vignore_function_time_stamp = 2;\n      else if (sval == \"system\")\n        Vignore_function_time_stamp = 1;\n      else if (sval == \"none\")\n        Vignore_function_time_stamp = 0;\n      else\n        error (R\"(ignore_function_time_stamp: argument must be one of \"all\", \"system\", or \"none\")\");\n    }\n\n  return retval;\n}\n\n/*\n%!shared old_state\n%! old_state = ignore_function_time_stamp ();\n%!test\n%! state = ignore_function_time_stamp (\"all\");\n%! assert (state, old_state);\n%! assert (ignore_function_time_stamp (), \"all\");\n%! state = ignore_function_time_stamp (\"system\");\n%! assert (state, \"all\");\n%! assert (ignore_function_time_stamp (), \"system\");\n%! ignore_function_time_stamp (old_state);\n\n## Test input validation\n%!error ignore_function_time_stamp (\"all\", \"all\")\n%!error ignore_function_time_stamp (\"UNKNOWN_VALUE\")\n%!error ignore_function_time_stamp (42)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/fcn-info.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fcn_info_h)\n#define octave_fcn_info_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <map>\n#include <memory>\n#include <string>\n\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"symscope.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass fcn_info\n{\npublic:\n\n  typedef std::map<std::string, octave_value>::const_iterator\n    str_val_const_iterator;\n  typedef std::map<std::string, octave_value>::iterator str_val_iterator;\n\nprivate:\n\n  class fcn_info_rep\n  {\n  public:\n\n    fcn_info_rep (const std::string& nm)\n      : name (nm), package_name (), local_functions (),\n        private_functions (), class_constructors (), class_methods (),\n        cmdline_function (), autoload_function (), function_on_path (),\n        built_in_function ()\n    {\n      std::size_t pos = name.rfind ('.');\n\n      if (pos != std::string::npos)\n        {\n          package_name = name.substr (0, pos);\n          name = name.substr (pos+1);\n        }\n    }\n\n    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (fcn_info_rep)\n\n    ~fcn_info_rep () = default;\n\n    octave_value install_local_function (const std::string& file_name);\n\n    octave_value load_private_function (const std::string& dir_name);\n\n    octave_value load_class_constructor ();\n\n    octave_value load_class_method (const std::string& dispatch_type);\n\n    octave_value find (const symbol_scope& search_scope,\n                       const octave_value_list& args);\n\n    octave_value builtin_find (const symbol_scope& search_scope);\n\n    octave_value find_scoped_function (const symbol_scope& search_scope);\n\n    octave_value find_private_function (const std::string& dir_name);\n\n    octave_value find_method (const std::string& dispatch_type);\n\n    octave_value find_method (const octave_value_list& args);\n\n    octave_value find_autoload ();\n\n    octave_value find_package ();\n\n    octave_value find_user_function ();\n\n    bool is_user_function_defined () const\n    {\n      return function_on_path.is_defined ();\n    }\n\n    octave_value find_function (const symbol_scope& search_scope,\n                                const octave_value_list& args)\n    {\n      return find (search_scope, args);\n    }\n\n    void install_cmdline_function (const octave_value& f)\n    {\n      cmdline_function = f;\n    }\n\n    void install_local_function (const octave_value& f,\n                                 const std::string& file_name)\n    {\n      local_functions[file_name] = f;\n    }\n\n    void install_user_function (const octave_value& f)\n    {\n      function_on_path = f;\n    }\n\n    void install_built_in_function (const octave_value& f)\n    {\n      built_in_function = f;\n    }\n\n    void install_built_in_dispatch (const std::string& klass);\n\n    template <typename T>\n    void\n    clear_map (std::map<T, octave_value>& map, bool force = false)\n    {\n      auto p = map.begin ();\n\n      while (p != map.end ())\n        {\n          if (force || ! p->second.islocked ())\n            map.erase (p++);\n          else\n            p++;\n        }\n    }\n\n    void clear_autoload_function (bool force = false)\n    {\n      if (force || ! autoload_function.islocked ())\n        autoload_function = octave_value ();\n    }\n\n    // We also clear command line functions here, as these are both\n    // \"user defined\"\n    void clear_user_function (bool force = false)\n    {\n      clear_autoload_function (force);\n\n      if (force || ! function_on_path.islocked ())\n        function_on_path = octave_value ();\n\n      if (force || ! cmdline_function.islocked ())\n        cmdline_function = octave_value ();\n    }\n\n    void clear_mex_function ()\n    {\n      if (function_on_path.is_mex_function ())\n        clear_user_function ();\n    }\n\n    void clear_package ()\n    {\n      package = octave_value ();\n    }\n\n    void clear (bool force = false)\n    {\n      clear_map (local_functions, force);\n      clear_map (private_functions, force);\n      clear_map (class_constructors, force);\n      clear_map (class_methods, force);\n\n      clear_autoload_function (force);\n      clear_user_function (force);\n      clear_package ();\n    }\n\n    octave_value dump () const;\n\n    std::string full_name () const\n    {\n      if (package_name.empty ())\n        return name;\n      else\n        return package_name + '.' + name;\n    }\n\n    std::string name;\n\n    std::string package_name;\n\n    // File name to function object.\n    std::map<std::string, octave_value> local_functions;\n\n    // Directory name to function object.\n    std::map<std::string, octave_value> private_functions;\n\n    // Class name to function object.\n    std::map<std::string, octave_value> class_constructors;\n\n    // Dispatch type to function object.\n    std::map<std::string, octave_value> class_methods;\n\n    octave_value cmdline_function;\n\n    octave_value autoload_function;\n\n    octave_value function_on_path;\n\n    octave_value package;\n\n    octave_value built_in_function;\n\n  private:\n\n    octave_value xfind (const symbol_scope& search_scope,\n                        const octave_value_list& args);\n\n    octave_value x_builtin_find (const symbol_scope& search_scope);\n  };\n\npublic:\n\n  fcn_info (const std::string& nm = \"\")\n    : m_rep (new fcn_info_rep (nm)) { }\n\n  fcn_info (const fcn_info&) = default;\n\n  fcn_info& operator = (const fcn_info&) = default;\n\n  ~fcn_info () = default;\n\n  octave_value find (const symbol_scope& search_scope,\n                     const octave_value_list& args = octave_value_list ())\n  {\n    return m_rep->find (search_scope, args);\n  }\n\n  octave_value\n  builtin_find (const symbol_scope& search_scope)\n  {\n    return m_rep->builtin_find (search_scope);\n  }\n\n  octave_value find_scoped_function (const symbol_scope& search_scope) const\n  {\n    return m_rep->find_scoped_function (search_scope);\n  }\n\n  octave_value find_private_function (const std::string& dir_name) const\n  {\n    return m_rep->find_private_function (dir_name);\n  }\n\n  octave_value find_method (const std::string& dispatch_type) const\n  {\n    return m_rep->find_method (dispatch_type);\n  }\n\n  octave_value find_built_in_function () const\n  {\n    return m_rep->built_in_function;\n  }\n\n  octave_value find_cmdline_function () const\n  {\n    return m_rep->cmdline_function;\n  }\n\n  octave_value find_autoload ()\n  {\n    return m_rep->find_autoload ();\n  }\n\n  // FIXME: find_function_on_path might be a better name?\n  octave_value find_user_function ()\n  {\n    return m_rep->find_user_function ();\n  }\n\n  bool is_user_function_defined () const\n  {\n    return m_rep->is_user_function_defined ();\n  }\n\n  octave_value\n  find_function (const symbol_scope& search_scope,\n                 const octave_value_list& args = octave_value_list ())\n  {\n    return m_rep->find_function (search_scope, args);\n  }\n\n  void install_cmdline_function (const octave_value& f)\n  {\n    m_rep->install_cmdline_function (f);\n  }\n\n  void install_local_function (const octave_value& f,\n                               const std::string& file_name)\n  {\n    m_rep->install_local_function (f, file_name);\n  }\n\n  void install_user_function (const octave_value& f)\n  {\n    m_rep->install_user_function (f);\n  }\n\n  void install_built_in_function (const octave_value& f)\n  {\n    m_rep->install_built_in_function (f);\n  }\n\n  void install_built_in_dispatch (const std::string& klass)\n  {\n    m_rep->install_built_in_dispatch (klass);\n  }\n\n  void clear (bool force = false) { m_rep->clear (force); }\n\n  void clear_user_function (bool force = false)\n  {\n    m_rep->clear_user_function (force);\n  }\n\n  void clear_autoload_function (bool force = false)\n  {\n    m_rep->clear_autoload_function (force);\n  }\n\n  void clear_mex_function () { m_rep->clear_mex_function (); }\n\n  octave_value dump () const { return m_rep->dump (); }\n\nprivate:\n\n  std::shared_ptr<fcn_info_rep> m_rep;\n};\n\nextern OCTINTERP_API std::string\nget_dispatch_type (const octave_value_list& args);\n\nextern OCTINTERP_API std::string\nget_dispatch_type (const octave_value_list& args,\n                   builtin_type_t& builtin_type);\n\nextern octave_value\ndump_function_map (const std::map<std::string, octave_value>& fcn_map);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/file-io.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Originally written by John C. Campbell <jcc@bevo.che.wisc.edu>\n//\n// Thomas Baier <baier@ci.tuwien.ac.at> added the original versions of\n// the following functions:\n//\n//   popen\n//   pclose\n//   execute       (now popen2.m)\n//   sync_system   (now merged with system)\n//   async_system  (now merged with system)\n\n// Extensively revised by John W. Eaton <jwe@octave.org>,\n// April 1996.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n#include <cstdio>\n\n#include <iomanip>\n#include <string>\n\n#if defined (HAVE_ZLIB_H)\n#  include <zlib.h>\n#endif\n\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"iconv-wrappers.h\"\n#include \"lo-ieee.h\"\n#include \"localcharset-wrapper.h\"\n#include \"mkostemp-wrapper.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sysdep.h\"\n#include \"unistd-wrappers.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"oct-fstrm.h\"\n#include \"oct-iostrm.h\"\n#include \"oct-map.h\"\n#include \"oct-prcstrm.h\"\n#include \"oct-stream.h\"\n#include \"oct-strstrm.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"sysdep.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic void\nnormalize_fopen_mode (std::string& mode, bool& use_zlib)\n{\n  use_zlib = false;\n\n  if (! mode.empty ())\n    {\n      // Matlab uses 'A' and 'W' to indicate that buffered writing should\n      // take place.  Octave already does that.  Theoretically, we should\n      // warn about using 'a', 'r', or 'w' because Octave does not enable\n      // automatic flushing with these modes.  The performance hit is ~4X\n      // when using automatic flushing and seems completely unnecessary.\n      // See bug #52644.\n\n      std::size_t pos = mode.find ('W');\n\n      if (pos != std::string::npos)\n        mode[pos] = 'w';\n\n      pos = mode.find ('R');\n\n      if (pos != std::string::npos)\n        mode[pos] = 'r';\n\n      pos = mode.find ('A');\n\n      if (pos != std::string::npos)\n        mode[pos] = 'a';\n\n      pos = mode.find ('z');\n\n      if (pos != std::string::npos)\n        {\n#if defined (HAVE_ZLIB)\n          use_zlib = true;\n          mode.erase (pos, 1);\n#else\n          err_disabled_feature (\"\", \"gzipped files (zlib)\");\n#endif\n        }\n\n      // Use binary mode if 't' is not specified, but don't add\n      // 'b' if it is already present.\n\n      std::size_t bpos = mode.find ('b');\n      std::size_t tpos = mode.find ('t');\n\n      if (bpos == std::string::npos && tpos == std::string::npos)\n        mode += 'b';\n    }\n}\n\nstatic std::ios::openmode\nfopen_mode_to_ios_mode (const std::string& mode)\n{\n  std::ios::openmode retval = std::ios::in;\n\n  if (mode == \"rt\")\n    retval = std::ios::in;\n  else if (mode == \"wt\")\n    retval = std::ios::out | std::ios::trunc;\n  else if (mode == \"at\")\n    retval = std::ios::out | std::ios::app;\n  else if (mode == \"r+t\" || mode == \"rt+\")\n    retval = std::ios::in | std::ios::out;\n  else if (mode == \"w+t\" || mode == \"wt+\")\n    retval = std::ios::in | std::ios::out | std::ios::trunc;\n  else if (mode == \"a+t\" || mode == \"at+\")\n    retval = std::ios::in | std::ios::out | std::ios::app;\n  else if (mode == \"rb\" || mode == \"r\")\n    retval = std::ios::in | std::ios::binary;\n  else if (mode == \"wb\" || mode == \"w\")\n    retval = std::ios::out | std::ios::trunc | std::ios::binary;\n  else if (mode == \"ab\" || mode == \"a\")\n    retval = std::ios::out | std::ios::app | std::ios::binary;\n  else if (mode == \"r+b\" || mode == \"rb+\" || mode == \"r+\")\n    retval = std::ios::in | std::ios::out | std::ios::binary;\n  else if (mode == \"w+b\" || mode == \"wb+\" || mode == \"w+\")\n    retval = (std::ios::in | std::ios::out | std::ios::trunc\n              | std::ios::binary);\n  else if (mode == \"a+b\" || mode == \"ab+\" || mode == \"a+\")\n    retval = (std::ios::in | std::ios::out | std::ios::app\n              | std::ios::binary);\n  else\n    error (\"invalid mode specified\");\n\n  return retval;\n}\n\nDEFMETHOD (fclose, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{status} =} fclose (@var{fid})\n@deftypefnx {} {@var{status} =} fclose (\"all\")\nClose the file specified by the file descriptor @var{fid}.\n\nIf successful, @code{fclose} returns 0, otherwise, it returns -1.  The\nsecond form of the @code{fclose} call closes all open files except\n@code{stdin}, @code{stdout}, @code{stderr}, and any FIDs associated\nwith gnuplot.\n@seealso{fopen, fflush, freport}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  return ovl (streams.remove (args(0), \"fclose\"));\n}\n\nDEFMETHOD (fclear, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} fclear (@var{fid})\nClear the stream state for the file specified by the file descriptor\n@var{fid}.\n@seealso{ferror, fopen}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  int fid = streams.get_file_number (args(0));\n\n  stream os = streams.lookup (fid, \"fclear\");\n\n  os.clearerr ();\n\n  return ovl ();\n}\n\nDEFMETHOD (fflush, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} fflush (@var{fid})\nFlush output to file descriptor @var{fid}.\n\n@code{fflush} returns 0 on success and an OS dependent error value\n(@minus{}1 on Unix) on error.\n\nProgramming Note: Flushing is useful for ensuring that all pending output\nmakes it to the screen before some other event occurs.  For example, it is\nalways a good idea to flush the standard output stream before calling\n@code{input}.\n@seealso{fopen, fclose}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value retval = -1;\n\n  stream_list& streams = interp.get_stream_list ();\n\n  // FIXME: any way to avoid special case for stdout?\n  int fid = streams.get_file_number (args(0));\n\n  if (fid == 1)\n    {\n      flush_stdout ();\n\n      retval = 0;\n    }\n  else\n    {\n      stream os = streams.lookup (fid, \"fflush\");\n\n      retval = os.flush ();\n    }\n\n  return retval;\n}\n\nDEFMETHOD (fgetl, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{str} =} fgetl (@var{fid})\n@deftypefnx {} {@var{str} =} fgetl (@var{fid}, @var{len})\nRead characters from a file, stopping after a newline, or EOF,\nor @var{len} characters have been read.\n\nThe characters read, excluding the possible trailing newline, are returned\nas a string.\n\nIf @var{len} is omitted, @code{fgetl} reads until the next newline\ncharacter.\n\nIf there are no more characters to read, @code{fgetl} returns @minus{}1.\n\nTo read a line and return the terminating newline,\n@pxref{XREFfgets,,@code{fgets}}.\n@seealso{fgets, fscanf, fread, fopen}\n@end deftypefn */)\n{\n  static const std::string who = \"fgetl\";\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), who);\n\n  octave_value len_arg = (nargin == 2) ? args(1) : octave_value ();\n\n  bool err = false;\n\n  std::string tmp = os.getl (len_arg, err, who);\n\n  if (! err)\n    return ovl (tmp, tmp.length ());\n  else\n    return ovl (-1, 0);\n}\n\nDEFMETHOD (fgets, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{str} =} fgets (@var{fid})\n@deftypefnx {} {@var{str} =} fgets (@var{fid}, @var{len})\nRead characters from a file, stopping after a newline, or EOF,\nor @var{len} characters have been read.\n\nThe characters read, including the possible trailing newline, are returned\nas a string.\n\nIf @var{len} is omitted, @code{fgets} reads until the next newline\ncharacter.\n\nIf there are no more characters to read, @code{fgets} returns @minus{}1.\n\nTo read a line and discard the terminating newline,\n@pxref{XREFfgetl,,@code{fgetl}}.\n@seealso{fputs, fgetl, fscanf, fread, fopen}\n@end deftypefn */)\n{\n  static const std::string who = \"fgets\";\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), who);\n\n  octave_value len_arg = (nargin == 2) ? args(1) : octave_value ();\n\n  bool err = false;\n\n  std::string tmp = os.gets (len_arg, err, who);\n\n  if (! err)\n    return ovl (tmp, tmp.length ());\n  else\n    return ovl (-1.0, 0.0);\n}\n\nDEFMETHOD (fskipl, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{nlines} =} fskipl (@var{fid})\n@deftypefnx {} {@var{nlines} =} fskipl (@var{fid}, @var{count})\n@deftypefnx {} {@var{nlines} =} fskipl (@var{fid}, Inf)\nRead and skip @var{count} lines from the file specified by the file\ndescriptor @var{fid}.\n\n@code{fskipl} discards characters until an end-of-line is encountered\nexactly @var{count}-times, or until the end-of-file marker is found.\n\nIf @var{count} is omitted, it defaults to 1.  @var{count} may also be\n@code{Inf}, in which case lines are skipped until the end of the file.\nThis form is suitable for counting the number of lines in a file.\n\nReturns the number of lines skipped (end-of-line sequences encountered).\n@seealso{fgetl, fgets, fscanf, fopen}\n@end deftypefn */)\n{\n  static const std::string who = \"fskipl\";\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), who);\n\n  octave_value count_arg = (nargin == 2) ? args(1) : octave_value ();\n\n  bool err = false;\n\n  off_t tmp = os.skipl (count_arg, err, who);\n\n  if (! err)\n    return ovl (tmp);\n  else\n    return ovl ();\n}\n\nstatic stream\ndo_stream_open (const std::string& name, const std::string& mode_arg,\n                const std::string& arch, std::string encoding, int& fid)\n{\n  stream retval;\n\n  fid = -1;\n\n  if (encoding.compare (\"utf-8\"))\n    {\n      // check if encoding is valid\n      void *codec = octave_iconv_open_wrapper (encoding.c_str (), \"utf-8\");\n      if (codec == reinterpret_cast<void *> (-1))\n        {\n          if (errno == EINVAL)\n            error (\"fopen: conversion from codepage '%s' not supported\",\n                   encoding.c_str ());\n        }\n      else\n        octave_iconv_close_wrapper (codec);\n    }\n\n  std::string mode = mode_arg;\n  bool use_zlib = false;\n  normalize_fopen_mode (mode, use_zlib);\n\n  std::ios::openmode md = fopen_mode_to_ios_mode (mode);\n\n  mach_info::float_format flt_fmt\n    = mach_info::string_to_float_format (arch);\n\n  std::string fname = sys::file_ops::tilde_expand (name);\n\n  bool is_dir = sys::dir_exists (fname);\n\n  if (! (md & std::ios::out))\n    fname = find_data_file_in_load_path (\"fopen\", fname);\n\n  if (! is_dir)\n    {\n#if defined (HAVE_ZLIB)\n      if (use_zlib)\n        {\n          FILE *fptr = sys::fopen (fname.c_str (), mode.c_str ());\n\n          if (fptr)\n            {\n              int fd = fileno (fptr);\n\n              gzFile gzf = ::gzdopen (fd, mode.c_str ());\n\n              retval = zstdiostream::create (fname, gzf, fd, md, flt_fmt,\n                                             encoding);\n            }\n          else\n            retval.error (std::strerror (errno));\n        }\n      else\n#endif\n        {\n          FILE *fptr = sys::fopen (fname, mode);\n\n          retval = stdiostream::create (fname, fptr, md, flt_fmt, encoding);\n\n          if (! fptr)\n            retval.error (std::strerror (errno));\n        }\n\n    }\n\n  return retval;\n}\n\nstatic stream\ndo_stream_open (const octave_value& tc_name, const octave_value& tc_mode,\n                const octave_value& tc_arch, const octave_value& tc_encoding,\n                const char *fcn, int& fid)\n{\n  stream retval;\n\n  fid = -1;\n\n  std::string name = tc_name.xstring_value (\"%s: filename must be a string\", fcn);\n  std::string mode = tc_mode.xstring_value (\"%s: file mode must be a string\", fcn);\n  std::string arch = tc_arch.xstring_value (\"%s: architecture type must be a string\", fcn);\n  std::string encoding = tc_encoding.xstring_value (\"%s: ENCODING must be a string\", fcn);\n\n  // Valid names for encodings consist of ASCII characters only.\n  std::transform (encoding.begin (), encoding.end (), encoding.begin (),\n                  ::tolower);\n\n  if (encoding == \"system\")\n    {\n      encoding = octave_locale_charset_wrapper ();\n      std::transform (encoding.begin (), encoding.end (), encoding.begin (),\n                      ::tolower);\n    }\n\n#if defined (OCTAVE_HAVE_STRICT_ENCODING_FACET)\n  if (encoding != \"utf-8\")\n    {\n      warning_with_id (\"Octave:fopen:encoding-unsupported\",\n                       \"fopen: encoding must be 'UTF-8' for this configuration \"\n                       \"of Octave.  Opening file '%s' as 'UTF-8' even though \"\n                       \"encoding was specified as '%s'.\",\n                       name.c_str (), encoding.c_str ());\n      encoding = \"utf-8\";\n    }\n#endif\n\n  retval = do_stream_open (name, mode, arch, encoding, fid);\n\n  return retval;\n}\n\nDEFMETHOD (fopen, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{fid} =} fopen (@var{name})\n@deftypefnx {} {@var{fid} =} fopen (@var{name}, @var{mode})\n@deftypefnx {} {@var{fid} =} fopen (@var{name}, @var{mode}, @var{arch})\n@deftypefnx {} {@var{fid} =} fopen (@var{name}, @var{mode}, @var{arch}, @var{encoding})\n@deftypefnx {} {[@var{fid}, @var{msg}] =} fopen (@dots{})\n@deftypefnx {} {@var{fid_list} =} fopen (\"all\")\n@deftypefnx {} {[@var{file}, @var{mode}, @var{arch}, @var{encoding}] =} fopen (@var{fid})\nOpen a file for low-level I/O or query open files and file descriptors.\n\nThe first form of the @code{fopen} function opens the named file with\nthe specified mode (read-write, read-only, etc.@:), architecture\ninterpretation (IEEE big endian, IEEE little endian, etc.@:) and file encoding,\nand returns an integer value that may be used to refer to the file later.  If\nan error occurs, @var{fid} is set to @minus{}1 and @var{msg} contains the\ncorresponding system error message.  The @var{mode} is a one or two\ncharacter string that specifies whether the file is to be opened for\nreading, writing, or both.  The @var{encoding} is a character string with a\nvalid encoding identifier.  This encoding is used when strings are read from\nor written to the file.  By default, that is UTF-8.\n\nThe second form of the @code{fopen} function returns a vector of file ids\ncorresponding to all the currently open files, excluding the\n@code{stdin}, @code{stdout}, and @code{stderr} streams.\n\nThe third form of the @code{fopen} function returns information about the\nopen file given its file id.\n\nFor example,\n\n@example\nmyfile = fopen (\"splat.dat\", \"r\", \"ieee-le\");\n@end example\n\n@noindent\nopens the file @file{splat.dat} for reading.  If necessary, binary\nnumeric values will be read assuming they are stored in IEEE@tie{}754 format\nwith the least significant bit first, and then converted to the native\nrepresentation.\n\nOpening a file that is already open simply opens it again and returns a\nseparate file id.  It is not an error to open a file several times,\nthough writing to the same file through several different file ids may\nproduce unexpected results.\n\nThe possible values of @var{mode} are\n\n@table @asis\n@item @samp{r} (default)\nOpen a file for reading.\n\n@item @samp{w}\nOpen a file for writing.  The previous contents are discarded.\n\n@item @samp{a}\nOpen or create a file for writing at the end of the file.\n\n@item @samp{r+}\nOpen an existing file for reading and writing.\n\n@item @samp{w+}\nOpen a file for reading or writing.  The previous contents are\ndiscarded.\n\n@item @samp{a+}\nOpen or create a file for reading or writing at the end of the\nfile.\n@end table\n\nAppend a @qcode{\"t\"} to the mode string to open the file in text mode or a\n@qcode{\"b\"} to open in binary mode.  On Windows systems,\ntext mode reading and writing automatically converts linefeeds to the\nappropriate line end character for the system (carriage-return linefeed on\nWindows).  The default when no mode is specified is binary.\n\nAdditionally, you may append a @qcode{\"z\"} to the mode string to open a\ngzipped file for reading or writing.  For this to be successful, you\nmust also open the file in binary mode.\n\nThe parameter @var{arch} is a string specifying the default data format\nfor the file.  Valid values for @var{arch} are:\n\n@table @asis\n@item @qcode{\"native\"} or @qcode{\"n\"} (default)\nThe format of the current machine.\n\n@item @qcode{\"ieee-be\"} or @qcode{\"b\"}\nIEEE big endian format.\n\n@item @qcode{\"ieee-le\"} or @qcode{\"l\"}\nIEEE little endian format.\n@end table\n\nWhen opening a new file that does not yet exist, permissions will be set to\n@code{0666 - @var{umask}}.\n\nCompatibility Note: Octave opens files using buffered I/O.  Small writes are\naccumulated until an internal buffer is filled, and then everything is written\nin a single operation.  This is very efficient and improves performance.\n@sc{matlab}, however, opens files using flushed I/O where every write operation\nis immediately performed.  If the write operation must be performed immediately\nafter data has been written then the write should be followed by a call to\n@code{fflush} to flush the internal buffer.\n@seealso{fclose, fgets, fgetl, fscanf, fread, fputs, fdisp, fprintf, fwrite,\nfskipl, fseek, frewind, ftell, feof, ferror, fclear, fflush, freport, umask}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 4)\n    print_usage ();\n\n  octave_value_list retval = ovl (-1.0);\n\n  stream_list& streams = interp.get_stream_list ();\n\n  if (nargin == 1)\n    {\n      if (args(0).is_string ())\n        {\n          // If there is only one argument and it is a string but it\n          // is not the string \"all\", we assume it is a file to open\n          // with MODE = \"r\".  To open a file called \"all\", you have\n          // to supply more than one argument.\n          if (nargout < 2 && args(0).string_value () == \"all\")\n            return streams.open_file_numbers ();\n        }\n      else\n        {\n          string_vector tmp = streams.get_info (args(0));\n\n          retval = ovl (tmp(0), tmp(1), tmp(2), tmp(3));\n\n          return retval;\n        }\n    }\n\n  octave_value mode = (nargin > 1) ? args(1) : octave_value (\"r\");\n\n  octave_value arch = (nargin > 2) ? args(2) : octave_value (\"native\");\n\n  octave_value encoding = (nargin > 3) ? args(3) : octave_value (\"utf-8\");\n\n  int fid = -1;\n\n  stream os = do_stream_open (args(0), mode, arch, encoding, \"fopen\",\n                              fid);\n\n  if (os)\n    retval = ovl (streams.insert (os), \"\");\n  else\n    {\n      int error_number = 0;\n\n      retval = ovl (-1.0, os.error (false, error_number));\n    }\n\n  return retval;\n}\n\n/*\n## Further tests are in io.tst\n%!test   # Uses hardcoded value of 1 for stdout\n%! [name, mode, arch, encoding] = fopen (1);\n%! assert (name, \"stdout\");\n%! assert (mode, \"w\");\n%! assert (encoding, \"utf-8\");\n\n%!test   # Query of non-existent stream returns all \"\"\n%! [name, mode, arch] = fopen (-1);\n%! assert (name, \"\");\n%! assert (mode, \"\");\n%! assert (arch, \"\");\n\n## FIXME: should be conditional on OCTAVE_HAVE_STRICT_ENCODING_FACET\n%!testif HAVE_LLVM_LIBCXX\n%! fname = tempname ();\n%! unwind_protect\n%!   fail (\"fid = fopen (fname, 'wb', 'n', 'Windows-1252')\", ...\n%!         \"warning\", \"encoding must be 'UTF-8'\");\n%!   [name, mode, arch, encoding] = fopen (fid);\n%!   assert (name, fname);\n%!   assert (mode, \"wb\");\n%!   assert (encoding, \"utf-8\");  # fallback after warning\n%! unwind_protect_cleanup\n%!   fclose (fid);\n%!   unlink (fname);\n%! end_unwind_protect\n*/\n\nDEFMETHOD (freport, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} freport ()\nPrint a list of which files have been opened, and whether they are open\nfor reading, writing, or both.\n\nFor example:\n\n@example\n@group\nfreport ()\n\n     @print{}  number  mode  arch       name\n     @print{}  ------  ----  ----       ----\n     @print{}     0     r    ieee-le    stdin\n     @print{}     1     w    ieee-le    stdout\n     @print{}     2     w    ieee-le    stderr\n     @print{}     3     r    ieee-le    myfile\n@end group\n@end example\n@seealso{fopen, fclose, is_valid_file_id}\n@end deftypefn */)\n{\n  if (args.length () > 0)\n    warning (\"freport: ignoring extra arguments\");\n\n  stream_list& streams = interp.get_stream_list ();\n\n  octave_stdout << streams.list_open_files ();\n\n  return ovl ();\n}\n\nDEFMETHOD (frewind, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} frewind (@var{fid})\n@deftypefnx {} {@var{status} =} frewind (@var{fid})\nMove the file pointer to the beginning of the file specified by file\ndescriptor @var{fid}.\n\nIf an output @var{status} is requested then @code{frewind} returns 0 for\nsuccess, and -1 if an error is encountered.\n\nProgramming Note: @code{frewind} is equivalent to\n@code{fseek (@var{fid}, 0, SEEK_SET)}.\n@seealso{fseek, ftell, fopen}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int result = -1;\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), \"frewind\");\n\n  result = os.rewind ();\n\n  if (nargout > 0)\n    return ovl (result);\n  else\n    return ovl ();\n}\n\nDEFMETHOD (fseek, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{status} =} fseek (@var{fid}, @var{offset})\n@deftypefnx {} {@var{status} =} fseek (@var{fid}, @var{offset}, @var{origin})\nSet the file pointer to the location @var{offset} within the file @var{fid}.\n\nThe pointer is positioned @var{offset} characters from the @var{origin}, which\nmay be one of the predefined variables @w{@qcode{SEEK_SET}}@ (beginning),\n@w{@qcode{SEEK_CUR}}@ (current position), or @w{@qcode{SEEK_END}}@ (end of file)\nor strings @nospell{@qcode{\"bof\"}}, @nospell{@qcode{\"cof\"}}, or\n@nospell{@qcode{\"eof\"}}.  If @var{origin} is omitted, @w{@qcode{SEEK_SET}}@ is\nassumed.  @var{offset} may be positive, negative, or zero but not all\ncombinations of @var{origin} and @var{offset} can be realized.\n\n@code{fseek} returns 0 on success and -1 on error.\n@seealso{fskipl, frewind, ftell, fopen, SEEK_SET, SEEK_CUR, SEEK_END}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), \"fseek\");\n\n  octave_value origin_arg = (nargin == 3) ? args(2) : octave_value (-1.0);\n\n  return ovl (os.seek (args(1), origin_arg));\n}\n\nDEFMETHOD (ftell, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{pos} =} ftell (@var{fid})\nReturn the position of the file pointer as the number of characters from the\nbeginning of the file specified by file descriptor @var{fid}.\n@seealso{fseek, frewind, feof, fopen}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), \"ftell\");\n\n  return ovl (os.tell ());\n}\n\nstatic octave_value_list\nprintf_internal (interpreter& interp, const std::string& who,\n                 const octave_value_list& args, int nargout)\n{\n  int nargin = args.length ();\n\n  if (! (nargin > 1 || (nargin > 0 && args(0).is_string ())))\n    print_usage ();\n\n  int result;\n\n  stream os;\n  int fmt_n = 0;\n\n  stream_list& streams = interp.get_stream_list ();\n\n  if (args(0).is_string ())\n    os = streams.lookup (1, who);\n  else\n    {\n      fmt_n = 1;\n      os = streams.lookup (args(0), who);\n    }\n\n  if (! args(fmt_n).is_string ())\n    error (\"%s: format TEMPLATE must be a string\", who.c_str ());\n\n  octave_value_list tmp_args;\n\n  if (nargin > 1 + fmt_n)\n    {\n      tmp_args.resize (nargin-fmt_n-1, octave_value ());\n\n      for (int i = fmt_n + 1; i < nargin; i++)\n        tmp_args(i-fmt_n-1) = args(i);\n    }\n\n  result = os.printf (args(fmt_n), tmp_args, who);\n\n  if (nargout > 0)\n    return ovl (result);\n  else\n    return ovl ();\n}\n\nDEFMETHOD (fprintf, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} fprintf (@var{fid}, @var{template}, @dots{})\n@deftypefnx {} {} fprintf (@var{template}, @dots{})\n@deftypefnx {} {@var{numbytes} =} fprintf (@dots{})\nThis function is equivalent to @code{printf}, except that the output is\nwritten to the file descriptor @var{fid} instead of @code{stdout}.\n\nIf @var{fid} is omitted, the output is written to @code{stdout} making the\nfunction exactly equivalent to @code{printf}.\n\nThe optional output @var{numbytes} returns the number of bytes written to the\nfile.\n\nImplementation Note: For compatibility with @sc{matlab}, escape sequences in\nthe template string (e.g., @qcode{\"@backslashchar{}n\"} => newline) are\nexpanded even when the template string is defined with single quotes.\n@seealso{fputs, fdisp, fwrite, fscanf, printf, sprintf, fopen}\n@end deftypefn */)\n{\n  static const std::string who = \"fprintf\";\n\n  return printf_internal (interp, who, args, nargout);\n}\n\nDEFMETHOD (printf, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} printf (@var{template}, @dots{})\n@deftypefnx {} {@var{numbytes} =} printf (@dots{})\nPrint optional arguments under the control of the template string\n@var{template} to the stream @code{stdout} and return the number of characters\nprinted.\n@ifclear OCTAVE_MANUAL\n\nSee the Formatted Output section of the GNU Octave manual for a complete\ndescription of the syntax of the template string.\n@end ifclear\n\nThe optional output @var{numbytes} returns the number of bytes printed.\n\nImplementation Note: For compatibility with @sc{matlab}, escape sequences in\nthe template string (e.g., @qcode{\"@backslashchar{}n\"} => newline) are\nexpanded even when the template string is defined with single quotes.\n@seealso{fprintf, sprintf, scanf}\n@end deftypefn */)\n{\n  static const std::string who = \"printf\";\n\n  octave_value_list tmp_args = args;\n\n  return printf_internal (interp, who, tmp_args.prepend (octave_value (1)),\n                          nargout);\n}\n\nstatic octave_value_list\nputs_internal (interpreter& interp, const std::string& who,\n               const octave_value_list& args)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), who);\n\n  return ovl (- (os.puts (args(1), who) < 0));\n}\n\nDEFMETHOD (fputs, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} fputs (@var{fid}, @var{string})\nWrite the string @var{string} to the file with file descriptor @var{fid}.\n\nThe string is written to the file with no additional formatting.  Use\n@code{fdisp} instead to automatically append a newline character appropriate\nfor the local machine.\n\nThe optional output @var{status} is 0 for success, or -1 if an error was\nencountered.\n@seealso{fdisp, fprintf, fwrite, fopen}\n@end deftypefn */)\n{\n  static const std::string who = \"fputs\";\n\n  return puts_internal (interp, who, args);\n}\n\n/*\n## Check if text is correctly converted to output encoding\n# FIXME: should be conditional on OCTAVE_HAVE_STRICT_ENCODING_FACET\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")  <*61839>\n%! str = \"aäöu\";  # string with non-ASCII characters\n%! fname = tempname ();\n%! fid = fopen (fname, \"wt\", \"n\", \"ISO-8859-1\");\n%! unwind_protect\n%!   fprintf (fid, '%s\\n', str);\n%!   fdisp (fid, str);\n%!   fputs (fid, str);\n%!   fclose (fid);\n%!   ## re-open file for reading in binary mode\n%!   fid = fopen (fname, \"rb\");\n%!   fb = fread (fid);\n%!   fclose (fid);\n%!   ## check file content\n%!   encoded = [97 228 246 117];  # original string in ISO-8859-1 encoding\n%!   if (ispc ())\n%!     eol = double (\"\\r\\n\");\n%!   else\n%!     eol = double (\"\\n\");\n%!   endif\n%!   assert (fb.', [encoded eol encoded eol encoded]);\n%! unwind_protect_cleanup\n%!   unlink (fname);\n%! end_unwind_protect\n*/\n\nDEFMETHOD (puts, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} puts (@var{string})\nWrite a string to the standard output with no formatting.\n\nThe string is written verbatim to the standard output.  Use @code{disp} to\nautomatically append a newline character appropriate for the local machine.\n\nThe optional output @var{status} is 0 for success, or -1 if an error was\nencountered.\n@seealso{fputs, disp}\n@end deftypefn */)\n{\n  static const std::string who = \"puts\";\n\n  octave_value_list tmp_args = args;\n\n  return puts_internal (interp, who, tmp_args.prepend (octave_value (1)));\n}\n\nDEFUN (sprintf, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{str} =} sprintf (@var{template}, @dots{})\nThis is like @code{printf}, except that the output is returned as a\nstring.\n\nUnlike the C library function, which requires you to provide a suitably\nsized string as an argument, Octave's @code{sprintf} function returns the\nstring, automatically sized to hold all of the items converted.\n\nImplementation Note: For compatibility with @sc{matlab}, escape sequences in\nthe template string (e.g., @qcode{\"@backslashchar{}n\"} => newline) are\nexpanded even when the template string is defined with single quotes.\n@seealso{printf, fprintf, sscanf}\n@end deftypefn */)\n{\n  static const std::string who = \"sprintf\";\n\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  // We don't use ostrstream::create here because need direct\n  // access to the OSTR object so that we can extract a string object\n  // from it to return.\n  ostrstream *ostr = new ostrstream ();\n\n  // The stream destructor will delete OSTR for us.\n  stream os (ostr);\n\n  if (! os.is_valid ())\n    error (\"%s: unable to create output buffer\", who.c_str ());\n\n  octave_value fmt_arg = args(0);\n\n  if (! fmt_arg.is_string ())\n    error (\"%s: format TEMPLATE must be a string\", who.c_str ());\n\n  octave_value_list retval (3);\n\n  octave_value_list tmp_args;\n  if (nargin > 1)\n    {\n      tmp_args.resize (nargin-1, octave_value ());\n\n      for (int i = 1; i < nargin; i++)\n        tmp_args(i-1) = args(i);\n    }\n\n  // NOTE: Call to os.error must precede next call to ostr which might reset it.\n  retval(2) = os.printf (fmt_arg, tmp_args, who);\n  retval(1) = os.error ();\n\n  std::string result = ostr->str ();\n  char type = (fmt_arg.is_sq_string () ? '\\'' : '\"');\n\n  retval(0) = (result.empty () ? octave_value (charMatrix (1, 0), type)\n               : octave_value (result, type));\n\n  return retval;\n}\n\nstatic octave_value_list\nscanf_internal (interpreter& interp, const std::string& who,\n                const octave_value_list& args)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  octave_value_list retval;\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), who);\n\n  if (! args(1).is_string ())\n    error (\"%s: format TEMPLATE must be a string\", who.c_str ());\n\n  if (nargin == 3 && args(2).is_string ())\n    {\n      retval = os.oscanf (args(1), who);\n    }\n  else\n    {\n      octave_idx_type count = 0;\n\n      Array<double> size\n        = (nargin == 3\n           ? args(2).vector_value ()\n           : Array<double> (dim_vector (1, 1), lo_ieee_inf_value ()));\n\n      octave_value tmp = os.scanf (args(1), size, count, who);\n\n      retval = ovl (tmp, count, os.error ());\n    }\n\n  return retval;\n}\n\nDEFMETHOD (fscanf, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{val}, @var{count}, @var{errmsg}] =} fscanf (@var{fid}, @var{template}, @var{size})\n@deftypefnx {} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} fscanf (@var{fid}, @var{template}, \"C\")\nIn the first form, read from @var{fid} according to @var{template},\nreturning the result in the matrix @var{val}.\n\nThe optional argument @var{size} specifies the amount of data to read\nand may be one of\n\n@table @code\n@item Inf\nRead as much as possible, returning a column vector.\n\n@item @var{nr}\nRead up to @var{nr} elements, returning a column vector.\n\n@item [@var{nr}, Inf]\nRead as much as possible, returning a matrix with @var{nr} rows.  If the\nnumber of elements read is not an exact multiple of @var{nr}, the last\ncolumn is padded with zeros.\n\n@item [@var{nr}, @var{nc}]\nRead up to @code{@var{nr} * @var{nc}} elements, returning a matrix with\n@var{nr} rows.  If the number of elements read is not an exact multiple\nof @var{nr}, the last column is padded with zeros.\n@end table\n\n@noindent\nIf @var{size} is omitted, a value of @code{Inf} is assumed.\n\nA string is returned if @var{template} specifies only character conversions.\n\nThe number of items successfully read is returned in @var{count}.\n\nIf an error occurs, @var{errmsg} contains a system-dependent error message.\n\nIn the second form, read from @var{fid} according to @var{template},\nwith each conversion specifier in @var{template} corresponding to a\nsingle scalar return value.  This form is more ``C-like'', and also\ncompatible with previous versions of Octave.  The number of successful\nconversions is returned in @var{count}\n@ifclear OCTAVE_MANUAL\n\nSee the Formatted Input section of the GNU Octave manual for a\ncomplete description of the syntax of the template string.\n@end ifclear\n@seealso{fgets, fgetl, fread, scanf, sscanf, fopen}\n@end deftypefn */)\n{\n  static const std::string who = \"fscanf\";\n\n  return scanf_internal (interp, who, args);\n}\n\nstatic std::string\nget_scan_string_data (const octave_value& val, const std::string& who)\n{\n  std::string retval;\n\n  if (! val.is_string ())\n    error (\"%s: argument STRING must be a string\", who.c_str ());\n\n  octave_value tmp = val.reshape (dim_vector (1, val.numel ()));\n\n  retval = tmp.string_value ();\n\n  return retval;\n}\n\nDEFUN (sscanf, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{val}, @var{count}, @var{errmsg}, @var{pos}] =} sscanf (@var{string}, @var{template}, @var{size})\n@deftypefnx {} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} sscanf (@var{string}, @var{template}, \"C\")\nThis is like @code{fscanf}, except that the characters are taken from the\nstring @var{string} instead of from a stream.\n\nReaching the end of the string is treated as an end-of-file condition.  In\naddition to the values returned by @code{fscanf}, the index of the next\ncharacter to be read is returned in @var{pos}.\n@seealso{fscanf, scanf, sprintf}\n@end deftypefn */)\n{\n  static const std::string who = \"sscanf\";\n\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  octave_value_list retval;\n\n  std::string data = get_scan_string_data (args(0), who);\n\n  stream os = istrstream::create (data);\n\n  if (! os.is_valid ())\n    error (\"%s: unable to create temporary input buffer\", who.c_str ());\n\n  if (! args(1).is_string ())\n    error (\"%s: format TEMPLATE must be a string\", who.c_str ());\n\n  if (nargin == 3 && args(2).is_string ())\n    {\n      retval = os.oscanf (args(1), who);\n    }\n  else\n    {\n      octave_idx_type count = 0;\n\n      Array<double> size = (nargin == 3) ? args(2).vector_value ()\n                           : Array<double> (dim_vector (1, 1),\n                                            lo_ieee_inf_value ());\n\n      octave_value tmp = os.scanf (args(1), size, count, who);\n\n      // FIXME: is this the right thing to do?\n      // Extract error message first, because getting\n      // position will clear it.\n      std::string errmsg = os.error ();\n\n      retval = ovl (tmp, count, errmsg,\n                    (os.eof () ? data.length () : os.tell ()) + 1);\n    }\n\n  return retval;\n}\n\n/*\n%!test <*56396>\n%! [val, count, errmsg, nextpos] = sscanf ('1234a6', '%2d', 3);\n%! assert (val, [12; 34]);\n%! assert (count, 2);\n%! assert (errmsg, \"sscanf: format failed to match\");\n%! assert (nextpos, 5);\n*/\n\nDEFMETHOD (scanf, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{val}, @var{count}, @var{errmsg}] =} scanf (@var{template}, @var{size})\n@deftypefnx {} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} scanf (@var{template}, \"C\")\nThis is equivalent to calling @code{fscanf} with @var{fid} = @code{stdin}.\n\nIt is currently not useful to call @code{scanf} in interactive programs.\n@seealso{fscanf, sscanf, printf}\n@end deftypefn */)\n{\n  static const std::string who = \"scanf\";\n\n  octave_value_list tmp_args = args;\n\n  return scanf_internal (interp, who, tmp_args.prepend (octave_value (0)));\n}\n\nstatic octave_value_list\ntextscan_internal (interpreter& interp, const std::string& who,\n                   const octave_value_list& args)\n{\n  if (args.length () < 1)\n    print_usage (who);\n\n  stream os;\n\n  if (args(0).is_string ())\n    {\n      std::string data = get_scan_string_data (args(0), who);\n\n      os = istrstream::create (data);\n\n      if (! os.is_valid ())\n        error (\"%s: unable to create temporary input buffer\", who.c_str ());\n    }\n  else\n    {\n      stream_list& streams = interp.get_stream_list ();\n\n      os = streams.lookup (args(0), who);\n    }\n\n  int nskip = 1;\n\n  std::string fmt;\n\n  if (args.length () == 1)\n    {\n      // omitted format = %f.  explicit \"\" = width from file\n      fmt = \"%f\";\n    }\n  else if (args(1).is_string ())\n    {\n      fmt = args(1).string_value ();\n\n      if (args(1).is_sq_string ())\n        fmt = do_string_escapes (fmt);\n\n      nskip++;\n    }\n  else\n    error (\"%s: FORMAT must be a string\", who.c_str ());\n\n  octave_idx_type ntimes = -1;\n\n  if (args.length () > 2)\n    {\n      if (args(2).isnumeric ())\n        {\n          ntimes = args(2).idx_type_value ();\n\n          if (ntimes < args(2).double_value ())\n            error (\"%s: REPEAT = %g is too large\",\n                   who.c_str (), args(2).double_value ());\n\n          nskip++;\n        }\n    }\n\n  octave_value_list options = args.splice (0, nskip);\n\n  octave_idx_type count = 0;\n\n  octave_value result = os.textscan (fmt, ntimes, options, who, count);\n\n  std::string errmsg = os.error ();\n\n  return ovl (result, count, errmsg);\n}\n\nDEFMETHOD (textscan, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} textscan (@var{fid}, @var{format})\n@deftypefnx {} {@var{C} =} textscan (@var{fid}, @var{format}, @var{repeat})\n@deftypefnx {} {@var{C} =} textscan (@var{fid}, @var{format}, @var{param}, @var{value}, @dots{})\n@deftypefnx {} {@var{C} =} textscan (@var{fid}, @var{format}, @var{repeat}, @var{param}, @var{value}, @dots{})\n@deftypefnx {} {@var{C} =} textscan (@var{str}, @dots{})\n@deftypefnx {} {[@var{C}, @var{position}, @var{errmsg}] =} textscan (@dots{})\nRead data from a text file or string.\n\nThe string @var{str} or file associated with @var{fid} is read from and\nparsed according to @var{format}.  The function is an extension of\n@code{strread} and @code{textread}.  Differences include: the ability to\nread from either a file or a string, additional options, and additional\nformat specifiers.\n\nThe input is interpreted as a sequence of words, delimiters (such as\nwhitespace), and literals.  The characters that form delimiters and\nwhitespace are determined by the options.  The format consists of format\nspecifiers interspersed between literals.  In the format, whitespace forms\na delimiter between consecutive literals, but is otherwise ignored.\n\nThe output @var{C} is a cell array where the number of columns is determined\nby the number of format specifiers.\n\nThe first word of the input is matched to the first specifier of the format\nand placed in the first column of the output; the second is matched to the\nsecond specifier and placed in the second column and so forth.  If there\nare more words than specifiers then the process is repeated until all words\nhave been processed or the limit imposed by @var{repeat} has been met (see\nbelow).\n\nThe string @var{format} describes how the words in @var{str} should be\nparsed.  As in @var{fscanf}, any (non-whitespace) text in the format that is\nnot one of these specifiers is considered a literal.  If there is a literal\nbetween two format specifiers then that same literal must appear in the\ninput stream between the matching words.\n\nThe following specifiers are valid:\n\n@table @code\n@item  %f\n@itemx %f64\n@itemx %n\nThe word is parsed as a number and converted to double.\n\n@item  %f32\nThe word is parsed as a number and converted to single (float).\n\n@item  %d\n@itemx %d8\n@itemx %d16\n@itemx %d32\n@itemx %d64\nThe word is parsed as a number and converted to int8, int16, int32, or\nint64.  If no size is specified then int32 is used.\n\n@item  %u\n@itemx %u8\n@itemx %u16\n@itemx %u32\n@itemx %u64\nThe word is parsed as a number and converted to uint8, uint16, uint32, or\nuint64.  If no size is specified then uint32 is used.\n\n@item %s\nThe word is parsed as a string ending at the last character before\nwhitespace, an end-of-line, or a delimiter specified in the options.\n\n@item %q\nThe word is parsed as a \"quoted string\".\nIf the first character of the string is a double quote (\") then the string\nincludes everything until a matching double quote---including whitespace,\ndelimiters, and end-of-line characters.  If a pair of consecutive double\nquotes appears in the input, it is replaced in the output by a single\ndouble quote.  For examples, the input \"He said \"\"Hello\"\"\" would\nreturn the value 'He said \"Hello\"'.\n\n@item  %c\nThe next character of the input is read.\nThis includes delimiters, whitespace, and end-of-line characters.\n\n@item  %[@dots{}]\n@itemx %[^@dots{}]\nIn the first form, the word consists of the longest run consisting of only\ncharacters between the brackets.  Ranges of characters can be specified by\na hyphen; for example, %[0-9a-zA-Z] matches all alphanumeric characters (if\nthe underlying character set is ASCII).  Since @sc{matlab} treats hyphens\nliterally, this expansion only applies to alphanumeric characters.  To\ninclude '-' in the set, it should appear first or last in the brackets; to\ninclude ']', it should be the first character.  If the first character is\n'^' then the word consists of characters @strong{not} listed.\n\n@item %N@dots{}\nFor %s, %c %d, %f, %n, %u, an optional width can be specified as %Ns, etc.\nwhere N is an integer > 1.  For %c, this causes exactly N characters to be\nread instead of a single character.  For the other specifiers, it is an\nupper bound on the number of characters read; normal delimiters can cause\nfewer characters to be read.  For complex numbers, this limit applies to\nthe real and imaginary components individually.  For %f and %n, format\nspecifiers like %N.Mf are allowed, where M is an upper bound on number of\ncharacters after the decimal point to be considered; subsequent digits are\nskipped.  For example, the specifier %8.2f would read 12.345e6 as 1.234e7.\n\n@item %*@dots{}\nThe word specified by the remainder of the conversion specifier is skipped.\n\n@item literals\nIn addition the format may contain literal character strings; these will be\nskipped during reading.  If the input string does not match this literal,\nthe processing terminates.\n@end table\n\nParsed words corresponding to the first specifier are returned in the first\noutput argument and likewise for the rest of the specifiers.\n\nBy default, if there is only one input argument, @var{format} is @t{\"%f\"}.\nThis means that numbers are read from the input into a single column vector.\nIf @var{format} is explicitly empty (@qcode{\"\"}) then textscan will\nreturn data in a number of columns matching the number of fields on the\nfirst data line of the input.  Either of these is suitable only when the\ninput is exclusively numeric.\n\nFor example, the string\n\n@smallexample\n@group\n@var{str} = \"\\\nBunny Bugs   5.5\\n\\\nDuck Daffy  -7.5e-5\\n\\\nPenguin Tux   6\"\n@end group\n@end smallexample\n\n@noindent\ncan be read using\n\n@example\n@var{a} = textscan (@var{str}, \"%s %s %f\");\n@end example\n\nThe optional numeric argument @var{repeat} can be used for limiting the\nnumber of items read:\n\n@table @asis\n@item -1\nRead all of the string or file until the end (default).\n\n@item N\nRead until the first of two conditions occurs: 1) the format has been\nprocessed N times, or 2) N lines of the input have been processed.  Zero\n(0) is an acceptable value for @var{repeat}.  Currently, end-of-line\ncharacters inside %q, %c, and %[@dots{}]$ conversions do not contribute to\nthe line count.  This is incompatible with @sc{matlab} and may change in\nfuture.\n@end table\n\nThe behavior of @code{textscan} can be changed via property/value pairs.\nThe following properties are recognized:\n\n@table @asis\n@item @qcode{\"BufSize\"}\nThis specifies the number of bytes to use for the internal buffer.\nA modest speed improvement may be obtained by setting this to a large value\nwhen reading a large file, especially if the input contains long strings.\nThe default is 4096, or a value dependent on @var{n} if that is specified.\n\n@item @qcode{\"CollectOutput\"}\nA value of 1 or true instructs @code{textscan} to concatenate consecutive\ncolumns of the same class in the output cell array.  A value of 0 or false\n(default) leaves output in distinct columns.\n\n@item @qcode{\"CommentStyle\"}\nSpecify parts of the input which are considered comments and will be\nskipped.  @var{value} is the comment style and can be either (1) A string\nor 1x1 cell string, to skip everything to the right of it; (2) A cell array\nof two strings, to skip everything between the first and second strings.\nComments are only parsed where whitespace is accepted and do not act as\ndelimiters.\n\n@item @qcode{\"Delimiter\"}\nIf @var{value} is a string, any character in @var{value} will be used to\nsplit the input into words.  If @var{value} is a cell array of strings,\nany string in the array will be used to split the input into words.\n(default value = any whitespace.)\n\n@item @qcode{\"EmptyValue\"}\nValue to return for empty numeric values in non-whitespace delimited data.\nThe default is NaN@.  When the data type does not support NaN (int32 for\nexample), then the default is zero.\n\n@item @qcode{\"EndOfLine\"}\n@var{value} can be either an empty or one character specifying the\nend-of-line character, or the pair\n@qcode{\"@backslashchar{}r@backslashchar{}n\"} (CRLF).\nIn the latter case, any of\n@qcode{\"@backslashchar{}r\"}, @qcode{\"@backslashchar{}n\"} or\n@qcode{\"@backslashchar{}r@backslashchar{}n\"} is counted as a (single)\nnewline.  If no value is given,\n@qcode{\"@backslashchar{}r@backslashchar{}n\"} is used.\n@c If set to \"\" (empty string) EOLs are ignored as delimiters and added\n@c to whitespace.\n\n@c When reading from a character string, optional input argument @var{n}\n@c specifies the number of times @var{format} should be used (i.e., to limit\n@c the amount of data read).\n@c When reading from file, @var{n} specifies the number of data lines to read;\n@c in this sense it differs slightly from the format repeat count in strread.\n\n@item @qcode{\"HeaderLines\"}\nThe first @var{value} number of lines of @var{fid} are skipped.  Note that\nthis does not refer to the first non-comment lines, but the first lines of\nany type.\n\n@item @qcode{\"MultipleDelimsAsOne\"}\nIf @var{value} is nonzero, treat a series of consecutive delimiters,\nwithout whitespace in between, as a single delimiter.  Consecutive\ndelimiter series need not be vertically aligned.  Without this option, a\nsingle delimiter before the end of the line does not cause the line to be\nconsidered to end with an empty value, but a single delimiter at the start\nof a line causes the line to be considered to start with an empty value.\n\n@item @qcode{\"TreatAsEmpty\"}\nTreat single occurrences (surrounded by delimiters or whitespace) of the\nstring(s) in @var{value} as missing values.\n\n@item @qcode{\"ReturnOnError\"}\nIf set to numerical 1 or true, return normally as soon as an error is\nencountered, such as trying to read a string using @code{%f}.\nIf set to 0 or false, return an error and no data.\n\n@item @qcode{\"Whitespace\"}\nAny character in @var{value} will be interpreted as whitespace and trimmed;\nThe default value for whitespace is\n@c Note: the next line specifically has a newline which generates a space\n@c       in the output of qcode, but keeps the next line < 80 characters.\n@qcode{\"\n@backslashchar{}b@backslashchar{}r@backslashchar{}n@backslashchar{}t\"}\n(note the space).  Unless whitespace is set to @qcode{\"\"} (empty) AND at\nleast one @qcode{\"%s\"} format conversion specifier is supplied, a space is\nalways part of whitespace.\n\n@end table\n\nWhen the number of words in @var{str} or @var{fid} doesn't match an exact\nmultiple of the number of format conversion specifiers, @code{textscan}'s\nbehavior depends on whether the last character of the string or file is an\nend-of-line as specified by the @code{EndOfLine} option:\n\n@table @asis\n@item last character = end-of-line\nData columns are padded with empty fields, NaN or 0 (for integer fields) so\nthat all columns have equal length\n\n@item last character is not end-of-line\nData columns are not padded; @code{textscan} returns columns of unequal\nlength\n@end table\n\nThe second output @var{position} provides the location, in characters\nfrom the beginning of the file or string, where processing stopped.\n\n@seealso{dlmread, fscanf, load, strread, textread}\n@end deftypefn */)\n{\n  static const std::string who = \"textscan\";\n\n  return textscan_internal (interp, who, args);\n}\n\nDEFMETHOD (__textscan__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} __textscan__ (@var{who}, @dots{})\nLike @code{textscan} but accept additional argument @var{who} to use\nas the name of the function when reporting errors.\n@end deftypefn */)\n{\n  if (args.length () == 0)\n    print_usage ();\n\n  return textscan_internal (interp, args(0).string_value (),\n                            args.splice (0, 1));\n}\n\n/*\n%!test\n%! str = \"1,  2,  3,  4\\n 5,  ,  ,  8\\n 9, 10, 11, 12\";\n%! fmtstr = \"%f %d %f %s\";\n%! c = textscan (str, fmtstr, 2, \"delimiter\", \",\", \"emptyvalue\", -Inf);\n%! assert (c{1}, [1;5]);\n%! assert (c{3}, [3; -Inf]);\n%! assert (iscellstr (c{4}));\n\n%!test\n%! b = [10:10:100];\n%! b = [b; 8*b/5];\n%! str = sprintf (\"%g miles/hr = %g kilometers/hr\\n\", b);\n%! fmt = \"%f miles/hr = %f kilometers/hr\";\n%! c = textscan (str, fmt);\n%! assert (c{1}, b(1,:)', 1e-5);\n%! assert (c{2}, b(2,:)', 1e-5);\n\n%!test\n%! str = \"13, -, NA, str1, -25\\r\\n// Middle line\\r\\n36, na, 05, str3, 6\";\n%! c = textscan (str, \"%d %n %f %s %n\", \"delimiter\", \",\",\n%!                    \"treatAsEmpty\", {\"NA\", \"na\", \"-\"}, \"commentStyle\", \"//\");\n%! assert (c{1}, int32 ([13; 36]));\n%! assert (c{2}, [NaN; NaN]);\n%! assert (c{3}, [NaN; 5]);\n%! assert (c{4}, {\"str1\"; \"str3\"});\n%! assert (c{5}, [-25; 6]);\n\n%!test\n%! str = \"Km:10 = hhhBjjj miles16hour\\r\\n\";\n%! str = [str \"Km:15 = hhhJjjj miles241hour\\r\\n\"];\n%! str = [str \"Km:2 = hhhRjjj miles3hour\\r\\n\"];\n%! str = [str \"Km:25 = hhhZ\\r\\n\"];\n%! fmt = \"Km:%d = hhh%1sjjj miles%dhour\";\n%! c = textscan (str, fmt, \"delimiter\", \" \");\n%! assert (c{1}', int32 ([10, 15, 2, 25]));\n%! assert (c{2}', {'B' 'J' 'R' 'Z'});\n%! assert (c{3}', int32 ([16, 241, 3, 0]));\n\n## Test with default EndOfLine parameter\n%!test\n%! c = textscan (\"L1\\nL2\", \"%s\");\n%! assert (c{:}, {\"L1\"; \"L2\"});\n\n## Test with EndofLine parameter set to \"\" (empty) - newline should be in word\n%!test\n%! c = textscan (\"L1\\nL2\", \"%s\", \"endofline\", \"\");\n%! assert (int8 ([c{:}{:}]), int8 ([76, 49, 10, 76, 50]));\n\n##  Matlab fails this test.  A literal after a conversion is not a delimiter\n%!#test\n%! ## No delimiters at all besides EOL.  Skip fields, even empty fields\n%! str = \"Text1Text2Text\\nTextText4Text\\nText57Text\";\n%! c = textscan (str, \"Text%*dText%dText\");\n%! assert (c{1}, int32 ([2; 4; 0]));\n\n## CollectOutput test\n%!test\n%! b = [10:10:100];\n%! b = [b; 8*b/5; 8*b*1000/5];\n%! str = sprintf (\"%g miles/hr = %g (%g) kilometers (meters)/hr\\n\", b);\n%! fmt = \"%f miles%s %s %f (%f) kilometers %*s\";\n%! c = textscan (str, fmt, \"collectoutput\", 1);\n%! assert (size (c{3}), [10, 2]);\n%! assert (size (c{2}), [10, 2]);\n\n## CollectOutput test with uneven column length files\n%!test\n%! b = [10:10:100];\n%! b = [b; 8*b/5; 8*b*1000/5];\n%! str = sprintf (\"%g miles/hr = %g (%g) kilometers (meters)/hr\\n\", b);\n%! str = [str \"110 miles/hr\"];\n%! fmt = \"%f miles%s %s %f (%f) kilometers %*s\";\n%! c = textscan (str, fmt, \"collectoutput\", 1);\n%! assert (size (c{1}), [11, 1]);\n%! assert (size (c{3}), [11, 2]);\n%! assert (size (c{2}), [11, 2]);\n%! assert (c{3}(end), NaN);\n%! assert (c{2}{11, 1}, \"/hr\");\n%! assert (isempty (c{2}{11, 2}), true);\n\n## Double quoted string\n%!test\n%! str = 'First    \"the second called \"\"the middle\"\"\" third';\n%! fmt = \"%q\";\n%! c = textscan (str, fmt);\n%! assert (c{1}, {\"First\"; 'the second called \"the middle\"'; \"third\"});\n\n## Arbitrary character\n%!test\n%! c = textscan (\"a first, \\n second, third\", \"%s %c %11c\", \"delimiter\", \" ,\");\n%! assert (c{1}, {\"a\"; \"ond\"});\n%! assert (c{2}, {\"f\"; \"t\"});\n%! assert (c{3}, {\"irst, \\n sec\"; \"hird\"});\n\n## Field width and non-standard delimiters\n%!test\n%! str = \"12;34;123456789;7\";\n%! c = textscan (str, \"%4d %4d\", \"delimiter\", \";\", \"collectOutput\", 1);\n%! assert (c, {[12, 34; 1234, 5678; 9, 7]});\n\n## Field width and non-standard delimiters (2)\n%!test\n%! str = \"12;34;123456789;7\";\n%! c = textscan (str, \"%4f %f\", \"delimiter\", \";\", \"collectOutput\", 1);\n%! assert (c, {[12, 34; 1234, 56789; 7, NaN]});\n\n## FIXME: Not Matlab compatible.  Matlab prioritizes precision over field width\n## so \"12.234e+2\", when read with \"%10.2f %f\", yields \"12.23\" and \"4e+2\".\n## Ignore trailing delimiter, but use leading one\n%!#test\n%! str = \"12.234e+2,34, \\n12345.789-9876j,78\\n,10|3\";\n%! c = textscan (str, \"%10.2f %f\", \"delimiter\", \",\", \"collectOutput\", 1,\n%!                    \"expChars\", \"e|\");\n%! assert (c, {[1223, 34; 12345.79-9876j, 78; NaN, 10000]}, 1e-6);\n\n## Multi-character delimiter\n%!test\n%! str = \"99end2 space88gap 4564\";\n%! c = textscan (str, \"%d %s\", \"delimiter\", {\"end\", \"gap\", \"space\"});\n%! assert (c{1}, int32 ([99; 88]));\n%! assert (c{2}, {\"2 \"; \"4564\"});\n\n## FIXME: Following two tests still fail (4/13/2016).\n## Delimiters as part of literals, and following literals\n%!#test\n%! str = \"12 R&D & 7\";\n%! c = textscan (str, \"%f R&D %f\", \"delimiter\", \"&\", \"collectOutput\", 1,\n%!                    \"EmptyValue\", -99);\n%! assert (c, {[12, -99; 7, -99]});\n\n## Delimiters as part of literals, and before literals\n%!#test\n%! str = \"12 & R&D 7\";\n%! c = textscan (str, \"%f R&D %f\", \"delimiter\", \"&\", \"collectOutput\", 1);\n%! assert (c, {[12 7]});\n\n## Check number of lines read, not number of passes through format string\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid, \"1\\n2\\n3\\n4\\n5\\n6\");\n%! fseek (fid, 0, \"bof\");\n%! c = textscan (fid, \"%f %f\", 2);\n%! E = feof (fid);\n%! fclose (fid);\n%! unlink (f);\n%! assert (c, {1, 2});\n%! assert (! E);\n\n## Check number of lines read, not number of passes through format string\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid, \"1\\r\\n2\\r3\\n4\\r\\n5\\n6\");\n%! fseek (fid, 0, \"bof\");\n%! c = textscan (fid, \"%f %f\", 4);\n%! fclose (fid);\n%! unlink (f);\n%! assert (c, {[1;3], [2;4]});\n\n## Check number of lines read, with multiple delimiters\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid, \"1-\\r\\n-2\\r3-\\n-4\\r\\n5\\n6\");\n%! fseek (fid, 0, \"bof\");\n%! c = textscan (fid, \"%f %f\", 4, \"delimiter\", \"-\", \"multipleDelimsAsOne\", 1);\n%! fclose (fid);\n%! unlink (f);\n%! assert (c, {[1;3], [2;4]});\n\n## Check ReturnOnError\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! str = \"1 2 3\\n4 s 6\";\n%! fprintf (fid, str);\n%! fseek (fid, 0, \"bof\");\n%! c = textscan (fid, \"%f %f %f\", \"ReturnOnError\", 1);\n%! fseek (fid, 0, \"bof\");\n%! fclose (fid);\n%! unlink (f);\n%! u = textscan (str, \"%f %f %f\", \"ReturnOnError\", 1);\n%! assert (c, {[1;4], [2], [3]});\n%! assert (u, {[1;4], [2], [3]});\n\n%! ## Check ReturnOnError (2)\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! str = \"1 2 3\\n4 s 6\\n\";\n%! fprintf (fid, str);\n%! fseek (fid, 0, \"bof\");\n%! c = textscan (fid, \"%f %f %f\", \"ReturnOnError\", 1);\n%! fseek (fid, 0, \"bof\");\n%! fclose (fid);\n%! unlink (f);\n%! u = textscan (str, \"%f %f %f\", \"ReturnOnError\", 1);\n%! assert (c, {[1;4], 2, 3});\n%! assert (u, {[1;4], 2, 3});\n\n%!error <Read error in field 2 of row 2>\n%! textscan (\"1 2 3\\n4 s 6\", \"%f %f %f\", \"ReturnOnError\", 0);\n\n## Check ReturnOnError (3)\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid, \"1 s 3\\n4 5 6\");\n%! fseek (fid, 0, \"bof\");\n%! c = textscan (fid, \"\", \"ReturnOnError\", 1);\n%! fseek (fid, 0, \"bof\");\n%! fclose (fid);\n%! unlink (f);\n%! assert (c, {1});\n\n## Check ReturnOnError with empty fields\n%!test\n%! c = textscan (\"1,,3\\n4,5,6\", \"\", \"Delimiter\", \",\", \"ReturnOnError\", 1);\n%! assert (c, {[1;4], [NaN;5], [3;6]});\n\n## Check ReturnOnError with empty fields (2)\n%!test\n%! c = textscan (\"1,,3\\n4,5,6\", \"%f %f %f\", \"Delimiter\", \",\",\n%!               \"ReturnOnError\", 1);\n%! assert (c, {[1;4], [NaN;5], [3;6]});\n\n## Check ReturnOnError in first column\n%!test\n%! c = textscan (\"1 2 3\\ns 5 6\", \"\", \"ReturnOnError\", 1);\n%! assert (c, {1, 2, 3});\n\n## FIXME: This test fails (4/14/16)\n## Test incomplete first data line\n%!#test\n%! R = textscan (['Empty1' char(10)], 'Empty%d %f');\n%! assert (R{1}, int32 (1));\n%! assert (isempty (R{2}), true);\n\n%!test <*37023>\n%! data = textscan (\"   1. 1 \\n 2 3\\n\", '%f %f');\n%! assert (data{1}, [1; 2], 1e-15);\n%! assert (data{2}, [1; 3], 1e-15);\n\n## Whitespace test using delimiter \";\"\n%!test <*37333>\n%! tc{1, 1} = \"C:/code;\";\n%! tc{1, end+1} = \"C:/code/meas;\";\n%! tc{1, end+1} = \" C:/code/sim;\";\n%! tc{1, end+1} = \"C:/code/utils;\";\n%! string = [tc{:}];\n%! c = textscan (string, \"%s\", \"delimiter\", \";\");\n%! for k = 1:max (numel (c{1}), numel (tc))\n%!   lh = c{1}{k};\n%!   rh = tc{k};\n%!   rh(rh == \";\") = \"\";\n%!   rh = strtrim (rh);\n%!   assert (strcmp (lh, rh));\n%! endfor\n\n## Whitespace test, adding multipleDelimsAsOne true arg\n%!test <*37333>\n%! tc{1, 1} = \"C:/code;\";\n%! tc{1, end+1} = \" C:/code/meas;\";\n%! tc{1, end+1} = \"C:/code/sim;;\";\n%! tc{1, end+1} = \"C:/code/utils;\";\n%! string = [tc{:}];\n%! c = textscan (string, \"%s\", \"delimiter\", \";\", \"multipleDelimsAsOne\", 1);\n%! for k = 1:max (numel (c{1}), numel (tc))\n%!   lh = c{1}{k};\n%!   rh = tc{k};\n%!   rh(rh == \";\") = \"\";\n%!   rh = strtrim (rh);\n%!   assert (strcmp (lh, rh));\n%! endfor\n\n## Whitespace test (bug #37333), adding multipleDelimsAsOne false arg\n%!test <*37333>\n%! tc{1, 1} = \"C:/code;\";\n%! tc{1, end+1} = \" C:/code/meas;\";\n%! tc{1, end+1} = \"C:/code/sim;;\";\n%! tc{1, end+1} = \"\";\n%! tc{1, end+1} = \"C:/code/utils;\";\n%! string = [tc{:}];\n%! c = textscan (string, \"%s\", \"delimiter\", \";\", \"multipleDelimsAsOne\", 0);\n%! for k = 1:max (numel (c{1}), numel (tc))\n%!   lh = c{1}{k};\n%!   rh = tc{k};\n%!   rh(rh == \";\") = \"\";\n%!   rh = strtrim (rh);\n%!   assert (strcmp (lh, rh));\n%! endfor\n\n## Whitespace test (bug #37333) whitespace \"\" arg\n%!test <*37333>\n%! tc{1, 1} = \"C:/code;\";\n%! tc{1, end+1} = \" C:/code/meas;\";\n%! tc{1, end+1} = \"C:/code/sim;\";\n%! tc{1, end+1} = \"C:/code/utils;\";\n%! string = [tc{:}];\n%! c = textscan (string, \"%s\", \"delimiter\", \";\", \"whitespace\", \"\");\n%! for k = 1:max (numel (c{1}), numel (tc))\n%!   lh = c{1}{k};\n%!   rh = tc{k};\n%!   rh(rh == \";\") = \"\";\n%!   assert (strcmp (lh, rh));\n%! endfor\n\n## Whitespace test (bug #37333), whitespace \" \" arg\n%!test <*37333>\n%! tc{1, 1} = \"C:/code;\";\n%! tc{1, end+1} = \" C:/code/meas;\";\n%! tc{1, end+1} = \"C:/code/sim;\";\n%! tc{1, end+1} = \"C:/code/utils;\";\n%! string = [tc{:}];\n%! c = textscan (string, \"%s\", \"delimiter\", \";\", \"whitespace\", \" \");\n%! for k = 1:max (numel (c{1}), numel (tc))\n%!   lh = c{1}{k};\n%!   rh = tc{k};\n%!   rh(rh == \";\") = \"\";\n%!   rh = strtrim (rh);\n%!   assert (strcmp (lh, rh));\n%! endfor\n\n## Tests reading with empty format, should return proper nr of columns\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid, \" 1 2 3 4\\n5 6 7 8\");\n%! fseek (fid, 0, \"bof\");\n%! C = textscan (fid, \"\");\n%! E = feof (fid);\n%! fclose (fid);\n%! unlink (f);\n%! assert (C{1}, [1 ; 5], 1e-6);\n%! assert (C{2}, [2 ; 6], 1e-6);\n%! assert (C{3}, [3 ; 7], 1e-6);\n%! assert (C{4}, [4 ; 8], 1e-6);\n%! assert (E);\n\n## Test leaving the file at the correct position on exit\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid, \"1,2\\n3,4\\n\");\n%! fseek (fid, 0, \"bof\");\n%! C = textscan (fid, \"%s %f\", 2, \"Delimiter\", \",\");\n%! E = ftell (fid);\n%! fclose (fid);\n%! unlink (f);\n%! assert (E, 8);\n\n## Tests reading with empty format; empty fields & incomplete lower row\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid, \" ,2,,4\\n5,6\");\n%! fseek (fid, 0, \"bof\");\n%! C = textscan (fid, \"\", \"delimiter\", \",\", \"EmptyValue\", 999,\n%!                    \"CollectOutput\" , 1);\n%! fclose (fid);\n%! unlink (f);\n%! assert (C{1}, [999, 2, 999, 4; 5, 6, 999, 999], 1e-6);\n\n## Error message tests\n\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! msg1 = \"textscan: 1 parameters given, but only 0 values\";\n%! try\n%!   C = textscan (fid, \"\", \"headerlines\");\n%! end_try_catch\n%! assert (! feof (fid));\n%! fclose (fid);\n%! unlink (f);\n%! assert (msg1, lasterr);\n\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! msg1 = \"textscan: HeaderLines must be numeric\";\n%! try\n%!   C = textscan (fid, \"\", \"headerlines\", \"hh\");\n%! end_try_catch\n%! fclose (fid);\n%! unlink (f);\n%! assert (msg1, lasterr);\n\n## Skip headerlines\n%!test\n%! C = textscan (\"field 1  field2\\n 1 2\\n3 4\", \"\", \"headerlines\", 1,\n%!               \"collectOutput\", 1);\n%! assert (C, {[1 2; 3 4]});\n\n## Skip headerlines with non-default EOL\n%!test\n%! C = textscan (\"field 1  field2\\r 1 2\\r3 4\", \"\", \"headerlines\", 2,\n%!               \"collectOutput\", 1, \"EndOfLine\", '\\r');\n%! assert (C, {[3 4]});\n\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid,\"some_string\");\n%! fseek (fid, 0, \"bof\");\n%! msg1 = \"textscan: EndOfLine must be at most one character or '\\\\r\\\\n'\";\n%! try\n%!   C = textscan (fid, \"%f\", \"EndOfLine\", \"\\n\\r\");\n%! end_try_catch\n%! fclose (fid);\n%! unlink (f);\n%! assert (msg1, lasterr);\n\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid,\"some_string\");\n%! fseek (fid, 0, \"bof\");\n%! msg1 = \"textscan: EndOfLine must be at most one character or '\\\\r\\\\n'\";\n%! try\n%!   C = textscan (fid, \"%f\", \"EndOfLine\", 33);\n%! end_try_catch\n%! fclose (fid);\n%! unlink (f);\n%! assert (msg1, lasterr);\n\n%!assert <*41824> (textscan (\"123\", \"\", \"whitespace\", \" \"){:}, 123)\n\n## just test supplied emptyvalue\n%!assert <*42343> (textscan (\",NaN\", \"\", \"delimiter\", \",\" ,\"emptyValue\" ,Inf),\n%!                {Inf, NaN})\n\n## test padding with supplied emptyvalue\n%!test <*42343>\n%! c = textscan (\",1,,4\\nInf,  ,NaN\\n\", \"\", \"delimiter\", \",\",\n%!               \"emptyvalue\", -10);\n%! assert (cell2mat (c), [-10, 1, -10, 4; Inf, -10, NaN, -10]);\n\n%!test <*42528>\n%! assert (textscan (\"1i\", \"\"){1}, 0+1i);\n%! C = textscan (\"3, 2-4i, NaN\\n -i, 1, 23.4+2.2i\\n 1+1 1+1j\", \"\",\n%!               \"delimiter\", \",\");\n%! assert (cell2mat (C), [3+0i, 2-4i, NaN+0i; 0-i, 1+0i, 23.4+2.2i; 1 1 1+1i]);\n\n%!test\n%! ## TreatAsEmpty\n%! C = textscan (\"1,2,3,NN,5,6\\n\", \"%d%d%d%f\", \"delimiter\", \",\",\n%!               \"TreatAsEmpty\", \"NN\");\n%! assert (C{3}(1), int32 (3));\n%! assert (C{4}(1), NaN);\n\n## MultipleDelimsAsOne\n%!test\n%! str = \"11, 12, 13,, 15\\n21,, 23, 24, 25\\n,, 33, 34, 35\\n\";\n%! C = textscan (str, \"%f %f %f %f\", \"delimiter\", \",\",\n%!                    \"multipledelimsasone\", 1, \"endofline\", \"\\n\");\n%! assert (C{1}', [11, 21, 33]);\n%! assert (C{2}', [12, 23, 34]);\n%! assert (C{3}', [13, 24, 35]);\n%! assert (C{4}', [15, 25, NaN]);\n\n## Single-quoted escape sequences\n%!test\n%! str = \"11\\t12\\t13\\r21\\t22\\t23\";\n%! c = textscan (str, \"\", \"delimiter\", '\\t', \"EndOfLine\", '\\r');\n%! assert (c{1}', [11, 21]);\n%! assert (c{2}', [12, 22]);\n%! assert (c{3}', [13, 23]);\n\n%!test <*44750>\n%! c = textscan (\"/home/foo/\", \"%s\", \"delimiter\", \"/\",\n%!               \"MultipleDelimsAsOne\", 1);\n%! assert (c{1}, {\"home\"; \"foo\"});\n\n## FIXME: Test still fails (4/13/2016).\n## Allow cuddling %sliteral, but warn it is ambiguous\n%!#test\n%! C = textscan (\"abcxyz51\\nxyz83\\n##xyz101\", \"%s xyz %d\");\n%! assert (C{1}([1 3]), {\"abc\"; \"##\"});\n%! assert (isempty (C{1}{2}), true);\n%! assert (C{2}, int32 ([51; 83; 101]));\n\n## Literals are not delimiters.\n\n## Test for false positives in check for non-supported format specifiers\n%!test\n%! c = textscan (\"Total: 32.5 % (of cm values)\",\n%!               \"Total: %f %% (of cm values)\");\n%! assert (c{1}, 32.5, 1e-5);\n\n## Test various forms of string format specifiers\n%!test <*45712>\n%! str = \"14 :1 z:2 z:3 z:5 z:11\";\n%! C = textscan (str, \"%f %s %*s %3s %*3s %f\", \"delimiter\", \":\");\n%! assert (C, {14, {\"1 z\"}, {\"3 z\"}, 11});\n\n## Bit width, fixed width conversion specifiers\n%!test\n%! str2 = \"123456789012345 \";\n%! str2 = [str2 str2 str2 str2 str2 str2 str2 str2];\n%! str2 = [str2 \"123456789.01234 1234567890.1234 12345.678901234 12345.678901234\"];\n%! pttrn = \"%3u8%*s %5u16%*s %10u32%*s %15u64 %3d8%*s %5d16%*s %10d32%*s %15d64 %9f32%*s %14f64%*s %10.2f32%*s %12.2f64%*s\";\n%! C = textscan (str2, pttrn, \"delimiter\", \" \");\n%! assert (C{1}, uint8 (123));\n%! assert (C{2}, uint16 (12345));\n%! assert (C{3}, uint32 (1234567890));\n%! assert (C{4}, uint64 (123456789012345));\n%! assert (C{5}, int8 (123));\n%! assert (C{6}, int16 (12345));\n%! assert (C{7}, int32 (1234567890));\n%! assert (C{8}, int64 (123456789012345));\n%! assert (C{9}, single (123456789), 1e-12);\n%! assert (C{10}, double (1234567890.123), 1e-15);\n%! assert (C{11}, single (12345.68), 1e-5);\n%! assert (C{12}, double (12345.68), 1e-11);\n\n## Bit width, fixed width conv. specifiers -- check the right amount is left\n%!test\n%! str2 = \"123456789012345 \";\n%! str2 = [str2 str2 \"123456789.01234\"];\n%! pttrn = \"%3u8 %5u16 %10u32 %3d8 %5d16 %10d32 %9f32 %9f\";\n%! C = textscan (str2, pttrn, \"delimiter\", \" \");\n%! assert (C{1}, uint8 (123));\n%! assert (C{2}, uint16 (45678));\n%! assert (C{3}, uint32 (9012345));\n%! assert (C{4}, int8 (123));\n%! assert (C{5}, int16 (45678));\n%! assert (C{6}, int32 (9012345));\n%! assert (C{7}, single (123456789), 1e-12);\n%! assert (C{8}, double (0.01234), 1e-12);\n\n%!test\n%! C = textscan (\"123.123\", \"%2f %3f %3f\");\n%! assert (C{1}, 12);\n%! assert (C{2}, 3.1, 1e-11);\n%! assert (C{3}, 23);\n\n%!test\n%! C = textscan (\"123.123\", \"%3f %3f %3f\");\n%! assert (C{1}, 123);\n%! assert (C{2}, 0.12, 1e-11);\n%! assert (C{3}, 3);\n\n%!test\n%! C = textscan (\"123.123\", \"%4f %3f\");\n%! assert (C{1}, 123);\n%! assert (C{2}, 123);\n\n## field width interrupts exponent.  (Matlab incorrectly gives [12, 2e12])\n%!test\n%! assert (textscan (\"12e12\",  \"%4f\"), {[120;  2]});\n%! assert (textscan (\"12e+12\", \"%5f\"), {[120;  2]});\n%! assert (textscan (\"125e-12\",\"%6f\"), {[12.5; 2]});\n\n## %[] tests\n## Plain [..] and *[..]\n%!test\n%! ar = \"abcdefguvwxAny\\nacegxyzTrailing\\nJunk\";\n%! C = textscan (ar, \"%[abcdefg] %*[uvwxyz] %s\");\n%! assert (C{1}, {\"abcdefg\"; \"aceg\"; \"\"});\n%! assert (C{2}, {\"Any\"; \"Trailing\"; \"Junk\"});\n\n%!test\n%! assert (textscan (\"A2 B2 C3\", \"%*[ABC]%d\", 3), {int32([2; 2; 3])});\n\n## [^..] and *[^..]\n%!test\n%! br = \"abcdefguvwx1Any\\nacegxyz2Trailing\\n3Junk\";\n%! C = textscan (br, \"%[abcdefg] %*[^0123456789] %s\");\n%! assert (C{1}, {\"abcdefg\"; \"aceg\"; \"\"});\n%! assert (C{2}, {\"1Any\"; \"2Trailing\"; \"3Junk\"});\n\n## [..] and [^..] containing delimiters\n%!test\n%! cr = \"ab cd efguv wx1Any\\na ce gx yz2Trailing\\n   3Junk\";\n%! C = textscan (cr, \"%[ abcdefg] %*[^0123456789] %s\", \"delimiter\", \" \\n\",\n%!                   \"whitespace\", \"\");\n%! assert (C{1}, {\"ab cd efg\"; \"a ce g\"; \"   \"});\n%! assert (C{2}, {\"1Any\"; \"2Trailing\"; \"3Junk\"});\n\n%!assert <*36464> (textscan (\"1 2 3 4 5 6\", \"%*n%n%*[^\\n]\"){1}, 2)\n\n## test %[]] and %[^]]\n%!test\n%! assert (textscan (\"345]\", \"%*[123456]%[]]\"){1}{1}, \"]\");\n%! assert (textscan (\"345]\", \"%*[^]]%s\"){1}{1}, \"]\");\n\n## Test that \"-i\" checks the next two characters\n%!test\n%! C = textscan (\"-i -in -inf -infinity\", \"%f %f%s %f %f %s\");\n%! assert (C, {-i, -i, {\"n\"}, -Inf, -Inf, {\"inity\"}});\n\n## Again for \"+i\", this time with custom parser\n%!test\n%! C = textscan (\"+i +in +inf +infinity\", \"%f %f%s %f %f %s\", \"ExpChars\", \"eE\");\n%! assert (C, {i, i, {\"n\"}, Inf, Inf, {\"inity\"}});\n\n## Check single quoted format interprets control sequences\n%!test\n%! C = textscan (\"1 2\\t3 4\", '%f %[^\\t] %f %f');\n%! assert (C, {1, {\"2\"}, 3, 4});\n\n## Check a non-empty line with no valid conversion registers empytValue\n%!test\n%! C = textscan (\"Empty\\n\", \"Empty%f %f\");\n%! assert (C, { NaN, NaN });\n\n## Check overflow and underflow of integer types\n%!test\n%! a = \"-1e90 \";\n%! b = \"1e90 \";\n%! fmt = \"%d8 %d16 %d32 %d64 %u8 %u16 %u32 %u64 \";\n%! C = textscan ([a a a a a a a a b b b b b b b b], fmt);\n%! assert (C{1}, int8 ([-128; 127]));\n%! assert (C{2}, int16 ([-32768; 32767]));\n%! assert (C{3}, int32 ([-2147483648; 2147483647]));\n%! assert (C{4}, int64 ([-9223372036854775808; 9223372036854775807]));\n%! assert (C{5}, uint8 ([0; 255]));\n%! assert (C{6}, uint16 ([0; 65535]));\n%! assert (C{7}, uint32 ([0; 4294967295]));\n%! assert (C{8}, uint64 ([0; 18446744073709551615]));\n\n## Tests from Matlab (does The MathWorks have any copyright over the input?)\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid,\"09/12/2005 Level1 12.34 45 1.23e10 inf Nan Yes 5.1+3i\\n\");\n%! fprintf (fid,\"10/12/2005 Level2 23.54 60 9e19 -inf  0.001 No 2.2-.5i\\n\");\n%! fprintf (fid,\"11/12/2005 Level3 34.90 12 2e5   10  100   No 3.1+.1i\\n\");\n%! fseek (fid, 0, \"bof\");\n%! C = textscan (fid,\"%s %s %f32 %d8 %u %f %f %s %f\");\n%! %assert (C{1}, {\"09/12/2005\";\"10/12/2005\";\"11/12/2005\"});\n%! assert (C{2}, {\"Level1\";\"Level2\";\"Level3\"});\n%! assert (C{3}, [single(12.34);single(23.54);single(34.90)]);\n%! assert (C{4}, [int8(45);int8(60);int8(12)]);\n%! assert (C{5}, [uint32(4294967295);uint32(4294967295);uint32(200000)]);\n%! assert (C{6}, [inf;-inf;10]);\n%! assert (C{7}, [NaN;0.001;100], eps);\n%! assert (C{8}, {\"Yes\";\"No\";\"No\"});\n%! assert (C{9}, [5.1+3i;2.2-0.5i;3.1+0.1i]);\n%! fseek (fid, 0, \"bof\");\n%! C = textscan (fid,\"%s Level%d %f32 %d8 %u %f %f %s %f\");\n%! assert (C{2}, [int32(1);int32(2);int32(3)]);\n%! assert (C{3}, [single(12.34);single(23.54);single(34.90)]);\n%! fseek (fid, 0, \"bof\");\n%! C = textscan (fid, '%s %*[^\\n]');\n%! fclose (fid);\n%! unlink (f);\n%! assert (C, {{\"09/12/2005\";\"10/12/2005\";\"11/12/2005\"}});\n\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid,\"1,  2,  3,  4,   ,  6\\n\");\n%! fprintf (fid,\"7,  8,  9,   , 11, 12\\n\");\n%! fseek (fid, 0, \"bof\");\n%! C = textscan (fid,\"%f %f %f %f %u8 %f\", \"Delimiter\",\",\",\"EmptyValue\",-Inf);\n%! fclose (fid);\n%! unlink (f);\n%! assert (C{4}, [4; -Inf]);\n%! assert (C{5}, uint8 ([0; 11]));\n\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! fprintf (fid,\"abc, 2, NA, 3, 4\\n\");\n%! fprintf (fid,\"// Comment Here\\n\");\n%! fprintf (fid,\"def, na, 5, 6, 7\\n\");\n%! fseek (fid, 0, \"bof\");\n%! C = textscan (fid, \"%s %n %n %n %n\", \"Delimiter\", \",\",\n%!                    \"TreatAsEmpty\", {\"NA\",\"na\"}, \"CommentStyle\", \"//\");\n%! fclose (fid);\n%! unlink (f);\n%! assert (C{1}, {\"abc\";\"def\"});\n%! assert (C{2}, [2; NaN]);\n%! assert (C{3}, [NaN; 5]);\n%! assert (C{4}, [3; 6]);\n%! assert (C{5}, [4; 7]);\n\n## FIXME: Almost passes.  Second return value is {\"/\"}.  Tested 4/14/16.\n## Test start of comment as string\n%!#test\n%! c = textscan (\"1 / 2 // 3\", \"%n %s %u8\", \"CommentStyle\", {\"//\"});\n%! assert (c(1), {1, \"/\", 2});\n\n%!assert (textscan ([\"1 2 3 4\"; \"5 6 7 8\"], \"%f\"), {[15; 26; 37; 48]})\n\n## Check for delimiter after exponent\n%!assert (textscan (\"1e-3|42\", \"%f\", \"delimiter\", \"|\"), {[1e-3; 42]})\n\n%!test <*52479>\n%! str = \"\\t\\ta\\tb\\tc\\n\";\n%! ret = textscan (str, \"%s\", \"delimiter\", \"\\t\");\n%! assert (ret, { {''; ''; 'a'; 'b'; 'c'} });\n\n%!test <*52479>\n%! str = \"\\t\\ta\\tb\\tc\\n\";\n%! ret = textscan (str, \"%s\", \"delimiter\", {\"\\t\"});\n%! assert (ret, { {''; ''; 'a'; 'b'; 'c'} });\n\n%!test <*52550>\n%! str = \",,1,2,3\\n\";\n%! obs = textscan (str, \"%d\", \"delimiter\", \",\");\n%! assert (obs, { [0; 0; 1; 2; 3] });\n%! obs = textscan (str, \"%d\", \"delimiter\", {\",\"});\n%! assert (obs, { [0; 0; 1; 2; 3] });\n\n%!test <*52550>\n%! str = \" , ,1,2,3\\n\";\n%! obs = textscan (str, \"%d\", \"delimiter\", \",\");\n%! assert (obs, { [0; 0; 1; 2; 3] });\n%! textscan (str, \"%d\", \"delimiter\", {\",\"});\n%! assert (obs, { [0; 0; 1; 2; 3] });\n\n%!test <*52550>\n%! str = \" 0 , 5+6j , -INF+INFj ,NaN,3\\n\";\n%! obs = textscan (str, \"%f\", \"delimiter\", \",\");\n%! assert (obs, { [0; 5+6i; complex(-Inf,Inf); NaN; 3] });\n%! obs = textscan (str, \"%f\", \"delimiter\", {\",\"});\n%! assert (obs, { [0; 5+6i; complex(-Inf,Inf); NaN; 3] });\n\n%!test <*52550>\n%! str = \" 0;,;,1;,2;,3\\n\";\n%! assert (textscan (str, \"%f\", \"delimiter\", {\";,\"}), { [0; NaN; 1; 2; 3] });\n\n%!test <*52550>\n%! str = \" 0 ;1 , $ 2 ;3\\n\";\n%! obs = textscan (str, \"%f\", \"delimiter\", \",;$\");\n%! assert (obs, { [0; 1; NaN; 2; 3] });\n%! obs = textscan (str, \"%f\", \"delimiter\", {\",\",\";\",\"$\"});\n%! assert (obs, { [0; 1; NaN; 2; 3] });\n\n## file stream with encoding\n## FIXME: should be conditional on OCTAVE_HAVE_STRICT_ENCODING_FACET\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! f = tempname ();\n%! fid = fopen (f, \"wt+\", \"n\", \"iso-8859-1\");\n%! unwind_protect\n%!   fprintf (fid, \"abc,äöü\\n\");\n%!   fflush (fid);\n%!   fseek (fid, 0, \"bof\");\n%!   obs = textscan (fid, \"%s\", \"delimiter\", \",\");\n%!   fclose (fid);\n%!   assert (obs, { {\"abc\"; \"äöü\"} });\n%! unwind_protect_cleanup\n%!   unlink (f);\n%! end_unwind_protect\n\n%!test <*56917>\n%! str = '\"a,b\",\"c\"';\n%! obs = textscan (str, \"%q\", \"delimiter\", \",\");\n%! assert (obs, { { \"a,b\"; \"c\" } });\n\n%!test <*58008>\n%! txt = sprintf ('literal_other_1_1;literal_other_1_2\\nliteral_other_2_1;literal_other_2_2\\nliteral_other_3_1;literal_other_3_2');\n%! nm1 = textscan (txt, 'literal%s literal%s', 'Delimiter', ';');\n%! assert (nm1{1}, {\"_other_1_1\" ; \"_other_2_1\" ; \"_other_3_1\"});\n%! assert (nm1{2}, {\"_other_1_2\" ; \"_other_2_2\" ; \"_other_3_2\"});\n%! nm2 = textscan (txt, 'literal%s;literal%s', 'Delimiter', ';');\n%! assert (nm1, nm2);\n\n%!test <*57612>\n%! str = sprintf (['101,' '\\n' '201,']);\n%! C = textscan (str, '%s%q', 'Delimiter', ',');\n%! assert (size (C), [1, 2]);\n%! assert (C{1}, { \"101\"; \"201\" });\n%! assert (C{2}, { \"\"; \"\" });\n\n%!test <*57612>\n%! str = sprintf (['101,' '\\n' '201,']);\n%! C = textscan (str, '%s%f', 'Delimiter', ',');\n%! assert (size (C), [1, 2]);\n%! assert (C{1}, { \"101\"; \"201\" });\n%! assert (C{2}, [ NaN; NaN ]);\n\n%!test <*57612>\n%! str = sprintf (['101,' '\\n' '201,']);\n%! C = textscan (str, '%s%d', 'Delimiter', ',');\n%! assert (size (C), [1, 2]);\n%! assert (C{1}, { \"101\"; \"201\" });\n%! assert (C{2}, int32 ([ 0; 0 ]));\n\n%!test <*51093>\n%! str = sprintf ('a\\t\\tb\\tc');\n%! C = textscan (str, '%s', 'Delimiter', '\\t', 'MultipleDelimsAsOne', false);\n%! assert (C{1}, {'a'; ''; 'b'; 'c'});\n\n%!test <50743>\n%! C = textscan ('5973459727478852968', '%u64');\n%! assert (C{1}, uint64 (5973459727478852968));\n\n%!assert <*60711> (textscan('1,.,2', '%f', 'Delimiter', ','), {1})\n\n*/\n\n// These tests have end-comment sequences, so can't just be in a comment\n#if 0\n## Test unfinished comment\n%!test\n%! c = textscan (\"1 2 /* half comment\", \"%n %u8\", \"CommentStyle\", {\"/*\", \"*/\"});\n%! assert (c, {1, 2});\n\n## Test reading from a real file\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w+\");\n%! d = rand (1, 4);\n%! fprintf (fid, \"  %f %f /* comment */  %f  %f \", d);\n%! fseek (fid, 0, \"bof\");\n%! A = textscan (fid, \"%f %f\", \"CommentStyle\", {\"/*\", \"*/\"});\n%! E = feof (fid);\n%! fclose (fid);\n%! unlink (f);\n%! assert (A{1}, [d(1); d(3)], 1e-6);\n%! assert (A{2}, [d(2); d(4)], 1e-6);\n%! assert (E);\n#endif\n\n/*\n## Test input validation\n%!error textscan ()\n%!error <file id must be> textscan (single (4))\n%!error <file id must be> textscan ({4})\n%!error <must be a string> textscan (\"Hello World\", 2)\n%!error <at most one character or>\n%! textscan (\"Hello World\", \"%s\", \"EndOfLine\", 3);\n%!error <'%z' is not a valid format specifier> textscan (\"1.0\", \"%z\")\n%!error <no valid format conversion specifiers> textscan (\"1.0\", \"foo\")\n*/\n\nstatic octave_value\ndo_fread (stream& os, const octave_value& size_arg,\n          const octave_value& prec_arg, const octave_value& skip_arg,\n          const octave_value& arch_arg, octave_idx_type& count)\n{\n  count = -1;\n\n  Array<double> size = size_arg.xvector_value (\"fread: invalid SIZE specified\");\n\n  std::string prec = prec_arg.xstring_value (\"fread: PRECISION must be a string\");\n\n  int block_size = 1;\n  oct_data_conv::data_type input_type;\n  oct_data_conv::data_type output_type;\n\n  try\n    {\n      oct_data_conv::string_to_data_type (prec, block_size,\n                                          input_type, output_type);\n    }\n  catch (execution_exception& ee)\n    {\n      error (ee, \"fread: invalid PRECISION specified\");\n    }\n\n  int skip = 0;\n\n  try\n    {\n      skip = skip_arg.int_value (true);\n    }\n  catch (execution_exception& ee)\n    {\n      error (ee, \"fread: SKIP must be an integer\");\n    }\n\n  std::string arch = arch_arg.xstring_value (\"fread: ARCH architecture type must be a string\");\n\n  mach_info::float_format flt_fmt\n    = mach_info::string_to_float_format (arch);\n\n  return os.read (size, block_size, input_type, output_type, skip,\n                  flt_fmt, count);\n}\n\nDEFMETHOD (fread, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} fread (@var{fid})\n@deftypefnx {} {@var{val} =} fread (@var{fid}, @var{size})\n@deftypefnx {} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision})\n@deftypefnx {} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip})\n@deftypefnx {} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})\n@deftypefnx {} {[@var{val}, @var{count}] =} fread (@dots{})\nRead binary data from the file specified by the file descriptor @var{fid}.\n\nThe optional argument @var{size} specifies the amount of data to read\nand may be one of\n\n@table @code\n@item Inf\nRead as much as possible, returning a column vector.\n\n@item @var{nr}\nRead up to @var{nr} elements, returning a column vector.\n\n@item [@var{nr}, Inf]\nRead as much as possible, returning a matrix with @var{nr} rows.  If the\nnumber of elements read is not an exact multiple of @var{nr}, the last\ncolumn is padded with zeros.\n\n@item [@var{nr}, @var{nc}]\nRead up to @code{@var{nr} * @var{nc}} elements, returning a matrix with\n@var{nr} rows.  If the number of elements read is not an exact multiple\nof @var{nr}, the last column is padded with zeros.\n@end table\n\n@noindent\nIf @var{size} is omitted, a value of @code{Inf} is assumed.\n\nThe optional argument @var{precision} is a string specifying the type of\ndata to read and may be one of\n\n@table @asis\n@item @qcode{\"uint8\"} (default)\n8-bit unsigned integer.\n\n@item  @qcode{\"int8\"}\n@itemx @qcode{\"integer*1\"}\n8-bit signed integer.\n\n@item  @qcode{\"uint16\"}\n@itemx @qcode{\"ushort\"}\n@itemx @qcode{\"unsigned short\"}\n16-bit unsigned integer.\n\n@item  @qcode{\"int16\"}\n@itemx @qcode{\"integer*2\"}\n@itemx @qcode{\"short\"}\n16-bit signed integer.\n\n@item  @qcode{\"uint\"}\n@itemx @qcode{\"uint32\"}\n@itemx @qcode{\"unsigned int\"}\n@itemx @qcode{\"ulong\"}\n@itemx @qcode{\"unsigned long\"}\n32-bit unsigned integer.\n\n@item  @qcode{\"int\"}\n@itemx @qcode{\"int32\"}\n@itemx @qcode{\"integer*4\"}\n@itemx @qcode{\"long\"}\n32-bit signed integer.\n\n@item @qcode{\"uint64\"}\n64-bit unsigned integer.\n\n@item  @qcode{\"int64\"}\n@itemx @qcode{\"integer*8\"}\n64-bit signed integer.\n\n@item  @qcode{\"single\"}\n@itemx @qcode{\"float\"}\n@itemx @qcode{\"float32\"}\n@itemx @qcode{\"real*4\"}\n32-bit floating point number.\n\n@item  @qcode{\"double\"}\n@itemx @qcode{\"float64\"}\n@itemx @qcode{\"real*8\"}\n64-bit floating point number.\n\n@item  @qcode{\"char\"}\n@itemx @qcode{\"char*1\"}\n8-bit single character.\n\n@item  @qcode{\"uchar\"}\n@itemx @qcode{\"unsigned char\"}\n8-bit unsigned character.\n\n@item  @qcode{\"schar\"}\n@itemx @qcode{\"signed char\"}\n8-bit signed character.\n\n@end table\n\n@noindent\nThe default precision is @qcode{\"uint8\"}.\n\nThe @var{precision} argument may also specify an optional repeat\ncount.  For example, @samp{32*single} causes @code{fread} to read\na block of 32 single precision floating point numbers.  Reading in\nblocks is useful in combination with the @var{skip} argument.\n\nThe @var{precision} argument may also specify a type conversion.\nFor example, @samp{int16=>int32} causes @code{fread} to read 16-bit\ninteger values and return an array of 32-bit integer values.  By\ndefault, @code{fread} returns a double precision array.  The special\nform @samp{*TYPE} is shorthand for @samp{TYPE=>TYPE}.\n\nThe conversion and repeat counts may be combined.  For example, the\nspecification @samp{32*single=>single} causes @code{fread} to read\nblocks of single precision floating point values and return an array\nof single precision values instead of the default array of double\nprecision values.\n\nThe optional argument @var{skip} specifies the number of bytes to skip\nafter each element (or block of elements) is read.  If it is not\nspecified, a value of 0 is assumed.  If the final block read is not\ncomplete, the final skip is omitted.  For example,\n\n@example\nfread (f, 10, \"3*single=>single\", 8)\n@end example\n\n@noindent\nwill omit the final 8-byte skip because the last read will not be\na complete block of 3 values.\n\nThe optional argument @var{arch} is a string specifying the data format\nfor the file.  Valid values are\n\n@table @asis\n@item @qcode{\"native\"} or @qcode{\"n\"}\nThe format of the current machine.\n\n@item @qcode{\"ieee-be\"} or @qcode{\"b\"}\nIEEE big endian.\n\n@item @qcode{\"ieee-le\"} or @qcode{\"l\"}\nIEEE little endian.\n@end table\n\nIf no @var{arch} is given the value used in the call to @code{fopen} which\ncreated the file descriptor is used.  Otherwise, the value specified with\n@code{fread} overrides that of @code{fopen} and determines the data format.\n\nThe output argument @var{val} contains the data read from the file.\n\nThe optional return value @var{count} contains the number of elements read.\n@seealso{fwrite, fgets, fgetl, fscanf, fopen}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 5)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), \"fread\");\n\n  octave_value size = lo_ieee_inf_value ();\n  octave_value prec = \"uint8\";\n  octave_value skip = 0;\n  octave_value arch = \"unknown\";\n\n  int idx = 1;\n\n  if (nargin > idx && ! args(idx).is_string ())\n    size = args(idx++);\n\n  if (nargin > idx)\n    prec = args(idx++);\n\n  if (nargin > idx)\n    skip = args(idx++);\n\n  if (nargin > idx)\n    arch = args(idx++);\n  else if (skip.is_string ())\n    {\n      arch = skip;\n      skip = 0;\n    }\n\n  octave_idx_type count = -1;\n\n  octave_value tmp = do_fread (os, size, prec, skip, arch, count);\n\n  return ovl (tmp, count);\n}\n\nstatic int\ndo_fwrite (stream& os, const octave_value& data,\n           const octave_value& prec_arg, const octave_value& skip_arg,\n           const octave_value& arch_arg)\n{\n  std::string prec = prec_arg.xstring_value (\"fwrite: PRECISION must be a string\");\n\n  int block_size = 1;\n  oct_data_conv::data_type output_type;\n\n  try\n    {\n      oct_data_conv::string_to_data_type (prec, block_size, output_type);\n    }\n  catch (execution_exception& ee)\n    {\n      error (ee, \"fwrite: invalid PRECISION specified\");\n    }\n\n  int skip = 0;\n\n  try\n    {\n      skip = skip_arg.int_value (true);\n    }\n  catch (execution_exception& ee)\n    {\n      error (ee, \"fwrite: SKIP must be an integer\");\n    }\n\n  std::string arch = arch_arg.xstring_value (\"fwrite: ARCH architecture type must be a string\");\n\n  mach_info::float_format flt_fmt\n    = mach_info::string_to_float_format (arch);\n\n  return os.write (data, block_size, output_type, skip, flt_fmt);\n}\n\nDEFMETHOD (fwrite, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{count} =} fwrite (@var{fid}, @var{data})\n@deftypefnx {} {@var{count} =} fwrite (@var{fid}, @var{data}, @var{precision})\n@deftypefnx {} {@var{count} =} fwrite (@var{fid}, @var{data}, @var{precision}, @var{skip})\n@deftypefnx {} {@var{count} =} fwrite (@var{fid}, @var{data}, @var{precision}, @var{skip}, @var{arch})\nWrite data in binary form to the file specified by the file descriptor\n@var{fid}.\n\nThe argument @var{data} is a matrix of values that are to be written to the\nfile.  The values are extracted in column-major order.\n\nThe remaining arguments @var{precision}, @var{skip}, and @var{arch} are\noptional, and are interpreted as described for @code{fread}.\n\nThe output @var{count} is the number of data items successfully written.\n\nProgramming Note: The behavior of @code{fwrite} is undefined if the values in\n@var{data} are too large to fit in the specified precision.\n@seealso{fread, fputs, fprintf, fopen}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 5)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), \"fwrite\");\n\n  octave_value prec = \"uchar\";\n  octave_value skip = 0;\n  octave_value arch = \"unknown\";\n\n  int idx = 1;\n\n  octave_value data = args(idx++);\n\n  if (nargin > idx)\n    prec = args(idx++);\n\n  if (nargin > idx)\n    skip = args(idx++);\n\n  if (nargin > idx)\n    arch = args(idx++);\n  else if (skip.is_string ())\n    {\n      arch = skip;\n      skip = 0;\n    }\n\n  return ovl (do_fwrite (os, data, prec, skip, arch));\n}\n\nDEFMETHODX (\"feof\", Ffeof, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} feof (@var{fid})\nReturn 1 if an end-of-file condition has been encountered for the file\nspecified by file descriptor @var{fid} and 0 otherwise.\n\nNote that @code{feof} will only return 1 if the end of the file has already\nbeen encountered, not if the next read operation will result in an\nend-of-file condition.\n@seealso{fread, frewind, fseek, fclear, fopen}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), \"feof\");\n\n  return ovl (os.eof () ? 1.0 : 0.0);\n}\n\nDEFMETHODX (\"ferror\", Fferror, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{msg} =} ferror (@var{fid})\n@deftypefnx {} {[@var{msg}, @var{err}] =} ferror (@var{fid})\n@deftypefnx {} {[@dots{}] =} ferror (@var{fid}, \"clear\")\nQuery the error status of the stream specified by file descriptor @var{fid}.\n\nIf an error condition exists then return a string @var{msg} describing the\nerror.  Otherwise, return an empty string @qcode{\"\"}.\n\nThe second input @qcode{\"clear\"} is optional.  If supplied, the error\nstate on the stream will be cleared.\n\nThe optional second output is a numeric indication of the error status.\n@var{err} is 1 if an error condition has been encountered and 0 otherwise.\n\nNote that @code{ferror} indicates if an error has already occurred, not\nwhether the next operation will result in an error condition.\n@seealso{fclear, fopen}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  stream os = streams.lookup (args(0), \"ferror\");\n\n  bool clear = false;\n\n  if (nargin == 2)\n    {\n      std::string opt = args(1).string_value ();\n\n      clear = (opt == \"clear\");\n    }\n\n  int error_number = 0;\n\n  std::string error_message = os.error (clear, error_number);\n\n  return ovl (error_message, error_number);\n}\n\nDEFMETHODX (\"popen\", Fpopen, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fid} =} popen (@var{command}, @var{mode})\nStart a process and create a pipe.\n\nThe name of the command to run is given by @var{command}.  The argument\n@var{mode} may be\n\n@table @asis\n@item @qcode{\"r\"}\nThe pipe will be connected to the standard output of the process, and\nopen for reading.\n\n@item @qcode{\"w\"}\nThe pipe will be connected to the standard input of the process, and\nopen for writing.\n@end table\n\nThe file identifier corresponding to the input or output stream of the\nprocess is returned in @var{fid}.\n\nFor example:\n\n@example\n@group\nfid = popen (\"ls -ltr / | tail -3\", \"r\");\nwhile (ischar (s = fgets (fid)))\n  fputs (stdout, s);\nendwhile\n\n   @print{} drwxr-xr-x  33 root  root  3072 Feb 15 13:28 etc\n   @print{} drwxr-xr-x   3 root  root  1024 Feb 15 13:28 lib\n   @print{} drwxrwxrwt  15 root  root  2048 Feb 17 14:53 tmp\n@end group\n@end example\n@seealso{popen2}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"popen: COMMAND must be a string\");\n  std::string mode = args(1).xstring_value (\"popen: MODE must be a string\");\n\n  octave_value retval;\n\n  stream_list& streams = interp.get_stream_list ();\n\n  if (mode == \"r\")\n    {\n      stream ips = octave_iprocstream::create (name);\n\n      retval = streams.insert (ips);\n    }\n  else if (mode == \"w\")\n    {\n      stream ops = octave_oprocstream::create (name);\n\n      retval = streams.insert (ops);\n    }\n  else\n    error (\"popen: invalid MODE specified\");\n\n  return retval;\n}\n\nDEFMETHODX (\"pclose\", Fpclose, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} pclose (@var{fid})\nClose a file identifier @var{fid} that was opened by @code{popen}.\n\nIf successful, @code{fclose} returns 0, otherwise, it returns -1.\n\nProgramming Note: The function @code{fclose} may also be used for the same\npurpose.\n@seealso{fclose, popen}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  return ovl (streams.remove (args(0), \"pclose\"));\n}\n\nDEFUN (tempdir, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{dir} =} tempdir ()\nReturn the name of the host system's directory for temporary files.\n\nThe directory name is taken first from the environment variable @env{TMPDIR}.\nIf that does not exist, the environment variable @env{TMP} (and on Windows\nplatforms also with higher priority the environment variable @env{TEMP}) is\nchecked.  If none of those are set, the system default returned by\n@code{P_tmpdir} is used.\n@seealso{P_tmpdir, tempname, mkstemp, tmpfile}\n@end deftypefn */)\n{\n  if (args.length () > 0)\n    print_usage ();\n\n  std::string tmpdir = sys::env::get_temp_directory ();\n\n  if (! sys::file_ops::is_dir_sep (tmpdir.back ()))\n    tmpdir += sys::file_ops::dir_sep_str ();\n\n  return ovl (tmpdir);\n}\n\n/*\n%!assert (ischar (tempdir ()))\n\n%!test\n%! old_wstate = warning (\"off\");\n%! old_tmpdir = getenv (\"TMPDIR\");\n%! unwind_protect\n%!   setenv (\"TMPDIR\", \"__MY_TMP_DIR__\");\n%!   assert (tempdir (), [\"__MY_TMP_DIR__\" filesep()]);\n%! unwind_protect_cleanup\n%!   if (! isempty (old_tmpdir))\n%!     setenv (\"TMPDIR\", old_tmpdir);\n%!   else\n%!     unsetenv (\"TMPDIR\");\n%!   endif\n%!   warning (old_wstate);\n%! end_unwind_protect\n*/\n\nDEFUN (tempname, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{fname} =} tempname ()\n@deftypefnx {} {@var{fname} =} tempname (@var{dir})\n@deftypefnx {} {@var{fname} =} tempname (@var{dir}, @var{prefix})\nReturn a unique temporary filename as a string.\n\nIf @var{prefix} is omitted, a value of @qcode{\"oct-\"} is used.\n\nIf @var{dir} is also omitted, the default directory for temporary files\n(@code{P_tmpdir}) is used.  If @var{dir} is provided, it must exist,\notherwise the default directory for temporary files is used.\n\nProgramming Note: Because the named file is not opened by @code{tempname},\nit is possible, though relatively unlikely, that it will not be available\nby the time your program attempts to open it.  If this is a concern,\n@pxref{XREFtmpfile,,@code{tmpfile}}.\n@seealso{mkstemp, tempdir, P_tmpdir, tmpfile}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 2)\n    print_usage ();\n\n  std::string dir;\n\n  if (nargin > 0)\n    dir = args(0).xstring_value (\"tempname: DIR must be a string\");\n\n  std::string pfx (\"oct-\");\n\n  if (nargin > 1)\n    pfx = args(1).xstring_value (\"tempname: PREFIX must be a string\");\n\n  return ovl (sys::tempnam (dir, pfx));\n}\n\n/*\n%!test\n%! envvar = {\"TMPDIR\", \"TMP\"};\n%! envdir = cellfun (@(x) getenv (x), envvar, \"uniformoutput\", false);\n%! unwind_protect\n%!   cellfun (@(x) unsetenv (x), envvar);\n%!   envname = \"TMPDIR\";\n%!   def_tmpdir = P_tmpdir;\n%!   ## Strip trailing file separators from P_tmpdir\n%!   while (length (def_tmpdir) > 2 && any (def_tmpdir(end) == filesep (\"all\")))\n%!     def_tmpdir(end) = [];\n%!   endwhile\n%!\n%!   ## Test 0-argument form\n%!   fname = tempname ();\n%!   [tmpdir, tmpfname] = fileparts (fname);\n%!   assert (tmpdir, def_tmpdir);\n%!   assert (tmpfname (1:4), \"oct-\");\n%!   ## Test 1-argument form\n%!   tmp_tmpdir = [def_tmpdir filesep() substr(tmpfname, -5)];\n%!   mkdir (tmp_tmpdir) || error (\"Unable to create tmp dir\");\n%!   setenv (envname, def_tmpdir);\n%!   fname = tempname (tmp_tmpdir);\n%!   [tmpdir, tmpfname] = fileparts (fname);\n%!   assert (tmpdir, tmp_tmpdir);\n%!   assert (tmpfname (1:4), \"oct-\");\n%!   ## Test 1-argument form w/null tmpdir\n%!   fname = tempname (\"\");\n%!   [tmpdir, tmpfname] = fileparts (fname);\n%!   assert (tmpdir, def_tmpdir);\n%!   assert (tmpfname (1:4), \"oct-\");\n%!   ## Test 2-argument form\n%!   fname = tempname (tmp_tmpdir, \"pfx-\");\n%!   [tmpdir, tmpfname] = fileparts (fname);\n%!   assert (tmpdir, tmp_tmpdir);\n%!   assert (tmpfname (1:4), \"pfx-\");\n%!   ## Test 2-argument form w/null prefix\n%!   fname = tempname (tmp_tmpdir, \"\");\n%!   [tmpdir, tmpfname] = fileparts (fname);\n%!   assert (tmpdir, tmp_tmpdir);\n%!   assert (tmpfname (1:4), \"file\");\n%! unwind_protect_cleanup\n%!   sts = rmdir (tmp_tmpdir);\n%!   for i = 1:numel (envvar)\n%!     if (isempty (envdir{i}))\n%!       unsetenv (envvar{i});\n%!     else\n%!       setenv (envvar{i}, envdir{i});\n%!     endif\n%!   endfor\n%! end_unwind_protect\n*/\n\nDEFMETHOD (tmpfile, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{fid}, @var{msg}] =} tmpfile ()\nReturn the file ID corresponding to a new temporary file with a unique\nname.\n\nThe file is opened in binary read/write (@qcode{\"w+b\"}) mode and will be\ndeleted automatically when it is closed or when Octave exits.\n\nIf successful, @var{fid} is a valid file ID and @var{msg} is an empty\nstring.  Otherwise, @var{fid} is -1 and @var{msg} contains a\nsystem-dependent error message.\n@seealso{tempname, mkstemp, tempdir, P_tmpdir}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  octave_value_list retval;\n\n  std::string tmpfile (sys::tempnam (sys::env::get_temp_directory (), \"oct-\"));\n\n  FILE *fid = sys::fopen_tmp (tmpfile, \"w+b\");\n\n  if (fid)\n    {\n      std::ios::openmode md = fopen_mode_to_ios_mode (\"w+b\");\n\n      stream s = stdiostream::create (tmpfile, fid, md);\n\n      if (! s)\n        {\n          fclose (fid);\n\n          error (\"tmpfile: failed to create stdiostream object\");\n        }\n\n      stream_list& streams = interp.get_stream_list ();\n\n      retval = ovl (streams.insert (s), \"\");\n    }\n  else\n    retval = ovl (-1, std::strerror (errno));\n\n  return retval;\n}\n\nDEFMETHOD (mkstemp, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{fid}, @var{name}, @var{msg}] =} mkstemp (\"@var{template}\")\n@deftypefnx {} {[@var{fid}, @var{name}, @var{msg}] =} mkstemp (\"@var{template}\", @var{delete})\nReturn the file descriptor @var{fid} corresponding to a new temporary file\nwith a unique name created from @var{template}.\n\nThe last six characters of @var{template} must be @qcode{\"XXXXXX\"} and\nthese are replaced with a string that makes the filename unique.  The file\nis then created with mode read/write and permissions that are system\ndependent (on GNU/Linux systems, the permissions will be 0600 for versions\nof glibc 2.0.7 and later).  The file is opened in binary mode and with the\n@w{@code{O_EXCL}}@ flag.\n\nIf the optional argument @var{delete} is supplied and is true, the file will\nbe deleted automatically when Octave exits.\n\nIf successful, @var{fid} is a valid file ID, @var{name} is the name of the\nfile, and @var{msg} is an empty string.  Otherwise, @var{fid} is -1,\n@var{name} is empty, and @var{msg} contains a system-dependent error\nmessage.\n@seealso{tempname, tempdir, P_tmpdir, tmpfile, fopen}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string tmpl8 = args(0).xstring_value (\"mkstemp: TEMPLATE argument must be a string\");\n\n  octave_value_list retval = ovl (-1, \"\", \"\");\n\n  OCTAVE_LOCAL_BUFFER (char, tmp, tmpl8.size () + 1);\n  strcpy (tmp, tmpl8.c_str ());\n\n  int fd = octave_mkostemp_wrapper (tmp);\n\n  if (fd < 0)\n    {\n      retval(0) = fd;\n      retval(2) = std::strerror (errno);\n    }\n  else\n    {\n      const char *fopen_mode = \"w+b\";\n\n      FILE *fid = fdopen (fd, fopen_mode);\n\n      if (! fid)\n        {\n          retval(0) = -1;\n          retval(2) = std::strerror (errno);\n        }\n      else\n        {\n          std::string nm = tmp;\n\n          std::ios::openmode md = fopen_mode_to_ios_mode (fopen_mode);\n\n          stream s = stdiostream::create (nm, fid, md);\n\n          if (! s)\n            error (\"mkstemp: failed to create stdiostream object\");\n\n          stream_list& streams = interp.get_stream_list ();\n\n          retval(0) = streams.insert (s);\n          retval(1) = nm;\n\n          if (nargin == 2 && args(1).is_true ())\n            interp.mark_for_deletion (nm);\n        }\n    }\n\n  return retval;\n}\n\n// FIXME: This routine also exists verbatim in syscalls.cc.\n//        Maybe change to be a general utility routine.\nstatic int\nconvert (int x, int ibase, int obase)\n{\n  int retval = 0;\n\n  int tmp = x % obase;\n\n  if (tmp > ibase - 1)\n    error (\"umask: invalid digit\");\n\n  retval = tmp;\n  int mult = ibase;\n  while ((x = (x - tmp) / obase))\n    {\n      tmp = x % obase;\n\n      if (tmp > ibase - 1)\n        error (\"umask: invalid digit\");\n\n      retval += mult * tmp;\n      mult *= ibase;\n    }\n\n  return retval;\n}\n\nDEFUNX (\"umask\", Fumask, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{oldmask} =} umask (@var{mask})\nSet the permission mask for file creation.\n\nThe parameter @var{mask} is an integer, interpreted as an octal number.\n\nIf successful, returns the previous value of the mask (as an integer to be\ninterpreted as an octal number); otherwise an error message is printed.\n\nThe permission mask is a UNIX concept used when creating new objects on a\nfile system such as files, directories, or named FIFOs.  The object to be\ncreated has base permissions in an octal number @var{mode} which are\nmodified according to the octal value of @var{mask}.  The final permissions\nfor the new object are @code{@var{mode} - @var{mask}}.\n@seealso{fopen, mkdir, mkfifo}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int mask = args(0).strict_int_value (\"umask: MASK must be an integer\");\n\n  if (mask < 0)\n    error (\"umask: MASK must be a positive integer value\");\n\n  int oct_mask = convert (mask, 8, 10);\n\n  int status = convert (sys::umask (oct_mask), 10, 8);\n\n  if (status >= 0)\n    return ovl (status);\n  else\n    return ovl ();\n}\n\nstatic octave_value\nconst_value (const char *, const octave_value_list& args, int val)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return octave_value (val);\n}\n\nDEFUNX (\"P_tmpdir\", FP_tmpdir, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{sys_tmpdir} =} P_tmpdir ()\nReturn the name of the host system's @strong{default} directory for\ntemporary files.\n\nProgramming Note: The value returned by @code{P_tmpdir} is always the\ndefault location.  This value may not agree with that returned from\n@code{tempdir} if the user has overridden the default with the @env{TMPDIR}\nenvironment variable.\n@seealso{tempdir, tempname, mkstemp, tmpfile}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (get_P_tmpdir ());\n}\n\n// NOTE: the values of SEEK_SET, SEEK_CUR, and SEEK_END have to be\n//       this way for Matlab compatibility.\n\nDEFUNX (\"SEEK_SET\", FSEEK_SET, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fseek_origin} =} SEEK_SET ()\nReturn the numerical value to pass to @code{fseek} to position the file pointer\nrelative to the beginning of the file.\n@seealso{SEEK_CUR, SEEK_END, fseek}\n@end deftypefn */)\n{\n  return const_value (\"SEEK_SET\", args, -1);\n}\n\nDEFUNX (\"SEEK_CUR\", FSEEK_CUR, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fseek_origin} =} SEEK_CUR ()\nReturn the numerical value to pass to @code{fseek} to position the file pointer\nrelative to the current position.\n@seealso{SEEK_SET, SEEK_END, fseek}\n@end deftypefn */)\n{\n  return const_value (\"SEEK_CUR\", args, 0);\n}\n\nDEFUNX (\"SEEK_END\", FSEEK_END, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fseek_origin} =} SEEK_END ()\nReturn the numerical value to pass to @code{fseek} to position the file pointer\nrelative to the end of the file.\n@seealso{SEEK_SET, SEEK_CUR, fseek}\n@end deftypefn */)\n{\n  return const_value (\"SEEK_END\", args, 1);\n}\n\nstatic octave_value\nconst_value (const char *, const octave_value_list& args,\n             const octave_value& val)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return octave_value (val);\n}\n\nDEFMETHODX (\"stdin\", Fstdin, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fid} =} stdin ()\nReturn the numeric value corresponding to the standard input stream.\n\nWhen Octave is used interactively, stdin is filtered through the command\nline editing functions.\n@seealso{stdout, stderr}\n@end deftypefn */)\n{\n  stream_list& streams = interp.get_stream_list ();\n\n  return const_value (\"stdin\", args, streams.stdin_file ());\n}\n\nDEFMETHODX (\"stdout\", Fstdout, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fid} =} stdout ()\nReturn the numeric value corresponding to the standard output stream.\n\nData written to the standard output may be filtered through the pager.\n@seealso{stdin, stderr, page_screen_output}\n@end deftypefn */)\n{\n  stream_list& streams = interp.get_stream_list ();\n\n  return const_value (\"stdout\", args, streams.stdout_file ());\n}\n\nDEFMETHODX (\"stderr\", Fstderr, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fid} =} stderr ()\nReturn the numeric value corresponding to the standard error stream.\n\nEven if paging is turned on, the standard error is not sent to the pager.\nIt is useful for error messages and prompts.\n@seealso{stdin, stdout}\n@end deftypefn */)\n{\n  stream_list& streams = interp.get_stream_list ();\n\n  return const_value (\"stderr\", args, streams.stderr_file ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/file-io.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_file_io_h)\n#define octave_file_io_h 1\n\n#warning \"file-io.h was deprecated in Octave 8 and will be removed in a future version.\"\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ft-text-renderer.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"base-text-renderer.h\"\n#include \"ft-text-renderer.h\"\n\n#if defined (HAVE_FREETYPE)\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n#include <ft2build.h>\n#include FT_FREETYPE_H\n#include FT_GLYPH_H\n\n#if defined (HAVE_FONTCONFIG)\n#  include <fontconfig/fontconfig.h>\n#endif\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n#  pragma GCC diagnostic pop\n#endif\n\n#include <clocale>\n#include <cwchar>\n#include <map>\n#include <utility>\n\n#include \"singleton-cleanup.h\"\n#include \"unistr-wrappers.h\"\n\n#include \"defaults.h\"\n#include \"error.h\"\n#include \"file-ops.h\"\n#include \"oct-env.h\"\n#include \"pr-output.h\"\n#include \"sysdep.h\"\n#include \"text-renderer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// FIXME: maybe issue at most one warning per glyph/font/size/weight\n//        combination.\n\nstatic void\nwarn_missing_glyph (FT_ULong c)\n{\n  warning_with_id (\"Octave:missing-glyph\",\n                   \"text_renderer: skipping missing glyph for character '%lx'\", c);\n}\n\nstatic void\nwarn_glyph_render (FT_ULong c)\n{\n  warning_with_id (\"Octave:glyph-render\",\n                   \"text_renderer: unable to render glyph for character '%lx'\", c);\n}\n\n#if defined (_MSC_VER)\n// FIXME: is this really needed?\n//\n// This is just a trick to avoid multiple symbol definitions.\n// PermMatrix.h contains a dllexport'ed Array<octave_idx_type>\n// that will cause MSVC not to generate a new instantiation and\n// use the imported one instead.\n#  include \"PermMatrix.h\"\n#endif\n\n// Forward declaration\nstatic void ft_face_destroyed (void *object);\n\nclass ft_manager\n{\nprivate:\n\n  ft_manager ()\n    : m_library (), m_freetype_initialized (false),\n      m_fontconfig_initialized (false)\n  {\n    if (FT_Init_FreeType (&m_library))\n      error (\"unable to initialize FreeType library\");\n    else\n      m_freetype_initialized = true;\n\n#if defined (HAVE_FONTCONFIG)\n    if (! FcInit ())\n      error (\"unable to initialize fontconfig library\");\n    else\n      m_fontconfig_initialized = true;\n#endif\n  }\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (ft_manager)\n\nprivate:\n\n  ~ft_manager ()\n  {\n    if (m_freetype_initialized)\n      FT_Done_FreeType (m_library);\n\n#if defined (HAVE_FONTCONFIG)\n    // FIXME: Skip the call to FcFini because it can trigger the assertion\n    //\n    //   octave: fccache.c:507: FcCacheFini: Assertion 'fcCacheChains[i] == ((void *)0)' failed.\n    //\n    // if (m_fontconfig_initialized)\n    //   FcFini ();\n#endif\n  }\n\npublic:\n\n  static bool instance_ok ()\n  {\n    bool retval = true;\n\n    if (! s_instance)\n      {\n        s_instance = new ft_manager ();\n        singleton_cleanup_list::add (cleanup_instance);\n      }\n\n    return retval;\n  }\n\n  static void cleanup_instance ()\n  { delete s_instance; s_instance = nullptr; }\n\n  static FT_Face get_font (const std::string& name, const std::string& weight,\n                           const std::string& angle, double size,\n                           FT_ULong c = 0)\n  {\n    return (instance_ok ()\n            ? s_instance->do_get_font (name, weight, angle, size, c)\n            : nullptr);\n  }\n\n  static octave_map get_system_fonts ()\n  {\n    return (instance_ok ()\n            ? s_instance->do_get_system_fonts ()\n            : octave_map ());\n  }\n\n  static void font_destroyed (FT_Face face)\n  {\n    if (instance_ok ())\n      s_instance->do_font_destroyed (face);\n  }\n\nprivate:\n\n  typedef std::pair<std::string, double> ft_key;\n  typedef std::map<ft_key, FT_Face> ft_cache;\n\n  static octave_map do_get_system_fonts ()\n  {\n    static octave_map font_map;\n\n    if (font_map.isempty ())\n      {\n#if defined (HAVE_FONTCONFIG)\n        FcConfig *config = FcConfigGetCurrent();\n        FcPattern *pat = FcPatternCreate ();\n        FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_SLANT, FC_WEIGHT,\n                                            FC_CHARSET, nullptr);\n        FcFontSet *fs = FcFontList (config, pat, os);\n\n        if (fs->nfont > 0)\n          {\n            // Mark fonts that have at least all printable ASCII chars\n            FcCharSet *minimal_charset =  FcCharSetCreate ();\n            for (int i = 32; i < 127; i++)\n              FcCharSetAddChar (minimal_charset, static_cast<FcChar32> (i));\n\n            string_vector fields (4);\n            fields(0) = \"family\";\n            fields(1) = \"angle\";\n            fields(2) = \"weight\";\n            fields(3) = \"suitable\";\n\n            dim_vector dv (1, fs->nfont);\n            Cell families (dv);\n            Cell angles (dv);\n            Cell weights (dv);\n            Cell suitable (dv);\n\n            unsigned char *family;\n            int val;\n            for (int i = 0; fs && i < fs->nfont; i++)\n              {\n                FcPattern *font = fs->fonts[i];\n                if (FcPatternGetString (font, FC_FAMILY, 0, &family)\n                    == FcResultMatch)\n                  families(i) = std::string (reinterpret_cast<char *> (family));\n                else\n                  families(i) = \"unknown\";\n\n                if (FcPatternGetInteger (font, FC_SLANT, 0, &val)\n                    == FcResultMatch)\n                  angles(i) = (val == FC_SLANT_ITALIC\n                               || val == FC_SLANT_OBLIQUE)\n                              ? \"italic\" : \"normal\";\n                else\n                  angles(i) = \"unknown\";\n\n                if (FcPatternGetInteger (font, FC_WEIGHT, 0, &val)\n                    == FcResultMatch)\n                  weights(i) = (val == FC_WEIGHT_BOLD\n                                || val == FC_WEIGHT_DEMIBOLD)\n                               ? \"bold\" : \"normal\";\n                else\n                  weights(i) = \"unknown\";\n\n                FcCharSet *cset;\n                if (FcPatternGetCharSet (font, FC_CHARSET, 0, &cset)\n                    == FcResultMatch)\n                  suitable(i) = (FcCharSetIsSubset (minimal_charset, cset)\n                                 ? true : false);\n                else\n                  suitable(i) = false;\n              }\n\n            font_map = octave_map (dv, fields);\n\n            font_map.assign (\"family\", families);\n            font_map.assign (\"angle\", angles);\n            font_map.assign (\"weight\", weights);\n            font_map.assign (\"suitable\", suitable);\n\n            // Free up memory within libfontconfig.\n            if (fs)\n              FcFontSetDestroy (fs);\n            if (pat)  // Supposed to be freed by FcFontSetDestroy above, but isn't.\n              FcPatternDestroy (pat);\n            if (os)\n              FcObjectSetDestroy (os);\n            if (minimal_charset)\n              FcCharSetDestroy (minimal_charset);\n          }\n#endif\n      }\n\n    return font_map;\n  }\n\n  FT_Face do_get_font (const std::string& name, const std::string& weight,\n                       const std::string& angle, double size,\n                       FT_ULong search_code_point)\n  {\n    FT_Face retval = nullptr;\n\n#if defined (HAVE_FT_REFERENCE_FACE)\n    // Look first into the font cache, then use fontconfig.  If the font\n    // is present in the cache, simply add a reference and return it.\n\n    ft_key key (name + ':' + weight + ':' + angle + ':'\n                + std::to_string (search_code_point), size);\n    ft_cache::const_iterator it = m_cache.find (key);\n\n    if (it != m_cache.end ())\n      {\n        FT_Reference_Face (it->second);\n        return it->second;\n      }\n#endif\n\n    static std::string fonts_dir;\n\n    if (fonts_dir.empty ())\n      {\n        fonts_dir = sys::env::getenv (\"OCTAVE_FONTS_DIR\");\n\n        if (fonts_dir.empty ())\n#if defined (SYSTEM_FREEFONT_DIR)\n          fonts_dir = SYSTEM_FREEFONT_DIR;\n#else\n          fonts_dir = config::oct_fonts_dir ();\n#endif\n      }\n\n\n    // Default font file\n    std::string file;\n\n    if (! fonts_dir.empty ())\n      {\n        file = fonts_dir + sys::file_ops::dir_sep_str () + \"FreeSans\";\n\n        if (weight == \"bold\")\n          file += \"Bold\";\n\n        if (angle == \"italic\" || angle == \"oblique\")\n          file += \"Oblique\";\n\n        file += \".otf\";\n      }\n\n#if defined (HAVE_FONTCONFIG)\n    if ((search_code_point != 0 || name != \"*\") && m_fontconfig_initialized)\n      {\n        int fc_weight, fc_angle;\n\n        if (weight == \"bold\")\n          fc_weight = FC_WEIGHT_BOLD;\n        else\n          fc_weight = FC_WEIGHT_NORMAL;\n\n        if (angle == \"italic\")\n          fc_angle = FC_SLANT_ITALIC;\n        else if (angle == \"oblique\")\n          fc_angle = FC_SLANT_OBLIQUE;\n        else\n          fc_angle = FC_SLANT_ROMAN;\n\n        FcPattern *pat = FcPatternCreate ();\n\n        FcPatternAddString (pat, FC_FAMILY,\n                            (reinterpret_cast<const FcChar8 *>\n                             (name.c_str ())));\n\n        FcPatternAddInteger (pat, FC_WEIGHT, fc_weight);\n        FcPatternAddInteger (pat, FC_SLANT, fc_angle);\n        FcPatternAddDouble (pat, FC_PIXEL_SIZE, size);\n\n        if (search_code_point > 0)\n          {\n            FcCharSet *minimal_charset =  FcCharSetCreate ();\n            FcCharSetAddChar (minimal_charset,\n                              static_cast<FcChar32> (search_code_point));\n            FcPatternAddCharSet (pat, FC_CHARSET, minimal_charset);\n          }\n\n        if (FcConfigSubstitute (nullptr, pat, FcMatchPattern))\n          {\n            FcResult res;\n            FcPattern *match;\n\n            FcDefaultSubstitute (pat);\n\n            match = FcFontMatch (nullptr, pat, &res);\n\n            // FIXME: originally, this test also required that\n            // res != FcResultNoMatch.  Is that really needed?\n            if (match)\n              {\n                unsigned char *tmp;\n\n                FcPatternGetString (match, FC_FILE, 0, &tmp);\n                file = reinterpret_cast<char *> (tmp);\n              }\n            else\n              ::warning (\"could not match any font: %s-%s-%s-%g, using default font\",\n                         name.c_str (), weight.c_str (), angle.c_str (),\n                         size);\n\n            if (match)\n              FcPatternDestroy (match);\n          }\n\n        FcPatternDestroy (pat);\n      }\n#endif\n\n    if (file.empty ())\n      ::warning (\"unable to find default font files\");\n    else\n      {\n        std::string ascii_file = sys::get_ASCII_filename (file);\n\n        if (FT_New_Face (m_library, ascii_file.c_str (), 0, &retval))\n          ::warning (\"ft_manager: unable to load font: %s\", file.c_str ());\n#if defined (HAVE_FT_REFERENCE_FACE)\n        else\n          {\n            // Install a finalizer to notify ft_manager that the font is\n            // being destroyed.  The class ft_manager only keeps weak\n            // references to font objects.\n\n            retval->generic.data = new ft_key (key);\n            retval->generic.finalizer = ft_face_destroyed;\n\n            // Insert loaded font into the cache.\n            if (FT_Reference_Face (retval) == 0)\n              m_cache[key] = retval;\n          }\n#endif\n      }\n\n    return retval;\n  }\n\n  void do_font_destroyed (FT_Face face)\n  {\n    if (face->generic.data)\n      {\n        ft_key *pkey = reinterpret_cast<ft_key *> (face->generic.data);\n\n        m_cache.erase (*pkey);\n        delete pkey;\n        face->generic.data = nullptr;\n        FT_Done_Face (face);\n      }\n  }\n\n  //--------\n\n  static ft_manager *s_instance;\n\n  // Cache the fonts loaded by FreeType.  This cache only contains\n  // weak references to the fonts, strong references are only present\n  // in class text_renderer.\n  ft_cache m_cache;\n\n  FT_Library m_library;\n  bool m_freetype_initialized;\n  bool m_fontconfig_initialized;\n};\n\nft_manager *ft_manager::s_instance = nullptr;\n\nstatic void\nft_face_destroyed (void *object)\n{\n  ft_manager::font_destroyed (reinterpret_cast<FT_Face> (object));\n}\n\nclass OCTINTERP_API ft_text_renderer : public base_text_renderer\n{\npublic:\n\n  enum\n  {\n    MODE_BBOX   = 0,\n    MODE_RENDER = 1\n  };\n\npublic:\n\n  ft_text_renderer ()\n    : base_text_renderer (), m_font (), m_bbox (1, 4, 0.0), m_halign (0),\n      m_xoffset (0), m_line_yoffset (0), m_yoffset (0), m_mode (MODE_BBOX),\n      m_color (dim_vector (1, 3), 0), m_do_strlist (false), m_strlist (),\n      m_line_xoffset (0), m_ymin (0), m_ymax (0), m_deltax (0),\n      m_max_fontsize (0), m_antialias (true)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (ft_text_renderer)\n\n  ~ft_text_renderer () = default;\n\n  void visit (text_element_string& e);\n\n  void visit (text_element_list& e);\n\n  void visit (text_element_subscript& e);\n\n  void visit (text_element_superscript& e);\n\n  void visit (text_element_color& e);\n\n  void visit (text_element_fontsize& e);\n\n  void visit (text_element_fontname& e);\n\n  void visit (text_element_fontstyle& e);\n\n  void visit (text_element_symbol& e);\n\n  void visit (text_element_combined& e);\n\n  void reset ();\n\n  uint8NDArray get_pixels () const { return m_pixels; }\n\n  Matrix get_boundingbox () const { return m_bbox; }\n\n  uint8NDArray render (text_element *elt, Matrix& box,\n                       int rotation = ROTATION_0);\n\n  Matrix get_extent (text_element *elt, double rotation = 0.0);\n  Matrix get_extent (const std::string& txt, double rotation,\n                     const caseless_str& interpreter);\n\n  void set_anti_aliasing (bool val) { m_antialias = val; };\n\n  void set_font (const std::string& name, const std::string& weight,\n                 const std::string& angle, double size);\n\n  octave_map get_system_fonts ();\n\n  void set_color (const Matrix& c);\n\n  void set_mode (int m);\n\n  void text_to_pixels (const std::string& txt,\n                       uint8NDArray& pxls, Matrix& bbox,\n                       int halign, int valign, double rotation,\n                       const caseless_str& interpreter,\n                       bool handle_rotation);\n\nprivate:\n\n  // Class to hold information about fonts and a strong\n  // reference to the font objects loaded by FreeType.\n\n  class ft_font : public text_renderer::font\n  {\n  public:\n\n    ft_font ()\n      : text_renderer::font (), m_face (nullptr) { }\n\n    ft_font (const std::string& nm, const std::string& wt,\n             const std::string& ang, double sz, FT_Face f = nullptr)\n      : text_renderer::font (nm, wt, ang, sz), m_face (f)\n    { }\n\n    ft_font (const ft_font& ft);\n\n    ~ft_font ()\n    {\n      if (m_face)\n        FT_Done_Face (m_face);\n    }\n\n    ft_font& operator = (const ft_font& ft);\n\n    bool is_valid () const { return get_face (); }\n\n    FT_Face get_face () const;\n\n  private:\n\n    mutable FT_Face m_face;\n  };\n\n  void push_new_line ();\n\n  void update_line_bbox ();\n\n  void compute_bbox ();\n\n  int compute_line_xoffset (const Matrix& lb) const;\n\n  FT_UInt process_character (FT_ULong code, FT_UInt previous,\n                             std::string& sub_font);\n\npublic:\n\n  void text_to_strlist (const std::string& txt,\n                        std::list<text_renderer::string>& lst, Matrix& bbox,\n                        int halign, int valign, double rotation,\n                        const caseless_str& interp);\n\nprivate:\n\n  // The current font used by the renderer.\n  ft_font m_font;\n\n  // Used to stored the bounding box corresponding to the rendered text.\n  // The bounding box has the form [x, y, w, h] where x and y represent the\n  // coordinates of the bottom left corner relative to the anchor point of\n  // the text (== start of text on the baseline).  Due to font descent or\n  // multiple lines, the value y is usually negative.\n  Matrix m_bbox;\n\n  // Used to stored the rendered text.  It's a 3-D matrix with size MxNx4\n  // where M and N are the width and height of the bounding box.\n  uint8NDArray m_pixels;\n\n  // Used to store the bounding box of each line.  This is used to layout\n  // multiline text properly.\n  std::list<Matrix> m_line_bbox;\n\n  // The current horizontal alignment.  This is used to align multi-line text.\n  int m_halign;\n\n  // The X offset for the next glyph.\n  int m_xoffset;\n\n  // The Y offset of the baseline for the current line.\n  int m_line_yoffset;\n\n  // The Y offset of the baseline for the next glyph.  The offset is relative\n  // to line_yoffset.  The total Y offset is computed with:\n  // line_yoffset + yoffset.\n  int m_yoffset;\n\n  // The current mode of the rendering process (box computing or rendering).\n  int m_mode;\n\n  // The base color of the rendered text.\n  uint8NDArray m_color;\n\n  // A list of parsed strings to be used for printing.\n  bool m_do_strlist;\n  std::list<text_renderer::string> m_strlist;\n\n  // The X offset of the baseline for the current line.\n  int m_line_xoffset;\n\n  // Min and max y coordinates of all glyphs in a line.\n  FT_Pos m_ymin;\n  FT_Pos m_ymax;\n\n  // Difference between the advance and the actual extent of the latest glyph\n  FT_Pos m_deltax;\n\n  // Used for computing the distance between lines.\n  double m_max_fontsize;\n\n  // Anti-aliasing.\n  bool m_antialias;\n\n};\n\nvoid\nft_text_renderer::set_font (const std::string& name,\n                            const std::string& weight,\n                            const std::string& angle, double size)\n{\n  // FIXME: take \"fontunits\" into account\n  m_font = ft_font (name, weight, angle, size, nullptr);\n}\n\noctave_map\nft_text_renderer::get_system_fonts ()\n{\n  return ft_manager::get_system_fonts ();\n}\n\nvoid\nft_text_renderer::push_new_line ()\n{\n  switch (m_mode)\n    {\n    case MODE_BBOX:\n      {\n        // Create a new bbox entry based on the current font.\n\n        FT_Face face = m_font.get_face ();\n\n        if (face)\n          {\n            Matrix bb (1, 5, 0.0);\n\n            m_line_bbox.push_back (bb);\n\n            m_xoffset = m_yoffset = 0;\n            m_ymin = m_ymax = m_deltax = 0;\n          }\n      }\n      break;\n\n    case MODE_RENDER:\n      {\n        // Move to the next line bbox, adjust xoffset based on alignment\n        // and yoffset based on the old and new line bbox.\n\n        Matrix old_bbox = m_line_bbox.front ();\n        m_line_bbox.pop_front ();\n        Matrix new_bbox = m_line_bbox.front ();\n\n        m_xoffset = m_line_xoffset = compute_line_xoffset (new_bbox);\n        m_line_yoffset -= (-old_bbox(1) + math::round (0.4 * m_max_fontsize)\n                           + (new_bbox(3) + new_bbox(1)));\n        m_yoffset = 0;\n        m_ymin = m_ymax = m_deltax = 0;\n      }\n      break;\n    }\n}\n\nint\nft_text_renderer::compute_line_xoffset (const Matrix& lb) const\n{\n  if (! m_bbox.isempty ())\n    {\n      switch (m_halign)\n        {\n        case 0:\n          return 0;\n        case 1:\n          return (m_bbox(2) - lb(2)) / 2;\n        case 2:\n          return (m_bbox(2) - lb(2));\n        }\n    }\n\n  return 0;\n}\n\nvoid\nft_text_renderer::compute_bbox ()\n{\n  // Stack the various line bbox together and compute the final\n  // bounding box for the entire text string.\n\n  m_bbox = Matrix ();\n\n  switch (m_line_bbox.size ())\n    {\n    case 0:\n      break;\n\n    case 1:\n      m_bbox = m_line_bbox.front ().extract (0, 0, 0, 3);\n      break;\n\n    default:\n      for (const auto& lbox : m_line_bbox)\n        {\n          if (m_bbox.isempty ())\n            m_bbox = lbox.extract (0, 0, 0, 3);\n          else\n            {\n              double delta = math::round (0.4 * m_max_fontsize) + lbox(3);\n              m_bbox(1) -= delta;\n              m_bbox(3) += delta;\n              m_bbox(2) = math::max (m_bbox(2), lbox(2));\n            }\n        }\n      break;\n    }\n}\n\nvoid\nft_text_renderer::update_line_bbox ()\n{\n  // Called after a font change, when in MODE_BBOX mode, to update the\n  // current line bbox with the new font metrics.  This also includes the\n  // current yoffset, that is the offset of the current glyph's baseline\n  // the line's baseline.\n\n  if (m_mode == MODE_BBOX)\n    {\n      Matrix& bb = m_line_bbox.back ();\n      bb(1) = m_ymin;\n      // Add one pixel to the bbox height to avoid occasional text clipping.\n      // See bug #55328.\n      bb(3) = (m_ymax + 1) - m_ymin;\n      if (m_deltax > 0)\n        bb(2) += m_deltax;\n    }\n}\n\nvoid\nft_text_renderer::set_mode (int m)\n{\n  m_mode = m;\n\n  switch (m_mode)\n    {\n    case MODE_BBOX:\n      m_xoffset = m_line_yoffset = m_yoffset = 0;\n      m_max_fontsize = 0.0;\n      m_bbox = Matrix (1, 4, 0.0);\n      m_line_bbox.clear ();\n      push_new_line ();\n      break;\n\n    case MODE_RENDER:\n      if (m_bbox.numel () != 4)\n        {\n          ::error (\"ft_text_renderer: invalid bounding box, cannot render\");\n\n          m_xoffset = m_line_yoffset = m_yoffset = 0;\n          m_pixels = uint8NDArray ();\n        }\n      else\n        {\n          dim_vector d (4, octave_idx_type (m_bbox(2)),\n                        octave_idx_type (m_bbox(3)));\n          m_pixels = uint8NDArray (d, static_cast<uint8_t> (0));\n          m_xoffset = compute_line_xoffset (m_line_bbox.front ());\n          m_line_yoffset = -m_bbox(1);\n          m_yoffset = 0;\n        }\n      break;\n\n    default:\n      error (\"ft_text_renderer: invalid mode '%d'\", m_mode);\n      break;\n    }\n}\n\nbool\nis_opaque (const FT_GlyphSlot& glyph, const int x, const int y)\n{\n  // Borrowed from https://stackoverflow.com/questions/14800827/\n                         //    indexing-pixels-in-a-monochrome-freetype-glyph-buffer\n  int pitch = std::abs (glyph->bitmap.pitch);\n  unsigned char *row = &glyph->bitmap.buffer[pitch * y];\n  char cvalue = row[x >> 3];\n\n  return ((cvalue & (128 >> (x & 7))) != 0);\n}\n\nFT_UInt\nft_text_renderer::process_character (FT_ULong code, FT_UInt previous,\n                                     std::string& sub_name)\n{\n  FT_Face face = m_font.get_face ();\n\n  sub_name = face->family_name;\n\n  FT_UInt glyph_index = 0;\n\n  if (face)\n    {\n      glyph_index = FT_Get_Char_Index (face, code);\n\n      if (code != '\\n' && code != '\\t'\n          && (! glyph_index\n              || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)))\n        {\n#if defined (HAVE_FONTCONFIG)\n          // Try to substitue font\n          FT_Face sub_face = ft_manager::get_font (m_font.get_name (),\n                             m_font.get_weight (),\n                             m_font.get_angle (),\n                             m_font.get_size (),\n                             code);\n\n          if (sub_face)\n            {\n              FT_Set_Char_Size (sub_face, 0, m_font.get_size ()*64, 0, 0);\n\n              glyph_index = FT_Get_Char_Index (sub_face, code);\n\n              if (glyph_index\n                  && (FT_Load_Glyph (sub_face, glyph_index, FT_LOAD_DEFAULT)\n                      == 0))\n                {\n                  static std::string prev_sub_name;\n\n                  if (prev_sub_name.empty ()\n                      || prev_sub_name != std::string (sub_face->family_name))\n                    {\n                      prev_sub_name = sub_face->family_name;\n                      warning_with_id (\"Octave:substituted-glyph\",\n                                       \"text_renderer: substituting font to '%s' for some characters\",\n                                       sub_face->family_name);\n                    }\n\n                  ft_font saved_font = m_font;\n\n                  m_font = ft_font (m_font.get_name (), m_font.get_weight (),\n                                    m_font.get_angle (), m_font.get_size (),\n                                    sub_face);\n\n                  process_character (code, previous, sub_name);\n\n                  m_font = saved_font;\n                }\n              else\n                {\n                  glyph_index = 0;\n                  warn_missing_glyph (code);\n                }\n            }\n          else\n            {\n              glyph_index = 0;\n              warn_missing_glyph (code);\n            }\n#else\n          glyph_index = 0;\n          warn_missing_glyph (code);\n#endif\n        }\n      else if ((code == '\\n') || (code == '\\t'))\n        {\n          glyph_index = FT_Get_Char_Index (face, ' ');\n          if (! glyph_index\n              || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))\n            {\n              glyph_index = 0;\n              warn_missing_glyph (' ');\n            }\n          else if (code == '\\n')\n            push_new_line ();\n          else\n            {\n              // Advance to next multiple of 4 times the width of the \"space\"\n              // character.\n              int x_tab = 4 * (face->glyph->advance.x >> 6);\n              m_xoffset = (1 + std::floor (1. * m_xoffset / x_tab)) * x_tab;\n            }\n        }\n      else\n        {\n          switch (m_mode)\n            {\n            case MODE_RENDER:\n              if (FT_Render_Glyph (face->glyph, (m_antialias\n                                                 ? FT_RENDER_MODE_NORMAL\n                                                 : FT_RENDER_MODE_MONO)))\n                {\n                  glyph_index = 0;\n                  warn_glyph_render (code);\n                }\n              else\n                {\n                  FT_Bitmap& bitmap = face->glyph->bitmap;\n                  int x0, y0;\n\n                  if (previous)\n                    {\n                      FT_Vector delta;\n\n                      FT_Get_Kerning (face, previous, glyph_index,\n                                      FT_KERNING_DEFAULT, &delta);\n\n                      m_xoffset += (delta.x >> 6);\n                    }\n\n                  x0 = m_xoffset + face->glyph->bitmap_left;\n                  y0 = m_line_yoffset + m_yoffset\n                       + (face->glyph->bitmap_top - 1);\n\n                  // 'w' seems to have a negative -1\n                  // face->glyph->bitmap_left, this is so we don't index out\n                  // of bound, and assumes we've allocated the right amount of\n                  // horizontal space in the bbox.\n                  if (x0 < 0)\n                    x0 = 0;\n\n                  for (int r = 0; static_cast<unsigned int> (r) < bitmap.rows; r++)\n                    for (int c = 0; static_cast<unsigned int> (c) < bitmap.width; c++)\n                      {\n                        unsigned char pix\n                          = (m_antialias\n                             ? bitmap.buffer[r*bitmap.width+c]\n                             : (is_opaque (face->glyph, c, r) ? 255 : 0));\n\n                        if (x0+c < 0 || x0+c >= m_pixels.dim2 ()\n                            || y0-r < 0 || y0-r >= m_pixels.dim3 ())\n                          {\n                            // ::warning (\"ft_text_renderer: x %d,  y %d\",\n                            //            x0+c, y0-r);\n                          }\n                        else if (m_pixels(3, x0+c, y0-r).value () == 0)\n                          {\n                            m_pixels(0, x0+c, y0-r) = m_color(0);\n                            m_pixels(1, x0+c, y0-r) = m_color(1);\n                            m_pixels(2, x0+c, y0-r) = m_color(2);\n                            m_pixels(3, x0+c, y0-r) = pix;\n                          }\n                      }\n\n                  m_xoffset += (face->glyph->advance.x >> 6);\n                }\n              break;\n\n            case MODE_BBOX:\n              Matrix& bb = m_line_bbox.back ();\n\n              // If we have a previous glyph, use kerning information.  This\n              // usually means moving a bit backward before adding the next\n              // glyph.  That is, \"delta.x\" is usually < 0.\n              if (previous)\n                {\n                  FT_Vector delta;\n\n                  FT_Get_Kerning (face, previous, glyph_index,\n                                  FT_KERNING_DEFAULT, &delta);\n\n                  m_xoffset += (delta.x >> 6);\n                }\n\n              // Extend current X offset box by the width of the current\n              // glyph.  Then extend the line bounding box if necessary.\n\n              m_xoffset += (face->glyph->advance.x >> 6);\n              bb(2) = math::max (bb(2), m_xoffset);\n\n              // Store the actual bbox vertical coordinates of this character\n              FT_Glyph glyph;\n              if (FT_Get_Glyph (face->glyph, &glyph))\n                warn_glyph_render (code);\n              else\n                {\n                  FT_BBox glyph_bbox;\n                  FT_Glyph_Get_CBox (glyph, FT_GLYPH_BBOX_UNSCALED,\n                                     &glyph_bbox);\n                  m_deltax = (glyph_bbox.xMax - face->glyph->advance.x) >> 6;\n                  m_ymin = math::min ((glyph_bbox.yMin >> 6) + m_yoffset,\n                                      m_ymin);\n                  m_ymax = math::max ((glyph_bbox.yMax >> 6) + m_yoffset,\n                                      m_ymax);\n                  FT_Done_Glyph (glyph);\n                  update_line_bbox ();\n                }\n              break;\n            }\n        }\n    }\n\n  return glyph_index;\n}\n\nvoid\nft_text_renderer::text_to_strlist (const std::string& txt,\n                                   std::list<text_renderer::string>& lst,\n                                   Matrix& box,\n                                   int ha, int va, double rot,\n                                   const caseless_str& interp)\n{\n  uint8NDArray pxls;\n\n  // First run text_to_pixels which will also build the string list\n\n  m_strlist = std::list<text_renderer::string> ();\n\n  unwind_protect_var<bool> restore_var1 (m_do_strlist);\n  unwind_protect_var<std::list<text_renderer::string>>\n      restore_var2 (m_strlist);\n\n  m_do_strlist = true;\n\n  text_to_pixels (txt, pxls, box, ha, va, rot, interp, false);\n\n  lst = m_strlist;\n}\n\nvoid\nft_text_renderer::visit (text_element_string& e)\n{\n  if (m_font.is_valid ())\n    {\n      m_max_fontsize = std::max (m_max_fontsize, m_font.get_size ());\n      FT_UInt glyph_index, previous = 0;\n\n      std::string str = e.string_value ();\n      const uint8_t *c = reinterpret_cast<const uint8_t *> (str.c_str ());\n      uint32_t u32_c;\n\n      std::size_t n = str.size ();\n      std::size_t icurr = 0;\n      std::size_t ibegin = 0;\n\n      // Initialize a new string\n      text_renderer::string fs (str, m_font, m_xoffset, m_yoffset);\n\n      std::string fname = m_font.get_face ()->family_name;\n\n      if (fname.find (\" \") != std::string::npos)\n        fname = \"'\" + fname + \"'\";\n\n      fs.set_family (fname);\n\n      std::vector<double> xdata;\n      std::string sub_name;\n\n      while (n > 0)\n        {\n          // Retrieve the length and the u32 representation of the current\n          // character\n          int mblen = octave_u8_strmbtouc_wrapper (&u32_c, c + icurr);\n          if (mblen < 1)\n            {\n              // This is not an UTF-8 character, use a replacement character\n              mblen = 1;\n              u32_c = 0xFFFD;\n            }\n\n          n -= mblen;\n\n          if (m_do_strlist && m_mode == MODE_RENDER)\n            {\n              if (u32_c == 10)\n                {\n                  // Finish previous string in m_strlist before processing\n                  // the newline character\n                  fs.set_y (m_line_yoffset + m_yoffset);\n                  fs.set_color (m_color);\n\n                  std::string s = str.substr (ibegin, icurr - ibegin);\n                  if (! s.empty ())\n                    {\n                      fs.set_string (s);\n                      fs.set_y (m_line_yoffset + m_yoffset);\n                      fs.set_xdata (xdata);\n                      fs.set_family (fname);\n                      m_strlist.push_back (fs);\n                    }\n                }\n              else\n                xdata.push_back (m_xoffset);\n            }\n\n          glyph_index = process_character (u32_c, previous, sub_name);\n\n          if (m_do_strlist && m_mode == MODE_RENDER && ! sub_name.empty ())\n            {\n              // Add substitution font to the family name stack\n              std::string tmp_family = fs.get_family ();\n\n              if (tmp_family.find (sub_name) == std::string::npos)\n                {\n                  if (sub_name.find (\" \") != std::string::npos)\n                    sub_name = \"'\" + sub_name + \"'\";\n\n                  fs.set_family (tmp_family + \", \" + sub_name);\n                }\n            }\n\n          if (u32_c == 10)\n            {\n              previous = 0;\n\n              if (m_do_strlist && m_mode == MODE_RENDER)\n                {\n                  // Start a new string in m_strlist\n                  ibegin = icurr+1;\n                  xdata.clear ();\n                  fs = text_renderer::string (str.substr (ibegin), m_font,\n                                              m_line_xoffset, m_yoffset);\n                }\n            }\n          else\n            previous = glyph_index;\n\n          icurr += mblen;\n        }\n\n      if (m_do_strlist && m_mode == MODE_RENDER\n          && ! fs.get_string ().empty ())\n        {\n          fs.set_y (m_line_yoffset + m_yoffset);\n          fs.set_color (m_color);\n          fs.set_xdata (xdata);\n          m_strlist.push_back (fs);\n        }\n    }\n}\n\nvoid\nft_text_renderer::visit (text_element_list& e)\n{\n  // Save and restore (after processing the list) the current font and color.\n\n  ft_font saved_font (m_font);\n  uint8NDArray saved_color (m_color);\n\n  text_processor::visit (e);\n\n  m_font = saved_font;\n  m_color = saved_color;\n}\n\nvoid\nft_text_renderer::visit (text_element_subscript& e)\n{\n  ft_font saved_font (m_font);\n  int saved_line_yoffset = m_line_yoffset;\n  int saved_yoffset = m_yoffset;\n\n  double sz = m_font.get_size ();\n\n  // Reducing font size by 70% produces decent results.\n  set_font (m_font.get_name (), m_font.get_weight (), m_font.get_angle (),\n            std::max (5.0, sz * 0.7));\n\n  if (m_font.is_valid ())\n    {\n      // Shifting the baseline by 15% of the font size gives decent results.\n      m_yoffset -= std::ceil (sz * 0.15);\n\n      if (m_mode == MODE_BBOX)\n        update_line_bbox ();\n    }\n\n  text_processor::visit (e);\n\n  m_font = saved_font;\n  // If line_yoffset changed, this means we moved to a new line; hence yoffset\n  // cannot be restored, because the saved value is not relevant anymore.\n  if (m_line_yoffset == saved_line_yoffset)\n    m_yoffset = saved_yoffset;\n}\n\nvoid\nft_text_renderer::visit (text_element_superscript& e)\n{\n  ft_font saved_font (m_font);\n  int saved_line_yoffset = m_line_yoffset;\n  int saved_yoffset = m_yoffset;\n\n  double sz = m_font.get_size ();\n\n  // Reducing font size by 70% produces decent results.\n  set_font (m_font.get_name (), m_font.get_weight (), m_font.get_angle (),\n            std::max (5.0, sz * 0.7));\n\n  if (saved_font.is_valid ())\n    {\n      // Shifting the baseline by 40% of the font size gives decent results.\n      m_yoffset += std::ceil (sz * 0.4);\n\n      if (m_mode == MODE_BBOX)\n        update_line_bbox ();\n    }\n\n  text_processor::visit (e);\n\n  m_font = saved_font;\n  // If line_yoffset changed, this means we moved to a new line; hence yoffset\n  // cannot be restored, because the saved value is not relevant anymore.\n  if (m_line_yoffset == saved_line_yoffset)\n    m_yoffset = saved_yoffset;\n}\n\nvoid\nft_text_renderer::visit (text_element_color& e)\n{\n  if (m_mode == MODE_RENDER)\n    set_color (e.get_color ());\n}\n\nvoid\nft_text_renderer::visit (text_element_fontsize& e)\n{\n  double sz = e.get_fontsize ();\n\n  // FIXME: Matlab documentation says that the font size is expressed\n  //        in the text object FontUnit.\n\n  set_font (m_font.get_name (), m_font.get_weight (),\n            m_font.get_angle (), sz);\n\n  if (m_mode == MODE_BBOX)\n    update_line_bbox ();\n}\n\nvoid\nft_text_renderer::visit (text_element_fontname& e)\n{\n  set_font (e.get_fontname (), m_font.get_weight (), m_font.get_angle (),\n            m_font.get_size ());\n\n  if (m_mode == MODE_BBOX)\n    update_line_bbox ();\n}\n\nvoid\nft_text_renderer::visit (text_element_fontstyle& e)\n{\n  switch (e.get_fontstyle ())\n    {\n    case text_element_fontstyle::normal:\n      set_font (m_font.get_name (), \"normal\", \"normal\", m_font.get_size ());\n      break;\n\n    case text_element_fontstyle::bold:\n      set_font (m_font.get_name (), \"bold\", \"normal\", m_font.get_size ());\n      break;\n\n    case text_element_fontstyle::italic:\n      set_font (m_font.get_name (), \"normal\", \"italic\", m_font.get_size ());\n      break;\n\n    case text_element_fontstyle::oblique:\n      set_font (m_font.get_name (), \"normal\", \"oblique\", m_font.get_size ());\n      break;\n    }\n\n  if (m_mode == MODE_BBOX)\n    update_line_bbox ();\n}\n\nvoid\nft_text_renderer::visit (text_element_symbol& e)\n{\n  uint32_t code = e.get_symbol_code ();\n\n  std::vector<double> xdata (1, m_xoffset);\n  text_renderer::string fs (\"-\", m_font, m_xoffset, m_yoffset);\n\n  if (code != text_element_symbol::invalid_code && m_font.is_valid ())\n    {\n      std::string sub_name;\n\n      process_character (code, 0, sub_name);\n\n      if (m_do_strlist && m_mode == MODE_RENDER)\n        {\n          if (! sub_name.empty ())\n            {\n              // Add substitution font to the family name\n              std::string tmp_family = fs.get_family ();\n\n              if (tmp_family.find (sub_name) == std::string::npos)\n                {\n                  if (sub_name.find (\" \") != std::string::npos)\n                    sub_name = \"'\" + sub_name + \"'\";\n\n                  fs.set_family (tmp_family + \", \" + sub_name);\n                }\n            }\n\n          fs.set_code (code);\n          fs.set_xdata (xdata);\n        }\n    }\n  else if (m_font.is_valid ())\n    ::warning (\"ignoring unknown symbol: %d\", e.get_symbol ());\n\n  if (m_do_strlist && m_mode == MODE_RENDER && fs.get_code ())\n    {\n      fs.set_y (m_line_yoffset + m_yoffset);\n      fs.set_color (m_color);\n      fs.set_family (m_font.get_face ()->family_name);\n      m_strlist.push_back (fs);\n    }\n}\n\nvoid\nft_text_renderer::visit (text_element_combined& e)\n{\n  int saved_xoffset = m_xoffset;\n  int max_xoffset = m_xoffset;\n\n  for (auto *txt_elt : e)\n    {\n      m_xoffset = saved_xoffset;\n      txt_elt->accept (*this);\n      max_xoffset = math::max (m_xoffset, max_xoffset);\n    }\n\n  m_xoffset = max_xoffset;\n}\n\nvoid\nft_text_renderer::reset ()\n{\n  set_mode (MODE_BBOX);\n  set_color (Matrix (1, 3, 0.0));\n  m_strlist = std::list<text_renderer::string> ();\n}\n\nvoid\nft_text_renderer::set_color (const Matrix& c)\n{\n  if (c.numel () == 3)\n    {\n      m_color(0) = static_cast<uint8_t> (c(0)*255);\n      m_color(1) = static_cast<uint8_t> (c(1)*255);\n      m_color(2) = static_cast<uint8_t> (c(2)*255);\n    }\n  else\n    ::warning (\"ft_text_renderer::set_color: invalid color\");\n}\n\nuint8NDArray\nft_text_renderer::render (text_element *elt, Matrix& box, int rotation)\n{\n  set_mode (MODE_BBOX);\n  elt->accept (*this);\n  compute_bbox ();\n  box = m_bbox;\n\n  set_mode (MODE_RENDER);\n\n  if (m_pixels.numel () > 0)\n    {\n      elt->accept (*this);\n\n      rotate_pixels (m_pixels, rotation);\n    }\n\n  return m_pixels;\n}\n\n// Note:\n// x-extent accurately measures width of glyphs.\n// y-extent is overly large because it is measured from baseline-to-baseline.\n// Calling routines, such as ylabel, may need to account for this mismatch.\n\nMatrix\nft_text_renderer::get_extent (text_element *elt, double rotation)\n{\n  set_mode (MODE_BBOX);\n  elt->accept (*this);\n  compute_bbox ();\n\n  Matrix extent (1, 2, 0.0);\n\n  switch (rotation_to_mode (rotation))\n    {\n    case ROTATION_0:\n    case ROTATION_180:\n      extent(0) = m_bbox(2);\n      extent(1) = m_bbox(3);\n      break;\n\n    case ROTATION_90:\n    case ROTATION_270:\n      extent(0) = m_bbox(3);\n      extent(1) = m_bbox(2);\n    }\n\n  return extent;\n}\n\nMatrix\nft_text_renderer::get_extent (const std::string& txt, double rotation,\n                              const caseless_str& interpreter)\n{\n  text_element *elt = text_parser::parse (txt, interpreter);\n  Matrix extent = get_extent (elt, rotation);\n  delete elt;\n\n  return extent;\n}\n\nvoid\nft_text_renderer::text_to_pixels (const std::string& txt,\n                                  uint8NDArray& pxls, Matrix& box,\n                                  int _halign, int valign, double rotation,\n                                  const caseless_str& interpreter,\n                                  bool handle_rotation)\n{\n  int rot_mode = rotation_to_mode (rotation);\n\n  m_halign = _halign;\n\n  text_element *elt = text_parser::parse (txt, interpreter);\n  pxls = render (elt, box, rot_mode);\n  delete elt;\n\n  if (pxls.isempty ())\n    return;  // nothing to render\n\n  // Move X0 and Y0 depending on alignments and eventually swap all values\n  // for text rotated 90° 180° or 270°\n  fix_bbox_anchor (box, m_halign, valign, rot_mode, handle_rotation);\n}\n\nft_text_renderer::ft_font::ft_font (const ft_font& ft)\n  : text_renderer::font (ft), m_face (nullptr)\n{\n#if defined (HAVE_FT_REFERENCE_FACE)\n  FT_Face ft_face = ft.get_face ();\n\n  if (ft_face && FT_Reference_Face (ft_face) == 0)\n    m_face = ft_face;\n#endif\n}\n\nft_text_renderer::ft_font&\nft_text_renderer::ft_font::operator = (const ft_font& ft)\n{\n  if (&ft != this)\n    {\n      text_renderer::font::operator = (ft);\n\n      if (m_face)\n        {\n          FT_Done_Face (m_face);\n          m_face = nullptr;\n        }\n\n#if defined (HAVE_FT_REFERENCE_FACE)\n      FT_Face ft_face = ft.get_face ();\n\n      if (ft_face && FT_Reference_Face (ft_face) == 0)\n        m_face = ft_face;\n#endif\n    }\n\n  return *this;\n}\n\nFT_Face\nft_text_renderer::ft_font::get_face () const\n{\n  if (! m_face && ! m_name.empty ())\n    {\n      m_face = ft_manager::get_font (m_name, m_weight, m_angle, m_size);\n\n      if (m_face)\n        {\n          if (FT_Set_Char_Size (m_face, 0, m_size*64, 0, 0))\n            ::warning (\"ft_text_renderer: unable to set font size to %g\", m_size);\n        }\n      else\n        ::warning (\"ft_text_renderer: unable to load appropriate font\");\n    }\n\n  return m_face;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nbase_text_renderer *\nmake_ft_text_renderer ()\n{\n#if defined (HAVE_FREETYPE)\n  return new ft_text_renderer ();\n#else\n  return 0;\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/ft-text-renderer.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ft_text_renderer_h)\n#define octave_ft_text_renderer_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_text_renderer;\n\nextern base_text_renderer * make_ft_text_renderer ();\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/genprops.awk",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n##\n## Generate the graphics.h file from graphics.h.in and write the\n## output to stdout.\n##\n## If the variable emit_graphics_props is set on the command line,\n## generate the graphics-props.cc file from graphics.h.in and write\n## the output to stdout.\n##\n## Lines between the BEGIN_PROPERTIES and END_PROPERTIES markers have\n## one of the following formats:\n##\n##   TYPE NAME\n##   TYPE NAME QUALIFIERS\n##   mutable TYPE NAME\n##   mutable TYPE NAME QUALIFIERS\n##\n## For each property, we generate a declaration for the property.\n##\n## If QUALIFIERS is omitted, we generate the following functions directly\n## in the class declaration:\n##\n##   TYPE\n##   get_NAME () const\n##   {\n##     return NAME;\n##   }\n##\n##   void\n##   set_NAME (const TYPE& val)\n##   {\n##     NAME = val;\n##   }\n##\n##   void\n##   set_NAME (const octave_value& val)\n##   {\n##     set_NAME (TYPE (val));\n##   }\n##\n## If present, the QUALIFIERS string may include any of the characters\n## g, G, m, s, S, o, O, h, d which have the following meanings:\n##\n##   g:  There is a custom inline definition for the get function,\n##       so we don't emit one.\n##\n##   G:  There is a custom extern definition for the get function,\n##       so we emit only the declaration.\n##\n##   s:  There is a custom inline definition for the type-specific set\n##       function, so we don't emit one.\n##\n##   S:  There is a custom extern definition for the type-specific set\n##       function, so we emit only the declaration.\n##\n##   d:  The property is deprecated and a warning is emitted when accessing it.\n##\n################################################################################\n##   'o','O','a' are currently not processed.  They are commented out in code.\n################################################################################\n##\n##   o:  There is a custom inline definition for the octave_value version\n##       of the set function, so we don't emit one.\n##\n##   O:  There is a custom extern definition for the octave_value version\n##       of the set function, so we emit only the declaration.\n##\n##   a:  The octave_value version of the set function will use assignment:\n##\n##         void\n##         set_NAME (const octave_value& val)\n##         {\n##           TYPE tmp (NAME);\n##           tmp = val;\n##           set_NAME (tmp);\n##         }\n##\n##       This is useful for things like the radio_value classes which\n##       use an overloaded assignment operator of the form\n##\n##         radio_property& operator = (const octave_value& val);\n##\n##       that preserves the list of possible values, which is different\n##       from what would happen if we simply used the\n##\n##         TYPE (const octave_value&)\n##\n##       constructor, which creates a new radio_property and so cannot\n##       preserve the old list of possible values.\n################################################################################\n##\n##   l:  Add the line\n##\n##         update_axis_limits (\"NAME\");\n##\n##       to the type-specific set function.\n##\n##   m:  Add the line\n##\n##         set_NAMEmode (\"manual\");\n##\n##       to the type-specific set function.\n##\n##   h:  Make the property hidden\n##\n##   r:  Make the property read-only.  A read-only property is not\n##       settable from the global set (caseless_str, octave_value)\n##       method, but still has set_X accessor.\n##\n##   u:  The property has an inline updater method.  This effectively\n##       add the line\n##\n##         update_NAME ();\n##\n##       to the type-specific set function.  This line is added before\n##       any other update call (like those added by the 'l' or 'm'\n##       modifiers.\n##\n##   U:  Like 'u' modifier except that the updater is not inline.\n##       A declaration for the updater function will be emitted.\n##\n##   f:  The property does not have any factory default value.\n##\n## The 'o' and 'O' qualifiers are only useful when the property type\n## is something other than octave_value.\n\n## simple accessor\n\nfunction emit_get_accessor (i, rtype, faccess)\n{\n  printf (\"  %s get_%s () const\", rtype, name[i]);\n\n  if (emit_get[i] == \"definition\" && deprecated[i])\n    printf (\"\\n  {\\n    warning_with_id (\\\"Octave:deprecated-property\\\",\\\"'%s' is deprecated and will be removed from a future version of Octave\\\");\\n    return m_%s.%s ();\\n  }\\n\", name[i], name[i], faccess);\n  else if (emit_get[i] == \"definition\")\n    printf (\" { return m_%s.%s (); }\\n\", name[i], faccess);\n  else\n    printf (\";\\n\");\n}\n\n## bool_property\n\nfunction emit_get_bool (i)\n{\n  printf (\"  bool is_%s () const\", name[i]);\n\n  if (emit_get[i] == \"definition\")\n    printf (\" { return m_%s.is_on (); }\\n\", name[i]);\n  else\n    printf (\";\\n\");\n\n  emit_get_accessor(i, \"std::string\", \"current_value\");\n}\n\n## radio_property\n\nfunction emit_get_radio (i)\n{\n  printf (\"  bool %s_is (const std::string& v) const\", name[i]);\n\n  if (emit_get[i] == \"definition\")\n    printf (\" { return m_%s.is (v); }\\n\", name[i]);\n  else\n    printf (\";\\n\");\n\n  emit_get_accessor(i, \"std::string\", \"current_value\");\n}\n\n## color_property\n\nfunction emit_get_color (i)\n{\n  printf (\"  bool %s_is_rgb () const { return m_%s.is_rgb (); }\\n\", name[i], name[i]);\n\n  printf (\"  bool %s_is (const std::string& v) const\", name[i]);\n\n  if (emit_get[i] == \"definition\")\n    printf (\" { return m_%s.is (v); }\\n\", name[i]);\n  else\n    printf (\";\\n\");\n\n  printf (\"  Matrix get_%s_rgb () const\", name[i]);\n\n  if (emit_get[i] == \"definition\")\n    printf (\" { return (m_%s.is_rgb () ? m_%s.rgb () : Matrix ()); }\\n\", name[i], name[i]);\n  else\n    printf (\";\\n\");\n\n  emit_get_accessor(i, \"octave_value\", \"get\");\n}\n\n## double_radio_property\n\nfunction emit_get_double_radio (i)\n{\n  printf (\"  bool %s_is_double () const { return m_%s.is_double (); }\\n\", name[i], name[i]);\n\n  printf (\"  bool %s_is (const std::string& v) const\", name[i]);\n\n  if (emit_get[i] == \"definition\")\n    printf (\" { return m_%s.is (v); }\\n\", name[i]);\n  else\n    printf (\";\\n\");\n\n  printf (\"  double get_%s_double () const\", name[i]);\n\n  if (emit_get[i] == \"definition\")\n    printf (\" { return (m_%s.is_double () ? m_%s.double_value () : 0); }\\n\", name[i], name[i]);\n  else\n    printf (\";\\n\");\n\n  emit_get_accessor(i, \"octave_value\", \"get\");\n}\n\n## callback_property\n\nfunction emit_get_callback (i)\n{\n  printf (\"  void execute_%s (const octave_value& new_data = octave_value ()) const\", name[i]);\n\n  if (emit_get[i] == \"definition\")\n    printf (\" { m_%s.execute (new_data); }\\n\", name[i]);\n  else\n    printf (\";\\n\");\n\n  emit_get_accessor(i, \"octave_value\", \"get\");\n}\n\n## array_property\n\nfunction emit_get_array (i)\n{\n  emit_get_accessor(i, \"octave_value\", \"get\");\n}\n\n## string_array_property\n\nfunction emit_get_string_array (i)\n{\n  printf (\"  std::string get_%s_string () const\", name[i]);\n\n  if (emit_get[i] == \"definition\")\n    printf (\" { return m_%s.string_value (); }\\n\", name[i]);\n  else\n    printf (\";\\n\");\n\n  printf (\"  string_vector get_%s_vector () const\", name[i]);\n\n  if (emit_get[i] == \"definition\")\n    printf (\" { return m_%s.string_vector_value (); }\\n\", name[i]);\n  else\n    printf (\";\\n\");\n\n  emit_get_accessor(i, \"octave_value\", \"get\");\n}\n\n## common section\n\nfunction emit_common_declarations ()\n{\n  printf (\"public:\\n\");\n  printf (\"  properties (const graphics_handle& mh, const graphics_handle& p);\\n\\n\");\n  printf (\"  properties () = delete;\\n\\n\");\n  printf (\"  OCTAVE_DISABLE_COPY_MOVE (properties)\\n\\n\");\n  printf (\"  ~properties () = default;\\n\\n\");\n  printf (\"  void set (const caseless_str& pname, const octave_value& val);\\n\\n\");\n  printf (\"  octave_value get (bool all = false) const;\\n\\n\");\n  printf (\"  octave_value get (const caseless_str& pname) const;\\n\\n\");\n  printf (\"  octave_value get (const std::string& pname) const\\n  {\\n    return get (caseless_str (pname));\\n  }\\n\\n\");\n  printf (\"  octave_value get (const char *pname) const\\n  {\\n    return get (caseless_str (pname));\\n  }\\n\\n\");\n  printf (\"  property get_property (const caseless_str& pname);\\n\\n\");\n  printf (\"  std::string graphics_object_name () const { return s_go_name; }\\n\\n\");\n  printf (\"  static property_list::pval_map_type factory_defaults ();\\n\\n\");\n  printf (\"private:\\n  static std::string s_go_name;\\n\\n\");\n}\n\nfunction emit_declarations ()\n{\n  if (class_name && ! base)\n    emit_common_declarations();\n\n  printf (\"public:\\n\\n\\n  static std::set<std::string> core_property_names ();\\n\\n  static std::set<std::string> readonly_property_names ();\\n\\n  static bool has_core_property (const caseless_str& pname);\\n\\n  static bool has_readonly_property (const caseless_str& pname);\\n\\n  std::set<std::string> all_property_names () const;\\n\\n\");\n\n  if (! base)\n    printf (\"  bool has_property (const caseless_str& pname) const;\\n\\n\");\n\n  if (idx > 0)\n    print (base ? \"protected:\\n\" : \"private:\\n\");\n\n  for (i = 1; i <= idx; i++)\n    printf (\"  %s%s m_%s;\\n\", mutable[i] ? \"mutable \" : \"\", type[i], name[i]);\n\n  if (idx > 0)\n    print \"\\npublic:\\n\";\n\n  if (idx > 0)\n  {\n    printf (\"  enum\\n  {\");\n    for (i = 1; i <= idx; i++)\n    {\n      printf (\"%s\\n    ID_%s = %d\", (i == 1 ? \"\" : \",\"), toupper(name[i]), pcount);\n      pcount++;\n    }\n    printf (\"\\n  };\\n\\n\");\n    pcount = (int(pcount/1000)+1)*1000;\n  }\n\n  for (i = 1; i <= idx; i++)\n  {\n    if (emit_get[i])\n    {\n      if (type[i] == \"any_property\")\n        emit_get_accessor(i, \"octave_value\", \"get\");\n      else if (type[i] == \"handle_property\")\n        emit_get_accessor(i, \"graphics_handle\", \"handle_value\");\n      else if (type[i] == \"string_property\")\n        emit_get_accessor(i, \"std::string\", \"string_value\");\n      else if (type[i] == \"text_label_property\")\n        emit_get_accessor(i, \"octave_value\", \"get\");\n      else if (type[i] == \"double_property\")\n        emit_get_accessor(i, \"double\", \"double_value\");\n      else if (type[i] == \"double_radio_property\")\n        emit_get_double_radio(i);\n      else if (type[i] == \"array_property\" \\\n               || type[i] == \"row_vector_property\")\n        emit_get_array(i);\n      else if (type[i] == \"bool_property\")\n        emit_get_bool(i);\n      else if (type[i] == \"radio_property\")\n        emit_get_radio(i);\n      else if (type[i] == \"color_property\")\n        emit_get_color(i);\n      else if (type[i] == \"callback_property\")\n        emit_get_callback(i);\n      else if (type[i] == \"string_array_property\")\n        emit_get_string_array(i);\n      else\n      {\n        printf (\"  %s get_%s () const\", type[i], name[i]);\n\n        if (emit_get[i] == \"definition\")\n          printf (\" { return m_%s; }\\n\", name[i]);\n        else\n          printf (\";\\n\");\n      }\n      printf (\"\\n\");\n    }\n  }\n\n  if (idx > 0)\n    printf (\"\\n\");\n\n  for (i = 1; i <= idx; i++)\n  {\n    if (emit_set[i])\n    {\n      ## Allow mutable properties to be set from const methods by\n      ## declaring the corresponding set method const.  The idea here is\n      ## to allow \"constant\" properties to be set after initialization.\n      ## For example, info about the OpenGL context for a figure can\n      ## only be set once the context is established, and that happens\n      ## after the figure object is created.  Properties handled this\n      ## way should probably also be declared read only.\n\n      printf (\"  void set_%s (const octave_value& val)%s\",\n              name[i], mutable[i] ? \" const\" : \"\");\n\n      if (emit_set[i] == \"definition\")\n      {\n        if (updaters[i] || limits[i] || mode[i])\n          has_builtin_listeners = 1;\n        else\n          has_builtin_listeners = 0;\n\n        printf (\"\\n  {\\n    if (m_%s.set (val, %s))\\n      {\\n\",\n          name[i], (has_builtin_listeners ? \"false\" : \"true\"));\n        if (mode[i])\n          printf (\"        set_%smode (\\\"manual\\\");\\n\", name[i]);\n        if (updater[i])\n          printf (\"        update_%s ();\\n\", name[i]);\n        if (deprecated[i])\n          printf (\"        warning_with_id (\\\"Octave:deprecated-property\\\",\\\"'%s' is deprecated and will be removed from a future version of Octave\\\");\\n\", name[i]);\n        if (limits[i])\n          printf (\"        update_axis_limits (\\\"%s\\\");\\n\", name[i]);\n        if (has_builtin_listeners)\n          printf (\"        m_%s.run_listeners (GCB_POSTSET);\\n\", name[i]);\n        if (! mutable[i])\n          printf (\"        mark_modified ();\\n\");\n        printf (\"      }\\n\");\n        if (mode[i])\n          printf (\"    else\\n      set_%smode (\\\"manual\\\");\\n\", name[i]);\n        printf (\"  }\\n\\n\");\n      }\n      else\n        printf (\";\\n\\n\");\n    }\n\n    if (updater[i] == \"extern\")\n    {\n      printf (\"  void update_%s ();\\n\\n\", name[i]);\n    }\n\n##    if (emit_ov_set[i])\n##    {\n##      printf (\"  void set_%s (const octave_value& val)\", name[i]);\n##\n##      if (emit_ov_set[i] == \"definition\")\n##        printf (\" { set_%s (%s (val)); }\\n\\n\", name[i], type[i]);\n##      else if (emit_ov_set[i] == \"assignment\")\n##      {\n##        printf (\"\\n  {\\n    %s tmp (%s);\\n    tmp = val;\\n    set_%s (tmp);\\n  };\\n\\n\",\n##                type[i], name[i], name[i], name[i]);\n##      }\n##      else\n##        printf (\";\\n\");\n##    }\n  }\n\n##  if (idx > 0)\n##    print \"\\nprivate:\";\n}\n\nfunction emit_source ()\n{\n  if (class_name)\n  {\n    printf (\"// ******** %s ********\\n\\n\", class_name);\n\n    ## constructor\n\n    if (base)\n      printf (\"base_properties::base_properties (const std::string& ty, const graphics_handle& mh, const graphics_handle& p)\\n  : \");\n    else\n    {\n      printf (\"%s::properties::properties (const graphics_handle& mh, const graphics_handle& p)\\n\", class_name);\n      printf (\"  : base_properties (s_go_name, mh, p),\\n\");\n    }\n\n    for (i = 1; i <= idx; i++)\n    {\n      if (ptype[i])\n        printf (\"    m_%s (\\\"%s\\\", mh, %s)\", name[i], name[i], defval[i]);\n      else\n        printf (\"    m_%s (%s)\", name[i], defval[i]);\n      if (i < idx)\n        printf (\",\");\n      printf (\"\\n\");\n    }\n\n    printf (\"{\\n\");\n\n    for (i = 1; i <= idx; i++)\n    {\n      if (ptype[i])\n      {\n        printf (\"  m_%s.set_id (ID_%s);\\n\", name[i], toupper(name[i]));\n        if (hidden[i])\n          printf (\"  m_%s.set_hidden (true);\\n\", name[i]);\n      }\n    }\n\n    printf (\"  init ();\\n}\\n\\n\");\n\n    ## set method\n\n    if (base)\n      printf (\"void\\nbase_properties::set (const caseless_str& pname, const octave_value& val)\\n{\\n\");\n    else\n      printf (\"void\\n%s::properties::set (const caseless_str& pname_arg, const octave_value& val)\\n{\\n\",\n              class_name);\n\n    if (! base)\n        printf (\"  const std::set<std::string>& pnames = all_property_names ();\\n\\n  caseless_str pname = validate_property_name (\\\"set\\\", s_go_name, pnames, pname_arg);\\n\\n  if (has_readonly_property (pname))\\n    {\\n      error (\\\"set: \\\\\\\"%%s\\\\\\\" is read-only\\\", pname.c_str ());\\n      return;\\n    }\\n\\n\");\n\n    first = 1;\n\n    for (i = 1; i <= idx; i++)\n    {\n      if (! readonly[i])\n      {\n        printf (\"  %sif (pname.compare (\\\"%s\\\"))\\n    set_%s (val);\\n\",\n                (first == 0 ? \"else \" : \"\"), name[i], name[i]);\n        first = 0;\n      }\n    }\n\n    if (base)\n      printf (\"  else\\n    set_dynamic (pname, val);\\n}\\n\\n\");\n    else\n      printf (\"  else\\n    base_properties::set (pname, val);\\n}\\n\\n\");\n\n    ## get \"all\" method\n\n    if (base)\n    {\n      printf (\"octave_value\\nbase_properties::get (bool all) const\\n{\\n\");\n      printf (\"  octave_map m = get_dynamic (all).map_value ();\\n\\n\");\n    }\n    else\n    {\n      printf (\"octave_value\\n%s::properties::get (bool all) const\\n{\\n\", class_name);\n      printf (\"  octave_map m = base_properties::get (all).map_value ();\\n\\n\");\n    }\n\n    for (i = 1; i <= idx; i++)\n    {\n      if (hidden[i])\n        printf (\"  if (all)\\n    m.assign (\\\"%s\\\", octave_value (get_%s ()%s));\\n\", name[i], name[i],\n                (type[i] == \"handle_property\" || type[i] == \"graphics_handle\" ? \".as_octave_value ()\" : \"\"));\n      else\n        printf (\"  m.assign (\\\"%s\\\", octave_value (get_%s ()%s));\\n\", name[i], name[i],\n                (type[i] == \"handle_property\" || type[i] == \"graphics_handle\" ? \".as_octave_value ()\" : \"\"));\n    }\n\n    printf (\"\\n  return m;\\n}\\n\\n\");\n\n    ## get \"one\" method\n\n    if (base)\n      printf (\"octave_value\\nbase_properties::get (const caseless_str& pname) const\\n{\\n\");\n    else\n      printf (\"octave_value\\n%s::properties::get (const caseless_str& pname_arg) const\\n{\\n\",\n              class_name);\n    printf (\"  octave_value retval;\\n\\n\");\n\n    if (! base)\n      printf (\"  const std::set<std::string>& pnames = all_property_names ();\\n\\n  caseless_str pname = validate_property_name (\\\"get\\\", s_go_name, pnames, pname_arg);\\n\\n\");\n\n    for (i = 1; i<= idx; i++)\n    {\n      printf (\"  %sif (pname.compare (\\\"%s\\\"))\\n\",\n              (i > 1 ? \"else \" : \"\"), name[i]);\n      printf (\"    retval = get_%s ()%s;\\n\", name[i],\n              (type[i] == \"handle_property\" || type[i] == \"graphics_handle\" ? \".as_octave_value ()\" : \"\"));\n    }\n\n    if (base)\n      printf (\"  else\\n    retval = get_dynamic (pname);\\n\\n\");\n    else\n      printf (\"  else\\n    retval = base_properties::get (pname);\\n\\n\");\n    printf (\"  return retval;\\n}\\n\\n\");\n\n    ## get_property method\n\n    if (base)\n      printf (\"property\\nbase_properties::get_property (const caseless_str& pname)\\n{\\n\");\n    else\n      printf (\"property\\n%s::properties::get_property (const caseless_str& pname_arg)\\n{\\n\",\n              class_name);\n\n    if (! base)\n      printf (\"  const std::set<std::string>& pnames = all_property_names ();\\n\\n  caseless_str pname = validate_property_name (\\\"get\\\", s_go_name, pnames, pname_arg);\\n\\n\");\n\n    for (i = 1; i<= idx; i++)\n    {\n      if (ptype[i])\n      {\n        printf (\"  %sif (pname.compare (\\\"%s\\\"))\\n\",\n                (i > 1 ? \"else \" : \"\"), name[i]);\n        printf (\"    return property (&m_%s, true);\\n\", name[i]);\n      }\n    }\n\n    if (base)\n      printf (\"  else\\n    return get_property_dynamic (pname);\\n\");\n    else\n      printf (\"  else\\n    return base_properties::get_property (pname);\\n\");\n    printf (\"}\\n\\n\");\n\n\n    ## factory defaults method\n\n    if (base)\n    {\n      printf (\"property_list::pval_map_type\\nbase_properties::factory_defaults ()\\n{\\n\");\n      printf (\"  property_list::pval_map_type m;\\n\\n\");\n    }\n    else\n    {\n      printf (\"property_list::pval_map_type\\n%s::properties::factory_defaults ()\\n{\\n\",\n              class_name);\n      printf (\"  property_list::pval_map_type m = base_properties::factory_defaults ();\\n\\n\");\n    }\n\n    for (i = 1; i <= idx; i++)\n    {\n      if (factory[i])\n      {\n        dval = defval[i];\n        if (type[i] == \"radio_property\")\n        {\n          k = index (dval, \"{\");\n          dval = substr (dval, k+1);\n          l = index (dval, \"}\");\n          if (k > 0 && l > 0)\n            dval = \"\\\"\" substr (dval, 1, l-1) \"\\\"\";\n          else\n            dval = \"octave_value ()\";\n        }\n\n        printf (\"  m[\\\"%s\\\"] = %s%s;\\n\", name[i], dval,\n                (type[i] == \"handle_property\" || type[i] == \"graphics_handle\" ? \".as_octave_value ()\" : \"\"));\n      }\n    }\n\n    printf (\"\\n  return m;\\n}\\n\\n\");\n\n    ## s_go_name static field\n\n    if (! base)\n      printf (\"std::string %s::properties::s_go_name (\\\"%s\\\");\\n\\n\",\n              class_name, object_name);\n\n    ## core_property_names\n    printf (\"std::set<std::string>\\n\");\n    if (base)\n      printf (\"base_properties\");\n    else\n      printf (\"%s::properties\", class_name);\n    printf (\"::core_property_names ()\\n{\\n  static std::set<std::string> all_pnames;\\n\\n  static bool initialized = false;\\n\\n  if (! initialized)\\n    {\\n\");\n    for (i = 1; i <= idx; i++)\n      printf (\"      all_pnames.insert (\\\"%s\\\");\\n\", name[i]);\n    if (! base)\n      printf (\"\\n      std::set<std::string> base_pnames = base_properties::core_property_names ();\\n      all_pnames.insert (base_pnames.begin (), base_pnames.end ());\\n\");\n    printf (\"\\n      initialized = true;\\n    }\\n\\n  return all_pnames;\\n}\\n\\n\");\n    ## has_core_property\n    printf (\"bool\\n\");\n    if (base)\n      printf (\"base_properties\");\n    else\n      printf (\"%s::properties\", class_name);\n    printf (\"::has_core_property (const caseless_str& pname)\\n{\\n  std::set<std::string> pnames = core_property_names ();\\n\\n  return pnames.find (pname) != pnames.end ();\\n}\\n\\n\", class_name);\n\n    ## readonly_property_names\n    printf (\"std::set<std::string>\\n\");\n    if (base)\n      printf (\"base_properties\");\n    else\n      printf (\"%s::properties\", class_name);\n    printf (\"::readonly_property_names ()\\n{\\n  static std::set<std::string> all_pnames;\\n\\n  static bool initialized = false;\\n\\n  if (! initialized)\\n    {\\n\");\n    for (i = 1; i <= idx; i++)\n        if (readonly[i])\n        {\n            printf (\"      all_pnames.insert (\\\"%s\\\");\\n\", name[i]);\n        }\n    if (! base)\n      printf (\"\\n      std::set<std::string> base_pnames = base_properties::readonly_property_names ();\\n      all_pnames.insert (base_pnames.begin (), base_pnames.end ());\\n\");\n    printf (\"\\n      initialized = true;\\n    }\\n\\n  return all_pnames;\\n}\\n\\n\");\n    ## has_readonly_property\n    printf (\"bool\\n\");\n    if (base)\n      printf (\"base_properties\");\n    else\n      printf (\"%s::properties\", class_name);\n    printf (\"::has_readonly_property (const caseless_str& pname)\\n{\\n  std::set<std::string> pnames = readonly_property_names ();\\n\\n  return pnames.find (pname) != pnames.end ();\\n}\\n\\n\", class_name);\n\n    ## all_property_names\n    printf (\"std::set<std::string>\\n\");\n    if (base)\n        printf (\"base_properties\");\n    else\n      printf (\"%s::properties\", class_name);\n    printf (\"::all_property_names () const\\n{\\n  static std::set<std::string> all_pnames = core_property_names ();\\n\\n\");\n    if (base)\n      printf (\"  std::set<std::string> retval = all_pnames;\\n  std::set<std::string> dyn_props = dynamic_property_names ();\\n  retval.insert (dyn_props.begin (), dyn_props.end ());\\n  for (std::map<caseless_str, property, cmp_caseless_str>::const_iterator p = m_all_props.begin ();\\n       p != m_all_props.end (); p++)\\n    retval.insert (p->first);\\n\\n  return retval;\\n}\\n\\n\");\n    else\n      printf (\"  std::set<std::string> retval = all_pnames;\\n  std::set<std::string> base_props = base_properties::all_property_names ();\\n  retval.insert (base_props.begin (), base_props.end ());\\n\\n  return retval;\\n}\\n\\n\");\n\n    if (! base)\n      printf (\"bool\\n%s::properties::has_property (const caseless_str& pname) const\\n{\\n  std::set<std::string> pnames = all_property_names ();\\n\\n  return pnames.find (pname) != pnames.end ();\\n}\\n\\n\", class_name);\n  }\n}\n\nBEGIN {\n  printf (\"// DO NOT EDIT!  Generated automatically by genprops.awk.\\n\\n\")\n  pcount = 0;\n}\n\n/BEGIN_PROPERTIES *\\(.*\\)/ {\n  gather = 1;\n  idx = 0;\n  str = $0;\n  beg = index (str, \"(\") + 1;\n  len = index (str, \")\") - beg;\n  args = substr (str, beg, len);\n  n = split (args, arg_list, \",\");\n  if (n > 0)\n      class_name = arg_list[1];\n  if (n > 1)\n      object_name = arg_list[2];\n  else\n      object_name = class_name;\n  gsub (/ /, \"\", class_name);\n  gsub (/ /, \"\", object_name);\n  base = 0;\n  next;\n}\n\n/BEGIN_PROPERTIES/ {\n  gather = 1;\n  idx = 0;\n  class_name = \"\";\n  base = 0;\n  next;\n}\n\n/BEGIN_BASE_PROPERTIES/ {\n  gather = 1;\n  idx = 0;\n  class_name = \"base\";\n  base = 1;\n  next;\n}\n\n/END_PROPERTIES/ {\n  if (emit_graphics_props)\n    emit_source();\n  else\n    emit_declarations();\n  gather = 0;\n  next;\n}\n\n{\n  if (gather)\n  {\n    if (NF < 2 || /^[ \\t]*\\/\\//)\n      next;\n\n    idx++;\n\n    field = 1;\n\n    if ($field == \"mutable\")\n    {\n      mutable[idx] = 1;\n      field++;\n    }\n    else\n      mutable[idx] = 0;\n\n    type[idx] = $(field++);\n    ptype[idx] = (type[idx] ~ /^.*_property$/);\n    name[idx] = $(field++);\n\n    limits[idx] = 0;\n    mode[idx] = 0;\n    hidden[idx] = 0;\n    readonly[idx] = 0;\n    emit_get[idx] = \"definition\";\n    emit_set[idx] = \"definition\";\n    defval[idx] = \"\";\n    updater[idx] = \"\";\n    deprecated[idx] = 0;\n    factory[idx] = 1;\n##    if (type[idx] == \"octave_value\")\n##      emit_ov_set[idx] = \"\";\n##    else\n##      emit_ov_set[idx] = \"definition\";\n\n    if (NF >= field)\n    {\n      if ($field != \",\")\n      {\n        quals = $(field++);\n\n        if (index (quals, \"l\"))\n          limits[idx] = 1;\n\n        if (index (quals, \"m\"))\n          mode[idx] = 1;\n\n        ## There is a custom inline definition for the get function,\n        ## so we don't emit anything.\n        if (index (quals, \"g\"))\n          emit_get[idx] = \"\";\n\n        ## There is a custom extern definition for the get function,\n        ## but we still emit the declaration.\n        if (index (quals, \"G\"))\n          emit_get[idx] = \"declaration\";\n\n        ## There is a custom inline definition for the set function,\n        ## so we don't emit anything.\n        if (index (quals, \"s\"))\n          emit_set[idx] = \"\";\n\n        ## There is a custom extern definition for the set function,\n        ## but we still emit the declaration.\n        if (index (quals, \"S\"))\n          emit_set[idx] = \"declaration\";\n\n        ## The property is hidden\n        if (index (quals, \"h\"))\n          hidden[idx] = 1;\n\n        ## The property is read-only\n        if (index (quals, \"r\"))\n          readonly[idx] = 1;\n\n        ## There is an inline updater method that should be called\n        ## from the set method\n        if (index (quals, \"u\"))\n          updater[idx] = \"inline\";\n\n        ## There is an extern updater method that should be called\n        ## from the set method\n        if (index (quals, \"U\"))\n          updater[idx] = \"extern\";\n\n        ## The property is deprecated\n        if (index (quals, \"d\"))\n          deprecated[idx] = 1;\n\n        ## There is not factory default value\n        if (index (quals, \"f\"))\n          factory[idx] = 0;\n\n##        ## emit an assignment set function\n##        if (index (quals, \"a\"))\n##          emit_ov_set[idx] = \"assignment\";\n##\n##        if (type[idx] != \"octave_value\")\n##        {\n##          ## The 'o' and 'O' qualifiers are only useful when the\n##          ## the property type is something other than an\n##          ## octave_value.\n##\n##          ## There is a custom inline definition for the\n##          ## octave_value version of the set function, so we\n##          ## don't emit anything.\n##          if (index (quals, \"o\"))\n##            emit_ov_set[idx] = \"\";\n##\n##          ## There is a custom extern definition for the\n##          ## octave_value version of the set function, but we\n##          ## still emit the declaration.\n##          if (index (quals, \"O\"))\n##            emit_ov_set[idx] = \"declaration\";\n##        }\n      }\n\n      if (NF > field && $field == \",\")\n      {\n        field++;\n\n        for (i = field; i <= NF; i++)\n          defval[idx] = (defval[idx] (i > field ? \" \" : \"\") $i);\n      }\n    }\n\n  }\n  else if (! emit_graphics_props)\n    print $0;\n}\n"
  },
  {
    "path": "libinterp/corefcn/gh-manager.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"cmd-edit.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"gh-manager.h\"\n#include \"graphics-utils.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic double\nmake_handle_fraction ()\n{\n  static double maxrand = RAND_MAX + 2.0;\n\n  return (rand () + 1.0) / maxrand;\n}\n\ngraphics_handle\ngh_manager::get_handle (bool integer_figure_handle)\n{\n  graphics_handle retval;\n\n  if (integer_figure_handle)\n    {\n      // Figure handles are positive integers corresponding\n      // to the figure number.\n\n      // We always want the lowest unused figure number.\n\n      retval = 1;\n\n      while (m_handle_map.find (retval) != m_handle_map.end ())\n        retval++;\n    }\n  else\n    {\n      // Other graphics handles are negative integers plus some random\n      // fractional part.  To avoid running out of integers, we recycle the\n      // integer part but tack on a new random part each time.\n\n      auto p = m_handle_free_list.begin ();\n\n      if (p != m_handle_free_list.end ())\n        {\n          retval = *p;\n          m_handle_free_list.erase (p);\n        }\n      else\n        {\n          retval = graphics_handle (m_next_handle);\n\n          m_next_handle = std::ceil (m_next_handle) - 1.0 - make_handle_fraction ();\n        }\n    }\n\n  return retval;\n}\n\nvoid\ngh_manager::free (const graphics_handle& h, bool from_root)\n{\n  if (h.ok ())\n    {\n      if (h.value () == 0)\n        error (\"graphics_handle::free: can't delete root object\");\n\n      auto p = m_handle_map.find (h);\n\n      if (p == m_handle_map.end ())\n        error (\"graphics_handle::free: invalid object %g\", h.value ());\n\n      base_properties& bp = p->second.get_properties ();\n\n      if (! p->second.valid_object () || bp.is_beingdeleted ())\n        return;\n\n      graphics_handle parent_h = p->second.get_parent ();\n      graphics_object parent_go = nullptr;\n      if (! from_root || isfigure (h.value ()))\n        parent_go = get_object (parent_h);\n\n      bp.set_beingdeleted (true);\n\n      // delete listeners before invalidating object\n      p->second.remove_all_listeners ();\n\n      bp.delete_children (true, from_root);\n\n      // NOTE: Call the delete function while the object's state is still valid.\n      octave_value val = bp.get_deletefcn ();\n\n      bp.execute_deletefcn ();\n\n      // Notify graphics toolkit.\n      p->second.finalize ();\n\n\n      // NOTE: Call remove_child before erasing the go from the map if not\n      // removing from groot.\n      // A callback function might have already deleted the parent\n      if ((! from_root || isfigure (h.value ())) && parent_go.valid_object ()\n          && h.ok ())\n        parent_go.remove_child (h);\n\n      // Note: this will be valid only for first explicitly deleted\n      // object.  All its children will then have an\n      // unknown graphics toolkit.\n\n      // Graphics handles for non-figure objects are negative\n      // integers plus some random fractional part.  To avoid\n      // running out of integers, we recycle the integer part\n      // but tack on a new random part each time.\n\n      m_handle_map.erase (p);\n\n      if (h.value () < 0)\n        m_handle_free_list.insert\n        (std::ceil (h.value ()) - make_handle_fraction ());\n    }\n}\n\nvoid\ngh_manager::renumber_figure (const graphics_handle& old_gh,\n                             const graphics_handle& new_gh)\n{\n  auto p = m_handle_map.find (old_gh);\n\n  if (p == m_handle_map.end ())\n    error (\"graphics_handle::free: invalid object %g\", old_gh.value ());\n\n  graphics_object go = p->second;\n\n  m_handle_map.erase (p);\n\n  m_handle_map[new_gh] = go;\n\n  if (old_gh.value () < 0)\n    m_handle_free_list.insert (std::ceil (old_gh.value ())\n                               - make_handle_fraction ());\n\n  for (auto& hfig : m_figure_list)\n    {\n      if (hfig == old_gh)\n        {\n          hfig = new_gh;\n          break;\n        }\n    }\n}\n\nvoid\ngh_manager::close_all_figures ()\n{\n  // FIXME: should we process or discard pending events?\n\n  m_event_queue.clear ();\n\n  // Don't use m_figure_list_iterator because we'll be removing elements\n  // from the list elsewhere.\n\n  Matrix hlist = figure_handle_list (true);\n\n  for (octave_idx_type i = 0; i < hlist.numel (); i++)\n    {\n      graphics_handle h = lookup (hlist(i));\n\n      if (h.ok ())\n        close_figure (h);\n    }\n\n  // They should all be closed now.  If not, force them to close.\n\n  hlist = figure_handle_list (true);\n\n  for (octave_idx_type i = 0; i < hlist.numel (); i++)\n    {\n      graphics_handle h = lookup (hlist(i));\n\n      if (h.ok ())\n        force_close_figure (h);\n    }\n\n  // None left now, right?\n\n  hlist = figure_handle_list (true);\n\n  if (hlist.numel () != 0)\n    warning (\"gh_manager::close_all_figures: some graphics elements failed to close\");\n\n  // Clear all callback objects from our list.\n\n  m_callback_objects.clear ();\n}\n\n// We use a random value for the handle to avoid issues with plots and\n// scalar values for the first argument.\ngh_manager::gh_manager (octave::interpreter& interp)\n  : m_interpreter (interp), m_handle_map (), m_handle_free_list (),\n    m_next_handle (-1.0 - (rand () + 1.0) / (RAND_MAX + 2.0)),\n    m_figure_list (), m_graphics_lock (), m_event_queue (),\n    m_callback_objects (), m_event_processing (0)\n{\n  m_handle_map[0] = graphics_object (new root_figure ());\n\n  octave::gtk_manager& gtk_mgr = octave::__get_gtk_manager__ ();\n\n  // Make sure the default graphics toolkit is registered.\n  gtk_mgr.default_toolkit ();\n}\n\ngraphics_handle\ngh_manager::make_graphics_handle (const std::string& go_name,\n                                  const graphics_handle& p,\n                                  bool integer_figure_handle,\n                                  bool call_createfcn, bool notify_toolkit)\n{\n  graphics_handle h = get_handle (integer_figure_handle);\n\n  base_graphics_object *bgo = make_graphics_object_from_type (go_name, h, p);\n\n  if (! bgo)\n    error (\"gh_manager::make_graphics_handle: invalid object type '%s'\",\n           go_name.c_str ());\n\n  graphics_object go (bgo);\n\n  m_handle_map[h] = go;\n\n  if (go_name == \"axes\")\n    {\n      // Handle defaults for labels since overriding defaults for\n      // them can't work before the axes object is fully\n      // constructed.\n\n      axes::properties& props\n        = dynamic_cast<axes::properties&> (go.get_properties ());\n\n      graphics_object tgo;\n\n      tgo = get_object (props.get_xlabel ());\n      tgo.override_defaults ();\n\n      tgo = get_object (props.get_ylabel ());\n      tgo.override_defaults ();\n\n      tgo = get_object (props.get_zlabel ());\n      tgo.override_defaults ();\n\n      tgo = get_object (props.get_title ());\n      tgo.override_defaults ();\n    }\n\n  // Overriding defaults will work now because the handle is valid\n  // and we can find parent objects (not just handles).\n  go.override_defaults ();\n\n  if (call_createfcn)\n    bgo->get_properties ().execute_createfcn ();\n\n  // Notify graphics toolkit.\n  if (notify_toolkit)\n    go.initialize ();\n\n  return h;\n}\n\ngraphics_handle\ngh_manager::make_figure_handle (double val, bool notify_toolkit)\n{\n  graphics_handle h = val;\n\n  base_graphics_object *bgo = new figure (h, 0);\n  graphics_object go (bgo);\n\n  m_handle_map[h] = go;\n\n  // Notify graphics toolkit.\n  if (notify_toolkit)\n    go.initialize ();\n\n  go.override_defaults ();\n\n  return h;\n}\n\nvoid\ngh_manager::push_figure (const graphics_handle& h)\n{\n  pop_figure (h);\n\n  m_figure_list.push_front (h);\n}\n\nvoid\ngh_manager::pop_figure (const graphics_handle& h)\n{\n  for (auto it = m_figure_list.begin (); it != m_figure_list.end (); it++)\n    {\n      if (*it == h)\n        {\n          m_figure_list.erase (it);\n          break;\n        }\n    }\n}\n\nstatic void\nxset_gcbo (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (0);\n\n  root_figure::properties& props\n    = dynamic_cast<root_figure::properties&> (go.get_properties ());\n\n  props.set_callbackobject (h.as_octave_value ());\n}\n\nvoid\ngh_manager::restore_gcbo ()\n{\n  octave::autolock guard (m_graphics_lock);\n\n  m_callback_objects.pop_front ();\n\n  xset_gcbo (m_callback_objects.empty ()\n             ? graphics_handle () : m_callback_objects.front ().get_handle ());\n}\n\nvoid\ngh_manager::execute_listener (const graphics_handle& h, const octave_value& l)\n{\n  if (octave::thread::is_thread ())\n    execute_callback (h, l, octave_value ());\n  else\n    {\n      octave::autolock guard (m_graphics_lock);\n\n      post_event (graphics_event::create_callback_event (h, l));\n    }\n}\n\nvoid\ngh_manager::execute_callback (const graphics_handle& h,\n                              const octave_value& cb_arg,\n                              const octave_value& data)\n{\n  if (cb_arg.is_defined () && ! cb_arg.isempty ())\n    {\n      octave_value_list args;\n      octave_value ov_fcn;\n      octave_function *fcn = nullptr;\n\n      args(0) = h.as_octave_value ();\n      if (data.is_defined ())\n        args(1) = data;\n      else\n        args(1) = Matrix ();\n\n      octave::unwind_action_safe restore_gcbo_action\n      (&gh_manager::restore_gcbo, this);\n\n      graphics_object go (get_object (h));\n      if (go)\n        {\n          // FIXME: Is the lock necessary when we're only calling a\n          //        const \"get\" method?\n          octave::autolock guard (m_graphics_lock);\n          m_callback_objects.push_front (go);\n          xset_gcbo (h);\n        }\n\n      // Copy CB because \"function_value\" method is non-const.\n      octave_value cb = cb_arg;\n\n      if (cb.is_function ())\n        fcn = cb.function_value ();\n      else if (cb.is_function_handle ())\n        ov_fcn = cb;\n      else if (cb.is_string ())\n        {\n          int status;\n          std::string s = cb.string_value ();\n\n          try\n            {\n              m_interpreter.eval_string (s, false, status, 0);\n            }\n          catch (const octave::execution_exception& ee)\n            {\n              m_interpreter.handle_exception (ee);\n            }\n        }\n      else if (cb.iscell () && cb.length () > 0\n               && (cb.rows () == 1 || cb.columns () == 1)\n               && (cb.cell_value ()(0).is_function ()\n                   || cb.cell_value ()(0).is_function_handle ()))\n        {\n          Cell c = cb.cell_value ();\n\n          ov_fcn = c(0);\n\n          for (int i = 1; i < c.numel () ; i++)\n            args(1+i) = c(i);\n        }\n      else\n        {\n          std::string nm = cb.class_name ();\n          error (\"trying to execute non-executable object (class = %s)\",\n                 nm.c_str ());\n        }\n\n      if (fcn || ov_fcn.is_defined ())\n        try\n          {\n            if (ov_fcn.is_defined ())\n              m_interpreter.feval (ov_fcn, args);\n            else\n              m_interpreter.feval (fcn, args);\n          }\n        catch (const octave::execution_exception& ee)\n          {\n            m_interpreter.handle_exception (ee);\n          }\n\n      // Redraw after interacting with a user-interface (ui*) object.\n      if (Vdrawnow_requested)\n        {\n          if (go)\n            {\n              std::string go_name\n                = go.get_properties ().graphics_object_name ();\n\n              if (go_name.length () > 1\n                  && go_name[0] == 'u' && go_name[1] == 'i')\n                {\n                  Fdrawnow (m_interpreter);\n                  Vdrawnow_requested = false;\n                }\n            }\n        }\n    }\n}\n\nstatic int\nprocess_graphics_events ()\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  return gh_mgr.process_events ();\n}\n\nvoid\ngh_manager::post_event (const graphics_event& e)\n{\n  m_event_queue.push_back (e);\n\n  octave::command_editor::add_event_hook (process_graphics_events);\n}\n\nvoid\ngh_manager::post_callback (const graphics_handle& h, const std::string& name,\n                           const octave_value& data)\n{\n  octave::autolock guard (m_graphics_lock);\n\n  graphics_object go = get_object (h);\n\n  if (go.valid_object ())\n    {\n      caseless_str cname (name);\n      int busyaction = base_graphics_event::QUEUE;\n\n      if (cname == \"deletefcn\" || cname == \"createfcn\"\n          || cname == \"closerequestfcn\"\n          || ((go.isa (\"figure\") || go.isa (\"uipanel\")\n               || go.isa (\"uibuttongroup\"))\n              && (cname == \"resizefcn\" || cname == \"sizechangedfcn\")))\n        busyaction = base_graphics_event::INTERRUPT;\n      else if (go.get_properties ().get_busyaction () == \"cancel\")\n        busyaction = base_graphics_event::CANCEL;\n\n      // The \"closerequestfcn\" callback must be executed once the figure has\n      // been made current.  Let \"close\" do the job.\n      if (cname == \"closerequestfcn\")\n        {\n          std::string cmd (\"close (gcbf ());\");\n          post_event (graphics_event::create_mcode_event (h, cmd, busyaction));\n        }\n      else\n        post_event (graphics_event::create_callback_event (h, name, data,\n                    busyaction));\n    }\n}\n\nvoid\ngh_manager::post_function (graphics_event::event_fcn fcn, void *fcn_data)\n{\n  octave::autolock guard (m_graphics_lock);\n\n  post_event (graphics_event::create_function_event (fcn, fcn_data));\n}\n\nvoid\ngh_manager::post_set (const graphics_handle& h, const std::string& name,\n                      const octave_value& value, bool notify_toolkit,\n                      bool redraw_figure)\n{\n  octave::autolock guard (m_graphics_lock);\n\n  post_event (graphics_event::create_set_event (h, name, value, notify_toolkit,\n              redraw_figure));\n}\n\nint\ngh_manager::process_events (bool force)\n{\n  graphics_event e;\n  bool old_Vdrawnow_requested = Vdrawnow_requested;\n  bool events_executed = false;\n\n  do\n    {\n      e = graphics_event ();\n\n      {\n        octave::autolock guard (m_graphics_lock);\n\n        if (! m_event_queue.empty ())\n          {\n            if (m_callback_objects.empty () || force)\n              {\n                e = m_event_queue.front ();\n\n                m_event_queue.pop_front ();\n              }\n            else\n              {\n                const graphics_object& go = m_callback_objects.front ();\n\n                if (go.get_properties ().is_interruptible ())\n                  {\n                    e = m_event_queue.front ();\n\n                    m_event_queue.pop_front ();\n                  }\n                else\n                  {\n                    std::list<graphics_event>::iterator p = m_event_queue.begin ();\n\n                    while (p != m_event_queue.end ())\n                      if (p->get_busyaction () == base_graphics_event::CANCEL)\n                        {\n                          p = m_event_queue.erase (p);\n                        }\n                      else if (p->get_busyaction ()\n                               == base_graphics_event::INTERRUPT)\n                        {\n                          e = (*p);\n                          m_event_queue.erase (p);\n                          break;\n                        }\n                      else\n                        p++;\n                  }\n              }\n          }\n      }\n\n      if (e.ok ())\n        {\n          e.execute ();\n          events_executed = true;\n        }\n    }\n  while (e.ok ());\n\n  {\n    octave::autolock guard (m_graphics_lock);\n\n    if (m_event_queue.empty () && m_event_processing == 0)\n      octave::command_editor::remove_event_hook (process_graphics_events);\n  }\n\n  if (events_executed)\n    octave::flush_stdout ();\n\n  if (Vdrawnow_requested && ! old_Vdrawnow_requested)\n    {\n      Fdrawnow (m_interpreter);\n\n      Vdrawnow_requested = false;\n    }\n\n  return 0;\n}\n\n\n/*\n## Test interruptible/busyaction properties\n%!function cb (h, ~)\n%! setappdata (gcbf (), \"cb_exec\", [getappdata(gcbf (), \"cb_exec\") h]);\n%! drawnow ();\n%! setappdata (gcbf (), \"cb_exec\", [getappdata(gcbf (), \"cb_exec\") h]);\n%!endfunction\n%!\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! hf = figure (\"visible\", \"off\", \"resizefcn\", @cb);\n%! graphics_toolkit (hf, \"qt\");\n%! unwind_protect\n%!   ## Default\n%!   hui1 = uicontrol (\"parent\", hf, \"interruptible\", \"on\", \"callback\", @cb);\n%!   hui2 = uicontrol (\"parent\", hf, \"busyaction\", \"queue\", \"callback\", @cb);\n%!   hui3 = uicontrol (\"parent\", hf, \"busyaction\", \"queue\", \"callback\", @cb);\n%!   __go_post_callback__ (hui1, \"callback\");\n%!   __go_post_callback__ (hui2, \"callback\");\n%!   __go_post_callback__ (hui3, \"callback\");\n%!\n%!   assert (getappdata (hf, \"cb_exec\"), []);\n%!   drawnow ();\n%!   assert (getappdata (hf, \"cb_exec\"), [hui1 hui2 hui3 hui3 hui2 hui1]);\n%!\n%!   ## Interruptible off\n%!   setappdata (hf, \"cb_exec\", []);\n%!   set (hui1, \"interruptible\", \"off\");\n%!   __go_post_callback__ (hui1, \"callback\");\n%!   __go_post_callback__ (hui2, \"callback\");\n%!   __go_post_callback__ (hui3, \"callback\");\n%!   drawnow ();\n%!   assert (getappdata (hf, \"cb_exec\"), [hui1 hui1 hui2 hui3 hui3 hui2]);\n%!\n%!   ## \"resizefcn\" callback interrupts regardless of interruptible property\n%!   setappdata (hf, \"cb_exec\", []);\n%!   __go_post_callback__ (hui1, \"callback\");\n%!   __go_post_callback__ (hf, \"resizefcn\");\n%!   drawnow ();\n%!   assert (getappdata (hf, \"cb_exec\"), [hui1 hf hf hui1]);\n%!\n%!   ## test \"busyaction\" \"cancel\"\n%!   setappdata (hf, \"cb_exec\", []);\n%!   set (hui2, \"busyaction\", \"cancel\");\n%!   __go_post_callback__ (hui1, \"callback\");\n%!   __go_post_callback__ (hui2, \"callback\");\n%!   __go_post_callback__ (hui3, \"callback\");\n%!   __go_post_callback__ (hf, \"resizefcn\");\n%!   drawnow ();\n%!   assert (getappdata (hf, \"cb_exec\"), [hui1 hf hui3 hui3 hf hui1]);\n%! unwind_protect_cleanup\n%!   close (hf)\n%! end_unwind_protect\n*/\n\nvoid\ngh_manager::enable_event_processing (bool enable)\n{\n  octave::autolock guard (m_graphics_lock);\n\n  if (enable)\n    {\n      m_event_processing++;\n\n      octave::command_editor::add_event_hook (process_graphics_events);\n    }\n  else\n    {\n      m_event_processing--;\n\n      if (m_event_queue.empty () && m_event_processing == 0)\n        octave::command_editor::remove_event_hook (process_graphics_events);\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/gh-manager.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gh_manager_h)\n#define octave_gh_manager_h 1\n\n#include \"octave-config.h\"\n\n#include \"graphics.h\"\n#include \"gtk-manager.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API gh_manager\n{\npublic:\n\n  typedef std::pair<uint8NDArray /*pixels*/, std::string /*svg*/> latex_data;\n\n  OCTINTERP_API gh_manager (octave::interpreter& interp);\n\n  // FIXME: eventually eliminate these static functions and access\n  // gh_manager object through the interpreter.\n\n  OCTINTERP_API graphics_handle get_handle (bool integer_figure_handle);\n\n  OCTINTERP_API void free (const graphics_handle& h, bool from_root = false);\n\n  OCTINTERP_API void renumber_figure (const graphics_handle& old_gh,\n                                      const graphics_handle& new_gh);\n\n  graphics_handle lookup (double val) const\n  {\n    const_iterator p = (octave::math::isnan (val)\n                        ? m_handle_map.end () : m_handle_map.find (val));\n\n    return (p != m_handle_map.end ()) ? p->first : graphics_handle ();\n  }\n\n  graphics_handle lookup (const octave_value& val) const\n  {\n    return (val.is_real_scalar ()\n            ? lookup (val.double_value ()) : graphics_handle ());\n  }\n\n  graphics_object get_object (double val) const\n  {\n    return get_object (lookup (val));\n  }\n\n  graphics_object get_object (const graphics_handle& h) const\n  {\n    const_iterator p = (h.ok () ? m_handle_map.find (h) : m_handle_map.end ());\n\n    return (p != m_handle_map.end ()) ? p->second : graphics_object ();\n  }\n\n  OCTINTERP_API graphics_handle\n  make_graphics_handle (const std::string& go_name,\n                        const graphics_handle& p,\n                        bool integer_figure_handle = false,\n                        bool call_createfcn = true,\n                        bool notify_toolkit = true);\n\n  OCTINTERP_API graphics_handle\n  make_figure_handle (double val, bool notify_toolkit = true);\n\n  OCTINTERP_API void push_figure (const graphics_handle& h);\n\n  OCTINTERP_API void pop_figure (const graphics_handle& h);\n\n  graphics_handle current_figure () const\n  {\n    graphics_handle retval;\n\n    for (const auto& hfig : m_figure_list)\n      {\n        if (is_handle_visible (hfig))\n          retval = hfig;\n      }\n\n    return retval;\n  }\n\n  Matrix handle_list (bool show_hidden = false)\n  {\n    Matrix retval (1, m_handle_map.size ());\n\n    octave_idx_type i = 0;\n    for (const auto& h_iter : m_handle_map)\n      {\n        graphics_handle h = h_iter.first;\n\n        if (show_hidden || is_handle_visible (h))\n          retval(i++) = h.value ();\n      }\n\n    retval.resize (1, i);\n\n    return retval;\n  }\n\n  void lock () { m_graphics_lock.lock (); }\n\n  bool try_lock () { return m_graphics_lock.try_lock (); }\n\n  void unlock () { m_graphics_lock.unlock (); }\n\n  Matrix figure_handle_list (bool show_hidden = false)\n  {\n    Matrix retval (1, m_figure_list.size ());\n\n    octave_idx_type i = 0;\n    for (const auto& hfig : m_figure_list)\n      {\n        if (show_hidden || is_handle_visible (hfig))\n          retval(i++) = hfig.value ();\n      }\n\n    retval.resize (1, i);\n\n    return retval;\n  }\n\n  OCTINTERP_API void\n  execute_listener (const graphics_handle& h, const octave_value& l);\n\n  void execute_callback (const graphics_handle& h,\n                         const std::string& name,\n                         const octave_value& data = Matrix ())\n  {\n    octave_value cb;\n\n    if (true)\n      {\n        octave::autolock guard (graphics_lock ());\n\n        graphics_object go = get_object (h);\n\n        if (go.valid_object ())\n          cb = go.get (name);\n      }\n\n    execute_callback (h, cb, data);\n  }\n\n  OCTINTERP_API void\n  execute_callback (const graphics_handle& h, const octave_value& cb,\n                    const octave_value& data = Matrix ());\n\n  OCTINTERP_API void\n  post_callback (const graphics_handle& h, const std::string& name,\n                 const octave_value& data = Matrix ());\n\n  OCTINTERP_API void\n  post_function (graphics_event::event_fcn fcn, void *fcn_data = nullptr);\n\n  OCTINTERP_API void\n  post_set (const graphics_handle& h, const std::string& name,\n            const octave_value& value, bool notify_toolkit = true,\n            bool redraw_figure = false);\n\n  OCTINTERP_API int process_events (bool force = false);\n\n  OCTINTERP_API void enable_event_processing (bool enable = true);\n\n  bool is_handle_visible (const graphics_handle& h) const\n  {\n    bool retval = false;\n\n    graphics_object go = get_object (h);\n\n    if (go.valid_object ())\n      retval = go.is_handle_visible ();\n\n    return retval;\n  }\n\n  OCTINTERP_API void close_all_figures ();\n\n  OCTINTERP_API void restore_gcbo ();\n\n  OCTINTERP_API void post_event (const graphics_event& e);\n\n  octave::mutex graphics_lock ()\n  {\n    return m_graphics_lock;\n  }\n\n  latex_data get_latex_data (const std::string& key) const\n  {\n    latex_data retval;\n\n    const auto it = m_latex_cache.find (key);\n\n    if (it != m_latex_cache.end ())\n      retval = it->second;\n\n    return retval;\n  }\n\n  void set_latex_data (const std::string& key, latex_data val)\n  {\n    // Limit the number of cache entries to 500\n    if (m_latex_keys.size () >= 500)\n      {\n        auto it = m_latex_cache.find (m_latex_keys.front ());\n\n        if (it != m_latex_cache.end ())\n          m_latex_cache.erase (it);\n\n        m_latex_keys.pop_front ();\n      }\n\n    m_latex_cache[key] = val;\n    m_latex_keys.push_back (key);\n  }\n\nprivate:\n\n  typedef std::map<graphics_handle, graphics_object>::iterator iterator;\n  typedef std::map<graphics_handle, graphics_object>::const_iterator\n    const_iterator;\n\n  typedef std::set<graphics_handle>::iterator free_list_iterator;\n  typedef std::set<graphics_handle>::const_iterator const_free_list_iterator;\n\n  typedef std::list<graphics_handle>::iterator figure_list_iterator;\n  typedef std::list<graphics_handle>::const_iterator const_figure_list_iterator;\n\n  octave::interpreter& m_interpreter;\n\n  // A map of handles to graphics objects.\n  std::map<graphics_handle, graphics_object> m_handle_map;\n\n  // The available graphics handles.\n  std::set<graphics_handle> m_handle_free_list;\n\n  // The next handle available if m_handle_free_list is empty.\n  double m_next_handle;\n\n  // The allocated figure handles.  Top of the stack is most recently\n  // created.\n  std::list<graphics_handle> m_figure_list;\n\n  // The lock for accessing the graphics sytsem.\n  octave::mutex m_graphics_lock;\n\n  // The list of events queued by graphics toolkits.\n  std::list<graphics_event> m_event_queue;\n\n  // The stack of callback objects.\n  std::list<graphics_object> m_callback_objects;\n\n  // A flag telling whether event processing must be constantly on.\n  int m_event_processing;\n\n  // Cache of already parsed latex strings.  Store a separate list of keys\n  // to allow for erasing oldest entries if cache size becomes too large.\n  std::unordered_map<std::string, latex_data> m_latex_cache;\n  std::list<std::string> m_latex_keys;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/gl-render.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <array>\n#include <limits>\n#include <memory>\n#include <sstream>\n\n#if defined (HAVE_WINDOWS_H)\n#  define WIN32_LEAN_AND_MEAN\n#  include <windows.h>\n#endif\n\n#include \"mappers.h\"\n#include \"oct-locbuf.h\"\n\n#include \"errwarn.h\"\n#include \"gh-manager.h\"\n#include \"gl-render.h\"\n#include \"interpreter-private.h\"\n#include \"oct-opengl.h\"\n#include \"text-renderer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_OPENGL)\n\nstatic int\nnext_power_of_2 (int n)\n{\n  int m = 1;\n\n  while (m < n && m < std::numeric_limits<int>::max ())\n    m <<= 1;\n\n  return m;\n}\n\n#define LIGHT_MODE GL_FRONT_AND_BACK\n\n// Use symbolic names for axes\nenum\n{\n  X_AXIS,\n  Y_AXIS,\n  Z_AXIS\n};\n\n// Use symbolic names for color mode\nenum\n{\n  UNIFORM,\n  FLAT,\n  INTERP,\n  TEXTURE\n};\n\n// Use symbolic names for lighting\nenum\n{\n  NONE,\n  //FLAT,  // Already declared in anonymous enum for color mode\n  GOURAUD = 2\n};\n\n// Win32 API requires the CALLBACK attributes for\n// GLU callback functions.  Define it to empty on\n// other platforms.\n#if ! defined (CALLBACK)\n#  define CALLBACK\n#endif\n\nclass opengl_texture\n{\nprivate:\n\n  class texture_rep\n  {\n  public:\n\n    texture_rep (opengl_functions& glfcns)\n      : m_glfcns (glfcns), m_id (), m_w (), m_h (), m_tw (), m_th (),\n        m_tx (), m_ty (), m_valid (false)\n    { }\n\n    texture_rep (opengl_functions& glfcns, GLuint id, int w, int h,\n                 int tw, int th)\n      : m_glfcns (glfcns), m_id (id), m_w (w), m_h (h), m_tw (tw), m_th (th),\n        m_tx (double(m_w)/m_tw), m_ty (double(m_h)/m_th), m_valid (true)\n    { }\n\n    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (texture_rep)\n\n    ~texture_rep ()\n    {\n      if (m_valid)\n        m_glfcns.glDeleteTextures (1, &m_id);\n    }\n\n    void bind (int mode) const\n    {\n      if (m_valid)\n        m_glfcns.glBindTexture (mode, m_id);\n    }\n\n    void tex_coord (double q, double r) const\n    {\n      if (m_valid)\n        m_glfcns.glTexCoord2d (q*m_tx, r*m_ty);\n    }\n\n    opengl_functions& m_glfcns;\n    GLuint m_id;\n    int m_w, m_h;\n    int m_tw, m_th;\n    double m_tx, m_ty;\n    bool m_valid;\n  };\n\npublic:\n\n  opengl_texture () = delete;\n\n  opengl_texture (opengl_functions& glfcns)\n    : m_rep (new texture_rep (glfcns))\n  { }\n\n  opengl_texture (opengl_functions& glfcns, GLuint id, int w, int h,\n                  int tw, int th)\n    : m_rep (new texture_rep (glfcns, id, w, h, tw, th))\n  { }\n\n  OCTAVE_DEFAULT_COPY_DELETE (opengl_texture)\n\n  static opengl_texture create (opengl_functions& glfcns,\n                                const octave_value& data);\n\n  void bind (int mode = GL_TEXTURE_2D) const { m_rep->bind (mode); }\n\n  void tex_coord (double q, double r) const { m_rep->tex_coord (q, r); }\n\n  bool is_valid () const { return m_rep->m_valid; }\n\nprivate:\n\n  opengl_texture (const std::shared_ptr<texture_rep>& new_rep)\n    : m_rep (new_rep)\n  { }\n\n  std::shared_ptr<texture_rep> m_rep;\n};\n\nopengl_texture\nopengl_texture::create (opengl_functions& glfcns, const octave_value& data)\n{\n  opengl_texture retval (glfcns);\n\n  const dim_vector& dv = data.dims ();\n\n  // Expect RGB data\n  if (dv.ndims () == 3 && (dv(2) == 3 || dv(2) == 4))\n    {\n      // FIXME: dim_vectors hold octave_idx_type values.\n      //        Should we check for dimensions larger than intmax?\n      int h, w, tw, th;\n      h = dv(0), w = dv(1);\n\n      // Return early if the image data are larger than the texture\n      // can hold\n      int max_size;\n      glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_size);\n      static bool warned = false;\n      if (h > max_size || w > max_size)\n        {\n          if (! warned)\n            {\n              warning (\"opengl_texture::create: the opengl library in use \"\n                       \"doesn't support images with either dimension larger \"\n                       \"than %d.  Not rendering.\", max_size);\n              warned = true;\n            }\n\n          return opengl_texture (glfcns);\n        }\n\n      GLuint id;\n      bool ok = true;\n\n      tw = next_power_of_2 (w);\n      th = next_power_of_2 (h);\n\n      glfcns.glGenTextures (1, &id);\n      glfcns.glBindTexture (GL_TEXTURE_2D, id);\n\n      if (data.is_double_type ())\n        {\n          const NDArray xdata = data.array_value ();\n\n          OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th));\n\n          for (int i = 0; i < h; i++)\n            {\n              for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)\n                {\n                  a[idx]   = xdata(i, j, 0);\n                  a[idx+1] = xdata(i, j, 1);\n                  a[idx+2] = xdata(i, j, 2);\n                }\n            }\n\n          glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB,\n                               GL_FLOAT, a);\n        }\n\n      else if (data.is_single_type ())\n        {\n          const FloatNDArray xdata = data.float_array_value ();\n\n          OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th));\n\n          for (int i = 0; i < h; i++)\n            {\n              for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)\n                {\n                  a[idx]   = xdata(i, j, 0);\n                  a[idx+1] = xdata(i, j, 1);\n                  a[idx+2] = xdata(i, j, 2);\n                }\n            }\n\n          glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB,\n                               GL_FLOAT, a);\n        }\n      else if (data.is_uint16_type ())\n        {\n          const uint16NDArray xdata = data.uint16_array_value ();\n\n          OCTAVE_LOCAL_BUFFER (GLushort, a, (3*tw*th));\n\n          for (int i = 0; i < h; i++)\n            {\n              for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)\n                {\n                  a[idx]   = xdata(i, j, 0);\n                  a[idx+1] = xdata(i, j, 1);\n                  a[idx+2] = xdata(i, j, 2);\n                }\n            }\n\n          glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,\n                               GL_RGB, GL_UNSIGNED_SHORT, a);\n        }\n      else if (data.is_uint8_type () && dv(2) == 3)\n        {\n          const uint8NDArray xdata = data.uint8_array_value ();\n\n          OCTAVE_LOCAL_BUFFER (GLubyte, a, (3*tw*th));\n\n          for (int i = 0; i < h; i++)\n            {\n              for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)\n                {\n                  a[idx]   = xdata(i, j, 0);\n                  a[idx+1] = xdata(i, j, 1);\n                  a[idx+2] = xdata(i, j, 2);\n                }\n            }\n\n          glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,\n                               GL_RGB, GL_UNSIGNED_BYTE, a);\n        }\n      else if (data.is_uint8_type () && dv(2) == 4)\n        {\n          const uint8NDArray xdata = data.uint8_array_value ();\n\n          OCTAVE_LOCAL_BUFFER (GLubyte, a, (4*tw*th));\n\n          for (int i = 0; i < h; i++)\n            {\n              for (int j = 0, idx = i*tw*4; j < w; j++, idx += 4)\n                {\n                  a[idx]   = xdata(i, j, 0);\n                  a[idx+1] = xdata(i, j, 1);\n                  a[idx+2] = xdata(i, j, 2);\n                  a[idx+3] = xdata(i, j, 3);\n                }\n            }\n\n          glfcns.glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0,\n                               GL_RGBA, GL_UNSIGNED_BYTE, a);\n        }\n      else\n        {\n          ok = false;\n          warning (\"opengl_texture::create: invalid image data type, expected double, single, uint8, or uint16\");\n        }\n\n      if (ok)\n        {\n          glfcns.glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,\n                                  GL_NEAREST);\n          glfcns.glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,\n                                  GL_NEAREST);\n\n          if (glfcns.glGetError () != GL_NO_ERROR)\n            warning (\"opengl_texture::create: OpenGL error while generating texture data\");\n          else\n            retval = opengl_texture (glfcns, id, w, h, tw, th);\n        }\n    }\n  else\n    warning (\"opengl_texture::create: invalid texture data size\");\n\n  return retval;\n}\n\nclass opengl_tessellator\n{\npublic:\n#if defined (HAVE_FRAMEWORK_OPENGL) && defined (HAVE_GLUTESSCALLBACK_THREEDOTS)\n  typedef GLvoid (CALLBACK *fcn) (...);\n#else\n  typedef void (CALLBACK *fcn) ();\n#endif\n\npublic:\n\n  opengl_tessellator () : m_glu_tess (nullptr), m_fill () { init (); }\n\n  OCTAVE_DISABLE_COPY_MOVE (opengl_tessellator)\n\n  virtual ~opengl_tessellator ()\n  { if (m_glu_tess) gluDeleteTess (m_glu_tess); }\n\n  void begin_polygon (bool filled = true)\n  {\n    gluTessProperty (m_glu_tess, GLU_TESS_BOUNDARY_ONLY,\n                     (filled ? GL_FALSE : GL_TRUE));\n    m_fill = filled;\n    gluTessBeginPolygon (m_glu_tess, this);\n  }\n\n  void end_polygon () const\n  { gluTessEndPolygon (m_glu_tess); }\n\n  void begin_contour () const\n  { gluTessBeginContour (m_glu_tess); }\n\n  void end_contour () const\n  { gluTessEndContour (m_glu_tess); }\n\n  void add_vertex (double *loc, void *data) const\n  { gluTessVertex (m_glu_tess, loc, data); }\n\nprotected:\n  virtual void begin (GLenum /*type*/) { }\n\n  virtual void end () { }\n\n  virtual void vertex (void * /*data*/) { }\n\n  virtual void combine (GLdouble [3] /*c*/, void *[4] /*data*/,\n                        GLfloat  [4] /*w*/, void ** /*out_data*/) { }\n\n  virtual void edge_flag (GLboolean /*flag*/) { }\n\n  virtual void error (GLenum err)\n  { ::error (\"OpenGL tessellation error (%d)\", err); }\n\n  virtual void init ()\n  {\n    m_glu_tess = gluNewTess ();\n\n    gluTessCallback (m_glu_tess, GLU_TESS_BEGIN_DATA,\n                     reinterpret_cast<fcn> (tess_begin));\n    gluTessCallback (m_glu_tess, GLU_TESS_END_DATA,\n                     reinterpret_cast<fcn> (tess_end));\n    gluTessCallback (m_glu_tess, GLU_TESS_VERTEX_DATA,\n                     reinterpret_cast<fcn> (tess_vertex));\n    gluTessCallback (m_glu_tess, GLU_TESS_COMBINE_DATA,\n                     reinterpret_cast<fcn> (tess_combine));\n    gluTessCallback (m_glu_tess, GLU_TESS_EDGE_FLAG_DATA,\n                     reinterpret_cast<fcn> (tess_edge_flag));\n    gluTessCallback (m_glu_tess, GLU_TESS_ERROR_DATA,\n                     reinterpret_cast<fcn> (tess_error));\n  }\n\n  bool is_filled () const { return m_fill; }\n\nprivate:\n  static void CALLBACK tess_begin (GLenum type, void *t)\n  { reinterpret_cast<opengl_tessellator *> (t)->begin (type); }\n\n  static void CALLBACK tess_end (void *t)\n  { reinterpret_cast<opengl_tessellator *> (t)->end (); }\n\n  static void CALLBACK tess_vertex (void *v, void *t)\n  { reinterpret_cast<opengl_tessellator *> (t)->vertex (v); }\n\n  static void CALLBACK tess_combine (GLdouble c[3], void *v[4], GLfloat w[4],\n                                     void **out, void *t)\n  { reinterpret_cast<opengl_tessellator *> (t)->combine (c, v, w, out); }\n\n  static void CALLBACK tess_edge_flag (GLboolean flag, void *t)\n  { reinterpret_cast<opengl_tessellator *> (t)->edge_flag (flag); }\n\n  static void CALLBACK tess_error (GLenum err, void *t)\n  { reinterpret_cast<opengl_tessellator *> (t)->error (err); }\n\n  //--------\n\n  GLUtesselator *m_glu_tess;\n  bool m_fill;\n};\n\nclass vertex_data\n{\npublic:\n\n  class vertex_data_rep\n  {\n  public:\n\n    vertex_data_rep ()\n      : m_coords (), m_color (), m_vertex_normal (), m_face_normal (),\n        m_alpha (), m_ambient (), m_diffuse (), m_specular (),\n        m_specular_exp (), m_specular_color_refl ()\n    { }\n\n    vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& vn,\n                     const Matrix& fn, double a, float as, float ds, float ss,\n                     float se, float scr)\n      : m_coords (c), m_color (col), m_vertex_normal (vn),\n        m_face_normal (fn), m_alpha (a), m_ambient (as), m_diffuse (ds),\n        m_specular (ss), m_specular_exp (se), m_specular_color_refl (scr)\n    { }\n\n    OCTAVE_DEFAULT_COPY (vertex_data_rep)\n\n    ~vertex_data_rep () = default;\n\n    Matrix m_coords;\n    Matrix m_color;\n    Matrix m_vertex_normal;\n    Matrix m_face_normal;\n    double m_alpha;\n    float m_ambient;\n    float m_diffuse;\n    float m_specular;\n    float m_specular_exp;\n    float m_specular_color_refl;\n  };\n\npublic:\n\n  // Required to instantiate std::list<vertex_data> objects.\n  vertex_data () : m_rep (nil_rep ()) { }\n\n  vertex_data (const Matrix& c, const Matrix& col, const Matrix& vn,\n               const Matrix& fn, double a, float as, float ds, float ss,\n               float se, float scr)\n    : m_rep (new vertex_data_rep (c, col, vn, fn, a, as, ds, ss, se, scr))\n  { }\n\n  vertex_data (const vertex_data&) = default;\n\n  ~vertex_data () = default;\n\n  vertex_data& operator = (const vertex_data&) = default;\n\n  vertex_data_rep * get_rep () const { return m_rep.get (); }\n\nprivate:\n\n  static std::shared_ptr<vertex_data_rep> nil_rep ()\n  {\n    static std::shared_ptr<vertex_data_rep> nr (new vertex_data_rep ());\n\n    return nr;\n  }\n\n  std::shared_ptr<vertex_data_rep> m_rep;\n};\n\nclass opengl_renderer::patch_tessellator : public opengl_tessellator\n{\npublic:\n\n  patch_tessellator (opengl_renderer *r, int cmode, int lmode, bool fl,\n                     float idx = 0.0)\n    : opengl_tessellator (), m_renderer (r),\n      m_color_mode (cmode), m_light_mode (lmode), m_face_lighting (fl),\n      m_index (idx), m_first (true), m_tmp_vdata ()\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (patch_tessellator)\n\n  ~patch_tessellator () = default;\n\nprotected:\n  void begin (GLenum type)\n  {\n    opengl_functions& glfcns = m_renderer->get_opengl_functions ();\n\n    //printf (\"patch_tessellator::begin (%d)\\n\", type);\n    m_first = true;\n\n    if (m_color_mode == INTERP || m_light_mode == GOURAUD)\n      glfcns.glShadeModel (GL_SMOOTH);\n    else\n      glfcns.glShadeModel (GL_FLAT);\n\n    if (is_filled ())\n      m_renderer->set_polygon_offset (true, m_index);\n\n    glfcns.glBegin (type);\n  }\n\n  void end ()\n  {\n    opengl_functions& glfcns = m_renderer->get_opengl_functions ();\n\n    //printf (\"patch_tessellator::end\\n\");\n    glfcns.glEnd ();\n    m_renderer->set_polygon_offset (false);\n  }\n\n  void vertex (void *data)\n  {\n    opengl_functions& glfcns = m_renderer->get_opengl_functions ();\n\n    vertex_data::vertex_data_rep *v\n      = reinterpret_cast<vertex_data::vertex_data_rep *> (data);\n    //printf (\"patch_tessellator::vertex (%g, %g, %g)\\n\", v->m_coords(0), v->m_coords(1), v->m_coords(2));\n\n    // NOTE: OpenGL can re-order vertices.  For \"flat\" coloring of FaceColor\n    // the first vertex must be identified in the draw_patch routine.\n\n    if (m_color_mode == INTERP || (m_color_mode == FLAT && ! is_filled ()))\n      {\n        Matrix col = v->m_color;\n\n        if (col.numel () == 3)\n          {\n            glfcns.glColor4d (col(0), col(1), col(2), v->m_alpha);\n            if (m_light_mode > 0)\n              {\n                // edge lighting only uses ambient light\n                float buf[4] = { 0.0f, 0.0f, 0.0f, 1.0f };\n\n                if (m_face_lighting)\n                  for (int k = 0; k < 3; k++)\n                    buf[k] = (v->m_specular\n                              * (v->m_specular_color_refl +\n                                 (1 - v->m_specular_color_refl) * col(k)));\n                glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);\n\n                if (m_face_lighting)\n                  for (int k = 0; k < 3; k++)\n                    buf[k] = (v->m_diffuse * col(k));\n                glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, buf);\n\n                for (int k = 0; k < 3; k++)\n                  buf[k] = (v->m_ambient * col(k));\n                glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);\n              }\n          }\n      }\n\n    if (m_light_mode == FLAT && m_first)\n      glfcns.glNormal3dv (v->m_face_normal.data ());\n    else if (m_light_mode == GOURAUD)\n      glfcns.glNormal3dv (v->m_vertex_normal.data ());\n\n    glfcns.glVertex3dv (v->m_coords.data ());\n\n    m_first = false;\n  }\n\n  void combine (GLdouble xyz[3], void *data[4], GLfloat w[4], void **out_data)\n  {\n    vertex_data::vertex_data_rep *v[4];\n    int vmax = 4;\n\n    for (int i = 0; i < 4; i++)\n      {\n        v[i] = reinterpret_cast<vertex_data::vertex_data_rep *> (data[i]);\n\n        if (vmax == 4 && ! v[i])\n          vmax = i;\n      }\n\n    Matrix vv (1, 3, 0.0);\n    Matrix cc;\n    Matrix vnn (1, 3, 0.0);\n    Matrix fnn (1, 3, 0.0);\n    double aa = 0.0;\n\n    vv(0) = xyz[0];\n    vv(1) = xyz[1];\n    vv(2) = xyz[2];\n\n    if (v[0]->m_color.numel ())\n      {\n        cc.resize (1, 3, 0.0);\n        for (int ic = 0; ic < 3; ic++)\n          for (int iv = 0; iv < vmax; iv++)\n            cc(ic) += (w[iv] * v[iv]->m_color (ic));\n      }\n\n    if (v[0]->m_vertex_normal.numel () > 0)\n      {\n        for (int in = 0; in < 3; in++)\n          for (int iv = 0; iv < vmax; iv++)\n            vnn(in) += (w[iv] * v[iv]->m_vertex_normal (in));\n      }\n\n    if (v[0]->m_face_normal.numel () > 0)\n      {\n        for (int in = 0; in < 3; in++)\n          for (int iv = 0; iv < vmax; iv++)\n            fnn(in) += (w[iv] * v[iv]->m_face_normal (in));\n      }\n\n    for (int iv = 0; iv < vmax; iv++)\n      aa += (w[iv] * v[iv]->m_alpha);\n\n    vertex_data new_v (vv, cc, vnn, fnn, aa, v[0]->m_ambient, v[0]->m_diffuse,\n                       v[0]->m_specular, v[0]->m_specular_exp,\n                       v[0]->m_specular_color_refl);\n    m_tmp_vdata.push_back (new_v);\n\n    *out_data = new_v.get_rep ();\n  }\n\nprivate:\n\n  // FIXME: We don't own this object; should it be a shared/weak/unique\n  // pointer?  Managed some other way?\n  opengl_renderer *m_renderer;\n  int m_color_mode;\n  int m_light_mode;\n  bool m_face_lighting;\n  int m_index;\n  bool m_first;\n  std::list<vertex_data> m_tmp_vdata;\n};\n\n#else\n\nclass opengl_renderer::patch_tessellator\n{\n  // Dummy class.\n};\n\nOCTAVE_NORETURN static void\nerror_unexpected (const char *name)\n{\n  error (\"unexpected call to %s when HAVE_OPENGL is not defined - please report this bug\", name);\n}\n\n#endif\n\nopengl_renderer::opengl_renderer (opengl_functions& glfcns)\n  : m_glfcns (glfcns), m_xmin (), m_xmax (), m_ymin (), m_ymax (),\n    m_zmin (), m_zmax (), m_devpixratio (1.0), m_xform (), m_toolkit (),\n    m_xZ1 (), m_xZ2 (), m_marker_id (), m_filled_marker_id (),\n    m_camera_pos (), m_camera_dir (), m_view_vector (),\n    m_interpreter (\"none\"), m_txt_renderer (), m_current_light (0),\n    m_max_lights (0), m_selecting (false), m_printing (false)\n{\n  // This constructor will fail if we don't have OpenGL or if the data\n  // types we assumed in our public interface aren't compatible with the\n  // OpenGL types.\n\n#if defined (HAVE_OPENGL)\n\n  // Ensure that we can't request an image larger than OpenGL can handle.\n  // FIXME: should we check signed vs. unsigned?\n\n  static bool ok = (sizeof (int) <= sizeof (GLsizei));\n\n  if (! ok)\n    error (\"the size of GLsizei is smaller than the size of int\");\n\n#else\n\n  err_disabled_feature (\"opengl_renderer\", \"OpenGL\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw (const graphics_object& go, bool toplevel)\n{\n  if (! go.valid_object ())\n    return;\n\n  const base_properties& props = go.get_properties ();\n\n  if (! m_toolkit)\n    m_toolkit = props.get_toolkit ();\n\n  if (go.isa (\"figure\"))\n    draw_figure (dynamic_cast<const figure::properties&> (props));\n  else if (go.isa (\"axes\"))\n    draw_axes (dynamic_cast<const axes::properties&> (props));\n  else if (go.isa (\"line\"))\n    draw_line (dynamic_cast<const line::properties&> (props));\n  else if (go.isa (\"surface\"))\n    draw_surface (dynamic_cast<const surface::properties&> (props));\n  else if (go.isa (\"patch\"))\n    draw_patch (dynamic_cast<const patch::properties&> (props));\n  else if (go.isa (\"scatter\"))\n    draw_scatter (dynamic_cast<const scatter::properties&> (props));\n  else if (go.isa (\"light\"))\n    draw_light (dynamic_cast<const light::properties&> (props));\n  else if (go.isa (\"hggroup\"))\n    draw_hggroup (dynamic_cast<const hggroup::properties&> (props));\n  else if (go.isa (\"text\"))\n    draw_text (dynamic_cast<const text::properties&> (props));\n  else if (go.isa (\"image\"))\n    draw_image (dynamic_cast<const image::properties&> (props));\n  else if (go.isa (\"uimenu\") || go.isa (\"uicontrol\")\n           || go.isa (\"uicontextmenu\") || go.isa (\"uitoolbar\")\n           || go.isa (\"uipushtool\") || go.isa (\"uitoggletool\")\n           || go.isa (\"uitable\"))\n    ; // SKIP\n  else if (go.isa (\"uipanel\"))\n    {\n      if (toplevel)\n        draw_uipanel (dynamic_cast<const uipanel::properties&> (props), go);\n    }\n  else if (go.isa (\"uibuttongroup\"))\n    {\n      if (toplevel)\n        draw_uibuttongroup (dynamic_cast<const uibuttongroup::properties&> (props), go);\n    }\n  else\n    {\n      warning (\"opengl_renderer: cannot render object of type '%s'\",\n               props.graphics_object_name ().c_str ());\n    }\n\n#if defined (HAVE_OPENGL)\n\n  GLenum gl_error = m_glfcns.glGetError ();\n  if (gl_error)\n    warning (\"opengl_renderer: Error '%s' (%d) occurred drawing '%s' object\",\n             gluErrorString (gl_error), gl_error,\n             props.graphics_object_name ().c_str ());\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_figure (const figure::properties& props)\n{\n  m_printing = props.is___printing__ ();\n\n  // Initialize OpenGL context\n  init_gl_context (props.is_graphicssmoothing (), props.get_color_rgb ());\n\n#if defined (HAVE_OPENGL)\n\n  props.set___gl_extensions__ (get_string (GL_EXTENSIONS));\n  props.set___gl_renderer__ (get_string (GL_RENDERER));\n  props.set___gl_vendor__ (get_string (GL_VENDOR));\n  props.set___gl_version__ (get_string (GL_VERSION));\n\n#endif\n\n  // Draw children\n\n  draw (props.get_all_children (), false);\n}\n\nvoid\nopengl_renderer::draw_uipanel (const uipanel::properties& props,\n                               const graphics_object& go)\n{\n  graphics_object fig = go.get_ancestor (\"figure\");\n  const figure::properties& figProps\n    = dynamic_cast<const figure::properties&> (fig.get_properties ());\n\n  // Initialize OpenGL context\n\n  init_gl_context (figProps.is_graphicssmoothing (),\n                   props.get_backgroundcolor_rgb ());\n\n  // Draw children\n\n  draw (props.get_all_children (), false);\n}\n\nvoid\nopengl_renderer::draw_uibuttongroup (const uibuttongroup::properties& props,\n                                     const graphics_object& go)\n{\n  graphics_object fig = go.get_ancestor (\"figure\");\n  const figure::properties& figProps\n    = dynamic_cast<const figure::properties&> (fig.get_properties ());\n\n  // Initialize OpenGL context\n\n  init_gl_context (figProps.is_graphicssmoothing (),\n                   props.get_backgroundcolor_rgb ());\n\n  // Draw children\n\n  draw (props.get_all_children (), false);\n}\n\nvoid\nopengl_renderer::init_gl_context (bool enhanced, const Matrix& c)\n{\n#if defined (HAVE_OPENGL)\n\n  // Initialize OpenGL context\n\n  m_glfcns.glEnable (GL_DEPTH_TEST);\n  m_glfcns.glDepthFunc (GL_LEQUAL);\n#if defined (HAVE_GLBLENDFUNCSEPARATE)\n  std::string gl_version = get_string (GL_VERSION);\n  if (gl_version.size() >= 3 && gl_version.substr(0, 3) >= \"1.4\")\n    m_glfcns.glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,\n                                  GL_ONE, GL_ONE_MINUS_SRC_ALPHA);\n  else\n#endif\n  m_glfcns.glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n\n  m_glfcns.glAlphaFunc (GL_GREATER, 0.0f);\n  m_glfcns.glEnable (GL_NORMALIZE);\n  m_glfcns.glEnable (GL_BLEND);\n\n  if (enhanced)\n    {\n      m_glfcns.glEnable (GL_MULTISAMPLE);\n      bool has_multisample = false;\n      if (! m_glfcns.glGetError ())\n        {\n          GLint iMultiSample, iNumSamples;\n          m_glfcns.glGetIntegerv (GL_SAMPLE_BUFFERS, &iMultiSample);\n          m_glfcns.glGetIntegerv (GL_SAMPLES, &iNumSamples);\n          if (iMultiSample == GL_TRUE && iNumSamples > 0)\n            has_multisample = true;\n        }\n\n      if (! has_multisample)\n        {\n          // MultiSample not implemented.  Use old-style anti-aliasing\n          m_glfcns.glDisable (GL_MULTISAMPLE);\n          // Disabling GL_MULTISAMPLE will raise a gl error if it is not\n          // implemented.  Thus, call glGetError to reset the error state.\n          m_glfcns.glGetError ();\n\n          m_glfcns.glEnable (GL_LINE_SMOOTH);\n          m_glfcns.glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);\n        }\n    }\n  else\n    {\n      m_glfcns.glDisable (GL_LINE_SMOOTH);\n    }\n\n  // Clear background\n\n  if (c.numel () >= 3)\n    {\n      m_glfcns.glClearColor (c(0), c(1), c(2), 1);\n      m_glfcns.glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n    }\n\n  GLenum gl_error = m_glfcns.glGetError ();\n  if (gl_error)\n    warning (\"opengl_renderer: Error '%s' (%d) occurred in init_gl_context\",\n             gluErrorString (gl_error), gl_error);\n\n#else\n\n  octave_unused_parameter (enhanced);\n  octave_unused_parameter (c);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::init_gl_context\");\n\n#endif\n}\n\nvoid\nopengl_renderer::render_grid (const double linewidth,\n                              const std::string& gridstyle,\n                              const Matrix& gridcolor, const double gridalpha,\n                              const Matrix& ticks, double lim1, double lim2,\n                              double p1, double p1N, double p2, double p2N,\n                              int xyz, bool is_3D)\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glColor4d (gridcolor(0), gridcolor(1), gridcolor(2), gridalpha);\n  set_linestyle (gridstyle, true, linewidth);\n  m_glfcns.glBegin (GL_LINES);\n  for (int i = 0; i < ticks.numel (); i++)\n    {\n      double val = ticks(i);\n      if (lim1 <= val && val <= lim2)\n        {\n          if (xyz == X_AXIS)\n            {\n              m_glfcns.glVertex3d (val, p1N, p2);\n              m_glfcns.glVertex3d (val, p1, p2);\n              if (is_3D)\n                {\n                  m_glfcns.glVertex3d (val, p1, p2N);\n                  m_glfcns.glVertex3d (val, p1, p2);\n                }\n            }\n          else if (xyz == Y_AXIS)\n            {\n              m_glfcns.glVertex3d (p1N, val, p2);\n              m_glfcns.glVertex3d (p1, val, p2);\n              if (is_3D)\n                {\n                  m_glfcns.glVertex3d (p1, val, p2N);\n                  m_glfcns.glVertex3d (p1, val, p2);\n                }\n            }\n          else if (xyz == Z_AXIS)\n            {\n              m_glfcns.glVertex3d (p1N, p2, val);\n              m_glfcns.glVertex3d (p1, p2, val);\n              m_glfcns.glVertex3d (p1, p2N, val);\n              m_glfcns.glVertex3d (p1, p2, val);\n            }\n        }\n    }\n  m_glfcns.glEnd ();\n  set_linestyle (\"-\");  // Disable LineStipple\n  double black[3] = {0, 0, 0};\n  m_glfcns.glColor3dv (black);\n\n#else\n\n  octave_unused_parameter (linewidth);\n  octave_unused_parameter (gridstyle);\n  octave_unused_parameter (gridcolor);\n  octave_unused_parameter (gridalpha);\n  octave_unused_parameter (ticks);\n  octave_unused_parameter (lim1);\n  octave_unused_parameter (lim2);\n  octave_unused_parameter (p1);\n  octave_unused_parameter (p1N);\n  octave_unused_parameter (p2);\n  octave_unused_parameter (p2N);\n  octave_unused_parameter (xyz);\n  octave_unused_parameter (is_3D);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::render_grid\");\n\n#endif\n}\n\nvoid\nopengl_renderer::render_tickmarks (const Matrix& ticks,\n                                   double lim1, double lim2,\n                                   double p1, double p1N,\n                                   double p2, double p2N,\n                                   double dx, double dy, double dz,\n                                   int xyz, bool mirror, bool tickdir_both)\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glBegin (GL_LINES);\n\n  for (int i = 0; i < ticks.numel (); i++)\n    {\n      double val = ticks(i);\n\n      if (lim1 <= val && val <= lim2)\n        {\n          if (xyz == X_AXIS)\n            {\n              m_glfcns.glVertex3d (val, p1 + (tickdir_both ? -dy : 0),\n                                   p2 + (tickdir_both ? -dz : 0));\n              m_glfcns.glVertex3d (val, p1+dy, p2+dz);\n              if (mirror)\n                {\n                  m_glfcns.glVertex3d (val, p1N + (tickdir_both ? dy : 0),\n                                       p2N + (tickdir_both ? dz : 0));\n                  m_glfcns.glVertex3d (val, p1N-dy, p2N-dz);\n                }\n            }\n          else if (xyz == Y_AXIS)\n            {\n              m_glfcns.glVertex3d (p1 + (tickdir_both ? -dx : 0), val,\n                                   p2 + (tickdir_both ? -dz : 0));\n              m_glfcns.glVertex3d (p1+dx, val, p2+dz);\n              if (mirror)\n                {\n                  m_glfcns.glVertex3d (p1N + (tickdir_both ? dx : 0), val,\n                                       p2N + (tickdir_both ? dz : 0));\n                  m_glfcns.glVertex3d (p1N-dx, val, p2N-dz);\n                }\n            }\n          else if (xyz == Z_AXIS)\n            {\n              m_glfcns.glVertex3d (p1 + (tickdir_both ? -dx : 0),\n                                   p2 + (tickdir_both ? -dy : 0), val);\n              m_glfcns.glVertex3d (p1+dx, p2+dy, val);\n              if (mirror)\n                {\n                  m_glfcns.glVertex3d (p1N + (tickdir_both ? dx : 0),\n                                       p2N + (tickdir_both ? dy : 0), val);\n                  m_glfcns.glVertex3d (p1N-dx, p2N-dy, val);\n                }\n            }\n        }\n    }\n\n  m_glfcns.glEnd ();\n\n#else\n\n  octave_unused_parameter (ticks);\n  octave_unused_parameter (lim1);\n  octave_unused_parameter (lim2);\n  octave_unused_parameter (p1);\n  octave_unused_parameter (p1N);\n  octave_unused_parameter (p2);\n  octave_unused_parameter (p2N);\n  octave_unused_parameter (dx);\n  octave_unused_parameter (dy);\n  octave_unused_parameter (dz);\n  octave_unused_parameter (xyz);\n  octave_unused_parameter (mirror);\n  octave_unused_parameter (tickdir_both);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::render_tickmarks\");\n\n#endif\n}\n\nvoid\nopengl_renderer::render_ticktexts (const Matrix& ticks,\n                                   const string_vector& ticklabels,\n                                   double lim1, double lim2,\n                                   double p1, double p2,\n                                   int xyz, int ha, int va,\n                                   int& wmax, int& hmax)\n{\n#if defined (HAVE_OPENGL)\n\n  int nticks  = ticks.numel ();\n  int nlabels = ticklabels.numel ();\n\n  if (nlabels == 0)\n    return;\n\n  for (int i = 0; i < nticks; i++)\n    {\n      double val = ticks(i);\n\n      if (lim1 <= val && val <= lim2)\n        {\n          Matrix b;\n\n          std::string label (ticklabels(i % nlabels));\n\n          // FIXME: As tick text is transparent, shouldn't it be\n          //        drawn after axes object, for correct rendering?\n          if (xyz == X_AXIS)\n            {\n              b = render_text (label, val, p1, p2, ha, va);\n            }\n          else if (xyz == Y_AXIS)\n            {\n              b = render_text (label, p1, val, p2, ha, va);\n            }\n          else if (xyz == Z_AXIS)\n            {\n              b = render_text (label, p1, p2, val, ha, va);\n            }\n\n          wmax = std::max (wmax, static_cast<int> (b(2)));\n          hmax = std::max (hmax, static_cast<int> (b(3)));\n        }\n    }\n\n#else\n\n  octave_unused_parameter (ticks);\n  octave_unused_parameter (ticklabels);\n  octave_unused_parameter (lim1);\n  octave_unused_parameter (lim2);\n  octave_unused_parameter (p1);\n  octave_unused_parameter (p2);\n  octave_unused_parameter (xyz);\n  octave_unused_parameter (ha);\n  octave_unused_parameter (va);\n  octave_unused_parameter (wmax);\n  octave_unused_parameter (hmax);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::render_ticktexts\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_zoom_rect (int x1, int y1, int x2, int y2)\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glVertex2d (x1, y1);\n  m_glfcns.glVertex2d (x2, y1);\n  m_glfcns.glVertex2d (x2, y2);\n  m_glfcns.glVertex2d (x1, y2);\n  m_glfcns.glVertex2d (x1, y1);\n\n#else\n\n  octave_unused_parameter (x1);\n  octave_unused_parameter (x2);\n  octave_unused_parameter (y1);\n  octave_unused_parameter (y2);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_zoom_rect\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_zoom_box (int width, int height,\n                                int x1, int y1, int x2, int y2,\n                                const Matrix& overlaycolor,\n                                double overlayalpha,\n                                const Matrix& bordercolor,\n                                double borderalpha, double borderwidth)\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glMatrixMode (GL_MODELVIEW);\n  m_glfcns.glPushMatrix ();\n  m_glfcns.glLoadIdentity ();\n\n  m_glfcns.glMatrixMode (GL_PROJECTION);\n  m_glfcns.glPushMatrix ();\n  m_glfcns.glLoadIdentity ();\n  m_glfcns.glOrtho (0, width, height, 0, 1, -1);\n\n  m_glfcns.glPushAttrib (GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT);\n  m_glfcns.glDisable (GL_DEPTH_TEST);\n\n  m_glfcns.glBegin (GL_POLYGON);\n  m_glfcns.glColor4f (overlaycolor(0), overlaycolor(1), overlaycolor(2),\n                      overlayalpha);\n  draw_zoom_rect (x1, y1, x2, y2);\n  m_glfcns.glEnd ();\n\n  m_glfcns.glLineWidth (borderwidth);\n  m_glfcns.glBegin (GL_LINE_STRIP);\n  m_glfcns.glColor4f (bordercolor(0), bordercolor(1), bordercolor(2),\n                      borderalpha);\n  draw_zoom_rect (x1, y1, x2, y2);\n  m_glfcns.glEnd ();\n\n  m_glfcns.glPopAttrib ();\n\n  m_glfcns.glMatrixMode (GL_MODELVIEW);\n  m_glfcns.glPopMatrix ();\n\n  m_glfcns.glMatrixMode (GL_PROJECTION);\n  m_glfcns.glPopMatrix ();\n\n#else\n\n  octave_unused_parameter (width);\n  octave_unused_parameter (height);\n  octave_unused_parameter (x1);\n  octave_unused_parameter (x2);\n  octave_unused_parameter (y1);\n  octave_unused_parameter (y2);\n  octave_unused_parameter (overlaycolor);\n  octave_unused_parameter (overlayalpha);\n  octave_unused_parameter (bordercolor);\n  octave_unused_parameter (borderalpha);\n  octave_unused_parameter (borderwidth);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_zoom_box\");\n\n#endif\n}\n\nuint8NDArray\nopengl_renderer::get_pixels (int width, int height)\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glPixelStorei (GL_PACK_ALIGNMENT, 1);\n  uint8NDArray pix(dim_vector (3, width, height), 0);\n\n  m_glfcns.glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE,\n                        pix.rwdata ());\n\n  // Permute and flip data\n  Array<octave_idx_type> perm (dim_vector (3, 1));\n  perm(0) = 2;\n  perm(1) = 1;\n  perm(2) = 0;\n\n  Array<idx_vector> idx (dim_vector (3, 1));\n  idx(0) = idx_vector::make_range (height - 1, -1, height);\n  idx(1) = idx_vector::colon;\n  idx(2) = idx_vector::colon;\n\n  return pix.permute (perm).index (idx);\n\n#else\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  octave_unused_parameter (width);\n  octave_unused_parameter (height);\n\n  error_unexpected (\"opengl_renderer::get_pixels\");\n\n#endif\n}\n\nvoid\nopengl_renderer::finish ()\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glFinish ();\n\n#else\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::finish\");\n\n#endif\n}\n\nvoid\nopengl_renderer::setup_opengl_transformation (const axes::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  // setup OpenGL transformation\n\n  Matrix x_zlim = props.get_transform_zlim ();\n\n  // Expand the distance between the clipping planes symmetrically by\n  // an arbitrary factor (see bug #54551).\n  const double expansion_fac = 100.0;\n  // Also make sure that the distance between the clipping planes\n  // differs in single precision (see bug #58956).  This factor is also\n  // arbitrary.  Different values (>2) might also work.\n  const double single_prec_fac = 10.0;\n\n  double avgZ = x_zlim(0) / 2.0 + x_zlim(1) / 2.0;\n  double span\n    = std::max (expansion_fac * (x_zlim(1)-x_zlim(0)),\n                single_prec_fac * std::abs (avgZ)\n                * std::numeric_limits<float>::epsilon ());\n  m_xZ1 = avgZ - span;\n  m_xZ2 = avgZ + span;\n\n  Matrix x_mat1 = props.get_opengl_matrix_1 ();\n  Matrix x_mat2 = props.get_opengl_matrix_2 ();\n\n  m_glfcns.glMatrixMode (GL_MODELVIEW);\n  m_glfcns.glLoadIdentity ();\n  m_glfcns.glScaled (1, 1, -1);\n  m_glfcns.glMultMatrixd (x_mat1.data ());\n  m_glfcns.glMatrixMode (GL_PROJECTION);\n  m_glfcns.glLoadIdentity ();\n\n  Matrix vp = get_viewport_scaled ();\n  m_glfcns.glOrtho (0, vp(2), vp(3), 0, m_xZ1, m_xZ2);\n  m_glfcns.glMultMatrixd (x_mat2.data ());\n  m_glfcns.glMatrixMode (GL_MODELVIEW);\n\n  m_glfcns.glClear (GL_DEPTH_BUFFER_BIT);\n\n  // store axes transformation data\n\n  m_xform = props.get_transform ();\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::setup_opengl_transformation\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_axes_planes (const axes::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  Matrix axe_color = props.get_color_rgb ();\n  if (axe_color.isempty () || ! props.is_visible ())\n    return;\n\n  double xPlane = props.get_xPlane ();\n  double yPlane = props.get_yPlane ();\n  double zPlane = props.get_zPlane ();\n  double xPlaneN = props.get_xPlaneN ();\n  double yPlaneN = props.get_yPlaneN ();\n  double zPlaneN = props.get_zPlaneN ();\n  bool is2D = props.get_is2D ();\n\n  // Axes planes\n  set_color (axe_color);\n  set_polygon_offset (true, 9.0);\n\n  m_glfcns.glBegin (GL_QUADS);\n\n  if (! is2D)\n    {\n      // X plane\n      m_glfcns.glVertex3d (xPlane, yPlaneN, zPlaneN);\n      m_glfcns.glVertex3d (xPlane, yPlane, zPlaneN);\n      m_glfcns.glVertex3d (xPlane, yPlane, zPlane);\n      m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane);\n\n      // Y plane\n      m_glfcns.glVertex3d (xPlaneN, yPlane, zPlaneN);\n      m_glfcns.glVertex3d (xPlane, yPlane, zPlaneN);\n      m_glfcns.glVertex3d (xPlane, yPlane, zPlane);\n      m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane);\n    }\n\n  // Z plane\n  m_glfcns.glVertex3d (xPlaneN, yPlaneN, zPlane);\n  m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane);\n  m_glfcns.glVertex3d (xPlane, yPlane, zPlane);\n  m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane);\n\n  m_glfcns.glEnd ();\n\n  set_polygon_offset (false);\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_axes_planes\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_axes_boxes (const axes::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  if (! props.is_visible ())\n    return;\n\n  bool xySym = props.get_xySym ();\n  bool layer2Dtop = props.get_layer2Dtop ();\n  bool is2D = props.get_is2D ();\n  bool isXOrigin = props.xaxislocation_is (\"origin\")\n                   && ! props.yscale_is (\"log\");\n  bool isYOrigin = props.yaxislocation_is (\"origin\")\n                   && ! props.xscale_is (\"log\");\n  bool boxFull = (props.get_boxstyle () == \"full\");\n  double linewidth = props.get_linewidth ();\n  double xPlane = props.get_xPlane ();\n  double yPlane = props.get_yPlane ();\n  double zPlane = props.get_zPlane ();\n  double xPlaneN = props.get_xPlaneN ();\n  double yPlaneN = props.get_yPlaneN ();\n  double zPlaneN = props.get_zPlaneN ();\n  double xpTick = props.get_xpTick ();\n  double ypTick = props.get_ypTick ();\n  double zpTick = props.get_zpTick ();\n  double xpTickN = props.get_xpTickN ();\n  double ypTickN = props.get_ypTickN ();\n  double zpTickN = props.get_zpTickN ();\n\n  bool plotyy = (props.has_property (\"__plotyy_axes__\"));\n\n  // Axes box\n\n  set_linecap (\"square\");\n  set_linestyle (\"-\", true, linewidth);\n\n  m_glfcns.glBegin (GL_LINES);\n\n  if (layer2Dtop)\n    std::swap (zpTick, zpTickN);\n\n  // X box\n  Matrix color = props.get_xcolor_rgb ();\n\n  if (! color.isempty ())\n    {\n      set_color (color);\n\n      if (! isXOrigin || props.is_box() || ! is2D)\n        {\n          m_glfcns.glVertex3d (xPlaneN, ypTick, zpTick);\n          m_glfcns.glVertex3d (xPlane, ypTick, zpTick);\n        }\n\n      if (props.is_box ())\n        {\n          m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTick);\n          m_glfcns.glVertex3d (xPlane, ypTickN, zpTick);\n          if (! is2D)\n            {\n              m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTickN);\n              m_glfcns.glVertex3d (xPlane, ypTickN, zpTickN);\n              if (boxFull)\n                {\n                  m_glfcns.glVertex3d (xPlaneN, ypTick, zpTickN);\n                  m_glfcns.glVertex3d (xPlane, ypTick, zpTickN);\n                }\n            }\n        }\n    }\n\n  // Y box\n  color = props.get_ycolor_rgb ();\n\n  if (! color.isempty ())\n    {\n      set_color (color);\n      if (! isYOrigin || props.is_box() || ! is2D)\n        {\n          m_glfcns.glVertex3d (xpTick, yPlaneN, zpTick);\n          m_glfcns.glVertex3d (xpTick, yPlane, zpTick);\n        }\n\n      if (props.is_box () && ! plotyy)\n        {\n          m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTick);\n          m_glfcns.glVertex3d (xpTickN, yPlane, zpTick);\n\n          if (! is2D)\n            {\n              m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTickN);\n              m_glfcns.glVertex3d (xpTickN, yPlane, zpTickN);\n              if (boxFull)\n                {\n                  m_glfcns.glVertex3d (xpTick, yPlaneN, zpTickN);\n                  m_glfcns.glVertex3d (xpTick, yPlane, zpTickN);\n                }\n            }\n        }\n    }\n\n  // Z box\n  color = props.get_zcolor_rgb ();\n\n  if (! color.isempty () && ! is2D)\n    {\n      set_color (color);\n\n      if (xySym)\n        {\n          m_glfcns.glVertex3d (xPlaneN, yPlane, zPlaneN);\n          m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane);\n        }\n      else\n        {\n          m_glfcns.glVertex3d (xPlane, yPlaneN, zPlaneN);\n          m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane);\n        }\n\n      if (props.is_box ())\n        {\n          m_glfcns.glVertex3d (xPlane, yPlane, zPlaneN);\n          m_glfcns.glVertex3d (xPlane, yPlane, zPlane);\n\n          if (xySym)\n            {\n              m_glfcns.glVertex3d (xPlane, yPlaneN, zPlaneN);\n              m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane);\n            }\n          else\n            {\n              m_glfcns.glVertex3d (xPlaneN, yPlane, zPlaneN);\n              m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane);\n            }\n\n          if (boxFull)\n            {\n              m_glfcns.glVertex3d (xPlaneN, yPlaneN, zPlaneN);\n              m_glfcns.glVertex3d (xPlaneN, yPlaneN, zPlane);\n            }\n        }\n    }\n\n  m_glfcns.glEnd ();\n\n  set_linestyle (\"-\");  // Disable LineStipple\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_axes_boxes\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_axes_x_grid (const axes::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  int xstate = props.get_xstate ();\n\n  if (xstate != AXE_DEPTH_DIR\n      && (props.is_visible ()\n          || (m_selecting && props.pickableparts_is (\"all\"))))\n    {\n      int zstate = props.get_zstate ();\n      bool x2Dtop = props.get_x2Dtop ();\n      bool layer2Dtop = props.get_layer2Dtop ();\n      bool xyzSym = props.get_xyzSym ();\n      bool nearhoriz = props.get_nearhoriz ();\n      double xticklen = props.get_xticklen ();\n      double xtickoffset = props.get_xtickoffset ();\n      double fy = props.get_fy ();\n      double fz = props.get_fz ();\n      double x_min = props.get_x_min ();\n      double x_max = props.get_x_max ();\n      double y_min = props.get_y_min ();\n      double y_max = props.get_y_max ();\n      double yPlane = props.get_yPlane ();\n      double yPlaneN = props.get_yPlaneN ();\n      double ypTick = props.get_ypTick ();\n      double ypTickN = props.get_ypTickN ();\n      double zPlane = props.get_zPlane ();\n      double zPlaneN = props.get_zPlaneN ();\n      double zpTick = props.get_zpTick ();\n      double zpTickN = props.get_zpTickN ();\n\n      // X ticks and grid properties\n      Matrix xticks = m_xform.xscale (props.get_xtick ().matrix_value ());\n      Matrix xmticks = m_xform.xscale (props.get_xminortickvalues ().matrix_value ());\n      bool do_xtick = ! props.tickdir_is (\"none\") && ! xticks.isempty ();\n      bool do_xminortick = do_xtick && props.is_xminortick ();\n      string_vector xticklabels = props.get_xticklabel ().string_vector_value ();\n      int wmax = 0;\n      int hmax = 0;\n      bool tick_along_z = nearhoriz || math::isinf (fy);\n      double linewidth = props.get_linewidth ();\n      std::string gridstyle = props.get_gridlinestyle ();\n      std::string minorgridstyle = props.get_minorgridlinestyle ();\n      Matrix gridcolor = props.get_gridcolor_rgb ();\n      Matrix minorgridcolor = props.get_minorgridcolor_rgb ();\n      double gridalpha = props.get_gridalpha ();\n      double minorgridalpha = props.get_minorgridalpha ();\n      bool do_xgrid = (props.is_xgrid () && (gridstyle != \"none\"));\n      bool do_xminorgrid = (props.is_xminorgrid ()\n                            && (minorgridstyle != \"none\")\n                            && ! xticks.isempty ());\n      bool is_origin = props.xaxislocation_is (\"origin\") && props.get_is2D ()\n                       && ! props.yscale_is (\"log\");\n      bool is_origin_low = is_origin && (y_min + y_max) < 0;\n      bool mirror = props.is_box () && xstate != AXE_ANY_DIR;\n      bool is_tickdir_both = props.tickdir_is (\"both\");\n\n      // X grid\n\n      // possibly use axis color for gridcolor & minorgridcolor\n      if (props.gridcolormode_is (\"auto\"))\n        if (props.xcolormode_is (\"manual\") && ! props.xcolor_is (\"none\"))\n          gridcolor = props.get_xcolor_rgb ();\n\n      if (props.minorgridcolormode_is (\"auto\"))\n        if (props.xcolormode_is (\"manual\") && ! props.xcolor_is (\"none\"))\n          minorgridcolor = props.get_xcolor_rgb ();\n\n      if (gridcolor.isempty ())\n        do_xgrid = false;\n\n      if (minorgridcolor.isempty ())\n        do_xminorgrid = false;\n\n      // set styles when drawing only minor grid\n      if (do_xminorgrid && ! do_xgrid)\n        {\n          gridstyle = minorgridstyle;\n          gridcolor = minorgridcolor;\n          gridalpha = minorgridalpha;\n          do_xgrid = true;\n        }\n\n      // minor grid lines\n      if (do_xminorgrid)\n        render_grid (linewidth,\n                     minorgridstyle, minorgridcolor, minorgridalpha,\n                     xmticks, x_min, x_max,\n                     yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,\n                     0, (zstate != AXE_DEPTH_DIR));\n\n      // grid lines\n      if (do_xgrid)\n        render_grid (linewidth,\n                     gridstyle, gridcolor, gridalpha,\n                     xticks, x_min, x_max,\n                     yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,\n                     0, (zstate != AXE_DEPTH_DIR));\n\n      // Skip drawing axis, ticks, and ticklabels when color is \"none\"\n      if (props.xcolor_is (\"none\"))\n        return;\n\n      set_color (props.get_xcolor_rgb ());\n\n      // axis line\n      double y_axis_pos = 0.;\n      if (is_origin)\n        {\n          y_axis_pos = math::max (math::min (0., y_max), y_min);\n          m_glfcns.glBegin (GL_LINES);\n          set_color (props.get_xcolor_rgb ());\n          m_glfcns.glVertex3d (x_min, y_axis_pos, zpTick);\n          m_glfcns.glVertex3d (x_max, y_axis_pos, zpTick);\n          m_glfcns.glEnd ();\n        }\n\n      // minor tick marks\n      if (do_xminortick)\n        {\n          if (tick_along_z)\n            render_tickmarks (xmticks, x_min, x_max,\n                              is_origin ? y_axis_pos : ypTick, ypTick,\n                              zpTick, zpTickN,\n                              0., 0., (is_origin_low ? -1. : 1.) *\n                              math::signum (zpTick-zpTickN)*fz*xticklen/2,\n                              0, ! is_origin && mirror, is_tickdir_both);\n          else\n            render_tickmarks (xmticks, x_min, x_max,\n                              is_origin ? y_axis_pos : ypTick, ypTickN,\n                              zpTick, zpTick,\n                              0., (is_origin_low ? -1. : 1.) *\n                              math::signum (ypTick-ypTickN)*fy*xticklen/2, 0.,\n                              0, ! is_origin && mirror, is_tickdir_both);\n        }\n\n      // tick marks\n      if (do_xtick)\n        {\n          if (tick_along_z)\n            render_tickmarks (xticks, x_min, x_max,\n                              is_origin ? y_axis_pos : ypTick, ypTick,\n                              zpTick, zpTickN,\n                              0., 0., (is_origin_low ? -1. : 1.) *\n                              math::signum (zpTick-zpTickN)*fz*xticklen,\n                              0, ! is_origin && mirror, is_tickdir_both);\n          else\n            render_tickmarks (xticks, x_min, x_max,\n                              is_origin ? y_axis_pos : ypTick, ypTickN,\n                              zpTick, zpTick,\n                              0., (is_origin_low ? -1. : 1.) *\n                              math::signum (ypTick-ypTickN)*fy*xticklen, 0.,\n                              0, ! is_origin && mirror, is_tickdir_both);\n        }\n\n      // tick texts\n      if (xticklabels.numel () > 0)\n        {\n          int halign = (xstate == AXE_HORZ_DIR\n                        ? 1\n                        : (xyzSym || is_origin_low ? 0 : 2));\n          int valign = (xstate == AXE_VERT_DIR\n                        ? 1\n                        : (x2Dtop || is_origin_low ? 0 : 2));\n\n          if (tick_along_z)\n            render_ticktexts (xticks, xticklabels, x_min, x_max,\n                              is_origin ? y_axis_pos : ypTick,\n                              zpTick +\n                              (is_origin_low ? -1. : 1.) *\n                              math::signum (zpTick-zpTickN)*fz*xtickoffset,\n                              0, halign, valign, wmax, hmax);\n          else\n            render_ticktexts (xticks, xticklabels, x_min, x_max,\n                              (is_origin ? y_axis_pos : ypTick) +\n                              (is_origin_low ?  -1. : 1.) *\n                              math::signum (ypTick-ypTickN)*fy*xtickoffset,\n                              zpTick, 0, halign, valign, wmax, hmax);\n        }\n    }\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_axes_x_grid\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_axes_y_grid (const axes::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  int ystate = props.get_ystate ();\n\n  if (ystate != AXE_DEPTH_DIR && props.is_visible ()\n      && (props.is_visible ()\n          || (m_selecting && props.pickableparts_is (\"all\"))))\n    {\n      int zstate = props.get_zstate ();\n      bool y2Dright = props.get_y2Dright ();\n      bool layer2Dtop = props.get_layer2Dtop ();\n      bool xyzSym = props.get_xyzSym ();\n      bool nearhoriz = props.get_nearhoriz ();\n      double yticklen = props.get_yticklen ();\n      double ytickoffset = props.get_ytickoffset ();\n      double fx = props.get_fx ();\n      double fz = props.get_fz ();\n      double xPlane = props.get_xPlane ();\n      double xPlaneN = props.get_xPlaneN ();\n      double xpTick = props.get_xpTick ();\n      double xpTickN = props.get_xpTickN ();\n      double y_min = props.get_y_min ();\n      double y_max = props.get_y_max ();\n      double x_min = props.get_x_min ();\n      double x_max = props.get_x_max ();\n      double zPlane = props.get_zPlane ();\n      double zPlaneN = props.get_zPlaneN ();\n      double zpTick = props.get_zpTick ();\n      double zpTickN = props.get_zpTickN ();\n\n      // Y ticks and grid properties\n      Matrix yticks = m_xform.yscale (props.get_ytick ().matrix_value ());\n      Matrix ymticks = m_xform.yscale (props.get_yminortickvalues ().matrix_value ());\n      bool do_ytick = ! props.tickdir_is (\"none\") && ! yticks.isempty ();\n      bool do_yminortick = do_ytick && props.is_yminortick ();\n      string_vector yticklabels = props.get_yticklabel ().string_vector_value ();\n      int wmax = 0;\n      int hmax = 0;\n      bool tick_along_z = nearhoriz || math::isinf (fx);\n      double linewidth = props.get_linewidth ();\n      std::string gridstyle = props.get_gridlinestyle ();\n      std::string minorgridstyle = props.get_minorgridlinestyle ();\n      Matrix gridcolor = props.get_gridcolor_rgb ();\n      Matrix minorgridcolor = props.get_minorgridcolor_rgb ();\n      double gridalpha = props.get_gridalpha ();\n      double minorgridalpha = props.get_minorgridalpha ();\n      bool do_ygrid = (props.is_ygrid () && (gridstyle != \"none\"));\n      bool do_yminorgrid = (props.is_yminorgrid ()\n                            && (minorgridstyle != \"none\")\n                            && ! yticks.isempty ());\n      bool is_origin = props.yaxislocation_is (\"origin\") && props.get_is2D ()\n                       && ! props.xscale_is (\"log\");\n      bool is_origin_low = is_origin && (x_min + x_max) < 0;\n      bool mirror = props.is_box () && ystate != AXE_ANY_DIR\n                    && (! props.has_property (\"__plotyy_axes__\"));\n      bool is_tickdir_both = props.tickdir_is (\"both\");\n\n      // Y grid\n\n      // possibly use axis color for gridcolor & minorgridcolor\n      if (props.gridcolormode_is (\"auto\"))\n        if (props.ycolormode_is (\"manual\") && ! props.ycolor_is (\"none\"))\n          gridcolor = props.get_ycolor_rgb ();\n\n      if (props.minorgridcolormode_is (\"auto\"))\n        if (props.ycolormode_is (\"manual\") && ! props.ycolor_is (\"none\"))\n          minorgridcolor = props.get_ycolor_rgb ();\n\n      if (gridcolor.isempty ())\n        do_ygrid = false;\n\n      if (minorgridcolor.isempty ())\n        do_yminorgrid = false;\n\n      // set styles when drawing only minor grid\n      if (do_yminorgrid && ! do_ygrid)\n        {\n          gridstyle = minorgridstyle;\n          gridcolor = minorgridcolor;\n          gridalpha = minorgridalpha;\n          do_ygrid = true;\n        }\n\n      // minor grid lines\n      if (do_yminorgrid)\n        render_grid (linewidth,\n                     minorgridstyle, minorgridcolor, minorgridalpha,\n                     ymticks, y_min, y_max,\n                     xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,\n                     1, (zstate != AXE_DEPTH_DIR));\n\n      // grid lines\n      if (do_ygrid)\n        render_grid (linewidth,\n                     gridstyle, gridcolor, gridalpha,\n                     yticks, y_min, y_max,\n                     xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,\n                     1, (zstate != AXE_DEPTH_DIR));\n\n      // Skip drawing axis, ticks, and ticklabels when color is \"none\"\n      if (props.ycolor_is (\"none\"))\n        return;\n\n      set_color (props.get_ycolor_rgb ());\n\n      // axis line\n      double x_axis_pos = 0.;\n      if (is_origin)\n        {\n          x_axis_pos = math::max (math::min (0., x_max), x_min);\n          m_glfcns.glBegin (GL_LINES);\n          set_color (props.get_ycolor_rgb ());\n          m_glfcns.glVertex3d (x_axis_pos, y_min, zpTick);\n          m_glfcns.glVertex3d (x_axis_pos, y_max, zpTick);\n          m_glfcns.glEnd ();\n        }\n\n      // minor tick marks\n      if (do_yminortick)\n        {\n          if (tick_along_z)\n            render_tickmarks (ymticks, y_min, y_max,\n                              is_origin ? x_axis_pos : xpTick, xpTick,\n                              zpTick, zpTickN,\n                              0., 0., (is_origin_low ? -1. : 1.) *\n                              math::signum (zpTick-zpTickN)*fz*yticklen/2,\n                              1, ! is_origin && mirror, is_tickdir_both);\n          else\n            render_tickmarks (ymticks, y_min, y_max,\n                              is_origin ? x_axis_pos : xpTick, xpTickN,\n                              zpTick, zpTick,\n                              (is_origin_low ? -1. : 1.) *\n                              math::signum (xpTick-xpTickN)*fx*yticklen/2, 0., 0.,\n                              1, ! is_origin && mirror, is_tickdir_both);\n        }\n\n      // tick marks\n      if (do_ytick)\n        {\n          if (tick_along_z)\n            render_tickmarks (yticks, y_min, y_max,\n                              is_origin ? x_axis_pos : xpTick, xpTick,\n                              zpTick, zpTickN,\n                              0., 0., (is_origin_low ? -1. : 1.) *\n                              math::signum (zpTick-zpTickN)*fz*yticklen,\n                              1, ! is_origin && mirror, is_tickdir_both);\n          else\n            render_tickmarks (yticks, y_min, y_max,\n                              is_origin ? x_axis_pos : xpTick, xpTickN,\n                              zpTick, zpTick,\n                              (is_origin_low ? -1. : 1.) *\n                              math::signum (xPlaneN-xPlane)*fx*yticklen, 0., 0.,\n                              1, ! is_origin && mirror, is_tickdir_both);\n        }\n\n      // tick texts\n      if (yticklabels.numel () > 0)\n        {\n          int halign = (ystate == AXE_HORZ_DIR\n                        ? 1\n                        : (! xyzSym || y2Dright || is_origin_low ? 0 : 2));\n          int valign = (ystate == AXE_VERT_DIR\n                        ? 1\n                        : (is_origin_low ? 0 : 2));\n\n          if (tick_along_z)\n            render_ticktexts (yticks, yticklabels, y_min, y_max,\n                              is_origin ? x_axis_pos : xpTick,\n                              zpTick +\n                              (is_origin_low ? -1. : 1.) *\n                              math::signum (zpTick-zpTickN)*fz*ytickoffset,\n                              1, halign, valign, wmax, hmax);\n          else\n            render_ticktexts (yticks, yticklabels, y_min, y_max,\n                              (is_origin ? x_axis_pos : xpTick) +\n                              (is_origin_low ?  -1. : 1.) *\n                              math::signum (xpTick-xpTickN)*fx*ytickoffset,\n                              zpTick, 1, halign, valign, wmax, hmax);\n        }\n    }\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_axes_y_grid\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_axes_z_grid (const axes::properties& props)\n{\n\n  int zstate = props.get_zstate ();\n\n  if (zstate != AXE_DEPTH_DIR && props.is_visible ()\n      && (props.is_visible ()\n          || (m_selecting && props.pickableparts_is (\"all\"))))\n    {\n      bool xySym = props.get_xySym ();\n      bool zSign = props.get_zSign ();\n      double zticklen = props.get_zticklen ();\n      double ztickoffset = props.get_ztickoffset ();\n      double fx = props.get_fx ();\n      double fy = props.get_fy ();\n      double xPlane = props.get_xPlane ();\n      double xPlaneN = props.get_xPlaneN ();\n      double yPlane = props.get_yPlane ();\n      double yPlaneN = props.get_yPlaneN ();\n      double z_min = props.get_z_min ();\n      double z_max = props.get_z_max ();\n\n      // Z ticks and grid properties\n      Matrix zticks = m_xform.zscale (props.get_ztick ().matrix_value ());\n      Matrix zmticks = m_xform.zscale (props.get_zminortickvalues ().matrix_value ());\n      bool do_ztick = ! props.tickdir_is (\"none\") && ! zticks.isempty ();\n      bool do_zminortick = do_ztick && props.is_zminortick ();\n      string_vector zticklabels = props.get_zticklabel ().string_vector_value ();\n      int wmax = 0;\n      int hmax = 0;\n      double linewidth = props.get_linewidth ();\n      std::string gridstyle = props.get_gridlinestyle ();\n      std::string minorgridstyle = props.get_minorgridlinestyle ();\n      Matrix gridcolor = props.get_gridcolor_rgb ();\n      Matrix minorgridcolor = props.get_minorgridcolor_rgb ();\n      double gridalpha = props.get_gridalpha ();\n      double minorgridalpha = props.get_minorgridalpha ();\n      bool do_zgrid = (props.is_zgrid () && (gridstyle != \"none\"));\n      bool do_zminorgrid = (props.is_zminorgrid ()\n                            && (minorgridstyle != \"none\")\n                            && ! zticks.isempty ());\n      bool mirror = props.is_box () && zstate != AXE_ANY_DIR;\n      bool is_tickdir_both = props.tickdir_is (\"both\");\n\n      // Z grid\n\n      // possibly use axis color for gridcolor & minorgridcolor\n      if (props.gridcolormode_is (\"auto\"))\n        if (props.zcolormode_is (\"manual\") && ! props.zcolor_is (\"none\"))\n          gridcolor = props.get_zcolor_rgb ();\n\n      if (props.minorgridcolormode_is (\"auto\"))\n        if (props.zcolormode_is (\"manual\") && ! props.zcolor_is (\"none\"))\n          minorgridcolor = props.get_zcolor_rgb ();\n\n      if (gridcolor.isempty ())\n        do_zgrid = false;\n\n      if (minorgridcolor.isempty ())\n        do_zminorgrid = false;\n\n      // set styles when drawing only minor grid\n      if (do_zminorgrid && ! do_zgrid)\n        {\n          gridstyle = minorgridstyle;\n          gridcolor = minorgridcolor;\n          gridalpha = minorgridalpha;\n          do_zgrid = true;\n        }\n\n      // minor grid lines\n      if (do_zminorgrid)\n        render_grid (linewidth,\n                     minorgridstyle, minorgridcolor, minorgridalpha,\n                     zmticks, z_min, z_max,\n                     xPlane, xPlaneN, yPlane, yPlaneN, 2, true);\n\n      // grid lines\n      if (do_zgrid)\n        render_grid (linewidth,\n                     gridstyle, gridcolor, gridalpha,\n                     zticks, z_min, z_max,\n                     xPlane, xPlaneN, yPlane, yPlaneN, 2, true);\n\n      // Skip drawing axis, ticks, and ticklabels when color is \"none\"\n      if (props.zcolor_is (\"none\"))\n        return;\n\n      set_color (props.get_zcolor_rgb ());\n\n      // minor tick marks\n      if (do_zminortick)\n        {\n          if (xySym)\n            {\n              if (math::isinf (fy))\n                render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane,\n                                  yPlane, yPlane,\n                                  math::signum (xPlaneN-xPlane)*fx*zticklen/2, 0., 0.,\n                                  2, mirror, is_tickdir_both);\n              else\n                render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN,\n                                  yPlane, yPlane,\n                                  0., math::signum (yPlane-yPlaneN)*fy*zticklen/2, 0.,\n                                  2, false, is_tickdir_both);\n            }\n          else\n            {\n              if (math::isinf (fx))\n                render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,\n                                  yPlaneN, yPlane,\n                                  0., math::signum (yPlaneN-yPlane)*fy*zticklen/2, 0.,\n                                  2, mirror, is_tickdir_both);\n              else\n                render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,\n                                  yPlaneN, yPlaneN,\n                                  math::signum (xPlane-xPlaneN)*fx*zticklen/2, 0., 0.,\n                                  2, false, is_tickdir_both);\n            }\n        }\n\n      // tick marks\n      if (do_ztick)\n        {\n          if (xySym)\n            {\n              if (math::isinf (fy))\n                render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,\n                                  yPlane, yPlane,\n                                  math::signum (xPlaneN-xPlane)*fx*zticklen, 0., 0.,\n                                  2, mirror, is_tickdir_both);\n              else\n                render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,\n                                  yPlane, yPlane,\n                                  0., math::signum (yPlane-yPlaneN)*fy*zticklen, 0.,\n                                  2, false, is_tickdir_both);\n            }\n          else\n            {\n              if (math::isinf (fx))\n                render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,\n                                  yPlaneN, yPlane,\n                                  0., math::signum (yPlaneN-yPlane)*fy*zticklen, 0.,\n                                  2, mirror, is_tickdir_both);\n              else\n                render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,\n                                  yPlaneN, yPlane,\n                                  math::signum (xPlane-xPlaneN)*fx*zticklen, 0., 0.,\n                                  2, false, is_tickdir_both);\n            }\n        }\n\n      // tick texts\n      if (zticklabels.numel () > 0)\n        {\n          int halign = 2;\n          int valign = (zstate == AXE_VERT_DIR ? 1 : (zSign ? 3 : 2));\n\n          if (xySym)\n            {\n              if (math::isinf (fy))\n                render_ticktexts (zticks, zticklabels, z_min, z_max,\n                                  xPlaneN + math::signum (xPlaneN-xPlane)*fx*ztickoffset,\n                                  yPlane, 2, halign, valign, wmax, hmax);\n              else\n                render_ticktexts (zticks, zticklabels, z_min, z_max, xPlaneN,\n                                  yPlane + math::signum (yPlane-yPlaneN)*fy*ztickoffset,\n                                  2, halign, valign, wmax, hmax);\n            }\n          else\n            {\n              if (math::isinf (fx))\n                render_ticktexts (zticks, zticklabels, z_min, z_max, xPlane,\n                                  yPlaneN + math::signum (yPlaneN-yPlane)*fy*ztickoffset,\n                                  2, halign, valign, wmax, hmax);\n              else\n                render_ticktexts (zticks, zticklabels, z_min, z_max,\n                                  xPlane + math::signum (xPlane-xPlaneN)*fx*ztickoffset,\n                                  yPlaneN, 2, halign, valign, wmax, hmax);\n            }\n        }\n    }\n}\n\nvoid\nopengl_renderer::draw_axes_grids (const axes::properties& props)\n{\n#if defined (HAVE_OPENGL)\n  // Disable line smoothing for axes\n  GLboolean antialias;\n\n  m_glfcns.glGetBooleanv (GL_LINE_SMOOTH, &antialias);\n\n  if (antialias == GL_TRUE)\n    m_glfcns.glDisable (GL_LINE_SMOOTH);\n\n  set_linecap (\"butt\");\n  set_linewidth (props.get_linewidth ());\n  set_font (props);\n  set_interpreter (props.get_ticklabelinterpreter ());\n\n  draw_axes_x_grid (props);\n  draw_axes_y_grid (props);\n  draw_axes_z_grid (props);\n\n  if (antialias == GL_TRUE)\n    m_glfcns.glEnable (GL_LINE_SMOOTH);\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_axes_grids\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_all_lights (const base_properties& props,\n                                  std::list<graphics_object>& obj_list)\n{\n#if defined (HAVE_OPENGL)\n  gh_manager& gh_mgr = __get_gh_manager__ ();\n\n  Matrix children = props.get_all_children ();\n\n  for (octave_idx_type i = children.numel () - 1; i >= 0; i--)\n    {\n      graphics_object go = gh_mgr.get_object (children(i));\n\n      base_properties& p = go.get_properties ();\n\n      if (p.is_visible ()\n          || (m_selecting && p.pickableparts_is (\"all\")))\n        {\n          if (go.isa (\"light\") && ! m_selecting)\n            {\n              if (m_current_light-GL_LIGHT0 < m_max_lights)\n                {\n                  set_clipping (p.is_clipping ());\n                  draw (go);\n                  m_current_light++;\n                }\n            }\n          else if (go.isa (\"hggroup\")\n                   && ! (m_selecting && p.pickableparts_is (\"none\")))\n            draw_all_lights (go.get_properties (), obj_list);\n          else if (! (m_selecting && p.pickableparts_is (\"none\")))\n            obj_list.push_back (go);\n        }\n    }\n#else\n\n  octave_unused_parameter (props);\n  octave_unused_parameter (obj_list);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_all_lights\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_axes_children (const axes::properties& props)\n{\n#if defined (HAVE_OPENGL)\n  // list for non-light child objects\n  std::list<graphics_object> obj_list;\n  std::list<graphics_object>::iterator it;\n\n  // 1st pass: draw light objects\n\n  // FIXME: max_lights only needs to be set once.\n  // It would be better if this could be in the constructor for gl_renderer\n  // but this seems to lead to calls of OpenGL functions before the context\n  // is actually initialized.  See bug #48669.\n  // Check actual maximum number of lights possible\n  init_maxlights ();\n\n  // Start with the last element of the array of child objects to\n  // display them in the order they were added to the array.\n\n  if (props.get_num_lights () > m_max_lights)\n    warning_with_id (\"Octave:max-lights-exceeded\",\n                     \"light: Maximum number of lights (%d) in these axes is \"\n                     \"exceeded.\", m_max_lights);\n\n  m_current_light = GL_LIGHT0;\n  draw_all_lights (props, obj_list);\n\n  // disable other OpenGL lights\n  for (unsigned int i = props.get_num_lights (); i < m_max_lights; i++)\n    m_glfcns.glDisable (GL_LIGHT0 + i);\n\n  // save camera position and set ambient light color before drawing\n  // other objects\n  m_view_vector = props.get_cameraposition ().matrix_value ();\n\n  float cb[4] = { 1.0, 1.0, 1.0, 1.0 };\n  ColumnVector ambient_color = props.get_ambientlightcolor_rgb ();\n  for (int i = 0; i < 3; i++)\n    cb[i] = ambient_color(i);\n  m_glfcns.glLightfv (GL_LIGHT0, GL_AMBIENT, cb);\n\n  // 2nd pass: draw other objects (with units set to \"data\")\n\n  it = obj_list.begin ();\n  while (it != obj_list.end ())\n    {\n      graphics_object go = (*it);\n\n      // FIXME: check whether object has \"units\" property and it is set\n      // to \"data\"\n      if (! go.isa (\"text\") || go.get (\"units\").string_value () == \"data\")\n        {\n          set_clipping (go.get_properties ().is_clipping ());\n          draw (go);\n\n          it = obj_list.erase (it);\n        }\n      else\n        it++;\n    }\n\n  // 3rd pass: draw remaining objects\n\n  m_glfcns.glDisable (GL_DEPTH_TEST);\n\n  for (const graphics_object& go : obj_list)\n    {\n      set_clipping (go.get_properties ().is_clipping ());\n      draw (go);\n    }\n\n  set_clipping (false);\n\n  // FIXME: finalize rendering (transparency processing)\n  // FIXME: draw zoom box, if needed\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_axes_children\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_axes (const axes::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  // Legends are not drawn when \"visible\" is \"off\".\n  if (! props.is_visible () && props.get_tag () == \"legend\")\n    return;\n\n  // Don't draw the axes and its children if we are in selection and\n  // pickable parts is \"none\".\n  if (m_selecting && props.pickableparts_is (\"none\"))\n    return;\n\n  static double floatmax = std::numeric_limits<float>::max ();\n\n  double x_min = props.get_x_min ();\n  double x_max = props.get_x_max ();\n  double y_min = props.get_y_min ();\n  double y_max = props.get_y_max ();\n  double z_min = props.get_z_min ();\n  double z_max = props.get_z_max ();\n\n  if (x_max > floatmax || y_max > floatmax || z_max > floatmax\n      || x_min < -floatmax || y_min < -floatmax || z_min < -floatmax)\n    {\n      warning (\"opengl_renderer: data values greater than float capacity.  (1) Scale data, or (2) Use gnuplot\");\n      return;\n    }\n\n  setup_opengl_transformation (props);\n\n  // For 2-D axes with only 2-D primitives, draw from back to front without\n  // depth sorting\n  bool is2D = props.get_is2D (true);\n  if (is2D)\n    m_glfcns.glDisable (GL_DEPTH_TEST);\n  else\n    m_glfcns.glEnable (GL_DEPTH_TEST);\n\n  draw_axes_planes (props);\n\n  if (! is2D || props.layer_is (\"bottom\"))\n    {\n      draw_axes_grids (props);\n      if (props.get_tag () != \"legend\" || props.get_box () != \"off\")\n        draw_axes_boxes (props);\n    }\n\n  set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max);\n\n  draw_axes_children (props);\n\n  if (is2D && props.layer_is (\"top\"))\n    {\n      draw_axes_grids (props);\n      if (props.get_tag () != \"legend\" || props.get_box () != \"off\")\n        draw_axes_boxes (props);\n    }\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_axes\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_line (const line::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  bool draw_all = m_selecting && props.pickableparts_is (\"all\");\n\n  Matrix x = m_xform.xscale (props.get_xdata ().matrix_value ());\n  Matrix y = m_xform.yscale (props.get_ydata ().matrix_value ());\n  Matrix z = m_xform.zscale (props.get_zdata ().matrix_value ());\n\n  bool has_z = (z.numel () > 0);\n  int n = static_cast<int> (std::min (std::min (x.numel (), y.numel ()),\n                                      (has_z ? z.numel ()\n                                       : std::numeric_limits<int>::max ())));\n  uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40);\n  uint8_t clip_ok = 0x40;\n\n  std::vector<uint8_t> clip (n);\n\n  if (has_z)\n    for (int i = 0; i < n; i++)\n      clip[i] = (clip_code (x(i), y(i), z(i)) & clip_mask);\n  else\n    {\n      double z_mid = (m_zmin+m_zmax)/2;\n\n      for (int i = 0; i < n; i++)\n        clip[i] = (clip_code (x(i), y(i), z_mid) & clip_mask);\n    }\n\n  if (! props.linestyle_is (\"none\") && ! props.color_is (\"none\"))\n    {\n      set_color (props.get_color_rgb ());\n      set_linestyle (props.get_linestyle (), false, props.get_linewidth ());\n      set_linewidth (props.get_linewidth ());\n      set_linecap (\"butt\");\n      set_linejoin (props.get_linejoin ());\n\n      if (has_z)\n        {\n          bool flag = false;\n\n          for (int i = 1; i < n; i++)\n            {\n              if ((clip[i-1] & clip[i]) == clip_ok)\n                {\n                  if (! flag)\n                    {\n                      flag = true;\n                      m_glfcns.glBegin (GL_LINE_STRIP);\n                      m_glfcns.glVertex3d (x(i-1), y(i-1), z(i-1));\n                    }\n                  m_glfcns.glVertex3d (x(i), y(i), z(i));\n                }\n              else if (flag)\n                {\n                  flag = false;\n                  m_glfcns.glEnd ();\n                }\n            }\n\n          if (flag)\n            m_glfcns.glEnd ();\n        }\n      else\n        {\n          bool flag = false;\n\n          for (int i = 1; i < n; i++)\n            {\n              if ((clip[i-1] & clip[i]) == clip_ok)\n                {\n                  if (! flag)\n                    {\n                      flag = true;\n                      m_glfcns.glBegin (GL_LINE_STRIP);\n                      m_glfcns.glVertex2d (x(i-1), y(i-1));\n                    }\n                  m_glfcns.glVertex2d (x(i), y(i));\n                }\n              else if (flag)\n                {\n                  flag = false;\n                  m_glfcns.glEnd ();\n                }\n            }\n\n          if (flag)\n            m_glfcns.glEnd ();\n        }\n\n      set_linewidth (0.5f);\n      set_linestyle (\"-\");\n    }\n\n  set_clipping (false);\n\n  if (! props.marker_is (\"none\")\n      && ! (props.markeredgecolor_is (\"none\")\n            && props.markerfacecolor_is (\"none\")))\n    {\n      Matrix lc, fc;\n\n      if (draw_all)\n        lc = Matrix (1, 3, 0.0);\n      else if (props.markeredgecolor_is (\"auto\"))\n        lc = props.get_color_rgb ();\n      else if (! props.markeredgecolor_is (\"none\"))\n        lc = props.get_markeredgecolor_rgb ();\n\n      if (draw_all)\n        fc = Matrix (1, 3, 0.0);\n      if (props.markerfacecolor_is (\"auto\"))\n        fc = props.get_color_rgb ();\n      else if (! props.markerfacecolor_is (\"none\"))\n        fc = props.get_markerfacecolor_rgb ();\n\n      init_marker (props.get_marker (), props.get_markersize (),\n                   props.get_linewidth ());\n\n      for (int i = 0; i < n; i++)\n        {\n          if (clip[i] == clip_ok)\n            draw_marker (x(i), y(i),\n                         has_z ? z(i) : 0.0,\n                         lc, fc);\n        }\n\n      end_marker ();\n    }\n\n  set_clipping (props.is_clipping ());\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_line\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_surface (const surface::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  bool draw_all = m_selecting && props.pickableparts_is (\"all\");\n\n  const Matrix x = m_xform.xscale (props.get_xdata ().matrix_value ());\n  const Matrix y = m_xform.yscale (props.get_ydata ().matrix_value ());\n  const Matrix z = m_xform.zscale (props.get_zdata ().matrix_value ());\n\n  int zr = z.rows ();\n  int zc = z.columns ();\n\n  NDArray c;\n  const NDArray vn = props.get_vertexnormals ().array_value ();\n  const dim_vector& vn_dims = vn.dims ();\n  bool has_vertex_normals = (vn_dims(0) == zr && vn_dims(1) == zc\n                             && vn_dims(2) == 3);\n  const NDArray fn = props.get_facenormals ().array_value ();\n  const dim_vector& fn_dims = fn.dims ();\n  bool has_face_normals = (fn_dims(0) == zr - 1 && fn_dims(1) == zc - 1\n                           && fn_dims(2) == 3);\n\n  // FIXME: handle transparency\n  Matrix a;\n\n  int fc_mode = (props.facecolor_is_rgb () ? 0 :\n                 (props.facecolor_is (\"flat\") ? 1 :\n                  (props.facecolor_is (\"interp\") ? 2 :\n                   (props.facecolor_is (\"texturemap\") ? 3 : -1))));\n  int fl_mode = (props.facelighting_is (\"none\") ? 0 :\n                 (props.facelighting_is (\"flat\") ?\n                  (has_face_normals ? 1 : 0) :\n                  (has_vertex_normals ? 2 : 0)));\n  int fa_mode = (props.facealpha_is_double () ? 0 :\n                 (props.facealpha_is (\"flat\") ? 1 : 2));\n  int ec_mode = (props.edgecolor_is_rgb () ? 0 :\n                 (props.edgecolor_is (\"flat\") ? 1 :\n                  (props.edgecolor_is (\"interp\") ? 2 : -1)));\n  int el_mode = (props.edgelighting_is (\"none\") ? 0 :\n                 (props.edgelighting_is (\"flat\") ?\n                  (has_face_normals ? 1 : 0) :\n                  (has_vertex_normals ? 2 : 0)));\n  int ea_mode = (props.edgealpha_is_double () ? 0 :\n                 (props.edgealpha_is (\"flat\") ? 1 : 2));\n  int bfl_mode = (props.backfacelighting_is (\"lit\") ? 0 :\n                  (props.backfacelighting_is (\"reverselit\") ? 1 : 2));\n  bool do_lighting = props.get_do_lighting ();\n\n  Matrix fcolor = (fc_mode == TEXTURE ? Matrix (1, 3, 1.0)\n                   : props.get_facecolor_rgb ());\n  Matrix ecolor = props.get_edgecolor_rgb ();\n  double fa = 1.0;\n\n  float as = props.get_ambientstrength ();\n  float ds = props.get_diffusestrength ();\n  float ss = props.get_specularstrength ();\n  float se = props.get_specularexponent () * 5; // to fit Matlab\n  float scr = props.get_specularcolorreflectance ();\n  float cb[4] = { 0.0, 0.0, 0.0, 1.0 };\n\n  opengl_texture tex (m_glfcns);\n\n  int i1, i2, j1, j2;\n  bool x_mat = (x.rows () == z.rows ());\n  bool y_mat = (y.columns () == z.columns ());\n\n  i1 = i2 = j1 = j2 = 0;\n\n  if ((fc_mode > 0 && fc_mode < 3) || ec_mode > 0)\n    c = props.get_color_data ().array_value ();\n\n  boolMatrix clip (z.dims (), false);\n\n  for (int i = 0; i < zr; i++)\n    {\n      if (x_mat)\n        i1 = i;\n\n      for (int j = 0; j < zc; j++)\n        {\n          if (y_mat)\n            j1 = j;\n\n          clip(i, j) = is_nan_or_inf (x(i1, j), y(i, j1), z(i, j));\n        }\n    }\n\n  if (fa_mode > 0 || ea_mode > 0)\n    {\n      // FIXME: implement alphadata conversion\n      //a = props.get_alpha_data ();\n    }\n\n  if (fl_mode > 0 || el_mode > 0)\n    m_glfcns.glMaterialf (LIGHT_MODE, GL_SHININESS, se);\n\n  // FIXME: good candidate for caching,\n  //        transferring pixel data to OpenGL is time consuming.\n  if (fc_mode == TEXTURE)\n    tex = opengl_texture::create (m_glfcns, props.get_color_data ());\n\n  if (draw_all || ! props.facecolor_is (\"none\"))\n    {\n      if (fa_mode == 0)\n        {\n          fa = props.get_facealpha_double ();\n          cb[3] = fa;\n          if (fc_mode == UNIFORM || fc_mode == TEXTURE)\n            {\n              m_glfcns.glColor4d (fcolor(0), fcolor(1), fcolor(2), fa);\n              if (fl_mode > 0)\n                {\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = as * fcolor(i);\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);\n\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = ds * fcolor(i);\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);\n\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = ss * (scr + (1-scr) * fcolor(i));\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);\n                }\n            }\n\n          if ((fl_mode > 0) && do_lighting)\n            m_glfcns.glEnable (GL_LIGHTING);\n          m_glfcns.glShadeModel ((fc_mode == INTERP || fl_mode == GOURAUD)\n                                 ? GL_SMOOTH : GL_FLAT);\n          set_polygon_offset (true, 1.0);\n          if (fc_mode == TEXTURE)\n            m_glfcns.glEnable (GL_TEXTURE_2D);\n\n          for (int i = 1; i < zc; i++)\n            {\n              if (y_mat)\n                {\n                  i1 = i-1;\n                  i2 = i;\n                }\n\n              for (int j = 1; j < zr; j++)\n                {\n\n                  if (clip(j-1, i-1) || clip(j, i-1)\n                      || clip(j-1, i) || clip(j, i))\n                    continue;\n\n                  if (fc_mode == FLAT)\n                    {\n                      // \"flat\" only needs color at lower-left vertex\n                      if (! math::isfinite (c(j-1, i-1)))\n                        continue;\n                    }\n                  else if (fc_mode == INTERP)\n                    {\n                      // \"interp\" needs valid color at all 4 vertices\n                      if (! (math::isfinite (c(j-1, i-1))\n                             && math::isfinite (c(j, i-1))\n                             && math::isfinite (c(j-1, i))\n                             && math::isfinite (c(j, i))))\n                        continue;\n                    }\n\n                  if (x_mat)\n                    {\n                      j1 = j-1;\n                      j2 = j;\n                    }\n\n                  m_glfcns.glBegin (GL_QUADS);\n\n                  // Vertex 1\n                  if (fc_mode == TEXTURE)\n                    tex.tex_coord (double (i-1) / (zc-1),\n                                   double (j-1) / (zr-1));\n                  else if (fc_mode > 0)\n                    {\n                      // FIXME: is there a smarter way to do this?\n                      for (int k = 0; k < 3; k++)\n                        cb[k] = c(j-1, i-1, k);\n                      m_glfcns.glColor4fv (cb);\n\n                      if (fl_mode > 0)\n                        {\n                          for (int k = 0; k < 3; k++)\n                            cb[k] *= as;\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);\n\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = ds * c(j-1, i-1, k);\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);\n\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = ss * (scr + (1-scr) * c(j-1, i-1, k));\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);\n                        }\n                    }\n                  if (fl_mode > 0)\n                    set_normal (bfl_mode, (fl_mode == GOURAUD ? vn : fn),\n                                j-1, i-1);\n\n                  m_glfcns.glVertex3d (x(j1, i-1), y(j-1, i1), z(j-1, i-1));\n\n                  // Vertex 2\n                  if (fc_mode == TEXTURE)\n                    tex.tex_coord (double (i) / (zc-1),\n                                   double (j-1) / (zr-1));\n                  else if (fc_mode == INTERP)\n                    {\n                      for (int k = 0; k < 3; k++)\n                        cb[k] = c(j-1, i, k);\n                      m_glfcns.glColor4fv (cb);\n\n                      if (fl_mode > 0)\n                        {\n                          for (int k = 0; k < 3; k++)\n                            cb[k] *= as;\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);\n\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = ds * c(j-1, i, k);\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);\n\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = ss * (scr + (1-scr) * c(j-1, i, k));\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);\n                        }\n                    }\n\n                  if (fl_mode == GOURAUD)\n                    set_normal (bfl_mode, vn, j-1, i);\n\n                  m_glfcns.glVertex3d (x(j1, i), y(j-1, i2), z(j-1, i));\n\n                  // Vertex 3\n                  if (fc_mode == TEXTURE)\n                    tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1));\n                  else if (fc_mode == INTERP)\n                    {\n                      for (int k = 0; k < 3; k++)\n                        cb[k] = c(j, i, k);\n                      m_glfcns.glColor4fv (cb);\n\n                      if (fl_mode > 0)\n                        {\n                          for (int k = 0; k < 3; k++)\n                            cb[k] *= as;\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);\n\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = ds * c(j, i, k);\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);\n\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = ss * (scr + (1-scr) * c(j, i, k));\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);\n                        }\n                    }\n                  if (fl_mode == GOURAUD)\n                    set_normal (bfl_mode, vn, j, i);\n\n                  m_glfcns.glVertex3d (x(j2, i), y(j, i2), z(j, i));\n\n                  // Vertex 4\n                  if (fc_mode == TEXTURE)\n                    tex.tex_coord (double (i-1) / (zc-1),\n                                   double (j) / (zr-1));\n                  else if (fc_mode == INTERP)\n                    {\n                      for (int k = 0; k < 3; k++)\n                        cb[k] = c(j, i-1, k);\n                      m_glfcns.glColor4fv (cb);\n\n                      if (fl_mode > 0)\n                        {\n                          for (int k = 0; k < 3; k++)\n                            cb[k] *= as;\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);\n\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = ds * c(j, i-1, k);\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);\n\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = ss * (scr + (1-scr) * c(j, i-1, k));\n                          m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);\n                        }\n                    }\n                  if (fl_mode == GOURAUD)\n                    set_normal (bfl_mode, vn, j, i-1);\n\n                  m_glfcns.glVertex3d (x(j2, i-1), y(j, i1), z(j, i-1));\n\n                  m_glfcns.glEnd ();\n                }\n            }\n\n          set_polygon_offset (false);\n          if (fc_mode == TEXTURE)\n            m_glfcns.glDisable (GL_TEXTURE_2D);\n\n          if ((fl_mode > 0) && do_lighting)\n            m_glfcns.glDisable (GL_LIGHTING);\n        }\n      else\n        {\n          // FIXME: implement flat, interp and texturemap transparency\n        }\n    }\n\n  if (! props.edgecolor_is (\"none\") && ! props.linestyle_is (\"none\"))\n    {\n      if (props.get_edgealpha_double () == 1)\n        {\n          cb[3] = 1.0; // edgealpha isn't implemented yet\n          if (ec_mode == UNIFORM)\n            {\n              m_glfcns.glColor3dv (ecolor.data ());\n              if (el_mode > 0)\n                {\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = as * ecolor(i);\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);\n\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = ds * ecolor(i);\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);\n\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = ss * (scr + (1-scr) * ecolor(i));\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);\n                }\n            }\n\n          if ((el_mode > 0) && do_lighting)\n            m_glfcns.glEnable (GL_LIGHTING);\n          m_glfcns.glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD)\n                                 ? GL_SMOOTH : GL_FLAT);\n\n          set_linestyle (props.get_linestyle (), false,\n                         props.get_linewidth ());\n          set_linewidth (props.get_linewidth ());\n          set_linecap (\"butt\");\n          set_linejoin (\"miter\");\n\n          // Mesh along Y-axis\n\n          if (props.meshstyle_is (\"both\") || props.meshstyle_is (\"column\"))\n            {\n              for (int i = 0; i < zc; i++)\n                {\n                  if (y_mat)\n                    {\n                      i1 = i-1;\n                      i2 = i;\n                    }\n\n                  for (int j = 1; j < zr; j++)\n                    {\n                      if (clip(j-1, i) || clip(j, i))\n                        continue;\n\n                      if (ec_mode == FLAT)\n                        {\n                          // \"flat\" only needs color at lower-left vertex\n                          if (! math::isfinite (c(j-1, i)))\n                            continue;\n                        }\n                      else if (ec_mode == INTERP)\n                        {\n                          // \"interp\" needs valid color at both vertices\n                          if (! (math::isfinite (c(j-1, i))\n                                 && math::isfinite (c(j, i))))\n                            continue;\n                        }\n\n                      if (x_mat)\n                        {\n                          j1 = j-1;\n                          j2 = j;\n                        }\n\n                      m_glfcns.glBegin (GL_LINES);\n\n                      // Vertex 1\n                      if (ec_mode > 0)\n                        {\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = c(j-1, i, k);\n                          m_glfcns.glColor3fv (cb);\n\n                          if (el_mode > 0)\n                            {\n                              for (int k = 0; k < 3; k++)\n                                cb[k] *= as;\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT,\n                                                     cb);\n\n                              for (int k = 0; k < 3; k++)\n                                cb[k] = ds * c(j-1, i, k);\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE,\n                                                     cb);\n\n                              for (int k = 0; k < 3; k++)\n                                cb[k] = ss * (scr + (1-scr) * c(j-1, i, k));\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR,\n                                                     cb);\n                            }\n                        }\n                      if (el_mode > 0)\n                        {\n                          if (el_mode == GOURAUD)\n                            set_normal (bfl_mode, vn, j-1, i);\n                          else\n                            set_normal (bfl_mode, fn, j-1, std::min (i, zc-2));\n                        }\n\n                      m_glfcns.glVertex3d (x(j1, i), y(j-1, i2), z(j-1, i));\n\n                      // Vertex 2\n                      if (ec_mode == INTERP)\n                        {\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = c(j, i, k);\n                          m_glfcns.glColor3fv (cb);\n\n                          if (el_mode > 0)\n                            {\n                              for (int k = 0; k < 3; k++)\n                                cb[k] *= as;\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT,\n                                                     cb);\n\n                              for (int k = 0; k < 3; k++)\n                                cb[k] = ds * c(j, i, k);\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE,\n                                                     cb);\n\n                              for (int k = 0; k < 3; k++)\n                                cb[k] = ss * (scr + (1-scr) * c(j, i, k));\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR,\n                                                     cb);\n                            }\n                        }\n                      if (el_mode == GOURAUD)\n                        set_normal (bfl_mode, vn, j, i);\n\n                      m_glfcns.glVertex3d (x(j2, i), y(j, i2), z(j, i));\n\n                      m_glfcns.glEnd ();\n                    }\n                }\n            }\n\n          // Mesh along X-axis\n\n          if (props.meshstyle_is (\"both\") || props.meshstyle_is (\"row\"))\n            {\n              for (int j = 0; j < zr; j++)\n                {\n                  if (x_mat)\n                    {\n                      j1 = j-1;\n                      j2 = j;\n                    }\n\n                  for (int i = 1; i < zc; i++)\n                    {\n                      if (clip(j, i-1) || clip(j, i))\n                        continue;\n\n                      if (ec_mode == FLAT)\n                        {\n                          // \"flat\" only needs color at lower-left vertex\n                          if (! math::isfinite (c(j, i-1)))\n                            continue;\n                        }\n                      else if (ec_mode == INTERP)\n                        {\n                          // \"interp\" needs valid color at both vertices\n                          if (! (math::isfinite (c(j, i-1))\n                                 && math::isfinite (c(j, i))))\n                            continue;\n                        }\n\n                      if (y_mat)\n                        {\n                          i1 = i-1;\n                          i2 = i;\n                        }\n\n                      m_glfcns.glBegin (GL_LINES);\n\n                      // Vertex 1\n                      if (ec_mode > 0)\n                        {\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = c(j, i-1, k);\n                          m_glfcns.glColor3fv (cb);\n\n                          if (el_mode > 0)\n                            {\n                              for (int k = 0; k < 3; k++)\n                                cb[k] *= as;\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT,\n                                                     cb);\n\n                              for (int k = 0; k < 3; k++)\n                                cb[k] = ds * c(j, i-1, k);\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE,\n                                                     cb);\n\n                              for (int k = 0; k < 3; k++)\n                                cb[k] = ss * (scr + (1-scr) * c(j, i-1, k));\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR,\n                                                     cb);\n                            }\n                        }\n                      if (el_mode > 0)\n                        {\n                          if (el_mode == GOURAUD)\n                            set_normal (bfl_mode, vn, j, i-1);\n                          else\n                            set_normal (bfl_mode, fn, std::min (j, zr-2), i-1);\n                        }\n\n                      m_glfcns.glVertex3d (x(j2, i-1), y(j, i1), z(j, i-1));\n\n                      // Vertex 2\n                      if (ec_mode == INTERP)\n                        {\n                          for (int k = 0; k < 3; k++)\n                            cb[k] = c(j, i, k);\n                          m_glfcns.glColor3fv (cb);\n\n                          if (el_mode > 0)\n                            {\n                              for (int k = 0; k < 3; k++)\n                                cb[k] *= as;\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT,\n                                                     cb);\n\n                              for (int k = 0; k < 3; k++)\n                                cb[k] = ds * c(j, i, k);\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE,\n                                                     cb);\n\n                              for (int k = 0; k < 3; k++)\n                                cb[k] = ss * (scr + (1-scr) * c(j, i, k));\n                              m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR,\n                                                     cb);\n                            }\n                        }\n                      if (el_mode == GOURAUD)\n                        set_normal (bfl_mode, vn, j, i);\n\n                      m_glfcns.glVertex3d (x(j2, i), y(j, i2), z(j, i));\n\n                      m_glfcns.glEnd ();\n                    }\n                }\n            }\n\n          set_linestyle (\"-\");  // Disable LineStipple\n          set_linewidth (0.5f);\n\n          if ((el_mode > 0) && do_lighting)\n            m_glfcns.glDisable (GL_LIGHTING);\n        }\n      else\n        {\n          // FIXME: implement transparency\n        }\n    }\n\n  if (! props.marker_is (\"none\")\n      && ! (props.markeredgecolor_is (\"none\")\n            && props.markerfacecolor_is (\"none\")))\n    {\n      // FIXME: check how transparency should be handled in markers\n      // FIXME: check what to do with marker facecolor set to auto\n      //        and facecolor set to none.\n\n      bool do_edge = draw_all || ! props.markeredgecolor_is (\"none\");\n      bool do_face = draw_all || ! props.markerfacecolor_is (\"none\");\n\n      Matrix mecolor = (draw_all ? Matrix (1, 3, 0.0) :\n                        props.get_markeredgecolor_rgb ());\n      Matrix mfcolor = (draw_all ? Matrix (1, 3, 0.0) :\n                        props.get_markerfacecolor_rgb ());\n      Matrix cc (1, 3, 0.0);\n\n      if (mecolor.isempty () && props.markeredgecolor_is (\"auto\"))\n        {\n          mecolor = props.get_edgecolor_rgb ();\n          do_edge = ! props.edgecolor_is (\"none\");\n        }\n\n      if (mfcolor.isempty () && props.markerfacecolor_is (\"auto\"))\n        {\n          mfcolor = props.get_facecolor_rgb ();\n          do_face = ! props.facecolor_is (\"none\");\n        }\n\n      if ((mecolor.isempty () || mfcolor.isempty ()) && c.isempty ())\n        c = props.get_color_data ().array_value ();\n\n      init_marker (props.get_marker (), props.get_markersize (),\n                   props.get_linewidth ());\n\n      uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40);\n      uint8_t clip_ok = 0x40;\n\n      for (int i = 0; i < zc; i++)\n        {\n          if (y_mat)\n            i1 = i;\n\n          for (int j = 0; j < zr; j++)\n            {\n              if (x_mat)\n                j1 = j;\n\n              if ((clip_code (x(j1, i), y(j, i1), z(j, i)) & clip_mask)\n                  != clip_ok)\n                continue;\n\n              if ((do_edge && mecolor.isempty ())\n                  || (do_face && mfcolor.isempty ()))\n                {\n                  if (! math::isfinite (c(j, i)))\n                    continue;  // Skip NaNs in color data\n\n                  for (int k = 0; k < 3; k++)\n                    cc(k) = c(j, i, k);\n                }\n\n              Matrix lc = (do_edge ? (mecolor.isempty () ? cc : mecolor)\n                           : Matrix ());\n              Matrix fc = (do_face ? (mfcolor.isempty () ? cc : mfcolor)\n                           : Matrix ());\n\n              draw_marker (x(j1, i), y(j, i1), z(j, i), lc, fc);\n            }\n        }\n\n      end_marker ();\n    }\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_surface\");\n\n#endif\n}\n\n// FIXME: global optimization (rendering, data structures...),\n// there is probably a smarter/faster/less-memory-consuming way to do this.\nvoid\nopengl_renderer::draw_patch (const patch::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  // Do not render if the patch has incoherent data\n  std::string msg;\n  if (props.has_bad_data (msg))\n    {\n      warning (\"opengl_renderer: %s.  Not rendering.\", msg.c_str ());\n      return;\n    }\n\n  bool draw_all = m_selecting && props.pickableparts_is (\"all\");\n  const Matrix f = props.get_faces ().matrix_value ();\n  const Matrix v = m_xform.scale (props.get_vertices ().matrix_value ());\n  Matrix c;\n  Matrix a;\n  double fa = 1.0;\n\n  int nv = v.rows ();\n  int nf = f.rows ();\n  int fcmax = f.columns ();\n\n  bool has_z = (v.columns () > 2);\n  bool has_facecolor = false;\n  bool has_facealpha = false;\n\n  int fc_mode = ((props.facecolor_is (\"none\")\n                  || props.facecolor_is_rgb () || draw_all) ? 0 :\n                 (props.facecolor_is (\"flat\") ? 1 : 2));\n  int fl_mode = (props.facelighting_is (\"none\") ? 0 :\n                 (props.facelighting_is (\"flat\") ? 1 : 2));\n  int fa_mode = (props.facealpha_is_double () ? 0 :\n                 (props.facealpha_is (\"flat\") ? 1 : 2));\n  int ec_mode = ((props.edgecolor_is (\"none\")\n                  || props.edgecolor_is_rgb ()) ? 0 :\n                 (props.edgecolor_is (\"flat\") ? 1 : 2));\n  int el_mode = (props.edgelighting_is (\"none\") ? 0 :\n                 (props.edgelighting_is (\"flat\") ? 1 : 2));\n  int ea_mode = (props.edgealpha_is_double () ? 0 :\n                 (props.edgealpha_is (\"flat\") ? 1 : 2));\n  int bfl_mode = (props.backfacelighting_is (\"lit\") ? 0 :\n                  (props.backfacelighting_is (\"reverselit\") ? 1 : 2));\n  bool do_lighting = props.get_do_lighting ();\n\n  Matrix fcolor = props.get_facecolor_rgb ();\n  Matrix ecolor = props.get_edgecolor_rgb ();\n\n  float as = props.get_ambientstrength ();\n  float ds = props.get_diffusestrength ();\n  float ss = props.get_specularstrength ();\n  float se = props.get_specularexponent () * 5; // to fit Matlab\n  float scr = props.get_specularcolorreflectance ();\n\n  const Matrix vn = props.get_vertexnormals ().matrix_value ();\n  bool has_vertex_normals = (vn.rows () == nv);\n  const Matrix fn = props.get_facenormals ().matrix_value ();\n  bool has_face_normals = (fn.rows () == nf);\n\n  boolMatrix clip (1, nv, false);\n\n  if (has_z)\n    for (int i = 0; i < nv; i++)\n      clip(i) = is_nan_or_inf (v(i, 0), v(i, 1), v(i, 2));\n  else\n    for (int i = 0; i < nv; i++)\n      clip(i) = is_nan_or_inf (v(i, 0), v(i, 1), 0);\n\n  boolMatrix clip_f (1, nf, false);\n  Array<int> count_f (dim_vector (nf, 1), 0);\n\n  for (int i = 0; i < nf; i++)\n    {\n      bool fclip = false;\n      int count = 0;\n\n      for (int j = 0; j < fcmax && ! math::isnan (f(i, j)); j++, count++)\n        fclip = (fclip || clip(int (f(i, j) - 1)));\n\n      clip_f(i) = fclip;\n      count_f(i) = count;\n    }\n\n  if (draw_all || fc_mode > 0 || ec_mode > 0)\n    {\n      if (draw_all)\n        c = Matrix (1, 3, 0.0);\n      else\n        c = props.get_color_data ().matrix_value ();\n\n      if (c.rows () == 1)\n        {\n          // Single color specifications, we can simplify a little bit\n\n          if (draw_all || fc_mode > 0)\n            {\n              fcolor = c;\n              fc_mode = UNIFORM;\n            }\n\n          if (draw_all || ec_mode > 0)\n            {\n              ecolor = c;\n              ec_mode = UNIFORM;\n            }\n\n          c = Matrix ();\n        }\n      else\n        has_facecolor = ((c.numel () > 0) && (c.rows () == f.rows ()));\n    }\n\n  if (fa_mode > 0 || ea_mode > 0)\n    {\n      // FIXME: retrieve alpha data from patch object\n      //a = props.get_alpha_data ();\n      has_facealpha = ((a.numel () > 0) && (a.rows () == f.rows ()));\n    }\n\n  if (fa_mode == 0)\n    fa = props.get_facealpha_double ();\n\n  octave_idx_type fr = f.rows ();\n  std::vector<vertex_data> vdata (f.numel ());\n\n  for (int i = 0; i < nf; i++)\n    for (int j = 0; j < count_f(i); j++)\n      {\n        int idx = int (f(i, j) - 1);\n\n        Matrix vv (1, 3, 0.0);\n        Matrix cc;\n        Matrix vnn (1, 3, 0.0);\n        Matrix fnn (1, 3, 0.0);\n        double aa = 1.0;\n\n        vv(0) = v(idx, 0); vv(1) = v(idx, 1);\n        if (has_z)\n          vv(2) = v(idx, 2);\n        if (((fl_mode == FLAT) || (el_mode == FLAT)) && has_face_normals)\n          {\n            double dir = 1.0;\n            if (bfl_mode > 0)\n              dir = ((fn(i, 0) * m_view_vector(0)\n                      + fn(i, 1) * m_view_vector(1)\n                      + fn(i, 2) * m_view_vector(2) < 0)\n                     ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0);\n            fnn(0) = dir * fn(i, 0);\n            fnn(1) = dir * fn(i, 1);\n            fnn(2) = dir * fn(i, 2);\n          }\n        if ((fl_mode == GOURAUD || el_mode == GOURAUD) && has_vertex_normals)\n          {\n            double dir = 1.0;\n            if (bfl_mode > 0)\n              dir = ((vn(idx, 0) * m_view_vector(0)\n                      + vn(idx, 1) * m_view_vector(1)\n                      + vn(idx, 2) * m_view_vector(2) < 0)\n                     ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0);\n            vnn(0) = dir * vn(idx, 0);\n            vnn(1) = dir * vn(idx, 1);\n            vnn(2) = dir * vn(idx, 2);\n          }\n        if (c.numel () > 0)\n          {\n            cc.resize (1, 3);\n            if (has_facecolor)\n              cc(0) = c(i, 0), cc(1) = c(i, 1), cc(2) = c(i, 2);\n            else\n              cc(0) = c(idx, 0), cc(1) = c(idx, 1), cc(2) = c(idx, 2);\n          }\n        if (fa_mode == 0)\n          aa = fa;\n        else if (a.numel () > 0)\n          {\n            if (has_facealpha)\n              aa = a(i);\n            else\n              aa = a(idx);\n          }\n\n        vdata[i+j*fr]\n          = vertex_data (vv, cc, vnn, fnn, aa, as, ds, ss, se, scr);\n      }\n\n  if (fl_mode > 0 || el_mode > 0)\n    m_glfcns.glMaterialf (LIGHT_MODE, GL_SHININESS, se);\n\n  if (draw_all || ! props.facecolor_is (\"none\"))\n    {\n      // FIXME: adapt to double-radio property\n      if (fa_mode == 0)\n        {\n          if (fc_mode == UNIFORM)\n            {\n              m_glfcns.glColor4d (fcolor(0), fcolor(1), fcolor(2), fa);\n              if (fl_mode > 0)\n                {\n                  float cb[4] = { 0.0f, 0.0f, 0.0f, 1.0f };\n\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = as * fcolor(i);\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);\n\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = ds * fcolor(i);\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);\n\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = ss * (scr + (1-scr) * fcolor(i));\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);\n                }\n            }\n\n          if ((fl_mode > 0) && do_lighting)\n            m_glfcns.glEnable (GL_LIGHTING);\n\n          // NOTE: Push filled part of patch backwards to avoid Z-fighting\n          // with tessellator outline.  A value of 1.0 seems to work fine.\n          // Value can't be too large or the patch will be pushed below the\n          // axes planes at +2.5.\n          patch_tessellator tess (this, fc_mode, fl_mode, true, 1.0);\n\n          std::vector<octave_idx_type>::const_iterator it;\n          octave_idx_type i_start, i_end;\n\n          for (int i = 0; i < nf; i++)\n            {\n              if (clip_f(i))\n                continue;\n\n              bool is_non_planar = false;\n              if (props.m_coplanar_last_idx.size () > 0\n                  && props.m_coplanar_last_idx[i].size () > 1)\n                {\n                  is_non_planar = true;\n                  it = props.m_coplanar_last_idx[i].end ();\n                  it--;\n                }\n\n              // loop over planar subsets of face\n              do\n                {\n                  if (is_non_planar)\n                    {\n                      i_end = *it;\n                      if (it == props.m_coplanar_last_idx[i].begin ())\n                        i_start = 0;\n                      else\n                        {\n                          it--;\n                          i_start = *it - 1;\n                        }\n                    }\n                  else\n                    {\n                      i_end = count_f(i) - 1;\n                      i_start = 0;\n                    }\n\n                  tess.begin_polygon (true);\n                  tess.begin_contour ();\n\n                  // Add vertices in reverse order for Matlab compatibility\n                  for (int j = i_end; j > i_start; j--)\n                    {\n                      vertex_data::vertex_data_rep *vv\n                        = vdata[i+j*fr].get_rep ();\n\n                      tess.add_vertex (vv->m_coords.rwdata (), vv);\n                    }\n\n                  if (count_f(i) > 0)\n                    {\n                      vertex_data::vertex_data_rep *vv = vdata[i].get_rep ();\n\n                      if (fc_mode == FLAT)\n                        {\n                          // For \"flat\" shading, use color of 1st vertex.\n                          Matrix col = vv->m_color;\n\n                          if (col.numel () == 3)\n                            {\n                              m_glfcns.glColor4d (col(0), col(1), col(2), fa);\n                              if (fl_mode > 0)\n                                {\n                                  float cb[4] = { 0.0f, 0.0f, 0.0f, 1.0f };\n\n                                  for (int k = 0; k < 3; k++)\n                                    cb[k] = (vv->m_ambient * col(k));\n                                  m_glfcns.glMaterialfv (LIGHT_MODE,\n                                                         GL_AMBIENT, cb);\n\n                                  for (int k = 0; k < 3; k++)\n                                    cb[k] = (vv->m_diffuse * col(k));\n                                  m_glfcns.glMaterialfv (LIGHT_MODE,\n                                                         GL_DIFFUSE, cb);\n\n                                  for (int k = 0; k < 3; k++)\n                                    cb[k] = vv->m_specular *\n                                            (vv->m_specular_color_refl\n                                             + (1-vv->m_specular_color_refl) *\n                                             col(k));\n                                  m_glfcns.glMaterialfv (LIGHT_MODE,\n                                                         GL_SPECULAR, cb);\n                                }\n                            }\n                        }\n\n                      tess.add_vertex (vv->m_coords.rwdata (), vv);\n                    }\n\n                  tess.end_contour ();\n                  tess.end_polygon ();\n                }\n              while (i_start > 0);\n            }\n\n          if ((fl_mode > 0) && do_lighting)\n            m_glfcns.glDisable (GL_LIGHTING);\n        }\n      else\n        {\n          // FIXME: implement flat and interp transparency\n        }\n    }\n\n  if (draw_all\n      || (! props.edgecolor_is (\"none\") && ! props.linestyle_is (\"none\")))\n    {\n      // FIXME: adapt to double-radio property\n      if (props.get_edgealpha_double () == 1)\n        {\n          if (ec_mode == UNIFORM)\n            {\n              m_glfcns.glColor3dv (ecolor.data ());\n              if (el_mode > 0)\n                {\n                  // edge lighting only uses ambient light\n                  float cb[4] = { 0.0f, 0.0f, 0.0f, 1.0f };\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);\n\n                  for (int i = 0; i < 3; i++)\n                    cb[i] = (as * ecolor(i));\n                  m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);\n                }\n            }\n\n          if ((el_mode > 0) && do_lighting)\n            m_glfcns.glEnable (GL_LIGHTING);\n\n          double linewidth = props.get_linewidth ();\n          set_linestyle (props.get_linestyle (), false, linewidth);\n          set_linewidth (linewidth);\n          set_linecap (\"butt\");\n          set_linejoin (\"miter\");\n\n          // NOTE: patch contour cannot be offset.  Offset must occur with\n          // the filled portion of the patch above.  The tessellator uses\n          // GLU_TESS_BOUNDARY_ONLY to get the outline of the patch and OpenGL\n          // automatically sets the glType to GL_LINE_LOOP.  This primitive is\n          // not supported by glPolygonOffset which is used to do Z offsets.\n          patch_tessellator tess (this, ec_mode, el_mode, false);\n\n          for (int i = 0; i < nf; i++)\n            {\n              bool is_non_planar = false;\n              if (props.m_coplanar_last_idx.size () > 0\n                  && props.m_coplanar_last_idx[i].size () > 1)\n                is_non_planar = true;\n              if (clip_f(i) || is_non_planar)\n                {\n                  // This is an unclosed contour or a non-planar face.\n                  // Draw it as a line.\n                  bool flag = false;\n\n                  m_glfcns.glShadeModel ((ec_mode == INTERP\n                                          || el_mode == GOURAUD)\n                                         ? GL_SMOOTH : GL_FLAT);\n\n                  // Add vertices in reverse order for Matlab compatibility\n                  for (int j = count_f(i)-1; j >= 0; j--)\n                    {\n                      if (! clip(int (f(i, j) - 1)))\n                        {\n                          vertex_data::vertex_data_rep *vv\n                            = vdata[i+j*fr].get_rep ();\n                          const Matrix m = vv->m_coords;\n                          if (! flag)\n                            {\n                              flag = true;\n                              m_glfcns.glBegin (GL_LINE_STRIP);\n                            }\n                          if (ec_mode != UNIFORM)\n                            {\n                              Matrix col = vv->m_color;\n\n                              if (col.numel () == 3)\n                                m_glfcns.glColor3dv (col.data ());\n                            }\n                          m_glfcns.glVertex3d (m(0), m(1), m(2));\n                        }\n                      else if (flag)\n                        {\n                          flag = false;\n                          m_glfcns.glEnd ();\n                        }\n                    }\n                  // Do loop body with vertex N to \"close\" GL_LINE_STRIP\n                  // from vertex 0 to vertex N.\n                  int j = count_f(i)-1;\n                  if (flag && ! clip(int (f(i, j) - 1)))\n                    {\n                      vertex_data::vertex_data_rep *vv\n                        = vdata[i+j*fr].get_rep ();\n                      const Matrix m = vv->m_coords;\n                      if (ec_mode != UNIFORM)\n                        {\n                          Matrix col = vv->m_color;\n\n                          if (col.numel () == 3)\n                            m_glfcns.glColor3dv (col.data ());\n                        }\n                      m_glfcns.glVertex3d (m(0), m(1), m(2));\n                    }\n\n                  if (flag)\n                    m_glfcns.glEnd ();\n                }\n              else  // Normal edge contour drawn with tessellator\n                {\n                  tess.begin_polygon (false);\n                  tess.begin_contour ();\n\n                  for (int j = count_f(i)-1; j >= 0; j--)\n                    {\n                      vertex_data::vertex_data_rep *vv\n                        = vdata[i+j*fr].get_rep ();\n                      tess.add_vertex (vv->m_coords.rwdata (), vv);\n                    }\n\n                  tess.end_contour ();\n                  tess.end_polygon ();\n                }\n            }\n\n          set_linestyle (\"-\");  // Disable LineStipple\n          set_linewidth (0.5f);\n\n          if ((el_mode > 0) && do_lighting)\n            m_glfcns.glDisable (GL_LIGHTING);\n        }\n      else\n        {\n          // FIXME: implement transparency\n        }\n    }\n\n  if (! props.marker_is (\"none\")\n      && ! (props.markeredgecolor_is (\"none\")\n            && props.markerfacecolor_is (\"none\")))\n    {\n      bool do_edge = draw_all || ! props.markeredgecolor_is (\"none\");\n      bool do_face = draw_all || ! props.markerfacecolor_is (\"none\");\n\n      Matrix mecolor = (draw_all ? Matrix (1, 3, 0.0) :\n                        props.get_markeredgecolor_rgb ());\n      Matrix mfcolor = (draw_all ? Matrix (1, 3, 0.0) :\n                        props.get_markerfacecolor_rgb ());\n\n      bool has_markerfacecolor = draw_all || false;\n\n      if ((mecolor.isempty () && ! props.markeredgecolor_is (\"none\"))\n          || (mfcolor.isempty () && ! props.markerfacecolor_is (\"none\")))\n        {\n          Matrix mc = props.get_color_data ().matrix_value ();\n\n          if (mc.rows () == 1)\n            {\n              // Single color specifications, we can simplify a little bit\n              if (mfcolor.isempty () && ! props.markerfacecolor_is (\"none\"))\n                mfcolor = mc;\n\n              if (mecolor.isempty () && ! props.markeredgecolor_is (\"none\"))\n                mecolor = mc;\n            }\n          else\n            {\n              if (c.isempty ())\n                c = props.get_color_data ().matrix_value ();\n              has_markerfacecolor = ((c.numel () > 0)\n                                     && (c.rows () == f.rows ()));\n            }\n        }\n\n      init_marker (props.get_marker (), props.get_markersize (),\n                   props.get_linewidth ());\n\n      uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40);\n      uint8_t clip_ok = 0x40;\n\n      for (int i = 0; i < nf; i++)\n        for (int j = 0; j < count_f(i); j++)\n          {\n            int idx = int (f(i, j) - 1);\n\n            if ((clip_code (v(idx, 0), v(idx, 1), (has_z ? v(idx, 2) : 0))\n                 & clip_mask) != clip_ok)\n              continue;\n\n            Matrix cc;\n            if (c.numel () > 0)\n              {\n                cc.resize (1, 3);\n                if (has_markerfacecolor)\n                  cc(0) = c(i, 0), cc(1) = c(i, 1), cc(2) = c(i, 2);\n                else\n                  cc(0) = c(idx, 0), cc(1) = c(idx, 1), cc(2) = c(idx, 2);\n              }\n\n            Matrix lc = (do_edge ? (mecolor.isempty () ? cc : mecolor)\n                         : Matrix ());\n            Matrix fc = (do_face ? (mfcolor.isempty () ? cc : mfcolor)\n                         : Matrix ());\n\n            draw_marker (v(idx, 0), v(idx, 1), (has_z ? v(idx, 2) : 0), lc, fc);\n          }\n\n      end_marker ();\n    }\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_patch\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_scatter (const scatter::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  // Do not render if the scatter object has incoherent data\n  std::string msg;\n  if (props.has_bad_data (msg))\n    {\n      warning (\"opengl_renderer: %s.  Not rendering.\", msg.c_str ());\n      return;\n    }\n\n  bool draw_all = m_selecting;\n\n  if (draw_all || (! props.marker_is (\"none\")\n                   && ! (props.markeredgecolor_is (\"none\")\n                         && props.markerfacecolor_is (\"none\"))))\n    {\n      bool do_edge = draw_all || ! props.markeredgecolor_is (\"none\");\n      bool do_face = draw_all || ! props.markerfacecolor_is (\"none\");\n\n      const Matrix x = m_xform.xscale (props.get_xdata ().matrix_value ());\n      const Matrix y = m_xform.yscale (props.get_ydata ().matrix_value ());\n      const Matrix z = m_xform.zscale (props.get_zdata ().matrix_value ());\n      const Matrix c = props.get_color_data ().matrix_value ();\n      const Matrix s = props.get_sizedata ().matrix_value ();\n\n      int np = x.rows ();\n      bool has_z = ! z.isempty ();\n\n      // If markeredgecolor is \"flat\", mecolor is empty\n      Matrix mecolor = (draw_all ? Matrix (1, 3, 0.0) :\n                        props.get_markeredgecolor_rgb ());\n      Matrix mfcolor = (draw_all ? Matrix (1, 3, 0.0) :\n                        props.get_markerfacecolor_rgb ());\n      const double mea = props.get_markeredgealpha ();\n      const double mfa = props.get_markerfacealpha ();\n\n      if (props.markerfacecolor_is (\"auto\"))\n        {\n          gh_manager& gh_mgr = __get_gh_manager__ ();\n          graphics_object go = gh_mgr.get_object (props.get___myhandle__ ());\n          graphics_object ax = go.get_ancestor (\"axes\");\n          const axes::properties& ax_props\n            = dynamic_cast<const axes::properties&> (ax.get_properties ());\n\n          mfcolor = ax_props.get_color ().matrix_value ();\n        }\n\n      init_marker (props.get_marker (), std::sqrt (s(0)),\n                   props.get_linewidth ());\n\n      uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40);\n      uint8_t clip_ok = 0x40;\n\n      Matrix cc;\n      if (! c.isempty ())\n        {\n          if (c.rows () == 1)\n            cc = c;\n          else\n            {\n              cc.resize (1, 3);\n              cc(0) = c(0, 0);\n              cc(1) = c(0, 1);\n              cc(2) = c(0, 2);\n            }\n        }\n\n      for (int i = 0; i < np; i++)\n        {\n          if ((clip_code (x(i), y(i), (has_z ? z(i) : 0.0)) & clip_mask)\n              != clip_ok)\n            continue;\n\n          if (c.rows () > 1)\n            {\n              cc(0) = c(i, 0);\n              cc(1) = c(i, 1);\n              cc(2) = c(i, 2);\n            }\n\n          Matrix lc = (do_edge ? (mecolor.isempty () ? cc : mecolor)\n                       : Matrix ());\n          Matrix fc = (do_face ? (mfcolor.isempty () ? cc : mfcolor)\n                       : Matrix ());\n\n          if (s.numel () > 1)\n            change_marker (props.get_marker (), std::sqrt (s(i)));\n\n          draw_marker (x(i), y(i), (has_z ? z(i) : 0.0), lc, fc, mea, mfa);\n        }\n\n      end_marker ();\n    }\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_scatter\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_light (const light::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  // enable light source\n  m_glfcns.glEnable (m_current_light);\n\n  // light position\n  float pos[4] = { 0, 0, 0, 0 }; // X,Y,Z,infinite/local\n  Matrix lpos = props.get_position ().matrix_value ();\n  for (int i = 0; i < 3; i++)\n    pos[i] = lpos(i);\n  if (props.style_is (\"local\"))\n    pos[3] = 1;\n  m_glfcns.glLightfv (m_current_light, GL_POSITION, pos);\n\n  // light color\n  float col[4] = { 1, 1, 1, 1 }; // R,G,B,ALPHA (the latter has no meaning)\n  Matrix lcolor = props.get_color ().matrix_value ();\n  for (int i = 0; i < 3; i++)\n    col[i] = lcolor(i);\n  m_glfcns.glLightfv (m_current_light, GL_DIFFUSE,  col);\n  m_glfcns.glLightfv (m_current_light, GL_SPECULAR, col);\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_light\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_hggroup (const hggroup::properties& props)\n{\n  draw (props.get_children ());\n}\n\nvoid\nopengl_renderer::set_ortho_coordinates ()\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glMatrixMode (GL_PROJECTION);\n  m_glfcns.glPushMatrix ();\n  m_glfcns.glLoadIdentity ();\n\n  Matrix vp = get_viewport_scaled ();\n  m_glfcns.glOrtho (0, vp(2), vp(3), 0, m_xZ1, m_xZ2);\n  m_glfcns.glMatrixMode (GL_MODELVIEW);\n  m_glfcns.glPushMatrix ();\n  m_glfcns.glLoadIdentity ();\n\n#else\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::set_ortho_coordinates\");\n\n#endif\n}\n\nvoid\nopengl_renderer::restore_previous_coordinates ()\n{\n#if defined (HAVE_OPENGL)\n\n  // Restore previous coordinate system\n  m_glfcns.glMatrixMode (GL_MODELVIEW);\n  m_glfcns.glPopMatrix();\n  m_glfcns.glMatrixMode (GL_PROJECTION);\n  m_glfcns.glPopMatrix();\n\n#else\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::restore_previous_coordinates\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_text (const text::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  if (props.get_string ().isempty () || props.color_is (\"none\"))\n    return;\n\n  Matrix pos = m_xform.scale (props.get_data_position ());\n\n  // Handle clipping manually when drawing text in ortho coordinates\n  if (! props.is_clipping ()\n      || (clip_code (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0) == 0x40))\n    {\n      set_clipping (false);\n\n      draw_text_background (props);\n\n      set_font (props);\n\n      render_text (props.get_pixels (), props.get_extent_matrix (),\n                   pos(0), pos(1), pos(2), props.get_rotation ());\n\n      set_clipping (props.is_clipping ());\n    }\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_text\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_text_background (const text::properties& props,\n                                       bool /*do_rotate*/)\n{\n#if defined (HAVE_OPENGL)\n\n  Matrix bgcol = props.get_backgroundcolor_rgb ();\n  Matrix ecol = props.get_edgecolor_rgb ();\n\n  if (bgcol.isempty () && ecol.isempty ())\n    return;\n\n  Matrix pos = props.get_data_position ();\n  ColumnVector pixpos = get_transform ().transform (pos(0), pos(1),\n                        pos(2), true);\n\n  // Save current transform matrices and set orthogonal window coordinates\n  set_ortho_coordinates ();\n\n  // Translate coordinates so that the text anchor is (0,0)\n  m_glfcns.glTranslated (pixpos(0), pixpos(1), -pixpos(2));\n\n  // FIXME: Only multiples of 90° are handled by the text renderer.\n  //        Handle others here.\n  double rotation = props.get_rotation ();\n\n  m_glfcns.glRotated (-rotation, 0.0, 0.0, 1.0);\n\n  double m = points_to_pixels (props.get_margin ());\n  const Matrix bbox = props.get_extent_matrix ();\n  double x0 = bbox (0) / m_devpixratio - m;\n  double x1 = x0 + bbox(2) / m_devpixratio + 2 * m;\n  double y0 = -(bbox (1) / m_devpixratio - m);\n  double y1 = y0 - (bbox(3) / m_devpixratio + 2 * m);\n\n  if (! bgcol.isempty ())\n    {\n      m_glfcns.glColor3f (bgcol(0), bgcol(1), bgcol(2));\n\n      bool depth_test = m_glfcns.glIsEnabled (GL_DEPTH_TEST);\n      if (depth_test)\n        set_polygon_offset (true, 4.0);\n\n      m_glfcns.glBegin (GL_QUADS);\n      m_glfcns.glVertex2d (x0, y0);\n      m_glfcns.glVertex2d (x1, y0);\n      m_glfcns.glVertex2d (x1, y1);\n      m_glfcns.glVertex2d (x0, y1);\n      m_glfcns.glEnd ();\n\n      if (depth_test)\n        set_polygon_offset (false);\n    }\n\n  if (! ecol.isempty ())\n    {\n      m_glfcns.glColor3f (ecol(0), ecol(1), ecol(2));\n\n      set_linestyle (props.get_linestyle (), false, props.get_linewidth ());\n      set_linewidth (props.get_linewidth ());\n\n      m_glfcns.glBegin (GL_LINE_STRIP);\n      m_glfcns.glVertex2d (x0, y0);\n      m_glfcns.glVertex2d (x1, y0);\n      m_glfcns.glVertex2d (x1, y1);\n      m_glfcns.glVertex2d (x0, y1);\n      m_glfcns.glVertex2d (x0, y0);\n      m_glfcns.glEnd ();\n\n      set_linestyle (\"-\");\n    }\n\n  restore_previous_coordinates ();\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_text_background\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_image (const image::properties& props)\n{\n#if defined (HAVE_OPENGL)\n\n  octave_value cdata = props.get_color_data ();\n  Matrix x = props.get_xdata ().matrix_value ();\n  Matrix y = props.get_ydata ().matrix_value ();\n\n  draw_texture_image (cdata, x, y);\n\n#else\n\n  octave_unused_parameter (props);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_image\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_texture_image (const octave_value cdata, Matrix x,\n                                     Matrix y, bool ortho)\n{\n#if defined (HAVE_OPENGL)\n\n  const dim_vector& dv = cdata.dims ();\n  int h = dv(0);\n  int w = dv(1);\n  double x0, x1, y0, y1;\n\n  double dx = 1.0;\n  if (w > 1)\n    dx = (x(1) - x(0)) / (w - 1);\n\n  x0 = x(0)-dx/2;\n  x1 = x(1)+dx/2;\n\n  double dy = 1.0;\n  if (h > 1)\n    dy = (y(1) - y(0)) / (h - 1);\n\n  y0 = y(0)-dy/2;\n  y1 = y(1)+dy/2;\n\n  // Expect RGB data\n  if (dv.ndims () == 3 && (dv(2) == 3 || dv(2) == 4))\n    {\n      opengl_texture tex = opengl_texture::create (m_glfcns, cdata);\n      if (tex.is_valid ())\n        {\n          m_glfcns.glColor4d (1.0, 1.0, 1.0, 1.0);\n\n          m_glfcns.glEnable (GL_TEXTURE_2D);\n\n          m_glfcns.glBegin (GL_QUADS);\n\n          tex.tex_coord (0.0, 0.0);\n          if (ortho)\n            m_glfcns.glVertex2d (x0, y0);\n          else\n            m_glfcns.glVertex3d (x0, y0, 0.0);\n\n          tex.tex_coord (1.0, 0.0);\n          if (ortho)\n            m_glfcns.glVertex2d (x1, y0);\n          else\n            m_glfcns.glVertex3d (x1, y0, 0.0);\n\n          tex.tex_coord (1.0, 1.0);\n          if (ortho)\n            m_glfcns.glVertex2d (x1, y1);\n          else\n            m_glfcns.glVertex3d (x1, y1, 0.0);\n\n          tex.tex_coord (0.0, 1.0);\n          if (ortho)\n            m_glfcns.glVertex2d (x0, y1);\n          else\n            m_glfcns.glVertex3d (x0, y1, 0.0);\n\n          m_glfcns.glEnd ();\n          m_glfcns.glDisable (GL_TEXTURE_2D);\n        }\n    }\n  else\n    warning (\"opengl_renderer: invalid image size (expected MxNx3 or MxN)\");\n\n#else\n\n  octave_unused_parameter (cdata);\n  octave_unused_parameter (x);\n  octave_unused_parameter (y);\n  octave_unused_parameter (ortho);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_texture_image\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw (const Matrix& hlist, bool toplevel)\n{\n  int len = hlist.numel ();\n\n  gh_manager& gh_mgr = __get_gh_manager__ ();\n\n  for (int i = len-1; i >= 0; i--)\n    {\n      graphics_object obj = gh_mgr.get_object (hlist(i));\n\n      if (obj)\n        draw (obj, toplevel);\n    }\n}\n\nvoid\nopengl_renderer::set_viewport (int w, int h)\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glViewport (0, 0, w, h);\n\n#else\n\n  octave_unused_parameter (w);\n  octave_unused_parameter (h);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::set_viewport\");\n\n#endif\n}\n\nMatrix\nopengl_renderer::get_viewport_scaled () const\n{\n  Matrix retval (1, 4, 0.0);\n\n#if defined (HAVE_OPENGL)\n#if defined (HAVE_FRAMEWORK_OPENGL)\n  GLint vp[4];\n#else\n  int vp[4];\n#endif\n\n  m_glfcns.glGetIntegerv (GL_VIEWPORT, vp);\n\n  for (int i = 0; i < 4; i++)\n    retval(i) = static_cast<double> (vp[i]) / m_devpixratio;\n\n#else\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::get_viewport_scaled\");\n\n#endif\n\n  return retval;\n}\n\nvoid\nopengl_renderer::set_color (const Matrix& c)\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glColor3dv (c.data ());\n\n  if (! c.isempty ())\n    m_txt_renderer.set_color (c);\n\n#else\n\n  octave_unused_parameter (c);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::set_color\");\n\n#endif\n}\n\nvoid\nopengl_renderer::set_font (const base_properties& props)\n{\n  bool do_anti_alias = props.get (\"fontsmoothing\").string_value () == \"on\";\n  m_txt_renderer.set_anti_aliasing (do_anti_alias);\n  m_txt_renderer.set_font (props.get (\"fontname\").string_value (),\n                           props.get (\"fontweight\").string_value (),\n                           props.get (\"fontangle\").string_value (),\n                           props.get (\"__fontsize_points__\").double_value ()\n                           * m_devpixratio);\n}\n\nvoid\nopengl_renderer::set_polygon_offset (bool on, float offset)\n{\n#if defined (HAVE_OPENGL)\n\n  if (on)\n    {\n      m_glfcns.glEnable (GL_POLYGON_OFFSET_FILL);\n      m_glfcns.glEnable (GL_POLYGON_OFFSET_LINE);\n      m_glfcns.glPolygonOffset (offset, offset);\n    }\n  else\n    {\n      m_glfcns.glDisable (GL_POLYGON_OFFSET_FILL);\n      m_glfcns.glDisable (GL_POLYGON_OFFSET_LINE);\n    }\n\n#else\n\n  octave_unused_parameter (on);\n  octave_unused_parameter (offset);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::set_polygon_offset\");\n\n#endif\n}\n\nvoid\nopengl_renderer::set_linewidth (float w)\n{\n#if defined (HAVE_OPENGL)\n  // Measure LineWidth in points.  See bug #53056.\n  m_glfcns.glLineWidth (points_to_pixels (w) * m_devpixratio);\n\n#else\n\n  octave_unused_parameter (w);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::set_linewidth\");\n\n#endif\n}\n\nvoid\nopengl_renderer::set_linestyle (const std::string& s, bool use_stipple,\n                                double linewidth)\n{\n#if defined (HAVE_OPENGL)\n  // Measure LineWidth in points.  See bug #53056.\n  int factor = math::round (points_to_pixels (linewidth) * m_devpixratio);\n  if (factor < 1)\n    factor = 1;\n\n  uint16_t pattern = 0xFFFF;\n\n  bool solid = false;\n\n  if (s == \"-\")\n    solid = true;\n  else if (s == \":\")\n    {\n      if (factor > 1)\n        pattern = 0x5555;\n      else\n        pattern = 0x1111;\n    }\n  else if (s == \"--\")\n    {\n      if (factor > 1)\n        pattern = 0x0F0F;\n      else\n        pattern = 0x01FF;\n    }\n  else if (s == \"-.\")\n    {\n      if (factor > 1)\n        pattern = 0x6F6F;\n      else\n        pattern = 0x18FF;\n    }\n  else\n    pattern = 0x0000;\n\n  m_glfcns.glLineStipple (factor, pattern);\n\n  if (solid && ! use_stipple)\n    m_glfcns.glDisable (GL_LINE_STIPPLE);\n  else\n    m_glfcns.glEnable (GL_LINE_STIPPLE);\n\n#else\n\n  octave_unused_parameter (s);\n  octave_unused_parameter (use_stipple);\n  octave_unused_parameter (linewidth);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::set_linestyle\");\n\n#endif\n}\n\nvoid\nopengl_renderer::set_clipbox (double x1, double x2, double y1, double y2,\n                              double z1, double z2)\n{\n#if defined (HAVE_OPENGL)\n\n  double dx = (x2-x1);\n  double dy = (y2-y1);\n  double dz = (z2-z1);\n\n  x1 -= 0.001*dx; x2 += 0.001*dx;\n  y1 -= 0.001*dy; y2 += 0.001*dy;\n  z1 -= 0.001*dz; z2 += 0.001*dz;\n\n  std::array<double, 4> p = {0.0, 0.0, 0.0, 0.0};\n\n  p[0] = -1; p[3] = x2;\n  m_glfcns.glClipPlane (GL_CLIP_PLANE0, p.data ());\n  p[0] = 1; p[3] = -x1;\n  m_glfcns.glClipPlane (GL_CLIP_PLANE1, p.data ());\n  p[0] = 0; p[1] = -1; p[3] = y2;\n  m_glfcns.glClipPlane (GL_CLIP_PLANE2, p.data ());\n  p[1] = 1; p[3] = -y1;\n  m_glfcns.glClipPlane (GL_CLIP_PLANE3, p.data ());\n  p[1] = 0; p[2] = -1; p[3] = z2;\n  m_glfcns.glClipPlane (GL_CLIP_PLANE4, p.data ());\n  p[2] = 1; p[3] = -z1;\n  m_glfcns.glClipPlane (GL_CLIP_PLANE5, p.data ());\n\n  m_xmin = x1; m_xmax = x2;\n  m_ymin = y1; m_ymax = y2;\n  m_zmin = z1; m_zmax = z2;\n\n#else\n\n  octave_unused_parameter (x1);\n  octave_unused_parameter (x2);\n  octave_unused_parameter (y1);\n  octave_unused_parameter (y2);\n  octave_unused_parameter (z1);\n  octave_unused_parameter (z2);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::set_clipbox\");\n\n#endif\n}\n\nvoid\nopengl_renderer::set_clipping (bool enable)\n{\n#if defined (HAVE_OPENGL)\n\n  bool has_clipping = (m_glfcns.glIsEnabled (GL_CLIP_PLANE0) == GL_TRUE);\n\n  if (enable != has_clipping)\n    {\n      if (enable)\n        for (int i = 0; i < 6; i++)\n          m_glfcns.glEnable (GL_CLIP_PLANE0+i);\n      else\n        for (int i = 0; i < 6; i++)\n          m_glfcns.glDisable (GL_CLIP_PLANE0+i);\n    }\n\n#else\n\n  octave_unused_parameter (enable);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::set_clipping\");\n\n#endif\n}\n\nvoid\nopengl_renderer::init_marker (const std::string& m, double size, float width)\n{\n#if defined (HAVE_OPENGL)\n  m_glfcns.glMatrixMode (GL_PROJECTION);\n  m_glfcns.glPushMatrix ();\n  m_glfcns.glLoadIdentity ();\n\n  Matrix vp = get_viewport_scaled ();\n  m_glfcns.glOrtho (0, vp(2), vp(3), 0, m_xZ1, m_xZ2);\n  m_glfcns.glMatrixMode (GL_MODELVIEW);\n  m_glfcns.glPushMatrix ();\n\n  set_clipping (false);\n  set_linewidth (width);\n\n  m_marker_id = make_marker_list (m, size, false);\n  m_filled_marker_id = make_marker_list (m, size, true);\n\n#else\n\n  octave_unused_parameter (m);\n  octave_unused_parameter (size);\n  octave_unused_parameter (width);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::init_marker\");\n\n#endif\n}\n\nvoid\nopengl_renderer::change_marker (const std::string& m, double size)\n{\n#if defined (HAVE_OPENGL)\n\n  m_marker_id = make_marker_list (m, size, false);\n  m_filled_marker_id = make_marker_list (m, size, true);\n\n#else\n\n  octave_unused_parameter (m);\n  octave_unused_parameter (size);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::change_marker\");\n\n#endif\n}\n\nvoid\nopengl_renderer::end_marker ()\n{\n#if defined (HAVE_OPENGL)\n\n  m_glfcns.glDeleteLists (m_marker_id, 1);\n  m_glfcns.glDeleteLists (m_filled_marker_id, 1);\n\n  m_glfcns.glMatrixMode (GL_MODELVIEW);\n  m_glfcns.glPopMatrix ();\n  m_glfcns.glMatrixMode (GL_PROJECTION);\n  m_glfcns.glPopMatrix ();\n  set_linewidth (0.5f);\n\n#else\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::end_marker\");\n\n#endif\n}\n\nvoid\nopengl_renderer::draw_marker (double x, double y, double z,\n                              const Matrix& lc, const Matrix& fc,\n                              const double la, const double fa)\n{\n#if defined (HAVE_OPENGL)\n\n  ColumnVector tmp = m_xform.transform (x, y, z, false);\n\n  m_glfcns.glLoadIdentity ();\n  m_glfcns.glTranslated (tmp(0), tmp(1), -tmp(2));\n\n  if (m_filled_marker_id > 0 && fc.numel () > 0)\n    {\n      m_glfcns.glColor4d (fc(0), fc(1), fc(2), fa);\n      set_polygon_offset (true, -1.0);\n      m_glfcns.glCallList (m_filled_marker_id);\n      if (lc.numel () > 0)\n        {\n          m_glfcns.glColor4d (lc(0), lc(1), lc(2), la);\n          m_glfcns.glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n          m_glfcns.glEdgeFlag (GL_TRUE);\n          set_polygon_offset (true, -2.0);\n          m_glfcns.glCallList (m_filled_marker_id);\n          m_glfcns.glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n        }\n      set_polygon_offset (false);\n    }\n  else if (m_marker_id > 0 && lc.numel () > 0)\n    {\n      m_glfcns.glColor4d (lc(0), lc(1), lc(2), la);\n      m_glfcns.glCallList (m_marker_id);\n    }\n\n#else\n\n  octave_unused_parameter (x);\n  octave_unused_parameter (y);\n  octave_unused_parameter (z);\n  octave_unused_parameter (lc);\n  octave_unused_parameter (fc);\n  octave_unused_parameter (la);\n  octave_unused_parameter (fa);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::draw_marker\");\n\n#endif\n}\n\nvoid\nopengl_renderer::init_maxlights ()\n{\n#if defined (HAVE_OPENGL)\n\n  // Check actual maximum number of lights possible\n  if (m_max_lights == 0)\n    {\n      GLint max_lights;\n      m_glfcns.glGetIntegerv (GL_MAX_LIGHTS, &max_lights);\n      m_max_lights = max_lights;\n    }\n\n#else\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::init_maxlights\");\n\n#endif\n}\n\nstd::string\nopengl_renderer::get_string (unsigned int id) const\n{\n#if defined (HAVE_OPENGL)\n\n  // This is kind of ugly, but glGetString returns a pointer to GLubyte\n  // and there is no std::string constructor that matches.  Is there a\n  // better way?\n\n  std::ostringstream buf;\n\n  buf << m_glfcns.glGetString (static_cast<GLenum> (id));\n\n  return std::string (buf.str ());\n\n#else\n\n  octave_unused_parameter (id);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::get_string\");\n  return std::string ();\n\n#endif\n}\n\nvoid\nopengl_renderer::set_normal (int bfl_mode, const NDArray& n, int j, int i)\n{\n#if defined (HAVE_OPENGL)\n\n  double x = n(j, i, 0);\n  double y = n(j, i, 1);\n  double z = n(j, i, 2);\n\n  double d = sqrt (x*x + y*y + z*z);\n\n  double dir = 1.0;\n\n  if (bfl_mode > 0)\n    dir = ((x*m_view_vector(0) + y*m_view_vector(1) + z*m_view_vector(2) < 0)\n           ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0);\n\n  m_glfcns.glNormal3d (dir*x/d, dir*y/d, dir*z/d);\n\n#else\n\n  octave_unused_parameter (bfl_mode);\n  octave_unused_parameter (n);\n  octave_unused_parameter (j);\n  octave_unused_parameter (i);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::set_normal\");\n\n#endif\n}\n\ndouble\nopengl_renderer::points_to_pixels (const double val) const\n{\n  gh_manager& gh_mgr = __get_gh_manager__ ();\n\n  // FIXME: Does making this static cause problems if figure is moved to a\n  //        2nd monitor with a different value for \"screenpixelsperinch\"?\n  static const double pix_per_pts =\n    gh_mgr.get_object (0).get (\"screenpixelsperinch\").double_value () / 72.0;\n\n  double retval = val;\n\n  if (! m_printing)\n    retval *= pix_per_pts;\n\n  return retval;\n}\n\nunsigned int\nopengl_renderer::make_marker_list (const std::string& marker, double size,\n                                   bool filled) const\n{\n#if defined (HAVE_OPENGL)\n\n  char c = marker[0];\n\n  if (filled && (c == '+' || c == 'x' || c == '*' || c == '.'\n                 || c == '|' || c == '_'))\n    return 0;\n\n  unsigned int ID = m_glfcns.glGenLists (1);\n\n  // FIXME: See bug #53056 (measure LineWidth in points).\n  double sz = points_to_pixels (size);\n\n  // constants for the * marker\n  const double sqrt2d4 = 0.35355339059327;\n  double tt = sz*sqrt2d4;\n\n  m_glfcns.glNewList (ID, GL_COMPILE);\n\n  switch (marker[0])\n    {\n    case '+':\n      m_glfcns.glBegin (GL_LINES);\n      m_glfcns.glVertex2d (-sz/2, 0);\n      m_glfcns.glVertex2d (sz/2, 0);\n      m_glfcns.glVertex2d (0, -sz/2);\n      m_glfcns.glVertex2d (0, sz/2);\n      m_glfcns.glEnd ();\n      break;\n    case '|':\n      m_glfcns.glBegin (GL_LINES);\n      m_glfcns.glVertex2d (0, -sz/2);\n      m_glfcns.glVertex2d (0, sz/2);\n      m_glfcns.glEnd ();\n      break;\n    case '_':\n      m_glfcns.glBegin (GL_LINES);\n      m_glfcns.glVertex2d (-sz/2, 0);\n      m_glfcns.glVertex2d (sz/2, 0);\n      m_glfcns.glEnd ();\n      break;\n    case 'x':\n      m_glfcns.glBegin (GL_LINES);\n      m_glfcns.glVertex2d (-sz/2, -sz/2);\n      m_glfcns.glVertex2d (sz/2, sz/2);\n      m_glfcns.glVertex2d (-sz/2, sz/2);\n      m_glfcns.glVertex2d (sz/2, -sz/2);\n      m_glfcns.glEnd ();\n      break;\n    case '*':\n      m_glfcns.glBegin (GL_LINES);\n      m_glfcns.glVertex2d (-sz/2, 0);\n      m_glfcns.glVertex2d (sz/2, 0);\n      m_glfcns.glVertex2d (0, -sz/2);\n      m_glfcns.glVertex2d (0, sz/2);\n      m_glfcns.glVertex2d (-tt, -tt);\n      m_glfcns.glVertex2d (+tt, +tt);\n      m_glfcns.glVertex2d (-tt, +tt);\n      m_glfcns.glVertex2d (+tt, -tt);\n      m_glfcns.glEnd ();\n      break;\n    case '.':\n      {\n        // The dot marker is special and is drawn at 1/3rd the specified size\n\n        // Ensure that something is drawn even at very small markersizes\n        if (sz > 0 && sz < 3)\n          sz = 3;\n\n        int div = static_cast<int> (M_PI * sz / 12);\n        if (! (div % 2))\n          div += 1;               // ensure odd number for left/right symmetry\n        div = std::max (div, 3);  // ensure at least a few vertices are drawn\n        double ang_step = M_PI / div;\n\n        m_glfcns.glBegin (GL_POLYGON);\n        for (double ang = 0; ang < 2*M_PI; ang += ang_step)\n          m_glfcns.glVertex2d (sz/6*cos (ang), sz/6*sin (ang));\n        m_glfcns.glEnd ();\n      }\n      break;\n    case 's':\n      m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);\n      m_glfcns.glVertex2d (-sz/2, -sz/2);\n      m_glfcns.glVertex2d (-sz/2, sz/2);\n      m_glfcns.glVertex2d (sz/2, sz/2);\n      m_glfcns.glVertex2d (sz/2, -sz/2);\n      m_glfcns.glEnd ();\n      break;\n    case 'o':\n      {\n        int div = static_cast<int> (M_PI * sz / 4);\n        if (! (div % 2))\n          div += 1;               // ensure odd number for left/right symmetry\n        div = std::max (div, 5);  // ensure at least a few vertices are drawn\n        double ang_step = M_PI / div;\n\n        m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);\n        for (double ang = 0; ang < 2*M_PI; ang += ang_step)\n          m_glfcns.glVertex2d (sz/2*cos (ang), sz/2*sin (ang));\n        m_glfcns.glEnd ();\n      }\n      break;\n    case 'd':\n      m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);\n      m_glfcns.glVertex2d (0, -sz/2);\n      m_glfcns.glVertex2d (sz/2, 0);\n      m_glfcns.glVertex2d (0, sz/2);\n      m_glfcns.glVertex2d (-sz/2, 0);\n      m_glfcns.glEnd ();\n      break;\n    case 'v':\n      m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);\n      m_glfcns.glVertex2d (0, sz/2);\n      m_glfcns.glVertex2d (sz/2, -sz/2);\n      m_glfcns.glVertex2d (-sz/2, -sz/2);\n      m_glfcns.glEnd ();\n      break;\n    case '^':\n      m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);\n      m_glfcns.glVertex2d (0, -sz/2);\n      m_glfcns.glVertex2d (-sz/2, sz/2);\n      m_glfcns.glVertex2d (sz/2, sz/2);\n      m_glfcns.glEnd ();\n      break;\n    case '>':\n      m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);\n      m_glfcns.glVertex2d (sz/2, 0);\n      m_glfcns.glVertex2d (-sz/2, sz/2);\n      m_glfcns.glVertex2d (-sz/2, -sz/2);\n      m_glfcns.glEnd ();\n      break;\n    case '<':\n      m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);\n      m_glfcns.glVertex2d (-sz/2, 0);\n      m_glfcns.glVertex2d (sz/2, -sz/2);\n      m_glfcns.glVertex2d (sz/2, sz/2);\n      m_glfcns.glEnd ();\n      break;\n    case 'p':\n      {\n        double ang, r, dr;\n        dr = 1.0 - sin (M_PI/10)/sin (3*M_PI/10)*1.02;\n\n        m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);\n        for (int i = 0; i < 2*5; i++)\n          {\n            ang = (-0.5 + double (i+1) / 5) * M_PI;\n            r = 1.0 - (dr * fmod (double (i+1), 2.0));\n            m_glfcns.glVertex2d (sz/2*r*cos (ang), sz/2*r*sin (ang));\n          }\n        m_glfcns.glEnd ();\n      }\n      break;\n    case 'h':\n      {\n        double ang, r, dr;\n        dr = 1.0 - 0.5/sin (M_PI/3)*1.02;\n\n        m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);\n        for (int i = 0; i < 2*6; i++)\n          {\n            ang = (0.5 + double (i+1) / 6.0) * M_PI;\n            r = 1.0 - (dr * fmod (double (i+1), 2.0));\n            m_glfcns.glVertex2d (sz/2*r*cos (ang), sz/2*r*sin (ang));\n          }\n        m_glfcns.glEnd ();\n      }\n      break;\n    default:\n      warning (\"opengl_renderer: unsupported marker '%s'\", marker.c_str ());\n      break;\n    }\n\n  m_glfcns.glEndList ();\n\n  return ID;\n\n#else\n\n  octave_unused_parameter (marker);\n  octave_unused_parameter (size);\n  octave_unused_parameter (filled);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::make_marker_list\");\n\n#endif\n}\n\nvoid\nopengl_renderer::text_to_pixels (const std::string& txt,\n                                 uint8NDArray& pixels,\n                                 Matrix& bbox,\n                                 int halign, int valign, double rotation)\n{\n  m_txt_renderer.text_to_pixels (txt, pixels, bbox, halign, valign,\n                                 rotation, m_interpreter);\n}\n\nvoid\nopengl_renderer::text_to_strlist (const std::string& txt,\n                                  std::list<text_renderer::string>& lst,\n                                  Matrix& bbox,\n                                  int halign, int valign, double rotation)\n{\n  m_txt_renderer.text_to_strlist (txt, lst, bbox, halign, valign,\n                                  rotation, m_interpreter);\n}\n\nMatrix\nopengl_renderer::render_text (const std::string& txt,\n                              double x, double y, double z,\n                              int halign, int valign, double rotation)\n{\n#if defined (HAVE_OPENGL)\n\n  Matrix bbox (1, 4, 0.0);\n\n  if (txt.empty ())\n    return bbox;\n\n  if (m_txt_renderer.ok ())\n    {\n      uint8NDArray pixels;\n      text_to_pixels (txt, pixels, bbox, halign, valign, rotation);\n\n      render_text (pixels, bbox, x, y, z, rotation);\n    }\n\n  return bbox;\n\n#else\n\n  octave_unused_parameter (txt);\n  octave_unused_parameter (x);\n  octave_unused_parameter (y);\n  octave_unused_parameter (z);\n  octave_unused_parameter (halign);\n  octave_unused_parameter (valign);\n  octave_unused_parameter (rotation);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::render_text\");\n\n#endif\n}\n\nvoid\nopengl_renderer::render_text (uint8NDArray pixels, Matrix bbox,\n                              double x, double y, double z, double rotation)\n{\n#if defined (HAVE_OPENGL)\n\n  // Transform data coordinates to screen pixel ortho coordinates\n  ColumnVector pixpos = get_transform ().transform (x, y, z, false);\n  Matrix xdata(1, 2, bbox(0) / m_devpixratio);\n  xdata(1) += (bbox(2) - 1) / m_devpixratio;\n  Matrix ydata(1, 2, -bbox(1) / m_devpixratio);\n  ydata(1) -= (bbox(3) - 1) / m_devpixratio;\n\n  bool blend = m_glfcns.glIsEnabled (GL_BLEND);\n  m_glfcns.glEnable (GL_BLEND);\n  m_glfcns.glEnable (GL_ALPHA_TEST);\n\n  set_ortho_coordinates ();\n\n  // Translate coordinates so that the text anchor is (0,0)\n  m_glfcns.glTranslated (pixpos(0), pixpos(1), -pixpos(2));\n\n  m_glfcns.glRotated (-rotation, 0.0, 0.0, 1.0);\n\n  // Permute pixels returned by freetype\n  Array<octave_idx_type> perm (dim_vector (3, 1));\n  perm(0) = 2;\n  perm(1) = 1;\n  perm(2) = 0;\n  draw_texture_image (pixels.permute (perm),\n                      xdata, ydata, true);\n\n  restore_previous_coordinates ();\n\n  m_glfcns.glDisable (GL_ALPHA_TEST);\n\n  if (! blend)\n    m_glfcns.glDisable (GL_BLEND);\n\n#else\n\n  octave_unused_parameter (pixels);\n  octave_unused_parameter (bbox);\n  octave_unused_parameter (x);\n  octave_unused_parameter (y);\n  octave_unused_parameter (z);\n  octave_unused_parameter (rotation);\n\n  // This shouldn't happen because construction of opengl_renderer\n  // objects is supposed to be impossible if OpenGL is not available.\n\n  error_unexpected (\"opengl_renderer::render_text\");\n\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/gl-render.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gl_render_h)\n#define octave_gl_render_h 1\n\n#include \"octave-config.h\"\n\n#include \"graphics.h\"\n#include \"text-renderer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass opengl_functions;\n\nclass OCTINTERP_API opengl_renderer\n{\npublic:\n\n  opengl_renderer (opengl_functions& glfcns);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (opengl_renderer)\n\n  virtual ~opengl_renderer () = default;\n\n  opengl_functions& get_opengl_functions () const { return m_glfcns; }\n\n  virtual void draw (const graphics_object& go, bool toplevel = true);\n\n  // The following version of the draw method is not declared virtual\n  // because no derived class overrides it.\n\n  void draw (const Matrix& hlist, bool toplevel = false);\n\n  virtual void set_viewport (int w, int h);\n  virtual void set_device_pixel_ratio (double dpr) { m_devpixratio = dpr; }\n  virtual Matrix get_viewport_scaled () const;\n  virtual graphics_xform get_transform () const { return m_xform; }\n  virtual uint8NDArray get_pixels (int width, int height);\n\n  virtual void draw_zoom_box (int width, int height,\n                              int x1, int y1, int x2, int y2,\n                              const Matrix& overlaycolor,\n                              double overlayalpha,\n                              const Matrix& bordercolor,\n                              double borderalpha, double borderwidth);\n\n  virtual void finish ();\n\nprotected:\n\n  virtual void draw_figure (const figure::properties& props);\n  virtual void draw_axes (const axes::properties& props);\n  virtual void draw_line (const line::properties& props);\n  virtual void draw_surface (const surface::properties& props);\n  virtual void draw_patch (const patch::properties& props);\n  virtual void draw_scatter (const scatter::properties& props);\n  virtual void draw_light (const light::properties& props);\n  virtual void draw_hggroup (const hggroup::properties& props);\n  virtual void draw_text (const text::properties& props);\n  virtual void draw_text_background (const text::properties& props,\n                                     bool do_rotate = false);\n  virtual void draw_image (const image::properties& props);\n  virtual void draw_uipanel (const uipanel::properties& props,\n                             const graphics_object& go);\n  virtual void draw_uibuttongroup (const uibuttongroup::properties& props,\n                                   const graphics_object& go);\n  virtual void init_gl_context (bool enhanced, const Matrix& backgroundColor);\n  virtual void setup_opengl_transformation (const axes::properties& props);\n\n  virtual void set_clipbox (double x1, double x2, double y1, double y2,\n                            double z1, double z2);\n  virtual void set_clipping (bool on);\n  virtual void set_font (const base_properties& props);\n  virtual void set_color (const Matrix& c);\n  virtual void set_interpreter (const caseless_str& interp)\n  {\n    m_interpreter = interp;\n  }\n  virtual void set_linewidth (float w);\n  virtual void set_linestyle (const std::string& s, bool stipple = false,\n                              double linewidth = 0.5);\n  virtual void set_linecap (const std::string&) { }\n  virtual void set_linejoin (const std::string&) { }\n  virtual void set_polygon_offset (bool on, float offset = 0.0f);\n  virtual void set_selecting (bool on)\n  {\n    m_selecting = on;\n  }\n\n  virtual void init_marker (const std::string& m, double size, float width);\n  virtual void change_marker (const std::string& m, double size);\n  virtual void end_marker ();\n  virtual void draw_marker (double x, double y, double z,\n                            const Matrix& lc, const Matrix& fc,\n                            const double la = 1.0, const double fa = 1.0);\n\n  virtual void text_to_pixels (const std::string& txt,\n                               uint8NDArray& pixels,\n                               Matrix& bbox,\n                               int halign = 0, int valign = 0,\n                               double rotation = 0.0);\n\n  virtual void text_to_strlist (const std::string& txt,\n                                std::list<text_renderer::string>& lst,\n                                Matrix& bbox,\n                                int halign = 0, int valign = 0,\n                                double rotation = 0.0);\n\n  virtual Matrix render_text (const std::string& txt,\n                              double x, double y, double z,\n                              int halign, int valign, double rotation = 0.0);\n\n  virtual void render_grid (const double linewidth,\n                            const std::string& gridstyle,\n                            const Matrix& gridcolor, const double gridalpha,\n                            const Matrix& ticks, double lim1, double lim2,\n                            double p1, double p1N, double p2, double p2N,\n                            int xyz, bool is_3D);\n\n  virtual void render_tickmarks (const Matrix& ticks,\n                                 double lim1, double lim2,\n                                 double p1, double p1N, double p2, double p2N,\n                                 double dx, double dy, double dz,\n                                 int xyz, bool doubleside, bool tickdir_both);\n\n  virtual void render_ticktexts (const Matrix& ticks,\n                                 const string_vector& ticklabels,\n                                 double lim1, double lim2,\n                                 double p1, double p2,\n                                 int xyz, int ha, int va,\n                                 int& wmax, int& hmax);\n\n  virtual void draw_zoom_rect (int x1, int y1, int x2, int y2);\n\n  //--------\n\n  opengl_functions& m_glfcns;\n\n  // axis limits in model scaled coordinate\n  double m_xmin, m_xmax;\n  double m_ymin, m_ymax;\n  double m_zmin, m_zmax;\n\n  // Factor used for translating Octave pixels to actual device pixels\n  double m_devpixratio;\n\n  // axes transformation data\n  graphics_xform m_xform;\n\nprivate:\n\n  class patch_tessellator;\n\n  void init_maxlights ();\n\n  std::string get_string (unsigned int id) const;\n\n  bool is_nan_or_inf (double x, double y, double z) const\n  {\n    return (math::isnan (x) || math::isnan (y)\n            || math::isnan (z)\n            || math::isinf (x) || math::isinf (y)\n            || math::isinf (z));\n  }\n\n  uint8_t clip_code (double x, double y, double z) const\n  {\n    return ((x < m_xmin ? 1 : 0)\n            | (x > m_xmax ? 1 : 0) << 1\n            | (y < m_ymin ? 1 : 0) << 2\n            | (y > m_ymax ? 1 : 0) << 3\n            | (z < m_zmin ? 1 : 0) << 4\n            | (z > m_zmax ? 1 : 0) << 5\n            | (is_nan_or_inf (x, y, z) ? 0 : 1) << 6);\n  }\n\n  void render_text (uint8NDArray pixels, Matrix bbox,\n                    double x, double y, double z, double rotation);\n\n  void set_normal (int bfl_mode, const NDArray& n, int j, int i);\n\n  void set_ortho_coordinates ();\n\n  void restore_previous_coordinates ();\n\n  double points_to_pixels (const double val) const;\n\n  unsigned int make_marker_list (const std::string& m, double size,\n                                 bool filled) const;\n\n  void draw_axes_planes (const axes::properties& props);\n  void draw_axes_boxes (const axes::properties& props);\n\n  void draw_axes_grids (const axes::properties& props);\n  void draw_axes_x_grid (const axes::properties& props);\n  void draw_axes_y_grid (const axes::properties& props);\n  void draw_axes_z_grid (const axes::properties& props);\n\n  void draw_axes_children (const axes::properties& props);\n\n  void draw_all_lights (const base_properties& props,\n                        std::list<graphics_object>& obj_list);\n\n  void draw_texture_image (const octave_value cdata,\n                           Matrix x, Matrix y, bool ortho = false);\n\n  //--------\n\n  // The graphics m_toolkit associated with the figure being rendered.\n  graphics_toolkit m_toolkit;\n\n  // Z projection limits in windows coordinate\n  double m_xZ1, m_xZ2;\n\n  // call lists identifiers for markers\n  unsigned int m_marker_id, m_filled_marker_id;\n\n  // camera information for primitive sorting and lighting\n  ColumnVector m_camera_pos, m_camera_dir, m_view_vector;\n\n  // interpreter to be used by text_to_pixels\n  caseless_str m_interpreter;\n\n  text_renderer m_txt_renderer;\n\n  // light object present and visible\n  unsigned int m_current_light;\n  unsigned int m_max_lights;\n\n  // Indicate we are drawing for selection purpose\n  bool m_selecting;\n\n  // Indicate we are drawing for printing purpose\n  bool m_printing;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/gl2ps-print.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Both header files are required outside of HAVE_GLP2S_H\n#include \"errwarn.h\"\n#include \"gl2ps-print.h\"\n\n#if defined (HAVE_GL2PS_H) && defined (HAVE_OPENGL)\n\n#include <cstdio>\n\n#include <limits>\n\n#include <gl2ps.h>\n\n#include \"file-ops.h\"\n#include \"filepos-wrappers.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"unistd-wrappers.h\"\n#include \"unistr-wrappers.h\"\n#include \"unwind-prot.h\"\n\n#include \"gh-manager.h\"\n#include \"gl-render.h\"\n#include \"interpreter-private.h\"\n#include \"oct-opengl.h\"\n#include \"sighandlers.h\"\n#include \"sysdep.h\"\n#include \"text-renderer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API gl2ps_renderer : public opengl_renderer\n{\npublic:\n\n  gl2ps_renderer (opengl_functions& glfcns, FILE *_fp,\n                  const std::string& _term)\n    : opengl_renderer (glfcns), m_fp (_fp), m_term (_term), m_fontsize (),\n      m_fontname (), m_buffer_overflow (false), m_svg_def_index (0)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (gl2ps_renderer)\n\n  ~gl2ps_renderer () = default;\n\n  // FIXME: should we import the functions from the base class and\n  // overload them here, or should we use a different name so we don't\n  // have to do this?  Without the using declaration or a name change,\n  // the base class functions will be hidden.  That may be OK, but it\n  // can also cause some confusion.\n  using opengl_renderer::draw;\n\n  void draw (const graphics_object& go, const std::string& print_cmd);\n\nprotected:\n\n  Matrix render_text (const std::string& txt,\n                      double x, double y, double z,\n                      int halign, int valign, double rotation = 0.0);\n\n  void set_font (const base_properties& props);\n\n  static bool has_alpha (const graphics_handle& h)\n  {\n    bool retval = false;\n\n    gh_manager& gh_mgr = __get_gh_manager__ ();\n\n    graphics_object go = gh_mgr.get_object (h);\n\n    if (! go.valid_object ())\n      return retval;\n\n    if (go.isa (\"axes\") || go.isa (\"hggroup\"))\n      {\n        Matrix children = go.get (\"children\").matrix_value ();\n        for (octave_idx_type ii = 0; ii < children.numel (); ii++)\n          {\n            retval = has_alpha (graphics_handle (children(ii)));\n            if (retval)\n              break;\n          }\n      }\n    else if (go.isa (\"patch\") || go.isa (\"surface\"))\n      {\n        octave_value fa = go.get (\"facealpha\");\n        if (fa.is_scalar_type () && fa.is_double_type ()\n            && fa.double_value () < 1)\n          retval = true;\n      }\n    else if (go.isa (\"scatter\"))\n      {\n        octave_value fa = go.get (\"markerfacealpha\");\n        if (fa.is_scalar_type () && fa.is_double_type ()\n            && fa.double_value () < 1)\n          retval = true;\n      }\n\n    return retval;\n  }\n\n  void draw_axes (const axes::properties& props)\n  {\n    // Initialize a sorting tree (viewport) in gl2ps for each axes\n    GLint vp[4];\n    m_glfcns.glGetIntegerv (GL_VIEWPORT, vp);\n    gl2psBeginViewport (vp);\n\n\n    // Don't remove hidden primitives when some of them are transparent\n    GLint opts;\n    gl2psGetOptions (&opts);\n    if (has_alpha (props.get___myhandle__ ()))\n      {\n        opts &= ~GL2PS_OCCLUSION_CULL;\n        // FIXME: currently the GL2PS_BLEND (which is more an equivalent of\n        // GL_ALPHA_TEST than GL_BLEND) is not working on a per primitive\n        // basis.  We thus set it once per viewport.\n        gl2psEnable (GL2PS_BLEND);\n      }\n    else\n      {\n        opts |= GL2PS_OCCLUSION_CULL;\n        gl2psDisable (GL2PS_BLEND);\n      }\n\n    gl2psSetOptions (opts);\n\n    // Draw and finish () or there may be primitives missing in the gl2ps\n    // output.\n    opengl_renderer::draw_axes (props);\n    finish ();\n\n    // Finalize viewport\n    GLint state = gl2psEndViewport ();\n    if (state == GL2PS_NO_FEEDBACK && props.is_visible ())\n      warning (\"gl2ps_renderer::draw_axes: empty feedback buffer and/or nothing else to print\");\n    else if (state == GL2PS_ERROR)\n      error (\"gl2ps_renderer::draw_axes: gl2psEndPage returned GL2PS_ERROR\");\n\n    m_buffer_overflow |= (state == GL2PS_OVERFLOW);\n\n    // Don't draw background for subsequent viewports (legends, subplots,\n    // etc.)\n    gl2psGetOptions (&opts);\n    opts &= ~GL2PS_DRAW_BACKGROUND;\n    gl2psSetOptions (opts);\n  }\n\n  void draw_text (const text::properties& props);\n\n  void draw_image (const image::properties& props);\n  void draw_pixels (int w, int h, const float *data);\n  void draw_pixels (int w, int h, const uint8_t *data);\n  void draw_pixels (int w, int h, const uint16_t *data);\n\n  void init_marker (const std::string& m, double size, float width)\n  {\n    opengl_renderer::init_marker (m, size, width);\n\n    // FIXME: gl2ps can't handle closed contours so we set linecap/linejoin\n    //        round to obtain a better looking result for some markers.\n    if (m == \"o\" || m == \"v\" || m == \"^\" || m == \">\" || m == \"<\" || m == \"h\"\n        || m == \"hexagram\" || m == \"p\" || m == \"pentagram\")\n      {\n        set_linejoin (\"round\");\n        set_linecap (\"round\");\n      }\n    else\n      {\n        set_linejoin (\"miter\");\n        set_linecap (\"square\");\n      }\n  }\n\n  void set_linestyle (const std::string& s, bool use_stipple = false,\n                      double linewidth = 0.5)\n  {\n    opengl_renderer::set_linestyle (s, use_stipple, linewidth);\n\n    if (s == \"-\" && ! use_stipple)\n      gl2psDisable (GL2PS_LINE_STIPPLE);\n    else\n      gl2psEnable (GL2PS_LINE_STIPPLE);\n  }\n\n  void set_linecap (const std::string& s)\n  {\n    opengl_renderer::set_linejoin (s);\n\n#if defined (HAVE_GL2PSLINEJOIN)\n    if (s == \"butt\")\n      gl2psLineCap (GL2PS_LINE_CAP_BUTT);\n    else if (s == \"square\")\n      gl2psLineCap (GL2PS_LINE_CAP_SQUARE);\n    else if (s == \"round\")\n      gl2psLineCap (GL2PS_LINE_CAP_ROUND);\n#endif\n  }\n\n  void set_linejoin (const std::string& s)\n  {\n    opengl_renderer::set_linejoin (s);\n\n#if defined (HAVE_GL2PSLINEJOIN)\n    if (s == \"round\")\n      gl2psLineJoin (GL2PS_LINE_JOIN_ROUND);\n    else if (s == \"miter\")\n      gl2psLineJoin (GL2PS_LINE_JOIN_MITER);\n    else if (s == \"chamfer\")\n      gl2psLineJoin (GL2PS_LINE_JOIN_BEVEL);\n#endif\n  }\n\n  void set_polygon_offset (bool on, float offset = 0.0f)\n  {\n    if (on)\n      {\n        opengl_renderer::set_polygon_offset (on, offset);\n        gl2psEnable (GL2PS_POLYGON_OFFSET_FILL);\n      }\n    else\n      {\n        gl2psDisable (GL2PS_POLYGON_OFFSET_FILL);\n        opengl_renderer::set_polygon_offset (on, offset);\n      }\n  }\n\n  void set_linewidth (float w)\n  {\n    gl2psLineWidth (w);\n  }\n\nprivate:\n\n  // Use xform to compute the coordinates of the string list\n  // that have been parsed by freetype.\n  void fix_strlist_position (double x, double y, double z,\n                             Matrix box, double rotation,\n                             std::list<text_renderer::string>& lst);\n\n  // Build an svg text element from a list of parsed strings\n  std::string format_svg_element (std::string str, Matrix bbox,\n                                  double rotation, ColumnVector coord_pix,\n                                  Matrix color);\n\n  std::string strlist_to_svg (double x, double y, double z, Matrix box,\n                              double rotation,\n                              std::list<text_renderer::string>& lst);\n\n  // Build a list of postscript commands from a list of parsed strings.\n  std::string strlist_to_ps (double x, double y, double z, Matrix box,\n                             double rotation,\n                             std::list<text_renderer::string>& lst);\n\n  int alignment_to_mode (int ha, int va) const;\n\n  FILE *m_fp;\n  caseless_str m_term;\n  double m_fontsize;\n  std::string m_fontname;\n  bool m_buffer_overflow;\n  std::size_t m_svg_def_index;\n};\n\nstatic bool\nhas_2D_axes (const graphics_handle& h)\n{\n  bool retval = true;\n\n  gh_manager& gh_mgr = __get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (! go.valid_object ())\n    return retval;\n\n  if (go.isa (\"figure\") || go.isa (\"uipanel\"))\n    {\n      Matrix children = go.get (\"children\").matrix_value ();\n      for (octave_idx_type ii = 0; ii < children.numel (); ii++)\n        {\n          retval = has_2D_axes (graphics_handle (children(ii)));\n          if (! retval)\n            break;\n        }\n    }\n  else if (go.isa (\"axes\"))\n    {\n      axes::properties& ap\n        = reinterpret_cast<axes::properties&> (go.get_properties ());\n      retval = ap.get_is2D (true);\n    }\n\n  return retval;\n}\n\nstatic std::string\nget_title (const graphics_handle& h)\n{\n  std::string retval;\n\n  gh_manager& gh_mgr = __get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (! go.valid_object ())\n    return retval;\n\n  if (go.isa (\"figure\"))\n    {\n      figure::properties& fp\n        = reinterpret_cast<figure::properties&> (go.get_properties ());\n\n      retval = fp.get_title ();\n    }\n\n  return retval;\n}\n\nvoid\ngl2ps_renderer::draw (const graphics_object& go, const std::string& print_cmd)\n{\n  static bool in_draw = false;\n  static std::string old_print_cmd;\n  static GLint buffsize;\n\n  if (! in_draw)\n    {\n      unwind_protect frame;\n\n      frame.protect_var (in_draw);\n\n      in_draw = true;\n\n      GLint gl2ps_term = GL2PS_PS;\n      if (m_term.find (\"eps\") != std::string::npos)\n        gl2ps_term = GL2PS_EPS;\n      else if (m_term.find (\"pdf\") != std::string::npos)\n        gl2ps_term = GL2PS_PDF;\n      else if (m_term.find (\"ps\") != std::string::npos)\n        gl2ps_term = GL2PS_PS;\n      else if (m_term.find (\"svg\") != std::string::npos)\n        gl2ps_term = GL2PS_SVG;\n      else if (m_term.find (\"pgf\") != std::string::npos)\n        gl2ps_term = GL2PS_PGF;\n      else if (m_term.find (\"tex\") != std::string::npos)\n        gl2ps_term = GL2PS_TEX;\n      else\n        warning (\"gl2ps_renderer::draw: Unknown terminal %s, using 'ps'\",\n                 m_term.c_str ());\n\n      GLint gl2ps_text = 0;\n      if (m_term.find (\"notxt\") != std::string::npos)\n        gl2ps_text = GL2PS_NO_TEXT;\n\n      // Find Title for plot\n      const graphics_handle& myhandle = go.get (\"__myhandle__\");\n      std::string plot_title = get_title (myhandle);\n      if (plot_title.empty ())\n        plot_title = \"Octave plot\";\n\n      // Default sort order optimizes for 3-D plots\n      GLint gl2ps_sort = GL2PS_BSP_SORT;\n\n      // FIXME: gl2ps does not provide a way to change the sorting algorithm\n      // on a viewport basis, we thus disable sorting only if all axes are 2-D\n      if (has_2D_axes (myhandle))\n        gl2ps_sort = GL2PS_NO_SORT;\n\n      // Use a temporary file in case an overflow happens\n      std::string tmpfile (sys::tempnam (sys::env::get_temp_directory (),\n                                         \"oct-\"));\n      FILE *tmpf = sys::fopen_tmp (tmpfile, \"w+b\");\n\n      if (! tmpf)\n        error (\"gl2ps_renderer::draw: couldn't open temporary file for printing\");\n\n      frame.add ([tmpf] () { std::fclose (tmpf); });\n\n      // Reset buffsize, unless this is 2nd pass of a texstandalone print.\n      if (m_term.find (\"tex\") == std::string::npos)\n        buffsize = 2*1024*1024;\n      else\n        buffsize /= 2;\n\n      m_buffer_overflow = true;\n\n      while (m_buffer_overflow)\n        {\n          m_buffer_overflow = false;\n          buffsize *= 2;\n\n          octave_fseeko_wrapper (tmpf, 0, SEEK_SET);\n          octave_ftruncate_wrapper (fileno (tmpf), 0);\n\n          // For LaTeX output the print process uses 2 drawnow() commands.\n          // The first one is for the pdf/ps/eps graph to be included.  The\n          // print_cmd is saved as old_print_cmd.  Then the second drawnow()\n          // outputs the tex-file and the graphic filename to be included is\n          // extracted from old_print_cmd.\n\n          std::string include_graph;\n\n          std::size_t found_redirect = old_print_cmd.find ('>');\n\n          if (found_redirect != std::string::npos)\n            include_graph = old_print_cmd.substr (found_redirect + 1);\n          else\n            include_graph = old_print_cmd;\n\n          std::size_t n_begin = include_graph.find_first_not_of (R\"( \"')\");\n\n          if (n_begin != std::string::npos)\n            {\n              // Strip any quote characters around filename\n              std::size_t n_end = include_graph.find_last_not_of (R\"( \"')\");\n              include_graph = include_graph.substr (n_begin,\n                                                    n_end - n_begin + 1);\n              // Strip path from filename\n              n_begin = include_graph.find_last_of (sys::file_ops::dir_sep_chars ());\n              include_graph = include_graph.substr (n_begin + 1);\n            }\n          else\n            include_graph = \"foobar-inc\";\n\n          // FIXME: workaround gl2ps drawing 2 background planes, the first\n          //        eventually being black and producing visual artifacts\n          const figure::properties& fprop\n            = dynamic_cast<const figure::properties&> (go.get_properties ());\n          Matrix c = fprop.get_color_rgb ();\n          m_glfcns.glClearColor (c(0), c(1), c(2), 1);\n\n          // Allow figures to be printed at arbitrary resolution\n          set_device_pixel_ratio (fprop.get___device_pixel_ratio__ ());\n\n          // GL2PS_SILENT was removed to allow gl2ps to print errors on stderr\n          GLint ret = gl2psBeginPage (plot_title.c_str (), \"Octave\",\n                                      nullptr, gl2ps_term, gl2ps_sort,\n                                      (GL2PS_BEST_ROOT\n                                       | gl2ps_text\n                                       | GL2PS_DRAW_BACKGROUND\n                                       | GL2PS_NO_PS3_SHADING\n                                       | GL2PS_USE_CURRENT_VIEWPORT),\n                                      GL_RGBA, 0, nullptr, 0, 0, 0,\n                                      buffsize, tmpf, include_graph.c_str ());\n          if (ret == GL2PS_ERROR)\n            {\n              old_print_cmd.clear ();\n              error (\"gl2ps_renderer::draw: gl2psBeginPage returned GL2PS_ERROR\");\n            }\n\n          opengl_renderer::draw (go);\n\n          if (m_buffer_overflow)\n            warning (\"gl2ps_renderer::draw: retrying with buffer size: %.1E B\\n\", double (2*buffsize));\n\n          if (! m_buffer_overflow)\n            old_print_cmd = print_cmd;\n\n          // Don't check return value of gl2psEndPage, it is not meaningful.\n          // Errors and warnings are checked after gl2psEndViewport in\n          // gl2ps_renderer::draw_axes instead.\n          gl2psEndPage ();\n        }\n\n      // Copy temporary file to pipe\n      octave_fseeko_wrapper (tmpf, 0, SEEK_SET);\n      char str[8192];  // 8 kB is a common kernel buffersize\n      std::size_t nread, nwrite;\n      nread = 1;\n\n      // In EPS terminal read the header line by line and insert a\n      // new procedure\n      const char *fcn = \"/SRX  { gsave FCT moveto rotate xshow grestore } BD\\n\";\n      bool header_found = ! (m_term.find (\"eps\") != std::string::npos\n                             || m_term.find (\"svg\") != std::string::npos);\n\n      while (! feof (tmpf) && nread)\n        {\n          if (! header_found && std::fgets (str, 8192, tmpf))\n            nread = strlen (str);\n          else\n            nread = std::fread (str, 1, 8192, tmpf);\n\n          if (nread)\n            {\n              if (! header_found && std::strncmp (str, \"/SBCR\", 5) == 0)\n                {\n                  header_found = true;\n                  nwrite = std::fwrite (fcn, 1, strlen (fcn), m_fp);\n                  if (nwrite != strlen (fcn))\n                    {\n                      // FIXME: is this the best thing to do here?\n                      respond_to_pending_signals ();\n                      error (\"gl2ps_renderer::draw: internal pipe error\");\n                    }\n                }\n              else if (m_term.find (\"svg\") != std::string::npos)\n                {\n                  // FIXME: gl2ps uses pixel units for SVG format.\n                  //        Modify resulting svg to use points instead.\n                  //        Remove this \"else if\" block, and\n                  //        make header_found true for SVG if gl2ps is fixed.\n\n                  // Specify number of characters because STR may have\n                  // come from std::fread and not end with a NUL\n                  // character.\n                  std::string srchstr (str, nread);\n                  std::size_t pos = srchstr.find (\"<svg \");\n                  if (! header_found && pos != std::string::npos)\n                    {\n                      header_found = true;\n                      pos = srchstr.find (\"px\");\n                      if (pos != std::string::npos)\n                        {\n                          srchstr[pos+1] = 't';  // \"px\" -> \"pt\"\n                                                 // Assume the second occurrence is at the same line\n                          pos = srchstr.find (\"px\", pos);\n                          srchstr[pos+1] = 't';  // \"px\" -> \"pt\"\n                          std::strcpy (str, srchstr.c_str ());\n                        }\n                    }\n                }\n\n              nwrite = std::fwrite (str, 1, nread, m_fp);\n              if (nwrite != nread)\n                {\n                  // FIXME: is this the best thing to do here?\n                  respond_to_pending_signals ();   // Clear SIGPIPE signal\n                  error (\"gl2ps_renderer::draw: internal pipe error\");\n                }\n            }\n        }\n    }\n  else\n    opengl_renderer::draw (go);\n}\n\nint\ngl2ps_renderer::alignment_to_mode (int ha, int va) const\n{\n  int gl2psa = GL2PS_TEXT_BL;\n\n  if (ha == 0)\n    {\n      if (va == 0 || va == 3)\n        gl2psa=GL2PS_TEXT_BL;\n      else if (va == 2)\n        gl2psa=GL2PS_TEXT_TL;\n      else if (va == 1)\n        gl2psa=GL2PS_TEXT_CL;\n    }\n  else if (ha == 2)\n    {\n      if (va == 0 || va == 3)\n        gl2psa=GL2PS_TEXT_BR;\n      else if (va == 2)\n        gl2psa=GL2PS_TEXT_TR;\n      else if (va == 1)\n        gl2psa=GL2PS_TEXT_CR;\n    }\n  else if (ha == 1)\n    {\n      if (va == 0 || va == 3)\n        gl2psa=GL2PS_TEXT_B;\n      else if (va == 2)\n        gl2psa=GL2PS_TEXT_T;\n      else if (va == 1)\n        gl2psa=GL2PS_TEXT_C;\n    }\n\n  return gl2psa;\n}\n\nvoid\ngl2ps_renderer::fix_strlist_position (double x, double y, double z,\n                                      Matrix box, double rotation,\n                                      std::list<text_renderer::string>& lst)\n{\n  for (auto& txtobj : lst)\n    {\n      // Get pixel coordinates\n      ColumnVector coord_pix = get_transform ().transform (x, y, z, false);\n\n      // Translate and rotate\n      double rot = rotation * 4.0 * atan (1.0) / 180;\n      coord_pix(0) += (txtobj.get_x () + box(0))* cos (rot)\n                      - (txtobj.get_y () + box(1))* sin (rot);\n      coord_pix(1) -= (txtobj.get_y () + box(1))* cos (rot)\n                      + (txtobj.get_x () + box(0))* sin (rot);\n\n      GLint vp[4];\n      m_glfcns.glGetIntegerv (GL_VIEWPORT, vp);\n\n      txtobj.set_x (coord_pix(0));\n      txtobj.set_y (vp[3] - coord_pix(1));\n      txtobj.set_z (coord_pix(2));\n    }\n}\n\nstatic std::string\ncode_to_symbol (uint32_t code)\n{\n  std::string retval;\n\n  uint32_t idx = code - 945;\n  if (idx < 25)\n    {\n      std::string characters (\"abgdezhqiklmnxoprVstufcyw\");\n      retval = characters[idx];\n      return retval;\n    }\n\n  idx = code - 913;\n  if (idx < 25)\n    {\n      std::string characters (\"ABGDEZHQIKLMNXOPRVSTUFCYW\");\n      retval = characters[idx];\n    }\n  else if (code == 978)\n    retval = \"U\";\n  else if (code == 215)\n    retval = \"\\xb4\";\n  else if (code == 177)\n    retval = \"\\xb1\";\n  else if (code == 8501)\n    retval = \"\\xc0\";\n  else if (code == 8465)\n    retval = \"\\xc1\";\n  else if (code == 8242)\n    retval = \"\\xa2\";\n  else if (code == 8736)\n    retval = \"\\xd0\";\n  else if (code == 172)\n    retval = \"\\xd8\";\n  else if (code == 9829)\n    retval = \"\\xa9\";\n  else if (code == 8472)\n    retval = \"\\xc3\";\n  else if (code == 8706)\n    retval = \"\\xb6\";\n  else if (code == 8704)\n    retval = \"\\x22\";\n  else if (code == 9827)\n    retval = \"\\xa7\";\n  else if (code == 9824)\n    retval = \"\\xaa\";\n  else if (code == 8476)\n    retval = \"\\xc2\";\n  else if (code == 8734)\n    retval = \"\\xa5\";\n  else if (code == 8730)\n    retval = \"\\xd6\";\n  else if (code == 8707)\n    retval = \"\\x24\";\n  else if (code == 9830)\n    retval = \"\\xa8\";\n  else if (code == 8747)\n    retval = \"\\xf2\";\n  else if (code == 8727)\n    retval = \"\\x2a\";\n  else if (code == 8744)\n    retval = \"\\xda\";\n  else if (code == 8855)\n    retval = \"\\xc4\";\n  else if (code == 8901)\n    retval = \"\\xd7\";\n  else if (code == 8728)\n    retval = \"\\xb0\";\n  else if (code == 8745)\n    retval = \"\\xc7\";\n  else if (code == 8743)\n    retval = \"\\xd9\";\n  else if (code == 8856)\n    retval = \"\\xc6\";\n  else if (code == 8729)\n    retval = \"\\xb7\";\n  else if (code == 8746)\n    retval = \"\\xc8\";\n  else if (code == 8853)\n    retval = \"\\xc5\";\n  else if (code == 8804)\n    retval = \"\\xa3\";\n  else if (code == 8712)\n    retval = \"\\xce\";\n  else if (code == 8839)\n    retval = \"\\xca\";\n  else if (code == 8801)\n    retval = \"\\xba\";\n  else if (code == 8773)\n    retval = \"\\x40\";\n  else if (code == 8834)\n    retval = \"\\xcc\";\n  else if (code == 8805)\n    retval = \"\\xb3\";\n  else if (code == 8715)\n    retval = \"\\x27\";\n  else if (code == 8764)\n    retval = \"\\x7e\";\n  else if (code == 8733)\n    retval = \"\\xb5\";\n  else if (code == 8838)\n    retval = \"\\xcd\";\n  else if (code == 8835)\n    retval = \"\\xc9\";\n  else if (code == 8739)\n    retval = \"\\xbd\";\n  else if (code == 8776)\n    retval = \"\\xbb\";\n  else if (code == 8869)\n    retval = \"\\x5e\";\n  else if (code == 8656)\n    retval = \"\\xdc\";\n  else if (code == 8592)\n    retval = \"\\xac\";\n  else if (code == 8658)\n    retval = \"\\xde\";\n  else if (code == 8594)\n    retval = \"\\xae\";\n  else if (code == 8596)\n    retval = \"\\xab\";\n  else if (code == 8593)\n    retval = \"\\xad\";\n  else if (code == 8595)\n    retval = \"\\xaf\";\n  else if (code == 8970)\n    retval = \"\\xeb\";\n  else if (code == 8971)\n    retval = \"\\xfb\";\n  else if (code == 10216)\n    retval = \"\\xe1\";\n  else if (code == 10217)\n    retval = \"\\xf1\";\n  else if (code == 8968)\n    retval = \"\\xe9\";\n  else if (code == 8969)\n    retval = \"\\xf9\";\n  else if (code == 8800)\n    retval = \"\\xb9\";\n  else if (code == 8230)\n    retval = \"\\xbc\";\n  else if (code == 176)\n    retval = \"\\xb0\";\n  else if (code == 8709)\n    retval = \"\\xc6\";\n  else if (code == 169)\n    retval = \"\\xd3\";\n\n  if (retval.empty ())\n    warning (\"print: unhandled symbol %d\", code);\n\n  return retval;\n}\n\nstatic std::string\nselect_font (caseless_str fn, bool isbold, bool isitalic)\n{\n  std::transform (fn.begin (), fn.end (), fn.begin (), ::tolower);\n  std::string fontname;\n  if (fn == \"times\" || fn == \"times-roman\")\n    {\n      if (isitalic && isbold)\n        fontname = \"Times-BoldItalic\";\n      else if (isitalic)\n        fontname = \"Times-Italic\";\n      else if (isbold)\n        fontname = \"Times-Bold\";\n      else\n        fontname = \"Times-Roman\";\n    }\n  else if (fn == \"courier\")\n    {\n      if (isitalic && isbold)\n        fontname = \"Courier-BoldOblique\";\n      else if (isitalic)\n        fontname = \"Courier-Oblique\";\n      else if (isbold)\n        fontname = \"Courier-Bold\";\n      else\n        fontname = \"Courier\";\n    }\n  else if (fn == \"symbol\")\n    fontname = \"Symbol\";\n  else if (fn == \"zapfdingbats\")\n    fontname = \"ZapfDingbats\";\n  else\n    {\n      if (isitalic && isbold)\n        fontname = \"Helvetica-BoldOblique\";\n      else if (isitalic)\n        fontname = \"Helvetica-Oblique\";\n      else if (isbold)\n        fontname = \"Helvetica-Bold\";\n      else\n        fontname = \"Helvetica\";\n    }\n  return fontname;\n}\n\nstatic void\nescape_character (const std::string chr, std::string& str)\n{\n  std::size_t idx = str.find (chr);\n  while (idx != std::string::npos)\n    {\n      str.insert (idx, 1, '\\\\');\n      idx = str.find (chr, idx + 2);\n    }\n}\n\nstd::string\ngl2ps_renderer::format_svg_element (std::string str, Matrix box,\n                                    double rotation, ColumnVector coord_pix,\n                                    Matrix color)\n{\n  // Extract <defs> elements and change their id to avoid conflict with\n  // defs coming from another svg string\n  std::string::size_type n1 = str.find (\"<defs>\");\n  if (n1 == std::string::npos)\n    return std::string ();\n\n  std::string id, new_id;\n  n1 = str.find (\"<path\", ++n1);\n  std::string::size_type n2;\n\n  while (n1 != std::string::npos)\n    {\n      // Extract the identifier id='identifier'\n      n1 = str.find (\"id='\", n1) + 4;\n      n2 = str.find (\"'\", n1);\n      id = str.substr (n1, n2-n1);\n\n      new_id = std::to_string (m_svg_def_index) + \"-\" + id ;\n\n      str.replace (n1, n2-n1, new_id);\n\n      std::string::size_type n_ref = str.find (\"#\" + id);\n\n      while (n_ref != std::string::npos)\n        {\n          str.replace (n_ref + 1, id.length (), new_id);\n          n_ref = str.find (\"#\" + id);\n        }\n\n      n1 = str.find (\"<path\", n1);\n    }\n\n  m_svg_def_index++;\n\n  n1 = str.find (\"<defs>\");\n  n2 = str.find (\"</defs>\") + 7;\n\n  std::string defs = str.substr (n1, n2-n1);\n\n  // Extract the group containing the <use> elements and transform its\n  // coordinates using the bbox and coordinates info.\n\n  // Extract the original viewBox anchor\n  n1 = str.find (\"viewBox='\") + 9;\n  if (n1 == std::string::npos)\n    return std::string ();\n\n  n2 = str.find (\" \", n1);\n  double original_x0 = std::stod (str.substr (n1, n2-n1));\n\n  n1 = n2+1;\n  n2 = str.find (\" \", n1);\n  double original_y0 = std::stod (str.substr (n1, n2-n1));\n\n  // First look for local transform in the original svg\n  std::string orig_trans;\n  n1 = str.find (\"<g id='page1' transform='\");\n  if (n1 != std::string::npos)\n    {\n      n1 += 25;\n      n2 = str.find (\"'\", n1);\n      orig_trans = str.substr (n1, n2-n1);\n      n1 = n2 + 1;\n    }\n  else\n    {\n      n1 = str.find (\"<g id='page1'\");\n      n1 += 13;\n    }\n\n  n2 = str.find (\"</g>\", n1) + 4;\n\n  // The first applied transformation is the right-most\n  // 1* Apply original transform\n  std::string tform = orig_trans;\n\n  // 2* Move the anchor to the final position\n  tform = std::string (\"translate\")\n          + \"(\" + std::to_string (box(0) - original_x0 + coord_pix(0))\n          + \",\" + std::to_string (-(box(3) + box(1)) - original_y0 + coord_pix(1))\n          + \") \" + tform;\n\n  // 3* Rotate around the final position\n  if (rotation != 0)\n    tform = std::string (\"rotate\")\n            + \"(\" + std::to_string (-rotation)\n            + \",\" + std::to_string (coord_pix(0))\n            + \",\" + std::to_string (coord_pix(1))\n            + \") \" + tform;\n\n  // Fill color\n  std::string fill = \"fill='rgb(\"\n                     + std::to_string (static_cast<uint8_t> (color(0) * 255.0)) + \",\"\n                     + std::to_string (static_cast<uint8_t> (color(1) * 255.0)) + \",\"\n                     + std::to_string (static_cast<uint8_t> (color(2) * 255.0)) + \")' \";\n\n  std::string use_group = \"<g \"\n                          + fill\n                          + \"transform='\" + tform + \"'\"\n                          + str.substr (n1, n2-n1);\n\n  return defs + \"\\n\" + use_group;\n}\n\nstd::string\ngl2ps_renderer::strlist_to_svg (double x, double y, double z,\n                                Matrix box, double rotation,\n                                std::list<text_renderer::string>& lst)\n{\n  //Use pixel coordinates to conform to gl2ps\n  ColumnVector coord_pix = get_transform ().transform (x, y, z, false);\n\n  if (lst.empty ())\n    return \"\";\n\n  // This may already be an svg image.\n  std::string svg = lst.front ().get_svg_element ();\n  if (! svg.empty ())\n    return format_svg_element (svg, box, rotation, coord_pix,\n                               lst.front ().get_color ());\n\n  // Rotation and translation are applied to the whole group\n  std::ostringstream os;\n  os << R\"(<g xml:space=\"preserve\" )\";\n  os << \"transform=\\\"\"\n     << \"translate(\" << coord_pix(0) + box(0) << \",\" << coord_pix(1) - box(1)\n     << \") rotate(\" << -rotation << \",\" << -box(0) << \",\" << box(1)\n     << \")\\\" \";\n\n  // Use the first entry for the base text font\n  auto p = lst.begin ();\n  std::string name = p->get_family ();\n  std::string weight = p->get_weight ();\n  std::string angle = p->get_angle ();\n  double size = p->get_size ();\n\n  os << \"font-family=\\\"\" << name << \"\\\" \"\n     << \"font-weight=\\\"\" << weight << \"\\\" \"\n     << \"font-style=\\\"\" << angle << \"\\\" \"\n     << \"font-size=\\\"\" << size << \"\\\">\";\n\n\n  // Build a text element for each element in the strlist\n  for (p = lst.begin (); p != lst.end (); p++)\n    {\n      os << \"<text \";\n\n      if (name.compare (p->get_family ()))\n        os << \"font-family=\\\"\" << p->get_family () << \"\\\" \";\n\n      if (weight.compare (p->get_weight ()))\n        os << \"font-weight=\\\"\" << p->get_weight () << \"\\\" \";\n\n      if (angle.compare (p->get_angle ()))\n        os << \"font-style=\\\"\" << p->get_angle () << \"\\\" \";\n\n      if (size != p->get_size ())\n        os << \"font-size=\\\"\" << p->get_size () << \"\\\" \";\n\n      os << \"y=\\\"\" << - p->get_y () << \"\\\" \";\n\n      Matrix col = p->get_color ();\n      os << \"fill=\\\"rgb(\" << col(0)*255 << \",\"\n         << col(1)*255 << \",\" << col(2)*255 << \")\\\" \";\n\n      // provide an x coordinate for each character in the string\n      os << \"x=\\\"\";\n      std::vector<double> xdata = p->get_xdata ();\n      for (const auto& q : xdata)\n        os << q << \" \";\n      os << '\"';\n\n      os << '>';\n\n      // translate unicode and special xml characters\n      if (p->get_code ())\n        os << \"&#\" << p->get_code () <<  \";\";\n      else\n        {\n          const std::string str = p->get_string ();\n          for (const auto& q : str)\n            {\n              std::stringstream chr;\n              chr << q;\n              if (chr.str () == \"\\\"\")\n                os << \"&quot;\";\n              else if (chr.str () == \"'\")\n                os << \"&apos;\";\n              else if (chr.str () == \"&\")\n                os << \"&amp;\";\n              else if (chr.str () == \"<\")\n                os << \"&lt;\";\n              else if (chr.str () == \">\")\n                os << \"&gt;\";\n              else\n                os << chr.str ();\n            }\n        }\n      os << \"</text>\";\n    }\n  os << \"</g>\";\n\n  return os.str ();\n}\n\nstd::string\ngl2ps_renderer::strlist_to_ps (double x, double y, double z,\n                               Matrix box, double rotation,\n                               std::list<text_renderer::string>& lst)\n{\n  if (lst.empty ())\n    return \"\";\n  else if (lst.size () == 1)\n    {\n      static bool warned = false;\n      // This may be an svg image, not handled in native eps format.\n      if (! lst.front ().get_svg_element ().empty ())\n        {\n          if (! warned)\n            {\n              warned = true;\n              warning_with_id (\"Octave:print:unhandled-svg-content\",\n                               \"print: unhandled LaTeX strings.  \"\n                               \"Use -svgconvert option or -d*latex* output \"\n                               \"device.\");\n            }\n          return \"\";\n        }\n    }\n\n  // Translate and rotate coordinates in order to use bottom-left alignment\n  fix_strlist_position (x, y, z, box, rotation, lst);\n  Matrix prev_color (1, 3, -1);\n\n  std::ostringstream ss;\n  ss << \"gsave\\n\";\n\n  static bool warned = false;\n\n  for (const auto& txtobj : lst)\n    {\n      // Color\n      if (txtobj.get_color () != prev_color)\n        {\n          prev_color = txtobj.get_color ();\n          for (int i = 0; i < 3; i++)\n            ss << prev_color(i) << \" \";\n\n          ss << \"C\\n\";\n        }\n\n      // String\n      std::string str;\n      if (txtobj.get_code ())\n        {\n          m_fontname = \"Symbol\";\n          str = code_to_symbol (txtobj.get_code ());\n        }\n      else\n        {\n          m_fontname = select_font (txtobj.get_name (),\n                                    txtobj.get_weight () == \"bold\",\n                                    txtobj.get_angle () == \"italic\");\n\n          // Check that the string is composed of single byte characters\n          const std::string tmpstr = txtobj.get_string ();\n          const uint8_t *c\n            = reinterpret_cast<const uint8_t *> (tmpstr.c_str ());\n\n          for (std::size_t i = 0; i < tmpstr.size ();)\n            {\n              int mblen = octave_u8_strmblen_wrapper (c + i);\n\n              // Replace multibyte or non ascii characters by a question mark\n              if (mblen > 1)\n                {\n                  str += \"?\";\n                  if (! warned)\n                    {\n                      warning_with_id (\"Octave:print:unsupported-multibyte\",\n                                       \"print: only ASCII characters are \"\n                                       \"supported for EPS and derived \"\n                                       \"formats.  Use the '-svgconvert' \"\n                                       \"option for better font support.\");\n                      warned = true;\n                    }\n                }\n              else if (mblen < 1)\n                {\n                  mblen = 1;\n                  str += \"?\";\n                  if (! warned)\n                    {\n                      warning_with_id (\"Octave:print:unhandled-character\",\n                                       \"print: only ASCII characters are \"\n                                       \"supported for EPS and derived \"\n                                       \"formats.  Use the '-svgconvert' \"\n                                       \"option for better font support.\");\n                      warned = true;\n                    }\n                }\n              else\n                str += tmpstr.at (i);\n\n              i += mblen;\n            }\n        }\n\n      escape_character (\"\\\\\", str);\n      escape_character (\"(\", str);\n      escape_character (\")\", str);\n\n      ss << \"(\" << str << \") [\";\n\n      std::vector<double> xdata = txtobj.get_xdata ();\n      for (std::size_t i = 1; i < xdata.size (); i++)\n        ss << xdata[i] - xdata[i-1] << \" \";\n\n      ss << \"10] \" << rotation << \" \" << txtobj.get_x ()\n         << \" \" << txtobj.get_y () << \" \" << txtobj.get_size ()\n         << \" /\" << m_fontname << \" SRX\\n\";\n    }\n\n  ss << \"grestore\\n\";\n\n  return ss.str ();\n}\n\nMatrix\ngl2ps_renderer::render_text (const std::string& txt,\n                             double x, double y, double z,\n                             int ha, int va, double rotation)\n{\n  std::string saved_font = m_fontname;\n\n  if (txt.empty ())\n    return Matrix (1, 4, 0.0);\n\n  Matrix bbox;\n  std::string str = txt;\n  std::list<text_renderer::string> lst;\n\n  text_to_strlist (str, lst, bbox, ha, va, rotation);\n  m_glfcns.glRasterPos3d (x, y, z);\n\n  // For svg/eps directly dump a preformated text element into gl2ps output\n  if (m_term.find (\"svg\") != std::string::npos)\n    {\n      std::string elt = strlist_to_svg (x, y, z, bbox, rotation, lst);\n      if (! elt.empty ())\n        gl2psSpecial (GL2PS_SVG, elt.c_str ());\n    }\n  else if (m_term.find (\"eps\") != std::string::npos)\n    {\n      std::string elt = strlist_to_ps (x, y, z, bbox, rotation, lst);\n      if (! elt.empty ())\n        gl2psSpecial (GL2PS_EPS, elt.c_str ());\n\n    }\n  else\n    gl2psTextOpt (str.c_str (), m_fontname.c_str (), m_fontsize,\n                  alignment_to_mode (ha, va), rotation);\n\n  m_fontname = saved_font;\n\n  return bbox;\n}\n\nvoid\ngl2ps_renderer::set_font (const base_properties& props)\n{\n  opengl_renderer::set_font (props);\n\n  // Set the interpreter so that text_to_pixels can parse strings properly\n  if (props.has_property (\"interpreter\"))\n    set_interpreter (props.get (\"interpreter\").string_value ());\n\n  m_fontsize = props.get (\"__fontsize_points__\").double_value ();\n\n  caseless_str fn = props.get (\"fontname\").xtolower ().string_value ();\n  bool isbold\n    =(props.get (\"fontweight\").xtolower ().string_value () == \"bold\");\n  bool isitalic\n    = (props.get (\"fontangle\").xtolower ().string_value () == \"italic\");\n\n  m_fontname = select_font (fn, isbold, isitalic);\n}\n\nvoid\ngl2ps_renderer::draw_image (const image::properties& props)\n{\n  octave_value cdata = props.get_color_data ();\n  const dim_vector& dv = cdata.dims ();\n  int h = dv(0);\n  int w = dv(1);\n\n  Matrix x = props.get_xdata ().matrix_value ();\n  Matrix y = props.get_ydata ().matrix_value ();\n\n  // Someone wants us to draw an empty image?  No way.\n  if (x.isempty () || y.isempty ())\n    return;\n\n  // Sort x/ydata and mark flipped dimensions\n  bool xflip = false;\n  if (x(0) > x(1))\n    {\n      std::swap (x(0), x(1));\n      xflip = true;\n    }\n  else if (w > 1 && x(1) == x(0))\n    x(1) = x(1) + (w-1);\n\n  bool yflip = false;\n  if (y(0) > y(1))\n    {\n      std::swap (y(0), y(1));\n      yflip = true;\n    }\n  else if (h > 1 && y(1) == y(0))\n    y(1) = y(1) + (h-1);\n\n\n  const ColumnVector p0 = m_xform.transform (x(0), y(0), 0);\n  const ColumnVector p1 = m_xform.transform (x(1), y(1), 0);\n\n  if (math::isnan (p0(0)) || math::isnan (p0(1))\n      || math::isnan (p1(0)) || math::isnan (p1(1)))\n    {\n      warning (\"opengl_renderer: image X,Y data too large to draw\");\n      return;\n    }\n\n  // image pixel size in screen pixel units\n  float pix_dx, pix_dy;\n  // image pixel size in normalized units\n  float nor_dx, nor_dy;\n\n  if (w > 1)\n    {\n      pix_dx = (p1(0) - p0(0)) / (w-1);\n      nor_dx = (x(1) - x(0)) / (w-1);\n    }\n  else\n    {\n      const ColumnVector p1w = m_xform.transform (x(1) + 1, y(1), 0);\n      pix_dx = p1w(0) - p0(0);\n      nor_dx = 1;\n    }\n\n  if (h > 1)\n    {\n      pix_dy = (p1(1) - p0(1)) / (h-1);\n      nor_dy = (y(1) - y(0)) / (h-1);\n    }\n  else\n    {\n      const ColumnVector p1h = m_xform.transform (x(1), y(1) + 1, 0);\n      pix_dy = p1h(1) - p0(1);\n      nor_dy = 1;\n    }\n\n  // OpenGL won't draw any of the image if its origin is outside the\n  // viewport/clipping plane so we must do the clipping ourselves.\n\n  int j0, j1, jj, i0, i1, ii;\n  j0 = 0, j1 = w;\n  i0 = 0, i1 = h;\n\n  float im_xmin = x(0) - nor_dx/2;\n  float im_xmax = x(1) + nor_dx/2;\n  float im_ymin = y(0) - nor_dy/2;\n  float im_ymax = y(1) + nor_dy/2;\n\n  // Clip to axes or viewport\n  bool do_clip = props.is_clipping ();\n  Matrix vp = get_viewport_scaled ();\n\n  ColumnVector vp_lim_min\n    = m_xform.untransform (std::numeric_limits<float>::epsilon (),\n                           std::numeric_limits<float>::epsilon ());\n  ColumnVector vp_lim_max = m_xform.untransform (vp(2), vp(3));\n\n  if (vp_lim_min(0) > vp_lim_max(0))\n    std::swap (vp_lim_min(0), vp_lim_max(0));\n\n  if (vp_lim_min(1) > vp_lim_max(1))\n    std::swap (vp_lim_min(1), vp_lim_max(1));\n\n  float clip_xmin\n    = do_clip ? (vp_lim_min(0) > m_xmin ? vp_lim_min(0) : m_xmin)\n      : vp_lim_min(0);\n\n  float clip_ymin\n    = do_clip ? (vp_lim_min(1) > m_ymin ? vp_lim_min(1) : m_ymin)\n      : vp_lim_min(1);\n\n  float clip_xmax\n    = do_clip ? (vp_lim_max(0) < m_xmax ? vp_lim_max(0) : m_xmax)\n      : vp_lim_max(0);\n\n  float clip_ymax\n    = do_clip ? (vp_lim_max(1) < m_ymax ? vp_lim_max(1) : m_ymax)\n      : vp_lim_max(1);\n\n  if (im_xmin < clip_xmin)\n    j0 += (clip_xmin - im_xmin)/nor_dx + 1;\n\n  if (im_xmax > clip_xmax)\n    j1 -= (im_xmax - clip_xmax)/nor_dx;\n\n  if (im_ymin < clip_ymin)\n    i0 += (clip_ymin - im_ymin)/nor_dy + 1;\n\n  if (im_ymax > clip_ymax)\n    i1 -= (im_ymax - clip_ymax)/nor_dy;\n\n  if (i0 >= i1 || j0 >= j1)\n    return;\n\n  float zoom_x;\n  m_glfcns.glGetFloatv (GL_ZOOM_X, &zoom_x);\n  float zoom_y;\n  m_glfcns.glGetFloatv (GL_ZOOM_Y, &zoom_y);\n\n  m_glfcns.glPixelZoom (m_devpixratio * pix_dx, - m_devpixratio * pix_dy);\n  m_glfcns.glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);\n\n  // Expect RGB data\n  if (dv.ndims () == 3 && dv(2) == 3)\n    {\n      if (cdata.is_double_type ())\n        {\n          const NDArray xcdata = cdata.array_value ();\n\n          OCTAVE_LOCAL_BUFFER (GLfloat, a,\n                               static_cast<size_t> (3)*(j1-j0)*(i1-i0));\n\n          for (int i = i0; i < i1; i++)\n            {\n              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)\n                {\n                  if (! yflip)\n                    ii = i;\n                  else\n                    ii = h - i - 1;\n\n                  if (! xflip)\n                    jj = j;\n                  else\n                    jj = w - j - 1;\n\n                  a[idx]   = xcdata(ii, jj, 0);\n                  a[idx+1] = xcdata(ii, jj, 1);\n                  a[idx+2] = xcdata(ii, jj, 2);\n                }\n            }\n\n          draw_pixels (j1-j0, i1-i0, a);\n\n        }\n      else if (cdata.is_single_type ())\n        {\n          const FloatNDArray xcdata = cdata.float_array_value ();\n\n          OCTAVE_LOCAL_BUFFER (GLfloat, a,\n                               static_cast<size_t> (3)*(j1-j0)*(i1-i0));\n\n          for (int i = i0; i < i1; i++)\n            {\n              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)\n                {\n                  if (! yflip)\n                    ii = i;\n                  else\n                    ii = h - i - 1;\n\n                  if (! xflip)\n                    jj = j;\n                  else\n                    jj = w - j - 1;\n\n                  a[idx]   = xcdata(ii, jj, 0);\n                  a[idx+1] = xcdata(ii, jj, 1);\n                  a[idx+2] = xcdata(ii, jj, 2);\n                }\n            }\n\n          draw_pixels (j1-j0, i1-i0, a);\n\n        }\n      else if (cdata.is_uint8_type ())\n        {\n          const uint8NDArray xcdata = cdata.uint8_array_value ();\n\n          OCTAVE_LOCAL_BUFFER (GLubyte, a,\n                               static_cast<size_t> (3)*(j1-j0)*(i1-i0));\n\n          for (int i = i0; i < i1; i++)\n            {\n              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)\n                {\n                  if (! yflip)\n                    ii = i;\n                  else\n                    ii = h - i - 1;\n\n                  if (! xflip)\n                    jj = j;\n                  else\n                    jj = w - j - 1;\n\n                  a[idx]   = xcdata(ii, jj, 0);\n                  a[idx+1] = xcdata(ii, jj, 1);\n                  a[idx+2] = xcdata(ii, jj, 2);\n                }\n            }\n\n          draw_pixels (j1-j0, i1-i0, a);\n\n        }\n      else if (cdata.is_uint16_type ())\n        {\n          const uint16NDArray xcdata = cdata.uint16_array_value ();\n\n          OCTAVE_LOCAL_BUFFER (GLushort, a,\n                               static_cast<size_t> (3)*(j1-j0)*(i1-i0));\n\n          for (int i = i0; i < i1; i++)\n            {\n              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)\n                {\n                  if (! yflip)\n                    ii = i;\n                  else\n                    ii = h - i - 1;\n\n                  if (! xflip)\n                    jj = j;\n                  else\n                    jj = w - j - 1;\n\n                  a[idx]   = xcdata(ii, jj, 0);\n                  a[idx+1] = xcdata(ii, jj, 1);\n                  a[idx+2] = xcdata(ii, jj, 2);\n                }\n            }\n\n          draw_pixels (j1-j0, i1-i0, a);\n\n        }\n      else\n        warning (\"opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)\");\n\n      m_glfcns.glPixelZoom (zoom_x, zoom_y);\n\n    }\n}\n\nvoid\ngl2ps_renderer::draw_pixels (int w, int h, const float *data)\n{\n  // Clip data between 0 and 1 for float values\n  OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast<size_t> (3)*w*h);\n\n  for (int i = 0; i < 3*h*w; i++)\n    tmp_data[i] = (data[i] < 0.0f ? 0.0f : (data[i] > 1.0f ? 1.0f : data[i]));\n\n  gl2psDrawPixels (w, h, 0, 0, GL_RGB, GL_FLOAT, tmp_data);\n}\n\nvoid\ngl2ps_renderer::draw_pixels (int w, int h, const uint8_t *data)\n{\n  // gl2psDrawPixels only supports the GL_FLOAT type.\n\n  OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast<size_t> (3)*w*h);\n\n  static constexpr float MAXVAL = std::numeric_limits<uint8_t>::max ();\n\n  for (int i = 0; i < 3*w*h; i++)\n    tmp_data[i] = data[i] / MAXVAL;\n\n  draw_pixels (w, h, tmp_data);\n}\n\nvoid\ngl2ps_renderer::draw_pixels (int w, int h, const uint16_t *data)\n{\n  // gl2psDrawPixels only supports the GL_FLOAT type.\n\n  OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast<size_t> (3)*w*h);\n\n  static constexpr float MAXVAL = std::numeric_limits<uint16_t>::max ();\n\n  for (int i = 0; i < 3*w*h; i++)\n    tmp_data[i] = data[i] / MAXVAL;\n\n  draw_pixels (w, h, tmp_data);\n}\n\nvoid\ngl2ps_renderer::draw_text (const text::properties& props)\n{\n  if (props.get_string ().isempty ())\n    return;\n\n  draw_text_background (props, true);\n\n  // First set font properties: freetype will use them to compute\n  // coordinates and gl2ps will retrieve the color directly from the\n  // feedback buffer\n  set_font (props);\n  set_color (props.get_color_rgb ());\n\n  std::string saved_font = m_fontname;\n\n  // Alignment\n  int halign = 0;\n  int valign = 0;\n\n  if (props.horizontalalignment_is (\"center\"))\n    halign = 1;\n  else if (props.horizontalalignment_is (\"right\"))\n    halign = 2;\n\n  if (props.verticalalignment_is (\"top\"))\n    valign = 2;\n  else if (props.verticalalignment_is (\"baseline\"))\n    valign = 3;\n  else if (props.verticalalignment_is (\"middle\"))\n    valign = 1;\n\n  // FIXME: handle margin and surrounding box\n  // Matrix bbox;\n\n  const Matrix pos = get_transform ().scale (props.get_data_position ());\n  std::string str = props.get_string ().string_vector_value ().join (\"\\n\");\n\n  render_text (str, pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0,\n               halign, valign, props.get_rotation ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// If the name of the stream begins with '|', open a pipe to the command\n// named by the rest of the string.  Otherwise, write to the named file.\n\nvoid\ngl2ps_print (opengl_functions& glfcns, const graphics_object& fig,\n             const std::string& stream, const std::string& term)\n{\n#if defined (HAVE_GL2PS_H) && defined (HAVE_OPENGL)\n\n  // FIXME: should we have a way to create a file that begins with the\n  // character '|'?\n\n  bool have_cmd = stream.length () > 1 && stream[0] == '|';\n\n  FILE *m_fp = nullptr;\n\n  unwind_protect frame;\n\n  if (have_cmd)\n    {\n      // Create process and pipe gl2ps output to it.\n\n      std::string cmd = stream.substr (1);\n\n      m_fp = popen (cmd.c_str (), \"w\");\n\n      if (! m_fp)\n        error (R\"(print: failed to open pipe \"%s\")\", stream.c_str ());\n\n      // Need octave:: qualifier here to avoid ambiguity.\n      frame.add ([m_fp] () { octave::pclose (m_fp); });\n    }\n  else\n    {\n      // Write gl2ps output directly to file.\n\n      m_fp = sys::fopen (stream.c_str (), \"w\");\n\n      if (! m_fp)\n        error (R\"(gl2ps_print: failed to create file \"%s\")\", stream.c_str ());\n\n      frame.add ([m_fp] () { std::fclose (m_fp); });\n    }\n\n  gl2ps_renderer rend (glfcns, m_fp, term);\n\n  Matrix pos = fig.get (\"position\").matrix_value ();\n  rend.set_viewport (pos(2), pos(3));\n  rend.draw (fig, stream);\n\n  // Make sure buffered commands are finished!!!\n  rend.finish ();\n\n#else\n\n  octave_unused_parameter (glfcns);\n  octave_unused_parameter (fig);\n  octave_unused_parameter (stream);\n  octave_unused_parameter (term);\n\n  err_disabled_feature (\"gl2ps_print\", \"gl2ps\");\n\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/gl2ps-print.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gl2ps_renderer_h)\n#define octave_gl2ps_renderer_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"graphics.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass opengl_functions;\n\nextern OCTINTERP_API void\ngl2ps_print (opengl_functions& glfcns, const graphics_object& fig,\n             const std::string& stream, const std::string& term);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/graphics-handle.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_graphics_handle_h)\n#define octave_graphics_handle_h 1\n\n#include \"octave-config.h\"\n\n#include \"oct-handle.h\"\n\ntypedef octave_handle graphics_handle;\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/graphics-toolkit.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"gh-manager.h\"\n#include \"graphics.h\"\n#include \"gtk-manager.h\"\n#include \"interpreter-private.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\nbase_graphics_toolkit::update (const graphics_handle& h, int id)\n{\n  gh_manager& gh_mgr = __get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  update (go, id);\n}\n\nbool\nbase_graphics_toolkit::initialize (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = __get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  return initialize (go);\n}\n\nvoid\nbase_graphics_toolkit::finalize (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = __get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  finalize (go);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/graphics-toolkit.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_graphics_toolkit_h)\n#define octave_graphics_toolkit_h 1\n\n#include \"octave-config.h\"\n\n#include <map>\n#include <memory>\n#include <string>\n\n#include \"dMatrix.h\"\n\n#include \"Cell.h\"\n#include \"error.h\"\n#include \"graphics-handle.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass graphics_object;\nclass graphics_toolkit;\n\nclass base_graphics_toolkit\n{\npublic:\n\n  friend class graphics_toolkit;\n\npublic:\n\n  base_graphics_toolkit (const std::string& nm)\n    : m_name (nm)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (base_graphics_toolkit)\n\n  virtual ~base_graphics_toolkit () = default;\n\n  std::string get_name () const\n  {\n    return m_name;\n  }\n\n  virtual bool is_valid () const\n  {\n    return false;\n  }\n\n  virtual void redraw_figure (const graphics_object&) const\n  {\n    gripe_if_tkit_invalid (\"redraw_figure\");\n  }\n\n  virtual void show_figure (const graphics_object&) const\n  {\n    gripe_if_tkit_invalid (\"show_figure\");\n  }\n\n  virtual void print_figure (const graphics_object&, const std::string&,\n                             const std::string&,\n                             const std::string& = \"\") const\n  {\n    gripe_if_tkit_invalid (\"print_figure\");\n  }\n\n  virtual uint8NDArray get_pixels (const graphics_object&) const\n  {\n    gripe_if_tkit_invalid (\"get_pixels\");\n    return uint8NDArray ();\n  }\n\n  virtual Matrix get_canvas_size (const graphics_handle&) const\n  {\n    gripe_if_tkit_invalid (\"get_canvas_size\");\n    return Matrix (1, 2, 0.0);\n  }\n\n  virtual double get_screen_resolution () const\n  {\n    gripe_if_tkit_invalid (\"get_screen_resolution\");\n    return 72.0;\n  }\n\n  virtual Matrix get_screen_size () const\n  {\n    gripe_if_tkit_invalid (\"get_screen_size\");\n    return Matrix (1, 2, 0.0);\n  }\n\n  virtual Matrix get_text_extent (const graphics_object&) const\n  {\n    gripe_if_tkit_invalid (\"get_text_extent\");\n    return Matrix ();\n  }\n\n  // Callback function executed when the given graphics object\n  // changes.  This allows the graphics toolkit to act on property\n  // changes if needed.\n  virtual void update (const graphics_object&, int)\n  {\n    gripe_if_tkit_invalid (\"base_graphics_toolkit::update\");\n  }\n\n  void update (const graphics_handle&, int);\n\n  // Callback function executed when the given graphics object is\n  // created.  This allows the graphics toolkit to do toolkit-specific\n  // initializations for a newly created object.\n  virtual bool initialize (const graphics_object&)\n  {\n    gripe_if_tkit_invalid (\"base_graphics_toolkit::initialize\");\n    return false;\n  }\n\n  bool initialize (const graphics_handle&);\n\n  // Callback function executed just prior to deleting the given\n  // graphics object.  This allows the graphics toolkit to perform\n  // toolkit-specific cleanup operations before an object is deleted.\n  virtual void finalize (const graphics_object&)\n  {\n    gripe_if_tkit_invalid (\"base_graphics_toolkit::finalize\");\n  }\n\n  void finalize (const graphics_handle&);\n\n  // Close the graphics toolkit.\n  virtual void close ()\n  {\n    gripe_if_tkit_invalid (\"base_graphics_toolkit::close\");\n  }\n\nprivate:\n\n  std::string m_name;\n\nprivate:\n\n  void gripe_if_tkit_invalid (const std::string& fname) const\n  {\n    if (! is_valid ())\n      error (\"%s: invalid graphics toolkit\", fname.c_str ());\n  }\n};\n\nclass graphics_toolkit\n{\npublic:\n  graphics_toolkit (const std::string& name = \"unknown\")\n    : m_rep (new base_graphics_toolkit (name))\n  { }\n\n  // NEW_REP must be dynamically allocated.\n  graphics_toolkit (base_graphics_toolkit *new_rep)\n    : m_rep (std::shared_ptr<base_graphics_toolkit> (new_rep))\n  {\n    if (! m_rep)\n      error (\"invalid graphics_toolkit!\");\n  }\n\n  graphics_toolkit (const graphics_toolkit& b) = default;\n\n  graphics_toolkit& operator = (const graphics_toolkit& b) = default;\n\n  ~graphics_toolkit () = default;\n\n  operator bool () const\n  {\n    return m_rep->is_valid ();\n  }\n\n  std::string get_name () const\n  {\n    return m_rep->get_name ();\n  }\n\n  void redraw_figure (const graphics_object& go) const\n  {\n    m_rep->redraw_figure (go);\n  }\n\n  void show_figure (const graphics_object& go) const\n  {\n    m_rep->show_figure (go);\n  }\n\n  void print_figure (const graphics_object& go, const std::string& term,\n                     const std::string& file,\n                     const std::string& debug_file = \"\") const\n  {\n    m_rep->print_figure (go, term, file, debug_file);\n  }\n\n  uint8NDArray get_pixels (const graphics_object& go) const\n  {\n    return m_rep->get_pixels (go);\n  }\n\n  Matrix get_canvas_size (const graphics_handle& fh) const\n  {\n    return m_rep->get_canvas_size (fh);\n  }\n\n  double get_screen_resolution () const\n  {\n    return m_rep->get_screen_resolution ();\n  }\n\n  Matrix get_screen_size () const\n  {\n    return m_rep->get_screen_size ();\n  }\n\n  Matrix get_text_extent (const graphics_object& go) const\n  {\n    return m_rep->get_text_extent (go);\n  }\n\n  // Notifies graphics toolkit that object't property has changed.\n  void update (const graphics_object& go, int id)\n  {\n    m_rep->update (go, id);\n  }\n\n  void update (const graphics_handle& h, int id)\n  {\n    m_rep->update (h, id);\n  }\n\n  // Notifies graphics toolkit that new object was created.\n  bool initialize (const graphics_object& go)\n  {\n    return m_rep->initialize (go);\n  }\n\n  bool initialize (const graphics_handle& h)\n  {\n    return m_rep->initialize (h);\n  }\n\n  // Notifies graphics toolkit that object was destroyed.\n  // This is called only for explicitly deleted object.\n  // Children are deleted implicitly and graphics toolkit isn't notified.\n  void finalize (const graphics_object& go)\n  {\n    m_rep->finalize (go);\n  }\n\n  void finalize (const graphics_handle& h)\n  {\n    m_rep->finalize (h);\n  }\n\n  // Close the graphics toolkit.\n  void close ()\n  {\n    m_rep->close ();\n  }\n\nprivate:\n\n  std::shared_ptr<base_graphics_toolkit> m_rep;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/graphics-utils.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"caseless-str.h\"\n\n#include \"gh-manager.h\"\n#include \"graphics-utils.h\"\n#include \"graphics.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Flag to stop redraws due to callbacks while deletion is in progress.\nbool delete_executing = false;\n\nvoid\nxset (const graphics_handle& h, const caseless_str& pname,\n      const octave_value& val)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  go.set (pname, val);\n}\n\nvoid\nxset (const graphics_handle& h, const octave_value_list& args)\n{\n  if (args.length () > 0)\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go = gh_mgr.get_object (h);\n\n      go.set (args);\n    }\n}\n\noctave_value\nxget (const graphics_handle& h, const caseless_str& pname)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  return go.get (pname);\n}\n\nbool\nisfigure (double val)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (val);\n\n  return go && go.isa (\"figure\");\n}\n\ngraphics_handle\nreparent (const octave_value& ov, const std::string& who,\n          const std::string& pname, const graphics_handle& new_parent,\n          bool adopt)\n{\n  double hv = ov.xdouble_value (\"%s: %s must be a graphics handle\",\n                                who.c_str (), pname.c_str ());\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_handle h = gh_mgr.lookup (hv);\n\n  if (! h.ok ())\n    error (\"%s: invalid graphics handle (= %g) for %s\",\n           who.c_str (), hv, pname.c_str ());\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  graphics_handle parent_h = go.get_parent ();\n\n  graphics_object parent_go = gh_mgr.get_object (parent_h);\n\n  parent_go.remove_child (h);\n\n  if (adopt)\n    go.set (\"parent\", new_parent.value ());\n  else\n    go.reparent (new_parent);\n\n  return h;\n}\n\nvoid\ndelete_graphics_object (const graphics_handle& h, bool from_root)\n{\n  if (h.ok ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go = gh_mgr.get_object (h);\n\n      // Don't do recursive deleting, due to callbacks\n      if (! go.get_properties ().is_beingdeleted ())\n        {\n          // NOTE: Freeing the handle also calls any deletefcn.  It also calls\n          //       the parent's delete_child function.\n\n          gh_mgr.free (h, from_root || go.isa (\"figure\"));\n\n          Vdrawnow_requested = true;\n        }\n    }\n}\n\nvoid\ndelete_graphics_object (double val, bool from_root)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  delete_graphics_object (gh_mgr.lookup (val), from_root || isfigure (val));\n}\n\nvoid\ndelete_graphics_objects (const NDArray vals, bool from_root)\n{\n  // Prevent redraw of partially deleted objects.\n  octave::unwind_protect_var<bool> restore_var (delete_executing, true);\n\n  for (octave_idx_type i = 0; i < vals.numel (); i++)\n    delete_graphics_object (vals.elem (i), from_root);\n}\n\nvoid\nclose_figure (const graphics_handle& h)\n{\n  octave_value closerequestfcn = xget (h, \"closerequestfcn\");\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  gh_mgr.execute_callback (h, closerequestfcn);\n}\n\nvoid\nforce_close_figure (const graphics_handle& h)\n{\n  // Remove the deletefcn and closerequestfcn callbacks\n  // and delete the object directly.\n\n  xset (h, \"deletefcn\", Matrix ());\n  xset (h, \"closerequestfcn\", Matrix ());\n\n  delete_graphics_object (h, true);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/graphics-utils.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_graphics_utils_h)\n#define octave_graphics_utils_h 1\n\n// The functions defined here are private and should not be exported.\n// This header file should not be installed.\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"graphics-handle.h\"\n\nclass caseless_str;\nclass octave_value;\nclass NDArray;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Flag to stop redraws due to callbacks while deletion is in progress.\nextern bool delete_executing;\n\nextern void xset (const graphics_handle& h, const caseless_str& pname,\n                  const octave_value& val);\n\nextern void xset (const graphics_handle& h, const octave_value_list& args);\n\nextern octave_value xget (const graphics_handle& h, const caseless_str& pname);\n\nextern bool isfigure (double val);\n\nextern graphics_handle\nreparent (const octave_value& ov, const std::string& who,\n          const std::string& pname, const graphics_handle& new_parent,\n          bool adopt = true);\n\nextern void\ndelete_graphics_object (const graphics_handle& h, bool from_root = false);\n\nextern void delete_graphics_object (double val, bool from_root = false);\n\nextern void\ndelete_graphics_objects (const NDArray vals, bool from_root = false);\n\nextern void close_figure (const graphics_handle& h);\n\nextern void force_close_figure (const graphics_handle& h);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/graphics.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cctype>\n#include <cmath>\n#include <cstdint>\n#include <cstdlib>\n\n#include <algorithm>\n#include <array>\n#include <iostream>\n#include <limits>\n#include <list>\n#include <map>\n#include <set>\n#include <string>\n#include <sstream>\n\n#include \"cmd-edit.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sysdep.h\"\n#include \"oct-time.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"display.h\"\n#include \"error.h\"\n#include \"gh-manager.h\"\n#include \"graphics-utils.h\"\n#include \"graphics.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"oct-map.h\"\n#include \"ov-fcn-handle.h\"\n#include \"pager.h\"\n#include \"text-engine.h\"\n#include \"text-renderer.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"octave-default-image.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_NORETURN static\nvoid\nerr_set_invalid (const std::string& pname)\n{\n  error (\"set: invalid value for %s property\", pname.c_str ());\n}\n\n// Check to see that PNAME matches just one of PNAMES uniquely.\n// Return the full name of the match, or an empty caseless_str object\n// if there is no match, or the match is ambiguous.\n\nstatic caseless_str\nvalidate_property_name (const std::string& who, const std::string& what,\n                        const std::set<std::string>& pnames,\n                        const caseless_str& pname)\n{\n  std::size_t len = pname.length ();\n  std::set<std::string> matches;\n\n  // Find exact or partial matches to property name\n  for (const auto& propnm : pnames)\n    {\n      if (pname.compare (propnm, len))\n        {\n          if (len == propnm.length ())\n            return pname;  // Exact match.\n\n          matches.insert (propnm);\n        }\n    }\n\n  std::size_t num_matches = matches.size ();\n\n  if (num_matches == 0)\n    error (\"%s: unknown %s property %s\",\n           who.c_str (), what.c_str (), pname.c_str ());\n  else if (num_matches > 1)\n    {\n      string_vector sv (matches);\n\n      std::ostringstream os;\n      const int width = command_editor::terminal_cols ();\n\n      sv.list_in_columns (os, width);\n\n      std::string match_list = os.str ();\n\n      error (\"%s: ambiguous %s property name %s; possible matches:\\n\\n%s\",\n             who.c_str (), what.c_str (), pname.c_str (), match_list.c_str ());\n    }\n  else  // num_matches == 1\n    {\n      // Exact match was handled above.\n      std::string possible_match = *(matches.begin ());\n\n      warning_with_id (\"Octave:abbreviated-property-match\",\n                       \"%s: allowing %s to match %s property %s\",\n                       who.c_str (), pname.c_str (), what.c_str (),\n                       possible_match.c_str ());\n\n      return possible_match;\n    }\n\n  return caseless_str ();\n}\n\nstatic Matrix\nviridis_colormap ()\n{\n  // The values below have been produced by \"viridis ()(:)\".\n  // It would be nice to be able to feval the viridis function but since there\n  // is a static property object that includes a colormap_property object, we\n  // need to initialize this before main() is even called, so calling an\n  // interpreted function is not possible.\n\n  const double cmapv[] =\n  {\n    0.26700401, 0.26851048, 0.26994384,\n    0.27130489, 0.27259384, 0.27380934,\n    0.27495242, 0.27602238, 0.27701840,\n    0.27794143, 0.27879067, 0.27956550,\n    0.28026658, 0.28089358, 0.28144581,\n    0.28192358, 0.28232739, 0.28265633,\n    0.28291049, 0.28309095, 0.28319704,\n    0.28322882, 0.28318684, 0.28307200,\n    0.28288389, 0.28262297, 0.28229037,\n    0.28188676, 0.28141228, 0.28086773,\n    0.28025468, 0.27957399, 0.27882618,\n    0.27801236, 0.27713437, 0.27619376,\n    0.27519116, 0.27412802, 0.27300596,\n    0.27182812, 0.27059473, 0.26930756,\n    0.26796846, 0.26657984, 0.26514450,\n    0.26366320, 0.26213801, 0.26057103,\n    0.25896451, 0.25732244, 0.25564519,\n    0.25393498, 0.25219404, 0.25042462,\n    0.24862899, 0.24681140, 0.24497208,\n    0.24311324, 0.24123708, 0.23934575,\n    0.23744138, 0.23552606, 0.23360277,\n    0.23167350, 0.22973926, 0.22780192,\n    0.22586330, 0.22392515, 0.22198915,\n    0.22005691, 0.21812995, 0.21620971,\n    0.21429757, 0.21239477, 0.21050310,\n    0.20862342, 0.20675628, 0.20490257,\n    0.20306309, 0.20123854, 0.19942950,\n    0.19763650, 0.19585993, 0.19410009,\n    0.19235719, 0.19063135, 0.18892259,\n    0.18723083, 0.18555593, 0.18389763,\n    0.18225561, 0.18062949, 0.17901879,\n    0.17742298, 0.17584148, 0.17427363,\n    0.17271876, 0.17117615, 0.16964573,\n    0.16812641, 0.16661710, 0.16511703,\n    0.16362543, 0.16214155, 0.16066467,\n    0.15919413, 0.15772933, 0.15626973,\n    0.15481488, 0.15336445, 0.15191820,\n    0.15047605, 0.14903918, 0.14760731,\n    0.14618026, 0.14475863, 0.14334327,\n    0.14193527, 0.14053599, 0.13914708,\n    0.13777048, 0.13640850, 0.13506561,\n    0.13374299, 0.13244401, 0.13117249,\n    0.12993270, 0.12872938, 0.12756771,\n    0.12645338, 0.12539383, 0.12439474,\n    0.12346281, 0.12260562, 0.12183122,\n    0.12114807, 0.12056501, 0.12009154,\n    0.11973756, 0.11951163, 0.11942341,\n    0.11948255, 0.11969858, 0.12008079,\n    0.12063824, 0.12137972, 0.12231244,\n    0.12344358, 0.12477953, 0.12632581,\n    0.12808703, 0.13006688, 0.13226797,\n    0.13469183, 0.13733921, 0.14020991,\n    0.14330291, 0.14661640, 0.15014782,\n    0.15389405, 0.15785146, 0.16201598,\n    0.16638320, 0.17094840, 0.17570671,\n    0.18065314, 0.18578266, 0.19109018,\n    0.19657063, 0.20221902, 0.20803045,\n    0.21400015, 0.22012381, 0.22639690,\n    0.23281498, 0.23937390, 0.24606968,\n    0.25289851, 0.25985676, 0.26694127,\n    0.27414922, 0.28147681, 0.28892102,\n    0.29647899, 0.30414796, 0.31192534,\n    0.31980860, 0.32779580, 0.33588539,\n    0.34407411, 0.35235985, 0.36074053,\n    0.36921420, 0.37777892, 0.38643282,\n    0.39517408, 0.40400101, 0.41291350,\n    0.42190813, 0.43098317, 0.44013691,\n    0.44936763, 0.45867362, 0.46805314,\n    0.47750446, 0.48702580, 0.49661536,\n    0.50627130, 0.51599182, 0.52577622,\n    0.53562110, 0.54552440, 0.55548397,\n    0.56549760, 0.57556297, 0.58567772,\n    0.59583934, 0.60604528, 0.61629283,\n    0.62657923, 0.63690157, 0.64725685,\n    0.65764197, 0.66805369, 0.67848868,\n    0.68894351, 0.69941463, 0.70989842,\n    0.72039115, 0.73088902, 0.74138803,\n    0.75188414, 0.76237342, 0.77285183,\n    0.78331535, 0.79375994, 0.80418159,\n    0.81457634, 0.82494028, 0.83526959,\n    0.84556056, 0.85580960, 0.86601325,\n    0.87616824, 0.88627146, 0.89632002,\n    0.90631121, 0.91624212, 0.92610579,\n    0.93590444, 0.94563626, 0.95529972,\n    0.96489353, 0.97441665, 0.98386829,\n    0.99324789, 0.00487433, 0.00960483,\n    0.01462494, 0.01994186, 0.02556309,\n    0.03149748, 0.03775181, 0.04416723,\n    0.05034437, 0.05632444, 0.06214536,\n    0.06783587, 0.07341724, 0.07890703,\n    0.08431970, 0.08966622, 0.09495545,\n    0.10019576, 0.10539345, 0.11055307,\n    0.11567966, 0.12077701, 0.12584799,\n    0.13089477, 0.13592005, 0.14092556,\n    0.14591233, 0.15088147, 0.15583425,\n    0.16077132, 0.16569272, 0.17059884,\n    0.17549020, 0.18036684, 0.18522836,\n    0.19007447, 0.19490540, 0.19972086,\n    0.20452049, 0.20930306, 0.21406899,\n    0.21881782, 0.22354911, 0.22826210,\n    0.23295593, 0.23763078, 0.24228619,\n    0.24692170, 0.25153685, 0.25613040,\n    0.26070284, 0.26525384, 0.26978306,\n    0.27429024, 0.27877509, 0.28323662,\n    0.28767547, 0.29209154, 0.29648471,\n    0.30085494, 0.30520222, 0.30952657,\n    0.31382773, 0.31810580, 0.32236127,\n    0.32659432, 0.33080515, 0.33499400,\n    0.33916114, 0.34330688, 0.34743154,\n    0.35153548, 0.35561907, 0.35968273,\n    0.36372671, 0.36775151, 0.37175775,\n    0.37574589, 0.37971644, 0.38366989,\n    0.38760678, 0.39152762, 0.39543297,\n    0.39932336, 0.40319934, 0.40706148,\n    0.41091033, 0.41474645, 0.41857040,\n    0.42238275, 0.42618405, 0.42997486,\n    0.43375572, 0.43752720, 0.44128981,\n    0.44504410, 0.44879060, 0.45252980,\n    0.45626209, 0.45998802, 0.46370813,\n    0.46742290, 0.47113278, 0.47483821,\n    0.47853961, 0.48223740, 0.48593197,\n    0.48962370, 0.49331293, 0.49700003,\n    0.50068529, 0.50436904, 0.50805136,\n    0.51173263, 0.51541316, 0.51909319,\n    0.52277292, 0.52645254, 0.53013219,\n    0.53381201, 0.53749213, 0.54117264,\n    0.54485335, 0.54853458, 0.55221637,\n    0.55589872, 0.55958162, 0.56326503,\n    0.56694891, 0.57063316, 0.57431754,\n    0.57800205, 0.58168661, 0.58537105,\n    0.58905521, 0.59273889, 0.59642187,\n    0.60010387, 0.60378459, 0.60746388,\n    0.61114146, 0.61481702, 0.61849025,\n    0.62216081, 0.62582833, 0.62949242,\n    0.63315277, 0.63680899, 0.64046069,\n    0.64410744, 0.64774881, 0.65138436,\n    0.65501363, 0.65863619, 0.66225157,\n    0.66585927, 0.66945881, 0.67304968,\n    0.67663139, 0.68020343, 0.68376525,\n    0.68731632, 0.69085611, 0.69438405,\n    0.69789960, 0.70140222, 0.70489133,\n    0.70836635, 0.71182668, 0.71527175,\n    0.71870095, 0.72211371, 0.72550945,\n    0.72888753, 0.73224735, 0.73558828,\n    0.73890972, 0.74221104, 0.74549162,\n    0.74875084, 0.75198807, 0.75520266,\n    0.75839399, 0.76156142, 0.76470433,\n    0.76782207, 0.77091403, 0.77397953,\n    0.77701790, 0.78002855, 0.78301086,\n    0.78596419, 0.78888793, 0.79178146,\n    0.79464415, 0.79747541, 0.80027461,\n    0.80304099, 0.80577412, 0.80847343,\n    0.81113836, 0.81376835, 0.81636288,\n    0.81892143, 0.82144351, 0.82392862,\n    0.82637633, 0.82878621, 0.83115784,\n    0.83349064, 0.83578452, 0.83803918,\n    0.84025437, 0.84242990, 0.84456561,\n    0.84666139, 0.84871722, 0.85073310,\n    0.85270912, 0.85464543, 0.85654226,\n    0.85839991, 0.86021878, 0.86199932,\n    0.86374211, 0.86544779, 0.86711711,\n    0.86875092, 0.87035015, 0.87191584,\n    0.87344918, 0.87495143, 0.87642392,\n    0.87786808, 0.87928545, 0.88067763,\n    0.88204632, 0.88339329, 0.88472036,\n    0.88602943, 0.88732243, 0.88860134,\n    0.88986815, 0.89112487, 0.89237353,\n    0.89361614, 0.89485467, 0.89609127,\n    0.89732977, 0.89857040, 0.89981500,\n    0.90106534, 0.90232311, 0.90358991,\n    0.90486726, 0.90615657, 0.32941519,\n    0.33542652, 0.34137895, 0.34726862,\n    0.35309303, 0.35885256, 0.36454323,\n    0.37016418, 0.37571452, 0.38119074,\n    0.38659204, 0.39191723, 0.39716349,\n    0.40232944, 0.40741404, 0.41241521,\n    0.41733086, 0.42216032, 0.42690202,\n    0.43155375, 0.43611482, 0.44058404,\n    0.44496000, 0.44924127, 0.45342734,\n    0.45751726, 0.46150995, 0.46540474,\n    0.46920128, 0.47289909, 0.47649762,\n    0.47999675, 0.48339654, 0.48669702,\n    0.48989831, 0.49300074, 0.49600488,\n    0.49891131, 0.50172076, 0.50443413,\n    0.50705243, 0.50957678, 0.51200840,\n    0.51434870, 0.51659930, 0.51876163,\n    0.52083736, 0.52282822, 0.52473609,\n    0.52656332, 0.52831152, 0.52998273,\n    0.53157905, 0.53310261, 0.53455561,\n    0.53594093, 0.53726018, 0.53851561,\n    0.53970946, 0.54084398, 0.54192140,\n    0.54294396, 0.54391424, 0.54483444,\n    0.54570633, 0.54653200, 0.54731353,\n    0.54805291, 0.54875211, 0.54941304,\n    0.55003755, 0.55062743, 0.55118440,\n    0.55171011, 0.55220646, 0.55267486,\n    0.55311653, 0.55353282, 0.55392505,\n    0.55429441, 0.55464205, 0.55496905,\n    0.55527637, 0.55556494, 0.55583559,\n    0.55608907, 0.55632606, 0.55654717,\n    0.55675292, 0.55694377, 0.55712010,\n    0.55728221, 0.55743035, 0.55756466,\n    0.55768526, 0.55779216, 0.55788532,\n    0.55796464, 0.55803034, 0.55808199,\n    0.55811913, 0.55814141, 0.55814842,\n    0.55813967, 0.55811466, 0.55807280,\n    0.55801347, 0.55793600, 0.55783967,\n    0.55772371, 0.55758733, 0.55742968,\n    0.55725050, 0.55704861, 0.55682271,\n    0.55657181, 0.55629491, 0.55599097,\n    0.55565893, 0.55529773, 0.55490625,\n    0.55448339, 0.55402906, 0.55354108,\n    0.55301828, 0.55245948, 0.55186354,\n    0.55122927, 0.55055551, 0.54984110,\n    0.54908564, 0.54828740, 0.54744498,\n    0.54655722, 0.54562298, 0.54464114,\n    0.54361058, 0.54253043, 0.54139999,\n    0.54021751, 0.53898192, 0.53769219,\n    0.53634733, 0.53494633, 0.53348834,\n    0.53197275, 0.53039808, 0.52876343,\n    0.52706792, 0.52531069, 0.52349092,\n    0.52160791, 0.51966086, 0.51764880,\n    0.51557101, 0.51342680, 0.51121549,\n    0.50893644, 0.50658890, 0.50417217,\n    0.50168574, 0.49912906, 0.49650163,\n    0.49380294, 0.49103252, 0.48818938,\n    0.48527326, 0.48228395, 0.47922108,\n    0.47608431, 0.47287330, 0.46958774,\n    0.46622638, 0.46278934, 0.45927675,\n    0.45568838, 0.45202405, 0.44828355,\n    0.44446673, 0.44057284, 0.43660090,\n    0.43255207, 0.42842626, 0.42422341,\n    0.41994346, 0.41558638, 0.41115215,\n    0.40664011, 0.40204917, 0.39738103,\n    0.39263579, 0.38781353, 0.38291438,\n    0.37793850, 0.37288606, 0.36775726,\n    0.36255223, 0.35726893, 0.35191009,\n    0.34647607, 0.34096730, 0.33538426,\n    0.32972749, 0.32399761, 0.31819529,\n    0.31232133, 0.30637661, 0.30036211,\n    0.29427888, 0.28812650, 0.28190832,\n    0.27562602, 0.26928147, 0.26287683,\n    0.25641457, 0.24989748, 0.24332878,\n    0.23671214, 0.23005179, 0.22335258,\n    0.21662012, 0.20986086, 0.20308229,\n    0.19629307, 0.18950326, 0.18272455,\n    0.17597055, 0.16925712, 0.16260273,\n    0.15602894, 0.14956101, 0.14322828,\n    0.13706449, 0.13110864, 0.12540538,\n    0.12000532, 0.11496505, 0.11034678,\n    0.10621724, 0.10264590, 0.09970219,\n    0.09745186, 0.09595277, 0.09525046,\n    0.09537439, 0.09633538, 0.09812496,\n    0.10071680, 0.10407067, 0.10813094,\n    0.11283773, 0.11812832, 0.12394051,\n    0.13021494, 0.13689671, 0.14393620,\n  };\n\n  // It would be nice if Matrix had a ctor allowing to do the\n  // following without a copy\n  Matrix cmap (256, 3, 0.0);\n  std::copy (cmapv, cmapv + (256*3), cmap.rwdata ());\n  return cmap;\n}\n\n/*\n## Test default colormap returns a 256-color viridis map\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   assert (get (hax, \"colormap\"), viridis (256));\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n*/\n\nstatic double\ndefault_screendepth ()\n{\n  octave::display_info& dpy_info = octave::__get_display_info__ ();\n\n  return dpy_info.depth ();\n}\n\nstatic Matrix\ndefault_screensize ()\n{\n  Matrix retval (1, 4);\n\n  octave::display_info& dpy_info = octave::__get_display_info__ ();\n\n  retval(0) = 1.0;\n  retval(1) = 1.0;\n  retval(2) = dpy_info.width ();\n  retval(3) = dpy_info.height ();\n\n  return retval;\n}\n\nstatic double\ndefault_screenpixelsperinch ()\n{\n  octave::display_info& dpy_info = octave::__get_display_info__ ();\n\n  return (dpy_info.x_dpi () + dpy_info.y_dpi ()) / 2;\n}\n\nstatic Matrix\ndefault_colororder ()\n{\n  Matrix retval (7, 3, 0.0);\n\n  retval(0, 1) = 0.447;\n  retval(0, 2) = 0.741;\n\n  retval(1, 0) = 0.850;\n  retval(1, 1) = 0.325;\n  retval(1, 2) = 0.098;\n\n  retval(2, 0) = 0.929;\n  retval(2, 1) = 0.694;\n  retval(2, 2) = 0.125;\n\n  retval(3, 0) = 0.494;\n  retval(3, 1) = 0.184;\n  retval(3, 2) = 0.556;\n\n  retval(4, 0) = 0.466;\n  retval(4, 1) = 0.674;\n  retval(4, 2) = 0.188;\n\n  retval(5, 0) = 0.301;\n  retval(5, 1) = 0.745;\n  retval(5, 2) = 0.933;\n\n  retval(6, 0) = 0.635;\n  retval(6, 1) = 0.078;\n  retval(6, 2) = 0.184;\n\n  return retval;\n}\n\nstatic Matrix\ndefault_lim (bool logscale = false)\n{\n  Matrix m (1, 2);\n\n  if (logscale)\n    {\n      m(0) = 0.1;\n      m(1) = 1.0;\n    }\n  else\n    {\n      m(0) = 0.0;\n      m(1) = 1.0;\n    }\n\n  return m;\n}\n\nstatic Matrix\ndefault_data ()\n{\n  Matrix retval (1, 2);\n\n  retval(0) = 0;\n  retval(1) = 1;\n\n  return retval;\n}\n\nstatic Matrix\ndefault_data_lim ()\n{\n  Matrix retval (1, 4);\n\n  retval(0) = 0;\n  retval(1) = 1;\n  retval(2) = 1;  // minimum positive\n  retval(3) = -octave::numeric_limits<double>::Inf (); // maximum negative\n\n  return retval;\n}\n\nstatic Matrix\ndefault_image_cdata ()\n{\n  Matrix m (64, 64);\n\n  int i = 0;\n  for (int col = 0; col < 64; col++)\n    for (int row = 0; row < 64; row++)\n      {\n        m(col, row) = static_cast<double> (default_im_data[i]);\n        i++;\n      }\n\n  return m;\n}\n\nstatic Matrix\ndefault_surface_xdata ()\n{\n  Matrix m (3, 3);\n\n  for (int col = 0; col < 3; col++)\n    for (int row = 0; row < 3; row++)\n      m(row, col) = col+1;\n\n  return m;\n}\n\nstatic Matrix\ndefault_surface_ydata ()\n{\n  Matrix m (3, 3);\n\n  for (int row = 0; row < 3; row++)\n    for (int col = 0; col < 3; col++)\n      m(row, col) = row+1;\n\n  return m;\n}\n\nstatic Matrix\ndefault_surface_zdata ()\n{\n  Matrix m (3, 3, 0.0);\n\n  for (int row = 0; row < 3; row++)\n    m(row, row) = 1.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_surface_cdata ()\n{\n  return default_surface_zdata ();\n}\n\nstatic Matrix\ndefault_patch_faces ()\n{\n  Matrix m (1, 3);\n\n  m(0) = 1.0;\n  m(1) = 2.0;\n  m(2) = 3.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_patch_vertices ()\n{\n  Matrix m (3, 2, 0.0);\n\n  m(1) = 1.0;\n  m(3) = 1.0;\n  m(4) = 1.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_patch_xdata ()\n{\n  Matrix m (3, 1, 0.0);\n\n  m(1) = 1.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_patch_ydata ()\n{\n  Matrix m (3, 1, 1.0);\n\n  m(2) = 0.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_axes_position ()\n{\n  Matrix m (1, 4);\n\n  m(0) = 0.13;\n  m(1) = 0.11;\n  m(2) = 0.775;\n  m(3) = 0.815;\n\n  return m;\n}\n\nstatic Matrix\ndefault_axes_outerposition ()\n{\n  Matrix m (1, 4);\n\n  m(0) = 0.0;\n  m(1) = 0.0;\n  m(2) = 1.0;\n  m(3) = 1.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_axes_view ()\n{\n  Matrix m (1, 2);\n\n  m(0) = 0.0;\n  m(1) = 90.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_axes_tick ()\n{\n  Matrix m (1, 6);\n\n  m(0) = 0.0;\n  m(1) = 0.2;\n  m(2) = 0.4;\n  m(3) = 0.6;\n  m(4) = 0.8;\n  m(5) = 1.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_axes_ticklength ()\n{\n  Matrix m (1, 2);\n\n  m(0) = 0.01;\n  m(1) = 0.025;\n\n  return m;\n}\n\nstatic Matrix\ndefault_figure_position ()\n{\n  Matrix m (1, 4);\n\n  m(0) = 300;\n  m(1) = 200;\n  m(2) = 560;\n  m(3) = 420;\n\n  return m;\n}\n\nstatic Matrix\ndefault_figure_papersize ()\n{\n  Matrix m (1, 2);\n\n  m(0) = 8.5;\n  m(1) = 11.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_figure_paperposition ()\n{\n  Matrix m (1, 4);\n\n  // Update if default_figure_position or default_figure_papersize change\n  m(0) = 1.3421852580027660;\n  m(1) = 3.3191389435020748;\n  m(2) = 5.8156294839944680;\n  m(3) = 4.3617221129958503;\n\n  return m;\n}\n\nstatic std::string\ndefault_graphics_toolkit ()\n{\n  octave::gtk_manager& gtk_mgr = octave::__get_gtk_manager__ ();\n\n  return gtk_mgr.default_toolkit ();\n}\n\nstatic Matrix\ndefault_control_position ()\n{\n  Matrix retval (1, 4);\n\n  retval(0) = 0;\n  retval(1) = 0;\n  retval(2) = 80;\n  retval(3) = 30;\n\n  return retval;\n}\n\nstatic Matrix\ndefault_control_sliderstep ()\n{\n  Matrix retval (1, 2);\n\n  retval(0) = 0.01;\n  retval(1) = 0.1;\n\n  return retval;\n}\n\nstatic Matrix\ndefault_panel_position ()\n{\n  Matrix retval (1, 4);\n\n  retval(0) = 0;\n  retval(1) = 0;\n  retval(2) = 1;\n  retval(3) = 1;\n\n  return retval;\n}\n\nstatic Matrix\ndefault_light_position ()\n{\n  Matrix m (1, 3);\n\n  m(0) = 1.0;\n  m(1) = 0.0;\n  m(2) = 1.0;\n\n  return m;\n}\n\nstatic Matrix\ndefault_table_position ()\n{\n  Matrix retval (1, 4);\n\n  retval(0) = 20;\n  retval(1) = 20;\n  retval(2) = 300;\n  retval(3) = 300;\n\n  return retval;\n}\n\nstatic Matrix\ndefault_table_backgroundcolor ()\n{\n  Matrix retval (2, 3);\n  retval(0, 0) = 1;\n  retval(0, 1) = 1;\n  retval(0, 2) = 1;\n  retval(1, 0) = 0.94;\n  retval(1, 1) = 0.94;\n  retval(1, 2) = 0.94;\n  return retval;\n}\n\nstatic graphics_handle\nmake_graphics_handle (const std::string& go_name,\n                      const graphics_handle& parent,\n                      bool integer_figure_handle = false,\n                      bool call_createfcn = true,\n                      bool notify_toolkit = true)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  return gh_mgr.make_graphics_handle (go_name, parent, integer_figure_handle,\n                                      call_createfcn, notify_toolkit);\n}\n\nstatic double\nconvert_font_size (double font_size, const caseless_str& from_units,\n                   const caseless_str& to_units, double parent_height = 0)\n{\n  // Simple case where from_units == to_units\n\n  if (from_units.compare (to_units))\n    return font_size;\n\n  // Converts the given fontsize using the following transformation:\n  // <old_font_size> => points => <new_font_size>\n\n  double points_size = 0;\n  double res = 0;\n\n  if (from_units.compare (\"points\"))\n    points_size = font_size;\n  else\n    {\n      res = xget (0, \"screenpixelsperinch\").double_value ();\n\n      if (from_units.compare (\"pixels\"))\n        points_size = font_size * 72.0 / res;\n      else if (from_units.compare (\"inches\"))\n        points_size = font_size * 72.0;\n      else if (from_units.compare (\"centimeters\"))\n        points_size = font_size * 72.0 / 2.54;\n      else if (from_units.compare (\"normalized\"))\n        points_size = font_size * parent_height * 72.0 / res;\n    }\n\n  double new_font_size = 0;\n\n  if (to_units.compare (\"points\"))\n    new_font_size = points_size;\n  else\n    {\n      if (res <= 0)\n        res = xget (0, \"screenpixelsperinch\").double_value ();\n\n      if (to_units.compare (\"pixels\"))\n        new_font_size = points_size * res / 72.0;\n      else if (to_units.compare (\"inches\"))\n        new_font_size = points_size / 72.0;\n      else if (to_units.compare (\"centimeters\"))\n        new_font_size = points_size * 2.54 / 72.0;\n      else if (to_units.compare (\"normalized\"))\n        {\n          // Avoid setting font size to (0/0) = NaN\n\n          if (parent_height > 0)\n            new_font_size = points_size * res / (parent_height * 72.0);\n        }\n    }\n\n  return new_font_size;\n}\n\nstatic Matrix\nconvert_position (const Matrix& pos, const caseless_str& from_units,\n                  const caseless_str& to_units, const Matrix& parent_dim)\n{\n  Matrix retval (1, pos.numel (), 0.0);\n  double res = 0;\n  bool is_rectangle = (pos.numel () == 4);\n  bool is_2D = (pos.numel () == 2);\n\n  if (from_units.compare (\"pixels\"))\n    retval = pos;\n  else if (from_units.compare (\"normalized\"))\n    {\n      retval(0) = pos(0) * parent_dim(0) + 1;\n      retval(1) = pos(1) * parent_dim(1) + 1;\n      if (is_rectangle)\n        {\n          retval(2) = pos(2) * parent_dim(0);\n          retval(3) = pos(3) * parent_dim(1);\n        }\n      else if (! is_2D)\n        retval(2) = 0;\n    }\n  else if (from_units.compare (\"characters\"))\n    {\n      if (res <= 0)\n        res = xget (0, \"screenpixelsperinch\").double_value ();\n\n      double f = 0.0;\n\n      // FIXME: this assumes the system font is Helvetica 10pt\n      //        (for which \"x\" requires 6x12 pixels at 74.951 pixels/inch)\n      f = 12.0 * res / 74.951;\n\n      if (f > 0)\n        {\n          retval(0) = 0.5 * pos(0) * f;\n          retval(1) = pos(1) * f;\n          if (is_rectangle)\n            {\n              retval(2) = 0.5 * pos(2) * f;\n              retval(3) = pos(3) * f;\n            }\n          else if (! is_2D)\n            retval(2) = 0;\n        }\n    }\n  else\n    {\n      if (res <= 0)\n        res = xget (0, \"screenpixelsperinch\").double_value ();\n\n      double f = 0.0;\n\n      if (from_units.compare (\"points\"))\n        f = res / 72.0;\n      else if (from_units.compare (\"inches\"))\n        f = res;\n      else if (from_units.compare (\"centimeters\"))\n        f = res / 2.54;\n\n      if (f > 0)\n        {\n          retval(0) = pos(0) * f + 1;\n          retval(1) = pos(1) * f + 1;\n          if (is_rectangle)\n            {\n              retval(2) = pos(2) * f;\n              retval(3) = pos(3) * f;\n            }\n          else if (! is_2D)\n            retval(2) = 0;\n        }\n    }\n\n  if (! to_units.compare (\"pixels\"))\n    {\n      if (to_units.compare (\"normalized\"))\n        {\n          retval(0) = (retval(0) - 1) / parent_dim(0);\n          retval(1) = (retval(1) - 1) / parent_dim(1);\n          if (is_rectangle)\n            {\n              retval(2) /= parent_dim(0);\n              retval(3) /= parent_dim(1);\n            }\n          else if (! is_2D)\n            retval(2) = 0;\n        }\n      else if (to_units.compare (\"characters\"))\n        {\n          if (res <= 0)\n            res = xget (0, \"screenpixelsperinch\").double_value ();\n\n          double f = 0.0;\n\n          f = 12.0 * res / 74.951;\n\n          if (f > 0)\n            {\n              retval(0) = 2 * retval(0) / f;\n              retval(1) = retval(1) / f;\n              if (is_rectangle)\n                {\n                  retval(2) = 2 * retval(2) / f;\n                  retval(3) = retval(3) / f;\n                }\n              else if (! is_2D)\n                retval(2) = 0;\n            }\n        }\n      else\n        {\n          if (res <= 0)\n            res = xget (0, \"screenpixelsperinch\").double_value ();\n\n          double f = 0.0;\n\n          if (to_units.compare (\"points\"))\n            f = res / 72.0;\n          else if (to_units.compare (\"inches\"))\n            f = res;\n          else if (to_units.compare (\"centimeters\"))\n            f = res / 2.54;\n\n          if (f > 0)\n            {\n              retval(0) = (retval(0) - 1) / f;\n              retval(1) = (retval(1) - 1) / f;\n              if (is_rectangle)\n                {\n                  retval(2) /= f;\n                  retval(3) /= f;\n                }\n              else if (! is_2D)\n                retval(2) = 0;\n            }\n        }\n    }\n\n  return retval;\n}\n\nstatic Matrix\nconvert_text_position (const Matrix& pos, const text::properties& props,\n                       const caseless_str& from_units,\n                       const caseless_str& to_units)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (props.get___myhandle__ ());\n\n  graphics_object ax = go.get_ancestor (\"axes\");\n\n  Matrix retval;\n\n  if (ax.valid_object ())\n    {\n      const axes::properties& ax_props\n        = dynamic_cast<const axes::properties&> (ax.get_properties ());\n      graphics_xform ax_xform = ax_props.get_transform ();\n      bool is_rectangle = (pos.numel () == 4);\n      Matrix ax_bbox = ax_props.get_boundingbox (true),\n             ax_size = ax_bbox.extract_n (0, 2, 1, 2);\n\n      if (from_units.compare (\"data\"))\n        {\n          if (is_rectangle)\n            {\n              ColumnVector v1 = ax_xform.transform (pos(0), pos(1), 0),\n                           v2 = ax_xform.transform (pos(0) + pos(2),\n                                                    pos(1) + pos(3), 0);\n\n              retval.resize (1, 4);\n\n              retval(0) = v1(0) - ax_bbox(0) + 1;\n              retval(1) = ax_bbox(1) + ax_bbox(3) - v1(1) + 1;\n              retval(2) = v2(0) - v1(0);\n              retval(3) = v1(1) - v2(1);\n            }\n          else\n            {\n              ColumnVector v = ax_xform.transform (pos(0), pos(1), pos(2));\n\n              retval.resize (1, 3);\n\n              retval(0) = v(0) - ax_bbox(0) + 1;\n              retval(1) = ax_bbox(1) + ax_bbox(3) - v(1) + 1;\n              retval(2) = 0;\n            }\n        }\n      else\n        retval = convert_position (pos, from_units, \"pixels\", ax_size);\n\n      if (! to_units.compare (\"pixels\"))\n        {\n          if (to_units.compare (\"data\"))\n            {\n              if (is_rectangle)\n                {\n                  ColumnVector v1, v2;\n                  v1 = ax_xform.untransform (retval(0)  + ax_bbox(0) - 1,\n                                             ax_bbox(1) + ax_bbox(3) - retval(1) + 1);\n                  v2 = ax_xform.untransform (retval(0)  + retval(2)  + ax_bbox(0) - 1,\n                                             ax_bbox(1) + ax_bbox(3) - (retval(1) + retval(3)) + 1);\n\n                  retval.resize (1, 4);\n\n                  retval(0) = v1(0);\n                  retval(1) = v1(1);\n                  retval(2) = v2(0) - v1(0);\n                  retval(3) = v2(1) - v1(1);\n                }\n              else\n                {\n                  ColumnVector v;\n                  v = ax_xform.untransform (retval(0)  + ax_bbox(0) - 1,\n                                            ax_bbox(1) + ax_bbox(3) - retval(1) + 1);\n\n                  retval.resize (1, 3);\n\n                  retval(0) = v(0);\n                  retval(1) = v(1);\n                  retval(2) = v(2);\n                }\n            }\n          else\n            retval = convert_position (retval, \"pixels\", to_units, ax_size);\n        }\n    }\n\n  return retval;\n}\n\n// This function always returns the screensize in pixels\nstatic Matrix\nscreen_size_pixels ()\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object obj = gh_mgr.get_object (0);\n\n  Matrix sz = obj.get (\"screensize\").matrix_value ();\n\n  return convert_position (sz, obj.get (\"units\").string_value (), \"pixels\",\n                           sz.extract_n (0, 2, 1, 2)).extract_n (0, 2, 1, 2);\n}\n\nstatic double\ndevice_pixel_ratio (graphics_handle h)\n{\n  double retval = 1.0;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object fig = gh_mgr.get_object (h).get_ancestor (\"figure\");\n\n  if (fig.valid_object ())\n    retval = fig.get (\"__device_pixel_ratio__\").double_value ();\n\n  return retval;\n}\n\nstatic void\nconvert_cdata_2 (bool is_scaled, bool is_real, double clim_0, double clim_1,\n                 const double *cmapv, double x, octave_idx_type lda,\n                 octave_idx_type nc, octave_idx_type i, double *av)\n{\n  if (is_scaled)\n    x = octave::math::fix (nc * (x - clim_0) / (clim_1 - clim_0));\n  else if (is_real)\n    x = octave::math::fix (x - 1);\n\n  if (octave::math::isnan (x))\n    {\n      av[i]       = x;\n      av[i+lda]   = x;\n      av[i+2*lda] = x;\n    }\n  else\n    {\n      if (x < 0)\n        x = 0;\n      else if (x >= nc)\n        x = (nc - 1);\n\n      octave_idx_type idx = static_cast<octave_idx_type> (x);\n\n      av[i]       = cmapv[idx];\n      av[i+lda]   = cmapv[idx+nc];\n      av[i+2*lda] = cmapv[idx+2*nc];\n    }\n}\n\ntemplate <typename T>\nvoid\nconvert_cdata_1 (bool is_scaled, bool is_real, double clim_0, double clim_1,\n                 const double *cmapv, const T *cv, octave_idx_type lda,\n                 octave_idx_type nc, double *av)\n{\n  for (octave_idx_type i = 0; i < lda; i++)\n    convert_cdata_2 (is_scaled, is_real,\n                     clim_0, clim_1, cmapv, cv[i], lda, nc, i, av);\n}\n\nstatic octave_value\nconvert_cdata (const base_properties& props, const octave_value& cdata,\n               bool is_scaled, int cdim)\n{\n  dim_vector dv (cdata.dims ());\n\n  // TrueColor data doesn't require conversion\n  if (dv.ndims () == cdim && dv(cdim-1) == 3)\n    return cdata;\n\n  Matrix cmap (1, 3, 0.0);\n  Matrix clim (1, 2, 0.0);\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (props.get___myhandle__ ());\n  graphics_object ax = go.get_ancestor (\"axes\");\n\n  if (ax.valid_object ())\n    {\n      Matrix _cmap = ax.get (caseless_str (\"colormap\")).matrix_value ();\n\n      cmap = _cmap;\n\n      if (is_scaled)\n        {\n          Matrix _clim = ax.get (caseless_str (\"clim\")).matrix_value ();\n\n          clim = _clim;\n        }\n    }\n\n  dv.resize (cdim);\n  dv(cdim-1) = 3;\n\n  NDArray a (dv);\n\n  octave_idx_type lda = a.numel () / static_cast<octave_idx_type> (3);\n  octave_idx_type nc = cmap.rows ();\n\n  double *av = a.rwdata ();\n  const double *cmapv = cmap.data ();\n\n  double clim_0 = clim(0);\n  double clim_1 = clim(1);\n\n  // FIXME: There is a lot of processing time spent just on data conversion\n  //        both here in graphics.cc and again in gl-render.cc.  There must\n  //        be room for improvement!  Here a macro expands to a templated\n  //        function which in turn calls another function (covert_cdata_2).\n  //        And in gl-render.cc (opengl_renderer::draw_image), only GLfloat\n  //        is supported anyways so there is another double for loop across\n  //        height and width to convert all of the input data to GLfloat.\n\n#define CONVERT_CDATA_1(ARRAY_T, VAL_FN, IS_REAL)                       \\\n  do                                                                    \\\n    {                                                                   \\\n      ARRAY_T tmp = cdata. VAL_FN ## array_value ();                    \\\n                                                                        \\\n      convert_cdata_1 (is_scaled, IS_REAL, clim_0, clim_1, cmapv,       \\\n                       tmp.data (), lda, nc, av);                       \\\n    }                                                                   \\\n  while (0)\n\n  if (cdata.is_int8_type ())\n    CONVERT_CDATA_1 (int8NDArray, int8_, false);\n  else if (cdata.is_int16_type ())\n    CONVERT_CDATA_1 (int16NDArray, int16_, false);\n  else if (cdata.is_int32_type ())\n    CONVERT_CDATA_1 (int32NDArray, int32_, false);\n  else if (cdata.is_int64_type ())\n    CONVERT_CDATA_1 (int64NDArray, int64_, false);\n  else if (cdata.is_uint8_type ())\n    CONVERT_CDATA_1 (uint8NDArray, uint8_, false);\n  else if (cdata.is_uint16_type ())\n    CONVERT_CDATA_1 (uint16NDArray, uint16_, false);\n  else if (cdata.is_uint32_type ())\n    CONVERT_CDATA_1 (uint32NDArray, uint32_, false);\n  else if (cdata.is_uint64_type ())\n    CONVERT_CDATA_1 (uint64NDArray, uint64_, false);\n  else if (cdata.is_double_type ())\n    CONVERT_CDATA_1 (NDArray,, true);\n  else if (cdata.is_single_type ())\n    CONVERT_CDATA_1 (FloatNDArray, float_, true);\n  else if (cdata.islogical ())\n    CONVERT_CDATA_1 (boolNDArray, bool_, false);\n  else\n    {\n      // Don't throw an error; leads to an incomplete FLTK object (bug #46933).\n      warning (\"unsupported type for cdata (= %s).  \"\n               \"Valid types are int8, int16, int32, int64, uint8, uint16, \"\n               \"uint32, uint64, double, single, and bool.\",\n               cdata.type_name ().c_str ());\n      a = NDArray (dv, 0);  // return 0 instead\n    }\n\n#undef CONVERT_CDATA_1\n\n  return octave_value (a);\n}\n\ntemplate <typename T>\nstatic void\nget_array_limits (const Array<T>& m, double& emin, double& emax,\n                  double& eminp, double& emaxp)\n{\n  const T *data = m.data ();\n  octave_idx_type n = m.numel ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      double e = double (data[i]);\n\n      // Don't need to test for NaN here as NaN>x and NaN<x is always false\n      if (! octave::math::isinf (e))\n        {\n          if (e < emin)\n            emin = e;\n\n          if (e > emax)\n            emax = e;\n\n          if (e > 0 && e < eminp)\n            eminp = e;\n\n          if (e < 0 && e > emaxp)\n            emaxp = e;\n        }\n    }\n}\n\nstatic bool\nlookup_object_name (const caseless_str& name, caseless_str& go_name,\n                    caseless_str& rest)\n{\n  int len = name.length ();\n  int offset = 0;\n  bool result = false;\n\n  if (len >= 4)\n    {\n      caseless_str pfx = name.substr (0, 4);\n\n      if (pfx.compare (\"axes\") || pfx.compare (\"line\")\n          || pfx.compare (\"text\"))\n        offset = 4;\n      else if (len >= 5)\n        {\n          pfx = name.substr (0, 5);\n\n          if (pfx.compare (\"image\") || pfx.compare (\"patch\"))\n            offset = 5;\n          else if (len >= 6)\n            {\n              pfx = name.substr (0, 6);\n\n              if (pfx.compare (\"figure\") || pfx.compare (\"uimenu\"))\n                offset = 6;\n              else if (len >= 7)\n                {\n                  pfx = name.substr (0, 7);\n\n                  if (pfx.compare (\"surface\") || pfx.compare (\"scatter\")\n                      || pfx.compare (\"hggroup\") || pfx.compare (\"uipanel\")\n                      || pfx.compare (\"uitable\"))\n                    offset = 7;\n                  else if (len >= 9)\n                    {\n                      pfx = name.substr (0, 9);\n\n                      if (pfx.compare (\"uicontrol\")\n                          || pfx.compare (\"uitoolbar\"))\n                        offset = 9;\n                      else if (len >= 10)\n                        {\n                          pfx = name.substr (0, 10);\n\n                          if (pfx.compare (\"uipushtool\"))\n                            offset = 10;\n                          else if (len >= 12)\n                            {\n                              pfx = name.substr (0, 12);\n\n                              if (pfx.compare (\"uitoggletool\"))\n                                offset = 12;\n                              else if (len >= 13)\n                                {\n                                  pfx = name.substr (0, 13);\n\n                                  if (pfx.compare (\"uicontextmenu\")\n                                      || pfx.compare (\"uibuttongroup\"))\n                                    offset = 13;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n      if (offset > 0)\n        {\n          go_name = pfx;\n          rest = name.substr (offset);\n          result = true;\n        }\n    }\n\n  return result;\n}\n\nbase_graphics_object *\nmake_graphics_object_from_type (const caseless_str& type,\n                                const graphics_handle& h,\n                                const graphics_handle& p)\n{\n  base_graphics_object *go = nullptr;\n\n  if (type.compare (\"figure\"))\n    go = new figure (h, p);\n  else if (type.compare (\"axes\"))\n    go = new axes (h, p);\n  else if (type.compare (\"line\"))\n    go = new line (h, p);\n  else if (type.compare (\"text\"))\n    go = new text (h, p);\n  else if (type.compare (\"image\"))\n    go = new image (h, p);\n  else if (type.compare (\"light\"))\n    go = new light (h, p);\n  else if (type.compare (\"patch\"))\n    go = new patch (h, p);\n  else if (type.compare (\"scatter\"))\n    go = new scatter (h, p);\n  else if (type.compare (\"surface\"))\n    go = new surface (h, p);\n  else if (type.compare (\"hggroup\"))\n    go = new hggroup (h, p);\n  else if (type.compare (\"uimenu\"))\n    go = new uimenu (h, p);\n  else if (type.compare (\"uicontrol\"))\n    go = new uicontrol (h, p);\n  else if (type.compare (\"uipanel\"))\n    go = new uipanel (h, p);\n  else if (type.compare (\"uibuttongroup\"))\n    go = new uibuttongroup (h, p);\n  else if (type.compare (\"uicontextmenu\"))\n    go = new uicontextmenu (h, p);\n  else if (type.compare (\"uitable\"))\n    go = new uitable (h, p);\n  else if (type.compare (\"uitoolbar\"))\n    go = new uitoolbar (h, p);\n  else if (type.compare (\"uipushtool\"))\n    go = new uipushtool (h, p);\n  else if (type.compare (\"uitoggletool\"))\n    go = new uitoggletool (h, p);\n  return go;\n}\n\n// ---------------------------------------------------------------------\n\nbool\nbase_property::set (const octave_value& v, bool do_run, bool do_notify_toolkit)\n{\n  if (do_set (v))\n    {\n      // Notify graphics toolkit.\n      if (m_id >= 0 && do_notify_toolkit)\n        {\n          gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n          graphics_object go = gh_mgr.get_object (m_parent);\n          if (go)\n            go.update (m_id);\n        }\n\n      // run listeners\n      if (do_run)\n        run_listeners (GCB_POSTSET);\n\n      return true;\n    }\n\n  return false;\n}\n\nvoid\nbase_property::run_listeners (listener_mode mode)\n{\n  const octave_value_list& l = m_listeners[mode];\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  for (int i = 0; i < l.length (); i++)\n    gh_mgr.execute_listener (m_parent, l(i));\n}\n\nradio_values::radio_values (const std::string& opt_string)\n  : m_default_val (), m_possible_vals ()\n{\n  std::size_t beg = 0;\n  std::size_t len = opt_string.length ();\n  bool done = len == 0;\n\n  while (! done)\n    {\n      std::size_t end = opt_string.find ('|', beg);\n\n      if (end == std::string::npos)\n        {\n          end = len;\n          done = true;\n        }\n\n      std::string t = opt_string.substr (beg, end-beg);\n\n      // Special case for '|' symbol itself\n      if (t.empty () && opt_string[beg] == '|')\n        {\n          t = '|';\n          end++;\n        }\n\n      // Might want more error checking on parsing default value...\n      if (t[0] == '{')\n        {\n          t = t.substr (1, t.length () - 2);\n          m_default_val = t;\n        }\n      else if (beg == 0) // ensure default value\n        m_default_val = t;\n\n      m_possible_vals.insert (t);\n\n      beg = end + 1;\n    }\n}\n\nstd::string\nradio_values::values_as_string () const\n{\n  std::string retval;\n\n  for (const auto& val : m_possible_vals)\n    {\n      if (retval.empty ())\n        {\n          if (val == default_value ())\n            retval = '{' + val + '}';\n          else\n            retval = val;\n        }\n      else\n        {\n          if (val == default_value ())\n            retval += \" | {\" + val + '}';\n          else\n            retval += \" | \" + val;\n        }\n    }\n\n  if (! retval.empty ())\n    retval = \"[ \" + retval + \" ]\";\n\n  return retval;\n}\n\nCell\nradio_values::values_as_cell () const\n{\n  octave_idx_type i = 0;\n  Cell retval (nelem (), 1);\n\n  for (const auto& val : m_possible_vals)\n    retval(i++) = std::string (val);\n\n  return retval;\n}\n\nbool\ncolor_values::str2rgb (const std::string& str_arg)\n{\n  bool retval = true;\n\n  double tmp_rgb[3] = {0, 0, 0};\n\n  std::string str = str_arg;\n  unsigned int len = str.length ();\n\n  std::transform (str.begin (), str.end (), str.begin (), tolower);\n\n  // \"blue\" must precede black for Matlab compatibility\n  if (str.compare (0, len, \"blue\", 0, len) == 0)\n    tmp_rgb[2] = 1;\n  else if (str.compare (0, len, \"black\", 0, len) == 0\n           || str.compare (0, len, \"k\", 0, len) == 0)\n    tmp_rgb[0] = tmp_rgb[1] = tmp_rgb[2] = 0;\n  else if (str.compare (0, len, \"red\", 0, len) == 0)\n    tmp_rgb[0] = 1;\n  else if (str.compare (0, len, \"green\", 0, len) == 0)\n    tmp_rgb[1] = 1;\n  else if (str.compare (0, len, \"yellow\", 0, len) == 0)\n    tmp_rgb[0] = tmp_rgb[1] = 1;\n  else if (str.compare (0, len, \"magenta\", 0, len) == 0)\n    tmp_rgb[0] = tmp_rgb[2] = 1;\n  else if (str.compare (0, len, \"cyan\", 0, len) == 0)\n    tmp_rgb[1] = tmp_rgb[2] = 1;\n  else if (str.compare (0, len, \"white\", 0, len) == 0\n           || str.compare (0, len, \"w\", 0, len) == 0)\n    tmp_rgb[0] = tmp_rgb[1] = tmp_rgb[2] = 1;\n  else if (str[0] == '#' && len == 7)\n    {\n      try\n        {\n          tmp_rgb[0] = static_cast<double> (stoi (str.substr (1, 2), nullptr, 16))\n                       / 255.0;\n          tmp_rgb[1] = static_cast<double> (stoi (str.substr (3, 2), nullptr, 16))\n                       / 255.0;\n          tmp_rgb[2] = static_cast<double> (stoi (str.substr (5, 2), nullptr, 16))\n                       / 255.0;\n        }\n      catch (const octave::execution_exception&)\n        {\n          retval = false;\n        }\n      catch (const std::invalid_argument&)\n        {\n          retval = false;\n        }\n\n    }\n  else if (str[0] == '#' && len == 4)\n    {\n      try\n        {\n          tmp_rgb[0] = static_cast<double> (stoi (str.substr (1, 1), nullptr, 16))\n                       / 15.0;\n          tmp_rgb[1] = static_cast<double> (stoi (str.substr (2, 1), nullptr, 16))\n                       / 15.0;\n          tmp_rgb[2] = static_cast<double> (stoi (str.substr (3, 1), nullptr, 16))\n                       / 15.0;\n        }\n      catch (const octave::execution_exception&)\n        {\n          retval = false;\n        }\n      catch (const std::invalid_argument&)\n        {\n          retval = false;\n        }\n    }\n  else\n    retval = false;\n\n  if (retval)\n    {\n      for (int i = 0; i < 3; i++)\n        m_rgb(i) = tmp_rgb[i];\n    }\n\n  return retval;\n}\n\nbool\ncolor_property::do_set (const octave_value& val)\n{\n  if (val.is_string ())\n    {\n      std::string s = val.string_value ();\n\n      if (s.empty ())\n        error (R\"(invalid value for color property \"%s\")\",\n               get_name ().c_str ());\n\n      std::string match;\n\n      if (m_radio_val.contains (s, match))\n        {\n          if (m_current_type != radio_t || match != m_current_val)\n            {\n              if (s.length () != match.length ())\n                warning_with_id (\"Octave:abbreviated-property-match\",\n                                 \"%s: allowing %s to match %s value %s\",\n                                 \"set\", s.c_str (), get_name ().c_str (),\n                                 match.c_str ());\n              m_current_val = match;\n              m_current_type = radio_t;\n              return true;\n            }\n        }\n      else\n        {\n          try\n            {\n              color_values col (s);\n\n              if (m_current_type != color_t || col != m_color_val)\n                {\n                  m_color_val = col;\n                  m_current_type = color_t;\n                  return true;\n                }\n            }\n          catch (octave::execution_exception& ee)\n            {\n              error (ee, R\"(invalid value for color property \"%s\" (value = %s))\",\n                     get_name ().c_str (), s.c_str ());\n            }\n        }\n    }\n  else if (val.isnumeric ())\n    {\n      Matrix m = val.matrix_value ();\n\n      if (m.numel () != 3)\n        error (R\"(invalid value for color property \"%s\")\",\n               get_name ().c_str ());\n\n      color_values col (m(0), m(1), m(2));\n\n      if (m_current_type != color_t || col != m_color_val)\n        {\n          m_color_val = col;\n          m_current_type = color_t;\n          return true;\n        }\n    }\n  else\n    error (R\"(invalid value for color property \"%s\")\",\n           get_name ().c_str ());\n\n  return false;\n}\n\nbool\ndouble_radio_property::do_set (const octave_value& val)\n{\n  if (val.is_string ())\n    {\n      std::string s = val.string_value ();\n      std::string match;\n\n      if (s.empty () || ! m_radio_val.contains (s, match))\n        error (R\"(invalid value for double_radio property \"%s\")\",\n               get_name ().c_str ());\n\n      if (m_current_type != radio_t || match != m_current_val)\n        {\n          if (s.length () != match.length ())\n            warning_with_id (\"Octave:abbreviated-property-match\",\n                             \"%s: allowing %s to match %s value %s\",\n                             \"set\", s.c_str (), get_name ().c_str (),\n                             match.c_str ());\n          m_current_val = match;\n          m_current_type = radio_t;\n          return true;\n        }\n    }\n  else if (val.is_scalar_type () && val.isreal ())\n    {\n      double new_dval = val.double_value ();\n\n      if (m_current_type != double_t || new_dval != m_dval)\n        {\n          m_dval = new_dval;\n          m_current_type = double_t;\n          return true;\n        }\n    }\n  else\n    error (R\"(invalid value for double_radio property \"%s\")\",\n           get_name ().c_str ());\n\n  return false;\n}\n\nbool\narray_property::validate (const octave_value& v)\n{\n  bool xok = false;\n\n  // check value type\n  if (m_type_constraints.size () > 0)\n    {\n      if (m_type_constraints.find (v.class_name ()) != m_type_constraints.end ())\n        xok = true;\n\n      // check if complex is allowed (it's also of class \"double\", so\n      // checking that alone is not enough to ensure real type)\n      if (m_type_constraints.find (\"real\") != m_type_constraints.end ()\n          && v.iscomplex ())\n        xok = false;\n    }\n  else\n    xok = v.isnumeric () || v.is_bool_scalar ();\n\n  if (xok && m_size_constraints.size () > 0)\n    {\n      const dim_vector& vdims = v.dims ();\n      int vlen = vdims.ndims ();\n\n      xok = false;\n\n      // check dimensional size constraints until a match is found\n      for (auto it = m_size_constraints.cbegin ();\n           ! xok && it != m_size_constraints.cend ();\n           ++it)\n        {\n          dim_vector itdims = (*it);\n\n          if (itdims.ndims () == vlen)\n            {\n              xok = true;\n\n              for (int i = 0; xok && i < vlen; i++)\n                {\n                  if (itdims(i) > 0)\n                    {\n                      if (itdims(i) != vdims(i))\n                        xok = false;\n                    }\n                  else if (itdims(i) == 0)\n                    {\n                      if (! v.isempty ())\n                        xok = false;\n                      break;\n                    }\n                }\n            }\n        }\n    }\n\n  if (xok)\n    {\n      NDArray v_mat = v.array_value ();\n      // Check min and max\n      if (! octave::math::isnan (m_minval.first))\n        {\n          for (octave_idx_type i = 0; i < v_mat.numel (); i++)\n            if (m_minval.second && m_minval.first > v_mat(i))\n              error (R\"(set: \"%s\" must be greater than or equal to %g)\",\n                     get_name ().c_str (), m_minval.first);\n            else if (! m_minval.second && m_minval.first >= v_mat(i))\n              error (R\"(set: \"%s\" must be greater than %g)\",\n                     get_name ().c_str (), m_minval.first);\n        }\n\n      if (! octave::math::isnan (m_maxval.first))\n        {\n          for (octave_idx_type i = 0; i < v_mat.numel (); i++)\n            if (m_maxval.second && m_maxval.first < v_mat(i))\n              error (R\"(set: \"%s\" must be less than or equal to %g)\",\n                     get_name ().c_str (), m_maxval.first);\n            else if (! m_maxval.second && m_maxval.first <= v_mat(i))\n              error (R\"(set: \"%s\" must be less than %g)\",\n                     get_name ().c_str (), m_maxval.first);\n        }\n\n      if (m_finite_constraint == NO_CHECK) { /* do nothing */ }\n      else if (m_finite_constraint == FINITE)\n        {\n          for (octave_idx_type i = 0; i < v_mat.numel (); i++)\n            if (! octave::math::isfinite (v_mat(i)))\n              error (R\"(set: \"%s\" must be finite)\", get_name ().c_str ());\n        }\n      else if (m_finite_constraint == NOT_NAN)\n        {\n          for (octave_idx_type i = 0; i < v_mat.numel (); i++)\n            if (octave::math::isnan (v_mat(i)))\n              error (R\"(set: \"%s\" must not be NaN)\", get_name ().c_str ());\n        }\n      else if (m_finite_constraint == NOT_INF)\n        {\n          for (octave_idx_type i = 0; i < v_mat.numel (); i++)\n            if (octave::math::isinf (v_mat(i)))\n              error (R\"(set: \"%s\" must not be infinite)\", get_name ().c_str ());\n        }\n\n    }\n\n  return xok;\n}\n\nbool\narray_property::is_equal (const octave_value& v) const\n{\n  if (m_data.type_name () == v.type_name ())\n    {\n      if (m_data.dims () == v.dims ())\n        {\n\n#define CHECK_ARRAY_EQUAL(T, F, A)                                      \\\n          {                                                             \\\n            if (m_data.numel () == 1)                                     \\\n              return m_data.F ## scalar_value () ==                       \\\n                v.F ## scalar_value ();                                 \\\n            else                                                        \\\n              {                                                         \\\n                /* Keep copy of array_value to allow */                 \\\n                /* sparse/bool arrays that are converted, to */         \\\n                /* not be deallocated early */                          \\\n                const A m1 = m_data.F ## array_value ();                  \\\n                const T *d1 = m1.data ();                               \\\n                const A m2 = v.F ## array_value ();                     \\\n                const T *d2 = m2.data ();                               \\\n                                                                        \\\n                bool flag = true;                                       \\\n                                                                        \\\n                for (int i = 0; flag && i < m_data.numel (); i++)         \\\n                  if (d1[i] != d2[i])                                   \\\n                    flag = false;                                       \\\n                                                                        \\\n                return flag;                                            \\\n              }                                                         \\\n          }\n\n          if (m_data.is_double_type () || m_data.islogical ())\n            CHECK_ARRAY_EQUAL (double,, NDArray)\n            else if (m_data.is_single_type ())\n              CHECK_ARRAY_EQUAL (float, float_, FloatNDArray)\n              else if (m_data.is_int8_type ())\n                CHECK_ARRAY_EQUAL (octave_int8, int8_, int8NDArray)\n                else if (m_data.is_int16_type ())\n                  CHECK_ARRAY_EQUAL (octave_int16, int16_, int16NDArray)\n                  else if (m_data.is_int32_type ())\n                    CHECK_ARRAY_EQUAL (octave_int32, int32_, int32NDArray)\n                    else if (m_data.is_int64_type ())\n                      CHECK_ARRAY_EQUAL (octave_int64, int64_, int64NDArray)\n                      else if (m_data.is_uint8_type ())\n                        CHECK_ARRAY_EQUAL (octave_uint8, uint8_, uint8NDArray)\n                        else if (m_data.is_uint16_type ())\n                          CHECK_ARRAY_EQUAL (octave_uint16, uint16_, uint16NDArray)\n                          else if (m_data.is_uint32_type ())\n                            CHECK_ARRAY_EQUAL (octave_uint32, uint32_, uint32NDArray)\n                            else if (m_data.is_uint64_type ())\n                              CHECK_ARRAY_EQUAL (octave_uint64, uint64_, uint64NDArray)\n                            }\n    }\n\n  return false;\n}\n\nvoid\narray_property::get_data_limits ()\n{\n  m_min_val = m_min_pos = octave::numeric_limits<double>::Inf ();\n  m_max_val = m_max_neg = -octave::numeric_limits<double>::Inf ();\n\n  if (! m_data.isempty ())\n    {\n      if (m_data.isinteger ())\n        {\n          if (m_data.is_int8_type ())\n            get_array_limits (m_data.int8_array_value (),\n                              m_min_val, m_max_val, m_min_pos, m_max_neg);\n          else if (m_data.is_uint8_type ())\n            get_array_limits (m_data.uint8_array_value (),\n                              m_min_val, m_max_val, m_min_pos, m_max_neg);\n          else if (m_data.is_int16_type ())\n            get_array_limits (m_data.int16_array_value (),\n                              m_min_val, m_max_val, m_min_pos, m_max_neg);\n          else if (m_data.is_uint16_type ())\n            get_array_limits (m_data.uint16_array_value (),\n                              m_min_val, m_max_val, m_min_pos, m_max_neg);\n          else if (m_data.is_int32_type ())\n            get_array_limits (m_data.int32_array_value (),\n                              m_min_val, m_max_val, m_min_pos, m_max_neg);\n          else if (m_data.is_uint32_type ())\n            get_array_limits (m_data.uint32_array_value (),\n                              m_min_val, m_max_val, m_min_pos, m_max_neg);\n          else if (m_data.is_int64_type ())\n            get_array_limits (m_data.int64_array_value (),\n                              m_min_val, m_max_val, m_min_pos, m_max_neg);\n          else if (m_data.is_uint64_type ())\n            get_array_limits (m_data.uint64_array_value (),\n                              m_min_val, m_max_val, m_min_pos, m_max_neg);\n        }\n      else\n        get_array_limits (m_data.array_value (),\n                          m_min_val, m_max_val, m_min_pos, m_max_neg);\n    }\n}\n\nbool\nhandle_property::do_set (const octave_value& v)\n{\n  // Users may want to use empty matrix to reset a handle property\n  if (v.isempty ())\n    {\n      if (! get ().isempty ())\n        {\n          m_current_val = graphics_handle ();\n          return true;\n        }\n      else\n        return false;\n    }\n\n  double dv = v.xdouble_value (R\"(set: invalid graphics handle for property \"%s\")\",\n                               get_name ().c_str ());\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_handle gh = gh_mgr.lookup (dv);\n\n  // Check the object type if necessary\n  bool type_ok = true;\n  if (gh.ok () && ! m_type_constraints.empty ())\n    {\n      type_ok = false;\n      graphics_object obj = gh_mgr.get_object (gh);\n\n      for (const auto& type : m_type_constraints)\n        if (obj.isa (type))\n          {\n            type_ok = true;\n            break;\n          }\n    }\n\n  if (! octave::math::isnan (gh.value ()) && ! (gh.ok () && type_ok))\n    {\n      if (type_ok)\n        error (R\"(set: invalid graphics handle (= %g) for property \"%s\")\",\n               dv, get_name ().c_str ());\n      else\n        error (R\"(set: invalid graphics object type for property \"%s\")\",\n               get_name ().c_str ());\n    }\n\n  if (m_current_val != gh)\n    {\n      m_current_val = gh;\n      return true;\n    }\n\n  return false;\n}\n\n/*\n## Test validation of contextmenu property\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hpa = patch (\"parent\", hax);\n%!   try\n%!     set (hax, \"contextmenu\", hpa);\n%!   catch\n%!     err = lasterr ();\n%!   end_try_catch\n%!   assert (err, 'set: invalid graphics object type for property \"contextmenu\"');\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n*/\n\nMatrix\nchildren_property::do_get_children (bool return_hidden) const\n{\n  Matrix retval (m_children_list.size (), 1);\n  octave_idx_type k = 0;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (0);\n\n  root_figure::properties& props\n    = dynamic_cast<root_figure::properties&> (go.get_properties ());\n\n  if (! props.is_showhiddenhandles ())\n    {\n      for (const auto& hchild : m_children_list)\n        {\n          graphics_handle kid = hchild;\n\n          if (gh_mgr.is_handle_visible (kid))\n            {\n              if (! return_hidden)\n                retval(k++) = hchild;\n            }\n          else if (return_hidden)\n            retval(k++) = hchild;\n        }\n\n      retval.resize (k, 1);\n    }\n  else\n    {\n      for (const auto& hchild : m_children_list)\n        retval(k++) = hchild;\n    }\n\n  // Return a 0x0 empty array, not 0x1.\n  if (retval.isempty ())\n    retval.resize (0,0);\n\n  return retval;\n}\n\nvoid\nchildren_property::do_delete_children (bool clear, bool from_root)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  if (from_root)\n    {\n      for (graphics_handle hchild : m_children_list)\n        {\n          graphics_object go = gh_mgr.get_object (hchild);\n          if (go.valid_object ()\n              && ! go.get_properties ().is_beingdeleted ())\n            gh_mgr.free (hchild, from_root);\n        }\n      m_children_list.clear ();\n    }\n  else\n    while (! m_children_list.empty ())\n      {\n        // gh_mgr.free removes hchild from children_list\n        graphics_handle hchild = m_children_list.front ();\n        graphics_object go = gh_mgr.get_object (hchild);\n        if (go.valid_object ()\n            && ! go.get_properties ().is_beingdeleted ())\n          gh_mgr.free (hchild, from_root);\n      }\n\n  // FIXME: children_list should be clear anyway at this point.\n  if (clear)\n    m_children_list.clear ();\n}\n\nbool\ncallback_property::validate (const octave_value& v) const\n{\n  // case 1: empty matrix\n  // case 2: function handle\n  // case 3: string corresponding to known function name\n  // case 4: string that can be eval()'ed\n  // case 5: cell array with first element being a function handle\n\n  if (v.isempty ())\n    return true;\n  else if (v.is_function_handle ())\n    return true;\n  else if (v.is_string ())\n    // complete validation will be done at execution-time\n    return true;\n  else if (v.iscell () && (v.rows () == 1 || v.columns () == 1)\n           && v.cell_value ()(0).is_function_handle ())\n    return true;\n\n  return false;\n}\n\nclass callback_props\n{\npublic:\n\n  callback_props () : m_set () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (callback_props)\n\n  ~callback_props () = default;\n\n  bool empty () const { return m_set.empty (); }\n\n  void insert (const callback_property *ptr)\n  {\n    m_set.insert (reinterpret_cast<intptr_t> (ptr));\n  }\n\n  void erase (const callback_property *ptr)\n  {\n    m_set.erase (reinterpret_cast<intptr_t> (ptr));\n  }\n\n  bool contains (const callback_property *ptr) const\n  {\n    return m_set.find (reinterpret_cast<intptr_t> (ptr)) != m_set.end ();\n  }\n\nprivate:\n\n  std::set<intptr_t> m_set;\n};\n\n// Elements of this set are pointers to currently executing\n// callback_property objects.  Used to determine handle visibility\n// inside callback functions.\n\nstatic callback_props executing_callbacks;\n\nvoid\ncallback_property::execute (const octave_value& data) const\n{\n  // We are executing a callback function, so allow handles that have\n  // their handlevisibility property set to \"callback\" to be visible.\n\n  octave::unwind_action executing_callbacks_cleanup\n  ([this] () { executing_callbacks.erase (this); });\n\n  if (! executing_callbacks.contains (this))\n    {\n      executing_callbacks.insert (this);\n\n      if (m_callback.is_defined () && ! m_callback.isempty ())\n        {\n          gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n          gh_mgr.execute_callback (get_parent (), m_callback, data);\n        }\n    }\n}\n\n// Used to cache dummy graphics objects from which dynamic properties can be\n// cloned.\nstatic std::map<caseless_str, graphics_object> dprop_obj_map;\n\nproperty\nproperty::create (const std::string& name, const graphics_handle& h,\n                  const caseless_str& type, const octave_value_list& args)\n{\n  property retval;\n\n  if (type.compare (\"string\"))\n    {\n      std::string sv = (args.length () > 0 ? args(0).string_value () : \"\");\n\n      retval = property (new string_property (name, h, sv));\n    }\n  else if (type.compare (\"any\"))\n    {\n      octave_value ov = (args.length () > 0 ? args(0)\n                         : octave_value (Matrix ()));\n\n      retval = property (new any_property (name, h, ov));\n    }\n  else if (type.compare (\"radio\"))\n    {\n      if (args.length () < 1)\n        error (\"addproperty: missing possible values for radio property\");\n\n      std::string sv = args(0).xstring_value (\"addproperty: argument for radio property must be a string\");\n\n      retval = property (new radio_property (name, h, sv));\n\n      if (args.length () > 1)\n        retval.set (args(1));\n    }\n  else if (type.compare (\"double\"))\n    {\n      double dv = (args.length () > 0 ? args(0).double_value () : 0.0);\n\n      retval = property (new double_property (name, h, dv));\n    }\n  else if (type.compare (\"handle\"))\n    {\n      double hv = (args.length () > 0 ? args(0).double_value ()\n                   : octave::numeric_limits<double>::NaN ());\n\n      graphics_handle gh (hv);\n\n      retval = property (new handle_property (name, h, gh));\n    }\n  else if (type.compare (\"boolean\"))\n    {\n      retval = property (new bool_property (name, h, false));\n\n      if (args.length () > 0)\n        retval.set (args(0));\n    }\n  else if (type.compare (\"data\"))\n    {\n      retval = property (new array_property (name, h, Matrix ()));\n\n      if (args.length () > 0)\n        {\n          retval.set (args(0));\n          // FIXME: additional argument could define constraints,\n          //        but is this really useful?\n        }\n    }\n  else if (type.compare (\"color\"))\n    {\n      color_values cv (0, 0, 0);\n      radio_values rv;\n\n      if (args.length () > 1)\n        rv = radio_values (args(1).string_value ());\n\n      retval = property (new color_property (name, h, cv, rv));\n\n      if (args.length () > 0 && ! args(0).isempty ())\n        retval.set (args(0));\n      else\n        retval.set (rv.default_value ());\n    }\n  else\n    {\n      caseless_str go_name, go_rest;\n\n      if (! lookup_object_name (type, go_name, go_rest))\n        error (\"addproperty: unsupported type for dynamic property (= %s)\",\n               type.c_str ());\n\n      graphics_object go;\n\n      std::map<caseless_str, graphics_object>::const_iterator it\n        = dprop_obj_map.find (go_name);\n\n      if (it == dprop_obj_map.end ())\n        {\n          base_graphics_object *bgo = make_graphics_object_from_type (go_name);\n\n          if (bgo)\n            {\n              go = graphics_object (bgo);\n\n              dprop_obj_map[go_name] = go;\n            }\n        }\n      else\n        go = it->second;\n\n      if (! go.valid_object ())\n        error (\"addproperty: invalid object type (= %s)\",\n               go_name.c_str ());\n\n      property prop = go.get_properties ().get_property (go_rest);\n\n      retval = prop.clone ();\n\n      retval.set_parent (h);\n      retval.set_name (name);\n\n      if (args.length () > 0)\n        retval.set (args(0));\n    }\n\n  return retval;\n}\n\nstatic void\nfinalize_r (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (go)\n    {\n      Matrix children = go.get_properties ().get_all_children ();\n\n      for (int k = 0; k < children.numel (); k++)\n        finalize_r (children(k));\n\n      go.finalize ();\n    }\n}\n\nstatic void\ninitialize_r (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (go)\n    {\n      Matrix children = go.get_properties ().get_all_children ();\n\n      go.initialize ();\n\n      for (int k = 0; k < children.numel (); k++)\n        initialize_r (children(k));\n    }\n}\n\nvoid\nfigure::properties::set_toolkit (const octave::graphics_toolkit& b)\n{\n  if (m_toolkit)\n    finalize_r (get___myhandle__ ());\n\n  m_toolkit = b;\n  m___graphics_toolkit__ = b.get_name ();\n  m___plot_stream__ = Matrix ();\n\n  if (m_toolkit)\n    initialize_r (get___myhandle__ ());\n\n  mark_modified ();\n}\n\nvoid\nfigure::properties::set___mouse_mode__ (const octave_value& val_arg)\n{\n  std::string direction = \"in\";\n\n  octave_value val = val_arg;\n\n  if (val.is_string ())\n    {\n      std::string modestr = val.string_value ();\n\n      if (modestr == \"zoom in\")\n        {\n          val = modestr = \"zoom\";\n          direction = \"in\";\n        }\n      else if (modestr == \"zoom out\")\n        {\n          val = modestr = \"zoom\";\n          direction = \"out\";\n        }\n\n      if (m___mouse_mode__.set (val, true))\n        {\n          std::string mode = m___mouse_mode__.current_value ();\n\n          octave_scalar_map pm = get___pan_mode__ ().scalar_map_value ();\n          pm.setfield (\"Enable\", mode == \"pan\" ? \"on\" : \"off\");\n          set___pan_mode__ (pm);\n\n          octave_scalar_map rm = get___rotate_mode__ ().scalar_map_value ();\n          rm.setfield (\"Enable\", mode == \"rotate\" ? \"on\" : \"off\");\n          set___rotate_mode__ (rm);\n\n          octave_scalar_map zm = get___zoom_mode__ ().scalar_map_value ();\n          zm.setfield (\"Enable\", mode == \"zoom\" ? \"on\" : \"off\");\n          zm.setfield (\"Direction\", direction);\n          set___zoom_mode__ (zm);\n\n          mark_modified ();\n        }\n      else if (modestr == \"zoom\")\n        {\n          octave_scalar_map zm = get___zoom_mode__ ().scalar_map_value ();\n          std::string curr_direction\n            = zm.getfield (\"Direction\").string_value ();\n\n          if (direction != curr_direction)\n            {\n              zm.setfield (\"Direction\", direction);\n              set___zoom_mode__ (zm);\n\n              mark_modified ();\n            }\n        }\n    }\n}\n\nvoid\nfigure::properties::update_handlevisibility ()\n{\n  if (! is_handle_visible ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      octave_value cf = gh_mgr.get_object (0).get (\"currentfigure\");\n\n      if (! cf.isempty () && cf.double_value () == m___myhandle__)\n        {\n          octave::autolock guard (gh_mgr.graphics_lock ());\n\n          octave_value kids =  gh_mgr.get_object (0).get (\"children\");\n\n          if (kids.isempty ())\n            gh_mgr.get_object (0).set (\"currentfigure\", Matrix ());\n          else\n            {\n              NDArray kidsarray = kids.array_value ();\n              gh_mgr.get_object (0).set (\"currentfigure\", kidsarray(0));\n            }\n        }\n    }\n\n  base_properties::update_handlevisibility ();\n}\n\nstatic void\nupdate_text_pos (graphics_handle h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (go.isa (\"text\"))\n    {\n      text::properties& tp\n        = dynamic_cast<text::properties&> (go.get_properties ());\n      tp.update_font ();\n      tp.update_text_extent ();\n    }\n  else if (go.isa (\"figure\") || go.isa (\"uipanel\") || go.isa (\"axes\")\n           || go.isa (\"hggroup\"))\n    {\n      Matrix ch = go.get_properties ().get_all_children ();\n      for (octave_idx_type ii = 0; ii < ch.numel (); ii++)\n        update_text_pos (graphics_handle (ch(ii)));\n\n      if (go.isa (\"axes\"))\n        {\n          axes::properties& ap\n            = dynamic_cast<axes::properties&> (go.get_properties ());\n          ap.update_font ();\n          ap.sync_positions ();\n        }\n    }\n}\n\nvoid\nfigure::properties::update___device_pixel_ratio__ ()\n{\n  update_text_pos (get___myhandle__ ());\n}\n\n// ---------------------------------------------------------------------\n\nvoid\nproperty_list::set (const caseless_str& name, const octave_value& val)\n{\n  std::size_t offset = 0;\n\n  std::size_t len = name.length ();\n\n  if (len > 4)\n    {\n      caseless_str pfx = name.substr (0, 4);\n\n      if (pfx.compare (\"axes\") || pfx.compare (\"line\")\n          || pfx.compare (\"text\"))\n        offset = 4;\n      else if (len > 5)\n        {\n          pfx = name.substr (0, 5);\n\n          if (pfx.compare (\"image\") || pfx.compare (\"patch\"))\n            offset = 5;\n          else if (len > 6)\n            {\n              pfx = name.substr (0, 6);\n\n              if (pfx.compare (\"figure\") || pfx.compare (\"uimenu\"))\n                offset = 6;\n              else if (len > 7)\n                {\n                  pfx = name.substr (0, 7);\n\n                  if (pfx.compare (\"surface\") || pfx.compare (\"scatter\")\n                      || pfx.compare (\"hggroup\")|| pfx.compare (\"uipanel\")\n                      || pfx.compare (\"uitable\"))\n                    offset = 7;\n                  else if (len > 9)\n                    {\n                      pfx = name.substr (0, 9);\n\n                      if (pfx.compare (\"uicontrol\")\n                          || pfx.compare (\"uitoolbar\"))\n                        offset = 9;\n                      else if (len > 10)\n                        {\n                          pfx = name.substr (0, 10);\n\n                          if (pfx.compare (\"uipushtool\"))\n                            offset = 10;\n                          else if (len > 12)\n                            {\n                              pfx = name.substr (0, 12);\n\n                              if (pfx.compare (\"uitoogletool\"))\n                                offset = 12;\n                              else if (len > 13)\n                                {\n                                  pfx = name.substr (0, 13);\n\n                                  if (pfx.compare (\"uicontextmenu\")\n                                      || pfx.compare (\"uibuttongroup\"))\n                                    offset = 13;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n      if (offset > 0)\n        {\n          // FIXME: should we validate property names and values here?\n\n          std::string pname = name.substr (offset);\n\n          std::transform (pfx.begin (), pfx.end (), pfx.begin (), tolower);\n          std::transform (pname.begin (), pname.end (), pname.begin (),\n                          tolower);\n\n          bool has_property = false;\n          if (pfx == \"axes\")\n            has_property = axes::properties::has_core_property (pname);\n          else if (pfx == \"figure\")\n            has_property = figure::properties::has_core_property (pname);\n          else if (pfx == \"line\")\n            has_property = line::properties::has_core_property (pname);\n          else if (pfx == \"text\")\n            has_property = text::properties::has_core_property (pname);\n          else if (pfx == \"image\")\n            has_property = image::properties::has_core_property (pname);\n          else if (pfx == \"patch\")\n            has_property = patch::properties::has_core_property (pname);\n          else if (pfx == \"scatter\")\n            has_property = scatter::properties::has_core_property (pname);\n          else if (pfx == \"surface\")\n            has_property = surface::properties::has_core_property (pname);\n          else if (pfx == \"hggroup\")\n            has_property = hggroup::properties::has_core_property (pname);\n          else if (pfx == \"uimenu\")\n            has_property = uimenu::properties::has_core_property (pname);\n          else if (pfx == \"uicontrol\")\n            has_property = uicontrol::properties::has_core_property (pname);\n          else if (pfx == \"uibuttongroup\")\n            has_property = uibuttongroup::properties::has_core_property (pname);\n          else if (pfx == \"uipanel\")\n            has_property = uipanel::properties::has_core_property (pname);\n          else if (pfx == \"uicontextmenu\")\n            has_property = uicontextmenu::properties::has_core_property (pname);\n          else if (pfx == \"uitable\")\n            has_property = uitable::properties::has_core_property (pname);\n          else if (pfx == \"uitoolbar\")\n            has_property = uitoolbar::properties::has_core_property (pname);\n          else if (pfx == \"uipushtool\")\n            has_property = uipushtool::properties::has_core_property (pname);\n\n          if (! has_property)\n            error (\"invalid %s property '%s'\", pfx.c_str (), pname.c_str ());\n\n          bool remove = false;\n          if (val.is_string ())\n            {\n              std::string sval = val.string_value ();\n\n              remove = (sval == \"remove\");\n            }\n\n          pval_map_type& pval_map = m_plist_map[pfx];\n\n          if (remove)\n            {\n              auto p = pval_map.find (pname);\n\n              if (p != pval_map.end ())\n                pval_map.erase (p);\n            }\n          else\n            pval_map[pname] = val;\n        }\n    }\n\n  if (offset == 0)\n    error (\"invalid default property specification\");\n}\n\noctave_value\nproperty_list::lookup (const caseless_str& name) const\n{\n  octave_value retval;\n\n  std::size_t offset = 0;\n\n  std::size_t len = name.length ();\n\n  if (len > 4)\n    {\n      caseless_str pfx = name.substr (0, 4);\n\n      if (pfx.compare (\"axes\") || pfx.compare (\"line\")\n          || pfx.compare (\"text\"))\n        offset = 4;\n      else if (len > 5)\n        {\n          pfx = name.substr (0, 5);\n\n          if (pfx.compare (\"image\") || pfx.compare (\"patch\"))\n            offset = 5;\n          else if (len > 6)\n            {\n              pfx = name.substr (0, 6);\n\n              if (pfx.compare (\"figure\") || pfx.compare (\"uimenu\"))\n                offset = 6;\n              else if (len > 7)\n                {\n                  pfx = name.substr (0, 7);\n\n                  if (pfx.compare (\"surface\") || pfx.compare (\"scatter\")\n                      || pfx.compare (\"hggroup\") || pfx.compare (\"uipanel\")\n                      || pfx.compare (\"uitable\"))\n                    offset = 7;\n                  else if (len > 9)\n                    {\n                      pfx = name.substr (0, 9);\n\n                      if (pfx.compare (\"uicontrol\")\n                          || pfx.compare (\"uitoolbar\"))\n                        offset = 9;\n                      else if (len > 10)\n                        {\n                          pfx = name.substr (0, 10);\n\n                          if (pfx.compare (\"uipushtool\"))\n                            offset = 10;\n                          else if (len > 12)\n                            {\n                              pfx = name.substr (0, 12);\n\n                              if (pfx.compare (\"uitoggletool\"))\n                                offset = 12;\n                              else if (len > 13)\n                                {\n                                  pfx = name.substr (0, 13);\n\n                                  if (pfx.compare (\"uicontextmenu\")\n                                      || pfx.compare (\"uibuttongroup\"))\n                                    offset = 13;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n      if (offset > 0)\n        {\n          std::string pname = name.substr (offset);\n\n          std::transform (pfx.begin (), pfx.end (), pfx.begin (), tolower);\n          std::transform (pname.begin (), pname.end (), pname.begin (),\n                          tolower);\n\n          plist_map_const_iterator p = find (pfx);\n\n          if (p != end ())\n            {\n              const pval_map_type& pval_map = p->second;\n\n              pval_map_const_iterator q = pval_map.find (pname);\n\n              if (q != pval_map.end ())\n                retval = q->second;\n            }\n        }\n    }\n\n  return retval;\n}\n\noctave_scalar_map\nproperty_list::as_struct (const std::string& prefix_arg) const\n{\n  octave_scalar_map m;\n\n  for (const auto& p : *this)\n    {\n      std::string prefix = prefix_arg + p.first;\n\n      for (const auto& prop_val : p.second)\n        m.assign (prefix + prop_val.first, prop_val.second);\n    }\n\n  return m;\n}\n\n// Set property given as either cs-list of name/value pairs or a struct.\n\nvoid\ngraphics_object::set (const octave_value_list& args)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    error (\"graphics_object::set: Nothing to set\");\n\n  for (int i = 0; i < nargin; )\n    {\n      if (args(i).isstruct ())\n        {\n          set (args(i).map_value ());\n          i++;\n        }\n      else if (i < nargin - 1)\n        {\n          caseless_str pname = args(i).xstring_value (\"set: argument %d must be a property name\", i);\n          octave_value val = args(i+1);\n          set_value_or_default (pname, val);\n          i += 2;\n        }\n      else\n        error (\"set: invalid number of arguments\");\n    }\n}\n\n/*\n## test set with name, value pairs\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! h = plot (1:10, 10:-1:1);\n%! set (h, \"linewidth\", 10, \"marker\", \"x\");\n%! lw = get (h, \"linewidth\");\n%! mk = get (h, \"marker\");\n%! close (hf);\n%! assert (lw, 10);\n%! assert (mk, \"x\");\n*/\n\n// Set properties given in two cell arrays containing names and values.\nvoid\ngraphics_object::set (const Array<std::string>& pnames,\n                      const Cell& values, octave_idx_type row)\n{\n  if (pnames.numel () != values.columns ())\n    error (\"set: number of names must match number of value columns \"\n           \"(%\" OCTAVE_IDX_TYPE_FORMAT \" != %\" OCTAVE_IDX_TYPE_FORMAT \")\",\n           pnames.numel (), values.columns ());\n\n  octave_idx_type k = pnames.columns ();\n\n  for (octave_idx_type column = 0; column < k; column++)\n    {\n      caseless_str pname = pnames(column);\n      octave_value val = values(row, column);\n\n      set_value_or_default (pname, val);\n    }\n}\n\n/*\n## test set with cell array arguments\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! h = plot (1:10, 10:-1:1);\n%! set (h, {\"linewidth\", \"marker\"}, {10, \"x\"});\n%! lw = get (h, \"linewidth\");\n%! mk = get (h, \"marker\");\n%! close (hf);\n%! assert (lw, 10);\n%! assert (mk, \"x\");\n\n## test set with multiple handles and cell array arguments\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = plot (1:10, 10:-1:1, 1:10, 1:10);\n%!   set (h, {\"linewidth\", \"marker\"}, {10, \"x\"; 5, \"o\"});\n%!   assert (get (h, \"linewidth\"), {10; 5});\n%!   assert (get (h, \"marker\"), {\"x\"; \"o\"});\n%!   set (h, {\"linewidth\", \"marker\"}, {10, \"x\"});\n%!   assert (get (h, \"linewidth\"), {10; 10});\n%!   assert (get (h, \"marker\"), {\"x\"; \"x\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <set: number of graphics handles must match number of value rows>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = plot (1:10, 10:-1:1, 1:10, 1:10);\n%!   set (h, {\"linewidth\", \"marker\"}, {10, \"x\"; 5, \"o\"; 7, \".\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <set: number of names must match number of value columns>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = plot (1:10, 10:-1:1, 1:10, 1:10);\n%!   set (h, {\"linewidth\"}, {10, \"x\"; 5, \"o\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\n// Set properties given in a struct array\nvoid\ngraphics_object::set (const octave_map& m)\n{\n  for (octave_idx_type p = 0; p < m.nfields (); p++)\n    {\n      // FIXME: Would it be better to extract all the keys at once rather than\n      //        repeatedly call keys() inside a for loop?\n      caseless_str pname = m.keys ()[p];\n\n      octave_value val = octave_value (m.contents (pname).elem (m.numel () - 1));\n\n      set_value_or_default (pname, val);\n    }\n}\n\n/*\n## test set with struct arguments\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = plot (1:10, 10:-1:1);\n%!   set (h, struct (\"linewidth\", 10, \"marker\", \"x\"));\n%!   assert (get (h, \"linewidth\"), 10);\n%!   assert (get (h, \"marker\"), \"x\");\n%!   h = plot (1:10, 10:-1:1, 1:10, 1:10);\n%!   set (h, struct (\"linewidth\", {5, 10}));\n%!   assert (get (h, \"linewidth\"), {10; 10});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test ordering\n%!test\n%! markchanged = @(h, foobar, name) set (h, \"userdata\", [get(h,\"userdata\"); {name}]);\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = line ();\n%!   set (h, \"userdata\", {});\n%!   addlistener (h, \"color\", {markchanged, \"color\"});\n%!   addlistener (h, \"linewidth\", {markchanged, \"linewidth\"});\n%!   ## \"linewidth\" first\n%!   props.linewidth = 2;\n%!   props.color = \"r\";\n%!   set (h, props);\n%!   assert (get (h, \"userdata\"), fieldnames (props));\n%!   clear props;\n%!   clf ();\n%!   h = line ();\n%!   set (h, \"userdata\", {});\n%!   addlistener (h, \"color\", {markchanged, \"color\"});\n%!   addlistener (h, \"linewidth\", {markchanged, \"linewidth\"});\n%!   ## \"color\" first\n%!   props.color = \"r\";\n%!   props.linewidth = 2;\n%!   set (h, props);\n%!   assert (get (h, \"userdata\"), fieldnames (props));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\n// Set a property to a value or to its (factory) default value.\n\nvoid\ngraphics_object::set_value_or_default (const caseless_str& pname,\n                                       const octave_value& val)\n{\n  if (val.is_string () && val.rows () == 1)\n    {\n      std::string sval = val.string_value ();\n\n      octave_value default_val;\n\n      if (sval == \"default\")\n        {\n          default_val = get_default (pname);\n\n          m_rep->set (pname, default_val);\n        }\n      else if (sval == \"factory\")\n        {\n          default_val = get_factory_default (pname);\n\n          m_rep->set (pname, default_val);\n        }\n      else\n        {\n          // Matlab specifically uses \"\\default\" to escape string setting\n          if (sval == R\"(\\default)\")\n            m_rep->set (pname, \"default\");\n          else if (sval == R\"(\\factory)\")\n            m_rep->set (pname, \"factory\");\n          else\n            m_rep->set (pname, val);\n        }\n    }\n  else\n    m_rep->set (pname, val);\n}\n\n/*\n## test setting of default values\n%!test\n%! old_lw = get (0, \"defaultlinelinewidth\");\n%! unwind_protect\n%!   hf = figure (\"visible\", \"off\");\n%!   h = plot (1:10, 10:-1:1);\n%!   set (0, \"defaultlinelinewidth\", 20);\n%!   set (h, \"linewidth\", \"default\");\n%!   assert (get (h, \"linewidth\"), 20);\n%!   set (h, \"linewidth\", \"factory\");\n%!   assert (get (h, \"linewidth\"), 0.5);\n%! unwind_protect_cleanup\n%!   close (hf);\n%!   set (0, \"defaultlinelinewidth\", old_lw);\n%! end_unwind_protect\n*/\n\n// This function is NOT equivalent to the scripting language function gcf.\ngraphics_handle\ngcf ()\n{\n  octave_value val = xget (0, \"currentfigure\");\n\n  return val.isempty () ? octave::numeric_limits<double>::NaN ()\n         : val.double_value ();\n}\n\n// This function is NOT equivalent to the scripting language function gca.\ngraphics_handle\ngca ()\n{\n  octave_value val = xget (gcf (), \"currentaxes\");\n\n  return val.isempty () ? octave::numeric_limits<double>::NaN ()\n         : val.double_value ();\n}\n\nstatic void\nadopt (const graphics_handle& parent_h, const graphics_handle& h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (parent_h);\n\n  parent_go.adopt (h);\n}\n\nstatic bool\nishghandle (const graphics_handle& h)\n{\n  return h.ok ();\n}\n\nstatic bool\nishghandle (double val)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_handle h = gh_mgr.lookup (val);\n\n  return h.ok ();\n}\n\nstatic octave_value\nishghandle (const octave_value& val)\n{\n  octave_value retval = false;\n\n  if (val.is_real_scalar () && ishghandle (val.double_value ()))\n    retval = true;\n  else if (val.isnumeric () && val.isreal ())\n    {\n      const NDArray handles = val.array_value ();\n\n      boolNDArray result (handles.dims ());\n\n      for (octave_idx_type i = 0; i < handles.numel (); i++)\n        result.xelem (i) = ishghandle (handles(i));\n\n      retval = result;\n    }\n\n  return retval;\n}\n\nstatic void\nxcreatefcn (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  go.get_properties ().execute_createfcn  ();\n}\n\nstatic void\nxinitialize (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (go)\n    go.initialize ();\n}\n\n// ---------------------------------------------------------------------\n\nstatic int\ntoggle_warn (std::string id, bool on, int state = -1)\n{\n  if (! on)\n    {\n      state = octave::warning_enabled (id);\n      octave::disable_warning (id);\n    }\n  else\n    {\n      if (state == 1)\n        octave::set_warning_state (id, \"on\");\n      else if (state == 2)\n        octave::set_warning_state (id, \"error\");\n    }\n  return state;\n}\n\nstatic void\nxreset_default_properties (graphics_handle h,\n                           property_list::pval_map_type factory_pval)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  // Replace factory defaults by user defined ones\n  std::string go_name = go.get_properties ().graphics_object_name ();\n  property_list::pval_map_type pval;\n  go.build_user_defaults_map (pval, go_name);\n\n  for (const auto& p : pval)\n    factory_pval[p.first] = p.second;\n\n  // Save warning state of \"Octave:deprecated-property\"\n  int state = toggle_warn (\"Octave:deprecated-property\", false);\n\n  // Reset defaults\n  for (const auto& p : factory_pval)\n    {\n      std::string pname = p.first;\n\n      // Don't reset internal properties and handle_properties\n      if (! go.has_readonly_property (pname)\n          && pname.find (\"__\") != 0 && pname.find (\"current\") != 0\n          && pname != \"uicontextmenu\" && pname != \"parent\")\n        {\n          // Store *mode prop/val in order to set them last\n          if (pname.find (\"mode\") == (pname.length () - 4))\n            pval[pname] = p.second;\n          else\n            go.set (pname, p.second);\n        }\n    }\n\n  // set *mode properties\n  for (const auto& p : pval)\n    go.set (p.first, p.second);\n\n  toggle_warn (\"Octave:deprecated-property\", true, state);\n}\n\n// ---------------------------------------------------------------------\n\nvoid\nbase_properties::set_from_list (base_graphics_object& bgo,\n                                property_list& defaults)\n{\n  std::string go_name = graphics_object_name ();\n\n  property_list::plist_map_const_iterator plist = defaults.find (go_name);\n\n  if (plist != defaults.end ())\n    {\n      const property_list::pval_map_type pval_map = plist->second;\n\n      for (const auto& prop_val : pval_map)\n        {\n          std::string pname = prop_val.first;\n\n          try\n            {\n              bgo.set (pname, prop_val.second);\n            }\n          catch (octave::execution_exception& ee)\n            {\n              error (ee, \"error setting default property %s\", pname.c_str ());\n            }\n        }\n    }\n}\n\n/*\n## test defaults are set in the order they were stored\n%!test\n%! set (0, \"defaultfigureunits\", \"normalized\");\n%! set(0, \"defaultfigureposition\", [0.7 0 0.3 0.3]);\n%! hf = figure (\"visible\", \"off\");\n%! tol = 20 * eps;\n%! unwind_protect\n%!   assert (get (hf, \"position\"), [0.7 0 0.3 0.3], tol);\n%! unwind_protect_cleanup\n%!   close (hf);\n%!   set (0, \"defaultfigureunits\", \"remove\");\n%!   set (0, \"defaultfigureposition\", \"remove\");\n%! end_unwind_protect\n*/\n\noctave_value\nbase_properties::get_dynamic (const caseless_str& pname) const\n{\n  std::map<caseless_str, property, cmp_caseless_str>::const_iterator it\n    = m_all_props.find (pname);\n\n  if (it == m_all_props.end ())\n    error (R\"(get: unknown property \"%s\")\", pname.c_str ());\n\n  return it->second.get ();\n}\n\noctave_value\nbase_properties::get_dynamic (bool all) const\n{\n  octave_scalar_map m;\n\n  for (const auto& it : m_all_props)\n    if (all || ! it.second.is_hidden ())\n      m.assign (it.second.get_name (), it.second.get ());\n\n  return m;\n}\n\nstd::set<std::string>\nbase_properties::dynamic_property_names () const\n{\n  return m_dynamic_properties;\n}\n\nbool\nbase_properties::has_dynamic_property (const std::string& pname) const\n{\n  const std::set<std::string>& dynprops = dynamic_property_names ();\n\n  if (dynprops.find (pname) != dynprops.end ())\n    return true;\n  else\n    return m_all_props.find (pname) != m_all_props.end ();\n}\n\nvoid\nbase_properties::set_dynamic (const caseless_str& pname,\n                              const octave_value& val)\n{\n  auto it = m_all_props.find (pname);\n\n  if (it == m_all_props.end ())\n    error (R\"(set: unknown property \"%s\")\", pname.c_str ());\n\n  it->second.set (val);\n\n  m_dynamic_properties.insert (pname);\n\n  mark_modified ();\n}\n\nproperty\nbase_properties::get_property_dynamic (const caseless_str& pname) const\n{\n  std::map<caseless_str, property, cmp_caseless_str>::const_iterator it\n    = m_all_props.find (pname);\n\n  if (it == m_all_props.end ())\n    error (R\"(get_property: unknown property \"%s\")\", pname.c_str ());\n\n  return it->second;\n}\n\nvoid\nbase_properties::set_parent (const octave_value& val)\n{\n  double hp = val.xdouble_value (\"set: parent must be a graphics handle\");\n  if (hp == m___myhandle__)\n    error (\"set: can not set object parent to be object itself\");\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_handle new_parent = gh_mgr.lookup (hp);\n  if (! new_parent.ok ())\n    error (\"set: invalid graphics handle (= %g) for parent\", hp);\n\n  // Remove child from current parent\n  graphics_object old_parent_go;\n  old_parent_go = gh_mgr.get_object (get_parent ());\n\n  if (old_parent_go.get_handle () != hp)\n    old_parent_go.remove_child (m___myhandle__);\n  else\n    return;  // Do nothing more\n\n  // Check new parent's parent is not this child to avoid recursion\n  graphics_object new_parent_go;\n  new_parent_go = gh_mgr.get_object (new_parent);\n  if (new_parent_go.get_parent () == m___myhandle__)\n    {\n      // new parent's parent gets child's original parent\n      new_parent_go.get_properties ().set_parent (get_parent ().as_octave_value ());\n    }\n\n  // Set parent property to new_parent and do adoption\n  m_parent = new_parent.as_octave_value ();\n  octave::adopt (m_parent.handle_value (), m___myhandle__);\n}\n\n/*\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   set (hax, \"parent\", gcf ());\n%!   assert (gca (), hax);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\nvoid\nbase_properties::mark_modified ()\n{\n  // Mark existing object as modified\n  m___modified__ = \"on\";\n\n  // Attempt to mark parent object as modified if it exists\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  if (parent_go)\n    parent_go.mark_modified ();\n}\n\nvoid\nbase_properties::override_defaults (base_graphics_object& obj)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  if (parent_go)\n    parent_go.override_defaults (obj);\n}\n\nvoid\nbase_properties::update_axis_limits (const std::string& axis_type) const\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (m___myhandle__);\n\n  if (go)\n    go.update_axis_limits (axis_type);\n}\n\nvoid\nbase_properties::update_axis_limits (const std::string& axis_type,\n                                     const graphics_handle& h) const\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (m___myhandle__);\n\n  if (go)\n    go.update_axis_limits (axis_type, h);\n}\n\nvoid\nbase_properties::update_contextmenu () const\n{\n  if (m_contextmenu.get ().isempty ())\n    return;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (m_contextmenu.get ());\n\n  if (go && go.isa (\"uicontextmenu\"))\n    {\n      uicontextmenu::properties& props\n        = reinterpret_cast<uicontextmenu::properties&> (go.get_properties ());\n      props.add_dependent_obj (m___myhandle__);\n    }\n}\n\nbool\nbase_properties::is_handle_visible () const\n{\n  return (m_handlevisibility.is (\"on\")\n          || (! executing_callbacks.empty () && ! m_handlevisibility.is (\"off\")));\n}\n\noctave::graphics_toolkit\nbase_properties::get_toolkit () const\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get_parent ());\n\n  if (go)\n    return go.get_toolkit ();\n  else\n    return octave::graphics_toolkit ();\n}\n\nvoid\nbase_properties::update_boundingbox ()\n{\n  Matrix kids = get_children ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  for (int i = 0; i < kids.numel (); i++)\n    {\n      graphics_object go = gh_mgr.get_object (kids(i));\n\n      if (go.valid_object ())\n        go.get_properties ().update_boundingbox ();\n    }\n}\n\nvoid\nbase_properties::update_autopos (const std::string& elem_type)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  if (parent_go.valid_object ())\n    parent_go.get_properties ().update_autopos (elem_type);\n}\n\nvoid\nbase_properties::update_handlevisibility ()\n{\n  if (is_handle_visible ())\n    return;\n\n  // This object should not be the figure \"currentobject\"\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go (gh_mgr.get_object (get___myhandle__ ()));\n\n  graphics_object fig (go.get_ancestor (\"figure\"));\n\n  if (fig.valid_object ())\n    {\n      octave_value co = fig.get (\"currentobject\");\n      if (! co.isempty () && co.double_value () == m___myhandle__)\n        {\n          octave::autolock guard (gh_mgr.graphics_lock ());\n\n          auto& fig_props = dynamic_cast<figure::properties&> (fig.get_properties ());\n          fig_props.set_currentobject (Matrix ());\n        }\n    }\n}\n\n/*\n## test current figure and current axes have visible handles\n%!test\n%! hf1 = figure (\"visible\", \"off\");\n%! hf2 = figure (\"visible\", \"off\");\n%! hax1 = axes ();\n%! hax2 = axes ();\n%! unwind_protect\n%!   assert (get (0, \"currentfigure\"), hf2);\n%!   assert (get (hf2, \"currentaxes\"), hax2);\n%!   set (hf2, \"handlevisibility\", \"off\");\n%!   assert (get (0, \"currentfigure\"), hf1);\n%!   set (hax2, \"handlevisibility\", \"off\");\n%!   assert (get (hf2, \"currentaxes\"), hax1);\n%!   assert (get (hf2, \"currentobject\"), []);\n%! unwind_protect_cleanup\n%!   close ([hf1, hf2]);\n%! end_unwind_protect\n*/\n\n/*\n## test current callback object have visible handle\n%!test\n%! hf = figure (\"handlevisibility\", \"off\", \"visible\", \"off\");\n%! hax = axes (\"parent\", hf, \"handlevisibility\", \"off\");\n%! unwind_protect\n%!   fcn = @(h, ~) setappdata (h, \"testdata\", gcbo ());\n%!   addlistener (hf, \"color\", fcn);\n%!   addlistener (hax, \"color\", fcn);\n%!   set (hf, \"color\", \"b\");\n%!   set (hax, \"color\", \"b\");\n%!   assert (getappdata (hf, \"testdata\"), hf);\n%!   assert (getappdata (hax, \"testdata\"), hax);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\nvoid\nbase_properties::add_listener (const caseless_str& pname,\n                               const octave_value& val,\n                               listener_mode mode)\n{\n  property p = get_property (pname);\n\n  if (p.ok ())\n    p.add_listener (val, mode);\n}\n\nvoid\nbase_properties::delete_listener (const caseless_str& pname,\n                                  const octave_value& val,\n                                  listener_mode mode)\n{\n  property p = get_property (pname);\n\n  if (p.ok ())\n    p.delete_listener (val, mode);\n}\n\nvoid\nbase_properties::get_children_of_type (const caseless_str& chtype,\n                                       bool get_invisible,\n                                       bool traverse,\n                                       std::list<graphics_object>& children_list) const\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  Matrix ch = get_children ();\n\n  for (octave_idx_type i = 0; i < ch.numel (); i++)\n    {\n      graphics_handle hkid = gh_mgr.lookup (ch(i));\n\n      if (hkid.ok ())\n        {\n          graphics_object go = gh_mgr.get_object (hkid);\n          if ( get_invisible || go.get_properties ().is_visible () )\n            {\n              if (go.isa (chtype))\n                children_list.push_back (go);\n              else if (traverse && go.isa (\"hggroup\"))\n                go.get_properties ().get_children_of_type (chtype,\n                    get_invisible,\n                    traverse,\n                    children_list);\n            }\n        }\n    }\n}\n\n// ---------------------------------------------------------------------\n\nvoid\nbase_graphics_object::update_axis_limits (const std::string& axis_type)\n{\n  if (! valid_object ())\n    error (\"base_graphics_object::update_axis_limits: invalid graphics object\");\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  if (parent_go)\n    parent_go.update_axis_limits (axis_type);\n}\n\nvoid\nbase_graphics_object::update_axis_limits (const std::string& axis_type,\n    const graphics_handle& h)\n{\n  if (! valid_object ())\n    error (\"base_graphics_object::update_axis_limits: invalid graphics object\");\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  if (parent_go)\n    parent_go.update_axis_limits (axis_type, h);\n}\n\nvoid\nbase_graphics_object::remove_all_listeners ()\n{\n  int state = toggle_warn (\"Octave:deprecated-property\", false);\n  octave_map m = get (true).map_value ();\n  toggle_warn (\"Octave:deprecated-property\", true, state);\n\n  for (const auto& pm : m)\n    {\n      // FIXME: there has to be a better way.  I think we want to\n      // ask whether it is OK to delete the listener for the given\n      // property.  How can we know in advance that it will be OK?\n\n      octave::unwind_protect frame;\n\n      octave::interpreter_try (frame);\n\n      try\n        {\n          property p = get_properties ().get_property (pm.first);\n\n          if (p.ok ())\n            p.delete_listener ();\n        }\n      catch (const octave::execution_exception&)\n        {\n          octave::interpreter& interp = octave::__get_interpreter__ ();\n\n          interp.recover_from_exception ();\n        }\n    }\n}\n\nvoid\nbase_graphics_object::build_user_defaults_map (property_list::pval_map_type& def,\n    const std::string go_name) const\n{\n  property_list local_defaults = get_defaults_list ();\n  const auto it = local_defaults.find (go_name);\n\n  if (it != local_defaults.end ())\n    {\n      property_list::pval_map_type pval_lst = it->second;\n      for (const auto& prop_val : pval_lst)\n        {\n          std::string pname = prop_val.first;\n          if (def.find (pname) == def.end ())\n            def[pname] = prop_val.second;\n        }\n    }\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  if (parent_go)\n    parent_go.build_user_defaults_map (def, go_name);\n}\n\nvoid\nbase_graphics_object::reset_default_properties ()\n{\n  if (valid_object ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      property_list::pval_map_type factory_pval\n        = gh_mgr.get_object (0).get_factory_defaults_list ().find (type ())->second;\n\n      remove_all_listeners ();\n      xreset_default_properties (get_handle (), factory_pval);\n    }\n}\n\nstd::string\nbase_graphics_object::values_as_string ()\n{\n  if (! valid_object ())\n    error (\"base_graphics_object::values_as_string: invalid graphics object\");\n\n  std::string retval;\n  octave_map m = get ().map_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get_handle ());\n\n  for (const auto& pm : m)\n    {\n      const auto& pname = pm.first;\n      if (pname != \"children\" && ! go.has_readonly_property (pname))\n        {\n          property p = get_properties ().get_property (pname);\n\n          if (p.ok () && ! p.is_hidden ())\n            {\n              retval += \"\\n\\t\" + std::string (pname) + \":  \";\n              if (p.is_radio ())\n                retval += p.values_as_string ();\n            }\n        }\n    }\n\n  if (! retval.empty ())\n    retval += '\\n';\n\n  return retval;\n}\n\nstd::string\nbase_graphics_object::value_as_string (const std::string& prop)\n{\n  std::string retval;\n\n  if (! valid_object ())\n    error (\"base_graphics_object::value_as_string: invalid graphics object\");\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get_handle ());\n\n  if (prop != \"children\" && ! go.has_readonly_property (prop))\n    {\n      property p = get_properties ().get_property (prop);\n\n      if (p.ok () && ! p.is_hidden ())\n        {\n          if (p.is_radio ())\n            retval += p.values_as_string ();\n        }\n    }\n\n  if (! retval.empty ())\n    retval += '\\n';\n\n  return retval;\n}\n\noctave_scalar_map\nbase_graphics_object::values_as_struct ()\n{\n  octave_scalar_map retval;\n\n  if (! valid_object ())\n    error (\"base_graphics_object::values_as_struct: invalid graphics object\");\n\n  octave_scalar_map m = get ().scalar_map_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get_handle ());\n\n  for (const auto& pm : m)\n    {\n      const auto& pname = pm.first;\n      if (pname != \"children\" && ! go.has_readonly_property (pname))\n        {\n          property p = get_properties ().get_property (pname);\n\n          if (p.ok () && ! p.is_hidden ())\n            {\n              if (p.is_radio ())\n                retval.assign (p.get_name (), p.values_as_cell ());\n              else\n                retval.assign (p.get_name (), Cell ());\n            }\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! hfig = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   ret = set (hax, \"tightinset\");\n%!   assert (isempty (ret));\n%!   ret = set (hax, \"type\");\n%!   assert (isempty (ret));\n%!   ret = set (hfig, \"tag\");\n%!   assert (isempty (ret));\n%!   ret = set (0, \"commandwindowsize\");\n%!   assert (isempty (ret));\n%!   ret = set (0);\n%!   assert (! isfield (ret, \"commandwindowsize\"));\n%! unwind_protect_cleanup\n%!   close (hfig);\n%! end_unwind_protect\n*/\n\ngraphics_object\ngraphics_object::get_ancestor (const std::string& obj_type) const\n{\n  if (valid_object ())\n    {\n      if (isa (obj_type))\n        return *this;\n      else\n        {\n          gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n          return gh_mgr.get_object (get_parent ()).get_ancestor (obj_type);\n        }\n    }\n  else\n    return graphics_object ();\n}\n\n// ---------------------------------------------------------------------\n\n#include \"graphics-props.cc\"\n\n// ---------------------------------------------------------------------\n\nvoid\nroot_figure::properties::set_callbackobject (const octave_value& v)\n{\n  graphics_handle val (v);\n\n  if (octave::math::isnan (val.value ()))\n    m_callbackobject = graphics_handle ();\n  else if (ishghandle (val))\n    m_callbackobject = val;\n  else\n    err_set_invalid (\"callbackobject\");\n}\n\nvoid\nroot_figure::properties::set_currentfigure (const octave_value& v)\n{\n  graphics_handle val (v);\n\n  if (octave::math::isnan (val.value ()) || ishghandle (val))\n    {\n      m_currentfigure = val;\n\n      if (val.ok ())\n        {\n          gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n          gh_mgr.push_figure (val);\n        }\n    }\n  else\n    err_set_invalid (\"currentfigure\");\n}\n\nvoid\nfigure::properties::set_integerhandle (const octave_value& val)\n{\n  if (m_integerhandle.set (val, true))\n    {\n      bool int_fig_handle = m_integerhandle.is_on ();\n\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object this_go = gh_mgr.get_object (m___myhandle__);\n\n      graphics_handle old_myhandle = m___myhandle__;\n\n      m___myhandle__ = gh_mgr.get_handle (int_fig_handle);\n\n      gh_mgr.renumber_figure (old_myhandle, m___myhandle__);\n\n      graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n      base_properties& props = parent_go.get_properties ();\n\n      props.renumber_child (old_myhandle, m___myhandle__);\n\n      Matrix kids = get_children ();\n\n      for (octave_idx_type i = 0; i < kids.numel (); i++)\n        {\n          graphics_object kid = gh_mgr.get_object (kids(i));\n\n          kid.get_properties ().renumber_parent (m___myhandle__);\n        }\n\n      graphics_handle cf = gh_mgr.current_figure ();\n\n      if (m___myhandle__ == cf)\n        xset (0, \"currentfigure\", m___myhandle__.value ());\n\n      this_go.update (m_integerhandle.get_id ());\n\n      mark_modified ();\n    }\n}\n\n// FIXME: This should update monitorpositions and pointerlocation, but as these\n// properties aren't yet used, it doesn't matter that they aren't set either.\nvoid\nroot_figure::properties::update_units ()\n{\n  std::string xunits = get_units ();\n\n  Matrix scrn_sz = default_screensize ();\n\n  double dpi = get_screenpixelsperinch ();\n\n  if (xunits == \"pixels\")\n    {\n      // Most common case (default).\n      // Don't need to convert anything, but short-circuit if/else tree.\n    }\n  else if (xunits == \"normalized\")\n    {\n      scrn_sz = Matrix (1, 4, 1.0);\n      scrn_sz(0) = 0;\n      scrn_sz(1) = 0;\n    }\n  else if (xunits == \"inches\")\n    {\n      scrn_sz(0) = 0;\n      scrn_sz(1) = 0;\n      scrn_sz(2) /= dpi;\n      scrn_sz(3) /= dpi;\n    }\n  else if (xunits == \"centimeters\")\n    {\n      scrn_sz(0) = 0;\n      scrn_sz(1) = 0;\n      scrn_sz(2) *= 2.54 / dpi;\n      scrn_sz(3) *= 2.54 / dpi;\n    }\n  else if (xunits == \"points\")\n    {\n      scrn_sz(0) = 0;\n      scrn_sz(1) = 0;\n      scrn_sz(2) *= 72 / dpi;\n      scrn_sz(3) *= 72 / dpi;\n    }\n  else if (xunits == \"characters\")\n    {\n      scrn_sz(0) = 0;\n      scrn_sz(1) = 0;\n      // FIXME: this assumes the system font is Helvetica 10pt\n      //        (for which \"x\" requires 6x12 pixels at 74.951 pixels/inch)\n      scrn_sz(2) *= 74.951 / 12.0 / dpi;\n      scrn_sz(3) *= 74.951 / 12.0 / dpi;\n    }\n\n  set_screensize (scrn_sz);\n}\n\nMatrix\nroot_figure::properties::get_boundingbox (bool, const Matrix&) const\n{\n  Matrix screen_size = screen_size_pixels ();\n  Matrix pos = Matrix (1, 4, 0.0);\n\n  pos(2) = screen_size(0);\n  pos(3) = screen_size(1);\n\n  return pos;\n}\n\n/*\n%!test\n%! old_units = get (0, \"units\");\n%! unwind_protect\n%!   set (0, \"units\", \"pixels\");\n%!   sz = get (0, \"screensize\") - [1, 1, 0, 0];\n%!   dpi = get (0, \"screenpixelsperinch\");\n%!   set (0, \"units\", \"inches\");\n%!   assert (get (0, \"screensize\"), sz / dpi, 0.5 / dpi);\n%!   set (0, \"units\", \"centimeters\");\n%!   assert (get (0, \"screensize\"), sz / dpi * 2.54, 0.5 / dpi * 2.54);\n%!   set (0, \"units\", \"points\");\n%!   assert (get (0, \"screensize\"), sz / dpi * 72, 0.5 / dpi * 72);\n%!   set (0, \"units\", \"normalized\");\n%!   assert (get (0, \"screensize\"), [0.0, 0.0, 1.0, 1.0]);\n%!   set (0, \"units\", \"pixels\");\n%!   assert (get (0, \"screensize\"), sz + [1, 1, 0, 0]);\n%!   set (0, \"units\", \"characters\");\n%!   assert (get (0, \"screensize\"),\n%!           sz / dpi * (74.951 / 12.0), 0.5 / dpi * (74.951 / 12.0));\n%! unwind_protect_cleanup\n%!   set (0, \"units\", old_units);\n%! end_unwind_protect\n*/\n\nvoid\nroot_figure::properties::remove_child (const graphics_handle& h, bool)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  gh_mgr.pop_figure (h);\n\n  graphics_handle cf = gh_mgr.current_figure ();\n\n  xset (0, \"currentfigure\", cf.value ());\n\n  base_properties::remove_child (h, true);\n}\n\nvoid\nroot_figure::reset_default_properties ()\n{\n  // empty list of local defaults\n  m_default_properties = property_list ();\n\n  remove_all_listeners ();\n  xreset_default_properties (get_handle (),\n                             m_properties.factory_defaults ());\n}\n\n// ---------------------------------------------------------------------\n\nvoid\nfigure::properties::set_currentaxes (const octave_value& val)\n{\n  graphics_handle hax (val);\n\n  if (octave::math::isnan (hax.value ()) || ishghandle (hax))\n    m_currentaxes = hax;\n  else\n    err_set_invalid (\"currentaxes\");\n}\n\nvoid\nfigure::properties::remove_child (const graphics_handle& h, bool from_root)\n{\n  base_properties::remove_child (h, from_root);\n\n  if (h == m_currentaxes.handle_value ())\n    {\n      graphics_handle new_currentaxes;\n\n      Matrix kids = get_children ();\n\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      for (octave_idx_type i = 0; i < kids.numel (); i++)\n        {\n          graphics_handle kid = kids(i);\n\n          graphics_object go = gh_mgr.get_object (kid);\n\n          if (go.isa (\"axes\"))\n            {\n              new_currentaxes = kid;\n              break;\n            }\n        }\n\n      m_currentaxes = new_currentaxes;\n    }\n}\n\noctave_value\nfigure::properties::get_number () const\n{\n  if (m_integerhandle.is_on ())\n    return m___myhandle__.value ();\n  else\n    return Matrix ();\n}\n\noctave::graphics_toolkit\nfigure::properties::get_toolkit () const\n{\n  return m_toolkit;\n}\n\nvoid\nfigure::properties::set___graphics_toolkit__ (const octave_value& val)\n{\n  if (! val.is_string ())\n    error (\"set___graphics_toolkit__: toolkit must be a string\");\n\n  std::string nm = val.string_value ();\n\n  octave::gtk_manager& gtk_mgr = octave::__get_gtk_manager__ ();\n\n  octave::graphics_toolkit b = gtk_mgr.find_toolkit (nm);\n\n  if (b.get_name () != nm)\n    error (\"set___graphics_toolkit__: invalid graphics toolkit\");\n\n  if (nm != get___graphics_toolkit__ ())\n    {\n      set_toolkit (b);\n      mark_modified ();\n    }\n}\n\nvoid\nfigure::properties::adopt (const graphics_handle& h)\n{\n  base_properties::adopt (h);\n\n  if (! get_currentaxes ().ok ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go = gh_mgr.get_object (h);\n\n      if (go.type () == \"axes\")\n        set_currentaxes (h.as_octave_value ());\n    }\n}\n\n/*\n%!test\n%! hf1 = figure (\"visible\", \"off\");\n%! ax1 = subplot (1,2,1);\n%! ax2 = subplot (1,2,2);\n%! hf2 = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (ax2, \"parent\", hf2);\n%!   assert (get (hf2, \"currentaxes\"), ax2);\n%!   assert (get (hf1, \"currentaxes\"), ax1);\n%!   set (ax1, \"parent\", hf2);\n%!   assert (get (hf2, \"currentaxes\"), ax2);\n%! unwind_protect_cleanup\n%!   close (hf1);\n%!   close (hf2);\n%! end_unwind_protect\n*/\n\nvoid\nfigure::properties::set_visible (const octave_value& val)\n{\n  std::string sval = val.string_value ();\n\n  if (sval == \"on\")\n    xset (0, \"currentfigure\", m___myhandle__.value ());\n\n  m_visible = val;\n}\n\nMatrix\nfigure::properties::get_boundingbox (bool internal, const Matrix&) const\n{\n#if defined (__APPLE__) && defined (__MACH__)\n  // On macOS with Retina display, it looks like we'd need to divide the\n  // \"__device_pixel_ratio__\" (reported by Qt) by the \"backingScaleFactor\":\n  // https://developer.apple.com/documentation/appkit/nswindow/1419459-backingscalefactor\n  // It might also be that we'd need to multiply the screensize (in pixels) by\n  // the \"backingScaleFactor\" instead.\n  // Afaict, that factor is only available via an Objective-C-API.\n  // FIXME: Check how to get that from C++.\n  // As a workaround, assume that we are either on a display prior to Retina\n  // scaling where \"__device_pixel_ratio__\" and \"backingScaleFactor\" are both\n  // 1, or we are on a Retina display where both are probably 2.  The latter\n  // might not always be the case.\n  double dpr = 1.0;\n#else\n  double dpr = get___device_pixel_ratio__ ();\n#endif\n  Matrix screen_size = screen_size_pixels ();\n  Matrix pos = (internal ?\n                get_position ().matrix_value () :\n                get_outerposition ().matrix_value ());\n\n  pos = convert_position (pos, get_units (), \"pixels\", screen_size);\n\n  pos(0)--;\n  pos(1)--;\n  pos(1) = screen_size(1) / dpr - pos(1) - pos(3);\n\n  return pos;\n}\n\nMatrix\nfigure::properties::bbox2position (const Matrix& bb) const\n{\n#if defined (__APPLE__) && defined (__MACH__)\n  // FIXME: See comment in figure::properties::get_boundingbox.\n  double dpr = 1.0;\n#else\n  double dpr = get___device_pixel_ratio__ ();\n#endif\n  Matrix screen_size = screen_size_pixels ();\n  Matrix pos = bb;\n\n  pos(1) = screen_size(1) - (pos(1) + pos(3)) * dpr;\n  pos(1)++;\n  pos(0)++;\n  pos = convert_position (pos, \"pixels\", get_units (), screen_size);\n  return pos;\n}\n\nvoid\nfigure::properties::set_boundingbox (const Matrix& bb, bool internal,\n                                     bool do_notify_toolkit)\n{\n  Matrix pos = bbox2position (bb);\n\n  if (internal)\n    set_position (pos, do_notify_toolkit);\n  else\n    set_outerposition (pos, do_notify_toolkit);\n}\n\nMatrix\nfigure::properties::map_from_boundingbox (double x, double y) const\n{\n  Matrix bb = get_boundingbox (true);\n  Matrix pos (1, 2, 0.0);\n\n  pos(0) = x;\n  pos(1) = y;\n\n  pos(1) = bb(3) - pos(1);\n  pos(0)++;\n  pos = convert_position (pos, \"pixels\", get_units (),\n                          bb.extract_n (0, 2, 1, 2));\n\n  return pos;\n}\n\nMatrix\nfigure::properties::map_to_boundingbox (double x, double y) const\n{\n  Matrix bb = get_boundingbox (true);\n  Matrix pos (1, 2, 0.0);\n\n  pos(0) = x;\n  pos(1) = y;\n\n  pos = convert_position (pos, get_units (), \"pixels\",\n                          bb.extract_n (0, 2, 1, 2));\n  pos(0)--;\n  pos(1) = bb(3) - pos(1);\n\n  return pos;\n}\n\nvoid\nfigure::properties::set_position (const octave_value& v,\n                                  bool do_notify_toolkit)\n{\n  Matrix old_bb, new_bb;\n  bool modified = false;\n\n  old_bb = get_boundingbox (true);\n  modified = m_position.set (v, false, do_notify_toolkit);\n  new_bb = get_boundingbox (true);\n\n  if (old_bb != new_bb)\n    {\n      if (old_bb(2) != new_bb(2) || old_bb(3) != new_bb(3))\n        {\n          gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n          if (! get_resizefcn ().isempty ())\n            gh_mgr.post_callback (m___myhandle__, \"resizefcn\");\n\n          if (! get_sizechangedfcn ().isempty ())\n            gh_mgr.post_callback (m___myhandle__, \"sizechangedfcn\");\n\n          update_boundingbox ();\n        }\n    }\n\n  if (modified)\n    {\n      m_position.run_listeners (GCB_POSTSET);\n      mark_modified ();\n    }\n\n  if (m_paperpositionmode.is (\"auto\"))\n    m_paperposition.set (get_auto_paperposition ());\n}\n\nvoid\nfigure::properties::set_outerposition (const octave_value& v,\n                                       bool do_notify_toolkit)\n{\n  if (m_outerposition.set (v, true, do_notify_toolkit))\n    mark_modified ();\n}\n\nvoid\nfigure::properties::set_paperunits (const octave_value& val)\n{\n  caseless_str punits = val.string_value ();\n  caseless_str ptype = get_papertype ();\n\n  if (punits.compare (\"normalized\") && ptype.compare (\"<custom>\"))\n    error (\"set: can't set paperunits to normalized when papertype is custom\");\n\n  caseless_str old_paperunits = get_paperunits ();\n  if (m_paperunits.set (val, true))\n    {\n      update_paperunits (old_paperunits);\n      mark_modified ();\n    }\n}\n\nvoid\nfigure::properties::set_papertype (const octave_value& val)\n{\n  caseless_str ptype = val.string_value ();\n  caseless_str punits = get_paperunits ();\n\n  if (punits.compare (\"normalized\") && ptype.compare (\"<custom>\"))\n    error (\"set: can't set paperunits to normalized when papertype is custom\");\n\n  if (m_papertype.set (val, true))\n    {\n      update_papertype ();\n      mark_modified ();\n    }\n}\n\nstatic Matrix\npapersize_from_type (const caseless_str punits, const caseless_str ptype)\n{\n  Matrix retval (1, 2, 1.0);\n\n  if (! punits.compare (\"normalized\"))\n    {\n      double in2units;\n      double mm2units;\n\n      if (punits.compare (\"inches\"))\n        {\n          in2units = 1.0;\n          mm2units = 1 / 25.4;\n        }\n      else if (punits.compare (\"centimeters\"))\n        {\n          in2units = 2.54;\n          mm2units = 1 / 10.0;\n        }\n      else // points\n        {\n          in2units = 72.0;\n          mm2units = 72.0 / 25.4;\n        }\n\n      if (ptype.compare (\"usletter\"))\n        {\n          retval(0) = 8.5 * in2units;\n          retval(1) = 11.0 * in2units;\n        }\n      else if (ptype.compare (\"uslegal\"))\n        {\n          retval(0) = 8.5 * in2units;\n          retval(1) = 14.0 * in2units;\n        }\n      else if (ptype.compare (\"tabloid\"))\n        {\n          retval(0) = 11.0 * in2units;\n          retval(1) = 17.0 * in2units;\n        }\n      else if (ptype.compare (\"a0\"))\n        {\n          retval(0) = 841.0 * mm2units;\n          retval(1) = 1189.0 * mm2units;\n        }\n      else if (ptype.compare (\"a1\"))\n        {\n          retval(0) = 594.0 * mm2units;\n          retval(1) = 841.0 * mm2units;\n        }\n      else if (ptype.compare (\"a2\"))\n        {\n          retval(0) = 420.0 * mm2units;\n          retval(1) = 594.0 * mm2units;\n        }\n      else if (ptype.compare (\"a3\"))\n        {\n          retval(0) = 297.0 * mm2units;\n          retval(1) = 420.0 * mm2units;\n        }\n      else if (ptype.compare (\"a4\"))\n        {\n          retval(0) = 210.0 * mm2units;\n          retval(1) = 297.0 * mm2units;\n        }\n      else if (ptype.compare (\"a5\"))\n        {\n          retval(0) = 148.0 * mm2units;\n          retval(1) = 210.0 * mm2units;\n        }\n      else if (ptype.compare (\"b0\"))\n        {\n          retval(0) = 1029.0 * mm2units;\n          retval(1) = 1456.0 * mm2units;\n        }\n      else if (ptype.compare (\"b1\"))\n        {\n          retval(0) = 728.0 * mm2units;\n          retval(1) = 1028.0 * mm2units;\n        }\n      else if (ptype.compare (\"b2\"))\n        {\n          retval(0) = 514.0 * mm2units;\n          retval(1) = 728.0 * mm2units;\n        }\n      else if (ptype.compare (\"b3\"))\n        {\n          retval(0) = 364.0 * mm2units;\n          retval(1) = 514.0 * mm2units;\n        }\n      else if (ptype.compare (\"b4\"))\n        {\n          retval(0) = 257.0 * mm2units;\n          retval(1) = 364.0 * mm2units;\n        }\n      else if (ptype.compare (\"b5\"))\n        {\n          retval(0) = 182.0 * mm2units;\n          retval(1) = 257.0 * mm2units;\n        }\n      else if (ptype.compare (\"arch-a\"))\n        {\n          retval(0) = 9.0 * in2units;\n          retval(1) = 12.0 * in2units;\n        }\n      else if (ptype.compare (\"arch-b\"))\n        {\n          retval(0) = 12.0 * in2units;\n          retval(1) = 18.0 * in2units;\n        }\n      else if (ptype.compare (\"arch-c\"))\n        {\n          retval(0) = 18.0 * in2units;\n          retval(1) = 24.0 * in2units;\n        }\n      else if (ptype.compare (\"arch-d\"))\n        {\n          retval(0) = 24.0 * in2units;\n          retval(1) = 36.0 * in2units;\n        }\n      else if (ptype.compare (\"arch-e\"))\n        {\n          retval(0) = 36.0 * in2units;\n          retval(1) = 48.0 * in2units;\n        }\n      else if (ptype.compare (\"a\"))\n        {\n          retval(0) = 8.5 * in2units;\n          retval(1) = 11.0 * in2units;\n        }\n      else if (ptype.compare (\"b\"))\n        {\n          retval(0) = 11.0 * in2units;\n          retval(1) = 17.0 * in2units;\n        }\n      else if (ptype.compare (\"c\"))\n        {\n          retval(0) = 17.0 * in2units;\n          retval(1) = 22.0 * in2units;\n        }\n      else if (ptype.compare (\"d\"))\n        {\n          retval(0) = 22.0 * in2units;\n          retval(1) = 34.0 * in2units;\n        }\n      else if (ptype.compare (\"e\"))\n        {\n          retval(0) = 34.0 * in2units;\n          retval(1) = 43.0 * in2units;\n        }\n    }\n\n  return retval;\n}\n\nMatrix\nfigure::properties::get_auto_paperposition ()\n{\n  Matrix pos = get_position ().matrix_value ();\n  Matrix sz;\n\n  caseless_str funits = get_units ();\n  caseless_str punits = get_paperunits ();\n\n  // Convert position from figure units to paperunits\n  if (funits == \"normalized\" || punits == \"normalized\")\n    {\n      sz = screen_size_pixels ();\n      pos = convert_position (pos, funits, \"inches\", sz);\n\n      if (punits == \"normalized\")\n        sz = papersize_from_type (\"points\", get_papertype ());\n\n      pos = convert_position (pos, \"inches\", punits, sz);\n    }\n  else\n    pos = convert_position (pos, funits, punits, sz);\n\n  // Center the figure on the page\n  sz = get_papersize ().matrix_value ();\n\n  pos(0) = sz(0)/2 - pos(2)/2;\n  pos(1) = sz(1)/2 - pos(3)/2;\n\n  return pos;\n}\n\n/*\n%!test\n%! hf = figure (\"visible\", \"off\", \"paperpositionmode\", \"auto\");\n%! in_pos = [0 0 4 5];\n%! tol = 20 * eps ();\n%! unwind_protect\n%!   ## paperpositionmode \"auto\" converts figure size to paper units\n%!   set (hf, \"units\", \"inches\");\n%!   set (hf, \"position\", in_pos);\n%!   set (hf, \"paperunits\", \"centimeters\");\n%!   psz = get (hf, \"papersize\");\n%!   fsz = in_pos(3:4) * 2.54;\n%!   pos = [(psz/2 - fsz/2) fsz];\n%!   set (hf, \"paperpositionmode\", \"auto\");\n%!   assert (get (hf, \"paperposition\"), pos, tol);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\", \"paperpositionmode\", \"auto\");\n%! in_pos = [0 0 4 5];\n%! tol = 20 * eps ();\n%! unwind_protect\n%!   ## likewise with normalized units\n%!   set (hf, \"units\", \"inches\");\n%!   set (hf, \"position\", in_pos);\n%!   psz = get (hf, \"papersize\");\n%!   set (hf, \"paperunits\", \"normalized\");\n%!   fsz = in_pos(3:4) ./ psz;\n%!   pos = [([0.5 0.5] - fsz/2) fsz];\n%!   assert (get (hf, \"paperposition\"), pos, tol);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\", \"paperpositionmode\", \"auto\");\n%! in_pos = [0 0 4 5];\n%! tol = 20 * eps ();\n%! unwind_protect\n%!   ## changing papertype updates paperposition\n%!   set (hf, \"units\", \"inches\");\n%!   set (hf, \"position\", in_pos);\n%!   set  (hf, \"papertype\", \"a4\");\n%!   psz = get (hf, \"papersize\");\n%!   fsz = in_pos(3:4);\n%!   pos = [(psz/2 - fsz/2) fsz];\n%!   assert (get (hf, \"paperposition\"), pos, tol);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\", \"paperpositionmode\", \"auto\");\n%! in_pos = [0 0 4 5];\n%! tol = 20 * eps ();\n%! unwind_protect\n%!   ## lanscape updates paperposition\n%!   set (hf, \"units\", \"inches\");\n%!   set (hf, \"position\", in_pos);\n%!   set (hf, \"paperorientation\", \"landscape\");\n%!   psz = get (hf, \"papersize\");\n%!   fsz = in_pos(3:4);\n%!   pos = [(psz/2 - fsz/2) fsz];\n%!   assert (get (hf, \"paperposition\"), pos, tol);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\", \"paperpositionmode\", \"auto\");\n%! in_pos = [0 0 4 5];\n%! unwind_protect\n%!   ## back to manual mode\n%!   set (hf, \"paperposition\", in_pos * 1.1);\n%!   assert (get (hf, \"paperpositionmode\"), \"manual\");\n%!   assert (get (hf, \"paperposition\"), in_pos * 1.1);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\nvoid\nfigure::properties::update_paperunits (const caseless_str& old_paperunits)\n{\n  Matrix pos = get_paperposition ().matrix_value ();\n  Matrix sz = get_papersize ().matrix_value ();\n\n  pos(0) /= sz(0);\n  pos(1) /= sz(1);\n  pos(2) /= sz(0);\n  pos(3) /= sz(1);\n\n  std::string porient = get_paperorientation ();\n  caseless_str punits = get_paperunits ();\n  caseless_str ptype = get_papertype ();\n\n  if (ptype.compare (\"<custom>\"))\n    {\n      if (old_paperunits.compare (\"centimeters\"))\n        {\n          sz(0) /= 2.54;\n          sz(1) /= 2.54;\n        }\n      else if (old_paperunits.compare (\"points\"))\n        {\n          sz(0) /= 72.0;\n          sz(1) /= 72.0;\n        }\n\n      if (punits.compare (\"centimeters\"))\n        {\n          sz(0) *= 2.54;\n          sz(1) *= 2.54;\n        }\n      else if (punits.compare (\"points\"))\n        {\n          sz(0) *= 72.0;\n          sz(1) *= 72.0;\n        }\n    }\n  else\n    {\n      sz = papersize_from_type (punits, ptype);\n      if (porient == \"landscape\")\n        std::swap (sz(0), sz(1));\n    }\n\n  pos(0) *= sz(0);\n  pos(1) *= sz(1);\n  pos(2) *= sz(0);\n  pos(3) *= sz(1);\n\n  m_papersize.set (octave_value (sz));\n  m_paperposition.set (octave_value (pos));\n}\n\nvoid\nfigure::properties::update_papertype ()\n{\n  std::string typ = get_papertype ();\n  if (typ != \"<custom>\")\n    {\n      Matrix sz = papersize_from_type (get_paperunits (), typ);\n      if (get_paperorientation () == \"landscape\")\n        std::swap (sz(0), sz(1));\n      // Call papersize.set rather than set_papersize to avoid loops\n      // between update_papersize and update_papertype.\n      m_papersize.set (octave_value (sz));\n    }\n\n  if (m_paperpositionmode.is (\"auto\"))\n    m_paperposition.set (get_auto_paperposition ());\n}\n\nvoid\nfigure::properties::update_papersize ()\n{\n  Matrix sz = get_papersize ().matrix_value ();\n  if (sz(0) > sz(1))\n    {\n      std::swap (sz(0), sz(1));\n      m_papersize.set (octave_value (sz));\n      m_paperorientation.set (octave_value (\"landscape\"));\n    }\n  else\n    {\n      m_paperorientation.set (\"portrait\");\n    }\n\n  std::string punits = get_paperunits ();\n  if (punits == \"centimeters\")\n    {\n      sz(0) /= 2.54;\n      sz(1) /= 2.54;\n    }\n  else if (punits == \"points\")\n    {\n      sz(0) /= 72.0;\n      sz(1) /= 72.0;\n    }\n  if (punits == \"normalized\")\n    {\n      if (get_papertype () == \"<custom>\")\n        error (\"set: can't set the papertype to <custom> when the paperunits is normalized\");\n    }\n  else\n    {\n      // FIXME: The papersizes info is also in papersize_from_type().\n      //        Both should be rewritten to avoid the duplication.\n      //        Don't Repeat Yourself (DRY) principle.\n      std::string ptype = \"<custom>\";\n      const double mm2in = 1.0 / 25.4;\n      const double tol = 0.01;\n\n      if (std::abs (sz(0) - 8.5) + std::abs (sz(1) - 11.0) < tol)\n        ptype = \"usletter\";\n      else if (std::abs (sz(0) - 8.5) + std::abs (sz(1) - 14.0) < tol)\n        ptype = \"uslegal\";\n      else if (std::abs (sz(0) - 11.0) + std::abs (sz(1) - 17.0) < tol)\n        ptype = \"tabloid\";\n      else if (std::abs (sz(0) - 841.0 * mm2in)\n               + std::abs (sz(1) - 1198.0 * mm2in) < tol)\n        ptype = \"a0\";\n      else if (std::abs (sz(0) - 594.0 * mm2in)\n               + std::abs (sz(1) - 841.0 * mm2in) < tol)\n        ptype = \"a1\";\n      else if (std::abs (sz(0) - 420.0 * mm2in)\n               + std::abs (sz(1) - 594.0 * mm2in) < tol)\n        ptype = \"a2\";\n      else if (std::abs (sz(0) - 297.0 * mm2in)\n               + std::abs (sz(1) - 420.0 * mm2in) < tol)\n        ptype = \"a3\";\n      else if (std::abs (sz(0) - 210.0 * mm2in)\n               + std::abs (sz(1) - 297.0 * mm2in) < tol)\n        ptype = \"a4\";\n      else if (std::abs (sz(0) - 148.0 * mm2in)\n               + std::abs (sz(1) - 210.0 * mm2in) < tol)\n        ptype = \"a5\";\n      else if (std::abs (sz(0) - 1029.0 * mm2in)\n               + std::abs (sz(1) - 1456.0 * mm2in) < tol)\n        ptype = \"b0\";\n      else if (std::abs (sz(0) - 728.0 * mm2in)\n               + std::abs (sz(1) - 1028.0 * mm2in) < tol)\n        ptype = \"b1\";\n      else if (std::abs (sz(0) - 514.0 * mm2in)\n               + std::abs (sz(1) - 728.0 * mm2in) < tol)\n        ptype = \"b2\";\n      else if (std::abs (sz(0) - 364.0 * mm2in)\n               + std::abs (sz(1) - 514.0 * mm2in) < tol)\n        ptype = \"b3\";\n      else if (std::abs (sz(0) - 257.0 * mm2in)\n               + std::abs (sz(1) - 364.0 * mm2in) < tol)\n        ptype = \"b4\";\n      else if (std::abs (sz(0) - 182.0 * mm2in)\n               + std::abs (sz(1) - 257.0 * mm2in) < tol)\n        ptype = \"b5\";\n      else if (std::abs (sz(0) - 9.0)\n               + std::abs (sz(1) - 12.0) < tol)\n        ptype = \"arch-a\";\n      else if (std::abs (sz(0) - 12.0)\n               + std::abs (sz(1) - 18.0) < tol)\n        ptype = \"arch-b\";\n      else if (std::abs (sz(0) - 18.0)\n               + std::abs (sz(1) - 24.0) < tol)\n        ptype = \"arch-c\";\n      else if (std::abs (sz(0) - 24.0)\n               + std::abs (sz(1) - 36.0) < tol)\n        ptype = \"arch-d\";\n      else if (std::abs (sz(0) - 36.0)\n               + std::abs (sz(1) - 48.0) < tol)\n        ptype = \"arch-e\";\n      else if (std::abs (sz(0) - 8.5)\n               + std::abs (sz(1) - 11.0) < tol)\n        ptype = \"a\";\n      else if (std::abs (sz(0) - 11.0)\n               + std::abs (sz(1) - 17.0) < tol)\n        ptype = \"b\";\n      else if (std::abs (sz(0) - 17.0)\n               + std::abs (sz(1) - 22.0) < tol)\n        ptype = \"c\";\n      else if (std::abs (sz(0) - 22.0)\n               + std::abs (sz(1) - 34.0) < tol)\n        ptype = \"d\";\n      else if (std::abs (sz(0) - 34.0)\n               + std::abs (sz(1) - 43.0) < tol)\n        ptype = \"e\";\n      // Call papertype.set rather than set_papertype to avoid loops between\n      // update_papersize and update_papertype\n      m_papertype.set (ptype);\n    }\n  if (punits == \"centimeters\")\n    {\n      sz(0) *= 2.54;\n      sz(1) *= 2.54;\n    }\n  else if (punits == \"points\")\n    {\n      sz(0) *= 72.0;\n      sz(1) *= 72.0;\n    }\n  if (get_paperorientation () == \"landscape\")\n    {\n      std::swap (sz(0), sz(1));\n      m_papersize.set (octave_value (sz));\n    }\n\n  if (m_paperpositionmode.is (\"auto\"))\n    m_paperposition.set (get_auto_paperposition ());\n}\n\n/*\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (hf, \"paperunits\", \"inches\");\n%!   set (hf, \"papersize\", [5, 4]);\n%!   set (hf, \"paperunits\", \"points\");\n%!   assert (get (hf, \"papersize\"), [5, 4] * 72, 1);\n%!   papersize = get (hf, \"papersize\");\n%!   set (hf, \"papersize\", papersize + 1);\n%!   set (hf, \"papersize\", papersize);\n%!   assert (get (hf, \"papersize\"), [5, 4] * 72, 1);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (hf, \"paperunits\", \"inches\");\n%!   set (hf, \"papersize\", [5, 4]);\n%!   set (hf, \"paperunits\", \"centimeters\");\n%!   assert (get (hf, \"papersize\"), [5, 4] * 2.54, 2.54/72);\n%!   papersize = get (hf, \"papersize\");\n%!   set (hf, \"papersize\", papersize + 1);\n%!   set (hf, \"papersize\", papersize);\n%!   assert (get (hf, \"papersize\"), [5, 4] * 2.54, 2.54/72);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\nvoid\nfigure::properties::update_paperorientation ()\n{\n  std::string porient = get_paperorientation ();\n  Matrix sz = get_papersize ().matrix_value ();\n  if ((sz(0) > sz(1) && porient == \"portrait\")\n      || (sz(0) < sz(1) && porient == \"landscape\"))\n    {\n      std::swap (sz(0), sz(1));\n      // Call papertype.set rather than set_papertype to avoid loops\n      // between update_papersize and update_papertype\n      m_papersize.set (octave_value (sz));\n    }\n\n  if (m_paperpositionmode.is (\"auto\"))\n    m_paperposition.set (get_auto_paperposition ());\n}\n\n/*\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   tol = 100 * eps ();\n%!   ## UPPER case and MiXed case is part of test and should not be changed.\n%!   set (hf, \"paperorientation\", \"PORTRAIT\");\n%!   set (hf, \"paperunits\", \"inches\");\n%!   set (hf, \"papertype\", \"USletter\");\n%!   assert (get (hf, \"papersize\"), [8.5, 11.0], tol);\n%!   set (hf, \"paperorientation\", \"Landscape\");\n%!   assert (get (hf, \"papersize\"), [11.0, 8.5], tol);\n%!   set (hf, \"paperunits\", \"centimeters\");\n%!   assert (get (hf, \"papersize\"), [11.0, 8.5] * 2.54, tol);\n%!   set (hf, \"papertype\", \"a4\");\n%!   assert (get (hf, \"papersize\"), [29.7, 21.0], tol);\n%!   set (hf, \"paperunits\", \"inches\", \"papersize\", [8.5, 11.0]);\n%!   assert (get (hf, \"papertype\"), \"usletter\");\n%!   assert (get (hf, \"paperorientation\"), \"portrait\");\n%!   set (hf, \"papersize\", [11.0, 8.5]);\n%!   assert (get (hf, \"papertype\"), \"usletter\");\n%!   assert (get (hf, \"paperorientation\"), \"landscape\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\nvoid\nfigure::properties::set_units (const octave_value& val)\n{\n  caseless_str old_units = get_units ();\n\n  if (m_units.set (val, true))\n    {\n      update_units (old_units);\n      mark_modified ();\n    }\n}\n\nvoid\nfigure::properties::update_units (const caseless_str& old_units)\n{\n  m_position.set (convert_position (get_position ().matrix_value (),\n                                    old_units, get_units (),\n                                    screen_size_pixels ()), false);\n}\n\n/*\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! old_units = get (0, \"units\");\n%! unwind_protect\n%!   set (0, \"units\", \"pixels\");\n%!   rsz = get (0, \"screensize\");\n%!   set (gcf (), \"units\", \"pixels\");\n%!   fsz = get (gcf (), \"position\");\n%!   set (gcf (), \"units\", \"normalized\");\n%!   pos = get (gcf (), \"position\");\n%!   assert (pos, (fsz - [1, 1, 0, 0]) ./ rsz([3, 4, 3, 4]));\n%! unwind_protect_cleanup\n%!   close (hf);\n%!   set (0, \"units\", old_units);\n%! end_unwind_protect\n*/\n\nstd::string\nfigure::properties::get_title () const\n{\n  std::string title;\n  if (! get_number ().isempty () && is_numbertitle ())\n    {\n      std::ostringstream os;\n      std::string nm = get_name ();\n\n      os << \"Figure \" << m___myhandle__.value ();\n      if (! nm.empty ())\n        os << \": \" << get_name ();\n\n      title = os.str ();\n    }\n  else\n    title = get_name ();\n\n  // Qt will use QCoreApplication name (set in main-window.cc)\n  // if the name is empty, so force blank.\n  if (title.empty ())\n    title = \" \";\n\n  return title;\n}\n\noctave_value\nfigure::get_default (const caseless_str& name) const\n{\n  octave_value retval = m_default_properties.lookup (name);\n\n  if (retval.is_undefined ())\n    {\n      graphics_handle parent_h = get_parent ();\n\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object parent_go = gh_mgr.get_object (parent_h);\n\n      retval = parent_go.get_default (name);\n    }\n\n  return retval;\n}\n\nvoid\nfigure::reset_default_properties ()\n{\n  // empty list of local defaults\n  m_default_properties = property_list ();\n  property_list::pval_map_type plist = m_properties.factory_defaults ();\n\n  plist.erase (\"units\");\n  plist.erase (\"position\");\n  plist.erase (\"innerposition\");\n  plist.erase (\"outerposition\");\n  plist.erase (\"paperunits\");\n  plist.erase (\"paperposition\");\n  plist.erase (\"paperpositionmode\");\n  plist.erase (\"windowstyle\");\n\n  remove_all_listeners ();\n  xreset_default_properties (get_handle (), plist);\n}\n\n// ---------------------------------------------------------------------\n\nvoid\naxes::properties::init ()\n{\n  m_position.add_constraint (dim_vector (1, 4));\n  m_outerposition.add_constraint (dim_vector (1, 4));\n  m_tightinset.add_constraint (dim_vector (1, 4));\n  m_looseinset.add_constraint (dim_vector (1, 4));\n  m_colororder.add_constraint (dim_vector (-1, 3));\n  m_dataaspectratio.add_constraint (3);\n  m_dataaspectratio.add_constraint (\"min\", 0, false);\n  m_dataaspectratio.add_constraint (FINITE);\n  m_plotboxaspectratio.add_constraint (3);\n  m_plotboxaspectratio.add_constraint (\"min\", 0, false);\n  m_plotboxaspectratio.add_constraint (FINITE);\n  // FIXME: Should these use dimension vectors?  Currently can set 'xlim' to\n  // any matrix size, but only first two elements are used.\n  m_alim.add_constraint (2);\n  m_alim.add_constraint (NOT_NAN);\n  m_clim.add_constraint (2);\n  m_clim.add_constraint (NOT_NAN);\n  m_xlim.add_constraint (2);\n  m_xlim.add_constraint (NOT_NAN);\n  m_ylim.add_constraint (2);\n  m_ylim.add_constraint (NOT_NAN);\n  m_zlim.add_constraint (2);\n  m_zlim.add_constraint (NOT_NAN);\n  m_xtick.add_constraint (dim_vector (1, -1));\n  m_xtick.add_constraint (FINITE);\n  m_ytick.add_constraint (dim_vector (1, -1));\n  m_ytick.add_constraint (FINITE);\n  m_ztick.add_constraint (dim_vector (1, -1));\n  m_ztick.add_constraint (FINITE);\n  m_ticklength.add_constraint (dim_vector (1, 2));\n  Matrix vw (1, 2, 0);\n  vw(1) = 90;\n  m_view = vw;\n  m_view.add_constraint (dim_vector (1, 2));\n  m_cameraposition.add_constraint (3);\n  m_cameraposition.add_constraint (FINITE);\n  m_cameratarget.add_constraint (3);\n  m_cameratarget.add_constraint (FINITE);\n  Matrix upv (1, 3, 0.0);\n  upv(2) = 1.0;\n  m_cameraupvector = upv;\n  m_cameraupvector.add_constraint (3);\n  m_cameraupvector.add_constraint (FINITE);\n  m_cameraviewangle.add_constraint (FINITE);\n  m_currentpoint.add_constraint (dim_vector (2, 3));\n\n  // Range constraints for double properties\n  m_fontsize.add_constraint (\"min\", 0.0, false);\n  m_gridalpha.add_constraint (\"min\", 0.0, true);\n  m_gridalpha.add_constraint (\"max\", 1.0, true);\n  m_labelfontsizemultiplier.add_constraint (\"min\", 0.0, false);\n  m_linewidth.add_constraint (\"min\", 0.0, false);\n  m_minorgridalpha.add_constraint (\"min\", 0.0, true);\n  m_minorgridalpha.add_constraint (\"max\", 1.0, true);\n  m_titlefontsizemultiplier.add_constraint (\"min\", 0.0, false);\n\n  // No constraints for hidden transform properties\n  update_font ();\n\n  m_x_zlim.resize (1, 2);\n\n  m_sx = \"linear\";\n  m_sy = \"linear\";\n  m_sz = \"linear\";\n\n  calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is (\"log\"),\n                   xaxislocation_is (\"origin\"),\n                   m_yscale.is (\"log\") ? 2 : (yaxislocation_is (\"origin\") ? 0 :\n                       (yaxislocation_is (\"left\") ? -1 : 1)), m_xlim);\n  calc_ticklabels (m_ytick, m_yticklabel, m_yscale.is (\"log\"),\n                   yaxislocation_is (\"origin\"),\n                   m_xscale.is (\"log\") ? 2 : (xaxislocation_is (\"origin\") ? 0 :\n                       (xaxislocation_is (\"bottom\") ? -1 : 1)), m_ylim);\n  calc_ticklabels (m_ztick, m_zticklabel, m_zscale.is (\"log\"),\n                   false, 2, m_zlim);\n\n  xset (m_xlabel.handle_value (), \"handlevisibility\", \"off\");\n  xset (m_ylabel.handle_value (), \"handlevisibility\", \"off\");\n  xset (m_zlabel.handle_value (), \"handlevisibility\", \"off\");\n  xset (m_title.handle_value (), \"handlevisibility\", \"off\");\n\n  xset (m_xlabel.handle_value (), \"horizontalalignment\", \"center\");\n  xset (m_xlabel.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_ylabel.handle_value (), \"horizontalalignment\", \"center\");\n  xset (m_ylabel.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_zlabel.handle_value (), \"horizontalalignment\", \"right\");\n  xset (m_zlabel.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_title.handle_value (), \"horizontalalignment\", \"center\");\n  xset (m_title.handle_value (), \"horizontalalignmentmode\", \"auto\");\n\n  xset (m_xlabel.handle_value (), \"verticalalignment\", \"top\");\n  xset (m_xlabel.handle_value (), \"verticalalignmentmode\", \"auto\");\n  xset (m_ylabel.handle_value (), \"verticalalignment\", \"bottom\");\n  xset (m_ylabel.handle_value (), \"verticalalignmentmode\", \"auto\");\n  xset (m_title.handle_value (), \"verticalalignment\", \"bottom\");\n  xset (m_title.handle_value (), \"verticalalignmentmode\", \"auto\");\n\n  xset (m_ylabel.handle_value (), \"rotation\", 90.0);\n  xset (m_ylabel.handle_value (), \"rotationmode\", \"auto\");\n\n  xset (m_zlabel.handle_value (), \"visible\", \"off\");\n\n  xset (m_xlabel.handle_value (), \"clipping\", \"off\");\n  xset (m_ylabel.handle_value (), \"clipping\", \"off\");\n  xset (m_zlabel.handle_value (), \"clipping\", \"off\");\n  xset (m_title.handle_value (), \"clipping\", \"off\");\n\n  xset (m_xlabel.handle_value (), \"__autopos_tag__\", \"xlabel\");\n  xset (m_ylabel.handle_value (), \"__autopos_tag__\", \"ylabel\");\n  xset (m_zlabel.handle_value (), \"__autopos_tag__\", \"zlabel\");\n  xset (m_title.handle_value (), \"__autopos_tag__\", \"title\");\n\n  double fs = m_labelfontsizemultiplier.double_value () *\n              m_fontsize.double_value ();\n  xset (m_xlabel.handle_value (), \"fontsize\", octave_value (fs));\n  xset (m_ylabel.handle_value (), \"fontsize\", octave_value (fs));\n  xset (m_zlabel.handle_value (), \"fontsize\", octave_value (fs));\n  fs = m_titlefontsizemultiplier.double_value () * m_fontsize.double_value ();\n  xset (m_title.handle_value (), \"fontsize\", octave_value (fs));\n  xset (m_title.handle_value (), \"fontweight\", m_titlefontweight.get ());\n\n  adopt (m_xlabel.handle_value ());\n  adopt (m_ylabel.handle_value ());\n  adopt (m_zlabel.handle_value ());\n  adopt (m_title.handle_value ());\n\n  Matrix tlooseinset = default_axes_position ();\n  tlooseinset(2) = 1-tlooseinset(0)-tlooseinset(2);\n  tlooseinset(3) = 1-tlooseinset(1)-tlooseinset(3);\n  m_looseinset = tlooseinset;\n}\n\n/*\n## Test validation of axes double properties range\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   try\n%!     set (hax, \"linewidth\", -1);\n%!   catch\n%!     err = lasterr ();\n%!   end_try_catch\n%!   assert (err, 'set: \"linewidth\" must be greater than 0');\n%!   try\n%!     set (hax, \"minorgridalpha\", 1.5);\n%!   catch\n%!     err = lasterr ();\n%!   end_try_catch\n%!   assert (err, 'set: \"minorgridalpha\" must be less than or equal to 1');\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n*/\n\nMatrix\naxes::properties::calc_tightbox (const Matrix& init_pos)\n{\n  Matrix pos = init_pos;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get_parent ());\n\n  Matrix parent_bb = go.get_properties ().get_boundingbox (true);\n\n  // FIXME: The layout should be clean at this stage and we should not have to\n  //        update ticks and labels positions here again.  See bug #48718.\n  update_ticklength ();\n\n  Matrix ext = get_extent (true, true);\n  ext(1) = parent_bb(3) - ext(1) - ext(3);\n  ext(0)++;\n  ext(1)++;\n  ext = convert_position (ext, \"pixels\", get_units (),\n                          parent_bb.extract_n (0, 2, 1, 2));\n  if (ext(0) < pos(0))\n    {\n      pos(2) += pos(0)-ext(0);\n      pos(0) = ext(0);\n    }\n  if (ext(0)+ext(2) > pos(0)+pos(2))\n    pos(2) = ext(0)+ext(2)-pos(0);\n\n  if (ext(1) < pos(1))\n    {\n      pos(3) += pos(1)-ext(1);\n      pos(1) = ext(1);\n    }\n  if (ext(1)+ext(3) > pos(1)+pos(3))\n    pos(3) = ext(1)+ext(3)-pos(1);\n\n  return pos;\n}\n\nvoid\naxes::properties::sync_positions ()\n{\n  // First part is equivalent to 'update_tightinset ()'\n  if (m_positionconstraint.is (\"innerposition\"))\n    update_position ();\n  else\n    update_outerposition ();\n  caseless_str old_units = get_units ();\n  set_units (\"normalized\");\n  Matrix pos = m_position.get ().matrix_value ();\n  Matrix outpos = m_outerposition.get ().matrix_value ();\n  Matrix tightpos = calc_tightbox (pos);\n  Matrix tinset (1, 4, 1.0);\n  tinset(0) = pos(0)-tightpos(0);\n  tinset(1) = pos(1)-tightpos(1);\n  tinset(2) = tightpos(0)+tightpos(2)-pos(0)-pos(2);\n  tinset(3) = tightpos(1)+tightpos(3)-pos(1)-pos(3);\n  m_tightinset = tinset;\n  set_units (old_units);\n  update_transform ();\n  if (m_positionconstraint.is (\"innerposition\"))\n    update_position ();\n  else\n    update_outerposition ();\n}\n\n/*\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! hf = figure (\"visible\", \"off\");\n%! graphics_toolkit (hf, \"qt\");\n%! unwind_protect\n%!   subplot (2,1,1); plot (rand (10,1)); subplot (2,1,2); plot (rand (10,1));\n%!   hax = findall (gcf (), \"type\", \"axes\");\n%!   positions = cell2mat (get (hax, \"position\"));\n%!   outerpositions = cell2mat (get (hax, \"outerposition\"));\n%!   looseinsets = cell2mat (get (hax, \"looseinset\"));\n%!   tightinsets = cell2mat (get (hax, \"tightinset\"));\n%!   subplot (2,1,1); plot (rand (10,1)); subplot (2,1,2); plot (rand (10,1));\n%!   hax = findall (gcf (), \"type\", \"axes\");\n%!   assert (cell2mat (get (hax, \"position\")), positions, 1e-4);\n%!   assert (cell2mat (get (hax, \"outerposition\")), outerpositions, 1e-4);\n%!   assert (cell2mat (get (hax, \"looseinset\")), looseinsets, 1e-4);\n%!   assert (cell2mat (get (hax, \"tightinset\")), tightinsets, 1e-4);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! hf = figure (\"visible\", \"off\");\n%! graphics_toolkit (hf, \"qt\");\n%! fpos = get (hf, \"position\");\n%! unwind_protect\n%!   plot (rand (3));\n%!   position = get (gca, \"position\");\n%!   outerposition = get (gca, \"outerposition\");\n%!   looseinset = get (gca, \"looseinset\");\n%!   tightinset = get (gca, \"tightinset\");\n%!   set (hf, \"position\", [fpos(1:2), 2*fpos(3:4)]);\n%!   set (hf, \"position\", fpos);\n%!   assert (get (gca, \"outerposition\"), outerposition, 0.001);\n%!   assert (get (gca, \"position\"), position, 0.001);\n%!   assert (get (gca, \"looseinset\"), looseinset, 0.001);\n%!   assert (get (gca, \"tightinset\"), tightinset, 0.001);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! hf = figure (\"visible\", \"off\");\n%! graphics_toolkit (hf, \"qt\");\n%! fpos = get (hf, \"position\");\n%! set (gca, \"positionconstraint\", \"innerposition\");\n%! unwind_protect\n%!   plot (rand (3));\n%!   position = get (gca, \"position\");\n%!   outerposition = get (gca, \"outerposition\");\n%!   looseinset = get (gca, \"looseinset\");\n%!   tightinset = get (gca, \"tightinset\");\n%!   set (hf, \"position\", [fpos(1:2), 2*fpos(3:4)]);\n%!   set (hf, \"position\", fpos);\n%!   assert (get (gca, \"position\"), position, 0.001);\n%!   assert (get (gca, \"outerposition\"), outerposition, 0.001);\n%!   assert (get (gca, \"looseinset\"), looseinset, 0.001);\n%!   assert (get (gca, \"tightinset\"), tightinset, 0.001);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\nvoid\naxes::properties::set_text_child (handle_property& hp,\n                                  const std::string& who,\n                                  const octave_value& v)\n{\n  if (v.is_string ())\n    {\n      xset (hp.handle_value (), \"string\", v);\n      return;\n    }\n\n  graphics_handle val;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (gh_mgr.lookup (v));\n\n  if (go.isa (\"text\"))\n    val = octave::reparent (v, \"set\", who, m___myhandle__, false);\n  else\n    {\n      std::string cname = v.class_name ();\n\n      error (\"set: expecting text graphics object or character string for %s property, found %s\",\n             who.c_str (), cname.c_str ());\n    }\n\n  xset (val, \"handlevisibility\", \"off\");\n\n  gh_mgr.free (hp.handle_value ());\n\n  hp = val;\n\n  adopt (hp.handle_value ());\n}\n\nvoid\naxes::properties::set_xlabel (const octave_value& v)\n{\n  set_text_child (m_xlabel, \"xlabel\", v);\n  xset (m_xlabel.handle_value (), \"positionmode\", \"auto\");\n  xset (m_xlabel.handle_value (), \"rotationmode\", \"auto\");\n  xset (m_xlabel.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_xlabel.handle_value (), \"verticalalignmentmode\", \"auto\");\n  xset (m_xlabel.handle_value (), \"clipping\", \"off\");\n  xset (m_xlabel.handle_value (), \"color\", get_xcolor ());\n  xset (m_xlabel.handle_value (), \"__autopos_tag__\", \"xlabel\");\n  update_xlabel_position ();\n}\n\nvoid\naxes::properties::set_ylabel (const octave_value& v)\n{\n  set_text_child (m_ylabel, \"ylabel\", v);\n  xset (m_ylabel.handle_value (), \"positionmode\", \"auto\");\n  xset (m_ylabel.handle_value (), \"rotationmode\", \"auto\");\n  xset (m_ylabel.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_ylabel.handle_value (), \"verticalalignmentmode\", \"auto\");\n  xset (m_ylabel.handle_value (), \"clipping\", \"off\");\n  xset (m_ylabel.handle_value (), \"color\", get_ycolor ());\n  xset (m_ylabel.handle_value (), \"__autopos_tag__\", \"ylabel\");\n  update_ylabel_position ();\n}\n\nvoid\naxes::properties::set_zlabel (const octave_value& v)\n{\n  set_text_child (m_zlabel, \"zlabel\", v);\n  xset (m_zlabel.handle_value (), \"positionmode\", \"auto\");\n  xset (m_zlabel.handle_value (), \"rotationmode\", \"auto\");\n  xset (m_zlabel.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_zlabel.handle_value (), \"verticalalignmentmode\", \"auto\");\n  xset (m_zlabel.handle_value (), \"clipping\", \"off\");\n  xset (m_zlabel.handle_value (), \"color\", get_zcolor ());\n  xset (m_zlabel.handle_value (), \"__autopos_tag__\", \"zlabel\");\n  update_zlabel_position ();\n}\n\nvoid\naxes::properties::set_title (const octave_value& v)\n{\n  set_text_child (m_title, \"title\", v);\n  xset (m_title.handle_value (), \"positionmode\", \"auto\");\n  xset (m_title.handle_value (), \"horizontalalignment\", \"center\");\n  xset (m_title.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_title.handle_value (), \"verticalalignment\", \"bottom\");\n  xset (m_title.handle_value (), \"verticalalignmentmode\", \"auto\");\n  xset (m_title.handle_value (), \"clipping\", \"off\");\n  xset (m_title.handle_value (), \"__autopos_tag__\", \"title\");\n  update_title_position ();\n}\n\nvoid\naxes::properties::set_defaults (base_graphics_object& bgo,\n                                const std::string& mode)\n{\n  // FIXME: Should this have all properties in it?\n  // Including ones we do don't implement?\n\n  // FIXME: This function is probably never called without mode == \"reset\".\n  //        Error if this is not true.  If there are reports of problems\n  //        then figure out what code is calling it with the mode set to\n  //        something else.  It's apparently been this way since\n  //        1/6/2017 without any reports.  Maybe we should eliminate the\n  //        mode argument?\n\n  if (mode != \"reset\")\n    error (R\"(axes::properties::set_defaults: expected mode = \"reset\", found \"%s\")\", mode.c_str ());\n\n  Matrix tlim (1, 2, 0.0);\n  tlim(1) = 1;\n  m_alim = tlim;\n  m_clim = tlim;\n  m_xlim = tlim;\n  m_ylim = tlim;\n  m_zlim = tlim;\n\n  m_alimmode = \"auto\";\n  m_climmode = \"auto\";\n  m_xlimmode = \"auto\";\n  m_ylimmode = \"auto\";\n  m_zlimmode = \"auto\";\n\n  m_alphamap = Matrix ();\n  m_alphascale = \"linear\";\n\n  m_ambientlightcolor = Matrix (1, 3, 1.0);\n\n  m_box = \"off\";\n  m_boxstyle = \"back\";\n\n  // Note: camera properties (not mode) will be set in update_transform\n  m_camerapositionmode = \"auto\";\n  m_cameratargetmode = \"auto\";\n  m_cameraupvectormode = \"auto\";\n  m_cameraviewanglemode = \"auto\";\n\n  m_clippingstyle = \"3dbox\";\n\n  m_color = color_values (\"white\");\n  m_colormap = Matrix ();\n  m_colororder = default_colororder ();\n  m_colororderindex = 1.0;\n  m_colorscale = \"linear\";\n\n  // Note: dataspectratio (not mode) will be set through update_aspectratios\n  m_dataaspectratiomode = \"auto\";\n\n  m_fontangle = \"normal\";\n  m_fontname = OCTAVE_DEFAULT_FONTNAME;\n  m_fontsize = 10;\n  m_fontsizemode = \"auto\";\n  m_fontsmoothing = \"on\";\n  m_fontunits = \"points\";\n  m_fontweight = \"normal\";\n\n  m_gridalpha = 0.15;\n  m_gridalphamode = \"auto\";\n  m_gridcolor = color_values (0.15, 0.15, 0.15);\n  m_gridcolormode = \"auto\";\n  m_gridlinestyle = \"-\";\n\n  m_labelfontsizemultiplier = 1.1;\n\n  m_layer = \"bottom\";\n\n  m_linestyleorder = \"-\";\n  m_linestyleorderindex = 1.0;\n\n  m_linewidth = 0.5;\n\n  m_minorgridalpha = 0.25;\n  m_minorgridalphamode = \"auto\";\n  m_minorgridcolor = color_values (0.1, 0.1, 0.1);\n  m_minorgridcolormode = \"auto\";\n  m_minorgridlinestyle = \":\";\n\n  m_nextplot = \"replace\";\n\n  // Note: plotboxaspectratio will be set through update_aspectratios\n  m_plotboxaspectratiomode = \"auto\";\n  m_projection = \"orthographic\";\n\n  m_sortmethod = \"depth\";\n\n  m_tickdir = \"in\";\n  m_tickdirmode = \"auto\";\n  m_ticklabelinterpreter = \"tex\";\n  m_ticklength = default_axes_ticklength ();\n\n  m_tightinset = Matrix (1, 4, 0.0);\n\n  m_titlefontsizemultiplier = 1.1;\n  m_titlefontweight = \"bold\";\n\n  Matrix tview (1, 2, 0.0);\n  tview(1) = 90;\n  m_view = tview;\n\n  m_xaxislocation = \"bottom\";\n\n  m_xcolor = color_values (0.15, 0.15, 0.15);\n  m_xcolormode = \"auto\";\n  m_xdir = \"normal\";\n  m_xgrid = \"off\";\n  m_xlimitmethod = \"tickaligned\";\n  m_xminorgrid = \"off\";\n  m_xminortick = \"off\";\n  m_xminortickvalues = Matrix ();\n  m_xminortickvaluesmode = \"auto\";\n  m_xscale = \"linear\";\n  m_xtick = Matrix ();\n  m_xticklabel = \"\";\n  m_xticklabelmode = \"auto\";\n  m_xticklabelrotation = 0.0;\n  m_xtickmode = \"auto\";\n\n  m_yaxislocation = \"left\";\n\n  m_ycolor = color_values (0.15, 0.15, 0.15);\n  m_ycolormode = \"auto\";\n  m_ydir = \"normal\";\n  m_ygrid = \"off\";\n  m_ylimitmethod = \"tickaligned\";\n  m_yminorgrid = \"off\";\n  m_yminortick = \"off\";\n  m_yminortickvalues = Matrix ();\n  m_yminortickvaluesmode = \"auto\";\n  m_yscale = \"linear\";\n  m_ytick = Matrix ();\n  m_yticklabel = \"\";\n  m_yticklabelmode = \"auto\";\n  m_yticklabelrotation = 0.0;\n  m_ytickmode = \"auto\";\n\n  m_zcolor = color_values (0.15, 0.15, 0.15);\n  m_zcolormode = \"auto\";\n  m_zdir = \"normal\";\n  m_zgrid = \"off\";\n  m_zlimitmethod = \"tickaligned\";\n  m_zminorgrid = \"off\";\n  m_zminortick = \"off\";\n  m_zminortickvalues = Matrix ();\n  m_zminortickvaluesmode = \"auto\";\n  m_zscale = \"linear\";\n  m_ztick = Matrix ();\n  m_zticklabel = \"\";\n  m_zticklabelmode = \"auto\";\n  m_zticklabelrotation = 0.0;\n  m_ztickmode = \"auto\";\n\n  m_sx = \"linear\";\n  m_sy = \"linear\";\n  m_sz = \"linear\";\n\n  m_visible = \"on\";\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (m_xlabel.handle_value ());\n  go.reset_default_properties ();\n  go = gh_mgr.get_object (m_ylabel.handle_value ());\n  go.reset_default_properties ();\n  go = gh_mgr.get_object (m_zlabel.handle_value ());\n  go.reset_default_properties ();\n  go = gh_mgr.get_object (m_title.handle_value ());\n  go.reset_default_properties ();\n\n  xset (m_xlabel.handle_value (), \"handlevisibility\", \"off\");\n  xset (m_ylabel.handle_value (), \"handlevisibility\", \"off\");\n  xset (m_zlabel.handle_value (), \"handlevisibility\", \"off\");\n  xset (m_title.handle_value (), \"handlevisibility\", \"off\");\n\n  xset (m_xlabel.handle_value (), \"horizontalalignment\", \"center\");\n  xset (m_xlabel.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_ylabel.handle_value (), \"horizontalalignment\", \"center\");\n  xset (m_ylabel.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_zlabel.handle_value (), \"horizontalalignment\", \"right\");\n  xset (m_zlabel.handle_value (), \"horizontalalignmentmode\", \"auto\");\n  xset (m_title.handle_value (), \"horizontalalignment\", \"center\");\n  xset (m_title.handle_value (), \"horizontalalignmentmode\", \"auto\");\n\n  xset (m_xlabel.handle_value (), \"verticalalignment\", \"top\");\n  xset (m_xlabel.handle_value (), \"verticalalignmentmode\", \"auto\");\n  xset (m_ylabel.handle_value (), \"verticalalignment\", \"bottom\");\n  xset (m_ylabel.handle_value (), \"verticalalignmentmode\", \"auto\");\n  xset (m_title.handle_value (), \"verticalalignment\", \"bottom\");\n  xset (m_title.handle_value (), \"verticalalignmentmode\", \"auto\");\n\n  xset (m_ylabel.handle_value (), \"rotation\", 90.0);\n  xset (m_ylabel.handle_value (), \"rotationmode\", \"auto\");\n\n  xset (m_zlabel.handle_value (), \"visible\", \"off\");\n\n  xset (m_xlabel.handle_value (), \"clipping\", \"off\");\n  xset (m_ylabel.handle_value (), \"clipping\", \"off\");\n  xset (m_zlabel.handle_value (), \"clipping\", \"off\");\n  xset (m_title.handle_value (), \"clipping\", \"off\");\n\n  xset (m_xlabel.handle_value (), \"__autopos_tag__\", \"xlabel\");\n  xset (m_ylabel.handle_value (), \"__autopos_tag__\", \"ylabel\");\n  xset (m_zlabel.handle_value (), \"__autopos_tag__\", \"zlabel\");\n  xset (m_title.handle_value (), \"__autopos_tag__\", \"title\");\n\n  double fs;\n  fs = m_labelfontsizemultiplier.double_value () * m_fontsize.double_value ();\n  xset (m_xlabel.handle_value (), \"fontsize\", octave_value (fs));\n  xset (m_ylabel.handle_value (), \"fontsize\", octave_value (fs));\n  xset (m_zlabel.handle_value (), \"fontsize\", octave_value (fs));\n  fs = m_titlefontsizemultiplier.double_value () * m_fontsize.double_value ();\n  xset (m_title.handle_value (), \"fontsize\", octave_value (fs));\n  xset (m_title.handle_value (), \"fontweight\", m_titlefontweight.get ());\n\n  update_transform ();\n  sync_positions ();\n  override_defaults (bgo);\n}\n\noctave_value\naxes::properties::get_colormap () const\n{\n  if (m___colormap__.get ().isempty ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go (gh_mgr.get_object (get___myhandle__ ()));\n      graphics_object go_f (go.get_ancestor (\"figure\"));\n      figure::properties& figure_props\n        = reinterpret_cast<figure::properties&> (go_f.get_properties ());\n      return figure_props.get_colormap ();\n    }\n\n  return get___colormap__ ();\n}\n\nvoid\naxes::properties::delete_text_child (handle_property& hp, bool from_root)\n{\n  graphics_handle h = hp.handle_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  if (h.ok ())\n    {\n      graphics_object go = gh_mgr.get_object (h);\n\n      if (go.valid_object ())\n        gh_mgr.free (h, from_root);\n    }\n\n  // FIXME: is it necessary to check whether the axes object is\n  // being deleted now?  I think this function is only called when an\n  // individual child object is delete and not when the parent axes\n  // object is deleted.\n\n  if (! is_beingdeleted ())\n    {\n      hp = gh_mgr.make_graphics_handle (\"text\", m___myhandle__, false, false);\n\n      xset (hp.handle_value (), \"handlevisibility\", \"off\");\n\n      adopt (hp.handle_value ());\n    }\n}\n\nvoid\naxes::properties::remove_child (const graphics_handle& h, bool from_root)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (m_xlabel.handle_value ().ok () && h == m_xlabel.handle_value ())\n    {\n      delete_text_child (m_xlabel, from_root);\n      update_xlabel_position ();\n    }\n  else if (m_ylabel.handle_value ().ok () && h == m_ylabel.handle_value ())\n    {\n      delete_text_child (m_ylabel, from_root);\n      update_ylabel_position ();\n    }\n  else if (m_zlabel.handle_value ().ok () && h == m_zlabel.handle_value ())\n    {\n      delete_text_child (m_zlabel, from_root);\n      update_zlabel_position ();\n    }\n  else if (m_title.handle_value ().ok () && h == m_title.handle_value ())\n    {\n      delete_text_child (m_title, from_root);\n      update_title_position ();\n    }\n  else if (get_num_lights () > 0 && go.isa (\"light\")\n           && go.get_properties ().is_visible ())\n    decrease_num_lights ();\n\n  if (go.valid_object ())\n    base_properties::remove_child (h, from_root);\n\n}\n\nvoid\naxes::properties::update_visible ()\n{\n  xset (m_xlabel.handle_value (), \"visible\",\n        is_visible () ? \"on\" : \"off\");\n  xset (m_ylabel.handle_value (), \"visible\",\n        is_visible () ? \"on\" : \"off\");\n  xset (m_zlabel.handle_value (), \"visible\",\n        (is_visible () && ! m_is2D) ? \"on\" : \"off\");\n}\n\n/*\n## Test visibility of labels\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hx = xlabel (hax, \"X\");\n%!   hy = ylabel (hax, \"Y\");\n%!   hz = zlabel (hax, \"Z\");\n%!   assert (get (hx, \"visible\"), \"on\");\n%!   assert (get (hy, \"visible\"), \"on\");\n%!   assert (get (hz, \"visible\"), \"off\");\n%!   view (3)\n%!   assert (get (hx, \"visible\"), \"on\");\n%!   assert (get (hy, \"visible\"), \"on\");\n%!   assert (get (hz, \"visible\"), \"on\");\n%!   set (hax, \"visible\", \"off\")\n%!   assert (get (hx, \"visible\"), \"off\");\n%!   assert (get (hy, \"visible\"), \"off\");\n%!   assert (get (hz, \"visible\"), \"off\");\n%!   set (hx, \"visible\", \"on\")\n%!   assert (get (hx, \"visible\"), \"on\");\n%!   assert (get (hy, \"visible\"), \"off\");\n%!   assert (get (hz, \"visible\"), \"off\");\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n*/\n\nvoid\naxes::properties::adopt (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go (gh_mgr.get_object (h));\n\n  if (go.isa (\"light\") && go.get_properties ().is_visible ())\n    increase_num_lights ();\n\n  base_properties::adopt (h);\n\n  // FIXME: For performance reasons, we would like to call\n  //          update_axis_limits (\"xlim\", h);\n  //        which updates the limits based ONLY on the new data from h.\n  //        But this isn't working properly at the moment, so we\n  //        call the other form which invokes a full tree traversal of all\n  //        of the axes children.\n  if (xlimmode_is (\"auto\"))\n    update_axis_limits (\"xlim\");\n\n  if (ylimmode_is (\"auto\"))\n    update_axis_limits (\"ylim\");\n\n  if (zlimmode_is (\"auto\"))\n    update_axis_limits (\"zlim\");\n\n  if (climmode_is (\"auto\"))\n    update_axis_limits (\"clim\");\n\n  if (climmode_is (\"auto\"))\n    update_axis_limits (\"alim\");\n}\n\ninline Matrix\nxform_matrix ()\n{\n  Matrix m (4, 4, 0.0);\n\n  for (int i = 0; i < 4; i++)\n    m(i, i) = 1;\n\n  return m;\n}\n\ninline ColumnVector\nxform_vector ()\n{\n  ColumnVector v (4, 0.0);\n\n  v(3) = 1;\n\n  return v;\n}\n\ninline ColumnVector\nxform_vector (double x, double y, double z)\n{\n  ColumnVector v (4, 1.0);\n\n  v(0) = x;\n  v(1) = y;\n  v(2) = z;\n\n  return v;\n}\n\ninline ColumnVector\ntransform (const Matrix& m, double x, double y, double z)\n{\n  return (m * xform_vector (x, y, z));\n}\n\ninline Matrix\nxform_scale (double x, double y, double z)\n{\n  Matrix m (4, 4, 0.0);\n\n  m(0, 0) = x;\n  m(1, 1) = y;\n  m(2, 2) = z;\n  m(3, 3) = 1;\n\n  return m;\n}\n\ninline Matrix\nxform_translate (double x, double y, double z)\n{\n  Matrix m = xform_matrix ();\n\n  m(0, 3) = x;\n  m(1, 3) = y;\n  m(2, 3) = z;\n  m(3, 3) = 1;\n\n  return m;\n}\n\ninline void\nscale (Matrix& m, double x, double y, double z)\n{\n  m = m * xform_scale (x, y, z);\n}\n\ninline void\ntranslate (Matrix& m, double x, double y, double z)\n{\n  m = m * xform_translate (x, y, z);\n}\n\ninline void\nxform (ColumnVector& v, const Matrix& m)\n{\n  v = m * v;\n}\n\ninline void\nscale (ColumnVector& v, double x, double y, double z)\n{\n  v(0) *= x;\n  v(1) *= y;\n  v(2) *= z;\n}\n\ninline void\ntranslate (ColumnVector& v, double x, double y, double z)\n{\n  v(0) += x;\n  v(1) += y;\n  v(2) += z;\n}\n\ninline void\nnormalize (ColumnVector& v)\n{\n  double fact = 1.0 / sqrt (v(0)*v(0)+v(1)*v(1)+v(2)*v(2));\n  scale (v, fact, fact, fact);\n}\n\ninline double\ndot (const ColumnVector& v1, const ColumnVector& v2)\n{\n  return (v1(0)*v2(0)+v1(1)*v2(1)+v1(2)*v2(2));\n}\n\ninline double\nnorm (const ColumnVector& v)\n{\n  return sqrt (dot (v, v));\n}\n\ninline ColumnVector\ncross (const ColumnVector& v1, const ColumnVector& v2)\n{\n  ColumnVector r = xform_vector ();\n\n  r(0) = v1(1)*v2(2) - v1(2)*v2(1);\n  r(1) = v1(2)*v2(0) - v1(0)*v2(2);\n  r(2) = v1(0)*v2(1) - v1(1)*v2(0);\n\n  return r;\n}\n\ninline Matrix\nunit_cube ()\n{\n  static double data[32] =\n  {\n    0, 0, 0, 1,\n    1, 0, 0, 1,\n    0, 1, 0, 1,\n    0, 0, 1, 1,\n    1, 1, 0, 1,\n    1, 0, 1, 1,\n    0, 1, 1, 1,\n    1, 1, 1, 1\n  };\n  Matrix m (4, 8);\n\n  memcpy (m.rwdata (), data, sizeof (double)*32);\n\n  return m;\n}\n\ninline ColumnVector\ncam2xform (const Array<double>& m)\n{\n  ColumnVector retval (4, 1.0);\n\n  memcpy (retval.rwdata (), m.data (), sizeof (double)*3);\n\n  return retval;\n}\n\ninline RowVector\nxform2cam (const ColumnVector& v)\n{\n  return v.extract_n (0, 3).transpose ();\n}\n\nvoid\naxes::properties::update_camera ()\n{\n  double xd = (xdir_is (\"normal\") ? 1 : -1);\n  double yd = (ydir_is (\"normal\") ? 1 : -1);\n  double zd = (zdir_is (\"normal\") ? 1 : -1);\n\n  Matrix xlimits = m_sx.scale (get_xlim ().matrix_value ());\n  Matrix ylimits = m_sy.scale (get_ylim ().matrix_value ());\n  Matrix zlimits = m_sz.scale (get_zlim ().matrix_value ());\n\n  double xo = xlimits(xd > 0 ? 0 : 1);\n  double yo = ylimits(yd > 0 ? 0 : 1);\n  double zo = zlimits(zd > 0 ? 0 : 1);\n\n  Matrix pb = get_plotboxaspectratio ().matrix_value ();\n\n  bool autocam = (camerapositionmode_is (\"auto\")\n                  && cameratargetmode_is (\"auto\")\n                  && cameraupvectormode_is (\"auto\")\n                  && cameraviewanglemode_is (\"auto\"));\n  bool dowarp = (autocam && dataaspectratiomode_is (\"auto\")\n                 && plotboxaspectratiomode_is (\"auto\"));\n\n  ColumnVector c_eye (xform_vector ());\n  ColumnVector c_center (xform_vector ());\n  ColumnVector c_upv (xform_vector ());\n\n  if (cameratargetmode_is (\"auto\"))\n    {\n      c_center(0) = (xlimits(0) + xlimits(1)) / 2;\n      c_center(1) = (ylimits(0) + ylimits(1)) / 2;\n      c_center(2) = (zlimits(0) + zlimits(1)) / 2;\n\n      m_cameratarget = xform2cam (c_center);\n    }\n  else\n    c_center = cam2xform (get_cameratarget ().matrix_value ());\n\n  if (camerapositionmode_is (\"auto\"))\n    {\n      Matrix tview = get_view ().matrix_value ();\n      double az = tview(0);\n      double el = tview(1);\n      double d = 5 * sqrt (pb(0)*pb(0) + pb(1)*pb(1) + pb(2)*pb(2));\n\n      if (el == 90 || el == -90)\n        c_eye(2) = d*octave::math::signum (el);\n      else\n        {\n          az *= M_PI/180.0;\n          el *= M_PI/180.0;\n          c_eye(0) = d * cos (el) * sin (az);\n          c_eye(1) = -d* cos (el) * cos (az);\n          c_eye(2) = d * sin (el);\n        }\n      c_eye(0) = c_eye(0)*(xlimits(1)-xlimits(0))/(xd*pb(0))+c_center(0);\n      c_eye(1) = c_eye(1)*(ylimits(1)-ylimits(0))/(yd*pb(1))+c_center(1);\n      c_eye(2) = c_eye(2)*(zlimits(1)-zlimits(0))/(zd*pb(2))+c_center(2);\n\n      m_cameraposition = xform2cam (c_eye);\n    }\n  else\n    c_eye = cam2xform (get_cameraposition ().matrix_value ());\n\n  if (cameraupvectormode_is (\"auto\"))\n    {\n      Matrix tview = get_view ().matrix_value ();\n      double az = tview(0);\n      double el = tview(1);\n\n      if (el == 90 || el == -90)\n        {\n          c_upv(0) = -octave::math::signum (el)\n                     * sin (az*M_PI/180.0)*(xlimits(1)-xlimits(0))/pb(0);\n          c_upv(1) = octave::math::signum (el)\n                     * cos (az*M_PI/180.0)*(ylimits(1)-ylimits(0))/pb(1);\n        }\n      else\n        c_upv(2) = 1;\n\n      m_cameraupvector = xform2cam (c_upv);\n    }\n  else\n    c_upv = cam2xform (get_cameraupvector ().matrix_value ());\n\n  Matrix x_view = xform_matrix ();\n  Matrix x_projection = xform_matrix ();\n  Matrix x_viewport = xform_matrix ();\n  Matrix x_normrender;\n  Matrix x_pre = xform_matrix ();\n\n  m_x_render = xform_matrix ();\n  m_x_render_inv = xform_matrix ();\n\n  scale (x_pre, pb(0), pb(1), pb(2));\n  translate (x_pre, -0.5, -0.5, -0.5);\n  scale (x_pre, xd/(xlimits(1)-xlimits(0)), yd/(ylimits(1)-ylimits(0)),\n         zd/(zlimits(1)-zlimits(0)));\n  translate (x_pre, -xo, -yo, -zo);\n\n  xform (c_eye, x_pre);\n  xform (c_center, x_pre);\n  scale (c_upv, pb(0)/(xlimits(1)-xlimits(0)), pb(1)/(ylimits(1)-ylimits(0)),\n         pb(2)/(zlimits(1)-zlimits(0)));\n  translate (c_center, -c_eye(0), -c_eye(1), -c_eye(2));\n\n  ColumnVector F (c_center), f (F), UP (c_upv);\n  normalize (f);\n  normalize (UP);\n\n  if (std::abs (dot (f, UP)) > 1e-15)\n    {\n      double fa = 1 / sqrt (1 - f(2)*f(2));\n      scale (UP, fa, fa, fa);\n    }\n\n  ColumnVector s = cross (f, UP);\n  ColumnVector u = cross (s, f);\n\n  scale (x_view, 1, 1, -1);\n  Matrix l = xform_matrix ();\n  l(0, 0) = s(0); l(0, 1) = s(1); l(0, 2) = s(2);\n  l(1, 0) = u(0); l(1, 1) = u(1); l(1, 2) = u(2);\n  l(2, 0) = -f(0); l(2, 1) = -f(1); l(2, 2) = -f(2);\n  x_view = x_view * l;\n  translate (x_view, -c_eye(0), -c_eye(1), -c_eye(2));\n  scale (x_view, pb(0), pb(1), pb(2));\n  translate (x_view, -0.5, -0.5, -0.5);\n\n  Matrix x_cube = x_view * unit_cube ();\n  ColumnVector cmin = x_cube.row_min ();\n  ColumnVector cmax = x_cube.row_max ();\n  double xM = cmax(0) - cmin(0);\n  double yM = cmax(1) - cmin(1);\n\n  Matrix bb = get_boundingbox (true);\n\n  double v_angle;\n\n  if (cameraviewanglemode_is (\"auto\"))\n    {\n      double af;\n\n      // FIXME: was this really needed?  When compared to Matlab, it\n      // does not seem to be required.  Need investigation with concrete\n      // graphics toolkit to see results visually.\n      if (false && dowarp)\n        af = (1.0 / (xM > yM ? xM : yM));\n      else\n        {\n          if ((bb(2)/bb(3)) > (xM/yM))\n            af = 1.0 / yM;\n          else\n            af = 1.0 / xM;\n        }\n      v_angle = 2 * (180.0 / M_PI) * atan (1 / (2 * af * norm (F)));\n\n      m_cameraviewangle = v_angle;\n    }\n  else\n    v_angle = get_cameraviewangle ();\n\n  double pf = 1 / (2 * tan ((v_angle / 2) * M_PI / 180.0) * norm (F));\n  scale (x_projection, pf, pf, 1);\n\n  if (dowarp)\n    {\n      xM *= pf;\n      yM *= pf;\n      translate (x_viewport, bb(0)+bb(2)/2, bb(1)+bb(3)/2, 0);\n      scale (x_viewport, bb(2)/xM, -bb(3)/yM, 1);\n    }\n  else\n    {\n      double pix = 1;\n      if (autocam)\n        {\n          if ((bb(2)/bb(3)) > (xM/yM))\n            pix = bb(3);\n          else\n            pix = bb(2);\n        }\n      else\n        pix = (bb(2) < bb(3) ? bb(2) : bb(3));\n      translate (x_viewport, bb(0)+bb(2)/2, bb(1)+bb(3)/2, 0);\n      scale (x_viewport, pix, -pix, 1);\n    }\n\n  x_normrender = x_viewport * x_projection * x_view;\n\n  x_cube = x_normrender * unit_cube ();\n  cmin = x_cube.row_min ();\n  cmax = x_cube.row_max ();\n  m_x_zlim.resize (1, 2);\n  m_x_zlim(0) = cmin(2);\n  m_x_zlim(1) = cmax(2);\n\n  m_x_render = x_normrender;\n  scale (m_x_render, xd/(xlimits(1)-xlimits(0)), yd/(ylimits(1)-ylimits(0)),\n         zd/(zlimits(1)-zlimits(0)));\n  translate (m_x_render, -xo, -yo, -zo);\n\n  m_x_render_inv = m_x_render.inverse ();\n\n  // Note: these matrices are a slight modified version of the regular matrices,\n  // more suited for OpenGL rendering (m_x_gl_mat1 => light => m_x_gl_mat2)\n  m_x_gl_mat1 = x_view;\n  scale (m_x_gl_mat1, xd/(xlimits(1)-xlimits(0)), yd/(ylimits(1)-ylimits(0)),\n         zd/(zlimits(1)-zlimits(0)));\n  translate (m_x_gl_mat1, -xo, -yo, -zo);\n  m_x_gl_mat2 = x_viewport * x_projection;\n}\n\nstatic bool updating_axes_layout = false;\n\nvoid\naxes::properties::update_axes_layout ()\n{\n  if (updating_axes_layout)\n    return;\n\n  graphics_xform xform = get_transform ();\n\n  double xd = (xdir_is (\"normal\") ? 1 : -1);\n  double yd = (ydir_is (\"normal\") ? 1 : -1);\n  double zd = (zdir_is (\"normal\") ? 1 : -1);\n\n  const Matrix xlims = xform.xscale (get_xlim ().matrix_value ());\n  const Matrix ylims = xform.yscale (get_ylim ().matrix_value ());\n  const Matrix zlims = xform.zscale (get_zlim ().matrix_value ());\n\n  double x_min, x_max, y_min, y_max, z_min, z_max;\n  x_min = xlims(0), x_max = xlims(1);\n  y_min = ylims(0), y_max = ylims(1);\n  z_min = zlims(0), z_max = zlims(1);\n\n  ColumnVector p1, p2, dir (3);\n\n  m_xstate = m_ystate = m_zstate = AXE_ANY_DIR;\n\n  p1 = xform.transform (x_min, (y_min+y_max)/2, (z_min+z_max)/2, false);\n  p2 = xform.transform (x_max, (y_min+y_max)/2, (z_min+z_max)/2, false);\n  dir(0) = octave::math::round (p2(0) - p1(0));\n  dir(1) = octave::math::round (p2(1) - p1(1));\n  dir(2) = (p2(2) - p1(2));\n  if (dir(0) == 0 && dir(1) == 0)\n    m_xstate = AXE_DEPTH_DIR;\n  else if (dir(2) == 0)\n    {\n      if (dir(0) == 0)\n        m_xstate = AXE_VERT_DIR;\n      else if (dir(1) == 0)\n        m_xstate = AXE_HORZ_DIR;\n    }\n\n  if (dir(2) == 0)\n    {\n      if (dir(1) == 0)\n        m_xPlane = (dir(0) > 0 ? x_max : x_min);\n      else\n        m_xPlane = (dir(1) < 0 ? x_max : x_min);\n    }\n  else\n    m_xPlane = (dir(2) < 0 ? x_min : x_max);\n\n  m_xPlaneN = (m_xPlane == x_min ? x_max : x_min);\n  m_fx = (x_max - x_min) / sqrt (dir(0)*dir(0) + dir(1)*dir(1));\n\n  p1 = xform.transform ((x_min + x_max)/2, y_min, (z_min + z_max)/2, false);\n  p2 = xform.transform ((x_min + x_max)/2, y_max, (z_min + z_max)/2, false);\n  dir(0) = octave::math::round (p2(0) - p1(0));\n  dir(1) = octave::math::round (p2(1) - p1(1));\n  dir(2) = (p2(2) - p1(2));\n  if (dir(0) == 0 && dir(1) == 0)\n    m_ystate = AXE_DEPTH_DIR;\n  else if (dir(2) == 0)\n    {\n      if (dir(0) == 0)\n        m_ystate = AXE_VERT_DIR;\n      else if (dir(1) == 0)\n        m_ystate = AXE_HORZ_DIR;\n    }\n\n  if (dir(2) == 0)\n    {\n      if (dir(1) == 0)\n        m_yPlane = (dir(0) > 0 ? y_max : y_min);\n      else\n        m_yPlane = (dir(1) < 0 ? y_max : y_min);\n    }\n  else\n    m_yPlane = (dir(2) < 0 ? y_min : y_max);\n\n  m_yPlaneN = (m_yPlane == y_min ? y_max : y_min);\n  m_fy = (y_max - y_min) / sqrt (dir(0)*dir(0) + dir(1)*dir(1));\n\n  p1 = xform.transform ((x_min + x_max)/2, (y_min + y_max)/2, z_min, false);\n  p2 = xform.transform ((x_min + x_max)/2, (y_min + y_max)/2, z_max, false);\n  dir(0) = octave::math::round (p2(0) - p1(0));\n  dir(1) = octave::math::round (p2(1) - p1(1));\n  dir(2) = (p2(2) - p1(2));\n  if (dir(0) == 0 && dir(1) == 0)\n    m_zstate = AXE_DEPTH_DIR;\n  else if (dir(2) == 0)\n    {\n      if (dir(0) == 0)\n        m_zstate = AXE_VERT_DIR;\n      else if (dir(1) == 0)\n        m_zstate = AXE_HORZ_DIR;\n    }\n\n  if (dir(2) == 0)\n    {\n      if (dir(1) == 0)\n        m_zPlane = (dir(0) > 0 ? z_min : z_max);\n      else\n        m_zPlane = (dir(1) < 0 ? z_min : z_max);\n    }\n  else\n    m_zPlane = (dir(2) < 0 ? z_min : z_max);\n\n  m_zPlaneN = (m_zPlane == z_min ? z_max : z_min);\n  m_fz = (z_max - z_min) / sqrt (dir(0)*dir(0) + dir(1)*dir(1));\n\n  octave::unwind_protect_var<bool> restore_var (updating_axes_layout, true);\n\n  m_xySym = (xd*yd*(m_xPlane-m_xPlaneN)*(m_yPlane-m_yPlaneN) > 0);\n  m_zSign = (zd*(m_zPlane-m_zPlaneN) <= 0);\n  m_xyzSym = (m_zSign ? m_xySym : ! m_xySym);\n  m_xpTick = (m_zSign ? m_xPlaneN : m_xPlane);\n  m_ypTick = (m_zSign ? m_yPlaneN : m_yPlane);\n  m_zpTick = (m_zSign ? m_zPlane : m_zPlaneN);\n  m_xpTickN = (m_zSign ? m_xPlane : m_xPlaneN);\n  m_ypTickN = (m_zSign ? m_yPlane : m_yPlaneN);\n  m_zpTickN = (m_zSign ? m_zPlaneN : m_zPlane);\n\n  // 2-D mode\n  m_x2Dtop = false;\n  m_y2Dright = false;\n  m_layer2Dtop = false;\n  if (m_xstate == AXE_HORZ_DIR && m_ystate == AXE_VERT_DIR)\n    {\n      Matrix ylimits = get_ylim ().matrix_value ();\n      if (xaxislocation_is (\"top\")\n          || (yscale_is (\"log\") && xaxislocation_is (\"origin\")\n              && (ylimits(1) < 0.)))\n        {\n          std::swap (m_yPlane, m_yPlaneN);\n          m_x2Dtop = true;\n        }\n      m_ypTick = m_yPlaneN;\n      m_ypTickN = m_yPlane;\n      Matrix xlimits = get_xlim ().matrix_value ();\n      if (yaxislocation_is (\"right\")\n          || (xscale_is (\"log\") && yaxislocation_is (\"origin\")\n              && (xlimits(1) < 0.)))\n        {\n          std::swap (m_xPlane, m_xPlaneN);\n          m_y2Dright = true;\n        }\n      m_xpTick = m_xPlaneN;\n      m_xpTickN = m_xPlane;\n      if (layer_is (\"top\"))\n        {\n          m_zpTick = m_zPlaneN;\n          m_layer2Dtop = true;\n        }\n      else\n        m_zpTick = m_zPlane;\n    }\n\n  Matrix viewmat = get_view ().matrix_value ();\n  m_nearhoriz = std::abs (viewmat(1)) <= 5;\n\n  bool saved_is_2D = m_is2D;\n  m_is2D = viewmat(1) == 90;\n\n  if (m_is2D != saved_is_2D)\n    update_visible ();\n  \n  update_ticklength ();\n}\n\nvoid\naxes::properties::update_ticklength ()\n{\n  bool mode2D = (((m_xstate > AXE_DEPTH_DIR ? 1 : 0) +\n                  (m_ystate > AXE_DEPTH_DIR ? 1 : 0) +\n                  (m_zstate > AXE_DEPTH_DIR ? 1 : 0)) == 2);\n\n  if (tickdirmode_is (\"auto\"))\n    m_tickdir.set (mode2D ? \"in\" : \"out\", true);\n\n  double ticksign;\n  std::string tickdir = get_tickdir ();\n  if (tickdir == \"in\")\n    ticksign = -1;\n  else if (tickdir == \"out\")\n    ticksign = 1;\n  else if (tickdir == \"both\")\n    ticksign = 1;\n  else  // tickdir == \"none\"\n    ticksign = 0;\n\n  Matrix bbox = get_boundingbox (true);\n  Matrix ticklen = get_ticklength ().matrix_value ();\n  ticklen(0) *= std::max (bbox(2), bbox(3));\n  // FIXME: This algorithm is not Matlab-compatible.  See bug #55483.\n  //        Scale the results of Octave's algorithm for better visuals.\n  ticklen(1) *= (0.76 * std::max (bbox(2), bbox(3)));\n\n  m_xticklen = ticksign * (mode2D ? ticklen(0) : ticklen(1));\n  m_yticklen = ticksign * (mode2D ? ticklen(0) : ticklen(1));\n  m_zticklen = ticksign * (mode2D ? ticklen(0) : ticklen(1));\n\n  double offset = get___fontsize_points__ () / 2;\n\n  m_xtickoffset = (mode2D ? std::max (0., m_xticklen) : std::abs (m_xticklen)) +\n                  (m_xstate == AXE_HORZ_DIR ? offset*1.5 : offset);\n  m_ytickoffset = (mode2D ? std::max (0., m_yticklen) : std::abs (m_yticklen)) +\n                  (m_ystate == AXE_HORZ_DIR ? offset*1.5 : offset);\n  m_ztickoffset = (mode2D ? std::max (0., m_zticklen) : std::abs (m_zticklen)) +\n                  (m_zstate == AXE_HORZ_DIR ? offset*1.5 : offset);\n\n  update_xlabel_position ();\n  update_ylabel_position ();\n  update_zlabel_position ();\n  update_title_position ();\n}\n\n/*\n## FIXME: A demo can't be called in a C++ file.  This should be made a test\n## or moved to a .m file where it can be called.\n%!demo\n%! clf;\n%! subplot (2,1,1);\n%!  plot (rand (3));\n%!  xlabel xlabel;\n%!  ylabel ylabel;\n%!  title title;\n%! subplot (2,1,2);\n%!  plot (rand (3));\n%!  set (gca, \"ticklength\", get (gca, \"ticklength\") * 2, \"tickdir\", \"out\");\n%!  xlabel xlabel;\n%!  ylabel ylabel;\n%!  title title;\n*/\n\nstatic ColumnVector\nconvert_label_position (const ColumnVector& p,\n                        const text::properties& props,\n                        const graphics_xform& xform,\n                        const Matrix& bbox)\n{\n  ColumnVector retval;\n\n  std::string to_units = props.get_units ();\n\n  if (to_units != \"data\")\n    {\n      ColumnVector v = xform.transform (p(0), p(1), p(2));\n\n      retval.resize (3);\n\n      retval(0) = v(0) - bbox(0) + 1;\n      retval(1) = bbox(1) + bbox(3) - v(1) + 1;\n      retval(2) = 0;\n\n      retval = convert_position (retval, \"pixels\", to_units,\n                                 bbox.extract_n (0, 2, 1, 2));\n    }\n  else\n    retval = p;\n\n  return retval;\n}\n\nstatic bool updating_xlabel_position = false;\n\nvoid\naxes::properties::update_xlabel_position ()\n{\n  if (updating_xlabel_position)\n    return;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get_xlabel ());\n\n  if (! go.valid_object ())\n    return;\n\n  text::properties& xlabel_props\n    = reinterpret_cast<text::properties&> (go.get_properties ());\n\n  bool isempty = xlabel_props.get_string ().isempty ();\n\n  octave::unwind_protect_var<bool>\n  restore_var (updating_xlabel_position, true);\n\n  if (! isempty)\n    {\n      if (xlabel_props.horizontalalignmentmode_is (\"auto\"))\n        {\n          xlabel_props.set_horizontalalignment\n          (m_xstate > AXE_DEPTH_DIR ? \"center\"\n           : (m_xyzSym ? \"left\" : \"right\"));\n\n          xlabel_props.set_horizontalalignmentmode (\"auto\");\n        }\n\n      if (xlabel_props.verticalalignmentmode_is (\"auto\"))\n        {\n          xlabel_props.set_verticalalignment\n          (m_xstate == AXE_VERT_DIR || m_x2Dtop ? \"bottom\" : \"top\");\n\n          xlabel_props.set_verticalalignmentmode (\"auto\");\n        }\n    }\n\n  if (xlabel_props.positionmode_is (\"auto\")\n      || xlabel_props.rotationmode_is (\"auto\"))\n    {\n      graphics_xform xform = get_transform ();\n\n      Matrix ext (1, 2, 0.0);\n      ext = get_ticklabel_extents (get_xtick ().matrix_value (),\n                                   get_xticklabel ().string_vector_value (),\n                                   get_xlim ().matrix_value ());\n\n      double margin = 5;\n      double wmax = ext(0) + margin;\n      double hmax = ext(1) + margin;\n      double angle = 0.0;\n      ColumnVector p\n        = graphics_xform::xform_vector ((m_xpTickN + m_xpTick)/2, m_ypTick, m_zpTick);\n\n      bool tick_along_z = m_nearhoriz || octave::math::isinf (m_fy);\n      if (tick_along_z)\n        p(2) += (octave::math::signum (m_zpTick - m_zpTickN) * m_fz * m_xtickoffset);\n      else\n        p(1) += (octave::math::signum (m_ypTick - m_ypTickN) * m_fy * m_xtickoffset);\n\n      p = xform.transform (p(0), p(1), p(2), false);\n\n      switch (m_xstate)\n        {\n        case AXE_ANY_DIR:\n          p(0) += (m_xyzSym ? wmax : -wmax);\n          p(1) += hmax;\n          break;\n\n        case AXE_VERT_DIR:\n          p(0) -= wmax;\n          angle = 90;\n          break;\n\n        case AXE_HORZ_DIR:\n          p(1) += (m_x2Dtop ? -hmax : hmax);\n          break;\n        }\n\n      if (xlabel_props.positionmode_is (\"auto\"))\n        {\n          p = xform.untransform (p(0), p(1), p(2), true);\n\n          p = convert_label_position (p, xlabel_props, xform,\n                                      get_extent (false));\n\n          xlabel_props.set_position (p.extract_n (0, 3).transpose ());\n          xlabel_props.set_positionmode (\"auto\");\n        }\n\n      if (! isempty && xlabel_props.rotationmode_is (\"auto\"))\n        {\n          xlabel_props.set_rotation (angle);\n          xlabel_props.set_rotationmode (\"auto\");\n        }\n    }\n}\n\nstatic bool updating_ylabel_position = false;\n\nvoid\naxes::properties::update_ylabel_position ()\n{\n  if (updating_ylabel_position)\n    return;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get_ylabel ());\n\n  if (! go.valid_object ())\n    return;\n\n  text::properties& ylabel_props\n    = reinterpret_cast<text::properties&> (go.get_properties ());\n\n  bool isempty = ylabel_props.get_string ().isempty ();\n\n  octave::unwind_protect_var<bool>\n  restore_var (updating_ylabel_position, true);\n\n  if (! isempty)\n    {\n      if (ylabel_props.horizontalalignmentmode_is (\"auto\"))\n        {\n          ylabel_props.set_horizontalalignment\n          (m_ystate > AXE_DEPTH_DIR ? \"center\"\n           : (! m_xyzSym ? \"left\" : \"right\"));\n\n          ylabel_props.set_horizontalalignmentmode (\"auto\");\n        }\n\n      if (ylabel_props.verticalalignmentmode_is (\"auto\"))\n        {\n          ylabel_props.set_verticalalignment\n          (m_ystate == AXE_VERT_DIR && ! m_y2Dright ? \"bottom\" : \"top\");\n\n          ylabel_props.set_verticalalignmentmode (\"auto\");\n        }\n    }\n\n  if (ylabel_props.positionmode_is (\"auto\")\n      || ylabel_props.rotationmode_is (\"auto\"))\n    {\n      graphics_xform xform = get_transform ();\n\n      Matrix ext (1, 2, 0.0);\n\n      ext = get_ticklabel_extents (get_ytick ().matrix_value (),\n                                   get_yticklabel ().string_vector_value (),\n                                   get_ylim ().matrix_value ());\n      double margin = 5;\n      double wmax = ext(0) + margin;\n      double hmax = ext(1) + margin;\n      double angle = 0.0;\n      ColumnVector p\n        = graphics_xform::xform_vector (m_xpTick, (m_ypTickN + m_ypTick)/2, m_zpTick);\n\n      bool tick_along_z = m_nearhoriz || octave::math::isinf (m_fx);\n      if (tick_along_z)\n        p(2) += (octave::math::signum (m_zpTick - m_zpTickN) * m_fz * m_ytickoffset);\n      else\n        p(0) += (octave::math::signum (m_xpTick - m_xpTickN) * m_fx * m_ytickoffset);\n\n      p = xform.transform (p(0), p(1), p(2), false);\n\n      switch (m_ystate)\n        {\n        case AXE_ANY_DIR:\n          p(0) += (! m_xyzSym ? wmax : -wmax);\n          p(1) += hmax;\n          break;\n\n        case AXE_VERT_DIR:\n          p(0) += (m_y2Dright ? wmax : -wmax);\n          angle = 90;\n          break;\n\n        case AXE_HORZ_DIR:\n          p(1) += hmax;\n          break;\n        }\n\n      if (ylabel_props.positionmode_is (\"auto\"))\n        {\n          p = xform.untransform (p(0), p(1), p(2), true);\n\n          p = convert_label_position (p, ylabel_props, xform,\n                                      get_extent (false));\n\n          ylabel_props.set_position (p.extract_n (0, 3).transpose ());\n          ylabel_props.set_positionmode (\"auto\");\n        }\n\n      if (! isempty && ylabel_props.rotationmode_is (\"auto\"))\n        {\n          ylabel_props.set_rotation (angle);\n          ylabel_props.set_rotationmode (\"auto\");\n        }\n    }\n}\n\nstatic bool updating_zlabel_position = false;\n\nvoid\naxes::properties::update_zlabel_position ()\n{\n  if (updating_zlabel_position)\n    return;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get_zlabel ());\n\n  if (! go.valid_object ())\n    return;\n\n  text::properties& zlabel_props\n    = reinterpret_cast<text::properties&> (go.get_properties ());\n\n  bool camAuto = cameraupvectormode_is (\"auto\");\n  bool isempty = zlabel_props.get_string ().isempty ();\n\n  octave::unwind_protect_var<bool>\n  restore_updating_zlabel_position (updating_zlabel_position, true);\n\n  if (! isempty)\n    {\n      if (zlabel_props.horizontalalignmentmode_is (\"auto\"))\n        {\n          zlabel_props.set_horizontalalignment\n          ((m_zstate > AXE_DEPTH_DIR || camAuto) ? \"center\" : \"right\");\n\n          zlabel_props.set_horizontalalignmentmode (\"auto\");\n        }\n\n      if (zlabel_props.verticalalignmentmode_is (\"auto\"))\n        {\n          zlabel_props.set_verticalalignment\n          (m_zstate == AXE_VERT_DIR\n           ? \"bottom\" : ((m_zSign || camAuto) ? \"bottom\" : \"top\"));\n\n          zlabel_props.set_verticalalignmentmode (\"auto\");\n        }\n    }\n\n  if (zlabel_props.positionmode_is (\"auto\")\n      || zlabel_props.rotationmode_is (\"auto\"))\n    {\n      graphics_xform xform = get_transform ();\n\n      Matrix ext (1, 2, 0.0);\n      ext = get_ticklabel_extents (get_ztick ().matrix_value (),\n                                   get_zticklabel ().string_vector_value (),\n                                   get_zlim ().matrix_value ());\n\n      double margin = 5;\n      double wmax = ext(0) + margin;\n      double hmax = ext(1) + margin;\n      double angle = 0.0;\n      ColumnVector p;\n\n      if (m_xySym)\n        {\n          p = graphics_xform::xform_vector (m_xPlaneN, m_yPlane,\n                                            (m_zpTickN + m_zpTick)/2);\n          if (octave::math::isinf (m_fy))\n            p(0) += octave::math::signum (m_xPlaneN - m_xPlane) * m_fx * m_ztickoffset;\n          else\n            p(1) += octave::math::signum (m_yPlane - m_yPlaneN) * m_fy * m_ztickoffset;\n        }\n      else\n        {\n          p = graphics_xform::xform_vector (m_xPlane, m_yPlaneN,\n                                            (m_zpTickN + m_zpTick)/2);\n          if (octave::math::isinf (m_fx))\n            p(1) += octave::math::signum (m_yPlaneN - m_yPlane) * m_fy * m_ztickoffset;\n          else\n            p(0) += octave::math::signum (m_xPlane - m_xPlaneN) * m_fx * m_ztickoffset;\n        }\n\n      p = xform.transform (p(0), p(1), p(2), false);\n\n      switch (m_zstate)\n        {\n        case AXE_ANY_DIR:\n          if (camAuto)\n            {\n              p(0) -= wmax;\n              angle = 90;\n            }\n\n          // FIXME: what's the correct offset?\n          //\n          //   p[0] += (! m_xySym ? wmax : -wmax);\n          //   p[1] += (m_zSign ? hmax : -hmax);\n\n          break;\n\n        case AXE_VERT_DIR:\n          p(0) -= wmax;\n          angle = 90;\n          break;\n\n        case AXE_HORZ_DIR:\n          p(1) += hmax;\n          break;\n        }\n\n      if (zlabel_props.positionmode_is (\"auto\"))\n        {\n          p = xform.untransform (p(0), p(1), p(2), true);\n\n          p = convert_label_position (p, zlabel_props, xform,\n                                      get_extent (false));\n\n          zlabel_props.set_position (p.extract_n (0, 3).transpose ());\n          zlabel_props.set_positionmode (\"auto\");\n        }\n\n      if (! isempty && zlabel_props.rotationmode_is (\"auto\"))\n        {\n          zlabel_props.set_rotation (angle);\n          zlabel_props.set_rotationmode (\"auto\");\n        }\n    }\n}\n\nstatic bool updating_title_position = false;\n\nvoid\naxes::properties::update_title_position ()\n{\n  if (updating_title_position)\n    return;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get_title ());\n\n  if (! go.valid_object ())\n    return;\n\n  text::properties& title_props\n    = reinterpret_cast<text::properties&> (go.get_properties ());\n\n  octave::unwind_protect_var<bool> restore_var (updating_title_position, true);\n\n  if (title_props.positionmode_is (\"auto\"))\n    {\n      graphics_xform xform = get_transform ();\n\n      // FIXME: bbox should be stored in axes::properties\n      Matrix bbox = get_extent (false);\n\n      ColumnVector p\n        = graphics_xform::xform_vector (bbox(0) + bbox(2)/2, bbox(1) - 10,\n                                        (m_x_zlim(0) + m_x_zlim(1))/2);\n\n      if (m_x2Dtop)\n        {\n          Matrix ext (1, 2, 0.0);\n          ext = get_ticklabel_extents (get_xtick ().matrix_value (),\n                                       get_xticklabel ().string_vector_value (),\n                                       get_xlim ().matrix_value ());\n          p(1) -= ext(1);\n        }\n\n      p = xform.untransform (p(0), p(1), p(2), true);\n\n      p = convert_label_position (p, title_props, xform, bbox);\n\n      title_props.set_position (p.extract_n (0, 3).transpose ());\n      title_props.set_positionmode (\"auto\");\n    }\n}\n\nvoid\naxes::properties::update_autopos (const std::string& elem_type)\n{\n  if (elem_type == \"xlabel\")\n    update_xlabel_position ();\n  else if (elem_type == \"ylabel\")\n    update_ylabel_position ();\n  else if (elem_type == \"zlabel\")\n    update_zlabel_position ();\n  else if (elem_type == \"title\")\n    update_title_position ();\n  else if (elem_type == \"sync\")\n    sync_positions ();\n}\n\nstatic void\nnormalized_aspectratios (Matrix& aspectratios, const Matrix& scalefactors,\n                         double xlength, double ylength, double zlength)\n{\n  double xval = xlength / scalefactors(0);\n  double yval = ylength / scalefactors(1);\n  double zval = zlength / scalefactors(2);\n\n  double minval = octave::math::min (octave::math::min (xval, yval), zval);\n\n  aspectratios(0) = xval / minval;\n  aspectratios(1) = yval / minval;\n  aspectratios(2) = zval / minval;\n}\n\nstatic void\nmax_axes_scale (double& s, Matrix& limits, const Matrix& kids,\n                double pbfactor, double dafactor, char limit_type, bool tight)\n{\n  if (tight)\n    {\n      double minval = octave::numeric_limits<double>::Inf ();\n      double maxval = -octave::numeric_limits<double>::Inf ();\n      double min_pos = octave::numeric_limits<double>::Inf ();\n      double max_neg = -octave::numeric_limits<double>::Inf ();\n      get_children_limits (minval, maxval, min_pos, max_neg, kids, limit_type);\n      if (octave::math::isfinite (minval) && octave::math::isfinite (maxval))\n        {\n          limits(0) = minval;\n          limits(1) = maxval;\n          s = octave::math::max (s, (maxval - minval) / (pbfactor * dafactor));\n        }\n    }\n  else\n    s = octave::math::max (s, (limits(1) - limits(0)) / (pbfactor * dafactor));\n}\n\nstatic std::set<double> updating_aspectratios;\n\nvoid\naxes::properties::update_aspectratios ()\n{\n  if (updating_aspectratios.find (get___myhandle__ ().value ())\n      != updating_aspectratios.end ())\n    return;\n\n  Matrix xlimits = get_xlim ().matrix_value ();\n  Matrix ylimits = get_ylim ().matrix_value ();\n  Matrix zlimits = get_zlim ().matrix_value ();\n\n  double dx = (xlimits(1) - xlimits(0));\n  double dy = (ylimits(1) - ylimits(0));\n  double dz = (zlimits(1) - zlimits(0));\n\n  Matrix da = get_dataaspectratio ().matrix_value ();\n  Matrix pba = get_plotboxaspectratio ().matrix_value ();\n\n  if (dataaspectratiomode_is (\"auto\"))\n    {\n      if (plotboxaspectratiomode_is (\"auto\"))\n        {\n          pba = Matrix (1, 3, 1.0);\n          m_plotboxaspectratio.set (pba, false);\n        }\n\n      normalized_aspectratios (da, pba, dx, dy, dz);\n      m_dataaspectratio.set (da, false);\n    }\n  else if (plotboxaspectratiomode_is (\"auto\"))\n    {\n      normalized_aspectratios (pba, da, dx, dy, dz);\n      m_plotboxaspectratio.set (pba, false);\n    }\n  else\n    {\n      double s = -octave::numeric_limits<double>::Inf ();\n      bool modified_limits = false;\n      Matrix kids;\n\n      if (xlimmode_is (\"auto\") && ylimmode_is (\"auto\") && zlimmode_is (\"auto\"))\n        {\n          modified_limits = true;\n          kids = get_children ();\n          max_axes_scale (s, xlimits, kids, pba(0), da(0), 'x', true);\n          max_axes_scale (s, ylimits, kids, pba(1), da(1), 'y', true);\n          max_axes_scale (s, zlimits, kids, pba(2), da(2), 'z', true);\n        }\n      else if (xlimmode_is (\"auto\") && ylimmode_is (\"auto\"))\n        {\n          modified_limits = true;\n          max_axes_scale (s, zlimits, kids, pba(2), da(2), 'z', false);\n        }\n      else if (ylimmode_is (\"auto\") && zlimmode_is (\"auto\"))\n        {\n          modified_limits = true;\n          max_axes_scale (s, xlimits, kids, pba(0), da(0), 'x', false);\n        }\n      else if (zlimmode_is (\"auto\") && xlimmode_is (\"auto\"))\n        {\n          modified_limits = true;\n          max_axes_scale (s, ylimits, kids, pba(1), da(1), 'y', false);\n        }\n\n      if (modified_limits)\n        {\n          octave::unwind_protect_var<std::set<double>>\n              restore_var (updating_aspectratios);\n\n          updating_aspectratios.insert (get___myhandle__ ().value ());\n\n          dx = pba(0) * da(0);\n          dy = pba(1) * da(1);\n          dz = pba(2) * da(2);\n          if (octave::math::isinf (s))\n            s = 1 / octave::math::min (octave::math::min (dx, dy), dz);\n\n          if (xlimmode_is (\"auto\"))\n            {\n              dx = s * dx;\n              xlimits(0) = 0.5 * (xlimits(0) + xlimits(1) - dx);\n              xlimits(1) = xlimits(0) + dx;\n              set_xlim (xlimits);\n              set_xlimmode (\"auto\");\n            }\n\n          if (ylimmode_is (\"auto\"))\n            {\n              dy = s * dy;\n              ylimits(0) = 0.5 * (ylimits(0) + ylimits(1) - dy);\n              ylimits(1) = ylimits(0) + dy;\n              set_ylim (ylimits);\n              set_ylimmode (\"auto\");\n            }\n\n          if (zlimmode_is (\"auto\"))\n            {\n              dz = s * dz;\n              zlimits(0) = 0.5 * (zlimits(0) + zlimits(1) - dz);\n              zlimits(1) = zlimits(0) + dz;\n              set_zlim (zlimits);\n              set_zlimmode (\"auto\");\n            }\n        }\n      else\n        {\n          normalized_aspectratios (pba, da, dx, dy, dz);\n          m_plotboxaspectratio.set (pba, false);\n        }\n    }\n}\n\nvoid\naxes::properties::update_label_color (handle_property label,\n                                      color_property col)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  gh_mgr.get_object (label.handle_value ()).set (\"color\", col.get ());\n}\n\nvoid\naxes::properties::update_font (std::string prop)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  if (! prop.empty ())\n    {\n      octave_value val = get (prop);\n      octave_value tval = val;\n      if (prop == \"fontsize\")\n        {\n          tval = octave_value (val.double_value () *\n                               get_titlefontsizemultiplier ());\n          val  = octave_value (val.double_value () *\n                               get_labelfontsizemultiplier ());\n        }\n      else if (prop == \"fontweight\")\n        tval = get (\"titlefontweight\");\n\n      gh_mgr.get_object (get_xlabel ()).set (prop, val);\n      gh_mgr.get_object (get_ylabel ()).set (prop, val);\n      gh_mgr.get_object (get_zlabel ()).set (prop, val);\n      gh_mgr.get_object (get_title ()).set (prop, tval);\n    }\n\n  double dpr = device_pixel_ratio (get___myhandle__ ());\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  m_txt_renderer.set_font (get (\"fontname\").string_value (),\n                           get (\"fontweight\").string_value (),\n                           get (\"fontangle\").string_value (),\n                           get (\"__fontsize_points__\").double_value () * dpr);\n}\n\n// The INTERNAL flag defines whether position or outerposition is used.\n\nMatrix\naxes::properties::get_boundingbox (bool internal,\n                                   const Matrix& parent_pix_size) const\n{\n  Matrix pos = (internal ? get_position ().matrix_value ()\n                : get_outerposition ().matrix_value ());\n  Matrix parent_size (parent_pix_size);\n\n  if (parent_size.isempty ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go = gh_mgr.get_object (get_parent ());\n\n      if (go.valid_object ())\n        parent_size\n          = go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);\n      else\n        parent_size = default_figure_position ();\n    }\n\n  pos = convert_position (pos, get_units (), \"pixels\", parent_size);\n\n  pos(0)--;\n  pos(1)--;\n  pos(1) = parent_size(1) - pos(1) - pos(3);\n\n  return pos;\n}\n\nMatrix\naxes::properties::get_extent (bool with_text, bool only_text_height) const\n{\n  graphics_xform xform = get_transform ();\n\n  Matrix ext (1, 4, 0.0);\n  ext(0) = ext(1) = octave::numeric_limits<double>::Inf ();\n  ext(2) = ext(3) = -octave::numeric_limits<double>::Inf ();\n  for (int i = 0; i <= 1; i++)\n    for (int j = 0; j <= 1; j++)\n      for (int k = 0; k <= 1; k++)\n        {\n          ColumnVector p = xform.transform (i ? m_xPlaneN : m_xPlane,\n                                            j ? m_yPlaneN : m_yPlane,\n                                            k ? m_zPlaneN : m_zPlane, false);\n          ext(0) = std::min (ext(0), p(0));\n          ext(1) = std::min (ext(1), p(1));\n          ext(2) = std::max (ext(2), p(0));\n          ext(3) = std::max (ext(3), p(1));\n        }\n\n  if (with_text)\n    {\n      for (int i = 0; i < 4; i++)\n        {\n          graphics_handle htext;\n          if (i == 0)\n            htext = get_title ();\n          else if (i == 1)\n            htext = get_xlabel ();\n          else if (i == 2)\n            htext = get_ylabel ();\n          else if (i == 3)\n            htext = get_zlabel ();\n\n          gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n          text::properties& text_props\n            = reinterpret_cast<text::properties&>\n              (gh_mgr.get_object (htext).get_properties ());\n\n          Matrix text_pos = text_props.get_data_position ();\n          text_pos = xform.transform (text_pos(0), text_pos(1), text_pos(2));\n          if (text_props.get_string ().isempty ())\n            {\n              ext(0) = std::min (ext(0), text_pos(0));\n              ext(1) = std::min (ext(1), text_pos(1));\n              ext(2) = std::max (ext(2), text_pos(0));\n              ext(3) = std::max (ext(3), text_pos(1));\n            }\n          else\n            {\n              Matrix text_ext = text_props.get_extent_matrix (true);\n\n              // The text extent is returned in device pixels.  Unscale and\n              // work with logical pixels\n              double dpr = device_pixel_ratio (get___myhandle__ ());\n              if (dpr != 1.0)\n                for (int j = 0; j < 4; j++)\n                  text_ext(j) /= dpr;\n\n              bool ignore_horizontal = false;\n              bool ignore_vertical = false;\n              if (only_text_height)\n                {\n                  double text_rotation = text_props.get_rotation ();\n                  if (text_rotation == 0. || text_rotation == 180.)\n                    ignore_horizontal = true;\n                  else if (text_rotation == 90. || text_rotation == 270.)\n                    ignore_vertical = true;\n                }\n\n              if (! ignore_horizontal)\n                {\n                  ext(0) = std::min (ext(0), text_pos(0)+text_ext(0));\n                  ext(2) = std::max (ext(2),\n                                     text_pos(0)+text_ext(0)+text_ext(2));\n                }\n\n              if (! ignore_vertical)\n                {\n                  ext(1) = std::min (ext(1),\n                                     text_pos(1)-text_ext(1)-text_ext(3));\n                  ext(3) = std::max (ext(3), text_pos(1)-text_ext(1));\n                }\n            }\n        }\n    }\n\n  ext(2) = ext(2) - ext(0);\n  ext(3) = ext(3) - ext(1);\n\n  return ext;\n}\n\nstatic octave_value\nconvert_ticklabel_string (const octave_value& val)\n{\n  octave_value retval = val;\n\n  if (val.iscellstr ())\n    {\n      // Always return a column vector for Matlab compatibility\n      if (val.columns () > 1)\n        retval = val.reshape (dim_vector (val.numel (), 1));\n    }\n  else\n    {\n      string_vector sv;\n      if (val.isnumeric ())\n        {\n          NDArray data = val.array_value ();\n          std::ostringstream oss;\n          oss.precision (5);\n          for (octave_idx_type i = 0; i < val.numel (); i++)\n            {\n              oss.str (\"\");\n              // FIXME: Code should probably call out to display routines\n              // within Octave, rather than hack things up with C++ library.\n              // See FIXME in calc_ticklabels().\n              if (std::abs (data(i)) < 1.0)\n                oss.precision (4);\n              else\n                oss.precision (5);\n              oss << data(i);\n              sv.append (oss.str ());\n            }\n        }\n      else if (val.is_string () && val.rows () == 1)\n        {\n          std::string valstr = val.string_value ();\n          std::istringstream iss (valstr);\n          std::string tmpstr;\n\n          // Split string with delimiter '|'\n          while (std::getline (iss, tmpstr, '|'))\n            sv.append (tmpstr);\n\n          // If string ends with '|' Matlab appends a null string\n          if (*valstr.rbegin () == '|')\n            sv.append (std::string (\"\"));\n        }\n      else\n        return retval;\n\n      charMatrix chmat (sv, ' ');\n\n      retval = octave_value (chmat);\n    }\n\n  return retval;\n}\n\nvoid\naxes::properties::set_xticklabel (const octave_value& val)\n{\n  if (m_xticklabel.set (convert_ticklabel_string (val), false))\n    {\n      set_xticklabelmode (\"manual\");\n      m_xticklabel.run_listeners (GCB_POSTSET);\n      mark_modified ();\n    }\n  else\n    set_xticklabelmode (\"manual\");\n\n  sync_positions ();\n}\n\nvoid\naxes::properties::set_yticklabel (const octave_value& val)\n{\n  if (m_yticklabel.set (convert_ticklabel_string (val), false))\n    {\n      set_yticklabelmode (\"manual\");\n      m_yticklabel.run_listeners (GCB_POSTSET);\n      mark_modified ();\n    }\n  else\n    set_yticklabelmode (\"manual\");\n\n  sync_positions ();\n}\n\nvoid\naxes::properties::set_zticklabel (const octave_value& val)\n{\n  if (m_zticklabel.set (convert_ticklabel_string (val), false))\n    {\n      set_zticklabelmode (\"manual\");\n      m_zticklabel.run_listeners (GCB_POSTSET);\n      mark_modified ();\n    }\n  else\n    set_zticklabelmode (\"manual\");\n\n  sync_positions ();\n}\n\n// Almost identical to convert_ticklabel_string but it only accepts\n// cellstr or string, not numeric input.\nstatic octave_value\nconvert_linestyleorder_string (const octave_value& val)\n{\n  octave_value retval = val;\n\n  if (val.iscellstr ())\n    {\n      // Always return a column vector for Matlab Compatibility\n      if (val.columns () > 1)\n        retval = val.reshape (dim_vector (val.numel (), 1));\n    }\n  else\n    {\n      string_vector sv;\n      if (val.is_string () && val.rows () == 1)\n        {\n          std::string valstr = val.string_value ();\n          std::istringstream iss (valstr);\n          std::string tmpstr;\n\n          // Split string with delimiter '|'\n          while (std::getline (iss, tmpstr, '|'))\n            sv.append (tmpstr);\n\n          // If string ends with '|' Matlab appends a null string\n          if (*valstr.rbegin () == '|')\n            sv.append (std::string (\"\"));\n        }\n      else\n        return retval;\n\n      charMatrix chmat (sv, ' ');\n\n      retval = octave_value (chmat);\n    }\n\n  return retval;\n}\n\nvoid\naxes::properties::set_linestyleorder (const octave_value& val)\n{\n  m_linestyleorder.set (convert_linestyleorder_string (val), false);\n}\n\nvoid\naxes::properties::set_units (const octave_value& val)\n{\n  caseless_str old_units = get_units ();\n\n  if (m_units.set (val, true))\n    {\n      update_units (old_units);\n      mark_modified ();\n    }\n}\n\nvoid\naxes::properties::update_units (const caseless_str& old_units)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  Matrix parent_bb\n    = parent_go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);\n\n  caseless_str new_units = get_units ();\n  m_position.set (octave_value\n                  (convert_position (get_position ().matrix_value (),\n                                     old_units, new_units, parent_bb)),\n                  false);\n  m_outerposition.set (octave_value\n                       (convert_position (get_outerposition ().matrix_value (),\n                                          old_units, new_units, parent_bb)),\n                       false);\n  m_tightinset.set (octave_value\n                    (convert_position (get_tightinset ().matrix_value (),\n                                       old_units, new_units, parent_bb)),\n                    false);\n  m_looseinset.set (octave_value\n                    (convert_position (get_looseinset ().matrix_value (),\n                                       old_units, new_units, parent_bb)),\n                    false);\n}\n\nvoid\naxes::properties::set_fontunits (const octave_value& val)\n{\n  caseless_str old_fontunits = get_fontunits ();\n\n  if (m_fontunits.set (val, true))\n    {\n      update_fontunits (old_fontunits);\n      mark_modified ();\n    }\n}\n\nvoid\naxes::properties::update_fontunits (const caseless_str& old_units)\n{\n  caseless_str new_units = get_fontunits ();\n  double parent_height = get_boundingbox (true).elem (3);\n  double fontsz = get_fontsize ();\n\n  fontsz = convert_font_size (fontsz, old_units, new_units, parent_height);\n\n  set_fontsize (octave_value (fontsz));\n}\n\ndouble\naxes::properties::get___fontsize_points__ (double box_pix_height) const\n{\n  double fontsz = get_fontsize ();\n  double parent_height = box_pix_height;\n\n  if (fontunits_is (\"normalized\") && parent_height <= 0)\n    parent_height = get_boundingbox (true).elem (3);\n\n  return convert_font_size (fontsz, get_fontunits (), \"points\", parent_height);\n}\n\nColumnVector\ngraphics_xform::xform_vector (double x, double y, double z)\n{\n  return octave::xform_vector (x, y, z);\n}\n\nMatrix\ngraphics_xform::xform_eye ()\n{\n  return octave::xform_matrix ();\n}\n\nColumnVector\ngraphics_xform::transform (double x, double y, double z, bool use_scale) const\n{\n  if (use_scale)\n    {\n      x = m_sx.scale (x);\n      y = m_sy.scale (y);\n      z = m_sz.scale (z);\n    }\n\n  return octave::transform (m_xform, x, y, z);\n}\n\nColumnVector\ngraphics_xform::untransform (double x, double y, double z,\n                             bool use_scale) const\n{\n  ColumnVector v = octave::transform (m_xform_inv, x, y, z);\n\n  if (use_scale)\n    {\n      v(0) = m_sx.unscale (v(0));\n      v(1) = m_sy.unscale (v(1));\n      v(2) = m_sz.unscale (v(2));\n    }\n\n  return v;\n}\n\noctave_value\naxes::get_default (const caseless_str& pname) const\n{\n  octave_value retval = m_default_properties.lookup (pname);\n\n  if (retval.is_undefined ())\n    {\n      graphics_handle parent_h = get_parent ();\n\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object parent_go = gh_mgr.get_object (parent_h);\n\n      retval = parent_go.get_default (pname);\n    }\n\n  return retval;\n}\n\n// FIXME: remove.\n// FIXME: maybe this should go into array_property class?\n/*\nstatic void\ncheck_limit_vals (double& min_val, double& max_val,\n                  double& min_pos, double& max_neg,\n                  const array_property& data)\n{\n  double val = data.min_val ();\n  if (octave::math::isfinite (val) && val < min_val)\n    min_val = val;\n  val = data.max_val ();\n  if (octave::math::isfinite (val) && val > max_val)\n    max_val = val;\n  val = data.min_pos ();\n  if (octave::math::isfinite (val) && val > 0 && val < min_pos)\n    min_pos = val;\n  val = data.max_neg ();\n  if (octave::math::isfinite (val) && val < 0 && val > max_neg)\n    max_neg = val;\n}\n*/\n\nstatic void\ncheck_limit_vals (double& min_val, double& max_val,\n                  double& min_pos, double& max_neg,\n                  const octave_value& data)\n{\n  Matrix m;\n\n  if (data.is_matrix_type ())\n    m = data.matrix_value ();\n\n  if (m.numel () != 4)\n    {\n      m = Matrix (1, 4, 0.0);\n      m(2) = octave::numeric_limits<double>::Inf ();\n      m(3) = -octave::numeric_limits<double>::Inf ();\n    }\n\n  double val;\n\n  val = m(0);\n  if (octave::math::isfinite (val) && val < min_val)\n    min_val = val;\n\n  val = m(1);\n  if (octave::math::isfinite (val) && val > max_val)\n    max_val = val;\n\n  val = m(2);\n  if (octave::math::isfinite (val) && val > 0 && val < min_pos)\n    min_pos = val;\n\n  val = m(3);\n  if (octave::math::isfinite (val) && val < 0 && val > max_neg)\n    max_neg = val;\n}\n\n// magform(x) Returns (a, b),\n// where x = a * 10^b, abs (a) >= 1., and b is integer.\n\nstatic void\nmagform (double x, double& a, int& b)\n{\n  if (x == 0)\n    {\n      a = 0;\n      b = 0;\n    }\n  else\n    {\n      b = static_cast<int> (std::floor (std::log10 (std::abs (x))));\n      a = x / std::pow (10.0, b);\n    }\n}\n\nvoid\naxes::properties::update_outerposition ()\n{\n  set_positionconstraint (\"outerposition\");\n  caseless_str old_units = get_units ();\n  set_units (\"normalized\");\n\n  Matrix outerbox = m_outerposition.get ().matrix_value ();\n\n  double outer_left = outerbox(0);\n  double outer_bottom = outerbox(1);\n  double outer_width = outerbox(2);\n  double outer_height = outerbox(3);\n\n  double outer_right = outer_width + outer_left;\n  double outer_top = outer_height + outer_bottom;\n\n  Matrix linset = m_looseinset.get ().matrix_value ();\n  Matrix tinset = m_tightinset.get ().matrix_value ();\n\n  double left_margin = std::max (linset(0), tinset(0));\n  double bottom_margin = std::max (linset(1), tinset(1));\n  double right_margin = std::max (linset(2), tinset(2));\n  double top_margin = std::max (linset(3), tinset(3));\n\n  double inner_left = outer_left;\n  double inner_right = outer_right;\n\n  if ((left_margin + right_margin) < outer_width)\n    {\n      inner_left += left_margin;\n      inner_right -= right_margin;\n    }\n\n  double inner_bottom = outer_bottom;\n  double inner_top = outer_top;\n\n  if ((bottom_margin + top_margin) < outer_height)\n    {\n      inner_bottom += bottom_margin;\n      inner_top -= top_margin;\n    }\n\n  double inner_width = inner_right - inner_left;\n  double inner_height = inner_top - inner_bottom;\n\n  Matrix innerbox (1, 4);\n\n  innerbox(0) = inner_left;\n  innerbox(1) = inner_bottom;\n  innerbox(2) = inner_width;\n  innerbox(3) = inner_height;\n\n  m_position = innerbox;\n\n  set_units (old_units);\n  update_transform ();\n}\n\nvoid\naxes::properties::update_position ()\n{\n  set_positionconstraint (\"innerposition\");\n  caseless_str old_units = get_units ();\n  set_units (\"normalized\");\n\n  Matrix innerbox = m_position.get ().matrix_value ();\n\n  double inner_left = innerbox(0);\n  double inner_bottom = innerbox(1);\n  double inner_width = innerbox(2);\n  double inner_height = innerbox(3);\n\n  double inner_right = inner_width + inner_left;\n  double inner_top = inner_height + inner_bottom;\n\n  Matrix linset = m_looseinset.get ().matrix_value ();\n  Matrix tinset = m_tightinset.get ().matrix_value ();\n\n  double left_margin = std::max (linset(0), tinset(0));\n  double bottom_margin = std::max (linset(1), tinset(1));\n  double right_margin = std::max (linset(2), tinset(2));\n  double top_margin = std::max (linset(3), tinset(3));\n\n  // FIXME: do we need to place limits on any of these?\n\n  double outer_left = inner_left - left_margin;\n  double outer_bottom = inner_bottom - bottom_margin;\n  double outer_right = inner_right + right_margin;\n  double outer_top = inner_top + top_margin;\n\n  double outer_width = outer_right - outer_left;\n  double outer_height = outer_top - outer_bottom;\n\n  Matrix outerbox (1, 4);\n\n  outerbox(0) = outer_left;\n  outerbox(1) = outer_bottom;\n  outerbox(2) = outer_width;\n  outerbox(3) = outer_height;\n\n  m_outerposition = outerbox;\n\n  set_units (old_units);\n  update_transform ();\n}\n\nvoid\naxes::properties::update_looseinset ()\n{\n  caseless_str old_units = get_units ();\n  set_units (\"normalized\");\n\n  Matrix linset = m_looseinset.get ().matrix_value ();\n  Matrix tinset = m_tightinset.get ().matrix_value ();\n\n  double left_margin = std::max (linset(0), tinset(0));\n  double bottom_margin = std::max (linset(1), tinset(1));\n  double right_margin = std::max (linset(2), tinset(2));\n  double top_margin = std::max (linset(3), tinset(3));\n\n  if (m_positionconstraint.is (\"innerposition\"))\n    {\n      Matrix innerbox = m_position.get ().matrix_value ();\n\n      double inner_left = innerbox(0);\n      double inner_bottom = innerbox(1);\n      double inner_width = innerbox(2);\n      double inner_height = innerbox(3);\n\n      double inner_right = inner_width + inner_left;\n      double inner_top = inner_height + inner_bottom;\n\n      // FIXME: do we need to place limits on any of these?\n\n      double outer_left = inner_left - left_margin;\n      double outer_bottom = inner_bottom - bottom_margin;\n      double outer_right = inner_right + right_margin;\n      double outer_top = inner_top + top_margin;\n\n      double outer_width = outer_right - outer_left;\n      double outer_height = outer_top - outer_bottom;\n\n      Matrix outerbox (1, 4);\n\n      outerbox(0) = outer_left;\n      outerbox(1) = outer_bottom;\n      outerbox(2) = outer_width;\n      outerbox(3) = outer_height;\n\n      m_outerposition = outerbox;\n    }\n  else\n    {\n      Matrix outerbox = m_outerposition.get ().matrix_value ();\n\n      double outer_left = outerbox(0);\n      double outer_bottom = outerbox(1);\n      double outer_width = outerbox(2);\n      double outer_height = outerbox(3);\n\n      double outer_right = outer_width + outer_left;\n      double outer_top = outer_height + outer_bottom;\n\n      double inner_left = outer_left;\n      double inner_right = outer_right;\n\n      if ((left_margin + right_margin) < outer_width)\n        {\n          inner_left += left_margin;\n          inner_right -= right_margin;\n        }\n\n      double inner_bottom = outer_bottom;\n      double inner_top = outer_top;\n\n      if ((bottom_margin + top_margin) < outer_height)\n        {\n          inner_bottom += bottom_margin;\n          inner_top -= top_margin;\n        }\n\n      double inner_width = inner_right - inner_left;\n      double inner_height = inner_top - inner_bottom;\n\n      Matrix innerbox (1, 4);\n\n      innerbox(0) = inner_left;\n      innerbox(1) = inner_bottom;\n      innerbox(2) = inner_width;\n      innerbox(3) = inner_height;\n\n      m_position = innerbox;\n    }\n\n  set_units (old_units);\n  update_transform ();\n}\n\n// A translation from Tom Holoryd's python code at\n// http://kurage.nimh.nih.gov/tomh/tics.py\n// FIXME: add log ticks\n\ndouble\naxes::properties::calc_tick_sep (double lo, double hi)\n{\n  int ticint = 5;\n\n  // Reference: C. R. Lewart, \"Algorithms SCALE1, SCALE2, and SCALE3 for\n  // Determination of Scales on Computer Generated Plots\", Communications of\n  // the ACM, 10, pp. 639-640, 1973.\n  // Also cited as ACM Algorithm 463.\n\n  double a;\n  int b, x;\n\n  magform ((hi - lo) / ticint, a, b);\n\n  static const double SQRT_2 = sqrt (2.0);\n  static const double SQRT_10 = sqrt (10.0);\n  static const double SQRT_50 = sqrt (50.0);\n\n  if (a < SQRT_2)\n    x = 1;\n  else if (a < SQRT_10)\n    x = 2;\n  else if (a < SQRT_50)\n    x = 5;\n  else\n    x = 10;\n\n  return x * std::pow (10.0, b);\n}\n\n// Attempt to make \"nice\" limits from the actual max and min of the data.\n// For log plots, we will also use the smallest strictly positive value.\n\nMatrix\naxes::properties::get_axis_limits (double xmin, double xmax,\n                                   double min_pos, double max_neg,\n                                   const bool logscale,\n                                   const std::string& method)\n{\n  Matrix retval;\n\n  double min_val = xmin;\n  double max_val = xmax;\n\n  if (octave::math::isinf (min_val) && min_val > 0\n      && octave::math::isinf (max_val) && max_val < 0)\n    {\n      retval = default_lim (logscale);\n      return retval;\n    }\n  else if (! (octave::math::isinf (min_val) || octave::math::isinf (max_val)))\n    {\n      if (logscale)\n        {\n          if (octave::math::isinf (min_pos) && octave::math::isinf (max_neg))\n            {\n              // FIXME: max_neg is needed for \"loglog ([0 -Inf])\"\n              //        This is the *only* place where max_neg is needed.\n              //        Is there another way?\n              retval = default_lim (logscale);\n              return retval;\n            }\n          if (min_val <= 0)\n            {\n              if (max_val > 0)\n                {\n                  warning_with_id (\"Octave:negative-data-log-axis\",\n                                   \"axis: omitting non-positive data in log plot\");\n                  min_val = min_pos;\n                }\n              else if (max_val == 0)\n                max_val = max_neg;\n            }\n          // FIXME: maybe this test should also be relative?\n          if (std::abs (min_val - max_val)\n              < sqrt (std::numeric_limits<double>::epsilon ()))\n            {\n              // Widen range when too small\n              if (min_val >= 0)\n                {\n                  min_val *= 0.9;\n                  max_val *= 1.1;\n                }\n              else\n                {\n                  min_val *= 1.1;\n                  max_val *= 0.9;\n                }\n            }\n\n          if (method == \"tickaligned\")\n            {\n              if (min_val > 0)\n                {\n                  // Log plots with all positive data\n                  min_val = std::pow (10, std::floor (log10 (min_val)));\n                  max_val = std::pow (10, std::ceil (log10 (max_val)));\n                }\n              else\n                {\n                  // Log plots with all negative data\n                  min_val = -std::pow (10, std::ceil (log10 (-min_val)));\n                  max_val = -std::pow (10, std::floor (log10 (-max_val)));\n                }\n            }\n          else if (method == \"padded\")\n            {\n              if (min_val > 0)\n                {\n                  // Log plots with all positive data\n                  double pad = (log10 (max_val) - log10 (min_val)) * 0.07;\n                  min_val = std::pow (10, log10 (min_val) - pad);\n                  max_val = std::pow (10, log10 (max_val) + pad);\n                }\n              else\n                {\n                  // Log plots with all negative data\n                  double pad = (log10 (-min_val) - log10 (-max_val)) * 0.07;\n                  min_val = -std::pow (10, log10 (-min_val) + pad);\n                  max_val = -std::pow (10, log10 (-max_val) - pad);\n                }\n            }\n        }\n      else\n        {\n          if (min_val == 0 && max_val == 0)\n            {\n              min_val = -1;\n              max_val = 1;\n            }\n          // FIXME: maybe this test should also be relative?\n          else if (std::abs (min_val - max_val)\n                   < sqrt (std::numeric_limits<double>::epsilon ()))\n            {\n              min_val -= 0.1 * std::abs (min_val);\n              max_val += 0.1 * std::abs (max_val);\n            }\n\n          if (method == \"tickaligned\")\n            {\n              double tick_sep = calc_tick_sep (min_val, max_val);\n              double min_tick = std::floor (min_val / tick_sep);\n              double max_tick = std::ceil (max_val / tick_sep);\n              // Prevent round-off from cropping ticks\n              min_val = std::min (min_val, tick_sep * min_tick);\n              max_val = std::max (max_val, tick_sep * max_tick);\n            }\n          else if (method == \"padded\")\n            {\n              double pad = 0.07 * (max_val - min_val);\n              min_val -= pad;\n              max_val += pad;\n            }\n        }\n    }\n\n  retval.resize (1, 2);\n\n  retval(0) = min_val;\n  retval(1) = max_val;\n\n  return retval;\n}\n\nvoid\naxes::properties::check_axis_limits (Matrix& limits, const Matrix kids,\n                                     const bool logscale, char& update_type)\n{\n  double min_val = octave::numeric_limits<double>::Inf ();\n  double max_val = -octave::numeric_limits<double>::Inf ();\n  double min_pos = octave::numeric_limits<double>::Inf ();\n  double max_neg = -octave::numeric_limits<double>::Inf ();\n  double eps = std::numeric_limits<double>::epsilon ();\n  bool do_update = false;\n  bool have_children_limits = false;\n\n  // check whether we need to get children limits\n  if (! octave::math::isfinite (limits(0))\n      || ! octave::math::isfinite (limits(1)))\n    {\n      get_children_limits (min_val, max_val, min_pos, max_neg, kids,\n                           update_type);\n      have_children_limits = true;\n    }\n  if (! octave::math::isfinite (limits(0)))\n    {\n      limits(0) = min_val;\n      do_update = true;\n    }\n  if (! octave::math::isfinite (limits(1)))\n    {\n      limits(1) = max_val;\n      do_update = true;\n    }\n  if (limits(0) == 0 && limits(1) == 0)\n    {\n      limits = default_lim (logscale);\n      do_update = true;\n    }\n  // FIXME: maybe this test should also be relative?\n  else if (! logscale && (std::abs (limits(0) - limits(1)) < sqrt (eps)))\n    {\n      limits(0) -= 0.1 * std::abs (limits(0));\n      limits(1) += 0.1 * std::abs (limits(1));\n      do_update = true;\n    }\n  else if (logscale\n           && (std::abs (std::log10 (limits(0) / limits(1))) < sqrt (eps)))\n    {\n      limits(0) = (limits(0) < 0 ? 10.0 * limits(0) : 0.1 * limits(0));\n      limits(1) = (limits(1) < 0 ? 0.1 * limits(1) : 10.0 * limits(1));\n      do_update = true;\n    }\n\n  if (logscale && limits(0)*limits(1) <= 0)\n    {\n      if (! have_children_limits)\n        get_children_limits (min_val, max_val, min_pos, max_neg, kids,\n                             update_type);\n\n      if (limits(1) > 0)\n        {\n          warning_with_id (\"Octave:axis-non-positive-log-limits\",\n                           \"Non-positive limit for logarithmic axis ignored\\n\");\n          if (octave::math::isfinite (min_pos))\n            limits(0) = min_pos;\n          else\n            limits(0) = 0.1 * limits(1);\n        }\n      else\n        {\n          warning_with_id (\"Octave:axis-non-negative-log-limits\",\n                           \"Non-negative limit for logarithmic axis ignored\\n\");\n          if (octave::math::isfinite (max_neg))\n            limits(1) = max_neg;\n          else\n            limits(1) = 0.1 * limits(0);\n        }\n      // FIXME: maybe this test should also be relative?\n      if (std::abs (limits(0) - limits(1)) < sqrt (eps))\n        {\n          // Widen range when too small\n          if (limits(0) > 0)\n            {\n              limits(0) *= 0.9;\n              limits(1) *= 1.1;\n            }\n          else\n            {\n              limits(0) *= 1.1;\n              limits(1) *= 0.9;\n            }\n        }\n      do_update = true;\n    }\n\n  if (! do_update)\n    update_type = 0;\n\n}\n\n/*\n## Test validation of auto and manual axis limits\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   plot (0, pi);\n%!   assert (get (hax, \"xlim\"), [-1, 1]);\n%!   assert (get (hax, \"xlimmode\"), \"auto\");\n%!   assert (get (hax, \"ylim\"), [2.8, 3.5], 2*eps);\n%!   assert (get (hax, \"ylimmode\"), \"auto\");\n%!   set (hax, \"xlim\", [1, 1], \"ylim\", [0, 0]);\n%!   assert (get (hax, \"xlim\"), [0.9, 1.1]);\n%!   assert (get (hax, \"xlimmode\"), \"manual\");\n%!   assert (get (hax, \"ylim\"), [0, 1]);\n%!   assert (get (hax, \"ylimmode\"), \"manual\");\n%!   set (hax, \"xlim\", [-Inf, Inf], \"ylim\", [-Inf, Inf]);\n%!   ## Matlab does not update the properties\n%!   assert (get (hax, \"xlim\"), [0, 1]);\n%!   assert (get (hax, \"ylim\"), [0.9, 1.1]*pi, 2*eps);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   plot ([0, exp(1)], [-pi, 3]);\n%!   assert (get (hax, \"xlim\"), [0, 3]);\n%!   assert (get (hax, \"xlimmode\"), \"auto\");\n%!   assert (get (hax, \"ylim\"), [-4, 3]);\n%!   assert (get (hax, \"ylimmode\"), \"auto\");\n%!   set (hax, \"xlim\", [-Inf, Inf], \"ylim\", [-Inf, Inf]);\n%!   ## Matlab does not update the properties but uses tight limits on screen\n%!   assert (get (hax, \"xlim\"), [0, exp(1)]);\n%!   assert (get (hax, \"xlimmode\"), \"manual\");\n%!   assert (get (hax, \"ylim\"), [-pi, 3]);\n%!   assert (get (hax, \"ylimmode\"), \"manual\");\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   loglog (0, pi);\n%!   assert (get (hax, \"xlim\"), [0.1, 1.0]);\n%!   assert (get (hax, \"xlimmode\"), \"auto\");\n%!   assert (get (hax, \"ylim\"), [1, 10]);\n%!   assert (get (hax, \"ylimmode\"), \"auto\");\n%!   set (hax, \"xlim\", [1, 1], \"ylim\", [0, 0]);\n%!   assert (get (hax, \"xlim\"), [0.1, 10]);\n%!   assert (get (hax, \"xlimmode\"), \"manual\");\n%!   assert (get (hax, \"ylim\"), [0.1, 1.0]);\n%!   assert (get (hax, \"ylimmode\"), \"manual\");\n%!   set (hax, \"xlim\", [-Inf, Inf], \"ylim\", [-Inf, Inf]);\n%!   ## Matlab does not update the properties\n%!   assert (get (hax, \"xlim\"), [0.1, 1.0]);\n%!   assert (get (hax, \"ylim\"), [0.1, 10]*pi);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   loglog ([0 -1], [0 1]);\n%!   assert (get (hax, \"xlim\"), [-10, -0.1]);\n%!   assert (get (hax, \"xlimmode\"), \"auto\");\n%!   assert (get (hax, \"ylim\"), [0.1, 10]);\n%!   assert (get (hax, \"ylimmode\"), \"auto\");\n%!   set (hax, \"xlim\", [-Inf, Inf], \"ylim\", [-Inf, Inf]);\n%!   ## Matlab does not update the properties\n%!   assert (get (hax, \"xlim\"), [-1.1, -0.9]);\n%!   assert (get (hax, \"ylim\"), [0.9, 1.1]);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   loglog ([1 -1], [1 pi]);\n%!   assert (get (hax, \"xlim\"), [0.1, 10]);\n%!   assert (get (hax, \"xlimmode\"), \"auto\");\n%!   assert (get (hax, \"ylim\"), [1, 10]);\n%!   assert (get (hax, \"ylimmode\"), \"auto\");\n%!   set (hax, \"xlim\", [-Inf, Inf], \"ylim\", [-Inf, Inf]);\n%!   ## Matlab does not update the properties but uses tight limits on screen\n%!   assert (get (hax, \"xlim\"), [0.9, 1.1]);\n%!   assert (get (hax, \"ylim\"), [1, pi]);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n## Check that graphics objects with hidden handle visibility are included in\n## axis limit calculation.\n%!test <*63095>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   plot (hax, [0, 1]);\n%!   assert (get (hax, \"ylim\"), [0, 1]);\n%!   hold (hax, \"on\");\n%!   plot (hax, [2, 0], \"handlevisibility\", \"off\");\n%!   assert (get (hax, \"ylim\"), [0, 2]);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n## Check automatically determined axes ticks with \"tickaligned\" (default) and\n## \"tight\" xlimitmethod.\n%!test <*63624>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   plot (hax, [1, 201], [0, 1]);\n%!   assert (get (hax, \"xtick\"), 0:50:250);\n%!   axis (hax, \"tight\");\n%!   assert (get (hax, \"xtick\"), 50:50:200);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n*/\n\nvoid\naxes::properties::calc_ticks_and_lims (array_property& lims,\n                                       array_property& ticks,\n                                       array_property& mticks,\n                                       bool limmode_is_auto,\n                                       bool tickmode_is_auto,\n                                       bool minortickvaluesmode_is_auto,\n                                       bool is_logscale,\n                                       bool method_is_padded,\n                                       bool method_is_tight)\n{\n  if (lims.get ().isempty ())\n    return;\n\n  double lo = (lims.get ().matrix_value ())(0);\n  double hi = (lims.get ().matrix_value ())(1);\n\n  double lo_lim = lo;\n  double hi_lim = hi;\n  bool is_negative = lo < 0 && hi < 0;\n\n  // FIXME: should this be checked for somewhere else? (i.e., set{x,y,z}lim)\n  if (hi < lo)\n    std::swap (hi, lo);\n\n  if (is_logscale)\n    {\n      if (is_negative)\n        {\n          double tmp = hi;\n          hi = std::log10 (-lo);\n          lo = std::log10 (-tmp);\n        }\n      else\n        {\n          hi = std::log10 (hi);\n          lo = std::log10 (lo);\n        }\n    }\n\n  Matrix tmp_ticks;\n  if (tickmode_is_auto)\n    {\n      double tick_sep;\n\n      if (is_logscale)\n        {\n          if (! (octave::math::isinf (hi) || octave::math::isinf (lo)))\n            tick_sep = 1;  // Tick is every order of magnitude (bug #39449)\n          else\n            tick_sep = 0;\n        }\n      else\n        tick_sep = calc_tick_sep (lo, hi);\n\n      double i1 = std::floor (lo / tick_sep);\n      double i2 = std::ceil (hi / tick_sep);\n\n      if (limmode_is_auto)\n        {\n          Matrix tmp_lims (1, 2);\n\n          if (! method_is_padded && ! method_is_tight)\n            {\n              // Adjust limits to include min and max ticks\n              tmp_lims(0) = std::min (tick_sep * i1, lo);\n              tmp_lims(1) = std::max (tick_sep * i2, hi);\n            }\n          else\n            {\n              tmp_lims(0) = lo;\n              tmp_lims(1) = hi;\n\n              // adjust min and max ticks to be within limits\n              if (i1*tick_sep < lo)\n                i1++;\n              if (i2*tick_sep > hi && i2 > i1)\n                i2--;\n            }\n\n          if (is_logscale)\n            {\n              tmp_lims(0) = std::pow (10., tmp_lims(0));\n              tmp_lims(1) = std::pow (10., tmp_lims(1));\n\n              if (tmp_lims(0) <= 0)\n                tmp_lims(0) = std::pow (10., lo);\n\n              if (is_negative)\n                {\n                  double tmp = tmp_lims(0);\n                  tmp_lims(0) = -tmp_lims(1);\n                  tmp_lims(1) = -tmp;\n                }\n            }\n\n          lims = tmp_lims;\n        }\n      else\n        {\n          // adjust min and max ticks to be within limits\n          if (i1*tick_sep < lo)\n            i1++;\n          if (i2*tick_sep > hi && i2 > i1)\n            i2--;\n        }\n\n      tmp_ticks = Matrix (1, i2-i1+1);\n      for (int i = 0; i <= static_cast<int> (i2-i1); i++)\n        {\n          tmp_ticks(i) = tick_sep * (i+i1);\n          if (is_logscale)\n            tmp_ticks(i) = std::pow (10., tmp_ticks(i));\n        }\n      if (is_logscale && is_negative)\n        {\n          Matrix rev_ticks (1, i2-i1+1);\n          rev_ticks = -tmp_ticks;\n          for (int i = 0; i <= static_cast<int> (i2-i1); i++)\n            tmp_ticks(i) = rev_ticks(i2-i1-i);\n        }\n\n      ticks = tmp_ticks;\n    }\n  else\n    tmp_ticks = ticks.get ().matrix_value ();\n\n  octave_idx_type n_ticks = tmp_ticks.numel ();\n  if (n_ticks < 2)\n    return;\n\n  // minor ticks between, above, and below min and max ticks\n  if (minortickvaluesmode_is_auto)\n    {\n      const int MAX_MINOR_TICKS = 1000;\n      int n = (is_logscale ? 8 : 4);\n      double mult_below = (is_logscale ? tmp_ticks(1) / tmp_ticks(0) : 1);\n      double mult_above = (is_logscale ?\n                           tmp_ticks(n_ticks-1) / tmp_ticks(n_ticks-2) : 1);\n\n      double d_below = (tmp_ticks(1) - tmp_ticks(0)) / mult_below / (n+1);\n      int n_below = static_cast<int> (std::floor ((tmp_ticks(0)-lo_lim)\n                                                  / d_below));\n      if (n_below < 0)\n        n_below = 0;\n      else if (n_below > MAX_MINOR_TICKS)\n        n_below = MAX_MINOR_TICKS;\n\n      int n_between = n * (n_ticks - 1);\n      double d_above = (tmp_ticks(n_ticks-1) - tmp_ticks(n_ticks-2))\n        * mult_above\n        / (n+1);\n      int n_above = static_cast<int> (std::floor ((hi_lim-tmp_ticks(n_ticks-1))\n                                                  / d_above));\n      if (n_above < 0)\n        n_above = 0;\n      else if (n_above > MAX_MINOR_TICKS)\n        n_above = MAX_MINOR_TICKS;\n\n      Matrix tmp_mticks (1, n_below + n_between + n_above);\n      for (int i = 0; i < n_below; i++)\n        tmp_mticks(i) = tmp_ticks(0) - (n_below-i) * d_below;\n      for (int i = 0; i < n_ticks-1; i++)\n        {\n          double d = (tmp_ticks(i+1) - tmp_ticks(i)) / (n + 1);\n          for (int j = 0; j < n; j++)\n            tmp_mticks(n_below+n*i+j) = tmp_ticks(i) + d * (j+1);\n        }\n      for (int i = 0; i < n_above; i++)\n        tmp_mticks(n_below+n_between+i) = tmp_ticks(n_ticks-1) + (i + 1)\n          * d_above;\n\n      mticks = tmp_mticks;\n    }\n}\n\n/*\n%!test <*45356>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   xlim ([4.75, 8.5]);\n%!   tics = get (gca, \"xtick\");\n%!   assert (tics, [5 6 7 8]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\nvoid\naxes::properties::calc_ticklabels (const array_property& ticks,\n                                   any_property& labels, bool logscale,\n                                   const bool is_origin,\n                                   const int other_axislocation,\n                                   const array_property& axis_lims)\n{\n  Matrix values = ticks.get ().matrix_value ();\n  Matrix lims = axis_lims.get ().matrix_value ();\n  Cell c (dim_vector (values.numel (), 1));  // column vector for ML compat.\n  std::ostringstream os;\n\n\n  // omit tick labels depending on location of other axis\n  const double NaN = octave::numeric_limits<double>::NaN ();\n  std::array<double, 3> omit_ticks = {NaN, NaN, NaN};\n\n  if (get_is2D () && is_origin)\n    {\n      if (other_axislocation == 0)\n        {\n          omit_ticks[0] = octave::math::max (octave::math::min (0., lims(1)),\n                                             lims(0));\n        }\n      else if (other_axislocation == 1)\n        omit_ticks[0] = lims(1);\n      else if (other_axislocation == -1)\n        omit_ticks[0] = lims(0);\n      if (is_box ())\n        {\n          omit_ticks[1] = lims(0);\n          omit_ticks[2] = lims(1);\n        }\n    }\n\n  if (logscale)\n    {\n      double significand;\n      double exponent;\n      bool is_2digit_exp = false;\n\n      for (int i = 0; i < values.numel (); i++)\n        {\n          double exp = std::abs (std::log10 (values(i)));\n          if (exp >= 10.0)\n            {\n              is_2digit_exp = true;\n              break;\n            }\n        }\n\n      for (int i = 0; i < values.numel (); i++)\n        {\n          bool omit_tick = false;\n          for (std::size_t i_omit = 0; i_omit < omit_ticks.size (); i_omit++)\n            if (values(i) == omit_ticks[i_omit])\n              omit_tick = true;\n          if (omit_tick)\n            {\n              c(i) = \"\";\n              continue;\n            }\n\n          if (values(i) < 0.0)\n            exponent = std::floor (std::log10 (-values(i)));\n          else\n            exponent = std::floor (std::log10 (values(i)));\n          significand = values(i) * std::pow (10.0, -exponent);\n\n          os.precision (5);\n          os.str (\"\");\n          if ((std::abs (significand) - 1) >\n              10*std::numeric_limits<double>::epsilon())\n            os << significand << 'x';\n          else if (significand < 0)\n            os << '-';\n\n          os << \"10^{\";\n\n          if (exponent < 0.0)\n            {\n              os << '-';\n              exponent = -exponent;\n            }\n          if (exponent < 10.0 && is_2digit_exp)\n            os << '0';\n          os << exponent << '}';\n\n          if (m_ticklabelinterpreter.is (\"latex\"))\n            c(i) = \"$\" + os.str () + \"$\";\n          else\n            c(i) = os.str ();\n        }\n    }\n  else\n    {\n      for (int i = 0; i < values.numel (); i++)\n        {\n          bool omit_tick = false;\n          for (std::size_t i_omit = 0; i_omit < omit_ticks.size (); i_omit++)\n            if (values(i) == omit_ticks[i_omit])\n              omit_tick = true;\n          if (omit_tick)\n            c(i) = \"\";\n          else\n            {\n              os.str (\"\");\n              // FIXME: Code should probably call out to display routines\n              // within Octave, rather than hack things up with C++ library.\n              // In particular, this fails for values much less than 1 where\n              // 4 significant digits will be preceded by zeros making the\n              // overall field length large.  For example, pi/1000.\n              if (std::abs (values(i)) < 1.0)\n                os.precision (4);\n              else\n                os.precision (5);\n              os << values(i);\n              c(i) = os.str ();\n            }\n        }\n    }\n\n  labels = c;\n}\n\nMatrix\naxes::properties::get_ticklabel_extents (const Matrix& ticks,\n    const string_vector& ticklabels,\n    const Matrix& limits)\n{\n  Matrix ext (1, 2, 0.0);\n  double wmax, hmax;\n  double dpr = device_pixel_ratio (get___myhandle__ ());\n  wmax = hmax = 0.0;\n  int n = std::min (ticklabels.numel (), ticks.numel ());\n  for (int i = 0; i < n; i++)\n    {\n      double val = ticks(i);\n      if (limits(0) <= val && val <= limits(1))\n        {\n          std::string label (ticklabels(i));\n          label.erase (0, label.find_first_not_of (' '));\n          label = label.substr (0, label.find_last_not_of (' ')+1);\n\n          if (m_txt_renderer.ok ())\n            {\n              gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n              octave::autolock guard (gh_mgr.graphics_lock ());\n\n              ext = m_txt_renderer.get_extent (label, 0.0,\n                                               get_ticklabelinterpreter ());\n\n              wmax = std::max (wmax, ext(0) / dpr);\n              hmax = std::max (hmax, ext(1) / dpr);\n            }\n          else\n            {\n              // FIXME: find a better approximation\n              double fsize = get (\"fontsize\").double_value ();\n              int len = label.length ();\n\n              wmax = std::max (wmax, 0.5*fsize*len);\n              hmax = fsize;\n            }\n        }\n    }\n\n  ext(0) = wmax;\n  ext(1) = hmax;\n  return ext;\n}\n\nvoid\nget_children_limits (double& min_val, double& max_val,\n                     double& min_pos, double& max_neg,\n                     const Matrix& kids, char limit_type)\n{\n  octave_idx_type n = kids.numel ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  switch (limit_type)\n    {\n    case 'x':\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          graphics_object go = gh_mgr.get_object (kids(i));\n\n          if (go.is_xliminclude ())\n            {\n              octave_value lim = go.get_xlim ();\n\n              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);\n            }\n        }\n      break;\n\n    case 'y':\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          graphics_object go = gh_mgr.get_object (kids(i));\n\n          if (go.is_yliminclude ())\n            {\n              octave_value lim = go.get_ylim ();\n\n              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);\n            }\n        }\n      break;\n\n    case 'z':\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          graphics_object go = gh_mgr.get_object (kids(i));\n\n          if (go.is_zliminclude ())\n            {\n              octave_value lim = go.get_zlim ();\n\n              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);\n            }\n        }\n      break;\n\n    case 'c':\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          graphics_object go = gh_mgr.get_object (kids(i));\n\n          if (go.is_climinclude ())\n            {\n              octave_value lim = go.get_clim ();\n\n              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);\n            }\n        }\n      break;\n\n    case 'a':\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          graphics_object go = gh_mgr.get_object (kids(i));\n\n          if (go.is_aliminclude ())\n            {\n              octave_value lim = go.get_alim ();\n\n              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);\n            }\n        }\n      break;\n\n    default:\n      break;\n    }\n}\n\nstatic std::set<double> updating_axis_limits;\n\nvoid\naxes::update_axis_limits (const std::string& axis_type,\n                          const graphics_handle& h)\n{\n  if (updating_axis_limits.find (get_handle ().value ())\n      != updating_axis_limits.end ())\n    return;\n\n  Matrix kids = Matrix (1, 1, h.value ());\n\n  double min_val = octave::numeric_limits<double>::Inf ();\n  double max_val = -octave::numeric_limits<double>::Inf ();\n  double min_pos = octave::numeric_limits<double>::Inf ();\n  double max_neg = -octave::numeric_limits<double>::Inf ();\n\n  char update_type = 0;\n\n  Matrix limits (1, 2);\n  double val;\n\n#define FIX_LIMITS                          \\\n  val = limits(0);                          \\\n  if (octave::math::isfinite (val))         \\\n    min_val = val;                          \\\n  val = limits(1);                          \\\n  if (octave::math::isfinite (val))         \\\n    max_val = val;\n\n  if (axis_type == \"xdata\" || axis_type == \"xscale\"\n      || axis_type == \"xlimmode\" || axis_type == \"xliminclude\"\n      || axis_type == \"xlim\")\n    {\n      limits = m_properties.get_xlim ().matrix_value ();\n      FIX_LIMITS;\n\n      update_type = 'x';\n      if (m_properties.xlimmode_is (\"auto\"))\n        {\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'x');\n\n          std::string method = m_properties.get_xlimitmethod ();\n          limits = m_properties.get_axis_limits (min_val, max_val,\n                                                 min_pos, max_neg,\n                                                 m_properties.xscale_is (\"log\"),\n                                                 method);\n        }\n      else\n        m_properties.check_axis_limits (limits, kids,\n                                        m_properties.xscale_is (\"log\"),\n                                        update_type);\n    }\n  else if (axis_type == \"ydata\" || axis_type == \"yscale\"\n           || axis_type == \"ylimmode\" || axis_type == \"yliminclude\"\n           || axis_type == \"ylim\")\n    {\n      limits = m_properties.get_ylim ().matrix_value ();\n      FIX_LIMITS;\n\n      update_type = 'y';\n      if (m_properties.ylimmode_is (\"auto\"))\n        {\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'y');\n\n          std::string method = m_properties.get_ylimitmethod ();\n          limits = m_properties.get_axis_limits (min_val, max_val,\n                                                 min_pos, max_neg,\n                                                 m_properties.yscale_is (\"log\"),\n                                                 method);\n        }\n      else\n        m_properties.check_axis_limits (limits, kids,\n                                        m_properties.yscale_is (\"log\"),\n                                        update_type);\n    }\n  else if (axis_type == \"zdata\" || axis_type == \"zscale\"\n           || axis_type == \"zlimmode\" || axis_type == \"zliminclude\"\n           || axis_type == \"zlim\")\n    {\n      limits = m_properties.get_zlim ().matrix_value ();\n      FIX_LIMITS;\n\n      update_type = 'z';\n      if (m_properties.zlimmode_is (\"auto\"))\n        {\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');\n\n          m_properties.set_has3Dkids ((max_val - min_val) >\n                                      std::numeric_limits<double>::epsilon ());\n\n          std::string method = m_properties.get_zlimitmethod ();\n          limits = m_properties.get_axis_limits (min_val, max_val,\n                                                 min_pos, max_neg,\n                                                 m_properties.zscale_is (\"log\"),\n                                                 method);\n        }\n      else\n        {\n          // FIXME: get_children_limits is only needed here in order to know\n          // if there are 3-D children.  Is there a way to avoid this call?\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');\n\n          m_properties.set_has3Dkids ((max_val - min_val) >\n                                      std::numeric_limits<double>::epsilon ());\n\n          m_properties.check_axis_limits (limits, kids,\n                                          m_properties.zscale_is (\"log\"),\n                                          update_type);\n        }\n    }\n  else if (axis_type == \"cdata\" || axis_type == \"climmode\"\n           || axis_type == \"cdatamapping\" || axis_type == \"climinclude\"\n           || axis_type == \"clim\")\n    {\n      if (m_properties.climmode_is (\"auto\"))\n        {\n          limits = m_properties.get_clim ().matrix_value ();\n          FIX_LIMITS;\n\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'c');\n\n          if (min_val > max_val)\n            {\n              min_val = min_pos = 0;\n              max_val = 1;\n            }\n          else if (min_val == max_val)\n            {\n              max_val = min_val + 1;\n              min_val -= 1;\n            }\n\n          limits(0) = min_val;\n          limits(1) = max_val;\n\n          update_type = 'c';\n        }\n    }\n  else if (axis_type == \"alphadata\" || axis_type == \"alimmode\"\n           || axis_type == \"alphadatamapping\" || axis_type == \"aliminclude\"\n           || axis_type == \"alim\")\n    {\n      if (m_properties.alimmode_is (\"auto\"))\n        {\n          limits = m_properties.get_alim ().matrix_value ();\n          FIX_LIMITS;\n\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'a');\n\n          if (min_val > max_val)\n            {\n              min_val = min_pos = 0;\n              max_val = 1;\n            }\n          else if (min_val == max_val)\n            max_val = min_val + 1;\n\n          limits(0) = min_val;\n          limits(1) = max_val;\n\n          update_type = 'a';\n        }\n    }\n\n#undef FIX_LIMITS\n\n  octave::unwind_protect_var<std::set<double>>\n      restore_var (updating_axis_limits);\n\n  updating_axis_limits.insert (get_handle ().value ());\n  bool is_auto;\n\n  switch (update_type)\n    {\n    case 'x':\n      is_auto = m_properties.xlimmode_is (\"auto\");\n      m_properties.set_xlim (limits);\n      if (is_auto)\n        m_properties.set_xlimmode (\"auto\");\n      m_properties.update_xlim ();\n      break;\n\n    case 'y':\n      is_auto = m_properties.ylimmode_is (\"auto\");\n      m_properties.set_ylim (limits);\n      if (is_auto)\n        m_properties.set_ylimmode (\"auto\");\n      m_properties.update_ylim ();\n      break;\n\n    case 'z':\n      is_auto = m_properties.zlimmode_is (\"auto\");\n      m_properties.set_zlim (limits);\n      if (is_auto)\n        m_properties.set_zlimmode (\"auto\");\n      m_properties.update_zlim ();\n      break;\n\n    case 'c':\n      m_properties.set_clim (limits);\n      m_properties.set_climmode (\"auto\");\n      break;\n\n    case 'a':\n      m_properties.set_alim (limits);\n      m_properties.set_alimmode (\"auto\");\n      break;\n\n    default:\n      break;\n    }\n\n  m_properties.update_transform ();\n}\n\n// FIXME: This function is called repeatedly while the axes are being set up.\n// There is probably some way to make this more efficient.\n\nvoid\naxes::update_axis_limits (const std::string& axis_type)\n{\n  if ((updating_axis_limits.find (get_handle ().value ())\n       != updating_axis_limits.end ())\n      || (updating_aspectratios.find (get_handle ().value ())\n          != updating_aspectratios.end ()))\n    return;\n\n  Matrix kids = m_properties.get_all_children ();\n\n  double min_val = octave::numeric_limits<double>::Inf ();\n  double max_val = -octave::numeric_limits<double>::Inf ();\n  double min_pos = octave::numeric_limits<double>::Inf ();\n  double max_neg = -octave::numeric_limits<double>::Inf ();\n\n  char update_type = 0;\n\n  Matrix limits;\n\n  if (axis_type == \"xdata\" || axis_type == \"xscale\"\n      || axis_type == \"xlimmode\" || axis_type == \"xliminclude\"\n      || axis_type == \"xlim\")\n    {\n      update_type = 'x';\n      if (m_properties.xlimmode_is (\"auto\"))\n        {\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'x');\n\n          std::string method = m_properties.get_xlimitmethod ();\n          limits = m_properties.get_axis_limits (min_val, max_val,\n                                                 min_pos, max_neg,\n                                                 m_properties.xscale_is (\"log\"),\n                                                 method);\n        }\n      else\n        {\n          limits = m_properties.get_xlim ().matrix_value ();\n          m_properties.check_axis_limits (limits, kids,\n                                          m_properties.xscale_is (\"log\"),\n                                          update_type);\n          if (axis_type == \"xscale\")\n            update_type = 'x';\n        }\n    }\n  else if (axis_type == \"ydata\" || axis_type == \"yscale\"\n           || axis_type == \"ylimmode\" || axis_type == \"yliminclude\"\n           || axis_type == \"ylim\")\n    {\n      update_type = 'y';\n      if (m_properties.ylimmode_is (\"auto\"))\n        {\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'y');\n\n          std::string method = m_properties.get_ylimitmethod ();\n          limits = m_properties.get_axis_limits (min_val, max_val,\n                                                 min_pos, max_neg,\n                                                 m_properties.yscale_is (\"log\"),\n                                                 method);\n        }\n      else\n        {\n          limits = m_properties.get_ylim ().matrix_value ();\n          m_properties.check_axis_limits (limits, kids,\n                                          m_properties.yscale_is (\"log\"),\n                                          update_type);\n          if (axis_type == \"yscale\")\n            update_type = 'y';\n        }\n    }\n  else if (axis_type == \"zdata\" || axis_type == \"zscale\"\n           || axis_type == \"zlimmode\" || axis_type == \"zliminclude\"\n           || axis_type == \"zlim\")\n    {\n      update_type = 'z';\n      if (m_properties.zlimmode_is (\"auto\"))\n        {\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');\n\n          m_properties.set_has3Dkids ((max_val - min_val) >\n                                      std::numeric_limits<double>::epsilon ());\n\n          // FIXME: How to correctly handle (positive or negative) log scale?\n          if ((! octave::math::isfinite (min_val)\n               || ! octave::math::isfinite (max_val))\n              && ! m_properties.zscale_is (\"log\"))\n            min_val = max_val = 0.;\n\n          std::string method = m_properties.get_zlimitmethod ();\n          limits = m_properties.get_axis_limits (min_val, max_val,\n                                                 min_pos, max_neg,\n                                                 m_properties.zscale_is (\"log\"),\n                                                 method);\n        }\n      else\n        {\n          // FIXME: get_children_limits is only needed here in order to know\n          // if there are 3-D children.  Is there a way to avoid this call?\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');\n\n          m_properties.set_has3Dkids ((max_val - min_val) >\n                                      std::numeric_limits<double>::epsilon ());\n\n          limits = m_properties.get_zlim ().matrix_value ();\n          m_properties.check_axis_limits (limits, kids,\n                                          m_properties.zscale_is (\"log\"),\n                                          update_type);\n          if (axis_type == \"zscale\")\n            update_type = 'z';\n        }\n    }\n  else if (axis_type == \"cdata\" || axis_type == \"climmode\"\n           || axis_type == \"cdatamapping\" || axis_type == \"climinclude\"\n           || axis_type == \"clim\")\n    {\n      if (m_properties.climmode_is (\"auto\"))\n        {\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'c');\n\n          if (min_val > max_val)\n            {\n              min_val = min_pos = 0;\n              max_val = 1;\n            }\n          else if (min_val == max_val)\n            {\n              max_val = min_val + 1;\n              min_val -= 1;\n            }\n\n          limits.resize (1, 2);\n\n          limits(0) = min_val;\n          limits(1) = max_val;\n\n          update_type = 'c';\n        }\n\n    }\n  else if (axis_type == \"alphadata\" || axis_type == \"alimmode\"\n           || axis_type == \"alphadatamapping\" || axis_type == \"aliminclude\"\n           || axis_type == \"alim\")\n    {\n      if (m_properties.alimmode_is (\"auto\"))\n        {\n          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'a');\n\n          if (min_val > max_val)\n            {\n              min_val = min_pos = 0;\n              max_val = 1;\n            }\n          else if (min_val == max_val)\n            max_val = min_val + 1;\n\n          limits.resize (1, 2);\n\n          limits(0) = min_val;\n          limits(1) = max_val;\n\n          update_type = 'a';\n        }\n\n    }\n\n  octave::unwind_protect_var<std::set<double>>\n      restore_var (updating_axis_limits);\n\n  updating_axis_limits.insert (get_handle ().value ());\n  bool is_auto;\n\n  switch (update_type)\n    {\n    case 'x':\n      is_auto = m_properties.xlimmode_is (\"auto\");\n      m_properties.set_xlim (limits);\n      if (is_auto)\n        m_properties.set_xlimmode (\"auto\");\n      m_properties.update_xlim ();\n      break;\n\n    case 'y':\n      is_auto = m_properties.ylimmode_is (\"auto\");\n      m_properties.set_ylim (limits);\n      if (is_auto)\n        m_properties.set_ylimmode (\"auto\");\n      m_properties.update_ylim ();\n      break;\n\n    case 'z':\n      is_auto = m_properties.zlimmode_is (\"auto\");\n      m_properties.set_zlim (limits);\n      if (is_auto)\n        m_properties.set_zlimmode (\"auto\");\n      m_properties.update_zlim ();\n      break;\n\n    case 'c':\n      m_properties.set_clim (limits);\n      m_properties.set_climmode (\"auto\");\n      break;\n\n    case 'a':\n      m_properties.set_alim (limits);\n      m_properties.set_alimmode (\"auto\");\n      break;\n\n    default:\n      break;\n    }\n\n  m_properties.update_transform ();\n}\n\ninline double\nforce_in_range (double x, double lower, double upper)\n{\n  if (x < lower)\n    return lower;\n  else if (x > upper)\n    return upper;\n  else\n    return x;\n}\n\nstatic Matrix\ndo_zoom (double val, double factor, const Matrix& lims, bool is_logscale)\n{\n  Matrix new_lims = lims;\n\n  double lo = lims(0);\n  double hi = lims(1);\n\n  bool is_negative = lo < 0 && hi < 0;\n\n  if (is_logscale)\n    {\n      if (is_negative)\n        {\n          double tmp = hi;\n          hi = std::log10 (-lo);\n          lo = std::log10 (-tmp);\n          val = std::log10 (-val);\n        }\n      else\n        {\n          hi = std::log10 (hi);\n          lo = std::log10 (lo);\n          val = std::log10 (val);\n        }\n    }\n\n  // Perform the zooming\n  lo = val + (lo - val) / factor;\n  hi = val + (hi - val) / factor;\n\n  if (is_logscale)\n    {\n      if (is_negative)\n        {\n          double tmp = -std::pow (10.0, hi);\n          hi = -std::pow (10.0, lo);\n          lo = tmp;\n        }\n      else\n        {\n          lo = std::pow (10.0, lo);\n          hi = std::pow (10.0, hi);\n        }\n    }\n\n  new_lims(0) = lo;\n  new_lims(1) = hi;\n\n  return new_lims;\n}\n\nvoid\naxes::properties::zoom_about_point (const std::string& mode,\n                                    double x, double y, double factor,\n                                    bool push_to_zoom_stack)\n{\n  // FIXME: Do we need error checking here?\n  Matrix xlims = get_xlim ().matrix_value ();\n  Matrix ylims = get_ylim ().matrix_value ();\n\n  // Get children axes limits\n  Matrix kids = get_children ();\n  double minx = octave::numeric_limits<double>::Inf ();\n  double maxx = -octave::numeric_limits<double>::Inf ();\n  double min_pos_x = octave::numeric_limits<double>::Inf ();\n  double max_neg_x = -octave::numeric_limits<double>::Inf ();\n  get_children_limits (minx, maxx, min_pos_x, max_neg_x, kids, 'x');\n\n  double miny = octave::numeric_limits<double>::Inf ();\n  double maxy = -octave::numeric_limits<double>::Inf ();\n  double min_pos_y = octave::numeric_limits<double>::Inf ();\n  double max_neg_y = -octave::numeric_limits<double>::Inf ();\n  get_children_limits (miny, maxy, min_pos_y, max_neg_y, kids, 'y');\n\n  xlims = do_zoom (x, factor, xlims, xscale_is (\"log\"));\n  ylims = do_zoom (y, factor, ylims, yscale_is (\"log\"));\n\n  zoom (mode, xlims, ylims, push_to_zoom_stack);\n}\n\nvoid\naxes::properties::zoom (const std::string& mode, double factor,\n                        bool push_to_zoom_stack)\n{\n  // FIXME: Do we need error checking here?\n  Matrix xlims = get_xlim ().matrix_value ();\n  Matrix ylims = get_ylim ().matrix_value ();\n\n  double x = (xlims(0) + xlims(1)) / 2;\n  double y = (ylims(0) + ylims(1)) / 2;\n\n  zoom_about_point (mode, x, y, factor, push_to_zoom_stack);\n}\n\nvoid\naxes::properties::push_zoom_stack ()\n{\n  if (m_zoom_stack.empty ())\n    {\n      m_zoom_stack.push_front (m_xlimmode.get ());\n      m_zoom_stack.push_front (m_xlim.get ());\n      m_zoom_stack.push_front (m_ylimmode.get ());\n      m_zoom_stack.push_front (m_ylim.get ());\n      m_zoom_stack.push_front (m_zlimmode.get ());\n      m_zoom_stack.push_front (m_zlim.get ());\n      m_zoom_stack.push_front (m_view.get ());\n    }\n}\n\nvoid\naxes::properties::zoom (const std::string& mode,\n                        const Matrix& xl, const Matrix& yl,\n                        bool push_to_zoom_stack)\n{\n  if (xl(0) == xl(1) || yl(0) == yl(1))\n    {\n      warning (\"invalid zoom region\");\n      return;\n    }\n\n  if (push_to_zoom_stack)\n    push_zoom_stack ();\n\n  if (mode == \"horizontal\" || mode == \"both\")\n    {\n      m_xlim = xl;\n      m_xlimmode = \"manual\";\n    }\n\n  if (mode == \"vertical\" || mode == \"both\")\n    {\n      m_ylim = yl;\n      m_ylimmode = \"manual\";\n    }\n\n  update_transform ();\n\n  if (mode == \"horizontal\" || mode == \"both\")\n    update_xlim ();\n\n  if (mode == \"vertical\" || mode == \"both\")\n    update_ylim ();\n}\n\nstatic Matrix\ndo_translate (double x0, double x1, const Matrix& lims, bool is_logscale)\n{\n  Matrix new_lims = lims;\n\n  double lo = lims(0);\n  double hi = lims(1);\n\n  bool is_negative = lo < 0 && hi < 0;\n\n  double delta;\n\n  if (is_logscale)\n    {\n      if (is_negative)\n        {\n          double tmp = hi;\n          hi = std::log10 (-lo);\n          lo = std::log10 (-tmp);\n          x0 = -x0;\n          x1 = -x1;\n        }\n      else\n        {\n          hi = std::log10 (hi);\n          lo = std::log10 (lo);\n        }\n\n      delta = std::log10 (x0) - std::log10 (x1);\n    }\n  else\n    {\n      delta = x0 - x1;\n    }\n\n  // Perform the translation\n  lo += delta;\n  hi += delta;\n\n  if (is_logscale)\n    {\n      if (is_negative)\n        {\n          double tmp = -std::pow (10.0, hi);\n          hi = -std::pow (10.0, lo);\n          lo = tmp;\n        }\n      else\n        {\n          lo = std::pow (10.0, lo);\n          hi = std::pow (10.0, hi);\n        }\n    }\n\n  new_lims(0) = lo;\n  new_lims(1) = hi;\n\n  return new_lims;\n}\n\nvoid\naxes::properties::translate_view (const std::string& mode,\n                                  double x0, double x1, double y0, double y1,\n                                  bool push_to_zoom_stack)\n{\n  // FIXME: Do we need error checking here?\n  Matrix xlims = get_xlim ().matrix_value ();\n  Matrix ylims = get_ylim ().matrix_value ();\n\n  // Get children axes limits\n  Matrix kids = get_children ();\n  double minx = octave::numeric_limits<double>::Inf ();\n  double maxx = -octave::numeric_limits<double>::Inf ();\n  double min_pos_x = octave::numeric_limits<double>::Inf ();\n  double max_neg_x = -octave::numeric_limits<double>::Inf ();\n  get_children_limits (minx, maxx, min_pos_x, max_neg_x, kids, 'x');\n\n  double miny = octave::numeric_limits<double>::Inf ();\n  double maxy = -octave::numeric_limits<double>::Inf ();\n  double min_pos_y = octave::numeric_limits<double>::Inf ();\n  double max_neg_y = -octave::numeric_limits<double>::Inf ();\n  get_children_limits (miny, maxy, min_pos_y, max_neg_y, kids, 'y');\n\n  xlims = do_translate (x0, x1, xlims, xscale_is (\"log\"));\n  ylims = do_translate (y0, y1, ylims, yscale_is (\"log\"));\n\n  zoom (mode, xlims, ylims, push_to_zoom_stack);\n}\n\nvoid\naxes::properties::pan (const std::string& mode, double factor,\n                       bool push_to_zoom_stack)\n{\n  // FIXME: Do we need error checking here?\n  Matrix xlims = get_xlim ().matrix_value ();\n  Matrix ylims = get_ylim ().matrix_value ();\n\n  double x0 = (xlims(0) + xlims(1)) / 2;\n  double y0 = (ylims(0) + ylims(1)) / 2;\n\n  double x1 = x0 + (xlims(1) - xlims(0)) * factor;\n  double y1 = y0 + (ylims(1) - ylims(0)) * factor;\n\n  translate_view (mode, x0, x1, y0, y1, push_to_zoom_stack);\n}\n\nvoid\naxes::properties::rotate3d (double x0, double x1, double y0, double y1,\n                            bool push_to_zoom_stack)\n{\n  if (push_to_zoom_stack)\n    push_zoom_stack ();\n\n  Matrix bb = get_boundingbox (true);\n  Matrix new_view = get_view ().matrix_value ();\n\n  // Compute new view angles\n  new_view(0) += ((x0 - x1) * (180.0 / bb(2)));\n  new_view(1) += ((y1 - y0) * (180.0 / bb(3)));\n\n  // Clipping\n  new_view(1) = std::min (new_view(1), 90.0);\n  new_view(1) = std::max (new_view(1), -90.0);\n  if (new_view(0) > 180.0)\n    new_view(0) -= 360.0;\n  else if (new_view(0) < -180.0)\n    new_view(0) += 360.0;\n\n  // Snapping\n  double snapmargin = 1.0;\n  for (int a = -90; a <= 90; a += 90)\n    {\n      if ((a - snapmargin) < new_view(1) && new_view(1) < (a + snapmargin))\n        {\n          new_view(1) = a;\n          break;\n        }\n    }\n\n  for (int a = -180; a <= 180; a += 180)\n    if ((a - snapmargin) < new_view(0) && new_view(0) < (a + snapmargin))\n      {\n        if (a == 180)\n          new_view(0) = -180;\n        else\n          new_view(0) = a;\n        break;\n      }\n\n  // Update axes properties\n  set_view (new_view);\n}\n\nvoid\naxes::properties::rotate_view (double delta_el, double delta_az,\n                               bool push_to_zoom_stack)\n{\n  if (push_to_zoom_stack)\n    push_zoom_stack ();\n\n  Matrix v = get_view ().matrix_value ();\n\n  v(1) += delta_el;\n\n  if (v(1) > 90)\n    v(1) = 90;\n  if (v(1) < -90)\n    v(1) = -90;\n\n  v(0) = fmod (v(0) - delta_az + 720, 360);\n\n  set_view (v);\n\n  update_transform ();\n}\n\nvoid\naxes::properties::unzoom ()\n{\n  if (m_zoom_stack.size () >= 7)\n    {\n      m_view = m_zoom_stack.front ();\n      m_zoom_stack.pop_front ();\n\n      m_zlim = m_zoom_stack.front ();\n      m_zoom_stack.pop_front ();\n\n      m_zlimmode = m_zoom_stack.front ();\n      m_zoom_stack.pop_front ();\n\n      m_ylim = m_zoom_stack.front ();\n      m_zoom_stack.pop_front ();\n\n      m_ylimmode = m_zoom_stack.front ();\n      m_zoom_stack.pop_front ();\n\n      m_xlim = m_zoom_stack.front ();\n      m_zoom_stack.pop_front ();\n\n      m_xlimmode = m_zoom_stack.front ();\n      m_zoom_stack.pop_front ();\n\n      update_transform ();\n\n      update_xlim ();\n      update_ylim ();\n      update_zlim ();\n\n      update_view ();\n    }\n}\n\nvoid\naxes::properties::update_handlevisibility ()\n{\n  if (! is_handle_visible ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go (gh_mgr.get_object (get___myhandle__ ()));\n\n      graphics_object fig (go.get_ancestor (\"figure\"));\n      octave_value ca = fig.get (\"currentaxes\");\n      if (! ca.isempty () && ca.double_value () == m___myhandle__)\n        {\n          octave::autolock guard (gh_mgr.graphics_lock ());\n\n          octave_value kids =  fig.get (\"children\");\n          if (kids.isempty ())\n            fig.set (\"currentaxes\", Matrix ());\n          else\n            {\n              NDArray kidsarray = kids.array_value ();\n              fig.set (\"currentaxes\", kidsarray(0));\n            }\n        }\n    }\n\n  base_properties::update_handlevisibility ();\n}\n\nvoid\nfigure::properties::init_toolkit ()\n{\n  octave::gtk_manager& gtk_mgr = octave::__get_gtk_manager__ ();\n\n  m_toolkit = gtk_mgr.get_toolkit ();\n}\n\nvoid\naxes::properties::clear_zoom_stack (bool do_unzoom)\n{\n  std::size_t items_to_leave_on_stack = (do_unzoom ? 7 : 0);\n\n  while (m_zoom_stack.size () > items_to_leave_on_stack)\n    m_zoom_stack.pop_front ();\n\n  if (do_unzoom)\n    unzoom ();\n}\n\nvoid\naxes::properties::trigger_normals_calc ()\n{\n  // Find all patch (and surface) objects within axes\n  std::list<graphics_object> children_list;\n  std::list<graphics_object>::iterator children_list_iter;\n  get_children_of_type (\"patch\", false, true, children_list);\n  get_children_of_type (\"surface\", false, true, children_list);\n\n  // trigger normals calculation for these objects\n  for (children_list_iter = children_list.begin ();\n       children_list_iter != children_list.end (); children_list_iter++)\n    {\n      graphics_object kid = *children_list_iter;\n      if (kid.isa (\"patch\"))\n        {\n          patch::properties& patch_props\n            = dynamic_cast<patch::properties&> (kid.get_properties ());\n          patch_props.update_normals (false);\n        }\n      else\n        {\n          surface::properties& surface_props\n            = dynamic_cast<surface::properties&> (kid.get_properties ());\n          surface_props.update_normals (false);\n        }\n    }\n}\n\nvoid\naxes::reset_default_properties ()\n{\n  // empty list of local defaults\n  m_default_properties = property_list ();\n\n  // Save warning state of \"Octave:deprecated-property\"\n  int state = toggle_warn (\"Octave:deprecated-property\", false);\n\n  // reset factory defaults\n  remove_all_listeners ();\n  set_defaults (\"reset\");\n\n  toggle_warn (\"Octave:deprecated-property\", true, state);\n}\n\nvoid\naxes::initialize (const graphics_object& go)\n{\n  base_graphics_object::initialize (go);\n\n  xinitialize (m_properties.get_title ());\n  xinitialize (m_properties.get_xlabel ());\n  xinitialize (m_properties.get_ylabel ());\n  xinitialize (m_properties.get_zlabel ());\n\n  m_properties.sync_positions ();\n}\n\n// ---------------------------------------------------------------------\n\nMatrix\nline::properties::compute_xlim () const\n{\n  Matrix m (1, 4);\n\n  m(0) = m_xdata.min_val ();\n  m(1) = m_xdata.max_val ();\n  m(2) = m_xdata.min_pos ();\n  m(3) = m_xdata.max_neg ();\n\n  return m;\n}\n\nMatrix\nline::properties::compute_ylim () const\n{\n  Matrix m (1, 4);\n\n  m(0) = m_ydata.min_val ();\n  m(1) = m_ydata.max_val ();\n  m(2) = m_ydata.min_pos ();\n  m(3) = m_ydata.max_neg ();\n\n  return m;\n}\n\n// ---------------------------------------------------------------------\n\nMatrix\ntext::properties::get_data_position () const\n{\n  Matrix pos = get_position ().matrix_value ();\n\n  if (! units_is (\"data\"))\n    pos = convert_text_position (pos, *this, get_units (), \"data\");\n\n  return pos;\n}\n\nMatrix\ntext::properties::get_extent_matrix (bool rotated) const\n{\n  // FIXME: Should this function also add the (x,y) base position?\n  Matrix ext = m_extent.get ().matrix_value ();\n\n  if (rotated && get_rotation () != 0)\n    {\n      double rot = get_rotation () * 4.0 * atan (1.0) / 180;\n      double x0 = ext(0) * cos (rot) - ext(1) * sin (rot);\n      double x1 = x0;\n      double y0 = ext(0) * sin (rot) + ext(1) * cos (rot);\n      double y1 = y0;\n\n      double tmp = (ext(0)+ext(2)) * cos (rot) - ext(1) * sin (rot);\n      x0 = std::min (x0, tmp);\n      x1 = std::max (x1, tmp);\n      tmp = (ext(0)+ext(2)) * sin (rot) + ext(1) * cos (rot);\n      y0 = std::min (y0, tmp);\n      y1 = std::max (y1, tmp);\n\n      tmp = (ext(0)+ext(2)) * cos (rot) - (ext(1)+ext(3)) * sin (rot);\n      x0 = std::min (x0, tmp);\n      x1 = std::max (x1, tmp);\n      tmp = (ext(0)+ext(2)) * sin (rot) + (ext(1)+ext(3)) * cos (rot);\n      y0 = std::min (y0, tmp);\n      y1 = std::max (y1, tmp);\n\n      tmp = ext(0) * cos (rot) - (ext(1)+ext(3)) * sin (rot);\n      x0 = std::min (x0, tmp);\n      x1 = std::max (x1, tmp);\n      tmp = ext(0) * sin (rot) + (ext(1)+ext(3)) * cos (rot);\n      y0 = std::min (y0, tmp);\n      y1 = std::max (y1, tmp);\n\n      ext(0) = x0;\n      ext(1) = y0;\n      ext(2) = x1 - x0;\n      ext(3) = y1 - y0;\n    }\n\n  return ext;\n}\n\noctave_value\ntext::properties::get_extent () const\n{\n  // FIXME: This doesn't work right for 3-D plots.\n  // (It doesn't in Matlab either, at least not in version 6.5.)\n  Matrix m = get_extent_matrix (true);\n  Matrix pos = get_position ().matrix_value ();\n  Matrix p = convert_text_position (pos, *this, get_units (), \"pixels\");\n\n  m(0) += p(0);\n  m(1) += p(1);\n\n  Matrix bbox = convert_text_position (m, *this, \"pixels\", get_units ());\n\n  double dpr = device_pixel_ratio (get___myhandle__ ());\n\n  for (octave_idx_type ii = 0; ii < bbox.numel (); ii++)\n    bbox(ii) = bbox(ii) / dpr;\n\n  return bbox;\n}\n\nvoid\ntext::properties::set_fontunits (const octave_value& val)\n{\n  caseless_str old_fontunits = get_fontunits ();\n\n  if (m_fontunits.set (val, true))\n    {\n      update_fontunits (old_fontunits);\n      mark_modified ();\n    }\n}\n\nvoid\ntext::properties::update_fontunits (const caseless_str& old_units)\n{\n  caseless_str new_units = get_fontunits ();\n  double parent_height = 0;\n  double fontsz = get_fontsize ();\n\n  if (new_units == \"normalized\" || old_units == \"normalized\")\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go (gh_mgr.get_object (get___myhandle__ ()));\n\n      graphics_object ax (go.get_ancestor (\"axes\"));\n\n      parent_height = ax.get_properties ().get_boundingbox (true).elem (3);\n    }\n\n  fontsz = convert_font_size (fontsz, old_units, new_units, parent_height);\n\n  set_fontsize (octave_value (fontsz));\n}\n\nvoid\ntext::properties::update_font ()\n{\n  double dpr = device_pixel_ratio (get___myhandle__ ());\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  m_txt_renderer.set_font (get (\"fontname\").string_value (),\n                           get (\"fontweight\").string_value (),\n                           get (\"fontangle\").string_value (),\n                           get (\"__fontsize_points__\").double_value () * dpr);\n\n  m_txt_renderer.set_anti_aliasing (is_fontsmoothing ());\n\n  Matrix c = get_color_rgb ();\n  if (! c.isempty ())\n    m_txt_renderer.set_color (c);\n\n}\n\nvoid\ntext::properties::update_text_extent ()\n{\n  int halign = 0;\n  int valign = 0;\n\n  if (horizontalalignment_is (\"center\"))\n    halign = 1;\n  else if (horizontalalignment_is (\"right\"))\n    halign = 2;\n\n  if (verticalalignment_is (\"middle\"))\n    valign = 1;\n  else if (verticalalignment_is (\"top\"))\n    valign = 2;\n  else if (verticalalignment_is (\"baseline\"))\n    valign = 3;\n  else if (verticalalignment_is (\"cap\"))\n    valign = 4;\n\n  Matrix bbox;\n\n  // FIXME: string should be parsed only when modified, for efficiency\n\n  octave_value string_prop = get_string ();\n\n  string_vector sv = string_prop.string_vector_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  m_txt_renderer.text_to_pixels (sv.join (\"\\n\"), m_pixels, bbox,\n                                 halign, valign, 0.0, get_interpreter ());\n  // The bbox is relative to the text's position.  We'll leave it that\n  // way, because get_position does not return valid results when the\n  // text is first constructed.  Conversion to proper coordinates is\n  // performed in get_extent.\n  set_extent (bbox);\n\n  if (__autopos_tag___is (\"xlabel\") || __autopos_tag___is (\"ylabel\")\n      || __autopos_tag___is (\"zlabel\") || __autopos_tag___is (\"title\"))\n    update_autopos (\"sync\");\n}\n\nvoid\ntext::properties::request_autopos ()\n{\n  if (__autopos_tag___is (\"xlabel\") || __autopos_tag___is (\"ylabel\")\n      || __autopos_tag___is (\"zlabel\") || __autopos_tag___is (\"title\"))\n    update_autopos (get___autopos_tag__ ());\n}\n\nvoid\ntext::properties::update_units ()\n{\n  if (! units_is (\"data\"))\n    {\n      set_xliminclude (\"off\");\n      set_yliminclude (\"off\");\n      set_zliminclude (\"off\");\n    }\n\n  Matrix pos = get_position ().matrix_value ();\n\n  pos = convert_text_position (pos, *this, m_cached_units, get_units ());\n\n  // FIXME: if the current axes view is 2-D, then one should probably drop\n  // the z-component of \"pos\" and leave \"zliminclude\" to \"off\".\n\n  bool autopos = positionmode_is (\"auto\");\n\n  set_position (pos);\n\n  if (autopos)\n    set_positionmode (\"auto\");\n\n  if (units_is (\"data\"))\n    {\n      set_xliminclude (\"on\");\n      set_yliminclude (\"on\");\n      // FIXME: see above\n      set_zliminclude (\"off\");\n    }\n\n  m_cached_units = get_units ();\n}\n\ndouble\ntext::properties::get___fontsize_points__ (double box_pix_height) const\n{\n  double fontsz = get_fontsize ();\n  double parent_height = box_pix_height;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go (gh_mgr.get_object (get___myhandle__ ()));\n\n  if (fontunits_is (\"normalized\") && parent_height <= 0)\n    {\n      graphics_object ax (go.get_ancestor (\"axes\"));\n\n      parent_height = ax.get_properties ().get_boundingbox (true).elem (3);\n    }\n\n  return convert_font_size (fontsz, get_fontunits (), \"points\", parent_height);\n}\n\n// ---------------------------------------------------------------------\n\noctave_value\nimage::properties::get_color_data () const\n{\n  return convert_cdata (*this, get_cdata (), cdatamapping_is (\"scaled\"), 3);\n}\n\n// ---------------------------------------------------------------------\n\nvoid\nlight::initialize (const graphics_object& go)\n{\n  base_graphics_object::initialize (go);\n\n  // trigger normals calculation for the respective children of this axes object\n  axes::properties& parent_axes_prop\n    = dynamic_cast<axes::properties&> (go.get_ancestor (\"axes\").get_properties ());\n  parent_axes_prop.trigger_normals_calc ();\n}\n\nvoid\nlight::properties::update_visible ()\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get___myhandle__ ());\n\n  axes::properties& ax_props = dynamic_cast<axes::properties&>\n                               (go.get_ancestor (\"axes\").get_properties ());\n  if (is_visible ())\n    ax_props.increase_num_lights ();\n  else\n    ax_props.decrease_num_lights ();\n}\n\n// ---------------------------------------------------------------------\n\nbool\npatch::properties::get_do_lighting () const\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get___myhandle__ ());\n\n  axes::properties& ax_props = dynamic_cast<axes::properties&>\n                               (go.get_ancestor (\"axes\").get_properties ());\n\n  return (ax_props.get_num_lights () > 0);\n}\n\noctave_value\npatch::properties::get_color_data () const\n{\n  octave_value fvc = get_facevertexcdata ();\n  if (fvc.is_undefined () || fvc.isempty ())\n    return Matrix ();\n  else\n    return convert_cdata (*this, fvc, cdatamapping_is (\"scaled\"), 2);\n}\n\nstatic bool updating_patch_data = false;\n\nvoid\npatch::properties::update_fvc ()\n{\n  if (updating_patch_data)\n    return;\n\n  Matrix xd = get_xdata ().matrix_value ();\n  Matrix yd = get_ydata ().matrix_value ();\n  Matrix zd = get_zdata ().matrix_value ();\n  NDArray cd = get_cdata ().array_value ();\n\n  m_bad_data_msg = \"\";\n  if (xd.dims () != yd.dims ()\n      || (xd.dims () != zd.dims () && ! zd.isempty ()))\n    {\n      m_bad_data_msg = \"x/y/zdata must have the same dimensions\";\n      return;\n    }\n\n  octave_idx_type nv = xd.rows ();\n  octave_idx_type nf = xd.columns ();\n  octave_idx_type ncv = cd.rows ();\n  octave_idx_type ncf = cd.columns ();\n  if ((ncf > 1 || ncv > 1) && ((ncf != nf) || (ncv != 1 && ncv != nv)))\n    {\n      m_bad_data_msg = \"cdata does not match number of faces \"\n                       \"or number of vertices per face\";\n      return;\n    }\n\n  bool isRGB = false;\n  if (cd.ndims () == 3)\n    isRGB = true;\n\n  // Faces and Vertices\n  dim_vector dv;\n  bool is3D = false;\n  if (nv == 1 && nf > 1)\n    {\n      nv = nf;\n      nf = 1;\n      xd = xd.as_column ();\n      yd = yd.as_column ();\n      zd = zd.as_column ();\n    }\n\n  bool pervertex = false;\n  if (ncv == nv)\n    pervertex = true;\n\n  dv(0) = nv * nf;\n  if (zd.isempty ())\n    dv(1) = 2;\n  else\n    {\n      dv(1) = 3;\n      is3D = true;\n    }\n\n  Matrix vert (dv);\n  Matrix idx (nf, nv);\n\n  Matrix fvc;\n  if (pervertex)\n    {\n      // \"facevertexcdata\" holds color data per vertex\n      fvc.resize (nv * nf, (isRGB ? 3 : 1));\n    }\n  else if (! cd.isempty ())\n    {\n      // \"facevertexcdata\" holds color data per face\n      dv(0) = ncf;\n      dv(1) = (isRGB ? 3 : 1);\n      fvc = cd.reshape (dv);\n    }\n\n  // create list of vertices from x/y/zdata\n  // FIXME: It might be possible to share vertices between adjacent faces.\n  octave_idx_type kk = 0;\n  for (octave_idx_type jj = 0; jj < nf; jj++)\n    {\n      for (octave_idx_type ii = 0; ii < nv; ii++)\n        {\n          vert(kk, 0) = xd(ii, jj);\n          vert(kk, 1) = yd(ii, jj);\n          if (is3D)\n            vert(kk, 2) = zd(ii, jj);\n\n          if (pervertex)\n            {\n              fvc(kk, 0) = cd(ii, jj, 0);\n              if (isRGB)\n                {\n                  fvc(kk, 1) = cd(ii, jj, 1);\n                  fvc(kk, 2) = cd(ii, jj, 2);\n                }\n            }\n\n          idx(jj, ii) = static_cast<double> (kk+1);\n\n          kk++;\n        }\n    }\n\n  // FIXME: shouldn't we update facevertexalphadata here ?\n\n  octave::unwind_protect_var<bool> restore_var (updating_patch_data, true);\n\n  m_faces.set (idx);\n  m_vertices.set (vert);\n  m_facevertexcdata.set (fvc);\n\n  updating_patch_data = false;\n  update_data ();\n}\n\n// core coplanar tester\nbool\nis_coplanar (const Matrix& cov)\n{\n  // Accuracy note: this test will also accept single precision input (although\n  // stored in double precision).  This is because the error threshold is\n  // sqrt(tol) = 1.5e-7.\n  double tol = 100 * std::numeric_limits<double>::epsilon ();\n  EIG eig (cov, false, false, true);\n  ColumnVector ev = real (eig.eigenvalues ());\n  return ev.min () <= tol * ev.max ();\n}\n\nstd::vector<octave_idx_type>\ncoplanar_partition (const Matrix& vert, const Matrix& idx,\n                    octave_idx_type nc, octave_idx_type jj)\n{\n  std::vector<octave_idx_type> coplanar_ends;\n\n  Matrix plane_pivot = Matrix (1, 3, 0.0);\n  for (octave_idx_type i = 0; i < 3; i++)\n    plane_pivot(0, i) = vert(idx(0, jj)-1, i);\n\n  Matrix fc = Matrix (0, 3, 0.0);  // face corner vertex coordinates\n  Matrix fa = Matrix (1, 3, 0.0);  // for append face corner\n  Matrix coor_cov = Matrix (3, 3, 0.0);\n\n  if (nc >= 5)\n    {\n      // Coplanar test that involves all points.\n      // For nc == 4, this initial test is not beneficial at all.\n      // If the probability of coplanar input is more than half, for\n      // the best average performance, we should use nc >= 5.\n      // Higher threshold is meaningful only when input is known to be\n      // non-coplanar and nc is small.\n\n      fc.resize (nc - 1, 3);\n      for (octave_idx_type j = 1; j < nc; j++)\n        for (octave_idx_type i = 0; i < 3; i++)\n          fc(j-1, i) = vert(idx(j, jj)-1, i) - plane_pivot(i);\n\n      coor_cov = fc.transpose () * fc;\n      if (is_coplanar (coor_cov))\n        {\n          coplanar_ends.push_back (nc - 1);\n          return coplanar_ends;\n        }\n    }\n\n  fc.resize (3, 3);\n  octave_idx_type i_start = 1;\n  octave_idx_type i_end = 2;\n\n  // Split the polygon into coplanar segments.\n  // The first point is common corner of all planes.\n  while (i_start < nc - 1)\n    {\n      i_end = i_start + 2;\n      if (i_end > nc - 1)\n        {\n          coplanar_ends.push_back (nc - 1);\n          break;\n        }\n\n      // Algorithm: Start from 3 points, keep adding points until the point set\n      // is no more in a plane.  Record the coplanar point set, then advance\n      // i_start.\n\n      // Prepare 1+3 points for coplanar test.\n      // The first point is implicitly included.\n      for (octave_idx_type j = 0; j < 3; j++)\n        for (octave_idx_type i = 0; i < 3; i++)\n          fc(j, i) = vert(idx(j+i_start, jj)-1, i) - plane_pivot(i);\n\n      // covariance matrix between coordinates of vertices\n      coor_cov = fc.transpose () * fc;\n\n      while (true)\n        {\n          // coplanar test\n          if (! is_coplanar (coor_cov))\n            break;\n\n          i_end++;\n          if (i_end > nc - 1)\n            break;\n\n          // add a point to plane\n          for (octave_idx_type i = 0; i < 3; i++)\n            fa(0, i) = vert(idx(i_end, jj)-1, i) - plane_pivot(i);\n          coor_cov += fa.transpose () * fa;\n        }\n\n      i_start = i_end - 1;\n      coplanar_ends.push_back (i_start);\n    }\n  return coplanar_ends;\n}\n\nvoid\npatch::properties::update_data ()\n{\n  if (updating_patch_data)\n    return;\n\n  Matrix idx = get_faces ().matrix_value ().transpose ();\n  Matrix vert = get_vertices ().matrix_value ();\n  NDArray fvc = get_facevertexcdata ().array_value ();\n\n  octave_idx_type nfaces = idx.columns ();\n  octave_idx_type nvert = vert.rows ();\n\n  // Check all vertices in faces are defined\n  m_bad_data_msg = \"\";\n  if (static_cast<double> (nvert) < idx.row_max ().max ())\n    {\n      m_bad_data_msg = R\"(some vertices in \"faces\" property are undefined)\";\n      return;\n    }\n\n  // Check if number of color values matches number of faces or vertices\n  octave_idx_type nfvc = fvc.rows ();\n  if (nfvc > 1 && nfvc != nfaces && nfvc != nvert)\n    {\n      m_bad_data_msg = \"number of facevertexcdata values matches \"\n                       \"neither number of faces nor number of vertices\";\n      return;\n    }\n\n  // Replace NaNs\n  if (idx.any_element_is_inf_or_nan ())\n    {\n      for (octave_idx_type jj = 0; jj < idx.columns (); jj++)\n        {\n          double valid_vert = idx(0, jj);\n          bool turn_valid = false;\n          for (octave_idx_type ii = 0; ii < idx.rows (); ii++)\n            {\n              if (octave::math::isnan (idx(ii, jj)) || turn_valid)\n                {\n                  idx(ii, jj) = valid_vert;\n                  turn_valid = true;\n                }\n              else\n                valid_vert = idx(ii, jj);\n            }\n        }\n    }\n\n  // check coplanarity for 3-D-faces with more than 3 corners\n  int fcmax = idx.rows ();\n  if (fcmax > 3 && vert.columns () > 2\n      && ! (facecolor_is (\"none\") && edgecolor_is (\"none\")))\n    {\n      m_coplanar_last_idx.resize (idx.columns ());\n      for (octave_idx_type jj = 0; jj < idx.columns (); jj++)\n        {\n          if (octave::math::isnan (idx(3, jj)))\n            continue;\n\n          // find first element that is NaN to get number of corners\n          octave_idx_type nc = 3;\n          while (nc < fcmax && ! octave::math::isnan (idx(nc, jj)))\n            nc++;\n\n          // If any of the corners is NaN or Inf, skip coplanar test.\n          // FIXME: Add support for non-coplanar faces with unclosed contour.\n          bool is_unclosed = false;\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              const octave_idx_type k = idx(j, jj) - 1;\n              if (! (octave::math::isfinite (vert(k, 0))\n                     && octave::math::isfinite (vert(k, 1))\n                     && octave::math::isfinite (vert(k, 2))))\n                {\n                  is_unclosed = true;\n                  break;\n                }\n            }\n          if (is_unclosed)\n            continue;\n\n          m_coplanar_last_idx[jj] = coplanar_partition (vert, idx, nc, jj);\n        }\n    }\n  else\n    m_coplanar_last_idx.resize (0);\n\n  // Build cdata\n  dim_vector dv = dim_vector::alloc (3);\n  NDArray cd;\n  bool pervertex = false;\n\n  if (fvc.rows () == nfaces || fvc.rows () == 1)\n    {\n      // \"facevertexcdata\" holds color data per face or same color for all\n      dv(0) = 1;\n      dv(1) = fvc.rows ();\n      dv(2) = fvc.columns ();\n      cd = fvc.reshape (dv);\n    }\n  else if (! fvc.isempty ())\n    {\n      // \"facevertexcdata\" holds color data per vertex\n      dv(0) = idx.rows ();\n      dv(1) = nfaces;\n      dv(2) = fvc.columns ();\n      cd.resize (dv);\n      pervertex = true;\n    }\n\n  // Build x,y,zdata and eventually per vertex cdata\n  Matrix xd (idx.dims ());\n  Matrix yd (idx.dims ());\n  Matrix zd;\n  bool has_zd = false;\n  if (vert.columns () > 2)\n    {\n      zd = Matrix (idx.dims ());\n      has_zd = true;\n    }\n\n  for (octave_idx_type jj = 0; jj < nfaces; jj++)\n    {\n      for (octave_idx_type ii = 0; ii < idx.rows (); ii++)\n        {\n          octave_idx_type row = static_cast<octave_idx_type> (idx(ii, jj)-1);\n          xd(ii, jj) = vert(row, 0);\n          yd(ii, jj) = vert(row, 1);\n\n          if (has_zd)\n            zd(ii, jj) = vert(row, 2);\n\n          if (pervertex)\n            for (int kk = 0; kk < fvc.columns (); kk++)\n              cd(ii, jj, kk) = fvc(row, kk);\n        }\n    }\n\n  // Update normals\n  update_normals (true);\n\n  octave::unwind_protect_var<bool> restore_var (updating_patch_data, true);\n\n  set_xdata (xd);\n  set_ydata (yd);\n  set_zdata (zd);\n  set_cdata (cd);\n}\n\ninline void\ncross_product (double x1, double y1, double z1,\n               double x2, double y2, double z2,\n               double& x, double& y, double& z)\n{\n  x += (y1 * z2 - z1 * y2);\n  y += (z1 * x2 - x1 * z2);\n  z += (x1 * y2 - y1 * x2);\n}\n\nvoid\npatch::properties::calc_face_normals (Matrix& fn)\n{\n  Matrix v = get_vertices ().matrix_value ();\n  Matrix f = get_faces ().matrix_value ();\n\n  bool is_3D = (v.columns () == 3);   // 2-D or 3-D patches\n  octave_idx_type num_f = f.rows ();  // number of faces\n  octave_idx_type max_nc = f.columns ();  // max. number of polygon corners\n\n  // In which cases can we skip updating the normals?\n  if (max_nc < 3)\n    {\n      fn = Matrix ();\n      return;\n    }\n\n  // Calculate normals for all faces\n  octave_idx_type i1, i2, i3;\n  octave_idx_type j1, j2;\n  for (octave_idx_type i = 0; i < num_f; i++)\n    {\n      bool is_coplanar = true;\n      if (m_coplanar_last_idx.size () > 0 && m_coplanar_last_idx[i].size () > 1)\n        is_coplanar = false;\n\n      // get number of corners\n      octave_idx_type nc = 3;\n      if (max_nc > 3)\n        {\n          while (nc < max_nc && ! octave::math::isnan (f(i, nc)))\n            nc++;\n        }\n\n      std::array<double, 3> fnc = {0.0, 0.0, 0.0};\n      double& nx = fnc[0];\n      double& ny = fnc[1];\n      double& nz = fnc[2];\n\n      if (is_coplanar)\n        {\n          // fast way for coplanar polygons\n          i1 = f(i, 0) - 1; i2 = f(i, 1) - 1; i3 = f(i, nc-1) - 1;\n\n          if (is_3D)\n            cross_product\n            (v(i3, 0) - v(i1, 0), v(i3, 1) - v(i1, 1), v(i3, 2) - v(i1, 2),\n             v(i2, 0) - v(i1, 0), v(i2, 1) - v(i1, 1), v(i2, 2) - v(i1, 2),\n             nx, ny, nz);\n          else\n            {\n              nz = (v(i2, 0) - v(i1, 0)) * (v(i3, 1) - v(i1, 1)) -\n                   (v(i2, 1) - v(i1, 1)) * (v(i3, 0) - v(i1, 0));\n              // 2-D vertices always point towards +z\n              nz = (nz < 0) ? -nz : nz;\n            }\n        }\n      else\n        {\n          // more general for non-planar polygons\n\n          // calculate face normal with Newell's method\n          // https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal#Newell.27s_Method\n\n          j1 = nc - 1; j2 = 0;\n          i1 = f(i, j1) - 1; i2 = f(i, j2) - 1;\n\n          nx = (v(i2, 1) - v(i1, 1)) * (v(i1, 2) + v(i2, 2));\n          ny = (v(i2, 2) - v(i1, 2)) * (v(i1, 0) + v(i2, 0));\n          nz = (v(i2, 0) - v(i1, 0)) * (v(i1, 1) + v(i2, 1));\n\n          for (octave_idx_type j = 1; j < nc; j++)\n            {\n              j1 = j-1; j2 = j;\n              i1 = f(i, j1) - 1; i2 = f(i, j2) - 1;\n\n              nx += (v(i2, 1) - v(i1, 1)) * (v(i1, 2) + v(i2, 2));\n              ny += (v(i2, 2) - v(i1, 2)) * (v(i1, 0) + v(i2, 0));\n              nz += (v(i2, 0) - v(i1, 0)) * (v(i1, 1) + v(i2, 1));\n            }\n        }\n\n      // normalize normal vector\n      double n_len = sqrt (nx*nx+ny*ny+nz*nz);\n\n      // assign normal to current face\n      if ( n_len < std::numeric_limits<double>::epsilon () )\n        for (octave_idx_type j = 0; j < 3; j++)\n          fn(i, j) = 0.0;\n      else\n        for (octave_idx_type j = 0; j < 3; j++)\n          fn(i, j) = fnc[j] / n_len;\n    }\n}\n\nvoid\npatch::properties::update_face_normals (bool reset, bool force)\n{\n  if (updating_patch_data || ! facenormalsmode_is (\"auto\"))\n    return;\n\n  if (force || ((facelighting_is (\"flat\") || edgelighting_is (\"flat\"))\n                && get_do_lighting ()))\n    {\n      Matrix f = get_faces ().matrix_value ();\n\n      octave_idx_type num_f = f.rows ();  // number of faces\n      Matrix fn (num_f, 3, 0.0);\n\n      calc_face_normals (fn);\n      m_facenormals = fn;\n    }\n  else if (reset)\n    m_facenormals = Matrix ();\n}\n\nvoid\npatch::properties::update_vertex_normals (bool reset, bool force)\n{\n  if (updating_patch_data || ! vertexnormalsmode_is (\"auto\"))\n    return;\n\n  if (force || ((facelighting_is (\"gouraud\") || facelighting_is (\"phong\")\n                 || edgelighting_is (\"gouraud\") || edgelighting_is (\"phong\"))\n                && get_do_lighting ()))\n    {\n      Matrix v = get_vertices ().matrix_value ();\n      Matrix f = get_faces ().matrix_value ();\n\n      octave_idx_type num_v = v.rows ();      // number of vertices\n      octave_idx_type num_f = f.rows ();      // number of faces\n      octave_idx_type max_nc = f.columns ();  // max. number of polygon corners\n\n      // In which cases can we skip updating the normals?\n      if (max_nc < 3)\n        return;\n\n      // First step: Calculate the normals for all faces\n      Matrix fn = get_facenormals ().matrix_value ();\n      if ( fn.isempty () )\n        {\n          // calculate facenormals here\n          fn = Matrix (num_f, 3, 0.0);\n          calc_face_normals (fn);\n        }\n\n      // Second step: assign normals to the respective vertices\n\n      // The following code collects the face normals for all faces adjacent to\n      // each vertex.  For this, a std::vector of length NUM_V (which might be\n      // very large) is used so that memory is allocated from the heap rather\n      // than the stack.  Each element of this vector corresponds to one vertex\n      // of the patch.  The element itself is a variable length std::vector.\n      // This second vector contains the face normals (of type RowVector) of\n      // the adjacent faces.\n      std::vector<std::vector<RowVector>> vec_vn (num_v);\n      for (octave_idx_type i = 0; i < num_f; i++)\n        {\n          // get number of corners\n          octave_idx_type nc = 3;\n          if (max_nc > 3)\n            {\n              while (nc < max_nc && ! octave::math::isnan (f(i, nc)))\n                nc++;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            vec_vn[static_cast<octave_idx_type> (f(i, j) - 1)].push_back (fn.row (i));\n        }\n\n      // Third step: Calculate the normal for the vertices taking the average\n      // of the normals determined from all adjacent faces\n      Matrix vn (num_v, 3, 0.0);\n      for (octave_idx_type i = 0; i < num_v; i++)\n        {\n          std::vector<RowVector>::iterator it = vec_vn[i].begin ();\n\n          // The normal of unused vertices is NaN.\n          RowVector vn0 (3, octave_NaN);\n\n          if (it != vec_vn[i].end ())\n            {\n              // FIXME: Currently, the first vector also determines the\n              // direction of the normal.  How to determine the inner and outer\n              // faces of all parts of the patch and point the normals outwards?\n              // (Necessary for correct lighting with \"backfacelighting\" set to\n              // \"lit\" or \"unlit\".)  Matlab does not seem to do it correctly\n              // either.  So should we bother?\n\n              vn0 = *it;\n\n              for (++it; it != vec_vn[i].end (); ++it)\n                {\n                  RowVector vn1 = *it;\n                  // Use sign of dot product to point vectors in a similar\n                  // direction before taking the average.\n                  double dir = (vn0(0)*vn1(0) + vn0(1)*vn1(1) + vn0(2)*vn1(2) < 0) ? -1 : 1;\n                  for (octave_idx_type j = 0; j < 3; j++)\n                    vn0(j) += dir * vn1(j);\n                }\n\n              // normalize normal vector\n              double n_len = sqrt (vn0(0)*vn0(0)+vn0(1)*vn0(1)+vn0(2)*vn0(2));\n\n              // save normal in matrix\n              for (octave_idx_type j = 0; j < 3; j++)\n                vn(i, j) = vn0(j)/n_len;\n            }\n        }\n\n      m_vertexnormals = vn;\n    }\n  else if (reset)\n    m_vertexnormals = Matrix ();\n}\n\nvoid\npatch::initialize (const graphics_object& go)\n{\n  base_graphics_object::initialize (go);\n\n  // calculate normals for default data\n  // This is done because the normals for the default data do not match\n  // get(0, \"DefaultPatchVertexNormals\") in Matlab.\n  m_properties.update_normals (true);\n}\n\n\nvoid\npatch::reset_default_properties ()\n{\n  // empty list of local defaults\n  m_default_properties = property_list ();\n  xreset_default_properties (get_handle (), m_properties.factory_defaults ());\n\n  // calculate normals for default data\n  // This is done because the normals for the default data do not match\n  // get(0, \"DefaultPatchVertexNormals\") in Matlab.\n  m_properties.update_normals (true);\n}\n\n// ---------------------------------------------------------------------\n\noctave_value\nscatter::properties::get_color_data () const\n{\n  octave_value c = get_cdata ();\n  if (c.is_undefined () || c.isempty ())\n    return Matrix ();\n  else\n    return convert_cdata (*this, c, c.columns () == 1, 2);\n}\n\nvoid\nscatter::properties::update_data ()\n{\n  Matrix xd = get_xdata ().matrix_value ();\n  Matrix yd = get_ydata ().matrix_value ();\n  Matrix zd = get_zdata ().matrix_value ();\n  Matrix cd = get_cdata ().matrix_value ();\n  Matrix sd = get_sizedata ().matrix_value ();\n\n  m_bad_data_msg = \"\";\n  if (xd.dims () != yd.dims ()\n      || (xd.dims () != zd.dims () && ! zd.isempty ()))\n    {\n      m_bad_data_msg = \"x/y/zdata must have the same dimensions\";\n      return;\n    }\n\n  octave_idx_type x_rows = xd.rows ();\n  octave_idx_type c_cols = cd.columns ();\n  octave_idx_type c_rows = cd.rows ();\n\n  if (! cd.isempty () && (c_rows != 1 || c_cols != 3)\n      && (c_rows != x_rows || (c_cols != 1 && c_cols != 3)))\n    {\n      m_bad_data_msg = \"cdata must be an rgb triplet or have the same number \"\n                       \"of rows as X and one or three columns\";\n      return;\n    }\n\n  octave_idx_type s_rows = sd.rows ();\n  if (s_rows != 1 && s_rows != x_rows)\n    {\n      m_bad_data_msg = \"sizedata must be a scalar or a vector with the same \"\n                       \"dimensions as X\";\n      return;\n    }\n}\n\nstatic bool updating_scatter_cdata = false;\n\nvoid\nscatter::properties::update_color ()\n{\n  if (updating_scatter_cdata)\n    return;\n\n  Matrix series_idx = get_seriesindex ().matrix_value ();\n  if (series_idx.isempty ())\n    return;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get___myhandle__ ());\n\n  axes::properties& parent_axes_prop\n    = dynamic_cast<axes::properties&>\n      (go.get_ancestor (\"axes\").get_properties ());\n\n  Matrix color_order = parent_axes_prop.get_colororder ().matrix_value ();\n  octave_idx_type s = (static_cast<octave_idx_type> (series_idx(0)) - 1)\n                      % color_order.rows ();\n\n  Matrix color = Matrix (1, 3, 0.);\n  color(0) = color_order(s, 0);\n  color(1) = color_order(s, 1);\n  color(2) = color_order(s, 2);\n\n  octave::unwind_protect_var<bool> restore_var (updating_scatter_cdata, true);\n\n  set_cdata (color);\n  set_cdatamode (\"auto\");\n}\n\nvoid\nscatter::initialize (const graphics_object& go)\n{\n  base_graphics_object::initialize (go);\n\n  Matrix series_idx = m_properties.get_seriesindex ().matrix_value ();\n  if (series_idx.isempty ())\n    {\n      // Increment series index counter in parent axes\n      axes::properties& parent_axes_prop\n        = dynamic_cast<axes::properties&>\n          (go.get_ancestor (\"axes\").get_properties ());\n\n      if (! parent_axes_prop.nextplot_is (\"add\"))\n        parent_axes_prop.set_nextseriesindex (1);\n\n      series_idx.resize (1, 1);\n      series_idx(0) = parent_axes_prop.get_nextseriesindex ();\n      m_properties.set_seriesindex (series_idx);\n\n      parent_axes_prop.set_nextseriesindex\n      (parent_axes_prop.get_nextseriesindex () + 1);\n    }\n\n  if (m_properties.cdatamode_is (\"auto\"))\n    m_properties.update_color ();\n}\n\n// ---------------------------------------------------------------------\n\noctave_value\nsurface::properties::get_color_data () const\n{\n  return convert_cdata (*this, get_cdata (), cdatamapping_is (\"scaled\"), 3);\n}\n\nbool\nsurface::properties::get_do_lighting () const\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get___myhandle__ ());\n\n  axes::properties& ax_prop = dynamic_cast<axes::properties&>\n                              (go.get_ancestor (\"axes\").get_properties ());\n\n  return (ax_prop.get_num_lights () > 0);\n}\n\nvoid\nsurface::properties::update_face_normals (bool reset, bool force)\n{\n  if (! facenormalsmode_is (\"auto\"))\n    return;\n\n  if (force || ((facelighting_is (\"flat\") || edgelighting_is (\"flat\"))\n                && get_do_lighting ()))\n    {\n      Matrix x = get_xdata ().matrix_value ();\n      Matrix y = get_ydata ().matrix_value ();\n      Matrix z = get_zdata ().matrix_value ();\n\n      int p = z.columns ();\n      int q = z.rows ();\n\n      // FIXME: There might be a cleaner way to do this.  When data is changed\n      // the update_xdata, update_ydata, update_zdata routines are called in a\n      // serial fashion.  Until the final call to update_zdata the matrices\n      // will be of mismatched dimensions which can cause an out-of-bound\n      // indexing in the code below.  This one-liner prevents calculating\n      // normals until dimensions match.\n      if (x.columns () != p || y.rows () != q)\n        return;\n\n      bool x_mat = (x.rows () == q);\n      bool y_mat = (y.columns () == p);\n\n      NDArray n (dim_vector (q-1, p-1, 3), 1);\n\n      int i1, i2, j1, j2;\n      i1 = i2 = 0;\n      j1 = j2 = 0;\n      double x0, x1, x2, x3, y0, y1, y2, y3, z0, z1, z2, z3;\n      double x1m0, x2m1, x3m2, x0m3, y1m0, y2m1, y3m2, y0m3;\n      double x1p0, x2p1, x3p2, x0p3, y1p0, y2p1, y3p2, y0p3;\n      x3m2 = y0m3 = -1;\n      x2m1 = x0m3 = y1m0 = y3m2 = 0;\n      x1m0 = y2m1 = 1;\n      x0p3 = y1p0 = 0;\n      x1p0 = x3p2 = y2p1 = y0p3 = 1;\n      x2p1 = y3p2 = 2;\n\n      for (int i = 0; i < p-1; i++)\n        {\n          i1 = i;\n          i2 = i + 1;\n\n          for (int j = 0; j < q-1; j++)\n            {\n              j1 = j;\n              j2 = j + 1;\n\n              if (x_mat || y_mat)\n                {\n                  x0 = x(x_mat?j1:0, y_mat?i1:0);\n                  x1 = x(x_mat?j1:0, y_mat?i2:0);\n                  x2 = x(x_mat?j2:0, y_mat?i2:0);\n                  x3 = x(x_mat?j2:0, y_mat?i1:0);\n                  x1m0 = x1 - x0;\n                  x2m1 = x2 - x1;\n                  x3m2 = x3 - x2;\n                  x0m3 = x0 - x3;\n                  x1p0 = x1 + x0;\n                  x2p1 = x2 + x1;\n                  x3p2 = x3 + x2;\n                  x0p3 = x0 + x3;\n                  y0 = y(x_mat?j1:0, y_mat?i1:0);\n                  y1 = y(x_mat?j1:0, y_mat?i2:0);\n                  y2 = y(x_mat?j2:0, y_mat?i2:0);\n                  y3 = y(x_mat?j2:0, y_mat?i1:0);\n                  y1m0 = y1 - y0;\n                  y2m1 = y2 - y1;\n                  y3m2 = y3 - y2;\n                  y0m3 = y0 - y3;\n                  y1p0 = y1 + y0;\n                  y2p1 = y2 + y1;\n                  y3p2 = y3 + y2;\n                  y0p3 = y0 + y3;\n                }\n\n              double& nx = n(j, i, 0);\n              double& ny = n(j, i, 1);\n              double& nz = n(j, i, 2);\n\n              z0 = z(j1, i1);\n              z1 = z(j1, i2);\n              z2 = z(j2, i2);\n              z3 = z(j2, i1);\n\n              // calculate face normal with Newell's method\n              // https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal#Newell.27s_Method\n\n              nx = y1m0 * (z1 + z0) + y2m1 * (z2 + z1)\n                   + y3m2 * (z3 + z2) + y0m3 * (z0 + z3);\n              ny = (z1 - z0) * x1p0 + (z2 - z1) * x2p1\n                   + (z3 - z2) * x3p2 + (z0 - z3) * x0p3;\n              nz = x1m0 * y1p0 + x2m1 * y2p1 + x3m2 * y3p2 + x0m3 * y0p3;\n\n              double d = std::max (std::max (fabs (nx), fabs (ny)), fabs (nz));\n\n              nx /= d;\n              ny /= d;\n              nz /= d;\n            }\n        }\n      m_facenormals = n;\n    }\n  else if (reset)\n    m_facenormals = Matrix ();\n}\n\nvoid\nsurface::properties::update_vertex_normals (bool reset, bool force)\n{\n  if (! vertexnormalsmode_is (\"auto\"))\n    return;\n\n  if (force || ((facelighting_is (\"gouraud\") || facelighting_is (\"phong\")\n                 || edgelighting_is (\"gouraud\") || edgelighting_is (\"phong\"))\n                && get_do_lighting ()))\n    {\n      Matrix x = get_xdata ().matrix_value ();\n      Matrix y = get_ydata ().matrix_value ();\n      Matrix z = get_zdata ().matrix_value ();\n\n      int p = z.columns ();\n      int q = z.rows ();\n\n      // FIXME: There might be a cleaner way to do this.  When data is changed\n      // the update_xdata, update_ydata, update_zdata routines are called in a\n      // serial fashion.  Until the final call to update_zdata the matrices\n      // will be of mismatched dimensions which can cause an out-of-bound\n      // indexing in the code below.  This one-liner prevents calculating\n      // normals until dimensions match.\n      if (x.columns () != p || y.rows () != q)\n        return;\n\n      NDArray n (dim_vector (q, p, 3), 0.0);\n\n      bool x_mat = (x.rows () == q);\n      bool y_mat = (y.columns () == p);\n\n      int i1, i2, i3, j1, j2, j3;\n      i1 = i2 = i3 = 0;\n      j1 = j2 = j3 = 0;\n\n      for (int i = 0; i < p; i++)\n        {\n          if (y_mat)\n            {\n              i1 = i - 1;\n              i2 = i;\n              i3 = i + 1;\n            }\n\n          for (int j = 0; j < q; j++)\n            {\n              if (x_mat)\n                {\n                  j1 = j - 1;\n                  j2 = j;\n                  j3 = j + 1;\n                }\n\n              double& nx = n(j, i, 0);\n              double& ny = n(j, i, 1);\n              double& nz = n(j, i, 2);\n\n              if ((j > 0) && (i > 0))\n                // upper left quadrangle\n                cross_product\n                (x(j1, i-1)-x(j2, i), y(j-1, i1)-y(j, i2), z(j-1, i-1)-z(j, i),\n                 x(j2, i-1)-x(j1, i), y(j, i1)-y(j-1, i2), z(j, i-1)-z(j-1, i),\n                 nx, ny, nz);\n\n              if ((j > 0) && (i < (p -1)))\n                // upper right quadrangle\n                cross_product\n                (x(j1, i+1)-x(j2, i), y(j-1, i3)-y(j, i2), z(j-1, i+1)-z(j, i),\n                 x(j1, i)-x(j2, i+1), y(j-1, i2)-y(j, i3), z(j-1, i)-z(j, i+1),\n                 nx, ny, nz);\n\n              if ((j < (q - 1)) && (i > 0))\n                // lower left quadrangle\n                cross_product\n                (x(j2, i-1)-x(j3, i), y(j, i1)-y(j+1, i2), z(j, i-1)-z(j+1, i),\n                 x(j3, i-1)-x(j2, i), y(j+1, i1)-y(j, i2), z(j+1, i-1)-z(j, i),\n                 nx, ny, nz);\n\n              if ((j < (q - 1)) && (i < (p -1)))\n                // lower right quadrangle\n                cross_product\n                (x(j3, i)-x(j2, i+1), y(j+1, i2)-y(j, i3), z(j+1, i)-z(j, i+1),\n                 x(j3, i+1)-x(j2, i), y(j+1, i3)-y(j, i2), z(j+1, i+1)-z(j, i),\n                 nx, ny, nz);\n\n              double d = -std::max (std::max (fabs (nx), fabs (ny)), fabs (nz));\n\n              nx /= d;\n              ny /= d;\n              nz /= d;\n            }\n        }\n      m_vertexnormals = n;\n    }\n  else if (reset)\n    m_vertexnormals = Matrix ();\n}\n\nDEFMETHOD (__update_normals__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __update_normals__ (@var{h})\nUpdate FaceNormals and VertexNormals of the patch or surface referred to by\n@var{h}.\n\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value val = args(0);\n\n  graphics_object go = gh_mgr.get_object (val);\n\n  if (go.isa (\"surface\"))\n    {\n      surface::properties& props\n        = dynamic_cast<surface::properties&> (go.get_properties ());\n      props.update_normals (false, true);\n    }\n  else if (go.isa (\"patch\"))\n    {\n      patch::properties& props\n        = dynamic_cast<patch::properties&> (go.get_properties ());\n      props.update_normals (false, true);\n    }\n  else\n    error (\"__update_normals__: \"\n           \"H must be a handle to a valid surface or patch object.\");\n\n  return ovl ();\n}\n\n/*\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   Z = peaks ();\n%!   hs = surf (Z, \"facelighting\", \"none\");\n%!   assert (isempty (get (hs, \"vertexnormals\")));\n%!   assert (isempty (get (hs, \"facenormals\")));\n%!   __update_normals__ (hs);\n%!   assert (! isempty (get (hs, \"vertexnormals\")));\n%!   assert (! isempty (get (hs, \"facenormals\")));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hp = patch (\"facelighting\", \"none\");\n%!   assert (isempty (get (hp, \"vertexnormals\")));\n%!   assert (isempty (get (hp, \"facenormals\")));\n%!   __update_normals__ (hp);\n%!   assert (! isempty (get (hp, \"vertexnormals\")));\n%!   assert (! isempty (get (hp, \"facenormals\")));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\n// ---------------------------------------------------------------------\n\nvoid\nhggroup::properties::remove_child (const graphics_handle& h, bool from_root)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (! from_root && go.isa (\"light\") && go.get_properties ().is_visible ())\n    {\n      axes::properties& ax_props\n        = dynamic_cast<axes::properties&> (go.get_ancestor (\"axes\").get_properties ());\n      ax_props.decrease_num_lights ();\n    }\n  base_properties::remove_child (h, from_root);\n  update_limits ();\n}\n\nvoid\nhggroup::properties::adopt (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (go.isa (\"light\") && go.get_properties ().is_visible ())\n    {\n      axes::properties& ax_props\n        = dynamic_cast<axes::properties&> (go.get_ancestor (\"axes\").get_properties ());\n      ax_props.increase_num_lights ();\n    }\n  base_properties::adopt (h);\n  update_limits (h);\n}\n\nvoid\nhggroup::properties::update_limits () const\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (m___myhandle__);\n\n  if (go)\n    {\n      go.update_axis_limits (\"xlim\");\n      go.update_axis_limits (\"ylim\");\n      go.update_axis_limits (\"zlim\");\n      go.update_axis_limits (\"clim\");\n      go.update_axis_limits (\"alim\");\n    }\n}\n\nvoid\nhggroup::properties::update_limits (const graphics_handle& h) const\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (m___myhandle__);\n\n  if (go)\n    {\n      go.update_axis_limits (\"xlim\", h);\n      go.update_axis_limits (\"ylim\", h);\n      go.update_axis_limits (\"zlim\", h);\n      go.update_axis_limits (\"clim\", h);\n      go.update_axis_limits (\"alim\", h);\n    }\n}\n\nstatic bool updating_hggroup_limits = false;\n\nvoid\nhggroup::update_axis_limits (const std::string& axis_type,\n                             const graphics_handle& h)\n{\n  if (updating_hggroup_limits)\n    return;\n\n  Matrix kids = Matrix (1, 1, h.value ());\n\n  double min_val = octave::numeric_limits<double>::Inf ();\n  double max_val = -octave::numeric_limits<double>::Inf ();\n  double min_pos = octave::numeric_limits<double>::Inf ();\n  double max_neg = -octave::numeric_limits<double>::Inf ();\n\n  Matrix limits;\n  double val;\n\n  char update_type = 0;\n\n  if (axis_type == \"xlim\" || axis_type == \"xliminclude\")\n    {\n      limits = m_properties.get_xlim ().matrix_value ();\n      update_type = 'x';\n    }\n  else if (axis_type == \"ylim\" || axis_type == \"yliminclude\")\n    {\n      limits = m_properties.get_ylim ().matrix_value ();\n      update_type = 'y';\n    }\n  else if (axis_type == \"zlim\" || axis_type == \"zliminclude\")\n    {\n      limits = m_properties.get_zlim ().matrix_value ();\n      update_type = 'z';\n    }\n  else if (axis_type == \"clim\" || axis_type == \"climinclude\")\n    {\n      limits = m_properties.get_clim ().matrix_value ();\n      update_type = 'c';\n    }\n  else if (axis_type == \"alim\" || axis_type == \"aliminclude\")\n    {\n      limits = m_properties.get_alim ().matrix_value ();\n      update_type = 'a';\n    }\n\n  if (limits.numel () == 4)\n    {\n      val = limits(0);\n      if (octave::math::isfinite (val))\n        min_val = val;\n      val = limits(1);\n      if (octave::math::isfinite (val))\n        max_val = val;\n      val = limits(2);\n      if (octave::math::isfinite (val))\n        min_pos = val;\n      val = limits(3);\n      if (octave::math::isfinite (val))\n        max_neg = val;\n    }\n  else\n    {\n      limits.resize (1, 4);\n      limits(0) = min_val;\n      limits(1) = max_val;\n      limits(2) = min_pos;\n      limits(3) = max_neg;\n    }\n\n  get_children_limits (min_val, max_val, min_pos, max_neg, kids, update_type);\n\n  octave::unwind_protect_var<bool> restore_var (updating_hggroup_limits, true);\n\n  if (limits(0) != min_val || limits(1) != max_val\n      || limits(2) != min_pos || limits(3) != max_neg)\n    {\n      limits(0) = min_val;\n      limits(1) = max_val;\n      limits(2) = min_pos;\n      limits(3) = max_neg;\n\n      switch (update_type)\n        {\n        case 'x':\n          m_properties.set_xlim (limits);\n          break;\n\n        case 'y':\n          m_properties.set_ylim (limits);\n          break;\n\n        case 'z':\n          m_properties.set_zlim (limits);\n          break;\n\n        case 'c':\n          m_properties.set_clim (limits);\n          break;\n\n        case 'a':\n          m_properties.set_alim (limits);\n          break;\n\n        default:\n          break;\n        }\n\n      graphics_handle hg = m_properties.get___myhandle__ ();\n      base_graphics_object::update_axis_limits (axis_type, hg);\n    }\n}\n\nvoid\nhggroup::update_axis_limits (const std::string& axis_type)\n{\n  if (updating_hggroup_limits)\n    return;\n\n  Matrix kids = m_properties.get_children ();\n\n  double min_val = octave::numeric_limits<double>::Inf ();\n  double max_val = -octave::numeric_limits<double>::Inf ();\n  double min_pos = octave::numeric_limits<double>::Inf ();\n  double max_neg = -octave::numeric_limits<double>::Inf ();\n\n  char update_type = 0;\n\n  if (axis_type == \"xlim\" || axis_type == \"xliminclude\")\n    {\n      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'x');\n\n      update_type = 'x';\n    }\n  else if (axis_type == \"ylim\" || axis_type == \"yliminclude\")\n    {\n      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'y');\n\n      update_type = 'y';\n    }\n  else if (axis_type == \"zlim\" || axis_type == \"zliminclude\")\n    {\n      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');\n\n      update_type = 'z';\n    }\n  else if (axis_type == \"clim\" || axis_type == \"climinclude\")\n    {\n      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'c');\n\n      update_type = 'c';\n    }\n  else if (axis_type == \"alim\" || axis_type == \"aliminclude\")\n    {\n      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'a');\n\n      update_type = 'a';\n    }\n\n  octave::unwind_protect_var<bool> restore_var (updating_hggroup_limits, true);\n\n  Matrix limits (1, 4);\n\n  limits(0) = min_val;\n  limits(1) = max_val;\n  limits(2) = min_pos;\n  limits(3) = max_neg;\n\n  switch (update_type)\n    {\n    case 'x':\n      m_properties.set_xlim (limits);\n      break;\n\n    case 'y':\n      m_properties.set_ylim (limits);\n      break;\n\n    case 'z':\n      m_properties.set_zlim (limits);\n      break;\n\n    case 'c':\n      m_properties.set_clim (limits);\n      break;\n\n    case 'a':\n      m_properties.set_alim (limits);\n      break;\n\n    default:\n      break;\n    }\n\n  base_graphics_object::update_axis_limits (axis_type);\n}\n\n// ---------------------------------------------------------------------\n\nvoid\nuicontextmenu::properties::update_beingdeleted ()\n{\n  // Clear the uicontextmenu property of dependent objects\n  if (m_beingdeleted.is (\"on\"))\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      std::list<graphics_handle> lst = get_dependent_obj_list ();\n\n      for (auto& hobj : lst)\n        {\n          graphics_object go = gh_mgr.get_object (hobj);\n\n          if (go.valid_object ()\n              && go.get (\"contextmenu\") == get___myhandle__ ())\n            go.set (\"contextmenu\", Matrix ());\n        }\n    }\n}\n\n/*\n## Test deletion/reset of uicontextmenu\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = axes (\"parent\", hf);\n%! unwind_protect\n%!   hctx1 = uicontextmenu (\"parent\", hf);\n%!   hctx2 = uicontextmenu (\"parent\", hf);\n%!   set (hf, \"uicontextmenu\", hctx2);\n%!   set (hax, \"uicontextmenu\", hctx2);\n%!   assert (get (hf, \"uicontextmenu\"), hctx2);\n%!   assert (get (hax, \"uicontextmenu\"), hctx2);\n%!   assert (get (hf, \"children\"), [hctx2; hctx1; hax]);\n%!   delete (hctx2);\n%!   assert (get (hf, \"uicontextmenu\"), []);\n%!   assert (get (hax, \"uicontextmenu\"), []);\n%!   assert (get (hf, \"children\"), [hctx1; hax]);\n%!   set (hf, \"uicontextmenu\", hctx1);\n%!   assert (get (hf, \"uicontextmenu\"), hctx1);\n%!   set (hf, \"uicontextmenu\", []);\n%!   assert (get (hf, \"uicontextmenu\"), []);\n%!   assert (get (hf, \"children\"), [hctx1; hax]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n*/\n\n// ---------------------------------------------------------------------\n\noctave_value\nuicontrol::properties::get_extent () const\n{\n  Matrix m = m_extent.get ().matrix_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);\n  Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);\n\n  return convert_position (m, \"pixels\", get_units (), parent_size);\n}\n\nvoid\nuicontrol::properties::update_text_extent ()\n{\n  // FIXME: support multiline text\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (get___myhandle__ ());\n\n  set_extent (go.get_toolkit ().get_text_extent (go));\n}\n\nvoid\nuicontrol::properties::update_units ()\n{\n  Matrix pos = get_position ().matrix_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);\n  Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);\n\n  pos = convert_position (pos, m_cached_units, get_units (), parent_size);\n  set_position (pos);\n\n  m_cached_units = get_units ();\n}\n\nvoid\nuicontrol::properties::set_style (const octave_value& st)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go_parent = gh_mgr.get_object (get_parent ());\n  if (go_parent.valid_object () && go_parent.isa (\"uibuttongroup\"))\n    {\n      bool was_button = style_is (\"radiobutton\") || style_is (\"togglebutton\");\n      m_style = st;\n      bool now_button = style_is (\"radiobutton\") || style_is (\"togglebutton\");\n      uibuttongroup::properties& props =\n        dynamic_cast<uibuttongroup::properties&> (go_parent.get_properties ());\n      // update selectedobject\n      if (! was_button && now_button && ! props.get_selectedobject ().ok ())\n        {\n          props.set_selectedobject (get___myhandle__ ().value ());\n          m_value.set (octave_value (1));\n        }\n      else if (was_button && ! now_button\n               && (props.get_selectedobject ().value ()\n                   == get___myhandle__ ().value ()))\n        props.set_selectedobject (Matrix ());\n    }\n\n  // Don't notify the style change until the \"value\" property is fixed\n  bool modified = m_style.set (st, true, false);\n\n  // Override \"value\" property for listbox and popupmenu.\n  if (modified)\n    {\n      if (style_is (\"listbox\") || style_is (\"popupmenu\"))\n        {\n          Matrix v = m_value.get ().matrix_value ();\n          if (v.numel () == 1 && v(0) == 0)\n            m_value.set (octave_value (1), true, false);\n        }\n\n      // Notify toolkit\n\n      graphics_object go = gh_mgr.get_object (get___myhandle__ ());\n\n      if (go)\n        go.update (m_style.get_id ());\n    }\n}\n\nMatrix\nuicontrol::properties::get_boundingbox (bool,\n                                        const Matrix& parent_pix_size) const\n{\n  Matrix pos = get_position ().matrix_value ();\n  Matrix parent_size (parent_pix_size);\n\n  if (parent_size.isempty ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go = gh_mgr.get_object (get_parent ());\n\n      if (go.valid_object ())\n        parent_size = go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);\n      else\n        parent_size = default_figure_position ();\n    }\n\n  pos = convert_position (pos, get_units (), \"pixels\", parent_size);\n\n  pos(0)--;\n  pos(1)--;\n  pos(1) = parent_size(1) - pos(1) - pos(3);\n\n  return pos;\n}\n\nvoid\nuicontrol::properties::set_fontunits (const octave_value& val)\n{\n  caseless_str old_fontunits = get_fontunits ();\n\n  if (m_fontunits.set (val, true))\n    {\n      update_fontunits (old_fontunits);\n      mark_modified ();\n    }\n}\n\nvoid\nuicontrol::properties::update_fontunits (const caseless_str& old_units)\n{\n  caseless_str new_units = get_fontunits ();\n  double parent_height = get_boundingbox (false).elem (3);\n  double fontsz = get_fontsize ();\n\n  fontsz = convert_font_size (fontsz, old_units, new_units, parent_height);\n\n  m_fontsize.set (octave_value (fontsz), true);\n}\n\ndouble\nuicontrol::properties::get___fontsize_points__ (double box_pix_height) const\n{\n  double fontsz = get_fontsize ();\n  double parent_height = box_pix_height;\n\n  if (fontunits_is (\"normalized\") && parent_height <= 0)\n    parent_height = get_boundingbox (false).elem (3);\n\n  return convert_font_size (fontsz, get_fontunits (), \"points\", parent_height);\n}\n\n// ---------------------------------------------------------------------\n\nMatrix\nuibuttongroup::properties::get_boundingbox (bool internal,\n    const Matrix& parent_pix_size) const\n{\n  Matrix pos = get_position ().matrix_value ();\n  Matrix parent_size (parent_pix_size);\n\n  if (parent_size.isempty ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go = gh_mgr.get_object (get_parent ());\n\n      parent_size = go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);\n    }\n\n  pos = convert_position (pos, get_units (), \"pixels\", parent_size);\n\n  pos(0)--;\n  pos(1)--;\n  pos(1) = parent_size(1) - pos(1) - pos(3);\n\n  if (internal)\n    {\n      double outer_height = pos(3);\n\n      pos(0) = pos(1) = 0;\n\n      if (! bordertype_is (\"none\"))\n        {\n          double bw = get_borderwidth ();\n          double mul = 1.0;\n\n          if (bordertype_is (\"etchedin\") || bordertype_is (\"etchedout\"))\n            mul = 2.0;\n\n          pos(0) += mul * bw;\n          pos(1) += mul * bw;\n          pos(2) -= 2 * mul * bw;\n          pos(3) -= 2 * mul * bw;\n        }\n\n      if (! get_title ().empty ())\n        {\n          double fontsz = get_fontsize ();\n\n          if (! fontunits_is (\"pixels\"))\n            {\n              double res = xget (0, \"screenpixelsperinch\").double_value ();\n\n              if (fontunits_is (\"points\"))\n                fontsz *= (res / 72.0);\n              else if (fontunits_is (\"inches\"))\n                fontsz *= res;\n              else if (fontunits_is (\"centimeters\"))\n                fontsz *= (res / 2.54);\n              else if (fontunits_is (\"normalized\"))\n                fontsz *= outer_height;\n            }\n\n          if (titleposition_is (\"lefttop\") || titleposition_is (\"centertop\")\n              || titleposition_is (\"righttop\"))\n            pos(1) += (fontsz / 2);\n          pos(3) -= (fontsz / 2);\n        }\n    }\n\n  return pos;\n}\n\nvoid\nuibuttongroup::properties::set_position (const octave_value& v)\n{\n  Matrix old_bb, new_bb;\n  bool modified = false;\n\n  old_bb = get_boundingbox (true);\n  modified = m_position.set (v, false);\n  new_bb = get_boundingbox (true);\n\n  if (old_bb != new_bb)\n    {\n      if (old_bb(2) != new_bb(2) || old_bb(3) != new_bb(3))\n        {\n          gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n          if (! get_resizefcn ().isempty ())\n            gh_mgr.post_callback (m___myhandle__, \"resizefcn\");\n\n          if (! get_sizechangedfcn ().isempty ())\n            gh_mgr.post_callback (m___myhandle__, \"sizechangedfcn\");\n\n          update_boundingbox ();\n        }\n    }\n\n  if (modified)\n    {\n      m_position.run_listeners (GCB_POSTSET);\n      mark_modified ();\n    }\n}\n\nvoid\nuibuttongroup::properties::set_units (const octave_value& val)\n{\n  caseless_str old_units = get_units ();\n\n  if (m_units.set (val, true))\n    {\n      update_units (old_units);\n      mark_modified ();\n    }\n}\n\nvoid\nuibuttongroup::properties::update_units (const caseless_str& old_units)\n{\n  Matrix pos = get_position ().matrix_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);\n  Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);\n\n  pos = convert_position (pos, old_units, get_units (), parent_size);\n  set_position (pos);\n}\n\nvoid\nuibuttongroup::properties::set_fontunits (const octave_value& val)\n{\n  caseless_str old_fontunits = get_fontunits ();\n\n  if (m_fontunits.set (val, true))\n    {\n      update_fontunits (old_fontunits);\n      mark_modified ();\n    }\n}\n\nvoid\nuibuttongroup::properties::update_fontunits (const caseless_str& old_units)\n{\n  caseless_str new_units = get_fontunits ();\n  double parent_height = get_boundingbox (false).elem (3);\n  double fontsz = get_fontsize ();\n\n  fontsz = convert_font_size (fontsz, old_units, new_units, parent_height);\n\n  set_fontsize (octave_value (fontsz));\n}\n\ndouble\nuibuttongroup::properties::get___fontsize_points__ (double box_pix_height) const\n{\n  double fontsz = get_fontsize ();\n  double parent_height = box_pix_height;\n\n  if (fontunits_is (\"normalized\") && parent_height <= 0)\n    parent_height = get_boundingbox (false).elem (3);\n\n  return convert_font_size (fontsz, get_fontunits (), \"points\", parent_height);\n}\n\nvoid\nuibuttongroup::properties::set_selectedobject (const octave_value& v)\n{\n  graphics_handle current_selectedobject = get_selectedobject();\n  m_selectedobject = current_selectedobject;\n  if (v.isempty ())\n    {\n      if (current_selectedobject.ok ())\n        {\n          m_selectedobject = graphics_handle ();\n          mark_modified ();\n        }\n      return;\n    }\n\n  graphics_handle val (v);\n  if (val.ok ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go (gh_mgr.get_object (val));\n\n      base_properties& gop = go.get_properties ();\n\n      if (go.valid_object ()\n          && gop.get_parent () == get___myhandle__ ()\n          && go.isa (\"uicontrol\"))\n        {\n          uicontrol::properties& cop\n            = dynamic_cast<uicontrol::properties&> (go.get_properties ());\n          const caseless_str& style = cop.get_style ();\n          if (style.compare (\"radiobutton\") || style.compare (\"togglebutton\"))\n            {\n              m_selectedobject = val;\n              mark_modified ();\n              return;\n            }\n        }\n    }\n  err_set_invalid (\"selectedobject\");\n}\n\nvoid\nuibuttongroup::properties::remove_child (const graphics_handle& h,\n    bool from_root)\n{\n  graphics_handle current_selected = get_selectedobject ();\n  if (h.value () == current_selected.value ())\n    set_selectedobject (Matrix ());\n\n  base_properties::remove_child (h, from_root);\n}\n\nvoid\nuibuttongroup::properties::adopt (const graphics_handle& h)\n{\n  base_properties::adopt (h);\n\n  graphics_handle current_selected = get_selectedobject ();\n  bool has_selected = current_selected.ok ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (! has_selected && go.valid_object () && go.isa (\"uicontrol\"))\n    {\n      const uicontrol::properties& props =\n        dynamic_cast<const uicontrol::properties&> (go.get_properties ());\n      if (props.style_is (\"radiobutton\") || props.style_is (\"togglebutton\"))\n        set_selectedobject (h.value ());\n    }\n}\n\n// ---------------------------------------------------------------------\n\nMatrix\nuipanel::properties::get_boundingbox (bool internal,\n                                      const Matrix& parent_pix_size) const\n{\n  Matrix pos = get_position ().matrix_value ();\n  Matrix parent_size (parent_pix_size);\n\n  if (parent_size.isempty ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go = gh_mgr.get_object (get_parent ());\n\n      parent_size = go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);\n    }\n\n  pos = convert_position (pos, get_units (), \"pixels\", parent_size);\n\n  pos(0)--;\n  pos(1)--;\n  pos(1) = parent_size(1) - pos(1) - pos(3);\n\n  if (internal)\n    {\n      double outer_height = pos(3);\n\n      pos(0) = pos(1) = 0;\n\n      if (! bordertype_is (\"none\"))\n        {\n          double bw = get_borderwidth ();\n          double mul = 1.0;\n\n          if (bordertype_is (\"etchedin\") || bordertype_is (\"etchedout\"))\n            mul = 2.0;\n\n          pos(0) += mul * bw;\n          pos(1) += mul * bw;\n          pos(2) -= 2 * mul * bw;\n          pos(3) -= 2 * mul * bw;\n        }\n\n      if (! get_title ().empty ())\n        {\n          double fontsz = get_fontsize ();\n\n          if (! fontunits_is (\"pixels\"))\n            {\n              double res = xget (0, \"screenpixelsperinch\").double_value ();\n\n              if (fontunits_is (\"points\"))\n                fontsz *= (res / 72.0);\n              else if (fontunits_is (\"inches\"))\n                fontsz *= res;\n              else if (fontunits_is (\"centimeters\"))\n                fontsz *= (res / 2.54);\n              else if (fontunits_is (\"normalized\"))\n                fontsz *= outer_height;\n            }\n\n          if (titleposition_is (\"lefttop\") || titleposition_is (\"centertop\")\n              || titleposition_is (\"righttop\"))\n            pos(1) += (fontsz / 2);\n          pos(3) -= (fontsz / 2);\n        }\n    }\n\n  return pos;\n}\n\nvoid\nuipanel::properties::set_position (const octave_value& v)\n{\n  Matrix old_bb, new_bb;\n  bool modified = false;\n\n  old_bb = get_boundingbox (true);\n  modified = m_position.set (v, false);\n  new_bb = get_boundingbox (true);\n\n  if (old_bb != new_bb)\n    {\n      if (old_bb(2) != new_bb(2) || old_bb(3) != new_bb(3))\n        {\n          gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n          if (! get_resizefcn ().isempty ())\n            gh_mgr.post_callback (m___myhandle__, \"resizefcn\");\n\n          if (! get_sizechangedfcn ().isempty ())\n            gh_mgr.post_callback (m___myhandle__, \"sizechangedfcn\");\n\n          update_boundingbox ();\n        }\n    }\n\n  if (modified)\n    {\n      m_position.run_listeners (GCB_POSTSET);\n      mark_modified ();\n    }\n}\n\n\nvoid\nuipanel::properties::set_units (const octave_value& val)\n{\n  caseless_str old_units = get_units ();\n\n  if (m_units.set (val, true))\n    {\n      update_units (old_units);\n      mark_modified ();\n    }\n}\n\nvoid\nuipanel::properties::update_units (const caseless_str& old_units)\n{\n  Matrix pos = get_position ().matrix_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);\n  Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);\n\n  pos = convert_position (pos, old_units, get_units (), parent_size);\n  set_position (pos);\n}\n\nvoid\nuipanel::properties::set_fontunits (const octave_value& val)\n{\n  caseless_str old_fontunits = get_fontunits ();\n\n  if (m_fontunits.set (val, true))\n    {\n      update_fontunits (old_fontunits);\n      mark_modified ();\n    }\n}\n\nvoid\nuipanel::properties::update_fontunits (const caseless_str& old_units)\n{\n  caseless_str new_units = get_fontunits ();\n  double parent_height = get_boundingbox (false).elem (3);\n  double fontsz = get_fontsize ();\n\n  fontsz = convert_font_size (fontsz, old_units, new_units, parent_height);\n\n  set_fontsize (octave_value (fontsz));\n}\n\ndouble\nuipanel::properties::get___fontsize_points__ (double box_pix_height) const\n{\n  double fontsz = get_fontsize ();\n  double parent_height = box_pix_height;\n\n  if (fontunits_is (\"normalized\") && parent_height <= 0)\n    parent_height = get_boundingbox (false).elem (3);\n\n  return convert_font_size (fontsz, get_fontunits (), \"points\", parent_height);\n}\n\n// ---------------------------------------------------------------------\n\nMatrix\nuitable::properties::get_boundingbox (bool,\n                                      const Matrix& parent_pix_size) const\n{\n  Matrix pos = get_position ().matrix_value ();\n  Matrix parent_size (parent_pix_size);\n\n  if (parent_size.isempty ())\n    {\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object go = gh_mgr.get_object (get_parent ());\n\n      parent_size = go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);\n    }\n\n  pos = convert_position (pos, get_units (), \"pixels\", parent_size);\n\n  pos(0)--;\n  pos(1)--;\n  pos(1) = parent_size(1) - pos(1) - pos(3);\n\n  return pos;\n}\n\nvoid\nuitable::properties::set_columnformat (const octave_value& val)\n{\n  /* Matlab only allows certain values for ColumnFormat.  Here we only check the\n   * structure of the argument.  Values will be checked in Table.cc */\n\n  if (val.iscellstr ())\n    {\n      if (m_columnformat.set (val, true))\n        mark_modified ();\n    }\n  else if (val.iscell ())\n    {\n      Cell cell_value = val.cell_value ();\n\n      for (int i = 0; i < cell_value.numel (); i++)\n        {\n          octave_value v = cell_value(i);\n          if (v.iscell ())\n            {\n              /* We are in a pop-up menu selection.\n               * Matlab only allows non-empty strings here. */\n              Cell popup = v.cell_value ();\n              for (int j = 0; j < popup.numel (); j++)\n                {\n                  octave_value p = popup(j);\n                  if (! p.is_string () || p.isempty ())\n                    error (\"set: pop-up menu definitions must be non-empty strings\");\n                }\n            }\n          else if (! (v.is_string () || v.isempty ()))\n            {\n              error (\"set: columnformat definintions must be a cellstr of \"\n                     \"either 'char', 'short [e|g|eng]?', 'long [e|g|eng]?', \"\n                     \"'numeric', 'bank', '+', 'rat', 'logical', \"\n                     \"or a cellstr of non-empty pop-up menu definitions.\");\n            }\n        }\n\n      if (m_columnformat.set (val, true))\n        mark_modified ();\n    }\n  else if (val.isempty ())\n    {\n      if (m_columnformat.set (Cell (), true))\n        mark_modified ();\n    }\n  else\n    {\n      error (\"set: expecting cell of strings\");\n    }\n}\n\nvoid\nuitable::properties::set_columnwidth (const octave_value& val)\n{\n  bool isvalid = true;\n\n  if (val.is_string ())\n    {\n      std::string option = val.string_value (false);\n      if (option != \"auto\" && option != \"fit\")\n        isvalid = false;\n    }\n  else if (val.iscell ())\n    {\n      Cell cell_value = val.cell_value ();\n      for (int i = 0; i < cell_value.numel (); i++)\n        {\n          octave_value v = cell_value(i);\n          if (v.is_string ())\n            {\n              std::string option = v.string_value (false);\n              if (option != \"auto\" && option != \"fit\")\n                isvalid = false;\n            }\n          else if (! (v.isreal () && v.is_scalar_type ()))\n            {\n              isvalid = false;\n            }\n        }\n    }\n  else\n    isvalid = false;\n\n  if (! isvalid)\n    error (\"set: expecting either 'auto', 'fit', or a cell array of pixel values, 'auto', or 'fit'\");\n\n  if (m_columnwidth.set (val, true))\n    mark_modified ();\n}\n\nvoid\nuitable::properties::set_data (const octave_value& val)\n{\n  if (! (val.iscell () || val.is_matrix_type () || val.is_scalar_type ()\n         || val.is_range ()))\n    error (\"set: 'Data' must be an array or cell array\");\n\n  if (m_data.set (val, true))\n    mark_modified ();\n}\n\nvoid\nuitable::properties::set_units (const octave_value& val)\n{\n  caseless_str old_units = get_units ();\n\n  if (m_units.set (val, true))\n    {\n      update_units (old_units);\n      mark_modified ();\n    }\n}\n\nvoid\nuitable::properties::update_units (const caseless_str& old_units)\n{\n  Matrix pos = get_position ().matrix_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);\n  Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);\n\n  pos = convert_position (pos, old_units, get_units (), parent_size);\n  set_position (pos);\n}\n\nvoid\nuitable::properties::set_fontunits (const octave_value& val)\n{\n  caseless_str old_fontunits = get_fontunits ();\n\n  if (m_fontunits.set (val, true))\n    {\n      update_fontunits (old_fontunits);\n      mark_modified ();\n    }\n}\n\nvoid\nuitable::properties::update_fontunits (const caseless_str& old_units)\n{\n  caseless_str new_units = get_fontunits ();\n  double parent_height = get_boundingbox (false).elem (3);\n  double fontsz = get_fontsize ();\n\n  fontsz = convert_font_size (fontsz, old_units, new_units, parent_height);\n\n  set_fontsize (octave_value (fontsz));\n}\n\ndouble\nuitable::properties::get___fontsize_points__ (double box_pix_height) const\n{\n  double fontsz = get_fontsize ();\n  double parent_height = box_pix_height;\n\n  if (fontunits_is (\"normalized\") && parent_height <= 0)\n    parent_height = get_boundingbox (false).elem (3);\n\n  return convert_font_size (fontsz, get_fontunits (), \"points\", parent_height);\n}\n\ndouble\nuitable::properties::get_fontsize_pixels (double box_pix_height) const\n{\n  double fontsz = get_fontsize ();\n  double parent_height = box_pix_height;\n\n  if (fontunits_is (\"normalized\") && parent_height <= 0)\n    parent_height = get_boundingbox (false).elem (3);\n\n  return convert_font_size (fontsz, get_fontunits (), \"pixels\", parent_height);\n}\n\nMatrix\nuitable::properties::get_backgroundcolor_rgb ()\n{\n  Matrix bg = m_backgroundcolor.get ().matrix_value ();\n  return bg.row (0);\n}\n\nMatrix\nuitable::properties::get_alternatebackgroundcolor_rgb ()\n{\n  int i = 0;\n  Matrix bg = m_backgroundcolor.get ().matrix_value ();\n  if (bg.rows () > 1)\n    i = 1;\n\n  return bg.row (i);\n}\n\nMatrix\nuitable::properties::get_extent_matrix () const\n{\n  return m_extent.get ().matrix_value ();\n}\n\noctave_value\nuitable::properties::get_extent () const\n{\n  // FIXME: Is it really acceptable to just let the toolkit update the extent?\n  Matrix m = m_extent.get ().matrix_value ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (get_parent ());\n\n  if (parent_go)\n    {\n      Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);\n      Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);\n\n      return convert_position (m, \"pixels\", get_units (), parent_size);\n    }\n\n  return m;\n}\n\n// ---------------------------------------------------------------------\n\noctave_value\nuitoolbar::get_default (const caseless_str& pname) const\n{\n  octave_value retval = m_default_properties.lookup (pname);\n\n  if (retval.is_undefined ())\n    {\n      graphics_handle parent_h = get_parent ();\n\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      graphics_object parent_go = gh_mgr.get_object (parent_h);\n\n      retval = parent_go.get_default (pname);\n    }\n\n  return retval;\n}\n\nvoid\nuitoolbar::reset_default_properties ()\n{\n  // empty list of local defaults\n  m_default_properties = property_list ();\n\n  remove_all_listeners ();\n  xreset_default_properties (get_handle (), m_properties.factory_defaults ());\n}\n\n// ---------------------------------------------------------------------\n\noctave_value\nbase_graphics_object::get_default (const caseless_str& pname) const\n{\n  graphics_handle parent_h = get_parent ();\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (parent_h);\n\n  return parent_go.get_default (type () + pname);\n}\n\noctave_value\nbase_graphics_object::get_factory_default (const caseless_str& name) const\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object parent_go = gh_mgr.get_object (0);\n\n  return parent_go.get_factory_default (type () + name);\n}\n\nclass callback_event : public base_graphics_event\n{\npublic:\n  callback_event (const graphics_handle& h, const std::string& name,\n                  const octave_value& data = Matrix (),\n                  int busyaction = base_graphics_event::QUEUE)\n    : base_graphics_event (busyaction), m_handle (h), m_callback_name (name),\n      m_callback (), m_callback_data (data) { }\n\n  callback_event (const graphics_handle& h, const octave_value& cb,\n                  const octave_value& data = Matrix (),\n                  int busyaction = base_graphics_event::QUEUE)\n    : base_graphics_event (busyaction), m_handle (h), m_callback_name (),\n      m_callback (cb), m_callback_data (data) { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (callback_event)\n\n  ~callback_event () = default;\n\n  void execute ()\n  {\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    if (m_callback.is_defined ())\n      gh_mgr.execute_callback (m_handle, m_callback, m_callback_data);\n    else\n      gh_mgr.execute_callback (m_handle, m_callback_name, m_callback_data);\n  }\n\nprivate:\n  graphics_handle m_handle;\n  std::string m_callback_name;\n  octave_value m_callback;\n  octave_value m_callback_data;\n};\n\nclass mcode_event : public base_graphics_event\n{\npublic:\n  mcode_event (const graphics_handle& h, const std::string& cmd,\n               int busyaction = base_graphics_event::QUEUE)\n    : base_graphics_event (busyaction), m_handle (h), m_mcode (cmd)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (mcode_event)\n\n  ~mcode_event () = default;\n\n  void execute ()\n  {\n    if (! m_mcode.empty ())\n      {\n        gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n        graphics_object go = gh_mgr.get_object (m_handle);\n\n        if (go.valid_object ())\n          {\n            octave_value cb (m_mcode);\n            gh_mgr.execute_callback (m_handle, cb);\n          }\n      }\n  }\n\nprivate:\n  graphics_handle m_handle;\n  std::string m_mcode;\n};\n\nclass function_event : public base_graphics_event\n{\npublic:\n\n  function_event (graphics_event::event_fcn fcn, void *data = nullptr)\n    : base_graphics_event (), m_function (fcn), m_function_data (data)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (function_event)\n\n  ~function_event () = default;\n\n  void execute ()\n  {\n    m_function (m_function_data);\n  }\n\nprivate:\n\n  graphics_event::event_fcn m_function;\n\n  void *m_function_data;\n};\n\nclass set_event : public base_graphics_event\n{\npublic:\n  set_event (const graphics_handle& h, const std::string& name,\n             const octave_value& value, bool do_notify_toolkit = true,\n             bool redraw_figure = false)\n    : base_graphics_event (), m_handle (h), m_property_name (name),\n      m_property_value (value), m_notify_toolkit (do_notify_toolkit),\n      m_redraw_figure (redraw_figure)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (set_event)\n\n  ~set_event () = default;\n\n  void execute ()\n  {\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    octave::autolock guard (gh_mgr.graphics_lock ());\n\n    graphics_object go = gh_mgr.get_object (m_handle);\n\n    if (go)\n      {\n        property p = go.get_properties ().get_property (m_property_name);\n\n        if (p.ok ())\n          {\n            // FIXME: figure position and outerposition properties set_xxx have\n            // a signature that allows passing the notify_toolkit argument.\n            // Should we change all set_xxx signatures and allow\n            // base_properties::set to accept this also? This would allow for\n            // the use of high level set_xxx instead of directly changing the\n            // property value.\n            if (go.isa (\"figure\") && m_property_name == \"position\")\n              {\n                figure::properties& fprops\n                  = dynamic_cast<figure::properties&> (go.get_properties ());\n                fprops.set_position (m_property_value, m_notify_toolkit);\n              }\n            else if (go.isa (\"figure\") && m_property_name == \"outerposition\")\n              {\n                figure::properties& fprops\n                  = dynamic_cast<figure::properties&> (go.get_properties ());\n                fprops.set_outerposition (m_property_value, m_notify_toolkit);\n              }\n            else\n              p.set (m_property_value, true, m_notify_toolkit);\n\n            if (m_redraw_figure)\n              {\n                if (! go.isa (\"figure\"))\n                  go = go.get_ancestor (\"figure\");\n\n                if (go.valid_object ())\n                  {\n                    figure::properties& fprops\n                      = dynamic_cast<figure::properties&> (go.get_properties ());\n                    fprops.get_toolkit ().redraw_figure (go);\n                  }\n              }\n          }\n      }\n  }\n\nprivate:\n  graphics_handle m_handle;\n  std::string m_property_name;\n  octave_value m_property_value;\n  bool m_notify_toolkit;\n  bool m_redraw_figure;\n};\n\ngraphics_event\ngraphics_event::create_callback_event (const graphics_handle& h,\n                                       const std::string& name,\n                                       const octave_value& data,\n                                       int busyaction)\n{\n  return graphics_event (new callback_event (h, name, data, busyaction));\n}\n\ngraphics_event\ngraphics_event::create_callback_event (const graphics_handle& h,\n                                       const octave_value& cb,\n                                       const octave_value& data,\n                                       int busyaction)\n{\n  return graphics_event (new callback_event (h, cb, data, busyaction));\n}\n\ngraphics_event\ngraphics_event::create_mcode_event (const graphics_handle& h,\n                                    const std::string& cmd,\n                                    int busyaction)\n{\n  return graphics_event (new mcode_event (h, cmd, busyaction));\n}\n\ngraphics_event\ngraphics_event::create_function_event (graphics_event::event_fcn fcn,\n                                       void *data)\n{\n  return graphics_event (new function_event (fcn, data));\n}\n\ngraphics_event\ngraphics_event::create_set_event (const graphics_handle& h,\n                                  const std::string& name,\n                                  const octave_value& data,\n                                  bool notify_toolkit, bool redraw_figure)\n{\n  return graphics_event (new set_event (h, name, data, notify_toolkit,\n                                        redraw_figure));\n}\n\nproperty_list::plist_map_type\nroot_figure::init_factory_properties ()\n{\n  property_list::plist_map_type plist_map;\n\n  plist_map[\"figure\"] = figure::properties::factory_defaults ();\n  plist_map[\"axes\"] = axes::properties::factory_defaults ();\n  plist_map[\"line\"] = line::properties::factory_defaults ();\n  plist_map[\"text\"] = text::properties::factory_defaults ();\n  plist_map[\"image\"] = image::properties::factory_defaults ();\n  plist_map[\"patch\"] = patch::properties::factory_defaults ();\n  plist_map[\"scatter\"] = scatter::properties::factory_defaults ();\n  plist_map[\"surface\"] = surface::properties::factory_defaults ();\n  plist_map[\"light\"] = light::properties::factory_defaults ();\n  plist_map[\"hggroup\"] = hggroup::properties::factory_defaults ();\n  plist_map[\"uimenu\"] = uimenu::properties::factory_defaults ();\n  plist_map[\"uicontrol\"] = uicontrol::properties::factory_defaults ();\n  plist_map[\"uibuttongroup\"] = uibuttongroup::properties::factory_defaults ();\n  plist_map[\"uipanel\"] = uipanel::properties::factory_defaults ();\n  plist_map[\"uicontextmenu\"] = uicontextmenu::properties::factory_defaults ();\n  plist_map[\"uitoolbar\"] = uitoolbar::properties::factory_defaults ();\n  plist_map[\"uipushtool\"] = uipushtool::properties::factory_defaults ();\n  plist_map[\"uitoggletool\"] = uitoggletool::properties::factory_defaults ();\n\n  return plist_map;\n}\n\n// ---------------------------------------------------------------------\n\nDEFMETHOD (ishghandle, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} ishghandle (@var{h})\nReturn true if @var{h} is a graphics handle and false otherwise.\n\n@var{h} may also be a matrix of handles in which case a logical array is\nreturned that is true where the elements of @var{h} are graphics handles and\nfalse where they are not.\n@seealso{isgraphics, isaxes, isfigure, ishandle}\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (ishghandle (args(0)));\n}\n\n/*\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   assert (ishghandle (hf));\n%!   assert (! ishghandle (-hf));\n%!   ax = gca ();\n%!   l = line ();\n%!   assert (ishghandle (ax));\n%!   assert (! ishghandle (-ax));\n%!   assert (ishghandle ([l, -1, ax, hf]), logical ([1, 0, 1, 1]));\n%!   assert (ishghandle ([l, -1, ax, hf]'), logical ([1, 0, 1, 1]'));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!assert (ishghandle ([-1 0]), [false true])\n*/\n\nstatic bool\nis_handle_visible (const graphics_handle& h)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  return h.ok () && gh_mgr.is_handle_visible (h);\n}\n\nstatic bool\nis_handle_visible (double val)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  return is_handle_visible (gh_mgr.lookup (val));\n}\n\nstatic octave_value\nis_handle_visible (const octave_value& val)\n{\n  octave_value retval = false;\n\n  if (val.is_real_scalar () && is_handle_visible (val.double_value ()))\n    retval = true;\n  else if (val.isnumeric () && val.isreal ())\n    {\n      const NDArray handles = val.array_value ();\n\n      boolNDArray result (handles.dims ());\n\n      for (octave_idx_type i = 0; i < handles.numel (); i++)\n        result.xelem (i) = is_handle_visible (handles(i));\n\n      retval = result;\n    }\n\n  return retval;\n}\n\nDEFUN (__is_handle_visible__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} __is_handle_visible__ (@var{h})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (is_handle_visible (args(0)));\n}\n\nDEFMETHOD (reset, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} reset (@var{h})\nReset the properties of the graphic object @var{h} to their default values.\n\nFor figures, the properties @qcode{\"position\"}, @qcode{\"units\"},\n@qcode{\"windowstyle\"}, and @qcode{\"paperunits\"} are not affected.\nFor axes, the properties @qcode{\"position\"} and @qcode{\"units\"} are\nnot affected.\n\nThe input @var{h} may also be a vector of graphic handles in which case\neach individual object will be reset.\n@seealso{cla, clf, newplot}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // get vector of graphics handles\n  ColumnVector hcv = args(0).xvector_value (\"reset: H must be a graphics handle\");\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  // loop over graphics objects\n  for (octave_idx_type n = 0; n < hcv.numel (); n++)\n    gh_mgr.get_object (hcv(n)).reset_default_properties ();\n\n  Vdrawnow_requested = true;\n\n  return ovl ();\n}\n\n/*\n\n%!test  # line object\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   tol = 20 * eps;\n%!   hax = axes (\"defaultlinelinewidth\", 3);\n%!\n%!   hli = line (1:10, 1:10, 1:10, \"marker\", \"o\",\n%!               \"markerfacecolor\", \"b\", \"linestyle\", \":\");\n%!\n%!   reset (hli);\n%!   assert (get (hli, \"marker\"), get (0, \"defaultlinemarker\"));\n%!   assert (get (hli, \"markerfacecolor\"),\n%!           get (0, \"defaultlinemarkerfacecolor\"));\n%!   assert (get (hli, \"linestyle\"), get (0, \"defaultlinelinestyle\"));\n%!   assert (get (hli, \"linewidth\"), 3, tol);  # parent axes defaults\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test  # patch object\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   tol = 20 * eps;\n%!   t1 = (1/16:1/8:1)' * 2*pi;\n%!   t2 = ((1/16:1/16:1)' + 1/32) * 2*pi;\n%!   x1 = sin (t1) - 0.8;\n%!   y1 = cos (t1);\n%!   x2 = sin (t2) + 0.8;\n%!   y2 = cos (t2);\n%!   vert = [x1, y1; x2, y2];\n%!   fac = [1:8,NaN(1,8);9:24];\n%!   hpa = patch (\"Faces\",fac, \"Vertices\",vert, \"FaceColor\",\"r\");\n%!\n%!   reset (hpa);\n%!   assert (get (hpa, \"faces\"), get (0, \"defaultpatchfaces\"), tol);\n%!   assert (get (hpa, \"vertices\"), get (0, \"defaultpatchvertices\"), tol);\n%!   assert (get (hpa, \"facevertexcdata\"),\n%!           get (0, \"defaultpatchfacevertexcdata\"), tol);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test  # surface object\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   tol = 20 * eps;\n%!   hsu = surface (peaks, \"edgecolor\", \"none\");\n%!\n%!   reset (hsu);\n%!   assert (get (hsu, \"xdata\"), get (0, \"defaultsurfacexdata\"), tol);\n%!   assert (get (hsu, \"ydata\"), get (0, \"defaultsurfaceydata\"), tol);\n%!   assert (get (hsu, \"zdata\"), get (0, \"defaultsurfacezdata\"), tol);\n%!   assert (get (hsu, \"edgecolor\"), get (0, \"defaultsurfaceedgecolor\"), tol);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test  # image object\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   tol = 20 * eps;\n%!   him = image (rand (10,10), \"cdatamapping\", \"scaled\");\n%!\n%!   reset (him);\n%!   assert (get (him, \"cdata\"), get (0, \"defaultimagecdata\"), tol);\n%!   assert (get (him, \"cdatamapping\"),\n%!           get (0, \"defaultimagecdatamapping\"), tol);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test  # text object\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   tol = 20 * eps;\n%!   hte = text (5, 5, \"Hi!\", \"fontsize\", 20 ,\"color\", \"r\");\n%!\n%!   reset (hte);\n%!   assert (get (hte, \"position\"), get (0, \"defaulttextposition\"), tol);\n%!   assert (get (hte, \"fontsize\"), get (0, \"defaulttextfontsize\"), tol);\n%!   assert (get (hte, \"color\"), get (0, \"defaulttextcolor\"), tol);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test  # axes object\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   tol = 20 * eps;\n%!   pos = get (0, \"defaultaxesposition\") * .5;\n%!   hax = axes (\"linewidth\", 2, \"position\", pos);\n%!   title (\"Reset me, please!\");\n%!\n%!   reset (hax);\n%!   assert (get (hax, \"linewidth\"), get (0, \"defaultaxeslinewidth\"), tol);\n%!   assert (get (hax, \"position\"), pos, tol);  # axes position is unchanged\n%!   assert (get (hax, \"default\"), struct ());  # no more axes' defaults\n%!   assert (get (get (hax, \"title\"), \"string\"), \"\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test  # figure object\n%! set (0, \"defaultfigurevisible\", \"off\");\n%! hf = figure (\"visible\", \"off\",\n%!              \"units\", \"normalized\",\n%!              \"position\", [0, 0, pi/10, e/10],\n%!              \"paperunits\", \"normalized\",\n%!              \"paperposition\", [0.1, 0.1, 0.9, 0.9],\n%!              \"tag\", \"foobar\");\n%! unwind_protect\n%!   reset (hf);\n%!   ## Ordinary property is reset\n%!   assert (get (hf, \"tag\"), \"\");\n%!   ## Following 4 special properties are not reset\n%!   assert (get (hf, \"units\"), \"normalized\");\n%!   assert (get (hf, \"position\"), [0, 0, pi/10, e/10]);\n%!   assert (get (hf, \"paperunits\"), \"normalized\");\n%!   assert (get (hf, \"paperposition\"), [0.1, 0.1, 0.9, 0.9]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%!   set (0, \"defaultfigurevisible\", \"remove\");\n%! end_unwind_protect\n\n*/\n\nDEFMETHOD (set, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} set (@var{h}, @var{property}, @var{value}, @dots{})\n@deftypefnx {} {} set (@var{h}, @{@var{properties}@}, @{@var{values}@})\n@deftypefnx {} {} set (@var{h}, @var{pv})\n@deftypefnx {} {@var{value_list} =} set (@var{h}, @var{property})\n@deftypefnx {} {@var{all_value_list} =} set (@var{h})\nSet named property values for the graphics handle (or vector of graphics\nhandles) @var{h}.\n\nThere are three ways to give the property names and values:\n\n@itemize\n@item as a comma-separated list of @var{property}, @var{value} pairs\n\nEach @var{property} is a string containing the property name, each @var{value}\nis a value of the appropriate type for the property.  When there are multiple\nhandles in @var{h}, each one is assigned the same @var{value}.  For example:\n\n@example\n@group\nh = plot ([0, 1]);\nset (h, 'color', 'green');\n@end group\n@end example\n\n@item as a cell array of strings @var{properties} containing property names\nand a cell array @var{values} containing property values.\n\nIn this case, the number of columns of @var{values} must match the number of\nelements in @var{properties}.  The first column of @var{values} contains\nvalues for the first entry in @var{properties}, etc.  The number of rows of\n@var{values} must be 1 or match the number of elements of @var{h}.  In the\nfirst case, each handle in @var{h} will be assigned the same values.  In the\nsecond case, the first handle in @var{h} will be assigned the values from\nthe first row of @var{values} and so on.  For example:\n\n@example\n@group\nh = plot ([0, 1; 1, 0]);\nset (h, @{'color'@}, @{'green'; 'red'@});\n@end group\n@end example\n\n@item as a structure @var{pv}\n\nThis is the same as the first case where the field names of @var{pv} represent\nthe property names, and the field values give the property values.  As with\nthe first case, it is only possible to set one value for a property which will\nbe applied to all handles in @var{h}.  For example:\n\n@example\n@group\nh = plot ([0, 1]);\nprops.color = 'green';\nset (h, props);\n@end group\n@end example\n\n@end itemize\n\nThe three syntaxes for setting properties may appear in any combination.\n\n@code{set} is also used to query the list of values a named property will\ntake.  @code{@var{clist} = set (@var{h}, \"property\")} will return the list\nof possible values for @qcode{\"property\"} in the cell list @var{clist}.\nIf no output variable is used then the list is formatted and printed to the\nscreen.\n\nIf no property is specified (@code{@var{slist} = set (@var{h})}) then a\nstructure @var{slist} is returned where the fieldnames are the properties of\nthe object @var{h} and the fields are the list of possible values for each\nproperty.  If no output variable is used then the list is formatted and\nprinted to the screen.\n\nWhen querying properties only a single graphics handle @var{h} for a single\ngraphics object is permitted.\n\nExample Query\n\n@example\n@group\nhf = figure ();\nset (hf, \"paperorientation\")\n@xresult{}  [ landscape | @{portrait@} ]\n@end group\n@end example\n\n@noindent\nshows the paperorientation property can take two values with the default\nbeing @qcode{\"portrait\"}.\n@seealso{get}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  // get vector of graphics handles\n  ColumnVector hcv = args(0).xvector_value (\"set: H must be a graphics handle\");\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  octave_value retval;\n\n  // Process requests for default value(s)\n  if (nargin == 1)\n    {\n      if (hcv.numel () > 1)\n        error (\"set: H must be a single graphics handle when querying properties\");\n\n      graphics_object go = gh_mgr.get_object (hcv(0));\n      if (! go)\n        error (\"set: invalid handle (= %g)\", hcv(0));\n\n      if (nargout > 0)\n        retval = go.values_as_struct ();\n      else\n        {\n          std::string s = go.values_as_string ();\n\n          octave_stdout << s;\n        }\n\n      return retval;\n    }\n  else if (nargin == 2 && args(1).is_string ())\n    {\n      if (hcv.numel () > 1)\n        error (\"set: H must be a single graphics handle when querying properties\");\n\n      std::string property = args(1).string_value ();\n      std::transform (property.begin (), property.end (),\n                      property.begin (), tolower);\n\n      graphics_object go = gh_mgr.get_object (hcv(0));\n\n      if (! go)\n        error (\"set: invalid handle (= %g)\", hcv(0));\n\n      octave_map pmap = go.values_as_struct ();\n\n      if (go.has_readonly_property (property))\n        {\n          if (nargout > 0)\n            retval = Matrix ();\n          else\n            octave_stdout << \"set: \" << property << \" is read-only\"\n                          << std::endl;\n        }\n      else if (pmap.isfield (property))\n        {\n          if (nargout != 0)\n            retval = pmap.getfield (property)(0);\n          else\n            {\n              std::string s = go.value_as_string (property);\n\n              octave_stdout << s;\n            }\n        }\n      else\n        error (R\"(set: unknown property \"%s\")\", property.c_str ());\n\n      return retval;\n    }\n\n  bool request_drawnow = false;\n\n  // Loop over graphics objects\n  for (octave_idx_type n = 0; n < hcv.numel (); n++)\n    {\n      graphics_object go = gh_mgr.get_object (hcv(n));\n\n      if (! go)\n        error (\"set: invalid handle (= %g)\", hcv(n));\n\n      // Loop over input arguments\n      for (octave_idx_type i = 1; i < args.length (); )\n        {\n          if (args(i).is_string ())\n            {\n              if (i == nargin - 1)\n                error (\"set: PROPERTY name must be followed by a VALUE\");\n              const caseless_str pname = args(i).string_value ();\n              const octave_value val = args(i+1);\n              go.set_value_or_default (pname, val);\n              i += 2;\n            }\n          else if (args(i).iscellstr ())\n            {\n              if ((i == nargin - 1) || ! args(i+1).iscell ())\n                error (\"set: cell array of PROPERTIES must be followed by cell array of VALUES\");\n              if (args(i+1).cell_value ().rows () == 1)\n                go.set (args(i).cellstr_value (), args(i+1).cell_value (), 0);\n              else if (hcv.numel () == args(i+1).cell_value ().rows ())\n                go.set (args(i).cellstr_value (), args(i+1).cell_value (), n);\n              else\n                error (\"set: number of graphics handles must match number of \"\n                       \"value rows (%\" OCTAVE_IDX_TYPE_FORMAT \" != \"\n                       \"%\" OCTAVE_IDX_TYPE_FORMAT \")\",\n                       hcv.numel (), args(i+1).cell_value ().rows ());\n              i += 2;\n            }\n          else if (args(i).isstruct ())\n            {\n              go.set (args(i).map_value ());\n              i += 1;\n            }\n          else\n            error (\"set: invalid syntax\");\n        }\n\n      request_drawnow = true;\n    }\n\n  if (request_drawnow)\n    Vdrawnow_requested = true;\n\n  return retval;\n}\n\n/*\n## test setting ticklabels for compatibility\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! set (gca (), \"xticklabel\", [0, 0.2, 0.4, 0.6, 0.8, 1]);\n%! xticklabel = get (gca (), \"xticklabel\");\n%! close (hf);\n%! assert (class (xticklabel), \"char\");\n%! assert (size (xticklabel), [6, 3]);\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! set (gca (), \"xticklabel\", \"0|0.2|0.4|0.6|0.8|1\");\n%! xticklabel = get (gca (), \"xticklabel\");\n%! close (hf);\n%! assert (class (xticklabel), \"char\");\n%! assert (size (xticklabel), [6, 3]);\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! set (gca (), \"xticklabel\", [\"0 \"; \"0.2\"; \"0.4\"; \"0.6\"; \"0.8\"; \"1 \"]);\n%! xticklabel = get (gca (), \"xticklabel\");\n%! close (hf);\n%! assert (class (xticklabel), \"char\");\n%! assert (size (xticklabel), [6, 3]);\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! set (gca (), \"xticklabel\", {\"0\", \"0.2\", \"0.4\", \"0.6\", \"0.8\", \"1\"});\n%! xticklabel = get (gca (), \"xticklabel\");\n%! close (hf);\n%! assert (class (xticklabel), \"cell\");\n%! assert (size (xticklabel), [6, 1]);\n*/\n\nstatic std::string\nget_graphics_object_type (double val)\n{\n  std::string retval;\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_object go = gh_mgr.get_object (val);\n\n  if (! go)\n    error (\"get: invalid handle (= %g)\", val);\n\n  return go.type ();\n}\n\nDEFMETHOD (get, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} get (@var{h})\n@deftypefnx {} {@var{val} =} get (@var{h}, @var{p})\nReturn the value of the named property @var{p} from the graphics handle\n@var{h}.\n\nIf @var{p} is omitted, return the complete property list for @var{h}.\n\nIf @var{h} is a vector, return a cell array including the property values or\nlists respectively.\n@seealso{set}\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  if (args(0).isempty ())\n    return ovl (Matrix ());\n\n  ColumnVector hcv = args(0).xvector_value (\"get: H must be a graphics handle\");\n\n  octave_idx_type hcv_len = hcv.numel ();\n\n  if (nargin == 1 && hcv_len > 1)\n    {\n      std::string typ0 = get_graphics_object_type (hcv(0));\n\n      for (octave_idx_type n = 1; n < hcv_len; n++)\n        {\n          std::string typ = get_graphics_object_type (hcv(n));\n\n          if (typ != typ0)\n            error (\"get: vector of handles must all have the same type\");\n        }\n    }\n\n  octave_value retval;\n  Cell vals;\n  bool use_cell_format = false;\n\n  if (nargin > 1 && args(1).iscellstr ())\n    {\n      Array<std::string> plist = args(1).cellstr_value ();\n\n      octave_idx_type plen = plist.numel ();\n\n      use_cell_format = true;\n\n      vals.resize (dim_vector (hcv_len, plen));\n\n      for (octave_idx_type n = 0; n < hcv_len; n++)\n        {\n          graphics_object go = gh_mgr.get_object (hcv(n));\n\n          if (! go)\n            error (\"get: invalid handle (= %g)\", hcv(n));\n\n          for (octave_idx_type m = 0; m < plen; m++)\n            {\n              caseless_str property = plist(m);\n\n              vals(n, m) = go.get (property);\n            }\n        }\n    }\n  else\n    {\n      caseless_str property;\n\n      if (nargin > 1)\n        property = args(1).xstring_value (\"get: second argument must be property name or cell array of property names\");\n\n      vals.resize (dim_vector (hcv_len, 1));\n\n      for (octave_idx_type n = 0; n < hcv_len; n++)\n        {\n          graphics_object go = gh_mgr.get_object (hcv(n));\n\n          if (! go)\n            error (\"get: invalid handle (= %g)\", hcv(n));\n\n          if (nargin == 1)\n            vals(n) = go.get ();\n          else\n            vals(n) = go.get (property);\n        }\n    }\n\n  if (use_cell_format)\n    retval = vals;\n  else\n    {\n      octave_idx_type vals_len = vals.numel ();\n\n      if (vals_len == 0)\n        retval = Matrix ();\n      else if (vals_len == 1)\n        retval = vals(0);\n      else if (vals_len > 1 && nargin == 1)\n        {\n          OCTAVE_LOCAL_BUFFER (octave_scalar_map, tmp, vals_len);\n\n          for (octave_idx_type n = 0; n < vals_len; n++)\n            tmp[n] = vals(n).scalar_map_value ();\n\n          retval = octave_map::cat (0, vals_len, tmp);\n        }\n      else\n        retval = vals;\n    }\n\n  return retval;\n}\n\n/*\n%!assert (get (findobj (0, \"Tag\", \"nonexistenttag\"), \"nonexistentproperty\"), [])\n*/\n\n// Return all properties from the graphics handle @var{h}.\n// If @var{h} is a vector, return a cell array including the\n// property values or lists respectively.\n\nDEFMETHOD (__get__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{props} =} __get__ (@var{h})\nUndocumented internal function.\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (args.length () != 1)\n    print_usage ();\n\n  ColumnVector hcv = args(0).xvector_value (\"get: H must be a graphics handle\");\n\n  octave_idx_type hcv_len = hcv.numel ();\n\n  Cell vals (dim_vector (hcv_len, 1));\n\n//  vals.resize (dim_vector (hcv_len, 1));\n\n  for (octave_idx_type n = 0; n < hcv_len; n++)\n    {\n      graphics_object go = gh_mgr.get_object (hcv(n));\n\n      if (! go)\n        error (\"get: invalid handle (= %g)\", hcv(n));\n\n      // Disable \"Octave:deprecated-property\" warnings\n      int state = toggle_warn (\"Octave:deprecated-property\", false);\n\n      vals(n) = go.get (true);\n\n      toggle_warn (\"Octave:deprecated-property\", true, state);\n    }\n\n  octave_idx_type vals_len = vals.numel ();\n\n  if (vals_len > 1)\n    return ovl (vals);\n  else if (vals_len == 1)\n    return ovl (vals(0));\n  else\n    return ovl ();\n}\n\nstatic octave_value\nmake_graphics_object (const std::string& go_name,\n                      bool integer_figure_handle,\n                      const octave_value_list& args)\n{\n  octave_value retval;\n\n  double val = octave::numeric_limits<double>::NaN ();\n\n  octave_value_list xargs = args.splice (0, 1);\n\n  caseless_str p (\"parent\");\n\n  // Remove all \"parent\" property overrides of the first argument to function\n  // and accept only the last one (bug #55322).\n  for (int i = 0; i < xargs.length (); i += 2)\n    {\n      if (xargs(i).is_string () && p.compare (xargs(i).string_value ()))\n        {\n          if (i >= (xargs.length () - 1))\n            error (\"__go_%s__: missing value for parent property\",\n                   go_name.c_str ());\n\n          val = xargs(i+1).double_value ();\n\n          xargs = xargs.splice (i, 2);\n          i -= 2;\n        }\n    }\n\n  if (octave::math::isnan (val))\n    val = args(0).xdouble_value (\"__go_%s__: invalid parent\", go_name.c_str ());\n\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  graphics_handle parent = gh_mgr.lookup (val);\n\n  if (! parent.ok ())\n    error (\"__go_%s__: invalid parent\", go_name.c_str ());\n\n  graphics_handle h;\n\n  try\n    {\n      h = gh_mgr.make_graphics_handle (go_name, parent,\n                                       integer_figure_handle, false, false);\n    }\n  catch (octave::execution_exception& ee)\n    {\n      error (ee, \"__go_%s__: %s, unable to create graphics handle\",\n             go_name.c_str (), ee.message ().c_str ());\n    }\n\n  try\n    {\n      xset (h, xargs);\n    }\n  catch (octave::execution_exception& ee)\n    {\n      delete_graphics_object (h);\n      error (ee, \"__go_%s__: %s, unable to create graphics handle\",\n             go_name.c_str (), ee.message ().c_str ());\n    }\n\n  adopt (parent, h);\n\n  xcreatefcn (h);\n  xinitialize (h);\n\n  retval = h.value ();\n\n  Vdrawnow_requested = true;\n\n  return retval;\n}\n\nDEFMETHOD (__go_figure__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hfig} =} __go_figure__ (@var{fignum})\nUndocumented internal function.\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (args.length () == 0)\n    print_usage ();\n\n  double val = args(0).xdouble_value (\"__go_figure__: figure number must be a double value\");\n\n  octave_value retval;\n\n  if (isfigure (val))\n    {\n      graphics_handle h = gh_mgr.lookup (val);\n\n      xset (h, args.splice (0, 1));\n\n      retval = h.value ();\n    }\n  else\n    {\n      bool int_fig_handle = true;\n\n      octave_value_list xargs = args.splice (0, 1);\n\n      graphics_handle h = octave::numeric_limits<double>::NaN ();\n\n      if (octave::math::isnan (val))\n        {\n          caseless_str pname (\"integerhandle\");\n\n          for (int i = 0; i < xargs.length (); i++)\n            {\n              if (xargs(i).is_string ()\n                  && pname.compare (xargs(i).string_value ()))\n                {\n                  if (i < (xargs.length () - 1))\n                    {\n                      std::string pval = xargs(i+1).string_value ();\n\n                      caseless_str on (\"on\");\n                      int_fig_handle = on.compare (pval);\n                      xargs = xargs.splice (i, 2);\n\n                      break;\n                    }\n                }\n            }\n\n          h = gh_mgr.make_graphics_handle (\"figure\", 0, int_fig_handle,\n                                           false, false);\n\n          if (! int_fig_handle)\n            {\n              // We need to initialize the integerhandle property\n              // without calling the set_integerhandle method,\n              // because doing that will generate a new handle value...\n              graphics_object go = gh_mgr.get_object (h);\n              go.get_properties ().init_integerhandle (\"off\");\n            }\n        }\n      else if (val > 0 && octave::math::is_integer (val))\n        h = gh_mgr.make_figure_handle (val, false);\n\n      if (! h.ok ())\n        error (\"__go_figure__: failed to create figure handle\");\n\n      try\n        {\n          xset (h, xargs);\n        }\n      catch (octave::execution_exception& ee)\n        {\n          delete_graphics_object (h);\n          error (ee, \"__go_figure__: unable to create figure handle\");\n        }\n\n      adopt (0, h);\n\n      gh_mgr.push_figure (h);\n\n      xcreatefcn (h);\n      xinitialize (h);\n\n      retval = h.value ();\n    }\n\n  return retval;\n}\n\n#define GO_BODY(TYPE)                                                   \\\n  gh_manager& gh_mgr = interp.get_gh_manager ();                        \\\n                                                                        \\\n  octave::autolock guard (gh_mgr.graphics_lock ());                     \\\n                                                                        \\\n  if (args.length () == 0)                                              \\\n    print_usage ();                                                     \\\n                                                                        \\\n  return octave_value (make_graphics_object (#TYPE, false, args));      \\\n\nint\ncalc_dimensions (const graphics_object& go)\n{\n  int nd = 2;\n\n  if (go.isa (\"surface\"))\n    nd = 3;\n  else if ((go.isa (\"line\") || go.isa (\"patch\") || go.isa (\"scatter\"))\n           && ! go.get (\"zdata\").isempty ())\n    nd = 3;\n  else\n    {\n      Matrix kids = go.get_properties ().get_children ();\n\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      for (octave_idx_type i = 0; i < kids.numel (); i++)\n        {\n          graphics_handle hkid = gh_mgr.lookup (kids(i));\n\n          if (hkid.ok ())\n            {\n              const graphics_object& kid = gh_mgr.get_object (hkid);\n\n              if (kid.valid_object ())\n                nd = calc_dimensions (kid);\n\n              if (nd == 3)\n                break;\n            }\n        }\n    }\n\n  return nd;\n}\n\nDEFMETHOD (__calc_dimensions__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{ndims} =} __calc_dimensions__ (@var{axes})\nInternal function.\n\nDetermine the number of dimensions in a graphics object, either 2 or 3.\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (args.length () != 1)\n    print_usage ();\n\n  double h = args(0).xdouble_value (\"__calc_dimensions__: first argument must be a graphics handle\");\n\n  return ovl (calc_dimensions (gh_mgr.get_object (h)));\n}\n\nDEFMETHOD (__go_axes__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hax} =} __go_axes__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (axes);\n}\n\nDEFMETHOD (__go_line__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hl} =} __go_line__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (line);\n}\n\nDEFMETHOD (__go_text__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{ht} =} __go_text__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (text);\n}\n\nDEFMETHOD (__go_image__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hi} =} __go_image__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (image);\n}\n\nDEFMETHOD (__go_surface__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hs} =} __go_surface__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (surface);\n}\n\nDEFMETHOD (__go_patch__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hp} =} __go_patch__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (patch);\n}\n\nDEFMETHOD (__go_scatter__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hs} =} __go_scatter__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (scatter);\n}\n\nDEFMETHOD (__go_light__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hl} =} __go_light__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (light);\n}\n\nDEFMETHOD (__go_hggroup__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hgg} =} __go_hggroup__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (hggroup);\n}\n\nDEFMETHOD (__go_uimenu__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hui} =} __go_uimenu__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (uimenu);\n}\n\nDEFMETHOD (__go_uicontrol__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hui} =} __go_uicontrol__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (uicontrol);\n}\n\nDEFMETHOD (__go_uibuttongroup__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hui} =} __go_uibuttongroup__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (uibuttongroup);\n}\n\nDEFMETHOD (__go_uipanel__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hui} =} __go_uipanel__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (uipanel);\n}\n\nDEFMETHOD (__go_uicontextmenu__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hui} =} __go_uicontextmenu__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (uicontextmenu);\n}\n\nDEFMETHOD (__go_uitable__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hui} =} __go_uitable__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (uitable);\n}\n\nDEFMETHOD (__go_uitoolbar__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hui} =} __go_uitoolbar__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (uitoolbar);\n}\n\nDEFMETHOD (__go_uipushtool__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hui} =} __go_uipushtool__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (uipushtool);\n}\n\nDEFMETHOD (__go_uitoggletool__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hui} =} __go_uitoggletool__ (@var{parent})\nUndocumented internal function.\n@end deftypefn */)\n{\n  GO_BODY (uitoggletool);\n}\n\nDEFMETHOD (__go_delete__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __go_delete__ (@var{h})\nUndocumented internal function.\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (args.length () != 1)\n    print_usage ();\n\n  graphics_handle h = octave::numeric_limits<double>::NaN ();\n\n  const NDArray vals = args(0).xarray_value (\"delete: invalid graphics object\");\n\n  // Check all the handles to delete are valid first,\n  // as callbacks might delete one of the handles we later want to delete.\n  for (octave_idx_type i = 0; i < vals.numel (); i++)\n    {\n      h = gh_mgr.lookup (vals(i));\n\n      if (! h.ok ())\n        error (\"delete: invalid graphics object (= %g)\", vals(i));\n    }\n\n  delete_graphics_objects (vals);\n\n  return ovl ();\n}\n\nDEFMETHOD (__go_handles__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hg_list} =} __go_handles__ (@var{show_hidden})\nUndocumented internal function.\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  bool show_hidden = false;\n\n  if (args.length () > 0)\n    show_hidden = args(0).bool_value ();\n\n  return ovl (gh_mgr.handle_list (show_hidden));\n}\n\nDEFMETHOD (__go_figure_handles__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hfig_list} =} __go_figure_handles__ (@var{show_hidden})\nUndocumented internal function.\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  bool show_hidden = false;\n\n  if (args.length () > 0)\n    show_hidden = args(0).bool_value ();\n\n  return ovl (gh_mgr.figure_handle_list (show_hidden));\n}\n\nDEFMETHOD (__go_execute_callback__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __go_execute_callback__ (@var{h}, @var{name})\n@deftypefnx {} {} __go_execute_callback__ (@var{h}, @var{name}, @var{param})\nUndocumented internal function.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  const NDArray vals = args(0).xarray_value (\"__go_execute_callback__: invalid graphics object\");\n\n  std::string name = args(1).xstring_value (\"__go_execute_callback__: invalid callback name\");\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  for (octave_idx_type i = 0; i < vals.numel (); i++)\n    {\n      double val = vals(i);\n\n      graphics_handle h = gh_mgr.lookup (val);\n\n      if (! h.ok ())\n        error (\"__go_execute_callback__: invalid graphics object (= %g)\", val);\n\n      if (nargin == 2)\n        gh_mgr.execute_callback (h, name);\n      else\n        gh_mgr.execute_callback (h, name, args(2));\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (__go_post_callback__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __go_post_callback__ (@var{h}, @var{name})\n@deftypefnx {} {} __go_post_callback__ (@var{h}, @var{name}, @var{param})\nUndocumented internal function.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  const NDArray vals = args(0).xarray_value (\"__go_post_callback__: invalid graphics object\");\n\n  std::string name = args(1).xstring_value (\"__go_post_callback__: invalid callback name\");\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  for (octave_idx_type i = 0; i < vals.numel (); i++)\n    {\n      double val = vals(i);\n\n      graphics_handle h = gh_mgr.lookup (val);\n\n      if (! h.ok ())\n        error (\"__go_execute_callback__: invalid graphics object (= %g)\", val);\n\n      if (nargin == 2)\n        gh_mgr.post_callback (h, name);\n      else\n        gh_mgr.post_callback (h, name, args(2));\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (__image_pixel_size__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{sz} =} __image_pixel_size__ (@var{h})\nInternal function: returns the pixel size of the image in normalized units.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  double h = args(0).xdouble_value (\"__image_pixel_size__: argument is not a handle\");\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (! go || ! go.isa (\"image\"))\n    error (\"__image_pixel_size__: object is not an image\");\n\n  image::properties& ip\n    = dynamic_cast<image::properties&> (go.get_properties ());\n\n  Matrix dp = Matrix (1, 2);\n  dp(0) = ip.pixel_xsize ();\n  dp(1) = ip.pixel_ysize ();\n  return ovl (dp);\n}\n\nDEFMETHOD (available_graphics_toolkits, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{toolkits} =} available_graphics_toolkits ()\nReturn a cell array of registered graphics toolkits.\n@seealso{graphics_toolkit, register_graphics_toolkit}\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  octave::gtk_manager& gtk_mgr = interp.get_gtk_manager ();\n\n  return ovl (gtk_mgr.available_toolkits_list ());\n}\n\nDEFMETHOD (register_graphics_toolkit, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} register_graphics_toolkit (\"@var{toolkit}\")\nList @var{toolkit} as an available graphics toolkit.\n\nProgramming Note: No input validation is done on the input string; it is simply\nadded to the list of possible graphics toolkits.\n@seealso{available_graphics_toolkits}\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"register_graphics_toolkit: TOOLKIT must be a string\");\n\n  octave::gtk_manager& gtk_mgr = interp.get_gtk_manager ();\n\n  gtk_mgr.register_toolkit (name);\n\n  return ovl ();\n}\n\nDEFMETHOD (loaded_graphics_toolkits, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{toolkits} =} loaded_graphics_toolkits ()\nReturn a cell array of the currently loaded graphics toolkits.\n@seealso{available_graphics_toolkits}\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  octave::gtk_manager& gtk_mgr = interp.get_gtk_manager ();\n\n  return ovl (gtk_mgr.loaded_toolkits_list ());\n}\n\nDEFMETHOD (__show_figure__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __show_figure__ (@var{n})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  double h = args(0).xdouble_value (\"__show_figure__: invalid handle H\");\n\n  graphics_handle gh = gh_mgr.lookup (h);\n\n  if (! gh.ok ())\n    error (\"__show_figure__: invalid graphics object (= %g)\", h);\n\n  graphics_object go = gh_mgr.get_object (gh);\n\n  figure::properties& fprops\n    = dynamic_cast<figure::properties&> (go.get_properties ());\n\n  fprops.get_toolkit ().show_figure (go);\n\n  return ovl ();\n}\n\nDEFMETHOD (drawnow, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} drawnow ()\n@deftypefnx {} {} drawnow (\"expose\")\n@deftypefnx {} {} drawnow (@var{term}, @var{file}, @var{debug_file})\nUpdate figure windows and their children.\n\nThe event queue is flushed and any callbacks generated are executed.\n\nWith the optional argument @qcode{\"expose\"}, only graphic objects are\nupdated and no other events or callbacks are processed.\n\nThe third calling form of @code{drawnow} is for debugging and is\nundocumented.\n@seealso{refresh}\n@end deftypefn */)\n{\n  if (args.length () > 3)\n    print_usage ();\n\n  octave::unwind_protect_var<bool> restore_var (Vdrawnow_requested, false);\n\n  // Redraw unless we are in the middle of a deletion.\n\n  if (! delete_executing)\n    {\n      gh_manager& gh_mgr = interp.get_gh_manager ();\n\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      if (args.length () <= 1)\n        {\n          // First process events so that the redraw happens when all\n          // objects are in their definite state.\n          bool do_events = true;\n\n          if (args.length () == 1)\n            {\n              caseless_str val (args(0).xstring_value (\"drawnow: first argument must be a string\"));\n\n              if (val.compare (\"expose\"))\n                do_events = false;\n              else\n                error (\"drawnow: invalid argument, 'expose' is only valid option\");\n            }\n\n          if (do_events)\n            {\n              gh_mgr.unlock ();\n\n              gh_mgr.process_events ();\n\n              gh_mgr.lock ();\n            }\n\n          Matrix hlist = gh_mgr.figure_handle_list (true);\n\n          // Redraw modified figures\n          for (int i = 0; i < hlist.numel (); i++)\n            {\n              graphics_handle h = gh_mgr.lookup (hlist(i));\n\n              if (h.ok () && h != 0)\n                {\n                  graphics_object go = gh_mgr.get_object (h);\n                  figure::properties& fprops\n                    = dynamic_cast<figure::properties&> (go.get_properties ());\n\n                  if (fprops.is_modified ())\n                    {\n                      if (fprops.is_visible ())\n                        {\n                          gh_mgr.unlock ();\n\n                          fprops.get_toolkit ().redraw_figure (go);\n\n                          gh_mgr.lock ();\n                        }\n\n                      fprops.set_modified (false);\n                    }\n                }\n\n            }\n        }\n      else if (args.length () >= 2 && args.length () <= 3)\n        {\n          std::string term, file, debug_file;\n\n          term = args(0).xstring_value (\"drawnow: TERM must be a string\");\n\n          file = args(1).xstring_value (\"drawnow: FILE must be a string\");\n\n          if (file.empty ())\n            error (\"drawnow: empty output ''\");\n          else if (file.length () == 1 && file[0] == '|')\n            error (\"drawnow: empty pipe '|'\");\n          else if (file[0] != '|')\n            {\n              std::size_t pos = file.find_last_of (octave::sys::file_ops::dir_sep_chars ());\n\n              if (pos != std::string::npos)\n                {\n                  std::string dirname = file.substr (0, pos+1);\n\n                  if (! octave::sys::dir_exists (dirname))\n                    error (\"drawnow: nonexistent directory '%s'\",\n                           dirname.c_str ());\n\n                }\n            }\n\n          debug_file = (args.length () > 2 ? args(2).xstring_value (\"drawnow: DEBUG_FILE must be a string\") :\n                        \"\");\n\n          graphics_handle h = gcf ();\n\n          if (! h.ok ())\n            error (\"drawnow: nothing to draw\");\n\n          graphics_object go = gh_mgr.get_object (h);\n\n          gh_mgr.unlock ();\n\n          go.get_toolkit ().print_figure (go, term, file, debug_file);\n\n          gh_mgr.lock ();\n        }\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (addlistener, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} addlistener (@var{h}, @var{prop}, @var{fcn})\nRegister @var{fcn} as listener for the property @var{prop} of the graphics\nobject @var{h}.\n\nProperty listeners are executed (in order of registration) when the property\nis set.  The new value is already available when the listeners are executed.\n\n@var{prop} must be a string naming a valid property in @var{h}.\n\n@var{fcn} can be a function handle, a string or a cell array whose first\nelement is a function handle.  If @var{fcn} is a function handle, the\ncorresponding function should accept at least 2 arguments, that will be\nset to the object handle and the empty matrix respectively.  If @var{fcn}\nis a string, it must be any valid octave expression.  If @var{fcn} is a cell\narray, the first element must be a function handle with the same signature\nas described above.  The next elements of the cell array are passed\nas additional arguments to the function.\n\nExample:\n\n@example\n@group\nfunction my_listener (h, dummy, p1)\n  fprintf (\"my_listener called with p1=%s\\n\", p1);\nendfunction\n\naddlistener (gcf, \"position\", @{@@my_listener, \"my string\"@})\n@end group\n@end example\n\n@seealso{dellistener, addproperty, hggroup}\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  int nargin = args.length ();\n\n  if (nargin < 3 || nargin > 4)\n    print_usage ();\n\n  double h = args(0).xdouble_value (\"addlistener: invalid handle H\");\n\n  std::string pname = args(1).xstring_value (\"addlistener: PROP must be a string\");\n\n  graphics_handle gh = gh_mgr.lookup (h);\n\n  if (! gh.ok ())\n    error (\"addlistener: invalid graphics object (= %g)\", h);\n\n  graphics_object go = gh_mgr.get_object (gh);\n\n  go.add_property_listener (pname, args(2), GCB_POSTSET);\n\n  if (args.length () == 4)\n    {\n      caseless_str persistent = args(3).string_value ();\n      if (persistent.compare (\"persistent\"))\n        go.add_property_listener (pname, args(2), GCB_PERSISTENT);\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (dellistener, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} dellistener (@var{h}, @var{prop}, @var{fcn})\nRemove the registration of @var{fcn} as a listener for the property\n@var{prop} of the graphics object @var{h}.\n\nThe function @var{fcn} must be the same variable (not just the same value),\nas was passed to the original call to @code{addlistener}.\n\nIf @var{fcn} is not defined then all listener functions of @var{prop}\nare removed.\n\nExample:\n\n@example\n@group\nfunction my_listener (h, dummy, p1)\n  fprintf (\"my_listener called with p1=%s\\n\", p1);\nendfunction\n\nc = @{@@my_listener, \"my string\"@};\naddlistener (gcf, \"position\", c);\ndellistener (gcf, \"position\", c);\n@end group\n@end example\n\n@seealso{addlistener}\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (args.length () < 2 || args.length () > 3)\n    print_usage ();\n\n  double h = args(0).xdouble_value (\"dellistener: invalid handle\");\n\n  std::string pname = args(1).xstring_value (\"dellistener: PROP must be a string\");\n\n  graphics_handle gh = gh_mgr.lookup (h);\n\n  if (! gh.ok ())\n    error (\"dellistener: invalid graphics object (= %g)\", h);\n\n  graphics_object go = gh_mgr.get_object (gh);\n\n  if (args.length () == 2)\n    go.delete_property_listener (pname, octave_value (), GCB_POSTSET);\n  else\n    {\n      if (args(2).is_string ()\n          && args(2).string_value () == \"persistent\")\n        {\n          go.delete_property_listener (pname, octave_value (),\n                                       GCB_PERSISTENT);\n          go.delete_property_listener (pname, octave_value (),\n                                       GCB_POSTSET);\n        }\n      else\n        go.delete_property_listener (pname, args(2), GCB_POSTSET);\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (addproperty, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} addproperty (@var{name}, @var{h}, @var{type})\n@deftypefnx {} {} addproperty (@var{name}, @var{h}, @var{type}, @var{arg}, @dots{})\nCreate a new property named @var{name} in graphics object @var{h}.\n\n@var{type} determines the type of the property to create.  @var{args}\nusually contains the default value of the property, but additional\narguments might be given, depending on the type of the property.\n\nThe supported property types are:\n\n@table @code\n@item string\nA string property.  @var{arg} contains the default string value.\n\n@item any\nAn @nospell{un-typed} property.  This kind of property can hold any octave\nvalue.  @var{args} contains the default value.\n\n@item radio\nA string property with a limited set of accepted values.  The first\nargument must be a string with all accepted values separated by\na vertical bar ('|').  The default value can be marked by enclosing\nit with a '@{' '@}' pair.  The default value may also be given as\nan optional second string argument.\n\n@item boolean\nA boolean property.  This property type is equivalent to a radio\nproperty with \"on|off\" as accepted values.  @var{arg} contains\nthe default property value.\n\n@item double\nA scalar double property.  @var{arg} contains the default value.\n\n@item handle\nA handle property.  This kind of property holds the handle of a\ngraphics object.  @var{arg} contains the default handle value.\nWhen no default value is given, the property is initialized to\nthe empty matrix.\n\n@item data\nA data (matrix) property.  @var{arg} contains the default data\nvalue.  When no default value is given, the data is initialized to\nthe empty matrix.\n\n@item color\nA color property.  @var{arg} contains the default color value.\nWhen no default color is given, the property is set to black.\nAn optional second string argument may be given to specify an\nadditional set of accepted string values (like a radio property).\n@end table\n\n@var{type} may also be the concatenation of a core object type and\na valid property name for that object type.  The property created\nthen has the same characteristics as the referenced property (type,\npossible values, hidden state@dots{}).  This allows one to clone an\nexisting property into the graphics object @var{h}.\n\nExamples:\n\n@example\n@group\naddproperty (\"my_property\", gcf, \"string\", \"a string value\");\naddproperty (\"my_radio\", gcf, \"radio\", \"val_1|val_2|@{val_3@}\");\naddproperty (\"my_style\", gcf, \"linelinestyle\", \"--\");\n@end group\n@end example\n\n@seealso{addlistener, hggroup}\n@end deftypefn */)\n{\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  if (args.length () < 3)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"addproperty: NAME must be a string\");\n\n  double h = args(1).xdouble_value (\"addproperty: invalid handle H\");\n\n  graphics_handle gh = gh_mgr.lookup (h);\n\n  if (! gh.ok ())\n    error (\"addproperty: invalid graphics object (= %g)\", h);\n\n  graphics_object go = gh_mgr.get_object (gh);\n\n  std::string type = args(2).xstring_value (\"addproperty: TYPE must be a string\");\n\n  if (go.get_properties ().has_property (name))\n    error (\"addproperty: a '%s' property already exists in the graphics object\",\n           name.c_str ());\n\n  property p = property::create (name, gh, type, args.splice (0, 3));\n\n  go.get_properties ().insert_property (name, p);\n\n  return ovl ();\n}\n\noctave_value\nget_property_from_handle (double handle, const std::string& property,\n                          const std::string& fcn)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  graphics_object go = gh_mgr.get_object (handle);\n\n  if (! go)\n    error (\"%s: invalid handle (= %g)\", fcn.c_str (), handle);\n\n  return go.get (caseless_str (property));\n}\n\nbool\nset_property_in_handle (double handle, const std::string& property,\n                        const octave_value& arg, const std::string& fcn)\n{\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  graphics_object go = gh_mgr.get_object (handle);\n\n  if (! go)\n    error (\"%s: invalid handle (= %g)\", fcn.c_str (), handle);\n\n  go.set (caseless_str (property), arg);\n\n  return true;\n}\n\nstatic bool\ncompare_property_values (octave::interpreter& interp,\n                         const octave_value& ov1, const octave_value& ov2)\n{\n  octave_value_list args(2);\n\n  args(0) = ov1;\n  args(1) = ov2;\n\n  octave_value_list result = interp.feval (\"isequal\", args, 1);\n\n  if (result.length () > 0)\n    return result(0).bool_value ();\n\n  return false;\n}\n\nstatic std::map<uint32_t, bool> waitfor_results;\n\nstatic void\ncleanup_waitfor_id (uint32_t id)\n{\n  waitfor_results.erase (id);\n}\n\nstatic void\ndo_cleanup_waitfor_listener (const octave_value& listener,\n                             listener_mode mode = GCB_POSTSET)\n{\n  Cell c = listener.cell_value ();\n\n  if (c.numel () >= 4)\n    {\n      double h = c(2).double_value ();\n\n      caseless_str pname = c(3).string_value ();\n\n      gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n      octave::autolock guard (gh_mgr.graphics_lock ());\n\n      graphics_handle gh = gh_mgr.lookup (h);\n\n      if (gh.ok ())\n        {\n          graphics_object go = gh_mgr.get_object (gh);\n\n          if (go.get_properties ().has_property (pname))\n            {\n              go.get_properties ().delete_listener (pname, listener, mode);\n\n              if (mode == GCB_POSTSET)\n                go.get_properties ().delete_listener (pname, listener,\n                                                      GCB_PERSISTENT);\n            }\n        }\n    }\n}\n\nstatic void\ncleanup_waitfor_postset_listener (const octave_value& listener)\n{ do_cleanup_waitfor_listener (listener, GCB_POSTSET); }\n\nstatic void\ncleanup_waitfor_predelete_listener (const octave_value& listener)\n{ do_cleanup_waitfor_listener (listener, GCB_PREDELETE); }\n\nDECLARE_STATIC_METHODX (waitfor_listener, interp, args, )\n{\n  if (args.length () > 3)\n    {\n      uint32_t id = args(2).uint32_scalar_value ().value ();\n\n      if (args.length () > 5)\n        {\n          double h = args(0).double_value ();\n\n          caseless_str pname = args(4).string_value ();\n\n          gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n          octave::autolock guard (gh_mgr.graphics_lock ());\n\n          graphics_handle gh = gh_mgr.lookup (h);\n\n          if (gh.ok ())\n            {\n              graphics_object go = gh_mgr.get_object (gh);\n              octave_value pvalue = go.get (pname);\n\n              if (compare_property_values (interp, pvalue, args(5)))\n                waitfor_results[id] = true;\n            }\n        }\n      else\n        waitfor_results[id] = true;\n    }\n\n  return ovl ();\n}\n\nDECLARE_STATIC_FUNX (waitfor_del_listener, args, )\n{\n  if (args.length () > 2)\n    {\n      uint32_t id = args(2).uint32_scalar_value ().value ();\n\n      waitfor_results[id] = true;\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (waitfor, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} waitfor (@var{h})\n@deftypefnx {} {} waitfor (@var{h}, @var{prop})\n@deftypefnx {} {} waitfor (@var{h}, @var{prop}, @var{value})\n@deftypefnx {} {} waitfor (@dots{}, \"timeout\", @var{timeout})\nSuspend the execution of the current program until a condition is\nsatisfied on the graphics handle @var{h}.\n\nWhile the program is suspended graphics events are still processed normally,\nallowing callbacks to modify the state of graphics objects.  This function\nis reentrant and can be called from a callback, while another @code{waitfor}\ncall is pending at the top-level.\n\nIn the first form, program execution is suspended until the graphics object\n@var{h} is destroyed.  If the graphics handle is invalid or if @var{h} is\nthe root graphics handle and no property @var{prop} was provided, the function\nreturns immediately.\n\nIn the second form, execution is suspended until the graphics object is\ndestroyed or the property named @var{prop} is modified.  If the graphics\nhandle is invalid or the property does not exist, the function returns\nimmediately.\n\nIn the third form, execution is suspended until the graphics object is\ndestroyed or the property named @var{prop} is set to @var{value}.  The\nfunction @code{isequal} is used to compare property values.  If the graphics\nhandle is invalid, the property does not exist or the property is already\nset to @var{value}, the function returns immediately.\n\nAn optional timeout can be specified using the property @qcode{\"timeout\"}.\nThis timeout value is the number of seconds to wait for the condition to be\ntrue.  @var{timeout} must be at least 1.  If a smaller value is specified, a\nwarning is issued and a value of 1 is used instead.  If the timeout value is\nnot an integer, it is truncated towards 0.\n\nTo define a condition on a property named @qcode{\"timeout\"}, use the string\n@qcode{'@backslashchar{}timeout'} instead.\n\nIn all cases, typing CTRL-C stops program execution immediately.\n@seealso{waitforbuttonpress, isequal}\n@end deftypefn */)\n{\n  if (args.length () == 0)\n    print_usage ();\n\n  // return immediately if the graphics handle is invalid\n  if (args(0).isempty ())\n    return ovl ();\n\n  double h = args(0).xdouble_value (\"waitfor: invalid handle value\");\n\n  if (! ishghandle (h) || (h == 0 && args.length () == 1))\n    return ovl ();\n\n  caseless_str pname;\n\n  octave::unwind_action cleanup_waitfor_id_action;\n  octave::unwind_action cleanup_waitfor_postset_listener_action;\n  octave::unwind_action cleanup_waitfor_predelete_listener_action;\n\n  static uint32_t id_counter = 0;\n  uint32_t id = 0;\n\n  int max_arg_index = 0;\n  int timeout_index = -1;\n\n  double timeout = 0;\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  if (args.length () > 1)\n    {\n      pname = args(1).xstring_value (\"waitfor: PROP must be a string\");\n\n      if (pname.empty ())\n        error (\"waitfor: PROP must be a non-empty string\");\n\n      if (pname != \"timeout\")\n        {\n          if (pname.compare (R\"(\\timeout)\"))\n            pname = \"timeout\";\n\n          static octave_value wf_listener;\n\n          if (! wf_listener.is_defined ())\n            wf_listener\n              = octave_value (new octave_builtin (waitfor_listener,\n                                                  \"waitfor_listener\"));\n\n          max_arg_index++;\n          if (args.length () > 2)\n            {\n              if (args(2).is_string ())\n                {\n                  caseless_str s = args(2).string_value ();\n\n                  if (s.compare (\"timeout\"))\n                    timeout_index = 2;\n                  else\n                    max_arg_index++;\n                }\n              else\n                max_arg_index++;\n            }\n\n          Cell listener (1, max_arg_index >= 2 ? 5 : 4);\n\n          id = id_counter++;\n          cleanup_waitfor_id_action.set (cleanup_waitfor_id, id);\n          waitfor_results[id] = false;\n\n          listener(0) = wf_listener;\n          listener(1) = octave_uint32 (id);\n          listener(2) = h;\n          listener(3) = pname;\n\n          if (max_arg_index >= 2)\n            listener(4) = args(2);\n\n          octave_value ov_listener (listener);\n\n          octave::autolock guard (gh_mgr.graphics_lock ());\n\n          graphics_handle gh = gh_mgr.lookup (h);\n\n          if (gh.ok ())\n            {\n              graphics_object go = gh_mgr.get_object (gh);\n\n              if (max_arg_index >= 2\n                  && compare_property_values (interp, go.get (pname), args(2)))\n                waitfor_results[id] = true;\n              else\n                {\n                  cleanup_waitfor_postset_listener_action.set\n                  (cleanup_waitfor_postset_listener, ov_listener);\n\n                  go.add_property_listener (pname, ov_listener, GCB_POSTSET);\n                  go.add_property_listener (pname, ov_listener, GCB_PERSISTENT);\n\n                  if (go.get_properties ().has_dynamic_property (pname))\n                    {\n                      static octave_value wf_del_listener;\n\n                      if (! wf_del_listener.is_defined ())\n                        wf_del_listener\n                          = octave_value (new octave_builtin\n                                          (waitfor_del_listener,\n                                           \"waitfor_del_listener\"));\n\n                      Cell del_listener (1, 4);\n\n                      del_listener(0) = wf_del_listener;\n                      del_listener(1) = octave_uint32 (id);\n                      del_listener(2) = h;\n                      del_listener(3) = pname;\n\n                      octave_value ov_del_listener (del_listener);\n\n                      cleanup_waitfor_predelete_listener_action.set\n                      (cleanup_waitfor_predelete_listener, ov_del_listener);\n\n                      go.add_property_listener (pname, ov_del_listener,\n                                                GCB_PREDELETE);\n                    }\n                }\n            }\n        }\n    }\n\n  if (timeout_index < 0 && args.length () > (max_arg_index + 1))\n    {\n      caseless_str s = args(max_arg_index +\n                            1).xstring_value (\"waitfor: invalid parameter, expected 'timeout'\");\n\n      if (! s.compare (\"timeout\"))\n        error (\"waitfor: invalid parameter '%s'\", s.c_str ());\n\n      timeout_index = max_arg_index + 1;\n    }\n\n  if (timeout_index >= 0)\n    {\n      if (args.length () <= (timeout_index + 1))\n        error (\"waitfor: missing TIMEOUT value\");\n\n      timeout = args(timeout_index + 1).xscalar_value (\"waitfor: TIMEOUT must be a scalar >= 1\");\n\n      if (timeout < 1)\n        {\n          warning (\"waitfor: TIMEOUT value must be >= 1, using 1 instead\");\n          timeout = 1;\n        }\n    }\n\n  // FIXME: There is still a \"hole\" in the following loop.  The code\n  //        assumes that an object handle is unique, which is a fair\n  //        assumption, except for figures.  If a figure is destroyed\n  //        then recreated with the same figure ID, within the same\n  //        run of event hooks, then the figure destruction won't be\n  //        caught and the loop will not stop.  This is an unlikely\n  //        possibility in practice, though.\n  //\n  //        Using deletefcn callback is also unreliable as it could be\n  //        modified during a callback execution and the waitfor loop\n  //        would not stop.\n  //\n  //        The only \"good\" implementation would require object\n  //        listeners, similar to property listeners.\n\n  octave::sys::time start;\n\n  if (timeout > 0)\n    start.stamp ();\n\n  while (true)\n    {\n      if (true)\n        {\n          octave::autolock guard (gh_mgr.graphics_lock ());\n\n          graphics_handle gh = gh_mgr.lookup (h);\n\n          if (gh.ok ())\n            {\n              if (! pname.empty () && waitfor_results[id])\n                break;\n            }\n          else\n            break;\n        }\n\n      octave::sleep (0.1);  // FIXME: really needed?\n\n      octave_quit ();\n\n      octave::command_editor::run_event_hooks ();\n\n      if (timeout > 0)\n        {\n          octave::sys::time now;\n\n          if (start + timeout < now)\n            break;\n        }\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (__zoom__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __zoom__ (@var{axes}, @var{mode}, @var{factor})\n@deftypefnx {} {} __zoom__ (@var{axes}, \"out\")\n@deftypefnx {} {} __zoom__ (@var{axes}, \"reset\")\nUndocumented internal function.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin != 2 && nargin != 3)\n    print_usage ();\n\n  double h = args(0).double_value ();\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  octave::autolock guard (gh_mgr.graphics_lock ());\n\n  graphics_handle handle = gh_mgr.lookup (h);\n\n  if (! handle.ok ())\n    error (\"__zoom__: invalid handle\");\n\n  graphics_object ax = gh_mgr.get_object (handle);\n\n  axes::properties& ax_props\n    = dynamic_cast<axes::properties&> (ax.get_properties ());\n\n  if (nargin == 2)\n    {\n      std::string opt = args(1).string_value ();\n\n      if (opt == \"out\" || opt == \"reset\")\n        {\n          if (opt == \"out\")\n            {\n              ax_props.clear_zoom_stack ();\n              Vdrawnow_requested = true;\n            }\n          else\n            ax_props.clear_zoom_stack (false);\n        }\n    }\n  else\n    {\n      std::string mode = args(1).string_value ();\n      double factor = args(2).scalar_value ();\n\n      ax_props.zoom (mode, factor);\n      Vdrawnow_requested = true;\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (__get_frame__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{cdata} =} __get_frame__ (@var{hfig})\nInternal function.\n\nReturn the pixel cdata of figure hfig in the form of a height-by-width-by-3\nuint8 array.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double h = args(0).xdouble_value (\"__get_frame__: HFIG is not a handle\");\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (! go || ! go.isa (\"figure\"))\n    error (\"__get_frame__: HFIG is not a figure\");\n\n  // For Matlab compatibility, getframe must flush the event queue.\n  gh_mgr.process_events ();\n\n  return ovl (go.get_toolkit ().get_pixels (go));\n}\n\nDEFMETHOD (__get_position__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{pos} =} __get_position__ (@var{h}, @var{units})\nInternal function.\n\nReturn the position of the graphics object @var{h} in the specified\n@var{units}.\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  double h\n    = args(0).xdouble_value (\"__get_position__: H must be a graphics handle\");\n\n  std::string units\n    = args(1).xstring_value (\"__get_position__: UNITS must be a string\");\n\n  gh_manager& gh_mgr = interp.get_gh_manager ();\n\n  graphics_object go = gh_mgr.get_object (h);\n\n  if (h == 0 || ! go)\n    error (\"__get_position__: H must be a handle to a valid graphics object\");\n\n  graphics_object parent_go = gh_mgr.get_object (go.get_parent ());\n  Matrix bbox = parent_go.get_properties ().get_boundingbox (true)\n                .extract_n (0, 2, 1, 2);\n\n  Matrix pos = convert_position (go.get (\"position\").matrix_value (),\n                                 go.get (\"units\").string_value (),\n                                 units, bbox);\n\n  return ovl (pos);\n}\n\nDEFUN (__get_system_fonts__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{font_struct} =} __get_system_fonts__ ()\nInternal function.\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  octave::text_renderer txt_renderer;\n\n  return ovl (txt_renderer.get_system_fonts ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/graphics.in.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_graphics_h)\n#define octave_graphics_h 1\n\n#include \"octave-config.h\"\n\n#include <cctype>\n#include <cmath>\n\n#include <algorithm>\n#include <list>\n#include <map>\n#include <memory>\n#include <set>\n#include <sstream>\n#include <string>\n#include <unordered_map>\n#include <vector>\n\n#include \"caseless-str.h\"\n\n#include \"errwarn.h\"\n#include \"graphics-handle.h\"\n#include \"graphics-toolkit.h\"\n#include \"oct-map.h\"\n#include \"oct-mutex.h\"\n#include \"oct-refcount.h\"\n#include \"ov.h\"\n#include \"text-renderer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// FIXME: maybe this should be a configure option?\n// Matlab defaults to \"Helvetica\", but that causes problems for many\n// gnuplot users.\n#if ! defined (OCTAVE_DEFAULT_FONTNAME)\n#define OCTAVE_DEFAULT_FONTNAME \"*\"\n#endif\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API base_scaler\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (base_scaler)\n\n  virtual ~base_scaler () = default;\n\n  virtual Matrix scale (const Matrix&) const\n  {\n    error (\"invalid axis scale\");\n  }\n\n  virtual NDArray scale (const NDArray&) const\n  {\n    error (\"invalid axis scale\");\n  }\n\n  virtual double scale (double) const\n  {\n    error (\"invalid axis scale\");\n  }\n\n  virtual double unscale (double) const\n  {\n    error (\"invalid axis scale\");\n  }\n\n  virtual base_scaler * clone () const\n  { return new base_scaler (); }\n\n  virtual bool is_linear () const\n  { return false; }\n};\n\nclass lin_scaler : public base_scaler\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (lin_scaler)\n\n  Matrix scale (const Matrix& m) const { return m; }\n\n  NDArray scale (const NDArray& m) const { return m; }\n\n  double scale (double d) const { return d; }\n\n  double unscale (double d) const { return d; }\n\n  base_scaler * clone () const { return new lin_scaler (); }\n\n  bool is_linear () const { return true; }\n};\n\nclass log_scaler : public base_scaler\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (log_scaler)\n\n  Matrix scale (const Matrix& m) const\n  {\n    Matrix retval (m.rows (), m.cols ());\n\n    do_scale (m.data (), retval.rwdata (), m.numel ());\n\n    return retval;\n  }\n\n  NDArray scale (const NDArray& m) const\n  {\n    NDArray retval (m.dims ());\n\n    do_scale (m.data (), retval.rwdata (), m.numel ());\n\n    return retval;\n  }\n\n  double scale (double d) const\n  { return log10 (d); }\n\n  double unscale (double d) const\n  { return std::pow (10.0, d); }\n\n  base_scaler * clone () const\n  { return new log_scaler (); }\n\nprivate:\n  void do_scale (const double *src, double *dest, int n) const\n  {\n    for (int i = 0; i < n; i++)\n      dest[i] = log10 (src[i]);\n  }\n};\n\nclass OCTINTERP_API neg_log_scaler : public base_scaler\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (neg_log_scaler)\n\n  Matrix scale (const Matrix& m) const\n  {\n    Matrix retval (m.rows (), m.cols ());\n\n    do_scale (m.data (), retval.rwdata (), m.numel ());\n\n    return retval;\n  }\n\n  NDArray scale (const NDArray& m) const\n  {\n    NDArray retval (m.dims ());\n\n    do_scale (m.data (), retval.rwdata (), m.numel ());\n\n    return retval;\n  }\n\n  double scale (double d) const\n  { return -log10 (-d); }\n\n  double unscale (double d) const\n  { return -std::pow (10.0, -d); }\n\n  base_scaler * clone () const\n  { return new neg_log_scaler (); }\n\nprivate:\n  void do_scale (const double *src, double *dest, int n) const\n  {\n    for (int i = 0; i < n; i++)\n      dest[i] = -log10 (-src[i]);\n  }\n};\n\nclass OCTINTERP_API scaler\n{\npublic:\n\n  scaler () : m_rep (new base_scaler ()) { }\n\n  scaler (const scaler& s) : m_rep (s.m_rep->clone ()) { }\n\n  scaler (const std::string& s)\n    : m_rep (s == \"log\"\n             ? new log_scaler ()\n             : (s == \"neglog\"\n                ? new neg_log_scaler ()\n                : (s == \"linear\"\n                   ? new lin_scaler ()\n                   : new base_scaler ())))\n  { }\n\n  ~scaler () { delete m_rep; }\n\n  Matrix scale (const Matrix& m) const\n  { return m_rep->scale (m); }\n\n  NDArray scale (const NDArray& m) const\n  { return m_rep->scale (m); }\n\n  double scale (double d) const\n  { return m_rep->scale (d); }\n\n  double unscale (double d) const\n  { return m_rep->unscale (d); }\n\n  bool is_linear () const\n  { return m_rep->is_linear (); }\n\n  scaler& operator = (const scaler& s)\n  {\n    if (&s != this)\n      {\n        delete m_rep;\n\n        m_rep = s.m_rep->clone ();\n      }\n\n    return *this;\n  }\n\n  scaler& operator = (const std::string& s)\n  {\n    delete m_rep;\n\n    if (s == \"log\")\n      m_rep = new log_scaler ();\n    else if (s == \"neglog\")\n      m_rep = new neg_log_scaler ();\n    else if (s == \"linear\")\n      m_rep = new lin_scaler ();\n    else\n      m_rep = new base_scaler ();\n\n    return *this;\n  }\n\nprivate:\n  base_scaler *m_rep;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API property;\n\n// FIXME: These values should probably be defined inside a namespace or\n// class, but which one is most appropriate?  For now, prefix with\n// \"GCB_\" to avoid conflict with PERSISTENT token ID used in the lexer.\n// The lexer token IDs should probably also be fixed...\n\nenum listener_mode { GCB_POSTSET, GCB_PERSISTENT, GCB_PREDELETE };\n\nclass OCTINTERP_API base_property\n{\npublic:\n  friend class property;\n\npublic:\n  base_property ()\n    : m_id (-1), m_count (1), m_name (), m_parent (), m_hidden (),\n      m_listeners ()\n  { }\n\n  base_property (const std::string& s, const graphics_handle& h)\n    : m_id (-1), m_count (1), m_name (s), m_parent (h), m_hidden (false),\n      m_listeners ()\n  { }\n\n  base_property (const base_property& p)\n    : m_id (-1), m_count (1), m_name (p.m_name), m_parent (p.m_parent),\n      m_hidden (p.m_hidden), m_listeners ()\n  { }\n\n  // FIXME: should we define assignment?\n  base_property& operator = (const base_property&) = delete;\n\n  virtual ~base_property () = default;\n\n  bool ok () const { return m_parent.ok (); }\n\n  std::string get_name () const { return m_name; }\n\n  void set_name (const std::string& s) { m_name = s; }\n\n  graphics_handle get_parent () const { return m_parent; }\n\n  void set_parent (const graphics_handle& h) { m_parent = h; }\n\n  bool is_hidden () const { return m_hidden; }\n\n  void set_hidden (bool flag) { m_hidden = flag; }\n\n  virtual bool is_radio () const { return false; }\n\n  int get_id () const { return m_id; }\n\n  void set_id (int d) { m_id = d; }\n\n  // Sets property value, notifies graphics toolkit.\n  // If do_run is true, runs associated listeners.\n  OCTINTERP_API bool set (const octave_value& v, bool do_run = true,\n                          bool do_notify_toolkit = true);\n\n  virtual octave_value get () const\n  {\n    error (R\"(get: invalid property \"%s\")\", m_name.c_str ());\n  }\n\n  virtual std::string values_as_string () const\n  {\n    error (R\"(values_as_string: invalid property \"%s\")\", m_name.c_str ());\n  }\n\n  virtual Cell values_as_cell () const\n  {\n    error (R\"(values_as_cell: invalid property \"%s\")\", m_name.c_str ());\n  }\n\n  base_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  void add_listener (const octave_value& v, listener_mode mode = GCB_POSTSET)\n  {\n    octave_value_list& l = m_listeners[mode];\n    l.resize (l.length () + 1, v);\n  }\n\n  void delete_listener (const octave_value& v = octave_value (),\n                        listener_mode mode = GCB_POSTSET)\n  {\n    octave_value_list& l = m_listeners[mode];\n\n    if (v.is_defined ())\n      {\n        bool found = false;\n        int i;\n\n        for (i = 0; i < l.length (); i++)\n          {\n            if (v.internal_rep () == l(i).internal_rep ())\n              {\n                found = true;\n                break;\n              }\n          }\n        if (found)\n          {\n            for (int j = i; j < l.length () - 1; j++)\n              l(j) = l(j + 1);\n\n            l.resize (l.length () - 1);\n          }\n      }\n    else\n      {\n        if (mode == GCB_PERSISTENT)\n          l.resize (0);\n        else\n          {\n            octave_value_list lnew (0);\n            octave_value_list& lp = m_listeners[GCB_PERSISTENT];\n            for (int i = l.length () - 1; i >= 0 ; i--)\n              {\n                for (int j = 0; j < lp.length (); j++)\n                  {\n                    if (l(i).internal_rep () == lp(j).internal_rep ())\n                      {\n                        lnew.resize (lnew.length () + 1, l(i));\n                        break;\n                      }\n                  }\n              }\n            l = lnew;\n          }\n      }\n\n  }\n\n  OCTINTERP_API void run_listeners (listener_mode mode = GCB_POSTSET);\n\n  virtual base_property * clone () const\n  { return new base_property (*this); }\n\nprotected:\n  virtual bool do_set (const octave_value&)\n  {\n    error (R\"(set: invalid property \"%s\")\", m_name.c_str ());\n  }\n\nprivate:\n  typedef std::map<listener_mode, octave_value_list> listener_map;\n  typedef std::map<listener_mode, octave_value_list>::iterator\n    listener_map_iterator;\n  typedef std::map<listener_mode, octave_value_list>::const_iterator\n    listener_map_const_iterator;\n\nprivate:\n  int m_id;\n  octave::refcount<octave_idx_type> m_count;\n  std::string m_name;\n  graphics_handle m_parent;\n  bool m_hidden;\n  listener_map m_listeners;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API string_property : public base_property\n{\npublic:\n\n  string_property () = delete;\n\n  string_property (const std::string& s, const graphics_handle& h,\n                   const std::string& val = \"\")\n    : base_property (s, h), m_str (val) { }\n\n  string_property (const string_property&) = default;\n\n  // FIXME: should we define assignment?\n  string_property& operator = (const string_property&) = delete;\n\n  ~string_property () = default;\n\n  octave_value get () const\n  { return octave_value (m_str); }\n\n  std::string string_value () const { return m_str; }\n\n  string_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const { return new string_property (*this); }\n\nprotected:\n  bool do_set (const octave_value& val)\n  {\n    if (! val.is_string ())\n      error (R\"(set: invalid string property value for \"%s\")\",\n             get_name ().c_str ());\n\n    std::string new_str = val.string_value ();\n\n    if (new_str != m_str)\n      {\n        m_str = new_str;\n        return true;\n      }\n    return false;\n  }\n\nprivate:\n  std::string m_str;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API string_array_property : public base_property\n{\npublic:\n  enum desired_enum { string_t, cell_t };\n\n  string_array_property () = delete;\n\n  string_array_property (const std::string& s, const graphics_handle& h,\n                         const std::string& val = \"\", const char& sep = '|',\n                         const desired_enum& typ = string_t)\n    : base_property (s, h), m_desired_type (typ), m_separator (sep), m_str ()\n  {\n    std::size_t pos = 0;\n\n    while (true)\n      {\n        std::size_t new_pos = val.find_first_of (m_separator, pos);\n\n        if (new_pos == std::string::npos)\n          {\n            m_str.append (val.substr (pos));\n            break;\n          }\n        else\n          m_str.append (val.substr (pos, new_pos - pos));\n\n        pos = new_pos + 1;\n      }\n  }\n\n  string_array_property (const std::string& s, const graphics_handle& h,\n                         const Cell& c, const char& sep = '|',\n                         const desired_enum& typ = string_t)\n    : base_property (s, h), m_desired_type (typ), m_separator (sep), m_str ()\n  {\n    if (! c.iscellstr ())\n      error (R\"(set: invalid order property value for \"%s\")\",\n             get_name ().c_str ());\n\n    string_vector strings (c.numel ());\n\n    for (octave_idx_type i = 0; i < c.numel (); i++)\n      strings[i] = c(i).string_value ();\n\n    m_str = strings;\n  }\n\n  string_array_property (const string_array_property&) = default;\n\n  // FIXME: should we define assignment?\n  string_array_property& operator = (const string_array_property&) = delete;\n\n  ~string_array_property () = default;\n\n  octave_value get () const\n  {\n    if (m_desired_type == string_t)\n      return octave_value (string_value ());\n    else\n      return octave_value (cell_value ());\n  }\n\n  std::string string_value () const\n  {\n    std::string s;\n\n    for (octave_idx_type i = 0; i < m_str.numel (); i++)\n      {\n        s += m_str[i];\n        if (i != m_str.numel () - 1)\n          s += m_separator;\n      }\n\n    return s;\n  }\n\n  Cell cell_value () const {return Cell (m_str);}\n\n  string_vector string_vector_value () const { return m_str; }\n\n  string_array_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const\n  { return new string_array_property (*this); }\n\nprotected:\n  bool do_set (const octave_value& val)\n  {\n    if (val.is_string () && val.rows () == 1)\n      {\n        bool replace = false;\n        std::string new_str = val.string_value ();\n        string_vector strings;\n        std::size_t pos = 0;\n\n        // Split single string on delimiter (usually '|')\n        while (pos != std::string::npos)\n          {\n            std::size_t new_pos = new_str.find_first_of (m_separator, pos);\n\n            if (new_pos == std::string::npos)\n              {\n                strings.append (new_str.substr (pos));\n                break;\n              }\n            else\n              strings.append (new_str.substr (pos, new_pos - pos));\n\n            pos = new_pos + 1;\n          }\n\n        if (m_str.numel () == strings.numel ())\n          {\n            for (octave_idx_type i = 0; i < m_str.numel (); i++)\n              if (strings[i] != m_str[i])\n                {\n                  replace = true;\n                  break;\n                }\n          }\n        else\n          replace = true;\n\n        m_desired_type = string_t;\n\n        if (replace)\n          {\n            m_str = strings;\n            return true;\n          }\n      }\n    else if (val.is_string ())  // multi-row character matrix\n      {\n        bool replace = false;\n        charMatrix chm = val.char_matrix_value ();\n        octave_idx_type nel = chm.rows ();\n        string_vector strings (nel);\n\n        if (nel != m_str.numel ())\n          replace = true;\n        for (octave_idx_type i = 0; i < nel; i++)\n          {\n            strings[i] = chm.row_as_string (i);\n            if (! replace && strings[i] != m_str[i])\n              replace = true;\n          }\n\n        m_desired_type = string_t;\n\n        if (replace)\n          {\n            m_str = strings;\n            return true;\n          }\n      }\n    else if (val.iscellstr ())\n      {\n        bool replace = false;\n        Cell new_cell = val.cell_value ();\n\n        string_vector strings = new_cell.cellstr_value ();\n\n        octave_idx_type nel = strings.numel ();\n\n        if (nel != m_str.numel ())\n          replace = true;\n        else\n          {\n            for (octave_idx_type i = 0; i < nel; i++)\n              {\n                if (strings[i] != m_str[i])\n                  {\n                    replace = true;\n                    break;\n                  }\n              }\n          }\n\n        m_desired_type = cell_t;\n\n        if (replace)\n          {\n            m_str = strings;\n            return true;\n          }\n      }\n    else\n      error (R\"(set: invalid string property value for \"%s\")\",\n             get_name ().c_str ());\n\n    return false;\n  }\n\nprivate:\n  desired_enum m_desired_type;\n  char m_separator;\n  string_vector m_str;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API text_label_property : public base_property\n{\npublic:\n  enum type { char_t, cellstr_t };\n\n  text_label_property () = delete;\n\n  text_label_property (const std::string& s, const graphics_handle& h,\n                       const std::string& val = \"\")\n    : base_property (s, h), m_value (val), m_stored_type (char_t)\n  { }\n\n  text_label_property (const std::string& s, const graphics_handle& h,\n                       const NDArray& nda)\n    : base_property (s, h), m_stored_type (char_t)\n  {\n    octave_idx_type nel = nda.numel ();\n\n    m_value.resize (nel);\n\n    for (octave_idx_type i = 0; i < nel; i++)\n      {\n        std::ostringstream buf;\n        buf << nda(i);\n        m_value[i] = buf.str ();\n      }\n  }\n\n  text_label_property (const std::string& s, const graphics_handle& h,\n                       const Cell& c)\n    : base_property (s, h), m_stored_type (cellstr_t)\n  {\n    octave_idx_type nel = c.numel ();\n\n    m_value.resize (nel);\n\n    for (octave_idx_type i = 0; i < nel; i++)\n      {\n        octave_value tmp = c(i);\n\n        if (tmp.is_string ())\n          m_value[i] = c(i).string_value ();\n        else\n          {\n            double d = c(i).double_value ();\n\n            std::ostringstream buf;\n            buf << d;\n            m_value[i] = buf.str ();\n          }\n      }\n  }\n\n  text_label_property (const text_label_property&) = default;\n\n  // FIXME: should we define assignment?\n  text_label_property& operator = (const text_label_property&) = delete;\n\n  ~text_label_property () = default;\n\n  bool empty () const\n  {\n    octave_value tmp = get ();\n    return tmp.isempty ();\n  }\n\n  octave_value get () const\n  {\n    if (m_stored_type == char_t)\n      return octave_value (char_value ());\n    else\n      return octave_value (cell_value ());\n  }\n\n  std::string string_value () const\n  {\n    return m_value.empty () ? \"\" : m_value[0];\n  }\n\n  string_vector string_vector_value () const { return m_value; }\n\n  charMatrix char_value () const { return charMatrix (m_value, ' '); }\n\n  Cell cell_value () const {return Cell (m_value); }\n\n  text_label_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const { return new text_label_property (*this); }\n\nprotected:\n\n  bool do_set (const octave_value& val)\n  {\n    if (val.is_string ())\n      {\n        m_value = val.string_vector_value ();\n\n        m_stored_type = char_t;\n      }\n    else if (val.iscell ())\n      {\n        Cell c = val.cell_value ();\n\n        octave_idx_type nel = c.numel ();\n\n        m_value.resize (nel);\n\n        for (octave_idx_type i = 0; i < nel; i++)\n          {\n            octave_value tmp = c(i);\n\n            if (tmp.is_string ())\n              m_value[i] = c(i).string_value ();\n            else\n              {\n                double d = c(i).double_value ();\n\n                std::ostringstream buf;\n                buf << d;\n                m_value[i] = buf.str ();\n              }\n          }\n\n        m_stored_type = cellstr_t;\n      }\n    else\n      {\n        NDArray nda;\n\n        try\n          {\n            nda = val.array_value ();\n          }\n        catch (octave::execution_exception& ee)\n          {\n            error (ee, R\"(set: invalid string property value for \"%s\")\",\n                   get_name ().c_str ());\n          }\n\n        octave_idx_type nel = nda.numel ();\n\n        m_value.resize (nel);\n\n        for (octave_idx_type i = 0; i < nel; i++)\n          {\n            std::ostringstream buf;\n            buf << nda(i);\n            m_value[i] = buf.str ();\n          }\n\n        m_stored_type = char_t;\n      }\n\n    return true;\n  }\n\nprivate:\n  string_vector m_value;\n  type m_stored_type;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API radio_values\n{\npublic:\n  OCTINTERP_API radio_values (const std::string& opt_string = \"\");\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (radio_values)\n\n  std::string default_value () const { return m_default_val; }\n\n  bool validate (const std::string& val, std::string& match)\n  {\n    bool retval = true;\n\n    if (! contains (val, match))\n      error (\"invalid value = %s\", val.c_str ());\n\n    return retval;\n  }\n\n  bool contains (const std::string& val, std::string& match)\n  {\n    std::size_t k = 0;\n\n    std::size_t len = val.length ();\n\n    std::string first_match;\n\n    for (const auto& possible_val : m_possible_vals)\n      {\n        if (possible_val.compare (val, len))\n          {\n            if (len == possible_val.length ())\n              {\n                // We found a full match (consider the case of val == \"replace\"\n                // with possible values \"replace\" and \"replacechildren\").  Any\n                // other matches are irrelevant, so set match and return now.\n                match = possible_val;\n                return true;\n              }\n            else\n              {\n                if (k == 0)\n                  first_match = possible_val;\n\n                k++;\n              }\n          }\n      }\n\n    if (k == 1)\n      {\n        match = first_match;\n        return true;\n      }\n    else\n      return false;\n  }\n\n  OCTINTERP_API std::string values_as_string () const;\n\n  OCTINTERP_API Cell values_as_cell () const;\n\n  octave_idx_type nelem () const { return m_possible_vals.size (); }\n\nprivate:\n  // Might also want to cache\n  std::string m_default_val;\n  std::set<caseless_str> m_possible_vals;\n};\n\nclass OCTINTERP_API radio_property : public base_property\n{\npublic:\n\n  radio_property () = delete;\n\n  radio_property (const std::string& nm, const graphics_handle& h,\n                  const radio_values& v = radio_values ())\n    : base_property (nm, h),\n      m_vals (v), m_current_val (v.default_value ()) { }\n\n  radio_property (const std::string& nm, const graphics_handle& h,\n                  const std::string& v)\n    : base_property (nm, h),\n      m_vals (v), m_current_val (m_vals.default_value ()) { }\n\n  radio_property (const std::string& nm, const graphics_handle& h,\n                  const radio_values& v, const std::string& def)\n    : base_property (nm, h),\n      m_vals (v), m_current_val (def) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_CTOR (radio_property)\n  OCTAVE_DISABLE_COPY_MOVE_ASGN (radio_property)\n\n  ~radio_property () = default;\n\n  octave_value get () const { return octave_value (m_current_val); }\n\n  const std::string& current_value () const { return m_current_val; }\n\n  std::string values_as_string () const\n  { return m_vals.values_as_string (); }\n\n  Cell values_as_cell () const { return m_vals.values_as_cell (); }\n\n  bool is (const caseless_str& v) const\n  { return v.compare (m_current_val); }\n\n  bool is_radio () const { return true; }\n\n  radio_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const { return new radio_property (*this); }\n\nprotected:\n  bool do_set (const octave_value& newval)\n  {\n    if (! newval.is_string ())\n      error (R\"(set: invalid value for radio property \"%s\")\",\n             get_name ().c_str ());\n\n    std::string s = newval.string_value ();\n\n    std::string match;\n\n    if (! m_vals.validate (s, match))\n      error (R\"(set: invalid value for radio property \"%s\" (value = %s))\",\n             get_name ().c_str (), s.c_str ());\n\n    if (match != m_current_val)\n      {\n        if (s.length () != match.length ())\n          warning_with_id (\"Octave:abbreviated-property-match\",\n                           \"%s: allowing %s to match %s value %s\",\n                           \"set\", s.c_str (), get_name ().c_str (),\n                           match.c_str ());\n        m_current_val = match;\n        return true;\n      }\n    return false;\n  }\n\nprivate:\n  radio_values m_vals;\n  std::string m_current_val;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API color_values\n{\npublic:\n  color_values (double r = 0, double g = 0, double b = 1)\n    : m_rgb (1, 3)\n  {\n    m_rgb(0) = r;\n    m_rgb(1) = g;\n    m_rgb(2) = b;\n\n    validate ();\n  }\n\n  color_values (const std::string& str)\n    : m_rgb (1, 3)\n  {\n    if (! str2rgb (str))\n      error (\"invalid color specification: %s\", str.c_str ());\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (color_values)\n\n  bool operator == (const color_values& c) const\n  {\n    return (m_rgb(0) == c.m_rgb(0)\n            && m_rgb(1) == c.m_rgb(1)\n            && m_rgb(2) == c.m_rgb(2));\n  }\n\n  bool operator != (const color_values& c) const\n  { return ! (*this == c); }\n\n  Matrix rgb () const { return m_rgb; }\n\n  operator octave_value () const { return m_rgb; }\n\n  void validate () const\n  {\n    for (int i = 0; i < 3; i++)\n      {\n        if (m_rgb(i) < 0 ||  m_rgb(i) > 1)\n          error (\"invalid RGB color specification\");\n      }\n  }\n\nprivate:\n  Matrix m_rgb;\n\n  OCTINTERP_API bool str2rgb (const std::string& str);\n};\n\nclass OCTINTERP_API color_property : public base_property\n{\npublic:\n\n  color_property () = delete;\n\n  color_property (const color_values& c, const radio_values& v)\n    : base_property (\"\", graphics_handle ()),\n      m_current_type (color_t), m_color_val (c), m_radio_val (v),\n      m_current_val (v.default_value ())\n  { }\n\n  color_property (const radio_values& v, const color_values& c)\n    : base_property (\"\", graphics_handle ()),\n      m_current_type (radio_t), m_color_val (c), m_radio_val (v),\n      m_current_val (v.default_value ())\n  { }\n\n  color_property (const std::string& nm, const graphics_handle& h,\n                  const color_values& c = color_values (),\n                  const radio_values& v = radio_values ())\n    : base_property (nm, h),\n      m_current_type (color_t), m_color_val (c), m_radio_val (v),\n      m_current_val (v.default_value ())\n  { }\n\n  color_property (const std::string& nm, const graphics_handle& h,\n                  const radio_values& v)\n    : base_property (nm, h),\n      m_current_type (radio_t), m_color_val (color_values ()), m_radio_val (v),\n      m_current_val (v.default_value ())\n  { }\n\n  color_property (const std::string& nm, const graphics_handle& h,\n                  const std::string& v)\n    : base_property (nm, h),\n      m_current_type (radio_t), m_color_val (color_values ()), m_radio_val (v),\n      m_current_val (m_radio_val.default_value ())\n  { }\n\n  color_property (const std::string& nm, const graphics_handle& h,\n                  const color_property& v)\n    : base_property (nm, h),\n      m_current_type (v.m_current_type), m_color_val (v.m_color_val),\n      m_radio_val (v.m_radio_val), m_current_val (v.m_current_val)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_CTOR (color_property)\n  OCTAVE_DISABLE_COPY_MOVE_ASGN (color_property)\n\n  ~color_property () = default;\n\n  octave_value get () const\n  {\n    if (m_current_type == color_t)\n      return m_color_val.rgb ();\n\n    return m_current_val;\n  }\n\n  bool is_rgb () const { return (m_current_type == color_t); }\n\n  bool is_radio () const { return (m_current_type == radio_t); }\n\n  bool is (const std::string& v) const\n  { return (is_radio () && m_current_val == v); }\n\n  Matrix rgb () const\n  {\n    if (m_current_type != color_t)\n      error (\"color has no RGB value\");\n\n    return m_color_val.rgb ();\n  }\n\n  const std::string& current_value () const\n  {\n    if (m_current_type != radio_t)\n      error (\"color has no radio value\");\n\n    return m_current_val;\n  }\n\n  color_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  operator octave_value () const { return get (); }\n\n  base_property * clone () const { return new color_property (*this); }\n\n  std::string values_as_string () const\n  { return m_radio_val.values_as_string (); }\n\n  Cell values_as_cell () const { return m_radio_val.values_as_cell (); }\n\nprotected:\n  OCTINTERP_API bool do_set (const octave_value& newval);\n\nprivate:\n  enum current_enum { color_t, radio_t } m_current_type;\n  color_values m_color_val;\n  radio_values m_radio_val;\n  std::string m_current_val;\n};\n\n// ---------------------------------------------------------------------\n\nenum finite_type\n{\n  NO_CHECK,\n  FINITE,\n  NOT_NAN,\n  NOT_INF\n};\n\nclass OCTINTERP_API double_property : public base_property\n{\npublic:\n\n  double_property () = delete;\n\n  double_property (const std::string& nm, const graphics_handle& h,\n                   double d = 0)\n    : base_property (nm, h),\n      m_current_val (d), m_finite_constraint (NO_CHECK),\n      m_minval (std::pair<double, bool> (octave_NaN, true)),\n      m_maxval (std::pair<double, bool> (octave_NaN, true)) { }\n\n  double_property (const double_property& p)\n    : base_property (p), m_current_val (p.m_current_val),\n      m_finite_constraint (NO_CHECK),\n      m_minval (std::pair<double, bool> (octave_NaN, true)),\n      m_maxval (std::pair<double, bool> (octave_NaN, true)) { }\n\n  // FIXME: should we define assignment?\n  double_property& operator = (const double_property&) = delete;\n\n  ~double_property () = default;\n\n  octave_value get () const { return octave_value (m_current_val); }\n\n  double double_value () const { return m_current_val; }\n\n  double_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const\n  {\n    double_property *p = new double_property (*this);\n\n    p->m_finite_constraint = m_finite_constraint;\n    p->m_minval = m_minval;\n    p->m_maxval = m_maxval;\n\n    return p;\n  }\n\n  void add_constraint (const std::string& type, double val, bool inclusive)\n  {\n    if (type == \"min\")\n      m_minval = std::pair<double, bool> (val, inclusive);\n    else if (type == \"max\")\n      m_maxval = std::pair<double, bool> (val, inclusive);\n  }\n\n  void add_constraint (const finite_type finite)\n  { m_finite_constraint = finite; }\n\nprotected:\n  bool do_set (const octave_value& v)\n  {\n    if (! v.is_scalar_type () || ! v.isreal ())\n      error (R\"(set: invalid value for double property \"%s\")\",\n             get_name ().c_str ());\n\n    double new_val = v.double_value ();\n\n    // Check min and max\n    if (! octave::math::isnan (m_minval.first))\n      {\n        if (m_minval.second && m_minval.first > new_val)\n          error (R\"(set: \"%s\" must be greater than or equal to %g)\",\n                 get_name ().c_str (), m_minval.first);\n        else if (! m_minval.second && m_minval.first >= new_val)\n          error (R\"(set: \"%s\" must be greater than %g)\",\n                 get_name ().c_str (), m_minval.first);\n      }\n\n    if (! octave::math::isnan (m_maxval.first))\n      {\n        if (m_maxval.second && m_maxval.first < new_val)\n          error (R\"(set: \"%s\" must be less than or equal to %g)\",\n                 get_name ().c_str (), m_maxval.first);\n        else if (! m_maxval.second && m_maxval.first <= new_val)\n          error (R\"(set: \"%s\" must be less than %g)\",\n                 get_name ().c_str (), m_maxval.first);\n      }\n\n    if (m_finite_constraint == NO_CHECK) { /* do nothing */ }\n    else if (m_finite_constraint == FINITE)\n      {\n        if (! octave::math::isfinite (new_val))\n          error (R\"(set: \"%s\" must be finite)\", get_name ().c_str ());\n      }\n    else if (m_finite_constraint == NOT_NAN)\n      {\n        if (octave::math::isnan (new_val))\n          error (R\"(set: \"%s\" must not be NaN)\", get_name ().c_str ());\n      }\n    else if (m_finite_constraint == NOT_INF)\n      {\n        if (octave::math::isinf (new_val))\n          error (R\"(set: \"%s\" must not be infinite)\", get_name ().c_str ());\n      }\n\n    if (new_val != m_current_val)\n      {\n        m_current_val = new_val;\n        return true;\n      }\n\n    return false;\n  }\n\nprivate:\n  double m_current_val;\n  finite_type m_finite_constraint;\n  std::pair<double, bool> m_minval, m_maxval;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API double_radio_property : public base_property\n{\npublic:\n\n  double_radio_property () = delete;\n\n  double_radio_property (double d, const radio_values& v)\n    : base_property (\"\", graphics_handle ()),\n      m_current_type (double_t), m_dval (d), m_radio_val (v),\n      m_current_val (v.default_value ())\n  { }\n\n  double_radio_property (const std::string& nm, const graphics_handle& h,\n                         const std::string& v)\n    : base_property (nm, h),\n      m_current_type (radio_t), m_dval (0), m_radio_val (v),\n      m_current_val (m_radio_val.default_value ())\n  { }\n\n  double_radio_property (const std::string& nm, const graphics_handle& h,\n                         const double_radio_property& v)\n    : base_property (nm, h),\n      m_current_type (v.m_current_type), m_dval (v.m_dval),\n      m_radio_val (v.m_radio_val), m_current_val (v.m_current_val)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_CTOR (double_radio_property)\n  OCTAVE_DISABLE_COPY_MOVE_ASGN (double_radio_property)\n\n  ~double_radio_property () = default;\n\n  octave_value get () const\n  {\n    if (m_current_type == double_t)\n      return m_dval;\n\n    return m_current_val;\n  }\n\n  bool is_double () const { return (m_current_type == double_t); }\n\n  bool is_radio () const { return (m_current_type == radio_t); }\n\n  bool is (const std::string& v) const\n  { return (is_radio () && m_current_val == v); }\n\n  double double_value () const\n  {\n    if (m_current_type != double_t)\n      error (\"%s: property has no double\", get_name ().c_str ());\n\n    return m_dval;\n  }\n\n  const std::string& current_value () const\n  {\n    if (m_current_type != radio_t)\n      error (\"%s: property has no radio value\", get_name ().c_str ());\n\n    return m_current_val;\n  }\n\n  double_radio_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  operator octave_value () const { return get (); }\n\n  base_property * clone () const\n  { return new double_radio_property (*this); }\n\nprotected:\n  OCTINTERP_API bool do_set (const octave_value& v);\n\nprivate:\n  enum current_enum { double_t, radio_t } m_current_type;\n  double m_dval;\n  radio_values m_radio_val;\n  std::string m_current_val;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API array_property : public base_property\n{\npublic:\n  array_property ()\n    : base_property (\"\", graphics_handle ()), m_data (Matrix ()),\n      m_min_val (), m_max_val (), m_min_pos (), m_max_neg (),\n      m_type_constraints (), m_size_constraints (),\n      m_finite_constraint (NO_CHECK),\n      m_minval (std::pair<double, bool> (octave_NaN, true)),\n      m_maxval (std::pair<double, bool> (octave_NaN, true))\n  {\n    get_data_limits ();\n  }\n\n  array_property (const std::string& nm, const graphics_handle& h,\n                  const octave_value& m)\n    : base_property (nm, h), m_data (m.issparse () ? m.full_value () : m),\n      m_min_val (), m_max_val (), m_min_pos (), m_max_neg (),\n      m_type_constraints (), m_size_constraints (),\n      m_finite_constraint (NO_CHECK),\n      m_minval (std::pair<double, bool> (octave_NaN, true)),\n      m_maxval (std::pair<double, bool> (octave_NaN, true))\n  {\n    get_data_limits ();\n  }\n\n  // This copy constructor is only intended to be used\n  // internally to access min/max values; no need to\n  // copy constraints.\n  array_property (const array_property& p)\n    : base_property (p), m_data (p.m_data),\n      m_min_val (p.m_min_val), m_max_val (p.m_max_val),\n      m_min_pos (p.m_min_pos), m_max_neg (p.m_max_neg),\n      m_type_constraints (), m_size_constraints (),\n      m_finite_constraint (NO_CHECK),\n      m_minval (std::pair<double, bool> (octave_NaN, true)),\n      m_maxval (std::pair<double, bool> (octave_NaN, true))\n  { }\n\n  // FIXME: Should we define assignment?\n  array_property& operator = (const array_property&) = delete;\n\n  ~array_property () = default;\n\n  octave_value get () const { return m_data; }\n\n  void add_constraint (const std::string& type)\n  { m_type_constraints.insert (type); }\n\n  void add_constraint (const dim_vector& dims)\n  { m_size_constraints.push_back (dims); }\n\n  void add_constraint (const finite_type finite)\n  { m_finite_constraint = finite; }\n\n  void add_constraint (const std::string& type, double val, bool inclusive)\n  {\n    if (type == \"min\")\n      m_minval = std::pair<double, bool> (val, inclusive);\n    else if (type == \"max\")\n      m_maxval = std::pair<double, bool> (val, inclusive);\n  }\n\n  double min_val () const { return m_min_val; }\n  double max_val () const { return m_max_val; }\n  double min_pos () const { return m_min_pos; }\n  double max_neg () const { return m_max_neg; }\n\n  Matrix get_limits () const\n  {\n    Matrix m (1, 4);\n\n    m(0) = min_val ();\n    m(1) = max_val ();\n    m(2) = min_pos ();\n    m(3) = max_neg ();\n\n    return m;\n  }\n\n  array_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const\n  {\n    array_property *p = new array_property (*this);\n\n    p->m_type_constraints = m_type_constraints;\n    p->m_size_constraints = m_size_constraints;\n    p->m_finite_constraint = m_finite_constraint;\n    p->m_minval = m_minval;\n    p->m_maxval = m_maxval;\n\n    return p;\n  }\n\nprotected:\n  bool do_set (const octave_value& v)\n  {\n    octave_value tmp = (v.issparse () ? v.full_value () : v);\n\n    if (! validate (tmp))\n      error (R\"(invalid value for array property \"%s\")\",\n             get_name ().c_str ());\n\n    // FIXME: should we check for actual data change?\n    if (! is_equal (tmp))\n      {\n        m_data = tmp;\n\n        get_data_limits ();\n\n        return true;\n      }\n\n    return false;\n  }\n\nprivate:\n  OCTINTERP_API bool validate (const octave_value& v);\n\n  OCTINTERP_API bool is_equal (const octave_value& v) const;\n\n  OCTINTERP_API void get_data_limits ();\n\nprotected:\n  octave_value m_data;\n  double m_min_val;\n  double m_max_val;\n  double m_min_pos;\n  double m_max_neg;\n  std::set<std::string> m_type_constraints;\n  std::list<dim_vector> m_size_constraints;\n  finite_type m_finite_constraint;\n  std::pair<double, bool> m_minval, m_maxval;\n};\n\nclass OCTINTERP_API row_vector_property : public array_property\n{\npublic:\n\n  row_vector_property () = delete;\n\n  row_vector_property (const std::string& nm, const graphics_handle& h,\n                       const octave_value& m)\n    : array_property (nm, h, m)\n  {\n    add_constraint (dim_vector (-1, 1));\n    add_constraint (dim_vector (1, -1));\n    add_constraint (dim_vector (0, 0));\n  }\n\n  row_vector_property (const row_vector_property& p)\n    : array_property (p)\n  {\n    add_constraint (dim_vector (-1, 1));\n    add_constraint (dim_vector (1, -1));\n    add_constraint (dim_vector (0, 0));\n  }\n\n  // FIXME: should we define assignment?\n  row_vector_property& operator = (const row_vector_property&) = delete;\n\n  ~row_vector_property () = default;\n\n  void add_constraint (const std::string& type)\n  {\n    array_property::add_constraint (type);\n  }\n\n  void add_constraint (const dim_vector& dims)\n  {\n    array_property::add_constraint (dims);\n  }\n\n  void add_constraint (const finite_type finite)\n  {\n    array_property::add_constraint (finite);\n  }\n\n  void add_constraint (const std::string& type, double val, bool inclusive)\n  {\n    array_property::add_constraint (type, val, inclusive);\n  }\n\n  void add_constraint (octave_idx_type len)\n  {\n    m_size_constraints.remove (dim_vector (1, -1));\n    m_size_constraints.remove (dim_vector (-1, 1));\n    m_size_constraints.remove (dim_vector (0, 0));\n\n    add_constraint (dim_vector (1, len));\n    add_constraint (dim_vector (len, 1));\n  }\n\n  row_vector_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const\n  {\n    row_vector_property *p = new row_vector_property (*this);\n\n    p->m_type_constraints = m_type_constraints;\n    p->m_size_constraints = m_size_constraints;\n    p->m_finite_constraint = m_finite_constraint;\n    p->m_minval = m_minval;\n    p->m_maxval = m_maxval;\n\n    return p;\n  }\n\nprotected:\n  bool do_set (const octave_value& v)\n  {\n    bool retval = array_property::do_set (v);\n\n    dim_vector dv = m_data.dims ();\n\n    if (dv(0) > 1 && dv(1) == 1)\n      {\n        int tmp = dv(0);\n        dv(0) = dv(1);\n        dv(1) = tmp;\n\n        m_data = m_data.reshape (dv);\n      }\n\n    return retval;\n  }\n\nprivate:\n  OCTINTERP_API bool validate (const octave_value& v);\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API bool_property : public radio_property\n{\npublic:\n\n  bool_property () = delete;\n\n  bool_property (const std::string& nm, const graphics_handle& h,\n                 bool val)\n    : radio_property (nm, h, radio_values (val ? \"{on}|off\" : \"on|{off}\"))\n  { }\n\n  bool_property (const std::string& nm, const graphics_handle& h,\n                 const char *val)\n    : radio_property (nm, h, radio_values (std::string (val) == \"on\" ?\n                                           \"{on}|off\" : \"on|{off}\"), val)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_CTOR (bool_property)\n  OCTAVE_DISABLE_COPY_MOVE_ASGN (bool_property)\n\n  ~bool_property () = default;\n\n  bool is_on () const { return is (\"on\"); }\n\n  bool_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const { return new bool_property (*this); }\n\nprotected:\n  bool do_set (const octave_value& val)\n  {\n    if (val.is_bool_scalar ())\n      return radio_property::do_set (val.bool_value () ? \"on\" : \"off\");\n    else\n      return radio_property::do_set (val);\n  }\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API handle_property : public base_property\n{\npublic:\n\n  handle_property () = delete;\n\n  handle_property (const std::string& nm, const graphics_handle& h,\n                   const graphics_handle& val = graphics_handle ())\n    : base_property (nm, h),\n      m_current_val (val) { }\n\n  handle_property (const handle_property&) = default;\n\n  // FIXME: should we define assignment?\n  handle_property& operator = (const handle_property&) = delete;\n\n  ~handle_property () = default;\n\n  octave_value get () const { return m_current_val.as_octave_value (); }\n\n  graphics_handle handle_value () const { return m_current_val; }\n\n  handle_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  handle_property& operator = (const graphics_handle& h)\n  {\n    set (octave_value (h.value ()));\n    return *this;\n  }\n\n  void invalidate ()\n  { m_current_val = octave::numeric_limits<double>::NaN (); }\n\n  base_property * clone () const { return new handle_property (*this); }\n\n  void add_constraint (const std::string& type)\n  { m_type_constraints.insert (type); }\n\nprotected:\n  OCTINTERP_API bool do_set (const octave_value& v);\n  std::set<std::string> m_type_constraints;\n\nprivate:\n  graphics_handle m_current_val;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API any_property : public base_property\n{\npublic:\n\n  any_property () = delete;\n\n  any_property (const std::string& nm, const graphics_handle& h,\n                const octave_value& m = Matrix ())\n    : base_property (nm, h), m_data (m) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_CTOR (any_property)\n  OCTAVE_DISABLE_COPY_MOVE_ASGN (any_property)\n\n  ~any_property () = default;\n\n  octave_value get () const { return m_data; }\n\n  any_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const { return new any_property (*this); }\n\nprotected:\n  bool do_set (const octave_value& v)\n  {\n    m_data = v;\n    return true;\n  }\n\nprivate:\n  octave_value m_data;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API children_property : public base_property\n{\npublic:\n  children_property ()\n    : base_property (\"\", graphics_handle ()), m_children_list ()\n  {\n    do_init_children (Matrix ());\n  }\n\n  children_property (const std::string& nm, const graphics_handle& h,\n                     const Matrix& val)\n    : base_property (nm, h), m_children_list ()\n  {\n    do_init_children (val);\n  }\n\n  children_property (const children_property& p)\n    : base_property (p), m_children_list ()\n  {\n    do_init_children (p.m_children_list);\n  }\n\n  children_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  // FIXME: should we define assignment?\n  children_property& operator = (const children_property&) = delete;\n\n  ~children_property () = default;\n\n  base_property * clone () const { return new children_property (*this); }\n\n  bool remove_child (double val)\n  {\n    return do_remove_child (val);\n  }\n\n  void adopt (double val)\n  {\n    do_adopt_child (val);\n  }\n\n  Matrix get_children () const\n  {\n    return do_get_children (false);\n  }\n\n  Matrix get_hidden () const\n  {\n    return do_get_children (true);\n  }\n\n  Matrix get_all () const\n  {\n    return do_get_all_children ();\n  }\n\n  octave_value get () const\n  {\n    return octave_value (get_children ());\n  }\n\n  void delete_children (bool clear = false, bool from_root = false)\n  {\n    do_delete_children (clear, from_root);\n  }\n\n  void renumber (graphics_handle old_gh, graphics_handle new_gh)\n  {\n    for (auto& hchild : m_children_list)\n      {\n        if (hchild == old_gh)\n          {\n            hchild = new_gh.value ();\n            return;\n          }\n      }\n\n    error (\"children_list::renumber: child not found!\");\n  }\n\nprivate:\n  typedef std::list<double>::iterator children_list_iterator;\n  typedef std::list<double>::const_iterator const_children_list_iterator;\n  std::list<double> m_children_list;\n\nprotected:\n  bool do_set (const octave_value& val)\n  {\n    Matrix new_kids;\n\n    try\n      {\n        new_kids = val.matrix_value ();\n      }\n    catch (octave::execution_exception& ee)\n      {\n        error (ee, \"set: children must be an array of graphics handles\");\n      }\n\n    octave_idx_type nel = new_kids.numel ();\n\n    const Matrix new_kids_column = new_kids.reshape (dim_vector (nel, 1));\n\n    bool is_ok = true;\n    bool add_hidden = true;\n\n    const Matrix visible_kids = do_get_children (false);\n    const Matrix hidden_kids = do_get_children (true);\n\n    if (visible_kids.numel () == new_kids.numel ())\n      {\n        Matrix t1 = visible_kids.sort ();\n        Matrix t2 = new_kids_column.sort ();\n        Matrix t3 = hidden_kids.sort ();\n\n        if (t1 != t2)\n          is_ok = false;\n\n        if (t1 == t3)\n          add_hidden = false;\n      }\n    else\n      is_ok = false;\n\n    if (! is_ok)\n      error (\"set: new children list must be a permutation of existing \"\n             \"children with visible handles\");\n\n    m_children_list.clear ();\n\n    // Don't use do_init_children here, as that reverses the\n    // order of the list, and we don't want to do that if setting\n    // the child list directly.\n    for (octave_idx_type i = 0; i < new_kids_column.numel (); i++)\n      m_children_list.push_back (new_kids_column.xelem (i));\n\n    if (add_hidden)\n      for (octave_idx_type i = 0; i < hidden_kids.numel (); i++)\n        m_children_list.push_back (hidden_kids.xelem (i));\n\n    return true;\n  }\n\nprivate:\n  void do_init_children (const Matrix& val)\n  {\n    m_children_list.clear ();\n    for (octave_idx_type i = 0; i < val.numel (); i++)\n      m_children_list.push_front (val.xelem (i));\n  }\n\n  void do_init_children (const std::list<double>& val)\n  {\n    m_children_list.clear ();\n    m_children_list = val;\n  }\n\n  OCTINTERP_API Matrix do_get_children (bool return_hidden) const;\n\n  Matrix do_get_all_children () const\n  {\n    Matrix retval (m_children_list.size (), 1);\n    octave_idx_type i = 0;\n\n    for (const auto& hchild : m_children_list)\n      retval(i++) = hchild;\n\n    return retval;\n  }\n\n  bool do_remove_child (double child)\n  {\n    for (auto it = m_children_list.begin (); it != m_children_list.end (); it++)\n      {\n        if (*it == child)\n          {\n            m_children_list.erase (it);\n            return true;\n          }\n      }\n    return false;\n  }\n\n  void do_adopt_child (double val)\n  {\n    m_children_list.push_front (val);\n  }\n\n  void do_delete_children (bool clear, bool from_root);\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API callback_property : public base_property\n{\npublic:\n\n  callback_property () = delete;\n\n  callback_property (const std::string& nm, const graphics_handle& h,\n                     const octave_value& m)\n    : base_property (nm, h), m_callback (m) { }\n\n  callback_property (const callback_property&) = default;\n\n  // FIXME: should we define assignment?\n  callback_property& operator = (const callback_property&) = delete;\n\n  ~callback_property () = default;\n\n  octave_value get () const { return m_callback; }\n\n  OCTINTERP_API void execute (const octave_value& data = octave_value ()) const;\n\n  bool is_defined () const\n  {\n    return (m_callback.is_defined () && ! m_callback.isempty ());\n  }\n\n  callback_property& operator = (const octave_value& val)\n  {\n    set (val);\n    return *this;\n  }\n\n  base_property * clone () const { return new callback_property (*this); }\n\nprotected:\n  bool do_set (const octave_value& v)\n  {\n    if (! validate (v))\n      error (R\"(invalid value for callback property \"%s\")\",\n             get_name ().c_str ());\n\n    m_callback = v;\n    return true;\n    return false;\n  }\n\nprivate:\n  OCTINTERP_API bool validate (const octave_value& v) const;\n\nprivate:\n  octave_value m_callback;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API property\n{\npublic:\n  property () : m_rep (new base_property (\"\", graphics_handle ()))\n  { }\n\n  property (base_property *bp, bool persist = false) : m_rep (bp)\n  { if (persist) m_rep->m_count++; }\n\n  property (const property& p) : m_rep (p.m_rep)\n  {\n    m_rep->m_count++;\n  }\n\n  ~property ()\n  {\n    if (--m_rep->m_count == 0)\n      delete m_rep;\n  }\n\n  bool ok () const\n  { return m_rep->ok (); }\n\n  std::string get_name () const\n  { return m_rep->get_name (); }\n\n  void set_name (const std::string& name)\n  { m_rep->set_name (name); }\n\n  graphics_handle get_parent () const\n  { return m_rep->get_parent (); }\n\n  void set_parent (const graphics_handle& h)\n  { m_rep->set_parent (h); }\n\n  bool is_hidden () const\n  { return m_rep->is_hidden (); }\n\n  void set_hidden (bool flag)\n  { m_rep->set_hidden (flag); }\n\n  bool is_radio () const\n  { return m_rep->is_radio (); }\n\n  int get_id () const\n  { return m_rep->get_id (); }\n\n  void set_id (int d)\n  { m_rep->set_id (d); }\n\n  octave_value get () const\n  { return m_rep->get (); }\n\n  bool set (const octave_value& val, bool do_run = true,\n            bool do_notify_toolkit = true)\n  { return m_rep->set (val, do_run, do_notify_toolkit); }\n\n  std::string values_as_string () const\n  { return m_rep->values_as_string (); }\n\n  Cell values_as_cell () const\n  { return m_rep->values_as_cell (); }\n\n  property& operator = (const octave_value& val)\n  {\n    *m_rep = val;\n    return *this;\n  }\n\n  property& operator = (const property& p)\n  {\n    if (m_rep && --m_rep->m_count == 0)\n      delete m_rep;\n\n    m_rep = p.m_rep;\n    m_rep->m_count++;\n\n    return *this;\n  }\n\n  void add_listener (const octave_value& v, listener_mode mode = GCB_POSTSET)\n  { m_rep->add_listener (v, mode); }\n\n  void delete_listener (const octave_value& v = octave_value (),\n                        listener_mode mode = GCB_POSTSET)\n  { m_rep->delete_listener (v, mode); }\n\n  void run_listeners (listener_mode mode = GCB_POSTSET)\n  { m_rep->run_listeners (mode); }\n\n  static OCTINTERP_API property\n  create (const std::string& name, const graphics_handle& parent,\n          const caseless_str& type, const octave_value_list& args);\n\n  property clone () const\n  { return property (m_rep->clone ()); }\n\nprivate:\n  base_property *m_rep;\n};\n\n// ---------------------------------------------------------------------\n\ntypedef std::pair<std::string, octave_value> pval_pair;\n\nclass OCTINTERP_API pval_vector : public std::vector<pval_pair>\n{\npublic:\n  const_iterator find (const std::string pname) const\n  {\n    const_iterator it;\n\n    for (it = (*this).begin (); it != (*this).end (); it++)\n      if (pname == (*it).first)\n        return it;\n\n    return (*this).end ();\n  }\n\n  iterator find (const std::string pname)\n  {\n    iterator it;\n\n    for (it = (*this).begin (); it != (*this).end (); it++)\n      if (pname == (*it).first)\n        return it;\n\n    return (*this).end ();\n  }\n\n  octave_value lookup (const std::string pname) const\n  {\n    octave_value retval;\n\n    const_iterator it = find (pname);\n\n    if (it != (*this).end ())\n      retval = (*it).second;\n\n    return retval;\n  }\n\n  octave_value& operator [] (const std::string pname)\n  {\n    iterator it = find (pname);\n\n    if (it == (*this).end ())\n      {\n        push_back (pval_pair (pname, octave_value ()));\n        return (*this).back ().second;\n      }\n\n    return (*it).second;\n  }\n\n  void erase (const std::string pname)\n  {\n    iterator it = find (pname);\n    if (it != (*this).end ())\n      erase (it);\n  }\n\n  void erase (iterator it)\n  {\n    std::vector<pval_pair>::erase (it);\n  }\n\n};\n\nclass OCTINTERP_API property_list\n{\npublic:\n  typedef pval_vector pval_map_type;\n  typedef std::map<std::string, pval_map_type> plist_map_type;\n\n  typedef pval_map_type::iterator pval_map_iterator;\n  typedef pval_map_type::const_iterator pval_map_const_iterator;\n\n  typedef plist_map_type::iterator plist_map_iterator;\n  typedef plist_map_type::const_iterator plist_map_const_iterator;\n\n  property_list (const plist_map_type& m = plist_map_type ())\n    : m_plist_map (m) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (property_list)\n\n  OCTINTERP_API void set (const caseless_str& name, const octave_value& val);\n\n  OCTINTERP_API octave_value lookup (const caseless_str& name) const;\n\n  plist_map_iterator begin () { return m_plist_map.begin (); }\n  plist_map_const_iterator begin () const { return m_plist_map.begin (); }\n\n  plist_map_iterator end () { return m_plist_map.end (); }\n  plist_map_const_iterator end () const { return m_plist_map.end (); }\n\n  plist_map_iterator find (const std::string& go_name)\n  {\n    return m_plist_map.find (go_name);\n  }\n\n  plist_map_const_iterator find (const std::string& go_name) const\n  {\n    return m_plist_map.find (go_name);\n  }\n\n  OCTINTERP_API octave_scalar_map\n  as_struct (const std::string& prefix_arg) const;\n\nprivate:\n  plist_map_type m_plist_map;\n};\n\n// ---------------------------------------------------------------------\n\nclass base_graphics_object;\nclass graphics_object;\n\nclass OCTINTERP_API base_properties\n{\npublic:\n  base_properties (const std::string& ty = \"unknown\",\n                   const graphics_handle& mh = graphics_handle (),\n                   const graphics_handle& p = graphics_handle ());\n\n  OCTAVE_DISABLE_COPY_MOVE (base_properties)\n\n  virtual ~base_properties () = default;\n\n  virtual std::string graphics_object_name () const { return \"unknown\"; }\n\n  OCTINTERP_API void mark_modified ();\n\n  OCTINTERP_API void override_defaults (base_graphics_object& obj);\n\n  virtual void init_integerhandle (const octave_value&)\n  {\n    error (\"unexpected call to base_properties::init_integerhandle - please report this bug\");\n  }\n\n  // Look through DEFAULTS for properties with given CLASS_NAME, and\n  // apply them to the current object with set (virtual method).\n\n  OCTINTERP_API void\n  set_from_list (base_graphics_object& obj, property_list& defaults);\n\n  void insert_property (const std::string& name, property p)\n  {\n    p.set_name (name);\n    p.set_parent (m___myhandle__);\n    m_all_props[name] = p;\n  }\n\n  virtual void set (const caseless_str&, const octave_value&);\n\n  virtual octave_value get (const caseless_str& pname) const;\n\n  virtual octave_value get (const std::string& pname) const\n  {\n    return get (caseless_str (pname));\n  }\n\n  virtual octave_value get (const char *pname) const\n  {\n    return get (caseless_str (pname));\n  }\n\n  virtual octave_value get (bool all = false) const;\n\n  // FIXME: It seems like this function should be const, but that is\n  // currently not possible with the way that properties are stored as\n  // specific types in the graphics_object classes.\n  virtual property get_property (const caseless_str& pname);\n\n  virtual bool has_property (const caseless_str&) const\n  {\n    error (\"unexpected call to base_properties::has_property - please report this bug\");\n\n    return false;\n  }\n\n  bool is_modified () const { return is___modified__ (); }\n\n  virtual void remove_child (const graphics_handle& h, bool = false)\n  {\n    if (m_children.remove_child (h.value ()))\n      {\n        m_children.run_listeners ();\n        mark_modified ();\n      }\n  }\n\n  virtual void adopt (const graphics_handle& h)\n  {\n    m_children.adopt (h.value ());\n    m_children.run_listeners ();\n    mark_modified ();\n  }\n\n  virtual octave::graphics_toolkit get_toolkit () const;\n\n  virtual Matrix\n  get_boundingbox (bool /* finternal */ = false,\n                   const Matrix& /* parent_pix_size */ = Matrix ()) const\n  { return Matrix (1, 4, 0.0); }\n\n  virtual void update_boundingbox ();\n\n  virtual void update_autopos (const std::string& elem_type);\n\n  virtual void add_listener (const caseless_str&, const octave_value&,\n                             listener_mode = GCB_POSTSET);\n\n  virtual void delete_listener (const caseless_str&, const octave_value&,\n                                listener_mode = GCB_POSTSET);\n\n  void set_beingdeleted (const octave_value& val)\n  {\n    m_beingdeleted.set (val, true, false);\n    update_beingdeleted ();\n  }\n\n  void set_tag (const octave_value& val) { m_tag = val; }\n\n  OCTINTERP_API void set_parent (const octave_value& val);\n\n  Matrix get_children () const\n  {\n    return m_children.get_children ();\n  }\n\n  Matrix get_all_children () const\n  {\n    return m_children.get_all ();\n  }\n\n  Matrix get_hidden_children () const\n  {\n    return m_children.get_hidden ();\n  }\n\n  OCTINTERP_API void\n  get_children_of_type (const caseless_str& type, bool get_invisible,\n                        bool traverse,\n                        std::list<graphics_object>& children_list) const;\n\n  void set_modified (const octave_value& val) { set___modified__ (val); }\n\n  void set___modified__ (const octave_value& val) { m___modified__ = val; }\n\n  // Redirect calls to \"uicontextmenu\" to \"contextmenu\".\n\n  graphics_handle get_uicontextmenu () const\n  {\n    return get_contextmenu ();\n  }\n\n  void set_uicontextmenu (const octave_value& val)\n  {\n    set_contextmenu (val);\n  }\n\n  void reparent (const graphics_handle& new_parent) { m_parent = new_parent; }\n\n  // Update data limits for AXIS_TYPE (xdata, ydata, etc.) in the parent\n  // axes object.\n\n  virtual void update_axis_limits (const std::string& axis_type) const;\n\n  virtual void update_axis_limits (const std::string& axis_type,\n                                   const graphics_handle& h) const;\n\n  virtual void update_contextmenu () const;\n\n  virtual void delete_children (bool clear = false, bool from_root = false)\n  {\n    m_children.delete_children (clear, from_root);\n  }\n\n  void renumber_child (graphics_handle old_gh, graphics_handle new_gh)\n  {\n    m_children.renumber (old_gh, new_gh);\n  }\n\n  void renumber_parent (graphics_handle new_gh)\n  {\n    m_parent = new_gh;\n  }\n\n  static OCTINTERP_API property_list::pval_map_type factory_defaults ();\n\n  // FIXME: These functions should be generated automatically by the\n  //        genprops.awk script.\n  //\n  // EMIT_BASE_PROPERTIES_GET_FUNCTIONS\n\n  virtual octave_value get_alim () const { return octave_value (); }\n  virtual octave_value get_clim () const { return octave_value (); }\n  virtual octave_value get_xlim () const { return octave_value (); }\n  virtual octave_value get_ylim () const { return octave_value (); }\n  virtual octave_value get_zlim () const { return octave_value (); }\n\n  virtual bool is_aliminclude () const { return false; }\n  virtual bool is_climinclude () const { return false; }\n  virtual bool is_xliminclude () const { return false; }\n  virtual bool is_yliminclude () const { return false; }\n  virtual bool is_zliminclude () const { return false; }\n\n  OCTINTERP_API bool is_handle_visible () const;\n\n  OCTINTERP_API std::set<std::string> dynamic_property_names () const;\n\n  OCTINTERP_API bool has_dynamic_property (const std::string& pname) const;\n\nprotected:\n  std::set<std::string> m_dynamic_properties;\n\n  OCTINTERP_API void\n  set_dynamic (const caseless_str& pname, const octave_value& val);\n\n  OCTINTERP_API octave_value get_dynamic (const caseless_str& pname) const;\n\n  OCTINTERP_API octave_value get_dynamic (bool all = false) const;\n\n  OCTINTERP_API property get_property_dynamic (const caseless_str& pname) const;\n\n  BEGIN_BASE_PROPERTIES\n    // properties common to all objects\n    bool_property beingdeleted s , \"off\"\n    radio_property busyaction , \"{queue}|cancel\"\n    callback_property buttondownfcn , Matrix ()\n    children_property children gf , Matrix ()\n    bool_property clipping , \"on\"\n    handle_property contextmenu u , graphics_handle ()\n    callback_property createfcn , Matrix ()\n    callback_property deletefcn , Matrix ()\n    radio_property handlevisibility u , \"{on}|callback|off\"\n    bool_property hittest , \"on\"\n    bool_property interruptible , \"on\"\n    handle_property parent fs , p\n    radio_property pickableparts , \"{visible}|all|none\"\n    bool_property selected , \"off\"\n    bool_property selectionhighlight , \"on\"\n    string_property tag s , \"\"\n    string_property type frs , ty\n    handle_property uicontextmenu gsh , graphics_handle ()\n    any_property userdata , Matrix ()\n    bool_property visible u , \"on\"\n\n    // Octave-specific properties\n    any_property __appdata__ h , Matrix ()\n    bool_property __modified__ hs , \"on\"\n    graphics_handle __myhandle__ fhrs , mh\n  END_PROPERTIES\n\n  virtual void update_beingdeleted () { }\n\n  virtual void update_handlevisibility ();\n\n  virtual void update_visible () { }\n\nprotected:\n  struct cmp_caseless_str\n  {\n  public:\n    bool operator () (const caseless_str& a, const caseless_str& b) const\n    {\n      std::string a1 = a;\n      std::transform (a1.begin (), a1.end (), a1.begin (), tolower);\n      std::string b1 = b;\n      std::transform (b1.begin (), b1.end (), b1.begin (), tolower);\n\n      return a1 < b1;\n    }\n  };\n\n  std::map<caseless_str, property, cmp_caseless_str> m_all_props;\n\nprotected:\n\n  virtual void init ()\n  {\n    m_contextmenu.add_constraint (\"uicontextmenu\");\n  }\n};\n\nclass OCTINTERP_API base_graphics_object\n{\npublic:\n  friend class graphics_object;\n\n  base_graphics_object () : m_toolkit_flag (false) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (base_graphics_object)\n\n  virtual ~base_graphics_object () = default;\n\n  virtual void mark_modified ()\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::mark_modified: invalid graphics object\");\n\n    get_properties ().mark_modified ();\n  }\n\n  virtual void override_defaults (base_graphics_object& obj)\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::override_defaults: invalid graphics object\");\n    get_properties ().override_defaults (obj);\n  }\n\n  void build_user_defaults_map (property_list::pval_map_type& def,\n                                const std::string go_name) const;\n\n  virtual void set_from_list (property_list& plist)\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::set_from_list: invalid graphics object\");\n\n    get_properties ().set_from_list (*this, plist);\n  }\n\n  virtual void set (const caseless_str& pname, const octave_value& pval)\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::set: invalid graphics object\");\n\n    get_properties ().set (pname, pval);\n  }\n\n  virtual void set_defaults (const std::string&)\n  {\n    error (\"base_graphics_object::set_defaults: invalid graphics object\");\n  }\n\n  // The following version of the get method is not declared virtual\n  // because no derived class overrides it.\n\n  octave_value get (bool all = false) const\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::get: invalid graphics object\");\n\n    return get_properties ().get (all);\n  }\n\n  virtual octave_value get (const caseless_str& pname) const\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::get: invalid graphics object\");\n\n    return get_properties ().get (pname);\n  }\n\n  virtual octave_value get_default (const caseless_str&) const;\n\n  virtual octave_value get_factory_default (const caseless_str&) const;\n\n  virtual octave_value get_defaults () const\n  {\n    error (\"base_graphics_object::get_defaults: invalid graphics object\");\n  }\n\n  virtual property_list get_defaults_list () const\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::get_defaults_list: invalid graphics object\");\n\n    return property_list ();\n  }\n\n  virtual octave_value get_factory_defaults () const\n  {\n    error (\"base_graphics_object::get_factory_defaults: invalid graphics object\");\n  }\n\n  virtual property_list get_factory_defaults_list () const\n  {\n    error (\"base_graphics_object::get_factory_defaults_list: invalid graphics object\");\n  }\n\n  virtual bool has_readonly_property (const caseless_str& pname) const\n  {\n    return base_properties::has_readonly_property (pname);\n  }\n\n  // FIXME: It seems like this function should be const, but that is\n  // currently not possible.\n  virtual std::string values_as_string ();\n\n  // FIXME: It seems like this function should be const, but that is\n  // currently not possible.\n  virtual std::string value_as_string (const std::string& prop);\n\n  // FIXME: It seems like this function should be const, but that is\n  // currently not possible.\n  virtual octave_scalar_map values_as_struct ();\n\n  virtual graphics_handle get_parent () const\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::get_parent: invalid graphics object\");\n\n    return get_properties ().get_parent ();\n  }\n\n  graphics_handle get_handle () const\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::get_handle: invalid graphics object\");\n\n    return get_properties ().get___myhandle__ ();\n  }\n\n  virtual void remove_child (const graphics_handle& h, bool from_root = false)\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::remove_child: invalid graphics object\");\n\n    get_properties ().remove_child (h, from_root);\n  }\n\n  virtual void adopt (const graphics_handle& h)\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::adopt: invalid graphics object\");\n\n    get_properties ().adopt (h);\n  }\n\n  virtual void reparent (const graphics_handle& np)\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::reparent: invalid graphics object\");\n\n    get_properties ().reparent (np);\n  }\n\n  virtual void defaults () const\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::default: invalid graphics object\");\n\n    std::string msg = (type () + \"::defaults\");\n    err_not_implemented (msg.c_str ());\n  }\n\n  virtual base_properties& get_properties ()\n  {\n    static base_properties properties;\n    warning (\"base_graphics_object::get_properties: invalid graphics object\");\n    return properties;\n  }\n\n  virtual const base_properties& get_properties () const\n  {\n    static base_properties properties;\n    warning (\"base_graphics_object::get_properties: invalid graphics object\");\n    return properties;\n  }\n\n  virtual void update_axis_limits (const std::string& axis_type);\n\n  virtual void update_axis_limits (const std::string& axis_type,\n                                   const graphics_handle& h);\n\n  virtual bool valid_object () const { return false; }\n\n  bool valid_toolkit_object () const { return m_toolkit_flag; }\n\n  virtual std::string type () const\n  {\n    return (valid_object () ? get_properties ().graphics_object_name ()\n                            : \"unknown\");\n  }\n\n  bool isa (const std::string& go_name) const\n  {\n    return type () == go_name;\n  }\n\n  virtual octave::graphics_toolkit get_toolkit () const\n  {\n    if (! valid_object ())\n      error (\"base_graphics_object::get_toolkit: invalid graphics object\");\n\n    return get_properties ().get_toolkit ();\n  }\n\n  virtual void add_property_listener (const std::string& nm,\n                                      const octave_value& v,\n                                      listener_mode mode = GCB_POSTSET)\n  {\n    if (valid_object ())\n      get_properties ().add_listener (nm, v, mode);\n  }\n\n  virtual void delete_property_listener (const std::string& nm,\n                                         const octave_value& v,\n                                         listener_mode mode = GCB_POSTSET)\n  {\n    if (valid_object ())\n      get_properties ().delete_listener (nm, v, mode);\n  }\n\n  virtual void remove_all_listeners ();\n\n  virtual void reset_default_properties ();\n\nprotected:\n  virtual void initialize (const graphics_object& go)\n  {\n    if (! m_toolkit_flag)\n      m_toolkit_flag = get_toolkit ().initialize (go);\n  }\n\n  virtual void finalize (const graphics_object& go)\n  {\n    if (m_toolkit_flag)\n      {\n        get_toolkit ().finalize (go);\n        m_toolkit_flag = false;\n      }\n  }\n\n  virtual void update (const graphics_object& go, int id)\n  {\n    if (m_toolkit_flag)\n      get_toolkit ().update (go, id);\n  }\n\nprotected:\n\n  // A flag telling whether this object is a valid object\n  // in the backend context.\n  bool m_toolkit_flag;\n};\n\nclass OCTINTERP_API graphics_object\n{\npublic:\n\n  graphics_object () : m_rep (new base_graphics_object ()) { }\n\n  graphics_object (base_graphics_object *new_rep) : m_rep (new_rep) { }\n\n  graphics_object (const graphics_object&) = default;\n\n  graphics_object& operator = (const graphics_object&) = default;\n\n  ~graphics_object () = default;\n\n  void mark_modified () { m_rep->mark_modified (); }\n\n  void override_defaults (base_graphics_object& obj)\n  {\n    m_rep->override_defaults (obj);\n  }\n\n  void override_defaults ()\n  {\n    m_rep->override_defaults (*m_rep);\n  }\n\n  void build_user_defaults_map (property_list::pval_map_type& def,\n                                const std::string go_name) const\n  {\n    m_rep->build_user_defaults_map (def, go_name);\n  }\n\n  void set_from_list (property_list& plist) { m_rep->set_from_list (plist); }\n\n  void set (const caseless_str& name, const octave_value& val)\n  {\n    m_rep->set (name, val);\n  }\n\n  OCTINTERP_API void set (const octave_value_list& args);\n\n  OCTINTERP_API void set (const Array<std::string>& names, const Cell& values,\n                          octave_idx_type row);\n\n  OCTINTERP_API void set (const octave_map& m);\n\n  OCTINTERP_API void set_value_or_default (const caseless_str& name,\n                                           const octave_value& val);\n\n  void set_defaults (const std::string& mode) { m_rep->set_defaults (mode); }\n\n  octave_value get (bool all = false) const { return m_rep->get (all); }\n\n  octave_value get (const caseless_str& name) const\n  {\n    return name.compare (\"default\")\n           ? get_defaults ()\n           : (name.compare (\"factory\")\n              ? get_factory_defaults () : m_rep->get (name));\n  }\n\n  octave_value get (const std::string& name) const\n  {\n    return get (caseless_str (name));\n  }\n\n  octave_value get (const char *name) const\n  {\n    return get (caseless_str (name));\n  }\n\n  octave_value get_default (const caseless_str& name) const\n  {\n    return m_rep->get_default (name);\n  }\n\n  octave_value get_factory_default (const caseless_str& name) const\n  {\n    return m_rep->get_factory_default (name);\n  }\n\n  octave_value get_defaults () const { return m_rep->get_defaults (); }\n\n  property_list get_defaults_list () const\n  {\n    return m_rep->get_defaults_list ();\n  }\n\n  octave_value get_factory_defaults () const\n  {\n    return m_rep->get_factory_defaults ();\n  }\n\n  property_list get_factory_defaults_list () const\n  {\n    return m_rep->get_factory_defaults_list ();\n  }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    return m_rep->has_readonly_property (pname);\n  }\n\n  // FIXME: It seems like this function should be const, but that is\n  // currently not possible.\n  std::string values_as_string () { return m_rep->values_as_string (); }\n\n  // FIXME: It seems like this function should be const, but that is\n  // currently not possible.\n  std::string value_as_string (const std::string& prop)\n  {\n    return m_rep->value_as_string (prop);\n  }\n\n  // FIXME: It seems like this function should be const, but that is\n  // currently not possible.\n  octave_map values_as_struct () { return m_rep->values_as_struct (); }\n\n  graphics_handle get_parent () const { return m_rep->get_parent (); }\n\n  graphics_handle get_handle () const { return m_rep->get_handle (); }\n\n  OCTINTERP_API graphics_object get_ancestor (const std::string& type) const;\n\n  void remove_child (const graphics_handle& h) { m_rep->remove_child (h); }\n\n  void adopt (const graphics_handle& h) { m_rep->adopt (h); }\n\n  void reparent (const graphics_handle& h) { m_rep->reparent (h); }\n\n  void defaults () const { m_rep->defaults (); }\n\n  bool isa (const std::string& go_name) const { return m_rep->isa (go_name); }\n\n  base_properties& get_properties () { return m_rep->get_properties (); }\n\n  const base_properties& get_properties () const\n  {\n    return m_rep->get_properties ();\n  }\n\n  void update_axis_limits (const std::string& axis_type)\n  {\n    m_rep->update_axis_limits (axis_type);\n  }\n\n  void update_axis_limits (const std::string& axis_type,\n                           const graphics_handle& h)\n  {\n    m_rep->update_axis_limits (axis_type, h);\n  }\n\n  bool valid_object () const { return m_rep->valid_object (); }\n\n  std::string type () const { return m_rep->type (); }\n\n  operator bool () const { return m_rep->valid_object (); }\n\n  // FIXME: These functions should be generated automatically by the\n  //        genprops.awk script.\n  //\n  // EMIT_GRAPHICS_OBJECT_GET_FUNCTIONS\n\n  octave_value get_alim () const\n  { return get_properties ().get_alim (); }\n\n  octave_value get_clim () const\n  { return get_properties ().get_clim (); }\n\n  octave_value get_xlim () const\n  { return get_properties ().get_xlim (); }\n\n  octave_value get_ylim () const\n  { return get_properties ().get_ylim (); }\n\n  octave_value get_zlim () const\n  { return get_properties ().get_zlim (); }\n\n  bool is_aliminclude () const\n  { return get_properties ().is_aliminclude (); }\n\n  bool is_climinclude () const\n  { return get_properties ().is_climinclude (); }\n\n  bool is_xliminclude () const\n  { return get_properties ().is_xliminclude (); }\n\n  bool is_yliminclude () const\n  { return get_properties ().is_yliminclude (); }\n\n  bool is_zliminclude () const\n  { return get_properties ().is_zliminclude (); }\n\n  bool is_handle_visible () const\n  { return get_properties ().is_handle_visible (); }\n\n  octave::graphics_toolkit get_toolkit () const\n  { return m_rep->get_toolkit (); }\n\n  void add_property_listener (const std::string& nm, const octave_value& v,\n                              listener_mode mode = GCB_POSTSET)\n  { m_rep->add_property_listener (nm, v, mode); }\n\n  void delete_property_listener (const std::string& nm, const octave_value& v,\n                                 listener_mode mode = GCB_POSTSET)\n  { m_rep->delete_property_listener (nm, v, mode); }\n\n  void remove_all_listeners () { m_rep->remove_all_listeners (); }\n\n  void initialize () { m_rep->initialize (*this); }\n\n  void finalize () { m_rep->finalize (*this); }\n\n  void update (int id) { m_rep->update (*this, id); }\n\n  void reset_default_properties ()\n  { m_rep->reset_default_properties (); }\n\nprivate:\n\n  std::shared_ptr<base_graphics_object> m_rep;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API root_figure : public base_graphics_object\n{\npublic:\n\n  // The gh_manager constructor creates the single instance of\n  // the root_figure object.\n\n  friend class gh_manager;\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n    OCTINTERP_API void\n    remove_child (const graphics_handle& h, bool from_root = false);\n\n    OCTINTERP_API Matrix\n    get_boundingbox (bool internal = false,\n                     const Matrix& parent_pix_size = Matrix ()) const;\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n\n    // FIXME: Properties that still don't have callbacks are:\n    // monitorpositions, pointerlocation, pointerwindow.\n    // Note that these properties are not yet used by Octave, so setting\n    // them will have no effect.\n\n    // FIXME: The commandwindowsize property has been deprecated in Matlab\n    //        and is now available through matlab.desktop.comandwindow.size.\n    //        Until Octave has something similar, keep this property in root.\n\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (root_figure, root)\n      handle_property callbackobject Sr , graphics_handle ()\n      array_property commandwindowsize r , Matrix (1, 2, 0)\n      handle_property currentfigure S , graphics_handle ()\n      string_property fixedwidthfontname , \"Courier\"\n      array_property monitorpositions r , default_screensize ()\n      array_property pointerlocation , Matrix (1, 2, 0)\n      double_property pointerwindow r , 0.0\n      double_property screendepth r , default_screendepth ()\n      double_property screenpixelsperinch r , default_screenpixelsperinch ()\n      array_property screensize r , default_screensize ()\n      bool_property showhiddenhandles , \"off\"\n      radio_property units U , \"{pixels}|inches|centimeters|points|normalized|characters\"\n      // Hide base properties which don't make sense for root object\n      //radio_property beingdeleted h , \"{off}|on\"\n    END_PROPERTIES\n  };\n\nprivate:\n\n  properties m_properties;\n\nprotected:\n\n  root_figure ()\n    : m_properties (0, graphics_handle ()), m_default_properties (),\n      m_factory_properties (init_factory_properties ())\n  { }\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (root_figure)\n\n  ~root_figure () = default;\n\n  void mark_modified () { }\n\n  void override_defaults (base_graphics_object& obj)\n  {\n    // Now override with our defaults.  If the default_properties\n    // list includes the properties for all defaults (line,\n    // surface, etc.) then we don't have to know the type of OBJ\n    // here, we just call its set function and let it decide which\n    // properties from the list to use.\n    obj.set_from_list (m_default_properties);\n  }\n\n  void set (const caseless_str& name, const octave_value& value)\n  {\n    if (name.compare (\"default\", 7))\n      // strip \"default\", pass rest to function that will\n      // parse the remainder and add the element to the\n      // default_properties map.\n      m_default_properties.set (name.substr (7), value);\n    else\n      m_properties.set (name, value);\n  }\n\n  octave_value get (const caseless_str& name) const\n  {\n    octave_value retval;\n\n    if (name.compare (\"default\", 7))\n      return get_default (name.substr (7));\n    else if (name.compare (\"factory\", 7))\n      return get_factory_default (name.substr (7));\n    else\n      retval = m_properties.get (name);\n\n    return retval;\n  }\n\n  octave_value get_default (const caseless_str& name) const\n  {\n    octave_value retval = m_default_properties.lookup (name);\n\n    if (retval.is_undefined ())\n      {\n        // no default property found, use factory default\n        retval = m_factory_properties.lookup (name);\n\n        if (retval.is_undefined ())\n          error (\"get: invalid default property '%s'\", name.c_str ());\n      }\n\n    return retval;\n  }\n\n  octave_value get_factory_default (const caseless_str& name) const\n  {\n    octave_value retval = m_factory_properties.lookup (name);\n\n    if (retval.is_undefined ())\n      error (\"get: invalid factory default property '%s'\", name.c_str ());\n\n    return retval;\n  }\n\n  octave_value get_defaults () const\n  {\n    return m_default_properties.as_struct (\"default\");\n  }\n\n  property_list get_defaults_list () const\n  {\n    return m_default_properties;\n  }\n\n  octave_value get_factory_defaults () const\n  {\n    return m_factory_properties.as_struct (\"factory\");\n  }\n\n  property_list get_factory_defaults_list () const\n  {\n    return m_factory_properties;\n  }\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  OCTINTERP_API void reset_default_properties ();\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\nprivate:\n\n  property_list m_default_properties;\n\n  property_list m_factory_properties;\n\n  static OCTINTERP_API property_list::plist_map_type\n  init_factory_properties ();\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API figure : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n    void init_integerhandle (const octave_value& val)\n    {\n      m_integerhandle = val;\n    }\n\n    OCTINTERP_API void\n    remove_child (const graphics_handle& h, bool from_root = false);\n\n    OCTINTERP_API void set_visible (const octave_value& val);\n\n    OCTINTERP_API octave::graphics_toolkit get_toolkit () const;\n\n    OCTINTERP_API void set_toolkit (const octave::graphics_toolkit& b);\n\n    OCTINTERP_API void set___graphics_toolkit__ (const octave_value& val);\n\n    OCTINTERP_API void adopt (const graphics_handle& h);\n\n    // Alias \"innerposition\" to \"position\".\n    octave_value get_innerposition () const\n    {\n      return get_position ();\n    }\n\n    void set_innerposition (const octave_value& val)\n    {\n      set_position (val);\n    }\n\n    OCTINTERP_API void set_position (const octave_value& val,\n                                     bool do_notify_toolkit = true);\n\n    OCTINTERP_API void set_outerposition (const octave_value& val,\n                                          bool do_notify_toolkit = true);\n\n    OCTINTERP_API Matrix bbox2position (const Matrix& bbox) const;\n\n    OCTINTERP_API Matrix\n    get_boundingbox (bool internal = false,\n                     const Matrix& parent_pix_size = Matrix ()) const;\n\n    OCTINTERP_API void\n    set_boundingbox (const Matrix& bb, bool internal = false,\n                     bool do_notify_toolkit = true);\n\n    OCTINTERP_API Matrix map_from_boundingbox (double x, double y) const;\n\n    OCTINTERP_API Matrix map_to_boundingbox (double x, double y) const;\n\n    OCTINTERP_API void update_units (const caseless_str& old_units);\n\n    OCTINTERP_API void update_paperunits (const caseless_str& old_paperunits);\n\n    OCTINTERP_API std::string get_title () const;\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (figure)\n      array_property alphamap , Matrix (64, 1, 1)\n      callback_property buttondownfcn , Matrix ()\n      callback_property closerequestfcn , \"closereq\"\n      color_property color , color_property (color_values (1, 1, 1), radio_values (\"none\"))\n      array_property colormap , viridis_colormap ()\n      handle_property currentaxes S , graphics_handle ()\n      string_property currentcharacter r , \"\"\n      handle_property currentobject r , graphics_handle ()\n      array_property currentpoint r , Matrix (2, 1, 0)\n      bool_property dockcontrols , \"on\"\n      string_property filename , \"\"\n      bool_property graphicssmoothing , \"on\"\n      array_property innerposition sg , default_figure_position ()\n      bool_property integerhandle S , \"on\"\n      bool_property inverthardcopy , \"on\"\n      callback_property keypressfcn , Matrix ()\n      callback_property keyreleasefcn , Matrix ()\n      radio_property menubar , \"{figure}|none\"\n      string_property name , \"\"\n      array_property number rG , Matrix ()\n      radio_property nextplot , \"{add}|new|replace|replacechildren\"\n      bool_property numbertitle , \"on\"\n      array_property outerposition s , Matrix (1, 4, -1.0)\n      radio_property paperorientation U , \"{portrait}|landscape\"\n      array_property paperposition m , default_figure_paperposition ()\n      // FIXME: Matlab default is \"auto\", but this messes up hgsave BIST test.\n      radio_property paperpositionmode au , \"{auto}|manual\"\n      array_property papersize U , default_figure_papersize ()\n      radio_property papertype SU , \"{usletter}|uslegal|a0|a1|a2|a3|a4|a5|b0|b1|b2|b3|b4|b5|arch-a|arch-b|arch-c|arch-d|arch-e|a|b|c|d|e|tabloid|<custom>\"\n      radio_property paperunits Su , \"{inches}|centimeters|normalized|points\"\n      radio_property pointer , \"{arrow}|crosshair|ibeam|watch|topl|topr|botl|botr|left|top|right|bottom|circle|cross|fleur|custom|hand\"\n      array_property pointershapecdata , Matrix (16, 16, 1)\n      array_property pointershapehotspot , Matrix (1, 2, 1)\n      array_property position s , default_figure_position ()\n      radio_property renderer m , \"{opengl}|painters\"\n      radio_property renderermode , \"{auto}|manual\"\n      bool_property resize , \"on\"\n      // FIXME: \"resizefcn\" is no longer recommended by Matlab,\n      //        and has been replaced with \"sizechangedfcn\"\n      //        Eventually this will need to be hidden, and then removed.\n      callback_property resizefcn , Matrix ()\n      radio_property selectiontype , \"{normal}|extend|alt|open\"\n      callback_property sizechangedfcn , Matrix ()\n      radio_property toolbar , \"{auto}|figure|none\"\n      radio_property units Su , \"{pixels}|normalized|inches|centimeters|points|characters\"\n      callback_property windowbuttondownfcn , Matrix ()\n      callback_property windowbuttonmotionfcn , Matrix ()\n      callback_property windowbuttonupfcn , Matrix ()\n      callback_property windowkeypressfcn , Matrix ()\n      callback_property windowkeyreleasefcn , Matrix ()\n      callback_property windowscrollwheelfcn , Matrix ()\n      radio_property windowstate , \"{normal}|minimized|maximized|fullscreen\"\n      radio_property windowstyle , \"{normal}|modal|docked\"\n\n      // Overridden base property\n      // Property is not implemented for figures.\n      // Hide it and set it to a default value that works.\n      radio_property pickableparts h , \"{visible}\"\n\n      // Octave-specific properties\n      mutable string_property __gl_extensions__ hr , \"\"\n      mutable string_property __gl_renderer__ hr , \"\"\n      mutable string_property __gl_vendor__ hr , \"\"\n      mutable string_property __gl_version__ hr , \"\"\n      bool_property __gl_window__ h , \"off\"\n      string_property __graphics_toolkit__ hs , default_graphics_toolkit ()\n      any_property __guidata__ h , Matrix ()\n      radio_property __mouse_mode__ hS , \"{none}|pan|rotate|select|text|zoom\"\n      bool_property __printing__ h , \"off\"\n      any_property __pan_mode__ h , Matrix ()\n      any_property __plot_stream__ h , Matrix ()\n      any_property __rotate_mode__ h , Matrix ()\n      any_property __zoom_mode__ h , Matrix ()\n      double_property __device_pixel_ratio__ hU , 1.0\n\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_alphamap.add_constraint (dim_vector (-1, 1));\n      m_alphamap.add_constraint (dim_vector (1, -1));\n      m_colormap.add_constraint (dim_vector (-1, 3));\n      m_colormap.add_constraint (dim_vector (0, 0));\n      m_outerposition.add_constraint (dim_vector (1, 4));\n      m_outerposition.add_constraint (FINITE);\n      m_paperposition.add_constraint (dim_vector (1, 4));\n      m_paperposition.add_constraint (FINITE);\n      m_papersize.add_constraint (dim_vector (1, 2));\n      m_papersize.add_constraint (FINITE);\n      m_pointershapecdata.add_constraint (dim_vector (16, 16));\n      m_pointershapecdata.add_constraint (dim_vector (32, 32));\n      m_pointershapehotspot.add_constraint (dim_vector (1, 2));\n      m_position.add_constraint (dim_vector (1, 4));\n      m_position.add_constraint (FINITE);\n\n      init_toolkit ();\n    }\n\n  private:\n    OCTINTERP_API Matrix get_auto_paperposition ();\n\n    void update_paperpositionmode ()\n    {\n      if (m_paperpositionmode.is (\"auto\"))\n        m_paperposition.set (get_auto_paperposition ());\n    }\n\n    OCTINTERP_API void update_handlevisibility ();\n\n    OCTINTERP_API void init_toolkit ();\n\n    octave::graphics_toolkit m_toolkit;\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n\n  figure (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p), m_default_properties ()\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (figure)\n\n  ~figure () = default;\n\n  void override_defaults (base_graphics_object& obj)\n  {\n    // Allow parent (root object) to override first (properties knows how\n    // to find the parent object).\n    m_properties.override_defaults (obj);\n\n    // Now override with our defaults.  If the default_properties\n    // list includes the properties for all defaults (line,\n    // surface, etc.) then we don't have to know the type of OBJ\n    // here, we just call its set function and let it decide which\n    // properties from the list to use.\n    obj.set_from_list (m_default_properties);\n  }\n\n  void set (const caseless_str& name, const octave_value& value)\n  {\n    if (name.compare (\"default\", 7))\n      // strip \"default\", pass rest to function that will\n      // parse the remainder and add the element to the\n      // default_properties map.\n      m_default_properties.set (name.substr (7), value);\n    else\n      m_properties.set (name, value);\n  }\n\n  octave_value get (const caseless_str& name) const\n  {\n    octave_value retval;\n\n    if (name.compare (\"default\", 7))\n      retval = get_default (name.substr (7));\n    else\n      retval = m_properties.get (name);\n\n    return retval;\n  }\n\n  OCTINTERP_API octave_value get_default (const caseless_str& name) const;\n\n  octave_value get_defaults () const\n  {\n    return m_default_properties.as_struct (\"default\");\n  }\n\n  property_list get_defaults_list () const\n  {\n    return m_default_properties;\n  }\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  OCTINTERP_API void reset_default_properties ();\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\nprivate:\n  property_list m_default_properties;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API graphics_xform\n{\npublic:\n\n  graphics_xform ()\n    : m_xform (xform_eye ()), m_xform_inv (xform_eye ()),\n      m_sx (\"linear\"), m_sy (\"linear\"), m_sz (\"linear\"), m_zlim (1, 2, 0.0)\n  {\n    m_zlim(1) = 1.0;\n  }\n\n  graphics_xform (const Matrix& xm, const Matrix& xim,\n                  const scaler& x, const scaler& y, const scaler& z,\n                  const Matrix& zl)\n    : m_xform (xm), m_xform_inv (xim), m_sx (x), m_sy (y),\n      m_sz (z), m_zlim (zl)\n  { }\n\n  graphics_xform (const graphics_xform& g)\n    : m_xform (g.m_xform), m_xform_inv (g.m_xform_inv), m_sx (g.m_sx),\n      m_sy (g.m_sy), m_sz (g.m_sz), m_zlim (g.m_zlim) { }\n\n  ~graphics_xform () = default;\n\n  graphics_xform& operator = (const graphics_xform& g)\n  {\n    m_xform = g.m_xform;\n    m_xform_inv = g.m_xform_inv;\n    m_sx = g.m_sx;\n    m_sy = g.m_sy;\n    m_sz = g.m_sz;\n    m_zlim = g.m_zlim;\n\n    return *this;\n  }\n\n  static OCTINTERP_API ColumnVector xform_vector (double x, double y, double z);\n\n  static OCTINTERP_API Matrix xform_eye ();\n\n  OCTINTERP_API ColumnVector\n  transform (double x, double y, double z, bool use_scale = true) const;\n\n  OCTINTERP_API ColumnVector\n  untransform (double x, double y, double z, bool use_scale = true) const;\n\n  ColumnVector untransform (double x, double y, bool use_scale = true) const\n  { return untransform (x, y, (m_zlim(0)+m_zlim(1))/2, use_scale); }\n\n  Matrix xscale (const Matrix& m) const { return m_sx.scale (m); }\n  Matrix yscale (const Matrix& m) const { return m_sy.scale (m); }\n  Matrix zscale (const Matrix& m) const { return m_sz.scale (m); }\n\n  Matrix scale (const Matrix& m) const\n  {\n    bool has_z = (m.columns () > 2);\n\n    if (m_sx.is_linear () && m_sy.is_linear ()\n        && (! has_z || m_sz.is_linear ()))\n      return m;\n\n    Matrix retval (m.dims ());\n\n    int r = m.rows ();\n\n    for (int i = 0; i < r; i++)\n      {\n        retval(i, 0) = m_sx.scale (m(i, 0));\n        retval(i, 1) = m_sy.scale (m(i, 1));\n        if (has_z)\n          retval(i, 2) = m_sz.scale (m(i, 2));\n      }\n\n    return retval;\n  }\n\nprivate:\n  Matrix m_xform;\n  Matrix m_xform_inv;\n  scaler m_sx, m_sy, m_sz;\n  Matrix m_zlim;\n};\n\nenum\n{\n  AXE_ANY_DIR   = 0,\n  AXE_DEPTH_DIR = 1,\n  AXE_HORZ_DIR  = 2,\n  AXE_VERT_DIR  = 3\n};\n\nclass OCTINTERP_API axes : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    OCTINTERP_API void\n    set_defaults (base_graphics_object& obj, const std::string& mode);\n\n    OCTINTERP_API void\n    remove_child (const graphics_handle& h, bool from_root = false);\n\n    OCTINTERP_API void adopt (const graphics_handle& h);\n\n    const scaler& get_x_scaler () const { return m_sx; }\n    const scaler& get_y_scaler () const { return m_sy; }\n    const scaler& get_z_scaler () const { return m_sz; }\n\n    OCTINTERP_API Matrix\n    get_boundingbox (bool internal = false,\n                     const Matrix& parent_pix_size = Matrix ()) const;\n    OCTINTERP_API Matrix\n    get_extent (bool with_text = false,\n                bool only_text_height=false) const;\n\n    OCTINTERP_API double\n    get___fontsize_points__ (double box_pix_height = 0) const;\n\n    void update_boundingbox ()\n    {\n      if (units_is (\"normalized\"))\n        {\n          sync_positions ();\n          base_properties::update_boundingbox ();\n        }\n    }\n\n    OCTINTERP_API void update_camera ();\n    OCTINTERP_API void update_axes_layout ();\n    OCTINTERP_API void update_aspectratios ();\n    void update_transform ()\n    {\n      update_aspectratios ();\n      update_camera ();\n      update_axes_layout ();\n    }\n\n    OCTINTERP_API void sync_positions ();\n\n    // Redirect calls to \"activepositionproperty\" to \"positionconstraint\".\n\n    std::string get_activepositionproperty () const\n    {\n      std::string cur_val;\n\n      if (m_positionconstraint.is (\"innerposition\"))\n        cur_val = \"position\";\n      else\n        cur_val = \"outerposition\";\n\n      return cur_val;\n    }\n\n    void set_activepositionproperty (const octave_value& val)\n    {\n      // call set method to validate the input\n      m_activepositionproperty.set (val);\n\n      if (val.char_matrix_value ().row_as_string (0) == \"position\")\n        set_positionconstraint (\"innerposition\");\n      else\n        set_positionconstraint (val);\n    }\n\n    // Redirect calls to \"innerposition\" to \"position\".\n\n    octave_value get_innerposition () const\n    {\n      return get_position ();\n    }\n\n    void set_innerposition (const octave_value& val)\n    {\n      set_position (val);\n    }\n\n    OCTINTERP_API void update_autopos (const std::string& elem_type);\n    OCTINTERP_API void update_xlabel_position ();\n    OCTINTERP_API void update_ylabel_position ();\n    OCTINTERP_API void update_zlabel_position ();\n    OCTINTERP_API void update_title_position ();\n\n    graphics_xform get_transform () const\n    {\n      return graphics_xform (m_x_render, m_x_render_inv,\n                             m_sx, m_sy, m_sz, m_x_zlim);\n    }\n\n    Matrix get_transform_matrix () const { return m_x_render; }\n    Matrix get_inverse_transform_matrix () const { return m_x_render_inv; }\n    Matrix get_opengl_matrix_1 () const { return m_x_gl_mat1; }\n    Matrix get_opengl_matrix_2 () const { return m_x_gl_mat2; }\n    Matrix get_transform_zlim () const { return m_x_zlim; }\n\n    int get_xstate () const { return m_xstate; }\n    int get_ystate () const { return m_ystate; }\n    int get_zstate () const { return m_zstate; }\n    double get_xPlane () const { return m_xPlane; }\n    double get_xPlaneN () const { return m_xPlaneN; }\n    double get_yPlane () const { return m_yPlane; }\n    double get_yPlaneN () const { return m_yPlaneN; }\n    double get_zPlane () const { return m_zPlane; }\n    double get_zPlaneN () const { return m_zPlaneN; }\n    double get_xpTick () const { return m_xpTick; }\n    double get_xpTickN () const { return m_xpTickN; }\n    double get_ypTick () const { return m_ypTick; }\n    double get_ypTickN () const { return m_ypTickN; }\n    double get_zpTick () const { return m_zpTick; }\n    double get_zpTickN () const { return m_zpTickN; }\n    double get_x_min () const { return std::min (m_xPlane, m_xPlaneN); }\n    double get_x_max () const { return std::max (m_xPlane, m_xPlaneN); }\n    double get_y_min () const { return std::min (m_yPlane, m_yPlaneN); }\n    double get_y_max () const { return std::max (m_yPlane, m_yPlaneN); }\n    double get_z_min () const { return std::min (m_zPlane, m_zPlaneN); }\n    double get_z_max () const { return std::max (m_zPlane, m_zPlaneN); }\n    double get_fx () const { return m_fx; }\n    double get_fy () const { return m_fy; }\n    double get_fz () const { return m_fz; }\n    double get_xticklen () const { return m_xticklen; }\n    double get_yticklen () const { return m_yticklen; }\n    double get_zticklen () const { return m_zticklen; }\n    double get_xtickoffset () const { return m_xtickoffset; }\n    double get_ytickoffset () const { return m_ytickoffset; }\n    double get_ztickoffset () const { return m_ztickoffset; }\n    bool get_x2Dtop () const { return m_x2Dtop; }\n    bool get_y2Dright () const { return m_y2Dright; }\n    bool get_layer2Dtop () const { return m_layer2Dtop; }\n    bool get_is2D (bool include_kids = false) const\n    { return (include_kids ? (m_is2D && ! m_has3Dkids) : m_is2D); }\n    void set_has3Dkids (bool val) { m_has3Dkids = val; }\n    bool get_xySym () const { return m_xySym; }\n    bool get_xyzSym () const { return m_xyzSym; }\n    bool get_zSign () const { return m_zSign; }\n    bool get_nearhoriz () const { return m_nearhoriz; }\n\n    ColumnVector pixel2coord (double px, double py) const\n    {\n      return get_transform ().untransform (px, py,\n                                           (m_x_zlim(0)+m_x_zlim(1))/2);\n    }\n\n    ColumnVector coord2pixel (double x, double y, double z) const\n    { return get_transform ().transform (x, y, z); }\n\n    OCTINTERP_API void\n    zoom_about_point (const std::string& mode, double x, double y,\n                      double factor, bool push_to_zoom_stack = true);\n    OCTINTERP_API void\n    zoom (const std::string& mode, double factor,\n          bool push_to_zoom_stack = true);\n    OCTINTERP_API void\n    zoom (const std::string& mode, const Matrix& xl, const Matrix& yl,\n          bool push_to_zoom_stack = true);\n\n    OCTINTERP_API void\n    translate_view (const std::string& mode,\n                    double x0, double x1, double y0, double y1,\n                    bool push_to_zoom_stack = true);\n\n    OCTINTERP_API void\n    pan (const std::string& mode, double factor,\n         bool push_to_zoom_stack = true);\n\n    OCTINTERP_API void\n    rotate3d (double x0, double x1, double y0, double y1,\n              bool push_to_zoom_stack = true);\n\n    OCTINTERP_API void\n    rotate_view (double delta_az, double delta_el,\n                 bool push_to_zoom_stack = true);\n\n    OCTINTERP_API void unzoom ();\n    OCTINTERP_API void update_handlevisibility ();\n    OCTINTERP_API void push_zoom_stack ();\n    OCTINTERP_API void clear_zoom_stack (bool do_unzoom = true);\n\n    OCTINTERP_API void update_units (const caseless_str& old_units);\n\n    OCTINTERP_API void update_font (std::string prop = \"\");\n\n    OCTINTERP_API void update_fontunits (const caseless_str& old_fontunits);\n\n    void increase_num_lights () { m_num_lights++; }\n    void decrease_num_lights () { m_num_lights--; }\n    unsigned int get_num_lights () const { return m_num_lights; }\n\n  private:\n\n    scaler m_sx = scaler ();\n    scaler m_sy = scaler ();\n    scaler m_sz = scaler ();\n\n    Matrix m_x_render = Matrix ();\n    Matrix m_x_render_inv = Matrix ();\n    Matrix m_x_gl_mat1 = Matrix ();\n    Matrix m_x_gl_mat2 = Matrix ();\n    Matrix m_x_zlim = Matrix ();\n\n    std::list<octave_value> m_zoom_stack = std::list<octave_value> ();\n\n    // Axes layout data\n    int m_xstate = 0;\n    int m_ystate = 0;\n    int m_zstate = 0;\n\n    double m_xPlane = 0.0;\n    double m_yPlane = 0.0;\n    double m_zPlane = 0.0;\n\n    double m_xPlaneN = 0.0;\n    double m_yPlaneN = 0.0;\n    double m_zPlaneN = 0.0;\n\n    double m_xpTick = 0.0;\n    double m_ypTick = 0.0;\n    double m_zpTick = 0.0;\n\n    double m_xpTickN = 0.0;\n    double m_ypTickN = 0.0;\n    double m_zpTickN = 0.0;\n\n    double m_fx = 0.0;\n    double m_fy = 0.0;\n    double m_fz = 0.0;\n\n    double m_xticklen = 0.0;\n    double m_yticklen = 0.0;\n    double m_zticklen = 0.0;\n\n    double m_xtickoffset = 0.0;\n    double m_ytickoffset = 0.0;\n    double m_ztickoffset = 0.0;\n\n    bool m_x2Dtop = false;\n    bool m_y2Dright = false;\n    bool m_layer2Dtop = false;\n    bool m_is2D = false;\n    bool m_has3Dkids = false;\n    bool m_xySym = false;\n    bool m_xyzSym = false;\n    bool m_zSign = false;\n    bool m_nearhoriz = false;\n\n    unsigned int m_num_lights = 0;\n\n    // Text renderer, used for calculation of text (tick labels) size\n    octave::text_renderer m_txt_renderer;\n\n    OCTINTERP_API void\n    set_text_child (handle_property& h, const std::string& who,\n                    const octave_value& v);\n\n    OCTINTERP_API void\n    delete_text_child (handle_property& h, bool from_root = false);\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (axes)\n      radio_property activepositionproperty gsh , \"{outerposition}|position\"\n      row_vector_property alim m , default_lim ()\n      radio_property alimmode , \"{auto}|manual\"\n      // FIXME: not yet implemented\n      array_property alphamap , Matrix ()\n      radio_property alphascale , \"{linear}|log\"\n      color_property ambientlightcolor , color_values (1, 1, 1)\n      bool_property box u , \"off\"\n      radio_property boxstyle , \"{back}|full\"\n      row_vector_property cameraposition mu , Matrix (1, 3, 0.0)\n      radio_property camerapositionmode u , \"{auto}|manual\"\n      row_vector_property cameratarget mu , Matrix (1, 3, 0.0)\n      radio_property cameratargetmode u , \"{auto}|manual\"\n      row_vector_property cameraupvector mu , Matrix (1, 3, 0.0)\n      radio_property cameraupvectormode u , \"{auto}|manual\"\n      double_property cameraviewangle mu , 6.6086\n      radio_property cameraviewanglemode u , \"{auto}|manual\"\n      row_vector_property clim m , default_lim ()\n      radio_property climmode al , \"{auto}|manual\"\n      radio_property clippingstyle , \"{3dbox}|rectangle\"\n      color_property color , color_property (color_values (1, 1, 1), radio_values (\"none\"))\n      array_property colormap sg , Matrix ()\n      array_property colororder , default_colororder ()\n      double_property colororderindex , 1.0\n      radio_property colorscale , \"{linear}|log\"\n      array_property currentpoint , Matrix (2, 3, 0.0)\n      row_vector_property dataaspectratio mu , Matrix (1, 3, 1.0)\n      radio_property dataaspectratiomode u , \"{auto}|manual\"\n      radio_property fontangle u , \"{normal}|italic\"\n      string_property fontname u , OCTAVE_DEFAULT_FONTNAME\n      double_property fontsize mu , 10\n      // FIXME: not yet implemented\n      radio_property fontsizemode , \"{auto}|manual\"\n      bool_property fontsmoothing u , \"on\"\n      radio_property fontunits SU , \"{points}|inches|centimeters|normalized|pixels\"\n      radio_property fontweight u , \"{normal}|bold\"\n      double_property gridalpha m , 0.15\n      radio_property gridalphamode , \"{auto}|manual\"\n      color_property gridcolor m , color_property (color_values (0.15, 0.15, 0.15), radio_values (\"none\"))\n      radio_property gridcolormode , \"{auto}|manual\"\n      radio_property gridlinestyle , \"{-}|--|:|-.|none\"\n      array_property innerposition sg , default_axes_position ()\n      // FIXME: Should be an array of \"interaction objects\".\n      // Make it read-only for now.\n      any_property interactions r , Matrix ()\n      double_property labelfontsizemultiplier u , 1.1\n      radio_property layer u , \"{bottom}|top\"\n      // FIXME: Should be a \"layoutoptions\" object.  Make it read-only for now.\n      handle_property layout r , graphics_handle ()\n      // FIXME: Should be a \"legend\" object.  Make it read-only for now.\n      handle_property legend r , graphics_handle ()\n      // FIXME: should be kind of string array.\n      any_property linestyleorder S , \"-\"\n      double_property linestyleorderindex , 1.0\n      double_property linewidth , 0.5\n      double_property minorgridalpha m , 0.25\n      radio_property minorgridalphamode , \"{auto}|manual\"\n      color_property minorgridcolor m , color_property (color_values (0.1, 0.1, 0.1), radio_values (\"none\"))\n      radio_property minorgridcolormode , \"{auto}|manual\"\n      radio_property minorgridlinestyle , \"{:}|-|--|-.|none\"\n      radio_property nextplot , \"{replace}|add|replacechildren\"\n      double_property nextseriesindex r , 1.0\n      array_property outerposition u , default_axes_outerposition ()\n      row_vector_property plotboxaspectratio mu , Matrix (1, 3, 1.0)\n      radio_property plotboxaspectratiomode u , \"{auto}|manual\"\n      array_property position u , default_axes_position ()\n      radio_property positionconstraint , \"{outerposition}|innerposition\"\n      radio_property projection , \"{orthographic}|perspective\"\n      radio_property sortmethod , \"{depth}|childorder\"\n      radio_property tickdir mu , \"{in}|out|both|none\"\n      radio_property tickdirmode u , \"{auto}|manual\"\n      // FIXME: Added recently to Matlab, should replace interpreter property.\n      radio_property ticklabelinterpreter u , \"{tex}|latex|none\"\n      array_property ticklength u , default_axes_ticklength ()\n      array_property tightinset r , Matrix (1, 4, 0.0)\n      handle_property title SOf , make_graphics_handle (\"text\", m___myhandle__, false, false, false)\n      double_property titlefontsizemultiplier u , 1.1\n      radio_property titlefontweight u , \"{bold}|normal\"\n      // FIXME: Should be a \"axestoolbar\" object.  Make it read-only for now.\n      handle_property toolbar r , graphics_handle ()\n      radio_property units SU , \"{normalized}|inches|centimeters|points|pixels|characters\"\n      array_property view u , default_axes_view ()\n      // FIXME: Should be a \"ruler\" object.  Make it read-only for now.\n      handle_property xaxis r , graphics_handle ()\n      radio_property xaxislocation u , \"{bottom}|top|origin\"\n      color_property xcolor mu , color_property (color_values (0.15, 0.15, 0.15), radio_values (\"none\"))\n      radio_property xcolormode , \"{auto}|manual\"\n      radio_property xdir u , \"{normal}|reverse\"\n      bool_property xgrid , \"off\"\n      handle_property xlabel SOf , make_graphics_handle (\"text\", m___myhandle__, false, false, false)\n      row_vector_property xlim mu , default_lim ()\n      radio_property xlimitmethod u , \"{tickaligned}|tight|padded\"\n      radio_property xlimmode al , \"{auto}|manual\"\n      bool_property xminorgrid , \"off\"\n      bool_property xminortick , \"off\"\n      row_vector_property xminortickvalues m , Matrix ()\n      radio_property xminortickvaluesmode u , \"{auto}|manual\"\n      radio_property xscale alu , \"{linear}|log\"\n      row_vector_property xtick mu , default_axes_tick ()\n      // FIXME: should be kind of string array.\n      any_property xticklabel S , \"\"\n      radio_property xticklabelmode u , \"{auto}|manual\"\n      double_property xticklabelrotation , 0.0\n      radio_property xtickmode u , \"{auto}|manual\"\n      // FIXME: Should be a \"ruler\" object.  Make it read-only for now.\n      handle_property yaxis r , graphics_handle ()\n      radio_property yaxislocation u , \"{left}|right|origin\"\n      color_property ycolor mu , color_property (color_values (0.15, 0.15, 0.15), radio_values (\"none\"))\n      radio_property ycolormode , \"{auto}|manual\"\n      radio_property ydir u , \"{normal}|reverse\"\n      bool_property ygrid , \"off\"\n      handle_property ylabel SOf , make_graphics_handle (\"text\", m___myhandle__, false, false, false)\n      row_vector_property ylim mu , default_lim ()\n      radio_property ylimitmethod u , \"{tickaligned}|tight|padded\"\n      radio_property ylimmode al , \"{auto}|manual\"\n      bool_property yminorgrid , \"off\"\n      bool_property yminortick , \"off\"\n      row_vector_property yminortickvalues m , Matrix ()\n      radio_property yminortickvaluesmode u , \"{auto}|manual\"\n      radio_property yscale alu , \"{linear}|log\"\n      row_vector_property ytick mu , default_axes_tick ()\n      any_property yticklabel S , \"\"\n      radio_property yticklabelmode u , \"{auto}|manual\"\n      double_property yticklabelrotation , 0.0\n      radio_property ytickmode u , \"{auto}|manual\"\n      // FIXME: Should be a \"ruler\" object.  Make it read-only for now.\n      handle_property zaxis r , graphics_handle ()\n      color_property zcolor mu , color_property (color_values (0.15, 0.15, 0.15), radio_values (\"none\"))\n      radio_property zcolormode , \"{auto}|manual\"\n      radio_property zdir u , \"{normal}|reverse\"\n      bool_property zgrid , \"off\"\n      handle_property zlabel SOf , make_graphics_handle (\"text\", m___myhandle__, false, false, false)\n      row_vector_property zlim mu , default_lim ()\n      radio_property zlimitmethod u , \"{tickaligned}|tight|padded\"\n      radio_property zlimmode al , \"{auto}|manual\"\n      bool_property zminorgrid , \"off\"\n      bool_property zminortick , \"off\"\n      row_vector_property zminortickvalues m , Matrix ()\n      radio_property zminortickvaluesmode u , \"{auto}|manual\"\n      radio_property zscale alu , \"{linear}|log\"\n      row_vector_property ztick mu , default_axes_tick ()\n      any_property zticklabel S , \"\"\n      radio_property zticklabelmode u , \"{auto}|manual\"\n      double_property zticklabelrotation , 0.0\n      radio_property ztickmode u , \"{auto}|manual\"\n\n      // Octave-specific properties\n      array_property __colormap__ hu , Matrix ()\n      double_property mousewheelzoom , 0.5\n\n      // hidden properties for alignment of subplots\n      radio_property __autopos_tag__ h , \"{none}|subplot\"\n      // hidden properties for inset\n      array_property looseinset hu , Matrix (1, 4, 0.0)\n      // hidden property for text rendering\n      double_property __fontsize_points__ hgr , 0\n   END_PROPERTIES\n\n  protected:\n    OCTINTERP_API void init ();\n\n  private:\n\n    std::string\n    get_scale (const std::string& scale, const Matrix& lims)\n    {\n      std::string retval = scale;\n\n      if (scale == \"log\" && lims.numel () > 1 && lims(0) < 0 && lims(1) < 0)\n        retval = \"neglog\";\n\n      return retval;\n    }\n\n    void update_xscale ()\n    {\n      m_sx = get_scale (get_xscale (), m_xlim.get ().matrix_value ());\n    }\n\n    void update_yscale ()\n    {\n      m_sy = get_scale (get_yscale (), m_ylim.get ().matrix_value ());\n    }\n\n    void update_zscale ()\n    {\n      m_sz = get_scale (get_zscale (), m_zlim.get ().matrix_value ());\n    }\n\n    OCTINTERP_API void\n    update_label_color (handle_property label, color_property col);\n    void update_xcolor ()\n    { update_label_color (m_xlabel, m_xcolor); }\n\n    void update_ycolor ()\n    { update_label_color (m_ylabel, m_ycolor); }\n\n    void update_zcolor ()\n    { update_label_color (m_zlabel, m_zcolor); }\n\n    void update_view () { sync_positions (); }\n    \n    void update_visible ();\n\n    void update_cameraposition () { update_transform (); }\n    void update_cameratarget () { update_transform (); }\n    void update_cameraupvector () { update_transform (); }\n    void update_cameraviewangle () { update_transform (); }\n\n    void update_camerapositionmode ()\n    {\n      if (camerapositionmode_is (\"auto\"))\n        update_cameraposition ();\n    }\n    void update_cameratargetmode ()\n    {\n      if (cameratargetmode_is (\"auto\"))\n        update_cameratarget ();\n    }\n    void update_cameraupvectormode ()\n    {\n      if (cameraupvectormode_is (\"auto\"))\n        update_cameraupvector ();\n    }\n    void update_cameraviewanglemode ()\n    {\n      if (cameraviewanglemode_is (\"auto\"))\n        update_cameraviewangle ();\n    }\n\n    void update_dataaspectratio () { sync_positions (); }\n    void update_dataaspectratiomode () { sync_positions (); }\n    void update_plotboxaspectratio () { sync_positions (); }\n    void update_plotboxaspectratiomode () { sync_positions (); }\n\n    void update_layer () { update_axes_layout (); }\n    void update_box ()\n    {\n      if (m_xticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is (\"log\"),\n                         xaxislocation_is (\"origin\"),\n                         m_yscale.is (\"log\") ? 2 :\n                           (yaxislocation_is (\"origin\") ? 0 :\n                             (yaxislocation_is (\"left\") ? -1 : 1)),\n                         m_xlim);\n      if (m_yticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_ytick, m_yticklabel, m_yscale.is (\"log\"),\n                         yaxislocation_is (\"origin\"),\n                         m_xscale.is (\"log\") ? 2 :\n                           (xaxislocation_is (\"origin\") ? 0 :\n                             (xaxislocation_is (\"bottom\") ? -1 : 1)),\n                         m_ylim);\n    }\n    void update_yaxislocation ()\n    {\n      sync_positions ();\n      update_axes_layout ();\n      if (m_xticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is (\"log\"),\n                         xaxislocation_is (\"origin\"),\n                         m_yscale.is (\"log\") ? 2 :\n                           (yaxislocation_is (\"origin\") ? 0 :\n                             (yaxislocation_is (\"left\") ? -1 : 1)),\n                         m_xlim);\n      if (m_yticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_ytick, m_yticklabel, m_yscale.is (\"log\"),\n                         yaxislocation_is (\"origin\"),\n                         m_xscale.is (\"log\") ? 2 :\n                           (xaxislocation_is (\"origin\") ? 0 :\n                             (xaxislocation_is (\"bottom\") ? -1 : 1)),\n                         m_ylim);\n      update_ylabel_position ();\n    }\n    void update_xaxislocation ()\n    {\n      sync_positions ();\n      update_axes_layout ();\n      if (m_xticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is (\"log\"),\n                         xaxislocation_is (\"origin\"),\n                         m_yscale.is (\"log\") ? 2 :\n                           (yaxislocation_is (\"origin\") ? 0 :\n                             (yaxislocation_is (\"left\") ? -1 : 1)),\n                         m_xlim);\n      if (m_yticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_ytick, m_yticklabel, m_yscale.is (\"log\"),\n                         yaxislocation_is (\"origin\"),\n                         m_xscale.is (\"log\") ? 2 :\n                           (xaxislocation_is (\"origin\") ? 0 :\n                             (xaxislocation_is (\"bottom\") ? -1 : 1)),\n                         m_ylim);\n      update_xlabel_position ();\n    }\n\n    void update_xdir () { update_camera (); update_axes_layout (); }\n    void update_ydir () { update_camera (); update_axes_layout (); }\n    void update_zdir () { update_camera (); update_axes_layout (); }\n\n    void update_ticklength ();\n    void update_tickdir () { update_ticklength (); }\n    void update_tickdirmode () { update_ticklength (); }\n\n    void update_ticklabelinterpreter ()\n    {\n      update_xtick (false);\n      update_ytick (false);\n      update_ztick (true);\n    }\n\n    void update_xtick (bool sync_pos = true)\n    {\n      calc_ticks_and_lims (m_xlim, m_xtick, m_xminortickvalues,\n                           m_xlimmode.is (\"auto\"), m_xtickmode.is (\"auto\"),\n                           m_xminortickvaluesmode.is (\"auto\"),\n                           m_xscale.is (\"log\"), m_xlimitmethod.is (\"padded\"),\n                           m_xlimitmethod.is (\"tight\"));\n      if (m_xticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is (\"log\"),\n                         xaxislocation_is (\"origin\"),\n                         m_yscale.is (\"log\") ? 2 :\n                           (yaxislocation_is (\"origin\") ? 0 :\n                             (yaxislocation_is (\"left\") ? -1 : 1)),\n                         m_xlim);\n\n      if (sync_pos)\n        sync_positions ();\n    }\n    void update_ytick (bool sync_pos = true)\n    {\n      calc_ticks_and_lims (m_ylim, m_ytick, m_yminortickvalues,\n                           m_ylimmode.is (\"auto\"), m_ytickmode.is (\"auto\"),\n                           m_yminortickvaluesmode.is (\"auto\"),\n                           m_yscale.is (\"log\"), m_ylimitmethod.is (\"padded\"),\n                           m_ylimitmethod.is (\"tight\"));\n      if (m_yticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_ytick, m_yticklabel, m_yscale.is (\"log\"),\n                         yaxislocation_is (\"origin\"),\n                         m_xscale.is (\"log\") ? 2 :\n                           (xaxislocation_is (\"origin\") ? 0 :\n                             (xaxislocation_is (\"bottom\") ? -1 : 1)),\n                         m_ylim);\n\n      if (sync_pos)\n        sync_positions ();\n    }\n    void update_ztick (bool sync_pos = true)\n    {\n      calc_ticks_and_lims (m_zlim, m_ztick, m_zminortickvalues,\n                           m_zlimmode.is (\"auto\"), m_ztickmode.is (\"auto\"),\n                           m_zminortickvaluesmode.is (\"auto\"),\n                           m_zscale.is (\"log\"), m_zlimitmethod.is (\"padded\"),\n                           m_zlimitmethod.is (\"tight\"));\n      if (m_zticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_ztick, m_zticklabel, m_zscale.is (\"log\"), false,\n                         2, m_zlim);\n\n      if (sync_pos)\n        sync_positions ();\n    }\n\n    void update_xtickmode ()\n    {\n      if (m_xtickmode.is (\"auto\"))\n        update_xtick ();\n    }\n    void update_ytickmode ()\n    {\n      if (m_ytickmode.is (\"auto\"))\n        update_ytick ();\n    }\n    void update_ztickmode ()\n    {\n      if (m_ztickmode.is (\"auto\"))\n        update_ztick ();\n    }\n\n    void update_xticklabelmode ()\n    {\n      if (m_xticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is (\"log\"),\n                         xaxislocation_is (\"origin\"),\n                         m_yscale.is (\"log\") ? 2 :\n                           (yaxislocation_is (\"origin\") ? 0 :\n                             (yaxislocation_is (\"left\") ? -1 : 1)),\n                         m_xlim);\n    }\n    void update_yticklabelmode ()\n    {\n      if (m_yticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_ytick, m_yticklabel, m_yscale.is (\"log\"),\n                         yaxislocation_is (\"origin\"),\n                         m_xscale.is (\"log\") ? 2 :\n                           (xaxislocation_is (\"origin\") ? 0 :\n                             (xaxislocation_is (\"bottom\") ? -1 : 1)),\n                         m_ylim);\n    }\n    void update_zticklabelmode ()\n    {\n      if (m_zticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_ztick, m_zticklabel, m_zscale.is (\"log\"),\n                         false, 2, m_zlim);\n    }\n\n    void update_xminortickvaluesmode ()\n    {\n      if (m_xminortickvaluesmode.is (\"auto\"))\n        calc_ticks_and_lims (m_xlim, m_xtick, m_xminortickvalues,\n                             m_xlimmode.is (\"auto\"), m_xtickmode.is (\"auto\"),\n                             true,\n                             m_xscale.is (\"log\"), m_xlimitmethod.is (\"padded\"),\n                             m_xlimitmethod.is (\"tight\"));\n    }\n    void update_yminortickvaluesmode ()\n    {\n      if (m_yminortickvaluesmode.is (\"auto\"))\n        calc_ticks_and_lims (m_ylim, m_ytick, m_yminortickvalues,\n                             m_ylimmode.is (\"auto\"), m_ytickmode.is (\"auto\"),\n                             true,\n                             m_yscale.is (\"log\"), m_ylimitmethod.is (\"padded\"),\n                             m_ylimitmethod.is (\"tight\"));\n    }\n    void update_zminortickvaluesmode ()\n    {\n      if (m_zminortickvaluesmode.is (\"auto\"))\n        calc_ticks_and_lims (m_zlim, m_ztick, m_zminortickvalues,\n                             m_zlimmode.is (\"auto\"), m_ztickmode.is (\"auto\"),\n                             true,\n                             m_zscale.is (\"log\"), m_zlimitmethod.is (\"padded\"),\n                             m_zlimitmethod.is (\"tight\"));\n    }\n\n    void update_fontname ()\n    {\n      update_font (\"fontname\");\n      sync_positions ();\n    }\n    void update_fontsize ()\n    {\n      update_font (\"fontsize\");\n      sync_positions ();\n    }\n    void update_fontsmoothing ()\n    {\n      update_font (\"fontsmoothing\");\n    }\n    void update_fontangle ()\n    {\n      update_font (\"fontangle\");\n      sync_positions ();\n    }\n    void update_fontweight ()\n    {\n      update_font (\"fontweight\");\n      sync_positions ();\n    }\n\n    void update_titlefontsizemultiplier ()\n    {\n      // update_font handles title and axis labels\n      update_font (\"fontsize\");\n      sync_positions ();\n    }\n\n    void update_labelfontsizemultiplier ()\n    {\n      update_font (\"fontsize\");\n      sync_positions ();\n    }\n\n    void update_titlefontweight ()\n    {\n      // update_font handles title and axis labels\n      update_font (\"fontweight\");\n      sync_positions ();\n    }\n\n    OCTINTERP_API void update_outerposition ();\n    OCTINTERP_API void update_position ();\n    OCTINTERP_API void update_looseinset ();\n\n    OCTINTERP_API double calc_tick_sep (double minval, double maxval);\n    OCTINTERP_API void\n    calc_ticks_and_lims (array_property& lims, array_property& ticks,\n                         array_property& mticks, bool limmode_is_auto,\n                         bool tickmode_is_auto, bool minortickvaluemode_is_auto,\n                         bool is_logscale, bool method_is_padded, bool method_is_tight);\n    OCTINTERP_API void\n    calc_ticklabels (const array_property& ticks, any_property& labels,\n                     bool is_logscale, const bool is_origin,\n                     const int other_axislocation,\n                     const array_property& axis_lims);\n    OCTINTERP_API Matrix\n    get_ticklabel_extents (const Matrix& ticks,\n                           const string_vector& ticklabels,\n                           const Matrix& limits);\n\n    void fix_limits (array_property& lims)\n    {\n      if (lims.get ().isempty ())\n        return;\n\n      Matrix l = lims.get ().matrix_value ();\n      if (l(0) > l(1))\n        {\n          l(0) = 0;\n          l(1) = 1;\n          lims = l;\n        }\n      else if (l(0) == l(1))\n        {\n          l(0) -= 0.5;\n          l(1) += 0.5;\n          lims = l;\n        }\n    }\n\n    OCTINTERP_API Matrix calc_tightbox (const Matrix& init_pos);\n\n    void set_colormap (const octave_value& val)\n    {\n      set___colormap__ (val);\n    }\n\n    void update___colormap__ ()\n    {\n      m_colormap.run_listeners (GCB_POSTSET);\n    }\n\n    OCTINTERP_API octave_value get_colormap () const;\n\n  public:\n    OCTINTERP_API Matrix\n    get_axis_limits (double xmin, double xmax,\n                     double min_pos, double max_neg,\n                     const bool logscale, const std::string& method);\n\n    OCTINTERP_API void\n    check_axis_limits (Matrix& limits, const Matrix kids,\n                       const bool logscale, char& update_type);\n\n    void update_xlim ()\n    {\n      update_axis_limits (\"xlim\");\n\n      calc_ticks_and_lims (m_xlim, m_xtick, m_xminortickvalues,\n                           m_xlimmode.is (\"auto\"), m_xtickmode.is (\"auto\"),\n                           m_xminortickvaluesmode.is (\"auto\"),\n                           m_xscale.is (\"log\"), m_xlimitmethod.is (\"padded\"),\n                           m_xlimitmethod.is (\"tight\"));\n      if (m_xticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is (\"log\"),\n                         m_xaxislocation.is (\"origin\"),\n                         m_yscale.is (\"log\") ? 2 :\n                           (yaxislocation_is (\"origin\") ? 0 :\n                             (yaxislocation_is (\"left\") ? -1 : 1)),\n                         m_xlim);\n\n      fix_limits (m_xlim);\n\n      update_xscale ();\n\n      update_axes_layout ();\n    }\n\n    void update_xlimitmethod ()\n    {\n      update_xlim ();\n    }\n\n    void update_ylim ()\n    {\n      update_axis_limits (\"ylim\");\n\n      calc_ticks_and_lims (m_ylim, m_ytick, m_yminortickvalues,\n                           m_ylimmode.is (\"auto\"), m_ytickmode.is (\"auto\"),\n                           m_yminortickvaluesmode.is (\"auto\"),\n                           m_yscale.is (\"log\"), m_ylimitmethod.is (\"padded\"),\n                           m_ylimitmethod.is (\"tight\"));\n      if (m_yticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_ytick, m_yticklabel, m_yscale.is (\"log\"),\n                         yaxislocation_is (\"origin\"),\n                         m_xscale.is (\"log\") ? 2 :\n                           (xaxislocation_is (\"origin\") ? 0 :\n                             (xaxislocation_is (\"bottom\") ? -1 : 1)),\n                         m_ylim);\n\n      fix_limits (m_ylim);\n\n      update_yscale ();\n\n      update_axes_layout ();\n    }\n\n    void update_ylimitmethod ()\n    {\n      update_ylim ();\n    }\n\n    void update_zlim ()\n    {\n      update_axis_limits (\"zlim\");\n\n      calc_ticks_and_lims (m_zlim, m_ztick, m_zminortickvalues,\n                           m_zlimmode.is (\"auto\"), m_ztickmode.is (\"auto\"),\n                           m_zminortickvaluesmode.is (\"auto\"),\n                           m_zscale.is (\"log\"), m_zlimitmethod.is (\"padded\"),\n                           m_zlimitmethod.is (\"tight\"));\n      if (m_zticklabelmode.is (\"auto\"))\n        calc_ticklabels (m_ztick, m_zticklabel, m_zscale.is (\"log\"), false,\n                         2, m_zlim);\n\n      fix_limits (m_zlim);\n\n      update_zscale ();\n\n      update_axes_layout ();\n    }\n\n    void update_zlimitmethod ()\n    {\n      update_zlim ();\n    }\n\n    void trigger_normals_calc ();\n\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  axes (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p), m_default_properties ()\n  {\n    m_properties.update_transform ();\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (axes)\n\n  ~axes () = default;\n\n  void override_defaults (base_graphics_object& obj)\n  {\n    // Allow parent (figure) to override first (properties knows how\n    // to find the parent object).\n    m_properties.override_defaults (obj);\n\n    // Now override with our defaults.  If the default_properties\n    // list includes the properties for all defaults (line,\n    // surface, etc.) then we don't have to know the type of OBJ\n    // here, we just call its set function and let it decide which\n    // properties from the list to use.\n    obj.set_from_list (m_default_properties);\n  }\n\n  void set (const caseless_str& name, const octave_value& value)\n  {\n    if (name.compare (\"default\", 7))\n      // strip \"default\", pass rest to function that will\n      // parse the remainder and add the element to the\n      // default_properties map.\n      m_default_properties.set (name.substr (7), value);\n    else\n      m_properties.set (name, value);\n  }\n\n  void set_defaults (const std::string& mode)\n  {\n    m_properties.set_defaults (*this, mode);\n  }\n\n  octave_value get (const caseless_str& name) const\n  {\n    octave_value retval;\n\n    // FIXME: finish this.\n    if (name.compare (\"default\", 7))\n      retval = get_default (name.substr (7));\n    else\n      retval = m_properties.get (name);\n\n    return retval;\n  }\n\n  OCTINTERP_API octave_value get_default (const caseless_str& name) const;\n\n  octave_value get_defaults () const\n  {\n    return m_default_properties.as_struct (\"default\");\n  }\n\n  property_list get_defaults_list () const\n  {\n    return m_default_properties;\n  }\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  OCTINTERP_API void update_axis_limits (const std::string& axis_type);\n\n  OCTINTERP_API void update_axis_limits (const std::string& axis_type,\n                                         const graphics_handle& h);\n\n  bool valid_object () const { return true; }\n\n  OCTINTERP_API void reset_default_properties ();\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\nprotected:\n  OCTINTERP_API void initialize (const graphics_object& go);\n\nprivate:\n  property_list m_default_properties;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API line : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (line)\n      color_property color , color_property (color_values (0, 0, 0), radio_values (\"none\"))\n      string_property displayname , \"\"\n      radio_property linejoin , \"{round}|miter|chamfer\"\n      radio_property linestyle , \"{-}|--|:|-.|none\"\n      double_property linewidth , 0.5\n      radio_property marker , \"{none}|+|o|*|.|x|||_|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram\"\n      color_property markeredgecolor , color_property (radio_values (\"{auto}|none\"), color_values (0, 0, 0))\n      color_property markerfacecolor , color_property (radio_values (\"auto|{none}\"), color_values (0, 0, 0))\n      double_property markersize , 6\n      row_vector_property xdata u , default_data ()\n      string_property xdatasource , \"\"\n      row_vector_property ydata u , default_data ()\n      string_property ydatasource , \"\"\n      row_vector_property zdata u , Matrix ()\n      string_property zdatasource , \"\"\n\n      // hidden properties for limit computation\n      row_vector_property xlim hlr , default_data_lim ()\n      row_vector_property ylim hlr , default_data_lim ()\n      row_vector_property zlim hlr , Matrix ()\n      bool_property xliminclude hl , \"on\"\n      bool_property yliminclude hl , \"on\"\n      bool_property zliminclude hl , \"on\"\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_linewidth.add_constraint (\"min\", 0, false);\n      m_markersize.add_constraint (\"min\", 0, false);\n    }\n\n  private:\n    OCTINTERP_API Matrix compute_xlim () const;\n    OCTINTERP_API Matrix compute_ylim () const;\n\n    void update_xdata () { set_xlim (compute_xlim ()); }\n\n    void update_ydata () { set_ylim (compute_ylim ()); }\n\n    void update_zdata () { set_zlim (m_zdata.get_limits ()); }\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  line (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (line)\n\n  ~line () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API text : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    OCTINTERP_API double\n    get___fontsize_points__ (double box_pix_height = 0) const;\n\n    OCTINTERP_API void update_text_extent ();\n\n    OCTINTERP_API void update_font ();\n\n    void set_position (const octave_value& val)\n    {\n      octave_value new_val (val);\n\n      if (new_val.numel () == 2)\n        {\n          dim_vector dv (1, 3);\n\n          new_val = new_val.resize (dv, true);\n        }\n\n      if (m_position.set (new_val, false))\n        {\n          set_positionmode (\"manual\");\n          update_position ();\n          m_position.run_listeners (GCB_POSTSET);\n          mark_modified ();\n        }\n      else\n        set_positionmode (\"manual\");\n    }\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (text)\n      color_property backgroundcolor , color_property (radio_values (\"{none}\"), color_values (1, 1, 1))\n      color_property color u , color_property (color_values (0, 0, 0), radio_values (\"none\"))\n      color_property edgecolor , color_property (radio_values (\"{none}\"), color_values (0, 0, 0))\n      bool_property editing , \"off\"\n      array_property extent rG , Matrix (1, 4, 0.0)\n      radio_property fontangle u , \"{normal}|italic\"\n      string_property fontname u , OCTAVE_DEFAULT_FONTNAME\n      double_property fontsize u , 10\n      bool_property fontsmoothing u , \"on\"\n      radio_property fontunits SU , \"inches|centimeters|normalized|{points}|pixels\"\n      radio_property fontweight u , \"{normal}|bold\"\n      radio_property horizontalalignment mu , \"{left}|center|right\"\n      radio_property interpreter u , \"{tex}|none|latex\"\n      radio_property linestyle , \"{-}|--|:|-.|none\"\n      double_property linewidth , 0.5\n      double_property margin , 3\n      array_property position smu , Matrix (1, 3, 0.0)\n      double_property rotation mu , 0\n      text_label_property string u , \"\"\n      radio_property units u , \"{data}|pixels|normalized|inches|centimeters|points\"\n      radio_property verticalalignment mu , \"top|cap|{middle}|baseline|bottom\"\n\n      // hidden properties for limit computation\n      row_vector_property xlim hlr , Matrix ()\n      row_vector_property ylim hlr , Matrix ()\n      row_vector_property zlim hlr , Matrix ()\n      bool_property xliminclude hl , \"off\"\n      bool_property yliminclude hl , \"off\"\n      bool_property zliminclude hl , \"off\"\n      // hidden properties for auto-positioning\n      radio_property positionmode hu , \"{auto}|manual\"\n      radio_property rotationmode hu , \"{auto}|manual\"\n      radio_property horizontalalignmentmode hu , \"{auto}|manual\"\n      radio_property verticalalignmentmode hu , \"{auto}|manual\"\n      radio_property __autopos_tag__ h , \"{none}|xlabel|ylabel|zlabel|title\"\n      // hidden property for text rendering\n      double_property __fontsize_points__ hgr , 0\n    END_PROPERTIES\n\n    OCTINTERP_API Matrix get_data_position () const;\n    OCTINTERP_API Matrix get_extent_matrix (bool rotated = false) const;\n    const uint8NDArray& get_pixels () const { return m_pixels; }\n\n    // Text renderer, used for calculation of text size\n    octave::text_renderer m_txt_renderer;\n\n  protected:\n    void init ()\n    {\n      m_position.add_constraint (dim_vector (1, 3));\n      m_fontsize.add_constraint (\"min\", 0.0, false);\n      m_linewidth.add_constraint (\"min\", 0.0, false);\n      m_margin.add_constraint (\"min\", 0.0, false);\n      m_cached_units = get_units ();\n      update_font ();\n    }\n\n  private:\n    void update_position ()\n    {\n      Matrix pos = get_data_position ();\n      Matrix lim;\n\n      lim = Matrix (1, 4, pos(0));\n      lim(2) = (lim(2) <= 0 ? octave::numeric_limits<double>::Inf () : lim(2));\n      lim(3) = (lim(3) >= 0 ? -octave::numeric_limits<double>::Inf () : lim(3));\n      set_xlim (lim);\n\n      lim = Matrix (1, 4, pos(1));\n      lim(2) = (lim(2) <= 0 ? octave::numeric_limits<double>::Inf () : lim(2));\n      lim(3) = (lim(3) >= 0 ? -octave::numeric_limits<double>::Inf () : lim(3));\n      set_ylim (lim);\n\n      if (pos.numel () == 3)\n        {\n          lim = Matrix (1, 4, pos(2));\n          lim(2) = (lim(2) <= 0 ? octave::numeric_limits<double>::Inf ()\n                                : lim(2));\n          lim(3) = (lim(3) >= 0 ? -octave::numeric_limits<double>::Inf ()\n                                : lim(3));\n          set_zlim (lim);\n        }\n    }\n\n    OCTINTERP_API void request_autopos ();\n    void update_positionmode () { request_autopos (); }\n    void update_rotationmode () { request_autopos (); }\n    void update_horizontalalignmentmode () { request_autopos (); }\n    void update_verticalalignmentmode () { request_autopos (); }\n\n    void update_string () { request_autopos (); update_text_extent (); }\n    void update_rotation () { update_text_extent (); }\n    void update_fontname () { update_font (); update_text_extent (); }\n    void update_fontsize () { update_font (); update_text_extent (); }\n    void update_fontsmoothing () { update_font (); update_text_extent (); }\n\n    void update_color ()\n    {\n      if (! m_color.is (\"none\"))\n        {\n          update_font ();\n          update_text_extent ();\n        }\n    }\n\n    void update_fontangle ()\n    {\n      update_font ();\n      update_text_extent ();\n    }\n    void update_fontweight () { update_font (); update_text_extent (); }\n\n    void update_interpreter () { update_text_extent (); }\n    void update_horizontalalignment () { update_text_extent (); }\n    void update_verticalalignment () { update_text_extent (); }\n\n    OCTINTERP_API void update_units ();\n    OCTINTERP_API void update_fontunits (const caseless_str& old_fontunits);\n\n  private:\n    std::string m_cached_units;\n    uint8NDArray m_pixels;\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  text (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  {\n    m_properties.set_clipping (\"off\");\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (text)\n\n  ~text () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API image : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    bool is_aliminclude () const\n    { return (m_aliminclude.is_on () && m_alphadatamapping.is (\"scaled\")); }\n    std::string get_aliminclude () const\n    { return m_aliminclude.current_value (); }\n\n    bool is_climinclude () const\n    {\n      return (m_climinclude.is_on ()\n              && ! (m_cdatamapping.is (\"direct\")\n                    || m_cdata.get ().ndims () == 3));\n    }\n    std::string get_climinclude () const\n    { return m_climinclude.current_value (); }\n\n    OCTINTERP_API octave_value get_color_data () const;\n\n    void initialize_data () { update_cdata (); }\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (image)\n      array_property alphadata u , Matrix (1, 1, 1.0)\n      radio_property alphadatamapping al , \"{none}|direct|scaled\"\n      array_property cdata u , default_image_cdata ()\n      radio_property cdatamapping al , \"scaled|{direct}\"\n      row_vector_property xdata mu , Matrix ()\n      row_vector_property ydata mu , Matrix ()\n      // hidden properties for limit computation\n      row_vector_property alim hlr , Matrix ()\n      row_vector_property clim hlr , Matrix ()\n      row_vector_property xlim hlr , Matrix ()\n      row_vector_property ylim hlr , Matrix ()\n      bool_property aliminclude hlg , \"on\"\n      bool_property climinclude hlg , \"on\"\n      bool_property xliminclude hl , \"on\"\n      bool_property yliminclude hl , \"on\"\n      radio_property xdatamode ha , \"{auto}|manual\"\n      radio_property ydatamode ha , \"{auto}|manual\"\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_xdata.add_constraint (2);\n      m_xdata.add_constraint (dim_vector (0, 0));\n      m_ydata.add_constraint (2);\n      m_ydata.add_constraint (dim_vector (0, 0));\n      m_cdata.add_constraint (\"double\");\n      m_cdata.add_constraint (\"single\");\n      m_cdata.add_constraint (\"logical\");\n      m_cdata.add_constraint (\"int8\");\n      m_cdata.add_constraint (\"int16\");\n      m_cdata.add_constraint (\"int32\");\n      m_cdata.add_constraint (\"int64\");\n      m_cdata.add_constraint (\"uint8\");\n      m_cdata.add_constraint (\"uint16\");\n      m_cdata.add_constraint (\"uint32\");\n      m_cdata.add_constraint (\"uint64\");\n      m_cdata.add_constraint (\"real\");\n      m_cdata.add_constraint (dim_vector (-1, -1));\n      m_cdata.add_constraint (dim_vector (-1, -1, 3));\n      m_alphadata.add_constraint (\"double\");\n      m_alphadata.add_constraint (\"uint8\");\n      m_alphadata.add_constraint (dim_vector (-1, -1));\n    }\n\n  private:\n    void update_alphadata ()\n    {\n      if (alphadatamapping_is (\"scaled\"))\n        set_alim (m_alphadata.get_limits ());\n      else\n        m_alim = m_alphadata.get_limits ();\n    }\n\n    void update_cdata ()\n    {\n      if (cdatamapping_is (\"scaled\"))\n        set_clim (m_cdata.get_limits ());\n      else\n        m_clim = m_cdata.get_limits ();\n\n      if (m_xdatamode.is (\"auto\"))\n        update_xdata ();\n\n      if (m_ydatamode.is (\"auto\"))\n        update_ydata ();\n    }\n\n    void update_xdata ()\n    {\n      if (m_xdata.get ().isempty ())\n        set_xdatamode (\"auto\");\n\n      if (m_xdatamode.is (\"auto\"))\n        {\n          set_xdata (get_auto_xdata ());\n          set_xdatamode (\"auto\");\n        }\n\n      Matrix limits = m_xdata.get_limits ();\n      float dp = pixel_xsize ();\n\n      limits(0) = limits(0) - dp;\n      limits(1) = limits(1) + dp;\n      set_xlim (limits);\n    }\n\n    void update_ydata ()\n    {\n      if (m_ydata.get ().isempty ())\n        set_ydatamode (\"auto\");\n\n      if (m_ydatamode.is (\"auto\"))\n        {\n          set_ydata (get_auto_ydata ());\n          set_ydatamode (\"auto\");\n        }\n\n      Matrix limits = m_ydata.get_limits ();\n      float dp = pixel_ysize ();\n\n      limits(0) = limits(0) - dp;\n      limits(1) = limits(1) + dp;\n      set_ylim (limits);\n    }\n\n    Matrix get_auto_xdata ()\n    {\n      const dim_vector& dv = get_cdata ().dims ();\n      Matrix data;\n      if (dv(1) > 0.)\n        {\n          data = Matrix (1, 2, 1);\n          data(1) = dv(1);\n        }\n      return data;\n    }\n\n    Matrix get_auto_ydata ()\n    {\n      const dim_vector& dv = get_cdata ().dims ();\n      Matrix data;\n      if (dv(0) > 0.)\n        {\n          data = Matrix (1, 2, 1);\n          data(1) = dv(0);\n        }\n      return data;\n    }\n\n    float pixel_size (octave_idx_type dim, const Matrix limits)\n    {\n      octave_idx_type l = dim - 1;\n      float dp;\n\n      if (l > 0 && limits(0) != limits(1))\n        dp = (limits(1) - limits(0))/(2*l);\n      else\n        {\n          if (limits(1) == limits(2))\n            dp = 0.5;\n          else\n            dp = (limits(1) - limits(0))/2;\n        }\n      return dp;\n    }\n\n  public:\n    float pixel_xsize ()\n    {\n      return pixel_size ((get_cdata ().dims ())(1), m_xdata.get_limits ());\n    }\n\n    float pixel_ysize ()\n    {\n      return pixel_size ((get_cdata ().dims ())(0), m_ydata.get_limits ());\n    }\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  image (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  {\n    m_properties.initialize_data ();\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (image)\n\n  ~image () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API light : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (light)\n      color_property color , color_values (1, 1, 1)\n      array_property position , default_light_position ()\n      radio_property style , \"{infinite}|local\"\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_position.add_constraint (dim_vector (1, 3));\n    }\n\n  private:\n    OCTINTERP_API void update_visible ();\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  light (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (light)\n\n  ~light () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\nprotected:\n  OCTINTERP_API void initialize (const graphics_object& go);\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API patch : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    octave_value get_color_data () const;\n\n    // Matlab allows incoherent data to be stored into patch properties.\n    // The patch should then be ignored by the renderer.\n    bool has_bad_data (std::string& msg) const\n    {\n      msg = m_bad_data_msg;\n      return ! msg.empty ();\n    }\n\n    bool is_aliminclude () const\n    { return (m_aliminclude.is_on () && m_alphadatamapping.is (\"scaled\")); }\n    std::string get_aliminclude () const\n    { return m_aliminclude.current_value (); }\n\n    bool is_climinclude () const\n    {\n      return (m_climinclude.is_on ()\n              && ! (m_cdatamapping.is (\"direct\")\n                    || m_cdata.get ().ndims () == 3));\n    }\n    std::string get_climinclude () const\n    { return m_climinclude.current_value (); }\n\n    OCTINTERP_API bool get_do_lighting () const;\n\n    std::vector<std::vector<octave_idx_type>> m_coplanar_last_idx;\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (patch)\n      radio_property alphadatamapping l , \"none|{scaled}|direct\"\n      double_property ambientstrength , 0.3\n      radio_property backfacelighting , \"unlit|lit|{reverselit}\"\n      array_property cdata u , Matrix ()\n      radio_property cdatamapping l , \"{scaled}|direct\"\n      double_property diffusestrength , 0.6\n      string_property displayname , \"\"\n      double_radio_property edgealpha , double_radio_property (1.0, radio_values (\"flat|interp\"))\n      color_property edgecolor , color_property (color_values (0, 0, 0), radio_values (\"none|flat|interp\"))\n      radio_property edgelighting u , \"{none}|flat|gouraud|phong\"\n      double_radio_property facealpha , double_radio_property (1.0, radio_values (\"flat|interp\"))\n      color_property facecolor , color_property (color_values (0, 0, 0), radio_values (\"none|flat|interp\"))\n      radio_property facelighting u , \"none|{flat}|gouraud|phong\"\n      array_property facenormals m , Matrix ()\n      radio_property facenormalsmode u , \"{auto}|manual\"\n      array_property faces u , default_patch_faces ()\n      array_property facevertexalphadata , Matrix ()\n      array_property facevertexcdata u , Matrix ()\n      radio_property linestyle , \"{-}|--|:|-.|none\"\n      double_property linewidth , 0.5\n      radio_property marker , \"{none}|+|o|*|.|x|||_|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram\"\n      color_property markeredgecolor , color_property (radio_values (\"none|{auto}|flat\"), color_values (0, 0, 0))\n      color_property markerfacecolor , color_property (radio_values (\"{none}|auto|flat\"), color_values (0, 0, 0))\n      double_property markersize , 6\n      double_property specularcolorreflectance , 1.0\n      double_property specularexponent , 10.0\n      double_property specularstrength , 0.9\n      array_property vertexnormals m , Matrix ()\n      radio_property vertexnormalsmode u , \"{auto}|manual\"\n      array_property vertices u , default_patch_vertices ()\n      array_property xdata u , default_patch_xdata ()\n      array_property ydata u , default_patch_ydata ()\n      array_property zdata u , Matrix ()\n\n      // hidden properties for limit computation\n      row_vector_property alim hlr , Matrix ()\n      row_vector_property clim hlr , Matrix ()\n      row_vector_property xlim hlr , Matrix ()\n      row_vector_property ylim hlr , Matrix ()\n      row_vector_property zlim hlr , Matrix ()\n      bool_property aliminclude hlg , \"on\"\n      bool_property climinclude hlg , \"on\"\n      bool_property xliminclude hl , \"on\"\n      bool_property yliminclude hl , \"on\"\n      bool_property zliminclude hl , \"on\"\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_xdata.add_constraint (dim_vector (-1, -1));\n      m_ydata.add_constraint (dim_vector (-1, -1));\n      m_zdata.add_constraint (dim_vector (-1, -1));\n      m_faces.add_constraint (dim_vector (-1, -1));\n      m_vertices.add_constraint (dim_vector (-1, 2));\n      m_vertices.add_constraint (dim_vector (-1, 3));\n      m_cdata.add_constraint (\"double\");\n      m_cdata.add_constraint (\"single\");\n      m_cdata.add_constraint (\"logical\");\n      m_cdata.add_constraint (\"int8\");\n      m_cdata.add_constraint (\"int16\");\n      m_cdata.add_constraint (\"int32\");\n      m_cdata.add_constraint (\"int64\");\n      m_cdata.add_constraint (\"uint8\");\n      m_cdata.add_constraint (\"uint16\");\n      m_cdata.add_constraint (\"uint32\");\n      m_cdata.add_constraint (\"uint64\");\n      m_cdata.add_constraint (\"real\");\n      m_cdata.add_constraint (dim_vector (-1, -1));\n      m_cdata.add_constraint (dim_vector (-1, -1, 3));\n      m_facevertexcdata.add_constraint (dim_vector (-1, 1));\n      m_facevertexcdata.add_constraint (dim_vector (-1, 3));\n      m_facevertexcdata.add_constraint (dim_vector (0, 0));\n      m_facevertexalphadata.add_constraint (dim_vector (-1, 1));\n      m_facevertexalphadata.add_constraint (dim_vector (0, 0));\n      m_facenormals.add_constraint (dim_vector (-1, 3));\n      m_facenormals.add_constraint (dim_vector (0, 0));\n      m_vertexnormals.add_constraint (dim_vector (-1, 3));\n      m_vertexnormals.add_constraint (dim_vector (0, 0));\n\n      m_ambientstrength.add_constraint (\"min\", 0.0, true);\n      m_ambientstrength.add_constraint (\"max\", 1.0, true);\n      m_diffusestrength.add_constraint (\"min\", 0.0, true);\n      m_diffusestrength.add_constraint (\"max\", 1.0, true);\n      m_linewidth.add_constraint (\"min\", 0.0, false);\n      m_markersize.add_constraint (\"min\", 0.0, false);\n      m_specularcolorreflectance.add_constraint (\"min\", 0.0, true);\n      m_specularcolorreflectance.add_constraint (\"max\", 1.0, true);\n      m_specularexponent.add_constraint (\"min\", 0.0, false);\n      m_specularstrength.add_constraint (\"min\", 0.0, true);\n      m_specularstrength.add_constraint (\"max\", 1.0, true);\n    }\n\n  public:\n    void update_normals (bool reset, bool force = false)\n    {\n      update_face_normals (reset, force);\n      update_vertex_normals (reset, force);\n    }\n\n\n  private:\n    std::string m_bad_data_msg;\n\n    void update_faces () { update_data ();}\n\n    void update_vertices () { update_data ();}\n\n    void update_facevertexcdata () { update_data ();}\n\n    OCTINTERP_API void update_fvc ();\n\n    void update_xdata ()\n    {\n      if (get_xdata ().isempty ())\n        {\n          // For compatibility with matlab behavior,\n          // if x/ydata are set empty, silently empty other *data and\n          // faces properties while vertices remain unchanged.\n          set_ydata (Matrix ());\n          set_zdata (Matrix ());\n          set_cdata (Matrix ());\n          set_faces (Matrix ());\n        }\n      else\n        {\n          update_fvc ();\n          update_normals (true);\n        }\n\n      set_xlim (m_xdata.get_limits ());\n    }\n\n    void update_ydata ()\n    {\n      if (get_ydata ().isempty ())\n        {\n          set_xdata (Matrix ());\n          set_zdata (Matrix ());\n          set_cdata (Matrix ());\n          set_faces (Matrix ());\n        }\n      else\n        {\n          update_fvc ();\n          update_normals (true);\n        }\n\n      set_ylim (m_ydata.get_limits ());\n    }\n\n    void update_zdata ()\n    {\n      update_fvc ();\n      update_normals (true);\n      set_zlim (m_zdata.get_limits ());\n    }\n\n    void update_cdata ()\n    {\n      update_fvc ();\n      update_normals (false);\n\n      if (cdatamapping_is (\"scaled\"))\n        set_clim (m_cdata.get_limits ());\n      else\n        m_clim = m_cdata.get_limits ();\n    }\n\n    OCTINTERP_API void update_data ();\n\n    OCTINTERP_API void calc_face_normals (Matrix& normals);\n    OCTINTERP_API void update_face_normals (bool reset, bool force = false);\n    OCTINTERP_API void update_vertex_normals (bool reset, bool force = false);\n\n    void update_edgelighting ()\n    {\n      update_normals (false);\n    }\n\n    void update_facelighting ()\n    {\n      update_normals (false);\n    }\n\n    void update_facenormalsmode ()\n    {\n      update_face_normals (false);\n    }\n\n    void update_vertexnormalsmode ()\n    {\n      update_vertex_normals (false);\n    }\n\n    void update_visible ()\n    {\n      if (is_visible ())\n        update_normals (false);\n    }\n  };\n\nprivate:\n  properties m_properties;\n  property_list m_default_properties;\n\npublic:\n  patch (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (patch)\n\n  ~patch () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\n  OCTINTERP_API void reset_default_properties ();\n\nprotected:\n  OCTINTERP_API void initialize (const graphics_object& go);\n\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API scatter : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    OCTINTERP_API octave_value get_color_data () const;\n\n    // Matlab allows incoherent data to be stored in scatter properties.\n    // The scatter object should then be ignored by the renderer.\n    bool has_bad_data (std::string& msg) const\n    {\n      msg = m_bad_data_msg;\n      return ! msg.empty ();\n    }\n\n    bool is_aliminclude () const\n    { return m_aliminclude.is_on (); }\n    std::string get_aliminclude () const\n    { return m_aliminclude.current_value (); }\n\n    bool is_climinclude () const\n    { return m_climinclude.is_on (); }\n    std::string get_climinclude () const\n    { return m_climinclude.current_value (); }\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (scatter)\n      array_property annotation , Matrix ()\n      array_property cdata mu , Matrix ()\n      radio_property cdatamode u , \"{auto}|manual\"\n      string_property cdatasource , \"\"\n      array_property datatiptemplate , Matrix ()\n      string_property displayname , \"\"\n      array_property latitudedata , Matrix ()\n      string_property latitudedatasource , \"\"\n      double_property linewidth , 0.5\n      array_property longitudedata , Matrix ()\n      string_property longitudedatasource , \"\"\n      radio_property marker , \"{o}|+|*|.|x|||_|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram|none\"\n      double_property markeredgealpha , 1.0\n      color_property markeredgecolor , color_property (radio_values (\"{flat}|none\"), color_values (0, 0, 0))\n      double_property markerfacealpha , 1.0\n      color_property markerfacecolor , color_property (radio_values (\"{none}|auto|flat\"), color_values (0, 0, 0))\n      array_property rdata , Matrix ()\n      string_property rdatasource , \"\"\n      array_property seriesindex u , Matrix ()\n      array_property sizedata u , Matrix ()\n      string_property sizedatasource , \"\"\n      array_property thetadata , Matrix ()\n      string_property thetadatasource , \"\"\n      array_property xdata u , Matrix ()\n      string_property xdatasource , \"\"\n      array_property ydata u , Matrix ()\n      string_property ydatasource , \"\"\n      array_property zdata u , Matrix ()\n      string_property zdatasource , \"\"\n\n      // hidden properties for limit computation\n      row_vector_property alim hlr , Matrix ()\n      row_vector_property clim hlr , Matrix ()\n      row_vector_property xlim hlr , Matrix ()\n      row_vector_property ylim hlr , Matrix ()\n      row_vector_property zlim hlr , Matrix ()\n      bool_property aliminclude hlg , \"on\"\n      bool_property climinclude hlg , \"on\"\n      bool_property xliminclude hl , \"on\"\n      bool_property yliminclude hl , \"on\"\n      bool_property zliminclude hl , \"on\"\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_xdata.add_constraint (dim_vector (-1, 1));\n      m_xdata.add_constraint (dim_vector (1, -1));\n      m_xdata.add_constraint (dim_vector (-1, 0));\n      m_xdata.add_constraint (dim_vector (0, -1));\n      m_ydata.add_constraint (dim_vector (-1, 1));\n      m_ydata.add_constraint (dim_vector (1, -1));\n      m_ydata.add_constraint (dim_vector (-1, 0));\n      m_ydata.add_constraint (dim_vector (0, -1));\n      m_zdata.add_constraint (dim_vector (-1, 1));\n      m_zdata.add_constraint (dim_vector (1, -1));\n      m_zdata.add_constraint (dim_vector (-1, 0));\n      m_zdata.add_constraint (dim_vector (0, -1));\n      m_sizedata.add_constraint (\"min\", 0.0, false);\n      m_sizedata.add_constraint (dim_vector (-1, 1));\n      m_sizedata.add_constraint (dim_vector (1, -1));\n      m_sizedata.add_constraint (dim_vector (-1, 0));\n      m_sizedata.add_constraint (dim_vector (0, -1));\n      m_cdata.add_constraint (\"double\");\n      m_cdata.add_constraint (\"single\");\n      m_cdata.add_constraint (\"logical\");\n      m_cdata.add_constraint (\"int8\");\n      m_cdata.add_constraint (\"int16\");\n      m_cdata.add_constraint (\"int32\");\n      m_cdata.add_constraint (\"int64\");\n      m_cdata.add_constraint (\"uint8\");\n      m_cdata.add_constraint (\"uint16\");\n      m_cdata.add_constraint (\"uint32\");\n      m_cdata.add_constraint (\"uint64\");\n      m_cdata.add_constraint (\"real\");\n      m_cdata.add_constraint (dim_vector (-1, 1));\n      m_cdata.add_constraint (dim_vector (-1, 3));\n      m_cdata.add_constraint (dim_vector (-1, 0));\n      m_cdata.add_constraint (dim_vector (0, -1));\n\n      m_linewidth.add_constraint (\"min\", 0.0, false);\n      m_seriesindex.add_constraint (dim_vector (1, 1));\n      m_seriesindex.add_constraint (dim_vector (-1, 0));\n      m_seriesindex.add_constraint (dim_vector (0, -1));\n    }\n\n  public:\n    OCTINTERP_API void update_color ();\n\n  private:\n    std::string m_bad_data_msg;\n\n    void update_xdata ()\n    {\n      if (get_xdata ().isempty ())\n        {\n          // For compatibility with Matlab behavior,\n          // if x/ydata are set empty, silently empty other *data properties.\n          set_ydata (Matrix ());\n          set_zdata (Matrix ());\n          bool cdatamode_auto = m_cdatamode.is (\"auto\");\n          set_cdata (Matrix ());\n          if (cdatamode_auto)\n            set_cdatamode (\"auto\");\n        }\n\n      set_xlim (m_xdata.get_limits ());\n\n      update_data ();\n    }\n\n    void update_ydata ()\n    {\n      if (get_ydata ().isempty ())\n        {\n          set_xdata (Matrix ());\n          set_zdata (Matrix ());\n          bool cdatamode_auto = m_cdatamode.is (\"auto\");\n          set_cdata (Matrix ());\n          if (cdatamode_auto)\n            set_cdatamode (\"auto\");\n        }\n\n      set_ylim (m_ydata.get_limits ());\n\n      update_data ();\n    }\n\n    void update_zdata ()\n    {\n      set_zlim (m_zdata.get_limits ());\n\n      update_data ();\n    }\n\n    void update_sizedata ()\n    {\n      update_data ();\n    }\n\n    void update_cdata ()\n    {\n      if (get_cdata ().matrix_value ().rows () == 1)\n        set_clim (m_cdata.get_limits ());\n      else\n        m_clim = m_cdata.get_limits ();\n\n      update_data ();\n    }\n\n    void update_cdatamode ()\n    {\n      if (m_cdatamode.is (\"auto\"))\n        update_color ();\n    }\n\n    void update_seriesindex ()\n    {\n      if (m_cdatamode.is (\"auto\"))\n        update_color ();\n    }\n\n    void update_data ();\n\n  };\n\nprivate:\n  properties m_properties;\n  property_list m_default_properties;\n\npublic:\n  scatter (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  {\n    // FIXME: seriesindex should increment by one each time a new scatter\n    // object is added to the axes.\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (scatter)\n\n  ~scatter () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\nprotected:\n  OCTINTERP_API void initialize (const graphics_object& go);\n\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API surface : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    octave_value get_color_data () const;\n\n    bool is_aliminclude () const\n    { return (m_aliminclude.is_on () && m_alphadatamapping.is (\"scaled\")); }\n    std::string get_aliminclude () const\n    { return m_aliminclude.current_value (); }\n\n    bool is_climinclude () const\n    {\n      return (m_climinclude.is_on ()\n              && ! (m_cdatamapping.is (\"direct\")\n                    || m_cdata.get ().ndims () == 3));\n    }\n    std::string get_climinclude () const\n    { return m_climinclude.current_value (); }\n\n    OCTINTERP_API bool get_do_lighting () const;\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (surface)\n      array_property alphadata u , Matrix (1, 1, 1.0)\n      radio_property alphadatamapping l , \"none|direct|{scaled}\"\n      double_property ambientstrength , 0.3\n      radio_property backfacelighting , \"unlit|lit|{reverselit}\"\n      array_property cdata u , default_surface_cdata ()\n      radio_property cdatamapping al , \"{scaled}|direct\"\n      string_property cdatasource , \"\"\n      double_property diffusestrength , 0.6\n      string_property displayname , \"\"\n      double_radio_property edgealpha , double_radio_property (1.0, radio_values (\"flat|interp\"))\n      color_property edgecolor , color_property (color_values (0, 0, 0), radio_values (\"none|flat|interp\"))\n      radio_property edgelighting u , \"{none}|flat|gouraud|phong\"\n      double_radio_property facealpha , double_radio_property (1.0, radio_values (\"flat|interp|texturemap\"))\n      color_property facecolor , color_property (radio_values (\"none|{flat}|interp|texturemap\"), color_values (0, 0, 0))\n      radio_property facelighting u , \"none|{flat}|gouraud|phong\"\n      array_property facenormals m , Matrix ()\n      radio_property facenormalsmode u , \"{auto}|manual\"\n      radio_property linestyle , \"{-}|--|:|-.|none\"\n      double_property linewidth , 0.5\n      radio_property marker , \"{none}|+|o|*|.|x|||_|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram\"\n      color_property markeredgecolor , color_property (radio_values (\"none|{auto}|flat\"), color_values (0, 0, 0))\n      color_property markerfacecolor , color_property (radio_values (\"{none}|auto|flat\"), color_values (0, 0, 0))\n      double_property markersize , 6\n      radio_property meshstyle , \"{both}|row|column\"\n      double_property specularcolorreflectance , 1\n      double_property specularexponent , 10\n      double_property specularstrength , 0.9\n      array_property vertexnormals m , Matrix ()\n      radio_property vertexnormalsmode u , \"{auto}|manual\"\n      array_property xdata u , default_surface_xdata ()\n      string_property xdatasource , \"\"\n      array_property ydata u , default_surface_ydata ()\n      string_property ydatasource , \"\"\n      array_property zdata u , default_surface_zdata ()\n      string_property zdatasource , \"\"\n\n      // hidden properties for limit computation\n      row_vector_property alim hlr , Matrix ()\n      row_vector_property clim hlr , Matrix ()\n      row_vector_property xlim hlr , Matrix ()\n      row_vector_property ylim hlr , Matrix ()\n      row_vector_property zlim hlr , Matrix ()\n      bool_property aliminclude hlg , \"on\"\n      bool_property climinclude hlg , \"on\"\n      bool_property xliminclude hl , \"on\"\n      bool_property yliminclude hl , \"on\"\n      bool_property zliminclude hl , \"on\"\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_xdata.add_constraint (dim_vector (-1, -1));\n      m_ydata.add_constraint (dim_vector (-1, -1));\n      m_zdata.add_constraint (dim_vector (-1, -1));\n      m_cdata.add_constraint (\"double\");\n      m_cdata.add_constraint (\"single\");\n      m_cdata.add_constraint (\"logical\");\n      m_cdata.add_constraint (\"int8\");\n      m_cdata.add_constraint (\"int16\");\n      m_cdata.add_constraint (\"int32\");\n      m_cdata.add_constraint (\"int64\");\n      m_cdata.add_constraint (\"uint8\");\n      m_cdata.add_constraint (\"uint16\");\n      m_cdata.add_constraint (\"uint32\");\n      m_cdata.add_constraint (\"uint64\");\n      m_cdata.add_constraint (\"real\");\n      m_cdata.add_constraint (dim_vector (-1, -1));\n      m_cdata.add_constraint (dim_vector (-1, -1, 3));\n      m_alphadata.add_constraint (\"double\");\n      m_alphadata.add_constraint (\"uint8\");\n      m_alphadata.add_constraint (dim_vector (-1, -1));\n      m_facenormals.add_constraint (dim_vector (-1, -1, 3));\n      m_facenormals.add_constraint (dim_vector (0, 0));\n      m_vertexnormals.add_constraint (dim_vector (-1, -1, 3));\n      m_vertexnormals.add_constraint (dim_vector (0, 0));\n\n      m_ambientstrength.add_constraint (\"min\", 0.0, true);\n      m_ambientstrength.add_constraint (\"max\", 1.0, true);\n      m_diffusestrength.add_constraint (\"min\", 0.0, true);\n      m_diffusestrength.add_constraint (\"max\", 1.0, true);\n      m_linewidth.add_constraint (\"min\", 0.0, false);\n      m_markersize.add_constraint (\"min\", 0.0, false);\n      m_specularcolorreflectance.add_constraint (\"min\", 0.0, true);\n      m_specularcolorreflectance.add_constraint (\"max\", 1.0, true);\n      m_specularexponent.add_constraint (\"min\", 0.0, false);\n      m_specularstrength.add_constraint (\"min\", 0.0, true);\n      m_specularstrength.add_constraint (\"max\", 1.0, true);\n    }\n\n  public:\n    void update_normals (bool reset, bool force = false)\n    {\n      update_face_normals (reset, force);\n      update_vertex_normals (reset, force);\n    }\n\n\n  private:\n    void update_alphadata ()\n    {\n      if (alphadatamapping_is (\"scaled\"))\n        set_alim (m_alphadata.get_limits ());\n      else\n        m_alim = m_alphadata.get_limits ();\n    }\n\n    void update_cdata ()\n    {\n      if (cdatamapping_is (\"scaled\"))\n        set_clim (m_cdata.get_limits ());\n      else\n        m_clim = m_cdata.get_limits ();\n    }\n\n    void update_xdata ()\n    {\n      update_normals (true);\n      set_xlim (m_xdata.get_limits ());\n    }\n\n    void update_ydata ()\n    {\n      update_normals (true);\n      set_ylim (m_ydata.get_limits ());\n    }\n\n    void update_zdata ()\n    {\n      update_normals (true);\n      set_zlim (m_zdata.get_limits ());\n    }\n\n    OCTINTERP_API void update_face_normals (bool reset, bool force = false);\n    OCTINTERP_API void update_vertex_normals (bool reset, bool force = false);\n\n    void update_facenormalsmode ()\n    { update_face_normals (false); }\n\n    void update_vertexnormalsmode ()\n    { update_vertex_normals (false); }\n\n    void update_edgelighting ()\n    { update_normals (false); }\n\n    void update_facelighting ()\n    { update_normals (false); }\n\n    void update_visible ()\n    {\n      if (is_visible ())\n        update_normals (false);\n    }\n\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  surface (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (surface)\n\n  ~surface () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API hggroup : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    OCTINTERP_API void\n    remove_child (const graphics_handle& h, bool from_root = false);\n\n    OCTINTERP_API void adopt (const graphics_handle& h);\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (hggroup)\n      string_property displayname , \"\"\n\n      // hidden properties for limit computation\n      row_vector_property alim hr , Matrix ()\n      row_vector_property clim hr , Matrix ()\n      row_vector_property xlim hr , Matrix ()\n      row_vector_property ylim hr , Matrix ()\n      row_vector_property zlim hr , Matrix ()\n      bool_property aliminclude h , \"on\"\n      bool_property climinclude h , \"on\"\n      bool_property xliminclude h , \"on\"\n      bool_property yliminclude h , \"on\"\n      bool_property zliminclude h , \"on\"\n    END_PROPERTIES\n\n  private:\n    OCTINTERP_API void update_limits () const;\n\n    OCTINTERP_API void update_limits (const graphics_handle& h) const;\n\n  protected:\n    void init ()\n    { }\n\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  hggroup (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (hggroup)\n\n  ~hggroup () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  OCTINTERP_API void update_axis_limits (const std::string& axis_type);\n\n  OCTINTERP_API void update_axis_limits (const std::string& axis_type,\n                                         const graphics_handle& h);\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API uimenu : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    void remove_child (const graphics_handle& h, bool from_root = false)\n    {\n      base_properties::remove_child (h, from_root);\n    }\n\n    void adopt (const graphics_handle& h)\n    {\n      base_properties::adopt (h);\n    }\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (uimenu)\n      string_property accelerator , \"\"\n      // Deprecated in R2017b (replaced by \"MenuSelectedFcn\")\n      callback_property callback hgs , Matrix ()\n      bool_property checked , \"off\"\n      bool_property enable , \"on\"\n      color_property foregroundcolor , color_values (0, 0, 0)\n      // Deprecated in R2017b (replaced by \"Text\")\n      string_property label hgs , \"\"\n      callback_property menuselectedfcn , Matrix ()\n      // Deprecated in R2017b, but replacement of re-ordering \"children\"\n      // property of parent does not work yet in Octave.\n      double_property position , 0\n      bool_property separator , \"off\"\n      string_property text , \"\"\n\n      // Octave-specific properties\n      string_property __fltk_label__ h , \"\"\n      any_property __object__ h , Matrix ()\n    END_PROPERTIES\n\n    // Make \"Label\" an alias for \"Text\".\n    std::string get_label () const\n    {\n      return get_text ();\n    }\n\n    void set_label (const octave_value& val)\n    {\n      set_text (val);\n    }\n\n    // Make \"Callback\" an alias for \"MenuSelectedFcn\".\n    octave_value get_callback () const\n    {\n      return get_menuselectedfcn ();\n    }\n\n    void set_callback (const octave_value& val)\n    {\n      set_menuselectedfcn (val);\n    }\n\n  protected:\n    void init ()\n    {\n      m_position.add_constraint (\"min\", 0, true);\n    }\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  uimenu (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uimenu)\n\n  ~uimenu () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\n};\n\n// ---------------------------------------------------------------------\n\n// FIXME: This class has been renamed to \"contextmenu\" in Matlab R2020a.\nclass OCTINTERP_API uicontextmenu : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    void add_dependent_obj (graphics_handle gh)\n    { m_dependent_obj_list.push_back (gh); }\n\n    // FIXME: the list may contain duplicates.\n    //        Should we return only unique elements?\n    const std::list<graphics_handle> get_dependent_obj_list ()\n    { return m_dependent_obj_list; }\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (uicontextmenu)\n      callback_property callback , Matrix ()\n      array_property position , Matrix (1, 2, 0.0)\n\n      // Octave-specific properties\n      any_property __object__ h , Matrix ()\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_position.add_constraint (dim_vector (1, 2));\n      m_position.add_constraint (dim_vector (2, 1));\n      m_visible.set (octave_value (false));\n    }\n\n  private:\n    // List of objects that might depend on this uicontextmenu object\n    std::list<graphics_handle> m_dependent_obj_list;\n\n    OCTINTERP_API void update_beingdeleted ();\n\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  uicontextmenu (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uicontextmenu)\n\n  ~uicontextmenu () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API uicontrol : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    OCTINTERP_API Matrix\n    get_boundingbox (bool internal = false,\n                     const Matrix& parent_pix_size = Matrix ()) const;\n\n    OCTINTERP_API double\n    get___fontsize_points__ (double box_pix_height = 0) const;\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (uicontrol)\n      color_property backgroundcolor , color_values (0.94, 0.94, 0.94)\n      callback_property callback , Matrix ()\n      array_property cdata , Matrix ()\n      bool_property clipping , \"on\"\n      radio_property enable , \"{on}|inactive|off\"\n      array_property extent rG , Matrix (1, 4, 0.0)\n      radio_property fontangle u , \"{normal}|italic\"\n      string_property fontname u , OCTAVE_DEFAULT_FONTNAME\n      double_property fontsize u , 10\n      radio_property fontunits S , \"inches|centimeters|normalized|{points}|pixels\"\n      radio_property fontweight u , \"{normal}|bold\"\n      color_property foregroundcolor , color_values (0, 0, 0)\n      radio_property horizontalalignment , \"left|{center}|right\"\n      callback_property keypressfcn , Matrix ()\n      double_property listboxtop , 1\n      double_property max , 1\n      double_property min , 0\n      array_property position , default_control_position ()\n      array_property sliderstep , default_control_sliderstep ()\n      string_array_property string u , \"\"\n      radio_property style S , \"{pushbutton}|togglebutton|radiobutton|checkbox|edit|text|slider|frame|listbox|popupmenu\"\n      string_property tooltipstring , \"\"\n      radio_property units u , \"normalized|inches|centimeters|points|{pixels}|characters\"\n      row_vector_property value , Matrix (1, 1, 0.0)\n      radio_property verticalalignment , \"top|{middle}|bottom\"\n\n      // Octave-specific properties\n      bool_property __focus__ h , \"off\"\n      any_property __object__ h , Matrix ()\n    END_PROPERTIES\n\n  private:\n    std::string m_cached_units;\n\n  protected:\n    void init ()\n    {\n      m_cdata.add_constraint (\"double\");\n      m_cdata.add_constraint (\"single\");\n      m_cdata.add_constraint (\"uint8\");\n      m_cdata.add_constraint (dim_vector (-1, -1, 3));\n      m_cdata.add_constraint (dim_vector (0, 0));\n      m_position.add_constraint (dim_vector (1, 4));\n      m_sliderstep.add_constraint (dim_vector (1, 2));\n      m_fontsize.add_constraint (\"min\", 0.0, false);\n      m_cached_units = get_units ();\n    }\n\n    OCTINTERP_API void update_text_extent ();\n\n    void update_string () { update_text_extent (); }\n    void update_fontname () { update_text_extent (); }\n    void update_fontsize () { update_text_extent (); }\n    void update_fontangle ()\n    {\n      update_text_extent ();\n    }\n    void update_fontweight () { update_text_extent (); }\n\n    OCTINTERP_API void update_fontunits (const caseless_str& old_units);\n\n    OCTINTERP_API void update_units ();\n\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  uicontrol (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uicontrol)\n\n  ~uicontrol () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API uibuttongroup : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    OCTINTERP_API void\n    remove_child (const graphics_handle& h, bool from_root = false);\n\n    OCTINTERP_API void adopt (const graphics_handle& h);\n\n    OCTINTERP_API Matrix\n    get_boundingbox (bool internal = false,\n                     const Matrix& parent_pix_size = Matrix ()) const;\n\n    OCTINTERP_API double\n    get___fontsize_points__ (double box_pix_height = 0) const;\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (uibuttongroup)\n      color_property backgroundcolor , color_values (0.94, 0.94, 0.94)\n      radio_property bordertype , \"none|{etchedin}|etchedout|beveledin|beveledout|line\"\n      double_property borderwidth , 1\n      bool_property clipping , \"on\"\n      radio_property fontangle , \"{normal}|italic\"\n      string_property fontname , OCTAVE_DEFAULT_FONTNAME\n      double_property fontsize , 10\n      radio_property fontunits S , \"inches|centimeters|normalized|{points}|pixels\"\n      radio_property fontweight , \"{normal}|bold\"\n      color_property foregroundcolor , color_values (0, 0, 0)\n      color_property highlightcolor , color_values (1, 1, 1)\n      array_property position S , default_panel_position ()\n      // FIXME: \"resizefcn\" is no longer recommended by Matlab,\n      //        and has been replaced with \"sizechangedfcn\"\n      //        Eventually this will need to be hidden, and then removed.\n      callback_property resizefcn , Matrix ()\n      handle_property selectedobject S , graphics_handle ()\n      callback_property selectionchangedfcn , Matrix ()\n      color_property shadowcolor , color_values (0.7, 0.7, 0.7)\n      callback_property sizechangedfcn , Matrix ()\n      radio_property units S , \"{normalized}|inches|centimeters|points|pixels|characters\"\n      string_property title , \"\"\n      radio_property titleposition , \"{lefttop}|centertop|righttop|leftbottom|centerbottom|rightbottom\"\n\n      // Octave-specific properties\n      any_property __object__ h , Matrix ()\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_position.add_constraint (dim_vector (1, 4));\n      m_borderwidth.add_constraint (\"min\", 0.0, true);\n      m_fontsize.add_constraint (\"min\", 0.0, false);\n    }\n\n    // void update_text_extent ();\n    // void update_string () { update_text_extent (); }\n    // void update_fontname () { update_text_extent (); }\n    // void update_fontsize () { update_text_extent (); }\n    // void update_fontangle () { update_text_extent (); }\n    // void update_fontweight () { update_fontweight (); }\n\n    OCTINTERP_API void update_units (const caseless_str& old_units);\n    OCTINTERP_API void update_fontunits (const caseless_str& old_units);\n\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  uibuttongroup (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uibuttongroup)\n\n  ~uibuttongroup () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API uipanel : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    OCTINTERP_API Matrix\n    get_boundingbox (bool internal = false,\n                     const Matrix& parent_pix_size = Matrix ()) const;\n\n    OCTINTERP_API double\n    get___fontsize_points__ (double box_pix_height = 0) const;\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (uipanel)\n      color_property backgroundcolor , color_values (0.94, 0.94, 0.94)\n      radio_property bordertype , \"none|{etchedin}|etchedout|beveledin|beveledout|line\"\n      double_property borderwidth , 1\n      radio_property fontangle , \"{normal}|italic\"\n      string_property fontname , OCTAVE_DEFAULT_FONTNAME\n      double_property fontsize , 10\n      radio_property fontunits S , \"inches|centimeters|normalized|{points}|pixels\"\n      radio_property fontweight , \"{normal}|bold\"\n      color_property foregroundcolor , color_values (0, 0, 0)\n      color_property highlightcolor , color_values (1, 1, 1)\n      array_property position S , default_panel_position ()\n      // FIXME: \"resizefcn\" is no longer recommended by Matlab,\n      //        and has been replaced with \"sizechangedfcn\"\n      //        Eventually this will need to be hidden, and then removed.\n      callback_property resizefcn , Matrix ()\n      color_property shadowcolor , color_values (0.7, 0.7, 0.7)\n      callback_property sizechangedfcn , Matrix ()\n      string_property title , \"\"\n      radio_property titleposition , \"{lefttop}|centertop|righttop|leftbottom|centerbottom|rightbottom\"\n      radio_property units S , \"{normalized}|inches|centimeters|points|pixels|characters\"\n      // Octave-specific properties\n      any_property __object__ h , Matrix ()\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_borderwidth.add_constraint (\"min\", 0.0, true);\n      m_fontsize.add_constraint (\"min\", 0.0, false);\n      m_position.add_constraint (dim_vector (1, 4));\n    }\n\n    OCTINTERP_API void update_units (const caseless_str& old_units);\n    OCTINTERP_API void update_fontunits (const caseless_str& old_units);\n\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  uipanel (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uipanel)\n\n  ~uipanel () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API uitable : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    OCTINTERP_API Matrix\n    get_boundingbox (bool internal = false,\n                     const Matrix& parent_pix_size = Matrix ()) const;\n\n    OCTINTERP_API double\n    get___fontsize_points__ (double box_pix_height = 0) const;\n\n    OCTINTERP_API double\n    get_fontsize_pixels (double box_pix_height = 0) const;\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    // FIXME: keypressfcn, keyreleasefcn, rearrangeablecolumns properties\n    //        seem to have been removed from Matlab.\n\n    BEGIN_PROPERTIES (uitable)\n      any_property __object__ h , Matrix ()\n      array_property backgroundcolor , default_table_backgroundcolor ()\n      callback_property celleditcallback , Matrix ()\n      callback_property cellselectioncallback , Matrix ()\n      row_vector_property columneditable , Matrix ()\n      any_property columnformat S , Cell ()\n      any_property columnname , \"numbered\"\n      any_property columnwidth S , \"auto\"\n      any_property data S , Matrix ()\n      bool_property enable , \"on\"\n      array_property extent rG , Matrix (1, 4, 0.0)\n      radio_property fontangle u , \"{normal}|italic\"\n      string_property fontname u , OCTAVE_DEFAULT_FONTNAME\n      double_property fontsize u , 10\n      radio_property fontunits S , \"inches|centimeters|normalized|{points}|pixels\"\n      radio_property fontweight u , \"{normal}|bold\"\n      color_property foregroundcolor , color_values (0, 0, 0)\n      callback_property keypressfcn , Matrix ()\n      callback_property keyreleasefcn , Matrix ()\n      array_property position , default_table_position ()\n      bool_property rearrangeablecolumns , \"off\"\n      any_property rowname , \"numbered\"\n      bool_property rowstriping , \"on\"\n      string_property tooltipstring , \"\"\n      radio_property units S , \"normalized|inches|centimeters|points|{pixels}|characters\"\n    END_PROPERTIES\n\n    OCTINTERP_API Matrix get_extent_matrix () const;\n\n    OCTINTERP_API Matrix get_backgroundcolor_rgb ();\n\n    OCTINTERP_API Matrix get_alternatebackgroundcolor_rgb ();\n\n  protected:\n    void init ()\n    {\n      m_position.add_constraint (dim_vector (1, 4));\n      m_extent.add_constraint (dim_vector (1, 4));\n      m_backgroundcolor.add_constraint (\"double\");\n      m_backgroundcolor.add_constraint (dim_vector (-1, 3));\n      m_columneditable.add_constraint (\"logical\");\n    }\n\n    OCTINTERP_API void update_units (const caseless_str& old_units);\n    OCTINTERP_API void update_fontunits (const caseless_str& old_units);\n    void update_table_extent () { }\n    void update_fontname () { update_table_extent (); }\n    void update_fontsize () { update_table_extent (); }\n    void update_fontangle () { update_table_extent (); }\n    void update_fontweight () { update_table_extent (); }\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  uitable (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uitable)\n\n  ~uitable () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API uitoolbar : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (uitoolbar)\n      // Octave-specific properties\n      any_property __object__ h , Matrix ()\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    { }\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  uitoolbar (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p), m_default_properties ()\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uitoolbar)\n\n  ~uitoolbar () = default;\n\n  void override_defaults (base_graphics_object& obj)\n  {\n    // Allow parent (figure) to override first (properties knows how\n    // to find the parent object).\n    m_properties.override_defaults (obj);\n\n    // Now override with our defaults.  If the default_properties\n    // list includes the properties for all defaults (line,\n    // surface, etc.) then we don't have to know the type of OBJ\n    // here, we just call its set function and let it decide which\n    // properties from the list to use.\n    obj.set_from_list (m_default_properties);\n  }\n\n  void set (const caseless_str& name, const octave_value& value)\n  {\n    if (name.compare (\"default\", 7))\n      // strip \"default\", pass rest to function that will\n      // parse the remainder and add the element to the\n      // default_properties map.\n      m_default_properties.set (name.substr (7), value);\n    else\n      m_properties.set (name, value);\n  }\n\n  octave_value get (const caseless_str& name) const\n  {\n    octave_value retval;\n\n    if (name.compare (\"default\", 7))\n      retval = get_default (name.substr (7));\n    else\n      retval = m_properties.get (name);\n\n    return retval;\n  }\n\n  OCTINTERP_API octave_value get_default (const caseless_str& name) const;\n\n  octave_value get_defaults () const\n  {\n    return m_default_properties.as_struct (\"default\");\n  }\n\n  property_list get_defaults_list () const\n  {\n    return m_default_properties;\n  }\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  OCTINTERP_API void reset_default_properties ();\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\nprivate:\n  property_list m_default_properties;\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API uipushtool : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (uipushtool)\n      array_property cdata , Matrix ()\n      callback_property clickedcallback , Matrix ()\n      bool_property enable , \"on\"\n      bool_property separator , \"off\"\n      string_property tooltipstring , \"\"\n\n      // Octave-specific properties\n      string_property __named_icon__ , \"\"\n      any_property __object__ h , Matrix ()\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_cdata.add_constraint (\"double\");\n      m_cdata.add_constraint (\"single\");\n      m_cdata.add_constraint (\"uint8\");\n      m_cdata.add_constraint (dim_vector (-1, -1, 3));\n      m_cdata.add_constraint (dim_vector (0, 0));\n    }\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  uipushtool (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uipushtool)\n\n  ~uipushtool () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\n};\n\n// ---------------------------------------------------------------------\n\nclass OCTINTERP_API uitoggletool : public base_graphics_object\n{\npublic:\n\n  class OCTINTERP_API properties : public base_properties\n  {\n  public:\n\n    // See the genprops.awk script for an explanation of the\n    // properties declarations.\n    // Programming note: Keep property list sorted if new ones are added.\n\n    BEGIN_PROPERTIES (uitoggletool)\n      array_property cdata , Matrix ()\n      callback_property clickedcallback , Matrix ()\n      bool_property enable , \"on\"\n      callback_property offcallback , Matrix ()\n      callback_property oncallback , Matrix ()\n      bool_property separator , \"off\"\n      bool_property state , \"off\"\n      string_property tooltipstring , \"\"\n\n      // Octave-specific properties\n      string_property __named_icon__ , \"\"\n      any_property __object__ h , Matrix ()\n    END_PROPERTIES\n\n  protected:\n    void init ()\n    {\n      m_cdata.add_constraint (\"double\");\n      m_cdata.add_constraint (\"single\");\n      m_cdata.add_constraint (\"uint8\");\n      m_cdata.add_constraint (dim_vector (-1, -1, 3));\n      m_cdata.add_constraint (dim_vector (0, 0));\n    }\n  };\n\nprivate:\n  properties m_properties;\n\npublic:\n  uitoggletool (const graphics_handle& mh, const graphics_handle& p)\n    : base_graphics_object (), m_properties (mh, p)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uitoggletool)\n\n  ~uitoggletool () = default;\n\n  base_properties& get_properties () { return m_properties; }\n\n  const base_properties& get_properties () const { return m_properties; }\n\n  bool valid_object () const { return true; }\n\n  bool has_readonly_property (const caseless_str& pname) const\n  {\n    bool retval = m_properties.has_readonly_property (pname);\n    if (! retval)\n      retval = base_properties::has_readonly_property (pname);\n    return retval;\n  }\n\n};\n\n// ---------------------------------------------------------------------\n\nOCTINTERP_API octave_value\nget_property_from_handle (double handle, const std::string& property,\n                          const std::string& fcn);\nOCTINTERP_API bool\nset_property_in_handle (double handle, const std::string& property,\n                        const octave_value& arg, const std::string& fcn);\n\n// ---------------------------------------------------------------------\n\nclass graphics_event;\n\nclass OCTINTERP_API base_graphics_event\n{\npublic:\n  enum priority { INTERRUPT, QUEUE, CANCEL };\n\n  friend class graphics_event;\n\n  base_graphics_event ()\n    : m_busyaction (QUEUE)\n  { }\n\n  base_graphics_event (int busyaction)\n    : m_busyaction (busyaction)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE (base_graphics_event)\n\n  virtual ~base_graphics_event () = default;\n\n  int get_busyaction () { return m_busyaction; }\n\n  virtual void execute () = 0;\n\nprivate:\n  int m_busyaction;\n};\n\nclass OCTINTERP_API graphics_event\n{\npublic:\n\n  typedef void (*event_fcn) (void *);\n\n  graphics_event () = default;\n\n  graphics_event (base_graphics_event *new_rep) : m_rep (new_rep) { }\n\n  graphics_event (const graphics_event&) = default;\n\n  ~graphics_event () = default;\n\n  graphics_event& operator = (const graphics_event&) = default;\n\n  int get_busyaction ()\n  {\n    if (ok ())\n      return m_rep->get_busyaction ();\n    else\n      error (\"graphics_event::busyaction: invalid graphics_event\");\n  }\n\n  void execute ()\n  {\n    if (ok ())\n      m_rep->execute ();\n  }\n\n  bool ok () const { return (m_rep != nullptr); }\n\n  static OCTINTERP_API graphics_event\n  create_callback_event (const graphics_handle& h,\n                         const std::string& name,\n                         const octave_value& data = Matrix (),\n                         int busyaction = base_graphics_event::QUEUE);\n\n  static OCTINTERP_API graphics_event\n  create_callback_event (const graphics_handle& h,\n                         const octave_value& cb,\n                         const octave_value& data = Matrix (),\n                         int busyaction = base_graphics_event::QUEUE);\n\n  static OCTINTERP_API graphics_event\n  create_mcode_event (const graphics_handle& h, const std::string& cmd,\n                      int busyaction);\n\n  static OCTINTERP_API graphics_event\n  create_function_event (event_fcn fcn, void *data = nullptr);\n\n  static OCTINTERP_API graphics_event\n  create_set_event (const graphics_handle& h, const std::string& name,\n                    const octave_value& value, bool notify_toolkit = true,\n                    bool redraw_figure = false);\nprivate:\n\n  std::shared_ptr<base_graphics_event> m_rep;\n};\n\nOCTINTERP_API base_graphics_object *\nmake_graphics_object_from_type (const caseless_str& type,\n                                const graphics_handle& h = graphics_handle (),\n                                const graphics_handle& p = graphics_handle ());\n\nOCTINTERP_API void\nget_children_limits (double& min_val, double& max_val,\n                     double& min_pos, double& max_neg,\n                     const Matrix& kids, char limit_type);\n\nOCTINTERP_API int calc_dimensions (const graphics_object& gh);\n\n// This function is NOT equivalent to the scripting language function gcf.\nOCTINTERP_API graphics_handle gcf ();\n\n// This function is NOT equivalent to the scripting language function gca.\nOCTINTERP_API graphics_handle gca ();\n\nOCTINTERP_API void close_all_figures ();\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/gtk-manager.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"interpreter.h\"\n#include \"graphics-toolkit.h\"\n#include \"gtk-manager.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ngraphics_toolkit\ngtk_manager::get_toolkit () const\n{\n  graphics_toolkit retval;\n\n  if (m_dtk.empty ())\n    error (\"no graphics toolkits are available!\");\n\n  auto pl = m_loaded_toolkits.find (m_dtk);\n\n  if (pl == m_loaded_toolkits.end ())\n    {\n      auto pa = m_available_toolkits.find (m_dtk);\n\n      if (pa == m_available_toolkits.end ())\n        error (\"default graphics toolkit '%s' is not available!\",\n               m_dtk.c_str ());\n\n      octave_value_list args;\n      args(0) = m_dtk;\n      m_interpreter.feval (\"graphics_toolkit\", args);\n\n      pl = m_loaded_toolkits.find (m_dtk);\n\n      if (pl == m_loaded_toolkits.end ())\n        error (\"failed to load %s graphics toolkit\", m_dtk.c_str ());\n\n      retval = pl->second;\n    }\n  else\n    retval = pl->second;\n\n  return retval;\n}\n\nvoid\ngtk_manager::register_toolkit (const std::string& name)\n{\n  if (m_dtk.empty () || name == \"qt\"\n      || (name == \"fltk\"\n          && m_available_toolkits.find (\"qt\") == m_available_toolkits.end ()))\n    m_dtk = name;\n\n  m_available_toolkits.insert (name);\n}\n\nvoid\ngtk_manager::unregister_toolkit (const std::string& name)\n{\n  m_available_toolkits.erase (name);\n\n  if (m_dtk == name)\n    {\n      if (m_available_toolkits.empty ())\n        m_dtk.clear ();\n      else\n        {\n          auto pa = m_available_toolkits.cbegin ();\n\n          m_dtk = *pa++;\n\n          while (pa != m_available_toolkits.cend ())\n            {\n              std::string tk_name = *pa++;\n\n              if (tk_name == \"qt\"\n                  || (tk_name == \"fltk\"\n                      && (m_available_toolkits.find (\"qt\")\n                          == m_available_toolkits.cend ())))\n                m_dtk = tk_name;\n            }\n        }\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/gtk-manager.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gtk_manager_h)\n#define octave_gtk_manager_h 1\n\n#include \"octave-config.h\"\n\n#include <map>\n#include <set>\n#include <string>\n\n#include \"Cell.h\"\n#include \"graphics-toolkit.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass OCTINTERP_API gtk_manager\n{\npublic:\n\n  gtk_manager (interpreter& interp) : m_interpreter (interp) { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (gtk_manager)\n\n  ~gtk_manager ()\n  {\n    unload_all_toolkits ();\n  }\n\n  graphics_toolkit get_toolkit () const;\n\n  void register_toolkit (const std::string& name);\n\n  void unregister_toolkit (const std::string& name);\n\n  void load_toolkit (const graphics_toolkit& tk)\n  {\n    m_loaded_toolkits[tk.get_name ()] = tk;\n  }\n\n  void unload_toolkit (const std::string& name)\n  {\n    m_loaded_toolkits.erase (name);\n  }\n\n  graphics_toolkit find_toolkit (const std::string& name) const\n  {\n    auto p = m_loaded_toolkits.find (name);\n\n    if (p != m_loaded_toolkits.end ())\n      return p->second;\n    else\n      return graphics_toolkit ();\n  }\n\n  Cell available_toolkits_list () const\n  {\n    Cell m (1, m_available_toolkits.size ());\n\n    octave_idx_type i = 0;\n    for (const auto& tkit : m_available_toolkits)\n      m(i++) = tkit;\n\n    return m;\n  }\n\n  Cell loaded_toolkits_list () const\n  {\n    Cell m (1, m_loaded_toolkits.size ());\n\n    octave_idx_type i = 0;\n    for (const auto& nm_tkit_p : m_loaded_toolkits)\n      m(i++) = nm_tkit_p.first;\n\n    return m;\n  }\n\n  void unload_all_toolkits ()\n  {\n    while (! m_loaded_toolkits.empty ())\n      {\n        auto p = m_loaded_toolkits.begin ();\n\n        std::string name = p->first;\n\n        p->second.close ();\n\n        // The toolkit may have unloaded itself.  If not, we'll do it here.\n        if (m_loaded_toolkits.find (name) != m_loaded_toolkits.end ())\n          unload_toolkit (name);\n      }\n  }\n\n  std::string default_toolkit () const { return m_dtk; }\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  // The name of the default toolkit.\n  std::string m_dtk;\n\n  // The list of toolkits that we know about.\n  std::set<std::string> m_available_toolkits;\n\n  // The list of toolkits we have actually loaded.\n  std::map<std::string, graphics_toolkit> m_loaded_toolkits;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/gzfstream.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\n This file is adapted from the zlib 1.2.2 contrib/iostream3 code,\n written by\n\n   Ludwig Schwardt <schwardt@sun.ac.za>\n   original version by Kevin Ruland <kevin@rodin.wustl.edu>\n\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"gzfstream.h\"\n\n#if defined (HAVE_ZLIB)\n\n// For strcpy, strcat, strlen (mode strings).\n#include <cstring>\n// For BUFSIZ.\n#include <cstdio>\n\n#if defined (OCTAVE_USE_WINDOWS_API) && ! defined (OCTAVE_HAVE_WINDOWS_UTF8_LOCALE)\n#  include \"oct-string.h\"\n\n#  include \"error.h\"\n#endif\n\n// Internal buffer sizes (default and \"unbuffered\" versions)\n#define STASHED_CHARACTERS 16\n#define BIGBUFSIZE (256 * 1024 + STASHED_CHARACTERS)\n#define SMALLBUFSIZE 1\n\n// Default constructor\ngzfilebuf::gzfilebuf ()\n  : m_file(nullptr), m_io_mode(std::ios_base::openmode(0)), m_own_fd(false),\n    m_buffer(nullptr), m_buffer_size(BIGBUFSIZE), m_own_buffer(true)\n{\n  // No buffers to start with\n  this->disable_buffer ();\n}\n\n// Destructor\ngzfilebuf::~gzfilebuf ()\n{\n  // Sync output buffer and close only if responsible for file\n  // (i.e., attached streams should be left open at this stage)\n  this->sync ();\n  if (m_own_fd)\n    this->close ();\n  // Make sure internal buffer is deallocated\n  this->disable_buffer ();\n}\n\n// Set compression level and strategy\nint\ngzfilebuf::setcompression (int comp_level, int comp_strategy)\n{\n  return gzsetparams (m_file, comp_level, comp_strategy);\n}\n\n// Open gzipped file\ngzfilebuf *\ngzfilebuf::open (const char *name, std::ios_base::openmode mode)\n{\n  // Fail if file already open\n  if (this->is_open ())\n    return nullptr;\n  // Don't support simultaneous read/write access (yet)\n  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))\n    return nullptr;\n\n  // Build mode string for gzopen and check it [27.8.1.3.2]\n  char char_mode[6] = \"\\0\\0\\0\\0\\0\";\n  if (! this->open_mode (mode, char_mode))\n    return nullptr;\n\n#if defined (OCTAVE_USE_WINDOWS_API) && ! defined (OCTAVE_HAVE_WINDOWS_UTF8_LOCALE)\n  // Check for any non-ASCII characters on Windows configurations that don't\n  // support UTF-8.\n  // FIXME: A potential (but brittle) work-around could be to open a stream to\n  //        a temporary file with only ASCII characters in its path and move\n  //        that temporary file to the actual file after it has been closed.\n  //        That would not work when appending to existing files though.\n  if (octave::string::any_non_ascii_chars (name))\n    error (\"zlib: cannot open gzip-compressed file %s with non-ASCII characters in its name\",\n           name);\n#endif\n\n  // Attempt to open file\n  if ((m_file = gzopen (name, char_mode)) == nullptr)\n    return nullptr;\n\n  // On success, allocate internal buffer and set flags\n  this->enable_buffer ();\n  m_io_mode = mode;\n  m_own_fd = true;\n  return this;\n}\n\n// Attach to gzipped file\ngzfilebuf *\ngzfilebuf::attach (int fd, std::ios_base::openmode mode)\n{\n  // Fail if file already open\n  if (this->is_open ())\n    return nullptr;\n  // Don't support simultaneous read/write access (yet)\n  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))\n    return nullptr;\n\n  // Build mode string for gzdopen and check it [27.8.1.3.2]\n  char char_mode[6] = \"\\0\\0\\0\\0\\0\";\n  if (! this->open_mode (mode, char_mode))\n    return nullptr;\n\n  // Attempt to attach to file\n  if ((m_file = gzdopen (fd, char_mode)) == nullptr)\n    return nullptr;\n\n  // On success, allocate internal buffer and set flags\n  this->enable_buffer ();\n  m_io_mode = mode;\n  m_own_fd = false;\n  return this;\n}\n\n// Close gzipped file\ngzfilebuf *\ngzfilebuf::close ()\n{\n  // Fail immediately if no file is open\n  if (! this->is_open ())\n    return nullptr;\n  // Assume success\n  gzfilebuf *retval = this;\n  // Attempt to sync and close gzipped file\n  if (this->sync () == -1)\n    retval = nullptr;\n  if (gzclose (m_file) < 0)\n    retval = nullptr;\n  // File is now gone anyway (postcondition [27.8.1.3.8])\n  m_file = nullptr;\n  m_own_fd = false;\n  // Destroy internal buffer if it exists\n  this->disable_buffer ();\n  return retval;\n}\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n// Convert int open mode to mode string\nbool\ngzfilebuf::open_mode (std::ios_base::openmode mode, char *c_mode) const\n{\n  // FIXME: do we need testb?\n  // bool testb = mode & std::ios_base::binary;\n  bool testi = mode & std::ios_base::in;\n  bool testo = mode & std::ios_base::out;\n  bool testt = mode & std::ios_base::trunc;\n  bool testa = mode & std::ios_base::app;\n\n  // Check for valid flag combinations - see [27.8.1.3.2] (Table 92)\n  // Original zfstream hardcoded the compression level to maximum here...\n  // Double the time for less than 1% size improvement seems\n  // excessive though - keeping it at the default level\n  // To change back, just append \"9\" to the next three mode strings\n  if (! testi && testo && ! testt && ! testa)\n    strcpy (c_mode, \"w\");\n  if (! testi && testo && ! testt && testa)\n    strcpy (c_mode, \"a\");\n  if (! testi && testo && testt && ! testa)\n    strcpy (c_mode, \"w\");\n  if (testi && ! testo && ! testt && ! testa)\n    strcpy (c_mode, \"r\");\n  // No read/write mode yet\n  //  if (testi && testo && ! testt && ! testa)\n  //    strcpy(c_mode, \"r+\");\n  //  if (testi && testo && testt && ! testa)\n  //    strcpy(c_mode, \"w+\");\n\n  // Mode string should be empty for invalid combination of flags\n  if (strlen (c_mode) == 0)\n    return false;\n\n  strcat (c_mode, \"b\");\n\n  return true;\n}\n\n// Determine number of characters in internal get buffer\nstd::streamsize\ngzfilebuf::showmanyc ()\n{\n  // Calls to underflow will fail if file not opened for reading\n  if (! this->is_open () || ! (m_io_mode & std::ios_base::in))\n    return -1;\n  // Make sure get area is in use\n  if (this->gptr () && (this->gptr () < this->egptr ()))\n    return std::streamsize (this->egptr () - this->gptr ());\n  else\n    return 0;\n}\n\n// Puts back a character to the stream in two cases.  Firstly, when there\n// is no putback position available, and secondly when the character putback\n// differs from the one in the file.  We can only support the first case\n// with gzipped files.\ngzfilebuf::int_type\ngzfilebuf::pbackfail (gzfilebuf::int_type c)\n{\n  if (this->is_open ())\n    {\n      if (gzseek (m_file, this->gptr () - this->egptr () - 1, SEEK_CUR) < 0)\n        return traits_type::eof ();\n\n      // Invalidates contents of the buffer\n      enable_buffer ();\n\n      // Attempt to fill internal buffer from gzipped file\n      // (buffer must be guaranteed to exist...)\n      int bytes_read = gzread (m_file, m_buffer, m_buffer_size);\n      // Indicates error or EOF\n      if (bytes_read <= 0)\n        {\n          // Reset get area\n          this->setg (m_buffer, m_buffer, m_buffer);\n          return traits_type::eof ();\n        }\n\n      // Make all bytes read from file available as get area\n      this->setg (m_buffer, m_buffer, m_buffer + bytes_read);\n\n      // If next character in get area differs from putback character\n      // flag a failure\n      gzfilebuf::int_type ret = traits_type::to_int_type (*(this->gptr ()));\n      if (ret != c)\n        return traits_type::eof ();\n      else\n        return ret;\n    }\n  else\n    return traits_type::eof ();\n}\n\n// Fill get area from gzipped file\ngzfilebuf::int_type\ngzfilebuf::underflow ()\n{\n  // If something is left in the get area by chance, return it\n  // (this shouldn't normally happen, as underflow is only supposed\n  // to be called when gptr >= egptr, but it serves as error check)\n  if (this->gptr () && (this->gptr () < this->egptr ()))\n    return traits_type::to_int_type (*(this->gptr ()));\n\n  // If the file hasn't been opened for reading, produce error\n  if (! this->is_open () || ! (m_io_mode & std::ios_base::in))\n    return traits_type::eof ();\n\n  // Copy the final characters to the front of the buffer\n  int stash = 0;\n  if (this->eback () && m_buffer && m_buffer_size > STASHED_CHARACTERS)\n    {\n      char_type *ptr1 = m_buffer;\n      char_type *ptr2 = this->egptr () - STASHED_CHARACTERS + 1;\n      if (ptr2 > this->eback ())\n        while (stash++ <= STASHED_CHARACTERS)\n          *ptr1++ = *ptr2++;\n    }\n\n  // Attempt to fill internal buffer from gzipped file\n  // (buffer must be guaranteed to exist...)\n  int bytes_read = gzread (m_file, m_buffer + stash, m_buffer_size - stash);\n\n  // Indicates error or EOF\n  if (bytes_read <= 0)\n    {\n      // Reset get area\n      this->setg (m_buffer, m_buffer, m_buffer);\n      return traits_type::eof ();\n    }\n  // Make all bytes read from file plus the stash available as get area\n  this->setg (m_buffer, m_buffer + stash, m_buffer + bytes_read + stash);\n\n  // Return next character in get area\n  return traits_type::to_int_type (*(this->gptr ()));\n}\n\n// Write put area to gzipped file\ngzfilebuf::int_type\ngzfilebuf::overflow (int_type c)\n{\n  // Determine whether put area is in use\n  if (this->pbase ())\n    {\n      // Double-check pointer range\n      if (this->pptr () > this->epptr () || this->pptr () < this->pbase ())\n        return traits_type::eof ();\n      // Add extra character to buffer if not EOF\n      if (! traits_type::eq_int_type (c, traits_type::eof ()))\n        {\n          *(this->pptr ()) = traits_type::to_char_type (c);\n          this->pbump (1);\n        }\n      // Number of characters to write to file\n      int bytes_to_write = this->pptr () - this->pbase ();\n      // Overflow doesn't fail if nothing is to be written\n      if (bytes_to_write > 0)\n        {\n          // If the file hasn't been opened for writing, produce error\n          if (! this->is_open () || ! (m_io_mode & std::ios_base::out))\n            return traits_type::eof ();\n          // If gzipped file won't accept all bytes written to it, fail\n          if (gzwrite (m_file, this->pbase (), bytes_to_write)\n              != bytes_to_write)\n            return traits_type::eof ();\n          // Reset next pointer to point to pbase on success\n          this->pbump (-bytes_to_write);\n        }\n    }\n  // Write extra character to file if not EOF\n  else if (! traits_type::eq_int_type (c, traits_type::eof ()))\n    {\n      // If the file hasn't been opened for writing, produce error\n      if (! this->is_open () || ! (m_io_mode & std::ios_base::out))\n        return traits_type::eof ();\n      // Impromptu char buffer (allows \"unbuffered\" output)\n      char_type last_char = traits_type::to_char_type (c);\n      // If gzipped file won't accept this character, fail\n      if (gzwrite (m_file, &last_char, 1) != 1)\n        return traits_type::eof ();\n    }\n\n  // If you got here, you have succeeded (even if c was EOF)\n  // The return value should therefore be non-EOF\n  if (traits_type::eq_int_type (c, traits_type::eof ()))\n    return traits_type::not_eof (c);\n  else\n    return c;\n}\n\n// Assign new buffer\nstd::streambuf *\ngzfilebuf::setbuf (char_type *p, std::streamsize n)\n{\n  // First make sure stuff is sync'ed, for safety\n  if (this->sync () == -1)\n    return nullptr;\n  // If buffering is turned off on purpose via setbuf(0,0), still allocate one.\n  // \"Unbuffered\" only really refers to put [27.8.1.4.10], while get needs at\n  // least a buffer of size 1 (very inefficient though, therefore make it\n  // bigger?).  This follows from [27.5.2.4.3]/12 (gptr needs to point at\n  // something, it seems).\n  if (! p || ! n)\n    {\n      // Replace existing buffer (if any) with small internal buffer\n      this->disable_buffer ();\n      m_buffer = nullptr;\n      m_buffer_size = 0;\n      m_own_buffer = true;\n      this->enable_buffer ();\n    }\n  else\n    {\n      // Replace existing buffer (if any) with external buffer\n      this->disable_buffer ();\n      m_buffer = p;\n      m_buffer_size = n;\n      m_own_buffer = false;\n      this->enable_buffer ();\n    }\n  return this;\n}\n\n// Write put area to gzipped file (i.e., ensures that put area is empty)\nint\ngzfilebuf::sync ()\n{\n  return traits_type::eq_int_type (this->overflow (),\n                                   traits_type::eof ()) ? -1 : 0;\n}\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n// Allocate internal buffer\nvoid\ngzfilebuf::enable_buffer ()\n{\n  // If internal buffer required, allocate one\n  if (m_own_buffer && ! m_buffer)\n    {\n      // Check for buffered vs. \"unbuffered\"\n      if (m_buffer_size > 0)\n        {\n          // Allocate internal buffer\n          m_buffer = new char_type [m_buffer_size];\n          // Get area starts empty and will be expanded by underflow as needed\n          this->setg (m_buffer, m_buffer, m_buffer);\n          // Setup entire internal buffer as put area.\n          // The one-past-end pointer actually points to the last element of\n          // the buffer, so that overflow(c) can safely add the extra character\n          // c to the sequence.  These pointers remain in place for the\n          // duration of the buffer\n          this->setp (m_buffer, m_buffer + m_buffer_size - 1);\n        }\n      else\n        {\n          // Even in \"unbuffered\" case, (small?) get buffer is still required\n          m_buffer_size = SMALLBUFSIZE;\n          m_buffer = new char_type [m_buffer_size];\n          this->setg (m_buffer, m_buffer, m_buffer);\n          // \"Unbuffered\" means no put buffer\n          this->setp (nullptr, nullptr);\n        }\n    }\n  else\n    {\n      // If buffer already allocated, reset buffer pointers just to make sure no\n      // stale chars are lying around\n      this->setg (m_buffer, m_buffer, m_buffer);\n      this->setp (m_buffer, m_buffer + m_buffer_size - 1);\n    }\n}\n\n// Destroy internal buffer\nvoid\ngzfilebuf::disable_buffer ()\n{\n  // If internal buffer exists, deallocate it\n  if (m_own_buffer && m_buffer)\n    {\n      // Preserve unbuffered status by zeroing size\n      if (! this->pbase ())\n        m_buffer_size = 0;\n      delete [] m_buffer;\n      m_buffer = nullptr;\n      this->setg (nullptr, nullptr, nullptr);\n      this->setp (nullptr, nullptr);\n    }\n  else\n    {\n      // Reset buffer pointers to initial state if external buffer exists\n      this->setg (m_buffer, m_buffer, m_buffer);\n      if (m_buffer)\n        this->setp (m_buffer, m_buffer + m_buffer_size - 1);\n      else\n        this->setp (nullptr, nullptr);\n    }\n}\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n// Seek functions\ngzfilebuf::pos_type\ngzfilebuf::seekoff (off_type off, std::ios_base::seekdir way,\n                    std::ios_base::openmode)\n{\n  pos_type ret = pos_type (off_type (-1));\n\n  if (this->is_open ())\n    {\n      off_type computed_off = off;\n\n      if ((m_io_mode & std::ios_base::in) && way == std::ios_base::cur)\n        computed_off += this->gptr () - this->egptr ();\n\n      // Handle tellg/tellp as a special case up front, no need to seek\n      // or invalidate get/put buffers\n      if (off == 0 && way == std::ios_base::cur)\n        return pos_type (gztell (m_file) + computed_off);\n\n      if (way == std::ios_base::beg)\n        ret = pos_type (gzseek (m_file, computed_off, SEEK_SET));\n      else if (way == std::ios_base::cur)\n        ret = pos_type (gzseek (m_file, computed_off, SEEK_CUR));\n      else\n        // Can't seek from end of a gzipped file, so this will give -1\n        ret = pos_type (gzseek (m_file, computed_off, SEEK_END));\n\n      if (m_io_mode & std::ios_base::in)\n        // Invalidates contents of the buffer\n        enable_buffer ();\n      else\n        // flush contents of buffer to file\n        overflow ();\n    }\n\n  return ret;\n}\n\ngzfilebuf::pos_type\ngzfilebuf::seekpos (pos_type sp, std::ios_base::openmode)\n{\n  pos_type ret = pos_type (off_type (-1));\n\n  if (this->is_open ())\n    {\n      ret = pos_type (gzseek (m_file, sp, SEEK_SET));\n\n      if (m_io_mode & std::ios_base::in)\n        // Invalidates contents of the buffer\n        enable_buffer ();\n      else\n        // flush contents of buffer to file\n        overflow ();\n    }\n\n  return ret;\n}\n\n// Default constructor initializes stream buffer\ngzifstream::gzifstream ()\n  : std::istream (nullptr), m_sb ()\n{ this->init (&m_sb); }\n\n// Initialize stream buffer and open file\ngzifstream::gzifstream (const char *name, std::ios_base::openmode mode)\n  : std::istream (nullptr), m_sb ()\n{\n  this->init (&m_sb);\n  this->open (name, mode);\n}\n\n// Initialize stream buffer and attach to file\ngzifstream::gzifstream (int fd, std::ios_base::openmode mode)\n  : std::istream (nullptr), m_sb ()\n{\n  this->init (&m_sb);\n  this->attach (fd, mode);\n}\n\n// Open file and go into fail() state if unsuccessful\nvoid\ngzifstream::open (const char *name, std::ios_base::openmode mode)\n{\n  if (! m_sb.open (name, mode | std::ios_base::in))\n    this->setstate (std::ios_base::failbit);\n  else\n    this->clear ();\n}\n\n// Attach to file and go into fail() state if unsuccessful\nvoid\ngzifstream::attach (int fd, std::ios_base::openmode mode)\n{\n  if (! m_sb.attach (fd, mode | std::ios_base::in))\n    this->setstate (std::ios_base::failbit);\n  else\n    this->clear ();\n}\n\n// Close file\nvoid\ngzifstream::close ()\n{\n  if (! m_sb.close ())\n    this->setstate (std::ios_base::failbit);\n}\n\n// Default constructor initializes stream buffer\ngzofstream::gzofstream ()\n  : std::ostream (nullptr), m_sb ()\n{ this->init (&m_sb); }\n\n// Initialize stream buffer and open file\ngzofstream::gzofstream (const char *name, std::ios_base::openmode mode)\n  : std::ostream (nullptr), m_sb ()\n{\n  this->init (&m_sb);\n  this->open (name, mode);\n}\n\n// Initialize stream buffer and attach to file\ngzofstream::gzofstream (int fd, std::ios_base::openmode mode)\n  : std::ostream (nullptr), m_sb ()\n{\n  this->init (&m_sb);\n  this->attach (fd, mode);\n}\n\n// Open file and go into fail() state if unsuccessful\nvoid\ngzofstream::open (const char *name, std::ios_base::openmode mode)\n{\n  if (! m_sb.open (name, mode | std::ios_base::out))\n    this->setstate (std::ios_base::failbit);\n  else\n    this->clear ();\n}\n\n// Attach to file and go into fail() state if unsuccessful\nvoid\ngzofstream::attach (int fd, std::ios_base::openmode mode)\n{\n  if (! m_sb.attach (fd, mode | std::ios_base::out))\n    this->setstate (std::ios_base::failbit);\n  else\n    this->clear ();\n}\n\n// Close file\nvoid\ngzofstream::close ()\n{\n  if (! m_sb.close ())\n    this->setstate (std::ios_base::failbit);\n}\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/gzfstream.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\n This file is adapted from the zlib 1.2.2 contrib/iostream3 code,\n written by\n\n   Ludwig Schwardt <schwardt@sun.ac.za>\n   original version by Kevin Ruland <kevin@rodin.wustl.edu>\n\n*/\n\n#if ! defined (octave_zfsstream_h)\n#define octave_zfsstream_h 1\n\n#include \"octave-config.h\"\n\n#if defined (HAVE_ZLIB)\n\n#include <iosfwd>\n\n#include \"zlib.h\"\n\n/**\n *  @brief  Gzipped file stream buffer class.\n *\n *  This class implements basic_filebuf for gzipped files.  It doesn't yet\n *  support seeking (allowed by zlib but slow/limited), putback and read/write\n *  access *  (tricky).  Otherwise, it attempts to be a drop-in replacement for\n *  the standard file streambuf.\n*/\nclass gzfilebuf : public std::streambuf\n{\npublic:\n  //  Default constructor.\n  gzfilebuf ();\n\n  OCTAVE_DISABLE_COPY_MOVE (gzfilebuf)\n\n  //  Destructor.\n  virtual ~gzfilebuf ();\n\n  /**\n   *  @brief  Set compression level and strategy on the fly.\n   *  @param  comp_level  Compression level (see zlib.h for allowed values)\n   *  @param  comp_strategy  Compression strategy (see zlib.h for allowed values)\n   *  @return  Z_OK on success, Z_STREAM_ERROR otherwise.\n   *\n   *  Unfortunately, these parameters cannot be modified separately, as the\n   *  previous zfstream version assumed.  Since the strategy is seldom changed,\n   *  it can default and setcompression(level) then becomes like the old\n   *  setcompressionlevel(level).\n  */\n  int\n  setcompression (int comp_level,\n                  int comp_strategy = Z_DEFAULT_STRATEGY);\n\n  /**\n   *  @brief  Check if file is open.\n   *  @return  True if file is open.\n  */\n  bool\n  is_open () const { return (m_file != nullptr); }\n\n  /**\n   *  @brief  Open gzipped file.\n   *  @param  name  Filename.\n   *  @param  mode  Open mode flags.\n   *  @return  @c this on success, NULL on failure.\n  */\n  gzfilebuf *\n  open (const char *name,\n        std::ios_base::openmode mode);\n\n  /**\n   *  @brief  Attach to already open gzipped file.\n   *  @param  fd  File descriptor.\n   *  @param  mode  Open mode flags.\n   *  @return  @c this on success, NULL on failure.\n  */\n  gzfilebuf *\n  attach (int fd,\n          std::ios_base::openmode mode);\n\n  /**\n   *  @brief  Close gzipped file.\n   *  @return  @c this on success, NULL on failure.\n  */\n  gzfilebuf *\n  close ();\n\nprotected:\n  /**\n   *  @brief  Convert ios open mode int to mode string used by zlib.\n   *  @return  True if valid mode flag combination.\n  */\n  bool\n  open_mode (std::ios_base::openmode mode,\n             char *c_mode) const;\n\n  /**\n   *  @brief  Number of characters available in stream buffer.\n   *  @return  Number of characters.\n   *\n   *  This indicates number of characters in get area of stream buffer.\n   *  These characters can be read without accessing the gzipped file.\n  */\n  virtual std::streamsize\n  showmanyc ();\n\n  /**\n   *  @brief  Fill get area from gzipped file.\n   *  @return  First character in get area on success, EOF on error.\n   *\n   *  This actually reads characters from gzipped file to stream\n   *  buffer.  Always buffered.\n  */\n  virtual int_type\n  underflow ();\n\n  /**\n   *  @brief  Write put area to gzipped file.\n   *  @param  c  Extra character to add to buffer contents.\n   *  @return  Non-EOF on success, EOF on error.\n   *\n   *  This actually writes characters in stream buffer to\n   *  gzipped file.  With unbuffered output this is done one\n   *  character at a time.\n  */\n  virtual int_type\n  overflow (int_type c = traits_type::eof ());\n\n  /**\n   *  @brief  Installs external stream buffer.\n   *  @param  p  Pointer to char buffer.\n   *  @param  n  Size of external buffer.\n   *  @return  @c this on success, NULL on failure.\n   *\n   *  Call setbuf(0,0) to enable unbuffered output.\n  */\n  virtual std::streambuf *\n  setbuf (char_type *p,\n          std::streamsize n);\n\n  /**\n   *  @brief  Flush stream buffer to file.\n   *  @return  0 on success, -1 on error.\n   *\n   *  This calls underflow(EOF) to do the job.\n  */\n  virtual int\n  sync ();\n\n  /**\n   *  @brief  Alters the stream positions.\n   *\n   *  Each derived class provides its own appropriate behavior.\n   */\n  virtual pos_type\n  seekoff (off_type off, std::ios_base::seekdir way,\n           std::ios_base::openmode mode =\n             std::ios_base::in | std::ios_base::out);\n\n  /**\n   *  @brief  Alters the stream positions.\n   *\n   *  Each derived class provides its own appropriate behavior.\n   */\n  virtual pos_type\n  seekpos (pos_type sp, std::ios_base::openmode mode =\n             std::ios_base::in | std::ios_base::out);\n\n  virtual int_type\n  pbackfail (int_type c = traits_type::eof ());\n\n//\n// Some future enhancements\n//\n//  virtual int_type uflow();\n//  virtual int_type pbackfail(int_type c = traits_type::eof());\n\nprivate:\n\n  /**\n   *  @brief  Allocate internal buffer.\n   *\n   *  This function is safe to call multiple times.  It will ensure\n   *  that a proper internal buffer exists if it is required.  If the\n   *  buffer already exists or is external, the buffer pointers will be\n   *  reset to their original state.\n  */\n  void\n  enable_buffer ();\n\n  /**\n   *  @brief  Destroy internal buffer.\n   *\n   *  This function is safe to call multiple times.  It will ensure\n   *  that the internal buffer is deallocated if it exists.  In any\n   *  case, it will also reset the buffer pointers.\n  */\n  void\n  disable_buffer ();\n\n  /**\n   *  Underlying file pointer.\n  */\n  gzFile m_file;\n\n  /**\n   *  Mode in which file was opened.\n  */\n  std::ios_base::openmode m_io_mode;\n\n  /**\n   *  @brief  True if this object owns file descriptor.\n   *\n   *  This makes the class responsible for closing the file\n   *  upon destruction.\n  */\n  bool m_own_fd;\n\n  /**\n   *  @brief  Stream buffer.\n   *\n   *  For simplicity this remains allocated on the free store for the\n   *  entire life span of the gzfilebuf object, unless replaced by setbuf.\n  */\n  char_type *m_buffer;\n\n  /**\n   *  @brief  Stream buffer size.\n   *\n   *  Defaults to system default buffer size (typically 8192 bytes).\n   *  Modified by setbuf.\n  */\n  std::streamsize m_buffer_size;\n\n  /**\n   *  @brief  True if this object owns stream buffer.\n   *\n   *  This makes the class responsible for deleting the buffer\n   *  upon destruction.\n  */\n  bool m_own_buffer;\n};\n\n/**\n *  @brief  Gzipped file input stream class.\n *\n *  This class implements ifstream for gzipped files.  Seeking and putback\n *  is not supported yet.\n*/\nclass gzifstream : public std::istream\n{\npublic:\n  //  Default constructor\n  gzifstream ();\n\n  /**\n   *  @brief  Construct stream on gzipped file to be opened.\n   *  @param  name  Filename.\n   *  @param  mode  Open mode flags (forced to contain ios::in).\n  */\n  explicit\n  gzifstream (const char *name,\n              std::ios_base::openmode mode = std::ios_base::in);\n\n  /**\n   *  @brief  Construct stream on already open gzipped file.\n   *  @param  fd    File descriptor.\n   *  @param  mode  Open mode flags (forced to contain ios::in).\n  */\n  explicit\n  gzifstream (int fd,\n              std::ios_base::openmode mode = std::ios_base::in);\n\n  /**\n   *  Obtain underlying stream buffer.\n  */\n  gzfilebuf *\n  rdbuf () const\n  { return const_cast<gzfilebuf *> (&m_sb); }\n\n  /**\n   *  @brief  Check if file is open.\n   *  @return  True if file is open.\n  */\n  bool\n  is_open () { return m_sb.is_open (); }\n\n  /**\n   *  @brief  Open gzipped file.\n   *  @param  name  Filename.\n   *  @param  mode  Open mode flags (forced to contain ios::in).\n   *\n   *  Stream will be in state good() if file opens successfully;\n   *  otherwise in state fail().  This differs from the behavior of\n   *  ifstream, which never sets the state to good() and therefore\n   *  won't allow you to reuse the stream for a second file unless\n   *  you manually clear() the state.  The choice is a matter of\n   *  convenience.\n  */\n  void\n  open (const char *name,\n        std::ios_base::openmode mode = std::ios_base::in);\n\n  /**\n   *  @brief  Attach to already open gzipped file.\n   *  @param  fd  File descriptor.\n   *  @param  mode  Open mode flags (forced to contain ios::in).\n   *\n   *  Stream will be in state good() if attach succeeded; otherwise\n   *  in state fail().\n  */\n  void\n  attach (int fd,\n          std::ios_base::openmode mode = std::ios_base::in);\n\n  /**\n   *  @brief  Close gzipped file.\n   *\n   *  Stream will be in state fail() if close failed.\n  */\n  void\n  close ();\n\nprivate:\n  /**\n   *  Underlying stream buffer.\n  */\n  gzfilebuf m_sb;\n};\n\n/**\n *  @brief  Gzipped file output stream class.\n *\n *  This class implements ofstream for gzipped files.  Seeking and putback\n *  is not supported yet.\n*/\nclass gzofstream : public std::ostream\n{\npublic:\n  //  Default constructor\n  gzofstream ();\n\n  /**\n   *  @brief  Construct stream on gzipped file to be opened.\n   *  @param  name  Filename.\n   *  @param  mode  Open mode flags (forced to contain ios::out).\n  */\n  explicit\n  gzofstream (const char *name,\n              std::ios_base::openmode mode = std::ios_base::out);\n\n  /**\n   *  @brief  Construct stream on already open gzipped file.\n   *  @param  fd    File descriptor.\n   *  @param  mode  Open mode flags (forced to contain ios::out).\n  */\n  explicit\n  gzofstream (int fd,\n              std::ios_base::openmode mode = std::ios_base::out);\n\n  /**\n   *  Obtain underlying stream buffer.\n  */\n  gzfilebuf *\n  rdbuf () const\n  { return const_cast<gzfilebuf *> (&m_sb); }\n\n  /**\n   *  @brief  Check if file is open.\n   *  @return  True if file is open.\n  */\n  bool\n  is_open () { return m_sb.is_open (); }\n\n  /**\n   *  @brief  Open gzipped file.\n   *  @param  name  Filename.\n   *  @param  mode  Open mode flags (forced to contain ios::out).\n   *\n   *  Stream will be in state good() if file opens successfully;\n   *  otherwise in state fail().  This differs from the behavior of\n   *  ofstream, which never sets the state to good() and therefore\n   *  won't allow you to reuse the stream for a second file unless\n   *  you manually clear() the state.  The choice is a matter of\n   *  convenience.\n  */\n  void\n  open (const char *name,\n        std::ios_base::openmode mode = std::ios_base::out);\n\n  /**\n   *  @brief  Attach to already open gzipped file.\n   *  @param  fd  File descriptor.\n   *  @param  mode  Open mode flags (forced to contain ios::out).\n   *\n   *  Stream will be in state good() if attach succeeded; otherwise\n   *  in state fail().\n  */\n  void\n  attach (int fd,\n          std::ios_base::openmode mode = std::ios_base::out);\n\n  /**\n   *  @brief  Close gzipped file.\n   *\n   *  Stream will be in state fail() if close failed.\n  */\n  void\n  close ();\n\nprivate:\n  /**\n   *  Underlying stream buffer.\n  */\n  gzfilebuf m_sb;\n};\n\n/**\n *  @brief  Gzipped file output stream manipulator class.\n *\n *  This class defines a two-argument manipulator for gzofstream.  It is used\n *  as base for the setcompression(int,int) manipulator.\n*/\ntemplate <typename T1, typename T2>\nclass gzomanip2\n{\npublic:\n  // Allows insertor to peek at internals\n  template <typename Ta, typename Tb>\n  friend gzofstream&\n  operator<<(gzofstream&,\n             const gzomanip2<Ta, Tb>&);\n\n  // Constructor\n  gzomanip2 (gzofstream& (*f)(gzofstream&, T1, T2),\n             T1 v1,\n             T2 v2);\nprivate:\n  // Underlying manipulator function\n  gzofstream&\n  (*m_fcn)(gzofstream&, T1, T2);\n\n  // Arguments for manipulator function\n  T1 m_val1;\n  T2 m_val2;\n};\n\n// Manipulator function thunks through to stream buffer\ninline gzofstream&\nsetcompression (gzofstream& gzs, int l, int s = Z_DEFAULT_STRATEGY)\n{\n  (gzs.rdbuf ())->setcompression (l, s);\n  return gzs;\n}\n\n// Manipulator constructor stores arguments\ntemplate <typename T1, typename T2>\ninline\ngzomanip2<T1, T2>::gzomanip2 (gzofstream &(*f)(gzofstream&, T1, T2),\n                              T1 v1,\n                              T2 v2)\n  : m_fcn(f), m_val1(v1), m_val2(v2)\n{ }\n\n// Insertor applies underlying manipulator function to stream\ntemplate <typename T1, typename T2>\ninline gzofstream&\noperator<<(gzofstream& s, const gzomanip2<T1, T2>& m)\n{ return (*m.m_fcn) (s, m.m_val1, m.m_val2); }\n\n// Insert this onto stream to simplify setting of compression level\ninline gzomanip2<int, int>\nsetcompression (int l, int s = Z_DEFAULT_STRATEGY)\n{ return gzomanip2<int, int> (&setcompression, l, s); }\n\n#endif\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/help.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n#include <cstring>\n\n#include <fstream>\n#include <istream>\n#include <map>\n#include <string>\n\n#include \"cmd-edit.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sysdep.h\"\n#include \"str-vec.h\"\n\n#include \"Cell.h\"\n#include \"builtin-defun-decls.h\"\n#include \"defaults.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"help.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ov-classdef.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-usr-fcn.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"pathsearch.h\"\n#include \"procstream.h\"\n#include \"quit.h\"\n#include \"sighandlers.h\"\n#include \"symtab.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"version.h\"\n\n#include \"default-defs.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nconst static char *const operators[] =\n{\n  \"!\",\n  \"~\",\n  \"!=\",\n  \"~=\",\n  R\"(\")\",\n  \"#\",\n  \"%\",\n  \"#{\",\n  \"%{\",\n  \"#}\",\n  \"%}\",\n  \"...\",\n  \"&\",\n  \"&&\",\n  \"'\",\n  \"(\",\n  \")\",\n  \"*\",\n  \"^\",\n  \"+\",\n  \"++\",\n  \",\",\n  \"-\",\n  \"--\",\n  \".'\",\n  \".*\",\n  \".^\",\n  \"./\",\n  \"/\",\n  R\"(.\\)\",\n  R\"(\\)\",\n  \":\",\n  \";\",\n  \"<\",\n  \"<=\",\n  \"=\",\n  \"==\",\n  \">\",\n  \">=\",\n  \"[\",\n  \"]\",\n  \"|\",\n  \"||\",\n  nullptr\n};\n\nconst static string_vector operator_names (operators);\n\nstatic bool\nlooks_like_html (const std::string& msg)\n{\n  const std::size_t p1 = msg.find ('\\n');\n  std::string t = msg.substr (0, p1);\n  // FIXME: this comparison should be case-insensitive\n  const std::size_t p2 = t.find (\"<html\");\n\n  return (p2 != std::string::npos);\n}\n\nstatic bool\nlooks_like_texinfo (const std::string& msg, std::size_t& p1)\n{\n  p1 = msg.find ('\\n');\n\n  std::string t = msg.substr (0, p1);\n\n  if (p1 == std::string::npos)\n    p1 = 0;\n\n  std::size_t p2 = t.find (\"-*- texinfo -*-\");\n\n  return (p2 != std::string::npos);\n}\n\noctave_value\nhelp_system::built_in_docstrings_file (const octave_value_list& args,\n                                       int nargout)\n{\n  return set_internal_variable (m_built_in_docstrings_file, args, nargout,\n                                \"built_in_docstrings_file\", false);\n}\n\noctave_value\nhelp_system::doc_cache_file (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_doc_cache_file, args, nargout,\n                                \"doc_cache_file\", false);\n}\n\noctave_value\nhelp_system::info_file (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_info_file, args, nargout,\n                                \"info_file\", false);\n}\n\noctave_value\nhelp_system::info_program (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_info_program, args, nargout,\n                                \"info_program\", false);\n}\n\noctave_value\nhelp_system::makeinfo_program (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_makeinfo_program, args, nargout,\n                                \"makeinfo_program\", false);\n}\n\noctave_value\nhelp_system::suppress_verbose_help_message (const octave_value_list& args,\n    int nargout)\n{\n  return set_internal_variable (m_suppress_verbose_help_message, args,\n                                nargout, \"suppress_verbose_help_message\");\n}\n\noctave_value\nhelp_system::texi_macros_file (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_texi_macros_file, args, nargout,\n                                \"texi_macros_file\", false);\n}\n\nstd::string\nhelp_system::raw_help (const std::string& nm, bool& symbol_found) const\n{\n  std::string h;\n  std::string w;\n  std::string f;\n\n  bool found;\n\n  found = raw_help_from_symbol_table (nm, h, w, symbol_found);\n\n  if (! found)\n    found = raw_help_from_file (nm, h, f, symbol_found);\n\n  bool external_doc = h.compare (0, 12, \"external-doc\") == 0;\n\n  if (! found || external_doc)\n    {\n      std::string tmp_nm = nm;\n\n      if (external_doc && h.length () > 12 && h[12] == ':')\n        tmp_nm = h.substr (13);\n\n      raw_help_from_docstrings_file (tmp_nm, h, symbol_found);\n    }\n\n  return h;\n}\n\nbool\nhelp_system::get_which_info_from_fcn (const std::string& name, const octave_value& ov_fcn, std::string& file, std::string& type) const\n{\n  file = \"\";\n  type = \"\";\n\n  if (ov_fcn.is_function ())\n    {\n      octave_function *fcn = ov_fcn.function_value ();\n\n      if (fcn)\n        {\n          if (fcn->is_classdef_meta ())\n            {\n              octave_classdef_meta *meta_obj\n                = dynamic_cast<octave_classdef_meta *> (fcn);\n\n              file = meta_obj->file_name ();\n\n              if (meta_obj->is_classdef_constructor ())\n                type = \"class constructor\";\n              else if (meta_obj->is_classdef_method ())\n                type = \"class method\";\n              else\n                type = \"classdef meta object\";\n            }\n          else\n            {\n              file = fcn->fcn_file_name ();\n\n              if (! file.empty ())\n                type = ov_fcn.is_user_script () ? \"script\" : \"function\";\n              else\n                {\n                  if (fcn->is_user_function ())\n                    type = \"command-line function\";\n                  else\n                    {\n                      file = fcn->src_file_name ();\n                      type = \"built-in function\";\n                    }\n                }\n            }\n\n          return true;\n        }\n      else\n        {\n          // We might find a file that contains only a doc string.\n\n          load_path& lp = m_interpreter.get_load_path ();\n\n          file = lp.find_fcn_file (name);\n\n          if (file.empty ())\n            return false;\n        }\n    }\n\n  return false;\n}\n\n// FIXME: There is a lot of duplication between the following function\n// and help_system::raw_help_from_symbol_table.  Some refactoring would\n// probably be useful.\n\nstd::string\nhelp_system::which (const std::string& name,\n                    std::string& type) const\n{\n  std::string file;\n\n  if (name.empty ())\n    return file;\n\n  type = \"\";\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  size_t pos = name.find ('.');\n\n  if (pos == std::string::npos)\n    {\n      // Simple name.  If not found, continue looking for packages and\n      // classes.\n\n      octave_value ov_fcn = symtab.find_function (name);\n\n      if (get_which_info_from_fcn (name, ov_fcn, file, type))\n        return file;\n    }\n\n  // NAME contains '.' and must match the following pattern:\n  //\n  //   (package.)*(package|classname).(property|method)*\n  //\n  // Start by looking up the full name.  It could be either a package or\n  // a class and we are done.  Otherwise, strip the final component and\n  // lookup that name.  If it is a package, look for a function.  If it\n  // is a class, look for a property or method.\n\n  cdef_manager& cdm = m_interpreter.get_cdef_manager ();\n\n  // FIXME: In the following search we may load classes.  Is that really\n  // what we want, or should we just search the loadpath for\n  // +pkga/+pkgb/classname/file.m, etc. and attempt to extract help text\n  // without actually installing packages and classes into the fcn_info\n  // table?\n\n  // Is NAME a class?\n\n  cdef_class cls = cdm.find_class (name, false, true);\n\n  if (cls.ok ())\n    {\n      // FIXME: Return documentation for the class or the class\n      // constructor?\n\n      file = cls.file_name ();\n      type = \"classdef class\";\n\n      return file;\n    }\n\n  cdef_package pkg = cdm.find_package (name, false, true);\n\n  if (pkg.ok ())\n    {\n      // FIXME: How to get the fill name of a package?\n      file = pkg.get_name ();\n      type = \"package\";\n\n      return file;\n    }\n\n  // Strip final component (might be a property or method name).\n\n  pos = name.rfind ('.');\n  std::string prefix = name.substr (0, pos);\n  std::string nm = name.substr (pos+1);\n\n  // Is PREFIX the name of a class?\n\n  cls = cdm.find_class (prefix, false, true);\n\n  if (cls.ok ())\n    {\n      // FIXME: Should we only find public methods here?\n\n      octave_value ov_meth = cls.get_method (nm);\n\n      if (get_which_info_from_fcn (nm, ov_meth, file, type))\n        return file;\n\n      // FIXME: Should we only find public properties here?\n\n      cdef_property prop = cls.find_property (nm);\n\n      if (prop.ok ())\n        {\n          file = cls.file_name ();\n          type = \"class property\";\n\n          return file;\n        }\n    }\n\n  // Or is PREFIX the name of a package?\n\n  pkg = cdm.find_package (prefix, false, true);\n\n  if (pkg.ok ())\n    {\n      octave_value ov_fcn = pkg.find (nm);\n\n      if (get_which_info_from_fcn (nm, ov_fcn, file, type))\n        return file;\n    }\n\n  // File query.\n\n  load_path& lp = m_interpreter.get_load_path ();\n\n  // For compatibility: \"file.\" queries \"file\".\n  if (name.size () > 1 && name[name.size () - 1] == '.')\n    file = lp.find_file (name.substr (0, name.size () - 1));\n  else\n    file = lp.find_file (name);\n\n  file = sys::env::make_absolute (file);\n\n  if (! file.empty ())\n    type = \"file\";\n\n  return file;\n}\n\nstd::string\nhelp_system::which (const std::string& name) const\n{\n  std::string type;\n\n  return which (name, type);\n}\n\nstring_vector\nhelp_system::make_name_list () const\n{\n  const static string_vector keywords\n    = Fiskeyword ()(0).string_vector_value ();\n\n  const static int key_len = keywords.numel ();\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  const string_vector bif = symtab.built_in_function_names ();\n  const int bif_len = bif.numel ();\n\n  const string_vector cfl = symtab.cmdline_function_names ();\n  const int cfl_len = cfl.numel ();\n\n  const string_vector lcl = m_interpreter.variable_names ();\n  const int lcl_len = lcl.numel ();\n\n  load_path& lp = m_interpreter.get_load_path ();\n\n  const string_vector ffl = lp.fcn_names ();\n  const int ffl_len = ffl.numel ();\n\n  const string_vector afl = m_interpreter.autoloaded_functions ();\n  const int afl_len = afl.numel ();\n\n  const string_vector lfl = local_functions ();\n  const int lfl_len = lfl.numel ();\n\n  const int total_len\n    = key_len + bif_len + cfl_len + lcl_len + ffl_len + afl_len + lfl_len;\n\n  string_vector list (total_len);\n\n  // Put all the symbols in one big list.\n\n  int j = 0;\n  int i = 0;\n\n  for (i = 0; i < key_len; i++)\n    list[j++] = keywords[i];\n\n  for (i = 0; i < bif_len; i++)\n    list[j++] = bif[i];\n\n  for (i = 0; i < cfl_len; i++)\n    list[j++] = cfl[i];\n\n  for (i = 0; i < lcl_len; i++)\n    list[j++] = lcl[i];\n\n  for (i = 0; i < ffl_len; i++)\n    list[j++] = ffl[i];\n\n  for (i = 0; i < afl_len; i++)\n    list[j++] = afl[i];\n\n  for (i = 0; i < lfl_len; i++)\n    list[j++] = lfl[i];\n\n  return list;\n}\n\nvoid\nhelp_system::get_help_text (const std::string& name, std::string& text,\n                            std::string& format) const\n{\n  bool symbol_found = false;\n  text = raw_help (name, symbol_found);\n\n  format = \"Not found\";\n  if (symbol_found)\n    {\n      std::size_t idx = -1;\n      if (text.empty ())\n        {\n          format = \"Not documented\";\n        }\n      else if (looks_like_texinfo (text, idx))\n        {\n          format = \"texinfo\";\n          text.erase (0, idx);\n        }\n      else if (looks_like_html (text))\n        {\n          format = \"html\";\n        }\n      else\n        {\n          format = \"plain text\";\n        }\n    }\n}\n\nvoid\nhelp_system::get_help_text_from_file (const std::string& fname,\n                                      std::string& text,\n                                      std::string& format) const\n{\n  bool symbol_found = false;\n\n  std::string f;\n\n  raw_help_from_file (fname, text, f, symbol_found);\n\n  format = \"Not found\";\n  if (symbol_found)\n    {\n      std::size_t idx = -1;\n      if (text.empty ())\n        {\n          format = \"Not documented\";\n        }\n      else if (looks_like_texinfo (text, idx))\n        {\n          format = \"texinfo\";\n          text.erase (0, idx);\n        }\n      else if (looks_like_html (text))\n        {\n          format = \"html\";\n        }\n      else\n        {\n          format = \"plain text\";\n        }\n    }\n}\n\nstd::string\nhelp_system::init_built_in_docstrings_file ()\n{\n  std::string df = sys::env::getenv (\"OCTAVE_BUILT_IN_DOCSTRINGS_FILE\");\n\n  std::string dir_sep = sys::file_ops::dir_sep_str ();\n\n  if (df.empty ())\n    df = config::oct_etc_dir () + dir_sep + \"built-in-docstrings\";\n\n  return df;\n}\n\nstd::string\nhelp_system::init_doc_cache_file ()\n{\n  std::string def_file = config::prepend_octave_home (OCTAVE_DOC_CACHE_FILE);\n\n  std::string env_file = sys::env::getenv (\"OCTAVE_DOC_CACHE_FILE\");\n\n  return (env_file.empty () ? def_file : env_file);\n}\n\nstd::string\nhelp_system::init_info_file ()\n{\n  std::string std_info_file = config::prepend_octave_home (OCTAVE_INFOFILE);\n\n  std::string oct_info_file = sys::env::getenv (\"OCTAVE_INFO_FILE\");\n\n  return (oct_info_file.empty () ? std_info_file : oct_info_file);\n}\n\nstd::string\nhelp_system::init_info_program ()\n{\n  std::string info_prog = sys::env::getenv (\"OCTAVE_INFO_PROGRAM\");\n\n  if (info_prog.empty ())\n    info_prog = \"info\";\n\n  return info_prog;\n}\n\nstd::string\nhelp_system::init_texi_macros_file ()\n{\n  std::string def_file\n    = config::prepend_octave_home (OCTAVE_TEXI_MACROS_FILE);\n\n  std::string env_file = sys::env::getenv (\"OCTAVE_TEXI_MACROS_FILE\");\n\n  return (env_file.empty () ? def_file : env_file);\n}\n\n// Return a vector of all functions from this file,\n// for use in command line auto-completion.\nstring_vector\nhelp_system::local_functions () const\n{\n  string_vector retval;\n\n  tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n  octave_user_code *curr_fcn = tw.current_user_code ();\n\n  if (! curr_fcn)\n    return retval;\n\n  // All subfunctions are listed in the top-level function of this file.\n  // If curr_fcn is a subfunction, then there must be a parent and\n  // curr_fcn will always be valid in and after executing this loop.\n\n  while (curr_fcn->is_subfunction ())\n    {\n      symbol_scope pscope = curr_fcn->parent_fcn_scope ();\n      curr_fcn = pscope.user_code ();\n    }\n\n  // Get subfunctions.\n  const std::list<std::string> names = curr_fcn->subfunction_names ();\n\n  std::size_t sz = names.size ();\n  retval.resize (sz);\n\n  // Loop over them.\n  std::size_t i = 0;\n  for (const auto& nm : names)\n    retval(i++) = nm;\n\n  return retval;\n}\n\nstatic bool\nget_help_from_fcn (const std::string& fcn_nm, const octave_value& ov_fcn, std::string& help, std::string& what, bool& symbol_found)\n{\n  symbol_found = false;\n\n  help = \"\";\n  what = \"\";\n\n  if (ov_fcn.is_function ())\n    {\n      octave_function *fcn = ov_fcn.function_value ();\n\n      help = fcn->doc_string (fcn_nm);\n      what = fcn->fcn_file_name ();\n\n      if (help.empty () && ov_fcn.is_user_function ())\n        {\n          octave_user_function *ufcn = ov_fcn.user_function_value ();\n\n          if (ufcn->is_classdef_constructor ())\n            help = \"undocumented constructor: \";\n          else if (ufcn->is_classdef_method ())\n            help = \"undocumented method: \";\n          else\n            help = \"undocumented function: \";\n\n          help += ufcn->signature ();\n        }\n\n      if (what.empty ())\n        what = fcn->is_user_function () ? \"command-line function\" : \"built-in function\";\n\n      symbol_found = true;\n    }\n\n  return symbol_found;\n}\n\nbool\nhelp_system::raw_help_for_class (const cdef_class& cls,\n                                 const std::string& name,\n                                 std::string& help, std::string& what,\n                                 bool& symbol_found) const\n{\n  if (cls.ok ())\n    {\n      // Is the class documented?\n      help = cls.doc_string ();\n\n      if (! help.empty ())\n        {\n          what = \"class\";\n\n          symbol_found = true;\n          return true;\n        }\n\n      // Look for constructor.\n      std::size_t pos = name.rfind ('.');\n\n      if (pos != std::string::npos)\n        {\n          std::string nm = name.substr (pos+1);\n\n          octave_value ov_meth = cls.get_method (nm);\n\n          if (get_help_from_fcn (nm, ov_meth, help, what, symbol_found))\n            {\n              what = \"constructor\";\n              return true;\n            }\n        }\n\n      // No dot in name and class is undocumented.  Look for documented\n      // constructor.\n\n      octave_value ov_meth = cls.get_method (name);\n\n      if (get_help_from_fcn (name, ov_meth, help, what, symbol_found))\n        {\n          what = \"constructor\";\n          symbol_found = true;\n          return true;\n        }\n\n      // We found a class, but no docstring for it and there is no\n      // constructor explicitly defined.\n\n      help = \"default constructor: obj = \" + name + \" ()\";\n      what = \"constructor\";\n      symbol_found = true;\n      return true;\n    }\n\n  return false;\n}\n\n// FIXME: There is a lot of duplication between the following function\n// and help_system::which.  Some refactoring would probably be useful.\n\nbool\nhelp_system::raw_help_from_symbol_table (const std::string& name, std::string& help, std::string& what, bool& symbol_found) const\n{\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  size_t pos = name.find ('.');\n\n  if (pos == std::string::npos)\n    {\n      // Simple name.  If not found, continue looking for packages and\n      // classes.\n\n      octave_value ov_fcn = symtab.find_function (name);\n\n      // FIXME: it seems like there is a lot of potential for confusion\n      // because is_function can also return true for\n      // octave_classdef_meta objects.\n\n      if (! ov_fcn.is_classdef_meta ()\n          && get_help_from_fcn (name, ov_fcn, help, what, symbol_found))\n        return true;\n    }\n\n  // If NAME does not contain '.', then it should be a package or a\n  // class name.\n  //\n  // If NAME contains '.' it should match the following pattern:\n  //\n  //   (package.)*(package|classname).(property|method)*\n  //\n  // Start by looking up the full name.  It could be either a package or\n  // a class and we are done.  Otherwise, strip the final component and\n  // lookup that name.  If it is a package, look for a function.  If it\n  // is a class, look for a property or method.\n\n  cdef_manager& cdm = m_interpreter.get_cdef_manager ();\n\n  // FIXME: In the following search we may load classes.  Is that really\n  // what we want, or should we just search the loadpath for\n  // +pkga/+pkgb/classname/file.m, etc. and attempt to extract help text\n  // without actually installing packages and classes into the fcn_info\n  // table?\n\n  // Is NAME a class?\n\n  cdef_class cls = cdm.find_class (name, false, true);\n\n  if (raw_help_for_class (cls, name, help, what, symbol_found))\n    return true;\n\n  cdef_package pkg = cdm.find_package (name, false, true);\n\n  if (pkg.ok ())\n    {\n      help = \"package \" + name;\n      what = \"package\";\n\n      symbol_found = true;\n      return true;\n    }\n\n  // Strip final component (might be a property or method name).\n\n  pos = name.rfind ('.');\n  std::string prefix = name.substr (0, pos);\n  std::string nm = name.substr (pos+1);\n\n  // Is PREFIX the name of a class?\n\n  cls = cdm.find_class (prefix, false, true);\n\n  bool found_class = cls.ok ();\n\n  if (found_class)\n    {\n      // FIXME: Should we only find public methods here?\n\n      octave_value ov_meth = cls.get_method (nm);\n\n      if (get_help_from_fcn (nm, ov_meth, help, what, symbol_found))\n        {\n          what = \"class method\";\n          return true;\n        }\n\n      // Found class but no method.  If the NM is the same as the name\n      // of the class, then we have a default constructor.\n\n      if (cls.get_name () == nm)\n        {\n          help = \"default constructor: obj = \" + nm + \" ()\";\n          what = \"constructor\";\n          symbol_found = true;\n          return true;\n        }\n\n      // FIXME: Should we only find public properties here?\n\n      cdef_property prop = cls.find_property (nm);\n\n      if (prop.ok ())\n        {\n          // FIXME: is it supposed to be possible to document\n          // properties?\n\n          help = prop.doc_string ();\n          what = \"class property\";\n\n          symbol_found = true;\n          return true;\n        }\n    }\n\n  // Or is PREFIX the name of a package?\n\n  pkg = cdm.find_package (prefix, false, true);\n\n  if (pkg.ok ())\n    {\n      octave_value ov_fcn = pkg.find (nm);\n\n      if (get_help_from_fcn (nm, ov_fcn, help, what, symbol_found))\n        return true;\n    }\n\n  if (nm == \"m\" && raw_help_for_class (cls, prefix, help, what, symbol_found))\n    return true;\n\n  return false;\n}\n\nbool\nhelp_system::raw_help_from_file (const std::string& nm,\n                                 std::string& h, std::string& file,\n                                 bool& symbol_found) const\n{\n  bool retval = false;\n\n  h = get_help_from_file (nm, symbol_found, file);\n\n  if (h.length () > 0)\n    retval = true;\n\n  return retval;\n}\n\nbool\nhelp_system::raw_help_from_docstrings_file (const std::string& nm,\n    std::string& h,\n    bool& symbol_found) const\n{\n  typedef std::pair<std::streampos, std::streamoff> txt_limits_type;\n  typedef std::map<std::string, txt_limits_type> help_txt_map_type;\n\n  static help_txt_map_type help_txt_map;\n  static bool initialized = false;\n\n  h = \"\";\n  symbol_found = false;\n\n  // FIXME: Should we cache the timestamp of the file and reload the\n  // offsets if it changes?  Or just warn about that?  Or just ignore\n  // it, and assume it won't change?\n\n  if (! initialized)\n    {\n      std::ifstream file = sys::ifstream (m_built_in_docstrings_file.c_str (),\n                                          std::ios::in | std::ios::binary);\n\n      if (! file)\n        error (\"failed to open docstrings file: %s\",\n               m_built_in_docstrings_file.c_str ());\n\n      // Ignore header;\n      file.ignore (std::numeric_limits<std::streamsize>::max(), 0x1d);\n\n      if (file.eof ())\n        error (\"invalid built-in-docstrings file!\");\n\n      // FIXME: eliminate fixed buffer size.\n      std::size_t bufsize = 1000;\n      OCTAVE_LOCAL_BUFFER (char, buf, bufsize);\n\n      while (! file.eof ())\n        {\n          std::string name;\n          int i = 0;\n          int c;\n          while (file\n                 && (c = file.get ()) != std::istream::traits_type::eof ())\n            {\n              if (c == '\\n' || c == '\\r')\n                {\n                  buf[i] = '\\0';\n                  name = buf;\n                  break;\n                }\n              else\n                buf[i++] = c;\n            }\n\n          // Skip @c FILENAME which is part of current DOCSTRINGS\n          // syntax.  This may disappear if a specific format for\n          // docstring files is developed.\n          while (file\n                 && (c = file.get ()) != std::istream::traits_type::eof ()\n                 && c != '\\n' && c != '\\r')\n            ; // skip text\n\n          // skip newline characters\n          while (file\n                 && (c = file.get ()) != std::istream::traits_type::eof ()\n                 && (c == '\\n' || c == '\\r'))\n            ; // skip text\n\n          file.unget ();\n\n          // Position of beginning of help text.\n          std::streampos beg = file.tellg ();\n\n          // Skip help text.\n          file.ignore (std::numeric_limits<std::streamsize>::max(), 0x1d);\n\n          // Position of end of help text.\n          std::streamoff len;\n\n          if (! file.eof ())\n            len = file.tellg () - beg - 1;\n          else\n            {\n              file.seekg (0, file.end);\n              len = file.tellg () - beg - 1;\n              file.setstate (file.eofbit);  // reset eof flag\n            }\n\n          help_txt_map[name] = txt_limits_type (beg, len);\n        }\n\n      initialized = true;\n    }\n\n  help_txt_map_type::const_iterator it = help_txt_map.find (nm);\n\n  if (it != help_txt_map.end ())\n    {\n      txt_limits_type txt_limits = it->second;\n\n      std::streampos beg = txt_limits.first;\n      std::streamoff len = txt_limits.second;\n\n      std::ifstream file = sys::ifstream (m_built_in_docstrings_file.c_str (),\n                                          std::ios::in | std::ios::binary);\n\n      if (! file)\n        error (\"failed to open docstrings file: %s\",\n               m_built_in_docstrings_file.c_str ());\n\n      file.seekg (beg);\n\n      std::size_t txt_len = len;\n      OCTAVE_LOCAL_BUFFER (char, buf, txt_len + 1);\n\n      file.read (buf, txt_len);\n\n      buf[txt_len] = '\\0';\n\n      h = buf;\n\n      symbol_found = true;\n    }\n\n  return symbol_found;\n}\n\n// FIXME: It's not likely that this does the right thing now.\n\nstring_vector\nmake_name_list ()\n{\n  help_system& help_sys = __get_help_system__ ();\n\n  return help_sys.make_name_list ();\n}\n\nDEFMETHOD (get_help_text, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{text}, @var{format}] =} get_help_text (@var{name})\nReturn the raw help text of function @var{name}.\n\nThe raw help text is returned in @var{text} and the format in @var{format}.\nThe format is a string which is one of @qcode{\"texinfo\"}, @qcode{\"html\"}, or\n@w{@qcode{\"plain text\"}}.\n@seealso{get_help_text_from_file}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  const std::string name = args(0).xstring_value (\"get_help_text: NAME must be a string\");\n\n  help_system& help_sys = interp.get_help_system ();\n\n  std::string text, format;\n\n  help_sys.get_help_text (name, text, format);\n\n  return ovl (text, format);\n}\n\nDEFMETHOD (get_help_text_from_file, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{text}, @var{format}] =} get_help_text_from_file (@var{fname})\nReturn the raw help text from the file @var{fname}.\n\nThe raw help text is returned in @var{text} and the format in @var{format}.\nThe format is a string which is one of @qcode{\"texinfo\"}, @qcode{\"html\"}, or\n@w{@qcode{\"plain text\"}}.\n@seealso{get_help_text}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  const std::string fname = args(0).xstring_value (\"get_help_text_from_file: NAME must be a string\");\n\n  help_system& help_sys = interp.get_help_system ();\n\n  std::string text, format;\n\n  help_sys.get_help_text_from_file (fname, text, format);\n\n  return ovl (text, format);\n}\n\n// Return a cell array of strings containing the names of all operators.\n\nDEFUN (__operators__, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{cstr} =} __operators__ ()\nReturn a cell array of strings of all possible Octave operators.\n@end deftypefn */)\n{\n  return ovl (Cell (operator_names));\n}\n\n// Return a cell array of strings containing the names of all keywords.\n// iskeyword() function is located in lex.ll and is based on what the parser\n// thinks is a keyword.\n\nDEFALIAS (__keywords__, iskeyword)\n\n// Return a cell array of strings with the names of all builtin functions.\n\nDEFMETHOD (__builtins__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __builtins__ ()\nReturn a cell array of all builtin (compiled) functions available to Octave.\n@end deftypefn */)\n{\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  const string_vector bif = symtab.built_in_function_names ();\n\n  return ovl (Cell (bif));\n}\n\nDEFMETHOD (localfunctions, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{subfcn_list} =} localfunctions ()\nReturn a list of all local functions, i.e., subfunctions, within the current\nfile.\n\nThe return value is a column cell array of function handles to all local\nfunctions accessible from the function from which @code{localfunctions} is\ncalled.  Nested functions are @emph{not} included in the list.\n\nIf the call is from the command line, an anonymous function, or a script,\nthe return value is an empty cell array.\n\n@seealso{functions}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  Cell retval;\n\n  // Find the main function we are in.\n  tree_evaluator& tw = interp.get_evaluator ();\n  octave_user_code *caller = tw.debug_user_code ();\n\n  if (! caller)\n    return ovl (retval);\n\n  symbol_scope scope = caller->scope ();\n\n  return ovl (Cell (scope.localfunctions ()));\n}\n\n/*\n%!test\n%! f = tempname (tempdir (), \"oct_\");\n%! [~, fcn_name] = fileparts (f);\n%! f = [f \".m\"];\n%! save_path = path ();\n%! unwind_protect\n%!   addpath (tempdir ());\n%!   fid = fopen (f, \"w+\");\n%!   fprintf (fid, \"function z = %s\\n z = localfunctions; end\\n\", fcn_name);\n%!   fprintf (fid, \"function z = b(x)\\n z = x+1; end\\n\");\n%!   fprintf (fid, \"function z = c(x)\\n z = 2*x; end\\n\");\n%!   fclose (fid);\n%!   d = eval (fcn_name);\n%!   assert (size (d), [2, 1]);\n%!   assert (d{1} (3), 4);\n%!   assert (d{2} (3), 6);\n%! unwind_protect_cleanup\n%!   unlink (f);\n%!   path (save_path);\n%! end_unwind_protect\n*/\n\nDEFMETHOD (__which__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{var_struct} =} __which__ (@var{name}, @dots{})\nUndocumented internal function.\n@end deftypefn */)\n{\n  help_system& help_sys = interp.get_help_system ();\n\n  string_vector argv = args.make_argv ();\n\n  int nargin = argv.numel ();\n\n  octave_map m (dim_vector (1, nargin));\n\n  Cell names (1, nargin);\n  Cell files (1, nargin);\n  Cell types (1, nargin);\n\n  for (int i = 0; i < nargin; i++)\n    {\n      std::string name = argv[i];\n\n      std::string type;\n\n      std::string file = help_sys.which (name, type);\n\n      names(i) = name;\n      files(i) = file;\n      types(i) = type;\n    }\n\n  m.assign (\"name\", names);\n  m.assign (\"file\", files);\n  m.assign (\"type\", types);\n\n  return ovl (m);\n}\n\n// Return a cell array of strings containing the names of all\n// functions available in DIRECTORY.  If no directory is given, search\n// the current path.\n\nDEFMETHOD (__list_functions__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{retval} =} __list_functions__ ()\n@deftypefnx {} {@var{retval} =} __list_functions__ (@var{directory})\nReturn a list of all functions (.m and .oct functions) in the load path.\n\nIf the optional argument @var{directory} is given then list only the functions\nin that directory.\n@seealso{path}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  load_path& lp = interp.get_load_path ();\n\n  if (args.length () == 0)\n    {\n      // Get list of all functions\n      string_vector ffl = lp.fcn_names ();\n      string_vector afl = interp.autoloaded_functions ();\n\n      retval = Cell (ffl.append (afl));\n    }\n  else\n    {\n      std::string dir = args(0).xstring_value (\"__list_functions__: DIRECTORY argument must be a string\");\n\n      string_vector fl = lp.files (dir, true);\n\n      // Return a sorted list with unique entries (in case of .m and .oct\n      // versions of the same function in a given directory, for example).\n      fl.sort (true);\n\n      retval = Cell (fl);\n    }\n\n  return retval;\n}\n\nDEFMETHOD (built_in_docstrings_file, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} built_in_docstrings_file ()\n@deftypefnx {} {@var{old_val} =} built_in_docstrings_file (@var{new_val})\n@deftypefnx {} {@var{old_val} =} built_in_docstrings_file (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the name of the\nfile containing docstrings for built-in Octave functions.\n\nThe default value is\n@file{@var{octave-home}/share/octave/@var{version}/etc/built-in-docstrings},\nin which @var{octave-home} is the root directory of the Octave installation,\nand @var{version} is the Octave version number.  The default value may be\noverridden by the environment variable\n@w{@env{OCTAVE_BUILT_IN_DOCSTRINGS_FILE}}, or the command line argument\n@option{--built-in-docstrings-file FNAME}.\n\nNote: This variable is only used when Octave is initializing itself.\nModifying it during a running session of Octave will have no effect.\n@end deftypefn */)\n{\n  help_system& help_sys = interp.get_help_system ();\n\n  return help_sys.built_in_docstrings_file (args, nargout);\n}\n\nDEFMETHOD (doc_cache_file, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} doc_cache_file ()\n@deftypefnx {} {@var{old_val} =} doc_cache_file (@var{new_val})\n@deftypefnx {} {@var{old_val} =} doc_cache_file (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the name of the\nOctave documentation cache file.\n\nA cache file significantly improves the performance of the @code{lookfor}\ncommand.  The default value is\n@file{@var{octave-home}/share/octave/@var{version}/etc/doc-cache},\nin which @var{octave-home} is the root directory of the Octave installation,\nand @var{version} is the Octave version number.\nThe default value may be overridden by the environment variable\n@w{@env{OCTAVE_DOC_CACHE_FILE}}, or the command line argument\n@option{--doc-cache-file FNAME}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{doc_cache_create, lookfor, info_program, doc, help, makeinfo_program}\n@seealso{lookfor}\n@end deftypefn */)\n{\n  help_system& help_sys = interp.get_help_system ();\n\n  return help_sys.doc_cache_file (args, nargout);\n}\n\nDEFMETHOD (info_file, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} info_file ()\n@deftypefnx {} {@var{old_val} =} info_file (@var{new_val})\n@deftypefnx {} {@var{old_val} =} info_file (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the name of the\nOctave info file.\n\nThe default value is\n@file{@var{octave-home}/share/info/octave.info}, in\nwhich @var{octave-home} is the root directory of the Octave installation.\nThe default value may be overridden by the environment variable\n@w{@env{OCTAVE_INFO_FILE}}, or the command line argument\n@option{--info-file FNAME}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{info_program, doc, help, makeinfo_program}\n@end deftypefn */)\n{\n  help_system& help_sys = interp.get_help_system ();\n\n  return help_sys.info_file (args, nargout);\n}\n\nDEFMETHOD (info_program, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} info_program ()\n@deftypefnx {} {@var{old_val} =} info_program (@var{new_val})\n@deftypefnx {} {@var{old_val} =} info_program (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the name of the\ninfo program to run.\n\nThe default value is @file{info}.  The default value may be\noverridden by the environment variable @w{@env{OCTAVE_INFO_PROGRAM}}, or the\ncommand line argument @option{--info-program NAME}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{info_file, doc, help, makeinfo_program}\n@end deftypefn */)\n{\n  help_system& help_sys = interp.get_help_system ();\n\n  return help_sys.info_program (args, nargout);\n}\n\nDEFMETHOD (makeinfo_program, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} makeinfo_program ()\n@deftypefnx {} {@var{old_val} =} makeinfo_program (@var{new_val})\n@deftypefnx {} {@var{old_val} =} makeinfo_program (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the name of the\nprogram that Octave runs to format help text containing\nTexinfo markup commands.\n\nThe default value is @code{makeinfo}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{texi_macros_file, info_file, info_program, doc, help}\n@end deftypefn */)\n{\n  help_system& help_sys = interp.get_help_system ();\n\n  return help_sys.makeinfo_program (args, nargout);\n}\n\nDEFMETHOD (suppress_verbose_help_message, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} suppress_verbose_help_message ()\n@deftypefnx {} {@var{old_val} =} suppress_verbose_help_message (@var{new_val})\n@deftypefnx {} {@var{old_val} =} suppress_verbose_help_message (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave\nwill add additional help information to the end of the output from\nthe @code{help} command and usage messages for built-in commands.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  help_system& help_sys = interp.get_help_system ();\n\n  return help_sys.suppress_verbose_help_message (args, nargout);\n}\n\nDEFMETHOD (texi_macros_file, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} texi_macros_file ()\n@deftypefnx {} {@var{old_val} =} texi_macros_file (@var{new_val})\n@deftypefnx {} {@var{old_val} =} texi_macros_file (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the name of the\nfile containing Texinfo macros that are prepended to documentation strings\nbefore they are passed to makeinfo.\n\nThe default value is\n@file{@var{octave-home}/share/octave/@var{version}/etc/macros.texi},\nin which @var{octave-home} is the root directory of the Octave installation,\nand @var{version} is the Octave version number.\nThe default value may be overridden by the environment variable\n@w{@env{OCTAVE_TEXI_MACROS_FILE}}, or the command line argument\n@option{--texi-macros-file FNAME}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{makeinfo_program}\n@end deftypefn */)\n{\n  help_system& help_sys = interp.get_help_system ();\n\n  return help_sys.texi_macros_file (args, nargout);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/help.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_help_h)\n#define octave_help_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\nclass string_vector;\n\nclass octave_value;\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass cdef_class;\nclass interpreter;\n\nclass help_system\n{\npublic:\n\n  help_system (interpreter& interp)\n    : m_interpreter (interp),\n      m_built_in_docstrings_file (init_built_in_docstrings_file ()),\n      m_doc_cache_file (init_doc_cache_file ()),\n      m_info_file (init_info_file ()),\n      m_info_program (init_info_program ()),\n      m_makeinfo_program (\"makeinfo\"),\n      m_suppress_verbose_help_message (false),\n      m_texi_macros_file (init_texi_macros_file ())\n  { }\n\n  octave_value\n  built_in_docstrings_file (const octave_value_list& args, int nargout);\n\n  std::string\n  built_in_docstrings_file () const { return m_built_in_docstrings_file; }\n\n  std::string built_in_docstrings_file (const std::string& file)\n  {\n    return set (m_built_in_docstrings_file, file);\n  }\n\n  octave_value doc_cache_file (const octave_value_list& args, int nargout);\n\n  std::string doc_cache_file () const { return m_doc_cache_file; }\n\n  std::string doc_cache_file (const std::string& file)\n  {\n    return set (m_doc_cache_file, file);\n  }\n\n  octave_value info_file (const octave_value_list& args, int nargout);\n\n  std::string info_file () const { return m_info_file; }\n\n  std::string info_file (const std::string& file)\n  {\n    return set (m_info_file, file);\n  }\n\n  octave_value info_program (const octave_value_list& args, int nargout);\n\n  std::string info_program () const { return m_info_program; }\n\n  std::string info_program (const std::string& file)\n  {\n    return set (m_info_program, file);\n  }\n\n  octave_value makeinfo_program (const octave_value_list& args, int nargout);\n\n  std::string makeinfo_program () const { return m_makeinfo_program; }\n\n  std::string makeinfo_program (const std::string& file)\n  {\n    return set (m_makeinfo_program, file);\n  }\n\n  octave_value\n  suppress_verbose_help_message (const octave_value_list& args, int nargout);\n\n  bool suppress_verbose_help_message () const\n  {\n    return m_suppress_verbose_help_message;\n  }\n\n  bool suppress_verbose_help_message (bool flag)\n  {\n    return set (m_suppress_verbose_help_message, flag);\n  }\n\n  octave_value texi_macros_file (const octave_value_list& args, int nargout);\n\n  std::string texi_macros_file () const { return m_texi_macros_file; }\n\n  std::string texi_macros_file (const std::string& file)\n  {\n    return set (m_texi_macros_file, file);\n  }\n\n  std::string raw_help (const std::string&, bool&) const;\n\n  std::string which (const std::string& name) const;\n  std::string which (const std::string& name, std::string& type) const;\n\n  string_vector make_name_list () const;\n\n  void get_help_text (const std::string& name, std::string& text,\n                      std::string& format) const;\n\n  void get_help_text_from_file (const std::string& fname, std::string& text,\n                                std::string& format) const;\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  // Name of the file containing doc strings for built-in functions.\n  // (--built-in-docstrings-file file)\n  std::string m_built_in_docstrings_file;\n\n  // Name of the doc cache file specified on the command line.\n  // (--doc-cache-file file)\n  std::string m_doc_cache_file;\n\n  // Name of the info file specified on command line.\n  // (--info-file file)\n  std::string m_info_file;\n\n  // Name of the info reader we'd like to use.\n  // (--info-program program)\n  std::string m_info_program;\n\n  // Name of the makeinfo program to run.\n  std::string m_makeinfo_program;\n\n  // If TRUE, don't print additional help message in help and usage\n  // functions.\n  bool m_suppress_verbose_help_message;\n\n  // Name of the file containing local Texinfo macros that are prepended\n  // to doc strings before processing.\n  // (--texi-macros-file)\n  std::string m_texi_macros_file;\n\n  static std::string init_built_in_docstrings_file ();\n\n  static std::string init_doc_cache_file ();\n\n  static std::string init_info_file ();\n\n  static std::string init_info_program ();\n\n  static std::string init_texi_macros_file ();\n\n  template <typename T>\n  T set (T& var, const T& new_val)\n  {\n    T old_val = var;\n    var = new_val;\n    return old_val;\n  }\n\n  bool get_which_info_from_fcn (const std::string& name, const octave_value& ov_fcn, std::string& file, std::string& type) const;\n\n  string_vector local_functions () const;\n\n  bool raw_help_for_class (const cdef_class& cls, const std::string& nm,\n                           std::string& h, std::string& w,\n                           bool& symbol_found) const;\n\n  bool raw_help_from_symbol_table (const std::string& nm,\n                                   std::string& h, std::string& w,\n                                   bool& symbol_found) const;\n\n  bool raw_help_from_file (const std::string& nm,\n                           std::string& h, std::string& file,\n                           bool& symbol_found) const;\n\n  bool raw_help_from_docstrings_file (const std::string& nm, std::string& h,\n                                      bool& symbol_found) const;\n};\n\nextern string_vector make_name_list ();\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/hook-fcn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"hook-fcn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nhook_function::hook_function (const octave_value& f, const octave_value& d)\n{\n  if (f.is_string ())\n    {\n      std::string name = f.string_value ();\n\n      m_rep = std::shared_ptr<base_hook_function> (new named_hook_function (name, d));\n    }\n  else if (f.is_function_handle ())\n    {\n      m_rep = std::shared_ptr<base_hook_function> (new fcn_handle_hook_function (f, d));\n    }\n  else\n    error (\"invalid hook function\");\n}\n\nvoid\nnamed_hook_function::eval (const octave_value_list& initial_args)\n{\n  octave_value_list args = initial_args;\n\n  if (m_data.is_defined ())\n    args.append (m_data);\n\n  interpreter& interp = __get_interpreter__ ();\n\n  interp.feval (m_name, args, 0);\n}\n\nvoid\nfcn_handle_hook_function::eval (const octave_value_list& initial_args)\n{\n  octave_value_list args = initial_args;\n\n  if (m_data.is_defined ())\n    args.append (m_data);\n\n  interpreter& interp = __get_interpreter__ ();\n\n  interp.feval (m_fcn_handle, args, 0);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/hook-fcn.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_hook_fcn_h)\n#define octave_hook_fcn_h 1\n\n#include \"octave-config.h\"\n\n#include <memory>\n#include <string>\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-fcn-handle.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_hook_function\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY (base_hook_function)\n\n  virtual ~base_hook_function () = default;\n\n  virtual std::string id () const { return \"\"; }\n\n  virtual bool is_valid () const { return false; }\n\n  virtual void eval (const octave_value_list&) { }\n};\n\nclass hook_function\n{\npublic:\n\n  hook_function ()\n  {\n    static std::shared_ptr<base_hook_function>\n    nil_rep (new base_hook_function ());\n\n    m_rep = nil_rep;\n  }\n\n  hook_function (const octave_value& f,\n                 const octave_value& d = octave_value ());\n\n  OCTAVE_DEFAULT_COPY (hook_function)\n\n  ~hook_function () = default;\n\n  std::string id () const { return m_rep->id (); }\n\n  bool is_valid () const { return m_rep->is_valid (); }\n\n  void eval (const octave_value_list& initial_args)\n  {\n    m_rep->eval (initial_args);\n  }\n\nprivate:\n\n  std::shared_ptr<base_hook_function> m_rep;\n};\n\nclass named_hook_function : public base_hook_function\n{\npublic:\n\n  named_hook_function () = delete;\n\n  named_hook_function (const std::string& n, const octave_value& d)\n    : m_name (n), m_data (d)\n  { }\n\n  OCTAVE_DEFAULT_COPY_DELETE (named_hook_function)\n\n  void eval (const octave_value_list& initial_args);\n\n  std::string id () const { return m_name; }\n\n  bool is_valid () const { return is_valid_function (m_name); }\n\nprivate:\n\n  std::string m_name;\n\n  octave_value m_data;\n};\n\nclass fcn_handle_hook_function : public base_hook_function\n{\npublic:\n\n  fcn_handle_hook_function () = delete;\n\n  fcn_handle_hook_function (const octave_value& fh_arg, const octave_value& d)\n    : m_ident (), m_valid (false), m_fcn_handle (fh_arg), m_data (d)\n  {\n    octave_fcn_handle *fh = m_fcn_handle.fcn_handle_value (true);\n\n    if (fh)\n      {\n        m_valid = true;\n\n        std::ostringstream buf;\n        buf << fh;\n        m_ident = fh->fcn_name () + ':' + buf.str ();\n      }\n  }\n\n  OCTAVE_DEFAULT_COPY_DELETE (fcn_handle_hook_function)\n\n  void eval (const octave_value_list& initial_args);\n\n  std::string id () const { return m_ident; }\n\n  bool is_valid () const { return m_valid; }\n\nprivate:\n\n  std::string m_ident;\n\n  bool m_valid;\n\n  octave_value m_fcn_handle;\n\n  octave_value m_data;\n};\n\nclass hook_function_list\n{\npublic:\n\n  typedef std::map<std::string, hook_function> map_type;\n\n  typedef map_type::iterator iterator;\n  typedef map_type::const_iterator const_iterator;\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_DELETE (hook_function_list)\n\n  bool empty () const { return m_fcn_map.empty (); }\n\n  void clear () { m_fcn_map.clear (); }\n\n  void insert (const std::string& id, const hook_function& f)\n  {\n    m_fcn_map[id] = f;\n  }\n\n  iterator find (const std::string& id)\n  {\n    return m_fcn_map.find (id);\n  }\n\n  const_iterator find (const std::string& id) const\n  {\n    return m_fcn_map.find (id);\n  }\n\n  iterator end () { return m_fcn_map.end (); }\n\n  const_iterator end () const { return m_fcn_map.end (); }\n\n  void erase (iterator p) { m_fcn_map.erase (p); }\n\n  void run (const octave_value_list& initial_args = octave_value_list ())\n  {\n    auto p = m_fcn_map.begin ();\n\n    while (p != m_fcn_map.end ())\n      {\n        std::string hook_fcn_id = p->first;\n        hook_function hook_fcn = p->second;\n\n        auto q = p++;\n\n        if (hook_fcn.is_valid ())\n          hook_fcn.eval (initial_args);\n        else\n          m_fcn_map.erase (q);\n      }\n  }\n\nprivate:\n\n  map_type m_fcn_map;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/input.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Get command input interactively or from files.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n\n#include <algorithm>\n#include <queue>\n#include <string>\n\n#include \"cmd-edit.h\"\n#include \"file-ops.h\"\n#include \"iconv-wrappers.h\"\n#include \"localcharset-wrapper.h\"\n#include \"oct-env.h\"\n#include \"oct-string.h\"\n#include \"quit.h\"\n#include \"str-vec.h\"\n#include \"uniconv-wrappers.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"event-manager.h\"\n#include \"help.h\"\n#include \"hook-fcn.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"octave.h\"\n#include \"oct-map.h\"\n#include \"oct-hist.h\"\n#include \"interpreter.h\"\n#include \"event-manager.h\"\n#include \"ovl.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"pt-eval.h\"\n#include \"pt-stmt.h\"\n#include \"sighandlers.h\"\n#include \"sysdep.h\"\n#include \"interpreter.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n// The time we last printed a prompt.\noctave::sys::time Vlast_prompt_time = 0.0;\n\n// TRUE after a call to completion_matches.\nbool octave_completion_matches_called = false;\n\n// TRUE if the plotting system has requested a call to drawnow at\n// the next user prompt.\nbool Vdrawnow_requested = false;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic std::string\nquoting_filename (const std::string& text, int, char quote)\n{\n  if (quote)\n    return text;\n  else\n    return (\"'\" + text);\n}\n\n// Try to parse a partial command line in reverse, excluding trailing TEXT.\n// If it appears a variable has been indexed by () or {},\n// return that expression,\n// to allow autocomplete of field names of arrays of structures.\nstatic std::string\nfind_indexed_expression (const std::string& text)\n{\n  std::string line = command_editor::get_line_buffer ();\n\n  int pos = line.length () - text.length ();\n  int curly_count = 0;\n  int paren_count = 0;\n\n  int last = --pos;\n\n  while (pos >= 0 && (line[pos] == ')' || line[pos] == '}'))\n    {\n      if (line[pos] == ')')\n        paren_count++;\n      else\n        curly_count++;\n\n      while (curly_count + paren_count > 0 && --pos >= 0)\n        {\n          if (line[pos] == ')')\n            paren_count++;\n          else if (line[pos] == '(')\n            paren_count--;\n          else if (line[pos] == '}')\n            curly_count++;\n          else if (line[pos] == '{')\n            curly_count--;\n        }\n\n      while (--pos >= 0 && line[pos] == ' ')\n        ;\n    }\n\n  while (pos >= 0 && (isalnum (line[pos]) || line[pos] == '_'))\n    pos--;\n\n  if (++pos >= 0)\n    return (line.substr (pos, last + 1 - pos));\n  else\n    return std::string ();\n}\n\nstatic string_vector\ngenerate_struct_completions (const std::string& text,\n                             std::string& prefix, std::string& hint)\n{\n  string_vector names;\n\n  std::size_t pos = text.rfind ('.');\n  bool array = false;\n\n  if (pos != std::string::npos)\n    {\n      if (pos == text.length ())\n        hint = \"\";\n      else\n        hint = text.substr (pos+1);\n\n      prefix = text.substr (0, pos);\n\n      if (prefix == \"\")\n        {\n          array = true;\n          prefix = find_indexed_expression (text);\n        }\n\n      std::string base_name = prefix;\n\n      pos = base_name.find_first_of (\"{(. \");\n\n      if (pos != std::string::npos)\n        base_name = base_name.substr (0, pos);\n\n      interpreter& interp = __get_interpreter__ ();\n\n      if (interp.is_variable (base_name))\n        {\n          int parse_status;\n\n          error_system& es = interp.get_error_system ();\n\n          unwind_protect frame;\n\n          frame.add (&error_system::set_discard_warning_messages, &es,\n                     es.discard_warning_messages ());\n\n          es.discard_warning_messages (true);\n\n          try\n            {\n              octave_value tmp\n                = interp.eval_string (prefix, true, parse_status);\n\n              frame.run ();\n\n              if (tmp.is_defined ()\n                  && (tmp.isstruct () || tmp.isjava () || tmp.is_classdef_object ()))\n                names = tmp.map_keys ();\n            }\n          catch (const execution_exception&)\n            {\n              interp.recover_from_exception ();\n            }\n        }\n    }\n\n  // Undo look-back that found the array expression,\n  // but insert an extra \".\" to distinguish from the non-struct case.\n  if (array)\n    prefix = \".\";\n\n  return names;\n}\n\n// FIXME: this will have to be much smarter to work \"correctly\".\nstatic bool\nlooks_like_struct (const std::string& text, char prev_char)\n{\n  bool retval = (! text.empty ()\n                 && (text != \".\" || prev_char == ')' || prev_char == '}')\n                 && text.find_first_of (sys::file_ops::dir_sep_chars ()) == std::string::npos\n                 && text.find (\"..\") == std::string::npos\n                 && text.rfind ('.') != std::string::npos);\n\n  return retval;\n}\n\n// FIXME: make this generate filenames when appropriate.\n\nstatic string_vector\ngenerate_possible_completions (const std::string& text, std::string& prefix,\n                               std::string& hint, bool& deemed_struct)\n{\n  string_vector names;\n\n  prefix = \"\";\n\n  char prev_char = command_editor::get_prev_char (text.length ());\n  deemed_struct = looks_like_struct (text, prev_char);\n\n  if (deemed_struct)\n    names = generate_struct_completions (text, prefix, hint);\n  else\n    names = make_name_list ();\n\n  // Sort and remove duplicates.\n\n  names.sort (true);\n\n  return names;\n}\n\nstatic bool\nis_completing_dirfns ()\n{\n  static std::string dirfns_commands[] = {\"cd\", \"isfile\", \"isfolder\", \"ls\"};\n  static const std::size_t DIRFNS_COMMANDS_LENGTH = 4;\n\n  bool retval = false;\n\n  std::string line = command_editor::get_line_buffer ();\n\n  for (std::size_t i = 0; i < DIRFNS_COMMANDS_LENGTH; i++)\n    {\n      int index = line.find (dirfns_commands[i] + ' ');\n\n      if (index == 0)\n        {\n          retval = true;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nstatic std::string\ngenerate_completion (const std::string& text, int state)\n{\n  std::string retval;\n\n  static std::string prefix;\n  static std::string hint;\n\n  static std::size_t hint_len = 0;\n\n  static int list_index = 0;\n  static int name_list_len = 0;\n  static int name_list_total_len = 0;\n  static string_vector name_list;\n  static string_vector file_name_list;\n\n  static int matches = 0;\n\n  if (state == 0)\n    {\n      list_index = 0;\n\n      prefix = \"\";\n\n      hint = text;\n\n      // No reason to display symbols while completing a\n      // file/directory operation.\n\n      bool deemed_struct = false;\n\n      if (is_completing_dirfns ())\n        name_list = string_vector ();\n      else\n        name_list = generate_possible_completions (text, prefix, hint,\n                    deemed_struct);\n\n      name_list_len = name_list.numel ();\n\n      // If the line was something like \"a{1}.\" then text = \".\" but\n      // we don't want to expand all the . files.\n      if (! deemed_struct)\n        {\n\n          file_name_list = command_editor::generate_filename_completions (text);\n\n          name_list.append (file_name_list);\n\n        }\n\n      name_list_total_len = name_list.numel ();\n\n      hint_len = hint.length ();\n\n      matches = 0;\n\n      for (int i = 0; i < name_list_len; i++)\n        if (hint == name_list[i].substr (0, hint_len))\n          matches++;\n    }\n\n  if (name_list_total_len > 0 && matches > 0)\n    {\n      while (list_index < name_list_total_len)\n        {\n          std::string name = name_list[list_index];\n\n          list_index++;\n\n          if (hint == name.substr (0, hint_len))\n            {\n              // Special case: array reference forces prefix=\".\"\n              //               in generate_struct_completions ()\n              if (list_index <= name_list_len && ! prefix.empty ())\n                retval = (prefix == \".\" ? \"\" : prefix) + '.' + name;\n              else\n                retval = name;\n\n              char prev_char =\n                command_editor::get_prev_char (text.length ());\n\n              if (matches == 1 && looks_like_struct (retval, prev_char))\n                {\n                  // Don't append anything, since we don't know\n                  // whether it should be '(' or '.'.\n\n                  command_editor::set_completion_append_character ('\\0');\n                }\n              else\n                {\n                  input_system& input_sys = __get_input_system__ ();\n\n                  command_editor::set_completion_append_character\n                  (input_sys.completion_append_char ());\n                }\n\n              break;\n            }\n        }\n    }\n\n  return retval;\n}\n\nstatic int\ninternal_input_event_hook_fcn ()\n{\n  octave_quit ();\n\n  input_system& input_sys = __get_input_system__ ();\n\n  input_sys.run_input_event_hooks ();\n\n  return 0;\n}\n\n// Use literal \"octave\" in default setting for PS1 instead of\n// \"\\\\s\" to avoid setting the prompt to \"octave.exe\" or\n// \"octave-gui\", etc.\n\ninput_system::input_system (interpreter& interp)\n  : m_interpreter (interp), m_PS1 (R\"(octave:\\#> )\"), m_PS2 (\"> \"),\n    m_completion_append_char (' '), m_gud_mode (false),\n    m_mfile_encoding (\"utf-8\"), m_auto_repeat_debug_command (true),\n    m_last_debugging_command (\"\\n\"), m_input_event_hook_functions (),\n    m_initialized (false)\n{ }\n\nvoid\ninput_system::initialize (bool line_editing)\n{\n  if (m_initialized)\n    return;\n\n  // Force default line editor if we don't want readline editing.\n  if (! line_editing)\n    {\n      command_editor::force_default_editor ();\n      return;\n    }\n\n  // If we are using readline, this allows conditional parsing of the\n  // .inputrc file.\n\n  command_editor::set_name (\"Octave\");\n\n  // FIXME: this needs to include a comma too, but that\n  // causes trouble for the new struct element completion code.\n\n  static const char *s = \"\\t\\n !\\\"\\'*+-/:;<=>(){}[\\\\]^`~\";\n\n  command_editor::set_basic_word_break_characters (s);\n\n  command_editor::set_completer_word_break_characters (s);\n\n  command_editor::set_basic_quote_characters (R\"(\")\");\n\n  command_editor::set_filename_quote_characters (\" \\t\\n\\\\\\\"'<>=;|&()#$`?*[!:{\");\n\n  command_editor::set_completer_quote_characters (R\"('\")\");\n\n  command_editor::set_completion_function (generate_completion);\n\n  command_editor::set_quoting_function (quoting_filename);\n\n  command_editor::add_event_hook (internal_input_event_hook_fcn);\n\n  m_initialized = true;\n}\n\noctave_value\ninput_system::PS1 (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_PS1, args, nargout, \"PS1\");\n}\n\noctave_value\ninput_system::PS2 (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_PS2, args, nargout, \"PS2\");\n}\n\noctave_value\ninput_system::completion_append_char (const octave_value_list& args,\n                                      int nargout)\n{\n  return set_internal_variable (m_completion_append_char, args, nargout,\n                                \"completion_append_char\");\n}\n\noctave_value\ninput_system::gud_mode (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_gud_mode, args, nargout, \"__gud_mode__\");\n}\n\noctave_value\ninput_system::mfile_encoding (const octave_value_list& args, int nargout)\n{\n  // Save current value in case there is an error in the additional\n  // validation below.\n\n  std::string saved_encoding = m_mfile_encoding;\n\n  // We must pass the actual variable to change here for temporary\n  // \"local\" settings to work properly.\n\n  octave_value retval\n    = set_internal_variable (m_mfile_encoding, args, nargout,\n                             \"mfile_encoding\");\n\n  // Additional validation if the encoding has changed.\n\n  if (m_mfile_encoding != saved_encoding)\n    {\n      if (m_mfile_encoding.empty ())\n        {\n          m_mfile_encoding = \"system\";\n        }\n      else\n        {\n          std::transform (m_mfile_encoding.begin (),\n                          m_mfile_encoding.end (),\n                          m_mfile_encoding.begin (), ::tolower);\n\n          std::string encoding = (m_mfile_encoding.compare (\"system\") == 0)\n                                 ? octave_locale_charset_wrapper () : m_mfile_encoding;\n\n          // Check for valid encoding name.\n          void *codec\n            = octave_iconv_open_wrapper (encoding.c_str (), \"utf-8\");\n\n          if (codec == reinterpret_cast<void *> (-1))\n            {\n              m_mfile_encoding = saved_encoding;\n              if (errno == EINVAL)\n                error (\"mfile_encoding: conversion from encoding '%s' \"\n                       \"not supported\", encoding.c_str ());\n              else\n                error (\"mfile_encoding: error %d opening encoding '%s'\",\n                       errno, encoding.c_str ());\n            }\n          else\n            octave_iconv_close_wrapper (codec);\n        }\n\n    }\n\n  // Synchronize the related gui preference for editor encoding\n  F__event_manager_gui_preference__ (m_interpreter, ovl (\"editor/default_encoding\", m_mfile_encoding));\n\n  return retval;\n}\n\n// Get part of the directory that would be added to the load path\nstatic std::string\nload_path_dir (const std::string& dir)\n{\n  std::string lp_dir = dir;\n\n  // strip trailing filesep\n  std::size_t ipos = lp_dir.find_last_not_of (sys::file_ops::dir_sep_chars ());\n  if (ipos != std::string::npos)\n    lp_dir = lp_dir.erase (ipos+1);\n\n  // strip trailing private folder\n  ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ());\n  if (ipos != std::string::npos\n      && lp_dir.substr (ipos+1).compare (\"private\") == 0)\n    {\n      lp_dir = lp_dir.erase (ipos);\n      ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ());\n    }\n\n  // strip trailing @class folder\n  if (ipos != std::string::npos && lp_dir[ipos+1] == '@')\n    {\n      lp_dir = lp_dir.erase (ipos);\n      ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ());\n    }\n\n  // strip (nested) +namespace folders\n  while (ipos != std::string::npos && lp_dir[ipos+1] == '+')\n    {\n      lp_dir = lp_dir.erase (ipos);\n      ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ());\n    }\n\n  return lp_dir;\n}\n\nstd::string\ninput_system::dir_encoding (const std::string& dir)\n{\n  std::string enc = m_mfile_encoding;\n  // use canonicalized path as key\n  const std::string key = sys::canonicalize_file_name (dir);\n\n  auto enc_it = m_dir_encoding.find (key);\n  if (enc_it != m_dir_encoding.end ())\n    enc = enc_it->second;\n\n  return enc;\n}\n\nvoid\ninput_system::set_dir_encoding (const std::string& dir,\n                                std::string& enc)\n{\n  // use lowercase\n  std::transform (enc.begin (), enc.end (), enc.begin (), ::tolower);\n\n  if (enc.compare (\"delete\") == 0)\n    {\n      // Remove path from map\n      m_dir_encoding.erase (load_path_dir (dir));\n      return;\n    }\n  else if (enc.compare (\"utf-8\"))\n    {\n      // Check for valid encoding name.\n      // FIXME: This will probably not happen very often and opening the\n      //        encoder doesn't take long.\n      //        Should we cache working encoding identifiers anyway?\n      void *codec\n        = octave_iconv_open_wrapper (enc.c_str (), \"utf-8\");\n\n      if (codec == reinterpret_cast<void *> (-1))\n        {\n          if (errno == EINVAL)\n            error (\"dir_encoding: conversion from encoding '%s' \"\n                   \"not supported\", enc.c_str ());\n          else\n            error (\"dir_encoding: error %d opening encoding '%s'.\",\n                   errno, enc.c_str ());\n        }\n      else\n        octave_iconv_close_wrapper (codec);\n    }\n\n  m_dir_encoding[load_path_dir (dir)] = enc;\n\n  return;\n}\n\noctave_value\ninput_system::auto_repeat_debug_command (const octave_value_list& args,\n    int nargout)\n{\n  return set_internal_variable (m_auto_repeat_debug_command, args, nargout,\n                                \"auto_repeat_debug_command\");\n}\n\nbool\ninput_system::yes_or_no (const std::string& prompt)\n{\n  std::string prompt_string = prompt + \"(yes or no) \";\n\n  while (1)\n    {\n      bool eof = false;\n\n      std::string input_buf = interactive_input (prompt_string, eof, true);\n\n      if (input_buf == \"yes\")\n        return true;\n      else if (input_buf == \"no\")\n        return false;\n      else\n        message (nullptr, \"Please answer yes or no.\");\n    }\n}\n\nstd::string\ninput_system::interactive_input (const std::string& s, bool& eof,\n                                 bool interactive)\n{\n  Vlast_prompt_time.stamp ();\n\n  if (Vdrawnow_requested && m_interpreter.interactive ())\n    {\n      bool eval_error = false;\n\n      try\n        {\n          Fdrawnow (m_interpreter);\n        }\n      catch (const execution_exception& ee)\n        {\n          eval_error = true;\n\n          m_interpreter.handle_exception (ee);\n        }\n\n      flush_stdout ();\n\n      // We set Vdrawnow_requested to false even if there is an error in\n      // drawnow so that the error doesn't reappear at every prompt.\n\n      Vdrawnow_requested = false;\n\n      if (eval_error)\n        return \"\\n\";\n    }\n\n  return gnu_readline (s, eof, interactive);\n}\n\n// If the user simply hits return, this will produce an empty matrix.\n\noctave_value_list\ninput_system::get_user_input (const octave_value_list& args, int nargout)\n{\n  octave_value_list retval;\n\n  std::string prompt = args(0).xstring_value (\"input: unrecognized argument\");\n\n  bool read_as_string = false;\n  if (args.length () == 2)  // `input (..., \"s\")`?\n    {\n      std::string literal\n        = args(1).xstring_value (\"input: second argument must be 's'.\");\n      if (literal.length () != 1 || literal[0] != 's')\n        error (\"input: second argument must be 's'.\");\n\n      read_as_string = true;\n    }\n\n  output_system& output_sys = m_interpreter.get_output_system ();\n\n  output_sys.reset ();\n\n  octave_diary << prompt;\n\n  bool eof = false;\n\n  std::string input_buf = interactive_input (prompt.c_str (), eof, true);\n\n  if (input_buf.empty ())\n    error (\"input: reading user-input failed!\");\n\n  std::size_t len = input_buf.length ();\n\n  octave_diary << input_buf;\n\n  if (input_buf[len - 1] != '\\n')\n    octave_diary << \"\\n\";\n\n  if (read_as_string)\n    {\n      // FIXME: fix gnu_readline and octave_gets instead!\n      if (input_buf.length () == 1 && input_buf[0] == '\\n')\n        retval(0) = \"\";\n      else\n        retval(0) = input_buf;\n    }\n  else\n    {\n      int parse_status = 0;\n\n      retval\n        = m_interpreter.eval_string (input_buf, true, parse_status, nargout);\n\n      tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n      if (! tw.in_debug_repl () && retval.empty ())\n        retval(0) = Matrix ();\n    }\n\n  return retval;\n}\n\nbool\ninput_system::have_input_event_hooks () const\n{\n  return ! m_input_event_hook_functions.empty ();\n}\n\nvoid\ninput_system::add_input_event_hook (const hook_function& hook_fcn)\n{\n  m_input_event_hook_functions.insert (hook_fcn.id (), hook_fcn);\n}\n\nbool\ninput_system::remove_input_event_hook (const std::string& hook_fcn_id)\n{\n  hook_function_list::iterator p\n    = m_input_event_hook_functions.find (hook_fcn_id);\n\n  if (p == m_input_event_hook_functions.end ())\n    return false;\n\n  m_input_event_hook_functions.erase (p);\n  return true;\n}\n\nvoid\ninput_system::clear_input_event_hooks ()\n{\n  m_input_event_hook_functions.clear ();\n}\n\nvoid\ninput_system::run_input_event_hooks ()\n{\n  m_input_event_hook_functions.run ();\n}\n\nstd::string\ninput_system::gnu_readline (const std::string& s, bool& eof, bool interactive)\n{\n  octave_quit ();\n\n  eof = false;\n\n  application *app = nullptr;\n  if (interactive && application::is_gui_running ()) \n    app = application::app ();\n\n  std::string retval;\n  if (app && app->experimental_terminal_widget ())\n    {\n      // With the experimental terminal widget, use signals to write to output\n      // and to read from input instead of using readline to avoid deadlocks\n      // between the GUI thread and readline.\n      event_manager& evmgr = m_interpreter.get_event_manager ();\n\n      retval = evmgr.get_input_from_terminal (s);\n    }\n  else\n    retval = command_editor::readline (s, eof);\n\n  if (! eof && retval.empty ())\n    retval = \"\\n\";\n\n  return retval;\n}\n\nstd::string\nbase_reader::octave_gets (const std::string& prompt, bool& eof)\n{\n  octave_quit ();\n\n  eof = false;\n\n  std::string retval;\n\n  // Process pre input event hook function prior to flushing output and\n  // printing the prompt.\n\n  tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n  event_manager& evmgr = m_interpreter.get_event_manager ();\n\n  if (m_interpreter.interactive ())\n    {\n      if (! tw.in_debug_repl ())\n        evmgr.exit_debugger_event ();\n\n      evmgr.pre_input_event ();\n\n      evmgr.set_workspace ();\n    }\n\n  bool history_skip_auto_repeated_debugging_command = false;\n\n  input_system& input_sys = m_interpreter.get_input_system ();\n\n  pipe_handler_error_count = 0;\n\n  output_system& output_sys = m_interpreter.get_output_system ();\n\n  output_sys.reset ();\n\n  octave_diary << prompt;\n\n  retval = input_sys.interactive_input (prompt, eof);\n\n  // There is no need to update the load_path cache if there is no\n  // user input.\n  if (retval != \"\\n\"\n      && retval.find_first_not_of (\" \\t\\n\\r\") != std::string::npos)\n    {\n      load_path& lp = m_interpreter.get_load_path ();\n\n      lp.update ();\n\n      if (tw.in_debug_repl ())\n        input_sys.last_debugging_command (retval);\n      else\n        input_sys.last_debugging_command (\"\\n\");\n    }\n  else if (tw.in_debug_repl () && input_sys.auto_repeat_debug_command ())\n    {\n      retval = input_sys.last_debugging_command ();\n      history_skip_auto_repeated_debugging_command = true;\n    }\n\n  if (retval != \"\\n\")\n    {\n      if (! history_skip_auto_repeated_debugging_command)\n        {\n          if (command_history::add (retval))\n            evmgr.append_history (retval);\n        }\n\n      octave_diary << retval;\n\n      if (! retval.empty () && retval.back () != '\\n')\n        octave_diary << \"\\n\";\n    }\n  else\n    octave_diary << \"\\n\";\n\n  // Process post input event hook function after the internal history\n  // list has been updated.\n\n  if (m_interpreter.interactive ())\n    evmgr.post_input_event ();\n\n  return retval;\n}\n\nclass terminal_reader : public base_reader\n{\npublic:\n\n  terminal_reader (interpreter& interp)\n    : base_reader (interp), m_eof (false), m_input_queue ()\n  { }\n\n  std::string get_input (const std::string& prompt, bool& eof);\n\n  std::string input_source () const { return s_in_src; }\n\n  bool input_from_terminal () const { return true; }\n\nprivate:\n\n  bool m_eof;\n  std::queue<std::string> m_input_queue;\n\n  static const std::string s_in_src;\n};\n\nclass file_reader : public base_reader\n{\npublic:\n\n  file_reader (interpreter& interp, FILE *f_arg)\n    : base_reader (interp), m_file (f_arg)\n  {\n    input_system& input_sys = interp.get_input_system ();\n    m_encoding = input_sys.mfile_encoding ();\n  }\n\n  file_reader (interpreter& interp, FILE *f_arg, const std::string& enc)\n    : base_reader (interp), m_file (f_arg), m_encoding (enc) { }\n\n  std::string get_input (const std::string& prompt, bool& eof);\n\n  std::string input_source () const { return s_in_src; }\n\n  bool input_from_file () const { return true; }\n\nprivate:\n\n  FILE *m_file;\n\n  std::string m_encoding;\n\n  static const std::string s_in_src;\n};\n\nclass eval_string_reader : public base_reader\n{\npublic:\n\n  eval_string_reader (interpreter& interp, const std::string& str)\n    : base_reader (interp), m_eval_string (str)\n  { }\n\n  std::string get_input (const std::string& prompt, bool& eof);\n\n  std::string input_source () const { return s_in_src; }\n\n  bool input_from_eval_string () const { return true; }\n\nprivate:\n\n  std::string m_eval_string;\n\n  static const std::string s_in_src;\n};\n\ninput_reader::input_reader (interpreter& interp)\n  : m_rep (new terminal_reader (interp))\n{ }\n\ninput_reader::input_reader (interpreter& interp, FILE *file)\n  : m_rep (new file_reader (interp, file))\n{ }\n\ninput_reader::input_reader (interpreter& interp, FILE *file,\n                            const std::string& enc)\n  : m_rep (new file_reader (interp, file, enc))\n{ }\n\ninput_reader::input_reader (interpreter& interp, const std::string& str)\n  : m_rep (new eval_string_reader (interp, str))\n{ }\n\nconst std::string base_reader::s_in_src (\"invalid\");\n\nconst std::string terminal_reader::s_in_src (\"terminal\");\n\n// If octave_gets returns multiple lines, we cache the input and\n// return it one line at a time.  Multiple input lines may happen when\n// using readline and bracketed paste mode is enabled, for example.\n// Instead of queueing lines here, it might be better to modify the\n// grammar in the parser to handle multiple lines when working\n// interactively.  See also bug #59938.\n\nstd::string\nterminal_reader::get_input (const std::string& prompt, bool& eof)\n{\n  octave_quit ();\n\n  eof = false;\n\n  if (m_input_queue.empty ())\n    {\n      std::string input = octave_gets (prompt, m_eof);\n\n      std::size_t len = input.size ();\n\n      if (len == 0)\n        {\n          if (m_eof)\n            {\n              eof = m_eof;\n              return input;\n            }\n          else\n            {\n              // Can this happen, or will the string returned from\n              // octave_gets always end in a newline character?\n\n              input = \"\\n\";\n              len = 1;\n            }\n        }\n\n      std::size_t beg = 0;\n      while (beg < len)\n        {\n          std::size_t end = input.find ('\\n', beg);\n\n          if (end == std::string::npos)\n            {\n              m_input_queue.push (input.substr (beg));\n              break;\n            }\n          else\n            {\n              m_input_queue.push (input.substr (beg, end-beg+1));\n              beg = end + 1;\n            }\n        }\n    }\n\n  std::string retval = m_input_queue.front ();\n  m_input_queue.pop ();\n\n  if (m_input_queue.empty ())\n    eof = m_eof;\n\n  return retval;\n}\n\nconst std::string file_reader::s_in_src (\"file\");\n\nstd::string\nfile_reader::get_input (const std::string& /*prompt*/, bool& eof)\n{\n  octave_quit ();\n\n  eof = false;\n\n  std::string src_str = fgets (m_file, eof);\n\n  std::string mfile_encoding;\n\n  if (m_encoding.empty ())\n    {\n      input_system& input_sys = m_interpreter.get_input_system ();\n      mfile_encoding = input_sys.mfile_encoding ();\n    }\n  else\n    mfile_encoding = m_encoding;\n\n  std::string encoding;\n  if (mfile_encoding.compare (\"system\") == 0)\n    {\n      encoding = octave_locale_charset_wrapper ();\n      // encoding identifiers should consist of ASCII only characters\n      std::transform (encoding.begin (), encoding.end (), encoding.begin (),\n                      ::tolower);\n    }\n  else\n    encoding = mfile_encoding;\n\n  if (encoding.compare (\"utf-8\") == 0)\n    {\n      // Check for BOM and strip it\n      if (src_str.compare (0, 3, \"\\xef\\xbb\\xbf\") == 0)\n        src_str.erase (0, 3);\n\n      // replace invalid portions of the string\n      // FIXME: Include file name that corresponds to m_file.\n      if (string::u8_validate (\"get_input\", src_str) > 0)\n        warning_with_id (\"octave:get_input:invalid_utf8\",\n                         \"Invalid UTF-8 byte sequences have been replaced.\");\n    }\n  else\n    {\n      // convert encoding to UTF-8 before returning string\n      const char *src = src_str.c_str ();\n      std::size_t srclen = src_str.length ();\n\n      std::size_t length;\n      uint8_t *utf8_str;\n\n      utf8_str = octave_u8_conv_from_encoding (encoding.c_str (), src, srclen,\n                 &length);\n\n      if (! utf8_str)\n        error (\"file_reader::get_input: \"\n               \"converting from codepage '%s' to UTF-8: %s\",\n               encoding.c_str (), std::strerror (errno));\n\n      unwind_action free_utf8_str ([utf8_str] () { ::free (utf8_str); });\n\n      src_str = std::string (reinterpret_cast<char *> (utf8_str), length);\n    }\n\n  return src_str;\n}\n\nconst std::string eval_string_reader::s_in_src (\"eval_string\");\n\nstd::string\neval_string_reader::get_input (const std::string& /*prompt*/, bool& eof)\n{\n  octave_quit ();\n\n  eof = false;\n\n  std::string retval;\n\n  retval = m_eval_string;\n\n  // Clear the eval string so that the next call will return\n  // an empty character string with EOF = true.\n  m_eval_string = \"\";\n\n  if (retval.empty ())\n    eof = true;\n\n  return retval;\n}\n\nDEFMETHOD (input, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{ans} =} input (@var{prompt})\n@deftypefnx {} {@var{ans} =} input (@var{prompt}, \"s\")\nPrint @var{prompt} and wait for user input.\n\nFor example,\n\n@example\ninput (\"Pick a number, any number! \")\n@end example\n\n@noindent\nprints the prompt\n\n@example\nPick a number, any number!\n@end example\n\n@noindent\nand waits for the user to enter a value.  The string entered by the user\nis evaluated as an expression, so it may be a literal constant, a variable\nname, or any other valid Octave code.\n\nThe number of return arguments, their size, and their class depend on the\nexpression entered.\n\nIf you are only interested in getting a literal string value, you can call\n@code{input} with the character string @qcode{\"s\"} as the second argument.\nThis tells Octave to return the string entered by the user directly, without\nevaluating it first.\n\nBecause there may be output waiting to be displayed by the pager, it is a\ngood idea to always call @code{fflush (stdout)} before calling @code{input}.\n This will ensure that all pending output is written to the screen before\nyour prompt.\n@seealso{yes_or_no, kbhit, pause, menu, listdlg}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  input_system& input_sys = interp.get_input_system ();\n\n  return input_sys.get_user_input (args, std::max (nargout, 1));\n}\n\nDEFMETHOD (yes_or_no, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{ans} =} yes_or_no (\"@var{prompt}\")\nAsk the user a yes-or-no question.\n\nReturn logical true if the answer is yes or false if the answer is no.\n\nTakes one argument, @var{prompt}, which is the string to display when asking\nthe question.  @var{prompt} should end in a space; @code{yes-or-no} adds the\nstring @samp{(yes or no) } to it.  The user must confirm the answer with\n@key{RET} and can edit it until it has been confirmed.\n@seealso{input}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  input_system& input_sys = interp.get_input_system ();\n\n  std::string prompt;\n\n  if (nargin == 1)\n    prompt = args(0).xstring_value (\"yes_or_no: PROMPT must be a string\");\n\n  return ovl (input_sys.yes_or_no (prompt));\n}\n\nDEFMETHOD (keyboard, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} keyboard ()\n@deftypefnx {} {} keyboard (\"@var{prompt}\")\nStop m-file execution and enter debug mode.\n\nWhen the @code{keyboard} function is executed, Octave prints a prompt and\nwaits for user input.  The input strings are then evaluated and the results\nare printed.  This makes it possible to examine the values of variables\nwithin a function, and to assign new values if necessary.  To leave the\nprompt and return to normal execution type @samp{return} or @samp{dbcont}.\nThe @code{keyboard} function does not return an exit status.\n\nIf @code{keyboard} is invoked without arguments, a default prompt of\n@samp{debug> } is used.\n@seealso{dbstop, dbcont, dbquit}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  if (nargin == 1)\n    {\n      std::string prompt\n        = args(0).xstring_value (\"keyboard: PROMPT must be a string\");\n\n      tw.keyboard (prompt);\n    }\n  else\n    tw.keyboard ();\n\n  return ovl ();\n}\n\nDEFUN (completion_matches, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{completion_list} =} completion_matches (\"@var{hint}\")\nGenerate possible word completions for Octave given the character sequence\n@var{hint}.\n\nThis function is provided for the benefit of programs like Emacs which might be\ncontrolling Octave and handling user input.  For example:\n\n@example\n@group\ncompletion_matches (\"sine\")\n@xresult{}\nsinetone\nsinewave\n@end group\n@end example\n\nProgramming Note: The current command number in Octave is not incremented when\nthis function is called.  This is a feature, not a bug.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value retval;\n\n  std::string hint = args(0).string_value ();\n\n  int n = 32;\n\n  string_vector list (n);\n\n  int k = 0;\n\n  for (;;)\n    {\n      std::string cmd = generate_completion (hint, k);\n\n      if (! cmd.empty ())\n        {\n          if (k == n)\n            {\n              n *= 2;\n              list.resize (n);\n            }\n\n          list[k++] = cmd;\n        }\n      else\n        {\n          list.resize (k);\n          break;\n        }\n    }\n\n  if (nargout > 0)\n    {\n      if (! list.empty ())\n        retval = list;\n      else\n        retval = \"\";\n    }\n  else\n    {\n      // We don't use string_vector::list_in_columns here\n      // because it will be easier for Emacs if the names\n      // appear in a single column.\n\n      int len = list.numel ();\n\n      for (int i = 0; i < len; i++)\n        octave_stdout << list[i] << \"\\n\";\n    }\n\n  octave_completion_matches_called = true;\n\n  return retval;\n}\n\n/*\n%!assert (ischar (completion_matches (\"\")))\n%!assert (ischar (completion_matches (\"a\")))\n%!assert (ischar (completion_matches (\" \")))\n%!assert (isempty (completion_matches (\" \")))\n%!assert (any (strcmp (\"abs\", deblank (cellstr (completion_matches (\"\"))))))\n%!assert (any (strcmp (\"abs\", deblank (cellstr (completion_matches (\"a\"))))))\n%!assert (any (strcmp (\"abs\", deblank (cellstr (completion_matches (\"ab\"))))))\n%!assert (any (strcmp (\"abs\", deblank (cellstr (completion_matches (\"abs\"))))))\n%!assert (! any (strcmp (\"abs\", deblank (cellstr (completion_matches (\"absa\"))))))\n\n%!error completion_matches ()\n%!error completion_matches (1, 2)\n*/\n\nDEFUN (readline_read_init_file, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} readline_read_init_file ()\n@deftypefnx {} {} readline_read_init_file (@var{file})\nRead the readline library initialization file @var{file}.\n\nIf @var{file} is omitted, read the default initialization file\n(normally @file{~/.inputrc}).\n\n@c FIXME: Texinfo @xref works for Info and HTML output formats.\n@c        For PDF, replace with cross-reference in plain text.\n@ifnottex\n@xref{Readline Init File,,,readline, GNU Readline Library},\n@end ifnottex\n@iftex\nSee Section \"Readline Init File\" in @cite{GNU Readline Library},\n@end iftex\nfor details.\n@seealso{readline_re_read_init_file}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 0)\n    command_editor::read_init_file ();\n  else\n    {\n      std::string file = args(0).string_value ();\n\n      command_editor::read_init_file (file);\n    }\n\n  return ovl ();\n}\n\nDEFUN (readline_re_read_init_file, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {} readline_re_read_init_file ()\nRe-read the last readline library initialization file that was read.\n\n@c FIXME: Texinfo @xref works for Info and HTML output formats.\n@c        For PDF, replace with cross-reference in plain text.\n@ifnottex\n@xref{Readline Init File,,,readline, GNU Readline Library},\n@end ifnottex\n@iftex\nSee Section \"Readline Init File\" in @cite{GNU Readline Library},\n@end iftex\nfor details.\n@seealso{readline_read_init_file}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  command_editor::re_read_init_file ();\n\n  return ovl ();\n}\n\nDEFMETHOD (add_input_event_hook, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{id} =} add_input_event_hook (@var{fcn})\n@deftypefnx {} {@var{id} =} add_input_event_hook (@var{fcn}, @var{data})\nAdd the named function or function handle @var{fcn} to the list of functions\nto call periodically when Octave is waiting for input.\n\nThe function should have the form\n\n@example\n@var{fcn} (@var{data})\n@end example\n\nIf @var{data} is omitted, Octave calls the function without any arguments.\n\nThe returned identifier may be used to remove the function handle from the\nlist of input hook functions.\n@seealso{remove_input_event_hook}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value user_data;\n\n  if (nargin == 2)\n    user_data = args(1);\n\n  input_system& input_sys = interp.get_input_system ();\n\n  hook_function hook_fcn (args(0), user_data);\n\n  input_sys.add_input_event_hook (hook_fcn);\n\n  return ovl (hook_fcn.id ());\n}\n\nDEFMETHOD (remove_input_event_hook, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} remove_input_event_hook (@var{name})\n@deftypefnx {} {} remove_input_event_hook (@var{fcn_id})\nRemove the named function or function handle with the given identifier\nfrom the list of functions to call periodically when Octave is waiting\nfor input.\n@seealso{add_input_event_hook}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string hook_fcn_id = args(0).xstring_value (\"remove_input_event_hook: argument not valid as a hook function name or id\");\n\n  bool warn = (nargin < 2);\n\n  input_system& input_sys = interp.get_input_system ();\n\n  if (! input_sys.remove_input_event_hook (hook_fcn_id) && warn)\n    warning (\"remove_input_event_hook: %s not found in list\",\n             hook_fcn_id.c_str ());\n\n  return ovl ();\n}\n\nDEFMETHOD (PS1, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} PS1 ()\n@deftypefnx {} {@var{old_val} =} PS1 (@var{new_val})\n@deftypefnx {} {@var{old_val} =} PS1 (@var{new_val}, \"local\")\nQuery or set the primary prompt string.\n\nWhen executing interactively, Octave displays the primary prompt when it is\nready to read a command.\n\nThe default value of the primary prompt string is\n@qcode{'octave:@backslashchar{}#> '}.  To change it, use a command like\n\n@example\nPS1 ('\\u@@\\H> ')\n@end example\n\n@noindent\nwhich will result in the prompt @samp{boris@@kremvax> } for the user\n@samp{boris} logged in on the host @samp{kremvax.kgb.su}.  Note that two\nbackslashes are required to enter a backslash into a double-quoted\ncharacter string.  @xref{Strings}.\n\nYou can also use ANSI escape sequences if your terminal supports them.\nThis can be useful for coloring the prompt.  For example,\n\n@example\nPS1 ('\\[\\033[01;31m\\]\\s:\\#> \\[\\033[0m\\]')\n@end example\n\n@noindent\nwill give the default Octave prompt a red coloring.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{PS2, PS4}\n@end deftypefn */)\n{\n  return interp.PS1 (args, nargout);\n}\n\nDEFMETHOD (PS2, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} PS2 ()\n@deftypefnx {} {@var{old_val} =} PS2 (@var{new_val})\n@deftypefnx {} {@var{old_val} =} PS2 (@var{new_val}, \"local\")\nQuery or set the secondary prompt string.\n\nThe secondary prompt is printed when Octave is expecting additional input to\ncomplete a command.  For example, if you are typing a @code{for} loop that\nspans several lines, Octave will print the secondary prompt at the beginning\nof each line after the first.  The default value of the secondary prompt\nstring is @qcode{\"> \"}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{PS1, PS4}\n@end deftypefn */)\n{\n  return interp.PS2 (args, nargout);\n}\n\nDEFMETHOD (completion_append_char, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} completion_append_char ()\n@deftypefnx {} {@var{old_val} =} completion_append_char (@var{new_val})\n@deftypefnx {} {@var{old_val} =} completion_append_char (@var{new_val}, \"local\")\nQuery or set the internal character variable that is appended to\nsuccessful command-line completion attempts.\n\nThe default value is @qcode{\" \"} (a single space).\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  input_system& input_sys = interp.get_input_system ();\n\n  return input_sys.completion_append_char (args, nargout);\n}\n\nDEFMETHOD (__request_drawnow__,, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __request_drawnow__ ()\n@deftypefnx {} {} __request_drawnow__ (@var{flag})\nUndocumented internal function.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 0)\n    Vdrawnow_requested = true;\n  else\n    Vdrawnow_requested = args(0).bool_value ();\n\n  return ovl ();\n}\n\nDEFMETHOD (__gud_mode__, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{state} =} __gud_mode__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  input_system& input_sys = interp.get_input_system ();\n\n  return input_sys.gud_mode (args, nargout);\n}\n\nDEFMETHOD (mfile_encoding, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{current_encoding} =} mfile_encoding ()\n@deftypefnx {} {} mfile_encoding (@var{new_encoding})\n@deftypefnx {} {@var{old_encoding} =} mfile_encoding (@var{new_encoding})\nQuery or set the encoding that is used for reading m-files.\n\nThe input and output are strings naming an encoding, e.g.,\n@nospell{@qcode{\"utf-8\"}}.\n\nThis encoding is used by Octave's parser when reading m-files unless a\ndifferent encoding was set for a specific directory containing m-files using\nthe function @code{dir_encoding} or in a file @file{.oct-config} in that\ndirectory.\n\nThe special value @qcode{\"system\"} selects the encoding that matches the system\nlocale.\n\nIf the m-file encoding is changed after the m-files have already been parsed,\nthe files have to be parsed again for that change to take effect.  That can be\ntriggered with the command @code{clear all}.\n\nAdditionally, this encoding is used to load and save files with the built-in\neditor in Octave's GUI.\n\n@seealso{dir_encoding}\n@end deftypefn */)\n{\n  input_system& input_sys = interp.get_input_system ();\n\n  return input_sys.mfile_encoding (args, nargout);\n}\n\nDEFALIAS (__mfile_encoding__, mfile_encoding);\n\nDEFMETHOD (dir_encoding, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{current_encoding} =} dir_encoding (@var{dir})\n@deftypefnx {} {} dir_encoding (@var{dir}, @var{new_encoding})\n@deftypefnx {} {} dir_encoding (@var{dir}, \"delete\")\n@deftypefnx {} {@var{old_encoding} =} dir_encoding (@var{dir}, @var{new_encoding})\nQuery or set the @var{encoding} that is used for reading m-files in @var{dir}.\n\nThe per-directory encoding overrides the (globally set) m-file encoding,\n@pxref{XREFmfile_encoding,,@code{mfile_encoding}}.\n\nThe string @var{DIR} must match how the directory would appear in the load\npath.\n\nThe @var{new_encoding} input must be a valid encoding identifier or\n@qcode{\"delete\"}.  In the latter case, any per-directory encoding is removed\nand the (globally set) m-file encoding will be used for the given @var{dir}.\n\nThe currently or previously used encoding is returned only if an output\nargument is requested.\n\nThe directory encoding is automatically read from the file @file{.oct-config}\nwhen a new path is added to the load path (for example with @code{addpath}).\nTo set the encoding for all files in the same folder, that file must contain\na line starting with @qcode{\"encoding=\"} followed by the encoding identifier.\n\nFor example to set the file encoding for all files in the same folder to\nISO 8859-1 (Latin-1), create a file @file{.oct-config} with the following\ncontent:\n\n@example\nencoding=iso8859-1\n@end example\n\nIf the file encoding is changed after the files have already been parsed, the\nfiles have to be parsed again for that change to take effect.  That can be done\nwith the command @code{clear all}.\n\n@seealso{addpath, path, mfile_encoding}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string dir\n    = args(0).xstring_value (\"dir_encoding: DIR must be a string\");\n\n  octave_value retval;\n\n  input_system& input_sys = interp.get_input_system ();\n\n  if (nargout > 0)\n    retval = input_sys.dir_encoding (dir);\n\n  if (nargin > 1)\n    {\n      std::string encoding\n        = args(1).xstring_value (\"dir_encoding: ENCODING must be a string\");\n\n      input_sys.set_dir_encoding (dir, encoding);\n    }\n\n  return ovl (retval);\n\n}\n\nDEFMETHOD (auto_repeat_debug_command, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} auto_repeat_debug_command ()\n@deftypefnx {} {@var{old_val} =} auto_repeat_debug_command (@var{new_val})\n@deftypefnx {} {@var{old_val} =} auto_repeat_debug_command (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether debugging\ncommands are automatically repeated when the input line is empty (typing\njust @key{RET}).\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  input_system& input_sys = interp.get_input_system ();\n\n  return input_sys.auto_repeat_debug_command (args, nargout);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/input.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Use the GNU readline library for command line editing and history.\n\n#if ! defined (octave_input_h)\n#define octave_input_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdio>\n\n#include <memory>\n#include <string>\n#include <unordered_map>\n\n#include \"hook-fcn.h\"\n#include \"oct-time.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n\n// TRUE after a call to completion_matches.\nextern OCTINTERP_API bool octave_completion_matches_called;\n\n// TRUE if the plotting system has requested a call to drawnow at\n// the next user prompt.\nextern OCTINTERP_API bool Vdrawnow_requested;\n\nextern OCTINTERP_API octave::sys::time Vlast_prompt_time;\n\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass input_system\n{\npublic:\n\n  input_system (interpreter& interp);\n\n  void initialize (bool line_editing);\n\n  octave_value PS1 (const octave_value_list& args, int nargout);\n\n  std::string PS1 () const { return m_PS1; }\n\n  std::string PS1 (const std::string& s)\n  {\n    std::string val = m_PS1;\n    m_PS1 = s;\n    return val;\n  }\n\n  void set_PS1 (const std::string& s) { m_PS1 = s; }\n\n  octave_value PS2 (const octave_value_list& args, int nargout);\n\n  std::string PS2 () const { return m_PS2; }\n\n  std::string PS2 (const std::string& s)\n  {\n    std::string val = m_PS2;\n    m_PS2 = s;\n    return val;\n  }\n\n  void set_PS2 (const std::string& s) { m_PS2 = s; }\n\n  std::string last_debugging_command () const\n  {\n    return m_last_debugging_command;\n  }\n\n  std::string last_debugging_command (const std::string& s)\n  {\n    std::string val = m_last_debugging_command;\n    m_last_debugging_command = s;\n    return val;\n  }\n\n  octave_value\n  completion_append_char (const octave_value_list& args, int nargout);\n\n  char completion_append_char () const\n  {\n    return m_completion_append_char;\n  }\n\n  char completion_append_char (char c)\n  {\n    char val = m_completion_append_char;\n    m_completion_append_char = c;\n    return val;\n  }\n\n  void set_completion_append_char (char c) { m_completion_append_char = c; }\n\n  octave_value gud_mode (const octave_value_list& args, int nargout);\n\n  bool gud_mode () const { return m_gud_mode; }\n\n  bool gud_mode (bool flag)\n  {\n    bool val = m_gud_mode;\n    m_gud_mode = flag;\n    return val;\n  }\n\n  void set_gud_mode (bool flag) { m_gud_mode = flag; }\n\n  octave_value mfile_encoding (const octave_value_list& args, int nargout);\n\n  std::string mfile_encoding () const { return m_mfile_encoding; }\n\n  std::string mfile_encoding (const std::string& s)\n  {\n    std::string val = m_mfile_encoding;\n    m_mfile_encoding = s;\n    return val;\n  }\n\n  void set_mfile_encoding (const std::string& s) { m_mfile_encoding = s; }\n\n  std::string dir_encoding (const std::string& dir);\n\n  void set_dir_encoding (const std::string& dir, std::string& enc);\n\n  octave_value\n  auto_repeat_debug_command (const octave_value_list& args, int nargout);\n\n  bool auto_repeat_debug_command () const\n  {\n    return m_auto_repeat_debug_command;\n  }\n\n  bool auto_repeat_debug_command (bool val)\n  {\n    bool old_val = m_auto_repeat_debug_command;\n    m_auto_repeat_debug_command = val;\n    return old_val;\n  }\n\n  bool yes_or_no (const std::string& prompt);\n\n  std::string interactive_input (const std::string& s, bool& eof,\n                                 bool interactive = false);\n\n  octave_value_list\n  get_user_input (const octave_value_list& args, int nargout);\n\n  bool have_input_event_hooks () const;\n\n  void add_input_event_hook (const hook_function& hook_fcn);\n\n  bool remove_input_event_hook (const std::string& hook_fcn_id);\n\n  void clear_input_event_hooks ();\n\n  void run_input_event_hooks ();\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  // Primary prompt string.\n  std::string m_PS1;\n\n  // Secondary prompt string.\n  std::string m_PS2;\n\n  // Character to append after successful command-line completion\n  // attempts.\n  char m_completion_append_char;\n\n  // TRUE if we are running in the Emacs GUD mode.\n  bool m_gud_mode;\n\n  // Codepage which is used to read .m files\n  std::string m_mfile_encoding;\n\n  // map of directories -> used mfile encoding\n  std::unordered_map<std::string, std::string> m_dir_encoding;\n\n  // TRUE means repeat last debug command if the user just types RET.\n  bool m_auto_repeat_debug_command;\n\n  // If we are in debugging mode, this is the last command entered,\n  // so that we can repeat the previous command if the user just\n  // types RET.\n  std::string m_last_debugging_command;\n\n  hook_function_list m_input_event_hook_functions;\n\n  bool m_initialized;\n\n  std::string gnu_readline (const std::string& s, bool& eof,\n                            bool interactive = false);\n};\n\nclass base_reader\n{\npublic:\n\n  friend class input_reader;\n\n  base_reader (interpreter& interp)\n    : m_interpreter (interp)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (base_reader)\n\n  virtual ~base_reader () = default;\n\n  virtual std::string get_input (const std::string& prompt, bool& eof) = 0;\n\n  virtual std::string input_source () const { return s_in_src; }\n\n  std::string octave_gets (const std::string& prompt, bool& eof);\n\n  virtual bool input_from_terminal () const { return false; }\n\n  virtual bool input_from_file () const { return false; }\n\n  virtual bool input_from_eval_string () const { return false; }\n\nprotected:\n\n  interpreter& m_interpreter;\n\nprivate:\n\n  static const std::string s_in_src;\n};\n\nclass input_reader\n{\npublic:\n\n  input_reader () = delete;\n\n  input_reader (interpreter& interp);\n\n  input_reader (interpreter& interp, FILE *file);\n\n  input_reader (interpreter& interp, FILE *file, const std::string& enc);\n\n  input_reader (interpreter& interp, const std::string& str);\n\n  OCTAVE_DEFAULT_COPY_DELETE (input_reader)\n\n  std::string get_input (const std::string& prompt, bool& eof)\n  {\n    return m_rep->get_input (prompt, eof);\n  }\n\n  std::string input_source () const\n  {\n    return m_rep->input_source ();\n  }\n\n  bool input_from_terminal () const\n  {\n    return m_rep->input_from_terminal ();\n  }\n\n  bool input_from_file () const\n  {\n    return m_rep->input_from_file ();\n  }\n\n  bool input_from_eval_string () const\n  {\n    return m_rep->input_from_eval_string ();\n  }\n\nprivate:\n\n  std::shared_ptr<base_reader> m_rep;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/interpreter-private.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n#include <list>\n#include <string>\n\n#include \"bp-table.h\"\n#include \"cdef-manager.h\"\n#include \"child-list.h\"\n#include \"display.h\"\n#include \"error.h\"\n#include \"event-manager.h\"\n#include \"gtk-manager.h\"\n#include \"help.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"load-save.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"symtab.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ninterpreter& __get_interpreter__ ()\n{\n  interpreter *interp = interpreter::the_interpreter ();\n\n  if (! interp)\n    {\n      std::cerr << \"fatal error: octave interpreter context missing\" << std::endl;\n      abort ();\n    }\n\n  return *interp;\n}\n\ndynamic_loader&\n__get_dynamic_loader__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_dynamic_loader ();\n}\n\nerror_system&\n__get_error_system__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_error_system ();\n}\n\ngh_manager&\n__get_gh_manager__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_gh_manager ();\n}\n\nhelp_system&\n__get_help_system__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_help_system ();\n}\n\ninput_system&\n__get_input_system__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_input_system ();\n}\n\noutput_system&\n__get_output_system__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_output_system ();\n}\n\nload_path&\n__get_load_path__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_load_path ();\n}\n\nload_save_system&\n__get_load_save_system__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_load_save_system ();\n}\n\nevent_manager&\n__get_event_manager__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_event_manager ();\n}\n\ntype_info&\n__get_type_info__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_type_info ();\n}\n\nsymbol_table&\n__get_symbol_table__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_symbol_table ();\n}\n\nsymbol_scope\n__get_current_scope__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_current_scope ();\n}\n\nsymbol_scope\n__require_current_scope__ ()\n{\n  symbol_scope scope = __get_current_scope__ ();\n\n  if (! scope)\n    error (\"__require_current_scope__: symbol table scope missing\");\n\n  return scope;\n}\n\ntree_evaluator&\n__get_evaluator__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_evaluator ();\n}\n\nbp_table&\n__get_bp_table__ ()\n{\n  tree_evaluator& tw = __get_evaluator__ ();\n\n  return tw.get_bp_table ();\n}\n\nchild_list&\n__get_child_list__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_child_list ();\n}\n\ncdef_manager&\n__get_cdef_manager__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_cdef_manager ();\n}\n\ndisplay_info&\n__get_display_info__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_display_info ();\n}\n\ngtk_manager&\n__get_gtk_manager__ ()\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.get_gtk_manager ();\n}\n\noctave_value\nget_function_handle (interpreter& interp, const octave_value& arg,\n                     const std::string& parameter_name)\n{\n  std::list<std::string> parameter_names;\n  parameter_names.push_back (parameter_name);\n  return get_function_handle (interp, arg, parameter_names);\n}\n\n// May return a function handle object, inline function object, or\n// function object.\n\noctave_value\nget_function_handle (interpreter& interp, const octave_value& arg,\n                     const std::list<std::string>& parameter_names)\n{\n  if (arg.is_function_handle () || arg.is_inline_function ())\n    return arg;\n  else if (arg.is_string ())\n    {\n      std::string fstr = arg.string_value ();\n\n      if (fstr.empty ())\n        return octave_value ();\n\n      symbol_table& symtab = interp.get_symbol_table ();\n\n      octave_value fcn = symtab.find_function (fstr);\n\n      if (fcn.is_defined ())\n        return fcn;\n\n      // Possibly warn here that passing the function body in a\n      // character string is discouraged.\n\n      octave_value_list args (parameter_names.size () + 1);\n      octave_idx_type i = 0;\n      args(i++) = fstr;\n      for (const auto& pname : parameter_names)\n        args(i++) = pname;\n\n      octave_value_list tmp = interp.feval (\"inline\", args, 1);\n\n      if (tmp.length () > 0)\n        return tmp(0);\n    }\n\n  return octave_value ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/interpreter-private.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_interpreter_private_h)\n#define octave_interpreter_private_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n\n#include \"symtab.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass bp_table;\nclass cdef_manager;\nclass child_list;\nclass display_info;\nclass dynamic_loader;\nclass error_system;\nclass event_manager;\nclass gh_manager;\nclass gtk_manager;\nclass help_system;\nclass input_system;\nclass interpreter;\nclass load_path;\nclass load_save_system;\nclass output_system;\nclass tree_evaluator;\nclass type_info;\n\nextern OCTINTERP_API interpreter& __get_interpreter__ ();\n\nextern OCTINTERP_API dynamic_loader& __get_dynamic_loader__ ();\n\nextern OCTINTERP_API error_system& __get_error_system__ ();\n\nextern OCTINTERP_API gh_manager& __get_gh_manager__ ();\n\nextern OCTINTERP_API help_system& __get_help_system__ ();\n\nextern OCTINTERP_API input_system& __get_input_system__ ();\n\nextern OCTINTERP_API load_path& __get_load_path__ ();\n\nextern OCTINTERP_API load_save_system& __get_load_save_system__ ();\n\nextern OCTINTERP_API event_manager& __get_event_manager__ ();\n\nextern OCTINTERP_API output_system& __get_output_system__ ();\n\nextern OCTINTERP_API type_info& __get_type_info__ ();\n\nextern OCTINTERP_API symbol_table& __get_symbol_table__ ();\n\nextern OCTINTERP_API symbol_scope __get_current_scope__ ();\n\nextern OCTINTERP_API symbol_scope __require_current_scope__ ();\n\nextern OCTINTERP_API tree_evaluator& __get_evaluator__ ();\n\nextern OCTINTERP_API bp_table& __get_bp_table__ ();\n\nextern OCTINTERP_API child_list& __get_child_list__ ();\n\nextern OCTINTERP_API cdef_manager& __get_cdef_manager__ ();\n\nextern OCTINTERP_API display_info& __get_display_info__ ();\n\nextern OCTINTERP_API gtk_manager& __get_gtk_manager__ ();\n\n// Functions that could be methods in the interpreter class but maybe\n// shouldn't be exposed as part of the public interface.\n\n// Convert octave_value object ARG to be a function handle object.  It\n// may be a function handle, inline function, the name of a function,\n// or the text of an inline function that has the given argument names\n// PARAMETER_NAMES.  Use of the latter form is discouraged.\n\nOCTINTERP_API\noctave_value\nget_function_handle (interpreter& interp, const octave_value& arg,\n                     const std::string& parameter_name);\n\nOCTINTERP_API\noctave_value\nget_function_handle (interpreter& interp, const octave_value& arg,\n                     const std::list<std::string>& parameter_names\n                     = std::list<std::string> ());\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/interpreter.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <clocale>\n\n#include <iostream>\n#include <set>\n#include <string>\n#include <thread>\n\n#include \"blas-proto.h\"\n#include \"cmd-edit.h\"\n#include \"cmd-hist.h\"\n#include \"file-ops.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"fpucw-wrappers.h\"\n#include \"oct-env.h\"\n#include \"oct-error.h\"\n#include \"oct-sysdep.h\"\n#include \"quit.h\"\n#include \"signal-wrappers.h\"\n#include \"str-vec.h\"\n#include \"unistd-wrappers.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"defaults.h\"\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"display.h\"\n#include \"error.h\"\n#include \"event-manager.h\"\n#include \"graphics.h\"\n#include \"help.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"load-save.h\"\n#include \"octave.h\"\n#include \"oct-hist.h\"\n#include \"oct-map.h\"\n#include \"oct-mutex.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-classdef.h\"\n#include \"parse.h\"\n#include \"pt-classdef.h\"\n#include \"pt-eval.h\"\n#include \"pt-jump.h\"\n#include \"pt-stmt.h\"\n#include \"sighandlers.h\"\n#include \"sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"version.h\"\n\n// TRUE means the quit() call is allowed.\nbool quit_allowed = true;\n\n// TRUE means we are ready to interpret commands, but not everything\n// is ready for interactive use.\nbool octave_interpreter_ready = false;\n\n// TRUE means we've processed all the init code and we are good to go.\nstd::atomic<bool> octave_initialized {false};\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (__version_info__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {retval =} __version_info__ (@var{name}, @var{version}, @var{release}, @var{date})\nUndocumented internal function.\n@end deftypefn */)\n{\n  static octave_map vinfo;\n\n  int nargin = args.length ();\n\n  if (nargin != 0 && nargin != 4)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 0)\n    retval = vinfo;\n  else if (nargin == 4)\n    {\n      if (vinfo.nfields () == 0)\n        {\n          vinfo.assign (\"Name\", args(0));\n          vinfo.assign (\"Version\", args(1));\n          vinfo.assign (\"Release\", args(2));\n          vinfo.assign (\"Date\", args(3));\n        }\n      else\n        {\n          octave_idx_type n = vinfo.numel () + 1;\n\n          vinfo.resize (dim_vector (n, 1));\n\n          octave_value idx (n);\n\n          vinfo.assign (idx, \"Name\", Cell (octave_value (args(0))));\n          vinfo.assign (idx, \"Version\", Cell (octave_value (args(1))));\n          vinfo.assign (idx, \"Release\", Cell (octave_value (args(2))));\n          vinfo.assign (idx, \"Date\", Cell (octave_value (args(3))));\n        }\n    }\n\n  return retval;\n}\n\nDEFMETHOD (quit, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} quit\n@deftypefnx {} {} quit cancel\n@deftypefnx {} {} quit force\n@deftypefnx {} {} quit (\"cancel\")\n@deftypefnx {} {} quit (\"force\")\n@deftypefnx {} {} quit (@var{status})\n@deftypefnx {} {} quit (@var{status}, \"force\")\n@deftypefnx {} {} exit (@dots{})\nQuit the current Octave session.\n\nIf the optional integer value @var{status} is supplied, pass that value to\nthe operating system as Octave's exit status.  The default value is zero.\n\nWhen exiting, Octave will attempt to run the m-file @file{finish.m} if it\nexists.  User commands to save the workspace or clean up temporary files\nmay be placed in that file.  Alternatively, another m-file may be scheduled\nto run using @code{atexit}.  If an error occurs while executing the\n@file{finish.m} file, Octave does not exit and control is returned to\nthe command prompt.\n\nIf the optional argument @qcode{\"cancel\"} is provided, Octave does not\nexit and control is returned to the command prompt.  This feature allows\nthe @code{finish.m} file to cancel the quit process.\n\nIf the user preference to request confirmation before exiting, Octave\nwill display a dialog and give the user an option to cancel the exit\nprocess.\n\nIf the optional argument @qcode{\"force\"} is provided, no confirmation is\nrequested, and the execution of the @file{finish.m} file is skipped.\n\nProgramming Note: @code{exit} is an alias for @code{quit} and can be used\ninterchangeably.\n@seealso{atexit}\n@end deftypefn */)\n{\n  int numel = args.length ();\n\n  if (numel > 2)\n    print_usage ();\n\n  int exit_status = 0;\n\n  bool force = false;\n  bool cancel = false;\n\n  if (numel == 2)\n    {\n      exit_status = args(0).xnint_value (\"quit: STATUS must be an integer\");\n      std::string frc\n        = args(1).xstring_value (\"quit: second argument must be a string\");\n\n      if (frc == \"force\")\n        force = true;\n      else\n        error (R\"(quit: second argument must be string \"force\")\");\n    }\n  else if (numel == 1)\n    {\n      if (args(0).is_string ())\n        {\n          const char *msg\n            = R\"(quit: option must be string \"cancel\" or \"force\")\";\n\n          std::string opt = args(0).xstring_value (msg);\n\n          if (opt == \"cancel\")\n            cancel = true;\n          else if (opt == \"force\")\n            force = true;\n          else\n            error (\"%s\", msg);\n        }\n      else\n        exit_status = args(0).xnint_value (\"quit: STATUS must be an integer\");\n    }\n\n  if (cancel)\n    {\n      // No effect if \"quit cancel\" appears outside of finish script.\n\n      if (interp.executing_finish_script ())\n        interp.cancel_quit (true);\n\n      return ovl ();\n    }\n\n  interp.quit (exit_status, force);\n\n  return ovl ();\n}\n\nDEFALIAS (exit, quit);\n\nDEFMETHOD (atexit, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} atexit (@var{fcn})\n@deftypefnx {} {} atexit (@var{fcn}, true)\n@deftypefnx {} {} atexit (@var{fcn}, false)\n@deftypefnx {} {@var{status} =} atexit (@var{fcn}, false)\nRegister a function to be called when Octave exits.\n\nFor example,\n\n@example\n@group\nfunction last_words ()\n  disp (\"Bye bye\");\nendfunction\natexit (\"last_words\");\n@end group\n@end example\n\n@noindent\nwill print the message @qcode{\"Bye bye\"} when Octave exits.\n\nThe additional argument @var{flag} will register or unregister @var{fcn}\nfrom the list of functions to be called when Octave exits.  If @var{flag} is\ntrue, the function is registered, and if @var{flag} is false, it is\nunregistered.  For example, after registering the function @code{last_words}\nabove,\n\n@example\natexit (\"last_words\", false);\n@end example\n\n@noindent\nwill remove the function from the list and Octave will not call\n@code{last_words} when it exits.\n\nThe optional output @var{status} is only available when unregistering a\nfunction.  The value is true if the unregistering was successful and false\notherwise.\n\nProgramming Note: @code{atexit} only removes the first occurrence of a function\nfrom the list; if a function was placed in the list multiple times with\n@code{atexit}, it must also be removed from the list multiple times.\n@seealso{quit}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string arg = args(0).xstring_value (\"atexit: FCN argument must be a string\");\n\n  bool add_mode = (nargin == 2)\n                  ? args(1).strict_bool_value (\"atexit: FLAG argument must be a logical value\")\n                  : true;\n\n  octave_value_list retval;\n\n  if (add_mode)\n    interp.add_atexit_fcn (arg);\n  else\n    {\n      bool found = interp.remove_atexit_fcn (arg);\n\n      if (nargout > 0)\n        retval = ovl (found);\n    }\n\n  return retval;\n}\n\nDEFMETHOD (__traditional__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} __traditional__ ()\nReturn true if Octave was invoked with the @w{@env{--traditional}}@ option.\n@end deftypefn */)\n{\n  return ovl (interp.traditional ());\n}\n\ntemporary_file_list::~temporary_file_list ()\n{\n  cleanup ();\n}\n\nvoid\ntemporary_file_list::insert (const std::string& file)\n{\n  m_files.insert (file);\n}\n\nvoid\ntemporary_file_list::cleanup ()\n{\n  while (! m_files.empty ())\n    {\n      auto it = m_files.begin ();\n\n      octave_unlink_wrapper (it->c_str ());\n\n      m_files.erase (it);\n    }\n}\n\n// The time we last time we changed directories.\nsys::time Vlast_chdir_time = 0.0;\n\nstatic void\ninitialize_version_info ()\n{\n  octave_value_list args (4);\n\n  args(0) = \"GNU Octave\";\n  args(1) = OCTAVE_VERSION;\n  args(2) = config::release ();\n  args(3) = OCTAVE_RELEASE_DATE;\n\n  F__version_info__ (args);\n}\n\nstatic void\nxerbla_abort ()\n{\n  error (\"Fortran procedure terminated by call to XERBLA\");\n}\n\nstatic void\ninitialize_xerbla_error_handler ()\n{\n  // The idea here is to force xerbla to be referenced so that we will\n  // link to our own version instead of the one provided by the BLAS\n  // library.  But numeric_limits<double>::NaN () should never be -1, so\n  // we should never actually call xerbla.  FIXME (again!): If this\n  // becomes a constant expression the test might be optimized away and\n  // then the reference to the function might also disappear.\n\n  if (numeric_limits<double>::NaN () == -1)\n    F77_FUNC (xerbla, XERBLA) (\"octave\", 13 F77_CHAR_ARG_LEN (6));\n\n  typedef void (*xerbla_handler_ptr) ();\n\n  typedef void (*octave_set_xerbla_handler_ptr) (xerbla_handler_ptr);\n\n  dynamic_library libs (\"\");\n\n  if (libs)\n    {\n      octave_set_xerbla_handler_ptr octave_set_xerbla_handler\n        = reinterpret_cast<octave_set_xerbla_handler_ptr>\n          (libs.search (\"octave_set_xerbla_handler\"));\n\n      if (octave_set_xerbla_handler)\n        octave_set_xerbla_handler (xerbla_abort);\n    }\n}\n\nOCTAVE_NORETURN static void\nlo_error_handler (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  verror_with_cfn (fmt, args);\n  va_end (args);\n\n  throw execution_exception ();\n}\n\nOCTAVE_NORETURN static void\nlo_error_with_id_handler (const char *id, const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  verror_with_id_cfn (id, fmt, args);\n  va_end (args);\n\n  throw execution_exception ();\n}\n\nstatic void\ninitialize_error_handlers ()\n{\n  set_liboctave_error_handler (lo_error_handler);\n  set_liboctave_error_with_id_handler (lo_error_with_id_handler);\n  set_liboctave_warning_handler (warning);\n  set_liboctave_warning_with_id_handler (warning_with_id);\n}\n\n// Create an interpreter object and perform initialization up to the\n// point of setting reading command history and setting the load\n// path.\n\ninterpreter::interpreter (application *app_context)\n  : m_app_context (app_context),\n    m_tmp_files (),\n    m_atexit_fcns (),\n    m_display_info (),\n    m_environment (),\n    m_evaluator (*this),\n    m_help_system (*this),\n    m_input_system (*this),\n    m_output_system (*this),\n    m_history_system (*this),\n    m_dynamic_loader (*this),\n    m_load_path (*this),\n    m_load_save_system (*this),\n    m_type_info (),\n    m_symbol_table (*this),\n    m_stream_list (*this),\n    m_child_list (),\n    m_url_handle_manager (),\n    m_cdef_manager (*this),\n    m_gtk_manager (*this),\n    m_event_manager (*this),\n    m_gh_manager (nullptr),\n    m_interactive (false),\n    m_read_site_files (true),\n    m_read_user_files (m_app_context != nullptr),\n    m_init_trace (false),\n    m_traditional (false),\n    m_inhibit_startup_message (false),\n    m_load_path_initialized (false),\n    m_history_initialized (false),\n    m_interrupt_all_in_process_group (true),\n    m_cancel_quit (false),\n    m_executing_finish_script (false),\n    m_executing_atexit (false),\n    m_initialized (false)\n{\n  // FIXME: When thread_local storage is used by default, this message\n  // should change to say something like\n  //\n  //   only one Octave interpreter may be active in any given thread\n\n  if (s_instance)\n    throw std::runtime_error\n    (\"only one Octave interpreter may be active\");\n\n  s_instance = this;\n\n#if defined (OCTAVE_HAVE_WINDOWS_UTF8_LOCALE)\n  // Force a UTF-8 locale on Windows if possible\n  std::setlocale (LC_ALL, \".UTF8\");\n#else\n  std::setlocale (LC_ALL, \"\");\n#endif\n  // Matlab uses \"C\" locale for LC_NUMERIC class regardless of local setting\n  std::setlocale (LC_NUMERIC, \"C\");\n  std::setlocale (LC_TIME, \"C\");\n  sys::env::putenv (\"LC_NUMERIC\", \"C\");\n  sys::env::putenv (\"LC_TIME\", \"C\");\n\n  // Perform system-dependent initialization here in case it has not\n  // already been executed (for example, by the application\n  // constructor).\n  sysdep_init ();\n\n  // Initialize the default floating point unit control state.\n  octave_set_default_fpucw ();\n\n  thread::init ();\n\n  octave_ieee_init ();\n\n  initialize_xerbla_error_handler ();\n\n  initialize_error_handlers ();\n\n  if (m_app_context)\n    {\n      install_signal_handlers ();\n      octave_unblock_signal_by_name (\"SIGTSTP\");\n    }\n  else\n    quit_allowed = false;\n\n  if (! m_app_context)\n    m_display_info.initialize ();\n\n  bool line_editing = false;\n\n  if (m_app_context)\n    {\n      // Embedded interpreters don't execute command line options.\n      const cmdline_options& options = m_app_context->options ();\n\n      // Make all command-line arguments available to startup files,\n      // including PKG_ADD files.\n\n      string_vector args = options.all_args ();\n\n      m_app_context->intern_argv (args);\n      intern_nargin (args.numel () - 1);\n\n      bool is_octave_program = m_app_context->is_octave_program ();\n\n      std::list<std::string> command_line_path = options.command_line_path ();\n\n      for (const auto& pth : command_line_path)\n        m_load_path.set_command_line_path (pth);\n\n      std::string exec_path = options.exec_path ();\n      if (! exec_path.empty ())\n        m_environment.exec_path (exec_path);\n\n      std::string image_path = options.image_path ();\n      if (! image_path.empty ())\n        m_environment.image_path (image_path);\n\n      if (! options.no_window_system ())\n        m_display_info.initialize ();\n\n      // Is input coming from a terminal?  If so, we are probably\n      // interactive.\n\n      // If stdin is not a tty, then we are reading commands from a\n      // pipe or a redirected file.\n      bool stdin_is_tty = octave_isatty_wrapper (fileno (stdin));\n\n      m_interactive = (! is_octave_program && stdin_is_tty\n                       && octave_isatty_wrapper (fileno (stdout)));\n\n      // Don't force interactive if we're already interactive (bug #60696).\n      bool forced_interactive = options.forced_interactive ();\n      if (m_interactive)\n        {\n          m_app_context->forced_interactive (false);\n          forced_interactive = false;\n        }\n\n      // Check if the user forced an interactive session.\n      if (forced_interactive)\n        m_interactive = true;\n\n      line_editing = options.line_editing ();\n      if ((! m_interactive || forced_interactive)\n          && ! options.forced_line_editing ())\n        line_editing = false;\n\n      m_traditional = options.traditional ();\n\n      // FIXME: if possible, perform the following actions directly\n      // instead of using the interpreter-level functions.\n\n      if (options.echo_commands ())\n        m_evaluator.echo\n        (tree_evaluator::ECHO_SCRIPTS | tree_evaluator::ECHO_FUNCTIONS\n         | tree_evaluator::ECHO_ALL);\n\n      std::string docstrings_file = options.docstrings_file ();\n      if (! docstrings_file.empty ())\n        Fbuilt_in_docstrings_file (*this, ovl (docstrings_file));\n\n      std::string doc_cache_file = options.doc_cache_file ();\n      if (! doc_cache_file.empty ())\n        Fdoc_cache_file (*this, ovl (doc_cache_file));\n\n      std::string info_file = options.info_file ();\n      if (! info_file.empty ())\n        Finfo_file (*this, ovl (info_file));\n\n      std::string info_program = options.info_program ();\n      if (! info_program.empty ())\n        Finfo_program (*this, ovl (info_program));\n\n      std::string texi_macros_file = options.texi_macros_file ();\n      if (! texi_macros_file.empty ())\n        Ftexi_macros_file (*this, ovl (texi_macros_file));\n    }\n  else\n    // No arguments for embedded interpreters\n    intern_nargin (0);\n\n  // FIXME: we defer creation of the gh_manager object because it\n  // creates a root_figure object that requires the display_info\n  // object, but that is currently only accessible through the global\n  // interpreter object and that is not available until after the\n  // interpreter::instance pointer is set (above).  It would be better\n  // if m_gh_manager could be an object value instead of a pointer and\n  // created as part of the interpreter initialization.  To do that,\n  // we should either make the display_info object independent of the\n  // interpreter object (does it really need to cache any\n  // information?) or defer creation of the root_figure object until\n  // it is actually needed.\n  m_gh_manager = new gh_manager (*this);\n\n  m_input_system.initialize (line_editing);\n\n  // These can come after command line args since none of them set any\n  // defaults that might be changed by command line options.\n\n  initialize_version_info ();\n\n  // This should be done before initializing the load path because\n  // some PKG_ADD files might need --traditional behavior.\n\n  if (m_traditional)\n    maximum_braindamage ();\n\n  octave_interpreter_ready = true;\n}\n\nOCTAVE_THREAD_LOCAL interpreter *interpreter::s_instance = nullptr;\n\ninterpreter::~interpreter ()\n{\n  if (! m_app_context)\n    shutdown ();\n\n  delete m_gh_manager;\n}\n\nvoid\ninterpreter::intern_nargin (octave_idx_type nargs)\n{\n  m_evaluator.set_auto_fcn_var (stack_frame::NARGIN, nargs);\n}\n\n// Read the history file unless a command-line option inhibits that.\n\nvoid\ninterpreter::initialize_history (bool read_history_file)\n{\n  if (! m_history_initialized)\n    {\n      // Allow command-line option to override.\n\n      if (m_app_context)\n        {\n          const cmdline_options& options = m_app_context->options ();\n\n          read_history_file = options.read_history_file ();\n\n          if (! read_history_file)\n            command_history::ignore_entries ();\n        }\n\n      m_history_system.initialize (read_history_file);\n\n      if (! m_app_context)\n        command_history::ignore_entries ();\n\n      m_history_initialized = true;\n    }\n}\n\n// Set the initial path to the system default unless command-line\n// option says to leave it empty.\n\nvoid\ninterpreter::initialize_load_path (bool set_initial_path)\n{\n  if (! m_load_path_initialized)\n    {\n      // Allow command-line option to override.\n\n      if (m_app_context)\n        {\n          const cmdline_options& options = m_app_context->options ();\n\n          set_initial_path = options.set_initial_path ();\n        }\n\n      // Temporarily set the execute_pkg_add function to one that\n      // catches exceptions.  This is better than wrapping\n      // load_path::initialize in a try-catch block because it will\n      // not stop executing PKG_ADD files at the first exception.\n      // It's also better than changing the default execute_pkg_add\n      // function to use safe_source file because that will normally\n      // be evaluated from the normal interpreter loop where exceptions\n      // are already handled.\n\n      unwind_action restore_add_hook (&load_path::set_add_hook, &m_load_path,\n                                      m_load_path.get_add_hook ());\n\n      m_load_path.set_add_hook ([this] (const std::string& dir) { this->execute_pkg_add (dir); });\n\n      m_load_path.initialize (set_initial_path);\n\n      m_load_path_initialized = true;\n    }\n}\n\n// This may be called separately from execute\n\nvoid\ninterpreter::initialize ()\n{\n  if (m_initialized)\n    return;\n\n  if (m_app_context)\n    {\n      const cmdline_options& options = m_app_context->options ();\n\n      if (options.experimental_terminal_widget ())\n        {\n          if (! options.gui ())\n            display_startup_message ();\n        }\n      else\n        display_startup_message ();\n    }\n  else\n    display_startup_message ();\n\n  // Wait to read the history file until the interpreter reads input\n  // files and begins evaluating commands.\n\n  initialize_history ();\n\n  // Initializing the load path may execute PKG_ADD files, so can't be\n  // done until the interpreter is ready to execute commands.\n\n  // Deferring it to the execute step also allows the path to be\n  // initialized between creating and execute the interpreter, for\n  // example, to set a custom path for an embedded interpreter.\n\n  initialize_load_path ();\n\n  octave_save_signal_mask ();\n\n  can_interrupt = true;\n\n  octave_signal_hook = respond_to_pending_signals;\n  octave_interrupt_hook = nullptr;\n\n  catch_interrupts ();\n\n  // FIXME: could we eliminate this variable or make it not be global?\n  // Global used to communicate with signal handler.\n  octave_initialized = true;\n\n  m_initialized = true;\n\n  run_startup_tests ();\n}\n\n// Note: this function is currently only used with the new\n// experimental terminal widget.\n\nvoid\ninterpreter::get_line_and_eval ()\n{\n  m_evaluator.get_line_and_eval ();\n}\n\n// Note: the following class is currently only used with the new\n// experimental terminal widget.\n\nclass cli_input_reader\n{\npublic:\n\n  cli_input_reader (interpreter& interp)\n    : m_interpreter (interp), m_thread () { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (cli_input_reader)\n\n  ~cli_input_reader ()\n  {\n    // FIXME: Would it be better to ensure that\n    // interpreter::get_line_and_eval exits and then call\n    // m_thread.join () here?\n\n    m_thread.detach ();\n  }\n\n  void start ()\n  {\n    m_thread = std::thread (&interpreter::get_line_and_eval, &m_interpreter);\n  }\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  std::thread m_thread;\n};\n\nvoid\ninterpreter::parse_and_execute (const std::string& input,\n                                bool& incomplete_parse)\n{\n  m_evaluator.parse_and_execute (input, incomplete_parse);\n}\n\n// FIXME: this function is intended to be executed only once.  Should\n// we enforce that restriction?\n\nint\ninterpreter::execute ()\n{\n  int exit_status = 0;\n\n  try\n    {\n      initialize ();\n\n      execute_startup_files ();\n\n      if (m_app_context)\n        {\n          const cmdline_options& options = m_app_context->options ();\n\n          if (m_app_context->have_eval_option_code ())\n            {\n              int status = execute_eval_option_code ();\n\n              if (status )\n                exit_status = status;\n\n              if (! options.persist ())\n                {\n                  shutdown ();\n\n                  return exit_status;\n                }\n            }\n\n          // If there is an extra argument, see if it names a file to\n          // read.  Additional arguments are taken as command line options\n          // for the script.\n\n          if (m_app_context->have_script_file ())\n            {\n              int status = execute_command_line_file ();\n\n              if (status)\n                exit_status = status;\n\n              if (! options.persist ())\n                {\n                  shutdown ();\n\n                  return exit_status;\n                }\n            }\n\n          if (options.forced_interactive ())\n            command_editor::blink_matching_paren (false);\n\n          if (options.server ())\n            exit_status = server_loop ();\n          else if (options.experimental_terminal_widget ())\n            {\n              if (options.gui ())\n                {\n                  m_event_manager.start_gui (true);\n\n                  exit_status = server_loop ();\n                }\n              else\n                {\n                  // Use an object so that the thread started for the\n                  // reader will be cleaned up no matter how we exit\n                  // this function.\n\n                  cli_input_reader reader (*this);\n\n                  reader.start ();\n\n                  exit_status = server_loop ();\n                }\n            }\n          else\n            exit_status = main_loop ();\n\n          shutdown ();\n        }\n    }\n  catch (const exit_exception& xe)\n    {\n      exit_status = xe.exit_status ();\n\n      shutdown ();\n    }\n\n  return exit_status;\n}\n\n// Call a function with exceptions handled to avoid problems with\n// errors while shutting down.\n\n#define OCTAVE_IGNORE_EXCEPTION(E)                                      \\\n  catch (E)                                                             \\\n    {                                                                   \\\n      recover_from_exception ();                                        \\\n                                                                        \\\n      std::cerr << \"error: ignoring \" #E \" while preparing to exit\"     \\\n                << std::endl;                                           \\\n    }\n\n#define OCTAVE_SAFE_CALL(F, ARGS)                                       \\\n  do                                                                    \\\n    {                                                                   \\\n      try                                                               \\\n        {                                                               \\\n          error_system& es = get_error_system ();                       \\\n          unwind_action restore_debug_on_error                          \\\n            (&error_system::set_debug_on_error, &es,                    \\\n             es.debug_on_error ());                                     \\\n                                                                        \\\n          unwind_action restore_debug_on_warning                        \\\n            (&error_system::set_debug_on_warning, &es,                  \\\n             es.debug_on_warning ());                                   \\\n                                                                        \\\n          es.debug_on_error (false);                                    \\\n          es.debug_on_warning (false);                                  \\\n                                                                        \\\n          F ARGS;                                                       \\\n        }                                                               \\\n      OCTAVE_IGNORE_EXCEPTION (const exit_exception&)                   \\\n      OCTAVE_IGNORE_EXCEPTION (const interrupt_exception&)              \\\n      OCTAVE_IGNORE_EXCEPTION (const execution_exception&)              \\\n      OCTAVE_IGNORE_EXCEPTION (const std::bad_alloc&)                   \\\n    }                                                                   \\\n  while (0)\n\nvoid\ninterpreter::shutdown ()\n{\n  // Attempt to prevent more than one call to shutdown.\n\n  if (! m_initialized)\n    return;\n\n  m_initialized = false;\n\n  OCTAVE_SAFE_CALL (feval, (\"close\", ovl (\"all\"), 0));\n\n  // Any atexit functions added after this function call won't be\n  // executed.  Each atexit function is executed with\n  // OCTAVE_SAFE_CALL, so we don't need that here.\n\n  execute_atexit_fcns ();\n\n  // Clear all functions and variables while the event manager is\n  // still processing events and notify the event manager.  This way,\n  // the workspace model will be cleared before the GUI exits.\n\n  // FIXME: This approach seems a bit fragile since there could be\n  // other places in the GUI that have references to interpreter\n  // objects.  How can we reliably ensure that they are all removed\n  // before the interpreter exits?  Maybe the best solution is to\n  // always start the GUI from the interpreter and close it when the\n  // interpreter exits?  However, the workspace model is owned by the\n  // base_qobject object not the workspace viewer or the main window,\n  // so simply closing the GUI window(s) is not sufficient.  See also\n  // bug #61994.\n\n  // Note that we don't force symbols to be cleared, so we will\n  // respect mlock at this point.  Later, we'll force all variables\n  // and functions to be cleared.\n\n  OCTAVE_SAFE_CALL (clear_all, ());\n  OCTAVE_SAFE_CALL (m_event_manager.clear_workspace, ());\n\n  // If we are attached to a GUI, queue and event to close it (only\n  // works with the new terminal widget), process pending events and\n  // disable the link.\n\n  OCTAVE_SAFE_CALL (m_event_manager.close_gui, ());\n  OCTAVE_SAFE_CALL (m_event_manager.process_events, (true));\n  OCTAVE_SAFE_CALL (m_event_manager.disable, ());\n\n  OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ());\n\n  // We may still have some figures.  Close them.\n\n  OCTAVE_SAFE_CALL (feval, (\"close\", ovl (\"all\"), 0));\n\n  // What is supposed to happen if a figure has a closerequestfcn or\n  // deletefcn callback registered that creates other figures or\n  // variables?  What if those variables are classdef objects with\n  // destructors that can create figures?  The possibilities are\n  // endless.  At some point, we have to give up and force execution\n  // to end.\n\n  // Note that we again don't force symbols to be cleared, so we\n  // continue to respect mlock here.  Later, we'll force all variables\n  // and functions to be cleared.\n\n  OCTAVE_SAFE_CALL (clear_all, ());\n\n  // Do this explicitly so that destructors for mex file objects\n  // are called, so that functions registered with mexAtExit are\n  // called.\n\n  OCTAVE_SAFE_CALL (m_symbol_table.clear_mex_functions, ());\n\n  OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ());\n\n  OCTAVE_SAFE_CALL (m_history_system.write_timestamp, ());\n\n  if (! command_history::ignoring_entries ())\n    OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ());\n\n  OCTAVE_SAFE_CALL (m_gtk_manager.unload_all_toolkits, ());\n\n  // Now that the graphics toolkits have been unloaded, force all\n  // symbols to be cleared.\n\n  OCTAVE_SAFE_CALL (clear_all, (true));\n\n  // FIXME: May still need something like this to ensure that\n  // destructors for class objects will run properly.  Should that be\n  // done earlier?  Before or after atexit functions are executed?\n  // What will happen if the destructor for an obect attempts to\n  // display a figure?\n\n  OCTAVE_SAFE_CALL (m_symbol_table.cleanup, ());\n\n  OCTAVE_SAFE_CALL (sysdep_cleanup, ());\n\n  OCTAVE_SAFE_CALL (flush_stdout, ());\n\n  // Don't call singleton_cleanup_list::cleanup until we have the\n  // problems with registering/unregistering types worked out.  For\n  // example, uncomment the following line, then use the make_int\n  // function from the examples directory to create an integer\n  // object and then exit Octave.  Octave should crash with a\n  // segfault when cleaning up the typinfo singleton.  We need some\n  // way to force new octave_value_X types that are created in\n  // .oct files to be unregistered when the .oct file shared library\n  // is unloaded.\n  //\n  // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ());\n}\n\nvoid\ninterpreter::execute_atexit_fcns ()\n{\n  // Prevent atexit functions from adding new functions to the list.\n  m_executing_atexit = true;\n\n  while (! m_atexit_fcns.empty ())\n    {\n      std::string fcn = m_atexit_fcns.front ();\n\n      m_atexit_fcns.pop_front ();\n\n      OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0));\n\n      OCTAVE_SAFE_CALL (flush_stdout, ());\n    }\n}\n\nvoid\ninterpreter::run_startup_tests ()\n{\n  bool inhibit_startup_tests = false;\n\n  if (m_app_context)\n    {\n      const cmdline_options& options = m_app_context->options ();\n\n      inhibit_startup_tests = options.inhibit_startup_tests ();\n    }\n\n  if (! inhibit_startup_tests)\n    {\n      // Check if BLAS implementation returns single precision values\n      F77_REAL retval = 0.0;\n      F77_INT n = 2;\n      F77_REAL x[2] = {1.0, 2.0};\n      F77_REAL y[2] = {3.0, 4.0};\n      F77_FUNC (xsdot, XSDOT) (n, x, 1, y, 1, retval);\n\n      if (retval != 11.0f)\n        {\n          std::cerr << \"BLAS implementation returns incorrect single \"\n                       \"precision floating-point type\" << std::endl;\n          quit (1, true, false);\n        }\n    }\n}\n\nvoid\ninterpreter::display_startup_message () const\n{\n  bool inhibit_startup_message = false;\n\n  if (m_app_context)\n    {\n      const cmdline_options& options = m_app_context->options ();\n\n      inhibit_startup_message = options.inhibit_startup_message ();\n    }\n\n  if (m_interactive && ! inhibit_startup_message)\n    std::cout << octave_startup_message () << \"\\n\" << std::endl;\n}\n\n// Initialize by reading startup files.  Return nonzero if an exception\n// occurs when reading any of them, but don't exit early because of an\n// exception.\n\nint\ninterpreter::execute_startup_files ()\n{\n  bool read_site_files = m_read_site_files;\n  bool read_user_files = m_read_user_files;\n  bool trace = m_init_trace;\n  bool inhibit_startup_message = m_inhibit_startup_message;\n\n  if (m_app_context)\n    {\n      const cmdline_options& options = m_app_context->options ();\n\n      read_site_files = options.read_site_files ();\n      read_user_files = options.read_user_files ();\n      trace = options.init_trace ();\n      inhibit_startup_message = options.inhibit_startup_message ();\n    }\n\n  trace = (trace && ! inhibit_startup_message);\n\n  bool require_file = false;\n\n  std::string context;\n\n  int exit_status = 0;\n\n  if (read_site_files)\n    {\n      // Execute commands from the site-wide configuration file.\n      // First from the file $(prefix)/lib/octave/site/m/octaverc\n      // (if it exists), then from the file\n      // $(prefix)/share/octave/$(version)/m/octaverc (if it exists).\n\n      int status = safe_source_file (config::local_site_defaults_file (),\n                                     context, trace, require_file);\n\n      if (status)\n        exit_status = status;\n\n      status = safe_source_file (config::site_defaults_file (),\n                                 context, trace, require_file);\n\n      if (status)\n        exit_status = status;\n    }\n\n  if (read_user_files)\n    {\n      // Try to execute commands from the Matlab compatible startup.m file\n      // if it exists anywhere in the load path when starting Octave.\n      std::string ff_startup_m = file_in_path (\"startup.m\", \"\");\n\n      if (! ff_startup_m.empty ())\n        {\n          int parse_status = 0;\n\n          try\n            {\n              eval_string (std::string (\"startup\"), false, parse_status, 0);\n            }\n          catch (const interrupt_exception&)\n            {\n              recover_from_exception ();\n            }\n          catch (const execution_exception& ee)\n            {\n              handle_exception (ee);\n            }\n        }\n\n      // Try to execute commands from $CONFIG/octave/octaverc, where\n      // $CONFIG is the platform-dependent location for user local\n      // configuration files.\n\n      std::string user_config_dir = sys::env::get_user_config_directory ();\n\n      std::string cfg_dir = user_config_dir + sys::file_ops::dir_sep_str ()\n                            + \"octave\";\n\n      std::string cfg_rc = sys::env::make_absolute (\"octaverc\", cfg_dir);\n\n      if (! cfg_rc.empty ())\n        {\n          int status = safe_source_file (cfg_rc, context, trace,\n                                         require_file);\n\n          if (status)\n            exit_status = status;\n        }\n\n      // Try to execute commands from $HOME/$OCTAVE_INITFILE and\n      // $OCTAVE_INITFILE.  If $OCTAVE_INITFILE is not set,\n      // .octaverc is assumed.\n\n      bool home_rc_already_executed = false;\n\n      std::string initfile = sys::env::getenv (\"OCTAVE_INITFILE\");\n\n      if (initfile.empty ())\n        initfile = \".octaverc\";\n\n      std::string home_dir = sys::env::get_home_directory ();\n\n      std::string home_rc = sys::env::make_absolute (initfile, home_dir);\n\n      std::string local_rc;\n\n      if (! home_rc.empty ())\n        {\n          int status = safe_source_file (home_rc, context, trace,\n                                         require_file);\n\n          if (status)\n            exit_status = status;\n\n          // Names alone are not enough.\n\n          if (sys::file_exists (home_rc))\n            {\n              // We want to check for curr_dir after executing home_rc\n              // because doing that may change the working directory.\n\n              local_rc = sys::env::make_absolute (initfile);\n\n              home_rc_already_executed = sys::same_file (home_rc, local_rc);\n            }\n        }\n\n      if (! home_rc_already_executed)\n        {\n          if (local_rc.empty ())\n            local_rc = sys::env::make_absolute (initfile);\n\n          int status = safe_source_file (local_rc, context, trace,\n                                         require_file);\n\n          if (status)\n            exit_status = status;\n        }\n    }\n\n  if (m_interactive && trace)\n    octave_stdout << std::endl;\n\n  return exit_status;\n}\n\n// Execute any code specified with --eval 'CODE'\n\nint\ninterpreter::execute_eval_option_code ()\n{\n  if (! m_app_context)\n    return 0;\n\n  const cmdline_options& options = m_app_context->options ();\n\n  std::string code_to_eval = options.code_to_eval ();\n\n  unwind_protect_var<bool> upv (m_interactive, false);\n\n  int parse_status = 0;\n\n  try\n    {\n      eval_string (code_to_eval, false, parse_status, 0);\n    }\n  catch (const interrupt_exception&)\n    {\n      recover_from_exception ();\n\n      return 1;\n    }\n  catch (const execution_exception& ee)\n    {\n      handle_exception (ee);\n\n      return 1;\n    }\n\n  return parse_status;\n}\n\nint\ninterpreter::execute_command_line_file ()\n{\n  if (! m_app_context)\n    return 0;\n\n  const cmdline_options& options = m_app_context->options ();\n\n  string_vector args = options.all_args ();\n\n  void (interpreter::*interactive_fptr) (bool) = &interpreter::interactive;\n  unwind_action restore_interactive (interactive_fptr, this, m_interactive);\n\n  unwind_action restore_argv (&application::intern_argv, m_app_context, args);\n\n  unwind_action restore_nargin (&interpreter::intern_nargin, this,\n                                args.numel () - 1);\n\n  void (application::*program_invocation_name_fptr) (const std::string&)\n    = &application::program_invocation_name;\n  unwind_action restore_program_invocation_name\n  (program_invocation_name_fptr, m_app_context,\n   application::program_invocation_name ());\n\n  void (application::*program_name_fptr) (const std::string&)\n    = &application::program_name;\n  unwind_action restore_program_name\n  (program_name_fptr, m_app_context, application::program_name ());\n\n  m_interactive = false;\n\n  // If we are running an executable script (#! /bin/octave) then\n  // we should only see the args passed to the script.\n\n  string_vector script_args = options.remaining_args ();\n\n  m_app_context->intern_argv (script_args);\n  intern_nargin (script_args.numel () - 1);\n\n  std::string fname = script_args[0];\n\n  m_app_context->set_program_names (fname);\n\n  std::string context;\n  bool verbose = false;\n  bool require_file = true;\n\n  return safe_source_file (fname, context, verbose, require_file);\n}\n\nint\ninterpreter::main_loop ()\n{\n  command_editor::add_event_hook (release_unreferenced_dynamic_libraries);\n\n  return m_evaluator.repl ();\n}\n\nint\ninterpreter::server_loop ()\n{\n  return m_evaluator.server_loop ();\n}\n\ntree_evaluator&\ninterpreter::get_evaluator ()\n{\n  return m_evaluator;\n}\n\nstream_list&\ninterpreter::get_stream_list ()\n{\n  return m_stream_list;\n}\n\nurl_handle_manager&\ninterpreter::get_url_handle_manager ()\n{\n  return m_url_handle_manager;\n}\n\nsymbol_scope\ninterpreter::get_top_scope () const\n{\n  return m_evaluator.get_top_scope ();\n}\n\nsymbol_scope\ninterpreter::get_current_scope () const\n{\n  return m_evaluator.get_current_scope ();\n}\n\nsymbol_scope\ninterpreter::require_current_scope (const std::string& who) const\n{\n  symbol_scope scope = get_current_scope ();\n\n  if (! scope)\n    error (\"%s: symbol table scope missing\", who.c_str ());\n\n  return scope;\n}\n\nprofiler&\ninterpreter::get_profiler ()\n{\n  return m_evaluator.get_profiler ();\n}\n\nint\ninterpreter::chdir (const std::string& dir)\n{\n  std::string xdir = sys::file_ops::tilde_expand (dir);\n\n  int cd_ok = sys::env::chdir (xdir);\n\n  if (! cd_ok)\n    error (\"%s: %s\", dir.c_str (), std::strerror (errno));\n\n  Vlast_chdir_time.stamp ();\n\n  // FIXME: should these actions be handled as a list of functions\n  // to call so users can add their own chdir handlers?\n\n  m_load_path.read_dir_config (\".\");\n  m_load_path.update ();\n  // Updating the last prompt time stamp avoids skipping a fcn-info refresh\n  // so that functions in the new current directory can shadow functions\n  // further back in the load path order.\n  Vlast_prompt_time.stamp ();\n\n  m_event_manager.directory_changed (sys::env::get_current_directory ());\n\n  return cd_ok;\n}\n\nvoid\ninterpreter::mlock (bool skip_first) const\n{\n  m_evaluator.mlock (skip_first);\n}\n\nvoid\ninterpreter::munlock (bool skip_first) const\n{\n  m_evaluator.munlock (skip_first);\n}\n\nbool\ninterpreter::mislocked (bool skip_first) const\n{\n  return m_evaluator.mislocked (skip_first);\n}\n\nvoid\ninterpreter::munlock (const char *nm)\n{\n  if (! nm)\n    error (\"munlock: invalid value for NAME\");\n\n  munlock (std::string (nm));\n}\n\nvoid\ninterpreter::munlock (const std::string& nm)\n{\n  octave_value val = m_symbol_table.find_function (nm);\n\n  if (val.is_defined ())\n    {\n      octave_function *fcn = val.function_value ();\n\n      if (fcn)\n        fcn->unlock ();\n    }\n}\n\nbool\ninterpreter::mislocked (const char *nm)\n{\n  if (! nm)\n    error (\"mislocked: invalid value for NAME\");\n\n  return mislocked (std::string (nm));\n}\n\nbool\ninterpreter::mislocked (const std::string& nm)\n{\n  bool retval = false;\n\n  octave_value val = m_symbol_table.find_function (nm);\n\n  if (val.is_defined ())\n    {\n      octave_function *fcn = val.function_value ();\n\n      if (fcn)\n        retval = fcn->islocked ();\n    }\n\n  return retval;\n}\n\nstd::string\ninterpreter::mfilename (const std::string& opt) const\n{\n  return m_evaluator.mfilename (opt);\n}\n\noctave_value_list\ninterpreter::eval_string (const std::string& eval_str,\n                          bool silent, int& parse_status,\n                          int nargout)\n{\n  return m_evaluator.eval_string (eval_str, silent, parse_status, nargout);\n}\n\noctave_value\ninterpreter::eval_string (const std::string& eval_str,\n                          bool silent, int& parse_status)\n{\n  return m_evaluator.eval_string (eval_str, silent, parse_status);\n}\n\noctave_value_list\ninterpreter::eval_string (const octave_value& arg,\n                          bool silent, int& parse_status,\n                          int nargout)\n{\n  return m_evaluator.eval_string (arg, silent, parse_status, nargout);\n}\n\noctave_value_list\ninterpreter::eval (const std::string& try_code,\n                   int nargout)\n{\n  return m_evaluator.eval (try_code, nargout);\n}\n\noctave_value_list\ninterpreter::eval (const std::string& try_code,\n                   const std::string& catch_code,\n                   int nargout)\n{\n  return m_evaluator.eval (try_code, catch_code, nargout);\n}\n\noctave_value_list\ninterpreter::evalin (const std::string& context,\n                     const std::string& try_code,\n                     int nargout)\n{\n  return m_evaluator.evalin (context, try_code, nargout);\n}\n\noctave_value_list\ninterpreter::evalin (const std::string& context,\n                     const std::string& try_code,\n                     const std::string& catch_code,\n                     int nargout)\n{\n  return m_evaluator.evalin (context, try_code, catch_code, nargout);\n}\n\n//! Evaluate an Octave function (built-in or interpreted) and return\n//! the list of result values.\n//!\n//! @param name The name of the function to call.\n//! @param args The arguments to the function.\n//! @param nargout The number of output arguments expected.\n//! @return A list of output values.  The length of the list is not\n//!         necessarily the same as @c nargout.\n\noctave_value_list\ninterpreter::feval (const char *name,\n                    const octave_value_list& args,\n                    int nargout)\n{\n  return feval (std::string (name), args, nargout);\n}\n\noctave_value_list\ninterpreter::feval (const std::string& name,\n                    const octave_value_list& args,\n                    int nargout)\n{\n  octave_value fcn = m_symbol_table.find_function (name, args);\n\n  if (fcn.is_undefined ())\n    error (\"feval: function '%s' not found\", name.c_str ());\n\n  octave_function *of = fcn.function_value ();\n\n  return of->call (m_evaluator, nargout, args);\n}\n\noctave_value_list\ninterpreter::feval (octave_function *fcn,\n                    const octave_value_list& args,\n                    int nargout)\n{\n  if (fcn)\n    return fcn->call (m_evaluator, nargout, args);\n\n  return octave_value_list ();\n}\n\noctave_value_list\ninterpreter::feval (const octave_value& val,\n                    const octave_value_list& args,\n                    int nargout)\n{\n  // FIXME: do we really want to silently return an empty ovl if\n  // the function object is undefined?  It's essentially what the\n  // version above that accepts a pointer to an octave_function\n  // object does and some code was apparently written to rely on it\n  // (for example, __ode15__).\n\n  if (val.is_undefined ())\n    return ovl ();\n\n  if (val.is_function ())\n    {\n      return feval (val.function_value (), args, nargout);\n    }\n  else if (val.is_function_handle () || val.is_inline_function ())\n    {\n      // This covers function handles, inline functions, and anonymous\n      //  functions.\n\n      std::list<octave_value_list> arg_list;\n      arg_list.push_back (args);\n\n      // FIXME: could we make octave_value::subsref a const method?\n      // It would be difficult because there are instances of\n      // incrementing the reference count inside subsref methods,\n      // which means they can't be const with the current way of\n      // handling reference counting.\n\n      octave_value xval = val;\n      return xval.subsref (\"(\", arg_list, nargout);\n    }\n  else if (val.is_string ())\n    {\n      return feval (val.string_value (), args, nargout);\n    }\n  else\n    error (\"feval: first argument must be a string, inline function, or a function handle\");\n\n  return ovl ();\n}\n\n//! Evaluate an Octave function (built-in or interpreted) and return\n//! the list of result values.\n//!\n//! @param args The first element of @c args is the function to call.\n//!             It may be the name of the function as a string, a function\n//!             handle, or an inline function.  The remaining arguments are\n//!             passed to the function.\n//! @param nargout The number of output arguments expected.\n//! @return A list of output values.  The length of the list is not\n//!         necessarily the same as @c nargout.\n\noctave_value_list\ninterpreter::feval (const octave_value_list& args,\n                    int nargout)\n{\n  if (args.length () == 0)\n    error (\"feval: first argument must be a string, inline function, or a function handle\");\n\n  octave_value f_arg = args(0);\n\n  octave_value_list tmp_args = args.slice (1, args.length () - 1, true);\n\n  return feval (f_arg, tmp_args, nargout);\n}\n\nstd::string\ninterpreter::inputname (int n, bool ids_only) const\n{\n  return m_evaluator.inputname (n, ids_only);\n}\n\noctave_value\ninterpreter::make_function_handle (const std::string& name)\n{\n  return m_evaluator.make_fcn_handle (name);\n}\n\nvoid\ninterpreter::install_variable (const std::string& name,\n                               const octave_value& value, bool global)\n{\n  m_evaluator.install_variable (name, value, global);\n}\n\noctave_value\ninterpreter::global_varval (const std::string& name) const\n{\n  return m_evaluator.global_varval (name);\n}\n\nvoid\ninterpreter::global_assign (const std::string& name,\n                            const octave_value& val)\n{\n  m_evaluator.global_assign (name, val);\n}\n\noctave_value\ninterpreter::top_level_varval (const std::string& name) const\n{\n  return m_evaluator.top_level_varval (name);\n}\n\nvoid\ninterpreter::top_level_assign (const std::string& name,\n                               const octave_value& val)\n{\n  m_evaluator.top_level_assign (name, val);\n}\n\nbool\ninterpreter::is_variable (const std::string& name) const\n{\n  return m_evaluator.is_variable (name);\n}\n\nbool\ninterpreter::is_local_variable (const std::string& name) const\n{\n  return m_evaluator.is_local_variable (name);\n}\n\noctave_value\ninterpreter::varval (const std::string& name) const\n{\n  return m_evaluator.varval (name);\n}\n\nvoid\ninterpreter::assign (const std::string& name,\n                     const octave_value& val)\n{\n  m_evaluator.assign (name, val);\n}\n\nvoid\ninterpreter::assignin (const std::string& context,\n                       const std::string& name,\n                       const octave_value& val)\n{\n  m_evaluator.assignin (context, name, val);\n}\n\nvoid\ninterpreter::source_file (const std::string& file_name,\n                          const std::string& context, bool verbose,\n                          bool require_file)\n{\n  m_evaluator.source_file (file_name, context, verbose, require_file);\n}\n\nbool\ninterpreter::at_top_level () const\n{\n  return m_evaluator.at_top_level ();\n}\n\nbool\ninterpreter::isglobal (const std::string& name) const\n{\n  return m_evaluator.is_global (name);\n}\n\noctave_value\ninterpreter::find (const std::string& name)\n{\n  return m_evaluator.find (name);\n}\n\nvoid\ninterpreter::clear_all (bool force)\n{\n  m_evaluator.clear_all (force);\n}\n\nvoid\ninterpreter::clear_objects ()\n{\n  m_evaluator.clear_objects ();\n}\n\nvoid\ninterpreter::clear_variable (const std::string& name)\n{\n  m_evaluator.clear_variable (name);\n}\n\nvoid\ninterpreter::clear_variable_pattern (const std::string& pattern)\n{\n  m_evaluator.clear_variable_pattern (pattern);\n}\n\nvoid\ninterpreter::clear_variable_regexp (const std::string& pattern)\n{\n  m_evaluator.clear_variable_regexp (pattern);\n}\n\nvoid\ninterpreter::clear_variables ()\n{\n  m_evaluator.clear_variables ();\n}\n\nvoid\ninterpreter::clear_global_variable (const std::string& name)\n{\n  m_evaluator.clear_global_variable (name);\n}\n\nvoid\ninterpreter::clear_global_variable_pattern (const std::string& pattern)\n{\n  m_evaluator.clear_global_variable_pattern (pattern);\n}\n\nvoid\ninterpreter::clear_global_variable_regexp (const std::string& pattern)\n{\n  m_evaluator.clear_global_variable_regexp (pattern);\n}\n\nvoid\ninterpreter::clear_global_variables ()\n{\n  m_evaluator.clear_global_variables ();\n}\n\nvoid\ninterpreter::clear_functions (bool force)\n{\n  m_symbol_table.clear_functions (force);\n}\n\nvoid\ninterpreter::clear_function (const std::string& name)\n{\n  m_symbol_table.clear_function (name);\n}\n\nvoid\ninterpreter::clear_symbol (const std::string& name)\n{\n  m_evaluator.clear_symbol (name);\n}\n\nvoid\ninterpreter::clear_function_pattern (const std::string& pat)\n{\n  m_symbol_table.clear_function_pattern (pat);\n}\n\nvoid\ninterpreter::clear_function_regexp (const std::string& pat)\n{\n  m_symbol_table.clear_function_regexp (pat);\n}\n\nvoid\ninterpreter::clear_symbol_pattern (const std::string& pat)\n{\n  return m_evaluator.clear_symbol_pattern (pat);\n}\n\nvoid\ninterpreter::clear_symbol_regexp (const std::string& pat)\n{\n  return m_evaluator.clear_symbol_regexp (pat);\n}\n\nstd::list<std::string>\ninterpreter::global_variable_names ()\n{\n  return m_evaluator.global_variable_names ();\n}\n\nstd::list<std::string>\ninterpreter::top_level_variable_names ()\n{\n  return m_evaluator.top_level_variable_names ();\n}\n\nstd::list<std::string>\ninterpreter::variable_names ()\n{\n  return m_evaluator.variable_names ();\n}\n\nstd::list<std::string>\ninterpreter::user_function_names ()\n{\n  return m_symbol_table.user_function_names ();\n}\n\nstd::list<std::string>\ninterpreter::autoloaded_functions () const\n{\n  return m_evaluator.autoloaded_functions ();\n}\n\n// May be used to send an interrupt signal to the interpreter from\n// another thread (for example, the GUI).\n\nvoid\ninterpreter::interrupt ()\n{\n  static int sigint = 0;\n  static bool first = true;\n\n  if (first)\n    {\n      octave_get_sig_number (\"SIGINT\", &sigint);\n      first = false;\n    }\n\n  // Send SIGINT to Octave and (optionally) all other processes in its\n  // process group.  The signal handler for SIGINT will set a global\n  // variable indicating an interrupt has happened.  That variable is\n  // checked in many places in the Octave interpreter and eventually\n  // results in an interrupt_exception being thrown.  Finally, that\n  // exception is caught and returns control to one of the\n  // read-eval-print loops or to the server loop.  We use a signal\n  // instead of just setting the global variables here so that we will\n  // probably send interrupt signals to any subprocesses as well as\n  // interrupt execution of the interpreter.\n\n  pid_t pid\n    = m_interrupt_all_in_process_group ? 0 : octave_getpid_wrapper ();\n\n  octave_kill_wrapper (pid, sigint);\n}\n\nvoid\ninterpreter::pause ()\n{\n  // FIXME: To be reliable, these tree_evaluator functions must be\n  // made thread safe.\n\n  m_evaluator.break_on_next_statement (true);\n  m_evaluator.reset_debug_state ();\n}\n\nvoid\ninterpreter::stop ()\n{\n  // FIXME: To be reliable, these tree_evaluator functions must be\n  // made thread safe.\n\n  if (m_evaluator.in_debug_repl ())\n    m_evaluator.dbquit (true);\n  else\n    interrupt ();\n}\n\nvoid\ninterpreter::resume ()\n{\n  // FIXME: To be reliable, these tree_evaluator functions must be\n  // made thread safe.\n\n  // FIXME: Should there be any feeback about not doing anything if\n  // not in debug mode?\n\n  if (m_evaluator.in_debug_repl ())\n    m_evaluator.dbcont ();\n}\n\noctave_value\ninterpreter::PS1 (const octave_value_list& args, int nargout)\n{\n  return m_input_system.PS1 (args, nargout);\n}\n\nstd::string\ninterpreter::PS1 () const\n{\n  return m_input_system.PS1 ();\n}\n\nstd::string\ninterpreter::PS1 (const std::string& s)\n{\n  return m_input_system.PS1 (s);\n}\n\nvoid\ninterpreter::set_PS1 (const std::string& s)\n{\n  m_input_system.set_PS1 (s);\n}\n\noctave_value\ninterpreter::PS2 (const octave_value_list& args, int nargout)\n{\n  return m_input_system.PS2 (args, nargout);\n}\n\nstd::string\ninterpreter::PS2 () const\n{\n  return m_input_system.PS2 ();\n}\n\nstd::string\ninterpreter::PS2 (const std::string& s)\n{\n  return m_input_system.PS2 (s);\n}\n\nvoid\ninterpreter::set_PS2 (const std::string& s)\n{\n  m_input_system.set_PS2 (s);\n}\n\noctave_value\ninterpreter::PS4 (const octave_value_list& args, int nargout)\n{\n  return m_evaluator.PS4 (args, nargout);\n}\n\nstd::string\ninterpreter::PS4 () const\n{\n  return m_evaluator.PS4 ();\n}\n\nstd::string\ninterpreter::PS4 (const std::string& s)\n{\n  return m_evaluator.PS4 (s);\n}\n\nvoid\ninterpreter::set_PS4 (const std::string& s)\n{\n  m_evaluator.set_PS4 (s);\n}\n\n// Provided for convenience.  Will be removed once we eliminate the\n// old terminal widget.\nbool\ninterpreter::experimental_terminal_widget () const\n{\n  if (! m_app_context)\n    return false;\n\n  // Embedded interpreters don't execute command line options.\n  const cmdline_options& options = m_app_context->options ();\n\n  return options.experimental_terminal_widget ();\n}\n\nvoid\ninterpreter::add_debug_watch_expression (const std::string& expr)\n{\n  m_evaluator.add_debug_watch_expression (expr);\n}\n\nvoid\ninterpreter::remove_debug_watch_expression (const std::string& expr)\n{\n  m_evaluator.remove_debug_watch_expression (expr);\n}\n\nvoid\ninterpreter::clear_debug_watch_expressions ()\n{\n  m_evaluator.clear_debug_watch_expressions ();\n}\n\nstd::set<std::string>\ninterpreter::debug_watch_expressions () const\n{\n  return m_evaluator.debug_watch_expressions ();\n}\n\nvoid\ninterpreter::handle_exception (const execution_exception& ee)\n{\n  error_system& es = get_error_system ();\n\n  es.save_exception (ee);\n\n  // FIXME: use a separate stream instead of std::cerr directly so that\n  // error messages can be redirected more easily?  Pass the message\n  // to an event manager function?\n  es.display_exception (ee);\n\n  recover_from_exception ();\n}\n\nvoid\ninterpreter::recover_from_exception ()\n{\n  if (octave_interrupt_state)\n    m_event_manager.interpreter_interrupted ();\n\n  can_interrupt = true;\n  octave_interrupt_state = 0;\n  octave_signal_caught = false;\n  octave_restore_signal_mask ();\n  catch_interrupts ();\n}\n\nvoid\ninterpreter::mark_for_deletion (const std::string& file)\n{\n  m_tmp_files.insert (file);\n}\n\nvoid\ninterpreter::cleanup_tmp_files ()\n{\n  m_tmp_files.cleanup ();\n}\n\nvoid\ninterpreter::quit (int exit_status, bool force, bool confirm)\n{\n  if (! force)\n    {\n      try\n        {\n          bool cancel = false;\n\n          if (symbol_exist (\"finish.m\", \"file\"))\n            {\n              unwind_protect_var<bool> upv1 (m_executing_finish_script, true);\n              unwind_protect_var<bool> upv2 (m_cancel_quit);\n\n              evalin (\"base\", \"finish\", 0);\n\n              cancel = m_cancel_quit;\n            }\n\n          if (cancel)\n            return;\n\n          // Check for confirmation.\n\n          if (confirm && ! m_event_manager.confirm_shutdown ())\n            return;\n        }\n      catch (const execution_exception&)\n        {\n          // Catch execution_exceptions so we don't throw an\n          // exit_exception if there is an in finish.m.  But throw it\n          // again so that will be handled as any other\n          // execution_exception by the evaluator.  This way, errors\n          // will be ignored properly and we won't exit if quit is\n          // called recursively from finish.m.\n\n          throw;\n        }\n    }\n\n  throw exit_exception (exit_status);\n}\n\nvoid\ninterpreter::add_atexit_fcn (const std::string& fname)\n{\n  if (m_executing_atexit)\n    return;\n\n  m_atexit_fcns.push_front (fname);\n}\n\nbool\ninterpreter::remove_atexit_fcn (const std::string& fname)\n{\n  bool found = false;\n\n  for (auto it = m_atexit_fcns.begin ();\n       it != m_atexit_fcns.end (); it++)\n    {\n      if (*it == fname)\n        {\n          m_atexit_fcns.erase (it);\n          found = true;\n          break;\n        }\n    }\n\n  return found;\n}\n\n// What internal options get configured by --traditional.\n\nvoid\ninterpreter::maximum_braindamage ()\n{\n  PS1 (\">> \");\n  PS2 (\"\");\n  PS4 (\"\");\n  error_system& es = get_error_system ();\n  es.beep_on_error (true);\n  Fconfirm_recursive_rmdir (ovl (false));\n  m_load_save_system.crash_dumps_octave_core (false);\n  Foptimize_diagonal_matrix (ovl (false));\n  Foptimize_permutation_matrix (ovl (false));\n  Foptimize_range (ovl (false));\n  Ffixed_point_format (ovl (true));\n  m_history_system.timestamp_format_string (\"%%-- %D %I:%M %p --%%\");\n  Fprint_struct_array_contents (ovl (true));\n  m_load_save_system.save_default_options (\"-mat-binary\");\n  Fstruct_levels_to_print (ovl (0));\n\n  es.disable_warning (\"Octave:abbreviated-property-match\");\n  es.disable_warning (\"Octave:colon-nonscalar-argument\");\n  es.disable_warning (\"Octave:data-file-in-path\");\n  es.disable_warning (\"Octave:empty-index\");\n  es.disable_warning (\"Octave:function-name-clash\");\n  es.disable_warning (\"Octave:possible-matlab-short-circuit-operator\");\n}\n\nvoid\ninterpreter::execute_pkg_add (const std::string& dir)\n{\n  try\n    {\n      m_load_path.execute_pkg_add (dir);\n    }\n  catch (const interrupt_exception&)\n    {\n      recover_from_exception ();\n    }\n  catch (const execution_exception& ee)\n    {\n      handle_exception (ee);\n    }\n}\n\n// Execute commands from a file and catch potential exceptions in a consistent\n// way.  This function should be called anywhere we might parse and execute\n// commands from a file before we have entered the main loop in\n// toplev.cc.\n\nint\ninterpreter::safe_source_file (const std::string& file_name,\n                               const std::string& context,\n                               bool verbose, bool require_file)\n{\n  try\n    {\n      source_file (file_name, context, verbose, require_file);\n    }\n  catch (const interrupt_exception&)\n    {\n      recover_from_exception ();\n\n      return 1;\n    }\n  catch (const execution_exception& ee)\n    {\n      handle_exception (ee);\n\n      return 1;\n    }\n\n  return 0;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/interpreter.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_interpreter_h)\n#define octave_interpreter_h 1\n\n#include \"octave-config.h\"\n\n#include <atomic>\n#include <map>\n#include <set>\n#include <stack>\n#include <string>\n\n#include \"child-list.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n#include \"str-vec.h\"\n\n#include \"cdef-manager.h\"\n#include \"display.h\"\n#include \"dynamic-ld.h\"\n#include \"environment.h\"\n#include \"error.h\"\n#include \"event-manager.h\"\n#include \"gh-manager.h\"\n#include \"graphics.h\"\n#include \"gtk-manager.h\"\n#include \"help.h\"\n#include \"input.h\"\n#include \"load-path.h\"\n#include \"load-save.h\"\n#include \"oct-hist.h\"\n#include \"oct-stream.h\"\n#include \"ov-typeinfo.h\"\n#include \"pager.h\"\n#include \"pt-eval.h\"\n#include \"symtab.h\"\n#include \"url-handle-manager.h\"\n\nextern OCTINTERP_API bool quit_allowed;\n\n// TRUE means we are ready to interpret commands, but not everything\n// is ready for interactive use.\nextern OCTINTERP_API bool octave_interpreter_ready;\n\n// TRUE means we've processed all the init code and we are good to go.\nextern OCTINTERP_API std::atomic<bool> octave_initialized;\n\n#include \"oct-time.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass profiler;\nclass child_list;\nclass push_parser;\n\n// The time we last time we changed directories.\nextern sys::time Vlast_chdir_time;\n\n// The application object contains a pointer to the current\n// interpreter and the interpreter contains a pointer back to the\n// application context so we need a forward declaration for one (or\n// both) of them...\n\nclass application;\n\nclass temporary_file_list\n{\npublic:\n\n  temporary_file_list () : m_files () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (temporary_file_list)\n\n  ~temporary_file_list ();\n\n  void insert (const std::string& file);\n\n  void cleanup ();\n\nprivate:\n\n  // List of temporary files to delete when we exit.\n  std::set<std::string> m_files;\n\n};\n\nclass OCTINTERP_API interpreter\n{\npublic:\n\n  // Create an interpreter object and perform basic initialization.\n\n  interpreter (application *app_context = nullptr);\n\n  OCTAVE_DISABLE_COPY_MOVE (interpreter)\n\n  // Clean up the interpreter object.\n\n  ~interpreter ();\n\n  void intern_nargin (octave_idx_type nargs);\n\n  // If creating an embedded interpreter, you may inhibit reading\n  // the command history file by calling initialize_history with\n  // read_history_file = false prior to calling initialize.\n\n  void initialize_history (bool read_history_file = false);\n\n  // If creating an embedded interpreter, you may inhibit setting\n  // the default compiled-in path by calling initialize_load_path\n  // with set_initial_path = false prior calling initialize.  After\n  // that, you can add directories to the load path to set up a\n  // custom path.\n\n  void initialize_load_path (bool set_initial_path = true);\n\n  // Load command line history, set the load path.\n\n  void initialize ();\n\n  // Note: GET_LINE_AND_EVAL is only used by new experimental terminal\n  // widget.\n\n  void get_line_and_eval ();\n\n  // Parse a line of input.  If input ends at a complete statement\n  // boundary, execute the resulting parse tree.  Useful to handle\n  // parsing user input when running in server mode.\n\n  void parse_and_execute (const std::string& input, bool& incomplete_parse);\n\n  // Initialize the interpreter (if not already done by an explicit\n  // call to initialize), execute startup files, --eval option code,\n  // script files, and/or interactive commands.\n\n  int execute ();\n\n  bool server_mode () const { return m_evaluator.server_mode (); }\n\n  bool interactive () const\n  {\n    return m_interactive;\n  }\n\n  void interactive (bool arg)\n  {\n    m_interactive = arg;\n  }\n\n  void read_site_files (bool flag)\n  {\n    m_read_site_files = flag;\n  }\n\n  void read_user_files (bool flag)\n  {\n    m_read_user_files = flag;\n  }\n\n  void init_trace (bool flag)\n  {\n    m_init_trace = flag;\n  }\n\n  void traditional (bool flag)\n  {\n    m_traditional = flag;\n  }\n\n  bool traditional () const\n  {\n    return m_traditional;\n  }\n\n  void inhibit_startup_message (bool flag)\n  {\n    m_inhibit_startup_message = flag;\n  }\n\n  bool in_top_level_repl () const\n  {\n    return m_evaluator.in_top_level_repl ();\n  }\n\n  bool is_initialized () const\n  {\n    return m_initialized;\n  }\n\n  void interrupt_all_in_process_group (bool b)\n  {\n    m_interrupt_all_in_process_group = b;\n  }\n\n  bool interrupt_all_in_process_group () const\n  {\n    return m_interrupt_all_in_process_group;\n  }\n\n  application * get_app_context ()\n  {\n    return m_app_context;\n  }\n\n  display_info& get_display_info ()\n  {\n    return m_display_info;\n  }\n\n  environment& get_environment ()\n  {\n    return m_environment;\n  }\n\n  error_system& get_error_system ()\n  {\n    return m_evaluator.get_error_system ();\n  }\n\n  tree_evaluator& get_evaluator ();\n\n  help_system& get_help_system ()\n  {\n    return m_help_system;\n  }\n\n  input_system& get_input_system ()\n  {\n    return m_input_system;\n  }\n\n  output_system& get_output_system ()\n  {\n    return m_output_system;\n  }\n\n  history_system& get_history_system ()\n  {\n    return m_history_system;\n  }\n\n  dynamic_loader& get_dynamic_loader ()\n  {\n    return m_dynamic_loader;\n  }\n\n  load_path& get_load_path ()\n  {\n    return m_load_path;\n  }\n\n  load_save_system& get_load_save_system ()\n  {\n    return m_load_save_system;\n  }\n\n  type_info& get_type_info ()\n  {\n    return m_type_info;\n  }\n\n  symbol_table& get_symbol_table ()\n  {\n    return m_symbol_table;\n  }\n\n  symbol_scope get_top_scope () const;\n  symbol_scope get_current_scope () const;\n  symbol_scope require_current_scope (const std::string& who) const;\n\n  profiler& get_profiler ();\n\n  stream_list& get_stream_list ();\n\n  child_list& get_child_list ()\n  {\n    return m_child_list;\n  }\n\n  url_handle_manager& get_url_handle_manager ();\n\n  cdef_manager& get_cdef_manager ()\n  {\n    return m_cdef_manager;\n  }\n\n  gtk_manager& get_gtk_manager ()\n  {\n    return m_gtk_manager;\n  }\n\n  event_manager& get_event_manager ()\n  {\n    return m_event_manager;\n  }\n\n  gh_manager& get_gh_manager ()\n  {\n    return *m_gh_manager;\n  }\n\n  // Any Octave code that needs to change the current directory should\n  // call this function instead of calling the system chdir function\n  // directly so that the load-path and GUI may be notified of the\n  // change.\n\n  int chdir (const std::string& dir);\n\n  void mlock (bool skip_first = false) const;\n  void munlock (bool skip_first = false) const;\n  bool mislocked (bool skip_first = false) const;\n\n  // NOTE: since we have a version that accepts a bool argument, we\n  // can't rely on automatic conversion from char* to std::string.\n  void munlock (const char *nm);\n  void munlock (const std::string& nm);\n\n  bool mislocked (const char *nm);\n  bool mislocked (const std::string& nm);\n\n  std::string mfilename (const std::string& opt = \"\") const;\n\n  octave_value_list eval_string (const std::string& eval_str, bool silent,\n                                 int& parse_status, int nargout);\n\n  octave_value eval_string (const std::string& eval_str, bool silent,\n                            int& parse_status);\n\n  octave_value_list eval_string (const octave_value& arg, bool silent,\n                                 int& parse_status, int nargout);\n\n  octave_value_list eval (const std::string& try_code, int nargout);\n\n  octave_value_list eval (const std::string& try_code,\n                          const std::string& catch_code, int nargout);\n\n  octave_value_list evalin (const std::string& context,\n                            const std::string& try_code, int nargout);\n\n  octave_value_list evalin (const std::string& context,\n                            const std::string& try_code,\n                            const std::string& catch_code, int nargout);\n\n  octave_value_list\n  feval (const char *name,\n         const octave_value_list& args = octave_value_list (),\n         int nargout = 0);\n\n  octave_value_list\n  feval (const std::string& name,\n         const octave_value_list& args = octave_value_list (),\n         int nargout = 0);\n\n  octave_value_list\n  feval (octave_function *fcn,\n         const octave_value_list& args = octave_value_list (),\n         int nargout = 0);\n\n  octave_value_list\n  feval (const octave_value& f_arg,\n         const octave_value_list& args = octave_value_list (),\n         int nargout = 0);\n\n  octave_value_list feval (const octave_value_list& args, int nargout = 0);\n\n  std::string inputname (int n, bool ids_only = true) const;\n\n  octave_value make_function_handle (const std::string& name);\n\n  void install_variable (const std::string& name, const octave_value& value,\n                         bool global);\n\n  void set_global_value (const std::string& name, const octave_value& value);\n\n  octave_value global_varval (const std::string& name) const;\n\n  void global_assign (const std::string& name,\n                      const octave_value& val = octave_value ());\n\n  octave_value top_level_varval (const std::string& name) const;\n\n  void top_level_assign (const std::string& name,\n                         const octave_value& val = octave_value ());\n\n  bool is_variable (const std::string& name) const;\n\n  bool is_local_variable (const std::string& name) const;\n\n  octave_value varval (const std::string& name) const;\n\n  void assign (const std::string& name,\n               const octave_value& val = octave_value ());\n\n  void assignin (const std::string& context, const std::string& varname,\n                 const octave_value& val = octave_value ());\n\n  void source_file (const std::string& file_name,\n                    const std::string& context = \"\",\n                    bool verbose = false, bool require_file = true);\n\n  bool at_top_level () const;\n\n  bool isglobal (const std::string& name) const;\n\n  octave_value find (const std::string& name);\n\n  void clear_all (bool force = false);\n\n  void clear_objects ();\n\n  void clear_variable (const std::string& name);\n\n  void clear_variable_pattern (const std::string& pattern);\n\n  void clear_variable_regexp (const std::string& pattern);\n\n  void clear_variables ();\n\n  void clear_global_variable (const std::string& name);\n\n  void clear_global_variable_pattern (const std::string& pattern);\n\n  void clear_global_variable_regexp (const std::string& pattern);\n\n  void clear_global_variables ();\n\n  void clear_functions (bool force = false);\n\n  void clear_function (const std::string& name);\n\n  void clear_symbol (const std::string& name);\n\n  void clear_function_pattern (const std::string& pat);\n\n  void clear_function_regexp (const std::string& pat);\n\n  void clear_symbol_pattern (const std::string& pat);\n\n  void clear_symbol_regexp (const std::string& pat);\n\n  std::list<std::string> variable_names ();\n\n  std::list<std::string> top_level_variable_names ();\n\n  std::list<std::string> global_variable_names ();\n\n  std::list<std::string> user_function_names ();\n\n  std::list<std::string> autoloaded_functions () const;\n\n  void interrupt ();\n\n  // Pause interpreter execution at the next available statement and\n  // enter the debugger.\n  void pause ();\n\n  // Exit debugger or stop execution and return to the top-level REPL\n  // or server loop.\n  void stop ();\n\n  // Add EXPR to the set of expressions that may be evaluated when the\n  // debugger stops at a breakpoint.\n  void add_debug_watch_expression (const std::string& expr);\n\n  // Remove EXPR from the set of expressions that may be evaluated\n  // when the debugger stops at a breakpoint.\n  void remove_debug_watch_expression (const std::string& expr);\n\n  // Clear the set of expressions that may be evaluated when the\n  // debugger stops at a breakpoint.\n  void clear_debug_watch_expressions ();\n\n  // Return the set of expressions that may be evaluated when the\n  // debugger stops at a breakpoint.\n  std::set<std::string> debug_watch_expressions () const;\n\n  // Resume interpreter execution if paused.\n  void resume ();\n\n  octave_value PS1 (const octave_value_list& args, int nargout);\n  std::string PS1 () const;\n  std::string PS1 (const std::string& s);\n  void set_PS1 (const std::string& s);\n\n  octave_value PS2 (const octave_value_list& args, int nargout);\n  std::string PS2 () const;\n  std::string PS2 (const std::string& s);\n  void set_PS2 (const std::string& s);\n\n  octave_value PS4 (const octave_value_list& args, int nargout);\n  std::string PS4 () const;\n  std::string PS4 (const std::string& s);\n  void set_PS4 (const std::string& s);\n\n  // Provided for convenience.  Will be removed once we eliminate the\n  // old terminal widget.\n  bool experimental_terminal_widget () const;\n\n  void handle_exception (const execution_exception& ee);\n\n  void recover_from_exception ();\n\n  void mark_for_deletion (const std::string& file);\n\n  void cleanup_tmp_files ();\n\n  void quit (int exit_status, bool force = false, bool confirm = true);\n\n  void cancel_quit (bool flag) { m_cancel_quit = flag; }\n\n  bool executing_finish_script () const\n  {\n    return m_executing_finish_script;\n  }\n\n  void add_atexit_fcn (const std::string& fname);\n\n  bool remove_atexit_fcn (const std::string& fname);\n\n  static interpreter * the_interpreter () { return s_instance; }\n\nprivate:\n\n  void display_startup_message () const;\n\n  int execute_startup_files ();\n\n  int execute_eval_option_code ();\n\n  int execute_command_line_file ();\n\n  void run_startup_tests ();\n\n  int main_loop ();\n\n  int server_loop ();\n\n  void shutdown ();\n\n  void execute_atexit_fcns ();\n\n  void maximum_braindamage ();\n\n  void execute_pkg_add (const std::string& dir);\n\n  int safe_source_file (const std::string& file_name,\n                        const std::string& context = \"\",\n                        bool verbose = false, bool require_file = true);\n\n  //--------\n\n  // The interpreter instance; Currently it is only possible to\n  // have one, so OCTAVE_THREAD_LOCAL will normally be defined to be\n  // empty.  Eventually we would like to allow multiple interpreters\n  // to be active at once, but they will still be limited to one per\n  // thread.  When that is possible, OCTAVE_THREAD_LOCAL can be\n  // replaced by the C++ thread_local keyword.  For now, use a macro\n  // to allow experimenting with thread_local storage.\n\n  OCTAVE_THREAD_LOCAL static interpreter *s_instance;\n\n  application *m_app_context;\n\n  temporary_file_list m_tmp_files;\n\n  std::list<std::string> m_atexit_fcns;\n\n  display_info m_display_info;\n\n  environment m_environment;\n\n  tree_evaluator m_evaluator;\n\n  help_system m_help_system;\n\n  input_system m_input_system;\n\n  output_system m_output_system;\n\n  history_system m_history_system;\n\n  dynamic_loader m_dynamic_loader;\n\n  load_path m_load_path;\n\n  load_save_system m_load_save_system;\n\n  type_info m_type_info;\n\n  symbol_table m_symbol_table;\n\n  stream_list m_stream_list;\n\n  child_list m_child_list;\n\n  url_handle_manager m_url_handle_manager;\n\n  cdef_manager m_cdef_manager;\n\n  gtk_manager m_gtk_manager;\n\n  event_manager m_event_manager;\n\n  gh_manager *m_gh_manager;\n\n  // TRUE means this is an interactive interpreter (forced or not).\n  bool m_interactive;\n\n  bool m_read_site_files;\n\n  bool m_read_user_files;\n\n  bool m_init_trace;\n\n  bool m_traditional;\n\n  bool m_inhibit_startup_message;\n\n  bool m_load_path_initialized;\n\n  bool m_history_initialized;\n\n  bool m_interrupt_all_in_process_group;\n\n  bool m_cancel_quit;\n\n  bool m_executing_finish_script;\n\n  bool m_executing_atexit;\n\n  bool m_initialized;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/latex-text-renderer.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n#include <fstream>\n\n#include \"base-text-renderer.h\"\n#include \"builtin-defun-decls.h\"\n#include \"dim-vector.h\"\n#include \"error.h\"\n#include \"graphics.h\"\n#include \"file-ops.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"oct-env.h\"\n#include \"oct-process.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstd::string\nquote_string (std::string str)\n{\n  return ('\"' + str + '\"');\n}\n\nclass OCTINTERP_API latex_renderer : public base_text_renderer\n{\npublic:\n\n  latex_renderer ()\n    : m_fontsize (10.0), m_fontname (\"cmr\"), m_tmp_dir (),\n      m_color (dim_vector (1, 3), 0), m_latex_binary (\"latex\"),\n      m_dvipng_binary (\"dvipng\"), m_dvisvg_binary (\"dvisvgm\"),\n      m_debug (false), m_testing (true)\n  {\n    std::string bin = sys::env::getenv (\"OCTAVE_LATEX_BINARY\");\n    if (! bin.empty ())\n      m_latex_binary = quote_string (bin);\n\n    bin = sys::env::getenv (\"OCTAVE_DVIPNG_BINARY\");\n    if (! bin.empty ())\n      m_dvipng_binary = quote_string (bin);\n\n    bin = sys::env::getenv (\"OCTAVE_DVISVG_BINARY\");\n    if (! bin.empty ())\n      m_dvisvg_binary = quote_string (bin);\n\n    m_debug = ! sys::env::getenv (\"OCTAVE_LATEX_DEBUG\").empty ();\n    // FIXME: Deprecated, remove in Octave 13.\n    if (! sys::env::getenv (\"OCTAVE_LATEX_DEBUG_FLAG\").empty ())\n      {\n        m_debug = true; \n\n        static bool warned = false;\n        if (! warned)\n          {  \n            warning (\"The environment variable OCTAVE_LATEX_DEBUG_FLAG is deprecated and will be removed from a future version of Octave, please use OCTAVE_LATEX_DEBUG instead\\n\");  \n            warned = true;\n          }\n      }\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (latex_renderer)\n\n  ~latex_renderer ()\n  {\n    if (! m_tmp_dir.empty () && ! m_debug)\n      sys::recursive_rmdir (m_tmp_dir);\n  }\n\n  void set_font (const std::string& /*name*/, const std::string& /*weight*/,\n                 const std::string& /*angle*/, double size)\n  {\n    m_fontsize = size;\n  }\n\n  void set_color (const Matrix& c)\n  {\n    if (c.numel () == 3)\n      {\n        m_color(0) = static_cast<uint8_t> (c (0) * 255);\n        m_color(1) = static_cast<uint8_t> (c (1) * 255);\n        m_color(2) = static_cast<uint8_t> (c (2) * 255);\n      }\n  }\n\n  Matrix get_extent (text_element * /*elt*/, double /*rotation*/)\n  {\n    return Matrix (1, 2, 0.0);\n  }\n\n  Matrix get_extent (const std::string& txt, double rotation,\n                     const caseless_str& interpreter)\n  {\n    Matrix bbox;\n    uint8NDArray pixels;\n\n    text_to_pixels (txt, pixels, bbox, 0, 0, rotation, interpreter, false);\n\n    return bbox.extract_n (0, 2, 1, 2);\n  }\n\n  void text_to_strlist (const std::string& txt,\n                        std::list<text_renderer::string>& lst,\n                        Matrix& bbox, int halign, int valign, double rotation,\n                        const caseless_str& interp)\n  {\n    uint8NDArray pixels;\n    text_to_pixels (txt, pixels, bbox, halign, valign, rotation,\n                    interp, false);\n\n    text_renderer::font fnt;\n    text_renderer::string str (\"\", fnt, 0.0, 0.0);\n    str.set_color (m_color);\n\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    gh_manager::latex_data ldata = gh_mgr.get_latex_data (key (txt, halign));\n\n    str.set_svg_element (ldata.second);\n\n    lst.push_back (str);\n  }\n\n  void text_to_pixels (const std::string& txt, uint8NDArray& pxls,\n                       Matrix& bbox, int halign, int valign, double rotation,\n                       const caseless_str& interpreter,\n                       bool handle_rotation);\n\n  void set_anti_aliasing (bool /*val*/) { }\n\n  octave_map get_system_fonts () { return octave_map (); }\n\n  bool ok ();\n\nprivate:\n\n  std::string key (const std::string& txt, int halign)\n  {\n    return (txt + \":\"\n            + std::to_string (m_fontsize) + \":\"\n            + std::to_string (halign) + \":\"\n            + std::to_string (m_color(0)) + \":\"\n            + std::to_string (m_color(1)) + \":\"\n            + std::to_string (m_color(2)));\n  }\n\n  void warn_helper (std::string caller, std::string txt, std::string cmd,\n                    process_execution_result result);\n\n  uint8NDArray render (const std::string& txt, int halign = 0);\n\n  bool read_image (const std::string& png_file, uint8NDArray& data) const;\n\n  std::string write_tex_file (const std::string& txt, int halign);\n\nprivate:\n  double m_fontsize;\n  std::string m_fontname;\n  std::string m_tmp_dir;\n  uint8NDArray m_color;\n  std::string m_latex_binary;\n  std::string m_dvipng_binary;\n  std::string m_dvisvg_binary;\n  bool m_debug;\n  bool m_testing;\n\n};\n\nbool\nlatex_renderer::ok ()\n{\n  // Only run the test once in a session\n  static bool tested = false;\n\n  static bool isok = false;\n\n  if (! tested)\n    {\n      tested = true;\n\n      // For testing, render a questoin mark\n      uint8NDArray pixels = render (\"?\");\n\n      if (! pixels.isempty ())\n        isok = true;\n      else\n        warning_with_id (\"Octave:LaTeX:internal-error\",\n                         \"latex_renderer: a run-time test failed and the 'latex' interpreter has been disabled.\");\n    }\n\n  m_testing = false;\n\n  return isok;\n}\n\nstd::string\nlatex_renderer::write_tex_file (const std::string& txt, int halign)\n{\n  if (m_tmp_dir.empty ())\n    {\n      //Create the temporary directory\n#if defined (OCTAVE_USE_WINDOWS_API)\n      static std::string base_tmp_dir;\n\n      if (base_tmp_dir.empty ())\n        {\n          base_tmp_dir = sys::env::get_temp_directory ();\n\n          // Make sure we don't get short 8.3 path on Windows since some\n          // versions of latex on that platform don't support them\n          // (see bug #62779)\n          if (base_tmp_dir.find ('~') != std::string::npos)\n            base_tmp_dir = sys::canonicalize_file_name (base_tmp_dir);\n        }\n\n      m_tmp_dir = sys::tempnam (base_tmp_dir, \"latex\");\n#else\n      m_tmp_dir = sys::tempnam (\"\", \"latex\");\n#endif\n\n      if (sys::mkdir (m_tmp_dir, 0700) != 0)\n        {\n          warning_with_id (\"Octave:LaTeX:internal-error\",\n                           \"latex_renderer: unable to create temp directory\");\n          return std::string ();\n        }\n    }\n\n  std::string base_file_name\n    = sys::file_ops::concat (m_tmp_dir, \"default\");\n\n  // Duplicate \\n characters and align multi-line strings based on\n  // horizontalalignment\n  std::string latex_txt (txt);\n  std::size_t pos = 0;\n\n  while (true)\n    {\n      pos =  txt.find_first_of (\"\\n\", pos);\n\n      if (pos == std::string::npos)\n        break;\n\n      latex_txt.replace (pos, 1, \"\\n\\n\");\n\n      pos += 1;\n    }\n\n  std::string env (\"flushleft\");\n  if (halign == 1)\n    env = \"center\";\n  else if (halign == 2)\n    env = \"flushright\";\n\n  latex_txt = std::string (\"\\\\begin{\" ) + env + \"}\\n\"\n              + latex_txt + \"\\n\"\n              + \"\\\\end{\" + env + \"}\\n\";\n\n  // Write to temporary .tex file\n  std::ofstream file;\n  file.open (base_file_name + \".tex\");\n  file << \"\\\\documentclass[10pt, varwidth]{standalone}\\n\"\n       << \"\\\\usepackage{amsmath}\\n\"\n       << \"\\\\usepackage[utf8]{inputenc}\\n\"\n       << \"\\\\begin{document}\\n\"\n       << latex_txt << \"\\n\"\n       << \"\\\\end{document}\";\n  file.close ();\n\n  return base_file_name;\n}\n\nbool\nlatex_renderer::read_image (const std::string& png_file,\n                            uint8NDArray& data) const\n{\n  uint8NDArray alpha;\n  uint8NDArray rgb;\n  int height;\n  int width;\n\n  try\n    {\n      // First get the image size to build the argument to __magick_read__\n      octave_value_list retval = F__magick_ping__ (ovl (png_file), 1);\n\n      octave_scalar_map info\n        = retval(0).xscalar_map_value (\"latex_renderer::read_image: \"\n                                       \"Wrong type for info\");\n      height = info.getfield (\"rows\").int_value ();\n      width = info.getfield (\"columns\").int_value ();\n      Cell region (dim_vector(1, 2));\n      region(0) = range<double> (1.0, height);\n      region(1) = range<double> (1.0, width);\n      info.setfield (\"region\", region);\n      info.setfield (\"index\", octave_value (1));\n\n      // Retrieve the alpha map\n      retval = F__magick_read__ (ovl (png_file, info), 3);\n\n      alpha = retval(2).xuint8_array_value (\"latex_renderer::read_image: \"\n                                            \"Wrong type for alpha\");\n    }\n  catch (const execution_exception& ee)\n    {\n      warning_with_id (\"Octave:LaTeX:internal-error\",\n                       \"latex_renderer:: failed to read png data.  %s\",\n                       ee.message ().c_str ());\n\n      interpreter& interp = __get_interpreter__ ();\n\n      interp.recover_from_exception ();\n\n      return false;\n    }\n\n  data = uint8NDArray (dim_vector (4, width, height),\n                       static_cast<uint8_t> (0));\n\n  for (int i = 0; i < height; i++)\n    {\n      for (int j = 0; j < width; j++)\n        {\n          data(0, j, i) = m_color(0);\n          data(1, j, i) = m_color(1);\n          data(2, j, i) = m_color(2);\n          data(3, j, i) = alpha(height-i-1, j);\n        }\n    }\n\n  return true;\n}\n\nvoid\nlatex_renderer::warn_helper (std::string caller, std::string txt,\n                             std::string cmd, process_execution_result result)\n{\n  if (m_testing && ! m_debug)\n    return;\n\n  if (! m_debug)\n    warning_with_id (\"Octave:LaTeX:internal-error\",\n                     \"latex_renderer: unable to compile \\\"%s\\\"\",\n                     txt.c_str ());\n  else\n    warning_with_id (\"Octave:LaTeX:internal-error\",\n                     \"latex_renderer: %s failed for string \\\"%s\\\"\\n\\\n* Command:\\n\\t%s\\n\\n* Error:\\n%s\\n\\n* Stdout:\\n%s\",\n                     caller.c_str (), txt.c_str (), cmd.c_str (),\n                     result.err_msg ().c_str (),\n                     result.stdout_output ().c_str ());\n}\n\nuint8NDArray\nlatex_renderer::render (const std::string& txt, int halign)\n{\n  // Render if it was not already done\n  gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n  gh_manager::latex_data ldata = gh_mgr.get_latex_data (key (txt, halign));\n\n  if (! ldata.first.isempty ())\n    return ldata.first;\n\n  uint8NDArray data;\n\n  // First write the base .tex file\n  std::string base_file_name = write_tex_file (txt, halign);\n\n  if (base_file_name.empty ())\n    return data;\n\n  // Generate DVI file\n  std::string tex_file = quote_string (base_file_name + \".tex\");\n  std::string dvi_file = quote_string (base_file_name + \".dvi\");\n  std::string log_file = quote_string (base_file_name + \".log\");\n\n  process_execution_result result;\n  std::string cmd = (m_latex_binary + \" -interaction=nonstopmode \"\n                     + \"-output-directory=\" + quote_string (m_tmp_dir) + \" \"\n                     + tex_file);\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  cmd = quote_string (cmd);\n#endif\n\n  result = run_command_and_return_output (cmd);\n\n  if (result.exit_status () != 0)\n    {\n      warn_helper (\"latex\", txt, cmd, result);\n\n      if (txt != \"?\")\n        {\n          write_tex_file (\"?\", halign);\n\n          result = run_command_and_return_output (cmd);\n          if (result.exit_status () != 0)\n            return data;\n        }\n      else\n        return data;\n    }\n\n  double size_factor = m_fontsize / 10.0;\n\n\n  // Convert DVI to SVG, read file and store its content for later use in\n  // gl2ps_print\n  std::string svg_file = base_file_name + \".svg\";\n\n  cmd = (m_dvisvg_binary + \" -n \"\n         + \"-TS\" + std::to_string (size_factor) + \" \"\n         + \"-v1 -o \" + quote_string (svg_file) + \" \"\n         + dvi_file);\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  cmd = quote_string (cmd);\n#endif\n\n  result = run_command_and_return_output (cmd);\n\n  if (result.exit_status () != 0)\n    {\n      warn_helper (\"dvisvg\", txt, cmd, result);\n      return data;\n    }\n\n  std::ifstream svg_stream (svg_file);\n  std::string svg_string;\n  svg_string.assign (std::istreambuf_iterator<char> (svg_stream),\n                     std::istreambuf_iterator<char> ());\n\n  // Convert DVI to PNG, read file and format pixel data for later use in\n  // OpenGL\n  std::string png_file = base_file_name + \".png\";\n\n  cmd = (m_dvipng_binary + \" \" + dvi_file + \" \"\n         + \"-q -o \" + quote_string (png_file) + \" \"\n         + \"-bg Transparent -D \"\n         + std::to_string (std::floor (72.0 * size_factor)));\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  cmd = quote_string (cmd);\n#endif\n\n  result = run_command_and_return_output (cmd);\n\n  if (result.exit_status () != 0)\n    {\n      warn_helper (\"dvipng\", txt, cmd, result);\n      return data;\n    }\n\n  if (! read_image (png_file, data))\n    return data;\n\n  // Cache pixel and svg data for this string\n  ldata.first = data;\n  ldata.second = svg_string;\n\n  gh_mgr.set_latex_data (key (txt, halign), ldata);\n\n  if (m_debug)\n    std::cout << \"* Caching \" << key (txt, halign) << std::endl;\n\n  return data;\n}\n\nvoid\nlatex_renderer::text_to_pixels (const std::string& txt, uint8NDArray& pixels,\n                                Matrix& bbox, int halign, int valign,\n                                double rotation,\n                                const caseless_str& /*interpreter*/,\n                                bool handle_rotation)\n{\n  // Return early for empty strings\n  if (txt.empty ())\n    {\n      bbox = Matrix (1, 4, 0.0);\n      return;\n    }\n\n  if (ok ())\n    pixels = render (txt, halign);\n  else\n    pixels = uint8NDArray (dim_vector (4, 1, 1), static_cast<uint8_t> (0));\n\n  if (pixels.ndims () < 3 || pixels.isempty ())\n    return;  // nothing to render\n\n  // Store unrotated bbox size\n  bbox = Matrix (1, 4, 0.0);\n  bbox (2) = pixels.dim2 ();\n  bbox (3) = pixels.dim3 ();\n\n  // Now rotate pixels if necessary\n  int rot_mode = rotation_to_mode (rotation);\n\n  if (! pixels.isempty ())\n    rotate_pixels (pixels, rot_mode);\n\n  // Move X0 and Y0 depending on alignments and eventually swap values\n  // for text rotated 90° 180° or 270°\n  fix_bbox_anchor (bbox, halign, valign, rot_mode, handle_rotation);\n}\n\nbase_text_renderer *\nmake_latex_text_renderer ()\n{\n  latex_renderer *renderer = new latex_renderer ();\n\n  return renderer;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/latex-text-renderer.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_latex_text_renderer_h)\n#define octave_latex_text_renderer_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_text_renderer;\n\nextern base_text_renderer * make_latex_text_renderer ();\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/load-path.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// #define OCTAVE_LOADPATH_DEBUG 1\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <cctype>\n\n#include \"cmd-edit.h\"\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"oct-env.h\"\n#include \"oct-sysdep.h\"\n#include \"pathsearch.h\"\n#if ! defined (OCTAVE_USE_WINDOWS_API)\n#  include \"file-stat.h\"\n#endif\n\n#include \"defaults.h\"\n#include \"defun.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Canonicalize file name (keeping the path relative) if it exists.\n// Return it unmodified otherwise.\n\nstatic std::string\nmaybe_canonicalize (const std::string& dir_arg)\n{\n  bool is_absolute_path = sys::env::absolute_pathname (dir_arg);\n\n  std::string canonical_dir = sys::canonicalize_file_name (dir_arg);\n  std::string dir;\n  if (canonical_dir.empty ())\n    dir = dir_arg;\n  else\n    {\n      dir = canonical_dir;\n\n      if (! is_absolute_path)\n        {\n          // Remove current path from absolute path generated by\n          // canonicalize_file_name.\n          std::string cwd = sys::canonicalize_file_name (\".\");\n          if (dir.compare (0, cwd.length (), cwd) == 0)\n            dir.erase (0, cwd.length ()+1);\n          if (dir.empty ())\n            dir = \".\";\n        }\n    }\n\n  return dir;\n}\n\nstatic void\nmaybe_add_path_elts (std::string& path, const std::string& dir)\n{\n  std::string tpath = genpath (maybe_canonicalize (dir));\n\n  if (! tpath.empty ())\n    {\n      if (path.empty ())\n        path = tpath;\n      else\n        path += directory_path::path_sep_str () + tpath;\n    }\n}\n\nstatic std::list<std::string>\nsplit_path (const std::string& p)\n{\n  std::list<std::string> retval;\n\n  std::size_t beg = 0;\n  std::size_t end = p.find (directory_path::path_sep_char ());\n\n  std::size_t len = p.length ();\n\n  while (end != std::string::npos)\n    {\n      std::string elt = p.substr (beg, end-beg);\n\n      if (! elt.empty ())\n        retval.push_back (elt);\n\n      beg = end + 1;\n\n      if (beg == len)\n        break;\n\n      end = p.find (directory_path::path_sep_char (), beg);\n    }\n\n  std::string elt = p.substr (beg);\n\n  if (! elt.empty ())\n    retval.push_back (elt);\n\n  return retval;\n}\n\n// Strip trailing directory separators.\n\nstatic std::string\nstrip_trailing_separators (const std::string& dir_arg)\n{\n  std::string dir = dir_arg;\n\n  std::size_t k = dir.length ();\n\n  while (k > 1 && sys::file_ops::is_dir_sep (dir[k-1]))\n    k--;\n\n  if (k < dir.length ())\n    dir.resize (k);\n\n  return dir;\n}\n\n// True if a path is contained in a path list separated by path_sep_char\n\nstatic bool\nin_path_list (const std::string& path_list, const std::string& path)\n{\n  std::size_t ps = path.size ();\n  std::size_t pls = path_list.size ();\n  std::size_t pos = path_list.find (path);\n  char psc = directory_path::path_sep_char ();\n  while (pos != std::string::npos)\n    {\n      if ((pos == 0 || path_list[pos-1] == psc)\n          && (pos + ps == pls || path_list[pos + ps] == psc))\n        return true;\n      else\n        pos = path_list.find (path, pos + 1);\n    }\n\n  return false;\n}\n\n//! Check if directory contains modified subdirectories.\n//!\n//! @param d directory to check\n//! @param last_checked time of last check\n//!\n//! Path patterns that need to be checked for modifications:\n//!\n//! @code{.unparsed}\n//! private/\n//!\n//! @class/\n//! @class/private/\n//!\n//! +namespace/\n//! +namespace/private/\n//!\n//! +namespace/@class/\n//! +namespace/@class/private/\n//! @endcode\n//!\n//! Recursion into sub-namespaces:\n//!\n//! @code{.unparsed}\n//! +namespace/+subnamespace/<like above>\n//! @endcode\n//!\n//! @return true if directory contains modified subdirectories\n\nstatic bool\nsubdirs_modified (const std::string& d, const sys::file_time& last_checked)\n{\n  sys::dir_entry dir (d);\n\n  if (dir)\n    {\n      string_vector flist = dir.read ();\n\n      octave_idx_type len = flist.numel ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          std::string fname = flist[i];\n\n          std::string full_name = sys::file_ops::concat (d, fname);\n\n          // Check if directory AND if relevant (@,+,private)\n          // AND (if modified OR recursion into (@,+) sub-directories)\n#if defined (OCTAVE_USE_WINDOWS_API)\n          if (sys::dir_exists (full_name)\n#else\n          sys::file_stat fs (full_name);\n\n          if (fs && fs.is_dir ()\n#endif\n              && (fname[0] == '@' || fname[0] == '+' || fname == \"private\")\n#if defined (OCTAVE_USE_WINDOWS_API)\n              && ((sys::file_time (full_name)\n#else\n              && ((sys::file_time (fs.mtime ().unix_time ())\n#endif\n                   + sys::file_time::time_resolution () > last_checked)\n                  || ((fname[0] == '@' || fname[0] == '+')\n                      && subdirs_modified (full_name, last_checked))))\n            return true;\n        }\n    }\n  else\n    {\n      std::string msg = dir.error ();\n      warning (\"load_path: %s: %s\", d.c_str (), msg.c_str ());\n    }\n\n  return false;\n}\n\nstd::string load_path::s_sys_path;\nload_path::abs_dir_cache_type load_path::s_abs_dir_cache;\n\nload_path::load_path (interpreter& interp)\n  : m_add_hook ([this] (const std::string& dir) { this->execute_pkg_add (dir); }),\nm_remove_hook ([this] (const std::string& dir) { this->execute_pkg_del (dir); }),\nm_interpreter (interp), m_package_map (), m_top_level_package (),\nm_dir_info_list (), m_init_dirs (), m_command_line_path ()\n{ }\n\nvoid\nload_path::initialize (bool set_initial_path)\n{\n  s_sys_path = \"\";\n\n  if (set_initial_path)\n    {\n      maybe_add_path_elts (s_sys_path, config::local_ver_oct_file_dir ());\n      maybe_add_path_elts (s_sys_path, config::local_api_oct_file_dir ());\n      maybe_add_path_elts (s_sys_path, config::local_oct_file_dir ());\n      maybe_add_path_elts (s_sys_path, config::local_ver_fcn_file_dir ());\n      maybe_add_path_elts (s_sys_path, config::local_api_fcn_file_dir ());\n      maybe_add_path_elts (s_sys_path, config::local_fcn_file_dir ());\n      maybe_add_path_elts (s_sys_path, config::oct_file_dir ());\n      maybe_add_path_elts (s_sys_path, config::fcn_file_dir ());\n      maybe_add_path_elts (s_sys_path, config::oct_data_dir ());\n    }\n\n  std::string tpath = load_path::m_command_line_path;\n\n  if (tpath.empty ())\n    tpath = sys::env::getenv (\"OCTAVE_PATH\");\n\n  std::string xpath;\n\n  if (! tpath.empty ())\n    {\n      xpath = tpath;\n\n      if (! s_sys_path.empty ())\n        xpath += directory_path::path_sep_str () + s_sys_path;\n    }\n  else\n    xpath = s_sys_path;\n\n  set (xpath, false, true);\n}\n\nvoid\nload_path::clear ()\n{\n  m_dir_info_list.clear ();\n\n  m_top_level_package.clear ();\n\n  m_package_map.clear ();\n}\n\nvoid\nload_path::set (const std::string& p, bool warn, bool is_init)\n{\n  // Use a list when we need to preserve order.\n  std::list<std::string> elts = split_path (p);\n\n  for (auto& elt : elts)\n    elt = maybe_canonicalize (elt);\n\n  // Use a set when we need to search and order is not important.\n  std::set<std::string> elts_set (elts.begin (), elts.end ());\n\n  if (is_init)\n    m_init_dirs = elts_set;\n  else\n    {\n      for (const auto& init_dir : m_init_dirs)\n        {\n          if (elts_set.find (init_dir) == elts_set.end ())\n            {\n              warning_with_id (\"Octave:remove-init-dir\",\n                               \"default load path altered.  Some built-in functions may not be found.  Try restoredefaultpath() to recover it.\");\n              break;\n            }\n        }\n    }\n\n  // Temporarily disable add hook.\n\n  unwind_protect frame;\n  frame.protect_var (m_add_hook);\n\n  m_add_hook = nullptr;\n\n  clear ();\n\n  for (const auto& elt : elts)\n    append (elt, warn);\n\n  // Always prepend current directory.\n  prepend (\".\", warn);\n\n  // Restore add hook and execute for all newly added directories.\n  frame.run_first ();\n\n  if (m_add_hook)\n    {\n      // FIXME: Why not use const here?  Does add_hook change dir_info_list?\n      // FIXME: We should be able to assume that the current directory is\n      //        always the first element in the list.  When we assume C++20 or\n      //        later, consider replacing the range-based loop with:\n      //            for (auto& di : m_dir_info_list | std::views::drop (1))\n      //        Then, the string comparison inside the loop could be dropped.\n      for (auto& di : m_dir_info_list)\n        {\n          // execute PKG_ADD script (but not in the current directory)\n          if (di.m_dir_name.compare (\".\"))\n            m_add_hook (di.m_dir_name);\n        }\n    }\n}\n\nvoid\nload_path::append (const std::string& dir, bool warn)\n{\n  if (! dir.empty ())\n    add (dir, true, warn);\n}\n\nvoid\nload_path::prepend (const std::string& dir, bool warn)\n{\n  if (! dir.empty ())\n    add (dir, false, warn);\n}\n\nbool\nload_path::remove (const std::string& dir_arg)\n{\n  bool retval = false;\n\n  if (! dir_arg.empty ())\n    {\n      if (sys::same_file (dir_arg, \".\"))\n        {\n          warning (R\"(rmpath: can't remove \".\" from path)\");\n\n          // Avoid additional warnings.\n          retval = true;\n        }\n      else\n        {\n          std::string dir = sys::file_ops::tilde_expand (dir_arg);\n\n          dir = strip_trailing_separators (dir);\n\n          auto i = find_dir_info (dir);\n\n          if (i != m_dir_info_list.end ())\n            {\n              retval = true;\n\n              if (m_remove_hook)\n                m_remove_hook (dir);\n\n              dir_info& di = *i;\n\n              remove (di);\n\n              m_dir_info_list.erase (i);\n            }\n        }\n    }\n\n  return retval;\n}\n\nvoid\nload_path::update ()\n{\n  // I don't see a better way to do this because we need to\n  // preserve the correct directory ordering for new files that\n  // have appeared.\n\n  m_top_level_package.clear ();\n\n  m_package_map.clear ();\n\n  for (dir_info_list_iterator di = m_dir_info_list.begin ();\n       di != m_dir_info_list.end ();)\n    {\n      bool ok = di->update ();\n\n      if (! ok)\n        {\n          warning_with_id\n            (\"Octave:load-path:update-failed\",\n             \"load-path: update failed for '%s', removing from path\",\n             di->m_dir_name.c_str ());\n\n          if (m_remove_hook)\n            m_remove_hook (di->m_dir_name.c_str ());\n\n          remove (*di);\n\n          di = m_dir_info_list.erase (di);\n        }\n      else\n        {\n          add (*di, true, \"\", true);\n          di++;\n        }\n    }\n}\n\nbool\nload_path::contains_canonical (const std::string& dir) const\n{\n  bool retval = false;\n\n  for (const auto& d : m_dir_info_list)\n    {\n      if (sys::same_file (dir, d.m_dir_name))\n        {\n          retval = true;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nbool\nload_path::contains_file_in_dir (const std::string& file,\n                                 const std::string& dir)\n{\n  bool ok = false;\n  bool addpath_option = true;\n\n  std::string curr_dir = sys::env::get_current_directory ();\n\n  if (sys::same_file (curr_dir, dir))\n    ok = true;\n  else\n    {\n      bool dir_in_load_path = contains_canonical (dir);\n\n      // get base name, allowing \"@class/method.m\" (bug #41514)\n      std::string base_file = (file.length () > dir.length ())\n                              ? file.substr (dir.length () + 1)\n                              : sys::env::base_pathname (file);\n\n      std::string lp_file = find_file (base_file);\n\n      if (dir_in_load_path)\n        {\n          if (sys::same_file (lp_file, file))\n            ok = true;\n        }\n      else\n        {\n          // File directory is not in path.  Is the file in the path in\n          // the current directory?  If so, then changing the current\n          // directory will be needed.  Adding directory to path is\n          // not enough because the file in the current directory would\n          // still be found.\n\n          if (sys::same_file (lp_file, base_file))\n            {\n              if (sys::same_file (curr_dir, dir))\n                ok = true;\n              else\n                addpath_option = false;\n            }\n        }\n    }\n\n  if (! ok)\n    {\n      event_manager& evmgr = m_interpreter.get_event_manager ();\n\n      int action\n        = evmgr.debug_cd_or_addpath_error (file, dir, addpath_option);\n\n      switch (action)\n        {\n        case 1:\n          m_interpreter.chdir (dir);\n          ok = true;\n          break;\n\n        case 2:\n          {\n            prepend (dir);\n            ok = true;\n          }\n          break;\n\n        default:\n          break;\n        }\n    }\n\n  return ok;\n}\n\nstd::list<std::string>\nload_path::overloads (const std::string& meth) const\n{\n  std::list<std::string> retval;\n\n  //  update ();\n\n  m_top_level_package.overloads (meth, retval);\n\n  for (const auto& nm_ldr : m_package_map)\n    nm_ldr.second.overloads (meth, retval);\n\n  return retval;\n}\n\nstd::list<std::string>\nload_path::get_all_package_names (bool only_top_level) const\n{\n  std::list<std::string> retval;\n\n  for (const auto& dir_ldr : m_package_map)\n    {\n      if (! only_top_level || dir_ldr.first.find ('.') == std::string::npos)\n        retval.push_back (dir_ldr.first);\n    }\n\n  return retval;\n}\n\nstd::string\nload_path::find_file (const std::string& file) const\n{\n  std::string retval;\n\n  if (sys::env::absolute_pathname (file)\n      || sys::env::rooted_relative_pathname (file))\n    return sys::file_exists (file) ? file : retval;\n  else\n    {\n      std::string tfile = find_private_file (file);\n\n      if (! tfile.empty ())\n        return tfile;\n    }\n\n  if (file.find_first_of (sys::file_ops::dir_sep_chars ())\n      != std::string::npos)\n    {\n      // Given name has a directory separator, so append it to each\n      // element of the load path in turn.\n      for (const auto& di : m_dir_info_list)\n        {\n          std::string tfile = sys::file_ops::concat (di.m_abs_dir_name, file);\n\n          if (sys::file_exists (tfile))\n            return tfile;\n        }\n    }\n  else\n    {\n      // Look in cache.\n      for (const auto& di : m_dir_info_list)\n        {\n          string_vector all_files = di.m_all_files;\n\n          octave_idx_type len = all_files.numel ();\n\n          for (octave_idx_type i = 0; i < len; i++)\n            {\n              if (all_files[i] == file)\n                return sys::file_ops::concat (di.m_abs_dir_name, file);\n            }\n        }\n    }\n\n  return retval;\n}\n\nstd::string\nload_path::find_dir (const std::string& dir) const\n{\n  std::string retval;\n\n  if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos\n      && (sys::env::absolute_pathname (dir)\n          || sys::env::rooted_relative_pathname (dir)))\n    {\n      if (sys::dir_exists (dir))\n        return dir;\n    }\n  else\n    {\n      std::string canon_dir = maybe_canonicalize (dir);\n      for (const auto& di : m_dir_info_list)\n        {\n          std::string dname = di.m_abs_dir_name;\n\n          std::size_t dname_len = dname.length ();\n\n          if (dname.substr (dname_len - 1)\n              == sys::file_ops::dir_sep_str ())\n            {\n              dname = dname.substr (0, dname_len - 1);\n              dname_len--;\n            }\n\n          std::size_t dir_len = canon_dir.length ();\n\n          if (dname_len > dir_len\n              && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])\n              && canon_dir == dname.substr (dname_len - dir_len)\n              && sys::dir_exists (di.m_dir_name))\n            return di.m_abs_dir_name;\n        }\n    }\n\n  return retval;\n}\n\nstring_vector\nload_path::find_matching_dirs (const std::string& dir) const\n{\n  std::list<std::string> retlist;\n\n  if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos\n      && (sys::env::absolute_pathname (dir)\n          || sys::env::rooted_relative_pathname (dir)))\n    {\n      if (sys::dir_exists (dir))\n        retlist.push_back (dir);\n    }\n  else\n    {\n      std::string canon_dir = maybe_canonicalize (dir);\n      for (const auto& di : m_dir_info_list)\n        {\n          std::string dname = di.m_abs_dir_name;\n\n          std::size_t dname_len = dname.length ();\n\n          if (dname.substr (dname_len - 1)\n              == sys::file_ops::dir_sep_str ())\n            {\n              dname = dname.substr (0, dname_len - 1);\n              dname_len--;\n            }\n\n          std::size_t dir_len = canon_dir.length ();\n\n          if (dname_len > dir_len\n              && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])\n              && canon_dir == dname.substr (dname_len - dir_len)\n              && sys::dir_exists (di.m_dir_name))\n            retlist.push_back (di.m_abs_dir_name);\n        }\n    }\n\n  return retlist;\n}\n\nstd::string\nload_path::find_first_of (const string_vector& flist) const\n{\n  std::string retval;\n\n  std::string dir_name;\n  std::string file_name;\n\n  octave_idx_type flen = flist.numel ();\n  octave_idx_type rel_flen = 0;\n\n  string_vector rel_flist (flen);\n\n  for (octave_idx_type i = 0; i < flen; i++)\n    {\n      std::string file = flist[i];\n\n      if (file.find_first_of (sys::file_ops::dir_sep_chars ())\n          != std::string::npos)\n        {\n          if (sys::env::absolute_pathname (file)\n              || sys::env::rooted_relative_pathname (file))\n            {\n              if (sys::file_exists (file))\n                return file;\n            }\n          else\n            {\n              for (const auto& di : m_dir_info_list)\n                {\n                  std::string tfile;\n                  tfile = sys::file_ops::concat (di.m_abs_dir_name, file);\n\n                  if (sys::file_exists (tfile))\n                    return tfile;\n                }\n            }\n        }\n      else\n        rel_flist[rel_flen++] = file;\n    }\n\n  rel_flist.resize (rel_flen);\n\n  for (const auto& di : m_dir_info_list)\n    {\n      string_vector all_files = di.m_all_files;\n\n      octave_idx_type len = all_files.numel ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          for (octave_idx_type j = 0; j < rel_flen; j++)\n            {\n              if (all_files[i] == rel_flist[j])\n                {\n                  dir_name = di.m_abs_dir_name;\n                  file_name = rel_flist[j];\n\n                  goto done;\n                }\n            }\n        }\n    }\n\ndone:\n\n  if (! dir_name.empty ())\n    retval = sys::file_ops::concat (dir_name, file_name);\n\n  return retval;\n}\n\nstring_vector\nload_path::find_all_first_of (const string_vector& flist) const\n{\n  std::list<std::string> retlist;\n\n  std::string dir_name;\n  std::string file_name;\n\n  octave_idx_type flen = flist.numel ();\n  octave_idx_type rel_flen = 0;\n\n  string_vector rel_flist (flen);\n\n  for (octave_idx_type i = 0; i < flen; i++)\n    {\n      std::string file = flist[i];\n\n      if (file.find_first_of (sys::file_ops::dir_sep_chars ())\n          != std::string::npos)\n        {\n          if (sys::env::absolute_pathname (file)\n              || sys::env::rooted_relative_pathname (file))\n            {\n              if (sys::file_exists (file))\n                retlist.push_back (file);\n            }\n          else\n            {\n              for (const auto& di : m_dir_info_list)\n                {\n                  std::string tfile;\n                  tfile = sys::file_ops::concat (di.m_abs_dir_name, file);\n\n                  if (sys::file_exists (tfile))\n                    retlist.push_back (tfile);\n                }\n            }\n        }\n      else\n        rel_flist[rel_flen++] = file;\n    }\n\n  rel_flist.resize (rel_flen);\n\n  for (const auto& di : m_dir_info_list)\n    {\n      string_vector all_files = di.m_all_files;\n\n      octave_idx_type len = all_files.numel ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          for (octave_idx_type j = 0; j < rel_flen; j++)\n            {\n              if (all_files[i] == rel_flist[j])\n                retlist.push_back (sys::file_ops::concat (di.m_abs_dir_name,\n                                   rel_flist[j]));\n            }\n        }\n    }\n\n  return retlist;\n}\n\nstring_vector\nload_path::dirs () const\n{\n  std::size_t len = m_dir_info_list.size ();\n\n  string_vector retval (len);\n\n  octave_idx_type k = 0;\n\n  for (const auto& di : m_dir_info_list)\n    retval[k++] = di.m_dir_name;\n\n  return retval;\n}\n\nstd::list<std::string>\nload_path::dir_list () const\n{\n  std::list<std::string> retval;\n\n  for (const auto& di : m_dir_info_list)\n    retval.push_back (di.m_dir_name);\n\n  return retval;\n}\n\nstring_vector\nload_path::files (const std::string& dir, bool omit_exts) const\n{\n  string_vector retval;\n\n  const_dir_info_list_iterator p = find_dir_info (dir);\n\n  if (p != m_dir_info_list.end ())\n    retval = p->m_fcn_files;\n\n  if (omit_exts)\n    {\n      octave_idx_type len = retval.numel ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          std::string fname = retval[i];\n\n          std::size_t pos = fname.rfind ('.');\n\n          if (pos != std::string::npos)\n            retval[i] = fname.substr (0, pos);\n        }\n    }\n\n  return retval;\n}\n\nstring_vector\nload_path::fcn_names () const\n{\n  return m_top_level_package.fcn_names ();\n}\n\nstd::string\nload_path::path () const\n{\n  std::string xpath;\n\n  string_vector xdirs = load_path::dirs ();\n\n  octave_idx_type len = xdirs.numel ();\n\n  if (len > 0)\n    xpath = xdirs[0];\n\n  for (octave_idx_type i = 1; i < len; i++)\n    xpath += directory_path::path_sep_str () + xdirs[i];\n\n  return xpath;\n}\n\nvoid\nload_path::display (std::ostream& os) const\n{\n  for (const auto& di : m_dir_info_list)\n    {\n      string_vector fcn_files = di.m_fcn_files;\n\n      if (! fcn_files.empty ())\n        {\n          os << \"\\n*** function files in \" << di.m_dir_name << \":\\n\\n\";\n\n          const int width = command_editor::terminal_cols ();\n\n          fcn_files.list_in_columns (os, width);\n        }\n\n      const dir_info::method_file_map_type& method_file_map\n        = di.m_method_file_map;\n\n      if (! method_file_map.empty ())\n        {\n          const int width = command_editor::terminal_cols ();\n\n          for (const auto& cls_ci : method_file_map)\n            {\n              os << \"\\n*** methods in \" << di.m_dir_name\n                 << \"/@\" << cls_ci.first << \":\\n\\n\";\n\n              const dir_info::class_info& ci = cls_ci.second;\n\n              string_vector method_files = get_file_list (ci.m_method_file_map);\n\n              method_files.list_in_columns (os, width);\n            }\n        }\n    }\n\n  m_top_level_package.display (os);\n\n  for (const auto& nm_ldr : m_package_map)\n    nm_ldr.second.display (os);\n}\n\nvoid\nload_path::execute_pkg_add (const std::string& dir)\n{\n  execute_pkg_add_or_del (dir, \"PKG_ADD\");\n}\n\nvoid\nload_path::execute_pkg_del (const std::string& dir)\n{\n  execute_pkg_add_or_del (dir, \"PKG_DEL\");\n}\n\nvoid\nload_path::rehash ()\n{\n  update ();\n\n  // Signal the GUI allowing updating the load path dialog\n\n  event_manager& evmgr = m_interpreter.get_event_manager ();\n\n  evmgr.update_path_dialog ();\n\n  // FIXME: maybe we should rename this variable since it is being\n  // used for more than keeping track of the prompt time.\n\n  // This will force updated functions to be found.\n  Vlast_prompt_time.stamp ();\n}\n\nvoid\nload_path::execute_pkg_add_or_del (const std::string& dir,\n                                   const std::string& script_file)\n{\n  if (! octave_interpreter_ready)\n    return;\n\n  std::string file = sys::file_ops::concat (dir, script_file);\n\n  if (sys::file_exists (file))\n    source_file (file, \"base\");\n}\n\n// FIXME: maybe we should also maintain a map to speed up this method of\n//        access.\n\nload_path::const_dir_info_list_iterator\nload_path::find_dir_info (const std::string& dir_arg) const\n{\n  std::string dir = sys::file_ops::tilde_expand (dir_arg);\n\n  dir = maybe_canonicalize (dir);\n\n  auto retval = m_dir_info_list.cbegin ();\n\n  while (retval != m_dir_info_list.cend ())\n    {\n      if (retval->m_dir_name == dir)\n        break;\n\n      retval++;\n    }\n\n  return retval;\n}\n\nload_path::dir_info_list_iterator\nload_path::find_dir_info (const std::string& dir_arg)\n{\n  std::string dir = sys::file_ops::tilde_expand (dir_arg);\n\n  dir = maybe_canonicalize (dir);\n\n  auto retval = m_dir_info_list.begin ();\n\n  while (retval != m_dir_info_list.end ())\n    {\n      if (retval->m_dir_name == dir)\n        break;\n\n      retval++;\n    }\n\n  return retval;\n}\n\nbool\nload_path::contains (const std::string& dir) const\n{\n  return find_dir_info (dir) != m_dir_info_list.end ();\n}\n\nvoid\nload_path::move (dir_info_list_iterator i, bool at_end)\n{\n  if (m_dir_info_list.size () > 1)\n    {\n      dir_info di = *i;\n\n      m_dir_info_list.erase (i);\n\n      if (at_end)\n        m_dir_info_list.push_back (di);\n      else\n        m_dir_info_list.push_front (di);\n\n      move (di, at_end);\n    }\n}\n\nvoid\nload_path::move (const dir_info& di, bool at_end, const std::string& pname)\n{\n  package_info& l = get_package (pname);\n\n  l.move (di, at_end);\n\n  dir_info::package_dir_map_type package_dir_map = di.m_package_dir_map;\n\n  for (const auto& pkg_di : package_dir_map)\n    {\n      std::string full_name = pkg_di.first;\n\n      if (! pname.empty ())\n        full_name = pname + '.' + full_name;\n\n      move (pkg_di.second, at_end, full_name);\n    }\n}\n\nvoid\nload_path::add (const std::string& dir_arg, bool at_end, bool warn)\n{\n  std::size_t len = dir_arg.length ();\n\n  if (len > 1 && dir_arg.substr (len-2) == \"//\")\n    warning_with_id (\"Octave:recursive-path-search\",\n                     \"trailing '//' is no longer special in search path elements\");\n\n  std::string dir = sys::file_ops::tilde_expand (dir_arg);\n\n  dir = strip_trailing_separators (dir);\n\n  dir = maybe_canonicalize (dir);\n\n  auto i = find_dir_info (dir);\n\n  if (i != m_dir_info_list.end ())\n    move (i, at_end);\n  else\n    {\n      std::string msg;\n\n      if (sys::dir_exists (dir, msg))\n        {\n          read_dir_config (dir);\n\n          dir_info di (dir);\n\n          if (at_end)\n            m_dir_info_list.push_back (di);\n          else\n            m_dir_info_list.push_front (di);\n\n          add (di, at_end);\n\n          if (m_add_hook && di.m_dir_name.compare (\".\"))\n            m_add_hook (dir);\n        }\n\n      if (warn && ! msg.empty ())\n        warning (\"addpath: %s: %s\", dir_arg.c_str (), msg.c_str ());\n    }\n\n  // FIXME: Is there a better way to keep \".\" at the front of the various lists\n  //        that are kept with information about the load path?\n\n  i = find_dir_info (\".\");\n\n  if (i != m_dir_info_list.end ())\n    move (i, false);\n}\n\nvoid\nload_path::remove (const dir_info& di, const std::string& pname)\n{\n  package_info& l = get_package (pname);\n\n  l.remove (di);\n\n  dir_info::package_dir_map_type package_dir_map = di.m_package_dir_map;\n\n  for (const auto& pkg_di : package_dir_map)\n    {\n      std::string full_name = pkg_di.first;\n\n      if (! pname.empty ())\n        full_name = pname + '.' + full_name;\n\n      remove (pkg_di.second, full_name);\n    }\n}\n\nvoid\nload_path::read_dir_config (const std::string& dir) const\n{\n  // use canonicalized path as key\n  const std::string key = sys::canonicalize_file_name (dir);\n\n  // read file with directory configuration\n  const std::string\n  conf_file = key + sys::file_ops::dir_sep_str () + \".oct-config\";\n\n  FILE *cfile = sys::fopen (conf_file, \"rb\");\n\n  if (! cfile)\n    {\n      // reset directory encoding\n      input_system& input_sys = __get_input_system__ ();\n\n      std::string enc_val = \"delete\";\n      input_sys.set_dir_encoding (key, enc_val);\n      return;\n    }\n\n  unwind_action close_file ([cfile] () { fclose (cfile); });\n\n  // find line with character encoding and read it\n  bool eof = false;\n  const std::string enc_prop = \"encoding\";\n  while (! eof)\n    {\n      std::string conf_str = fgets (cfile, eof);\n\n      // delete any preceeding whitespace\n      auto it = std::find_if_not (conf_str.begin (), conf_str.end (),\n                                  [] (unsigned char c)\n      { return std::isblank (c); });\n      conf_str.erase (conf_str.begin (), it);\n\n      // match identifier\n      if (conf_str.compare (0, enc_prop.size (), enc_prop) == 0)\n        {\n          // skip delimiter characters\n          std::size_t pos = conf_str.find_first_not_of (\" \\t=:\",\n                            enc_prop.size ());\n          if (pos == std::string::npos)\n            continue;\n\n          std::string enc_val = conf_str.substr (pos);\n\n          // take alphanumeric and '-' characters\n          it = std::find_if_not (enc_val.begin (), enc_val.end (),\n                                 [] (unsigned char c)\n          { return std::isalnum (c) || c == '-'; });\n          enc_val.erase(it, enc_val.end ());\n\n          if (enc_val.empty ())\n            continue;\n\n          // set encoding for this directory in input system\n          input_system& input_sys = __get_input_system__ ();\n          input_sys.set_dir_encoding (key, enc_val);\n          return;\n        }\n    }\n\n  // reset directory encoding\n  input_system& input_sys = __get_input_system__ ();\n\n  std::string enc_val = \"delete\";\n  input_sys.set_dir_encoding (dir, enc_val);\n\n}\n\nbool\nload_path::is_package (const std::string& name) const\n{\n  for (const auto& di : m_dir_info_list)\n    {\n      if (di.is_package (name))\n        return true;\n    }\n\n  return false;\n}\n\nvoid\nload_path::add (const dir_info& di, bool at_end,\n                const std::string& pname, bool updating)\n{\n  package_info& l = get_package (pname);\n\n  l.add (di, at_end, updating);\n\n  dir_info::package_dir_map_type package_dir_map = di.m_package_dir_map;\n\n  for (const auto& pkg_di : package_dir_map)\n    {\n      std::string full_name = pkg_di.first;\n\n      if (! pname.empty ())\n        full_name = pname + '.' + full_name;\n\n      add (pkg_di.second, at_end, full_name);\n    }\n}\n\nstring_vector\nload_path::get_file_list (const load_path::dir_info::fcn_file_map_type& lst) const\n{\n  octave_idx_type n = lst.size ();\n\n  string_vector retval (n);\n\n  octave_idx_type count = 0;\n\n  for (const auto& nm_typ : lst)\n    {\n      std::string nm = nm_typ.first;\n\n      int types = nm_typ.second;\n\n      if (types & load_path::OCT_FILE)\n        nm += \".oct\";\n      else if (types & load_path::MEX_FILE)\n        nm += \".mex\";\n      else\n        nm += \".m\";\n\n      retval[count++] = nm;\n    }\n\n  return retval;\n}\n\n// Should we cache all files in private directories, or is it OK to just\n// look them up each time as needed?\n\nstd::string\nload_path::find_private_file (const std::string& fname) const\n{\n  std::string retval;\n\n  // Look in private directory corresponding to current function (if\n  // any).\n\n  symbol_scope scope = m_interpreter.get_current_scope ();\n\n  octave_user_code *curr_code = scope ? scope.user_code () : nullptr;\n\n  if (curr_code)\n    {\n      // Even for private functions, dir_name doesn't contain the\n      // \"private\" directory component so we append it here in all\n      // cases.\n\n      std::string dir_name = curr_code->dir_name ();\n\n      if (! dir_name.empty ())\n        {\n          std::string pfname = dir_name + sys::file_ops::dir_sep_str ()\n                               + \"private\" + sys::file_ops::dir_sep_str ()\n                               + fname;\n\n          if (sys::file_exists (pfname, false))\n            retval = pfname;\n        }\n    }\n\n  return retval;\n}\n\nload_path::dir_info::fcn_file_map_type\nget_fcn_files (const std::string& d)\n{\n  load_path::dir_info::fcn_file_map_type retval;\n\n  string_vector flist;\n  std::string msg;\n\n  if (! sys::get_dirlist (d, flist, msg))\n    warning (\"load_path: %s: %s\", d.c_str (), msg.c_str ());\n  else\n    {\n      octave_idx_type len = flist.numel ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          std::string fname = flist[i];\n\n          std::size_t pos = fname.rfind ('.');\n\n          if (pos != std::string::npos)\n            {\n              std::string base = fname.substr (0, pos);\n              std::string ext = fname.substr (pos);\n\n              if (valid_identifier (base))\n                {\n                  int t = 0;\n\n                  if (ext == \".m\")\n                    t = load_path::M_FILE;\n                  else if (ext == \".oct\")\n                    t = load_path::OCT_FILE;\n                  else if (ext == \".mex\")\n                    t = load_path::MEX_FILE;\n\n                  if (t)\n                    {\n                      load_path::dir_info::fcn_file_map_iterator p\n                        = retval.find (base);\n\n                      if (p == retval.end ())\n                        retval[base] = t;\n                      else\n                        p->second |= t;\n                    }\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\nbool\nload_path::dir_info::update ()\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::string msg;\n\n  if (! sys::dir_exists (m_dir_name, msg))\n    {\n#else\n  sys::file_stat fs (m_dir_name);\n\n  if (! fs)\n    {\n      std::string msg = fs.error ();\n#endif\n      warning_with_id (\"Octave:load-path:dir-info:update-failed\",\n                       \"load_path: %s: %s\", m_dir_name.c_str (), msg.c_str ());\n\n      return false;\n    }\n\n  if (m_is_relative)\n    {\n      try\n        {\n          std::string abs_name = sys::canonicalize_file_name (m_dir_name);\n\n          const_abs_dir_cache_iterator p = s_abs_dir_cache.find (abs_name);\n\n          if (p != s_abs_dir_cache.end ())\n            {\n              // The directory is in the cache of all directories we have\n              // visited (indexed by absolute name).  If it is out of date,\n              // initialize it.  Otherwise, copy the info from the cache.\n              // By doing that, we avoid unnecessary calls to stat that can\n              // slow things down tremendously for large directories.\n              const dir_info& di = p->second;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n              if ((sys::file_time (m_dir_name)\n#else\n              if ((sys::file_time (fs.mtime ().unix_time ())\n#endif\n                   + sys::file_time::time_resolution ()\n                   > di.m_dir_time_last_checked)\n                  || subdirs_modified (m_dir_name, m_dir_time_last_checked))\n                initialize ();\n              else\n                {\n                  // Copy over info from cache, but leave dir_name and\n                  // is_relative unmodified.\n                  m_abs_dir_name = di.m_abs_dir_name;\n                  m_dir_mtime = di.m_dir_mtime;\n                  m_dir_time_last_checked = di.m_dir_time_last_checked;\n                  m_all_files = di.m_all_files;\n                  m_fcn_files = di.m_fcn_files;\n                  m_private_file_map = di.m_private_file_map;\n                  m_method_file_map = di.m_method_file_map;\n                  m_package_dir_map = di.m_package_dir_map;\n                }\n            }\n          else\n            {\n              // We haven't seen this directory before.\n              initialize ();\n            }\n        }\n      catch (const execution_exception& ee)\n        {\n          // Skip updating if we don't know where we are, but don't\n          // treat it as an error.\n\n          interpreter& interp = __get_interpreter__ ();\n\n          interp.recover_from_exception ();\n        }\n    }\n  // Absolute path, check timestamp to see whether it requires re-caching\n#if defined (OCTAVE_USE_WINDOWS_API)\n  else if (sys::file_time (m_dir_name)\n#else\n  else if (sys::file_time (fs.mtime ().unix_time ())\n#endif\n           + sys::file_time::time_resolution () > m_dir_time_last_checked\n           || subdirs_modified (m_dir_name, m_dir_time_last_checked))\n    initialize ();\n\n  return true;\n}\n\nbool\nload_path::dir_info::is_package (const std::string& name) const\n{\n  std::size_t pos = name.find ('.');\n\n  if (pos == std::string::npos)\n    return m_package_dir_map.find (name) != m_package_dir_map.end ();\n  else\n    {\n      std::string name_head = name.substr (0, pos);\n      std::string name_tail = name.substr (pos + 1);\n\n      const_package_dir_map_iterator it = m_package_dir_map.find (name_head);\n\n      if (it != m_package_dir_map.end ())\n        return it->second.is_package (name_tail);\n      else\n        return false;\n    }\n}\n\nvoid\nload_path::dir_info::initialize ()\n{\n  m_is_relative = ! sys::env::absolute_pathname (m_dir_name);\n\n  m_dir_time_last_checked = sys::file_time (static_cast<OCTAVE_TIME_T> (0));\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::string msg;\n\n  if (sys::dir_exists (m_dir_name, msg))\n#else\n  sys::file_stat fs (m_dir_name);\n\n  if (fs)\n#endif\n    {\n      m_method_file_map.clear ();\n      m_package_dir_map.clear ();\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n      m_dir_mtime = sys::file_time (m_dir_name);\n#else\n      m_dir_mtime = fs.mtime ().unix_time ();\n#endif\n\n      m_dir_time_last_checked = sys::file_time ();\n\n      get_file_list (m_dir_name);\n\n      try\n        {\n          m_abs_dir_name = sys::canonicalize_file_name (m_dir_name);\n\n          // FIXME: nothing is ever removed from this cache of\n          // directory information, so there could be some resource\n          // problems.  Perhaps it should be pruned from time to time.\n\n          s_abs_dir_cache[m_abs_dir_name] = *this;\n        }\n      catch (const execution_exception&)\n        {\n          // Skip updating if we don't know where we are but don't treat\n          // it as an error.\n\n          interpreter& interp = __get_interpreter__ ();\n\n          interp.recover_from_exception ();\n        }\n    }\n  else\n    {\n#if ! defined (OCTAVE_USE_WINDOWS_API)\n      std::string msg = fs.error ();\n#endif\n      warning (\"load_path: %s: %s\", m_dir_name.c_str (), msg.c_str ());\n    }\n}\n\nvoid\nload_path::dir_info::get_file_list (const std::string& d)\n{\n  string_vector flist;\n  std::string msg;\n\n  if (! sys::get_dirlist (d, flist, msg))\n    {\n      warning (\"load_path: %s: %s\", d.c_str (), msg.c_str ());\n      return;\n    }\n\n  octave_idx_type len = flist.numel ();\n\n  m_all_files.resize (len);\n  m_fcn_files.resize (len);\n\n  octave_idx_type all_files_count = 0;\n  octave_idx_type fcn_files_count = 0;\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      std::string fname = flist[i];\n\n      std::string full_name = sys::file_ops::concat (d, fname);\n\n      if (sys::dir_exists (full_name))\n        {\n          if (fname == \"private\")\n            get_private_file_map (full_name);\n          else if (fname[0] == '@')\n            get_method_file_map (full_name, fname.substr (1));\n          else if (fname[0] == '+')\n            get_package_dir (full_name, fname.substr (1));\n        }\n      else if (sys::file_exists (full_name))\n        {\n          m_all_files[all_files_count++] = fname;\n\n          std::size_t pos = fname.rfind ('.');\n\n          if (pos != std::string::npos)\n            {\n              std::string ext = fname.substr (pos);\n\n              if (ext == \".m\" || ext == \".oct\" || ext == \".mex\")\n                {\n                  std::string base = fname.substr (0, pos);\n\n                  if (valid_identifier (base))\n                    m_fcn_files[fcn_files_count++] = fname;\n                }\n            }\n        }\n    }\n\n  m_all_files.resize (all_files_count);\n  m_fcn_files.resize (fcn_files_count);\n}\n\nvoid\nload_path::dir_info::get_private_file_map (const std::string& d)\n{\n  m_private_file_map = get_fcn_files (d);\n}\n\nvoid\nload_path::dir_info::get_method_file_map (const std::string& d,\n    const std::string& class_name)\n{\n  m_method_file_map[class_name].m_method_file_map = get_fcn_files (d);\n\n  std::string pd = sys::file_ops::concat (d, \"private\");\n\n  if (sys::dir_exists (pd))\n    m_method_file_map[class_name].m_private_file_map = get_fcn_files (pd);\n}\n\nvoid\nload_path::dir_info::get_package_dir (const std::string& d,\n                                      const std::string& package_name)\n{\n  m_package_dir_map[package_name] = dir_info (d);\n}\n\nvoid\nload_path::package_info::move (const dir_info& di, bool at_end)\n{\n  std::string dir_name = di.m_abs_dir_name;\n\n  auto s = std::find (m_dir_list.begin (), m_dir_list.end (), dir_name);\n\n  if (s != m_dir_list.end ())\n    {\n      m_dir_list.erase (s);\n\n      if (at_end)\n        m_dir_list.push_back (dir_name);\n      else\n        m_dir_list.push_front (dir_name);\n    }\n\n  move_fcn_map (dir_name, di.m_fcn_files, at_end);\n\n  // No need to move elements of private function map.\n\n  move_method_map (dir_name, at_end);\n}\n\nvoid\nload_path::package_info::remove (const dir_info& di)\n{\n  std::string dir = di.m_abs_dir_name;\n\n  string_vector fcn_files = di.m_fcn_files;\n\n  m_dir_list.remove (dir);\n\n  remove_fcn_map (dir, fcn_files);\n\n  remove_private_fcn_map (dir);\n\n  remove_method_map (dir);\n}\n\nvoid\nload_path::package_info::display (std::ostream& os) const\n{\n  os << \"*** package_info: \"\n     << (m_package_name.empty () ? \"<top-level>\" : m_package_name)\n     << \"\\n\\n\";\n\n  for (const auto& dir : m_dir_list)\n    os << dir << \"\\n\";\n  os << \"\\n\";\n\n  for (const auto& dir_fnlst : m_private_fcn_map)\n    {\n      os << \"\\n*** private functions in \"\n         << sys::file_ops::concat (dir_fnlst.first, \"private\")\n         << \":\\n\\n\";\n\n      print_fcn_list (os, dir_fnlst.second);\n    }\n\n#if defined (OCTAVE_LOADPATH_DEBUG)\n\n  for (const auto& nm_filst : m_fcn_map)\n    {\n      os << nm_filst.first << \":\\n\";\n\n      const file_info_list_type& file_info_list = nm_filst.second;\n\n      for (const auto& finfo : file_info_list)\n        {\n          os << \"  \" << finfo.dir_name << \" (\";\n\n          print_types (os, finfo.types);\n\n          os << \")\\n\";\n        }\n    }\n\n  for (const auto& cls_fnmap : m_method_map)\n    {\n      os << \"CLASS \" << cls_fnmap.first << \":\\n\";\n\n      const fcn_map_type& fm = cls_fnmap.second;\n\n      for (const auto& nm_fnlst : m_fcn_map)\n        {\n          os << \"  \" << nm_fnlst.first << \":\\n\";\n\n          const file_info_list_type& file_info_list = nm_fnlst.second;\n\n          for (const auto& finfo : file_info_list)\n            {\n              os << \"  \" << finfo.dir_name << \" (\";\n\n              print_types (os, finfo.types);\n\n              os << \")\\n\";\n            }\n        }\n    }\n\n  os << \"\\n\";\n#endif\n\n}\n\nstd::string\nload_path::package_info::find_fcn (const std::string& fcn,\n                                   std::string& dir_name,\n                                   int type) const\n{\n  std::string retval;\n\n  //  update ();\n\n  if (fcn.length () > 0 && fcn[0] == '@')\n    {\n      std::size_t pos = fcn.find ('/');\n\n      if (pos != std::string::npos)\n        {\n          std::string class_name = fcn.substr (1, pos-1);\n          std::string meth = fcn.substr (pos+1);\n\n          retval = find_method (class_name, meth, dir_name);\n        }\n    }\n  else\n    {\n      // Ensure that dir_name is empty if function is not found.\n      dir_name = \"\";\n\n      const_fcn_map_iterator p = m_fcn_map.find (fcn);\n\n      if (p != m_fcn_map.end ())\n        {\n          const file_info_list_type& file_info_list = p->second;\n\n          for (const auto& fi : file_info_list)\n            {\n              retval = sys::file_ops::concat (fi.m_dir_name, fcn);\n\n              if (check_file_type (retval, type, fi.m_types,\n                                   fcn, \"load_path::find_fcn\"))\n                {\n                  dir_name = fi.m_dir_name;\n                  break;\n                }\n              else\n                retval = \"\";\n            }\n        }\n    }\n\n  return retval;\n}\n\nstd::string\nload_path::package_info::find_private_fcn (const std::string& dir,\n    const std::string& fcn,\n    int type) const\n{\n  std::string retval;\n\n  //  update ();\n\n  const_private_fcn_map_iterator q = m_private_fcn_map.find (dir);\n\n  if (q != m_private_fcn_map.end ())\n    {\n      const dir_info::fcn_file_map_type& fcn_file_map = q->second;\n\n      dir_info::const_fcn_file_map_iterator p = fcn_file_map.find (fcn);\n\n      if (p != fcn_file_map.end ())\n        {\n          std::string fname\n            = sys::file_ops::concat (sys::file_ops::concat (dir, \"private\"),\n                                     fcn);\n\n          if (check_file_type (fname, type, p->second, fcn,\n                               \"load_path::find_private_fcn\"))\n            retval = fname;\n        }\n    }\n\n  return retval;\n}\n\nstd::string\nload_path::package_info::find_method (const std::string& class_name,\n                                      const std::string& meth,\n                                      std::string& dir_name,\n                                      int type) const\n{\n  std::string retval;\n\n  //  update ();\n\n  // Ensure that dir_name is empty if method is not found.\n  dir_name = \"\";\n\n  const_method_map_iterator q = m_method_map.find (class_name);\n\n  if (q != m_method_map.end ())\n    {\n      const fcn_map_type& m = q->second;\n\n      const_fcn_map_iterator p = m.find (meth);\n\n      if (p != m.end ())\n        {\n          const file_info_list_type& file_info_list = p->second;\n\n          for (const auto& fi : file_info_list)\n            {\n              retval = sys::file_ops::concat (fi.m_dir_name, meth);\n\n              bool found = check_file_type (retval, type, fi.m_types,\n                                            meth, \"load_path::find_method\");\n\n              if (found)\n                {\n                  dir_name = fi.m_dir_name;\n                  break;\n                }\n              else\n                retval = \"\";\n            }\n        }\n    }\n\n  return retval;\n}\n\nstd::list<std::string>\nload_path::package_info::methods (const std::string& class_name) const\n{\n  std::list<std::string> retval;\n\n  //  update ();\n\n  const_method_map_iterator mtd_map_it = m_method_map.find (class_name);\n\n  if (mtd_map_it != m_method_map.end ())\n    {\n      for (const auto& nm_filst : mtd_map_it->second)\n        retval.push_back (nm_filst.first);\n    }\n\n  if (! retval.empty ())\n    retval.sort ();\n\n  return retval;\n}\n\nvoid\nload_path::package_info::overloads (const std::string& meth,\n                                    std::list<std::string>& l) const\n{\n  for (const auto& cls_fnmap : m_method_map)\n    {\n      const fcn_map_type& m = cls_fnmap.second;\n\n      if (m.find (meth) != m.end ())\n        {\n          std::string class_name = cls_fnmap.first;\n\n          if (! m_package_name.empty ())\n            class_name = m_package_name + '.' + class_name;\n\n          l.push_back (class_name);\n        }\n    }\n}\n\nstring_vector\nload_path::package_info::fcn_names () const\n{\n  std::size_t len = m_fcn_map.size ();\n\n  string_vector retval (len);\n\n  octave_idx_type count = 0;\n\n  for (const auto& nm_filst : m_fcn_map)\n    retval[count++] = nm_filst.first;\n\n  return retval;\n}\n\nvoid\nload_path::package_info::add_to_fcn_map (const dir_info& di,\n    bool at_end, bool updating)\n{\n  std::string dir_name = di.m_abs_dir_name;\n\n  string_vector fcn_files = di.m_fcn_files;\n\n  octave_idx_type len = fcn_files.numel ();\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      std::string fname = fcn_files[i];\n\n      std::string ext;\n      std::string base = fname;\n\n      std::size_t pos = fname.rfind ('.');\n\n      if (pos != std::string::npos)\n        {\n          base = fname.substr (0, pos);\n          ext = fname.substr (pos);\n        }\n\n      file_info_list_type& file_info_list = m_fcn_map[base];\n\n      auto p = file_info_list.begin ();\n\n      while (p != file_info_list.end ())\n        {\n          if (p->m_dir_name == dir_name)\n            break;\n\n          p++;\n        }\n\n      int t = 0;\n      if (ext == \".m\")\n        t = load_path::M_FILE;\n      else if (ext == \".oct\")\n        t = load_path::OCT_FILE;\n      else if (ext == \".mex\")\n        t = load_path::MEX_FILE;\n\n      if (p == file_info_list.end ())\n        {\n          // Warn if a built-in or library function is being shadowed,\n          // but not if we are just updating (rehashing) the list.\n\n          if (! updating)\n            {\n              if (file_info_list.empty ())\n                {\n                  symbol_table& symtab = __get_symbol_table__ ();\n\n                  // FIXME: It is currently not possible to check for built-in\n                  //        functions including their +package namespace.\n                  //        Assume that no built-in functions with a +package\n                  //        namespace are installed and skip the warning for\n                  //        new functions that *are* in a +package namespace.\n\n                  if (m_package_name.empty ()\n                      && symtab.is_built_in_function_name (base))\n                    {\n                      std::string fcn_path = sys::file_ops::concat (dir_name,\n                                             fname);\n\n                      warning_with_id (\"Octave:shadowed-function\",\n                                       \"function %s shadows a built-in function\",\n                                       fcn_path.c_str ());\n                    }\n                }\n              else if (! at_end)\n                {\n                  file_info& old = file_info_list.front ();\n\n                  // FIXME: do we need to be more careful about the\n                  // way we look for old.dir_name in sys_path to avoid\n                  // partial matches?\n\n                  // Don't warn about Contents.m files since we expect\n                  // more than one to exist in the load path.\n\n                  if (fname != \"Contents.m\"\n                      && s_sys_path.find (old.m_dir_name) != std::string::npos\n                      && in_path_list (s_sys_path, old.m_dir_name))\n                    {\n                      std::string fcn_path = sys::file_ops::concat (dir_name,\n                                             fname);\n\n                      warning_with_id (\"Octave:shadowed-function\",\n                                       \"function %s shadows a core library function\",\n                                       fcn_path.c_str ());\n                    }\n                }\n            }\n\n          file_info fi (dir_name, t);\n\n          if (at_end)\n            file_info_list.push_back (fi);\n          else\n            file_info_list.push_front (fi);\n        }\n      else\n        {\n          file_info& fi = *p;\n\n          fi.m_types |= t;\n        }\n    }\n}\n\nvoid\nload_path::package_info::add_to_private_fcn_map (const dir_info& di)\n{\n  dir_info::fcn_file_map_type private_file_map = di.m_private_file_map;\n\n  if (! private_file_map.empty ())\n    m_private_fcn_map[di.m_abs_dir_name] = private_file_map;\n}\n\nvoid\nload_path::package_info::add_to_method_map (const dir_info& di, bool at_end)\n{\n  std::string dir_name = di.m_abs_dir_name;\n\n  // <CLASS_NAME, CLASS_INFO>\n  dir_info::method_file_map_type method_file_map = di.m_method_file_map;\n\n  for (const auto& cls_ci : method_file_map)\n    {\n      std::string class_name = cls_ci.first;\n\n      fcn_map_type& fm = m_method_map[class_name];\n\n      std::string full_dir_name\n        = sys::file_ops::concat (dir_name, '@' + class_name);\n\n      const dir_info::class_info& ci = cls_ci.second;\n\n      // <FCN_NAME, TYPES>\n      const dir_info::fcn_file_map_type& m = ci.m_method_file_map;\n\n      for (const auto& nm_typ : m)\n        {\n          std::string base = nm_typ.first;\n          int types = nm_typ.second;\n\n          file_info_list_type& file_info_list = fm[base];\n\n          auto p2 = file_info_list.begin ();\n          while (p2 != file_info_list.end ())\n            {\n              if (p2->m_dir_name == full_dir_name)\n                break;\n\n              p2++;\n            }\n\n          if (p2 == file_info_list.end ())\n            {\n              file_info fi (full_dir_name, types);\n\n              if (at_end)\n                file_info_list.push_back (fi);\n              else\n                file_info_list.push_front (fi);\n            }\n          else\n            {\n              // FIXME: is this possible?\n              file_info& fi = *p2;\n\n              fi.m_types = types;\n            }\n        }\n\n      // <FCN_NAME, TYPES>\n      dir_info::fcn_file_map_type private_file_map = ci.m_private_file_map;\n\n      if (! private_file_map.empty ())\n        m_private_fcn_map[full_dir_name] = private_file_map;\n    }\n}\n\nvoid\nload_path::package_info::move_fcn_map (const std::string& dir_name,\n                                       const string_vector& fcn_files,\n                                       bool at_end)\n{\n  octave_idx_type len = fcn_files.numel ();\n\n  for (octave_idx_type k = 0; k < len; k++)\n    {\n      std::string fname = fcn_files[k];\n\n      std::string ext;\n      std::string base = fname;\n\n      std::size_t pos = fname.rfind ('.');\n\n      if (pos != std::string::npos)\n        {\n          base = fname.substr (0, pos);\n          ext = fname.substr (pos);\n        }\n\n      file_info_list_type& file_info_list = m_fcn_map[base];\n\n      if (file_info_list.size () == 1)\n        continue;\n      else\n        {\n          for (auto fi_it = file_info_list.begin ();\n               fi_it != file_info_list.end ();\n               fi_it++)\n            {\n              if (fi_it->m_dir_name == dir_name)\n                {\n                  file_info fi_tmp = *fi_it;\n\n                  file_info_list.erase (fi_it);\n\n                  if (at_end)\n                    file_info_list.push_back (fi_tmp);\n                  else\n                    file_info_list.push_front (fi_tmp);\n\n                  break;\n                }\n            }\n        }\n    }\n}\n\nvoid\nload_path::package_info::move_method_map (const std::string& dir_name,\n    bool at_end)\n{\n  for (auto& cls_fnmap : m_method_map)\n    {\n      std::string class_name = cls_fnmap.first;\n\n      fcn_map_type& fn_map = cls_fnmap.second;\n\n      std::string full_dir_name\n        = sys::file_ops::concat (dir_name, '@' + class_name);\n\n      for (auto& nm_filst : fn_map)\n        {\n          file_info_list_type& file_info_list = nm_filst.second;\n\n          if (file_info_list.size () == 1)\n            continue;\n          else\n            {\n              for (auto fi_it = file_info_list.begin ();\n                   fi_it != file_info_list.end (); fi_it++)\n                {\n                  if (fi_it->m_dir_name == full_dir_name)\n                    {\n                      file_info fi_tmp = *fi_it;\n\n                      file_info_list.erase (fi_it);\n\n                      if (at_end)\n                        file_info_list.push_back (fi_tmp);\n                      else\n                        file_info_list.push_front (fi_tmp);\n\n                      break;\n                    }\n                }\n            }\n        }\n    }\n}\n\nvoid\nload_path::package_info::remove_fcn_map (const std::string& dir,\n    const string_vector& fcn_files)\n{\n  octave_idx_type len = fcn_files.numel ();\n\n  for (octave_idx_type k = 0; k < len; k++)\n    {\n      std::string fname = fcn_files[k];\n\n      std::string ext;\n      std::string base = fname;\n\n      std::size_t pos = fname.rfind ('.');\n\n      if (pos != std::string::npos)\n        {\n          base = fname.substr (0, pos);\n          ext = fname.substr (pos);\n        }\n\n      file_info_list_type& file_info_list = m_fcn_map[base];\n\n      for (auto fi_it = file_info_list.begin ();\n           fi_it != file_info_list.end ();\n           fi_it++)\n        {\n          if (fi_it->m_dir_name == dir)\n            {\n              file_info_list.erase (fi_it);\n\n              if (file_info_list.empty ())\n                m_fcn_map.erase (fname);\n\n              break;\n            }\n        }\n    }\n}\n\nvoid\nload_path::package_info::remove_private_fcn_map (const std::string& dir)\n{\n  auto p = m_private_fcn_map.find (dir);\n\n  if (p != m_private_fcn_map.end ())\n    m_private_fcn_map.erase (p);\n}\n\nvoid\nload_path::package_info::remove_method_map (const std::string& dir)\n{\n  for (auto& cls_fnmap : m_method_map)\n    {\n      std::string class_name = cls_fnmap.first;\n\n      fcn_map_type& fn_map = cls_fnmap.second;\n\n      std::string full_dir_name\n        = sys::file_ops::concat (dir, '@' + class_name);\n\n      for (auto& nm_filst : fn_map)\n        {\n          file_info_list_type& file_info_list = nm_filst.second;\n\n          if (file_info_list.size () == 1)\n            continue;\n          else\n            {\n              for (auto fi_it = file_info_list.begin ();\n                   fi_it != file_info_list.end (); fi_it++)\n                {\n                  if (fi_it->m_dir_name == full_dir_name)\n                    {\n                      file_info_list.erase (fi_it);\n                      // FIXME: if there are no other elements, we\n                      // should remove this element of fn_map but calling\n                      // erase here would invalidate the iterator fi_it.\n\n                      break;\n                    }\n                }\n            }\n        }\n    }\n}\n\nbool\nload_path::package_info::check_file_type (std::string& fname, int type,\n    int possible_types,\n    const std::string& fcn,\n    const char *who) const\n{\n  bool retval = false;\n\n  if (type == load_path::OCT_FILE)\n    {\n      if ((type & possible_types) == load_path::OCT_FILE)\n        {\n          fname += \".oct\";\n          retval = true;\n        }\n    }\n  else if (type == load_path::M_FILE)\n    {\n      if ((type & possible_types) == load_path::M_FILE)\n        {\n          fname += \".m\";\n          retval = true;\n        }\n    }\n  else if (type == load_path::MEX_FILE)\n    {\n      if ((type & possible_types) == load_path::MEX_FILE)\n        {\n          fname += \".mex\";\n          retval = true;\n        }\n    }\n  else if (type == (load_path::M_FILE | load_path::OCT_FILE))\n    {\n      if (possible_types & load_path::OCT_FILE)\n        {\n          fname += \".oct\";\n          retval = true;\n        }\n      else if (possible_types & load_path::M_FILE)\n        {\n          fname += \".m\";\n          retval = true;\n        }\n    }\n  else if (type == (load_path::M_FILE | load_path::MEX_FILE))\n    {\n      if (possible_types & load_path::MEX_FILE)\n        {\n          fname += \".mex\";\n          retval = true;\n        }\n      else if (possible_types & load_path::M_FILE)\n        {\n          fname += \".m\";\n          retval = true;\n        }\n    }\n  else if (type == (load_path::OCT_FILE | load_path::MEX_FILE))\n    {\n      if (possible_types & load_path::OCT_FILE)\n        {\n          fname += \".oct\";\n          retval = true;\n        }\n      else if (possible_types & load_path::MEX_FILE)\n        {\n          fname += \".mex\";\n          retval = true;\n        }\n    }\n  else if (type == (load_path::M_FILE | load_path::OCT_FILE\n                    | load_path::MEX_FILE))\n    {\n      if (possible_types & load_path::OCT_FILE)\n        {\n          fname += \".oct\";\n          retval = true;\n        }\n      else if (possible_types & load_path::MEX_FILE)\n        {\n          fname += \".mex\";\n          retval = true;\n        }\n      else if (possible_types & load_path::M_FILE)\n        {\n          fname += \".m\";\n          retval = true;\n        }\n    }\n  else\n    error (\"%s: %s: invalid type code = %d\", who, fcn.c_str (), type);\n\n  return retval;\n}\n\nvoid\nload_path::package_info::print_types (std::ostream& os, int types) const\n{\n  bool printed_type = false;\n\n  if (types & load_path::OCT_FILE)\n    {\n      os << \"oct\";\n      printed_type = true;\n    }\n\n  if (types & load_path::MEX_FILE)\n    {\n      if (printed_type)\n        os << '|';\n      os << \"mex\";\n      printed_type = true;\n    }\n\n  if (types & load_path::M_FILE)\n    {\n      if (printed_type)\n        os << '|';\n      os << 'm';\n      printed_type = true;\n    }\n}\n\nvoid\nload_path::package_info::print_fcn_list (std::ostream& os,\n    const load_path::dir_info::fcn_file_map_type& lst) const\n{\n  for (const auto& nm_typ : lst)\n    {\n      os << \"  \" << nm_typ.first << \" (\";\n\n      print_types (os, nm_typ.second);\n\n      os << \")\\n\";\n    }\n}\n\nstd::string\ngenpath (const std::string& dirname, const string_vector& skip)\n{\n  std::string retval;\n  string_vector dirlist;\n  std::string msg;\n\n  if (! sys::get_dirlist (dirname, dirlist, msg))\n    return retval;\n\n  retval = dirname;\n\n  dirlist = dirlist.sort (false);\n\n  octave_idx_type len = dirlist.numel ();\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      std::string elt = dirlist[i];\n\n      bool skip_p = (elt == \".\" || elt == \"..\" || elt[0] == '@'\n                     || elt[0] == '+');\n\n      if (! skip_p)\n        {\n          for (octave_idx_type j = 0; j < skip.numel (); j++)\n            {\n              skip_p = (elt == skip[j]);\n              if (skip_p)\n                break;\n            }\n\n          if (! skip_p)\n            {\n              std::string nm = sys::file_ops::concat (dirname, elt);\n\n              if (sys::dir_exists (nm))\n                retval += (directory_path::path_sep_str ()\n                           + genpath (nm, skip));\n            }\n        }\n    }\n\n  return retval;\n}\n\nDEFUN (genpath, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{pathstr} =} genpath (@var{dir})\n@deftypefnx {} {@var{pathstr} =} genpath (@var{dir}, @var{skipdir1}, @dots{})\nReturn a path constructed from @var{dir} and all its subdirectories.\n\nThe path does not include package directories (beginning with @samp{+}),\nold-style class directories (beginning with @samp{@@}), @file{private}\ndirectories, or any subdirectories of these types.\n\nIf additional string parameters are given, the resulting path will exclude\ndirectories with those names.\n@seealso{path, addpath}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 1)\n    {\n      std::string dirname = args(0).xstring_value (\"genpath: DIR must be a string\");\n\n      retval = genpath (dirname);\n    }\n  else\n    {\n      std::string dirname = args(0).xstring_value (\"genpath: all arguments must be strings\");\n\n      string_vector skip (nargin - 1);\n\n      for (octave_idx_type i = 1; i < nargin; i++)\n        skip[i-1] = args(i).xstring_value (\"genpath: all arguments must be strings\");\n\n      retval = genpath (dirname, skip);\n    }\n\n  return retval;\n}\n\nDEFMETHOD (rehash, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} rehash ()\nReinitialize Octave's load path directory cache.\n@end deftypefn */)\n{\n  load_path& lp = interp.get_load_path ();\n\n  lp.rehash ();\n\n  return ovl ();\n}\n\nDEFMETHOD (command_line_path, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{pathstr} =} command_line_path ()\nReturn the path argument given to Octave at the command line when the\ninterpreter was started (@w{@env{--path @var{arg}}}).\n\n@seealso{path, addpath, rmpath, genpath, pathdef, savepath, pathsep}\n@end deftypefn */)\n{\n  if (! args.empty ())\n    print_usage ();\n\n  load_path& lp = interp.get_load_path ();\n\n  return ovl (lp.get_command_line_path ());\n}\n\nDEFMETHOD (restoredefaultpath, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{pathstr} =} restoredefaultpath ()\nRestore Octave's path to its initial state at startup.\n\nThe re-initialized path is returned as an output.\n@seealso{path, addpath, rmpath, genpath, pathdef, savepath, pathsep}\n@end deftypefn */)\n{\n  if (! args.empty ())\n    print_usage ();\n\n  load_path& lp = interp.get_load_path ();\n\n  lp.initialize (true);\n\n  return ovl (lp.system_path ());\n}\n\n// Return Octave's original default list of directories in which to\n// search for function files.  This corresponds to the path that\n// exists prior to running the system's octaverc file or the user's\n// ~/.octaverc file\n\nDEFMETHOD (__pathorig__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{sys_path} =} __pathorig__ ()\n@deftypefnx {} {@var{prev_sys_path} =} __pathorig__ (sys_path)\nUndocumented internal function.\n@end deftypefn */)\n{\n  load_path& lp = interp.get_load_path ();\n\n  if (args.empty ())\n    return ovl (lp.system_path ());\n\n  std::string sys_path = args(0).xstring_value (\"__pathorig__: SYS_PATH must be a string\");\n  std::string prev_sys_path = lp.system_path ();\n  lp.system_path (sys_path);\n  return ovl (prev_sys_path);\n}\n\nDEFMETHOD (path, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} path ()\n@deftypefnx {} {@var{str} =} path ()\n@deftypefnx {} {@var{str} =} path (@var{path1}, @dots{})\nModify or display Octave's load path.\n\nIf @var{nargin} and @var{nargout} are zero, display the elements of\nOctave's load path in an easy to read format.\n\nIf @var{nargin} is zero and nargout is greater than zero, return the\ncurrent load path.\n\nIf @var{nargin} is greater than zero, concatenate the arguments,\nseparating them with @code{pathsep}.  Set the internal search path\nto the result and return it.\n\nNo checks are made for duplicate elements.\n@seealso{addpath, rmpath, genpath, pathdef, savepath, pathsep}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  string_vector argv = args.make_argv (\"path\");\n\n  load_path& lp = interp.get_load_path ();\n\n  if (nargin > 0)\n    {\n      std::string path = argv[1];\n\n      for (int i = 2; i <= nargin; i++)\n        path += directory_path::path_sep_str () + argv[i];\n\n      lp.set (path, true);\n\n      lp.rehash ();\n    }\n\n  if (nargout > 0)\n    return ovl (lp.path ());\n  else if (nargin == 0 && nargout == 0)\n    {\n      octave_stdout <<\n                    \"\\nOctave's search path contains the following directories:\\n\\n\";\n\n      string_vector dirs = lp.dirs ();\n      const int width = command_editor::terminal_cols ();\n\n      dirs.list_in_columns (octave_stdout, width);\n\n      octave_stdout << \"\\n\";\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (addpath, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} addpath (@var{dir1}, @dots{})\n@deftypefnx {} {} addpath (@var{dir1}, @dots{}, @var{option})\n@deftypefnx {} {@var{oldpath} =} addpath (@dots{})\nAdd named directories to the function search path.\n\nIf @var{option} is @qcode{\"-begin\"} or 0 (the default), prepend the directory\nname(s) to the current path.  If @var{option} is @qcode{\"-end\"} or 1, append\nthe directory name(s) to the current path.  Directories added to the path must\nexist.\n\nIn addition to accepting individual directory arguments, lists of\ndirectory names separated by @code{pathsep} are also accepted.  For example:\n\n@example\naddpath (\"dir1:/dir2:~/dir3\")\n@end example\n\nThe newly added paths appear in the load path in the same order that they\nappear in the arguments of @code{addpath}.  When extending the load path to\nthe front, the last path in the list of arguments is added first.  When\nextending the load path to the end, the first path in the list of arguments\nis added first.\n\nFor each directory that is added, and that was not already in the path,\n@code{addpath} checks for the existence of a file named @file{PKG_ADD}\n(note lack of .m extension) and runs it if it exists.\n\n@seealso{path, rmpath, genpath, pathdef, savepath, pathsep}\n@end deftypefn */)\n{\n  // Originally written by Bill Denney and Etienne Grossman.\n  // Heavily modified and translated to C++ by jwe.\n\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  load_path& lp = interp.get_load_path ();\n\n  octave_value retval;\n\n  if (nargout > 0)\n    retval = lp.path ();\n\n  bool append = false;\n\n  octave_value option_arg = args(nargin-1);\n\n  if (option_arg.is_string ())\n    {\n      std::string option = option_arg.string_value ();\n\n      if (option == \"-end\")\n        {\n          append = true;\n          nargin--;\n        }\n      else if (option == \"-begin\")\n        nargin--;\n    }\n  else if (option_arg.isnumeric ())\n    {\n      int val = option_arg.strict_int_value (\"addpath: OPTION must be '-begin'/0 or '-end'/1\");\n\n      if (val == 0)\n        nargin--;\n      else if (val == 1)\n        {\n          append = true;\n          nargin--;\n        }\n      else\n        error (\"addpath: OPTION must be '-begin'/0 or '-end'/1\");\n    }\n\n  bool need_to_update = false;\n\n  octave_value_list arglist (args.slice (0, nargin));\n  if (! append)\n    arglist.reverse ();\n\n  for (int i = 0; i < arglist.length (); i++)\n    {\n      std::string arg = arglist(i).xstring_value (\"addpath: all arguments must be strings\");\n\n      std::list<std::string> dir_elts = split_path (arg);\n\n      if (! append)\n        std::reverse (dir_elts.begin (), dir_elts.end ());\n\n      for (auto dir : dir_elts)\n        {\n          // Remove duplicate directory separators\n          auto it_start = dir.begin ();\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)\n          // In Windows, start check at second character (for UNC paths).\n          it_start++;\n#endif\n          dir.erase (std::unique\n                     (it_start, dir.end (),\n                      [] (char l, char r)\n          {\n            return l == r && sys::file_ops::is_dir_sep (l);\n          }),\n          dir.end ());\n\n          auto pos = dir.find_last_of (sys::file_ops::dir_sep_chars ());\n          if (pos == std::string::npos)\n            {\n              if (! dir.empty () && dir[0] == '+')\n                warning_with_id (\"Octave:addpath-pkg\",\n                                 \"addpath: package directories should not be \"\n                                 \"added to path: %s\\n\", dir.c_str ());\n            }\n          else\n            {\n              if (pos + 1 < dir.length () && dir[pos+1] == '+')\n                warning_with_id (\"Octave:addpath-pkg\",\n                                 \"addpath: package directories should not be \"\n                                 \"added to path: %s\\n\", dir.c_str ());\n            }\n\n          if (append)\n            lp.append (dir, true);\n          else\n            lp.prepend (dir, true);\n\n          need_to_update = true;\n        }\n    }\n\n  if (need_to_update)\n    lp.rehash ();\n\n  return retval;\n}\n\nDEFMETHOD (rmpath, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} rmpath (@var{dir1}, @dots{})\n@deftypefnx {} {@var{oldpath} =} rmpath (@var{dir1}, @dots{})\nRemove @var{dir1}, @dots{} from the current function search path.\n\nIn addition to accepting individual directory arguments, lists of\ndirectory names separated by @code{pathsep} are also accepted.  For example:\n\n@example\nrmpath (\"dir1:/dir2:~/dir3\")\n@end example\n\nFor each directory that is removed, @code{rmpath} checks for the\nexistence of a file named @file{PKG_DEL} (note lack of .m extension)\nand runs it if it exists.\n\n@seealso{path, addpath, genpath, pathdef, savepath, pathsep}\n@end deftypefn */)\n{\n  // Originally written by Etienne Grossmann.  Heavily modified and translated\n  // to C++ by jwe.\n\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  octave_value retval;\n\n  load_path& lp = interp.get_load_path ();\n\n  if (nargout > 0)\n    retval = lp.path ();\n\n  bool need_to_update = false;\n\n  for (int i = 0; i < nargin; i++)\n    {\n      std::string arg = args(i).xstring_value (\"rmpath: all arguments must be strings\");\n      std::list<std::string> dir_elts = split_path (arg);\n\n      for (const auto& dir : dir_elts)\n        {\n          //dir = regexprep (dir_elts{j}, '//+', \"/\");\n                                           //dir = regexprep (dir, '/$', \"\");\n\n          if (! lp.remove (dir))\n            warning (\"rmpath: %s: not found\", dir.c_str ());\n          else\n            need_to_update = true;\n        }\n    }\n\n  if (need_to_update)\n    lp.rehash ();\n\n  return retval;\n}\n\nDEFMETHOD (__dump_load_path__, interp, , ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __dump_load_path__ ()\nPretty print Octave path directories and the files within each directory.\n@end deftypefn */)\n{\n  load_path& lp = interp.get_load_path ();\n\n  lp.display (octave_stdout);\n\n  return ovl ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/load-path.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_load_path_h)\n#define octave_load_path_h 1\n\n#include \"octave-config.h\"\n\n#include <functional>\n#include <iosfwd>\n#include <list>\n#include <map>\n#include <set>\n#include <string>\n\n#include \"oct-time.h\"\n#include \"pathsearch.h\"\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API load_path\n{\npublic:\n\n  load_path (interpreter& interp);\n\n  typedef void (*hook_fcn_ptr) (const std::string& dir);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (load_path)\n\n  ~load_path () = default;\n\n  void initialize (bool set_initial_path = false);\n\n  void clear ();\n\n  void set (const std::string& p, bool warn = false, bool is_init = false);\n\n  void append (const std::string& dir, bool warn = false);\n\n  void prepend (const std::string& dir, bool warn = false);\n\n  bool remove (const std::string& dir);\n\n  void update ();\n\n  bool contains_canonical (const std::string& dir_name) const;\n\n  bool contains_file_in_dir (const std::string& file_name,\n                             const std::string& dir_name);\n\n  std::string find_method (const std::string& class_name,\n                           const std::string& meth,\n                           std::string& dir_name,\n                           const std::string& pack_name = \"\")\n  {\n    return get_package (pack_name).find_method (class_name, meth, dir_name);\n  }\n\n  std::string find_method (const std::string& class_name,\n                           const std::string& meth,\n                           const std::string& pack_name = \"\")\n  {\n    std::string dir_name;\n    return find_method (class_name, meth, dir_name, pack_name);\n  }\n\n  std::list<std::string> methods (const std::string& class_name,\n                                  const std::string& pack_name = \"\")\n  {\n    return get_package (pack_name).methods (class_name);\n  }\n\n  std::list<std::string> overloads (const std::string& meth) const;\n\n  bool find_package (const std::string& package_name) const\n  {\n    return (m_package_map.find (package_name) != m_package_map.end ());\n  }\n\n  std::list<std::string>\n  get_all_package_names (bool only_top_level = true) const;\n\n  std::string find_fcn (const std::string& fcn, std::string& dir_name,\n                        const std::string& pack_name = \"\")\n  {\n    return get_package (pack_name).find_fcn (fcn, dir_name);\n  }\n\n  std::string find_fcn (const std::string& fcn,\n                        const std::string& pack_name = \"\")\n  {\n    std::string dir_name;\n    return find_fcn (fcn, dir_name, pack_name);\n  }\n\n  std::string find_private_fcn (const std::string& dir,\n                                const std::string& fcn,\n                                const std::string& pack_name = \"\")\n  {\n    return get_package (pack_name).find_private_fcn (dir, fcn);\n  }\n\n  std::string find_fcn_file (const std::string& fcn,\n                             const std::string& pack_name = \"\")\n  {\n    std::string dir_name;\n    return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE);\n  }\n\n  std::string find_oct_file (const std::string& fcn,\n                             const std::string& pack_name = \"\")\n  {\n    std::string dir_name;\n    return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE);\n  }\n\n  std::string find_mex_file (const std::string& fcn,\n                             const std::string& pack_name = \"\")\n  {\n    std::string dir_name;\n    return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE);\n  }\n\n  std::string find_file (const std::string& file) const;\n\n  std::string find_dir (const std::string& dir) const;\n\n  string_vector find_matching_dirs (const std::string& dir) const;\n\n  std::string find_first_of (const string_vector& files) const;\n\n  string_vector find_all_first_of (const string_vector& files) const;\n\n  string_vector dirs () const;\n\n  std::list<std::string> dir_list () const;\n\n  string_vector files (const std::string& dir, bool omit_exts = false) const;\n\n  string_vector fcn_names () const;\n\n  std::string path () const;\n\n  void display (std::ostream& os) const;\n\n  std::function<void (const std::string&)> get_add_hook ()\n  {\n    return m_add_hook;\n  }\n\n  std::function<void (const std::string&)> get_remove_hook ()\n  {\n    return m_remove_hook;\n  }\n\n  void set_add_hook (const std::function<void (const std::string&)>& f)\n  {\n    m_add_hook = f;\n  }\n\n  void set_remove_hook (const std::function<void (const std::string&)>& f)\n  {\n    m_remove_hook = f;\n  }\n\n  void read_dir_config (const std::string& dir) const;\n\n  void execute_pkg_add (const std::string& dir);\n  void execute_pkg_del (const std::string& dir);\n\n  void set_command_line_path (const std::string& p)\n  {\n    if (m_command_line_path.empty ())\n      m_command_line_path = p;\n    else\n      m_command_line_path += directory_path::path_sep_str () + p;\n  }\n\n  std::string get_command_line_path () const\n  {\n    return m_command_line_path;\n  }\n\n  std::string system_path () const { return s_sys_path; }\n  void system_path (const std::string& sys_path)\n  {\n    s_sys_path = sys_path;\n    return;\n  }\n\n  void rehash ();\n\n  static const int M_FILE = 1;\n  static const int OCT_FILE = 2;\n  static const int MEX_FILE = 4;\n\nprivate:\n\n  class dir_info\n  {\n  public:\n\n    // <FCN_NAME, TYPE>\n    typedef std::map<std::string, int> fcn_file_map_type;\n\n    typedef fcn_file_map_type::const_iterator const_fcn_file_map_iterator;\n    typedef fcn_file_map_type::iterator fcn_file_map_iterator;\n\n    struct class_info\n    {\n    public:\n      class_info () : m_method_file_map (), m_private_file_map () { }\n\n      class_info (const class_info& ci)\n        : m_method_file_map (ci.m_method_file_map),\n          m_private_file_map (ci.m_private_file_map)\n      { }\n\n      class_info& operator = (const class_info& ci)\n      {\n        if (this != &ci)\n          {\n            m_method_file_map = ci.m_method_file_map;\n            m_private_file_map = ci.m_private_file_map;\n          }\n        return *this;\n      }\n\n      ~class_info () = default;\n\n      fcn_file_map_type m_method_file_map;\n      fcn_file_map_type m_private_file_map;\n    };\n\n    // <CLASS_NAME, CLASS_INFO>\n    typedef std::map<std::string, class_info> method_file_map_type;\n\n    typedef method_file_map_type::const_iterator const_method_file_map_iterator;\n    typedef method_file_map_type::iterator method_file_map_iterator;\n\n    // <PACKAGE_NAME, DIR_INFO>\n    typedef std::map<std::string, dir_info> package_dir_map_type;\n\n    typedef package_dir_map_type::const_iterator const_package_dir_map_iterator;\n    typedef package_dir_map_type::iterator package_dir_map_iterator;\n\n    // This default constructor is only provided so we can create a\n    // std::map of dir_info objects.  You should not use this\n    // constructor for any other purpose.\n    dir_info () = default;\n\n    dir_info (const std::string& d)\n      : m_dir_name (d), m_abs_dir_name (), m_is_relative (false),\n        m_dir_mtime (), m_dir_time_last_checked (), m_all_files (),\n        m_fcn_files (), m_private_file_map (), m_method_file_map (),\n        m_package_dir_map ()\n    {\n      initialize ();\n    }\n\n    dir_info (const dir_info&) = default;\n\n    ~dir_info () = default;\n\n    dir_info& operator = (const dir_info&) = default;\n\n    bool update ();\n\n    bool is_package (const std::string& name) const;\n\n    //--------\n\n    std::string m_dir_name;\n    std::string m_abs_dir_name;\n    bool m_is_relative;\n    sys::file_time m_dir_mtime;\n    sys::file_time m_dir_time_last_checked;\n    string_vector m_all_files;\n    string_vector m_fcn_files;\n    fcn_file_map_type m_private_file_map;\n    method_file_map_type m_method_file_map;\n    package_dir_map_type m_package_dir_map;\n\n  private:\n\n    void initialize ();\n\n    void get_file_list (const std::string& d);\n\n    void get_private_file_map (const std::string& d);\n\n    void get_method_file_map (const std::string& d,\n                              const std::string& class_name);\n\n    void get_package_dir (const std::string& d,\n                          const std::string& package_name);\n\n    friend fcn_file_map_type get_fcn_files (const std::string& d);\n  };  // end class dir_info\n\n  class file_info\n  {\n  public:\n\n    file_info () = delete;\n\n    file_info (const std::string& d, int t) : m_dir_name (d), m_types (t) { }\n\n    file_info (const file_info& fi)\n      : m_dir_name (fi.m_dir_name), m_types (fi.m_types) { }\n\n    ~file_info () = default;\n\n    file_info& operator = (const file_info& fi)\n    {\n      if (&fi != this)\n        {\n          m_dir_name = fi.m_dir_name;\n          m_types = fi.m_types;\n        }\n\n      return *this;\n    }\n\n    //--------\n\n    std::string m_dir_name;\n    int m_types;\n  };  // end class file_info\n\n  // We maintain two ways of looking at the same information.\n  //\n  // First, a list of directories and the set of \"public\" files and\n  // private files (those found in the special \"private\" subdirectory)\n  // in each directory.\n  //\n  // Second, a map from filenames (the union of all \"public\" files for all\n  // directories, but without filename extensions) to a list of\n  // corresponding information (directory name and file types).  This\n  // way, we can quickly find shadowed filenames and look up all\n  // overloaded functions (in the \"@\" directories used to implement\n  // classes).\n\n  typedef std::list<dir_info> dir_info_list_type;\n\n  typedef dir_info_list_type::const_iterator const_dir_info_list_iterator;\n  typedef dir_info_list_type::iterator dir_info_list_iterator;\n\n  typedef std::map<std::string, dir_info> abs_dir_cache_type;\n\n  typedef abs_dir_cache_type::const_iterator const_abs_dir_cache_iterator;\n  typedef abs_dir_cache_type::iterator abs_dir_cache_iterator;\n\n  typedef std::list<file_info> file_info_list_type;\n\n  typedef file_info_list_type::const_iterator const_file_info_list_iterator;\n  typedef file_info_list_type::iterator file_info_list_iterator;\n\n  // <FCN_NAME, FILE_INFO_LIST>\n  typedef std::map<std::string, file_info_list_type> fcn_map_type;\n\n  typedef fcn_map_type::const_iterator const_fcn_map_iterator;\n  typedef fcn_map_type::iterator fcn_map_iterator;\n\n  // <DIR_NAME, <FCN_NAME, TYPES>>\n  typedef std::map<std::string, dir_info::fcn_file_map_type>\n    private_fcn_map_type;\n\n  typedef private_fcn_map_type::const_iterator const_private_fcn_map_iterator;\n  typedef private_fcn_map_type::iterator private_fcn_map_iterator;\n\n  // <CLASS_NAME, <FCN_NAME, FILE_INFO_LIST>>\n  typedef std::map<std::string, fcn_map_type> method_map_type;\n\n  typedef method_map_type::const_iterator const_method_map_iterator;\n  typedef method_map_type::iterator method_map_iterator;\n\n  class package_info\n  {\n  public:\n\n    package_info (const std::string& package_name = \"\")\n      : m_package_name (package_name), m_dir_list (), m_fcn_map (),\n        m_private_fcn_map (), m_method_map ()\n    { }\n\n    package_info (const package_info& l)\n      : m_package_name (l.m_package_name), m_dir_list (l.m_dir_list),\n        m_private_fcn_map (l.m_private_fcn_map), m_method_map (l.m_method_map)\n    { }\n\n    ~package_info () = default;\n\n    package_info& operator = (const package_info& l)\n    {\n      if (&l != this)\n        {\n          m_package_name = l.m_package_name;\n          m_dir_list = l.m_dir_list;\n          m_fcn_map = l.m_fcn_map;\n          m_private_fcn_map = l.m_private_fcn_map;\n          m_method_map = l.m_method_map;\n        }\n\n      return *this;\n    }\n\n    void add (const dir_info& di, bool at_end, bool updating)\n    {\n      if (at_end)\n        m_dir_list.push_back (di.m_dir_name);\n      else\n        m_dir_list.push_front (di.m_dir_name);\n\n      add_to_fcn_map (di, at_end, updating);\n\n      add_to_private_fcn_map (di);\n\n      add_to_method_map (di, at_end);\n    }\n\n    void move (const dir_info& di, bool at_end);\n\n    void remove (const dir_info& di);\n\n    void clear ()\n    {\n      m_dir_list.clear ();\n\n      m_fcn_map.clear ();\n\n      m_private_fcn_map.clear ();\n\n      m_method_map.clear ();\n    }\n\n    void display (std::ostream& out) const;\n\n    std::string\n    find_fcn (const std::string& fcn, std::string& dir_name,\n              int type = M_FILE | OCT_FILE | MEX_FILE) const;\n\n    std::string\n    find_private_fcn (const std::string& dir, const std::string& fcn,\n                      int type = M_FILE | OCT_FILE | MEX_FILE) const;\n\n    std::string\n    find_method (const std::string& class_name, const std::string& meth,\n                 std::string& dir_name,\n                 int type = M_FILE | OCT_FILE | MEX_FILE) const;\n\n    std::list<std::string> methods (const std::string& class_name) const;\n\n    void overloads (const std::string& meth, std::list<std::string>& l) const;\n\n    string_vector fcn_names () const;\n\n  private:\n\n    void add_to_fcn_map (const dir_info& di, bool at_end, bool updating);\n\n    void add_to_private_fcn_map (const dir_info& di);\n\n    void add_to_method_map (const dir_info& di, bool at_end);\n\n    void move_fcn_map (const std::string& dir,\n                       const string_vector& fcn_files, bool at_end);\n\n    void move_method_map (const std::string& dir, bool at_end);\n\n    void remove_fcn_map (const std::string& dir,\n                         const string_vector& fcn_files);\n\n    void remove_private_fcn_map (const std::string& dir);\n\n    void remove_method_map (const std::string& dir);\n\n    bool check_file_type (std::string& fname, int type, int possible_types,\n                          const std::string& fcn, const char *who) const;\n\n    void print_types (std::ostream& os, int types) const;\n\n    void print_fcn_list (std::ostream& os,\n                         const dir_info::fcn_file_map_type& lst) const;\n\n    //--------\n\n    std::string m_package_name;\n\n    std::list<std::string> m_dir_list;\n\n    fcn_map_type m_fcn_map;\n\n    private_fcn_map_type m_private_fcn_map;\n\n    method_map_type m_method_map;\n  };  // end class package_info\n\n  // <PACKAGE_NAME, PACKAGE_INFO>\n  typedef std::map<std::string, package_info> package_map_type;\n\n  typedef package_map_type::const_iterator const_package_map_iterator;\n  typedef package_map_type::iterator package_map_iterator;\n\n  std::function<void (const std::string&)> m_add_hook;\n\n  std::function<void (const std::string&)> m_remove_hook;\n\n  void execute_pkg_add_or_del (const std::string& dir,\n                               const std::string& script_file);\n\n  const_dir_info_list_iterator find_dir_info (const std::string& dir) const;\n  dir_info_list_iterator find_dir_info (const std::string& dir);\n\n  bool contains (const std::string& dir) const;\n\n  void move (dir_info_list_iterator i, bool at_end);\n\n  void move (const dir_info& di, bool at_end, const std::string& pname = \"\");\n\n  void remove (const dir_info& di, const std::string& pname = \"\");\n\n  void add (const std::string& dir, bool at_end, bool warn);\n\n  void add (const dir_info& di, bool at_end, const std::string& pname = \"\",\n            bool updating = false);\n\n  bool is_package (const std::string& name) const;\n\n  package_info& get_package (const std::string& name)\n  {\n    if (! name.empty () && is_package (name))\n      {\n        package_map_iterator l = m_package_map.find (name);\n\n        if (l == m_package_map.end ())\n          l = m_package_map.insert (m_package_map.end (),\n                                    package_map_type::value_type (name, package_info (name)));\n\n        return l->second;\n      }\n\n    return m_top_level_package;\n  }\n\n  string_vector get_file_list (const dir_info::fcn_file_map_type& lst) const;\n\n  std::string find_private_file (const std::string& fname) const;\n\n  friend dir_info::fcn_file_map_type get_fcn_files (const std::string& d);\n\n  //--------\n\n  static std::string s_sys_path;\n\n  static abs_dir_cache_type s_abs_dir_cache;\n\n  interpreter& m_interpreter;\n\n  package_map_type m_package_map;\n\n  package_info m_top_level_package;\n\n  dir_info_list_type m_dir_info_list;\n\n  std::set<std::string> m_init_dirs;\n\n  std::string m_command_line_path;\n\n};  // end class load_path\n\nextern std::string\ngenpath (const std::string& dir, const string_vector& skip = \"private\");\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/load-save.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstring>\n\n#include <fstream>\n#include <iomanip>\n#include <iostream>\n#include <list>\n#include <sstream>\n#include <string>\n\n#include \"byte-swap.h\"\n#include \"dMatrix.h\"\n#include \"data-conv.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"glob-match.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sysdep.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n#include \"str-vec.h\"\n#include \"strftime-wrapper.h\"\n\n#include \"Cell.h\"\n#include \"cmd-edit.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"load-path.h\"\n#include \"load-save.h\"\n#include \"oct-hdf5.h\"\n#include \"ovl.h\"\n#include \"oct-map.h\"\n#include \"ov-cell.h\"\n#include \"pager.h\"\n#include \"syminfo.h\"\n#include \"sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"version.h\"\n\n#include \"ls-hdf5.h\"\n#include \"ls-mat-ascii.h\"\n#include \"ls-mat4.h\"\n#include \"ls-mat5.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-oct-binary.h\"\n#include \"ls-mat-subsys.h\"\n\n// Remove gnulib definitions, if any.\n#if defined (close)\n#  undef close\n#endif\n#if defined (open)\n#  undef open\n#endif\n\n#if defined (HAVE_ZLIB)\n#  include \"gzfstream.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_NORETURN static\nvoid\nerr_file_open (const std::string& fcn, const std::string& file)\n{\n  if (fcn == \"load\")\n    error (\"%s: unable to open input file '%s'\", fcn.c_str (), file.c_str ());\n  else if (fcn == \"save\")\n    error (\"%s: unable to open output file '%s'\", fcn.c_str (), file.c_str ());\n  else\n    error (\"%s: unable to open file '%s'\", fcn.c_str (), file.c_str ());\n}\n\n// Return TRUE if NAME matches one of the given globbing PATTERNS.\n\nstatic bool\nmatches_patterns (const string_vector& patterns, int pat_idx,\n                  int num_pat, const std::string& name)\n{\n  for (int i = pat_idx; i < num_pat; i++)\n    {\n      symbol_match pattern (patterns[i]);\n\n      if (pattern.match (name))\n        return true;\n    }\n\n  return false;\n}\n\nstatic int\nread_binary_file_header (std::istream& is, bool& swap,\n                         mach_info::float_format& flt_fmt,\n                         bool quiet = false)\n{\n  const int magic_len = 10;\n  char magic[magic_len+1];\n  is.read (magic, magic_len);\n  magic[magic_len] = '\\0';\n\n  if (strncmp (magic, \"Octave-1-L\", magic_len) == 0)\n    swap = mach_info::words_big_endian ();\n  else if (strncmp (magic, \"Octave-1-B\", magic_len) == 0)\n    swap = ! mach_info::words_big_endian ();\n  else\n    {\n      if (! quiet)\n        error (\"load: unable to read binary file\");\n\n      return -1;\n    }\n\n  char tmp = 0;\n  is.read (&tmp, 1);\n\n  flt_fmt = mopt_digit_to_float_format (tmp);\n\n  if (flt_fmt == mach_info::flt_fmt_unknown)\n    {\n      if (! quiet)\n        error (\"load: unrecognized binary format!\");\n\n      return -1;\n    }\n\n  return 0;\n}\n\n#if defined (HAVE_ZLIB)\nstatic bool\ncheck_gzip_magic (const std::string& fname)\n{\n  bool retval = false;\n\n  std::ifstream file = sys::ifstream (fname.c_str (),\n                                      std::ios::in | std::ios::binary);\n\n  unsigned char magic[2];\n  if (file.read (reinterpret_cast<char *> (&magic[0]), 2)\n      && magic[0] == 0x1f && magic[1] == 0x8b)\n    retval = true;\n\n  file.close ();\n\n  return retval;\n}\n#endif\n\nstatic std::string\nfind_file_to_load (const std::string& name, const std::string& orig_name)\n{\n  std::string fname = find_data_file_in_load_path (\"load\", name, true);\n\n  std::size_t dot_pos = fname.rfind ('.');\n  std::size_t sep_pos = fname.find_last_of (sys::file_ops::dir_sep_chars ());\n\n  if (dot_pos == std::string::npos\n      || (sep_pos != std::string::npos && dot_pos < sep_pos))\n    {\n      // Either no '.' in name or no '.' appears after last directory\n      // separator.\n\n      if (! (sys::file_exists (fname, false)))\n        fname = find_file_to_load (fname + \".mat\", orig_name);\n    }\n  else\n    {\n      if (! (sys::file_exists (fname, false)))\n        {\n          fname = \"\";\n\n          error (\"load: unable to find file %s\", orig_name.c_str ());\n        }\n    }\n\n  return fname;\n}\n\n// Return TRUE if PATTERN has any special globbing chars in it.\n\nstatic bool\nglob_pattern_p (const std::string& pattern)\n{\n  int open = 0;\n\n  int len = pattern.length ();\n\n  for (int i = 0; i < len; i++)\n    {\n      char c = pattern[i];\n\n      switch (c)\n        {\n        case '?':\n        case '*':\n          return true;\n\n        case '[':       // Only accept an open brace if there is a close\n          open++;       // brace to match it.  Bracket expressions must be\n          continue;     // complete, according to Posix.2\n\n        case ']':\n          if (open)\n            return true;\n          continue;\n\n        case '\\\\':\n          if (i == len - 1)\n            return false;\n          continue;\n\n        default:\n          continue;\n        }\n    }\n\n  return false;\n}\n\nload_save_system::load_save_system (interpreter& interp)\n  : m_interpreter (interp),\n    m_crash_dumps_octave_core (true),\n    m_octave_core_file_limit (-1.0),\n    m_octave_core_file_name (\"octave-workspace\"),\n    m_save_default_options (\"-text\"),\n    m_octave_core_file_options (\"-binary\"),\n    m_save_header_format_string (init_save_header_format ())\n{\n#if defined (HAVE_HDF5)\n  H5dont_atexit ();\n#endif\n}\n\nload_save_system::~load_save_system ()\n{\n#if defined (HAVE_HDF5)\n  H5close ();\n#endif\n}\n\noctave_value\nload_save_system::crash_dumps_octave_core (const octave_value_list& args,\n    int nargout)\n{\n  return set_internal_variable (m_crash_dumps_octave_core, args, nargout,\n                                \"crash_dumps_octave_core\");\n}\n\noctave_value\nload_save_system::octave_core_file_limit (const octave_value_list& args,\n    int nargout)\n{\n  return set_internal_variable (m_octave_core_file_limit, args, nargout,\n                                \"octave_core_file_limit\");\n}\n\noctave_value\nload_save_system::octave_core_file_name (const octave_value_list& args,\n    int nargout)\n{\n  return set_internal_variable (m_octave_core_file_name, args, nargout,\n                                \"octave_core_file_name\", false);\n}\n\noctave_value\nload_save_system::save_default_options (const octave_value_list& args,\n                                        int nargout)\n{\n  return set_internal_variable (m_save_default_options, args, nargout,\n                                \"save_default_options\", false);\n}\n\noctave_value\nload_save_system::octave_core_file_options (const octave_value_list& args,\n    int nargout)\n{\n  return set_internal_variable (m_octave_core_file_options, args, nargout,\n                                \"octave_core_file_options\", false);\n}\n\noctave_value\nload_save_system::save_header_format_string (const octave_value_list& args,\n    int nargout)\n{\n  return set_internal_variable (m_save_header_format_string, args, nargout,\n                                \"save_header_format_string\");\n}\n\nload_save_format\nload_save_system::get_file_format (const std::string& fname,\n                                   const std::string& orig_fname,\n                                   bool& use_zlib, bool quiet)\n{\n  load_save_format retval = UNKNOWN;\n\n#if defined (HAVE_HDF5_UTF8)\n  std::string ascii_fname = fname;\n#else\n  std::string ascii_fname = sys::get_ASCII_filename (fname);\n#endif\n\n#if defined (HAVE_HDF5)\n  // check this before we open the file\n  if (H5Fis_hdf5 (ascii_fname.c_str ()) > 0)\n    return HDF5;\n#endif\n\n#if defined (HAVE_ZLIB)\n  use_zlib = check_gzip_magic (fname);\n#else\n  use_zlib = false;\n#endif\n\n  if (! use_zlib)\n    {\n      std::ifstream file = sys::ifstream (fname.c_str (),\n                                          std::ios::in | std::ios::binary);\n      if (file)\n        {\n          retval = get_file_format (file, orig_fname);\n          file.close ();\n        }\n      else if (! quiet)\n        err_file_open (\"load\", orig_fname);\n    }\n#if defined (HAVE_ZLIB)\n  else\n    {\n      gzifstream gzfile (fname.c_str (), std::ios::in | std::ios::binary);\n      if (gzfile)\n        {\n          retval = get_file_format (gzfile, orig_fname);\n          gzfile.close ();\n        }\n      else if (! quiet)\n        err_file_open (\"load\", orig_fname);\n    }\n#endif\n\n  return retval;\n}\n\noctave_value\nload_save_system::load_vars (std::istream& stream,\n                             const std::string& orig_fname,\n                             const load_save_format& fmt,\n                             mach_info::float_format flt_fmt,\n                             bool list_only, bool swap, bool verbose,\n                             const string_vector& argv, int argv_idx,\n                             int argc, int nargout)\n{\n  octave_value retval;\n\n  octave_scalar_map retstruct;\n\n  std::ostringstream output_buf;\n  std::list<std::string> symbol_names;\n\n  octave_idx_type count = 0;\n\n  for (;;)\n    {\n      bool global = false;\n      octave_value tc;\n\n      std::string name;\n      std::string doc;\n\n      switch (fmt.type ())\n        {\n        case TEXT:\n          name = read_text_data (stream, orig_fname, global, tc, count);\n          break;\n\n        case BINARY:\n          name = read_binary_data (stream, swap, flt_fmt, orig_fname,\n                                   global, tc, doc);\n          break;\n\n        case MAT_ASCII:\n          name = read_mat_ascii_data (stream, orig_fname, tc);\n          break;\n\n        case MAT_BINARY:\n          name = read_mat_binary_data (stream, orig_fname, tc);\n          break;\n\n#if defined (HAVE_HDF5)\n        case HDF5:\n          name = read_hdf5_data (stream, orig_fname, global, tc, doc,\n                                 argv, argv_idx, argc);\n          break;\n#endif\n\n        case MAT5_BINARY:\n        case MAT7_BINARY:\n          name = read_mat5_binary_element (stream, orig_fname, swap,\n                                           global, tc);\n          break;\n\n        default:\n          err_unrecognized_data_fmt (\"load\");\n          break;\n        }\n\n      if (stream.eof () || name.empty ())\n        break;\n      else\n        {\n          if (! tc.is_defined ())\n            error (\"load: unable to load variable '%s'\", name.c_str ());\n\n          if (fmt.type () == MAT_ASCII && argv_idx < argc)\n            warning (\"load: loaded ASCII file '%s' -- ignoring extra args\",\n                     orig_fname.c_str ());\n\n          if (fmt.type () == MAT_ASCII\n              || argv_idx == argc\n              || matches_patterns (argv, argv_idx, argc, name))\n            {\n              count++;\n              if (list_only)\n                {\n                  if (verbose)\n                    {\n                      if (count == 1)\n                        output_buf\n                            << \"type               rows   cols   name\\n\"\n                            << \"====               ====   ====   ====\\n\";\n\n                      output_buf\n                          << std::setiosflags (std::ios::left)\n                          << std::setw (16) << tc.type_name ().c_str ()\n                          << std::setiosflags (std::ios::right)\n                          << std::setw (7) << tc.rows ()\n                          << std::setw (7) << tc.columns ()\n                          << \"   \" << name << \"\\n\";\n                    }\n                  else\n                    symbol_names.push_back (name);\n                }\n              else\n                {\n                  if (nargout == 1)\n                    {\n                      if (fmt.type () == MAT_ASCII)\n                        retval = tc;\n                      else\n                        retstruct.assign (name, tc);\n                    }\n                  else\n                    install_loaded_variable (name, tc, global, doc);\n                }\n            }\n\n          // Only attempt to read one item from a headless text file.\n\n          if (fmt.type () == MAT_ASCII)\n            break;\n        }\n    }\n\n  if (list_only && count)\n    {\n      if (verbose)\n        {\n          std::string msg = output_buf.str ();\n\n          if (nargout > 0)\n            retval = msg;\n          else\n            octave_stdout << msg;\n        }\n      else\n        {\n          if (nargout  > 0)\n            retval = Cell (string_vector (symbol_names));\n          else\n            {\n              string_vector names (symbol_names);\n              const int width = command_editor::terminal_cols ();\n\n              names.list_in_columns (octave_stdout, width);\n\n              octave_stdout << \"\\n\";\n            }\n        }\n    }\n  else if (retstruct.nfields () != 0)\n    retval = retstruct;\n\n  return retval;\n}\n\nstring_vector\nload_save_system::parse_save_options (const string_vector& argv,\n                                      load_save_format& fmt, bool& append,\n                                      bool& save_as_floats, bool& use_zlib)\n{\n#if ! defined (HAVE_ZLIB)\n  octave_unused_parameter (use_zlib);\n#endif\n\n  string_vector retval;\n  int argc = argv.numel ();\n\n  bool do_double = false;\n  bool do_tabs = false;\n\n  for (int i = 0; i < argc; i++)\n    {\n      if (argv[i] == \"-append\")\n        {\n          append = true;\n        }\n      else if (argv[i] == \"-ascii\" || argv[i] == \"-a\")\n        {\n          fmt.set_type (MAT_ASCII);\n        }\n      else if (argv[i] == \"-double\")\n        {\n          do_double = true;\n        }\n      else if (argv[i] == \"-tabs\")\n        {\n          do_tabs = true;\n        }\n      else if (argv[i] == \"-text\" || argv[i] == \"-t\")\n        {\n          fmt.set_type (TEXT);\n        }\n      else if (argv[i] == \"-binary\" || argv[i] == \"-b\")\n        {\n          fmt.set_type (BINARY);\n        }\n      else if (argv[i] == \"-hdf5\" || argv[i] == \"-h\")\n        {\n#if defined (HAVE_HDF5)\n          fmt.set_type (HDF5);\n#else\n          err_disabled_feature (\"save\", \"HDF5\");\n#endif\n        }\n      else if (argv[i] == \"-v7.3\" || argv[i] == \"-V7.3\" || argv[i] == \"-7.3\")\n        {\n          error (\"save: Matlab file format -v7.3 is not yet implemented\");\n        }\n#if defined (HAVE_ZLIB)\n      else if (argv[i] == \"-v7\" || argv[i] == \"-V7\" || argv[i] == \"-7\"\n               || argv[i] == \"-mat7-binary\")\n        {\n          fmt.set_type (MAT7_BINARY);\n        }\n#endif\n      else if (argv[i] == \"-mat\" || argv[i] == \"-m\"\n               || argv[i] == \"-v6\" || argv[i] == \"-V6\" || argv[i] == \"-6\"\n               || argv[i] == \"-mat-binary\")\n        {\n          fmt.set_type (MAT5_BINARY);\n        }\n      else if (argv[i] == \"-v4\" || argv[i] == \"-V4\" || argv[i] == \"-4\"\n               || argv[i] == \"-mat4-binary\")\n        {\n          fmt.set_type (MAT_BINARY);\n        }\n      else if (argv[i] == \"-float-binary\" || argv[i] == \"-f\")\n        {\n          fmt.set_type (BINARY);\n          save_as_floats = true;\n        }\n      else if (argv[i] == \"-float-hdf5\")\n        {\n#if defined (HAVE_HDF5)\n          fmt.set_type (HDF5);\n          save_as_floats = true;\n#else\n          err_disabled_feature (\"save\", \"HDF5\");\n#endif\n        }\n#if defined (HAVE_ZLIB)\n      else if (argv[i] == \"-zip\" || argv[i] == \"-z\")\n        {\n          use_zlib = true;\n        }\n#endif\n      else if (argv[i] == \"-struct\")\n        {\n          retval.append (argv[i]);\n        }\n      else if (argv[i][0] == '-' && argv[i] != \"-\")\n        {\n          error (\"save: Unrecognized option '%s'\", argv[i].c_str ());\n        }\n      else\n        retval.append (argv[i]);\n    }\n\n  if (do_double)\n    {\n      if (fmt.type () == MAT_ASCII)\n        fmt.set_option (MAT_ASCII_LONG);\n      else\n        warning (R\"(save: \"-double\" option only has an effect with \"-ascii\")\");\n    }\n\n  if (do_tabs)\n    {\n      if (fmt.type () == MAT_ASCII)\n        fmt.set_option (MAT_ASCII_TABS);\n      else\n        warning (R\"(save: \"-tabs\" option only has an effect with \"-ascii\")\");\n    }\n\n  if (append && use_zlib\n      && (fmt.type () != TEXT && fmt.type () != MAT_ASCII))\n    error (\"save: -append and -zip options can only be used together with a text format (-text or -ascii)\");\n\n  return retval;\n}\n\nstring_vector\nload_save_system::parse_save_options (const std::string& arg,\n                                      load_save_format& fmt,\n                                      bool& append, bool& save_as_floats,\n                                      bool& use_zlib)\n{\n  std::istringstream is (arg);\n  std::string str;\n  string_vector argv;\n\n  while (! is.eof ())\n    {\n      is >> str;\n      argv.append (str);\n    }\n\n  return parse_save_options (argv, fmt, append, save_as_floats, use_zlib);\n}\n\nvoid\nload_save_system::save_vars (const string_vector& argv, int argv_idx,\n                             int argc, std::ostream& os,\n                             const load_save_format& fmt,\n                             bool save_as_floats,\n                             bool write_header_info)\n{\n  if (write_header_info)\n    write_header (os, fmt);\n\n  create_subsystem_handler ();  // for MAT file formats\n\n  octave::unwind_action\n  clear_obj_cache ([this] ()\n    {\n      clear_mcos_object_cache ();\n      clear_subsystem_handler ();\n    });\n\n  if (argv_idx == argc)\n    {\n      save_vars (os, \"*\", fmt, save_as_floats);\n    }\n  else if (argv[argv_idx] == \"-struct\")\n    {\n      if (++argv_idx >= argc)\n        error (\"save: missing struct name\");\n\n      std::string struct_name = argv[argv_idx];\n\n      if (! m_interpreter.is_variable (struct_name))\n        error (\"save: no such variable: '%s'\", struct_name.c_str ());\n\n      octave_value struct_var = m_interpreter.varval (struct_name);\n\n      if (! struct_var.isstruct () || struct_var.numel () != 1)\n        error (\"save: '%s' is not a scalar structure\", struct_name.c_str ());\n\n      octave_scalar_map struct_var_map = struct_var.scalar_map_value ();\n\n      ++argv_idx;\n\n      if (argv_idx < argc)\n        {\n          for (int i = argv_idx; i < argc; i++)\n            {\n              if (! save_fields (os, struct_var_map, argv[i], fmt,\n                                 save_as_floats))\n                {\n                  warning (\"save: no such field '%s.%s'\",\n                           struct_name.c_str (), argv[i].c_str ());\n                }\n            }\n        }\n      else\n        save_fields (os, struct_var_map, \"*\", fmt, save_as_floats);\n    }\n  else\n    {\n      for (int i = argv_idx; i < argc; i++)\n        {\n          if (argv[i] == \"\")\n            continue;  // Skip empty vars for Matlab compatibility\n          if (! save_vars (os, argv[i], fmt, save_as_floats))\n            warning (\"save: no such variable '%s'\", argv[i].c_str ());\n        }\n    }\n\n  // write subsystem data\n  if (fmt.type() == MAT5_BINARY || fmt.type() == MAT7_BINARY)  // any other formats?\n    {\n      subsystem_handler *sh = get_subsystem_handler ();\n      sh->serialize_to_cell_array ();\n      // serialized data needs to be saved first to calculate nbytes during save\n\n      if (sh->has_serialized_data ())\n        {\n          // create new output stream for subsystem data\n          std::ostringstream subsys_stream;\n\n          const char *header;\n          if (mach_info::words_big_endian ())\n            header = \"\\x01\\x00\\x4d\\x49\\x00\\x00\\x00\\x00\";\n          else\n            header = \"\\x00\\x01\\x49\\x4d\\x00\\x00\\x00\\x00\";\n          subsys_stream.write (header, 8);\n\n          // create FileWrapper__ object to register as MAT_FILE_WORKSPACE_CLASS\n          octave::cdef_manager& cdm = octave::__get_cdef_manager__ ();\n          octave::cdef_class filewrapper_class\n            = cdm.make_class (\"FileWrapper__\", std::list<octave::cdef_class> ());\n          octave_value filewrapper_obj\n            = filewrapper_class.construct (octave_value_list (), true);\n\n          octave_scalar_map subsys_map;\n          subsys_map.assign (\"MCOS\", filewrapper_obj);\n          // TODO: include other type systems \"java\" and \"handle\"\n\n          std::string help;\n          do_save (subsys_stream, subsys_map, \"\", help, false, MAT5_BINARY,\n                   save_as_floats);\n          // don't use zlib compression on subsys_stream\n\n          // convert stream to uint8NDArray\n          // FIXME: How to optimize?\n          const std::string& stream_data = subsys_stream.str();\n          octave_idx_type data_size = stream_data.size ();\n          uint8NDArray subsys_data (dim_vector (1, data_size));\n          std::memcpy (subsys_data.rwdata(), stream_data.data(), data_size);\n\n          // save the uint8NDArray to original stream without variable name\n          octave_value subsys_value (subsys_data);\n          std::streampos subsys_offset = os.tellp ();\n          do_save (os, subsys_value, \"\", help, false, fmt, save_as_floats);\n\n          // update subsystem offset in MAT-file header\n          std::streampos current_pos = os.tellp ();\n          os.seekp (116);\n          uint64_t offset_val = static_cast<uint64_t> (subsys_offset);\n          os.write (reinterpret_cast<const char*> (&offset_val), 8);\n          os.seekp (current_pos);\n        }\n    }\n}\n\nvoid\nload_save_system::dump_octave_core ()\n{\n  if (m_crash_dumps_octave_core)\n    {\n      // FIXME: should choose better filename?\n\n      const char *fname = m_octave_core_file_name.c_str ();\n\n      message (nullptr, \"attempting to save variables to '%s'...\", fname);\n\n      load_save_format fmt (BINARY);\n\n      bool save_as_floats = false;\n\n      bool append = false;\n\n      bool use_zlib = false;\n\n      load_save_system::parse_save_options (m_octave_core_file_options,\n                                            fmt, append, save_as_floats,\n                                            use_zlib);\n\n      std::ios::openmode mode = std::ios::out;\n\n      // Matlab v7 files are always compressed\n      if (fmt.type () == MAT7_BINARY)\n        use_zlib = false;\n\n      if (fmt.type () == BINARY\n#if defined (HAVE_HDF5)\n          || fmt.type () == HDF5\n#endif\n          || fmt.type () == MAT_BINARY\n          || fmt.type () == MAT5_BINARY\n          || fmt.type () == MAT7_BINARY)\n        mode |= std::ios::binary;\n\n      mode |= append ? std::ios::ate : std::ios::trunc;\n\n#if defined (HAVE_HDF5)\n      if (fmt.type () == HDF5)\n        {\n          hdf5_ofstream file (fname, mode);\n\n          if (file.file_id >= 0)\n            {\n              dump_octave_core (file, fname, fmt, save_as_floats);\n\n              file.close ();\n            }\n          else\n            warning (\"dump_octave_core: unable to open '%s' for writing...\",\n                     fname);\n        }\n      else\n#endif\n        // don't insert any commands here!  The open brace below must\n        // go with the else above!\n        {\n#if defined (HAVE_ZLIB)\n          if (use_zlib)\n            {\n              gzofstream file (fname, mode);\n\n              if (file)\n                {\n                  dump_octave_core (file, fname, fmt, save_as_floats);\n\n                  file.close ();\n                }\n              else\n                warning (\"dump_octave_core: unable to open '%s' for writing...\",\n                         fname);\n            }\n          else\n#endif\n            {\n              std::ofstream file = sys::ofstream (fname, mode);\n\n              if (file)\n                {\n                  dump_octave_core (file, fname, fmt, save_as_floats);\n\n                  file.close ();\n                }\n              else\n                warning (\"dump_octave_core: unable to open '%s' for writing...\",\n                         fname);\n            }\n        }\n    }\n}\n\nvoid\nload_save_system::write_header (std::ostream& os,\n                                const load_save_format& fmt)\n{\n  switch (fmt.type ())\n    {\n    case BINARY:\n      {\n        os << (mach_info::words_big_endian ()\n               ? \"Octave-1-B\" : \"Octave-1-L\");\n\n        mach_info::float_format flt_fmt = mach_info::native_float_format ();\n\n        char tmp = static_cast<char> (float_format_to_mopt_digit (flt_fmt));\n\n        os.write (&tmp, 1);\n      }\n      break;\n\n    case MAT5_BINARY:\n    case MAT7_BINARY:\n      {\n        char const *versionmagic;\n        char headertext[128];\n        sys::gmtime now;\n\n        // ISO 8601 format date\n        const char *matlab_format = \"MATLAB 5.0 MAT-file, written by Octave \"\n                                    OCTAVE_VERSION \", %Y-%m-%d %T UTC\";\n        std::string comment_string = now.strftime (matlab_format);\n\n        std::size_t len = std::min (comment_string.length (),\n                                    static_cast<std::size_t> (124));\n        memset (headertext, '\\0', 124);\n        memcpy (headertext, comment_string.data (), len);\n\n        // The first pair of bytes give the version of the MAT file\n        // format.  The second pair of bytes form a magic number which\n        // signals a MAT file.  MAT file data are always written in\n        // native byte order.  The order of the bytes in the second\n        // pair indicates whether the file was written by a big- or\n        // little-endian machine.  However, the version number is\n        // written in the *opposite* byte order from everything else!\n        if (mach_info::words_big_endian ())\n          versionmagic = \"\\x01\\x00\\x4d\\x49\"; // this machine is big endian\n        else\n          versionmagic = \"\\x00\\x01\\x49\\x4d\"; // this machine is little endian\n\n        memcpy (headertext+124, versionmagic, 4);\n        os.write (headertext, 128);\n      }\n\n      break;\n\n#if defined (HAVE_HDF5)\n    case HDF5:\n#endif\n    case TEXT:\n      {\n        sys::localtime now;\n\n        std::string comment_string = now.strftime (m_save_header_format_string);\n\n        if (! comment_string.empty ())\n          {\n#if defined (HAVE_HDF5)\n            if (fmt.type () == HDF5)\n              {\n                hdf5_ofstream& hs = dynamic_cast<hdf5_ofstream&> (os);\n                H5Gset_comment (hs.file_id, \"/\", comment_string.c_str ());\n              }\n            else\n#endif\n              os << comment_string << \"\\n\";\n          }\n      }\n      break;\n\n    default:\n      break;\n    }\n}\n\n// Save variables with names matching PATTERN on stream OS in the\n// format specified by FMT.\n\nstd::size_t\nload_save_system::save_vars (std::ostream& os,\n                             const std::string& pattern,\n                             const load_save_format& fmt,\n                             bool save_as_floats)\n{\n  tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n  symbol_info_list syminfo_list = tw.glob_symbol_info (pattern);\n\n  std::size_t saved = 0;\n\n  for (const auto& syminfo : syminfo_list)\n    {\n      do_save (os, syminfo, fmt, save_as_floats);\n\n      saved++;\n    }\n\n  return saved;\n}\n\nvoid\nload_save_system::do_save (std::ostream& os, const octave_value& tc,\n                           const std::string& name,\n                           const std::string& help,\n                           bool global, const load_save_format& fmt,\n                           bool save_as_floats)\n{\n  switch (fmt.type ())\n    {\n    case TEXT:\n      save_text_data (os, tc, name, global, 0);\n      break;\n\n    case BINARY:\n      save_binary_data (os, tc, name, help, global, save_as_floats);\n      break;\n\n    case MAT_ASCII:\n      if (! save_mat_ascii_data (os, tc,\n                                 fmt.options () & MAT_ASCII_LONG ? 16 : 8,\n                                 fmt.options () & MAT_ASCII_TABS))\n        warning (\"save: unable to save %s in ASCII format\", name.c_str ());\n      break;\n\n    case MAT_BINARY:\n      save_mat_binary_data (os, tc, name);\n      break;\n\n#if defined (HAVE_HDF5)\n    case HDF5:\n      save_hdf5_data (os, tc, name, help, global, save_as_floats);\n      break;\n#endif\n\n    case MAT5_BINARY:\n      save_mat5_binary_element (os, tc, name, global, false, save_as_floats);\n      break;\n\n    case MAT7_BINARY:\n      save_mat5_binary_element (os, tc, name, global, true, save_as_floats);\n      break;\n\n    default:\n      err_unrecognized_data_fmt (\"save\");\n      break;\n    }\n}\n\n// Save the info from SR on stream OS in the format specified by FMT.\n\nvoid\nload_save_system::do_save (std::ostream& os,\n                           const symbol_info& syminfo,\n                           const load_save_format& fmt,\n                           bool save_as_floats)\n{\n  octave_value val = syminfo.value ();\n\n  if (val.is_defined ())\n    {\n      std::string name = syminfo.name ();\n      std::string help;\n      bool global = syminfo.is_global ();\n\n      do_save (os, val, name, help, global, fmt, save_as_floats);\n    }\n}\n\n// save fields of a scalar structure STR matching PATTERN on stream OS\n// in the format specified by FMT.\n\nstd::size_t\nload_save_system::save_fields (std::ostream& os,\n                               const octave_scalar_map& m,\n                               const std::string& pattern,\n                               const load_save_format& fmt,\n                               bool save_as_floats)\n{\n  symbol_match pat (pattern);\n\n  std::size_t saved = 0;\n\n  for (auto it = m.begin (); it != m.end (); it++)\n    {\n      std::string empty_str;\n\n      if (pat.match (m.key (it)))\n        {\n          do_save (os, m.contents (it), m.key (it), empty_str,\n                   0, fmt, save_as_floats);\n\n          saved++;\n        }\n    }\n\n  return saved;\n}\n\nvoid\nload_save_system::dump_octave_core (std::ostream& os,\n                                    const char *fname,\n                                    const load_save_format& fmt,\n                                    bool save_as_floats)\n{\n  write_header (os, fmt);\n\n  tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n  symbol_info_list syminfo_list = tw.top_scope_symbol_info ();\n\n  double save_mem_size = 0;\n\n  for (const auto& syminfo : syminfo_list)\n    {\n      octave_value val = syminfo.value ();\n\n      std::string name = syminfo.name ();\n      std::string help;\n      bool global = syminfo.is_global ();\n\n      double val_size = val.byte_size () / 1024;\n\n      // FIXME: maybe we should try to throw out the largest first...\n\n      if (m_octave_core_file_limit < 0\n          || save_mem_size + val_size < m_octave_core_file_limit)\n        {\n          save_mem_size += val_size;\n\n          do_save (os, val, name, help, global, fmt, save_as_floats);\n        }\n    }\n\n  message (nullptr, \"save to '%s' complete\", fname);\n}\n\n// Install a variable with name NAME and the value VAL in the\n// symbol table.  If GLOBAL is TRUE, make the variable global.\n\nvoid\nload_save_system::install_loaded_variable (const std::string& name,\n    const octave_value& val,\n    bool global,\n    const std::string& /*doc*/)\n{\n  m_interpreter.install_variable (name, val, global);\n}\n\nstd::string\nload_save_system::init_save_header_format ()\n{\n  return \"# Created by Octave \" OCTAVE_VERSION \", %a %b %d %H:%M:%S %Y %Z\";\n}\n\nload_save_format\nload_save_system::get_file_format (std::istream& file,\n                                   const std::string& filename)\n{\n  load_save_format retval = load_save_system::UNKNOWN;\n\n  mach_info::float_format flt_fmt\n    = mach_info::flt_fmt_unknown;\n\n  bool swap = false;\n\n  if (read_binary_file_header (file, swap, flt_fmt, true) == 0)\n    retval = BINARY;\n  else\n    {\n      file.clear ();\n      file.seekg (0, std::ios::beg);\n\n      int32_t mopt, nr, nc, imag, len;\n\n      int err = read_mat_file_header (file, swap, mopt, nr, nc, imag, len,\n                                      true);\n\n      if (! err)\n        retval = MAT_BINARY;\n      else\n        {\n          file.clear ();\n          file.seekg (0, std::ios::beg);\n\n          err = read_mat5_binary_file_header (file, swap, true, filename);\n\n          if (! err)\n            {\n              file.clear ();\n              file.seekg (0, std::ios::beg);\n              retval = MAT5_BINARY;\n            }\n          else\n            {\n              file.clear ();\n              file.seekg (0, std::ios::beg);\n\n              std::string name_val = extract_keyword (file, \"name\");\n              std::string type_val = extract_keyword (file, \"type\");\n\n              if (name_val.empty () != true && type_val.empty () != true)\n                retval = TEXT;\n              else\n                {\n                  file.clear ();\n                  file.seekg (0, std::ios::beg);\n\n                  // FIXME: looks_like_mat_ascii_file does not check\n                  // to see whether the file contains numbers.  It\n                  // just skips comments and checks for the same\n                  // number of words on each line.  We may need a\n                  // better check here.  The best way to do that might\n                  // be just to try to read the file and see if it\n                  // works.\n\n                  if (looks_like_mat_ascii_file (file, filename))\n                    retval = MAT_ASCII;\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\noctave_value_list\nload_save_system::load (const octave_value_list& args, int nargout)\n{\n  octave_value_list retval;\n\n  int argc = args.length () + 1;\n\n  string_vector argv = args.make_argv (\"load\");\n\n  int i = 1;\n  std::string orig_fname = \"\";\n\n  // Function called with Matlab-style [\"filename\", options] syntax\n  if (argc > 1 && ! argv[1].empty () && argv[1].at (0) != '-')\n    {\n      orig_fname = argv[1];\n      i++;\n    }\n\n  // It isn't necessary to have the default load format stored in a\n  // user preference variable since we can determine the type of file\n  // as we are reading.\n\n  load_save_format format = UNKNOWN;\n\n  bool list_only = false;\n  bool verbose = false;\n\n  create_subsystem_handler ();  // for MAT file formats\n\n  octave::unwind_action\n  clear_obj_cache ([this] ()\n    {\n      clear_mcos_object_cache ();\n      clear_subsystem_handler ();\n    });\n\n  for (; i < argc; i++)\n    {\n      if (argv[i] == \"-text\" || argv[i] == \"-t\")\n        {\n          format = TEXT;\n        }\n      else if (argv[i] == \"-binary\" || argv[i] == \"-b\")\n        {\n          format = BINARY;\n        }\n      else if (argv[i] == \"-hdf5\" || argv[i] == \"-h\")\n        {\n#if defined (HAVE_HDF5)\n          format = HDF5;\n#else\n          err_disabled_feature (\"load\", \"HDF5\");\n#endif\n        }\n      else if (argv[i] == \"-ascii\" || argv[i] == \"-a\")\n        {\n          format = MAT_ASCII;\n        }\n      else if (argv[i] == \"-v7.3\" || argv[i] == \"-V7.3\" || argv[i] == \"-7.3\")\n        {\n          error (\"load: Matlab file format -v7.3 is not yet implemented\");\n        }\n      else if (argv[i] == \"-v7\" || argv[i] == \"-V7\" || argv[i] == \"-7\"\n               || argv[i] == \"-mat7-binary\")\n        {\n          format = MAT7_BINARY;\n        }\n      else if (argv[i] == \"-mat\" || argv[i] == \"-m\"\n               || argv[i] == \"-v6\" || argv[i] == \"-V6\" || argv[i] == \"-6\"\n               || argv[i] == \"-mat-binary\")\n        {\n          format = MAT5_BINARY;\n        }\n      else if (argv[i] == \"-v4\" || argv[i] == \"-V4\" || argv[i] == \"-4\"\n               || argv[i] == \"-mat4-binary\")\n        {\n          format = MAT_BINARY;\n        }\n      else if (argv[i] == \"-list\" || argv[i] == \"-l\")\n        {\n          list_only = true;\n        }\n      else if (argv[i] == \"-verbose\" || argv[i] == \"-v\")\n        {\n          verbose = true;\n        }\n      else\n        break;\n    }\n\n  if (orig_fname == \"\")\n    {\n      if (i == argc)\n        print_usage ();\n\n      orig_fname = argv[i];\n    }\n  else\n    i--;\n\n  mach_info::float_format flt_fmt = mach_info::flt_fmt_unknown;\n\n  bool swap = false;\n\n  if (orig_fname == \"-\")\n    {\n      i++;\n\n#if defined (HAVE_HDF5)\n      if (format.type () == HDF5)\n        error (\"load: cannot read HDF5 format from stdin\");\n      else\n#endif\n        if (format.type () != UNKNOWN)\n          {\n            // FIXME: if we have already seen EOF on a previous call,\n            // how do we fix up the state of std::cin so that we can get\n            // additional input?  I'm afraid that we can't fix this\n            // using std::cin only.\n\n            retval = load_vars (std::cin, orig_fname, format, flt_fmt,\n                                list_only, swap, verbose, argv, i,\n                                argc, nargout);\n          }\n        else\n          error (\"load: must specify file format if reading from stdin\");\n    }\n  else\n    {\n      std::string fname = sys::file_ops::tilde_expand (orig_fname);\n\n      fname = find_file_to_load (fname, orig_fname);\n\n      bool use_zlib = false;\n\n      if (format.type () == UNKNOWN)\n        format = get_file_format (fname, orig_fname, use_zlib);\n\n#if defined (HAVE_HDF5)\n      if (format.type () == HDF5)\n        {\n          i++;\n\n          hdf5_ifstream hdf5_file (fname.c_str ());\n\n          if (hdf5_file.file_id < 0)\n            err_file_open (\"load\", orig_fname);\n\n          retval = load_vars (hdf5_file, orig_fname, format, flt_fmt,\n                              list_only, swap, verbose, argv, i,\n                              argc, nargout);\n\n          hdf5_file.close ();\n        }\n      else\n#endif\n        // don't insert any statements here; the \"else\" above has to\n        // go with the \"if\" below!!!!!\n        if (format.type () != UNKNOWN)\n          {\n            i++;\n\n            // Always open in binary mode and handle various\n            // line-endings explicitly.\n            std::ios::openmode mode = std::ios::in | std::ios::binary;\n\n#if defined (HAVE_ZLIB)\n            if (use_zlib)\n              {\n                gzifstream file (fname.c_str (), mode);\n\n                if (! file)\n                  err_file_open (\"load\", orig_fname);\n\n                if (format.type () == BINARY)\n                  {\n                    if (read_binary_file_header (file, swap, flt_fmt) < 0)\n                      {\n                        if (file) file.close ();\n                        return retval;\n                      }\n                  }\n                else if (format.type () == MAT5_BINARY\n                         || format.type () == MAT7_BINARY)\n                  {\n                    if (read_mat5_binary_file_header (file, swap, false,\n                                                      orig_fname) < 0)\n                      {\n                        if (file) file.close ();\n                        return retval;\n                      }\n                  }\n\n                retval = load_vars (file, orig_fname, format, flt_fmt,\n                                    list_only, swap, verbose, argv, i,\n                                    argc, nargout);\n\n                file.close ();\n              }\n            else\n#endif\n              {\n                std::ifstream file = sys::ifstream (fname.c_str (), mode);\n\n                if (! file)\n                  error (\"load: unable to open input file '%s'\",\n                         orig_fname.c_str ());\n\n                if (format.type () == BINARY)\n                  {\n                    if (read_binary_file_header (file, swap, flt_fmt) < 0)\n                      {\n                        if (file) file.close ();\n                        return retval;\n                      }\n                  }\n                else if (format.type () == MAT5_BINARY\n                         || format.type () == MAT7_BINARY)\n                  {\n                    if (read_mat5_binary_file_header (file, swap, false,\n                                                      orig_fname) < 0)\n                      {\n                        if (file) file.close ();\n                        return retval;\n                      }\n                  }\n\n                retval = load_vars (file, orig_fname, format, flt_fmt,\n                                    list_only, swap, verbose, argv, i,\n                                    argc, nargout);\n\n                file.close ();\n              }\n          }\n        else\n          error (\"load: unable to determine file format of '%s'\",\n                 orig_fname.c_str ());\n\n    }\n\n  return retval;\n}\n\noctave_value_list\nload_save_system::save (const octave_value_list& args, int nargout)\n{\n  // Here is where we would get the default save format if it were\n  // stored in a user preference variable.\n  load_save_format format = TEXT;\n  bool save_as_floats = false;\n  bool append = false;\n  bool use_zlib = false;\n\n\n  // get default options\n  parse_save_options (save_default_options (), format, append,\n                      save_as_floats, use_zlib);\n\n  // override from command line\n  string_vector argv = args.make_argv ();\n\n  argv = parse_save_options (argv, format, append, save_as_floats, use_zlib);\n\n  int argc = argv.numel ();\n  int i = 0;\n\n  if (i == argc)\n    print_usage ();\n\n  if (save_as_floats && format.type () == TEXT)\n    error (\"save: cannot specify both -text and -float-binary\");\n\n  octave_value_list retval;\n\n  if (argv[i] == \"-\")\n    {\n      i++;\n\n#if defined (HAVE_HDF5)\n      if (format.type () == HDF5)\n        error (\"save: cannot write HDF5 format to stdout\");\n      else\n#endif\n        // don't insert any commands here!  the brace below must go\n        // with the \"else\" above!\n        {\n          if (append)\n            warning (\"save: ignoring -append option for output to stdout\");\n\n          if (nargout == 0)\n            save_vars (argv, i, argc, octave_stdout, format,\n                       save_as_floats, true);\n          else\n            {\n              std::ostringstream output_buf;\n              save_vars (argv, i, argc, output_buf, format,\n                         save_as_floats, true);\n              retval = octave_value (output_buf.str());\n            }\n        }\n    }\n\n  // Guard against things like 'save a*', which are probably mistakes...\n\n  else if (i == argc - 1 && glob_pattern_p (argv[i]))\n    print_usage ();\n  else\n    {\n      // For non-append mode, we make a new temporary filename, write to that\n      // instead of the file specified, then rename it at the end.\n      // That way, if something goes wrong during the save like OOM,\n      // we won't overwrite already-saved data in a file.\n      // See bug #63803 for context.\n      // In append mode, this kind of guard is counterproductive so we write\n      // directly to the specified file.\n\n      std::string desiredname = sys::file_ops::tilde_expand (argv[i]);\n      std::string fname = desiredname + (append ? \"\" : \".saving_in_progress\");\n\n      i++;\n\n      // Matlab v7 files are always compressed\n      if (format.type () == MAT7_BINARY)\n        use_zlib = false;\n\n      // Matlab v6 and v4 files are never compressed\n      if (use_zlib && (format.type () == MAT5_BINARY\n                       || format.type () == MAT_BINARY))\n        {\n          use_zlib = false;\n          warning (\"save: MATLAB compatible formats '-v4' and '-v6' are uncompressed\");\n        }\n\n      std::ios::openmode mode\n        = (append ? (std::ios::app | std::ios::ate) : std::ios::out);\n\n      // Always open in binary mode to save line endings as is.\n      mode |= std::ios::binary;\n\n#if defined (HAVE_HDF5)\n      if (format.type () == HDF5)\n        {\n          // FIXME: It should be possible to append to HDF5 files.\n          if (append)\n            error (\"save: appending to HDF5 files is not implemented\");\n\n#  if defined (HAVE_HDF5_UTF8)\n          bool write_header_info\n            = ! (append && H5Fis_hdf5 (fname.c_str ()) > 0);\n#  else\n          std::string ascii_fname = sys::get_ASCII_filename (fname);\n\n          bool write_header_info\n            = ! (append && H5Fis_hdf5 (ascii_fname.c_str ()) > 0);\n#  endif\n\n          hdf5_ofstream hdf5_file (fname.c_str (), mode);\n\n          if (hdf5_file.file_id == -1)\n            err_file_open (\"save\", fname);\n\n          save_vars (argv, i, argc, hdf5_file, format, save_as_floats,\n                     write_header_info);\n\n          hdf5_file.close ();\n        }\n      else\n#endif\n        // don't insert any statements here!  The brace below must go\n        // with the \"else\" above!\n        {\n#if defined (HAVE_ZLIB)\n          if (use_zlib)\n            {\n              gzofstream file (fname.c_str (), mode);\n\n              if (! file)\n                err_file_open (\"save\", fname);\n\n              bool write_header_info = ! file.tellp ();\n\n              save_vars (argv, i, argc, file, format, save_as_floats,\n                         write_header_info);\n\n              file.close ();\n            }\n          else\n#endif\n            {\n              std::ofstream file = sys::ofstream (fname.c_str (), mode);\n\n              if (! file)\n                err_file_open (\"save\", fname);\n\n              bool write_header_info = ! file.tellp ();\n\n              save_vars (argv, i, argc, file, format, save_as_floats,\n                         write_header_info);\n\n              file.close ();\n            }\n        }\n\n      // If we are all the way here without Octave crashing or running\n      // out of memory etc, then we can say that writing to the\n      // temporary file was successful.  So now we try to rename it to\n      // the actual file that was specified, unless we were in append mode\n      // in which case we take no action.\n\n      if (! append)\n        {\n          std::string msg;\n          if (octave::sys::rename (fname, desiredname, msg) < 0)\n            error (\"save: unable to save to %s  %s\",\n                   desiredname.c_str (), msg.c_str ());\n        }\n    }\n\n  return retval;\n}\n\nvoid\nload_save_system::clear_mcos_object_cache ()\n{\n  m_mcos_object_load_cache.clear ();\n  m_mcos_object_save_cache.clear ();\n}\n\nvoid\nload_save_system::set_mcos_object_cache_entry (uint32_t object_id,\n                                               octave_value& obj)\n{\n  m_mcos_object_load_cache[object_id] = obj;\n}\n\noctave_value&\nload_save_system::get_mcos_object_cache_entry (uint32_t object_id)\n{\n  return m_mcos_object_load_cache[object_id];\n}\n\nbool\nload_save_system::is_mcos_object_cache_entry (uint32_t object_id)\n{\n  // FIXME: Consider replacing this with std::unordered_map<>::contains when we\n  //        allow C++20.\n  return m_mcos_object_load_cache.find (object_id)\n           !=  m_mcos_object_load_cache.end ();\n}\n\nuint32_t\nload_save_system::get_mcos_object_cache_id (const void *obj, bool& new_entry)\n{\n  // identify objects by their address in memory\n  uint32_t id = m_mcos_object_save_cache[obj];\n  if (id == 0)\n    {\n      // The object hasn't been present in the cache yet.\n      // Assign and return a new id (starting at 1).\n      id = m_mcos_object_save_cache.size ();\n      m_mcos_object_save_cache[obj] = id;\n      new_entry = true;\n    }\n  else\n    new_entry = false;\n\n  return id;\n}\n\nvoid\nload_save_system::create_subsystem_handler ()\n{\n  m_subsystem_handler = std::make_unique<subsystem_handler> ();\n}\n\nsubsystem_handler*\nload_save_system::get_subsystem_handler ()\n{\n  return m_subsystem_handler.get ();\n}\n\nvoid\nload_save_system::clear_subsystem_handler ()\n{\n  m_subsystem_handler.reset ();\n}\n\nDEFMETHOD (load, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} load file\n@deftypefnx {} {} load options file\n@deftypefnx {} {} load options file v1 v2 @dots{}\n@deftypefnx {} {S =} load (\"options\", \"file\", \"v1\", \"v2\", @dots{})\n@deftypefnx {} {} load file options\n@deftypefnx {} {} load file options v1 v2 @dots{}\n@deftypefnx {} {S =} load (\"file\", \"options\", \"v1\", \"v2\", @dots{})\nLoad the named variables @var{v1}, @var{v2}, @dots{}, from the file @var{file}.\n\nIf no variables are specified then all variables found in the file will be\nloaded.  Otherwise, full variable names or pattern syntax can be used to\nspecify the variables to save.  The format of the file is automatically\ndetected but may be overridden by supplying the appropriate option.\n\nThe @code{load} command may also be invoked using the functional form\n\n@example\nload (\"-option1\", @dots{}, \"file\", \"v1\", @dots{})\n@end example\n\n@noindent\nwhere the @var{options}, @var{file}, and variable name arguments (@var{v1},\n@dots{}) must be specified as character strings.\n\nValid options for @code{load} are listed in the following table.\n\n@table @code\n\n@item -ascii\nForce Octave to assume the file contains columns of numbers in text format\nwithout any header or other information.  Data in the file will be loaded\nas a single numeric matrix with the name of the variable derived from the\nname of the file.\n\n@item -binary\nForce Octave to assume the file is in Octave's binary format.\n\n@item -hdf5\nForce Octave to assume the file is in @sc{hdf5} format.  (@sc{hdf5} is a free,\nportable binary format developed by the National Center for Supercomputing\nApplications at the University of Illinois.)  Note that @code{load} is only\ndesigned to read @sc{hdf5} files that were created by Octave with @code{save},\nand attempts to read other @sc{hdf5} files may fail or produce unpredictable\nresults.  The @option{-hdf5} option provides a limited ability to read files\ncreated using @sc{matlab}'s @option{-v7.3} option (which saves in @sc{hdf5}\nformat) although many data types are not yet supported.  This format is only\navailable if Octave was built with a link to the @sc{hdf5} libraries.\n\n@item -text\nForce Octave to assume the file is in Octave's text format.\n\n@item  -v7.3\n@itemx -V7.3\n@itemx -7.3\nOctave does @strong{not} yet implement @sc{matlab}'s v7.3 binary data format.\nAs the v7.3 format is an @sc{hdf5} based format, the @qcode{\"-hdf5\"} option\nmay be used to attempt to open a v7.3 format file, although most non-numeric\ndata types are not yet supported.  Note that Octave @strong{can not} currently\nsave in this format.\n\n@item  -v7\n@itemx -V7\n@itemx -7\n@itemx -mat7-binary\nForce Octave to assume the file is in @sc{matlab}'s version 7 binary format.\n\n@item  -v6\n@itemx -V6\n@itemx -6\n@itemx -mat\n@itemx -mat-binary\nForce Octave to assume the file is in @sc{matlab}'s version 6 binary format.\n\n@item  -v4\n@itemx -V4\n@itemx -4\n@itemx -mat4-binary\nForce Octave to assume the file is in @sc{matlab}'s version 4 binary format.\n\n@end table\n\nThe list of variables to load may use wildcard patterns (glob patterns)\ncontaining the following special characters:\n\n@table @code\n@item ?\nMatch any single character.\n\n@item *\nMatch zero or more characters.\n\n@item [ @var{list} ]\nMatch the list of characters specified by @var{list}.  If the first character\nis @code{!} or @code{^}, match all characters except those specified by\n@var{list}.  For example, the pattern @code{[a-zA-Z]} will match all lower and\nuppercase alphabetic characters.\n\n@end table\n\nIf invoked with a single output argument, Octave assigns loaded data to the\noutput instead of inserting variables in the symbol table.  If the data file\ncontains only numbers (TAB- or space-delimited columns), a matrix of values is\nreturned.  Otherwise, @code{load} returns a structure with members\ncorresponding to the names of the variables in the file.\n\nThe @code{load} command can read data stored in Octave's text and binary\nformats, @sc{matlab}'s binary format, and many simple formats such as\ncomma-separated-values (CSV).  If compiled with zlib support, it can also load\ngzip-compressed files.  It will automatically detect the type of file and do\nconversion from different floating point formats (currently only IEEE big and\nlittle endian, though other formats may be added in the future).\n\nProgramming Note: If a variable that is not marked as global is loaded from a\nfile when a global symbol with the same name already exists, it is loaded in\nthe global symbol table.  Also, if a variable is marked as global in a file and\na local symbol exists, the local symbol is moved to the global symbol table and\ngiven the value from the file.\n\n@seealso{save, csvread, dlmread, fread, textscan}\n@end deftypefn */)\n{\n  load_save_system& load_save_sys = interp.get_load_save_system ();\n\n  return load_save_sys.load (args, nargout);\n}\n\nDEFMETHOD (save, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} save file\n@deftypefnx {} {} save options file\n@deftypefnx {} {} save options file @var{v1} @var{v2} @dots{}\n@deftypefnx {} {} save options file -struct @var{STRUCT}\n@deftypefnx {} {} save options file -struct @var{STRUCT} @var{f1} @var{f2} @dots{}\n@deftypefnx {} {} save - @var{v1} @var{v2} @dots{}\n@deftypefnx {} {@var{str} =} save (\"-\", @qcode{\"@var{v1}\"}, @qcode{\"@var{v2}\"}, @dots{})\nSave the named variables @var{v1}, @var{v2}, @dots{}, in the file @var{file}.\n\nIf no variable names are listed, Octave saves all the variables in the current\nscope.  Otherwise, full variable names or pattern syntax can be used to specify\nthe variables to save.  If the @option{-struct} modifier is used then the\nfields of the @strong{scalar} struct are saved as if they were variables with\nthe corresponding field names.  The @option{-struct} option can be combined\nwith specific field names @var{f1}, @var{f2}, @dots{} to write only certain\nfields to the file.\n\nThe @code{save} command may also be invoked using the functional form\n\n@example\nsave (\"-option1\", @dots{}, \"file\", \"v1\", @dots{})\n@end example\n\n@noindent\nwhere the @var{options}, @var{file}, and variable name arguments (@var{v1},\n@dots{}) must be specified as character strings.\n\nValid options for the @code{save} command are listed in the following table.\nOptions that modify the output format override the format specified by\n@code{save_default_options}.\n\n@table @code\n@item -append\nAppend to the file instead of overwriting.\n\n@item -ascii\nSave a matrix in a text file without a header or any other information.  The\nmatrix must be 2-D and only the real part of any complex value is written to\nthe file.  Numbers are stored in single-precision format and separated by\nspaces.  Additional options for the @option{-ascii} format are\n\n@table @code\n@item -double\nStore numbers in double-precision format.\n\n@item -tabs\nSeparate numbers with tabs.\n@end table\n\n@item -binary\nSave the data in Octave's binary data format.\n\n@item -float-binary\nSave the data in Octave's binary data format using just single precision.\nUse this format @strong{only} if you know that all the values to be saved can\nbe represented in single precision.\n\n@item -hdf5\nSave the data in @sc{hdf5} format.  (@sc{hdf5} is a free, portable, binary\nformat developed by the National Center for Supercomputing Applications at the\nUniversity of Illinois.)  This format is only available if Octave was built\nwith a link to the @sc{hdf5} libraries.\n\n@item -float-hdf5\nSave the data in @sc{hdf5} format using just single precision.  Use this\nformat @strong{only} if you know that all the values to be saved can be\nrepresented in single precision.\n\n@item -text (default)\nSave the data in Octave's text data format.  The\n@ref{XREFsave_precision,,@code{save_precision}} function specifies the number\nof significant figures to use when saving data (default: 17).  The header of\nthe text data file can be configure with\n@ref{XREFsave_header_format_string,,save_header_format_string}.\n\n@item  -v7.3\n@itemx -V7.3\n@itemx -7.3\nOctave does @strong{not} yet implement saving in @sc{matlab}'s v7.3 binary\ndata format.\n\n@item  -v7\n@itemx -V7\n@itemx -7\n@itemx -mat7-binary\nSave the data in @sc{matlab}'s v7 binary data format.\n\n@item  -v6\n@itemx -V6\n@itemx -6\n@itemx -mat\n@itemx -mat-binary\nSave the data in @sc{matlab}'s v6 binary data format.\n\n@item  -v4\n@itemx -V4\n@itemx -4\n@itemx -mat4-binary\nSave the data in @sc{matlab}'s v4 binary data format.\n\n@item  -zip\n@itemx -z\nUse the gzip algorithm to compress the file.  This works on files that are\ncompressed with gzip outside of Octave, and gzip can also be used to convert\nthe files for backward compatibility.  This option is only available if Octave\nwas built with a link to the zlib libraries.\n@end table\n\nThe list of variables to save may use wildcard patterns (glob patterns)\ncontaining the following special characters:\n\n@table @code\n@item ?\nMatch any single character.\n\n@item *\nMatch zero or more characters.\n\n@item [ @var{list} ]\nMatch the list of characters specified by @var{list}.  If the first character\nis @code{!} or @code{^}, match all characters except those specified by\n@var{list}.  For example, the pattern @code{[a-zA-Z]} will match all lower and\nuppercase alphabetic characters.\n\nWildcards may also be used in the field name specifications when using the\n@option{-struct} modifier (but not in the struct name itself).\n\n@end table\n\nProgramming Notes: If called with the special filename @qcode{\"-\"} the data to\nbe saved is returned as a string rather than writing it to an actual file.\n\nWhen saving global variables the global status of the variable is also stored.\nIf the variable is restored at a later time using @code{load}, it will be\nrestored as a global variable.  Global status is @emph{not} preserved if\nusing a @sc{matlab} binary data file format or the @option{-ascii} format.\n\nExample:\n\nThe command\n\n@example\nsave -binary data a b*\n@end example\n\n@noindent\nsaves the variable @samp{a} and all variables beginning with @samp{b} to the\nfile @file{data} in Octave's binary format.\n\n@seealso{load, save_default_options, save_header_format_string, save_precision,\ncsvwrite, dlmwrite, fwrite}\n@end deftypefn */)\n{\n  load_save_system& load_save_sys = interp.get_load_save_system ();\n\n  return load_save_sys.save (args, nargout);\n}\n\n/*\n## Save and load strings with \"-v6\"\n%!test\n%! A = A2 = \"foobar\";  # normal string\n%! B = B2 = \"a\";  # short string\n%! C = C2 = [\"foo\"; \"bar\"];  # character matrix\n%! D = D2 = \"ab\".';  # short character matrix\n%! E = E2 = {\"foo\", \"bar\"};  # cell string\n%! F = F2 = {\"Saint Barthélemy\", \"Saint Kitts and Nevis\"};  % non-ASCII\n%! mat_file = [tempname(), \".mat\"];\n%! unwind_protect\n%!   save (mat_file, \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"-v6\");\n%!   clear (\"A\", \"B\", \"C\", \"D\", \"E\", \"F\");\n%!   load (mat_file);\n%! unwind_protect_cleanup\n%!   delete ([mat_file, '*']);\n%! end_unwind_protect\n%! assert (A, A2);\n%! assert (B, B2);\n%! assert (C, C2);\n%! assert (D, D2);\n%! assert (E, E2);\n%! assert (F, F2);\n\n## Save and load strings with \"-v7\"\n%!testif HAVE_ZLIB\n%! A = A2 = \"foobar\";  # normal string\n%! B = B2 = \"a\";  # short string\n%! C = C2 = [\"foo\"; \"bar\"];  # character matrix\n%! D = D2 = \"ab\".';  # short character matrix\n%! E = E2 = {\"foo\", \"bar\"};  # cell string\n%! F = F2 = {\"Saint Barthélemy\", \"Saint Kitts and Nevis\"};  # non-ASCII\n%! mat_file = [tempname(), \".mat\"];\n%! unwind_protect\n%!   save (mat_file, \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"-v7\");\n%!   clear (\"A\", \"B\", \"C\", \"D\", \"E\", \"F\");\n%!   load (mat_file);\n%! unwind_protect_cleanup\n%!   delete ([mat_file, '*']);\n%! end_unwind_protect\n%! assert (A, A2);\n%! assert (B, B2);\n%! assert (C, C2);\n%! assert (D, D2);\n%! assert (E, E2);\n%! assert (F, F2);\n\n## Save and load struct with \"-v6\"\n%!test\n%! struc.a = \"foobar\";  # normal string\n%! struc.b = \"a\";  # short string\n%! struc.c = [\"foo\"; \"bar\"];  # character matrix\n%! struc.d = \"ab\".';  # short character matrix\n%! struc.e = {\"foo\", \"bar\"};  # cell string\n%! struc.f = {\"Saint Barthélemy\", \"Saint Kitts and Nevis\"};  # non-ASCII\n%! struc.g = [1 2 3];  # double vector\n%! struc.h = 1:5;  # range\n%! struc2 = struc;\n%! mat_file = [tempname(), \".mat\"];\n%! unwind_protect\n%!   save (mat_file, \"struc\", \"-v6\");\n%!   clear (\"struc\");\n%!   load (mat_file);\n%! unwind_protect_cleanup\n%!   delete ([mat_file, '*']);\n%! end_unwind_protect\n%! assert (struc, struc2);\n\n## Save and load struct with \"-v7\"\n%!testif HAVE_ZLIB\n%! struc.a = \"foobar\";  # normal string\n%! struc.b = \"a\";  # short string\n%! struc.c = [\"foo\"; \"bar\"];  # character matrix\n%! struc.d = \"ab\".';  # short character matrix\n%! struc.e = {\"foo\", \"bar\"};  # cell string\n%! struc.f = {\"Saint Barthélemy\", \"Saint Kitts and Nevis\"};  # non-ASCII\n%! struc.g = [1 2 3];  # double vector\n%! struc.h = 1:5;  # range\n%! struc2 = struc;\n%! mat_file = [tempname(), \".mat\"];\n%! unwind_protect\n%!   save (mat_file, \"struc\", \"-v7\");\n%!   clear (\"struc\");\n%!   load (mat_file);\n%! unwind_protect_cleanup\n%!   delete ([mat_file, '*']);\n%! end_unwind_protect\n%! assert (struc, struc2);\n\n## Save and load double and single matrix in \"-binary\"\n%!test <*67699>\n%! x = [1, 1+eps()];\n%! y = single (x);  # i.e., [1, 1]\n%! mat_file = [tempname(), \".bin\"];\n%! unwind_protect\n%!   save (mat_file, \"x\", \"y\", \"-binary\");\n%!   clear (\"x\", \"y\");\n%!   load (mat_file);\n%! unwind_protect_cleanup\n%!   delete ([mat_file, '*']);\n%! end_unwind_protect\n%! assert (x, [1, 1+eps()]);\n%! assert (y, single ([1, 1+eps()]));\n\n## Save and load double and single matrix in \"-float-binary\"\n%!test <*67699>\n%! x = [1, 1+eps()];  # truncates to [1, 1] when saving as \"-float-binary\"\n%! y = single (x);  # i.e., [1, 1]\n%! mat_file = [tempname(), \".bin\"];\n%! unwind_protect\n%!   save (mat_file, \"x\", \"y\", \"-float-binary\");\n%!   clear (\"x\", \"y\");\n%!   load (mat_file);\n%! unwind_protect_cleanup\n%!   delete ([mat_file, '*']);\n%! end_unwind_protect\n%! assert (x, double (single ([1, 1+eps()])));\n%! assert (y, single ([1, 1+eps()]));\n\n## Test input validation\n%!testif HAVE_ZLIB <*59225>\n%! fname = tempname ();\n%! x = 1;\n%! fail ('save (\"-append\", \"-zip\", \"-binary\", fname, \"x\")',\n%!       \"-append and -zip options .* with a text format\");\n*/\n\nDEFMETHOD (crash_dumps_octave_core, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} crash_dumps_octave_core ()\n@deftypefnx {} {@var{old_val} =} crash_dumps_octave_core (@var{new_val})\n@deftypefnx {} {@var{old_val} =} crash_dumps_octave_core (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave tries\nto save all current variables to the file @file{octave-workspace} if it\ncrashes or receives a hangup, terminate or similar signal.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{octave_core_file_limit, octave_core_file_name,\noctave_core_file_options}\n@end deftypefn */)\n{\n  load_save_system& load_save_sys = interp.get_load_save_system ();\n\n  return load_save_sys.crash_dumps_octave_core (args, nargout);\n}\n\nDEFMETHOD (save_default_options, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} save_default_options ()\n@deftypefnx {} {@var{old_val} =} save_default_options (@var{new_val})\n@deftypefnx {} {@var{old_val} =} save_default_options (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the default options\nfor the @code{save} command, and defines the default format.\n\nThe default value is @qcode{\"-text\"} (Octave's own text-based file format).\nSee the documentation of the @code{save} command for other choices.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{save, save_header_format_string, save_precision}\n@end deftypefn */)\n{\n  load_save_system& load_save_sys = interp.get_load_save_system ();\n\n  return load_save_sys.save_default_options (args, nargout);\n}\n\nDEFMETHOD (octave_core_file_limit, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} octave_core_file_limit ()\n@deftypefnx {} {@var{old_val} =} octave_core_file_limit (@var{new_val})\n@deftypefnx {} {@var{old_val} =} octave_core_file_limit (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the maximum amount of memory\nthat Octave will save when writing a crash dump file.\n\nThe limit is measured in kilobytes and is applied to the top-level workspace.\nThe name of the crash dump file is specified by\n@var{octave_core_file_name}.\n\nIf @var{octave_core_file_options} flags specify a binary format, then\n@var{octave_core_file_limit} will be approximately the maximum size of the\nfile.  If a text file format is used, then the file could be much larger than\nthe limit.  The default value is -1 (unlimited).\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{crash_dumps_octave_core, octave_core_file_name,\noctave_core_file_options}\n@end deftypefn */)\n{\n  load_save_system& load_save_sys = interp.get_load_save_system ();\n\n  return load_save_sys.octave_core_file_limit (args, nargout);\n}\n\nDEFMETHOD (octave_core_file_name, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} octave_core_file_name ()\n@deftypefnx {} {@var{old_val} =} octave_core_file_name (@var{new_val})\n@deftypefnx {} {@var{old_val} =} octave_core_file_name (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the name of the file\nused for saving data from the top-level workspace if Octave aborts.\n\nThe default value is @qcode{\"octave-workspace\"}\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{crash_dumps_octave_core, octave_core_file_name,\noctave_core_file_options}\n@end deftypefn */)\n{\n  load_save_system& load_save_sys = interp.get_load_save_system ();\n\n  return load_save_sys.octave_core_file_name (args, nargout);\n}\n\nDEFMETHOD (octave_core_file_options, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} octave_core_file_options ()\n@deftypefnx {} {@var{old_val} =} octave_core_file_options (@var{new_val})\n@deftypefnx {} {@var{old_val} =} octave_core_file_options (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the options used for\nsaving the workspace data if Octave aborts.\n\nThe value of @code{octave_core_file_options} should follow the same format\nas the options for the @code{save} function.  The default value is Octave's\nbinary format.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{crash_dumps_octave_core, octave_core_file_name, octave_core_file_limit}\n@end deftypefn */)\n{\n  load_save_system& load_save_sys = interp.get_load_save_system ();\n\n  return load_save_sys.octave_core_file_options (args, nargout);\n}\n\nDEFMETHOD (save_header_format_string, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} save_header_format_string ()\n@deftypefnx {} {@var{old_val} =} save_header_format_string (@var{new_val})\n@deftypefnx {} {@var{old_val} =} save_header_format_string (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the format string used for\nthe comment line written at the beginning of text-format data files saved by\nOctave.\n\nThe format string is passed to @code{strftime} and must begin with the\ncharacter @samp{#} and contain no newline characters.  If the value of\n@code{save_header_format_string} is the empty string, the header comment is\nomitted from text-format data files.  The default value is\n@c Set example in small font to prevent overfull line\n\n@smallexample\n\"# Created by Octave VERSION, %a %b %d %H:%M:%S %Y %Z\"\n@end smallexample\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{strftime, save_default_options}\n@end deftypefn */)\n{\n  load_save_system& load_save_sys = interp.get_load_save_system ();\n\n  return load_save_sys.save_header_format_string (args, nargout);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/load-save.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_load_save_h)\n#define octave_load_save_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n#include <unordered_map>\n\n#include \"mach-info.h\"\n\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\nclass load_save_format;\nclass symbol_info;\nclass subsystem_handler;\n\nclass load_save_system\n{\npublic:\n\n  // FIXME: maybe MAT5 and MAT7 should be options to MAT_BINARY.\n  // Similarly, save_as_floats may be an option for LS_BINARY,\n  // LS_HDF5 etc.\n\n  enum format_type\n  {\n    TEXT,\n    BINARY,\n    MAT_ASCII,\n    MAT_BINARY,\n    MAT5_BINARY,\n    MAT7_BINARY,\n    HDF5,\n    UNKNOWN\n  };\n\n  enum format_options\n  {\n    // MAT_ASCII options (not exclusive)\n    MAT_ASCII_LONG = 1,\n    MAT_ASCII_TABS = 2,\n    // MAT_BINARY options\n    MAT_BINARY_V5 = 1,\n    MAT_BINARY_V7,\n    // zero means no option.\n    NO_OPTION = 0\n  };\n\n  OCTINTERP_API load_save_system (interpreter& interp);\n\n  OCTINTERP_API ~load_save_system ();\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (load_save_system)\n\n  OCTINTERP_API octave_value\n  crash_dumps_octave_core (const octave_value_list& args, int nargout);\n\n  bool crash_dumps_octave_core () const\n  {\n    return m_crash_dumps_octave_core;\n  }\n\n  bool crash_dumps_octave_core (bool flag)\n  {\n    return set (m_crash_dumps_octave_core, flag);\n  }\n\n  octave_value octave_core_file_limit (const octave_value_list& args,\n                                       int nargout);\n\n  double octave_core_file_limit () const\n  {\n    return m_octave_core_file_limit;\n  }\n\n  double octave_core_file_limit (double limit)\n  {\n    return set (m_octave_core_file_limit, limit);\n  }\n\n  OCTINTERP_API octave_value\n  octave_core_file_name (const octave_value_list& args, int nargout);\n\n  std::string octave_core_file_name () const\n  {\n    return m_octave_core_file_name;\n  }\n\n  std::string octave_core_file_name (const std::string& file)\n  {\n    return set (m_octave_core_file_name, file);\n  }\n\n  OCTINTERP_API octave_value\n  save_default_options (const octave_value_list& args, int nargout);\n\n  std::string save_default_options () const\n  {\n    return m_save_default_options;\n  }\n\n  std::string save_default_options (const std::string& options)\n  {\n    return set (m_save_default_options, options);\n  }\n\n  OCTINTERP_API octave_value\n  octave_core_file_options (const octave_value_list& args, int nargout);\n\n  std::string octave_core_file_options () const\n  {\n    return m_octave_core_file_options;\n  }\n\n  std::string octave_core_file_options (const std::string& options)\n  {\n    return set (m_octave_core_file_options, options);\n  }\n\n  OCTINTERP_API octave_value\n  save_header_format_string (const octave_value_list& args, int nargout);\n\n  std::string save_header_format_string () const\n  {\n    return m_save_header_format_string;\n  }\n\n  std::string save_header_format_string (const std::string& format)\n  {\n    return set (m_save_header_format_string, format);\n  }\n\n  static OCTINTERP_API load_save_format\n  get_file_format (const std::string& fname, const std::string& orig_fname,\n                   bool& use_zlib, bool quiet = false);\n\n  // FIXME: this is probably not the best public interface for\n  // loading and saving variables, but it is what is currently\n  // needed for the Fload and Fsave functions.\n\n  OCTINTERP_API octave_value\n  load_vars (std::istream& stream, const std::string& orig_fname,\n             const load_save_format& fmt, mach_info::float_format flt_fmt,\n             bool list_only, bool swap, bool verbose,\n             const string_vector& argv, int argv_idx, int argc, int nargout);\n\n  static OCTINTERP_API string_vector\n  parse_save_options (const string_vector& argv, load_save_format& fmt,\n                      bool& append, bool& save_as_floats, bool& use_zlib);\n\n  static OCTINTERP_API string_vector\n  parse_save_options (const std::string& arg, load_save_format& fmt,\n                      bool& append, bool& save_as_floats, bool& use_zlib);\n\n  OCTINTERP_API void\n  save_vars (const string_vector& argv, int argv_idx, int argc,\n             std::ostream& os, const load_save_format& fmt,\n             bool save_as_floats, bool write_header_info);\n\n  OCTINTERP_API void dump_octave_core ();\n\n  OCTINTERP_API octave_value_list\n  load (const octave_value_list& args = octave_value_list (),\n        int nargout = 0);\n\n  OCTINTERP_API octave_value_list\n  save (const octave_value_list& args = octave_value_list (),\n        int nargout = 0);\n\n  // MCOS object cache management for loading classdef objects\n  OCTINTERP_API void clear_mcos_object_cache ();\n\n  OCTINTERP_API void\n  set_mcos_object_cache_entry (uint32_t object_id, octave_value& obj);\n\n  OCTINTERP_API octave_value& get_mcos_object_cache_entry (uint32_t object_id);\n\n  OCTINTERP_API bool is_mcos_object_cache_entry (uint32_t object_id);\n\n  OCTINTERP_API uint32_t\n  get_mcos_object_cache_id (const void *obj, bool& new_entry);\n\n  OCTINTERP_API void create_subsystem_handler ();\n\n  OCTINTERP_API subsystem_handler * get_subsystem_handler ();\n\n  OCTINTERP_API void clear_subsystem_handler ();\n\nprivate:\n\n  // Subsystem handler is used to read and write MCOS objects in MAT-files\n  std::unique_ptr<subsystem_handler> m_subsystem_handler;\n\n  interpreter& m_interpreter;\n\n  // Write octave-workspace file if Octave crashes or is killed by a\n  // signal.\n  bool m_crash_dumps_octave_core;\n\n  // The maximum amount of memory (in kilobytes) that we will\n  // attempt to write to the Octave core file.\n  double m_octave_core_file_limit;\n\n  // The name of the Octave core file.\n  std::string m_octave_core_file_name;\n\n  // The default output format.  May be one of \"binary\", \"text\",\n  // \"mat-binary\", or \"hdf5\".\n  std::string m_save_default_options;\n\n  // The output format for Octave core files.\n  std::string m_octave_core_file_options;\n\n  // The format string for the comment line at the top of\n  // text-format save files.  Passed to strftime.  Should begin with\n  // '#' and contain no newline characters.\n  std::string m_save_header_format_string;\n\n  // Cache for constructed MCOS objects and their object IDs during loading\n  std::unordered_map<uint32_t, octave_value> m_mcos_object_load_cache;\n\n  // Cache for constructed MCOS objects and their object IDs during saving\n  std::unordered_map<const void *, uint32_t> m_mcos_object_save_cache;\n\n  OCTINTERP_API void\n  write_header (std::ostream& os, const load_save_format& fmt);\n\n  OCTINTERP_API std::size_t\n  save_vars (std::ostream& os, const std::string& pattern,\n             const load_save_format& fmt, bool save_as_floats);\n\n  OCTINTERP_API void\n  do_save (std::ostream& os, const octave_value& tc, const std::string& name,\n           const std::string& help, bool global, const load_save_format& fmt,\n           bool save_as_floats);\n\n  OCTINTERP_API void\n  do_save (std::ostream& os, const symbol_info& syminfo,\n           const load_save_format& fmt, bool save_as_floats);\n\n  OCTINTERP_API std::size_t\n  save_fields (std::ostream& os, const octave_scalar_map& m,\n               const std::string& pattern, const load_save_format& fmt,\n               bool save_as_floats);\n\n  OCTINTERP_API void\n  dump_octave_core (std::ostream& os, const char *fname,\n                    const load_save_format& fmt, bool save_as_floats);\n\n  OCTINTERP_API void\n  install_loaded_variable (const std::string& name, const octave_value& val,\n                           bool global, const std::string& /*doc*/);\n\n  static OCTINTERP_API std::string init_save_header_format ();\n\n  static OCTINTERP_API load_save_format\n  get_file_format (std::istream& file, const std::string& filename);\n\n  template <typename T>\n  T set (T& var, const T& new_val)\n  {\n    T old_val = var;\n    var = new_val;\n    return old_val;\n  }\n};\n\nclass load_save_format\n{\npublic:\n\n  load_save_format (load_save_system::format_type type,\n                    load_save_system::format_options options = load_save_system::NO_OPTION)\n    : m_type (type), m_options (options)\n  { }\n\n  void set_type (load_save_system::format_type type) { m_type = type; }\n\n  load_save_system::format_type type () const { return m_type; }\n\n  void set_option (load_save_system::format_options option)\n  {\n    m_options |= option;\n  }\n\n  int options () const { return m_options; }\n\nprivate:\n\n  load_save_system::format_type m_type;\n  int m_options;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-ascii-helper.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ls-ascii-helper.h\"\n\n#include <istream>\n#include <sstream>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Helper functions when reading from ascii files.\n\n// These functions take care of different line endings (LF, CR, CRLF)\n// when files were opened in text mode for writing and are now opened in\n// binary mode for reading.\n// Even though we no longer store files in text mode, keep this logic\n// to allow loading older files that might have CRLF or CR line endings.\n\n// Skip characters from stream IS until a newline is reached.\n// Depending on KEEP_NEWLINE, either eat newline from stream or\n// keep it unread.\n\nvoid\nskip_until_newline (std::istream& is, bool keep_newline)\n{\n  if (! is)\n    return;\n\n  while (is)\n    {\n      char c = is.peek ();\n\n      if (c == '\\n' || c == '\\r')\n        {\n          // Reached newline.\n          if (! keep_newline)\n            {\n              // Eat the CR or LF character.\n              char d;\n              is.get (d);\n\n              // Make sure that for binary-mode opened ascii files\n              // containing CRLF line endings we skip the LF after CR.\n              if (c == '\\r' && is.peek () == '\\n')\n                {\n                  // Yes, LF following CR, eat it.\n                  is.get (d);\n                }\n            }\n\n          // Newline was found, and read from stream if\n          // keep_newline == true, so exit loop.\n          break;\n        }\n      else\n        {\n          // No newline character peeked, so read it and proceed to next\n          // character.\n          char d;\n          is.get (d);\n        }\n    }\n}\n\n// If stream IS currently points to a newline (a leftover from a previous read)\n// then eat newline(s) until a non-newline character is found.\n\nvoid\nskip_preceeding_newline (std::istream& is)\n{\n  if (! is)\n    return;\n\n  // Check whether IS currently points to newline character.\n  char c = is.peek ();\n\n  if (c == '\\n' || c == '\\r')\n    {\n      // Yes, at newline.\n      do\n        {\n          // Eat the CR or LF character.\n          char d;\n          is.get (d);\n\n          // Make sure that for binary-mode opened ascii files\n          // containing CRLF line endings we skip the LF after CR.\n          if (c == '\\r' && is.peek () == '\\n')\n            {\n              // Yes, LF following CR, eat it.\n              is.get (d);\n            }\n\n          // Peek into next character.\n          c = is.peek ();\n\n          // Loop while still a newline ahead.\n        }\n      while (c == '\\n' || c == '\\r');\n    }\n}\n\n// Read characters from stream IS until a newline is reached.\n// Depending on KEEP_NEWLINE, either eat newline from stream or keep\n// it unread.  Characters read are stored and returned as\n// std::string.\n\nstd::string\nread_until_newline (std::istream& is, bool keep_newline)\n{\n  if (! is)\n    return \"\";\n\n  std::ostringstream buf;\n\n  while (is)\n    {\n      char c = is.peek ();\n\n      if (c == '\\n' || c == '\\r')\n        {\n          // Reached newline.\n          if (! keep_newline)\n            {\n              // Eat the CR or LF character.\n              char d;\n              is.get (d);\n\n              // Make sure that for binary-mode opened ascii files\n              // containing CRLF line endings we skip the LF after\n              // CR.\n\n              if (c == '\\r' && is.peek () == '\\n')\n                {\n                  // Yes, LF following CR, eat it.\n                  is.get (d);\n                }\n            }\n\n          // Newline was found, and read from stream if\n          // keep_newline == true, so exit loop.\n          break;\n        }\n      else\n        {\n          // No newline character peeked, so read it, store it, and\n          // proceed to next.\n          char d;\n          is.get (d);\n          buf << d;\n        }\n    }\n\n  return buf.str ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/ls-ascii-helper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ls_ascii_helper_h)\n#define octave_ls_ascii_helper_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API void\nskip_until_newline (std::istream& is, bool keep_newline = false);\n\nextern OCTINTERP_API void\nskip_preceeding_newline (std::istream& is);\n\nextern OCTINTERP_API std::string\nread_until_newline (std::istream& is, bool keep_newline = false);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-hdf5.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_HDF5)\n\n#include <cctype>\n\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <string>\n#include <vector>\n\n#include \"byte-swap.h\"\n#include \"data-conv.h\"\n#include \"file-ops.h\"\n#include \"glob-match.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n#include \"str-vec.h\"\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"load-save.h\"\n#include \"oct-hdf5.h\"\n#include \"ovl.h\"\n#include \"oct-map.h\"\n#include \"ov-cell.h\"\n#include \"ov-classdef.h\"\n#include \"pager.h\"\n#include \"sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"version.h\"\n#include \"dMatrix.h\"\n#include \"ov-lazy-idx.h\"\n\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\n#if defined (HAVE_HDF5)\n\nstatic hid_t\ncheck_hdf5_id_value (octave_hdf5_id id, const char *who)\n{\n  if (id > std::numeric_limits<hid_t>::max ())\n    error (\"%s: internal error: ID too large for hid_t\", who);\n\n  return static_cast<hid_t> (id);\n}\n\n#else\n\nOCTAVE_NORETURN static void\nerror_unexpected (const char *name)\n{\n  error (\"unexpected call to %s when HAVE_HDF5 is not defined - please report this bug\", name);\n}\n\n#endif\n\nhdf5_fstreambase::hdf5_fstreambase (const char *name, int mode, int /* prot */)\n  : file_id (-1), current_item (-1)\n{\n#if defined (HAVE_HDF5)\n  open_create (name, mode);\n\n  current_item = 0;\n\n#else\n  err_disabled_feature (\"hdf5_fstreambase\", \"HDF5\");\n#endif\n}\n\nvoid\nhdf5_fstreambase::close ()\n{\n#if defined (HAVE_HDF5)\n\n  if (file_id >= 0)\n    {\n      if (H5Fclose (file_id) < 0)\n        std::ios::setstate (std::ios::badbit);\n      file_id = -1;\n    }\n\n#else\n\n  error_unexpected (\"hdf5_fstreambase::close\");\n\n#endif\n}\n\nvoid\nhdf5_fstreambase::open (const char *name, int mode, int)\n{\n#if defined (HAVE_HDF5)\n\n  clear ();\n\n  open_create (name, mode);\n\n  current_item = 0;\n\n#else\n\n  error_unexpected (\"hdf5_fstreambase::open\");\n\n#endif\n}\n\nvoid\nhdf5_fstreambase::open_create (const char *name, int mode)\n{\n#if defined (HAVE_HDF5)\n  // Open the HDF5 file NAME.  If it does not exist, create the file.\n\n#  if defined (HAVE_HDF5_UTF8)\n  const char *fname = name;\n#  else\n  std::string fname_str (name);\n  std::string ascii_fname_str = octave::sys::get_ASCII_filename (fname_str);\n  const char *fname = ascii_fname_str.c_str ();\n#  endif\n\n  if (mode & std::ios::in)\n    file_id = H5Fopen (fname, H5F_ACC_RDONLY, octave_H5P_DEFAULT);\n  else if (mode & std::ios::out)\n    {\n      if (mode & std::ios::app && H5Fis_hdf5 (fname) > 0)\n        file_id = H5Fopen (fname, H5F_ACC_RDWR, octave_H5P_DEFAULT);\n      else\n#  if defined (HAVE_HDF5_UTF8)\n        file_id = H5Fcreate (fname, H5F_ACC_TRUNC, octave_H5P_DEFAULT,\n                             octave_H5P_DEFAULT);\n#  else\n        {\n          // Check whether file already exists\n          std::string abs_ascii_fname\n            = octave::sys::canonicalize_file_name (ascii_fname_str);\n          if (! abs_ascii_fname.empty ())\n            {\n              // Use the existing file\n              file_id = H5Fcreate (fname, H5F_ACC_TRUNC,\n                                   octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n              if (file_id < 0)\n                std::ios::setstate (std::ios::badbit);\n\n              return;\n            }\n\n          // Check whether filename contains non-ASCII (UTF-8) characters.\n          std::string::const_iterator first_non_ASCII\n            = std::find_if (fname_str.begin (), fname_str.end (),\n          [](char c) { return (c < 0 || c >= 128); });\n          if (first_non_ASCII == fname_str.end ())\n            {\n              // No non-ASCII characters\n              file_id = H5Fcreate (name, H5F_ACC_TRUNC, octave_H5P_DEFAULT,\n                                   octave_H5P_DEFAULT);\n              if (file_id < 0)\n                std::ios::setstate (std::ios::badbit);\n\n              return;\n            }\n\n          // Create file in temp folder\n          std::string tmp_name = octave::sys::tempnam (\"\", \"oct-\");\n          octave_hdf5_id hdf5_fid = H5Fcreate (tmp_name.c_str (), H5F_ACC_TRUNC,\n                                               octave_H5P_DEFAULT,\n                                               octave_H5P_DEFAULT);\n          if (hdf5_fid < 0)\n            {\n              file_id = -1;\n              std::ios::setstate (std::ios::badbit);\n              return;\n            }\n\n          // Close file\n          H5Fclose (hdf5_fid);\n\n          // Move temporary file to final destination\n          std::string msg;\n          int res = octave::sys::rename (tmp_name, name, msg);\n          if (res < 0)\n            {\n              std::ios::setstate (std::ios::badbit);\n              file_id = -1;\n              return;\n            }\n\n          // Open file at final location\n          ascii_fname_str = octave::sys::get_ASCII_filename (fname_str);\n          ascii_fname = ascii_fname_str.c_str ();\n          file_id = H5Fopen (ascii_fname, H5F_ACC_RDWR, octave_H5P_DEFAULT);\n        }\n#  endif\n    }\n  if (file_id < 0)\n    std::ios::setstate (std::ios::badbit);\n\n  return;\n\n#else\n\n  error_unexpected (\"hdf5_fstreambase::open_create\");\n\n#endif\n}\n\nstatic std::string\nmake_valid_identifier (const std::string& nm)\n{\n  std::string retval;\n\n  std::size_t nm_len = nm.length ();\n\n  if (nm_len > 0)\n    {\n      if (! isalpha (nm[0]))\n        retval += '_';\n\n      for (std::size_t i = 0; i < nm_len; i++)\n        {\n          char c = nm[i];\n          retval += (isalnum (c) || c == '_') ? c : '_';\n        }\n    }\n\n  return retval;\n}\n\n// Given two compound types t1 and t2, determine whether they\n// are compatible for reading/writing.  This function only\n// works for non-nested types composed of simple elements (ints, floats...),\n// which is all we need it for\n\nbool\nhdf5_types_compatible (octave_hdf5_id t1, octave_hdf5_id t2)\n{\n#if defined (HAVE_HDF5)\n\n  int n;\n  if ((n = H5Tget_nmembers (t1)) != H5Tget_nmembers (t2))\n    return false;\n\n  for (int i = 0; i < n; ++i)\n    {\n      hid_t mt1 = H5Tget_member_type (t1, i);\n      hid_t mt2 = H5Tget_member_type (t2, i);\n\n      if (H5Tget_class (mt1) != H5Tget_class (mt2))\n        return false;\n\n      H5Tclose (mt2);\n      H5Tclose (mt1);\n    }\n\n  return true;\n\n#else\n  err_disabled_feature (\"hdf5_types_compatible\", \"HDF5\");\n#endif\n}\n\n// Return true if loc_id has the attribute named attr_name, and false\n// otherwise.\n\nbool\nhdf5_check_attr (octave_hdf5_id loc_id, const char *attr_name)\n{\n#if defined (HAVE_HDF5)\n\n  bool retval = false;\n\n  // we have to pull some shenanigans here to make sure\n  // HDF5 doesn't print out all sorts of error messages if we\n  // call H5Aopen for a non-existing attribute\n\n  H5E_auto_t err_fcn;\n  void *err_fcn_data;\n\n  // turn off error reporting temporarily, but save the error\n  // reporting function:\n\n#if defined (HAVE_HDF5_18)\n  H5Eget_auto (octave_H5E_DEFAULT, &err_fcn, &err_fcn_data);\n  H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr);\n#else\n  H5Eget_auto (&err_fcn, &err_fcn_data);\n  H5Eset_auto (nullptr, nullptr);\n#endif\n\n  hid_t attr_id = H5Aopen_name (loc_id, attr_name);\n\n  if (attr_id >= 0)\n    {\n      // successful\n      retval = true;\n      H5Aclose (attr_id);\n    }\n\n  // restore error reporting:\n#if defined (HAVE_HDF5_18)\n  H5Eset_auto (octave_H5E_DEFAULT, err_fcn, err_fcn_data);\n#else\n  H5Eset_auto (err_fcn, err_fcn_data);\n#endif\n  return retval;\n\n#else\n  err_disabled_feature (\"hdf5_check_attr\", \"HDF5\");\n#endif\n}\n\nbool\nhdf5_get_scalar_attr (octave_hdf5_id loc_id, octave_hdf5_id type_id,\n                      const char *attr_name, void *buf)\n{\n#if defined (HAVE_HDF5)\n\n  bool retval = false;\n\n  // we have to pull some shenanigans here to make sure\n  // HDF5 doesn't print out all sorts of error messages if we\n  // call H5Aopen for a non-existing attribute\n\n  H5E_auto_t err_fcn;\n  void *err_fcn_data;\n\n  // turn off error reporting temporarily, but save the error\n  // reporting function:\n\n#if defined (HAVE_HDF5_18)\n  H5Eget_auto (octave_H5E_DEFAULT, &err_fcn, &err_fcn_data);\n  H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr);\n#else\n  H5Eget_auto (&err_fcn, &err_fcn_data);\n  H5Eset_auto (nullptr, nullptr);\n#endif\n\n  hid_t attr_id = H5Aopen_name (loc_id, attr_name);\n\n  if (attr_id >= 0)\n    {\n      hid_t space_id = H5Aget_space (attr_id);\n\n      hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n      if (rank == 0)\n        retval = H5Aread (attr_id, type_id, buf) >= 0;\n      H5Aclose (attr_id);\n    }\n\n  // restore error reporting:\n#if defined (HAVE_HDF5_18)\n  H5Eset_auto (octave_H5E_DEFAULT, err_fcn, err_fcn_data);\n#else\n  H5Eset_auto (err_fcn, err_fcn_data);\n#endif\n  return retval;\n\n#else\n  err_disabled_feature (\"hdf5_get_scalar_attr\", \"HDF5\");\n#endif\n}\n\n// The following subroutines creates an HDF5 representations of the way\n// we will store Octave complex types (pairs of floating-point numbers).\n// NUM_TYPE is the HDF5 numeric type to use for storage (e.g.,\n// H5T_NATIVE_DOUBLE to save as 'double').  Note that any necessary\n// conversions are handled automatically by HDF5.\n\noctave_hdf5_id\nhdf5_make_complex_type (octave_hdf5_id num_type)\n{\n#if defined (HAVE_HDF5)\n\n  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 2);\n\n  H5Tinsert (type_id, \"real\", 0 * sizeof (double), num_type);\n  H5Tinsert (type_id, \"imag\", 1 * sizeof (double), num_type);\n\n  return type_id;\n\n#else\n  err_disabled_feature (\"hdf5_make_complex_type\", \"HDF5\");\n#endif\n}\n\n#if defined (HAVE_HDF5)\n\n// The following subroutine creates an HDF5 representation of the way\n// we will store Octave range types (triplets of floating-point numbers).\n// NUM_TYPE is the HDF5 numeric type to use for storage\n// (e.g., H5T_NATIVE_DOUBLE to save as 'double').\n// Note that any necessary conversions are handled automatically by HDF5.\n\nstatic hid_t\nhdf5_make_range_type (hid_t num_type)\n{\n  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 3);\n\n  H5Tinsert (type_id, \"base\", 0 * sizeof (double), num_type);\n  H5Tinsert (type_id, \"limit\", 1 * sizeof (double), num_type);\n  H5Tinsert (type_id, \"increment\", 2 * sizeof (double), num_type);\n\n  return type_id;\n}\n\nstatic herr_t\nload_inline_fcn (hid_t loc_id, const char *name, octave_value& retval)\n{\n#if defined (HAVE_HDF5)\n\n  hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id;\n  hsize_t rank;\n  int slen;\n\n#if defined (HAVE_HDF5_18)\n  group_hid = H5Gopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  group_hid = H5Gopen (loc_id, name);\n#endif\n  if (group_hid < 0) return -1;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"args\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"args\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Dclose (data_hid);\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  octave_value_list args (hdims[1]+1);\n\n  OCTAVE_LOCAL_BUFFER (char, s1, hdims[0] * hdims[1]);\n\n  if (H5Dread (data_hid, H5T_NATIVE_UCHAR, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, s1) < 0)\n    {\n      H5Dclose (data_hid);\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n  for (std::size_t i = 0; i < hdims[1]; i++)\n    args(i+1) = std::string (s1 + i*hdims[0]);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nm\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nm\");\n#endif\n\n  if (data_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  type_hid = H5Dget_type (data_hid);\n  type_class_hid = H5Tget_class (type_hid);\n\n  if (type_class_hid != H5T_STRING)\n    {\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  slen = H5Tget_size (type_hid);\n  if (slen < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  OCTAVE_LOCAL_BUFFER (char, nm_tmp, slen);\n\n  // create datatype for (null-terminated) string to read into:\n  st_id = H5Tcopy (H5T_C_S1);\n  H5Tset_size (st_id, slen);\n\n  if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, nm_tmp) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n  H5Tclose (st_id);\n  H5Dclose (data_hid);\n  // NAME is obsolete and unused.\n  // std::string name (nm_tmp);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"iftext\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"iftext\");\n#endif\n\n  if (data_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  type_hid = H5Dget_type (data_hid);\n  type_class_hid = H5Tget_class (type_hid);\n\n  if (type_class_hid != H5T_STRING)\n    {\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  slen = H5Tget_size (type_hid);\n  if (slen < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n\n  OCTAVE_LOCAL_BUFFER (char, iftext_tmp, slen);\n\n  // create datatype for (null-terminated) string to read into:\n  st_id = H5Tcopy (H5T_C_S1);\n  H5Tset_size (st_id, slen);\n\n  if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, iftext_tmp) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return -1;\n    }\n  H5Tclose (st_id);\n  H5Dclose (data_hid);\n\n  args(0) = std::string (iftext_tmp);\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave_value_list tmp = interp.feval (\"inline\", args, 1);\n\n  if (tmp.length () > 0)\n    {\n      retval = tmp(0);\n      return 1;\n    }\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (retval);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return -1;\n}\n\n// This function is designed to be passed to H5Giterate, which calls it\n// on each data item in an HDF5 file.  For the item whose name is NAME in\n// the group GROUP_ID, this function sets dv->tc to an Octave representation\n// of that item.  (dv must be a pointer to hdf5_callback_data.)  (It also\n// sets the other fields of dv).\n//\n// It returns 1 on success (in which case H5Giterate stops and returns),\n// -1 on error, and 0 to tell H5Giterate to continue on to the next item\n// (e.g., if NAME was a data type we don't recognize).\n//\n// This function must not throw an exception.\n\nstatic herr_t\nhdf5_read_next_data_internal (hid_t group_id, const char *name, void *dv)\n{\n  hdf5_callback_data *d = static_cast<hdf5_callback_data *> (dv);\n  hid_t type_id = -1;\n  hid_t type_class_id = -1;\n  hid_t data_id = -1;\n  hid_t subgroup_id = -1;\n  hid_t space_id = -1;\n\n  H5G_stat_t info;\n  herr_t retval = 0;\n  bool ident_valid = octave::valid_identifier (name);\n\n  std::string vname = name;\n\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  // Allow identifiers as all digits so we can load lists saved by\n  // earlier versions of Octave.\n\n  if (! ident_valid)\n    {\n      // fix the identifier, replacing invalid chars with underscores\n      vname = make_valid_identifier (vname);\n\n      // check again (in case vname was null, empty, or some such thing):\n      ident_valid = octave::valid_identifier (vname);\n    }\n\n  H5Gget_objinfo (group_id, name, 1, &info);\n\n  if (info.type == H5G_GROUP && ident_valid)\n    {\n#if defined (HAVE_HDF5_18)\n      subgroup_id = H5Gopen (group_id, name, octave_H5P_DEFAULT);\n#else\n      subgroup_id = H5Gopen (group_id, name);\n#endif\n\n      if (subgroup_id < 0)\n        {\n          retval = subgroup_id;\n          goto done;\n        }\n\n      if (hdf5_check_attr (subgroup_id, \"OCTAVE_NEW_FORMAT\"))\n        {\n#if defined (HAVE_HDF5_18)\n          data_id = H5Dopen (subgroup_id, \"type\", octave_H5P_DEFAULT);\n#else\n          data_id = H5Dopen (subgroup_id, \"type\");\n#endif\n\n          if (data_id < 0)\n            {\n              retval = data_id;\n              goto done;\n            }\n\n          type_id = H5Dget_type (data_id);\n\n          type_class_id = H5Tget_class (type_id);\n\n          if (type_class_id != H5T_STRING)\n            goto done;\n\n          space_id = H5Dget_space (data_id);\n          hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n          if (rank != 0)\n            goto done;\n\n          int slen = H5Tget_size (type_id);\n          if (slen < 0)\n            goto done;\n\n          OCTAVE_LOCAL_BUFFER (char, typ, slen);\n\n          // create datatype for (null-terminated) string to read into:\n          hid_t st_id = H5Tcopy (H5T_C_S1);\n          H5Tset_size (st_id, slen);\n\n          if (H5Dread (data_id, st_id, octave_H5S_ALL, octave_H5S_ALL,\n                       octave_H5P_DEFAULT, typ) < 0)\n            goto done;\n\n          H5Tclose (st_id);\n          H5Dclose (data_id);\n\n          if (std::string (typ, slen-1) == \"inline function\")\n            {\n              retval = load_inline_fcn (subgroup_id, name, d->tc);\n            }\n          else\n            {\n              d->tc = type_info.lookup_type (std::string (typ, slen-1));\n\n              try\n                {\n                  retval = (d->tc.load_hdf5 (subgroup_id, \"value\") ? 1 : -1);\n                }\n              catch (const octave::execution_exception& ee)\n                {\n                  retval = -1;\n                }\n            }\n\n          // check for OCTAVE_GLOBAL attribute:\n          d->global = hdf5_check_attr (subgroup_id, \"OCTAVE_GLOBAL\");\n\n          H5Gclose (subgroup_id);\n        }\n      else\n        {\n          // It seems that this block only applies to an old list type\n          // and that we shouldn't need to handle the old inline\n          // function type here.\n\n          // an HDF5 group is treated as an octave structure by\n          // default (since that preserves name information), and an\n          // octave list otherwise.\n\n          if (hdf5_check_attr (subgroup_id, \"OCTAVE_LIST\"))\n            d->tc = type_info.lookup_type (\"list\");\n          else\n            d->tc = type_info.lookup_type (\"struct\");\n\n          // check for OCTAVE_GLOBAL attribute:\n          d->global = hdf5_check_attr (subgroup_id, \"OCTAVE_GLOBAL\");\n\n          H5Gclose (subgroup_id);\n\n          try\n            {\n              retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);\n            }\n          catch (const octave::execution_exception& ee)\n            {\n              retval = -1;\n            }\n        }\n\n    }\n  else if (info.type == H5G_DATASET && ident_valid)\n    {\n      // It seems that this block only applies to an old version of\n      // Octave HDF5 files and that it is probably not important to\n      // handle the old inline function type here.\n\n      // For backwards compatibility.\n#if defined (HAVE_HDF5_18)\n      data_id = H5Dopen (group_id, name, octave_H5P_DEFAULT);\n#else\n      data_id = H5Dopen (group_id, name);\n#endif\n\n      if (data_id < 0)\n        {\n          retval = data_id;\n          goto done;\n        }\n\n      type_id = H5Dget_type (data_id);\n\n      type_class_id = H5Tget_class (type_id);\n\n      if (type_class_id == H5T_FLOAT)\n        {\n          space_id = H5Dget_space (data_id);\n\n          hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n          if (rank == 0)\n            d->tc = type_info.lookup_type (\"scalar\");\n          else\n            d->tc = type_info.lookup_type (\"matrix\");\n\n          H5Sclose (space_id);\n        }\n      else if (type_class_id == H5T_INTEGER)\n        {\n          // What integer type do we really have..\n          std::string int_typ;\n#if defined (HAVE_H5T_GET_NATIVE_TYPE)\n          // FIXME: test this code and activated with an autoconf\n          // test!! It is also incorrect for 64-bit indexing!!\n\n          switch (H5Tget_native_type (type_id, H5T_DIR_ASCEND))\n            {\n            case H5T_NATIVE_CHAR:\n              int_typ = \"int8 \";\n              break;\n\n            case H5T_NATIVE_SHORT:\n              int_typ = \"int16 \";\n              break;\n\n            case H5T_NATIVE_INT:\n            case H5T_NATIVE_LONG:\n              int_typ = \"int32 \";\n              break;\n\n            case H5T_NATIVE_LLONG:\n              int_typ = \"int64 \";\n              break;\n\n            case H5T_NATIVE_UCHAR:\n              int_typ = \"uint8 \";\n              break;\n\n            case H5T_NATIVE_USHORT:\n              int_typ = \"uint16 \";\n              break;\n\n            case H5T_NATIVE_UINT:\n            case H5T_NATIVE_ULONG:\n              int_typ = \"uint32 \";\n              break;\n\n            case H5T_NATIVE_ULLONG:\n              int_typ = \"uint64 \";\n              break;\n            }\n#else\n          hid_t int_sign = H5Tget_sign (type_id);\n\n          if (int_sign == H5T_SGN_ERROR)\n            warning (\"load: can't read '%s' (unknown datatype)\", name);\n          else\n            {\n              if (int_sign == H5T_SGN_NONE)\n                int_typ.push_back ('u');\n              int_typ.append (\"int\");\n\n              int slen = H5Tget_size (type_id);\n              if (slen < 0)\n                warning (\"load: can't read '%s' (unknown datatype)\", name);\n              else\n                {\n                  switch (slen)\n                    {\n                    case 1:\n                      int_typ.append (\"8 \");\n                      break;\n\n                    case 2:\n                      int_typ.append (\"16 \");\n                      break;\n\n                    case 4:\n                      int_typ.append (\"32 \");\n                      break;\n\n                    case 8:\n                      int_typ.append (\"64 \");\n                      break;\n\n                    default:\n                      warning (\"load: can't read '%s' (unknown datatype)\",\n                               name);\n                      int_typ = \"\";\n                      break;\n                    }\n                }\n            }\n#endif\n          if (int_typ == \"\")\n            warning (\"load: can't read '%s' (unknown datatype)\", name);\n          else\n            {\n              // Matrix or scalar?\n              space_id = H5Dget_space (data_id);\n\n              hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n              if (rank == 0)\n                int_typ.append (\"scalar\");\n              else\n                int_typ.append (\"matrix\");\n\n              d->tc = type_info.lookup_type (int_typ);\n              H5Sclose (space_id);\n            }\n        }\n      else if (type_class_id == H5T_STRING)\n        d->tc = type_info.lookup_type (\"string\");\n      else if (type_class_id == H5T_COMPOUND)\n        {\n          hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);\n          hid_t range_type = hdf5_make_range_type (H5T_NATIVE_DOUBLE);\n\n          if (hdf5_types_compatible (type_id, complex_type))\n            {\n              // read complex matrix or scalar variable\n              space_id = H5Dget_space (data_id);\n              hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n              if (rank == 0)\n                d->tc = type_info.lookup_type (\"complex scalar\");\n              else\n                d->tc = type_info.lookup_type (\"complex matrix\");\n\n              H5Sclose (space_id);\n            }\n          else if (hdf5_types_compatible (type_id, range_type))\n            {\n              // If it's not a complex, check if it's a range\n              d->tc = octave_value_typeinfo::lookup_type (\"range\");\n            }\n          else // Otherwise, just ignore it with a warning.\n            {\n              warning (\"load: can't read '%s' (unknown datatype)\", name);\n              retval = 0;  // unknown datatype; skip\n              return retval;\n            }\n\n          H5Tclose (range_type);\n          H5Tclose (complex_type);\n        }\n      else\n        {\n          warning (\"load: can't read '%s' (unknown datatype)\", name);\n          retval = 0;  // unknown datatype; skip\n          return retval;\n        }\n\n      // check for OCTAVE_GLOBAL attribute:\n      d->global = hdf5_check_attr (data_id, \"OCTAVE_GLOBAL\");\n\n      try\n        {\n          retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);\n        }\n      catch (const octave::execution_exception& ee)\n        {\n          retval = -1;\n        }\n\n      H5Tclose (type_id);\n      H5Dclose (data_id);\n    }\n\n  if (! ident_valid)\n    {\n      // should we attempt to handle invalid identifiers by converting\n      // bad characters to '_', say?\n      warning (\"load: skipping invalid identifier '%s' in hdf5 file\",\n               name);\n    }\n\ndone:\n  if (retval < 0)\n    {\n      // Must be warning.  A call to error aborts and leaves H5Giterate in\n      // a mangled state that causes segfault on exit (bug #56149).\n      warning (\"load: error while reading hdf5 item '%s'\", name);\n    }\n\n  if (retval > 0)\n    {\n      // get documentation string, if any:\n      int comment_length = H5Gget_comment (group_id, name, 0, nullptr);\n\n      if (comment_length > 1)\n        {\n          OCTAVE_LOCAL_BUFFER (char, tdoc, comment_length);\n          H5Gget_comment (group_id, name, comment_length, tdoc);\n          d->doc = tdoc;\n        }\n      else if (vname != name)\n        {\n          // the name was changed; store the original name\n          // as the documentation string:\n          d->doc = name;\n        }\n\n      // copy name (actually, vname):\n      d->name = vname;\n    }\n\n  return retval;\n}\n\n#endif\n\noctave_hdf5_err\nhdf5_read_next_data (octave_hdf5_id group_id, const char *name, void *dv)\n{\n#if defined (HAVE_HDF5)\n\n  hid_t new_id = check_hdf5_id_value (group_id, \"hdf5_read_next_data\");\n\n  return hdf5_read_next_data_internal (new_id, name, dv);\n\n#else\n  err_disabled_feature (\"hdf5_read_next_data\", \"HDF5\");\n#endif\n}\n\noctave_hdf5_err\nhdf5_h5g_iterate (octave_hdf5_id loc_id, const char *name, int *idx,\n                  void *operator_data)\n{\n#if defined (HAVE_HDF5)\n\n  hid_t new_id = check_hdf5_id_value (loc_id, \"hdf5_h5g_iterate\");\n\n  return H5Giterate (new_id, name, idx, hdf5_read_next_data_internal,\n                     operator_data);\n\n#else\n  err_disabled_feature (\"hdf5_h5g_iterate\", \"HDF5\");\n#endif\n}\n\n// Read the next Octave variable from the stream IS, which must really be an\n// hdf5_ifstream.  Return the variable value in tc, its docstring in doc, and\n// whether it is global in global.  The return value is the name of the\n// variable, or NULL if none were found or there was an error.\nstd::string\nread_hdf5_data (std::istream& is, const std::string& /* filename */,\n                bool& global, octave_value& tc, std::string& doc,\n                const string_vector& argv, int argv_idx, int argc)\n{\n#if defined (HAVE_HDF5)\n\n  octave::check_hdf5_types ();\n\n  std::string retval;\n\n  doc.clear ();\n\n  hdf5_ifstream& hs = dynamic_cast<hdf5_ifstream&> (is);\n  hdf5_callback_data d;\n\n  herr_t H5Giterate_retval = -1;\n\n  hsize_t num_obj = 0;\n#if defined (HAVE_HDF5_18)\n  hid_t group_id = H5Gopen (hs.file_id, \"/\", octave_H5P_DEFAULT);\n#else\n  hid_t group_id = H5Gopen (hs.file_id, \"/\");\n#endif\n  H5Gget_num_objs (group_id, &num_obj);\n  H5Gclose (group_id);\n\n  // For large datasets and out-of-core functionality,\n  // check if only parts of the data is requested\n  bool load_named_vars = argv_idx < argc;\n  while (load_named_vars && hs.current_item < static_cast<int> (num_obj))\n    {\n      std::vector<char> var_name;\n      bool found = false;\n      std::size_t len = 0;\n\n      len = H5Gget_objname_by_idx (hs.file_id, hs.current_item, nullptr, 0);\n      var_name.resize (len+1);\n      H5Gget_objname_by_idx (hs.file_id, hs.current_item, &var_name[0], len+1);\n\n      for (int i = argv_idx; i < argc; i++)\n        {\n          symbol_match pattern (argv[i]);\n          if (pattern.match (std::string (&var_name[0])))\n            {\n              found = true;\n              break;\n            }\n        }\n\n      if (found)\n        break;\n\n      hs.current_item++;\n    }\n\n  if (hs.current_item < static_cast<int> (num_obj))\n    H5Giterate_retval = H5Giterate (hs.file_id, \"/\", &hs.current_item,\n                                    hdf5_read_next_data_internal, &d);\n\n  if (H5Giterate_retval > 0)\n    {\n      global = d.global;\n      tc = d.tc;\n      doc = d.doc;\n    }\n  else\n    {\n      // An error occurred (H5Giterate_retval < 0),\n      // or there are no more datasets (H5Giterate_retval == 0).\n      // hdf5_read_next_data_internal has already printed a warning msg.\n    }\n\n  if (! d.name.empty ())\n    retval = d.name;\n\n  return retval;\n\n#else\n  err_disabled_feature (\"read_hdf5_data\", \"HDF5\");\n#endif\n}\n\n// Add an attribute named attr_name to loc_id (a simple scalar\n// attribute with value 1).  Return value is >= 0 on success.\noctave_hdf5_err\nhdf5_add_attr (octave_hdf5_id loc_id, const char *attr_name)\n{\n#if defined (HAVE_HDF5)\n\n  herr_t retval = 0;\n\n  hid_t as_id = H5Screate (H5S_SCALAR);\n\n  if (as_id >= 0)\n    {\n#if defined (HAVE_HDF5_18)\n      hid_t a_id = H5Acreate (loc_id, attr_name, H5T_NATIVE_UCHAR,\n                              as_id, octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n#else\n      hid_t a_id = H5Acreate (loc_id, attr_name,\n                              H5T_NATIVE_UCHAR, as_id, octave_H5P_DEFAULT);\n#endif\n      if (a_id >= 0)\n        {\n          unsigned char attr_val = 1;\n\n          retval = H5Awrite (a_id, H5T_NATIVE_UCHAR, &attr_val);\n\n          H5Aclose (a_id);\n        }\n      else\n        retval = a_id;\n\n      H5Sclose (as_id);\n    }\n  else\n    retval = as_id;\n\n  return retval;\n\n#else\n  err_disabled_feature (\"hdf5_add_attr\", \"HDF5\");\n#endif\n}\n\noctave_hdf5_err\nhdf5_add_scalar_attr (octave_hdf5_id loc_id, octave_hdf5_id type_id,\n                      const char *attr_name, void *buf)\n{\n#if defined (HAVE_HDF5)\n\n  herr_t retval = 0;\n\n  hid_t as_id = H5Screate (H5S_SCALAR);\n\n  if (as_id >= 0)\n    {\n#if defined (HAVE_HDF5_18)\n      hid_t a_id = H5Acreate (loc_id, attr_name, type_id,\n                              as_id, octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n#else\n      hid_t a_id = H5Acreate (loc_id, attr_name,\n                              type_id, as_id, octave_H5P_DEFAULT);\n#endif\n      if (a_id >= 0)\n        {\n          retval = H5Awrite (a_id, type_id, buf);\n\n          H5Aclose (a_id);\n        }\n      else\n        retval = a_id;\n\n      H5Sclose (as_id);\n    }\n  else\n    retval = as_id;\n\n  return retval;\n\n#else\n  err_disabled_feature (\"hdf5_add_scalar_attr\", \"HDF5\");\n#endif\n}\n\n// Save an empty matrix, if needed.  Returns\n//    > 0  Saved empty matrix\n//    = 0  Not an empty matrix; did nothing\n//    < 0  Error condition\nint\nsave_hdf5_empty (octave_hdf5_id loc_id, const char *name, const dim_vector& d)\n{\n#if defined (HAVE_HDF5)\n\n  hsize_t sz = d.length ();\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, sz);\n  bool empty = false;\n  hid_t space_hid = -1;\n  hid_t data_hid = -1;\n  int retval;\n  for (hsize_t i = 0; i < sz; i++)\n    {\n      dims[i] = d(i);\n      if (dims[i] < 1)\n        empty = true;\n    }\n\n  if (! empty)\n    return 0;\n\n  space_hid = H5Screate_simple (1, &sz, nullptr);\n  if (space_hid < 0) return space_hid;\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return data_hid;\n    }\n\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, dims) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n  if (retval)\n    retval = hdf5_add_attr (loc_id, \"OCTAVE_EMPTY_MATRIX\");\n\n  return (retval == 0 ? 1 : retval);\n\n#else\n  err_disabled_feature (\"save_hdf5_empty\", \"HDF5\");\n#endif\n}\n\n// Load an empty matrix, if needed.  Returns\n//    > 0  loaded empty matrix, dimensions returned\n//    = 0  Not an empty matrix; did nothing\n//    < 0  Error condition\nint\nload_hdf5_empty (octave_hdf5_id loc_id, const char *name, dim_vector& d)\n{\n#if defined (HAVE_HDF5)\n\n  if (! hdf5_check_attr (loc_id, \"OCTAVE_EMPTY_MATRIX\"))\n    return 0;\n\n  hsize_t hdims, maxdims;\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_id = H5Dget_space (data_hid);\n  H5Sget_simple_extent_dims (space_id, &hdims, &maxdims);\n  int retval;\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, hdims);\n\n  retval = H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                    octave_H5P_DEFAULT, dims);\n  if (retval >= 0)\n    {\n      d.resize (hdims);\n      for (hsize_t i = 0; i < hdims; i++)\n        d(i) = dims[i];\n    }\n\n  H5Sclose (space_id);\n  H5Dclose (data_hid);\n\n  return (retval == 0 ? hdims : retval);\n\n#else\n  err_disabled_feature (\"load_hdf5_empty\", \"HDF5\");\n#endif\n}\n\n// save_type_to_hdf5 is not currently used, since hdf5 doesn't yet support\n// automatic float<->integer conversions:\n\n// return the HDF5 type id corresponding to the Octave save_type\n\noctave_hdf5_id\nsave_type_to_hdf5 (save_type st)\n{\n#if defined (HAVE_HDF5)\n#  if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS)\n\n  switch (st)\n    {\n    case LS_U_CHAR:\n      return H5T_NATIVE_UCHAR;\n\n    case LS_U_SHORT:\n      return H5T_NATIVE_USHORT;\n\n    case LS_U_INT:\n      return H5T_NATIVE_UINT;\n\n    case LS_CHAR:\n      return H5T_NATIVE_CHAR;\n\n    case LS_SHORT:\n      return H5T_NATIVE_SHORT;\n\n    case LS_INT:\n      return H5T_NATIVE_INT;\n\n    case LS_FLOAT:\n      return H5T_NATIVE_FLOAT;\n\n    case LS_DOUBLE:\n    default:\n      return H5T_NATIVE_DOUBLE;\n    }\n\n#  else\n\n  octave_unused_parameter (st);\n\n  return -1;\n\n#  endif\n\n#else\n\n  octave_unused_parameter (st);\n\n  err_disabled_feature (\"save_type_to_hdf5\", \"HDF5\");\n\n#endif\n}\n\n// Add the data from TC to the HDF5 location loc_id, which could\n// be either a file or a group within a file.  Return true if\n// successful.  This function calls itself recursively for lists\n// (stored as HDF5 groups).\n\nbool\nadd_hdf5_data (octave_hdf5_id loc_id, const octave_value& tc_in,\n               const std::string& name, const std::string& doc,\n               bool mark_global, bool save_as_floats)\n{\n#if defined (HAVE_HDF5)\n\n  octave_value tc;\n  if (tc_in.is_classdef_object ())\n    {\n      warning_with_id (\"Octave:save:classdef:unsupported\",\n                       \"Saving classdef objects is not supported.  \"\n                       \"Attempting to save '%s' as struct.\",\n                       name.c_str ());\n      tc = tc_in.classdef_object_value ()->map_value (false, false);\n    }\n  else\n    tc = tc_in;\n\n  hsize_t dims[3];\n  hid_t type_id, space_id, data_id, data_type_id;\n  type_id = space_id = data_id = data_type_id = -1;\n\n  bool retval = false;\n  octave_value val = tc;\n  // FIXME: diagonal & permutation matrices currently don't know how to save\n  // themselves, so we convert them first to normal matrices using A = A(:,:).\n  // This is a temporary hack.\n  if (val.is_diag_matrix () || val.is_perm_matrix ()\n      || val.type_id () == octave_lazy_index::static_type_id ())\n    val = val.full_value ();\n\n  std::string t = val.type_name ();\n#if defined (HAVE_HDF5_18)\n  data_id = H5Gcreate (loc_id, name.c_str (), octave_H5P_DEFAULT,\n                       octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n#else\n  data_id = H5Gcreate (loc_id, name.c_str (), 0);\n#endif\n  if (data_id < 0)\n    goto error_cleanup;\n\n  // attach the type of the variable\n  type_id = H5Tcopy (H5T_C_S1);\n  H5Tset_size (type_id, t.length () + 1);\n  if (type_id < 0)\n    goto error_cleanup;\n\n  dims[0] = 0;\n  space_id = H5Screate_simple (0, dims, nullptr);\n  if (space_id < 0)\n    goto error_cleanup;\n#if defined (HAVE_HDF5_18)\n  data_type_id = H5Dcreate (data_id, \"type\", type_id, space_id,\n                            octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                            octave_H5P_DEFAULT);\n#else\n  data_type_id = H5Dcreate (data_id, \"type\", type_id, space_id,\n                            octave_H5P_DEFAULT);\n#endif\n  if (data_type_id < 0\n      || H5Dwrite (data_type_id, type_id, octave_H5S_ALL, octave_H5S_ALL,\n                   octave_H5P_DEFAULT, t.c_str ()) < 0)\n    goto error_cleanup;\n\n  // Now call the real function to save the variable\n  retval = val.save_hdf5 (data_id, \"value\", save_as_floats);\n\n  // attach doc string as comment:\n  if (retval && doc.length () > 0\n      && H5Gset_comment (loc_id, name.c_str (), doc.c_str ()) < 0)\n    retval = false;\n\n  // if it's global, add an attribute \"OCTAVE_GLOBAL\" with value 1\n  if (retval && mark_global)\n    retval = hdf5_add_attr (data_id, \"OCTAVE_GLOBAL\") >= 0;\n\n  // We are saving in the new variable format, so mark it\n  if (retval)\n    retval = hdf5_add_attr (data_id, \"OCTAVE_NEW_FORMAT\") >= 0;\n\nerror_cleanup:\n\n  if (data_type_id >= 0)\n    H5Dclose (data_type_id);\n\n  if (type_id >= 0)\n    H5Tclose (type_id);\n\n  if (space_id >= 0)\n    H5Sclose (space_id);\n\n  if (data_id >= 0)\n    H5Gclose (data_id);\n\n  if (! retval)\n    error (\"save: error while writing '%s' to hdf5 file\", name.c_str ());\n\n  return retval;\n\n#else\n  err_disabled_feature (\"add_hdf5_data\", \"HDF5\");\n#endif\n}\n\n// Write data from TC in HDF5 (binary) format to the stream OS,\n// which must be an hdf5_ofstream, returning true on success.\n\nbool\nsave_hdf5_data (std::ostream& os, const octave_value& tc,\n                const std::string& name, const std::string& doc,\n                bool mark_global, bool save_as_floats)\n{\n#if defined (HAVE_HDF5)\n\n  octave::check_hdf5_types ();\n\n  hdf5_ofstream& hs = dynamic_cast<hdf5_ofstream&> (os);\n\n  return add_hdf5_data (hs.file_id, tc, name, doc,\n                        mark_global, save_as_floats);\n\n#else\n  err_disabled_feature (\"save_hdf5_data\", \"HDF5\");\n#endif\n}\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-hdf5.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ls_hdf5_h)\n#define octave_ls_hdf5_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n#include \"oct-hdf5-types.h\"\n#include \"ov.h\"\n\n// first, we need to define our own dummy stream subclass, since\n// HDF5 needs to do its own file i/o\n\n// hdf5_fstreambase is used for both input and output streams, modeled\n// on the fstreambase class in <fstream.h>\n\nclass hdf5_fstreambase : virtual public std::ios\n{\npublic:\n\n  // HDF5 uses an \"id\" to refer to an open file\n  octave_hdf5_id file_id;\n\n  // keep track of current item index in the file\n  int current_item;\n\n  hdf5_fstreambase () : file_id (-1), current_item () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (hdf5_fstreambase)\n\n  ~hdf5_fstreambase () { close (); }\n\n  OCTINTERP_API hdf5_fstreambase (const char *name, int mode,\n                                  int /* prot */ = 0);\n\n  OCTINTERP_API void close ();\n\n  OCTINTERP_API void open (const char *name, int mode, int);\n\n  OCTINTERP_API void open_create (const char *name, int mode);\n};\n\n// input and output streams, subclassing istream and ostream\n// so that we can pass them for stream parameters in the functions below.\n\nclass hdf5_ifstream : public hdf5_fstreambase, public std::istream\n{\npublic:\n\n  hdf5_ifstream () : hdf5_fstreambase (), std::istream (nullptr) { }\n\n  hdf5_ifstream (const char *name, int mode = std::ios::in | std::ios::binary,\n                 int prot = 0)\n    : hdf5_fstreambase (name, mode, prot), std::istream (nullptr) { }\n\n  void open (const char *name, int mode = std::ios::in | std::ios::binary,\n             int prot = 0)\n  { hdf5_fstreambase::open (name, mode, prot); }\n};\n\nclass hdf5_ofstream : public hdf5_fstreambase, public std::ostream\n{\npublic:\n\n  hdf5_ofstream () : hdf5_fstreambase (), std::ostream (nullptr) { }\n\n  hdf5_ofstream (const char *name, int mode = std::ios::out | std::ios::binary,\n                 int prot = 0)\n    : hdf5_fstreambase (name, mode, prot), std::ostream (nullptr) { }\n\n  void open (const char *name, int mode = std::ios::out | std::ios::binary,\n             int prot = 0)\n  { hdf5_fstreambase::open (name, mode, prot); }\n};\n\n// Callback data structure for passing data to hdf5_read_next_data, below.\n\nstruct hdf5_callback_data\n{\npublic:\n\n  hdf5_callback_data ()\n    : name (), global (false), tc (), doc () { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (hdf5_callback_data)\n\n  // the following fields are set by hdf5_read_data on successful return:\n\n  // the name of the variable\n  std::string name;\n\n  // whether it is global\n  bool global;\n\n  // the value of the variable, in Octave form\n  octave_value tc;\n\n  // a documentation string (NULL if none)\n  std::string doc;\n};\n\nextern OCTINTERP_API octave_hdf5_id\nsave_type_to_hdf5 (save_type st);\n\nextern OCTINTERP_API octave_hdf5_id\nhdf5_make_complex_type (octave_hdf5_id num_type);\n\nextern OCTINTERP_API bool\nhdf5_types_compatible (octave_hdf5_id t1, octave_hdf5_id t2);\n\nextern OCTINTERP_API octave_hdf5_err\nhdf5_read_next_data (octave_hdf5_id group_id, const char *name, void *dv);\n\nextern OCTINTERP_API octave_hdf5_err\nhdf5_h5g_iterate (octave_hdf5_id loc_id, const char *name, int *idx,\n                  void *operator_data);\n\nextern OCTINTERP_API bool\nadd_hdf5_data (octave_hdf5_id loc_id, const octave_value& tc,\n               const std::string& name, const std::string& doc,\n               bool mark_global, bool save_as_floats);\n\nextern OCTINTERP_API int\nsave_hdf5_empty (octave_hdf5_id loc_id, const char *name, const dim_vector& d);\n\nextern OCTINTERP_API int\nload_hdf5_empty (octave_hdf5_id loc_id, const char *name, dim_vector& d);\n\nextern OCTINTERP_API std::string\nread_hdf5_data (std::istream& is, const std::string& filename, bool& global,\n                octave_value& tc, std::string& doc,\n                const string_vector& argv, int argv_idx, int argc);\n\nextern OCTINTERP_API bool\nsave_hdf5_data (std::ostream& os, const octave_value& tc,\n                const std::string& name, const std::string& doc,\n                bool mark_global, bool save_as_floats);\n\nextern OCTINTERP_API bool\nhdf5_check_attr (octave_hdf5_id loc_id, const char *attr_name);\n\nextern OCTINTERP_API bool\nhdf5_get_scalar_attr (octave_hdf5_id loc_id, octave_hdf5_id type_id,\n                      const char *attr_name, void *buf);\n\nextern OCTINTERP_API octave_hdf5_err\nhdf5_add_attr (octave_hdf5_id loc_id, const char *attr_name);\n\n\nextern OCTINTERP_API octave_hdf5_err\nhdf5_add_scalar_attr (octave_hdf5_id loc_id, octave_hdf5_id type_id,\n                      const char *attr_name, void *buf);\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-mat-ascii.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cctype>\n\n#include <istream>\n#include <ostream>\n#include <sstream>\n#include <string>\n\n#include \"byte-swap.h\"\n#include \"dMatrix.h\"\n#include \"data-conv.h\"\n#include \"file-ops.h\"\n#include \"glob-match.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"lex.h\"\n#include \"load-save.h\"\n#include \"ls-ascii-helper.h\"\n#include \"ls-mat-ascii.h\"\n#include \"oct-map.h\"\n#include \"ov-cell.h\"\n#include \"ov.h\"\n#include \"pager.h\"\n#include \"sysdep.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"version.h\"\n\nstatic std::string\nget_mat_data_input_line (std::istream& is)\n{\n  std::string retval;\n\n  bool have_data = false;\n\n  do\n    {\n      retval = \"\";\n\n      char c;\n      while (is.get (c))\n        {\n          if (c == '\\n' || c == '\\r')\n            {\n              is.putback (c);\n              octave::skip_preceeding_newline (is);\n              break;\n            }\n\n          if (c == '%' || c == '#')\n            {\n              octave::skip_until_newline (is, false);\n              break;\n            }\n\n          if (! is.eof ())\n            {\n              if (! have_data && c != ' ' && c != '\\t')\n                have_data = true;\n\n              retval += c;\n            }\n        }\n    }\n  while (! (have_data || is.eof () || is.fail ()));\n\n  return retval;\n}\n\nstatic void\nget_lines_and_columns (std::istream& is,\n                       octave_idx_type& nr, octave_idx_type& nc,\n                       const std::string& filename = \"\",\n                       bool quiet = false, bool check_numeric = false)\n{\n  std::streampos pos = is.tellg ();\n\n  int file_line_number = 0;\n\n  nr = 0;\n  nc = 0;\n\n  while (is)\n    {\n      octave_quit ();\n\n      std::string buf = get_mat_data_input_line (is);\n\n      file_line_number++;\n\n      std::size_t beg = buf.find_first_not_of (\", \\t\");\n\n      // If we see a CR as the last character in the buffer, we had a\n      // CRLF pair as the line separator.  Any other CR in the text\n      // will not be considered as whitespace.\n\n      if (beg != std::string::npos && buf[beg] == '\\r'\n          && beg == buf.length () - 1)\n        {\n          // We had a blank line ending with a CRLF.  Handle it the\n          // same as an empty line.\n          beg = std::string::npos;\n        }\n\n      octave_idx_type tmp_nc = 0;\n\n      while (beg != std::string::npos)\n        {\n          tmp_nc++;\n\n          std::size_t end = buf.find_first_of (\", \\t\", beg);\n\n          if (end != std::string::npos)\n            {\n              if (check_numeric)\n                {\n                  std::istringstream tmp_stream (buf.substr (beg, end-beg));\n\n                  octave::read_value<double> (tmp_stream);\n\n                  if (tmp_stream.fail ())\n                    {\n                      if (! quiet)\n                        error (\"load: %s: non-numeric data found near line %d\",\n                               filename.c_str (), file_line_number);\n\n                      nr = 0;\n                      nc = 0;\n\n                      goto done;\n                    }\n                }\n\n              beg = buf.find_first_not_of (\", \\t\", end);\n\n              if (beg == std::string::npos\n                  || (buf[beg] == '\\r' && beg == buf.length () - 1))\n                {\n                  // We had a line with trailing spaces and ending with a CRLF,\n                  // so this should look like EOL, not a new column.\n                  break;\n                }\n            }\n          else\n            break;\n        }\n\n      if (tmp_nc > 0)\n        {\n          if (nc == 0)\n            {\n              nc = tmp_nc;\n              nr++;\n            }\n          else if (nc == tmp_nc)\n            nr++;\n          else\n            {\n              if (! quiet)\n                error (\"load: %s: inconsistent number of columns near line %d\",\n                       filename.c_str (), file_line_number);\n\n              nr = 0;\n              nc = 0;\n\n              goto done;\n            }\n        }\n    }\n\n  if (! quiet && (nr == 0 || nc == 0))\n    error (\"load: file '%s' seems to be empty!\", filename.c_str ());\n\ndone:\n\n  is.clear ();\n  is.seekg (pos);\n}\n\n// Extract a matrix from a file of numbers only.\n//\n// Comments are not allowed.  The file should only have numeric values.\n//\n// Reads the file twice.  Once to find the number of rows and columns,\n// and once to extract the matrix.\n//\n// FILENAME is used for error messages.\n//\n// This format provides no way to tag the data as global.\n\nstd::string\nread_mat_ascii_data (std::istream& is, const std::string& filename,\n                     octave_value& tc)\n{\n  std::string varname;\n\n  std::size_t pos = filename.rfind ('/');\n\n  if (pos != std::string::npos)\n    varname = filename.substr (pos+1);\n  else\n    varname = filename;\n\n  pos = varname.rfind ('.');\n\n  if (pos != std::string::npos)\n    varname = varname.substr (0, pos);\n\n  std::size_t len = varname.length ();\n  for (std::size_t i = 0; i < len; i++)\n    {\n      char c = varname[i];\n      if (! (isalnum (c) || c == '_'))\n        varname[i] = '_';\n    }\n\n  if (octave::iskeyword (varname) || ! isalpha (varname[0]))\n    varname.insert (0, \"X\");\n\n  if (! octave::valid_identifier (varname))\n    error (\"load: unable to convert filename '%s' to valid identifier\",\n           filename.c_str ());\n\n  octave_idx_type nr = 0;\n  octave_idx_type nc = 0;\n\n  octave_idx_type total_count = 0;\n\n  get_lines_and_columns (is, nr, nc, filename);\n\n  octave_quit ();\n\n  if (nr <= 0 || nc <= 0)\n    error (\"load: unable to extract matrix size from file '%s'\",\n           filename.c_str ());\n\n  Matrix tmp (nr, nc);\n\n  double d;\n  for (octave_idx_type i = 0; i < nr; i++)\n    {\n      std::string buf = get_mat_data_input_line (is);\n\n      std::istringstream tmp_stream (buf);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          d = octave::read_value<double> (tmp_stream);\n\n          if (! tmp_stream && ! tmp_stream.eof ())\n            error (\"load: failed to read matrix from file '%s'\",\n                   filename.c_str ());\n\n          tmp.elem (i, j) = d;\n          total_count++;\n\n          // Skip whitespace and commas.\n          char c;\n          while (1)\n            {\n              tmp_stream >> c;\n\n              if (! tmp_stream)\n                break;\n\n              if (! (c == ' ' || c == '\\t' || c == ','))\n                {\n                  tmp_stream.putback (c);\n                  break;\n                }\n            }\n\n          if (tmp_stream.eof ())\n            break;\n        }\n    }\n\n  if (! is && ! is.eof ())\n    error (\"load: failed to read matrix from file '%s'\", filename.c_str ());\n\n  // FIXME: not sure this is best, but it works.\n  if (is.eof ())\n    is.clear ();\n\n  octave_idx_type expected = nr * nc;\n\n  if (expected != total_count)\n    error (\"load: expected %\" OCTAVE_IDX_TYPE_FORMAT \" elements, found \"\n           \"%\" OCTAVE_IDX_TYPE_FORMAT, expected, total_count);\n\n  tc = tmp;\n\n  return varname;\n}\n\nbool\nsave_mat_ascii_data (std::ostream& os, const octave_value& val,\n                     int precision, bool tabs)\n{\n  bool success = true;\n\n  if (val.iscomplex ())\n    warning (\"save: omitting imaginary part for ASCII file\");\n\n  if (val.ndims () > 2)\n    {\n      warning (\"save: skipping variable which is not a 2-D matrix\");\n      return true;\n    }\n\n  Matrix m;\n\n  try\n    {\n      m = val.matrix_value (true);\n    }\n  catch (const octave::execution_exception&)\n    {\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      interp.recover_from_exception ();\n\n      success = false;\n    }\n\n  if (success)\n    {\n      long old_precision = os.precision ();\n\n      os.precision (precision);\n\n      std::ios::fmtflags oflags\n        = os.flags (static_cast<std::ios::fmtflags> (std::ios::scientific));\n\n      if (tabs)\n        {\n          for (octave_idx_type i = 0; i < m.rows (); i++)\n            {\n              for (octave_idx_type j = 0; j < m.cols (); j++)\n                {\n                  // Omit leading tabs.\n                  if (j != 0) os << '\\t';\n                  octave::write_value<double> (os, m(i, j));\n                }\n              os << \"\\n\";\n            }\n        }\n      else\n        os << m;\n\n      // Restore format\n      os.flags (oflags);\n      os.precision (old_precision);\n    }\n\n  return (os && success);\n}\n\nbool\nlooks_like_mat_ascii_file (std::istream& is, const std::string& filename)\n{\n  bool retval = false;\n  octave_idx_type nr = 0;\n  octave_idx_type nc = 0;\n\n  get_lines_and_columns (is, nr, nc, filename, true, true);\n  retval = (nr != 0 && nc != 0);\n\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/corefcn/ls-mat-ascii.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ls_mat_ascii_h)\n#define octave_ls_mat_ascii_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\nclass octave_value;\n\nextern OCTINTERP_API std::string\nread_mat_ascii_data (std::istream& is, const std::string& filename,\n                     octave_value& tc);\n\nextern OCTINTERP_API bool\nsave_mat_ascii_data (std::ostream& os, const octave_value& val_arg,\n                     int precision, bool tabs = false);\n\nextern OCTINTERP_API bool\nlooks_like_mat_ascii_file (std::istream& is, const std::string& filename);\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-mat-subsys.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"byte-swap.h\"\n\n#include \"cdef-class.h\"\n#include \"cdef-utils.h\"\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"load-save.h\"\n#include \"ls-mat-subsys.h\"\n#include \"ov-classdef.h\"\n\nstatic uint32_t MIN_FILEWRAPPER_VERSION = 2;\nstatic uint32_t MCOS_MAGIC_NUMBER = 0xDD000000;\n\nstatic inline bool\nis_valid_mcos_object (const octave_value& metadata)\n{\n  // Metadata must be N X 1 uint32 array, N>=3\n  if (! metadata.is_uint32_type ())\n    {\n      if (metadata.isstruct () && metadata.is_scalar_type ())\n        {\n          // Metadata for enumeration class objects are stored as structs\n          // with a field \"EnumerationInstanceTag\" set to 0xDD000000.\n\n          const octave_scalar_map& md = metadata.scalar_map_value ();\n          if (md.contains (\"EnumerationInstanceTag\"))\n            {\n              const octave_value& enum_tag = md.contents (\"EnumerationInstanceTag\");\n              if (enum_tag.is_uint32_type () && enum_tag.is_scalar_type ()\n                  && static_cast<uint32_t> (enum_tag.uint32_scalar_value ())\n                       == MCOS_MAGIC_NUMBER)\n                warning_with_id (\"Octave:load:classdef-not-supported\",\n                    \"load: MATLAB enumeration class object cannot be loaded.  \"\n                    \"Returning as %s\",\n                    metadata.class_name ().c_str ());\n            }\n        }\n\n      return false;\n    }\n\n  const uint32NDArray& md = metadata.uint32_array_value ();\n  if (md.ndims () != 2)\n    return false;\n\n  dim_vector dv = md.dims ();\n  if (dv(1) != 1)\n    return false;\n\n  if (md.numel () < 3)\n    return false;\n\n  // first value must be 0xDD000000\n  if (static_cast<uint32_t> (md(0, 0)) != MCOS_MAGIC_NUMBER)\n    return false;\n\n  return true;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic octave_value\nsearch_mcos_classdef_objects (const octave_value& val, bool save_mode)\n{\n  if (save_mode && val.is_classdef_object ())\n    {\n      subsystem_handler *sh = octave::__get_load_save_system__ ().get_subsystem_handler ();\n      return octave_value (sh->set_mcos_object_metadata (val));\n    }\n  else if (! save_mode && is_valid_mcos_object (val))\n    {\n      return load_mcos_object (val);\n    }\n\n  // iterate through cell arrays\n  if (val.iscell ())\n    {\n      Cell cv = val.cell_value ();\n      for (octave_idx_type i = 0; i < cv.numel (); i++)\n        cv(i) = search_mcos_classdef_objects (cv(i), save_mode);\n\n      return cv;\n    }\n\n  // iterate through struct arrays\n  if (val.isstruct ())\n    {\n      if (val.is_scalar_type ())\n        {\n          octave_scalar_map mv = val.scalar_map_value ();\n          for (auto it = mv.begin (); it != mv.end (); ++it)\n            {\n              std::string field_name = mv.key (it);\n              octave_value field_val = mv.contents (it);\n              mv.assign (field_name,\n                         search_mcos_classdef_objects (field_val, save_mode));\n            }\n          return octave_value (mv);\n        }\n      else\n        {\n          octave_map mv = val.map_value ();\n          string_vector field_names = mv.fieldnames ();\n\n          for (octave_idx_type field_idx = 0; field_idx < field_names.numel ();\n               field_idx++)\n            {\n              std::string field_name = field_names[field_idx];\n              Cell field_values = mv.contents (field_name);\n\n              for (octave_idx_type i = 0; i < field_values.numel (); i++)\n                field_values(i) = search_mcos_classdef_objects (field_values(i),\n                                                                save_mode);\n\n              mv.assign (field_name, field_values);\n            }\n\n          return octave_value (mv);\n        }\n    }\n\n  return val;\n}\n\noctave_value\nload_mcos_object (const octave_value& objmetadata, bool as_struct)\n{\n  // Object metadata is a Nx1 uint32 array with the following structure:\n  // [0xDD000000, objdims, dim1, dim2, ..., dimN,\n  // object_id1, object_id2, ..., object_idN,\n  // class_id]\n\n  octave::load_save_system& lss = octave::__get_load_save_system__ ();\n  octave::subsystem_handler *sh = lss.get_subsystem_handler ();\n\n  const octave_uint32 *dt = objmetadata.uint32_array_value ().data ();\n  if (static_cast<uint32_t>(dt[0]) != MCOS_MAGIC_NUMBER)\n    {\n      warning_with_id (\"Octave:load:invalid-mcos-object\",\n                       \"load: invalid MCOS object metadata.  Returning as %s\",\n                       objmetadata.class_name ().c_str ());\n      return objmetadata;\n    }\n  int32_t objdims = dt[1];\n\n  dim_vector dv;\n  dv.resize (objdims);\n  for (octave_idx_type i = 0; i < objdims; i++)\n    dv(i) = dt[2 + i];\n\n  int nobjects = dv.numel ();\n  std::vector<std::tuple<octave_map, uint32_t, bool>> m (nobjects);\n\n  for (octave_idx_type i = 0; i < nobjects; i++)\n    std::get<uint32_t> (m[i]) = dt[2 + objdims + i];\n\n  uint32_t class_id = dt[2 + objdims + nobjects];\n  std::string classname = sh->get_class_name (class_id);\n\n  bool skip_constructor = true;\n  octave::cdef_class cls;\n  if (! as_struct)\n    {\n      // \"function_handle_workspace\" objects contain data of the workspace\n      // context of function handles.  Return it as structure.\n      // FIXME: Add compatible implementation of this class.\n      if (classname == \"function_handle_workspace\")\n        as_struct = true;\n      else\n        {\n          cls = octave::lookup_class (classname, false, true);\n          if (! cls.ok ())\n            {\n              warning_with_id (\"Octave:load:classdef-not-found\",\n                               \"load: classdef not found.  Element loaded as %s\",\n                               objmetadata.class_name ().c_str ());\n\n              return objmetadata;\n            }\n\n          skip_constructor = ! cls.get (\"ConstructOnLoad\").bool_value ();\n        }\n    }\n\n  for (octave_idx_type i = 0; i < nobjects; i++)\n    {\n      uint32_t obj_id = std::get<uint32_t> (m[i]);\n      if (! obj_id)\n        {\n          // FIXME: Properly support deleted objects.\n          warning_with_id (\"Octave:load:deleted-object\",\n                           \"load: object of class '%s' was deleted in MATLAB \"\n                           \"and cannot be loaded.  Returning metadata\",\n                           classname.c_str ());\n          return objmetadata;\n        }\n      if (! lss.is_mcos_object_cache_entry (obj_id))\n        {\n          if (! as_struct)\n            {\n              // put (scalar) object in cache for this object ID\n              octave_value ovc\n                = cls.construct (octave_value_list (), skip_constructor);\n              lss.set_mcos_object_cache_entry (obj_id, ovc);\n            }\n\n          auto [saveobj_type, obj_type_id, obj_dep_id]\n            = sh->get_object_dependencies (obj_id);\n\n          std::get<octave_map> (m[i])\n            = sh->get_object_properties (obj_type_id, class_id, saveobj_type,\n                                         as_struct);\n          std::get<bool> (m[i]) = saveobj_type;\n\n          if (! as_struct && sh->check_dyn_props (obj_dep_id))\n            warning_with_id (\"Octave:load:dynamic-properties-not-supported\",\n                             \"load: dynamic properties cannot be loaded and \"\n                             \"will be skipped \");\n        }\n    }\n\n  if (as_struct)\n    {\n      OCTAVE_LOCAL_BUFFER (octave_map, map_list, nobjects);\n\n      octave_idx_type j = 0;\n      for (octave_idx_type i = 0; i < nobjects; i++)\n        {\n          if ((std::get<octave_map> (m[i])).isfield (\"any\"))\n            {\n              // object was saved with overloaded \"saveobj\" method that\n              // returns a different type\n              octave_value any_val\n                = ((std::get<octave_map> (m[i])).getfield (\"any\"))(0);\n              // FIXME: This is specifically for loading\n              //        \"function_handle_workspace\" objects saved with MATLAB.\n              //        Do we need to be more generic?\n              if (any_val.iscell () && any_val.numel () > 1)\n                {\n                  Cell any_cell = any_val.cell_value ();\n                  map_list[j] = any_cell(1).scalar_map_value ();\n                }\n            }\n          else\n            map_list[j] = std::get<octave_map> (m[i]);\n\n          j++;\n        }\n\n      if (j == 1)\n        return map_list[0];\n      else\n        return octave_map::cat (-1, nobjects, map_list);\n    }\n  else\n    {\n      // create object with loaded data\n      octave_value obj = cls.construct (octave_value_list (), true);\n      octave_classdef *objdef = obj.classdef_object_value ();\n      objdef->loadobj (m, dv);\n\n      return obj;\n    }\n}\n\nbool\nsubsystem_handler::read_mat_subsystem (const octave_value& subsys, bool swap)\n{\n  if (! subsys.isstruct ())\n    return false;\n\n  const octave_scalar_map& subsys_map = subsys.scalar_map_value ();\n\n  if (subsys_map.contains (\"MCOS\"))\n    {\n      const octave_value& mcos_data = subsys_map.contents (\"MCOS\");\n      if (mcos_data.is_defined () && ! mcos_data.isempty ()\n          && ! read_filewrapper (mcos_data.cell_value (), swap))\n        return false;\n    }\n\n  if (subsys_map.contains (\"java\"))\n    {\n      const octave_value& java_data = subsys_map.contents (\"java\");\n      if (java_data.is_defined () && ! java_data.isempty ())\n        m_type_java = java_data;\n    }\n\n  if (subsys_map.contains (\"handle\"))\n    {\n      const octave_value& handle_data = subsys_map.contents (\"handle\");\n      if (handle_data.is_defined () && ! handle_data.isempty ())\n        m_type_handle = handle_data;\n    }\n\n  return true;\n}\n\nbool\nsubsystem_handler::read_filewrapper (const Cell& fwrap_data, bool swap)\n{\n  const octave_value& fwrap_metadata = fwrap_data(0, 0);\n  if (! fwrap_metadata.is_uint8_type ())\n    return false;\n\n  const uint8NDArray& fwrap_metadata_array = fwrap_metadata.uint8_array_value ();\n\n  // check version compatibility\n  uint32_t version;\n  std::memcpy (&version, fwrap_metadata_array.data (), sizeof (version));\n  if (swap)\n    swap_bytes<4> (&version, 1);\n  if (version > m_filewrapper_version || version < MIN_FILEWRAPPER_VERSION)\n    error (\"load: filewrapper version %u is not supported.  MCOS objects cannot be loaded.\",\n           version);\n\n  // get number of unique property names and class names\n  std::memcpy (&m_num_names, fwrap_metadata_array.data () + 4,\n               sizeof (m_num_names));\n  if (swap)\n    swap_bytes<4> (&m_num_names, 1);\n\n  // read region offsets\n  for (octave_idx_type i = 0; i < 8; i++)\n    {\n      std::memcpy (m_region_offsets.data () + i,\n                   fwrap_metadata_array.data () + 8 + i * 4,\n                   sizeof (int32_t));\n      if (swap)\n        swap_bytes<4> (&m_region_offsets[i], 1);\n    }\n\n  // read property names and class names\n  // stored as list of null terminated integers\n  m_prop_class_names.resize (m_num_names);\n  size_t name_offset = 40;\n  for (uint32_t i = 0; i < m_num_names; i++)\n    {\n      size_t start_offset = name_offset;\n      while (static_cast<uint8_t> (fwrap_metadata_array(name_offset)) != 0)\n        name_offset++;\n\n      std::string name;\n      for (size_t j = start_offset; j < name_offset; j++)\n        name += static_cast<char> (fwrap_metadata_array(j));\n\n      m_prop_class_names[i] = name;\n      name_offset++;  // skip the null terminator\n    }\n\n  // read property values\n  // Property values are stored in fwrap_data(2:end-X) where:\n  // X = [1,2,3] for Filewrapper version [2,3,4]\n  int prop_vals_idx_end = version - 1;  // simple hack for above mapping\n  // ignore first 2 entries as well\n  octave_idx_type prop_vals_size = fwrap_data.numel () - prop_vals_idx_end - 2;\n  if (prop_vals_size > 0)\n    {\n      m_fwrap_prop_vals.resize (prop_vals_size);\n      for (octave_idx_type i = 0; i < prop_vals_size; i++)\n        m_fwrap_prop_vals[i] = fwrap_data(2 + i);\n    }\n  else\n    m_fwrap_prop_vals.clear ();  // mark undefined\n\n  // Default values are stored in fwrap_data(end).\n  m_fwrap_default_vals = fwrap_data(fwrap_data.numel () - 1).cell_value ();\n\n  // read m_class_name_refs\n  // contains list of indices to classname and namespace qualifier (if any) for\n  // each class\n  size_t class_name_size = (m_region_offsets[1] - m_region_offsets[0]) / 4;\n  m_class_name_refs.resize (class_name_size);\n  for (size_t i = 0; i < class_name_size; i++)\n    {\n      uint32_t val;\n      std::memcpy (&val,\n                   fwrap_metadata_array.data () + m_region_offsets[0] + i * 4,\n                   sizeof (val));\n      if (swap)\n        swap_bytes<4> (&val, 1);\n      m_class_name_refs[i] = val;\n    }\n\n  // read m_object_id_refs\n  // contains class ID, object_type_ID, dependency_ID for each object\n  size_t object_id_size = (m_region_offsets[3] - m_region_offsets[2]) / 4;\n  m_object_id_refs.resize (object_id_size);\n  for (size_t i = 0; i < object_id_size; i++)\n    {\n      uint32_t val;\n      std::memcpy (&val,\n                   fwrap_metadata_array.data () + m_region_offsets[2] + i * 4,\n                   sizeof (val));\n      if (swap)\n        swap_bytes<4> (&val, 1);\n      m_object_id_refs[i] = val;\n    }\n\n  // read m_object_prop_fields\n  // contains blocks of property name indexes and values for each object\n  size_t object_prop_size = (m_region_offsets[4] - m_region_offsets[3]) / 4;\n  m_object_prop_fields.resize (object_prop_size);\n  for (size_t i = 0; i < object_prop_size; i++)\n    {\n      uint32_t val;\n      std::memcpy (&val,\n                   fwrap_metadata_array.data () + m_region_offsets[3] + i * 4,\n                   sizeof (val));\n      if (swap)\n        swap_bytes<4> (&val, 1);\n      m_object_prop_fields[i] = val;\n    }\n\n  // read m_saveobj_prop_fields\n  // contains value index for each object with custom saveobj return types\n  size_t saveobj_prop_size = (m_region_offsets[2] - m_region_offsets[1]) / 4;\n  m_saveobj_prop_fields.resize (saveobj_prop_size);\n  for (size_t i = 0; i < saveobj_prop_size; i++)\n    {\n      uint32_t val;\n      std::memcpy (&val,\n                   fwrap_metadata_array.data () + m_region_offsets[1] + i * 4,\n                   sizeof (val));\n      if (swap)\n        swap_bytes<4> (&val, 1);\n      m_saveobj_prop_fields[i] = val;\n    }\n\n  // read m_dynamic_prop_refs\n  // lists dynamic properties (if any) for each object dependency ID\n  size_t dynamic_prop_size = (m_region_offsets[5] - m_region_offsets[4]) / 4;\n  m_dynamic_prop_refs.resize (dynamic_prop_size);\n  for (size_t i = 0; i < dynamic_prop_size; i++)\n    {\n      uint32_t val;\n      std::memcpy (&val,\n                   fwrap_metadata_array.data () + m_region_offsets[4] + i * 4,\n                   sizeof (val));\n      if (swap)\n        swap_bytes<4> (&val, 1);\n      m_dynamic_prop_refs[i] = val;\n    }\n\n  return true;\n}\n\nstd::string\nsubsystem_handler::get_class_name (const uint32_t class_id)\n{\n  // (namespace_idx, classname_idx, X, X)\n  // ordered by class ID\n\n  constexpr int block_size = 4;\n  uint32_t namespace_idx = m_class_name_refs[class_id * block_size];\n  uint32_t class_idx = m_class_name_refs[class_id * block_size + 1];\n\n  std::string classname;\n  if (namespace_idx)\n    classname = m_prop_class_names[namespace_idx - 1] + \".\";\n  classname += m_prop_class_names[class_idx - 1];\n  return classname;\n}\n\nstd::tuple<bool, uint32_t, uint32_t>\nsubsystem_handler::get_object_dependencies (const uint32_t obj_id)\n{\n  // (class_ID, X, X, saveobj_ID, normal_obj_ID, dependency_ID)\n  // ordered by object ID\n\n  constexpr int block_size = 6;\n  bool saveobj_type = true;\n\n  uint32_t obj_dep_id = m_object_id_refs[obj_id * block_size + 5];\n  uint32_t obj_con_id = m_object_id_refs[obj_id * block_size + 3];\n  if (! obj_con_id)\n    {\n      saveobj_type = false;\n      obj_con_id = m_object_id_refs[obj_id * block_size + 4];\n    }\n\n  return {saveobj_type, obj_con_id, obj_dep_id};\n}\n\noctave_map\nsubsystem_handler::get_object_properties (const uint32_t obj_type_id,\n                                          const uint32_t class_id,\n                                          const bool saveobj_ret_type,\n                                          bool as_struct)\n{\n  // (nprops, prop1_name_idx, prop1_val_type, prop1_val, prop2_name_idx ...)\n  // ordered by object type ID\n\n  const std::vector<uint32_t>& offset_fields\n    = saveobj_ret_type ? m_saveobj_prop_fields : m_object_prop_fields;\n  const uint32_t* ptr = offset_fields.data();\n  const uint32_t* end_ptr = ptr + offset_fields.size();\n\n  // skip to the correct obj_type_id block\n  constexpr int block_size = 3;\n  for (uint32_t current_id = 0; current_id < obj_type_id; current_id++)\n    {\n      uint32_t nprops = *ptr++;\n      ptr += nprops * block_size;\n      ptr += (1 + (nprops * block_size)) % 2;  // padding\n      if (ptr >= end_ptr)\n        error (\"Could not load file\");\n    }\n\n  octave_idx_type nprops = *ptr++;\n  octave_map prop_vals;\n  if (! as_struct)\n    {\n      octave_value& default_vals = m_fwrap_default_vals(class_id);\n      default_vals = search_mcos_classdef_objects (default_vals, false);\n      prop_vals = default_vals.map_value ();\n    }\n\n  for (octave_idx_type i = 0; i < nprops && ptr + 2 < end_ptr; i++)\n    {\n      uint32_t prop_name_idx = *ptr++;\n      uint32_t prop_val_type = *ptr++;\n      uint32_t prop_val_idx = *ptr++;\n\n      const std::string& prop_name = m_prop_class_names[prop_name_idx - 1];\n\n      switch (prop_val_type)\n        {\n        case 0:\n          // Property value is enum/string reference\n          {\n            warning_with_id (\"Octave:load:enum-string-ref\",\n                   \"load: property '%s' is an enum reference.  \"\n                   \"This may not be supported and is read as a string.\",\n                   prop_name.c_str ());\n            const std::string& prop_val = m_prop_class_names[prop_val_idx - 1];\n            prop_vals.assign (prop_name, octave_value (prop_val));\n          }\n          break;\n\n        case 1:\n          // Property value points to a cell in m_fwrap_prop_vals\n          {\n            octave_value& prop_val = m_fwrap_prop_vals[prop_val_idx];\n            prop_val = search_mcos_classdef_objects (prop_val, false);\n            prop_vals.assign (prop_name, prop_val);\n          }\n          break;\n\n        case 2:\n          // prop_val_idx is the property value itself? (Not sure)\n          {\n            prop_vals.assign (prop_name, octave_value (prop_val_idx));\n          }\n          break;\n\n        default:\n          warning (\"load: unknown property value type %u for property '%s'\",\n                   prop_val_type, prop_name.c_str ());\n          break;\n        }\n    }\n\n  return prop_vals;\n}\n\nbool\nsubsystem_handler::check_dyn_props (const uint32_t obj_dep_id)\n{\n  // (ndynprops, dynprop1_obj_id, dynprop2_obj_id ...)\n  // ordered by dependency ID\n\n  // FIXME: Actually implement support when Octave supports dynamicprops.\n  //        For now, only check if exists.\n\n  // Newer filewrapper versions do not write metadata if no dynprops are present.\n  // However, older versions write blocks of zeros.\n  if (m_dynamic_prop_refs.empty () || (! obj_dep_id))\n    return false;  // no dynamic properties present\n\n  const uint32_t *ptr = m_dynamic_prop_refs.data ();\n  const uint32_t *end_ptr = ptr + m_dynamic_prop_refs.size ();\n\n  bool has_dyn_props = false;\n  for (uint32_t current_id = 0; current_id < obj_dep_id; current_id++)\n    {\n      uint32_t nprops = *ptr++;\n      ptr += nprops;\n      ptr += (1 + nprops) % 2;  // padding\n      if (ptr >= end_ptr)\n          return false;\n    }\n\n  uint32_t nprops = *ptr++;\n  if (nprops)\n    has_dyn_props = true;\n  return has_dyn_props;\n}\n\nstd::pair<std::string, std::string>\nsubsystem_handler::parse_class_name (const std::string& full_class_name)\n{\n  std::string namespace_name;\n  std::string class_name;\n\n  // separate namespace from class name\n  size_t last_dot_pos = full_class_name.find_last_of ('.');\n  if (last_dot_pos != std::string::npos)\n    {\n      namespace_name = full_class_name.substr (0, last_dot_pos);\n      class_name = full_class_name.substr (last_dot_pos + 1);\n    }\n  else\n    {\n      namespace_name = \"\";\n      class_name = full_class_name;\n    }\n\n  return std::make_pair (namespace_name, class_name);\n}\n\nuint32_t\nsubsystem_handler::get_name_index (const std::string& name)\n{\n  for (octave_idx_type i = 0; i < m_prop_class_names.numel (); i++)\n    {\n      if (m_prop_class_names[i] == name)\n        return i + 1;  // names are 1-indexed\n    }\n\n  m_prop_class_names.append (name);\n  m_num_names = m_prop_class_names.numel ();\n  return m_num_names;\n}\n\nuint32_t\nsubsystem_handler::get_or_create_class_id (const std::string& namespace_name,\n                                           const std::string& class_name)\n{\n  uint32_t current_class_id = 1;\n  bool class_exists = false;\n\n  // search through existing m_class_name_refs to find this class\n  for (size_t i = 0; i < m_class_name_refs.size(); i += 4)\n    {\n      uint32_t existing_namespace_idx = m_class_name_refs[i];\n      uint32_t existing_class_idx = m_class_name_refs[i + 1];\n\n      std::string existing_namespace\n        = ((existing_namespace_idx > 0)\n           ? m_prop_class_names[existing_namespace_idx - 1] : \"\");\n      std::string existing_class = m_prop_class_names[existing_class_idx - 1];\n\n      if (existing_namespace == namespace_name && existing_class == class_name)\n        {\n          class_exists = true;\n          break;\n        }\n      current_class_id++;\n    }\n\n  if (! class_exists)\n    {\n      m_class_id_counter++;\n\n      // individual names can be shared\n      uint32_t namespace_idx = (namespace_name.empty()\n                                ? 0 : get_name_index (namespace_name));\n      uint32_t class_name_idx = get_name_index (class_name);\n\n      m_class_name_refs.push_back (namespace_idx);\n      m_class_name_refs.push_back (class_name_idx);\n      m_class_name_refs.push_back (0);\n      m_class_name_refs.push_back (0);\n    }\n\n  return current_class_id;\n}\n\nuint32NDArray\nsubsystem_handler::create_metadata_array (const dim_vector& obj_dims,\n                                          const std::vector<uint32_t>& object_ids,\n                                          uint32_t class_id)\n{\n  uint32_t obj_ndims = obj_dims.ndims ();\n  uint32_t nobjects = obj_dims.numel ();\n\n  // metadata format: [0xDD000000, objdims, dim1, dim2, ..., dimN,\n  //                   object_id1, object_id2, ..., object_idN, class_id]\n  uint32NDArray metadata (dim_vector (3 + obj_ndims + nobjects, 1));\n\n  metadata(0) = MCOS_MAGIC_NUMBER;  // magic number for MCOS objects\n  metadata(1) = obj_ndims;\n\n  for (uint32_t i = 0; i < obj_ndims; i++)\n    metadata(2 + i) = obj_dims(i);\n\n  for (uint32_t i = 0; i < nobjects; i++)\n    metadata(2 + obj_ndims + i) = object_ids[i];\n\n  metadata(2 + obj_ndims + nobjects) = class_id;\n\n  return metadata;\n}\n\nvoid\nsubsystem_handler::process_object_properties (const std::vector<std::tuple<octave_map, uint32_t, bool>>& saveobj_data,\n                                              const std::vector<bool>& is_new,\n                                              uint32_t class_id)\n{\n  // Save positions for insertion at the end\n  size_t object_id_refs_pos = m_object_id_refs.size ();\n  size_t object_prop_fields_pos = m_object_prop_fields.size ();\n  size_t saveobj_prop_fields_pos = m_saveobj_prop_fields.size ();\n\n  // local storage for this batch of objects\n  std::vector<uint32_t> local_object_id_refs;\n  std::vector<uint32_t> local_object_prop_fields;\n  std::vector<uint32_t> local_saveobj_prop_fields;\n  std::vector<uint32_t> local_dynamic_prop_refs;\n\n  for (size_t obj_idx = 0; obj_idx < saveobj_data.size (); obj_idx++)\n    {\n      const auto& obj_tuple = saveobj_data[obj_idx];\n      const octave_map& prop_map = std::get<octave_map> (obj_tuple);\n      bool saveobj_ret_type = std::get<bool> (obj_tuple);\n\n      if (is_new[obj_idx])\n        {\n          uint32_t saveobj_object_id = 0;\n          uint32_t normal_object_id = 0;\n          std::vector<uint32_t>& target_prop_fields\n            = (saveobj_ret_type ? local_saveobj_prop_fields\n                                : local_object_prop_fields);\n\n          if (saveobj_ret_type)\n            saveobj_object_id = ++m_saveobj_object_counter;\n          else\n            normal_object_id = ++m_normal_object_counter;\n\n          // TODO: Add dependency IDs\n          local_object_id_refs.push_back (class_id);\n          local_object_id_refs.push_back (0);\n          local_object_id_refs.push_back (0);\n          local_object_id_refs.push_back (saveobj_object_id);\n          local_object_id_refs.push_back (normal_object_id);\n          local_object_id_refs.push_back (0);\n\n          string_vector prop_names = prop_map.fieldnames ();\n          octave_idx_type num_props = prop_names.numel ();\n          target_prop_fields.push_back (num_props);\n\n          for (octave_idx_type prop_idx = 0; prop_idx < num_props; prop_idx++)\n            {\n              std::string prop_name = prop_names[prop_idx];\n              octave_value prop_value = (prop_map.contents (prop_name))(0);\n\n              prop_value = search_mcos_classdef_objects (prop_value, true);\n\n              uint32_t field_name_idx = get_name_index (prop_name);\n              uint32_t cell_number_idx = m_fwrap_prop_vals.size ();\n              m_fwrap_prop_vals.push_back (prop_value);\n\n              // (field_name_idx, field_val_type, cell_idx)\n              target_prop_fields.push_back (field_name_idx);\n              target_prop_fields.push_back (1);\n              target_prop_fields.push_back (cell_number_idx);\n            }\n\n          // TODO: Parse for different property types\n\n          if ((num_props * 3 + 1) % 2 != 0)\n            target_prop_fields.push_back (0);  // padding\n\n          // dummy values for compatibility\n          local_dynamic_prop_refs.push_back (0);\n          local_dynamic_prop_refs.push_back (0);\n        }\n    }\n\n  // Insert at saved positions instead of appending to end\n  m_object_id_refs.insert (m_object_id_refs.begin () + object_id_refs_pos,\n                           local_object_id_refs.begin (),\n                           local_object_id_refs.end ());\n  m_object_prop_fields.insert (m_object_prop_fields.begin () + object_prop_fields_pos,\n                               local_object_prop_fields.begin (),\n                               local_object_prop_fields.end ());\n  m_saveobj_prop_fields.insert (m_saveobj_prop_fields.begin () + saveobj_prop_fields_pos,\n                                local_saveobj_prop_fields.begin (),\n                                local_saveobj_prop_fields.end ());\n  m_dynamic_prop_refs.insert (m_dynamic_prop_refs.end (),\n                              local_dynamic_prop_refs.begin (),\n                              local_dynamic_prop_refs.end ());\n}\n\nuint32NDArray\nsubsystem_handler::set_mcos_object_metadata (const octave_value& obj)\n{\n  std::string full_class_name = obj.class_name ();\n  auto [namespace_name, class_name] = parse_class_name (full_class_name);\n\n  uint32_t current_class_id = get_or_create_class_id (namespace_name, class_name);\n\n  std::vector<bool> is_new (obj.numel ());\n  std::vector<std::tuple<octave_map, uint32_t, bool>> saveobj_data\n    = obj.classdef_object_value ()->saveobj (is_new);\n\n  dim_vector obj_dims = obj.dims ();\n  std::vector<uint32_t> actual_object_ids;\n  actual_object_ids.reserve (obj_dims.numel ());\n\n  for (const auto& obj_tuple : saveobj_data)\n    {\n      uint32_t obj_id = std::get<uint32_t> (obj_tuple);\n      actual_object_ids.push_back (obj_id);\n    }\n\n\n  process_object_properties (saveobj_data, is_new, current_class_id);\n\n  return create_metadata_array (obj_dims, actual_object_ids, current_class_id);\n}\n\nuint8NDArray\nsubsystem_handler::create_filewrapper_metadata ()\n{\n  // helper to write data for object ID = 0\n  // Note: MATLAB has values for some kind of placeholder object with ID = 0\n  auto write_object_id_0 = [](uint8_t*& ptr, int count) -> void\n    {\n      uint32_t zero = 0;\n      for (int i = 0; i < count; i++)\n        {\n          std::memcpy (ptr, &zero, 4);\n          ptr += 4;\n        }\n    };\n\n  // calculate region offsets\n  size_t current_offset = 40;  // start after header (version + m_num_names + 8 offsets)\n\n  for (octave_idx_type i = 0; i < m_prop_class_names.numel (); i++)\n    current_offset += m_prop_class_names[i].length () + 1;  // +1 for null terminator\n\n  // padding\n  size_t padding_length = 0;\n  if (current_offset % 8 != 0)\n    {\n      padding_length = 8 - (current_offset % 8);\n      current_offset += padding_length;\n    }\n\n  m_region_offsets[0] = current_offset;  // class_name metadata\n\n  current_offset += (m_class_name_refs.size () + 4) * 4;\n  m_region_offsets[1] = current_offset;  // saveobj prop metadata\n\n  current_offset += m_saveobj_prop_fields.size () * 4;\n  if (m_saveobj_prop_fields.size () > 0)\n    current_offset += 8;\n  m_region_offsets[2] = current_offset;  // object id metadata\n\n  current_offset += (m_object_id_refs.size () + 6) * 4;\n  m_region_offsets[3] = current_offset;  // object prop metadata\n\n  current_offset += m_object_prop_fields.size () * 4;\n  if (m_object_prop_fields.size () > 0)\n    current_offset += 8;\n  m_region_offsets[4] = current_offset;  // dynamicprop metadata\n\n  // Offsets 5-7: Unknown purposes\n  current_offset += m_dynamic_prop_refs.size () * 4;\n  current_offset += 8;\n  m_region_offsets[5] = current_offset;\n  m_region_offsets[6] = current_offset;\n  current_offset += 8;\n  m_region_offsets[7] = current_offset;  // end of metadata\n\n  uint32_t& metadata_size = m_region_offsets[7];\n\n  // metadata format:\n  // version, m_num_names, region offsets, names\n  // class name metadata, saveobj prop metadata\n  // object id metadata, obj prop metadata\n  // dynamicprop metadata + unknowns\n  uint8NDArray metadata (dim_vector (metadata_size, 1));\n  uint8_t* metadata_ptr = reinterpret_cast<uint8_t*> (metadata.rwdata ());\n\n  uint32_t version = m_filewrapper_version;\n  std::memcpy (metadata_ptr, &version, 4);\n  metadata_ptr += 4;\n\n  std::memcpy (metadata_ptr, &m_num_names, 4);\n  metadata_ptr += 4;\n\n  for (int i = 0; i < 8; i++)\n    {\n      uint32_t offset_value = static_cast<uint32_t> (m_region_offsets[i]);\n      std::memcpy (metadata_ptr, &offset_value, 4);\n      metadata_ptr += 4;\n    }\n\n  for (octave_idx_type i = 0; i < m_prop_class_names.numel (); i++)\n    {\n      const std::string& name = m_prop_class_names[i];\n      std::memcpy (metadata_ptr, name.c_str (), name.length ());\n      metadata_ptr += name.length ();\n      *metadata_ptr++ = 0;  // null terminator\n    }\n  for (size_t i = 0; i < padding_length; i++)\n    *metadata_ptr++ = 0;  // padding\n\n  write_object_id_0 (metadata_ptr, 4);\n  for (size_t i = 0; i < m_class_name_refs.size (); i++)\n    {\n      uint32_t value = m_class_name_refs[i];\n      std::memcpy (metadata_ptr, &value, 4);\n      metadata_ptr += 4;\n    }\n\n  if (m_saveobj_prop_fields.size () > 0)\n    write_object_id_0 (metadata_ptr, 2);  // slot 0 padding\n  for (size_t i = 0; i < m_saveobj_prop_fields.size (); i++)\n    {\n      uint32_t value = m_saveobj_prop_fields[i];\n      std::memcpy (metadata_ptr, &value, 4);\n      metadata_ptr += 4;\n    }\n\n  write_object_id_0 (metadata_ptr, 6);  // slot 0 padding\n  for (size_t i = 0; i < m_object_id_refs.size (); i++)\n    {\n      uint32_t value = m_object_id_refs[i];\n      std::memcpy (metadata_ptr, &value, 4);\n      metadata_ptr += 4;\n    }\n\n  if (m_object_prop_fields.size () > 0)\n    write_object_id_0 (metadata_ptr, 2);  // slot 0 padding\n  for (size_t i = 0; i < m_object_prop_fields.size (); i++)\n    {\n      uint32_t value = m_object_prop_fields[i];\n      std::memcpy (metadata_ptr, &value, 4);\n      metadata_ptr += 4;\n    }\n\n  write_object_id_0 (metadata_ptr, 2);  // slot 0 padding\n  for (size_t i = 0; i < m_dynamic_prop_refs.size (); i++)\n    {\n      uint32_t value = m_dynamic_prop_refs[i];\n      std::memcpy (metadata_ptr, &value, 4);\n      metadata_ptr += 4;\n    }\n\n  // write 8 bytes of zeros for region_offset[6]\n  for (int i = 0; i < 8; i++)\n    *metadata_ptr++ = 0;\n\n  return metadata;\n}\n\nvoid\nsubsystem_handler::serialize_to_cell_array ()\n{\n  if (! m_class_id_counter)\n    return;\n\n  // create cell array with size = m_fwrap_prop_vals.size () + 2 + 3\n  // (for the additional cells)\n  octave_idx_type cell_size = m_fwrap_prop_vals.size () + 5;\n  Cell result (dim_vector (cell_size, 1));\n\n  result(0) = create_filewrapper_metadata ();\n  result(1) = octave_value (Matrix ());  // empty matrix for some reason\n\n  // set remaining cells to property values\n  for (size_t i = 0; i < m_fwrap_prop_vals.size (); i++)\n    result(i + 2) = m_fwrap_prop_vals[i];\n\n  // unknown cells\n  // These contain some class-level metadata\n  // typically a cell array of empty 1x0 structs for each class ID\n  octave_idx_type base_idx = m_fwrap_prop_vals.size () + 2;\n  uint32_t num_class_ids = m_class_id_counter + 1;\n\n  Cell u3_structs (dim_vector (num_class_ids, 1));\n  for (uint32_t i = 0; i < num_class_ids; i++)\n    u3_structs(i) = octave_value (octave_map (dim_vector (1, 0)));\n  result(base_idx) = octave_value (u3_structs);\n\n  int32NDArray u2_zeros (dim_vector (num_class_ids, 1));\n  for (uint32_t i = 0; i < num_class_ids; i++)\n    u2_zeros(i) = 0;\n  result(base_idx + 1) = octave_value (u2_zeros);\n\n  // contains default values - not separately tagged in Octave\n  m_fwrap_default_vals.resize (dim_vector (num_class_ids, 1));\n  for (uint32_t i = 0; i < num_class_ids; i++)\n    m_fwrap_default_vals(i) = octave_value (octave_map (dim_vector (1, 0)));\n  result(base_idx + 2) = octave_value (m_fwrap_default_vals);\n\n  // storing only because save -> save_mat5_element_length which needs the\n  // actual contents to write nbytes\n  m_serialized_data = result;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/ls-mat-subsys.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ls_mat_subsys_h)\n#define octave_ls_mat_subsys_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdint>\n\n#include <array>\n#include <iosfwd>\n#include <string>\n#include <tuple>\n#include <utility>\n#include <vector>\n\n#include \"Cell.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTINTERP_API octave_value\nload_mcos_object (const octave_value& objmetadata, bool as_struct = false);\n\nclass subsystem_handler\n{\n  public:\n\n    // load methods\n    bool read_mat_subsystem (const octave_value& subsys, bool swap);\n\n    bool read_filewrapper (const Cell& fwrap_data, bool swap);\n\n    std::string get_class_name (const uint32_t class_id);\n\n    std::tuple<bool, uint32_t, uint32_t>\n    get_object_dependencies (const uint32_t obj_id);\n\n    octave_map\n    get_object_properties (const uint32_t obj_type_id, const uint32_t class_id,\n                           const bool saveobj_type, bool as_struct = false);\n\n    bool check_dyn_props (const uint32_t obj_dep_id);\n\n    // save methods\n    uint32NDArray set_mcos_object_metadata (const octave_value& obj);\n\n    uint8NDArray create_filewrapper_metadata ();\n\n    void serialize_to_cell_array ();\n\n    octave_value get_serialized_data () const { return m_serialized_data; }\n\n    bool has_serialized_data () const\n    { return m_serialized_data.is_defined (); }\n\n  private:\n\n    uint32_t get_name_index (const std::string& name);\n\n    // helper functions for set_mcos_object_metadata\n    std::pair<std::string, std::string>\n    parse_class_name (const std::string& full_class_name);\n\n    uint32_t\n    get_or_create_class_id (const std::string& namespace_name,\n                            const std::string& class_name);\n\n    uint32NDArray\n    create_metadata_array (const dim_vector& obj_dims,\n                           const std::vector<uint32_t>& object_ids,\n                           uint32_t class_id);\n\n    void\n    process_object_properties (const std::vector<std::tuple<octave_map, uint32_t, bool>>& saveobj_data,\n                               const std::vector<bool>& is_new,\n                               uint32_t class_id);\n\n  private:\n\n    const uint32_t m_filewrapper_version = 4;\n\n    // load variables\n    octave_value m_type_java;\n    octave_value m_type_handle;\n\n    // save variables\n    uint32_t m_object_id_counter = 0;  // To manage dependency graphs; FIXME: unused?\n    uint32_t m_class_id_counter = 0;\n    uint32_t m_saveobj_object_counter = 0;\n    uint32_t m_normal_object_counter = 0;\n\n    octave_value m_serialized_data;  // required for writing nbytes when saving\n\n    // load-save variables\n    uint32_t m_num_names;  // number of unique class and property names\n    string_vector m_prop_class_names;\n\n    std::array<uint32_t, 8> m_region_offsets;\n\n    std::vector<uint32_t> m_class_name_refs;\n    std::vector<uint32_t> m_object_id_refs;\n    std::vector<uint32_t> m_object_prop_fields;\n    std::vector<uint32_t> m_saveobj_prop_fields;\n    std::vector<uint32_t> m_dynamic_prop_refs;\n\n    std::vector<octave_value> m_fwrap_prop_vals;\n    Cell m_fwrap_default_vals;\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-mat4.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n#include <string>\n\n#include \"byte-swap.h\"\n#include \"dMatrix.h\"\n#include \"dSparse.h\"\n#include \"data-conv.h\"\n#include \"file-ops.h\"\n#include \"glob-match.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n\n#include \"ls-mat4.h\"\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"load-save.h\"\n#include \"oct-map.h\"\n#include \"ov-cell.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"sysdep.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"version.h\"\n\n\n// Read LEN elements of data from IS in the format specified by\n// PRECISION, placing the result in DATA.  If SWAP is TRUE, swap\n// the bytes of each element before copying to DATA.  FLT_FMT\n// specifies the format of the data if we are reading floating point\n// numbers.\n\nstatic void\nread_mat_binary_data (std::istream& is, double *data, int precision,\n                      int len, bool swap,\n                      octave::mach_info::float_format flt_fmt)\n{\n  switch (precision)\n    {\n    case 0:\n      read_doubles (is, data, LS_DOUBLE, len, swap, flt_fmt);\n      break;\n\n    case 1:\n      read_doubles (is, data, LS_FLOAT, len, swap, flt_fmt);\n      break;\n\n    case 2:\n      read_doubles (is, data, LS_INT, len, swap, flt_fmt);\n      break;\n\n    case 3:\n      read_doubles (is, data, LS_SHORT, len, swap, flt_fmt);\n      break;\n\n    case 4:\n      read_doubles (is, data, LS_U_SHORT, len, swap, flt_fmt);\n      break;\n\n    case 5:\n      read_doubles (is, data, LS_U_CHAR, len, swap, flt_fmt);\n      break;\n\n    default:\n      break;\n    }\n}\n\nint\nread_mat_file_header (std::istream& is, bool& swap, int32_t& mopt,\n                      int32_t& nr, int32_t& nc,\n                      int32_t& imag, int32_t& len,\n                      int quiet)\n{\n  swap = false;\n\n  // We expect to fail here, at the beginning of a record, so not\n  // being able to read another mopt value should not result in an\n  // error.\n\n  is.read (reinterpret_cast<char *> (&mopt), 4);\n  if (! is)\n    return 1;\n\n  if (! is.read (reinterpret_cast<char *> (&nr), 4))\n    return -1;\n\n  if (! is.read (reinterpret_cast<char *> (&nc), 4))\n    return -1;\n\n  if (! is.read (reinterpret_cast<char *> (&imag), 4))\n    return -1;\n\n  if (! is.read (reinterpret_cast<char *> (&len), 4))\n    return -1;\n\n// If mopt is nonzero and the byte order is swapped, mopt will be\n// bigger than we expect, so we swap bytes.\n//\n// If mopt is zero, it means the file was written on a little endian machine,\n// and we only need to swap if we are running on a big endian machine.\n//\n// Gag me.\n\n  if (octave::mach_info::words_big_endian () && mopt == 0)\n    swap = true;\n\n  // mopt is signed, therefore byte swap may result in negative value.\n\n  if (mopt > 9999 || mopt < 0)\n    swap = true;\n\n  if (swap)\n    {\n      swap_bytes<4> (&mopt);\n      swap_bytes<4> (&nr);\n      swap_bytes<4> (&nc);\n      swap_bytes<4> (&imag);\n      swap_bytes<4> (&len);\n    }\n\n  if (mopt > 9999 || mopt < 0 || imag > 1 || imag < 0)\n    {\n      if (! quiet)\n        error (\"load: can't read binary file\");\n\n      return -1;\n    }\n\n  return 0;\n}\n\n// We don't just use a cast here, because we need to be able to detect\n// possible errors.\n\noctave::mach_info::float_format\nmopt_digit_to_float_format (int mach)\n{\n  octave::mach_info::float_format flt_fmt = octave::mach_info::flt_fmt_unknown;\n\n  switch (mach)\n    {\n    case 0:\n      flt_fmt = octave::mach_info::flt_fmt_ieee_little_endian;\n      break;\n\n    case 1:\n      flt_fmt = octave::mach_info::flt_fmt_ieee_big_endian;\n      break;\n\n    case 2:\n    case 3:\n    case 4:\n    default:\n      flt_fmt = octave::mach_info::flt_fmt_unknown;\n      break;\n    }\n\n  return flt_fmt;\n}\n\nint\nfloat_format_to_mopt_digit (octave::mach_info::float_format flt_fmt)\n{\n  int retval = -1;\n\n  switch (flt_fmt)\n    {\n    case octave::mach_info::flt_fmt_ieee_little_endian:\n      retval = 0;\n      break;\n\n    case octave::mach_info::flt_fmt_ieee_big_endian:\n      retval = 1;\n      break;\n\n    default:\n      break;\n    }\n\n  return retval;\n}\n\n// Extract one value (scalar, matrix, string, etc.) from stream IS and\n// place it in TC, returning the name of the variable.\n//\n// The data is expected to be in Matlab version 4 .mat format, though\n// not all the features of that format are supported.\n//\n// FILENAME is used for error messages.\n//\n// This format provides no way to tag the data as global.\n\nstd::string\nread_mat_binary_data (std::istream& is, const std::string& filename,\n                      octave_value& tc)\n{\n  std::string retval;\n\n  bool swap = false;\n  int32_t mopt, nr, nc, imag, len;\n\n  int err = read_mat_file_header (is, swap, mopt, nr, nc, imag, len);\n  if (err)\n    {\n      if (err < 0)\n        error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n\n      return retval;\n    }\n\n  int type = 0;\n  int prec = 0;\n  int order = 0;\n  int mach = 0;\n\n  type = mopt % 10;  // Full, sparse, etc.\n  mopt /= 10;        // Eliminate first digit.\n  prec = mopt % 10;  // double, float, int, etc.\n  mopt /= 10;        // Eliminate second digit.\n  order = mopt % 10; // Row or column major ordering.\n  mopt /= 10;        // Eliminate third digit.\n  mach = mopt % 10;  // IEEE, VAX, etc.\n\n  octave::mach_info::float_format flt_fmt;\n  flt_fmt = mopt_digit_to_float_format (mach);\n\n  if (flt_fmt == octave::mach_info::flt_fmt_unknown)\n    error (\"load: unrecognized binary format!\");\n\n  if (imag && type == 1)\n    error (\"load: encountered complex matrix with string flag set!\");\n\n  int dlen = 0;\n\n  // LEN includes the terminating character, and the file is also\n  // supposed to include it, but apparently not all files do.  Either\n  // way, I think this should work.\n\n  {\n    OCTAVE_LOCAL_BUFFER (char, name, len+1);\n    name[len] = '\\0';\n    if (! is.read (name, len))\n      error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n    retval = name;\n\n    dlen = nr * nc;\n    if (dlen < 0)\n      error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n\n    if (order)\n      {\n        octave_idx_type tmp = nr;\n        nr = nc;\n        nc = tmp;\n      }\n\n    if (type == 2)\n      {\n        if (nc == 4)\n          {\n            octave_idx_type nr_new, nc_new;\n            Array<Complex> data (dim_vector (1, nr - 1));\n            Array<octave_idx_type> c (dim_vector (1, nr - 1));\n            Array<octave_idx_type> r (dim_vector (1, nr - 1));\n            OCTAVE_LOCAL_BUFFER (double, dtmp, nr);\n            OCTAVE_LOCAL_BUFFER (double, ctmp, nr);\n\n            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);\n            for (octave_idx_type i = 0; i < nr - 1; i++)\n              r.xelem (i) = dtmp[i] - 1;\n            nr_new = dtmp[nr - 1];\n            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);\n            for (octave_idx_type i = 0; i < nr - 1; i++)\n              c.xelem (i) = dtmp[i] - 1;\n            nc_new = dtmp[nr - 1];\n            read_mat_binary_data (is, dtmp, prec, nr - 1, swap, flt_fmt);\n            read_mat_binary_data (is, ctmp, prec, 1, swap, flt_fmt);\n            read_mat_binary_data (is, ctmp, prec, nr - 1, swap, flt_fmt);\n\n            for (octave_idx_type i = 0; i < nr - 1; i++)\n              data.xelem (i) = Complex (dtmp[i], ctmp[i]);\n            read_mat_binary_data (is, ctmp, prec, 1, swap, flt_fmt);\n\n            SparseComplexMatrix smc = SparseComplexMatrix (data, r, c,\n                                      nr_new, nc_new);\n\n            tc = (order ? smc.transpose () : smc);\n          }\n        else\n          {\n            octave_idx_type nr_new, nc_new;\n            Array<double> data (dim_vector (1, nr - 1));\n            Array<octave_idx_type> c (dim_vector (1, nr - 1));\n            Array<octave_idx_type> r (dim_vector (1, nr - 1));\n            OCTAVE_LOCAL_BUFFER (double, dtmp, nr);\n\n            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);\n            for (octave_idx_type i = 0; i < nr - 1; i++)\n              r.xelem (i) = dtmp[i] - 1;\n            nr_new = dtmp[nr - 1];\n            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);\n            for (octave_idx_type i = 0; i < nr - 1; i++)\n              c.xelem (i) = dtmp[i] - 1;\n            nc_new = dtmp[nr - 1];\n            read_mat_binary_data (is, data.rwdata (), prec, nr - 1,\n                                  swap, flt_fmt);\n            read_mat_binary_data (is, dtmp, prec, 1, swap, flt_fmt);\n\n            SparseMatrix sm = SparseMatrix (data, r, c, nr_new, nc_new);\n\n            tc = (order ? sm.transpose () : sm);\n          }\n      }\n    else\n      {\n        Matrix re (nr, nc);\n\n        read_mat_binary_data (is, re.rwdata (), prec, dlen, swap, flt_fmt);\n\n        if (! is)\n          error (\"load: reading matrix data for '%s'\", name);\n\n        if (imag)\n          {\n            Matrix im (nr, nc);\n\n            read_mat_binary_data (is, im.rwdata (), prec, dlen, swap,\n                                  flt_fmt);\n\n            if (! is)\n              error (\"load: reading imaginary matrix data for '%s'\", name);\n\n            ComplexMatrix ctmp (nr, nc);\n\n            for (octave_idx_type j = 0; j < nc; j++)\n              for (octave_idx_type i = 0; i < nr; i++)\n                ctmp (i, j) = Complex (re(i, j), im(i, j));\n\n            tc = (order ? ctmp.transpose () : ctmp);\n          }\n        else\n          tc = (order ? re.transpose () : re);\n\n        if (type == 1)\n          tc = tc.convert_to_str (false, true, '\\'');\n      }\n\n    return retval;\n  }\n}\n\n// Save the data from TC along with the corresponding NAME on stream OS\n// in the MatLab version 4 binary format.\n\nbool\nsave_mat_binary_data (std::ostream& os, const octave_value& tc,\n                      const std::string& name)\n{\n  int32_t mopt = 0;\n\n  mopt += tc.issparse () ? 2 : tc.is_string () ? 1 : 0;\n\n  octave::mach_info::float_format flt_fmt\n    = octave::mach_info::native_float_format ();\n\n  mopt += 1000 * float_format_to_mopt_digit (flt_fmt);\n\n  os.write (reinterpret_cast<char *> (&mopt), 4);\n\n  octave_idx_type len;\n  int32_t nr = tc.rows ();\n\n  int32_t nc = tc.columns ();\n\n  if (tc.issparse ())\n    {\n      len = tc.nnz ();\n      uint32_t nnz = len + 1;\n      os.write (reinterpret_cast<char *> (&nnz), 4);\n\n      uint32_t iscmplx = (tc.iscomplex () ? 4 : 3);\n      os.write (reinterpret_cast<char *> (&iscmplx), 4);\n\n      uint32_t tmp = 0;\n      os.write (reinterpret_cast<char *> (&tmp), 4);\n    }\n  else\n    {\n      os.write (reinterpret_cast<char *> (&nr), 4);\n      os.write (reinterpret_cast<char *> (&nc), 4);\n\n      int32_t imag = (tc.iscomplex () ? 1 : 0);\n      os.write (reinterpret_cast<char *> (&imag), 4);\n\n      len = static_cast<octave_idx_type> (nr) * nc;\n    }\n\n  // LEN includes the terminating character, and the file is also\n  // supposed to include it.\n\n  int32_t name_len = name.length () + 1;\n\n  os.write (reinterpret_cast<char *> (&name_len), 4);\n  os << name << '\\0';\n\n  if (tc.is_string ())\n    {\n      charMatrix chm = tc.char_matrix_value ();\n\n      octave_idx_type nrow = chm.rows ();\n      octave_idx_type ncol = chm.cols ();\n\n      OCTAVE_LOCAL_BUFFER (double, buf, ncol*nrow);\n\n      for (octave_idx_type i = 0; i < nrow; i++)\n        {\n          std::string tstr = chm.row_as_string (i);\n          const char *s = tstr.data ();\n\n          for (octave_idx_type j = 0; j < ncol; j++)\n            buf[j*nrow+i] = static_cast<double> (*s++ & 0x00FF);\n        }\n      std::streamsize n_bytes = static_cast<std::streamsize> (nrow) *\n                                static_cast<std::streamsize> (ncol) *\n                                sizeof (double);\n      os.write (reinterpret_cast<char *> (buf), n_bytes);\n    }\n  else if (tc.is_range ())\n    {\n      octave::range<double> r = tc.range_value ();\n      double base = r.base ();\n      double inc = r.increment ();\n      octave_idx_type nel = r.numel ();\n      for (octave_idx_type i = 0; i < nel; i++)\n        {\n          double x = base + i * inc;\n          os.write (reinterpret_cast<char *> (&x), 8);\n        }\n    }\n  else if (tc.is_real_scalar ())\n    {\n      double tmp = tc.double_value ();\n      os.write (reinterpret_cast<char *> (&tmp), 8);\n    }\n  else if (tc.issparse ())\n    {\n      double ds;\n      OCTAVE_LOCAL_BUFFER (double, dtmp, len);\n      if (tc.is_complex_matrix ())\n        {\n          SparseComplexMatrix m = tc.sparse_complex_matrix_value ();\n\n          for (octave_idx_type i = 0; i < len; i++)\n            dtmp[i] = m.ridx (i) + 1;\n          std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);\n          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);\n          ds = nr;\n          os.write (reinterpret_cast<const char *> (&ds), 8);\n\n          octave_idx_type ii = 0;\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n              dtmp[ii++] = j + 1;\n          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);\n          ds = nc;\n          os.write (reinterpret_cast<const char *> (&ds), 8);\n\n          for (octave_idx_type i = 0; i < len; i++)\n            dtmp[i] = std::real (m.data (i));\n          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);\n          ds = 0.;\n          os.write (reinterpret_cast<const char *> (&ds), 8);\n\n          for (octave_idx_type i = 0; i < len; i++)\n            dtmp[i] = std::imag (m.data (i));\n          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);\n          os.write (reinterpret_cast<const char *> (&ds), 8);\n        }\n      else\n        {\n          SparseMatrix m = tc.sparse_matrix_value ();\n\n          for (octave_idx_type i = 0; i < len; i++)\n            dtmp[i] = m.ridx (i) + 1;\n          std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);\n          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);\n          ds = nr;\n          os.write (reinterpret_cast<const char *> (&ds), 8);\n\n          octave_idx_type ii = 0;\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n              dtmp[ii++] = j + 1;\n          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);\n          ds = nc;\n          os.write (reinterpret_cast<const char *> (&ds), 8);\n\n          os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);\n          ds = 0.;\n          os.write (reinterpret_cast<const char *> (&ds), 8);\n        }\n    }\n  else if (tc.is_real_matrix ())\n    {\n      Matrix m = tc.matrix_value ();\n      std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);\n      os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);\n    }\n  else if (tc.is_complex_scalar ())\n    {\n      Complex tmp = tc.complex_value ();\n      os.write (reinterpret_cast<char *> (&tmp), 16);\n    }\n  else if (tc.is_complex_matrix ())\n    {\n      ComplexMatrix m_cmplx = tc.complex_matrix_value ();\n      Matrix m = ::real (m_cmplx);\n      std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);\n      os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);\n      m = ::imag (m_cmplx);\n      os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);\n    }\n  else\n    // FIXME: Should this just error out rather than warn?\n    warn_wrong_type_arg (\"save\", tc);\n\n  return ! os.fail ();\n}\n"
  },
  {
    "path": "libinterp/corefcn/ls-mat4.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ls_mat4_h)\n#define octave_ls_mat4_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n#include \"mach-info.h\"\n\nclass octave_value;\n\nextern OCTINTERP_API octave::mach_info::float_format\nmopt_digit_to_float_format (int mach);\n\nextern OCTINTERP_API int\nfloat_format_to_mopt_digit (octave::mach_info::float_format flt_fmt);\n\nextern OCTINTERP_API int\nread_mat_file_header (std::istream& is, bool& swap, int32_t& mopt,\n                      int32_t& nr, int32_t& nc, int32_t& imag,\n                      int32_t& len, int quiet = 0);\n\nextern OCTINTERP_API std::string\nread_mat_binary_data (std::istream& is, const std::string& filename,\n                      octave_value& tc);\n\nextern OCTINTERP_API bool\nsave_mat_binary_data (std::ostream& os, const octave_value& tc,\n                      const std::string& name);\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-mat5.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstring>\n\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"byte-swap.h\"\n#include \"dMatrix.h\"\n#include \"data-conv.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"glob-match.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sysdep.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n#include \"str-vec.h\"\n#include \"unistr-wrappers.h\"\n\n#include \"cdef-utils.h\"\n#include \"Cell.h\"\n#include \"defaults.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"load-save.h\"\n#include \"ls-mat5.h\"\n#include \"ls-mat-subsys.h\"\n#include \"ls-utils.h\"\n#include \"oct-map.h\"\n#include \"ov-cell.h\"\n#include \"ov-class.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"pt-eval.h\"\n#include \"stack-frame.h\"\n#include \"sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"version.h\"\n\n#if defined (HAVE_ZLIB)\n#  include <zlib.h>\n#endif\n\n#define READ_PAD(is_small_data_element, l) ((is_small_data_element) ? 4 : (((l)+7)/8)*8)\n#define PAD(l) (((l) > 0 && (l) <= 4) ? 4 : (((l)+7)/8)*8)\n#define INT8(l) ((l) == miINT8 || (l) == miUINT8 || (l) == miUTF8)\n\n// FIXME: the following enum values should be the same as the\n// mxClassID values in mexproto.h, but it seems they have also changed\n// over time.  What is the correct way to handle this and maintain\n// backward compatibility with old MAT files?  For now, use\n// \"MAT_FILE_\" instead of \"mx\" as the prefix for these names to avoid\n// conflict with the mxClassID enum in mexproto.h.\n\nenum arrayclasstype\n{\n  MAT_FILE_CELL_CLASS=1,              // cell array\n  MAT_FILE_STRUCT_CLASS,              // structure\n  MAT_FILE_OBJECT_CLASS,              // object\n  MAT_FILE_CHAR_CLASS,                // character array\n  MAT_FILE_SPARSE_CLASS,              // sparse array\n  MAT_FILE_DOUBLE_CLASS,              // double precision array\n  MAT_FILE_SINGLE_CLASS,              // single precision floating point\n  MAT_FILE_INT8_CLASS,                // 8 bit signed integer\n  MAT_FILE_UINT8_CLASS,               // 8 bit unsigned integer\n  MAT_FILE_INT16_CLASS,               // 16 bit signed integer\n  MAT_FILE_UINT16_CLASS,              // 16 bit unsigned integer\n  MAT_FILE_INT32_CLASS,               // 32 bit signed integer\n  MAT_FILE_UINT32_CLASS,              // 32 bit unsigned integer\n  MAT_FILE_INT64_CLASS,               // 64 bit signed integer\n  MAT_FILE_UINT64_CLASS,              // 64 bit unsigned integer\n  MAT_FILE_FUNCTION_CLASS,            // Function handle\n  MAT_FILE_WORKSPACE_CLASS            // Workspace (undocumented)\n};\n\n// Read COUNT elements of data from IS in the format specified by TYPE,\n// placing the result in DATA.  If SWAP is TRUE, swap the bytes of\n// each element before copying to DATA.  FLT_FMT specifies the format\n// of the data if we are reading floating point numbers.\n\nstatic void\nread_mat5_binary_data (std::istream& is, double *data,\n                       octave_idx_type  count, bool swap, mat5_data_type type,\n                       octave::mach_info::float_format flt_fmt)\n{\n\n  switch (type)\n    {\n    case miINT8:\n      read_doubles (is, data, LS_CHAR, count, swap, flt_fmt);\n      break;\n\n    case miUTF8:\n    case miUINT8:\n      read_doubles (is, data, LS_U_CHAR, count, swap, flt_fmt);\n      break;\n\n    case miINT16:\n      read_doubles (is, data, LS_SHORT, count, swap, flt_fmt);\n      break;\n\n    case miUTF16:\n    case miUINT16:\n      read_doubles (is, data, LS_U_SHORT, count, swap, flt_fmt);\n      break;\n\n    case miINT32:\n      read_doubles (is, data, LS_INT, count, swap, flt_fmt);\n      break;\n\n    case miUTF32:\n    case miUINT32:\n      read_doubles (is, data, LS_U_INT, count, swap, flt_fmt);\n      break;\n\n    case miSINGLE:\n      read_doubles (is, data, LS_FLOAT, count, swap, flt_fmt);\n      break;\n\n    case miRESERVE1:\n      break;\n\n    case miDOUBLE:\n      read_doubles (is, data, LS_DOUBLE, count, swap, flt_fmt);\n      break;\n\n    case miRESERVE2:\n    case miRESERVE3:\n      break;\n\n    // FIXME: how are the 64-bit cases supposed to work here?\n    case miINT64:\n      read_doubles (is, data, LS_LONG, count, swap, flt_fmt);\n      break;\n\n    case miUINT64:\n      read_doubles (is, data, LS_U_LONG, count, swap, flt_fmt);\n      break;\n\n    case miMATRIX:\n    default:\n      break;\n    }\n}\n\nstatic void\nread_mat5_binary_data (std::istream& is, float *data,\n                       octave_idx_type  count, bool swap, mat5_data_type type,\n                       octave::mach_info::float_format flt_fmt)\n{\n\n  switch (type)\n    {\n    case miINT8:\n      read_floats (is, data, LS_CHAR, count, swap, flt_fmt);\n      break;\n\n    case miUTF8:\n    case miUINT8:\n      read_floats (is, data, LS_U_CHAR, count, swap, flt_fmt);\n      break;\n\n    case miINT16:\n      read_floats (is, data, LS_SHORT, count, swap, flt_fmt);\n      break;\n\n    case miUTF16:\n    case miUINT16:\n      read_floats (is, data, LS_U_SHORT, count, swap, flt_fmt);\n      break;\n\n    case miINT32:\n      read_floats (is, data, LS_INT, count, swap, flt_fmt);\n      break;\n\n    case miUTF32:\n    case miUINT32:\n      read_floats (is, data, LS_U_INT, count, swap, flt_fmt);\n      break;\n\n    case miSINGLE:\n      read_floats (is, data, LS_FLOAT, count, swap, flt_fmt);\n      break;\n\n    case miRESERVE1:\n      break;\n\n    case miDOUBLE:\n      read_floats (is, data, LS_DOUBLE, count, swap, flt_fmt);\n      break;\n\n    case miRESERVE2:\n    case miRESERVE3:\n      break;\n\n    // FIXME: how are the 64-bit cases supposed to work here?\n    case miINT64:\n      read_floats (is, data, LS_LONG, count, swap, flt_fmt);\n      break;\n\n    case miUINT64:\n      read_floats (is, data, LS_U_LONG, count, swap, flt_fmt);\n      break;\n\n    case miMATRIX:\n    default:\n      break;\n    }\n}\n\ntemplate <typename T>\nvoid\nread_mat5_integer_data (std::istream& is, T *m, octave_idx_type count,\n                        bool swap, mat5_data_type type)\n{\n\n#define READ_INTEGER_DATA(TYPE, swap, data, size, len, stream)          \\\n  do                                                                    \\\n    {                                                                   \\\n      if (len > 0)                                                      \\\n        {                                                               \\\n          OCTAVE_LOCAL_BUFFER (TYPE, ptr, len);                         \\\n          std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \\\n          stream.read (reinterpret_cast<char *> (ptr), n_bytes);        \\\n          if (swap)                                                     \\\n            swap_bytes< size > (ptr, len);                              \\\n          for (octave_idx_type i = 0; i < len; i++)                     \\\n            data[i] = ptr[i];                                           \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\n  switch (type)\n    {\n    case miINT8:\n      READ_INTEGER_DATA (int8_t, swap, m, 1, count, is);\n      break;\n\n    case miUINT8:\n      READ_INTEGER_DATA (uint8_t, swap, m, 1, count, is);\n      break;\n\n    case miINT16:\n      READ_INTEGER_DATA (int16_t, swap, m, 2, count, is);\n      break;\n\n    case miUINT16:\n      READ_INTEGER_DATA (uint16_t, swap, m, 2, count, is);\n      break;\n\n    case miINT32:\n      READ_INTEGER_DATA (int32_t, swap, m, 4, count, is);\n      break;\n\n    case miUINT32:\n      READ_INTEGER_DATA (uint32_t, swap, m, 4, count, is);\n      break;\n\n    case miSINGLE:\n    case miRESERVE1:\n    case miDOUBLE:\n    case miRESERVE2:\n    case miRESERVE3:\n      break;\n\n    case miINT64:\n      READ_INTEGER_DATA (int64_t, swap, m, 8, count, is);\n      break;\n\n    case miUINT64:\n      READ_INTEGER_DATA (uint64_t, swap, m, 8, count, is);\n      break;\n\n    case miMATRIX:\n    default:\n      break;\n    }\n\n#undef READ_INTEGER_DATA\n\n}\n\ntemplate void\nread_mat5_integer_data (std::istream& is, octave_int8 *m,\n                        octave_idx_type count, bool swap,\n                        mat5_data_type type);\n\ntemplate void\nread_mat5_integer_data (std::istream& is, octave_int16 *m,\n                        octave_idx_type count, bool swap,\n                        mat5_data_type type);\n\ntemplate void\nread_mat5_integer_data (std::istream& is, octave_int32 *m,\n                        octave_idx_type count, bool swap,\n                        mat5_data_type type);\n\ntemplate void\nread_mat5_integer_data (std::istream& is, octave_int64 *m,\n                        octave_idx_type count, bool swap,\n                        mat5_data_type type);\n\ntemplate void\nread_mat5_integer_data (std::istream& is, octave_uint8 *m,\n                        octave_idx_type count, bool swap,\n                        mat5_data_type type);\n\ntemplate void\nread_mat5_integer_data (std::istream& is, octave_uint16 *m,\n                        octave_idx_type count, bool swap,\n                        mat5_data_type type);\n\ntemplate void\nread_mat5_integer_data (std::istream& is, octave_uint32 *m,\n                        octave_idx_type count, bool swap,\n                        mat5_data_type type);\n\ntemplate void\nread_mat5_integer_data (std::istream& is, octave_uint64 *m,\n                        octave_idx_type count, bool swap,\n                        mat5_data_type type);\n\ntemplate void\nread_mat5_integer_data (std::istream& is, int *m,\n                        octave_idx_type count, bool swap,\n                        mat5_data_type type);\n\n#define OCTAVE_MAT5_INTEGER_READ(TYP)                                   \\\n  {                                                                     \\\n    TYP re (dims);                                                      \\\n                                                                        \\\n    std::streampos tmp_pos;                                             \\\n                                                                        \\\n    if (read_mat5_tag (is, swap, type, len, is_small_data_element))     \\\n      error (\"load: reading matrix data for '%s'\", retval.c_str ());    \\\n                                                                        \\\n    octave_idx_type n = re.numel ();                                    \\\n    tmp_pos = is.tellg ();                                              \\\n    read_mat5_integer_data (is, re.rwdata (), n, swap,             \\\n                            static_cast<enum mat5_data_type> (type));   \\\n                                                                        \\\n    if (! is)                                                           \\\n      error (\"load: reading matrix data for '%s'\", retval.c_str ());    \\\n                                                                        \\\n    is.seekg (tmp_pos + static_cast<std::streamoff>                     \\\n              (READ_PAD (is_small_data_element, len)));                 \\\n                                                                        \\\n    if (imag)                                                           \\\n      {                                                                 \\\n        /* We don't handle imag integer types, convert to an array */   \\\n        NDArray im (dims);                                              \\\n                                                                        \\\n        if (read_mat5_tag (is, swap, type, len, is_small_data_element)) \\\n          error (\"load: reading matrix data for '%s'\",                  \\\n                 retval.c_str ());                                      \\\n                                                                        \\\n        n = im.numel ();                                                \\\n        read_mat5_binary_data (is, im.rwdata (), n, swap,          \\\n                               static_cast<enum mat5_data_type> (type), flt_fmt); \\\n                                                                        \\\n        if (! is)                                                       \\\n          error (\"load: reading imaginary matrix data for '%s'\",        \\\n                 retval.c_str ());                                      \\\n                                                                        \\\n        ComplexNDArray ctmp (dims);                                     \\\n                                                                        \\\n        for (octave_idx_type i = 0; i < n; i++)                         \\\n          ctmp(i) = Complex (re(i).double_value (), im(i));             \\\n                                                                        \\\n        tc = ctmp;                                                      \\\n      }                                                                 \\\n    else                                                                \\\n      tc = re;                                                          \\\n  }\n\n// Read one element tag from stream IS,\n// place the type code in TYPE, the byte count in BYTES and true (false) to\n// IS_SMALL_DATA_ELEMENT if the tag is 4 (8) bytes long.\n// return nonzero on error\nstatic int\nread_mat5_tag (std::istream& is, bool swap, int32_t& type, int32_t& bytes,\n               bool& is_small_data_element)\n{\n  unsigned int upper;\n  int32_t temp;\n\n  if (! is.read (reinterpret_cast<char *> (&temp), 4))\n    return 1;\n\n  if (swap)\n    swap_bytes<4> (&temp);\n\n  upper = (temp >> 16) & 0xffff;\n  type = temp & 0xffff;\n\n  if (upper)\n    {\n      // \"compressed\" format\n      bytes = upper;\n      is_small_data_element = true;\n    }\n  else\n    {\n      if (! is.read (reinterpret_cast<char *> (&temp), 4))\n        return 1;\n      if (swap)\n        swap_bytes<4> (&temp);\n      bytes = temp;\n      is_small_data_element = false;\n    }\n\n  return 0;\n}\n\nstatic void\nread_int (std::istream& is, bool swap, int32_t& val)\n{\n  is.read (reinterpret_cast<char *> (&val), 4);\n\n  if (swap)\n    swap_bytes<4> (&val);\n}\n\n// Extract one data element (scalar, matrix, string, etc.) from stream\n// IS and place it in TC, returning the name of the variable.\n//\n// The data is expected to be in Matlab's \"Version 5\" .mat format,\n// though not all the features of that format are supported.\n//\n// FILENAME is used for error messages.\n\nstd::string\nread_mat5_binary_element (std::istream& is, const std::string& filename,\n                          bool swap, bool& global, octave_value& tc)\n{\n  std::string retval;\n\n  global = false;\n\n  // NOTE: these are initialized here instead of closer to where they\n  // are first used to avoid errors from gcc about goto crossing\n  // initialization of variable.\n\n  bool imag;\n  bool isclass = false;\n  bool logicalvar;\n  dim_vector dims;\n  enum arrayclasstype arrayclass;\n  octave_idx_type nzmax;\n  std::string classname;\n\n  bool flt_fmt_is_big_endian\n    = (octave::mach_info::native_float_format ()\n       == octave::mach_info::flt_fmt_ieee_big_endian);\n\n  // MAT files always use IEEE floating point\n  octave::mach_info::float_format flt_fmt = octave::mach_info::flt_fmt_unknown;\n  if ((flt_fmt_is_big_endian && ! swap) || (! flt_fmt_is_big_endian && swap))\n    flt_fmt = octave::mach_info::flt_fmt_ieee_big_endian;\n  else\n    flt_fmt = octave::mach_info::flt_fmt_ieee_little_endian;\n\n  // element type, length and small data element flag\n  int32_t type = 0;\n  int32_t element_length;\n  bool is_small_data_element;\n  if (read_mat5_tag (is, swap, type, element_length, is_small_data_element))\n    return retval;                      // EOF\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  if (type == miCOMPRESSED)\n    {\n#if defined (HAVE_ZLIB)\n      // If C++ allowed us direct access to the file descriptor of an\n      // ifstream in a uniform way, the code below could be vastly\n      // simplified, and additional copies of the data in memory\n      // wouldn't be needed.\n\n      OCTAVE_LOCAL_BUFFER (char, inbuf, element_length);\n      is.read (inbuf, element_length);\n\n      // We uncompress the first 8 bytes of the header to get the buffer length\n      // This will fail with an error Z_MEM_ERROR\n      uLongf destLen = 8;\n      uLongf elt_len = element_length;\n      OCTAVE_LOCAL_BUFFER (unsigned int, tmp, 2);\n      if (uncompress2 (reinterpret_cast<Bytef *> (tmp), &destLen,\n                       reinterpret_cast<Bytef *> (inbuf), &elt_len)\n          == Z_MEM_ERROR)\n        error (\"load: error probing size of compressed data element\");\n\n      // Why should I have to initialize outbuf as I'll just overwrite!!\n      if (swap)\n        swap_bytes<4> (tmp, 2);\n\n      destLen = tmp[1] + 8;\n      std::string outbuf (destLen, ' ');\n\n      // FIXME: find a way to avoid casting away const here!\n\n      elt_len = element_length;\n      int err = uncompress2 (reinterpret_cast<Bytef *>\n                             (const_cast<char *> (outbuf.c_str ())),\n                             &destLen, reinterpret_cast<Bytef *> (inbuf),\n                             &elt_len);\n\n      // Ignore buffer error if we have consumed all the input buffer\n      // and uncompressing the data generated as many bytes of output as\n      // we were expecting given the data element size that was stored\n      // in the Matlab data element header.\n      if (err == Z_BUF_ERROR && destLen == tmp[1] + 8\n          && elt_len == static_cast<uLongf> (element_length))\n        err = Z_OK;\n\n      if (err != Z_OK)\n        {\n          std::string msg;\n          switch (err)\n            {\n            case Z_STREAM_END:\n              msg = \"stream end\";\n              break;\n\n            case Z_NEED_DICT:\n              msg = \"need dict\";\n              break;\n\n            case Z_ERRNO:\n              msg = \"errno case\";\n              break;\n\n            case Z_STREAM_ERROR:\n              msg = \"stream error\";\n              break;\n\n            case Z_DATA_ERROR:\n              msg = \"data error\";\n              break;\n\n            case Z_MEM_ERROR:\n              msg = \"mem error\";\n              break;\n\n            case Z_BUF_ERROR:\n              msg = \"buf error\";\n              break;\n\n            case Z_VERSION_ERROR:\n              msg = \"version error\";\n              break;\n            }\n\n          error (\"load: error uncompressing data element (%s from zlib)\",\n                 msg.c_str ());\n        }\n      else\n        {\n          std::istringstream gz_is (outbuf);\n          retval = read_mat5_binary_element (gz_is, filename,\n                                             swap, global, tc);\n        }\n\n      return retval;\n\n#else\n      err_disabled_feature (\"load\", \"compressed data elements (zlib)\");\n#endif\n    }\n\n  std::streampos pos;\n\n  if (type != miMATRIX)\n    {\n      pos = is.tellg ();\n      error (\"load: invalid element type = %d\", type);\n    }\n\n  if (element_length == 0)\n    {\n      tc = Matrix ();\n      return retval;\n    }\n\n  pos = is.tellg ();\n\n  // array flags subelement\n  int32_t len;\n  if (read_mat5_tag (is, swap, type, len, is_small_data_element)\n      || type != miUINT32 || len != 8 || is_small_data_element)\n    error (\"load: invalid array flags subelement\");\n\n  int32_t flags;\n  read_int (is, swap, flags);\n\n  imag = (flags & 0x0800) != 0; // has an imaginary part?\n\n  global = (flags & 0x0400) != 0; // global variable?\n\n  logicalvar = (flags & 0x0200) != 0; // boolean ?\n\n  arrayclass = static_cast<arrayclasstype> (flags & 0xff);\n\n  int32_t tmp_nzmax;\n  read_int (is, swap, tmp_nzmax);   // max number of nonzero in sparse\n  nzmax = tmp_nzmax;\n\n  // dimensions array subelement\n  if (arrayclass != MAT_FILE_WORKSPACE_CLASS)\n    {\n      int32_t dim_len;\n\n      if (read_mat5_tag (is, swap, type, dim_len, is_small_data_element)\n          || type != miINT32)\n        error (\"load: invalid dimensions array subelement\");\n\n      int ndims = dim_len / 4;\n      if (ndims == 1)\n        {\n          // R and Python can create a 1-D object which is really an Nx1 object\n          dims.resize (2);\n          dims(1) = 1;\n        }\n      else\n        dims.resize (ndims);\n\n      for (int i = 0; i < ndims; i++)\n        {\n          int32_t n;\n          read_int (is, swap, n);\n          dims(i) = n;\n        }\n\n      std::streampos tmp_pos = is.tellg ();\n      is.seekg (tmp_pos + static_cast<std::streamoff>\n                (READ_PAD (is_small_data_element, dim_len) - dim_len));\n    }\n\n  if (read_mat5_tag (is, swap, type, len, is_small_data_element)\n      || ! INT8 (type))\n    error (\"load: invalid array name subelement\");\n\n  {\n    OCTAVE_LOCAL_BUFFER (char, name, len+1);\n\n    // Structure field subelements have zero-length array name subelements.\n\n    std::streampos tmp_pos = is.tellg ();\n\n    if (len)\n      {\n        if (! is.read (name, len))\n          goto data_read_error;\n\n        is.seekg (tmp_pos + static_cast<std::streamoff>\n                  (READ_PAD (is_small_data_element, len)));\n      }\n\n    name[len] = '\\0';\n    retval = name;\n  }\n\n  switch (arrayclass)\n    {\n    case MAT_FILE_CELL_CLASS:\n      {\n        Cell cell_array (dims);\n\n        octave_idx_type n = cell_array.numel ();\n\n        for (octave_idx_type i = 0; i < n; i++)\n          {\n            octave_value tc2;\n\n            std::string nm\n              = read_mat5_binary_element (is, filename, swap, global, tc2);\n\n            if (! is)\n              error (\"load: reading cell data for '%s'\", nm.c_str ());\n\n            cell_array(i) = tc2;\n          }\n\n        tc = cell_array;\n      }\n      break;\n\n    case MAT_FILE_SPARSE_CLASS:\n      {\n        octave_idx_type nr = dims(0);\n        octave_idx_type nc = dims(1);\n        SparseMatrix sm;\n        SparseComplexMatrix scm;\n        octave_idx_type *ridx;\n        octave_idx_type *cidx;\n        double *data;\n\n        // Setup return value\n        if (imag)\n          {\n            scm = SparseComplexMatrix (nr, nc, nzmax);\n            ridx = scm.ridx ();\n            cidx = scm.cidx ();\n            data = nullptr;\n          }\n        else\n          {\n            sm = SparseMatrix (nr, nc, nzmax);\n            ridx = sm.ridx ();\n            cidx = sm.cidx ();\n            data = sm.data ();\n          }\n\n        // row indices\n        std::streampos tmp_pos;\n\n        if (read_mat5_tag (is, swap, type, len, is_small_data_element))\n          error (\"load: reading sparse row data for '%s'\", retval.c_str ());\n\n        tmp_pos = is.tellg ();\n\n        read_mat5_integer_data (is, ridx, nzmax, swap,\n                                static_cast<enum mat5_data_type> (type));\n\n        if (! is)\n          error (\"load: reading sparse row data for '%s'\", retval.c_str ());\n\n        is.seekg (tmp_pos + static_cast<std::streamoff>\n                  (READ_PAD (is_small_data_element, len)));\n\n        // col indices\n        if (read_mat5_tag (is, swap, type, len, is_small_data_element))\n          error (\"load: reading sparse column data for '%s'\",\n                 retval.c_str ());\n\n        tmp_pos = is.tellg ();\n\n        read_mat5_integer_data (is, cidx, nc + 1, swap,\n                                static_cast<enum mat5_data_type> (type));\n\n        if (! is)\n          error (\"load: reading sparse column data for '%s'\",\n                 retval.c_str ());\n\n        is.seekg (tmp_pos + static_cast<std::streamoff>\n                  (READ_PAD (is_small_data_element, len)));\n\n        // real data subelement\n        if (read_mat5_tag (is, swap, type, len, is_small_data_element))\n          error (\"load: reading sparse matrix data for '%s'\",\n                 retval.c_str ());\n\n        octave_idx_type nnz = cidx[nc];\n        NDArray re;\n        if (imag)\n          {\n            re = NDArray (dim_vector (nnz, 1));\n            data = re.rwdata ();\n          }\n\n        tmp_pos = is.tellg ();\n        read_mat5_binary_data (is, data, nnz, swap,\n                               static_cast<enum mat5_data_type> (type),\n                               flt_fmt);\n\n        if (! is)\n          error (\"load: reading sparse matrix data for '%s'\",\n                 retval.c_str ());\n\n        is.seekg (tmp_pos + static_cast<std::streamoff>\n                  (READ_PAD (is_small_data_element, len)));\n\n        // imaginary data subelement\n        if (imag)\n          {\n            NDArray im (dim_vector (static_cast<int> (nnz), 1));\n\n            if (read_mat5_tag (is, swap, type, len, is_small_data_element))\n              error (\"load: reading sparse matrix data for '%s'\",\n                     retval.c_str ());\n\n            read_mat5_binary_data (is, im.rwdata (), nnz, swap,\n                                   static_cast<enum mat5_data_type> (type),\n                                   flt_fmt);\n\n            if (! is)\n              error (\"load: reading imaginary sparse matrix data for '%s'\",\n                     retval.c_str ());\n\n            for (octave_idx_type i = 0; i < nnz; i++)\n              scm.xdata (i) = Complex (re (i), im (i));\n\n            tc = scm;\n          }\n        else\n          tc = sm;\n      }\n      break;\n\n    case MAT_FILE_FUNCTION_CLASS:\n      {\n        octave_value tc2;\n        std::string nm\n          = read_mat5_binary_element (is, filename, swap, global, tc2);\n\n        if (! is)\n          goto data_read_error;\n\n        // Octave can handle both \"/\" and \"\\\" as a directory separator\n        // and so can ignore the separator field of m0.  I think the\n        // sentinel field is also save to ignore.\n        octave_scalar_map m0 = tc2.scalar_map_value ();\n        octave_scalar_map m1\n          = m0.contents (\"function_handle\").scalar_map_value ();\n        std::string ftype = m1.contents (\"type\").string_value ();\n        std::string fname = m1.contents (\"function\").string_value ();\n        std::string fpath = m1.contents (\"file\").string_value ();\n\n        if (ftype == \"simple\" || ftype == \"scopedfunction\")\n          {\n            if (fpath.empty ())\n              {\n                octave::tree_evaluator& tw = interp.get_evaluator ();\n\n                // We have a builtin function\n                // XXX FCN_HANDLE: SIMPLE/SCOPED\n                tc = tw.make_fcn_handle (fname);\n              }\n            else\n              {\n                std::string mroot = m0.contents (\"matlabroot\").string_value ();\n\n                if ((fpath.length () >= mroot.length ())\n                    && fpath.substr (0, mroot.length ()) == mroot\n                    && octave::config::octave_exec_home () != mroot)\n                  {\n                    // If fpath starts with matlabroot, and matlabroot\n                    // doesn't equal __octave_config_info__ (\"exec_prefix\")\n                    // then the function points to a version of Octave\n                    // or Matlab other than the running version.  In that\n                    // case we replace with the same function in the\n                    // running version of Octave?\n\n                    // First check if just replacing matlabroot is enough\n                    std::string str\n                      = (octave::config::octave_exec_home ()\n                         + fpath.substr (mroot.length ()));\n\n                    if (octave::sys::file_exists (str))\n                      {\n                        std::size_t xpos\n                          = str.find_last_of (octave::sys::file_ops::dir_sep_chars ());\n\n                        std::string dir_name = str.substr (0, xpos);\n\n                        octave_value ov_fcn\n                          = octave::load_fcn_from_file (str, dir_name,\n                                                        \"\", \"\", fname);\n\n                        if (ov_fcn.is_defined ())\n                          // XXX FCN_HANDLE: SIMPLE/SCOPED\n                          tc = octave_value (new octave_fcn_handle (ov_fcn,\n                                             fname));\n                      }\n                    else\n                      {\n                        // Next just search for it anywhere in the system path\n                        std::list<std::string> names;\n                        names.push_back (fname + \".oct\");\n                        names.push_back (fname + \".mex\");\n                        names.push_back (fname + \".m\");\n\n                        octave::load_path& lp = interp.get_load_path ();\n\n                        octave::directory_path p (lp.system_path ());\n\n                        str = octave::sys::env::make_absolute (p.find_first_of (names));\n\n                        std::size_t xpos\n                          = str.find_last_of (octave::sys::file_ops::dir_sep_chars ());\n\n                        std::string dir_name = str.substr (0, xpos);\n\n                        octave_value ov_fcn\n                          = octave::load_fcn_from_file (str, dir_name,\n                                                        \"\", \"\", fname);\n\n                        if (ov_fcn.is_defined ())\n                          // XXX FCN_HANDLE: SIMPLE/SCOPED\n                          tc = octave_value (new octave_fcn_handle (ov_fcn,\n                                             fname));\n                        else\n                          {\n                            warning_with_id (\"Octave:load:file-not-found\",\n                                             \"load: can't find the file %s\",\n                                             fpath.c_str ());\n                            goto skip_ahead;\n                          }\n                      }\n                  }\n                else\n                  {\n                    std::size_t xpos\n                      = fpath.find_last_of (octave::sys::file_ops::dir_sep_chars ());\n\n                    std::string dir_name = fpath.substr (0, xpos);\n\n                    octave_value ov_fcn\n                      = octave::load_fcn_from_file (fpath, dir_name,\n                                                    \"\", \"\", fname);\n\n                    if (ov_fcn.is_defined ())\n                      // XXX FCN_HANDLE: SIMPLE/SCOPED\n                      tc = octave_value (new octave_fcn_handle (ov_fcn, fname));\n                    else\n                      {\n                        warning_with_id (\"Octave:load:file-not-found\",\n                                         \"load: can't find the file %s\",\n                                         fpath.c_str ());\n                        goto skip_ahead;\n                      }\n                  }\n              }\n          }\n        else if (ftype == \"nested\")\n          {\n            warning_with_id (\"Octave:load:unsupported-type\",\n                             \"load: can't load nested function\");\n            goto skip_ahead;\n          }\n        else if (ftype == \"anonymous\")\n          {\n            // get workspace context of anonymous function handle\n            tc2 = m1.contents (\"workspace\");\n\n            octave::stack_frame::local_vars_map local_vars;\n\n            if (! tc2.isempty ())\n              {\n                octave_scalar_map m2 = tc2.scalar_map_value ();\n\n                if (m2.nfields () > 0)\n                  {\n                    for (auto p0 = m2.begin (); p0 != m2.end (); p0++)\n                      {\n                        std::string key = m2.key (p0);\n                        octave_value val = m2.contents (p0);\n\n                        local_vars[key] = val;\n                      }\n                  }\n              }\n\n            // Set up temporary scope to use for evaluating the text\n            // that defines the anonymous function so that we don't\n            // pick up values of random variables that might be in the\n            // current scope.\n\n            octave::tree_evaluator& tw = interp.get_evaluator ();\n            tw.push_dummy_scope (\"read_mat5_binary_element\");\n\n            octave::unwind_action act ([&tw] () { tw.pop_scope (); });\n\n            // FIXME: If evaluation of the string gives us an anonymous\n            // function handle object, then why extract the function and\n            // create a new anonymous function object?  Why not just\n            // attach the workspace values to the object returned by\n            // eval_string?  This code is also is duplicated in\n            // anon_fcn_handle::parse_anon_fcn_handle.\n\n            int parse_status;\n            octave_value anon_fcn_handle\n              = interp.eval_string (fname.substr (4), true, parse_status);\n\n            if (parse_status != 0)\n              error (\"load: failed to load anonymous function handle\");\n\n            octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();\n\n            if (! fh)\n              error (\"load: failed to load anonymous function handle\");\n\n            // XXX FCN_HANDLE: ANONYMOUS\n            tc = octave_value (new octave_fcn_handle (fh->fcn_val (),\n                                                      local_vars));\n          }\n        else\n          error (\"load: invalid function handle type\");\n      }\n      break;\n\n    case MAT_FILE_WORKSPACE_CLASS:\n      {\n\n        std::string type_system;\n        if (read_mat5_tag (is, swap, type, len, is_small_data_element)\n            || ! INT8 (type))\n          error (\"load: invalid type system\");\n\n        {\n          // Type System\n          OCTAVE_LOCAL_BUFFER (char, name, len+1);\n\n          std::streampos tmp_pos = is.tellg ();\n\n          if (len)\n            {\n              if (! is.read (name, len))\n                goto data_read_error;\n\n              is.seekg (tmp_pos + static_cast<std::streamoff>\n                        (READ_PAD (is_small_data_element, len)));\n            }\n\n          name[len] = '\\0';\n          type_system = name;\n        }\n\n\n        if (read_mat5_tag (is, swap, type, len, is_small_data_element)\n            || ! INT8 (type))\n          error (\"load: invalid class name\");\n\n        {\n          // Class Name\n          OCTAVE_LOCAL_BUFFER (char, name, len+1);\n\n          std::streampos tmp_pos = is.tellg ();\n\n          if (len)\n            {\n              if (! is.read (name, len))\n                goto data_read_error;\n\n              is.seekg (tmp_pos + static_cast<std::streamoff>\n                        (READ_PAD (is_small_data_element, len)));\n            }\n\n          name[len] = '\\0';\n          classname = name;\n        }\n\n        octave_value objmetadata;\n        read_mat5_binary_element (is, filename, swap, global, objmetadata);\n        if (! is)\n          goto data_read_error;\n\n        if (type_system != \"MCOS\")\n          {\n            // Other type systems known are \"java\" and \"handle\"\n            // java is used for java objects\n            // handle is used for certain COM objects\n            warning_with_id (\"Octave:load:classdef-not-supported\",\n                             \"load: MATLAB class object with type system '%s' \"\n                             \"not supported.  Loading as %s\",\n                              type_system.c_str (),\n                              objmetadata.class_name ().c_str ());\n            tc = objmetadata;\n          }\n        else if (classname == \"FileWrapper__\")\n          {\n            // \"FileWrapper__\" objects contain serialized object data as a cell\n            // array.  In MATLAB, this is an MCOS class with a constructor and\n            // no properties.\n            // Return the serialized data for these cases.\n            tc = objmetadata;\n          }\n        else if (objmetadata.isstruct ())\n          {\n            warning_with_id (\"Octave:load:classdef-not-supported\",\n                             \"load: MATLAB enumeration classes are not \"\n                             \"supported.  Loading as %s\",\n                             objmetadata.class_name ().c_str ());\n            tc = objmetadata;\n          }\n        else\n          {\n            // \"function_handle_workspace\" objects contain data of the\n            // workspace context of function handles.\n            // FIXME: Add compatible implementation of this class.\n            tc = octave::load_mcos_object (objmetadata,\n                                           classname == \"function_handle_workspace\");\n          }\n      }\n\n      break;\n\n    case MAT_FILE_OBJECT_CLASS:\n      {\n        isclass = true;\n\n        if (read_mat5_tag (is, swap, type, len, is_small_data_element)\n            || ! INT8 (type))\n          error (\"load: invalid class name\");\n\n        {\n          OCTAVE_LOCAL_BUFFER (char, name, len+1);\n\n          std::streampos tmp_pos = is.tellg ();\n\n          if (len)\n            {\n              if (! is.read (name, len))\n                goto data_read_error;\n\n              is.seekg (tmp_pos + static_cast<std::streamoff>\n                        (READ_PAD (is_small_data_element, len)));\n            }\n\n          name[len] = '\\0';\n          classname = name;\n        }\n      }\n    // Fall-through\n\n    case MAT_FILE_STRUCT_CLASS:\n      {\n        octave_map m (dims);\n        int32_t fn_type;\n        int32_t fn_len;\n        int32_t field_name_length;\n\n        // field name length subelement -- actually the maximum length\n        // of a field name.  The Matlab docs promise this will always\n        // be 32.  We read and use the actual value, on the theory\n        // that eventually someone will recognize that's a waste of space.\n        if (read_mat5_tag (is, swap, fn_type, fn_len, is_small_data_element)\n            || fn_type != miINT32)\n          error (\"load: invalid field name length subelement\");\n\n        if (! is.read (reinterpret_cast<char *> (&field_name_length), fn_len))\n          goto data_read_error;\n\n        if (swap)\n          swap_bytes<4> (&field_name_length);\n\n        // field name subelement.  The length of this subelement tells\n        // us how many fields there are.\n        if (read_mat5_tag (is, swap, fn_type, fn_len, is_small_data_element)\n            || ! INT8 (fn_type))\n          error (\"load: invalid field name subelement\");\n\n        octave_idx_type n_fields = fn_len/field_name_length;\n\n        if (n_fields > 0)\n          {\n            fn_len = READ_PAD (is_small_data_element, fn_len);\n\n            OCTAVE_LOCAL_BUFFER (char, elname, fn_len);\n\n            if (! is.read (elname, fn_len))\n              goto data_read_error;\n\n            std::vector<Cell> elt (n_fields);\n\n            for (octave_idx_type i = 0; i < n_fields; i++)\n              elt[i] = Cell (dims);\n\n            octave_idx_type n = dims.numel ();\n\n            // fields subelements\n            for (octave_idx_type j = 0; j < n; j++)\n              {\n                for (octave_idx_type i = 0; i < n_fields; i++)\n                  {\n                    octave_value fieldtc;\n                    read_mat5_binary_element (is, filename, swap, global,\n                                              fieldtc);\n                    elt[i](j) = fieldtc;\n                  }\n              }\n\n            for (octave_idx_type i = 0; i < n_fields; i++)\n              {\n                const char *key = elname + i*field_name_length;\n\n                m.assign (key, elt[i]);\n              }\n          }\n\n        if (isclass)\n          {\n            octave::cdef_manager& cdm = interp.get_cdef_manager ();\n\n            if (cdm.find_class (classname, false, true).ok ())\n              {\n                tc = m;\n                warning_with_id (\"Octave:load:classdef-to-struct\",\n                                 \"load: classdef element has been converted to a struct\");\n              }\n            else\n              {\n                octave_class *cls\n                  = new octave_class (m, classname,\n                                      std::list<std::string> ());\n\n                if (cls->reconstruct_exemplar ())\n                  {\n\n                    if (! cls->reconstruct_parents ())\n                      warning_with_id (\"Octave:load:classdef-object-inheritance\",\n                                       \"load: unable to reconstruct object inheritance\");\n\n                    tc = cls;\n\n                    octave::load_path& lp = interp.get_load_path ();\n\n                    if (lp.find_method (classname, \"loadobj\") != \"\")\n                      {\n                        try\n                          {\n                            octave_value_list tmp = interp.feval (\"loadobj\", tc, 1);\n\n                            tc = tmp(0);\n                          }\n                        catch (const octave::execution_exception&)\n                          {\n                            goto data_read_error;\n                          }\n                      }\n                  }\n                else\n                  {\n                    tc = m;\n                    warning_with_id (\"Octave:load:classdef-to-struct\",\n                                     \"load: element has been converted to a structure\");\n                  }\n              }\n          }\n        else\n          tc = m;\n      }\n      break;\n\n    case MAT_FILE_INT8_CLASS:\n      OCTAVE_MAT5_INTEGER_READ (int8NDArray);\n      break;\n\n    case MAT_FILE_UINT8_CLASS:\n      {\n        OCTAVE_MAT5_INTEGER_READ (uint8NDArray);\n\n        // Logical variables can either be MAT_FILE_UINT8_CLASS or\n        // MAT_FILE_DOUBLE_CLASS, so check if we have a logical\n        // variable and convert it.\n\n        if (logicalvar)\n          {\n            uint8NDArray in = tc.uint8_array_value ();\n            octave_idx_type nel = in.numel ();\n            boolNDArray out (dims);\n\n            for (octave_idx_type i = 0; i < nel; i++)\n              out(i) = in(i).bool_value ();\n\n            tc = out;\n          }\n      }\n      break;\n\n    case MAT_FILE_INT16_CLASS:\n      OCTAVE_MAT5_INTEGER_READ (int16NDArray);\n      break;\n\n    case MAT_FILE_UINT16_CLASS:\n      OCTAVE_MAT5_INTEGER_READ (uint16NDArray);\n      break;\n\n    case MAT_FILE_INT32_CLASS:\n      OCTAVE_MAT5_INTEGER_READ (int32NDArray);\n      break;\n\n    case MAT_FILE_UINT32_CLASS:\n      OCTAVE_MAT5_INTEGER_READ (uint32NDArray);\n      break;\n\n    case MAT_FILE_INT64_CLASS:\n      OCTAVE_MAT5_INTEGER_READ (int64NDArray);\n      break;\n\n    case MAT_FILE_UINT64_CLASS:\n      OCTAVE_MAT5_INTEGER_READ (uint64NDArray);\n      break;\n\n    case MAT_FILE_SINGLE_CLASS:\n      {\n        FloatNDArray re (dims);\n\n        // real data subelement\n\n        std::streampos tmp_pos;\n\n        if (read_mat5_tag (is, swap, type, len, is_small_data_element))\n          error (\"load: reading matrix data for '%s'\", retval.c_str ());\n\n        octave_idx_type n = re.numel ();\n        tmp_pos = is.tellg ();\n        read_mat5_binary_data (is, re.rwdata (), n, swap,\n                               static_cast<enum mat5_data_type> (type),\n                               flt_fmt);\n\n        if (! is)\n          error (\"load: reading matrix data for '%s'\", retval.c_str ());\n\n        is.seekg (tmp_pos + static_cast<std::streamoff>\n                  (READ_PAD (is_small_data_element, len)));\n\n        if (imag)\n          {\n            // imaginary data subelement\n\n            FloatNDArray im (dims);\n\n            if (read_mat5_tag (is, swap, type, len, is_small_data_element))\n              error (\"load: reading matrix data for '%s'\", retval.c_str ());\n\n            n = im.numel ();\n            read_mat5_binary_data (is, im.rwdata (), n, swap,\n                                   static_cast<enum mat5_data_type> (type),\n                                   flt_fmt);\n\n            if (! is)\n              error (\"load: reading imaginary matrix data for '%s'\",\n                     retval.c_str ());\n\n            FloatComplexNDArray ctmp (dims);\n\n            for (octave_idx_type i = 0; i < n; i++)\n              ctmp(i) = FloatComplex (re(i), im(i));\n\n            tc = ctmp;\n          }\n        else\n          tc = re;\n      }\n      break;\n\n    case MAT_FILE_CHAR_CLASS:\n    // handle as a numerical array to start with\n\n    case MAT_FILE_DOUBLE_CLASS:\n    default:\n      {\n        NDArray re (dims);\n\n        // real data subelement\n\n        std::streampos tmp_pos;\n\n        if (read_mat5_tag (is, swap, type, len, is_small_data_element))\n          error (\"load: reading matrix data for '%s'\", retval.c_str ());\n\n        octave_idx_type n = re.numel ();\n        tmp_pos = is.tellg ();\n        read_mat5_binary_data (is, re.rwdata (), n, swap,\n                               static_cast<enum mat5_data_type> (type),\n                               flt_fmt);\n\n        if (! is)\n          error (\"load: reading matrix data for '%s'\", retval.c_str ());\n\n        is.seekg (tmp_pos + static_cast<std::streamoff>\n                  (READ_PAD (is_small_data_element, len)));\n\n        if (logicalvar)\n          {\n            // Logical variables can either be MAT_FILE_UINT8_CLASS or\n            // MAT_FILE_DOUBLE_CLASS, so check if we have a logical\n            // variable and convert it.\n\n            boolNDArray out (dims);\n\n            for (octave_idx_type i = 0; i < n; i++)\n              out (i) = static_cast<bool> (re (i));\n\n            tc = out;\n          }\n        else if (imag)\n          {\n            // imaginary data subelement\n\n            NDArray im (dims);\n\n            if (read_mat5_tag (is, swap, type, len, is_small_data_element))\n              error (\"load: reading matrix data for '%s'\", retval.c_str ());\n\n            n = im.numel ();\n            read_mat5_binary_data (is, im.rwdata (), n, swap,\n                                   static_cast<enum mat5_data_type> (type),\n                                   flt_fmt);\n\n            if (! is)\n              error (\"load: reading imaginary matrix data for '%s'\",\n                     retval.c_str ());\n\n            ComplexNDArray ctmp (dims);\n\n            for (octave_idx_type i = 0; i < n; i++)\n              ctmp(i) = Complex (re(i), im(i));\n\n            tc = ctmp;\n          }\n        else if (arrayclass == MAT_FILE_CHAR_CLASS)\n          {\n            bool converted = false;\n            if (re.isvector () && (type == miUTF16 || type == miUINT16))\n              {\n                uint16NDArray u16 = re;\n                const uint16_t *u16_str\n                  = reinterpret_cast<const uint16_t *> (u16.data ());\n\n                // Convert to UTF-8.\n                std::size_t n8;\n                uint8_t *u8_str = octave_u16_to_u8_wrapper (u16_str,\n                                  u16.numel (),\n                                  nullptr, &n8);\n                if (u8_str)\n                  {\n                    // FIXME: Is there a better way to construct a charMatrix\n                    // from a nonzero terminated buffer?\n                    tc = charMatrix (std::string (reinterpret_cast<char *> (u8_str), n8));\n                    free (u8_str);\n                    converted = true;\n                  }\n              }\n            else if (re.isvector () && (type == miUTF32 || type == miUINT32))\n              {\n                uint32NDArray u32 = re;\n                const uint32_t *u32_str\n                  = reinterpret_cast<const uint32_t *> (u32.data ());\n\n                // Convert to UTF-8.\n                std::size_t n8;\n                uint8_t *u8_str = octave_u32_to_u8_wrapper (u32_str,\n                                  u32.numel (),\n                                  nullptr, &n8);\n                if (u8_str)\n                  {\n                    // FIXME: Is there a better way to construct a charMatrix\n                    // from a nonzero terminated buffer?\n                    tc = charMatrix (std::string (reinterpret_cast<char *> (u8_str), n8));\n                    free (u8_str);\n                    converted = true;\n                  }\n              }\n            else if (type == miUTF8 || type == miUINT8)\n              {\n                // Octave's internal encoding is UTF-8.  So we should be\n                // able to use this natively.\n                tc = re;\n                tc = tc.convert_to_str (false, true, '\\'');\n                converted = true;\n              }\n\n            if (! converted)\n              {\n                // Fall back to manually replacing non-ASCII\n                // characters by \"?\".\n                bool found_big_char = false;\n                for (octave_idx_type i = 0; i < n; i++)\n                  {\n                    if (re(i) > 127)\n                      {\n                        re(i) = '?';\n                        found_big_char = true;\n                      }\n                  }\n\n                if (found_big_char)\n                  warning_with_id (\"Octave:load:unsupported-utf-char\",\n                                   \"load: failed to convert from input to UTF-8; \"\n                                   \"replacing non-ASCII characters with '?'\");\n\n                tc = re;\n                tc = tc.convert_to_str (false, true, '\\'');\n              }\n\n          }\n        else\n          tc = re;\n      }\n    }\n\n  is.seekg (pos + static_cast<std::streamoff> (element_length));\n\n  if (is.eof ())\n    is.clear ();\n\n  return retval;\n\n// FIXME: With short-circuiting error(), no need for goto in code\ndata_read_error:\n  error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n\nskip_ahead:\n  warning_with_id (\"Octave:load:skip-unsupported-element\",\n                   \"load: skipping over '%s'\", retval.c_str ());\n  is.seekg (pos + static_cast<std::streamoff> (element_length));\n  return read_mat5_binary_element (is, filename, swap, global, tc);\n}\n\nint\nread_mat5_binary_file_header (std::istream& is, bool& swap, bool quiet,\n                              const std::string& filename)\n{\n  int16_t version = 0;\n  int16_t magic = 0;\n  uint64_t subsys_offset;\n\n  is.seekg (116, std::ios::beg);\n  is.read (reinterpret_cast<char *> (&subsys_offset), 8);\n\n  is.seekg (124, std::ios::beg);\n  is.read (reinterpret_cast<char *> (&version), 2);\n  is.read (reinterpret_cast<char *> (&magic), 2);\n\n  if (magic == 0x4d49)\n    swap = false;\n  else if (magic == 0x494d)\n    swap = true;\n  else\n    {\n      if (! quiet)\n        error (\"load: can't read binary file\");\n\n      return -1;\n    }\n\n  if (! swap)                   // version number is inverse swapped!\n    version = ((version >> 8) & 0xff) + ((version & 0xff) << 8);\n\n  if (version != 1 && ! quiet)\n    warning_with_id (\"Octave:load:unsupported-version\",\n                     \"load: found version %d binary MAT file, but only prepared for version 1\",\n                     version);\n\n  if (swap)\n    swap_bytes<8> (&subsys_offset, 1);\n\n  if (subsys_offset != UINT64_C (0x2020202020202020)\n      && subsys_offset != UINT64_C (0))\n    {\n      // Read the subsystem data block\n      is.seekg (subsys_offset, std::ios::beg);\n\n      octave_value tc;\n      bool global;\n      read_mat5_binary_element (is, filename, swap, global, tc);\n\n      if (! is)\n        return -1;\n\n      if (tc.is_uint8_type ())\n        {\n          const uint8NDArray itmp = tc.uint8_array_value ();\n          octave_idx_type ilen = itmp.numel ();\n\n          // Why should I have to initialize outbuf as just overwrite\n          std::string outbuf (ilen - 7, ' ');\n\n          // FIXME: find a way to avoid casting away const here\n          char *ctmp = const_cast<char *> (outbuf.c_str ());\n          for (octave_idx_type j = 8; j < ilen; j++)\n            ctmp[j-8] = itmp(j).char_value ();\n\n          std::istringstream fh_ws (outbuf);\n          octave_value subsys_ov;\n          read_mat5_binary_element (fh_ws, filename, swap, global, subsys_ov);\n\n          octave::subsystem_handler *sh = octave::__get_load_save_system__ ().get_subsystem_handler ();\n          if (! sh->read_mat_subsystem (subsys_ov, swap))\n            error (\"load: unable to read subsystem data from MAT-file '%s'\", filename.c_str ());\n\n          if (! is)\n            return -1;\n        }\n      else\n        return -1;\n\n      // Reposition to just after the header\n      is.seekg (128, std::ios::beg);\n    }\n\n  return 0;\n}\n\nstatic int\nwrite_mat5_tag (std::ostream& is, int type, octave_idx_type bytes)\n{\n  int32_t temp;\n\n  if (bytes > 0 && bytes <= 4)\n    temp = (bytes << 16) + type;\n  else\n    {\n      temp = type;\n      if (! is.write (reinterpret_cast<char *> (&temp), 4))\n        return 1;\n      temp = bytes;\n    }\n\n  if (! is.write (reinterpret_cast<char *> (&temp), 4))\n    return 1;\n\n  return 0;\n}\n\n// Have to use copy here to avoid writing over data accessed via\n// Matrix::data().\n\n#define MAT5_DO_WRITE(TYPE, data, count, stream)                        \\\n  do                                                                    \\\n    {                                                                   \\\n      OCTAVE_LOCAL_BUFFER (TYPE, ptr, count);                           \\\n      for (octave_idx_type i = 0; i < count; i++)                       \\\n        ptr[i] = static_cast<TYPE> (data[i]);                           \\\n      std::streamsize n_bytes = sizeof (TYPE) * static_cast<std::streamsize> (count); \\\n      stream.write (reinterpret_cast<char *> (ptr), n_bytes);           \\\n    }                                                                   \\\n  while (0)\n\n// write out the numeric values in M to OS,\n// preceded by the appropriate tag.\nstatic void\nwrite_mat5_array (std::ostream& os, const NDArray& m, bool save_as_floats)\n{\n  save_type st = LS_DOUBLE;\n  const double *data = m.data ();\n\n  if (save_as_floats)\n    {\n      if (m.too_large_for_float ())\n        {\n          warning_with_id (\"Octave:save:too-large-for-float\",\n                           \"save: some values too large to save as floats -- saving as doubles instead\");\n        }\n      else\n        st = LS_FLOAT;\n    }\n\n  double max_val, min_val;\n  if (m.all_integers (max_val, min_val))\n    st = octave::get_save_type (max_val, min_val);\n\n  mat5_data_type mst;\n  int size;\n  switch (st)\n    {\n    default:\n    case LS_DOUBLE:  mst = miDOUBLE; size = 8; break;\n    case LS_FLOAT:   mst = miSINGLE; size = 4; break;\n    case LS_U_CHAR:  mst = miUINT8;  size = 1; break;\n    case LS_U_SHORT: mst = miUINT16; size = 2; break;\n    case LS_U_INT:   mst = miUINT32; size = 4; break;\n    case LS_CHAR:    mst = miINT8;   size = 1; break;\n    case LS_SHORT:   mst = miINT16;  size = 2; break;\n    case LS_INT:     mst = miINT32;  size = 4; break;\n    }\n\n  octave_idx_type nel = m.numel ();\n  octave_idx_type len = nel*size;\n\n  write_mat5_tag (os, mst, len);\n\n  {\n    switch (st)\n      {\n      case LS_U_CHAR:\n        MAT5_DO_WRITE (uint8_t, data, nel, os);\n        break;\n\n      case LS_U_SHORT:\n        MAT5_DO_WRITE (uint16_t, data, nel, os);\n        break;\n\n      case LS_U_INT:\n        MAT5_DO_WRITE (uint32_t, data, nel, os);\n        break;\n\n      case LS_U_LONG:\n        MAT5_DO_WRITE (uint64_t, data, nel, os);\n        break;\n\n      case LS_CHAR:\n        MAT5_DO_WRITE (int8_t, data, nel, os);\n        break;\n\n      case LS_SHORT:\n        MAT5_DO_WRITE (int16_t, data, nel, os);\n        break;\n\n      case LS_INT:\n        MAT5_DO_WRITE (int32_t, data, nel, os);\n        break;\n\n      case LS_LONG:\n        MAT5_DO_WRITE (int64_t, data, nel, os);\n        break;\n\n      case LS_FLOAT:\n        MAT5_DO_WRITE (float, data, nel, os);\n        break;\n\n      case LS_DOUBLE: // No conversion necessary.\n        os.write (reinterpret_cast<const char *> (data), len);\n        break;\n\n      default:\n        error (\"unrecognized data format requested\");\n        break;\n      }\n  }\n  if (PAD (len) > len)\n    {\n      static char buf[9]=\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\";\n      os.write (buf, PAD (len) - len);\n    }\n}\n\nstatic void\nwrite_mat5_array (std::ostream& os, const FloatNDArray& m, bool)\n{\n  save_type st = LS_FLOAT;\n  const float *data = m.data ();\n\n  float max_val, min_val;\n  if (m.all_integers (max_val, min_val))\n    st = octave::get_save_type (max_val, min_val);\n\n  mat5_data_type mst;\n  int size;\n  switch (st)\n    {\n    default:\n    case LS_DOUBLE:  mst = miDOUBLE; size = 8; break;\n    case LS_FLOAT:   mst = miSINGLE; size = 4; break;\n    case LS_U_CHAR:  mst = miUINT8;  size = 1; break;\n    case LS_U_SHORT: mst = miUINT16; size = 2; break;\n    case LS_U_INT:   mst = miUINT32; size = 4; break;\n    case LS_CHAR:    mst = miINT8;   size = 1; break;\n    case LS_SHORT:   mst = miINT16;  size = 2; break;\n    case LS_INT:     mst = miINT32;  size = 4; break;\n    }\n\n  octave_idx_type nel = m.numel ();\n  octave_idx_type len = nel*size;\n\n  write_mat5_tag (os, mst, len);\n\n  {\n    switch (st)\n      {\n      case LS_U_CHAR:\n        MAT5_DO_WRITE (uint8_t, data, nel, os);\n        break;\n\n      case LS_U_SHORT:\n        MAT5_DO_WRITE (uint16_t, data, nel, os);\n        break;\n\n      case LS_U_INT:\n        MAT5_DO_WRITE (uint32_t, data, nel, os);\n        break;\n\n      case LS_U_LONG:\n        MAT5_DO_WRITE (uint64_t, data, nel, os);\n        break;\n\n      case LS_CHAR:\n        MAT5_DO_WRITE (int8_t, data, nel, os);\n        break;\n\n      case LS_SHORT:\n        MAT5_DO_WRITE (int16_t, data, nel, os);\n        break;\n\n      case LS_INT:\n        MAT5_DO_WRITE (int32_t, data, nel, os);\n        break;\n\n      case LS_LONG:\n        MAT5_DO_WRITE (int64_t, data, nel, os);\n        break;\n\n      case LS_FLOAT: // No conversion necessary.\n        os.write (reinterpret_cast<const char *> (data), len);\n        break;\n\n      case LS_DOUBLE:\n        MAT5_DO_WRITE (double, data, nel, os);\n        break;\n\n      default:\n        error (\"unrecognized data format requested\");\n        break;\n      }\n  }\n  if (PAD (len) > len)\n    {\n      static char buf[9]=\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\";\n      os.write (buf, PAD (len) - len);\n    }\n}\n\ntemplate <typename T>\nvoid\nwrite_mat5_integer_data (std::ostream& os, const T *m, int size,\n                         octave_idx_type nel)\n{\n  mat5_data_type mst;\n  unsigned len;\n\n  switch (size)\n    {\n    case 1:\n      mst = miUINT8;\n      break;\n    case 2:\n      mst = miUINT16;\n      break;\n    case 4:\n      mst = miUINT32;\n      break;\n    case 8:\n      mst = miUINT64;\n      break;\n    case -1:\n      mst = miINT8;\n      size = - size;\n      break;\n    case -2:\n      mst = miINT16;\n      size = - size;\n      break;\n    case -4:\n      mst = miINT32;\n      size = - size;\n      break;\n    case -8:\n    default:\n      mst = miINT64;\n      size = - size;\n      break;\n    }\n\n  len = nel*size;\n  write_mat5_tag (os, mst, len);\n\n  os.write (reinterpret_cast<const char *> (m), len);\n\n  if (PAD (len) > len)\n    {\n      static char buf[9]=\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\";\n      os.write (buf, PAD (len) - len);\n    }\n}\n\ntemplate void\nwrite_mat5_integer_data (std::ostream& os, const octave_int8 *m,\n                         int size, octave_idx_type nel);\n\ntemplate void\nwrite_mat5_integer_data (std::ostream& os, const octave_int16 *m,\n                         int size, octave_idx_type nel);\n\ntemplate void\nwrite_mat5_integer_data (std::ostream& os, const octave_int32 *m,\n                         int size, octave_idx_type nel);\n\ntemplate void\nwrite_mat5_integer_data (std::ostream& os, const octave_int64 *m,\n                         int size, octave_idx_type nel);\n\ntemplate void\nwrite_mat5_integer_data (std::ostream& os, const octave_uint8 *m,\n                         int size, octave_idx_type nel);\n\ntemplate void\nwrite_mat5_integer_data (std::ostream& os, const octave_uint16 *m,\n                         int size, octave_idx_type nel);\n\ntemplate void\nwrite_mat5_integer_data (std::ostream& os, const octave_uint32 *m,\n                         int size, octave_idx_type nel);\n\ntemplate void\nwrite_mat5_integer_data (std::ostream& os, const octave_uint64 *m,\n                         int size, octave_idx_type nel);\n\ntemplate void\nwrite_mat5_integer_data (std::ostream& os, const int *m,\n                         int size, octave_idx_type nel);\n\n// Write out cell element values in the cell array to OS, preceded by\n// the appropriate tag.\n\nstatic bool\nwrite_mat5_cell_array (std::ostream& os, const Cell& cell,\n                       bool mark_global, bool save_as_floats)\n{\n  octave_idx_type nel = cell.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      octave_value ov = cell(i);\n\n      if (! save_mat5_binary_element (os, ov, \"\", mark_global,\n                                      false, save_as_floats))\n        return false;\n    }\n\n  return true;\n}\n\nint\nsave_mat5_array_length (const double *val, octave_idx_type nel,\n                        bool save_as_floats)\n{\n  if (nel > 0)\n    {\n      int size = 8;\n\n      if (save_as_floats)\n        {\n          bool too_large_for_float = false;\n          for (octave_idx_type i = 0; i < nel; i++)\n            {\n              double tmp = val[i];\n\n              if (octave::math::isfinite (tmp)\n                  && fabs (tmp) > std::numeric_limits<float>::max ())\n                {\n                  too_large_for_float = true;\n                  break;\n                }\n            }\n\n          if (! too_large_for_float)\n            size = 4;\n        }\n\n      // The code below is disabled since get_save_type currently\n      // doesn't deal with integer types.  This will need to be\n      // activated if get_save_type is changed.\n\n      // double max_val = val[0];\n      // double min_val = val[0];\n      // bool all_integers = true;\n      //\n      // for (int i = 0; i < nel; i++)\n      //   {\n      //     double val = val[i];\n      //\n      //     if (val > max_val)\n      //       max_val = val;\n      //\n      //     if (val < min_val)\n      //       min_val = val;\n      //\n      //     if (octave::math::round (val) != val)\n      //       {\n      //         all_integers = false;\n      //         break;\n      //       }\n      //   }\n      //\n      // if (all_integers)\n      //   {\n      //     if (max_val < 256 && min_val > -1)\n      //       size = 1;\n      //     else if (max_val < 65536 && min_val > -1)\n      //       size = 2;\n      //     else if (max_val < 4294967295UL && min_val > -1)\n      //       size = 4;\n      //     else if (max_val < 128 && min_val >= -128)\n      //       size = 1;\n      //     else if (max_val < 32768 && min_val >= -32768)\n      //       size = 2;\n      //     else if (max_val <= 2147483647L && min_val >= -2147483647L)\n      //       size = 4;\n      //   }\n\n      return 8 + nel * size;\n    }\n  else\n    return 8;\n}\n\nint\nsave_mat5_array_length (const float * /* val */, octave_idx_type nel, bool)\n{\n  if (nel > 0)\n    {\n      int size = 4;\n\n      // The code below is disabled since get_save_type currently\n      // doesn't deal with integer types.  This will need to be\n      // activated if get_save_type is changed.\n\n      // float max_val = val[0];\n      // float min_val = val[0];\n      // bool all_integers = true;\n      //\n      // for (int i = 0; i < nel; i++)\n      //   {\n      //     float val = val[i];\n      //\n      //     if (val > max_val)\n      //       max_val = val;\n      //\n      //     if (val < min_val)\n      //       min_val = val;\n      //\n      //     if (octave::math::round (val) != val)\n      //       {\n      //         all_integers = false;\n      //         break;\n      //       }\n      //   }\n      //\n      // if (all_integers)\n      //   {\n      //     if (max_val < 256 && min_val > -1)\n      //       size = 1;\n      //     else if (max_val < 65536 && min_val > -1)\n      //       size = 2;\n      //     else if (max_val < 4294967295UL && min_val > -1)\n      //       size = 4;\n      //     else if (max_val < 128 && min_val >= -128)\n      //       size = 1;\n      //     else if (max_val < 32768 && min_val >= -32768)\n      //       size = 2;\n      //     else if (max_val <= 2147483647L && min_val >= -2147483647L)\n      //       size = 4;\n      //\n\n      // Round nel up to nearest even number of elements.\n      // Take into account short tags for 4 byte elements.\n      return PAD ((nel * size <= 4 ? 4 : 8) + nel * size);\n    }\n  else\n    return 8;\n}\n\nint\nsave_mat5_array_length (const Complex *val, octave_idx_type nel,\n                        bool save_as_floats)\n{\n  int ret;\n\n  OCTAVE_LOCAL_BUFFER (double, tmp, nel);\n\n  for (octave_idx_type i = 1; i < nel; i++)\n    tmp[i] = std::real (val[i]);\n\n  ret = save_mat5_array_length (tmp, nel, save_as_floats);\n\n  for (octave_idx_type i = 1; i < nel; i++)\n    tmp[i] = std::imag (val[i]);\n\n  ret += save_mat5_array_length (tmp, nel, save_as_floats);\n\n  return ret;\n}\n\nint\nsave_mat5_array_length (const FloatComplex *val, octave_idx_type nel,\n                        bool save_as_floats)\n{\n  int ret;\n\n  OCTAVE_LOCAL_BUFFER (float, tmp, nel);\n\n  for (octave_idx_type i = 1; i < nel; i++)\n    tmp[i] = std::real (val[i]);\n\n  ret = save_mat5_array_length (tmp, nel, save_as_floats);\n\n  for (octave_idx_type i = 1; i < nel; i++)\n    tmp[i] = std::imag (val[i]);\n\n  ret += save_mat5_array_length (tmp, nel, save_as_floats);\n\n  return ret;\n}\n\nstatic uint16_t *\nmaybe_convert_to_u16 (const charNDArray& chm, std::size_t& n16_str)\n{\n  uint16_t *u16_str;\n  const dim_vector& dv = chm.dims ();\n\n  if (chm.ndims () == 2 && dv(0) == 1)\n    {\n      const uint8_t *u8_str = reinterpret_cast<const uint8_t *> (chm.data ());\n      u16_str = octave_u8_to_u16_wrapper (u8_str, chm.numel (),\n                                          nullptr, &n16_str);\n    }\n  else\n    u16_str = nullptr;\n\n  return u16_str;\n}\n\nint\nsave_mat5_element_length (const octave_value& tc, const std::string& name,\n                          bool save_as_floats, bool mat7_format)\n{\n  std::size_t max_namelen = 63;\n  std::size_t len = name.length ();\n  std::string cname = tc.class_name ();\n  int ret = 24;\n\n  if (len > 4)\n    ret += PAD (len > max_namelen ? max_namelen : len);\n\n  if (! tc.is_classdef_object ())\n    {\n      // dimensions flag\n      ret += 8;\n      ret += PAD (4 * tc.ndims ());\n    }\n\n  if (tc.is_string ())\n    {\n      charNDArray chm = tc.char_array_value ();\n      // convert to UTF-16\n      std::size_t n16_str;\n      uint16_t *u16_str = maybe_convert_to_u16 (chm, n16_str);\n      ret += 8;\n\n      octave_idx_type str_len;\n      std::size_t sz_of = 1;\n      if (u16_str)\n        {\n          free (u16_str);\n          // Count number of elements in converted string\n          str_len = n16_str;\n          sz_of = 2;\n        }\n      else\n        str_len = chm.numel ();\n\n      if (str_len > 2)\n        ret += PAD (sz_of * str_len);\n    }\n  else if (tc.issparse ())\n    {\n      if (tc.iscomplex ())\n        {\n          const SparseComplexMatrix m = tc.sparse_complex_matrix_value ();\n          octave_idx_type nc = m.cols ();\n          octave_idx_type nnz = m.nnz ();\n\n          ret += 16 + save_mat5_array_length (m.data (), nnz, save_as_floats);\n          if (nnz > 1)\n            ret += PAD (nnz * sizeof (int32_t));\n          if (nc > 0)\n            ret += PAD ((nc + 1) * sizeof (int32_t));\n        }\n      else\n        {\n          const SparseMatrix m = tc.sparse_matrix_value ();\n          octave_idx_type nc = m.cols ();\n          octave_idx_type nnz = m.nnz ();\n\n          ret += 16 + save_mat5_array_length (m.data (), nnz, save_as_floats);\n          if (nnz > 1)\n            ret += PAD (nnz * sizeof (int32_t));\n          if (nc > 0)\n            ret += PAD ((nc + 1) * sizeof (int32_t));\n        }\n    }\n\n#define INT_LEN(nel, size)                      \\\n  {                                             \\\n    ret += 8;                                   \\\n    octave_idx_type sz = nel * size;            \\\n    if (sz > 4)                                 \\\n      ret += PAD (sz);                          \\\n  }\n\n  else if (cname == \"int8\")\n    INT_LEN (tc.int8_array_value ().numel (), 1)\n  else if (cname == \"int16\")\n    INT_LEN (tc.int16_array_value ().numel (), 2)\n  else if (cname == \"int32\")\n    INT_LEN (tc.int32_array_value ().numel (), 4)\n  else if (cname == \"int64\")\n    INT_LEN (tc.int64_array_value ().numel (), 8)\n  else if (cname == \"uint8\")\n    INT_LEN (tc.uint8_array_value ().numel (), 1)\n  else if (cname == \"uint16\")\n    INT_LEN (tc.uint16_array_value ().numel (), 2)\n  else if (cname == \"uint32\")\n    INT_LEN (tc.uint32_array_value ().numel (), 4)\n  else if (cname == \"uint64\")\n    INT_LEN (tc.uint64_array_value ().numel (), 8)\n  else if (tc.islogical ())\n    INT_LEN (tc.bool_array_value ().numel (), 1)\n  else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())\n    {\n      if (tc.is_single_type ())\n        {\n          const FloatNDArray m = tc.float_array_value ();\n          ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats);\n        }\n      else\n        {\n          const NDArray m = tc.array_value ();\n          ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats);\n        }\n    }\n  else if (tc.iscell ())\n    {\n      Cell cell = tc.cell_value ();\n      octave_idx_type nel = cell.numel ();\n\n      for (int i = 0; i < nel; i++)\n        ret += 8 +\n               save_mat5_element_length (cell (i), \"\", save_as_floats, mat7_format);\n    }\n  else if (tc.is_complex_scalar () || tc.is_complex_matrix ())\n    {\n      if (tc.is_single_type ())\n        {\n          const FloatComplexNDArray m = tc.float_complex_array_value ();\n          ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats);\n        }\n      else\n        {\n          const ComplexNDArray m = tc.complex_array_value ();\n          ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats);\n        }\n    }\n  else if (tc.is_classdef_object ())\n    {\n      // assuming MCOS objects only\n      ret +=  8;  // for type system - MCOS uses small element format\n\n      std::size_t classlen = cname.length ();\n      ret += 8;\n      if (classlen > 4)\n        ret += PAD (classlen > max_namelen ? max_namelen : classlen);\n\n      const dim_vector& dv = tc.dims ();\n      int ndims = dv.ndims ();\n      int nobjs = dv.numel ();\n\n      if (cname == \"FileWrapper__\")\n        {\n          octave::load_save_system& lss = octave::__get_load_save_system__ ();\n          const octave_value& fwrap_data\n            = lss.get_subsystem_handler ()->get_serialized_data ();\n          ret += 8 + save_mat5_element_length (fwrap_data, \"\", save_as_floats, false);\n        }\n      else\n        {\n          //! Does not work for enumerations\n          uint32NDArray mcos_metadata_arr (dim_vector (ndims + nobjs + 3, 1));\n          ret += 8 + save_mat5_element_length (mcos_metadata_arr, \"\",\n                                               save_as_floats, mat7_format);\n        }\n    }\n  else if (tc.isstruct () || tc.is_inline_function () || tc.isobject ())\n    {\n      int fieldcnt = 0;\n      const octave_map m = tc.map_value ();\n      octave_idx_type nel = m.numel ();\n\n      if (tc.is_inline_function ())\n        ret += 8 + PAD (6);  // length of \"inline\" is 6\n      else if (tc.isobject ())\n        {\n          std::size_t classlen = tc.class_name ().length ();\n\n          ret += 8 + PAD (classlen > max_namelen ? max_namelen : classlen);\n        }\n\n      for (auto i = m.begin (); i != m.end (); i++)\n        fieldcnt++;\n\n      ret += 16 + fieldcnt * (max_namelen + 1);\n\n      for (octave_idx_type j = 0; j < nel; j++)\n        {\n          for (auto i = m.begin (); i != m.end (); i++)\n            {\n              const Cell elts = m.contents (i);\n\n              ret += 8 + save_mat5_element_length (elts(j), \"\", save_as_floats,\n                                                   mat7_format);\n            }\n        }\n    }\n  else\n    ret = -1;\n\n  return ret;\n}\n\nstatic void\nwrite_mat5_sparse_index_vector (std::ostream& os,\n                                const octave_idx_type *idx,\n                                octave_idx_type nel)\n{\n  int tmp = sizeof (int32_t);\n\n  OCTAVE_LOCAL_BUFFER (int32_t, tmp_idx, nel);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    tmp_idx[i] = idx[i];\n\n  write_mat5_integer_data (os, tmp_idx, -tmp, nel);\n}\n\nstatic void\nwarn_dim_too_large (const std::string& name)\n{\n  warning_with_id (\"Octave:save:dimension-too-large\",\n                   \"save: skipping %s: dimension too large for MAT format\",\n                   name.c_str ());\n}\n\n// save the data from TC along with the corresponding NAME on stream\n// OS in the MatLab version 5 binary format.  Return true on success.\nbool\nsave_mat5_binary_element (std::ostream& os,\n                          const octave_value& tc, const std::string& name,\n                          bool mark_global, bool mat7_format,\n                          bool save_as_floats, bool compressing)\n{\n  int32_t flags = 0;\n  int32_t nnz_32 = 0;\n  std::string cname = tc.class_name ();\n  std::size_t max_namelen = 63;\n\n  const dim_vector& dv = tc.dims ();\n  int nd = tc.ndims ();\n  int dim_len = 4*nd;\n\n  static octave_idx_type max_dim_val = std::numeric_limits<int32_t>::max ();\n\n  // Strings need to be converted here (or dim-vector will be off).\n  charNDArray chm;\n  uint16_t *u16_str = nullptr;\n  std::size_t n16_str;\n  bool conv_u16 = false;\n  if (tc.is_string ())\n    {\n      chm = tc.char_array_value ();\n      u16_str = maybe_convert_to_u16 (chm, n16_str);\n\n      if (u16_str)\n        conv_u16 = true;\n    }\n  // Guarantee that memory is freed regardless of path through code.\n  octave::unwind_action free_memory ([u16_str] ()\n                                     { if (u16_str != nullptr) free (u16_str); }); \n\n  if (conv_u16)\n    {\n      if (n16_str > static_cast<std::size_t> (max_dim_val))\n        {\n          warn_dim_too_large (name);\n          return true;  // skip to next\n        }\n    }\n  else\n    {\n      for (int i = 0; i < nd; i++)\n        {\n          if (dv(i) > max_dim_val)\n            {\n              warn_dim_too_large (name);\n              return true;  // skip to next\n            }\n        }\n    }\n\n  if (tc.issparse ())\n    {\n      octave_idx_type nnz;\n      octave_idx_type nc;\n\n      if (tc.iscomplex ())\n        {\n          SparseComplexMatrix scm = tc.sparse_complex_matrix_value ();\n          nnz = scm.nzmax ();\n          nc = scm.cols ();\n        }\n      else\n        {\n          SparseMatrix sm = tc.sparse_matrix_value ();\n          nnz = sm.nzmax ();\n          nc = sm.cols ();\n        }\n\n      if (nnz > max_dim_val || nc + 1 > max_dim_val)\n        {\n          warn_dim_too_large (name);\n          return true;  // skip to next\n        }\n\n      nnz_32 = nnz;\n    }\n  else if (dv.numel () > max_dim_val)\n    {\n      warn_dim_too_large (name);\n      return true;  // skip to next\n    }\n\n#if defined (HAVE_ZLIB)\n\n  if (mat7_format && ! compressing)\n    {\n      bool ret = false;\n\n      std::ostringstream buf;\n\n      // The code seeks backwards in the stream to fix the header.\n      // Can't do this with zlib, so use a stringstream.\n      ret = save_mat5_binary_element (buf, tc, name, mark_global, true,\n                                      save_as_floats, true);\n\n      if (ret)\n        {\n          // destLen must be at least 0.1% larger than source buffer\n          // + 12 bytes.  Reality is it must be larger again than that.\n          std::string buf_str = buf.str ();\n          uLongf srcLen = buf_str.length ();\n          uLongf destLen = compressBound (srcLen);\n          OCTAVE_LOCAL_BUFFER (char, out_buf, destLen);\n\n          if (compress (reinterpret_cast<Bytef *> (out_buf), &destLen,\n                        reinterpret_cast<const Bytef *> (buf_str.c_str ()),\n                        srcLen)\n              != Z_OK)\n            error (\"save: error compressing data element\");\n\n          write_mat5_tag (os, miCOMPRESSED,\n                          static_cast<octave_idx_type> (destLen));\n\n          os.write (out_buf, destLen);\n        }\n\n      return ret;\n    }\n\n#else\n\n  octave_unused_parameter (compressing);\n\n#endif\n\n  write_mat5_tag (os, miMATRIX, save_mat5_element_length\n                  (tc, name, save_as_floats, mat7_format));\n\n  // array flags subelement\n  write_mat5_tag (os, miUINT32, 8);\n\n  if (tc.islogical ())\n    flags |= 0x0200;\n\n  if (mark_global)\n    flags |= 0x0400;\n\n  if (tc.is_complex_scalar () || tc.is_complex_matrix ())\n    flags |= 0x0800;\n\n  if (tc.is_string ())\n    flags |= MAT_FILE_CHAR_CLASS;\n  else if (cname == \"int8\")\n    flags |= MAT_FILE_INT8_CLASS;\n  else if (cname == \"int16\")\n    flags |= MAT_FILE_INT16_CLASS;\n  else if (cname == \"int32\")\n    flags |= MAT_FILE_INT32_CLASS;\n  else if (cname == \"int64\")\n    flags |= MAT_FILE_INT64_CLASS;\n  else if (cname == \"uint8\" || tc.islogical ())\n    flags |= MAT_FILE_UINT8_CLASS;\n  else if (cname == \"uint16\")\n    flags |= MAT_FILE_UINT16_CLASS;\n  else if (cname == \"uint32\")\n    flags |= MAT_FILE_UINT32_CLASS;\n  else if (cname == \"uint64\")\n    flags |= MAT_FILE_UINT64_CLASS;\n  else if (tc.issparse ())\n    flags |= MAT_FILE_SPARSE_CLASS;\n  else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ()\n           || tc.is_complex_scalar () || tc.is_complex_matrix ())\n    {\n      if (tc.is_single_type ())\n        flags |= MAT_FILE_SINGLE_CLASS;\n      else\n        flags |= MAT_FILE_DOUBLE_CLASS;\n    }\n  else if (tc.isstruct ())\n    flags |= MAT_FILE_STRUCT_CLASS;\n  else if (tc.iscell ())\n    flags |= MAT_FILE_CELL_CLASS;\n  else if (tc.is_classdef_object ())\n    flags |= MAT_FILE_WORKSPACE_CLASS;\n  else if (tc.is_inline_function () || tc.isobject ())\n    flags |= MAT_FILE_OBJECT_CLASS;\n  else\n    {\n      // FIXME: Should this just error out rather than warn?\n      warn_wrong_type_arg (\"save\", tc);\n      error (\"save: error while writing '%s' to MAT file\", name.c_str ());\n    }\n\n  os.write (reinterpret_cast<char *> (&flags), 4);\n  // Matlab seems to have trouble reading files that have nzmax == 0 at\n  // this point in the file.\n  if (nnz_32 == 0)\n    nnz_32 = 1;\n  os.write (reinterpret_cast<char *> (&nnz_32), 4);\n\n  if (! tc.is_classdef_object ())\n    {\n      // classdef objects don't have dims subelement\n      write_mat5_tag (os, miINT32, dim_len);\n\n      if (conv_u16)\n        {\n          int32_t n[2] = {1, static_cast<int32_t> (n16_str)};\n          os.write (reinterpret_cast<char *> (&n), 8);\n        }\n      else\n        for (int i = 0; i < nd; i++)\n          {\n            int32_t n = dv(i);\n            os.write (reinterpret_cast<char *> (&n), 4);\n          }\n\n      if (PAD (dim_len) > dim_len)\n        {\n          static char buf[9] = \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\";\n          os.write (buf, PAD (dim_len) - dim_len);\n        }\n    }\n\n  // array name subelement\n  {\n    std::size_t namelen = name.length ();\n\n    if (namelen > max_namelen)\n      namelen = max_namelen;  // Truncate names if necessary\n\n    int paddedlength = PAD (namelen);\n\n    write_mat5_tag (os, miINT8, namelen);\n    OCTAVE_LOCAL_BUFFER (char, paddedname, paddedlength);\n    memset (paddedname, 0, paddedlength);\n    strncpy (paddedname, name.c_str (), namelen);\n    os.write (paddedname, paddedlength);\n  }\n\n  if (tc.is_classdef_object ())\n    {\n      // type system\n      std::string type_system;\n      if (tc.type_name () == \"object\")\n        type_system = \"MCOS\";\n      std::size_t type_sys_len = type_system.length ();\n      int paddedlength = PAD (type_sys_len);\n      write_mat5_tag (os, miINT8, type_sys_len);\n      OCTAVE_LOCAL_BUFFER (char, paddedtype, paddedlength);\n      memset (paddedtype, 0, paddedlength);\n      strncpy (paddedtype, type_system.c_str (), type_sys_len);\n      os.write (paddedtype, paddedlength);\n\n      // class name\n      std::size_t class_name_len = cname.length ();\n      paddedlength = PAD (class_name_len);\n      write_mat5_tag (os, miINT8, class_name_len);\n      OCTAVE_LOCAL_BUFFER (char, paddedclass, paddedlength);\n      memset (paddedclass, 0, paddedlength);\n      strncpy (paddedclass, cname.c_str (), class_name_len);\n      os.write (paddedclass, paddedlength);\n    }\n\n  // data element\n  if (tc.is_string ())\n    {\n      octave_idx_type len;\n      octave_idx_type paddedlength;\n\n      if (conv_u16)\n        {\n          // converted UTF-16\n          len = n16_str*2;\n          paddedlength = PAD (len);\n\n          write_mat5_tag (os, miUTF16, len);\n\n          os.write (reinterpret_cast<char *> (u16_str), len);\n        }\n      else\n        {\n          // write as UTF-8\n          len = chm.numel ();\n          paddedlength = PAD (len);\n\n          write_mat5_tag (os, miUTF8, len);\n\n          os.write (chm.data (), len);\n        }\n\n      if (paddedlength > len)\n        {\n          static char padbuf[9] = \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\";\n          os.write (padbuf, paddedlength - len);\n        }\n    }\n  else if (tc.issparse ())\n    {\n      if (tc.iscomplex ())\n        {\n          const SparseComplexMatrix m = tc.sparse_complex_matrix_value ();\n          octave_idx_type nnz = m.nnz ();\n          octave_idx_type nc = m.cols ();\n\n          write_mat5_sparse_index_vector (os, m.ridx (), nnz);\n          write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);\n\n          NDArray buf (dim_vector (nnz, 1));\n\n          for (octave_idx_type i = 0; i < nnz; i++)\n            buf (i) = std::real (m.data (i));\n\n          write_mat5_array (os, buf, save_as_floats);\n\n          for (octave_idx_type i = 0; i < nnz; i++)\n            buf (i) = std::imag (m.data (i));\n\n          write_mat5_array (os, buf, save_as_floats);\n        }\n      else\n        {\n          const SparseMatrix m = tc.sparse_matrix_value ();\n          octave_idx_type nnz = m.nnz ();\n          octave_idx_type nc = m.cols ();\n\n          write_mat5_sparse_index_vector (os, m.ridx (), nnz);\n          write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);\n\n          // FIXME\n          // Is there a way to easily do without this buffer\n          NDArray buf (dim_vector (nnz, 1));\n\n          for (int i = 0; i < nnz; i++)\n            buf (i) = m.data (i);\n\n          write_mat5_array (os, buf, save_as_floats);\n        }\n    }\n  else if (cname == \"int8\")\n    {\n      int8NDArray m = tc.int8_array_value ();\n\n      write_mat5_integer_data (os, m.data (), -1, m.numel ());\n    }\n  else if (cname == \"int16\")\n    {\n      int16NDArray m = tc.int16_array_value ();\n\n      write_mat5_integer_data (os, m.data (), -2, m.numel ());\n    }\n  else if (cname == \"int32\")\n    {\n      int32NDArray m = tc.int32_array_value ();\n\n      write_mat5_integer_data (os, m.data (), -4, m.numel ());\n    }\n  else if (cname == \"int64\")\n    {\n      int64NDArray m = tc.int64_array_value ();\n\n      write_mat5_integer_data (os, m.data (), -8, m.numel ());\n    }\n  else if (cname == \"uint8\")\n    {\n      uint8NDArray m = tc.uint8_array_value ();\n\n      write_mat5_integer_data (os, m.data (), 1, m.numel ());\n    }\n  else if (cname == \"uint16\")\n    {\n      uint16NDArray m = tc.uint16_array_value ();\n\n      write_mat5_integer_data (os, m.data (), 2, m.numel ());\n    }\n  else if (cname == \"uint32\")\n    {\n      uint32NDArray m = tc.uint32_array_value ();\n\n      write_mat5_integer_data (os, m.data (), 4, m.numel ());\n    }\n  else if (cname == \"uint64\")\n    {\n      uint64NDArray m = tc.uint64_array_value ();\n\n      write_mat5_integer_data (os, m.data (), 8, m.numel ());\n    }\n  else if (tc.islogical ())\n    {\n      uint8NDArray m (tc.bool_array_value ());\n\n      write_mat5_integer_data (os, m.data (), 1, m.numel ());\n    }\n  else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())\n    {\n      if (tc.is_single_type ())\n        {\n          FloatNDArray m = tc.float_array_value ();\n\n          write_mat5_array (os, m, save_as_floats);\n        }\n      else\n        {\n          NDArray m = tc.array_value ();\n\n          write_mat5_array (os, m, save_as_floats);\n        }\n    }\n  else if (tc.iscell ())\n    {\n      Cell cell = tc.cell_value ();\n\n      if (! write_mat5_cell_array (os, cell, mark_global, save_as_floats))\n        error (\"save: error while writing '%s' to MAT file\", name.c_str ());\n    }\n  else if (tc.is_complex_scalar () || tc.is_complex_matrix ())\n    {\n      if (tc.is_single_type ())\n        {\n          FloatComplexNDArray m_cmplx = tc.float_complex_array_value ();\n\n          write_mat5_array (os, ::real (m_cmplx), save_as_floats);\n          write_mat5_array (os, ::imag (m_cmplx), save_as_floats);\n        }\n      else\n        {\n          ComplexNDArray m_cmplx = tc.complex_array_value ();\n\n          write_mat5_array (os, ::real (m_cmplx), save_as_floats);\n          write_mat5_array (os, ::imag (m_cmplx), save_as_floats);\n        }\n    }\n  else if (tc.is_classdef_object ())\n    {\n      octave::subsystem_handler *sh\n        = octave::__get_load_save_system__ ().get_subsystem_handler ();\n      octave_value objmetadata;\n\n      if (cname == \"FileWrapper__\")\n        objmetadata = sh->get_serialized_data ();\n      else if (sh->has_serialized_data ())\n        {\n          // MAT-files write metadata without MAT_FILE_WORKSPACE_CLASS header\n          // in subsystem.\n          // Current version writes header for these objects, which involves\n          // modifying subsystem.\n          // Workaround to prevent invalid memory access\n          warning_with_id (\"MATLAB:save:\",\n                           \"Object of class %s cannot be loaded in Octave due \"\n                           \"to issues with MAT-compatibility and is returned \"\n                           \"as a Cell\",\n                           cname.c_str ());\n          objmetadata = Cell (dim_vector (0, 0));\n        }\n      else\n        objmetadata = sh->set_mcos_object_metadata (tc);\n\n      bool retval2 = save_mat5_binary_element (os, objmetadata, \"\", false,\n                                               false, save_as_floats);\n      if (! retval2)\n        error (\"save: error while writing '%s' to MAT file\",\n               name.c_str ());\n    }\n  else if (tc.isstruct () || tc.is_inline_function () || tc.isobject ())\n    {\n      if (tc.is_inline_function () || tc.isobject ())\n        {\n          std::string classname = (tc.isobject () ? tc.class_name ()\n                                   : \"inline\");\n          std::size_t namelen = classname.length ();\n\n          if (namelen > max_namelen)\n            namelen = max_namelen; // Truncate names if necessary\n\n          int paddedlength = PAD (namelen);\n\n          write_mat5_tag (os, miINT8, namelen);\n          OCTAVE_LOCAL_BUFFER (char, paddedname, paddedlength);\n          memset (paddedname, 0, paddedlength);\n          strncpy (paddedname, classname.c_str (), namelen);\n          os.write (paddedname, paddedlength);\n        }\n\n      octave_map m;\n\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      octave::load_path& lp = interp.get_load_path ();\n\n      if (tc.isobject ()\n          && lp.find_method (tc.class_name (), \"saveobj\") != \"\")\n        {\n          try\n            {\n              octave_value_list tmp = interp.feval (\"saveobj\", tc, 1);\n\n              m = tmp(0).map_value ();\n            }\n          catch (const octave::execution_exception&)\n            {\n              error (\"save: error while writing '%s' to MAT file\",\n                     name.c_str ());\n            }\n        }\n      else\n        m = tc.map_value ();\n\n      // an Octave structure */\n      // recursively write each element of the structure\n      {\n        char buf[64];\n        int32_t maxfieldnamelength = max_namelen + 1;\n\n        octave_idx_type nf = m.nfields ();\n\n        write_mat5_tag (os, miINT32, 4);\n        os.write (reinterpret_cast<char *> (&maxfieldnamelength), 4);\n        write_mat5_tag (os, miINT8, nf*maxfieldnamelength);\n\n        // Iterating over the list of keys will preserve the order of\n        // the fields.\n        string_vector keys = m.keys ();\n\n        for (octave_idx_type i = 0; i < nf; i++)\n          {\n            std::string key = keys(i);\n\n            // write the name of each element\n            memset (buf, 0, max_namelen + 1);\n            // only 31 or 63 char names permitted\n            strncpy (buf, key.c_str (), max_namelen);\n            os.write (buf, max_namelen + 1);\n          }\n\n        octave_idx_type len = m.numel ();\n\n        // Create temporary copy of structure contents to avoid\n        // multiple calls of the contents method.\n        std::vector<const octave_value *> elts (nf);\n        for (octave_idx_type i = 0; i < nf; i++)\n          elts[i] = m.contents (keys(i)).data ();\n\n        for (octave_idx_type j = 0; j < len; j++)\n          {\n            // write the data of each element\n\n            // Iterating over the list of keys will preserve the order\n            // of the fields.\n            for (octave_idx_type i = 0; i < nf; i++)\n              {\n                bool retval2 = save_mat5_binary_element (os, elts[i][j], \"\",\n                                                         mark_global, false,\n                                                         save_as_floats);\n                if (! retval2)\n                  error (\"save: error while writing '%s' to MAT file\",\n                         name.c_str ());\n              }\n          }\n      }\n    }\n  else\n    // FIXME: Should this just error out rather than warn?\n    warn_wrong_type_arg (\"save\", tc);\n\n  return true;\n}\n"
  },
  {
    "path": "libinterp/corefcn/ls-mat5.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ls_mat5_h)\n#define octave_ls_mat5_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\nclass octave_value;\n\nenum mat5_data_type\n{\n  miINT8 = 1,                 // 8 bit signed\n  miUINT8,                    // 8 bit unsigned\n  miINT16,                    // 16 bit signed\n  miUINT16,                   // 16 bit unsigned\n  miINT32,                    // 32 bit signed\n  miUINT32,                   // 32 bit unsigned\n  miSINGLE,                   // IEEE 754 single precision float\n  miRESERVE1,\n  miDOUBLE,                   // IEEE 754 double precision float\n  miRESERVE2,\n  miRESERVE3,\n  miINT64,                    // 64 bit signed\n  miUINT64,                   // 64 bit unsigned\n  miMATRIX,                   // MATLAB array\n  miCOMPRESSED,               // Compressed data\n  miUTF8,                     // Unicode UTF-8 Encoded Character Data\n  miUTF16,                    // Unicode UTF-16 Encoded Character Data\n  miUTF32                     // Unicode UTF-32 Encoded Character Data\n};\n\nextern OCTINTERP_API int\nread_mat5_binary_file_header (std::istream& is, bool& swap,\n                              bool quiet = false,\n                              const std::string& filename = \"\");\nextern OCTINTERP_API std::string\nread_mat5_binary_element (std::istream& is, const std::string& filename,\n                          bool swap, bool& global, octave_value& tc);\nextern OCTINTERP_API bool\nsave_mat5_binary_element (std::ostream& os,\n                          const octave_value& tc, const std::string& name,\n                          bool mark_global, bool mat7_format,\n                          bool save_as_floats, bool compressing = false);\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-oct-binary.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n#include <string>\n\n#include \"byte-swap.h\"\n#include \"data-conv.h\"\n#include \"file-ops.h\"\n#include \"glob-match.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-time.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"load-save.h\"\n#include \"ls-oct-binary.h\"\n#include \"ls-utils.h\"\n#include \"ov-cell.h\"\n#include \"ov-classdef.h\"\n#include \"ov.h\"\n#include \"pager.h\"\n#include \"sysdep.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"version.h\"\n\nstatic bool\nload_inline_fcn (std::istream& is, bool swap, octave::mach_info::float_format,\n                 octave_value& retval)\n{\n  int32_t nargs;\n  if (! is.read (reinterpret_cast<char *> (&nargs), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&nargs);\n\n  if (nargs < 1)\n    return false;\n  else\n    {\n      int32_t tmp;\n      octave_value_list args (nargs+1);\n      for (int i = 0; i < nargs; i++)\n        {\n          if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n            return false;\n          if (swap)\n            swap_bytes<4> (&tmp);\n\n          OCTAVE_LOCAL_BUFFER (char, ctmp, tmp+1);\n          is.read (ctmp, tmp);\n          args(i+1) = std::string (ctmp);\n\n          if (! is)\n            return false;\n        }\n\n      if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&tmp);\n\n      OCTAVE_LOCAL_BUFFER (char, ctmp1, tmp+1);\n      is.read (ctmp1, tmp);\n      // NAME is obsolete and unused.\n      // std::string name (ctmp1);\n\n      if (! is)\n        return false;\n\n      if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&tmp);\n\n      OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);\n      is.read (ctmp2, tmp);\n\n      if (is)\n        {\n          args(0) = std::string (ctmp2);\n\n          octave::interpreter& interp = octave::__get_interpreter__ ();\n\n          octave_value_list tmp_inl = interp.feval (\"inline\", args, 1);\n\n          if (tmp_inl.length () > 0)\n            {\n              retval = tmp_inl(0);\n              return true;\n            }\n        }\n    }\n\n  return false;\n}\n\n// Extract one value (scalar, matrix, string, etc.) from stream IS and\n// place it in TC, returning the name of the variable.  If the value\n// is tagged as global in the file, return TRUE in GLOBAL.  If SWAP\n// is TRUE, swap bytes after reading.\n//\n// The data is expected to be in the following format:\n//\n// Header (one per file):\n// =====================\n//\n//   object               type            bytes\n//   ------               ----            -----\n//   magic number         string             10\n//\n//   float format         integer             1\n//\n//\n// Data (one set for each item):\n// ============================\n//\n//   object               type            bytes\n//   ------               ----            -----\n//   name_length          integer             4\n//\n//   name                 string    name_length\n//\n//   doc_length           integer             4\n//\n//   doc                  string     doc_length\n//\n//   global flag          integer             1\n//\n//   data type            char                1\n//\n// In general \"data type\" is 255, and in that case the next arguments\n// in the data set are\n//\n//   object               type            bytes\n//   ------               ----            -----\n//   type_length          integer             4\n//\n//   type                 string    type_length\n//\n// The string \"type\" is then used with octave::type_info::lookup_type\n// to create an octave_value of the correct type.  The specific load/save\n// function is then called.\n//\n// For backward compatibility \"data type\" can also be a value between 1\n// and 7, where this defines a hardcoded octave_value of the type\n//\n//   data type                  octave_value\n//   ---------                  ------------\n//   1                          scalar\n//   2                          matrix\n//   3                          complex scalar\n//   4                          complex matrix\n//   5                          string   (old style storage)\n//   6                          range\n//   7                          string\n//\n// Except for \"data type\" equal 5 that requires special treatment, these\n// old style \"data type\" value also cause the specific load/save functions\n// to be called.  FILENAME is used for error messages.\n\nstd::string\nread_binary_data (std::istream& is, bool swap,\n                  octave::mach_info::float_format fmt,\n                  const std::string& filename, bool& global,\n                  octave_value& tc, std::string& doc)\n{\n  std::string retval;\n\n  unsigned char tmp = 0;\n\n  int32_t name_len = 0;\n  int32_t doc_len = 0;\n\n  doc.clear ();\n\n  // We expect to fail here, at the beginning of a record, so not\n  // being able to read another name should not result in an error.\n\n  is.read (reinterpret_cast<char *> (&name_len), 4);\n  if (! is)\n    return retval;\n  if (swap)\n    swap_bytes<4> (&name_len);\n\n  {\n    OCTAVE_LOCAL_BUFFER (char, name, name_len+1);\n    name[name_len] = '\\0';\n    if (! is.read (reinterpret_cast<char *> (name), name_len))\n      error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n    retval = name;\n  }\n\n  is.read (reinterpret_cast<char *> (&doc_len), 4);\n  if (! is)\n    error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n  if (swap)\n    swap_bytes<4> (&doc_len);\n\n  {\n    OCTAVE_LOCAL_BUFFER (char, tdoc, doc_len+1);\n    tdoc[doc_len] = '\\0';\n    if (! is.read (reinterpret_cast<char *> (tdoc), doc_len))\n      error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n    doc = tdoc;\n  }\n\n  if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n    error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n  global = (tmp ? 1 : 0);\n\n  tmp = 0;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n    error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  // All cases except 255 kept for backwards compatibility\n  switch (tmp)\n    {\n    case 1:\n      tc = type_info.lookup_type (\"scalar\");\n      break;\n\n    case 2:\n      tc = type_info.lookup_type (\"matrix\");\n      break;\n\n    case 3:\n      tc = type_info.lookup_type (\"complex scalar\");\n      break;\n\n    case 4:\n      tc = type_info.lookup_type (\"complex matrix\");\n      break;\n\n    case 5:\n      {\n        // FIXME:\n        // This is cruft, since its for a save type that is old.\n        // Maybe this is taking backward compatibility too far!\n        int32_t len;\n        if (! is.read (reinterpret_cast<char *> (&len), 4))\n          error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n        if (swap)\n          swap_bytes<4> (&len);\n        OCTAVE_LOCAL_BUFFER (char, s, len+1);\n        if (! is.read (reinterpret_cast<char *> (s), len))\n          error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n        s[len] = '\\0';\n        tc = s;\n\n        // Early return, since don't want rest of this function\n        return retval;\n      }\n      break;\n\n    case 6:\n      tc = type_info.lookup_type (\"range\");\n      break;\n\n    case 7:\n      tc = type_info.lookup_type (\"string\");\n      break;\n\n    case 255:\n      {\n        // Read the saved variable type\n        int32_t len;\n        if (! is.read (reinterpret_cast<char *> (&len), 4))\n          error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n        if (swap)\n          swap_bytes<4> (&len);\n        OCTAVE_LOCAL_BUFFER (char, s, len+1);\n        if (! is.read (s, len))\n          error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n        s[len] = '\\0';\n        std::string typ = s;\n\n        if (typ == \"inline function\")\n          {\n            // Special case for loading old octave_inline_fcn objects.\n            if (! load_inline_fcn (is, swap, fmt, tc))\n              error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n            return retval;\n          }\n\n        tc = type_info.lookup_type (typ);\n      }\n      break;\n    default:\n      error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n      break;\n    }\n\n  if (! tc.load_binary (is, swap, fmt))\n    error (\"load: trouble reading binary file '%s'\", filename.c_str ());\n\n  return retval;\n}\n\n// Save the data from TC along with the corresponding NAME, help\n// string DOC, and global flag MARK_AS_GLOBAL on stream OS in the\n// binary format described above for read_binary_data.\n\nbool\nsave_binary_data (std::ostream& os, const octave_value& tc_in,\n                  const std::string& name, const std::string& doc,\n                  bool mark_global, bool save_as_floats)\n{\n  octave_value tc;\n  if (tc_in.is_classdef_object ())\n    {\n      warning_with_id (\"Octave:save:classdef:unsupported\",\n                       \"Saving classdef objects is not supported.  \"\n                       \"Attempting to save '%s' as struct.\",\n                       name.c_str ());\n      tc = tc_in.classdef_object_value ()->map_value (false, false);\n    }\n  else\n    tc = tc_in;\n\n  constexpr octave_idx_type max_dim_val = std::numeric_limits<int32_t>::max () - 1;\n\n  dim_vector dv = tc.dims ();\n  if (dv.ndims () > max_dim_val)\n    {\n      warning_with_id (\"Octave:save:dimension-too-large\",\n                       \"save: skipping %s: number of dimensions too large for binary format\",\n                       name.c_str ());\n      return true;\n    }\n\n  for (octave_idx_type i_dim = 0; i_dim < dv.ndims (); i_dim++)\n    {\n      if (dv(i_dim) > max_dim_val)\n        {\n          warning_with_id (\"Octave:save:dimension-too-large\",\n                           \"save: skipping %s: dimensions too large for binary format\",\n                           name.c_str ());\n          return true;\n        }\n    }\n\n  int32_t name_len = name.length ();\n\n  os.write (reinterpret_cast<char *> (&name_len), 4);\n  os << name;\n\n  int32_t doc_len = doc.length ();\n\n  os.write (reinterpret_cast<char *> (&doc_len), 4);\n  os << doc;\n\n  unsigned char tmp;\n\n  tmp = mark_global;\n  os.write (reinterpret_cast<char *> (&tmp), 1);\n\n  // 255 flags the new binary format\n  tmp = 255;\n  os.write (reinterpret_cast<char *> (&tmp), 1);\n\n  // Write the string corresponding to the octave_value type\n  std::string typ = tc.type_name ();\n  int32_t len = typ.length ();\n  os.write (reinterpret_cast<char *> (&len), 4);\n  const char *btmp = typ.data ();\n  os.write (btmp, len);\n\n  // The octave_value of tc is const.  Make a copy...\n  octave_value val = tc;\n\n  // Call specific save function\n  bool success = val.save_binary (os, save_as_floats);\n\n  return (os && success);\n}\n"
  },
  {
    "path": "libinterp/corefcn/ls-oct-binary.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ls_oct_binary_h)\n#define octave_ls_oct_binary_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n#include \"mach-info.h\"\n\nclass octave_value;\n\nextern OCTINTERP_API bool\nsave_binary_data (std::ostream& os, const octave_value& tc,\n                  const std::string& name, const std::string& doc,\n                  bool mark_global, bool save_as_floats);\n\nextern OCTINTERP_API std::string\nread_binary_data (std::istream& is, bool swap,\n                  octave::mach_info::float_format fmt,\n                  const std::string& filename, bool& global,\n                  octave_value& tc, std::string& doc);\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-oct-text.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstring>\n#include <cctype>\n\n#include <istream>\n#include <ostream>\n#include <sstream>\n#include <string>\n\n#include \"byte-swap.h\"\n#include \"data-conv.h\"\n#include \"file-ops.h\"\n#include \"glob-match.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-time.h\"\n#include \"str-vec.h\"\n\n#include \"cdef-utils.h\"\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"load-save.h\"\n#include \"ls-ascii-helper.h\"\n#include \"ls-oct-text.h\"\n#include \"ovl.h\"\n#include \"oct-map.h\"\n#include \"ov-cell.h\"\n#include \"pager.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"version.h\"\n#include \"dMatrix.h\"\n\n// The number of decimal digits to use when writing ASCII data.\n// 17 is the minimum necessary for lossless save/restore of IEEE-754 doubles.\nstatic int Vsave_precision = 17;\n\n// Functions for reading octave format text data.\n\n// Extract a KEYWORD and its value from stream IS, returning the\n// associated value in a new string.\n//\n// Input should look something like:\n//\n//  [%#][ \\t]*keyword[ \\t]*:[ \\t]*string-value[ \\t]*\\n\n\nstd::string\nextract_keyword (std::istream& is, const char *keyword, const bool next_only)\n{\n  std::string retval;\n\n  int ch = is.peek ();\n  if (next_only && ch != '%' && ch != '#')\n    return retval;\n\n  char c;\n  while (is.get (c))\n    {\n      if (c == '%' || c == '#')\n        {\n          std::ostringstream buf;\n\n          while (is.get (c) && (c == ' ' || c == '\\t' || c == '%' || c == '#'))\n            ; // Skip whitespace and comment characters.\n\n          if (isalpha (c))\n            buf << c;\n\n          while (is.get (c) && isalpha (c))\n            buf << c;\n\n          std::string tmp = buf.str ();\n          bool match = (tmp.substr (0, strlen (keyword)) == keyword);\n\n          if (match)\n            {\n              std::ostringstream value;\n              while (is.get (c) && (c == ' ' || c == '\\t' || c == ':'))\n                ; // Skip whitespace and the colon.\n\n              is.putback (c);\n              retval = octave::read_until_newline (is, false);\n              break;\n            }\n          else if (next_only)\n            break;\n          else\n            octave::skip_until_newline (is, false);\n        }\n    }\n\n  int len = retval.length ();\n\n  if (len > 0)\n    {\n      while (len)\n        {\n          c = retval[len-1];\n\n          if (c == ' ' || c == '\\t')\n            len--;\n          else\n            {\n              retval.resize (len);\n              break;\n            }\n        }\n    }\n\n  return retval;\n}\n\n// Extract one value (scalar, matrix, string, etc.) from stream IS and\n// place it in TC, returning the name of the variable.  If the value\n// is tagged as global in the file, return TRUE in GLOBAL.\n//\n// Each type supplies its own function to load the data, and so this\n// function is extensible.\n//\n// FILENAME is used for error messages.\n//\n// The data is expected to be in the following format:\n//\n// The input file must have a header followed by some data.\n//\n// All lines in the header must begin with a '#' character.\n//\n// The header must contain a list of keyword and value pairs with the\n// keyword and value separated by a colon.\n//\n// Keywords must appear in the following order:\n//\n// # name: <name>\n// # type: <type>\n// # <info>\n//\n// Where, for the built in types are:\n//\n//  <name> : a valid identifier\n//\n//  <type> : <typename>\n//         | global <typename>\n//\n//  <typename> : scalar\n//             | complex scalar\n//             | matrix\n//             | complex matrix\n//             | bool\n//             | bool matrix\n//             | string\n//             | range\n//\n//  <info> : <matrix info>\n//         | <string info>\n//\n//  <matrix info> : # rows: <integer>\n//                : # columns: <integer>\n//\n//  <string info> : # elements: <integer>\n//                : # length: <integer> (once before each string)\n//\n// For backward compatibility the type \"string array\" is treated as a\n// \"string\" type.  Also \"string\" can have a single element with no elements\n// line such that\n//\n//  <string info> : # length: <integer>\n//\n// Formatted ASCII data follows the header.\n//\n// Example:\n//\n//  # name: foo\n//  # type: matrix\n//  # rows: 2\n//  # columns: 2\n//    2  4\n//    1  3\n//\n// Example:\n//\n//  # name: foo\n//  # type: string\n//  # elements: 5\n//  # length: 4\n//  this\n//  # length: 2\n//  is\n//  # length: 1\n//  a\n//  # length: 6\n//  string\n//  # length: 5\n//  array\n//\n// FIXME: This format is fairly rigid, and doesn't allow for arbitrary comments.\n// Someone should fix that.  It does allow arbitrary types however.\n\n// Ugh.  The signature of the compare method is not standard in older\n// versions of the GNU libstdc++.  Do this instead:\n\n#define SUBSTRING_COMPARE_EQ(s, pos, n, t) (s.substr (pos, n) == (t))\n\nstatic octave_value\nload_inline_fcn (std::istream& is, const std::string& filename)\n{\n  int nargs;\n  if (extract_keyword (is, \"nargs\", nargs, true))\n    {\n      std::string name;\n      octave_value_list args (nargs+1);\n      for (int i = 0; i < nargs; i++)\n        {\n          std::string tmp;\n          is >> tmp;\n          args(i+1) = tmp;\n        }\n      is >> name;\n      if (name == \"0\")\n        name = \"\";\n\n      octave::skip_preceeding_newline (is);\n\n      std::string buf;\n\n      if (is)\n        {\n\n          // Get a line of text whitespace characters included,\n          // leaving newline in the stream.\n          buf = octave::read_until_newline (is, true);\n        }\n\n      if (is)\n        {\n          args(0) = std::string (buf);\n\n          octave::interpreter& interp = octave::__get_interpreter__ ();\n\n          octave_value_list tmp = interp.feval (\"inline\", args, 1);\n\n          if (tmp.length () > 0)\n            return tmp(0);\n        }\n    }\n\n  error (\"load: trouble reading ascii file '%s'\", filename.c_str ());\n}\n\nstd::string\nread_text_data (std::istream& is, const std::string& filename, bool& global,\n                octave_value& tc, octave_idx_type count,\n                const bool do_name_validation)\n{\n  // Read name for this entry or break on EOF.\n  std::string name = extract_keyword (is, \"name\");\n\n  if (name.empty ())\n    {\n      if (count == 0)\n        error (\"load: empty name keyword or no data found in file '%s'\",\n               filename.c_str ());\n\n      return \"\";\n    }\n\n  if (name != CELL_ELT_TAG\n      && do_name_validation && ! octave::valid_identifier (name))\n    error (\"load: invalid identifier '%s' found in file '%s'\",\n           name.c_str (), filename.c_str ());\n\n  // Look for type keyword.\n\n  std::string tag = extract_keyword (is, \"type\");\n\n  if (tag.empty ())\n    error (\"load: failed to extract keyword specifying value type\");\n\n  std::string typ;\n  std::size_t pos = tag.rfind (' ');\n\n  if (pos != std::string::npos)\n    {\n      global = SUBSTRING_COMPARE_EQ (tag, 0, 6, \"global\");\n\n      typ = (global ? tag.substr (7) : tag);\n    }\n  else\n    typ = tag;\n\n\n  // Special case for backward compatibility.  A small bit of cruft\n  if (SUBSTRING_COMPARE_EQ (typ, 0, 12, \"string array\"))\n    tc = charMatrix ();\n  else if (SUBSTRING_COMPARE_EQ (typ, 0, 15, \"inline function\"))\n    {\n      // Special case for loading old octave_inline_fcn objects.\n      tc = load_inline_fcn (is, filename);\n      return name;\n    }\n  else if (SUBSTRING_COMPARE_EQ (typ, 0, 6, \"object\"))\n    {\n      // classdef object\n      std::string class_nm = extract_keyword (is, \"classname\");\n\n      if (class_nm.empty ())\n        error (\"load: failed to extract keyword specifying classdef class\");\n\n      octave::cdef_class cls = octave::lookup_class (class_nm, false, true);\n\n      if (! cls.ok () || (cls.get_name () != class_nm))\n        error (\"load: no definition for classdef '%s' available\",\n               class_nm.c_str ());\n\n      bool skip_constructor = ! cls.get (\"ConstructOnLoad\").bool_value ();\n      tc = cls.construct (octave_value_list (), skip_constructor);\n    }\n  else\n    {\n      octave::type_info& type_info = octave::__get_type_info__ ();\n\n      tc = type_info.lookup_type (typ);\n    }\n\n  if (! tc.load_ascii (is))\n    error (\"load: trouble reading ascii file '%s'\", filename.c_str ());\n\n  return name;\n}\n\n// Save the data from TC along with the corresponding NAME, and global\n// flag MARK_AS_GLOBAL on stream OS in the plain text format described\n// above for load_text_data.  If NAME is empty, the name: line is not\n// generated.  PRECISION specifies the number of decimal digits to print.\n//\n// Assumes ranges and strings cannot contain Inf or NaN values.\n//\n// Returns 1 for success and 0 for failure.\n\n// FIXME: should probably write the help string here too.\n\nbool\nsave_text_data (std::ostream& os, const octave_value& val_arg,\n                const std::string& name, bool mark_global,\n                int precision)\n{\n  if (! name.empty ())\n    os << \"# name: \" << name << \"\\n\";\n\n  octave_value val = val_arg;\n\n  if (mark_global)\n    os << \"# type: global \";\n  else\n    os << \"# type: \";\n\n  os << val.type_name () << \"\\n\";\n\n  if (! precision)\n    precision = Vsave_precision;\n\n  long old_precision = os.precision ();\n  os.precision (precision);\n\n  bool success = val.save_ascii (os);\n\n  // Insert an extra pair of newline characters after the data so that\n  // multiple data elements may be handled separately by gnuplot (see\n  // the description of the index qualifier for the plot command in the\n  // gnuplot documentation).\n  os << \"\\n\\n\";\n\n  os.precision (old_precision);\n\n  return (os && success);\n}\n\nbool\nsave_text_data_for_plotting (std::ostream& os, const octave_value& t,\n                             const std::string& name)\n{\n  return save_text_data (os, t, name, false, 6);\n}\n\n// Maybe this should be a static function in tree-plot.cc?\n\n// If TC is matrix, save it on stream OS in a format useful for\n// making a 3-D plot with gnuplot.  If PARAMETRIC is TRUE,\n// assume a parametric 3-D plot will be generated.\n\nbool\nsave_three_d (std::ostream& os, const octave_value& tc, bool parametric)\n{\n  octave_idx_type nr = tc.rows ();\n  octave_idx_type nc = tc.columns ();\n\n  if (! tc.is_real_matrix ())\n    error (\"for now, I can only save real matrices in 3-D format\");\n\n  os << \"# 3-D data...\\n\"\n     << \"# type: matrix\\n\"\n     << \"# total rows: \" << nr << \"\\n\"\n     << \"# total columns: \" << nc << \"\\n\";\n\n  long old_precision = os.precision ();\n  os.precision (6);\n\n  if (parametric)\n    {\n      octave_idx_type extras = nc % 3;\n      if (extras)\n        warning (\"ignoring last %\" OCTAVE_IDX_TYPE_FORMAT \" columns\", extras);\n\n      Matrix tmp = tc.matrix_value ();\n      nr = tmp.rows ();\n\n      for (octave_idx_type i = 0; i < nc-extras; i += 3)\n        {\n          os << tmp.extract (0, i, nr-1, i+2);\n          if (i+3 < nc-extras)\n            os << \"\\n\";\n        }\n    }\n  else\n    {\n      Matrix tmp = tc.matrix_value ();\n      nr = tmp.rows ();\n\n      for (octave_idx_type i = 0; i < nc; i++)\n        {\n          os << tmp.extract (0, i, nr-1, i);\n          if (i+1 < nc)\n            os << \"\\n\";\n        }\n    }\n\n  os.precision (old_precision);\n\n  return (static_cast<bool> (os));\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (save_precision, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} save_precision ()\n@deftypefnx {} {@var{old_val} =} save_precision (@var{new_val})\n@deftypefnx {} {@var{old_val} =} save_precision (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the number of digits to\nkeep when saving data in text format.\n\nThe default value is 17 which is the minimum necessary for the lossless saving\nand restoring of IEEE@tie{}754 double values; For IEEE@tie{}754 single values\nthe minimum value is 9.  If file size is a concern, it is probably better to\nchoose a binary format for saving data rather than to reduce the precision of\nthe saved values.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n\n@seealso{save_default_options}\n@end deftypefn */)\n{\n  return set_internal_variable (Vsave_precision, args, nargout,\n                                \"save_precision\", -1,\n                                std::numeric_limits<int>::max ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/ls-oct-text.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ls_oct_text_h)\n#define octave_ls_oct_text_h 1\n\n#include \"octave-config.h\"\n\n#include <limits>\n#include <sstream>\n#include <string>\n\n#include \"str-vec.h\"\n\n#include \"ls-ascii-helper.h\"\n\nclass octave_value;\n\n// Flag for cell elements\n#define CELL_ELT_TAG \"<cell-element>\"\n\n// Used when converting Inf to something that gnuplot can read.\n\n#if ! defined (OCT_RBV)\n#  define OCT_RBV (std::numeric_limits<double>::max () / 100.0)\n#endif\n\nextern OCTINTERP_API std::string\nextract_keyword (std::istream& is, const char *keyword,\n                 const bool next_only = false);\n\nextern OCTINTERP_API std::string\nread_text_data (std::istream& is, const std::string& filename, bool& global,\n                octave_value& tc, octave_idx_type count,\n                const bool do_name_validation = true);\n\nextern OCTINTERP_API bool\nsave_text_data (std::ostream& os, const octave_value& val_arg,\n                const std::string& name, bool mark_global, int precision);\n\nextern OCTINTERP_API bool\nsave_text_data_for_plotting (std::ostream& os, const octave_value& t,\n                             const std::string& name);\n\nextern OCTINTERP_API bool\nsave_three_d (std::ostream& os, const octave_value& t,\n              bool parametric = false);\n\n// Match KEYWORD on stream IS, placing the associated value in VALUE,\n// returning TRUE if successful and FALSE otherwise.\n//\n// Input should look something like:\n//\n//  [%#][ \\t]*keyword[ \\t]*int-value.*\\n\n\ntemplate <typename T>\nbool\nextract_keyword (std::istream& is, const char *keyword, T& value,\n                 const bool next_only = false)\n{\n  bool status = false;\n  value = T ();\n\n  char c;\n  while (is.get (c))\n    {\n      if (c == '%' || c == '#')\n        {\n          std::ostringstream buf;\n\n          while (is.get (c) && (c == ' ' || c == '\\t' || c == '%' || c == '#'))\n            ; // Skip whitespace and comment characters.\n\n          if (isalpha (c))\n            buf << c;\n\n          while (is.get (c) && isalpha (c))\n            buf << c;\n\n          std::string tmp = buf.str ();\n          bool match = (tmp.substr (0, strlen (keyword)) == keyword);\n\n          if (match)\n            {\n              while (is.get (c) && (c == ' ' || c == '\\t' || c == ':'))\n                ; // Skip whitespace and the colon.\n\n              is.putback (c);\n              if (c != '\\n' && c != '\\r')\n                is >> value;\n              if (is)\n                status = true;\n              octave::skip_until_newline (is, false);\n              break;\n            }\n          else if (next_only)\n            break;\n        }\n    }\n  return status;\n}\n\ntemplate <typename T>\nbool\nextract_keyword (std::istream& is, const std::string& kw, T& value,\n                 const bool next_only = false)\n{\n  return extract_keyword (is, kw.c_str (), value, next_only);\n}\n\n// Match one of the elements in KEYWORDS on stream IS, placing the\n// matched keyword in KW and the associated value in VALUE,\n// returning TRUE if successful and FALSE otherwise.\n//\n// Input should look something like:\n//\n//  [%#][ \\t]*keyword[ \\t]*int-value.*\\n\n\ntemplate <typename T>\nbool\nextract_keyword (std::istream& is, const string_vector& keywords,\n                 std::string& kw, T& value, const bool next_only = false)\n{\n  bool status = false;\n  kw = \"\";\n  value = 0;\n\n  char c;\n  while (is.get (c))\n    {\n      if (c == '%' || c == '#')\n        {\n          std::ostringstream buf;\n\n          while (is.get (c) && (c == ' ' || c == '\\t' || c == '%' || c == '#'))\n            ; // Skip whitespace and comment characters.\n\n          if (isalpha (c))\n            buf << c;\n\n          while (is.get (c) && isalpha (c))\n            buf << c;\n\n          std::string tmp = buf.str ();\n\n          for (int i = 0; i < keywords.numel (); i++)\n            {\n              int match = (tmp == keywords[i]);\n\n              if (match)\n                {\n                  kw = keywords[i];\n\n                  while (is.get (c) && (c == ' ' || c == '\\t' || c == ':'))\n                    ; // Skip whitespace and the colon.\n\n                  is.putback (c);\n                  if (c != '\\n' && c != '\\r')\n                    is >> value;\n                  if (is)\n                    status = true;\n                  octave::skip_until_newline (is, false);\n                  return status;\n                }\n            }\n\n          if (next_only)\n            break;\n        }\n    }\n  return status;\n}\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/ls-utils.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"data-conv.h\"\n\n#include \"ls-utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// MAX_VAL and MIN_VAL are assumed to have integral values even though\n// they are stored in doubles.\n\nsave_type\nget_save_type (double /* max_val */, double /* min_val */)\n{\n  save_type st = LS_DOUBLE;\n\n  // Matlab doesn't seem to load the UINT32 type correctly, so let's\n  // avoid it (and the other unsigned types, even though they may not\n  // have the same problem.  And apparently, there are problems with\n  // other smaller types as well.  If we avoid them all, then maybe we\n  // will avoid problems.  Unfortunately, we won't be able to save\n  // space...\n\n  //  if (max_val < 256 && min_val > -1)\n  //    st = LS_U_CHAR;\n  //  else if (max_val < 65536 && min_val > -1)\n  //    st = LS_U_SHORT;\n  //  else if (max_val < 4294967295UL && min_val > -1)\n  //    st = LS_U_INT;\n  //  else if (max_val < 128 && min_val >= -128)\n  //    st = LS_CHAR;\n  //  else if (max_val < 32768 && min_val >= -32768)\n  //    st = LS_SHORT;\n  //  else if (max_val <= 2147483647L && min_val >= -2147483647L)\n  //    st = LS_INT;\n\n  return st;\n}\n\nsave_type\nget_save_type (float /* max_val */, float /* min_val */)\n{\n  save_type st = LS_FLOAT;\n\n  // Matlab doesn't seem to load the UINT32 type correctly, so let's\n  // avoid it (and the other unsigned types, even though they may not\n  // have the same problem.  And apparently, there are problems with\n  // other smaller types as well.  If we avoid them all, then maybe we\n  // will avoid problems.  Unfortunately, we won't be able to save\n  // space...\n\n  //  if (max_val < 256 && min_val > -1)\n  //    st = LS_U_CHAR;\n  //  else if (max_val < 65536 && min_val > -1)\n  //    st = LS_U_SHORT;\n  //  else if (max_val < 4294967295UL && min_val > -1)\n  //    st = LS_U_INT;\n  //  else if (max_val < 128 && min_val >= -128)\n  //    st = LS_CHAR;\n  //  else if (max_val < 32768 && min_val >= -32768)\n  //    st = LS_SHORT;\n  //  else if (max_val <= 2147483647L && min_val >= -2147483647L)\n  //    st = LS_INT;\n\n  return st;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/ls-utils.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ls_utils_h)\n#define octave_ls_utils_h 1\n\n#include \"octave-config.h\"\n\n#include \"data-conv.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API save_type\nget_save_type (double max_val, double min_val);\n\nextern OCTINTERP_API save_type\nget_save_type (float max_val, float min_val);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/mex-private.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2022-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mex_private_h)\n#define octave_mex_private_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API octave_value_list\ncall_mex (octave_mex_function& mex_fcn, const octave_value_list& args,\n          int nargout_arg);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/mk-mxtypes-h.in.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n: ${SED=@SED@}\n\nOCTAVE_IDX_TYPE=\"@OCTAVE_IDX_TYPE@\"\n\n$SED \\\n  -e \"s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by mx-mxtypes-h.sh|\" \\\n  -e \"s|%OCTAVE_IDX_TYPE%|${OCTAVE_IDX_TYPE}|\"\n"
  },
  {
    "path": "libinterp/corefcn/module.mk",
    "content": "DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nCOREFCN_INC = \\\n  %reldir%/auto-shlib.h \\\n  %reldir%/base-text-renderer.h \\\n  %reldir%/Cell.h \\\n  %reldir%/c-file-ptr-stream.h \\\n  %reldir%/call-stack.h \\\n  %reldir%/cdisplay.h \\\n  %reldir%/cmd-edit.h \\\n  %reldir%/cmd-hist.h \\\n  %reldir%/data.h \\\n  %reldir%/defaults.h \\\n  %reldir%/defun-dld.h \\\n  %reldir%/defun-int.h \\\n  %reldir%/defun.h \\\n  %reldir%/display.h \\\n  %reldir%/dynamic-ld.h \\\n  %reldir%/environment.h \\\n  %reldir%/error.h \\\n  %reldir%/errwarn.h \\\n  %reldir%/event-manager.h \\\n  %reldir%/event-queue.h \\\n  %reldir%/fcn-info.h \\\n  %reldir%/file-io.h \\\n  %reldir%/ft-text-renderer.h \\\n  %reldir%/gh-manager.h \\\n  %reldir%/gl-render.h \\\n  %reldir%/gl2ps-print.h \\\n  %reldir%/graphics-handle.h \\\n  %reldir%/graphics-toolkit.h \\\n  %reldir%/gtk-manager.h \\\n  %reldir%/help.h \\\n  %reldir%/hook-fcn.h \\\n  %reldir%/input.h \\\n  %reldir%/interpreter.h \\\n  %reldir%/latex-text-renderer.h \\\n  %reldir%/load-path.h \\\n  %reldir%/load-save.h \\\n  %reldir%/ls-ascii-helper.h \\\n  %reldir%/ls-hdf5.h \\\n  %reldir%/ls-mat-ascii.h \\\n  %reldir%/ls-mat-subsys.h \\\n  %reldir%/ls-mat4.h \\\n  %reldir%/ls-mat5.h \\\n  %reldir%/ls-oct-text.h \\\n  %reldir%/ls-oct-binary.h \\\n  %reldir%/ls-utils.h \\\n  %reldir%/mx-type-traits.h \\\n  %reldir%/mxarray.h \\\n  %reldir%/oct-errno.h \\\n  %reldir%/oct-fstrm.h \\\n  %reldir%/oct-handle.h \\\n  %reldir%/oct-hdf5-types.h \\\n  %reldir%/oct-hist.h \\\n  %reldir%/oct-iostrm.h \\\n  %reldir%/oct-map.h \\\n  %reldir%/oct-prcstrm.h \\\n  %reldir%/oct-procbuf.h \\\n  %reldir%/oct-process.h \\\n  %reldir%/oct-rl-edit.h \\\n  %reldir%/oct-rl-hist.h \\\n  %reldir%/oct-stdstrm.h \\\n  %reldir%/oct-stream.h \\\n  %reldir%/oct-strstrm.h \\\n  %reldir%/oct.h \\\n  %reldir%/octave-default-image.h \\\n  %reldir%/pager.h \\\n  %reldir%/panic.h \\\n  %reldir%/pr-flt-fmt.h \\\n  %reldir%/pr-output.h \\\n  %reldir%/procstream.h \\\n  %reldir%/sighandlers.h \\\n  %reldir%/sparse-xdiv.h \\\n  %reldir%/sparse-xpow.h \\\n  %reldir%/stack-frame.h \\\n  %reldir%/syminfo.h \\\n  %reldir%/symrec.h \\\n  %reldir%/symscope.h \\\n  %reldir%/symtab.h \\\n  %reldir%/sysdep.h \\\n  %reldir%/text-engine.h \\\n  %reldir%/text-renderer.h \\\n  %reldir%/url-handle-manager.h \\\n  %reldir%/utils.h \\\n  %reldir%/variables.h \\\n  %reldir%/xdiv.h \\\n  %reldir%/xnorm.h \\\n  %reldir%/xpow.h \\\n  %reldir%/gzfstream.h\n\nNOINSTALL_COREFCN_INC = \\\n  %reldir%/graphics-utils.h \\\n  %reldir%/interpreter-private.h \\\n  %reldir%/mex-private.h \\\n  %reldir%/oct-hdf5.h \\\n  %reldir%/oct-opengl.h\n\nCOREFCN_C_SRC = \\\n  %reldir%/oct-rl-edit.c \\\n  %reldir%/oct-rl-hist.c\n\n## oct-tex-parser.h is in the SRC list so that it will be distributed\n## but not installed.\n\nCOREFCN_SRC = \\\n  %reldir%/Cell.cc \\\n  %reldir%/__magick_read__.cc \\\n  %reldir%/auto-shlib.cc \\\n  %reldir%/base-text-renderer.cc \\\n  %reldir%/c-file-ptr-stream.cc \\\n  %reldir%/call-stack.cc \\\n  %reldir%/cdisplay.c \\\n  %reldir%/cmd-edit.cc \\\n  %reldir%/cmd-hist.cc \\\n  %reldir%/coct-hdf5-types.c \\\n  %reldir%/data.cc \\\n  %reldir%/debug.cc \\\n  %reldir%/defaults.cc \\\n  %reldir%/defun.cc \\\n  %reldir%/display.cc \\\n  %reldir%/dynamic-ld.cc \\\n  %reldir%/environment.cc \\\n  %reldir%/error.cc \\\n  %reldir%/errwarn.cc \\\n  %reldir%/event-manager.cc \\\n  %reldir%/event-queue.cc \\\n  %reldir%/fcn-info.cc \\\n  %reldir%/file-io.cc \\\n  %reldir%/ft-text-renderer.cc \\\n  %reldir%/gh-manager.cc \\\n  %reldir%/gl-render.cc \\\n  %reldir%/gl2ps-print.cc \\\n  %reldir%/graphics-toolkit.cc \\\n  %reldir%/graphics-utils.cc \\\n  %reldir%/graphics.cc \\\n  %reldir%/gtk-manager.cc \\\n  %reldir%/help.cc \\\n  %reldir%/hook-fcn.cc \\\n  %reldir%/input.cc \\\n  %reldir%/interpreter-private.cc \\\n  %reldir%/interpreter.cc \\\n  %reldir%/latex-text-renderer.cc \\\n  %reldir%/load-path.cc \\\n  %reldir%/load-save.cc \\\n  %reldir%/ls-ascii-helper.cc \\\n  %reldir%/ls-hdf5.cc \\\n  %reldir%/ls-mat-ascii.cc \\\n  %reldir%/ls-mat-subsys.cc \\\n  %reldir%/ls-mat4.cc \\\n  %reldir%/ls-mat5.cc \\\n  %reldir%/ls-oct-binary.cc \\\n  %reldir%/ls-oct-text.cc \\\n  %reldir%/ls-utils.cc \\\n  %reldir%/mxarray.cc \\\n  %reldir%/oct-fstrm.cc \\\n  %reldir%/oct-hdf5-types.cc \\\n  %reldir%/oct-hist.cc \\\n  %reldir%/oct-iostrm.cc \\\n  %reldir%/oct-map.cc \\\n  %reldir%/oct-prcstrm.cc \\\n  %reldir%/oct-procbuf.cc \\\n  %reldir%/oct-process.cc \\\n  %reldir%/oct-stream.cc \\\n  %reldir%/oct-strstrm.cc \\\n  %reldir%/oct-tex-lexer.ll \\\n  %reldir%/oct-tex-parser.h \\\n  %reldir%/oct-tex-parser.yy \\\n  %reldir%/pager.cc \\\n  %reldir%/panic.cc \\\n  %reldir%/pr-flt-fmt.cc \\\n  %reldir%/pr-output.cc \\\n  %reldir%/procstream.cc \\\n  %reldir%/sighandlers.cc \\\n  %reldir%/sparse-xdiv.cc \\\n  %reldir%/sparse-xpow.cc \\\n  %reldir%/stack-frame.cc \\\n  %reldir%/syminfo.cc \\\n  %reldir%/symrec.cc \\\n  %reldir%/symscope.cc \\\n  %reldir%/symtab.cc \\\n  %reldir%/sysdep.cc \\\n  %reldir%/text-engine.cc \\\n  %reldir%/text-renderer.cc \\\n  %reldir%/toplev.cc \\\n  %reldir%/url-handle-manager.cc \\\n  %reldir%/utils.cc \\\n  %reldir%/variables.cc \\\n  %reldir%/xdiv.cc \\\n  %reldir%/xnorm.cc \\\n  %reldir%/xpow.cc \\\n  %reldir%/gzfstream.cc \\\n\t$(COREFCN_C_SRC) \\\n  $(NOINSTALL_COREFCN_INC)\n\n## Special rules for sources which must be built before rest of compilation.\n\n%reldir%/default-defs.h: %reldir%/default-defs.in.h build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)\n\n%reldir%/graphics.h: %reldir%/graphics.in.h %reldir%/genprops.awk | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t && \\\n\t$(AWK) -f $(srcdir)/%reldir%/genprops.awk $< > $@-t && \\\n\tmv $@-t $@\n\n%reldir%/graphics-props.cc: %reldir%/graphics.in.h %reldir%/genprops.awk | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t && \\\n\t$(AWK) -v emit_graphics_props=1 -f $(srcdir)/%reldir%/genprops.awk $< > $@-t && \\\n\tmv $@-t $@\n\n%reldir%/mxtypes.h: %reldir%/mxtypes.in.h %reldir%/mk-mxtypes-h.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(call simple-filter-rule,%reldir%/mk-mxtypes-h.sh)\n\n%reldir%/oct-tex-lexer.ll: %reldir%/oct-tex-lexer.in.ll %reldir%/oct-tex-symbols.in | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t && \\\n\t$(AWK) 'BEGIN { print \"/* DO NOT EDIT.  AUTOMATICALLY GENERATED FROM oct-tex-lexer.in.ll and oct-tex-symbols.in. */\"; } /^@SYMBOL_RULES@$$/ { count = 0; while (getline < \"$(srcdir)/%reldir%/oct-tex-symbols.in\") { if ($$0 !~ /^#.*/ && NF == 3) { printf(\"\\\"\\\\\\\\%s\\\" { yylval->sym = %d; return SYM; }\\n\", $$1, count); count++; } } getline } ! /^@SYMBOL_RULES@$$/ { print }' $< > $@-t && \\\n\tmv $@-t $@\n\n%reldir%/oct-tex-symbols.cc: %reldir%/oct-tex-symbols.in | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t && \\\n\t$(AWK) 'BEGIN { print \"// DO NOT EDIT.  AUTOMATICALLY GENERATED FROM oct-tex-symbols.in.\"; print \"static uint32_t symbol_codes[][2] = {\"; count = 0; } END { print \"};\"; printf(\"static int num_symbol_codes = %d;\\n\", count); } !/^#/ && (NF == 3) { printf(\"  { %s, %s },\\n\", $$2, $$3); count++; }' $< > $@-t && \\\n\tmv $@-t $@\n\n%reldir%/oct-tex-lexer.cc: LEX_OUTPUT_ROOT := lex.octave_tex_\n\nnoinst_LTLIBRARIES += \\\n  %reldir%/libcorefcn.la\n\ninclude %reldir%/numeric/module.mk\ninclude %reldir%/system/module.mk\ninclude %reldir%/util/module.mk\n\n%canon_reldir%_libcorefcn_la_SOURCES = $(COREFCN_SRC)\n\n%canon_reldir%_libcorefcn_la_CPPFLAGS = \\\n  $(libinterp_liboctinterp_la_CPPFLAGS) \\\n  -DOCTAVE_MEX_SOVERSION=\"$(OCTAVE_LIBOCTMEX_SOVERSION_MAJOR)\" \\\n  $(FONTCONFIG_CPPFLAGS) \\\n  $(FT2_CPPFLAGS) \\\n  $(HDF5_CPPFLAGS) \\\n  $(WAYLAND_CLIENT_CPPFLAGS) \\\n  $(Z_CPPFLAGS) \\\n  $(OCTAVE_TEX_PARSER_CPPFLAGS)\n\nlibinterp_EXTRA_DIST += \\\n  %reldir%/default-defs.in.h \\\n  %reldir%/genprops.awk \\\n  %reldir%/graphics.in.h \\\n  %reldir%/mk-mxtypes-h.in.sh \\\n  %reldir%/mxtypes.in.h \\\n  %reldir%/oct-tex-lexer.in.ll \\\n  %reldir%/oct-tex-symbols.in\n\nGEN_CONFIG_SHELL += \\\n  %reldir%/mk-mxtypes-h.sh\n\nlibinterp_liboctinterp_la_LIBADD += %reldir%/libcorefcn.la\n"
  },
  {
    "path": "libinterp/corefcn/mx-type-traits.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mx_type_traits_h)\n#define octave_mx_type_traits_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"mxtypes.h\"\n#include \"oct-inttypes-fwd.h\"\n\ntemplate <typename T>\nclass mx_type_traits\n{\npublic:\n  static const mxClassID mx_class;\n  typedef T mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<bool>\n{\npublic:\n  static const mxClassID mx_class = mxLOGICAL_CLASS;\n  typedef mxDouble mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<char>\n{\npublic:\n  static const mxClassID mx_class = mxCHAR_CLASS;\n  typedef mxChar mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<double>\n{\npublic:\n  static const mxClassID mx_class = mxDOUBLE_CLASS;\n  typedef mxDouble mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<float>\n{\npublic:\n  static const mxClassID mx_class = mxSINGLE_CLASS;\n  typedef mxSingle mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<octave_int8>\n{\npublic:\n  static const mxClassID mx_class = mxINT8_CLASS;\n  typedef mxInt8 mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<octave_uint8>\n{\npublic:\n  static const mxClassID mx_class = mxUINT8_CLASS;\n  typedef mxUint8 mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<octave_int16>\n{\npublic:\n  static const mxClassID mx_class = mxINT16_CLASS;\n  typedef mxInt16 mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<octave_uint16>\n{\npublic:\n  static const mxClassID mx_class = mxUINT16_CLASS;\n  typedef mxUint16 mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<octave_int32>\n{\npublic:\n  static const mxClassID mx_class = mxINT32_CLASS;\n  typedef mxInt32 mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<octave_uint32>\n{\npublic:\n  static const mxClassID mx_class = mxUINT32_CLASS;\n  typedef mxUint32 mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<octave_int64>\n{\npublic:\n  static const mxClassID mx_class = mxINT64_CLASS;\n  typedef mxInt64 mx_type;\n};\n\ntemplate <>\nclass mx_type_traits<octave_uint64>\n{\npublic:\n  static const mxClassID mx_class = mxUINT64_CLASS;\n  typedef mxUint64 mx_type;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/mxarray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// #define OCTAVE_MXARRAY_DEBUG 1\n\n#include <cstdlib>\n#include <cstring>\n\n#include <map>\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n#  include <memory_resource>\n#endif\n#include <set>\n#include <string>\n\n#if defined (OCTAVE_MXARRAY_DEBUG)\n#  include <iostream>\n#endif\n\n#include \"f77-fcn.h\"\n#include \"oct-locbuf.h\"\n#include \"quit.h\"\n\n#include \"Cell.h\"\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"mxarray.h\"\n#include \"oct-map.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-classdef.h\"\n#include \"ov-mex-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"graphics.h\"\n\nOCTAVE_NORETURN static void\nerror_impossible_call (const char *fcn_name)\n{\n  error (\"unexpected call to %s - please report this bug\", fcn_name);\n}\n\nstatic void *\nxmalloc (size_t n)\n{\n  void *ptr = std::malloc (n);\n\n#if defined (OCTAVE_MXARRAY_DEBUG)\n  std::cerr << \"xmalloc (\" << n << \") = \" << ptr << std::endl;\n#endif\n\n  return ptr;\n}\n\nstatic void *\nxrealloc (void *ptr, size_t n)\n{\n  void *newptr = std::realloc (ptr, n);\n\n#if defined (OCTAVE_MXARRAY_DEBUG)\n  std::cerr << \"xrealloc (\" << ptr << \", \" << n << \") = \" << newptr << std::endl;\n#endif\n\n  return newptr;\n}\n\nstatic void\nxfree (void *ptr)\n{\n#if defined (OCTAVE_MXARRAY_DEBUG)\n  std::cerr << \"xfree (\" << ptr << \")\" << std::endl;\n#endif\n\n  std::free (ptr);\n}\n\nstatic mwSize\nmax_str_len (mwSize m, const char **str)\n{\n  int max_len = 0;\n\n  for (mwSize i = 0; i < m; i++)\n    {\n      mwSize tmp = strlen (str[i]);\n\n      if (tmp > max_len)\n        max_len = tmp;\n    }\n\n  return max_len;\n}\n\nstatic void * mxRealloc (void *ptr, std::size_t size);\n\nstatic void mxFree (void *ptr);\n\n// FIXME: Is there a better/standard way to do this job?\n\ntemplate <typename T>\nclass fp_type_traits\n{\npublic:\n  static const bool is_complex = false;\n};\n\ntemplate <>\nclass fp_type_traits<Complex>\n{\npublic:\n  static const bool is_complex = true;\n};\n\ntemplate <>\nclass fp_type_traits<FloatComplex>\n{\npublic:\n  static const bool is_complex = true;\n};\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n\nclass mx_deleting_memory_resource : public std::pmr::memory_resource\n{\nprivate:\n\n  void * do_allocate (std::size_t bytes, size_t /*alignment*/)\n  {\n    void *ptr = xmalloc (bytes);\n\n    if (! ptr)\n      throw std::bad_alloc ();\n\n    return ptr;\n  }\n\n  void do_deallocate (void *ptr, std::size_t /*bytes*/,\n                      std::size_t /*alignment*/)\n  {\n    xfree (ptr);\n  }\n\n  bool do_is_equal (const std::pmr::memory_resource& other) const noexcept\n  {\n    return this == dynamic_cast<const mx_deleting_memory_resource *> (&other);\n  }\n};\n\nclass mx_preserving_memory_resource : public std::pmr::memory_resource\n{\nprivate:\n\n  void * do_allocate (std::size_t bytes, size_t /*alignment*/)\n  {\n    void *ptr = xmalloc (bytes);\n\n    if (! ptr)\n      throw std::bad_alloc ();\n\n    return ptr;\n  }\n\n  void do_deallocate (void * /*ptr*/, std::size_t /*bytes*/,\n                      std::size_t /*alignment*/)\n  { }\n\n  bool do_is_equal (const std::pmr::memory_resource& other) const noexcept\n  {\n    return this == dynamic_cast<const mx_preserving_memory_resource *> (&other);\n  }\n};\n\n// FIXME: Is it OK for the memory resource object to be defined this\n// way?\nstatic mx_deleting_memory_resource the_mx_deleting_memory_resource;\nOCTINTERP_API mx_preserving_memory_resource the_mx_preserving_memory_resource;\n\nOCTINTERP_API std::pmr::memory_resource *current_mx_memory_resource = &the_mx_deleting_memory_resource;\n\n#endif\n\noctave_value_list\nmx_to_ov_args (int nargin, mxArray *argin[])\n{\n  // Use a separate function for this job so that the\n  // current_mx_memory_resource will be restored immediately after the\n  // octave_value objects borrow the mxArray data.  We could also use a\n  // dummy scope in mexCallMATLAB, but this function seems less likely\n  // to be accidentally deleted.\n\n  octave_value_list args (nargin);\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n\n  // Use allocator that doesn't free memory because Octave may mutate\n  // the value (single element mxArray -> scalar octave_value object,\n  // for example) and we need these objects to continue to exist after\n  // mexCallMATLAB returns.\n\n  octave::unwind_protect_var<std::pmr::memory_resource *>\n  upv (current_mx_memory_resource, &the_mx_preserving_memory_resource);\n\n#endif\n\n  for (int i = 0; i < nargin; i++)\n    args(i) = mxArray::as_octave_value (argin[i]);\n\n  return args;\n}\n\nvoid\nmexErrMsgTxt_impl (const char *who, const char *s)\n{\n  std::size_t len;\n\n  if (s && (len = strlen (s)) > 0)\n    {\n      if (s[len - 1] == '\\n')\n        {\n          std::string s_tmp (s, len - 1);\n          error (\"%s: %s\\n\", who, s_tmp.c_str ());\n        }\n      else\n        error (\"%s: %s\", who, s);\n    }\n  else\n    {\n      // For compatibility with Matlab, print an empty message.\n      // Octave's error routine requires a non-null input so use a SPACE.\n      error (\" \");\n    }\n}\n\nint\nmexPutVariable_impl (const char *space, const char *name, const mxArray *ptr)\n{\n  if (! ptr)\n    return 1;\n\n  if (! name)\n    return 1;\n\n  if (name[0] == '\\0')\n    name = ptr->get_name ();\n\n  if (! name || name[0] == '\\0')\n    return 1;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  if (! strcmp (space, \"global\"))\n    {\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n\n      // Use allocator that doesn't free memory because Octave may mutate\n      // the value (single element mxArray -> scalar octave_value object,\n      // for example) and we need these objects to continue to exist after\n      // mexCallMATLAB returns.\n\n      octave::unwind_protect_var<std::pmr::memory_resource *>\n      upv (current_mx_memory_resource, &the_mx_preserving_memory_resource);\n#endif\n\n      interp.global_assign (name, mxArray::as_octave_value (ptr));\n    }\n  else\n    {\n      // FIXME: should this be in variables.cc?\n\n      octave::unwind_protect frame;\n\n      bool caller = ! strcmp (space, \"caller\");\n      bool base = ! strcmp (space, \"base\");\n\n      if (caller || base)\n        {\n          // MEX files don't create a separate frame in the call stack,\n          // so we are already in the \"caller\" frame.\n\n          if (base)\n            {\n              octave::tree_evaluator& tw = interp.get_evaluator ();\n\n              frame.add (&octave::tree_evaluator::restore_frame, &tw,\n                         tw.current_call_stack_frame_number ());\n\n              tw.goto_base_frame ();\n            }\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n\n          // Use allocator that doesn't free memory because Octave may\n          // mutate the value (single element mxArray -> scalar\n          // octave_value object, for example) and we need these objects\n          // to continue to exist after mexCallMATLAB returns.\n\n          octave::unwind_protect_var<std::pmr::memory_resource *>\n          upv (current_mx_memory_resource,\n               &the_mx_preserving_memory_resource);\n#endif\n\n          interp.assign (name, mxArray::as_octave_value (ptr));\n        }\n      else\n        mexErrMsgTxt_impl (\"mexPutVariable\",\n                           \"symbol table does not exist\");\n    }\n\n  return 0;\n}\n\nint\nmexSet_impl (double handle, const char *property, mxArray *val)\n{\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n\n  // Use allocator that doesn't free memory because Octave may mutate\n  // the value (single element mxArray -> scalar octave_value object,\n  // for example) and we need these objects to continue to exist after\n  // mexCallMATLAB returns.\n\n  octave::unwind_protect_var<std::pmr::memory_resource *>\n  upv (current_mx_memory_resource, &the_mx_preserving_memory_resource);\n\n#endif\n\n  bool ret = octave::set_property_in_handle (handle, property,\n             mxArray::as_octave_value (val),\n             \"mexSet\");\n  return (ret ? 0 : 1);\n}\n\n// ------------------------------------------------------------------\n\nmxArray_base::mxArray_base (bool interleaved)\n  : m_interleaved (interleaved)\n{ }\n\nstatic mwIndex\ncalc_single_subscript_internal (mwSize ndims, const mwSize *dims,\n                                mwSize nsubs, const mwIndex *subs)\n{\n  mwIndex retval = 0;\n\n  switch (nsubs)\n    {\n    case 0:\n      break;\n\n    case 1:\n      retval = subs[0];\n      break;\n\n    default:\n      {\n        // Both nsubs and ndims should be at least 2 here.\n\n        mwSize n = (nsubs <= ndims ? nsubs : ndims);\n\n        retval = subs[--n];\n\n        while (--n >= 0)\n          retval = dims[n] * retval + subs[n];\n      }\n      break;\n    }\n\n  return retval;\n}\n\n// The object that handles values pass to MEX files from Octave.  Some\n// methods in this class may set mutate_flag to TRUE to tell the\n// mxArray class to convert to the Matlab-style representation and\n// then invoke the method on that object instead (for example, getting\n// a pointer to real or imaginary data from a complex object requires\n// a mutation but getting a pointer to real data from a real object\n// does not).  Changing the representation causes a copy so we try to\n// avoid it unless it is really necessary.  Once the conversion\n// happens, we delete this representation, so the conversion can only\n// happen once per call to a MEX file.\n\nstatic inline void *maybe_mark_foreign (void *ptr);\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\nstatic inline void maybe_disown_ptr (void *ptr);\n#endif\n\n#define VOID_MUTATION_METHOD(FCN_NAME, ARG_LIST)        \\\n  void FCN_NAME ARG_LIST { request_mutation (); }\n\n#define CONST_VOID_MUTATION_METHOD(FCN_NAME, ARG_LIST)  \\\n  void FCN_NAME ARG_LIST const { request_mutation (); }\n\n#define MUTATION_METHOD(RET_TYPE, FCN_NAME, ARG_LIST, RET_VAL)          \\\n  RET_TYPE FCN_NAME ARG_LIST { request_mutation (); return RET_VAL; }\n\n#define CONST_MUTATION_METHOD(RET_TYPE, FCN_NAME, ARG_LIST, RET_VAL)    \\\n  RET_TYPE FCN_NAME ARG_LIST const { request_mutation (); return RET_VAL; }\n\n#define GET_DATA_METHOD(RT, FCN_NAME, ID, COMPLEXITY)                   \\\n  RT * FCN_NAME () const { return get_data<RT> (ID, COMPLEXITY); }\n\nclass mxArray_octave_value : public mxArray_base\n{\npublic:\n\n  mxArray_octave_value () = delete;\n\n  mxArray_octave_value (bool interleaved, const octave_value& ov)\n    : mxArray_base (interleaved), m_val (ov), m_mutate_flag (false),\n      m_id (mxUNKNOWN_CLASS), m_class_name (nullptr), m_ndims (-1),\n      m_dims (nullptr)\n  { }\n\n  // No assignment!  FIXME: should this be implemented?  Note that we\n  // do have a copy constructor.\n\n  mxArray_octave_value& operator = (const mxArray_octave_value&) = delete;\n\n  mxArray_base * dup () const { return new mxArray_octave_value (*this); }\n\n  mxArray * as_mxArray () const\n  {\n    mxArray *retval = m_val.as_mxArray (m_interleaved);\n\n    // RETVAL is assumed to be an mxArray_matlab object.  Should we\n    // panic_unless that condition here or just check and throw an\n    // error?\n\n    if (retval)\n      {\n        // Preserve cached values of class name and dimensions in case\n        // they will be used after we mutate.\n\n        // set_class_name will handle deleting class name that comes\n        // from as_mxArray conversion function.\n\n        if (m_class_name)\n          {\n            retval->set_class_name (m_class_name);\n\n            m_class_name = nullptr;\n          }\n\n        if (m_dims)\n          {\n            mwSize *xdims = retval->get_dimensions ();\n\n            mxFree (xdims);\n\n            retval->set_dimensions (m_dims, m_ndims);\n\n            m_dims = nullptr;\n          }\n      }\n\n    return retval;\n  }\n\n  ~mxArray_octave_value ()\n  {\n    mxFree (m_class_name);\n    mxFree (m_dims);\n  }\n\n  bool is_octave_value () const { return true; }\n\n  int iscell () const { return m_val.iscell (); }\n\n  int is_char () const { return m_val.is_string (); }\n\n  int is_complex () const { return m_val.iscomplex (); }\n\n  int is_double () const { return m_val.is_double_type (); }\n\n  int is_function_handle () const { return m_val.is_function_handle (); }\n\n  int is_int16 () const { return m_val.is_int16_type (); }\n\n  int is_int32 () const { return m_val.is_int32_type (); }\n\n  int is_int64 () const { return m_val.is_int64_type (); }\n\n  int is_int8 () const { return m_val.is_int8_type (); }\n\n  int is_logical () const { return m_val.islogical (); }\n\n  int is_numeric () const { return m_val.isnumeric (); }\n\n  int is_single () const { return m_val.is_single_type (); }\n\n  int is_sparse () const { return m_val.issparse (); }\n\n  int is_struct () const { return m_val.isstruct (); }\n\n  int is_uint16 () const { return m_val.is_uint16_type (); }\n\n  int is_uint32 () const { return m_val.is_uint32_type (); }\n\n  int is_uint64 () const { return m_val.is_uint64_type (); }\n\n  int is_uint8 () const { return m_val.is_uint8_type (); }\n\n  int is_range () const { return m_val.is_range (); }\n\n  int isreal () const { return m_val.isreal (); }\n\n  int is_logical_scalar_true () const\n  {\n    return (is_logical_scalar () && m_val.is_true ());\n  }\n\n  mwSize get_m () const { return m_val.rows (); }\n\n  mwSize get_n () const\n  {\n    mwSize n = 1;\n\n    // Force m_dims and m_ndims to be cached.\n    get_dimensions ();\n\n    for (mwIndex i = m_ndims - 1; i > 0; i--)\n      n *= m_dims[i];\n\n    return n;\n  }\n\n  mwSize * get_dimensions () const\n  {\n    if (! m_dims)\n      {\n        m_ndims = m_val.ndims ();\n\n        m_dims = static_cast<mwSize *> (mxArray::malloc (m_ndims\n                                        * sizeof (mwSize)));\n\n        const dim_vector& dv = m_val.dims ();\n\n        for (mwIndex i = 0; i < m_ndims; i++)\n          m_dims[i] = dv(i);\n      }\n\n    return m_dims;\n  }\n\n  mwSize get_number_of_dimensions () const\n  {\n    // Force m_dims and m_ndims to be cached.\n    get_dimensions ();\n\n    return m_ndims;\n  }\n\n  VOID_MUTATION_METHOD (set_m, (mwSize))\n  VOID_MUTATION_METHOD (set_n, (mwSize))\n\n  MUTATION_METHOD (int, set_dimensions, (mwSize *, mwSize), 0)\n\n  mwSize get_number_of_elements () const { return m_val.numel (); }\n\n  int isempty () const { return m_val.isempty (); }\n\n  bool is_scalar () const\n  {\n    // Force m_dims and m_ndims to be cached.\n    get_dimensions ();\n\n    return m_ndims == 2 && m_dims[0] == 1 && m_dims[1] == 1;\n  }\n\n  mxClassID get_class_id () const\n  {\n    m_id = mxUNKNOWN_CLASS;\n\n    std::string cn = m_val.class_name ();\n\n    if (cn == \"double\")\n      m_id = mxDOUBLE_CLASS;\n    else if (cn == \"single\")\n      m_id = mxSINGLE_CLASS;\n    else if (cn == \"char\")\n      m_id = mxCHAR_CLASS;\n    else if (cn == \"logical\")\n      m_id = mxLOGICAL_CLASS;\n    else if (cn == \"cell\")\n      m_id = mxCELL_CLASS;\n    else if (cn == \"struct\")\n      m_id = mxSTRUCT_CLASS;\n    else if (cn == \"function_handle\")\n      m_id = mxFUNCTION_CLASS;\n    else if (cn == \"int8\")\n      m_id = mxINT8_CLASS;\n    else if (cn == \"uint8\")\n      m_id = mxUINT8_CLASS;\n    else if (cn == \"int16\")\n      m_id = mxINT16_CLASS;\n    else if (cn == \"uint16\")\n      m_id = mxUINT16_CLASS;\n    else if (cn == \"int32\")\n      m_id = mxINT32_CLASS;\n    else if (cn == \"uint32\")\n      m_id = mxUINT32_CLASS;\n    else if (cn == \"int64\")\n      m_id = mxINT64_CLASS;\n    else if (cn == \"uint64\")\n      m_id = mxUINT64_CLASS;\n\n    return m_id;\n  }\n\n  const char * get_class_name () const\n  {\n    if (! m_class_name)\n      {\n        std::string s = m_val.class_name ();\n        m_class_name = mxArray::strsave (s.c_str ());\n      }\n\n    return m_class_name;\n  }\n\n  // Not allowed.\n  VOID_MUTATION_METHOD (set_class_name, (const char *))\n\n  mxArray * get_property (mwIndex idx, const char *pname) const\n  {\n    mxArray *retval = nullptr;\n\n    if (m_val.is_classdef_object ())\n      {\n        octave_classdef *ov_cdef = m_val.classdef_object_value ();\n\n        if (ov_cdef)\n          {\n            octave_value pval = ov_cdef->get_property (idx, pname);\n\n            if (pval.is_defined())\n              retval = new mxArray (m_interleaved, pval);\n          }\n      }\n\n    return retval;\n  }\n\n  void set_property (mwIndex idx, const char *pname, const mxArray *pval)\n  {\n    if (m_val.is_classdef_object ())\n      {\n        octave_classdef *ov_cdef = m_val.classdef_object_value ();\n\n        if (ov_cdef)\n          ov_cdef->set_property (idx, pname, pval->as_octave_value ());\n      }\n    else\n      err_invalid_type (\"set_property\");\n  }\n\n  CONST_MUTATION_METHOD (mxArray *, get_cell, (mwIndex), nullptr)\n\n  // Not allowed.\n  VOID_MUTATION_METHOD (set_cell, (mwIndex, mxArray *))\n\n  double get_scalar () const\n  {\n    if (m_val.issparse ())\n      {\n        // For sparse arrays, return the first nonzero value.\n        const void *m_data = m_val.mex_get_data ();\n        if (m_data == nullptr)\n          return 0.0;\n\n        if (m_val.islogical ())\n          return *static_cast<const bool *> (m_data);\n        else if (m_val.isreal ())\n          return *static_cast<const double *> (m_data);\n        else  // Complex type, only return real part\n          return *static_cast<const double *> (m_data);\n      }\n    else\n      return m_val.scalar_value (true);\n  }\n\n  void * get_data () const\n  {\n    // Casting away const required for MEX interface.\n\n    void *retval = const_cast<void *> (m_val.mex_get_data ());\n\n    if (retval && (m_val.isreal () || m_interleaved))\n      {\n        maybe_mark_foreign (retval);\n        return retval;\n      }\n\n    request_mutation ();\n    return nullptr;\n  }\n\n  template <typename T>\n  T * get_data (mxClassID class_id, mxComplexity complexity) const\n  {\n    // Casting away const required for MEX interface.\n\n    void *ptr = const_cast<void *> (m_val.mex_get_data (class_id, complexity));\n\n    T *retval = static_cast<T *> (ptr);\n\n    if (retval && (complexity == mxREAL || m_interleaved))\n      {\n        maybe_mark_foreign (retval);\n        return retval;\n      }\n\n    request_mutation ();\n    return nullptr;\n  }\n\n  GET_DATA_METHOD (mxDouble, get_doubles, mxDOUBLE_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxSingle, get_singles, mxSINGLE_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxInt8, get_int8s, mxINT8_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxInt16, get_int16s, mxINT16_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxInt32, get_int32s, mxINT32_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxInt64, get_int64s, mxINT64_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxUint8, get_uint8s, mxUINT8_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxUint16, get_uint16s, mxUINT16_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxUint32, get_uint32s, mxUINT32_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxUint64, get_uint64s, mxUINT64_CLASS, mxREAL);\n\n  GET_DATA_METHOD (mxComplexDouble, get_complex_doubles,\n                   mxDOUBLE_CLASS, mxCOMPLEX);\n\n  GET_DATA_METHOD (mxComplexSingle, get_complex_singles,\n                   mxDOUBLE_CLASS, mxCOMPLEX);\n\n  void * get_imag_data () const\n  {\n    void *retval = nullptr;\n\n    if (is_numeric () && isreal ())\n      retval = nullptr;\n    else\n      request_mutation ();\n\n    return retval;\n  }\n\n  // Not allowed.\n  VOID_MUTATION_METHOD (set_data, (void *))\n\n  MUTATION_METHOD (int, set_doubles, (mxDouble *), 0)\n  MUTATION_METHOD (int, set_singles, (mxSingle *), 0)\n  MUTATION_METHOD (int, set_int8s, (mxInt8 *), 0)\n  MUTATION_METHOD (int, set_int16s, (mxInt16 *), 0)\n  MUTATION_METHOD (int, set_int32s, (mxInt32 *), 0)\n  MUTATION_METHOD (int, set_int64s, (mxInt64 *), 0)\n  MUTATION_METHOD (int, set_uint8s, (mxUint8 *), 0)\n  MUTATION_METHOD (int, set_uint16s, (mxUint16 *), 0)\n  MUTATION_METHOD (int, set_uint32s, (mxUint32 *), 0)\n  MUTATION_METHOD (int, set_uint64s, (mxUint64 *), 0)\n\n  MUTATION_METHOD (int, set_complex_doubles, (mxComplexDouble *), 0)\n  MUTATION_METHOD (int, set_complex_singles, (mxComplexSingle *), 0)\n\n  // Not allowed.\n  VOID_MUTATION_METHOD (set_imag_data, (void *))\n\n  mwIndex * get_ir () const\n  {\n    // Casting away const required for MEX interface.\n\n    octave_idx_type *ptr = const_cast<octave_idx_type *> (m_val.mex_get_ir ());\n    return static_cast<mwIndex *> (maybe_mark_foreign (ptr));\n  }\n\n  mwIndex * get_jc () const\n  {\n    // Casting away const required for MEX interface.\n\n    octave_idx_type *ptr = const_cast<octave_idx_type *> (m_val.mex_get_jc ());\n    return static_cast<mwIndex *> (maybe_mark_foreign (ptr));\n  }\n\n  mwSize get_nzmax () const { return m_val.nzmax (); }\n\n  // Not allowed.\n  VOID_MUTATION_METHOD (set_ir, (mwIndex *))\n\n  // Not allowed.\n  VOID_MUTATION_METHOD (set_jc, (mwIndex *))\n\n  // Not allowed.\n  VOID_MUTATION_METHOD (set_nzmax, (mwSize))\n\n  // Not allowed.\n  MUTATION_METHOD (int, add_field, (const char *), 0)\n\n  // Not allowed.\n  VOID_MUTATION_METHOD (remove_field, (int))\n\n  CONST_MUTATION_METHOD (mxArray *, get_field_by_number, (mwIndex, int), nullptr)\n\n  // Not allowed.\n  VOID_MUTATION_METHOD (set_field_by_number, (mwIndex, int, mxArray *))\n\n  int get_number_of_fields () const { return m_val.nfields (); }\n\n  CONST_MUTATION_METHOD (const char *, get_field_name_by_number, (int), nullptr)\n\n  CONST_MUTATION_METHOD (int, get_field_number, (const char *), 0)\n\n  int get_string (char *buf, mwSize buflen) const\n  {\n    int retval = 1;\n\n    mwSize nel = get_number_of_elements ();\n\n    if (m_val.is_string () && nel < buflen)\n      {\n        charNDArray tmp = m_val.char_array_value ();\n\n        const char *p = tmp.data ();\n\n        for (mwIndex i = 0; i < nel; i++)\n          buf[i] = p[i];\n\n        buf[nel] = 0;\n\n        retval = 0;\n      }\n\n    return retval;\n  }\n\n  char * array_to_string () const\n  {\n    // FIXME: this is supposed to handle multi-byte character strings.\n\n    char *buf = nullptr;\n\n    if (m_val.is_string ())\n      {\n        mwSize nel = get_number_of_elements ();\n\n        buf = static_cast<char *> (mxArray::malloc (nel + 1));\n\n        if (buf)\n          {\n            charNDArray tmp = m_val.char_array_value ();\n\n            const char *p = tmp.data ();\n\n            for (mwIndex i = 0; i < nel; i++)\n              buf[i] = p[i];\n\n            buf[nel] = '\\0';\n          }\n      }\n\n    return buf;\n  }\n\n  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const\n  {\n    // Force m_ndims, n_dims to be cached.\n    get_dimensions ();\n\n    return calc_single_subscript_internal (m_ndims, m_dims, nsubs, subs);\n  }\n\n  std::size_t get_element_size () const\n  {\n    // Force m_id to be cached.\n    get_class_id ();\n\n    switch (m_id)\n      {\n      case mxCELL_CLASS: return sizeof (mxArray *);\n      case mxSTRUCT_CLASS: return sizeof (mxArray *);\n      case mxLOGICAL_CLASS: return sizeof (mxLogical);\n      case mxCHAR_CLASS: return sizeof (mxChar);\n      case mxDOUBLE_CLASS: return get_numeric_element_size (sizeof (mxDouble));\n      case mxSINGLE_CLASS: return get_numeric_element_size (sizeof (mxSingle));\n      case mxINT8_CLASS: return get_numeric_element_size (sizeof (mxInt8));\n      case mxUINT8_CLASS: return get_numeric_element_size (sizeof (mxUint8));\n      case mxINT16_CLASS: return get_numeric_element_size (sizeof (mxInt16));\n      case mxUINT16_CLASS: return get_numeric_element_size (sizeof (mxUint16));\n      case mxINT32_CLASS: return get_numeric_element_size (sizeof (mxInt32));\n      case mxUINT32_CLASS: return get_numeric_element_size (sizeof (mxUint32));\n      case mxINT64_CLASS: return get_numeric_element_size (sizeof (mxInt64));\n      case mxUINT64_CLASS: return get_numeric_element_size (sizeof (mxUint64));\n      case mxFUNCTION_CLASS: return 0;\n      // FIXME: user-defined objects need their own class ID.\n      //        What should they return, size of pointer?\n      default: return 0;\n      }\n  }\n\n  bool mutation_needed () const { return m_mutate_flag; }\n\n  void request_mutation () const\n  {\n    if (m_mutate_flag)\n      error (\"unexpected: m_mutate_flag is true in mxArray_octave_value::request_mutation - please report this bug\");\n\n    m_mutate_flag = true;\n  }\n\n  mxArray * mutate () const { return as_mxArray (); }\n\n  octave_value as_octave_value () const { return m_val; }\n\nprotected:\n\n  mxArray_octave_value (const mxArray_octave_value& arg)\n    : mxArray_base (arg), m_val (arg.m_val), m_mutate_flag (arg.m_mutate_flag),\n      m_id (arg.m_id), m_class_name (mxArray::strsave (arg.m_class_name)),\n      m_ndims (arg.m_ndims),\n      m_dims (m_ndims > 0\n              ? static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize)))\n              : nullptr)\n  {\n    if (m_dims)\n      {\n        for (mwIndex i = 0; i < m_ndims; i++)\n          m_dims[i] = arg.m_dims[i];\n      }\n  }\n\nprivate:\n\n  octave_value m_val;\n\n  mutable bool m_mutate_flag;\n\n  // Caching these does not cost much or lead to much duplicated\n  // code.  For other things, we just request mutation to a\n  // Matlab-style mxArray object.\n\n  mutable mxClassID m_id;\n  mutable char *m_class_name;\n  mutable mwSize m_ndims;\n  mutable mwSize *m_dims;\n};\n\n// The base class for the Matlab-style representation, used to handle\n// things that are common to all Matlab-style objects.\n\nclass mxArray_matlab : public mxArray_base\n{\npublic:\n\n  mxArray_matlab () = delete;\n\n  // No assignment!\n  // FIXME: should this be implemented?\n  //        Note that we *do* have a copy constructor.\n\n  mxArray_matlab& operator = (const mxArray_matlab&) = delete;\n\n  ~mxArray_matlab ()\n  {\n    mxFree (m_class_name);\n    mxFree (m_dims);\n  }\n\n  int iscell () const { return m_id == mxCELL_CLASS; }\n\n  int is_char () const { return m_id == mxCHAR_CLASS; }\n\n  int is_complex () const { return m_is_complex; }\n\n  int is_double () const { return m_id == mxDOUBLE_CLASS; }\n\n  int is_function_handle () const { return m_id == mxFUNCTION_CLASS; }\n\n  int is_int16 () const { return m_id == mxINT16_CLASS; }\n\n  int is_int32 () const { return m_id == mxINT32_CLASS; }\n\n  int is_int64 () const { return m_id == mxINT64_CLASS; }\n\n  int is_int8 () const { return m_id == mxINT8_CLASS; }\n\n  int is_logical () const { return m_id == mxLOGICAL_CLASS; }\n\n  int is_numeric () const\n  {\n    return (m_id == mxDOUBLE_CLASS || m_id == mxSINGLE_CLASS\n            || m_id == mxINT8_CLASS || m_id == mxUINT8_CLASS\n            || m_id == mxINT16_CLASS || m_id == mxUINT16_CLASS\n            || m_id == mxINT32_CLASS || m_id == mxUINT32_CLASS\n            || m_id == mxINT64_CLASS || m_id == mxUINT64_CLASS);\n  }\n\n  int is_single () const { return m_id == mxSINGLE_CLASS; }\n\n  int is_sparse () const { return 0; }\n\n  int is_struct () const { return m_id == mxSTRUCT_CLASS; }\n\n  int is_uint16 () const { return m_id == mxUINT16_CLASS; }\n\n  int is_uint32 () const { return m_id == mxUINT32_CLASS; }\n\n  int is_uint64 () const { return m_id == mxUINT64_CLASS; }\n\n  int is_uint8 () const { return m_id == mxUINT8_CLASS; }\n\n  int is_logical_scalar_true () const\n  {\n    return (is_logical_scalar ()\n            && static_cast<mxLogical *> (get_data ())[0] != 0);\n  }\n\n  mwSize get_m () const { return m_dims[0]; }\n\n  mwSize get_n () const\n  {\n    mwSize n = 1;\n\n    for (mwSize i = m_ndims - 1 ; i > 0 ; i--)\n      n *= m_dims[i];\n\n    return n;\n  }\n\n  mwSize * get_dimensions () const { return m_dims; }\n\n  mwSize get_number_of_dimensions () const { return m_ndims; }\n\n  void set_m (mwSize m) { m_dims[0] = m; }\n\n  void set_n (mwSize n) { m_dims[1] = n; }\n\n  int set_dimensions (mwSize *dims, mwSize ndims)\n  {\n    m_ndims = ndims;\n\n    mxFree (m_dims);\n\n    if (m_ndims > 0)\n      {\n        m_dims\n          = static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize)));\n\n        if (m_dims == nullptr)\n          return 1;\n\n        for (int i = 0; i < m_ndims; i++)\n          m_dims[i] = dims[i];\n\n        return 0;\n      }\n    else\n      {\n        m_dims = nullptr;\n        return 0;\n      }\n  }\n\n  mwSize get_number_of_elements () const\n  {\n    mwSize retval = m_dims[0];\n\n    for (mwIndex i = 1; i < m_ndims; i++)\n      retval *= m_dims[i];\n\n    return retval;\n  }\n\n  int isempty () const { return get_number_of_elements () == 0; }\n\n  bool is_scalar () const\n  {\n    return m_ndims == 2 && m_dims[0] == 1 && m_dims[1] == 1;\n  }\n\n  mxClassID get_class_id () const { return m_id; }\n\n  static std::string get_class_name (mxClassID id)\n  {\n    switch (id)\n      {\n      case mxDOUBLE_CLASS: return \"double\";\n      case mxSINGLE_CLASS: return \"single\";\n      case mxCHAR_CLASS: return \"char\";\n      case mxLOGICAL_CLASS: return \"logical\";\n      case mxCELL_CLASS: return \"cell\";\n      case mxSTRUCT_CLASS: return \"struct\";\n      case mxFUNCTION_CLASS: return \"function_handle\";\n      case mxINT8_CLASS: return \"int8\";\n      case mxUINT8_CLASS: return \"uint8\";\n      case mxINT16_CLASS: return \"int16\";\n      case mxUINT16_CLASS: return \"uint16\";\n      case mxINT32_CLASS: return \"int32\";\n      case mxUINT32_CLASS: return \"uint32\";\n      case mxINT64_CLASS: return \"int64\";\n      case mxUINT64_CLASS: return \"uint64\";\n      case mxUNKNOWN_CLASS: return \"unknown\";\n      // FIXME: should return the classname of user-defined objects\n      default: return \"unknown\";\n      }\n  }\n\n  const char * get_class_name () const\n  {\n    return m_class_name;\n  }\n\n  void set_class_name (const char *name)\n  {\n    mxFree (m_class_name);\n    m_class_name = static_cast<char *> (mxArray::malloc (strlen (name) + 1));\n    strcpy (m_class_name, name);\n  }\n\n  mxArray * get_cell (mwIndex /*idx*/) const\n  {\n    err_invalid_type (\"get_cell\");\n  }\n\n  void set_cell (mwIndex /*idx*/, mxArray * /*val*/)\n  {\n    err_invalid_type (\"set_cell\");\n  }\n\n  double get_scalar () const\n  {\n    err_invalid_type (\"get_scalar\");\n  }\n\n  void * get_data () const\n  {\n    err_invalid_type (\"get_data\");\n  }\n\n  mxDouble * get_doubles () const\n  {\n    err_invalid_type (\"get_doubles\");\n  }\n\n  mxSingle * get_singles () const\n  {\n    err_invalid_type (\"get_singles\");\n  }\n\n  mxInt8 * get_int8s () const\n  {\n    err_invalid_type (\"get_int8s\");\n  }\n\n  mxInt16 * get_int16s () const\n  {\n    err_invalid_type (\"get_int16s\");\n  }\n\n  mxInt32 * get_int32s () const\n  {\n    err_invalid_type (\"get_int32s\");\n  }\n\n  mxInt64 * get_int64s () const\n  {\n    err_invalid_type (\"get_int64s\");\n  }\n\n  mxUint8 * get_uint8s () const\n  {\n    err_invalid_type (\"get_uint8s\");\n  }\n\n  mxUint16 * get_uint16s () const\n  {\n    err_invalid_type (\"get_uint16s\");\n  }\n\n  mxUint32 * get_uint32s () const\n  {\n    err_invalid_type (\"get_uint32s\");\n  }\n\n  mxUint64 * get_uint64s () const\n  {\n    err_invalid_type (\"get_uint64s\");\n  }\n\n  mxComplexDouble * get_complex_doubles () const\n  {\n    err_invalid_type (\"get_complex_doubles\");\n  }\n\n  mxComplexSingle * get_complex_singles () const\n  {\n    err_invalid_type (\"get_complex_singles\");\n  }\n\n  void * get_imag_data () const\n  {\n    err_invalid_type (\"get_imag_data\");\n  }\n\n  void set_data (void * /*pr*/)\n  {\n    err_invalid_type (\"set_data\");\n  }\n\n  int set_doubles (mxDouble *)\n  {\n    err_invalid_type (\"set_doubles\");\n  }\n\n  int set_singles (mxSingle *)\n  {\n    err_invalid_type (\"set_singles\");\n  }\n\n  int set_int8s (mxInt8 *)\n  {\n    err_invalid_type (\"set_int8s\");\n  }\n\n  int set_int16s (mxInt16 *)\n  {\n    err_invalid_type (\"set_int16s\");\n  }\n\n  int set_int32s (mxInt32 *)\n  {\n    err_invalid_type (\"set_int32s\");\n  }\n\n  int set_int64s (mxInt64 *)\n  {\n    err_invalid_type (\"set_int64s\");\n  }\n\n  int set_uint8s (mxUint8 *)\n  {\n    err_invalid_type (\"set_uint8s\");\n  }\n\n  int set_uint16s (mxUint16 *)\n  {\n    err_invalid_type (\"set_uint16s\");\n  }\n\n  int set_uint32s (mxUint32 *)\n  {\n    err_invalid_type (\"set_uint32s\");\n  }\n\n  int set_uint64s (mxUint64 *)\n  {\n    err_invalid_type (\"set_uint64s\");\n  }\n\n  int set_complex_doubles (mxComplexDouble *)\n  {\n    err_invalid_type (\"set_complex_doubles\");\n  }\n\n  int set_complex_singles (mxComplexSingle *)\n  {\n    err_invalid_type (\"set_complex_singles\");\n  }\n\n  void set_imag_data (void * /*pi*/)\n  {\n    err_invalid_type (\"set_imag_data\");\n  }\n\n  mwIndex * get_ir () const\n  {\n    err_invalid_type (\"get_ir\");\n  }\n\n  mwIndex * get_jc () const\n  {\n    err_invalid_type (\"get_jc\");\n  }\n\n  mwSize get_nzmax () const\n  {\n    err_invalid_type (\"get_nzmax\");\n  }\n\n  void set_ir (mwIndex * /*ir*/)\n  {\n    err_invalid_type (\"set_ir\");\n  }\n\n  void set_jc (mwIndex * /*jc*/)\n  {\n    err_invalid_type (\"set_jc\");\n  }\n\n  void set_nzmax (mwSize /*nzmax*/)\n  {\n    err_invalid_type (\"set_nzmax\");\n  }\n\n  int add_field (const char * /*key*/)\n  {\n    err_invalid_type (\"add_field\");\n  }\n\n  void remove_field (int /*key_num*/)\n  {\n    err_invalid_type (\"remove_field\");\n  }\n\n  mxArray * get_field_by_number (mwIndex /*index*/, int /*key_num*/) const\n  {\n    err_invalid_type (\"get_field_by_number\");\n  }\n\n  void set_field_by_number (mwIndex /*index*/, int /*key_num*/,\n                            mxArray * /*val*/)\n  {\n    err_invalid_type (\"set_field_by_number\");\n  }\n\n  int get_number_of_fields () const\n  {\n    err_invalid_type (\"get_number_of_fields\");\n  }\n\n  const char * get_field_name_by_number (int /*key_num*/) const\n  {\n    err_invalid_type (\"get_field_name_by_number\");\n  }\n\n  int get_field_number (const char * /*key*/) const\n  {\n    return -1;\n  }\n\n  int get_string (char * /*buf*/, mwSize /*buflen*/) const\n  {\n    err_invalid_type (\"get_string\");\n  }\n\n  char * array_to_string () const\n  {\n    err_invalid_type (\"array_to_string\");\n  }\n\n  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const\n  {\n    return calc_single_subscript_internal (m_ndims, m_dims, nsubs, subs);\n  }\n\n  std::size_t get_element_size () const\n  {\n    switch (m_id)\n      {\n      case mxCELL_CLASS: return sizeof (mxArray *);\n      case mxSTRUCT_CLASS: return sizeof (mxArray *);\n      case mxLOGICAL_CLASS: return sizeof (mxLogical);\n      case mxCHAR_CLASS: return sizeof (mxChar);\n      case mxDOUBLE_CLASS: return get_numeric_element_size (sizeof (mxDouble));\n      case mxSINGLE_CLASS: return get_numeric_element_size (sizeof (mxSingle));\n      case mxINT8_CLASS: return get_numeric_element_size (sizeof (mxInt8));\n      case mxUINT8_CLASS: return get_numeric_element_size (sizeof (mxUint8));\n      case mxINT16_CLASS: return get_numeric_element_size (sizeof (mxInt16));\n      case mxUINT16_CLASS: return get_numeric_element_size (sizeof (mxUint16));\n      case mxINT32_CLASS: return get_numeric_element_size (sizeof (mxInt32));\n      case mxUINT32_CLASS: return get_numeric_element_size (sizeof (mxUint32));\n      case mxINT64_CLASS: return get_numeric_element_size (sizeof (mxInt64));\n      case mxUINT64_CLASS: return get_numeric_element_size (sizeof (mxUint64));\n      case mxFUNCTION_CLASS: return 0;\n      // FIXME: user-defined objects need their own class ID.\n      //        What should they return, size of pointer?\n      default: return 0;\n      }\n  }\n\nprotected:\n\n  mxArray_matlab (bool interleaved, bool is_complex, mxClassID id,\n                  mwSize ndims, const mwSize *dims)\n    : mxArray_base (interleaved), m_class_name (nullptr), m_id (id),\n      m_is_complex (is_complex), m_ndims (ndims < 2 ? 2 : ndims),\n      m_dims (static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize))))\n  {\n    if (ndims == 0)\n      {\n        m_dims[0] = 0;\n        m_dims[1] = 0;\n      }\n    else if (ndims < 2)\n      {\n        m_dims[0] = 1;\n        m_dims[1] = 1;\n      }\n\n    for (mwIndex i = 0; i < ndims; i++)\n      m_dims[i] = dims[i];\n\n    for (mwIndex i = m_ndims - 1; i > 1; i--)\n      {\n        if (m_dims[i] == 1)\n          m_ndims--;\n        else\n          break;\n      }\n  }\n\n  mxArray_matlab (bool interleaved, bool is_complex, mxClassID id,\n                  const dim_vector& dv)\n    : mxArray_base (interleaved), m_class_name (nullptr), m_id (id),\n      m_is_complex (is_complex), m_ndims (dv.ndims ()),\n      m_dims (static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize))))\n  {\n    for (mwIndex i = 0; i < m_ndims; i++)\n      m_dims[i] = dv(i);\n\n    for (mwIndex i = m_ndims - 1; i > 1; i--)\n      {\n        if (m_dims[i] == 1)\n          m_ndims--;\n        else\n          break;\n      }\n  }\n\n  mxArray_matlab (bool interleaved, bool is_complex, mxClassID id,\n                  mwSize m, mwSize n)\n    : mxArray_base (interleaved), m_class_name (nullptr), m_id (id),\n      m_is_complex (is_complex), m_ndims (2),\n      m_dims (static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize))))\n  {\n    m_dims[0] = m;\n    m_dims[1] = n;\n  }\n\n  mxArray_matlab (const mxArray_matlab& val)\n    : mxArray_base (val), m_class_name (mxArray::strsave (val.m_class_name)),\n      m_id (val.m_id), m_is_complex (val.m_is_complex), m_ndims (val.m_ndims),\n      m_dims (static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize))))\n  {\n    for (mwIndex i = 0; i < m_ndims; i++)\n      m_dims[i] = val.m_dims[i];\n  }\n\n  void set_complexity (bool is_complex) { m_is_complex = is_complex; }\n\n  dim_vector\n  dims_to_dim_vector () const\n  {\n    mwSize nd = get_number_of_dimensions ();\n\n    mwSize *d = get_dimensions ();\n\n    dim_vector dv;\n    dv.resize (nd);\n\n    for (mwIndex i = 0; i < nd; i++)\n      dv(i) = d[i];\n\n    return dv;\n  }\n\nprivate:\n\n  char *m_class_name;\n\n  mxClassID m_id;\n\n  bool m_is_complex;\n\n  mwSize m_ndims;\n  mwSize *m_dims;\n};\n\n\n// Matlab-style numeric, character, and logical data.\n\nclass mxArray_base_full : public mxArray_matlab\n{\npublic:\n\n  mxArray_base_full () = delete;\n\n  mxArray_base_full (bool interleaved, bool is_complex, mxClassID id,\n                     mwSize ndims, const mwSize *dims, bool init = true)\n    : mxArray_matlab (interleaved, is_complex, id, ndims, dims),\n      m_pr (mxArray::alloc (init, get_number_of_elements (), get_element_size ()))\n  { }\n\n  mxArray_base_full (bool interleaved, bool is_complex, mxClassID id,\n                     const dim_vector& dv)\n    : mxArray_matlab (interleaved, is_complex, id, dv),\n      m_pr (mxArray::calloc (get_number_of_elements (), get_element_size ()))\n  { }\n\n  mxArray_base_full (bool interleaved, bool is_complex, mxClassID id,\n                     mwSize m, mwSize n, bool init = true)\n    : mxArray_matlab (interleaved, is_complex, id, m, n),\n      m_pr (mxArray::alloc (init, get_number_of_elements (), get_element_size ()))\n  { }\n\n  mxArray_base_full (bool interleaved, mxClassID id, double val)\n    : mxArray_matlab (interleaved, false, id, 1, 1),\n      m_pr (mxArray::calloc (get_number_of_elements (), get_element_size ()))\n  {\n    double *dpr = static_cast<double *> (m_pr);\n    dpr[0] = val;\n  }\n\n  mxArray_base_full (bool interleaved, mxClassID id, mxLogical val)\n    : mxArray_matlab (interleaved, false, id, 1, 1),\n      m_pr (mxArray::calloc (get_number_of_elements (), get_element_size ()))\n  {\n    mxLogical *lpr = static_cast<mxLogical *> (m_pr);\n    lpr[0] = val;\n  }\n\n  mxArray_base_full (bool interleaved, const char *str)\n    : mxArray_matlab (interleaved, false, mxCHAR_CLASS,\n                      str ? (strlen (str) ? 1 : 0) : 0,\n                      str ? strlen (str) : 0),\n      m_pr (mxArray::calloc (get_number_of_elements (), get_element_size ()))\n  {\n    mxChar *cpr = static_cast<mxChar *> (m_pr);\n    mwSize nel = get_number_of_elements ();\n    for (mwIndex i = 0; i < nel; i++)\n      cpr[i] = str[i];\n  }\n\n  // FIXME: ???\n  mxArray_base_full (bool interleaved, mwSize m, const char **str)\n    : mxArray_matlab (interleaved, false, mxCHAR_CLASS, m, max_str_len (m, str)),\n      m_pr (mxArray::calloc (get_number_of_elements (), get_element_size ()))\n  {\n    mxChar *cpr = static_cast<mxChar *> (m_pr);\n\n    mwSize *dv = get_dimensions ();\n\n    mwSize nc = dv[1];\n\n    for (mwIndex j = 0; j < m; j++)\n      {\n        const char *ptr = str[j];\n\n        std::size_t tmp_len = strlen (ptr);\n\n        for (std::size_t i = 0; i < tmp_len; i++)\n          cpr[m*i+j] = static_cast<mxChar> (ptr[i]);\n\n        for (std::size_t i = tmp_len; i < static_cast<std::size_t> (nc); i++)\n          cpr[m*i+j] = static_cast<mxChar> (' ');\n      }\n  }\n\n  // No assignment!  FIXME: should this be implemented?  Note that we\n  // do have a copy constructor.\n\n  mxArray_base_full& operator = (const mxArray_base_full&) = delete;\n\n  mxArray_base * dup () const\n  {\n    return new mxArray_base_full (*this);\n  }\n\n  ~mxArray_base_full ()\n  {\n    mxFree (m_pr);\n  }\n\n  double get_scalar () const\n  {\n    // FIXME: how does this work for interleaved complex arrays?\n\n    double retval = 0;\n\n    mxClassID id = get_class_id ();\n\n    switch (id)\n      {\n      case mxDOUBLE_CLASS:\n        retval = *(static_cast<double *> (m_pr));\n        break;\n\n      case mxSINGLE_CLASS:\n        retval = *(static_cast<float *> (m_pr));\n        break;\n\n      case mxCHAR_CLASS:\n        retval = *(static_cast<mxChar *> (m_pr));\n        break;\n\n      case mxLOGICAL_CLASS:\n        retval = *(static_cast<bool *> (m_pr));\n        break;\n\n      case mxINT8_CLASS:\n        retval = *(static_cast<int8_t *> (m_pr));\n        break;\n\n      case mxUINT8_CLASS:\n        retval = *(static_cast<uint8_t *> (m_pr));\n        break;\n\n      case mxINT16_CLASS:\n        retval = *(static_cast<int16_t *> (m_pr));\n        break;\n\n      case mxUINT16_CLASS:\n        retval = *(static_cast<uint16_t *> (m_pr));\n        break;\n\n      case mxINT32_CLASS:\n        retval = *(static_cast<int32_t *> (m_pr));\n        break;\n\n      case mxUINT32_CLASS:\n        retval = *(static_cast<uint32_t *> (m_pr));\n        break;\n\n      case mxINT64_CLASS:\n        retval = *(static_cast<int64_t *> (m_pr));\n        break;\n\n      case mxUINT64_CLASS:\n        retval = *(static_cast<uint64_t *> (m_pr));\n        break;\n\n      case mxCELL_CLASS:\n      case mxFUNCTION_CLASS:\n      case mxSTRUCT_CLASS:\n      case mxUNKNOWN_CLASS:\n      case mxVOID_CLASS:\n        {\n          std::string dest_cname = get_class_name (id);\n          error (\"invalid conversion from %s mxArray to %s scalar value\", get_class_name (), dest_cname.c_str ());\n        }\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n    return retval;\n  }\n\n  void * get_data () const { return m_pr; }\n\n  void set_data (void *pr) { m_pr = pr; }\n\n  // The typed get and set functions only work for interleaved data but\n  // they are defined here because this class owns PR.  There are\n  // definitions in the mxArray_separate_full class that override these\n  // functions.\n\n  mxDouble * get_doubles () const\n  {\n    return static_cast<mxDouble *> (m_pr);\n  }\n\n  mxSingle * get_singles () const\n  {\n    return static_cast<mxSingle *> (m_pr);\n  }\n\n  mxInt8 * get_int8s () const\n  {\n    return static_cast<mxInt8 *> (m_pr);\n  }\n\n  mxInt16 * get_int16s () const\n  {\n    return static_cast<mxInt16 *> (m_pr);\n  }\n\n  mxInt32 * get_int32s () const\n  {\n    return static_cast<mxInt32 *> (m_pr);\n  }\n\n  mxInt64 * get_int64s () const\n  {\n    return static_cast<mxInt64 *> (m_pr);\n  }\n\n  mxUint8 * get_uint8s () const\n  {\n    return static_cast<mxUint8 *> (m_pr);\n  }\n\n  mxUint16 * get_uint16s () const\n  {\n    return static_cast<mxUint16 *> (m_pr);\n  }\n\n  mxUint32 * get_uint32s () const\n  {\n    return static_cast<mxUint32 *> (m_pr);\n  }\n\n  mxUint64 * get_uint64s () const\n  {\n    return static_cast<mxUint64 *> (m_pr);\n  }\n\n  mxComplexDouble * get_complex_doubles () const\n  {\n    return static_cast<mxComplexDouble *> (m_pr);\n  }\n\n  mxComplexSingle * get_complex_singles () const\n  {\n    return static_cast<mxComplexSingle *> (m_pr);\n  }\n\n  int set_doubles (mxDouble *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_singles (mxSingle *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_int8s (mxInt8 *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_int16s (mxInt16 *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_int32s (mxInt32 *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_int64s (mxInt64 *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_uint8s (mxUint8 *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_uint16s (mxUint16 *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_uint32s (mxUint32 *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_uint64s (mxUint64 *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_complex_doubles (mxComplexDouble *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_complex_singles (mxComplexSingle *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int get_string (char *buf, mwSize buflen) const\n  {\n    int retval = 0;\n\n    mwSize nel = get_number_of_elements ();\n\n    if (! (nel < buflen))\n      {\n        retval = 1;\n        if (buflen > 0)\n          nel = buflen-1;\n      }\n\n    if (nel < buflen)\n      {\n        mxChar *ptr = static_cast<mxChar *> (m_pr);\n\n        for (mwIndex i = 0; i < nel; i++)\n          buf[i] = static_cast<char> (ptr[i]);\n\n        buf[nel] = 0;\n      }\n\n    return retval;\n  }\n\n  char * array_to_string () const\n  {\n    // FIXME: this is supposed to handle multi-byte character strings.\n\n    mwSize nel = get_number_of_elements ();\n\n    char *buf = static_cast<char *> (mxArray::malloc (nel + 1));\n\n    if (buf)\n      {\n        mxChar *ptr = static_cast<mxChar *> (m_pr);\n\n        for (mwIndex i = 0; i < nel; i++)\n          buf[i] = static_cast<char> (ptr[i]);\n\n        buf[nel] = '\\0';\n      }\n\n    return buf;\n  }\n\n  octave_value as_octave_value () const\n  {\n    octave_value retval;\n\n    const dim_vector& dv = dims_to_dim_vector ();\n\n    switch (get_class_id ())\n      {\n      case mxDOUBLE_CLASS:\n        return (is_complex ()\n                ? fp_to_ov<Complex> (dv) : fp_to_ov<double> (dv));\n\n      case mxSINGLE_CLASS:\n        return (is_complex ()\n                ? fp_to_ov<FloatComplex> (dv) : fp_to_ov<float> (dv));\n\n      case mxCHAR_CLASS:\n        return int_to_ov<mxChar, charNDArray, char> (dv);\n\n      case mxLOGICAL_CLASS:\n        return int_to_ov<mxLogical, boolNDArray, bool> (dv);\n\n      case mxINT8_CLASS:\n        return int_to_ov<int8_t, int8NDArray, octave_int8> (dv);\n\n      case mxUINT8_CLASS:\n        return int_to_ov<uint8_t, uint8NDArray, octave_uint8> (dv);\n\n      case mxINT16_CLASS:\n        return int_to_ov<int16_t, int16NDArray, octave_int16> (dv);\n\n      case mxUINT16_CLASS:\n        return int_to_ov<uint16_t, uint16NDArray, octave_uint16> (dv);\n\n      case mxINT32_CLASS:\n        return int_to_ov<int32_t, int32NDArray, octave_int32> (dv);\n\n      case mxUINT32_CLASS:\n        return int_to_ov<uint32_t, uint32NDArray, octave_uint32> (dv);\n\n      case mxINT64_CLASS:\n        return int_to_ov<int64_t, int64NDArray, octave_int64> (dv);\n\n      case mxUINT64_CLASS:\n        return int_to_ov<uint64_t, uint64NDArray, octave_uint64> (dv);\n\n      case mxCELL_CLASS:\n      case mxFUNCTION_CLASS:\n      case mxSTRUCT_CLASS:\n      case mxUNKNOWN_CLASS:\n      case mxVOID_CLASS:\n        error (\"invalid conversion from %s%s mxArray to octave_value\", (is_complex () ? \"complex \" : \"\"), get_class_name ());\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n    return retval;\n  }\n\nprotected:\n\n  mxArray_base_full (const mxArray_base_full& val)\n    : mxArray_matlab (val),\n      m_pr (mxArray::malloc (get_number_of_elements () * get_element_size ()))\n  {\n    if (m_pr)\n      memcpy (m_pr, val.m_pr, get_number_of_elements () * get_element_size ());\n  }\n\n  template <typename ELT_T>\n  octave_value\n  fp_to_ov (const dim_vector& dv) const\n  {\n    octave_value retval;\n\n    ELT_T *ppr = static_cast<ELT_T *> (m_pr);\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n\n    if (current_mx_memory_resource == &the_mx_deleting_memory_resource)\n      {\n        octave::unwind_action act ([this] () { maybe_disown_ptr (m_pr); });\n\n        return octave_value (Array<ELT_T> (ppr, dv, current_mx_memory_resource));\n      }\n    else\n      return octave_value (Array<ELT_T> (ppr, dv, current_mx_memory_resource));\n\n#else\n\n    // Copy data instead of allowing the octave_value object to borrow\n    // the mxArray object data.\n\n    Array<ELT_T> val (dv);\n\n    ELT_T *ptr = val.rwdata ();\n\n    mwSize nel = get_number_of_elements ();\n\n    for (mwIndex i = 0; i < nel; i++)\n      ptr[i] = ppr[i];\n\n    return octave_value (val);\n\n#endif\n  }\n\n  template <typename ELT_T, typename ARRAY_T, typename ARRAY_ELT_T>\n  octave_value\n  int_to_ov (const dim_vector& dv) const\n  {\n    if (is_complex ())\n      error (\"complex integer types are not supported\");\n\n    ELT_T *ppr = static_cast<ELT_T *> (m_pr);\n\n    // Copy data instead of allowing the octave_value object to borrow\n    // the mxArray object data.\n\n    ARRAY_T val (dv);\n\n    ARRAY_ELT_T *ptr = val.rwdata ();\n\n    mwSize nel = get_number_of_elements ();\n\n    for (mwIndex i = 0; i < nel; i++)\n      ptr[i] = ppr[i];\n\n    return octave_value (val);\n\n  }\n\nprotected:\n\n  // If using interleaved complex storage, this is the pointer to data\n  // (real, complex, or logical).  Otherwise, it is the pointer to the\n  // real part of the data.\n  void *m_pr;\n};\n\nclass mxArray_interleaved_full : public mxArray_base_full\n{\npublic:\n\n  mxArray_interleaved_full () = delete;\n\n  mxArray_interleaved_full (mxClassID id, mwSize ndims, const mwSize *dims,\n                            mxComplexity flag = mxREAL, bool init = true)\n    : mxArray_base_full (true, flag == mxCOMPLEX, id, ndims, dims, init)\n  { }\n\n  mxArray_interleaved_full (mxClassID id, const dim_vector& dv,\n                            mxComplexity flag = mxREAL)\n    : mxArray_base_full (true, flag == mxCOMPLEX, id, dv)\n  { }\n\n  mxArray_interleaved_full (mxClassID id, mwSize m, mwSize n,\n                            mxComplexity flag = mxREAL, bool init = true)\n    : mxArray_base_full (true, flag == mxCOMPLEX, id, m, n, init)\n  { }\n\n  mxArray_interleaved_full (mxClassID id, double val)\n    : mxArray_base_full (true, id, val)\n  { }\n\n  mxArray_interleaved_full (mxClassID id, mxLogical val)\n    : mxArray_base_full (true, id, val)\n  { }\n\n  mxArray_interleaved_full (const char *str)\n    : mxArray_base_full (true, str)\n  { }\n\n  // FIXME: ???\n  mxArray_interleaved_full (mwSize m, const char **str)\n    : mxArray_base_full (true, m, str)\n  { }\n\n  // No assignment!  FIXME: should this be implemented?  Note that we\n  // do have a copy constructor.\n\n  mxArray_interleaved_full& operator = (const mxArray_interleaved_full&) = delete;\n\n  mxArray_base * dup () const\n  {\n    return new mxArray_interleaved_full (*this);\n  }\n\n  ~mxArray_interleaved_full () = default;\n\n  void * get_imag_data () const { error_impossible_call (\"mxArray_interleaved_full::get_imag_data\"); }\n\n  void set_imag_data (void */*pi*/) { error_impossible_call (\"mxArray_interleaved_full::set_imag_data\"); }\n\nprotected:\n\n  mxArray_interleaved_full (const mxArray_interleaved_full& val)\n    : mxArray_base_full (val)\n  { }\n};\n\nclass mxArray_separate_full : public mxArray_base_full\n{\npublic:\n\n  mxArray_separate_full () = delete;\n\n  mxArray_separate_full (mxClassID id, mwSize ndims, const mwSize *dims,\n                         mxComplexity flag = mxREAL, bool init = true)\n    : mxArray_base_full (false, flag == mxCOMPLEX, id, ndims, dims, init),\n      m_pi (flag == mxCOMPLEX\n            ? mxArray::alloc (init, get_number_of_elements (), get_element_size ())\n            : nullptr)\n  { }\n\n  mxArray_separate_full (mxClassID id, const dim_vector& dv,\n                         mxComplexity flag = mxREAL)\n    : mxArray_base_full (false, flag == mxCOMPLEX, id, dv),\n      m_pi (is_complex ()\n            ? mxArray::calloc (get_number_of_elements (), get_element_size ())\n            : nullptr)\n  { }\n\n  mxArray_separate_full (mxClassID id, mwSize m, mwSize n,\n                         mxComplexity flag = mxREAL, bool init = true)\n    : mxArray_base_full (false, flag == mxCOMPLEX, id, m, n, init),\n      m_pi (is_complex ()\n            ? (mxArray::alloc (init, get_number_of_elements (), get_element_size ()))\n            : nullptr)\n  { }\n\n  mxArray_separate_full (mxClassID id, double val)\n    : mxArray_base_full (false, id, val), m_pi (nullptr)\n  { }\n\n  mxArray_separate_full (mxClassID id, mxLogical val)\n    : mxArray_base_full (false, id, val), m_pi (nullptr)\n  { }\n\n  mxArray_separate_full (const char *str)\n    : mxArray_base_full (false, str), m_pi (nullptr)\n  { }\n\n  // FIXME: ???\n  mxArray_separate_full (mwSize m, const char **str)\n    : mxArray_base_full (false, m, str), m_pi (nullptr)\n  { }\n\n  // No assignment!  FIXME: should this be implemented?  Note that we\n  // do have a copy constructor.\n\n  mxArray_separate_full& operator = (const mxArray_separate_full&) = delete;\n\n  mxArray_base * dup () const\n  {\n    return new mxArray_separate_full (*this);\n  }\n\n  ~mxArray_separate_full ()\n  {\n    mxFree (m_pi);\n  }\n\n  void * get_imag_data () const { return m_pi; }\n\n  void set_imag_data (void *pi)\n  {\n    m_pi = pi;\n\n    set_complexity (m_pi != nullptr);\n  }\n\n  mxDouble * get_doubles () const { error_impossible_call (\"mxArray_separate_full::get_doubles\"); }\n  mxSingle * get_singles () const { error_impossible_call (\"mxArray_separate_full::get_singles\"); }\n  mxInt8 * get_int8s () const { error_impossible_call (\"mxArray_separate_full::get_int8s\"); }\n  mxInt16 * get_int16s () const { error_impossible_call (\"mxArray_separate_full::get_int16s\"); }\n  mxInt32 * get_int32s () const { error_impossible_call (\"mxArray_separate_full::get_int32s\"); }\n  mxInt64 * get_int64s () const { error_impossible_call (\"mxArray_separate_full::get_int64s\"); }\n  mxUint8 * get_uint8s () const { error_impossible_call (\"mxArray_separate_full::get_uint8s\"); }\n  mxUint16 * get_uint16s () const { error_impossible_call (\"mxArray_separate_full::get_uint16s\"); }\n  mxUint32 * get_uint32s () const { error_impossible_call (\"mxArray_separate_full::get_uint32s\"); }\n  mxUint64 * get_uint64s () const { error_impossible_call (\"mxArray_separate_full::get_uint64s\"); }\n\n  mxComplexDouble * get_complex_doubles () const { error_impossible_call (\"mxArray_separate_full::get_complex_doubles\"); }\n  mxComplexSingle * get_complex_singles () const { error_impossible_call (\"mxArray_separate_full::get_complex_singles\"); }\n\n  // We don't have complex integer types, but for separate storage they\n  // still would not work.\n  mxComplexInt8 * get_complex_int8s () const { error_impossible_call (\"mxArray_separate_full::get_complex_int8s\"); }\n  mxComplexInt16 * get_complex_int16s () const { error_impossible_call (\"mxArray_separate_full::get_complex_int16s\"); }\n  mxComplexInt32 * get_complex_int32s () const { error_impossible_call (\"mxArray_separate_full::get_complex_int32s\"); }\n  mxComplexInt64 * get_complex_int64s () const { error_impossible_call (\"mxArray_separate_full::get_complex_int64s\"); }\n  mxComplexUint8 * get_complex_uint8s () const { error_impossible_call (\"mxArray_separate_full::get_complex_uint8s\"); }\n  mxComplexUint16 * get_complex_uint16s () const { error_impossible_call (\"mxArray_separate_full::get_complex_uint16s\"); }\n  mxComplexUint32 * get_complex_uint32s () const { error_impossible_call (\"mxArray_separate_full::get_complex_uint32s\"); }\n  mxComplexUint64 * get_complex_uint64s () const { error_impossible_call (\"mxArray_separate_full::get_complex_uint64s\"); }\n\n  int set_doubles (mxDouble *) { error_impossible_call (\"mxArray_separate_full::set_doubles\"); }\n  int set_singles (mxSingle *) { error_impossible_call (\"mxArray_separate_full::set_singles\"); }\n  int set_int8s (mxInt8 *) { error_impossible_call (\"mxArray_separate_full::set_int8s\"); }\n  int set_int16s (mxInt16 *) { error_impossible_call (\"mxArray_separate_full::set_int16s\"); }\n  int set_int32s (mxInt32 *) { error_impossible_call (\"mxArray_separate_full::set_int32s\"); }\n  int set_int64s (mxInt64 *) { error_impossible_call (\"mxArray_separate_full::set_int64s\"); }\n  int set_uint8s (mxUint8 *) { error_impossible_call (\"mxArray_separate_full::set_uint8s\"); }\n  int set_uint16s (mxUint16 *) { error_impossible_call (\"mxArray_separate_full::set_uint16s\"); }\n  int set_uint32s (mxUint32 *) { error_impossible_call (\"mxArray_separate_full::set_uint32s\"); }\n  int set_uint64s (mxUint64 *) { error_impossible_call (\"mxArray_separate_full::set_uint64s\"); }\n\n  int set_complex_doubles (mxComplexDouble *) { error_impossible_call (\"mxArray_separate_full::set_complex_doubles\"); }\n  int set_complex_singles (mxComplexSingle *) { error_impossible_call (\"mxArray_separate_full::set_complex_singles\"); }\n\n  // We don't have complex integer types, but for separate storage they\n  // still would not work.\n  int set_complex_int8s (mxComplexInt8 *) { error_impossible_call (\"mxArray_separate_full::set_complex_int8s\"); }\n  int set_complex_int16s (mxComplexInt16 *) { error_impossible_call (\"mxArray_separate_full::set_complex_int16s\"); }\n  int set_complex_int32s (mxComplexInt32 *) { error_impossible_call (\"mxArray_separate_full::set_complex_int32s\"); }\n  int set_complex_int64s (mxComplexInt64 *) { error_impossible_call (\"mxArray_separate_full::set_complex_int64s\"); }\n  int set_complex_uint8s (mxComplexUint8 *) { error_impossible_call (\"mxArray_separate_full::set_complex_uint8s\"); }\n  int set_complex_uint16s (mxComplexUint16 *) { error_impossible_call (\"mxArray_separate_full::set_complex_uint16s\"); }\n  int set_complex_uint32s (mxComplexUint32 *) { error_impossible_call (\"mxArray_separate_full::set_complex_uint32s\"); }\n  int set_complex_uint64s (mxComplexUint64 *) { error_impossible_call (\"mxArray_separate_full::set_complex_uint64s\"); }\n\n  octave_value as_octave_value () const\n  {\n    if (! is_complex ())\n      return mxArray_base_full::as_octave_value ();\n\n    octave_value retval;\n\n    const dim_vector& dv = dims_to_dim_vector ();\n\n    switch (get_class_id ())\n      {\n      case mxDOUBLE_CLASS:\n        return to_ov<double> (dv);\n\n      case mxSINGLE_CLASS:\n        return to_ov<float> (dv);\n\n      case mxLOGICAL_CLASS:\n      case mxINT8_CLASS:\n      case mxUINT8_CLASS:\n      case mxINT16_CLASS:\n      case mxUINT16_CLASS:\n      case mxINT32_CLASS:\n      case mxUINT32_CLASS:\n      case mxINT64_CLASS:\n      case mxUINT64_CLASS:\n        error (\"complex integer types are not supported\");\n\n      case mxCELL_CLASS:\n      case mxCHAR_CLASS:\n      case mxFUNCTION_CLASS:\n      case mxSTRUCT_CLASS:\n      case mxUNKNOWN_CLASS:\n      case mxVOID_CLASS:\n        error (\"invalid conversion from complex %s mxArray to octave_value\", get_class_name ());\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n    return retval;\n  }\n\nprotected:\n\n  mxArray_separate_full (const mxArray_separate_full& val)\n    : mxArray_base_full (val),\n      m_pi (val.m_pi\n            ? mxArray::malloc (get_number_of_elements () * get_element_size ())\n            : nullptr)\n  {\n    if (m_pi)\n      memcpy (m_pi, val.m_pi, get_number_of_elements () * get_element_size ());\n  }\n\nprivate:\n\n  template <typename T>\n  octave_value\n  to_ov (const dim_vector& dv) const\n  {\n    mwSize nel = get_number_of_elements ();\n\n    T *ppr = static_cast<T *> (m_pr);\n\n    // We allocate in the Array<T> constructor and copy here, so we\n    // don't need the custom allocator for this object.\n\n    Array<std::complex<T>> val (dv);\n\n    std::complex<T> *ptr = val.rwdata ();\n\n    T *ppi = static_cast<T *> (m_pi);\n\n    for (mwIndex i = 0; i < nel; i++)\n      ptr[i] = std::complex<T> (ppr[i], ppi[i]);\n\n    return octave_value (val);\n  }\n\n  // Pointer to the imaginary part of the data.\n  void *m_pi;\n};\n\n// Matlab-style sparse arrays.\n\nclass mxArray_base_sparse : public mxArray_matlab\n{\npublic:\n\n  mxArray_base_sparse () = delete;\n\n  mxArray_base_sparse (bool interleaved, bool is_complex,\n                       mxClassID id, mwSize m, mwSize n, mwSize nzmax)\n    : mxArray_matlab (interleaved, is_complex, id, m, n),\n\n      m_nzmax (nzmax > 0 ? nzmax : 1),\n      m_ir (static_cast<mwIndex *> (mxArray::calloc (m_nzmax, sizeof (mwIndex)))),\n      m_jc (static_cast<mwIndex *> (mxArray::calloc (n + 1, sizeof (mwIndex)))),\n      m_pr (mxArray::calloc (m_nzmax, get_element_size ()))\n  { }\n\nprotected:\n\n  mxArray_base_sparse (const mxArray_base_sparse& val)\n    : mxArray_matlab (val), m_nzmax (val.m_nzmax),\n      m_ir (static_cast<mwIndex *> (mxArray::malloc (m_nzmax * sizeof (mwIndex)))),\n      m_jc (static_cast<mwIndex *> (mxArray::malloc (m_nzmax * sizeof (mwIndex)))),\n      m_pr (mxArray::malloc (m_nzmax * get_element_size ()))\n  {\n    if (m_ir)\n      memcpy (m_ir, val.m_ir, m_nzmax * sizeof (mwIndex));\n\n    if (m_jc)\n      memcpy (m_jc, val.m_jc, (val.get_n () + 1) * sizeof (mwIndex));\n\n    if (m_pr)\n      memcpy (m_pr, val.m_pr, m_nzmax * get_element_size ());\n  }\n\npublic:\n\n  // No assignment!  FIXME: should this be implemented?  Note that we\n  // do have a copy constructor.\n\n  mxArray_base_sparse& operator = (const mxArray_base_sparse&) = delete;\n\n  mxArray_base * dup () const\n  {\n    return new mxArray_base_sparse (*this);\n  }\n\n  ~mxArray_base_sparse ()\n  {\n    mxFree (m_ir);\n    mxFree (m_jc);\n    mxFree (m_pr);\n  }\n\n  int is_sparse () const { return 1; }\n\n  void * get_data () const { return m_pr; }\n\n  void set_data (void *pr) { m_pr = pr; }\n\n  mxDouble * get_doubles () const\n  {\n    return static_cast<mxDouble *> (m_pr);\n  }\n\n  mxComplexDouble * get_complex_doubles () const\n  {\n    return static_cast<mxComplexDouble *> (m_pr);\n  }\n\n  int set_doubles (mxDouble *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  int set_complex_doubles (mxComplexDouble *d)\n  {\n    m_pr = d;\n    return 0;\n  }\n\n  mwIndex * get_ir () const { return m_ir; }\n\n  mwIndex * get_jc () const { return m_jc; }\n\n  mwSize get_nzmax () const { return m_nzmax; }\n\n  void set_ir (mwIndex *ir) { m_ir = ir; }\n\n  void set_jc (mwIndex *jc) { m_jc = jc; }\n\n  void set_nzmax (mwSize nzmax)\n  {\n    /* Require storage for at least 1 element */\n    m_nzmax = (nzmax > 0 ? nzmax : 1);\n  }\n\n  octave_value as_octave_value () const\n  {\n    octave_value retval;\n\n    const dim_vector& dv = dims_to_dim_vector ();\n\n    switch (get_class_id ())\n      {\n      case mxDOUBLE_CLASS:\n        return is_complex () ? to_ov<Complex> (dv): to_ov<double> (dv);\n\n      case mxSINGLE_CLASS:\n        error (\"single precision sparse data type not supported\");\n\n      case mxLOGICAL_CLASS:\n        return to_ov<bool> (dv);\n\n      case mxINT8_CLASS:\n      case mxUINT8_CLASS:\n      case mxINT16_CLASS:\n      case mxUINT16_CLASS:\n      case mxINT32_CLASS:\n      case mxUINT32_CLASS:\n      case mxINT64_CLASS:\n      case mxUINT64_CLASS:\n      case mxCELL_CLASS:\n      case mxCHAR_CLASS:\n      case mxFUNCTION_CLASS:\n      case mxSTRUCT_CLASS:\n      case mxUNKNOWN_CLASS:\n      case mxVOID_CLASS:\n        error (\"invalid conversion from %s%s sparse mxArray to octave_value\", (is_complex () ? \"complex \" : \"\"), get_class_name ());\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n    return retval;\n  }\n\nprotected:\n\n  template <typename ELT_T>\n  octave_value\n  to_ov (const dim_vector& dv) const\n  {\n    ELT_T *ppr = static_cast<ELT_T *> (m_pr);\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n\n    if (current_mx_memory_resource == &the_mx_deleting_memory_resource)\n      {\n        octave::unwind_action act ([this] ()\n        {\n          maybe_disown_ptr (m_pr);\n          maybe_disown_ptr (m_ir);\n          maybe_disown_ptr (m_jc);\n        });\n\n        return octave_value\n               (Sparse<ELT_T> (dv,  static_cast<octave_idx_type> (m_nzmax),\n                               ppr, m_ir, m_jc, current_mx_memory_resource));\n      }\n    else\n      return octave_value\n             (Sparse<ELT_T> (dv,  static_cast<octave_idx_type> (m_nzmax),\n                             ppr, m_ir, m_jc, current_mx_memory_resource));\n#else\n\n    // Copy data instead of allowing the octave_value object to borrow\n    // the mxArray object data.\n\n    octave_idx_type m = dv(0);\n    octave_idx_type n = dv(1);\n\n    Sparse<ELT_T> val (m, n, static_cast<octave_idx_type> (m_nzmax));\n\n    for (mwIndex i = 0; i < m_nzmax; i++)\n      {\n        val.xdata (i) = ppr[i];\n        val.xridx (i) = m_ir[i];\n      }\n\n    for (mwIndex i = 0; i < n + 1; i++)\n      val.xcidx (i) = m_jc[i];\n\n    return octave_value (val);\n\n#endif\n  }\n\n  // Maximun number of nonzero elements.\n  mwSize m_nzmax;\n\n  // Sparse storage indexing arrays.\n  mwIndex *m_ir;\n  mwIndex *m_jc;\n\n  // If using interleaved complex storage, this is the pointer to data\n  // (real, complex, or logical).  Otherwise, it is the pointer to the\n  // real part of the data.\n  void *m_pr;\n};\n\nclass mxArray_interleaved_sparse : public mxArray_base_sparse\n{\npublic:\n\n  mxArray_interleaved_sparse () = delete;\n\n  mxArray_interleaved_sparse (mxClassID id, mwSize m, mwSize n, mwSize nzmax,\n                              mxComplexity flag = mxREAL)\n    : mxArray_base_sparse (true, flag == mxCOMPLEX, id, m, n, nzmax)\n  { }\n\nprivate:\n\n  mxArray_interleaved_sparse (const mxArray_interleaved_sparse& val)\n    : mxArray_base_sparse (val)\n  { }\n\npublic:\n\n  // No assignment!  FIXME: should this be implemented?  Note that we\n  // do have a copy constructor.\n\n  mxArray_interleaved_sparse& operator = (const mxArray_interleaved_sparse&) = delete;\n\n  mxArray_base * dup () const\n  {\n    return new mxArray_interleaved_sparse (*this);\n  }\n\n  ~mxArray_interleaved_sparse () = default;\n\n  void * get_imag_data () const { error_impossible_call (\"mxArray_interleaved_sparse::get_imag_data\"); }\n\n  void set_imag_data (void */*pi*/) { error_impossible_call (\"mxArray_interleaved_sparse::set_imag_data\"); }\n};\n\nclass mxArray_separate_sparse : public mxArray_base_sparse\n{\npublic:\n\n  mxArray_separate_sparse () = delete;\n\n  mxArray_separate_sparse (mxClassID id, mwSize m, mwSize n, mwSize nzmax,\n                           mxComplexity flag = mxREAL)\n    : mxArray_base_sparse (false, flag == mxCOMPLEX, id, m, n, nzmax),\n      m_pi (is_complex ()\n            ? mxArray::calloc (m_nzmax, get_element_size ())\n            : nullptr)\n  { }\n\nprivate:\n\n  mxArray_separate_sparse (const mxArray_separate_sparse& val)\n    : mxArray_base_sparse (val),\n      m_pi (val.m_pi\n            ? mxArray::malloc (m_nzmax * get_element_size ())\n            : nullptr)\n  {\n    if (m_pi)\n      memcpy (m_pi, val.m_pi, m_nzmax * get_element_size ());\n  }\n\npublic:\n\n  // No assignment!  FIXME: should this be implemented?  Note that we\n  // do have a copy constructor.\n\n  mxArray_separate_sparse& operator = (const mxArray_separate_sparse&) = delete;\n\n  mxArray_base * dup () const\n  {\n    return new mxArray_separate_sparse (*this);\n  }\n\n  ~mxArray_separate_sparse ()\n  {\n    mxFree (m_pi);\n  }\n\n  void * get_imag_data () const { return m_pi; }\n\n  void set_imag_data (void *pi)\n  {\n    m_pi = pi;\n    set_complexity (m_pi != nullptr);\n  }\n\n  mxDouble * get_doubles () const { error_impossible_call (\"mxArray_separate_sparse::get_doubles\"); }\n  mxComplexDouble * get_complex_doubles () const { error_impossible_call (\"mxArray_separate_sparse::get_complex_doubles\"); }\n\n  int set_doubles (mxDouble *) { error_impossible_call (\"mxArray_separate_sparse::set_doubles\"); }\n  int set_complex_doubles (mxComplexDouble *) { error_impossible_call (\"mxArray_separate_sparse::set_complex_doubles\"); }\n\n  octave_value as_octave_value () const\n  {\n    if (! is_complex ())\n      return mxArray_base_sparse::as_octave_value ();\n\n    octave_value retval;\n\n    switch (get_class_id ())\n      {\n      case mxDOUBLE_CLASS:\n        {\n          double *ppr = static_cast<double *> (m_pr);\n          double *ppi = static_cast<double *> (m_pi);\n\n          SparseComplexMatrix val (get_m (), get_n (),\n                                   static_cast<octave_idx_type> (m_nzmax));\n\n          for (mwIndex i = 0; i < m_nzmax; i++)\n            {\n              val.xdata (i) = Complex (ppr[i], ppi[i]);\n              val.xridx (i) = m_ir[i];\n            }\n\n          for (mwIndex i = 0; i < get_n () + 1; i++)\n            val.xcidx (i) = m_jc[i];\n\n          retval = val;\n        }\n        break;\n\n      case mxSINGLE_CLASS:\n        error (\"single precision sparse data type not supported\");\n\n      case mxLOGICAL_CLASS:\n      case mxINT8_CLASS:\n      case mxUINT8_CLASS:\n      case mxINT16_CLASS:\n      case mxUINT16_CLASS:\n      case mxINT32_CLASS:\n      case mxUINT32_CLASS:\n      case mxINT64_CLASS:\n      case mxUINT64_CLASS:\n      case mxCELL_CLASS:\n      case mxCHAR_CLASS:\n      case mxFUNCTION_CLASS:\n      case mxSTRUCT_CLASS:\n      case mxUNKNOWN_CLASS:\n      case mxVOID_CLASS:\n        error (\"invalid conversion from complex %s sparse mxArray to octave_value\", get_class_name ());\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n    return retval;\n  }\n\nprivate:\n\n  // Pointer to the imaginary part of the data.\n  void *m_pi;\n};\n\n// Matlab-style struct arrays.\n\nclass mxArray_struct : public mxArray_matlab\n{\npublic:\n\n  mxArray_struct () = delete;\n\n  mxArray_struct (bool interleaved, mwSize ndims, const mwSize *dims,\n                  int num_keys, const char **keys)\n    : mxArray_matlab (interleaved, false, mxSTRUCT_CLASS, ndims, dims),\n      m_nfields (num_keys),\n      m_fields (static_cast<char **> (mxArray::calloc (m_nfields,\n                                      sizeof (char *)))),\n      m_data (static_cast<mxArray * *> (mxArray::calloc (m_nfields *\n                                        get_number_of_elements (),\n                                        sizeof (mxArray *))))\n  {\n    init (keys);\n  }\n\n  mxArray_struct (bool interleaved, const dim_vector& dv, int num_keys,\n                  const char **keys)\n    : mxArray_matlab (interleaved, false, mxSTRUCT_CLASS, dv),\n      m_nfields (num_keys),\n      m_fields (static_cast<char **> (mxArray::calloc (m_nfields,\n                                      sizeof (char *)))),\n      m_data (static_cast<mxArray * *> (mxArray::calloc (m_nfields *\n                                        get_number_of_elements (),\n                                        sizeof (mxArray *))))\n  {\n    init (keys);\n  }\n\n  mxArray_struct (bool interleaved, mwSize m, mwSize n, int num_keys,\n                  const char **keys)\n    : mxArray_matlab (interleaved, false, mxSTRUCT_CLASS, m, n),\n      m_nfields (num_keys),\n      m_fields (static_cast<char **> (mxArray::calloc (m_nfields,\n                                      sizeof (char *)))),\n      m_data (static_cast<mxArray * *> (mxArray::calloc (m_nfields *\n                                        get_number_of_elements (),\n                                        sizeof (mxArray *))))\n  {\n    init (keys);\n  }\n\nprivate:\n\n  mxArray_struct (const mxArray_struct& val)\n    : mxArray_matlab (val), m_nfields (val.m_nfields),\n      m_fields (static_cast<char **> (mxArray::malloc (m_nfields\n                                      * sizeof (char *)))),\n      m_data (static_cast<mxArray * *> (mxArray::malloc (m_nfields *\n                                        get_number_of_elements ()\n                                        * sizeof (mxArray *))))\n  {\n    for (int i = 0; i < m_nfields; i++)\n      m_fields[i] = mxArray::strsave (val.m_fields[i]);\n\n    mwSize nel = get_number_of_elements ();\n\n    for (mwIndex i = 0; i < nel * m_nfields; i++)\n      {\n        mxArray *ptr = val.m_data[i];\n        m_data[i] = (ptr ? ptr->dup () : nullptr);\n      }\n  }\n\npublic:\n\n  // No assignment!  FIXME: should this be implemented?  Note that we\n  // do have a copy constructor.\n\n  mxArray_struct& operator = (const mxArray_struct& val) = delete;\n\n  void init (const char **keys)\n  {\n    for (int i = 0; i < m_nfields; i++)\n      m_fields[i] = mxArray::strsave (keys[i]);\n  }\n\n  mxArray_base * dup () const { return new mxArray_struct (*this); }\n\n  ~mxArray_struct ()\n  {\n    for (int i = 0; i < m_nfields; i++)\n      mxFree (m_fields[i]);\n\n    mxFree (m_fields);\n\n    mwSize ntot = m_nfields * get_number_of_elements ();\n\n    for  (mwIndex i = 0; i < ntot; i++)\n      delete m_data[i];\n\n    mxFree (m_data);\n  }\n\n  int add_field (const char *key)\n  {\n    int retval = -1;\n\n    m_nfields++;\n\n    m_fields = static_cast<char **>\n               (mxRealloc (m_fields, m_nfields * sizeof (char *)));\n\n    if (m_fields)\n      {\n        m_fields[m_nfields-1] = mxArray::strsave (key);\n\n        mwSize nel = get_number_of_elements ();\n\n        mwSize ntot = m_nfields * nel;\n\n        mxArray **new_data;\n        new_data = static_cast<mxArray **>\n                   (mxArray::malloc (ntot * sizeof (mxArray *)));\n\n        if (new_data)\n          {\n            mwIndex j = 0;\n            mwIndex k = 0;\n            mwIndex n = 0;\n\n            for (mwIndex i = 0; i < ntot; i++)\n              {\n                if (++n == m_nfields)\n                  {\n                    new_data[j++] = nullptr;\n                    n = 0;\n                  }\n                else\n                  new_data[j++] = m_data[k++];\n              }\n\n            mxFree (m_data);\n\n            m_data = new_data;\n\n            retval = m_nfields - 1;\n          }\n      }\n\n    return retval;\n  }\n\n  void remove_field (int key_num)\n  {\n    if (key_num >= 0 && key_num < m_nfields)\n      {\n        mwSize nel = get_number_of_elements ();\n\n        mwSize ntot = m_nfields * nel;\n\n        int new_nfields = m_nfields - 1;\n\n        char **new_fields = static_cast<char **>\n                            (mxArray::malloc (new_nfields * sizeof (char *)));\n\n        mxArray **new_data = static_cast<mxArray **>\n                             (mxArray::malloc (new_nfields * nel\n                                               * sizeof (mxArray *)));\n\n        for (int i = 0; i < key_num; i++)\n          new_fields[i] = m_fields[i];\n\n        for (int i = key_num + 1; i < m_nfields; i++)\n          new_fields[i-1] = m_fields[i];\n\n        if (new_nfields > 0)\n          {\n            mwIndex j = 0;\n            mwIndex k = 0;\n            mwIndex n = 0;\n\n            for (mwIndex i = 0; i < ntot; i++)\n              {\n                if (n == key_num)\n                  k++;\n                else\n                  new_data[j++] = m_data[k++];\n\n                if (++n == m_nfields)\n                  n = 0;\n              }\n          }\n\n        m_nfields = new_nfields;\n\n        mxFree (m_fields);\n        mxFree (m_data);\n\n        m_fields = new_fields;\n        m_data = new_data;\n      }\n  }\n\n  mxArray * get_field_by_number (mwIndex index, int key_num) const\n  {\n    return key_num >= 0 && key_num < m_nfields\n           ? m_data[m_nfields * index + key_num] : nullptr;\n  }\n\n  void set_field_by_number (mwIndex index, int key_num, mxArray *val);\n\n  int get_number_of_fields () const { return m_nfields; }\n\n  const char * get_field_name_by_number (int key_num) const\n  {\n    return key_num >= 0 && key_num < m_nfields ? m_fields[key_num] : nullptr;\n  }\n\n  int get_field_number (const char *key) const\n  {\n    int retval = -1;\n\n    for (int i = 0; i < m_nfields; i++)\n      {\n        if (! strcmp (key, m_fields[i]))\n          {\n            retval = i;\n            break;\n          }\n      }\n\n    return retval;\n  }\n\n  void * get_data () const { return m_data; }\n\n  void set_data (void *data) { m_data = static_cast<mxArray **> (data); }\n\n  octave_value as_octave_value () const\n  {\n    const dim_vector& dv = dims_to_dim_vector ();\n\n    string_vector keys (m_fields, m_nfields);\n\n    octave_map m (dv);\n\n    mwSize ntot = m_nfields * get_number_of_elements ();\n\n    for (int i = 0; i < m_nfields; i++)\n      {\n        Cell c (dv);\n\n        octave_value *p = c.rwdata ();\n\n        mwIndex k = 0;\n        for (mwIndex j = i; j < ntot; j += m_nfields)\n          p[k++] = mxArray::as_octave_value (m_data[j]);\n\n        m.assign (keys[i], c);\n      }\n\n    return m;\n  }\n\nprivate:\n\n  int m_nfields;\n\n  char **m_fields;\n\n  mxArray **m_data;\n};\n\n// Matlab-style cell arrays.\n\nclass mxArray_cell : public mxArray_matlab\n{\npublic:\n\n  mxArray_cell () = delete;\n\n  mxArray_cell (bool interleaved, mwSize ndims, const mwSize *dims)\n    : mxArray_matlab (interleaved, false, mxCELL_CLASS, ndims, dims),\n      m_data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))\n  { }\n\n  mxArray_cell (bool interleaved, const dim_vector& dv)\n    : mxArray_matlab (interleaved, false, mxCELL_CLASS, dv),\n      m_data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))\n  { }\n\n  mxArray_cell (bool interleaved, mwSize m, mwSize n)\n    : mxArray_matlab (interleaved, false, mxCELL_CLASS, m, n),\n      m_data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))\n  { }\n\nprivate:\n\n  mxArray_cell (const mxArray_cell& val)\n    : mxArray_matlab (val),\n      m_data (static_cast<mxArray **> (mxArray::malloc (get_number_of_elements () * sizeof (mxArray *))))\n  {\n    mwSize nel = get_number_of_elements ();\n\n    for (mwIndex i = 0; i < nel; i++)\n      {\n        mxArray *ptr = val.m_data[i];\n        m_data[i] = (ptr ? ptr->dup () : nullptr);\n      }\n  }\n\npublic:\n\n  // No assignment!  FIXME: should this be implemented?  Note that we\n  // do have a copy constructor.\n\n  mxArray_cell& operator = (const mxArray_cell&) = delete;\n\n  mxArray_base * dup () const { return new mxArray_cell (*this); }\n\n  ~mxArray_cell ()\n  {\n    mwSize nel = get_number_of_elements ();\n\n    for (mwIndex i = 0; i < nel; i++)\n      delete m_data[i];\n\n    mxFree (m_data);\n  }\n\n  mxArray * get_cell (mwIndex idx) const\n  {\n    return idx >= 0 && idx < get_number_of_elements () ? m_data[idx] : nullptr;\n  }\n\n  void set_cell (mwIndex idx, mxArray *val);\n\n  void * get_data () const { return m_data; }\n\n  void set_data (void *data) { m_data = static_cast<mxArray **> (data); }\n\n  octave_value as_octave_value () const\n  {\n    const dim_vector& dv = dims_to_dim_vector ();\n\n    Cell c (dv);\n\n    mwSize nel = get_number_of_elements ();\n\n    octave_value *p = c.rwdata ();\n\n    for (mwIndex i = 0; i < nel; i++)\n      p[i] = mxArray::as_octave_value (m_data[i]);\n\n    return c;\n  }\n\nprivate:\n\n  mxArray **m_data;\n};\n\n// ------------------------------------------------------------------\n\nmxArray::mxArray (bool interleaved, const octave_value& ov)\n  : m_rep (create_rep (interleaved, ov)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mxClassID id, mwSize ndims,\n                  const mwSize *dims, mxComplexity flag, bool init)\n  : m_rep (create_rep (interleaved, id, ndims, dims, flag, init)),\n    m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mxClassID id, const dim_vector& dv,\n                  mxComplexity flag)\n  : m_rep (create_rep (interleaved, id, dv, flag)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n,\n                  mxComplexity flag, bool init)\n  : m_rep (create_rep (interleaved, id, m, n, flag, init)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mxClassID id, double val)\n  : m_rep (create_rep (interleaved, id, val)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mxClassID id, mxLogical val)\n  : m_rep (create_rep (interleaved, id, val)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, const char *str)\n  : m_rep (create_rep (interleaved, str)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mwSize m, const char **str)\n  : m_rep (create_rep (interleaved, m, str)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n,\n                  mwSize nzmax, mxComplexity flag)\n  : m_rep (create_rep (interleaved, id, m, n, nzmax, flag)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mwSize ndims, const mwSize *dims,\n                  int num_keys,\n                  const char **keys)\n  : m_rep (new mxArray_struct (interleaved, ndims, dims, num_keys, keys)),\n    m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, const dim_vector& dv, int num_keys,\n                  const char **keys)\n  : m_rep (new mxArray_struct (interleaved, dv, num_keys, keys)),\n    m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mwSize m, mwSize n, int num_keys,\n                  const char **keys)\n  : m_rep (new mxArray_struct (interleaved, m, n, num_keys, keys)),\n    m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mwSize ndims, const mwSize *dims)\n  : m_rep (new mxArray_cell (interleaved, ndims, dims)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, const dim_vector& dv)\n  : m_rep (new mxArray_cell (interleaved, dv)), m_name (nullptr)\n{ }\n\nmxArray::mxArray (bool interleaved, mwSize m, mwSize n)\n  : m_rep (new mxArray_cell (interleaved, m, n)), m_name (nullptr)\n{ }\n\nmxArray::~mxArray ()\n{\n  mxFree (m_name);\n\n  delete m_rep;\n}\n\nvoid\nmxArray::set_name (const char *name)\n{\n  mxFree (m_name);\n  m_name = mxArray::strsave (name);\n}\n\noctave_value\nmxArray::as_octave_value (const mxArray *ptr, bool null_is_empty)\n{\n  static const octave_value empty_matrix = Matrix ();\n\n  return (ptr\n          ? ptr->as_octave_value ()\n          : (null_is_empty ? empty_matrix : octave_value ()));\n}\n\noctave_value\nmxArray::as_octave_value () const\n{\n  return m_rep->as_octave_value ();\n}\n\nmxArray_base *\nmxArray::create_rep (bool interleaved, const octave_value& ov)\n{\n  return new mxArray_octave_value (interleaved, ov);\n}\n\nmxArray_base *\nmxArray::create_rep (bool interleaved, mxClassID id, mwSize ndims,\n                     const mwSize *dims, mxComplexity flag, bool init)\n{\n  if (interleaved)\n    return new mxArray_interleaved_full (id, ndims, dims, flag, init);\n  else\n    return new mxArray_separate_full (id, ndims, dims, flag, init);\n}\n\nmxArray_base *\nmxArray::create_rep (bool interleaved, mxClassID id, const dim_vector& dv,\n                     mxComplexity flag)\n{\n  if (interleaved)\n    return new mxArray_interleaved_full (id, dv, flag);\n  else\n    return new mxArray_separate_full (id, dv, flag);\n}\n\nmxArray_base *\nmxArray::create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,\n                     mxComplexity flag, bool init)\n{\n  if (interleaved)\n    return new mxArray_interleaved_full (id, m, n, flag, init);\n  else\n    return new mxArray_separate_full (id, m, n, flag, init);\n}\n\nmxArray_base *\nmxArray::create_rep (bool interleaved, mxClassID id, double val)\n{\n  if (interleaved)\n    return new mxArray_interleaved_full (id, val);\n  else\n    return new mxArray_separate_full (id, val);\n}\n\nmxArray_base *\nmxArray::create_rep (bool interleaved, mxClassID id, mxLogical val)\n{\n  if (interleaved)\n    return new mxArray_interleaved_full (id, val);\n  else\n    return new mxArray_separate_full (id, val);\n}\n\nmxArray_base *\nmxArray::create_rep (bool interleaved, const char *str)\n{\n  if (interleaved)\n    return new mxArray_interleaved_full (str);\n  else\n    return new mxArray_separate_full (str);\n}\n\nmxArray_base *\nmxArray::create_rep (bool interleaved, mwSize m, const char **str)\n{\n  if (interleaved)\n    return new mxArray_interleaved_full (m, str);\n  else\n    return new mxArray_separate_full (m, str);\n}\n\nmxArray_base *\nmxArray::create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,\n                     mwSize nzmax, mxComplexity flag)\n{\n  if (interleaved)\n    return new mxArray_interleaved_sparse (id, m, n, nzmax, flag);\n  else\n    return new mxArray_separate_sparse (id, m, n, nzmax, flag);\n}\n\nvoid\nmxArray::maybe_mutate () const\n{\n  if (m_rep->is_octave_value ())\n    {\n      // The mutate function returns a pointer to a complete new\n      // mxArray object (or 0, if no mutation happened).  We just want\n      // to replace the existing rep with the rep from the new object.\n\n      mxArray *new_val = m_rep->mutate ();\n\n      if (new_val)\n        {\n          delete m_rep;\n          m_rep = new_val->m_rep;\n          new_val->m_rep = nullptr;\n          delete new_val;\n        }\n    }\n}\n\n// ------------------------------------------------------------------\n\n// A class to manage calls to MEX functions.  Mostly deals with memory\n// management.\n\nmex::~mex ()\n{\n  // We can't use mex::free here because it modifies memlist.\n  while (! m_memlist.empty ())\n    {\n      auto p = m_memlist.begin ();\n      xfree (*p);\n      m_memlist.erase (p);\n    }\n\n  // We can't use mex::free_value here because it modifies arraylist.\n  while (! m_arraylist.empty ())\n    {\n      auto p = m_arraylist.begin ();\n      delete *p;\n      m_arraylist.erase (p);\n    }\n\n  if (! (m_memlist.empty () && m_arraylist.empty ()))\n    error (\"mex: %s: cleanup failed\", function_name ());\n\n  mxFree (m_fname);\n}\n\nconst char *\nmex::function_name () const\n{\n  if (! m_fname)\n    {\n      octave::tree_evaluator& tw = octave::__get_evaluator__ ();\n\n      octave_function *fcn = tw.current_function ();\n\n      if (fcn)\n        {\n          std::string nm = fcn->name ();\n          m_fname = mxArray::strsave (nm.c_str ());\n        }\n      else\n        m_fname = mxArray::strsave (\"unknown\");\n    }\n\n  return m_fname;\n}\n\n// Allocate memory.\nvoid *\nmex::malloc_unmarked (std::size_t n)\n{\n  void *ptr = xmalloc (n);\n\n  if (! ptr)\n    {\n      // FIXME: could use \"octave_new_handler();\" instead\n      error (\"%s: failed to allocate %zd bytes of memory\",\n             function_name (), n);\n    }\n\n  global_mark (ptr);\n\n  return ptr;\n}\n\n// Reallocate a pointer obtained from malloc or calloc.\n// If the pointer is NULL, allocate using malloc.\n// We don't need an \"unmarked\" version of this.\nvoid *\nmex::realloc (void *ptr, std::size_t n)\n{\n  void *v;\n\n  if (ptr)\n    {\n      auto p_local = m_memlist.find (ptr);\n      auto p_global = s_global_memlist.find (ptr);\n\n      v = xrealloc (ptr, n);\n\n      if (v)\n        {\n          if (p_local != m_memlist.end ())\n            {\n              m_memlist.erase (p_local);\n              m_memlist.insert (v);\n            }\n\n          if (p_global != s_global_memlist.end ())\n            {\n              s_global_memlist.erase (p_global);\n              s_global_memlist.insert (v);\n            }\n        }\n    }\n  else\n    v = malloc (n);\n\n  return v;\n}\n\n// Free a pointer obtained from malloc or calloc.\nvoid mex::free (void *ptr)\n{\n  if (ptr)\n    {\n      unmark (ptr);\n\n      auto p = s_global_memlist.find (ptr);\n\n      if (p != s_global_memlist.end ())\n        {\n          s_global_memlist.erase (p);\n\n          xfree (ptr);\n        }\n      else\n        {\n          p = m_foreign_memlist.find (ptr);\n\n          if (p != m_foreign_memlist.end ())\n            m_foreign_memlist.erase (p);\n#if defined (OCTAVE_MXARRAY_DEBUG)\n          else\n            warning (\"mxFree: skipping memory not allocated by mxMalloc, mxCalloc, or mxRealloc\");\n#endif\n        }\n    }\n}\n\n// List of memory resources we allocated.\nstd::set<void *> mex::s_global_memlist;\n\n// Current context.\nOCTINTERP_API mex *mex_context = nullptr;\n\nvoid * mxRealloc (void *ptr, std::size_t size)\n{\n  return (mex_context\n          ? mex_context->realloc (ptr, size) : xrealloc (ptr, size));\n}\n\nvoid mxFree (void *ptr)\n{\n  if (mex_context)\n    mex_context->free (ptr);\n  else\n    xfree (ptr);\n}\n\nvoid *\nmxArray::malloc (std::size_t n)\n{\n  return mex_context ? mex_context->malloc_unmarked (n) : xmalloc (n);\n}\n\nvoid *\nmxArray::calloc (std::size_t n, std::size_t t)\n{\n  return mex_context ? mex_context->calloc_unmarked (n, t) : ::calloc (n, t);\n}\n\nvoid *\nmxArray::alloc (bool init, std::size_t n, std::size_t t)\n{\n  return init ? mxArray::calloc (n, t) : mxArray::malloc (n * t);\n}\n\nstatic inline void *\nmaybe_mark_foreign (void *ptr)\n{\n  if (mex_context)\n    mex_context->mark_foreign (ptr);\n\n  return ptr;\n}\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n\nstatic inline void\nmaybe_disown_ptr (void *ptr)\n{\n  if (mex_context)\n    {\n      mex_context->unmark (ptr);\n      mex_context->global_unmark (ptr);\n      mex_context->mark_foreign (ptr);\n    }\n}\n\n#endif\n\nstatic inline mxArray *\nmaybe_unmark_array (mxArray *ptr)\n{\n  if (mex_context)\n    mex_context->unmark_array (ptr);\n\n  return ptr;\n}\n\ntemplate <typename T>\nstatic inline T *\nmaybe_unmark (T *ptr)\n{\n  if (mex_context)\n    mex_context->unmark (ptr);\n\n  return ptr;\n}\n\nvoid\nmxArray_struct::set_field_by_number (mwIndex index, int key_num, mxArray *val)\n{\n  if (key_num >= 0 && key_num < m_nfields)\n    m_data[m_nfields * index + key_num] = maybe_unmark_array (val);\n}\n\nvoid\nmxArray_cell::set_cell (mwIndex idx, mxArray *val)\n{\n  if (idx >= 0 && idx < get_number_of_elements ())\n    m_data[idx] = maybe_unmark_array (val);\n}\n\n// ------------------------------------------------------------------\n\nextern \"C\" {\n  typedef void (*cmex_fptr) (int nlhs, mxArray *plhs[],\n                             int nrhs, const mxArray *prhs[]);\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\noctave_value_list\ncall_mex (octave_mex_function& mex_fcn, const octave_value_list& args,\n          int nargout_arg)\n{\n  octave_quit ();\n\n  // Use at least 1 for nargout since even for zero specified args,\n  // still want to be able to return an ans.\n\n  int nargout = nargout_arg;\n\n  int nargin = args.length ();\n  OCTAVE_LOCAL_BUFFER (mxArray *, argin, nargin);\n  for (int i = 0; i < nargin; i++)\n    argin[i] = nullptr;\n\n  int nout = (nargout == 0 ? 1 : nargout);\n  OCTAVE_LOCAL_BUFFER (mxArray *, argout, nout);\n  for (int i = 0; i < nout; i++)\n    argout[i] = nullptr;\n\n  // Save old mex pointer.\n  octave::unwind_protect_var<mex *> restore_var (mex_context);\n\n  mex context (mex_fcn);\n\n  for (int i = 0; i < nargin; i++)\n    argin[i] = context.make_value (args(i));\n\n  mex_context = &context;\n\n  cmex_fptr fcn = reinterpret_cast<cmex_fptr> (mex_fcn.mex_fcn_ptr ());\n\n  fcn (nargout, argout, nargin, const_cast<const mxArray **> (argin));\n\n  // Convert returned array entries back into octave values.\n\n  octave_value_list retval;\n\n  if (nargout == 0 && argout[0])\n    {\n      // We have something for ans.\n      nargout = 1;\n    }\n\n  retval.resize (nargout);\n\n  // If using std::pmr::memory_resource object to manage memory, pass\n  // default allocator here because we are done with these mxArray\n  // values and want Octave to delete them.\n\n  for (int i = 0; i < nargout; i++)\n    retval(i) = mxArray::as_octave_value (argout[i], false);\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/mxarray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nPart of this code was originally distributed as part of Octave Forge under\nthe following terms:\n\nAuthor: Paul Kienzle\nI grant this code to the public domain.\n2001-03-22\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\nOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n\n*/\n\n#if ! defined (octave_mxarray_h)\n#define octave_mxarray_h 1\n\n#include \"octave-config.h\"\n\n#include \"mxtypes.h\"\n\n#include <cstring>\n#include <set>\n\n#include \"error.h\"\n\n#include \"ov-mex-fcn.h\"\n\nclass octave_value;\nclass dim_vector;\n\n#define DO_MUTABLE_METHOD(RET_T, METHOD_CALL)   \\\n  RET_T retval = m_rep->METHOD_CALL;            \\\n                                                \\\n  if (m_rep->mutation_needed ())                \\\n    {                                           \\\n      maybe_mutate ();                          \\\n      retval = m_rep->METHOD_CALL;              \\\n    }                                           \\\n                                                \\\n  return retval\n\n#define DO_VOID_MUTABLE_METHOD(METHOD_CALL)     \\\n  m_rep->METHOD_CALL;                           \\\n                                                \\\n  if (m_rep->mutation_needed ())                \\\n    {                                           \\\n      maybe_mutate ();                          \\\n      m_rep->METHOD_CALL;                       \\\n    }\n\nclass OCTINTERP_API mxArray;\n\n// A class to provide the default implementation of some of the\n// virtual functions declared in the mxArray class.\n\nclass OCTINTERP_API mxArray_base\n{\nprotected:\n\n  OCTINTERP_API mxArray_base (bool interleaved);\n\npublic:\n\n  mxArray_base () = delete;\n\n  OCTAVE_DEFAULT_COPY_MOVE (mxArray_base)\n\n  virtual mxArray_base * dup () const = 0;\n\n  virtual mxArray * as_mxArray () const { return nullptr; }\n\n  virtual ~mxArray_base () = default;\n\n  virtual bool is_octave_value () const { return false; }\n\n  virtual int iscell () const = 0;\n\n  virtual int is_char () const = 0;\n\n  virtual int is_class (const char *name_arg) const\n  {\n    int retval = 0;\n\n    const char *cname = get_class_name ();\n\n    if (cname && name_arg)\n      retval = ! strcmp (cname, name_arg);\n\n    return retval;\n  }\n\n  virtual int is_complex () const = 0;\n\n  virtual int is_double () const = 0;\n\n  virtual int is_function_handle () const = 0;\n\n  virtual int is_int16 () const = 0;\n\n  virtual int is_int32 () const = 0;\n\n  virtual int is_int64 () const = 0;\n\n  virtual int is_int8 () const = 0;\n\n  virtual int is_logical () const = 0;\n\n  virtual int is_numeric () const = 0;\n\n  virtual int is_single () const = 0;\n\n  virtual int is_sparse () const = 0;\n\n  virtual int is_struct () const = 0;\n\n  virtual int is_uint16 () const = 0;\n\n  virtual int is_uint32 () const = 0;\n\n  virtual int is_uint64 () const = 0;\n\n  virtual int is_uint8 () const = 0;\n\n  virtual int is_logical_scalar () const\n  {\n    return is_logical () && get_number_of_elements () == 1;\n  }\n\n  virtual int is_logical_scalar_true () const = 0;\n\n  virtual mwSize get_m () const = 0;\n\n  virtual mwSize get_n () const = 0;\n\n  virtual mwSize * get_dimensions () const = 0;\n\n  virtual mwSize get_number_of_dimensions () const = 0;\n\n  virtual void set_m (mwSize m) = 0;\n\n  virtual void set_n (mwSize n) = 0;\n\n  virtual int set_dimensions (mwSize *dims_arg, mwSize ndims_arg) = 0;\n\n  virtual mwSize get_number_of_elements () const = 0;\n\n  virtual int isempty () const = 0;\n\n  virtual bool is_scalar () const = 0;\n\n  virtual mxClassID get_class_id () const = 0;\n\n  virtual const char * get_class_name () const = 0;\n\n  virtual void set_class_name (const char *name_arg) = 0;\n\n  // The following functions aren't pure virtual because they are only\n  // valid for one type.  Making them pure virtual would mean that they\n  // have to be implemented for all derived types, and all of those\n  // would need to throw errors instead of just doing it once here.\n\n  virtual mxArray *\n  get_property (mwIndex /*idx*/, const char * /*pname*/) const\n  {\n    return nullptr;\n  }\n\n  virtual void set_property (mwIndex /*idx*/, const char * /*pname*/,\n                             const mxArray * /*pval*/)\n  {\n    err_invalid_type (\"set_property\");\n  }\n\n  virtual mxArray * get_cell (mwIndex /*idx*/) const\n  {\n    err_invalid_type (\"get_cell\");\n  }\n\n  virtual void set_cell (mwIndex idx, mxArray *val) = 0;\n\n  virtual double get_scalar () const = 0;\n\n  virtual void * get_data () const = 0;\n\n  virtual mxDouble * get_doubles () const = 0;\n  virtual mxSingle * get_singles () const = 0;\n  virtual mxInt8 * get_int8s () const = 0;\n  virtual mxInt16 * get_int16s () const = 0;\n  virtual mxInt32 * get_int32s () const = 0;\n  virtual mxInt64 * get_int64s () const = 0;\n  virtual mxUint8 * get_uint8s () const = 0;\n  virtual mxUint16 * get_uint16s () const = 0;\n  virtual mxUint32 * get_uint32s () const = 0;\n  virtual mxUint64 * get_uint64s () const = 0;\n\n  virtual mxComplexDouble * get_complex_doubles () const = 0;\n  virtual mxComplexSingle * get_complex_singles () const = 0;\n\n  virtual void * get_imag_data () const = 0;\n\n  virtual void set_data (void *pr) = 0;\n\n  virtual int set_doubles (mxDouble *data) = 0;\n  virtual int set_singles (mxSingle *data) = 0;\n  virtual int set_int8s (mxInt8 *data) = 0;\n  virtual int set_int16s (mxInt16 *data) = 0;\n  virtual int set_int32s (mxInt32 *data) = 0;\n  virtual int set_int64s (mxInt64 *data) = 0;\n  virtual int set_uint8s (mxUint8 *data) = 0;\n  virtual int set_uint16s (mxUint16 *data) = 0;\n  virtual int set_uint32s (mxUint32 *data) = 0;\n  virtual int set_uint64s (mxUint64 *data) = 0;\n\n  virtual int set_complex_doubles (mxComplexDouble *data) = 0;\n  virtual int set_complex_singles (mxComplexSingle *data) = 0;\n\n  virtual void set_imag_data (void *pi) = 0;\n\n  virtual mwIndex * get_ir () const = 0;\n\n  virtual mwIndex * get_jc () const = 0;\n\n  virtual mwSize get_nzmax () const = 0;\n\n  virtual void set_ir (mwIndex *ir) = 0;\n\n  virtual void set_jc (mwIndex *jc) = 0;\n\n  virtual void set_nzmax (mwSize nzmax) = 0;\n\n  virtual int add_field (const char *key) = 0;\n\n  virtual void remove_field (int key_num) = 0;\n\n  virtual mxArray * get_field_by_number (mwIndex index, int key_num) const = 0;\n\n  virtual void\n  set_field_by_number (mwIndex index, int key_num, mxArray *val) = 0;\n\n  virtual int get_number_of_fields () const = 0;\n\n  virtual const char * get_field_name_by_number (int key_num) const = 0;\n\n  virtual int get_field_number (const char *key) const = 0;\n\n  virtual int get_string (char *buf, mwSize buflen) const = 0;\n\n  virtual char * array_to_string () const = 0;\n\n  virtual mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const = 0;\n\n  virtual std::size_t get_element_size () const = 0;\n\n  virtual bool mutation_needed () const { return false; }\n\n  virtual mxArray * mutate () const { return nullptr; }\n\n  virtual octave_value as_octave_value () const = 0;\n\nprotected:\n\n  std::size_t get_numeric_element_size (std::size_t size) const\n  {\n    return (m_interleaved\n            ? is_complex () ? 2 * size : size\n            : size);\n  }\n\n  OCTAVE_NORETURN void err_invalid_type (const char *op) const\n  {\n    error (\"%s: invalid type for mxArray::%s\", get_class_name (), op);\n  }\n\n  //--------\n\n  // If TRUE, we are using interleaved storage for complex numeric arrays.\n  bool m_interleaved;\n\n};\n\n// The main interface class.  The representation can be based on an\n// octave_value object or a separate object that tries to reproduce\n// the semantics of mxArray objects in Matlab more directly.\n\nclass mxArray\n{\npublic:\n\n  OCTINTERP_API mxArray (bool interleaved, const octave_value& ov);\n\n  OCTINTERP_API mxArray (bool interleaved, mxClassID id, mwSize ndims,\n                         const mwSize *dims, mxComplexity flag = mxREAL,\n                         bool init = true);\n\n  OCTINTERP_API mxArray (bool interleaved, mxClassID id, const dim_vector& dv,\n                         mxComplexity flag = mxREAL);\n\n  OCTINTERP_API mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n,\n                         mxComplexity flag = mxREAL, bool init = true);\n\n  OCTINTERP_API mxArray (bool interleaved, mxClassID id, double val);\n\n  OCTINTERP_API mxArray (bool interleaved, mxClassID id, mxLogical val);\n\n  OCTINTERP_API mxArray (bool interleaved, const char *str);\n\n  OCTINTERP_API mxArray (bool interleaved, mwSize m, const char **str);\n\n  OCTINTERP_API mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n,\n                         mwSize nzmax, mxComplexity flag = mxREAL);\n\n  OCTINTERP_API mxArray (bool interleaved, mwSize ndims, const mwSize *dims,\n                         int num_keys, const char **keys);\n\n  OCTINTERP_API mxArray (bool interleaved, const dim_vector& dv, int num_keys,\n                         const char **keys);\n\n  OCTINTERP_API mxArray (bool interleaved, mwSize m, mwSize n, int num_keys,\n                         const char **keys);\n\n  OCTINTERP_API mxArray (bool interleaved, mwSize ndims, const mwSize *dims);\n\n  OCTINTERP_API mxArray (bool interleaved, const dim_vector& dv);\n\n  OCTINTERP_API mxArray (bool interleaved, mwSize m, mwSize n);\n\n  mxArray * dup () const\n  {\n    mxArray *retval = m_rep->as_mxArray ();\n\n    if (retval)\n      retval->set_name (m_name);\n    else\n      {\n        mxArray_base *new_rep = m_rep->dup ();\n\n        retval = new mxArray (new_rep, m_name);\n      }\n\n    return retval;\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (mxArray)\n\n  OCTINTERP_API ~mxArray ();\n\n  bool is_octave_value () const { return m_rep->is_octave_value (); }\n\n  int iscell () const { return m_rep->iscell (); }\n\n  int is_char () const { return m_rep->is_char (); }\n\n  int is_class (const char *name_arg) const { return m_rep->is_class (name_arg); }\n\n  int is_complex () const { return m_rep->is_complex (); }\n\n  int is_double () const { return m_rep->is_double (); }\n\n  int is_function_handle () const { return m_rep->is_function_handle (); }\n\n  int is_int16 () const { return m_rep->is_int16 (); }\n\n  int is_int32 () const { return m_rep->is_int32 (); }\n\n  int is_int64 () const { return m_rep->is_int64 (); }\n\n  int is_int8 () const { return m_rep->is_int8 (); }\n\n  int is_logical () const { return m_rep->is_logical (); }\n\n  int is_numeric () const { return m_rep->is_numeric (); }\n\n  int is_single () const { return m_rep->is_single (); }\n\n  int is_sparse () const { return m_rep->is_sparse (); }\n\n  int is_struct () const { return m_rep->is_struct (); }\n\n  int is_uint16 () const { return m_rep->is_uint16 (); }\n\n  int is_uint32 () const { return m_rep->is_uint32 (); }\n\n  int is_uint64 () const { return m_rep->is_uint64 (); }\n\n  int is_uint8 () const { return m_rep->is_uint8 (); }\n\n  int is_logical_scalar () const { return m_rep->is_logical_scalar (); }\n\n  int is_logical_scalar_true () const\n  { return m_rep->is_logical_scalar_true (); }\n\n  mwSize get_m () const { return m_rep->get_m (); }\n\n  mwSize get_n () const { return m_rep->get_n (); }\n\n  mwSize * get_dimensions () const { return m_rep->get_dimensions (); }\n\n  mwSize get_number_of_dimensions () const\n  { return m_rep->get_number_of_dimensions (); }\n\n  void set_m (mwSize m) { DO_VOID_MUTABLE_METHOD (set_m (m)); }\n\n  void set_n (mwSize n) { DO_VOID_MUTABLE_METHOD (set_n (n)); }\n\n  int set_dimensions (mwSize *dims_arg, mwSize ndims_arg)\n  { DO_MUTABLE_METHOD (int, set_dimensions (dims_arg, ndims_arg)); }\n\n  mwSize get_number_of_elements () const\n  { return m_rep->get_number_of_elements (); }\n\n  int isempty () const { return get_number_of_elements () == 0; }\n\n  bool is_scalar () const { return m_rep->is_scalar (); }\n\n  const char * get_name () const { return m_name; }\n\n  OCTINTERP_API void set_name (const char *name);\n\n  mxClassID get_class_id () const { return m_rep->get_class_id (); }\n\n  const char * get_class_name () const { return m_rep->get_class_name (); }\n\n  mxArray * get_property (mwIndex idx, const char *pname) const\n  { return m_rep->get_property (idx, pname); }\n\n  void set_property (mwIndex idx, const char *pname, const mxArray *pval)\n  { m_rep->set_property (idx, pname, pval); }\n\n  void set_class_name (const char *name_arg)\n  { DO_VOID_MUTABLE_METHOD (set_class_name (name_arg)); }\n\n  mxArray * get_cell (mwIndex idx) const\n  { DO_MUTABLE_METHOD (mxArray *, get_cell (idx)); }\n\n  void set_cell (mwIndex idx, mxArray *val)\n  { DO_VOID_MUTABLE_METHOD (set_cell (idx, val)); }\n\n  double get_scalar () const { return m_rep->get_scalar (); }\n\n  void * get_data () const { DO_MUTABLE_METHOD (void *, get_data ()); }\n\n  mxDouble * get_doubles () const\n  { DO_MUTABLE_METHOD (mxDouble *, get_doubles ()); }\n\n  mxSingle * get_singles () const\n  { DO_MUTABLE_METHOD (mxSingle *, get_singles ()); }\n\n  mxInt8 * get_int8s () const\n  { DO_MUTABLE_METHOD (mxInt8 *, get_int8s ()); }\n\n  mxInt16 * get_int16s () const\n  { DO_MUTABLE_METHOD (mxInt16 *, get_int16s ()); }\n\n  mxInt32 * get_int32s () const\n  { DO_MUTABLE_METHOD (mxInt32 *, get_int32s ()); }\n\n  mxInt64 * get_int64s () const\n  { DO_MUTABLE_METHOD (mxInt64 *, get_int64s ()); }\n\n  mxUint8 * get_uint8s () const\n  { DO_MUTABLE_METHOD (mxUint8 *, get_uint8s ()); }\n\n  mxUint16 * get_uint16s () const\n  { DO_MUTABLE_METHOD (mxUint16 *, get_uint16s ()); }\n\n  mxUint32 * get_uint32s () const\n  { DO_MUTABLE_METHOD (mxUint32 *, get_uint32s ()); }\n\n  mxUint64 * get_uint64s () const\n  { DO_MUTABLE_METHOD (mxUint64 *, get_uint64s ()); }\n\n  mxComplexDouble * get_complex_doubles () const\n  { DO_MUTABLE_METHOD (mxComplexDouble *, get_complex_doubles ()); }\n\n  mxComplexSingle * get_complex_singles () const\n  { DO_MUTABLE_METHOD (mxComplexSingle *, get_complex_singles ()); }\n\n  void * get_imag_data () const\n  { DO_MUTABLE_METHOD (void *, get_imag_data ()); }\n\n  void set_data (void *pr) { DO_VOID_MUTABLE_METHOD (set_data (pr)); }\n\n  int set_doubles (mxDouble *data)\n  { DO_MUTABLE_METHOD (int, set_doubles (data)); }\n\n  int set_singles (mxSingle *data)\n  { DO_MUTABLE_METHOD (int, set_singles (data)); }\n\n  int set_int8s (mxInt8 *data)\n  { DO_MUTABLE_METHOD (int, set_int8s (data)); }\n\n  int set_int16s (mxInt16 *data)\n  { DO_MUTABLE_METHOD (int, set_int16s (data)); }\n\n  int set_int32s (mxInt32 *data)\n  { DO_MUTABLE_METHOD (int, set_int32s (data)); }\n\n  int set_int64s (mxInt64 *data)\n  { DO_MUTABLE_METHOD (int, set_int64s (data)); }\n\n  int set_uint8s (mxUint8 *data)\n  { DO_MUTABLE_METHOD (int, set_uint8s (data)); }\n\n  int set_uint16s (mxUint16 *data)\n  { DO_MUTABLE_METHOD (int, set_uint16s (data)); }\n\n  int set_uint32s (mxUint32 *data)\n  { DO_MUTABLE_METHOD (int, set_uint32s (data)); }\n\n  int set_uint64s (mxUint64 *data)\n  { DO_MUTABLE_METHOD (int, set_uint64s (data)); }\n\n  int set_complex_doubles (mxComplexDouble *data)\n  { DO_MUTABLE_METHOD (int, set_complex_doubles (data)); }\n\n  int set_complex_singles (mxComplexSingle *data)\n  { DO_MUTABLE_METHOD (int, set_complex_singles (data)); }\n\n  void set_imag_data (void *pi) { DO_VOID_MUTABLE_METHOD (set_imag_data (pi)); }\n\n  mwIndex * get_ir () const { DO_MUTABLE_METHOD (mwIndex *, get_ir ()); }\n\n  mwIndex * get_jc () const { DO_MUTABLE_METHOD (mwIndex *, get_jc ()); }\n\n  mwSize get_nzmax () const { return m_rep->get_nzmax (); }\n\n  void set_ir (mwIndex *ir) { DO_VOID_MUTABLE_METHOD (set_ir (ir)); }\n\n  void set_jc (mwIndex *jc) { DO_VOID_MUTABLE_METHOD (set_jc (jc)); }\n\n  void set_nzmax (mwSize nzmax) { DO_VOID_MUTABLE_METHOD (set_nzmax (nzmax)); }\n\n  int add_field (const char *key) { DO_MUTABLE_METHOD (int, add_field (key)); }\n\n  void remove_field (int key_num)\n  { DO_VOID_MUTABLE_METHOD (remove_field (key_num)); }\n\n  mxArray * get_field_by_number (mwIndex index, int key_num) const\n  { DO_MUTABLE_METHOD (mxArray *, get_field_by_number (index, key_num)); }\n\n  void set_field_by_number (mwIndex index, int key_num, mxArray *val)\n  { DO_VOID_MUTABLE_METHOD (set_field_by_number (index, key_num, val)); }\n\n  int get_number_of_fields () const\n  { return m_rep->get_number_of_fields (); }\n\n  const char * get_field_name_by_number (int key_num) const\n  { DO_MUTABLE_METHOD (const char *, get_field_name_by_number (key_num)); }\n\n  int get_field_number (const char *key) const\n  { DO_MUTABLE_METHOD (int, get_field_number (key)); }\n\n  int get_string (char *buf, mwSize buflen) const\n  { return m_rep->get_string (buf, buflen); }\n\n  char * array_to_string () const { return m_rep->array_to_string (); }\n\n  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const\n  { return m_rep->calc_single_subscript (nsubs, subs); }\n\n  std::size_t get_element_size () const\n  { return m_rep->get_element_size (); }\n\n  bool mutation_needed () const { return m_rep->mutation_needed (); }\n\n  mxArray * mutate () const { return m_rep->mutate (); }\n\n  static OCTINTERP_API void * malloc (std::size_t n);\n\n  static OCTINTERP_API void * calloc (std::size_t n, std::size_t t);\n\n  static OCTINTERP_API void * alloc (bool init, std::size_t n, std::size_t t);\n\n  static char * strsave (const char *str)\n  {\n    char *retval = nullptr;\n\n    if (str)\n      {\n        mwSize sz = sizeof (mxChar) * (strlen (str) + 1);\n\n        retval = static_cast<char *> (mxArray::malloc (sz));\n\n        if (retval)\n          strcpy (retval, str);\n      }\n\n    return retval;\n  }\n\n  static OCTINTERP_API octave_value\n  as_octave_value (const mxArray *ptr, bool null_is_empty = true);\n\n  OCTINTERP_API octave_value as_octave_value () const;\n\nprivate:\n\n  mxArray (mxArray_base *r, const char *n)\n    : m_rep (r), m_name (mxArray::strsave (n)) { }\n\n  static OCTINTERP_API mxArray_base *\n  create_rep (bool interleaved, const octave_value& ov);\n\n  static OCTINTERP_API mxArray_base *\n  create_rep (bool interleaved, mxClassID id, mwSize ndims,\n              const mwSize *dims, mxComplexity flag, bool init);\n\n  static OCTINTERP_API mxArray_base *\n  create_rep (bool interleaved, mxClassID id, const dim_vector& dv,\n              mxComplexity flag);\n\n  static OCTINTERP_API mxArray_base *\n  create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,\n              mxComplexity flag, bool init);\n\n  static OCTINTERP_API mxArray_base *\n  create_rep (bool interleaved, mxClassID id, double val);\n\n  static OCTINTERP_API mxArray_base *\n  create_rep (bool interleaved, mxClassID id, mxLogical val);\n\n  static OCTINTERP_API mxArray_base *\n  create_rep (bool interleaved, const char *str);\n\n  static OCTINTERP_API mxArray_base *\n  create_rep (bool interleaved, mwSize m, const char **str);\n\n  static OCTINTERP_API mxArray_base *\n  create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,\n              mwSize nzmax, mxComplexity flag);\n\n  OCTINTERP_API void maybe_mutate () const;\n\n  //--------\n\n  mutable mxArray_base *m_rep;\n\n  char *m_name;\n\n};\n\n// A class to manage calls to MEX functions.  Mostly deals with memory\n// management.\n\nclass OCTINTERP_API mex\n{\npublic:\n\n  mex (octave_mex_function& f)\n    : m_curr_mex_fcn (f), m_memlist (), m_arraylist (), m_fname (nullptr) { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (mex)\n\n  ~mex ();\n\n  const char *function_name () const;\n\n  // Allocate memory.\n  void *malloc_unmarked (std::size_t n);\n\n  // Allocate memory to be freed on exit.\n  void *malloc (std::size_t n)\n  {\n    void *ptr = malloc_unmarked (n);\n\n    mark (ptr);\n\n    return ptr;\n  }\n\n  // Allocate memory and initialize to 0.\n  void *calloc_unmarked (std::size_t n, std::size_t t)\n  {\n    void *ptr = malloc_unmarked (n*t);\n\n    memset (ptr, 0, n*t);\n\n    return ptr;\n  }\n\n  // Allocate memory to be freed on exit and initialize to 0.\n  void *calloc (std::size_t n, std::size_t t)\n  {\n    void *ptr = calloc_unmarked (n, t);\n\n    mark (ptr);\n\n    return ptr;\n  }\n\n  // Reallocate a pointer obtained from malloc or calloc.\n  // If the pointer is NULL, allocate using malloc.\n  // We don't need an \"unmarked\" version of this.\n  void *realloc (void *ptr, std::size_t n);\n\n  // Free a pointer obtained from malloc or calloc.\n  void free (void *ptr);\n\n  // Mark a pointer to be freed on exit.\n  void mark (void *ptr)\n  {\n#if defined (OCTAVE_MXARRAY_DEBUG)\n    if (m_memlist.find (ptr) != m_memlist.end ())\n      warning (\"%s: double registration ignored\", function_name ());\n#endif\n\n    m_memlist.insert (ptr);\n  }\n\n  // Unmark a pointer to be freed on exit, either because it was\n  // made persistent, or because it was already freed.\n  void unmark (void *ptr)\n  {\n    auto p = m_memlist.find (ptr);\n\n    if (p != m_memlist.end ())\n      m_memlist.erase (p);\n#if defined (OCTAVE_MXARRAY_DEBUG)\n    else\n      warning (\"%s: value not marked\", function_name ());\n#endif\n  }\n\n  mxArray * mark_array (mxArray *ptr)\n  {\n    m_arraylist.insert (ptr);\n    return ptr;\n  }\n\n  void unmark_array (mxArray *ptr)\n  {\n    auto p = m_arraylist.find (ptr);\n\n    if (p != m_arraylist.end ())\n      m_arraylist.erase (p);\n  }\n\n  // Mark a pointer as one we allocated.\n  void mark_foreign (void *ptr)\n  {\n#if defined (OCTAVE_MXARRAY_DEBUG)\n    if (m_foreign_memlist.find (ptr) != m_foreign_memlist.end ())\n      warning (\"%s: double registration ignored\", function_name ());\n#endif\n\n    m_foreign_memlist.insert (ptr);\n  }\n\n  // Unmark a pointer as one we allocated.\n  void unmark_foreign (void *ptr)\n  {\n    auto p = m_foreign_memlist.find (ptr);\n\n    if (p != m_foreign_memlist.end ())\n      m_foreign_memlist.erase (p);\n#if defined (OCTAVE_MXARRAY_DEBUG)\n    else\n      warning (\"%s: value not marked\", function_name ());\n#endif\n  }\n\n  // Make a new array value and initialize from an octave value; it will be\n  // freed on exit unless marked as persistent.\n  mxArray * make_value (const octave_value& ov)\n  {\n    bool interleaved = m_curr_mex_fcn.use_interleaved_complex ();\n\n    return mark_array (new mxArray (interleaved, ov));\n  }\n\n  // Free an array and its contents.\n  bool free_value (mxArray *ptr)\n  {\n    bool inlist = false;\n\n    auto p = m_arraylist.find (ptr);\n\n    if (p != m_arraylist.end ())\n      {\n        inlist = true;\n        m_arraylist.erase (p);\n        delete ptr;\n      }\n#if defined (OCTAVE_MXARRAY_DEBUG)\n    else\n      warning (\"mex::free_value: skipping memory not allocated by mex::make_value\");\n#endif\n\n    return inlist;\n  }\n\n  octave_mex_function& current_mex_function () const\n  {\n    return m_curr_mex_fcn;\n  }\n\n  // 1 if error should be returned to MEX file, 0 if abort.\n  int trap_feval_error = 0;\n\n  // Mark a pointer as one we allocated.\n  void global_mark (void *ptr)\n  {\n#if defined (OCTAVE_MXARRAY_DEBUG)\n    if (s_global_memlist.find (ptr) != s_global_memlist.end ())\n      warning (\"%s: double registration ignored\", function_name ());\n#endif\n\n    s_global_memlist.insert (ptr);\n  }\n\n  // Unmark a pointer as one we allocated.\n  void global_unmark (void *ptr)\n  {\n    auto p = s_global_memlist.find (ptr);\n\n    if (p != s_global_memlist.end ())\n      s_global_memlist.erase (p);\n#if defined (OCTAVE_MXARRAY_DEBUG)\n    else\n      warning (\"%s: value not marked\", function_name ());\n#endif\n  }\n\nprivate:\n\n  // Pointer to the mex function that corresponds to this mex context.\n  octave_mex_function& m_curr_mex_fcn;\n\n  // List of memory resources that need to be freed upon exit.\n  std::set<void *> m_memlist;\n\n  // List of mxArray objects that need to be freed upon exit.\n  std::set<mxArray *> m_arraylist;\n\n  // List of memory resources we know about, but that were allocated\n  // elsewhere.\n  std::set<void *> m_foreign_memlist;\n\n  // The name of the currently executing function.\n  mutable char *m_fname;\n\n  // List of memory resources we allocated.\n  static std::set<void *> s_global_memlist;\n\n};\n\n#undef DO_MUTABLE_METHOD\n#undef DO_VOID_MUTABLE_METHOD\n\nOCTINTERP_API octave_value_list\nmx_to_ov_args (int nargin, mxArray *argin[]);\n\nOCTINTERP_API void\nmexErrMsgTxt_impl (const char *who, const char *s);\n\nOCTINTERP_API int\nmexPutVariable_impl (const char *space, const char *name, const mxArray *ptr);\n\nOCTINTERP_API int\nmexSet_impl (double handle, const char *property, mxArray *val);\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/mxtypes.in.h",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nPart of this code was originally distributed as part of Octave Forge under\nthe following terms:\n\nAuthor: Paul Kienzle\nI grant this code to the public domain.\n2001-03-22\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\nOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n\n*/\n\n#if ! defined (octave_mxtypes_h)\n#define octave_mxtypes_h 1\n\n#include \"octave-config.h\"\n\ntypedef enum\n  {\n  mxUNKNOWN_CLASS = 0,\n  mxCELL_CLASS,\n  mxSTRUCT_CLASS,\n  mxLOGICAL_CLASS,\n  mxCHAR_CLASS,\n  mxVOID_CLASS,\n  mxDOUBLE_CLASS,\n  mxSINGLE_CLASS,\n  mxINT8_CLASS,\n  mxUINT8_CLASS,\n  mxINT16_CLASS,\n  mxUINT16_CLASS,\n  mxINT32_CLASS,\n  mxUINT32_CLASS,\n  mxINT64_CLASS,\n  mxUINT64_CLASS,\n  mxFUNCTION_CLASS\n}\nmxClassID;\n\ntypedef enum\n  {\n  mxREAL = 0,\n  mxCOMPLEX = 1\n}\nmxComplexity;\n\n/* Matlab uses a wide char (uint16) internally, but Octave uses plain char. */\n/* typedef Uint16 mxChar; */\ntypedef char mxChar;\n\ntypedef unsigned char mxLogical;\n\ntypedef double mxDouble;\ntypedef float mxSingle;\n\ntypedef int8_t mxInt8;\ntypedef int16_t mxInt16;\ntypedef int32_t mxInt32;\ntypedef int64_t mxInt64;\n\ntypedef uint8_t mxUint8;\ntypedef uint16_t mxUint16;\ntypedef uint32_t mxUint32;\ntypedef uint64_t mxUint64;\n\ntypedef struct { mxDouble real; mxDouble imag; } mxComplexDouble;\ntypedef struct { mxSingle real; mxSingle imag; } mxComplexSingle;\n\n/* We don't have these yet but we can define the types. */\ntypedef struct { mxInt8 real; mxInt8 imag; } mxComplexInt8;\ntypedef struct { mxInt16 real; mxInt16 imag; } mxComplexInt16;\ntypedef struct { mxInt32 real; mxInt32 imag; } mxComplexInt32;\ntypedef struct { mxInt64 real; mxInt64 imag; } mxComplexInt64;\n\ntypedef struct { mxUint8 real; mxUint8 imag; } mxComplexUint8;\ntypedef struct { mxUint16 real; mxUint16 imag; } mxComplexUint16;\ntypedef struct { mxUint32 real; mxUint32 imag; } mxComplexUint32;\ntypedef struct { mxUint64 real; mxUint64 imag; } mxComplexUint64;\n\n/*\n * FIXME: Mathworks says mwSize, mwIndex should be int generally.\n * But on 64-bit systems, or when mex -largeArrayDims is used, it is size_t.\n * mwSignedIndex is supposed to be ptrdiff_t.  All of this is confusing.\n * Its better to conform to the same indexing as the rest of Octave.\n */\ntypedef %OCTAVE_IDX_TYPE% mwSize;\ntypedef %OCTAVE_IDX_TYPE% mwIndex;\ntypedef %OCTAVE_IDX_TYPE% mwSignedIndex;\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__betainc__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nDEFUN (__betainc__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} __betainc__ (@var{x}, @var{a}, @var{b})\nContinued fraction for incomplete beta function.\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  bool is_single = (args(0).is_single_type () || args(1).is_single_type ()\n                    || args(2).is_single_type ());\n\n  // Total number of scenarios: get maximum of length of all vectors\n  int numel_x = args(0).numel ();\n  int numel_a = args(1).numel ();\n  int numel_b = args(2).numel ();\n  int len = std::max (std::max (numel_x, numel_a), numel_b);\n\n  octave_value_list retval;\n  // Initialize output dimension vector\n  dim_vector output_dv (len, 1);\n\n  // Lentz's algorithm in two cases: single and double precision\n  if (is_single)\n    {\n      // Initialize output and inputs\n      FloatColumnVector output (output_dv);\n      FloatNDArray x, a, b;\n\n      if (numel_x == 1)\n        x = FloatNDArray (output_dv, args(0).float_scalar_value ());\n      else\n        x = args(0).float_array_value ();\n\n\n      if (numel_a == 1)\n        a = FloatNDArray (output_dv, args(1).float_scalar_value ());\n      else\n        a = args(1).float_array_value ();\n\n      if (numel_b == 1)\n        b = FloatNDArray (output_dv, args(2).float_scalar_value ());\n      else\n        b = args(2).float_array_value ();\n\n      // Initialize variables used in algorithm\n      static const float tiny = math::exp2 (-50.0f);\n      static constexpr float eps = std::numeric_limits<float>::epsilon ();\n      float xj, x2, y, Cj, Dj, aj, bj, Deltaj, alpha_j, beta_j;\n      int j, maxit;\n      maxit = 200;\n\n      // Loop over all elements\n      for (octave_idx_type i = 0; i < len; ++i)\n        {\n          // Catch Ctrl+C\n          OCTAVE_QUIT;\n\n          // Variable initialization for the current element\n          xj = x(i);\n          y = tiny;\n          Cj = y;\n          Dj = 0;\n          aj = a(i);\n          bj = b(i);\n          Deltaj = 0;\n          alpha_j = 1;\n          beta_j = aj - (aj * (aj + bj)) / (aj + 1) * xj;\n          x2 = xj * xj;\n          j = 1;\n\n          // Lentz's algorithm\n          while ((std::abs ((Deltaj - 1)) > eps) && (j < maxit))\n            {\n              Dj = beta_j + alpha_j * Dj;\n              if (Dj == 0)\n                Dj = tiny;\n              Cj = beta_j + alpha_j / Cj;\n              if (Cj == 0)\n                Cj = tiny;\n              Dj = 1 / Dj;\n              Deltaj = Cj * Dj;\n              y *= Deltaj;\n              alpha_j = ((aj + j - 1) * (aj + bj + j -1) * (bj - j) * j)\n                        / ((aj + 2 * j - 1) * (aj + 2 * j - 1)) * x2;\n              beta_j = aj + 2 * j + ((j * (bj - j)) / (aj + 2 * j - 1)\n                                     - ((aj + j) * (aj + bj + j)) / (aj + 2 * j + 1)) * xj;\n              j++;\n            }\n\n          output(i) = y;\n        }\n\n      retval(0) = output;\n    }\n  else\n    {\n      // Initialize output and inputs\n      ColumnVector output (output_dv);\n      NDArray x, a, b;\n\n      if (numel_x == 1)\n        x = NDArray (output_dv, args(0).scalar_value ());\n      else\n        x = args(0).array_value ();\n\n      if (numel_a == 1)\n        a = NDArray (output_dv, args(1).scalar_value ());\n      else\n        a = args(1).array_value ();\n\n      if (numel_b == 1)\n        b = NDArray (output_dv, args(2).scalar_value ());\n      else\n        b = args(2).array_value ();\n\n      // Initialize variables used in algorithm\n      static const double tiny = math::exp2 (-100.0);\n      static constexpr double eps = std::numeric_limits<double>::epsilon ();\n      double xj, x2, y, Cj, Dj, aj, bj, Deltaj, alpha_j, beta_j;\n      int j, maxit;\n      maxit = 200;\n\n      // Loop over all elements\n      for (octave_idx_type i = 0; i < len; ++i)\n        {\n          // Catch Ctrl+C\n          OCTAVE_QUIT;\n\n          // Variable initialization for the current element\n          xj = x(i);\n          y = tiny;\n          Cj = y;\n          Dj = 0;\n          aj = a(i);\n          bj = b(i);\n          Deltaj = 0;\n          alpha_j = 1;\n          beta_j = aj - (aj * (aj + bj)) / (aj + 1) * xj;\n          x2 = xj * xj;\n          j = 1;\n\n          // Lentz's algorithm\n          while ((std::abs ((Deltaj - 1)) > eps) && (j < maxit))\n            {\n              Dj = beta_j + alpha_j * Dj;\n              if (Dj == 0)\n                Dj = tiny;\n              Cj = beta_j + alpha_j / Cj;\n              if (Cj == 0)\n                Cj = tiny;\n              Dj = 1 / Dj;\n              Deltaj = Cj * Dj;\n              y *= Deltaj;\n              alpha_j = ((aj + j - 1) * (aj + bj + j - 1) * (bj - j) * j)\n                        / ((aj + 2 * j - 1) * (aj + 2 * j - 1)) * x2;\n              beta_j = aj + 2 * j + ((j * (bj - j)) / (aj + 2 * j - 1)\n                                     - ((aj + j) * (aj + bj + j)) / (aj + 2 * j + 1)) * xj;\n              j++;\n            }\n\n          output(i) = y;\n        }\n\n      retval(0) = output;\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__contourc__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Contour lines for function evaluated on a grid.\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// Adapted to an oct file from the stand alone contourl by Victro Munoz\n// Copyright (C) 2004 Victor Munoz\n//\n// Based on contour plot routine (plcont.c) in PLPlot package\n// http://plplot.org/\n//\n// Copyright (C) 1995, 2000, 2001 Maurice LeBrun\n// Copyright (C) 2000, 2002 Joao Cardoso\n// Copyright (C) 2000, 2001, 2002, 2004 Alan W. Irwin\n// Copyright (C) 2004 Andrew Ross\n//\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <limits>\n\n#include \"defun.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// FIXME: this looks like trouble...\nstatic Matrix this_contour;\nstatic Matrix contourc;\nstatic int elem;\n\n// This is the quanta in which we increase this_contour.\n#define CONTOUR_QUANT 50\n\n// Add a coordinate point (x,y) to this_contour.\nstatic void\nadd_point (double x, double y)\n{\n  if (elem % CONTOUR_QUANT == 0)\n    this_contour = this_contour.append (Matrix (2, CONTOUR_QUANT, 0));\n\n  this_contour(0, elem) = x;\n  this_contour(1, elem) = y;\n  elem++;\n}\n\n// Add contents of current contour to contourc.\n// this_contour.cols () - 1;\nstatic void\nend_contour ()\n{\n  if (elem > 2)\n    {\n      this_contour(1, 0) = elem - 1;\n      contourc = contourc.append (this_contour.extract_n (0, 0, 2, elem));\n    }\n\n  this_contour = Matrix ();\n  elem = 0;\n}\n\n// Start a new contour, and add contents of current one to contourc.\n\nstatic void\nstart_contour (double lvl, double x, double y)\n{\n  end_contour ();\n  this_contour.resize (2, 0);\n  add_point (lvl, 0);\n  add_point (x, y);\n}\n\nstatic void\ndrawcn (const RowVector& X, const RowVector& Y, const Matrix& Z,\n        double lvl, int r, int c, double ct_x, double ct_y,\n        unsigned int start_edge, bool first, charMatrix& mark)\n{\n  double px[4], py[4], pz[4], tmp;\n  unsigned int stop_edge, pt[2];\n\n  // Continue while next facet is not done yet.\n  while (r >= 0 && c >= 0 && r < mark.rows () && c < mark.cols ()\n         && mark(r, c) > 0)\n    {\n\n      //get x, y, and z - lvl for current facet\n      px[0] = px[3] = X(c);\n      px[1] = px[2] = X(c+1);\n\n      py[0] = py[1] = Y(r);\n      py[2] = py[3] = Y(r+1);\n\n      pz[3] = Z(r+1, c) - lvl;\n      pz[2] = Z(r+1, c + 1) - lvl;\n      pz[1] = Z(r, c+1) - lvl;\n      pz[0] = Z(r, c) - lvl;\n\n      // Facet edge and point naming assignment.\n      //\n      //  0-----1   .-0-.\n      //  |     |   |   |\n      //  |     |   3   1\n      //  |     |   |   |\n      //  3-----2   .-2-.\n\n      // Get mark value of current facet.\n      char id = static_cast<char> (mark(r, c));\n\n      // Check startedge s.\n      if (start_edge == 255)\n        {\n          // Find start edge.\n          for (unsigned int k = 0; k < 4; k++)\n            if (static_cast<char> (1 << k) & id)\n              start_edge = k;\n        }\n\n      if (start_edge == 255)\n        break;\n\n      // Decrease mark value of current facet for start edge.\n      mark(r, c) -= static_cast<char> (1 << start_edge);\n\n      // Next point (clockwise).\n      pt[0] = start_edge;\n      pt[1] = (pt[0] + 1) % 4;\n\n      // Calculate contour segment start if first of contour.\n      if (first)\n        {\n          tmp = fabs (pz[pt[1]]) / fabs (pz[pt[0]]);\n\n          if (math::isnan (tmp))\n            ct_x = ct_y = 0.5;\n          else\n            {\n              ct_x = px[pt[0]] + (px[pt[1]] - px[pt[0]])/(1 + tmp);\n              ct_y = py[pt[0]] + (py[pt[1]] - py[pt[0]])/(1 + tmp);\n            }\n\n          start_contour (lvl, ct_x, ct_y);\n          first = false;\n        }\n\n      // Find stop edge.\n      // FIXME: perhaps this should use a while loop?\n      for (unsigned int k = 1; k <= 4; k++)\n        {\n          if (start_edge == 0 || start_edge == 2)\n            stop_edge = (start_edge + k) % 4;\n          else\n            stop_edge = (start_edge - k) % 4;\n\n          if (static_cast<char> (1 << stop_edge) & id)\n            break;\n        }\n\n      pt[0] = stop_edge;\n      pt[1] = (pt[0] + 1) % 4;\n      tmp = fabs (pz[pt[1]]) / fabs (pz[pt[0]]);\n\n      if (math::isnan (tmp))\n        ct_x = ct_y = 0.5;\n      else\n        {\n          ct_x = px[pt[0]] + (px[pt[1]] - px[pt[0]])/(1 + tmp);\n          ct_y = py[pt[0]] + (py[pt[1]] - py[pt[0]])/(1 + tmp);\n        }\n\n      // Add point to contour.\n      add_point (ct_x, ct_y);\n\n      // Decrease id value of current facet for start edge.\n      mark(r, c) -= static_cast<char> (1 << stop_edge);\n\n      // Find next facet.\n      if (stop_edge == 0)\n        r--;\n      else if (stop_edge == 1)\n        c++;\n      else if (stop_edge == 2)\n        r++;\n      else if (stop_edge == 3)\n        c--;\n\n      // Go to next facet.\n      start_edge = (stop_edge + 2) % 4;\n\n    }\n}\n\nstatic void\nmark_facets (const Matrix& Z, charMatrix& mark, double lvl)\n{\n  unsigned int nr = mark.rows ();\n  unsigned int nc = mark.cols ();\n\n  double f[4];\n\n  for (unsigned int c = 0; c < nc; c++)\n    for (unsigned int r = 0; r < nr; r++)\n      {\n        f[0] = Z(r, c) - lvl;\n        f[1] = Z(r, c+1) - lvl;\n        f[3] = Z(r+1, c) - lvl;\n        f[2] = Z(r+1, c+1) - lvl;\n\n        for (unsigned int i = 0; i < 4; i++)\n          if (fabs(f[i]) < std::numeric_limits<double>::epsilon ())\n            f[i] = std::numeric_limits<double>::epsilon ();\n\n        if (f[1] * f[2] < 0)\n          mark(r, c) += 2;\n\n        if (f[0] * f[3] < 0)\n          mark(r, c) += 8;\n      }\n\n  for (unsigned int r = 0; r < nr; r++)\n    for (unsigned int c = 0; c < nc; c++)\n      {\n        f[0] = Z(r, c) - lvl;\n        f[1] = Z(r, c+1) - lvl;\n        f[3] = Z(r+1, c) - lvl;\n        f[2] = Z(r+1, c+1) - lvl;\n\n        for (unsigned int i = 0; i < 4; i++)\n          if (fabs(f[i]) < std::numeric_limits<double>::epsilon ())\n            f[i] = std::numeric_limits<double>::epsilon ();\n\n        if (f[0] * f[1] < 0)\n          mark(r, c) += 1;\n\n        if (f[2] * f[3] < 0)\n          mark(r, c) += 4;\n      }\n}\n\nstatic void\ncntr (const RowVector& X, const RowVector& Y, const Matrix& Z, double lvl)\n{\n  unsigned int nr = Z.rows ();\n  unsigned int nc = Z.cols ();\n\n  charMatrix mark (nr - 1, nc - 1, 0);\n\n  mark_facets (Z, mark, lvl);\n\n  // Find contours that start at a domain edge.\n\n  for (unsigned int c = 0; c < nc - 1; c++)\n    {\n      // Top.\n      if (mark(0, c) & 1)\n        drawcn (X, Y, Z, lvl, 0, c, 0.0, 0.0, 0, true, mark);\n\n      // Bottom.\n      if (mark(nr - 2, c) & 4)\n        drawcn (X, Y, Z, lvl, nr - 2, c, 0.0, 0.0, 2, true, mark);\n    }\n\n  for (unsigned int r = 0; r < nr - 1; r++)\n    {\n      // Left.\n      if (mark(r, 0) & 8)\n        drawcn (X, Y, Z, lvl, r, 0, 0.0, 0.0, 3, true, mark);\n\n      // Right.\n      if (mark(r, nc - 2) & 2)\n        drawcn (X, Y, Z, lvl, r, nc - 2, 0.0, 0.0, 1, true, mark);\n    }\n\n  for (unsigned int r = 0; r < nr - 1; r++)\n    for (unsigned int c = 0; c < nc - 1; c++)\n      if (mark (r, c) > 0)\n        drawcn (X, Y, Z, lvl, r, c, 0.0, 0.0, 255, true, mark);\n}\n\n\nDEFUN (__contourc__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{c} =} __contourc__ (@var{x}, @var{y}, @var{z}, @var{levels})\nCalculate Z-level contours (isolines).\n@end deftypefn */)\n{\n  RowVector X = args(0).row_vector_value ();\n  RowVector Y = args(1).row_vector_value ();\n  Matrix Z = args(2).matrix_value ();\n  RowVector L = args(3).row_vector_value ();\n\n  contourc.resize (2, 0);\n\n  for (int i = 0; i < L.numel (); i++)\n    cntr (X, Y, Z, L(i));\n\n  end_contour ();\n\n  return octave_value (contourc);\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__dsearchn__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (__dsearchn__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{idx}, @var{d}] =} dsearch (@var{x}, @var{xi})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  Matrix x = args(0).matrix_value ().transpose ();\n  Matrix xi = args(1).matrix_value ().transpose ();\n\n  if (x.rows () != xi.rows () || x.columns () < 1)\n    error (\"__dsearchn__: number of rows of X and XI must match\");\n\n  octave_idx_type n = x.rows ();\n  octave_idx_type nx = x.columns ();\n  octave_idx_type nxi = xi.columns ();\n\n  ColumnVector idx (nxi);\n  double *pidx = idx.rwdata ();\n  ColumnVector dist (nxi);\n  double *pdist = dist.rwdata ();\n\n#define DIST(dd, y, yi, m)                      \\\n  dd = 0.0;                                     \\\n  for (octave_idx_type k = 0; k < m; k++)       \\\n    {                                           \\\n      double yd = y[k] - yi[k];                 \\\n      dd += yd * yd;                            \\\n    }                                           \\\n  dd = sqrt (dd)\n\n  const double *pxi = xi.data ();\n  for (octave_idx_type i = 0; i < nxi; i++)\n    {\n      double d0;\n      const double *px = x.data ();\n      DIST(d0, px, pxi, n);\n      *pidx = 1.;\n      for (octave_idx_type j = 1; j < nx; j++)\n        {\n          px += n;\n          double d;\n          DIST (d, px, pxi, n);\n          if (d < d0)\n            {\n              d0 = d;\n              *pidx = static_cast<double> (j + 1);\n            }\n          octave_quit ();\n        }\n\n      *pdist++ = d0;\n      pidx++;\n      pxi += n;\n    }\n\n  return ovl (idx, dist);\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__eigs__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <limits>\n#include <string>\n\n#include \"Matrix.h\"\n#include \"eigs-base.h\"\n#include \"unwind-prot.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_ARPACK)\n\nstruct eigs_callback\n{\npublic:\n\n  eigs_callback (octave::interpreter& interp)\n    : m_interpreter (interp)\n  { }\n\n  ColumnVector\n  eigs_func (const ColumnVector& x, int& eigs_error);\n\n  ComplexColumnVector\n  eigs_complex_func (const ComplexColumnVector& x, int& eigs_error);\n\n  //--------\n\n  octave::interpreter& m_interpreter;\n\n  // Pointer for user defined function.\n  octave_value m_eigs_fcn;\n\n  // Have we warned about imaginary values returned from user function?\n  bool m_warned_imaginary = false;\n};\n\n// Is this a recursive call?\nstatic int call_depth = 0;\n\nColumnVector\neigs_callback::eigs_func (const ColumnVector& x, int& eigs_error)\n{\n  ColumnVector retval;\n  octave_value_list args;\n  args(0) = x;\n\n  if (m_eigs_fcn.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          tmp = m_interpreter.feval (m_eigs_fcn, args, 1);\n        }\n      catch (octave::execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"eigs\");\n        }\n\n      if (tmp.length () && tmp(0).is_defined ())\n        {\n          if (! m_warned_imaginary && tmp(0).iscomplex ())\n            {\n              warning (\"eigs: ignoring imaginary part returned from user-supplied function\");\n              m_warned_imaginary = true;\n            }\n\n          retval = tmp(0).xvector_value (\"eigs: evaluation of user-supplied function failed\");\n        }\n      else\n        {\n          eigs_error = 1;\n          err_user_supplied_eval (\"eigs\");\n        }\n    }\n\n  return retval;\n}\n\nComplexColumnVector\neigs_callback::eigs_complex_func (const ComplexColumnVector& x,\n                                  int& eigs_error)\n{\n  ComplexColumnVector retval;\n  octave_value_list args;\n  args(0) = x;\n\n  if (m_eigs_fcn.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          tmp = m_interpreter.feval (m_eigs_fcn, args, 1);\n        }\n      catch (octave::execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"eigs\");\n        }\n\n      if (tmp.length () && tmp(0).is_defined ())\n        {\n          retval = tmp(0).xcomplex_vector_value (\"eigs: evaluation of user-supplied function failed\");\n        }\n      else\n        {\n          eigs_error = 1;\n          err_user_supplied_eval (\"eigs\");\n        }\n    }\n\n  return retval;\n}\n\n#endif\n\nDEFMETHOD (__eigs__, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{d} =} __eigs__ (@var{A})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{A}, @var{k})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{A}, @var{k}, @var{sigma})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{A}, @var{k}, @var{sigma}, @var{opts})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{A}, @var{B})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{A}, @var{B}, @var{k})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{A}, @var{B}, @var{k}, @var{sigma})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{A}, @var{B}, @var{k}, @var{sigma}, @var{opts})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{af}, @var{n})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{af}, @var{n}, @var{B})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{af}, @var{n}, @var{k})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{af}, @var{n}, @var{B}, @var{k})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{af}, @var{n}, @var{k}, @var{sigma})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{af}, @var{n}, @var{B}, @var{k}, @var{sigma})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{af}, @var{n}, @var{k}, @var{sigma}, @var{opts})\n@deftypefnx {} {@var{d} =} __eigs__ (@var{af}, @var{n}, @var{B}, @var{k}, @var{sigma}, @var{opts})\n@deftypefnx {} {[@var{V}, @var{d}] =} __eigs__ (@var{A}, @dots{})\n@deftypefnx {} {[@var{V}, @var{d}] =} __eigs__ (@var{af}, @var{n}, @dots{})\n@deftypefnx {} {[@var{V}, @var{d}, @var{flag}] =} __eigs__ (@var{A}, @dots{})\n@deftypefnx {} {[@var{V}, @var{d}, @var{flag}] =} __eigs__ (@var{af}, @var{n}, @dots{})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_ARPACK)\n\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  octave_value_list retval;\n\n  std::string fcn_name;\n  octave_idx_type n = 0;\n  octave_idx_type k = 6;\n  Complex sigma = 0.0;\n  double sigmar, sigmai;\n  bool have_sigma = false;\n  std::string typ = \"LM\";\n  Matrix amm, bmm, bmt;\n  ComplexMatrix acm, bcm, bct;\n  SparseMatrix asmm, bsmm, bsmt;\n  SparseComplexMatrix ascm, bscm, bsct;\n  int b_arg = 0;\n  bool have_b = false;\n  bool have_a_fcn = false;\n  bool a_is_complex = false;\n  bool b_is_complex = false;\n  bool symmetric = false;\n  bool sym_tested = false;\n  bool cholB = false;\n  bool a_is_sparse = false;\n  bool b_is_sparse = false;\n  ColumnVector permB;\n  int arg_offset = 0;\n  double tol = std::numeric_limits<double>::epsilon ();\n  int maxit = 300;\n  int disp = 0;\n  octave_idx_type p = -1;\n  ColumnVector resid;\n  ComplexColumnVector cresid;\n  octave_idx_type info = 1;\n\n  eigs_callback callback (interp);\n\n  unwind_protect_var<int> restore_var (call_depth);\n  call_depth++;\n\n  if (call_depth > 1)\n    error (\"eigs: invalid recursive call\");\n\n  if (args(0).is_function_handle () || args(0).is_inline_function ()\n      || args(0).is_string ())\n    {\n      have_a_fcn = true;\n      callback.m_eigs_fcn = get_function_handle (interp, args(0), \"x\");\n\n      if (callback.m_eigs_fcn.is_undefined ())\n        error (\"eigs: unknown function\");\n      if (nargin < 2)\n        error (\"eigs: incorrect number of arguments\");\n\n      n = args(1).strict_int_value ();\n      arg_offset = 1;\n    }\n  else\n    {\n      // Matrix A\n      if (args(0).iscomplex ())\n        {\n          a_is_complex = true;\n          if (args(0).issparse ())\n            {\n              a_is_sparse = true;\n              ascm = args(0).sparse_complex_matrix_value ();\n              // Validation is 17x faster in C++ than in m-file.\n              if (ascm.any_element_is_inf_or_nan ())\n                error (\"eigs: matrix A contains Inf or NaN values\");\n            }\n          else\n            {\n              acm = args(0).complex_matrix_value ();\n              if (acm.any_element_is_inf_or_nan ())\n                error (\"eigs: matrix A contains Inf or NaN values\");\n            }\n        }\n      else\n        {\n          if (args(0).issparse ())\n            {\n              a_is_sparse = true;\n              asmm = args(0).sparse_matrix_value ();\n              if (asmm.any_element_is_inf_or_nan ())\n                error (\"eigs: matrix A contains Inf or NaN values\");\n            }\n          else\n            {\n              amm = args(0).matrix_value ();\n              if (amm.any_element_is_inf_or_nan ())\n                error (\"eigs: matrix A contains Inf or NaN values\");\n            }\n        }\n    }\n\n  // Note: hold off converting B until later to avoid issues of double\n  // copies of the matrix if B is full/real while A is complex.\n  if (nargin > (1+arg_offset) && ! args(1+arg_offset).is_real_scalar ())\n    {\n      have_b = true;\n      b_arg = 1 + arg_offset;\n      if (args(b_arg).iscomplex ())\n        {\n          b_is_complex = true;\n          if (args(b_arg).issparse ())\n            b_is_sparse = true;\n        }\n      else\n        {\n          if (args(b_arg).issparse ())\n            b_is_sparse = true;\n        }\n      arg_offset++;\n    }\n\n  if (nargin > (1+arg_offset))\n    k = args(1+arg_offset).strict_int_value ();\n\n  if (nargin > (2+arg_offset))\n    {\n      if (args(2+arg_offset).is_string ())\n        {\n          typ = args(2+arg_offset).string_value ();\n          // Use STL function to convert to uppercase\n          transform (typ.begin (), typ.end (), typ.begin (), toupper);\n\n          sigma = 0.0;\n        }\n      else\n        {\n          have_sigma = true;\n          sigma = args(2+arg_offset).xcomplex_value (\"eigs: SIGMA must be a scalar or a string\");\n        }\n    }\n\n  sigmar = sigma.real ();\n  sigmai = sigma.imag ();\n\n  if (nargin > (3+arg_offset))\n    {\n      if (! args(3+arg_offset).isstruct ())\n        error (\"eigs: OPTS argument must be a structure\");\n\n      octave_scalar_map map = args(3+arg_offset).xscalar_map_value (\"eigs: OPTS argument must be a scalar structure\");\n\n      octave_value tmp;\n\n      // issym is ignored for complex matrix inputs\n      tmp = map.getfield (\"issym\");\n      if (tmp.is_defined ())\n        {\n          if (tmp.numel () != 1)\n            error (\"eigs: OPTS.issym must be a scalar value\");\n\n          symmetric = tmp.strict_bool_value (\"eigs: OPTS.issym must be a logical value\");\n          sym_tested = true;\n        }\n\n      // isreal is ignored if A is not a function\n      if (have_a_fcn)\n        {\n          tmp = map.getfield (\"isreal\");\n          if (tmp.is_defined ())\n            {\n              if (tmp.numel () != 1)\n                error (\"eigs: OPTS.isreal must be a scalar value\");\n\n              a_is_complex = ! tmp.strict_bool_value (\"eigs: OPTS.isreal must be a logical value\");\n            }\n        }\n\n      tmp = map.getfield (\"tol\");\n      if (tmp.is_defined ())\n        tol = tmp.double_value ();\n\n      tmp = map.getfield (\"maxit\");\n      if (tmp.is_defined ())\n        maxit = tmp.strict_int_value ();\n\n      tmp = map.getfield (\"p\");\n      if (tmp.is_defined ())\n        p = tmp.strict_int_value ();\n\n      tmp = map.getfield (\"v0\");\n      if (tmp.is_defined ())\n        {\n          if (a_is_complex || b_is_complex)\n            cresid = ComplexColumnVector (tmp.complex_vector_value ());\n          else\n            resid = ColumnVector (tmp.vector_value ());\n        }\n\n      tmp = map.getfield (\"disp\");\n      if (tmp.is_defined ())\n        disp = tmp.strict_int_value ();\n\n      tmp = map.getfield (\"cholB\");\n      if (tmp.is_defined ())\n        {\n          if (tmp.numel () != 1)\n            error (\"eigs: OPTS.cholB must be a scalar value\");\n\n          cholB = tmp.strict_bool_value (\"eigs: OPTS.cholB must be a logical value\");\n        }\n\n      tmp = map.getfield (\"permB\");\n      if (tmp.is_defined ())\n        permB = ColumnVector (tmp.vector_value ()) - 1.0;\n    }\n\n  if (nargin > (4+arg_offset))\n    error (\"eigs: incorrect number of arguments\");\n\n  // Test undeclared (no issym) matrix inputs for symmetry\n  if (! sym_tested && ! have_a_fcn)\n    {\n      if (a_is_complex)\n        {\n          if (a_is_sparse)\n            symmetric = ascm.ishermitian ();\n          else\n            symmetric = acm.ishermitian ();\n        }\n      else\n        {\n          if (a_is_sparse)\n            symmetric = asmm.issymmetric ();\n          else\n            symmetric = amm.issymmetric ();\n        }\n    }\n\n  // Matrix B\n  if (have_b)\n    {\n      if (a_is_complex || b_is_complex)\n        {\n          if (b_is_sparse)\n            {\n              bscm = args(b_arg).sparse_complex_matrix_value ();\n              // Validation is 17x faster in C++ than in m-file.\n              if (bscm.any_element_is_inf_or_nan ())\n                error (\"eigs: matrix A contains Inf or NaN values\");\n            }\n          else\n            {\n              bcm = args(b_arg).complex_matrix_value ();\n              if (bcm.any_element_is_inf_or_nan ())\n                error (\"eigs: matrix B contains Inf or NaN values\");\n            }\n        }\n      else\n        {\n          if (b_is_sparse)\n            {\n              bsmm = args(b_arg).sparse_matrix_value ();\n              if (bsmm.any_element_is_inf_or_nan ())\n                error (\"eigs: matrix B contains Inf or NaN values\");\n            }\n          else\n            {\n              bmm = args(b_arg).matrix_value ();\n              if (bmm.any_element_is_inf_or_nan ())\n                error (\"eigs: matrix B contains Inf or NaN values\");\n            }\n        }\n    }\n\n  // Mode 1 for SM mode seems unstable for some reason.\n  // Use Mode 3 instead, with sigma = 0.\n  if (! have_sigma && typ == \"SM\")\n    have_sigma = true;\n\n  octave_idx_type nconv;\n  if (a_is_complex || b_is_complex)\n    {\n      EigsComplexFunc\n      eigs_complex_fcn = [&callback] (const ComplexColumnVector& x,\n                                      int& eigs_error)\n      {\n        return callback.eigs_complex_func (x, eigs_error);\n      };\n\n      ComplexMatrix eig_vec;\n      ComplexColumnVector eig_val;\n\n      if (have_a_fcn)\n        {\n          if (b_is_sparse)\n            nconv = EigsComplexNonSymmetricFunc\n                    (eigs_complex_fcn, n, typ, sigma, k, p, info, eig_vec,\n                     eig_val, bscm, permB, cresid, octave_stdout, tol,\n                     (nargout > 1), cholB, disp, maxit);\n          else\n            nconv = EigsComplexNonSymmetricFunc\n                    (eigs_complex_fcn, n, typ, sigma, k, p, info, eig_vec,\n                     eig_val, bcm, permB, cresid, octave_stdout, tol,\n                     (nargout > 1), cholB, disp, maxit);\n        }\n      else if (have_sigma)\n        {\n          if (a_is_sparse)\n            nconv = EigsComplexNonSymmetricMatrixShift\n                    (ascm, sigma, k, p, info, eig_vec, eig_val, bscm, permB,\n                     cresid, octave_stdout, tol, (nargout > 1), cholB, disp,\n                     maxit);\n          else\n            nconv = EigsComplexNonSymmetricMatrixShift\n                    (acm, sigma, k, p, info, eig_vec, eig_val, bcm, permB,\n                     cresid, octave_stdout, tol, (nargout > 1), cholB, disp,\n                     maxit);\n        }\n      else\n        {\n          if (a_is_sparse)\n            nconv = EigsComplexNonSymmetricMatrix\n                    (ascm, typ, k, p, info, eig_vec, eig_val, bscm, permB,\n                     cresid, octave_stdout, tol, (nargout > 1), cholB, disp,\n                     maxit);\n          else\n            nconv = EigsComplexNonSymmetricMatrix\n                    (acm, typ, k, p, info, eig_vec, eig_val, bcm, permB,\n                     cresid, octave_stdout, tol, (nargout > 1), cholB, disp,\n                     maxit);\n        }\n\n      if (nargout < 2)\n        {\n          if (symmetric)\n            retval(0) = real (eig_val);\n          else\n            retval(0) = eig_val;\n        }\n      else\n        {\n          if (symmetric)\n            retval = ovl (eig_vec, DiagMatrix (real (eig_val)), double (info));\n          else\n            retval = ovl (eig_vec, ComplexDiagMatrix (eig_val), double (info));\n        }\n    }\n  else if (sigmai != 0.0)\n    {\n      EigsComplexFunc\n      eigs_complex_fcn = [&callback] (const ComplexColumnVector& x,\n                                      int& eigs_error)\n      {\n        return callback.eigs_complex_func (x, eigs_error);\n      };\n\n      // Promote real problem to a complex one.\n      ComplexMatrix eig_vec;\n      ComplexColumnVector eig_val;\n\n      if (have_a_fcn)\n        {\n          if (b_is_sparse)\n            nconv = EigsComplexNonSymmetricFunc\n                    (eigs_complex_fcn, n, typ, sigma, k, p, info, eig_vec,\n                     eig_val, bscm, permB, cresid, octave_stdout, tol,\n                     (nargout > 1), cholB, disp, maxit);\n          else\n            nconv = EigsComplexNonSymmetricFunc\n                    (eigs_complex_fcn, n, typ, sigma, k, p, info, eig_vec,\n                     eig_val, bcm, permB, cresid, octave_stdout, tol,\n                     (nargout > 1), cholB, disp, maxit);\n        }\n      else\n        {\n          if (a_is_sparse)\n            nconv = EigsComplexNonSymmetricMatrixShift\n                    (SparseComplexMatrix (asmm), sigma, k, p, info, eig_vec,\n                     eig_val, SparseComplexMatrix (bsmm), permB, cresid,\n                     octave_stdout, tol, (nargout > 1), cholB, disp, maxit);\n          else\n            nconv = EigsComplexNonSymmetricMatrixShift\n                    (ComplexMatrix (amm), sigma, k, p, info, eig_vec,\n                     eig_val, ComplexMatrix (bmm), permB, cresid,\n                     octave_stdout, tol, (nargout > 1), cholB, disp, maxit);\n        }\n\n      if (nargout < 2)\n        {\n          if (symmetric)\n            retval(0) = real (eig_val);\n          else\n            retval(0) = eig_val;\n        }\n      else\n        {\n          if (symmetric)\n            retval = ovl (eig_vec, DiagMatrix (real (eig_val)), double (info));\n          else\n            retval = ovl (eig_vec, ComplexDiagMatrix (eig_val), double (info));\n        }\n    }\n  else\n    {\n      EigsFunc eigs_fcn = [&callback] (const ColumnVector& x, int& eigs_error)\n      {\n        return callback.eigs_func (x, eigs_error);\n      };\n\n      if (symmetric)\n        {\n          Matrix eig_vec;\n          ColumnVector eig_val;\n\n          if (have_a_fcn)\n            {\n              if (b_is_sparse)\n                nconv = EigsRealSymmetricFunc\n                        (eigs_fcn, n, typ, sigmar, k, p, info, eig_vec,\n                         eig_val, bsmm, permB, resid, octave_stdout, tol,\n                         (nargout > 1), cholB, disp, maxit);\n              else\n                nconv = EigsRealSymmetricFunc\n                        (eigs_fcn, n, typ, sigmar, k, p, info, eig_vec,\n                         eig_val, bmm, permB, resid, octave_stdout, tol,\n                         (nargout > 1), cholB, disp, maxit);\n            }\n          else if (have_sigma)\n            {\n              if (a_is_sparse)\n                nconv = EigsRealSymmetricMatrixShift\n                        (asmm, sigmar, k, p, info, eig_vec, eig_val, bsmm,\n                         permB, resid, octave_stdout, tol, (nargout > 1),\n                         cholB, disp, maxit);\n              else\n                nconv = EigsRealSymmetricMatrixShift\n                        (amm, sigmar, k, p, info, eig_vec, eig_val, bmm,\n                         permB, resid, octave_stdout, tol, (nargout > 1),\n                         cholB, disp, maxit);\n            }\n          else\n            {\n              if (a_is_sparse)\n                nconv = EigsRealSymmetricMatrix\n                        (asmm, typ, k, p, info, eig_vec, eig_val, bsmm,\n                         permB, resid, octave_stdout, tol, (nargout > 1),\n                         cholB, disp, maxit);\n              else\n                nconv = EigsRealSymmetricMatrix\n                        (amm, typ, k, p, info, eig_vec, eig_val, bmm, permB,\n                         resid, octave_stdout, tol, (nargout > 1), cholB,\n                         disp, maxit);\n            }\n\n          if (nargout < 2)\n            retval(0) = eig_val;\n          else\n            retval = ovl (eig_vec, DiagMatrix (eig_val), double (info));\n        }\n      else\n        {\n          ComplexMatrix eig_vec;\n          ComplexColumnVector eig_val;\n\n          if (have_a_fcn)\n            {\n              if (b_is_sparse)\n                nconv = EigsRealNonSymmetricFunc\n                        (eigs_fcn, n, typ, sigmar, k, p, info, eig_vec,\n                         eig_val, bsmm, permB, resid, octave_stdout, tol,\n                         (nargout > 1), cholB, disp, maxit);\n              else\n                nconv = EigsRealNonSymmetricFunc\n                        (eigs_fcn, n, typ, sigmar, k, p, info, eig_vec,\n                         eig_val, bmm, permB, resid, octave_stdout, tol,\n                         (nargout > 1), cholB, disp, maxit);\n            }\n          else if (have_sigma)\n            {\n              if (a_is_sparse)\n                nconv = EigsRealNonSymmetricMatrixShift\n                        (asmm, sigmar, k, p, info, eig_vec, eig_val, bsmm,\n                         permB, resid, octave_stdout, tol, (nargout > 1),\n                         cholB, disp, maxit);\n              else\n                nconv = EigsRealNonSymmetricMatrixShift\n                        (amm, sigmar, k, p, info, eig_vec, eig_val, bmm,\n                         permB, resid, octave_stdout, tol, (nargout > 1),\n                         cholB, disp, maxit);\n            }\n          else\n            {\n              if (a_is_sparse)\n                nconv = EigsRealNonSymmetricMatrix\n                        (asmm, typ, k, p, info, eig_vec, eig_val, bsmm,\n                         permB, resid, octave_stdout, tol, (nargout > 1),\n                         cholB, disp, maxit);\n              else\n                nconv = EigsRealNonSymmetricMatrix\n                        (amm, typ, k, p, info, eig_vec, eig_val, bmm, permB,\n                         resid, octave_stdout, tol, (nargout > 1), cholB,\n                         disp, maxit);\n            }\n\n          if (nargout < 2)\n            retval(0) = eig_val;\n          else\n            retval = ovl (eig_vec, ComplexDiagMatrix (eig_val), double (info));\n        }\n    }\n\n  if (nconv <= 0)\n    warning_with_id (\"Octave:eigs:UnconvergedEigenvalues\",\n                     \"eigs: None of the %\" OCTAVE_IDX_TYPE_FORMAT\n                     \" requested eigenvalues converged\", k);\n  else if (nconv < k)\n    warning_with_id (\"Octave:eigs:UnconvergedEigenvalues\",\n                     \"eigs: Only %\" OCTAVE_IDX_TYPE_FORMAT\n                     \" of the %\" OCTAVE_IDX_TYPE_FORMAT\n                     \" requested eigenvalues converged\",\n                     nconv, k);\n\n  if (! fcn_name.empty ())\n    {\n      symbol_table& symtab = interp.get_symbol_table ();\n\n      symtab.clear_function (fcn_name);\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (interp);\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"eigs\", \"ARPACK\");\n\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__expint__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"CNDArray.h\"\n#include \"defun.h\"\n#include \"fCNDArray.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (__expint__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} __expint__ (@var{x})\nContinued fraction expansion for the exponential integral.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value_list retval;\n\n  bool is_single = args(0).is_single_type ();\n\n  int numel_x = args(0).numel ();\n\n  // Initialize output dimension vector\n  dim_vector output_dv (numel_x, 1);\n\n  // Lentz's algorithm in two cases: single and double precision\n  if (is_single)\n    {\n      // Initialize output and inputs\n      FloatComplexColumnVector output (output_dv);\n      FloatComplexNDArray x;\n\n      if (numel_x == 1)\n        x = FloatComplexNDArray (output_dv, args(0).float_complex_value ());\n      else\n        x = args(0).float_complex_array_value ();\n\n      // Initialize variables used in algorithm\n      static const FloatComplex tiny = math::exp2 (-50.0f);\n      static constexpr float eps = std::numeric_limits<float>::epsilon ();\n      const FloatComplex cone (1.0, 0.0);\n      const FloatComplex czero (0.0, 0.0);\n      const int maxit = 100;\n\n      // Loop over all elements\n      for (octave_idx_type i = 0; i < numel_x; ++i)\n        {\n          // Catch Ctrl+C\n          OCTAVE_QUIT;\n\n          // Variable initialization for the current element\n          FloatComplex xj = x(i);\n          FloatComplex y = tiny;\n          FloatComplex Cj = y;\n          FloatComplex Dj = czero;\n          FloatComplex alpha_j = cone;\n          FloatComplex beta_j = xj;\n          FloatComplex Deltaj = czero;\n          int j = 1;\n\n          // Lentz's algorithm\n          while ((std::abs (Deltaj - cone)  > eps) && (j < maxit))\n            {\n              Dj = beta_j + alpha_j * Dj;\n              if (Dj == czero)\n                Dj = tiny;\n              Cj = beta_j + alpha_j / Cj;\n              if (Cj == czero)\n                Cj = tiny;\n              Dj = cone / Dj;\n              Deltaj = Cj * Dj;\n              y *= Deltaj;\n              alpha_j = (j + 1) / 2;\n              if ((j % 2) == 0)\n                beta_j = xj;\n              else\n                beta_j = cone;\n              j++;\n            }\n\n          output(i) = y;\n        }\n      retval(0) = output;\n    }\n  else\n    {\n      // Initialize output and inputs\n      ComplexColumnVector output (output_dv);\n      ComplexNDArray x;\n\n      if (numel_x == 1)\n        x = ComplexNDArray (output_dv, args(0).complex_value ());\n      else\n        x = args(0).complex_array_value ();\n\n      // Initialize variables used in algorithm\n      static const Complex tiny = math::exp2 (-100.0);\n      static constexpr double eps = std::numeric_limits<double>::epsilon ();\n      const Complex cone (1.0, 0.0);\n      const Complex czero (0.0, 0.0);\n      const int maxit = 200;\n\n      // Loop over all scenarios\n      for (octave_idx_type i = 0; i < numel_x; ++i)\n        {\n          // Catch Ctrl+C\n          OCTAVE_QUIT;\n\n          // Variable initialization for the current element\n          Complex xj = x(i);\n          Complex y = tiny;\n          Complex Cj = y;\n          Complex Dj = czero;\n          Complex alpha_j = cone;\n          Complex beta_j = xj;\n          Complex Deltaj = czero;\n          int j = 1;\n\n          // Lentz's algorithm\n          while ((std::abs (Deltaj - cone)  > eps) && (j < maxit))\n            {\n              Dj = beta_j + alpha_j * Dj;\n              if (Dj == czero)\n                Dj = tiny;\n              Cj = beta_j + alpha_j / Cj;\n              if (Cj == czero)\n                Cj = tiny;\n              Dj = cone / Dj;\n              Deltaj = Cj * Dj;\n              y *= Deltaj;\n              alpha_j = (j + 1) / 2;\n              if ((j % 2) == 0)\n                beta_j = xj;\n              else\n                beta_j = cone;\n              j++;\n            }\n\n          output(i) = y;\n        }\n\n      retval(0) = output;\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__gammainc__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"fNDArray.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (__gammainc__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} __gammainc__ (@var{x}, @var{a})\nContinued fraction for incomplete gamma function.\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  bool is_single = args(0).is_single_type () || args(1).is_single_type ();\n\n  // Total number of scenarios: get maximum of length of all vectors\n  int numel_x = args(0).numel ();\n  int numel_a = args(1).numel ();\n  int len = std::max (numel_x, numel_a);\n\n  octave_value_list retval;\n  // Initialize output dimension vector\n  dim_vector output_dv (len, 1);\n\n  // Lentz's algorithm in two cases: single and double precision\n  if (is_single)\n    {\n      // Initialize output and inputs\n      FloatColumnVector output (output_dv);\n      FloatNDArray x, a;\n\n      if (numel_x == 1)\n        x = FloatNDArray (output_dv, args(0).float_scalar_value ());\n      else\n        x = args(0).float_array_value ();\n\n      if (numel_a == 1)\n        a = FloatNDArray (output_dv, args(1).float_scalar_value ());\n      else\n        a = args(1).float_array_value ();\n\n      // Initialize variables used in algorithm\n      static const float tiny = math::exp2 (-50.0f);\n      static constexpr float eps = std::numeric_limits<float>::epsilon();\n      float y, Cj, Dj, bj, aj, Deltaj;\n      int j, maxit;\n      maxit = 200;\n\n      // Loop over all elements\n      for (octave_idx_type i = 0; i < len; ++i)\n        {\n          // Catch Ctrl+C\n          OCTAVE_QUIT;\n\n          // Variable initialization for the current element\n          y = tiny;\n          Cj = y;\n          Dj = 0;\n          bj = x(i) - a(i) + 1;\n          aj = a(i);\n          Deltaj = 0;\n          j = 1;\n\n          // Lentz's algorithm\n          while ((std::abs ((Deltaj - 1) / y) > eps) && (j < maxit))\n            {\n              Cj = bj + aj/Cj;\n              Dj = 1 / (bj + aj*Dj);\n              Deltaj = Cj * Dj;\n              y *= Deltaj;\n              bj += 2;\n              aj = j * (a(i) - j);\n              j++;\n            }\n\n          output(i) = y;\n        }\n\n      retval(0) = output;\n    }\n  else\n    {\n      // Initialize output and inputs\n      ColumnVector output (output_dv);\n      NDArray x, a;\n\n      if (numel_x == 1)\n        x = NDArray (output_dv, args(0).scalar_value ());\n      else\n        x = args(0).array_value ();\n\n      if (numel_a == 1)\n        a = NDArray (output_dv, args(1).scalar_value ());\n      else\n        a = args(1).array_value ();\n\n      // Initialize variables used in algorithm\n      static const double tiny = math::exp2 (-100.0);\n      static constexpr double eps = std::numeric_limits<double>::epsilon();\n      double y, Cj, Dj, bj, aj, Deltaj;\n      int j, maxit;\n      maxit = 200;\n\n      // Loop over all elements\n      for (octave_idx_type i = 0; i < len; ++i)\n        {\n          // Catch Ctrl+C\n          OCTAVE_QUIT;\n\n          // Variable initialization for the current element\n          y = tiny;\n          Cj = y;\n          Dj = 0;\n          bj = x(i) - a(i) + 1;\n          aj = a(i);\n          Deltaj = 0;\n          j = 1;\n\n          // Lentz's algorithm\n          while ((std::abs ((Deltaj - 1) / y) > eps) && (j < maxit))\n            {\n              Cj = bj + aj/Cj;\n              Dj = 1 / (bj + aj*Dj);\n              Deltaj = Cj * Dj;\n              y *= Deltaj;\n              bj += 2;\n              aj = j * (a(i) - j);\n              j++;\n            }\n\n          output(i) = y;\n        }\n\n      retval(0) = output;\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__ichol__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <limits>\n\n#include \"oct-locbuf.h\"\n#include \"oct-norm.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n\n#include \"builtin-defun-decls.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Secondary functions for complex and real case used in ichol algorithms.\nComplex ichol_mult_complex (Complex a, Complex b)\n{\n#if defined (HAVE_CXX_COMPLEX_SETTERS)\n  b.imag (-b.imag ());\n#elif defined (HAVE_CXX_COMPLEX_REFERENCE_ACCESSORS)\n  b.imag () = -b.imag ();\n#else\n  b = b.conj ();\n#endif\n  return a * b;\n}\n\ndouble\nichol_mult_real (double a, double b)\n{\n  return a * b;\n}\n\nbool\nichol_checkpivot_complex (Complex pivot)\n{\n  if (fabs (pivot.imag ()) > std::numeric_limits<double>::epsilon())\n    error (\"ichol: non-real pivot encountered.  The matrix must be Hermitian.\");\n  else if (pivot.real () < 0)\n    error (\"ichol: negative pivot encountered\");\n\n  return true;\n}\n\nbool\nichol_checkpivot_real (double pivot)\n{\n  if (pivot < 0)\n    error (\"ichol: negative pivot encountered\");\n\n  return true;\n}\n\ntemplate <typename octave_matrix_t, typename T, T (*ichol_mult) (T, T),\n          bool (*ichol_checkpivot) (T)>\nvoid\nichol_0 (octave_matrix_t& sm, const std::string michol = \"off\")\n{\n  const octave_idx_type n = sm.cols ();\n  octave_idx_type j1, jend, j2, jrow, jjrow, j, jw, i, k, jj, r;\n  T tl;\n\n  char opt;\n  enum {OFF, ON};\n  if (michol == \"on\")\n    opt = ON;\n  else\n    opt = OFF;\n\n  // Input matrix pointers\n  octave_idx_type *cidx = sm.cidx ();\n  octave_idx_type *ridx = sm.ridx ();\n  T *data = sm.data ();\n\n  // Working arrays\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Lfirst, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Llist, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, iw, n);\n  OCTAVE_LOCAL_BUFFER (T, dropsums, n);\n\n  // Initialize working arrays\n  for (i = 0; i < n; i++)\n    {\n      iw[i] = -1;\n      Llist[i] = -1;\n      Lfirst[i] = -1;\n      dropsums[i] = 0;\n    }\n\n  // Loop over all columns\n  for (k = 0; k < n; k++)\n    {\n      j1 = cidx[k];\n      j2 = cidx[k+1];\n      for (j = j1; j < j2; j++)\n        iw[ridx[j]] = j;\n\n      jrow = Llist[k];\n      // Iterate over each nonzero element in the actual row.\n      while (jrow != -1)\n        {\n          jjrow = Lfirst[jrow];\n          jend = cidx[jrow+1];\n          for (jj = jjrow; jj < jend; jj++)\n            {\n              r = ridx[jj];\n              jw = iw[r];\n              tl = ichol_mult (data[jj], data[jjrow]);\n              if (jw != -1)\n                data[jw] -= tl;\n              else\n                // Because of the symmetry of the matrix, we know\n                // the drops in the column r are also in the column k.\n                if (opt == ON)\n                  {\n                    dropsums[r] -= tl;\n                    dropsums[k] -= tl;\n                  }\n            }\n          // Update the linked list and the first entry of the actual column.\n          if ((jjrow + 1) < jend)\n            {\n              Lfirst[jrow]++;\n              j = jrow;\n              jrow = Llist[jrow];\n              Llist[j] = Llist[ridx[Lfirst[j]]];\n              Llist[ridx[Lfirst[j]]] = j;\n            }\n          else\n            jrow = Llist[jrow];\n        }\n\n      if (opt == ON)\n        data[j1] += dropsums[k];\n\n      // Test for j1 == j2 must be first to avoid invalid ridx[j1] access\n      if (j1 == j2 || ridx[j1] != k)\n        error (\"ichol: encountered a pivot equal to 0\");\n\n      if (! ichol_checkpivot (data[j1]))\n        break;\n\n      data[cidx[k]] = std::sqrt (data[j1]);\n\n      // Update Llist and Lfirst with the k-column information.  Also,\n      // scale the column elements by the pivot and reset the working array iw.\n      if (k < (n - 1))\n        {\n          iw[ridx[j1]] = -1;\n          for (i = j1 + 1; i < j2; i++)\n            {\n              iw[ridx[i]] = -1;\n              data[i] /= data[j1];\n            }\n          Lfirst[k] = j1;\n          if ((Lfirst[k] + 1) < j2)\n            {\n              Lfirst[k]++;\n              jjrow = ridx[Lfirst[k]];\n              Llist[k] = Llist[jjrow];\n              Llist[jjrow] = k;\n            }\n        }\n    }\n}\n\nDEFUN (__ichol0__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{L} =} __ichol0__ (@var{A}, @var{michol})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string michol = args(1).string_value ();\n\n  // In ICHOL0 algorithm the zero-pattern of the input matrix is preserved\n  // so its structure does not change during the algorithm.  The same input\n  // matrix is used to build the output matrix due to that fact.\n  if (! args(0).iscomplex ())\n    {\n      SparseMatrix sm = Ftril (ovl (args(0)))(0).sparse_matrix_value ();\n      ichol_0<SparseMatrix, double, ichol_mult_real,\n              ichol_checkpivot_real> (sm, michol);\n      return ovl (sm);\n    }\n  else\n    {\n      SparseComplexMatrix sm\n        = Ftril (ovl (args(0)))(0).sparse_complex_matrix_value ();\n      ichol_0<SparseComplexMatrix, Complex, ichol_mult_complex,\n              ichol_checkpivot_complex> (sm, michol);\n      return ovl (sm);\n    }\n}\n\ntemplate <typename octave_matrix_t, typename T, T (*ichol_mult) (T, T),\n          bool (*ichol_checkpivot) (T)>\nvoid\nichol_t (const octave_matrix_t& sm, octave_matrix_t& L, const T *cols_norm,\n         const T droptol, const std::string michol = \"off\")\n{\n\n  const octave_idx_type n = sm.cols ();\n  octave_idx_type j, jrow, jend, jjrow, i, k, jj, total_len,\n                  w_len, max_len, ind;\n  char opt;\n  enum {OFF, ON};\n  if (michol == \"on\")\n    opt = ON;\n  else\n    opt = OFF;\n\n  // Input matrix pointers (const -- sm is read-only)\n  const octave_idx_type *cidx = sm.cidx ();\n  const octave_idx_type *ridx = sm.ridx ();\n  const T *data = sm.data ();\n\n  // Output matrix data structures.  Because the final zero pattern of\n  // the output matrix is not known due to fill-in elements, a heuristic\n  // approach has been adopted for memory allocation.  The size of ridx_out_l\n  // and data_out_l is incremented 10% of their actual size (nnz (A) in the\n  // beginning).  If that amount is less than n, their size is just incremented\n  // in n elements.  This way the number of reallocations decreases throughout\n  // the process, obtaining a good performance.\n  max_len = sm.nnz ();\n  max_len += (0.1 * max_len) > n ? 0.1 * max_len : n;\n  Array<octave_idx_type> cidx_out_l (dim_vector (n + 1, 1));\n  octave_idx_type *cidx_l = cidx_out_l.rwdata ();\n  Array<octave_idx_type> ridx_out_l (dim_vector (max_len, 1));\n  octave_idx_type *ridx_l = ridx_out_l.rwdata ();\n  Array<T> data_out_l (dim_vector (max_len, 1));\n  T *data_l = data_out_l.rwdata ();\n\n  // Working arrays\n  OCTAVE_LOCAL_BUFFER (T, w_data, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Lfirst, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Llist, n);\n  OCTAVE_LOCAL_BUFFER (T, col_drops, n);\n  std::vector<octave_idx_type> vec (n, 0);\n  std::vector<bool> mark (n, false);\n\n  T zero = T (0);\n  cidx_l[0] = cidx[0];\n  for (i = 0; i < n; i++)\n    {\n      Llist[i] = -1;\n      Lfirst[i] = -1;\n      w_data[i] = 0;\n      col_drops[i] = zero;\n    }\n\n  total_len = 0;\n  for (k = 0; k < n; k++)\n    {\n      ind = 0;\n      for (j = cidx[k]; j < cidx[k+1]; j++)\n        {\n          w_data[ridx[j]] = data[j];\n          // Mark column index, intentionally outside the if-clause to ensure\n          // that mark[k] will be set to true as well.\n          mark[ridx[j]] = true;\n          if (ridx[j] != k)\n            {\n              vec[ind] = ridx[j];\n              ind++;\n            }\n        }\n      jrow = Llist[k];\n      while (jrow != -1)\n        {\n          jjrow = Lfirst[jrow];\n          jend = cidx_l[jrow+1];\n          for (jj = jjrow; jj < jend; jj++)\n            {\n              j = ridx_l[jj];\n              // If the element in the j position of the row is zero,\n              // then it will become nonzero, so we add it to the\n              // vector that tracks nonzero elements in the working row.\n              if (! mark[j])\n                {\n                  mark[j] = true;\n                  vec[ind] = j;\n                  ind++;\n                }\n              w_data[j] -= ichol_mult (data_l[jj], data_l[jjrow]);\n            }\n          // Update the actual column first element and\n          // update the linked list of the jrow row.\n          if ((jjrow + 1) < jend)\n            {\n              Lfirst[jrow]++;\n              j = jrow;\n              jrow = Llist[jrow];\n              Llist[j] = Llist[ridx_l[Lfirst[j]]];\n              Llist[ridx_l[Lfirst[j]]] = j;\n            }\n          else\n            jrow = Llist[jrow];\n        }\n\n      // Resizing output arrays\n      if ((max_len - total_len) < n)\n        {\n          max_len += (0.1 * max_len) > n ? 0.1 * max_len : n;\n          data_out_l.resize (dim_vector (max_len, 1));\n          data_l = data_out_l.rwdata ();\n          ridx_out_l.resize (dim_vector (max_len, 1));\n          ridx_l = ridx_out_l.rwdata ();\n        }\n\n      // The sorting of the nonzero elements of the working column can be\n      // handled in a couple of ways.  The most efficient two I found, are\n      // keeping the elements in an ordered binary search tree dynamically or\n      // keep them unsorted in a vector and at the end of the outer iteration\n      // order them.  The last approach exhibits lower execution times.\n      std::sort (vec.begin (), vec.begin () + ind);\n\n      data_l[total_len] = w_data[k];\n      ridx_l[total_len] = k;\n      w_len = 1;\n\n      // Extract the nonzero elements of working column and\n      // drop the elements that are lower than droptol * cols_norm[k].\n      for (i = 0; i < ind ; i++)\n        {\n          jrow = vec[i];\n          if (w_data[jrow] != zero)\n            {\n              if (std::abs (w_data[jrow]) < (droptol * cols_norm[k]))\n                {\n                  if (opt == ON)\n                    {\n                      col_drops[k] += w_data[jrow];\n                      col_drops[jrow] += w_data[jrow];\n                    }\n                }\n              else\n                {\n                  data_l[total_len + w_len] = w_data[jrow];\n                  ridx_l[total_len + w_len] = jrow;\n                  w_len++;\n                }\n            }\n          // Clear mark, vec, and w_data.  However, mark[k] is not set to zero.\n          mark[jrow] = false;\n          vec[i] = 0;\n          w_data[jrow] = zero;\n        }\n\n      // Compensate column sums --> michol option\n      if (opt == ON)\n        data_l[total_len] += col_drops[k];\n\n      if (data_l[total_len] == zero)\n        error (\"ichol: encountered a pivot equal to 0\");\n\n      if (! ichol_checkpivot (data_l[total_len]))\n        break;\n\n      // Once elements are dropped and compensation of column sums are done,\n      // scale the elements by the pivot.\n      data_l[total_len] = std::sqrt (data_l[total_len]);\n      for (jj = total_len + 1; jj < (total_len + w_len); jj++)\n        data_l[jj] /= data_l[total_len];\n      total_len += w_len;\n      // Check if there are too many elements to be indexed with\n      // octave_idx_type type due to fill-in during the process.\n      if (total_len < 0)\n        error (\"ichol: integer overflow.  Too many fill-in elements in L\");\n\n      cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len;\n\n      // Update Llist and Lfirst with the k-column information.\n      if (k < (n - 1))\n        {\n          Lfirst[k] = cidx_l[k];\n          if ((Lfirst[k] + 1) < cidx_l[k+1])\n            {\n              Lfirst[k]++;\n              jjrow = ridx_l[Lfirst[k]];\n              Llist[k] = Llist[jjrow];\n              Llist[jjrow] = k;\n            }\n        }\n    }\n\n  // Build the output matrices\n  L = octave_matrix_t (n, n, total_len);\n\n  for (i = 0; i <= n; i++)\n    L.cidx (i) = cidx_l[i];\n\n  for (i = 0; i < total_len; i++)\n    {\n      L.ridx (i) = ridx_l[i];\n      L.data (i) = data_l[i];\n    }\n}\n\nDEFUN (__icholt__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{L} =} __icholt__ (@var{A}, @var{droptol}, @var{michol})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  double droptol = args(1).double_value ();\n  std::string michol = args(2).string_value ();\n\n  if (! args(0).iscomplex ())\n    {\n      SparseMatrix L;\n      SparseMatrix sm_l = Ftril (ovl (args(0)))(0).sparse_matrix_value ();\n      RowVector sm_col_norms = xcolnorms (sm_l, 1);\n      ichol_t<SparseMatrix,\n              double, ichol_mult_real, ichol_checkpivot_real>\n              (sm_l, L, sm_col_norms.rwdata (), droptol, michol);\n\n      return ovl (L);\n    }\n  else\n    {\n      SparseComplexMatrix L;\n      SparseComplexMatrix sm_l\n        = Ftril (ovl (args(0)))(0).sparse_complex_matrix_value ();\n      Array<Complex> cols_norm = xcolnorms (sm_l, 1);\n      ichol_t <SparseComplexMatrix,\n              Complex, ichol_mult_complex, ichol_checkpivot_complex>\n              (sm_l, L, cols_norm.rwdata (),\n               Complex (droptol), michol);\n\n      return ovl (L);\n    }\n}\n\n/*\n%!test <*51736>\n%! k = 4;\n%! n = 2^k;\n%! Afull = diag (ones (n,1)) / ...\n%!          2+triu ([zeros(n,2), [n.^-[1;1;2]*ones(1,n-2);zeros(n-3,n-2)]], 1);\n%! A = sparse (Afull + Afull.');\n%! opts.type = \"ict\";\n%! opts.droptol = 0;\n%! L = ichol (A, opts);\n%! assert (norm (A - L*L.'), 0, 2*eps);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__ilu__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-locbuf.h\"\n#include \"oct-norm.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n\n#include \"builtin-defun-decls.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// This function implements the IKJ and JKI variants of Gaussian elimination to\n// perform the ILU0 decomposition.  The behavior is controlled by milu\n// parameter.  If milu = ['off'|'col'] the JKI version is performed taking\n// advantage of CCS format of the input matrix.  If milu = 'row' the input\n// matrix has to be transposed to obtain the equivalent CRS structure so we can\n// work efficiently with rows.  In this case IKJ version is used.\ntemplate <typename octave_matrix_t, typename T>\nvoid ilu_0 (octave_matrix_t& sm, const std::string milu = \"off\")\n{\n  const octave_idx_type n = sm.cols ();\n  octave_idx_type j1, j2, jrow, jw, i, j, k, jj;\n  T r;\n  T tl = 0;\n\n  enum {OFF, ROW, COL};\n  char opt;\n  if (milu == \"row\")\n    {\n      opt = ROW;\n      sm = sm.transpose ();\n    }\n  else if (milu == \"col\")\n    opt = COL;\n  else\n    opt = OFF;\n\n  // Input matrix pointers\n  octave_idx_type *cidx = sm.cidx ();\n  octave_idx_type *ridx = sm.ridx ();\n  T *data = sm.data ();\n\n  // Working arrays\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, iw, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, uptr, n);\n\n  // Initialize working arrays\n  for (i = 0; i < n; i++)\n    iw[i] = -1;\n\n  // Loop over all columns\n  for (k = 0; k < n; k++)\n    {\n      j1 = cidx[k];\n      j2 = cidx[k+1];\n\n      if (j1 == j2)\n        error (\"ilu: A has a zero on the diagonal\");\n\n      for (j = j1; j < j2; j++)\n        iw[ridx[j]] = j;\n\n      r = 0;\n      j = j1;\n      jrow = ridx[j1];\n      while ((jrow < k) && (j < j2))\n        {\n          if (opt == ROW)\n            {\n              tl = data[j] / data[uptr[jrow]];\n              data[j] = tl;\n            }\n          for (jj = uptr[jrow] + 1; jj < cidx[jrow+1]; jj++)\n            {\n              jw = iw[ridx[jj]];\n              if (jw != -1)\n                if (opt == ROW)\n                  data[jw] -= tl * data[jj];\n                else\n                  data[jw] -= data[j] * data[jj];\n\n              else\n                // That is for the milu='row'\n                if (opt == ROW)\n                  r += tl * data[jj];\n                else if (opt == COL)\n                  r += data[j] * data[jj];\n            }\n          j++;\n          jrow = ridx[j];\n        }\n      uptr[k] = j;\n      if (opt != OFF)\n        data[uptr[k]] -= r;\n\n      if (opt != ROW)\n        for (jj = uptr[k] + 1; jj < cidx[k+1]; jj++)\n          data[jj] /= data[uptr[k]];\n\n      if (k != jrow)\n        error (\"ilu: A has a zero on the diagonal\");\n\n      if (data[j] == T(0))\n        error (\"ilu: encountered a pivot equal to 0\");\n\n      for (i = j1; i < j2; i++)\n        iw[ridx[i]] = -1;\n    }\n\n  if (opt == ROW)\n    sm = sm.transpose ();\n}\n\nDEFUN (__ilu0__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{L}, @var{U}] =} __ilu0__ (@var{A}, @var{milu})\n@deftypefnx {} {[@var{L}, @var{U}, @var{P}] =} __ilu0__ (@var{A}, @var{milu})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value_list retval (2);\n\n  std::string milu = args(1).string_value ();\n\n  // In ILU0 algorithm the zero-pattern of the input matrix is preserved so\n  // its structure does not change during the algorithm.  The same input\n  // matrix is used to build the output matrix due to that fact.\n  octave_value_list arg_list;\n  if (! args(0).iscomplex ())\n    {\n      SparseMatrix sm = args(0).sparse_matrix_value ();\n      SparseMatrix speye (DiagMatrix (sm.cols (), sm.cols (), 1.0));\n\n      ilu_0<SparseMatrix, double> (sm, milu);\n\n      retval(0) = speye + Ftril (ovl (sm, -1))(0).sparse_matrix_value ();\n      retval(1) = Ftriu (ovl (sm))(0).sparse_matrix_value ();\n    }\n  else\n    {\n      SparseComplexMatrix sm = args(0).sparse_complex_matrix_value ();\n      SparseMatrix speye (DiagMatrix (sm.cols (), sm.cols (), 1.0));\n\n      ilu_0<SparseComplexMatrix, Complex> (sm, milu);\n\n      retval(0) = speye +\n                  Ftril (ovl (sm, -1))(0).sparse_complex_matrix_value ();\n      retval(1) = Ftriu (ovl (sm))(0).sparse_complex_matrix_value ();\n    }\n\n  return retval;\n}\n\ntemplate <typename octave_matrix_t, typename T>\nvoid\nilu_crout (octave_matrix_t& sm_l, octave_matrix_t& sm_u,\n           octave_matrix_t& L, octave_matrix_t& U, T *cols_norm,\n           T *rows_norm, const T droptol = 0,\n           const std::string milu = \"off\")\n{\n  // Map the strings into chars for faster comparing inside loops\n  char opt;\n  enum {OFF, ROW, COL};\n  if (milu == \"row\")\n    opt = ROW;\n  else if (milu == \"col\")\n    opt = COL;\n  else\n    opt = OFF;\n\n  octave_idx_type jrow, i, j, k, jj, total_len_l, total_len_u, max_len_u,\n                  max_len_l, w_len_u, w_len_l, cols_list_len, rows_list_len;\n\n  const octave_idx_type n = sm_u.cols ();\n  sm_u = sm_u.transpose ();\n\n  max_len_u = sm_u.nnz ();\n  max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;\n  max_len_l = sm_l.nnz ();\n  max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;\n\n  // Extract pointers to the arrays for faster access inside loops\n  octave_idx_type *cidx_in_u = sm_u.cidx ();\n  octave_idx_type *ridx_in_u = sm_u.ridx ();\n  T *data_in_u = sm_u.data ();\n  octave_idx_type *cidx_in_l = sm_l.cidx ();\n  octave_idx_type *ridx_in_l = sm_l.ridx ();\n  T *data_in_l = sm_l.data ();\n\n  // L output arrays\n  Array<octave_idx_type> ridx_out_l (dim_vector (max_len_l, 1));\n  octave_idx_type *ridx_l = ridx_out_l.rwdata ();\n  Array<T> data_out_l (dim_vector (max_len_l, 1));\n  T *data_l = data_out_l.rwdata ();\n\n  // U output arrays\n  Array<octave_idx_type> ridx_out_u (dim_vector (max_len_u, 1));\n  octave_idx_type *ridx_u = ridx_out_u.rwdata ();\n  Array<T> data_out_u (dim_vector (max_len_u, 1));\n  T *data_u = data_out_u.rwdata ();\n\n  // Working arrays\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, cidx_l, n + 1);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, cidx_u, n + 1);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, cols_list, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, rows_list, n);\n  OCTAVE_LOCAL_BUFFER (T, w_data_l, n);\n  OCTAVE_LOCAL_BUFFER (T, w_data_u, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Ufirst, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Lfirst, n);\n  OCTAVE_LOCAL_BUFFER (T, cr_sum, n);\n\n  T zero = T (0);\n\n  // Initialize working arrays\n  cidx_u[0] = cidx_in_u[0];\n  cidx_l[0] = cidx_in_l[0];\n  for (i = 0; i < n; i++)\n    {\n      w_data_u[i] = zero;\n      w_data_l[i] = zero;\n      cr_sum[i] = zero;\n    }\n\n  total_len_u = 0;\n  total_len_l = 0;\n  cols_list_len = 0;\n  rows_list_len = 0;\n\n  // Loop over all columns\n  for (k = 0; k < n; k++)\n    {\n      // Load the working column and working row\n      for (i = cidx_in_l[k]; i < cidx_in_l[k+1]; i++)\n        w_data_l[ridx_in_l[i]] = data_in_l[i];\n\n      for (i = cidx_in_u[k]; i < cidx_in_u[k+1]; i++)\n        w_data_u[ridx_in_u[i]] = data_in_u[i];\n\n      // Update U working row\n      for (j = 0; j < rows_list_len; j++)\n        {\n          if ((Ufirst[rows_list[j]] != -1))\n            for (jj = Ufirst[rows_list[j]]; jj < cidx_u[rows_list[j]+1]; jj++)\n              {\n                jrow = ridx_u[jj];\n                w_data_u[jrow] -= data_u[jj] * data_l[Lfirst[rows_list[j]]];\n              }\n        }\n      // Update L working column\n      for (j = 0; j < cols_list_len; j++)\n        {\n          if (Lfirst[cols_list[j]] != -1)\n            for (jj = Lfirst[cols_list[j]]; jj < cidx_l[cols_list[j]+1]; jj++)\n              {\n                jrow = ridx_l[jj];\n                w_data_l[jrow] -= data_l[jj] * data_u[Ufirst[cols_list[j]]];\n              }\n        }\n\n      if ((max_len_u - total_len_u) < n)\n        {\n          max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;\n          data_out_u.resize (dim_vector (max_len_u, 1));\n          data_u = data_out_u.rwdata ();\n          ridx_out_u.resize (dim_vector (max_len_u, 1));\n          ridx_u = ridx_out_u.rwdata ();\n        }\n\n      if ((max_len_l - total_len_l) < n)\n        {\n          max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;\n          data_out_l.resize (dim_vector (max_len_l, 1));\n          data_l = data_out_l.rwdata ();\n          ridx_out_l.resize (dim_vector (max_len_l, 1));\n          ridx_l = ridx_out_l.rwdata ();\n        }\n\n      // Expand the working row into the U output data structures\n      w_len_l = 0;\n      data_u[total_len_u] = w_data_u[k];\n      ridx_u[total_len_u] = k;\n      w_len_u = 1;\n      for (i = k + 1; i < n; i++)\n        {\n          if (w_data_u[i] != zero)\n            {\n              if (std::abs (w_data_u[i]) < (droptol * rows_norm[k]))\n                {\n                  if (opt == ROW)\n                    cr_sum[k] += w_data_u[i];\n                  else if (opt == COL)\n                    cr_sum[i] += w_data_u[i];\n                }\n              else\n                {\n                  data_u[total_len_u + w_len_u] = w_data_u[i];\n                  ridx_u[total_len_u + w_len_u] = i;\n                  w_len_u++;\n                }\n            }\n\n          // Expand the working column into the L output data structures\n          if (w_data_l[i] != zero)\n            {\n              if (std::abs (w_data_l[i]) < (droptol * cols_norm[k]))\n                {\n                  if (opt == COL)\n                    cr_sum[k] += w_data_l[i];\n                  else if (opt == ROW)\n                    cr_sum[i] += w_data_l[i];\n                }\n              else\n                {\n                  data_l[total_len_l + w_len_l] = w_data_l[i];\n                  ridx_l[total_len_l + w_len_l] = i;\n                  w_len_l++;\n                }\n            }\n          w_data_u[i] = zero;\n          w_data_l[i] = zero;\n        }\n\n      // Compensate row and column sums --> milu option\n      if (opt == COL || opt == ROW)\n        data_u[total_len_u] += cr_sum[k];\n\n      // Check if the pivot is zero\n      if (data_u[total_len_u] == zero)\n        error (\"ilu: encountered a pivot equal to 0\");\n\n      // Scale the elements in L by the pivot\n      for (i = total_len_l ; i < (total_len_l + w_len_l); i++)\n        data_l[i] /= data_u[total_len_u];\n\n      total_len_u += w_len_u;\n      total_len_l += w_len_l;\n      // Check if there are too many elements to be indexed with\n      // octave_idx_type type due to fill-in during the process.\n      if (total_len_l < 0 || total_len_u < 0)\n        error (\"ilu: integer overflow.  Too many fill-in elements in L or U\");\n\n      cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;\n      cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;\n\n      // The tricky part of the algorithm.  The arrays pointing to the first\n      // working element of each column in the next iteration (Lfirst) or\n      // the first working element of each row (Ufirst) are updated.  Also the\n      // arrays working as lists cols_list and rows_list are filled with\n      // indices pointing to Ufirst and Lfirst respectively.\n      // FIXME: Maybe the -1 indicating in Ufirst and Lfirst, that no elements\n      // have to be considered in a certain column or row in next iteration,\n      // can be removed.  It feels safer to me using such an indicator.\n      if (k < (n - 1))\n        {\n          if (w_len_u > 0)\n            Ufirst[k] = cidx_u[k];\n          else\n            Ufirst[k] = -1;\n          if (w_len_l > 0)\n            Lfirst[k] = cidx_l[k];\n          else\n            Lfirst[k] = -1;\n          cols_list_len = 0;\n          rows_list_len = 0;\n          for (i = 0; i <= k; i++)\n            {\n              if (Ufirst[i] != -1)\n                {\n                  jj = ridx_u[Ufirst[i]];\n                  if (jj < (k + 1))\n                    {\n                      if (Ufirst[i] < (cidx_u[i+1]))\n                        {\n                          Ufirst[i]++;\n                          if (Ufirst[i] == cidx_u[i+1])\n                            Ufirst[i] = -1;\n                          else\n                            jj = ridx_u[Ufirst[i]];\n                        }\n                    }\n                  if (jj == (k + 1))\n                    {\n                      cols_list[cols_list_len] = i;\n                      cols_list_len++;\n                    }\n                }\n\n              if (Lfirst[i] != -1)\n                {\n                  jj = ridx_l[Lfirst[i]];\n                  if (jj < (k + 1))\n                    if (Lfirst[i] < (cidx_l[i+1]))\n                      {\n                        Lfirst[i]++;\n                        if (Lfirst[i] == cidx_l[i+1])\n                          Lfirst[i] = -1;\n                        else\n                          jj = ridx_l[Lfirst[i]];\n                      }\n                  if (jj == (k + 1))\n                    {\n                      rows_list[rows_list_len] = i;\n                      rows_list_len++;\n                    }\n                }\n            }\n        }\n    }\n\n  // Build the output matrices\n  L = octave_matrix_t (n, n, total_len_l);\n  U = octave_matrix_t (n, n, total_len_u);\n\n  // FIXME: Can these loops be replaced by std::copy?\n  for (i = 0; i <= n; i++)\n    L.cidx (i) = cidx_l[i];\n\n  for (i = 0; i < total_len_l; i++)\n    {\n      L.ridx (i) = ridx_l[i];\n      L.data (i) = data_l[i];\n    }\n\n  for (i = 0; i <= n; i++)\n    U.cidx (i) = cidx_u[i];\n\n  for (i = 0; i < total_len_u; i++)\n    {\n      U.ridx (i) = ridx_u[i];\n      U.data (i) = data_u[i];\n    }\n\n  U = U.transpose ();\n}\n\nDEFUN (__iluc__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{L}, @var{U}] =} __iluc__ (@var{A}, @var{droptol}, @var{milu})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  double droptol = args(1).double_value ();\n  std::string milu = args(2).string_value ();\n\n  if (! args(0).iscomplex ())\n    {\n      SparseMatrix sm = args(0).sparse_matrix_value ();\n      SparseMatrix sm_u = Ftriu (ovl (sm))(0).sparse_matrix_value ();\n      SparseMatrix sm_l = Ftril (ovl (sm, -1))(0).sparse_matrix_value ();\n      SparseMatrix U, L;\n\n      RowVector sm_col_norms = xcolnorms (sm);\n      ColumnVector sm_row_norms = xrownorms (sm);\n      ilu_crout<SparseMatrix, double> (sm_l, sm_u, L, U,\n                                       sm_col_norms.rwdata (),\n                                       sm_row_norms.rwdata (),\n                                       droptol, milu);\n\n      SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0));\n\n      return ovl (L + speye, U);\n    }\n  else\n    {\n      SparseComplexMatrix sm = args(0).sparse_complex_matrix_value ();\n      SparseComplexMatrix sm_u = Ftriu (ovl (sm))(0).sparse_complex_matrix_value ();\n      SparseComplexMatrix sm_l = Ftril (ovl (sm, -1))(0).sparse_complex_matrix_value ();\n      SparseComplexMatrix U, L;\n      Array<Complex> cols_norm = xcolnorms (sm);\n      Array<Complex> rows_norm = xrownorms (sm);\n\n      ilu_crout<SparseComplexMatrix, Complex> (sm_l, sm_u, L, U,\n                                               cols_norm.rwdata (),\n                                               rows_norm.rwdata (),\n                                               Complex (droptol), milu);\n\n      SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0));\n\n      return ovl (L + speye, U);\n    }\n}\n\n// This function implements the IKJ and JKI variants of gaussian elimination\n// to perform the ILUTP decomposition.  The behavior is controlled by milu\n// parameter.  If milu = ['off'|'col'] the JKI version is performed taking\n// advantage of CCS format of the input matrix.  Row pivoting is performed.\n// If milu = 'row' the input matrix has to be transposed to obtain the\n// equivalent CRS structure so we can work efficiently with rows.  In that\n// case IKJ version is used and column pivoting is performed.\n\ntemplate <typename octave_matrix_t, typename T>\nvoid\nilu_tp (octave_matrix_t& sm, octave_matrix_t& L, octave_matrix_t& U,\n        octave_idx_type nnz_u, octave_idx_type nnz_l, T *cols_norm,\n        Array<octave_idx_type>& perm_vec, const T droptol = T(0),\n        const T thresh = T(0), const std::string milu = \"off\",\n        const double udiag = 0)\n{\n  char opt;\n  enum {OFF, ROW, COL};\n  if (milu == \"row\")\n    opt = ROW;\n  else if (milu == \"col\")\n    opt = COL;\n  else\n    opt = OFF;\n\n  const octave_idx_type n = sm.cols ();\n\n  // This is necessary for the JKI (milu = \"row\") variant.\n  if (opt == ROW)\n    sm = sm.transpose ();\n\n  // Extract pointers to the arrays for faster access inside loops\n  octave_idx_type *cidx_in = sm.cidx ();\n  octave_idx_type *ridx_in = sm.ridx ();\n  T *data_in = sm.data ();\n  octave_idx_type jrow, i, j, k, jj, c, total_len_l, total_len_u, p_perm,\n                  max_ind, max_len_l, max_len_u;\n  T zero = T(0);\n\n  T tl = zero, aux, maximum;\n\n  max_len_u = nnz_u;\n  max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;\n  max_len_l = nnz_l;\n  max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;\n\n  // Extract pointers to the arrays for faster access inside loops\n  Array<octave_idx_type> cidx_out_l (dim_vector (n + 1, 1));\n  octave_idx_type *cidx_l = cidx_out_l.rwdata ();\n  Array<octave_idx_type> ridx_out_l (dim_vector (max_len_l, 1));\n  octave_idx_type *ridx_l = ridx_out_l.rwdata ();\n  Array<T> data_out_l (dim_vector (max_len_l, 1));\n  T *data_l = data_out_l.rwdata ();\n\n  // Data for U\n  Array<octave_idx_type> cidx_out_u (dim_vector (n + 1, 1));\n  octave_idx_type *cidx_u = cidx_out_u.rwdata ();\n  Array<octave_idx_type> ridx_out_u (dim_vector (max_len_u, 1));\n  octave_idx_type *ridx_u = ridx_out_u.rwdata ();\n  Array<T> data_out_u (dim_vector (max_len_u, 1));\n  T *data_u = data_out_u.rwdata ();\n\n  // Working arrays and permutation arrays\n  octave_idx_type w_len_u, w_len_l;\n  T total_sum, partial_col_sum = zero, partial_row_sum = zero;\n  std::set<octave_idx_type> iw_l;\n  std::set<octave_idx_type> iw_u;\n  std::set<octave_idx_type>::iterator it, it2;\n  OCTAVE_LOCAL_BUFFER (T, w_data, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, iperm, n);\n  octave_idx_type *perm = perm_vec.rwdata ();\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, uptr, n);\n\n  // Initialize working and permutation arrays\n  cidx_l[0] = cidx_in[0];\n  cidx_u[0] = cidx_in[0];\n  for (i = 0; i < n; i++)\n    {\n      w_data[i] = 0;\n      perm[i] = i;\n      iperm[i] = i;\n    }\n  total_len_u = 0;\n  total_len_l = 0;\n\n  // Loop over all columns\n  for (k = 0; k < n; k++)\n    {\n      for (j = cidx_in[k]; j < cidx_in[k+1]; j++)\n        {\n          p_perm = iperm[ridx_in[j]];\n          w_data[iperm[ridx_in[j]]] = data_in[j];\n          if (p_perm > k)\n            iw_l.insert (ridx_in[j]);\n          else\n            iw_u.insert (p_perm);\n        }\n\n      it = iw_u.begin ();\n      total_sum = zero;\n      while (it != iw_u.end ())\n        {\n          jrow = *it;\n          if (jrow >= k)\n            break;\n\n          if (opt == COL)\n            partial_col_sum = w_data[jrow];\n          if (w_data[jrow] != zero)\n            {\n              if (opt == ROW)\n                {\n                  partial_row_sum = w_data[jrow];\n                  tl = w_data[jrow] / data_u[uptr[jrow]];\n                }\n              for (jj = cidx_l[jrow]; jj < cidx_l[jrow+1]; jj++)\n                {\n                  p_perm = iperm[ridx_l[jj]];\n                  aux = w_data[p_perm];\n                  if (opt == ROW)\n                    {\n                      w_data[p_perm] -= tl * data_l[jj];\n                      partial_row_sum += tl * data_l[jj];\n                    }\n                  else\n                    {\n                      tl = data_l[jj] * w_data[jrow];\n                      w_data[p_perm] -= tl;\n                      if (opt == COL)\n                        partial_col_sum += tl;\n                    }\n\n                  if ((aux == zero) && (w_data[p_perm] != zero))\n                    {\n                      if (p_perm > k)\n                        iw_l.insert (ridx_l[jj]);\n                      else\n                        iw_u.insert (p_perm);\n                    }\n                }\n\n              // Drop element from the U part in IKJ\n              // and L part in JKI variant (milu = [col|off])\n              if ((std::abs (w_data[jrow]) < (droptol * cols_norm[k]))\n                  && (w_data[jrow] != zero))\n                {\n                  if (opt == COL)\n                    total_sum += partial_col_sum;\n                  else if (opt == ROW)\n                    total_sum += partial_row_sum;\n                  w_data[jrow] = zero;\n                  it = iw_u.erase (it);  // Returns next valid iterator\n                  continue;\n                }\n              else\n                // This is the element scaled by the pivot\n                // in the actual iteration\n                if (opt == ROW)\n                  w_data[jrow] = tl;\n            }\n          ++it;  // Increment only when we did not erase\n        }\n\n      // Search for the pivot and update iw_l and iw_u if the pivot is not the\n      // diagonal element\n      if ((thresh > zero) && (k < (n - 1)))\n        {\n          maximum = std::abs (w_data[k]) / thresh;\n          max_ind = perm[k];\n          for (it = iw_l.begin (); it != iw_l.end (); ++it)\n            {\n              p_perm = iperm[*it];\n              if (std::abs (w_data[p_perm]) > maximum)\n                {\n                  maximum = std::abs (w_data[p_perm]);\n                  max_ind = *it;\n                  it2 = it;\n                }\n            }\n          // If the pivot is not the diagonal element update all\n          p_perm = iperm[max_ind];\n          if (max_ind != perm[k])\n            {\n              iw_l.erase (it2);\n              if (w_data[k] != zero)\n                iw_l.insert (perm[k]);\n              else\n                iw_u.insert (k);\n              // Update permutation vectors and swap data\n              iperm[perm[p_perm]] = k;\n              iperm[perm[k]] = p_perm;\n              std::swap (perm[k], perm[p_perm]);\n              std::swap (w_data[k], w_data[p_perm]);\n            }\n\n        }\n\n      // Drop elements in the L part in the IKJ version,\n      // and from the U part in the JKI version.\n      it = iw_l.begin ();\n      while (it != iw_l.end ())\n        {\n          p_perm = iperm[*it];\n          if (droptol > zero)\n            if (std::abs (w_data[p_perm]) < (droptol * cols_norm[k]))\n              {\n                if (opt != OFF)\n                  total_sum += w_data[p_perm];\n                w_data[p_perm] = zero;\n                it = iw_l.erase (it);\n                continue;\n              }\n\n          it++;\n        }\n\n      // If milu == [row|col] summation is preserved.\n      // Compensate diagonal element.\n      if (opt != OFF)\n        {\n          if ((total_sum > zero) && (w_data[k] == zero))\n            iw_u.insert (k);\n          w_data[k] += total_sum;\n        }\n\n      // Check if the pivot is zero and if udiag is active.\n      // NOTE: If the pivot == 0 and udiag is active, then if milu = [col|row]\n      //       will not preserve the row sum for that column/row.\n      if (w_data[k] == zero)\n        {\n          if (udiag != 1)\n            error (\"ilu: encountered a pivot equal to 0\");\n\n          w_data[k] = droptol;\n          iw_u.insert (k);\n        }\n\n      // Scale the elements on the L part for IKJ version (milu = [col|off])\n      if (opt != ROW)\n        for (it = iw_l.begin (); it != iw_l.end (); ++it)\n          {\n            p_perm = iperm[*it];\n            w_data[p_perm] = w_data[p_perm] / w_data[k];\n          }\n\n      if ((max_len_u - total_len_u) < n)\n        {\n          max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;\n          data_out_u.resize (dim_vector (max_len_u, 1));\n          data_u = data_out_u.rwdata ();\n          ridx_out_u.resize (dim_vector (max_len_u, 1));\n          ridx_u = ridx_out_u.rwdata ();\n        }\n\n      if ((max_len_l - total_len_l) < n)\n        {\n          max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;\n          data_out_l.resize (dim_vector (max_len_l, 1));\n          data_l = data_out_l.rwdata ();\n          ridx_out_l.resize (dim_vector (max_len_l, 1));\n          ridx_l = ridx_out_l.rwdata ();\n        }\n\n      // Expand working vector into U.\n      w_len_u = 0;\n      for (it = iw_u.begin (); it != iw_u.end (); ++it)\n        {\n          if (w_data[*it] != zero)\n            {\n              data_u[total_len_u + w_len_u] = w_data[*it];\n              ridx_u[total_len_u + w_len_u] = *it;\n              w_len_u++;\n            }\n          w_data[*it] = 0;\n        }\n\n      // Expand working vector into L.\n      w_len_l = 0;\n      for (it = iw_l.begin (); it != iw_l.end (); ++it)\n        {\n          p_perm = iperm[*it];\n          if (w_data[p_perm] != zero)\n            {\n              data_l[total_len_l + w_len_l] = w_data[p_perm];\n              ridx_l[total_len_l + w_len_l] = *it;\n              w_len_l++;\n            }\n          w_data[p_perm] = 0;\n        }\n      total_len_u += w_len_u;\n      total_len_l += w_len_l;\n\n      // Check if there are too many elements to be indexed with\n      // octave_idx_type type due to fill-in during the process.\n      if (total_len_l < 0 || total_len_u < 0)\n        error (\"ilu: Integer overflow.  Too many fill-in elements in L or U\");\n\n      if (opt == ROW)\n        uptr[k] = total_len_u - 1;\n\n      cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;\n      cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;\n\n      iw_l.clear ();\n      iw_u.clear ();\n    }\n\n  octave_matrix_t *L_ptr;\n  octave_matrix_t *U_ptr;\n  octave_matrix_t diag (n, n, n);\n\n  // L and U are interchanged if milu = 'row'.  It is a matter\n  // of nomenclature to re-use code with both IKJ and JKI\n  // versions of the algorithm.\n  if (opt == ROW)\n    {\n      L_ptr = &U;\n      U_ptr = &L;\n      L = octave_matrix_t (n, n, total_len_u - n);\n      U = octave_matrix_t (n, n, total_len_l);\n    }\n  else\n    {\n      L_ptr = &L;\n      U_ptr = &U;\n      L = octave_matrix_t (n, n, total_len_l);\n      U = octave_matrix_t (n, n, total_len_u);\n    }\n\n  for (i = 0; i <= n; i++)\n    {\n      L_ptr->cidx (i) = cidx_l[i];\n      U_ptr->cidx (i) = cidx_u[i];\n      if (opt == ROW)\n        U_ptr->cidx (i) -= i;\n    }\n\n  for (i = 0; i < n; i++)\n    {\n      if (opt == ROW)\n        diag.elem (i, i) = data_u[uptr[i]];\n      j = cidx_l[i];\n\n      while (j < cidx_l[i+1])\n        {\n          L_ptr->ridx (j) = ridx_l[j];\n          L_ptr->data (j) = data_l[j];\n          j++;\n        }\n      j = cidx_u[i];\n\n      while (j < cidx_u[i+1])\n        {\n          c = j;\n          if (opt == ROW)\n            {\n              // The diagonal is removed from L if milu = 'row'.\n              // That is because is convenient to have it inside\n              // the L part to carry out the process.\n              if (ridx_u[j] == i)\n                {\n                  j++;\n                  continue;\n                }\n              else\n                c -= i;\n            }\n          U_ptr->data (c) = data_u[j];\n          U_ptr->ridx (c) = ridx_u[j];\n          j++;\n        }\n    }\n\n  if (opt == ROW)\n    {\n      U = U.transpose ();\n      // The diagonal, conveniently permuted is added to U\n      U += diag.index (idx_vector::colon, perm_vec);\n      L = L.transpose ();\n    }\n}\n\nDEFUN (__ilutp__, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{L}, @var{U}] =} __ilutp__ (@var{A}, @var{droptol}, @var{thresh}, @var{milu}, @var{udiag})\n@deftypefnx {} {[@var{L}, @var{U}, @var{P}] =} __ilutp__ (@dots{})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 5)\n    print_usage ();\n\n  octave_value_list retval;\n  double droptol = args(1).double_value ();\n  double thresh = args(2).double_value ();\n  std::string milu = args(3).string_value ();\n  double udiag = args(4).double_value ();\n\n  octave_value_list arg_list;\n  octave_idx_type nnz_u, nnz_l;\n  if (! args(0).iscomplex ())\n    {\n      SparseMatrix sm = args(0).sparse_matrix_value ();\n      SparseMatrix U, L;\n      nnz_u = (Ftriu (ovl (sm))(0).sparse_matrix_value ()).nnz ();\n      nnz_l = (Ftril (ovl (sm, -1))(0).sparse_matrix_value ()).nnz ();\n      Array<double> rc_norm;\n      if (milu == \"row\")\n        rc_norm = xrownorms (sm);\n      else\n        rc_norm = xcolnorms (sm);\n      Array<octave_idx_type> perm (dim_vector (sm.cols (), 1));\n\n      ilu_tp<SparseMatrix, double> (sm, L, U, nnz_u, nnz_l,\n                                    rc_norm.rwdata (),\n                                    perm, droptol, thresh, milu, udiag);\n\n      SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0));\n      if (milu == \"row\")\n        {\n          retval(0) = L + speye;\n          if (nargout == 3)\n            {\n              retval(1) = U.index (idx_vector::colon, perm);\n              retval(2) = speye.index (idx_vector::colon, perm);\n            }\n          else\n            retval(1) = U;\n        }\n      else\n        {\n          retval(1) = U;\n          if (nargout == 3)\n            {\n              retval(0) = L.index (perm, idx_vector::colon) + speye;\n              retval(2) = speye.index (perm, idx_vector::colon);\n            }\n          else\n            retval(0) = L + speye.index (idx_vector::colon, perm);\n        }\n    }\n  else\n    {\n      SparseComplexMatrix sm = args(0).sparse_complex_matrix_value ();\n      SparseComplexMatrix U, L;\n      nnz_u = (Ftriu (ovl (sm))(0).sparse_complex_matrix_value ()).nnz ();\n      nnz_l = (Ftril (ovl (sm, -1))(0).sparse_complex_matrix_value ()).nnz ();\n      Array<Complex> rc_norm;\n      if (milu == \"row\")\n        rc_norm = xrownorms (sm);\n      else\n        rc_norm = xcolnorms (sm);\n      Array<octave_idx_type> perm (dim_vector (sm.cols (), 1));\n\n      ilu_tp<SparseComplexMatrix, Complex>\n      (sm, L, U, nnz_u, nnz_l, rc_norm.rwdata (), perm,\n       Complex (droptol), Complex (thresh), milu, udiag);\n\n      SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0));\n      if (milu == \"row\")\n        {\n          retval(0) = L + speye;\n          if (nargout == 3)\n            {\n              retval(1) = U.index (idx_vector::colon, perm);\n              retval(2) = speye.index (idx_vector::colon, perm);\n            }\n          else if (nargout == 2)\n            retval(1) = U;\n        }\n      else\n        {\n          retval(1) = U;\n          if (nargout == 3)\n            {\n              retval(0) = L.index (perm, idx_vector::colon) + speye;\n              retval(2) = speye.index (perm, idx_vector::colon);\n            }\n          else\n            retval(0) = L + speye.index (idx_vector::colon, perm);\n        }\n    }\n\n  return retval;\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__isprimelarge__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// This function implements the Schrage technique for modular multiplication.\n// The returned value is equivalent to \"mod (a*b, modulus)\"\n// but calculated without overflow.\nuint64_t\nsafemultiply (uint64_t a, uint64_t b, uint64_t modulus)\n{\n  if (! a || ! b)\n    return 0;\n  else if (b == 1)\n    return a;\n  else if (a == 1)\n    return b;\n  else if (a > b)\n    {\n      uint64_t tmp = a;\n      a = b;\n      b = tmp;\n    }\n\n  uint64_t q = modulus / a;\n  uint64_t r = modulus - q * a;\n  uint64_t term1 = a * (b % q);\n  uint64_t term2 = (r < q) ? r * (b / q) : safemultiply (r, b / q, modulus);\n  return (term1 > term2) ? (term1 - term2) : (term1 + modulus - term2);\n}\n\n// This function returns \"mod (a^b, modulus)\"\n// but calculated without overflow.\nuint64_t\nsafepower (uint64_t a, uint64_t b, uint64_t modulus)\n{\n  uint64_t retval = 1;\n  while (b > 0)\n    {\n      if (b & 1)\n        retval = safemultiply (retval, a, modulus);\n      b >>= 1;\n      a = safemultiply (a, a, modulus);\n    }\n  return retval;\n}\n\n// This function implements a single round of Miller-Rabin primality testing.\n// Returns false if composite, true if pseudoprime for this divisor.\nbool\nmillerrabin (uint64_t div, uint64_t d, uint64_t r, uint64_t n)\n{\n  uint64_t x = safepower (div, d, n);\n  if (x == 1 || x == n-1)\n    return true;\n\n  for (uint64_t j = 1; j < r; j++)\n    {\n      x = safemultiply (x, x, n);\n      if (x == n-1)\n        return true;\n    }\n  return false;\n}\n\n// This function uses the Miller-Rabin test to find out whether the input is\n// prime or composite.  The input is required to be a scalar 64-bit integer.\nbool\nisprimescalar (uint64_t n)\n{\n  // Fast return for even numbers.\n  // n==2 is excluded by the time this function is called.\n  if (! (n & 1))\n    return false;\n\n  // n is now odd.  Rewrite n as d * 2^r + 1, where d is odd.\n  uint64_t d = n-1;\n  uint64_t r = 0;\n  while (! (d & 1))\n    {\n      d >>= 1;\n      r++;\n    }\n\n  // Miller-Rabin test with the first 12 primes.\n  // If the number passes all 12 tests, then it is prime.\n  // If it fails any, then it is composite.\n  // The first 12 primes suffice to test all 64-bit integers.\n  return millerrabin ( 2, d, r, n) && millerrabin ( 3, d, r, n)\n         && millerrabin ( 5, d, r, n) && millerrabin ( 7, d, r, n)\n         && millerrabin (11, d, r, n) && millerrabin (13, d, r, n)\n         && millerrabin (17, d, r, n) && millerrabin (19, d, r, n)\n         && millerrabin (23, d, r, n) && millerrabin (29, d, r, n)\n         && millerrabin (31, d, r, n) && millerrabin (37, d, r, n);\n\n  /*\n  Mathematical references for the curious as to why we need only\n  the 12 smallest primes for testing all 64-bit numbers:\n  (1) https://oeis.org/A014233\n      Comment: a(12) > 2^64.  Hence the primality of numbers < 2^64 can be\n      determined by asserting strong pseudoprimality to all prime bases <= 37\n      (=prime(12)). Testing to prime bases <=31 does not suffice,\n      as a(11) < 2^64 and a(11) is a strong pseudoprime\n      to all prime bases <= 31 (=prime(11)). - Joerg Arndt, Jul 04 2012\n  (2) https://arxiv.org/abs/1509.00864\n      Strong Pseudoprimes to Twelve Prime Bases\n      Jonathan P. Sorenson, Jonathan Webster\n\n  In addition, a source listed here: https://miller-rabin.appspot.com/\n  reports that all 64-bit numbers can be covered with only 7 divisors,\n  namely 2, 325, 9375, 28178, 450775, 9780504, and 1795265022.\n  There was no peer-reviewed article to back it up though,\n  so this code uses the 12 primes <= 37.\n  */\n\n}\n\nDEFUN (__isprimelarge__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{x} =} __isprimelarge__ (@var{n})\nUse the Miller-Rabin test to find out whether the elements of N are prime or\ncomposite.  The input N is required to be a vector or array of 64-bit integers.\nYou should call isprime(N) instead of directly calling this function.\n\n@seealso{isprime, factor}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  // This function is intended for internal use by isprime.m,\n  // so the following error handling should not be necessary.  But it is\n  // probably good practice for any curious users calling it directly.\n  uint64NDArray vec = args(0).xuint64_array_value\n                      (\"__isprimelarge__: unable to convert input.  Call isprime() instead.\");\n\n  boolNDArray retval (vec.dims(), false);\n\n  for (octave_idx_type i = vec.numel() - 1; i >= 0; i--)\n    retval(i) = isprimescalar (vec(i));\n  // Note: If vec(i) <= 37, this function could go into an infinite loop.\n  // That situation does not arise when calling this from isprime.m\n  // but it could arise if the user calls this function directly with low input\n  // or negative input.\n  // But it turns out that adding this validation:\n  //   \"if (vec(i) <= 37) then raise an error else call isprimescalar (vec(i))\"\n  // slows this function down by over 20% for some inputs,\n  // so it is better to leave all the input validation in isprime.m\n  // and not add it here.  The function DOCSTRING now explicitly says:\n  // \"You should call isprime(N) instead of directly calling this function.\"\n\n  return ovl (retval);\n}\n\n/*\n%!assert (__isprimelarge__ (41:50), logical ([1 0 1 0 0 0 1 0 0 0]))\n%!assert (__isprimelarge__ (uint64 (12345)), false)\n%!assert (__isprimelarge__ (uint64 (2147483647)), true)\n%!assert (__isprimelarge__ (uint64 (2305843009213693951)), true)\n%!assert (__isprimelarge__ (uint64 (18446744073709551557)), true)\n\n%!assert (__isprimelarge__ ([uint64(12345), uint64(2147483647), ...\n%!                           uint64(2305843009213693951), ...\n%!                           uint64(18446744073709551557)]),\n%!        logical ([0 1 1 1]))\n\n%!error <unable to convert input> (__isprimelarge__ ({'foo'; 'bar'}))\n*/\n\n\n// This function implements a fast, private GCD function\n// optimized for uint64_t.  No input validation by design.\ninline\nuint64_t\nlocalgcd (uint64_t a, uint64_t b)\n{\n  return (a <= b) ? ( (b % a == 0) ? a : localgcd (a, b % a) )\n         : ( (a % b == 0) ? b : localgcd (a % b, b) );\n}\n\n// This function implements a textbook version of the Pollard Rho\n// factorization algorithm with Brent update.\n// The code is short and simple, but the math behind it is complicated.\nuint64_t\npollardrho (uint64_t n, uint64_t c = 1)\n{\n  uint64_t i = 1, j = 2;    // cycle index values\n  uint64_t x = (c+1) % n;   // can also be rand () % n\n  uint64_t y = x;           // other value in the chain\n  uint64_t g = 0;           // GCD\n\n  while (true)\n    {\n      i++;\n\n      // Calculate x = mod (x^2 + c, n) without overflow.\n      x = safemultiply (x, x, n) + c;\n      if (x >= n)\n        x -= n;\n\n      // Calculate GCD (abs (x-y), n).\n      g = (x > y) ? localgcd (x - y, n) : (x < y) ? localgcd (y - x, n) : 0;\n\n      if (i == j)  // cycle detected ==> double j\n        {\n          y = x;\n          j <<= 1;\n        }\n\n      if (g == n || i > 1000000)  // cut losses, restart with a different c\n        return pollardrho (n, c + 2);\n\n      if (g > 1)  // found GCD ==> exit loop properly\n        return g;\n    }\n}\n\nDEFUN (__pollardrho__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{x} =} __pollardrho__ (@var{n})\nPrivate function.  Use the Pollard Rho test to find a factor of @var{n}.\nThe input @var{n} is required to be a composite 64-bit integer.\nDo not pass it a prime input!  You should call factor(@var{n}) instead\nof directly calling this function.\n\n@seealso{isprime, factor}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_uint64 inp = args(0).xuint64_scalar_value\n                      (\"__pollardrho__: unable to convert input.  Call factor() instead.\");\n\n  uint64_t n = inp;\n  octave_uint64 retval = pollardrho (n);\n\n  return ovl (retval);\n}\n\n/*\n%!assert (__pollardrho__ (uint64 (78567695338254293)), uint64 (443363))\n%!assert (__pollardrho__ (1084978968791), uint64 (832957))\n\n%!error <unable to convert input> (__pollardrho__ ({'foo'; 'bar'}))\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__lin_interpn__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"dNDArray.h\"\n#include \"oct-locbuf.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\n#include <type_traits>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// equivalent to isvector.m\n\ntemplate <typename T>\nbool\nisvector (const T& array)\n{\n  const dim_vector dv = array.dims ();\n  return dv.ndims () == 2 && (dv(0) == 1 || dv(1) == 1);\n}\n\n// lookup a value in a sorted table (lookup.m)\ntemplate <typename T>\noctave_idx_type\nlookup (const T *x, octave_idx_type n, T y)\n{\n  octave_idx_type j;\n\n  if (x[0] < x[n-1])\n    {\n      // increasing x\n\n      if (y > x[n-1] || y < x[0])\n        return -1;\n\n#if defined (EXHAUSTIF)\n      for (j = 0; j < n - 1; j++)\n        {\n          if (x[j] <= y && y <= x[j+1])\n            return j;\n        }\n#else\n      octave_idx_type j0 = 0;\n      octave_idx_type j1 = n - 1;\n\n      while (true)\n        {\n          j = (j0+j1)/2;\n\n          if (y <= x[j+1])\n            {\n              if (x[j] <= y)\n                return j;\n\n              j1 = j;\n            }\n\n          if (x[j] <= y)\n            j0 = j;\n        }\n#endif\n    }\n  else\n    {\n      // decreasing x\n      // previous code with x -> -x and y -> -y\n\n      if (y > x[0] || y < x[n-1])\n        return -1;\n\n#if defined (EXHAUSTIF)\n      for (j = 0; j < n - 1; j++)\n        {\n          if (x[j+1] <= y && y <= x[j])\n            return j;\n        }\n#else\n      octave_idx_type j0 = 0;\n      octave_idx_type j1 = n - 1;\n\n      while (true)\n        {\n          j = (j0+j1)/2;\n\n          if (y >= x[j+1])\n            {\n              if (x[j] >= y)\n                return j;\n\n              j1 = j;\n            }\n\n          if (x[j] >= y)\n            j0 = j;\n        }\n#endif\n    }\n}\n\n// N-dimensional linear interpolation\n\ntemplate <typename T, typename DT>\nvoid\nlin_interpn (int n, const octave_idx_type *size, const octave_idx_type *scale,\n             octave_idx_type Ni, DT extrapval, const T **x,\n             const DT *v, const T **y, DT *vi)\n{\n  bool out = false;\n  int bit;\n\n  OCTAVE_LOCAL_BUFFER (T, coef, 2*n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, index, n);\n\n  // loop over all points\n  for (octave_idx_type m = 0; m < Ni; m++)\n    {\n      // loop over all dimensions\n      for (int i = 0; i < n; i++)\n        {\n          index[i] = lookup (x[i], size[i], y[i][m]);\n          out = index[i] == -1;\n\n          if (out)\n            break;\n          else\n            {\n              octave_idx_type j = index[i];\n              coef[2*i+1] = (y[i][m] - x[i][j])/(x[i][j+1] - x[i][j]);\n              coef[2*i] = 1 - coef[2*i+1];\n            }\n        }\n\n      if (out)\n        vi[m] = extrapval;\n      else\n        {\n          vi[m] = 0;\n\n          // loop over all corners of hypercube (1<<n = 2^n)\n          for (int i = 0; i < (1 << n); i++)\n            {\n              T c = 1;\n              octave_idx_type l = 0;\n\n              // loop over all dimensions\n              for (int j = 0; j < n; j++)\n                {\n                  // test if the jth bit in i is set\n                  bit = i >> j & 1;\n                  l += scale[j] * (index[j] + bit);\n                  c *= coef[2*j+bit];\n                }\n\n              vi[m] += c * v[l];\n            }\n        }\n    }\n}\n\ntemplate <typename MT, typename DMT, typename DT>\noctave_value\nlin_interpn (int n, MT *X, const DMT V, MT *Y, DT extrapval)\n{\n  static_assert(std::is_same<DT, typename DMT::element_type>::value,\n                \"Type DMT must be an ArrayType with elements of type DT.\");\n  using T = typename MT::element_type;\n\n  octave_value retval;\n\n  DMT Vi = DMT (Y[0].dims ());\n\n  OCTAVE_LOCAL_BUFFER (const T *, y, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, size, n);\n\n  for (int i = 0; i < n; i++)\n    {\n      y[i] = Y[i].data ();\n      size[i] = V.dims ()(i);\n    }\n\n  OCTAVE_LOCAL_BUFFER (const T *, x, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, scale, n);\n\n  const DT *v = V.data ();\n  DT *vi = Vi.rwdata ();\n  octave_idx_type Ni = Vi.numel ();\n\n  // offset in memory of each dimension\n\n  scale[0] = 1;\n\n  for (int i = 1; i < n; i++)\n    scale[i] = scale[i-1] * size[i-1];\n\n  // tests if X[0] is a vector, if yes, assume that all elements of X are\n  // in the ndgrid format.\n\n  if (! isvector (X[0]))\n    {\n      for (int i = 0; i < n; i++)\n        {\n          if (X[i].dims () != V.dims ())\n            error (\"interpn: incompatible size of argument number %d\", i+1);\n\n          MT tmp = MT (dim_vector (size[i], 1));\n\n          for (octave_idx_type j = 0; j < size[i]; j++)\n            tmp(j) = X[i](scale[i]*j);\n\n          X[i] = tmp;\n        }\n    }\n\n  for (int i = 0; i < n; i++)\n    {\n      if (! isvector (X[i]) && X[i].numel () != size[i])\n        error (\"interpn: incompatible size of argument number %d\", i+1);\n\n      x[i] = X[i].data ();\n    }\n\n  lin_interpn (n, size, scale, Ni, extrapval, x, v, y, vi);\n\n  retval = Vi;\n\n  return retval;\n}\n\n// Perform @var{n}-dimensional interpolation.  Each element of then\n// @var{n}-dimensional array @var{v} represents a value at a location\n// given by the parameters @var{x1}, @var{x2},...,@var{xn}.  The parameters\n// @var{x1}, @var{x2}, @dots{}, @var{xn} are either @var{n}-dimensional\n// arrays of the same size as the array @var{v} in the \"ndgrid\" format\n// or vectors.  The parameters @var{y1}, @var{y2}, @dots{}, @var{yn} are\n// all @var{n}-dimensional arrays of the same size and represent the\n// points at which the array @var{vi} is interpolated.\n//\n//This function only performs linear interpolation.\n\nDEFUN (__lin_interpn__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{vi} =} __lin_interpn__ (@var{x1}, @var{x2}, @dots{}, @var{xn}, @var{v}, @var{y1}, @var{y2}, @dots{}, @var{yn})\nUndocumented internal function.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin % 2 == 0)\n    print_usage ();\n\n  octave_value retval;\n\n  // dimension of the problem\n  int n = (nargin-1)/2;\n\n  if (args(n).is_single_type ())\n    {\n      OCTAVE_LOCAL_BUFFER (FloatNDArray, X, n);\n      OCTAVE_LOCAL_BUFFER (FloatNDArray, Y, n);\n\n      for (int i = 0; i < n; i++)\n        {\n          X[i] = args(i).float_array_value ();\n          Y[i] = args(n+i+1).float_array_value ();\n\n          if (Y[0].dims () != Y[i].dims ())\n            error (\"interpn: incompatible size of argument number %d\", n+i+2);\n        }\n\n      if (args(n).iscomplex ())\n        {\n          const FloatComplexNDArray V = args(n).float_complex_array_value ();\n          FloatComplex extrapval (octave_NA, octave_NA);\n          retval = lin_interpn (n, X, V, Y, extrapval);\n        }\n      else\n        {\n          const FloatNDArray V = args(n).float_array_value ();\n          float extrapval = octave_NA;\n          retval = lin_interpn (n, X, V, Y, extrapval);\n        }\n    }\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (NDArray, X, n);\n      OCTAVE_LOCAL_BUFFER (NDArray, Y, n);\n\n      for (int i = 0; i < n; i++)\n        {\n          X[i] = args(i).array_value ();\n          Y[i] = args(n+i+1).array_value ();\n\n          if (Y[0].dims () != Y[i].dims ())\n            error (\"interpn: incompatible size of argument number %d\", n+i+2);\n        }\n\n      if (args(n).iscomplex ())\n        {\n          const ComplexNDArray V = args(n).complex_array_value ();\n          Complex extrapval (octave_NA, octave_NA);\n          retval = lin_interpn (n, X, V, Y, extrapval);\n        }\n      else\n        {\n          const NDArray V = args(n).array_value ();\n          double extrapval = octave_NA;\n          retval = lin_interpn (n, X, V, Y, extrapval);\n        }\n    }\n\n  return retval;\n}\n\n/*\n## Test that real and imaginary parts are interpolated the same way\n## and outer points are set to NA + 1i*NA\n%!test <*61907>\n%! x1 = 1:3;\n%! x2 = 1:4;\n%! v = repmat(1:4, 3, 1) + 1i * repmat((1:3)', 1, 4);\n%! [XI2, XI1] = meshgrid(1.5:3.5, 1.5:3.5);\n%! vi_complex = __lin_interpn__ (x1, x2, v, XI1, XI2);\n%! vi_real = __lin_interpn__ (x1, x2, real (v), XI1, XI2);\n%! vi_imag = __lin_interpn__ (x1, x2, imag (v), XI1, XI2);\n%! assert (real (vi_complex), vi_real);\n%! assert (imag (vi_complex), vi_imag);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__pchip_deriv__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"slatec-proto.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n#include \"f77-fcn.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Wrapper for SLATEC/PCHIP function DPCHIM to calculate the derivates\n// for piecewise polynomials.\n\nDEFUN (__pchip_deriv__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{d} =} __pchip_deriv__ (@var{x}, @var{y}, @var{dim})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n  int nargin = args.length ();\n\n  bool rows = (nargin == 3 && args(2).uint_value () == 2);\n\n  if (nargin >= 2)\n    {\n      if (args(0).is_single_type () || args(1).is_single_type ())\n        {\n          FloatColumnVector xvec (args(0).float_vector_value ());\n          F77_INT nx = to_f77_int (xvec.numel ());\n          if (nx < 2)\n            error (\"__pchip_deriv__: X must be at least of length 2\");\n\n          if (args(1).iscomplex ())\n            {\n              FloatComplexMatrix ymat (args(1).float_complex_matrix_value ());\n\n              octave_idx_type nyr = ymat.rows ();\n              octave_idx_type nyc = ymat.columns ();\n\n              if (nx != (rows ? nyc : nyr))\n                error (\"__pchip_deriv__: X and Y dimension mismatch\");\n\n              FloatComplexMatrix dmat (nyr, nyc);\n\n              F77_INT ierr;\n              const F77_INT incfd = (rows ? to_f77_int (2*nyr) : 2);\n              const octave_idx_type inc = (rows ? 2 : 2*nyr);\n              octave_idx_type k = 0;\n\n              for (octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)\n                {\n                  F77_XFCN (pchim, PCHIM, (nx, xvec.data (),\n                                           reinterpret_cast<float const *> (ymat.data ()) + k * inc,\n                                           reinterpret_cast<float *> (dmat.rwdata ()) + k * inc,\n                                           incfd, ierr));\n\n                  if (ierr < 0)\n                    error (\"__pchip_deriv__: PCHIM failed for real part with ierr = %\"\n                           OCTAVE_F77_INT_TYPE_FORMAT, ierr);\n\n                  F77_XFCN (pchim, PCHIM, (nx, xvec.data (),\n                                           reinterpret_cast<float const *> (ymat.data ()) + 1 + k * inc,\n                                           reinterpret_cast<float *> (dmat.rwdata ()) + 1 + k * inc,\n                                           incfd, ierr));\n\n                  if (ierr < 0)\n                    error (\"__pchip_deriv__: PCHIM failed for imaginary part with ierr = %\"\n                           OCTAVE_F77_INT_TYPE_FORMAT, ierr);\n\n                  k++;\n                }\n\n              retval = dmat;\n            }\n          else\n            {\n              FloatMatrix ymat (args(1).float_matrix_value ());\n\n              octave_idx_type nyr = ymat.rows ();\n              octave_idx_type nyc = ymat.columns ();\n\n              if (nx != (rows ? nyc : nyr))\n                error (\"__pchip_deriv__: X and Y dimension mismatch\");\n\n              FloatMatrix dmat (nyr, nyc);\n\n              F77_INT ierr;\n              const F77_INT incfd = (rows ? to_f77_int (nyr) : 1);\n              const octave_idx_type inc = (rows ? 1 : nyr);\n              octave_idx_type k = 0;\n\n              for (octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)\n                {\n                  F77_XFCN (pchim, PCHIM, (nx, xvec.data (),\n                                           ymat.data () + k * inc,\n                                           dmat.rwdata () + k * inc,\n                                           incfd, ierr));\n\n                  k++;\n\n                  if (ierr < 0)\n                    error (\"__pchip_deriv__: PCHIM failed with ierr = %\"\n                           OCTAVE_F77_INT_TYPE_FORMAT, ierr);\n                }\n\n              retval = dmat;\n            }\n        }\n      else\n        {\n          ColumnVector xvec (args(0).vector_value ());\n          F77_INT nx = to_f77_int (xvec.numel ());\n          if (nx < 2)\n            error (\"__pchip_deriv__: X must be at least of length 2\");\n\n          if (args(1).iscomplex ())\n            {\n              ComplexMatrix ymat (args(1).complex_matrix_value ());\n\n              octave_idx_type nyr = ymat.rows ();\n              octave_idx_type nyc = ymat.columns ();\n\n              if (nx != (rows ? nyc : nyr))\n                error (\"__pchip_deriv__: X and Y dimension mismatch\");\n\n              ComplexMatrix dmat (nyr, nyc);\n\n              F77_INT ierr;\n              const F77_INT incfd = (rows ? to_f77_int (2*nyr) : 2);\n              const octave_idx_type inc = (rows ? 2 : 2*nyr);\n              octave_idx_type k = 0;\n\n              for (octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)\n                {\n                  F77_XFCN (dpchim, DPCHIM, (nx, xvec.data (),\n                                             reinterpret_cast<double const *> (ymat.data ()) + k * inc,\n                                             reinterpret_cast<double *> (dmat.rwdata ()) + k * inc,\n                                             incfd, ierr));\n\n                  if (ierr < 0)\n                    error (\"__pchip_deriv__: DPCHIM failed for real part with ierr = %\"\n                           OCTAVE_F77_INT_TYPE_FORMAT, ierr);\n\n                  F77_XFCN (dpchim, DPCHIM, (nx, xvec.data (),\n                                             reinterpret_cast<double const *> (ymat.data ()) + 1 + k * inc,\n                                             reinterpret_cast<double *> (dmat.rwdata ()) + 1 + k * inc,\n                                             incfd, ierr));\n\n                  if (ierr < 0)\n                    error (\"__pchip_deriv__: DPCHIM failed for imaginary part with ierr = %\"\n                           OCTAVE_F77_INT_TYPE_FORMAT, ierr);\n\n                  k++;\n                }\n\n              retval = dmat;\n            }\n          else\n            {\n              Matrix ymat (args(1).matrix_value ());\n\n              octave_idx_type nyr = ymat.rows ();\n              octave_idx_type nyc = ymat.columns ();\n\n              if (nx != (rows ? nyc : nyr))\n                error (\"__pchip_deriv__: X and Y dimension mismatch\");\n\n              Matrix dmat (nyr, nyc);\n\n              F77_INT ierr;\n              const F77_INT incfd = (rows ? to_f77_int (nyr) : 1);\n              const octave_idx_type inc = (rows ? 1 : nyr);\n              octave_idx_type k = 0;\n\n              for (octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)\n                {\n                  F77_XFCN (dpchim, DPCHIM, (nx, xvec.data (),\n                                             ymat.data () + k * inc,\n                                             dmat.rwdata () + k * inc,\n                                             incfd, ierr));\n                  k++;\n\n                  if (ierr < 0)\n                    error (\"__pchip_deriv__: DPCHIM failed with ierr = %\"\n                           OCTAVE_F77_INT_TYPE_FORMAT, ierr);\n                }\n\n              retval = dmat;\n            }\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!shared x, y\n%! x = 0:3;\n%! y = x.^2 + 1i * x.^3;\n\n%!test\n%! d_complex = __pchip_deriv__ (x, y, 2);\n%! d_real = __pchip_deriv__ (x, real (y), 2);\n%! d_imag = __pchip_deriv__ (x, imag (y), 2);\n%! assert (real (d_complex), d_real);\n%! assert (imag (d_complex), d_imag);\n\n%!test\n%! d_complex = __pchip_deriv__ (x.', y.');\n%! d_real = __pchip_deriv__ (x.', real (y.'));\n%! d_imag = __pchip_deriv__ (x.', imag (y.'));\n%! assert (real (d_complex), d_real);\n%! assert (imag (d_complex), d_imag);\n\n%!test\n%! d_complex = __pchip_deriv__ (single (x), single (y), 2);\n%! d_real = __pchip_deriv__ (single (x), real (single (y)), 2);\n%! d_imag = __pchip_deriv__ (single (x), imag (single (y)), 2);\n%! assert (real (d_complex), d_real);\n%! assert (imag (d_complex), d_imag);\n\n%!test\n%! d_complex = __pchip_deriv__ (single (x'), single (y'));\n%! d_real = __pchip_deriv__ (single (x'), real (single (y')));\n%! d_imag = __pchip_deriv__ (single (x'), imag (single (y')));\n%! assert (real (d_complex), d_real);\n%! assert (imag (d_complex), d_imag);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/__qp__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <limits>\n\n#include \"chol.h\"\n#include \"svd.h\"\n#include \"mx-m-dm.h\"\n#include \"EIG.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"pr-output.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic octave_idx_type\nmin_index (const ColumnVector& x)\n{\n  double min_val = x.min ();\n\n  for (octave_idx_type i = 0; i < x.numel (); i++)\n    if (min_val == x.xelem (i))\n      return i;\n\n  return 0;\n}\n\nstatic Matrix\nnull (const Matrix& A, octave_idx_type& rank)\n{\n  Matrix retval;\n\n  rank = 0;\n\n  if (! A.isempty ())\n    {\n      math::svd<Matrix> A_svd (A);\n\n      DiagMatrix S = A_svd.singular_values ();\n\n      ColumnVector s = S.extract_diag ();\n\n      Matrix V = A_svd.right_singular_matrix ();\n\n      octave_idx_type A_nr = A.rows ();\n      octave_idx_type A_nc = A.cols ();\n\n      octave_idx_type tmp = (A_nr > A_nc ? A_nr : A_nc);\n\n      double tol = tmp * s(0) * std::numeric_limits<double>::epsilon ();\n\n      octave_idx_type n = s.numel ();\n\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          if (s(i) > tol)\n            rank++;\n        }\n\n      if (rank < A_nc)\n        retval = V.extract (0, rank, A_nc-1, A_nc-1);\n      else\n        retval.resize (A_nc, 0);\n\n      for (octave_idx_type i = 0; i < retval.numel (); i++)\n        if (std::abs (retval(i)) < std::numeric_limits<double>::epsilon ())\n          retval(i) = 0;\n    }\n\n  return retval;\n}\n\nstatic int\nqp (const Matrix& H, const ColumnVector& q,\n    const Matrix& Aeq, const ColumnVector& beq,\n    const Matrix& Ain, const ColumnVector& bin,\n    int maxit, double rtol,\n    ColumnVector& x, ColumnVector& lambda, int& iter)\n{\n  int info = 0;\n\n  iter = 0;\n\n  // Problem dimension.\n  octave_idx_type n = x.numel ();\n\n  // Dimension of constraints.\n  octave_idx_type n_eq = beq.numel ();\n  octave_idx_type n_in = bin.numel ();\n\n  // Filling the current active set.\n\n  octave_idx_type n_act = n_eq;\n\n  octave_idx_type n_tot = n_eq + n_in;\n\n  // Equality constraints come first.  We won't check the sign of the\n  // Lagrange multiplier for those.\n\n  Matrix Aact = Aeq;\n  ColumnVector bact = beq;\n  ColumnVector Wact;\n\n  if (n_in > 0)\n    {\n      ColumnVector res = Ain*x - bin;\n\n      for (octave_idx_type i = 0; i < n_in; i++)\n        {\n          res(i) /= (1.0 + std::abs (bin(i)));\n\n          if (res(i) < rtol)\n            {\n              n_act++;\n              Aact = Aact.stack (Ain.row (i));\n              bact.resize (n_act, bin(i));\n              Wact.resize (n_act-n_eq, i);\n            }\n        }\n    }\n\n  // Computing the ???\n\n  EIG eigH;\n\n  try\n    {\n      eigH = EIG (H);\n    }\n  catch (execution_exception& ee)\n    {\n      error (ee, \"qp: failed to compute eigenvalues of H\");\n    }\n\n  ColumnVector eigenvalH = real (eigH.eigenvalues ());\n  Matrix eigenvecH = real (eigH.right_eigenvectors ());\n  octave_idx_type indminR = min_index (eigenvalH);\n\n  bool done = false;\n\n  double alpha = 0.0;\n\n  Matrix R;\n  Matrix Y (n, 0, 0.0);\n\n  ColumnVector g (n, 0.0);\n  ColumnVector p (n, 0.0);\n\n  ColumnVector lambda_tmp (n_in, 0.0);\n\n  while (! done)\n    {\n      iter++;\n\n      // Current Gradient\n      // g = q + H * x;\n\n      g = q + H * x;\n\n      if (n_act == 0)\n        {\n          // There are no active constraints.\n\n          double minReal = eigenvalH.xelem (indminR);\n\n          if (minReal > 0.0)\n            {\n              // Inverting the Hessian.  Using the Cholesky\n              // factorization since the Hessian is positive\n              // definite.\n\n              math::chol<Matrix> cholH (H);\n\n              R = cholH.chol_matrix ();\n\n              Matrix Hinv = math::chol2inv (R);\n\n              // Computing the unconstrained step.\n              // p = -Hinv * g;\n\n              p = -Hinv * g;\n\n              info = 0;\n            }\n          else\n            {\n              // Finding the negative curvature of H.\n\n              p = eigenvecH.column (indminR);\n\n              // Following the negative curvature of H.\n\n              if (p.transpose () * g > std::numeric_limits<double>::epsilon ())\n                p = -p;\n\n              info = 1;\n            }\n\n          // Multipliers are zero.\n          lambda_tmp.fill (0.0);\n        }\n      else\n        {\n          // There are active constraints.\n\n          // Computing the null space.\n\n          octave_idx_type rank;\n\n          Matrix Z = null (Aact, rank);\n\n          octave_idx_type dimZ = n - rank;\n\n          // FIXME: still remain to handle the case of\n          // non-full rank active set matrix.\n\n          // Computing the Y matrix (orthogonal to Z)\n          Y = Aact.pseudo_inverse ();\n\n          // Reduced Hessian\n          Matrix Zt = Z.transpose ();\n          Matrix rH = Zt * H * Z;\n\n          octave_idx_type pR = 0;\n\n          if (dimZ > 0)\n            {\n              // Computing the Cholesky factorization (pR = 0 means\n              // that the reduced Hessian was positive definite).\n\n              math::chol<Matrix> cholrH (rH, pR);\n              Matrix tR = cholrH.chol_matrix ();\n              if (pR == 0)\n                R = tR;\n            }\n\n          if (pR == 0)\n            {\n              info = 0;\n\n              // Computing the step pz.\n              if (dimZ > 0)\n                {\n                  // Using the Cholesky factorization to invert rH\n\n                  Matrix rHinv = math::chol2inv (R);\n\n                  ColumnVector pz = -rHinv * Zt * g;\n\n                  // Global step.\n                  p = Z * pz;\n                }\n              else\n                {\n                  // Global step.\n                  p.fill (0.0);\n                }\n            }\n          else\n            {\n              info = 1;\n\n              // Searching for the most negative curvature.\n\n              EIG eigrH;\n\n              try\n                {\n                  eigrH = EIG (rH);\n                }\n              catch (execution_exception& ee)\n                {\n                  error (ee, \"qp: failed to compute eigenvalues of rH\");\n                }\n\n              ColumnVector eigenvalrH = real (eigrH.eigenvalues ());\n              Matrix eigenvecrH = real (eigrH.right_eigenvectors ());\n              indminR = min_index (eigenvalrH);\n\n              ColumnVector eVrH = eigenvecrH.column (indminR);\n\n              // Computing the step pz.\n              p = Z * eVrH;\n\n              if (p.transpose () * g > std::numeric_limits<double>::epsilon ())\n                p = -p;\n            }\n        }\n\n      // Checking the step-size.\n      ColumnVector abs_p (n);\n      for (octave_idx_type i = 0; i < n; i++)\n        abs_p(i) = std::abs (p(i));\n      double max_p = abs_p.max ();\n\n      if (max_p < rtol)\n        {\n          // The step is null.  Checking constraints.\n          if (n_act - n_eq == 0)\n            // Solution is found because no inequality\n            // constraints are active.\n            done = true;\n          else\n            {\n              // Computing the multipliers only for the inequality\n              // constraints that are active.  We do NOT compute\n              // multipliers for the equality constraints.\n              Matrix Yt = Y.transpose ();\n              Yt = Yt.extract_n (n_eq, 0, n_act-n_eq, n);\n              lambda_tmp = Yt * (g + H * p);\n\n              // Checking the multipliers.  We remove the most\n              // negative from the set (if any).\n              double min_lambda = lambda_tmp.min ();\n              if (min_lambda >= 0)\n                {\n                  // Solution is found.\n                  done = true;\n                }\n              else\n                {\n                  octave_idx_type which_eig = 0;\n                  for (octave_idx_type i = 0; i < n_act; i++)\n                    {\n                      if (lambda_tmp(i) == min_lambda)\n                        {\n                          which_eig = i;\n                          break;\n                        }\n                    }\n\n                  // At least one multiplier is negative, we\n                  // remove it from the set.\n\n                  n_act--;\n                  for (octave_idx_type i = which_eig; i < n_act - n_eq; i++)\n                    {\n                      Wact(i) = Wact(i+1);\n                      for (octave_idx_type j = 0; j < n; j++)\n                        Aact(n_eq+i, j) = Aact(n_eq+i+1, j);\n                      bact(n_eq+i) = bact(n_eq+i+1);\n                    }\n\n                  // Resizing the active set.\n                  Wact.resize (n_act-n_eq);\n                  bact.resize (n_act);\n                  Aact.resize (n_act, n);\n                }\n            }\n        }\n      else\n        {\n          // The step is not null.\n          if (n_act - n_eq == n_in)\n            {\n              // All inequality constraints were active.  We can\n              // add the whole step.\n              x += p;\n            }\n          else\n            {\n              // Some constraints were not active.  Checking if\n              // there is a blocking constraint.\n              alpha = 1.0;\n              octave_idx_type is_block = -1;\n\n              for (octave_idx_type i = 0; i < n_in; i++)\n                {\n                  bool found = false;\n\n                  for (octave_idx_type j = 0; j < n_act-n_eq; j++)\n                    {\n                      if (Wact(j) == i)\n                        {\n                          found = true;\n                          break;\n                        }\n                    }\n\n                  if (! found)\n                    {\n                      // The i-th constraint was not in the set.  Is it a\n                      // blocking constraint?\n\n                      RowVector tmp_row = Ain.row (i);\n                      double tmp = tmp_row * p;\n                      double res = tmp_row * x;\n\n                      if (tmp < 0.0)\n                        {\n                          double alpha_tmp = (bin(i) - res) / tmp;\n\n                          if (alpha_tmp < alpha)\n                            {\n                              alpha = alpha_tmp;\n                              is_block = i;\n                            }\n                        }\n                    }\n                }\n\n              // In is_block there is the index of the blocking\n              // constraint (if any).\n              if (is_block >= 0)\n                {\n                  // There is a blocking constraint (index in\n                  // is_block) which is added to the active set.\n                  n_act++;\n                  Aact = Aact.stack (Ain.row (is_block));\n                  bact.resize (n_act, bin(is_block));\n                  Wact.resize (n_act-n_eq, is_block);\n\n                  // Adding the reduced step\n                  x += alpha * p;\n                }\n              else\n                {\n                  // There are no blocking constraints.  Adding the\n                  // whole step.\n                  x += alpha * p;\n                }\n            }\n        }\n\n      if (iter == maxit)\n        {\n          done = true;\n          // warning (\"qp_main: maximum number of iteration reached\");\n          info = 3;\n        }\n    }\n\n  lambda_tmp = Y.transpose () * (g + H * p);\n\n  // Reordering the Lagrange multipliers.\n\n  lambda.resize (n_tot);\n  lambda.fill (0.0);\n  for (octave_idx_type i = 0; i < n_eq; i++)\n    lambda(i) = lambda_tmp(i);\n\n  for (octave_idx_type i = n_eq; i < n_tot; i++)\n    {\n      for (octave_idx_type j = 0; j < n_act-n_eq; j++)\n        {\n          if (Wact(j) == i - n_eq)\n            {\n              lambda(i) = lambda_tmp(n_eq+j);\n              break;\n            }\n        }\n    }\n\n  return info;\n}\n\nDEFUN (__qp__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{x}, @var{lambda}, @var{info}, @var{iter}] =} __qp__ (@var{x0}, @var{H}, @var{q}, @var{Aeq}, @var{beq}, @var{Ain}, @var{bin}, @var{maxit}, @var{rtol})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 9)\n    print_usage ();\n\n  const ColumnVector x0  (args(0).vector_value ());\n  const Matrix H         (args(1).matrix_value ());\n  const ColumnVector q   (args(2).vector_value ());\n  const Matrix Aeq       (args(3).matrix_value ());\n  const ColumnVector beq (args(4).vector_value ());\n  const Matrix Ain       (args(5).matrix_value ());\n  const ColumnVector bin (args(6).vector_value ());\n  const int maxit        (args(7).int_value ());\n  const double rtol      (args(8).double_value());\n\n  int iter = 0;\n\n  // Copy the initial guess into the working variable\n  ColumnVector x = x0;\n\n  // Reordering the Lagrange multipliers\n  ColumnVector lambda;\n\n  int info = qp (H, q, Aeq, beq, Ain, bin, maxit, rtol, x, lambda, iter);\n\n  return ovl (x, lambda, info, iter);\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/amd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This is the octave interface to amd, which bore the copyright given\n// in the help of the functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n\n#include \"CSparse.h\"\n#include \"Sparse.h\"\n#include \"dMatrix.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sparse.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"parse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (amd, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{p} =} amd (@var{S})\n@deftypefnx {} {@var{p} =} amd (@var{S}, @var{opts})\n\nReturn the approximate minimum degree permutation of a matrix.\n\nThis is a permutation such that the Cholesky@tie{}factorization of\n@code{@var{S} (@var{p}, @var{p})} tends to be sparser than the\nCholesky@tie{}factorization of @var{S} itself.  @code{amd} is typically\nfaster than @code{symamd} but serves a similar purpose.\n\nThe optional parameter @var{opts} is a structure that controls the behavior\nof @code{amd}.  The fields of the structure are\n\n@table @asis\n@item @var{opts}.dense\nDetermines what @code{amd} considers to be a dense row or column of the\ninput matrix.  Rows or columns with more than @code{max (16, (dense *\nsqrt (@var{n})))} entries, where @var{n} is the order of the matrix @var{S},\nare ignored by @code{amd} during the calculation of the permutation.\nThe value of dense must be a positive scalar and the default value is 10.0\n\n@item @var{opts}.aggressive\nIf this value is a nonzero scalar, then @code{amd} performs aggressive\nabsorption.  The default is not to perform aggressive absorption.\n@end table\n\nThe author of the code itself is Timothy A. Davis\n(see @url{http://faculty.cse.tamu.edu/davis/suitesparse.html}).\n@seealso{symamd, colamd}\n@end deftypefn */)\n{\n#if defined (HAVE_AMD)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_idx_type n_row, n_col;\n  const suitesparse_integer *ridx, *cidx;\n  SparseMatrix sm;\n  SparseComplexMatrix scm;\n\n  if (args(0).issparse ())\n    {\n      if (args(0).iscomplex ())\n        {\n          scm = args(0).sparse_complex_matrix_value ();\n          n_row = scm.rows ();\n          n_col = scm.cols ();\n          ridx = to_suitesparse_intptr (scm.xridx ());\n          cidx = to_suitesparse_intptr (scm.xcidx ());\n        }\n      else\n        {\n          sm = args(0).sparse_matrix_value ();\n          n_row = sm.rows ();\n          n_col = sm.cols ();\n          ridx = to_suitesparse_intptr (sm.xridx ());\n          cidx = to_suitesparse_intptr (sm.xcidx ());\n        }\n    }\n  else\n    {\n      if (args(0).iscomplex ())\n        sm = SparseMatrix (real (args(0).complex_matrix_value ()));\n      else\n        sm = SparseMatrix (args(0).matrix_value ());\n\n      n_row = sm.rows ();\n      n_col = sm.cols ();\n      ridx = to_suitesparse_intptr (sm.xridx ());\n      cidx = to_suitesparse_intptr (sm.xcidx ());\n    }\n\n  if (n_row != n_col)\n    err_square_matrix_required (\"amd\", \"S\");\n\n  OCTAVE_LOCAL_BUFFER (double, Control, AMD_CONTROL);\n  AMD_NAME (_defaults) (Control);\n  if (nargin > 1)\n    {\n      octave_scalar_map arg1 = args(1).xscalar_map_value (\"amd: OPTS argument must be a scalar structure\");\n\n      octave_value tmp;\n\n      tmp = arg1.getfield (\"dense\");\n      if (tmp.is_defined ())\n        Control[AMD_DENSE] = tmp.double_value ();\n\n      tmp = arg1.getfield (\"aggressive\");\n      if (tmp.is_defined ())\n        Control[AMD_AGGRESSIVE] = tmp.double_value ();\n    }\n\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, P, n_col);\n  Matrix xinfo (AMD_INFO, 1);\n  double *Info = xinfo.rwdata ();\n\n  // FIXME: how can we manage the memory allocation of amd\n  //        in a cleaner manner?\n  SUITESPARSE_ASSIGN_FPTR (malloc_func, amd_malloc, malloc);\n  SUITESPARSE_ASSIGN_FPTR (free_func, amd_free, free);\n  SUITESPARSE_ASSIGN_FPTR (calloc_func, amd_calloc, calloc);\n  SUITESPARSE_ASSIGN_FPTR (realloc_func, amd_realloc, realloc);\n  SUITESPARSE_ASSIGN_FPTR (printf_func, amd_printf, printf);\n\n  octave_idx_type result = AMD_NAME (_order) (n_col, cidx, ridx, P, Control,\n                           Info);\n\n  if (result == AMD_OUT_OF_MEMORY)\n    error (\"amd: out of memory\");\n  else if (result == AMD_INVALID)\n    error (\"amd: matrix S is corrupted\");\n\n  Matrix Pout (1, n_col);\n  for (octave_idx_type i = 0; i < n_col; i++)\n    Pout.xelem (i) = P[i] + 1;\n\n  if (nargout > 1)\n    return ovl (Pout, xinfo);\n  else\n    return ovl (Pout);\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"amd\", \"AMD\");\n\n#endif\n}\n\n/*\n%!shared A, A2, opts\n%! A = ones (20, 30);\n%! A2 = ones (30, 30);\n\n%!testif HAVE_AMD\n%! assert(amd (A2), [1:30]);\n%! opts.dense = 25;\n%! assert(amd (A2, opts), [1:30]);\n%! opts.aggressive = 1;\n%! assert(amd (A2, opts), [1:30]);\n\n%!testif HAVE_AMD\n%! assert (amd ([]), zeros (1,0));\n\n%!error <S must be a square matrix|was unavailable or disabled> amd (A)\n%!error amd (A2, 2)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/balance.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"CMatrix.h\"\n#include \"aepbalance.h\"\n#include \"dMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"fMatrix.h\"\n#include \"gepbalance.h\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"f77-fcn.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (balance, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{AA} =} balance (@var{A})\n@deftypefnx {} {@var{AA} =} balance (@var{A}, @var{opt})\n@deftypefnx {} {[@var{DD}, @var{AA}] =} balance (@var{A}, @var{opt})\n@deftypefnx {} {[@var{D}, @var{P}, @var{AA}] =} balance (@var{A}, @var{opt})\n@deftypefnx {} {[@var{CC}, @var{DD}, @var{AA}, @var{BB}] =} balance (@var{A}, @var{B}, @var{opt})\n\nBalance the matrix @var{A} to reduce numerical errors in future\ncalculations.\n\nCompute @code{@var{AA} = @var{DD} \\ @var{A} * @var{DD}} in which @var{AA}\nis a matrix whose row and column norms are roughly equal in magnitude, and\n@code{@var{DD} = @var{P} * @var{D}}, in which @var{P} is a permutation\nmatrix and @var{D} is a diagonal matrix of powers of two.  This allows the\nequilibration to be computed without round-off.  Results of eigenvalue\ncalculation are typically improved by balancing first.\n\nIf two output values are requested, @code{balance} returns\nthe diagonal @var{D} and the permutation @var{P} separately as vectors.\nIn this case, @code{@var{DD} = eye(n)(:,@var{P}) * diag (@var{D})}, where\n@math{n} is the matrix size.\n\nIf four output values are requested, compute @code{@var{AA} =\n@var{CC}*@var{A}*@var{DD}} and @code{@var{BB} = @var{CC}*@var{B}*@var{DD}},\nin which @var{AA} and @var{BB} have nonzero elements of approximately the\nsame magnitude and @var{CC} and @var{DD} are permuted diagonal matrices as\nin @var{DD} for the algebraic eigenvalue problem.\n\nThe eigenvalue balancing option @var{opt} may be one of:\n\n@table @asis\n@item @qcode{\"noperm\"}, @qcode{\"S\"}\nScale only; do not permute.\n\n@item @qcode{\"noscal\"}, @qcode{\"P\"}\nPermute only; do not scale.\n@end table\n\nAlgebraic eigenvalue balancing uses standard @sc{lapack} routines.\n\nGeneralized eigenvalue problem balancing uses Ward's algorithm\n(SIAM Journal on Scientific and Statistical Computing, 1981).\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3 || nargout < 0)\n    print_usage ();\n\n  octave_value_list retval;\n\n  // determine if it's AEP or GEP\n  bool AEPcase = nargin == 1 || args(1).is_string ();\n\n  // problem dimension\n  octave_idx_type nn = args(0).rows ();\n\n  if (nn != args(0).columns ())\n    err_square_matrix_required (\"balance\", \"A\");\n\n  bool isfloat = args(0).is_single_type ()\n                 || (! AEPcase && args(1).is_single_type ());\n\n  bool complex_case = args(0).iscomplex ()\n                      || (! AEPcase && args(1).iscomplex ());\n\n  // Extract argument 1 parameter for both AEP and GEP.\n  Matrix aa;\n  ComplexMatrix caa;\n  FloatMatrix faa;\n  FloatComplexMatrix fcaa;\n\n  if (isfloat)\n    {\n      if (complex_case)\n        fcaa = args(0).float_complex_matrix_value ();\n      else\n        faa = args(0).float_matrix_value ();\n    }\n  else\n    {\n      if (complex_case)\n        caa = args(0).complex_matrix_value ();\n      else\n        aa = args(0).matrix_value ();\n    }\n\n  // Treat AEP/GEP cases.\n  if (AEPcase)\n    {\n      // Algebraic eigenvalue problem.\n      bool noperm = false;\n      bool noscal = false;\n      if (nargin > 1)\n        {\n          std::string a1s = args(1).string_value ();\n          noperm = a1s == \"noperm\" || a1s == \"S\";\n          noscal = a1s == \"noscal\" || a1s == \"P\";\n        }\n\n      // balance the AEP\n      if (isfloat)\n        {\n          if (complex_case)\n            {\n              math::aepbalance<FloatComplexMatrix> result (fcaa, noperm, noscal);\n\n              if (nargout == 0 || nargout == 1)\n                retval = ovl (result.balanced_matrix ());\n              else if (nargout == 2)\n                retval = ovl (result.balancing_matrix (),\n                              result.balanced_matrix ());\n              else\n                retval = ovl (result.scaling_vector (),\n                              result.permuting_vector (),\n                              result.balanced_matrix ());\n            }\n          else\n            {\n              math::aepbalance<FloatMatrix> result (faa, noperm, noscal);\n\n              if (nargout == 0 || nargout == 1)\n                retval = ovl (result.balanced_matrix ());\n              else if (nargout == 2)\n                retval = ovl (result.balancing_matrix (),\n                              result.balanced_matrix ());\n              else\n                retval = ovl (result.scaling_vector (),\n                              result.permuting_vector (),\n                              result.balanced_matrix ());\n            }\n        }\n      else\n        {\n          if (complex_case)\n            {\n              math::aepbalance<ComplexMatrix> result (caa, noperm, noscal);\n\n              if (nargout == 0 || nargout == 1)\n                retval = ovl (result.balanced_matrix ());\n              else if (nargout == 2)\n                retval = ovl (result.balancing_matrix (),\n                              result.balanced_matrix ());\n              else\n                retval = ovl (result.scaling_vector (),\n                              result.permuting_vector (),\n                              result.balanced_matrix ());\n            }\n          else\n            {\n              math::aepbalance<Matrix> result (aa, noperm, noscal);\n\n              if (nargout == 0 || nargout == 1)\n                retval = ovl (result.balanced_matrix ());\n              else if (nargout == 2)\n                retval = ovl (result.balancing_matrix (),\n                              result.balanced_matrix ());\n              else\n                retval = ovl (result.scaling_vector (),\n                              result.permuting_vector (),\n                              result.balanced_matrix ());\n            }\n        }\n    }\n  else\n    {\n      std::string bal_job;\n      if (nargout == 1)\n        warning (\"balance: used GEP, should have two output arguments\");\n\n      // Generalized eigenvalue problem.\n      if (nargin == 2)\n        bal_job = 'B';\n      else\n        bal_job = args(2).xstring_value (\"balance: OPT argument must be a string\");\n\n      if ((nn != args(1).columns ()) || (nn != args(1).rows ()))\n        ::err_nonconformant ();\n\n      Matrix bb;\n      ComplexMatrix cbb;\n      FloatMatrix fbb;\n      FloatComplexMatrix fcbb;\n\n      if (isfloat)\n        {\n          if (complex_case)\n            fcbb = args(1).float_complex_matrix_value ();\n          else\n            fbb = args(1).float_matrix_value ();\n        }\n      else\n        {\n          if (complex_case)\n            cbb = args(1).complex_matrix_value ();\n          else\n            bb = args(1).matrix_value ();\n        }\n\n      // balance the GEP\n      if (isfloat)\n        {\n          if (complex_case)\n            {\n              math::gepbalance<FloatComplexMatrix> result (fcaa, fcbb, bal_job);\n\n              switch (nargout)\n                {\n                case 4:\n                  retval(3) = result.balanced_matrix2 ();\n                  OCTAVE_FALLTHROUGH;\n\n                case 3:\n                  retval(2) = result.balanced_matrix ();\n                  retval(1) = result.balancing_matrix2 ();\n                  retval(0) = result.balancing_matrix ();\n                  break;\n\n                case 2:\n                  retval(1) = result.balancing_matrix2 ();\n                  OCTAVE_FALLTHROUGH;\n\n                case 1:\n                  retval(0) = result.balancing_matrix ();\n                  break;\n\n                default:\n                  error (\"balance: invalid number of output arguments\");\n                  break;\n                }\n            }\n          else\n            {\n              math::gepbalance<FloatMatrix> result (faa, fbb, bal_job);\n\n              switch (nargout)\n                {\n                case 4:\n                  retval(3) = result.balanced_matrix2 ();\n                  OCTAVE_FALLTHROUGH;\n\n                case 3:\n                  retval(2) = result.balanced_matrix ();\n                  retval(1) = result.balancing_matrix2 ();\n                  retval(0) = result.balancing_matrix ();\n                  break;\n\n                case 2:\n                  retval(1) = result.balancing_matrix2 ();\n                  OCTAVE_FALLTHROUGH;\n\n                case 1:\n                  retval(0) = result.balancing_matrix ();\n                  break;\n\n                default:\n                  error (\"balance: invalid number of output arguments\");\n                  break;\n                }\n            }\n        }\n      else\n        {\n          if (complex_case)\n            {\n              math::gepbalance<ComplexMatrix> result (caa, cbb, bal_job);\n\n              switch (nargout)\n                {\n                case 4:\n                  retval(3) = result.balanced_matrix2 ();\n                  OCTAVE_FALLTHROUGH;\n\n                case 3:\n                  retval(2) = result.balanced_matrix ();\n                  retval(1) = result.balancing_matrix2 ();\n                  retval(0) = result.balancing_matrix ();\n                  break;\n\n                case 2:\n                  retval(1) = result.balancing_matrix2 ();\n                  OCTAVE_FALLTHROUGH;\n\n                case 1:\n                  retval(0) = result.balancing_matrix ();\n                  break;\n\n                default:\n                  error (\"balance: invalid number of output arguments\");\n                  break;\n                }\n            }\n          else\n            {\n              math::gepbalance<Matrix> result (aa, bb, bal_job);\n\n              switch (nargout)\n                {\n                case 4:\n                  retval(3) = result.balanced_matrix2 ();\n                  OCTAVE_FALLTHROUGH;\n\n                case 3:\n                  retval(2) = result.balanced_matrix ();\n                  retval(1) = result.balancing_matrix2 ();\n                  retval(0) = result.balancing_matrix ();\n                  break;\n\n                case 2:\n                  retval(1) = result.balancing_matrix2 ();\n                  OCTAVE_FALLTHROUGH;\n\n                case 1:\n                  retval(0) = result.balancing_matrix ();\n                  break;\n\n                default:\n                  error (\"balance: invalid number of output arguments\");\n                  break;\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/besselj.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1997-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-specfun.h\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nenum bessel_type\n{\n  BESSEL_J,\n  BESSEL_Y,\n  BESSEL_I,\n  BESSEL_K,\n  BESSEL_H1,\n  BESSEL_H2\n};\n\n#define DO_BESSEL(type, alpha, x, scaled, ierr, result)                 \\\n  do                                                                    \\\n    {                                                                   \\\n      switch (type)                                                     \\\n        {                                                               \\\n        case BESSEL_J:                                                  \\\n          result = math::besselj (alpha, x, scaled, ierr);      \\\n          break;                                                        \\\n                                                                        \\\n        case BESSEL_Y:                                                  \\\n          result = math::bessely (alpha, x, scaled, ierr);      \\\n          break;                                                        \\\n                                                                        \\\n        case BESSEL_I:                                                  \\\n          result = math::besseli (alpha, x, scaled, ierr);      \\\n          break;                                                        \\\n                                                                        \\\n        case BESSEL_K:                                                  \\\n          result = math::besselk (alpha, x, scaled, ierr);      \\\n          break;                                                        \\\n                                                                        \\\n        case BESSEL_H1:                                                 \\\n          result = math::besselh1 (alpha, x, scaled, ierr);     \\\n          break;                                                        \\\n                                                                        \\\n        case BESSEL_H2:                                                 \\\n          result = math::besselh2 (alpha, x, scaled, ierr);     \\\n          break;                                                        \\\n                                                                        \\\n        default:                                                        \\\n          break;                                                        \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\noctave_value_list\ndo_bessel (enum bessel_type type, const char *fcn,\n           const octave_value_list& args, int nargout)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n\n  bool scaled = false;\n  if (nargin == 3)\n    {\n      octave_value opt_arg = args(2);\n      bool rpt_error = false;\n\n      if (! opt_arg.is_scalar_type ())\n        rpt_error = true;\n      else if (opt_arg.isnumeric ())\n        {\n          double opt_val = opt_arg.double_value ();\n          if (opt_val != 0.0 && opt_val != 1.0)\n            rpt_error = true;\n          scaled = (opt_val == 1.0);\n        }\n      else if (opt_arg.islogical ())\n        scaled = opt_arg.bool_value ();\n\n      if (rpt_error)\n        error (\"%s: OPT must be 0 (or false) or 1 (or true)\", fcn);\n    }\n\n  octave_value alpha_arg = args(0);\n  octave_value x_arg = args(1);\n\n  if (alpha_arg.is_single_type () || x_arg.is_single_type ())\n    {\n      if (alpha_arg.is_scalar_type ())\n        {\n          float alpha = args(0).xfloat_value (\"%s: ALPHA must be a scalar or matrix\", fcn);\n\n          if (x_arg.is_scalar_type ())\n            {\n              FloatComplex x = x_arg.xfloat_complex_value (\"%s: X must be a scalar or matrix\", fcn);\n\n              octave_idx_type ierr;\n              octave_value result;\n\n              DO_BESSEL (type, alpha, x, scaled, ierr, result);\n\n              retval(0) = result;\n              if (nargout > 1)\n                retval(1) = static_cast<float> (ierr);\n            }\n          else\n            {\n              FloatComplexNDArray x = x_arg.xfloat_complex_array_value (\"%s: X must be a scalar or matrix\", fcn);\n\n              Array<octave_idx_type> ierr;\n              octave_value result;\n\n              DO_BESSEL (type, alpha, x, scaled, ierr, result);\n\n              retval(0) = result;\n              if (nargout > 1)\n                retval(1) = NDArray (ierr);\n            }\n        }\n      else\n        {\n          const dim_vector& dv0 = args(0).dims ();\n          const dim_vector& dv1 = args(1).dims ();\n\n          bool args0_is_row_vector = (dv0(1) == dv0.numel ());\n          bool args1_is_col_vector = (dv1(0) == dv1.numel ());\n\n          if (args0_is_row_vector && args1_is_col_vector)\n            {\n              FloatRowVector ralpha = args(0).xfloat_row_vector_value (\"%s: ALPHA must be a scalar or matrix\",\n                                      fcn);\n\n              FloatComplexColumnVector cx\n                = x_arg.xfloat_complex_column_vector_value (\"%s: X must be a scalar or matrix\", fcn);\n\n              Array<octave_idx_type> ierr;\n              octave_value result;\n\n              DO_BESSEL (type, ralpha, cx, scaled, ierr, result);\n\n              retval(0) = result;\n              if (nargout > 1)\n                retval(1) = NDArray (ierr);\n            }\n          else\n            {\n              FloatNDArray alpha = args(0).xfloat_array_value (\"%s: ALPHA must be a scalar or matrix\", fcn);\n\n              if (x_arg.is_scalar_type ())\n                {\n                  FloatComplex x = x_arg.xfloat_complex_value (\"%s: X must be a scalar or matrix\", fcn);\n\n                  Array<octave_idx_type> ierr;\n                  octave_value result;\n\n                  DO_BESSEL (type, alpha, x, scaled, ierr, result);\n\n                  retval(0) = result;\n                  if (nargout > 1)\n                    retval(1) = NDArray (ierr);\n                }\n              else\n                {\n                  FloatComplexNDArray x = x_arg.xfloat_complex_array_value (\"%s: X must be a scalar or matrix\", fcn);\n\n                  Array<octave_idx_type> ierr;\n                  octave_value result;\n\n                  DO_BESSEL (type, alpha, x, scaled, ierr, result);\n\n                  retval(0) = result;\n                  if (nargout > 1)\n                    retval(1) = NDArray (ierr);\n                }\n            }\n        }\n    }\n  else\n    {\n      if (alpha_arg.is_scalar_type ())\n        {\n          double alpha = args(0).xdouble_value (\"%s: ALPHA must be a scalar or matrix\", fcn);\n\n          if (x_arg.is_scalar_type ())\n            {\n              Complex x = x_arg.xcomplex_value (\"%s: X must be a scalar or matrix\", fcn);\n\n              octave_idx_type ierr;\n              octave_value result;\n\n              DO_BESSEL (type, alpha, x, scaled, ierr, result);\n\n              retval(0) = result;\n              if (nargout > 1)\n                retval(1) = static_cast<double> (ierr);\n            }\n          else\n            {\n              ComplexNDArray x = x_arg.xcomplex_array_value (\"%s: X must be a scalar or matrix\", fcn);\n\n              Array<octave_idx_type> ierr;\n              octave_value result;\n\n              DO_BESSEL (type, alpha, x, scaled, ierr, result);\n\n              retval(0) = result;\n              if (nargout > 1)\n                retval(1) = NDArray (ierr);\n            }\n        }\n      else\n        {\n          const dim_vector& dv0 = args(0).dims ();\n          const dim_vector& dv1 = args(1).dims ();\n\n          bool args0_is_row_vector = (dv0(1) == dv0.numel ());\n          bool args1_is_col_vector = (dv1(0) == dv1.numel ());\n\n          if (args0_is_row_vector && args1_is_col_vector)\n            {\n              RowVector ralpha = args(0).xrow_vector_value (\"%s: ALPHA must be a scalar or matrix\", fcn);\n\n              ComplexColumnVector cx\n                = x_arg.xcomplex_column_vector_value (\"%s: X must be a scalar or matrix\", fcn);\n\n              Array<octave_idx_type> ierr;\n              octave_value result;\n\n              DO_BESSEL (type, ralpha, cx, scaled, ierr, result);\n\n              retval(0) = result;\n              if (nargout > 1)\n                retval(1) = NDArray (ierr);\n            }\n          else\n            {\n              NDArray alpha = args(0).xarray_value (\"%s: ALPHA must be a scalar or matrix\", fcn);\n\n              if (x_arg.is_scalar_type ())\n                {\n                  Complex x = x_arg.xcomplex_value (\"%s: X must be a scalar or matrix\", fcn);\n\n                  Array<octave_idx_type> ierr;\n                  octave_value result;\n\n                  DO_BESSEL (type, alpha, x, scaled, ierr, result);\n\n                  retval(0) = result;\n                  if (nargout > 1)\n                    retval(1) = NDArray (ierr);\n                }\n              else\n                {\n                  ComplexNDArray x = x_arg.xcomplex_array_value (\"%s: X must be a scalar or matrix\", fcn);\n\n                  Array<octave_idx_type> ierr;\n                  octave_value result;\n\n                  DO_BESSEL (type, alpha, x, scaled, ierr, result);\n\n                  retval(0) = result;\n                  if (nargout > 1)\n                    retval(1) = NDArray (ierr);\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\nDEFUN (besselj, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{J} =} besselj (@var{alpha}, @var{x})\n@deftypefnx {} {@var{J} =} besselj (@var{alpha}, @var{x}, @var{opt})\n@deftypefnx {} {[@var{J}, @var{ierr}] =} besselj (@dots{})\nCompute Bessel functions of the first kind.\n\nThe order of the Bessel function @var{alpha} must be real.  The points for\nevaluation @var{x} may be complex.\n\nIf the optional argument @var{opt} is 1 or true, the result @var{J} is\nmultiplied by @w{@code{exp (-abs (imag (@var{x})))}}.\n\nIf @var{alpha} is a scalar, the result is the same size as @var{x}.  If @var{x}\nis a scalar, the result is the same size as @var{alpha}.  If @var{alpha} is a\nrow vector and @var{x} is a column vector, the result is a matrix with\n@code{length (@var{x})} rows and @code{length (@var{alpha})} columns.\nOtherwise, @var{alpha} and @var{x} must conform and the result will be the same\nsize.\n\nIf requested, @var{ierr} contains the following status information and is the\nsame size as the result.\n\n@enumerate 0\n@item\nNormal return.\n\n@item\nInput error, return @code{NaN}.\n\n@item\nOverflow, return @code{Inf}.\n\n@item\nLoss of significance by argument reduction results in less than half of machine\naccuracy.\n\n@item\nLoss of significance by argument reduction, output may be inaccurate.\n\n@item\nError---no computation, algorithm termination condition not met, return\n@code{NaN}.\n@end enumerate\n\n@seealso{bessely, besseli, besselk, besselh}\n@end deftypefn */)\n{\n  return do_bessel (BESSEL_J, \"besselj\", args, nargout);\n}\n\n/*\n%!# Function besselj is tested along with other bessels at the end of this file\n\n## besselj specific BIST\n%!assert <*48316> (! any (isnan (besselj (1, 10.^[5:12]))))\n\n*/\n\nDEFUN (bessely, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{Y} =} bessely (@var{alpha}, @var{x})\n@deftypefnx {} {@var{Y} =} bessely (@var{alpha}, @var{x}, @var{opt})\n@deftypefnx {} {[@var{Y}, @var{ierr}] =} bessely (@dots{})\nCompute Bessel functions of the second kind.\n\nThe order of the Bessel function @var{alpha} must be real.  The points for\nevaluation @var{x} may be complex.\n\nIf the optional argument @var{opt} is 1 or true, the result @var{Y} is\nmultiplied by @w{@code{exp (-abs (imag (@var{x})))}}.\n\nIf @var{alpha} is a scalar, the result is the same size as @var{x}.  If @var{x}\nis a scalar, the result is the same size as @var{alpha}.  If @var{alpha} is a\nrow vector and @var{x} is a column vector, the result is a matrix with\n@code{length (@var{x})} rows and @code{length (@var{alpha})} columns.\nOtherwise, @var{alpha} and @var{x} must conform and the result will be the same\nsize.\n\nIf requested, @var{ierr} contains the following status information and is the\nsame size as the result.\n\n@enumerate 0\n@item\nNormal return.\n\n@item\nInput error, return @code{NaN}.\n\n@item\nOverflow, return @code{Inf}.\n\n@item\nLoss of significance by argument reduction results in less than half of machine\naccuracy.\n\n@item\nComplete loss of significance by argument reduction, return @code{NaN}.\n\n@item\nError---no computation, algorithm termination condition not met, return\n@code{NaN}.\n@end enumerate\n\n@seealso{besselj, besseli, besselk, besselh}\n@end deftypefn */)\n{\n  return do_bessel (BESSEL_Y, \"bessely\", args, nargout);\n}\n\n/*\n%!# Function bessely is tested along with other bessels at the end of this file\n*/\n\nDEFUN (besseli, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{I} =} besseli (@var{alpha}, @var{x})\n@deftypefnx {} {@var{I} =} besseli (@var{alpha}, @var{x}, @var{opt})\n@deftypefnx {} {[@var{I}, @var{ierr}] =} besseli (@dots{})\nCompute modified Bessel functions of the first kind.\n\nThe order of the Bessel function @var{alpha} must be real.  The points for\nevaluation @var{x} may be complex.\n\nIf the optional argument @var{opt} is 1 or true, the result @var{I} is\nmultiplied by @w{@code{exp (-abs (real (@var{x})))}}.\n\nIf @var{alpha} is a scalar, the result is the same size as @var{x}.  If @var{x}\nis a scalar, the result is the same size as @var{alpha}.  If @var{alpha} is a\nrow vector and @var{x} is a column vector, the result is a matrix with\n@code{length (@var{x})} rows and @code{length (@var{alpha})} columns.\nOtherwise, @var{alpha} and @var{x} must conform and the result will be the same\nsize.\n\nIf requested, @var{ierr} contains the following status information and is the\nsame size as the result.\n\n@enumerate 0\n@item\nNormal return.\n\n@item\nInput error, return @code{NaN}.\n\n@item\nOverflow, return @code{Inf}.\n\n@item\nLoss of significance by argument reduction results in less than half of machine\naccuracy.\n\n@item\nComplete loss of significance by argument reduction, return @code{NaN}.\n\n@item\nError---no computation, algorithm termination condition not met, return\n@code{NaN}.\n@end enumerate\n\n@seealso{besselk, besselj, bessely, besselh}\n@end deftypefn */)\n\n{\n  return do_bessel (BESSEL_I, \"besseli\", args, nargout);\n}\n\n/*\n%!# Function besseli is tested along with other bessels at the end of this file\n\n## besseli specific BIST\n%!assert (! isinf (besseli (0, 700)))\n\n*/\n\nDEFUN (besselk, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{K} =} besselk (@var{alpha}, @var{x})\n@deftypefnx {} {@var{K} =} besselk (@var{alpha}, @var{x}, @var{opt})\n@deftypefnx {} {[@var{K}, @var{ierr}] =} besselk (@dots{})\n\nCompute modified Bessel functions of the second kind.\n\nThe order of the Bessel function @var{alpha} must be real.  The points for\nevaluation @var{x} may be complex.\n\nIf the optional argument @var{opt} is 1 or true, the result @var{K} is\nmultiplied by @w{@code{exp (@var{x})}}.\n\nIf @var{alpha} is a scalar, the result is the same size as @var{x}.  If @var{x}\nis a scalar, the result is the same size as @var{alpha}.  If @var{alpha} is a\nrow vector and @var{x} is a column vector, the result is a matrix with\n@code{length (@var{x})} rows and @code{length (@var{alpha})} columns.\nOtherwise, @var{alpha} and @var{x} must conform and the result will be the same\nsize.\n\nIf requested, @var{ierr} contains the following status information and is the\nsame size as the result.\n\n@enumerate 0\n@item\nNormal return.\n\n@item\nInput error, return @code{NaN}.\n\n@item\nOverflow, return @code{Inf}.\n\n@item\nLoss of significance by argument reduction results in less than half of machine\naccuracy.\n\n@item\nComplete loss of significance by argument reduction, return @code{NaN}.\n\n@item\nError---no computation, algorithm termination condition not met, return\n@code{NaN}.\n@end enumerate\n\n@seealso{besseli, besselj, bessely, besselh}\n@end deftypefn */)\n{\n  return do_bessel (BESSEL_K, \"besselk\", args, nargout);\n}\n\n/*\n%!# Function besselk is tested along with other bessels at the end of this file\n*/\n\nDEFUN (besselh, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{H} =} besselh (@var{alpha}, @var{x})\n@deftypefnx {} {@var{H} =} besselh (@var{alpha}, @var{k}, @var{x})\n@deftypefnx {} {@var{H} =} besselh (@var{alpha}, @var{k}, @var{x}, @var{opt})\n@deftypefnx {} {[@var{H}, @var{ierr}] =} besselh (@dots{})\nCompute Bessel functions of the third kind (Hankel functions).\n\nThe order of the Bessel function @var{alpha} must be real.  The kind of Hankel\nfunction is specified by @var{k} and may be either first (@var{k} = 1) or\nsecond (@var{k} = 2).  The default is Hankel functions of the first kind.  The\npoints for evaluation @var{x} may be complex.\n\nIf the optional argument @var{opt} is 1 or true, the result is multiplied\nby @code{exp (-I*@var{x})} for @var{k} = 1 or @code{exp (I*@var{x})} for\n@var{k} = 2.\n\nIf @var{alpha} is a scalar, the result is the same size as @var{x}.  If @var{x}\nis a scalar, the result is the same size as @var{alpha}.  If @var{alpha} is a\nrow vector and @var{x} is a column vector, the result is a matrix with\n@code{length (@var{x})} rows and @code{length (@var{alpha})} columns.\nOtherwise, @var{alpha} and @var{x} must conform and the result will be the same\nsize.\n\nIf requested, @var{ierr} contains the following status information and is the\nsame size as the result.\n\n@enumerate 0\n@item\nNormal return.\n\n@item\nInput error, return @code{NaN}.\n\n@item\nOverflow, return @code{Inf}.\n\n@item\nLoss of significance by argument reduction results in less than half of machine\naccuracy.\n\n@item\nComplete loss of significance by argument reduction, return @code{NaN}.\n\n@item\nError---no computation, algorithm termination condition not met, return\n@code{NaN}.\n@end enumerate\n\n@seealso{besselj, bessely, besseli, besselk}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n\n  octave_value_list retval;\n\n  if (nargin == 2)\n    {\n      retval = do_bessel (BESSEL_H1, \"besselh\", args, nargout);\n    }\n  else\n    {\n      octave_idx_type kind = args(1).strict_int_value (\"besselh: invalid value of K\");\n\n      octave_value_list tmp_args;\n\n      if (nargin == 4)\n        tmp_args(2) = args(3);\n\n      tmp_args(1) = args(2);\n      tmp_args(0) = args(0);\n\n      if (kind == 1)\n        retval = do_bessel (BESSEL_H1, \"besselh\", tmp_args, nargout);\n      else if (kind == 2)\n        retval = do_bessel (BESSEL_H2, \"besselh\", tmp_args, nargout);\n      else\n        error (\"besselh: K must be 1 or 2\");\n    }\n\n  return retval;\n}\n\n/*\n%!# Function besselh is tested along with other bessels at the end of this file\n*/\n\nDEFUN (airy, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{a} =} airy (@var{z})\n@deftypefnx {} {@var{a} =} airy (@var{k}, @var{z})\n@deftypefnx {} {@var{a} =} airy (@var{k}, @var{z}, @var{scale})\n@deftypefnx {} {[@var{a}, @var{ierr}] =} airy (@dots{})\n\nCompute Airy functions of the first and second kind, and their derivatives.\n\n@example\n@group\n K   Function   Scale factor (if @var{scale} is true)\n---  --------   ---------------------------------------\n 0   Ai (Z)     exp ((2/3) * Z * sqrt (Z))\n 1   dAi(Z)/dZ  exp ((2/3) * Z * sqrt (Z))\n 2   Bi (Z)     exp (-abs (real ((2/3) * Z * sqrt (Z))))\n 3   dBi(Z)/dZ  exp (-abs (real ((2/3) * Z * sqrt (Z))))\n@end group\n@end example\n\nThe function call @code{airy (@var{z})} is equivalent to\n@code{airy (0, @var{z})}.\n\nThe optional third input @var{scale} determines whether to\napply scaling as described above.  It is false by default.\n\nThe result @var{a} is the same size as @var{z}.\n\nThe optional output @var{ierr} contains the following status information and\nis the same size as the result.\n\n@enumerate 0\n@item\nNormal return.\n\n@item\nInput error, return @code{NaN}.\n\n@item\nOverflow, return @code{Inf}.\n\n@item\nLoss of significance by argument reduction results in less than half\n of machine accuracy.\n\n@item\nLoss of significance by argument reduction, output may be inaccurate.\n\n@item\nError---no computation, algorithm termination condition not met,\nreturn @code{NaN}.\n@end enumerate\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n\n  int kind = 0;\n  if (nargin > 1)\n    {\n      kind = args(0).strict_int_value (\"airy: K must be an integer value\");\n\n      if (kind < 0 || kind > 3)\n        error (\"airy: K must be 0, 1, 2, or 3\");\n    }\n\n  bool scale = (nargin == 3) && args(2).strict_bool_value (\"airy: scale option must be a logical value\");\n\n  int idx = (nargin == 1 ? 0 : 1);\n\n  Array<octave_idx_type> ierr;\n  octave_value result;\n\n  if (args(idx).is_single_type ())\n    {\n      FloatComplexNDArray z = args(idx).xfloat_complex_array_value (\"airy: Z must be a complex matrix\");\n\n      if (kind > 1)\n        result = math::biry (z, kind == 3, scale, ierr);\n      else\n        result = math::airy (z, kind == 1, scale, ierr);\n    }\n  else\n    {\n      ComplexNDArray z = args(idx).xcomplex_array_value (\"airy: Z must be a complex matrix\");\n\n      if (kind > 1)\n        result = math::biry (z, kind == 3, scale, ierr);\n      else\n        result = math::airy (z, kind == 1, scale, ierr);\n    }\n\n  retval(0) = result;\n  if (nargout > 1)\n    retval(1) = NDArray (ierr);\n\n  return retval;\n}\n\n/*\n%!test <*62321>\n%! assert (airy (0, +1, false),   0.1352924163128814,                       1e-15);\n%! assert (airy (0, -1, false),   0.5355608832923521,                       1e-15);\n%! assert (airy (0, +i, false),   0.3314933054321411 - 0.3174498589684437i, 1e-15);\n%! assert (airy (0, -i, false),   0.3314933054321411 + 0.3174498589684437i, 1e-15);\n%! assert (airy (0, +1,  true),   0.2635136447491401,                       1e-15);\n%! assert (airy (0, -1,  true),   0.4208904755499093 - 0.3311746779333462i, 1e-15);\n%! assert (airy (0, +i,  true),   0.2743053542644657 - 0.0825606941400591i, 1e-15);\n%! assert (airy (0, -i,  true),   0.2743053542644657 + 0.0825606941400591i, 1e-15);\n%! assert (airy (1, +1, false),  -0.1591474412967932,                       1e-15);\n%! assert (airy (1, -1, false),  -0.0101605671166451,                       1e-15);\n%! assert (airy (1, +i, false),  -0.4324926598418070 + 0.0980478562292432i, 1e-15);\n%! assert (airy (1, -i, false),  -0.4324926598418070 - 0.0980478562292432i, 1e-15);\n%! assert (airy (1, +1,  true),  -0.3099768889605148,                       1e-15);\n%! assert (airy (1, -1,  true),  -0.0079850602592406 + 0.0062829878869967i, 1e-15);\n%! assert (airy (1, +i,  true),  -0.2682792317254506 - 0.0680655016581369i, 1e-15);\n%! assert (airy (1, -i,  true),  -0.2682792317254506 + 0.0680655016581369i, 1e-15);\n%! assert (airy (2, +1, false),   1.2074235949528715,                       1e-15);\n%! assert (airy (2, -1, false),   0.1039973894969446,                       1e-15);\n%! assert (airy (2, +i, false),   0.6488582083303949 + 0.3449586347680484i, 1e-15);\n%! assert (airy (2, -i, false),   0.6488582083303949 - 0.3449586347680484i, 1e-15);\n%! assert (airy (2, +1,  true),   0.6199119435726786,                       1e-15);\n%! assert (airy (2, -1,  true),   0.1039973894969446,                       1e-15);\n%! assert (airy (2, +i,  true),   0.4049686654663902 + 0.2152973271658010i, 1e-15);\n%! assert (airy (2, -i,  true),   0.4049686654663902 - 0.2152973271658010i, 1e-15);\n%! assert (airy (3, +1, false),   0.9324359333927754,                       1e-15);\n%! assert (airy (3, -1, false),   0.5923756264227923,                       1e-15);\n%! assert (airy (3, +i, false),   0.1350266467108190 - 0.1288373867812549i, 1e-15);\n%! assert (airy (3, -i, false),   0.1350266467108190 + 0.1288373867812549i, 1e-15);\n%! assert (airy (3, +1,  true),   0.4787285706049846,                       1e-15);\n%! assert (airy (3, -1,  true),   0.5923756264227923,                       1e-15);\n%! assert (airy (3, +i,  true),   0.0842735134099415 - 0.0804106412111761i, 1e-15);\n%! assert (airy (3, -i,  true),   0.0842735134099415 + 0.0804106412111761i, 1e-15);\n%! z = -1 - 1e-6i;\n%! s1 = exp (2/3 * z * sqrt(z));\n%! s2 = exp (-abs (real (2/3 * z * sqrt(z))));\n%! assert (airy (0, z, true), s1 * airy (0, z, false), 1e-15);\n%! assert (airy (1, z, true), s1 * airy (1, z, false), 1e-15);\n%! assert (airy (2, z, true), s2 * airy (2, z, false), 1e-15);\n%! assert (airy (3, z, true), s2 * airy (3, z, false), 1e-15);\n\nInput validation tests\n%!error airy ()\n%!error airy (0, 1, 2, 3)\n%!error <K must be an integer value> airy (\"foo\", 2, false)\n%!error <K must be 0, 1, 2, or 3> airy (3743, 2, false)\n%!error <scale option must be a logical value> airy (0, 2, \"foo\")\n%!error <Z must be a complex matrix> airy (0, \"foo\", false)\n*/\n\n\n/*\n## Test values computed with GP/PARI version 2.3.3\n%!shared alpha, x, jx, yx, ix, kx, nix\n%!\n%! ## Bessel functions, even order, positive and negative x\n%! alpha = 2;  x = 1.25;\n%! jx = 0.1710911312405234823613091417;\n%! yx = -1.193199310178553861283790424;\n%! ix = 0.2220184483766341752692212604;\n%! kx = 0.9410016167388185767085460540;\n%!\n%!assert (besselj (alpha,x), jx, 100*eps)\n%!assert (bessely (alpha,x), yx, 100*eps)\n%!assert (besseli (alpha,x), ix, 100*eps)\n%!assert (besselk (alpha,x), kx, 100*eps)\n%!assert (besselh (alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%!assert (besselj (-alpha,x), jx, 100*eps)\n%!assert (bessely (-alpha,x), yx, 100*eps)\n%!assert (besseli (-alpha,x), ix, 100*eps)\n%!assert (besselk (-alpha,x), kx, 100*eps)\n%!assert (besselh (-alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (-alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (-alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (-alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (-alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (-alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (-alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! x *= -1;\n%! yx = -1.193199310178553861283790424 + 0.3421822624810469647226182835*I;\n%! kx = 0.9410016167388185767085460540 - 0.6974915263814386815610060884*I;\n%!\n%!assert (besselj (alpha,x), jx, 100*eps)\n%!assert (bessely (alpha,x), yx, 100*eps)\n%!assert (besseli (alpha,x), ix, 100*eps)\n%!assert (besselk (alpha,x), kx, 100*eps)\n%!assert (besselh (alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! ## Bessel functions, odd order, positive and negative x\n%! alpha = 3;  x = 2.5;\n%! jx = 0.2166003910391135247666890035;\n%! yx = -0.7560554967536709968379029772;\n%! ix = 0.4743704087780355895548240179;\n%! kx = 0.2682271463934492027663765197;\n%!\n%!assert (besselj (alpha,x), jx, 100*eps)\n%!assert (bessely (alpha,x), yx, 100*eps)\n%!assert (besseli (alpha,x), ix, 100*eps)\n%!assert (besselk (alpha,x), kx, 100*eps)\n%!assert (besselh (alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%!assert (besselj (-alpha,x), -jx, 100*eps)\n%!assert (bessely (-alpha,x), -yx, 100*eps)\n%!assert (besseli (-alpha,x), ix, 100*eps)\n%!assert (besselk (-alpha,x), kx, 100*eps)\n%!assert (besselh (-alpha,1,x), -(jx + I*yx), 100*eps)\n%!assert (besselh (-alpha,2,x), -(jx - I*yx), 100*eps)\n%!\n%!assert (besselj (-alpha,x,1), -jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (-alpha,x,1), -yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (-alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (-alpha,1,x,1), -(jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (-alpha,2,x,1), -(jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! x *= -1;\n%! jx = -jx;\n%! yx = 0.7560554967536709968379029772 - 0.4332007820782270495333780070*I;\n%! ix = -ix;\n%! kx = -0.2682271463934492027663765197 - 1.490278591297463775542004240*I;\n%!\n%!assert (besselj (alpha,x), jx, 100*eps)\n%!assert (bessely (alpha,x), yx, 100*eps)\n%!assert (besseli (alpha,x), ix, 100*eps)\n%!assert (besselk (alpha,x), kx, 100*eps)\n%!assert (besselh (alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! ## Bessel functions, fractional order, positive and negative x\n%!\n%! alpha = 3.5;  x = 2.75;\n%! jx = 0.1691636439842384154644784389;\n%! yx = -0.8301381935499356070267953387;\n%! ix = 0.3930540878794826310979363668;\n%! kx = 0.2844099013460621170288192503;\n%!\n%!assert (besselj (alpha,x), jx, 100*eps)\n%!assert (bessely (alpha,x), yx, 100*eps)\n%!assert (besseli (alpha,x), ix, 100*eps)\n%!assert (besselk (alpha,x), kx, 100*eps)\n%!assert (besselh (alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! nix = 0.2119931212254662995364461998;\n%!\n%!assert (besselj (-alpha,x), yx, 100*eps)\n%!assert (bessely (-alpha,x), -jx, 100*eps)\n%!assert (besseli (-alpha,x), nix, 100*eps)\n%!assert (besselk (-alpha,x), kx, 100*eps)\n%!assert (besselh (-alpha,1,x), -I*(jx + I*yx), 100*eps)\n%!assert (besselh (-alpha,2,x), I*(jx - I*yx), 100*eps)\n%!\n%!assert (besselj (-alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (-alpha,x,1), -jx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (-alpha,x,1), nix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (-alpha,1,x,1), -I*(jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (-alpha,2,x,1), I*(jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! x *= -1;\n%! jx *= -I;\n%! yx = -0.8301381935499356070267953387*I;\n%! ix *= -I;\n%! kx = -0.9504059335995575096509874508*I;\n%!\n%!assert (besselj (alpha,x), jx, 100*eps)\n%!assert (bessely (alpha,x), yx, 100*eps)\n%!assert (besseli (alpha,x), ix, 100*eps)\n%!assert (besselk (alpha,x), kx, 100*eps)\n%!assert (besselh (alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! ## Bessel functions, even order, complex x\n%!\n%! alpha = 2;  x = 1.25 + 3.625 * I;\n%! jx = -1.299533366810794494030065917 + 4.370833116012278943267479589*I;\n%! yx = -4.370357232383223896393056727 - 1.283083391453582032688834041*I;\n%! ix = -0.6717801680341515541002273932 - 0.2314623443930774099910228553*I;\n%! kx = -0.01108009888623253515463783379 + 0.2245218229358191588208084197*I;\n%!\n%!assert (besselj (alpha,x), jx, 100*eps)\n%!assert (bessely (alpha,x), yx, 100*eps)\n%!assert (besseli (alpha,x), ix, 100*eps)\n%!assert (besselk (alpha,x), kx, 100*eps)\n%!assert (besselh (alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%!assert (besselj (-alpha,x), jx, 100*eps)\n%!assert (bessely (-alpha,x), yx, 100*eps)\n%!assert (besseli (-alpha,x), ix, 100*eps)\n%!assert (besselk (-alpha,x), kx, 100*eps)\n%!assert (besselh (-alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (-alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (-alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (-alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (-alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (-alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (-alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! ## Bessel functions, odd order, complex x\n%!\n%! alpha = 3; x = 2.5 + 1.875 * I;\n%! jx = 0.1330721523048277493333458596 + 0.5386295217249660078754395597*I;\n%! yx = -0.6485072392105829901122401551 + 0.2608129289785456797046996987*I;\n%! ix = -0.6182064685486998097516365709 + 0.4677561094683470065767989920*I;\n%! kx = -0.1568585587733540007867882337 - 0.05185853709490846050505141321*I;\n%!\n%!assert (besselj (alpha,x), jx, 100*eps)\n%!assert (bessely (alpha,x), yx, 100*eps)\n%!assert (besseli (alpha,x), ix, 100*eps)\n%!assert (besselk (alpha,x), kx, 100*eps)\n%!assert (besselh (alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%!assert (besselj (-alpha,x), -jx, 100*eps)\n%!assert (bessely (-alpha,x), -yx, 100*eps)\n%!assert (besseli (-alpha,x), ix, 100*eps)\n%!assert (besselk (-alpha,x), kx, 100*eps)\n%!assert (besselh (-alpha,1,x), -(jx + I*yx), 100*eps)\n%!assert (besselh (-alpha,2,x), -(jx - I*yx), 100*eps)\n%!\n%!assert (besselj (-alpha,x,1), -jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (-alpha,x,1), -yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (-alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (-alpha,1,x,1), -(jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (-alpha,2,x,1), -(jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! ## Bessel functions, fractional order, complex x\n%!\n%! alpha = 3.5;  x = 1.75 + 4.125 * I;\n%! jx = -3.018566131370455929707009100 - 0.7585648436793900607704057611*I;\n%! yx = 0.7772278839106298215614791107 - 3.018518722313849782683792010*I;\n%! ix = 0.2100873577220057189038160913 - 0.6551765604618246531254970926*I;\n%! kx = 0.1757147290513239935341488069 + 0.08772348296883849205562558311*I;\n%!\n%!assert (besselj (alpha,x), jx, 100*eps)\n%!assert (bessely (alpha,x), yx, 100*eps)\n%!assert (besseli (alpha,x), ix, 100*eps)\n%!assert (besselk (alpha,x), kx, 100*eps)\n%!assert (besselh (alpha,1,x), jx + I*yx, 100*eps)\n%!assert (besselh (alpha,2,x), jx - I*yx, 100*eps)\n%!\n%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps)\n%!\n%! nix = 0.09822388691172060573913739253 - 0.7110230642207380127317227407*I;\n%!\n%!assert (besselj (-alpha,x), yx, 100*eps)\n%!assert (bessely (-alpha,x), -jx, 100*eps)\n%!assert (besseli (-alpha,x), nix, 100*eps)\n%!assert (besselk (-alpha,x), kx, 100*eps)\n%!assert (besselh (-alpha,1,x), -I*(jx + I*yx), 100*eps)\n%!assert (besselh (-alpha,2,x), I*(jx - I*yx), 100*eps)\n%!\n%!assert (besselj (-alpha,x,1), yx* exp (-abs (imag (x))), 100*eps)\n%!assert (bessely (-alpha,x,1), -jx* exp (-abs (imag (x))), 100*eps)\n%!assert (besseli (-alpha,x,1), nix* exp (-abs (real (x))), 100*eps)\n%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps)\n%!assert (besselh (-alpha,1,x,1), -I*(jx + I*yx)* exp (-I*x), 100*eps)\n%!assert (besselh (-alpha,2,x,1), I*(jx - I*yx)* exp (I*x), 100*eps)\n\nTests contributed by Robert T. Short.\nTests are based on the properties and tables in A&S:\n Abramowitz and Stegun, \"Handbook of Mathematical Functions\",\n 1972.\n\nFor regular Bessel functions, there are 3 tests.  These compare octave\nresults against Tables 9.1, 9.2, and 9.4 in A&S.  Tables 9.1 and 9.2\nare good to only a few decimal places, so any failures should be\nconsidered a broken implementation.  Table 9.4 is an extended table\nfor larger orders and arguments.  There are some differences between\nOctave and Table 9.4, mostly in the last decimal place but in a very\nfew instances the errors are in the last two places.  The comparison\ntolerance has been changed to reflect this.\n\nSimilarly for modified Bessel functions, there are 3 tests.  These\ncompare octave results against Tables 9.8, 9.9, and 9.11 in A&S.\nTables 9.8 and 9.9 are good to only a few decimal places, so any\nfailures should be considered a broken implementation.  Table 9.11 is\nan extended table for larger orders and arguments.  There are some\ndifferences between octave and Table 9.11, mostly in the last decimal\nplace but in a very few instances the errors are in the last two\nplaces.  The comparison tolerance has been changed to reflect this.\n\nFor spherical Bessel functions, there are also three tests, comparing\noctave results to Tables 10.1, 10.2, and 10.4 in A&S.  Very similar\ncomments may be made here as in the previous lines.  At this time,\nmodified spherical Bessel function tests are not included.\n\n% Table 9.1 - J and Y for integer orders 0, 1, 2.\n% Compare against excerpts of Table 9.1, Abramowitz and Stegun.\n%!test\n%! n = 0:2;\n%! z = (0:2.5:17.5)';\n%!\n%! Jt = [[ 1.000000000000000,  0.0000000000,  0.0000000000];\n%!       [-0.048383776468198,  0.4970941025,  0.4460590584];\n%!       [-0.177596771314338, -0.3275791376,  0.0465651163];\n%!       [ 0.266339657880378,  0.1352484276, -0.2302734105];\n%!       [-0.245935764451348,  0.0434727462,  0.2546303137];\n%!       [ 0.146884054700421, -0.1654838046, -0.1733614634];\n%!       [-0.014224472826781,  0.2051040386,  0.0415716780];\n%!       [-0.103110398228686, -0.1634199694,  0.0844338303]];\n%!\n%! Yt = [[-Inf,          -Inf,          -Inf        ];\n%!       [ 0.4980703596,  0.1459181380, -0.38133585 ];\n%!       [-0.3085176252,  0.1478631434,  0.36766288 ];\n%!       [ 0.1173132861, -0.2591285105, -0.18641422 ];\n%!       [ 0.0556711673,  0.2490154242, -0.00586808 ];\n%!       [-0.1712143068, -0.1538382565,  0.14660019 ];\n%!       [ 0.2054642960,  0.0210736280, -0.20265448 ];\n%!       [-0.1604111925,  0.0985727987,  0.17167666 ]];\n%!\n%! J = besselj (n,z);\n%! Y = bessely (n,z);\n%! assert (Jt(:,1), J(:,1), 0.5e-10);\n%! assert (Yt(:,1), Y(:,1), 0.5e-10);\n%! assert (Jt(:,2:3), J(:,2:3), 0.5e-10);\n\nTable 9.2 - J and Y for integer orders 3-9.\n\n%!test\n%! n = (3:9);\n%! z = (0:2:20).';\n%!\n%! Jt = [[ 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00];\n%!       [ 1.2894e-01, 3.3996e-02, 7.0396e-03, 1.2024e-03, 1.7494e-04, 2.2180e-05, 2.4923e-06];\n%!       [ 4.3017e-01, 2.8113e-01, 1.3209e-01, 4.9088e-02, 1.5176e-02, 4.0287e-03, 9.3860e-04];\n%!       [ 1.1477e-01, 3.5764e-01, 3.6209e-01, 2.4584e-01, 1.2959e-01, 5.6532e-02, 2.1165e-02];\n%!       [-2.9113e-01,-1.0536e-01, 1.8577e-01, 3.3758e-01, 3.2059e-01, 2.2345e-01, 1.2632e-01];\n%!       [ 5.8379e-02,-2.1960e-01,-2.3406e-01,-1.4459e-02, 2.1671e-01, 3.1785e-01, 2.9186e-01];\n%!       [ 1.9514e-01, 1.8250e-01,-7.3471e-02,-2.4372e-01,-1.7025e-01, 4.5095e-02, 2.3038e-01];\n%!       [-1.7681e-01, 7.6244e-02, 2.2038e-01, 8.1168e-02,-1.5080e-01,-2.3197e-01,-1.1431e-01];\n%!       [-4.3847e-02,-2.0264e-01,-5.7473e-02, 1.6672e-01, 1.8251e-01,-7.0211e-03,-1.8953e-01];\n%!       [ 1.8632e-01, 6.9640e-02,-1.5537e-01,-1.5596e-01, 5.1399e-02, 1.9593e-01, 1.2276e-01];\n%!       [-9.8901e-02, 1.3067e-01, 1.5117e-01,-5.5086e-02,-1.8422e-01,-7.3869e-02, 1.2513e-01]];\n%!\n%! Yt = [[       -Inf,       -Inf,       -Inf,       -Inf,       -Inf,       -Inf,       -Inf];\n%!       [-1.1278e+00,-2.7659e+00,-9.9360e+00,-4.6914e+01,-2.7155e+02,-1.8539e+03,-1.4560e+04];\n%!       [-1.8202e-01,-4.8894e-01,-7.9585e-01,-1.5007e+00,-3.7062e+00,-1.1471e+01,-4.2178e+01];\n%!       [ 3.2825e-01, 9.8391e-02,-1.9706e-01,-4.2683e-01,-6.5659e-01,-1.1052e+00,-2.2907e+00];\n%!       [ 2.6542e-02, 2.8294e-01, 2.5640e-01, 3.7558e-02,-2.0006e-01,-3.8767e-01,-5.7528e-01];\n%!       [-2.5136e-01,-1.4495e-01, 1.3540e-01, 2.8035e-01, 2.0102e-01, 1.0755e-03,-1.9930e-01];\n%!       [ 1.2901e-01,-1.5122e-01,-2.2982e-01,-4.0297e-02, 1.8952e-01, 2.6140e-01, 1.5902e-01];\n%!       [ 1.2350e-01, 2.0393e-01,-6.9717e-03,-2.0891e-01,-1.7209e-01, 3.6816e-02, 2.1417e-01];\n%!       [-1.9637e-01,-7.3222e-05, 1.9633e-01, 1.2278e-01,-1.0425e-01,-2.1399e-01,-1.0975e-01];\n%!       [ 3.3724e-02,-1.7722e-01,-1.1249e-01, 1.1472e-01, 1.8897e-01, 3.2253e-02,-1.6030e-01];\n%!       [ 1.4967e-01, 1.2409e-01,-1.0004e-01,-1.7411e-01,-4.4312e-03, 1.7101e-01, 1.4124e-01]];\n%!\n%! n = (3:9);\n%! z = (0:2:20).';\n%! J = besselj (n,z);\n%! Y = bessely (n,z);\n%!\n%! assert (J(1,:), zeros (1, columns (J)));\n%! assert (J(2:end,:), Jt(2:end,:), -5e-5);\n%! assert (Yt(1,:), Y(1,:));\n%! assert (Y(2:end,:), Yt(2:end,:), -5e-5);\n\nTable 9.4 - J and Y for various integer orders and arguments.\n\n%!test\n%! Jt = [[ 7.651976866e-01,   2.238907791e-01,  -1.775967713e-01,  -2.459357645e-01,  5.581232767e-02,  1.998585030e-02];\n%!       [ 2.497577302e-04,   7.039629756e-03,   2.611405461e-01,  -2.340615282e-01, -8.140024770e-02, -7.419573696e-02];\n%!       [ 2.630615124e-10,   2.515386283e-07,   1.467802647e-03,   2.074861066e-01, -1.138478491e-01, -5.473217694e-02];\n%!       [ 2.297531532e-17,   7.183016356e-13,   4.796743278e-07,   4.507973144e-03, -1.082255990e-01,  1.519812122e-02];\n%!       [ 3.873503009e-25,   3.918972805e-19,   2.770330052e-11,   1.151336925e-05, -1.167043528e-01,  6.221745850e-02];\n%!       [ 3.482869794e-42,   3.650256266e-33,   2.671177278e-21,   1.551096078e-12,  4.843425725e-02,  8.146012958e-02];\n%!       [ 1.107915851e-60,   1.196077458e-48,   8.702241617e-33,   6.030895312e-21, -1.381762812e-01,  7.270175482e-02];\n%!       [ 2.906004948e-80,   3.224095839e-65,   2.294247616e-45,   1.784513608e-30,  1.214090219e-01, -3.869833973e-02];\n%!       [ 8.431828790e-189,  1.060953112e-158,  6.267789396e-119,  6.597316064e-89,  1.115927368e-21,  9.636667330e-02]];\n%!\n%! Yt = [[ 8.825696420e-02,   5.103756726e-01,  -3.085176252e-01,   5.567116730e-02, -9.806499547e-02, -7.724431337e-02]\n%!       [-2.604058666e+02,  -9.935989128e+00,  -4.536948225e-01,   1.354030477e-01, -7.854841391e-02, -2.948019628e-02]\n%!       [-1.216180143e+08,  -1.291845422e+05,  -2.512911010e+01,  -3.598141522e-01,  5.723897182e-03,  5.833157424e-02]\n%!       [-9.256973276e+14,  -2.981023646e+10,  -4.694049564e+04,  -6.364745877e+00,  4.041280205e-02,  7.879068695e-02]\n%!       [-4.113970315e+22,  -4.081651389e+16,  -5.933965297e+08,  -1.597483848e+03,  1.644263395e-02,  5.124797308e-02]\n%!       [-3.048128783e+39,  -2.913223848e+30,  -4.028568418e+18,  -7.256142316e+09, -1.164572349e-01,  6.138839212e-03]\n%!       [-7.184874797e+57,  -6.661541235e+45,  -9.216816571e+29,  -1.362803297e+18, -4.530801120e-02,  4.074685217e-02]\n%!       [-2.191142813e+77,  -1.976150576e+62,  -2.788837017e+42,  -3.641066502e+27, -2.103165546e-01,  7.650526394e-02]\n%!       [-3.775287810e+185, -3.000826049e+155, -5.084863915e+115, -4.849148271e+85, -3.293800188e+18, -1.669214114e-01]];\n%!\n%! n = [(0:5:20).';30;40;50;100];\n%! z = [1,2,5,10,50,100];\n%! J = besselj (n.', z.').';\n%! Y = bessely (n.', z.').';\n%! assert (J, Jt, -1e-9);\n%! assert (Y, Yt, -1e-9);\n\nTable 9.8 - I and K for integer orders 0, 1, 2.\n\n%!test\n%! n  = 0:2;\n%! z1 = [0.1;2.5;5.0];\n%! z2 = [7.5;10.0;15.0;20.0];\n%! rtbl = [[ 0.9071009258   0.0452984468   0.1251041992   2.6823261023  10.890182683    1.995039646  ];\n%!         [ 0.2700464416   0.2065846495   0.2042345837   0.7595486903   0.9001744239   0.759126289  ];\n%!         [ 0.1835408126   0.1639722669   0.7002245988   0.5478075643   0.6002738588   0.132723593  ];\n%!         [ 0.1483158301   0.1380412115   0.111504840    0.4505236991   0.4796689336   0.57843541   ];\n%!         [ 0.1278333372   0.1212626814   0.103580801    0.3916319344   0.4107665704   0.47378525   ];\n%!         [ 0.1038995314   0.1003741751   0.090516308    0.3210023535   0.3315348950   0.36520701   ];\n%!         [ 0.0897803119   0.0875062222   0.081029690    0.2785448768   0.2854254970   0.30708743   ]];\n%!\n%! tbl = [besseli(n,z1,1), besselk(n,z1,1)];\n%! tbl(:,3) = tbl(:,3) .* (exp (z1) .* z1.^(-2));\n%! tbl(:,6) = tbl(:,6) .* (exp (-z1) .* z1.^(2));\n%! tbl = [tbl;[besseli(n,z2,1),besselk(n,z2,1)]];\n%!\n%! assert (tbl, rtbl, -2e-8);\n\nTable 9.9 - I and K for orders 3-9.\n\n%!test\n%! It = [[  0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00];\n%!       [  2.8791e-02  6.8654e-03  1.3298e-03  2.1656e-04  3.0402e-05  3.7487e-06  4.1199e-07];\n%!       [  6.1124e-02  2.5940e-02  9.2443e-03  2.8291e-03  7.5698e-04  1.7968e-04  3.8284e-05];\n%!       [  7.4736e-02  4.1238e-02  1.9752e-02  8.3181e-03  3.1156e-03  1.0484e-03  3.1978e-04];\n%!       [  7.9194e-02  5.0500e-02  2.8694e-02  1.4633e-02  6.7449e-03  2.8292e-03  1.0866e-03];\n%!       [  7.9830e-02  5.5683e-02  3.5284e-02  2.0398e-02  1.0806e-02  5.2694e-03  2.3753e-03];\n%!       [  7.8848e-02  5.8425e-02  3.9898e-02  2.5176e-02  1.4722e-02  8.0010e-03  4.0537e-03];\n%!       [  7.7183e-02  5.9723e-02  4.3056e-02  2.8969e-02  1.8225e-02  1.0744e-02  5.9469e-03];\n%!       [  7.5256e-02  6.0155e-02  4.5179e-02  3.1918e-02  2.1240e-02  1.3333e-02  7.9071e-03];\n%!       [  7.3263e-02  6.0059e-02  4.6571e-02  3.4186e-02  2.3780e-02  1.5691e-02  9.8324e-03];\n%!       [  7.1300e-02  5.9640e-02  4.7444e-02  3.5917e-02  2.5894e-02  1.7792e-02  1.1661e-02]];\n%!\n%! Kt = [[ Inf         Inf         Inf         Inf         Inf         Inf         Inf];\n%!      [  4.7836e+00  1.6226e+01  6.9687e+01  3.6466e+02  2.2576e+03  1.6168e+04  1.3160e+05];\n%!      [  1.6317e+00  3.3976e+00  8.4268e+00  2.4465e+01  8.1821e+01  3.1084e+02  1.3252e+03];\n%!      [  9.9723e-01  1.6798e+00  3.2370e+00  7.0748e+00  1.7387e+01  4.7644e+01  1.4444e+02];\n%!      [  7.3935e-01  1.1069e+00  1.8463e+00  3.4148e+00  6.9684e+00  1.5610e+01  3.8188e+01];\n%!      [  6.0028e-01  8.3395e-01  1.2674e+00  2.1014e+00  3.7891e+00  7.4062e+00  1.5639e+01];\n%!      [  5.1294e-01  6.7680e-01  9.6415e-01  1.4803e+00  2.4444e+00  4.3321e+00  8.2205e+00];\n%!      [  4.5266e-01  5.7519e-01  7.8133e-01  1.1333e+00  1.7527e+00  2.8860e+00  5.0510e+00];\n%!      [  4.0829e-01  5.0414e-01  6.6036e-01  9.1686e-01  1.3480e+00  2.0964e+00  3.4444e+00];\n%!      [  3.7411e-01  4.5162e-01  5.7483e-01  7.7097e-01  1.0888e+00  1.6178e+00  2.5269e+00];\n%!      [  3.4684e-01  4.1114e-01  5.1130e-01  6.6679e-01  9.1137e-01  1.3048e+00  1.9552e+00]];\n%!\n%! n = (3:9);\n%! z = (0:2:20).';\n%! I = besseli (n,z,1);\n%! K = besselk (n,z,1);\n%!\n%! assert (abs (I(1,:)), zeros (1, columns (I)));\n%! assert (I(2:end,:), It(2:end,:), -5e-5);\n%! assert (Kt(1,:), K(1,:));\n%! assert (K(2:end,:), Kt(2:end,:), -5e-5);\n\nTable 9.11 - I and K for various integer orders and arguments.\n\n%!test\n%! It = [[   1.266065878e+00    2.279585302e+00    2.723987182e+01    2.815716628e+03     2.93255378e+20     1.07375171e+42 ];\n%!       [   2.714631560e-04    9.825679323e-03    2.157974547e+00    7.771882864e+02     2.27854831e+20     9.47009387e+41 ];\n%!       [   2.752948040e-10    3.016963879e-07    4.580044419e-03    2.189170616e+01     1.07159716e+20     6.49897552e+41 ];\n%!       [   2.370463051e-17    8.139432531e-13    1.047977675e-06    1.043714907e-01     3.07376455e+19     3.47368638e+41 ];\n%!       [   3.966835986e-25    4.310560576e-19    5.024239358e-11    1.250799736e-04     5.44200840e+18     1.44834613e+41 ];\n%!       [   3.539500588e-42    3.893519664e-33    3.997844971e-21    7.787569783e-12     4.27499365e+16     1.20615487e+40 ];\n%!       [   1.121509741e-60    1.255869192e-48    1.180426980e-32    2.042123274e-20     6.00717897e+13     3.84170550e+38 ];\n%!       [   2.934635309e-80    3.353042830e-65    2.931469647e-45    4.756894561e-30     1.76508024e+10     4.82195809e+36 ];\n%!       [   8.473674008e-189   1.082171475e-158   7.093551489e-119   1.082344202e-88     2.72788795e-16     4.64153494e+21 ]];\n%!\n%! Kt = [[   4.210244382e-01    1.138938727e-01    3.691098334e-03    1.778006232e-05     3.41016774e-23     4.65662823e-45 ];\n%!       [   3.609605896e+02    9.431049101e+00    3.270627371e-02    5.754184999e-05     4.36718224e-23     5.27325611e-45 ];\n%!       [   1.807132899e+08    1.624824040e+05    9.758562829e+00    1.614255300e-03     9.15098819e-23     7.65542797e-45 ];\n%!       [   1.403066801e+15    4.059213332e+10    3.016976630e+04    2.656563849e-01     3.11621117e-22     1.42348325e-44 ];\n%!       [   6.294369360e+22    5.770856853e+16    4.827000521e+08    1.787442782e+02     1.70614838e-21     3.38520541e-44 ];\n%!       [   4.706145527e+39    4.271125755e+30    4.112132063e+18    2.030247813e+09     2.00581681e-19     3.97060205e-43 ];\n%!       [   1.114220651e+58    9.940839886e+45    1.050756722e+30    5.938224681e+17     1.29986971e-16     1.20842080e-41 ];\n%!       [   3.406896854e+77    2.979981740e+62    3.394322243e+42    2.061373775e+27     4.00601349e-13     9.27452265e-40 ];\n%!       [   5.900333184e+185   4.619415978e+155   7.039860193e+115   4.596674084e+85     1.63940352e+13     7.61712963e-25 ]];\n%!\n%! n = [(0:5:20).';30;40;50;100];\n%! z = [1,2,5,10,50,100];\n%! I = besseli (n.', z.').';\n%! K = besselk (n.', z.').';\n%! assert (I, It, -5e-9);\n%! assert (K, Kt, -5e-9);\n\nThe next section checks that negative integer orders and positive\ninteger orders are appropriately related.\n\n%!test\n%! n = (0:2:20);\n%! assert (besselj (n,1), besselj (-n,1), 1e-8);\n%! assert (-besselj (n+1,1), besselj (-n-1,1), 1e-8);\n\nbesseli (n,z) = besseli (-n,z);\n\n%!test\n%! n = (0:2:20);\n%! assert (besseli (n,1), besseli (-n,1), 1e-8);\n\nTable 10.1 - j and y for integer orders 0, 1, 2.\nCompare against excerpts of Table 10.1, Abramowitz and Stegun.\n\n%!test\n%! n = (0:2);\n%! z = [0.1;(2.5:2.5:10.0).'];\n%!\n%! jt = [[ 9.9833417e-01  3.33000119e-02  6.6619061e-04 ];\n%!       [ 2.3938886e-01  4.16212989e-01  2.6006673e-01 ];\n%!       [-1.9178485e-01 -9.50894081e-02  1.3473121e-01 ];\n%!       [    1.2507e-01     -2.9542e-02    -1.3688e-01 ];\n%!       [   -5.4402e-02      7.8467e-02     7.7942e-02 ]];\n%!\n%! yt = [[-9.9500417e+00  -1.0049875e+02 -3.0050125e+03 ];\n%!       [ 3.2045745e-01  -1.1120588e-01 -4.5390450e-01 ];\n%!       [-5.6732437e-02   1.8043837e-01  1.6499546e-01 ];\n%!       [   -4.6218e-02     -1.3123e-01    -6.2736e-03 ];\n%!       [    8.3907e-02      6.2793e-02    -6.5069e-02 ]];\n%!\n%! j = sqrt ((pi/2)./z) .* besselj (n+1/2,z);\n%! y = sqrt ((pi/2)./z) .* bessely (n+1/2,z);\n%! assert (jt, j, -5e-5);\n%! assert (yt, y, -5e-5);\n\nTable 10.2 - j and y for orders 3-8.\nCompare against excerpts of Table 10.2, Abramowitzh and Stegun.\n\n Important note: In A&S, y_4(0.1) = -1.0507e+7, but Octave returns\n y_4(0.1) = -1.0508e+07 (-10507503.75).  If I compute the same term using\n a series, the difference is in the eighth significant digit so I left\n the Octave results in place.\n\n%!test\n%! n = (3:8);\n%! z = (0:2.5:10).';  z(1) = 0.1;\n%!\n%! jt = [[ 9.5185e-06  1.0577e-07  9.6163e-10  7.3975e-12  4.9319e-14  2.9012e-16];\n%!       [ 1.0392e-01  3.0911e-02  7.3576e-03  1.4630e-03  2.5009e-04  3.7516e-05];\n%!       [ 2.2982e-01  1.8702e-01  1.0681e-01  4.7967e-02  1.7903e-02  5.7414e-03];\n%!       [-6.1713e-02  7.9285e-02  1.5685e-01  1.5077e-01  1.0448e-01  5.8188e-02];\n%!       [-3.9496e-02 -1.0559e-01 -5.5535e-02  4.4501e-02  1.1339e-01  1.2558e-01]];\n%!\n%! yt = [[-1.5015e+05 -1.0508e+07 -9.4553e+08 -1.0400e+11 -1.3519e+13 -2.0277e+15];\n%!       [-7.9660e-01 -1.7766e+00 -5.5991e+00 -2.2859e+01 -1.1327e+02 -6.5676e+02];\n%!       [-1.5443e-02 -1.8662e-01 -3.2047e-01 -5.1841e-01 -1.0274e+00 -2.5638e+00];\n%!       [ 1.2705e-01  1.2485e-01  2.2774e-02 -9.1449e-02 -1.8129e-01 -2.7112e-01];\n%!       [-9.5327e-02 -1.6599e-03  9.3834e-02  1.0488e-01  4.2506e-02 -4.1117e-02]];\n%!\n%! j = sqrt ((pi/2)./z) .* besselj (n+1/2,z);\n%! y = sqrt ((pi/2)./z) .* bessely (n+1/2,z);\n%!\n%! assert (jt, j, -5e-5);\n%! assert (yt, y, -5e-5);\n\nTable 10.4 - j and y for various integer orders and arguments.\n\n%!test\n%! jt = [[ 8.414709848e-01    4.546487134e-01   -1.917848549e-01   -5.440211109e-02   -5.247497074e-03   -5.063656411e-03];\n%!       [ 9.256115861e-05    2.635169770e-03    1.068111615e-01   -5.553451162e-02   -2.004830056e-02   -9.290148935e-03];\n%!       [ 7.116552640e-11    6.825300865e-08    4.073442442e-04    6.460515449e-02   -1.503922146e-02   -1.956578597e-04];\n%!       [ 5.132686115e-18    1.606982166e-13    1.084280182e-07    1.063542715e-03   -1.129084539e-02    7.877261748e-03];\n%!       [ 7.537795722e-26    7.632641101e-20    5.427726761e-12    2.308371961e-06   -1.578502990e-02    1.010767128e-02];\n%!       [ 5.566831267e-43    5.836617888e-34    4.282730217e-22    2.512057385e-13   -1.494673454e-03    8.700628514e-03];\n%!       [ 1.538210374e-61    1.660978779e-49    1.210347583e-33    8.435671634e-22   -2.606336952e-02    1.043410851e-02];\n%!       [ 3.615274717e-81    4.011575290e-66    2.857479350e-46    2.230696023e-31    1.882910737e-02    5.797140882e-04];\n%!       [7.444727742e-190   9.367832591e-160   5.535650303e-120    5.832040182e-90    1.019012263e-22    1.088047701e-02]];\n%!\n%! yt = [[ -5.403023059e-01    2.080734183e-01   -5.673243709e-02    8.390715291e-02   -1.929932057e-02   -8.623188723e-03]\n%!       [ -9.994403434e+02   -1.859144531e+01   -3.204650467e-01    9.383354168e-02   -6.971131965e-04    3.720678486e-03]\n%!       [ -6.722150083e+08   -3.554147201e+05   -2.665611441e+01   -1.724536721e-01    1.352468751e-02    1.002577737e-02]\n%!       [ -6.298007233e+15   -1.012182944e+11   -6.288146513e+04   -3.992071745e+00    1.712319725e-02    6.258641510e-03]\n%!       [ -3.239592219e+23   -1.605436493e+17   -9.267951403e+08   -1.211210605e+03    1.375953130e-02    5.631729379e-05]\n%!       [ -2.946428547e+40   -1.407393871e+31   -7.760717570e+18   -6.908318646e+09   -2.241226812e-02   -5.412929349e-03]\n%!       [ -8.028450851e+58   -3.720929322e+46   -2.055758716e+30   -1.510304919e+18    4.978797221e-05   -7.048420407e-04]\n%!       [ -2.739192285e+78   -1.235021944e+63   -6.964109188e+42   -4.528227272e+27   -4.190000150e-02    1.074782297e-02]\n%!       [-6.683079463e+186  -2.655955830e+156  -1.799713983e+116   -8.573226309e+85   -1.125692891e+18   -2.298385049e-02]];\n%!\n%! n = [(0:5:20).';30;40;50;100];\n%! z = [1,2,5,10,50,100];\n%! j = sqrt ((pi/2)./z) .* besselj ((n+1/2).', z.').';\n%! y = sqrt ((pi/2)./z) .* bessely ((n+1/2).', z.').';\n%! assert (j, jt, -1e-9);\n%! assert (y, yt, -1e-9);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/bitfcns.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <limits>\n\n#include \"str-vec.h\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ov.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint8.h\"\n#include \"ov-int64.h\"\n#include \"ov-int32.h\"\n#include \"ov-int16.h\"\n#include \"ov-int8.h\"\n#include \"ov-float.h\"\n#include \"ov-scalar.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-bool.h\"\n\n#include <functional>\n\n#if ! defined (HAVE_CXX_BITWISE_OP_TEMPLATES)\nOCTAVE_BEGIN_NAMESPACE(std)\n\ntemplate <typename T>\nstruct bit_and\n{\npublic:\n  T operator() (const T& op1, const T& op2) const { return (op1 & op2); }\n};\n\ntemplate <typename T>\nstruct bit_or\n{\npublic:\n  T operator() (const T& op1, const T& op2) const { return (op1 | op2); }\n};\n\ntemplate <typename T>\nstruct bit_xor\n{\npublic:\n  T operator() (const T& op1, const T& op2) const { return (op1 ^ op2); }\n};\n\nOCTAVE_END_NAMESPACE(std)\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename OP, typename T>\noctave_value\nbitopxx (const OP& op, const std::string& fname,\n         const Array<T>& x, const Array<T>& y)\n{\n  int nelx = x.numel ();\n  int nely = y.numel ();\n\n  bool is_scalar_op = (nelx == 1 || nely == 1);\n\n  const dim_vector& dvx = x.dims ();\n  const dim_vector& dvy = y.dims ();\n\n  bool is_array_op = (dvx == dvy);\n\n  if (! is_array_op && ! is_scalar_op)\n    error (\"%s: size of X and Y must match, or one operand must be a scalar\",\n           fname.c_str ());\n\n  Array<T> result;\n\n  if (nelx != 1)\n    result.resize (dvx);\n  else\n    result.resize (dvy);\n\n  for (int i = 0; i < nelx; i++)\n    if (is_scalar_op)\n      for (int k = 0; k < nely; k++)\n        result(i+k) = op (x(i), y(k));\n    else\n      result(i) = op (x(i), y(i));\n\n  return result;\n}\n\n// Trampoline function, instantiates the proper template above, with\n// reflective information hardwired.  We can't hardwire this information\n// in Fbitxxx DEFUNs below, because at that moment, we still don't have\n// information about which integer types we need to instantiate.\ntemplate <typename T>\noctave_value\nbitopx (const std::string& fname, const Array<T>& x, const Array<T>& y)\n{\n  if (fname == \"bitand\")\n    return bitopxx (std::bit_and<T>(), fname, x, y);\n  if (fname == \"bitor\")\n    return bitopxx (std::bit_or<T>(), fname, x, y);\n\n  //else (fname == \"bitxor\")\n  return bitopxx (std::bit_xor<T>(), fname, x, y);\n}\n\nstatic inline int\nbitop_arg_is_int (const octave_value& arg)\n{\n  return (arg.class_name () != octave_scalar::static_class_name ()\n          && arg.class_name () != octave_float_scalar::static_class_name ()\n          && arg.class_name () != octave_bool::static_class_name ());\n}\n\nstatic inline int\nbitop_arg_is_bool (const octave_value& arg)\n{\n  return arg.class_name () == octave_bool::static_class_name ();\n}\n\nstatic inline int\nbitop_arg_is_float (const octave_value& arg)\n{\n  return arg.class_name () == octave_float_scalar::static_class_name ();\n}\n\noctave_value\nbitop (const std::string& fname, const octave_value_list& args)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value retval;\n\n  if (args(0).class_name () == octave_scalar::static_class_name ()\n      || args(0).class_name () == octave_float_scalar::static_class_name ()\n      || args(0).class_name () == octave_bool::static_class_name ()\n      || args(1).class_name () == octave_scalar::static_class_name ()\n      || args(1).class_name () == octave_float_scalar::static_class_name ()\n      || args(1).class_name () == octave_bool::static_class_name ())\n    {\n      bool arg0_is_int = bitop_arg_is_int (args(0));\n      bool arg1_is_int = bitop_arg_is_int (args(1));\n\n      bool arg0_is_bool = bitop_arg_is_bool (args(0));\n      bool arg1_is_bool = bitop_arg_is_bool (args(1));\n\n      bool arg0_is_float = bitop_arg_is_float (args(0));\n      bool arg1_is_float = bitop_arg_is_float (args(1));\n\n      if (! (arg0_is_int || arg1_is_int))\n        {\n          if (arg0_is_bool && arg1_is_bool)\n            {\n              boolNDArray x (args(0).bool_array_value ());\n              boolNDArray y (args(1).bool_array_value ());\n\n              retval = bitopx (fname, x, y).bool_array_value ();\n            }\n          else if (arg0_is_float && arg1_is_float)\n            {\n              uint64NDArray x (args(0).float_array_value ());\n              uint64NDArray y (args(1).float_array_value ());\n\n              retval = bitopx (fname, x, y).float_array_value ();\n            }\n          else if (! (arg0_is_float || arg1_is_float))\n            {\n              uint64NDArray x (args(0).array_value ());\n              uint64NDArray y (args(1).array_value ());\n\n              retval = bitopx (fname, x, y).array_value ();\n            }\n          else\n            {\n              int p = (arg0_is_float ? 1 : 0);\n              int q = (arg0_is_float ? 0 : 1);\n\n              uint64NDArray x (args(p).array_value ());\n              uint64NDArray y (args(q).float_array_value ());\n\n              retval = bitopx (fname, x, y).float_array_value ();\n            }\n        }\n      else\n        {\n          int p = (arg0_is_int ? 1 : 0);\n          int q = (arg0_is_int ? 0 : 1);\n\n          NDArray dx = args(p).array_value ();\n\n          if (args(q).type_id () == octave_uint64_matrix::static_type_id ()\n              || args(q).type_id () == octave_uint64_scalar::static_type_id ())\n            {\n              uint64NDArray x (dx);\n              uint64NDArray y = args(q).uint64_array_value ();\n\n              retval = bitopx (fname, x, y);\n            }\n          else if (args(q).type_id () == octave_uint32_matrix::static_type_id ()\n                   || args(q).type_id () == octave_uint32_scalar::static_type_id ())\n            {\n              uint32NDArray x (dx);\n              uint32NDArray y = args(q).uint32_array_value ();\n\n              retval = bitopx (fname, x, y);\n            }\n          else if (args(q).type_id () == octave_uint16_matrix::static_type_id ()\n                   || args(q).type_id () == octave_uint16_scalar::static_type_id ())\n            {\n              uint16NDArray x (dx);\n              uint16NDArray y = args(q).uint16_array_value ();\n\n              retval = bitopx (fname, x, y);\n            }\n          else if (args(q).type_id () == octave_uint8_matrix::static_type_id ()\n                   || args(q).type_id () == octave_uint8_scalar::static_type_id ())\n            {\n              uint8NDArray x (dx);\n              uint8NDArray y = args(q).uint8_array_value ();\n\n              retval = bitopx (fname, x, y);\n            }\n          else if (args(q).type_id () == octave_int64_matrix::static_type_id ()\n                   || args(q).type_id () == octave_int64_scalar::static_type_id ())\n            {\n              int64NDArray x (dx);\n              int64NDArray y = args(q).int64_array_value ();\n\n              retval = bitopx (fname, x, y);\n            }\n          else if (args(q).type_id () == octave_int32_matrix::static_type_id ()\n                   || args(q).type_id () == octave_int32_scalar::static_type_id ())\n            {\n              int32NDArray x (dx);\n              int32NDArray y = args(q).int32_array_value ();\n\n              retval = bitopx (fname, x, y);\n            }\n          else if (args(q).type_id () == octave_int16_matrix::static_type_id ()\n                   || args(q).type_id () == octave_int16_scalar::static_type_id ())\n            {\n              int16NDArray x (dx);\n              int16NDArray y = args(q).int16_array_value ();\n\n              retval = bitopx (fname, x, y);\n            }\n          else if (args(q).type_id () == octave_int8_matrix::static_type_id ()\n                   || args(q).type_id () == octave_int8_scalar::static_type_id ())\n            {\n              int8NDArray x (dx);\n              int8NDArray y = args(q).int8_array_value ();\n\n              retval = bitopx (fname, x, y);\n            }\n          else\n            error (\"%s: invalid operand type\", fname.c_str ());\n        }\n    }\n  else if (args(0).class_name () == args(1).class_name ())\n    {\n      if (args(0).type_id () == octave_uint64_matrix::static_type_id ()\n          || args(0).type_id () == octave_uint64_scalar::static_type_id ())\n        {\n          uint64NDArray x = args(0).uint64_array_value ();\n          uint64NDArray y = args(1).uint64_array_value ();\n\n          retval = bitopx (fname, x, y);\n        }\n      else if (args(0).type_id () == octave_uint32_matrix::static_type_id ()\n               || args(0).type_id () == octave_uint32_scalar::static_type_id ())\n        {\n          uint32NDArray x = args(0).uint32_array_value ();\n          uint32NDArray y = args(1).uint32_array_value ();\n\n          retval = bitopx (fname, x, y);\n        }\n      else if (args(0).type_id () == octave_uint16_matrix::static_type_id ()\n               || args(0).type_id () == octave_uint16_scalar::static_type_id ())\n        {\n          uint16NDArray x = args(0).uint16_array_value ();\n          uint16NDArray y = args(1).uint16_array_value ();\n\n          retval = bitopx (fname, x, y);\n        }\n      else if (args(0).type_id () == octave_uint8_matrix::static_type_id ()\n               || args(0).type_id () == octave_uint8_scalar::static_type_id ())\n        {\n          uint8NDArray x = args(0).uint8_array_value ();\n          uint8NDArray y = args(1).uint8_array_value ();\n\n          retval = bitopx (fname, x, y);\n        }\n      else if (args(0).type_id () == octave_int64_matrix::static_type_id ()\n               || args(0).type_id () == octave_int64_scalar::static_type_id ())\n        {\n          int64NDArray x = args(0).int64_array_value ();\n          int64NDArray y = args(1).int64_array_value ();\n\n          retval = bitopx (fname, x, y);\n        }\n      else if (args(0).type_id () == octave_int32_matrix::static_type_id ()\n               || args(0).type_id () == octave_int32_scalar::static_type_id ())\n        {\n          int32NDArray x = args(0).int32_array_value ();\n          int32NDArray y = args(1).int32_array_value ();\n\n          retval = bitopx (fname, x, y);\n        }\n      else if (args(0).type_id () == octave_int16_matrix::static_type_id ()\n               || args(0).type_id () == octave_int16_scalar::static_type_id ())\n        {\n          int16NDArray x = args(0).int16_array_value ();\n          int16NDArray y = args(1).int16_array_value ();\n\n          retval = bitopx (fname, x, y);\n        }\n      else if (args(0).type_id () == octave_int8_matrix::static_type_id ()\n               || args(0).type_id () == octave_int8_scalar::static_type_id ())\n        {\n          int8NDArray x = args(0).int8_array_value ();\n          int8NDArray y = args(1).int8_array_value ();\n\n          retval = bitopx (fname, x, y);\n        }\n      else\n        error (\"%s: invalid operand type\", fname.c_str ());\n    }\n  else\n    error (\"%s: must have matching operand types\", fname.c_str ());\n\n  return retval;\n}\n\nDEFUN (bitand, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{z} =} bitand (@var{x}, @var{y})\nReturn the bitwise AND of non-negative integers.\n\n@var{x}, @var{y} must be in the range [0,intmax]\n@seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, intmax, flintmax}\n@end deftypefn */)\n{\n  return bitop (\"bitand\", args);\n}\n\n/*\n%!# Function bitand is tested as part of bitxor BIST tests\n*/\n\nDEFUN (bitor, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{z} =} bitor (@var{x}, @var{y})\nReturn the bitwise OR of non-negative integers @var{x} and @var{y}.\n\n@seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, intmax, flintmax}\n@end deftypefn */)\n{\n  return bitop (\"bitor\", args);\n}\n\n/*\n%!# Function bitor is tested as part of bitxor BIST tests\n*/\n\nDEFUN (bitxor, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{z} =} bitxor (@var{x}, @var{y})\nReturn the bitwise XOR of non-negative integers @var{x} and @var{y}.\n\n@seealso{bitand, bitor, bitset, bitget, bitcmp, bitshift, intmax, flintmax}\n@end deftypefn */)\n{\n  return bitop (\"bitxor\", args);\n}\n\n/*\n%!assert (bitand (true, false), false)\n%!assert (bitor  (true, false), true)\n%!assert (bitxor (true, false), true)\n\n%!assert (bitand (true, true), true)\n%!assert (bitor  (true, true), true)\n%!assert (bitxor (true, true), false)\n\n%!assert (bitand (true, 5), 1)\n\n%!assert (bitand (true, false), false)\n%!assert (bitand (true, true), true)\n%!assert (bitand (true, false), false)\n%!assert (bitand (true, false), false)\n\n## Test idx_arg.length () == 0\n%!error <size of X and Y must match> bitand ([0 0 0], [1 0])\n%!error <size of X and Y must match> bitand ([0; 0; 0], [0 0 0])\n*/\n\ntemplate <typename T>\nstatic int64_t\nmax_mantissa_value ()\n{\n  return (static_cast<int64_t> (1) << std::numeric_limits<T>::digits) - 1;\n}\n\nstatic int64_t\nbitshift (double a, int n, int64_t mask)\n{\n  // In the name of bug-for-bug compatibility.\n  if (a < 0)\n    return -bitshift (-a, n, mask);\n\n  if (n > 0)\n    return (static_cast<int64_t> (a) << n) & mask;\n  else if (n < 0)\n    return (static_cast<int64_t> (a) >> -n) & mask;\n  else\n    return static_cast<int64_t> (a) & mask;\n}\n\nstatic int64_t\nbitshift (float a, int n, int64_t mask)\n{\n  // In the name of bug-for-bug compatibility.\n  if (a < 0)\n    return -bitshift (-a, n, mask);\n\n  if (n > 0)\n    return (static_cast<int64_t> (a) << n) & mask;\n  else if (n < 0)\n    return (static_cast<int64_t> (a) >> -n) & mask;\n  else\n    return static_cast<int64_t> (a) & mask;\n}\n\n// Note that the bitshift operators are undefined if shifted by more\n// bits than in the type, so we need to test for the size of the\n// shift.\n\n#define DO_BITSHIFT(T)                                                  \\\n  double d1, d2;                                                        \\\n                                                                        \\\n  if (! n.all_integers (d1, d2))                                        \\\n    error (\"bitshift: K must be a scalar or array of integers\");        \\\n                                                                        \\\n  int m_nel = m.numel ();                                               \\\n  int n_nel = n.numel ();                                               \\\n                                                                        \\\n  bool is_scalar_op = (m_nel == 1 || n_nel == 1);                       \\\n                                                                        \\\n  const dim_vector& m_dv = m.dims ();                                   \\\n  const dim_vector& n_dv = n.dims ();                                   \\\n                                                                        \\\n  bool is_array_op = (m_dv == n_dv);                                    \\\n                                                                        \\\n  if (! is_array_op && ! is_scalar_op)                                  \\\n    error (\"bitshift: size of A and N must match, or one operand must be a scalar\"); \\\n                                                                        \\\n  T ## NDArray result;                                                  \\\n                                                                        \\\n  if (m_nel != 1)                                                       \\\n    result.resize (m_dv);                                               \\\n  else                                                                  \\\n    result.resize (n_dv);                                               \\\n                                                                        \\\n  for (int i = 0; i < m_nel; i++)                                       \\\n    if (is_scalar_op)                                                   \\\n      for (int k = 0; k < n_nel; k++)                                   \\\n        if (static_cast<int> (n(k)) >= bits_in_type)                    \\\n          result(i+k) = 0;                                              \\\n        else                                                            \\\n          result(i+k) = bitshift (m(i), static_cast<int> (n(k)), mask); \\\n    else                                                                \\\n      if (static_cast<int> (n(i)) >= bits_in_type)                      \\\n        result(i) = 0;                                                  \\\n      else                                                              \\\n        result(i) = bitshift (m(i), static_cast<int> (n(i)), mask);     \\\n                                                                        \\\n  retval = result;\n\n#define DO_UBITSHIFT(T, N)                              \\\n  do                                                    \\\n    {                                                   \\\n      int bits_in_type = octave_ ## T :: nbits ();      \\\n      T ## NDArray m = m_arg.T ## _array_value ();      \\\n      octave_ ## T mask = octave_ ## T::max ();         \\\n      if ((N) < bits_in_type)                           \\\n        mask = bitshift (mask, (N) - bits_in_type);     \\\n      else if ((N) < 1)                                 \\\n        mask = 0;                                       \\\n      DO_BITSHIFT (T);                                  \\\n    }                                                   \\\n  while (0)\n\n#define DO_SBITSHIFT(T, N)                              \\\n  do                                                    \\\n    {                                                   \\\n      int bits_in_type = octave_ ## T :: nbits ();      \\\n      T ## NDArray m = m_arg.T ## _array_value ();      \\\n      octave_ ## T mask = octave_ ## T::max ();         \\\n      if ((N) < bits_in_type)                           \\\n        mask = bitshift (mask, (N) - bits_in_type);     \\\n      else if ((N) < 1)                                 \\\n        mask = 0;                                       \\\n      /* FIXME: 2's complement only? */                 \\\n      mask = mask | octave_ ## T :: min ();             \\\n      DO_BITSHIFT (T);                                  \\\n    }                                                   \\\n  while (0)\n\nDEFUN (bitshift, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{B} =} bitshift (@var{A}, @var{k})\n@deftypefnx {} {@var{B} =} bitshift (@var{A}, @var{k}, @var{n})\nReturn a @var{k} bit shift of @var{n}-digit unsigned integers in @var{A}.\n\nA positive @var{k} leads to a left shift; A negative value to a right shift.\n\nIf @var{n} is omitted it defaults to 64.  @var{n} must be in the range [1,64].\n\n@example\n@group\nbitshift (eye (3), 1)\n@xresult{}\n@group\n2 0 0\n0 2 0\n0 0 2\n@end group\n\nbitshift (10, [-2, -1, 0, 1, 2])\n@xresult{} 2   5  10  20  40\n@c FIXME: restore this example when third arg is allowed to be an array.\n@c\n@c\n@c bitshift ([1, 10], 2, [3,4])\n@c @xresult{} 4  8\n@end group\n@end example\n@seealso{bitand, bitor, bitxor, bitset, bitget, bitcmp, intmax, flintmax}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  NDArray n = args(1).xarray_value (\"bitshift: K must be a scalar or array of integers\");\n\n  int nbits = 64;\n\n  if (nargin == 3)\n    {\n      // FIXME: for compatibility, we should accept an array or a scalar\n      //        as the third argument.\n      if (args(2).numel () > 1)\n        error (\"bitshift: N must be a scalar integer\");\n\n      nbits = args(2).strict_int_value (\"bitshift: N must be an integer\");\n\n      if (nbits < 0)\n        error (\"bitshift: N must be positive\");\n    }\n\n  octave_value retval;\n\n  octave_value m_arg = args(0);\n  std::string cname = m_arg.class_name ();\n\n  if (cname == \"double\")\n    {\n      static const int bits_in_mantissa\n        = std::numeric_limits<double>::digits;\n\n      nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);\n      int64_t mask = max_mantissa_value<double> ();\n      if (nbits < bits_in_mantissa)\n        mask = mask >> (bits_in_mantissa - nbits);\n      int bits_in_type = sizeof (double)\n                         * std::numeric_limits<unsigned char>::digits;\n      NDArray m = m_arg.array_value ();\n      DO_BITSHIFT ();\n    }\n  else if (cname == \"uint8\")\n    DO_UBITSHIFT (uint8, nbits < 8 ? nbits : 8);\n  else if (cname == \"uint16\")\n    DO_UBITSHIFT (uint16, nbits < 16 ? nbits : 16);\n  else if (cname == \"uint32\")\n    DO_UBITSHIFT (uint32, nbits < 32 ? nbits : 32);\n  else if (cname == \"uint64\")\n    DO_UBITSHIFT (uint64, nbits < 64 ? nbits : 64);\n  else if (cname == \"int8\")\n    DO_SBITSHIFT (int8, nbits < 8 ? nbits : 8);\n  else if (cname == \"int16\")\n    DO_SBITSHIFT (int16, nbits < 16 ? nbits : 16);\n  else if (cname == \"int32\")\n    DO_SBITSHIFT (int32, nbits < 32 ? nbits : 32);\n  else if (cname == \"int64\")\n    DO_SBITSHIFT (int64, nbits < 64 ? nbits : 64);\n  else if (cname == \"single\")\n    {\n      static const int bits_in_mantissa\n        = std::numeric_limits<float>::digits;\n      nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);\n      int64_t mask = max_mantissa_value<float> ();\n      if (nbits < bits_in_mantissa)\n        mask = mask >> (bits_in_mantissa - nbits);\n      int bits_in_type = sizeof (float)\n                         * std::numeric_limits<unsigned char>::digits;\n      FloatNDArray m = m_arg.float_array_value ();\n      DO_BITSHIFT (Float);\n    }\n  else\n    error (\"bitshift: not defined for %s objects\", cname.c_str ());\n\n  return retval;\n}\n\n/*\n%!assert (bitshift (uint8  (16), 1),  uint8 ( 32))\n%!assert (bitshift (uint16 (16), 2), uint16 ( 64))\n%!assert (bitshift (uint32 (16), 3), uint32 (128))\n%!assert (bitshift (uint64 (16), 4), uint64 (256))\n%!assert (bitshift (uint8 (255), 1),  uint8 (254))\n\n%!error <K must be a scalar or array of integers> bitshift (16, 1.5)\n%!error bitshift (16, {1})\n%!error <N must be a scalar integer> bitshift (10, [-2 -1 0 1 2], [1 1 1 1 1])\n%!error <N must be positive> bitshift (10, [-2 -1 0 1 2], -1)\n*/\n\nDEFUN (flintmax, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{Imax} =} flintmax ()\n@deftypefnx {} {@var{Imax} =} flintmax (\"double\")\n@deftypefnx {} {@var{Imax} =} flintmax (\"single\")\n@deftypefnx {} {@var{Imax} =} flintmax (@var{var})\nReturn the largest integer that can be represented consecutively in a\nfloating point value.\n\nThe input is either a string specifying a floating point type, or it is an\nexisting floating point variable @var{var}.\n\nThe default type is @qcode{\"double\"}, but @qcode{\"single\"} is a valid option.\nOn IEEE@tie{}754 compatible systems, @code{flintmax} is @w{@math{2^{53}}}@ for\n@qcode{\"double\"} and @w{@math{2^{24}}}@ for @qcode{\"single\"}.\n\nExample Code - query an existing variable\n\n@example\n@group\nx = single (1);\nflintmax (x)\n  @xresult{} 16777216\n@end group\n@end example\n\n@seealso{intmax, realmax, realmin}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  std::string cname = \"double\";\n  if (nargin == 1)\n    {\n      if (args(0).is_string ())\n        cname = args(0).string_value ();\n      else if (args(0).isfloat ())\n        cname = args(0).class_name ();\n      else\n        error (\"intmin: argument must be a string or floating point variable\");\n    }\n\n  if (cname == \"double\")\n    return ovl (static_cast<double> (max_mantissa_value<double> () + 1));\n  else if (cname == \"single\")\n    return ovl (static_cast<float> (max_mantissa_value<float> () + 1));\n  else\n    error (\"flintmax: not defined for class '%s'\", cname.c_str ());\n}\n\n/*\n%!assert (flintmax (), 2^53)\n%!assert (flintmax (\"double\"), 2^53)\n%!assert (flintmax (\"single\"), single (2^24))\n\n%!test\n%! x = single (1);\n%! assert (flintmax (x), single (16777216));\n\n%!error flintmax (\"double\", 0)\n%!error <must be a string or floating point variable> flintmax (int8 (1))\n%!error <not defined for class 'int8'> flintmax (\"int8\")\n%!error <not defined for class 'char'> flintmax (\"char\")\n*/\n\nDEFUN (intmax, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{Imax} =} intmax ()\n@deftypefnx {} {@var{Imax} =} intmax (\"@var{type}\")\n@deftypefnx {} {@var{Imax} =} intmax (@var{var})\nReturn the largest integer that can be represented by a specific integer type.\n\nThe input is either a string @qcode{\"@var{type}\"} specifying an integer type,\nor it is an existing integer variable @var{var}.\n\nPossible values for @var{type} are\n\n@table @asis\n@item @qcode{\"int8\"}\nsigned 8-bit integer.\n\n@item @qcode{\"int16\"}\nsigned 16-bit integer.\n\n@item @qcode{\"int32\"}\nsigned 32-bit integer.\n\n@item @qcode{\"int64\"}\nsigned 64-bit integer.\n\n@item @qcode{\"uint8\"}\nunsigned 8-bit integer.\n\n@item @qcode{\"uint16\"}\nunsigned 16-bit integer.\n\n@item @qcode{\"uint32\"}\nunsigned 32-bit integer.\n\n@item @qcode{\"uint64\"}\nunsigned 64-bit integer.\n@end table\n\nThe default for @var{type} is @qcode{\"int32\"}.\n\nExample Code - query an existing variable\n\n@example\n@group\nx = int8 (1);\nintmax (x)\n  @xresult{} 127\n@end group\n@end example\n\n@seealso{intmin, flintmax}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  std::string cname = \"int32\";\n  if (nargin == 1)\n    {\n      if (args(0).is_string ())\n        cname = args(0).string_value ();\n      else if (args(0).isinteger ())\n        cname = args(0).class_name ();\n      else\n        error (\"intmax: argument must be a string or integer variable\");\n    }\n\n  octave_value retval;\n\n  if (cname == \"uint8\")\n    retval = octave_uint8 (std::numeric_limits<uint8_t>::max ());\n  else if (cname == \"uint16\")\n    retval = octave_uint16 (std::numeric_limits<uint16_t>::max ());\n  else if (cname == \"uint32\")\n    retval = octave_uint32 (std::numeric_limits<uint32_t>::max ());\n  else if (cname == \"uint64\")\n    retval = octave_uint64 (std::numeric_limits<uint64_t>::max ());\n  else if (cname == \"int8\")\n    retval = octave_int8 (std::numeric_limits<int8_t>::max ());\n  else if (cname == \"int16\")\n    retval = octave_int16 (std::numeric_limits<int16_t>::max ());\n  else if (cname == \"int32\")\n    retval = octave_int32 (std::numeric_limits<int32_t>::max ());\n  else if (cname == \"int64\")\n    retval = octave_int64 (std::numeric_limits<int64_t>::max ());\n  else\n    error (\"intmax: not defined for '%s' objects\", cname.c_str ());\n\n  return retval;\n}\n\n/*\n%!assert (intmax (),          int32 (2^31 - 1))\n%!assert (intmax (\"int8\"),     int8 (2^7 - 1))\n%!assert (intmax (\"uint8\"),   uint8 (2^8 - 1))\n%!assert (intmax (\"int16\"),   int16 (2^15 - 1))\n%!assert (intmax (\"uint16\"), uint16 (2^16 - 1))\n%!assert (intmax (\"int32\"),   int32 (2^31 - 1))\n%!assert (intmax (\"uint32\"), uint32 (2^32 - 1))\n%!assert (intmax (\"int64\"),   int64 (2^63 - 1))\n%!assert (intmax (\"uint64\"), uint64 (2^64 - 1))\n\n%!test\n%! x = int8 (1);\n%! assert (intmax (x), int8 (127));\n\n%!error intmax (\"int32\", 0)\n%!error <must be a string or integer variable> intmax (1.0)\n%!error <not defined for 'double' objects> intmax (\"double\")\n%!error <not defined for 'char' objects> intmax (\"char\")\n*/\n\nDEFUN (intmin, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{Imin} =} intmin ()\n@deftypefnx {} {@var{Imin} =} intmin (\"@var{type}\")\n@deftypefnx {} {@var{Imin} =} intmin (@var{var})\nReturn the smallest integer that can be represented by a specific integer type.\n\nThe input is either a string @qcode{\"@var{type}\"} specifying an integer type,\nor it is an existing integer variable @var{var}.\n\nPossible values for @var{type} are\n\n@table @asis\n@item @qcode{\"int8\"}\nsigned 8-bit integer.\n\n@item @qcode{\"int16\"}\nsigned 16-bit integer.\n\n@item @qcode{\"int32\"}\nsigned 32-bit integer.\n\n@item @qcode{\"int64\"}\nsigned 64-bit integer.\n\n@item @qcode{\"uint8\"}\nunsigned 8-bit integer.\n\n@item @qcode{\"uint16\"}\nunsigned 16-bit integer.\n\n@item @qcode{\"uint32\"}\nunsigned 32-bit integer.\n\n@item @qcode{\"uint64\"}\nunsigned 64-bit integer.\n@end table\n\nThe default for @var{type} is @qcode{\"int32\"}.\n\nExample Code - query an existing variable\n\n@example\n@group\nx = int8 (1);\nintmin (x)\n  @xresult{} -128\n@end group\n@end example\n\n@seealso{intmax, flintmax}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  std::string cname = \"int32\";\n  if (nargin == 1)\n    {\n      if (args(0).is_string ())\n        cname = args(0).string_value ();\n      else if (args(0).isinteger ())\n        cname = args(0).class_name ();\n      else\n        error (\"intmin: argument must be a string or integer variable\");\n    }\n\n  octave_value retval;\n\n  if (cname == \"uint8\")\n    retval = octave_uint8 (std::numeric_limits<uint8_t>::min ());\n  else if (cname == \"uint16\")\n    retval = octave_uint16 (std::numeric_limits<uint16_t>::min ());\n  else if (cname == \"uint32\")\n    retval = octave_uint32 (std::numeric_limits<uint32_t>::min ());\n  else if (cname == \"uint64\")\n    retval = octave_uint64 (std::numeric_limits<uint64_t>::min ());\n  else if (cname == \"int8\")\n    retval = octave_int8 (std::numeric_limits<int8_t>::min ());\n  else if (cname == \"int16\")\n    retval = octave_int16 (std::numeric_limits<int16_t>::min ());\n  else if (cname == \"int32\")\n    retval = octave_int32 (std::numeric_limits<int32_t>::min ());\n  else if (cname == \"int64\")\n    retval = octave_int64 (std::numeric_limits<int64_t>::min ());\n  else\n    error (\"intmin: not defined for '%s' objects\", cname.c_str ());\n\n  return retval;\n}\n\n/*\n%!assert (intmin (),          int32 (-2^31))\n%!assert (intmin (\"int8\"),     int8 (-2^7))\n%!assert (intmin (\"uint8\"),   uint8 (-2^8))\n%!assert (intmin (\"int16\"),   int16 (-2^15))\n%!assert (intmin (\"uint16\"), uint16 (-2^16))\n%!assert (intmin (\"int32\"),   int32 (-2^31))\n%!assert (intmin (\"uint32\"), uint32 (-2^32))\n%!assert (intmin (\"int64\"),   int64 (-2^63))\n%!assert (intmin (\"uint64\"), uint64 (-2^64))\n\n%!test\n%! x = int8 (1);\n%! assert (intmin (x), int8 (-128));\n\n%!error intmin (\"int32\", 0)\n%!error <must be a string or integer variable> intmin (1.0)\n%!error <not defined for 'double' objects> intmin (\"double\")\n%!error <not defined for 'char' objects> intmin (\"char\")\n*/\n\nDEFUN (sizemax, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{max_numel} =} sizemax ()\nReturn the largest value allowed for the size of an array.\n\nIf Octave is compiled with 64-bit indexing, the result is of class int64,\notherwise it is of class int32.  The maximum array size is slightly smaller\nthan the maximum value allowable for the relevant class as reported by\n@code{intmax}.\n@seealso{intmax}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return octave_value (octave_int<octave_idx_type> (dim_vector::dim_max ()));\n}\n\n/*\n%!assert (sizemax () >= (intmax (\"int32\") - 1))\n\n%!error sizemax (0)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/ccolamd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This is the octave interface to ccolamd, which bore the copyright given\n// in the help of the functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n\n#include \"CSparse.h\"\n#include \"Sparse.h\"\n#include \"dNDArray.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sparse.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"pager.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (ccolamd, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{p} =} ccolamd (@var{S})\n@deftypefnx {} {@var{p} =} ccolamd (@var{S}, @var{knobs})\n@deftypefnx {} {@var{p} =} ccolamd (@var{S}, @var{knobs}, @var{cmember})\n@deftypefnx {} {[@var{p}, @var{stats}] =} ccolamd (@dots{})\n\nConstrained column approximate minimum degree permutation.\n\n@code{@var{p} = ccolamd (@var{S})} returns the column approximate minimum\ndegree permutation vector for the sparse matrix @var{S}.  For a\nnon-symmetric matrix @var{S}, @code{@var{S}(:, @var{p})} tends to have\nsparser LU@tie{}factors than @var{S}.\n@code{chol (@var{S}(:, @var{p})' * @var{S}(:, @var{p}))} also tends to be\nsparser than @code{chol (@var{S}' * @var{S})}.\n@code{@var{p} = ccolamd (@var{S}, 1)} optimizes the ordering for\n@code{lu (@var{S}(:, @var{p}))}.  The ordering is followed by a column\nelimination tree post-ordering.\n\n@var{knobs} is an optional 1-element to 5-element input vector, with a\ndefault value of @code{[0 10 10 1 0]} if not present or empty.  Entries not\npresent are set to their defaults.\n\n@table @code\n@item @var{knobs}(1)\nif nonzero, the ordering is optimized for @code{lu (S(:, p))}.  It will be a\npoor ordering for @code{chol (@var{S}(:, @var{p})' * @var{S}(:, @var{p}))}.\nThis is the most important knob for ccolamd.\n\n@item @var{knobs}(2)\nif @var{S} is m-by-n, rows with more than\n@code{max (16, @var{knobs}(2) * sqrt (n))} entries are ignored.\n\n@item @var{knobs}(3)\ncolumns with more than\n@code{max (16, @var{knobs}(3) * sqrt (min (@var{m}, @var{n})))} entries are\nignored and ordered last in the output permutation\n(subject to the @var{cmember} constraints).\n\n@item @var{knobs}(4)\nif nonzero, aggressive absorption is performed.\n\n@item @var{knobs}(5)\nif nonzero, statistics and knobs are printed.\n\n@end table\n\n@var{cmember} is an optional vector of length @math{n}.  It defines the\nconstraints on the column ordering.  If @code{@var{cmember}(j) = @var{c}},\nthen column @var{j} is in constraint set @var{c} (@var{c} must be in the\nrange 1 to n).  In the output permutation @var{p}, all columns in set 1\nappear first, followed by all columns in set 2, and so on.\n@code{@var{cmember} = ones (1,n)} if not present or empty.\n@code{ccolamd (@var{S}, [], 1 : n)} returns @code{1 : n}\n\n@code{@var{p} = ccolamd (@var{S})} is about the same as\n@code{@var{p} = colamd (@var{S})}.  @var{knobs} and its default values\ndiffer.  @code{colamd} always does aggressive absorption, and it finds an\nordering suitable for both @code{lu (@var{S}(:, @var{p}))} and @code{chol\n(@var{S}(:, @var{p})' * @var{S}(:, @var{p}))}; it cannot optimize its\nordering for @code{lu (@var{S}(:, @var{p}))} to the extent that\n@code{ccolamd (@var{S}, 1)} can.\n\n@var{stats} is an optional 20-element output vector that provides data\nabout the ordering and the validity of the input matrix @var{S}.  Ordering\nstatistics are in @code{@var{stats}(1 : 3)}.  @code{@var{stats}(1)} and\n@code{@var{stats}(2)} are the number of dense or empty rows and columns\nignored by @sc{ccolamd} and @code{@var{stats}(3)} is the number of garbage\ncollections performed on the internal data structure used by @sc{ccolamd}\n(roughly of size @code{2.2 * nnz (@var{S}) + 4 * @var{m} + 7 * @var{n}}\nintegers).\n\n@code{@var{stats}(4 : 7)} provide information if CCOLAMD was able to\ncontinue.  The matrix is OK if @code{@var{stats}(4)} is zero, or 1 if\ninvalid.  @code{@var{stats}(5)} is the rightmost column index that is\nunsorted or contains duplicate entries, or zero if no such column exists.\n@code{@var{stats}(6)} is the last seen duplicate or out-of-order row\nindex in the column index given by @code{@var{stats}(5)}, or zero if no\nsuch row index exists.  @code{@var{stats}(7)} is the number of duplicate\nor out-of-order row indices.  @code{@var{stats}(8 : 20)} is always zero in\nthe current version of @sc{ccolamd} (reserved for future use).\n\nThe authors of the code itself are @nospell{S. Larimore, T. Davis} and\n@nospell{S. Rajamanickam} in collaboration with @nospell{J. Bilbert and E. Ng}.\nSupported by the National Science Foundation\n@nospell{(DMS-9504974, DMS-9803599, CCR-0203270)}, and a grant from\n@nospell{Sandia} National Lab.\nSee @url{http://faculty.cse.tamu.edu/davis/suitesparse.html} for ccolamd,\ncsymamd, amd, colamd, symamd, and other related orderings.\n@seealso{colamd, csymamd}\n@end deftypefn */)\n{\n#if defined (HAVE_CCOLAMD)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  octave_value_list retval (nargout == 2 ? 2 : 1);\n  int spumoni = 0;\n\n  // Get knobs\n  static_assert (CCOLAMD_KNOBS <= 40,\n                 \"ccolamd: # of CCOLAMD_KNOBS exceeded.  Please report this to bugs.octave.org\");\n  double knob_storage[CCOLAMD_KNOBS];\n  double *knobs = &knob_storage[0];\n  CCOLAMD_NAME (_set_defaults) (knobs);\n\n  // Check for user-passed knobs\n  if (nargin > 1)\n    {\n      NDArray User_knobs = args(1).array_value ();\n      int nel_User_knobs = User_knobs.numel ();\n\n      if (nel_User_knobs > 0)\n        knobs[CCOLAMD_LU] = (User_knobs(0) != 0);\n      if (nel_User_knobs > 1)\n        knobs[CCOLAMD_DENSE_ROW] = User_knobs(1);\n      if (nel_User_knobs > 2)\n        knobs[CCOLAMD_DENSE_COL] = User_knobs(2);\n      if (nel_User_knobs > 3)\n        knobs[CCOLAMD_AGGRESSIVE] = (User_knobs(3) != 0);\n      if (nel_User_knobs > 4)\n        spumoni = (User_knobs(4) != 0);\n\n      // print knob settings if spumoni is set\n      if (spumoni)\n        {\n          octave_stdout << \"\\nccolamd version \" << CCOLAMD_MAIN_VERSION << '.'\n                        <<  CCOLAMD_SUB_VERSION << \", \" << CCOLAMD_DATE\n                        << \":\\nknobs(1): \" << User_knobs(0) << \", order for \";\n          if (knobs[CCOLAMD_LU] != 0)\n            octave_stdout << \"lu (A)\\n\";\n          else\n            octave_stdout << \"chol (A'*A)\\n\";\n\n          if (knobs[CCOLAMD_DENSE_ROW] >= 0)\n            octave_stdout << \"knobs(2): \" << User_knobs(1)\n                          << \", rows with > max (16,\"\n                          << knobs[CCOLAMD_DENSE_ROW]\n                          << \"* sqrt (columns(A)))\"\n                          << \" entries removed\\n\";\n          else\n            octave_stdout << \"knobs(2): \" << User_knobs(1)\n                          << \", no dense rows removed\\n\";\n\n          if (knobs[CCOLAMD_DENSE_COL] >= 0)\n            octave_stdout << \"knobs(3): \" << User_knobs(2)\n                          << \", cols with > max (16,\"\n                          << knobs[CCOLAMD_DENSE_COL] << \"* sqrt (size(A)))\"\n                          << \" entries removed\\n\";\n          else\n            octave_stdout << \"knobs(3): \" << User_knobs(2)\n                          << \", no dense columns removed\\n\";\n\n          if (knobs[CCOLAMD_AGGRESSIVE] != 0)\n            octave_stdout << \"knobs(4): \" << User_knobs(3)\n                          << \", aggressive absorption: yes\";\n          else\n            octave_stdout << \"knobs(4): \" << User_knobs(3)\n                          << \", aggressive absorption: no\";\n\n          octave_stdout << \"knobs(5): \" << User_knobs(4)\n                        << \", statistics and knobs printed\\n\";\n        }\n    }\n\n  octave_idx_type n_row, n_col, nnz;\n  octave_idx_type *ridx, *cidx;\n  SparseComplexMatrix scm;\n  SparseMatrix sm;\n\n  if (args(0).issparse ())\n    {\n      if (args(0).iscomplex ())\n        {\n          scm = args(0).sparse_complex_matrix_value ();\n          n_row = scm.rows ();\n          n_col = scm.cols ();\n          nnz = scm.nnz ();\n          ridx = scm.xridx ();\n          cidx = scm.xcidx ();\n        }\n      else\n        {\n          sm = args(0).sparse_matrix_value ();\n\n          n_row = sm.rows ();\n          n_col = sm.cols ();\n          nnz = sm.nnz ();\n          ridx = sm.xridx ();\n          cidx = sm.xcidx ();\n        }\n    }\n  else\n    {\n      if (args(0).iscomplex ())\n        sm = SparseMatrix (real (args(0).complex_matrix_value ()));\n      else\n        sm = SparseMatrix (args(0).matrix_value ());\n\n      n_row = sm.rows ();\n      n_col = sm.cols ();\n      nnz = sm.nnz ();\n      ridx = sm.xridx ();\n      cidx = sm.xcidx ();\n    }\n\n  // Allocate workspace for ccolamd\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, p, n_col+1);\n  for (octave_idx_type i = 0; i < n_col+1; i++)\n    p[i] = cidx[i];\n\n  octave_idx_type Alen = CCOLAMD_NAME (_recommended) (nnz, n_row, n_col);\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, A, Alen);\n  for (octave_idx_type i = 0; i < nnz; i++)\n    A[i] = ridx[i];\n\n  static_assert (CCOLAMD_STATS <= 40,\n                 \"ccolamd: # of CCOLAMD_STATS exceeded.  Please report this to bugs.octave.org\");\n  suitesparse_integer stats_storage[CCOLAMD_STATS];\n  suitesparse_integer *stats = &stats_storage[0];\n\n  if (nargin > 2)\n    {\n      NDArray in_cmember = args(2).array_value ();\n      octave_idx_type cslen = in_cmember.numel ();\n      OCTAVE_LOCAL_BUFFER (suitesparse_integer, cmember, cslen);\n      for (octave_idx_type i = 0; i < cslen; i++)\n        // convert cmember from 1-based to 0-based\n        cmember[i] = static_cast<suitesparse_integer> (in_cmember(i) - 1);\n\n      if (cslen != n_col)\n        error (\"ccolamd: CMEMBER must be of length equal to #cols of A\");\n\n      // Order the columns (destroys A)\n      if (! CCOLAMD_NAME () (n_row, n_col, Alen, A, p, knobs, stats, cmember))\n        {\n          CCOLAMD_NAME (_report) (stats);\n\n          error (\"ccolamd: internal error!\");\n        }\n    }\n  else\n    {\n      // Order the columns (destroys A)\n      if (! CCOLAMD_NAME () (n_row, n_col, Alen, A, p, knobs, stats, nullptr))\n        {\n          CCOLAMD_NAME (_report) (stats);\n\n          error (\"ccolamd: internal error!\");\n        }\n    }\n\n  // return the permutation vector\n  NDArray out_perm (dim_vector (1, n_col));\n  for (octave_idx_type i = 0; i < n_col; i++)\n    out_perm(i) = p[i] + 1;\n\n  retval(0) = out_perm;\n\n  // print stats if spumoni > 0\n  if (spumoni > 0)\n    CCOLAMD_NAME (_report) (stats);\n\n  // Return the stats vector\n  if (nargout == 2)\n    {\n      NDArray out_stats (dim_vector (1, CCOLAMD_STATS));\n      for (octave_idx_type i = 0 ; i < CCOLAMD_STATS ; i++)\n        out_stats(i) = stats[i];\n      retval(1) = out_stats;\n\n      // fix stats (5) and (6), for 1-based information on\n      // jumbled matrix.  note that this correction doesn't\n      // occur if symamd returns FALSE\n      out_stats(CCOLAMD_INFO1)++;\n      out_stats(CCOLAMD_INFO2)++;\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"ccolamd\", \"CCOLAMD\");\n\n#endif\n}\n\nDEFUN (csymamd, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{p} =} csymamd (@var{S})\n@deftypefnx {} {@var{p} =} csymamd (@var{S}, @var{knobs})\n@deftypefnx {} {@var{p} =} csymamd (@var{S}, @var{knobs}, @var{cmember})\n@deftypefnx {} {[@var{p}, @var{stats}] =} csymamd (@dots{})\n\nFor a symmetric positive definite matrix @var{S}, return the permutation\nvector @var{p} such that @code{@var{S}(@var{p},@var{p})} tends to have a\nsparser Cholesky@tie{}factor than @var{S}.\n\nSometimes @code{csymamd} works well for symmetric indefinite matrices too.\nThe matrix @var{S} is assumed to be symmetric; only the strictly lower\ntriangular part is referenced.  @var{S} must be square.  The ordering is\nfollowed by an elimination tree post-ordering.\n\n@var{knobs} is an optional 1-element to 3-element input vector, with a\ndefault value of @code{[10 1 0]}.  Entries not present are set to their\ndefaults.\n\n@table @code\n@item @var{knobs}(1)\nIf @var{S} is n-by-n, then rows and columns with more than\n@code{max(16,@var{knobs}(1)*sqrt(n))} entries are ignored, and ordered\nlast in the output permutation (subject to the cmember constraints).\n\n@item @var{knobs}(2)\nIf nonzero, aggressive absorption is performed.\n\n@item @var{knobs}(3)\nIf nonzero, statistics and knobs are printed.\n\n@end table\n\n@var{cmember} is an optional vector of length n.  It defines the constraints\non the ordering.  If @code{@var{cmember}(j) = @var{S}}, then row/column j is\nin constraint set @var{c} (@var{c} must be in the range 1 to n).  In the\noutput permutation @var{p}, rows/columns in set 1 appear first, followed\nby all rows/columns in set 2, and so on.  @code{@var{cmember} = ones (1,n)}\nif not present or empty.  @code{csymamd (@var{S},[],1:n)} returns\n@code{1:n}.\n\n@code{@var{p} = csymamd (@var{S})} is about the same as\n@code{@var{p} = symamd (@var{S})}.  @var{knobs} and its default values\ndiffer.\n\n@code{@var{stats}(4:7)} provide information if CCOLAMD was able to\ncontinue.  The matrix is OK if @code{@var{stats}(4)} is zero, or 1 if\ninvalid.  @code{@var{stats}(5)} is the rightmost column index that is\nunsorted or contains duplicate entries, or zero if no such column exists.\n@code{@var{stats}(6)} is the last seen duplicate or out-of-order row\nindex in the column index given by @code{@var{stats}(5)}, or zero if no\nsuch row index exists.  @code{@var{stats}(7)} is the number of duplicate\nor out-of-order row indices.  @code{@var{stats}(8:20)} is always zero in\nthe current version of @sc{ccolamd} (reserved for future use).\n\nThe authors of the code itself are @nospell{S. Larimore, T. Davis} and\n@nospell{S. Rajamanickam} in collaboration with @nospell{J. Bilbert and E. Ng}.\nSupported by the National Science Foundation\n@nospell{(DMS-9504974, DMS-9803599, CCR-0203270)}, and a grant from\n@nospell{Sandia} National Lab.\nSee @url{http://faculty.cse.tamu.edu/davis/suitesparse.html} for ccolamd,\ncolamd, csymamd, amd, colamd, symamd, and other related orderings.\n@seealso{symamd, ccolamd}\n@end deftypefn */)\n{\n#if defined (HAVE_CCOLAMD)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  octave_value_list retval (nargout == 2 ? 2 : 1);\n  int spumoni = 0;\n\n  // Get knobs\n  static_assert (CCOLAMD_KNOBS <= 40,\n                 \"csymamd: # of CCOLAMD_KNOBS exceeded.  Please report this to bugs.octave.org\");\n  double knob_storage[CCOLAMD_KNOBS];\n  double *knobs = &knob_storage[0];\n  CCOLAMD_NAME (_set_defaults) (knobs);\n\n  // Check for user-passed knobs\n  if (nargin > 1)\n    {\n      NDArray User_knobs = args(1).array_value ();\n      int nel_User_knobs = User_knobs.numel ();\n\n      if (nel_User_knobs > 0)\n        knobs[CCOLAMD_DENSE_ROW] = User_knobs(0);\n      if (nel_User_knobs > 1)\n        knobs[CCOLAMD_AGGRESSIVE] = User_knobs(1);\n      if (nel_User_knobs > 2)\n        spumoni = static_cast<int> (User_knobs(2));\n\n      // print knob settings if spumoni is set\n      if (spumoni)\n        {\n          octave_stdout << \"\\ncsymamd version \" << CCOLAMD_MAIN_VERSION\n                        << '.' << CCOLAMD_SUB_VERSION\n                        << \", \" << CCOLAMD_DATE << \"\\n\";\n\n          if (knobs[CCOLAMD_DENSE_ROW] >= 0)\n            octave_stdout << \"knobs(1): \" << User_knobs(0)\n                          << \", rows/cols with > max (16,\"\n                          << knobs[CCOLAMD_DENSE_ROW]\n                          << \"* sqrt (columns(A)))\"\n                          << \" entries removed\\n\";\n          else\n            octave_stdout << \"knobs(1): \" << User_knobs(0)\n                          << \", no dense rows/cols removed\\n\";\n\n          if (knobs[CCOLAMD_AGGRESSIVE] != 0)\n            octave_stdout << \"knobs(2): \" << User_knobs(1)\n                          << \", aggressive absorption: yes\";\n          else\n            octave_stdout << \"knobs(2): \" << User_knobs(1)\n                          << \", aggressive absorption: no\";\n\n          octave_stdout << \"knobs(3): \" << User_knobs(2)\n                        << \", statistics and knobs printed\\n\";\n        }\n    }\n\n  octave_idx_type n_row, n_col;\n  octave_idx_type *ridx, *cidx;\n  SparseMatrix sm;\n  SparseComplexMatrix scm;\n\n  if (args(0).issparse ())\n    {\n      if (args(0).iscomplex ())\n        {\n          scm = args(0).sparse_complex_matrix_value ();\n          n_row = scm.rows ();\n          n_col = scm.cols ();\n          ridx = scm.xridx ();\n          cidx = scm.xcidx ();\n        }\n      else\n        {\n          sm = args(0).sparse_matrix_value ();\n          n_row = sm.rows ();\n          n_col = sm.cols ();\n          ridx = sm.xridx ();\n          cidx = sm.xcidx ();\n        }\n    }\n  else\n    {\n      if (args(0).iscomplex ())\n        sm = SparseMatrix (real (args(0).complex_matrix_value ()));\n      else\n        sm = SparseMatrix (args(0).matrix_value ());\n\n      n_row = sm.rows ();\n      n_col = sm.cols ();\n      ridx = sm.xridx ();\n      cidx = sm.xcidx ();\n    }\n\n  if (n_row != n_col)\n    err_square_matrix_required (\"csymamd\", \"S\");\n\n  // Allocate workspace for symamd\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, perm, n_col+1);\n  static_assert (CCOLAMD_STATS <= 40,\n                 \"csymamd: # of CCOLAMD_STATS exceeded.  Please report this to bugs.octave.org\");\n  suitesparse_integer stats_storage[CCOLAMD_STATS];\n  suitesparse_integer *stats = &stats_storage[0];\n\n  if (nargin > 2)\n    {\n      NDArray in_cmember = args(2).array_value ();\n      octave_idx_type cslen = in_cmember.numel ();\n      OCTAVE_LOCAL_BUFFER (suitesparse_integer, cmember, cslen);\n      for (octave_idx_type i = 0; i < cslen; i++)\n        // convert cmember from 1-based to 0-based\n        cmember[i] = static_cast<octave_idx_type> (in_cmember(i) - 1);\n\n      if (cslen != n_col)\n        error (\"csymamd: CMEMBER must be of length equal to #cols of A\");\n\n      if (! CSYMAMD_NAME () (n_col,\n                             to_suitesparse_intptr (ridx),\n                             to_suitesparse_intptr (cidx),\n                             perm, knobs, stats, &calloc, &free, cmember, -1))\n        {\n          CSYMAMD_NAME (_report)(stats);\n\n          error (\"csymamd: internal error!\");\n        }\n    }\n  else\n    {\n      if (! CSYMAMD_NAME () (n_col,\n                             to_suitesparse_intptr (ridx),\n                             to_suitesparse_intptr (cidx),\n                             perm, knobs, stats, &calloc, &free, nullptr, -1))\n        {\n          CSYMAMD_NAME (_report)(stats);\n\n          error (\"csymamd: internal error!\");\n        }\n    }\n\n  // return the permutation vector\n  NDArray out_perm (dim_vector (1, n_col));\n  for (octave_idx_type i = 0; i < n_col; i++)\n    out_perm(i) = perm[i] + 1;\n\n  retval(0) = out_perm;\n\n  // print stats if spumoni > 0\n  if (spumoni > 0)\n    CSYMAMD_NAME (_report)(stats);\n\n  // Return the stats vector\n  if (nargout == 2)\n    {\n      NDArray out_stats (dim_vector (1, CCOLAMD_STATS));\n      for (octave_idx_type i = 0 ; i < CCOLAMD_STATS ; i++)\n        out_stats(i) = stats[i];\n      retval(1) = out_stats;\n\n      // fix stats (5) and (6), for 1-based information on\n      // jumbled matrix.  note that this correction doesn't\n      // occur if symamd returns FALSE\n      out_stats(CCOLAMD_INFO1)++;\n      out_stats(CCOLAMD_INFO2)++;\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"csymamd\", \"CCOLAMD\");\n\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/chol.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"Matrix.h\"\n#include \"chol.h\"\n#include \"oct-string.h\"\n#include \"sparse-chol.h\"\n#include \"sparse-util.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename CHOLT>\nstatic octave_value\nget_chol (const CHOLT& fact)\n{\n  return octave_value (fact.chol_matrix());\n}\n\ntemplate <typename CHOLT>\nstatic octave_value\nget_chol_r (const CHOLT& fact)\n{\n  return octave_value (fact.chol_matrix (),\n                       MatrixType (MatrixType::Upper));\n}\n\ntemplate <typename CHOLT>\nstatic octave_value\nget_chol_l (const CHOLT& fact)\n{\n  return octave_value (fact.chol_matrix ().transpose (),\n                       MatrixType (MatrixType::Lower));\n}\n\nDEFUN (chol, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{R} =} chol (@var{A})\n@deftypefnx {} {[@var{R}, @var{p}] =} chol (@var{A})\n@deftypefnx {} {[@var{R}, @var{p}, @var{Q}] =} chol (@var{A})\n@deftypefnx {} {[@var{R}, @var{p}, @var{Q}] =} chol (@var{A}, \"vector\")\n@deftypefnx {} {[@var{L}, @dots{}] =} chol (@dots{}, \"lower\")\n@deftypefnx {} {[@var{R}, @dots{}] =} chol (@dots{}, \"upper\")\n@cindex Cholesky factorization\nCompute the upper Cholesky@tie{}factor, @var{R}, of the real symmetric\nor complex Hermitian positive definite matrix @var{A}.\n\nThe upper Cholesky@tie{}factor @var{R} is computed by using the upper\ntriangular part of matrix @var{A} and is defined by\n@tex\n$ R^T R = A $.\n@end tex\n@ifnottex\n\n@example\n@var{R}' * @var{R} = @var{A}.\n@end example\n\n@end ifnottex\n\nCalling @code{chol} using the optional @qcode{\"upper\"} flag has the\nsame behavior.  In contrast, using the optional @qcode{\"lower\"} flag,\n@code{chol} returns the lower triangular factorization, computed by using\nthe lower triangular part of matrix @var{A}, such that\n@tex\n$ L L^T = A $.\n@end tex\n@ifnottex\n\n@example\n@var{L} * @var{L}' = @var{A}.\n@end example\n\n@end ifnottex\n\nCalled with one output argument @code{chol} fails if matrix @var{A} is\nnot positive definite.  Note that if matrix @var{A} is not real symmetric\nor complex Hermitian then the lower triangular part is considered to be\nthe (complex conjugate) transpose of the upper triangular part, or vice\nversa, given the @qcode{\"lower\"} flag.\n\nCalled with two or more output arguments @var{p} flags whether the matrix\n@var{A} was positive definite and @code{chol} does not fail.  A zero value\nof @var{p} indicates that matrix @var{A} is positive definite and @var{R}\ngives the factorization.  Otherwise, @var{p} will have a positive value.\n\nIf called with three output arguments matrix @var{A} must be sparse and\na sparsity preserving row/column permutation is applied to matrix @var{A}\nprior to the factorization.  That is @var{R} is the factorization of\n@code{@var{A}(@var{Q},@var{Q})} such that\n@tex\n$ R^T R = Q^T A Q$.\n@end tex\n@ifnottex\n\n@example\n@var{R}' * @var{R} = @var{Q}' * @var{A} * @var{Q}.\n@end example\n\n@end ifnottex\n\nThe sparsity preserving permutation is generally returned as a matrix.\nHowever, given the optional flag @qcode{\"vector\"}, @var{Q} will be\nreturned as a vector such that\n@tex\n$ R^T R = A (Q, Q)$.\n@end tex\n@ifnottex\n\n@example\n@var{R}' * @var{R} = @var{A}(@var{Q}, @var{Q}).\n@end example\n\n@end ifnottex\n\nIn general the lower triangular factorization is significantly faster for\nsparse matrices.\n@seealso{hess, lu, qr, qz, schur, svd, ichol, cholinv, chol2inv, cholupdate,\ncholinsert, choldelete, cholshift}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3 || nargout > 3)\n    print_usage ();\n  if (nargout > 2 && ! args(0).issparse ())\n    error (\"chol: using three output arguments, matrix A must be sparse\");\n\n  bool LLt = false;\n  bool vecout = false;\n\n  int n = 1;\n  while (n < nargin)\n    {\n      std::string tmp = args(n++).xstring_value (\"chol: optional arguments must be strings\");\n\n      if (string::strcmpi (tmp, \"vector\"))\n        vecout = true;\n      else if (string::strcmpi (tmp, \"lower\"))\n        LLt = true;\n      else if (string::strcmpi (tmp, \"upper\"))\n        LLt = false;\n      else\n        error (R\"(chol: optional argument must be one of \"vector\", \"lower\", or \"upper\")\");\n    }\n\n  octave_value_list retval;\n  octave_value arg = args(0);\n\n  if (arg.isempty ())\n    return ovl (Matrix ());\n\n  if (arg.issparse ())\n    {\n      octave_idx_type info;\n      bool natural = (nargout != 3);\n      bool force = nargout > 1;\n\n      if (arg.isreal ())\n        {\n          SparseMatrix m = arg.sparse_matrix_value ();\n\n          math::sparse_chol<SparseMatrix> fact (m, info, natural, force);\n\n          if (nargout == 3)\n            {\n              if (vecout)\n                retval(2) = fact.perm ();\n              else\n                retval(2) = fact.Q ();\n            }\n\n          if (nargout >= 2 || info == 0)\n            {\n              retval(1) = info;\n              if (LLt)\n                retval(0) = fact.L ();\n              else\n                retval(0) = fact.R ();\n            }\n          else\n            error (\"chol: input matrix must be positive definite\");\n        }\n      else if (arg.iscomplex ())\n        {\n          SparseComplexMatrix m = arg.sparse_complex_matrix_value ();\n\n          math::sparse_chol<SparseComplexMatrix> fact (m, info, natural, force);\n\n          if (nargout == 3)\n            {\n              if (vecout)\n                retval(2) = fact.perm ();\n              else\n                retval(2) = fact.Q ();\n            }\n\n          if (nargout >= 2 || info == 0)\n            {\n              retval(1) = info;\n              if (LLt)\n                retval(0) = fact.L ();\n              else\n                retval(0) = fact.R ();\n            }\n          else\n            error (\"chol: input matrix must be positive definite\");\n        }\n      else\n        err_wrong_type_arg (\"chol\", arg);\n    }\n  else if (arg.is_single_type ())\n    {\n      if (vecout)\n        error (R\"(chol: A must be sparse for the \"vector\" option)\");\n      if (arg.isreal ())\n        {\n          FloatMatrix m = arg.float_matrix_value ();\n\n          octave_idx_type info;\n\n          math::chol<FloatMatrix> fact (m, info, LLt != true);\n\n          if (nargout == 2 || info == 0)\n            retval = ovl (get_chol (fact), info);\n          else\n            error (\"chol: input matrix must be positive definite\");\n        }\n      else if (arg.iscomplex ())\n        {\n          FloatComplexMatrix m = arg.float_complex_matrix_value ();\n\n          octave_idx_type info;\n\n          math::chol<FloatComplexMatrix> fact (m, info, LLt != true);\n\n          if (nargout == 2 || info == 0)\n            retval = ovl (get_chol (fact), info);\n          else\n            error (\"chol: input matrix must be positive definite\");\n        }\n      else\n        err_wrong_type_arg (\"chol\", arg);\n    }\n  else\n    {\n      if (vecout)\n        error (R\"(chol: A must be sparse for the \"vector\" option)\");\n      if (arg.isreal ())\n        {\n          Matrix m = arg.matrix_value ();\n\n          octave_idx_type info;\n\n          math::chol<Matrix> fact (m, info, LLt != true);\n\n          if (nargout == 2 || info == 0)\n            retval = ovl (get_chol (fact), info);\n          else\n            error (\"chol: input matrix must be positive definite\");\n        }\n      else if (arg.iscomplex ())\n        {\n          ComplexMatrix m = arg.complex_matrix_value ();\n\n          octave_idx_type info;\n\n          math::chol<ComplexMatrix> fact (m, info, LLt != true);\n\n          if (nargout == 2 || info == 0)\n            retval = ovl (get_chol (fact), info);\n          else\n            error (\"chol: input matrix must be positive definite\");\n        }\n      else\n        err_wrong_type_arg (\"chol\", arg);\n    }\n\n  return retval;\n}\n\n/*\n%!assert (chol ([2, 1; 1, 1]), [sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)], sqrt (eps))\n%!assert (chol (single ([2, 1; 1, 1])),\n%!        single ([sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)]), sqrt (eps (\"single\")))\n\n%!assert (chol ([2, 1; 1, 1], \"upper\"), [sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)],\n%!        sqrt (eps))\n%!assert (chol ([2, 1; 1, 1], \"lower\"), [sqrt(2), 0; 1/sqrt(2), 1/sqrt(2)],\n%!        sqrt (eps))\n\n%!assert (chol ([2, 1; 1, 1], \"lower\"), chol ([2, 1; 1, 1], \"LoweR\"))\n%!assert (chol ([2, 1; 1, 1], \"upper\"), chol ([2, 1; 1, 1], \"Upper\"))\n\n## Check the \"vector\" option which only affects the 3rd argument and\n## is only valid for sparse input.\n%!testif HAVE_CHOLMOD\n%! a = sparse ([2 1; 1 1]);\n%! r = sparse ([sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)]);\n%! [rd, pd, qd] = chol (a);\n%! [rv, pv, qv] = chol (a, \"vector\");\n%! assert (r, rd, eps);\n%! assert (r, rv, eps);\n%! assert (pd, 0);\n%! assert (pd, pv);\n%! assert (qd, sparse (eye (2)));\n%! assert (qv, [1 2]);\n%!\n%! [rv, pv, qv] = chol (a, \"Vector\"); # check case sensitivity\n%! assert (r, rv, eps);\n%! assert (pd, pv);\n%! assert (qv, [1 2]);\n\n%!testif HAVE_CHOLMOD <*42587>\n%! A = sparse ([1 0 8;0 1 8;8 8 1]);\n%! [Q, p] = chol (A);\n%! assert (p != 0);\n\n%!error chol ()\n%!error <matrix must be positive definite> chol ([1, 2; 3, 4])\n%!error <requires square matrix> chol ([1, 2; 3, 4; 5, 6])\n%!error <optional arguments must be strings> chol (1, 2)\n%!error <optional argument must be one of \"vector\", \"lower\"> chol (1, \"foobar\")\n%!error <matrix A must be sparse> [L,p,Q] = chol ([1, 2; 3, 4])\n%!error <A must be sparse> [L, p] = chol ([1, 2; 3, 4], \"vector\")\n*/\n\nDEFUN (cholinv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{Ainv} =} cholinv (@var{A})\nCompute the inverse of the symmetric positive definite matrix @var{A} using\nthe Cholesky@tie{}factorization.\n@seealso{chol, chol2inv, inv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value retval;\n  octave_value arg = args(0);\n\n  octave_idx_type nr = arg.rows ();\n  octave_idx_type nc = arg.columns ();\n\n  if (nr == 0 || nc == 0)\n    retval = Matrix ();\n  else\n    {\n      if (arg.issparse ())\n        {\n          octave_idx_type info;\n\n          if (arg.isreal ())\n            {\n              SparseMatrix m = arg.sparse_matrix_value ();\n\n              math::sparse_chol<SparseMatrix> chol (m, info);\n\n              if (info == 0)\n                retval = chol.inverse ();\n              else\n                error (\"cholinv: A must be positive definite\");\n            }\n          else if (arg.iscomplex ())\n            {\n              SparseComplexMatrix m = arg.sparse_complex_matrix_value ();\n\n              math::sparse_chol<SparseComplexMatrix> chol (m, info);\n\n              if (info == 0)\n                retval = chol.inverse ();\n              else\n                error (\"cholinv: A must be positive definite\");\n            }\n          else\n            err_wrong_type_arg (\"cholinv\", arg);\n        }\n      else if (arg.is_single_type ())\n        {\n          if (arg.isreal ())\n            {\n              FloatMatrix m = arg.float_matrix_value ();\n\n              octave_idx_type info;\n              math::chol<FloatMatrix> chol (m, info);\n              if (info == 0)\n                retval = chol.inverse ();\n              else\n                error (\"cholinv: A must be positive definite\");\n            }\n          else if (arg.iscomplex ())\n            {\n              FloatComplexMatrix m = arg.float_complex_matrix_value ();\n\n              octave_idx_type info;\n              math::chol<FloatComplexMatrix> chol (m, info);\n              if (info == 0)\n                retval = chol.inverse ();\n              else\n                error (\"cholinv: A must be positive definite\");\n            }\n          else\n            err_wrong_type_arg (\"chol\", arg);\n        }\n      else\n        {\n          if (arg.isreal ())\n            {\n              Matrix m = arg.matrix_value ();\n\n              octave_idx_type info;\n              math::chol<Matrix> chol (m, info);\n              if (info == 0)\n                retval = chol.inverse ();\n              else\n                error (\"cholinv: A must be positive definite\");\n            }\n          else if (arg.iscomplex ())\n            {\n              ComplexMatrix m = arg.complex_matrix_value ();\n\n              octave_idx_type info;\n              math::chol<ComplexMatrix> chol (m, info);\n              if (info == 0)\n                retval = chol.inverse ();\n              else\n                error (\"cholinv: A must be positive definite\");\n            }\n          else\n            err_wrong_type_arg (\"chol\", arg);\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!shared A, Ainv\n%! A = [2,0.2;0.2,1];\n%! Ainv = inv (A);\n%!test\n%! Ainv1 = cholinv (A);\n%! assert (norm (Ainv-Ainv1), 0, 1e-10);\n%!testif HAVE_CHOLMOD\n%! Ainv2 = inv (sparse (A));\n%! assert (norm (Ainv-Ainv2), 0, 1e-10);\n%!testif HAVE_CHOLMOD\n%! Ainv3 = cholinv (sparse (A));\n%! assert (norm (Ainv-Ainv3), 0, 1e-10);\n*/\n\nDEFUN (chol2inv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{Ainv} =} chol2inv (@var{R})\nInvert a symmetric, positive definite square matrix from its Cholesky\ndecomposition, @var{R}.\n\nNote that @var{R} should be an upper-triangular matrix with positive diagonal\nelements.  @code{chol2inv (@var{U})} provides @code{inv (@var{R}'*@var{R})} but\nis much faster than using @code{inv}.\n@seealso{chol, cholinv, inv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value retval;\n\n  octave_value arg = args(0);\n\n  octave_idx_type nr = arg.rows ();\n  octave_idx_type nc = arg.columns ();\n\n  if (nr == 0 || nc == 0)\n    retval = Matrix ();\n  else\n    {\n      if (arg.issparse ())\n        {\n          if (arg.isreal ())\n            {\n              SparseMatrix r = arg.sparse_matrix_value ();\n\n              retval = math::chol2inv (r);\n            }\n          else if (arg.iscomplex ())\n            {\n              SparseComplexMatrix r = arg.sparse_complex_matrix_value ();\n\n              retval = math::chol2inv (r);\n            }\n          else\n            err_wrong_type_arg (\"chol2inv\", arg);\n        }\n      else if (arg.is_single_type ())\n        {\n          if (arg.isreal ())\n            {\n              FloatMatrix r = arg.float_matrix_value ();\n\n              retval = math::chol2inv (r);\n            }\n          else if (arg.iscomplex ())\n            {\n              FloatComplexMatrix r = arg.float_complex_matrix_value ();\n\n              retval = math::chol2inv (r);\n            }\n          else\n            err_wrong_type_arg (\"chol2inv\", arg);\n\n        }\n      else\n        {\n          if (arg.isreal ())\n            {\n              Matrix r = arg.matrix_value ();\n\n              retval = math::chol2inv (r);\n            }\n          else if (arg.iscomplex ())\n            {\n              ComplexMatrix r = arg.complex_matrix_value ();\n\n              retval = math::chol2inv (r);\n            }\n          else\n            err_wrong_type_arg (\"chol2inv\", arg);\n        }\n    }\n\n  return retval;\n}\n\n/*\n\n## Test for bug #36437\n%!function sparse_chol2inv (T, tol)\n%!  iT = inv (T);\n%!  ciT = chol2inv (chol (T));\n%!  assert (ciT, iT, tol);\n%!  assert (chol2inv (chol ( full (T))), ciT, tol*2);\n%!endfunction\n\n%!testif HAVE_CHOLMOD\n%! A = gallery (\"poisson\", 3);\n%! sparse_chol2inv (A, eps);\n\n%!testif HAVE_CHOLMOD\n%! n = 10;\n%! B = spdiags (ones (n, 1) * [1 2 1], [-1 0 1], n, n);\n%! sparse_chol2inv (B, eps*100);\n\n%!testif HAVE_CHOLMOD\n%! C = gallery (\"tridiag\", 5);\n%! sparse_chol2inv (C, eps*10);\n\n%!testif HAVE_CHOLMOD\n%! D = gallery (\"wathen\", 1, 1);\n%! sparse_chol2inv (D, eps*10^4);\n\n*/\n\nDEFUN (cholupdate, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{R1}, @var{info}] =} cholupdate (@var{R}, @var{u}, @var{op})\nUpdate or downdate a Cholesky@tie{}factorization.\n\nGiven an upper triangular matrix @var{R} and a column vector @var{u},\nattempt to determine another upper triangular matrix @var{R1} such that\n\n@itemize @bullet\n@item\n@var{R1}'*@var{R1} = @var{R}'*@var{R} + @var{u}*@var{u}'\nif @var{op} is @qcode{\"+\"}\n\n@item\n@var{R1}'*@var{R1} = @var{R}'*@var{R} - @var{u}*@var{u}'\nif @var{op} is @qcode{\"-\"}\n@end itemize\n\nIf @var{op} is @qcode{\"-\"}, @var{info} is set to\n\n@itemize\n@item 0 if the downdate was successful,\n\n@item 1 if @var{R}'*@var{R} - @var{u}*@var{u}' is not positive definite,\n\n@item 2 if @var{R} is singular.\n@end itemize\n\nIf @var{info} is not present, an error message is printed in cases 1 and 2.\n@seealso{chol, cholinsert, choldelete, cholshift}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  octave_value argr = args(0);\n  octave_value argu = args(1);\n\n  if (! argr.isnumeric () || ! argu.isnumeric ()\n      || (nargin > 2 && ! args(2).is_string ()))\n    print_usage ();\n\n  octave_value_list retval (nargout == 2 ? 2 : 1);\n\n  octave_idx_type n = argr.rows ();\n\n  std::string op = (nargin < 3) ? \"+\" : args(2).string_value ();\n\n  bool down = (op == \"-\");\n\n  if (! down && op != \"+\")\n    error (R\"(cholupdate: OP must be \"+\" or \"-\")\");\n\n  if (argr.columns () != n || argu.rows () != n || argu.columns () != 1)\n    error (\"cholupdate: dimension mismatch between R and U\");\n\n  int err = 0;\n  if (argr.is_single_type () || argu.is_single_type ())\n    {\n      if (argr.isreal () && argu.isreal ())\n        {\n          // real case\n          FloatMatrix R = argr.float_matrix_value ();\n          FloatColumnVector u = argu.float_column_vector_value ();\n\n          math::chol<FloatMatrix> fact;\n          fact.set (R);\n\n          if (down)\n            err = fact.downdate (u);\n          else\n            fact.update (u);\n\n          retval = ovl (get_chol_r (fact));\n        }\n      else\n        {\n          // complex case\n          FloatComplexMatrix R = argr.float_complex_matrix_value ();\n          FloatComplexColumnVector u\n            = argu.float_complex_column_vector_value ();\n\n          math::chol<FloatComplexMatrix> fact;\n          fact.set (R);\n\n          if (down)\n            err = fact.downdate (u);\n          else\n            fact.update (u);\n\n          retval = ovl (get_chol_r (fact));\n        }\n    }\n  else\n    {\n      if (argr.isreal () && argu.isreal ())\n        {\n          // real case\n          Matrix R = argr.matrix_value ();\n          ColumnVector u = argu.column_vector_value ();\n\n          math::chol<Matrix> fact;\n          fact.set (R);\n\n          if (down)\n            err = fact.downdate (u);\n          else\n            fact.update (u);\n\n          retval = ovl (get_chol_r (fact));\n        }\n      else\n        {\n          // complex case\n          ComplexMatrix R = argr.complex_matrix_value ();\n          ComplexColumnVector u = argu.complex_column_vector_value ();\n\n          math::chol<ComplexMatrix> fact;\n          fact.set (R);\n\n          if (down)\n            err = fact.downdate (u);\n          else\n            fact.update (u);\n\n          retval = ovl (get_chol_r (fact));\n        }\n    }\n\n  if (nargout > 1)\n    retval(1) = err;\n  else if (err == 1)\n    error (\"cholupdate: downdate violates positiveness\");\n  else if (err == 2)\n    error (\"cholupdate: singular matrix\");\n\n  return retval;\n}\n\n/*\n%!shared A, u, Ac, uc\n%! A = [  0.436997  -0.131721   0.124120  -0.061673 ;\n%!       -0.131721   0.738529   0.019851  -0.140295 ;\n%!        0.124120   0.019851   0.354879  -0.059472 ;\n%!       -0.061673  -0.140295  -0.059472   0.600939 ];\n%!\n%! u = [  0.98950 ;\n%!        0.39844 ;\n%!        0.63484 ;\n%!        0.13351 ];\n%! Ac = [  0.5585528 + 0.0000000i  -0.1662088 - 0.0315341i   0.0107873 + 0.0236411i  -0.0276775 - 0.0186073i ;\n%!        -0.1662088 + 0.0315341i   0.6760061 + 0.0000000i   0.0011452 - 0.0475528i   0.0145967 + 0.0247641i ;\n%!         0.0107873 - 0.0236411i   0.0011452 + 0.0475528i   0.6263149 - 0.0000000i  -0.1585837 - 0.0719763i ;\n%!        -0.0276775 + 0.0186073i   0.0145967 - 0.0247641i  -0.1585837 + 0.0719763i   0.6034234 - 0.0000000i ];\n%!\n%! uc = [ 0.54267 + 0.91519i ;\n%!        0.99647 + 0.43141i ;\n%!        0.83760 + 0.68977i ;\n%!        0.39160 + 0.90378i ];\n\n%!test\n%! R = chol (A);\n%! R1 = cholupdate (R, u);\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - R'*R - u*u', Inf), 0, 1e1*eps);\n%!\n%! R1 = cholupdate (R1, u, \"-\");\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1 - R, Inf), 0, 1e1*eps);\n\n%!test\n%! R = chol (Ac);\n%! R1 = cholupdate (R, uc);\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - R'*R - uc*uc', Inf), 0, 1e1*eps);\n%!\n%! R1 = cholupdate (R1, uc, \"-\");\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1 - R, Inf), 0, 11*eps);\n\n%!test\n%! R = chol (single (A));\n%! R1 = cholupdate (R, single (u));\n%! assert (norm (triu (R1)-R1, Inf), single (0));\n%! assert (norm (R1'*R1 - R'*R - single (u*u'), Inf), 0, 1e1* eps (\"single\"));\n%!\n%! R1 = cholupdate (R1, single (u), \"-\");\n%! assert (norm (triu (R1)-R1, Inf), single (0));\n%! assert (norm (R1 - R, Inf), 0, 2e1* eps (\"single\"));\n\n%!test\n%! R = chol (single (Ac));\n%! R1 = cholupdate (R, single (uc));\n%! assert (norm (triu (R1)-R1, Inf), single (0));\n%! assert (norm (R1'*R1 - R'*R - single (uc*uc'), Inf), 0, 1e1* eps (\"single\"));\n%!\n%! R1 = cholupdate (R1, single (uc), \"-\");\n%! assert (norm (triu (R1)-R1, Inf), single (0));\n%! assert (norm (R1 - R, Inf), 0, 2e1* eps (\"single\"));\n*/\n\nDEFUN (cholinsert, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{R1} =} cholinsert (@var{R}, @var{j}, @var{u})\n@deftypefnx {} {[@var{R1}, @var{info}] =} cholinsert (@var{R}, @var{j}, @var{u})\nUpdate a Cholesky factorization given a row or column to insert in the\noriginal factored matrix.\n\nGiven a Cholesky@tie{}factorization of a real symmetric or complex Hermitian\npositive definite matrix @w{@var{A} = @var{R}'*@var{R}}, @var{R}@tie{}upper\ntriangular, return the Cholesky@tie{}factorization of\n@var{A1}, where @w{A1(p,p) = A}, @w{A1(:,j) = A1(j,:)' = u}@ and\n@w{p = [1:j-1,j+1:n+1]}.  @w{u(j)}@ should be positive.\n\nOn return, @var{info} is set to\n\n@itemize\n@item 0 if the insertion was successful,\n\n@item 1 if @var{A1} is not positive definite,\n\n@item 2 if @var{R} is singular.\n@end itemize\n\nIf @var{info} is not present, an error message is printed in cases 1 and 2.\n@seealso{chol, cholupdate, choldelete, cholshift}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  octave_value argr = args(0);\n  octave_value argj = args(1);\n  octave_value argu = args(2);\n\n  if (! argr.isnumeric () || ! argu.isnumeric ()\n      || ! argj.is_real_scalar ())\n    print_usage ();\n\n  octave_idx_type n = argr.rows ();\n  octave_idx_type j = argj.scalar_value ();\n\n  if (argr.columns () != n || argu.rows () != n+1 || argu.columns () != 1)\n    error (\"cholinsert: dimension mismatch between R and U\");\n\n  if (j < 1 || j > n+1)\n    error (\"cholinsert: index J out of range\");\n\n  octave_value_list retval (nargout == 2 ? 2 : 1);\n\n  int err = 0;\n  if (argr.is_single_type () || argu.is_single_type ())\n    {\n      if (argr.isreal () && argu.isreal ())\n        {\n          // real case\n          FloatMatrix R = argr.float_matrix_value ();\n          FloatColumnVector u = argu.float_column_vector_value ();\n\n          math::chol<FloatMatrix> fact;\n          fact.set (R);\n          err = fact.insert_sym (u, j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n      else\n        {\n          // complex case\n          FloatComplexMatrix R = argr.float_complex_matrix_value ();\n          FloatComplexColumnVector u\n            = argu.float_complex_column_vector_value ();\n\n          math::chol<FloatComplexMatrix> fact;\n          fact.set (R);\n          err = fact.insert_sym (u, j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n    }\n  else\n    {\n      if (argr.isreal () && argu.isreal ())\n        {\n          // real case\n          Matrix R = argr.matrix_value ();\n          ColumnVector u = argu.column_vector_value ();\n\n          math::chol<Matrix> fact;\n          fact.set (R);\n          err = fact.insert_sym (u, j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n      else\n        {\n          // complex case\n          ComplexMatrix R = argr.complex_matrix_value ();\n          ComplexColumnVector u = argu.complex_column_vector_value ();\n\n          math::chol<ComplexMatrix> fact;\n          fact.set (R);\n          err = fact.insert_sym (u, j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n    }\n\n  if (nargout > 1)\n    retval(1) = err;\n  else if (err == 1)\n    error (\"cholinsert: insertion violates positiveness\");\n  else if (err == 2)\n    error (\"cholinsert: singular matrix\");\n  else if (err == 3)\n    error (\"cholinsert: diagonal element must be real\");\n\n  return retval;\n}\n\n/*\n%!test\n%! u2 = [  0.35080 ;\n%!         0.63930 ;\n%!         3.31057 ;\n%!        -0.13825 ;\n%!         0.45266 ];\n%!\n%! R = chol (A);\n%!\n%! j = 3;  p = [1:j-1, j+1:5];\n%! R1 = cholinsert (R, j, u2);\n%! A1 = R1'*R1;\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (A1(p,p) - A, Inf), 0, 1e1*eps);\n\n%!test\n%! u2 = [  0.35080  + 0.04298i;\n%!         0.63930  + 0.23778i;\n%!         3.31057  + 0.00000i;\n%!        -0.13825  + 0.19879i;\n%!         0.45266  + 0.50020i];\n%!\n%! R = chol (Ac);\n%!\n%! j = 3;  p = [1:j-1, j+1:5];\n%! R1 = cholinsert (R, j, u2);\n%! A1 = R1'*R1;\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (A1(p,p) - Ac, Inf), 0, 1e1*eps);\n\n%!test\n%! u2 = single ([  0.35080 ;\n%!                 0.63930 ;\n%!                 3.31057 ;\n%!                -0.13825 ;\n%!                 0.45266 ]);\n%!\n%! R = chol (single (A));\n%!\n%! j = 3;  p = [1:j-1, j+1:5];\n%! R1 = cholinsert (R, j, u2);\n%! A1 = R1'*R1;\n%!\n%! assert (norm (triu (R1)-R1, Inf), single (0));\n%! assert (norm (A1(p,p) - A, Inf), 0, 1e1* eps (\"single\"));\n\n%!test\n%! u2 = single ([  0.35080  + 0.04298i;\n%!                 0.63930  + 0.23778i;\n%!                 3.31057  + 0.00000i;\n%!                -0.13825  + 0.19879i;\n%!                 0.45266  + 0.50020i]);\n%!\n%! R = chol (single (Ac));\n%!\n%! j = 3;  p = [1:j-1, j+1:5];\n%! R1 = cholinsert (R, j, u2);\n%! A1 = R1'*R1;\n%!\n%! assert (norm (triu (R1)-R1, Inf), single (0));\n%! assert (norm (A1(p,p) - single (Ac), Inf), 0, 2e1* eps (\"single\"));\n\n%!test\n%! cu = chol (triu (A), \"upper\");\n%! cl = chol (tril (A), \"lower\");\n%! assert (cu, cl', eps);\n\n%!test\n%! cca   = chol (Ac);\n%!\n%! ccal  = chol (Ac, \"lower\");\n%! ccal2 = chol (tril (Ac), \"lower\");\n%!\n%! ccau  = chol (Ac, \"upper\");\n%! ccau2 = chol (triu (Ac), \"upper\");\n%!\n%! assert (cca'*cca,     Ac, eps);\n%! assert (ccau'*ccau,   Ac, eps);\n%! assert (ccau2'*ccau2, Ac, eps);\n%!\n%! assert (cca, ccal',  eps);\n%! assert (cca, ccau,   eps);\n%! assert (cca, ccal2', eps);\n%! assert (cca, ccau2,  eps);\n\n%!test\n%! cca   = chol (single (Ac));\n%!\n%! ccal  = chol (single (Ac), \"lower\");\n%! ccal2 = chol (tril (single (Ac)), \"lower\");\n%!\n%! ccau  = chol (single (Ac), \"upper\");\n%! ccau2 = chol (triu (single (Ac)), \"upper\");\n%!\n%! assert (cca'*cca,     single (Ac), eps (\"single\"));\n%! assert (ccau'*ccau,   single (Ac), eps (\"single\"));\n%! assert (ccau2'*ccau2, single (Ac), eps (\"single\"));\n%!\n%! assert (cca, ccal',  eps (\"single\"));\n%! assert (cca, ccau,   eps (\"single\"));\n%! assert (cca, ccal2', eps (\"single\"));\n%! assert (cca, ccau2,  eps (\"single\"));\n\n%!test\n%! a = [12,  2,  3,  4;\n%!       2, 14,  5,  3;\n%!       3,  5, 16,  6;\n%!       4,  3,  6, 16];\n%!\n%! b = [0,  1,  2,  3;\n%!     -1,  0,  1,  2;\n%!     -2, -1,  0,  1;\n%!     -3, -2, -1,  0];\n%!\n%! ca = a + i*b;\n%!\n%! cca   = chol (ca);\n%!\n%! ccal  = chol (ca, \"lower\");\n%! ccal2 = chol (tril (ca), \"lower\");\n%!\n%! ccau  = chol (ca, \"upper\");\n%! ccau2 = chol (triu (ca), \"upper\");\n%!\n%! assert (cca'*cca,     ca, 16*eps);\n%! assert (ccau'*ccau,   ca, 16*eps);\n%! assert (ccau2'*ccau2, ca, 16*eps);\n%!\n%! assert (cca, ccal',  16*eps);\n%! assert (cca, ccau,   16*eps);\n%! assert (cca, ccal2', 16*eps);\n%! assert (cca, ccau2,  16*eps);\n*/\n\nDEFUN (choldelete, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{R1} =} choldelete (@var{R}, @var{j})\nUpdate a Cholesky factorization given a row or column to delete from the\noriginal factored matrix.\n\nGiven a Cholesky@tie{}factorization of a real symmetric or complex Hermitian\npositive definite matrix @w{@var{A} = @var{R}'*@var{R}}, @var{R}@tie{}upper\ntriangular, return the Cholesky@tie{}factorization of @w{A(p,p)}, where\n@w{p = [1:j-1,j+1:n+1]}.\n@seealso{chol, cholupdate, cholinsert, cholshift}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value argr = args(0);\n  octave_value argj = args(1);\n\n  if (! argr.isnumeric () || ! argj.is_real_scalar ())\n    print_usage ();\n\n  octave_idx_type n = argr.rows ();\n  octave_idx_type j = argj.scalar_value ();\n\n  if (argr.columns () != n)\n    err_square_matrix_required (\"choldelete\", \"R\");\n\n  if (j < 0 && j > n)\n    error (\"choldelete: index J out of range\");\n\n  octave_value_list retval;\n\n  if (argr.is_single_type ())\n    {\n      if (argr.isreal ())\n        {\n          // real case\n          FloatMatrix R = argr.float_matrix_value ();\n\n          math::chol<FloatMatrix> fact;\n          fact.set (R);\n          fact.delete_sym (j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n      else\n        {\n          // complex case\n          FloatComplexMatrix R = argr.float_complex_matrix_value ();\n\n          math::chol<FloatComplexMatrix> fact;\n          fact.set (R);\n          fact.delete_sym (j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n    }\n  else\n    {\n      if (argr.isreal ())\n        {\n          // real case\n          Matrix R = argr.matrix_value ();\n\n          math::chol<Matrix> fact;\n          fact.set (R);\n          fact.delete_sym (j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n      else\n        {\n          // complex case\n          ComplexMatrix R = argr.complex_matrix_value ();\n\n          math::chol<ComplexMatrix> fact;\n          fact.set (R);\n          fact.delete_sym (j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! R = chol (A);\n%!\n%! j = 3;  p = [1:j-1,j+1:4];\n%! R1 = choldelete (R, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - A(p,p), Inf), 0, 1e1*eps);\n\n%!test\n%! R = chol (Ac);\n%!\n%! j = 3;  p = [1:j-1,j+1:4];\n%! R1 = choldelete (R, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - Ac(p,p), Inf), 0, 1e1*eps);\n\n%!test\n%! R = chol (single (A));\n%!\n%! j = 3;  p = [1:j-1,j+1:4];\n%! R1 = choldelete (R, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), single (0));\n%! assert (norm (R1'*R1 - single (A(p,p)), Inf), 0, 1e1* eps (\"single\"));\n\n%!test\n%! R = chol (single (Ac));\n%!\n%! j = 3;  p = [1:j-1,j+1:4];\n%! R1 = choldelete (R,j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), single (0));\n%! assert (norm (R1'*R1 - single (Ac(p,p)), Inf), 0, 1e1* eps (\"single\"));\n*/\n\nDEFUN (cholshift, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{R1} =} cholshift (@var{R}, @var{i}, @var{j})\nUpdate a Cholesky factorization given a range of columns to shift in the\noriginal factored matrix.\n\nGiven a Cholesky@tie{}factorization of a real symmetric or complex Hermitian\npositive definite matrix @w{@var{A} = @var{R}'*@var{R}}, @var{R}@tie{}upper\ntriangular, return the Cholesky@tie{}factorization of\n@w{@var{A}(p,p)}, where p is the permutation @*\n@code{p = [1:i-1, circshift(i:j, 1), j+1:n]} if @w{@var{i} < @var{j}} @*\n or @*\n@code{p = [1:j-1, circshift(j:i,-1), i+1:n]} if @w{@var{j} < @var{i}}.  @*\n\n@seealso{chol, cholupdate, cholinsert, choldelete}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  octave_value argr = args(0);\n  octave_value argi = args(1);\n  octave_value argj = args(2);\n\n  if (! argr.isnumeric () || ! argi.is_real_scalar ()\n      || ! argj.is_real_scalar ())\n    print_usage ();\n\n  octave_idx_type n = argr.rows ();\n  octave_idx_type i = argi.scalar_value ();\n  octave_idx_type j = argj.scalar_value ();\n\n  if (argr.columns () != n)\n    err_square_matrix_required (\"cholshift\", \"R\");\n\n  if (j < 0 || j > n+1 || i < 0 || i > n+1)\n    error (\"cholshift: index I or J is out of range\");\n\n  octave_value_list retval;\n\n  if (argr.is_single_type () && argi.is_single_type ()\n      && argj.is_single_type ())\n    {\n      if (argr.isreal ())\n        {\n          // real case\n          FloatMatrix R = argr.float_matrix_value ();\n\n          math::chol<FloatMatrix> fact;\n          fact.set (R);\n          fact.shift_sym (i-1, j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n      else\n        {\n          // complex case\n          FloatComplexMatrix R = argr.float_complex_matrix_value ();\n\n          math::chol<FloatComplexMatrix> fact;\n          fact.set (R);\n          fact.shift_sym (i-1, j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n    }\n  else\n    {\n      if (argr.isreal ())\n        {\n          // real case\n          Matrix R = argr.matrix_value ();\n\n          math::chol<Matrix> fact;\n          fact.set (R);\n          fact.shift_sym (i-1, j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n      else\n        {\n          // complex case\n          ComplexMatrix R = argr.complex_matrix_value ();\n\n          math::chol<ComplexMatrix> fact;\n          fact.set (R);\n          fact.shift_sym (i-1, j-1);\n\n          retval = ovl (get_chol_r (fact));\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! R = chol (A);\n%!\n%! i = 1;  j = 3;  p = [1:i-1, circshift(i:j,-1), j+1:4];\n%! R1 = cholshift (R, i, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - A(p,p), Inf), 0, 1e1*eps);\n%!\n%! j = 1;  i = 3;  p = [1:j-1, circshift(j:i,+1), i+1:4];\n%! R1 = cholshift (R, i, j);\n%!\n%! assert (norm (triu (R1) - R1, Inf), 0);\n%! assert (norm (R1'*R1 - A(p,p), Inf), 0, 1e1*eps);\n\n%!test\n%! R = chol (Ac);\n%!\n%! i = 1;  j = 3;  p = [1:i-1, circshift(i:j,-1), j+1:4];\n%! R1 = cholshift (R, i, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - Ac(p,p), Inf), 0, 1e1*eps);\n%!\n%! j = 1;  i = 3;  p = [1:j-1, circshift(j:i,+1), i+1:4];\n%! R1 = cholshift (R, i, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - Ac(p,p), Inf), 0, 1e1*eps);\n\n%!test\n%! R = chol (single (A));\n%!\n%! i = 1;  j = 3;  p = [1:i-1, circshift(i:j,-1), j+1:4];\n%! R1 = cholshift (R, i, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - single (A(p,p)), Inf), 0, 1e1* eps (\"single\"));\n%!\n%! j = 1;  i = 3;  p = [1:j-1, circshift(j:i,+1), i+1:4];\n%! R1 = cholshift (R, i, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - single (A(p,p)), Inf), 0, 1e1* eps (\"single\"));\n\n%!test\n%! R = chol (single (Ac));\n%!\n%! i = 1;  j = 3;  p = [1:i-1, circshift(i:j,-1), j+1:4];\n%! R1 = cholshift (R, i, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - single (Ac(p,p)), Inf), 0, 1e1* eps (\"single\"));\n%!\n%! j = 1; i = 3; p = [1:j-1, circshift(j:i,+1), i+1:4];\n%! R1 = cholshift (R, i, j);\n%!\n%! assert (norm (triu (R1)-R1, Inf), 0);\n%! assert (norm (R1'*R1 - single (Ac(p,p)), Inf), 0, 1e1* eps (\"single\"));\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/colamd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This is the octave interface to colamd, which bore the copyright given\n// in the help of the functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n\n#include <string>\n\n#include \"CSparse.h\"\n#include \"dNDArray.h\"\n#include \"dSparse.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sparse.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// The symmetric column elimination tree code take from the Davis LDL code.\n// Copyright given elsewhere in this file.\nstatic void\nsymetree (const octave_idx_type *ridx, const octave_idx_type *cidx,\n          octave_idx_type *Parent, octave_idx_type *P, octave_idx_type n)\n{\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Flag, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Pinv, (P ? n : 0));\n  if (P)\n    // If P is present then compute Pinv, the inverse of P\n    for (octave_idx_type k = 0 ; k < n ; k++)\n      Pinv[P[k]] = k;\n\n  for (octave_idx_type k = 0 ; k < n ; k++)\n    {\n      // L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k)\n      Parent[k] = n ;                // parent of k is not yet known\n      Flag[k] = k ;                  // mark node k as visited\n      octave_idx_type kk = (P ? P[k] : k); // kth original, or permuted, column\n      octave_idx_type p2 = cidx[kk+1];\n      for (octave_idx_type p = cidx[kk] ; p < p2 ; p++)\n        {\n          // A (i,k) is nonzero (original or permuted A)\n          octave_idx_type i = (P ? Pinv[ridx[p]] : ridx[p]);\n          if (i < k)\n            {\n              // follow path from i to root of etree, stop at flagged node\n              for ( ; Flag[i] != k ; i = Parent[i])\n                {\n                  // find parent of i if not yet determined\n                  if (Parent[i] == n)\n                    Parent[i] = k;\n                  Flag[i] = k ;        // mark i as visited\n                }\n            }\n        }\n    }\n}\n\n// The elimination tree post-ordering code below is taken from SuperLU\nstatic inline octave_idx_type\nmake_set (octave_idx_type i, octave_idx_type *pp)\n{\n  pp[i] = i;\n  return i;\n}\n\nstatic inline octave_idx_type\nlink (octave_idx_type s, octave_idx_type t, octave_idx_type *pp)\n{\n  pp[s] = t;\n  return t;\n}\n\nstatic inline octave_idx_type\nfind (octave_idx_type i, octave_idx_type *pp)\n{\n  octave_idx_type p = pp[i];\n  octave_idx_type gp = pp[p];\n\n  while (gp != p)\n    {\n      pp[i] = gp;\n      i = gp;\n      p = pp[i];\n      gp = pp[p];\n    }\n\n  return p;\n}\n\nstatic octave_idx_type\netdfs (octave_idx_type v, octave_idx_type *first_kid,\n       octave_idx_type *next_kid, octave_idx_type *post,\n       octave_idx_type postnum)\n{\n  for (octave_idx_type w = first_kid[v]; w != -1; w = next_kid[w])\n    postnum = etdfs (w, first_kid, next_kid, post, postnum);\n\n  post[postnum++] = v;\n\n  return postnum;\n}\n\nstatic void\ntree_postorder (octave_idx_type n, octave_idx_type *parent,\n                octave_idx_type *post)\n{\n  // Allocate storage for working arrays and results\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, first_kid, n+1);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, next_kid, n+1);\n\n  // Set up structure describing children\n  for (octave_idx_type v = 0; v <= n; first_kid[v++] = -1)\n    ; // do nothing\n\n  for (octave_idx_type v = n-1; v >= 0; v--)\n    {\n      octave_idx_type dad = parent[v];\n      next_kid[v] = first_kid[dad];\n      first_kid[dad] = v;\n    }\n\n  // Depth-first search from dummy root vertex #n\n  etdfs (n, first_kid, next_kid, post, 0);\n}\n\nstatic void\ncoletree (const octave_idx_type *ridx, const octave_idx_type *colbeg,\n          octave_idx_type *colend, octave_idx_type *parent,\n          octave_idx_type nr, octave_idx_type nc)\n{\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, root, nc);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, pp, nc);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, firstcol, nr);\n\n  // Compute firstcol[row] = first nonzero column in row\n  for (octave_idx_type row = 0; row < nr; firstcol[row++] = nc)\n    ; // do nothing\n\n  for (octave_idx_type col = 0; col < nc; col++)\n    for (octave_idx_type p = colbeg[col]; p < colend[col]; p++)\n      {\n        octave_idx_type row = ridx[p];\n        if (firstcol[row] > col)\n          firstcol[row] = col;\n      }\n\n  // Compute etree by Liu's algorithm for symmetric matrices,\n  // except use (firstcol[r],c) in place of an edge (r,c) of A.\n  // Thus each row clique in A'*A is replaced by a star\n  // centered at its first vertex, which has the same fill.\n  for (octave_idx_type col = 0; col < nc; col++)\n    {\n      octave_idx_type cset = make_set (col, pp);\n      root[cset] = col;\n      parent[col] = nc;\n      for (octave_idx_type p = colbeg[col]; p < colend[col]; p++)\n        {\n          octave_idx_type row = firstcol[ridx[p]];\n          if (row >= col)\n            continue;\n          octave_idx_type rset = find (row, pp);\n          octave_idx_type rroot = root[rset];\n          if (rroot != col)\n            {\n              parent[rroot] = col;\n              cset = link (cset, rset, pp);\n              root[cset] = col;\n            }\n        }\n    }\n}\n\nDEFUN (colamd, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{p} =} colamd (@var{S})\n@deftypefnx {} {@var{p} =} colamd (@var{S}, @var{knobs})\n@deftypefnx {} {[@var{p}, @var{stats}] =} colamd (@var{S})\n@deftypefnx {} {[@var{p}, @var{stats}] =} colamd (@var{S}, @var{knobs})\n\nCompute the column approximate minimum degree permutation.\n\n@code{@var{p} = colamd (@var{S})} returns the column approximate minimum\ndegree permutation vector for the sparse matrix @var{S}.  For a\nnon-symmetric matrix @var{S}, @code{@var{S}(:,@var{p})} tends to have\nsparser LU@tie{}factors than @var{S}.  The Cholesky@tie{}factorization of\n@code{@var{S}(:,@var{p})' * @var{S}(:,@var{p})} also tends to be sparser\nthan that of @code{@var{S}' * @var{S}}.\n\n@var{knobs} is an optional one- to three-element input vector.  If @var{S}\nis m-by-n, then rows with more than @code{max(16,@var{knobs}(1)*sqrt(n))}\nentries are ignored.  Columns with more than\n@code{max (16,@var{knobs}(2)*sqrt(min(m,n)))} entries are removed prior to\nordering, and ordered last in the output permutation @var{p}.  Only\ncompletely dense rows or columns are removed if @code{@var{knobs}(1)} and\n@code{@var{knobs}(2)} are < 0, respectively.  If @code{@var{knobs}(3)} is\nnonzero, @var{stats} and @var{knobs} are printed.  The default is\n@code{@var{knobs} = [10 10 0]}.  Note that @var{knobs} differs from earlier\nversions of colamd.\n\n@var{stats} is an optional 20-element output vector that provides data\nabout the ordering and the validity of the input matrix @var{S}.  Ordering\nstatistics are in @code{@var{stats}(1:3)}.  @code{@var{stats}(1)} and\n@code{@var{stats}(2)} are the number of dense or empty rows and columns\nignored by @sc{colamd} and @code{@var{stats}(3)} is the number of garbage\ncollections performed on the internal data structure used by @sc{colamd}\n(roughly of size @code{2.2 * nnz(@var{S}) + 4 * @var{m} + 7 * @var{n}}\nintegers).\n\nOctave built-in functions are intended to generate valid sparse matrices,\nwith no duplicate entries, with ascending row indices of the nonzeros\nin each column, with a non-negative number of entries in each column (!)\nand so on.  If a matrix is invalid, then @sc{colamd} may or may not be able\nto continue.  If there are duplicate entries (a row index appears two or\nmore times in the same column) or if the row indices in a column are out\nof order, then @sc{colamd} can correct these errors by ignoring the\nduplicate entries and sorting each column of its internal copy of the\nmatrix @var{S} (the input matrix @var{S} is not repaired, however).  If a\nmatrix is invalid in other ways then @sc{colamd} cannot continue, an error\nmessage is printed, and no output arguments (@var{p} or @var{stats}) are\nreturned.\n@sc{colamd} is thus a simple way to check a sparse matrix to see if it's\nvalid.\n\n@code{@var{stats}(4:7)} provide information if @sc{colamd} was able to\ncontinue.  The matrix is OK if @code{@var{stats}(4)} is zero, or 1 if\ninvalid.  @code{@var{stats}(5)} is the rightmost column index that is\nunsorted or contains duplicate entries, or zero if no such column exists.\n@code{@var{stats}(6)} is the last seen duplicate or out-of-order row\nindex in the column index given by @code{@var{stats}(5)}, or zero if no\nsuch row index exists.  @code{@var{stats}(7)} is the number of duplicate\nor out-of-order row indices.  @code{@var{stats}(8:20)} is always zero in\nthe current version of @sc{colamd} (reserved for future use).\n\nThe ordering is followed by a column elimination tree post-ordering.\n\nThe authors of the code itself are @nospell{Stefan I. Larimore} and\n@nospell{Timothy A. Davis}.  The algorithm was developed in collaboration with\n@nospell{John Gilbert}, Xerox PARC, and @nospell{Esmond Ng}, Oak Ridge National\nLaboratory.  (see @url{http://faculty.cse.tamu.edu/davis/suitesparse.html})\n@seealso{colperm, symamd, ccolamd}\n@end deftypefn */)\n{\n#if defined (HAVE_COLAMD)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value_list retval (nargout == 2 ? 2 : 1);\n  int spumoni = 0;\n\n  // Get knobs\n  static_assert (COLAMD_KNOBS <= 40,\n                 \"colamd: # of COLAMD_KNOBS exceeded.  Please report this to bugs.octave.org\");\n  double knob_storage[COLAMD_KNOBS];\n  double *knobs = &knob_storage[0];\n  COLAMD_NAME (_set_defaults) (knobs);\n\n  // Check for user-passed knobs\n  if (nargin == 2)\n    {\n      NDArray User_knobs = args(1).array_value ();\n      int nel_User_knobs = User_knobs.numel ();\n\n      if (nel_User_knobs > 0)\n        knobs[COLAMD_DENSE_ROW] = User_knobs(0);\n      if (nel_User_knobs > 1)\n        knobs[COLAMD_DENSE_COL] = User_knobs(1);\n      if (nel_User_knobs > 2)\n        spumoni = static_cast<int> (User_knobs(2));\n\n      // print knob settings if spumoni is set\n      if (spumoni)\n        {\n\n          octave_stdout << \"\\ncolamd version \" << COLAMD_MAIN_VERSION\n                        << '.' <<  COLAMD_SUB_VERSION\n                        << \", \" << COLAMD_DATE << \":\\n\";\n\n          if (knobs[COLAMD_DENSE_ROW] >= 0)\n            octave_stdout << \"knobs(1): \" << User_knobs (0)\n                          << \", rows with > max (16,\"\n                          << knobs[COLAMD_DENSE_ROW] << \"* sqrt (columns(A)))\"\n                          << \" entries removed\\n\";\n          else\n            octave_stdout << \"knobs(1): \" << User_knobs (0)\n                          << \", only completely dense rows removed\\n\";\n\n          if (knobs[COLAMD_DENSE_COL] >= 0)\n            octave_stdout << \"knobs(2): \" << User_knobs (1)\n                          << \", cols with > max (16,\"\n                          << knobs[COLAMD_DENSE_COL] << \"* sqrt (size(A)))\"\n                          << \" entries removed\\n\";\n          else\n            octave_stdout << \"knobs(2): \" << User_knobs (1)\n                          << \", only completely dense columns removed\\n\";\n\n          octave_stdout << \"knobs(3): \" << User_knobs (2)\n                        << \", statistics and knobs printed\\n\";\n\n        }\n    }\n\n  octave_idx_type n_row, n_col, nnz;\n  octave_idx_type *ridx, *cidx;\n  SparseComplexMatrix scm;\n  SparseMatrix sm;\n\n  if (args(0).issparse ())\n    {\n      if (args(0).iscomplex ())\n        {\n          scm = args(0).sparse_complex_matrix_value ();\n          n_row = scm.rows ();\n          n_col = scm.cols ();\n          nnz = scm.nnz ();\n          ridx = scm.xridx ();\n          cidx = scm.xcidx ();\n        }\n      else\n        {\n          sm = args(0).sparse_matrix_value ();\n\n          n_row = sm.rows ();\n          n_col = sm.cols ();\n          nnz = sm.nnz ();\n          ridx = sm.xridx ();\n          cidx = sm.xcidx ();\n        }\n    }\n  else\n    {\n      if (args(0).iscomplex ())\n        sm = SparseMatrix (real (args(0).complex_matrix_value ()));\n      else\n        sm = SparseMatrix (args(0).matrix_value ());\n\n      n_row = sm.rows ();\n      n_col = sm.cols ();\n      nnz = sm.nnz ();\n      ridx = sm.xridx ();\n      cidx = sm.xcidx ();\n    }\n\n  // Allocate workspace for colamd\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, p, n_col+1);\n  for (octave_idx_type i = 0; i < n_col+1; i++)\n    p[i] = cidx[i];\n\n  octave_idx_type Alen = COLAMD_NAME (_recommended) (nnz, n_row, n_col);\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, A, Alen);\n  for (octave_idx_type i = 0; i < nnz; i++)\n    A[i] = ridx[i];\n\n  // Order the columns (destroys A)\n  static_assert (COLAMD_STATS <= 40,\n                 \"colamd: # of COLAMD_STATS exceeded.  Please report this to bugs.octave.org\");\n  suitesparse_integer stats_storage[COLAMD_STATS];\n  suitesparse_integer *stats = &stats_storage[0];\n  if (! COLAMD_NAME () (n_row, n_col, Alen, A, p, knobs, stats))\n    {\n      COLAMD_NAME (_report)(stats);\n\n      error (\"colamd: internal error!\");\n    }\n\n  // column elimination tree post-ordering (reuse variables)\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, colbeg, n_col + 1);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, colend, n_col + 1);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1);\n\n  for (octave_idx_type i = 0; i < n_col; i++)\n    {\n      colbeg[i] = cidx[p[i]];\n      colend[i] = cidx[p[i]+1];\n    }\n\n  coletree (ridx, colbeg, colend, etree, n_row, n_col);\n\n  // Calculate the tree post-ordering\n  tree_postorder (n_col, etree, colbeg);\n\n  // return the permutation vector\n  NDArray out_perm (dim_vector (1, n_col));\n  for (octave_idx_type i = 0; i < n_col; i++)\n    out_perm(i) = p[colbeg[i]] + 1;\n\n  retval(0) = out_perm;\n\n  // print stats if spumoni > 0\n  if (spumoni > 0)\n    COLAMD_NAME (_report)(stats);\n\n  // Return the stats vector\n  if (nargout == 2)\n    {\n      NDArray out_stats (dim_vector (1, COLAMD_STATS));\n      for (octave_idx_type i = 0 ; i < COLAMD_STATS ; i++)\n        out_stats(i) = stats[i];\n      retval(1) = out_stats;\n\n      // fix stats (5) and (6), for 1-based information on\n      // jumbled matrix.  note that this correction doesn't\n      // occur if symamd returns FALSE\n      out_stats(COLAMD_INFO1)++;\n      out_stats(COLAMD_INFO2)++;\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"colamd\", \"COLAMD\");\n\n#endif\n}\n\nDEFUN (symamd, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{p} =} symamd (@var{S})\n@deftypefnx {} {@var{p} =} symamd (@var{S}, @var{knobs})\n@deftypefnx {} {[@var{p}, @var{stats}] =} symamd (@var{S})\n@deftypefnx {} {[@var{p}, @var{stats}] =} symamd (@var{S}, @var{knobs})\n\nFor a symmetric positive definite matrix @var{S}, returns the permutation\nvector p such that @code{@var{S}(@var{p}, @var{p})} tends to have a\nsparser Cholesky@tie{}factor than @var{S}.\n\nSometimes @code{symamd} works well for symmetric indefinite matrices too.\nThe matrix @var{S} is assumed to be symmetric; only the strictly lower\ntriangular part is referenced.  @var{S} must be square.\n\n@var{knobs} is an optional one- to two-element input vector.  If @var{S} is\nn-by-n, then rows and columns with more than\n@code{max (16,@var{knobs}(1)*sqrt(n))} entries are removed prior to\nordering, and ordered last in the output permutation @var{p}.  No\nrows/columns are removed if @code{@var{knobs}(1) < 0}.  If\n@code{@var{knobs}(2)} is nonzero, @var{stats} and @var{knobs} are\nprinted.  The default is @code{@var{knobs} = [10 0]}.  Note that\n@var{knobs} differs from earlier versions of @code{symamd}.\n\n@var{stats} is an optional 20-element output vector that provides data\nabout the ordering and the validity of the input matrix @var{S}.  Ordering\nstatistics are in @code{@var{stats}(1:3)}.\n@code{@var{stats}(1) = @var{stats}(2)} is the number of dense or empty rows\nand columns ignored by SYMAMD and @code{@var{stats}(3)} is the number of\ngarbage collections performed on the internal data structure used by SYMAMD\n(roughly of size @code{8.4 * nnz (tril (@var{S}, -1)) + 9 * @var{n}}\nintegers).\n\nOctave built-in functions are intended to generate valid sparse matrices,\nwith no duplicate entries, with ascending row indices of the nonzeros\nin each column, with a non-negative number of entries in each column (!)\nand so on.  If a matrix is invalid, then SYMAMD may or may not be able\nto continue.  If there are duplicate entries (a row index appears two or\nmore times in the same column) or if the row indices in a column are out\nof order, then SYMAMD can correct these errors by ignoring the duplicate\nentries and sorting each column of its internal copy of the matrix S (the\ninput matrix S is not repaired, however).  If a matrix is invalid in\nother ways then SYMAMD cannot continue, an error message is printed, and\nno output arguments (@var{p} or @var{stats}) are returned.  SYMAMD is\nthus a simple way to check a sparse matrix to see if it's valid.\n\n@code{@var{stats}(4:7)} provide information if SYMAMD was able to\ncontinue.  The matrix is OK if @code{@var{stats} (4)} is zero, or 1\nif invalid.  @code{@var{stats}(5)} is the rightmost column index that\nis unsorted or contains duplicate entries, or zero if no such column\nexists.  @code{@var{stats}(6)} is the last seen duplicate or out-of-order\nrow index in the column index given by @code{@var{stats}(5)}, or zero\nif no such row index exists.  @code{@var{stats}(7)} is the number of\nduplicate or out-of-order row indices.  @code{@var{stats}(8:20)} is\nalways zero in the current version of SYMAMD (reserved for future use).\n\nThe ordering is followed by a column elimination tree post-ordering.\n\nThe authors of the code itself are @nospell{Stefan I. Larimore} and\n@nospell{Timothy A. Davis}.  The algorithm was developed in collaboration with\n@nospell{John Gilbert}, Xerox PARC, and @nospell{Esmond Ng}, Oak Ridge National\nLaboratory.  (see @url{http://faculty.cse.tamu.edu/davis/suitesparse.html})\n@seealso{colperm, colamd}\n@end deftypefn */)\n{\n#if defined (HAVE_COLAMD)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value_list retval (nargin == 2 ? 2 : 1);\n  int spumoni = 0;\n\n  // Get knobs\n  static_assert (COLAMD_KNOBS <= 40,\n                 \"symamd: # of COLAMD_KNOBS exceeded.  Please report this to bugs.octave.org\");\n  double knob_storage[COLAMD_KNOBS];\n  double *knobs = &knob_storage[0];\n  COLAMD_NAME (_set_defaults) (knobs);\n\n  // Check for user-passed knobs\n  if (nargin == 2)\n    {\n      NDArray User_knobs = args(1).array_value ();\n      int nel_User_knobs = User_knobs.numel ();\n\n      if (nel_User_knobs > 0)\n        knobs[COLAMD_DENSE_ROW] = User_knobs(COLAMD_DENSE_ROW);\n      if (nel_User_knobs > 1)\n        spumoni = static_cast<int> (User_knobs (1));\n    }\n\n  // print knob settings if spumoni is set\n  if (spumoni > 0)\n    octave_stdout << \"symamd: dense row/col fraction: \"\n                  << knobs[COLAMD_DENSE_ROW] << std::endl;\n\n  octave_idx_type n_row, n_col;\n  octave_idx_type *ridx, *cidx;\n  SparseMatrix sm;\n  SparseComplexMatrix scm;\n\n  if (args(0).issparse ())\n    {\n      if (args(0).iscomplex ())\n        {\n          scm = args(0).sparse_complex_matrix_value ();\n          n_row = scm.rows ();\n          n_col = scm.cols ();\n          ridx = scm.xridx ();\n          cidx = scm.xcidx ();\n        }\n      else\n        {\n          sm = args(0).sparse_matrix_value ();\n          n_row = sm.rows ();\n          n_col = sm.cols ();\n          ridx = sm.xridx ();\n          cidx = sm.xcidx ();\n        }\n    }\n  else\n    {\n      if (args(0).iscomplex ())\n        sm = SparseMatrix (real (args(0).complex_matrix_value ()));\n      else\n        sm = SparseMatrix (args(0).matrix_value ());\n\n      n_row = sm.rows ();\n      n_col = sm.cols ();\n      ridx = sm.xridx ();\n      cidx = sm.xcidx ();\n    }\n\n  if (n_row != n_col)\n    err_square_matrix_required (\"symamd\", \"S\");\n\n  // Allocate workspace for symamd\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, n_col+1);\n  static_assert (COLAMD_STATS <= 40,\n                 \"symamd: # of COLAMD_STATS exceeded.  Please report this to bugs.octave.org\");\n  suitesparse_integer stats_storage[COLAMD_STATS];\n  suitesparse_integer *stats = &stats_storage[0];\n  if (! SYMAMD_NAME () (n_col, to_suitesparse_intptr (ridx),\n                        to_suitesparse_intptr (cidx),\n                        to_suitesparse_intptr (perm),\n                        knobs, stats, &calloc, &free))\n    {\n      SYMAMD_NAME (_report)(stats);\n\n      error (\"symamd: internal error!\");\n    }\n\n  // column elimination tree post-ordering\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1);\n  symetree (ridx, cidx, etree, perm, n_col);\n\n  // Calculate the tree post-ordering\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, post, n_col + 1);\n  tree_postorder (n_col, etree, post);\n\n  // return the permutation vector\n  NDArray out_perm (dim_vector (1, n_col));\n  for (octave_idx_type i = 0; i < n_col; i++)\n    out_perm(i) = perm[post[i]] + 1;\n\n  retval(0) = out_perm;\n\n  // print stats if spumoni > 0\n  if (spumoni > 0)\n    SYMAMD_NAME (_report)(stats);\n\n  // Return the stats vector\n  if (nargout == 2)\n    {\n      NDArray out_stats (dim_vector (1, COLAMD_STATS));\n      for (octave_idx_type i = 0 ; i < COLAMD_STATS ; i++)\n        out_stats(i) = stats[i];\n      retval(1) = out_stats;\n\n      // fix stats (5) and (6), for 1-based information on\n      // jumbled matrix.  note that this correction doesn't\n      // occur if symamd returns FALSE\n      out_stats(COLAMD_INFO1)++;\n      out_stats(COLAMD_INFO2)++;\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"symamd\", \"COLAMD\");\n\n#endif\n}\n\nDEFUN (etree, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{p} =} etree (@var{S})\n@deftypefnx {} {@var{p} =} etree (@var{S}, @var{typ})\n@deftypefnx {} {[@var{p}, @var{q}] =} etree (@var{S}, @var{typ})\n\nReturn the elimination tree for the matrix @var{S}.\n\nBy default @var{S} is assumed to be symmetric and the symmetric elimination\ntree is returned.  The argument @var{typ} controls whether a symmetric or\ncolumn elimination tree is returned.  Valid values of @var{typ} are\n@qcode{\"sym\"} or @qcode{\"col\"}, for symmetric or column elimination tree\nrespectively.\n\nCalled with a second argument, @code{etree} also returns the postorder\npermutations on the tree.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value_list retval (nargout == 2 ? 2 : 1);\n\n  octave_idx_type n_row = 0;\n  octave_idx_type n_col = 0;\n  octave_idx_type *ridx = nullptr;\n  octave_idx_type *cidx = nullptr;\n\n  SparseComplexMatrix scm;\n  SparseBoolMatrix sbm;\n  SparseMatrix sm;\n\n  if (args(0).iscomplex ())\n    {\n      scm = args(0).sparse_complex_matrix_value ();\n\n      n_row = scm.rows ();\n      n_col = scm.cols ();\n      ridx = scm.xridx ();\n      cidx = scm.xcidx ();\n    }\n  else if (args(0).islogical ())\n    {\n      sbm = args(0).sparse_bool_matrix_value ();\n\n      n_row = sbm.rows ();\n      n_col = sbm.cols ();\n      ridx = sbm.xridx ();\n      cidx = sbm.xcidx ();\n    }\n  else\n    {\n      sm = args(0).sparse_matrix_value ();\n\n      n_row = sm.rows ();\n      n_col = sm.cols ();\n      ridx = sm.xridx ();\n      cidx = sm.xcidx ();\n    }\n\n  bool is_sym = true;\n\n  if (nargin == 2)\n    {\n      std::string str = args(1).xstring_value (\"etree: TYP must be a string\");\n      if (str.find ('C') == 0 || str.find ('c') == 0)\n        is_sym = false;\n    }\n\n  // column elimination tree post-ordering (reuse variables)\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1);\n\n  if (is_sym)\n    {\n      if (n_row != n_col)\n        error (\"etree: S is marked as symmetric, but is not square\");\n\n      symetree (ridx, cidx, etree, nullptr, n_col);\n    }\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, colbeg, n_col);\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, colend, n_col);\n\n      for (octave_idx_type i = 0; i < n_col; i++)\n        {\n          colbeg[i] = cidx[i];\n          colend[i] = cidx[i+1];\n        }\n\n      coletree (ridx, colbeg, colend, etree, n_row, n_col);\n    }\n\n  NDArray tree (dim_vector (1, n_col));\n  for (octave_idx_type i = 0; i < n_col; i++)\n    // We flag a root with n_col while Matlab does it with zero\n    // Convert for Matlab-compatible output\n    if (etree[i] == n_col)\n      tree(i) = 0;\n    else\n      tree(i) = etree[i] + 1;\n\n  retval(0) = tree;\n\n  if (nargout == 2)\n    {\n      // Calculate the tree post-ordering\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, post, n_col + 1);\n      tree_postorder (n_col, etree, post);\n\n      NDArray postorder (dim_vector (1, n_col));\n      for (octave_idx_type i = 0; i < n_col; i++)\n        postorder(i) = post[i] + 1;\n\n      retval(1) = postorder;\n    }\n\n  return retval;\n}\n\n/*\n%!assert (etree (sparse ([1,2], [1,2], [1,1], 2, 2)), [0, 0])\n%!assert (etree (sparse ([1,2], [1,2], [true, true], 2, 2)), [0, 0])\n%!assert (etree (sparse ([1,2], [1,2], [i,i], 2, 2)), [0, 0])\n%!assert (etree (gallery (\"poisson\", 16)), [2:256, 0])\n\n%!error <Invalid call> etree ()\n%!error <Invalid call> etree (1, 2, 3)\n%!error <TYP must be a string> etree (speye (2), 3)\n%!error <is not square> etree (sprand (2, 4, .25))\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/colloc.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <string>\n\n#include \"CollocWt.h\"\n#include \"mappers.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (colloc, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{r}, @var{amat}, @var{bmat}, @var{q}] =} colloc (@var{n}, \"left\", \"right\")\nCompute derivative and integral weight matrices for orthogonal collocation.\n\nReference: @nospell{J. Villadsen}, @nospell{M. L. Michelsen},\n@cite{Solution of Differential Equation Models by Polynomial Approximation}.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  if (! args(0).is_scalar_type ())\n    error (\"colloc: N must be a scalar\");\n\n  double tmp = args(0).double_value ();\n  if (math::isnan (tmp))\n    error (\"colloc: N cannot be NaN\");\n\n  octave_idx_type ncol = math::nint_big (tmp);\n  if (ncol < 0)\n    error (\"colloc: N must be positive\");\n\n  octave_idx_type ntot = ncol;\n  octave_idx_type left = 0;\n  octave_idx_type right = 0;\n\n  for (int i = 1; i < nargin; i++)\n    {\n      std::string s = args(i).xstring_value (\"colloc: optional arguments must be strings\");\n\n      std::transform (s.begin (), s.end (), s.begin (), ::tolower);\n\n      if (s == \"r\" || s == \"right\")\n        right = 1;\n      else if (s == \"l\" || s == \"left\")\n        left = 1;\n      else\n        error (R\"(colloc: string argument must be \"left\" or \"right\")\");\n    }\n\n  ntot += left + right;\n  if (ntot < 1)\n    error (R\"(\"colloc: the total number of roots (N + \"left\" + \"right\") must be >= 1)\");\n\n  CollocWt wts (ncol, left, right);\n\n  ColumnVector r = wts.roots ();\n  Matrix A = wts.first ();\n  Matrix B = wts.second ();\n  ColumnVector q = wts.quad_weights ();\n\n  return ovl (r, A, B, q);\n}\n\n/*\n\n%!assert (colloc (1), 0.5)\n%!assert (colloc (1, \"left\"), [0; 0.5])\n%!assert (colloc (1, \"right\"), [0.5; 1])\n%!assert (colloc (1, \"left\", \"right\"), [0; 0.5; 1])\n\n## Test input validation\n%!error colloc ()\n%!error colloc (1,2,3,4)\n%!error <N must be a scalar> colloc (ones (2,2))\n%!error <N cannot be NaN> colloc (NaN)\n%!error <N must be positive> colloc (-1)\n%!error <optional arguments must be strings> colloc (1, 1)\n%!error <string argument must be \"left\" or \"right\"> colloc (1, \"foobar\")\n%!error <total number of roots .* must be .= 1> colloc (0)\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/conv2.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-convn.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nenum Shape { SHAPE_FULL, SHAPE_SAME, SHAPE_VALID };\n\nDEFUN (conv2, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} conv2 (@var{A}, @var{B})\n@deftypefnx {} {@var{C} =} conv2 (@var{v1}, @var{v2}, @var{m})\n@deftypefnx {} {@var{C} =} conv2 (@dots{}, @var{shape})\nReturn the 2-D convolution of @var{A} and @var{B}.\n\nThe size of the result is determined by the optional @var{shape} argument\nwhich takes the following values\n\n@table @asis\n@item @qcode{\"full\"}\nReturn the full convolution.  (default)\n\n@item @qcode{\"same\"}\nReturn the central part of the convolution with the same size as @var{A}.\nThe central part of the convolution begins at the indices\n@code{floor ([size(@var{B})/2] + 1)}.\n\n@item @qcode{\"valid\"}\nReturn only the parts which do not include zero-padded edges.\nThe size of the result is @code{max (size (A) - size (B) + 1, 0)}.\n@end table\n\nWhen the third argument is a matrix, return the convolution of the matrix\n@var{m} by the vector @var{v1} in the column direction and by the vector\n@var{v2} in the row direction.\n@seealso{conv, convn}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n\n  if (args(0).ndims () > 2 || args(1).ndims () > 2)\n    error (\"conv2: A and B must be 1-D vectors or 2-D matrices\");\n\n  std::string shape = \"full\";   // default\n  bool separable = false;\n  convn_type ct = convn_full;\n\n  if (nargin == 3)\n    {\n      if (args(2).is_string ())\n        shape = args(2).string_value ();\n      else\n        separable = true;\n    }\n  else if (nargin == 4)\n    {\n      separable = true;\n      shape = args(3).xstring_value (\"conv2: SHAPE must be a string\");\n    }\n\n  if (shape == \"full\")\n    ct = convn_full;\n  else if (shape == \"same\")\n    ct = convn_same;\n  else if (shape == \"valid\")\n    ct = convn_valid;\n  else\n    error (\"conv2: invalid SHAPE type\");\n\n  octave_value retval;\n\n  if (separable)\n    {\n      // If user requests separable, check first two params are vectors\n      if ((args(0).rows () != 1 && args(0).columns () != 1)\n          || (args(1).rows () != 1 &&  args(1).columns () != 1))\n        error (\"conv2: V1 and V2 arguments must be vectors\");\n\n      if (args(0).is_single_type () || args(1).is_single_type ()\n          || args(2).is_single_type ())\n        {\n          if (args(0).iscomplex () || args(1).iscomplex ()\n              || args(2).iscomplex ())\n            {\n              FloatComplexMatrix a (args(2).float_complex_matrix_value ());\n              if (args(1).isreal () && args(2).isreal ())\n                {\n                  FloatColumnVector v1 (args(0).float_vector_value ());\n                  FloatRowVector v2 (args(1).float_vector_value ());\n                  retval = convn (a, v1, v2, ct);\n                }\n              else\n                {\n                  FloatComplexColumnVector v1 (args(0).float_complex_vector_value ());\n                  FloatComplexRowVector v2 (args(1).float_complex_vector_value ());\n                  retval = convn (a, v1, v2, ct);\n                }\n            }\n          else\n            {\n              FloatColumnVector v1 (args(0).float_vector_value ());\n              FloatRowVector v2 (args(1).float_vector_value ());\n              FloatMatrix a (args(2).float_matrix_value ());\n              retval = convn (a, v1, v2, ct);\n            }\n        }\n      else\n        {\n          if (args(0).iscomplex () || args(1).iscomplex ()\n              || args(2).iscomplex ())\n            {\n              ComplexMatrix a (args(2).complex_matrix_value ());\n              if (args(1).isreal () && args(2).isreal ())\n                {\n                  ColumnVector v1 (args(0).vector_value ());\n                  RowVector v2 (args(1).vector_value ());\n                  retval = convn (a, v1, v2, ct);\n                }\n              else\n                {\n                  ComplexColumnVector v1 (args(0).complex_vector_value ());\n                  ComplexRowVector v2 (args(1).complex_vector_value ());\n                  retval = convn (a, v1, v2, ct);\n                }\n            }\n          else\n            {\n              ColumnVector v1 (args(0).vector_value ());\n              RowVector v2 (args(1).vector_value ());\n              Matrix a (args(2).matrix_value ());\n              retval = convn (a, v1, v2, ct);\n            }\n        }\n    }\n  else  // not separable\n    {\n      if (args(0).is_single_type () || args(1).is_single_type ())\n        {\n          if (args(0).iscomplex () || args(1).iscomplex ())\n            {\n              FloatComplexMatrix a (args(0).float_complex_matrix_value ());\n              if (args(1).isreal ())\n                {\n                  FloatMatrix b (args(1).float_matrix_value ());\n                  retval = convn (a, b, ct);\n                }\n              else\n                {\n                  FloatComplexMatrix b (args(1).float_complex_matrix_value ());\n                  retval = convn (a, b, ct);\n                }\n            }\n          else\n            {\n              FloatMatrix a (args(0).float_matrix_value ());\n              FloatMatrix b (args(1).float_matrix_value ());\n              retval = convn (a, b, ct);\n            }\n        }\n      else\n        {\n          if (args(0).iscomplex () || args(1).iscomplex ())\n            {\n              ComplexMatrix a (args(0).complex_matrix_value ());\n              if (args(1).isreal ())\n                {\n                  Matrix b (args(1).matrix_value ());\n                  retval = convn (a, b, ct);\n                }\n              else\n                {\n                  ComplexMatrix b (args(1).complex_matrix_value ());\n                  retval = convn (a, b, ct);\n                }\n            }\n          else\n            {\n              Matrix a (args(0).matrix_value ());\n              Matrix b (args(1).matrix_value ());\n              retval = convn (a, b, ct);\n            }\n        }\n\n    }\n\n  return retval;\n}\n\n/*\n## Test input classes: double, single, and uint8 => double\n%!test\n%! c = [0,1,2,3;1,8,12,12;4,20,24,21;7,22,25,18];\n%! assert (conv2 ([0,1;1,2], [1,2,3;4,5,6;7,8,9]), c);\n\n%!test\n%! c = single ([0,1,2,3;1,8,12,12;4,20,24,21;7,22,25,18]);\n%! assert (conv2 (single ([0,1;1,2]), single ([1,2,3;4,5,6;7,8,9])), c);\n\n%!test\n%! c = [0,1,2,3;1,8,12,12;4,20,24,21;7,22,25,18];\n%! assert (conv2 (uint8 ([0,1;1,2]), uint8 ([1,2,3;4,5,6;7,8,9])), c);\n\n%!test\n%! c = [1,4,4;5,18,16;14,48,40;19,62,48;15,48,36];\n%! assert (conv2 (1:3, 1:2, [1,2;3,4;5,6]), c);\n\n## Test that \"full\" is default shape\n%!assert (conv2 (1:3, 1:2, [1,2;3,4;5,6], \"full\"),\n%!        conv2 (1:3, 1:2, [1,2;3,4;5,6]));\n\n## Test shapes\n%!shared A, B, C\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 12345); # initialize generator to make behavior reproducible\n%! A = randi (100, 3, 4);\n%! B = randi (100, 4, 4);\n%! C = conv2 (A, B);\n%!assert (conv2 (A,B, \"full\"), C)\n%!assert (conv2 (A,B, \"same\"), C(3:5,3:6))\n%!assert (conv2 (A,B, \"valid\"), zeros (0, 1))\n%!assert (size (conv2 (B,A, \"valid\")), [2 1])\n\n%!test\n%! A = randi (100, 3, 4);\n%! B = randi (100, 5, 5);\n%! C = conv2 (A, B);\n%!assert (conv2 (A,B, \"full\"), C)\n%!assert (conv2 (A,B, \"same\"), C(3:5,3:6))\n%!assert (conv2 (A,B, \"valid\"), zeros (0, 0))\n%!assert (size (conv2 (B,A, \"valid\")), [3 2])\n\n## Clear shared variables so they are not reported for tests below\n%!shared\n\n## Test cases from Bug #34893\n%!assert <*34893> (conv2 ([1:5;1:5], [1:2], \"same\"),\n%!                [4 7 10 13 10; 4 7 10 13 10])\n%!assert <*34893> (conv2 ([1:5;1:5]', [1:2]', \"same\"),\n%!                [4 7 10 13 10; 4 7 10 13 10]')\n%!assert <*34893> (conv2 ([1:5;1:5], [1:2], \"valid\"),\n%!                [4 7 10 13; 4 7 10 13])\n%!assert <*34893> (conv2 ([1:5;1:5]', [1:2]', \"valid\"),\n%!                [4 7 10 13; 4 7 10 13]')\n\n%!test\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 12345); # initialize generator to make behavior reproducible\n%! x = randi (100, 100, 100);\n%! y = ones (5);\n%! A = conv2 (x, y)(5:end-4,5:end-4);\n%! B = conv2 (x, y, \"valid\");\n%! assert (B, A, eps);\n\n## Test input validation\n%!error <Invalid call> conv2 ()\n%!error <Invalid call> conv2 (1)\n%!error <Invalid call> conv2 (1,2,3,4,5)\n%!error <must be 1-D vectors or 2-D matrices> conv2 (ones (2,2,2), ones (2))\n%!error <must be 1-D vectors or 2-D matrices> conv2 (ones (2), ones (2,2,2))\n%!error <invalid SHAPE type> conv2 (1,2, \"NOT_A_SHAPE\")\n## Test alternate calling form which should be 2 vectors and a matrix\n%!error <V1 and V2 arguments must be vectors> conv2 (ones (2), 1, 1)\n%!error <V1 and V2 arguments must be vectors> conv2 (1, ones (2), 1)\n%!error <SHAPE must be a string> conv2 (1, ones (2), 1, {1})\n*/\n\nDEFUN (convn, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} convn (@var{A}, @var{B})\n@deftypefnx {} {@var{C} =} convn (@var{A}, @var{B}, @var{shape})\nReturn the N-D convolution of @var{A} and @var{B}.\n\nThe size of the result is determined by the optional @var{shape} argument\nwhich takes the following values\n\n@table @asis\n@item @qcode{\"full\"}\nReturn the full convolution.  (default)\n\n@item @qcode{\"same\"}\nReturn central part of the convolution with the same size as @var{A}.\nThe central part of the convolution begins at the indices\n@code{floor ([size(@var{B})/2] + 1)}.\n\n@item @qcode{\"valid\"}\nReturn only the parts which do not include zero-padded edges.\nThe size of the result is @code{max (size (A) - size (B) + 1, 0)}.\n@end table\n\n@seealso{conv2, conv}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  convn_type ct = convn_full;\n\n  if (nargin == 3)\n    {\n      std::string shape = args(2).xstring_value (\"convn: SHAPE must be a string\");\n\n      if (shape == \"full\")\n        ct = convn_full;\n      else if (shape == \"same\")\n        ct = convn_same;\n      else if (shape == \"valid\")\n        ct = convn_valid;\n      else\n        error (\"convn: SHAPE type not valid\");\n    }\n\n  octave_value retval;\n\n  if (args(0).is_single_type () || args(1).is_single_type ())\n    {\n      if (args(0).iscomplex () || args(1).iscomplex ())\n        {\n          FloatComplexNDArray a (args(0).float_complex_array_value ());\n          if (args(1).isreal ())\n            {\n              FloatNDArray b (args(1).float_array_value ());\n              retval = convn (a, b, ct);\n            }\n          else\n            {\n              FloatComplexNDArray b (args(1).float_complex_array_value ());\n              retval = convn (a, b, ct);\n            }\n        }\n      else\n        {\n          FloatNDArray a (args(0).float_array_value ());\n          FloatNDArray b (args(1).float_array_value ());\n          retval = convn (a, b, ct);\n        }\n    }\n  else\n    {\n      if (args(0).iscomplex () || args(1).iscomplex ())\n        {\n          ComplexNDArray a (args(0).complex_array_value ());\n          if (args(1).isreal ())\n            {\n              NDArray b (args(1).array_value ());\n              retval = convn (a, b, ct);\n            }\n          else\n            {\n              ComplexNDArray b (args(1).complex_array_value ());\n              retval = convn (a, b, ct);\n            }\n        }\n      else\n        {\n          NDArray a (args(0).array_value ());\n          NDArray b (args(1).array_value ());\n          retval = convn (a, b, ct);\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test <*39314>\n%! v = reshape ([1 2], [1 1 2]);\n%! assert (convn (v, v), reshape ([1 4 4], [1 1 3]));\n%! assert (convn (v, v, \"same\"), reshape ([4 4], [1 1 2]));\n%! assert (convn (v, v, \"valid\"), 4);\n\n## The following test may look weird since we are using the output\n## of convn to test itself.  However, because calculations are done\n## differently based on the shape option, it will help to catch some\n## bugs.  See also bug #39314.\n## FIXME: The \"valid\" option uses an entirely different code path\n##        through C++ and Fortran to calculate inner convolution.\n##        The terms in the convolution added in reverse order compared\n##        to the \"full\" option.  This produces differences on the order\n##        of tens of eps.  This should be fixed, but in the meantime\n##        the tests will be marked as known failures.\n%!shared a, b, c\n%! ## test 3-D by 3-D\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 12345); # initialize generator to make behavior reproducible\n%! a = randi (100, 10, 10, 10);\n%! b = randi (100, 3, 3, 3);\n%! c = convn (a, b, \"full\");\n%!assert (convn (a, b, \"same\"), c(2:11,2:11,2:11), eps)\n%!test <*39314>\n%! assert (all (abs ((convn (a, b, \"valid\") - c(3:10,3:10,3:10))(:)) <= eps),\n%!         \"central part of convn 'full' differs from convn 'valid'\");\n%!\n%!test\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 12345); # initialize generator to make behavior reproducible\n%! ## test 3-D by 2-D\n%! a = randi (100, 10, 10, 10);\n%! b = randi (100, 3, 3);\n%! c = convn (a, b, \"full\");\n%!assert (convn (a, b, \"same\"), c(2:11,2:11,:), eps)\n%!test <*39314>\n%! assert (all (abs ((convn (a, b, \"valid\") - c(3:10,3:10,:))(:)) <= eps),\n%!         \"central part of convn 'full' differs from convn 'valid'\");\n%!\n%!test\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 12345); # initialize generator to make behavior reproducible\n%! ## test 2-D by 3-D\n%! a = randi (100, 10, 10);\n%! b = randi (100, 3, 3, 3);\n%! c = convn (a, b, \"full\");\n%!assert (convn (a, b, \"same\"), c(2:11,2:11,2))\n%!assert (convn (a, b, \"valid\"), c(3:10,3:10,3:2))  # a 7x7x0 matrix\n%!\n%!test\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 12345); # initialize generator to make behavior reproducible\n%! ## test multiple different number of dimensions, with odd and even numbers\n%! a = randi (100, 10, 15, 7, 8, 10);\n%! b = randi (100, 4, 3, 2, 3);\n%! c = convn (a, b, \"full\");\n%!assert (convn (a, b, \"same\"), c(3:12,2:16,2:8,2:9,:))\n%!test <*39314>\n%! assert (all (abs ((convn (a, b, \"valid\") - c(4:10,3:15,2:7,3:8,:))(:)) <= eps),\n%!         \"central part of convn 'full' differs from convn 'valid'\");\n\n%!test\n%! a = reshape (floor (magic (16) /10), [4 8 4 2]);\n%! b = reshape (magic (6), [4 3 3]);\n%! c = zeros (7, 10, 6, 2);\n%! c(:,:,1,1) = [\n%!    875  1415  1215   741   288   264   635  1109   687   171\n%!    110   467  1551  1790  1891  1651  1165   900   659   568\n%!    883  1047  1475  1964  2181  2302  2117  1674   579   234\n%!    940  2330  3099  2573  2306  2207  2442  2918  2272  1004\n%!    161   500  1564  2066  2355  2270  2099  1621  1144   831\n%!    644   622   886  1121  1652  1967  1907  1668   529   228\n%!    160   752  1232   768   360   284   668  1132  1380   864];\n%! c(:,:,2,1) = [\n%!    150  1174  1903  1971  2030  1719  1467  1420  1220   472\n%!    986  2243  2603  2385  2308  2530  2971  3181  2266   768\n%!    914  2443  3750  3782  3976  3821  3723  3709  2599  1178\n%!   1922  3374  5198  5472  5563  5853  5794  5543  3578  1820\n%!   1060  2471  3846  3724  3682  3803  3812  3927  2876  1390\n%!    470  2078  3283  3225  2701  2265  2165  2261  2324  1124\n%!    700  1130  1486  1515  1830  2097  2081  2028  1009   348];\n%! c(:,:,3,1) = [\n%!   1350  2127  2461  2082  1694  1909  2230  2621  1681   683\n%!    877  2473  4362  4556  4543  4314  3879  3703  2863  1497\n%!   1934  4219  5874  6117  5966  6051  5984  5714  3891  1562\n%!   1927  5997  8573  8456  8517  8025  7957  8101  6121  2500\n%!   1558  3533  5595  6064  6453  6491  6275  5743  3794  1832\n%!   1950  2762  3455  3423  4019  4578  4807  4857  2304   907\n%!    525  1860  2731  2392  1872  1724  1961  2312  2315  1141];\n%! c(:,:,4,1) = [\n%!    150  1317  2230  2621  2996  2767  2472  2049  1514   583\n%!   1429  3056  3879  3703  3756  3964  4394  4570  3111  1250\n%!   1833  4037  5984  5714  5846  5788  5883  6129  4157  2011\n%!   3143  5469  7957  8101  8063  8475  8564  8439  5306  2538\n%!   2001  4514  6275  5743  5391  5389  5578  6110  4473  1953\n%!    817  3196  4807  4857  4229  3659  3477  3375  3208  1400\n%!    750  1365  1961  2312  2840  2993  2722  2344  1092   323];\n%! c(:,:,5,1) = [\n%!    475   734  1296  1352  1400  1595  1557  1517   960   490\n%!    751  1977  2831  2746  2607  2665  2733  2833  2186   912\n%!   1065  3142  4344  4150  3768  3734  3876  4086  3366  1327\n%!    976  3712  5530  5921  6158  5802  5481  5071  3821  1491\n%!   1397  2996  3971  4003  4088  4180  4199  4146  2649   985\n%!   1273  2121  2555  2247  2378  2624  2908  3229  1788   705\n%!    365  1108  1530  1652  1550  1407  1274  1127   889   264];\n%! c(:,:,6,1) = [\n%!      0   133   345   683   982  1058   960   623   310   100\n%!    437   806  1313  1332  1383  1391  1397  1370   864   495\n%!    928  1573  2201  1928  1864  1932  2183  2445  1557   855\n%!   1199  2083  2739  2573  2507  2656  2786  2928  1795   736\n%!    912  1997  2404  2028  1692  1591  1803  2159  1603   599\n%!    345  1092  1526  1666  1593  1437  1275  1116   863   253\n%!     50   235   510   811   998   894   615   318    77     0];\n%! c(:,:,1,2) = [\n%!    840  1350  1176   697   293   320   674  1153   717   180\n%!    142   490  1563  1824  1929  1604  1132   857   624   587\n%!    890  1084  1539  1979  2238  2333  2072  1610   509   202\n%!    966  2263  3034  2518  2250  2235  2512  2992  2305  1016\n%!    200   561  1607  2107  2361  2277  2030  1548  1102   818\n%!    652   631   922  1128  1670  1997  1895  1665   467   197\n%!    160   744  1192   692   292   256   708  1208  1448   900];\n%! c(:,:,2,2) = [\n%!    179  1199  1886  1987  1997  1716  1479  1383  1215   485\n%!    988  2213  2552  2358  2304  2615  3011  3210  2246   744\n%!    921  2483  3747  3768  3960  3835  3712  3698  2588  1183\n%!   1903  3416  5254  5490  5572  5826  5761  5505  3502  1814\n%!   1064  2507  3825  3666  3680  3748  3821  3958  2892  1395\n%!    495  2129  3277  3228  2566  2216  2154  2250  2390  1154\n%!    700  1105  1472  1524  1856  2113  2059  2019   975   325];\n%! c(:,:,3,2) = [\n%!   1302  2104  2439  2006  1723  1931  2280  2685  1678   690\n%!    877  2507  4408  4580  4523  4233  3852  3647  2850  1516\n%!   1949  4238  5895  6143  6018  6063  5930  5656  3847  1538\n%!   1953  5975  8547  8433  8407  8060  7955  8069  6170  2506\n%!   1621  3536  5624  6117  6459  6456  6180  5666  3735  1815\n%!   1904  2751  3429  3366  4122  4622  4840  4864  2242   882\n%!    517  1843  2674  2337  1777  1686  2005  2367  2385  1175];\n%! c(:,:,4,2) = [\n%!    198  1346  2280  2685  2980  2759  2396  1982  1497   576\n%!   1413  2994  3852  3647  3756  4035  4418  4595  3109  1231\n%!   1873  4025  5930  5656  5792  5772  5909  6152  4185  2035\n%!   3110  5510  7955  8069  8139  8456  8541  8439  5276  2541\n%!   1964  4462  6180  5666  5315  5409  5631  6178  4536  1998\n%!    869  3215  4840  4864  4121  3579  3420  3386  3271  1430\n%!    725  1361  2005  2367  2925  3006  2667  2297  1054   325];\n%! c(:,:,5,2) = [\n%!    462   754  1285  1359  1441  1605  1556  1488   938   488\n%!    729  1967  2788  2732  2608  2683  2744  2830  2195   912\n%!   1052  3139  4302  4101  3742  3730  3895  4103  3403  1335\n%!   1007  3725  5577  5964  6165  5754  5407  5006  3846  1507\n%!   1375  2969  3951  3990  4144  4183  4200  4150  2661   998\n%!   1258  2090  2495  2188  2403  2664  2954  3279  1814   723\n%!    388  1127  1551  1673  1525  1390  1253  1139   912   275];\n%! c(:,:,6,2) = [\n%!     19   147   384   716  1016  1059   927   570   276    80\n%!    441   791  1298  1320  1401  1396  1409  1367   865   500\n%!    932  1537  2155  1870  1860  1946  2221  2487  1584   874\n%!   1201  2067  2705  2538  2512  2687  2806  2971  1812   756\n%!    925  1976  2363  1971  1636  1600  1844  2239  1664   626\n%!    372  1133  1558  1687  1570  1401  1243  1122   883   264\n%!     60   270   556   857  1024   870   569   282    66     0];\n%!assert (convn (a, b, \"full\"), c)\n%!assert (convn (a, b, \"same\"), c(3:6,2:9,2:5,:))\n%!assert (convn (a, b, \"valid\"), c(4,3:8,3:4,:))\n\n## test correct class\n%!shared a, b, c, d\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 12345); # initialize generator to make behavior reproducible\n%! a = rand (5);\n%! b = rand (3);\n%! c = rand (5, \"single\");\n%! d = rand (3, \"single\");\n%!assert (class (convn (a, b)), \"double\")\n%!assert (class (convn (c, b)), \"single\")\n%!assert (class (convn (a, d)), \"single\")\n%!assert (class (convn (true (5), b)), \"double\")\n%!assert (class (convn (true (5), d)), \"single\")\n%!assert (class (convn (ones (5, \"uint8\"), b)), \"double\")\n%!assert (class (convn (d, ones (5, \"uint8\"))), \"single\")\n\n## Test input validation\n%!error <Invalid call> convn ()\n%!error <Invalid call> convn (1)\n%!error <Invalid call> convn (1,2,3,4)\n%!error <SHAPE must be a string> convn (1,2,{3})\n%!error <SHAPE type not valid> convn (1,2, \"NOT_A_SHAPE\")\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/daspk.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <list>\n#include <string>\n\n#include \"DASPK.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ovl.h\"\n#include \"ov-fcn.h\"\n#include \"ov-cell.h\"\n#include \"pager.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n#include \"DASPK-opts.cc\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Global pointer for user defined function required by daspk.\nstatic octave_value daspk_fcn;\n\n// Global pointer for optional user defined jacobian function.\nstatic octave_value daspk_jac;\n\n// Have we warned about imaginary values returned from user function?\nstatic bool warned_fcn_imaginary = false;\nstatic bool warned_jac_imaginary = false;\n\n// Is this a recursive call?\nstatic int call_depth = 0;\n\nstatic ColumnVector\ndaspk_user_function (const ColumnVector& x, const ColumnVector& xdot,\n                     double t, octave_idx_type& ires)\n{\n  ColumnVector retval;\n\n  panic_unless (x.numel () == xdot.numel ());\n\n  octave_value_list args;\n\n  args(2) = t;\n  args(1) = xdot;\n  args(0) = x;\n\n  if (daspk_fcn.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (daspk_fcn, args, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"daspk\");\n        }\n\n      int tlen = tmp.length ();\n      if (tlen == 0 || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"daspk\");\n\n      if (! warned_fcn_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"daspk: ignoring imaginary part returned from user-supplied function\");\n          warned_fcn_imaginary = true;\n        }\n\n      retval = tmp(0).vector_value ();\n\n      if (tlen > 1)\n        ires = tmp(1).idx_type_value ();\n\n      if (retval.isempty ())\n        err_user_supplied_eval (\"daspk\");\n    }\n\n  return retval;\n}\n\nstatic Matrix\ndaspk_user_jacobian (const ColumnVector& x, const ColumnVector& xdot,\n                     double t, double cj)\n{\n  Matrix retval;\n\n  panic_unless (x.numel () == xdot.numel ());\n\n  octave_value_list args;\n\n  args(3) = cj;\n  args(2) = t;\n  args(1) = xdot;\n  args(0) = x;\n\n  if (daspk_jac.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (daspk_jac, args, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"daspk\");\n        }\n\n      int tlen = tmp.length ();\n      if (tlen == 0 || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"daspk\");\n\n      if (! warned_jac_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"daspk: ignoring imaginary part returned from user-supplied jacobian function\");\n          warned_jac_imaginary = true;\n        }\n\n      retval = tmp(0).matrix_value ();\n\n      if (retval.isempty ())\n        err_user_supplied_eval (\"daspk\");\n    }\n\n  return retval;\n}\n\nDEFMETHOD (daspk, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{x}, @var{xdot}, @var{istate}, @var{msg}] =} daspk (@var{fcn}, @var{x_0}, @var{xdot_0}, @var{t}, @var{t_crit})\nSolve a set of differential-algebraic equations.\n\n@code{daspk} solves the set of equations\n@tex\n$$ 0 = f (x, \\dot{x}, t) $$\nwith\n$$ x(t_0) = x_0, \\dot{x}(t_0) = \\dot{x}_0 $$\n@end tex\n@ifnottex\n\n@example\n0 = f (x, xdot, t)\n@end example\n\n@noindent\nwith\n\n@example\nx(t_0) = x_0, xdot(t_0) = xdot_0\n@end example\n\n@end ifnottex\nThe solution is returned in the matrices @var{x} and @var{xdot},\nwith each row in the result matrices corresponding to one of the\nelements in the vector @var{t}.  The first element of @var{t}\nshould be @math{t_0} and correspond to the initial state of the\nsystem @var{x_0} and its derivative @var{xdot_0}, so that the first\nrow of the output @var{x} is @var{x_0} and the first row\nof the output @var{xdot} is @var{xdot_0}.\n\nThe first argument, @var{fcn}, is a string, inline, or function handle\nthat names the function @math{f} to call to compute the vector of\nresiduals for the set of equations.  It must have the form\n\n@example\n@var{res} = f (@var{x}, @var{xdot}, @var{t})\n@end example\n\n@noindent\nin which @var{x}, @var{xdot}, and @var{res} are vectors, and @var{t} is a\nscalar.\n\nIf @var{fcn} is a two-element string array or a two-element cell array\nof strings, inline functions, or function handles, the first element names\nthe function @math{f} described above, and the second element names a\nfunction to compute the modified Jacobian\n@tex\n$$\nJ = {\\partial f \\over \\partial x}\n  + c {\\partial f \\over \\partial \\dot{x}}\n$$\n@end tex\n@ifnottex\n\n@example\n@group\n      df       df\njac = -- + c ------\n      dx     d xdot\n@end group\n@end example\n\n@end ifnottex\n\nThe modified Jacobian function must have the form\n\n@example\n@group\n\n@var{jac} = j (@var{x}, @var{xdot}, @var{t}, @var{c})\n\n@end group\n@end example\n\nThe second and third arguments to @code{daspk} specify the initial\ncondition of the states and their derivatives, and the fourth argument\nspecifies a vector of output times at which the solution is desired,\nincluding the time corresponding to the initial condition.\n\nThe set of initial states and derivatives are not strictly required to\nbe consistent.  If they are not consistent, you must use the\n@code{daspk_options} function to provide additional information so\nthat @code{daspk} can compute a consistent starting point.\n\nThe fifth argument is optional, and may be used to specify a set of\ntimes that the DAE solver should not integrate past.  It is useful for\navoiding difficulties with singularities and points where there is a\ndiscontinuity in the derivative.\n\nAfter a successful computation, the value of @var{istate} will be\ngreater than zero (consistent with the Fortran version of @sc{daspk}).\n\nIf the computation is not successful, the value of @var{istate} will be\nless than zero and @var{msg} will contain additional information.\n\nYou can use the function @code{daspk_options} to set optional\nparameters for @code{daspk}.\n@seealso{dassl}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 4 || nargin > 5)\n    print_usage ();\n\n  warned_fcn_imaginary = false;\n  warned_jac_imaginary = false;\n\n  octave_value_list retval (4);\n\n  unwind_protect_var<int> restore_var (call_depth);\n  call_depth++;\n\n  if (call_depth > 1)\n    error (\"daspk: invalid recursive call\");\n\n  std::string fcn_name, fname, jac_name, jname;\n\n  daspk_fcn = octave_value ();\n  daspk_jac = octave_value ();\n\n  octave_value f_arg = args(0);\n\n  std::list<std::string> fcn_param_names ({\"x\", \"xdot\", \"t\"});\n  std::list<std::string> jac_param_names ({\"x\", \"xdot\", \"t\", \"cj\"});\n\n  if (f_arg.iscell ())\n    {\n      Cell c = f_arg.cell_value ();\n      if (c.numel () == 1)\n        f_arg = c(0);\n      else if (c.numel () == 2)\n        {\n          daspk_fcn = get_function_handle (interp, c(0), fcn_param_names);\n\n          if (daspk_fcn.is_defined ())\n            {\n              daspk_jac = get_function_handle (interp, c(1), jac_param_names);\n\n              if (daspk_jac.is_undefined ())\n                daspk_fcn = octave_value ();\n            }\n        }\n      else\n        error (\"daspk: incorrect number of elements in cell array\");\n    }\n\n  if (daspk_fcn.is_undefined () && ! f_arg.iscell ())\n    {\n      if (f_arg.is_function_handle () || f_arg.is_inline_function ())\n        daspk_fcn = f_arg;\n      else\n        {\n          switch (f_arg.rows ())\n            {\n            case 1:\n              daspk_fcn = get_function_handle (interp, f_arg, fcn_param_names);\n              break;\n\n            case 2:\n              {\n                string_vector tmp = f_arg.string_vector_value ();\n\n                daspk_fcn = get_function_handle (interp, tmp(0),\n                                                 fcn_param_names);\n\n                if (daspk_fcn.is_defined ())\n                  {\n                    daspk_jac = get_function_handle (interp, tmp(1),\n                                                     jac_param_names);\n\n                    if (daspk_jac.is_undefined ())\n                      daspk_fcn = octave_value ();\n                  }\n              }\n              break;\n\n            default:\n              error (\"daspk: first arg should be a string or 2-element string array\");\n            }\n        }\n    }\n\n  if (daspk_fcn.is_undefined ())\n    error (\"daspk: FCN argument is not a valid function name or handle\");\n\n  ColumnVector state = args(1).xvector_value (\"daspk: initial state X_0 must be a vector\");\n\n  ColumnVector deriv = args(2).xvector_value (\"daspk: initial derivatives XDOT_0 must be a vector\");\n\n  ColumnVector out_times = args(3).xvector_value (\"daspk: output time variable T must be a vector\");\n\n  ColumnVector crit_times;\n  int crit_times_set = 0;\n  if (nargin > 4)\n    {\n      crit_times = args(4).xvector_value (\"daspk: list of critical times T_CRIT must be a vector\");\n\n      crit_times_set = 1;\n    }\n\n  if (state.numel () != deriv.numel ())\n    error (\"daspk: X_0 and XDOT_0 must have the same size\");\n\n  double tzero = out_times (0);\n\n  DAEFunc fcn (daspk_user_function);\n  if (daspk_jac.is_defined ())\n    fcn.set_jacobian_function (daspk_user_jacobian);\n\n  DASPK dae (state, deriv, tzero, fcn);\n  dae.set_options (daspk_opts);\n\n  Matrix output;\n  Matrix deriv_output;\n\n  if (crit_times_set)\n    output = dae.integrate (out_times, deriv_output, crit_times);\n  else\n    output = dae.integrate (out_times, deriv_output);\n\n  std::string msg = dae.error_message ();\n\n  if (dae.integration_ok ())\n    {\n      retval(0) = output;\n      retval(1) = deriv_output;\n    }\n  else\n    {\n      if (nargout < 3)\n        error (\"daspk: %s\", msg.c_str ());\n\n      retval(0) = Matrix ();\n      retval(1) = Matrix ();\n    }\n\n  retval(2) = static_cast<double> (dae.integration_state ());\n  retval(3) = msg;\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/dasrt.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <list>\n#include <string>\n\n#include \"DASRT.h\"\n#include \"mappers.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ovl.h\"\n#include \"ov-fcn.h\"\n#include \"ov-cell.h\"\n#include \"pager.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n#include \"DASRT-opts.cc\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Global pointers for user defined function required by dasrt.\nstatic octave_value dasrt_fcn;\nstatic octave_value dasrt_jac;\nstatic octave_value dasrt_cf;\n\n// Have we warned about imaginary values returned from user function?\nstatic bool warned_fcn_imaginary = false;\nstatic bool warned_jac_imaginary = false;\nstatic bool warned_cf_imaginary = false;\n\n// Is this a recursive call?\nstatic int call_depth = 0;\n\nstatic ColumnVector\ndasrt_user_f (const ColumnVector& x, const ColumnVector& xdot,\n              double t, octave_idx_type&)\n{\n  ColumnVector retval;\n\n  panic_unless (x.numel () == xdot.numel ());\n\n  octave_value_list args;\n\n  args(2) = t;\n  args(1) = xdot;\n  args(0) = x;\n\n  if (dasrt_fcn.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (dasrt_fcn, args, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"dasrt\");\n        }\n\n      if (tmp.empty () || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"dasrt\");\n\n      if (! warned_fcn_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"dasrt: ignoring imaginary part returned from user-supplied function\");\n          warned_fcn_imaginary = true;\n        }\n\n      retval = tmp(0).vector_value ();\n\n      if (retval.isempty ())\n        err_user_supplied_eval (\"dasrt\");\n    }\n\n  return retval;\n}\n\nstatic ColumnVector\ndasrt_user_cf (const ColumnVector& x, double t)\n{\n  ColumnVector retval;\n\n  octave_value_list args;\n\n  args(1) = t;\n  args(0) = x;\n\n  if (dasrt_cf.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (dasrt_cf, args, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"dasrt\");\n        }\n\n      if (tmp.empty () || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"dasrt\");\n\n      if (! warned_cf_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"dasrt: ignoring imaginary part returned from user-supplied constraint function\");\n          warned_cf_imaginary = true;\n        }\n\n      retval = tmp(0).vector_value ();\n\n      if (retval.isempty ())\n        err_user_supplied_eval (\"dasrt\");\n    }\n\n  return retval;\n}\n\nstatic Matrix\ndasrt_user_j (const ColumnVector& x, const ColumnVector& xdot,\n              double t, double cj)\n{\n  Matrix retval;\n\n  panic_unless (x.numel () == xdot.numel ());\n\n  octave_value_list args;\n\n  args(3) = cj;\n  args(2) = t;\n  args(1) = xdot;\n  args(0) = x;\n\n  if (dasrt_jac.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (dasrt_jac, args, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"dasrt\");\n        }\n\n      int tlen = tmp.length ();\n      if (tlen == 0 || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"dasrt\");\n\n      if (! warned_jac_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"dasrt: ignoring imaginary part returned from user-supplied jacobian function\");\n          warned_jac_imaginary = true;\n        }\n\n      retval = tmp(0).matrix_value ();\n\n      if (retval.isempty ())\n        err_user_supplied_eval (\"dasrt\");\n    }\n\n  return retval;\n}\n\nDEFMETHOD (dasrt, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{x}, @var{xdot}, @var{t_out}, @var{istat}, @var{msg}] =} dasrt (@var{fcn}, @var{g}, @var{x_0}, @var{xdot_0}, @var{t})\n@deftypefnx {} {@dots{} =} dasrt (@var{fcn}, @var{g}, @var{x_0}, @var{xdot_0}, @var{t}, @var{t_crit})\n@deftypefnx {} {@dots{} =} dasrt (@var{fcn}, @var{x_0}, @var{xdot_0}, @var{t})\n@deftypefnx {} {@dots{} =} dasrt (@var{fcn}, @var{x_0}, @var{xdot_0}, @var{t}, @var{t_crit})\nSolve a set of differential-algebraic equations.\n\n@code{dasrt} solves the set of equations\n@tex\n$$ 0 = f (x, \\dot{x}, t) $$\nwith\n$$ x(t_0) = x_0, \\dot{x}(t_0) = \\dot{x}_0 $$\n@end tex\n@ifnottex\n\n@example\n0 = f (x, xdot, t)\n@end example\n\n@noindent\nwith\n\n@example\nx(t_0) = x_0, xdot(t_0) = xdot_0\n@end example\n\n@end ifnottex\nwith functional stopping criteria (root solving).\n\nThe solution is returned in the matrices @var{x} and @var{xdot},\nwith each row in the result matrices corresponding to one of the\nelements in the vector @var{t_out}.  The first element of @var{t}\nshould be @math{t_0} and correspond to the initial state of the\nsystem @var{x_0} and its derivative @var{xdot_0}, so that the first\nrow of the output @var{x} is @var{x_0} and the first row\nof the output @var{xdot} is @var{xdot_0}.\n\nThe vector @var{t} provides an upper limit on the length of the\nintegration.  If the stopping condition is met, the vector\n@var{t_out} will be shorter than @var{t}, and the final element of\n@var{t_out} will be the point at which the stopping condition was met,\nand may not correspond to any element of the vector @var{t}.\n\nThe first argument, @var{fcn}, is a string, inline, or function handle\nthat names the function @math{f} to call to compute the vector of\nresiduals for the set of equations.  It must have the form\n\n@example\n@var{res} = f (@var{x}, @var{xdot}, @var{t})\n@end example\n\n@noindent\nin which @var{x}, @var{xdot}, and @var{res} are vectors, and @var{t} is a\nscalar.\n\nIf @var{fcn} is a two-element string array or a two-element cell array\nof strings, inline functions, or function handles, the first element names\nthe function @math{f} described above, and the second element names a\nfunction to compute the modified Jacobian\n@tex\n$$\nJ = {\\partial f \\over \\partial x}\n  + c {\\partial f \\over \\partial \\dot{x}}\n$$\n@end tex\n@ifnottex\n\n@example\n@group\n      df       df\njac = -- + c ------\n      dx     d xdot\n@end group\n@end example\n\n@end ifnottex\n\nThe modified Jacobian function must have the form\n\n@example\n@group\n\n@var{jac} = j (@var{x}, @var{xdot}, @var{t}, @var{c})\n\n@end group\n@end example\n\nThe optional second argument names a function that defines the\nconstraint functions whose roots are desired during the integration.\nThis function must have the form\n\n@example\n@var{g_out} = g (@var{x}, @var{t})\n@end example\n\n@noindent\nand return a vector of the constraint function values.\nIf the value of any of the constraint functions changes sign, @sc{dasrt}\nwill attempt to stop the integration at the point of the sign change.\n\nIf the name of the constraint function is omitted, @code{dasrt} solves\nthe same problem as @code{daspk} or @code{dassl}.\n\nNote that because of numerical errors in the constraint functions\ndue to round-off and integration error, @sc{dasrt} may return false\nroots, or return the same root at two or more nearly equal values of\n@var{T}.  If such false roots are suspected, the user should consider\nsmaller error tolerances or higher precision in the evaluation of the\nconstraint functions.\n\nIf a root of some constraint function defines the end of the problem,\nthe input to @sc{dasrt} should nevertheless allow integration to a\npoint slightly past that root, so that @sc{dasrt} can locate the root\nby interpolation.\n\nThe third and fourth arguments to @code{dasrt} specify the initial\ncondition of the states and their derivatives, and the fourth argument\nspecifies a vector of output times at which the solution is desired,\nincluding the time corresponding to the initial condition.\n\nThe set of initial states and derivatives are not strictly required to\nbe consistent.  In practice, however, @sc{dassl} is not very good at\ndetermining a consistent set for you, so it is best if you ensure that\nthe initial values result in the function evaluating to zero.\n\nThe sixth argument is optional, and may be used to specify a set of\ntimes that the DAE solver should not integrate past.  It is useful for\navoiding difficulties with singularities and points where there is a\ndiscontinuity in the derivative.\n\nAfter a successful computation, the value of @var{istate} will be\ngreater than zero (consistent with the Fortran version of @sc{dassl}).\n\nIf the computation is not successful, the value of @var{istate} will be\nless than zero and @var{msg} will contain additional information.\n\nYou can use the function @code{dasrt_options} to set optional\nparameters for @code{dasrt}.\n@seealso{dasrt_options, daspk, dasrt, lsode}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 4 || nargin > 6)\n    print_usage ();\n\n  warned_fcn_imaginary = false;\n  warned_jac_imaginary = false;\n  warned_cf_imaginary = false;\n\n  octave_value_list retval (5);\n\n  unwind_protect_var<int> restore_var (call_depth);\n  call_depth++;\n\n  if (call_depth > 1)\n    error (\"dasrt: invalid recursive call\");\n\n  int argp = 0;\n  std::string fcn_name, fname, jac_name, jname;\n\n  dasrt_fcn = octave_value ();\n  dasrt_jac = octave_value ();\n  dasrt_cf = octave_value ();\n\n  // Check all the arguments.  Are they the right animals?\n\n  // Here's where I take care of f and j in one shot:\n\n  octave_value f_arg = args(0);\n\n  std::list<std::string> fcn_param_names ({\"x\", \"xdot\", \"t\"});\n  std::list<std::string> jac_param_names ({\"x\", \"xdot\", \"t\", \"cj\"});\n\n  if (f_arg.iscell ())\n    {\n      Cell c = f_arg.cell_value ();\n      if (c.numel () == 1)\n        f_arg = c(0);\n      else if (c.numel () == 2)\n        {\n          dasrt_fcn = get_function_handle (interp, c(0), fcn_param_names);\n\n          if (dasrt_fcn.is_defined ())\n            {\n              dasrt_jac = get_function_handle (interp, c(1), jac_param_names);\n\n              if (dasrt_jac.is_undefined ())\n                dasrt_fcn = octave_value ();\n            }\n        }\n      else\n        error (\"dasrt: incorrect number of elements in cell array\");\n    }\n\n  if (dasrt_fcn.is_undefined () && ! f_arg.iscell ())\n    {\n      if (f_arg.is_function_handle () || f_arg.is_inline_function ())\n        dasrt_fcn = f_arg;\n      else\n        {\n          switch (f_arg.rows ())\n            {\n            case 1:\n              dasrt_fcn = get_function_handle (interp, f_arg, fcn_param_names);\n              break;\n\n            case 2:\n              {\n                string_vector tmp = f_arg.string_vector_value ();\n\n                dasrt_fcn = get_function_handle (interp, tmp(0),\n                                                 fcn_param_names);\n\n                if (dasrt_fcn.is_defined ())\n                  {\n                    dasrt_jac = get_function_handle (interp, tmp(1),\n                                                     jac_param_names);\n\n                    if (dasrt_jac.is_undefined ())\n                      dasrt_fcn = octave_value ();\n                  }\n              }\n              break;\n\n            default:\n              error (\"dasrt: first arg should be a string or 2-element string array\");\n            }\n        }\n    }\n\n  if (dasrt_fcn.is_undefined ())\n    error (\"dasrt: FCN argument is not a valid function name or handle\");\n\n  DAERTFunc fcn (dasrt_user_f);\n\n  argp++;\n\n  if (args(1).isempty () && args(1).is_double_type ())\n    {\n      // Allow [] to skip constraint function.  This feature is\n      // undocumented now, but was supported by earlier versions.\n\n      argp++;\n    }\n  else\n    {\n      if (args(1).is_function_handle () || args(1).is_inline_function ()\n          || args(1).is_string ())\n        {\n          std::list<std::string> cf_param_names ({\"x\", \"t\"});\n\n          dasrt_cf = get_function_handle (interp, args(1), cf_param_names);\n        }\n\n      if (dasrt_cf.is_defined ())\n        {\n          argp++;\n\n          fcn.set_constraint_function (dasrt_user_cf);\n        }\n    }\n\n  if (argp + 3 > nargin)\n    print_usage ();\n\n  ColumnVector state = args(argp++).xvector_value (\"dasrt: initial state X_0 must be a vector\");\n\n  ColumnVector stateprime = args(argp++).xvector_value (\"dasrt: initial derivatives XDOT_0 must be a vector\");\n\n  ColumnVector out_times = args(argp++).xvector_value (\"dasrt: output time variable T must be a vector\");\n\n  double tzero = out_times (0);\n\n  ColumnVector crit_times;\n\n  bool crit_times_set = false;\n\n  if (argp < nargin)\n    {\n      crit_times = args(argp).xvector_value (\"dasrt: list of critical times T_CRIT must be a vector\");\n      argp++;\n\n      crit_times_set = true;\n    }\n\n  if (dasrt_jac.is_defined ())\n    fcn.set_jacobian_function (dasrt_user_j);\n\n  DASRT_result output;\n\n  DASRT dae = DASRT (state, stateprime, tzero, fcn);\n\n  dae.set_options (dasrt_opts);\n\n  if (crit_times_set)\n    output = dae.integrate (out_times, crit_times);\n  else\n    output = dae.integrate (out_times);\n\n  std::string msg = dae.error_message ();\n\n  if (dae.integration_ok ())\n    {\n      retval(0) = output.state ();\n      retval(1) = output.deriv ();\n      retval(2) = output.times ();\n    }\n  else\n    {\n      if (nargout < 4)\n        error (\"dasrt: %s\", msg.c_str ());\n\n      retval(0) = Matrix ();\n      retval(1) = Matrix ();\n      retval(2) = Matrix ();\n    }\n\n  retval(3) = static_cast<double> (dae.integration_state ());\n  retval(4) = msg;\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/dassl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"DASSL.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ovl.h\"\n#include \"ov-fcn.h\"\n#include \"ov-cell.h\"\n#include \"pager.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n#include \"DASSL-opts.cc\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Global pointer for user defined function required by dassl.\nstatic octave_value dassl_fcn;\n\n// Global pointer for optional user defined jacobian function.\nstatic octave_value dassl_jac;\n\n// Have we warned about imaginary values returned from user function?\nstatic bool warned_fcn_imaginary = false;\nstatic bool warned_jac_imaginary = false;\n\n// Is this a recursive call?\nstatic int call_depth = 0;\n\nstatic ColumnVector\ndassl_user_function (const ColumnVector& x, const ColumnVector& xdot,\n                     double t, octave_idx_type& ires)\n{\n  ColumnVector retval;\n\n  panic_unless (x.numel () == xdot.numel ());\n\n  octave_value_list args;\n\n  args(2) = t;\n  args(1) = xdot;\n  args(0) = x;\n\n  if (dassl_fcn.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (dassl_fcn, args, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"dassl\");\n        }\n\n      int tlen = tmp.length ();\n      if (tlen == 0 || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"dassl\");\n\n      if (! warned_fcn_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"dassl: ignoring imaginary part returned from user-supplied function\");\n          warned_fcn_imaginary = true;\n        }\n\n      retval = tmp(0).vector_value ();\n\n      if (tlen > 1)\n        ires = tmp(1).int_value ();\n\n      if (retval.isempty ())\n        err_user_supplied_eval (\"dassl\");\n    }\n\n  return retval;\n}\n\nstatic Matrix\ndassl_user_jacobian (const ColumnVector& x, const ColumnVector& xdot,\n                     double t, double cj)\n{\n  Matrix retval;\n\n  panic_unless (x.numel () == xdot.numel ());\n\n  octave_value_list args;\n\n  args(3) = cj;\n  args(2) = t;\n  args(1) = xdot;\n  args(0) = x;\n\n  if (dassl_jac.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (dassl_jac, args, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"dassl\");\n        }\n\n      int tlen = tmp.length ();\n      if (tlen == 0 || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"dassl\");\n\n      if (! warned_jac_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"dassl: ignoring imaginary part returned from user-supplied jacobian function\");\n          warned_jac_imaginary = true;\n        }\n\n      retval = tmp(0).matrix_value ();\n\n      if (retval.isempty ())\n        err_user_supplied_eval (\"dassl\");\n    }\n\n  return retval;\n}\n\nDEFMETHOD (dassl, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{x}, @var{xdot}, @var{istate}, @var{msg}] =} dassl (@var{fcn}, @var{x_0}, @var{xdot_0}, @var{t}, @var{t_crit})\nSolve a set of differential-algebraic equations.\n\n@code{dassl} solves the set of equations\n@tex\n$$ 0 = f (x, \\dot{x}, t) $$\nwith\n$$ x(t_0) = x_0, \\dot{x}(t_0) = \\dot{x}_0 $$\n@end tex\n@ifnottex\n\n@example\n0 = f (x, xdot, t)\n@end example\n\n@noindent\nwith\n\n@example\nx(t_0) = x_0, xdot(t_0) = xdot_0\n@end example\n\n@end ifnottex\nThe solution is returned in the matrices @var{x} and @var{xdot},\nwith each row in the result matrices corresponding to one of the\nelements in the vector @var{t}.  The first element of @var{t}\nshould be @math{t_0} and correspond to the initial state of the\nsystem @var{x_0} and its derivative @var{xdot_0}, so that the first\nrow of the output @var{x} is @var{x_0} and the first row\nof the output @var{xdot} is @var{xdot_0}.\n\nThe first argument, @var{fcn}, is a string, inline, or function handle\nthat names the function @math{f} to call to compute the vector of\nresiduals for the set of equations.  It must have the form\n\n@example\n@var{res} = f (@var{x}, @var{xdot}, @var{t})\n@end example\n\n@noindent\nin which @var{x}, @var{xdot}, and @var{res} are vectors, and @var{t} is a\nscalar.\n\nIf @var{fcn} is a two-element string array or a two-element cell array\nof strings, inline functions, or function handles, the first element names\nthe function @math{f} described above, and the second element names a\nfunction to compute the modified Jacobian\n@tex\n$$\nJ = {\\partial f \\over \\partial x}\n  + c {\\partial f \\over \\partial \\dot{x}}\n$$\n@end tex\n@ifnottex\n\n@example\n@group\n      df       df\njac = -- + c ------\n      dx     d xdot\n@end group\n@end example\n\n@end ifnottex\n\nThe modified Jacobian function must have the form\n\n@example\n@group\n\n@var{jac} = j (@var{x}, @var{xdot}, @var{t}, @var{c})\n\n@end group\n@end example\n\nThe second and third arguments to @code{dassl} specify the initial\ncondition of the states and their derivatives, and the fourth argument\nspecifies a vector of output times at which the solution is desired,\nincluding the time corresponding to the initial condition.\n\nThe set of initial states and derivatives are not strictly required to\nbe consistent.  In practice, however, @sc{dassl} is not very good at\ndetermining a consistent set for you, so it is best if you ensure that\nthe initial values result in the function evaluating to zero.\n\nThe fifth argument is optional, and may be used to specify a set of\ntimes that the DAE solver should not integrate past.  It is useful for\navoiding difficulties with singularities and points where there is a\ndiscontinuity in the derivative.\n\nAfter a successful computation, the value of @var{istate} will be\ngreater than zero (consistent with the Fortran version of @sc{dassl}).\n\nIf the computation is not successful, the value of @var{istate} will be\nless than zero and @var{msg} will contain additional information.\n\nYou can use the function @code{dassl_options} to set optional\nparameters for @code{dassl}.\n@seealso{daspk, dasrt, lsode}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 4 || nargin > 5)\n    print_usage ();\n\n  warned_fcn_imaginary = false;\n  warned_jac_imaginary = false;\n\n  octave_value_list retval (4);\n\n  unwind_protect_var<int> restore_var (call_depth);\n  call_depth++;\n\n  if (call_depth > 1)\n    error (\"dassl: invalid recursive call\");\n\n  std::string fcn_name, fname, jac_name, jname;\n\n  dassl_fcn = octave_value ();\n  dassl_jac = octave_value ();\n\n  octave_value f_arg = args(0);\n\n  std::list<std::string> fcn_param_names ({\"x\", \"xdot\", \"t\"});\n  std::list<std::string> jac_param_names ({\"x\", \"xdot\", \"t\", \"cj\"});\n\n  if (f_arg.iscell ())\n    {\n      Cell c = f_arg.cell_value ();\n      if (c.numel () == 1)\n        f_arg = c(0);\n      else if (c.numel () == 2)\n        {\n          dassl_fcn = get_function_handle (interp, c(0), fcn_param_names);\n\n          if (dassl_fcn.is_defined ())\n            {\n              dassl_jac = get_function_handle (interp, c(1), jac_param_names);\n\n              if (dassl_jac.is_undefined ())\n                dassl_fcn = octave_value ();\n            }\n        }\n      else\n        error (\"dassl: incorrect number of elements in cell array\");\n    }\n\n  if (dassl_fcn.is_undefined () && ! f_arg.iscell ())\n    {\n      if (f_arg.is_function_handle () || f_arg.is_inline_function ())\n        dassl_fcn = f_arg;\n      else\n        {\n          switch (f_arg.rows ())\n            {\n            case 1:\n              dassl_fcn = get_function_handle (interp, f_arg, fcn_param_names);\n              break;\n\n            case 2:\n              {\n                string_vector tmp = f_arg.string_vector_value ();\n\n                dassl_fcn = get_function_handle (interp, tmp(0),\n                                                 fcn_param_names);\n\n                if (dassl_fcn.is_defined ())\n                  {\n                    dassl_jac = get_function_handle (interp, tmp(1),\n                                                     jac_param_names);\n\n                    if (dassl_jac.is_undefined ())\n                      dassl_fcn = octave_value ();\n                  }\n              }\n              break;\n\n            default:\n              error (\"dassl: first arg should be a string or 2-element string array\");\n            }\n        }\n    }\n\n  if (dassl_fcn.is_undefined ())\n    error (\"dassl: FCN argument is not a valid function name or handle\");\n\n  ColumnVector state = args(1).xvector_value (\"dassl: initial state X_0 must be a vector\");\n\n  ColumnVector deriv = args(2).xvector_value (\"dassl: initial derivatives XDOT_0 must be a vector\");\n\n  ColumnVector out_times = args(3).xvector_value (\"dassl: output time variable T must be a vector\");\n\n  ColumnVector crit_times;\n  int crit_times_set = 0;\n  if (nargin > 4)\n    {\n      crit_times = args(4).xvector_value (\"dassl: list of critical times T_CRIT must be a vector\");\n\n      crit_times_set = 1;\n    }\n\n  if (state.numel () != deriv.numel ())\n    error (\"dassl: X and XDOT_0 must have the same size\");\n\n  double tzero = out_times (0);\n\n  DAEFunc fcn (dassl_user_function);\n  if (dassl_jac.is_defined ())\n    fcn.set_jacobian_function (dassl_user_jacobian);\n\n  DASSL dae (state, deriv, tzero, fcn);\n\n  dae.set_options (dassl_opts);\n\n  Matrix output;\n  Matrix deriv_output;\n\n  if (crit_times_set)\n    output = dae.integrate (out_times, deriv_output, crit_times);\n  else\n    output = dae.integrate (out_times, deriv_output);\n\n  std::string msg = dae.error_message ();\n\n  if (dae.integration_ok ())\n    {\n      retval(0) = output;\n      retval(1) = deriv_output;\n    }\n  else\n    {\n      if (nargout < 3)\n        error (\"dassl: %s\", msg.c_str ());\n\n      retval(0) = Matrix ();\n      retval(1) = Matrix ();\n    }\n\n  retval(2) = static_cast<double> (dae.integration_state ());\n  retval(3) = msg;\n\n  return retval;\n}\n\n/*\n## dassl-1.m\n##\n## Test dassl() function\n##\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         20 May 1998\n##\n## Problem\n##\n##    y1' = -y2,   y1(0) = 1\n##    y2' =  y1,   y2(0) = 0\n##\n## Solution\n##\n##    y1(t) = cos(t)\n##    y2(t) = sin(t)\n##\n%!function res = __f (x, xdot, t)\n%!  res = [xdot(1)+x(2); xdot(2)-x(1)];\n%!endfunction\n\n%!test\n%!\n%! x0 = [1; 0];\n%! xdot0 = [0; 1];\n%! t = (0:1:10)';\n%!\n%! tol = 100 * dassl_options (\"relative tolerance\");\n%!\n%! [x, xdot] = dassl (\"__f\", x0, xdot0, t);\n%!\n%! y = [cos(t), sin(t)];\n%!\n%! assert (x, y, tol);\n\n## dassl-2.m\n##\n## Test dassl() function\n##\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         20 May 1998\n##\n## Based on SLATEC quick check for DASSL by Linda Petzold\n##\n## Problem\n##\n##   x1' + 10*x1 = 0,   x1(0) = 1\n##   x1  + x2    = 1,   x2(0) = 0\n##\n##\n## Solution\n##\n##  x1(t) = exp(-10*t)\n##  x2(t) = 1 - x(1)\n##\n%!function res = __f (x, xdot, t)\n%!  res = [xdot(1)+10*x(1); x(1)+x(2)-1];\n%!endfunction\n\n%!test\n%!\n%! x0 = [1; 0];\n%! xdot0 = [-10; 10];\n%! t = (0:0.2:1)';\n%!\n%! tol = 500 * dassl_options (\"relative tolerance\");\n%!\n%! [x, xdot] = dassl (\"__f\", x0, xdot0, t);\n%!\n%! y = [exp(-10*t), 1-exp(-10*t)];\n%!\n%! assert (x, y, tol);\n\n%!test\n%! old_tol = dassl_options (\"absolute tolerance\");\n%! dassl_options (\"absolute tolerance\", eps);\n%! assert (dassl_options (\"absolute tolerance\") == eps);\n%! ## Restore old value of tolerance\n%! dassl_options (\"absolute tolerance\", old_tol);\n\n%!error dassl_options (\"foo\", 1, 2)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/det.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"DET.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ops.h\"\n\n#include \"ov-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-re-diag.h\"\n#include \"ov-cx-diag.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-flt-cx-diag.h\"\n#include \"ov-perm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#define MAYBE_CAST(VAR, CLASS)                                          \\\n  const CLASS *VAR = (arg.type_id () == CLASS::static_type_id ()        \\\n                      ? dynamic_cast<const CLASS *> (&arg.get_rep ())   \\\n                      : nullptr)\n\nDEFUN (det, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{d} =} det (@var{A})\n@deftypefnx {} {[@var{d}, @var{rcond}] =} det (@var{A})\nCompute the determinant of @var{A}.\n\nReturn an estimate of the reciprocal condition number if requested.\n\nProgramming Notes: Routines from @sc{lapack} are used for full matrices and\ncode from @sc{umfpack} is used for sparse matrices.\n\nThe determinant should not be used to check a matrix for singularity.\nFor that, use any of the condition number functions: @code{cond},\n@code{condest}, @code{rcond}.\n@seealso{cond, condest, rcond}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  if (arg.isempty ())\n    return ovl (1.0);\n\n  if (arg.rows () != arg.columns ())\n    err_square_matrix_required (\"det\", \"A\");\n\n  octave_value_list retval (2);\n\n  bool isfloat = arg.is_single_type ();\n\n  if (arg.is_diag_matrix ())\n    {\n      if (nargout <= 1)\n        retval.resize (1);\n\n      if (arg.iscomplex ())\n        {\n          if (isfloat)\n            {\n              retval(0) = arg.float_complex_diag_matrix_value ()\n                          .determinant ().value ();\n              if (nargout > 1)\n                retval(1) = arg.float_complex_diag_matrix_value ().rcond ();\n            }\n          else\n            {\n              retval(0) = arg.complex_diag_matrix_value ()\n                          .determinant ().value ();\n              if (nargout > 1)\n                retval(1) = arg.complex_diag_matrix_value ().rcond ();\n            }\n        }\n      else\n        {\n          if (isfloat)\n            {\n              retval(0) = arg.float_diag_matrix_value ()\n                          .determinant ().value ();\n              if (nargout > 1)\n                retval(1) = arg.float_diag_matrix_value ().rcond ();\n            }\n          else\n            {\n              retval(0) = arg.diag_matrix_value ().determinant ().value ();\n              if (nargout > 1)\n                retval(1) = arg.diag_matrix_value ().rcond ();\n            }\n        }\n    }\n  else if (arg.is_perm_matrix ())\n    {\n      if (nargout <= 1)\n        retval.resize (1);\n\n      retval(0) = static_cast<double> (arg.perm_matrix_value ().determinant ());\n      if (nargout > 1)\n        retval(1) = 1.0;\n    }\n  else if (arg.is_single_type ())\n    {\n      if (arg.isreal ())\n        {\n          octave_idx_type info;\n          float rcond = 0.0;\n          // Always compute rcond, so we can detect singular matrices.\n          FloatMatrix m = arg.float_matrix_value ();\n\n          MAYBE_CAST (rep, octave_float_matrix);\n          MatrixType mtype = (rep ? rep -> matrix_type () : MatrixType ());\n          FloatDET det = m.determinant (mtype, info, rcond);\n          retval(0) = (info == -1 ? 0.0f : det.value ());\n          retval(1) = rcond;\n          if (rep)\n            rep->matrix_type (mtype);\n        }\n      else if (arg.iscomplex ())\n        {\n          octave_idx_type info;\n          float rcond = 0.0;\n          // Always compute rcond, so we can detect singular matrices.\n          FloatComplexMatrix m = arg.float_complex_matrix_value ();\n\n          MAYBE_CAST (rep, octave_float_complex_matrix);\n          MatrixType mtype = (rep ? rep -> matrix_type () : MatrixType ());\n          FloatComplexDET det = m.determinant (mtype, info, rcond);\n          retval(0) = (info == -1 ? FloatComplex (0.0) : det.value ());\n          retval(1) = rcond;\n          if (rep)\n            rep->matrix_type (mtype);\n        }\n    }\n  else\n    {\n      if (arg.isreal ())\n        {\n          octave_idx_type info;\n          double rcond = 0.0;\n          // Always compute rcond, so we can detect singular matrices.\n          if (arg.issparse ())\n            {\n              SparseMatrix m = arg.sparse_matrix_value ();\n\n              DET det = m.determinant (info, rcond);\n              retval(0) = (info == -1 ? 0.0 : det.value ());\n              retval(1) = rcond;\n            }\n          else\n            {\n              Matrix m = arg.matrix_value ();\n\n              MAYBE_CAST (rep, octave_matrix);\n              MatrixType mtype = (rep ? rep -> matrix_type ()\n                                  : MatrixType ());\n              DET det = m.determinant (mtype, info, rcond);\n              retval(0) = (info == -1 ? 0.0 : det.value ());\n              retval(1) = rcond;\n              if (rep)\n                rep->matrix_type (mtype);\n            }\n        }\n      else if (arg.iscomplex ())\n        {\n          octave_idx_type info;\n          double rcond = 0.0;\n          // Always compute rcond, so we can detect singular matrices.\n          if (arg.issparse ())\n            {\n              SparseComplexMatrix m = arg.sparse_complex_matrix_value ();\n\n              ComplexDET det = m.determinant (info, rcond);\n              retval(0) = (info == -1 ? Complex (0.0) : det.value ());\n              retval(1) = rcond;\n            }\n          else\n            {\n              ComplexMatrix m = arg.complex_matrix_value ();\n\n              MAYBE_CAST (rep, octave_complex_matrix);\n              MatrixType mtype = (rep ? rep -> matrix_type ()\n                                  : MatrixType ());\n              ComplexDET det = m.determinant (mtype, info, rcond);\n              retval(0) = (info == -1 ? Complex (0.0) : det.value ());\n              retval(1) = rcond;\n              if (rep)\n                rep->matrix_type (mtype);\n            }\n        }\n      else\n        err_wrong_type_arg (\"det\", arg);\n    }\n\n  return retval;\n}\n\n/*\n%!assert (det ([1, 2; 3, 4]), -2, 10*eps)\n%!assert (det (single ([1, 2; 3, 4])), single (-2), 10* eps (\"single\"))\n%!assert (det (eye (2000)), 1)\n%!error det ()\n%!error det (1, 2)\n%!error <must be a square matrix> det ([1, 2; 3, 4; 5, 6])\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/dmperm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"CSparse.h\"\n#include \"dRowVector.h\"\n#include \"dSparse.h\"\n#include \"oct-sparse.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (OCTAVE_ENABLE_64)\n#  define CXSPARSE_NAME(name) cs_dl ## name\n#else\n#  define CXSPARSE_NAME(name) cs_di ## name\n#endif\n\n#if defined (HAVE_CXSPARSE)\n\nstatic RowVector\nput_int (suitesparse_integer *p, octave_idx_type n)\n{\n  RowVector ret (n);\n  for (octave_idx_type i = 0; i < n; i++)\n    ret.xelem (i) = p[i] + 1;\n  return ret;\n}\n\nstatic octave_value_list\ndmperm_internal (bool rank, const octave_value arg, int nargout)\n{\n  octave_value_list retval;\n  octave_idx_type nr = arg.rows ();\n  octave_idx_type nc = arg.columns ();\n  SparseMatrix m;\n  SparseComplexMatrix cm;\n  CXSPARSE_NAME () csm;\n  csm.m = nr;\n  csm.n = nc;\n  csm.x = nullptr;\n  csm.nz = -1;\n\n  if (arg.isreal ())\n    {\n      m = arg.sparse_matrix_value ();\n      csm.nzmax = m.nnz ();\n      csm.p = to_suitesparse_intptr (m.xcidx ());\n      csm.i = to_suitesparse_intptr (m.xridx ());\n    }\n  else\n    {\n      cm = arg.sparse_complex_matrix_value ();\n      csm.nzmax = cm.nnz ();\n      csm.p = to_suitesparse_intptr (cm.xcidx ());\n      csm.i = to_suitesparse_intptr (cm.xridx ());\n    }\n\n  if (nargout <= 1 || rank)\n    {\n      suitesparse_integer *jmatch = CXSPARSE_NAME (_maxtrans) (&csm, 0);\n      if (rank)\n        {\n          octave_idx_type r = 0;\n          for (octave_idx_type i = 0; i < nc; i++)\n            if (jmatch[nr+i] >= 0)\n              r++;\n          retval(0) = static_cast<double> (r);\n        }\n      else\n        retval(0) = put_int (jmatch + nr, nc);\n      CXSPARSE_NAME (_free) (jmatch);\n    }\n  else\n    {\n      CXSPARSE_NAME (d) *dm = CXSPARSE_NAME(_dmperm) (&csm, 0);\n\n      retval = ovl (put_int (dm->p, nr), put_int (dm->q, nc),\n                    put_int (dm->r, dm->nb+1), put_int (dm->s, dm->nb+1),\n                    put_int (dm->cc, 5), put_int (dm->rr, 5));\n\n      CXSPARSE_NAME (_dfree) (dm);\n    }\n\n  return retval;\n}\n\n#endif\n\n// NOTE: the docstring for dmperm is adapted from the text found in the\n// file cs_dmperm.m that is distributed with the CSparse portion of the\n// SuiteSparse library, version 5.6.0.  CSparse is distributed under the\n// terms of the LGPL v2.1 or any later version.\n\nDEFUN (dmperm, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{p} =} dmperm (@var{A})\n@deftypefnx {} {[@var{p}, @var{q}, @var{r}, @var{s}, @var{cc}, @var{rr}] =} dmperm (@var{A})\n\n@cindex @nospell{Dulmage-Mendelsohn} decomposition\nPerform a @nospell{Dulmage-Mendelsohn} permutation of the sparse matrix\n@var{A}.\n\nWith a single output argument @code{dmperm}, return a maximum matching @var{p}\nsuch that @code{p(j) = i} if column @var{j} is matched to row @var{i}, or 0 if\ncolumn @var{j} is unmatched.  If @var{A} is square and full structural rank,\n@var{p} is a row permutation and @code{A(p,:)} has a zero-free diagonal.  The\nstructural rank of @var{A} is @code{sprank(A) = sum(p>0)}.\n\nCalled with two or more output arguments, return the\n@nospell{Dulmage-Mendelsohn} decomposition of @var{A}.  @var{p} and @var{q} are\npermutation vectors.  @var{cc} and @var{rr} are vectors of length 5.\n@code{c = A(p,q)} is split into a 4-by-4 set of coarse blocks:\n\n@example\n@group\n   A11 A12 A13 A14\n    0  0   A23 A24\n    0  0    0  A34\n    0  0    0  A44\n@end group\n@end example\n\n@noindent\nwhere @code{A12}, @code{A23}, and @code{A34} are square with zero-free\ndiagonals.  The columns of @code{A11} are the unmatched columns, and the rows\nof @code{A44} are the unmatched rows.  Any of these blocks can be empty.  In\nthe \"coarse\" decomposition, the (i,j)-th block is\n@code{C(rr(i):rr(i+1)-1,cc(j):cc(j+1)-1)}.  In terms of a linear system,\n@code{[A11 A12]} is the underdetermined part of the system (it is always\nrectangular and with more columns and rows, or 0-by-0), @code{A23} is the\nwell-determined part of the system (it is always square), and\n@code{[A34 ; A44]} is the over-determined part of the system (it is always\nrectangular with more rows than columns, or 0-by-0).\n\nThe structural rank of @var{A} is @code{sprank (A) = rr(4)-1}, which is an\nupper bound on the numerical rank of @var{A}.\n@code{sprank(A) = rank(full(sprand(A)))} with probability 1 in exact\narithmetic.\n\nThe @code{A23} submatrix is further subdivided into block upper triangular form\nvia the \"fine\" decomposition (the strongly-connected components of @code{A23}).\nIf @var{A} is square and structurally non-singular, @code{A23} is the entire\nmatrix.\n\n@code{C(r(i):r(i+1)-1,s(j):s(j+1)-1)} is the (i,j)-th block of the fine\ndecomposition.  The (1,1) block is the rectangular block @code{[A11 A12]},\nunless this block is 0-by-0.  The (b,b) block is the rectangular block\n@code{[A34 ; A44]}, unless this block is 0-by-0, where @code{b = length(r)-1}.\nAll other blocks of the form @code{C(r(i):r(i+1)-1,s(i):s(i+1)-1)} are diagonal\nblocks of @code{A23}, and are square with a zero-free diagonal.\n\nThe method used is described in: @nospell{A. Pothen & C.-J. Fan.}\n\"Computing the Block Triangular Form of a Sparse Matrix\".\n@cite{@nospell{ACM Trans.@: Math.@: Software}}, 16(4), @w{pp.@: 303}--324,\n1990.\n@seealso{colamd, ccolamd}\n@end deftypefn */)\n{\n#if defined (HAVE_CXSPARSE)\n\n  if (args.length () != 1)\n    print_usage ();\n\n  return dmperm_internal (false, args(0), nargout);\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"dmperm\", \"CXSparse\");\n\n#endif\n}\n\n/*\n%!testif HAVE_CXSPARSE\n%! n = 20;\n%! a = speye (n,n);\n%! a = a(randperm (n),:);\n%! assert (a(dmperm (a),:), speye (n));\n\n%!testif HAVE_CXSPARSE\n%! n = 20;\n%! d = 0.2;\n%! a = tril (sprandn (n,n,d), -1) + speye (n,n);\n%! a = a(randperm (n), randperm (n));\n%! [p,q,r,s] = dmperm (a);\n%! assert (tril (a(p,q), -1), sparse (n, n));\n*/\n\nDEFUN (sprank, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{p} =} sprank (@var{S})\n@cindex structural rank\n\nCalculate the structural rank of the sparse matrix @var{S}.\n\nNote that only the structure of the matrix is used in this calculation based\non a @nospell{Dulmage-Mendelsohn} permutation to block triangular form.  As\nsuch the numerical rank of the matrix @var{S} is bounded by\n@code{sprank (@var{S}) >= rank (@var{S})}.  Ignoring floating point errors\n@code{sprank (@var{S}) == rank (@var{S})}.\n@seealso{dmperm}\n@end deftypefn */)\n{\n#if defined (HAVE_CXSPARSE)\n\n  if (args.length () != 1)\n    print_usage ();\n\n  return dmperm_internal (true, args(0), nargout);\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"sprank\", \"CXSparse\");\n\n#endif\n}\n\n/*\n%!testif HAVE_CXSPARSE\n%! assert (sprank (speye (20)), 20);\n%!testif HAVE_CXSPARSE\n%! assert (sprank ([1,0,2,0;2,0,4,0]), 2);\n\n%!error sprank (1,2)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/dot.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"blas-proto.h\"\n#include \"mx-base.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"parse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// FIXME: input 'y' is no longer necessary (2/5/2022).\n//        At some point it would be better to change all occurrences of\n//        get_red_dims to eliminate this input parameter.\nstatic void\nget_red_dims (const dim_vector& x, const dim_vector& /* y */, int dim,\n              dim_vector& z, F77_INT& m, F77_INT& n, F77_INT& k)\n{\n  int nd = x.ndims ();\n  z = dim_vector::alloc (nd);\n  octave_idx_type tmp_m = 1;\n  octave_idx_type tmp_n = 1;\n  octave_idx_type tmp_k = 1;\n  for (int i = 0; i < nd; i++)\n    {\n      if (i < dim)\n        {\n          z(i) = x(i);\n          tmp_m *= x(i);\n        }\n      else if (i > dim)\n        {\n          z(i) = x(i);\n          tmp_n *= x(i);\n        }\n      else\n        {\n          z(i) = 1;\n          tmp_k = x(i);\n        }\n    }\n\n  m = to_f77_int (tmp_m);\n  n = to_f77_int (tmp_n);\n  k = to_f77_int (tmp_k);\n}\n\nDEFUN (dot, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{z} =} dot (@var{x}, @var{y})\n@deftypefnx {} {@var{z} =} dot (@var{x}, @var{y}, @var{dim})\nCompute the dot product of two vectors.\n\nIf @var{x} and @var{y} are matrices, calculate the dot products along the\nfirst non-singleton dimension.\n\nIf the optional argument @var{dim} is given, calculate the dot products\nalong this dimension.\n\nImplementation Note: This is equivalent to\n@code{sum (conj (@var{X}) .* @var{Y}, @var{dim})}, but avoids forming a\ntemporary array and is faster.  When @var{X} and @var{Y} are column vectors,\nthe result is equivalent to @code{@var{X}' * @var{Y}}.  Although, @code{dot}\nis defined for integer arrays, the output may differ from the expected result\ndue to the limited range of integer objects.\n@seealso{cross, divergence, tensorprod}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  octave_value retval;\n  octave_value argx = args(0);\n  octave_value argy = args(1);\n\n  if (! argx.isnumeric () || ! argy.isnumeric ())\n    error (\"dot: X and Y must be numeric\");\n\n  dim_vector dimx = argx.dims ();\n  dim_vector dimy = argy.dims ();\n  bool match = dimx == dimy;\n  if (! match && nargin == 2 && dimx.isvector () && dimy.isvector ())\n    {\n      // Change to column vectors.\n      dimx = dimx.redim (1);\n      argx = argx.reshape (dimx);\n      dimy = dimy.redim (1);\n      argy = argy.reshape (dimy);\n      match = dimx == dimy;\n    }\n\n  if (! match)\n    error (\"dot: sizes of X and Y must match\");\n\n  int dim;\n  if (nargin == 2)\n    dim = dimx.first_non_singleton ();\n  else\n    dim = args(2).int_value (true) - 1;\n\n  if (dim < 0)\n    error (\"dot: DIM must be a valid dimension\");\n\n  F77_INT m, n, k;\n  dim_vector dimz;\n  if (argx.iscomplex () || argy.iscomplex ())\n    {\n      if (argx.is_single_type () || argy.is_single_type ())\n        {\n          FloatComplexNDArray x = argx.float_complex_array_value ();\n          FloatComplexNDArray y = argy.float_complex_array_value ();\n          get_red_dims (dimx, dimy, dim, dimz, m, n, k);\n          FloatComplexNDArray z (dimz);\n\n          F77_XFCN (cdotc3, CDOTC3, (m, n, k,\n                                     F77_CONST_CMPLX_ARG (x.data ()), F77_CONST_CMPLX_ARG (y.data ()),\n                                     F77_CMPLX_ARG (z.rwdata ())));\n          retval = z;\n        }\n      else\n        {\n          ComplexNDArray x = argx.complex_array_value ();\n          ComplexNDArray y = argy.complex_array_value ();\n          get_red_dims (dimx, dimy, dim, dimz, m, n, k);\n          ComplexNDArray z (dimz);\n\n          F77_XFCN (zdotc3, ZDOTC3, (m, n, k,\n                                     F77_CONST_DBLE_CMPLX_ARG (x.data ()), F77_CONST_DBLE_CMPLX_ARG (y.data ()),\n                                     F77_DBLE_CMPLX_ARG (z.rwdata ())));\n          retval = z;\n        }\n    }\n  else if (argx.isfloat () && argy.isfloat ())\n    {\n      if (argx.is_single_type () || argy.is_single_type ())\n        {\n          FloatNDArray x = argx.float_array_value ();\n          FloatNDArray y = argy.float_array_value ();\n          get_red_dims (dimx, dimy, dim, dimz, m, n, k);\n          FloatNDArray z (dimz);\n\n          F77_XFCN (sdot3, SDOT3, (m, n, k, x.data (), y.data (),\n                                   z.rwdata ()));\n          retval = z;\n        }\n      else\n        {\n          NDArray x = argx.array_value ();\n          NDArray y = argy.array_value ();\n          get_red_dims (dimx, dimy, dim, dimz, m, n, k);\n          NDArray z (dimz);\n\n          F77_XFCN (ddot3, DDOT3, (m, n, k, x.data (), y.data (),\n                                   z.rwdata ()));\n          retval = z;\n        }\n    }\n  else\n    {\n      // Non-optimized evaluation.\n      // FIXME: This may *not* do what the user expects.\n      // It might be more useful to issue a warning, or even an error, instead\n      // of calculating possibly garbage results.\n      // Think of the dot product of two int8 vectors where the multiplications\n      // exceed intmax.\n      octave_value_list tmp (2);\n      tmp(0) = binary_op (octave_value::op_el_mul, argx, argy);\n      tmp(1) = dim + 1;\n\n      tmp = Fsum (tmp, 1);\n      if (! tmp.empty ())\n        retval = tmp(0);\n    }\n\n  return retval;\n}\n\n/*\n%!assert (dot ([1, 2], [2, 3]), 8)\n\n%!test\n%! x = [2, 1; 2, 1];\n%! y = [-0.5, 2; 0.5, -2];\n%! assert (dot (x, y), [0 0]);\n%! assert (dot (single (x), single (y)), single ([0 0]));\n\n%!test\n%! x = [1+i, 3-i; 1-i, 3-i];\n%! assert (dot (x, x), [4, 20]);\n%! assert (dot (single (x), single (x)), single ([4, 20]));\n\n%!test\n%! x = int8 ([1, 2]);\n%! y = int8 ([2, 3]);\n%! assert (dot (x, y), 8);\n\n%!test\n%! x = int8 ([1, 2; 3, 4]);\n%! y = int8 ([5, 6; 7, 8]);\n%! assert (dot (x, y), [26 44]);\n%! assert (dot (x, y, 2), [17; 53]);\n%! assert (dot (x, y, 3), [5 12; 21 32]);\n\n## This is, perhaps, surprising.  Integer maximums and saturation mechanics\n## prevent accurate value from being calculated.\n%!test\n%! x = int8 ([127]);\n%! assert (dot (x, x), 127);\n\n## Test input validation\n%!error dot ()\n%!error dot (1)\n%!error dot (1,2,3,4)\n%!error <X and Y must be numeric> dot ({1,2}, [3,4])\n%!error <X and Y must be numeric> dot ([1,2], {3,4})\n%!error <sizes of X and Y must match> dot ([1 2], [1 2 3])\n%!error <sizes of X and Y must match> dot ([1 2]', [1 2 3]')\n%!error <sizes of X and Y must match> dot (ones (2,2), ones (2,3))\n%!error <DIM must be a valid dimension> dot ([1 2], [1 2], 0)\n*/\n\ntemplate <typename T>\nstatic void\nblkmm_internal (const T& x, const T& y, T& z,\n                F77_INT m, F77_INT n, F77_INT k, F77_INT np);\n\ntemplate <>\nvoid\nblkmm_internal (const FloatComplexNDArray& x, const FloatComplexNDArray& y,\n                FloatComplexNDArray& z,\n                F77_INT m, F77_INT n, F77_INT k, F77_INT np)\n{\n  F77_XFCN (cmatm3, CMATM3, (m, n, k, np,\n                             F77_CONST_CMPLX_ARG (x.data ()),\n                             F77_CONST_CMPLX_ARG (y.data ()),\n                             F77_CMPLX_ARG (z.rwdata ())));\n}\n\ntemplate <>\nvoid\nblkmm_internal (const ComplexNDArray& x, const ComplexNDArray& y,\n                ComplexNDArray& z,\n                F77_INT m, F77_INT n, F77_INT k, F77_INT np)\n{\n  F77_XFCN (zmatm3, ZMATM3, (m, n, k, np,\n                             F77_CONST_DBLE_CMPLX_ARG (x.data ()),\n                             F77_CONST_DBLE_CMPLX_ARG (y.data ()),\n                             F77_DBLE_CMPLX_ARG (z.rwdata ())));\n}\n\ntemplate <>\nvoid\nblkmm_internal (const FloatNDArray& x, const FloatNDArray& y, FloatNDArray& z,\n                F77_INT m, F77_INT n, F77_INT k, F77_INT np)\n{\n  F77_XFCN (smatm3, SMATM3, (m, n, k, np,\n                             x.data (), y.data (),\n                             z.rwdata ()));\n}\n\ntemplate <>\nvoid\nblkmm_internal (const NDArray& x, const NDArray& y, NDArray& z,\n                F77_INT m, F77_INT n, F77_INT k, F77_INT np)\n{\n  F77_XFCN (dmatm3, DMATM3, (m, n, k, np,\n                             x.data (), y.data (),\n                             z.rwdata ()));\n}\n\nstatic void\nget_blkmm_dims (const dim_vector& dimx, const dim_vector& dimy,\n                F77_INT& m, F77_INT& n, F77_INT& k, F77_INT& np,\n                dim_vector& dimz)\n{\n  int nd = dimx.ndims ();\n\n  m = to_f77_int (dimx(0));\n  k = to_f77_int (dimx(1));\n  n = to_f77_int (dimy(1));\n\n  octave_idx_type tmp_np = 1;\n\n  bool match = ((dimy(0) == k) && (nd == dimy.ndims ()));\n\n  dimz = dim_vector::alloc (nd);\n\n  dimz(0) = m;\n  dimz(1) = n;\n  for (int i = 2; match && i < nd; i++)\n    {\n      match = (dimx(i) == dimy(i));\n      dimz(i) = dimx(i);\n      tmp_np *= dimz(i);\n    }\n\n  np = to_f77_int (tmp_np);\n\n  if (! match)\n    error (\"blkmm: A and B dimensions don't match: (%s) and (%s)\",\n           dimx.str ().c_str (), dimy.str ().c_str ());\n}\n\ntemplate <typename T>\nT\ndo_blkmm (const octave_value& xov, const octave_value& yov)\n{\n  const T x = octave_value_extract<T> (xov);\n  const T y = octave_value_extract<T> (yov);\n  F77_INT m, n, k, np;\n  dim_vector dimz;\n\n  get_blkmm_dims (x.dims (), y.dims (), m, n, k, np, dimz);\n\n  T z (dimz);\n\n  if (n != 0 && m != 0)\n    blkmm_internal<T> (x, y, z, m, n, k, np);\n\n  return z;\n}\n\nDEFUN (blkmm, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} blkmm (@var{A}, @var{B})\nCompute products of matrix blocks.\n\nThe blocks are given as 2-dimensional subarrays of the arrays @var{A},\n@var{B}.  The size of @var{A} must have the form @code{[m,k,@dots{}]} and\nsize of @var{B} must be @code{[k,n,@dots{}]}.  The result is then of size\n@code{[m,n,@dots{}]} and is computed as follows:\n\n@example\n@group\nfor i = 1:prod (size (@var{A})(3:end))\n  @var{C}(:,:,i) = @var{A}(:,:,i) * @var{B}(:,:,i)\nendfor\n@end group\n@end example\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value retval;\n\n  octave_value argx = args(0);\n  octave_value argy = args(1);\n\n  if (! argx.isnumeric () || ! argy.isnumeric ())\n    error (\"blkmm: A and B must be numeric\");\n\n  if (argx.iscomplex () || argy.iscomplex ())\n    {\n      if (argx.is_single_type () || argy.is_single_type ())\n        retval = do_blkmm<FloatComplexNDArray> (argx, argy);\n      else\n        retval = do_blkmm<ComplexNDArray> (argx, argy);\n    }\n  else\n    {\n      if (argx.is_single_type () || argy.is_single_type ())\n        retval = do_blkmm<FloatNDArray> (argx, argy);\n      else\n        retval = do_blkmm<NDArray> (argx, argy);\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! x(:,:,1) = [1 2; 3 4];\n%! x(:,:,2) = [1 1; 1 1];\n%! z(:,:,1) = [7 10; 15 22];\n%! z(:,:,2) = [2 2; 2 2];\n%! assert (blkmm (x,x), z);\n%! assert (blkmm (single (x), single (x)), single (z));\n%! assert (blkmm (x, single (x)), single (z));\n\n%!test\n%! x(:,:,1) = [1 2; 3 4];\n%! x(:,:,2) = [1i 1i; 1i 1i];\n%! z(:,:,1) = [7 10; 15 22];\n%! z(:,:,2) = [-2 -2; -2 -2];\n%! assert (blkmm (x,x), z);\n%! assert (blkmm (single (x), single (x)), single (z));\n%! assert (blkmm (x, single (x)), single (z));\n\n%!test <*54261>\n%! x = ones (0, 3, 3);\n%! y = ones (3, 5, 3);\n%! z = blkmm (x,y);\n%! assert (size (z), [0, 5, 3]);\n%! x = ones (1, 3, 3);\n%! y = ones (3, 0, 3);\n%! z = blkmm (x,y);\n%! assert (size (z), [1, 0, 3]);\n\n## Test input validation\n%!error blkmm ()\n%!error blkmm (1)\n%!error blkmm (1,2,3)\n%!error <A and B must be numeric> blkmm ({1,2}, [3,4])\n%!error <A and B must be numeric> blkmm ([3,4], {1,2})\n%!error <A and B dimensions don't match> blkmm (ones (2,2), ones (3,3))\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/eig.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\n#include \"EIG.h\"\n#include \"fEIG.h\"\n#include \"oct-string.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (eig, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{lambda} =} eig (@var{A})\n@deftypefnx {} {@var{lambda} =} eig (@var{A}, @var{B})\n@deftypefnx {} {[@var{V}, @var{lambda}] =} eig (@var{A})\n@deftypefnx {} {[@var{V}, @var{lambda}] =} eig (@var{A}, @var{B})\n@deftypefnx {} {[@var{V}, @var{lambda}, @var{W}] =} eig (@var{A})\n@deftypefnx {} {[@var{V}, @var{lambda}, @var{W}] =} eig (@var{A}, @var{B})\n@deftypefnx {} {[@dots{}] =} eig (@var{A}, @var{balanceOption})\n@deftypefnx {} {[@dots{}] =} eig (@var{A}, @var{B}, @var{algorithm})\n@deftypefnx {} {[@dots{}] =} eig (@dots{}, @var{eigvalOption})\nCompute the eigenvalues (@var{lambda}) and optionally the right eigenvectors\n(@var{V}) and the left eigenvectors (@var{W}) of a matrix or pair of matrices.\n\nThe flag @var{balanceOption} can be one of:\n\n@table @asis\n@item @qcode{\"balance\"} (default)\nPreliminary balancing is on.\n\n@item @qcode{\"nobalance\"}\nDisables preliminary balancing.\n@end table\n\nThe flag @var{eigvalOption} can be one of:\n\n@table @asis\n@item @qcode{\"matrix\"}\nReturn the eigenvalues in a diagonal matrix.  (default if 2 or 3 outputs\nare requested)\n\n@item @qcode{\"vector\"}\nReturn the eigenvalues in a column vector.  (default if only 1 output is\nrequested, e.g., @code{@var{lambda} = eig (@var{A})})\n@end table\n\nThe flag @var{algorithm} can be one of:\n\n@table @asis\n@item @qcode{\"chol\"}\nUse the Cholesky factorization of B.  (default if @var{A} is symmetric\n(Hermitian) and @var{B} is symmetric (Hermitian) positive definite)\n\n@item @qcode{\"qz\"}\nUse the QZ algorithm.  (used whenever @var{A} or @var{B} are not symmetric)\n@end table\n\n@multitable @columnfractions .44 .14 .14 .10\n@headitem A and B @tab no flag @tab chol @tab qz\n@item both are symmetric\n@tab @qcode{\"chol\"}\n@tab @qcode{\"chol\"}\n@tab @qcode{\"qz\"}\n@item at least one is not symmetric\n@tab @qcode{\"qz\"}\n@tab @qcode{\"qz\"}\n@tab @qcode{\"qz\"}\n@end multitable\n\nThe eigenvalues returned by @code{eig} are not ordered.\n@seealso{eigs, svd}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 4 || nargin == 0)\n    print_usage ();\n\n  octave_value_list retval;\n\n  octave_value arg_a, arg_b;\n\n  arg_a = args(0);\n\n  if (arg_a.isempty ())\n    return octave_value_list (2, Matrix ());\n\n  if (! arg_a.isfloat ())\n    err_wrong_type_arg (\"eig\", arg_a);\n\n  if (arg_a.rows () != arg_a.columns ())\n    err_square_matrix_required (\"eig\", \"A\");\n\n  // determine if it's AEP or GEP\n  bool AEPcase = nargin == 1 || args(1).is_string ();\n\n  if (! AEPcase)\n    {\n      arg_b = args(1);\n\n      if (arg_b.isempty ())\n        return octave_value_list (2, Matrix ());\n\n      if (! arg_b.isfloat ())\n        err_wrong_type_arg (\"eig\", arg_b);\n\n      if (arg_b.rows () != arg_b.columns ())\n        err_square_matrix_required (\"eig\", \"B\");\n    }\n\n  bool qz_flag = false;\n  bool chol_flag = false;\n  bool balance_flag = false;\n  bool no_balance_flag = false;\n  bool matrix_flag = false;\n  bool vector_flag = false;\n\n  for (int i = (AEPcase ? 1 : 2); i < args.length (); ++i)\n    {\n      if (! args(i).is_string ())\n        err_wrong_type_arg (\"eig\", args(i));\n\n      std::string arg_i = args(i).string_value ();\n      if (string::strcmpi (arg_i, \"qz\"))\n        qz_flag = true;\n      else if (string::strcmpi (arg_i, \"chol\"))\n        chol_flag = true;\n      else if (string::strcmpi (arg_i, \"balance\"))\n        balance_flag = true;\n      else if (string::strcmpi (arg_i, \"nobalance\"))\n        no_balance_flag = true;\n      else if (string::strcmpi (arg_i, \"matrix\"))\n        matrix_flag = true;\n      else if (string::strcmpi (arg_i, \"vector\"))\n        vector_flag = true;\n      else\n        error (R\"(eig: invalid option \"%s\")\", arg_i.c_str ());\n    }\n\n  if (balance_flag && no_balance_flag)\n    error (R\"(eig: \"balance\" and \"nobalance\" options are mutually exclusive)\");\n  if (vector_flag && matrix_flag)\n    error (R\"(eig: \"vector\" and \"matrix\" options are mutually exclusive)\");\n  if (qz_flag && chol_flag)\n    error (R\"(eig: \"qz\" and \"chol\" options are mutually exclusive)\");\n\n  if (AEPcase)\n    {\n      if (qz_flag)\n        error (R\"(eig: invalid \"qz\" option for algebraic eigenvalue problem)\");\n      if (chol_flag)\n        error (R\"(eig: invalid \"chol\" option for algebraic eigenvalue problem)\");\n    }\n  else\n    {\n      if (balance_flag)\n        error (R\"(eig: invalid \"balance\" option for generalized eigenvalue problem)\");\n      if (no_balance_flag)\n        error (R\"(eig: invalid \"nobalance\" option for generalized eigenvalue problem)\");\n    }\n\n  // Default is to balance\n  const bool balance = (no_balance_flag ? false : true);\n  const bool force_qz = qz_flag;\n\n\n  Matrix tmp_a, tmp_b;\n  ComplexMatrix ctmp_a, ctmp_b;\n  FloatMatrix ftmp_a, ftmp_b;\n  FloatComplexMatrix fctmp_a, fctmp_b;\n\n  if (arg_a.is_single_type ())\n    {\n      FloatEIG result;\n      if (AEPcase)\n        {\n          if (arg_a.isreal ())\n            {\n              ftmp_a = arg_a.float_matrix_value ();\n\n              result = FloatEIG (ftmp_a, nargout > 1, nargout > 2, balance);\n            }\n          else\n            {\n              fctmp_a = arg_a.float_complex_matrix_value ();\n\n              result = FloatEIG (fctmp_a, nargout > 1, nargout > 2, balance);\n            }\n        }\n      else\n        {\n          if (arg_a.isreal () && arg_b.isreal ())\n            {\n              ftmp_a = arg_a.float_matrix_value ();\n              ftmp_b = arg_b.float_matrix_value ();\n\n              result = FloatEIG (ftmp_a, ftmp_b, nargout > 1, nargout > 2,\n                                 force_qz);\n            }\n          else\n            {\n              fctmp_a = arg_a.float_complex_matrix_value ();\n              fctmp_b = arg_b.float_complex_matrix_value ();\n\n              result = FloatEIG (fctmp_a, fctmp_b, nargout > 1, nargout > 2,\n                                 force_qz);\n            }\n        }\n\n      if (nargout == 0 || nargout == 1)\n        {\n          if (matrix_flag)\n            retval = ovl (FloatComplexDiagMatrix (result.eigenvalues ()));\n          else\n            retval = ovl (result.eigenvalues ());\n        }\n      else if (nargout == 2)\n        {\n          if (vector_flag)\n            retval = ovl (result.right_eigenvectors (), result.eigenvalues ());\n          else\n            retval = ovl (result.right_eigenvectors (),\n                          FloatComplexDiagMatrix (result.eigenvalues ()));\n        }\n      else\n        {\n          if (vector_flag)\n            retval = ovl (result.right_eigenvectors (),\n                          result.eigenvalues (),\n                          result.left_eigenvectors ());\n          else\n            retval = ovl (result.right_eigenvectors (),\n                          FloatComplexDiagMatrix (result.eigenvalues ()),\n                          result.left_eigenvectors ());\n        }\n    }\n  else\n    {\n      EIG result;\n\n      if (AEPcase)\n        {\n          if (arg_a.isreal ())\n            {\n              tmp_a = arg_a.matrix_value ();\n\n              result = EIG (tmp_a, nargout > 1, nargout > 2, balance);\n            }\n          else\n            {\n              ctmp_a = arg_a.complex_matrix_value ();\n\n              result = EIG (ctmp_a, nargout > 1, nargout > 2, balance);\n            }\n        }\n      else\n        {\n          if (arg_a.isreal () && arg_b.isreal ())\n            {\n              tmp_a = arg_a.matrix_value ();\n              tmp_b = arg_b.matrix_value ();\n\n              result = EIG (tmp_a, tmp_b, nargout > 1, nargout > 2, force_qz);\n            }\n          else\n            {\n              ctmp_a = arg_a.complex_matrix_value ();\n              ctmp_b = arg_b.complex_matrix_value ();\n\n              result = EIG (ctmp_a, ctmp_b, nargout > 1, nargout > 2, force_qz);\n            }\n        }\n\n      if (nargout == 0 || nargout == 1)\n        {\n          if (matrix_flag)\n            retval = ovl (ComplexDiagMatrix (result.eigenvalues ()));\n          else\n            retval = ovl (result.eigenvalues ());\n        }\n      else if (nargout == 2)\n        {\n          if (vector_flag)\n            retval = ovl (result.right_eigenvectors (), result.eigenvalues ());\n          else\n            retval = ovl (result.right_eigenvectors (),\n                          ComplexDiagMatrix (result.eigenvalues ()));\n        }\n      else\n        {\n          if (vector_flag)\n            retval = ovl (result.right_eigenvectors (),\n                          result.eigenvalues (),\n                          result.left_eigenvectors ());\n          else\n            retval = ovl (result.right_eigenvectors (),\n                          ComplexDiagMatrix (result.eigenvalues ()),\n                          result.left_eigenvectors ());\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!assert (eig ([1, 2; 2, 1]), [-1; 3], sqrt (eps))\n\n%!test\n%! [v, d] = eig ([1, 2; 2, 1]);\n%! x = 1 / sqrt (2);\n%! assert (d, [-1, 0; 0, 3], sqrt (eps));\n%! assert (v, [-x, x; x, x], sqrt (eps));\n\n%!test\n%! [v, d, w] = eig ([1, 2; 2, 1]);\n%! x = 1 / sqrt (2);\n%! assert (w, [-x, x; x, x], sqrt (eps));\n\n%!test\n%! [v, d] = eig ([1, 2; 2, 1], \"balance\");\n%! x = 1 / sqrt (2);\n%! assert (d, [-1, 0; 0, 3], sqrt (eps));\n%! assert (v, [-x, x; x, x], sqrt (eps));\n\n%!test\n%! [v, d, w] = eig ([1, 2; 2, 1], \"balance\");\n%! x = 1 / sqrt (2);\n%! assert (w, [-x, x; x, x], sqrt (eps));\n\n%!assert (eig (single ([1, 2; 2, 1])), single ([-1; 3]), sqrt (eps (\"single\")))\n\n%!assert (eig (single ([1, 2; 2, 1]), \"balance\"),\n%!        single ([-1; 3]), sqrt (eps (\"single\")))\n\n%!test\n%! [v, d] = eig (single ([1, 2; 2, 1]));\n%! x = single (1 / sqrt (2));\n%! assert (d, single ([-1, 0; 0, 3]), sqrt (eps (\"single\")));\n%! assert (v, [-x, x; x, x], sqrt (eps (\"single\")));\n\n%!test\n%! [v, d, w] = eig (single ([1, 2; 2, 1]));\n%! x = single (1 / sqrt (2));\n%! assert (w, [-x, x; x, x], sqrt (eps (\"single\")));\n\n%!test\n%! [v, d] = eig (single ([1, 2; 2, 1]), \"balance\");\n%! x = single (1 / sqrt (2));\n%! assert (d, single ([-1, 0; 0, 3]), sqrt (eps (\"single\")));\n%! assert (v, [-x, x; x, x], sqrt (eps (\"single\")));\n\n%!test\n%! [v, d, w] = eig (single ([1, 2; 2, 1]), \"balance\");\n%! x = single (1 / sqrt (2));\n%! assert (w, [-x, x; x, x], sqrt (eps (\"single\")));\n\n\n## If (at least one of) the matrices are non-symmetric,\n## regardless the algorithm flag the qz algorithm should be used.\n## So the results without algorithm flag, with \"qz\" and with \"chol\"\n## should be the same.\n%!function nonsym_chol_2_output (A, B, res = sqrt (eps))\n%!  [v, d] = eig (A, B);\n%!  [v2, d2] = eig (A, B, \"qz\");\n%!  [v3, d3] = eig (A, B, \"chol\");\n%!  assert (A * v(:, 1), d(1, 1) * B * v(:, 1), res);\n%!  assert (A * v(:, 2), d(2, 2) * B * v(:, 2), res);\n%!  assert (v, v2);\n%!  assert (v, v3);\n%!  assert (d, d2);\n%!  assert (d, d3);\n%!endfunction\n\n%!test nonsym_chol_2_output ([1, 2; -1, 1], [3, 3; 1, 2])\n%!test nonsym_chol_2_output ([1+3i, 2+3i; 3-8i, 8+3i], [8+i, 3+i; 4-9i, 3+i])\n%!test nonsym_chol_2_output ([1, 2; 3, 8], [8, 3; 4, 3])\n\n%!test nonsym_chol_2_output (single ([1, 2; -1, 1]),\n%!                           single ([3, 3; 1, 2]), sqrt (eps (\"single\")))\n%!test nonsym_chol_2_output (single ([1+3i, 2+3i; 3-8i, 8+3i]),\n%!                           single ([8+i, 3+i; 4-9i, 3+i]),\n%!                           sqrt (eps (\"single\")))\n\n%!function nonsym_chol_3_output (A, B, res = sqrt (eps))\n%!  [v, d, w] = eig (A, B);\n%!  [v2, d2, w2] = eig (A, B, \"qz\");\n%!  [v3, d3, w3] = eig (A, B, \"chol\");\n%!  wt = w';\n%!  assert (wt(1, :)* A, d(1, 1) * wt(1, :) * B, res);\n%!  assert (wt(2, :)* A, d(2, 2) * wt(2, :) * B, res);\n%!  assert (v, v2);\n%!  assert (v, v3);\n%!  assert (d, d2);\n%!  assert (d, d3);\n%!  assert (w, w2);\n%!  assert (w, w3);\n%!endfunction\n\n%!test nonsym_chol_3_output ([1, 2; -1, 1], [3, 3; 1, 2])\n%!test nonsym_chol_3_output ([1+3i, 2+3i; 3-8i, 8+3i], [8+i, 3+i; 4-9i, 3+i])\n%!test nonsym_chol_3_output ([1, 2; 3, 8], [8, 3; 4, 3])\n\n%!test nonsym_chol_3_output (single ([1, 2; -1, 1]),\n%!                           single ([3, 3; 1, 2]), sqrt (eps (\"single\")))\n%!test nonsym_chol_3_output (single ([1+3i, 2+3i; 3-8i, 8+3i]),\n%!                           single ([8+i, 3+i; 4-9i, 3+i]),\n%!                           sqrt (eps (\"single\")))\n\n## If the matrices are symmetric,\n## then the chol method is default.\n## So the results without algorithm flag and with \"chol\" should be the same.\n%!function sym_chol_2_input (A, B, res = sqrt (eps))\n%!  [v, d] = eig (A, B);\n%!  [v2, d2] = eig (A, B, \"chol\");\n%!  assert (A * v(:, 1), d(1, 1) * B * v(:, 1), res);\n%!  assert (A * v(:, 2), d(2, 2) * B * v(:, 2), res);\n%!  assert (v, v2);\n%!  assert (d, d2);\n%!endfunction\n\n%!test sym_chol_2_input ([1, 2; 2, 1], [3, -2; -2, 3])\n%!test sym_chol_2_input ([1+3i, 2+i; 2-i, 1+3i], [5+9i, 2+i; 2-i, 5+9i])\n%!test sym_chol_2_input ([1, 1+i; 1-i, 1], [2, 0; 0, 2])\n\n%!test sym_chol_2_input (single ([1, 2; 2, 1]), single ([3, -2; -2, 3]),\n%!                       sqrt (eps (\"single\")))\n%!test sym_chol_2_input (single ([1+3i, 2+i; 2-i, 1+3i]),\n%!                       single ([5+9i, 2+i; 2-i, 5+9i]), sqrt (eps (\"single\")))\n%!test sym_chol_2_input (single ([1, 1+i; 1-i, 1]), single ([2, 0; 0, 2]),\n%!                       sqrt (eps (\"single\")))\n\n%!function sym_chol_3_input (A, B, res = sqrt (eps))\n%!  [v, d, w] = eig (A, B);\n%!  [v2, d2, w2] = eig (A, B, \"chol\");\n%!  wt = w';\n%!  assert (wt(1, :)* A, d(1, 1) * wt(1, :) * B, res);\n%!  assert (wt(2, :)* A, d(2, 2) * wt(2, :) * B, res);\n%!  assert (v, v2);\n%!  assert (d, d2);\n%!  assert (w, w2);\n%!endfunction\n\n%!test sym_chol_3_input ([1, 2; 2, 1], [3, -2; -2, 3])\n%!test sym_chol_3_input ([1+3i, 2+i; 2-i, 1+3i], [5+9i, 2+i; 2-i, 5+9i])\n%!test sym_chol_3_input ([1, 1+i; 1-i, 1], [2, 0; 0, 2])\n\n%!test sym_chol_3_input (single ([1, 2; 2, 1]), single ([3, -2; -2, 3]),\n%!                       sqrt (eps (\"single\")))\n%!test sym_chol_3_input (single ([1+3i, 2+i; 2-i, 1+3i]),\n%!                       single ([5+9i, 2+i; 2-i, 5+9i]), sqrt (eps (\"single\")))\n%!test sym_chol_3_input (single ([1, 1+i; 1-i, 1]), single ([2, 0; 0, 2]),\n%!                       sqrt (eps (\"single\")))\n\n## \"balance\" is always default\n## so the results with and without \"balance\" should be the same\n## while in this case \"nobalance\" should produce different result\n%!test\n%! A = [3 -2 -0.9 0; -2 4 1 -0; -0 0 -1 0; -0.5 -0.5 0.1 1];\n%! [V1, D1] = eig (A);\n%! [V2, D2] = eig (A, \"balance\");\n%! [V3, D3] = eig (A, \"nobalance\");\n%! assert (V1, V2);\n%! assert (D1, D2);\n%! assert (isequal (V2, V3), false);\n\n## Testing the flags in all combination.\n## If 2 flags are on, than the result should be the same regardless\n## of the flags order.\n## option1 represents the first order while option2 represents the other order.\n## d and d2 should be a diagonal matrix if \"matrix\" flag is on while\n## these should be column vectors if the \"vector\" flag is on.\n%!function test_eig_args (args, options1, options2, testd = @() true)\n%!  [v, d, w] = eig (args{:}, options1{:});\n%!  [v2, d2, w2] = eig (args{:}, options2{:});\n%!  assert (testd (d));\n%!  assert (testd (d2));\n%!  assert (v, v2);\n%!  assert (d, d2);\n%!  assert (w, w2);\n%!endfunction\n\n%!function qz_chol_with_shapes (A, B)\n%!  for shapes = struct (\"name\", {\"vector\", \"matrix\"},\n%!                       \"test\", {@isvector, @isdiag})\n%!    test_eig_args ({A, B}, {\"qz\", shapes.name},\n%!                   {shapes.name, \"qz\"}, shapes.test);\n%!    test_eig_args ({A, B}, {\"chol\", shapes.name},\n%!                   {shapes.name, \"chol\"}, shapes.test);\n%!  endfor\n%!endfunction\n\n%!function balance_nobalance_with_shapes (A)\n%!  for shapes = struct (\"name\", {\"vector\", \"matrix\"},\n%!                       \"test\", {@isvector, @isdiag})\n%!    test_eig_args ({A}, {\"balance\", shapes.name},\n%!                   {shapes.name, \"balance\"}, shapes.test);\n%!    test_eig_args ({A}, {\"nobalance\", shapes.name},\n%!                   {shapes.name, \"nobalance\"}, shapes.test);\n%!  endfor\n%!endfunction\n\n## Default return format:\n## diagonal matrix if 2 or 3 outputs are specified\n## column vector if 1 output is specified\n%!function test_shapes (args)\n%!  d = eig (args{:});\n%!  assert (isvector (d));\n%!  d2 = eig (args{:}, \"vector\");\n%!  assert (isvector (d2));\n%!  [v, d3] = eig (args{:});\n%!  assert (isdiag (d3));\n%!  d4 = eig (args{:}, \"matrix\");\n%!  assert (isdiag (d4));\n%!  [v, d5, w] = eig (args{:});\n%!  assert (isdiag (d5));\n%!  d6 = eig (args{:}, \"matrix\");\n%!  assert (isdiag (d6));\n%!  assert (d, d2);\n%!  assert (d3, d4);\n%!  assert (d5, d6);\n%!  assert (d, diag (d3));\n%!  assert (d, diag (d5));\n%!endfunction\n\n%!function shapes_AEP (A)\n%!  test_shapes({A});\n%!endfunction\n\n%!function shapes_GEP (A, B)\n%!  test_shapes({A, B});\n%!endfunction\n\n%!test balance_nobalance_with_shapes ([1, 2; 2, 1]);\n%!test balance_nobalance_with_shapes (single ([1, 2; 2, 1]));\n\n%!test shapes_AEP ([1, 2; 2, 1]);\n%!test shapes_AEP (single ([1, 2; 2, 1]));\n\n%!test qz_chol_with_shapes ([1, 1+i; 1-i, 1], [2, 0; 0, 2]);\n%!test qz_chol_with_shapes ([1, 2; 3, 8], [8, 3; 4, 3]);\n%!test qz_chol_with_shapes ([1, 2; -1, 1], [3, 3; 1, 2]);\n\n%!test qz_chol_with_shapes (single ([1, 1+i; 1-i, 1]), single ([2, 0; 0, 2]));\n%!test qz_chol_with_shapes (single ([1, 2; 3, 8]), single ([8, 3; 4, 3]));\n%!test qz_chol_with_shapes (single ([1, 2; -1, 1]), single ([3, 3; 1, 2]));\n\n%!test shapes_GEP ([1, 1+i; 1-i, 1], [2, 0; 0, 2]);\n%!test shapes_GEP ([1, 2; 3, 8], [8, 3; 4, 3]);\n%!test shapes_GEP ([1, 2; -1, 1], [3, 3; 1, 2]);\n\n%!test shapes_GEP (single ([1, 1+i; 1-i, 1]), single ([2, 0; 0, 2]));\n%!test shapes_GEP (single ([1, 2; 3, 8]), single ([8, 3; 4, 3]));\n%!test shapes_GEP (single ([1, 2; -1, 1]), single ([3, 3; 1, 2]));\n\n## Check if correct default method is used for symmetric input\n%!function chol_qz_accuracy (A, B, is_qz_accurate, is_chol_accurate)\n%!  [V1, D1] = eig (A, B, 'qz');\n%!  [V2, D2] = eig (A, B); #default is chol\n%!  assert (isequal (A*V1, A*V1*D1), is_qz_accurate);\n%!  assert (isequal (A*V2, A*V2*D2), is_chol_accurate);\n%!endfunction\n%!test\n%! minij_100 = gallery ('minij', 100);\n%! chol_qz_accuracy (minij_100, minij_100, false, true);\n%! moler_100 = gallery ('moler', 100);\n%! chol_qz_accuracy (moler_100, moler_100, false, true);\n%! A = diag([1e-16, 1e-15]);\n%! chol_qz_accuracy (A, A, true, false);\n\n%!error eig ()\n%!error eig (false)\n%!error eig ([1, 2; 3, 4], [4, 3; 2, 1], 1)\n\n%!error <EIG requires same size matrices>\n%!  eig ([1, 2; 3, 4], 2)\n%!error <must be a square matrix>\n%! eig ([1, 2; 3, 4; 5, 6])\n%!error <wrong type argument>\n%!  eig (\"abcd\")\n%!error <invalid option \"abcd\">\n%!  eig ([1 2 ; 2 3], \"abcd\")\n%!error <invalid \"chol\" option for algebraic eigenvalue problem>\n%!  eig ([1 2 ; 2 3], \"chol\")\n%!error <invalid \"qz\" option for algebraic eigenvalue problem>\n%!  eig ([1 2 ; 2 3], \"qz\")\n%!error <wrong type argument>\n%!  eig (false, [1 2 ; 2 3])\n%!error <invalid option \"abcd\">\n%!  eig ([1 2 ; 2 3], [1 2 ; 2 3], \"abcd\")\n%!error <invalid \"qz\" option for algebraic eigenvalue problem>\n%!  eig ([1 2 ; 2 3], \"balance\", \"qz\")\n%!error <invalid option \"abcd\">\n%!  eig ([1 2 ; 2 3], [1 2 ; 2 3], \"vector\", \"abcd\")\n%!error <invalid option \"abcd\">\n%!  eig ([1 2 ; 2 3], \"balance\", \"matrix\", \"abcd\")\n%!error <\"balance\" and \"nobalance\" options are mutually exclusive>\n%!  eig ([1 2 ; 2 3], \"balance\", \"nobalance\")\n%!error <\"balance\" and \"nobalance\" options are mutually exclusive>\n%!  eig ([1 2 ; 2 3], \"nobalance\", \"balance\")\n%!error <\"vector\" and \"matrix\" options are mutually exclusive>\n%!  eig ([1 2 ; 2 3], \"matrix\", \"vector\")\n%!error <\"vector\" and \"matrix\" options are mutually exclusive>\n%!  eig ([1 2 ; 2 3], \"vector\", \"matrix\")\n%!error <\"vector\" and \"matrix\" options are mutually exclusive>\n%!  eig ([1 2 ; 2 3], [1 2 ; 2 3], \"matrix\", \"vector\")\n%!error <\"vector\" and \"matrix\" options are mutually exclusive>\n%!  eig ([1 2 ; 2 3], [1 2 ; 2 3], \"vector\", \"matrix\")\n%!error <wrong type argument>\n%!  eig ([1 2 ; 2 3], [1 2 ; 2 3], false)\n%!error <wrong type argument>\n%!  eig ([1 2 ; 2 3], [1 2 ; 2 3], [1 2 ; 2 3])\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/ellipj.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"oct-specfun.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (ellipj, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{sn}, @var{cn}, @var{dn}, @var{err}] =} ellipj (@var{u}, @var{m})\n@deftypefnx {} {[@var{sn}, @var{cn}, @var{dn}, @var{err}] =} ellipj (@var{u}, @var{m}, @var{tol})\nCompute the Jacobi elliptic functions @var{sn}, @var{cn}, and @var{dn}\nof complex argument @var{u} and real parameter @var{m}.\n\nIf @var{m} is a scalar, the results are the same size as @var{u}.\nIf @var{u} is a scalar, the results are the same size as @var{m}.\nIf @var{u} is a column vector and @var{m} is a row vector, the\nresults are matrices with @code{length (@var{u})} rows and\n@code{length (@var{m})} columns.  Otherwise, @var{u} and\n@var{m} must conform in size and the results will be the same size as the\ninputs.\n\nThe value of @var{u} may be complex.\nThe value of @var{m} must be 0 @leq{} @var{m} @leq{} 1.\n\nThe optional input @var{tol} is currently ignored (@sc{matlab} uses this to\nallow faster, less accurate approximation).\n\nIf requested, @var{err} contains the following status information\nand is the same size as the result.\n\n@enumerate 0\n@item\nNormal return.\n\n@item\nError---no computation, algorithm termination condition not met,\nreturn @code{NaN}.\n@end enumerate\n\nReference: @nospell{Milton Abramowitz} and @nospell{Irene A Stegun},\n@cite{Handbook of Mathematical Functions}, Chapter 16 (Sections 16.4, 16.13,\nand 16.15), Dover, 1965.\n\n@seealso{ellipke}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  octave_value u_arg = args(0);\n  octave_value m_arg = args(1);\n\n  if (m_arg.is_scalar_type ())\n    {\n      double m = args(1).xdouble_value (\"ellipj: M must be a scalar or matrix\");\n\n      if (u_arg.is_scalar_type ())\n        {\n          if (u_arg.isreal ())\n            {\n              // u real, m scalar\n              double u = args(0).xdouble_value (\"ellipj: U must be a scalar or matrix\");\n\n              double sn, cn, dn;\n              double err = 0;\n\n              math::ellipj (u, m, sn, cn, dn, err);\n\n              return ovl (sn, cn, dn, err);\n            }\n          else\n            {\n              // u complex, m scalar\n              Complex u = u_arg.xcomplex_value (\"ellipj: U must be a scalar or matrix\");\n\n              Complex sn, cn, dn;\n              double err = 0;\n\n              math::ellipj (u, m, sn, cn, dn, err);\n\n              return ovl (sn, cn, dn, err);\n            }\n        }\n      else\n        {\n          // u is matrix, m is scalar\n          ComplexNDArray u = u_arg.xcomplex_array_value (\"ellipj: U must be a scalar or matrix\");\n\n          const dim_vector& sz_u = u.dims ();\n\n          ComplexNDArray sn (sz_u), cn (sz_u), dn (sz_u);\n          NDArray err (sz_u);\n\n          const Complex *pu = u.data ();\n          Complex *psn = sn.rwdata ();\n          Complex *pcn = cn.rwdata ();\n          Complex *pdn = dn.rwdata ();\n          double *perr = err.rwdata ();\n          octave_idx_type nel = u.numel ();\n\n          for (octave_idx_type i = 0; i < nel; i++)\n            math::ellipj (pu[i], m, psn[i], pcn[i], pdn[i], perr[i]);\n\n          return ovl (sn, cn, dn, err);\n        }\n    }\n  else\n    {\n      NDArray m = args(1).xarray_value (\"ellipj: M must be a scalar or matrix\");\n\n      const dim_vector& sz_m = m.dims ();\n\n      if (u_arg.is_scalar_type ())\n        {\n          // u is scalar, m is array\n          if (u_arg.isreal ())\n            {\n              // u is real scalar, m is array\n              double u = u_arg.xdouble_value (\"ellipj: U must be a scalar or matrix\");\n\n              NDArray sn (sz_m), cn (sz_m), dn (sz_m);\n              NDArray err (sz_m);\n\n              const double *pm = m.data ();\n              double *psn = sn.rwdata ();\n              double *pcn = cn.rwdata ();\n              double *pdn = dn.rwdata ();\n              double *perr = err.rwdata ();\n              octave_idx_type nel = m.numel ();\n\n              for (octave_idx_type i = 0; i < nel; i++)\n                math::ellipj (u, pm[i], psn[i], pcn[i], pdn[i], perr[i]);\n\n              return ovl (sn, cn, dn, err);\n            }\n          else\n            {\n              // u is complex scalar, m is array\n              Complex u = u_arg.xcomplex_value (\"ellipj: U must be a scalar or matrix\");\n\n              ComplexNDArray sn (sz_m), cn (sz_m), dn (sz_m);\n              NDArray err (sz_m);\n\n              const double *pm = m.data ();\n              Complex *psn = sn.rwdata ();\n              Complex *pcn = cn.rwdata ();\n              Complex *pdn = dn.rwdata ();\n              double *perr = err.rwdata ();\n              octave_idx_type nel = m.numel ();\n\n              for (octave_idx_type i = 0; i < nel; i++)\n                math::ellipj (u, pm[i], psn[i], pcn[i], pdn[i], perr[i]);\n\n              return ovl (sn, cn, dn, err);\n            }\n        }\n      else\n        {\n          // u is array, m is array\n          if (u_arg.isreal ())\n            {\n              // u is real array, m is array\n              NDArray u = u_arg.xarray_value (\"ellipj: U must be a scalar or matrix\");\n\n              const dim_vector& sz_u = u.dims ();\n\n              if (sz_u.ndims () == 2 && sz_m.ndims () == 2\n                  && sz_u(1) == 1 && sz_m(0) == 1)\n                {\n                  // u is real column vector, m is row vector\n                  octave_idx_type ur = sz_u(0);\n                  octave_idx_type mc = sz_m(1);\n                  dim_vector sz_out (ur, mc);\n\n                  NDArray sn (sz_out), cn (sz_out), dn (sz_out);\n                  NDArray err (sz_out);\n\n                  const double *pu = u.data ();\n                  const double *pm = m.data ();\n\n                  for (octave_idx_type j = 0; j < mc; j++)\n                    for (octave_idx_type i = 0; i < ur; i++)\n                      math::ellipj (pu[i], pm[j], sn(i, j), cn(i, j), dn(i, j), err(i, j));\n\n                  return ovl (sn, cn, dn, err);\n                }\n              else if (sz_m == sz_u)\n                {\n                  NDArray sn (sz_m), cn (sz_m), dn (sz_m);\n                  NDArray err (sz_m);\n\n                  const double *pu = u.data ();\n                  const double *pm = m.data ();\n                  double *psn = sn.rwdata ();\n                  double *pcn = cn.rwdata ();\n                  double *pdn = dn.rwdata ();\n                  double *perr = err.rwdata ();\n                  octave_idx_type nel = m.numel ();\n\n                  for (octave_idx_type i = 0; i < nel; i++)\n                    math::ellipj (pu[i], pm[i], psn[i], pcn[i], pdn[i], perr[i]);\n\n                  return ovl (sn, cn, dn, err);\n                }\n              else\n                error (\"ellipj: Invalid size combination for U and M\");\n            }\n          else\n            {\n              // u is complex array, m is array\n              ComplexNDArray u = u_arg.xcomplex_array_value (\"ellipj: U must be a scalar or matrix\");\n\n              const dim_vector& sz_u = u.dims ();\n\n              if (sz_u.ndims () == 2 && sz_m.ndims () == 2\n                  && sz_u(1) == 1 && sz_m(0) == 1)\n                {\n                  // u is complex column vector, m is row vector\n                  octave_idx_type ur = sz_u(0);\n                  octave_idx_type mc = sz_m(1);\n                  dim_vector sz_out (ur, mc);\n\n                  ComplexNDArray sn (sz_out), cn (sz_out), dn (sz_out);\n                  NDArray err (sz_out);\n\n                  const Complex *pu = u.data ();\n                  const double  *pm = m.data ();\n\n                  for (octave_idx_type j = 0; j < mc; j++)\n                    for (octave_idx_type i = 0; i < ur; i++)\n                      math::ellipj (pu[i], pm[j], sn(i, j), cn(i, j), dn(i, j), err(i, j));\n\n                  return ovl (sn, cn, dn, err);\n                }\n              else if (sz_m == sz_u)\n                {\n                  ComplexNDArray sn (sz_m), cn (sz_m), dn (sz_m);\n                  NDArray err (sz_m);\n\n                  const Complex *pu = u.data ();\n                  const double  *pm = m.data ();\n                  Complex *psn = sn.rwdata ();\n                  Complex *pcn = cn.rwdata ();\n                  Complex *pdn = dn.rwdata ();\n                  double *perr = err.rwdata ();\n                  octave_idx_type nel = m.numel ();\n\n                  for (octave_idx_type i = 0; i < nel; i++)\n                    math::ellipj (pu[i], pm[i], psn[i], pcn[i], pdn[i], perr[i]);\n\n                  return ovl (sn, cn, dn, err);\n                }\n              else\n                error (\"ellipj: Invalid size combination for U and M\");\n            }\n        }\n    }  // m matrix\n\n  return ovl ();\n}\n\n/*\n## demos taken from inst/ellipj.m\n\n%!demo\n%! N = 150;\n%! # m = [1-logspace(0,log(eps),N-1), 1]; # m near 1\n%! # m = [0, logspace(log(eps),0,N-1)];   # m near 0\n%!   m = linspace (0,1,N);                # m equally spaced\n%! u = linspace (-20, 20, N);\n%! M = ones (length (u), 1) * m;\n%! U = u' * ones (1, length (m));\n%! [sn, cn, dn] = ellipj (U,M);\n%!\n%! ## Plotting\n%! data = {sn,cn,dn};\n%! dname = {\"sn\",\"cn\",\"dn\"};\n%! for i=1:3\n%!   subplot (1,3,i);\n%!   data{i}(data{i} > 1) = 1;\n%!   data{i}(data{i} < -1) = -1;\n%!   image (m,u,32*data{i}+32);\n%!   title (dname{i});\n%! endfor\n%! colormap (hot (64));\n\n%!demo\n%! N = 200;\n%! # m = [1-logspace(0,log(eps),N-1), 1]; # m near 1\n%! # m = [0, logspace(log(eps),0,N-1)];   # m near 0\n%!   m = linspace (0,1,N);                # m equally spaced\n%! u = linspace (0,20,5);\n%! M = ones (length (u), 1) * m;\n%! U = u' * ones (1, length (m));\n%! [sn, cn, dn] = ellipj (U,M);\n%!\n%! ## Plotting\n%! data = {sn,cn,dn};\n%! dname = {\"sn\",\"cn\",\"dn\"};\n%! for i=1:3\n%!   subplot (1,3,i);\n%!   plot (m, data{i});\n%!   title (dname{i});\n%!   grid on;\n%! endfor\n*/\n\n/*\n## tests taken from inst/test_sncndn.m\n\n%!test\n%! k = (tan (pi/8))^2;  m = k*k;\n%! SN = [\n%! -1. + I * 0. ,  -0.8392965923 + 0. * I\n%! -1. + I * 0.2 ,  -0.8559363407 + 0.108250955 * I\n%! -1. + I * 0.4 ,  -0.906529758 + 0.2204040232 * I\n%! -1. + I * 0.6 ,  -0.9931306727 + 0.3403783409 * I\n%! -1. + I * 0.8 ,  -1.119268095 + 0.4720784944 * I\n%! -1. + I * 1. ,  -1.29010951 + 0.6192468708 * I\n%! -1. + I * 1.2 ,  -1.512691987 + 0.7850890595 * I\n%! -1. + I * 1.4 ,  -1.796200374 + 0.9714821804 * I\n%! -1. + I * 1.6 ,  -2.152201882 + 1.177446413 * I\n%! -1. + I * 1.8 ,  -2.594547417 + 1.396378892 * I\n%! -1. + I * 2. ,  -3.138145339 + 1.611394819 * I\n%! -0.8 + I * 0. ,  -0.7158157937 + 0. * I\n%! -0.8 + I * 0.2 ,  -0.7301746722 + 0.1394690862 * I\n%! -0.8 + I * 0.4 ,  -0.7738940898 + 0.2841710966 * I\n%! -0.8 + I * 0.6 ,  -0.8489542135 + 0.4394411376 * I\n%! -0.8 + I * 0.8 ,  -0.9588386397 + 0.6107824358 * I\n%! -0.8 + I * 1. ,  -1.108848724 + 0.8038415767 * I\n%! -0.8 + I * 1.2 ,  -1.306629972 + 1.024193359 * I\n%! -0.8 + I * 1.4 ,  -1.563010199 + 1.276740951 * I\n%! -0.8 + I * 1.6 ,  -1.893274688 + 1.564345558 * I\n%! -0.8 + I * 1.8 ,  -2.318944084 + 1.88491973 * I\n%! -0.8 + I * 2. ,  -2.869716809 + 2.225506523 * I\n%! -0.6 + I * 0. ,  -0.5638287208 + 0. * I\n%! -0.6 + I * 0.2 ,  -0.5752723012 + 0.1654722474 * I\n%! -0.6 + I * 0.4 ,  -0.610164314 + 0.3374004736 * I\n%! -0.6 + I * 0.6 ,  -0.6702507087 + 0.5224614298 * I\n%! -0.6 + I * 0.8 ,  -0.7586657365 + 0.7277663879 * I\n%! -0.6 + I * 1. ,  -0.8803349115 + 0.9610513652 * I\n%! -0.6 + I * 1.2 ,  -1.042696526 + 1.230800819 * I\n%! -0.6 + I * 1.4 ,  -1.256964505 + 1.546195843 * I\n%! -0.6 + I * 1.6 ,  -1.540333527 + 1.916612621 * I\n%! -0.6 + I * 1.8 ,  -1.919816065 + 2.349972151 * I\n%! -0.6 + I * 2. ,  -2.438761841 + 2.848129496 * I\n%! -0.4 + I * 0. ,  -0.3891382858 + 0. * I\n%! -0.4 + I * 0.2 ,  -0.3971152026 + 0.1850563793 * I\n%! -0.4 + I * 0.4 ,  -0.4214662882 + 0.3775700801 * I\n%! -0.4 + I * 0.6 ,  -0.4635087491 + 0.5853434119 * I\n%! -0.4 + I * 0.8 ,  -0.5256432877 + 0.8168992398 * I\n%! -0.4 + I * 1. ,  -0.611733177 + 1.081923504 * I\n%! -0.4 + I * 1.2 ,  -0.7278102331 + 1.391822501 * I\n%! -0.4 + I * 1.4 ,  -0.8833807998 + 1.760456461 * I\n%! -0.4 + I * 1.6 ,  -1.093891878 + 2.205107766 * I\n%! -0.4 + I * 1.8 ,  -1.385545188 + 2.747638761 * I\n%! -0.4 + I * 2. ,  -1.805081271 + 3.41525351 * I\n%! -0.2 + I * 0. ,  -0.1986311721 + 0. * I\n%! -0.2 + I * 0.2 ,  -0.2027299916 + 0.1972398665 * I\n%! -0.2 + I * 0.4 ,  -0.2152524522 + 0.402598347 * I\n%! -0.2 + I * 0.6 ,  -0.2369100139 + 0.6246336356 * I\n%! -0.2 + I * 0.8 ,  -0.2690115146 + 0.8728455227 * I\n%! -0.2 + I * 1. ,  -0.3136938773 + 1.158323088 * I\n%! -0.2 + I * 1.2 ,  -0.3743615191 + 1.494672508 * I\n%! -0.2 + I * 1.4 ,  -0.4565255082 + 1.899466033 * I\n%! -0.2 + I * 1.6 ,  -0.5694611346 + 2.39667232 * I\n%! -0.2 + I * 1.8 ,  -0.7296612675 + 3.020990664 * I\n%! -0.2 + I * 2. ,  -0.9685726188 + 3.826022536 * I\n%! 0. + I * 0. ,  0. + 0. * I\n%! 0. + I * 0.2 ,  0. + 0.201376364 * I\n%! 0. + I * 0.4 ,  0. + 0.4111029248 * I\n%! 0. + I * 0.6 ,  0. + 0.6380048435 * I\n%! 0. + I * 0.8 ,  0. + 0.8919321473 * I\n%! 0. + I * 1. ,  0. + 1.184486615 * I\n%! 0. + I * 1.2 ,  0. + 1.530096023 * I\n%! 0. + I * 1.4 ,  0. + 1.947754612 * I\n%! 0. + I * 1.6 ,  0. + 2.464074356 * I\n%! 0. + I * 1.8 ,  0. + 3.119049475 * I\n%! 0. + I * 2. ,  0. + 3.97786237 * I\n%! 0.2 + I * 0. ,  0.1986311721 + 0. * I\n%! 0.2 + I * 0.2 ,  0.2027299916 + 0.1972398665 * I\n%! 0.2 + I * 0.4 ,  0.2152524522 + 0.402598347 * I\n%! 0.2 + I * 0.6 ,  0.2369100139 + 0.6246336356 * I\n%! 0.2 + I * 0.8 ,  0.2690115146 + 0.8728455227 * I\n%! 0.2 + I * 1. ,  0.3136938773 + 1.158323088 * I\n%! 0.2 + I * 1.2 ,  0.3743615191 + 1.494672508 * I\n%! 0.2 + I * 1.4 ,  0.4565255082 + 1.899466033 * I\n%! 0.2 + I * 1.6 ,  0.5694611346 + 2.39667232 * I\n%! 0.2 + I * 1.8 ,  0.7296612675 + 3.020990664 * I\n%! 0.2 + I * 2. ,  0.9685726188 + 3.826022536 * I\n%! 0.4 + I * 0. ,  0.3891382858 + 0. * I\n%! 0.4 + I * 0.2 ,  0.3971152026 + 0.1850563793 * I\n%! 0.4 + I * 0.4 ,  0.4214662882 + 0.3775700801 * I\n%! 0.4 + I * 0.6 ,  0.4635087491 + 0.5853434119 * I\n%! 0.4 + I * 0.8 ,  0.5256432877 + 0.8168992398 * I\n%! 0.4 + I * 1. ,  0.611733177 + 1.081923504 * I\n%! 0.4 + I * 1.2 ,  0.7278102331 + 1.391822501 * I\n%! 0.4 + I * 1.4 ,  0.8833807998 + 1.760456461 * I\n%! 0.4 + I * 1.6 ,  1.093891878 + 2.205107766 * I\n%! 0.4 + I * 1.8 ,  1.385545188 + 2.747638761 * I\n%! 0.4 + I * 2. ,  1.805081271 + 3.41525351 * I\n%! 0.6 + I * 0. ,  0.5638287208 + 0. * I\n%! 0.6 + I * 0.2 ,  0.5752723012 + 0.1654722474 * I\n%! 0.6 + I * 0.4 ,  0.610164314 + 0.3374004736 * I\n%! 0.6 + I * 0.6 ,  0.6702507087 + 0.5224614298 * I\n%! 0.6 + I * 0.8 ,  0.7586657365 + 0.7277663879 * I\n%! 0.6 + I * 1. ,  0.8803349115 + 0.9610513652 * I\n%! 0.6 + I * 1.2 ,  1.042696526 + 1.230800819 * I\n%! 0.6 + I * 1.4 ,  1.256964505 + 1.546195843 * I\n%! 0.6 + I * 1.6 ,  1.540333527 + 1.916612621 * I\n%! 0.6 + I * 1.8 ,  1.919816065 + 2.349972151 * I\n%! 0.6 + I * 2. ,  2.438761841 + 2.848129496 * I\n%! 0.8 + I * 0. ,  0.7158157937 + 0. * I\n%! 0.8 + I * 0.2 ,  0.7301746722 + 0.1394690862 * I\n%! 0.8 + I * 0.4 ,  0.7738940898 + 0.2841710966 * I\n%! 0.8 + I * 0.6 ,  0.8489542135 + 0.4394411376 * I\n%! 0.8 + I * 0.8 ,  0.9588386397 + 0.6107824358 * I\n%! 0.8 + I * 1. ,  1.108848724 + 0.8038415767 * I\n%! 0.8 + I * 1.2 ,  1.306629972 + 1.024193359 * I\n%! 0.8 + I * 1.4 ,  1.563010199 + 1.276740951 * I\n%! 0.8 + I * 1.6 ,  1.893274688 + 1.564345558 * I\n%! 0.8 + I * 1.8 ,  2.318944084 + 1.88491973 * I\n%! 0.8 + I * 2. ,  2.869716809 + 2.225506523 * I\n%! 1. + I * 0. ,  0.8392965923 + 0. * I\n%! 1. + I * 0.2 ,  0.8559363407 + 0.108250955 * I\n%! 1. + I * 0.4 ,  0.906529758 + 0.2204040232 * I\n%! 1. + I * 0.6 ,  0.9931306727 + 0.3403783409 * I\n%! 1. + I * 0.8 ,  1.119268095 + 0.4720784944 * I\n%! 1. + I * 1. ,  1.29010951 + 0.6192468708 * I\n%! 1. + I * 1.2 ,  1.512691987 + 0.7850890595 * I\n%! 1. + I * 1.4 ,  1.796200374 + 0.9714821804 * I\n%! 1. + I * 1.6 ,  2.152201882 + 1.177446413 * I\n%! 1. + I * 1.8 ,  2.594547417 + 1.396378892 * I\n%! 1. + I * 2. ,  3.138145339 + 1.611394819 * I\n%! ];\n%! CN = [\n%! -1. + I * 0. , 0.5436738271 + 0. * I\n%! -1. + I * 0.2 , 0.5541219664 + 0.1672121517 * I\n%! -1. + I * 0.4 , 0.5857703552 + 0.3410940893 * I\n%! -1. + I * 0.6 , 0.6395034233 + 0.5285979063 * I\n%! -1. + I * 0.8 , 0.716688504 + 0.7372552987 * I\n%! -1. + I * 1. , 0.8189576795 + 0.9755037374 * I\n%! -1. + I * 1.2 , 0.9477661951 + 1.253049471 * I\n%! -1. + I * 1.4 , 1.103540657 + 1.581252712 * I\n%! -1. + I * 1.6 , 1.284098214 + 1.973449038 * I\n%! -1. + I * 1.8 , 1.481835651 + 2.4449211 * I\n%! -1. + I * 2. , 1.679032464 + 3.011729224 * I\n%! -0.8 + I * 0. , 0.6982891589 + 0. * I\n%! -0.8 + I * 0.2 , 0.71187169 + 0.1430549855 * I\n%! -0.8 + I * 0.4 , 0.7530744458 + 0.2920273465 * I\n%! -0.8 + I * 0.6 , 0.8232501212 + 0.4531616768 * I\n%! -0.8 + I * 0.8 , 0.9245978896 + 0.6334016187 * I\n%! -0.8 + I * 1. , 1.060030206 + 0.8408616109 * I\n%! -0.8 + I * 1.2 , 1.232861756 + 1.085475913 * I\n%! -0.8 + I * 1.4 , 1.446126965 + 1.379933558 * I\n%! -0.8 + I * 1.6 , 1.701139468 + 1.741030588 * I\n%! -0.8 + I * 1.8 , 1.994526268 + 2.191509596 * I\n%! -0.8 + I * 2. , 2.312257188 + 2.762051518 * I\n%! -0.6 + I * 0. , 0.8258917445 + 0. * I\n%! -0.6 + I * 0.2 , 0.842151698 + 0.1130337928 * I\n%! -0.6 + I * 0.4 , 0.8915487431 + 0.2309124769 * I\n%! -0.6 + I * 0.6 , 0.975948103 + 0.3588102098 * I\n%! -0.6 + I * 0.8 , 1.098499209 + 0.5026234141 * I\n%! -0.6 + I * 1. , 1.263676101 + 0.6695125973 * I\n%! -0.6 + I * 1.2 , 1.477275851 + 0.8687285705 * I\n%! -0.6 + I * 1.4 , 1.746262523 + 1.112955966 * I\n%! -0.6 + I * 1.6 , 2.078179075 + 1.420581466 * I\n%! -0.6 + I * 1.8 , 2.479425208 + 1.819580713 * I\n%! -0.6 + I * 2. , 2.950586798 + 2.354077344 * I\n%! -0.4 + I * 0. , 0.9211793498 + 0. * I\n%! -0.4 + I * 0.2 , 0.9395019377 + 0.07822091534 * I\n%! -0.4 + I * 0.4 , 0.9952345231 + 0.1598950363 * I\n%! -0.4 + I * 0.6 , 1.090715991 + 0.2487465067 * I\n%! -0.4 + I * 0.8 , 1.229998843 + 0.34910407 * I\n%! -0.4 + I * 1. , 1.419103868 + 0.4663848201 * I\n%! -0.4 + I * 1.2 , 1.666426377 + 0.607877235 * I\n%! -0.4 + I * 1.4 , 1.983347336 + 0.7841054404 * I\n%! -0.4 + I * 1.6 , 2.385101684 + 1.01134031 * I\n%! -0.4 + I * 1.8 , 2.89185416 + 1.316448705 * I\n%! -0.4 + I * 2. , 3.529393374 + 1.74670531 * I\n%! -0.2 + I * 0. , 0.9800743122 + 0. * I\n%! -0.2 + I * 0.2 , 0.9997019476 + 0.03999835809 * I\n%! -0.2 + I * 0.4 , 1.059453907 + 0.08179712295 * I\n%! -0.2 + I * 0.6 , 1.16200643 + 0.1273503824 * I\n%! -0.2 + I * 0.8 , 1.312066413 + 0.1789585449 * I\n%! -0.2 + I * 1. , 1.516804331 + 0.2395555269 * I\n%! -0.2 + I * 1.2 , 1.786613221 + 0.313189147 * I\n%! -0.2 + I * 1.4 , 2.136422971 + 0.405890925 * I\n%! -0.2 + I * 1.6 , 2.588021972 + 0.527357091 * I\n%! -0.2 + I * 1.8 , 3.174302819 + 0.6944201617 * I\n%! -0.2 + I * 2. , 3.947361147 + 0.9387994989 * I\n%! 0. + I * 0. , 1. + 0. * I\n%! 0. + I * 0.2 , 1.020074723 + 0. * I\n%! 0. + I * 0.4 , 1.08120563 + 0. * I\n%! 0. + I * 0.6 , 1.18619146 + 0. * I\n%! 0. + I * 0.8 , 1.339978715 + 0. * I\n%! 0. + I * 1. , 1.550164037 + 0. * I\n%! 0. + I * 1.2 , 1.827893279 + 0. * I\n%! 0. + I * 1.4 , 2.189462954 + 0. * I\n%! 0. + I * 1.6 , 2.659259752 + 0. * I\n%! 0. + I * 1.8 , 3.275434266 + 0. * I\n%! 0. + I * 2. , 4.101632484 + 0. * I\n%! 0.2 + I * 0. , 0.9800743122 + 0. * I\n%! 0.2 + I * 0.2 , 0.9997019476 - 0.03999835809 * I\n%! 0.2 + I * 0.4 , 1.059453907 - 0.08179712295 * I\n%! 0.2 + I * 0.6 , 1.16200643 - 0.1273503824 * I\n%! 0.2 + I * 0.8 , 1.312066413 - 0.1789585449 * I\n%! 0.2 + I * 1. , 1.516804331 - 0.2395555269 * I\n%! 0.2 + I * 1.2 , 1.786613221 - 0.313189147 * I\n%! 0.2 + I * 1.4 , 2.136422971 - 0.405890925 * I\n%! 0.2 + I * 1.6 , 2.588021972 - 0.527357091 * I\n%! 0.2 + I * 1.8 , 3.174302819 - 0.6944201617 * I\n%! 0.2 + I * 2. , 3.947361147 - 0.9387994989 * I\n%! 0.4 + I * 0. , 0.9211793498 + 0. * I\n%! 0.4 + I * 0.2 , 0.9395019377 - 0.07822091534 * I\n%! 0.4 + I * 0.4 , 0.9952345231 - 0.1598950363 * I\n%! 0.4 + I * 0.6 , 1.090715991 - 0.2487465067 * I\n%! 0.4 + I * 0.8 , 1.229998843 - 0.34910407 * I\n%! 0.4 + I * 1. , 1.419103868 - 0.4663848201 * I\n%! 0.4 + I * 1.2 , 1.666426377 - 0.607877235 * I\n%! 0.4 + I * 1.4 , 1.983347336 - 0.7841054404 * I\n%! 0.4 + I * 1.6 , 2.385101684 - 1.01134031 * I\n%! 0.4 + I * 1.8 , 2.89185416 - 1.316448705 * I\n%! 0.4 + I * 2. , 3.529393374 - 1.74670531 * I\n%! 0.6 + I * 0. , 0.8258917445 + 0. * I\n%! 0.6 + I * 0.2 , 0.842151698 - 0.1130337928 * I\n%! 0.6 + I * 0.4 , 0.8915487431 - 0.2309124769 * I\n%! 0.6 + I * 0.6 , 0.975948103 - 0.3588102098 * I\n%! 0.6 + I * 0.8 , 1.098499209 - 0.5026234141 * I\n%! 0.6 + I * 1. , 1.263676101 - 0.6695125973 * I\n%! 0.6 + I * 1.2 , 1.477275851 - 0.8687285705 * I\n%! 0.6 + I * 1.4 , 1.746262523 - 1.112955966 * I\n%! 0.6 + I * 1.6 , 2.078179075 - 1.420581466 * I\n%! 0.6 + I * 1.8 , 2.479425208 - 1.819580713 * I\n%! 0.6 + I * 2. , 2.950586798 - 2.354077344 * I\n%! 0.8 + I * 0. , 0.6982891589 + 0. * I\n%! 0.8 + I * 0.2 , 0.71187169 - 0.1430549855 * I\n%! 0.8 + I * 0.4 , 0.7530744458 - 0.2920273465 * I\n%! 0.8 + I * 0.6 , 0.8232501212 - 0.4531616768 * I\n%! 0.8 + I * 0.8 , 0.9245978896 - 0.6334016187 * I\n%! 0.8 + I * 1. , 1.060030206 - 0.8408616109 * I\n%! 0.8 + I * 1.2 , 1.232861756 - 1.085475913 * I\n%! 0.8 + I * 1.4 , 1.446126965 - 1.379933558 * I\n%! 0.8 + I * 1.6 , 1.701139468 - 1.741030588 * I\n%! 0.8 + I * 1.8 , 1.994526268 - 2.191509596 * I\n%! 0.8 + I * 2. , 2.312257188 - 2.762051518 * I\n%! 1. + I * 0. , 0.5436738271 + 0. * I\n%! 1. + I * 0.2 , 0.5541219664 - 0.1672121517 * I\n%! 1. + I * 0.4 , 0.5857703552 - 0.3410940893 * I\n%! 1. + I * 0.6 , 0.6395034233 - 0.5285979063 * I\n%! 1. + I * 0.8 , 0.716688504 - 0.7372552987 * I\n%! 1. + I * 1. , 0.8189576795 - 0.9755037374 * I\n%! 1. + I * 1.2 , 0.9477661951 - 1.253049471 * I\n%! 1. + I * 1.4 , 1.103540657 - 1.581252712 * I\n%! 1. + I * 1.6 , 1.284098214 - 1.973449038 * I\n%! 1. + I * 1.8 , 1.481835651 - 2.4449211 * I\n%! 1. + I * 2. , 1.679032464 - 3.011729224 * I\n%! ];\n%! DN = [\n%! -1. + I * 0. , 0.9895776106 + 0. * I\n%! -1. + I * 0.2 , 0.9893361555 + 0.002756935338 * I\n%! -1. + I * 0.4 , 0.9885716856 + 0.005949639805 * I\n%! -1. + I * 0.6 , 0.9871564855 + 0.01008044183 * I\n%! -1. + I * 0.8 , 0.9848512162 + 0.01579337596 * I\n%! -1. + I * 1. , 0.9812582484 + 0.02396648455 * I\n%! -1. + I * 1.2 , 0.9757399152 + 0.0358288294 * I\n%! -1. + I * 1.4 , 0.9672786056 + 0.0531049859 * I\n%! -1. + I * 1.6 , 0.954237868 + 0.0781744383 * I\n%! -1. + I * 1.8 , 0.933957524 + 0.1141918269 * I\n%! -1. + I * 2. , 0.9020917489 + 0.1650142936 * I\n%! -0.8 + I * 0. , 0.992429635 + 0. * I\n%! -0.8 + I * 0.2 , 0.9924147861 + 0.003020708044 * I\n%! -0.8 + I * 0.4 , 0.99236555 + 0.00652359532 * I\n%! -0.8 + I * 0.6 , 0.9922655715 + 0.0110676219 * I\n%! -0.8 + I * 0.8 , 0.9920785856 + 0.01737733806 * I\n%! -0.8 + I * 1. , 0.9917291795 + 0.02645738598 * I\n%! -0.8 + I * 1.2 , 0.9910606387 + 0.03974949378 * I\n%! -0.8 + I * 1.4 , 0.9897435004 + 0.05935252515 * I\n%! -0.8 + I * 1.6 , 0.987077644 + 0.08832675281 * I\n%! -0.8 + I * 1.8 , 0.9815667458 + 0.1310872821 * I\n%! -0.8 + I * 2. , 0.970020127 + 0.1938136793 * I\n%! -0.6 + I * 0. , 0.9953099088 + 0. * I\n%! -0.6 + I * 0.2 , 0.995526009 + 0.002814772354 * I\n%! -0.6 + I * 0.4 , 0.9962071136 + 0.006083312292 * I\n%! -0.6 + I * 0.6 , 0.9974557125 + 0.01033463525 * I\n%! -0.6 + I * 0.8 , 0.9994560563 + 0.01626207722 * I\n%! -0.6 + I * 1. , 1.00249312 + 0.02484336286 * I\n%! -0.6 + I * 1.2 , 1.006973922 + 0.0375167093 * I\n%! -0.6 + I * 1.4 , 1.013436509 + 0.05645315628 * I\n%! -0.6 + I * 1.6 , 1.022504295 + 0.08499262247 * I\n%! -0.6 + I * 1.8 , 1.034670023 + 0.1283564595 * I\n%! -0.6 + I * 2. , 1.049599899 + 0.194806122 * I\n%! -0.4 + I * 0. , 0.9977686897 + 0. * I\n%! -0.4 + I * 0.2 , 0.9981836165 + 0.002167241934 * I\n%! -0.4 + I * 0.4 , 0.9994946045 + 0.004686808612 * I\n%! -0.4 + I * 0.6 , 1.001910789 + 0.00797144174 * I\n%! -0.4 + I * 0.8 , 1.005817375 + 0.01256717724 * I\n%! -0.4 + I * 1. , 1.011836374 + 0.01925509038 * I\n%! -0.4 + I * 1.2 , 1.020923572 + 0.02920828367 * I\n%! -0.4 + I * 1.4 , 1.034513743 + 0.04425213602 * I\n%! -0.4 + I * 1.6 , 1.054725746 + 0.06732276244 * I\n%! -0.4 + I * 1.8 , 1.08462027 + 0.1033236812 * I\n%! -0.4 + I * 2. , 1.128407402 + 0.1608240664 * I\n%! -0.2 + I * 0. , 0.9994191176 + 0. * I\n%! -0.2 + I * 0.2 , 0.9999683719 + 0.001177128019 * I\n%! -0.2 + I * 0.4 , 1.001705496 + 0.00254669712 * I\n%! -0.2 + I * 0.6 , 1.004913944 + 0.004334880912 * I\n%! -0.2 + I * 0.8 , 1.010120575 + 0.006842775622 * I\n%! -0.2 + I * 1. , 1.018189543 + 0.01050520136 * I\n%! -0.2 + I * 1.2 , 1.030482479 + 0.01598431001 * I\n%! -0.2 + I * 1.4 , 1.049126108 + 0.02433134655 * I\n%! -0.2 + I * 1.6 , 1.077466003 + 0.0372877718 * I\n%! -0.2 + I * 1.8 , 1.120863308 + 0.05789156398 * I\n%! -0.2 + I * 2. , 1.188162088 + 0.09181238708 * I\n%! 0. + I * 0. , 1. + 0. * I\n%! 0. + I * 0.2 , 1.000596698 + 0. * I\n%! 0. + I * 0.4 , 1.002484444 + 0. * I\n%! 0. + I * 0.6 , 1.005973379 + 0. * I\n%! 0. + I * 0.8 , 1.011641536 + 0. * I\n%! 0. + I * 1. , 1.020441432 + 0. * I\n%! 0. + I * 1.2 , 1.033885057 + 0. * I\n%! 0. + I * 1.4 , 1.054361188 + 0. * I\n%! 0. + I * 1.6 , 1.085694733 + 0. * I\n%! 0. + I * 1.8 , 1.134186672 + 0. * I\n%! 0. + I * 2. , 1.210701071 + 0. * I\n%! 0.2 + I * 0. , 0.9994191176 + 0. * I\n%! 0.2 + I * 0.2 , 0.9999683719 - 0.001177128019 * I\n%! 0.2 + I * 0.4 , 1.001705496 - 0.00254669712 * I\n%! 0.2 + I * 0.6 , 1.004913944 - 0.004334880912 * I\n%! 0.2 + I * 0.8 , 1.010120575 - 0.006842775622 * I\n%! 0.2 + I * 1. , 1.018189543 - 0.01050520136 * I\n%! 0.2 + I * 1.2 , 1.030482479 - 0.01598431001 * I\n%! 0.2 + I * 1.4 , 1.049126108 - 0.02433134655 * I\n%! 0.2 + I * 1.6 , 1.077466003 - 0.0372877718 * I\n%! 0.2 + I * 1.8 , 1.120863308 - 0.05789156398 * I\n%! 0.2 + I * 2. , 1.188162088 - 0.09181238708 * I\n%! 0.4 + I * 0. , 0.9977686897 + 0. * I\n%! 0.4 + I * 0.2 , 0.9981836165 - 0.002167241934 * I\n%! 0.4 + I * 0.4 , 0.9994946045 - 0.004686808612 * I\n%! 0.4 + I * 0.6 , 1.001910789 - 0.00797144174 * I\n%! 0.4 + I * 0.8 , 1.005817375 - 0.01256717724 * I\n%! 0.4 + I * 1. , 1.011836374 - 0.01925509038 * I\n%! 0.4 + I * 1.2 , 1.020923572 - 0.02920828367 * I\n%! 0.4 + I * 1.4 , 1.034513743 - 0.04425213602 * I\n%! 0.4 + I * 1.6 , 1.054725746 - 0.06732276244 * I\n%! 0.4 + I * 1.8 , 1.08462027 - 0.1033236812 * I\n%! 0.4 + I * 2. , 1.128407402 - 0.1608240664 * I\n%! 0.6 + I * 0. , 0.9953099088 + 0. * I\n%! 0.6 + I * 0.2 , 0.995526009 - 0.002814772354 * I\n%! 0.6 + I * 0.4 , 0.9962071136 - 0.006083312292 * I\n%! 0.6 + I * 0.6 , 0.9974557125 - 0.01033463525 * I\n%! 0.6 + I * 0.8 , 0.9994560563 - 0.01626207722 * I\n%! 0.6 + I * 1. , 1.00249312 - 0.02484336286 * I\n%! 0.6 + I * 1.2 , 1.006973922 - 0.0375167093 * I\n%! 0.6 + I * 1.4 , 1.013436509 - 0.05645315628 * I\n%! 0.6 + I * 1.6 , 1.022504295 - 0.08499262247 * I\n%! 0.6 + I * 1.8 , 1.034670023 - 0.1283564595 * I\n%! 0.6 + I * 2. , 1.049599899 - 0.194806122 * I\n%! 0.8 + I * 0. , 0.992429635 + 0. * I\n%! 0.8 + I * 0.2 , 0.9924147861 - 0.003020708044 * I\n%! 0.8 + I * 0.4 , 0.99236555 - 0.00652359532 * I\n%! 0.8 + I * 0.6 , 0.9922655715 - 0.0110676219 * I\n%! 0.8 + I * 0.8 , 0.9920785856 - 0.01737733806 * I\n%! 0.8 + I * 1. , 0.9917291795 - 0.02645738598 * I\n%! 0.8 + I * 1.2 , 0.9910606387 - 0.03974949378 * I\n%! 0.8 + I * 1.4 , 0.9897435004 - 0.05935252515 * I\n%! 0.8 + I * 1.6 , 0.987077644 - 0.08832675281 * I\n%! 0.8 + I * 1.8 , 0.9815667458 - 0.1310872821 * I\n%! 0.8 + I * 2. , 0.970020127 - 0.1938136793 * I\n%! 1. + I * 0. , 0.9895776106 + 0. * I\n%! 1. + I * 0.2 , 0.9893361555 - 0.002756935338 * I\n%! 1. + I * 0.4 , 0.9885716856 - 0.005949639805 * I\n%! 1. + I * 0.6 , 0.9871564855 - 0.01008044183 * I\n%! 1. + I * 0.8 , 0.9848512162 - 0.01579337596 * I\n%! 1. + I * 1. , 0.9812582484 - 0.02396648455 * I\n%! 1. + I * 1.2 , 0.9757399152 - 0.0358288294 * I\n%! 1. + I * 1.4 , 0.9672786056 - 0.0531049859 * I\n%! 1. + I * 1.6 , 0.954237868 - 0.0781744383 * I\n%! 1. + I * 1.8 , 0.933957524 - 0.1141918269 * I\n%! 1. + I * 2. , 0.9020917489 - 0.1650142936 * I\n%! ];\n%! tol = 1e-9;\n%! for x = 0:10\n%!   for y = 0:10\n%!     ur = -1 + x * 0.2;\n%!     ui =  y * 0.2;\n%!     ii = 1 + y + x*11;\n%!     [sn, cn, dn] = ellipj (ur + I * ui, m);\n%!     assert (sn, SN(ii, 2), tol);\n%!     assert (cn, CN(ii, 2), tol);\n%!     assert (dn, DN(ii, 2), tol);\n%!   endfor\n%! endfor\n\n## tests taken from test_ellipj.m\n%!test\n%! u1 = pi/3; m1 = 0;\n%! res1 = [sin(pi/3), cos(pi/3), 1];\n%! [sn,cn,dn] = ellipj (u1,m1);\n%! assert ([sn,cn,dn], res1, 10*eps);\n\n%!test\n%! u2 = log (2); m2 = 1;\n%! res2 = [ 3/5, 4/5, 4/5 ];\n%! [sn,cn,dn] = ellipj (u2,m2);\n%! assert ([sn,cn,dn], res2, 10*eps);\n\n%!test\n%! u3 = log (2)*1i; m3 = 0;\n%! res3 = [3i/4,5/4,1];\n%! [sn,cn,dn] = ellipj (u3,m3);\n%! assert ([sn,cn,dn], res3, 10*eps);\n\n%!test\n%! u4 = -1; m4 = tan (pi/8)^4;\n%! res4 = [-0.8392965923,0.5436738271,0.9895776106];\n%! [sn,cn,dn] = ellipj (u4, m4);\n%! assert ([sn,cn,dn], res4, 1e-10);\n\n%!test\n%! u5 = -0.2 + 0.4i; m5 = tan (pi/8)^4;\n%! res5 = [ -0.2152524522 + 0.402598347i, ...\n%!           1.059453907  + 0.08179712295i, ...\n%!           1.001705496  + 0.00254669712i ];\n%! [sn,cn,dn] = ellipj (u5,m5);\n%! assert ([sn,cn,dn], res5, 1e-9);\n\n%!test\n%! u6 = 0.2 + 0.6i; m6 = tan (pi/8)^4;\n%! res6 = [ 0.2369100139 + 0.624633635i, ...\n%!          1.16200643   - 0.1273503824i, ...\n%!          1.004913944  - 0.004334880912i ];\n%! [sn,cn,dn] = ellipj (u6,m6);\n%! assert ([sn,cn,dn], res6, 1e-8);\n\n%!test\n%! u7 = 0.8 + 0.8i; m7 = tan (pi/8)^4;\n%! res7 = [0.9588386397 + 0.6107824358i, ...\n%!         0.9245978896 - 0.6334016187i, ...\n%!         0.9920785856 - 0.01737733806i ];\n%! [sn,cn,dn] = ellipj (u7,m7);\n%! assert ([sn,cn,dn], res7, 1e-10);\n\n%!test\n%! u = [0,pi/6,pi/4,pi/2]; m=0;\n%! res = [0,1/2,1/sqrt(2),1;1,cos(pi/6),1/sqrt(2),0;1,1,1,1];\n%! [sn,cn,dn] = ellipj (u,m);\n%! assert ([sn;cn;dn], res, 100*eps);\n%! [sn,cn,dn] = ellipj (u',0);\n%! assert ([sn,cn,dn], res', 100*eps);\n\n## FIXME: need to check [real,complex]x[scalar,rowvec,colvec,matrix]x[u,m]\n\n## One test for u column vector x m row vector\n%!test\n%! u = [0,pi/6,pi/4,pi/2]';  m = [0 0 0 0];\n%! res = [0,1/2,1/sqrt(2),1;1,cos(pi/6),1/sqrt(2),0;1,1,1,1]';\n%! [sn,cn,dn] = ellipj (u,m);\n%! assert (sn, repmat (res(:,1), [1,4]), 100*eps);\n%! assert (cn, repmat (res(:,2), [1,4]), 100*eps);\n%! assert (dn, repmat (res(:,3), [1,4]), 100*eps);\n\n%!test\n%! ## Test Jacobi elliptic functions\n%! ## against \"exact\" solution from Mathematica 3.0\n%! ## David Billinghurst <David.Billinghurst@riotinto.com>\n%! ## 1 February 2001\n%! u = [ 0.25; 0.25; 0.20; 0.20; 0.672; 0.5];\n%! m = [ 0.0;  1.0;  0.19; 0.81; 0.36;  0.9999999999];\n%! S = [ sin(0.25);\n%!       tanh(0.25);\n%!       0.19842311013970879516;\n%!       0.19762082367187648571;\n%!       0.6095196917919021945;\n%!       0.4621171572617320908 ];\n%! C = [ cos(0.25);\n%!       sech(0.25);\n%!       0.9801164570409401062;\n%!       0.9802785369736752032;\n%!       0.7927709286533560550;\n%!       0.8868188839691764094 ];\n%! D = [ 1.0;\n%!       sech(0.25);\n%!       0.9962526643271134302;\n%!       0.9840560289645665155;\n%!       0.9307281387786906491;\n%!       0.8868188839812167635 ];\n%! [sn,cn,dn] = ellipj (u,m);\n%! assert (sn, S, 8*eps);\n%! assert (cn, C, 8*eps);\n%! assert (dn, D, 8*eps);\n\n%!test <*43344>\n%! ## Test continuity of dn when cn is near zero\n%! m = 0.5;\n%! u = ellipke (0.5);\n%! x = [-1e-3, -1e-12, 0, 1e-12, 1e-3];\n%! [~, ~, dn] = ellipj (u + x, m);\n%! D = 1/sqrt (2) * ones (size (x));\n%! assert (dn, D, 1e-6);\n\n%!error ellipj ()\n%!error ellipj (1)\n%!error ellipj (1,2,3,4)\n%!warning <required value 0 <= M <= 1> ellipj (1,2);\n## FIXME: errors commented out until lasterr() truly returns the last error.\n%!#error <M must be a scalar or matrix> ellipj (1, \"1\")\n%!#error <U must be a scalar or matrix> ellipj (\"1\", 1)\n%!#error <U must be a scalar or matrix> ellipj ({1}, 1)\n%!#error <U must be a scalar or matrix> ellipj ({1, 2}, 1)\n%!#error <M must be a scalar or matrix> ellipj (1, {1, 2})\n%!#error <U must be a scalar or matrix> ellipj (\"1\", [1, 2])\n%!#error <U must be a scalar or matrix> ellipj ({1}, [1, 2])\n%!#error <U must be a scalar or matrix> ellipj ({1}, [1, 2])\n%!#error <U must be a scalar or matrix> ellipj (\"1,2\", [1, 2])\n%!#error <U must be a scalar or matrix> ellipj ({1, 2}, [1, 2])\n%!error <Invalid size combination for U and M> ellipj ([1:4], [1:3])\n%!error <Invalid size combination for U and M> ellipj (complex (1:4,1:4), [1:3])\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/fft.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mappers.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic octave_value\ndo_fft (const octave_value_list& args, const char *fcn, int type)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  octave_value retval;\n  octave_value arg = args(0);\n  octave_idx_type n_points = -1;\n  dim_vector dims = arg.dims ();\n  int ndims = dims.ndims ();\n  int dim = -1;\n\n  if (nargin > 1)\n    {\n      if (! args(1).isempty ())\n        {\n          double dval = args(1).double_value ();\n          if (math::isnan (dval))\n            error (\"%s: number of points (N) cannot be NaN\", fcn);\n\n          n_points = math::nint_big (dval);\n          if (n_points < 0)\n            error (\"%s: number of points (N) must be greater than zero\", fcn);\n        }\n    }\n\n  if (nargin > 2)\n    {\n      double dval = args(2).double_value ();\n      if (math::isnan (dval))\n        error (\"%s: DIM cannot be NaN\", fcn);\n      else if (dval < 1 || dval > ndims)\n        error (\"%s: DIM must be a valid dimension along which to perform FFT\",\n               fcn);\n      else\n        // to be safe, cast it back to int since dim is an int\n        dim = math::nint (dval) - 1;\n    }\n\n  if (dim < 0)\n    {\n      dim = dims.first_non_singleton ();\n\n      // And if the first argument is scalar?\n      if (dim == ndims)\n        dim = 1;\n    }\n\n  if (n_points < 0)\n    n_points = dims(dim);\n  else\n    dims(dim) = n_points;\n\n  if (n_points == 0 || dims.any_zero ())\n    {\n      if (arg.is_single_type ())\n        return octave_value (FloatNDArray (dims));\n      else\n        return octave_value (NDArray (dims));\n    }\n\n  if (n_points == 1)\n    {\n      octave_value_list idx (ndims);\n      for (octave_idx_type i = 0; i < ndims; i++)\n        idx(i) = idx_vector::colon;\n      idx(dim) = idx_vector (0);\n\n      return arg.index_op (idx);\n    }\n\n  if (arg.is_single_type ())\n    {\n      if (arg.isreal ())\n        {\n          FloatNDArray nda = arg.float_array_value ();\n\n          nda.resize (dims, 0.0);\n          retval = (type != 0 ? nda.ifourier (dim) : nda.fourier (dim));\n        }\n      else\n        {\n          FloatComplexNDArray cnda = arg.float_complex_array_value ();\n\n          cnda.resize (dims, 0.0);\n          retval = (type != 0 ? cnda.ifourier (dim) : cnda.fourier (dim));\n        }\n    }\n  else\n    {\n      if (arg.isreal ())\n        {\n          NDArray nda = arg.array_value ();\n\n          nda.resize (dims, 0.0);\n          retval = (type != 0 ? nda.ifourier (dim) : nda.fourier (dim));\n        }\n      else if (arg.iscomplex ())\n        {\n          ComplexNDArray cnda = arg.complex_array_value ();\n\n          cnda.resize (dims, 0.0);\n          retval = (type != 0 ? cnda.ifourier (dim) : cnda.fourier (dim));\n        }\n      else\n        err_wrong_type_arg (fcn, arg);\n    }\n\n  return retval;\n}\n\n/*\n%!testif HAVE_FFTW\n%! assert (fft ([]), []);\n%!testif HAVE_FFTW\n%! assert (fft (zeros (10,0)), zeros (10,0));\n%!testif HAVE_FFTW\n%! assert (fft (zeros (0,10)), zeros (0,10));\n%!testif HAVE_FFTW\n%! assert (fft (0), 0);\n%!testif HAVE_FFTW\n%! assert (fft (1), 1);\n%!testif HAVE_FFTW\n%! assert (fft (ones (2,2)), [2,2; 0,0]);\n%!testif HAVE_FFTW\n%! assert (fft (eye (2,2)), [1,1; 1,-1]);\n\n%!testif HAVE_FFTW\n%! assert (fft (single ([])), single ([]));\n%!testif HAVE_FFTW\n%! assert (fft (zeros (10,0,\"single\")), zeros (10,0,\"single\"));\n%!testif HAVE_FFTW\n%! assert (fft (zeros (0,10,\"single\")), zeros (0,10,\"single\"));\n%!testif HAVE_FFTW\n%! assert (fft (single (0)), single (0));\n%!testif HAVE_FFTW\n%! assert (fft (single (1)), single (1));\n%!testif HAVE_FFTW\n%! assert (fft (ones (2,2,\"single\")), single ([2,2; 0,0]));\n%!testif HAVE_FFTW\n%! assert (fft (eye (2,2,\"single\")), single ([1,1; 1,-1]));\n\n%!error fft ()\n*/\n\n\nDEFUN (fft, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} fft (@var{x})\n@deftypefnx {} {@var{y} =} fft (@var{x}, @var{n})\n@deftypefnx {} {@var{y} =} fft (@var{x}, @var{n}, @var{dim})\nCompute the discrete Fourier transform of @var{x} using\na Fast Fourier Transform (FFT) algorithm.\n\nThe FFT is calculated along the first non-singleton dimension of the\narray.  Thus if @var{x} is a matrix, @code{fft (@var{x})} computes the\nFFT for each column of @var{x}.\n\nIf called with two arguments, @var{n} is expected to be an integer\nspecifying the number of elements of @var{x} to use, or an empty\nmatrix to specify that its value should be ignored.  If @var{n} is\nlarger than the dimension along which the FFT is calculated, then\n@var{x} is resized and padded with zeros.  Otherwise, if @var{n} is\nsmaller than the dimension along which the FFT is calculated, then\n@var{x} is truncated.\n\nIf called with three arguments, @var{dim} is an integer specifying the\ndimension of the matrix along which the FFT is performed.\n@seealso{ifft, fft2, fftn, fftw}\n@end deftypefn */)\n{\n  return do_fft (args, \"fft\", 0);\n}\n\n\nDEFUN (ifft, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} ifft (@var{y})\n@deftypefnx {} {@var{x} =} ifft (@var{y}, @var{n})\n@deftypefnx {} {@var{x} =} ifft (@var{y}, @var{n}, @var{dim})\nCompute the inverse discrete Fourier transform of @var{y}\nusing a Fast Fourier Transform (FFT) algorithm.\n\nThe inverse FFT is calculated along the first non-singleton dimension\nof the array.  Thus if @var{y} is a matrix, @code{ifft (@var{y})} computes\nthe inverse FFT for each column of @var{y}.\n\nIf called with two arguments, @var{n} is expected to be an integer\nspecifying the number of elements of @var{y} to use, or an empty\nmatrix to specify that its value should be ignored.  If @var{n} is\nlarger than the dimension along which the inverse FFT is calculated, then\n@var{y} is resized and padded with zeros.  Otherwise, if @var{n} is\nsmaller than the dimension along which the inverse FFT is calculated,\nthen @var{y} is truncated.\n\nIf called with three arguments, @var{dim} is an integer specifying the\ndimension of the matrix along which the inverse FFT is performed.\n@seealso{fft, ifft2, ifftn, fftw}\n@end deftypefn */)\n{\n  return do_fft (args, \"ifft\", 1);\n}\n\n/*\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         02 May 2000\n%!testif HAVE_FFTW\n%! N = 64;\n%! n = 4;\n%! t = 2*pi*(0:1:N-1)/N;\n%! s = cos (n*t);\n%! S = fft (s);\n%!\n%! answer = zeros (size (t));\n%! answer(n+1) = N/2;\n%! answer(N-n+1) = N/2;\n%!\n%! assert (S, answer, 4*N*eps);\n\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         02 May 2000\n%!testif HAVE_FFTW\n%! N = 64;\n%! n = 7;\n%! t = 2*pi*(0:1:N-1)/N;\n%! s = cos (n*t);\n%!\n%! S = zeros (size (t));\n%! S(n+1) = N/2;\n%! S(N-n+1) = N/2;\n%!\n%! assert (ifft (S), s, 4*N*eps);\n\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         02 May 2000\n%!testif HAVE_FFTW\n%! N = 64;\n%! n = 4;\n%! t = single (2*pi*(0:1:N-1)/N);\n%! s = cos (n*t);\n%! S = fft (s);\n%!\n%! answer = zeros (size (t), \"single\");\n%! answer(n+1) = N/2;\n%! answer(N-n+1) = N/2;\n%!\n%! assert (S, answer, 4*N* eps (\"single\"));\n\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         02 May 2000\n%!testif HAVE_FFTW\n%! N = 64;\n%! n = 7;\n%! t = 2*pi*(0:1:N-1)/N;\n%! s = cos (n*t);\n%!\n%! S = zeros (size (t), \"single\");\n%! S(n+1) = N/2;\n%! S(N-n+1) = N/2;\n%!\n%! assert (ifft (S), s, 4*N* eps (\"single\"));\n\n%!testif HAVE_FFTW <*64729>\n%! x = rand (5, 5, 5, 5);\n%! old_planner = fftw ('planner', 'measure');\n%! unwind_protect\n%!   y = fft (x);\n%!   y = fft (x);  # second invocation might crash Octave\n%!   assert (size (y), [5, 5, 5, 5]);\n%! unwind_protect_cleanup\n%!   fftw ('planner', old_planner);\n%! end_unwind_protect\n\n%!testif HAVE_FFTW <*64729>\n%! x = rand (5, 5, 5, 5, 'single');\n%! old_planner = fftw ('planner', 'measure');\n%! unwind_protect\n%!   y = fft (x);\n%!   y = fft (x);  # second invocation might crash Octave\n%!   assert (size (y), [5, 5, 5, 5]);\n%! unwind_protect_cleanup\n%!   fftw ('planner', old_planner);\n%! end_unwind_protect\n\n%!testif HAVE_FFTW <*64733>\n%! old_planner = fftw ('planner', 'measure');\n%! unwind_protect\n%!   assert (ifft ([2, 4, 6, 8]), [5, -1-1i, -1, -1+1i]);\n%! unwind_protect_cleanup\n%!   fftw ('planner', old_planner);\n%! end_unwind_protect\n\n%!testif HAVE_FFTW <*64733>\n%! old_planner = fftw ('planner', 'measure');\n%! unwind_protect\n%!   assert (ifft (single ([2, 4, 6, 8])), single ([5, -1-1i, -1, -1+1i]));\n%! unwind_protect_cleanup\n%!   fftw ('planner', old_planner);\n%! end_unwind_protect\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/fft2.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mappers.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// This function should be merged with Fifft.\n\nstatic octave_value\ndo_fft2 (const octave_value_list& args, const char *fcn, int type)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  octave_value retval;\n  octave_value arg = args(0);\n  dim_vector dims = arg.dims ();\n  octave_idx_type n_rows = -1;\n\n  if (nargin > 1)\n    {\n      double dval = args(1).double_value ();\n      if (math::isnan (dval))\n        error (\"%s: number of rows (M) cannot be NaN\", fcn);\n\n      n_rows = math::nint_big (dval);\n      if (n_rows < 0)\n        error (\"%s: number of rows (M) must be greater than zero\", fcn);\n    }\n\n  octave_idx_type n_cols = -1;\n  if (nargin > 2)\n    {\n      double dval = args(2).double_value ();\n      if (math::isnan (dval))\n        error (\"%s: number of columns (N) cannot be NaN\", fcn);\n\n      n_cols = math::nint_big (dval);\n      if (n_cols < 0)\n        error (\"%s: number of columns (N) must be greater than zero\", fcn);\n    }\n\n  for (int i = 0; i < dims.ndims (); i++)\n    if (dims(i) < 0)\n      return retval;\n\n  if (n_rows < 0)\n    n_rows = dims(0);\n  else\n    dims(0) = n_rows;\n\n  if (n_cols < 0)\n    n_cols = dims(1);\n  else\n    dims(1) = n_cols;\n\n  if (dims.any_zero ())\n    {\n      if (arg.is_single_type ())\n        return octave_value (FloatNDArray (dims));\n      else\n        return octave_value (NDArray (dims));\n    }\n\n  if (arg.is_single_type ())\n    {\n      if (arg.isreal ())\n        {\n          FloatNDArray nda = arg.float_array_value ();\n\n          nda.resize (dims, 0.0);\n          retval = (type != 0 ? nda.ifourier2d () : nda.fourier2d ());\n        }\n      else\n        {\n          FloatComplexNDArray cnda = arg.float_complex_array_value ();\n\n          cnda.resize (dims, 0.0);\n          retval = (type != 0 ? cnda.ifourier2d () : cnda.fourier2d ());\n        }\n    }\n  else\n    {\n      if (arg.isreal ())\n        {\n          NDArray nda = arg.array_value ();\n\n          nda.resize (dims, 0.0);\n          retval = (type != 0 ? nda.ifourier2d () : nda.fourier2d ());\n        }\n      else if (arg.iscomplex ())\n        {\n          ComplexNDArray cnda = arg.complex_array_value ();\n\n          cnda.resize (dims, 0.0);\n          retval = (type != 0 ? cnda.ifourier2d () : cnda.fourier2d ());\n        }\n      else\n        err_wrong_type_arg (fcn, arg);\n    }\n\n  return retval;\n}\n\nDEFUN (fft2, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{B} =} fft2 (@var{A})\n@deftypefnx {} {@var{B} =} fft2 (@var{A}, @var{m}, @var{n})\nCompute the two-dimensional discrete Fourier transform of @var{A} using\na Fast Fourier Transform (FFT) algorithm.\n\nThe optional arguments @var{m} and @var{n} may be used specify the number of\nrows and columns of @var{A} to use.  If either of these is larger than the\nsize of @var{A}, @var{A} is resized and padded with zeros.\n\nIf @var{A} is a multi-dimensional matrix, each two-dimensional sub-matrix\nof @var{A} is treated separately.\n@seealso{ifft2, fft, fftn, fftw}\n@end deftypefn */)\n{\n  return do_fft2 (args, \"fft2\", 0);\n}\n\n/*\n%!testif HAVE_FFTW <*65414>\n%! sz = size (fft2 (ones (2, 0, 3)));\n%! assert (sz, [2, 0, 3]);\n\n%!testif HAVE_FFTW <*65414>\n%! sz = size (fft2 (ones (5, 4, 3), 2, 0));\n%! assert (sz, [2, 0, 3]);\n\n%!error <number of rows \\(M\\) cannot be NaN> fft2 (ones (5,4,3), NaN, 2)\n%!error <number of rows \\(M\\) .* greater than zero> fft2 (ones (5,4,3), -1, 2)\n%!error <number of columns \\(N\\) cannot be NaN> fft2 (ones (5,4,3), 2, NaN)\n%!error <number of columns \\(N\\) .* greater than zero> fft2 (ones (5,4,3), 2, -1)\n*/\n\nDEFUN (ifft2, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{A} =} ifft2 (@var{B})\n@deftypefnx {} {@var{A} =} ifft2 (@var{B}, @var{m}, @var{n})\nCompute the inverse two-dimensional discrete Fourier transform of @var{B}\nusing a Fast Fourier Transform (FFT) algorithm.\n\nThe optional arguments @var{m} and @var{n} may be used specify the number of\nrows and columns of @var{B} to use.  If either of these is larger than the\nsize of @var{B}, @var{B} is resized and padded with zeros.\n\nIf @var{B} is a multi-dimensional matrix, each two-dimensional sub-matrix\nof @var{B} is treated separately.\n@seealso{fft2, ifft, ifftn, fftw}\n@end deftypefn */)\n{\n  return do_fft2 (args, \"ifft2\", 1);\n}\n\n/*\n%!testif HAVE_FFTW <*65414>\n%! sz = size (ifft2 (ones (2, 0, 3)));\n%! assert (sz, [2, 0, 3]);\n\n%!testif HAVE_FFTW <*65414>\n%! sz = size (ifft2 (ones (5, 4, 3), 2, 0));\n%! assert (sz, [2, 0, 3]);\n\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         02 May 2000\n%!testif HAVE_FFTW\n%! M = 16;\n%! N = 8;\n%!\n%! m = 5;\n%! n = 3;\n%!\n%! x = 2*pi*(0:1:M-1)/M;\n%! y = 2*pi*(0:1:N-1)/N;\n%! sx = cos (m*x);\n%! sy = sin (n*y);\n%! s = kron (sx',sy);\n%! S = fft2 (s);\n%! answer = kron (fft (sx)', fft (sy));\n%! assert (S, answer, 4*M*N*eps);\n\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         02 May 2000\n%!testif HAVE_FFTW\n%! M = 12;\n%! N = 7;\n%!\n%! m = 3;\n%! n = 2;\n%!\n%! x = 2*pi*(0:1:M-1)/M;\n%! y = 2*pi*(0:1:N-1)/N;\n%!\n%! sx = cos (m*x);\n%! sy = cos (n*y);\n%!\n%! S = kron (fft (sx)', fft (sy));\n%! answer = kron (sx', sy);\n%! s = ifft2 (S);\n%!\n%! assert (s, answer, 30*eps);\n\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         02 May 2000\n%!testif HAVE_FFTW\n%! M = 16;\n%! N = 8;\n%!\n%! m = 5;\n%! n = 3;\n%!\n%! x = 2*pi*(0:1:M-1)/M;\n%! y = 2*pi*(0:1:N-1)/N;\n%! sx = single (cos (m*x));\n%! sy = single (sin (n*y));\n%! s = kron (sx', sy);\n%! S = fft2 (s);\n%! answer = kron (fft (sx)', fft (sy));\n%! assert (S, answer, 4*M*N* eps (\"single\"));\n\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         02 May 2000\n%!testif HAVE_FFTW\n%! M = 12;\n%! N = 7;\n%!\n%! m = 3;\n%! n = 2;\n%!\n%! x = single (2*pi*(0:1:M-1)/M);\n%! y = single (2*pi*(0:1:N-1)/N);\n%!\n%! sx = cos (m*x);\n%! sy = cos (n*y);\n%!\n%! S = kron (fft (sx)', fft (sy));\n%! answer = kron (sx', sy);\n%! s = ifft2 (S);\n%!\n%! assert (s, answer, 30* eps (\"single\"));\n\n%!error <number of rows \\(M\\) cannot be NaN> ifft2 (ones (5,4,3), NaN, 2)\n%!error <number of rows \\(M\\) .* greater than zero> ifft2 (ones (5,4,3), -1, 2)\n%!error <number of columns \\(N\\) cannot be NaN> ifft2 (ones (5,4,3), 2, NaN)\n%!error <number of columns \\(N\\) .* greater than zero> ifft2 (ones (5,4,3), 2, -1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/fftn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mappers.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// This function should be merged with Fifft.\n\nstatic octave_value\ndo_fftn (const octave_value_list& args, const char *fcn, int type)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value retval;\n  octave_value arg = args(0);\n  dim_vector dims = arg.dims ();\n\n  for (int i = 0; i < dims.ndims (); i++)\n    if (dims(i) < 0)\n      return retval;\n\n  if (nargin > 1)\n    {\n      Matrix val = args(1).xmatrix_value (\"%s: SIZE must be a vector of length dim\", fcn);\n\n      if (val.rows () > val.columns ())\n        val = val.transpose ();\n\n      if (val.columns () != dims.ndims () || val.rows () != 1)\n        error (\"%s: SIZE must be a vector of length dim\", fcn);\n\n      for (int i = 0; i < dims.ndims (); i++)\n        {\n          if (math::isnan (val(i, 0)))\n            error (\"%s: SIZE has invalid NaN entries\", fcn);\n          else if (math::nint_big (val(i, 0)) < 0)\n            error (\"%s: all dimensions in SIZE must be greater than zero\", fcn);\n          else\n            dims(i) = math::nint_big(val(i, 0));\n        }\n    }\n\n  if (dims.any_zero ())\n    {\n      if (arg.is_single_type ())\n        return octave_value (FloatNDArray (dims));\n      else\n        return octave_value (NDArray (dims));\n    }\n\n  if (arg.is_single_type ())\n    {\n      if (arg.isreal ())\n        {\n          FloatNDArray nda = arg.float_array_value ();\n\n          nda.resize (dims, 0.0);\n          retval = (type != 0 ? nda.ifourierNd () : nda.fourierNd ());\n        }\n      else\n        {\n          FloatComplexNDArray cnda = arg.float_complex_array_value ();\n\n          cnda.resize (dims, 0.0);\n          retval = (type != 0 ? cnda.ifourierNd () : cnda.fourierNd ());\n        }\n    }\n  else\n    {\n      if (arg.isreal ())\n        {\n          NDArray nda = arg.array_value ();\n\n          nda.resize (dims, 0.0);\n          retval = (type != 0 ? nda.ifourierNd () : nda.fourierNd ());\n        }\n      else if (arg.iscomplex ())\n        {\n          ComplexNDArray cnda = arg.complex_array_value ();\n\n          cnda.resize (dims, 0.0);\n          retval = (type != 0 ? cnda.ifourierNd () : cnda.fourierNd ());\n        }\n      else\n        err_wrong_type_arg (fcn, arg);\n    }\n\n  return retval;\n}\n\nDEFUN (fftn, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{B} =} fftn (@var{A})\n@deftypefnx {} {@var{B} =} fftn (@var{A}, @var{size})\nCompute the N-dimensional discrete Fourier transform of @var{A} using\na Fast Fourier Transform (FFT) algorithm.\n\nThe optional vector argument @var{size} may be used specify the dimensions\nof the array to be used.  If an element of @var{size} is smaller than the\ncorresponding dimension of @var{A}, then the dimension of @var{A} is\ntruncated prior to performing the FFT@.  Otherwise, if an element of\n@var{size} is larger than the corresponding dimension then @var{A} is\nresized and padded with zeros.\n@seealso{ifftn, fft, fft2, fftw}\n@end deftypefn */)\n{\n  return do_fftn (args, \"fftn\", 0);\n}\n\n/*\n%!testif HAVE_FFTW <*65414>\n%! sz = size (fftn (ones (2, 0, 3)));\n%! assert (sz, [2, 0, 3]);\n\n%!testif HAVE_FFTW <*65414>\n%! sz = size (fftn (ones (5, 4, 3), [2, 0, 3]));\n%! assert (sz, [2, 0, 3]);\n*/\n\nDEFUN (ifftn, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{A} =} ifftn (@var{B})\n@deftypefnx {} {@var{A} =} ifftn (@var{B}, @var{size})\nCompute the inverse N-dimensional discrete Fourier transform of @var{B}\nusing a Fast Fourier Transform (FFT) algorithm.\n\nThe optional vector argument @var{size} may be used specify the dimensions\nof the array to be used.  If an element of @var{size} is smaller than the\ncorresponding dimension of @var{B}, then the dimension of @var{B} is\ntruncated prior to performing the inverse FFT@.  Otherwise, if an element of\n@var{size} is larger than the corresponding dimension then @var{B} is\nresized and padded with zeros.\n@seealso{fftn, ifft, ifft2, fftw}\n@end deftypefn */)\n{\n  return do_fftn (args, \"ifftn\", 1);\n}\n\n/*\n%!testif HAVE_FFTW <*65414>\n%! sz = size (ifftn (ones (2, 0, 3)));\n%! assert (sz, [2, 0, 3]);\n\n%!testif HAVE_FFTW <*65414>\n%! sz = size (ifftn (ones (5, 4, 3), [2, 0, 3]));\n%! assert (sz, [2, 0, 3]);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/filter.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Based on Tony Richardson's filter.m.\n//\n// Originally translated to C++ by KH (Kurt.Hornik@wu-wien.ac.at)\n// with help from Fritz Leisch and Andreas Weingessel on Oct 20, 1994.\n//\n// Rewritten to use templates to handle both real and complex cases by\n// jwe, Wed Nov 1 19:15:29 1995.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <type_traits>\n\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Helper functions for fused multiply-add (FMA) operations\n// Use std::fma for real types, regular operations for complex types\n\ntemplate <typename T>\ninline T\nfma_or_mul_add (const T& a, const T& b, const T& c)\n{\n  if constexpr (std::is_floating_point_v<T>)\n    return std::fma (a, b, c);\n  else\n    return a * b + c;\n}\n\ntemplate <typename T>\nMArray<T>\nfilter (MArray<T>& b, MArray<T>& a, MArray<T>& x, MArray<T>& si,\n        int dim = 0)\n{\n  octave_idx_type a_len = a.numel ();\n  octave_idx_type b_len = b.numel ();\n  octave_idx_type ab_len = (a_len > b_len ? a_len : b_len);\n\n  // FIXME: The two lines below should be unnecessary because\n  //        this template is called with a and b as column vectors\n  //        already.  However the a.resize line is currently (2011/04/26)\n  //        necessary to stop bug #33164.\n  b.resize (dim_vector (ab_len, 1), 0.0);\n  if (a_len > 1)\n    a.resize (dim_vector (ab_len, 1), 0.0);\n\n  T norm = a (0);\n  const T zero = static_cast<T> (0);\n\n  if (norm == zero)\n    error (\"filter: the first element of A must be nonzero\");\n\n  const dim_vector& x_dims = x.dims ();\n  if (dim < 0 || dim > x_dims.ndims ())\n    error (\"filter: DIM must be a valid dimension\");\n\n  octave_idx_type x_len = x_dims(dim);\n\n  const dim_vector& si_dims = si.dims ();\n  octave_idx_type si_len = si_dims(0);\n\n  if (si_len != ab_len - 1)\n    error (\"filter: first dimension of SI must be of length max (length (a), length (b)) - 1\");\n\n  if (si_dims.ndims () != x_dims.ndims ())\n    error (\"filter: dimensionality of SI and X must agree\");\n\n  for (octave_idx_type i = 1; i < dim; i++)\n    {\n      if (si_dims(i) != x_dims(i-1))\n        error (\"filter: dimensionality of SI and X must agree\");\n    }\n  for (octave_idx_type i = dim+1; i < x_dims.ndims (); i++)\n    {\n      if (si_dims(i) != x_dims(i))\n        error (\"filter: dimensionality of SI and X must agree\");\n    }\n\n  if (x_len == 0)\n    return x;\n\n  if (norm != static_cast<T> (1.0))\n    {\n      a /= norm;\n      b /= norm;\n    }\n\n  if (a_len <= 1 && si_len <= 0)\n    return b(0) * x;\n\n  // Here onwards, either a_len > 1 or si_len >= 1 or both.\n\n  MArray<T> y;\n  y.resize (x_dims, 0.0);\n\n  octave_idx_type x_stride = 1;\n  for (int i = 0; i < dim; i++)\n    x_stride *= x_dims(i);\n\n  octave_idx_type x_num = x_dims.numel () / x_len;\n  // For deconv and fftfilt, x_num seems to always be 1.\n  // For directly calling filter, it can be more than 1.\n\n  for (octave_idx_type num = 0; num < x_num; num++)\n    {\n      octave_idx_type x_offset = (x_stride == 1) ? num * x_len\n                                 : num + (num / x_stride) * x_stride * (x_len - 1);\n\n      octave_idx_type si_offset = num * si_len;\n\n      octave_idx_type num_execs = si_len-1; // 0 to num_execs-1\n\n      // Define variables here that are common to both the if-block and\n      // the else-block.\n      T *py = y.rwdata ();\n      T *psi = si.rwdata ();\n      const T *pb = b.data ();\n      const T *px = x.data ();\n      psi += si_offset;\n\n      if (a_len > 1)\n        {\n          const T *pa = a.data ();\n\n          // Usually the last element to be written will be si_len-1\n          // but if si_len is 0, then we need the 0th element to be written.\n          // Pulling this check out of the for-loop makes it run faster.\n          octave_idx_type iidx = (si_len > 0) ? si_len-1 : 0;\n\n          for (octave_idx_type i = 0, idx = x_offset;\n               i < x_len;\n               i++, idx += x_stride)\n            {\n              // Use FMA for the output calculation: y = si[0] + b[0]*x\n              py[idx] = fma_or_mul_add (pb[0], px[idx], psi[0]);\n              const T px_val = px[idx];\n              const T py_val = py[idx];\n              const bool px_nonzero = (px_val != zero);\n              const bool py_nonzero = (py_val != zero);\n\n              // Split into cases based on zero/nonzero to avoid a long\n              // sequence of multiplying by zero values.  See bug #67653.\n              // FIXME: Currently the loop is duplicated for performance.\n              // Can this be made fast without duplication? It was reported\n              // in bug #67653 that BLAS axpy is not as fast as these loops.\n              // Maybe test std::transform in future?\n              if (py_nonzero)\n                {\n                  if (px_nonzero)\n                    {\n                      // Compute: psi[j] = psi[j+1] - pa[j+1]*py + pb[j+1]*px\n                      // Use two FMAs: temp = psi[j+1] - pa*py, then result = temp + pb*px\n                      for (octave_idx_type j = 0; j < num_execs; j++)\n                        {\n                          T temp = fma_or_mul_add (-pa[j+1], py_val, psi[j+1]);\n                          psi[j] = fma_or_mul_add (pb[j+1], px_val, temp);\n                        }\n                    }\n                  else\n                    {\n                      // Compute: psi[j] = psi[j+1] - pa[j+1]*py\n                      for (octave_idx_type j = 0; j < num_execs; j++)\n                        psi[j] = fma_or_mul_add (-pa[j+1], py_val, psi[j+1]);\n                    }\n                }\n              else\n                {\n                  if (px_nonzero)\n                    {\n                      // Compute: psi[j] = psi[j+1] + pb[j+1]*px\n                      for (octave_idx_type j = 0; j < num_execs; j++)\n                        psi[j] = fma_or_mul_add (pb[j+1], px_val, psi[j+1]);\n                    }\n                  else\n                    for (octave_idx_type j = 0; j < num_execs; j++)\n                      psi[j] = psi[j+1];\n                }\n\n              // Compute: psi[iidx] = pb[si_len]*px - pa[si_len]*py\n              T temp = fma_or_mul_add (-pa[si_len], py_val, zero);\n              psi[iidx] = fma_or_mul_add (pb[si_len], px_val, temp);\n\n              if ((i & 4095) == 0)  // Check for interruptions every 4096 samples\n                octave_quit();\n            }\n        }\n      else // a_len <= 1 ==> si_len MUST be > 0\n        {\n          // This else-block is almost the same as the above if-block,\n          // except for the absence of variable pa.\n\n          for (octave_idx_type i = 0, idx = x_offset;\n               i < x_len;\n               i++, idx += x_stride)\n            {\n              const T px_val = px[idx];\n              const bool px_nonzero = (px_val != zero);\n\n              // Use FMA for: y = si[0] + b[0]*x\n              py[idx] = fma_or_mul_add (pb[0], px_val, psi[0]);\n\n              if (px_nonzero)\n                {\n                  // Use FMA to compute: psi[j] = psi[j+1] + pb[j+1]*px\n                  for (octave_idx_type j = 0; j < num_execs; j++)\n                    psi[j] = fma_or_mul_add (pb[j+1], px_val, psi[j+1]);\n                }\n              else\n                {\n                  for (octave_idx_type j = 0; j < num_execs; j++)\n                    psi[j] = psi[j+1];\n                }\n\n              psi[si_len-1] = pb[si_len] * px_val;\n\n              if ((i & 4095) == 0)  // Check for interruptions every 4096 samples\n                octave_quit();\n            }\n        }\n    }\n\n  return y;\n}\n\ntemplate <typename T>\nMArray<T>\nfilter (MArray<T>& b, MArray<T>& a, MArray<T>& x, int dim = -1)\n{\n  const dim_vector& x_dims = x.dims ();\n\n  if (dim < 0)\n    dim = x_dims.first_non_singleton ();\n  else if (dim > x_dims.ndims ())\n    error (\"filter: DIM must be a valid dimension\");\n\n  octave_idx_type a_len = a.numel ();\n  octave_idx_type b_len = b.numel ();\n\n  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;\n  dim_vector si_dims = x.dims ();\n  for (int i = dim; i > 0; i--)\n    si_dims(i) = si_dims(i-1);\n  si_dims(0) = si_len;\n\n  MArray<T> si (si_dims, T (0.0));\n\n  return filter (b, a, x, si, dim);\n}\n\nDEFUN (filter, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} filter (@var{b}, @var{a}, @var{x})\n@deftypefnx {} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si})\n@deftypefnx {} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, [], @var{dim})\n@deftypefnx {} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si}, @var{dim})\nApply a 1-D digital filter to the data @var{x}.\n\n@code{filter} returns the solution to the following linear, time-invariant\ndifference equation:\n@tex\n$$\n\\sum_{k=0}^N a_{k+1} y_{n-k} = \\sum_{k=0}^M b_{k+1} x_{n-k}, \\qquad\n 1 \\le n \\le P\n$$\n@end tex\n@ifnottex\n@c Set example in small font to prevent overfull line\n\n@smallexample\n@group\n N                   M\nSUM a(k+1) y(n-k) = SUM b(k+1) x(n-k)    for 1<=n<=length(x)\nk=0                 k=0\n@end group\n@end smallexample\n\n@end ifnottex\n\n@noindent\nwhere\n@ifnottex\nN=length(a)-1 and M=length(b)-1.\n@end ifnottex\n@tex\n$a \\in \\Re^{N-1}$, $b \\in \\Re^{M-1}$, and $x \\in \\Re^P$.\n@end tex\nThe result is calculated over the first non-singleton dimension of @var{x}\nor over @var{dim} if supplied.\n\nAn equivalent form of the equation is:\n@tex\n$$\ny_n = -\\sum_{k=1}^N c_{k+1} y_{n-k} + \\sum_{k=0}^M d_{k+1} x_{n-k}, \\qquad\n 1 \\le n \\le P\n$$\n@end tex\n@ifnottex\n@c Set example in small font to prevent overfull line\n\n@smallexample\n@group\n          N                   M\ny(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k)  for 1<=n<=length(x)\n         k=1                 k=0\n@end group\n@end smallexample\n\n@end ifnottex\n\n@noindent\nwhere\n@ifnottex\n c = a/a(1) and d = b/a(1).\n@end ifnottex\n@tex\n$c = a/a_1$ and $d = b/a_1$.\n@end tex\n\nIf the fourth argument @var{si} is provided, it is taken as the\ninitial state of the system and the final state is returned as\n@var{sf}.  The state vector is a column vector whose length is\nequal to the length of the longest coefficient vector minus one.\nIf @var{si} is not supplied, the initial state vector is set to all\nzeros.\n\nIn terms of the Z Transform, @var{y} is the result of passing the\ndiscrete-time signal @var{x} through a system characterized by the following\nrational system function:\n@tex\n$$\nH(z) = {\\displaystyle\\sum_{k=0}^M d_{k+1} z^{-k}\n        \\over 1 + \\displaystyle\\sum_{k+1}^N c_{k+1} z^{-k}}\n$$\n@end tex\n@ifnottex\n\n@example\n@group\n          M\n         SUM d(k+1) z^(-k)\n         k=0\nH(z) = ---------------------\n            N\n       1 + SUM c(k+1) z^(-k)\n           k=1\n@end group\n@end example\n\n@end ifnottex\n@seealso{filter2, fftfilt, freqz}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 3 || nargin > 5 || nargout > 2)\n    print_usage ();\n\n  int dim;\n  const dim_vector& x_dims = args(2).dims ();\n\n  if (nargin == 5)\n    {\n      dim = args(4).strict_int_value () - 1;\n      if (dim < 0 || dim >= x_dims.ndims ())\n        error (\"filter: DIM must be a valid dimension\");\n    }\n  else\n    dim = x_dims.first_non_singleton ();\n\n  octave_value_list retval ((nargout <= 1) ? 1 : 2);\n\n  const char *a_b_errmsg = \"filter: A and B must be vectors\";\n  const char *x_si_errmsg = \"filter: X and SI must be arrays\";\n\n  bool isfloat = (args(0).is_single_type ()\n                  || args(1).is_single_type ()\n                  || args(2).is_single_type ()\n                  || (nargin >= 4 && args(3).is_single_type ()));\n\n  if (args(0).iscomplex ()\n      || args(1).iscomplex ()\n      || args(2).iscomplex ()\n      || (nargin >= 4 && args(3).iscomplex ()))\n    {\n      if (isfloat)\n        {\n          FloatComplexColumnVector b = args(0).xfloat_complex_vector_value (a_b_errmsg);\n          FloatComplexColumnVector a = args(1).xfloat_complex_vector_value (a_b_errmsg);\n          FloatComplexNDArray x = args(2).xfloat_complex_array_value (x_si_errmsg);\n\n          FloatComplexNDArray si;\n\n          if (nargin == 3 || args(3).isempty ())\n            {\n              octave_idx_type a_len = a.numel ();\n              octave_idx_type b_len = b.numel ();\n\n              octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;\n\n              dim_vector si_dims = x.dims ();\n              for (int i = dim; i > 0; i--)\n                si_dims(i) = si_dims(i-1);\n              si_dims(0) = si_len;\n\n              si.resize (si_dims, 0.0);\n            }\n          else\n            {\n              si = args(3).xfloat_complex_array_value (x_si_errmsg);\n\n              if (si.isvector () && x.isvector ())\n                si = si.reshape (dim_vector (si.numel (), 1));\n            }\n\n          FloatComplexNDArray y (filter (b, a, x, si, dim));\n\n          retval(0) = y;\n          if (nargout > 1)\n            retval(1) = si;\n        }\n      else\n        {\n          ComplexColumnVector b = args(0).xcomplex_vector_value (a_b_errmsg);\n          ComplexColumnVector a = args(1).xcomplex_vector_value (a_b_errmsg);\n\n          ComplexNDArray x = args(2).xcomplex_array_value (x_si_errmsg);\n\n          ComplexNDArray si;\n\n          if (nargin == 3 || args(3).isempty ())\n            {\n              octave_idx_type a_len = a.numel ();\n              octave_idx_type b_len = b.numel ();\n\n              octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;\n\n              dim_vector si_dims = x.dims ();\n              for (int i = dim; i > 0; i--)\n                si_dims(i) = si_dims(i-1);\n              si_dims(0) = si_len;\n\n              si.resize (si_dims, 0.0);\n            }\n          else\n            {\n              si = args(3).xcomplex_array_value (x_si_errmsg);\n\n              if (si.isvector () && x.isvector ())\n                si = si.reshape (dim_vector (si.numel (), 1));\n            }\n\n          ComplexNDArray y (filter (b, a, x, si, dim));\n\n          retval(0) = y;\n          if (nargout > 1)\n            retval(1) = si;\n        }\n    }\n  else\n    {\n      if (isfloat)\n        {\n          FloatColumnVector b = args(0).xfloat_vector_value (a_b_errmsg);\n          FloatColumnVector a = args(1).xfloat_vector_value (a_b_errmsg);\n\n          FloatNDArray x = args(2).xfloat_array_value (x_si_errmsg);\n\n          FloatNDArray si;\n\n          if (nargin == 3 || args(3).isempty ())\n            {\n              octave_idx_type a_len = a.numel ();\n              octave_idx_type b_len = b.numel ();\n\n              octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;\n\n              dim_vector si_dims = x.dims ();\n              for (int i = dim; i > 0; i--)\n                si_dims(i) = si_dims(i-1);\n              si_dims(0) = si_len;\n\n              si.resize (si_dims, 0.0);\n            }\n          else\n            {\n              si = args(3).xfloat_array_value (x_si_errmsg);\n\n              if (si.isvector () && x.isvector ())\n                si = si.reshape (dim_vector (si.numel (), 1));\n            }\n\n          FloatNDArray y (filter (b, a, x, si, dim));\n\n          retval(0) = y;\n          if (nargout > 1)\n            retval(1) = si;\n        }\n      else\n        {\n          ColumnVector b = args(0).xvector_value (a_b_errmsg);\n          ColumnVector a = args(1).xvector_value (a_b_errmsg);\n\n          NDArray x = args(2).xarray_value (x_si_errmsg);\n\n          NDArray si;\n\n          if (nargin == 3 || args(3).isempty ())\n            {\n              octave_idx_type a_len = a.numel ();\n              octave_idx_type b_len = b.numel ();\n\n              octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;\n\n              dim_vector si_dims = x.dims ();\n              for (int i = dim; i > 0; i--)\n                si_dims(i) = si_dims(i-1);\n              si_dims(0) = si_len;\n\n              si.resize (si_dims, 0.0);\n            }\n          else\n            {\n              si = args(3).xarray_value (x_si_errmsg);\n\n              if (si.isvector () && x.isvector ())\n                si = si.reshape (dim_vector (si.numel (), 1));\n            }\n\n          NDArray y (filter (b, a, x, si, dim));\n\n          retval(0) = y;\n          if (nargout > 1)\n            retval(1) = si;\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!shared a, b, x, r\n%!test\n%! a = [1 1];\n%! b = [1 1];\n%! x = zeros (1,10);  x(1) = 1;\n%! assert (filter (b,   [1], x  ), [1 1 0 0 0 0 0 0 0 0]);\n%! assert (filter (b,   [1], x.'), [1 1 0 0 0 0 0 0 0 0].');\n%! assert (filter (b.', [1], x  ), [1 1 0 0 0 0 0 0 0 0]  );\n%! assert (filter (b.', [1], x.'), [1 1 0 0 0 0 0 0 0 0].');\n%! assert (filter ([1], a,   x  ), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1]  );\n%! assert (filter ([1], a,   x.'), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1].');\n%! assert (filter ([1], a.', x  ), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1]  );\n%! assert (filter ([1], a.', x.'), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1].');\n%! assert (filter (b,   a,   x  ), [1 0 0 0 0 0 0 0 0 0]  );\n%! assert (filter (b.', a,   x  ), [1 0 0 0 0 0 0 0 0 0]  );\n%! assert (filter (b,   a.', x  ), [1 0 0 0 0 0 0 0 0 0]  );\n%! assert (filter (b.', a,   x  ), [1 0 0 0 0 0 0 0 0 0]  );\n%! assert (filter (b,   a,   x.'), [1 0 0 0 0 0 0 0 0 0].');\n%! assert (filter (b.', a,   x.'), [1 0 0 0 0 0 0 0 0 0].');\n%! assert (filter (b,   a.', x.'), [1 0 0 0 0 0 0 0 0 0].');\n%! assert (filter (b.', a,   x.'), [1 0 0 0 0 0 0 0 0 0].');\n\n%!test\n%! r = sqrt (1/2) * (1+i);\n%! a = a*r;\n%! b = b*r;\n%! assert (filter (b, [1], x   ), r*[1 1 0 0 0 0 0 0 0 0]  , eps);\n%! assert (filter (b, [1], r*x ), r*r*[1 1 0 0 0 0 0 0 0 0], eps);\n%! assert (filter (b, [1], x.' ), r*[1 1 0 0 0 0 0 0 0 0].', eps);\n%! assert (filter (b, a,   x   ),   [1 0 0 0 0 0 0 0 0 0],   eps);\n%! assert (filter (b, a,   r*x ), r*[1 0 0 0 0 0 0 0 0 0],   eps);\n\n%!shared a, b, x, y, so\n%!test\n%! a = [1,1];\n%! b = [1,1];\n%! x = zeros (1,10);  x(1) = 1;\n%! [y, so] = filter (b, [1], x, [-1]);\n%! assert (y, [0 1 0 0 0 0 0 0 0 0]);\n%! assert (so, 0);\n\n%!test\n%! x  = zeros (10,3);  x(1,1) = -1;  x(1,2) = 1;\n%! y0 = zeros (10,3); y0(1:2,1) = -1;  y0(1:2,2) = 1;\n%! y = filter (b, [1], x);\n%! assert (y, y0);\n\n%!test\n%! a = [1,1];\n%! b=[1,1];\n%! x = zeros (4,4,2);  x(1,1:4,1) = +1;  x(1,1:4,2) = -1;\n%! y0 = zeros (4,4,2);  y0(1:2,1:4,1) = +1;  y0(1:2,1:4,2) = -1;\n%! y = filter (b, [1], x);\n%! assert (y, y0);\n\n%!assert (filter (1, ones (10,1) / 10, []), [])\n%!assert (filter (1, ones (10,1) / 10, zeros (0,10)), zeros (0,10))\n%!assert (filter (1, ones (10,1) / 10, single (1:5)),\n%!        repmat (single (10), 1, 5))\n\n## Test using initial conditions\n%!assert (filter ([1, 1, 1], [1, 1], [1 2], [1, 1]), [2 2])\n%!assert (filter ([1, 1, 1], [1, 1], [1 2], [1, 1]'), [2 2])\n%!assert (filter ([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]), [5 7; 6 10; 14 18])\n%!error filter ([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]')\n%!assert (filter ([1, 3, 2], [1], [1 2; 3 4; 5 6], [1 0 0; 1 0 0], 2),\n%!        [2 6; 3 13; 5 21])\n\n## Test of DIM parameter\n%!test\n%! x = ones (2, 1, 3, 4);\n%! x(1,1,:,:) = [1 2 3 4; 5 6 7 8; 9 10 11 12];\n%! y0 = [1 1 6 2 15 3 2 1 8 2 18 3 3 1 10 2 21 3 4 1 12 2 24 3];\n%! y0 = reshape (y0, size (x));\n%! y = filter ([1 1 1], 1, x, [], 3);\n%! assert (y, y0);\n*/\n\ntemplate MArray<double>\nfilter (MArray<double>&, MArray<double>&, MArray<double>&,\n        MArray<double>&, int dim);\n\ntemplate MArray<double>\nfilter (MArray<double>&, MArray<double>&, MArray<double>&, int dim);\n\ntemplate MArray<Complex>\nfilter (MArray<Complex>&, MArray<Complex>&, MArray<Complex>&,\n        MArray<Complex>&, int dim);\n\ntemplate MArray<Complex>\nfilter (MArray<Complex>&, MArray<Complex>&, MArray<Complex>&, int dim);\n\ntemplate MArray<float>\nfilter (MArray<float>&, MArray<float>&, MArray<float>&,\n        MArray<float>&, int dim);\n\ntemplate MArray<float>\nfilter (MArray<float>&, MArray<float>&, MArray<float>&, int dim);\n\ntemplate MArray<FloatComplex>\nfilter (MArray<FloatComplex>&, MArray<FloatComplex>&, MArray<FloatComplex>&,\n        MArray<FloatComplex>&, int dim);\n\ntemplate MArray<FloatComplex>\nfilter (MArray<FloatComplex>&, MArray<FloatComplex>&, MArray<FloatComplex>&,\n        int dim);\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/gcd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"CNDArray.h\"\n#include \"dNDArray.h\"\n#include \"fCNDArray.h\"\n#include \"fNDArray.h\"\n#include \"mappers.h\"\n#include \"oct-binmap.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic double\nsimple_gcd (double a, double b)\n{\n  if (! math::is_integer (a) || ! math::is_integer (b))\n    error (\"gcd: all values must be integers\");\n\n  double aa = fabs (a);\n  double bb = fabs (b);\n\n  while (bb != 0)\n    {\n      double tt = fmod (aa, bb);\n      aa = bb;\n      bb = tt;\n    }\n\n  return aa;\n}\n\ntemplate <typename FP>\nstatic void\ndivide (const std::complex<FP>& a, const std::complex<FP>& b,\n        std::complex<FP>& q, std::complex<FP>& r)\n{\n  FP qr = std::floor ((a/b).real () + 0.5);\n  FP qi = std::floor ((a/b).imag () + 0.5);\n\n  q = std::complex<FP> (qr, qi);\n\n  r = a - q*b;\n}\n\ntemplate <typename FP>\nstatic std::complex<FP>\nsimple_gcd (const std::complex<FP>& a, const std::complex<FP>& b)\n{\n  if (! math::is_integer (a.real ())\n      || ! math::is_integer (a.imag ())\n      || ! math::is_integer (b.real ())\n      || ! math::is_integer (b.imag ()))\n    error (\"gcd: all complex parts must be integers\");\n\n  std::complex<FP> aa = a;\n  std::complex<FP> bb = b;\n\n  if (abs (aa) < abs (bb))\n    std::swap (aa, bb);\n\n  while (abs (bb) != 0)\n    {\n      std::complex<FP> qq, rr;\n      divide (aa, bb, qq, rr);\n      aa = bb;\n      bb = rr;\n    }\n\n  return aa;\n}\n\ntemplate <typename T>\nstatic octave_int<T>\nsimple_gcd (const octave_int<T>& a, const octave_int<T>& b)\n{\n  T aa = a.abs ().value ();\n  T bb = b.abs ().value ();\n\n  while (bb != 0)\n    {\n      T tt = aa % bb;\n      aa = bb;\n      bb = tt;\n    }\n\n  return aa;\n}\n\nstatic double\nextended_gcd (double a, double b, double& x, double& y)\n{\n  if (! math::is_integer (a) || ! math::is_integer (b))\n    error (\"gcd: all values must be integers\");\n\n  double aa = fabs (a);\n  double bb = fabs (b);\n\n  double xx, lx, yy, ly;\n  xx = 0, lx = 1;\n  yy = 1, ly = 0;\n\n  while (bb != 0)\n    {\n      double qq = std::floor (aa / bb);\n      double tt = fmod (aa, bb);\n\n      aa = bb;\n      bb = tt;\n\n      double tx = lx - qq*xx;\n      lx = xx;\n      xx = tx;\n\n      double ty = ly - qq*yy;\n      ly = yy;\n      yy = ty;\n    }\n\n  x = (a >= 0 ? lx : -lx);\n  y = (b >= 0 ? ly : -ly);\n\n  return aa;\n}\n\ntemplate <typename FP>\nstatic std::complex<FP>\nextended_gcd (const std::complex<FP>& a, const std::complex<FP>& b,\n              std::complex<FP>& x, std::complex<FP>& y)\n{\n  if (! math::is_integer (a.real ())\n      || ! math::is_integer (a.imag ())\n      || ! math::is_integer (b.real ())\n      || ! math::is_integer (b.imag ()))\n    error (\"gcd: all complex parts must be integers\");\n\n  std::complex<FP> aa = a;\n  std::complex<FP> bb = b;\n  bool swapped = false;\n  if (abs (aa) < abs (bb))\n    {\n      std::swap (aa, bb);\n      swapped = true;\n    }\n\n  std::complex<FP> xx, lx, yy, ly;\n  xx = 0, lx = 1;\n  yy = 1, ly = 0;\n\n  while (abs(bb) != 0)\n    {\n      std::complex<FP> qq, rr;\n      divide (aa, bb, qq, rr);\n      aa = bb;\n      bb = rr;\n\n      std::complex<FP> tx = lx - qq*xx;\n      lx = xx;\n      xx = tx;\n\n      std::complex<FP> ty = ly - qq*yy;\n      ly = yy;\n      yy = ty;\n    }\n\n  x = lx;\n  y = ly;\n\n  if (swapped)\n    std::swap (x, y);\n\n  return aa;\n}\n\ntemplate <typename T>\nstatic octave_int<T>\nextended_gcd (const octave_int<T>& a, const octave_int<T>& b,\n              octave_int<T>& x, octave_int<T>& y)\n{\n  T aa = a.abs ().value ();\n  T bb = b.abs ().value ();\n  T xx, lx, yy, ly;\n  xx = 0, lx = 1;\n  yy = 1, ly = 0;\n\n  while (bb != 0)\n    {\n      T qq = aa / bb;\n      T tt = aa % bb;\n      aa = bb;\n      bb = tt;\n\n      T tx = lx - qq*xx;\n      lx = xx;\n      xx = tx;\n\n      T ty = ly - qq*yy;\n      ly = yy;\n      yy = ty;\n    }\n\n  x = octave_int<T> (lx) * a.signum ();\n  y = octave_int<T> (ly) * b.signum ();\n\n  return aa;\n}\n\ntemplate <typename NDA>\nstatic octave_value\ndo_simple_gcd (const octave_value& a, const octave_value& b)\n{\n  typedef typename NDA::element_type T;\n  octave_value retval;\n\n  if (a.is_scalar_type () && b.is_scalar_type ())\n    {\n      // Optimize scalar case.\n      T aa = octave_value_extract<T> (a);\n      T bb = octave_value_extract<T> (b);\n      retval = simple_gcd (aa, bb);\n    }\n  else\n    {\n      NDA aa = octave_value_extract<NDA> (a);\n      NDA bb = octave_value_extract<NDA> (b);\n      retval = binmap<T> (aa, bb, simple_gcd, \"gcd\");\n    }\n\n  return retval;\n}\n\n// Dispatcher\nstatic octave_value\ndo_simple_gcd (const octave_value& a, const octave_value& b)\n{\n  octave_value retval;\n  builtin_type_t btyp = btyp_mixed_numeric (a.builtin_type (),\n                        b.builtin_type ());\n  switch (btyp)\n    {\n    case btyp_double:\n      if (a.issparse () && b.issparse ())\n        {\n          retval = do_simple_gcd<SparseMatrix> (a, b);\n          break;\n        }\n      OCTAVE_FALLTHROUGH;\n\n    case btyp_float:\n      retval = do_simple_gcd<NDArray> (a, b);\n      break;\n\n#define MAKE_INT_BRANCH(X)                            \\\n    case btyp_ ## X:                                  \\\n      retval = do_simple_gcd<X ## NDArray> (a, b);    \\\n      break\n\n      MAKE_INT_BRANCH (int8);\n      MAKE_INT_BRANCH (int16);\n      MAKE_INT_BRANCH (int32);\n      MAKE_INT_BRANCH (int64);\n      MAKE_INT_BRANCH (uint8);\n      MAKE_INT_BRANCH (uint16);\n      MAKE_INT_BRANCH (uint32);\n      MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n    case btyp_complex:\n      retval = do_simple_gcd<ComplexNDArray> (a, b);\n      break;\n\n    case btyp_float_complex:\n      retval = do_simple_gcd<FloatComplexNDArray> (a, b);\n      break;\n\n    default:\n      error (\"gcd: invalid class combination for gcd: %s and %s\\n\",\n             a.class_name ().c_str (), b.class_name ().c_str ());\n    }\n\n  if (btyp == btyp_float)\n    retval = retval.float_array_value ();\n\n  return retval;\n}\n\ntemplate <typename NDA>\nstatic octave_value\ndo_extended_gcd (const octave_value& a, const octave_value& b,\n                 octave_value& x, octave_value& y)\n{\n  typedef typename NDA::element_type T;\n  octave_value retval;\n\n  if (a.is_scalar_type () && b.is_scalar_type ())\n    {\n      // Optimize scalar case.\n      T aa = octave_value_extract<T> (a);\n      T bb = octave_value_extract<T> (b);\n      T xx, yy;\n      retval = extended_gcd (aa, bb, xx, yy);\n      x = xx;\n      y = yy;\n    }\n  else\n    {\n      NDA aa = octave_value_extract<NDA> (a);\n      NDA bb = octave_value_extract<NDA> (b);\n\n      dim_vector dv = aa.dims ();\n      if (aa.numel () == 1)\n        dv = bb.dims ();\n      else if (bb.numel () != 1 && bb.dims () != dv)\n        err_nonconformant (\"gcd\", a.dims (), b.dims ());\n\n      NDA gg (dv), xx (dv), yy (dv);\n\n      const T *aptr = aa.data ();\n      const T *bptr = bb.data ();\n\n      bool inca = aa.numel () != 1;\n      bool incb = bb.numel () != 1;\n\n      T *gptr = gg.rwdata ();\n      T *xptr = xx.rwdata ();\n      T *yptr = yy.rwdata ();\n\n      octave_idx_type n = gg.numel ();\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          octave_quit ();\n\n          *gptr++ = extended_gcd (*aptr, *bptr, *xptr++, *yptr++);\n\n          aptr += inca;\n          bptr += incb;\n        }\n\n      x = xx;\n      y = yy;\n\n      retval = gg;\n    }\n\n  return retval;\n}\n\n// Dispatcher\nstatic octave_value\ndo_extended_gcd (const octave_value& a, const octave_value& b,\n                 octave_value& x, octave_value& y)\n{\n  octave_value retval;\n\n  builtin_type_t btyp = btyp_mixed_numeric (a.builtin_type (),\n                        b.builtin_type ());\n  switch (btyp)\n    {\n    case btyp_double:\n    case btyp_float:\n      retval = do_extended_gcd<NDArray> (a, b, x, y);\n      break;\n\n#define MAKE_INT_BRANCH(X)                                    \\\n    case btyp_ ## X:                                          \\\n      retval = do_extended_gcd<X ## NDArray> (a, b, x, y);    \\\n      break\n\n      MAKE_INT_BRANCH (int8);\n      MAKE_INT_BRANCH (int16);\n      MAKE_INT_BRANCH (int32);\n      MAKE_INT_BRANCH (int64);\n      MAKE_INT_BRANCH (uint8);\n      MAKE_INT_BRANCH (uint16);\n      MAKE_INT_BRANCH (uint32);\n      MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n    case btyp_complex:\n      retval = do_extended_gcd<ComplexNDArray> (a, b, x, y);\n      break;\n\n    case btyp_float_complex:\n      retval = do_extended_gcd<FloatComplexNDArray> (a, b, x, y);\n      break;\n\n    default:\n      error (\"gcd: invalid class combination for gcd: %s and %s\\n\",\n             a.class_name ().c_str (), b.class_name ().c_str ());\n    }\n\n  // For consistency.\n  if (a.issparse () && b.issparse ())\n    {\n      retval = retval.sparse_matrix_value ();\n      x = x.sparse_matrix_value ();\n      y = y.sparse_matrix_value ();\n    }\n\n  if (btyp == btyp_float)\n    {\n      retval = retval.float_array_value ();\n      x = x.float_array_value ();\n      y = y.float_array_value ();\n    }\n\n  return retval;\n}\n\nDEFUN (gcd, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{g} =} gcd (@var{a1}, @var{a2}, @dots{})\n@deftypefnx {} {[@var{g}, @var{v1}, @dots{}] =} gcd (@var{a1}, @var{a2}, @dots{})\nCompute the greatest common divisor of @var{a1}, @var{a2}, @enddots{}\n\nAll arguments must be the same size or scalar.  For arrays, the greatest common\ndivisor is calculated for each element individually.  All elements must be\nordinary or Gaussian (complex) integers.  Note that for Gaussian integers, the\ngcd is only unique up to a phase factor (multiplication by 1, -1, i, or -i), so\nan arbitrary greatest common divisor among the four possible is returned.\n\nOptional return arguments @var{v1}, @dots{}, contain integer vectors such\nthat,\n@tex\n$g = v_1 a_1 + v_2 a_2 + \\cdots$\n@end tex\n@ifnottex\n\n@example\n@var{g} = @var{v1} .* @var{a1} + @var{v2} .* @var{a2} + @dots{}\n@end example\n\n@end ifnottex\n\nExample code:\n\n@example\n@group\ngcd ([15, 9], [20, 18])\n   @xresult{}  5  9\n@end group\n@end example\n\nProgramming tip: To find the GCD of all the elements of a single array, use\n@code{num2cell} instead of nested calls or a loop:\n\n@example\n@group\nx = [30 42 70 105];    # vector or array of inputs\ngcd (num2cell (x) @{:@})\n   @xresult{}     1\n@end group\n@end example\n\n@seealso{lcm, factor, isprime}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  octave_value_list retval;\n\n  if (nargout > 1)\n    {\n      retval.resize (nargin + 1);\n\n      retval(0) = do_extended_gcd (args(0), args(1), retval(1), retval(2));\n\n      for (int j = 2; j < nargin; j++)\n        {\n          octave_value x;\n          retval(0) = do_extended_gcd (retval(0), args(j), x, retval(j+1));\n          for (int i = 0; i < j; i++)\n            retval(i+1).assign (octave_value::op_el_mul_eq, x);\n        }\n    }\n  else\n    {\n      retval(0) = do_simple_gcd (args(0), args(1));\n\n      for (int j = 2; j < nargin; j++)\n        retval(0) = do_simple_gcd (retval(0), args(j));\n    }\n\n  return retval;\n}\n\n/*\n%!assert (gcd (200, 300, 50, 35), 5)\n%!assert (gcd (int16 (200), int16 (300), int16 (50), int16 (35)), int16 (5))\n%!assert (gcd (uint64 (200), uint64 (300), uint64 (50), uint64 (35)),\n%!        uint64 (5))\n%!assert (gcd (18-i, -29+3i), -3-4i)\n\n%!test\n%! p = [953 967];\n%! u = [953 + i*971, 967 + i*977];\n%! [d, k(1), k(2)] = gcd (p(1), p(2));\n%! [z, w(1), w(2)] = gcd (u(1), u(2));\n%! assert (d, 1);\n%! assert (sum (p.*k), d);\n%! assert (abs (z), sqrt (2));\n%! assert (abs (sum (u.*w)), sqrt (2));\n\n%!error <all values must be integers> gcd (1/2, 2)\n%!error <all complex parts must be integers> gcd (e + i*pi, 1)\n\n%!error gcd ()\n\n%!test\n%! s.a = 1;\n%! fail (\"gcd (s)\");\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/givens.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Originally written by A. S. Hodel <scotte@eng.auburn.edu>\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (givens, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{G} =} givens (@var{x}, @var{y})\n@deftypefnx {} {[@var{c}, @var{s}] =} givens (@var{x}, @var{y})\nCompute the Givens rotation matrix @var{G}.\n@tex\nThe Givens matrix is a $2\\times 2$ orthogonal matrix\n$$\n G = \\left[\\matrix{c & s\\cr -s'& c\\cr}\\right]\n$$\nsuch that\n$$\n G \\left[\\matrix{x\\cr y}\\right] = \\left[\\matrix{\\ast\\cr 0}\\right]\n$$\nwith $x$ and $y$ scalars.\n@end tex\n@ifnottex\nThe Givens matrix is a 2-by-2 orthogonal matrix\n\n@example\n@group\n@var{G} = [ @var{c} , @var{s}\n     -@var{s}', @var{c}]\n@end group\n@end example\n\n@noindent\nsuch that\n\n@example\n@var{G} * [@var{x}; @var{y}] = [*; 0]\n@end example\n\n@noindent\nwith @var{x} and @var{y} scalars.\n@end ifnottex\n\nIf two output arguments are requested, return the factors @var{c} and @var{s}\nrather than the Givens rotation matrix.\n\nFor example:\n\n@example\n@group\ngivens (1, 1)\n   @xresult{}   0.70711   0.70711\n       -0.70711   0.70711\n@end group\n@end example\n\nNote: The Givens matrix represents a counterclockwise rotation of a 2-D\nplane and can be used to introduce zeros into a matrix prior to complete\nfactorization.\n@seealso{planerot, qr}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value_list retval;\n\n  if (args(0).is_single_type () || args(1).is_single_type ())\n    {\n      if (args(0).iscomplex () || args(1).iscomplex ())\n        {\n          FloatComplex cx = args(0).float_complex_value ();\n          FloatComplex cy = args(1).float_complex_value ();\n\n          FloatComplexMatrix result = Givens (cx, cy);\n\n          switch (nargout)\n            {\n            case 0:\n            case 1:\n              retval = ovl (result);\n              break;\n\n            case 2:\n              retval = ovl (result(0, 0), result(0, 1));\n              break;\n            }\n        }\n      else\n        {\n          float x = args(0).float_value ();\n          float y = args(1).float_value ();\n\n          FloatMatrix result = Givens (x, y);\n\n          switch (nargout)\n            {\n            case 0:\n            case 1:\n              retval = ovl (result);\n              break;\n\n            case 2:\n              retval = ovl (result(0, 0), result(0, 1));\n              break;\n            }\n        }\n    }\n  else\n    {\n      if (args(0).iscomplex () || args(1).iscomplex ())\n        {\n          Complex cx = args(0).complex_value ();\n          Complex cy = args(1).complex_value ();\n\n          ComplexMatrix result = Givens (cx, cy);\n\n          switch (nargout)\n            {\n            case 0:\n            case 1:\n              retval = ovl (result);\n              break;\n\n            case 2:\n              retval = ovl (result(0, 0), result(0, 1));\n              break;\n            }\n        }\n      else\n        {\n          double x = args(0).double_value ();\n          double y = args(1).double_value ();\n\n          Matrix result = Givens (x, y);\n\n          switch (nargout)\n            {\n            case 0:\n            case 1:\n              retval = ovl (result);\n              break;\n\n            case 2:\n              retval = ovl (result(0, 0), result(0, 1));\n              break;\n            }\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!assert (givens (1,1), [1, 1; -1, 1] / sqrt (2), 2*eps)\n%!assert (givens (1,0), eye (2))\n%!assert (givens (0,1), [0, 1; -1 0])\n\n%!error givens ()\n%!error givens (1)\n%!error [a,b,c] = givens (1, 1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/gsvd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1997-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"dMatrix.h\"\n#include \"CMatrix.h\"\n#include \"dDiagMatrix.h\"\n#include \"gsvd.h\"\n\n#include \"defun.h\"\n#include \"defun-int.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"utils.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T>\nstatic typename math::gsvd<T>::Type\ngsvd_type (int nargout, int nargin)\n{\n  if (nargout == 0 || nargout == 1)\n    return octave::math::gsvd<T>::Type::sigma_only;\n  else if (nargin < 3)\n    return octave::math::gsvd<T>::Type::std;\n  else\n    return octave::math::gsvd<T>::Type::economy;\n}\n\n// Named do_gsvd to avoid conflicts with the gsvd class itself.\ntemplate <typename T>\nstatic octave_value_list\ndo_gsvd (const T& A, const T& B,\n         const octave_idx_type nargout, const octave_idx_type nargin,\n         bool is_single = false)\n{\n  math::gsvd<T> result (A, B, gsvd_type<T> (nargout, nargin));\n\n  octave_value_list retval (nargout);\n  if (nargout <= 1)\n    {\n      if (is_single)\n        {\n          FloatMatrix sigA = result.singular_values_A ();\n          FloatMatrix sigB = result.singular_values_B ();\n          for (int i = sigA.rows () - 1; i >= 0; i--)\n            sigA.xelem (i) /= sigB.xelem (i);\n          retval(0) = sigA.sort ();\n        }\n      else\n        {\n          Matrix sigA = result.singular_values_A ();\n          Matrix sigB = result.singular_values_B ();\n          for (int i = sigA.rows () - 1; i >= 0; i--)\n            sigA.xelem (i) /= sigB.xelem (i);\n          retval(0) = sigA.sort ();\n        }\n    }\n  else\n    {\n      switch (nargout)\n        {\n        case 5:\n          retval(4) = result.singular_values_B ();\n          OCTAVE_FALLTHROUGH;\n\n        case 4:\n          retval(3) = result.singular_values_A ();\n          OCTAVE_FALLTHROUGH;\n\n        case 3:\n          retval(2) = result.right_singular_matrix ();\n        }\n\n      retval(1) = result.left_singular_matrix_B ();\n      retval(0) = result.left_singular_matrix_A ();\n    }\n\n  return retval;\n}\n\nDEFUN (gsvd, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{S} =} gsvd (@var{A}, @var{B})\n@deftypefnx {} {[@var{U}, @var{V}, @var{X}, @var{C}, @var{S}] =} gsvd (@var{A}, @var{B})\n@deftypefnx {} {[@var{U}, @var{V}, @var{X}, @var{C}, @var{S}] =} gsvd (@var{A}, @var{B}, 0)\nCompute the generalized singular value decomposition of (@var{A}, @var{B}).\n\nThe generalized singular value decomposition is defined by the following\nrelations:\n@tex\n$$ A = U C X^\\dagger $$\n$$ B = V S X^\\dagger $$\n$$ C^\\dagger C + S^\\dagger S = eye (columns (A)) $$\n@end tex\n@ifnottex\n\n@example\n@group\nA = U*C*X'\nB = V*S*X'\nC'*C + S'*S = eye (columns (A))\n@end group\n@end example\n\n@end ifnottex\n\nThe function @code{gsvd} normally returns just the vector of generalized\nsingular values\n@tex\n$$ \\sqrt{{{diag (C^\\dagger C)} \\over {diag (S^\\dagger S)}}} $$\n@end tex\n@ifnottex\n@code{sqrt (diag (C'*C) ./ diag (S'*S))}.\n@end ifnottex\nIf asked for five return values, it also computes\n@tex\n$U$, $V$, $X$, and $C$.\n@end tex\n@ifnottex\nU, V, X, and C.\n@end ifnottex\n\nIf the optional third input is present, @code{gsvd} constructs the\n\"economy-sized\" decomposition where the number of columns of @var{U}, @var{V}\nand the number of rows of @var{C}, @var{S} is less than or equal to the number\nof columns of @var{A}.  This option is not yet implemented.\n\nProgramming Note: the code is a wrapper to the corresponding @sc{lapack} dggsvd\nand zggsvd routines.  If matrices @var{A} and @var{B} are @emph{both} rank\ndeficient then @sc{lapack} will return an incorrect factorization.  Programmers\nshould avoid this combination.\n@seealso{svd}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n  else if (nargin == 3)\n    {\n      // FIXME: when \"economy\" is implemented delete this code\n      warning (\"gsvd: economy-sized decomposition is not yet implemented, returning full decomposition\");\n      nargin = 2;\n    }\n\n  octave_value_list retval;\n\n  octave_value argA = args(0);\n  octave_value argB = args(1);\n\n  if (argA.columns () != argB.columns ())\n    error (\"gsvd: A and B must have the same number of columns\");\n\n  if (argA.is_single_type () || argB.is_single_type ())\n    {\n      if (argA.isreal () && argB.isreal ())\n        {\n          FloatMatrix tmpA = argA.xfloat_matrix_value (\"gsvd: A must be a real or complex matrix\");\n          FloatMatrix tmpB = argB.xfloat_matrix_value (\"gsvd: B must be a real or complex matrix\");\n\n          if (tmpA.any_element_is_inf_or_nan ())\n            error (\"gsvd: A cannot have Inf or NaN values\");\n          if (tmpB.any_element_is_inf_or_nan ())\n            error (\"gsvd: B cannot have Inf or NaN values\");\n\n          retval = do_gsvd (tmpA, tmpB, nargout, nargin, true);\n        }\n      else if (argA.iscomplex () || argB.iscomplex ())\n        {\n          FloatComplexMatrix ctmpA =\n            argA.xfloat_complex_matrix_value (\"gsvd: A must be a real or complex matrix\");\n          FloatComplexMatrix ctmpB =\n            argB.xfloat_complex_matrix_value (\"gsvd: B must be a real or complex matrix\");\n\n          if (ctmpA.any_element_is_inf_or_nan ())\n            error (\"gsvd: A cannot have Inf or NaN values\");\n          if (ctmpB.any_element_is_inf_or_nan ())\n            error (\"gsvd: B cannot have Inf or NaN values\");\n\n          retval = do_gsvd (ctmpA, ctmpB, nargout, nargin, true);\n        }\n      else\n        error (\"gsvd: A and B must be real or complex matrices\");\n    }\n  else\n    {\n      if (argA.isreal () && argB.isreal ())\n        {\n          Matrix tmpA = argA.xmatrix_value (\"gsvd: A must be a real or complex matrix\");\n          Matrix tmpB = argB.xmatrix_value (\"gsvd: B must be a real or complex matrix\");\n\n          if (tmpA.any_element_is_inf_or_nan ())\n            error (\"gsvd: A cannot have Inf or NaN values\");\n          if (tmpB.any_element_is_inf_or_nan ())\n            error (\"gsvd: B cannot have Inf or NaN values\");\n\n          retval = do_gsvd (tmpA, tmpB, nargout, nargin);\n        }\n      else if (argA.iscomplex () || argB.iscomplex ())\n        {\n          ComplexMatrix ctmpA = argA.xcomplex_matrix_value (\"gsvd: A must be a real or complex matrix\");\n          ComplexMatrix ctmpB = argB.xcomplex_matrix_value (\"gsvd: B must be a real or complex matrix\");\n\n          if (ctmpA.any_element_is_inf_or_nan ())\n            error (\"gsvd: A cannot have Inf or NaN values\");\n          if (ctmpB.any_element_is_inf_or_nan ())\n            error (\"gsvd: B cannot have Inf or NaN values\");\n\n          retval = do_gsvd (ctmpA, ctmpB, nargout, nargin);\n        }\n      else\n        error (\"gsvd: A and B must be real or complex matrices\");\n    }\n\n  return retval;\n}\n\n/*\n\n## Basic tests of decomposition\n%!test <60273>\n%! A = reshape (1:15,5,3);\n%! B = magic (3);\n%! [U,V,X,C,S] = gsvd (A,B);\n%! assert (size (U), [5, 5]);\n%! assert (size (V), [3, 3]);\n%! assert (size (X), [3, 3]);\n%! assert (size (C), [5, 3]);\n%! assert (C(4:5, :), zeros (2,3));\n%! assert (size (S), [3, 3]);\n%! assert (U*C*X', A, 50*eps);\n%! assert (V*S*X', B, 50*eps);\n%! S0 = gsvd (A, B);\n%! assert (size (S0), [3, 1]);\n%! S1 = sort (svd (A / B));\n%! assert (S0, S1, 10*eps);\n\n%!test <60273>\n%! A = reshape (1:15,3,5);\n%! B = magic (5);\n%! [U,V,X,C,S] = gsvd (A,B);\n%! assert (size (U), [3, 3]);\n%! assert (size (V), [5, 5]);\n%! assert (size (X), [5, 5]);\n%! assert (size (C), [3, 5]);\n%! assert (C(:, 4:5), zeros (3,2));\n%! assert (size (S), [5, 5]);\n%! assert (U*C*X', A, 120*eps);  # less accurate in this orientation\n%! assert (V*S*X', B, 150*eps);  # for some reason.\n%! S0 = gsvd (A, B);\n%! assert (size (S0), [5, 1]);\n%! S0 = S0(3:end);\n%! S1 = sort (svd (A / B));\n%! assert (S0, S1, 20*eps);\n\n## a few tests for gsvd.m\n%!shared A0, B0\n%! old_state = randn (\"state\");\n%! restore_state = onCleanup (@() randn (\"state\", old_state));\n%! randn (\"state\", 40);  # initialize generator to make behavior reproducible\n%! A0 = randn (5, 3);\n%! B0 = diag ([1 2 4]);\n\n## A (5x3) and B (3x3) are full rank\n%!test <48807>\n%! A = A0;\n%! B = B0;\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (3), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 20*eps);\n\n## A: 5x3 full rank, B: 3x3 rank deficient\n%!test <48807>\n%! A = A0;\n%! B = B0;\n%! B(2, 2) = 0;\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (3), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 20*eps);\n\n## A: 5x3 rank deficient, B: 3x3 full rank\n%!test <48807>\n%! A = A0;\n%! B = B0;\n%! A(:, 3) = 2*A(:, 1) - A(:, 2);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (3), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 20*eps);\n\n## A and B are both rank deficient\n## FIXME: LAPACK seems to be completely broken for this case\n%!#test <48807>\n%! A = A0;\n%! B = B0;\n%! B(:, 3) = 2*B(:, 1) - B(:, 2);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (3), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 20*eps);\n\n## A (now 3x5) and B (now 5x5) are full rank\n%!test <48807>\n%! A = A0.';\n%! B = diag ([1 2 4 8 16]);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (5), 5*eps);\n%! assert (U*C*X', A, 15*eps);\n%! assert (V*S*X', B, 85*eps);\n\n## A: 3x5 full rank, B: 5x5 rank deficient\n%!test <48807>\n%! A = A0.';\n%! B = diag ([1 2 4 8 16]);\n%! B(2, 2) = 0;\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (5), 5*eps);\n%! assert (U*C*X', A, 15*eps);\n%! assert (V*S*X', B, 85*eps);\n\n## A: 3x5 rank deficient, B: 5x5 full rank\n%!test <48807>\n%! A = A0.';\n%! B = diag ([1 2 4 8 16]);\n%! A(3, :) = 2*A(1, :) - A(2, :);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (5), 5*eps);\n%! assert (U*C*X', A, 15*eps);\n%! assert (V*S*X', B, 85*eps);\n\n## A and B are both rank deficient\n## FIXME: LAPACK seems to be completely broken for this case\n%!#test <48807>\n%! A = A0.'; B = B0.';\n%! A(:, 3) = 2*A(:, 1) - A(:, 2);\n%! B(:, 3) = 2*B(:, 1) - B(:, 2);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (3), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 20*eps);\n\n## A: 5x3 complex full rank, B: 3x3 complex full rank\n%!test <48807>\n%! old_state = randn (\"state\");\n%! restore_state = onCleanup (@() randn (\"state\", old_state));\n%! randn (\"state\", 12345);  # initialize generator to make behavior reproducible\n%! A = A0 + j* randn (5, 3);\n%! B = diag ([1 2 4]) + j* diag ([4 -2 -1]);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (3), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 25*eps);\n\n## A: 5x3 complex full rank, B: 3x3 complex rank deficient\n%!test <48807>\n%! A = A0 + j* randn (5, 3);\n%! B = diag ([1 2 4]) + j* diag ([4 -2 -1]);\n%! B(2, 2) = 0;\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (3), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 25*eps);\n\n## A: 5x3 complex rank deficient, B: 3x3 complex full rank\n%!test <48807>\n%! A = A0 + j* randn (5, 3);\n%! B = diag ([1 2 4]) + j* diag ([4 -2 -1]);\n%! A(:, 3) = 2*A(:, 1) - A(:, 2);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (3), 5*eps);\n%! assert (U*C*X', A, 15*eps);\n%! assert (V*S*X', B, 25*eps);\n\n## A (5x3) and B (3x3) are both complex rank deficient\n## FIXME: LAPACK seems to be completely broken for this case\n%!#test <48807>\n%! A = A0 + j* randn (5, 3);\n%! B = diag ([1 2 4]) + j* diag ([4 -2 -1]);\n%! B(:, 3) = 2*B(:, 1) - B(:, 2);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (3), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 20*eps);\n\n## A (now 3x5) complex and B (now 5x5) complex are full rank\n## now, A is 3x5\n%!test <48807>\n%! A = A0.';\n%! B = diag ([1 2 4 8 16]) + j* diag ([-5 4 -3 2 -1]);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (5), 5*eps);\n%! assert (U*C*X', A, 25*eps);\n%! assert (V*S*X', B, 85*eps);\n\n## A: 3x5 complex full rank, B: 5x5 complex rank deficient\n%!test <48807>\n%! A = A0.';\n%! B = diag ([1 0 4 8 16]) + j* diag ([-5 0 -3 2 -1]);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (5), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 85*eps);\n\n## A: 3x5 complex rank deficient, B: 5x5 complex full rank\n%!test <48807>\n%! A = A0.';\n%! B = diag ([1 2 4 8 16]) + j* diag ([-5 4 -3 2 -1]);\n%! A(3, :) = 2*A(1, :) - A(2, :);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (5), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 85*eps);\n\n## A and B are both complex rank deficient\n## FIXME: LAPACK seems to be completely broken for this case\n%!#test <48807>\n%! A = A0.';\n%! B = B0.';\n%! A(:, 3) = 2*A(:, 1) - A(:, 2);\n%! B(:, 3) = 2*B(:, 1) - B(:, 2);\n%! [U, V, X, C, S] = gsvd (A, B);\n%! assert (C'*C + S'*S, eye (5), 5*eps);\n%! assert (U*C*X', A, 10*eps);\n%! assert (V*S*X', B, 85*eps);\n\n## Test that single inputs produce single outputs\n%!test\n%! A = A0.';\n%! B = diag ([1 2 4 8 16]) + j* diag ([-5 4 -3 2 -1]);\n%! s = gsvd (single (eye (5)), B);\n%! assert (class (s), \"single\");\n%! [U, V, X, C, S] = gsvd (single (eye(5)), B);\n%! assert (class (U), \"single\");\n%! assert (class (V), \"single\");\n%! assert (class (X), \"single\");\n%! assert (class (C), \"single\");\n%! assert (class (S), \"single\");\n%!\n%! s = gsvd (A, single (eye (5)));\n%! assert (class (s), \"single\");\n%! [U, V, X, C, S] = gsvd (A, single (eye (5)));\n%! assert (class (U), \"single\");\n%! assert (class (V), \"single\");\n%! assert (class (X), \"single\");\n%! assert (class (C), \"single\");\n%! assert (class (S), \"single\");\n\n## Test input validation\n%!error <Invalid call> gsvd ()\n%!error <Invalid call> gsvd (1)\n%!error <Invalid call> gsvd (1,2,3,4)\n%!warning <economy-sized decomposition is not yet implemented> gsvd (1,2,0);\n%!error <A and B must have the same number of columns> gsvd (1,[1, 2])\n## Test input validation for single (real and complex) inputs.\n%!error <A cannot have Inf or NaN values> gsvd (Inf, single (2))\n%!error <A cannot have Inf or NaN values> gsvd (NaN, single (2))\n%!error <B cannot have Inf or NaN values> gsvd (single (1), Inf)\n%!error <B cannot have Inf or NaN values> gsvd (single (1), NaN)\n%!error <A must be a real or complex matrix> gsvd ({1}, single (2i))\n%!error <B must be a real or complex matrix> gsvd (single (i), {2})\n%!error <A cannot have Inf or NaN values> gsvd (Inf, single (2i))\n%!error <A cannot have Inf or NaN values> gsvd (NaN, single (2i))\n%!error <B cannot have Inf or NaN values> gsvd (single (i), Inf)\n%!error <B cannot have Inf or NaN values> gsvd (single (i), NaN)\n## Test input validation for single, but not real or complex, inputs.\n%!error <A and B must be real or complex matrices> gsvd ({1}, single (2))\n%!error <A and B must be real or complex matrices> gsvd (single (1), {2})\n## Test input validation for double (real and complex) inputs.\n%!error <A cannot have Inf or NaN values> gsvd (Inf, 2)\n%!error <A cannot have Inf or NaN values> gsvd (NaN, 2)\n%!error <B cannot have Inf or NaN values> gsvd (1, Inf)\n%!error <B cannot have Inf or NaN values> gsvd (1, NaN)\n%!error <A must be a real or complex matrix> gsvd ({1}, 2i)\n%!error <B must be a real or complex matrix> gsvd (i, {2})\n%!error <A cannot have Inf or NaN values> gsvd (Inf, 2i)\n%!error <A cannot have Inf or NaN values> gsvd (NaN, 2i)\n%!error <B cannot have Inf or NaN values> gsvd (i, Inf)\n%!error <B cannot have Inf or NaN values> gsvd (i, NaN)\n## Test input validation for double, but not real or complex, inputs.\n%!error <A and B must be real or complex matrices> gsvd ({1}, double (2))\n%!error <A and B must be real or complex matrices> gsvd (double (1), {2})\n## Test input validation in liboctave/numeric/gsvd.cc\n%!error <A and B cannot be empty matrices> gsvd (zeros (0,1), 1)\n%!error <A and B cannot be empty matrices> gsvd (1, zeros (0,1))\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/hash.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\nImplementation note (Dec, 2015): All supported cryptographic hash\nfunctions are calling \"low-level\" implementations of the GNULIB.\n\nThe GNULIB, contains even more HMAC based algorithms, c.f.\nhttps://www.gnu.org/software/gnulib/MODULES.html#module=crypto/hmac-md5\nso a future project might be including these algorithms as well, adding\na third key input parameter.  There is also a GNULIB \"high-level\"\ninterface to Libcrypt.  It might be easier to use, but it introduces\na new build dependency, so better stick to the \"low-level\" functions\nfor now.\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"oct-hash.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (hash, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hashval} =} hash (\"@var{hashfcn}\", @var{str})\nCalculate the hash value of the string @var{str} using the hash function\n@var{hashfcn}.\n\nThe available hash functions are given in the table below.\n\n@table @samp\n@item MD2\nMessage-Digest Algorithm 2 (RFC 1319).\n\n@item MD4\nMessage-Digest Algorithm 4 (RFC 1320).\n\n@item MD5\nMessage-Digest Algorithm 5 (RFC 1321).\n\n@item SHA1\nSecure Hash Algorithm 1 (RFC 3174)\n\n@item SHA224\nSecure Hash Algorithm 2 (224 Bits, RFC 3874)\n\n@item SHA256\nSecure Hash Algorithm 2 (256 Bits, RFC 6234)\n\n@item SHA384\nSecure Hash Algorithm 2 (384 Bits, RFC 6234)\n\n@item SHA512\nSecure Hash Algorithm 2 (512 Bits, RFC 6234)\n@end table\n\nTo calculate for example the MD5 hash value of the string\n@nospell{@qcode{\"abc\"}} the @code{hash} function is called as follows:\n\n@example\n@group\nhash (\"md5\", \"abc\")\n     @print{} ans = 900150983cd24fb0d6963f7d28e17f72\n@end group\n@end example\n\nFor the same string, the SHA-1 hash value is calculated with:\n\n@example\n@group\nhash (\"sha1\", \"abc\")\n     @print{} ans = a9993e364706816aba3e25717850c26c9cd0d89d\n@end group\n@end example\n\nAnd to compute the hash value of a file, e.g., @code{file = \"file.txt\"},\ncall @code{hash} in combination with the @code{fileread}:\n\n@example\n@group\nhash (\"md5\", fileread (file));\n@end group\n@end example\n\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string hash_type = args(0).string_value ();\n  std::string str = args(1).string_value ();\n\n  return ovl (crypto::hash (hash_type, str));\n}\n\n/*\n## MD2 test suite (RFC 1319)\n%!assert (hash (\"md2\", \"\"), \"8350e5a3e24c153df2275c9f80692773\")\n%!assert (hash (\"md2\", \"a\"), \"32ec01ec4a6dac72c0ab96fb34c0b5d1\")\n%!assert (hash (\"md2\", \"abc\"), \"da853b0d3f88d99b30283a69e6ded6bb\")\n%!assert (hash (\"md2\", \"message digest\"), \"ab4f496bfb2a530b219ff33031fe06b0\")\n%!assert (hash (\"md2\", \"abcdefghijklmnopqrstuvwxyz\"),\n%!        \"4e8ddff3650292ab5a4108c3aa47940b\");\n%!assert (hash (\"md2\", [\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\", ...\n%!              \"abcdefghijklmnopqrstuvwxyz0123456789\"]),\n%!        \"da33def2a42df13975352846c30338cd\");\n%!assert (hash (\"md2\", [\"123456789012345678901234567890123456789\", ...\n%!              \"01234567890123456789012345678901234567890\"]),\n%!        \"d5976f79d83d3a0dc9806c3c66f3efd8\");\n\n## MD4 test suite (RFC 1320)\n%!assert (hash (\"md4\", \"\"), \"31d6cfe0d16ae931b73c59d7e0c089c0\")\n%!assert (hash (\"md4\", \"a\"), \"bde52cb31de33e46245e05fbdbd6fb24\")\n%!assert (hash (\"md4\", \"abc\"), \"a448017aaf21d8525fc10ae87aa6729d\")\n%!assert (hash (\"md4\", \"message digest\"), \"d9130a8164549fe818874806e1c7014b\")\n%!assert (hash (\"md4\", \"abcdefghijklmnopqrstuvwxyz\"),\n%!        \"d79e1c308aa5bbcdeea8ed63df412da9\");\n%!assert (hash (\"md4\", [\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\", ...\n%!              \"abcdefghijklmnopqrstuvwxyz0123456789\"]),\n%!        \"043f8582f241db351ce627e153e7f0e4\");\n%!assert (hash (\"md4\", [\"123456789012345678901234567890123456789\", ...\n%!              \"01234567890123456789012345678901234567890\"]),\n%!        \"e33b4ddc9c38f2199c3e7b164fcc0536\");\n\n## MD5 test suite (RFC 1321)\n%!assert (hash (\"md5\", \"\"), \"d41d8cd98f00b204e9800998ecf8427e\")\n%!assert (hash (\"md5\", \"a\"), \"0cc175b9c0f1b6a831c399e269772661\")\n%!assert (hash (\"md5\", \"abc\"), \"900150983cd24fb0d6963f7d28e17f72\")\n%!assert (hash (\"md5\", \"message digest\"), \"f96b697d7cb7938d525a2f31aaf161d0\")\n%!assert (hash (\"md5\", \"abcdefghijklmnopqrstuvwxyz\"),\n%!        \"c3fcd3d76192e4007dfb496cca67e13b\");\n%!assert (hash (\"md5\", [\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\", ...\n%!              \"abcdefghijklmnopqrstuvwxyz0123456789\"]),\n%!        \"d174ab98d277d9f5a5611c2c9f419d9f\");\n%!assert (hash (\"md5\", [\"123456789012345678901234567890123456789\", ...\n%!              \"01234567890123456789012345678901234567890\"]),\n%!        \"57edf4a22be3c955ac49da2e2107b67a\");\n\n## SHA1 test suite (RFC 3174) and more\n%!assert (hash (\"sha1\", \"\"), \"da39a3ee5e6b4b0d3255bfef95601890afd80709\")\n%!assert (hash (\"sha1\", \"a\"), \"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8\")\n%!assert (hash (\"sha1\", \"abc\"), \"a9993e364706816aba3e25717850c26c9cd0d89d\")\n%!assert (hash (\"sha1\", [\"abcdbcdecdefdefgefghfghighijhi\", ...\n%!              \"jkijkljklmklmnlmnomnopnopq\"]),\n%!        \"84983e441c3bd26ebaae4aa1f95129e5e54670f1\");\n%!assert (hash (\"sha1\", [\"01234567012345670123456701234567\", ...\n%!              \"01234567012345670123456701234567\"]),\n%!        \"e0c094e867ef46c350ef54a7f59dd60bed92ae83\");\n%!assert (hash (\"sha1\", \"The quick brown fox jumps over the lazy dog\"),\n%!        \"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\");\n\n## SHA224 test suite (RFC 3874) and more\n%!assert (hash (\"sha224\", \"\"),\n%!        \"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f\");\n%!assert (hash (\"sha224\", \"a\"),\n%!        \"abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5\");\n%!assert (hash (\"sha224\", \"abc\"),\n%!        \"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7\");\n%!assert (hash (\"sha224\", [\"abcdbcdecdefdefgefghfghighijh\", ...\n%!              \"ijkijkljklmklmnlmnomnopnopq\"]),\n%!        \"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525\");\n\n## SHA256/384/512 tests (RFC 6234) and more\n%!assert (hash (\"sha256\", \"\"),\n%!        \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\");\n%!assert (hash (\"sha384\", \"\"),\n%!        [\"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc\", ...\n%!         \"7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b\"]);\n%!assert (hash (\"sha512\", \"\"),\n%!        [\"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a\", ...\n%!         \"921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47\", ...\n%!         \"417a81a538327af927da3e\"]);\n\n## Test special character behavior\n%!assert <*31689> (hash (\"md2\", \"abc\\0\"), \"5a636d615002a7874ac1c9e9a43361f7\")\n%!assert <*31689> (hash (\"md4\", \"abc\\0\"), \"0ee5201897ecb206c4eaba1d2da5224d\")\n%!assert <*31689> (hash (\"md5\", \"abc\\0\"), \"147a664a2ca9410911e61986d3f0d52a\")\n%!assert <*31689> (hash (\"sha1\", \"abc\\0\"),\n%!                 \"686483805ac47ca14e03514f7481a7973b401762\")\n%!assert <*31689> (hash (\"sha224\", \"abc\\0\"),\n%!                 \"fbc8e47920e108bb1d0b631d18b36ae9b1549d28362aa15ebe960cfb\");\n%!assert <*31689> (hash (\"sha256\", \"abc\\0\"),\n%!       \"dc1114cd074914bd872cc1f9a23ec910ea2203bc79779ab2e17da25782a624fc\");\n%!assert <*31689> (hash (\"sha384\", \"abc\\0\"),\n%!       [\"eba81f2dfba4ec60d3f786c89d91b08e6c0b63d55986874378e385\", ...\n%!        \"e6fac587cce7a520ca9437290fe626cbf75c855e17\"]);\n%!assert <*31689> (hash (\"sha512\", \"abc\\0\"),\n%!       [\"7ce05eda233e545a2d5c626862a5ddaafb09b9d8ec3bec08aa458b\", ...\n%!        \"7c9e7d939d84a57d5a20d8a9002983aabae2457b19c50ba326bf5b\", ...\n%!        \"081f75b41342f42c3383\"]);\n\n## Test equivalence to deprecated md5sum offering file hashing\n%!test\n%! tfile = tempname ();\n%! fid = fopen (tfile, \"wb\");\n%! fwrite (fid, \"abc\\0\");\n%! fclose (fid);\n%! assert (hash (\"md5\", fileread (tfile)), \"147a664a2ca9410911e61986d3f0d52a\");\n%! unlink (tfile);\n\n## Test bad function calls\n%!error hash ()\n%!error hash (\"\")\n%!error hash (\"\", \"\")\n%!error hash (\"\", \"\", \"\")\n%!error hash (1, \"\")\n%!error hash ([1, 0; 0, 1], \"\")\n%!error hash (\"unknown\", \"\")\n%!error hash (\"md5\")\n%!error hash (\"sha1\")\n%!error hash (\"sha512\")\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/hess.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"hess.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (hess, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{H} =} hess (@var{A})\n@deftypefnx {} {[@var{P}, @var{H}] =} hess (@var{A})\n@cindex Hessenberg decomposition\nCompute the Hessenberg decomposition of the matrix @var{A}.\n\nThe Hessenberg decomposition is\n@tex\n$$\nA = PHP^T\n$$\nwhere $P$ is a square unitary matrix ($P^TP = I$), and $H$\nis upper Hessenberg ($H_{i,j} = 0, \\forall i > j+1$).\n@end tex\n@ifnottex\n@code{@var{P} * @var{H} * @var{P}' = @var{A}} where @var{P} is a square\nunitary matrix (@code{@var{P}' * @var{P} = I}, using complex-conjugate\ntransposition) and @var{H} is upper Hessenberg\n(@code{@var{H}(i, j) = 0 forall i > j+1)}.\n@end ifnottex\n\nThe Hessenberg decomposition is usually used as the first step in an\neigenvalue computation, but has other applications as well\n(see @nospell{Golub, Nash, and Van Loan},\nIEEE Transactions on Automatic Control, 1979).\n@seealso{eig, chol, lu, qr, qz, schur, svd}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  if (arg.isempty ())\n    return octave_value_list (2, Matrix ());\n\n  if (arg.rows () != arg.columns ())\n    err_square_matrix_required (\"hess\", \"A\");\n\n  octave_value_list retval;\n\n  if (arg.is_single_type ())\n    {\n      if (arg.isreal ())\n        {\n          FloatMatrix tmp = arg.float_matrix_value ();\n\n          math::hess<FloatMatrix> result (tmp);\n\n          if (nargout <= 1)\n            retval = ovl (result.hess_matrix ());\n          else\n            retval = ovl (result.unitary_hess_matrix (),\n                          result.hess_matrix ());\n        }\n      else if (arg.iscomplex ())\n        {\n          FloatComplexMatrix ctmp = arg.float_complex_matrix_value ();\n\n          math::hess<FloatComplexMatrix> result (ctmp);\n\n          if (nargout <= 1)\n            retval = ovl (result.hess_matrix ());\n          else\n            retval = ovl (result.unitary_hess_matrix (),\n                          result.hess_matrix ());\n        }\n    }\n  else\n    {\n      if (arg.isreal ())\n        {\n          Matrix tmp = arg.matrix_value ();\n\n          math::hess<Matrix> result (tmp);\n\n          if (nargout <= 1)\n            retval = ovl (result.hess_matrix ());\n          else\n            retval = ovl (result.unitary_hess_matrix (),\n                          result.hess_matrix ());\n        }\n      else if (arg.iscomplex ())\n        {\n          ComplexMatrix ctmp = arg.complex_matrix_value ();\n\n          math::hess<ComplexMatrix> result (ctmp);\n\n          if (nargout <= 1)\n            retval = ovl (result.hess_matrix ());\n          else\n            retval = ovl (result.unitary_hess_matrix (),\n                          result.hess_matrix ());\n        }\n      else\n        err_wrong_type_arg (\"hess\", arg);\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! a = [1, 2, 3; 5, 4, 6; 8, 7, 9];\n%! [p, h] = hess (a);\n%! assert (p * h * p', a, sqrt (eps));\n\n%!test\n%! a = single ([1, 2, 3; 5, 4, 6; 8, 7, 9]);\n%! [p, h] = hess (a);\n%! assert (p * h * p', a, sqrt (eps (\"single\")));\n\n%!error hess ()\n%!error hess ([1, 2; 3, 4], 2)\n%!error <must be a square matrix> hess ([1, 2; 3, 4; 5, 6])\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/hex2num.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"mach-info.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic inline bool\nis_little_endian (bool is_float)\n{\n  return ((is_float && (mach_info::native_float_format ()\n                        == mach_info::flt_fmt_ieee_little_endian))\n          || mach_info::words_little_endian ());\n}\n\nstatic uint8_t\nhex2nibble (unsigned char ch)\n{\n  unsigned char val = 0;\n\n  if (! isxdigit (ch))\n    error (\"hex2num: invalid character '%c' found in string S\", ch);\n\n  if (ch >= 'a')\n    val = static_cast<unsigned char> (ch - 'a' + 10);\n  else if (ch >= 'A')\n    val = static_cast<unsigned char> (ch - 'A' + 10);\n  else\n    val = static_cast<unsigned char> (ch - '0');\n\n  return val;\n}\n\nstatic void\nhex2num (const std::string& hex, void *num, std::size_t nbytes, bool swap_bytes)\n{\n  unsigned char *cp = reinterpret_cast<unsigned char *> (num);\n\n  const std::size_t nc = hex.length ();\n  const std::size_t nchars = 2 * nbytes;\n\n  if (nc > nchars)\n    error (\"hex2num: S must be no more than %zd characters\", nchars);\n\n  std::size_t j = 0;\n\n  for (std::size_t i = 0; i < nbytes; i++)\n    {\n      std::size_t k = (swap_bytes ? nbytes - i - 1 : i);\n\n      unsigned char ch1 = (j < nc) ? hex[j++] : '0';\n      unsigned char ch2 = (j < nc) ? hex[j++] : '0';\n\n      cp[k] = (hex2nibble (ch1) << 4) + hex2nibble (ch2);\n    }\n}\n\ntemplate <typename T>\nArray<T>\nhex2num (const Array<std::string>& val, bool swap_bytes)\n{\n  octave_idx_type nel = val.numel ();\n\n  Array<T> m (val.dims ());\n\n  std::size_t nbytes = sizeof (T);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      T num;\n\n      hex2num (val.xelem (i), &num, nbytes, swap_bytes);\n\n      m(i) = num;\n    }\n\n  return m;\n}\n\nDEFUN (hex2num, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{n} =} hex2num (@var{s})\n@deftypefnx {} {@var{n} =} hex2num (@var{s}, @var{class})\nTypecast a hexadecimal character array or cell array of strings to an\narray of numbers.\n\nBy default, the input array is interpreted as a hexadecimal number\nrepresenting a double precision value.  If fewer than 16 characters are\ngiven the strings are right padded with @qcode{'0'} characters.\n\nGiven a string matrix, @code{hex2num} treats each row as a separate number.\n\n@example\n@group\nhex2num ([\"4005bf0a8b145769\"; \"4024000000000000\"])\n   @xresult{} [2.7183; 10.000]\n@end group\n@end example\n\nThe optional second argument @var{class} may be used to cause the input\narray to be interpreted as a different value type.  Possible values are\n\n@multitable {@qcode{\"uint64\"}} {Characters}\n@headitem Option @tab Characters\n@item @qcode{\"int8\"} @tab 2\n@item @qcode{\"uint8\"} @tab 2\n@item @qcode{\"int16\"} @tab 4\n@item @qcode{\"uint16\"} @tab 4\n@item @qcode{\"int32\"} @tab 8\n@item @qcode{\"uint32\"} @tab 8\n@item @qcode{\"int64\"} @tab 16\n@item @qcode{\"uint64\"} @tab 16\n@item @qcode{\"char\"} @tab 2\n@item @qcode{\"single\"} @tab 8\n@item @qcode{\"double\"} @tab 16\n@end multitable\n\nFor example:\n\n@example\n@group\nhex2num ([\"402df854\"; \"41200000\"], \"single\")\n   @xresult{} [2.7183; 10.000]\n@end group\n@end example\n@seealso{num2hex, hex2dec, dec2hex}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string type = \"double\";\n  if (nargin == 2)\n    type = args(1).xstring_value (\"hex2num: CLASS must be a string\");\n\n  Array<std::string> val = args(0).cellstr_value ();\n\n  // We always use big-endian order for hex digits.\n  bool is_float = type == \"single\" || type == \"double\";\n  bool swap_bytes = is_little_endian (is_float);\n\n  if (type == \"int8\")\n    retval = octave_value (hex2num<octave_int8> (val, swap_bytes));\n  else if (type == \"uint8\")\n    retval = octave_value (hex2num<octave_uint8> (val, swap_bytes));\n  else if (type == \"int16\")\n    retval = octave_value (hex2num<octave_int16> (val, swap_bytes));\n  else if (type == \"uint16\")\n    retval = octave_value (hex2num<octave_uint16> (val, swap_bytes));\n  else if (type == \"int32\")\n    retval = octave_value (hex2num<octave_int32> (val, swap_bytes));\n  else if (type == \"uint32\")\n    retval = octave_value (hex2num<octave_uint32> (val, swap_bytes));\n  else if (type == \"int64\")\n    retval = octave_value (hex2num<octave_int64> (val, swap_bytes));\n  else if (type == \"uint64\")\n    retval = octave_value (hex2num<octave_uint64> (val, swap_bytes));\n  else if (type == \"char\")\n    retval = octave_value (hex2num<char> (val, swap_bytes));\n  else if (type == \"single\")\n    retval = octave_value (hex2num<float> (val, swap_bytes));\n  else if (type == \"double\")\n    retval = octave_value (hex2num<double> (val, swap_bytes));\n  else\n    error (\"hex2num: unrecognized CLASS '%s'\", type.c_str ());\n\n  return retval;\n}\n\n/*\n%!assert (hex2num ([\"c00\";\"bff\";\"000\";\"3ff\";\"400\"]), [-2:2]')\n%!assert (hex2num ([\"c00\";\"bf8\";\"000\";\"3f8\";\"400\"], \"single\"), single([-2:2])')\n%!assert (hex2num (\"ff\", \"uint8\"), intmax (\"uint8\"))\n%!assert (hex2num (\"ffff\", \"uint16\"), intmax (\"uint16\"))\n%!assert (hex2num (\"ffffffff\", \"uint32\"), intmax (\"uint32\"))\n%!assert (hex2num (\"ffffffff\", \"uint32\"), intmax (\"uint32\"))\n%!assert (hex2num (\"ffffffffffffffff\", \"uint64\"), intmax (\"uint64\"))\n*/\n\nstatic inline unsigned char\nnibble2hex (unsigned char ch)\n{\n  if (ch >= 10)\n    ch += 'a' - 10;\n  else\n    ch += '0';\n\n  return ch;\n}\n\nstatic inline void\nnum2hex (const void *p, std::size_t n, char *hex, bool swap_bytes)\n{\n  const unsigned char *cp = reinterpret_cast<const unsigned char *> (p);\n\n  std::size_t k = 0;\n\n  for (std::size_t i = 0; i < n; i++)\n    {\n      std::size_t j = (swap_bytes ? n - i - 1 : i);\n\n      unsigned char ch = cp[j];\n\n      hex[k++] = nibble2hex ((ch >> 4) & 0xF);\n      hex[k++] = nibble2hex (ch & 0xF);\n    }\n}\n\ntemplate <typename T>\nCell\nnum2hex (const Array<T>& v, bool swap_bytes)\n{\n  const std::size_t nbytes = sizeof (T);\n  const std::size_t nchars = 2 * nbytes;\n\n  octave_idx_type nel = v.numel ();\n\n  string_vector sv (nel);\n\n  const T *pv = v.data ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      char hex[nchars];\n\n      num2hex (pv++, nbytes, hex, swap_bytes);\n\n      sv[i] = std::string (hex, nchars);\n    }\n\n  return Cell (v.dims (), sv);\n}\n\nDEFUN (num2hex, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{s} =} num2hex (@var{n})\n@deftypefnx {} {@var{s} =} num2hex (@var{n}, \"cell\")\nConvert a numeric array to an array of hexadecimal strings.\n\nFor example:\n\n@example\n@group\nnum2hex ([-1, 1, e, Inf])\n@xresult{} \"bff0000000000000\n    3ff0000000000000\n    4005bf0a8b145769\n    7ff0000000000000\"\n@end group\n@end example\n\nIf the argument @var{n} is a single precision number or vector, the returned\nstring has a length of 8.  For example:\n\n@example\n@group\nnum2hex (single ([-1, 1, e, Inf]))\n@xresult{} \"bf800000\n    3f800000\n    402df854\n    7f800000\"\n@end group\n@end example\n\nWith the optional second argument @qcode{\"cell\"}, return a cell array of\nstrings instead of a character array.\n@seealso{hex2num, hex2dec, dec2hex}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  bool as_cell = false;\n\n  if (nargin == 2)\n    {\n      std::string opt = args(1).xstring_value (\"num2hex: second argument must be a string\");\n      if (opt == \"cell\")\n        as_cell = true;\n      else\n        error (\"num2hex: unrecognized option '%s'\", opt.c_str ());\n    }\n\n  octave_value val = args(0);\n\n  if (val.iscomplex ())\n    error (\"num2hex: N must be real\");\n\n  Cell result;\n\n  // We always use big-endian order for hex digits.\n  bool is_float = val.is_single_type () || val.is_double_type ();\n  bool swap_bytes = is_little_endian (is_float);\n\n  if (val.is_int8_type ())\n    result = num2hex (val.int8_array_value (), swap_bytes);\n  else if (val.is_int16_type ())\n    result = num2hex<octave_int16> (val.int16_array_value (), swap_bytes);\n  else if (val.is_int32_type ())\n    result = num2hex<octave_int32> (val.int32_array_value (), swap_bytes);\n  else if (val.is_int64_type ())\n    result = num2hex<octave_int64> (val.int64_array_value (), swap_bytes);\n  else if (val.is_uint8_type ())\n    result = num2hex<octave_uint8> (val.uint8_array_value (), swap_bytes);\n  else if (val.is_uint16_type ())\n    result = num2hex<octave_uint16> (val.uint16_array_value (), swap_bytes);\n  else if (val.is_uint32_type ())\n    result = num2hex<octave_uint32> (val.uint32_array_value (), swap_bytes);\n  else if (val.is_uint64_type ())\n    result = num2hex<octave_uint64> (val.uint64_array_value (), swap_bytes);\n  else if (val.is_char_matrix ())\n    result = num2hex<char> (val.char_array_value (), swap_bytes);\n  else if (val.is_single_type ())\n    result = num2hex<float> (val.float_vector_value (), swap_bytes);\n  else if (val.is_double_type ())\n    result = num2hex<double> (val.vector_value (), swap_bytes);\n  else\n    err_wrong_type_arg (\"num2hex\", val);\n\n  return (as_cell\n          ? octave_value (result)\n          : octave_value (result.string_vector_value ()));\n}\n\n/*\n%!assert (num2hex (-2:2),\n%!        [\"c000000000000000\";\"bff0000000000000\";\"0000000000000000\";\"3ff0000000000000\";\"4000000000000000\"])\n%!assert (num2hex (single (-2:2)),\n%!        [\"c0000000\";\"bf800000\";\"00000000\";\"3f800000\";\"40000000\"])\n%!assert (num2hex (intmax (\"uint8\")), \"ff\")\n%!assert (num2hex (intmax (\"uint16\")), \"ffff\")\n%!assert (num2hex (intmax (\"uint32\")), \"ffffffff\")\n%!assert (num2hex (intmax (\"uint32\")), \"ffffffff\")\n%!assert (num2hex (intmax (\"uint64\")), \"ffffffffffffffff\")\n\n%!assert (hex2num (num2hex (pi)), pi)\n%!assert (hex2num (num2hex (single (pi)), \"single\"), single (pi))\n\n%!error num2hex ()\n%!error num2hex (1,2)\n%!error num2hex (1,\"foo\")\n%!error num2hex (1,2,3)\n%!error num2hex (1j)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/inv.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ops.h\"\n#include \"ov-re-diag.h\"\n#include \"ov-cx-diag.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-flt-cx-diag.h\"\n#include \"ov-perm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (inv, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} inv (@var{A})\n@deftypefnx {} {[@var{x}, @var{rcond}] =} inv (@var{A})\n@deftypefnx {} {[@dots{}] =} inverse (@dots{})\nCompute the inverse of the square matrix @var{A}.\n\nReturn an estimate of the reciprocal condition number if requested,\notherwise warn of an ill-conditioned matrix if the reciprocal condition\nnumber is small.\n\nIn general it is best to avoid calculating the inverse of a matrix directly.\nFor example, it is both faster and more accurate to solve systems of\nequations (@var{A}*@math{x} = @math{b}) with\n@code{@var{y} = @var{A} \\ @math{b}}, rather than\n@code{@var{y} = inv (@var{A}) * @math{b}}.\n\nIf called with a sparse matrix, then in general @var{x} will be a full\nmatrix requiring significantly more storage.  Avoid forming the inverse of a\nsparse matrix if possible.\n\nProgramming Note: @code{inverse} is an alias for @code{inv} and can be used\ninterchangeably.\n@seealso{ldivide, rdivide, pinv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  if (! arg.isnumeric ())\n    err_wrong_type_arg (\"inv\", arg);\n\n  if (arg.isempty ())\n    return ovl (Matrix ());\n\n  if (arg.rows () != arg.columns ())\n    err_square_matrix_required (\"inv\", \"A\");\n\n  octave_value result;\n  octave_idx_type info = 0;\n  double rcond = 0.0;\n  float frcond = 0.0;\n  bool isfloat = arg.is_single_type ();\n\n  if (arg.is_diag_matrix ())\n    {\n      rcond = 1.0;\n      frcond = 1.0f;\n      if (arg.iscomplex ())\n        {\n          if (isfloat)\n            {\n              result = arg.float_complex_diag_matrix_value ().inverse (info);\n              if (info == -1)\n                frcond = 0.0f;\n              else if (nargout > 1)\n                frcond = arg.float_complex_diag_matrix_value ().rcond ();\n            }\n          else\n            {\n              result = arg.complex_diag_matrix_value ().inverse (info);\n              if (info == -1)\n                rcond = 0.0;\n              else if (nargout > 1)\n                rcond = arg.complex_diag_matrix_value ().rcond ();\n            }\n        }\n      else\n        {\n          if (isfloat)\n            {\n              result = arg.float_diag_matrix_value ().inverse (info);\n              if (info == -1)\n                frcond = 0.0f;\n              else if (nargout > 1)\n                frcond = arg.float_diag_matrix_value ().rcond ();\n            }\n          else\n            {\n              result = arg.diag_matrix_value ().inverse (info);\n              if (info == -1)\n                rcond = 0.0;\n              else if (nargout > 1)\n                rcond = arg.diag_matrix_value ().rcond ();\n            }\n        }\n    }\n  else if (arg.is_perm_matrix ())\n    {\n      info = 0;\n      rcond = 1.0;\n      result = arg.perm_matrix_value ().inverse ();\n    }\n  else if (isfloat)\n    {\n      if (arg.isreal ())\n        {\n          FloatMatrix m = arg.float_matrix_value ();\n\n          MatrixType mattyp = args(0).matrix_type ();\n          result = m.inverse (mattyp, info, frcond, true, true);\n          args(0).matrix_type (mattyp);\n        }\n      else if (arg.iscomplex ())\n        {\n          FloatComplexMatrix m = arg.float_complex_matrix_value ();\n\n          MatrixType mattyp = args(0).matrix_type ();\n          result = m.inverse (mattyp, info, frcond, true, true);\n          args(0).matrix_type (mattyp);\n        }\n    }\n  else\n    {\n      if (arg.isreal ())\n        {\n          if (arg.issparse ())\n            {\n              SparseMatrix m = arg.sparse_matrix_value ();\n\n              MatrixType mattyp = args(0).matrix_type ();\n              result = m.inverse (mattyp, info, rcond, true, true);\n              args(0).matrix_type (mattyp);\n            }\n          else\n            {\n              Matrix m = arg.matrix_value ();\n\n              MatrixType mattyp = args(0).matrix_type ();\n              result = m.inverse (mattyp, info, rcond, true, true);\n              args(0).matrix_type (mattyp);\n            }\n        }\n      else if (arg.iscomplex ())\n        {\n          if (arg.issparse ())\n            {\n              SparseComplexMatrix m = arg.sparse_complex_matrix_value ();\n\n              MatrixType mattyp = args(0).matrix_type ();\n              result = m.inverse (mattyp, info, rcond, true, true);\n              args(0).matrix_type (mattyp);\n            }\n          else\n            {\n              ComplexMatrix m = arg.complex_matrix_value ();\n\n              MatrixType mattyp = args(0).matrix_type ();\n              result = m.inverse (mattyp, info, rcond, true, true);\n              args(0).matrix_type (mattyp);\n            }\n        }\n      else\n        // Shouldn't get here since we checked for suitable arg earlier.\n        // Maybe for some user-defined classes?\n        err_wrong_type_arg (\"inv\", arg);\n    }\n\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n\n  retval(0) = result;\n  if (nargout > 1)\n    retval(1) = (isfloat ? octave_value (frcond) : octave_value (rcond));\n\n  if (nargout < 2)\n    {\n      bool is_singular;\n\n      if (isfloat)\n        is_singular = ((frcond + 1.0f == 1.0f) || octave::math::isnan (frcond))\n                      && ! arg.is_scalar_type ();\n      else\n        is_singular = ((rcond + 1.0 == 1.0) || octave::math::isnan (rcond))\n                      && ! arg.is_scalar_type ();\n\n      if (info == -1 || is_singular)\n        warn_singular_matrix (isfloat ? frcond : rcond);\n    }\n\n  return retval;\n}\n\n/*\n## Basic test for double/single matrices\n%!assert (inv ([1, 2; 3, 4]), [-2, 1; 1.5, -0.5], 5*eps)\n%!test\n%! [xinv, rcond] = inv ([1,2;3,4]);\n%! assert (xinv, [-2, 1; 1.5, -0.5], 5*eps);\n%! assert (isa (rcond, \"double\"));\n\n%!assert (inv (single ([1, 2; 3, 4])), single ([-2, 1; 1.5, -0.5]),\n%!        5* eps (\"single\"))\n%!test\n%! [xinv, rcond] = inv (single ([1,2;3,4]));\n%! assert (xinv, single ([-2, 1; 1.5, -0.5]), 5* eps (\"single\"));\n%! assert (isa (rcond, \"single\"));\n\n## Basic test for integer inputs\n%!assert (inv (int32 (2)), 0.5)\n%!assert (inv (uint32 (2)), 0.5)\n%!assert (inv (int64 (2)), 0.5)\n%!assert (inv (uint64 (2)), 0.5)\n\n## Normal scalar cases\n%!assert (inv (2), 0.5)\n%!test\n%! [xinv, rcond] = inv (2);\n%! assert (xinv, 0.5);\n%! assert (rcond, 1);\n%!assert (inv (single (2)), single (0.5))\n%!test\n%! [xinv, rcond] = inv (single (2));\n%! assert (xinv, single (0.5));\n%! assert (rcond, single (1));\n%!assert (inv (complex (1, -1)), 0.5+0.5i)\n%!test\n%! [xinv, rcond] = inv (complex (1, -1));\n%! assert (xinv, 0.5+0.5i);\n%! assert (rcond, 1);\n%!assert (inv (complex (single (1), -1)), single (0.5+0.5i))\n%!test\n%! [xinv, rcond] = inv (complex (single (1), -1));\n%! assert (xinv, single (0.5+0.5i));\n%! assert (rcond, single (1));\n\n## Test special inputs\n## Empty matrix\n%!assert (inv (zeros (2,0)), [])\n\n## Scalar \"0\"\n%!assert (inv (0), Inf)\n%!test\n%! [xinv, rcond] = inv (0);\n%! assert (xinv, Inf);\n%! assert (rcond, 0);\n%!assert (inv (single (0)), single (Inf))\n%!test\n%! [xinv, rcond] = inv (single (0));\n%! assert (xinv, single (Inf));\n%! assert (rcond, single (0));\n%!assert (inv (complex (0, 0)), Inf)\n%!test\n%! [xinv, rcond] = inv (complex (0, 0));\n%! assert (xinv, Inf);\n%! assert (rcond, 0);\n%!assert (inv (complex (single (0), 0)), single (Inf))\n%!test\n%! [xinv, rcond] = inv (complex (single (0), 0));\n%! assert (xinv, single (Inf));\n%! assert (rcond, single (0));\n## NOTE: Matlab returns +Inf for -0 input, but it returns -Inf for 1/-0.\n## These should be the same, and in Octave they are.\n%!assert (inv (-0), -Inf)\n%!test\n%! [xinv, rcond] = inv (-0);\n%! assert (xinv, -Inf);\n%! assert (rcond, 0);\n\n## Scalar \"Inf\"\n%!assert (inv (Inf), 0)\n%!test\n%! [xinv, rcond] = inv (Inf);\n%! assert (xinv, 0);\n%! assert (rcond, 0);\n%!assert (inv (single (Inf)), single (0))\n%!test\n%! [xinv, rcond] = inv (single (Inf));\n%! assert (xinv, single (0));\n%! assert (rcond, single (0));\n%!assert (inv (complex (1, Inf)), 0)\n%!test\n%! [xinv, rcond] = inv (complex (1, Inf));\n%! assert (xinv, 0);\n%! assert (rcond, 0);\n%!assert (inv (complex (single (1), Inf)), single (0))\n%!test\n%! [xinv, rcond] = inv (complex (single (1), Inf));\n%! assert (xinv, single (0));\n%! assert (rcond, single (0));\n\n## Scalar \"NaN\"\n%!assert (inv (NaN), NaN)\n%!test\n%! [xinv, rcond] = inv (NaN);\n%! assert (xinv, NaN);\n%! assert (rcond, NaN);\n%!assert (inv (single (NaN)), single (NaN))\n%!test\n%! [xinv, rcond] = inv (single (NaN));\n%! assert (xinv, single (NaN));\n%! assert (rcond, single (NaN));\n%!assert (inv (complex (1, NaN)), complex (NaN, NaN))\n%!test\n%! [xinv, rcond] = inv (complex (1, NaN));\n%! assert (xinv, complex (NaN, NaN));\n%! assert (rcond, NaN);\n%!assert (inv (complex (single (1), NaN)), complex (single (NaN), NaN))\n%!test\n%! [xinv, rcond] = inv (complex (single (1), NaN));\n%! assert (xinv, complex (single (NaN), NaN));\n%! assert (rcond, single (NaN));\n\n## Matrix special values\n## Matrix of all zeroes\n%!warning <matrix singular> assert (inv (zeros (2,2)), Inf (2,2))\n%!test\n%! [xinv, rcond] = inv (zeros (2,2));\n%! assert (xinv, Inf (2,2));\n%! assert (rcond, 0);\n## Matrix of all Inf\n%!xtest <65054>\n%! fail (\"A = inv (Inf (2,2))\", \"warning\", \"matrix singular\");\n%! assert (A, NaN (2,2));\n%!xtest <65054>\n%! [xinv, rcond] = inv (Inf (2,2));\n%! assert (xinv, NaN (2,2));\n%! assert (rcond, NaN);\n## Matrix of all NaN\n%!warning <rcond = > assert (inv (NaN (2,2)), NaN (2,2))\n%!test\n%! [xinv, rcond] = inv (NaN (2,2));\n%! assert (xinv, NaN (2,2));\n%! assert (rcond, NaN);\n\n## Special diagonal matrices\n%!test\n%! fail (\"A = inv (diag ([1, 0, 1]))\", \"warning\", \"matrix singular\");\n%! assert (A, diag ([Inf, Inf, Inf]));\n\n## Special sparse matrices\n%!testif HAVE_UMFPACK <*56232>\n%! fail (\"A = inv (sparse ([1, 2;0 ,0]))\", \"warning\", \"matrix singular\");\n%! assert (A, sparse ([Inf, Inf; 0, 0]));\n\n%!testif HAVE_UMFPACK <*56232>\n%! fail (\"A = inv (sparse ([1i, 2;0 ,0]))\", \"warning\", \"matrix singular\");\n%! assert (A, sparse ([Inf, Inf; 0, 0]));\n\n%!testif HAVE_UMFPACK <*56232>\n%! fail (\"A = inv (sparse ([1, 0, 0; 0, 0, 0; 0, 0, 1]))\",\n%!       \"warning\", \"matrix singular\");\n%! assert (A, sparse ([Inf, 0, 0; 0, 0, 0; 0, 0, Inf]));\n\n%!error <Invalid call> inv ()\n%!error <Invalid call> inv ([1, 2; 3, 4], 2)\n%!error <wrong type argument> inv (\"Hello World\")\n%!error <wrong type argument> inv ({1})\n%!error <wrong type argument> inv (true)\n%!error <must be a square matrix> inv ([1, 2; 3, 4; 5, 6])\n%!error <inverse of the null matrix not defined> inv (sparse (2, 2, 0))\n%!error <inverse of the null matrix not defined> inv (diag ([0, 0]))\n%!error <inverse of the null matrix not defined> inv (diag (complex ([0, 0])))\n*/\n\nDEFALIAS (inverse, inv);\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/kron.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"dMatrix.h\"\n#include \"fMatrix.h\"\n#include \"CMatrix.h\"\n#include \"fCMatrix.h\"\n\n#include \"dSparse.h\"\n#include \"CSparse.h\"\n\n#include \"dDiagMatrix.h\"\n#include \"fDiagMatrix.h\"\n#include \"CDiagMatrix.h\"\n#include \"fCDiagMatrix.h\"\n\n#include \"PermMatrix.h\"\n\n#include \"mx-inlines.cc\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename R, typename T>\nstatic MArray<T>\nkron (const MArray<R>& a, const MArray<T>& b)\n{\n  panic_unless (a.ndims () == 2);\n  panic_unless (b.ndims () == 2);\n\n  octave_idx_type nra = a.rows ();\n  octave_idx_type nrb = b.rows ();\n  octave_idx_type nca = a.cols ();\n  octave_idx_type ncb = b.cols ();\n\n  MArray<T> c (dim_vector (nra*nrb, nca*ncb));\n  T *cv = c.rwdata ();\n\n  for (octave_idx_type ja = 0; ja < nca; ja++)\n    {\n      octave_quit ();\n      for (octave_idx_type jb = 0; jb < ncb; jb++)\n        {\n          for (octave_idx_type ia = 0; ia < nra; ia++)\n            {\n              mx_inline_mul (nrb, cv, a(ia, ja), b.data () + nrb*jb);\n              cv += nrb;\n            }\n        }\n    }\n\n  return c;\n}\n\ntemplate <typename R, typename T>\nstatic MArray<T>\nkron (const MDiagArray2<R>& a, const MArray<T>& b)\n{\n  panic_unless (b.ndims () == 2);\n\n  octave_idx_type nra = a.rows ();\n  octave_idx_type nrb = b.rows ();\n  octave_idx_type dla = a.diag_length ();\n  octave_idx_type nca = a.cols ();\n  octave_idx_type ncb = b.cols ();\n\n  MArray<T> c (dim_vector (nra*nrb, nca*ncb), T ());\n\n  for (octave_idx_type ja = 0; ja < dla; ja++)\n    {\n      octave_quit ();\n      for (octave_idx_type jb = 0; jb < ncb; jb++)\n        {\n          mx_inline_mul (nrb, &c.xelem (ja*nrb, ja*ncb + jb), a.dgelem (ja),\n                         b.data () + nrb*jb);\n        }\n    }\n\n  return c;\n}\n\ntemplate <typename T>\nstatic MSparse<T>\nkron (const MSparse<T>& A, const MSparse<T>& B)\n{\n  octave_idx_type idx = 0;\n  MSparse<T> C (A.rows () * B.rows (), A.columns () * B.columns (),\n                A.nnz () * B.nnz ());\n\n  C.cidx (0) = 0;\n\n  for (octave_idx_type Aj = 0; Aj < A.columns (); Aj++)\n    {\n      octave_quit ();\n      for (octave_idx_type Bj = 0; Bj < B.columns (); Bj++)\n        {\n          for (octave_idx_type Ai = A.cidx (Aj); Ai < A.cidx (Aj+1); Ai++)\n            {\n              octave_idx_type Ci = A.ridx (Ai) * B.rows ();\n              const T v = A.data (Ai);\n\n              for (octave_idx_type Bi = B.cidx (Bj); Bi < B.cidx (Bj+1); Bi++)\n                {\n                  C.data (idx) = v * B.data (Bi);\n                  C.ridx (idx++) = Ci + B.ridx (Bi);\n                }\n            }\n          C.cidx (Aj * B.columns () + Bj + 1) = idx;\n        }\n    }\n\n  return C;\n}\n\nstatic PermMatrix\nkron (const PermMatrix& a, const PermMatrix& b)\n{\n  octave_idx_type na = a.rows ();\n  octave_idx_type nb = b.rows ();\n  const Array<octave_idx_type>& pa = a.col_perm_vec ();\n  const Array<octave_idx_type>& pb = b.col_perm_vec ();\n  Array<octave_idx_type> res_perm (dim_vector (na * nb, 1));\n  octave_idx_type rescol = 0;\n  for (octave_idx_type i = 0; i < na; i++)\n    {\n      octave_idx_type a_add = pa(i) * nb;\n      for (octave_idx_type j = 0; j < nb; j++)\n        res_perm.xelem (rescol++) = a_add + pb(j);\n    }\n\n  return PermMatrix (res_perm, true);\n}\n\ntemplate <typename MTA, typename MTB>\noctave_value\ndo_kron (const octave_value& a, const octave_value& b)\n{\n  MTA am = octave_value_extract<MTA> (a);\n  MTB bm = octave_value_extract<MTB> (b);\n\n  return octave_value (kron (am, bm));\n}\n\noctave_value\ndispatch_kron (const octave_value& a, const octave_value& b)\n{\n  octave_value retval;\n  if (a.is_perm_matrix () && b.is_perm_matrix ())\n    retval = do_kron<PermMatrix, PermMatrix> (a, b);\n  else if (a.issparse () || b.issparse ())\n    {\n      if (a.iscomplex () || b.iscomplex ())\n        retval = do_kron<SparseComplexMatrix, SparseComplexMatrix> (a, b);\n      else\n        retval = do_kron<SparseMatrix, SparseMatrix> (a, b);\n    }\n  else if (a.is_diag_matrix ())\n    {\n      if (b.is_diag_matrix () && a.rows () == a.columns ()\n          && b.rows () == b.columns ())\n        {\n          // We have two diagonal matrices, the product of those will be\n          // another diagonal matrix.  To do that efficiently, extract\n          // the diagonals as vectors and compute the product.  That\n          // will be another vector, which we then use to construct a\n          // diagonal matrix object.  Note that this will fail if our\n          // digaonal matrix object is modified to allow the nonzero\n          // values to be stored off of the principal diagonal (i.e., if\n          // diag ([1,2], 3) is modified to return a diagonal matrix\n          // object instead of a full matrix object).\n\n          octave_value tmp = dispatch_kron (a.diag (), b.diag ());\n          retval = tmp.diag ();\n        }\n      else if (a.is_single_type () || b.is_single_type ())\n        {\n          if (a.iscomplex ())\n            retval = do_kron<FloatComplexDiagMatrix, FloatComplexMatrix> (a, b);\n          else if (b.iscomplex ())\n            retval = do_kron<FloatDiagMatrix, FloatComplexMatrix> (a, b);\n          else\n            retval = do_kron<FloatDiagMatrix, FloatMatrix> (a, b);\n        }\n      else\n        {\n          if (a.iscomplex ())\n            retval = do_kron<ComplexDiagMatrix, ComplexMatrix> (a, b);\n          else if (b.iscomplex ())\n            retval = do_kron<DiagMatrix, ComplexMatrix> (a, b);\n          else\n            retval = do_kron<DiagMatrix, Matrix> (a, b);\n        }\n    }\n  else if (a.is_single_type () || b.is_single_type ())\n    {\n      if (a.iscomplex ())\n        retval = do_kron<FloatComplexMatrix, FloatComplexMatrix> (a, b);\n      else if (b.iscomplex ())\n        retval = do_kron<FloatMatrix, FloatComplexMatrix> (a, b);\n      else\n        retval = do_kron<FloatMatrix, FloatMatrix> (a, b);\n    }\n  else\n    {\n      if (a.iscomplex ())\n        retval = do_kron<ComplexMatrix, ComplexMatrix> (a, b);\n      else if (b.iscomplex ())\n        retval = do_kron<Matrix, ComplexMatrix> (a, b);\n      else\n        retval = do_kron<Matrix, Matrix> (a, b);\n    }\n  return retval;\n}\n\n\nDEFUN (kron, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} kron (@var{A}, @var{B})\n@deftypefnx {} {@var{C} =} kron (@var{A1}, @var{A2}, @dots{})\nForm the Kronecker product of two or more matrices.\n\nThis is defined block by block as\n\n@example\nc = [ a(i,j)*b ]\n@end example\n\nFor example:\n\n@example\n@group\nkron (1:4, ones (3, 1))\n     @xresult{}  1  2  3  4\n         1  2  3  4\n         1  2  3  4\n@end group\n@end example\n\nIf there are more than two input arguments @var{A1}, @var{A2}, @dots{},\n@var{An} the Kronecker product is computed as\n\n@example\nkron (kron (@var{A1}, @var{A2}), @dots{}, @var{An})\n@end example\n\n@noindent\nSince the Kronecker product is associative, this is well-defined.\n@seealso{tensorprod}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  octave_value retval;\n\n  octave_value a = args(0);\n  octave_value b = args(1);\n\n  retval = dispatch_kron (a, b);\n\n  for (octave_idx_type i = 2; i < nargin; i++)\n    retval = dispatch_kron (retval, args(i));\n\n  return retval;\n}\n\n/*\n%!test\n%! x = ones (2);\n%! assert (kron (x, x), ones (4));\n\n%!shared x, y, z, p1, p2, d1, d2\n%! x =  [1, 2];\n%! y =  [-1, -2];\n%! z =  [1,  2,  3,  4; 1,  2,  3,  4; 1,  2,  3,  4];\n%! p1 = eye (3)([2, 3, 1], :);  ## Permutation matrix\n%! p2 = [0 1 0; 0 0 1; 1 0 0];  ## Non-permutation equivalent\n%! d1 = diag ([1 2 3]);         ## Diag type matrix\n%! d2 = [1 0 0; 0 2 0; 0 0 3];  ## Non-diag equivalent\n%!assert (kron (1:4, ones (3, 1)), z)\n%!assert (kron (single (1:4), ones (3, 1)), single (z))\n%!assert (kron (sparse (1:4), ones (3, 1)), sparse (z))\n%!assert (kron (complex (1:4), ones (3, 1)), z)\n%!assert (kron (complex (single (1:4)), ones (3, 1)), single (z))\n%!assert (kron (x, y, z), kron (kron (x, y), z))\n%!assert (kron (x, y, z), kron (x, kron (y, z)))\n%!assert (kron (p1, p1), kron (p2, p2))\n%!assert (kron (p1, p2), kron (p2, p1))\n%!assert (kron (d1, d1), kron (d2, d2))\n%!assert (kron (d1, d2), kron (d2, d1))\n\n%!assert (kron (diag ([1, 2]), diag ([3, 4])), diag ([3, 4, 6, 8]))\n\n## Test for two diag matrices.\n## See the comments above in dispatch_kron for this case.\n%!test\n%! expected = zeros (16, 16);\n%! expected (1, 11) = 3;\n%! expected (2, 12) = 4;\n%! expected (5, 15) = 6;\n%! expected (6, 16) = 8;\n%! assert (kron (diag ([1, 2], 2), diag ([3, 4], 2)), expected);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/lsode.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <list>\n#include <string>\n\n#include \"LSODE.h\"\n#include \"mappers.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ov-cell.h\"\n#include \"ov-fcn.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"pr-output.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n#include \"LSODE-opts.cc\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Global pointer for user defined function required by lsode.\nstatic octave_value lsode_fcn;\n\n// Global pointer for optional user defined jacobian function used by lsode.\nstatic octave_value lsode_jac;\n\n// Have we warned about imaginary values returned from user function?\nstatic bool warned_fcn_imaginary = false;\nstatic bool warned_jac_imaginary = false;\n\n// Is this a recursive call?\nstatic int call_depth = 0;\n\nstatic ColumnVector\nlsode_user_function (const ColumnVector& x, double t)\n{\n  ColumnVector retval;\n\n  octave_value_list args;\n  args(1) = t;\n  args(0) = x;\n\n  if (lsode_fcn.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (lsode_fcn, args, 1);\n        }\n      catch (octave::execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"lsode\");\n        }\n\n      if (tmp.empty () || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"lsode\");\n\n      if (! warned_fcn_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"lsode: ignoring imaginary part returned from user-supplied function\");\n          warned_fcn_imaginary = true;\n        }\n\n      retval = tmp(0).xvector_value (\"lsode: expecting user supplied function to return numeric vector\");\n\n      if (retval.isempty ())\n        err_user_supplied_eval (\"lsode\");\n    }\n\n  return retval;\n}\n\nstatic Matrix\nlsode_user_jacobian (const ColumnVector& x, double t)\n{\n  Matrix retval;\n\n  octave_value_list args;\n  args(1) = t;\n  args(0) = x;\n\n  if (lsode_jac.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (lsode_jac, args, 1);\n        }\n      catch (octave::execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"lsode\");\n        }\n\n      if (tmp.empty () || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"lsode\");\n\n      if (! warned_jac_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"lsode: ignoring imaginary part returned from user-supplied jacobian function\");\n          warned_jac_imaginary = true;\n        }\n\n      retval = tmp(0).xmatrix_value (\"lsode: expecting user supplied jacobian function to return numeric array\");\n\n      if (retval.isempty ())\n        err_user_supplied_eval (\"lsode\");\n    }\n\n  return retval;\n}\n\nDEFMETHOD (lsode, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{x}, @var{istate}, @var{msg}] =} lsode (@var{fcn}, @var{x_0}, @var{t})\n@deftypefnx {} {[@var{x}, @var{istate}, @var{msg}] =} lsode (@var{fcn}, @var{x_0}, @var{t}, @var{t_crit})\nOrdinary Differential Equation (ODE) solver.\n\nThe set of differential equations to solve is\n@tex\n$$ {dx \\over dt} = f (x, t) $$\nwith\n$$ x(t_0) = x_0 $$\n@end tex\n@ifnottex\n\n@example\n@group\ndx\n-- = f (x, t)\ndt\n@end group\n@end example\n\n@noindent\nwith\n\n@example\nx(t_0) = x_0\n@end example\n\n@end ifnottex\nThe solution is returned in the matrix @var{x}, with each row\ncorresponding to an element of the vector @var{t}.  The first element\nof @var{t} should be @math{t_0} and should correspond to the initial\nstate of the system @var{x_0}, so that the first row of the output\nis @var{x_0}.\n\nThe first argument, @var{fcn}, is a string, inline, or function handle\nthat names the function @math{f} to call to compute the vector of right\nhand sides for the set of equations.  The function must have the form\n\n@example\n@var{xdot} = f (@var{x}, @var{t})\n@end example\n\n@noindent\nin which @var{xdot} and @var{x} are vectors and @var{t} is a scalar.\n\nIf @var{fcn} is a two-element string array or a two-element cell array\nof strings, inline functions, or function handles, the first element names\nthe function @math{f} described above, and the second element names a\nfunction to compute the Jacobian of @math{f}.  The Jacobian function\nmust have the form\n\n@example\n@var{jac} = j (@var{x}, @var{t})\n@end example\n\n@noindent\nin which @var{jac} is the matrix of partial derivatives\n@tex\n$$ J = {\\partial f_i \\over \\partial x_j} = \\left[\\matrix{\n{\\partial f_1 \\over \\partial x_1}\n  & {\\partial f_1 \\over \\partial x_2}\n  & \\cdots\n  & {\\partial f_1 \\over \\partial x_N} \\cr\n{\\partial f_2 \\over \\partial x_1}\n  & {\\partial f_2 \\over \\partial x_2}\n  & \\cdots\n  & {\\partial f_2 \\over \\partial x_N} \\cr\n \\vdots & \\vdots & \\ddots & \\vdots \\cr\n{\\partial f_M \\over \\partial x_1}\n  & {\\partial f_M \\over \\partial x_2}\n  & \\cdots\n  & {\\partial f_M \\over \\partial x_N} \\cr}\\right]$$\n@end tex\n@ifnottex\n\n@example\n@group\n             | df_1  df_1       df_1 |\n             | ----  ----  ...  ---- |\n             | dx_1  dx_2       dx_N |\n             |                       |\n             | df_2  df_2       df_2 |\n             | ----  ----  ...  ---- |\n      df_i   | dx_1  dx_2       dx_N |\njac = ---- = |                       |\n      dx_j   |  .    .     .    .    |\n             |  .    .      .   .    |\n             |  .    .       .  .    |\n             |                       |\n             | df_M  df_M       df_M |\n             | ----  ----  ...  ---- |\n             | dx_1  dx_2       dx_N |\n@end group\n@end example\n\n@end ifnottex\n\nThe second argument specifies the initial state of the system @math{x_0}.  The\nthird argument is a vector, @var{t}, specifying the time values for which a\nsolution is sought.\n\nThe fourth argument is optional, and may be used to specify a set of\ntimes that the ODE solver should not integrate past.  It is useful for\navoiding difficulties with singularities and points where there is a\ndiscontinuity in the derivative.\n\nAfter a successful computation, the value of @var{istate} will be 2\n(consistent with the Fortran version of @sc{lsode}).\n\nIf the computation is not successful, @var{istate} will be something\nother than 2 and @var{msg} will contain additional information.\n\nYou can use the function @code{lsode_options} to set optional\nparameters for @code{lsode}.\n\nSee @nospell{Alan C. Hindmarsh},\n\"ODEPACK, A Systematized Collection of ODE Solvers\",\n@cite{Scientific Computing}, @nospell{R. S. Stepleman}, editor, 1983.\nor @url{https://computing.llnl.gov/projects/odepack}\nfor more information about the inner workings of @code{lsode}.\n\nExample: Solve the @nospell{Van der Pol} equation\n\n@example\n@group\nfvdp = @@(@var{y},@var{t}) [@var{y}(2); (1 - @var{y}(1)^2) * @var{y}(2) - @var{y}(1)];\n@var{t} = linspace (0, 20, 100);\n@var{y} = lsode (fvdp, [2; 0], @var{t});\n@end group\n@end example\n@seealso{daspk, dassl, dasrt}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 3 || nargin > 4)\n    print_usage ();\n\n  warned_fcn_imaginary = false;\n  warned_jac_imaginary = false;\n\n  unwind_protect_var<int> restore_var (call_depth);\n  call_depth++;\n\n  if (call_depth > 1)\n    error (\"lsode: invalid recursive call\");\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  std::string fcn_name, fname, jac_name, jname;\n\n  lsode_fcn = octave_value ();\n  lsode_jac = octave_value ();\n\n  octave_value f_arg = args(0);\n\n  std::list<std::string> parameter_names ({\"x\", \"t\"});\n\n  if (f_arg.iscell ())\n    {\n      Cell c = f_arg.cell_value ();\n      if (c.numel () == 1)\n        f_arg = c(0);\n      else if (c.numel () == 2)\n        {\n          lsode_fcn = get_function_handle (interp, c(0), parameter_names);\n\n          if (lsode_fcn.is_defined ())\n            {\n              lsode_jac = get_function_handle (interp, c(1), parameter_names);\n\n              if (lsode_jac.is_undefined ())\n                lsode_fcn = octave_value ();\n            }\n        }\n      else\n        error (\"lsode: incorrect number of elements in cell array\");\n    }\n\n  if (lsode_fcn.is_undefined () && ! f_arg.iscell ())\n    {\n      if (f_arg.is_function_handle () || f_arg.is_inline_function ())\n        lsode_fcn = f_arg;\n      else\n        {\n          switch (f_arg.rows ())\n            {\n            case 1:\n              lsode_fcn = get_function_handle (interp, f_arg, parameter_names);\n              break;\n\n            case 2:\n              {\n                string_vector tmp = f_arg.string_vector_value ();\n\n                lsode_fcn = get_function_handle (interp, tmp(0),\n                                                 parameter_names);\n\n                if (lsode_fcn.is_defined ())\n                  {\n                    lsode_jac = get_function_handle (interp, tmp(1),\n                                                     parameter_names);\n\n                    if (lsode_jac.is_undefined ())\n                      lsode_fcn = octave_value ();\n                  }\n              }\n              break;\n\n            default:\n              error (\"lsode: first arg should be a string or 2-element string array\");\n            }\n        }\n    }\n\n  if (lsode_fcn.is_undefined ())\n    error (\"lsode: FCN argument is not a valid function name or handle\");\n\n  ColumnVector state = args(1).xvector_value (\"lsode: initial state X_0 must be a vector\");\n  ColumnVector out_times = args(2).xvector_value (\"lsode: output time variable T must be a vector\");\n\n  ColumnVector crit_times;\n\n  int crit_times_set = 0;\n  if (nargin > 3)\n    {\n      crit_times = args(3).xvector_value (\"lsode: list of critical times T_CRIT must be a vector\");\n\n      crit_times_set = 1;\n    }\n\n  double tzero = out_times (0);\n\n  ODEFunc fcn (lsode_user_function);\n\n  if (lsode_jac.is_defined ())\n    fcn.set_jacobian_function (lsode_user_jacobian);\n\n  LSODE ode (state, tzero, fcn);\n\n  ode.set_options (lsode_opts);\n\n  Matrix output;\n  if (crit_times_set)\n    output = ode.integrate (out_times, crit_times);\n  else\n    output = ode.integrate (out_times);\n\n  if (fcn_name.length ())\n    symtab.clear_function (fcn_name);\n  if (jac_name.length ())\n    symtab.clear_function (jac_name);\n\n  std::string msg = ode.error_message ();\n\n  octave_value_list retval (3);\n\n  if (ode.integration_ok ())\n    retval(0) = output;\n  else if (nargout < 2)\n    error (\"lsode: %s\", msg.c_str ());\n  else\n    retval(0) = Matrix ();\n\n  retval(1) = static_cast<double> (ode.integration_state ());\n  retval(2) = msg;\n\n  return retval;\n}\n\n/*\n\n## dassl-1.m\n##\n## Test lsode() function\n##\n## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)\n##         Comalco Research and Technology\n##         20 May 1998\n##\n## Problem\n##\n##    y1' = -y2,   y1(0) = 1\n##    y2' =  y1,   y2(0) = 0\n##\n## Solution\n##\n##    y1(t) = cos(t)\n##    y2(t) = sin(t)\n##\n%!function xdot = __f (x, t)\n%!  xdot = [-x(2); x(1)];\n%!endfunction\n%!test\n%!\n%! x0 = [1; 0];\n%! xdot0 = [0; 1];\n%! t = (0:1:10)';\n%!\n%! tol = 500 * lsode_options (\"relative tolerance\");\n%!\n%! x = lsode (\"__f\", x0, t);\n%!\n%! y = [cos(t), sin(t)];\n%!\n%! assert (x, y, tol);\n\n%!function xdotdot = __f (x, t)\n%!  xdotdot = [x(2); -x(1)];\n%!endfunction\n%!test\n%!\n%! x0 = [1; 0];\n%! t = [0; 2*pi];\n%! tol = 100 * dassl_options (\"relative tolerance\");\n%!\n%! x = lsode (\"__f\", x0, t);\n%!\n%! y = [1, 0; 1, 0];\n%!\n%! assert (x, y, tol);\n\n%!function xdot = __f (x, t)\n%!  xdot = x;\n%!endfunction\n%!test\n%!\n%! x0 = 1;\n%! t = [0; 1];\n%! tol = 100 * dassl_options (\"relative tolerance\");\n%!\n%! x = lsode (\"__f\", x0, t);\n%!\n%! y = [1; e];\n%!\n%! assert (x, y, tol);\n\n%!test\n%! lsode_options (\"absolute tolerance\", eps);\n%! assert (lsode_options (\"absolute tolerance\") == eps);\n\n%!error lsode_options (\"foo\", 1, 2)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/lu.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lu.h\"\n#include \"sparse-lu.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename MT>\nstatic octave_value\nget_lu_l (const math::lu<MT>& fact)\n{\n  MT L = fact.L ();\n  if (L.issquare ())\n    return octave_value (L, MatrixType (MatrixType::Lower));\n  else\n    return L;\n}\n\ntemplate <typename MT>\nstatic octave_value\nget_lu_u (const math::lu<MT>& fact)\n{\n  MT U = fact.U ();\n  if (U.issquare () && fact.regular ())\n    return octave_value (U, MatrixType (MatrixType::Upper));\n  else\n    return U;\n}\n\nDEFUN (lu, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{L}, @var{U}] =} lu (@var{A})\n@deftypefnx {} {[@var{L}, @var{U}, @var{P}] =} lu (@var{A})\n@deftypefnx {} {[@var{L}, @var{U}, @var{P}, @var{Q}] =} lu (@var{S})\n@deftypefnx {} {[@var{L}, @var{U}, @var{P}, @var{Q}, @var{R}] =} lu (@var{S})\n@deftypefnx {} {[@dots{}] =} lu (@var{S}, @var{thresh})\n@deftypefnx {} {@var{y} =} lu (@dots{})\n@deftypefnx {} {[@dots{}] =} lu (@dots{}, \"vector\")\n@cindex LU decomposition\nCompute the LU@tie{}decomposition of @var{A}.\n\nIf @var{A} is full then subroutines from @sc{lapack} are used, and if\n@var{A} is sparse then @sc{umfpack} is used.\n\nThe result is returned in a permuted form, according to the optional return\nvalue @var{P}.  For example, given the matrix @code{@var{A} = [1, 2; 3, 4]},\n\n@example\n[@var{L}, @var{U}, @var{P}] = lu (@var{A})\n@end example\n\n@noindent\nreturns\n\n@example\n@group\nL =\n\n  1.00000  0.00000\n  0.33333  1.00000\n\nU =\n\n  3.00000  4.00000\n  0.00000  0.66667\n\nP =\n\n  0  1\n  1  0\n@end group\n@end example\n\nThe matrix is not required to be square.\n\nWhen called with two or three output arguments and a sparse input matrix,\n@code{lu} does not attempt to perform sparsity preserving column permutations.\nCalled with a fourth output argument, the sparsity preserving column\ntransformation @var{Q} is returned, such that\n@code{@var{P} * @var{A} * @var{Q} = @var{L} * @var{U}}.  This is the\n@strong{preferred} way to call @code{lu} with sparse input matrices.\n\nCalled with a fifth output argument and a sparse input matrix, @code{lu}\nattempts to use a scaling factor @var{R} on the input matrix such that\n@code{@var{P} * (@var{R} \\ @var{A}) * @var{Q} = @var{L} * @var{U}}.\nThis typically leads to a sparser and more stable factorization.\n\nAn additional input argument @var{thresh} that defines the pivoting\nthreshold can be given.  @var{thresh} can be a scalar, in which case\nit defines the @sc{umfpack} pivoting tolerance for both symmetric and\nunsymmetric cases.  If @var{thresh} is a 2-element vector, then the first\nelement defines the pivoting tolerance for the unsymmetric @sc{umfpack}\npivoting strategy and the second for the symmetric strategy.  By default,\nthe values defined by @code{spparms} are used ([0.1, 0.001]).\n\nGiven the string argument @qcode{\"vector\"}, @code{lu} returns the values\nof @var{P} and @var{Q} as vector values, such that for full matrix,\n@code{@var{A}(@var{P},:) = @var{L} * @var{U}}, and @code{@var{R}(@var{P},:)\n* @var{A}(:,@var{Q}) = @var{L} * @var{U}}.\n\nWith two output arguments, returns the permuted forms of the upper and\nlower triangular matrices, such that @code{@var{A} = @var{L} * @var{U}}.\nWith one output argument @var{y}, then the matrix returned by the\n@sc{lapack} routines is returned.  If the input matrix is sparse then the\nmatrix @var{L} is embedded into @var{U} to give a return value similar to\nthe full case.  For both full and sparse matrices, @code{lu} loses the\npermutation information.\n@seealso{luupdate, ilu, chol, hess, qr, qz, schur, svd}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n  bool issparse = (nargin > 0 && args(0).issparse ());\n\n  if (nargin < 1 || (issparse && nargin > 3) || (! issparse && nargin > 2))\n    print_usage ();\n\n  bool vecout = false;\n  Matrix thresh;\n  int n = 1;\n\n  while (n < nargin)\n    {\n      if (args(n).is_string ())\n        {\n          std::string tmp = args(n++).string_value ();\n\n          if (tmp == \"vector\")\n            vecout = true;\n          else\n            error (\"lu: unrecognized string argument\");\n        }\n      else\n        {\n          if (! issparse)\n            error (\"lu: can not define pivoting threshold THRESH for full matrices\");\n\n          Matrix tmp = args(n++).matrix_value ();\n          if (tmp.numel () == 1)\n            {\n              thresh.resize (1, 2);\n              thresh(0) = tmp(0);\n              thresh(1) = tmp(0);\n            }\n          else if (tmp.numel () == 2)\n            thresh = tmp;\n          else\n            error (\"lu: THRESH must be a 1- or 2-element vector\");\n        }\n    }\n\n  octave_value_list retval;\n  bool scale = (nargout == 5);\n\n  octave_value arg = args(0);\n\n  octave_idx_type nr = arg.rows ();\n  octave_idx_type nc = arg.columns ();\n\n  if (issparse)\n    {\n      if (arg.isempty ())\n        return octave_value_list (5, SparseMatrix ());\n\n      if (arg.isreal ())\n        {\n          SparseMatrix m = arg.sparse_matrix_value ();\n\n          if (nargout < 4)\n            {\n              warning_with_id (\"Octave:lu:sparse_input\",\n                               \"lu: function may fail when called with less than 4 output arguments and a sparse input\");\n\n              ColumnVector Qinit (nc);\n              for (octave_idx_type i = 0; i < nc; i++)\n                Qinit(i) = i;\n              math::sparse_lu<SparseMatrix> fact (m, Qinit, thresh, false,\n                                                  true);\n\n              if (nargout < 2)\n                retval(0) = fact.Y ();\n              else\n                {\n                  retval.resize (nargout == 3 ? 3 : 2);\n                  retval(1)\n                    = octave_value (fact.U () * fact.Pc_mat ().transpose (),\n                                    MatrixType (MatrixType::Permuted_Upper,\n                                                nc, fact.col_perm ()));\n\n                  PermMatrix P = fact.Pr_mat ();\n                  SparseMatrix L = fact.L ();\n\n                  if (nargout == 2)\n                    retval(0)\n                      = octave_value (P.transpose () * L,\n                                      MatrixType (MatrixType::Permuted_Lower,\n                                                  nr, fact.row_perm ()));\n                  else\n                    {\n                      retval(0) = L;\n                      if (vecout)\n                        retval(2) = fact.Pr_vec();\n                      else\n                        retval(2) = P;\n                    }\n                }\n            }\n          else\n            {\n              retval.resize (scale ? 5 : 4);\n              math::sparse_lu<SparseMatrix> fact (m, thresh, scale);\n\n              retval(0) = octave_value (fact.L (),\n                                        MatrixType (MatrixType::Lower));\n              retval(1) = octave_value (fact.U (),\n                                        MatrixType (MatrixType::Upper));\n\n              if (vecout)\n                {\n                  retval(2) = fact.Pr_vec ();\n                  retval(3) = fact.Pc_vec ();\n                }\n              else\n                {\n                  retval(2) = fact.Pr_mat ();\n                  retval(3) = fact.Pc_mat ();\n                }\n\n              if (scale)\n                retval(4) = fact.R ();\n            }\n        }\n      else if (arg.iscomplex ())\n        {\n          SparseComplexMatrix m = arg.sparse_complex_matrix_value ();\n\n          if (nargout < 4)\n            {\n              warning_with_id (\"Octave:lu:sparse_input\",\n                               \"lu: function may fail when called with less than 4 output arguments and a sparse input\");\n\n              ColumnVector Qinit (nc);\n              for (octave_idx_type i = 0; i < nc; i++)\n                Qinit(i) = i;\n              math::sparse_lu<SparseComplexMatrix> fact (m, Qinit, thresh,\n                  false, true);\n\n              if (nargout < 2)\n                retval(0) = fact.Y ();\n              else\n                {\n                  retval.resize (nargout == 3 ? 3 : 2);\n                  retval(1)\n                    = octave_value (fact.U () * fact.Pc_mat ().transpose (),\n                                    MatrixType (MatrixType::Permuted_Upper,\n                                                nc, fact.col_perm ()));\n\n                  PermMatrix P = fact.Pr_mat ();\n                  SparseComplexMatrix L = fact.L ();\n                  if (nargout == 2)\n                    retval(0)\n                      = octave_value (P.transpose () * L,\n                                      MatrixType (MatrixType::Permuted_Lower,\n                                                  nr, fact.row_perm ()));\n                  else\n                    {\n                      retval(0) = L;\n                      if (vecout)\n                        retval(2) = fact.Pr_vec();\n                      else\n                        retval(2) = P;\n                    }\n                }\n            }\n          else\n            {\n              retval.resize (scale ? 5 : 4);\n              math::sparse_lu<SparseComplexMatrix> fact (m, thresh, scale);\n\n              retval(0) = octave_value (fact.L (),\n                                        MatrixType (MatrixType::Lower));\n              retval(1) = octave_value (fact.U (),\n                                        MatrixType (MatrixType::Upper));\n\n              if (vecout)\n                {\n                  retval(2) = fact.Pr_vec ();\n                  retval(3) = fact.Pc_vec ();\n                }\n              else\n                {\n                  retval(2) = fact.Pr_mat ();\n                  retval(3) = fact.Pc_mat ();\n                }\n\n              if (scale)\n                retval(4) = fact.R ();\n            }\n\n        }\n      else\n        err_wrong_type_arg (\"lu\", arg);\n    }\n  else\n    {\n      if (arg.isempty ())\n        return octave_value_list (3, Matrix ());\n\n      if (arg.isreal ())\n        {\n          if (arg.is_single_type ())\n            {\n              FloatMatrix m = arg.float_matrix_value ();\n\n              math::lu<FloatMatrix> fact (m);\n\n              switch (nargout)\n                {\n                case 0:\n                case 1:\n                  retval = ovl (fact.Y ());\n                  break;\n\n                case 2:\n                  {\n                    PermMatrix P = fact.P ();\n                    FloatMatrix L = P.transpose () * fact.L ();\n                    retval = ovl (L, get_lu_u (fact));\n                  }\n                  break;\n\n                case 3:\n                default:\n                  {\n                    if (vecout)\n                      retval = ovl (get_lu_l (fact), get_lu_u (fact),\n                                    fact.P_vec ());\n                    else\n                      retval = ovl (get_lu_l (fact), get_lu_u (fact),\n                                    fact.P ());\n                  }\n                  break;\n                }\n            }\n          else\n            {\n              Matrix m = arg.matrix_value ();\n\n              math::lu<Matrix> fact (m);\n\n              switch (nargout)\n                {\n                case 0:\n                case 1:\n                  retval = ovl (fact.Y ());\n                  break;\n\n                case 2:\n                  {\n                    PermMatrix P = fact.P ();\n                    Matrix L = P.transpose () * fact.L ();\n                    retval = ovl (L, get_lu_u (fact));\n                  }\n                  break;\n\n                case 3:\n                default:\n                  {\n                    if (vecout)\n                      retval = ovl (get_lu_l (fact), get_lu_u (fact),\n                                    fact.P_vec ());\n                    else\n                      retval = ovl (get_lu_l (fact), get_lu_u (fact),\n                                    fact.P ());\n                  }\n                  break;\n                }\n            }\n        }\n      else if (arg.iscomplex ())\n        {\n          if (arg.is_single_type ())\n            {\n              FloatComplexMatrix m = arg.float_complex_matrix_value ();\n\n              math::lu<FloatComplexMatrix> fact (m);\n\n              switch (nargout)\n                {\n                case 0:\n                case 1:\n                  retval = ovl (fact.Y ());\n                  break;\n\n                case 2:\n                  {\n                    PermMatrix P = fact.P ();\n                    FloatComplexMatrix L = P.transpose () * fact.L ();\n                    retval = ovl (L, get_lu_u (fact));\n                  }\n                  break;\n\n                case 3:\n                default:\n                  {\n                    if (vecout)\n                      retval = ovl (get_lu_l (fact), get_lu_u (fact),\n                                    fact.P_vec ());\n                    else\n                      retval = ovl (get_lu_l (fact), get_lu_u (fact),\n                                    fact.P ());\n                  }\n                  break;\n                }\n            }\n          else\n            {\n              ComplexMatrix m = arg.complex_matrix_value ();\n\n              math::lu<ComplexMatrix> fact (m);\n\n              switch (nargout)\n                {\n                case 0:\n                case 1:\n                  retval = ovl (fact.Y ());\n                  break;\n\n                case 2:\n                  {\n                    PermMatrix P = fact.P ();\n                    ComplexMatrix L = P.transpose () * fact.L ();\n                    retval = ovl (L, get_lu_u (fact));\n                  }\n                  break;\n\n                case 3:\n                default:\n                  {\n                    if (vecout)\n                      retval = ovl (get_lu_l (fact), get_lu_u (fact),\n                                    fact.P_vec ());\n                    else\n                      retval = ovl (get_lu_l (fact), get_lu_u (fact),\n                                    fact.P ());\n                  }\n                  break;\n                }\n            }\n        }\n      else\n        err_wrong_type_arg (\"lu\", arg);\n    }\n\n  return retval;\n}\n\n/*\n%!assert(lu ([1, 2; 3, 4]), [3, 4; 1/3, 2/3], eps)\n\n%!test\n%! [l, u] = lu ([1, 2; 3, 4]);\n%! assert (l, [1/3, 1; 1, 0], sqrt (eps));\n%! assert (u, [3, 4; 0, 2/3], sqrt (eps));\n\n%!test\n%! [l, u, p] = lu ([1, 2; 3, 4]);\n%! assert (l, [1, 0; 1/3, 1], sqrt (eps));\n%! assert (u, [3, 4; 0, 2/3], sqrt (eps));\n%! assert (p(:,:), [0, 1; 1, 0], sqrt (eps));\n\n%!test\n%! [l, u, p] = lu ([1, 2; 3, 4], \"vector\");\n%! assert (l, [1, 0; 1/3, 1], sqrt (eps));\n%! assert (u, [3, 4; 0, 2/3], sqrt (eps));\n%! assert (p, [2;1], sqrt (eps));\n\n%!test\n%! [l, u, p] = lu ([1, 2; 3, 4; 5, 6]);\n%! assert (l, [1, 0; 1/5, 1; 3/5, 1/2], sqrt (eps));\n%! assert (u, [5, 6; 0, 4/5], sqrt (eps));\n%! assert (p(:,:), [0, 0, 1; 1, 0, 0; 0 1 0], sqrt (eps));\n\n%!assert (lu (single ([1, 2; 3, 4])), single ([3, 4; 1/3, 2/3]), eps (\"single\"))\n\n%!test\n%! [l, u] = lu (single ([1, 2; 3, 4]));\n%! assert (l, single ([1/3, 1; 1, 0]), sqrt (eps (\"single\")));\n%! assert (u, single ([3, 4; 0, 2/3]), sqrt (eps (\"single\")));\n\n%!test\n%! [l, u, p] = lu (single ([1, 2; 3, 4]));\n%! assert (l, single ([1, 0; 1/3, 1]), sqrt (eps (\"single\")));\n%! assert (u, single ([3, 4; 0, 2/3]), sqrt (eps (\"single\")));\n%! assert (p(:,:), single ([0, 1; 1, 0]), sqrt (eps (\"single\")));\n\n%!test\n%! [l, u, p] = lu (single ([1, 2; 3, 4]), \"vector\");\n%! assert (l, single ([1, 0; 1/3, 1]), sqrt (eps (\"single\")));\n%! assert (u, single ([3, 4; 0, 2/3]), sqrt (eps (\"single\")));\n%! assert (p, single ([2;1]), sqrt (eps (\"single\")));\n\n%!test\n%! [l u p] = lu (single ([1, 2; 3, 4; 5, 6]));\n%! assert (l, single ([1, 0; 1/5, 1; 3/5, 1/2]), sqrt (eps (\"single\")));\n%! assert (u, single ([5, 6; 0, 4/5]), sqrt (eps (\"single\")));\n%! assert (p(:,:), single ([0, 0, 1; 1, 0, 0; 0 1 0]), sqrt (eps (\"single\")));\n\n# complex matrix input\n%!test\n%! C = [1, 0, 1, 0;\n%!      1i, 1/3, -1i, 1/3;\n%!      1, 2i/3, 1, -2i/3;\n%!      1i, -1/3, -1i, -1/3];\n%! [L, U, P] = lu (C);\n%! assert (rcond (C), 1/8, eps);\n%! assert (norm (P'*L*U - C, Inf) < eps);\n\n%!testif HAVE_UMFPACK\n%! Bi = [1 2 3 4 5 2 3 6 7 8 4 5 7 8 9];\n%! Bj = [1 3 4 5 6 7 8 9 11 12 13 14 15 16 17];\n%! Bv = [1 1 1 1 1 1 -1 1 1 1 1 -1 1 -1 1];\n%! B = sparse (Bi, Bj, Bv);\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! [L, U] = lu (B);\n%! assert (L*U, B);\n%! [L, U, P] = lu(B);\n%! assert (P'*L*U, B);\n%! [L, U, P, Q] = lu (B);\n%! assert (P'*L*U*Q', B);\n\n%!error lu ()\n%!testif HAVE_UMFPACK\n%! fail (\"[l,u] = lu (sparse (magic (3)))\", \"warning\", \"function may fail\");\n%!error <can not define pivoting threshold> lu ([1, 2; 3, 4], 2)\n\n*/\n\nstatic bool\ncheck_lu_dims (const octave_value& l, const octave_value& u,\n               const octave_value& p)\n{\n  octave_idx_type m = l.rows ();\n  octave_idx_type k = u.rows ();\n  octave_idx_type n = u.columns ();\n\n  return ((l.ndims () == 2 && u.ndims () == 2 && k == l.columns ())\n          && k == std::min (m, n)\n          && (p.is_undefined () || p.rows () == m));\n}\n\nDEFUN (luupdate, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{L}, @var{U}] =} luupdate (@var{L}, @var{U}, @var{x}, @var{y})\n@deftypefnx {} {[@var{L}, @var{U}, @var{P}] =} luupdate (@var{L}, @var{U}, @var{P}, @var{x}, @var{y})\nGiven an LU@tie{}factorization of a real or complex matrix\n@w{@var{A} = @var{L}*@var{U}}, @var{L}@tie{}lower unit trapezoidal and\n@var{U}@tie{}upper trapezoidal, return the LU@tie{}factorization\nof @w{@var{A} + @var{x}*@var{y}.'}, where @var{x} and @var{y} are\ncolumn vectors (rank-1 update) or matrices with equal number of columns\n(rank-k update).\n\nOptionally, row-pivoted updating can be used by supplying a row permutation\n(pivoting) matrix @var{P}; in that case, an updated permutation matrix is\nreturned.  Note that if @var{L}, @var{U}, @var{P} is a pivoted\nLU@tie{}factorization as obtained by @code{lu}:\n\n@example\n[@var{L}, @var{U}, @var{P}] = lu (@var{A});\n@end example\n\n@noindent\nthen a factorization of @tcode{@var{A}+@var{x}*@var{y}.'} can be obtained\neither as\n\n@example\n[@var{L1}, @var{U1}] = lu (@var{L}, @var{U}, @var{P}*@var{x}, @var{y})\n@end example\n\n@noindent\nor\n\n@example\n[@var{L1}, @var{U1}, @var{P1}] = lu (@var{L}, @var{U}, @var{P}, @var{x}, @var{y})\n@end example\n\nThe first form uses the unpivoted algorithm, which is faster, but less\nstable.  The second form uses a slower pivoted algorithm, which is more\nstable.\n\nThe matrix case is done as a sequence of rank-1 updates; thus, for large\nenough k, it will be both faster and more accurate to recompute the\nfactorization from scratch.\n@seealso{lu, cholupdate, qrupdate}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin != 4 && nargin != 5)\n    print_usage ();\n\n  bool pivoted = (nargin == 5);\n\n  octave_value argl = args(0);\n  octave_value argu = args(1);\n  octave_value argp = (pivoted ? args(2) : octave_value ());\n  octave_value argx = args(2 + pivoted);\n  octave_value argy = args(3 + pivoted);\n\n  if (! (argl.isnumeric () && argu.isnumeric ()\n         && argx.isnumeric () && argy.isnumeric ()\n         && (! pivoted || argp.is_perm_matrix ())))\n    error (\"luupdate: L, U, X, and Y must be numeric\");\n\n  if (! check_lu_dims (argl, argu, argp))\n    error (\"luupdate: dimension mismatch\");\n\n  PermMatrix P = (pivoted\n                  ? argp.perm_matrix_value ()\n                  : PermMatrix::eye (argl.rows ()));\n\n  if (argl.isreal () && argu.isreal ()\n      && argx.isreal () && argy.isreal ())\n    {\n      // all real case\n      if (argl.is_single_type () || argu.is_single_type ()\n          || argx.is_single_type () || argy.is_single_type ())\n        {\n          FloatMatrix L = argl.float_matrix_value ();\n          FloatMatrix U = argu.float_matrix_value ();\n          FloatMatrix x = argx.float_matrix_value ();\n          FloatMatrix y = argy.float_matrix_value ();\n\n          math::lu<FloatMatrix> fact (L, U, P);\n          if (pivoted)\n            fact.update_piv (x, y);\n          else\n            fact.update (x, y);\n\n          if (pivoted)\n            return ovl (get_lu_l (fact), get_lu_u (fact), fact.P ());\n          else\n            return ovl (get_lu_l (fact), get_lu_u (fact));\n        }\n      else\n        {\n          Matrix L = argl.matrix_value ();\n          Matrix U = argu.matrix_value ();\n          Matrix x = argx.matrix_value ();\n          Matrix y = argy.matrix_value ();\n\n          math::lu<Matrix> fact (L, U, P);\n          if (pivoted)\n            fact.update_piv (x, y);\n          else\n            fact.update (x, y);\n\n          if (pivoted)\n            return ovl (get_lu_l (fact), get_lu_u (fact), fact.P ());\n          else\n            return ovl (get_lu_l (fact), get_lu_u (fact));\n        }\n    }\n  else\n    {\n      // complex case\n      if (argl.is_single_type () || argu.is_single_type ()\n          || argx.is_single_type () || argy.is_single_type ())\n        {\n          FloatComplexMatrix L = argl.float_complex_matrix_value ();\n          FloatComplexMatrix U = argu.float_complex_matrix_value ();\n          FloatComplexMatrix x = argx.float_complex_matrix_value ();\n          FloatComplexMatrix y = argy.float_complex_matrix_value ();\n\n          math::lu<FloatComplexMatrix> fact (L, U, P);\n          if (pivoted)\n            fact.update_piv (x, y);\n          else\n            fact.update (x, y);\n\n          if (pivoted)\n            return ovl (get_lu_l (fact), get_lu_u (fact), fact.P ());\n          else\n            return ovl (get_lu_l (fact), get_lu_u (fact));\n        }\n      else\n        {\n          ComplexMatrix L = argl.complex_matrix_value ();\n          ComplexMatrix U = argu.complex_matrix_value ();\n          ComplexMatrix x = argx.complex_matrix_value ();\n          ComplexMatrix y = argy.complex_matrix_value ();\n\n          math::lu<ComplexMatrix> fact (L, U, P);\n          if (pivoted)\n            fact.update_piv (x, y);\n          else\n            fact.update (x, y);\n\n          if (pivoted)\n            return ovl (get_lu_l (fact), get_lu_u (fact), fact.P ());\n          else\n            return ovl (get_lu_l (fact), get_lu_u (fact));\n        }\n    }\n}\n\n/*\n%!shared A, u, v, Ac, uc, vc\n%! A = [0.091364  0.613038  0.999083;\n%!      0.594638  0.425302  0.603537;\n%!      0.383594  0.291238  0.085574;\n%!      0.265712  0.268003  0.238409;\n%!      0.669966  0.743851  0.445057 ];\n%!\n%! u = [0.85082;\n%!      0.76426;\n%!      0.42883;\n%!      0.53010;\n%!      0.80683 ];\n%!\n%! v = [0.98810;\n%!      0.24295;\n%!      0.43167 ];\n%!\n%! Ac = [0.620405 + 0.956953i  0.480013 + 0.048806i  0.402627 + 0.338171i;\n%!       0.589077 + 0.658457i  0.013205 + 0.279323i  0.229284 + 0.721929i;\n%!       0.092758 + 0.345687i  0.928679 + 0.241052i  0.764536 + 0.832406i;\n%!       0.912098 + 0.721024i  0.049018 + 0.269452i  0.730029 + 0.796517i;\n%!       0.112849 + 0.603871i  0.486352 + 0.142337i  0.355646 + 0.151496i ];\n%!\n%! uc = [0.20351 + 0.05401i;\n%!       0.13141 + 0.43708i;\n%!       0.29808 + 0.08789i;\n%!       0.69821 + 0.38844i;\n%!       0.74871 + 0.25821i ];\n%!\n%! vc = [0.85839 + 0.29468i;\n%!       0.20820 + 0.93090i;\n%!       0.86184 + 0.34689i ];\n%!\n\n%!testif HAVE_QRUPDATE_LUU\n%! [L,U,P] = lu (A);\n%! [L,U] = luupdate (L,U,P*u,v);\n%! assert (norm (vec (tril (L)-L), Inf) == 0);\n%! assert (norm (vec (triu (U)-U), Inf) == 0);\n%! assert (norm (vec (P'*L*U - A - u*v.'), Inf) < norm (A)*1e1*eps);\n%!\n%!testif HAVE_QRUPDATE_LUU\n%! [L,U,P] = lu (Ac);\n%! [L,U] = luupdate (L,U,P*uc,vc);\n%! assert (norm (vec (tril (L)-L), Inf) == 0);\n%! assert (norm (vec (triu (U)-U), Inf) == 0);\n%! assert (norm (vec (P'*L*U - Ac - uc*vc.'), Inf) < norm (Ac)*1e1*eps);\n\n%!testif HAVE_QRUPDATE_LUU\n%! [L,U,P] = lu (single (A));\n%! [L,U] = luupdate (L,U,P* single (u), single (v));\n%! assert (norm (vec (tril (L)-L), Inf) == 0);\n%! assert (norm (vec (triu (U)-U), Inf) == 0);\n%! assert (norm (vec (P'*L*U - single (A) - single (u)* single (v).'), Inf)\n%!         < norm (single (A))*1e1* eps (\"single\"));\n%!\n%!testif HAVE_QRUPDATE_LUU\n%! [L,U,P] = lu (single (Ac));\n%! [L,U] = luupdate (L,U,P* single (uc),single (vc));\n%! assert (norm (vec (tril (L)-L), Inf) == 0);\n%! assert (norm (vec (triu (U)-U), Inf) == 0);\n%! assert (norm (vec (P'*L*U - single (Ac) - single (uc)* single (vc).'), Inf)\n%!         < norm (single (Ac))*1e1* eps (\"single\"));\n\n%!testif HAVE_QRUPDATE_LUU\n%! [L,U,P] = lu (A);\n%! [L,U,P] = luupdate (L,U,P,u,v);\n%! assert (norm (vec (tril (L)-L), Inf) == 0);\n%! assert (norm (vec (triu (U)-U), Inf) == 0);\n%! assert (norm (vec (P'*L*U - A - u*v.'), Inf) < norm (A)*1e1*eps);\n%!\n%!testif HAVE_QRUPDATE_LUU\n%! [L,U,P] = lu (A);\n%! [~,ordcols] = max (P,[],1);\n%! [~,ordrows] = max (P,[],2);\n%! P1 = eye (size (P))(:,ordcols);\n%! P2 = eye (size (P))(ordrows,:);\n%! assert (P1 == P);\n%! assert (P2 == P);\n%! [L,U,P] = luupdate (L,U,P,u,v);\n%! [L,U,P1] = luupdate (L,U,P1,u,v);\n%! [L,U,P2] = luupdate (L,U,P2,u,v);\n%! assert (P1 == P);\n%! assert (P2 == P);\n%!\n%!testif HAVE_QRUPDATE_LUU\n%! [L,U,P] = lu (Ac);\n%! [L,U,P] = luupdate (L,U,P,uc,vc);\n%! assert (norm (vec (tril (L)-L), Inf) == 0);\n%! assert (norm (vec (triu (U)-U), Inf) == 0);\n%! assert (norm (vec (P'*L*U - Ac - uc*vc.'), Inf) < norm (Ac)*1e1*eps);\n\n%!testif HAVE_QRUPDATE_LUU\n%! [L,U,P] = lu (single (A));\n%! [L,U,P] = luupdate (L,U,P,single (u),single (v));\n%! assert (norm (vec (tril (L)-L), Inf) == 0);\n%! assert (norm (vec (triu (U)-U), Inf) == 0);\n%! assert (norm (vec (P'*L*U - single (A) - single (u)* single (v).'), Inf)\n%!         < norm (single (A))*1e1* eps (\"single\"));\n%!\n%!testif HAVE_QRUPDATE_LUU\n%! [L,U,P] = lu (single (Ac));\n%! [L,U,P] = luupdate (L,U,P,single (uc),single (vc));\n%! assert (norm (vec (tril (L)-L), Inf) == 0);\n%! assert (norm (vec (triu (U)-U), Inf) == 0);\n%! assert (norm (vec (P'*L*U - single (Ac) - single (uc)* single (vc).'), Inf)\n%!         < norm (single (Ac))*1e1* eps (\"single\"));\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/mappers.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"oct-specfun.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (abs, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{z} =} abs (@var{x})\nCompute the magnitude of @var{x}.\n\nThe magnitude is defined as\n@tex\n$|z| = \\sqrt{x^2 + y^2}$.\n@end tex\n@ifnottex\n|@var{z}| = @code{sqrt (x^2 + y^2)}.\n@end ifnottex\n\nFor example:\n\n@example\n@group\nabs (3 + 4i)\n     @xresult{} 5\n@end group\n@end example\n@seealso{arg}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).abs ());\n}\n\n/*\n%!assert (abs (1), 1)\n%!assert (abs (-3.5), 3.5)\n%!assert (abs (3+4i), 5)\n%!assert (abs (3-4i), 5)\n%!assert (abs ([1.1, 3i; 3+4i, -3-4i]), [1.1, 3; 5, 5])\n\n%!assert (abs (single (1)), single (1))\n%!assert (abs (single (-3.5)), single (3.5))\n%!assert (abs (single (3+4i)), single (5))\n%!assert (abs (single (3-4i)), single (5))\n%!assert (abs (single ([1.1, 3i; 3+4i, -3-4i])), single ([1.1, 3; 5, 5]))\n\n%!error abs ()\n%!error abs (1, 2)\n*/\n\nDEFUN (acos, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} acos (@var{x})\nCompute the inverse cosine in radians for each element of @var{x}.\n@seealso{cos, acosd}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).acos ());\n}\n\n/*\n%!shared rt2, rt3\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n\n%!test\n%! x = [1, rt3/2, rt2/2, 1/2, 0, -1/2, -rt2/2, -rt3/2, -1];\n%! v = [0, pi/6, pi/4, pi/3, pi/2, 2*pi/3, 3*pi/4, 5*pi/6, pi];\n%! assert (acos (x), v, sqrt (eps));\n\n%!test\n%! x = single ([1, rt3/2, rt2/2, 1/2, 0, -1/2, -rt2/2, -rt3/2, -1]);\n%! v = single ([0, pi/6, pi/4, pi/3, pi/2, 2*pi/3, 3*pi/4, 5*pi/6, pi]);\n%! assert (acos (x), v, sqrt (eps (\"single\")));\n\n## Test values on either side of branch cut\n%!test\n%! rval = 0;\n%! ival = 1.31695789692481671;\n%! obs = acos ([2, 2-i*eps, 2+i*eps]);\n%! exp = [rval + ival*i, rval + ival*i, rval - ival*i];\n%! assert (obs, exp, 3*eps);\n%! rval = pi;\n%! obs = acos ([-2, -2-i*eps, -2+i*eps]);\n%! exp = [rval - ival*i, rval + ival*i, rval - ival*i];\n%! assert (obs, exp, 5*eps);\n%! assert (acos ([2 0]),  [ival*i, pi/2], 3*eps);\n%! assert (acos ([2 0i]), [ival*i, pi/2], 3*eps);\n\n## Test large magnitude arguments (bug #45507)\n## Test fails with older versions of libm, solution is to upgrade.\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")  <*45507>\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [0, pi, pi/2, pi/2];\n%! assert (real (acos (x)), v);\n\n%!testif HAVE_LLVM_LIBCXX  <52627>\n%! ## Same test code as above, but intended for test statistics with libc++.\n%! ## Their trig/hyperbolic functions have huge tolerances.\n%! ## LLVM libc++ returns 0 for x(2) and x(4).\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [0, pi, pi/2, pi/2];\n%! assert (real (acos (x)), v);\n\n%!error acos ()\n%!error acos (1, 2)\n*/\n\nDEFUN (acosh, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} acosh (@var{x})\nCompute the inverse hyperbolic cosine for each element of @var{x}.\n@seealso{cosh}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).acosh ());\n}\n\n/*\n%!testif ; ! __have_feature__ (\"BSD_LIBC\")\n%! x = [1, 0, -1, 0];\n%! v = [0, pi/2*i, pi*i, pi/2*i];\n%! assert (acosh (x), v, sqrt (eps));\n\n%!testif HAVE_BSD_LIBC   <52627>\n%! ## Same test code as above, but intended only for test statistics with BSD\n%! ## libc.  The trig/hyperbolic functions in that C library used to have huge\n%! ## tolerances.\n%! x = [1, 0, -1, 0];\n%! v = [0, pi/2*i, pi*i, pi/2*i];\n%! assert (acosh (x), v, sqrt (eps));\n\n## FIXME: std::acosh on Windows platforms and with LLVM libc++, returns a\n## result that differs by 1 in the last significant digit.  This is ~30*eps\n## which is quite large.\n## The decision now (9/15/2016) is to mark the test with a bug number so\n## it is understood why it is failing, and wait for MinGW and LLVM to improve\n## their std library.\n%!test <49091>\n%! re = 2.99822295029797;\n%! im = pi/2;\n%! assert (acosh (-10i), re - i*im);\n\n%!testif ; ! __have_feature__ (\"BSD_LIBC\")\n%! x = single ([1, 0, -1, 0]);\n%! v = single ([0, pi/2*i, pi*i, pi/2*i]);\n%! assert (acosh (x), v, sqrt (eps (\"single\")));\n\n%!testif HAVE_BSD_LIBC  <52627>\n%! ## Same test code as above, but intended only for test statistics with BSD\n%! ## libc.  The trig/hyperbolic functions in that C library used to have huge\n%! ## tolerances.\n%! x = single ([1, 0, -1, 0]);\n%! v = single ([0, pi/2*i, pi*i, pi/2*i]);\n%! assert (acosh (x), v, sqrt (eps (\"single\")));\n\n%!test <49091>\n%! re = single (2.99822295029797);\n%! im = single (pi/2);\n%! assert (acosh (single (10i)), re + i*im, 5* eps (\"single\"));\n%! assert (acosh (single (-10i)), re - i*im, 5* eps (\"single\"));\n\n## Test large magnitude arguments (bug #45507)\n## Test fails with older versions of libm, solution is to upgrade.\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")  <*45507>\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [0, pi, pi/2, -pi/2];\n%! assert (imag (acosh (x)), v);\n\n%!testif HAVE_LLVM_LIBCXX  <52627>\n%! ## Same test code as above, but intended for test statistics with libc++.\n%! ## Their trig/hyperbolic functions have huge tolerances.\n%! ## LLVM libc++ returns 0 for x(2) and x(4).\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [0, pi, pi/2, -pi/2];\n%! assert (imag (acosh (x)), v);\n\n%!error acosh ()\n%!error acosh (1, 2)\n*/\n\nDEFUN (angle, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{theta} =} angle (@var{z})\n@xref{XREFarg,,arg}.\n@seealso{arg}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).arg ());\n}\n\nDEFUN (arg, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{theta} =} arg (@var{z})\n@deftypefnx {} {@var{theta} =} angle (@var{z})\nCompute the argument, i.e., angle of @var{z}.\n\nThis is defined as,\n@tex\n$\\theta = atan2 (y, x),$\n@end tex\n@ifnottex\n@var{theta} = @code{atan2 (@var{y}, @var{x})},\n@end ifnottex\nin radians.\n\nFor example:\n\n@example\n@group\narg (3 + 4i)\n     @xresult{} 0.92730\n@end group\n@end example\n@seealso{abs}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).arg ());\n}\n\n/*\n%!assert (arg (1), 0)\n%!assert (arg (i), pi/2)\n%!assert (arg (-1), pi)\n%!assert (arg (-i), -pi/2)\n%!assert (arg ([1, i; -1, -i]), [0, pi/2; pi, -pi/2])\n\n%!assert (arg (single (1)), single (0))\n%!assert (arg (single (i)), single (pi/2))\n%!test\n%! if (ismac ())\n%!   ## Avoid failing on a MacOS feature or bug, depending on your view\n%!   assert (arg (single (-1)), single (pi), 2* eps (single (1)));\n%! else\n%!   assert (arg (single (-1)), single (pi));\n%! endif\n%!assert (arg (single (-i)), single (-pi/2))\n%!assert (arg (single ([1, i; -1, -i])),\n%!        single ([0, pi/2; pi, -pi/2]), 2e1* eps (\"single\"))\n\n%!error arg ()\n%!error arg (1, 2)\n*/\n\nDEFUN (asin, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} asin (@var{x})\nCompute the inverse sine in radians for each element of @var{x}.\n@seealso{sin, asind}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).asin ());\n}\n\n/*\n%!shared rt2, rt3\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n\n%!test\n%! x = [0, 1/2, rt2/2, rt3/2, 1, rt3/2, rt2/2, 1/2, 0];\n%! v = [0, pi/6, pi/4, pi/3, pi/2, pi/3, pi/4, pi/6, 0];\n%! assert (asin (x), v, sqrt (eps));\n\n%!test\n%! x = single ([0, 1/2, rt2/2, rt3/2, 1, rt3/2, rt2/2, 1/2, 0]);\n%! v = single ([0, pi/6, pi/4, pi/3, pi/2, pi/3, pi/4, pi/6, 0]);\n%! assert (asin (x), v, sqrt (eps (\"single\")));\n\n## Test values on either side of branch cut\n%!test\n%! rval = pi/2;\n%! ival = 1.31695789692481635;\n%! obs = asin ([2, 2-i*eps, 2+i*eps]);\n%! exp = [rval - ival*i, rval - ival*i, rval + ival*i];\n%! if (__have_feature__ (\"BSD_LIBC\"))\n%!   ## BSD libc seems to implement asin with less accuracy.\n%!   tol = 6*eps;\n%! else\n%!   tol = 2*eps;\n%! endif\n%! assert (obs, exp, tol);\n%! obs = asin ([-2, -2-i*eps, -2+i*eps]);\n%! exp = [-rval + ival*i, -rval - ival*i, -rval + ival*i];\n%! assert (obs, exp, tol);\n%! assert (asin ([2 0]),  [rval - ival*i, 0], tol);\n%! assert (asin ([2 0i]), [rval - ival*i, 0], tol);\n\n## Test large magnitude arguments (bug #45507)\n## Test fails with older versions of libm, solution is to upgrade.\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")  <*45507>\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [pi/2, -pi/2, 0, -0];\n%! assert (real (asin (x)), v);\n\n%!testif HAVE_LLVM_LIBCXX  <52627>\n%! ## Same test code as above, but intended for test statistics with libc++.\n%! ## Their trig/hyperbolic functions have huge tolerances.\n%! ## LLVM libc++ returns 0 for x(1) and x(2).\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [pi/2, -pi/2, 0, -0];\n%! assert (real (asin (x)), v);\n\n%!error asin ()\n%!error asin (1, 2)\n*/\n\nDEFUN (asinh, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} asinh (@var{x})\nCompute the inverse hyperbolic sine for each element of @var{x}.\n@seealso{sinh}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).asinh ());\n}\n\n/*\n%!test\n%! v = [0, pi/2*i, 0, -pi/2*i];\n%! x = [0, i, 0, -i];\n%! assert (asinh (x), v, sqrt (eps));\n\n%!test\n%! v = single ([0, pi/2*i, 0, -pi/2*i]);\n%! x = single ([0, i, 0, -i]);\n%! assert (asinh (x), v, sqrt (eps (\"single\")));\n\n## Test large magnitude arguments (bug #45507)\n## Test fails with older versions of libm, solution is to upgrade.\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")  <*45507>\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [0, 0, pi/2, -pi/2];\n%! assert (imag (asinh (x)), v);\n\n%!testif HAVE_LLVM_LIBCXX  <52627>\n%! ## Same test code as above, but intended for test statistics with libc++.\n%! ## Their trig/hyperbolic functions have huge tolerances.\n%! ## LLVM libc++ returns 0 for x(4).\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [0, 0, pi/2, -pi/2];\n%! assert (imag (asinh (x)), v);\n\n%!error asinh ()\n%!error asinh (1, 2)\n*/\n\nDEFUN (atan, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} atan (@var{x})\nCompute the inverse tangent in radians for each element of @var{x}.\n@seealso{tan, atand}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).atan ());\n}\n\n/*\n%!shared rt2, rt3\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n\n%!test\n%! v = [0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0];\n%! x = [0, rt3/3, 1, rt3, -rt3, -1, -rt3/3, 0];\n%! assert (atan (x), v, sqrt (eps));\n\n%!test\n%! v = single ([0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0]);\n%! x = single ([0, rt3/3, 1, rt3, -rt3, -1, -rt3/3, 0]);\n%! assert (atan (x), v, sqrt (eps (\"single\")));\n\n## Test large magnitude arguments (bug #44310, bug #45507)\n%!test <*44310>\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [pi/2, -pi/2, pi/2, -pi/2];\n%! assert (real (atan (x)), v);\n%! assert (imag (atan (x)), [0, 0, 0, 0], eps);\n\n%!error atan ()\n%!error atan (1, 2)\n*/\n\nDEFUN (atanh, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} atanh (@var{x})\nCompute the inverse hyperbolic tangent for each element of @var{x}.\n@seealso{tanh}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).atanh ());\n}\n\n/*\n%!test\n%! v = [0, 0];\n%! x = [0, 0];\n%! assert (atanh (x), v, sqrt (eps));\n\n%!test\n%! v = single ([0, 0]);\n%! x = single ([0, 0]);\n%! assert (atanh (x), v, sqrt (eps (\"single\")));\n\n## Test large magnitude arguments (bug #44310, bug #45507)\n%!test <*44310>\n%! x = [1, -1, i, -i] .* 1e150;\n%! v = [pi/2, pi/2, pi/2, -pi/2];\n%! assert (imag (atanh (x)), v);\n%! assert (real (atanh (x)), [0, 0, 0, 0], eps);\n\n%!error atanh ()\n%!error atanh (1, 2)\n*/\n\nDEFUN (cbrt, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} cbrt (@var{x})\nCompute the real-valued cube root of each element of @var{x}.\n\nUnlike @code{@var{x}^(1/3)}, the result will be negative if @var{x} is\nnegative.\n\nIf any element of @var{x} is complex, @code{cbrt} aborts with an error.\n@seealso{nthroot}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).cbrt ());\n}\n\n/*\n%!assert (cbrt (64), 4)\n%!assert (cbrt (-125), -5)\n%!assert (cbrt (0), 0)\n%!assert (cbrt (Inf), Inf)\n%!assert (cbrt (-Inf), -Inf)\n%!assert (cbrt (NaN), NaN)\n%!assert (cbrt (2^300), 2^100)\n%!assert (cbrt (125*2^300), 5*2^100)\n\n%!error cbrt ()\n%!error cbrt (1, 2)\n*/\n\nDEFUN (ceil, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} ceil (@var{x})\nReturn the smallest integer not less than @var{x}.\n\nThis is equivalent to rounding towards positive infinity.\n\nIf @var{x} is complex, return\n@code{ceil (real (@var{x})) + ceil (imag (@var{x})) * I}.\n\n@example\n@group\nceil ([-2.7, 2.7])\n    @xresult{} -2    3\n@end group\n@end example\n@seealso{floor, round, fix}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).ceil ());\n}\n\n/*\n## double precision\n%!assert (ceil ([2, 1.1, -1.1, -1]), [2, 2, -1, -1])\n\n## complex double precision\n%!assert (ceil ([2+2i, 1.1+1.1i, -1.1-1.1i, -1-i]), [2+2i, 2+2i, -1-i, -1-i])\n\n## single precision\n%!assert (ceil (single ([2, 1.1, -1.1, -1])), single ([2, 2, -1, -1]))\n\n## complex single precision\n%!assert (ceil (single ([2+2i, 1.1+1.1i, -1.1-1.1i, -1-i])),\n%!        single ([2+2i, 2+2i, -1-i, -1-i]))\n\n%!error ceil ()\n%!error ceil (1, 2)\n*/\n\nDEFUN (conj, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{zc} =} conj (@var{z})\nReturn the complex conjugate of @var{z}.\n\nThe complex conjugate is defined as\n@tex\n$\\bar{z} = x - iy$.\n@end tex\n@ifnottex\n@code{conj (@var{z})} = @var{x} - @var{i}@var{y}.\n@end ifnottex\n@seealso{real, imag}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).conj ());\n}\n\n/*\n%!assert (conj (1), 1)\n%!assert (conj (i), -i)\n%!assert (conj (1+i), 1-i)\n%!assert (conj (1-i), 1+i)\n%!assert (conj ([-1, -i; -1+i, -1-i]), [-1, i; -1-i, -1+i])\n\n%!assert (conj (single (1)), single (1))\n%!assert (conj (single (i)), single (-i))\n%!assert (conj (single (1+i)), single (1-i))\n%!assert (conj (single (1-i)), single (1+i))\n%!assert (conj (single ([-1, -i; -1+i, -1-i])), single ([-1, i; -1-i, -1+i]))\n\n%!error conj ()\n%!error conj (1, 2)\n*/\n\nDEFUN (cos, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} cos (@var{x})\nCompute the cosine for each element of @var{x} in radians.\n@seealso{acos, cosd, cosh}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).cos ());\n}\n\n/*\n%!shared rt2, rt3\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n\n%!test\n%! x = [0, pi/6, pi/4, pi/3, pi/2, 2*pi/3, 3*pi/4, 5*pi/6, pi];\n%! v = [1, rt3/2, rt2/2, 1/2, 0, -1/2, -rt2/2, -rt3/2, -1];\n%! assert (cos (x), v, sqrt (eps));\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! x = single ([0, pi/6, pi/4, pi/3, pi/2, 2*pi/3, 3*pi/4, 5*pi/6, pi]);\n%! v = single ([1, rt3/2, rt2/2, 1/2, 0, -1/2, -rt2/2, -rt3/2, -1]);\n%! assert (cos (x), v, sqrt (eps (\"single\")));\n\n%!error cos ()\n%!error cos (1, 2)\n*/\n\nDEFUN (cosh, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} cosh (@var{x})\nCompute the hyperbolic cosine for each element of @var{x}.\n@seealso{acosh, sinh, tanh}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).cosh ());\n}\n\n/*\n%!test\n%! x = [0, pi/2*i, pi*i, 3*pi/2*i];\n%! v = [1, 0, -1, 0];\n%! assert (cosh (x), v, sqrt (eps));\n\n%!test\n%! x = single ([0, pi/2*i, pi*i, 3*pi/2*i]);\n%! v = single ([1, 0, -1, 0]);\n%! assert (cosh (x), v, sqrt (eps (\"single\")));\n\n%!error cosh ()\n%!error cosh (1, 2)\n*/\n\nDEFUN (erf, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} erf (@var{z})\nCompute the error function.\n\nThe error function is defined as\n@tex\n$$\n {\\rm erf} (z) = {2 \\over \\sqrt{\\pi}}\\int_0^z e^{-t^2} dt\n$$\n@end tex\n@ifnottex\n\n@example\n@group\n                        z\n              2        /\nerf (z) = --------- *  | e^(-t^2) dt\n          sqrt (pi)    /\n                    t=0\n@end group\n@end example\n\n@end ifnottex\n@seealso{erfc, erfcx, erfi, dawson, erfinv, erfcinv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).erf ());\n}\n\n/*\n%!test\n%! a = -1i* sqrt (-1/(6.4187*6.4187));\n%! assert (erf (a), erf (real (a)));\n\n%!test\n%! x = [0,.5,1];\n%! v = [0, .520499877813047, .842700792949715];\n%! assert (erf (x), v, 1.e-10);\n%! assert (erf (-x), -v, 1.e-10);\n%! assert (erfc (x), 1-v, 1.e-10);\n%! assert (erfinv (v), x, 1.e-10);\n\n%!test\n%! a = -1i* sqrt (single (-1/(6.4187*6.4187)));\n%! assert (erf (a), erf (real (a)));\n\n%!test\n%! x = single ([0,.5,1]);\n%! v = single ([0, .520499877813047, .842700792949715]);\n%! assert (erf (x), v, 1.e-6);\n%! assert (erf (-x), -v, 1.e-6);\n%! assert (erfc (x), 1-v, 1.e-6);\n%! assert (erfinv (v), x, 1.e-6);\n\n%!test\n%! x = [1+2i,-1+2i,1e-6+2e-6i,0+2i];\n%! v = [-0.53664356577857-5.04914370344703i, 0.536643565778565-5.04914370344703i, 0.112837916709965e-5+0.225675833419178e-5i, 18.5648024145755526i];\n%! assert (erf (x), v, -1.e-10);\n%! assert (erf (-x), -v, -1.e-10);\n%! assert (erfc (x), 1-v, -1.e-10);\n\n%!error erf ()\n%!error erf (1, 2)\n*/\n\nDEFUN (erfinv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} erfinv (@var{x})\nCompute the inverse error function.\n\nThe inverse error function is defined such that\n\n@example\nerf (@var{y}) == @var{x}\n@end example\n@seealso{erf, erfc, erfcx, erfi, dawson, erfcinv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).erfinv ());\n}\n\n/*\n## middle region\n%!assert (erf (erfinv ([-0.9 -0.3 0 0.4 0.8])), [-0.9 -0.3 0 0.4 0.8], eps)\n%!assert (erf (erfinv (single ([-0.9 -0.3 0 0.4 0.8]))),\n%!        single ([-0.9 -0.3 0 0.4 0.8]), eps (\"single\"))\n## tail region\n%!assert (erf (erfinv ([-0.999 -0.99 0.9999 0.99999])),\n%!        [-0.999 -0.99 0.9999 0.99999], eps)\n%!assert (erf (erfinv (single ([-0.999 -0.99 0.9999 0.99999]))),\n%!        single ([-0.999 -0.99 0.9999 0.99999]), eps (\"single\"))\n## backward - loss of accuracy\n%!assert (erfinv (erf ([-3 -1 -0.4 0.7 1.3 2.8])),\n%!        [-3 -1 -0.4 0.7 1.3 2.8], -1e-12)\n%!assert (erfinv (erf (single ([-3 -1 -0.4 0.7 1.3 2.8]))),\n%!        single ([-3 -1 -0.4 0.7 1.3 2.8]), -1e-4)\n## exceptional\n%!assert (erfinv ([-1, 1, 1.1, -2.1]), [-Inf, Inf, NaN, NaN])\n%!error erfinv (1+2i)\n\n%!error erfinv ()\n%!error erfinv (1, 2)\n*/\n\nDEFUN (erfcinv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} erfcinv (@var{x})\nCompute the inverse complementary error function.\n\nThe inverse complementary error function is defined such that\n\n@example\nerfc (@var{y}) == @var{x}\n@end example\n@seealso{erfc, erf, erfcx, erfi, dawson, erfinv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).erfcinv ());\n}\n\n/*\n## middle region\n%!assert (erfc (erfcinv ([1.9 1.3 1 0.6 0.2])), [1.9 1.3 1 0.6 0.2], eps)\n%!assert (erfc (erfcinv (single ([1.9 1.3 1 0.6 0.2]))),\n%!        single ([1.9 1.3 1 0.6 0.2]), eps (\"single\"))\n## tail region\n%!assert (erfc (erfcinv ([0.001 0.01 1.9999 1.99999])),\n%!        [0.001 0.01 1.9999 1.99999], eps)\n%!assert (erfc (erfcinv (single ([0.001 0.01 1.9999 1.99999]))),\n%!        single ([0.001 0.01 1.9999 1.99999]), eps (\"single\"))\n## backward - loss of accuracy\n%!assert (erfcinv (erfc ([-3 -1 -0.4 0.7 1.3 2.8])),\n%!        [-3 -1 -0.4 0.7 1.3 2.8], -1e-12)\n%!testif ; ! ispc ()\n%! assert (erfcinv (erfc (single ([-3 -1 -0.4 0.7 1.3 2.8]))),\n%!         single ([-3 -1 -0.4 0.7 1.3 2.8]), -1e-4)\n%!testif ; ispc ()  <65075>\n%! ## Same test code as above, but intended for test statistics with the UCRT.\n%! ## The deviations are twice as high with it.\n%! assert (erfcinv (erfc (single ([-3 -1 -0.4 0.7 1.3 2.8]))),\n%!         single ([-3 -1 -0.4 0.7 1.3 2.8]), -1e-4)\n## exceptional\n%!assert (erfcinv ([2, 0, -0.1, 2.1]), [-Inf, Inf, NaN, NaN])\n%!error erfcinv (1+2i)\n\n%!error erfcinv ()\n%!error erfcinv (1, 2)\n*/\n\nDEFUN (erfc, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} erfc (@var{z})\nCompute the complementary error function.\n\nThe complementary error function is defined as\n@tex\n$1 - {\\rm erf} (z)$.\n@end tex\n@ifnottex\n@w{@code{1 - erf (@var{z})}}.\n@end ifnottex\n@seealso{erfcinv, erfcx, erfi, dawson, erf, erfinv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).erfc ());\n}\n\n/*\n%!test\n%! a = -1i* sqrt (-1/(6.4187*6.4187));\n%! assert (erfc (a), erfc (real (a)));\n\n%!error erfc ()\n%!error erfc (1, 2)\n*/\n\nDEFUN (erfcx, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} erfcx (@var{z})\nCompute the scaled complementary error function.\n\nThe scaled complementary error function is defined as\n@tex\n$$\n e^{z^2} {\\rm erfc} (z) \\equiv e^{z^2} (1 - {\\rm erf} (z))\n$$\n@end tex\n@ifnottex\n\n@example\nexp (z^2) * erfc (z)\n@end example\n\n@end ifnottex\n@seealso{erfc, erf, erfi, dawson, erfinv, erfcinv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).erfcx ());\n}\n\n/*\n\n%!test\n%! x = [1+2i,-1+2i,1e-6+2e-6i,0+2i];\n%! assert (erfcx (x), exp (x.^2) .* erfc (x), -1.e-10);\n\n%!test\n%! x = [100, 100+20i];\n%! v = [0.0056416137829894329, 0.0054246791754558-0.00108483153786434i];\n%! assert (erfcx (x), v, -1.e-10);\n\n%!error erfcx ()\n%!error erfcx (1, 2)\n*/\n\nDEFUN (erfi, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} erfi (@var{z})\nCompute the imaginary error function.\n\nThe imaginary error function is defined as\n@tex\n$$\n -i {\\rm erf} (iz)\n$$\n@end tex\n@ifnottex\n\n@example\n-i * erf (i*z)\n@end example\n\n@end ifnottex\n@seealso{erfc, erf, erfcx, dawson, erfinv, erfcinv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).erfi ());\n}\n\n/*\n\n%!test\n%! x = [-0.1, 0.1, 1, 1+2i,-1+2i,1e-6+2e-6i,0+2i];\n%! assert (erfi (x), -i * erf (i*x), -1.e-10);\n\n%!error erfi ()\n%!error erfi (1, 2)\n*/\n\nDEFUN (dawson, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} dawson (@var{z})\nCompute the Dawson (scaled imaginary error) function.\n\nThe Dawson function is defined as\n@tex\n$$\n {\\sqrt{\\pi} \\over 2} e^{-z^2} {\\rm erfi} (z) \\equiv -i {\\sqrt{\\pi} \\over 2} e^{-z^2} {\\rm erf} (iz)\n$$\n@end tex\n@ifnottex\n\n@example\n(sqrt (pi) / 2) * exp (-z^2) * erfi (z)\n@end example\n\n@end ifnottex\n@seealso{erfc, erf, erfcx, erfi, erfinv, erfcinv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).dawson ());\n}\n\n/*\n\n%!test\n%! x = [0.1, 1, 1+2i,-1+2i,1e-4+2e-4i,0+2i];\n%! v = [0.099335992397852861, 0.53807950691, -13.38892731648-11.828715104i, 13.38892731648-11.828715104i, 0.0001000000073333+0.000200000001333i, 48.160012114291i];\n%! assert (dawson (x), v, -1.e-10);\n%! assert (dawson (-x), -v, -1.e-10);\n\n%!error dawson ()\n%!error dawson (1, 2)\n*/\n\nDEFUN (exp, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} exp (@var{x})\nCompute\n@tex\n$e^{x}$\n@end tex\n@ifnottex\n@code{e^x}\n@end ifnottex\nfor each element of @var{x}.\n\nTo compute the matrix exponential, @pxref{Linear Algebra}.\n@seealso{log}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).exp ());\n}\n\n/*\n%!assert (exp ([0, 1, -1, -1000]), [1, e, 1/e, 0], sqrt (eps))\n%!assert (exp (1+i), e * (cos (1) + sin (1) * i), sqrt (eps))\n%!assert (exp (single ([0, 1, -1, -1000])),\n%!        single ([1, e, 1/e, 0]), sqrt (eps (\"single\")))\n%!assert (exp (single (1+i)),\n%!        single (e * (cos (1) + sin (1) * i)), sqrt (eps (\"single\")))\n\n%!assert (exp ([Inf, -Inf, NaN]), [Inf 0 NaN])\n%!assert (exp (single ([Inf, -Inf, NaN])), single ([Inf 0 NaN]))\n\n%!error exp ()\n%!error exp (1, 2)\n*/\n\nDEFUN (expm1, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} expm1 (@var{x})\nCompute\n@tex\n$ e^{x} - 1 $\n@end tex\n@ifnottex\n@code{exp (@var{x}) - 1}\n@end ifnottex\naccurately in the neighborhood of zero.\n@seealso{exp}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).expm1 ());\n}\n\n/*\n%!assert (expm1 (2*eps), 2*eps, 1e-29)\n\n%!assert (expm1 ([Inf, -Inf, NaN]), [Inf -1 NaN])\n%!assert (expm1 (single ([Inf, -Inf, NaN])), single ([Inf -1 NaN]))\n\n%!error expm1 ()\n%!error expm1 (1, 2)\n*/\n\nDEFUN (isfinite, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isfinite (@var{x})\nReturn a logical array which is true where the elements of @var{x} are\nfinite values and false where they are not.\n\nFor example:\n\n@example\n@group\nisfinite ([13, Inf, NA, NaN])\n     @xresult{} [ 1, 0, 0, 0 ]\n@end group\n@end example\n@seealso{isinf, isnan, isna}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isfinite ());\n}\n\n/*\n%!assert (! isfinite (Inf))\n%!assert (! isfinite (NaN))\n%!assert (isfinite (rand (1,10)))\n\n%!assert (! isfinite (single (Inf)))\n%!assert (! isfinite (single (NaN)))\n%!assert (isfinite (single (rand (1,10))))\n%!assert (isfinite ('a'))\n\n%!error isfinite ()\n%!error isfinite (1, 2)\n*/\n\nDEFUN (fix, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} fix (@var{x})\nTruncate fractional portion of @var{x} and return the integer portion.\n\nThis is equivalent to rounding towards zero.  If @var{x} is complex, return\n@code{fix (real (@var{x})) + fix (imag (@var{x})) * I}.\n\n@example\n@group\nfix ([-2.7, 2.7])\n   @xresult{} -2    2\n@end group\n@end example\n@seealso{ceil, floor, round}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).fix ());\n}\n\n/*\n%!assert (fix ([1.1, 1, -1.1, -1]), [1, 1, -1, -1])\n%!assert (fix ([1.1+1.1i, 1+i, -1.1-1.1i, -1-i]), [1+i, 1+i, -1-i, -1-i])\n%!assert (fix (single ([1.1, 1, -1.1, -1])), single ([1, 1, -1, -1]))\n%!assert (fix (single ([1.1+1.1i, 1+i, -1.1-1.1i, -1-i])),\n%!        single ([1+i, 1+i, -1-i, -1-i]))\n\n%!error fix ()\n%!error fix (1, 2)\n*/\n\nDEFUN (floor, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} floor (@var{x})\nReturn the largest integer not greater than @var{x}.\n\nThis is equivalent to rounding towards negative infinity.  If @var{x} is\ncomplex, return @code{floor (real (@var{x})) + floor (imag (@var{x})) * I}.\n\n@example\n@group\nfloor ([-2.7, 2.7])\n     @xresult{} -3    2\n@end group\n@end example\n@seealso{ceil, round, fix}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).floor ());\n}\n\n/*\n%!assert (floor ([2, 1.1, -1.1, -1]), [2, 1, -2, -1])\n%!assert (floor ([2+2i, 1.1+1.1i, -1.1-1.1i, -1-i]), [2+2i, 1+i, -2-2i, -1-i])\n%!assert (floor (single ([2, 1.1, -1.1, -1])), single ([2, 1, -2, -1]))\n%!assert (floor (single ([2+2i, 1.1+1.1i, -1.1-1.1i, -1-i])),\n%!        single ([2+2i, 1+i, -2-2i, -1-i]))\n\n%!error floor ()\n%!error floor (1, 2)\n*/\n\nDEFUN (gamma, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} gamma (@var{z})\nCompute the Gamma function.\n\nThe Gamma function is defined as\n@tex\n$$\n \\Gamma (z) = \\int_0^\\infty t^{z-1} e^{-t} dt.\n$$\n@end tex\n@ifnottex\n\n@example\n@group\n             infinity\n            /\ngamma (z) = | t^(z-1) exp (-t) dt.\n            /\n         t=0\n@end group\n@end example\n\n@end ifnottex\n\nProgramming Note: The gamma function can grow quite large even for small\ninput values.  In many cases it may be preferable to use the natural\nlogarithm of the gamma function (@code{gammaln}) in calculations to minimize\nloss of precision.  The final result is then\n@code{exp (@var{result_using_gammaln}).}\n@seealso{gammainc, gammaln, factorial}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).gamma ());\n}\n\n/*\n%!test\n%! a = -1i* sqrt (-1/(6.4187*6.4187));\n%! assert (gamma (a), gamma (real (a)));\n\n%!test\n%! x = [.5, 1, 1.5, 2, 3, 4, 5];\n%! v = [sqrt(pi), 1, .5*sqrt(pi), 1, 2, 6, 24];\n%! assert (gamma (x), v, sqrt (eps));\n\n%!test\n%! a = single (-1i* sqrt (-1/(6.4187*6.4187)));\n%! assert (gamma (a), gamma (real (a)));\n\n%!test\n%! x = single ([.5, 1, 1.5, 2, 3, 4, 5]);\n%! v = single ([sqrt(pi), 1, .5*sqrt(pi), 1, 2, 6, 24]);\n%! assert (gamma (x), v, sqrt (eps (\"single\")));\n\n%!test\n%! ## Test exceptional values\n%! x = [-Inf, -1, -0, 0, 1, Inf, NaN];\n%! v = [Inf, Inf, -Inf, Inf, 1, Inf, NaN];\n%! assert (gamma (x), v);\n%! assert (gamma (single (x)), single (v));\n\n%!error gamma ()\n%!error gamma (1, 2)\n*/\n\nDEFUN (imag, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} imag (@var{z})\nReturn the imaginary part of @var{z} as a real number.\n@seealso{real, conj}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).imag ());\n}\n\n/*\n%!assert (imag (1), 0)\n%!assert (imag (i), 1)\n%!assert (imag (1+i), 1)\n%!assert (imag ([i, 1; 1, i]), full (eye (2)))\n\n%!assert (imag (single (1)), single (0))\n%!assert (imag (single (i)), single (1))\n%!assert (imag (single (1+i)), single (1))\n%!assert (imag (single ([i, 1; 1, i])), full (eye (2,\"single\")))\n\n%!error imag ()\n%!error imag (1, 2)\n*/\n\nDEFUNX (\"isalnum\", Fisalnum, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isalnum (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\nletters or digits and false where they are not.\n\nThis is equivalent to (@code{isalpha (@var{s}) | isdigit (@var{s})}).\n@seealso{isalpha, isdigit, ispunct, isspace, iscntrl}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xisalnum ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(double (\"A\":\"Z\") + 1) = true;\n%! result(double (\"0\":\"9\") + 1) = true;\n%! result(double (\"a\":\"z\") + 1) = true;\n%! assert (isalnum (charset), result);\n%!assert (isalnum([\"Ä8Aa?\"; \"(Uß ;\"]), logical ([1 1 1 1 1 0; 0 1 1 1 0 0]))\n\n%!error isalnum ()\n%!error isalnum (1, 2)\n*/\n\nDEFUNX (\"isalpha\", Fisalpha, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isalpha (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\nletters and false where they are not.\n\nThis is equivalent to (@code{islower (@var{s}) | isupper (@var{s})}).\n@seealso{isdigit, ispunct, isspace, iscntrl, isalnum, islower, isupper}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xisalpha ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(double (\"A\":\"Z\") + 1) = true;\n%! result(double (\"a\":\"z\") + 1) = true;\n%! assert (isalpha (charset), result);\n%!assert (isalpha(\"Ä8Aa(Uß ;\"), logical ([1 1 0 1 1 0 1 1 1 0 0]))\n\n%!error isalpha ()\n%!error isalpha (1, 2)\n*/\n\nDEFUNX (\"isascii\", Fisascii, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isascii (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\nASCII characters (in the range 0 to 127 decimal) and false where they are\nnot.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xisascii ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = true (1, 128);\n%! assert (isascii (charset), result);\n\n%!error isascii ()\n%!error isascii (1, 2)\n*/\n\nDEFUNX (\"iscntrl\", Fiscntrl, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} iscntrl (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\ncontrol characters and false where they are not.\n@seealso{ispunct, isspace, isalpha, isdigit}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xiscntrl ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(1:32) = true;\n%! result(128) = true;\n%! assert (iscntrl (charset), result);\n\n%!error iscntrl ()\n%!error iscntrl (1, 2)\n*/\n\nDEFUNX (\"isdigit\", Fisdigit, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isdigit (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\ndecimal digits (0-9) and false where they are not.\n@seealso{isxdigit, isalpha, isletter, ispunct, isspace, iscntrl}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xisdigit ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(double (\"0\":\"9\") + 1) = true;\n%! assert (isdigit (charset), result);\n%!assert (isdigit(\"Ä8Aa(Uß ;\"), logical ([0 0 1 0 0 0 0 0 0 0 0]))\n\n%!error isdigit ()\n%!error isdigit (1, 2)\n*/\n\nDEFUN (isinf, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isinf (@var{x})\nReturn a logical array which is true where the elements of @var{x} are\ninfinite and false where they are not.\n\nFor example:\n\n@example\n@group\nisinf ([13, Inf, NA, NaN])\n      @xresult{} [ 0, 1, 0, 0 ]\n@end group\n@end example\n@seealso{isfinite, isnan, isna}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isinf ());\n}\n\n/*\n%!assert (isinf (Inf))\n%!assert (! isinf (NaN))\n%!assert (! isinf (NA))\n%!assert (isinf (rand (1,10)), false (1,10))\n%!assert (isinf ([NaN -Inf -1 0 1 Inf NA]),\n%!        [false, true, false, false, false, true, false])\n\n%!assert (isinf (single (Inf)))\n%!assert (! isinf (single (NaN)))\n%!assert (! isinf (single (NA)))\n%!assert (isinf (single (rand (1,10))), false (1,10))\n%!assert (isinf (single ([NaN -Inf -1 0 1 Inf NA])),\n%!        [false, true, false, false, false, true, false])\n%!assert (! isinf ('a'))\n\n%!error isinf ()\n%!error isinf (1, 2)\n*/\n\nDEFUNX (\"isgraph\", Fisgraph, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isgraph (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\nprintable characters (but not the space character) and false where they are\nnot.\n@seealso{isprint}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xisgraph ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(34:127) = true;\n%! assert (isgraph (charset), result);\n%!assert (isgraph(\"Ä8Aa(Uß ;\"), logical ([1 1 1 1 1 1 1 1 1 0 1]))\n\n%!error isgraph ()\n%!error isgraph (1, 2)\n*/\n\nDEFUNX (\"islower\", Fislower, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} islower (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\nlowercase letters and false where they are not.\n@seealso{isupper, isalpha, isletter, isalnum}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xislower ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(double (\"a\":\"z\") + 1) = true;\n%! assert (islower (charset), result);\n%!assert (islower(\"Ä8Aa(Uß ;\"), logical ([0 0 0 0 1 0 0 1 1 0 0]))\n\n%!error islower ()\n%!error islower (1, 2)\n*/\n\nDEFUN (isna, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isna (@var{x})\nReturn a logical array which is true where the elements of @var{x} are\nNA (missing) values and false where they are not.\n\nFor example:\n\n@example\n@group\nisna ([13, Inf, NA, NaN])\n     @xresult{} [ 0, 0, 1, 0 ]\n@end group\n@end example\n@seealso{isnan, isinf, isfinite}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isna ());\n}\n\n/*\n%!assert (! isna (Inf))\n%!assert (! isna (NaN))\n%!assert (isna (NA))\n%!assert (isna (rand (1,10)), false (1,10))\n%!assert (isna ([NaN -Inf -1 0 1 Inf NA]),\n%!        [false, false, false, false, false, false, true])\n\n%!assert (! isna (single (Inf)))\n%!assert (! isna (single (NaN)))\n%!testif HAVE_QNAN_WITH_PAYLOAD\n%! assert (isna (single (NA)));\n%!testif HAVE_QNAN_WITH_PAYLOAD\n%! assert (isna (single (rand (1,10))), false (1,10));\n%!testif HAVE_QNAN_WITH_PAYLOAD\n%! assert (isna (single ([NaN -Inf -1 0 1 Inf NA])),\n%!         [false, false, false, false, false, false, true])\n// Duplicate from above.  Only for test statistics\n%!testif ; ! __have_feature__ (\"QNAN_WITH_PAYLOAD\") <59830>\n%! assert (isna (single (NA)));\n%!testif ; ! __have_feature__ (\"QNAN_WITH_PAYLOAD\") <59830>\n%! assert (isna (single (rand (1,10))), false (1,10));\n%!testif ; ! __have_feature__ (\"QNAN_WITH_PAYLOAD\") <59830>\n%! assert (isna (single ([NaN -Inf -1 0 1 Inf NA])),\n%!         [false, false, false, false, false, false, true])\n\n%!error isna ()\n%!error isna (1, 2)\n*/\n\nDEFUN (isnan, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isnan (@var{x})\nReturn a logical array which is true where the elements of @var{x} are\nNaN values and false where they are not.\n\nNA values are also considered NaN values.  For example:\n\n@example\n@group\nisnan ([13, Inf, NA, NaN])\n      @xresult{} [ 0, 0, 1, 1 ]\n@end group\n@end example\n@seealso{isna, isinf, isfinite}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isnan ());\n}\n\n/*\n%!assert (! isnan (Inf))\n%!assert (isnan (NaN))\n%!assert (isnan (NA))\n%!assert (isnan (rand (1,10)), false (1,10))\n%!assert (isnan ([NaN -Inf -1 0 1 Inf NA]),\n%!        [true, false, false, false, false, false, true])\n\n%!assert (! isnan (single (Inf)))\n%!assert (isnan (single (NaN)))\n%!assert (isnan (single (NA)))\n%!assert (isnan (single (rand (1,10))), false (1,10))\n%!assert (isnan (single ([NaN -Inf -1 0 1 Inf NA])),\n%!        [true, false, false, false, false, false, true])\n%!assert (! isnan ('a'))\n\n%!error isnan ()\n%!error isnan (1, 2)\n*/\n\nDEFUNX (\"isprint\", Fisprint, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isprint (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\nprintable characters (including the space character) and false where they\nare not.\n@seealso{isgraph}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xisprint ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(33:127) = true;\n%! assert (isprint (charset), result);\n%!assert (isprint(\"Ä8Aa(Uß ;\"), logical ([1 1 1 1 1 1 1 1 1 1 1]))\n\n%!error isprint ()\n%!error isprint (1, 2)\n*/\n\nDEFUNX (\"ispunct\", Fispunct, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} ispunct (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\npunctuation characters and false where they are not.\n@seealso{isalpha, isdigit, isspace, iscntrl}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xispunct ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(34:48) = true;\n%! result(59:65) = true;\n%! result(92:97) = true;\n%! result(124:127) = true;\n%! assert (ispunct (charset), result);\n%!assert (ispunct(\"Ä8Aa(Uß ;\"), logical ([0 0 0 0 0 1 0 0 0 0 1]))\n\n%!error ispunct ()\n%!error ispunct (1, 2)\n*/\n\nDEFUNX (\"isspace\", Fisspace, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isspace (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\nwhitespace characters (space, formfeed, newline, carriage return, tab, and\nvertical tab) and false where they are not.\n@seealso{iscntrl, ispunct, isalpha, isdigit}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xisspace ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(double (\" \\f\\n\\r\\t\\v\") + 1) = true;\n%! assert (isspace (charset), result);\n%!assert (isspace(\"Ä8Aa(Uß ;\"), logical ([0 0 0 0 0 0 0 0 0 1 0]))\n\n%!error isspace ()\n%!error isspace (1, 2)\n*/\n\nDEFUNX (\"isupper\", Fisupper, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isupper (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\nuppercase letters and false where they are not.\n@seealso{islower, isalpha, isletter, isalnum}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xisupper ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(double (\"A\":\"Z\") + 1) = true;\n%! assert (isupper (charset), result);\n%!assert (isupper(\"Ä8Aa(Uß ;\"), logical ([1 1 0 1 0 0 1 0 0 0 0]))\n\n%!error isupper ()\n%!error isupper (1, 2)\n*/\n\nDEFUNX (\"isxdigit\", Fisxdigit, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isxdigit (@var{s})\nReturn a logical array which is true where the elements of @var{s} are\nhexadecimal digits (0-9 and @nospell{a-fA-F}).\n@seealso{isdigit}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xisxdigit ());\n}\n\n/*\n%!test\n%! charset = char (0:127);\n%! result = false (1, 128);\n%! result(double (\"A\":\"F\") + 1) = true;\n%! result(double (\"0\":\"9\") + 1) = true;\n%! result(double (\"a\":\"f\") + 1) = true;\n%! assert (isxdigit (charset), result);\n%!assert (isxdigit(\"Ä8Aa(Uß ;\"), logical ([0 0 1 1 1 0 0 0 0 0 0]))\n\n%!error isxdigit ()\n%!error isxdigit (1, 2)\n*/\n\nDEFUN (lgamma, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} gammaln (@var{x})\n@deftypefnx {} {@var{y} =} lgamma (@var{x})\nReturn the natural logarithm of the gamma function of @var{x}.\n\nProgramming Note: @code{lgamma} is an alias for @code{gammaln} and either name\ncan be used in Octave.\n@seealso{gamma, gammainc}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).lgamma ());\n}\n\n/*\n%!test\n%! a = -1i* sqrt (-1/(6.4187*6.4187));\n%! assert (gammaln (a), gammaln (real (a)));\n\n%!test\n%! x = [.5, 1, 1.5, 2, 3, 4, 5];\n%! v = [sqrt(pi), 1, .5*sqrt(pi), 1, 2, 6, 24];\n%! assert (gammaln (x), log (v), sqrt (eps));\n\n%!test\n%! a = single (-1i* sqrt (-1/(6.4187*6.4187)));\n%! assert (gammaln (a), gammaln (real (a)));\n\n%!test\n%! x = single ([.5, 1, 1.5, 2, 3, 4, 5]);\n%! v = single ([sqrt(pi), 1, .5*sqrt(pi), 1, 2, 6, 24]);\n%! assert (gammaln (x), log (v), sqrt (eps (\"single\")));\n\n%!test\n%! x = [-1, 0, 1, Inf];\n%! v = [Inf, Inf, 0, Inf];\n%! assert (gammaln (x), v);\n%! assert (gammaln (single (x)), single (v));\n\n%!error gammaln ()\n%!error gammaln (1,2)\n*/\n\nDEFUN (log, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} log (@var{x})\nCompute the natural logarithm,\n@tex\n$\\ln{(x)},$\n@end tex\n@ifnottex\n@code{ln (@var{x})},\n@end ifnottex\nfor each element of @var{x}.\n\nTo compute the matrix logarithm, @pxref{Linear Algebra}.\n@seealso{exp, log1p, log2, log10, logspace}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).log ());\n}\n\n/*\n%!assert (log ([1, e, e^2]), [0, 1, 2], sqrt (eps))\n%!assert (log ([-0.5, -1.5, -2.5]), log ([0.5, 1.5, 2.5]) + pi*1i, sqrt (eps))\n\n%!assert (log (single ([1, e, e^2])), single ([0, 1, 2]), sqrt (eps (\"single\")))\n%!assert (log (single ([-0.5, -1.5, -2.5])),\n%!        single (log ([0.5, 1.5, 2.5]) + pi*1i), 4* eps (\"single\"))\n\n%!error log ()\n%!error log (1, 2)\n*/\n\nDEFUN (log10, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} log10 (@var{x})\nCompute the base-10 logarithm of each element of @var{x}.\n@seealso{log, log2, logspace, exp}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).log10 ());\n}\n\n/*\n%!assert (log10 ([0.01, 0.1, 1, 10, 100]), [-2, -1, 0, 1, 2], sqrt (eps))\n%!assert (log10 (single ([0.01, 0.1, 1, 10, 100])),\n%!        single ([-2, -1, 0, 1, 2]), sqrt (eps (\"single\")))\n\n%!error log10 ()\n%!error log10 (1, 2)\n*/\n\nDEFUN (log1p, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} log1p (@var{x})\nCompute\n@tex\n$\\ln{(1 + x)}$\n@end tex\n@ifnottex\n@code{log (1 + @var{x})}\n@end ifnottex\naccurately in the neighborhood of zero.\n@seealso{log, exp, expm1}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).log1p ());\n}\n\n/*\n%!assert (log1p ([0, 2*eps, -2*eps]), [0, 2*eps, -2*eps], 1e-29)\n%!assert (log1p (single ([0, 2*eps, -2*eps])), ...\n%!        single ([0, 2*eps, -2*eps]), 1e-29)\n## Compare to result from Wolfram Alpha rounded to 16 significant digits\n%!assert <*62094> (log1p (0.1i), ...\n%!                 0.004975165426584041 + 0.09966865249116203i, eps (0.2))\n%!assert <*62094> (log1p (single (0.1i)), ...\n%!                 single (0.004975165426584041 + 0.09966865249116203i), ...\n%!                 eps (single (0.2)))\n\n%!error log1p ()\n%!error log1p (1, 2)\n*/\n\nDEFUN (real, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{x} =} real (@var{z})\nReturn the real part of @var{z}.\n@seealso{imag, conj}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).real ());\n}\n\n/*\n%!assert (real (1), 1)\n%!assert (real (i), 0)\n%!assert (real (1+i), 1)\n%!assert (real ([1, i; i, 1]), full (eye (2)))\n\n%!assert (real (single (1)), single (1))\n%!assert (real (single (i)), single (0))\n%!assert (real (single (1+i)), single (1))\n%!assert (real (single ([1, i; i, 1])), full (eye (2, \"single\")))\n\n%!error real ()\n%!error real (1, 2)\n*/\n\nDEFUN (round, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} round (@var{x})\nReturn the integer nearest to @var{x}.\n\nIf @var{x} is complex, return\n@code{round (real (@var{x})) + round (imag (@var{x})) * I}.  If there\nare two nearest integers, return the one further away from zero.\n\n@example\n@group\nround ([-2.7, 2.7])\n     @xresult{} -3    3\n@end group\n@end example\n@seealso{ceil, floor, fix, roundb}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).round ());\n}\n\n/*\n%!assert (round (1), 1)\n%!assert (round (1.1), 1)\n%!assert (round (5.5), 6)\n%!assert (round (i), i)\n%!assert (round (2.5+3.5i), 3+4i)\n%!assert (round (-2.6), -3)\n%!assert (round ([1.1, -2.4; -3.7, 7.1]), [1, -2; -4, 7])\n\n%!assert (round (single (1)), single (1))\n%!assert (round (single (1.1)), single (1))\n%!assert (round (single (5.5)), single (6))\n%!assert (round (single (i)), single (i))\n%!assert (round (single (2.5+3.5i)), single (3+4i))\n%!assert (round (single (-2.6)), single (-3))\n%!assert (round (single ([1.1, -2.4; -3.7, 7.1])), single ([1, -2; -4, 7]))\n\n%!error round ()\n%!error round (1, 2)\n*/\n\nDEFUN (roundb, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} roundb (@var{x})\nReturn the integer nearest to @var{x}.  If there are two nearest\nintegers, return the even one (banker's rounding).\n\nIf @var{x} is complex,\nreturn @code{roundb (real (@var{x})) + roundb (imag (@var{x})) * I}.\n@seealso{round}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).roundb ());\n}\n\n/*\n%!assert (roundb (1), 1)\n%!assert (roundb (1.1), 1)\n%!assert (roundb (1.5), 2)\n%!assert (roundb (4.5), 4)\n%!assert (roundb (i), i)\n%!assert (roundb (2.5+3.5i), 2+4i)\n%!assert (roundb (-2.6), -3)\n%!assert (roundb ([1.1, -2.4; -3.7, 7.1]), [1, -2; -4, 7])\n\n%!assert (roundb (single (1)), single (1))\n%!assert (roundb (single (1.1)), single (1))\n%!assert (roundb (single (1.5)), single (2))\n%!assert (roundb (single (4.5)), single (4))\n%!assert (roundb (single (i)), single (i))\n%!assert (roundb (single (2.5+3.5i)), single (2+4i))\n%!assert (roundb (single (-2.6)), single (-3))\n%!assert (roundb (single ([1.1, -2.4; -3.7, 7.1])), single ([1, -2; -4, 7]))\n\n%!error roundb ()\n%!error roundb (1, 2)\n*/\n\nDEFUN (sign, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} sign (@var{x})\nCompute the @dfn{signum} function.\n\nThis is defined as\n@tex\n$$\n{\\rm sign} (@var{x}) = \\cases{1,&$x>0$;\\cr 0,&$x=0$;\\cr -1,&$x<0$.\\cr}\n$$\n@end tex\n@ifnottex\n\n@example\n@group\n           -1, x < 0;\nsign (x) =  0, x = 0;\n            1, x > 0.\n@end group\n@end example\n\n@end ifnottex\n\nFor complex arguments, @code{sign} returns @code{x ./ abs (@var{x})}.\n\nNote that @code{sign (-0.0)} is 0.  Although IEEE@tie{}754 floating point\nallows zero to be signed, 0.0 and -0.0 compare equal.  If you must test\nwhether zero is signed, use the @code{signbit} function.\n@seealso{signbit}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).signum ());\n}\n\n/*\n%!assert (sign (-2) , -1)\n%!assert (sign (0), 0)\n%!assert (sign (3), 1)\n%!assert (sign ([1, -pi; e, 0]), [1, -1; 1, 0])\n\n%!assert (sign (single (-2)) , single (-1))\n%!assert (sign (single (0)), single (0))\n%!assert (sign (single (3)), single (1))\n%!assert (sign (single ([1, -pi; e, 0])), single ([1, -1; 1, 0]))\n\n%!error sign ()\n%!error sign (1, 2)\n*/\n\nDEFUNX (\"signbit\", Fsignbit, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} signbit (@var{x})\nReturn logical true if the value of @var{x} has its sign bit set and false\notherwise.\n\nThis behavior is consistent with the other logical functions.\n@xref{Logical Values}.  The behavior differs from the C language function\nwhich returns nonzero if the sign bit is set.\n\nThis is not the same as @code{x < 0.0}, because IEEE@tie{}754 floating point\nallows zero to be signed.  The comparison @code{-0.0 < 0.0} is false,\nbut @code{signbit (-0.0)} will return a nonzero value.\n@seealso{sign}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value tmp = args(0).xsignbit ();\n\n  return ovl (tmp != 0);\n}\n\n/*\n%!assert (signbit (1) == 0)\n%!assert (signbit (-2) != 0)\n%!assert (signbit (0) == 0)\n%!assert (signbit (-0) != 0)\n\n%!assert (signbit (single (1)) == 0)\n%!assert (signbit (single (-2)) != 0)\n%!assert (signbit (single (0)) == 0)\n%!assert (signbit (single (-0)) != 0)\n\n%!error sign ()\n%!error sign (1, 2)\n*/\n\nDEFUN (sin, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} sin (@var{x})\nCompute the sine for each element of @var{x} in radians.\n@seealso{asin, sind, sinh}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).sin ());\n}\n\n/*\n%!shared rt2, rt3\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n\n%!test\n%! x = [0, pi/6, pi/4, pi/3, pi/2, 2*pi/3, 3*pi/4, 5*pi/6, pi];\n%! v = [0, 1/2, rt2/2, rt3/2, 1, rt3/2, rt2/2, 1/2, 0];\n%! assert (sin (x), v, sqrt (eps));\n\n%!test\n%! x = single ([0, pi/6, pi/4, pi/3, pi/2, 2*pi/3, 3*pi/4, 5*pi/6, pi]);\n%! v = single ([0, 1/2, rt2/2, rt3/2, 1, rt3/2, rt2/2, 1/2, 0]);\n%! assert (sin (x), v, sqrt (eps (\"single\")));\n\n%!error sin ()\n%!error sin (1, 2)\n*/\n\nDEFUN (sinh, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} sinh (@var{x})\nCompute the hyperbolic sine for each element of @var{x}.\n@seealso{asinh, cosh, tanh}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).sinh ());\n}\n\n/*\n%!test\n%! x = [0, pi/2*i, pi*i, 3*pi/2*i];\n%! v = [0, i, 0, -i];\n%! assert (sinh (x), v, sqrt (eps));\n\n%!test\n%! x = single ([0, pi/2*i, pi*i, 3*pi/2*i]);\n%! v = single ([0, i, 0, -i]);\n%! assert (sinh (x), v, sqrt (eps (\"single\")));\n\n%!error sinh ()\n%!error sinh (1, 2)\n*/\n\nDEFUN (sqrt, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} sqrt (@var{x})\nCompute the square root of each element of @var{x}.\n\nIf @var{x} is negative, a complex result is returned.\n\nTo compute the matrix square root, @pxref{Linear Algebra}.\n@seealso{realsqrt, nthroot}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).sqrt ());\n}\n\n/*\n%!assert (sqrt (4), 2)\n%!assert (sqrt (-1), i)\n%!assert (sqrt (1+i), exp (0.5 * log (1+i)), sqrt (eps))\n%!assert (sqrt ([4, -4; i, 1-i]),\n%!        [2, 2i; exp(0.5 * log (i)), exp(0.5 * log (1-i))], sqrt (eps))\n\n%!assert (sqrt (single (4)), single (2))\n%!assert (sqrt (single (-1)), single (i))\n%!assert (sqrt (single (1+i)),\n%!        single (exp (0.5 * log (1+i))), sqrt (eps (\"single\")))\n%!assert (sqrt (single ([4, -4; i, 1-i])),\n%!        single ([2, 2i; exp(0.5 * log (i)), exp(0.5 * log (1-i))]),\n%!        sqrt (eps (\"single\")))\n\n%!error sqrt ()\n%!error sqrt (1, 2)\n*/\n\nDEFUN (tan, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} tan (@var{z})\nCompute the tangent for each element of @var{x} in radians.\n@seealso{atan, tand, tanh}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).tan ());\n}\n\n/*\n%!shared rt2, rt3\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n\n%!test\n%! x = [0, pi/6, pi/4, pi/3, 2*pi/3, 3*pi/4, 5*pi/6, pi];\n%! v = [0, rt3/3, 1, rt3, -rt3, -1, -rt3/3, 0];\n%! assert (tan (x), v, sqrt (eps));\n\n%!test\n%! x = single ([0, pi/6, pi/4, pi/3, 2*pi/3, 3*pi/4, 5*pi/6, pi]);\n%! v = single ([0, rt3/3, 1, rt3, -rt3, -1, -rt3/3, 0]);\n%! assert (tan (x), v, sqrt (eps (\"single\")));\n\n%!error tan ()\n%!error tan (1, 2)\n*/\n\nDEFUN (tanh, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} tanh (@var{x})\nCompute hyperbolic tangent for each element of @var{x}.\n@seealso{atanh, sinh, cosh}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).tanh ());\n}\n\n/*\n%!test\n%! x = [0, pi*i];\n%! v = [0, 0];\n%! assert (tanh (x), v, sqrt (eps));\n\n%!test\n%! x = single ([0, pi*i]);\n%! v = single ([0, 0]);\n%! assert (tanh (x), v, sqrt (eps (\"single\")));\n\n%!error tanh ()\n%!error tanh (1, 2)\n*/\n\nDEFUN (lower, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} lower (@var{s})\n@deftypefnx {} {@var{y} =} tolower (@var{s})\nReturn a copy of the string or cell string @var{s}, with each uppercase\ncharacter replaced by the corresponding lowercase one; non-alphabetic\ncharacters are left unchanged.\n\nFor example:\n\n@example\n@group\nlower (\"MiXeD cAsE 123\")\n    @xresult{} \"mixed case 123\"\n@end group\n@end example\n\nProgramming Note: @code{tolower} is an alias for @code{lower} and either name\ncan be used in Octave.\n\n@seealso{upper}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xtolower ());\n}\n\nDEFALIAS (tolower, lower);\n\n/*\n%!assert (lower (\"OCTAVE\"), \"octave\")\n%!assert (lower (\"123OCTave! _&\"), \"123octave! _&\")\n%!assert (lower ({\"ABC\", \"DEF\", {\"GHI\", {\"JKL\"}}}),\n%!        {\"abc\", \"def\", {\"ghi\", {\"jkl\"}}})\n%!assert (lower ([\"ABC\"; \"DEF\"]), [\"abc\"; \"def\"])\n%!assert (lower ({[\"ABC\"; \"DEF\"]}), {[\"abc\";\"def\"]})\n%!assert (lower ([\"ABCÄÖÜSS\"; \"abcäöüß\"]),\n%!        [\"abcäöüss\"; \"abcäöüß\"])\n%!assert (lower (repmat (\"ÄÖÜ\", 2, 1, 3)), repmat (\"äöü\", 2, 1, 3))\n%!assert (lower (68), 68)\n%!assert (lower ({[68, 68; 68, 68]}), {[68, 68; 68, 68]})\n%!assert (lower (68i), 68i)\n%!assert (lower ({[68i, 68; 68, 68i]}), {[68i, 68; 68, 68i]})\n%!assert (lower (single (68i)), single (68i))\n%!assert (lower ({single([68i, 68; 68, 68i])}), {single([68i, 68; 68, 68i])})\n\n%!test\n%! classes = {@char, @double, @single, ...\n%!            @int8, @int16, @int32, @int64, ...\n%!            @uint8, @uint16, @uint32, @uint64};\n%! for i = 1:numel (classes)\n%!   cls = classes{i};\n%!   assert (class (lower (cls (97))), class (cls (97)));\n%!   assert (class (lower (cls ([98, 99]))), class (cls ([98, 99])));\n%! endfor\n%!test\n%! a(3,3,3,3) = \"D\";\n%! assert (lower (a)(3,3,3,3), \"d\");\n\n%!test\n%! charset = char (0:127);\n%! result = charset;\n%! result (double (\"A\":\"Z\") + 1) = result (double (\"a\":\"z\") + 1);\n%! assert (lower (charset), result);\n\n%!error <Invalid call to lower> lower ()\n%!error <Invalid call to lower> tolower ()\n%!error lower (1, 2)\n*/\n\nDEFUN (upper, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} upper (@var{s})\n@deftypefnx {} {@var{y} =} toupper (@var{s})\nReturn a copy of the string or cell string @var{s}, with each lowercase\ncharacter replaced by the corresponding uppercase one; non-alphabetic\ncharacters are left unchanged.\n\nFor example:\n\n@example\n@group\nupper (\"MiXeD cAsE 123\")\n    @xresult{} \"MIXED CASE 123\"\n@end group\n@end example\n\nProgramming Note: @code{toupper} is an alias for @code{upper} and either name\ncan be used in Octave.\n\n@seealso{lower}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).xtoupper ());\n}\n\nDEFALIAS (toupper, upper);\n\n/*\n%!assert (upper (\"octave\"), \"OCTAVE\")\n%!assert (upper (\"123OCTave! _&\"), \"123OCTAVE! _&\")\n%!assert (upper ({\"abc\", \"def\", {\"ghi\", {\"jkl\"}}}),\n%!        {\"ABC\", \"DEF\", {\"GHI\", {\"JKL\"}}})\n%!assert (upper ([\"abc\"; \"def\"]), [\"ABC\"; \"DEF\"])\n%!assert (upper ({[\"abc\"; \"def\"]}), {[\"ABC\";\"DEF\"]})\n%!assert (upper ([\"ABCÄÖÜSS\"; \"abcäöüß\"]),\n%!        [\"ABCÄÖÜSS\"; \"ABCÄÖÜSS\"])\n%!assert (upper (repmat (\"äöü\", 2, 1, 3)), repmat (\"ÄÖÜ\", 2, 1, 3))\n%!assert (upper (100), 100)\n%!assert (upper ({[100, 100; 100, 100]}), {[100, 100; 100, 100]})\n%!assert (upper (100i), 100i)\n%!assert (upper ({[100i, 100; 100, 100i]}), {[100i, 100; 100, 100i]})\n%!assert (upper (single (100i)), single (100i))\n%!assert (upper ({single([100i, 100; 100, 100i])}),\n%!        {single([100i, 100; 100, 100i])})\n\n%!test\n%! classes = {@char, @double, @single, ...\n%!            @int8, @int16, @int32, @int64, ...\n%!            @uint8, @uint16, @uint32, @uint64};\n%! for i = 1:numel (classes)\n%!   cls = classes{i};\n%!   assert (class (upper (cls (97))), class (cls (97)));\n%!   assert (class (upper (cls ([98, 99]))), class (cls ([98, 99])));\n%! endfor\n%!test\n%! a(3,3,3,3) = \"d\";\n%! assert (upper (a)(3,3,3,3), \"D\");\n%!test\n%! charset = char (0:127);\n%! result = charset;\n%! result (double  (\"a\":\"z\") + 1) = result (double  (\"A\":\"Z\") + 1);\n%! assert (upper (charset), result);\n\n%!error <Invalid call to upper> upper ()\n%!error <Invalid call to upper> toupper ()\n%!error upper (1, 2)\n*/\n\nDEFALIAS (gammaln, lgamma);\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/max.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"dNDArray.h\"\n#include \"CNDArray.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\n#include \"ov-cx-mat.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic void\nget_dim_vecdim_all (const octave_value& dimarg, octave_value& arg,\n                    int& dim, Array<int>& perm_vec, bool& do_perm,\n                    bool& allflag, const char *fcn)\n{\n  if (dimarg.is_scalar_type ())\n    {\n      dim = dimarg.int_value () - 1;\n      if (dim < 0)\n        error (\"%s: invalid dimension DIM = %d\", fcn, dim + 1);\n    }\n  else\n    {\n      Array<int> vec = dimarg.int_vector_value ();\n      std::vector<int> vecdim;\n      dim_vector sz = arg.dims ();\n      int ndims = arg.ndims ();\n      // Check for invalid dims and ignore any dims larger than actual ndims\n      for (int i = 0; i < vec.numel (); i++)\n        {\n          vec(i)--;\n          if (vec(i) < 0)\n            error (\"%s: invalid dimension in VECDIM = %d\", fcn, vec(i)+1);\n          if (vec(i) < ndims)\n            vecdim.push_back (vec(i));\n        }\n      int n = vecdim.size ();\n      // If no dimensions left, set DIM = ndims to return input as is\n      if (n == 0)\n        {\n          dim = ndims;\n          return;\n        }\n      octave_idx_type szvecdim = 1;\n      // Check for duplicate dims and add VECDIM to permutation vector\n      perm_vec.resize (dim_vector (1, ndims));\n      std::sort (vecdim.begin (), vecdim.end ());\n      // Check for duplicates FIRST before any array writes\n      auto dup = std::adjacent_find (vecdim.begin (), vecdim.end ());\n      if (dup != vecdim.end ())\n        error (\"%s: duplicate dimension in VECDIM = %d\", fcn, *dup + 1);\n\n       // Verified vecdim has unique entries in [0, ndims-1], hence n <= ndims\n       int out_pos = ndims - n;\n       for (int d : vecdim)\n         {\n           szvecdim *= sz (d);\n           perm_vec(out_pos++) = d;\n         }\n\n      // Parse vecdim\n      if (n == 1)\n        // Only one dimension given, treat as if dim were specified instead\n        dim = vecdim[0];\n      else if (ndims == n)\n        // vecdim contains all dimensions, treat as if \"all\" flag given.\n        allflag = true;\n      else\n        {\n          dim_vector new_sz;\n          new_sz.resize (ndims - n + 1);\n          int idx = 0;\n          // Add remaining dims to permutation vector\n          for (int i = 0; i < ndims; i++)\n            {\n              if (std::find (vecdim.begin (), vecdim.end (), i)\n                  == vecdim.end ())\n                {\n                  perm_vec(idx) = i;\n                  new_sz(idx) = sz(i);\n                  idx++;\n                }\n            }\n          new_sz(idx) = szvecdim;\n          arg = arg.permute (perm_vec, false);\n          arg = arg.reshape (new_sz);\n          do_perm = true;\n          dim = idx;\n        }\n    }\n}\n\nstatic dim_vector\ncustom_ind2sub (const dim_vector szx, octave_idx_type idx, int ndims)\n{\n  Array<octave_idx_type> szc;\n  szc.resize (dim_vector (1, ndims));\n  for (int i = 0; i < ndims; i++)\n    szc(i) = szx(i);\n  if (ndims > 1)\n    for (int i = 1; i < ndims; i++)\n      szc(i) *= szc(i-1);\n\n  dim_vector sub;\n  sub.resize (ndims);\n  for (int i = 0; i < ndims; i++)\n    sub(i) = 1;\n\n  for (octave_idx_type i = ndims - 1; i >= 0; i--)\n    {\n      int dsz = szc(i);\n      if (idx > dsz)\n        {\n          int tmp = idx / dsz; // dzc is never 0 at this point\n          if (idx % dsz > 0)\n            {\n              sub(i+1) = tmp + 1;\n              idx -= tmp * dsz;\n            }\n          else\n            {\n              sub(i+1) = tmp;\n              idx -= (tmp - 1) * dsz;\n            }\n        }\n      if (i == 0)\n        sub(i) = idx;\n    }\n  return sub;\n}\n\nstatic octave_idx_type\ncustom_sub2ind (const dim_vector& szx, const dim_vector& dims, int ndims)\n{\n  octave_idx_type ind = 1;\n  Array<octave_idx_type> szc;\n  szc.resize (dim_vector (1, ndims));\n  for (int i = 0; i < ndims; i++)\n    szc(i) = szx(i);\n  for (octave_idx_type i = 1; i < ndims; i++)\n    szc(i) *= szc(i-1);\n\n  Array<octave_idx_type> szce;\n  szce.resize (dim_vector (1, ndims + 1));\n  szce(0) = 1;\n  for (octave_idx_type i = 0; i < ndims; i++)\n    szce(i+1) = szc(i);\n\n  for (octave_idx_type i = 0; i < ndims; i++)\n    if (szx(i) > 1)\n      ind += szce(i) * (dims(i) - 1);\n\n  return ind;\n}\n\nstatic octave_value\nget_linear_index (const octave_value& index, const octave_value& arg,\n                  const Array<int>& vecdim, bool cumop)\n{\n  // Get index values and original index size\n  Array<octave_idx_type> idx = index.int_vector_value ();\n  dim_vector sz_idx = index.dims ();\n\n  // Get size and number of dimensions of input argument\n  dim_vector sz_arg = arg.dims ();\n  int nd_arg = arg.ndims ();\n\n  // Invalid input in VECDIM has already been ruled out\n  // Ignore any exceeding dimensions and get usable dimensions in VECDIM\n  std::vector<int> dim_page;\n  for (octave_idx_type i = 0; i < vecdim.numel (); i++)\n    if (vecdim(i) <= nd_arg)\n      dim_page.push_back (vecdim(i));\n  int nd_page = dim_page.size ();\n\n  // If no dimensions left, return linear index as [1:numel(x)]\n  if (nd_page == 0)\n    for (octave_idx_type i = 0; i < idx.numel (); i++)\n      idx(i) += i;\n  else\n    {\n      // Sort VECDIM\n      std::sort (dim_page.begin (), dim_page.end ());\n\n      // Calculate page size\n      dim_vector sz_page;\n      sz_page.resize (nd_page);\n      for (int i = 0; i < nd_page; i++)\n        sz_page(i) = sz_arg(dim_page[i]-1);\n\n      // Calculate operating index vector and reduced index dimensions\n      std::vector<int> dim_index;\n      dim_vector dim_vec;\n      dim_vec.resize (nd_arg);\n      for (int i = 0; i < nd_arg; i++)\n        {\n          dim_vec(i) = 1;\n          bool addindex = true;\n          for (int j = 0; j < nd_page; j++)\n            if (i+1 == dim_page[j])\n              addindex = false;\n          // Ignore singleton indexing dimensions\n          if (addindex && sz_arg(i) > 1)\n            dim_index.push_back (i + 1);\n        }\n      // Calculate reduced indexing size\n      int nd_index = dim_index.size ();\n      dim_vector sz_index;\n      sz_index.resize (nd_index);\n      for (int i = 0; i < nd_index; i++)\n        sz_index(i) = sz_arg(dim_index[i]-1);\n\n      // In cumulative operations, the first dimension of the operating page is\n      // expanded to 'prod (vecdim)'.  If the first dimension of the operating\n      // page is less than the first dimension in dim_index, every prod_vecdim\n      // number of index elements reuse the corresponding index of the first\n      // element.  Otherwise, they get reused after indexing the elements whose\n      // dim_index is less than first_vecdim.\n      octave_idx_type prod_vecdim = 1;\n      octave_idx_type group_index = 1;\n      if (cumop)\n        {\n          for (octave_idx_type i = 0; i < nd_page; i++)\n            prod_vecdim *= sz_page(i);\n          if (dim_page[0] > dim_index[0])\n            for (int i = 0; i < nd_index; i++)\n              if (dim_page[0] > dim_index[i])\n                group_index *= sz_index(i);\n        }\n\n      // Process each index value\n      dim_vector tmp;\n      octave_idx_type ii;\n      for (octave_idx_type i = 0; i < idx.numel (); i++)\n        {\n          if (cumop)\n            {\n              if (group_index == 1)\n                ii = i / prod_vecdim;\n              else\n                {\n                  octave_idx_type igm = i % group_index;\n                  octave_idx_type igf = i / group_index;\n                  ii = igm + ((igf / prod_vecdim) * group_index);\n                }\n            }\n          else\n            ii = i;\n          // Get index position and add it to corresponding dimensions\n          tmp = custom_ind2sub (sz_index, ii+1, nd_index);\n          for (octave_idx_type j = 0; j < nd_index; j++)\n            dim_vec(dim_index[j]-1) = tmp(j);\n\n          // Get page position and add it to corresponding dimensions\n          tmp = custom_ind2sub (sz_page, idx(i), nd_page);\n          for (octave_idx_type j = 0; j < nd_page; j++)\n            dim_vec(dim_page[j]-1) = tmp(j);\n\n          // Calculate linear index\n          idx(i) = custom_sub2ind (sz_arg, dim_vec, nd_arg);\n        }\n    }\n  return octave_value (idx).reshape (sz_idx);\n}\n\ntemplate <typename ArrayType>\nstatic octave_value_list\ndo_minmax_red_op (const octave_value& arg,\n                  int nargout, int dim, bool ismin)\n{\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n  ArrayType array = octave_value_extract<ArrayType> (arg);\n\n  if (nargout <= 1)\n    {\n      if (ismin)\n        retval(0) = array.min (dim);\n      else\n        retval(0) = array.max (dim);\n    }\n  else\n    {\n      Array<octave_idx_type> idx;\n      if (ismin)\n        retval(0) = array.min (idx, dim);\n      else\n        retval(0) = array.max (idx, dim);\n\n      retval(1) = octave_value (idx, true, true);\n    }\n\n  return retval;\n}\n\ntemplate <typename ArrayType>\nstatic octave_value_list\ndo_minmax_red_op (const octave_value& arg, int nargout,\n                  int dim, bool nanflag, bool ismin)\n{\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n  ArrayType array = octave_value_extract<ArrayType> (arg);\n\n  if (nargout <= 1)\n    {\n      if (ismin)\n        retval(0) = array.min (dim, nanflag);\n      else\n        retval(0) = array.max (dim, nanflag);\n    }\n  else\n    {\n      Array<octave_idx_type> idx;\n      if (ismin)\n        retval(0) = array.min (idx, dim, nanflag);\n      else\n        retval(0) = array.max (idx, dim, nanflag);\n\n      retval(1) = octave_value (idx, true, true);\n    }\n\n  return retval;\n}\n\ntemplate <typename ArrayType>\nstatic octave_value_list\ndo_minmax_red_op (const octave_value& arg, int nargout,\n                  int dim, bool nanflag, bool realabs, bool ismin)\n{\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n  ArrayType array = octave_value_extract<ArrayType> (arg);\n\n  if (nargout <= 1)\n    {\n      if (ismin)\n        retval(0) = array.min (dim, nanflag, realabs);\n      else\n        retval(0) = array.max (dim, nanflag, realabs);\n    }\n  else\n    {\n      Array<octave_idx_type> idx;\n      if (ismin)\n        retval(0) = array.min (idx, dim, nanflag, realabs);\n      else\n        retval(0) = array.max (idx, dim, nanflag, realabs);\n\n      retval(1) = octave_value (idx, true, true);\n    }\n\n  return retval;\n}\n\n// Matlab returns double arrays for min/max operations on character\n// arrays, so we specialize here to get that behavior.  Other possible\n// solutions are to convert the argument to double here and call the\n// code for double, but that could waste memory, or to have the\n// underlying charNDArray::min/max functions return NDArray instead of\n// charNDArray, but that is inconsistent with the way other min/max\n// functions work.\n\ntemplate <>\noctave_value_list\ndo_minmax_red_op<charNDArray> (const octave_value& arg,\n                               int nargout, int dim, bool ismin)\n{\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n  charNDArray array = octave_value_extract<charNDArray> (arg);\n\n  if (nargout <= 1)\n    {\n      if (ismin)\n        retval(0) = NDArray (array.min (dim));\n      else\n        retval(0) = NDArray (array.max (dim));\n    }\n  else\n    {\n      Array<octave_idx_type> idx;\n      if (ismin)\n        retval(0) = NDArray (array.min (idx, dim));\n      else\n        retval(0) = NDArray (array.max (idx, dim));\n\n      retval(1) = octave_value (idx, true, true);\n    }\n\n  return retval;\n}\n\n// Specialization for bool arrays (dense or sparse).\ntemplate <>\noctave_value_list\ndo_minmax_red_op<boolNDArray> (const octave_value& arg,\n                               int nargout, int dim, bool ismin)\n{\n  octave_value_list retval;\n\n  if (! arg.issparse ())\n    {\n      if (nargout <= 1)\n        {\n          // This case can be handled using any/all.\n          boolNDArray array = arg.bool_array_value ();\n\n          if (array.isempty ())\n            retval(0) = array;\n          else if (ismin)\n            retval(0) = array.all (dim);\n          else\n            retval(0) = array.any (dim);\n        }\n      else\n        {\n          // any/all don't have indexed versions, so do it via a conversion.\n          retval = do_minmax_red_op<int8NDArray> (arg, nargout, dim, ismin);\n\n          retval(0) = retval(0).bool_array_value ();\n        }\n    }\n  else\n    {\n      // Sparse: Don't use any/all trick, as full matrix could exceed memory.\n      // Instead, convert to double.\n      retval = do_minmax_red_op<SparseMatrix> (arg, nargout, dim, ismin);\n\n      retval(0) = retval(0).sparse_bool_matrix_value ();\n    }\n\n  return retval;\n}\n\ntemplate <typename ArrayType>\nstatic octave_value\ndo_minmax_bin_op (const octave_value& argx, const octave_value& argy,\n                  bool ismin)\n{\n  typedef typename ArrayType::element_type ScalarType;\n\n  octave_value retval;\n\n  if (argx.is_scalar_type ())\n    {\n      ScalarType x = octave_value_extract<ScalarType> (argx);\n      ArrayType y = octave_value_extract<ArrayType> (argy);\n\n      if (ismin)\n        retval = min (x, y);\n      else\n        retval = max (x, y);\n    }\n  else if (argy.is_scalar_type ())\n    {\n      ArrayType x = octave_value_extract<ArrayType> (argx);\n      ScalarType y = octave_value_extract<ScalarType> (argy);\n\n      if (ismin)\n        retval = min (x, y);\n      else\n        retval = max (x, y);\n    }\n  else\n    {\n      ArrayType x = octave_value_extract<ArrayType> (argx);\n      ArrayType y = octave_value_extract<ArrayType> (argy);\n\n      if (ismin)\n        retval = min (x, y);\n      else\n        retval = max (x, y);\n    }\n\n  return retval;\n}\n\ntemplate <typename ArrayType>\nstatic octave_value\ndo_minmax_bin_op (const octave_value& argx, const octave_value& argy,\n                  bool nanflag, bool ismin)\n{\n  typedef typename ArrayType::element_type ScalarType;\n\n  octave_value retval;\n\n  if (argx.is_scalar_type ())\n    {\n      ScalarType x = octave_value_extract<ScalarType> (argx);\n      ArrayType y = octave_value_extract<ArrayType> (argy);\n\n      if (ismin)\n        retval = min (x, y, nanflag);\n      else\n        retval = max (x, y, nanflag);\n    }\n  else if (argy.is_scalar_type ())\n    {\n      ArrayType x = octave_value_extract<ArrayType> (argx);\n      ScalarType y = octave_value_extract<ScalarType> (argy);\n\n      if (ismin)\n        retval = min (x, y, nanflag);\n      else\n        retval = max (x, y, nanflag);\n    }\n  else\n    {\n      ArrayType x = octave_value_extract<ArrayType> (argx);\n      ArrayType y = octave_value_extract<ArrayType> (argy);\n\n      if (ismin)\n        retval = min (x, y, nanflag);\n      else\n        retval = max (x, y, nanflag);\n    }\n\n  return retval;\n}\n\ntemplate <typename ArrayType>\nstatic octave_value\ndo_minmax_bin_op (const octave_value& argx, const octave_value& argy,\n                  bool nanflag, bool realabs, bool ismin)\n{\n  typedef typename ArrayType::element_type ScalarType;\n\n  octave_value retval;\n\n  if (argx.is_scalar_type ())\n    {\n      ScalarType x = octave_value_extract<ScalarType> (argx);\n      ArrayType y = octave_value_extract<ArrayType> (argy);\n\n      if (ismin)\n        retval = min (x, y, nanflag, realabs);\n      else\n        retval = max (x, y, nanflag, realabs);\n    }\n  else if (argy.is_scalar_type ())\n    {\n      ArrayType x = octave_value_extract<ArrayType> (argx);\n      ScalarType y = octave_value_extract<ScalarType> (argy);\n\n      if (ismin)\n        retval = min (x, y, nanflag, realabs);\n      else\n        retval = max (x, y, nanflag, realabs);\n    }\n  else\n    {\n      ArrayType x = octave_value_extract<ArrayType> (argx);\n      ArrayType y = octave_value_extract<ArrayType> (argy);\n\n      if (ismin)\n        retval = min (x, y, nanflag, realabs);\n      else\n        retval = max (x, y, nanflag, realabs);\n    }\n\n  return retval;\n}\n\n// Matlab returns double arrays for min/max operations on character\n// arrays, so we specialize here to get that behavior.  Other possible\n// solutions are to convert the arguments to double here and call the\n// code for double, but that could waste a lot of memory, or to have the\n// underlying charNDArray::min/max functions return NDArray instead of\n// charNDArray, but that is inconsistent with the way other min/max\n// functions work.\n\ntemplate <>\noctave_value\ndo_minmax_bin_op<charNDArray> (const octave_value& argx,\n                               const octave_value& argy, bool ismin)\n{\n  octave_value retval;\n\n  charNDArray x = octave_value_extract<charNDArray> (argx);\n  charNDArray y = octave_value_extract<charNDArray> (argy);\n\n  if (ismin)\n    {\n      if (x.numel () == 1)\n        retval = NDArray (min (x(0), y));\n      else if (y.numel () == 1)\n        retval = NDArray (min (x, y(0)));\n      else\n        retval = NDArray (min (x, y));\n    }\n  else\n    {\n      if (x.numel () == 1)\n        retval = NDArray (max (x(0), y));\n      else if (y.numel () == 1)\n        retval = NDArray (max (x, y(0)));\n      else\n        retval = NDArray (max (x, y));\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\ndo_minmax_body (const octave_value_list& args, int nargout, bool ismin)\n{\n  int nargin = args.length ();\n  int orig_nargin = nargin;\n\n  const char *fcn = (ismin ? \"min\" : \"max\");\n\n  bool do_perm = false;\n  bool allflag = false;\n  bool nanflag = true; // NaNs are ignored by default\n  bool cmethod = true; // resolves to \"auto\"\n  bool realabs = true;\n  bool red_op = false;\n  bool linear = false;\n\n  // Get \"ComparisonMethod\" optional argument first\n  if (nargin > 2\n      && args(nargin - 1).is_string () && args(nargin - 2).is_string ())\n    {\n      std::string name = args(nargin - 2).string_value ();\n      std::string sval = args(nargin - 1).string_value ();\n      if (name == \"ComparisonMethod\" || name == \"comparisonmethod\")\n        {\n          if (sval == \"auto\")\n            cmethod = true;\n          else if (sval == \"real\")\n            cmethod = false;\n          else if (sval == \"abs\")\n            {\n              cmethod = false;\n              realabs = false;\n            }\n          else\n            error (\"%s: invalid comparison method '%s'\", fcn, sval.c_str ());\n\n          nargin -= 2;\n        }\n    }\n\n  while (nargin > 2 && args(nargin - 1).is_string ())\n    {\n      std::string str = args(nargin - 1).string_value ();\n\n      if (str == \"all\")\n        {\n          allflag = true;\n          red_op = true;\n        }\n      else if (str == \"omitnan\" || str == \"omitmissing\")\n        {\n          if (args(0).is_double_type () || args(0).is_single_type ())\n            nanflag = true;\n        }\n      else if (str == \"includenan\" || str == \"includemissing\")\n        nanflag = false;\n      else if (str == \"linear\")\n        linear = true;\n      else\n        error (\"%s: unrecognized optional argument '%s'\", fcn, str.c_str ());\n\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  if (allflag && nargin > 2)\n    error (\"%s: cannot set DIM or VECDIM with 'all' flag\", fcn);\n  if (nargin > 2)\n    red_op = true;\n  if (nargin > 1)\n    if (orig_nargin > 2 && args(1).rows () == 0 && args(1). columns () == 0)\n      red_op = true;\n\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n  Array<int> vecdim;\n\n  if (nargin == 1 || red_op)\n    {\n      octave_value arg = args(0);\n      // Handle DIM, VECDIM\n      int dim = -1;\n      Array<int> perm_vec;\n      if (nargin == 3)\n        {\n          octave_value dimarg = args(2);\n          get_dim_vecdim_all (dimarg, arg, dim, perm_vec, do_perm, allflag, fcn);\n          vecdim = dimarg.int_vector_value ();\n\n          if (! args(1).isempty ())\n            warning (\"%s: second argument is ignored\", fcn);\n        }\n      else\n        {\n          dim_vector dims = arg.dims ();\n          vecdim.resize (dim_vector (1, 1));\n          vecdim(0) = dims.first_non_singleton () + 1;\n        }\n      // Handle allflag\n      if (allflag)\n        arg = arg.reshape (dim_vector (arg.numel (), 1));\n\n      switch (arg.builtin_type ())\n        {\n        case btyp_double:\n          {\n            if (arg.is_range () && (dim == -1 || dim == 1))\n              {\n                range<double> range = arg.range_value ();\n                if (range.numel () < 1)\n                  {\n                    retval(0) = arg;\n                    if (nargout > 1)\n                      retval(1) = arg;\n                  }\n                else if (ismin)\n                  {\n                    retval(0) = range.min ();\n                    if (nargout > 1)\n                      retval(1) = static_cast<double>\n                                  (range.increment () < 0 ? range.numel () : 1);\n                  }\n                else\n                  {\n                    retval(0) = range.max ();\n                    if (nargout > 1)\n                      retval(1) = static_cast<double>\n                                  (range.increment () >= 0 ? range.numel ()\n                                   : 1);\n                  }\n              }\n            else if (arg.issparse ())\n              {\n                if (cmethod)\n                  retval = do_minmax_red_op<SparseMatrix>\n                           (arg, nargout, dim, nanflag, ismin);\n                else\n                  retval = do_minmax_red_op<SparseMatrix>\n                           (arg, nargout, dim, nanflag, realabs, ismin);\n              }\n            else\n              {\n                if (cmethod)\n                  retval = do_minmax_red_op<NDArray>\n                           (arg, nargout, dim, nanflag, ismin);\n                else\n                  retval = do_minmax_red_op<NDArray>\n                           (arg, nargout, dim, nanflag, realabs, ismin);\n              }\n          }\n          break;\n\n        case btyp_complex:\n          {\n            if (arg.issparse ())\n              {\n                if (cmethod)\n                  retval = do_minmax_red_op<SparseComplexMatrix>\n                           (arg, nargout, dim, nanflag, ismin);\n                else\n                  retval = do_minmax_red_op<SparseComplexMatrix>\n                           (arg, nargout, dim, nanflag, realabs, ismin);\n              }\n            else\n              {\n                if (cmethod)\n                  retval = do_minmax_red_op<ComplexNDArray>\n                           (arg, nargout, dim, nanflag, ismin);\n                else\n                  retval = do_minmax_red_op<ComplexNDArray>\n                           (arg, nargout, dim, nanflag, realabs, ismin);\n              }\n          }\n          break;\n\n        case btyp_float:\n          {\n            if (cmethod)\n              retval = do_minmax_red_op<FloatNDArray>\n                       (arg, nargout, dim, nanflag, ismin);\n            else\n              retval = do_minmax_red_op<FloatNDArray>\n                       (arg, nargout, dim, nanflag, realabs, ismin);\n          }\n          break;\n\n        case btyp_float_complex:\n          {\n            if (cmethod)\n              retval = do_minmax_red_op<FloatComplexNDArray>\n                       (arg, nargout, dim, nanflag, ismin);\n            else\n              retval = do_minmax_red_op<FloatComplexNDArray>\n                       (arg, nargout, dim, nanflag, realabs, ismin);\n          }\n          break;\n\n        case btyp_char:\n          retval = do_minmax_red_op<charNDArray> (arg, nargout, dim, ismin);\n          break;\n\n#define MAKE_INT_BRANCH(X)                                        \\\n        case btyp_ ## X:                                          \\\n          {                                                       \\\n            if (cmethod)                                          \\\n              retval = do_minmax_red_op<X ## NDArray> (arg,       \\\n                       nargout, dim, ismin);                      \\\n            else                                                  \\\n              retval = do_minmax_red_op<X ## NDArray> (arg,       \\\n                       nargout, dim, nanflag, realabs, ismin);    \\\n          }                                                       \\\n          break;\n\n          MAKE_INT_BRANCH (int8);\n          MAKE_INT_BRANCH (int16);\n          MAKE_INT_BRANCH (int32);\n          MAKE_INT_BRANCH (int64);\n          MAKE_INT_BRANCH (uint8);\n          MAKE_INT_BRANCH (uint16);\n          MAKE_INT_BRANCH (uint32);\n          MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n        case btyp_bool:\n          retval = do_minmax_red_op<boolNDArray> (arg, nargout, dim, ismin);\n          break;\n\n        default:\n          err_wrong_type_arg (fcn, arg);\n        }\n\n      if (do_perm)\n        {\n          retval(0) = retval(0).permute (perm_vec, true);\n          if (nargout > 1)\n            retval(1) = retval(1).permute (perm_vec, true);\n        }\n    }\n  else\n    {\n      if (nargout > 1)\n        error (\"%s: two output arguments are not supported for two input arrays\", fcn);\n      if (linear)\n        error (\"%s: 'linear' is not supported for two input arrays\", fcn);\n      octave_value argx = args(0);\n      octave_value argy = args(1);\n      builtin_type_t xtyp = argx.builtin_type ();\n      builtin_type_t ytyp = argy.builtin_type ();\n      builtin_type_t rtyp;\n      if (xtyp == btyp_char && ytyp == btyp_char)\n        rtyp = btyp_char;\n      // FIXME: This is what should happen when boolNDArray has max()\n      // else if (xtyp == btyp_bool && ytyp == btyp_bool)\n      //   rtyp = btyp_bool;\n      else\n        rtyp = btyp_mixed_numeric (xtyp, ytyp);\n\n      switch (rtyp)\n        {\n        case btyp_double:\n          {\n            if ((argx.issparse ()\n                 && (argy.issparse () || argy.is_scalar_type ()))\n                || (argy.issparse () && argx.is_scalar_type ()))\n              {\n                if (cmethod)\n                  retval = do_minmax_bin_op<SparseMatrix>\n                           (argx, argy, nanflag, ismin);\n                else\n                  retval = do_minmax_bin_op<SparseMatrix>\n                           (argx, argy, nanflag, realabs, ismin);\n              }\n            else\n              {\n                if (cmethod)\n                  retval = do_minmax_bin_op<NDArray>\n                           (argx, argy, nanflag, ismin);\n                else\n                  retval = do_minmax_bin_op<NDArray>\n                           (argx, argy, nanflag, realabs, ismin);\n              }\n          }\n          break;\n\n        case btyp_complex:\n          {\n            if ((argx.issparse ()\n                 && (argy.issparse () || argy.is_scalar_type ()))\n                || (argy.issparse () && argx.is_scalar_type ()))\n              {\n                if (cmethod)\n                  retval = do_minmax_bin_op<SparseComplexMatrix>\n                           (argx, argy, nanflag, ismin);\n                else\n                  retval = do_minmax_bin_op<SparseComplexMatrix>\n                           (argx, argy, nanflag, realabs, ismin);\n              }\n            else\n              {\n                if (cmethod)\n                  retval = do_minmax_bin_op<ComplexNDArray>\n                           (argx, argy, nanflag, ismin);\n                else\n                  retval = do_minmax_bin_op<ComplexNDArray>\n                           (argx, argy, nanflag, realabs, ismin);\n              }\n          }\n          break;\n\n        case btyp_float:\n          {\n            if (cmethod)\n              retval = do_minmax_bin_op<FloatNDArray>\n                       (argx, argy, nanflag, ismin);\n            else\n              retval = do_minmax_bin_op<FloatNDArray>\n                       (argx, argy, nanflag, realabs, ismin);\n          }\n          break;\n\n        case btyp_float_complex:\n          {\n            if (cmethod)\n              retval = do_minmax_bin_op<FloatComplexNDArray>\n                       (argx, argy, nanflag, ismin);\n            else\n              retval = do_minmax_bin_op<FloatComplexNDArray>\n                       (argx, argy, nanflag, realabs, ismin);\n          }\n          break;\n\n        case btyp_char:\n          retval = do_minmax_bin_op<charNDArray> (argx, argy, ismin);\n          break;\n\n#define MAKE_INT_BRANCH(X)                                      \\\n        case btyp_ ## X:                                        \\\n          {                                                     \\\n            if (cmethod)                                        \\\n              retval = do_minmax_bin_op<X ## NDArray>           \\\n                       (argx, argy, ismin);                     \\\n            else                                                \\\n              retval = do_minmax_bin_op<X ## NDArray>           \\\n                       (argx, argy, nanflag, realabs, ismin);   \\\n          }                                                     \\\n          break;\n\n          MAKE_INT_BRANCH (int8);\n          MAKE_INT_BRANCH (int16);\n          MAKE_INT_BRANCH (int32);\n          MAKE_INT_BRANCH (int64);\n          MAKE_INT_BRANCH (uint8);\n          MAKE_INT_BRANCH (uint16);\n          MAKE_INT_BRANCH (uint32);\n          MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n        // FIXME: This is what should happen when boolNDArray has max()\n        // case btyp_bool:\n        //   retval = do_minmax_bin_op<boolNDArray> (argx, argy, ismin);\n        //   break;\n\n        default:\n          error (\"%s: cannot compute %s (%s, %s)\", fcn, fcn,\n                 argx.type_name ().c_str (), argy.type_name ().c_str ());\n        }\n\n      // FIXME: Delete when boolNDArray has max()\n      if (xtyp == btyp_bool && ytyp == btyp_bool)\n        retval(0) = retval(0).bool_array_value ();\n\n    }\n\n  // Process \"linear\" option\n  if (linear && nargout > 1 && ! allflag && ! args(0).isempty ())\n    retval(1) = get_linear_index (retval(1), args(0), vecdim, false);\n\n  return retval;\n}\n\nDEFUN (min, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{m} =} min (@var{x})\n@deftypefnx {} {@var{m} =} min (@var{x}, [], @var{dim})\n@deftypefnx {} {@var{m} =} min (@var{x}, [], @var{vecdim})\n@deftypefnx {} {@var{m} =} min (@var{x}, [], \"all\")\n@deftypefnx {} {@var{m} =} min (@var{x}, [], @var{nanflag})\n@deftypefnx {} {[@var{m}, @var{im}] =} min (@dots{})\n@deftypefnx {} {[@var{m}, @var{im}] =} min (@dots{}, \"linear\")\n@deftypefnx {} {@var{m} =} min (@var{x}, @var{y})\n@deftypefnx {} {@var{m} =} min (@var{x}, @var{y}, @var{nanflag})\n@deftypefnx {} {@dots{} =} min (@dots{}, \"ComparisonMethod\", @var{method})\nFind minimum values in the array @var{x}.\n\nIf @var{x} is a vector, then @code{min (@var{x})} returns the minimum value of\nthe elements in @var{x}.\n\nIf @var{x} is a matrix, then @code{min (@var{x})} returns a row vector with\neach element containing the minimum value of the corresponding column in\n@var{x}.\n\nIf @var{x} is an array, then @code{min (@var{x})} computes the minimum value\nalong the first non-singleton dimension of @var{x}.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension of @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{min} to operate on\non all elements of @var{x}, and is equivalent to @code{min (@var{x}(:))}.\n\nIf called with two output arguments, @code{min} also returns the first index of\nthe minimum value(s) in @var{x}.  The second output argument is only valid when\n@code{min} operates on a single input array.  Setting the @qcode{\"linear\"} flag\nreturns the linear index to the corresponding minimum values in @var{x}.\n\nIf called with two input arrays (@var{x} and @var{y}), @code{min} return the\npairwise minimum according to the rules for @ref{Broadcasting}.\n\nThe optional variable @var{nanflag} specifies whether to include or exclude\n@code{NaN} values from the calculation using any of the previously specified\ninput argument combinations.  The default value for @var{nanflag} is\n@qcode{\"omitnan\"} which ignores @code{NaN} values in the calculation.  To\ninclude @code{NaN} values, set the value of @var{nanflag} to\n@qcode{\"includenan\"}, in which case @code{min} will return @code{NaN}, if any\nelement along the operating dimension is @code{NaN}.\n\nThe optional @qcode{\"ComparisonMethod\"} paired argument specifies the\ncomparison method for numeric input and it applies to both one input and two\ninput arrays.  @var{method} can take any of the following values:\n\n@table @asis\n@item @qcode{'auto'}\nThis is the default method, which compares elements by @code{real (@var{x})}\nwhen @var{x} is real, and by @code{abs (@var{x})} when @var{x} is complex.\n\n@item @qcode{'real'}\nCompares elements by @code{real (@var{x})} when @var{x} is real or complex.\nFor elements with equal real parts, a second comparison by\n@code{imag (@var{x})} is performed.\n\n@item @qcode{'abs'}\nCompares elements by @code{abs (@var{x})} when @var{x} is real or complex.  For\nelements with equal magnitude, a second comparison by @code{angle (@var{x})} in\nthe interval from @math{-\\pi} to @math{\\pi} is performed.\n@end table\n@seealso{max, cummin, cummax}\n@end deftypefn */)\n{\n  return do_minmax_body (args, nargout, true);\n}\n\n/*\n## Test generic double class\n%!assert (min ([1, 4, 2, 3]), 1)\n%!assert (min ([1; -10; 5; -2]), -10)\n%!assert (min ([4, 2i 4.999; -2, 2, 3+4i]), [-2, 2, 4.999])\n## Special routines for char arrays\n%!assert (min ([\"abc\", \"ABC\"]), 65)\n%!assert (min ([\"abc\"; \"CBA\"]), [67 66 65])\n## Special routines for logical arrays\n%!assert (min (logical ([])), logical ([]))\n%!assert (min (logical ([0 0 1 0])), false)\n%!assert (min (logical ([0 0 1 0; 0 1 1 0])), logical ([0 0 1 0]))\n## Single values\n%!assert (min (single ([1, 4, 2, 3])), single (1))\n%!assert (min (single ([1; -10; 5; -2])), single (-10))\n%!assert (min (single ([4, 2i 4.999; -2, 2, 3+4i])), single ([-2, 2, 4.999]))\n## Integer values\n%!assert (min (uint8 ([1, 4, 2, 3])), uint8 (1))\n%!assert (min (uint8 ([1; -10; 5; -2])), uint8 (-10))\n%!assert (min (int8 ([1, 4, 2, 3])), int8 (1))\n%!assert (min (int8 ([1; -10; 5; -2])), int8 (-10))\n%!assert (min (uint16 ([1, 4, 2, 3])), uint16 (1))\n%!assert (min (uint16 ([1; -10; 5; -2])), uint16 (-10))\n%!assert (min (int16 ([1, 4, 2, 3])), int16 (1))\n%!assert (min (int16 ([1; -10; 5; -2])), int16 (-10))\n%!assert (min (uint32 ([1, 4, 2, 3])), uint32 (1))\n%!assert (min (uint32 ([1; -10; 5; -2])), uint32 (-10))\n%!assert (min (int32 ([1, 4, 2, 3])), int32 (1))\n%!assert (min (int32 ([1; -10; 5; -2])), int32 (-10))\n%!assert (min (uint64 ([1, 4, 2, 3])), uint64 (1))\n%!assert (min (uint64 ([1; -10; 5; -2])), uint64 (-10))\n%!assert (min (int64 ([1, 4, 2, 3])), int64 (1))\n%!assert (min (int64 ([1; -10; 5; -2])), int64 (-10))\n## Sparse double values\n%!assert (min (sparse ([1, 4, 2, 3])), sparse (1))\n%!assert (min (sparse ([1; -10; 5; -2])), sparse(-10))\n## Order sparse complex values by phase angle\n%!test <*51307>\n%! assert (min (sparse ([4, 2i 4.999; -2, 2, 3+4i])), sparse ([-2, 2, 4.999]));\n%! assert (min (sparse ([4, -2i 4.99; -2, 2, 3+4i])), sparse ([-2, -2i, 4.99]));\n%!assert (min (sparse ([4, 2i 4.999]), sparse ([-2, 2, 3+4i])),\n%!        sparse ([-2, 2, 4.999]))\n%!assert (min (sparse ([4, -2i 4.999]), sparse ([-2, 2, 3+4i])),\n%!        sparse ([-2, -2i, 4.999]))\n\n## Test dimension argument\n%!test\n%! x = reshape (1:8, [2,2,2]);\n%! assert (min (x, [], 1), reshape ([1, 3, 5, 7], [1,2,2]));\n%! assert (min (x, [], 2), reshape ([1, 2, 5, 6], [2,1,2]));\n%! [y, i] = min (x, [], 3);\n%! assert (ndims (y), 2);\n%! assert (y, [1, 3; 2, 4]);\n%! assert (ndims (i), 2);\n%! assert (i, [1, 1; 1, 1]);\n\n## Test vecdim argument\n%!test\n%! x = reshape (1:8, [2,2,2]);\n%! assert (min (x, [], [1, 3]), [1, 3]);\n%! assert (min (x, [], [2, 3]), [1; 2]);\n%! assert (min (x, [], [1, 2]), reshape ([1, 5], [1,1,2]));\n%! assert (min (x, [], [1, 2, 3]), min (x, [], \"all\"));\n\n## Test 2-output forms for various arg types\n## Special routines for char arrays\n%!test\n%! [y, i] = min ([\"abc\", \"ABC\"]);\n%! assert (y, 65);\n%! assert (i, 4);\n## Special routines for logical arrays\n%!test\n%! x = logical ([0 0 1 0]);\n%! [y, i] = min (x);\n%! assert (y, false);\n%! assert (i, 1);\n## Special handling of ranges\n%!test\n%! rng = 1:2:10;\n%! [y, i] = min (rng);\n%! assert (y, 1);\n%! assert (i, 1);\n%! rng = 10:-2:1;\n%! [y, i] = min (rng);\n%! assert (y, 2);\n%! assert (i, 5);\n\n## Test 2-input calling form for various arg types\n## Test generic double class\n%!test\n%! x = [1, 2, 3, 4];  y = fliplr (x);\n%! assert (min (x, y), [1 2 2 1]);\n%! assert (min (x, 3), [1 2 3 3]);\n%! assert (min (2, x), [1 2 2 2]);\n%! assert (min (x, 2.1i), [1 2 2.1i 2.1i]);\n## Test ordering of complex results with equal magnitude\n%!test <*51307>\n%! x = [1, 2, 3, 4];\n%! assert (min (x, 2i), [1 2 2i 2i]);\n%! assert (min (x, -2i), [1 -2i -2i -2i]);\n## Special routines for char arrays\n%!assert (min (\"abc\", \"b\"), [97 98 98])\n%!assert (min (\"b\", \"cba\"), [98 98 97])\n## Special handling for logical arrays\n%!assert (min ([true false], false), [false false])\n%!assert (min (true, [true false]), [true false])\n## Single values\n%!test\n%! x = single ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), single ([1 2 2 1]));\n%! assert (min (x, 3), single ([1 2 3 3]));\n%! assert (min (2, x), single ([1 2 2 2]));\n%! assert (min (x, 2.1i), single ([1 2 2.1i 2.1i]));\n## Integer values\n%!test\n%! x = uint8 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), uint8 ([1 2 2 1]));\n%! assert (min (x, 3), uint8 ([1 2 3 3]));\n%! assert (min (2, x), uint8 ([1 2 2 2]));\n%! x = int8 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), int8 ([1 2 2 1]));\n%! assert (min (x, 3), int8 ([1 2 3 3]));\n%! assert (min (2, x), int8 ([1 2 2 2]));\n%! x = uint16 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), uint16 ([1 2 2 1]));\n%! assert (min (x, 3), uint16 ([1 2 3 3]));\n%! assert (min (2, x), uint16 ([1 2 2 2]));\n%! x = int16 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), int16 ([1 2 2 1]));\n%! assert (min (x, 3), int16 ([1 2 3 3]));\n%! assert (min (2, x), int16 ([1 2 2 2]));\n%! x = uint32 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), uint32 ([1 2 2 1]));\n%! assert (min (x, 3), uint32 ([1 2 3 3]));\n%! assert (min (2, x), uint32 ([1 2 2 2]));\n%! x = int32 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), int32 ([1 2 2 1]));\n%! assert (min (x, 3), int32 ([1 2 3 3]));\n%! assert (min (2, x), int32 ([1 2 2 2]));\n%! x = uint64 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), uint64 ([1 2 2 1]));\n%! assert (min (x, 3), uint64 ([1 2 3 3]));\n%! assert (min (2, x), uint64 ([1 2 2 2]));\n%! x = int64 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), int64 ([1 2 2 1]));\n%! assert (min (x, 3), int64 ([1 2 3 3]));\n%! assert (min (2, x), int64 ([1 2 2 2]));\n## Sparse double values\n%!test\n%! x = sparse ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (min (x, y), sparse ([1 2 2 1]));\n%! assert (min (x, 3), sparse ([1 2 3 3]));\n%! assert (min (2, x), sparse ([1 2 2 2]));\n%! assert (min (x, 2.1i), sparse ([1 2 2.1i 2.1i]));\n%!assert (min (sparse ([4, 2i, 4.999; -2, 2, 3+4i])), sparse ([-2, 2, 4.999]))\n%!assert (min (sparse ([4, 2+i, 4.999; -2, 2, 3+4i])), sparse ([-2, 2, 4.999]))\n%!assert (min (sparse ([4, 2i, 4.999; -2, 2-i, 3+4i])),\n%!        sparse ([-2, 2i, 4.999]))\n\n## Sparse with NaNs\n%!assert (min (sparse ([NaN, 1, 2, 1])), sparse (1))\n%!assert (min (sparse ([NaN; 1; 2; 1])), sparse (1))\n%!assert (min (sparse ([0, NaN, 1, 2, 1])), sparse (0))\n%!assert (min (sparse ([0; NaN; 1; 2; 1])), sparse (0))\n%!assert (min (sparse ([0; NaN; 1; 2; 1]), [], \"includenan\"), sparse (NaN))\n%!assert (min (sparse ([0; NaN; 1; 2; 1]), [], 1, \"includenan\"), sparse (NaN))\n%!assert (min (sparse ([0; NaN; 1; 2; 1]), [], 2, \"includenan\"),\n%!        sparse ([0; NaN; 1; 2; 1]))\n%!assert (min (sparse ([NaN, 1i, 2, 1])), sparse (1))\n%!assert (min (sparse ([NaN, 1i, 2, 1]), \"ComparisonMethod\", \"real\"),\n%!        sparse (1i))\n%!assert (min (sparse (single ([NaN, 1, 2, 1]))), sparse (1))\n%!assert (min (sparse (single ([NaN; 1; 2; 1]))), sparse (1))\n%!assert (min (sparse (single ([0, NaN, 1, 2, 1]))), sparse (0))\n%!assert (min (sparse (single ([0; NaN; 1; 2; 1]))), sparse (0))\n%!assert (min (sparse (single ([0; NaN; 1; 2; 1])), [], \"includenan\"),\n%!        sparse (NaN))\n%!assert (min (sparse (single ([0; NaN; 1; 2; 1])), [], 1, \"includenan\"),\n%!        sparse (NaN))\n%!assert (min (sparse (single ([NaN, 1i, 2, 1]))), sparse (1))\n%!assert (min (sparse (single ([NaN, 1i, 2, 1])), \"ComparisonMethod\", \"real\"),\n%!        sparse (1i))\n%!assert (min (sparse (single ([NaN, 1i, 2, 1]))), sparse (1))\n\n## Test broadcasting of empty matrices with min/max functions\n%!assert (min (sparse (zeros (0,1)), sparse ([1, 2, 3, 4])),\n%!        sparse (zeros (0,4)))\n%!error min (sparse (zeros (0,2)), sparse ([1, 2, 3, 4]))\n%!assert (min (sparse (zeros (1,0)), sparse ([1; 2; 3; 4])),\n%!        sparse (zeros (4,0)))\n%!error min (sparse (zeros (2,0)), sparse ([1; 2; 3; 4]))\n%!assert (min (sparse (zeros (0,1)), sparse ([1, 2, 3, 4i])),\n%!        sparse (zeros (0,4)))\n%!error min (sparse (zeros (0,2)), sparse ([1, 2, 3, 4i]))\n%!assert (min (sparse (zeros (1,0)), sparse ([1; 2; 3; 4i])),\n%!        sparse (zeros (4,0)))\n%!error min (sparse (zeros (2,0)), sparse ([1; 2; 3; 4i]))\n\n## NaNs and complex numbers\n%!assert (min (NaN, 0), 0)\n%!assert (min (NaN+1i, 0), 0)\n%!assert (min (2+2i, 2-2i), 2-2i)\n%!assert (min (2-2i, 2+2i), 2-2i)\n%!test\n%! [M1, I1] = min ([2+2i, 2-2i]);\n%! [M2, I2] = min ([2-2i, 2+2i]);\n%! assert (M1, M2);\n%! assert (I1, 2);\n%! assert (I2, 1);\n%!assert (min (NaN, 0, \"ComparisonMethod\", \"real\"),\n%!        min (NaN+1i, 0, \"ComparisonMethod\", \"real\"))\n%!assert (min (2+i, 1+10i), 2+1i)\n%!assert (min (2+i, 1+10i, \"ComparisonMethod\", \"real\"), 1+10i)\n%!assert (min (2+i, 1+10i, \"ComparisonMethod\", \"abs\"), 2+1i)\n%!assert (min (2+i, -1+10i, \"ComparisonMethod\", \"abs\"), 2+1i)\n%!assert (min (2+i, -2+i, \"ComparisonMethod\", \"abs\"), 2+1i)\n%!assert (min (2+i, 2-i, \"ComparisonMethod\", \"abs\"), 2-1i)\n%!assert (min (2+i, 2-i, \"ComparisonMethod\", \"real\"), 2-1i)\n%!assert (min ([1i 2 -3 4]), 1i)\n%!assert (min ([-2+i, 2-i]), 2-1i)\n\n## Test nanflag with dense arrays\n%!test\n%! [m,i] = min ([1,2,3;4,3,NaN;4,5,6], [], 2, \"includenan\");\n%! assert (m, [1; NaN; 4]);\n%! assert (i, [1; 3; 1]);\n%! [m,i] = min ([1,2,3;4,NaN,NaN;4,5,6], [], 2, \"includenan\");\n%! assert (m, [1; NaN; 4]);\n%! assert (i, [1; 2; 1]);\n%!test\n%! x = magic (3);\n%! x(2, 3) = NaN;\n%! assert (min (x, [], 2, \"includenan\"), [1; NaN; 2]);\n\n## Test empty matrices and those with 0 dimensions (including catching errors)\n%!assert (size (min (0, zeros (0, 1))), [0, 1])\n%!assert (size (min ([], zeros (0, 1))), [0, 0])\n%!assert (size (min (zeros (0, 1), [])), [0, 0])\n%!assert (size (min ([], zeros (1, 0))), [0, 0])\n%!assert (size (min (zeros (1, 0), [])), [0, 0])\n%!error min ([1, 2, 3, 4], zeros (1, 0))\n%!assert (size (min ([1, 2, 3, 4], zeros (0, 1))), [0, 4])\n%!assert (min (0, sparse (zeros (1,0))), sparse (zeros (1, 0)))\n%!assert (min (sparse (zeros (1,0)), 0), sparse (zeros (1, 0)))\n%!error min (sparse (zeros (1,0)), sparse ([1, 2, 3, 4]))\n%!error min ([1, 2, NaN, 4], zeros (1, 0), 'includenan')\n%!assert (min ([1, 2, NaN, 4], zeros (0, 1), 'includenan'), zeros (0, 4))\n%!error min (sparse (zeros (1,0)), sparse ([1, 2, NaN 4]), 'includenan')\n%!assert (min (sparse (zeros (1,0)), sparse ([1; 2; 3; 4])),\n%!        sparse (zeros (4, 0)))\n%!assert (min (zeros(0,3), zeros (0, 1)), zeros (0, 3))\n%!error min (zeros(3, 0), zeros (0, 1))\n%!assert (min (zeros(3, 0), zeros (1, 0)), zeros (3, 0))\n%!error min (zeros(3, 0), zeros (0, 0))\n%!error min (zeros(3, 0), [])\n%!error min ([], zeros(3, 0))\n%!error min (zeros(0,1), zeros(3, 0))\n%!assert (min (zeros(1,0), zeros(3, 0)), zeros (3, 0))\n\n## Test \"linear\" option\n%!shared x\n%! x = repmat ([4,3,2,4,1,5,3,2], 3, 2, 5, 2);\n%!test\n%! [m, i] = min (x, [], [2, 3], 'linear');\n%! assert (m, ones (3, 1, 1, 2));\n%! assert (i(:,:,1,1), [13; 14; 15]);\n%! assert (i(:,:,1,2), [253; 254; 255]);\n%!test\n%! [m, i] = min (x, [], [1, 3], 'linear');\n%! assert (m, x(1,:,1,:));\n%! assert (i(:,:,1,1), [1:3:46]);\n%! assert (i(:,:,1,2), [241:3:286]);\n%!test\n%! [m, i] = min (x, [], [2, 4], 'linear');\n%! assert (m, ones (3, 1, 5));\n%! assert (i(:,:,1), [13; 14; 15]);\n%! assert (i(:,:,2), [61; 62; 63]);\n%! assert (i(:,:,3), [109; 110; 111]);\n%! assert (i(:,:,4), [157; 158; 159]);\n%! assert (i(:,:,5), [205; 206; 207]);\n%!test\n%! [m, i] = min (x, [], [1, 4], 'linear');\n%! assert (m, x(1, :,:,1));\n%! assert (i(:,:,1), [1:3:46]);\n%! assert (i(:,:,2), [49:3:94]);\n%! assert (i(:,:,3), [97:3:142]);\n%! assert (i(:,:,4), [145:3:190]);\n%! assert (i(:,:,5), [193:3:238]);\n%!test\n%! [m, i] = min (x, [], [1, 2, 3], 'linear');\n%! assert (m, ones (1, 1, 1, 2));\n%! assert (i(:,:,1,1), 13);\n%! assert (i(:,:,1,2), 253);\n%!test\n%! [m, i] = min (x, [], [2, 3, 4], 'linear');\n%! assert (m, [1; 1; 1]);\n%! assert (i, [13; 14; 15]);\n%!test\n%! [m, i] = min ([1, 2, 3; 4, 5, 6], [], 1, 'linear');\n%! assert (m, [1, 2, 3]);\n%! assert (i, [1, 3, 5]);\n%!test\n%! [m, i] = min ([1, 2, 3; 4, 5, 6], [], 2, 'linear');\n%! assert (m, [1; 4]);\n%! assert (i, [1; 2]);\n\n## Test input validation\n%!error <Invalid call> min ()\n%!error <Invalid call> min (1, 2, 3, 4)\n%!error <unrecognized optional argument 'foobar'> min (1, [], \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! min (ones (3,3), [], 1, \"all\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! min (ones (3,3), [], [1, 2], \"all\")\n%!error <invalid dimension DIM = 0> min (ones (3,3), [], 0)\n%!error <invalid dimension DIM = -1> min (ones (3,3), [], -1)\n%!error <invalid dimension in VECDIM = -2> min (ones (3,3), [], [1 -2])\n%!error <duplicate dimension in VECDIM = 2> min (ones (3,3), [], [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> min (ones (3,3), [], [1 1 2])\n%!warning <second argument is ignored> min ([1 2 3 4], 2, 2);\n%!error <wrong type argument 'cell'> min ({1 2 3 4})\n%!error <cannot compute min \\(cell, scalar\\)> min ({1, 2, 3}, 2)\n%!error <two output arguments are not supported for two input arrays>\n%! [m, i] = min ([], [])\n%!error <'linear' is not supported for two input arrays>\n%! min ([1 2 3 4], 1,  \"linear\")\n%! [m, i] = min ([1 2 3 4], [], \"linear\");\n*/\n\nDEFUN (max, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{m} =} max (@var{x})\n@deftypefnx {} {@var{m} =} max (@var{x}, [], @var{dim})\n@deftypefnx {} {@var{m} =} max (@var{x}, [], @var{vecdim})\n@deftypefnx {} {@var{m} =} max (@var{x}, [], \"all\")\n@deftypefnx {} {@var{m} =} max (@var{x}, [], @var{nanflag})\n@deftypefnx {} {[@var{m}, @var{im}] =} max (@dots{})\n@deftypefnx {} {[@var{m}, @var{im}] =} max (@dots{}, \"linear\")\n@deftypefnx {} {@var{m} =} max (@var{x}, @var{y})\n@deftypefnx {} {@var{m} =} max (@var{x}, @var{y}, @var{nanflag})\n@deftypefnx {} {@dots{} =} max (@dots{}, \"ComparisonMethod\", @var{method})\nFind maximum values in the array @var{x}.\n\nIf @var{x} is a vector, then @code{max (@var{x})} returns the maximum value of\nthe elements in @var{x}.\n\nIf @var{x} is a matrix, then @code{max (@var{x})} returns a row vector with\neach element containing the maximum value of the corresponding column in\n@var{x}.\n\nIf @var{x} is an array, then @code{max (@var{x})} computes the maximum value\nalong the first non-singleton dimension of @var{x}.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension of @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{max} to operate on\non all elements of @var{x}, and is equivalent to @code{max (@var{x}(:))}.\n\nIf called with two output arguments, @code{max} also returns the first index of\nthe maximum value(s) in @var{x}.  The second output argument is only valid when\n@code{max} operates on a single input array.  Setting the @qcode{\"linear\"} flag\nreturns the linear index to the corresponding minimum values in @var{x}.\n\nIf called with two input arrays (@var{x} and @var{y}), @code{max} return the\npairwise maximum according to the rules for @ref{Broadcasting}.\n\nThe optional variable @var{nanflag} specifies whether to include or exclude\n@code{NaN} values from the calculation using any of the previously specified\ninput argument combinations.  The default value for @var{nanflag} is\n@qcode{\"omitnan\"} which ignores @code{NaN} values in the calculation.  To\ninclude @code{NaN} values, set the value of @var{nanflag} to\n@qcode{\"includenan\"}, in which case @code{max} will return @code{NaN}, if any\nelement along the operating dimension is @code{NaN}.\n\nThe optional @qcode{\"ComparisonMethod\"} paired argument specifies the\ncomparison method for numeric input and it applies to both one input and two\ninput arrays.  @var{method} can take any of the following values:\n\n@table @asis\n@item @qcode{'auto'}\nThis is the default method, which compares elements by @code{real (@var{x})}\nwhen @var{x} is real, and by @code{abs (@var{x})} when @var{x} is complex.\n\n@item @qcode{'real'}\nCompares elements by @code{real (@var{x})} when @var{x} is real or complex.\nFor elements with equal real parts, a second comparison by\n@code{imag (@var{x})} is performed.\n\n@item @qcode{'abs'}\nCompares elements by @code{abs (@var{x})} when @var{x} is real or complex.  For\nelements with equal magnitude, a second comparison by @code{angle (@var{x})} in\nthe interval from @math{-\\pi} to @math{\\pi} is performed.\n@end table\n@seealso{min, cummax, cummin}\n@end deftypefn */)\n{\n  return do_minmax_body (args, nargout, false);\n}\n\n/*\n## Test generic double class\n%!assert (max ([1, 4, 2, 3]), 4)\n%!assert (max ([1; -10; 5; -2]), 5)\n%!assert (max ([4, 2i 4.999; -2, 2, 3+4i]), [4, 2i, 3+4i])\n## Special routines for char arrays\n%!assert (max ([\"abc\", \"ABC\"]), 99)\n%!assert (max ([\"abc\"; \"CBA\"]), [97 98 99])\n## Special routines for logical arrays\n%!assert (max (logical ([])), logical ([]))\n%!assert (max (logical ([0 0 1 0])), true)\n%!assert (max (logical ([0 0 1 0; 0 1 0 0])), logical ([0 1 1 0]))\n## Single values\n%!assert (max (single ([1, 4, 2, 3])), single (4))\n%!assert (max (single ([1; -10; 5; -2])), single (5))\n%!assert (max (single ([4, 2i 4.999; -2, 2, 3+4i])), single ([4, 2i, 3+4i]))\n## Integer values\n%!assert (max (uint8 ([1, 4, 2, 3])), uint8 (4))\n%!assert (max (uint8 ([1; -10; 5; -2])), uint8 (5))\n%!assert (max (int8 ([1, 4, 2, 3])), int8 (4))\n%!assert (max (int8 ([1; -10; 5; -2])), int8 (5))\n%!assert (max (uint16 ([1, 4, 2, 3])), uint16 (4))\n%!assert (max (uint16 ([1; -10; 5; -2])), uint16 (5))\n%!assert (max (int16 ([1, 4, 2, 3])), int16 (4))\n%!assert (max (int16 ([1; -10; 5; -2])), int16 (5))\n%!assert (max (uint32 ([1, 4, 2, 3])), uint32 (4))\n%!assert (max (uint32 ([1; -10; 5; -2])), uint32 (5))\n%!assert (max (int32 ([1, 4, 2, 3])), int32 (4))\n%!assert (max (int32 ([1; -10; 5; -2])), int32 (5))\n%!assert (max (uint64 ([1, 4, 2, 3])), uint64 (4))\n%!assert (max (uint64 ([1; -10; 5; -2])), uint64 (5))\n%!assert (max (int64 ([1, 4, 2, 3])), int64 (4))\n%!assert (max (int64 ([1; -10; 5; -2])), int64 (5))\n## Sparse double values\n%!assert (max (sparse ([1, 4, 2, 3])), sparse (4))\n%!assert (max (sparse ([1; -10; 5; -2])), sparse(5))\n## Order sparse complex values by phase angle\n%!test <*51307>\n%! assert (max (sparse ([4, 2i 4.999; -2, 2, 3+4i])), sparse ([4, 2i, 3+4i]));\n%! assert (max (sparse ([4, -2i 4.999; -2, 2, 3+4i])), sparse ([4, 2, 3+4i]));\n%!assert (max (sparse ([4, 2i 4.999]), sparse ([-2, 2, 3+4i])),\n%!        sparse ([4, 2i, 3+4i]))\n%!assert (max (sparse ([4, -2i 4.999]), sparse ([-2, 2, 3+4i])),\n%!        sparse ([4, 2, 3+4i]))\n\n## Test dimension argument\n%!test\n%! x = reshape (1:8, [2,2,2]);\n%! assert (max (x, [], 1), reshape ([2, 4, 6, 8], [1,2,2]));\n%! assert (max (x, [], 2), reshape ([3, 4, 7, 8], [2,1,2]));\n%! [y, i] = max (x, [], 3);\n%! assert (ndims (y), 2);\n%! assert (y, [5, 7; 6, 8]);\n%! assert (ndims (i), 2);\n%! assert (i, [2, 2; 2, 2]);\n\n## Test vecdim argument\n%!test\n%! x = reshape (1:8, [2,2,2]);\n%! assert (max (x, [], [1, 3]), [6, 8]);\n%! assert (max (x, [], [2, 3]), [7; 8]);\n%! assert (max (x, [], [1, 2]), reshape ([4, 8], [1,1,2]));\n%! assert (max (x, [], [1, 2, 3]), max (x, [], \"all\"));\n\n## Test 2-output forms for various arg types\n## Special routines for char arrays\n%!test\n%! [y, i] = max ([\"abc\", \"ABC\"]);\n%! assert (y, 99);\n%! assert (i, 3);\n## Special routines for logical arrays\n%!test\n%! x = logical ([0 0 1 0]);\n%! [y, i] = max (x);\n%! assert (y, true);\n%! assert (i, 3);\n## Special handling of ranges\n%!test\n%! rng = 1:2:10;\n%! [y, i] = max (rng);\n%! assert (y, 9);\n%! assert (i, 5);\n%! rng = 10:-2:1;\n%! [y, i] = max (rng);\n%! assert (y, 10);\n%! assert (i, 1);\n\n## Test 2-input calling form for various arg types\n## Test generic double class\n%!test\n%! x = [1, 2, 3, 4];  y = fliplr (x);\n%! assert (max (x, y), [4 3 3 4]);\n%! assert (max (x, 3), [3 3 3 4]);\n%! assert (max (2, x), [2 2 3 4]);\n%! assert (max (x, 2.1i), [2.1i 2.1i 3 4]);\n## Test ordering of complex results with equal magnitude\n%!test <*51307>\n%! x = [1, 2, 3, 4];\n%! assert (max (x, 2i), [2i 2i 3 4]);\n%! assert (max (x, -2i), [-2i 2 3 4]);\n## Special routines for char arrays\n%!assert (max (\"abc\", \"b\"), [98 98 99])\n%!assert (max (\"b\", \"cba\"), [99 98 98])\n## Special handling for logical arrays\n%!assert (max ([true false], false), [true false])\n%!assert (max (true, [false false]), [true true])\n## Single values\n%!test\n%! x = single ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), single ([4 3 3 4]));\n%! assert (max (x, 3), single ([3 3 3 4]));\n%! assert (max (2, x), single ([2 2 3 4]));\n%! assert (max (x, 2.1i), single ([2.1i 2.1i 3 4]));\n## Integer values\n%!test\n%! x = uint8 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), uint8 ([4 3 3 4]));\n%! assert (max (x, 3), uint8 ([3 3 3 4]));\n%! assert (max (2, x), uint8 ([2 2 3 4]));\n%! x = int8 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), int8 ([4 3 3 4]));\n%! assert (max (x, 3), int8 ([3 3 3 4]));\n%! assert (max (2, x), int8 ([2 2 3 4]));\n%! x = uint16 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), uint16 ([4 3 3 4]));\n%! assert (max (x, 3), uint16 ([3 3 3 4]));\n%! assert (max (2, x), uint16 ([2 2 3 4]));\n%! x = int16 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), int16 ([4 3 3 4]));\n%! assert (max (x, 3), int16 ([3 3 3 4]));\n%! assert (max (2, x), int16 ([2 2 3 4]));\n%! x = uint32 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), uint32 ([4 3 3 4]));\n%! assert (max (x, 3), uint32 ([3 3 3 4]));\n%! assert (max (2, x), uint32 ([2 2 3 4]));\n%! x = int32 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), int32 ([4 3 3 4]));\n%! assert (max (x, 3), int32 ([3 3 3 4]));\n%! assert (max (2, x), int32 ([2 2 3 4]));\n%! x = uint64 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), uint64 ([4 3 3 4]));\n%! assert (max (x, 3), uint64 ([3 3 3 4]));\n%! assert (max (2, x), uint64 ([2 2 3 4]));\n%! x = int64 ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), int64 ([4 3 3 4]));\n%! assert (max (x, 3), int64 ([3 3 3 4]));\n%! assert (max (2, x), int64 ([2 2 3 4]));\n## Sparse double values\n%!test\n%! x = sparse ([1, 2, 3, 4]);  y = fliplr (x);\n%! assert (max (x, y), sparse ([4 3 3 4]));\n%! assert (max (x, 3), sparse ([3 3 3 4]));\n%! assert (max (2, x), sparse ([2 2 3 4]));\n%! assert (max (x, 2.1i), sparse ([2.1i 2.1i 3 4]));\n%!assert (max (sparse ([4, 2i, 4.999; -2, 2, 3+4i])), sparse ([4, 2i, 3+4i]))\n%!assert (max (sparse ([4, 2+i, 4.999; -2, 2, 3+4i])), sparse ([4, 2+i, 3+4i]))\n%!assert (max (sparse ([4, 2i, 4.999; -2, 2-i, 3+4i])), sparse ([4, 2-i, 3+4i]))\n\n## Test for bug #40743\n%!assert <*40743> (max (zeros (1,0), ones (1,1)), zeros (1,0))\n%!assert <*40743> (max (sparse (zeros (1,0)), sparse (ones (1,1))),\n%!                sparse (zeros (1,0)))\n\n## Sparse with NaNs\n%!assert (max (sparse ([NaN, 1, 2, 1])), sparse (2))\n%!assert (max (sparse ([NaN; 1; 2; 1])), sparse (2))\n%!assert (max (sparse ([0, NaN, 1, 2, 1])), sparse (2))\n%!assert (max (sparse ([0; NaN; 1; 2; 1])), sparse (2))\n%!assert (max (sparse ([0; NaN; 1; 2; 1]), [], \"includenan\"), sparse (NaN))\n%!assert (max (sparse ([0; NaN; 1; 2; 1]), [], 1, \"includenan\"), sparse (NaN))\n%!assert (max (sparse ([0; NaN; 1; 2; 1]), [], 2, \"includenan\"),\n%!        sparse ([0; NaN; 1; 2; 1]))\n%!assert (max (sparse ([NaN, 1i, 2, 1])), sparse (2))\n%!assert (max (sparse ([NaN, 1i, 2, 1]), \"ComparisonMethod\", \"real\"),\n%!        sparse (2))\n%!assert (max (sparse (single ([NaN, 1, 2, 1]))), sparse (2))\n%!assert (max (sparse (single ([NaN; 1; 2; 1]))), sparse (2))\n%!assert (max (sparse (single ([0, NaN, 1, 2, 1]))), sparse (2))\n%!assert (max (sparse (single ([0; NaN; 1; 2; 1]))), sparse (2))\n%!assert (max (sparse (single ([0; NaN; 1; 2; 1])), [], \"includenan\"),\n%!        sparse (NaN))\n%!assert (max (sparse (single ([0; NaN; 1; 2; 1])), [], 1, \"includenan\"),\n%!        sparse (NaN))\n%!assert (max (sparse (single ([NaN, 1i, 2, 1]))), sparse (2))\n%!assert (max (sparse (single ([NaN, 1i, 2, 1])), \"ComparisonMethod\", \"real\"),\n%!        sparse (2))\n%!assert (max (sparse (single ([NaN, 1i, 1]))), sparse (1i))\n\n## Test broadcasting of empty matrices with min/max functions\n%!assert (max (sparse (zeros (0,1)), sparse ([1, 2, 3, 4])),\n%!        sparse (zeros (0,4)))\n%!error max (sparse (zeros (0,2)), sparse ([1, 2, 3, 4]))\n%!assert (max (sparse (zeros (1,0)), sparse ([1; 2; 3; 4])),\n%!        sparse (zeros (4,0)))\n%!error max (sparse (zeros (2,0)), sparse ([1; 2; 3; 4]))\n%!assert (max (sparse (zeros (0,1)), sparse ([1, 2, 3, 4i])),\n%!        sparse (zeros (0,4)))\n%!error max (sparse (zeros (0,2)), sparse ([1, 2, 3, 4i]))\n%!assert (max (sparse (zeros (1,0)), sparse ([1; 2; 3; 4i])),\n%!        sparse (zeros (4,0)))\n%!error max (sparse (zeros (2,0)), sparse ([1; 2; 3; 4i]))\n\n## NaNs and complex numbers\n%!assert (max (NaN, 0), 0)\n%!assert (max (NaN+1i, 0), 0)\n%!assert (max (2+2i, 2-2i), 2+2i)\n%!assert (max (2-2i, 2+2i), 2+2i)\n%!test\n%! [M1, I1] = max ([2+2i, 2-2i]);\n%! [M2, I2] = max ([2-2i, 2+2i]);\n%! assert (M1, M2);\n%! assert (I1, 1);\n%! assert (I2, 2);\n%!assert (max (NaN, 0, \"ComparisonMethod\", \"real\"),\n%!        max (NaN+1i, 0, \"ComparisonMethod\", \"real\"))\n%!assert (max (2+i, 1+10i), 1+10i)\n%!assert (max (2+i, 1+10i, \"ComparisonMethod\", \"real\"), 2+i)\n%!assert (max (2+i, 1+10i, \"ComparisonMethod\", \"abs\"), 1+10i)\n%!assert (max (2+i, -1+10i, \"ComparisonMethod\", \"abs\"), -1+10i)\n%!assert (max (2+i, -2+i, \"ComparisonMethod\", \"abs\"), -2+1i)\n%!assert (max (2+i, 2-i, \"ComparisonMethod\", \"abs\"), 2+1i)\n%!assert (max (2+i, 2-i, \"ComparisonMethod\", \"real\"), 2+1i)\n%!assert (max ([1i 2 -3 4]), 4)\n%!assert (max ([-2+i, 2-i]), -2+1i)\n\n## Test nanflag with dense arrays\n%!test\n%! [m,i] = max ([1,2,3;4,3,NaN;4,5,6], [], 2, \"includenan\");\n%! assert (m, [3; NaN; 6]);\n%! assert (i, [3; 3; 3]);\n%! [m,i] = max ([1,2,3;4,NaN,NaN;4,5,6], [], 2, \"includenan\");\n%! assert (m, [3; NaN; 6]);\n%! assert (i, [3; 2; 3]);\n%!test\n%! x = magic (3);\n%! x(2, 3) = NaN;\n%! assert (max (x, [], 2, \"includenan\"), [8; NaN; 9]);\n\n## Test empty matrices and those with 0 dimensions (including catching errors)\n%!assert (size (max (0, zeros (0, 1))), [0, 1])\n%!assert (size (max ([], zeros (0, 1))), [0, 0])\n%!assert (size (max (zeros (0, 1), [])), [0, 0])\n%!assert (size (max ([], zeros (1, 0))), [0, 0])\n%!assert (size (max (zeros (1, 0), [])), [0, 0])\n%!error max ([1, 2, 3, 4], zeros (1, 0))\n%!assert (size (max ([1, 2, 3, 4], zeros (0, 1))), [0, 4])\n%!assert (max (0, sparse (zeros (1,0))), sparse (zeros (1, 0)))\n%!assert (max (sparse (zeros (1,0)), 0), sparse (zeros (1, 0)))\n%!error max (sparse (zeros (1,0)), sparse ([1, 2, 3, 4]))\n%!error max ([1, 2, NaN, 4], zeros (1, 0), 'includenan')\n%!assert (max ([1, 2, NaN, 4], zeros (0, 1), 'includenan'), zeros (0, 4))\n%!error max (sparse (zeros (1,0)), sparse ([1, 2, NaN 4]), 'includenan')\n%!assert (max (sparse (zeros (1,0)), sparse ([1; 2; 3; 4])),\n%!        sparse (zeros (4, 0)))\n%!assert (max (zeros(0,3), zeros (0, 1)), zeros (0, 3))\n%!error max (zeros(3, 0), zeros (0, 1))\n%!assert (max (zeros(3, 0), zeros (1, 0)), zeros (3, 0))\n%!error max (zeros(3, 0), zeros (0, 0))\n%!error max (zeros(3, 0), [])\n%!error max ([], zeros(3, 0))\n%!error max (zeros(0,1), zeros(3, 0))\n%!assert (max (zeros(1,0), zeros(3, 0)), zeros (3, 0))\n\n## Test \"linear\" option\n%!shared x\n%! x = repmat ([4,3,2,4,1,5,3,2], 3, 2, 5, 2);\n%!test\n%! [m, i] = max (x, [], [2, 3], 'linear');\n%! assert (m, 5 * ones (3, 1, 1, 2));\n%! assert (i(:,:,1,1), [16; 17; 18]);\n%! assert (i(:,:,1,2), [256; 257; 258]);\n%!test\n%! [m, i] = max (x, [], [1, 3], 'linear');\n%! assert (m, x(1,:,1,:));\n%! assert (i(:,:,1,1), [1:3:46]);\n%! assert (i(:,:,1,2), [241:3:286]);\n%!test\n%! [m, i] = max (x, [], [2, 4], 'linear');\n%! assert (m, 5 * ones (3, 1, 5));\n%! assert (i(:,:,1), [16; 17; 18]);\n%! assert (i(:,:,2), [64; 65; 66]);\n%! assert (i(:,:,3), [112; 113; 114]);\n%! assert (i(:,:,4), [160; 161; 162]);\n%! assert (i(:,:,5), [208; 209; 210]);\n%!test\n%! [m, i] = max (x, [], [1, 4], 'linear');\n%! assert (m, x(1, :,:,1));\n%! assert (i(:,:,1), [1:3:46]);\n%! assert (i(:,:,2), [49:3:94]);\n%! assert (i(:,:,3), [97:3:142]);\n%! assert (i(:,:,4), [145:3:190]);\n%! assert (i(:,:,5), [193:3:238]);\n%!test\n%! [m, i] = max (x, [], [1, 2, 3], 'linear');\n%! assert (m, 5 * ones (1, 1, 1, 2));\n%! assert (i(:,:,1,1), 16);\n%! assert (i(:,:,1,2), 256);\n%!test\n%! [m, i] = max (x, [], [2, 3, 4], 'linear');\n%! assert (m, [5; 5; 5]);\n%! assert (i, [16; 17; 18]);\n%!test\n%! [m, i] = max ([1, 2, 3; 4, 5, 6], [], 1, 'linear');\n%! assert (m, [4, 5, 6]);\n%! assert (i, [2, 4, 6]);\n%!test\n%! [m, i] = max ([1, 2, 3; 4, 5, 6], [], 2, 'linear');\n%! assert (m, [3; 6]);\n%! assert (i, [5; 6]);\n\n## Test input validation\n%!error <Invalid call> max ()\n%!error <Invalid call> max (1, 2, 3, 4)\n%!error <unrecognized optional argument 'foobar'> max (1, [], \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! max (ones (3,3), [], 1, \"all\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! max (ones (3,3), [], [1, 2], \"all\")\n%!error <invalid dimension DIM = 0> max (ones (3,3), [], 0)\n%!error <invalid dimension DIM = -1> max (ones (3,3), [], -1)\n%!error <invalid dimension in VECDIM = -2> max (ones (3,3), [], [1 -2])\n%!error <duplicate dimension in VECDIM = 2> max (ones (3,3), [], [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> max (ones (3,3), [], [1 1 2])\n%!warning <second argument is ignored> max ([1 2 3 4], 2, 2);\n%!error <wrong type argument 'cell'> max ({1 2 3 4})\n%!error <cannot compute max \\(cell, scalar\\)> max ({1, 2, 3}, 2)\n%!error <two output arguments are not supported for two input arrays>\n%! [m, i] = max ([], [])\n%!error <'linear' is not supported for two input arrays>\n%! max ([1 2 3 4], 1,  \"linear\")\n%! [m ,i] = max ([1 2 3 4], [], \"linear\");\n*/\n\nstatic Array<octave_idx_type>\nreverse_index (Array<octave_idx_type> idx, const dim_vector array_size, int dim)\n{\n  octave_idx_type n = idx.numel ();\n  if (dim == -1)\n    dim = array_size.first_non_singleton ();\n  octave_idx_type dim_size = array_size(dim);\n  for (octave_idx_type i = 0; i < n; i++)\n    idx(i) = dim_size - idx(i) - 1;\n  return idx;\n}\n\ntemplate <typename ArrayType>\nstatic octave_value_list\ndo_cumminmax_red_op (const octave_value& arg, int nargout, int dim,\n                     bool nanflag, bool ismin, bool direction)\n{\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n  ArrayType array = octave_value_extract<ArrayType> (arg);\n\n  if (nargout <= 1)\n    {\n      if (ismin)\n        {\n          if (direction)\n            retval(0) = array.flip (dim).cummin (dim, nanflag).flip (dim);\n          else\n            retval(0) = array.cummin (dim, nanflag);\n        }\n      else\n        {\n          if (direction)\n            retval(0) = array.flip (dim).cummax (dim, nanflag).flip (dim);\n          else\n            retval(0) = array.cummax (dim, nanflag);\n        }\n    }\n  else\n    {\n      retval.resize (2);\n      Array<octave_idx_type> idx;\n      if (ismin)\n        {\n          if (direction)\n            {\n              retval(0) = array.flip (dim).cummin (idx, dim, nanflag).flip (dim);\n              idx = reverse_index (idx, array.dims (), dim);\n            }\n          else\n            retval(0) = array.cummin (idx, dim, nanflag);\n        }\n      else\n        {\n          if (direction)\n            {\n              retval(0) = array.flip (dim).cummax (idx, dim, nanflag).flip (dim);\n              idx = reverse_index (idx, array.dims (), dim);\n            }\n          else\n            retval(0) = array.cummax (idx, dim, nanflag);\n        }\n\n      retval(1) = octave_value (idx, true, true);\n      if (direction)\n        retval(1) = retval(1).array_value ().flip (dim);\n    }\n\n  return retval;\n}\n\ntemplate <typename ArrayType>\nstatic octave_value_list\ndo_cumminmax_red_op (const octave_value& arg, int nargout, int dim,\n                     bool nanflag, bool realabs, bool ismin, bool direction)\n{\n  octave_value_list retval (nargout > 1 ? 2 : 1);\n  ArrayType array = octave_value_extract<ArrayType> (arg);\n\n  if (nargout <= 1)\n    {\n      if (ismin)\n        {\n          if (direction)\n            retval(0) = array.flip (dim).cummin (dim, nanflag, realabs).flip (dim);\n          else\n            retval(0) = array.cummin (dim, nanflag, realabs);\n        }\n      else\n        {\n          if (direction)\n            retval(0) = array.flip (dim).cummax (dim, nanflag, realabs).flip (dim);\n          else\n            retval(0) = array.cummax (dim, nanflag, realabs);\n        }\n    }\n  else\n    {\n      retval.resize (2);\n      Array<octave_idx_type> idx;\n      if (ismin)\n        {\n          if (direction)\n            {\n              retval(0) = array.flip (dim).cummin (idx, dim, nanflag, realabs).flip (dim);\n              idx = reverse_index (idx, array.dims (), dim);\n            }\n          else\n            retval(0) = array.cummin (idx, dim, nanflag, realabs);\n        }\n      else\n        {\n          if (direction)\n            {\n              retval(0) = array.flip (dim).cummax (idx, dim, nanflag, realabs).flip (dim);\n              idx = reverse_index (idx, array.dims (), dim);\n            }\n          else\n            retval(0) = array.cummax (idx, dim, nanflag, realabs);\n        }\n\n      retval(1) = octave_value (idx, true, true);\n      if (direction)\n        retval(1) = retval(1).array_value ().flip (dim);\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\ndo_cumminmax_body (const octave_value_list& args,\n                   int nargout, bool ismin)\n{\n  int nargin = args.length ();\n\n  const char *fcn = (ismin ? \"cummin\" : \"cummax\");\n\n  bool direction = false;\n  bool do_perm = false;\n  bool allflag = false;\n  bool nanflag = true; // NaNs are ignored by default\n  bool cmethod = true; // resolves to \"auto\"\n  bool realabs = true;\n  bool linear = false;\n\n  // Get \"ComparisonMethod\" optional argument first\n  if (nargin > 2\n      && args(nargin - 1).is_string () && args(nargin - 2).is_string ())\n    {\n      std::string name = args(nargin - 2).string_value ();\n      std::string sval = args(nargin - 1).string_value ();\n      if (name == \"ComparisonMethod\" || name == \"comparisonmethod\")\n        {\n          if (sval == \"auto\")\n            cmethod = true;\n          else if (sval == \"real\")\n            cmethod = false;\n          else if (sval == \"abs\")\n            {\n              cmethod = false;\n              realabs = false;\n            }\n          else\n            error (\"%s: invalid comparison method '%s'\", fcn, sval.c_str ());\n\n          nargin -= 2;\n        }\n    }\n\n  while (nargin > 1 && args(nargin - 1).is_string ())\n    {\n      std::string str = args(nargin - 1).string_value ();\n\n      if (str == \"forward\")\n        direction = false;\n      else if (str == \"reverse\")\n        direction = true;\n      else if (str == \"all\")\n        allflag = true;\n      else if (str == \"omitnan\" || str == \"omitmissing\")\n        {\n          if (args(0).is_double_type () || args(0).is_single_type ())\n            nanflag = true;\n        }\n      else if (str == \"includenan\" || str == \"includemissing\")\n        nanflag = false;\n      else if (str == \"linear\")\n        linear = true;\n      else\n        error (\"%s: unrecognized optional argument '%s'\", fcn, str.c_str ());\n\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  if (allflag && nargin > 1)\n    error (\"%s: cannot set DIM or VECDIM with 'all' flag\", fcn);\n\n  octave_value arg = args(0);\n  Array<int> vecdim;\n\n  // Handle DIM, VECDIM\n  int dim = -1;\n  Array<int> perm_vec;\n  if (nargin == 2)\n    {\n      octave_value dimarg = args(1);\n      get_dim_vecdim_all (dimarg, arg, dim, perm_vec, do_perm, allflag, fcn);\n      vecdim = dimarg.int_vector_value ();\n    }\n  else\n    {\n      dim_vector dims = arg.dims ();\n      vecdim.resize (dim_vector (1, 1));\n      vecdim(0) = dims.first_non_singleton () + 1;\n    }\n\n  // Handle allflag\n  if (allflag)\n    arg = arg.reshape (dim_vector (arg.numel (), 1));\n\n  octave_value_list retval;\n\n  switch (arg.builtin_type ())\n    {\n    case btyp_double:\n      {\n        if (cmethod)\n          retval = do_cumminmax_red_op<NDArray>\n                   (arg, nargout, dim, nanflag, ismin, direction);\n        else\n          retval = do_cumminmax_red_op<NDArray>\n                   (arg, nargout, dim, nanflag, realabs, ismin, direction);\n      }\n      break;\n\n    case btyp_complex:\n      {\n        if (cmethod)\n          retval = do_cumminmax_red_op<ComplexNDArray>\n                   (arg, nargout, dim, nanflag, ismin, direction);\n        else\n          retval = do_cumminmax_red_op<ComplexNDArray>\n                   (arg, nargout, dim, nanflag, realabs, ismin, direction);\n      }\n      break;\n\n    case btyp_float:\n      {\n        if (cmethod)\n          retval = do_cumminmax_red_op<FloatNDArray>\n                   (arg, nargout, dim, nanflag, ismin, direction);\n        else\n          retval = do_cumminmax_red_op<FloatNDArray>\n                   (arg, nargout, dim, nanflag, realabs, ismin, direction);\n      }\n      break;\n\n    case btyp_float_complex:\n      {\n        if (cmethod)\n          retval = do_cumminmax_red_op<FloatComplexNDArray>\n                   (arg, nargout, dim, nanflag, ismin, direction);\n        else\n          retval = do_cumminmax_red_op<FloatComplexNDArray>\n                   (arg, nargout, dim, nanflag, realabs, ismin, direction);\n      }\n      break;\n\n#define MAKE_INT_BRANCH(X)                                            \\\n    case btyp_ ## X:                                                  \\\n      {                                                               \\\n        if (cmethod)                                                  \\\n          retval = do_cumminmax_red_op<X ## NDArray> (arg, nargout,   \\\n                   dim, nanflag, ismin, direction);                   \\\n        else                                                          \\\n          retval = do_cumminmax_red_op<X ## NDArray> (arg, nargout,   \\\n                   dim, nanflag, realabs, ismin, direction);          \\\n      }                                                               \\\n      break;\n\n      MAKE_INT_BRANCH (int8);\n      MAKE_INT_BRANCH (int16);\n      MAKE_INT_BRANCH (int32);\n      MAKE_INT_BRANCH (int64);\n      MAKE_INT_BRANCH (uint8);\n      MAKE_INT_BRANCH (uint16);\n      MAKE_INT_BRANCH (uint32);\n      MAKE_INT_BRANCH (uint64);\n\n#undef MAKE_INT_BRANCH\n\n    case btyp_bool:\n      {\n        if (cmethod)\n          retval = do_cumminmax_red_op<int8NDArray>\n                   (arg, nargout, dim, nanflag, ismin, direction);\n        else\n          retval = do_cumminmax_red_op<int8NDArray>\n                   (arg, nargout, dim, nanflag, realabs, ismin, direction);\n        if (retval.length () > 0)\n          retval(0) = retval(0).bool_array_value ();\n      }\n      break;\n\n    default:\n      err_wrong_type_arg (fcn, arg);\n    }\n\n  if (do_perm)\n    {\n      retval(0) = retval(0).permute (perm_vec, true);\n      if (nargout > 1)\n        retval(1) = retval(1).permute (perm_vec, true);\n    }\n\n  // Process \"linear\" option\n  if (linear && nargout > 1 && ! allflag && ! args(0).isempty ())\n    retval(1) = get_linear_index (retval(1), args(0), vecdim, true);\n\n  return retval;\n}\n\nDEFUN (cummin, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{M} =} cummin (@var{x})\n@deftypefnx {} {@var{m} =} cummin (@var{x}, @var{dim})\n@deftypefnx {} {@var{m} =} cummin (@var{x}, @var{vecdim})\n@deftypefnx {} {@var{m} =} cummin (@var{x}, \"all\")\n@deftypefnx {} {@var{m} =} cummin (@dots{}, @var{direction})\n@deftypefnx {} {@var{m} =} cummin (@var{x}, @var{nanflag})\n@deftypefnx {} {[@var{m}, @var{im}] =} cummin (@dots{})\n@deftypefnx {} {[@var{m}, @var{im}] =} cummin (@dots{}, \"linear\")\n@deftypefnx {} {@dots{} =} cummin (@dots{}, \"ComparisonMethod\", @var{method})\nReturn the cumulative minimum values from the array @var{x}.\n\nIf @var{x} is a vector, then @code{cummin (@var{x})} returns a vector of the\nsame size with the cumulative minimum values of @var{x}.\n\nIf @var{x} is a matrix, then @code{cummin (@var{x})} returns a matrix of the\nsame size with the cumulative minimum values along each column of @var{x}.\n\nIf @var{x} is an array, then @code{cummin(@var{x})} returns an array of the\nsame size with the cumulative product along the first non-singleton dimension\nof @var{x}.\n\nThe class of output @var{y} is the same as the class of input @var{x}, unless\n@var{x} is logical, in which case @var{y} is double.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension in @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{cummin} to operate\non all elements of @var{x}, and is equivalent to @code{cummin (@var{x}(:))}.\n\nThe optional input @var{direction} specifies how the operating dimension is\ntraversed and can take the following values:\n\n@table @asis\n@item @qcode{\"forward\"} (default)\n\nThe cumulative minimum values are computed from beginning (index 1) to end\nalong the operating dimension.\n\n@item @qcode{\"reverse\"}\n\nThe cumulative minimum values are computed from end to beginning along the\noperating dimension.\n@end table\n\nThe optional variable @var{nanflag} specifies whether to include or exclude\n@code{NaN} values from the calculation using any of the previously specified\ninput argument combinations.  The default value for @var{nanflag} is\n@qcode{\"omitnan\"} which ignores @code{NaN} values in the calculation.  To\ninclude @code{NaN} values, set the value of @var{nanflag} to\n@qcode{\"includenan\"}, in which case @code{max} will return @code{NaN}, if any\nelement along the operating dimension is @code{NaN}.\n\nIf called with two output arguments, @code{cummin} also returns the first index\nof the minimum value(s) in @var{x}.  Setting the @qcode{\"linear\"} flag returns\nthe linear index to the corresponding minimum values in @var{x}.\n\nThe optional @qcode{\"ComparisonMethod\"} paired argument specifies the\ncomparison method for numeric input and it applies to both one input and two\ninput arrays.  @var{method} can take any of the following values:\n\n@table @asis\n@item @qcode{'auto'} (default)\nCompare elements by @code{real (@var{x})} when @var{x} is real, and by\n@code{abs (@var{x})} when @var{x} is complex.\n\n@item @qcode{'real'}\nCompare elements by @code{real (@var{x})} when @var{x} is real or complex.  For\nelements with equal real parts, a second comparison by @code{imag (@var{x})} is\nperformed.\n\n@item @qcode{'abs'}\nCompare elements by @code{abs (@var{x})} when @var{x} is real or complex.  For\nelements with equal magnitude, a second comparison by @code{angle (@var{x})} in\nthe interval from @math{-\\pi} to @math{\\pi} is performed.\n@end table\n@seealso{cummax, min, max}\n@end deftypefn */)\n{\n  return do_cumminmax_body (args, nargout, true);\n}\n\n/*\n%!assert (cummin ([1, 4, 2, 3]), [1 1 1 1])\n%!assert (cummin ([1; -10; 5; -2]), [1; -10; -10; -10])\n%!assert (cummin ([4, i; -2, 2]), [4, i; -2, i])\n%!assert (cummin ([1, 2; NaN, 1], 2), [1, 1; NaN, 1])\n\n%!test\n%! x = reshape (1:8, [2,2,2]);\n%! assert (cummin (x, 1), reshape ([1 1 3 3 5 5 7 7], [2,2,2]));\n%! assert (cummin (x, 2), reshape ([1 2 1 2 5 6 5 6], [2,2,2]));\n%! [w, iw] = cummin (x, 3);\n%! assert (ndims (w), 3);\n%! assert (w, repmat ([1 3; 2 4], [1 1 2]));\n%! assert (ndims (iw), 3);\n%! assert (iw, ones (2,2,2));\n\n## Test \"includenan\" and \"reverse\" options\n%!assert (cummin ([1; -10; NaN; -2], 'includenan'), [1; -10; NaN; NaN])\n%!assert (cummin ([1; -10; NaN; -2], 'reverse', 'includenan'), [NaN(3,1); -2])\n%!assert (cummin ([1, -10, NaN, -2], 'includenan'), [1, -10, NaN, NaN])\n%!assert (cummin ([1, -10, NaN, -2], 'reverse', 'includenan'), [NaN(1,3), -2])\n%!shared A, C\n%! A = [3, 5, NaN, 4, 2; 2, 6, 2, 9, 4; 1, 3, 0, NaN, 1; 5, 3, 4, 2, 0];\n%! C = [3+2i, 5i, NaN, 4+i, 2i; 2, 6i, 2, 9+2i, 4i; ...\n%!      1, 2+3i, 0, NaN, 1i; 5, 3i, 4, 2i, 0+i];\n%!test\n%! [m, i] = cummin (A, 'includenan');\n%! m_exp = [3, 5, NaN, 4, 2; 2, 5, NaN, 4, 2; ...\n%!          1, 3, NaN, NaN, 1; 1, 3, NaN, NaN, 0];\n%! i_exp = [1, 1, 1, 1, 1; 2, 1, 1, 1, 1; 3, 3, 1, 3, 3; 3, 3, 1, 3, 4];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummin (A, 'includenan', 'reverse');\n%! m_exp = [1, 3, NaN, NaN, 0; 1, 3, 0, NaN, 0; ...\n%!          1, 3, 0, NaN, 0; 5, 3, 4, 2, 0];\n%! i_exp = [3, 4, 1, 3, 4; 3, 4, 3, 3, 4; 3, 4, 3, 3, 4; 4, 4, 4, 4, 4];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummin (A, 'reverse');\n%! m_exp = [1, 3, 0, 2, 0; 1, 3, 0, 2, 0; 1, 3, 0, 2, 0; 5, 3, 4, 2, 0];\n%! i_exp = [3, 4, 3, 4, 4; 3, 4, 3, 4, 4; 3, 4, 3, 4, 4; 4, 4, 4, 4, 4];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummin (A);\n%! m_exp = [3, 5, NaN, 4, 2; 2, 5, 2, 4, 2; 1, 3, 0, 4, 1; 1, 3, 0, 2, 0];\n%! i_exp = [1, 1, 1, 1, 1; 2, 1, 2, 1, 1; 3, 3, 3, 1, 3; 3, 3, 3, 4, 4];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummin (A, 2, 'includenan');\n%! m_exp = [3, 3, NaN, NaN, NaN; 2, 2, 2, 2, 2; 1, 1, 0, NaN, NaN; 5, 3, 3, 2, 0];\n%! i_exp = [1, 1, 3, 3, 3; 1, 1, 1, 1, 1; 1, 1, 3, 4, 4; 1, 2, 2, 4, 5];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummin (A, 2, 'includenan', 'reverse');\n%! m_exp = [NaN, NaN, NaN, 2, 2; 2, 2, 2, 4, 4; ...\n%!          NaN, NaN, NaN, NaN, 1; 0, 0, 0, 0, 0];\n%! i_exp = [3, 3, 3, 5, 5; 3, 3, 3, 5, 5; 4, 4, 4, 4, 5; 5, 5, 5, 5, 5];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummin (A, 2, 'reverse');\n%! m_exp = [2, 2, 2, 2, 2; 2, 2, 2, 4, 4; 0, 0, 0, 1, 1; 0, 0, 0, 0, 0];\n%! i_exp = [5, 5, 5, 5, 5; 3, 3, 3, 5, 5; 3, 3, 3, 5, 5; 5, 5, 5, 5, 5];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummin (A, 2);\n%! m_exp = [3, 3, 3, 3, 2; 2, 2, 2, 2, 2; 1, 1, 0, 0, 0; 5, 3, 3, 2, 0];\n%! i_exp = [1, 1, 1, 1, 5; 1, 1, 1, 1, 1; 1, 1, 3, 3, 3; 1, 2, 2, 4, 5];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n\n## Test single output against linear option with previous examples\n%!test\n%! [~, i_lin] = cummin (A, 'includenan', 'linear');\n%! assert (cummin (A, 'includenan'), A(i_lin));\n%!test\n%! [~, i_lin] = cummin (A, 'includenan', 'reverse', 'linear');\n%! assert (cummin (A, 'includenan', 'reverse'), A(i_lin));\n%!test\n%! [~, i_lin] = cummin (A, 'reverse', 'linear');\n%! assert (cummin (A, 'reverse'), A(i_lin));\n%!test\n%! [~, i_lin] = cummin (A, 'linear');\n%! assert (cummin (A), A(i_lin));\n%!test\n%! [~, i_lin] = cummin (A, 2, 'includenan', 'linear');\n%! assert (cummin (A, 2, 'includenan'), A(i_lin));\n%!test\n%! [~, i_lin] = cummin (A, 2, 'includenan', 'reverse', 'linear');\n%! assert (cummin (A, 2, 'includenan', 'reverse'), A(i_lin));\n%!test\n%! [~, i_lin] = cummin (A, 2, 'reverse', 'linear');\n%! assert (cummin (A, 2, 'reverse'), A(i_lin));\n%!test\n%! [~, i_lin] = cummin (A, 2, 'linear');\n%! assert (cummin (A, 2), A(i_lin));\n\n## Test \"includenan\" and \"reverse\" options with complex input\n%!test\n%! [m, idx] = cummin (C, 'includenan');\n%! m_exp = [3+2i, 5i, NaN, 4+i, 2i; 2, 5i, NaN, 4+i, 2i; ...\n%!          1, 2+3i, NaN, NaN, 1i; 1, 3i, NaN, NaN, 1i];\n%! i_exp = [1, 1, 1, 1, 1; 2, 1, 1, 1, 1; 3, 3, 1, 3, 3; 3, 4, 1, 3, 3];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummin (C, 'includenan', 'reverse');\n%! m_exp = [1, 3i, NaN, NaN, 1i; 1, 3i, 0, NaN, 1i; ...\n%!          1, 3i, 0, NaN, 1i; 5, 3i, 4, 2i, 1i];\n%! i_exp = [3, 4, 1, 3, 4; 3, 4, 3, 3, 4; 3, 4, 3, 3, 4; 4, 4, 4, 4, 4];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummin (C, 'reverse');\n%! m_exp = [1, 3i, 0, 2i, 1i; 1, 3i, 0, 2i, 1i; ...\n%!          1, 3i, 0, 2i, 1i; 5, 3i, 4, 2i, 1i];\n%! i_exp = [3, 4, 3, 4, 4; 3, 4, 3, 4, 4; 3, 4, 3, 4, 4; 4, 4, 4, 4, 4];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummin (C);\n%! m_exp = [3+2i, 5i, NaN, 4+i, 2i; 2, 5i, 2, 4+i, 2i; ...\n%!          1, 2+3i, 0, 4+i, 1i; 1, 3i, 0, 2i, 1i];\n%! i_exp = [1, 1, 1, 1, 1; 2, 1, 2, 1, 1; 3, 3, 3, 1, 3; 3, 4, 3, 4, 3];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummin (C, 2, 'includenan');\n%! m_exp = [3+2i, 3+2i, NaN, NaN, NaN; 2, 2, 2, 2, 2; ...\n%!          1, 1, 0, NaN, NaN; 5, 3i, 3i, 2i, 1i];\n%! i_exp = [1, 1, 3, 3, 3; 1, 1, 1, 1, 1; 1, 1, 3, 4, 4; 1, 2, 2, 4, 5];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummin (C, 2, 'includenan', 'reverse');\n%! m_exp = [NaN, NaN, NaN, 2i, 2i; 2, 2, 2, 4i, 4i; ...\n%!          NaN, NaN, NaN, NaN, 1i; 1i, 1i, 1i, 1i, 1i];\n%! i_exp = [3, 3, 3, 5, 5; 3, 3, 3, 5, 5; 4, 4, 4, 4, 5; 5, 5, 5, 5, 5];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummin (C, 2, 'reverse');\n%! m_exp = [2i, 2i, 2i, 2i, 2i; 2, 2, 2, 4i, 4i; ...\n%!          0, 0, 0, 1i, 1i; 1i, 1i, 1i, 1i, 1i];\n%! i_exp = [5, 5, 5, 5, 5; 3, 3, 3, 5, 5; 3, 3, 3, 5, 5; 5, 5, 5, 5, 5];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummin (C, 2);\n%! m_exp = [3+2i, 3+2i, 3+2i, 3+2i, 2i; 2, 2, 2, 2, 2; ...\n%!          1, 1, 0, 0, 0; 5, 3i, 3i, 2i, 1i];\n%! i_exp = [1, 1, 1, 1, 5; 1, 1, 1, 1, 1; 1, 1, 3, 3, 3; 1, 2, 2, 4, 5];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n\n## Test 'ComparisonMethod' with complex input\n%!test\n%! [m, idx] = cummin (C, 2, 'ComparisonMethod', 'real');\n%! m_exp = [3+2i, 5i, 5i, 5i, 2i; 2, 6i, 6i, 6i, 4i; ...\n%!          1, 1, 0, 0, 0; 5, 3i, 3i, 2i, 1i];\n%! i_exp = [1, 2, 2, 2, 5; 1, 2, 2, 2, 5; 1, 1, 3, 3, 3; 1, 2, 2, 4, 5];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummin (C, 'includenan', 'ComparisonMethod', 'real');\n%! m_exp = [3+2i, 5i, NaN, 4+i, 2i; 2, 5i, NaN, 4+i, 2i; ...\n%!          1, 5i, NaN, NaN, 1i; 1, 3i, NaN, NaN, 1i];\n%! i_exp = [1, 1, 1, 1, 1; 2, 1, 1, 1, 1; 3, 1, 1, 3, 3; 3, 4, 1, 3, 3];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n\n## Test \"linear\" option with N-D array\n%!shared x\n%! x = randi ([-10, 10], 3, 4, 5, 2);\n%!test\n%! [m, i] = cummin (x, [2, 3], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummin (x, [1, 3], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummin (x, [2, 4], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummin (x, [1, 4], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummin (x, [1, 2, 3], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummin (x, [2, 3, 4], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummin ([1, 2, 3; 4, 5, 6], 1, 'linear');\n%! assert (m, [1, 2, 3; 1, 2, 3]);\n%! assert (i, [1, 3, 5; 1, 3, 5]);\n%!test\n%! [m, i] = cummin ([1, 2, 3; 4, 5, 6], 2, 'linear');\n%! assert (m, [1, 1, 1; 4, 4, 4]);\n%! assert (i, [1, 1, 1; 2, 2, 2]);\n%!test\n%! [m, i] = cummin ([1, 2, 3; 4, 5, 6], 1, 'linear', 'reverse');\n%! assert (m, [1, 2, 3; 4, 5, 6]);\n%! assert (i, [1, 3, 5; 2, 4, 6]);\n%!test\n%! [m, i] = cummin ([1, 2, 3; 4, 5, 6], 2, 'linear', 'reverse');\n%! assert (m, [1, 2, 3; 4, 5, 6]);\n%! assert (i, [1, 3, 5; 2, 4, 6]);\n\n%!error <Invalid call> cummin ()\n%!error <Invalid call> cummin (1, 2, 3)\n%!error <unrecognized optional argument 'foobar'> cummin (1, \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! cummin (ones (3,3), 1, \"all\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! cummin (ones (3,3), [1, 2], \"all\")\n%!error <invalid dimension DIM = 0> cummin (ones (3,3), 0)\n%!error <invalid dimension DIM = -1> cummin (ones (3,3), -1)\n%!error <invalid dimension in VECDIM = -2> cummin (ones (3,3), [1 -2])\n%!error <duplicate dimension in VECDIM = 2> cummin (ones (3,3), [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> cummin (ones (3,3), [1 1 2])\n%!error <wrong type argument 'cell'> cummin ({1 2 3 4})\n*/\n\nDEFUN (cummax, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{M} =} cummax (@var{x})\n@deftypefnx {} {@var{m} =} cummax (@var{x}, @var{dim})\n@deftypefnx {} {@var{m} =} cummax (@var{x}, @var{vecdim})\n@deftypefnx {} {@var{m} =} cummax (@var{x}, \"all\")\n@deftypefnx {} {@var{m} =} cummax (@dots{}, @var{direction})\n@deftypefnx {} {@var{m} =} cummax (@var{x}, @var{nanflag})\n@deftypefnx {} {[@var{m}, @var{im}] =} cummax (@dots{})\n@deftypefnx {} {[@var{m}, @var{im}] =} cummax (@dots{}, \"linear\")\n@deftypefnx {} {@dots{} =} cummax (@dots{}, \"ComparisonMethod\", @var{method})\nReturn the cumulative maximum values from the array @var{x}.\n\nIf @var{x} is a vector, then @code{cummax (@var{x})} returns a vector of the\nsame size with the cumulative maximum values of @var{x}.\n\nIf @var{x} is a matrix, then @code{cummax (@var{x})} returns a matrix of the\nsame size with the cumulative maximum values along each column of @var{x}.\n\nIf @var{x} is an array, then @code{cummax(@var{x})} returns an array of the\nsame size with the cumulative product along the first non-singleton dimension\nof @var{x}.\n\nThe class of output @var{y} is the same as the class of input @var{x}, unless\n@var{x} is logical, in which case @var{y} is double.\n\nThe optional input @var{dim} specifies the dimension to operate on and must be\na positive integer.  Specifying any singleton dimension in @var{x}, including\nany dimension exceeding @code{ndims (@var{x})}, will return @var{x}.\n\nSpecifying multiple dimensions with input @var{vecdim}, a vector of\nnon-repeating dimensions, will operate along the array slice defined by\n@var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\nequivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim} greater\nthan @code{ndims (@var{x})} is ignored.\n\nSpecifying the dimension as @qcode{\"all\"} will cause @code{cummax} to operate\non all elements of @var{x}, and is equivalent to @code{cummax (@var{x}(:))}.\n\nThe optional input @var{direction} specifies how the operating dimension is\ntraversed and can take the following values:\n\n@table @asis\n@item @qcode{\"forward\"} (default)\n\nThe cumulative maximum values are computed from beginning (index 1) to end\nalong the operating dimension.\n\n@item @qcode{\"reverse\"}\n\nThe cumulative maximum values are computed from end to beginning along the\noperating dimension.\n@end table\n\nThe optional variable @var{nanflag} specifies whether to include or exclude\n@code{NaN} values from the calculation using any of the previously specified\ninput argument combinations.  The default value for @var{nanflag} is\n@qcode{\"omitnan\"} which ignores @code{NaN} values in the calculation.  To\ninclude @code{NaN} values, set the value of @var{nanflag} to\n@qcode{\"includenan\"}, in which case @code{max} will return @code{NaN}, if any\nelement along the operating dimension is @code{NaN}.\n\nIf called with two output arguments, @code{cummax} also returns the first index\nof the maximum value(s) in @var{x}.  Setting the @qcode{\"linear\"} flag returns\nthe linear index to the corresponding minimum values in @var{x}.\n\nThe optional @qcode{\"ComparisonMethod\"} paired argument specifies the\ncomparison method for numeric input and it applies to both one input and two\ninput arrays.  @var{method} can take any of the following values:\n\n@table @asis\n@item @qcode{'auto'} (default)\nCompare elements by @code{real (@var{x})} when @var{x} is real, and by\n@code{abs (@var{x})} when @var{x} is complex.\n\n@item @qcode{'real'}\nCompare elements by @code{real (@var{x})} when @var{x} is real or complex.  For\nelements with equal real parts, a second comparison by @code{imag (@var{x})} is\nperformed.\n\n@item @qcode{'abs'}\nCompare elements by @code{abs (@var{x})} when @var{x} is real or complex.  For\nelements with equal magnitude, a second comparison by @code{angle (@var{x})}\nin the interval from @math{-\\pi} to @math{\\pi} is performed.\n@end table\n@seealso{cummin, max, min}\n@end deftypefn */)\n{\n  return do_cumminmax_body (args, nargout, false);\n}\n\n/*\n%!assert (cummax ([1, 4, 2, 3]), [1, 4, 4, 4])\n%!assert (cummax ([1; -10; 5; -2]), [1; 1; 5; 5])\n%!assert (cummax ([4, i, 4.9, -2, 2, 3+4i]), [4, 4, 4.9, 4.9, 4.9, 3+4i])\n%!assert (cummax ([1, NaN, 0; NaN, NaN, 1], 2), [1, 1, 1; NaN, NaN, 1])\n\n%!test\n%! x = reshape (8:-1:1, [2,2,2]);\n%! assert (cummax (x, 1), reshape ([8 8 6 6 4 4 2 2], [2,2,2]));\n%! assert (cummax (x, 2), reshape ([8 7 8 7 4 3 4 3], [2,2,2]));\n%! [w, iw] = cummax (x, 3);\n%! assert (ndims (w), 3);\n%! assert (w, repmat ([8 6; 7 5], [1 1 2]));\n%! assert (ndims (iw), 3);\n%! assert (iw, ones (2,2,2));\n\n## Test \"includenan\" and \"reverse\" options\n%!assert (cummax ([1; -10; NaN; -2], 'includenan'), [1; 1; NaN; NaN])\n%!assert (cummax ([1; -10; NaN; -2], 'reverse', 'includenan'), [NaN(3,1); -2])\n%!assert (cummax ([1, -10, NaN, -2], 'includenan'), [1, 1, NaN, NaN])\n%!assert (cummax ([1, -10, NaN, -2], 'reverse', 'includenan'), [NaN(1,3), -2])\n%!shared A, C\n%! A = [3, 5, NaN, 4, 2; 2, 6, 2, 9, 4; 1, 3, 0, NaN, 1; 5, 3, 4, 2, 0];\n%! C = [3+2i, 5i, NaN, 4+i, 2i; 2, 6i, 2, 9+2i, 4i; ...\n%!      1, 2+3i, 0, NaN, 1i; 5, 3i, 4, 2i, 0+i];\n%!test\n%! [m, i] = cummax (A, 'includenan');\n%! m_exp = [3, 5, NaN, 4, 2; 3, 6, NaN, 9, 4; ...\n%!          3, 6, NaN, NaN, 4; 5, 6, NaN, NaN, 4];\n%! i_exp = [1, 1, 1, 1, 1; 1, 2, 1, 2, 2; 1, 2, 1, 3, 2; 4, 2, 1, 3, 2];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummax (A, 'includenan', 'reverse');\n%! m_exp = [5, 6, NaN, NaN, 4; 5, 6, 4, NaN, 4; ...\n%!          5, 3, 4, NaN, 1; 5, 3, 4, 2, 0];\n%! i_exp = [4, 2, 1, 3, 2; 4, 2, 4, 3, 2; 4, 4, 4, 3, 3; 4, 4, 4, 4, 4];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummax (A, 'reverse');\n%! m_exp = [5, 6, 4, 9, 4; 5, 6, 4, 9, 4; 5, 3, 4, 2, 1; 5, 3, 4, 2, 0];\n%! i_exp = [4, 2, 4, 2, 2; 4, 2, 4, 2, 2; 4, 4, 4, 4, 3; 4, 4, 4, 4, 4];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummax (A);\n%! m_exp = [3, 5, NaN, 4, 2; 3, 6, 2, 9, 4; 3, 6, 2, 9, 4; 5, 6, 4, 9, 4];\n%! i_exp = [1, 1, 1, 1, 1; 1, 2, 2, 2, 2; 1, 2, 2, 2, 2; 4, 2, 4, 2, 2];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummax (A, 2, 'includenan');\n%! m_exp = [3, 5, NaN, NaN, NaN; 2, 6, 6, 9, 9; 1, 3, 3, NaN, NaN; 5, 5, 5, 5, 5];\n%! i_exp = [1, 2, 3, 3, 3; 1, 2, 2, 4, 4; 1, 2, 2, 4, 4; 1, 1, 1, 1, 1];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummax (A, 2, 'includenan', 'reverse');\n%! m_exp = [NaN, NaN, NaN, 4, 2; 9, 9, 9, 9, 4; ...\n%!          NaN, NaN, NaN, NaN, 1; 5, 4, 4, 2, 0];\n%! i_exp = [3, 3, 3, 4, 5; 4, 4, 4, 4, 5; 4, 4, 4, 4, 5; 1, 3, 3, 4, 5];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummax (A, 2, 'reverse');\n%! m_exp = [5, 5, 4, 4, 2; 9, 9, 9, 9, 4; 3, 3, 1, 1, 1; 5, 4, 4, 2, 0];\n%! i_exp = [2, 2, 4, 4, 5; 4, 4, 4, 4, 5; 2, 2, 5, 5, 5; 1, 3, 3, 4, 5];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n%!test\n%! [m, i] = cummax (A, 2);\n%! m_exp = [3, 5, 5, 5, 5; 2, 6, 6, 9, 9; 1, 3, 3, 3, 3; 5, 5, 5, 5, 5];\n%! i_exp = [1, 2, 2, 2, 2; 1, 2, 2, 4, 4; 1, 2, 2, 2, 2; 1, 1, 1, 1, 1];\n%! assert (m, m_exp);\n%! assert (i, i_exp);\n\n## Test single output against linear option with previous examples\n%!test\n%! [~, i_lin] = cummax (A, 'includenan', 'linear');\n%! assert (cummax (A, 'includenan'), A(i_lin));\n%!test\n%! [~, i_lin] = cummax (A, 'includenan', 'reverse', 'linear');\n%! assert (cummax (A, 'includenan', 'reverse'), A(i_lin));\n%!test\n%! [~, i_lin] = cummax (A, 'reverse', 'linear');\n%! assert (cummax (A, 'reverse'), A(i_lin));\n%!test\n%! [~, i_lin] = cummax (A, 'linear');\n%! assert (cummax (A), A(i_lin));\n%!test\n%! [~, i_lin] = cummax (A, 2, 'includenan', 'linear');\n%! assert (cummax (A, 2, 'includenan'), A(i_lin));\n%!test\n%! [~, i_lin] = cummax (A, 2, 'includenan', 'reverse', 'linear');\n%! assert (cummax (A, 2, 'includenan', 'reverse'), A(i_lin));\n%!test\n%! [~, i_lin] = cummax (A, 2, 'reverse', 'linear');\n%! assert (cummax (A, 2, 'reverse'), A(i_lin));\n%!test\n%! [~, i_lin] = cummax (A, 2, 'linear');\n%! assert (cummax (A, 2), A(i_lin));\n\n## Test \"includenan\" and \"reverse\" options with complex input\n%!test\n%! [m, idx] = cummax (C, 'includenan');\n%! m_exp = [3+2i, 5i, NaN, 4+i, 2i; 3+2i, 6i, NaN, 9+2i, 4i; ...\n%!          3+2i, 6i, NaN, NaN, 4i; 5, 6i, NaN, NaN, 4i];\n%! i_exp = [1, 1, 1, 1, 1; 1, 2, 1, 2, 2; 1, 2, 1, 3, 2; 4, 2, 1, 3, 2];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummax (C, 'includenan', 'reverse');\n%! m_exp = [5, 6i, NaN, NaN, 4i; 5, 6i, 4, NaN, 4i; ...\n%!          5, 2+3i, 4, NaN, 1i; 5, 3i, 4, 2i, 1i];\n%! i_exp = [4, 2, 1, 3, 2; 4, 2, 4, 3, 2; 4, 3, 4, 3, 4; 4, 4, 4, 4, 4];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummax (C, 'reverse');\n%! m_exp = [5, 6i, 4, 9+2i, 4i; 5, 6i, 4, 9+2i, 4i; ...\n%!          5, 2+3i, 4, 2i, 1i; 5, 3i, 4, 2i, 1i];\n%! i_exp = [4, 2, 4, 2, 2; 4, 2, 4, 2, 2; 4, 3, 4, 4, 4; 4, 4, 4, 4, 4];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummax (C);\n%! m_exp = [3+2i, 5i, NaN, 4+i, 2i; 3+2i, 6i, 2, 9+2i, 4i; ...\n%!          3+2i, 6i, 2, 9+2i, 4i; 5, 6i, 4, 9+2i, 4i];\n%! i_exp = [1, 1, 1, 1, 1; 1, 2, 2, 2, 2; 1, 2, 2, 2, 2; 4, 2, 4, 2, 2];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummax (C, 2, 'includenan');\n%! m_exp = [3+2i, 5i, NaN, NaN, NaN; 2, 6i, 6i, 9+2i, 9+2i; ...\n%!          1, 2+3i, 2+3i, NaN, NaN; 5, 5, 5, 5, 5];\n%! i_exp = [1, 2, 3, 3, 3; 1, 2, 2, 4, 4; 1, 2, 2, 4, 4; 1, 1, 1, 1, 1];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummax (C, 2, 'includenan', 'reverse');\n%! m_exp = [NaN, NaN, NaN, 4+i, 2i; 9+2i, 9+2i, 9+2i, 9+2i, 4i; ...\n%!          NaN, NaN, NaN, NaN, 1i; 5, 4, 4, 2i, 1i];\n%! i_exp = [3, 3, 3, 4, 5; 4, 4, 4, 4, 5; 4, 4, 4, 4, 5; 1, 3, 3, 4, 5];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummax (C, 2, 'reverse');\n%! m_exp = [5i, 5i, 4+i, 4+i, 2i; 9+2i, 9+2i, 9+2i, 9+2i, 4i; ...\n%!          2+3i, 2+3i, 1i, 1i, 1i; 5, 4, 4, 2i, 1i];\n%! i_exp = [2, 2, 4, 4, 5; 4, 4, 4, 4, 5; 2, 2, 5, 5, 5; 1, 3, 3, 4, 5];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummax (C, 2);\n%! m_exp = [3+2i, 5i, 5i, 5i, 5i; 2, 6i, 6i, 9+2i, 9+2i; ...\n%!          1, 2+3i, 2+3i, 2+3i, 2+3i; 5, 5, 5, 5, 5];\n%! i_exp = [1, 2, 2, 2, 2; 1, 2, 2, 4, 4; 1, 2, 2, 2, 2; 1, 1, 1, 1, 1];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n\n## Test 'ComparisonMethod' with complex input\n%!test\n%! [m, idx] = cummax (C, 2, 'ComparisonMethod', 'real');\n%! m_exp = [3+2i, 3+2i, 3+2i, 4+i, 4+i; 2, 2, 2, 9+2i, 9+2i; ...\n%!          1, 2+3i, 2+3i, 2+3i, 2+3i; 5, 5, 5, 5, 5];\n%! i_exp = [1, 1, 1, 4, 4; 1, 1, 1, 4, 4; 1, 2, 2, 2, 2; 1, 1, 1, 1, 1];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n%!test\n%! [m, idx] = cummax (C, 'includenan', 'reverse', 'ComparisonMethod', 'real');\n%! m_exp = [5, 2+3i, NaN, NaN, 4i; 5, 2+3i, 4, NaN, 4i; ...\n%!          5, 2+3i, 4, NaN, 1i; 5, 3i, 4, 2i, 1i];\n%! i_exp = [4, 3, 1, 3, 2; 4, 3, 4, 3, 2; 4, 3, 4, 3, 4; 4, 4, 4, 4, 4];\n%! assert (m, m_exp);\n%! assert (idx, i_exp);\n\n## Test \"linear\" option with N-D array\n%!shared x\n%! x = randi ([-10, 10], 3, 4, 5, 2);\n%!test\n%! [m, i] = cummax (x, [2, 3], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummax (x, [1, 3], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummax (x, [2, 4], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummax (x, [1, 4], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummax (x, [1, 2, 3], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummax (x, [2, 3, 4], 'linear');\n%! assert (m, x(i));\n%!test\n%! [m, i] = cummax ([1, 2, 3; 4, 5, 6], 1, 'linear');\n%! assert (m, [1, 2, 3; 4, 5, 6]);\n%! assert (i, [1, 3, 5; 2, 4, 6]);\n%!test\n%! [m, i] = cummax ([1, 2, 3; 4, 5, 6], 2, 'linear');\n%! assert (m, [1, 2, 3; 4, 5, 6]);\n%! assert (i, [1, 3, 5; 2, 4, 6]);\n%!test\n%! [m, i] = cummax ([1, 2, 3; 4, 5, 6], 1, 'linear', 'reverse');\n%! assert (m, [4, 5, 6; 4, 5, 6]);\n%! assert (i, [2, 4, 6; 2, 4, 6]);\n%!test\n%! [m, i] = cummax ([1, 2, 3; 4, 5, 6], 2, 'linear', 'reverse');\n%! assert (m, [3, 3, 3; 6, 6, 6]);\n%! assert (i, [5, 5, 5; 6, 6, 6]);\n\n%!error <Invalid call> cummax ()\n%!error <Invalid call> cummax (1, 2, 3)\n%!error <unrecognized optional argument 'foobar'> cummax (1, \"foobar\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! cummax (ones (3,3), 1, \"all\")\n%!error <cannot set DIM or VECDIM with 'all' flag>\n%! cummax (ones (3,3), [1, 2], \"all\")\n%!error <invalid dimension DIM = 0> cummax (ones (3,3), 0)\n%!error <invalid dimension DIM = -1> cummax (ones (3,3), -1)\n%!error <invalid dimension in VECDIM = -2> cummax (ones (3,3), [1 -2])\n%!error <duplicate dimension in VECDIM = 2> cummax (ones (3,3), [1 2 2])\n%!error <duplicate dimension in VECDIM = 1> cummax (ones (3,3), [1 1 2])\n%!error <wrong type argument 'cell'> cummax ({1 2 3 4})\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/mgorth.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-norm.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename ColumnVector, typename Matrix, typename RowVector>\nstatic void\ndo_mgorth (ColumnVector& x, const Matrix& V, RowVector& h)\n{\n  octave_idx_type Vc = V.columns ();\n  h = RowVector (Vc + 1);\n  for (octave_idx_type j = 0; j < Vc; j++)\n    {\n      ColumnVector Vcj = V.column (j);\n      RowVector Vcjh = Vcj.hermitian ();\n      h(j) = Vcjh * x;\n      x -= h(j) * Vcj;\n    }\n\n  h(Vc) = xnorm (x);\n  if (std::real (h(Vc)) > 0)\n    x /= h(Vc);\n}\n\nDEFUN (mgorth, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{y}, @var{h}] =} mgorth (@var{x}, @var{v})\nOrthogonalize a given column vector @var{x} with respect to a set of\northonormal vectors comprising the columns of @var{v} using the modified\nGram-Schmidt method.\n\nOn exit, @var{y} is a unit vector such that:\n\n@example\n@group\n  norm (@var{y}) = 1\n  @var{v}' * @var{y} = 0\n  @var{x} = [@var{v}, @var{y}]*@var{h}'\n@end group\n@end example\n\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value arg_x = args(0);\n  octave_value arg_v = args(1);\n\n  if (arg_v.ndims () != 2 || arg_x.ndims () != 2 || arg_x.columns () != 1\n      || arg_v.rows () != arg_x.rows ())\n    error (\"mgorth: V should be a matrix, and X a column vector with\"\n           \" the same number of rows as V.\");\n\n  if (! arg_x.isnumeric () && ! arg_v.isnumeric ())\n    error (\"mgorth: X and V must be numeric\");\n\n  octave_value_list retval;\n\n  bool iscomplex = (arg_x.iscomplex () || arg_v.iscomplex ());\n  if (arg_x.is_single_type () || arg_v.is_single_type ())\n    {\n      if (iscomplex)\n        {\n          FloatComplexColumnVector x\n            = arg_x.float_complex_column_vector_value ();\n          FloatComplexMatrix V = arg_v.float_complex_matrix_value ();\n          FloatComplexRowVector h;\n          do_mgorth (x, V, h);\n          retval = ovl (x, h);\n        }\n      else\n        {\n          FloatColumnVector x = arg_x.float_column_vector_value ();\n          FloatMatrix V = arg_v.float_matrix_value ();\n          FloatRowVector h;\n          do_mgorth (x, V, h);\n          retval = ovl (x, h);\n        }\n    }\n  else\n    {\n      if (iscomplex)\n        {\n          ComplexColumnVector x = arg_x.complex_column_vector_value ();\n          ComplexMatrix V = arg_v.complex_matrix_value ();\n          ComplexRowVector h;\n          do_mgorth (x, V, h);\n          retval = ovl (x, h);\n        }\n      else\n        {\n          ColumnVector x = arg_x.column_vector_value ();\n          Matrix V = arg_v.matrix_value ();\n          RowVector h;\n          do_mgorth (x, V, h);\n          retval = ovl (x, h);\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! for ii=1:100\n%!   assert (abs (mgorth (randn (5, 1), eye (5, 4))), [0 0 0 0 1]', eps);\n%! endfor\n\n%!test\n%! a = hilb (5);\n%! a(:, 1) /= norm (a(:, 1));\n%! for ii = 1:5\n%!   a(:, ii) = mgorth (a(:, ii), a(:, 1:ii-1));\n%! endfor\n%! assert (a' * a, eye (5), 1e10);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/module.mk",
    "content": "## Options functions for Fortran packages like LSODE, DASPK.\n## These are generated automagically by configure and Perl.\nOPT_HANDLERS = \\\n  %reldir%/DASPK-opts.cc \\\n  %reldir%/DASRT-opts.cc \\\n  %reldir%/DASSL-opts.cc \\\n  %reldir%/LSODE-opts.cc \\\n  %reldir%/Quad-opts.cc\n\n$(OPT_HANDLERS): %reldir%/%.cc : liboctave/numeric/%.in | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(PERL) $(srcdir)/build-aux/mk-opts.pl --opt-handler-fcns $< > $@-t && \\\n\tmv $@-t $@\n\n$(OPT_HANDLERS): $(srcdir)/build-aux/mk-opts.pl\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nCOREFCN_NUMERIC_SRC = \\\n  %reldir%/__betainc__.cc \\\n  %reldir%/__contourc__.cc \\\n  %reldir%/__dsearchn__.cc \\\n  %reldir%/__eigs__.cc \\\n  %reldir%/__expint__.cc \\\n  %reldir%/__gammainc__.cc \\\n  %reldir%/__ichol__.cc \\\n  %reldir%/__ilu__.cc \\\n  %reldir%/__isprimelarge__.cc \\\n  %reldir%/__lin_interpn__.cc \\\n  %reldir%/__pchip_deriv__.cc \\\n  %reldir%/__qp__.cc \\\n  %reldir%/amd.cc \\\n  %reldir%/balance.cc \\\n  %reldir%/besselj.cc \\\n  %reldir%/bitfcns.cc \\\n  %reldir%/ccolamd.cc \\\n  %reldir%/chol.cc \\\n  %reldir%/colamd.cc \\\n  %reldir%/colloc.cc \\\n  %reldir%/conv2.cc \\\n  %reldir%/daspk.cc \\\n  %reldir%/dasrt.cc \\\n  %reldir%/dassl.cc \\\n  %reldir%/det.cc \\\n  %reldir%/dmperm.cc \\\n  %reldir%/dot.cc \\\n  %reldir%/eig.cc \\\n  %reldir%/ellipj.cc \\\n  %reldir%/fft.cc \\\n  %reldir%/fft2.cc \\\n  %reldir%/fftn.cc \\\n  %reldir%/filter.cc \\\n  %reldir%/gcd.cc \\\n  %reldir%/givens.cc \\\n  %reldir%/gsvd.cc \\\n  %reldir%/hash.cc \\\n  %reldir%/hess.cc \\\n  %reldir%/hex2num.cc \\\n  %reldir%/inv.cc \\\n  %reldir%/kron.cc \\\n  %reldir%/lsode.cc \\\n  %reldir%/lu.cc \\\n  %reldir%/mappers.cc \\\n  %reldir%/max.cc \\\n  %reldir%/mgorth.cc \\\n  %reldir%/ordqz.cc \\\n  %reldir%/ordschur.cc \\\n  %reldir%/perms.cc \\\n  %reldir%/pinv.cc \\\n  %reldir%/pow2.cc \\\n  %reldir%/psi.cc \\\n  %reldir%/qr.cc \\\n  %reldir%/quad.cc \\\n  %reldir%/quadcc.cc \\\n  %reldir%/qz.cc \\\n  %reldir%/rand.cc \\\n  %reldir%/rcond.cc \\\n  %reldir%/schur.cc \\\n  %reldir%/sparse.cc \\\n  %reldir%/spparms.cc \\\n  %reldir%/sqrtm.cc \\\n  %reldir%/stream-euler.cc \\\n  %reldir%/svd.cc \\\n  %reldir%/sylvester.cc \\\n  %reldir%/symbfact.cc \\\n  %reldir%/symrcm.cc \\\n  %reldir%/trexc.cc \\\n  %reldir%/tsearch.cc\n\nnoinst_LTLIBRARIES += \\\n  %reldir%/libnumeric.la\n\n%canon_reldir%_libnumeric_la_SOURCES = $(COREFCN_NUMERIC_SRC)\n\n%canon_reldir%_libnumeric_la_CPPFLAGS = \\\n  $(libinterp_liboctinterp_la_CPPFLAGS) \\\n  -I%reldir% -I$(srcdir)/%reldir% \\\n  $(FFTW_XCPPFLAGS) \\\n  $(SPARSE_XCPPFLAGS)\n\nlibinterp_liboctinterp_la_LIBADD += %reldir%/libnumeric.la\n"
  },
  {
    "path": "libinterp/corefcn/numeric/ordqz.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Generalized eigenvalue reordering via LAPACK\n\n// Originally written by M. Koehler <koehlerm(AT)mpi-magdeburg.mpg.de>\n\n#undef OCTAVE_ORDQZ_DEBUG\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cctype>\n#include <cmath>\n\n#include \"f77-fcn.h\"\n#include \"lapack-proto.h\"\n#include \"qr.h\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\n#if defined (OCTAVE_ORDQZ_DEBUG)\n#  include \"pager.h\"\n#  include \"pr-output.h\"\n#endif\n\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (ordqz, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{AR}, @var{BR}, @var{QR}, @var{ZR}] =} ordqz (@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{keyword})\n@deftypefnx {} {[@var{AR}, @var{BR}, @var{QR}, @var{ZR}] =} ordqz (@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{select})\nReorder the QZ@tie{}decomposition of a generalized eigenvalue problem.\n\nThe generalized eigenvalue problem is defined as\n@tex\n$$A x = \\lambda B x$$\n@end tex\n@ifnottex\n\n@math{A x = @var{lambda} B x}\n\n@end ifnottex\n\nIts generalized Schur decomposition is computed using the @code{qz} algorithm:\n\n@code{[@var{AA}, @var{BB}, @var{Q}, @var{Z}] = qz (@var{A}, @var{B})}\n\nwhere @var{AA}, @var{BB}, @var{Q}, and @var{Z} fulfill\n@tex\n$$ AA = Q \\cdot A \\cdot Z, BB = Q \\cdot B \\cdot Z $$\n@end tex\n@ifnottex\n\n@example\n@group\n\n@var{AA} = @var{Q} * @var{A} * @var{Z}, @var{BB} = @var{Q} * @var{B} * @var{Z}\n\n@end group\n@end example\n\n@end ifnottex\n\nThe @code{ordqz} function computes a unitary transformation @var{QR} and\n@var{ZR} such that the order of the eigenvalue on the diagonal of @var{AA} and\n@var{BB} is changed.  The resulting reordered matrices @var{AR} and @var{BR}\nfulfill:\n@tex\n$$ A_R = Q_R \\cdot A \\cdot Z_R, B_R = Q_R \\cdot B \\cdot Z_R $$\n@end tex\n@ifnottex\n\n@example\n@group\n\n@var{AR} = @var{QR} * @var{A} * @var{ZR}, @var{BR} = @var{QR} * @var{B} * @var{ZR}\n\n@end group\n@end example\n\n@end ifnottex\n\nThe function can either be called with the @var{keyword} argument which\nselects the eigenvalues in the top left block of @var{AR} and @var{BR} in the\nfollowing way:\n\n@table @asis\n@item @qcode{\"S\"}, @nospell{@qcode{\"udi\"}}\nsmall: leading block has all\n@tex\n$|\\lambda| < 1$\n@end tex\n@ifnottex\n|@var{lambda}| < 1\n@end ifnottex\n\n@item @qcode{\"B\"}, @nospell{@qcode{\"udo\"}}\nbig: leading block has all\n@tex\n$|\\lambda| \\geq 1$\n@end tex\n@ifnottex\n|@var{lambda}| @geq{} 1\n@end ifnottex\n\n@item @qcode{\"-\"}, @nospell{@qcode{\"lhp\"}}\nnegative real part: leading block has all eigenvalues in the open left\nhalf-plane\n\n@item @qcode{\"+\"}, @nospell{@qcode{\"rhp\"}}\nnon-negative real part: leading block has all eigenvalues in the closed right\nhalf-plane\n@end table\n\nIf a logical vector @var{select} is given instead of a keyword the @code{ordqz}\nfunction reorders all eigenvalues @code{k} to the left block for which\n@code{select(k)} is true.\n\nNote: The keywords are compatible with the ones from @code{qr}.\n\n@seealso{eig, ordeig, qz, schur, ordschur}\n@end deftypefn */)\n{\n  enum { LHP, RHP, UDI, UDO, VEC, NONE } select_mode = NONE;\n\n  if (args.length () != 5)\n    print_usage ();\n\n  // Check select argument\n  if (args(4).is_string())\n    {\n      std::string opts = args(4).string_value ();\n      std::for_each (opts.begin (), opts.end (),\n      [] (char& c) { c = std::tolower (c); });\n      if (opts == \"lhp\" || opts == \"-\")\n        select_mode = LHP;\n      else if (opts == \"rhp\" || opts == \"+\")\n        select_mode = RHP;\n      else if (opts == \"udi\" || opts == \"s\")\n        select_mode = UDI;\n      else if (opts == \"udo\" || opts == \"b\")\n        select_mode = UDO;\n      else\n        error_with_id (\"Octave:ordqz:unknown-keyword\",\n                       \"ordqz: unknown KEYWORD, possible values: \"\n                       \"lhp, rhp, udi, udo\");\n    }\n  else if (args(4).isreal () || args(4).isinteger () || args(4).islogical ())\n    {\n      if (args(4).rows () > 1 && args(4).columns () > 1)\n        error_with_id (\"Octave:ordqz:select-not-vector\",\n                       \"ordqz: SELECT argument must be a vector\");\n      select_mode = VEC;\n    }\n  else\n    error_with_id (\"Octave:ordqz:unknown-arg\",\n                   \"ordqz: OPT must be string or a logical vector\");\n\n  if (nargout > 4)\n    error_with_id (\"Octave:ordqz:nargout\",\n                   \"ordqz: at most four output arguments possible\");\n\n  // Matrix A: check dimensions.\n  F77_INT nn = to_f77_int (args(0).rows ());\n  F77_INT nc = to_f77_int (args(0).columns ());\n\n  if (args(0).isempty ())\n    {\n      warn_empty_arg (\"qz: A\");\n      return octave_value_list (2, Matrix ());\n    }\n  else if (nc != nn)\n    err_square_matrix_required (\"qz\", \"A\");\n\n  // Matrix A: get value.\n  Matrix aa;\n  ComplexMatrix caa;\n\n  if (args(0).iscomplex ())\n    caa = args(0).complex_matrix_value ();\n  else\n    aa = args(0).matrix_value ();\n\n  // Extract argument 2 (bb, or cbb if complex).\n  F77_INT b_nr = to_f77_int (args(1).rows ());\n  F77_INT b_nc = to_f77_int (args(1).columns ());\n\n  if (nn != b_nc || nn != b_nr)\n    ::err_nonconformant ();\n\n  Matrix bb;\n  ComplexMatrix cbb;\n\n  if (args(1).iscomplex ())\n    cbb = args(1).complex_matrix_value ();\n  else\n    bb = args(1).matrix_value ();\n\n  // Extract argument 3 (qq, or cqq if complex).\n  F77_INT q_nr = to_f77_int (args(2).rows ());\n  F77_INT q_nc = to_f77_int (args(2).columns ());\n\n  if (nn != q_nc || nn != q_nr)\n    ::err_nonconformant ();\n\n  Matrix qq;\n  ComplexMatrix cqq;\n\n  if (args(2).iscomplex ())\n    cqq = args(2).complex_matrix_value ().hermitian ();\n  else\n    qq = args(2).matrix_value ().transpose ();\n\n  // Extract argument 4 (zz, or czz if complex).\n  F77_INT z_nr = to_f77_int (args(3).rows ());\n  F77_INT z_nc = to_f77_int (args(3).columns ());\n\n  if (nn != z_nc || nn != z_nr)\n    ::err_nonconformant ();\n\n  Matrix zz;\n  ComplexMatrix czz;\n\n  if (args(3).iscomplex ())\n    czz = args(3).complex_matrix_value ();\n  else\n    zz = args(3).matrix_value ();\n\n  bool complex_case = (args(0).iscomplex () || args(1).iscomplex ()\n                       || args(2).iscomplex () || args(3).iscomplex ());\n\n  if (select_mode == VEC && args(4).rows () != nn && args(4).columns () != nn)\n    error_with_id (\"Octave:ordqz:numel_select\",\n                   \"ordqz: SELECT vector has the wrong number of elements\");\n\n  Array<double> select_array (dim_vector (nn, 1));\n  if (select_mode == VEC)\n    select_array = args(4).vector_value ();\n\n  Array<F77_LOGICAL> select (dim_vector (nn, 1));\n\n  if (complex_case)\n    {\n      // Complex\n      if (args(0).isreal ())\n        caa = ComplexMatrix (aa);\n      if (args(1).isreal ())\n        cbb = ComplexMatrix (bb);\n      if (args(2).isreal ())\n        cqq = ComplexMatrix (qq);\n      if (args(3).isreal ())\n        czz = ComplexMatrix (zz);\n\n      ComplexRowVector alpha (dim_vector (nn, 1));\n      ComplexRowVector beta  (dim_vector (nn, 1));\n      octave_idx_type k;\n\n      for (k = 0; k < nn-1; k++)\n        {\n          if (caa(k+1, k) != 0.0)\n            error_with_id (\"Octave:ordqz:unsupported_AA\",\n                           \"ordqz: quasi upper triangular matrices are not \"\n                           \"allowed with complex data\");\n        }\n\n      for (k = 0; k < nn; k++)\n        {\n          alpha(k) = caa(k, k);\n          beta(k)  = cbb(k, k);\n        }\n\n      for (k = 0; k < nn; k++)\n        {\n          switch (select_mode)\n            {\n            case LHP:\n              select(k) = real (alpha(k) * beta(k)) < 0;\n              break;\n            case RHP:\n              select(k) = real (alpha(k) * beta(k)) > 0;\n              break;\n            case UDI:\n              if (beta(k) != 0.0)\n                select(k) = abs (alpha(k)/beta(k)) < 1.0;\n              else\n                select(k) = false;\n              break;\n            case UDO:\n              if (beta(k) != 0.0)\n                select(k) = abs (alpha(k)/beta(k)) > 1.0;\n              else\n                select(k) = true;\n              break;\n            case VEC:\n              if (select_array(k) != 0.0)\n                select(k) = true;\n              else\n                select(k) = false;\n              break;\n            case NONE:\n              error (\"ordqz: invalid select mode NONE\");\n              break;\n\n              // We should have handled all possible enum values above.\n              // Rely on compiler diagnostics to warn if we haven't.\n              // For example, GCC's -Wswitch option, enabled by -Wall,\n              // will provide a warning.\n            }\n        }\n\n      F77_LOGICAL wantq, wantz;\n      wantq = 1,  wantz = 1;\n      F77_INT ijob, mm, lrwork3, liwork, info;\n      ijob = 0,  lrwork3 = 1,  liwork = 1;\n      F77_DBLE pl, pr;\n      ComplexRowVector work3 (lrwork3);\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n\n      F77_XFCN (ztgsen, ZTGSEN,\n                (ijob, wantq, wantz,\n                 select.rwdata (), nn,\n                 F77_DBLE_CMPLX_ARG (caa.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (cbb.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (alpha.rwdata ()),\n                 F77_DBLE_CMPLX_ARG (beta.rwdata ()),\n                 F77_DBLE_CMPLX_ARG (cqq.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (czz.rwdata ()), nn,\n                 mm,\n                 pl, pr,\n                 nullptr,\n                 F77_DBLE_CMPLX_ARG (work3.rwdata ()), lrwork3,\n                 iwork.rwdata (), liwork,\n                 info));\n      if (info != 0)\n        error_with_id (\"Octave:ordqz:ztgsen_failed\",\n                       \"ordqz: failed to reorder eigenvalues\");\n    }\n  else\n    {\n      // Extract eigenvalues\n      RowVector alphar (dim_vector (nn, 1));\n      RowVector alphai (dim_vector (nn, 1));\n      RowVector beta (dim_vector (nn, 1));\n\n      octave_idx_type k;\n\n      k = 0;\n      while (k < nn)\n        {\n#if defined (OCTAVE_ORDQZ_DEBUG)\n          octave_stdout << \"ordqz: k = \" << k  << \" nn = \" << nn << \" \\n\";\n#endif\n          if ((k < nn-1 && aa(k+1, k) == 0.0) || k == nn-1)\n            {\n              alphar(k) = aa(k, k);\n              alphai(k) = 0.0;\n              beta(k)   = bb(k, k);\n              k++;\n            }\n          else\n            {\n              double ar[2], ai[2], b[2], work[4];\n              char qz_job = 'E';\n              char comp_q = 'N';\n              char comp_z = 'N';\n              F77_INT nl = 2;\n              F77_INT ilo = 1;\n              F77_INT ihi = 2;\n              F77_INT lwork = 4;\n              F77_INT info = 0;\n              double *aa_vec = aa.rwdata ();\n              double *bb_vec = bb.rwdata ();\n\n              F77_XFCN (dhgeqz, DHGEQZ,\n                        (F77_CONST_CHAR_ARG2 (&qz_job, 1),\n                         F77_CONST_CHAR_ARG2 (&comp_q, 1),\n                         F77_CONST_CHAR_ARG2 (&comp_z, 1),\n                         nl, ilo, ihi,\n                         &aa_vec[k+k*nn], nn,\n                         &bb_vec[k+k*nn], nn,\n                         ar, ai, b,\n                         nullptr, nn,\n                         nullptr, nn, work, lwork, info\n                         F77_CHAR_ARG_LEN (1)\n                         F77_CHAR_ARG_LEN (1)\n                         F77_CHAR_ARG_LEN (1)));\n              if (info != 0)\n                error(\"ordqz: failed to extract eigenvalues\");\n\n              alphar(k)   = ar[0];\n              alphar(k+1) = ar[1];\n              alphai(k)   = ai[0];\n              alphai(k+1) = ai[1];\n              beta(k)   = b[0];\n              beta(k+1) = b[1];\n\n              k += 2;\n            }\n\n        }\n\n      for (k = 0; k < nn; k++)\n        {\n          switch (select_mode)\n            {\n            case LHP:\n              select(k) = alphar(k) * beta(k) < 0;\n              break;\n            case RHP:\n              select(k) = alphar(k) * beta(k) > 0;\n              break;\n            case UDI:\n              select(k) = alphar(k)*alphar(k)\n                          + alphai(k)*alphai(k) < beta(k)*beta(k);\n              break;\n            case UDO:\n              select(k) = alphar(k)*alphar(k)\n                          + alphai(k)*alphai(k) > beta(k)*beta(k);\n              break;\n            case VEC:\n              if (select_array(k) != 0.0)\n                select(k) = true;\n              else\n                select(k) = false;\n              break;\n            case NONE:\n              error (\"ordqz: invalid select mode NONE\");\n              break;\n\n              // We should have handled all possible enum values above.\n              // Rely on compiler diagnostics to warn if we haven't.\n              // For example, GCC's -Wswitch option, enabled by -Wall,\n              // will provide a warning.\n            }\n        }\n\n      F77_LOGICAL wantq, wantz;\n      wantq = 1,  wantz = 1;\n      F77_INT ijob, mm, lrwork3, liwork, info;\n      ijob = 0,  lrwork3 = 4*nn+16,  liwork = nn;\n      F77_DBLE pl, pr;\n      RowVector rwork3 (lrwork3);\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n\n      F77_XFCN (dtgsen, DTGSEN,\n                (ijob, wantq, wantz,\n                 select.rwdata (), nn,\n                 aa.rwdata (), nn,\n                 bb.rwdata (), nn,\n                 alphar.rwdata (),\n                 alphai.rwdata (),\n                 beta.rwdata (),\n                 qq.rwdata (), nn,\n                 zz.rwdata (), nn,\n                 mm,\n                 pl, pr,\n                 nullptr,\n                 rwork3.rwdata (), lrwork3,\n                 iwork.rwdata (), liwork,\n                 info));\n      if (info != 0)\n        error(\"ordqz: failed to reorder eigenvalues\");\n    }\n\n  octave_value_list retval (nargout);\n  switch (nargout)\n    {\n    case 4:\n      if (complex_case)\n        retval(3) = czz;\n      else\n        retval(3) = zz;\n      OCTAVE_FALLTHROUGH;\n    case 3:\n      if (complex_case)\n        retval(2) = cqq.hermitian();\n      else\n        retval(2) = qq.transpose();\n      OCTAVE_FALLTHROUGH;\n    case 2:\n      if (complex_case)\n        retval(1) = cbb;\n      else\n        retval(1) = bb;\n      OCTAVE_FALLTHROUGH;\n    case 1:\n      if (complex_case)\n        retval(0) = caa;\n      else\n        retval(0) = aa;\n      break;\n    case 0:\n      if (complex_case)\n        retval(0) = caa;\n      else\n        retval(0) = aa;\n      break;\n    }\n\n  return retval;\n}\n\n\n/*\n%!shared A, B, AA, BB, QQ, ZZ, AC, BC, AAC, BBC, QQC, ZZC, select, selectc\n%! A = [ -1.03428  0.24929  0.43205 -0.12860;\n%!        1.16228  0.27870  2.12954  0.69250;\n%!       -0.51524 -0.34939 -0.77820  2.13721;\n%!       -1.32941  2.11870  0.72005  1.00835 ];\n%! B = [  1.407302 -0.632956 -0.360628  0.068534;\n%!        0.149898  0.298248  0.991777  0.023652;\n%!        0.169281 -0.405205 -1.775834  1.511730;\n%!        0.717770  1.291390 -1.766607 -0.531352 ];\n%! AC = [ 0.4577 + 0.7199i   0.1476 + 0.6946i   0.6202 + 0.2092i   0.7559 + 0.2759i;\n%!        0.5868 + 0.7275i   0.9174 + 0.8781i   0.6741 + 0.1985i   0.4320 + 0.7023i;\n%!        0.2408 + 0.6359i   0.2959 + 0.8501i   0.3904 + 0.5613i   0.5000 + 0.1428i;\n%!        0.8177 + 0.8581i   0.2583 + 0.8970i   0.7706 + 0.5451i   0.1068 + 0.1650i];\n%! BC = [ 0.089898 + 0.209257i   0.157769 + 0.311387i   0.018926 + 0.622517i   0.058825 + 0.374647i;\n%!        0.009367 + 0.098211i   0.736087 + 0.095797i   0.973192 + 0.583765i   0.434018 + 0.461909i;\n%!        0.880784 + 0.868215i   0.032839 + 0.569461i   0.873437 + 0.266081i   0.739426 + 0.362017i;\n%!        0.121649 + 0.115111i   0.426695 + 0.492222i   0.247670 + 0.034414i   0.771629 + 0.078153i];\n%! [AA, BB, QQ, ZZ] = qz (A, B);\n%! [AAC, BBC, QQC, ZZC] = qz (AC, BC);\n%! select = [0 0 1 1];\n%! selectc = [0 0 0 1];\n\n%!test\n%! [AAX, BBX, QQX, ZZX] = ordqz (AA, BB, QQ, ZZ, \"rhp\");\n%! assert (all (real (eig (AAX(1:3,1:3), BBX(1:3,1:3))) >= 0));\n%! assert (all (real (eig (AAX(4:4,4:4), BBX(4:4,4:4))) < 0));\n%! assert (norm (QQX'*AAX*ZZX' - A, \"fro\"), 0, 1e-12);\n%! assert (norm (QQX'*BBX*ZZX' - B, \"fro\"), 0, 1e-12);\n\n%!test\n%! [AAX, BBX, QQX, ZZX] = ordqz (AA, BB, QQ, ZZ, \"+\");\n%! assert (all (real (eig (AAX(1:3,1:3), BBX(1:3,1:3))) >= 0));\n%! assert (all (real (eig (AAX(4:4,4:4), BBX(4:4,4:4))) < 0));\n\n%!test\n%! [AAX, BBX, QQX, ZZX] = ordqz (AA, BB, QQ, ZZ, \"lhp\");\n%! assert (all (real (eig (AAX(2:4,2:4), BBX(2:4,2:4))) >= 0));\n%! assert (all (real (eig (AAX(1:1,1:1), BBX(1:1,1:1))) < 0));\n%! assert (norm (QQX'*AAX*ZZX' - A, \"fro\"), 0, 1e-12);\n%! assert (norm (QQX'*BBX*ZZX' - B, \"fro\"), 0, 1e-12);\n\n%!test\n%! [AAX, BBX, QQX, ZZX] = ordqz (AA, BB, QQ, ZZ, \"-\");\n%! assert (all (real (eig (AAX(2:4,2:4), BBX(2:4,2:4))) >= 0));\n%! assert (all (real (eig (AAX(1:1,1:1), BBX(1:1,1:1))) < 0));\n\n%!test\n%! [AAX, BBX, QQX, ZZX] = ordqz (AA, BB, QQ, ZZ, \"udi\");\n%! assert (all (abs (eig (AAX(1:1,1:1), BBX(1:1,1:1))) < 1));\n%! assert (all (abs (eig (AAX(2:4,2:4), BBX(2:4,2:4))) > 1));\n%! assert (norm (QQX'*AAX*ZZX' - A, \"fro\"), 0, 1e-12);\n%! assert (norm (QQX'*BBX*ZZX' - B, \"fro\"), 0, 1e-12);\n\n%!test\n%! [AAX, BBX, QQX, ZZX] = ordqz (AA, BB, QQ, ZZ, \"S\");\n%! assert (all (abs (eig (AAX(1:1,1:1), BBX(1:1,1:1))) < 1));\n%! assert (all (abs (eig (AAX(2:4,2:4), BBX(2:4,2:4))) > 1));\n\n%!test\n%! [AAX, BBX, QQX, ZZX] = ordqz (AA, BB, QQ, ZZ, \"udo\");\n%! assert (all (abs (eig (AAX(1:3,1:3), BBX(1:3,1:3))) >= 1));\n%! assert (all (abs (eig (AAX(4:4,4:4), BBX(4:4,4:4))) < 1));\n%! assert (norm (QQX'*AAX*ZZX' - A, \"fro\"), 0, 1e-12);\n%! assert (norm (QQX'*BBX*ZZX' - B, \"fro\"), 0, 1e-12);\n\n%!test\n%! [AAX, BBX, QQX, ZZX] = ordqz (AA, BB, QQ, ZZ, \"B\");\n%! assert (all (abs (eig (AAX(1:3,1:3), BBX(1:3,1:3))) >= 1));\n%! assert (all (abs (eig (AAX(4:4,4:4), BBX(4:4,4:4))) < 1));\n\n%!test\n%! [AAX, BBX, QQX, ZZX] = ordqz (AA, BB, QQ, ZZ, select);\n%! assert (all (iscomplex (eig (AAX(1:2,1:2), BBX(1:2,1:2)))));\n%! assert (norm (QQX'*AAX*ZZX' - A, \"fro\"), 0, 1e-12);\n%! assert (norm (QQX'*BBX*ZZX' - B, \"fro\"), 0, 1e-12);\n\n%!test\n%! [AACX, BBCX, QQCX, ZZCX] = ordqz (AAC, BBC, QQC, ZZC, \"rhp\");\n%! assert (all (real (eig (AACX(1:2,1:2), BBCX(1:2,1:2))) >= 0));\n%! assert (all (real (eig (AACX(3:4,3:4), BBCX(3:4,3:4))) < 0));\n%! assert (norm (QQCX'*AACX*ZZCX' - AC, \"fro\"), 0, 1e-12);\n%! assert (norm (QQCX'*BBCX*ZZCX' - BC, \"fro\"), 0, 1e-12);\n\n%!test\n%! [AACX, BBCX, QQCX, ZZCX] = ordqz (AAC, BBC, QQC, ZZC, \"lhp\");\n%! assert (all (real (eig (AACX(1:2,1:2), BBCX(1:2,1:2))) < 0));\n%! assert (all (real (eig (AACX(3:4,3:4), BBCX(3:4,3:4))) >= 0));\n%! assert (norm (QQCX'*AACX*ZZCX' - AC, \"fro\"), 0, 1e-12);\n%! assert (norm (QQCX'*BBCX*ZZCX' - BC, \"fro\"), 0, 1e-12);\n\n%!test\n%! [AACX, BBCX, QQCX, ZZCX] = ordqz (AAC, BBC, QQC, ZZC, \"udi\");\n%! assert (all (abs (eig (AACX(1:2,1:2), BBCX(1:2,1:2))) < 1));\n%! assert (all (abs (eig (AACX(3:4,3:4), BBCX(3:4,3:4))) >= 1));\n%! assert (norm (QQCX'*AACX*ZZCX' - AC, \"fro\"), 0, 1e-12);\n%! assert (norm (QQCX'*BBCX*ZZCX' - BC, \"fro\"), 0, 1e-12);\n\n%!test\n%! [AACX, BBCX, QQCX, ZZCX] = ordqz (AAC, BBC, QQC, ZZC, \"udo\");\n%! assert (all (abs (eig (AACX(1:2,1:2), BBCX(1:2,1:2))) >= 1));\n%! assert (all (abs (eig (AACX(3:4,3:4), BBCX(3:4,3:4))) < 1));\n%! assert (norm (QQCX'*AACX*ZZCX' - AC, \"fro\"), 0, 1e-12);\n%! assert (norm (QQCX'*BBCX*ZZCX' - BC, \"fro\"), 0, 1e-12);\n\n%!test\n%! [AACX, BBCX, QQCX, ZZCX] = ordqz (AAC, BBC, QQC, ZZC, selectc);\n%! ev = abs (eig (AACX(1:1,1:1), BBCX(1:1,1:1)));\n%! assert(ev > 0.6 && ev < 0.7);\n%! assert (norm (QQCX'*AACX*ZZCX' - AC, \"fro\"), 0, 1e-12);\n%! assert (norm (QQCX'*BBCX*ZZCX' - BC, \"fro\"), 0, 1e-12);\n\n%!test\n%! A = toeplitz ([1,2,3,4]);\n%! [B, A] = qr (A);\n%! B = B';\n%! [AA, BB, Q, Z] = qz (A, B);\n%! [AAS, BBS, QS, ZS] = ordqz (AA, BB, Q, Z, \"lhp\");\n%! E2 = ordeig (AAS, BBS);\n%! ECOMP = [-3.414213562373092; -1.099019513592784;\n%!          -0.5857864376269046; 9.099019513592784];\n%! assert (norm (ECOMP - E2, \"Inf\"), 0, 1e-8);\n\n## Test input validation\n%!error <Invalid call> ordqz ()\n%!error <Invalid call> ordqz (eye (2))\n%!error <Invalid call> ordqz (eye (2), eye (2))\n%!error <Invalid call> ordqz (eye (2), eye (2), eye (2))\n%!error <Invalid call> ordqz (eye (2), eye (2), eye (2), eye (2))\n%!error id=Octave:ordqz:unknown-keyword\n%! ordqz (eye (2), eye (2), eye (2), eye (2), \"foobar\");\n%!error id=Octave:ordqz:select-not-vector\n%! ordqz (eye (2), eye (2), eye (2), eye (2), eye (2));\n%!error id=Octave:ordqz:unknown-arg\n%! ordqz (eye (2), eye (2), eye (2), eye (2), {\"foobar\"});\n%!error id=Octave:ordqz:nargout\n%! [a,b,c,d,e] = ordqz (eye (2), eye (2), eye (2), eye (2), \"udi\");\n%!warning <A: argument is empty matrix> ordqz ([], [], [], [], \"udi\");\n%!error <A must be a square matrix> ordqz (ones (1,2), [], [], [], \"udi\");\n%!error <nonconformant matrices>\n%! ordqz (eye (3), eye (2), eye (2), eye (2), \"udi\");\n%!error <nonconformant matrices>\n%! ordqz (eye (2), eye (3), eye (2), eye (2), \"udi\");\n%!error <nonconformant matrices>\n%! ordqz (eye (2), eye (2), eye (3), eye (2), \"udi\");\n%!error <nonconformant matrices>\n%! ordqz (eye (2), eye (2), eye (2), eye (3), \"udi\");\n%!error <SELECT vector .* wrong number of elements>\n%! ordqz (eye (2), eye (2), eye (2), eye (2), ones (1,5));\n%!error <quasi upper triangular matrices are not allowed with complex data>\n%! AA = zeros (2, 2);\n%! AA(2,1) = i;\n%! ordqz (AA, eye (2), eye (2), eye (2), \"udi\");\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/ordschur.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lapack-proto.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (ordschur, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{UR}, @var{SR}] =} ordschur (@var{U}, @var{S}, @var{select})\nReorder the real Schur factorization (@var{U},@var{S}) obtained with the\n@code{schur} function, so that selected eigenvalues appear in the upper left\ndiagonal blocks of the quasi triangular Schur matrix.\n\nThe logical vector @var{select} specifies the selected eigenvalues as they\nappear along @var{S}'s diagonal.\n\nFor example, given the matrix @code{@var{A} = [1, 2; 3, 4]}, and its Schur\ndecomposition\n\n@example\n[@var{U}, @var{S}] = schur (@var{A})\n@end example\n\n@noindent\nwhich returns\n\n@example\n@group\n@var{U} =\n\n  -0.82456  -0.56577\n   0.56577  -0.82456\n\n@var{S} =\n\n  -0.37228  -1.00000\n   0.00000   5.37228\n\n@end group\n@end example\n\nIt is possible to reorder the decomposition so that the positive eigenvalue\nis in the upper left corner, by doing:\n\n@example\n[@var{U}, @var{S}] = ordschur (@var{U}, @var{S}, [0,1])\n@end example\n\n@seealso{schur, trexc, ordeig, ordqz}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  const Array<octave_idx_type> sel_arg = args(2).xoctave_idx_type_vector_value (\"ordschur: SELECT must be an array of integers\");\n\n  const octave_idx_type sel_n = sel_arg.numel ();\n\n  const dim_vector dimU = args(0).dims ();\n  const dim_vector dimS = args(1).dims ();\n\n  if (sel_n != dimU(0))\n    error (\"ordschur: SELECT must have same length as the sides of U and S\");\n  else if (sel_n != dimU(0) || sel_n != dimS(0) || sel_n != dimU(1)\n           || sel_n != dimS(1))\n    error (\"ordschur: U and S must be square and of equal sizes\");\n\n  octave_value_list retval;\n\n  const bool double_type = args(0).is_double_type () || args(1).is_double_type ();\n  const bool complex_type = args(0).iscomplex () || args(1).iscomplex ();\n\n#define PREPARE_ARGS(TYPE, TYPE_M, TYPE_COND)                           \\\n  TYPE ## Matrix U = args(0).x ## TYPE_M ## _value                      \\\n    (\"ordschur: U and S must be real or complex floating point matrices\"); \\\n  TYPE ## Matrix S = args(1).x ## TYPE_M ## _value                      \\\n    (\"ordschur: U and S must be real or complex floating point matrices\"); \\\n  TYPE ## Matrix w (dim_vector (n, 1));                                 \\\n  TYPE ## Matrix work (dim_vector (n, 1));                              \\\n  F77_INT m;                                                            \\\n  F77_INT info;                                                         \\\n  TYPE_COND cond1, cond2;\n\n#define PREPARE_OUTPUT()                        \\\n  if (info != 0)                                \\\n    error (\"ordschur: trsen failed\");           \\\n                                                \\\n  retval = ovl (U, S);\n\n  F77_INT n = to_f77_int (sel_n);\n  Array<F77_INT> sel (dim_vector (n, 1));\n  for (F77_INT i = 0; i < n; i++)\n    sel.xelem (i) = to_f77_int (sel_arg.xelem (i));\n\n  if (double_type)\n    {\n      if (complex_type)\n        {\n          PREPARE_ARGS (Complex, complex_matrix, double)\n\n          F77_XFCN (ztrsen, ztrsen,\n                    (F77_CONST_CHAR_ARG (\"N\"), F77_CONST_CHAR_ARG (\"V\"),\n                     sel.data (), n, F77_DBLE_CMPLX_ARG (S.rwdata ()), n,\n                     F77_DBLE_CMPLX_ARG (U.rwdata ()), n,\n                     F77_DBLE_CMPLX_ARG (w.rwdata ()), m, cond1, cond2,\n                     F77_DBLE_CMPLX_ARG (work.rwdata ()), n, info\n                     F77_CHAR_ARG_LEN (1) F77_CHAR_ARG_LEN (1)));\n\n          PREPARE_OUTPUT()\n        }\n      else\n        {\n          PREPARE_ARGS (, matrix, double)\n          Matrix wi (dim_vector (n, 1));\n          Array<F77_INT> iwork (dim_vector (n, 1));\n\n          F77_XFCN (dtrsen, dtrsen,\n                    (F77_CONST_CHAR_ARG (\"N\"), F77_CONST_CHAR_ARG (\"V\"),\n                     sel.data (), n, S.rwdata (), n, U.rwdata (), n,\n                     w.rwdata (), wi.rwdata (), m, cond1, cond2,\n                     work.rwdata (), n, iwork.rwdata (), n, info\n                     F77_CHAR_ARG_LEN (1) F77_CHAR_ARG_LEN (1)));\n\n          PREPARE_OUTPUT ()\n        }\n    }\n  else\n    {\n      if (complex_type)\n        {\n          PREPARE_ARGS (FloatComplex, float_complex_matrix, float)\n\n          F77_XFCN (ctrsen, ctrsen,\n                    (F77_CONST_CHAR_ARG (\"N\"), F77_CONST_CHAR_ARG (\"V\"),\n                     sel.data (), n, F77_CMPLX_ARG (S.rwdata ()), n,\n                     F77_CMPLX_ARG (U.rwdata ()), n,\n                     F77_CMPLX_ARG (w.rwdata ()), m, cond1, cond2,\n                     F77_CMPLX_ARG (work.rwdata ()), n, info\n                     F77_CHAR_ARG_LEN (1) F77_CHAR_ARG_LEN (1)));\n\n          PREPARE_OUTPUT ()\n        }\n      else\n        {\n          PREPARE_ARGS (Float, float_matrix, float)\n          FloatMatrix wi (dim_vector (n, 1));\n          Array<F77_INT> iwork (dim_vector (n, 1));\n\n          F77_XFCN (strsen, strsen,\n                    (F77_CONST_CHAR_ARG (\"N\"), F77_CONST_CHAR_ARG (\"V\"),\n                     sel.data (), n, S.rwdata (), n, U.rwdata (), n,\n                     w.rwdata (), wi.rwdata (), m, cond1, cond2,\n                     work.rwdata (), n, iwork.rwdata (), n, info\n                     F77_CHAR_ARG_LEN (1) F77_CHAR_ARG_LEN (1)));\n\n          PREPARE_OUTPUT ()\n        }\n    }\n\n#undef PREPARE_ARGS\n#undef PREPARE_OUTPUT\n\n  return retval;\n}\n\n/*\n\n%!test\n%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4 ];\n%! [U, T] = schur (A);\n%! [US, TS] = ordschur (U, T, [ 0, 0, 1, 1 ]);\n%! assert (US*TS*US', A, sqrt (eps));\n%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps));\n\n%!test\n%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4 ];\n%! [U, T] = schur (A);\n%! [US, TS] = ordschur (single (U), single (T), [ 0, 0, 1, 1 ]);\n%! assert (US*TS*US', A, sqrt (eps (\"single\")));\n%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps (\"single\")));\n\n%!test\n%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4+3i ];\n%! [U, T] = schur (A);\n%! [US, TS] = ordschur (U, T, [ 0, 0, 1, 1 ]);\n%! assert (US*TS*US', A, sqrt (eps));\n%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps));\n\n%!test\n%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4+3i ];\n%! [U, T] = schur (A);\n%! [US, TS] = ordschur (single (U), single (T), [ 0, 0, 1, 1 ]);\n%! assert (US*TS*US', A, sqrt (eps (\"single\")));\n%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps (\"single\")));\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/perms.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2023-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <numeric>\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE (octave)\n\nstatic inline double\nFactorial (octave_idx_type n)\n{\n  double ret = 1;\n  for (octave_idx_type i = 2; i <= n; i++)\n    ret *= i;\n  return ret;\n}\n\n//\n// Use C++ template to cater for the different octave array classes.\n//\n\ntemplate <typename T>\nstatic inline Array<T>\nGetPerms (const Array<T>& ar_in, bool uniq_v = false)\n{\n  octave_idx_type m = ar_in.numel ();\n  double nr = Factorial (m);  // number of rows of resulting array\n\n  // Setup index vector filled from 0..m-1\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, myvidx, m);\n  std::iota (&myvidx[0], &myvidx[m], 0);\n\n  const T *Ar = ar_in.data ();\n\n  if (uniq_v)  // need to reduce the size of the resulting array\n    {\n      // Mutual Comparison is used to detect duplicated values.\n      // Using sort would be possible for numerical values and be of\n      // O(n*log (n)) complexity instead of O(n*(n -1) / 2).  But sort\n      // is not supported for the octave_value container (structs/cells).\n      // Moreover, sort requires overhead for creating, filling, and sorting\n      // the intermediate array which would need to be post-processed.\n      // In practice, and because n must be very small, mutual comparison is\n      // typically faster and consumes less memory.\n\n      // Number of unique permutations is n! / (n_el1! * n_el2! * ...)\n      // where n_elX is the number of myvidx elements with value X.\n      for (octave_idx_type i = 0; i < m - 1; i++)\n        {\n          octave_idx_type count = 1;\n          for (octave_idx_type j = i + 1; j < m; j++)\n            {\n              bool isequal;\n              if constexpr (std::is_same<T, octave_value>::value)\n                // operator '==' is not supported for octave_value objects\n                isequal = Ar[i].is_equal (Ar[j]);\n              else\n                isequal = (Ar[i] == Ar[j]);\n\n              if (myvidx[j] > myvidx[i] && isequal)\n              {\n                myvidx[j] = myvidx[i];  // not yet processed...\n                ++count;\n              }\n            }\n          nr /= Factorial (count);\n        }\n\n      // At this point, myvidx serves as a unique id of the elements.\n    }\n\n  // Sort vector indices for inverse lexicographic order later.\n  std::sort (myvidx, myvidx + m, std::greater<octave_idx_type> ());\n\n  // Set up result array\n  octave_idx_type n = static_cast<octave_idx_type> (nr);\n  Array<T> res (dim_vector (n, m));\n  T *Res = res.rwdata ();\n\n  // Do the actual job\n  octave_idx_type i = 0;\n  do\n    {\n      for (octave_idx_type j = 0; j < m; j++)\n        Res[i + j * n] = Ar[myvidx[j]];\n      i++;\n    }\n  while (std::next_permutation (myvidx, myvidx + m, std::greater<int> ()));\n\n  return res;\n}\n\nDEFUN (perms, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{P} =} perms (@var{v})\n@deftypefnx {} {@var{P} =} perms (@var{v}, \"unique\")\nGenerate all permutations of vector @var{v} with one row per permutation.\n\nResults are returned in reverse lexicographic order if @var{v} is in ascending\norder.  If @var{v} is in a different permutation, then the result is permuted\nthat way too.  Consequently, an input in descending order yields a result in\nnormal lexicographic order.  The result has size\n@code{factorial (@var{n}) * @var{n}}, where @var{n} is the length of @var{v}.\nAny repeated elements are included in the output.\n\nIf the optional argument @qcode{\"unique\"} is given then only unique\npermutations are returned, using less memory and taking less time than calling\n@code{unique (perms (@var{v}), \"rows\")}.\n\nExample 1\n\n@example\n@group\nperms ([1, 2, 3])\n@xresult{}\n3   2   1\n3   1   2\n2   3   1\n2   1   3\n1   3   2\n1   2   3\n@end group\n@end example\n\nExample 2\n\n@example\n@group\nperms ([1, 1, 2, 2], \"unique\")\n@xresult{}\n2   2   1   1\n2   1   2   1\n2   1   1   2\n1   2   2   1\n1   2   1   2\n1   1   2   2\n@end group\n@end example\n\nProgramming Note: If the @qcode{\"unique\"} option is not used, the length of\n@var{v} should be no more than 10-12 to limit memory consumption.  Even with\n@qcode{\"unique\"}, there should be no more than 10-12 unique elements in\n@var{v}.\n@seealso{permute, randperm, nchoosek}\n\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value retval;\n\n  // Parameter check \"unique\"\n  bool uniq_v = false;\n  if (nargin == 2)\n    {\n      const charMatrix opt = args (1).char_matrix_value ();\n      const char *str = opt.data ();\n      if (std::string (str, opt.cols ()) != \"unique\")\n        {\n          error (\"perms: option must be the string \\\"unique\\\".\");\n        }\n      uniq_v = true;\n    }\n\n  if (! (args (0).is_matrix_type () || args (0).is_range ()\n         || args (0).iscell () || args (0).is_scalar_type ()\n         || args (0).isstruct ()))\n    {\n      error (\"perms: V must be a matrix, range, cell array, \"\n             \"struct, or a scalar.\");\n    }\n\n  std::string clname = args (0).class_name ();\n\n  // Execute main permutation code for the different classes\n  if (clname == \"double\")\n    retval = GetPerms<double> (args (0).array_value (), uniq_v);\n  else if (clname == \"single\")\n    retval = GetPerms<float> (args (0).float_array_value (), uniq_v);\n  else if (clname == \"logical\")\n    retval = GetPerms<bool> (args (0).bool_array_value (), uniq_v);\n  else if (clname == \"char\")\n    retval = GetPerms<char> (args (0).char_array_value (), uniq_v);\n  else if (clname == \"int8\")\n    retval = GetPerms<octave_int8> (args (0).int8_array_value (), uniq_v);\n  else if (clname == \"int16\")\n    retval = GetPerms<octave_int16> (args (0).int16_array_value (), uniq_v);\n  else if (clname == \"int32\")\n    retval = GetPerms<octave_int32> (args (0).int32_array_value (), uniq_v);\n  else if (clname == \"int64\")\n    retval = GetPerms<octave_int64> (args (0).int64_array_value (), uniq_v);\n  else if (clname == \"uint8\")\n    retval = GetPerms<octave_uint8> (args (0).uint8_array_value (), uniq_v);\n  else if (clname == \"uint16\")\n    retval = GetPerms<octave_uint16> (args (0).uint16_array_value (), uniq_v);\n  else if (clname == \"uint32\")\n    retval = GetPerms<octave_uint32> (args (0).uint32_array_value (), uniq_v);\n  else if (clname == \"uint64\")\n    retval = GetPerms<octave_uint64> (args (0).uint64_array_value (), uniq_v);\n  else if (clname == \"cell\")\n    retval = Cell (GetPerms<octave_value> (args (0).cell_value (), uniq_v));\n  else if (clname == \"struct\")\n    {\n      const octave_map map_in (args (0).map_value ());\n      string_vector fn = map_in.fieldnames ();\n      if (fn.numel () == 0 && map_in.numel () != 0)\n        {\n          octave_scalar_map out;\n          retval = out;\n        }\n      else\n        {\n          octave_map out;\n          if (fn.numel () == 0)\n            {\n              out = octave_map (dim_vector (1, 0));\n            }\n          else\n            {\n              for (octave_idx_type i = 0; i < fn.numel (); i++)\n                {\n                  out.assign (fn (i), GetPerms<octave_value>\n                                      (map_in.contents (fn (i)), uniq_v));\n                }\n            }\n          retval = out;\n        }\n    }\n  else  // none of the above class criteria were met\n    {\n      warning (\"perms: unable to permute for class %s\", clname.c_str ());\n      // retval stays empty\n    }\n  return ovl (retval);\n}\n\n/*\n\n%!assert (rows (perms (1:6)), factorial (6))\n%!assert (perms (pi), pi)\n%!assert (perms ([e, pi]), [pi, e; e, pi])\n%!assert (perms ([pi, e]), [e, pi; pi, e])\n%!assert (perms ([1 2 3]), [3 2 1; 3 1 2; 2 3 1; 2 1 3; 1 3 2; 1 2 3])\n%!assert (sortrows (perms (1:5)), sortrows (perms ([2 5 4 1 3]')))\n%!assert (perms (\"abc\"), char (\"cba\", \"cab\", \"bca\", \"bac\", \"acb\", \"abc\"))\n%!assert (sortrows (perms (\"fobar\")), unique (perms (\"fobar\"), \"rows\"))\n%!assert (unique (perms (1:5)(:))', 1:5)\n%!assert (perms (int8 (1:4)), int8 (perms (1:4)))\n\n%!assert (sortrows (perms (\"abb\", \"unique\")), [\"abb\"; \"bab\"; \"bba\"])\n%!assert (size (perms ([1 1 1 1 2 2 2 3 3], \"unique\")), [1260 9])\n%!assert (size (perms (int8([1 1 1 1 1 2 2 2 2 3 3 3]), \"unique\")), [27720 12])\n\n## Test \"unique\" with different input orders.\n%!assert <*67115> (sortrows (perms ([1 1 2 2], \"unique\")), [1 1 2 2; 1 2 1 2; 1 2 2 1; 2 1 1 2; 2 1 2 1; 2 2 1 1])\n%!assert <*67115> (sortrows (perms ([1 2 1 2], \"unique\")), [1 1 2 2; 1 2 1 2; 1 2 2 1; 2 1 1 2; 2 1 2 1; 2 2 1 1])\n%!assert <*67115> (sortrows (perms ([1 2 2 1], \"unique\")), [1 1 2 2; 1 2 1 2; 1 2 2 1; 2 1 1 2; 2 1 2 1; 2 2 1 1])\n%!assert <*67115> (sortrows (perms ([2 1 1 2], \"unique\")), [1 1 2 2; 1 2 1 2; 1 2 2 1; 2 1 1 2; 2 1 2 1; 2 2 1 1])\n%!assert <*67115> (sortrows (perms ([2 1 2 1], \"unique\")), [1 1 2 2; 1 2 1 2; 1 2 2 1; 2 1 1 2; 2 1 2 1; 2 2 1 1])\n%!assert <*67115> (sortrows (perms ([2 2 1 1], \"unique\")), [1 1 2 2; 1 2 1 2; 1 2 2 1; 2 1 1 2; 2 1 2 1; 2 2 1 1])\n\n## Should work for any array type, such as cells and structs,\n## and not only for numeric data.\n\n%!assert <*52431> (perms ({1}), {1})\n%!assert <*52431> (perms ({0.1, \"foo\"}), {\"foo\", 0.1; 0.1, \"foo\"})\n%!assert <*52431> (perms ({\"foo\", 0.1}), {0.1, \"foo\"; \"foo\", 0.1})\n%!assert <*52431> (perms ({\"foo\"; 0.1}), {0.1, \"foo\"; \"foo\", 0.1})\n%!assert <*52431> (perms ({0.1; \"foo\"}), {\"foo\", 0.1; 0.1, \"foo\"})\n%!assert <*52431> (perms ({\"foo\", \"bar\"}), {\"bar\", \"foo\"; \"foo\", \"bar\"})\n%!assert <*52431> (perms ({\"bar\", \"foo\"}), {\"foo\", \"bar\"; \"bar\", \"foo\"})\n%!\n%!assert <*52431> (perms (struct ()), struct ())\n%!assert <*52431> (perms (struct (\"foo\", {1, 2})),\n%!                struct (\"foo\", {2, 1; 1, 2}))\n%!assert <*52431> (perms (struct (\"foo\", {1, 2}, \"bar\", {3, 4})),\n%!                struct (\"foo\", {2, 1; 1, 2}, \"bar\", {4, 3; 3, 4}))\n\n## Also sort logical input with order dependent on the input order and\n## not their values.\n\n%!assert <*52431> (perms (logical ([1 0])), logical ([0 1; 1 0]))\n%!assert <*52431> (perms (logical ([0 1])), logical ([1 0; 0 1]))\n%!assert <*52431> (perms (logical ([0 1 0])),\n%!                logical ([0 1 0; 0 0 1; 1 0 0; 1 0 0; 0 0 1; 0 1 0]))\n%!assert <*52431> (perms (logical ([0 1 1])),\n%!                logical ([1 1 0; 1 0 1; 1 1 0; 1 0 1; 0 1 1; 0 1 1]))\n\n%!assert <*52432> (perms ([]), reshape ([], 1, 0))\n%!assert <*52432> (perms (single ([])), reshape (single ([]), 1, 0))\n%!assert <*52432> (perms (int8 ([])), reshape (int8 ([]), 1, 0))\n%!assert <*52432> (perms ({}), cell (1, 0))\n\n%!test <*52432>\n%! s = struct ();\n%! s(1) = [];\n%! assert (perms (reshape (s, 0, 0)), reshape (s, 1, 0));\n%! assert (perms (reshape (s, 0, 1)), reshape (s, 1, 0));\n\n## test if \"unique\" works also for cell arrays\n%!assert <*63965> (perms ({\"foo\"; \"foo\"}, \"unique\"), {\"foo\", \"foo\"})\n%!assert <*63965> (perms ({\"foo\", \"foo\", \"bar\"}, \"unique\"), ...\n%!                        {\"bar\", \"foo\", \"foo\";\n%!                         \"foo\", \"bar\", \"foo\";\n%!                         \"foo\", \"foo\", \"bar\"})\n\n## Test input validation\n%!error <Invalid call> perms ()\n%!error <option must be the string \"unique\"> perms (1:5, \"foobar\")\n%!error <option must be the string \"unique\"> perms (1:5, {\"foo\"})\n\n*/\n\nOCTAVE_END_NAMESPACE (octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/pinv.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ops.h\"\n#include \"ov-re-diag.h\"\n#include \"ov-cx-diag.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-flt-cx-diag.h\"\n#include \"ov-perm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (pinv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{B} =} pinv (@var{A})\n@deftypefnx {} {@var{B} =} pinv (@var{A}, @var{tol})\nReturn the @nospell{Moore-Penrose} pseudoinverse of @var{A}.\n\nSingular values less than @var{tol} are ignored.\n\nIf the second argument is omitted, it is taken to be\n\n@example\ntol = max ([rows(@var{x}), columns(@var{x})]) * norm (@var{x}) * eps\n@end example\n\n@seealso{inv, ldivide}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  if (! arg.isnumeric ())\n    err_wrong_type_arg (\"pinv\", arg);\n\n  if (arg.isempty ())\n    return ovl (Matrix ());\n\n  octave_value retval;\n\n  bool isfloat = arg.is_single_type ();\n\n  if (arg.is_diag_matrix ())\n    {\n      if (isfloat)\n        {\n          float tol = 0.0;\n          if (nargin == 2)\n            tol = args(1).float_value ();\n\n          if (tol < 0.0)\n            error (\"pinv: TOL must be greater than zero\");\n\n          if (arg.isreal ())\n            retval = arg.float_diag_matrix_value ().pseudo_inverse (tol);\n          else\n            retval = arg.float_complex_diag_matrix_value ().pseudo_inverse (tol);\n        }\n      else\n        {\n          double tol = 0.0;\n          if (nargin == 2)\n            tol = args(1).double_value ();\n\n          if (tol < 0.0)\n            error (\"pinv: TOL must be greater than zero\");\n\n          if (arg.isreal ())\n            retval = arg.diag_matrix_value ().pseudo_inverse (tol);\n          else\n            retval = arg.complex_diag_matrix_value ().pseudo_inverse (tol);\n        }\n    }\n  else if (arg.is_perm_matrix ())\n    {\n      retval = arg.perm_matrix_value ().inverse ();\n    }\n  else if (isfloat)\n    {\n      float tol = 0.0;\n      if (nargin == 2)\n        tol = args(1).float_value ();\n\n      if (tol < 0.0)\n        error (\"pinv: TOL must be greater than zero\");\n\n      if (arg.isreal ())\n        {\n          FloatMatrix m = arg.float_matrix_value ();\n\n          retval = m.pseudo_inverse (tol);\n        }\n      else if (arg.iscomplex ())\n        {\n          FloatComplexMatrix m = arg.float_complex_matrix_value ();\n\n          retval = m.pseudo_inverse (tol);\n        }\n      else\n        err_wrong_type_arg (\"pinv\", arg);\n    }\n  else\n    {\n      double tol = 0.0;\n      if (nargin == 2)\n        tol = args(1).double_value ();\n\n      if (tol < 0.0)\n        error (\"pinv: TOL must be greater than zero\");\n\n      if (arg.isreal ())\n        {\n          Matrix m = arg.matrix_value ();\n\n          retval = m.pseudo_inverse (tol);\n        }\n      else if (arg.iscomplex ())\n        {\n          ComplexMatrix m = arg.complex_matrix_value ();\n\n          retval = m.pseudo_inverse (tol);\n        }\n      else\n        err_wrong_type_arg (\"pinv\", arg);\n    }\n\n  return retval;\n}\n\n/*\n%!shared a, b, tol, hitol, d, u, x, y\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 42); # initialize generator to make behavior reproducible\n%! a = reshape (rand*[1:16], 4, 4);  # Rank 2 matrix\n%! b = pinv (a);\n%! tol = 4e-14;\n%! hitol = 40* sqrt (eps);\n%! d = diag ([rand, rand, hitol, hitol]);\n%! u = rand (4);                     # Could be singular by freak accident\n%! x = inv (u)*d*u;\n%! y = pinv (x, sqrt (eps));\n\n## Verify Penrose conditions for pseudoinverse\n%!assert (a*b*a, a, tol)\n%!assert (b*a*b, b, tol)\n%!assert ((b*a)', b*a, tol)\n%!assert ((a*b)', a*b, tol)\n%!assert (x*y*x, x, -hitol)\n%!assert (y*x*y, y, -hitol)\n%!assert ((x*y)', x*y, hitol)\n%!assert ((y*x)', y*x, hitol)\n\n## Clear shared variables\n%!shared\n\n## Test pinv for Diagonal matrices\n%!test\n%! x = diag ([3 2 1 0 -0.5]);\n%! y = pinv (x);\n%! assert (typeinfo (y)(1:8), \"diagonal\");\n%! assert (isa (y, \"double\"));\n%! assert (diag (y), [1/3, 1/2, 1, 0  1/-0.5]');\n%! y = pinv (x, 1);\n%! assert (diag (y), [1/3 1/2 1 0 0]');\n%! y = pinv (x, 2);\n%! assert (diag (y), [1/3 1/2 0 0 0]');\n\n## Basic test for integer inputs\n%!assert (pinv (int32 (2)), 0.5)\n%!assert (pinv (uint32 (2)), 0.5)\n%!assert (pinv (int64 (2)), 0.5)\n%!assert (pinv (uint64 (2)), 0.5)\n\n## Test special case of 0 scalars and vectors\n%!assert (pinv (0), 0)\n%!assert (pinv ([0, 0, 0]), [0; 0; 0])\n%!assert (pinv (single (0)), single (0))\n%!assert (pinv (single ([0, 0, 0])), single ([0; 0; 0]))\n%!assert (pinv (complex (0,0)), 0)\n%!assert (pinv (complex ([0,0,0], [0,0,0])), [0; 0; 0])\n%!assert (pinv (complex (single (0),0)), single (0))\n%!assert (pinv (complex (single ([0,0,0]), [0,0,0])), single ([0; 0; 0]))\n\n## Test input validation\n%!error <wrong type argument> pinv (\"Hello World\")\n%!error <wrong type argument> pinv ({1})\n%!error <wrong type argument> pinv (true)\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/pow2.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2022-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include \"lo-array-errwarn.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n\n// FIXME: According to cppreference.com the implementation of `ldexp (f, e)`\n// might be less efficient that the corresponding `f * exp2 (e)`.  Consider\n// replacing our implementation with the latter.\n\ntemplate <typename T>\nvoid\nmap_2_xldexp (Array<T>& y, const Array<T>& f, const Array<T>& e)\n{\n  if (f.numel () == e.numel () || e.numel () == 1)\n    y = Array<T> (f.dims ());\n  else if (f.numel () == 1)\n    y = Array<T> (e.dims ());\n  else\n    octave::err_nonconformant (\"pow2\", f.dims (), e.dims ());\n\n  octave_idx_type f_inc = (f.numel () == 1) ? 0 : 1;\n  octave_idx_type e_inc = (e.numel () == 1) ? 0 : 1;\n\n  for (octave_idx_type i = 0; i < y.numel (); i++)\n    y.xelem (i) = std::ldexp (f.xelem (i * f_inc),\n                              static_cast<int> (e.xelem (i * e_inc)));\n}\n\nvoid\nmap_2_xldexp_sparse (SparseMatrix& y, const SparseMatrix& f,\n                     const SparseMatrix& e)\n{\n  if (e.numel () == 1)\n    {\n      int ee = static_cast<int> (e.data (0));\n      for (octave_idx_type i = 0; i < y.nnz (); i++)\n        y.data (i) = std::ldexp (f.data (i), ee);\n    }\n  else if (f.numel () == e.numel ())\n    {\n      octave_idx_type col = 1;\n      for (octave_idx_type i = 0; i < y.nnz (); i++)\n        {\n          // Determine current column.\n          while (i >= f.cidx (col))\n            col++;\n          int ee = static_cast<int> (e.xelem (f.ridx (i), col - 1));\n          y.data (i) = std::ldexp (f.data (i), ee);\n        }\n    }\n  else\n    octave::err_nonconformant (\"pow2\", f.dims (), e.dims ());\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (pow2, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} pow2 (@var{x})\n@deftypefnx {} {@var{y} =} pow2 (@var{f}, @var{e})\nWith one input argument, compute\n@tex\n$y = 2^x$\n@end tex\n@ifnottex\ny = 2 .^ x\n@end ifnottex\nfor each element of @var{x}.\n\nWith two input arguments, return\n@tex\n$y = f \\cdot 2^e$,\n@end tex\n@ifnottex\ny = f .* (2 .^ e).\n@end ifnottex\nwhere for complex inputs only the real part of both inputs is regarded\nand from @var{e} only the real integer part.  This calling form corresponds\nto C/C++ standard function @code{ldexp()}.\n@seealso{log2, nextpow2, power}\n@end deftypefn */)\n{\n  if (args.length () < 1 || args.length () > 2)\n    print_usage ();\n\n  if (! args(0).isfloat ())\n    err_wrong_type_arg (\"pow2\", args(0));\n\n  // Call exp2(f) where possible for numerical more accurate results.\n  if (args.length () == 1)\n    {\n      if (args(0).iscomplex ())\n        {\n          // The C++ standard does not define exp2 for complex arguments.\n          // Therefore call `2.^x`.\n          octave_value retval = octave::binary_op (octave_value::op_el_pow,\n                                2, args(0));\n\n          // Preserve sparse datatype, but even for sparse input fill-up\n          // is unavoidable `2^0 == 1` thus cast only.\n          if (args(0).issparse ())\n            retval = octave_value (retval.sparse_complex_matrix_value ());\n\n          return ovl (retval);\n        }\n      else if (args(0).is_single_type ())\n        {\n          FloatNDArray x = args(0).float_array_value ();\n          FloatNDArray y (x.dims ());\n          for (octave_idx_type i = 0; i < y.numel (); i++)\n            y.xelem (i) = std::exp2 (x.xelem (i));\n          return ovl (y);\n        }\n      else\n        {\n          NDArray x = args(0).array_value ();\n          NDArray y (x.dims ());\n          for (octave_idx_type i = 0; i < y.numel (); i++)\n            y.xelem (i) = std::exp2 (x.xelem (i));\n\n          // Preserve sparse datatype, but even for sparse input fill-up\n          // is unavoidable `2^0 == 1` thus cast only.\n          if (args(0).issparse ())\n            return ovl (SparseMatrix (y));\n          else\n            return ovl (y);\n        }\n    }\n\n  // For Matlab compatibility, the two argument call `y = pow2 (f, e)`\n  // corresponds to std::ldexp() (see bug #61968).  The resulting y is\n  // computed quickly by adding the integer part of e to the floating-point\n  // exponent of f.\n\n  if (! args(1).isfloat ())\n    err_wrong_type_arg (\"pow2\", args(1));\n\n  if (args(0).iscomplex () || args(1).iscomplex ())\n    warning_with_id (\"Octave:pow2:imaginary-ignored\",\n                     \"pow2: imaginary part is ignored\");\n\n  // Note: Matlab R2021a errors on `pow2 (sparse (f), single (e))`,\n  //       but sparsity in f determines output and can significantly\n  //       reduce computation, e.g., `N=1e5; pow2(speye(N),sparse(N,N))`.\n  if (args(0).issparse ())\n    {\n      SparseMatrix f = args(0).sparse_matrix_value ();\n\n      // Special case: return a sparse zero matrix in size of e.\n      if ((f.numel () == 1) && (f.nnz () == 0))\n        return ovl (SparseMatrix (args(1).rows (), args(1).columns ()));\n\n      // Only do sparse computation, if it pays off.  For scalar f fill-up\n      // is unavoidable even for sparse e because `f * 2^0 == f`.  Use dense\n      // code below in this case.\n      if (f.numel () > 1)\n        {\n          SparseMatrix e = args(1).sparse_matrix_value ();\n          SparseMatrix y = SparseMatrix (f);\n          map_2_xldexp_sparse (y, f, e);\n          return ovl (y);\n        }\n    }\n\n  if (args(0).is_single_type () || args(1).is_single_type ())\n    {\n      FloatNDArray f = args(0).float_array_value ();\n      FloatNDArray e = args(1).float_array_value ();\n      FloatNDArray y;\n      map_2_xldexp (y, f, e);\n      return ovl (y);\n    }\n  else\n    {\n      NDArray f = args(0).array_value ();\n      NDArray e = args(1).array_value ();\n      NDArray y;\n      map_2_xldexp (y, f, e);\n\n      // Preserve sparse datatype.\n      // Cases for efficient use of sparsity were treated above already.\n      if (args(0).issparse ())\n        return ovl (SparseMatrix (y));\n      else\n        return ovl (y);\n    }\n}\n\n/*\n## Call `y = pow2 (x)`\n\n%!test\n%! fcns = {@double, @single, @complex};\n%! x = [3, 0, -3];\n%! v = [8, 1, .125];\n%! for i = 1:numel (fcns)\n%!   fcn = fcns{i};\n%!   assert (pow2 (fcn (x)), fcn (v), sqrt (eps));\n%! endfor\n\n%!test\n%! fcns = {@double, @single, @complex, @sparse};\n%! x = [3, 1, -3];\n%! v = [8, 2, .125];\n%! for i = 1:numel (fcns)\n%!   fcn = fcns{i};\n%!   assert (pow2 (fcn (x)), fcn (v), sqrt (eps));\n%! endfor\n\n%!test\n%! fcns = {@double, @single, @complex, @sparse};\n%! x = [1, 1+1i, 1i];\n%! for i = 1:numel (fcns)\n%!   fcn = fcns{i};\n%!   assert (pow2 (fcn (x)), fcn (2) .^ fcn (x), sqrt (eps));\n%! endfor\n\n## Call `y = pow2 (f, e)`\n\n%!test\n%! fcns = {@double, @single, @complex, @sparse};\n%! f = [2 2];\n%! e = [2 2];\n%! z = [8 8];\n%! warning (\"off\", \"Octave:pow2:imaginary-ignored\", \"local\");\n%! for i = 1:numel (fcns)\n%!   fcn = fcns{i};\n%!   assert (pow2 (fcn (f), fcn (e)), real (fcn (z)));\n%! endfor\n\n## Only integer part is taken into account.\n%!test\n%! f = 2;\n%! e = [2, 2.1, 2.2, 2.4, 2.5, 2.8];\n%! z = 8 .* ones (1, length (e));\n%! assert (pow2 (f, e), z);\n\n## Only real part is taken into account.\n%!test\n%! f = [1+1i, 1];\n%! e = 2;\n%! z = [4, 4];\n%! warning (\"off\", \"Octave:pow2:imaginary-ignored\", \"local\");\n%! assert (pow2 (f, e), z);\n\n%!test\n%! f = 1;\n%! e = [1+1i, 1];\n%! z = [2, 2];\n%! warning (\"off\", \"Octave:pow2:imaginary-ignored\", \"local\");\n%! assert (pow2 (f, e), z);\n\n%!test\n%! f = [1/2, pi/4, -3/4, 1/2, 1-eps()/2, 1/2];\n%! e = [1, 2, 2, -51, 1024, -1021];\n%! z = [1, pi, -3, eps(), realmax(), realmin()];\n%! assert (pow2 (f, e), z);\n\n## Tests for sparsity.\n%!assert (pow2 (sparse (0), ones  (3)), sparse (3, 3))\n%!assert (pow2 (sparse (1), ones  (3)), 2 .* sparse (ones (3)))\n%!assert (pow2 (sparse (1), speye (3)), sparse (ones (3) + eye (3)))\n%!assert (pow2 (sparse (3, 3), ones (3)), sparse (3, 3))\n%!assert (pow2 (speye (3), ones (3)), 2 .* speye (3))\n%!assert (pow2 (speye (3), 1),        2 .* speye (3))\n\n%!test\n%! f = speye (3);\n%! e = sparse (3, 3);\n%! e(1,1) = 1;\n%! e(1,3) = 1;\n%! z = f;\n%! z(1,1) = 2;\n%! assert (pow2 (f, e), z);\n\n## Large sparse matrix (only few real elements).\n%!test\n%! ## FIXME: `N = 1e5` would be a better test, but `assert` fills-up somehow.\n%! N = 1e3;\n%! assert (pow2 (speye  (N), sparse (N,N)), speye (N));\n%! assert (pow2 (sparse (0), speye  (N)),   sparse(N,N));\n\n%!error <Invalid call> pow2 ()\n%!error <Invalid call> pow2 (1,2,3)\n%!error <wrong type argument> pow2 (int8 (1))\n%!error <wrong type argument> pow2 (2, int8 (1))\n%!warning <imaginary part is ignored> pow2 (i, 2);\n%!warning <imaginary part is ignored> pow2 (2, i);\n%!error <pow2: nonconformant arguments> pow2 ([1,2], [3,4,5])\n%!error <pow2: nonconformant arguments> pow2 (sparse ([1,2]), sparse ([3,4,5]))\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/psi.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-specfun.h\"\n\n#include \"ov.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (psi, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{y} =} psi (@var{z})\n@deftypefnx {} {@var{y} =} psi (@var{k}, @var{z})\nCompute the psi (polygamma) function.\n\nThe polygamma functions are the @var{k}th derivative of the logarithm\nof the gamma function.  If unspecified, @var{k} defaults to zero.  A value\nof zero computes the digamma function, a value of 1, the trigamma function,\nand so on.\n\nThe digamma function is defined:\n@tex\n$$\n\\Psi (z) = {d (log (\\Gamma (z))) \\over dx}\n$$\n@end tex\n@ifnottex\n\n@example\n@group\npsi (z) = d (log (gamma (z))) / dx\n@end group\n@end example\n\n@end ifnottex\n\nWhen computing the digamma function (when @var{k} equals zero), @var{z}\ncan have any value real or complex value.  However, for polygamma functions\n(@var{k} higher than 0), @var{z} must be real and non-negative.\n\n@seealso{gamma, gammainc, gammaln}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  const octave_value oct_z = (nargin == 1) ? args(0) : args(1);\n  const octave_idx_type k = (nargin == 1) ? 0 : args(0).strict_idx_type_value (\"psi: K must be an integer\");\n  if (k < 0)\n    error (\"psi: K must be non-negative\");\n\n  octave_value retval;\n\n  if (k == 0)\n    {\n#define FLOAT_BRANCH(T, A, M, E)                                \\\n      if (oct_z.is_ ## T ##_type ())                            \\\n        {                                                       \\\n          const A ## NDArray z = oct_z.M ## array_value ();     \\\n          A ## NDArray psi_z (z.dims ());                       \\\n                                                                \\\n          const E *zv = z.data ();                              \\\n          E *psi_zv = psi_z.rwdata ();                     \\\n          const octave_idx_type n = z.numel ();                 \\\n          for (octave_idx_type i = 0; i < n; i++)               \\\n            *psi_zv++ = math::psi (*zv++);              \\\n                                                                \\\n          retval = psi_z;                                       \\\n        }\n\n      if (oct_z.iscomplex ())\n        {\n          FLOAT_BRANCH(double, Complex, complex_, Complex)\n          else FLOAT_BRANCH(single, FloatComplex, float_complex_, FloatComplex)\n            else\n              error (\"psi: Z must be a floating point\");\n        }\n      else\n        {\n          FLOAT_BRANCH(double,,, double)\n          else FLOAT_BRANCH(single, Float, float_, float)\n            else\n              error (\"psi: Z must be a floating point\");\n        }\n\n#undef FLOAT_BRANCH\n    }\n  else\n    {\n      if (! oct_z.isreal ())\n        error (\"psi: Z must be real value for polygamma (K > 0)\");\n\n#define FLOAT_BRANCH(T, A, M, E)                                        \\\n      if (oct_z.is_ ## T ##_type ())                                    \\\n        {                                                               \\\n          const A ## NDArray z = oct_z.M ## array_value ();             \\\n          A ## NDArray psi_z (z.dims ());                               \\\n                                                                        \\\n          const E *zv = z.data ();                                      \\\n          E *psi_zv = psi_z.rwdata ();                             \\\n          const octave_idx_type n = z.numel ();                         \\\n          for (octave_idx_type i = 0; i < n; i++)                       \\\n            {                                                           \\\n              if (*zv < 0)                                              \\\n                error (\"psi: Z must be non-negative for polygamma (K > 0)\"); \\\n                                                                        \\\n              *psi_zv++ = math::psi (k, *zv++);                         \\\n            }                                                           \\\n          retval = psi_z;                                               \\\n        }\n\n      FLOAT_BRANCH(double,,, double)\n      else FLOAT_BRANCH(single, Float, float_, float)\n        else\n          error (\"psi: Z must be a floating point for polygamma (K > 0)\");\n\n#undef FLOAT_BRANCH\n    }\n\n  return retval;\n}\n\n/*\n%!shared em\n%! em = 0.577215664901532860606512090082402431042; # Euler-Mascheroni Constant\n\n%!assert (psi (ones (7, 3, 5)), repmat (-em, [7 3 5]))\n%!assert (psi ([0 1]), [-Inf -em])\n%!assert (psi ([-20:1]), [repmat(-Inf, [1 21]) -em])\n%!assert (psi (single ([0 1])), single ([-Inf -em]))\n\n## Abramowitz and Stegun, page 258, eq 6.3.5\n%!test\n%! z = [-100:-1 1:200] ./ 10; # drop the 0\n%! assert (psi (z + 1), psi (z) + 1 ./ z, eps*1000);\n\n## Abramowitz and Stegun, page 258, eq 6.3.2\n%!assert (psi (1), -em)\n\n## Abramowitz and Stegun, page 258, eq 6.3.3\n%!assert (psi (1/2), -em - 2 * log (2))\n\n## The following tests are from Pascal Sebah and Xavier Gourdon (2002)\n## \"Introduction to the Gamma Function\"\n\n## Interesting identities of the digamma function, in section of 5.1.3\n%!assert (psi (1/3), - em - (3/2) * log (3) - ((sqrt (3) / 6) * pi), eps*10)\n%!assert (psi (1/4), - em -3 * log (2) - pi/2, eps*10)\n%!assert (psi (1/6),\n%!        - em -2 * log (2) - (3/2) * log (3) - ((sqrt (3) / 2) * pi), eps*10)\n\n## First 6 zeros of the digamma function, in section of 5.1.5 (and also on\n## Abramowitz and Stegun, page 258, eq 6.3.19)\n%!assert (psi ( 1.46163214496836234126265954232572132846819620400644), 0, eps)\n%!assert (psi (-0.504083008264455409258269304533302498955385182368579), 0, eps*2)\n%!assert (psi (-1.573498473162390458778286043690434612655040859116846), 0, eps*2)\n%!assert (psi (-2.610720868444144650001537715718724207951074010873480), 0, eps*10)\n%!assert (psi (-3.635293366436901097839181566946017713948423861193530), 0, eps*10)\n%!assert (psi (-4.653237761743142441714598151148207363719069416133868), 0, eps*100)\n\n## Tests for complex values\n%!shared z\n%! z = [-100:-1 1:200] ./ 10; # drop the 0\n\n## Abramowitz and Stegun, page 259 eq 6.3.10\n%!assert (real (psi (i*z)), real (psi (1 - i*z)))\n\n## Abramowitz and Stegun, page 259 eq 6.3.11\n%!assert (imag (psi (i*z)), 1/2 .* 1./z + 1/2 * pi * coth (pi * z), eps *10)\n\n## Abramowitz and Stegun, page 259 eq 6.3.12\n%!assert (imag (psi (1/2 + i*z)), 1/2 * pi * tanh (pi * z), eps*10)\n\n## Abramowitz and Stegun, page 259 eq 6.3.13\n%!assert (imag (psi (1 + i*z)), - 1./(2*z) + 1/2 * pi * coth (pi * z), eps*10)\n\n## Abramowitz and Stegun, page 260 eq 6.4.5\n%!test\n%! for z = 0:20\n%!   assert (psi (1, z + 0.5),\n%!           0.5 * (pi^2) - 4 * sum ((2*(1:z) -1) .^(-2)),\n%!           eps*10);\n%! endfor\n\n## Abramowitz and Stegun, page 260 eq 6.4.6\n%!test\n%! z = 0.1:0.1:20;\n%! for n = 0:8\n%!   ## our precision goes down really quick when computing n is too high.\n%!   assert (psi (n, z+1),\n%!           psi (n, z) + ((-1)^n) * factorial (n) * (z.^(-n-1)), 0.1);\n%! endfor\n\n## Test input validation\n%!error psi ()\n%!error psi (1, 2, 3)\n%!error <Z must be> psi (\"non numeric\")\n%!error <K must be an integer> psi ({5.3}, 1)\n%!error <K must be non-negative> psi (-5, 1)\n%!error <Z must be non-negative for polygamma> psi (5, -1)\n%!error <Z must be a floating point> psi (5, uint8 (-1))\n%!error <Z must be real value for polygamma> psi (5, 5i)\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/qr.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"MArray.h\"\n#include \"Matrix.h\"\n#include \"qr.h\"\n#include \"qrp.h\"\n#include \"sparse-qr.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename MT>\nstatic octave_value\nget_qr_r (const math::qr<MT>& fact)\n{\n  MT R = fact.R ();\n  if (R.issquare () && fact.regular ())\n    return octave_value (R, MatrixType (MatrixType::Upper));\n  else\n    return R;\n}\n\ntemplate <typename T>\nstatic typename math::qr<T>::type\nqr_type (int nargout, bool economy)\n{\n  if (nargout == 0 || nargout == 1)\n    return math::qr<T>::raw;\n  else if (economy)\n    return math::qr<T>::economy;\n  else\n    return math::qr<T>::std;\n}\n\n// dense X\n//\n// [Q, R] = qr (X):       form Q unitary and R upper triangular such\n//                        that Q * R = X\n//\n// [Q, R] = qr (X, 0):    form the economy decomposition such that if X is\n//                        m by n then only the first n columns of Q are\n//                        computed.\n//\n// [Q, R, P] = qr (X):    form QRP factorization of X where\n//                        P is a permutation matrix such that\n//                        A * P = Q * R\n//\n// [Q, R, P] = qr (X, 0): form the economy decomposition with\n//                        permutation vector P such that Q * R = X(:, P)\n//\n// qr (X) alone returns the output of the LAPACK routine dgeqrf, such\n// that R = triu (qr (X))\n//\n// sparse X\n//\n// X = qr (A, B):         if M < N, X is the minimum 2-norm solution of\n//                        A\\B.  If M >= N, X is the least squares\n//                        approximation of A\\B.  X is calculated by\n//                        SPQR-function SuiteSparseQR_min2norm.\n//\nDEFUN (qr, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{Q}, @var{R}] =} qr (@var{A})\n@deftypefnx {} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A})\n@deftypefnx {} {@var{R} =} qr (@var{A})\n@deftypefnx {} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B})\n@deftypefnx {} {[@var{C}, @var{R}, @var{P}] =} qr (@var{A}, @var{B})\n@deftypefnx {} {@var{X} =} qr (@var{A}, @var{B})  # sparse only\n@deftypefnx {} {[@dots{}] =} qr (@dots{}, \"econ\")\n@deftypefnx {} {[@dots{}] =} qr (@dots{}, \"vector\")\n@deftypefnx {} {[@dots{}] =} qr (@dots{}, \"matrix\")\n@deftypefnx {} {[@dots{}] =} qr (@dots{}, 0)\n@cindex QR factorization\nCompute the QR@tie{}factorization of @var{A}.\n\nThe QR@tie{}factorization is\n@tex\n$QR = A$ where $Q$ is an orthogonal matrix and $R$ is upper triangular.\n@end tex\n@ifnottex\n\n@example\n@var{Q} * @var{R} = @var{A}\n@end example\n\n@noindent\nwhere @var{Q} is an orthogonal matrix and @var{R} is upper triangular.\n@end ifnottex\n\nFor example, given the matrix @code{@var{A} = [1, 2; 3, 4]},\n\n@example\n[@var{Q}, @var{R}] = qr (@var{A})\n@end example\n\n@noindent\nreturns\n\n@example\n@group\n@var{Q} =\n\n  -0.31623  -0.94868\n  -0.94868   0.31623\n\n@var{R} =\n\n  -3.16228  -4.42719\n   0.00000  -0.63246\n@end group\n@end example\n\n@noindent\nwhich multiplied together return the original matrix\n\n@example\n@group\n@var{Q} * @var{R}\n  @xresult{}\n     1.0000   2.0000\n     3.0000   4.0000\n@end group\n@end example\n\nIf just @strong{one return value} is requested then it is @var{R}.  (Note:\nunlike most commands, the single return value is not the first return value when\nmultiple values are requested.)\n\nIf a third output @var{P} is requested, then @code{qr} calculates the permuted\nQR@tie{}factorization\n@tex\n$QR = AP$ where $Q$ is an orthogonal matrix, $R$ is upper triangular, and $P$\nis a permutation matrix.\n@end tex\n@ifnottex\n\n@example\n@var{Q} * @var{R} = @var{A} * @var{P}\n@end example\n\n@noindent\nwhere @var{Q} is an orthogonal matrix, @var{R} is upper triangular, and\n@var{P} is a permutation matrix.\n@end ifnottex\n\nIf @var{A} is dense, the QR@tie{}factorization is computed using standard\n@sc{lapack} subroutines.  In this case, the permuted factorization has the\nadditional property that the diagonal entries of @var{R} are ordered by\ndecreasing magnitude.  In other words, @code{abs (diag (@var{R}))} will be\nordered from largest to smallest.\n\nIf @var{A} is sparse, @var{P} is a fill-reducing ordering of the columns of\n@var{A}.  In that case, the diagonal entries of @var{R} are not ordered by\ndecreasing magnitude.\n\nFor example, given the matrix @code{@var{A} = [1, 2; 3, 4]},\n\n@example\n[@var{Q}, @var{R}, @var{P}] = qr (@var{A})\n@end example\n\n@noindent\nreturns\n\n@example\n@group\n@var{Q} =\n\n  -0.44721  -0.89443\n  -0.89443   0.44721\n\n@var{R} =\n\n  -4.47214  -3.13050\n   0.00000   0.44721\n\n@var{P} =\n\n   0  1\n   1  0\n@end group\n@end example\n\nIf the input matrix @var{A} is sparse, the sparse QR@tie{}factorization\nis computed by using @sc{SPQR} or @sc{cxsparse} (e.g., if @sc{SPQR} is not\navailable).  Because the matrix @var{Q} is, in general, a full matrix, it is\nrecommended to request only one return value @var{R}.  In that case, the\ncomputation avoids the construction of @var{Q} and returns a sparse @var{R}\nsuch that @w{@code{@var{R} = chol (@var{A}' * @var{A})}}.\n\nIf @var{A} is dense, and an additional input matrix @var{B} is supplied, and\ntwo return values are requested, then @code{qr} returns @var{C}, where\n@w{@code{@var{C} = @var{Q}' * @var{B}}}.  This allows the least squares\napproximation of @w{@code{@var{A} \\ @var{B}}} to be calculated as\n\n@example\n@group\n[@var{C}, @var{R}] = qr (@var{A}, @var{B})\n@var{X} = @var{R} \\ @var{C}\n@end group\n@end example\n\nIf @var{A} is a sparse @nospell{MxN} matrix and an additional matrix @var{B} is\nsupplied, one or two return values are possible.  If one return value @var{X}\nis requested and @w{M < N}, then @var{X} is the minimum 2-norm solution of\n@w{@code{@var{A} \\ @var{B}}}.  If @w{M >= N}, @var{X} is the least squares\napproximation of @w{@code{@var{A} \\ @var{B}}}.  If two return values are\nrequested, @var{C} and @var{R} have the same meaning as in the dense case\n(@var{C} is dense and @var{R} is sparse).  The version with one return\nparameter should be preferred because it uses less memory and can handle\nrank-deficient matrices better.\n\nIf the final argument is the string @qcode{\"vector\"} then @var{P} is a\npermutation vector (of the columns of @var{A}) instead of a permutation matrix.\nIn this case, the defining relationship is:\n\n@example\n@var{Q} * @var{R} = @var{A}(:, @var{P})\n@end example\n\nThe default, however, is to return a permutation matrix and this may be\nexplicitly specified by using a final argument of @qcode{\"matrix\"}.\n\nWhen the optional argument is the string @qcode{\"econ\"}, an economy\nfactorization is returned.  If the original matrix @var{A} has size\n@nospell{MxN} and @w{M > N}, then the economy factorization will calculate just\nN rows in @var{R} and N columns in @var{Q} and omit the zeros in @var{R}.  If\n@w{M @leq{} N}, there is no difference between the economy and standard\nfactorizations.\n\nIf the optional argument is the numeric value @code{0} then @code{qr} acts as\nif the @qcode{\"econ\"} and @qcode{\"vector\"} arguments were both given.\n@strong{Warning:} This syntax is accepted, but no longer recommended and may\nbe removed in the future.  Use @qcode{\"econ\"} instead.\n\nBackground: The QR factorization has applications in the solution of least\nsquares problems\n@tex\n$$\n\\min_x \\left\\Vert A x - b \\right\\Vert_2\n$$\n@end tex\n@ifnottex\n\n@example\nmin norm (A*x - b)\n@end example\n\n@end ifnottex\nfor overdetermined systems of equations (i.e.,\n@tex\n$A$\n@end tex\n@ifnottex\n@var{A}\n@end ifnottex\nis a tall, thin matrix).\n\nThe permuted QR@tie{}factorization\n@w{@code{[@var{Q}, @var{R}, @var{P}] = qr (@var{A})}} allows the construction\nof an orthogonal basis of @code{span (A)}.\n\n@seealso{chol, hess, lu, qz, schur, svd, qrupdate, qrinsert, qrdelete, qrshift}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  if (nargout > 3)\n    error (\"qr: too many output arguments\");\n\n  octave_value_list retval;\n\n  octave_value arg = args(0);\n\n  bool economy = false;\n  bool is_cmplx = false;\n  bool have_b = false;\n  bool vector_p = false;\n\n  if (arg.iscomplex ())\n    is_cmplx = true;\n  if (nargin > 1)\n    {\n      have_b = true;\n      if (args(nargin-1).is_scalar_type ())\n        {\n          int val = args(nargin-1).int_value ();\n          if (val == 0)\n            {\n              economy = true;\n              vector_p = true;\n              have_b = (nargin > 2);\n            }\n          else if (nargin == 3)   // argument 3 should be 0 or a string\n            print_usage ();\n        }\n      else if (args(nargin-1).is_string ())\n        {\n          std::string str = args(nargin-1).string_value ();\n          if (str == \"econ\")\n            economy = true;\n          else if (str == \"vector\")\n            vector_p = true;\n          else if (str != \"matrix\")\n            error (\"qr: option string must be 'econ' or 'matrix' or 'vector', not \\\"%s\\\"\", str.c_str ());\n          have_b = (nargin > 2);\n        }\n      else if (! args(nargin-1).isnumeric ())\n        err_wrong_type_arg (\"qr\", args(nargin-1));\n      else if (nargin == 3)   // should be caught by is_scalar_type or is_string\n        print_usage ();\n\n      if (have_b && ! args(1).isnumeric ())\n        print_usage ();\n\n      if (have_b && args(1).iscomplex ())\n        is_cmplx = true;\n    }\n\n  if (arg.issparse ())\n    {\n      if (is_cmplx)\n        {\n          if (have_b && nargout == 1)\n            {\n              octave_idx_type info;\n\n              if (! args(1).issparse () && args(1).iscomplex ())\n                retval = ovl\n                         (math::sparse_qr<SparseComplexMatrix>::solve\n                          <MArray<Complex>, ComplexMatrix>\n                          (arg.sparse_complex_matrix_value (),\n                           args(1).complex_matrix_value (), info));\n              else if (args(1).issparse () && args(1).iscomplex ())\n                retval = ovl\n                         (math::sparse_qr<SparseComplexMatrix>::solve\n                          <SparseComplexMatrix, SparseComplexMatrix>\n                          (arg.sparse_complex_matrix_value (),\n                           args(1).sparse_complex_matrix_value (), info));\n              else if (! args(1).issparse () && ! args(1).iscomplex ())\n                retval = ovl\n                         (math::sparse_qr<SparseComplexMatrix>::solve\n                          <MArray<double>, ComplexMatrix>\n                          (arg.sparse_complex_matrix_value (),\n                           args(1).matrix_value (), info));\n              else if (args(1).issparse () && ! args(1).iscomplex ())\n                retval = ovl\n                         (math::sparse_qr<SparseComplexMatrix>::solve\n                          <SparseMatrix, SparseComplexMatrix>\n                          (arg.sparse_complex_matrix_value (),\n                           args(1).sparse_matrix_value (), info));\n            }\n          else if (have_b && nargout == 2)\n            {\n              math::sparse_qr<SparseComplexMatrix>\n              q (arg.sparse_complex_matrix_value (), 0);\n              retval = ovl (q.C (args(1).complex_matrix_value (), economy),\n                            q.R (economy));\n            }\n          else if (have_b && nargout == 3)\n            {\n              math::sparse_qr<SparseComplexMatrix>\n              q (arg.sparse_complex_matrix_value ());\n              if (vector_p)\n                retval = ovl (q.C (args(1).complex_matrix_value (), economy),\n                              q.R (economy), q.E ().transpose ());\n              else\n                retval = ovl (q.C (args(1).complex_matrix_value (), economy),\n                              q.R (economy), q.E_MAT ());\n            }\n          else\n            {\n              if (nargout > 2)\n                {\n                  math::sparse_qr<SparseComplexMatrix>\n                  q (arg.sparse_complex_matrix_value ());\n                  if (vector_p)\n                    retval = ovl (q.Q (economy), q.R (economy),\n                                  q.E ().transpose ());\n                  else\n                    retval = ovl (q.Q (economy), q.R (economy),\n                                  q.E_MAT ());\n                }\n              else if (nargout > 1)\n                {\n                  math::sparse_qr<SparseComplexMatrix>\n                  q (arg.sparse_complex_matrix_value (), 0);\n                  retval = ovl (q.Q (economy), q.R (economy));\n                }\n              else\n                {\n                  math::sparse_qr<SparseComplexMatrix>\n                  q (arg.sparse_complex_matrix_value (), 0);\n                  retval = ovl (q.R (economy));\n                }\n            }\n        }\n      else\n        {\n          if (have_b && nargout == 1)\n            {\n              octave_idx_type info;\n              if (args(1).issparse () && ! args(1).iscomplex ())\n                retval = ovl (math::sparse_qr<SparseMatrix>::solve\n                              <SparseMatrix, SparseMatrix>\n                              (arg.sparse_matrix_value (),\n                               args (1).sparse_matrix_value (), info));\n              else if (! args(1).issparse () && args(1).iscomplex ())\n                retval = ovl (math::sparse_qr<SparseMatrix>::solve\n                              <MArray<Complex>, ComplexMatrix>\n                              (arg.sparse_matrix_value (),\n                               args (1).complex_matrix_value (), info));\n              else if (! args(1).issparse () && ! args(1).iscomplex ())\n                retval = ovl (math::sparse_qr<SparseMatrix>::solve\n                              <MArray<double>, Matrix>\n                              (arg.sparse_matrix_value (),\n                               args (1).matrix_value (), info));\n              else if (args(1).issparse () &&  args(1).iscomplex ())\n                retval = ovl (math::sparse_qr<SparseMatrix>::solve\n                              <SparseComplexMatrix, SparseComplexMatrix>\n                              (arg.sparse_matrix_value (),\n                               args(1).sparse_complex_matrix_value (),\n                               info));\n            }\n          else if (have_b && nargout == 2)\n            {\n              math::sparse_qr<SparseMatrix>\n              q (arg.sparse_matrix_value (), 0);\n              retval = ovl (q.C (args(1).matrix_value (), economy),\n                            q.R (economy));\n            }\n          else if (have_b && nargout == 3)\n            {\n              math::sparse_qr<SparseMatrix>\n              q (arg.sparse_matrix_value ());\n              if (vector_p)\n                retval = ovl (q.C (args(1).matrix_value (), economy),\n                              q.R (economy), q.E ().transpose ());\n              else\n                retval = ovl (q.C (args(1).matrix_value (), economy),\n                              q.R (economy), q.E_MAT ());\n            }\n\n          else\n            {\n              if (nargout > 2)\n                {\n                  math::sparse_qr<SparseMatrix>\n                  q (arg.sparse_matrix_value ());\n                  if (vector_p)\n                    retval = ovl (q.Q (economy), q.R (economy),\n                                  q.E ().transpose ());\n                  else\n                    retval = ovl (q.Q (economy), q.R (economy),\n                                  q.E_MAT ());\n                }\n              else if (nargout > 1)\n                {\n                  math::sparse_qr<SparseMatrix>\n                  q (arg.sparse_matrix_value (), 0);\n                  retval = ovl (q.Q (economy), q.R (economy));\n                }\n              else\n                {\n                  math::sparse_qr<SparseMatrix>\n                  q (arg.sparse_matrix_value (), 0);\n                  retval = ovl (q.R (economy));\n                }\n            }\n        }\n    }\n  else\n    {\n      if (have_b && nargout > 2)\n        error (\"qr: too many output arguments when called with A and B\");\n\n      if (arg.is_single_type ())\n        {\n          if (arg.isreal ())\n            {\n              math::qr<FloatMatrix>::type type\n                = qr_type<FloatMatrix> (nargout, economy);\n\n              FloatMatrix m = arg.float_matrix_value ();\n\n              switch (nargout)\n                {\n                case 0:\n                case 1:\n                  {\n                    math::qr<FloatMatrix> fact (m, type);\n                    retval = Ftriu (ovl (fact.R ()));\n                  }\n                  break;\n\n                case 2:\n                  {\n                    math::qr<FloatMatrix> fact (m, type);\n                    retval = ovl (fact.Q (), get_qr_r (fact));\n                    if (have_b)\n                      {\n                        if (is_cmplx)\n                          retval(0) = fact.Q ().transpose ()\n                                      * args(1).float_complex_matrix_value ();\n                        else\n                          retval(0) = fact.Q ().transpose ()\n                                      * args(1).float_matrix_value ();\n                      }\n                  }\n                  break;\n\n                default:\n                  {\n                    math::qrp<FloatMatrix> fact (m, type);\n\n                    if (vector_p)\n                      retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());\n                    else\n                      retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());\n                  }\n                  break;\n                }\n            }\n          else if (arg.iscomplex ())\n            {\n              math::qr<FloatComplexMatrix>::type type\n                = qr_type<FloatComplexMatrix> (nargout, economy);\n\n              FloatComplexMatrix m = arg.float_complex_matrix_value ();\n\n              switch (nargout)\n                {\n                case 0:\n                case 1:\n                  {\n                    math::qr<FloatComplexMatrix> fact (m, type);\n                    retval = Ftriu (ovl (fact.R ()));\n                  }\n                  break;\n\n                case 2:\n                  {\n                    math::qr<FloatComplexMatrix> fact (m, type);\n                    retval = ovl (fact.Q (), get_qr_r (fact));\n                    if (have_b)\n                      retval(0) = conj (fact.Q ().transpose ())\n                                  * args(1).float_complex_matrix_value ();\n                  }\n                  break;\n\n                default:\n                  {\n                    math::qrp<FloatComplexMatrix> fact (m, type);\n                    if (vector_p)\n                      retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());\n                    else\n                      retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());\n                  }\n                  break;\n                }\n            }\n        }\n      else\n        {\n          if (arg.isreal ())\n            {\n              math::qr<Matrix>::type type = qr_type<Matrix> (nargout, economy);\n\n              Matrix m = arg.matrix_value ();\n\n              switch (nargout)\n                {\n                case 0:\n                case 1:\n                  {\n                    math::qr<Matrix> fact (m, type);\n                    // Note: LAPACK routine returns matrix with R in\n                    // upper-triangular portion.  The lower-triangular portion\n                    // contains information about Q, but is not relevant here.\n                    // Matlab returns just upper-triangular R since v2022a.\n                    // Octave will do the same.  See bug #64861.\n                    retval = Ftriu (ovl (fact.R ()));\n                  }\n                  break;\n\n                case 2:\n                  {\n                    math::qr<Matrix> fact (m, type);\n                    retval = ovl (fact.Q (), get_qr_r (fact));\n                    if (have_b)\n                      {\n                        if (is_cmplx)\n                          retval(0) = fact.Q ().transpose ()\n                                      * args(1).complex_matrix_value ();\n                        else\n                          retval(0) = fact.Q ().transpose ()\n                                      * args(1).matrix_value ();\n                      }\n                  }\n                  break;\n\n                default:\n                  {\n                    math::qrp<Matrix> fact (m, type);\n                    if (vector_p)\n                      retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());\n                    else\n                      retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());\n                  }\n                  break;\n                }\n            }\n          else if (arg.iscomplex ())\n            {\n              math::qr<ComplexMatrix>::type type\n                = qr_type<ComplexMatrix> (nargout, economy);\n\n              ComplexMatrix m = arg.complex_matrix_value ();\n\n              switch (nargout)\n                {\n                case 0:\n                case 1:\n                  {\n                    math::qr<ComplexMatrix> fact (m, type);\n                    retval = Ftriu (ovl (fact.R ()));\n                  }\n                  break;\n\n                case 2:\n                  {\n                    math::qr<ComplexMatrix> fact (m, type);\n                    retval = ovl (fact.Q (), get_qr_r (fact));\n                    if (have_b)\n                      retval(0) = conj (fact.Q ().transpose ())\n                                  * args(1).complex_matrix_value ();\n                  }\n                  break;\n\n                default:\n                  {\n                    math::qrp<ComplexMatrix> fact (m, type);\n                    if (vector_p)\n                      retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());\n                    else\n                      retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());\n                  }\n                  break;\n                }\n            }\n          else\n            err_wrong_type_arg (\"qr\", arg);\n        }\n    }\n\n  return retval;\n}\n\n/*\n## Restore all rand* \"state\" values\n%!function restore_rand_states (state)\n%!  rand (\"state\", state.rand);\n%!  randn (\"state\", state.randn);\n%!endfunction\n\n%!shared old_state, restore_state\n%! ## Save and restore the states of both random number generators that are\n%! ## tested by the unit tests in this file.\n%! old_state.rand = rand (\"state\");\n%! old_state.randn = randn (\"state\");\n%! restore_state = onCleanup (@() restore_rand_states (old_state));\n*/\n\n/*\n%!test\n%! a = [0, 2, 1; 2, 1, 2];\n%!\n%! [q, r] = qr (a);\n%! [qe, re] = qr (a, \"econ\");\n%! [qe2, re2] = qr (a, 0);\n%!\n%! assert (q * r, a, sqrt (eps));\n%! assert (qe * re, a, sqrt (eps));\n%! assert (qe2 * re2, a, sqrt (eps));\n\n%!test\n%! a = [0, 2, 1; 2, 1, 2];\n%!\n%! [q, r, p] = qr (a);  # FIXME: not giving right dimensions.\n%! [qe, re, pe] = qr (a, \"econ\");\n%! [qe2, re2, pe2] = qr (a, 0);\n%!\n%! assert (q * r, a * p, sqrt (eps));\n%! assert (qe * re, a * pe, sqrt (eps));\n%! assert (qe2 * re2, a(:, pe2), sqrt (eps));\n\n%!test\n%! a = [0, 2; 2, 1; 1, 2];\n%!\n%! [q, r] = qr (a);\n%! [qe, re] = qr (a, \"econ\");\n%! [qe2, re2] = qr (a, 0);\n%!\n%! assert (q * r, a, sqrt (eps));\n%! assert (qe * re, a, sqrt (eps));\n%! assert (qe2 * re2, a, sqrt (eps));\n\n%!test\n%! a = [0, 2; 2, 1; 1, 2];\n%!\n%! [q, r, p] = qr (a);\n%! [qe, re, pe] = qr (a, \"econ\");\n%! [qe2, re2, pe2] = qr (a, 0);\n%!\n%! assert (q * r, a * p, sqrt (eps));\n%! assert (qe * re, a * pe, sqrt (eps));\n%! assert (qe2 * re2, a(:, pe2), sqrt (eps));\n\n%!test\n%! a = [0, 2, 1; 2, 1, 2; 3, 1, 2];\n%! b = [1, 3, 2; 1, 1, 0; 3, 0, 2];\n%!\n%! [q, r] = qr (a);\n%! [c, re] = qr (a, b);\n%!\n%! assert (r, re, sqrt (eps));\n%! assert (q'*b, c, sqrt (eps));\n\n%!test\n%! a = [0, 2, i; 2, 1, 2; 3, 1, 2];\n%! b = [1, 3, 2; 1, i, 0; 3, 0, 2];\n%!\n%! [q, r] = qr (a);\n%! [c, re] = qr (a, b);\n%!\n%! assert (r, re, sqrt (eps));\n%! assert (q'*b, c, sqrt (eps));\n\n%!test\n%! a = [0, 2, i; 2, 1, 2; 3, 1, 2];\n%! b = [1, 3, 2; 1, 1, 0; 3, 0, 2];\n%!\n%! [q, r] = qr (a);\n%! [c, re] = qr (a, b);\n%!\n%! assert (r, re, sqrt (eps));\n%! assert (q'*b, c, sqrt (eps));\n\n%!test\n%! a = [0, 2, 1; 2, 1, 2; 3, 1, 2];\n%! b = [1, 3, 2; 1, i, 0; 3, 0, 2];\n%!\n%! [q, r] = qr (a);\n%! [c, re] = qr (a, b);\n%!\n%! assert (r, re, sqrt (eps));\n%! assert (q'*b, c, sqrt (eps));\n\n## Empty matrices\n%!test\n%! assert (qr (zeros (0, 0)), zeros (0, 0));\n%! assert (qr (zeros (1, 0)), zeros (1, 0));\n%! assert (qr (zeros (0, 1)), zeros (0, 1));\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\") <*63069>\n%! assert (qr (sparse (0, 0)), sparse (0, 0));\n%! assert (qr (sparse (1, 0)), sparse (1, 0));\n%! assert (qr (sparse (0, 1)), sparse (0, 1));\n\n%!test <*66488>\n%! ## Orientation of 'p' output for dense matrices\n%! [q, r, p] = qr (eye (3));\n%! assert (size (p), [3, 3]);\n%! [q, r, p] = qr (eye (3), 'vector');\n%! assert (size (p), [1, 3]);\n%! [q, r, p] = qr (eye (3), 'econ');\n%! assert (size (p), [3, 3]);\n%! [q, r, p] = qr (eye (3), 0);\n%! assert (size (p), [1, 3]);\n\n%!test <*64861>\n%! ## Return upper-triangular R for dense matrices\n%! A = [1; 4; 8];\n%! R = qr (A);\n%! assert (R, [-9; 0; 0]);\n%! A = single ([1; 4; 8]);\n%! R = qr (A);\n%! assert (R, single ([-9; 0; 0]));\n%! A = [1i; 4; 8];\n%! R = qr (A);\n%! assert (R, [-9; 0; 0]);\n%! A = single ([1i; 4; 8]);\n%! R = qr (A);\n%! assert (R, single ([-9; 0; 0]));\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\") <*66488>\n%! ## Orientation of 'p' output for sparse matrices\n%! [q, r, p] = qr (speye (3));\n%! assert (size (p), [3, 3]);\n%! [q, r, p] = qr (speye (3), 'vector');\n%! assert (size (p), [1, 3]);\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD\n%! [q, r, p] = qr (speye (3), 'econ');\n%! assert (size (p), [3, 3]);\n%! [q, r, p] = qr (speye (3), 0);\n%! assert (size (p), [1, 3]);\n\n%!function retval = __testqr (q, r, a, p)\n%!  tol = 100* eps (class (q));\n%!  retval = 0;\n%!  if (nargin == 3)\n%!    n1 = norm (q*r - a);\n%!    n2 = norm (q'*q - eye (columns (q)));\n%!    retval = (n1 < tol && n2 < tol);\n%!  else\n%!    n1 = norm (q'*q - eye (columns (q)));\n%!    retval = (n1 < tol);\n%!    if (isvector (p))\n%!      n2 = norm (q*r - a(:,p));\n%!      retval = (retval && n2 < tol);\n%!    else\n%!      n2 = norm (q*r - a*p);\n%!      retval = (retval && n2 < tol);\n%!    endif\n%!  endif\n%!endfunction\n\n%!test\n%! t = ones (24, 1);\n%! j = 1;\n%!\n%! if (false)  # eliminate big matrix tests\n%!   a = rand (5000, 20);\n%!   [q,r]   = qr (a, 0);  t(j++) = __testqr (q, r, a);\n%!   [q,r]   = qr (a',0);  t(j++) = __testqr (q, r, a');\n%!   [q,r,p] = qr (a, 0);  t(j++) = __testqr (q, r, a, p);\n%!   [q,r,p] = qr (a',0);  t(j++) = __testqr (q, r, a', p);\n%!\n%!   a = a+1i*eps;\n%!   [q,r]   = qr (a, 0);  t(j++) = __testqr (q, r, a);\n%!   [q,r]   = qr (a',0);  t(j++) = __testqr (q, r, a');\n%!   [q,r,p] = qr (a, 0);  t(j++) = __testqr (q, r, a, p);\n%!   [q,r,p] = qr (a',0);  t(j++) = __testqr (q, r, a', p);\n%! endif\n%!\n%! a = [ ones(1,15); sqrt(eps)*eye(15) ];\n%! [q,r]   = qr (a);   t(j++) = __testqr (q, r, a);\n%! [q,r]   = qr (a');  t(j++) = __testqr (q, r, a');\n%! [q,r,p] = qr (a);   t(j++) = __testqr (q, r, a, p);\n%! [q,r,p] = qr (a');  t(j++) = __testqr (q, r, a', p);\n%!\n%! a = a+1i*eps;\n%! [q,r]   = qr (a);   t(j++) = __testqr (q, r, a);\n%! [q,r]   = qr (a');  t(j++) = __testqr (q, r, a');\n%! [q,r,p] = qr (a);   t(j++) = __testqr (q, r, a, p);\n%! [q,r,p] = qr (a');  t(j++) = __testqr (q, r, a', p);\n%!\n%! a = [ ones(1,15); sqrt(eps)*eye(15) ];\n%! [q,r]   = qr (a, 0);  t(j++) = __testqr (q, r, a);\n%! [q,r]   = qr (a',0);  t(j++) = __testqr (q, r, a');\n%! [q,r,p] = qr (a, 0);  t(j++) = __testqr (q, r, a, p);\n%! [q,r,p] = qr (a',0);  t(j++) = __testqr (q, r, a', p);\n%!\n%! a = a+1i*eps;\n%! [q,r]   = qr (a, 0);  t(j++) = __testqr (q, r, a);\n%! [q,r]   = qr (a',0);  t(j++) = __testqr (q, r, a');\n%! [q,r,p] = qr (a, 0);  t(j++) = __testqr (q, r, a, p);\n%! [q,r,p] = qr (a',0);  t(j++) = __testqr (q, r, a', p);\n%!\n%! a = [ 611   196  -192   407    -8   -52   -49    29\n%!       196   899   113  -192   -71   -43    -8   -44\n%!      -192   113   899   196    61    49     8    52\n%!       407  -192   196   611     8    44    59   -23\n%!        -8   -71    61     8   411  -599   208   208\n%!       -52   -43    49    44  -599   411   208   208\n%!       -49    -8     8    59   208   208    99  -911\n%!        29   -44    52   -23   208   208  -911    99 ];\n%! [q,r] = qr (a);\n%!\n%! assert (all (t));\n%! if (all (t))\n%!   assert (norm (q*r - a), 0, eps (sum (size (a)) * norm (a)));\n%! endif\n\n%!test\n%! a = single ([0, 2, 1; 2, 1, 2]);\n%!\n%! [q, r] = qr (a);\n%! [qe, re] = qr (a, 0);\n%!\n%! assert (q * r, a, sqrt (eps (\"single\")));\n%! assert (qe * re, a, sqrt (eps (\"single\")));\n\n%!test\n%! a = single ([0, 2, 1; 2, 1, 2]);\n%!\n%! [q, r, p] = qr (a);  # FIXME: not giving right dimensions.\n%! [qe, re, pe] = qr (a, 0);\n%!\n%! assert (q * r, a * p, sqrt (eps (\"single\")));\n%! assert (qe * re, a(:, pe), sqrt (eps (\"single\")));\n\n%!test\n%! a = single ([0, 2; 2, 1; 1, 2]);\n%!\n%! [q, r] = qr (a);\n%! [qe, re] = qr (a, 0);\n%!\n%! assert (q * r, a, sqrt (eps (\"single\")));\n%! assert (qe * re, a, sqrt (eps (\"single\")));\n\n%!test\n%! a = single ([0, 2; 2, 1; 1, 2]);\n%!\n%! [q, r, p] = qr (a);\n%! [qe, re, pe] = qr (a, 0);\n%!\n%! assert (q * r, a * p, sqrt (eps (\"single\")));\n%! assert (qe * re, a(:, pe), sqrt (eps (\"single\")));\n\n%!test\n%! a = single ([0, 2, 1; 2, 1, 2; 3, 1, 2]);\n%! b = single ([1, 3, 2; 1, 1, 0; 3, 0, 2]);\n%!\n%! [q, r] = qr (a);\n%! [c, re] = qr (a, b);\n%!\n%! assert (r, re, sqrt (eps (\"single\")));\n%! assert (q'*b, c, sqrt (eps (\"single\")));\n\n%!test\n%! a = single ([0, 2, i; 2, 1, 2; 3, 1, 2]);\n%! b = single ([1, 3, 2; 1, i, 0; 3, 0, 2]);\n%!\n%! [q, r] = qr (a);\n%! [c, re] = qr (a, b);\n%!\n%! assert (r, re, sqrt (eps (\"single\")));\n%! assert (q'*b, c, sqrt (eps (\"single\")));\n\n%!test\n%! a = single ([0, 2, i; 2, 1, 2; 3, 1, 2]);\n%! b = single ([1, 3, 2; 1, 1, 0; 3, 0, 2]);\n%!\n%! [q, r] = qr (a);\n%! [c, re] = qr (a, b);\n%!\n%! assert (r, re, sqrt (eps));\n%! assert (q'*b, c, sqrt (eps));\n\n%!test\n%! a = single ([0, 2, 1; 2, 1, 2; 3, 1, 2]);\n%! b = single ([1, 3, 2; 1, i, 0; 3, 0, 2]);\n%!\n%! [q, r] = qr (a);\n%! [c, re] = qr (a, b);\n%!\n%! assert (r, re, sqrt (eps (\"single\")));\n%! assert (q'*b, c, sqrt (eps (\"single\")));\n\n%!test\n%! t = ones (24, 1);\n%! j = 1;\n%!\n%! if (false)  # eliminate big matrix tests\n%!   a = rand (5000,20);\n%!   [q,r]   = qr (a, 0);  t(j++) = __testqr (q, r, a);\n%!   [q,r]   = qr (a',0);  t(j++) = __testqr (q, r, a');\n%!   [q,r,p] = qr (a, 0);  t(j++) = __testqr (q, r, a, p);\n%!   [q,r,p] = qr (a',0);  t(j++) = __testqr (q, r, a', p);\n%!\n%!   a = a+1i* eps (\"single\");\n%!   [q,r]   = qr (a, 0);  t(j++) = __testqr (q, r, a);\n%!   [q,r]   = qr (a',0);  t(j++) = __testqr (q, r, a');\n%!   [q,r,p] = qr (a, 0);  t(j++) = __testqr (q, r, a, p);\n%!   [q,r,p] = qr (a',0);  t(j++) = __testqr (q, r, a', p);\n%! endif\n%!\n%! a = [ ones(1,15); sqrt(eps(\"single\"))*eye(15) ];\n%! [q,r]   = qr (a);   t(j++) = __testqr (q, r, a);\n%! [q,r]   = qr (a');  t(j++) = __testqr (q, r, a');\n%! [q,r,p] = qr (a);   t(j++) = __testqr (q, r, a, p);\n%! [q,r,p] = qr (a');  t(j++) = __testqr (q, r, a', p);\n%!\n%! a = a+1i* eps (\"single\");\n%! [q,r]   = qr (a);   t(j++) = __testqr (q, r, a);\n%! [q,r]   = qr (a');  t(j++) = __testqr (q, r, a');\n%! [q,r,p] = qr (a);   t(j++) = __testqr (q, r, a, p);\n%! [q,r,p] = qr (a');  t(j++) = __testqr (q, r, a', p);\n%!\n%! a = [ ones(1,15); sqrt(eps(\"single\"))*eye(15) ];\n%! [q,r]   = qr (a, 0);  t(j++) = __testqr (q, r, a);\n%! [q,r]   = qr (a',0);  t(j++) = __testqr (q, r, a');\n%! [q,r,p] = qr (a, 0);  t(j++) = __testqr (q, r, a, p);\n%! [q,r,p] = qr (a',0);  t(j++) = __testqr (q, r, a', p);\n%!\n%! a = a+1i* eps (\"single\");\n%! [q,r]   = qr (a, 0);  t(j++) = __testqr (q, r, a);\n%! [q,r]   = qr (a',0);  t(j++) = __testqr (q, r, a');\n%! [q,r,p] = qr (a, 0);  t(j++) = __testqr (q, r, a, p);\n%! [q,r,p] = qr (a',0);  t(j++) = __testqr (q, r, a',p);\n%!\n%! a = [ 611   196  -192   407    -8   -52   -49    29\n%!       196   899   113  -192   -71   -43    -8   -44\n%!      -192   113   899   196    61    49     8    52\n%!       407  -192   196   611     8    44    59   -23\n%!        -8   -71    61     8   411  -599   208   208\n%!       -52   -43    49    44  -599   411   208   208\n%!       -49    -8     8    59   208   208    99  -911\n%!        29   -44    52   -23   208   208  -911    99 ];\n%! [q,r] = qr (a);\n%!\n%! assert (all (t));\n%! if (all (t))\n%!   assert (norm (q*r - a), 0, 5000 * eps (\"single\"));\n%! endif\n\n## The deactivated tests below can't be tested till rectangular back-subs is\n## implemented for sparse matrices.\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (n,n,d) + speye (n,n);\n%! r = qr (a);\n%! assert (r'*r, a'*a, 1e-10);\n\n%!testif HAVE_COLAMD; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (n,n,d) + speye (n,n);\n%! q = symamd (a);\n%! a = a(q,q);\n%! r = qr (a);\n%! assert (r'*r, a'*a, 1e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (n,n,d) + speye (n,n);\n%! [c, r] = qr (a, ones (n,1));\n%! assert (r\\c, full (a)\\ones (n,1), 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (n,n,d) + speye (n,n);\n%! b = randn (n,2);\n%! [c, r] = qr (a, b);\n%! assert (r\\c, full (a)\\b, 10e-10);\n\n## Test under-determined systems!!\n%!#testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (n,n+1,d) + speye (n,n+1);\n%! b = randn (n,2);\n%! [c, r] = qr (a, b);\n%! assert (r\\c, full (a)\\b, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = 1i* sprandn (n,n,d) + speye (n,n);\n%! r = qr (a);\n%! assert (r'*r, a'*a, 1e-10);\n\n%!testif HAVE_COLAMD; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = 1i* sprandn (n,n,d) + speye (n,n);\n%! q = symamd (a);\n%! a = a(q,q);\n%! r = qr (a);\n%! assert (r'*r, a'*a, 1e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = 1i* sprandn (n,n,d) + speye (n,n);\n%! [c, r] = qr (a, ones (n,1));\n%! assert (r\\c, full (a)\\ones (n,1), 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = 1i* sprandn (n,n,d) + speye (n,n);\n%! b = randn (n,2);\n%! [c, r] = qr (a, b);\n%! assert (r\\c, full (a)\\b, 10e-10);\n\n## Test under-determined systems!!\n%!#testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 20;  d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = 1i* sprandn (n,n+1,d) + speye (n,n+1);\n%! b = randn (n, 2);\n%! [c, r] = qr (a, b);\n%! assert (r\\c, full (a)\\b, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (m, n, d);\n%! b = randn (m, 2);\n%! [c, r] = qr (a, b);\n%! assert (r\\c, full (a)\\b, 10e-10);\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (m, n, d);\n%! b = sprandn (m, 2, d);\n%! [c, r] = qr (a, b, 0);\n%! [c2, r2] = qr (full (a), full (b), 0);\n%! assert (r\\c, r2\\c2, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (m, n, d);\n%! b = randn (m, 2);\n%! [c, r, p] = qr (a, b, \"matrix\");\n%! x = p * (r\\c);\n%! [c2, r2] = qr (full (a), b);\n%! x2 = r2 \\ c2;\n%! assert (x, x2, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (m, n, d);\n%! [q, r, p] = qr (a, \"matrix\");\n%! assert (q * r, a * p, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (m, n, d);\n%! b = randn (m, 2);\n%! x = qr (a, b);\n%! [c2, r2] = qr (full (a), b);\n%! assert (x, r2\\c2, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (m, n, d);\n%! b = i * randn (m, 2);\n%! x = qr (a, b);\n%! [c2, r2] = qr (full (a), b);\n%! assert (x, r2\\c2, 10e-10);\n\n%!#testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (m, n, d);\n%! b = i * randn (m, 2);\n%! [c, r] = qr (a, b);\n%! [c2, r2] = qr (full (a), b);\n%! assert (r\\c, r2\\c2, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = sprandn (m, n, d);\n%! b = i * randn (m, 2);\n%! [c, r, p] = qr (a, b, \"matrix\");\n%! x = p * (r\\c);\n%! [c2, r2] = qr (full (a), b);\n%! x2 = r2 \\ c2;\n%! assert (x, x2, 10e-10);\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = i * sprandn (m, n, d);\n%! b = sprandn (m, 2, d);\n%! [c, r] = qr (a, b, 0);\n%! [c2, r2] = qr (full (a), full (b), 0);\n%! assert (r\\c, r2\\c2, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = i * sprandn (m, n, d);\n%! b = randn (m, 2);\n%! [c, r, p] = qr (a, b, \"matrix\");\n%! x = p * (r\\c);\n%! [c2, r2] = qr (full (a), b);\n%! x2 = r2 \\ c2;\n%! assert(x, x2, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = i * sprandn (m, n, d);\n%! [q, r, p] = qr (a, \"matrix\");\n%! assert(q * r, a * p, 10e-10);\n\n%!testif ; (__have_feature__ (\"SPQR\") && __have_feature__ (\"CHOLMOD\")) || __have_feature__ (\"CXSPARSE\")\n%! n = 12; m = 20; d = 0.2;\n%! ## initialize generators to make behavior reproducible\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! a = i * sprandn (m, n, d);\n%! b = randn (m, 2);\n%! x = qr (a, b);\n%! [c2, r2] = qr (full (a), b);\n%! assert (x, r2\\c2, 10e-10);\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD\n%! a = sparse (5, 6);\n%! a(3,1) = 0.8;\n%! a(2,2) = 1.4;\n%! a(1,6) = -0.5;\n%! r = qr (a);\n%! assert (r'*r, a'*a, 10e-10);\n\n## Test input validation\n%!error <Invalid call> qr ()\n%!error <Invalid call> qr (1,2,3,4)\n%!error <too many output arguments> [a,b,c,d] = qr (1)\n%!error <option string must be .*, not \"foo\"> qr (magic (3), \"foo\")\n%!error <option string must be .*, not \"foo\"> qr (magic (3), ones (3, 1), \"foo\")\n%!error <too many output arguments when called with A and B>\n%! [q, r, p] = qr (ones (3, 2), ones (3, 1));\n%!error <too many output arguments when called with A and B>\n%! [q, r, p] = qr (ones (3, 2), ones (3, 1), 0);\n\n*/\n\nstatic\nbool\ncheck_qr_dims (const octave_value& q, const octave_value& r,\n               bool allow_ecf = false)\n{\n  octave_idx_type m = q.rows ();\n  octave_idx_type k = r.rows ();\n  octave_idx_type n = r.columns ();\n  return ((q.ndims () == 2 && r.ndims () == 2 && k == q.columns ())\n          && (m == k || (allow_ecf && k == n && k < m)));\n}\n\nstatic\nbool\ncheck_index (const octave_value& i, bool vector_allowed = false)\n{\n  return ((i.isreal () || i.isinteger ())\n          && (i.is_scalar_type () || vector_allowed));\n}\n\nDEFUN (qrupdate, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{Q1}, @var{R1}] =} qrupdate (@var{Q}, @var{R}, @var{u}, @var{v})\nUpdate a QR factorization given update vectors or matrices.\n\nGiven a QR@tie{}factorization of a real or complex matrix\n@w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and\n@var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization of\n@w{@var{A} + @var{u}*@var{v}'}, where @var{u} and @var{v} are column vectors\n(rank-1 update) or matrices with equal number of columns\n(rank-k update).  Notice that the latter case is done as a sequence of\nrank-1 updates; thus, for k large enough, it will be both faster and more\naccurate to recompute the factorization from scratch.\n\nThe QR@tie{}factorization supplied may be either full (Q is square) or\neconomized (R is square).\n\n@seealso{qr, qrinsert, qrdelete, qrshift}\n@end deftypefn */)\n{\n  octave_value_list retval;\n\n  if (args.length () != 4)\n    print_usage ();\n\n  octave_value argq = args(0);\n  octave_value argr = args(1);\n  octave_value argu = args(2);\n  octave_value argv = args(3);\n\n  if (! argq.isnumeric () || ! argr.isnumeric ()\n      || ! argu.isnumeric () || ! argv.isnumeric ())\n    print_usage ();\n\n  if (! check_qr_dims (argq, argr, true))\n    error (\"qrupdate: Q and R dimensions don't match\");\n\n  if (argq.isreal () && argr.isreal () && argu.isreal ()\n      && argv.isreal ())\n    {\n      // all real case\n      if (argq.is_single_type () || argr.is_single_type ()\n          || argu.is_single_type () || argv.is_single_type ())\n        {\n          FloatMatrix Q = argq.float_matrix_value ();\n          FloatMatrix R = argr.float_matrix_value ();\n          FloatMatrix u = argu.float_matrix_value ();\n          FloatMatrix v = argv.float_matrix_value ();\n\n          math::qr<FloatMatrix> fact (Q, R);\n          fact.update (u, v);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n      else\n        {\n          Matrix Q = argq.matrix_value ();\n          Matrix R = argr.matrix_value ();\n          Matrix u = argu.matrix_value ();\n          Matrix v = argv.matrix_value ();\n\n          math::qr<Matrix> fact (Q, R);\n          fact.update (u, v);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n    }\n  else\n    {\n      // complex case\n      if (argq.is_single_type () || argr.is_single_type ()\n          || argu.is_single_type () || argv.is_single_type ())\n        {\n          FloatComplexMatrix Q = argq.float_complex_matrix_value ();\n          FloatComplexMatrix R = argr.float_complex_matrix_value ();\n          FloatComplexMatrix u = argu.float_complex_matrix_value ();\n          FloatComplexMatrix v = argv.float_complex_matrix_value ();\n\n          math::qr<FloatComplexMatrix> fact (Q, R);\n          fact.update (u, v);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n      else\n        {\n          ComplexMatrix Q = argq.complex_matrix_value ();\n          ComplexMatrix R = argr.complex_matrix_value ();\n          ComplexMatrix u = argu.complex_matrix_value ();\n          ComplexMatrix v = argv.complex_matrix_value ();\n\n          math::qr<ComplexMatrix> fact (Q, R);\n          fact.update (u, v);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!shared A, u, v, Ac, uc, vc\n%! A = [0.091364  0.613038  0.999083;\n%!      0.594638  0.425302  0.603537;\n%!      0.383594  0.291238  0.085574;\n%!      0.265712  0.268003  0.238409;\n%!      0.669966  0.743851  0.445057 ];\n%!\n%! u = [0.85082;\n%!      0.76426;\n%!      0.42883;\n%!      0.53010;\n%!      0.80683 ];\n%!\n%! v = [0.98810;\n%!      0.24295;\n%!      0.43167 ];\n%!\n%! Ac = [0.620405 + 0.956953i  0.480013 + 0.048806i  0.402627 + 0.338171i;\n%!      0.589077 + 0.658457i  0.013205 + 0.279323i  0.229284 + 0.721929i;\n%!      0.092758 + 0.345687i  0.928679 + 0.241052i  0.764536 + 0.832406i;\n%!      0.912098 + 0.721024i  0.049018 + 0.269452i  0.730029 + 0.796517i;\n%!      0.112849 + 0.603871i  0.486352 + 0.142337i  0.355646 + 0.151496i ];\n%!\n%! uc = [0.20351 + 0.05401i;\n%!      0.13141 + 0.43708i;\n%!      0.29808 + 0.08789i;\n%!      0.69821 + 0.38844i;\n%!      0.74871 + 0.25821i ];\n%!\n%! vc = [0.85839 + 0.29468i;\n%!      0.20820 + 0.93090i;\n%!      0.86184 + 0.34689i ];\n%!\n\n%!test\n%! [Q,R] = qr (A);\n%! [Q,R] = qrupdate (Q, R, u, v);\n%! assert (norm (vec (Q'*Q - eye (5)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R)-R), Inf), 0);\n%! assert (norm (vec (Q*R - A - u*v'), Inf), 0, norm (A)*1e1*eps);\n%!\n%!test\n%! [Q,R] = qr (Ac);\n%! [Q,R] = qrupdate (Q, R, uc, vc);\n%! assert (norm (vec (Q'*Q - eye (5)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R)-R), Inf), 0);\n%! assert (norm (vec (Q*R - Ac - uc*vc'), Inf), 0, norm (Ac)*1e1*eps);\n\n%!test\n%! [Q,R] = qr (single (A));\n%! [Q,R] = qrupdate (Q, R, single (u), single (v));\n%! assert (norm (vec (Q'*Q - eye (5,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R)-R), Inf), single (0));\n%! assert (norm (vec (Q*R - single (A) - single (u)* single (v)'), Inf), ...\n%!         single (0), norm (single (A))*1e1 * eps (\"single\"));\n%!\n%!test\n%! [Q,R] = qr (single (Ac));\n%! [Q,R] = qrupdate (Q, R, single (uc), single (vc));\n%! assert (norm (vec (Q'*Q - eye (5,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R)-R), Inf), single (0));\n%! assert (norm (vec (Q*R - single (Ac) - single (uc)* single (vc)'), Inf), ...\n%!         single (0), norm (single (Ac))*1e1 * eps (\"single\"));\n*/\n\nDEFUN (qrinsert, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{Q1}, @var{R1}] =} qrinsert (@var{Q}, @var{R}, @var{j}, @var{x}, @var{orient})\nUpdate a QR factorization given a row or column to insert in the original\nfactored matrix.\n\n\nGiven a QR@tie{}factorization of a real or complex matrix\n@w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and\n@var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization of\n@w{[A(:,1:j-1) x A(:,j:n)]}, where @var{u} is a column vector to be inserted\ninto @var{A} (if @var{orient} is @qcode{\"col\"}), or the\nQR@tie{}factorization of @w{[A(1:j-1,:);x;A(:,j:n)]}, where @var{x} is a row\nvector to be inserted into @var{A} (if @var{orient} is @qcode{\"row\"}).\n\nThe default value of @var{orient} is @qcode{\"col\"}.  If @var{orient} is\n@qcode{\"col\"}, @var{u} may be a matrix and @var{j} an index vector\nresulting in the QR@tie{}factorization of a matrix @var{B} such that\n@w{B(:,@var{j})}@ gives @var{u} and @w{B(:,@var{j}) = []}@ gives @var{A}.\nNotice that the latter case is done as a sequence of k insertions;\nthus, for k large enough, it will be both faster and more accurate to\nrecompute the factorization from scratch.\n\nIf @var{orient} is @qcode{\"col\"}, the QR@tie{}factorization supplied may\nbe either full (Q is square) or economized (R is square).\n\nIf @var{orient} is @qcode{\"row\"}, full factorization is needed.\n@seealso{qr, qrupdate, qrdelete, qrshift}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 4 || nargin > 5)\n    print_usage ();\n\n  octave_value argq = args(0);\n  octave_value argr = args(1);\n  octave_value argj = args(2);\n  octave_value argx = args(3);\n\n  if (! argq.isnumeric () || ! argr.isnumeric ()\n      || ! argx.isnumeric ()\n      || (nargin > 4 && ! args(4).is_string ()))\n    print_usage ();\n\n  std::string orient = (nargin < 5) ? \"col\" : args(4).string_value ();\n  bool col = (orient == \"col\");\n\n  if (! col && orient != \"row\")\n    error (R\"(qrinsert: ORIENT must be \"col\" or \"row\")\");\n\n  if (! check_qr_dims (argq, argr, col) || (! col && argx.rows () != 1))\n    error (\"qrinsert: dimension mismatch\");\n\n  if (! check_index (argj, col))\n    error (\"qrinsert: invalid index J\");\n\n  octave_value_list retval;\n\n  MArray<octave_idx_type> j = argj.octave_idx_type_vector_value ();\n\n  octave_idx_type one = 1;\n\n  if (argq.isreal () && argr.isreal () && argx.isreal ())\n    {\n      // real case\n      if (argq.is_single_type () || argr.is_single_type ()\n          || argx.is_single_type ())\n        {\n          FloatMatrix Q = argq.float_matrix_value ();\n          FloatMatrix R = argr.float_matrix_value ();\n          FloatMatrix x = argx.float_matrix_value ();\n\n          math::qr<FloatMatrix> fact (Q, R);\n\n          if (col)\n            fact.insert_col (x, j-one);\n          else\n            fact.insert_row (x.row (0), j(0)-one);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n      else\n        {\n          Matrix Q = argq.matrix_value ();\n          Matrix R = argr.matrix_value ();\n          Matrix x = argx.matrix_value ();\n\n          math::qr<Matrix> fact (Q, R);\n\n          if (col)\n            fact.insert_col (x, j-one);\n          else\n            fact.insert_row (x.row (0), j(0)-one);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n    }\n  else\n    {\n      // complex case\n      if (argq.is_single_type () || argr.is_single_type ()\n          || argx.is_single_type ())\n        {\n          FloatComplexMatrix Q = argq.float_complex_matrix_value ();\n          FloatComplexMatrix R = argr.float_complex_matrix_value ();\n          FloatComplexMatrix x = argx.float_complex_matrix_value ();\n\n          math::qr<FloatComplexMatrix> fact (Q, R);\n\n          if (col)\n            fact.insert_col (x, j-one);\n          else\n            fact.insert_row (x.row (0), j(0)-one);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n      else\n        {\n          ComplexMatrix Q = argq.complex_matrix_value ();\n          ComplexMatrix R = argr.complex_matrix_value ();\n          ComplexMatrix x = argx.complex_matrix_value ();\n\n          math::qr<ComplexMatrix> fact (Q, R);\n\n          if (col)\n            fact.insert_col (x, j-one);\n          else\n            fact.insert_row (x.row (0), j(0)-one);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! [Q,R] = qr (A);\n%! [Q,R] = qrinsert (Q, R, 3, u);\n%! assert (norm (vec (Q'*Q - eye (5)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - [A(:,1:2) u A(:,3)]), Inf), 0, norm (A)*1e1*eps);\n%!test\n%! [Q,R] = qr (Ac);\n%! [Q,R] = qrinsert (Q, R, 3, uc);\n%! assert (norm (vec (Q'*Q - eye (5)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - [Ac(:,1:2) uc Ac(:,3)]), Inf), 0, ...\n%!         norm (Ac) * 1e1 * eps);\n%!test\n%! x = [0.85082  0.76426  0.42883 ];\n%!\n%! [Q,R] = qr (A);\n%! [Q,R] = qrinsert (Q, R, 3, x, \"row\");\n%! assert (norm (vec (Q'*Q - eye (6)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - [A(1:2,:);x;A(3:5,:)]), Inf), 0, norm (A)*1e1*eps);\n%!test\n%! x = [0.20351 + 0.05401i  0.13141 + 0.43708i  0.29808 + 0.08789i ];\n%!\n%! [Q,R] = qr (Ac);\n%! [Q,R] = qrinsert (Q, R, 3, x, \"row\");\n%! assert (norm (vec (Q'*Q - eye (6)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - [Ac(1:2,:);x;Ac(3:5,:)]), Inf), 0, ...\n%!         norm (Ac) * 1e1 * eps);\n\n%!test\n%! [Q,R] = qr (single (A));\n%! [Q,R] = qrinsert (Q, R, 3, single (u));\n%! assert (norm (vec (Q'*Q - eye (5,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - single ([A(:,1:2) u A(:,3)])), Inf), ...\n%!         single (0), norm (single (A))*1e1 * eps (\"single\"));\n%!test\n%! [Q,R] = qr (single (Ac));\n%! [Q,R] = qrinsert (Q, R, 3, single (uc));\n%! assert (norm (vec (Q'*Q - eye (5,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - single ([Ac(:,1:2) uc Ac(:,3)])), Inf), ...\n%!         single (0), norm (single (Ac))*1e1 * eps (\"single\"));\n%!test\n%! x = single ([0.85082  0.76426  0.42883 ]);\n%!\n%! [Q,R] = qr (single (A));\n%! [Q,R] = qrinsert (Q, R, 3, x, \"row\");\n%! assert (norm (vec (Q'*Q - eye (6,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - single ([A(1:2,:);x;A(3:5,:)])), Inf), ...\n%!         single (0), norm (single (A))*1e1 * eps (\"single\"));\n%!test\n%! x = single ([0.20351 + 0.05401i  0.13141 + 0.43708i  0.29808 + 0.08789i ]);\n%!\n%! [Q,R] = qr (single (Ac));\n%! [Q,R] = qrinsert (Q, R, 3, x, \"row\");\n%! assert (norm (vec (Q'*Q - eye (6,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - single ([Ac(1:2,:);x;Ac(3:5,:)])), Inf), ...\n%!         single (0), norm (single (Ac))*1e1 * eps (\"single\"));\n*/\n\nDEFUN (qrdelete, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{Q1}, @var{R1}] =} qrdelete (@var{Q}, @var{R}, @var{j}, @var{orient})\nUpdate a QR factorization given a row or column to delete from the original\nfactored matrix.\n\nGiven a QR@tie{}factorization of a real or complex matrix\n@w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and\n@var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization of\n@w{[A(:,1:j-1), U, A(:,j:n)]},\nwhere @var{u} is a column vector to be inserted into @var{A}\n(if @var{orient} is @qcode{\"col\"}),\nor the QR@tie{}factorization of @w{[A(1:j-1,:);X;A(:,j:n)]},\nwhere @var{x} is a row @var{orient} is @qcode{\"row\"}).\nThe default value of @var{orient} is @qcode{\"col\"}.\n\nIf @var{orient} is @qcode{\"col\"}, @var{j} may be an index vector\nresulting in the QR@tie{}factorization of a matrix @var{B} such that\n@w{A(:,@var{j}) = []}@ gives @var{B}.  Notice that the latter case is done as\na sequence of k deletions; thus, for k large enough, it will be both faster\nand more accurate to recompute the factorization from scratch.\n\nIf @var{orient} is @qcode{\"col\"}, the QR@tie{}factorization supplied may\nbe either full (Q is square) or economized (R is square).\n\nIf @var{orient} is @qcode{\"row\"}, full factorization is needed.\n@seealso{qr, qrupdate, qrinsert, qrshift}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 3 || nargin > 4)\n    print_usage ();\n\n  octave_value argq = args(0);\n  octave_value argr = args(1);\n  octave_value argj = args(2);\n\n  if (! argq.isnumeric () || ! argr.isnumeric ()\n      || (nargin > 3 && ! args(3).is_string ()))\n    print_usage ();\n\n  std::string orient = (nargin < 4) ? \"col\" : args(3).string_value ();\n  bool col = orient == \"col\";\n\n  if (! col && orient != \"row\")\n    error (R\"(qrdelete: ORIENT must be \"col\" or \"row\")\");\n\n  if (! check_qr_dims (argq, argr, col))\n    error (\"qrdelete: dimension mismatch\");\n\n  MArray<octave_idx_type> j = argj.octave_idx_type_vector_value ();\n  if (! check_index (argj, col))\n    error (\"qrdelete: invalid index J\");\n\n  octave_value_list retval;\n\n  octave_idx_type one = 1;\n\n  if (argq.isreal () && argr.isreal ())\n    {\n      // real case\n      if (argq.is_single_type () || argr.is_single_type ())\n        {\n          FloatMatrix Q = argq.float_matrix_value ();\n          FloatMatrix R = argr.float_matrix_value ();\n\n          math::qr<FloatMatrix> fact (Q, R);\n\n          if (col)\n            fact.delete_col (j-one);\n          else\n            fact.delete_row (j(0)-one);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n      else\n        {\n          Matrix Q = argq.matrix_value ();\n          Matrix R = argr.matrix_value ();\n\n          math::qr<Matrix> fact (Q, R);\n\n          if (col)\n            fact.delete_col (j-one);\n          else\n            fact.delete_row (j(0)-one);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n    }\n  else\n    {\n      // complex case\n      if (argq.is_single_type () || argr.is_single_type ())\n        {\n          FloatComplexMatrix Q = argq.float_complex_matrix_value ();\n          FloatComplexMatrix R = argr.float_complex_matrix_value ();\n\n          math::qr<FloatComplexMatrix> fact (Q, R);\n\n          if (col)\n            fact.delete_col (j-one);\n          else\n            fact.delete_row (j(0)-one);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n      else\n        {\n          ComplexMatrix Q = argq.complex_matrix_value ();\n          ComplexMatrix R = argr.complex_matrix_value ();\n\n          math::qr<ComplexMatrix> fact (Q, R);\n\n          if (col)\n            fact.delete_col (j-one);\n          else\n            fact.delete_row (j(0)-one);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! AA = [0.091364  0.613038  0.027504  0.999083;\n%!       0.594638  0.425302  0.562834  0.603537;\n%!       0.383594  0.291238  0.742073  0.085574;\n%!       0.265712  0.268003  0.783553  0.238409;\n%!       0.669966  0.743851  0.457255  0.445057 ];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrdelete (Q, R, 3);\n%! assert (norm (vec (Q'*Q - eye (5)), Inf), 0, 16*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf), 0, norm (AA)*1e1*eps);\n%!\n%!test\n%! AA = [0.364554 + 0.993117i  0.669818 + 0.510234i  0.426568 + 0.041337i  0.847051 + 0.233291i;\n%!       0.049600 + 0.242783i  0.448946 + 0.484022i  0.141155 + 0.074420i  0.446746 + 0.392706i;\n%!       0.581922 + 0.657416i  0.581460 + 0.030016i  0.219909 + 0.447288i  0.201144 + 0.069132i;\n%!       0.694986 + 0.000571i  0.682327 + 0.841712i  0.807537 + 0.166086i  0.192767 + 0.358098i;\n%!       0.945002 + 0.066788i  0.350492 + 0.642638i  0.579629 + 0.048102i  0.600170 + 0.636938i ] * I;\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrdelete (Q, R, 3);\n%! assert (norm (vec (Q'*Q - eye (5)), Inf) < 16*eps);\n%! assert (norm (vec (triu (R) - R), Inf) == 0);\n%! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf) < norm (AA)*1e1*eps);\n%!\n%!test\n%! AA = [0.091364  0.613038  0.027504  0.999083;\n%!       0.594638  0.425302  0.562834  0.603537;\n%!       0.383594  0.291238  0.742073  0.085574;\n%!       0.265712  0.268003  0.783553  0.238409;\n%!       0.669966  0.743851  0.457255  0.445057 ];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrdelete (Q, R, 3, \"row\");\n%! assert (norm (vec (Q'*Q - eye (4)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf), 0, norm (AA)*1e1*eps);\n%!\n%!test\n%! AA = [0.364554 + 0.993117i  0.669818 + 0.510234i  0.426568 + 0.041337i  0.847051 + 0.233291i;\n%!       0.049600 + 0.242783i  0.448946 + 0.484022i  0.141155 + 0.074420i  0.446746 + 0.392706i;\n%!       0.581922 + 0.657416i  0.581460 + 0.030016i  0.219909 + 0.447288i  0.201144 + 0.069132i;\n%!       0.694986 + 0.000571i  0.682327 + 0.841712i  0.807537 + 0.166086i  0.192767 + 0.358098i;\n%!       0.945002 + 0.066788i  0.350492 + 0.642638i  0.579629 + 0.048102i  0.600170 + 0.636938i ] * I;\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrdelete (Q, R, 3, \"row\");\n%! assert (norm (vec (Q'*Q - eye (4)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf), 0, norm (AA)*1e1*eps);\n\n%!test\n%! AA = single ([0.091364  0.613038  0.027504  0.999083;\n%!               0.594638  0.425302  0.562834  0.603537;\n%!               0.383594  0.291238  0.742073  0.085574;\n%!               0.265712  0.268003  0.783553  0.238409;\n%!               0.669966  0.743851  0.457255  0.445057 ]);\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrdelete (Q, R, 3);\n%! assert (norm (vec (Q'*Q - eye (5,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf), single (0), ...\n%!         norm (AA)*1e1 * eps (\"single\"));\n%!\n%!test\n%! AA = single ([0.364554 + 0.993117i  0.669818 + 0.510234i  0.426568 + 0.041337i  0.847051 + 0.233291i;\n%!               0.049600 + 0.242783i  0.448946 + 0.484022i  0.141155 + 0.074420i  0.446746 + 0.392706i;\n%!               0.581922 + 0.657416i  0.581460 + 0.030016i  0.219909 + 0.447288i  0.201144 + 0.069132i;\n%!               0.694986 + 0.000571i  0.682327 + 0.841712i  0.807537 + 0.166086i  0.192767 + 0.358098i;\n%!               0.945002 + 0.066788i  0.350492 + 0.642638i  0.579629 + 0.048102i  0.600170 + 0.636938i ]) * I;\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrdelete (Q, R, 3);\n%! assert (norm (vec (Q'*Q - eye (5,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf), single (0), ...\n%!         norm (AA)*1e1 * eps (\"single\"));\n\n%!test\n%! AA = single ([0.091364  0.613038  0.027504  0.999083;\n%!               0.594638  0.425302  0.562834  0.603537;\n%!               0.383594  0.291238  0.742073  0.085574;\n%!               0.265712  0.268003  0.783553  0.238409;\n%!               0.669966  0.743851  0.457255  0.445057 ]);\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrdelete (Q, R, 3, \"row\");\n%! assert (norm (vec (Q'*Q - eye (4,\"single\")), Inf), single (0), ...\n%!         1.5e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf), single (0), ...\n%!         norm (AA)*1e1 * eps (\"single\"));\n%!testif HAVE_QRUPDATE\n%! ## Same test as above but with more precicision\n%! AA = single ([0.091364  0.613038  0.027504  0.999083;\n%!               0.594638  0.425302  0.562834  0.603537;\n%!               0.383594  0.291238  0.742073  0.085574;\n%!               0.265712  0.268003  0.783553  0.238409;\n%!               0.669966  0.743851  0.457255  0.445057 ]);\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrdelete (Q, R, 3, \"row\");\n%! assert (norm (vec (Q'*Q - eye (4,\"single\")), Inf), single (0), ...\n%!         1e1* eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf), single (0), ...\n%!         norm (AA)*1e1 * eps (\"single\"));\n%!\n%!test\n%! AA = single ([0.364554 + 0.993117i  0.669818 + 0.510234i  0.426568 + 0.041337i  0.847051 + 0.233291i;\n%!              0.049600 + 0.242783i  0.448946 + 0.484022i  0.141155 + 0.074420i  0.446746 + 0.392706i;\n%!              0.581922 + 0.657416i  0.581460 + 0.030016i  0.219909 + 0.447288i  0.201144 + 0.069132i;\n%!              0.694986 + 0.000571i  0.682327 + 0.841712i  0.807537 + 0.166086i  0.192767 + 0.358098i;\n%!              0.945002 + 0.066788i  0.350492 + 0.642638i  0.579629 + 0.048102i  0.600170 + 0.636938i ]) * I;\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrdelete (Q, R, 3, \"row\");\n%! assert (norm (vec (Q'*Q - eye (4,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf), single (0), ...\n%!         norm (AA)*1e1 * eps (\"single\"));\n*/\n\nDEFUN (qrshift, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{Q1}, @var{R1}] =} qrshift (@var{Q}, @var{R}, @var{i}, @var{j})\nUpdate a QR factorization given a range of columns to shift in the original\nfactored matrix.\n\nGiven a QR@tie{}factorization of a real or complex matrix\n@w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and\n@var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization\nof @w{@var{A}(:,p)}, where @w{p} is the permutation @*\n@code{p = [1:i-1, circshift(i:j, 1), j+1:n]} if @w{@var{i} < @var{j}} @*\n or @*\n@code{p = [1:j-1, circshift(j:i,-1), i+1:n]} if @w{@var{j} < @var{i}}.  @*\n\n@seealso{qr, qrupdate, qrinsert, qrdelete}\n@end deftypefn */)\n{\n  if (args.length () != 4)\n    print_usage ();\n\n  octave_value argq = args(0);\n  octave_value argr = args(1);\n  octave_value argi = args(2);\n  octave_value argj = args(3);\n\n  if (! argq.isnumeric () || ! argr.isnumeric ())\n    print_usage ();\n\n  if (! check_qr_dims (argq, argr, true))\n    error (\"qrshift: dimensions mismatch\");\n\n  octave_idx_type i = argi.idx_type_value ();\n  octave_idx_type j = argj.idx_type_value ();\n\n  if (! check_index (argi) || ! check_index (argj))\n    error (\"qrshift: invalid index I or J\");\n\n  octave_value_list retval;\n\n  if (argq.isreal () && argr.isreal ())\n    {\n      // all real case\n      if (argq.is_single_type ()\n          && argr.is_single_type ())\n        {\n          FloatMatrix Q = argq.float_matrix_value ();\n          FloatMatrix R = argr.float_matrix_value ();\n\n          math::qr<FloatMatrix> fact (Q, R);\n          fact.shift_cols (i-1, j-1);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n      else\n        {\n          Matrix Q = argq.matrix_value ();\n          Matrix R = argr.matrix_value ();\n\n          math::qr<Matrix> fact (Q, R);\n          fact.shift_cols (i-1, j-1);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n    }\n  else\n    {\n      // complex case\n      if (argq.is_single_type ()\n          && argr.is_single_type ())\n        {\n          FloatComplexMatrix Q = argq.float_complex_matrix_value ();\n          FloatComplexMatrix R = argr.float_complex_matrix_value ();\n\n          math::qr<FloatComplexMatrix> fact (Q, R);\n          fact.shift_cols (i-1, j-1);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n      else\n        {\n          ComplexMatrix Q = argq.complex_matrix_value ();\n          ComplexMatrix R = argr.complex_matrix_value ();\n\n          math::qr<ComplexMatrix> fact (Q, R);\n          fact.shift_cols (i-1, j-1);\n\n          retval = ovl (fact.Q (), get_qr_r (fact));\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! AA = A.';\n%! i = 2;  j = 4;  p = [1:i-1, circshift(i:j,-1), j+1:5];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrshift (Q, R, i, j);\n%! assert (norm (vec (Q'*Q - eye (3)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - AA(:,p)), Inf), 0, norm (AA)*1e1*eps);\n%!\n%! j = 2;  i = 4;  p = [1:j-1, circshift(j:i,+1), i+1:5];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrshift (Q, R, i, j);\n%! assert (norm (vec (Q'*Q - eye (3)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - AA(:,p)), Inf), 0, norm (AA)*1e1*eps);\n%!\n%!test\n%! AA = Ac.';\n%! i = 2;  j = 4;  p = [1:i-1, circshift(i:j,-1), j+1:5];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrshift (Q, R, i, j);\n%! assert (norm (vec (Q'*Q - eye (3)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - AA(:,p)), Inf), 0, norm (AA)*1e1*eps);\n%!\n%! j = 2;  i = 4;  p = [1:j-1, circshift(j:i,+1), i+1:5];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrshift (Q, R, i, j);\n%! assert (norm (vec (Q'*Q - eye (3)), Inf), 0, 1e1*eps);\n%! assert (norm (vec (triu (R) - R), Inf), 0);\n%! assert (norm (vec (Q*R - AA(:,p)), Inf), 0, norm (AA)*1e1*eps);\n\n%!test\n%! AA = single (A).';\n%! i = 2;  j = 4;  p = [1:i-1, circshift(i:j,-1), j+1:5];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrshift (Q, R, i, j);\n%! assert (norm (vec (Q'*Q - eye (3,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - AA(:,p)), Inf), single (0), ...\n%!         norm (AA)*1e1 * eps (\"single\"));\n%!\n%! j = 2;  i = 4;  p = [1:j-1, circshift(j:i,+1), i+1:5];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrshift (Q, R, i, j);\n%! assert (norm (vec (Q'*Q - eye (3,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - AA(:,p)), Inf), single (0), ...\n%!         norm (AA)*1e1 * eps (\"single\"));\n%!\n%!test\n%! AA = single (Ac).';\n%! i = 2;  j = 4;  p = [1:i-1, circshift(i:j,-1), j+1:5];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrshift (Q, R, i, j);\n%! assert (norm (vec (Q'*Q - eye (3,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - AA(:,p)), Inf), single (0), ...\n%!         norm (AA)*1e1 * eps (\"single\"));\n%!\n%! j = 2;  i = 4;  p = [1:j-1, circshift(j:i,+1), i+1:5];\n%!\n%! [Q,R] = qr (AA);\n%! [Q,R] = qrshift (Q, R, i, j);\n%! assert (norm (vec (Q'*Q - eye (3,\"single\")), Inf), single (0), ...\n%!         1e1 * eps (\"single\"));\n%! assert (norm (vec (triu (R) - R), Inf), single (0));\n%! assert (norm (vec (Q*R - AA(:,p)), Inf), single (0), ...\n%!         norm (AA)*1e1 * eps (\"single\"));\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/quad.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"Quad.h\"\n#include \"mappers.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n#include \"Quad-opts.cc\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Global pointer for user defined function required by quadrature functions.\nstatic octave_value quad_fcn;\n\n// Have we warned about imaginary values returned from user function?\nstatic bool warned_imaginary = false;\n\n// Is this a recursive call?\nstatic int call_depth = 0;\n\nstatic double\nquad_user_function (double x)\n{\n  double retval = 0.0;\n\n  octave_value_list args;\n  args(0) = x;\n\n  if (quad_fcn.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (quad_fcn, args, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"quad\");\n        }\n\n      if (! tmp.length () || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"quad\");\n\n      if (! warned_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"quad: ignoring imaginary part returned from user-supplied function\");\n          warned_imaginary = true;\n        }\n\n      retval = tmp(0).xdouble_value (\"quad: expecting user supplied function to return numeric value\");\n    }\n\n  return retval;\n}\n\nstatic float\nquad_float_user_function (float x)\n{\n  float retval = 0.0;\n\n  octave_value_list args;\n  args(0) = x;\n\n  if (quad_fcn.is_defined ())\n    {\n      octave_value_list tmp;\n\n      try\n        {\n          interpreter& interp = __get_interpreter__ ();\n\n          tmp = interp.feval (quad_fcn, args, 1);\n        }\n      catch (execution_exception& ee)\n        {\n          err_user_supplied_eval (ee, \"quad\");\n        }\n\n      if (! tmp.length () || ! tmp(0).is_defined ())\n        err_user_supplied_eval (\"quad\");\n\n      if (! warned_imaginary && tmp(0).iscomplex ())\n        {\n          warning (\"quad: ignoring imaginary part returned from user-supplied function\");\n          warned_imaginary = true;\n        }\n\n      retval = tmp(0).xfloat_value (\"quad: expecting user supplied function to return numeric value\");\n    }\n\n  return retval;\n}\n\nDEFMETHODX (\"quad\", Fquad, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{q} =} quad (@var{f}, @var{a}, @var{b})\n@deftypefnx {} {@var{q} =} quad (@var{f}, @var{a}, @var{b}, @var{tol})\n@deftypefnx {} {@var{q} =} quad (@var{f}, @var{a}, @var{b}, @var{tol}, @var{sing})\n@deftypefnx {} {[@var{q}, @var{ier}, @var{nfev}, @var{err}] =} quad (@dots{})\nNumerically evaluate the integral of @var{f} from @var{a} to @var{b} using\nFortran routines from @w{@sc{quadpack}}.\n\n@var{f} is a function handle, inline function, or a string containing the\nname of the function to evaluate.  The function must have the form @code{y =\nf (x)} where @var{y} and @var{x} are scalars.\n\n@var{a} and @var{b} are the lower and upper limits of integration.  Either\nor both may be infinite.\n\nThe optional argument @var{tol} is a vector that specifies the desired\naccuracy of the result.  The first element of the vector is the desired\nabsolute tolerance, and the second element is the desired relative\ntolerance.  To choose a relative test only, set the absolute\ntolerance to zero.  To choose an absolute test only, set the relative\ntolerance to zero.  Both tolerances default to @code{sqrt (eps)} or\napproximately 1.5e-8.\n\nThe optional argument @var{sing} is a vector of values at which the\nintegrand is known to be singular.\n\nThe result of the integration is returned in @var{q}.\n\n@var{ier} contains an integer error code (0 indicates a successful\nintegration).\n\n@var{nfev} indicates the number of function evaluations that were\nmade.\n\n@var{err} contains an estimate of the error in the solution.\n\nThe function @code{quad_options} can set other optional parameters for\n@code{quad}.\n\nNote: because @code{quad} is written in Fortran it cannot be called\nrecursively.  This prevents its use in integrating over more than one\nvariable by routines @code{dblquad} and @code{triplequad}.\n@seealso{quad_options, quadv, quadl, quadgk, quadcc, trapz, dblquad, triplequad}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 3 || nargin > 5)\n    print_usage ();\n\n  warned_imaginary = false;\n\n  unwind_protect_var<int> restore_var (call_depth);\n  call_depth++;\n\n  if (call_depth > 1)\n    error (\"quad: invalid recursive call\");\n\n  quad_fcn = get_function_handle (interp, args(0), \"x\");\n\n  octave_value_list retval;\n\n  if (args(1).is_single_type () || args(2).is_single_type ())\n    {\n      float a = args(1).xfloat_value (\"quad: lower limit of integration A must be a scalar\");\n      float b = args(2).xfloat_value (\"quad: upper limit of integration B must be a scalar\");\n\n      int indefinite = 0;\n      FloatIndefQuad::IntegralType indef_type\n        = FloatIndefQuad::doubly_infinite;\n      float bound = 0.0;\n      if (math::isinf (a) && math::isinf (b))\n        {\n          indefinite = 1;\n          indef_type = FloatIndefQuad::doubly_infinite;\n        }\n      else if (math::isinf (a))\n        {\n          indefinite = 1;\n          bound = b;\n          indef_type = FloatIndefQuad::neg_inf_to_bound;\n        }\n      else if (math::isinf (b))\n        {\n          indefinite = 1;\n          bound = a;\n          indef_type = FloatIndefQuad::bound_to_inf;\n        }\n\n      octave_idx_type ier = 0;\n      octave_idx_type nfev = 0;\n      float abserr = 0.0;\n      float val = 0.0;\n      bool have_sing = false;\n      FloatColumnVector sing;\n      FloatColumnVector tol;\n\n      switch (nargin)\n        {\n        case 5:\n          if (indefinite)\n            error (\"quad: singularities not allowed on infinite intervals\");\n\n          have_sing = true;\n\n          sing = args(4).xfloat_vector_value (\"quad: fifth argument SING must be a vector of singularities\");\n          OCTAVE_FALLTHROUGH;\n\n        case 4:\n          tol = args(3).xfloat_vector_value (\"quad: TOL must be a 1 or 2-element vector\");\n\n          switch (tol.numel ())\n            {\n            case 2:\n              quad_opts.set_single_precision_relative_tolerance (tol (1));\n              OCTAVE_FALLTHROUGH;\n\n            case 1:\n              quad_opts.set_single_precision_absolute_tolerance (tol (0));\n              break;\n\n            default:\n              error (\"quad: TOL must be a 1 or 2-element vector\");\n            }\n          OCTAVE_FALLTHROUGH;\n\n        case 3:\n          if (indefinite)\n            {\n              FloatIndefQuad iq (quad_float_user_function, bound,\n                                 indef_type);\n              iq.set_options (quad_opts);\n              val = iq.float_integrate (ier, nfev, abserr);\n            }\n          else\n            {\n              if (have_sing)\n                {\n                  FloatDefQuad dq (quad_float_user_function, a, b, sing);\n                  dq.set_options (quad_opts);\n                  val = dq.float_integrate (ier, nfev, abserr);\n                }\n              else\n                {\n                  FloatDefQuad dq (quad_float_user_function, a, b);\n                  dq.set_options (quad_opts);\n                  val = dq.float_integrate (ier, nfev, abserr);\n                }\n            }\n          break;\n\n        default:\n          error (\"quad: unexpected nargin = %d - please report this bug\", nargin);\n          break;\n        }\n\n      retval = ovl (val, ier, nfev, abserr);\n\n    }\n  else\n    {\n      double a = args(1).xdouble_value (\"quad: lower limit of integration A must be a scalar\");\n      double b = args(2).xdouble_value (\"quad: upper limit of integration B must be a scalar\");\n\n      int indefinite = 0;\n      IndefQuad::IntegralType indef_type = IndefQuad::doubly_infinite;\n      double bound = 0.0;\n      if (math::isinf (a) && math::isinf (b))\n        {\n          indefinite = 1;\n          indef_type = IndefQuad::doubly_infinite;\n        }\n      else if (math::isinf (a))\n        {\n          indefinite = 1;\n          bound = b;\n          indef_type = IndefQuad::neg_inf_to_bound;\n        }\n      else if (math::isinf (b))\n        {\n          indefinite = 1;\n          bound = a;\n          indef_type = IndefQuad::bound_to_inf;\n        }\n\n      octave_idx_type ier = 0;\n      octave_idx_type nfev = 0;\n      double abserr = 0.0;\n      double val = 0.0;\n      bool have_sing = false;\n      ColumnVector sing;\n      ColumnVector tol;\n\n      switch (nargin)\n        {\n        case 5:\n          if (indefinite)\n            error (\"quad: singularities not allowed on infinite intervals\");\n\n          have_sing = true;\n\n          sing = args(4).xvector_value (\"quad: fifth argument SING must be a vector of singularities\");\n          OCTAVE_FALLTHROUGH;\n\n        case 4:\n          tol = args(3).xvector_value (\"quad: TOL must be a 1 or 2-element vector\");\n\n          switch (tol.numel ())\n            {\n            case 2:\n              quad_opts.set_relative_tolerance (tol (1));\n              OCTAVE_FALLTHROUGH;\n\n            case 1:\n              quad_opts.set_absolute_tolerance (tol (0));\n              break;\n\n            default:\n              error (\"quad: TOL must be a 1 or 2-element vector\");\n            }\n          OCTAVE_FALLTHROUGH;\n\n        case 3:\n          if (indefinite)\n            {\n              IndefQuad iq (quad_user_function, bound, indef_type);\n              iq.set_options (quad_opts);\n              val = iq.integrate (ier, nfev, abserr);\n            }\n          else\n            {\n              if (have_sing)\n                {\n                  DefQuad dq (quad_user_function, a, b, sing);\n                  dq.set_options (quad_opts);\n                  val = dq.integrate (ier, nfev, abserr);\n                }\n              else\n                {\n                  DefQuad dq (quad_user_function, a, b);\n                  dq.set_options (quad_opts);\n                  val = dq.integrate (ier, nfev, abserr);\n                }\n            }\n          break;\n\n        default:\n          error (\"quad: unexpected nargin = %d - please report this bug\", nargin);\n          break;\n        }\n\n      retval = ovl (val, ier, nfev, abserr);\n    }\n\n  return retval;\n}\n\n/*\n%!function y = __f (x)\n%!  y = x + 1;\n%!endfunction\n\n%!test\n%! [v, ier, nfev, err] = quad (\"__f\", 0, 5);\n%! assert (ier, 0);\n%! assert (v, 17.5, sqrt (eps));\n%! assert (nfev > 0);\n%! assert (err < sqrt (eps));\n\n%!test\n%! [v, ier, nfev, err] = quad (\"__f\", single (0), single (5));\n%! assert (ier, 0);\n%! assert (v, 17.5, sqrt (eps (\"single\")));\n%! assert (nfev > 0);\n%! assert (err < sqrt (eps (\"single\")));\n\n%!function y = __f (x)\n%!  y = x .* sin (1 ./ x) .* sqrt (abs (1 - x));\n%!endfunction\n\n%!test\n%!  [v, ier, nfev, err] = quad (\"__f\", 0.001, 3);\n%! assert (ier == 0 || ier == 1);\n%! assert (v, 1.98194120273598, sqrt (eps));\n%! assert (nfev > 0);\n\n%!test\n%!  [v, ier, nfev, err] = quad (@__f, 0.001, 3);\n%! assert (ier == 0 || ier == 1);\n%! assert (v, 1.98194120273598, sqrt (eps));\n%! assert (nfev > 0);\n\n%!test\n%!  fstr = \"x .* sin (1 ./ x) .* sqrt (abs (1 - x))\";\n%!  [v, ier, nfev, err] = quad (fstr, 0.001, 3);\n%! assert (ier == 0 || ier == 1);\n%! assert (v, 1.98194120273598, sqrt (eps));\n%! assert (nfev > 0);\n\n%!test\n%!  anon_fcn = @(x) x .* sin (1 ./ x) .* sqrt (abs (1 - x));\n%!  [v, ier, nfev, err] = quad (anon_fcn, 0.001, 3);\n%! assert (ier == 0 || ier == 1);\n%! assert (v, 1.98194120273598, sqrt (eps));\n%! assert (nfev > 0);\n\n%!test\n%!  inline_fcn = inline (\"x .* sin (1 ./ x) .* sqrt (abs (1 - x))\", \"x\");\n%!  [v, ier, nfev, err] = quad (inline_fcn, 0.001, 3);\n%! assert (ier == 0 || ier == 1);\n%! assert (v, 1.98194120273598, sqrt (eps));\n%! assert (nfev > 0);\n\n%!test\n%!  [v, ier, nfev, err] = quad (\"__f\", single (0.001), single (3));\n%! assert (ier == 0 || ier == 1);\n%! assert (v, 1.98194120273598, sqrt (eps (\"single\")));\n%! assert (nfev > 0);\n\n%!error quad ()\n%!error quad (\"__f\", 1, 2, 3, 4, 5)\n\n%!test\n%! quad_options (\"absolute tolerance\", eps);\n%! assert (quad_options (\"absolute tolerance\") == eps);\n\n%!error quad_options (1, 2, 3)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/quadcc.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <algorithm>\n\n#include \"lo-ieee.h\"\n#include \"oct-locbuf.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n// Extended debugging.\n#define OCTAVE_QUADCC_DEBUG 0\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Define the minimum size of the interval heap.\nstatic const int MIN_CQUAD_HEAPSIZE = 200;\n\n// Data of a single interval.\nstruct cquad_ival\n{\n  double a, b;\n  double c[64];\n  double fx[33];\n  double igral, err;\n  int depth, rdepth, ndiv;\n};\n\n// Define relative tolerance used when deciding to drop an interval.\nstatic constexpr double DROP_RELTOL = std::numeric_limits<double>::epsilon () * 10;\n\n// Some constants and matrices that we'll need.\n\nstatic const double xi[33] =\n{\n  -1., -0.99518472667219688624, -0.98078528040323044912,\n    -0.95694033573220886493, -0.92387953251128675612,\n    -0.88192126434835502970, -0.83146961230254523708,\n    -0.77301045336273696082, -0.70710678118654752440,\n    -0.63439328416364549822, -0.55557023301960222475,\n    -0.47139673682599764857, -0.38268343236508977173,\n    -0.29028467725446236764, -0.19509032201612826785,\n    -0.098017140329560601995, 0., 0.098017140329560601995,\n    0.19509032201612826785, 0.29028467725446236764, 0.38268343236508977173,\n    0.47139673682599764857, 0.55557023301960222475, 0.63439328416364549822,\n    0.70710678118654752440, 0.77301045336273696082, 0.83146961230254523708,\n    0.88192126434835502970, 0.92387953251128675612, 0.95694033573220886493,\n    0.98078528040323044912, 0.99518472667219688624, 1.\n  };\n\nstatic const double bee[68] =\n{\n  0.00000000000000e+00, 2.28868854108532e-01, 0.00000000000000e+00,\n  -8.15740215243451e-01, 0.00000000000000e+00, 5.31212715259731e-01,\n  0.00000000000000e+00, 1.38538036812454e-02, 0.00000000000000e+00,\n  3.74405228908818e-02, 0.00000000000000e+00, 2.12224115039342e-01,\n  0.00000000000000e+00, -8.16362644507898e-01, 0.00000000000000e+00,\n  5.35648426691481e-01, 0.00000000000000e+00, 1.52417902753662e-03,\n  0.00000000000000e+00, 2.63058840550873e-03, 0.00000000000000e+00,\n  4.15292106318904e-03, 0.00000000000000e+00, 6.97106011119775e-03,\n  0.00000000000000e+00, 1.35535708431058e-02, 0.00000000000000e+00,\n  3.52132898424856e-02, 0.00000000000000e+00, 2.06946714741884e-01,\n  0.00000000000000e+00, -8.15674251283876e-01, 0.00000000000000e+00,\n  5.38841175520580e-01, 0.00000000000000e+00, 1.84909689577590e-04,\n  0.00000000000000e+00, 2.90936325007499e-04, 0.00000000000000e+00,\n  3.84877750950089e-04, 0.00000000000000e+00, 4.86436656735046e-04,\n  0.00000000000000e+00, 6.08688640346879e-04, 0.00000000000000e+00,\n  7.66732830740331e-04, 0.00000000000000e+00, 9.82753336104205e-04,\n  0.00000000000000e+00, 1.29359957505615e-03, 0.00000000000000e+00,\n  1.76616363801885e-03, 0.00000000000000e+00, 2.53323433039089e-03,\n  0.00000000000000e+00, 3.88872172121956e-03, 0.00000000000000e+00,\n  6.58635106468291e-03, 0.00000000000000e+00, 1.30326736343254e-02,\n  0.00000000000000e+00, 3.44353850696714e-02, 0.00000000000000e+00,\n  2.05025409531915e-01, 0.00000000000000e+00, -8.14985893995401e-01,\n  0.00000000000000e+00, 5.40679930965238e-01\n};\n\nstatic const double Lalpha[33] =\n{\n  5.77350269189626e-01, 5.16397779494322e-01, 5.07092552837110e-01,\n  5.03952630678970e-01, 5.02518907629606e-01, 5.01745206004255e-01,\n  5.01280411827603e-01, 5.00979432868120e-01, 5.00773395667191e-01,\n  5.00626174321759e-01, 5.00517330712619e-01, 5.00434593736979e-01,\n  5.00370233297676e-01, 5.00319182924304e-01, 5.00278009473803e-01,\n  5.00244319584578e-01, 5.00216403386025e-01, 5.00193012939056e-01,\n  5.00173220168024e-01, 5.00156323280355e-01, 5.00141783641018e-01,\n  5.00129182278347e-01, 5.00118189340972e-01, 5.00108542278496e-01,\n  5.00100030010004e-01, 5.00092481273333e-01, 5.00085755939229e-01,\n  5.00079738458365e-01, 5.00074332862969e-01, 5.00069458915387e-01,\n  5.00065049112355e-01, 5.00061046334395e-01, 5.00057401986298e-01\n};\n\nstatic const double Lgamma[33] =\n{\n  0.0, 0.0, 5.16397779494322e-01, 5.07092552837110e-01, 5.03952630678970e-01,\n  5.02518907629606e-01, 5.01745206004255e-01, 5.01280411827603e-01,\n  5.00979432868120e-01, 5.00773395667191e-01, 5.00626174321759e-01,\n  5.00517330712619e-01, 5.00434593736979e-01, 5.00370233297676e-01,\n  5.00319182924304e-01, 5.00278009473803e-01, 5.00244319584578e-01,\n  5.00216403386025e-01, 5.00193012939056e-01, 5.00173220168024e-01,\n  5.00156323280355e-01, 5.00141783641018e-01, 5.00129182278347e-01,\n  5.00118189340972e-01, 5.00108542278496e-01, 5.00100030010003e-01,\n  5.00092481273333e-01, 5.00085755939229e-01, 5.00079738458365e-01,\n  5.00074332862969e-01, 5.00069458915387e-01, 5.00065049112355e-01,\n  5.00061046334395e-01\n};\n\nstatic const double V1inv[5 * 5] =\n{\n  .47140452079103168293e-1, .37712361663282534635, .56568542494923801952,\n  .37712361663282534635, .47140452079103168293e-1,\n  -.81649658092772603273e-1, -.46188021535170061160, 0,\n  .46188021535170061160, .81649658092772603273e-1, .15058465048420853962,\n  .12046772038736683169, -.54210474174315074262, .12046772038736683169,\n  .15058465048420853962, -.21380899352993950775, .30237157840738178177, -0.,\n  -.30237157840738178177, .21380899352993950775, .10774960475223581324,\n  -.21549920950447162648, .21549920950447162648, -.21549920950447162648,\n  .10774960475223581324\n};\n\nstatic const double V2inv[9 * 9] =\n{\n  .11223917161691230546e-1, .10339219839658349826, .19754094204576565761,\n  .25577315077753587922, .27835314560994251755, .25577315077753587922,\n  .19754094204576565761, .10339219839658349826, .11223917161691230546e-1,\n  -.19440394783993476970e-1, -.16544884625069155470, -.24193725566041460608,\n  -.16953338808305493604, 0.0, .16953338808305493604, .24193725566041460608,\n  .16544884625069155470, .19440394783993476970e-1, .26466393115406349388e-1,\n  .17766815796285469394, .11316664642449611462, -.16306601003711325980,\n  -.30847037493128779631, -.16306601003711325980, .11316664642449611462,\n  .17766815796285469394, .26466393115406349388e-1,\n  -.32395302049990834508e-1, -.15521142532414866547,\n  .88573492664788602740e-1, .29570405784974857322, 0.0,\n  -.29570405784974857322, -.88573492664788602740e-1, .15521142532414866547,\n  .32395302049990834508e-1, .41442155673936851246e-1,\n  .98186757907405608245e-1, -.23056908429499411784,\n  -.68047008326360625520e-1, .31797435808002456774,\n  -.68047008326360625520e-1, -.23056908429499411784,\n  .98186757907405608245e-1, .41442155673936851246e-1,\n  -.49981120317798783134e-1, -.24861810572835756217e-1,\n  .23561326072010832539, -.24472785656448415351, 0.0, .24472785656448415351,\n  -.23561326072010832539, .24861810572835756217e-1,\n  .49981120317798783134e-1, .79691635865674781228e-1,\n  -.95725617891693941833e-1, -.57957553356854386344e-1,\n  .21164072460540271452, -.27529837844505833514, .21164072460540271452,\n  -.57957553356854386344e-1, -.95725617891693941833e-1,\n  .79691635865674781228e-1,\n  -.10894869830716590913, .20131094491947531782, -.15407672674888869038,\n  .83385723639789791384e-1, 0.0, -.83385723639789791384e-1,\n  .15407672674888869038, -.20131094491947531782, .10894869830716590913,\n  .54581057089643838221e-1, -.10916211417928767644, .10916211417928767644,\n  -.10916211417928767644, .10916211417928767644, -.10916211417928767644,\n  .10916211417928767644, -.10916211417928767644, .54581057089643838221e-1\n};\n\nstatic const double V3inv[17 * 17] =\n{\n  .27729677693590098996e-2, .26423663180333065153e-1,\n  .53374068493933898312e-1, .77007854739523195947e-1,\n  .98257061072911596869e-1, .11538049741786835604, .12832134344120884559,\n  .13612785914022865001, .13888293186236181317, .13612785914022865001,\n  .12832134344120884559, .11538049741786835604, .98257061072911596869e-1,\n  .77007854739523195947e-1, .53374068493933898312e-1,\n  .26423663180333065153e-1, .27729677693590098996e-2,\n  -.48029210642807413690e-2, -.44887724635478800254e-1,\n  -.85409520147301089416e-1, -.11090267822061423050, -.12033983162705862441,\n  -.11102786862182788886, -.85054870109799336515e-1,\n  -.45998467987742225160e-1, 0.0, .45998467987742225160e-1,\n  .85054870109799336515e-1, .11102786862182788886, .12033983162705862441,\n  .11090267822061423050, .85409520147301089416e-1, .44887724635478800254e-1,\n  .48029210642807413690e-2, .62758546879582030087e-2,\n  .55561297093529155869e-1,\n  .93281491021051539742e-1, .92320151237493695139e-1,\n  .55077987469605684531e-1,\n  -.96998141716497488255e-2, -.80285961895427405567e-1,\n  -.13496839655913850224,\n  -.15512521776684524331, -.13496839655913850224, -.80285961895427405567e-1,\n  -.96998141716497488255e-2, .55077987469605684531e-1,\n  .92320151237493695139e-1, .93281491021051539742e-1,\n  .55561297093529155869e-1, .62758546879582030087e-2,\n  -.74850969394858555939e-2, -.61751608943839234096e-1,\n  -.82974150437304275958e-1, -.38437763431942633378e-1,\n  .45745502025779701366e-1, .12369235652734542162, .14720439712852868239,\n  .98768034347019704401e-1, 0.0,\n  -.98768034347019704401e-1, -.14720439712852868239, -.12369235652734542162,\n  -.45745502025779701366e-1, .38437763431942633378e-1,\n  .82974150437304275958e-1, .61751608943839234096e-1,\n  .74850969394858555939e-2, .86710099994384056338e-2,\n  .64006230103659573344e-1, .58517426396091675690e-1,\n  -.29743410528985802680e-1,\n  -.11934127779157114754, -.12686773515361299409, -.30729137153877447035e-1,\n  .97307836256600731568e-1, .15635811574451401023, .97307836256600731568e-1,\n  -.30729137153877447035e-1, -.12686773515361299409, -.11934127779157114754,\n  -.29743410528985802680e-1, .58517426396091675690e-1,\n  .64006230103659573344e-1, .86710099994384056338e-2,\n  -.97486395666294840165e-2, -.62995604908060224672e-1,\n  -.24373234450275529219e-1, .87760984413626872730e-1,\n  .12205204576993351394,\n  .16216004196864002088e-1, -.12422320942156845775, -.13682714580929614678,\n  0.0, .13682714580929614678, .12422320942156845775,\n  -.16216004196864002088e-1, -.12205204576993351394,\n  -.87760984413626872730e-1, .24373234450275529219e-1,\n  .62995604908060224672e-1, .97486395666294840165e-2,\n  .10956271233750488468e-1, .58613204255294358939e-1,\n  -.13306063940736618859e-1, -.11606666444978454399,\n  -.52059598001115805639e-1, .10868540217796151849, .12594452879014618005,\n  -.44678658254872910434e-1, -.15617684362128533405,\n  -.44678658254872910434e-1, .12594452879014618005, .10868540217796151849,\n  -.52059598001115805639e-1, -.11606666444978454399,\n  -.13306063940736618859e-1, .58613204255294358939e-1,\n  .10956271233750488468e-1, -.12098893000863087230e-1,\n  -.51626244709126208453e-1, .48919433304746979330e-1,\n  .10467644465949427090,\n  -.48729879523084673782e-1, -.13668732103524749234, .28190838706814496438e-1,\n  .15434223333238741600, 0.0, -.15434223333238741600,\n  -.28190838706814496438e-1, .13668732103524749234,\n  .48729879523084673782e-1, -.10467644465949427090,\n  -.48919433304746979330e-1, .51626244709126208453e-1,\n  .12098893000863087230e-1, .13542668300437944822e-1,\n  .41712033418258689308e-1,\n  -.76190463272803434388e-1, -.58303943170068132010e-1, .12158068748245606853,\n  .42121099930651007882e-1, -.14684425840766337756,\n  -.16108203535058647043e-1, .15698075850757976092,\n  -.16108203535058647043e-1, -.14684425840766337756,\n  .42121099930651007882e-1, .12158068748245606853,\n  -.58303943170068132010e-1, -.76190463272803434388e-1,\n  .41712033418258689308e-1, .13542668300437944822e-1,\n  -.14939634995117694417e-1, -.30047246373341564039e-1,\n  .91624635082546425678e-1, -.79133374319110026377e-2,\n  -.12292558212072233355, .90013382617762643524e-1,\n  .84013717196539593395e-1, -.14813033309980695856, 0.0,\n  .14813033309980695856, -.84013717196539593395e-1,\n  -.90013382617762643524e-1,\n  .12292558212072233355, .79133374319110026377e-2, -.91624635082546425678e-1,\n  .30047246373341564039e-1, .14939634995117694417e-1,\n  .16986031342807474208e-1,\n  .15760203882617033601e-1, -.91494054040950941996e-1,\n  .70082459207876130806e-1,\n  .53390713710144539104e-1, -.14340746778352039430, .84048122493418898508e-1,\n  .72456667788091316868e-1, -.15564535320096811360,\n  .72456667788091316868e-1, .84048122493418898508e-1,\n  -.14340746778352039430, .53390713710144539104e-1,\n  .70082459207876130806e-1, -.91494054040950941996e-1,\n  .15760203882617033601e-1,\n  .16986031342807474208e-1, -.18994065631858742028e-1,\n  -.82901821370405592927e-3, .77239669773015192888e-1,\n  -.10850735431039424680, .47524484622086496464e-1,\n  .69148184871588737021e-1, -.14829314646228194928, .11992057742398672066,\n  0.0, -.11992057742398672066, .14829314646228194928,\n  -.69148184871588737021e-1, -.47524484622086496464e-1,\n  .10850735431039424680, -.77239669773015192888e-1,\n  .82901821370405592927e-3, .18994065631858742028e-1,\n  .22761703826371535132e-1, -.17728848711449643358e-1,\n  -.47496371572480503788e-1, .10659958402328690063, -.11696013966166296514,\n  .63073750910894244526e-1, .32928881123602721303e-1,\n  -.12280950532497593683, .15926189077282729505, -.12280950532497593683,\n  .32928881123602721303e-1, .63073750910894244526e-1,\n  -.11696013966166296514, .10659958402328690063, -.47496371572480503788e-1,\n  -.17728848711449643358e-1, .22761703826371535132e-1,\n  -.26493215276042203434e-1, .35579780856128386192e-1,\n  .10447309718398935122e-1, -.68616154085314996709e-1,\n  .11775363082763954214, -.13918901977011837274, .12312819418827395690,\n  -.72053565748259077905e-1, 0.0, .72053565748259077905e-1,\n  -.12312819418827395690, .13918901977011837274, -.11775363082763954214,\n  .68616154085314996709e-1, -.10447309718398935122e-1,\n  -.35579780856128386192e-1,\n  .26493215276042203434e-1, .40742523354399706918e-1,\n  -.73124912999529117195e-1, .49317266444153837821e-1,\n  -.13686605413876015320e-1, -.28342624942191100464e-1,\n  .70371855298258216249e-1, -.10600251632853603875, .12981016288391131812,\n  -.13817029659318161476, .12981016288391131812, -.10600251632853603875,\n  .70371855298258216249e-1, -.28342624942191100464e-1,\n  -.13686605413876015320e-1,\n  .49317266444153837821e-1, -.73124912999529117195e-1,\n  .40742523354399706918e-1, -.54944368958699908688e-1,\n  .10777725663147408190, -.10152395581538265428, .91369146312596428468e-1,\n  -.77703071757424700773e-1, .61050911730999815031e-1,\n  -.42052599404498348871e-1, .21438229266251454773e-1, 0.0,\n  -.21438229266251454773e-1, .42052599404498348871e-1,\n  -.61050911730999815031e-1, .77703071757424700773e-1,\n  -.91369146312596428468e-1,\n  .10152395581538265428, -.10777725663147408190, .54944368958699908688e-1,\n  .27485608464748840573e-1, -.54971216929497681146e-1,\n  .54971216929497681146e-1,\n  -.54971216929497681146e-1, .54971216929497681146e-1,\n  -.54971216929497681146e-1, .54971216929497681146e-1,\n  -.54971216929497681146e-1, .54971216929497681146e-1,\n  -.54971216929497681146e-1, .54971216929497681146e-1,\n  -.54971216929497681146e-1, .54971216929497681146e-1,\n  -.54971216929497681146e-1, .54971216929497681146e-1,\n  -.54971216929497681146e-1, .27485608464748840573e-1\n};\n\nstatic const double V4inv[33 * 33] =\n{\n  .69120897476690862600e-3, .66419939766331555194e-2,\n  .13600665164323186111e-1, .20122785860913684493e-1,\n  .26583214101668429944e-1, .32712713318999268739e-1,\n  .38576221976287138036e-1, .44033030938268925133e-1,\n  .49092709529622799673e-1, .53657949874312515646e-1,\n  .57724533144734311859e-1, .61219564530655179096e-1,\n  .64138907503837875026e-1, .66427905189318792009e-1,\n  .68088956652280022887e-1, .69083051391555695878e-1,\n  .69422738116739271449e-1, .69083051391555695878e-1,\n  .68088956652280022887e-1, .66427905189318792009e-1,\n  .64138907503837875026e-1, .61219564530655179096e-1,\n  .57724533144734311859e-1, .53657949874312515646e-1,\n  .49092709529622799673e-1, .44033030938268925133e-1,\n  .38576221976287138036e-1, .32712713318999268739e-1,\n  .26583214101668429944e-1, .20122785860913684493e-1,\n  .13600665164323186111e-1, .66419939766331555194e-2,\n  .69120897476690862600e-3, -.11972090629438798134e-2,\n  -.11448874821643225573e-1, -.23104401104002905904e-1,\n  -.33352899418646530133e-1, -.42538626424075425908e-1,\n  -.49969730733911825941e-1, -.55555454015360728353e-1,\n  -.58955533624852604918e-1, -.60126044219122513907e-1,\n  -.58959430451175833624e-1, -.55546925396227130606e-1,\n  -.49984739749347973762e-1, -.42513009141170294365e-1,\n  -.33399140950669746346e-1, -.23007690803851790829e-1,\n  -.11728275717520066169e-1, 0.0, .11728275717520066169e-1,\n  .23007690803851790829e-1, .33399140950669746346e-1,\n  .42513009141170294365e-1, .49984739749347973762e-1,\n  .55546925396227130606e-1, .58959430451175833624e-1,\n  .60126044219122513907e-1, .58955533624852604918e-1,\n  .55555454015360728353e-1, .49969730733911825941e-1,\n  .42538626424075425908e-1, .33352899418646530133e-1,\n  .23104401104002905904e-1, .11448874821643225573e-1,\n  .11972090629438798134e-2, .15501585012936019146e-2,\n  .14628781502199620482e-1, .28684915921474815271e-1,\n  .39299396074628048026e-1, .46393418975496284204e-1,\n  .48756902531094699526e-1, .46331333488337494692e-1,\n  .39012645376980228775e-1, .27452795421085791153e-1,\n  .12430953621169863781e-1, -.47682978056024928800e-2,\n  -.22825828045428973853e-1,\n  -.40195512090720278312e-1, -.55503004262826221955e-1,\n  -.67424537752827046308e-1, -.75020199300113606452e-1,\n  -.77607844312483656131e-1, -.75020199300113606452e-1,\n  -.67424537752827046308e-1, -.55503004262826221955e-1,\n  -.40195512090720278312e-1, -.22825828045428973853e-1,\n  -.47682978056024928800e-2, .12430953621169863781e-1,\n  .27452795421085791153e-1, .39012645376980228775e-1,\n  .46331333488337494692e-1, .48756902531094699526e-1,\n  .46393418975496284204e-1, .39299396074628048026e-1,\n  .28684915921474815271e-1, .14628781502199620482e-1,\n  .15501585012936019146e-2, -.18377757558949194214e-2,\n  -.17050470050949761565e-1, -.31952119564923250836e-1,\n  -.40197423449026348155e-1,\n  -.41205649520281371624e-1, -.33909965817492272248e-1,\n  -.19393664422115332144e-1, .56661049630886784692e-3,\n  .22948272173686561721e-1, .44489719570904738207e-1,\n  .61790363672287920596e-1, .72121014727028013894e-1,\n  .73627151185287858579e-1, .65784665375961398923e-1,\n  .49369676372333667559e-1, .26444326317059715065e-1, 0.0,\n  -.26444326317059715065e-1, -.49369676372333667559e-1,\n  -.65784665375961398923e-1, -.73627151185287858579e-1,\n  -.72121014727028013894e-1, -.61790363672287920596e-1,\n  -.44489719570904738207e-1, -.22948272173686561721e-1,\n  -.56661049630886784692e-3, .19393664422115332144e-1,\n  .33909965817492272248e-1, .41205649520281371624e-1,\n  .40197423449026348155e-1, .31952119564923250836e-1,\n  .17050470050949761565e-1, .18377757558949194214e-2,\n  .20942714740729767769e-2, .18935902405146518232e-1,\n  .33335840852491735126e-1, .36770680999102286065e-1,\n  .28873194534132768509e-1, .10267303017729535513e-1,\n  -.14607738306201572890e-1, -.40139568545572305818e-1,\n  -.59808326733858291561e-1, -.68528358823372627506e-1,\n  -.63306535387619244879e-1, -.44508601817574921056e-1,\n  -.15449116105605395357e-1, .17941083795006546367e-1,\n  .48747356011657242123e-1, .70329553984201665523e-1,\n  .78106117292526169663e-1, .70329553984201665523e-1,\n  .48747356011657242123e-1, .17941083795006546367e-1,\n  -.15449116105605395357e-1, -.44508601817574921056e-1,\n  -.63306535387619244879e-1, -.68528358823372627506e-1,\n  -.59808326733858291561e-1,\n  -.40139568545572305818e-1, -.14607738306201572890e-1,\n  .10267303017729535513e-1, .28873194534132768509e-1,\n  .36770680999102286065e-1, .33335840852491735126e-1,\n  .18935902405146518232e-1, .20942714740729767769e-2,\n  -.23245285491878278419e-2, -.20401404737639389919e-1,\n  -.33019548231022514097e-1, -.29709828426463720091e-1,\n  -.11760070922697422156e-1, .15987584743850393793e-1,\n  .43619012891472813485e-1, .61177322409671487721e-1,\n  .61144030218486655594e-1,\n  .41895377620089086167e-1, .80232011820644308033e-2,\n  -.30574701186675900915e-1,\n  -.62072243008844865848e-1, -.76336186183574765586e-1,\n  -.68435466095345537115e-1, -.40237669208466966207e-1, 0.0,\n  .40237669208466966207e-1, .68435466095345537115e-1,\n  .76336186183574765586e-1, .62072243008844865848e-1,\n  .30574701186675900915e-1, -.80232011820644308033e-2,\n  -.41895377620089086167e-1, -.61144030218486655594e-1,\n  -.61177322409671487721e-1, -.43619012891472813485e-1,\n  -.15987584743850393793e-1, .11760070922697422156e-1,\n  .29709828426463720091e-1, .33019548231022514097e-1,\n  .20401404737639389919e-1, .23245285491878278419e-2,\n  .25451717261579269307e-2, .21480418595666878775e-1,\n  .31177212469293007998e-1, .19816333607013379373e-1,\n  -.72439496274458793681e-2, -.38404203906598342397e-1,\n  -.57633632255322221046e-1, -.54070547403585392952e-1,\n  -.26249823354368866005e-1, .15643058212336881516e-1,\n  .54539832735118677194e-1, .73283028002473989724e-1,\n  .62835303524135936213e-1, .26175977027801048141e-1,\n  -.22193636309998606610e-1, -.62597049956093311234e-1,\n  -.78206986173170212505e-1, -.62597049956093311234e-1,\n  -.22193636309998606610e-1, .26175977027801048141e-1,\n  .62835303524135936213e-1,\n  .73283028002473989724e-1, .54539832735118677194e-1,\n  .15643058212336881516e-1,\n  -.26249823354368866005e-1, -.54070547403585392952e-1,\n  -.57633632255322221046e-1, -.38404203906598342397e-1,\n  -.72439496274458793681e-2, .19816333607013379373e-1,\n  .31177212469293007998e-1, .21480418595666878775e-1,\n  .25451717261579269307e-2, -.27506573922483820005e-2,\n  -.22224442095099251870e-1, -.27949927254215773020e-1,\n  -.80918481053370034987e-2, .25121859354449306916e-1,\n  .51563535009373061074e-1, .51936965107145960512e-1,\n  .22146626648171527753e-1,\n  -.24172689882103382748e-1, -.61731229104853568296e-1,\n  -.68477262429344201201e-1, -.38311232728303704742e-1,\n  .14160578713659552679e-1, .61248813427564184033e-1,\n  .77136328841293031805e-1, .52514801765183697988e-1, 0.0,\n  -.52514801765183697988e-1, -.77136328841293031805e-1,\n  -.61248813427564184033e-1, -.14160578713659552679e-1,\n  .38311232728303704742e-1,\n  .68477262429344201201e-1, .61731229104853568296e-1,\n  .24172689882103382748e-1,\n  -.22146626648171527753e-1, -.51936965107145960512e-1,\n  -.51563535009373061074e-1, -.25121859354449306916e-1,\n  .80918481053370034987e-2, .27949927254215773020e-1,\n  .22224442095099251870e-1, .27506573922483820005e-2,\n  .29562461131654311467e-2, .22630271480554450613e-1,\n  .23547399831373800971e-1, -.43964593440902476642e-2,\n  -.39055315767504970597e-1, -.52369643937940066804e-1,\n  -.28506131614971613422e-1, .19906048093338832322e-1,\n  .60408880866392420279e-1, .62493397473656883090e-1,\n  .21391278377641297859e-1, -.37302864786623254746e-1,\n  -.73665127933539496872e-1, -.61706142476854010202e-1,\n  -.78065168882546327888e-2, .52335307373945544428e-1,\n  .78278746279419264777e-1, .52335307373945544428e-1,\n  -.78065168882546327888e-2, -.61706142476854010202e-1,\n  -.73665127933539496872e-1, -.37302864786623254746e-1,\n  .21391278377641297859e-1, .62493397473656883090e-1,\n  .60408880866392420279e-1, .19906048093338832322e-1,\n  -.28506131614971613422e-1, -.52369643937940066804e-1,\n  -.39055315767504970597e-1, -.43964593440902476642e-2,\n  .23547399831373800971e-1, .22630271480554450613e-1,\n  .29562461131654311467e-2, -.31515718415504761303e-2,\n  -.22739451096655080673e-1, -.18157123602272119779e-1,\n  .16496480897167303621e-1, .46921166788569301124e-1,\n  .40644395739978416354e-1, -.46275803430732216900e-2,\n  -.52883375891308909486e-1, -.61116483226324111734e-1,\n  -.17411698764545629853e-1, .44773430013166822765e-1,\n  .73441577962383869198e-1, .42127368371995472815e-1,\n  -.25504645957196772465e-1, -.74126818045972742488e-1,\n  -.62780077864719287317e-1, 0.0, .62780077864719287317e-1,\n  .74126818045972742488e-1, .25504645957196772465e-1,\n  -.42127368371995472815e-1, -.73441577962383869198e-1,\n  -.44773430013166822765e-1, .17411698764545629853e-1,\n  .61116483226324111734e-1, .52883375891308909486e-1,\n  .46275803430732216900e-2, -.40644395739978416354e-1,\n  -.46921166788569301124e-1, -.16496480897167303621e-1,\n  .18157123602272119779e-1, .22739451096655080673e-1,\n  .31515718415504761303e-2, .33536559294882188208e-2,\n  .22535348942792006185e-1,\n  .12048629300953560767e-1, -.27166076791299493403e-1,\n  -.47492745604230978367e-1, -.19246623430993153174e-1,\n  .36231297307556299322e-1, .61713617181636122004e-1,\n  .25928029734266134490e-1, -.40478700752883602818e-1,\n  -.71053889866326412049e-1, -.31870824482961751482e-1,\n  .41515251100219081281e-1, .76481960760098381651e-1,\n  .36726509155999912440e-1, -.40090067032627055969e-1,\n  -.78270742903374539397e-1, -.40090067032627055969e-1,\n  .36726509155999912440e-1, .76481960760098381651e-1,\n  .41515251100219081281e-1, -.31870824482961751482e-1,\n  -.71053889866326412049e-1, -.40478700752883602818e-1,\n  .25928029734266134490e-1, .61713617181636122004e-1,\n  .36231297307556299322e-1, -.19246623430993153174e-1,\n  -.47492745604230978367e-1, -.27166076791299493403e-1,\n  .12048629300953560767e-1, .22535348942792006185e-1,\n  .33536559294882188208e-2,\n  -.35481220456925318865e-2, -.22062913693073191150e-1,\n  -.54487362861834144999e-2, .35438821865804087489e-1,\n  .40733077820527411302e-1, -.67403098138950720914e-2,\n  -.55559584405239171054e-1, -.42417050790865158745e-1,\n  .24499901971884704925e-1, .68721232891705409302e-1,\n  .34086082787461126592e-1, -.43441000373118474002e-1,\n  -.73878085292669148950e-1, -.18846995664706657127e-1,\n  .59827776178286834498e-1, .70644634584085901794e-1, 0.0,\n  -.70644634584085901794e-1, -.59827776178286834498e-1,\n  .18846995664706657127e-1, .73878085292669148950e-1,\n  .43441000373118474002e-1, -.34086082787461126592e-1,\n  -.68721232891705409302e-1, -.24499901971884704925e-1,\n  .42417050790865158745e-1, .55559584405239171054e-1,\n  .67403098138950720914e-2, -.40733077820527411302e-1,\n  -.35438821865804087489e-1, .54487362861834144999e-2,\n  .22062913693073191150e-1, .35481220456925318865e-2,\n  .37554176816665075631e-2, .21297045781589919482e-1,\n  -.13327293083183431816e-2,\n  -.40635299172764596484e-1, -.27659860508374175359e-1,\n  .31089232744083445986e-1, .56113781541334176109e-1,\n  .37577840643257763400e-2, -.60511227350664590865e-1,\n  -.46670556446129053853e-1, .33263195878575888247e-1,\n  .72757324720645228775e-1, .15011712351692283635e-1,\n  -.65601212994924119078e-1, -.60016855838843789772e-1,\n  .26220858553188665966e-1, .78322776605833552980e-1,\n  .26220858553188665966e-1, -.60016855838843789772e-1,\n  -.65601212994924119078e-1,\n  .15011712351692283635e-1, .72757324720645228775e-1,\n  .33263195878575888247e-1,\n  -.46670556446129053853e-1, -.60511227350664590865e-1,\n  .37577840643257763400e-2, .56113781541334176109e-1,\n  .31089232744083445986e-1, -.27659860508374175359e-1,\n  -.40635299172764596484e-1, -.13327293083183431816e-2,\n  .21297045781589919482e-1, .37554176816665075631e-2,\n  -.39566995305720591229e-2, -.20291873414438919995e-1,\n  .80617453830770930551e-2, .42270189157016547906e-1,\n  .10332624526759093004e-1, -.48054759547616142024e-1,\n  -.37678032941171643972e-1,\n  .36617192625732482394e-1, .61009425973424865714e-1,\n  -.95589113168026591466e-2,\n  -.71023202645076922361e-1, -.25097788086808784456e-1,\n  .62406621963267050244e-1, .56907293171100693511e-1,\n  -.36435383083882206257e-1, -.75790105119208756348e-1, 0.0,\n  .75790105119208756348e-1, .36435383083882206257e-1,\n  -.56907293171100693511e-1, -.62406621963267050244e-1,\n  .25097788086808784456e-1, .71023202645076922361e-1,\n  .95589113168026591466e-2,\n  -.61009425973424865714e-1, -.36617192625732482394e-1,\n  .37678032941171643972e-1, .48054759547616142024e-1,\n  -.10332624526759093004e-1, -.42270189157016547906e-1,\n  -.80617453830770930551e-2, .20291873414438919995e-1,\n  .39566995305720591229e-2, .41776092289182138591e-2,\n  .19013221163904414395e-1, -.14420609729849899876e-1,\n  -.40259160586844441220e-1, .86327811113710831649e-2,\n  .53564430703021034399e-1, .65469185402150431933e-2,\n  -.60383116311280629856e-1,\n  -.25657793784058876939e-1, .58745680576829226900e-1,\n  .45649937869034420296e-1,\n  -.49167932056844167772e-1, -.62696614328552187977e-1,\n  .32540234556426699997e-1, .74280410383464269758e-1,\n  -.11425672633410999870e-1, -.78280649404686404903e-1,\n  -.11425672633410999870e-1, .74280410383464269758e-1,\n  .32540234556426699997e-1, -.62696614328552187977e-1,\n  -.49167932056844167772e-1, .45649937869034420296e-1,\n  .58745680576829226900e-1, -.25657793784058876939e-1,\n  -.60383116311280629856e-1, .65469185402150431933e-2,\n  .53564430703021034399e-1,\n  .86327811113710831649e-2, -.40259160586844441220e-1,\n  -.14420609729849899876e-1, .19013221163904414395e-1,\n  .41776092289182138591e-2, -.43935502082478059199e-2,\n  -.17528761237509401631e-1, .20208915249153872535e-1,\n  .34734743119040669109e-1, -.26275910172353637955e-1,\n  -.46368003346018878786e-1,\n  .26800056330709381025e-1, .56681476464606609921e-1,\n  -.24749011438127255898e-1,\n  -.64934612189056658992e-1, .20333742247679279535e-1,\n  .71429299070059318651e-1,\n  -.14452513210428671266e-1, -.75793341281736586582e-1,\n  .74717094137184935270e-2, .78034921554757317374e-1, 0.0,\n  -.78034921554757317374e-1, -.74717094137184935270e-2,\n  .75793341281736586582e-1, .14452513210428671266e-1,\n  -.71429299070059318651e-1, -.20333742247679279535e-1,\n  .64934612189056658992e-1, .24749011438127255898e-1,\n  -.56681476464606609921e-1,\n  -.26800056330709381025e-1, .46368003346018878786e-1,\n  .26275910172353637955e-1,\n  -.34734743119040669109e-1, -.20208915249153872535e-1,\n  .17528761237509401631e-1, .43935502082478059199e-2,\n  .46379089482818671473e-2, .15791188144791287229e-1,\n  -.25134290048737455284e-1, -.26249795071946841205e-1,\n  .39960457575789924651e-1, .28111892450146525404e-1,\n  -.51026476400767918226e-1,\n  -.27266747278681831364e-1, .60708796647861610865e-1,\n  .23532306960642115854e-1,\n  -.68169639871532441111e-1, -.18204924701958312032e-1,\n  .73822890510656128485e-1, .11373392486424717019e-1,\n  -.77133324017644609416e-1, -.39295877480342619961e-2,\n  .78351902829418987960e-1, -.39295877480342619961e-2,\n  -.77133324017644609416e-1, .11373392486424717019e-1,\n  .73822890510656128485e-1, -.18204924701958312032e-1,\n  -.68169639871532441111e-1, .23532306960642115854e-1,\n  .60708796647861610865e-1, -.27266747278681831364e-1,\n  -.51026476400767918226e-1, .28111892450146525404e-1,\n  .39960457575789924651e-1, -.26249795071946841205e-1,\n  -.25134290048737455284e-1, .15791188144791287229e-1,\n  .46379089482818671473e-2, -.48780095920069827068e-2,\n  -.13886961667516983541e-1, .29071311049368895844e-1,\n  .15480559452075811600e-1, -.47527977686242313065e-1,\n  -.31929089844361042178e-2, .58015667638415922967e-1,\n  -.14547915466597622925e-1, -.61067668299848923244e-1,\n  .35093678009090186851e-1, .55378399159800654657e-1,\n  -.54277226474891610385e-1, -.42023830782434076509e-1,\n  .69197384645944912066e-1, .22610783557709586445e-1,\n  -.77269275900637030185e-1, 0.0, .77269275900637030185e-1,\n  -.22610783557709586445e-1,\n  -.69197384645944912066e-1, .42023830782434076509e-1,\n  .54277226474891610385e-1,\n  -.55378399159800654657e-1, -.35093678009090186851e-1,\n  .61067668299848923244e-1, .14547915466597622925e-1,\n  -.58015667638415922967e-1, .31929089844361042178e-2,\n  .47527977686242313065e-1, -.15480559452075811600e-1,\n  -.29071311049368895844e-1, .13886961667516983541e-1,\n  .48780095920069827068e-2, .51591759101720291381e-2,\n  .11747497650231330965e-1, -.31777863364694653331e-1,\n  -.34555825499804605557e-2, .47914131921157015198e-1,\n  -.22573685920142225247e-1, -.45320344390022666738e-1,\n  .49660630547172186418e-1, .25707858143963615736e-1,\n  -.68132707341917233933e-1, .67534860185243140399e-2,\n  .69268150370037450063e-1, -.41585011920451477177e-1,\n  -.51622397460510041271e-1, .68408139576363036148e-1,\n  .18981259024768933323e-1, -.78265472429342305554e-1,\n  .18981259024768933323e-1, .68408139576363036148e-1,\n  -.51622397460510041271e-1,\n  -.41585011920451477177e-1, .69268150370037450063e-1,\n  .67534860185243140399e-2,\n  -.68132707341917233933e-1, .25707858143963615736e-1,\n  .49660630547172186418e-1,\n  -.45320344390022666738e-1, -.22573685920142225247e-1,\n  .47914131921157015198e-1, -.34555825499804605557e-2,\n  -.31777863364694653331e-1, .11747497650231330965e-1,\n  .51591759101720291381e-2, -.54365757412741340377e-2,\n  -.94862516619529080191e-2, .33240472093448190877e-1,\n  -.88698898099681552229e-2,\n  -.40973252097216337576e-1, .42995673349795657065e-1,\n  .17320914507876958783e-1,\n  -.62201292691914856803e-1, .24726274174637346693e-1,\n  .51320859246515407288e-1,\n  -.62882063373810501763e-1, -.11003569131725622672e-1,\n  .73842261324108943465e-1, -.39240120294802923208e-1,\n  -.49293966443941122807e-1, .73552644778818223475e-1, 0.0,\n  -.73552644778818223475e-1, .49293966443941122807e-1,\n  .39240120294802923208e-1, -.73842261324108943465e-1,\n  .11003569131725622672e-1, .62882063373810501763e-1,\n  -.51320859246515407288e-1,\n  -.24726274174637346693e-1, .62201292691914856803e-1,\n  -.17320914507876958783e-1, -.42995673349795657065e-1,\n  .40973252097216337576e-1, .88698898099681552229e-2,\n  -.33240472093448190877e-1, .94862516619529080191e-2,\n  .54365757412741340377e-2, .57750194549356126240e-2,\n  .69981166020044116791e-2, -.33274982140403110792e-1,\n  .20297071020698356116e-1, .27898517839646066582e-1,\n  -.53368678853282030262e-1, .16656482990394548343e-1,\n  .46342901447260614255e-1,\n  -.60536796508149003365e-1, .29109107483842596340e-2,\n  .63224486124385124504e-1,\n  -.59028872851312033411e-1, -.14783105962696191734e-1,\n  .74269399241069253865e-1, -.49053677339382384625e-1,\n  -.33525466624811186739e-1, .78397349622515386647e-1,\n  -.33525466624811186739e-1, -.49053677339382384625e-1,\n  .74269399241069253865e-1, -.14783105962696191734e-1,\n  -.59028872851312033411e-1,\n  .63224486124385124504e-1, .29109107483842596340e-2,\n  -.60536796508149003365e-1,\n  .46342901447260614255e-1, .16656482990394548343e-1,\n  -.53368678853282030262e-1,\n  .27898517839646066582e-1, .20297071020698356116e-1,\n  -.33274982140403110792e-1,\n  .69981166020044116791e-2, .57750194549356126240e-2,\n  -.61100308370519200637e-2, -.44383614355738148616e-2,\n  .32011283412619094811e-1, -.29965011866372897633e-1,\n  -.10560682331349193348e-1, .51110336443392506342e-1,\n  -.45012284729681775492e-1, -.94236825555873320102e-2,\n  .60860695783141264746e-1,\n  -.55014628647083368926e-1, -.73474782382499482121e-2,\n  .66640148475243034781e-1, -.62533116045749887988e-1,\n  -.38650525912400102585e-2, .68429769005837003777e-1,\n  -.66984505412544901945e-1, 0.0, .66984505412544901945e-1,\n  -.68429769005837003777e-1, .38650525912400102585e-2,\n  .62533116045749887988e-1, -.66640148475243034781e-1,\n  .73474782382499482121e-2,\n  .55014628647083368926e-1, -.60860695783141264746e-1,\n  .94236825555873320102e-2,\n  .45012284729681775492e-1, -.51110336443392506342e-1,\n  .10560682331349193348e-1,\n  .29965011866372897633e-1, -.32011283412619094811e-1,\n  .44383614355738148616e-2,\n  .61100308370519200637e-2, .65409373892036191538e-2,\n  .16350101107071157065e-2, -.29301957285983144319e-1,\n  .36838667173388832579e-1, -.81922703976491586393e-2,\n  -.36955670021050133434e-1, .58374851095540469865e-1,\n  -.31977016246946181856e-1, -.25311073698658094646e-1,\n  .66674413950106952577e-1,\n  -.54865713324521039571e-1, -.39797027891537985440e-2,\n  .62830285264808449064e-1, -.72226313251296100676e-1,\n  .22560232697133353980e-1, .46455784709904033738e-1,\n  -.78200930751070349956e-1, .46455784709904033738e-1,\n  .22560232697133353980e-1, -.72226313251296100676e-1,\n  .62830285264808449064e-1, -.39797027891537985440e-2,\n  -.54865713324521039571e-1, .66674413950106952577e-1,\n  -.25311073698658094646e-1, -.31977016246946181856e-1,\n  .58374851095540469865e-1, -.36955670021050133434e-1,\n  -.81922703976491586393e-2, .36838667173388832579e-1,\n  -.29301957285983144319e-1, .16350101107071157065e-2,\n  .65409373892036191538e-2, -.69686180931868703196e-2,\n  .11849538727632789870e-2, .25452286414610537766e-1,\n  -.40522480651713943230e-1, .25694679053362813183e-1,\n  .14057118113748390637e-1, -.52037614725803488893e-1,\n  .58849342223684035589e-1,\n  -.25075229077361409271e-1, -.29559771094034181083e-1,\n  .68296746944165720199e-1, -.62890462146423984955e-1,\n  .14457636466274596445e-1, .45787612031322361496e-1,\n  -.77231759014655809742e-1, .57881203613910543657e-1, 0.0,\n  -.57881203613910543657e-1, .77231759014655809742e-1,\n  -.45787612031322361496e-1, -.14457636466274596445e-1,\n  .62890462146423984955e-1,\n  -.68296746944165720199e-1, .29559771094034181083e-1,\n  .25075229077361409271e-1,\n  -.58849342223684035589e-1, .52037614725803488893e-1,\n  -.14057118113748390637e-1, -.25694679053362813183e-1,\n  .40522480651713943230e-1, -.25452286414610537766e-1,\n  -.11849538727632789870e-2, .69686180931868703196e-2,\n  .75611653617520254845e-2, -.43290610418608409141e-2,\n  -.20277062025115566914e-1,\n  .40362947027704828926e-1, -.38938808024132120254e-1,\n  .11831186195916702262e-1,\n  .28476667401744525357e-1, -.59320969056617684621e-1,\n  .61101629747436200186e-1,\n  -.29514834848355389223e-1, -.20668001885001084821e-1,\n  .62923592802445122793e-1, -.73558456263588833115e-1,\n  .45314556330160999776e-1, .79031645918426015574e-2,\n  -.58136953576334689357e-1, .78538474524006405758e-1,\n  -.58136953576334689357e-1, .79031645918426015574e-2,\n  .45314556330160999776e-1, -.73558456263588833115e-1,\n  .62923592802445122793e-1, -.20668001885001084821e-1,\n  -.29514834848355389223e-1, .61101629747436200186e-1,\n  -.59320969056617684621e-1, .28476667401744525357e-1,\n  .11831186195916702262e-1, -.38938808024132120254e-1,\n  .40362947027704828926e-1, -.20277062025115566914e-1,\n  -.43290610418608409141e-2, .75611653617520254845e-2,\n  -.81505692478987769484e-2, .74297333588288568430e-2,\n  .14314212513540223314e-1, -.36711242251332751607e-1,\n  .46240027755503814626e-1, -.34921532671769023773e-1,\n  .46930051972353714773e-2,\n  .32842770336385381562e-1, -.61317813706529588466e-1,\n  .67000809902468893103e-1,\n  -.45337449655535622885e-1, .35794459576271920867e-2,\n  .41830061526027213385e-1,\n  -.72091371931944711708e-1, .74150028530317793195e-1,\n  -.46487632538609942002e-1, 0.0, .46487632538609942002e-1,\n  -.74150028530317793195e-1, .72091371931944711708e-1,\n  -.41830061526027213385e-1, -.35794459576271920867e-2,\n  .45337449655535622885e-1, -.67000809902468893103e-1,\n  .61317813706529588466e-1, -.32842770336385381562e-1,\n  -.46930051972353714773e-2, .34921532671769023773e-1,\n  -.46240027755503814626e-1, .36711242251332751607e-1,\n  -.14314212513540223314e-1, -.74297333588288568430e-2,\n  .81505692478987769484e-2, .90693182942442189743e-2,\n  -.11121000903959576737e-1, -.71308296141317458546e-2,\n  .29219439765986671645e-1, -.45820286629778129593e-1,\n  .49088381175879124421e-1, -.35614888785023038938e-1,\n  .78906970900092777895e-2,\n  .26262843038404929480e-1, -.56143674270125757857e-1,\n  .71700220472378350694e-1,\n  -.66963544500697307945e-1, .42215091779892228883e-1,\n  -.41338867413966866997e-2, -.36164891772995367321e-1,\n  .66584367783847858225e-1, -.77874712365070098328e-1,\n  .66584367783847858225e-1, -.36164891772995367321e-1,\n  -.41338867413966866997e-2, .42215091779892228883e-1,\n  -.66963544500697307945e-1,\n  .71700220472378350694e-1, -.56143674270125757857e-1,\n  .26262843038404929480e-1,\n  .78906970900092777895e-2, -.35614888785023038938e-1,\n  .49088381175879124421e-1,\n  -.45820286629778129593e-1, .29219439765986671645e-1,\n  -.71308296141317458546e-2, -.11121000903959576737e-1,\n  .90693182942442189743e-2, -.99848472706332791043e-2,\n  .14701271465939718856e-1, -.32917820356048383366e-3,\n  -.19201195309873585230e-1, .38409681836626963278e-1,\n  -.51647324405878909521e-1, .54522171113149311354e-1,\n  -.45040302741689006270e-1, .24183738595685990149e-1,\n  .42204134165479735097e-2, -.34317295181348742251e-1,\n  .59542472465494579941e-1, -.74135115907618101263e-1,\n  .74491937840566532596e-1, -.60042604725161994304e-1,\n  .33437677409000083169e-1, 0.0,\n  -.33437677409000083169e-1, .60042604725161994304e-1,\n  -.74491937840566532596e-1, .74135115907618101263e-1,\n  -.59542472465494579941e-1, .34317295181348742251e-1,\n  -.42204134165479735097e-2, -.24183738595685990149e-1,\n  .45040302741689006270e-1, -.54522171113149311354e-1,\n  .51647324405878909521e-1, -.38409681836626963278e-1,\n  .19201195309873585230e-1, .32917820356048383366e-3,\n  -.14701271465939718856e-1, .99848472706332791043e-2,\n  .11775579274769383373e-1, -.19892153937316935880e-1,\n  .95335114477449041055e-2, .57661528440359081617e-2,\n  -.23382690532380910781e-1, .40237257037170725321e-1,\n  -.53280289903551636474e-1, .59974361806023689068e-1,\n  -.58701684061992853224e-1, .49033407111597129616e-1,\n  -.31818835267847249219e-1, .90800541261162098886e-2,\n  .16272906819312603838e-1, -.40863896581186229487e-1,\n  .61346046297517367703e-1,\n  -.74896047554167268919e-1, .79632642148310325817e-1,\n  -.74896047554167268919e-1, .61346046297517367703e-1,\n  -.40863896581186229487e-1, .16272906819312603838e-1,\n  .90800541261162098886e-2, -.31818835267847249219e-1,\n  .49033407111597129616e-1, -.58701684061992853224e-1,\n  .59974361806023689068e-1, -.53280289903551636474e-1,\n  .40237257037170725321e-1, -.23382690532380910781e-1,\n  .57661528440359081617e-2, .95335114477449041055e-2,\n  -.19892153937316935880e-1,\n  .11775579274769383373e-1, -.13562702617218467450e-1,\n  .24885419969649845849e-1, -.18368693901908875583e-1,\n  .81673147806084084638e-2, .47890591326129587131e-2,\n  -.19313752945227974024e-1, .34065953398362954708e-1,\n  -.47667045133463415672e-1, .58820377816690514309e-1,\n  -.66424139824618415970e-1,\n  .69667606260856092515e-1, -.68102459384364543253e-1,\n  .61683024923302547971e-1,\n  -.50771943476441639136e-1, .36110771847327189215e-1,\n  -.18758028464284563358e-1, 0.0, .18758028464284563358e-1,\n  -.36110771847327189215e-1, .50771943476441639136e-1,\n  -.61683024923302547971e-1, .68102459384364543253e-1,\n  -.69667606260856092515e-1, .66424139824618415970e-1,\n  -.58820377816690514309e-1, .47667045133463415672e-1,\n  -.34065953398362954708e-1, .19313752945227974024e-1,\n  -.47890591326129587131e-2, -.81673147806084084638e-2,\n  .18368693901908875583e-1, -.24885419969649845849e-1,\n  .13562702617218467450e-1, .20576545037980523979e-1,\n  -.40093155172981004337e-1, .36954083167944054826e-1,\n  -.31856506837591907746e-1, .24996323181546255126e-1,\n  -.16637165210473614136e-1, .71002706773325085237e-2,\n  .32478629093205201133e-2,\n  -.14009562579050569518e-1, .24771262248780618922e-1,\n  -.35119395835433647559e-1, .44656290368574753171e-1,\n  -.53015448339647394161e-1, .59875631995693046782e-1,\n  -.64973208326045193862e-1, .68112280331082143373e-1,\n  -.69172215234062186994e-1, .68112280331082143373e-1,\n  -.64973208326045193862e-1, .59875631995693046782e-1,\n  -.53015448339647394161e-1, .44656290368574753171e-1,\n  -.35119395835433647559e-1, .24771262248780618922e-1,\n  -.14009562579050569518e-1, .32478629093205201133e-2,\n  .71002706773325085237e-2, -.16637165210473614136e-1,\n  .24996323181546255126e-1, -.31856506837591907746e-1,\n  .36954083167944054826e-1, -.40093155172981004337e-1,\n  .20576545037980523979e-1, -.27584914609096156163e-1,\n  .54904171411058497973e-1, -.54109756419563083153e-1,\n  .52794234894345577483e-1, -.50970276026831042415e-1,\n  .48655445537990983379e-1,\n  -.45872036510847994332e-1, .42646854695899611372e-1,\n  -.39010960357087507670e-1, .34999369144476467749e-1,\n  -.30650714874402762189e-1, .26006877464703437057e-1,\n  -.21112579608213651273e-1, .16014956068786763273e-1,\n  -.10763099747751940252e-1, .54075888924374485533e-2, 0.0,\n  -.54075888924374485533e-2, .10763099747751940252e-1,\n  -.16014956068786763273e-1,\n  .21112579608213651273e-1, -.26006877464703437057e-1,\n  .30650714874402762189e-1,\n  -.34999369144476467749e-1, .39010960357087507670e-1,\n  -.42646854695899611372e-1, .45872036510847994332e-1,\n  -.48655445537990983379e-1, .50970276026831042415e-1,\n  -.52794234894345577483e-1, .54109756419563083153e-1,\n  -.54904171411058497973e-1, .27584914609096156163e-1,\n  .13794141262469565740e-1, -.27588282524939131481e-1,\n  .27588282524939131481e-1, -.27588282524939131481e-1,\n  .27588282524939131481e-1, -.27588282524939131481e-1,\n  .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .27588282524939131481e-1,\n  -.27588282524939131481e-1, .13794141262469565740e-1\n};\n\nstatic const double Tleft[33 * 33] =\n{\n  1., -.86602540378443864678, 0., .33071891388307382381, 0.,\n  -.20728904939721249057, 0., .15128841196122722208, 0.,\n  -.11918864298744029244, 0., .98352013661686631224e-1, 0.,\n  -.83727065404940845733e-1, 0., .72893399403505841203e-1, 0.,\n  -.64544632643375022436e-1, 0., .57913170372415565639e-1, 0.,\n  -.52518242575729562263e-1, 0., .48043311993977520457e-1, 0.,\n  -.44271433659733990243e-1, 0., .41048928022856771981e-1, 0.,\n  -.38263878662008271459e-1, 0., .35832844026365304501e-1, 0., 0.,\n  .50000000000000000000, -.96824583655185422130, .57282196186948000082,\n  .21650635094610966169, -.35903516540862679125, -.97578093724974971969e-1,\n  .26203921611325660506, .55792409597991015609e-1, -.20644078533943456204,\n  -.36172381205961199479e-1, .17035068468874958194,\n  .25371838001497225980e-1, -.14501953125000000000,\n  -.18786835250972344757e-1, .12625507130328301066,\n  .14473795929590520582e-1, -.11179458309419422675,\n  -.11494434254897626155e-1, .10030855351241635862,\n  .93498556820544479096e-2, -.90964264465390582629e-1,\n  -.77546391824364392762e-2, .83213457337452292745e-1,\n  .65358085945588638605e-2, -.76680372422574234569e-1,\n  -.55835321940047427169e-2, .71098828931825789428e-1,\n  .48253327982967591019e-2, -.66274981937248958553e-1,\n  -.42118078245337801387e-2, .62064306433355646267e-1,\n  .37083386598903548973e-2, 0., 0., .25000000000000000000,\n  -.73950997288745200531, .83852549156242113615, -.23175620272173946716,\n  -.37791833195149451496, .25710129174850522325, .21608307321780204633,\n  -.22844049245646009157, -.14009503000335388415, .19897685605518413847,\n  .98264706042471226893e-1, -.17445445004279014046,\n  -.72761100054958328401e-1, .15463589893742108388,\n  .56056770591708784481e-1, -.13855313872640495158,\n  -.44517752443294564781e-1, .12534277657695128850,\n  .36211835346039665762e-1, -.11434398255136139683,\n  -.30033588409423828125e-1, .10506705408753910481,\n  .25313077840725783008e-1, -.97149327637744872155e-1,\n  -.21624927200393328444e-1, .90319582367202122625e-1,\n  .18688433567711780666e-1, -.84372291635345108584e-1,\n  -.16312261561845420752e-1, .79149526894804751586e-1,\n  .14362333871852474757e-1, 0., 0., 0., .12500000000000000000,\n  -.49607837082461073572, .82265291131801144317, -.59621200088559103072,\n  -.80054302859059362371e-1, .42612156697795759420,\n  -.90098145270865592887e-1, -.29769623255090078484, .13630307904779758221,\n  .21638835185708931831, -.14600247270306082052, -.16348801804014290453,\n  .14340708728599057249, .12755243353979286190, -.13661523715071346961,\n  -.10215585947881057394, .12864248070157166547, .83592528025348693602e-1,\n  -.12066728689302565222, -.69633728678718053052e-1, .11314245177331919532,\n  .58882939251410088028e-1, -.10621835858758221487,\n  -.50432266865187597572e-1, .99916834723527771581e-1,\n  .43672094283057258509e-1, -.94206380251950852413e-1,\n  -.38181356812697746418e-1, .89035739656537771225e-1,\n  .33661934598216332678e-1, 0., 0., 0., 0., .62500000000000000000e-1,\n  -.31093357409581873586, .67604086414949799246, -.75644205980613611039,\n  .28990586430124175741, .30648508196770360914, -.35801372616842500052,\n  -.91326869828709014708e-1, .31127929687500000000,\n  -.90915752838698393094e-2, -.25637381283965534330,\n  .57601077850322797594e-1, .21019685709225757945,\n  -.81244992138514014256e-1, -.17375078516720988858,\n  .92289437277967051125e-1, .14527351914265391374,\n  -.96675340792832019889e-1, -.12289485697108543415,\n  .97448175340011084006e-1, .10511755943298339844,\n  -.96242247086378239657e-1, -.90822942272780513537e-1,\n  .93966350452322132384e-1, .79189411876493712558e-1,\n  -.91139307067989309325e-1, -.69613039934383197265e-1,\n  .88062491671135767870e-1, .61646331729340817494e-1, 0., 0., 0., 0., 0.,\n  .31250000000000000000e-1, -.18684782411095934408, .50176689760410660236,\n  -.74784031498626095398, .56472001151566251186, .14842464993721351203e-1,\n  -.41162920273003120936, .20243071230196532282, .23772054897172750436,\n  -.24963810923972235950, -.12116179938394678936, .24330535483519110663,\n  .47903849781124471359e-1, -.22133299683101224293,\n  -.20542915138527200983e-2, .19653465717678146728,\n  -.26818172626509178444e-1, -.17319122357631210944,\n  .45065391411065545445e-1, .15253391395444065941,\n  -.56543897711725408302e-1, -.13469154928743585367,\n  .63632471400208840155e-1, .11941684923913523817,\n  -.67828850207933293098e-1, -.10636309084510652670,\n  .70095786922999181504e-1, .95187373095150709082e-1, 0., 0., 0., 0., 0.,\n  0., .15625000000000000000e-1, -.10909562534194485289,\n  .34842348626527747318, -.64461114561628111443, .69382480527334683659,\n  -.29551102358528827763, -.25527584713978439819, .38878771718544715394,\n  -.82956185835347407489e-2, -.31183177761966943912, .12831420840372374767,\n  .22067618205599434368, -.17569196937129496961, -.14598057000132284135,\n  .18864406621763419484, .89921002550386645767e-1, -.18571835020187122114,\n  -.48967672227195481777e-1, .17584685670380332798,\n  .19267984545067426324e-1, -.16335437520503462738,\n  .22598055455032407594e-2, .15032800884170631129,\n  -.17883358353754640871e-1, -.13774837869432209951,\n  .29227555960587143675e-1, .12604194747513151053, 0., 0., 0., 0., 0., 0.,\n  0., .78125000000000000000e-2, -.62377810244809812496e-1,\n  .23080781467370883845, -.50841310636012325368, .69834547012574056043,\n  -.52572723156526459672, .11464215704954976471e-1, .38698869011491210342,\n  -.26125646622255207507, -.16951698812361607510, .29773875898928782269,\n  .20130501202570367491e-1, -.26332493149159310198,\n  .67734613690401207009e-1, .21207315477103762715, -.11541543390889415193,\n  -.16249634759782417533, .13885887405041735068, .11996491328010275427,\n  -.14810432001630926895, -.85177658352556243411e-1, .14918860659904380587,\n  .57317789510444151564e-1, -.14569827645586660151,\n  -.35213090145965327390e-1, .13975998126844578198, 0., 0., 0., 0., 0., 0.,\n  0., 0., .39062500000000000000e-2, -.35101954600803571207e-1,\n  .14761284084133737720, -.37655033076080192966, .62410290231517322776,\n  -.64335622317683389875, .28188168266139524244, .22488495672137010675,\n  -.39393811089283576186, .75184777995770096714e-1, .28472023119398293003,\n  -.20410910833705899572, -.15590046962908511750, .23814567544617953125,\n  .54442805556829031204e-1, -.22855930338589720954,\n  .16303223615756629897e-1, .20172722433875559213,\n  -.62723406421217419404e-1, -.17012230831020922010,\n  .91754642766136561612e-1, .13927644821381121197, -.10886600968068418181,\n  -.11139075654373395292, .11797455976331702879, 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., .19531250000000000000e-2, -.19506820659607596598e-1,\n  .91865676095362231937e-1, -.26604607809696493849, .51425874205091288223,\n  -.66047561132505329292, .48660109511591303851, -.17575661168678285615e-1,\n  -.36594333408055703366, .29088854695378694533, .11318677346656537927,\n  -.31110645235730182168, .60733219161008787341e-1, .24333848233620420826,\n  -.15254312332655419708, -.15995968483455388613, .19010344455215289289,\n  .86040636766440260000e-1, -.19652589954665259945,\n  -.27633388517205837713e-1, .18660848552712880387,\n  -.15942583868416775867e-1, -.16902042462382064786,\n  .47278526495327740646e-1, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  .97656250000000000000e-3, -.10731084460857378207e-1,\n  .55939644713816406331e-1, -.18118487371914493668, .39914857299829864263,\n  -.60812322949933902435, .60011887183061967583, -.26002695805835928795,\n  -.20883922404786010096, .38988130966114638081, -.11797833550782589082,\n  -.25231824756239520077, .24817859972953934712, .90516417677868996417e-1,\n  -.26079073291293066798, .30259468817169480161e-1, .22178195264114178432,\n  -.10569877864302048175, -.16679648389266977455, .14637718550245050850,\n  .11219272032739559870, -.16359363640525750353, -.64358194509092101393e-1,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., .48828125000000000000e-3,\n  -.58542865274813470967e-2, .33461741635290096452e-1,\n  -.11979993155896201271, .29580223766987206958, -.51874761979436016742,\n  .62861483498014306968, -.44868895761051453296, .12567502628371529386e-1,\n  .35040366183235474275, -.30466868455569500886, -.70903913601490112666e-1,\n  .30822791893032512740, -.11969443264190207736, -.20764760317621313946,\n  .20629838355452128532, .95269702915334718507e-1, -.22432624768705133300,\n  -.33103381593477797101e-2, .20570036048155716333,\n  -.62208282720094518964e-1, -.17095309330441436348, 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., .24414062500000000000e-3,\n  -.31714797501871532475e-2, .19721062526127334100e-1,\n  -.77311181185536498246e-1, .21124871792841566575, -.41777980401893650886,\n  .59401977834943551650, -.56132417807488349048, .23433675061367565951,\n  .20222775295220942126, -.38280372496506190127, .14443804214023095767,\n  .22268950939178466797, -.27211314150777981984, -.34184876506180717313e-1,\n  .26006498895669734842, -.97650425186005090107e-1, -.19024527660129101293,\n  .16789164198044635671, .10875811641651905252, -.19276785058805921298, 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., .12207031250000000000e-3,\n  -.17078941137247586143e-2, .11477733754843910060e-1,\n  -.48887017020924625462e-1, .14634927241421789683, -.32156282683019547854,\n  .52165811920227223937, -.60001958466396926460, .41208501541480733755,\n  -.11366945503190350975e-2, -.33968093962672089159, .30955190935923386766,\n  .40657421856578262210e-1, -.29873400409871531764, .16094481791768257440,\n  .16876122436206497694, -.23650217045022161255, -.33070260090574765012e-1,\n  .22985258456375907796, -.68645651043827097771e-1, 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., .61035156250000000000e-4,\n  -.91501857608428649078e-3, .66085179496951987952e-2,\n  -.30383171695850355404e-1, .98840838845366876117e-1,\n  -.23855447246420318989, .43322017468145613917, -.58049033744876107191,\n  .52533893203742699346, -.20681056202371946180, -.20180000924562504384,\n  .37503922291962681797, -.15988102869837429062, -.19823558102762374094,\n  .28393023878803799622, -.11188133439357510403e-1, -.24730368377168229255,\n  .14731529061377942839, .14878558042884266021, 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., .30517578125000000000e-4,\n  -.48804277318479845551e-3, .37696080990601968396e-2,\n  -.18603912108994738255e-1, .65325006755649582964e-1,\n  -.17162960707938819795, .34411527956476971322, -.52289350347082497959,\n  .57319653625674910592, -.37662253421045430413, -.14099055105384663902e-1,\n  .33265570610216904208, -.30921265572647566661, -.19911390594166455281e-1,\n  .28738590811031797718, -.18912130469738472647, -.13235936203215819193,\n  .25076406142356675279, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., .15258789062500000000e-4, -.25928719280954633249e-3,\n  .21327398937568540428e-2, -.11244626133630732010e-1,\n  .42375605740664331966e-1, -.12031130345907846211, .26352562258934426830,\n  -.44590628258512682078, .56682835613700749379, -.49116715128261660395,\n  .17845943097110339078, .20541650677432497477, -.36739803642257458221,\n  .16776034069210108273, .17920950989905112908, -.28867732805385066532,\n  .46473465543376206337e-1, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., .76293945312500000000e-5, -.13727610943181290891e-3,\n  .11979683091449349286e-2, -.67195313034570709806e-2,\n  .27044920779931968175e-1, -.82472196498517457862e-1,\n  .19570475044896150093, -.36391620788543817693, .52241392782736588032,\n  -.54727504974907879912, .34211551468813581183, .31580472732719957762e-1,\n  -.32830006549176759667, .30563797665254420769, .64905014620683140120e-2,\n  -.27642986248995073032, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., .38146972656250000000e-5,\n  -.72454147007837596854e-4, .66859847582761390285e-3,\n  -.39751311980366118437e-2, .17015198650201528366e-1,\n  -.55443621868993855715e-1, .14157060481641692131, -.28641242619559616836,\n  .45610665490966615415, -.55262786406029265394, .45818352706035500108,\n  -.14984403004611673047, -.21163807462970713245, .36007252928843413718,\n  -.17030961385712954159, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., .19073486328125000000e-5,\n  -.38135049864067468562e-4, .37101393638555730015e-3,\n  -.23305339886279723213e-2, .10569913448297127219e-1,\n  -.36640175162216897547e-1, .10010476414320235508, -.21860074212675559892,\n  .38124757096345313719, -.52020999209879669177, .52172632730659212045,\n  -.30841620620308814614, -.50322546186721500184e-1, .32577618885114899053,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., .95367431640625000000e-6, -.20021483206955925244e-4,\n  .20481807322420625431e-3, -.13553476938058909882e-2,\n  .64919676350791905019e-2, -.23848725425069251903e-1,\n  .69384632678886421292e-1, -.16249711393618776934, .30736618106830314788,\n  -.46399909601971539157, .53765031034002467225, -.42598991476520183929,\n  .12130445348350215652, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., .47683715820312500000e-6,\n  -.10487707828484902486e-4, .11254146162337528943e-3,\n  -.78248929534271987118e-3, .39468337145306794566e-2,\n  -.15313546659475671763e-1, .47249070825218564146e-1,\n  -.11804374107101480543, .24031796927792491122, -.39629215049166341285,\n  .51629108968402548545, -.49622372075429782915, 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  .23841857910156250000e-6, -.54823314130625337326e-5,\n  .61575377321535518154e-4, -.44877834366497538134e-3,\n  .23774612048621955857e-2, -.97136347645161687796e-2,\n  .31671599547606636717e-1, -.84028665767000747480e-1,\n  .18298487576742964949, -.32647878537696945218, .46970971486488895077, 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., .11920928955078125000e-6, -.28604020001177375838e-5,\n  .33559227978295551013e-4, -.25583821662860610560e-3,\n  .14201552747787302339e-2, -.60938046986874414969e-2,\n  .20930869247951926793e-1, -.58745021125678072911e-1,\n  .13613725780285953720, -.26083988356030237586, 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  .59604644775390625000e-7, -.14898180663526043291e-5,\n  .18224991282807693921e-4, -.14504433444608833821e-3,\n  .84184722720281809548e-3, -.37846965430000478789e-2,\n  .13656355548211376864e-1, -.40409541997718853934e-1,\n  .99226988101858325902e-1, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  .29802322387695312500e-7, -.77471708843445529468e-6,\n  .98649879372606876995e-5, -.81814934772838523887e-4,\n  .49554483992403011328e-3, -.23290922072351413938e-2,\n  .88068134250844034186e-2, -.27393666952485719070e-1, 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., .14901161193847656250e-7, -.40226235946098233685e-6,\n  .53236418690561306700e-5, -.45933829691164002269e-4,\n  .28982005232838857913e-3, -.14212974043211018374e-2,\n  .56192363087488842264e-2, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  .74505805969238281250e-8, -.20858299254133430408e-6,\n  .28648457300134381744e-5, -.25677535898258910850e-4,\n  .16849420429491355445e-3, -.86062824010315834002e-3, 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., .37252902984619140625e-8, -.10801736017613096861e-6,\n  .15376606719887104015e-5, -.14296523739727437959e-4,\n  .97419023656050887203e-4, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  .18626451492309570312e-8, -.55871592916438890146e-7,\n  .82331193828137454068e-6, -.79302250528382787666e-5, 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., .93132257461547851562e-9,\n  -.28867244235852488244e-7, .43982811713864556957e-6, 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., .46566128730773925781e-9,\n  -.14899342093408253335e-7, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., .23283064365386962891e-9\n};\n\nstatic const double Tright[33 * 33] =\n{\n  1., .86602540378443864678, 0., -.33071891388307382381, 0.,\n  .20728904939721249057, 0., -.15128841196122722208, 0.,\n  .11918864298744029244, 0., -.98352013661686631224e-1, 0.,\n  .83727065404940845733e-1, 0., -.72893399403505841203e-1, 0.,\n  .64544632643375022436e-1, 0., -.57913170372415565639e-1, 0.,\n  .52518242575729562263e-1, 0., -.48043311993977520457e-1, 0.,\n  .44271433659733990243e-1, 0., -.41048928022856771981e-1, 0.,\n  .38263878662008271459e-1, 0., -.35832844026365304501e-1, 0., 0.,\n  .50000000000000000000, .96824583655185422130, .57282196186948000082,\n  -.21650635094610966169, -.35903516540862679125, .97578093724974971969e-1,\n  .26203921611325660506, -.55792409597991015609e-1, -.20644078533943456204,\n  .36172381205961199479e-1, .17035068468874958194,\n  -.25371838001497225980e-1, -.14501953125000000000,\n  .18786835250972344757e-1, .12625507130328301066,\n  -.14473795929590520582e-1, -.11179458309419422675,\n  .11494434254897626155e-1, .10030855351241635862,\n  -.93498556820544479096e-2, -.90964264465390582629e-1,\n  .77546391824364392762e-2, .83213457337452292745e-1,\n  -.65358085945588638605e-2, -.76680372422574234569e-1,\n  .55835321940047427169e-2, .71098828931825789428e-1,\n  -.48253327982967591019e-2, -.66274981937248958553e-1,\n  .42118078245337801387e-2, .62064306433355646267e-1,\n  -.37083386598903548973e-2, 0., 0., .25000000000000000000,\n  .73950997288745200531, .83852549156242113615, .23175620272173946716,\n  -.37791833195149451496, -.25710129174850522325, .21608307321780204633,\n  .22844049245646009157, -.14009503000335388415, -.19897685605518413847,\n  .98264706042471226893e-1, .17445445004279014046,\n  -.72761100054958328401e-1, -.15463589893742108388,\n  .56056770591708784481e-1, .13855313872640495158,\n  -.44517752443294564781e-1, -.12534277657695128850,\n  .36211835346039665762e-1, .11434398255136139683,\n  -.30033588409423828125e-1, -.10506705408753910481,\n  .25313077840725783008e-1, .97149327637744872155e-1,\n  -.21624927200393328444e-1, -.90319582367202122625e-1,\n  .18688433567711780666e-1, .84372291635345108584e-1,\n  -.16312261561845420752e-1, -.79149526894804751586e-1,\n  .14362333871852474757e-1, 0., 0., 0., .12500000000000000000,\n  .49607837082461073572, .82265291131801144317, .59621200088559103072,\n  -.80054302859059362371e-1, -.42612156697795759420,\n  -.90098145270865592887e-1, .29769623255090078484, .13630307904779758221,\n  -.21638835185708931831, -.14600247270306082052, .16348801804014290453,\n  .14340708728599057249, -.12755243353979286190, -.13661523715071346961,\n  .10215585947881057394, .12864248070157166547, -.83592528025348693602e-1,\n  -.12066728689302565222, .69633728678718053052e-1, .11314245177331919532,\n  -.58882939251410088028e-1, -.10621835858758221487,\n  .50432266865187597572e-1, .99916834723527771581e-1,\n  -.43672094283057258509e-1, -.94206380251950852413e-1,\n  .38181356812697746418e-1, .89035739656537771225e-1,\n  -.33661934598216332678e-1, 0., 0., 0., 0., .62500000000000000000e-1,\n  .31093357409581873586, .67604086414949799246, .75644205980613611039,\n  .28990586430124175741, -.30648508196770360914, -.35801372616842500052,\n  .91326869828709014708e-1, .31127929687500000000, .90915752838698393094e-2,\n  -.25637381283965534330, -.57601077850322797594e-1, .21019685709225757945,\n  .81244992138514014256e-1, -.17375078516720988858,\n  -.92289437277967051125e-1, .14527351914265391374,\n  .96675340792832019889e-1, -.12289485697108543415,\n  -.97448175340011084006e-1, .10511755943298339844,\n  .96242247086378239657e-1, -.90822942272780513537e-1,\n  -.93966350452322132384e-1, .79189411876493712558e-1,\n  .91139307067989309325e-1, -.69613039934383197265e-1,\n  -.88062491671135767870e-1, .61646331729340817494e-1, 0., 0., 0., 0., 0.,\n  .31250000000000000000e-1, .18684782411095934408, .50176689760410660236,\n  .74784031498626095398, .56472001151566251186, -.14842464993721351203e-1,\n  -.41162920273003120936, -.20243071230196532282, .23772054897172750436,\n  .24963810923972235950, -.12116179938394678936, -.24330535483519110663,\n  .47903849781124471359e-1, .22133299683101224293,\n  -.20542915138527200983e-2, -.19653465717678146728,\n  -.26818172626509178444e-1, .17319122357631210944,\n  .45065391411065545445e-1, -.15253391395444065941,\n  -.56543897711725408302e-1, .13469154928743585367,\n  .63632471400208840155e-1, -.11941684923913523817,\n  -.67828850207933293098e-1, .10636309084510652670,\n  .70095786922999181504e-1, -.95187373095150709082e-1, 0., 0., 0., 0., 0.,\n  0., .15625000000000000000e-1, .10909562534194485289,\n  .34842348626527747318, .64461114561628111443, .69382480527334683659,\n  .29551102358528827763, -.25527584713978439819, -.38878771718544715394,\n  -.82956185835347407489e-2, .31183177761966943912, .12831420840372374767,\n  -.22067618205599434368, -.17569196937129496961, .14598057000132284135,\n  .18864406621763419484, -.89921002550386645767e-1, -.18571835020187122114,\n  .48967672227195481777e-1, .17584685670380332798,\n  -.19267984545067426324e-1, -.16335437520503462738,\n  -.22598055455032407594e-2, .15032800884170631129,\n  .17883358353754640871e-1, -.13774837869432209951,\n  -.29227555960587143675e-1, .12604194747513151053, 0., 0., 0., 0., 0., 0.,\n  0., .78125000000000000000e-2, .62377810244809812496e-1,\n  .23080781467370883845, .50841310636012325368, .69834547012574056043,\n  .52572723156526459672, .11464215704954976471e-1, -.38698869011491210342,\n  -.26125646622255207507, .16951698812361607510, .29773875898928782269,\n  -.20130501202570367491e-1, -.26332493149159310198,\n  -.67734613690401207009e-1, .21207315477103762715, .11541543390889415193,\n  -.16249634759782417533, -.13885887405041735068, .11996491328010275427,\n  .14810432001630926895, -.85177658352556243411e-1, -.14918860659904380587,\n  .57317789510444151564e-1, .14569827645586660151,\n  -.35213090145965327390e-1, -.13975998126844578198, 0., 0., 0., 0., 0., 0.,\n  0., 0., .39062500000000000000e-2, .35101954600803571207e-1,\n  .14761284084133737720, .37655033076080192966, .62410290231517322776,\n  .64335622317683389875, .28188168266139524244, -.22488495672137010675,\n  -.39393811089283576186, -.75184777995770096714e-1, .28472023119398293003,\n  .20410910833705899572, -.15590046962908511750, -.23814567544617953125,\n  .54442805556829031204e-1, .22855930338589720954, .16303223615756629897e-1,\n  -.20172722433875559213, -.62723406421217419404e-1, .17012230831020922010,\n  .91754642766136561612e-1, -.13927644821381121197, -.10886600968068418181,\n  .11139075654373395292, .11797455976331702879, 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., .19531250000000000000e-2, .19506820659607596598e-1,\n  .91865676095362231937e-1, .26604607809696493849, .51425874205091288223,\n  .66047561132505329292, .48660109511591303851, .17575661168678285615e-1,\n  -.36594333408055703366, -.29088854695378694533, .11318677346656537927,\n  .31110645235730182168, .60733219161008787341e-1, -.24333848233620420826,\n  -.15254312332655419708, .15995968483455388613, .19010344455215289289,\n  -.86040636766440260000e-1, -.19652589954665259945,\n  .27633388517205837713e-1, .18660848552712880387, .15942583868416775867e-1,\n  -.16902042462382064786, -.47278526495327740646e-1, 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., .97656250000000000000e-3, .10731084460857378207e-1,\n  .55939644713816406331e-1, .18118487371914493668, .39914857299829864263,\n  .60812322949933902435, .60011887183061967583, .26002695805835928795,\n  -.20883922404786010096, -.38988130966114638081, -.11797833550782589082,\n  .25231824756239520077, .24817859972953934712, -.90516417677868996417e-1,\n  -.26079073291293066798, -.30259468817169480161e-1, .22178195264114178432,\n  .10569877864302048175, -.16679648389266977455, -.14637718550245050850,\n  .11219272032739559870, .16359363640525750353, -.64358194509092101393e-1,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., .48828125000000000000e-3,\n  .58542865274813470967e-2, .33461741635290096452e-1, .11979993155896201271,\n  .29580223766987206958, .51874761979436016742, .62861483498014306968,\n  .44868895761051453296, .12567502628371529386e-1, -.35040366183235474275,\n  -.30466868455569500886, .70903913601490112666e-1, .30822791893032512740,\n  .11969443264190207736, -.20764760317621313946, -.20629838355452128532,\n  .95269702915334718507e-1, .22432624768705133300,\n  -.33103381593477797101e-2, -.20570036048155716333,\n  -.62208282720094518964e-1, .17095309330441436348, 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., .24414062500000000000e-3,\n  .31714797501871532475e-2, .19721062526127334100e-1,\n  .77311181185536498246e-1, .21124871792841566575, .41777980401893650886,\n  .59401977834943551650, .56132417807488349048, .23433675061367565951,\n  -.20222775295220942126, -.38280372496506190127, -.14443804214023095767,\n  .22268950939178466797, .27211314150777981984, -.34184876506180717313e-1,\n  -.26006498895669734842, -.97650425186005090107e-1, .19024527660129101293,\n  .16789164198044635671, -.10875811641651905252, -.19276785058805921298, 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., .12207031250000000000e-3,\n  .17078941137247586143e-2, .11477733754843910060e-1,\n  .48887017020924625462e-1, .14634927241421789683, .32156282683019547854,\n  .52165811920227223937, .60001958466396926460, .41208501541480733755,\n  .11366945503190350975e-2, -.33968093962672089159, -.30955190935923386766,\n  .40657421856578262210e-1, .29873400409871531764, .16094481791768257440,\n  -.16876122436206497694, -.23650217045022161255, .33070260090574765012e-1,\n  .22985258456375907796, .68645651043827097771e-1, 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., .61035156250000000000e-4,\n  .91501857608428649078e-3, .66085179496951987952e-2,\n  .30383171695850355404e-1, .98840838845366876117e-1, .23855447246420318989,\n  .43322017468145613917, .58049033744876107191, .52533893203742699346,\n  .20681056202371946180, -.20180000924562504384, -.37503922291962681797,\n  -.15988102869837429062, .19823558102762374094, .28393023878803799622,\n  .11188133439357510403e-1, -.24730368377168229255, -.14731529061377942839,\n  .14878558042884266021, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., .30517578125000000000e-4, .48804277318479845551e-3,\n  .37696080990601968396e-2, .18603912108994738255e-1,\n  .65325006755649582964e-1, .17162960707938819795, .34411527956476971322,\n  .52289350347082497959, .57319653625674910592, .37662253421045430413,\n  -.14099055105384663902e-1, -.33265570610216904208, -.30921265572647566661,\n  .19911390594166455281e-1, .28738590811031797718, .18912130469738472647,\n  -.13235936203215819193, -.25076406142356675279, 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., .15258789062500000000e-4,\n  .25928719280954633249e-3, .21327398937568540428e-2,\n  .11244626133630732010e-1, .42375605740664331966e-1, .12031130345907846211,\n  .26352562258934426830, .44590628258512682078, .56682835613700749379,\n  .49116715128261660395, .17845943097110339078, -.20541650677432497477,\n  -.36739803642257458221, -.16776034069210108273, .17920950989905112908,\n  .28867732805385066532, .46473465543376206337e-1, 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., .76293945312500000000e-5,\n  .13727610943181290891e-3, .11979683091449349286e-2,\n  .67195313034570709806e-2, .27044920779931968175e-1,\n  .82472196498517457862e-1, .19570475044896150093, .36391620788543817693,\n  .52241392782736588032, .54727504974907879912, .34211551468813581183,\n  -.31580472732719957762e-1, -.32830006549176759667, -.30563797665254420769,\n  .64905014620683140120e-2, .27642986248995073032, 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., .38146972656250000000e-5,\n  .72454147007837596854e-4, .66859847582761390285e-3,\n  .39751311980366118437e-2, .17015198650201528366e-1,\n  .55443621868993855715e-1, .14157060481641692131, .28641242619559616836,\n  .45610665490966615415, .55262786406029265394, .45818352706035500108,\n  .14984403004611673047, -.21163807462970713245, -.36007252928843413718,\n  -.17030961385712954159, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., .19073486328125000000e-5,\n  .38135049864067468562e-4, .37101393638555730015e-3,\n  .23305339886279723213e-2, .10569913448297127219e-1,\n  .36640175162216897547e-1, .10010476414320235508, .21860074212675559892,\n  .38124757096345313719, .52020999209879669177, .52172632730659212045,\n  .30841620620308814614, -.50322546186721500184e-1, -.32577618885114899053,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., .95367431640625000000e-6, .20021483206955925244e-4,\n  .20481807322420625431e-3, .13553476938058909882e-2,\n  .64919676350791905019e-2, .23848725425069251903e-1,\n  .69384632678886421292e-1, .16249711393618776934, .30736618106830314788,\n  .46399909601971539157, .53765031034002467225, .42598991476520183929,\n  .12130445348350215652, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., .47683715820312500000e-6,\n  .10487707828484902486e-4, .11254146162337528943e-3,\n  .78248929534271987118e-3, .39468337145306794566e-2,\n  .15313546659475671763e-1, .47249070825218564146e-1, .11804374107101480543,\n  .24031796927792491122, .39629215049166341285, .51629108968402548545,\n  .49622372075429782915, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., .23841857910156250000e-6,\n  .54823314130625337326e-5, .61575377321535518154e-4,\n  .44877834366497538134e-3, .23774612048621955857e-2,\n  .97136347645161687796e-2, .31671599547606636717e-1,\n  .84028665767000747480e-1, .18298487576742964949, .32647878537696945218,\n  .46970971486488895077, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., .11920928955078125000e-6,\n  .28604020001177375838e-5, .33559227978295551013e-4,\n  .25583821662860610560e-3, .14201552747787302339e-2,\n  .60938046986874414969e-2, .20930869247951926793e-1,\n  .58745021125678072911e-1, .13613725780285953720, .26083988356030237586,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., .59604644775390625000e-7,\n  .14898180663526043291e-5, .18224991282807693921e-4,\n  .14504433444608833821e-3, .84184722720281809548e-3,\n  .37846965430000478789e-2, .13656355548211376864e-1,\n  .40409541997718853934e-1, .99226988101858325902e-1, 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., .29802322387695312500e-7, .77471708843445529468e-6,\n  .98649879372606876995e-5, .81814934772838523887e-4,\n  .49554483992403011328e-3, .23290922072351413938e-2,\n  .88068134250844034186e-2, .27393666952485719070e-1, 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., .14901161193847656250e-7, .40226235946098233685e-6,\n  .53236418690561306700e-5, .45933829691164002269e-4,\n  .28982005232838857913e-3, .14212974043211018374e-2,\n  .56192363087488842264e-2, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  .74505805969238281250e-8, .20858299254133430408e-6,\n  .28648457300134381744e-5, .25677535898258910850e-4,\n  .16849420429491355445e-3, .86062824010315834002e-3, 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., .37252902984619140625e-8, .10801736017613096861e-6,\n  .15376606719887104015e-5, .14296523739727437959e-4,\n  .97419023656050887203e-4, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  .18626451492309570312e-8, .55871592916438890146e-7,\n  .82331193828137454068e-6, .79302250528382787666e-5, 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., .93132257461547851562e-9,\n  .28867244235852488244e-7, .43982811713864556957e-6, 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., .46566128730773925781e-9,\n  .14899342093408253335e-7, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n  0., 0., .23283064365386962891e-9\n};\n\n// Allocates a workspace for the given maximum number of intervals.\n// Note that if the workspace gets filled, the intervals with the lowest\n// error estimates are dropped.  The maximum number of intervals is\n// therefore not the maximum number of intervals that will be computed,\n// but merely the size of the buffer.\n\n// Compute the product of fx with one of the inverse Vandermonde-like matrices.\n\nstatic void\nVinvfx (const double *fx, double *c, const int d)\n{\n  int i, j;\n\n  switch (d)\n    {\n    case 0:\n      for (i = 0; i <= 4; i++)\n        {\n          c[i] = 0.0;\n          for (j = 0; j <= 4; j++)\n            c[i] += V1inv[i*5 + j] * fx[j * 8];\n        }\n      break;\n    case 1:\n      for (i = 0; i <= 8; i++)\n        {\n          c[i] = 0.0;\n          for (j = 0; j <= 8; j++)\n            c[i] += V2inv[i*9 + j] * fx[j * 4];\n        }\n      break;\n    case 2:\n      for (i = 0; i <= 16; i++)\n        {\n          c[i] = 0.0;\n          for (j = 0; j <= 16; j++)\n            c[i] += V3inv[i*17 + j] * fx[j * 2];\n        }\n      break;\n    case 3:\n      for (i = 0; i <= 32; i++)\n        {\n          c[i] = 0.0;\n          for (j = 0; j <= 32; j++)\n            c[i] += V4inv[i*33 + j] * fx[j];\n        }\n      break;\n    }\n}\n\n// Downdate the interpolation given by the N coefficients C by removing\n// the nodes with indices in NaNs.\n\nstatic void\ndowndate (double *c, int n, int d, int *nans, int nnans)\n{\n  static const int bidx[4] = { 0, 6, 16, 34 };\n  double b_new[34], alpha;\n  int i, j;\n\n  for (i = 0; i <= n + 1; i++)\n    b_new[i] = bee[bidx[d] + i];\n  for (i = 0; i < nnans; i++)\n    {\n      b_new[n + 1] = b_new[n + 1] / Lalpha[n];\n      b_new[n] = (b_new[n] + xi[nans[i]] * b_new[n + 1]) / Lalpha[n - 1];\n      for (j = n - 1; j > 0; j--)\n        b_new[j] = (b_new[j] + xi[nans[i]] * b_new[j + 1]\n                    - Lgamma[j + 1] * b_new[j + 2]) / Lalpha[j - 1];\n      for (j = 0; j <= n; j++)\n        b_new[j] = b_new[j + 1];\n      alpha = c[n] / b_new[n];\n      for (j = 0; j < n; j++)\n        c[j] -= alpha * b_new[j];\n      c[n] = 0;\n      n--;\n    }\n}\n\n// The actual integration routine.\n\nDEFMETHOD (quadcc, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b})\n@deftypefnx {} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b}, @var{tol})\n@deftypefnx {} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b}, @var{tol}, @var{sing})\n@deftypefnx {} {[@var{q}, @var{err}, @var{nr_points}] =} quadcc (@dots{})\nNumerically evaluate the integral of @var{f} from @var{a} to @var{b} using\ndoubly-adaptive @nospell{Clenshaw-Curtis} quadrature.\n\n@var{f} is a function handle, inline function, or string containing the name\nof the function to evaluate.  The function @var{f} must be vectorized and\nmust return a vector of output values if given a vector of input values.\nFor example,\n\n@example\nf = @@(x) x .* sin (1./x) .* sqrt (abs (1 - x));\n@end example\n\n@noindent\nwhich uses the element-by-element ``dot'' form for all operators.\n\n@var{a} and @var{b} are the lower and upper limits of integration.  Either or\nboth limits may be infinite.  @code{quadcc} handles an infinite limit by\nsubstituting the variable of integration with @code{x = tan (pi/2*u)}.\n\nThe optional argument @var{tol} is a 1- or 2-element vector that specifies the\ndesired accuracy of the result.  The first element of the vector is the desired\nabsolute tolerance, and the second element is the desired relative tolerance.\nTo choose a relative test only, set the absolute tolerance to zero.  To choose\nan absolute test only, set the relative tolerance to zero.  The default\nabsolute tolerance is 1e-10 (1e-5 for single), and the default relative\ntolerance is 1e-6 (1e-4 for single).\n\nThe optional argument @var{sing} contains a list of points where the integrand\nhas known singularities, or discontinuities in any of its derivatives, inside\nthe integration interval.  For the example above, which has a discontinuity at\nx=1, the call to @code{quadcc} would be as follows\n\n@example\nint = quadcc (f, a, b, [], [ 1 ]);\n@end example\n\nThe result of the integration is returned in @var{q}.\n\n@var{err} is an estimate of the absolute integration error.\n\n@var{nr_points} is the number of points at which the integrand was evaluated.\n\nIf the adaptive integration did not converge, the value of @var{err} will be\nlarger than the requested tolerance.  If only a single output is requested then\na warning will be emitted when the requested tolerance is not met.  If the\nsecond output @var{err} is requested then no warning is issued and it is the\nresponsibility of the programmer to inspect and determine whether the results\nare satisfactory.\n\n@code{quadcc} is capable of dealing with non-numeric values of the integrand\nsuch as @code{NaN} or @code{Inf}.  If the integral diverges, and @code{quadcc}\ndetects this, then a warning is issued and @code{Inf} or @code{-Inf} is\nreturned.\n\nNote: @code{quadcc} is a general purpose quadrature algorithm and, as such,\nmay be less efficient for a smooth or otherwise well-behaved integrand than\nother methods such as @code{quadgk}.\n\nThe algorithm uses @nospell{Clenshaw-Curtis} quadrature rules of increasing\ndegree in each interval and bisects the interval if either the function does\nnot appear to be smooth or a rule of maximum degree has been reached.  The\nerror estimate is computed from the L2-norm of the difference between two\nsuccessive interpolations of the integrand over the nodes of the respective\nquadrature rules.\n\nReference: @nospell{P. Gonnet}, \"Increasing the Reliability of Adaptive\nQuadrature Using Explicit Interpolants\", @cite{@nospell{ACM Transactions on\nMathematical Software}}, @w{Vol.@: 37}, @w{Issue 3}, Article @w{No.@: 3}, 2010.\n@seealso{quad, quadv, quadl, quadgk, trapz, dblquad, triplequad}\n@end deftypefn */)\n{\n  // Some constants that we will need.\n  static const int n[4] = { 4, 8, 16, 32 };\n  static const int skip[4] = { 8, 4, 2, 1 };\n  static const int idx[4] = { 0, 5, 14, 31 };\n  static const double w = M_SQRT2 / 2;\n  static const int ndiv_max = 20;\n\n  // Arguments left and right.\n  int nargin = args.length ();\n  octave_value fcn;\n  double a, b, abstol, reltol, *sing;\n  bool issingle;\n\n  // Variables needed for transforming the integrand.\n  bool wrap = false;\n  double xw;\n\n  // Stuff we will need to call the integrand.\n  octave_value_list fargs, fvals;\n\n  // Actual variables (as opposed to constants above).\n  double m, h, ml, hl, mr, hr, temp;\n  double igral, err, igral_final, err_final;\n  int nivals;\n  int neval = 0;\n  int i, j, d, split;\n  int nnans, nans[33];\n  cquad_ival *iv, *ivl, *ivr;\n  double nc, ncdiff;\n\n  // Parse the input arguments.\n  if (nargin < 3)\n    print_usage ();\n\n  fcn = get_function_handle (interp, args(0), \"x\");\n\n  if (! args(1).is_real_scalar ())\n    error (\"quadcc: lower limit of integration (A) must be a real scalar\");\n  a = args(1).double_value ();\n  issingle = args(1).is_single_type ();\n\n  if (! args(2).is_real_scalar ())\n    error (\"quadcc: upper limit of integration (B) must be a real scalar\");\n  b = args(2).double_value ();\n  issingle = (issingle || args(2).is_single_type ());\n\n  if (nargin < 4 || args(3).isempty ())\n    {\n      if (issingle)\n        {\n          abstol = 1.0e-5;\n          reltol = 1.0e-4;\n        }\n      else\n        {\n          abstol = 1.0e-10;\n          reltol = 1.0e-6;\n        }\n    }\n  else if (! args(3).isnumeric () || args(3).numel () > 2)\n    error (\"quadcc: TOL must be a 1- or 2-element vector [AbsTol, RelTol]\");\n  else\n    {\n      NDArray tol = args(3).array_value ();\n\n      abstol = tol(0);\n      if (abstol < 0)\n        error (\"quadcc: absolute tolerance must be >=0\");\n\n      if (tol.numel () == 1)\n        {\n          if (issingle)\n            reltol = 1.0e-4;\n          else\n            reltol = 1.0e-6;\n        }\n      else\n        {\n          reltol = tol(1);\n          if (reltol < 0)\n            error (\"quadcc: relative tolerance must be >=0\");\n        }\n    }\n\n  if (nargin < 5)\n    nivals = 1;\n  else if (! (args(4).is_real_scalar () || args(4).is_real_matrix ()))\n    error (\"quadcc: list of singularities (SING) must be a vector of real values\");\n  else\n    nivals = 1 + args(4).numel ();\n\n  int cquad_heapsize = (nivals >= MIN_CQUAD_HEAPSIZE ? nivals + 1\n                        : MIN_CQUAD_HEAPSIZE);\n  // The interval heap.\n  OCTAVE_LOCAL_BUFFER (cquad_ival, ivals, cquad_heapsize);\n  OCTAVE_LOCAL_BUFFER (double, iivals, cquad_heapsize);\n  OCTAVE_LOCAL_BUFFER (int, heap, cquad_heapsize);\n\n  if (nivals == 1)\n    {\n      iivals[0] = a;\n      iivals[1] = b;\n    }\n  else\n    {\n      // Intervals around singularities.\n      NDArray arr = args(4).array_value ();\n      sing = arr.rwdata ();\n      iivals[0] = a;\n      std::copy_n (sing, nivals-1, iivals+1);\n      iivals[nivals] = b;\n    }\n\n  // If a or b are +/-Inf, transform the integral.\n  if (math::isinf (a) || math::isinf (b))\n    {\n      wrap = true;\n      for (i = 0; i < nivals + 1; i++)\n        if (math::isinf (iivals[i]))\n          iivals[i] = std::copysign (1.0, iivals[i]);\n        else\n          iivals[i] = 2.0 * atan (iivals[i]) / M_PI;\n    }\n\n  // Initialize the heaps.\n  for (i = 0; i < cquad_heapsize; i++)\n    heap[i] = i;\n\n  // Create the first interval(s).\n  igral = 0.0;\n  err = 0.0;\n  for (j = 0; j < nivals; j++)\n    {\n      // Initialize the interval.\n      iv = &(ivals[heap[j]]);\n      m = (iivals[j] + iivals[j + 1]) / 2;\n      h = (iivals[j + 1] - iivals[j]) / 2;\n      nnans = 0;\n      ColumnVector ex (33);\n      if (wrap)\n        {\n          for (i = 0; i <= n[3]; i++)\n            ex(i) = tan (M_PI/2 * (m + xi[i]*h));\n        }\n      else\n        {\n          for (i = 0; i <= n[3]; i++)\n            ex(i) = m + xi[i]*h;\n        }\n      fargs(0) = ex;\n      fvals = interp.feval (fcn, fargs, 1);\n      if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())\n        error (\"quadcc: integrand F must return a single, real-valued vector\");\n\n      Matrix effex = fvals(0).matrix_value ();\n      if (effex.numel () != ex.numel ())\n        error (\"quadcc: integrand F must return a single, real-valued vector of the same size as the input\");\n\n      for (i = 0; i <= n[3]; i++)\n        {\n          iv->fx[i] = effex(i);\n          if (wrap)\n            {\n              xw = ex(i);\n              iv->fx[i] *= (1.0 + xw*xw) * M_PI/2;\n            }\n          neval++;\n          if (! math::isfinite (iv->fx[i]))\n            {\n              nans[nnans++] = i;\n              iv->fx[i] = 0.0;\n            }\n        }\n      Vinvfx (iv->fx, &(iv->c[idx[3]]), 3);\n      Vinvfx (iv->fx, &(iv->c[idx[2]]), 2);\n      Vinvfx (iv->fx, &(iv->c[0]), 0);\n      for (i = 0; i < nnans; i++)\n        iv->fx[nans[i]] = numeric_limits<double>::NaN ();\n      iv->a = iivals[j];\n      iv->b = iivals[j + 1];\n      iv->depth = 3;\n      iv->rdepth = 1;\n      iv->ndiv = 0;\n      iv->igral = 2 * h * iv->c[idx[3]] * w;\n      nc = 0.0;\n      for (i = n[2] + 1; i <= n[3]; i++)\n        {\n          temp = iv->c[idx[3] + i];\n          nc += temp * temp;\n        }\n      ncdiff = nc;\n      for (i = 0; i <= n[2]; i++)\n        {\n          temp = iv->c[idx[2] + i] - iv->c[idx[3] + i];\n          ncdiff += temp * temp;\n          temp = iv->c[idx[3] + i];\n          nc += temp * temp;\n        }\n      ncdiff = sqrt (ncdiff);\n      nc = sqrt (nc);\n      iv->err = ncdiff * 2 * h;\n      if (ncdiff / nc > 0.1 && iv->err < 2 * h * nc)\n        iv->err = 2 * h * nc;\n\n      // Tabulate this interval's data.\n      igral += iv->igral;\n      err += iv->err;\n\n      // Sift it up the heap.\n      i = j;\n      while (i > 0 && ivals[heap[i / 2]].err < ivals[heap[i]].err)\n        {\n          std::swap (heap[i], heap[i / 2]);\n          i /= 2;\n        }\n    }\n\n  // Initialize some global values.\n  igral_final = 0.0;\n  err_final = 0.0;\n\n  // Main loop.\n  while (nivals > 0\n         && err > std::max (abstol, fabs (igral) * reltol)\n         && ! (err_final > std::max (abstol, fabs (igral) * reltol)\n               && err - err_final < std::max (abstol, fabs (igral) * reltol)))\n    {\n      // Allow the user to interrupt.\n      octave_quit ();\n\n      // Put our finger on the interval with the largest error.\n      iv = &(ivals[heap[0]]);\n      m = (iv->a + iv->b) / 2;\n      h = (iv->b - iv->a) / 2;\n\n#if (OCTAVE_QUADCC_DEBUG)\n      printf (\"quadcc: processing ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\\n\",\n              heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, iv->depth);\n#endif\n\n      // Should we try to increase the degree?\n      if (iv->depth < 3)\n        {\n          // Keep tabs on some variables.\n          d = ++iv->depth;\n\n          // Get the new (missing) function values.\n          {\n            ColumnVector ex (n[d] / 2);\n            if (wrap)\n              {\n                for (i = 0; i < n[d] / 2; i++)\n                  ex(i) = tan (M_PI/2 * (m + xi[(2*i + 1) * skip[d]] * h));\n              }\n            else\n              {\n                for (i = 0; i < n[d] / 2; i++)\n                  ex(i) = m + xi[(2*i + 1) * skip[d]] * h;\n              }\n            fargs(0) = ex;\n            fvals = interp.feval (fcn, fargs, 1);\n            if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())\n              error (\"quadcc: integrand F must return a single, real-valued vector\");\n\n            Matrix effex = fvals(0).matrix_value ();\n            if (effex.numel () != ex.numel ())\n              error (\"quadcc: integrand F must return a single, real-valued vector of the same size as the input\");\n\n            neval += effex.numel ();\n            for (i = 0; i < n[d] / 2; i++)\n              {\n                j = (2*i + 1) * skip[d];\n                iv->fx[j] = effex(i);\n                if (wrap)\n                  {\n                    xw = ex(i);\n                    iv->fx[j] *= (1.0 + xw*xw) * M_PI/2;\n                  }\n              }\n          }\n          nnans = 0;\n          for (i = 0; i <= 32; i += skip[d])\n            {\n              if (! math::isfinite (iv->fx[i]))\n                {\n                  nans[nnans++] = i;\n                  iv->fx[i] = 0.0;\n                }\n            }\n\n          // Compute the new coefficients.\n          Vinvfx (iv->fx, &(iv->c[idx[d]]), d);\n          // Downdate any NaNs.\n          if (nnans > 0)\n            {\n              downdate (&(iv->c[idx[d]]), n[d], d, nans, nnans);\n              for (i = 0; i < nnans; i++)\n                iv->fx[nans[i]] = numeric_limits<double>::NaN ();\n            }\n\n          // Compute the error estimate.\n          nc = 0.0;\n          for (i = n[d - 1] + 1; i <= n[d]; i++)\n            {\n              temp = iv->c[idx[d] + i];\n              nc += temp * temp;\n            }\n          ncdiff = nc;\n          for (i = 0; i <= n[d - 1]; i++)\n            {\n              temp = iv->c[idx[d - 1] + i] - iv->c[idx[d] + i];\n              ncdiff += temp * temp;\n              temp = iv->c[idx[d] + i];\n              nc += temp * temp;\n            }\n          ncdiff = sqrt (ncdiff);\n          nc = sqrt (nc);\n          iv->err = ncdiff * 2 * h;\n          // Compute the local integral.\n          iv->igral = 2 * h * w * iv->c[idx[d]];\n          // Split the interval prematurely?\n          split = (nc > 0 && ncdiff / nc > 0.1);\n        }\n      else\n        {\n          // Maximum degree reached, just split.\n          split = 1;\n        }\n\n      // Should we drop this interval?\n      if ((m + h*xi[0]) >= (m + h*xi[1])\n          || (m + h*xi[31]) >= (m + h*xi[32])\n          || iv->err < fabs (iv->igral) * DROP_RELTOL)\n        {\n#if (OCTAVE_QUADCC_DEBUG)\n          printf (\"quadcc: dropping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\\n\",\n                  heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, iv->depth);\n#endif\n\n          // Keep this interval's contribution.\n          err_final += iv->err;\n          igral_final += iv->igral;\n          // Swap with the last element on the heap.\n          std::swap (heap[nivals - 1], heap[0]);\n          nivals--;\n          // Fix up the heap.\n          i = 0;\n          while (2*i + 1 < nivals)\n            {\n              // Get the kids.\n              j = 2*i + 1;\n              // If the j+1st entry exists and is larger than the jth,\n              // use it instead.\n              if (j + 1 < nivals\n                  && ivals[heap[j + 1]].err >= ivals[heap[j]].err)\n                j++;\n              // Do we need to move the ith entry up?\n              if (ivals[heap[j]].err <= ivals[heap[i]].err)\n                break;\n              else\n                {\n                  std::swap (heap[j], heap[i]);\n                  i = j;\n                }\n            }\n        }\n      else if (split)\n        {\n          // Some values we will need often...\n          d = iv->depth;\n          // Generate the interval on the left.\n          ivl = &(ivals[heap[nivals++]]);\n          ivl->a = iv->a;\n          ivl->b = m;\n          ml = (ivl->a + ivl->b) / 2;\n          hl = h / 2;\n          ivl->depth = 0;\n          ivl->rdepth = iv->rdepth + 1;\n          ivl->fx[0] = iv->fx[0];\n          ivl->fx[32] = iv->fx[16];\n          {\n            ColumnVector ex (n[0] - 1);\n            if (wrap)\n              {\n                for (i = 0; i < n[0] - 1; i++)\n                  ex(i) = tan (M_PI/2 * (ml + xi[(i + 1) * skip[0]] * hl));\n              }\n            else\n              {\n                for (i = 0; i < n[0] - 1; i++)\n                  ex(i) = ml + xi[(i + 1) * skip[0]] * hl;\n              }\n            fargs(0) = ex;\n            fvals = interp.feval (fcn, fargs, 1);\n            if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())\n              error (\"quadcc: integrand F must return a single, real-valued vector\");\n\n            Matrix effex = fvals(0).matrix_value ();\n            if (effex.numel () != ex.numel ())\n              error (\"quadcc: integrand F must return a single, real-valued vector of the same size as the input\");\n\n            neval += effex.numel ();\n            for (i = 0; i < n[0] - 1; i++)\n              {\n                j = (i + 1) * skip[0];\n                ivl->fx[j] = effex(i);\n                if (wrap)\n                  {\n                    xw = ex(i);\n                    ivl->fx[j] *= (1.0 + xw*xw) * M_PI/2;\n                  }\n              }\n          }\n          nnans = 0;\n          for (i = 0; i <= 32; i += skip[0])\n            {\n              if (! math::isfinite (ivl->fx[i]))\n                {\n                  nans[nnans++] = i;\n                  ivl->fx[i] = 0.0;\n                }\n            }\n          Vinvfx (ivl->fx, ivl->c, 0);\n          if (nnans > 0)\n            {\n              downdate (ivl->c, n[0], 0, nans, nnans);\n              for (i = 0; i < nnans; i++)\n                ivl->fx[nans[i]] = numeric_limits<double>::NaN ();\n            }\n          for (i = 0; i <= n[d]; i++)\n            {\n              ivl->c[idx[d] + i] = 0.0;\n              for (j = i; j <= n[d]; j++)\n                ivl->c[idx[d] + i] += Tleft[i*33 + j] * iv->c[idx[d] + j];\n            }\n          ncdiff = 0.0;\n          for (i = 0; i <= n[0]; i++)\n            {\n              temp = ivl->c[i] - ivl->c[idx[d] + i];\n              ncdiff += temp * temp;\n            }\n          for (i = n[0] + 1; i <= n[d]; i++)\n            {\n              temp = ivl->c[idx[d] + i];\n              ncdiff += temp * temp;\n            }\n          ncdiff = sqrt (ncdiff);\n          ivl->err = ncdiff * h;\n          // Check for divergence.\n          ivl->ndiv = iv->ndiv + (fabs (iv->c[0]) > 0\n                                  && ivl->c[0] / iv->c[0] > 2);\n          if (ivl->ndiv > ndiv_max && 2*ivl->ndiv > ivl->rdepth)\n            {\n              igral = std::copysign (numeric_limits<double>::Inf (), igral);\n              warning (\"quadcc: divergent integral detected\");\n              break;\n            }\n\n          // Compute the local integral.\n          ivl->igral = h * w * ivl->c[0];\n\n          // Generate the interval on the right.\n          ivr = &(ivals[heap[nivals++]]);\n          ivr->a = m;\n          ivr->b = iv->b;\n          mr = (ivr->a + ivr->b) / 2;\n          hr = h / 2;\n          ivr->depth = 0;\n          ivr->rdepth = iv->rdepth + 1;\n          ivr->fx[0] = iv->fx[16];\n          ivr->fx[32] = iv->fx[32];\n          {\n            ColumnVector ex (n[0] - 1);\n            if (wrap)\n              {\n                for (i = 0; i < n[0] - 1; i++)\n                  ex(i) = tan (M_PI/2 * (mr + xi[(i + 1) * skip[0]] * hr));\n              }\n            else\n              {\n                for (i = 0; i < n[0] - 1; i++)\n                  ex(i) = mr + xi[(i + 1) * skip[0]] * hr;\n              }\n            fargs(0) = ex;\n            fvals = interp.feval (fcn, fargs, 1);\n            if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())\n              error (\"quadcc: integrand F must return a single, real-valued vector\");\n\n            Matrix effex = fvals(0).matrix_value ();\n            if (effex.numel () != ex.numel ())\n              error (\"quadcc: integrand F must return a single, real-valued vector of the same size as the input\");\n\n            neval += effex.numel ();\n            for (i = 0; i < n[0] - 1; i++)\n              {\n                j = (i + 1) * skip[0];\n                ivr->fx[j] = effex(i);\n                if (wrap)\n                  {\n                    xw = ex(i);\n                    ivr->fx[j] *= (1.0 + xw*xw) * M_PI/2;\n                  }\n              }\n          }\n          nnans = 0;\n          for (i = 0; i <= 32; i += skip[0])\n            {\n              if (! math::isfinite (ivr->fx[i]))\n                {\n                  nans[nnans++] = i;\n                  ivr->fx[i] = 0.0;\n                }\n            }\n          Vinvfx (ivr->fx, ivr->c, 0);\n          if (nnans > 0)\n            {\n              downdate (ivr->c, n[0], 0, nans, nnans);\n              for (i = 0; i < nnans; i++)\n                ivr->fx[nans[i]] = numeric_limits<double>::NaN ();\n            }\n          for (i = 0; i <= n[d]; i++)\n            {\n              ivr->c[idx[d] + i] = 0.0;\n              for (j = i; j <= n[d]; j++)\n                ivr->c[idx[d] + i] += Tright[i*33 + j] * iv->c[idx[d] + j];\n            }\n          ncdiff = 0.0;\n          for (i = 0; i <= n[0]; i++)\n            {\n              temp = ivr->c[i] - ivr->c[idx[d] + i];\n              ncdiff += temp * temp;\n            }\n          for (i = n[0] + 1; i <= n[d]; i++)\n            {\n              temp = ivr->c[idx[d] + i];\n              ncdiff += temp * temp;\n            }\n          ncdiff = sqrt (ncdiff);\n          ivr->err = ncdiff * h;\n          // Check for divergence.\n          ivr->ndiv = iv->ndiv + (fabs (iv->c[0]) > 0\n                                  && ivr->c[0] / iv->c[0] > 2);\n          if (ivr->ndiv > ndiv_max && 2*ivr->ndiv > ivr->rdepth)\n            {\n              igral = std::copysign (numeric_limits<double>::Inf (), igral);\n              warning (\"quadcc: divergent integral detected\");\n              break;\n            }\n\n          // Compute the local integral.\n          ivr->igral = h * w * ivr->c[0];\n\n          // Fix-up the heap: we now have one interval on top that we\n          // don't need any more and two new, unsorted ones at the bottom.\n\n          // Flip the last interval to the top of the heap and sift down.\n          std::swap (heap[nivals - 1], heap[0]);\n          nivals--;\n          // Sift this interval back down the heap.\n          i = 0;\n          while (2*i + 1 < nivals - 1)\n            {\n              j = 2*i + 1;\n              if (j + 1 < nivals - 1\n                  && ivals[heap[j + 1]].err >= ivals[heap[j]].err)\n                j++;\n              if (ivals[heap[j]].err <= ivals[heap[i]].err)\n                break;\n              else\n                {\n                  std::swap (heap[j], heap[i]);\n                  i = j;\n                }\n            }\n\n          // Now grab the last interval and sift it up the heap.\n          i = nivals - 1;\n          while (i > 0)\n            {\n              j = (i - 1) / 2;\n              if (ivals[heap[j]].err < ivals[heap[i]].err)\n                {\n                  std::swap (heap[j], heap[i]);\n                  i = j;\n                }\n              else\n                break;\n            }\n        }\n      else\n        {\n          // Otherwise, just fix-up the heap.\n          i = 0;\n          while (2*i + 1 < nivals)\n            {\n              j = 2*i + 1;\n              if (j + 1 < nivals\n                  && ivals[heap[j + 1]].err >= ivals[heap[j]].err)\n                j++;\n              if (ivals[heap[j]].err <= ivals[heap[i]].err)\n                break;\n              else\n                {\n                  std::swap (heap[j], heap[i]);\n                  i = j;\n                }\n            }\n        }\n\n      // If the heap is about to overflow, remove the last two intervals.\n      while (nivals > cquad_heapsize - 2)\n        {\n          iv = &(ivals[heap[nivals - 1]]);\n#if (OCTAVE_QUADCC_DEBUG)\n          printf (\"quadcc: dropping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\\n\",\n                  heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, iv->depth);\n#endif\n          err_final += iv->err;\n          igral_final += iv->igral;\n          nivals--;\n        }\n\n      // Collect the value of the integral and error.\n      igral = igral_final;\n      err = err_final;\n      for (i = 0; i < nivals; i++)\n        {\n          igral += ivals[heap[i]].igral;\n          err += ivals[heap[i]].err;\n        }\n    }\n\n#if (OCTAVE_QUADCC_DEBUG)\n  // Dump the contents of the heap.\n  for (i = 0; i < nivals; i++)\n    {\n      iv = &(ivals[heap[i]]);\n      printf (\"quadcc: ival %i (%i) with [%e,%e], int=%e, err=%e, depth=%i, rdepth=%i, ndiv=%i\\n\",\n              i, heap[i], iv->a, iv->b, iv->igral, iv->err, iv->depth,\n              iv->rdepth, iv->ndiv);\n    }\n#endif\n\n  if (nargout < 2 && err > std::max (abstol, reltol * std::abs (igral)))\n    warning (\"quadcc: Error tolerance not met.  Estimated error: %g\\n\", err);\n\n  if (issingle)\n    return ovl (static_cast<float> (igral), err, neval);\n  else\n    return ovl (igral, err, neval);\n}\n\n/*\n%!assert (quadcc (@sin, -pi, pi), 0, 1e-10)\n%!test\n%! warning (\"off\", \"Octave:legacy-function\", \"local\");\n%! assert (quadcc (inline (\"sin\"), -pi, pi), 0, 1e-10);\n%!assert (quadcc (\"sin\", -pi, pi), 0, 1e-10)\n\n%!assert (quadcc (@sin, -pi, 0), -2, 1e-10)\n%!assert (quadcc (@sin, 0, pi), 2, 1e-10)\n%!assert (quadcc (@(x) 1./sqrt (x), 0, 1), 2, -1e-6)\n%!assert (quadcc (@(x) 1./(sqrt (x).*(x+1)), 0, Inf), pi, -1e-6)\n%!assert (quadcc (@(x) 1./(sqrt (x).*(x+1)), 0, Inf, [0, 2e-7]), pi, -2e-7)\n\n%!assert (quadcc (@(x) exp (-x .^ 2), -Inf, Inf), sqrt (pi), 1e-10)\n%!assert (quadcc (@(x) exp (-x .^ 2), -Inf, 0), sqrt (pi)/2, 1e-10)\n\n## Test function with NaNs in interval\n%!function y = __nansin (x)\n%!  nan_locs = [-3*pi/4, -pi/4, 0, pi/3, pi/2, pi];\n%!  y = sin (x);\n%!  idx = min (abs (bsxfun (@minus, x(:), nan_locs)), [], 2);\n%!  y(idx < 1e-10) = NaN;\n%!endfunction\n\n%!test\n%! [q, err, npoints] = quadcc (\"__nansin\", -pi, pi, [0, 1e-6]);\n%! assert (q, 0, -1e-6);\n%! assert (err, 0, 15*eps);\n\n%!test\n%! assert (class (quadcc (@sin, 0, 1)), \"double\");\n%! assert (class (quadcc (@sin, single (0), 1)), \"single\");\n%! assert (class (quadcc (@sin, 0, single (1))), \"single\");\n%! assert (class (quadcc (@sin, single (0), single (1))), \"single\");\n\n%!test <*62412>\n%! f = @(t) -1 ./ t.^1.1;\n%! fail (\"quadcc (f, 1, Inf)\", \"warning\", \"Error tolerance not met\");\n%! [q, err] = quadcc (f, 1, Inf);\n%! assert (err > 1e-5);\n\n## Test input validation\n%!error quadcc ()\n%!error quadcc (@sin)\n%!error quadcc (@sin, 0)\n%!error <lower limit .* must be a .* scalar> (quadcc (@sin, ones (2), pi))\n%!error <lower limit .* must be a real scalar> (quadcc (@sin, -i, pi))\n%!error <upper limit .* must be a .* scalar> (quadcc (@sin, 0, ones (2)))\n%!error <upper limit .* must be a real scalar> (quadcc (@sin, 0, i))\n%!error <TOL must be a 1- or 2-element vector> (quadcc (@sin, 0, pi, {1}))\n%!error <TOL must be a 1- or 2-element vector> (quadcc (@sin, 0, pi, [1,2,3]))\n%!error <absolute tolerance must be .=0> (quadcc (@sin, 0, pi, -1))\n%!error <relative tolerance must be .=0> (quadcc (@sin, 0, pi, [1, -1]))\n%!error <SING.* must be .* real values> (quadcc (@sin, 0, pi, 1e-6, [ i ]))\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/qz.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Generalized eigenvalue balancing via LAPACK\n\n// Originally written by A. S. Hodel <scotte@eng.auburn.edu>, but is\n// substantially different with the change to use LAPACK.\n\n#undef OCTAVE_QZ_DEBUG\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"f77-fcn.h\"\n#include \"lapack-proto.h\"\n#include \"qr.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\n#if defined (OCTAVE_QZ_DEBUG)\n#  include \"pager.h\"\n#  include \"pr-output.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (qz, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{V}, @var{W}] =} qz (@var{A}, @var{B})\n@deftypefnx {} {[@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{V}, @var{W}] =} qz (@var{A}, @var{B}, @var{opt})\nCompute the QZ@tie{}decomposition of a generalized eigenvalue problem.\n\nThe generalized eigenvalue problem is defined as\n@tex\n$$A x = \\lambda B x$$\n@end tex\n@ifnottex\n\n@math{A x = @var{lambda} B x}\n\n@end ifnottex\n\nThere are two calling forms of the function:\n\n@enumerate\n@item @code{[@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{V}, @var{W}] = qz (@var{A}, @var{B})}\n\nCompute the complex QZ@tie{}decomposition, generalized eigenvectors, and\ngeneralized eigenvalues.\n@tex\n$$ AA = Q \\cdot A \\cdot Z, BB = Q \\cdot B \\cdot Z $$\n$$ A \\cdot V \\cdot {\\rm diag}(BB) = B \\cdot V \\cdot {\\rm diag}(AA) $$\n$$ {\\rm diag}(BB) \\cdot W^T \\cdot A = {\\rm diag}(AA) \\cdot W^T \\cdot B $$\n@end tex\n@ifnottex\n\n@example\n@group\n\n@var{AA} = @var{Q} * @var{A} * @var{Z}, @var{BB} = @var{Q} * @var{B} * @var{Z}\n@var{A} * @var{V} * diag (diag (@var{BB})) = @var{B} * @var{V} * diag (diag (@var{AA}))\ndiag (diag (@var{BB})) * @var{W}' * @var{A} = diag (diag (@var{AA})) * @var{W}' * @var{B}\n\n@end group\n@end example\n\n@end ifnottex\nwith @var{AA} and @var{BB} upper triangular, and @var{Q} and @var{Z}\nunitary.  The matrices @var{V} and @var{W} respectively contain the right\nand left generalized eigenvectors.\n\n@item @code{[@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{V}, @var{W}] = qz (@var{A}, @var{B}, @var{opt})}\n\nThe @var{opt} argument must be equal to either @qcode{\"real\"} or\n@qcode{\"complex\"}.  If it is equal to @qcode{\"complex\"}, then this\ncalling form is equivalent to the first one with only two input\narguments.\n\nIf @var{opt} is equal to @qcode{\"real\"}, then the real QZ decomposition\nis computed.  In particular, @var{AA} is only guaranteed to be\nquasi-upper triangular with 1-by-1 and 2-by-2 blocks on the diagonal,\nand @var{Q} and @var{Z} are orthogonal.  The identities mentioned above\nfor right and left generalized eigenvectors are only verified if\n@var{AA} is upper triangular (i.e., when all the generalized eigenvalues\nare real, in which case the real and complex QZ coincide).\n\n@end enumerate\n\nNote: @code{qz} performs permutation balancing, but not scaling\n(@pxref{XREFbalance,,@code{balance}}), which may lead to less accurate\nresults than @code{eig}.  The order of output arguments was selected for\ncompatibility with @sc{matlab}.\n\nFor eigenvalues, use the @code{ordeig} function to compute them based on\nthe resulting @var{AA} and @var{BB} matrices.\n\n@seealso{eig, gsvd, balance, chol, hess, lu, qr, qzhess, schur, ordeig}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n#if defined (OCTAVE_QZ_DEBUG)\n  octave_stdout << \"qz: nargin = \" << nargin\n                << \", nargout = \" << nargout << std::endl;\n#endif\n\n  if (nargin < 2 || nargin > 3 || nargout > 6)\n    print_usage ();\n\n  bool complex_case = true;\n\n  if (nargin == 3)\n    {\n      std::string opt = args(2).xstring_value (\"qz: OPT must be a string\");\n\n      if (opt == \"real\")\n        {\n          if (args(0).iscomplex () || args(1).iscomplex ())\n            {\n              warning (\"qz: ignoring 'real' option with complex matrices\");\n              complex_case = true;\n            }\n          else\n            complex_case = false;\n        }\n      else if (opt == \"complex\")\n        complex_case = true;\n      else\n        error (\"qz: OPT must be 'real' or 'complex'\");\n    }\n\n#if defined (OCTAVE_QZ_DEBUG)\n  octave_stdout << \"qz: check matrix A\" << std::endl;\n#endif\n\n  // Matrix A: check dimensions.\n  F77_INT nn = to_f77_int (args(0).rows ());\n  F77_INT nc = to_f77_int (args(0).columns ());\n\n#if defined (OCTAVE_QZ_DEBUG)\n  octave_stdout << \"Matrix A dimensions: (\" << nn << ',' << nc << ')' << std::endl;\n#endif\n\n  if (nc != nn)\n    err_square_matrix_required (\"qz\", \"A\");\n\n  // Matrix A: get value.\n  Matrix aa;\n  ComplexMatrix caa;\n\n  if (args(0).iscomplex ())\n    caa = args(0).complex_matrix_value ();\n  else\n    aa = args(0).matrix_value ();\n\n#if defined (OCTAVE_QZ_DEBUG)\n  octave_stdout << \"qz: check matrix B\" << std::endl;\n#endif\n\n  // Extract argument 2 (bb, or cbb if complex).\n  F77_INT b_nr = to_f77_int (args(1).rows ());\n  F77_INT b_nc = to_f77_int (args(1).columns ());\n\n  if (nn != b_nc || nn != b_nr)\n    ::err_nonconformant ();\n\n  Matrix bb;\n  ComplexMatrix cbb;\n\n  if (args(1).iscomplex ())\n    cbb = args(1).complex_matrix_value ();\n  else\n    bb = args(1).matrix_value ();\n\n  // First, declare variables used in both the real and complex cases.\n  // FIXME: There are a lot of excess variables declared.\n  //        Probably a better way to handle this.\n  Matrix QQ (nn, nn), ZZ (nn, nn), VR (nn, nn), VL (nn, nn);\n  RowVector alphar (nn), alphai (nn), betar (nn);\n  ComplexRowVector xalpha (nn), xbeta (nn);\n  ComplexMatrix CQ (nn, nn), CZ (nn, nn), CVR (nn, nn), CVL (nn, nn);\n  F77_INT ilo, ihi, info;\n  char comp_q = (nargout >= 3 ? 'V' : 'N');\n  char comp_z = (nargout >= 4 ? 'V' : 'N');\n\n  // Initialize Q, Z to identity matrix if either is needed\n  if (comp_q == 'V' || comp_z == 'V')\n    {\n      double *QQptr = QQ.rwdata ();\n      double *ZZptr = ZZ.rwdata ();\n      std::fill_n (QQptr, QQ.numel (), 0.0);\n      std::fill_n (ZZptr, ZZ.numel (), 0.0);\n      for (F77_INT i = 0; i < nn; i++)\n        {\n          QQ(i, i) = 1.0;\n          ZZ(i, i) = 1.0;\n        }\n    }\n\n  // Always perform permutation balancing.\n  const char bal_job = 'P';\n  RowVector lscale (nn), rscale (nn), work (6 * nn), rwork (nn);\n\n  if (complex_case)\n    {\n      if (args(0).isreal ())\n        caa = ComplexMatrix (aa);\n\n      if (args(1).isreal ())\n        cbb = ComplexMatrix (bb);\n\n      if (comp_q == 'V')\n        CQ = ComplexMatrix (QQ);\n\n#if defined (OCTAVE_QZ_DEBUG)\n      if (comp_q == 'V')\n        octave_stdout << \"qz: performing balancing; CQ =\\n\" << CQ << std::endl;\n#endif\n\n      if (comp_z == 'V')\n        CZ = ComplexMatrix (ZZ);\n\n      F77_XFCN (zggbal, ZGGBAL,\n                (F77_CONST_CHAR_ARG2 (&bal_job, 1),\n                 nn, F77_DBLE_CMPLX_ARG (caa.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (cbb.rwdata ()),\n                 nn, ilo, ihi, lscale.rwdata (),\n                 rscale.rwdata (), work.rwdata (), info\n                 F77_CHAR_ARG_LEN (1)));\n    }\n  else\n    {\n#if defined (OCTAVE_QZ_DEBUG)\n      if (comp_q == 'V')\n        octave_stdout << \"qz: performing balancing; QQ =\\n\" << QQ << std::endl;\n#endif\n\n      F77_XFCN (dggbal, DGGBAL,\n                (F77_CONST_CHAR_ARG2 (&bal_job, 1),\n                 nn, aa.rwdata (), nn, bb.rwdata (),\n                 nn, ilo, ihi, lscale.rwdata (),\n                 rscale.rwdata (), work.rwdata (), info\n                 F77_CHAR_ARG_LEN (1)));\n    }\n\n  // Only permutation balance above is done.  Skip scaling balance.\n\n  char qz_job = (nargout < 2 ? 'E' : 'S');\n\n  if (complex_case)\n    {\n      // Complex case.\n\n      // The QR decomposition of cbb.\n      math::qr<ComplexMatrix> cbqr (cbb);\n      // The R matrix of QR decomposition for cbb.\n      cbb = cbqr.R ();\n      // (Q*)caa for following work.\n      caa = (cbqr.Q ().hermitian ()) * caa;\n      CQ = CQ * cbqr.Q ();\n\n      F77_XFCN (zgghrd, ZGGHRD,\n                (F77_CONST_CHAR_ARG2 (&comp_q, 1),\n                 F77_CONST_CHAR_ARG2 (&comp_z, 1),\n                 nn, ilo, ihi, F77_DBLE_CMPLX_ARG (caa.rwdata ()),\n                 nn, F77_DBLE_CMPLX_ARG (cbb.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (CQ.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (CZ.rwdata ()), nn, info\n                 F77_CHAR_ARG_LEN (1)\n                 F77_CHAR_ARG_LEN (1)));\n\n      ComplexRowVector cwork (nn);\n\n      F77_XFCN (zhgeqz, ZHGEQZ,\n                (F77_CONST_CHAR_ARG2 (&qz_job, 1),\n                 F77_CONST_CHAR_ARG2 (&comp_q, 1),\n                 F77_CONST_CHAR_ARG2 (&comp_z, 1),\n                 nn, ilo, ihi,\n                 F77_DBLE_CMPLX_ARG (caa.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (cbb.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (xalpha.rwdata ()),\n                 F77_DBLE_CMPLX_ARG (xbeta.rwdata ()),\n                 F77_DBLE_CMPLX_ARG (CQ.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (CZ.rwdata ()), nn,\n                 F77_DBLE_CMPLX_ARG (cwork.rwdata ()), nn,\n                 rwork.rwdata (), info\n                 F77_CHAR_ARG_LEN (1)\n                 F77_CHAR_ARG_LEN (1)\n                 F77_CHAR_ARG_LEN (1)));\n\n      if (comp_q == 'V')\n        {\n          // Left eigenvector.\n          F77_XFCN (zggbak, ZGGBAK,\n                    (F77_CONST_CHAR_ARG2 (&bal_job, 1),\n                     F77_CONST_CHAR_ARG2 (\"L\", 1),\n                     nn, ilo, ihi, lscale.data (), rscale.data (),\n                     nn, F77_DBLE_CMPLX_ARG (CQ.rwdata ()), nn, info\n                     F77_CHAR_ARG_LEN (1)\n                     F77_CHAR_ARG_LEN (1)));\n        }\n\n      if (comp_z == 'V')\n        {\n          // Right eigenvector.\n          F77_XFCN (zggbak, ZGGBAK,\n                    (F77_CONST_CHAR_ARG2 (&bal_job, 1),\n                     F77_CONST_CHAR_ARG2 (\"R\", 1),\n                     nn, ilo, ihi, lscale.data (), rscale.data (),\n                     nn, F77_DBLE_CMPLX_ARG (CZ.rwdata ()), nn, info\n                     F77_CHAR_ARG_LEN (1)\n                     F77_CHAR_ARG_LEN (1)));\n        }\n\n    }\n  else\n    {\n#if defined (OCTAVE_QZ_DEBUG)\n      octave_stdout << \"qz: performing qr decomposition of bb\" << std::endl;\n#endif\n\n      // Compute the QR factorization of bb.\n      math::qr<Matrix> bqr (bb);\n\n#if defined (OCTAVE_QZ_DEBUG)\n      octave_stdout << \"qz: qr (bb) done; now performing qz decomposition\" << std::endl;\n#endif\n\n      bb = bqr.R ();\n\n#if defined (OCTAVE_QZ_DEBUG)\n      octave_stdout << \"qz: extracted bb\" << std::endl;\n#endif\n\n      aa = (bqr.Q ()).transpose () * aa;\n\n#if defined (OCTAVE_QZ_DEBUG)\n      octave_stdout << \"qz: updated aa \" << std::endl;\n      octave_stdout << \"bqr.Q () =\\n\" << bqr.Q () << std::endl;\n\n      if (comp_q == 'V')\n        octave_stdout << \"QQ =\" << QQ << std::endl;\n#endif\n\n      if (comp_q == 'V')\n        QQ = QQ * bqr.Q ();\n\n#if defined (OCTAVE_QZ_DEBUG)\n      octave_stdout << \"qz: precursors done...\" << std::endl;\n      octave_stdout << \"qz: comp_q = \" << comp_q << \", comp_z = \" << comp_z << std::endl;\n#endif\n\n      // Reduce to generalized Hessenberg form.\n      F77_XFCN (dgghrd, DGGHRD,\n                (F77_CONST_CHAR_ARG2 (&comp_q, 1),\n                 F77_CONST_CHAR_ARG2 (&comp_z, 1),\n                 nn, ilo, ihi, aa.rwdata (),\n                 nn, bb.rwdata (), nn, QQ.rwdata (), nn,\n                 ZZ.rwdata (), nn, info\n                 F77_CHAR_ARG_LEN (1)\n                 F77_CHAR_ARG_LEN (1)));\n\n      // Check if just computing generalized eigenvalues,\n      // or if we're actually computing the decomposition.\n\n      // Reduce to generalized Schur form.\n      F77_XFCN (dhgeqz, DHGEQZ,\n                (F77_CONST_CHAR_ARG2 (&qz_job, 1),\n                 F77_CONST_CHAR_ARG2 (&comp_q, 1),\n                 F77_CONST_CHAR_ARG2 (&comp_z, 1),\n                 nn, ilo, ihi, aa.rwdata (), nn, bb.rwdata (),\n                 nn, alphar.rwdata (), alphai.rwdata (),\n                 betar.rwdata (), QQ.rwdata (), nn,\n                 ZZ.rwdata (), nn, work.rwdata (), nn, info\n                 F77_CHAR_ARG_LEN (1)\n                 F77_CHAR_ARG_LEN (1)\n                 F77_CHAR_ARG_LEN (1)));\n\n      if (comp_q == 'V')\n        {\n          F77_XFCN (dggbak, DGGBAK,\n                    (F77_CONST_CHAR_ARG2 (&bal_job, 1),\n                     F77_CONST_CHAR_ARG2 (\"L\", 1),\n                     nn, ilo, ihi, lscale.data (), rscale.data (),\n                     nn, QQ.rwdata (), nn, info\n                     F77_CHAR_ARG_LEN (1)\n                     F77_CHAR_ARG_LEN (1)));\n\n#if defined (OCTAVE_QZ_DEBUG)\n          if (comp_q == 'V')\n            octave_stdout << \"qz: balancing done; QQ=\\n\" << QQ << std::endl;\n#endif\n        }\n\n      // then right\n      if (comp_z == 'V')\n        {\n          F77_XFCN (dggbak, DGGBAK,\n                    (F77_CONST_CHAR_ARG2 (&bal_job, 1),\n                     F77_CONST_CHAR_ARG2 (\"R\", 1),\n                     nn, ilo, ihi, lscale.data (), rscale.data (),\n                     nn, ZZ.rwdata (), nn, info\n                     F77_CHAR_ARG_LEN (1)\n                     F77_CHAR_ARG_LEN (1)));\n\n#if defined (OCTAVE_QZ_DEBUG)\n          if (comp_z == 'V')\n            octave_stdout << \"qz: balancing done; ZZ=\\n\" << ZZ << std::endl;\n#endif\n        }\n\n    }\n\n  // Right, left eigenvector matrices.\n  if (nargout >= 5)\n    {\n      // Which side to compute?\n      char side = (nargout == 5 ? 'R' : 'B');\n      // Compute all of them and backtransform\n      char howmany = 'B';\n      // Dummy pointer; select is not used.\n      F77_INT *select = nullptr;\n\n      if (complex_case)\n        {\n          CVL = CQ;\n          CVR = CZ;\n          ComplexRowVector cwork2 (2 * nn);\n          RowVector rwork2 (8 * nn);\n          F77_INT m;\n\n          F77_XFCN (ztgevc, ZTGEVC,\n                    (F77_CONST_CHAR_ARG2 (&side, 1),\n                     F77_CONST_CHAR_ARG2 (&howmany, 1),\n                     select, nn, F77_DBLE_CMPLX_ARG (caa.rwdata ()), nn,\n                     F77_DBLE_CMPLX_ARG (cbb.rwdata ()),\n                     nn, F77_DBLE_CMPLX_ARG (CVL.rwdata ()), nn,\n                     F77_DBLE_CMPLX_ARG (CVR.rwdata ()), nn, nn,\n                     m, F77_DBLE_CMPLX_ARG (cwork2.rwdata ()),\n                     rwork2.rwdata (), info\n                     F77_CHAR_ARG_LEN (1)\n                     F77_CHAR_ARG_LEN (1)));\n        }\n      else\n        {\n#if defined (OCTAVE_QZ_DEBUG)\n          octave_stdout << \"qz: computing generalized eigenvectors\" << std::endl;\n#endif\n\n          VL = QQ;\n          VR = ZZ;\n          F77_INT m;\n\n          F77_XFCN (dtgevc, DTGEVC,\n                    (F77_CONST_CHAR_ARG2 (&side, 1),\n                     F77_CONST_CHAR_ARG2 (&howmany, 1),\n                     select, nn, aa.rwdata (), nn, bb.rwdata (),\n                     nn, VL.rwdata (), nn, VR.rwdata (), nn, nn,\n                     m, work.rwdata (), info\n                     F77_CHAR_ARG_LEN (1)\n                     F77_CHAR_ARG_LEN (1)));\n        }\n    }\n\n  octave_value_list retval (nargout);\n\n  switch (nargout)\n    {\n    case 6:\n      // Return left eigenvectors.\n      if (complex_case)\n        retval(5) = CVL;\n      else\n        retval(5) = VL;\n      OCTAVE_FALLTHROUGH;\n\n    case 5:\n      // Return right eigenvectors.\n      if (complex_case)\n        retval(4) = CVR;\n      else\n        retval(4) = VR;\n      OCTAVE_FALLTHROUGH;\n\n    case 4:\n      if (complex_case)\n        retval(3) = CZ;\n      else\n        retval(3) = ZZ;\n      OCTAVE_FALLTHROUGH;\n\n    case 3:\n      if (complex_case)\n        retval(2) = CQ.hermitian ();\n      else\n        retval(2) = QQ.transpose ();\n      OCTAVE_FALLTHROUGH;\n\n    case 2:\n    case 1:\n    case 0:\n      {\n        if (complex_case)\n          {\n#if defined (OCTAVE_QZ_DEBUG)\n            octave_stdout << \"qz: retval(1) = cbb =\\n\";\n            octave_print_internal (octave_stdout, cbb);\n            octave_stdout << \"\\nqz: retval(0) = caa =\\n\";\n            octave_print_internal (octave_stdout, caa);\n            octave_stdout << std::endl;\n#endif\n            retval(1) = cbb;\n            retval(0) = caa;\n          }\n        else\n          {\n#if defined (OCTAVE_QZ_DEBUG)\n            octave_stdout << \"qz: retval(1) = bb =\\n\";\n            octave_print_internal (octave_stdout, bb);\n            octave_stdout << \"\\nqz: retval(0) = aa =\\n\";\n            octave_print_internal (octave_stdout, aa);\n            octave_stdout << std::endl;\n#endif\n            retval(1) = bb;\n            retval(0) = aa;\n          }\n      }\n      break;\n\n    }\n\n#if defined (OCTAVE_QZ_DEBUG)\n  octave_stdout << \"qz: exiting (at long last)\" << std::endl;\n#endif\n\n  return retval;\n}\n\n/*\n## Example 7.7.3 in Golub & Van Loan (3rd ed.; not present in 4th ed.)\n## The generalized eigenvalues are real, so the real and complex QZ coincide.\n%!test\n%! a = [ 10  1  2;\n%!        1  2 -1;\n%!        1  1  2 ];\n%! b = reshape (1:9, 3,3);\n%! [aa, bb, q, z, v, w] = qz (a, b);\n%! assert (isreal (aa) && isreal (bb) && isreal (q) && isreal (z) ...\n%!         && isreal (v) && isreal (w));\n%! assert (istriu (aa) && istriu (bb));\n%! assert (q * q', eye(3), 1e-15);\n%! assert (z * z', eye(3), 1e-15);\n%! assert (q * a * z, aa, norm (aa) * 1e-14);\n%! assert (q * b * z, bb, norm (bb) * 1e-14);\n%! assert (a * v * diag (diag (bb)), b * v * diag (diag (aa)), 1e-13);\n%! assert (diag (diag (bb)) * w' * a, diag (diag (aa)) * w' * b, 1e-13);\n\n## An example with real matrices where some generalized eigenvalues are\n## complex, so the real and complex QZ differ.\n%!test\n%! A = [ -1.03428  0.24929  0.43205 -0.12860;\n%!        1.16228  0.27870  2.12954  0.69250;\n%!       -0.51524 -0.34939 -0.77820  2.13721;\n%!       -1.32941  2.11870  0.72005  1.00835 ];\n%! B = [  1.407302 -0.632956 -0.360628  0.068534;\n%!        0.149898  0.298248  0.991777  0.023652;\n%!        0.169281 -0.405205 -1.775834  1.511730;\n%!        0.717770  1.291390 -1.766607 -0.531352 ];\n%! [CAA, CBB, CQ, CZ, CV, CW] = qz (A, B, 'complex');\n%! assert (iscomplex (CAA) && iscomplex (CBB) && iscomplex (CQ) ...\n%!         && iscomplex (CZ) && iscomplex (CV) && iscomplex (CW));\n%! assert (istriu (CAA) && istriu (CBB));\n%! assert (CQ * CQ', eye(4), 1e-14);\n%! assert (CZ * CZ', eye(4), 1e-14);\n%! assert (CQ * A * CZ, CAA, norm (CAA) * 1e-14);\n%! assert (CQ * B * CZ, CBB, norm (CBB) * 1e-14);\n%! assert (A * CV * diag (diag (CBB)), B * CV * diag (diag (CAA)), 1e-13);\n%! assert (diag (diag (CBB)) * CW' * A, diag (diag (CAA)) * CW' * B, 1e-13);\n%! [AA, BB, Q, Z, V, W] = qz (A, B, 'real');\n%! assert (isreal (AA) && isreal (BB) && isreal (Q) && isreal (Z) ...\n%!         && isreal (V) && isreal (W));\n%! assert (istriu (BB));\n%! assert (Q * Q', eye(4), 1e-14);\n%! assert (Z * Z', eye(4), 1e-14);\n%! assert (Q * A * Z, AA, norm (AA) * 1e-14);\n%! assert (Q * B * Z, BB, norm (BB) * 1e-14);\n\n## Test input validation\n%!error <Invalid call> qz ()\n%!error <Invalid call> qz (1)\n%!error <Invalid call> qz (1,2,3,4)\n%!error <Invalid call> [r1,r2,r3,r4,r5,r6,r7] = qz (1,2)\n%!error <OPT must be a string> qz (1,2, 3)\n%!error <OPT must be 'real' or 'complex'> qz (1,2, 'foobar')\n%!warning <ignoring 'real' option with complex matrices> qz (2i, 3, 'real');\n%!warning <ignoring 'real' option with complex matrices> qz (2, 3i, 'real');\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/rand.cc",
    "content": "/////////////////////////////////////////////////////////////////////////*\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <cstdint>\n#include <functional>\n#include <limits>\n#include <string_view>\n#include <unordered_map>\n#include <string>\n\n#include \"boolNDArray.h\"\n#include \"CNDArray.h\"\n#include \"fNDArray.h\"\n#include \"f77-fcn.h\"\n#include \"mappers.h\"\n#include \"oct-inttypes.h\"\n#include \"oct-rand.h\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"ov-re-mat.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n/*\n%% Restore all rand* \"seed\" and \"state\" values in order, so that the\n%% new \"state\" algorithm remains active after these tests complete.\n%!function restore_rand_states (seed, state)\n%!  rand (\"seed\", seed.rand);\n%!  rande (\"seed\", seed.rande);\n%!  randg (\"seed\", seed.randg);\n%!  randn (\"seed\", seed.randn);\n%!  randp (\"seed\", seed.randp);\n%!  rand (\"state\", state.rand);\n%!  rande (\"state\", state.rande);\n%!  randg (\"state\", state.randg);\n%!  randn (\"state\", state.randn);\n%!  randp (\"state\", state.randp);\n%!endfunction\n\n%!shared __random_statistical_tests__, old_seed, old_state, restore_state\n%! ## Flag whether the statistical tests should be run in \"make check\" or not\n%! __random_statistical_tests__ = 0;\n%! ## Save and restore the states of each of the random number generators\n%! ## that are tested by the unit tests in this file.\n%! old_seed.rand = rand (\"seed\");\n%! old_seed.rande = rande (\"seed\");\n%! old_seed.randg = randg (\"seed\");\n%! old_seed.randn = randn (\"seed\");\n%! old_seed.randp = randp (\"seed\");\n%! old_state.rand = rand (\"state\");\n%! old_state.rande = rande (\"state\");\n%! old_state.randg = randg (\"state\");\n%! old_state.randn = randn (\"state\");\n%! old_state.randp = randp (\"state\");\n%! restore_state = onCleanup (@() restore_rand_states (old_seed, old_state));\n*/\n\nstatic octave_value\ndo_rand (const octave_value_list& args, int nargin, const char *fcn,\n         const std::string& distribution, bool additional_arg = false)\n{\n  NDArray a;\n  int idx = 0;\n  bool is_single = false;\n\n  if (nargin > 0 && args(nargin-1).is_string ())\n    {\n      std::string s_arg = args(nargin-1).string_value ();\n\n      if (s_arg == \"single\")\n        {\n          is_single = true;\n          nargin--;\n        }\n      else if (s_arg == \"double\")\n        nargin--;\n    }\n\n  if (additional_arg)\n    {\n      if (nargin == 0)\n        error (\"%s: at least one argument is required\", fcn);\n      else if (args(0).is_string ())\n        additional_arg = false;\n      else\n        {\n          a = args(0).xarray_value (\"%s: dimension must be a scalar integer\", fcn);\n\n          idx++;\n          nargin--;\n        }\n    }\n\n  octave_value retval;\n  dim_vector dims;\n\n  // Restore current distribution on any exit.\n  unwind_action restore_distribution\n  ([] (const std::string& old_distribution)\n  {\n    rand::distribution (old_distribution);\n  }, rand::distribution ());\n\n  rand::distribution (distribution);\n\n  switch (nargin)\n    {\n    case 0:\n      {\n        if (additional_arg)\n          dims = a.dims ();\n        else\n          {\n            dims.resize (2);\n\n            dims(0) = 1;\n            dims(1) = 1;\n          }\n\n        goto gen_matrix;\n      }\n      break;\n\n    case 1:\n      {\n        octave_value tmp = args(idx);\n\n        if (tmp.is_string ())\n          {\n            std::string s_arg = tmp.string_value ();\n\n            if (s_arg == \"dist\")\n              retval = rand::distribution ();\n            else if (s_arg == \"seed\")\n              retval = rand::seed ();\n            else if (s_arg == \"state\" || s_arg == \"twister\")\n              retval = rand::state (fcn);\n            else if (s_arg == \"uniform\")\n              rand::uniform_distribution ();\n            else if (s_arg == \"normal\")\n              rand::normal_distribution ();\n            else if (s_arg == \"exponential\")\n              rand::exponential_distribution ();\n            else if (s_arg == \"poisson\")\n              rand::poisson_distribution ();\n            else if (s_arg == \"gamma\")\n              rand::gamma_distribution ();\n            else\n              error (\"%s: unrecognized string argument\", fcn);\n          }\n        else if (tmp.is_scalar_type ())\n          {\n            octave_idx_type n = tmp.idx_type_value (true);\n\n            dims.resize (2);\n\n            dims(0) = dims(1) = n;\n\n            goto gen_matrix;\n          }\n        else if (tmp.is_range ())\n          {\n            range<double> r = tmp.range_value ();\n\n            if (! r.all_elements_are_ints ())\n              error (\"%s: all elements of range must be integers\", fcn);\n\n            octave_idx_type n = r.numel ();\n\n            dims.resize (n);\n\n            octave_idx_type base = math::nint_big (r.base ());\n            octave_idx_type incr = math::nint_big (r.increment ());\n\n            for (octave_idx_type i = 0; i < n; i++)\n              {\n                // Negative dimensions treated as zero for Matlab compatibility\n                dims(i) = (base >= 0 ? base : 0);\n                base += incr;\n              }\n\n            goto gen_matrix;\n          }\n        else if (tmp.is_matrix_type ())\n          {\n            Array<octave_idx_type> iv;\n\n            try\n              {\n                iv = tmp.octave_idx_type_vector_value (true);\n              }\n            catch (execution_exception& ee)\n              {\n                error (ee, \"%s: dimensions must be a scalar or array of integers\", fcn);\n              }\n\n            octave_idx_type len = iv.numel ();\n\n            dims.resize (len);\n\n            for (octave_idx_type i = 0; i < len; i++)\n              {\n                // Negative dimensions treated as zero for Matlab compatibility\n                octave_idx_type elt = iv(i);\n                dims(i) = (elt >=0 ? elt : 0);\n              }\n\n            goto gen_matrix;\n          }\n        else\n          err_wrong_type_arg (\"rand\", tmp);\n      }\n      break;\n\n    default:\n      {\n        octave_value tmp = args(idx);\n\n        if (nargin == 2 && tmp.is_string ())\n          {\n            std::string ts = tmp.string_value ();\n\n            if (ts == \"seed\")\n              {\n                if (args(idx+1).is_real_scalar ())\n                  {\n                    double d = args(idx+1).double_value ();\n\n                    rand::seed (d);\n                  }\n                else if (args(idx+1).is_string ()\n                         && args(idx+1).string_value () == \"reset\")\n                  rand::reset ();\n                else\n                  error (\"%s: seed must be a real scalar\", fcn);\n              }\n            else if (ts == \"state\" || ts == \"twister\")\n              {\n                if (args(idx+1).is_string ()\n                    && args(idx+1).string_value () == \"reset\")\n                  rand::reset (fcn);\n                else\n                  {\n                    ColumnVector s\n                      = ColumnVector (args(idx+1).vector_value (false, true));\n\n                    // Backwards compatibility with previous versions of\n                    // Octave which mapped Inf to 0.\n                    for (octave_idx_type i = 0; i < s.numel (); i++)\n                      if (math::isinf (s.xelem (i)))\n                        s.xelem (i) = 0.0;\n\n                    rand::state (s, fcn);\n                  }\n              }\n            else\n              error (\"%s: unrecognized string argument\", fcn);\n          }\n        else\n          {\n            dims.resize (nargin);\n\n            for (int i = 0; i < nargin; i++)\n              {\n                octave_idx_type elt = args(idx+i).idx_type_value (true);\n\n                // Negative dimensions treated as zero for Matlab compatibility\n                dims(i) = (elt >= 0 ? elt : 0);\n              }\n\n            goto gen_matrix;\n          }\n      }\n      break;\n    }\n\n  // No \"goto gen_matrix\" in code path.  Must be done processing.\n  return retval;\n\ngen_matrix:\n\n  dims.chop_trailing_singletons ();\n\n  if (is_single)\n    {\n      if (additional_arg)\n        {\n          if (a.numel () == 1)\n            return rand::float_nd_array (dims, a(0));\n          else\n            {\n              if (a.dims () != dims)\n                error (\"%s: mismatch in argument size\", fcn);\n\n              octave_idx_type len = a.numel ();\n              FloatNDArray m (dims);\n              float *v = m.rwdata ();\n\n              for (octave_idx_type i = 0; i < len; i++)\n                v[i] = rand::float_scalar (a(i));\n\n              return m;\n            }\n        }\n      else\n        return rand::float_nd_array (dims);\n    }\n  else\n    {\n      if (additional_arg)\n        {\n          if (a.numel () == 1)\n            return rand::nd_array (dims, a(0));\n          else\n            {\n              if (a.dims () != dims)\n                error (\"%s: mismatch in argument size\", fcn);\n\n              octave_idx_type len = a.numel ();\n              NDArray m (dims);\n              double *v = m.rwdata ();\n\n              for (octave_idx_type i = 0; i < len; i++)\n                v[i] = rand::scalar (a(i));\n\n              return m;\n            }\n        }\n      else\n        return rand::nd_array (dims);\n    }\n}\n\nDEFUN (rand, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} rand ()\n@deftypefnx {} {@var{x} =} rand (@var{n})\n@deftypefnx {} {@var{x} =} rand (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} rand ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} rand (@dots{}, @var{class})\n@c FIXME: Should implement \"like\" option for rand function\n@c @deftypefnx {} {@var{x} =} rand (@dots{}, \"like\", @var{var})\n@deftypefnx {} {@var{v} =} rand (\"state\")\n@deftypefnx {} {} rand (\"state\", @var{v})\n@deftypefnx {} {} rand (\"state\", \"reset\")\n@deftypefnx {} {@var{v} =} rand (\"seed\")\n@deftypefnx {} {} rand (\"seed\", @var{v})\n@deftypefnx {} {} rand (\"seed\", \"reset\")\nReturn a scalar, matrix, or N-dimensional array whose elements are random\nnumbers uniformly distributed on the interval (0, 1).\n\nIf called with no arguments, return a scalar random value.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nProgramming Note: Any negative dimensions are treated as zero, and any zero\ndimensions will result in an empty matrix.  This odd behavior is for\n@sc{matlab} compatibility.\n\nThe additional calling forms provide an interface to the underlying random\nnumber generator.\n\nYou can query the state of the random number generator using the form\n\n@example\nv = rand (\"state\")\n@end example\n\nThis returns a column vector @var{v} of length 625.  Later, you can restore\nthe random number generator to the state @var{v} using the form\n\n@example\nrand (\"state\", v)\n@end example\n\n@noindent\nYou may also initialize the state vector from an arbitrary vector of length\n@leq{} 625 for @var{v}.  The new state will be a hash based on the value of\n@var{v}, not @var{v} itself.\n\nBy default, the generator is initialized by contributing entropy from the\nwall clock time, the CPU time, the current fraction of a second, the process\nID and---if available---up to 1024 bits from the C++ random number source\n@code{random_device}, which might be non-deterministic (implementation\nspecific).  Note that this differs from @sc{matlab}, which always initializes\nthe random number generator to the same state at startup.  To obtain behavior\ncomparable to @sc{matlab}, initialize with a deterministic state vector in\nOctave's startup files (@pxref{Startup Files}).\n\nProgramming Notes: To compute the pseudo-random sequence, @code{rand} uses the\nMersenne Twister with a period of @math{2^{19937}-1} (See\n@nospell{M. Matsumoto and T. Nishimura}, \"Mersenne Twister: A\n623-dimensionally equidistributed uniform pseudorandom number generator\",\n@cite{@nospell{ACM Trans.@: on Modeling and Computer Simulation}},\n@w{Vol.@: 8}, @w{No.@: 1}, @w{pp.@: 3}--30, January 1998,\n@url{http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html}).\nDo @strong{not} use for cryptography without securely hashing several returned\nvalues together, otherwise the generator state can be learned after reading 624\nconsecutive values.\n\nOlder versions of Octave used a different random number generator.  The new\ngenerator is used by default as it is significantly faster than the old\ngenerator, and produces random numbers with a significantly longer cycle time.\nHowever, in some circumstances it might be desirable to obtain the same random\nsequences as produced by the old generators.  To do this the keyword\n@qcode{\"seed\"} is used to specify that the old generators should be used, as in\n\n@example\nrand (\"seed\", val)\n@end example\n\n@noindent\nwhich sets the seed of the generator to @var{val}.  The seed of the generator\ncan be queried with\n\n@example\ns = rand (\"seed\")\n@end example\n\nHowever, it should be noted that querying the seed will not cause @code{rand}\nto use the old generators, only setting the seed will.  To cause @code{rand} to\nonce again use the new generators, the keyword @qcode{\"state\"} must be used\nto reset @code{rand} back to using the default generator.\n\nThe state or seed of the generator can be reset to a new random value using\nthe @qcode{\"reset\"} keyword.\n\n@seealso{randi, randn, rande, randg, randp}\n@end deftypefn */)\n{\n  return do_rand (args, args.length (), \"rand\", \"uniform\");\n}\n\n// FIXME: The old generator (selected when \"seed\" is set) will not\n// work properly if compiled to use 64-bit integers.\n\n/*\n%!test  # \"state\" can be a scalar\n%! rand (\"state\", 12);  x = rand (1,4);\n%! rand (\"state\", 12);  y = rand (1,4);\n%! assert (x, y);\n%!test  # \"state\" can be a vector\n%! rand (\"state\", [12,13]);  x = rand (1,4);\n%! rand (\"state\", [12;13]);  y = rand (1,4);\n%! assert (x, y);\n%!test  # querying \"state\" returns a value which can be used later\n%! s = rand (\"state\");  x = rand (1,2);\n%! rand (\"state\", s);   y = rand (1,2);\n%! assert (x, y);\n%!test  # querying \"state\" doesn't disturb sequence\n%! rand (\"state\", 12);  rand (1,2);  x = rand (1,2);\n%! rand (\"state\", 12);  rand (1,2);  s = rand (\"state\");  y = rand (1,2);\n%! assert (x, y);\n%! rand (\"state\", s);   z = rand (1,2);\n%! assert (x, z);\n%!test  # \"seed\" must be a scalar\n%! rand (\"seed\", 12);  x = rand (1,4);\n%! rand (\"seed\", 12);  y = rand (1,4);\n%! assert (x, y);\n%!error <seed must be a real scalar> rand (\"seed\", [12,13])\n%!test  # querying \"seed\" returns a value which can be used later\n%! s = rand (\"seed\");  x = rand (1,2);\n%! rand (\"seed\", s);   y = rand (1,2);\n%! assert (x, y);\n%!test  # querying \"seed\" doesn't disturb sequence\n%! rand (\"seed\", 12);  rand (1,2);  x = rand (1,2);\n%! rand (\"seed\", 12);  rand (1,2);  s = rand (\"seed\");  y = rand (1,2);\n%! assert (x, y);\n%! rand (\"seed\", s);  z = rand (1,2);\n%! assert (x, z);\n*/\n\n/*\n%!test\n%! ## Test a known fixed state\n%! rand (\"state\", 1);\n%! assert (rand (1,6), [0.1343642441124013 0.8474337369372327 0.763774618976614 0.2550690257394218 0.495435087091941 0.4494910647887382], eps);\n%!test\n%! ## Test a known fixed seed\n%! rand (\"seed\", 1);\n%! assert (rand (1,6), [0.8668024251237512 0.9126510815694928 0.09366085007786751 0.1664607301354408 0.7408077004365623 0.7615650338120759], 1e-6);\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   rand (\"state\", 12);\n%!   x = rand (100_000, 1);\n%!   assert (min (x) > 0);   #*** Please report this!!! ***\n%!   assert (max (x) < 1);   #*** Please report this!!! ***\n%!   assert (mean (x), 0.5, 0.0024);\n%!   assert (var (x), 1/48, 0.0632);\n%!   assert (skewness (x), 0, 0.012);\n%!   assert (kurtosis (x), -6/5, 0.0094);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   rand (\"seed\", 12);\n%!   x = rand (100_000, 1);\n%!   assert (max (x) < 1);   #*** Please report this!!! ***\n%!   assert (min (x) > 0);   #*** Please report this!!! ***\n%!   assert (mean (x), 0.5, 0.0024);\n%!   assert (var (x), 1/48, 0.0632);\n%!   assert (skewness (x), 0, 0.012);\n%!   assert (kurtosis (x), -6/5, 0.0094);\n%! endif\n*/\n\n/*\n## Test out-of-range values as rand() seeds.\n%!function v = __rand_sample__ (initval)\n%!  rand (\"state\", initval);\n%!  v = rand (1, 6);\n%!endfunction\n%!\n%!assert (__rand_sample__ (-1), __rand_sample__ (0))\n%!assert (__rand_sample__ (-Inf), __rand_sample__ (0))\n%!assert (__rand_sample__ (2^33), __rand_sample__ (intmax (\"uint32\")))\n%!assert (__rand_sample__ (Inf), __rand_sample__ (0))\n%!assert (__rand_sample__ (NaN), __rand_sample__ (0))\n*/\n\n/*\n## Note: Matlab compatibility requires using 0 for negative dimensions.\n%!assert (size (rand (1, -1, 2)), [1, 0, 2])\n\n## Test input validation\n%!error <conversion of 1.1 to.* failed> rand (1, 1.1)\n%!error <dimensions must be .* array of integers> rand ([1, 1.1])\n*/\n\nstatic std::string current_distribution = rand::distribution ();\n\nDEFUN (randn, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} randn ()\n@deftypefnx {} {@var{x} =} randn (@var{n})\n@deftypefnx {} {@var{x} =} randn (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} randn ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} randn (@dots{}, @var{class})\n@c FIXME: Should implement \"like\" option for randn function\n@c @deftypefnx {} {@var{x} =} randn (@dots{}, \"like\", @var{var})\n@deftypefnx {} {@var{v} =} randn (\"state\")\n@deftypefnx {} {} randn (\"state\", @var{v})\n@deftypefnx {} {} randn (\"state\", \"reset\")\n@deftypefnx {} {@var{v} =} randn (\"seed\")\n@deftypefnx {} {} randn (\"seed\", @var{v})\n@deftypefnx {} {} randn (\"seed\", \"reset\")\nReturn a scalar, matrix, or N-dimensional array whose elements are random\nnumbers from the standard normal distribution having a mean of @code{0} and a\nvariance of @code{1}.\n\nIf called with no arguments, return a scalar random value.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nProgramming Note: Any negative dimensions are treated as zero, and any zero\ndimensions will result in an empty matrix.  This odd behavior is for\n@sc{matlab} compatibility.\n\nThe additional calling forms provide an interface to the underlying random\nnumber generator.  See @ref{XREFrand,,@code{rand}} for documentation on\nquerying and controlling the random number generator.\n\nProgramming Note: By default, @code{randn} uses the\n@nospell{Marsaglia and Tsang} ``Ziggurat technique'' to transform from a\nuniform to a normal distribution.\n\nReference: @nospell{G. Marsaglia and W.W. Tsang},\n\"Ziggurat Method for Generating Random Variables\",\n@cite{J.@tie{}Statistical Software}, @w{Vol.@: 5}, 2000,\n@url{https://www.jstatsoft.org/v05/i08/}\n\n@seealso{rand, randi, rande, randg, randp}\n@end deftypefn */)\n{\n  return do_rand (args, args.length (), \"randn\", \"normal\");\n}\n\n/*\n%!test\n%! ## Test a known fixed state\n%! randn (\"state\", 1);\n%! assert (randn (1, 6), [-2.666521678978671 -0.7381719971724564 1.507903992673601 0.6019427189162239 -0.450661261143348 -0.7054431351574116], 14*eps);\n%!test\n%! ## Test a known fixed seed\n%! randn (\"seed\", 1);\n%! assert (randn (1, 6), [-1.039402365684509 -1.25938892364502 0.1968704611063004 0.3874166905879974 -0.5976632833480835 -0.6615074276924133], 1e-6);\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randn (\"state\", 12);\n%!   x = randn (100_000, 1);\n%!   assert (mean (x), 0, 0.01);\n%!   assert (var (x), 1, 0.02);\n%!   assert (skewness (x), 0, 0.02);\n%!   assert (kurtosis (x), 0, 0.04);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randn (\"seed\", 12);\n%!   x = randn (100_000, 1);\n%!   assert (mean (x), 0, 0.01);\n%!   assert (var (x), 1, 0.02);\n%!   assert (skewness (x), 0, 0.02);\n%!   assert (kurtosis (x), 0, 0.04);\n%! endif\n*/\n\nDEFUN (rande, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} rande ()\n@deftypefnx {} {@var{x} =} rande (@var{n})\n@deftypefnx {} {@var{x} =} rande (@var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} rande ([@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} rande (@dots{}, @var{class})\n@c FIXME: Should implement \"like\" option for rande function\n@c @deftypefnx {} {@var{x} =} rande (@dots{}, \"like\", @var{var})\n@deftypefnx {} {@var{v} =} rande (\"state\")\n@deftypefnx {} {} rande (\"state\", @var{v})\n@deftypefnx {} {} rande (\"state\", \"reset\")\n@deftypefnx {} {@var{v} =} rande (\"seed\")\n@deftypefnx {} {} rande (\"seed\", @var{v})\n@deftypefnx {} {} rande (\"seed\", \"reset\")\nReturn a scalar, matrix, or N-dimensional array whose elements are random\nnumbers from the exponential distribution with rate parameter @code{0}.\n\nIf called with no arguments, return a scalar random value.\n\nIf invoked with a single scalar integer argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer arguments, or a vector of integer\nvalues, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nProgramming Note: Any negative dimensions are treated as zero, and any zero\ndimensions will result in an empty matrix.  This odd behavior is for\n@sc{matlab} compatibility.\n\nThe additional calling forms provide an interface to the underlying random\nnumber generator.  See @ref{XREFrand,,@code{rand}} for documentation on\nquerying and controlling the random number generator.\n\nProgramming Note: By default, @code{rande} uses the\n@nospell{Marsaglia and Tsang} ``Ziggurat technique'' to transform from a\nuniform to an exponential distribution.\n\nReference: @nospell{G. Marsaglia and W.W. Tsang},\n\"Ziggurat Method for Generating Random Variables\",\n@cite{J.@tie{}Statistical Software}, @w{Vol@: 5}, 2000,\n@url{https://www.jstatsoft.org/v05/i08/}\n\n@seealso{rand, randi, randn, randg, randp}\n@end deftypefn */)\n{\n  return do_rand (args, args.length (), \"rande\", \"exponential\");\n}\n\n/*\n%!test\n%! ## Test a known fixed state\n%! rande (\"state\", 1);\n%! assert (rande (1, 6), [3.602973885835625 0.1386190677555021 0.6743112889616958 0.4512830847258422 0.7255744741233175 0.3415969205292291], 2*eps);\n%!test\n%! ## Test a known fixed seed\n%! rande (\"seed\", 1);\n%! assert (rande (1, 6), [0.06492075175653866 1.717980206012726 0.4816154008731246 0.5231300676241517 0.103910739364359 1.668931916356087], 1e-6);\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally\n%!   rande (\"state\", 1);\n%!   x = rande (100_000, 1);\n%!   assert (min (x) > 0);   # *** Please report this!!! ***\n%!   assert (mean (x), 1, 0.01);\n%!   assert (var (x), 1, 0.03);\n%!   assert (skewness (x), 2, 0.06);\n%!   assert (kurtosis (x), 6, 0.7);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally\n%!   rande (\"seed\", 1);\n%!   x = rande (100_000, 1);\n%!   assert (min (x)>0);   # *** Please report this!!! ***\n%!   assert (mean (x), 1, 0.01);\n%!   assert (var (x), 1, 0.03);\n%!   assert (skewness (x), 2, 0.06);\n%!   assert (kurtosis (x), 6, 0.7);\n%! endif\n*/\n\nDEFUN (randg, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} randg (@var{a})\n@deftypefnx {} {@var{x} =} randg (@var{a}, @var{n})\n@deftypefnx {} {@var{x} =} randg (@var{a}, @var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} randg (@var{a}, [@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} randg (@dots{}, @var{class})\n@c FIXME: Should implement \"like\" option for randg function\n@c @deftypefnx {} {@var{x} =} randg (@dots{}, \"like\", @var{var})\n@deftypefnx {} {@var{v} =} randg (\"state\")\n@deftypefnx {} {} randg (\"state\", @var{v})\n@deftypefnx {} {} randg (\"state\", \"reset\")\n@deftypefnx {} {@var{v} =} randg (\"seed\")\n@deftypefnx {} {} randg (\"seed\", @var{v})\n@deftypefnx {} {} randg (\"seed\", \"reset\")\nReturn a scalar, matrix, or N-dimensional array whose elements are random\nnumbers from the gamma distribution @code{gamma (@var{a},1)}.\n\nIf called with no size arguments, return a scalar random value.\n\nIf invoked with a single scalar size argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer size arguments, or a vector of\ninteger values, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nProgramming Note: Any negative dimensions are treated as zero, and any zero\ndimensions will result in an empty matrix.  This odd behavior is for\n@sc{matlab} compatibility.\n\nThe additional calling forms provide an interface to the underlying random\nnumber generator.  See @ref{XREFrand,,@code{rand}} for documentation on\nquerying and controlling the random number generator.\n\nProgramming Notes: The gamma distribution can be used to generate many\nother distributions:\n\n@table @asis\n@item @code{gamma (a, b)} for @code{a > -1}, @code{b > 0}\n\n@example\nr = b * randg (a)\n@end example\n\n@item @code{beta (a, b)} for @code{a > -1}, @code{b > -1}\n\n@example\n@group\nr1 = randg (a, 1)\nr = r1 / (r1 + randg (b, 1))\n@end group\n@end example\n\n@item @code{Erlang (a, n)}\n\n@example\nr = a * randg (n)\n@end example\n\n@item @code{chisq (df)} for @code{df > 0}\n\n@example\nr = 2 * randg (df / 2)\n@end example\n\n@item @code{t (df)} for @code{0 < df < inf} (use randn if df is infinite)\n\n@example\nr = randn () / sqrt (2 * randg (df / 2) / df)\n@end example\n\n@item @code{F (n1, n2)} for @code{0 < n1}, @code{0 < n2}\n\n@example\n@group\n## r1 equals 1 if n1 is infinite\nr1 = 2 * randg (n1 / 2) / n1\n## r2 equals 1 if n2 is infinite\nr2 = 2 * randg (n2 / 2) / n2\nr = r1 / r2\n@end group\n@end example\n\n@item negative @code{binomial (n, p)} for @code{n > 0}, @code{0 < p <= 1}\n\n@example\nr = randp ((1 - p) / p * randg (n))\n@end example\n\n@item non-central @code{chisq (df, L)}, for @code{df >= 0} and @code{L > 0}\n(use chisq if @code{L = 0})\n\n@example\n@group\nr = randp (L / 2)\nr(r > 0) = 2 * randg (r(r > 0))\nr(df > 0) += 2 * randg (df(df > 0)/2)\n@end group\n@end example\n\n@item @code{Dirichlet (a1, @dots{} ak)}\n\n@example\n@group\nr = (randg (a1), @dots{}, randg (ak))\nr = r / sum (r)\n@end group\n@end example\n\n@end table\n\n@seealso{rand, randi, randn, rande, randp}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1)\n    error (\"randg: insufficient arguments\");\n\n  return do_rand (args, nargin, \"randg\", \"gamma\", true);\n}\n\n/*\n%!test\n%! randg (\"state\", 12);\n%! assert (randg ([-inf, -1, 0, inf, NaN]), [NaN, NaN, NaN, NaN, NaN]);\n\n%!test\n%! ## Test a known fixed state\n%! randg (\"state\", 1);\n%! assert (randg (0.1, 1, 6), [0.0103951513331241 8.335671459898252e-05 0.00138691397249762 0.000587308416993855 0.495590518784736 2.3921917414795e-12], eps);\n%!test\n%! ## Test a known fixed state\n%! randg (\"state\", 1);\n%! assert (randg (0.95, 1, 6), [3.099382433255327 0.3974529788871218 0.644367450750855 1.143261091802246 1.964111762696822 0.04011915547957939], 12*eps);\n%!test\n%! ## Test a known fixed state\n%! randg (\"state\", 1);\n%! assert (randg (1, 1, 6), [0.2273389379645993 1.288822625058359 0.2406335209340746 1.218869553370733 1.024649860162554 0.09631230343599533], 40*eps);\n%!test\n%! ## Test a known fixed state\n%! randg (\"state\", 1);\n%! assert (randg (10, 1, 6), [3.520369644331133 15.15369864472106 8.332112081991205 8.406211067432674 11.81193475187611 10.88792728177059], 56*eps);\n%!test\n%! ## Test a known fixed state\n%! randg (\"state\", 1);\n%! assert (randg (100, 1, 6), [75.34570255262264 115.4911985594699 95.23493031356388 95.48926019250911 106.2397448229803 103.4813150404118], 256*eps);\n%!test\n%! ## Test a known fixed seed\n%! randg (\"seed\", 1);\n%! assert (randg (0.1, 1, 6), [0.07144210487604141 0.460641473531723 0.4749028384685516 0.06823389977216721 0.000293838675133884 1.802567535340305e-12], 1e-6);\n%!test\n%! ## Test a known fixed seed\n%! randg (\"seed\", 1);\n%! assert (randg (0.95, 1, 6), [1.664905071258545 1.879976987838745 1.905677795410156 0.9948706030845642 0.5606933236122131 0.0766092911362648], 1e-6);\n%!test\n%! ## Test a known fixed seed\n%! randg (\"seed\", 1);\n%! assert (randg (1, 1, 6), [0.03512085229158401 0.6488978862762451 0.8114678859710693 0.1666885763406754 1.60791552066803 1.90356981754303], 1e-6);\n%!test\n%! ## Test a known fixed seed\n%! randg (\"seed\", 1);\n%! assert (randg (10, 1, 6), [6.566435813903809 10.11648464202881 10.73162078857422 7.747178077697754 6.278522491455078 6.240195751190186], 1e-5);\n%!test\n%! ## Test a known fixed seed\n%! randg (\"seed\", 1);\n%! assert (randg (100, 1, 6), [89.40208435058594 101.4734725952148 103.4020004272461 93.62763214111328 88.33104705810547 88.1871337890625], 1e-4);\n%!test\n%! ## Test out-of-bounds values produce NaN w/old-style generators & floats\n%! randg (\"seed\", 1);\n%! result = randg ([-2 Inf], \"single\");\n%! assert (result, single ([NaN NaN]));\n\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"state\", 12);\n%!   a = 0.1;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.01);\n%!   assert (var (x),      a,          0.01);\n%!   assert (skewness (x), 2/sqrt (a), 1);\n%!   assert (kurtosis (x), 6/a,        50);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"state\", 12);\n%!   a = 0.95;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.01);\n%!   assert (var (x),      a,          0.04);\n%!   assert (skewness (x), 2/sqrt (a), 0.2);\n%!   assert (kurtosis (x), 6/a,        2);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"state\", 12);\n%!   a = 1;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.01);\n%!   assert (var (x),      a,          0.04);\n%!   assert (skewness (x), 2/sqrt (a), 0.2);\n%!   assert (kurtosis (x), 6/a,        2);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"state\", 12);\n%!   a = 10;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.1);\n%!   assert (var (x),      a,          0.5);\n%!   assert (skewness (x), 2/sqrt (a), 0.1);\n%!   assert (kurtosis (x), 6/a,        0.5);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"state\", 12);\n%!   a = 100;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.2);\n%!   assert (var (x),      a,          2);\n%!   assert (skewness (x), 2/sqrt (a), 0.05);\n%!   assert (kurtosis (x), 6/a,        0.2);\n%! endif\n%!test\n%! randg (\"seed\", 12);\n%! assert (randg ([-inf, -1, 0, inf, NaN]), [NaN, NaN, NaN, NaN, NaN]);\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"seed\", 12);\n%!   a = 0.1;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.01);\n%!   assert (var (x),      a,          0.01);\n%!   assert (skewness (x), 2/sqrt (a), 1);\n%!   assert (kurtosis (x), 6/a,        50);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"seed\", 12);\n%!   a = 0.95;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.01);\n%!   assert (var (x),      a,          0.04);\n%!   assert (skewness (x), 2/sqrt (a), 0.2);\n%!   assert (kurtosis (x), 6/a,        2);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"seed\", 12);\n%!   a = 1;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.01);\n%!   assert (var (x),      a,          0.04);\n%!   assert (skewness (x), 2/sqrt (a), 0.2);\n%!   assert (kurtosis (x), 6/a,        2);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"seed\", 12);\n%!   a = 10;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.1);\n%!   assert (var (x),      a,          0.5);\n%!   assert (skewness (x), 2/sqrt (a), 0.1);\n%!   assert (kurtosis (x), 6/a,        0.5);\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randg (\"seed\", 12);\n%!   a = 100;\n%!   x = randg (a, 100_000, 1);\n%!   assert (mean (x),     a,          0.2);\n%!   assert (var (x),      a,          2);\n%!   assert (skewness (x), 2/sqrt (a), 0.05);\n%!   assert (kurtosis (x), 6/a,        0.2);\n%! endif\n*/\n\nDEFUN (randp, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{x} =} randp (@var{l})\n@deftypefnx {} {@var{x} =} randp (@var{l}, @var{n})\n@deftypefnx {} {@var{x} =} randp (@var{l}, @var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{x} =} randp (@var{l}, [@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{x} =} randp (@dots{}, @var{class})\n@c FIXME: Should implement \"like\" option for randp function\n@c @deftypefnx {} {@var{x} =} randp (@dots{}, \"like\", @var{var})\n@deftypefnx {} {@var{v} =} randp (\"state\")\n@deftypefnx {} {} randp (\"state\", @var{v})\n@deftypefnx {} {} randp (\"state\", \"reset\")\n@deftypefnx {} {@var{v} =} randp (\"seed\")\n@deftypefnx {} {} randp (\"seed\", @var{v})\n@deftypefnx {} {} randp (\"seed\", \"reset\")\nReturn a scalar, matrix, or N-dimensional array whose elements are random\nnumbers from the Poisson distribution with mean value parameter @var{l}.\n\nIf called with no size arguments, return a scalar random value.\n\nIf invoked with a single scalar size argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer size arguments, or a vector of\ninteger values, return an array with the given dimensions.\n\nThe optional argument @var{class} specifies the class of the return array.\nThe only valid options are @qcode{\"double\"} (default) or @qcode{\"single\"}.\n\nProgramming Note: Any negative dimensions are treated as zero, and any zero\ndimensions will result in an empty matrix.  This odd behavior is for\n@sc{matlab} compatibility.\n\nThe additional calling forms provide an interface to the underlying random\nnumber generator.  See @ref{XREFrand,,@code{rand}} for documentation on\nquerying and controlling the random number generator.\n\nProgramming Notes: Five different algorithms are used depending on the range of\n@var{l} and whether @var{l} is a scalar or a matrix.\n\n@table @asis\n@item For scalar @var{l} @leq{} 12, use direct method.\n@nospell{W.H.@tie{}Press}, et@tie{}al., @cite{Numerical Recipes in C},\nCambridge University Press, 1992.\n\n@item For scalar @var{l} > 12, use rejection method.[1]\n@nospell{W.H.@tie{}Press}, et@tie{}al., @cite{Numerical Recipes in C},\nCambridge University Press, 1992.\n\n@item For matrix @var{l} @leq{} 10, use inversion method.[2]\n@nospell{E.@tie{}Stadlober, et@tie{}al., WinRand source code}, available via\nFTP.\n\n@item For matrix @var{l} > 10, use patchwork rejection method.\n@nospell{E.@tie{}Stadlober, et@tie{}al., WinRand source code}, available via\nFTP, or @nospell{H.@tie{}Zechner}, @cite{Efficient sampling from continuous and\ndiscrete unimodal distributions}, Doctoral Dissertation, @w{pp.@: 156},\nTechnical University @nospell{Graz}, Austria, 1994.\n\n@item For @var{l} > 1e8, use normal approximation.\n@nospell{L.@tie{}Montanet}, et@tie{}al., \"Review of Particle Properties\",\n@cite{Physical Review@tie{}D}, 50, @w{p.@: 1284}, 1994.\n@end table\n\n@seealso{rand, randi, randn, rande, randg}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1)\n    error (\"randp: insufficient arguments\");\n\n  return do_rand (args, nargin, \"randp\", \"poisson\", true);\n}\n\n/*\n%!test\n%! randp (\"state\", 12);\n%! assert (randp ([-inf, -1, 0, inf, NaN]), [NaN, NaN, 0, NaN, NaN]);\n%!test\n%! ## Test a known fixed state\n%! randp (\"state\", 1);\n%! assert (randp (5, 1, 6), [5 5 3 7 7 3]);\n%!test\n%! ## Test a known fixed state\n%! randp (\"state\", 1);\n%! assert (randp (15, 1, 6), [13 15 8 18 18 15]);\n%!test\n%! ## Test a known fixed state\n%! randp (\"state\", 1);\n%! assert (randp (1e9, 1, 6),\n%!         [999915677 999976657 1000047684 1000019035 999985749 999977692],\n%!         -1e-6);\n%!test\n%! ## Test a known fixed seed\n%! randp (\"seed\", 1);\n%! %%assert (randp (5, 1, 6), [8 2 3 6 6 8])\n%! assert (randp (5, 1, 5), [8 2 3 6 6]);\n%!test\n%! ## Test a known fixed seed\n%! randp (\"seed\", 1);\n%! assert (randp (15, 1, 6), [15 16 12 10 10 12]);\n%!test\n%! ## Test a known fixed seed\n%! randp (\"seed\", 1);\n%! assert (randp (1e9, 1, 6),\n%!         [1000006208 1000012224 999981120 999963520 999963072 999981440],\n%!         -1e-6);\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randp (\"state\", 12);\n%!   for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]\n%!     x = randp (a (1), 100_000, 1);\n%!     assert (min (x) >= 0);   # *** Please report this!!! ***\n%!     assert (mean (x), a(1), a(2));\n%!     assert (var (x), a(1), 0.02*a(1));\n%!     assert (skewness (x), 1/sqrt (a(1)), a(3));\n%!     assert (kurtosis (x), 1/a(1), 3*a(3));\n%!   endfor\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randp (\"state\", 12);\n%!   for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]\n%!     x = randp (a(1)* ones (100_000, 1), 100_000, 1);\n%!     assert (min (x) >= 0);   # *** Please report this!!! ***\n%!     assert (mean (x), a(1), a(2));\n%!     assert (var (x), a(1), 0.02*a(1));\n%!     assert (skewness (x), 1/sqrt (a(1)), a(3));\n%!     assert (kurtosis (x), 1/a(1), 3*a(3));\n%!   endfor\n%! endif\n%!test\n%! randp (\"seed\", 12);\n%! assert (randp ([-inf, -1, 0, inf, NaN]), [NaN, NaN, 0, NaN, NaN]);\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randp (\"seed\", 12);\n%!   for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]\n%!     x = randp (a(1), 100_000, 1);\n%!     assert (min (x) >= 0);   # *** Please report this!!! ***\n%!     assert (mean (x), a(1), a(2));\n%!     assert (var (x), a(1), 0.02*a(1));\n%!     assert (skewness (x), 1/sqrt (a(1)), a(3));\n%!     assert (kurtosis (x), 1/a(1), 3*a(3));\n%!   endfor\n%! endif\n%!test\n%! if (__random_statistical_tests__)\n%!   ## statistical tests may fail occasionally.\n%!   randp (\"seed\", 12);\n%!   for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]\n%!     x = randp (a(1)* ones (100_000, 1), 100_000, 1);\n%!     assert (min (x) >= 0);   # *** Please report this!!! ***\n%!     assert (mean (x), a(1), a(2));\n%!     assert (var (x), a(1), 0.02*a(1));\n%!     assert (skewness (x), 1/sqrt (a(1)), a(3));\n%!     assert (kurtosis (x), 1/a(1), 3*a(3));\n%!   endfor\n%! endif\n*/\n\nDEFUN (randperm, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{v} =} randperm (@var{n})\n@deftypefnx {} {@var{v} =} randperm (@var{n}, @var{m})\nReturn a row vector containing a random permutation of @code{1:@var{n}}.\n\nIf @var{m} is supplied, return @var{m} unique entries, sampled without\nreplacement from @code{1:@var{n}}.\n\nThe complexity is O(@var{n}) in memory and O(@var{m}) in time, unless\n@var{m} < @var{n}/5, in which case O(@var{m}) memory is used as well.  The\nrandomization is performed using rand().  All permutations are equally\nlikely.\n@seealso{perms}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_idx_type n = args(0).idx_type_value (true);\n  octave_idx_type m = (nargin == 2) ? args(1).idx_type_value (true) : n;\n\n  if (m < 0 || n < 0)\n    error (\"randperm: M and N must be non-negative\");\n\n  if (m > n)\n    error (\"randperm: M must be less than or equal to N\");\n\n  // Quick and dirty heuristic to decide if we allocate or not the\n  // whole vector for tracking the truncated shuffle.\n  bool short_shuffle = m < n/5;\n\n  // Generate random numbers.\n  NDArray r = rand::nd_array (dim_vector (1, m));\n  double *rvec = r.rwdata ();\n\n  octave_idx_type idx_len = (short_shuffle ? m : n);\n  Array<octave_idx_type> idx;\n  try\n    {\n      idx = Array<octave_idx_type> (dim_vector (1, idx_len));\n    }\n  catch (const std::bad_alloc&)\n    {\n      // Looks like n is too big and short_shuffle is false.\n      // Let's try again, but this time with the alternative.\n      idx_len = m;\n      short_shuffle = true;\n      idx = Array<octave_idx_type> (dim_vector (1, idx_len));\n    }\n\n  octave_idx_type *ivec = idx.rwdata ();\n\n  for (octave_idx_type i = 0; i < idx_len; i++)\n    ivec[i] = i;\n\n  if (short_shuffle)\n    {\n      std::unordered_map<octave_idx_type, octave_idx_type> map (m);\n\n      // Perform the Knuth shuffle only keeping track of moved\n      // entries in the map\n      for (octave_idx_type i = 0; i < m; i++)\n        {\n          // rand() gives u in [0,1). For non-negative values, truncation is\n          // equivalent to floor, so static_cast<octave_idx_type> (u * span)\n          // is safe and avoids the cost of std::floor.\n          octave_idx_type k = i + static_cast<octave_idx_type> (rvec[i] * (n - i));\n\n          // For shuffling first m entries, no need to use extra storage\n          if (k < m)\n            {\n              std::swap (ivec[i], ivec[k]);\n            }\n          else\n            {\n              if (map.find (k) == map.end ())\n                map[k] = k;\n\n              std::swap (ivec[i], map[k]);\n            }\n        }\n    }\n  else\n    {\n      // Perform the Knuth shuffle of the first m entries\n      for (octave_idx_type i = 0; i < m; i++)\n        {\n          // rand() gives u in [0,1). For non-negative values, truncation is\n          // equivalent to floor, so static_cast<octave_idx_type> (u * span)\n          // is safe and avoids the cost of std::floor.\n          octave_idx_type k = i + static_cast<octave_idx_type> (rvec[i] * (n - i));\n          std::swap (ivec[i], ivec[k]);\n        }\n    }\n\n  // Convert to doubles, reusing r.\n  for (octave_idx_type i = 0; i < m; i++)\n    rvec[i] = ivec[i] + 1;\n\n  if (m < n)\n    idx.resize (dim_vector (1, m));\n\n  // Now create an array object with a cached idx_vector.\n  return ovl (new octave_matrix (r, idx_vector (idx)));\n}\n\n/*\n%!assert (sort (randperm (20)), 1:20)\n%!assert (length (randperm (20,10)), 10)\n\n## Test biggish N\n%!assert <*39378> (length (randperm (30_000^2, 100_000)), 100_000)\n\n%!test\n%! rand (\"seed\", 0);\n%! for i = 1:100\n%!   p = randperm (305, 30);\n%!   assert (length (unique (p)), 30);\n%! endfor\n*/\n\n// ================== port of randi.m ========================\n\n// flintmax: largest consecutive integer representable in floating point\n// For IEEE 754 double: 2^53, for float: 2^24\ntemplate <typename F>\ninline constexpr F flintmax_v\n  = static_cast<F> (std::uint64_t {1} << std::numeric_limits<F>::digits);\n\n// Template function to fill array with random integers and cast to target type\n// Uses rejection sampling to ensure unbiased results.\ntemplate <typename T>\nstatic Array<T>\ndo_randi_array (const dim_vector& dims, double imin, double imax)\n{\n  constexpr double flintmax_val = flintmax_v<double>;\n\n  const double rng = (imax - imin) + 1.0;\n  const double K = std::floor (flintmax_val / rng);\n  const double K_rng = K * rng;\n\n  const octave_idx_type n = dims.numel ();\n\n  NDArray rand_vals = rand::nd_array (dims);\n  const double *rdata = rand_vals.data ();\n\n  Array<T> result (dims);\n  T *data = result.rwdata ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      double r_prim = std::floor (rdata[i] * flintmax_val);\n\n      // Rejection loop - rarely needed since K_rng is very close to flintmax\n      while (r_prim >= K_rng)\n        r_prim = std::floor (rand::scalar () * flintmax_val);\n\n      data[i] = static_cast<T> (imin + std::floor (r_prim / K));\n    }\n\n  return result;\n}\n\n// Specialization for double: work in-place to avoid extra allocation\ntemplate <>\nArray<double>\ndo_randi_array<double> (const dim_vector& dims, double imin, double imax)\n{\n  constexpr double flintmax_val = flintmax_v<double>;\n\n  const double rng = (imax - imin) + 1.0;\n  const double K = std::floor (flintmax_val / rng);\n  const double K_rng = K * rng;\n\n  const octave_idx_type n = dims.numel ();\n\n  // Generate random values and transform in-place\n  NDArray result = rand::nd_array (dims);\n  double *data = result.rwdata ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      double r_prim = std::floor (data[i] * flintmax_val);\n\n      // Rejection loop - rarely needed since K_rng is very close to flintmax\n      while (r_prim >= K_rng)\n        r_prim = std::floor (rand::scalar () * flintmax_val);\n\n      data[i] = imin + std::floor (r_prim / K);\n    }\n\n  return result;\n}\n\n// Specialization for float: work in-place to avoid extra allocation\ntemplate <>\nArray<float>\ndo_randi_array<float> (const dim_vector& dims, double imin, double imax)\n{\n  constexpr double flintmax_val = flintmax_v<double>;\n\n  const double rng = (imax - imin) + 1.0;\n  const double K = std::floor (flintmax_val / rng);\n  const double K_rng = K * rng;\n\n  const octave_idx_type n = dims.numel ();\n\n  // Generate random values in bulk, then transform\n  // Use double precision for intermediate calculations to maintain accuracy\n  NDArray rand_vals = rand::nd_array (dims);\n  const double *rdata = rand_vals.data ();\n\n  FloatNDArray result (dims);\n  float *data = result.rwdata ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      double r_prim = std::floor (rdata[i] * flintmax_val);\n\n      // Rejection loop - rarely needed since K_rng is very close to flintmax\n      while (r_prim >= K_rng)\n        r_prim = std::floor (rand::scalar () * flintmax_val);\n\n      data[i] = static_cast<float> (imin + std::floor (r_prim / K));\n    }\n\n  return result;\n}\n\n// Specialization for bool (logical): MATLAB uses value > 0, not value != 0\n// so calls like randi ([-1, 0], 3, 3, 'logical') return all zeros.\ntemplate <>\nArray<bool>\ndo_randi_array<bool> (const dim_vector& dims, double imin, double imax)\n{\n  constexpr double flintmax_val = flintmax_v<double>;\n\n  const double rng = (imax - imin) + 1.0;\n  const double K = std::floor (flintmax_val / rng);\n  const double K_rng = K * rng;\n\n  const octave_idx_type n = dims.numel ();\n\n  NDArray rand_vals = rand::nd_array (dims);\n  const double *rdata = rand_vals.data ();\n\n  boolNDArray result (dims);\n  bool *data = result.rwdata ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      double r_prim = std::floor (rdata[i] * flintmax_val);\n\n      while (r_prim >= K_rng)\n        r_prim = std::floor (rand::scalar () * flintmax_val);\n\n      // MATLAB logical: value > 0 gives true, otherwise false\n      double value = imin + std::floor (r_prim / K);\n      data[i] = value > 0.0;\n    }\n\n  return result;\n}\n\nDEFUN (randi, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{R} =} randi (@var{imax})\n@deftypefnx {} {@var{R} =} randi (@var{imax}, @var{n})\n@deftypefnx {} {@var{R} =} randi (@var{imax}, @var{m}, @var{n}, @dots{})\n@deftypefnx {} {@var{R} =} randi (@var{imax}, [@var{m}, @var{n}, @dots{}])\n@deftypefnx {} {@var{R} =} randi ([@var{imin}, @var{imax}], @dots{})\n@deftypefnx {} {@var{R} =} randi (@dots{}, \"@var{class}\")\nReturn a scalar, matrix, or N-dimensional array whose elements are random\nintegers in the range @w{[1, @var{imax}]}.\n\nIf called with no size arguments, return a scalar random value.\n\nIf invoked with a single scalar size argument @var{n}, return a square\n@nospell{NxN} matrix.\n\nIf invoked with two or more scalar integer size arguments, or a vector of\ninteger values, return an array with the given dimensions.\n\nThe integer range may optionally be described by a two-element matrix with a\nlower and upper bound in which case the returned integers will be on the\ninterval @w{[@var{imin}, @var{imax}]}.\n\nThe optional argument @var{class} will return a matrix of the requested type.\nThe default is @qcode{\"double\"}.  Supported classes are: @qcode{\"double\"},\n@qcode{\"single\"}, @qcode{\"int8\"}, @qcode{\"int16\"}, @qcode{\"int32\"},\n@qcode{\"uint8\"}, @qcode{\"uint16\"}, @qcode{\"uint32\"}, and @qcode{\"logical\"}.\n\nProgramming Notes: @code{randi} relies internally on @code{rand} which uses\nclass @qcode{\"double\"} to represent numbers.  This limits the maximum integer\n(@var{imax}) and range (@var{imax} - @var{imin}) to the value returned by the\n@code{flintmax} function.  For IEEE@tie{}754 floating point numbers this value\nis @w{@math{2^{53} - 1}}.\n\nWhen the output class is @qcode{\"logical\"} the function constructs an array of\nrandom integers as specified and then applies the test @w{@code{@var{x} > 0}}\nto determine which elements will be true.  Because the one-input form of the\nfunction uses @code{1} for @var{imin} @code{randi} will always return a matrix\nof all ones.\n\nExample: 150 integers in the range 1--10.\n\n@example\nri = randi (10, 150, 1)\n@end example\n\n@seealso{rand, randn, rande, randg, randp}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1)\n    print_usage ();\n\n  constexpr double flintmax_dbl = flintmax_v<double>;\n\n  // Parse bounds argument\n  octave_value bounds_arg = args(0);\n\n  if (! bounds_arg.isnumeric ())\n    error (\"randi: IMIN and IMAX must be integer bounds\");\n\n  if (bounds_arg.numel () < 1 || bounds_arg.numel () > 2)\n    error (\"randi: first argument must be scalar IMIN or 2-element vector [IMIN, IMAX]\");\n\n  NDArray bounds_array = bounds_arg.array_value ();\n\n  // Check that all bounds are integers\n  for (octave_idx_type i = 0; i < bounds_array.numel (); i++)\n    {\n      double val = bounds_array(i);\n      if (val != std::trunc (val))\n        error (\"randi: IMIN and IMAX must be integer bounds\");\n    }\n\n  double imin, imax;\n\n  if (bounds_array.numel () == 1)\n    {\n      imin = 1.0;\n      imax = bounds_array(0);\n      if (imax < 1)\n        error (\"randi: IMAX must be >= 1\");\n    }\n  else\n    {\n      imin = bounds_array(0);\n      imax = bounds_array(1);\n      if (imax < imin)\n        error (\"randi: IMIN must be <= IMAX\");\n    }\n\n  // Check bounds against flintmax\n  if (std::abs (imax) >= flintmax_dbl || std::abs (imin) >= flintmax_dbl)\n    error (\"randi: IMIN and IMAX must be smaller than flintmax\");\n\n  if ((imax - imin) >= (flintmax_dbl - 1.0))\n    error (\"randi: integer range must be smaller than flintmax-1\");\n\n  // Parse optional class argument (must be last if present)\n  std::string rclass = \"double\";\n  int size_args_end = nargin;\n\n  if (nargin > 1 && args(nargin - 1).is_string ())\n    {\n      rclass = args(nargin - 1).string_value ();\n      size_args_end = nargin - 1;\n    }\n\n  // Parse size arguments\n  dim_vector dims;\n  int size_args_start = 1;\n\n  if (size_args_end == size_args_start)\n    {\n      // No size arguments - return scalar\n      dims.resize (2);\n      dims(0) = 1;\n      dims(1) = 1;\n    }\n  else if (size_args_end == size_args_start + 1)\n    {\n      // Single size argument\n      octave_value size_arg = args(size_args_start);\n\n      if (size_arg.is_scalar_type ())\n        {\n          // FIXME: idx_type_value () produces a generic error\n          //        \"conversion of XX to int64_t value failed\".\n          // It might be nicer at some point to use try/catch block to map\n          // this to a nicer error message about dimensions must be integers.\n          octave_idx_type n = size_arg.idx_type_value (true);\n          dims.resize (2);\n          dims(0) = (n >= 0 ? n : 0);\n          dims(1) = (n >= 0 ? n : 0);\n        }\n      else if (size_arg.is_matrix_type () || size_arg.is_range ())\n        {\n          Array<octave_idx_type> size_vec;\n          try\n            {\n              size_vec = size_arg.octave_idx_type_vector_value (true);\n            }\n          catch (execution_exception& ee)\n            {\n              error (ee, \"randi: dimensions must be a scalar or array of integers\");\n            }\n\n          octave_idx_type len = size_vec.numel ();\n          dims.resize (len);\n\n          for (octave_idx_type i = 0; i < len; i++)\n            {\n              octave_idx_type d = size_vec(i);\n              dims(i) = (d >= 0 ? d : 0);\n            }\n        }\n      else\n        error (\"randi: dimensions must be a scalar or array of integers\");\n    }\n  else\n    {\n      // Multiple size arguments\n      int ndims = size_args_end - size_args_start;\n      dims.resize (ndims);\n\n      for (int i = 0; i < ndims; i++)\n        {\n          octave_idx_type d = args(size_args_start + i).idx_type_value (true);\n          dims(i) = (d >= 0 ? d : 0);\n        }\n    }\n\n  dims.chop_trailing_singletons ();\n\n  // Validate class and check for range warnings using numeric_limits\n  constexpr double flintmax_sgl = flintmax_v<float>;\n\n  double maxval, minval;\n  std::string_view rclass_sv = rclass;\n\n  // Dispatch table using lambdas for type-specific generation\n  std::function<octave_value (const dim_vector&, double, double)> generator;\n\n  if (rclass_sv == \"double\")\n    {\n      maxval = flintmax_dbl;\n      minval = -flintmax_dbl;\n      generator = do_randi_array<double>;\n    }\n  else if (rclass_sv == \"single\")\n    {\n      maxval = flintmax_sgl;\n      minval = -flintmax_sgl;\n      generator = do_randi_array<float>;\n    }\n  else if (rclass_sv == \"int8\")\n    {\n      maxval = std::numeric_limits<int8_t>::max ();\n      minval = std::numeric_limits<int8_t>::min ();\n      generator = do_randi_array<octave_int8>;\n    }\n  else if (rclass_sv == \"int16\")\n    {\n      maxval = std::numeric_limits<int16_t>::max ();\n      minval = std::numeric_limits<int16_t>::min ();\n      generator = do_randi_array<octave_int16>;\n    }\n  else if (rclass_sv == \"int32\")\n    {\n      maxval = std::numeric_limits<int32_t>::max ();\n      minval = std::numeric_limits<int32_t>::min ();\n      generator = do_randi_array<octave_int32>;\n    }\n  else if (rclass_sv == \"uint8\")\n    {\n      maxval = std::numeric_limits<uint8_t>::max ();\n      minval = std::numeric_limits<uint8_t>::min ();\n      generator = do_randi_array<octave_uint8>;\n    }\n  else if (rclass_sv == \"uint16\")\n    {\n      maxval = std::numeric_limits<uint16_t>::max ();\n      minval = std::numeric_limits<uint16_t>::min ();\n      generator = do_randi_array<octave_uint16>;\n    }\n  else if (rclass_sv == \"uint32\")\n    {\n      maxval = std::numeric_limits<uint32_t>::max ();\n      minval = std::numeric_limits<uint32_t>::min ();\n      generator = do_randi_array<octave_uint32>;\n    }\n  else if (rclass_sv == \"logical\")\n    {\n      // No range warnings for logical.\n      // Any value can be mapped to true (>0) or false (<=0)\n      maxval = flintmax_dbl;\n      minval = -flintmax_dbl;\n      generator = do_randi_array<bool>;\n    }\n  else\n    error (\"randi: unknown requested output CLASS '%s'\", rclass.c_str ());\n\n  if (imax > maxval)\n    warning (\"randi: integer IMAX exceeds requested type.  \"\n             \"Values might be truncated to requested type.\");\n\n  if (imin < minval)\n    warning (\"randi: integer IMIN exceeds requested type.  \"\n             \"Values might be truncated to requested type.\");\n\n  return generator (dims, imin, imax);\n}\n\n/*\n%!test\n%! ri = randi (10, 1000, 1);\n%! assert (ri, fix (ri));\n%! assert (min (ri), 1);\n%! assert (max (ri), 10);\n%! assert (rows (ri), 1000);\n%! assert (columns (ri), 1);\n%! assert (class (ri), \"double\");\n\n%!test\n%! ri = randi (int64 (100), 1, 1000);\n%! assert (ri, fix (ri));\n%! assert (min (ri), 1);\n%! assert (max (ri), 100);\n%! assert (rows (ri), 1);\n%! assert (columns (ri), 1000);\n%! assert (class (ri), \"double\");\n\n%!test\n%! ri = randi ([-100, 100], 1000, 1);\n%! assert (ri, fix (ri));\n%! assert (min (ri) >= -100);\n%! assert (max (ri) <= 100);\n%! assert (class (ri), \"double\");\n\n%!test\n%! ri = randi ([-5, 10], 1000, 1, \"int8\");\n%! assert (ri, fix (ri));\n%! assert (min (ri), int8 (-5));\n%! assert (max (ri), int8 (10));\n%! assert (class (ri), \"int8\");\n\n%!test\n%! ri = randi ([-1000, 1000], 1000, 1, \"int16\");\n%! assert (min (ri) >= int16 (-1000));\n%! assert (max (ri) <= int16 (1000));\n%! assert (class (ri), \"int16\");\n\n%!test\n%! ri = randi ([-1e6, 1e6], 1000, 1, \"int32\");\n%! assert (min (ri) >= int32 (-1e6));\n%! assert (max (ri) <= int32 (1e6));\n%! assert (class (ri), \"int32\");\n\n%!test\n%! ri = randi ([0, 200], 1000, 1, \"uint8\");\n%! assert (min (ri) >= uint8 (0));\n%! assert (max (ri) <= uint8 (200));\n%! assert (class (ri), \"uint8\");\n\n%!test\n%! ri = randi ([100, 1000], 1000, 1, \"uint16\");\n%! assert (min (ri) >= uint16 (100));\n%! assert (max (ri) <= uint16 (1000));\n%! assert (class (ri), \"uint16\");\n\n%!test\n%! ri = randi ([1e5, 1e6], 1000, 1, \"uint32\");\n%! assert (min (ri) >= uint32 (1e5));\n%! assert (max (ri) <= uint32 (1e6));\n%! assert (class (ri), \"uint32\");\n\n%!test\n%! ri = randi ([-5; 10], 1000, 1, \"single\");\n%! assert (ri, fix (ri));\n%! assert (min (ri), single (-5));\n%! assert (max (ri), single (10));\n%! assert (class (ri), \"single\");\n\n## logical: MATLAB uses value > 0 for true, not value != 0\n%!test\n%! ri = randi ([0, 1], 1000, 1, \"logical\");\n%! assert (islogical (ri));\n%! assert (any (ri));        # at least one true (from 1s)\n%! assert (! all (ri));      # at least one false (from 0s)\n\n%!test\n%! ## [-1, 0] should give all false since neither > 0\n%! ri = randi ([-1, 0], 1000, 1, \"logical\");\n%! assert (islogical (ri));\n%! assert (! any (ri));      # all false\n\n%!test\n%! ## [-1, 1] gives ~1/3 true (only 1 > 0)\n%! ri = randi ([-1, 1], 10000, 1, \"logical\");\n%! assert (islogical (ri));\n%! assert (any (ri));        # some true\n%! assert (! all (ri));      # some false\n%! assert (mean (ri), 1/3, 0.05);  # approximately 1/3 true\n\n%!test\n%! ## imax >= 1 always returns all true\n%! ri = randi (10, 3, 3, \"logical\");\n%! assert (islogical (ri));\n%! assert (size (ri), [3, 3]);\n%! assert (all (ri(:)));\n\n%!assert (size (randi (10, 3, 1, 2)), [3, 1, 2])\n%!assert (size (randi (10, [3, 1, 2])), [3, 1, 2])\n%!assert (size (randi ([1, 10], [3, 4])), [3, 4])\n%!assert (size (randi ([1, 10], [3, 4], \"int8\")), [3, 4])\n%!assert (class (randi ([1, 10], [3, 4], \"int16\")), \"int16\")\n\n%!shared max_int8, min_int8, max_uint8, min_uint8, max_single\n%! max_int8 = double (intmax (\"int8\"));\n%! min_int8 = double (intmin (\"int8\"));\n%! max_uint8 = double (intmax (\"uint8\"));\n%! min_uint8 = double (intmin (\"uint8\"));\n%! max_single = double (flintmax (\"single\"));\n\n## Test that no warning thrown if IMAX is exactly on the limits of the range\n%!function test_no_warning (fcn, varargin)\n%!  lastwarn (\"\");\n%!  fcn (varargin{:});\n%!  assert (lastwarn (), \"\");\n%!endfunction\n\n%!test test_no_warning (@randi, max_int8, \"int8\");\n%!test test_no_warning (@randi, max_uint8, \"uint8\");\n%!test test_no_warning (@randi, max_single, \"single\");\n%!test test_no_warning (@randi, [min_int8, max_int8], \"int8\");\n%!test test_no_warning (@randi, [min_uint8, max_uint8], \"uint8\");\n%!test test_no_warning (@randi, [-max_single, max_single], \"single\");\n\n## Test exceeding range\n%!warning <exceeds requested type>\n%! randi ([min_int8-1, max_int8], \"int8\");\n%!warning <exceeds requested type>\n%! randi ([min_uint8-1, max_uint8], \"uint8\");\n%!warning <exceeds requested type>\n%! randi ([min_int8, max_int8 + 1], \"int8\");\n%!warning <exceeds requested type>\n%! randi ([min_uint8, max_uint8 + 1], \"uint8\");\n%!warning <exceeds requested type>\n%! randi ([0, max_single + 1], \"single\");\n%!warning <exceeds requested type>\n%! ri = randi ([-5, 10], 1000, 1, \"uint8\");\n%! assert (ri, fix (ri));\n%! assert (min (ri), uint8 (-5));\n%! assert (max (ri), uint8 (10));\n%! assert (class (ri), \"uint8\");\n\n## Test input validation\n%!error <Invalid call> randi ()\n%!error <must be integer bounds> randi (\"test\")\n%!error <must be integer bounds> randi (struct (\"a\", 1))\n%!error <first argument must be scalar IMIN> randi ([])\n%!error <first argument must be .* 2-element vector> randi ([1,2,3])\n%!error <must be integer bounds> randi (1.5)\n%!error <must be integer bounds> randi ([1.5, 2])\n%!error <must be integer bounds> randi ([1, 2.5])\n%!error <must be integer bounds> randi ([1.5, 2.5])\n%!error <IMAX must be .= 1> randi (0)\n%!error <IMIN must be <= IMAX> randi ([10, 1])\n%!error <IMIN and IMAX must be smaller than flintmax> randi (flintmax ())\n%!error <range must be smaller than flintmax-1> randi ([-1, flintmax() - 1])\n%!error randi (10, 1.5)\n%!error <dimensions must be .* array of integers> randi (10, [1.5, 2])\n%!error <dimensions must be .* array of integers> randi (10, 1.5:0.5:3)\n%!error <dimensions must be a scalar or array of integers> randi (10, {1, 2})\n%!error randi (10, 1.5, 2)\n%!error <unknown requested output CLASS 'foo'> randi (10, \"foo\")\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/rcond.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (rcond, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{c} =} rcond (@var{A})\nCompute the 1-norm estimate of the reciprocal condition number as returned\nby @sc{lapack}.\n\nIf the matrix is well-conditioned then @var{c} will be near 1 and if the\nmatrix is poorly conditioned it will be close to 0.\n\nThe matrix @var{A} must not be sparse.  If the matrix is sparse then\n@code{condest (@var{A})} or @code{rcond (full (@var{A}))} should be used\ninstead.\n@seealso{cond, condest}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value retval;\n\n  if (args(0).issparse ())\n    error (\"rcond: for sparse matrices use 'rcond (full (a))' or 'condest (a)' instead\");\n\n  if (args(0).is_single_type ())\n    {\n      if (args(0).iscomplex ())\n        {\n          FloatComplexMatrix m = args(0).float_complex_matrix_value ();\n          MatrixType mattyp;\n          retval = m.rcond (mattyp);\n          args(0).matrix_type (mattyp);\n        }\n      else\n        {\n          FloatMatrix m = args(0).float_matrix_value ();\n          MatrixType mattyp;\n          retval = m.rcond (mattyp);\n          args(0).matrix_type (mattyp);\n        }\n    }\n  else if (args(0).iscomplex ())\n    {\n      ComplexMatrix m = args(0).complex_matrix_value ();\n      MatrixType mattyp;\n      retval = m.rcond (mattyp);\n      args(0).matrix_type (mattyp);\n    }\n  else\n    {\n      Matrix m = args(0).matrix_value ();\n      MatrixType mattyp;\n      retval = m.rcond (mattyp);\n      args(0).matrix_type (mattyp);\n    }\n\n  return retval;\n}\n\n/*\n%!assert (rcond (eye (2)), 1)\n%!assert (rcond (ones (2)), 0)\n%!assert (rcond ([1 1; 2 1]), 1/9)\n%!assert (rcond (magic (4)), 0, eps)\n\n%!shared x, sx\n%! x = [-5.25, -2.25; -2.25, 1] * eps () + ones (2) / 2;\n%! sx = [-5.25, -2.25; -2.25, 1] * eps (\"single\") + ones (2) / 2;\n%!assert (rcond (x) < eps ())\n%!assert (rcond (sx) < eps ('single'))\n%!assert (rcond (x*i) < eps ())\n%!assert (rcond (sx*i) < eps ('single'))\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/schur.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"schur.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename Matrix>\nstatic octave_value\nmark_upper_triangular (const Matrix& a)\n{\n  octave_value retval = a;\n\n  octave_idx_type n = a.rows ();\n  panic_unless (a.columns () == n);\n\n  const typename Matrix::element_type zero = typename Matrix::element_type ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    if (a(i, i) == zero)\n      return retval;\n\n  retval.matrix_type (MatrixType::Upper);\n\n  return retval;\n}\n\nDEFUN (schur, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{S} =} schur (@var{A})\n@deftypefnx {} {@var{S} =} schur (@var{A}, \"real\")\n@deftypefnx {} {@var{S} =} schur (@var{A}, \"complex\")\n@deftypefnx {} {@var{S} =} schur (@var{A}, @var{opt})\n@deftypefnx {} {[@var{U}, @var{S}] =} schur (@dots{})\n@cindex Schur decomposition\nCompute the Schur@tie{}decomposition of @var{A}.\n\nThe Schur@tie{}decomposition of a square matrix @var{A} is defined as\n@tex\n$$\n S = U^T A U\n$$\n@end tex\n@ifnottex\n\n@example\n@code{@var{S} = @var{U}' * @var{A} * @var{U}}\n@end example\n\n@end ifnottex\nwhere @var{U} is a unitary matrix\n@tex\n($U^T U$ is identity)\n@end tex\n@ifnottex\n(@code{@var{U}'* @var{U}} is identity)\n@end ifnottex\nand @var{S} is upper triangular.  The eigenvalues of @var{A} (and @var{S})\nare the diagonal elements of @var{S}.  If the matrix @var{A} is real, then\nthe real Schur@tie{}decomposition is computed, in which the matrix @var{U}\nis orthogonal and @var{S} is block upper triangular with blocks of size at\nmost\n@tex\n$2 \\times 2$\n@end tex\n@ifnottex\n@code{2 x 2}\n@end ifnottex\nalong the diagonal.\n\nThe default for real matrices is a real Schur@tie{}decomposition.  A complex\ndecomposition may be forced by passing the flag @qcode{\"complex\"}.\n\nThe eigenvalues are optionally ordered along the diagonal according to the\nvalue of @var{opt}:\n\n@table @asis\n@item @qcode{@var{opt} = \"a\"}\nMove eigenvalues with negative real parts to the leading block of @var{S}.\nMnemonic: @qcode{\"a\"} for Algebraic @nospell{Riccati} Equations, where this\nordering is useful.\n\n@item @qcode{@var{opt} = \"d\"}\nMove eigenvalues with magnitude less than one to the leading block of @var{S}.\nMnemonic: @qcode{\"d\"} for Discrete Algebraic @nospell{Riccati} Equations,\nwhere this ordering is useful.\n\n@item @qcode{@var{opt} = \"u\"}\nUnordered.  No particular ordering of eigenvalues (default).\n@end table\n\nThe leading @var{k} columns of @var{U} always span the @var{A}-invariant\nsubspace corresponding to the @var{k} leading eigenvalues of @var{S}.\n@seealso{rsf2csf, ordschur, trexc, ordeig, lu, chol, hess, qr, qz, svd, eig}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2 || nargout > 2)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  std::string ord;\n  if (nargin == 2)\n    ord = args(1).xstring_value (\"schur: second argument must be a string\");\n\n  bool force_complex = false;\n\n  if (ord == \"real\")\n    {\n      ord = \"\";\n    }\n  else if (ord == \"complex\")\n    {\n      force_complex = true;\n      ord = \"\";\n    }\n  else\n    {\n      char ord_char = (ord.empty () ? 'U' : ord[0]);\n\n      if (ord_char != 'U' && ord_char != 'A' && ord_char != 'D'\n          && ord_char != 'u' && ord_char != 'a' && ord_char != 'd')\n        {\n          warning (\"schur: incorrect ordered schur argument '%s'\",\n                   ord.c_str ());\n          return ovl ();\n        }\n    }\n\n  octave_idx_type nr = arg.rows ();\n  octave_idx_type nc = arg.columns ();\n\n  if (nr != nc)\n    err_square_matrix_required (\"schur\", \"A\");\n\n  if (! arg.isnumeric ())\n    err_wrong_type_arg (\"schur\", arg);\n\n  octave_value_list retval;\n\n  if (arg.is_single_type ())\n    {\n      if (! force_complex && arg.isreal ())\n        {\n          FloatMatrix tmp = arg.float_matrix_value ();\n\n          if (nargout <= 1)\n            {\n              math::schur<FloatMatrix> result (tmp, ord, false);\n              retval = ovl (result.schur_matrix ());\n            }\n          else\n            {\n              math::schur<FloatMatrix> result (tmp, ord, true);\n              retval = ovl (result.unitary_schur_matrix (),\n                            result.schur_matrix ());\n            }\n        }\n      else\n        {\n          FloatComplexMatrix ctmp = arg.float_complex_matrix_value ();\n\n          if (nargout <= 1)\n            {\n              math::schur<FloatComplexMatrix> result (ctmp, ord, false);\n              retval = ovl (mark_upper_triangular (result.schur_matrix ()));\n            }\n          else\n            {\n              math::schur<FloatComplexMatrix> result (ctmp, ord, true);\n              retval = ovl (result.unitary_schur_matrix (),\n                            mark_upper_triangular (result.schur_matrix ()));\n            }\n        }\n    }\n  else\n    {\n      if (! force_complex && arg.isreal ())\n        {\n          Matrix tmp = arg.matrix_value ();\n\n          if (nargout <= 1)\n            {\n              math::schur<Matrix> result (tmp, ord, false);\n              retval = ovl (result.schur_matrix ());\n            }\n          else\n            {\n              math::schur<Matrix> result (tmp, ord, true);\n              retval = ovl (result.unitary_schur_matrix (),\n                            result.schur_matrix ());\n            }\n        }\n      else\n        {\n          ComplexMatrix ctmp = arg.complex_matrix_value ();\n\n          if (nargout <= 1)\n            {\n              math::schur<ComplexMatrix> result (ctmp, ord, false);\n              retval = ovl (mark_upper_triangular (result.schur_matrix ()));\n            }\n          else\n            {\n              math::schur<ComplexMatrix> result (ctmp, ord, true);\n              retval = ovl (result.unitary_schur_matrix (),\n                            mark_upper_triangular (result.schur_matrix ()));\n            }\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! a = [1, 2, 3; 4, 5, 9; 7, 8, 6];\n%! [u, s] = schur (a);\n%! assert (u' * a * u, s, sqrt (eps));\n\n%!test\n%! a = single ([1, 2, 3; 4, 5, 9; 7, 8, 6]);\n%! [u, s] = schur (a);\n%! assert (u' * a * u, s, sqrt (eps (\"single\")));\n\n%!error schur ()\n%!error schur (1,2,3)\n%!error [a,b,c] = schur (1)\n%!error <must be a square matrix> schur ([1, 2, 3; 4, 5, 6])\n%!error <wrong type argument 'cell'> schur ({1})\n%!warning <incorrect ordered schur argument> schur ([1, 2; 3, 4], \"bad_opt\");\n\n*/\n\nDEFUN (rsf2csf, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{U}, @var{T}] =} rsf2csf (@var{UR}, @var{TR})\nConvert a real, upper quasi-triangular Schur@tie{}form @var{TR} to a\ncomplex, upper triangular Schur@tie{}form @var{T}.\n\nNote that the following relations hold:\n@tex\n$UR \\cdot TR \\cdot {UR}^T = U T U^{\\dagger}$ and\n$U^{\\dagger} U$ is the identity matrix I.\n@end tex\n@ifnottex\n@tcode{@var{UR} * @var{TR} * @var{UR}' = @var{U} * @var{T} * @var{U}'} and\n@code{@var{U}' * @var{U}} is the identity matrix I.\n@end ifnottex\n\nNote also that @var{U} and @var{T} are not unique.\n@seealso{schur, ordschur, trexc}\n@end deftypefn */)\n{\n  if (args.length () != 2 || nargout > 2)\n    print_usage ();\n\n  if (! args(0).isnumeric ())\n    err_wrong_type_arg (\"rsf2csf\", args(0));\n  if (! args(1).isnumeric ())\n    err_wrong_type_arg (\"rsf2csf\", args(1));\n  if (args(0).iscomplex () || args(1).iscomplex ())\n    error (\"rsf2csf: UR and TR must be real matrices\");\n\n  if (args(0).is_single_type () || args(1).is_single_type ())\n    {\n      FloatMatrix u = args(0).float_matrix_value ();\n      FloatMatrix t = args(1).float_matrix_value ();\n\n      math::schur<FloatComplexMatrix> cs\n        = math::rsf2csf<FloatComplexMatrix, FloatMatrix> (t, u);\n\n      return ovl (cs.unitary_schur_matrix (), cs.schur_matrix ());\n    }\n  else\n    {\n      Matrix u = args(0).matrix_value ();\n      Matrix t = args(1).matrix_value ();\n\n      math::schur<ComplexMatrix> cs\n        = math::rsf2csf<ComplexMatrix, Matrix> (t, u);\n\n      return ovl (cs.unitary_schur_matrix (), cs.schur_matrix ());\n    }\n}\n\n/*\n%!test\n%! A = [1, 1, 1, 2; 1, 2, 1, 1; 1, 1, 3, 1; -2, 1, 1, 1];\n%! [u, t] = schur (A);\n%! [U, T] = rsf2csf (u, t);\n%! assert (norm (u * t * u' - U * T * U'), 0, 1e-12);\n%! assert (norm (A - U * T * U'), 0, 1e-12);\n\n%!test\n%! A = rand (10);\n%! [u, t] = schur (A);\n%! [U, T] = rsf2csf (u, t);\n%! assert (norm (tril (T, -1)), 0);\n%! assert (norm (U * U'), 1, 1e-14);\n\n%!test\n%! A = [0, 1;-1, 0];\n%! [u, t] = schur (A);\n%! [U, T] = rsf2csf (u,t);\n%! assert (U * T * U', A, 1e-14);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/sparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"variables.h\"\n#include \"utils.h\"\n#include \"pager.h\"\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"quit.h\"\n#include \"unwind-prot.h\"\n\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n#include \"ov-bool-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (issparse, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} issparse (@var{x})\nReturn true if @var{x} is a sparse matrix.\n@seealso{ismatrix}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).issparse ());\n}\n\n/*\n%!assert (issparse (sparse (1)), true)\n%!assert (issparse (1), false)\n%!assert (issparse (sparse (false)), true)\n%!assert (issparse (true), false)\n%!test\n%! warning (\"off\", \"Octave:sparse:double-conversion\", \"local\");\n%! assert (issparse (sparse (single ([1 2]))), true);\n%!assert (issparse (single ([1, 2])), false)\n%!assert (issparse (sparse ([1+i, 2]')), true)\n%!assert (issparse ([1+i, 2]'), false)\n\n%!assert (issparse ([]), false)\n%!assert (issparse (sparse([])), true)\n%!assert (issparse (\"test\"), false)\n%!assert (issparse (struct (\"one\", {1})), false)\n%!assert (issparse (cell (1)), false)\n\n## Test input validation\n%!error issparse ()\n%!error issparse (1,2)\n*/\n\nDEFUN (sparse, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{S} =} sparse (@var{A})\n@deftypefnx {} {@var{S} =} sparse (@var{m}, @var{n})\n@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv})\n@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n})\n@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n}, \"unique\")\n@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n}, @var{nzmax})\nCreate a sparse matrix from a full matrix @var{A} or row, column, value\ntriplets.\n\nIf @var{A} is a full matrix, convert it to a sparse matrix representation,\nremoving all zero values in the process.  The matrix @var{A} should be of type\nlogical or double.\n\nIf two inputs @var{m} (rows) and @var{n} (columns) are specified then create\nan empty sparse matrix with the specified dimensions.\n\nGiven the integer index vectors @var{i} and @var{j}, and a 1-by-@code{nnz}\nvector of real or complex values @var{sv}, construct the sparse matrix\n@code{S(@var{i}(@var{k}),@var{j}(@var{k})) = @var{sv}(@var{k})} with overall\ndimensions @var{m} and @var{n}.  If any of @var{i}, @var{j}, or @var{sv} are\nscalars, they are expanded to have a common size.\n\nIf @var{m} or @var{n} are not specified then their values are derived from the\nmaximum index in the vectors @var{i} and @var{j} as given by\n@w{@code{@var{m} = max (@var{i})}}, @w{@code{@var{n} = max (@var{j})}}.\n\n@strong{Note}: If multiple values are specified with the same @var{i}, @var{j}\nindices, the corresponding value in @var{S} will be the sum of the values at\nthe repeated location.  @xref{XREFaccumarray,,accumarray}, for an example of\nhow to produce different behavior such as taking the minimum instead.\n\nIf the option @qcode{\"unique\"} is given, and more than one value is specified\nat the same @var{i}, @var{j} indices, then only the last specified value will\nbe used.  For completeness, the option @qcode{\"sum\"} can be given and will\nbe ignored as the default behavior is to sum values at repeated locations.\n\n@code{sparse (@var{m}, @var{n})} will create an empty @var{m}x@var{n} sparse\nmatrix and is equivalent to @code{sparse ([], [], [], @var{m}, @var{n})}\n\nThe optional final argument reserves space for @var{nzmax} values in the sparse\narray and is useful if the eventual number of nonzero values will be greater\nthan the number of values in @var{sv} used during the initial construction of\nthe array.  @xref{XREFspalloc,,spalloc}, for more information and usage\ninstructions.\n\nExample 1 (convert full matrix to sparse to save memory):\n\n@example\n@group\nx = full (diag (1:1000));\nsizeof (x)\n@xresult{}  8000000\ns = sparse (x);\nsizeof (xs)\n@xresult{}  24008\n@end group\n@end example\n\nExample 2 (sum at repeated indices):\n\n@example\n@group\n@var{i} = [1 1 2]; @var{j} = [1 1 2]; @var{sv} = [3 4 5];\nsparse (@var{i}, @var{j}, @var{sv}, 3, 4)\n@xresult{}\n   Compressed Column Sparse (rows = 3, cols = 4, nnz = 2 [17%])\n\n     (1, 1) ->  7\n     (2, 2) ->  5\n@end group\n@end example\n\nExample 3 (\"unique\" option):\n\n@example\n@group\n@var{i} = [1 1 2]; @var{j} = [1 1 2]; @var{sv} = [3 4 5];\nsparse (@var{i}, @var{j}, @var{sv}, 3, 4, \"unique\")\n@xresult{}\n   Compressed Column Sparse (rows = 3, cols = 4, nnz = 2 [17%])\n\n     (1, 1) ->  4\n     (2, 2) ->  5\n@end group\n@end example\n@seealso{full, accumarray, spalloc, spdiags, speye, spones, sprand, sprandn,\nsprandsym, spconvert, spfun}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0 || nargin > 6)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 1)\n    {\n      octave_value arg = args(0);\n      if (arg.ndims () != 2)\n        error (\"sparse: A must be a 2-D matrix\");\n      if (arg.isfloat ())\n        {\n          if (arg.is_single_type ())\n            warning_with_id (\"Octave:sparse:double-conversion\",\n                             \"sparse: input array cast to double\");\n          if (arg.iscomplex ())\n            retval = arg.sparse_complex_matrix_value ();\n          else\n            retval = arg.sparse_matrix_value ();\n        }\n      else if (arg.islogical ())\n        retval = arg.sparse_bool_matrix_value ();\n      else\n        err_wrong_type_arg (\"sparse\", arg);\n    }\n  else if (nargin == 2)\n    {\n      octave_idx_type m = args(0).strict_idx_type_value (\"sparse: M must be a non-negative integer\");\n      octave_idx_type n = args(1).strict_idx_type_value (\"sparse: N must be a non-negative integer\");\n\n      if (m < 0 || n < 0)\n        error (\"sparse: dimensions M and N must be non-negative\");\n\n      retval = SparseMatrix (m, n);\n    }\n  else if (nargin >= 3)\n    {\n      bool summation = true;\n      if (nargin > 3 && args(nargin-1).is_string ())\n        {\n          std::string opt = args(nargin-1).string_value ();\n          if (opt == \"unique\")\n            summation = false;\n          else if (opt == \"sum\" || opt == \"summation\")\n            summation = true;\n          else\n            error (\"sparse: invalid option: %s\", opt.c_str ());\n\n          nargin -= 1;\n        }\n\n      octave_idx_type m, n, nzmax;\n      m = n = nzmax = -1;\n      if (nargin == 6)\n        {\n          nzmax = args(5).idx_type_value ();\n          nargin--;\n        }\n\n      if (nargin == 5)\n        {\n          m = args(3).strict_idx_type_value (\"sparse: M must be a non-negative integer\");\n          n = args(4).strict_idx_type_value (\"sparse: N must be a non-negative integer\");\n\n          if (m < 0 || n < 0)\n            error (\"sparse: dimensions M and N must be non-negative\");\n        }\n\n      int argidx = 0;    // index being checked when index_vector throws\n      try\n        {\n          idx_vector i = args(0).index_vector ();\n          argidx = 1;\n          idx_vector j = args(1).index_vector ();\n\n          octave_value arg = args(2);  // temp var for code readability\n          if (arg.isfloat ())\n            {\n              if (arg.is_single_type ())\n                warning_with_id (\"Octave:sparse:double-conversion\",\n                                 \"sparse: input array cast to double\");\n              if (arg.iscomplex ())\n                retval = SparseComplexMatrix (arg.complex_array_value (),\n                                              i, j, m, n, summation, nzmax);\n              else\n                retval = SparseMatrix (arg.array_value (),\n                                       i, j, m, n, summation, nzmax);\n            }\n          else if (arg.islogical ())\n            retval = SparseBoolMatrix (arg.bool_array_value (),\n                                       i, j, m, n, summation, nzmax);\n          else\n            err_wrong_type_arg (\"sparse\", arg);\n        }\n      catch (index_exception& ie)\n        {\n          // Rethrow to allow more info to be reported later.\n          ie.set_pos_if_unset (2, argidx+1);\n          throw;\n        }\n    }\n\n  return retval;\n}\n\n/*\n## Tests for sparse constructor are in test/sparse.tst\n%!assert (1)\n*/\n\nDEFUN (spalloc, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{s} =} spalloc (@var{m}, @var{n}, @var{nz})\nCreate an @var{m}-by-@var{n} sparse matrix with pre-allocated space for at\nmost @var{nz} nonzero elements.\n\nThis is useful for building a matrix incrementally by a sequence of indexed\nassignments.  Subsequent indexed assignments after @code{spalloc} will reuse\nthe pre-allocated memory, provided they are of one of the simple forms\n\n@itemize\n@item @code{@var{s}(I:J) = @var{x}}\n\n@item @code{@var{s}(:,I:J) = @var{x}}\n\n@item @code{@var{s}(K:L,I:J) = @var{x}}\n@end itemize\n\n@b{and} that the following conditions are met:\n\n@itemize\n@item the assignment does not decrease @code{nnz (@var{S})}.\n\n@item after the assignment, @code{nnz (@var{S})} does not exceed @var{nz}.\n\n@item no index is out of bounds.\n@end itemize\n\nPartial movement of data may still occur, but in general the assignment will\nbe more memory and time efficient under these circumstances.  In particular,\nit is possible to efficiently build a pre-allocated sparse matrix from a\ncontiguous block of columns.\n\nThe amount of pre-allocated memory for a given matrix may be queried using\nthe function @code{nzmax}.\n\nProgramming Note: Octave always reserves memory for at least one value,\neven if @var{nz} is 0.\n@seealso{nzmax, sparse}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  octave_idx_type m = args(0).idx_type_value ();\n  octave_idx_type n = args(1).idx_type_value ();\n\n  octave_idx_type nz = 0;\n  if (nargin == 3)\n    nz = args(2).idx_type_value ();\n\n  if (m < 0 || n < 0 || nz < 0)\n    error (\"spalloc: M, N, and NZ must be non-negative\");\n\n  return ovl (SparseMatrix (dim_vector (m, n), nz));\n}\n\n/*\n%!assert (issparse (spalloc (1,1)))\n%!assert (spalloc (1,1), sparse (1,1))\n%!test\n%! s = spalloc (1,1,5);\n%! assert (s, sparse (1,1));\n%! assert (nzmax (s), 5);\n%!assert (spalloc (1,2), sparse (1,2))\n%!assert (spalloc (1,2,2), sparse (1,2))\n%!assert (spalloc (2,1), sparse (2,1))\n%!assert (spalloc (2,1,2), sparse (2,1))\n\n%!error spalloc ()\n%!error spalloc (1)\n%!error spalloc (1,2,3,4)\n%!error <M, N, and NZ must be non-negative> spalloc (-1, 1, 1)\n%!error <M, N, and NZ must be non-negative> spalloc (1, -1, 1)\n%!error <M, N, and NZ must be non-negative> spalloc (1, 1, -1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/spparms.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"ov.h\"\n#include \"pager.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n\n#include \"oct-spparms.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (spparms, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} { } spparms ()\n@deftypefnx {} {@var{vals} =} spparms ()\n@deftypefnx {} {[@var{keys}, @var{vals}] =} spparms ()\n@deftypefnx {} {@var{val} =} spparms (@var{key})\n@deftypefnx {} { } spparms (@var{vals})\n@deftypefnx {} { } spparms (\"default\")\n@deftypefnx {} { } spparms (\"tight\")\n@deftypefnx {} { } spparms (@var{key}, @var{val})\nQuery or set the parameters used by the sparse solvers and factorization\nfunctions.\n\nThe first four calls above get information about the current settings, while\nthe others change the current settings.  The parameters are stored as pairs\nof keys and values, where the values are all floats and the keys are one of\nthe following strings:\n\n@table @samp\n@item spumoni\nPrinting level of debugging information of the solvers (default 0)\n\n@item ths_rel\nIncluded for compatibility.  Not used.  (default 1)\n\n@item ths_abs\nIncluded for compatibility.  Not used.  (default 1)\n\n@item exact_d\nIncluded for compatibility.  Not used.  (default 0)\n\n@item supernd\nIncluded for compatibility.  Not used.  (default 3)\n\n@item rreduce\nIncluded for compatibility.  Not used.  (default 3)\n\n@item wh_frac\nIncluded for compatibility.  Not used.  (default 0.5)\n\n@item autommd\nFlag whether the LU/QR and the '\\' and '/' operators will automatically\nuse the sparsity preserving mmd functions (default 1)\n\n@item autoamd\nFlag whether the LU and the '\\' and '/' operators will automatically\nuse the sparsity preserving amd functions (default 1)\n\n@item piv_tol\nThe pivot tolerance of the @sc{umfpack} solvers (default 0.1)\n\n@item sym_tol\nThe pivot tolerance of the @sc{umfpack} symmetric solvers (default 0.001)\n\n@item bandden\nThe density of nonzero elements in a banded matrix before it is treated\nby the @sc{lapack} banded solvers (default 0.5)\n\n@item umfpack\nFlag whether the @sc{umfpack} or mmd solvers are used for the LU, '\\' and\n'/' operations (default 1)\n@end table\n\nThe value of individual keys can be set with\n@code{spparms (@var{key}, @var{val})}.\nThe default values can be restored with the special keyword\n@qcode{\"default\"}.  The special keyword @qcode{\"tight\"} can be used to\nset the mmd solvers to attempt a sparser solution at the potential cost of\nlonger running time.\n@seealso{chol, colamd, lu, qr, symamd}\n@end deftypefn */)\n{\n  octave_value_list retval;\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    {\n      if (nargout == 0)\n        sparse_params::print_info (octave_stdout, \"\");\n      else if (nargout == 1)\n        retval = ovl (sparse_params::get_vals ());\n      else if (nargout == 2)\n        retval = ovl (sparse_params::get_keys (),\n                      sparse_params::get_vals ());\n      else\n        error (\"spparms: too many output arguments\");\n    }\n  else if (nargin == 1)\n    {\n      if (args(0).is_string ())\n        {\n          std::string str = args(0).string_value ();\n          int len = str.length ();\n          for (int i = 0; i < len; i++)\n            str[i] = tolower (str[i]);\n\n          if (str == \"default\")\n            sparse_params::defaults ();\n          else if (str == \"tight\")\n            sparse_params::tight ();\n          else\n            {\n              double val = sparse_params::get_key (str);\n              if (math::isnan (val))\n                error (\"spparms: KEY not recognized\");\n\n              retval = ovl (val);\n            }\n        }\n      else\n        {\n          NDArray vals = args(0).xarray_value (\"spparms: input must be a string or a vector\");\n          if (vals.numel () > OCTAVE_SPARSE_CONTROLS_SIZE)\n            error (\"spparms: too many elements in vector VALS\");\n\n          sparse_params::set_vals (vals);\n        }\n    }\n  else if (nargin == 2)\n    {\n      std::string str = args(0).xstring_value (\"spparms: first argument must be a string\");\n\n      double val = args(1).xdouble_value (\"spparms: second argument must be a real scalar\");\n\n      if (str == \"umfpack\")\n        warning (\"spparms: request to disable umfpack solvers ignored\");\n      else if (! sparse_params::set_key (str, val))\n        error (\"spparms: KEY not found\");\n    }\n  else\n    error (\"spparms: too many input arguments\");\n\n  return retval;\n}\n\n/*\n%!test\n%! old_vals = spparms ();  # save state\n%! spparms (\"default\");\n%! vals = spparms ();\n%! assert (vals, [0 1 1 0 3 3 0.5 1.0 1.0 0.1 0.5 1.0 0.001]');\n%! [keys, vals] = spparms ();\n%! assert (rows (keys), 13);\n%! assert (keys(2,:), \"ths_rel\");\n%! assert (vals, [0 1 1 0 3 3 0.5 1.0 1.0 0.1 0.5 1.0 0.001]');\n%! spparms ([3 2 1]);\n%! assert (spparms ()(1:3), [3, 2, 1]');\n%! assert (spparms (\"ths_rel\"), 2);\n%! spparms (\"exact_d\", 5);\n%! assert (spparms (\"exact_d\"), 5);\n%! spparms (old_vals);     # restore state\n\n## Test input validation\n%!error <too many input arguments> spparms (1, 2, 3)\n%!error <too many output arguments> [x, y, z] = spparms ()\n%!error <KEY not recognized> spparms (\"UNKNOWN_KEY\")\n%!#error <input must be a string> spparms ({1, 2, 3})\n%!error spparms ({1, 2, 3})\n%!error <too many elements in vector VALS> spparms (ones (14, 1))\n%!error <first argument must be a string> spparms (1, 1)\n%!#error <second argument must be a real scalar> spparms (\"ths_rel\", \"hello\")\n%!error spparms (\"ths_rel\", \"hello\")\n%!error <KEY not found> spparms (\"UNKNOWN_KEY\", 1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/sqrtm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"oct-norm.h\"\n#include \"schur.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"utils.h\"\n#include \"xnorm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T>\nstatic void\nsqrtm_utri_inplace (T& m)\n{\n  typedef typename T::element_type element_type;\n  typedef typename T::real_matrix_type real_matrix_type;\n  typedef typename T::real_elt_type real_elt_type;\n\n  const element_type zero = element_type ();\n\n  bool singular = false;\n  bool diagonal = true;\n\n  // The Schur matrix of Hermitian matrices is diagonal.\n  // check for off-diagonal elements above tolerance\n  const octave_idx_type n = m.rows ();\n  real_matrix_type abs_m = m.abs ();\n\n  real_elt_type max_abs_diag = abs_m.diag ().max ()(0);\n\n  const real_elt_type tol = n * max_abs_diag\n                            * std::numeric_limits<real_elt_type>::epsilon ();\n\n  for (octave_idx_type j = 0; j < n && diagonal; j++)\n    {\n      for (octave_idx_type i = j-1; i >= 0; i--)\n        {\n          if (abs_m(i,j) > tol)\n            {\n              diagonal = false;\n              break;\n            }\n        }\n    }\n\n  element_type *mp = m.rwdata ();\n  if (diagonal)\n    {\n      // shortcut for diagonal Schur matrices\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          octave_idx_type idx_diag = i*(n+1);\n          if (mp[idx_diag] != zero)\n            mp[idx_diag] = sqrt (mp[idx_diag]);\n          else\n            singular = true;\n        }\n    }\n  else\n    {\n      // The following code is equivalent to this triple loop:\n      //\n      //   n = rows (m);\n      //   for j = 1:n\n      //     m(j,j) = sqrt (m(j,j));\n      //     for i = j-1:-1:1\n      //       if m(i,j) != 0\n      //         m(i,j) /= (m(i,i) + m(j,j));\n      //       endif\n      //       k = 1:i-1;\n      //       m(k,j) -= m(k,i) * m(i,j);\n      //     endfor\n      //   endfor\n      //\n      // this is an in-place, cache-aligned variant of the code\n      // given in Higham's paper.\n\n      for (octave_idx_type j = 0; j < n; j++)\n        {\n          element_type *colj = mp + n*j;\n          if (colj[j] != zero)\n            colj[j] = sqrt (colj[j]);\n          else\n            singular = true;\n\n          for (octave_idx_type i = j-1; i >= 0; i--)\n            {\n              const element_type *coli = mp + n*i;\n              if (colj[i] != zero)\n                colj[i] /= (coli[i] + colj[j]);\n              const element_type colji = colj[i];\n              for (octave_idx_type k = 0; k < i; k++)\n                colj[k] -= coli[k] * colji;\n            }\n        }\n    }\n\n  if (singular)\n    warning_with_id (\"Octave:sqrtm:SingularMatrix\",\n                     \"sqrtm: matrix is singular, may not have a square root\");\n}\n\ntemplate <typename Matrix, typename ComplexMatrix, typename ComplexSCHUR>\nstatic octave_value\ndo_sqrtm (const octave_value& arg)\n{\n\n  octave_value retval;\n\n  MatrixType mt = arg.matrix_type ();\n\n  bool iscomplex = arg.iscomplex ();\n\n  typedef typename Matrix::element_type real_type;\n\n  real_type cutoff = 0;\n  real_type one = 1;\n  real_type eps = std::numeric_limits<real_type>::epsilon ();\n\n  if (! iscomplex)\n    {\n      Matrix x = octave_value_extract<Matrix> (arg);\n\n      if (mt.is_unknown ()) // if type is not known, compute it now.\n        arg.matrix_type (mt = MatrixType (x));\n\n      switch (mt.type ())\n        {\n        case MatrixType::Upper:\n        case MatrixType::Diagonal:\n          if (! x.diag ().any_element_is_negative ())\n            {\n              // Do it in real arithmetic.\n              sqrtm_utri_inplace (x);\n              retval = x;\n              retval.matrix_type (mt);\n            }\n          else\n            iscomplex = true;\n          break;\n\n        case MatrixType::Lower:\n          if (! x.diag ().any_element_is_negative ())\n            {\n              x = x.transpose ();\n              sqrtm_utri_inplace (x);\n              retval = x.transpose ();\n              retval.matrix_type (mt);\n            }\n          else\n            iscomplex = true;\n          break;\n\n        default:\n          iscomplex = true;\n          break;\n        }\n\n      if (iscomplex)\n        cutoff = 10 * x.rows () * eps * xnorm (x, one);\n    }\n\n  if (iscomplex)\n    {\n      ComplexMatrix x = octave_value_extract<ComplexMatrix> (arg);\n\n      if (mt.is_unknown ()) // if type is not known, compute it now.\n        arg.matrix_type (mt = MatrixType (x));\n\n      switch (mt.type ())\n        {\n        case MatrixType::Upper:\n        case MatrixType::Diagonal:\n          sqrtm_utri_inplace (x);\n          retval = x;\n          retval.matrix_type (mt);\n          break;\n\n        case MatrixType::Lower:\n          x = x.transpose ();\n          sqrtm_utri_inplace (x);\n          retval = x.transpose ();\n          retval.matrix_type (mt);\n          break;\n\n        default:\n          {\n            ComplexMatrix u;\n\n            do\n              {\n                ComplexSCHUR schur_fact (x, \"\", true);\n                x = schur_fact.schur_matrix ();\n                u = schur_fact.unitary_schur_matrix ();\n              }\n            while (0);  // schur_fact no longer needed.\n\n            sqrtm_utri_inplace (x);\n\n            x = u * x;  // original x no longer needed.\n            ComplexMatrix res = xgemm (x, u, blas_no_trans, blas_conj_trans);\n\n            if (cutoff > 0 && xnorm (imag (res), one) <= cutoff)\n              retval = real (res);\n            else\n              retval = res;\n          }\n          break;\n        }\n    }\n\n  return retval;\n}\n\nDEFUN (sqrtm, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{s} =} sqrtm (@var{A})\n@deftypefnx {} {[@var{s}, @var{error_estimate}] =} sqrtm (@var{A})\nCompute the matrix square root of the square matrix @var{A}.\n\nRef: @nospell{N.J. Higham}, @cite{A New sqrtm for @sc{matlab}}, Numerical\nAnalysis Report @w{No.@: 336}, Manchester @nospell{Centre} for Computational\nMathematics, Manchester, England, January 1999.\n@seealso{expm, logm}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  octave_idx_type n = arg.rows ();\n  octave_idx_type nc = arg.columns ();\n\n  if (n != nc || arg.ndims () > 2)\n    err_square_matrix_required (\"sqrtm\", \"A\");\n\n  octave_value_list retval (nargout > 1 ? 3 : 1);\n\n  if (nargout > 1)\n    {\n      // FIXME: Octave does not calculate a condition number with respect to\n      //        sqrtm.  Should this return NaN instead of -1?\n      retval(2) = -1.0;\n    }\n\n  if (arg.is_diag_matrix ())\n    // sqrtm of a diagonal matrix is just sqrt.\n    retval(0) = arg.sqrt ();\n  else if (arg.is_single_type ())\n    retval(0) = do_sqrtm<FloatMatrix, FloatComplexMatrix,\n    math::schur<FloatComplexMatrix>> (arg);\n  else if (arg.isnumeric ())\n    retval(0) = do_sqrtm<Matrix, ComplexMatrix,\n    math::schur<ComplexMatrix>> (arg);\n\n  if (nargout > 1)\n    {\n      // This corresponds to generic code\n      //\n      //   norm (s*s - x, \"fro\") / norm (x, \"fro\");\n\n      octave_value s = retval(0);\n      retval(1) = xfrobnorm (s*s - arg) / xfrobnorm (arg);\n    }\n\n  return retval;\n}\n\n/*\n%!assert (sqrtm (2* ones (2)), ones (2), 3*eps)\n%!assert <*60797> (sqrtm (ones (4))^2, ones (4), 5*eps)\n\n## The following two tests are from the reference in the docstring above.\n%!test\n%! warning (\"off\", \"Octave:sqrtm:SingularMatrix\", \"local\");\n%! x = [0 1; 0 0];\n%! assert (any (isnan (sqrtm (x))(:)));\n\n%!test\n%! x = eye (4);  x(2,2) = x(3,3) = 2^-26;  x(1,4) = 1;\n%! z = eye (4);  z(2,2) = z(3,3) = 2^-13;  z(1,4) = 0.5;\n%! [y, err] = sqrtm (x);\n%! assert (y, z);\n%! assert (err, 0);   # Yes, this one has to hold exactly\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/stream-euler.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\n References:\n\n @article{\n    title = {Particle Tracing Algorithms for 3D Curvilinear Grids},\n    year = {2000},\n    author = {Nielson, Gregory and Uller, H. and Sadarjoen, I. and Walsum, Theo and Hin, Andrea and Post, Frits}\n }\n\n @article{\n    title = {Sources of error in the graphical analysis of CFD results},\n    publisher = {Journal of Scientific Computing},\n    year = {1988},\n    volume = {3},\n    number = {2},\n    pages = {149--164},\n    author = {Buning, Pieter G.},\n }\n\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Coordinates of a point in C-Space (unit square mesh)\n\nstruct Vector2\n{\n  double x, y;\n};\n\n// The integer value and the fractional value from a point in C-Space.\n// Equivalent to the cell index the point is located in and the local\n// coordinates of the point in the cell.\n\nstruct Cell2\n{\n  double fcx, fcy;\n  signed long idx, idy;\n};\n\nstruct Vector3\n{\n  double x, y, z;\n};\n\nstruct Cell3\n{\n  double fcx, fcy, fcz;\n  signed long idx, idy, idz;\n};\n\nstatic inline void\nnumber_to_fractional (signed long *id, double *fc, const double u)\n{\n  *id = floor (u);\n  *fc = u - *id;\n}\n\nstatic inline octave_idx_type\nhandle_border_index (const octave_idx_type id, const octave_idx_type N)\n{\n  return (id < N - 1 ? id : N - 2);\n}\n\nstatic inline void\nhandle_border (octave_idx_type *id2, double *fc2, const octave_idx_type id1,\n               const double fc1, const octave_idx_type N)\n{\n  if (id1 < N - 1)\n    {\n      *id2 = id1;\n      *fc2 = fc1;\n    }\n  else\n    {\n      *id2 = N - 2;\n      *fc2 = 1.0;\n    }\n}\n\nstatic inline double\nbilinear (const double u11, const double u21, const double u12,\n          const double u22, const double x, const double y)\n{\n  return (u11 * (1-x) * (1-y) +\n          u21 * x * (1-y) +\n          u12 * (1-x) * y +\n          u22 * x * y);\n}\n\nstatic inline Cell2\nvector_to_cell2d (const Vector2 X)\n{\n  Cell2 Z;\n\n  number_to_fractional (&Z.idx, &Z.fcx, X.x);\n  number_to_fractional (&Z.idy, &Z.fcy, X.y);\n\n  return (Z);\n}\n\nstatic inline bool\nis_in_definition_set2d (const Cell2 X, const octave_idx_type cols,\n                        const octave_idx_type rows)\n{\n  return ( (((X.idx >= 0) && (X.idx < cols-1)) ||\n            ((X.idx == cols-1) && (X.fcx == 0.0))) &&\n           (((X.idy >= 0) && (X.idy < rows-1)) ||\n            ((X.idy == rows-1) && (X.fcy == 0.0))) );\n}\n\nstatic inline Vector2\nadd2d (const Cell2 X, const Vector2 Y)\n{\n  Vector2 Z = {X.idx + X.fcx + Y.x,\n               X.idy + X.fcy + Y.y\n              };\n\n  return (Z);\n}\n\nstatic inline Vector2\nvector_interpolation2d (const Cell2 X, const Matrix& u, const Matrix& v,\n                        const octave_idx_type cols, const octave_idx_type rows)\n{\n  Vector2 V;\n  double fcx, fcy;\n  octave_idx_type idx, idy;\n\n  handle_border (&idx, &fcx, X.idx, X.fcx, cols);\n  handle_border (&idy, &fcy, X.idy, X.fcy, rows);\n\n  V.x = bilinear (u(idy, idx), u(idy, idx+1), u(idy+1, idx),\n                  u(idy+1, idx+1), fcx, fcy);\n  V.y = bilinear (v(idy, idx), v(idy, idx+1), v(idy+1, idx),\n                  v(idy+1, idx+1), fcx, fcy);\n\n  return (V);\n}\n\n// Apply the Jacobian matrix on the vector V.\n// The step vector length is set to h.\n\nstatic inline Vector2\ncalculate_step_vector2d (const Cell2 X, const Vector2 V,\n                         const RowVector& tx, const RowVector& ty,\n                         const octave_idx_type cols, const octave_idx_type rows,\n                         const double h)\n{\n  Vector2 S;\n\n  const octave_idx_type idx = handle_border_index (X.idx, cols);\n  const octave_idx_type idy = handle_border_index (X.idy, rows);\n\n  const double x = V.x * tx(idx);\n  const double y = V.y * ty(idy);\n  const double n = 1.0 / sqrt (x*x + y*y);\n  S.x = h * n * x;\n  S.y = h * n * y;\n\n  return (S);\n}\n\nstatic inline bool\nis_singular2d (const Vector2 V)\n{\n  return ((math::isnan (V.x) || math::isnan (V.y)) ||\n          ((V.x == 0) && (V.y == 0)));\n}\n\nstatic void\neuler2d (const octave_idx_type cols, const octave_idx_type rows,\n         const Matrix& u, const Matrix& v,\n         const RowVector& tx, const RowVector& ty,\n         const double zeta, const double xi,\n         const double h, const octave_idx_type maxnverts,\n         Matrix& buffer, octave_idx_type *nverts)\n{\n  Vector2 V0, V1, S0, X1, Xnxt, S1;\n  const Vector2 X0 = {zeta, xi};\n  Cell2 X0f, X1f;\n\n  octave_idx_type i = 0;\n\n  buffer(i, 0) = X0.x;\n  buffer(i, 1) = X0.y;\n\n  X0f = vector_to_cell2d (X0);\n  while (true)\n    {\n      if (! is_in_definition_set2d (X0f, cols, rows))\n        break;\n\n      V0 = vector_interpolation2d (X0f, u, v, cols, rows);\n      if (is_singular2d (V0))\n        break;\n\n      S0 = calculate_step_vector2d (X0f, V0, tx, ty, cols, rows, h);\n\n      X1 = add2d (X0f, S0);\n      X1f = vector_to_cell2d (X1);\n      if (! is_in_definition_set2d (X1f, cols, rows))\n        break;\n\n      V1 = vector_interpolation2d (X1f, u, v, cols, rows);\n      if (is_singular2d (V1))\n        break;\n\n      S1 = calculate_step_vector2d (X1f, V1, tx, ty, cols, rows, h);\n\n      // Runge Kutta - Heun's Scheme\n      const Vector2 S = {0.5 * (S0.x + S1.x),\n                         0.5 * (S0.y + S1.y)\n                        };\n      Xnxt = add2d (X0f, S);\n\n      X0f = vector_to_cell2d (Xnxt);\n      if (! is_in_definition_set2d (X0f, cols, rows))\n        break;\n\n      i++;\n      buffer(i, 0) = Xnxt.x;\n      buffer(i, 1) = Xnxt.y;\n\n      if (i + 1 >= maxnverts)\n        break;\n    }\n\n  *nverts = i + 1;\n}\n\nstatic inline double\ntrilinear (const double u111, const double u211, const double u121,\n           const double u221, const double u112, const double u212,\n           const double u122, const double u222,\n           const double x, const double y, const double z)\n{\n  return (u111 * (1-x) * (1-y) * (1-z) +\n          u211 * x * (1-y) * (1-z) +\n          u121 * (1-x) * y * (1-z) +\n          u221 * x * y * (1-z) +\n          u112 * (1-x) * (1-y) * z +\n          u212 * x * (1-y) * z +\n          u122 * (1-x) * y * z +\n          u222 * x * y * z);\n}\n\nstatic inline Cell3\nvector_to_cell3d (const Vector3 X)\n{\n  Cell3 Z;\n\n  number_to_fractional (&Z.idx, &Z.fcx, X.x);\n  number_to_fractional (&Z.idy, &Z.fcy, X.y);\n  number_to_fractional (&Z.idz, &Z.fcz, X.z);\n\n  return (Z);\n}\n\nstatic inline bool\nis_in_definition_set3d (const Cell3 X, const octave_idx_type nx,\n                        const octave_idx_type ny, const octave_idx_type nz)\n{\n  return ( (((X.idx >= 0) && (X.idx < nx-1)) ||\n            ((X.idx == nx-1) && (X.fcx == 0.0))) &&\n           (((X.idy >= 0) && (X.idy < ny-1)) ||\n            ((X.idy == ny-1) && (X.fcy == 0.0))) &&\n           (((X.idz >= 0) && (X.idz < nz-1)) ||\n            ((X.idz == nz-1) && (X.fcz == 0.0))) );\n}\n\nstatic inline Vector3\nadd3d (const Cell3 X, const Vector3 Y)\n{\n  Vector3 Z = {X.idx + X.fcx + Y.x,\n               X.idy + X.fcy + Y.y,\n               X.idz + X.fcz + Y.z\n              };\n\n  return (Z);\n}\n\nstatic inline Vector3\nvector_interpolation3d (const Cell3 X, const NDArray& u, const NDArray& v,\n                        const NDArray& w, const octave_idx_type nx,\n                        const octave_idx_type ny, const octave_idx_type nz)\n{\n  Vector3 V;\n  double fcx, fcy, fcz;\n  octave_idx_type idx, idy, idz;\n\n  handle_border (&idx, &fcx, X.idx, X.fcx, nx);\n  handle_border (&idy, &fcy, X.idy, X.fcy, ny);\n  handle_border (&idz, &fcz, X.idz, X.fcz, nz);\n\n  V.x = trilinear (u(idy, idx, idz), u(idy, idx+1, idz),\n                   u(idy+1, idx, idz), u(idy+1, idx+1, idz),\n                   u(idy, idx, idz+1), u(idy, idx+1, idz+1),\n                   u(idy+1, idx, idz+1), u(idy+1, idx+1, idz+1),\n                   fcx, fcy, fcz);\n  V.y = trilinear (v(idy, idx, idz), v(idy, idx+1, idz),\n                   v(idy+1, idx, idz), v(idy+1, idx+1, idz),\n                   v(idy, idx, idz+1), v(idy, idx+1, idz+1),\n                   v(idy+1, idx, idz+1), v(idy+1, idx+1, idz+1),\n                   fcx, fcy, fcz);\n  V.z = trilinear (w(idy, idx, idz), w(idy, idx+1, idz),\n                   w(idy+1, idx, idz), w(idy+1, idx+1, idz),\n                   w(idy, idx, idz+1), w(idy, idx+1, idz+1),\n                   w(idy+1, idx, idz+1), w(idy+1, idx+1, idz+1),\n                   fcx, fcy, fcz);\n\n  return (V);\n}\n\nstatic inline Vector3\ncalculate_step_vector3d (const Cell3 X, const Vector3 V,\n                         const RowVector& tx, const RowVector& ty, const RowVector& tz,\n                         const octave_idx_type nx, const octave_idx_type ny,\n                         const octave_idx_type nz, const double h)\n{\n  Vector3 S;\n\n  const octave_idx_type idx = handle_border_index (X.idx, nx);\n  const octave_idx_type idy = handle_border_index (X.idy, ny);\n  const octave_idx_type idz = handle_border_index (X.idz, nz);\n\n  const double x = V.x * tx(idx);\n  const double y = V.y * ty(idy);\n  const double z = V.z * tz(idz);\n  const double n = 1.0 / sqrt (x*x + y*y + z*z);\n  S.x = h * n * x;\n  S.y = h * n * y;\n  S.z = h * n * z;\n\n  return (S);\n}\n\nstatic inline bool\nis_singular3d (const Vector3 V)\n{\n  return ((math::isnan (V.x) || math::isnan (V.y) || math::isnan (V.z)) ||\n          ((V.x == 0) && (V.y == 0) && (V.z == 0)));\n}\n\nstatic void\neuler3d (const octave_idx_type nx, const octave_idx_type ny, const octave_idx_type nz,\n         const NDArray& u, const NDArray& v, const NDArray& w,\n         const RowVector& tx, const RowVector& ty, const RowVector& tz,\n         const double zeta, const double xi, const double rho,\n         const double h, const octave_idx_type maxnverts,\n         Matrix& buffer, octave_idx_type *nverts)\n{\n  Vector3 V0, V1, S0, X1, Xnxt, S1;\n  const Vector3 X0 = {zeta, xi, rho};\n  Cell3 X0f, X1f;\n\n  octave_idx_type i = 0;\n  buffer(i, 0) = X0.x;\n  buffer(i, 1) = X0.y;\n  buffer(i, 2) = X0.z;\n\n  X0f = vector_to_cell3d (X0);\n  while (true)\n    {\n      if (! is_in_definition_set3d (X0f, nx, ny, nz))\n        break;\n\n      V0 = vector_interpolation3d (X0f, u, v, w, nx, ny, nz);\n      if (is_singular3d (V0))\n        break;\n\n      S0 = calculate_step_vector3d (X0f, V0, tx, ty, tz, nx, ny, nz, h);\n\n      X1 = add3d (X0f, S0);\n\n      X1f = vector_to_cell3d (X1);\n      if (! is_in_definition_set3d (X1f, nx, ny, nz))\n        break;\n\n      V1 = vector_interpolation3d (X1f, u, v, w, nx, ny, nz);\n      if (is_singular3d (V1))\n        break;\n\n      S1 = calculate_step_vector3d (X1f, V1, tx, ty, tz, nx, ny, nz, h);\n\n      // Runge Kutta - Heun's Scheme\n      const Vector3 S = {0.5 * (S0.x + S1.x),\n                         0.5 * (S0.y + S1.y),\n                         0.5 * (S0.z + S1.z)\n                        };\n      Xnxt = add3d (X0f, S);\n\n      X0f = vector_to_cell3d (Xnxt);\n      if (! is_in_definition_set3d (X0f, nx, ny, nz))\n        break;\n\n      i++;\n      buffer(i, 0) = Xnxt.x;\n      buffer(i, 1) = Xnxt.y;\n      buffer(i, 2) = Xnxt.z;\n\n      if (i + 1 >= maxnverts)\n        break;\n\n    }\n\n  *nverts = i + 1;\n}\n\nstatic octave_value\nstreameuler2d_internal (const octave_value_list& args)\n{\n\n  const int nargin = args.length ();\n  if (nargin != 8)\n    print_usage ();\n\n  const Matrix U = args(0).matrix_value ();\n  const Matrix V = args(1).matrix_value ();\n  const RowVector TX = args(2).row_vector_value ();\n  const RowVector TY = args(3).row_vector_value ();\n  const double zeta = args(4).double_value ();\n  const double xi = args(5).double_value ();\n  const double h = args(6).double_value ();\n  const octave_idx_type maxnverts = args(7).idx_type_value ();\n\n  const octave_idx_type rows = U.rows ();\n  const octave_idx_type cols = U.columns ();\n\n  octave_idx_type nverts;\n  Matrix buffer (maxnverts, 2);\n\n  euler2d (cols, rows, U, V, TX, TY, zeta, xi, h, maxnverts,\n           buffer, &nverts);\n\n  Matrix xy = buffer.extract (0, 0, nverts-1, 1);\n\n  return octave_value (xy);\n}\n\nstatic octave_value\nstreameuler3d_internal (const octave_value_list& args, const char *fcn)\n{\n\n  const int nargin = args.length ();\n  if (nargin != 11)\n    print_usage ();\n\n  const NDArray U = args(0).array_value ();\n  const NDArray V = args(1).array_value ();\n  const NDArray W = args(2).array_value ();\n  const RowVector TX = args(3).row_vector_value ();\n  const RowVector TY = args(4).row_vector_value ();\n  const RowVector TZ = args(5).row_vector_value ();\n  const double zeta = args(6).double_value ();\n  const double xi = args(7).double_value ();\n  const double rho = args(8).double_value ();\n  const double h = args(9).double_value ();\n  const octave_idx_type maxnverts = args(10).idx_type_value ();\n\n  const dim_vector dims = args(0).dims ();\n  const int ndims = dims.ndims ();\n  if (ndims != 3)\n    error (\"%s: dimension must be 3\", fcn);\n\n  octave_idx_type nverts;\n  Matrix buffer (maxnverts, 3);\n\n  euler3d (dims(1), dims(0), dims(2), U, V, W, TX, TY, TZ, zeta, xi, rho,\n           h, maxnverts, buffer, &nverts);\n\n  Matrix xyz = buffer.extract (0, 0, nverts-1, 2);\n\n  return octave_value (xyz);\n}\n\nDEFUN (__streameuler2d__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{output} =} __streameuler2d__ (@var{U}, @var{V}, @var{TX}, @var{TY}, @var{ZETA}, @var{XI}, @var{H}, @var{MAXNVERTS})\nCalculate the streamline in a vector field @code{[@var{U}, @var{V}]} starting\nfrom a seed point at position @code{[@var{ZETA}, @var{XI}]}.  The integrator\nused is Heun's Scheme.  The step size can be controlled by @var{H}.  The\nJacobian matrix can be defined for each grid cell by\n@code{[@var{TX}, @var{TY}]}.\n\n@seealso{streamline, stream2, stream3, __streameuler3d__}\n@end deftypefn */)\n{\n  return streameuler2d_internal (args);\n}\n\nDEFUN (__streameuler3d__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{output} =} __streameuler3d__ (@var{U}, @var{V}, @var{W}, @var{TX}, @var{TY}, @var{TZ}, @var{ZETA}, @var{XI}, @var{RHO}, @var{H}, @var{MAXNVERTS})\nCalculate the streamline in a vector field @code{[@var{U}, @var{V}, @var{W}]}\nstarting from a seed point at position\n@code{[@var{ZETA}, @var{XI}, @var{RHO}]}.  The integrator used is Heun's\nScheme.  The step size can be controlled by @var{H}.  The Jacobian matrix can\nbe defined for each grid cell by @code{[@var{TX}, @var{TY}, @var{TZ}]}.\n\n@seealso{streamline, stream2, stream3, __streameuler2d__}\n@end deftypefn */)\n{\n  return streameuler3d_internal (args, \"__streameuler3d__\");\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/svd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"svd.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"pr-output.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic std::string Vsvd_driver = \"gesvd\";\n\ntemplate <typename T>\nstatic typename math::svd<T>::Type\nsvd_type (int nargin, int nargout, const octave_value_list& args, const T& A)\n{\n  if (nargout == 0 || nargout == 1)\n    return math::svd<T>::Type::sigma_only;\n  else if (nargin == 1)\n    return math::svd<T>::Type::std;\n  else if (! args(1).is_real_scalar ())\n    return math::svd<T>::Type::economy;\n  else\n    {\n      if (A.rows () > A.columns ())\n        return math::svd<T>::Type::economy;\n      else\n        return math::svd<T>::Type::std;\n    }\n}\n\ntemplate <typename T>\nstatic typename math::svd<T>::Driver\nsvd_driver ()\n{\n  if (Vsvd_driver == \"gejsv\")\n    return math::svd<T>::Driver::GEJSV;\n  else if (Vsvd_driver == \"gesdd\")\n    return math::svd<T>::Driver::GESDD;\n  else\n    return math::svd<T>::Driver::GESVD;  // default\n}\n\nDEFUN (svd, args, nargout,\n       classes: double single\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{s} =} svd (@var{A})\n@deftypefnx {} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A})\n@deftypefnx {} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A}, \"econ\")\n@deftypefnx {} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A}, 0)\n@cindex singular value decomposition\nCompute the singular value decomposition of @var{A}.\n\nThe singular value decomposition is defined by the relation\n@tex\n$$\n A = U S V^{\\dagger}\n$$\n@end tex\n@ifnottex\n\n@example\nA = U*S*V'\n@end example\n\n@end ifnottex\n\nThe function @code{svd} normally returns only the vector of singular values.\nWhen called with three return values, it computes\n@tex\n$U$, $S$, and $V$.\n@end tex\n@ifnottex\n@var{U}, @var{S}, and @var{V}.\n@end ifnottex\nFor example,\n\n@example\nsvd (hilb (3))\n@end example\n\n@noindent\nreturns\n\n@example\n@group\nans =\n\n  1.4083189\n  0.1223271\n  0.0026873\n@end group\n@end example\n\n@noindent\nand\n\n@example\n[u, s, v] = svd (hilb (3))\n@end example\n\n@noindent\nreturns\n\n@example\n@group\nu =\n\n  -0.82704   0.54745   0.12766\n  -0.45986  -0.52829  -0.71375\n  -0.32330  -0.64901   0.68867\n\ns =\n\n  1.40832  0.00000  0.00000\n  0.00000  0.12233  0.00000\n  0.00000  0.00000  0.00269\n\nv =\n\n  -0.82704   0.54745   0.12766\n  -0.45986  -0.52829  -0.71375\n  -0.32330  -0.64901   0.68867\n@end group\n@end example\n\nWhen given a second argument that is not 0, @code{svd} returns an economy-sized\ndecomposition, eliminating the unnecessary rows or columns of @var{U} or\n@var{V}.\n\nIf the second argument is exactly 0, then the choice of decomposition is based\non the matrix @var{A}.  If @var{A} has more rows than columns then an\neconomy-sized decomposition is returned, otherwise a regular decomposition\nis calculated.\n\nAlgorithm Notes: When calculating the full decomposition (left and right\nsingular matrices in addition to singular values) there is a choice of two\nroutines in @sc{lapack}.  The default routine used by Octave is @code{gesvd}.\nThe alternative is @code{gesdd} which is 5X faster, but may use more memory\nand may be inaccurate for some input matrices.  There is a third routine\n@code{gejsv}, suitable for better accuracy at extreme scale.  See the\ndocumentation for @code{svd_driver} for more information on choosing a driver.\n@seealso{svd_driver, svds, eig, lu, chol, hess, qr, qz}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2 || nargout > 3)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  if (arg.ndims () != 2)\n    error (\"svd: A must be a 2-D matrix\");\n\n  octave_value_list retval;\n\n  bool isfloat = arg.is_single_type ();\n\n  if (isfloat)\n    {\n      if (arg.isreal ())\n        {\n          FloatMatrix tmp = arg.float_matrix_value ();\n\n          if (tmp.any_element_is_inf_or_nan ())\n            error (\"svd: cannot take SVD of matrix containing Inf or NaN values\");\n\n          math::svd<FloatMatrix> result\n          (tmp,\n           svd_type<FloatMatrix> (nargin, nargout, args, tmp),\n           svd_driver<FloatMatrix> ());\n\n          FloatDiagMatrix sigma = result.singular_values ();\n\n          if (nargout == 0 || nargout == 1)\n            retval(0) = sigma.extract_diag ();\n          else if (nargout == 2)\n            retval = ovl (result.left_singular_matrix (),\n                          sigma);\n          else\n            retval = ovl (result.left_singular_matrix (),\n                          sigma,\n                          result.right_singular_matrix ());\n        }\n      else if (arg.iscomplex ())\n        {\n          FloatComplexMatrix ctmp = arg.float_complex_matrix_value ();\n\n          if (ctmp.any_element_is_inf_or_nan ())\n            error (\"svd: cannot take SVD of matrix containing Inf or NaN values\");\n\n          math::svd<FloatComplexMatrix> result\n          (ctmp,\n           svd_type<FloatComplexMatrix> (nargin, nargout, args, ctmp),\n           svd_driver<FloatComplexMatrix> ());\n\n          FloatDiagMatrix sigma = result.singular_values ();\n\n          if (nargout == 0 || nargout == 1)\n            retval(0) = sigma.extract_diag ();\n          else if (nargout == 2)\n            retval = ovl (result.left_singular_matrix (),\n                          sigma);\n          else\n            retval = ovl (result.left_singular_matrix (),\n                          sigma,\n                          result.right_singular_matrix ());\n        }\n    }\n  else\n    {\n      if (arg.isreal ())\n        {\n          Matrix tmp = arg.matrix_value ();\n\n          if (tmp.any_element_is_inf_or_nan ())\n            error (\"svd: cannot take SVD of matrix containing Inf or NaN values\");\n\n          math::svd<Matrix> result\n          (tmp,\n           svd_type<Matrix> (nargin, nargout, args, tmp),\n           svd_driver<Matrix> ());\n\n          DiagMatrix sigma = result.singular_values ();\n\n          if (nargout == 0 || nargout == 1)\n            retval(0) = sigma.extract_diag ();\n          else if (nargout == 2)\n            retval = ovl (result.left_singular_matrix (),\n                          sigma);\n          else\n            retval = ovl (result.left_singular_matrix (),\n                          sigma,\n                          result.right_singular_matrix ());\n        }\n      else if (arg.iscomplex ())\n        {\n          ComplexMatrix ctmp = arg.complex_matrix_value ();\n\n          if (ctmp.any_element_is_inf_or_nan ())\n            error (\"svd: cannot take SVD of matrix containing Inf or NaN values\");\n\n          math::svd<ComplexMatrix> result\n          (ctmp,\n           svd_type<ComplexMatrix> (nargin, nargout, args, ctmp),\n           svd_driver<ComplexMatrix> ());\n\n          DiagMatrix sigma = result.singular_values ();\n\n          if (nargout == 0 || nargout == 1)\n            retval(0) = sigma.extract_diag ();\n          else if (nargout == 2)\n            retval = ovl (result.left_singular_matrix (),\n                          sigma);\n          else\n            retval = ovl (result.left_singular_matrix (),\n                          sigma,\n                          result.right_singular_matrix ());\n        }\n      else\n        err_wrong_type_arg (\"svd\", arg);\n    }\n\n  return retval;\n}\n\n/*\n%!assert (svd ([1, 2; 2, 1]), [3; 1], sqrt (eps))\n\n%!test\n%! a = [1, 2; 3, 4] + [5, 6; 7, 8]*i;\n%! [u,s,v] = svd (a);\n%! assert (a, u * s * v', 128 * eps);\n\n%!test\n%! [u, s, v] = svd ([1, 2; 2, 1]);\n%! x = 1 / sqrt (2);\n%! ## Because values are accurate only up to a phase factor, tests must check\n%! ## separately for magnitude and for phase.\n%! assert (abs (u), abs ([-x, -x; -x, x]), sqrt (eps));\n%! phase = prod (sign (u));\n%! assert (phase == [1, -1] || phase == [-1, 1]); \n%! assert (s, [3, 0; 0, 1], sqrt (eps));\n%! assert (abs (v), abs ([-x, x; -x, -x]), sqrt (eps));\n%! phase = prod (sign (v));\n%! assert (phase == [1, -1] || phase == [-1, 1]); \n\n%!test\n%! a = [1, 2, 3; 4, 5, 6];\n%! [u, s, v] = svd (a);\n%! assert (u * s * v', a, sqrt (eps));\n\n%!test\n%! a = [1, 2; 3, 4; 5, 6];\n%! [u, s, v] = svd (a);\n%! assert (u * s * v', a, sqrt (eps));\n\n%!test\n%! a = [1, 2, 3; 4, 5, 6];\n%! [u, s, v] = svd (a, 1);\n%! assert (u * s * v', a, sqrt (eps));\n\n%!test\n%! a = [1, 2; 3, 4; 5, 6];\n%! [u, s, v] = svd (a, 1);\n%! assert (u * s * v', a, sqrt (eps));\n\n%!assert (svd (single ([1, 2; 2, 1])), single ([3; 1]), sqrt (eps (\"single\")))\n\n%!test\n%! [u, s, v] = svd (single ([1, 2; 2, 1]));\n%! x = single (1 / sqrt (2));\n\n%! assert (abs (u), abs ([-x, -x; -x, x]), sqrt (eps (\"single\")));\n%! phase = prod (sign (u));\n%! assert (phase == [1, -1] || phase == [-1, 1]); \n%! assert (s, single ([3, 0; 0, 1]), sqrt (eps (\"single\")));\n%! assert (abs (v), abs ([-x, x; -x, -x]), sqrt (eps (\"single\")));\n%! phase = prod (sign (v));\n%! assert (phase == [1, -1] || phase == [-1, 1]); \n\n%!test\n%! a = single ([1, 2, 3; 4, 5, 6]);\n%! [u, s, v] = svd (a);\n%! assert (u * s * v', a, sqrt (eps (\"single\")));\n\n%!test\n%! a = single ([1, 2; 3, 4; 5, 6]);\n%! [u, s, v] = svd (a);\n%! assert (u * s * v', a, sqrt (eps (\"single\")));\n\n%!test\n%! a = single ([1, 2, 3; 4, 5, 6]);\n%! [u, s, v] = svd (a, 1);\n%! assert (u * s * v', a, sqrt (eps (\"single\")));\n\n%!test\n%! a = single ([1, 2; 3, 4; 5, 6]);\n%! [u, s, v] = svd (a, 1);\n%! assert (u * s * v', a, sqrt (eps (\"single\")));\n\n%!test\n%! a = zeros (0, 5);\n%! [u, s, v] = svd (a);\n%! assert (size (u), [0, 0]);\n%! assert (size (s), [0, 5]);\n%! assert (size (v), [5, 5]);\n\n%!test\n%! a = zeros (5, 0);\n%! [u, s, v] = svd (a, 1);\n%! assert (size (u), [5, 0]);\n%! assert (size (s), [0, 0]);\n%! assert (size (v), [0, 0]);\n\n%!test <*49309>\n%! [~,~,v] = svd ([1, 1, 1], 0);\n%! assert (size (v), [3 3]);\n%! [~,~,v] = svd ([1, 1, 1], \"econ\");\n%! assert (size (v), [3 1]);\n\n%!assert <*55710> (1 / svd (-0), Inf)\n\n%!test\n%! old_driver = svd_driver (\"gejsv\");\n%! s0 = [1e-20; 1e-10; 1];  # only gejsv can pass\n%! q = sqrt (0.5);\n%! a = s0 .* [q, 0, -q; -0.5, q, -0.5; 0.5, q, 0.5];\n%! s1 = svd (a);\n%! svd_driver (old_driver);\n%! assert (sort (s1), s0, -10 * eps);\n\n%!error svd ()\n%!error svd ([1, 2; 4, 5], 2, 3)\n*/\n\nDEFUN (svd_driver, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} svd_driver ()\n@deftypefnx {} {@var{old_val} =} svd_driver (@var{new_val})\n@deftypefnx {} {@var{old_val} =} svd_driver (@var{new_val}, \"local\")\nQuery or set the underlying @sc{lapack} driver used by @code{svd}.\n\nCurrently recognized values are @qcode{\"gesdd\"}, @qcode{\"gesvd\"}, and\n@qcode{\"gejsv\"}.  The default is @qcode{\"gesvd\"}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n\nAlgorithm Notes: The @sc{lapack} library routines @code{gesvd} and @code{gesdd}\nare different only when calculating the full singular value decomposition (left\nand right singular matrices as well as singular values).  When calculating just\nthe singular values the following discussion is not relevant.\n\nThe newer @code{gesdd} routine is based on a Divide-and-Conquer algorithm that\nis 5X faster than the alternative @code{gesvd}, which is based on QR\nfactorization.  However, the new algorithm can use significantly more memory.\nFor an @nospell{MxN} input matrix the memory usage is of order O(min(M,N) ^ 2),\nwhereas the alternative is of order O(max(M,N)).\n\nThe routine @code{gejsv} uses a preconditioned Jacobi SVD algorithm.  Unlike\n@code{gesvd} and @code{gesdd}, in @code{gejsv}, there is no bidiagonalization\nstep that could contaminate accuracy in some extreme cases.  Also, @code{gejsv}\nis known to be optimally accurate in some sense.  However, the speed is slower\n(single threaded at its core) and uses more memory (O(min(M,N) ^ 2 + M + N)).\n\nBeyond speed and memory issues, there have been instances where some input\nmatrices were not accurately decomposed by @code{gesdd}.  See currently active\nbug @url{https://savannah.gnu.org/bugs/?55564}.  Until these accuracy issues\nare resolved in a new version of the @sc{lapack} library, the default driver\nin Octave has been set to @qcode{\"gesvd\"}.\n\n@seealso{svd}\n@end deftypefn */)\n{\n  static const char *driver_names[] = { \"gesvd\", \"gesdd\", \"gejsv\", nullptr };\n\n  return set_internal_variable (Vsvd_driver, args, nargout,\n                                \"svd_driver\", driver_names);\n}\n\n/*\n%!test\n%! A = [1+1i, 1-1i, 0; 0, 2, 0; 1i, 1i, 1+2i];\n%! old_driver = svd_driver (\"gesvd\");\n%! [U1, S1, V1] = svd (A);\n%! svd_driver (\"gesdd\");\n%! [U2, S2, V2] = svd (A);\n%! svd_driver (\"gejsv\");\n%! [U3, S3, V3] = svd (A);\n%! assert (svd_driver (), \"gejsv\");\n%! svd_driver (old_driver);\n%! assert (U1, U2, 6*eps);\n%! assert (S1, S2, 6*eps);\n%! assert (V1, V2, 6*eps);\n%! z = U1(1,:) ./ U3(1,:);\n%! assert (U1, U3 .* z, 100*eps);\n%! assert (S1, S3, 10*eps);\n%! assert (V1, V3 .* z, 100*eps);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/sylvester.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (sylvester, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{X} =} sylvester (@var{A}, @var{B}, @var{C})\nSolve the Sylvester equation.\n\nThe Sylvester equation is defined as:\n@tex\n$$\n A X + X B = C\n$$\n@end tex\n@ifnottex\n\n@example\nA X + X B = C\n@end example\n\n@end ifnottex\nThe solution is computed using standard @sc{lapack} subroutines.\n\nFor example:\n\n@example\n@group\nsylvester ([1, 2; 3, 4], [5, 6; 7, 8], [9, 10; 11, 12])\n   @xresult{} [ 0.50000, 0.66667; 0.66667, 0.50000 ]\n@end group\n@end example\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  octave_value retval;\n\n  octave_value arg_a = args(0);\n  octave_value arg_b = args(1);\n  octave_value arg_c = args(2);\n\n  octave_idx_type a_nr = arg_a.rows ();\n  octave_idx_type a_nc = arg_a.columns ();\n\n  octave_idx_type b_nr = arg_b.rows ();\n  octave_idx_type b_nc = arg_b.columns ();\n\n  octave_idx_type c_nr = arg_c.rows ();\n  octave_idx_type c_nc = arg_c.columns ();\n\n  bool isfloat = arg_a.is_single_type ()\n                 || arg_b.is_single_type ()\n                 || arg_c.is_single_type ();\n\n  if (arg_a.isempty () || arg_b.isempty () || arg_c.isempty ())\n    {\n      if (isfloat)\n        return ovl (FloatMatrix ());\n      else\n        return ovl (Matrix ());\n    }\n\n  // Arguments are not empty, so check for correct dimensions.\n\n  if (a_nr != a_nc)\n    err_square_matrix_required (\"sylvester\", \"A\");\n  if (b_nr != b_nc)\n    err_square_matrix_required (\"sylvester\", \"B\");\n  if (a_nr != c_nr || b_nr != c_nc)\n    ::err_nonconformant ();\n\n  if (isfloat)\n    {\n      if (arg_a.iscomplex ()\n          || arg_b.iscomplex ()\n          || arg_c.iscomplex ())\n        {\n          // Do everything in complex arithmetic;\n\n          FloatComplexMatrix ca = arg_a.float_complex_matrix_value ();\n          FloatComplexMatrix cb = arg_b.float_complex_matrix_value ();\n          FloatComplexMatrix cc = arg_c.float_complex_matrix_value ();\n\n          retval = Sylvester (ca, cb, cc);\n        }\n      else\n        {\n          // Do everything in real arithmetic.\n\n          FloatMatrix ca = arg_a.float_matrix_value ();\n          FloatMatrix cb = arg_b.float_matrix_value ();\n          FloatMatrix cc = arg_c.float_matrix_value ();\n\n          retval = Sylvester (ca, cb, cc);\n        }\n    }\n  else\n    {\n      if (arg_a.iscomplex ()\n          || arg_b.iscomplex ()\n          || arg_c.iscomplex ())\n        {\n          // Do everything in complex arithmetic;\n\n          ComplexMatrix ca = arg_a.complex_matrix_value ();\n          ComplexMatrix cb = arg_b.complex_matrix_value ();\n          ComplexMatrix cc = arg_c.complex_matrix_value ();\n\n          retval = Sylvester (ca, cb, cc);\n        }\n      else\n        {\n          // Do everything in real arithmetic.\n\n          Matrix ca = arg_a.matrix_value ();\n          Matrix cb = arg_b.matrix_value ();\n          Matrix cc = arg_c.matrix_value ();\n\n          retval = Sylvester (ca, cb, cc);\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!assert (sylvester ([1, 2; 3, 4], [5, 6; 7, 8], [9, 10; 11, 12]),\n%!        [1/2, 2/3; 2/3, 1/2], sqrt (eps))\n%!assert (sylvester (single ([1, 2; 3, 4]), single ([5, 6; 7, 8]), single ([9, 10; 11, 12])),\n%!        single ([1/2, 2/3; 2/3, 1/2]), sqrt (eps (\"single\")))\n\n## Test input validation\n%!error sylvester ()\n%!error sylvester (1)\n%!error sylvester (1,2)\n%!error sylvester (1, 2, 3, 4)\n%!error <A must be a square matrix> sylvester (ones (2,3), ones (2,2), ones (2,2))\n%!error <B must be a square matrix> sylvester (ones (2,2), ones (2,3), ones (2,2))\n%!error <nonconformant matrices> sylvester (ones (2,2), ones (2,2), ones (3,3))\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/symbfact.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <string>\n\n#include \"CSparse.h\"\n#include \"boolSparse.h\"\n#include \"dRowVector.h\"\n#include \"dSparse.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sparse.h\"\n#include \"oct-spparms.h\"\n#include \"sparse-util.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"parse.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (symbfact, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{count}, @var{h}, @var{parent}, @var{post}, @var{R}] =} symbfact (@var{S})\n@deftypefnx {} {[@dots{}] =} symbfact (@var{S}, @var{typ})\n@deftypefnx {} {[@dots{}] =} symbfact (@var{S}, @var{typ}, @var{mode})\n\nPerform a symbolic factorization analysis of the sparse matrix @var{S}.\n\nThe input variables are\n\n@table @var\n@item S\n@var{S} is a real or complex sparse matrix.\n\n@item typ\nIs the type of the factorization and can be one of\n\n@table @asis\n@item @qcode{\"sym\"} (default)\nFactorize @var{S}.  Assumes @var{S} is symmetric and uses the upper\ntriangular portion of the matrix.\n\n@item @qcode{\"col\"}\nFactorize @tcode{@var{S}' * @var{S}}.\n\n@item @qcode{\"row\"}\nFactorize @tcode{@var{S} * @var{S}'}.\n\n@item @qcode{\"lo\"}\nFactorize @tcode{@var{S}'}.  Assumes @var{S} is symmetric and uses the lower\ntriangular portion of the matrix.\n@end table\n\n@item mode\nWhen @var{mode} is unspecified return the Cholesky@tie{}factorization for\n@var{R}.  If @var{mode} is @qcode{\"lower\"} or @qcode{\"L\"} then return\nthe conjugate transpose @tcode{@var{R}'} which is a lower triangular factor.\nThe conjugate transpose version is faster and uses less memory, but still\nreturns the same values for all other outputs: @var{count}, @var{h},\n@var{parent}, and @var{post}.\n@end table\n\nThe output variables are:\n\n@table @var\n@item count\nThe row counts of the Cholesky@tie{}factorization as determined by\n@var{typ}.  The computational difficulty of performing the true\nfactorization using @code{chol} is @code{sum (@var{count} .^ 2)}.\n\n@item h\nThe height of the elimination tree.\n\n@item parent\nThe elimination tree itself.\n\n@item post\nA sparse boolean matrix whose structure is that of the\nCholesky@tie{}factorization as determined by @var{typ}.\n@end table\n@seealso{chol, etree, treelayout}\n@end deftypefn */)\n{\n#if defined (HAVE_CHOLMOD)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  octave_value_list retval;\n\n  double dummy;\n  cholmod_sparse Astore;\n  cholmod_sparse *A = &Astore;\n  A->packed = true;\n  A->sorted = true;\n  A->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n  A->itype = CHOLMOD_LONG;\n#else\n  A->itype = CHOLMOD_INT;\n#endif\n  A->dtype = CHOLMOD_DOUBLE;\n  A->stype = 1;\n  A->x = &dummy;\n\n  SparseMatrix sm;\n  SparseComplexMatrix scm;\n\n  if (args(0).isreal ())\n    {\n      sm = args(0).sparse_matrix_value ();\n      A->nrow = sm.rows ();\n      A->ncol = sm.cols ();\n      A->p = sm.cidx ();\n      A->i = sm.ridx ();\n      A->nzmax = sm.nnz ();\n      A->xtype = CHOLMOD_REAL;\n\n      if (A->nrow > 0 && A->ncol > 0)\n        A->x = sm.data ();\n    }\n  else if (args(0).iscomplex ())\n    {\n      scm = args(0).sparse_complex_matrix_value ();\n      A->nrow = scm.rows ();\n      A->ncol = scm.cols ();\n      A->p = scm.cidx ();\n      A->i = scm.ridx ();\n      A->nzmax = scm.nnz ();\n      A->xtype = CHOLMOD_COMPLEX;\n\n      if (A->nrow > 0 && A->ncol > 0)\n        A->x = scm.data ();\n    }\n  else\n    err_wrong_type_arg (\"symbfact\", args(0));\n\n  bool coletree = false;\n  octave_idx_type n = A->nrow;\n\n  if (nargin > 1)\n    {\n      std::string str = args(1).xstring_value (\"TYP must be a string\");\n      // FIXME: The input validation could be improved to use strncmp\n      char ch;\n      ch = tolower (str[0]);\n      if (ch == 'r')          // 'row'\n        A->stype = 0;\n      else if (ch == 'c')     // 'col'\n        {\n          n = A->ncol;\n          coletree = true;\n          A->stype = 0;\n        }\n      else if (ch == 's')     // 'sym' (default)\n        A->stype = 1;\n      else if (ch == 'l')     // 'lo'\n        A->stype = -1;\n      else\n        error (R\"(symbfact: unrecognized TYP \"%s\")\", str.c_str ());\n    }\n\n  if (nargin == 3)\n    {\n      std::string str = args(2).xstring_value (\"MODE must be a string\");\n      // FIXME: The input validation could be improved to use strncmp\n      char ch;\n      ch = toupper (str[0]);\n      if (ch != 'L')\n        error (R\"(symbfact: unrecognized MODE \"%s\")\", str.c_str ());\n    }\n\n  if (A->stype && A->nrow != A->ncol)\n    err_square_matrix_required (\"symbfact\", \"S\");\n\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, Parent, n);\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, Post, n);\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, ColCount, n);\n  OCTAVE_LOCAL_BUFFER (suitesparse_integer, First, n);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Level, n);\n\n  cholmod_common Common;\n  cholmod_common *cm = &Common;\n  CHOLMOD_NAME(start) (cm);\n\n  double spu = sparse_params::get_key (\"spumoni\");\n  if (spu == 0.0)\n    {\n      cm->print = -1;\n      SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n    }\n  else\n    {\n      cm->print = static_cast<int> (spu) + 2;\n      SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);\n    }\n\n  cm->error_handler = &SparseCholError;\n  SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);\n  SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n  cholmod_sparse *F = CHOLMOD_NAME(transpose) (A, 0, cm);\n  cholmod_sparse *Aup, *Alo;\n\n  if (A->stype == 1 || coletree)\n    {\n      Aup = A;\n      Alo = F;\n    }\n  else\n    {\n      Aup = F;\n      Alo = A;\n    }\n\n  CHOLMOD_NAME(etree) (Aup, Parent, cm);\n\n  RowVector tmp (n);    // Declaration must precede any goto cleanup.\n  std::string err_msg;\n\n  if (cm->status < CHOLMOD_OK)\n    {\n      err_msg = \"symbfact: matrix corrupted\";\n      goto cleanup;\n    }\n\n  if (CHOLMOD_NAME(postorder) (Parent, n, nullptr, Post, cm) != n)\n    {\n      err_msg = \"symbfact: postorder failed\";\n      goto cleanup;\n    }\n\n  CHOLMOD_NAME(rowcolcounts) (Alo, nullptr, 0, Parent, Post, nullptr, ColCount,\n                              First, to_suitesparse_intptr (Level), cm);\n\n  if (cm->status < CHOLMOD_OK)\n    {\n      err_msg = \"symbfact: matrix corrupted\";\n      goto cleanup;\n    }\n\n  if (nargout > 4)\n    {\n      cholmod_sparse *A1, *A2;\n\n      if (A->stype == 1)\n        {\n          A1 = A;\n          A2 = nullptr;\n        }\n      else if (A->stype == -1)\n        {\n          A1 = F;\n          A2 = nullptr;\n        }\n      else if (coletree)\n        {\n          A1 = F;\n          A2 = A;\n        }\n      else\n        {\n          A1 = A;\n          A2 = F;\n        }\n\n      // count the total number of entries in L\n      octave_idx_type lnz = 0;\n      for (octave_idx_type j = 0 ; j < n ; j++)\n        lnz += ColCount[j];\n\n      // allocate the output matrix L (pattern-only)\n      SparseBoolMatrix L (dim_vector (n, n), lnz);\n\n      // initialize column pointers\n      lnz = 0;\n      for (octave_idx_type j = 0 ; j < n ; j++)\n        {\n          L.xcidx(j) = lnz;\n          lnz += ColCount[j];\n        }\n      L.xcidx(n) = lnz;\n\n      // create a copy of the column pointers\n      suitesparse_integer *W = First;\n      for (octave_idx_type j = 0 ; j < n ; j++)\n        W[j] = L.xcidx (j);\n\n      // get workspace for computing one row of L\n      cholmod_sparse *R\n        = CHOLMOD_NAME(allocate_sparse) (n, 1, n, false, true,\n                                         0, CHOLMOD_PATTERN, cm);\n      octave_idx_type *Rp = static_cast<octave_idx_type *> (R->p);\n      octave_idx_type *Ri = static_cast<octave_idx_type *> (R->i);\n\n      // compute L one row at a time\n      for (octave_idx_type k = 0 ; k < n ; k++)\n        {\n          // get the kth row of L and store in the columns of L\n          CHOLMOD_NAME(row_subtree) (A1, A2, k, Parent, R, cm);\n          for (octave_idx_type p = 0 ; p < Rp[1] ; p++)\n            L.xridx (W[Ri[p]]++) = k;\n\n          // add the diagonal entry\n          L.xridx (W[k]++) = k;\n        }\n\n      // free workspace\n      CHOLMOD_NAME(free_sparse) (&R, cm);\n\n      // fill L with one's\n      std::fill_n (L.xdata (), lnz, true);\n\n      // transpose L to get R, or leave as is\n      if (nargin < 3)\n        L = L.transpose ();\n\n      retval(4) = L;\n    }\n\n  if (nargout > 3)\n    {\n      for (octave_idx_type i = 0; i < n; i++)\n        tmp(i) = Post[i] + 1;\n      retval(3) = tmp;\n    }\n\n  if (nargout > 2)\n    {\n      for (octave_idx_type i = 0; i < n; i++)\n        tmp(i) = Parent[i] + 1;\n      retval(2) = tmp;\n    }\n\n  if (nargout > 1)\n    {\n      // compute the elimination tree height\n      octave_idx_type height = 0;\n      for (int i = 0 ; i < n ; i++)\n        height = std::max (height, Level[i]);\n      height++;\n      retval(1) = static_cast<double> (height);\n    }\n\n  for (octave_idx_type i = 0; i < n; i++)\n    tmp(i) = ColCount[i];\n  retval(0) = tmp;\n\ncleanup:\n  CHOLMOD_NAME(free_sparse) (&F, cm);\n  CHOLMOD_NAME(finish) (cm);\n\n  if (! err_msg.empty ())\n    error (\"%s\", err_msg.c_str ());\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"symbfact\", \"CHOLMOD\");\n\n#endif\n}\n\n/*\n%!testif HAVE_CHOLMOD\n%! A = sparse (magic (3));\n%! [count, h, parent, post, r] = symbfact (A);\n%! assert (count, [3, 2, 1]);\n%! assert (h, 3);\n%! assert (parent, [2, 3, 0]);\n%! assert (r, sparse (triu (true (3))));\n\n%!testif HAVE_CHOLMOD\n%! ## Test MODE \"lower\"\n%! A = sparse (magic (3));\n%! [~, ~, ~, ~, l] = symbfact (A, \"sym\", \"lower\");\n%! assert (l, sparse (tril (true (3))));\n\n%!testif HAVE_CHOLMOD <*42587>\n%! ## singular matrix\n%! A = sparse ([1 0 8;0 1 8;8 8 1]);\n%! [count, h, parent, post, r] = symbfact (A);\n\n## Test input validation\n%!testif HAVE_CHOLMOD\n%! fail (\"symbfact ()\");\n%! fail (\"symbfact (1,2,3,4)\");\n%! fail (\"symbfact ({1})\", \"wrong type argument 'cell'\");\n%! fail (\"symbfact (sparse (1), {1})\", \"TYP must be a string\");\n%! fail (\"symbfact (sparse (1), 'foobar')\", 'unrecognized TYP \"foobar\"');\n%! fail (\"symbfact (sparse (1), 'sym', {'L'})\", \"MODE must be a string\");\n%! fail ('symbfact (sparse (1), \"sym\", \"foobar\")','unrecognized MODE \"foobar\"');\n%! fail (\"symbfact (sparse ([1, 2; 3, 4; 5, 6]))\", \"S must be a square matrix\");\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/symrcm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\nAn implementation of the Reverse Cuthill-McKee algorithm (symrcm)\n\nThe implementation of this algorithm is based in the descriptions found in\n\n@INPROCEEDINGS{,\n        author = {E. Cuthill and J. McKee},\n        title = {Reducing the Bandwidth of Sparse Symmetric Matrices},\n        booktitle = {Proceedings of the 24th ACM National Conference},\n        publisher = {Brandon Press},\n        pages = {157 -- 172},\n        location = {New Jersey},\n        year = {1969}\n}\n\n@BOOK{,\n        author = {Alan George and Joseph W. H. Liu},\n        title = {Computer Solution of Large Sparse Positive Definite Systems},\n        publisher = {Prentice Hall Series in Computational Mathematics},\n        ISBN = {0-13-165274-5},\n        year = {1981}\n}\n\nThe algorithm represents a heuristic approach to the NP-complete minimum\nbandwidth problem.\n\nWritten by Michael Weitzel <michael.weitzel@@uni-siegen.de>\n                           <weitzel@@ldknet.org>\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n\n#include \"CSparse.h\"\n#include \"boolNDArray.h\"\n#include \"dNDArray.h\"\n#include \"dSparse.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sparse.h\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// A node struct for the Cuthill-McKee algorithm\nstruct CMK_Node\n{\n  // the node's id (matrix row index)\n  octave_idx_type id;\n  // the node's degree\n  octave_idx_type deg;\n  // minimal distance to the root of the spanning tree\n  octave_idx_type dist;\n};\n\n// A simple queue.\n// Queues Q have a fixed maximum size N (rows,cols of the matrix) and are\n// stored in an array.  qh and qt point to queue head and tail.\n\n// Enqueue operation (adds a node \"o\" at the tail)\n\ninline static void\nQ_enq (CMK_Node *Q, octave_idx_type N, octave_idx_type& qt, const CMK_Node& o)\n{\n  Q[qt] = o;\n  qt = (qt + 1) % (N + 1);\n}\n\n// Dequeue operation (removes a node from the head)\n\ninline static CMK_Node\nQ_deq (CMK_Node *Q, octave_idx_type N, octave_idx_type& qh)\n{\n  CMK_Node r = Q[qh];\n  qh = (qh + 1) % (N + 1);\n  return r;\n}\n\n// Predicate (queue empty)\n#define Q_empty(Q, N, qh, qt)   ((qh) == (qt))\n\n// A simple, array-based binary heap (used as a priority queue for nodes)\n\n// the left descendant of entry i\n#define LEFT(i)         (((i) << 1) + 1)        // = (2*(i)+1)\n                                                // the right descendant of entry i\n#define RIGHT(i)        (((i) << 1) + 2)        // = (2*(i)+2)\n                                                // the parent of entry i\n#define PARENT(i)       (((i) - 1) >> 1)        // = floor(((i)-1)/2)\n\n// Builds a min-heap (the root contains the smallest element).  A is an array\n// with the graph's nodes, i is a starting position, size is the length of A.\n\nstatic void\nH_heapify_min (CMK_Node *A, octave_idx_type i, octave_idx_type size)\n{\n  octave_idx_type j = i;\n  for (;;)\n    {\n      octave_idx_type l = LEFT(j);\n      octave_idx_type r = RIGHT(j);\n\n      octave_idx_type smallest;\n      if (l < size && A[l].deg < A[j].deg)\n        smallest = l;\n      else\n        smallest = j;\n\n      if (r < size && A[r].deg < A[smallest].deg)\n        smallest = r;\n\n      if (smallest != j)\n        {\n          std::swap (A[j], A[smallest]);\n          j = smallest;\n        }\n      else\n        break;\n    }\n}\n\n// Heap operation insert.  Running time is O(log(n))\n\nstatic void\nH_insert (CMK_Node *H, octave_idx_type& h, const CMK_Node& o)\n{\n  octave_idx_type i = h++;\n\n  H[i] = o;\n\n  if (i == 0)\n    return;\n  do\n    {\n      octave_idx_type p = PARENT(i);\n      if (H[i].deg < H[p].deg)\n        {\n          std::swap (H[i], H[p]);\n\n          i = p;\n        }\n      else\n        break;\n    }\n  while (i > 0);\n}\n\n// Heap operation remove-min.  Removes the smallest element in O(1) and\n// reorganizes the heap optionally in O(log(n))\n\ninline static CMK_Node\nH_remove_min (CMK_Node *H, octave_idx_type& h, int reorg/*=1*/)\n{\n  CMK_Node r = H[0];\n  H[0] = H[--h];\n  if (reorg)\n    H_heapify_min (H, 0, h);\n  return r;\n}\n\n// Predicate (heap empty)\n#define H_empty(H, h)   ((h) == 0)\n\n// Helper function for the Cuthill-McKee algorithm.  Tries to determine a\n// pseudo-peripheral node of the graph as starting node.\n\nstatic octave_idx_type\nfind_starting_node (octave_idx_type N, const octave_idx_type *ridx,\n                    const octave_idx_type *cidx, const octave_idx_type *ridx2,\n                    const octave_idx_type *cidx2, octave_idx_type *D,\n                    octave_idx_type start)\n{\n  CMK_Node w;\n\n  OCTAVE_LOCAL_BUFFER (CMK_Node, Q, N+1);\n  boolNDArray btmp (dim_vector (1, N), false);\n  bool *visit = btmp.rwdata ();\n\n  octave_idx_type qh = 0;\n  octave_idx_type qt = 0;\n  CMK_Node x;\n  x.id = start;\n  x.deg = D[start];\n  x.dist = 0;\n  Q_enq (Q, N, qt, x);\n  visit[start] = true;\n\n  // distance level\n  octave_idx_type level = 0;\n  // current largest \"eccentricity\"\n  octave_idx_type max_dist = 0;\n\n  for (;;)\n    {\n      while (! Q_empty (Q, N, qh, qt))\n        {\n          CMK_Node v = Q_deq (Q, N, qh);\n\n          if (v.dist > x.dist || (v.id != x.id && v.deg > x.deg))\n            x = v;\n\n          octave_idx_type i = v.id;\n\n          // add all unvisited neighbors to the queue\n          octave_idx_type j1 = cidx[i];\n          octave_idx_type j2 = cidx2[i];\n          while (j1 < cidx[i+1] || j2 < cidx2[i+1])\n            {\n              if (j1 == cidx[i+1])\n                {\n                  octave_idx_type r2 = ridx2[j2++];\n                  if (! visit[r2])\n                    {\n                      // the distance of node j is dist(i)+1\n                      w.id = r2;\n                      w.deg = D[r2];\n                      w.dist = v.dist+1;\n                      Q_enq (Q, N, qt, w);\n                      visit[r2] = true;\n\n                      if (w.dist > level)\n                        level = w.dist;\n                    }\n                }\n              else if (j2 == cidx2[i+1])\n                {\n                  octave_idx_type r1 = ridx[j1++];\n                  if (! visit[r1])\n                    {\n                      // the distance of node j is dist(i)+1\n                      w.id = r1;\n                      w.deg = D[r1];\n                      w.dist = v.dist+1;\n                      Q_enq (Q, N, qt, w);\n                      visit[r1] = true;\n\n                      if (w.dist > level)\n                        level = w.dist;\n                    }\n                }\n              else\n                {\n                  octave_idx_type r1 = ridx[j1];\n                  octave_idx_type r2 = ridx2[j2];\n                  if (r1 <= r2)\n                    {\n                      if (! visit[r1])\n                        {\n                          w.id = r1;\n                          w.deg = D[r1];\n                          w.dist = v.dist+1;\n                          Q_enq (Q, N, qt, w);\n                          visit[r1] = true;\n\n                          if (w.dist > level)\n                            level = w.dist;\n                        }\n                      j1++;\n                      if (r1 == r2)\n                        j2++;\n                    }\n                  else\n                    {\n                      if (! visit[r2])\n                        {\n                          w.id = r2;\n                          w.deg = D[r2];\n                          w.dist = v.dist+1;\n                          Q_enq (Q, N, qt, w);\n                          visit[r2] = true;\n\n                          if (w.dist > level)\n                            level = w.dist;\n                        }\n                      j2++;\n                    }\n                }\n            }\n        } // finish of BFS\n\n      if (max_dist < x.dist)\n        {\n          max_dist = x.dist;\n\n          for (octave_idx_type i = 0; i < N; i++)\n            visit[i] = false;\n\n          visit[x.id] = true;\n          x.dist = 0;\n          qt = qh = 0;\n          Q_enq (Q, N, qt, x);\n        }\n      else\n        break;\n    }\n  return x.id;\n}\n\n// Calculates the node's degrees.  This means counting the nonzero elements\n// in the symmetric matrix' rows.  This works for non-symmetric matrices\n// as well.\n\nstatic octave_idx_type\ncalc_degrees (octave_idx_type N, octave_idx_type *cidx, octave_idx_type *ridx,\n              octave_idx_type *cidx2, octave_idx_type *ridx2, octave_idx_type *D)\n{\n  octave_idx_type max_deg = 0;\n  for (octave_idx_type i = 0; i < N; i++)\n    D[i] = 0;\n\n  for (octave_idx_type j = 0; j < N; j++)\n    for (octave_idx_type i = cidx[j]; i < cidx[j+1]; i++)\n      D[ridx[i]]++;\n\n  for (octave_idx_type j = 0; j < N; j++)\n    for (octave_idx_type i = cidx2[j]; i < cidx2[j+1]; i++)\n      D[ridx2[i]]++;\n\n  for (octave_idx_type i = 0; i < N; i++)\n    if (D[i] > max_deg)\n      max_deg = D[i];\n\n  return max_deg;\n}\n\n// Transpose of the structure of a square sparse matrix\n\nstatic void\ntranspose (octave_idx_type N, const octave_idx_type *ridx,\n           const octave_idx_type *cidx, octave_idx_type *ridx2,\n           octave_idx_type *cidx2)\n{\n  octave_idx_type nz = cidx[N];\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, w, N + 1);\n  for (octave_idx_type i = 0; i < N; i++)\n    w[i] = 0;\n  for (octave_idx_type i = 0; i < nz; i++)\n    w[ridx[i]]++;\n  nz = 0;\n  for (octave_idx_type i = 0; i < N; i++)\n    {\n      cidx2[i] = nz;\n      nz += w[i];\n      w[i] = cidx2[i];\n    }\n  cidx2[N] = nz;\n  w[N] = nz;\n\n  for (octave_idx_type j = 0; j < N; j++)\n    for (octave_idx_type k = cidx[j]; k < cidx[j + 1]; k++)\n      {\n        octave_idx_type q = w[ridx[k]]++;\n        ridx2[q] = j;\n      }\n}\n\n// An implementation of the Cuthill-McKee algorithm.\nDEFUN (symrcm, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{p} =} symrcm (@var{S})\nReturn the symmetric reverse @nospell{Cuthill-McKee} permutation of @var{S}.\n\n@var{p} is a permutation vector such that\n@code{@var{S}(@var{p}, @var{p})} tends to have its diagonal elements closer\nto the diagonal than @var{S}.  This is a good preordering for LU or\nCholesky@tie{}factorization of matrices that come from ``long, skinny''\nproblems.  It works for both symmetric and asymmetric @var{S}.\n\nThe algorithm represents a heuristic approach to the NP-complete bandwidth\nminimization problem.  The implementation is based in the descriptions found\nin\n\n@nospell{E. Cuthill, J. McKee}.\n\"Reducing the Bandwidth of Sparse Symmetric Matrices\".\n@cite{Proceedings of the 24th @nospell{ACM} National Conference},\n@w{pp.@: 157}--172, 1969, Brandon Press, New Jersey.\n\n@nospell{A. George, J.W.H. Liu}.\n\"Computer Solution of Large Sparse Positive Definite Systems\",\n@cite{Prentice Hall Series in Computational Mathematics}, ISBN 0-13-165274-5,\n1981.\n\n@seealso{colperm, colamd, symamd}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  octave_idx_type nr = arg.rows ();\n  octave_idx_type nc = arg.columns ();\n\n  if (nr != nc)\n    err_square_matrix_required (\"symrcm\", \"S\");\n\n  if (nr == 0 && nc == 0)\n    return ovl (NDArray (dim_vector (1, 0)));\n\n  // dimension of the matrix\n  octave_idx_type N = nr;\n\n  // the parameter of the matrix is converted into a sparse matrix\n  //(if necessary)\n  SparseMatrix Ar;\n\n  octave_quit ();\n\n  if (arg.isreal ())\n    {\n      Ar = arg.sparse_matrix_value ();\n    }\n  else\n    {\n      SparseComplexMatrix Ac = arg.sparse_complex_matrix_value ();\n      Ar = max (max (real (Ac), -real (Ac)), max (imag (Ac), -imag (Ac)));\n    }\n\n  octave_quit ();\n\n  // Note cidx/ridx are const, so use xridx and xcidx...\n  octave_idx_type *cidx = Ar.xcidx ();\n  octave_idx_type *ridx = Ar.xridx ();\n\n  // transpose\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, cidx2, N + 1);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, ridx2, cidx[N]);\n  transpose (N, ridx, cidx, ridx2, cidx2);\n\n  octave_quit ();\n\n  // vertex degrees\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, D, N);\n  octave_idx_type max_deg = calc_degrees (N, cidx, ridx, cidx2, ridx2, D);\n\n  octave_quit ();\n\n  // the permutation vector\n  NDArray P (dim_vector (1, N));\n\n  // if none of the nodes has a degree > 0 (a matrix of zeros)\n  // the return value corresponds to the identity permutation\n  if (max_deg == 0)\n    {\n      for (octave_idx_type i = 0; i < N; i++)\n        P(i) = i+1;  // +1 to convert from base-0 to base-1\n\n      return ovl (P);\n    }\n\n  // At this point, all early returns have completed.\n  // Proceed to BFS.\n\n  // sizes of the heaps\n  octave_idx_type s = 0;\n\n  // head- and tail-indices for the queue\n  octave_idx_type qt = 0;\n  octave_idx_type qh = 0;\n  CMK_Node v, w;\n\n  // a heap for the a node's neighbors.  The number of neighbors is\n  // limited by the maximum degree max_deg:\n  OCTAVE_LOCAL_BUFFER (CMK_Node, S, max_deg);\n\n  // a queue for the BFS.  The array is always one element larger than\n  // the number of entries that are stored.\n  OCTAVE_LOCAL_BUFFER (CMK_Node, Q, N+1);\n\n  // a counter (for building the permutation)\n  octave_idx_type c = -1;\n\n  // upper bound for the bandwidth (=quality of solution)\n  // initialize the bandwidth of the graph with 0.  B contains the\n  // the maximum of the theoretical lower limits of the subgraphs\n  // bandwidths.\n  octave_idx_type B = 0;\n\n  // mark all nodes as unvisited; with the exception of the nodes\n  // that have degree==0 and build a CC of the graph.\n\n  boolNDArray btmp (dim_vector (1, N), false);\n  bool *visit = btmp.rwdata ();\n\n  octave_quit ();\n\n  do\n    {\n      // locate an unvisited starting node of the graph\n      octave_idx_type i;\n      for (i = 0; i < N; i++)\n        if (! visit[i])\n          break;\n\n      // locate a probably better starting node\n      v.id = find_starting_node (N, ridx, cidx, ridx2, cidx2, D, i);\n\n      // mark the node as visited and enqueue it (a starting node\n      // for the BFS).  Since the node will be a root of a spanning\n      // tree, its dist is 0.\n      v.deg = D[v.id];\n      v.dist = 0;\n      visit[v.id] = true;\n      Q_enq (Q, N, qt, v);\n\n      // lower bound for the bandwidth of a subgraph\n      // keep a \"level\" in the spanning tree (= min. distance to the\n      // root) for determining the bandwidth of the computed\n      // permutation P\n      octave_idx_type Bsub = 0;\n      // min. dist. to the root is 0\n      octave_idx_type level = 0;\n      // the root is the first/only node on level 0\n      octave_idx_type level_N = 1;\n\n      while (! Q_empty (Q, N, qh, qt))\n        {\n          v = Q_deq (Q, N, qh);\n          i = v.id;\n\n          c++;\n\n          // for computing the inverse permutation P where\n          // A(inv(P),inv(P)) or P'*A*P is banded\n          //         P(i) = c;\n\n          // for computing permutation P where\n          // A(P(i),P(j)) or P*A*P' is banded\n          P(c) = i;\n\n          // put all unvisited neighbors j of node i on the heap\n          s = 0;\n          octave_idx_type j1 = cidx[i];\n          octave_idx_type j2 = cidx2[i];\n\n          while (j1 < cidx[i+1] || j2 < cidx2[i+1])\n            {\n              if (j1 == cidx[i+1])\n                {\n                  octave_idx_type r2 = ridx2[j2++];\n                  if (! visit[r2])\n                    {\n                      // the distance of node j is dist(i)+1\n                      w.id = r2;\n                      w.deg = D[r2];\n                      w.dist = v.dist+1;\n                      H_insert (S, s, w);\n                      visit[r2] = true;\n                    }\n                }\n              else if (j2 == cidx2[i+1])\n                {\n                  octave_idx_type r1 = ridx[j1++];\n                  if (! visit[r1])\n                    {\n                      w.id = r1;\n                      w.deg = D[r1];\n                      w.dist = v.dist+1;\n                      H_insert (S, s, w);\n                      visit[r1] = true;\n                    }\n                }\n              else\n                {\n                  octave_idx_type r1 = ridx[j1];\n                  octave_idx_type r2 = ridx2[j2];\n                  if (r1 <= r2)\n                    {\n                      if (! visit[r1])\n                        {\n                          w.id = r1;\n                          w.deg = D[r1];\n                          w.dist = v.dist+1;\n                          H_insert (S, s, w);\n                          visit[r1] = true;\n                        }\n                      j1++;\n                      if (r1 == r2)\n                        j2++;\n                    }\n                  else\n                    {\n                      if (! visit[r2])\n                        {\n                          w.id = r2;\n                          w.deg = D[r2];\n                          w.dist = v.dist+1;\n                          H_insert (S, s, w);\n                          visit[r2] = true;\n                        }\n                      j2++;\n                    }\n                }\n            }\n\n          // add the neighbors to the queue (sorted by node degree)\n          while (! H_empty (S, s))\n            {\n              // locate a neighbor of i with minimal degree in O(log(N))\n              v = H_remove_min (S, s, 1);\n\n              // entered the BFS a new level?\n              if (v.dist > level)\n                {\n                  // adjustment of bandwidth:\n                  // \"[...] the minimum bandwidth that\n                  // can be obtained [...] is the\n                  //  maximum number of nodes per level\"\n                  if (Bsub < level_N)\n                    Bsub = level_N;\n\n                  level = v.dist;\n                  // v is the first node on the new level\n                  level_N = 1;\n                }\n              else\n                {\n                  // there is no new level but another node on\n                  // this level:\n                  level_N++;\n                }\n\n              // enqueue v in O(1)\n              Q_enq (Q, N, qt, v);\n            }\n\n          // synchronize the bandwidth with level_N once again:\n          if (Bsub < level_N)\n            Bsub = level_N;\n        }\n      // finish of BFS.  If there are still unvisited nodes in the graph\n      // then it is split into CCs.  The computed bandwidth is the maximum\n      // of all subgraphs.  Update:\n      if (Bsub > B)\n        B = Bsub;\n    }\n  // are there any nodes left?\n  while (c+1 < N);\n\n  // compute the reverse-ordering\n  s = N / 2 - 1;\n  for (octave_idx_type i = 0, j = N - 1; i <= s; i++, j--)\n    std::swap (P.elem (i), P.elem (j));\n\n  // increment all indices, since Octave is not C\n  return ovl (P+1);\n}\n\n/*\n\n  basic functionality test, with icosahedron:\n%!test <*64718>\n%! adj = [ 0 1 1 1 1 1 0 0 0 0 0 0;\n%!         1 0 1 0 0 1 1 0 0 0 1 0;\n%!         1 1 0 1 0 0 1 1 0 0 0 0;\n%!         1 0 1 0 1 0 0 1 1 0 0 0;\n%!         1 0 0 1 0 1 0 0 1 1 0 0;\n%!         1 1 0 0 1 0 0 0 0 1 1 0;\n%!         0 1 1 0 0 0 0 1 0 0 1 1;\n%!         0 0 1 1 0 0 1 0 1 0 0 1;\n%!         0 0 0 1 1 0 0 1 0 1 0 1;\n%!         0 0 0 0 1 1 0 0 1 0 1 1;\n%!         0 1 0 0 0 1 1 0 0 1 0 1;\n%!         0 0 0 0 0 0 1 1 1 1 1 0 ];\n%! p = symrcm (adj);\n%! assert (p, [12 8 9 10 11 7 3 4 5 6 2 1]);\n%! assert (bandwidth (adj), 9);\n%! assert (bandwidth (adj(p, p)), 6);\n\n  handle zero-matrix properly:\n%!test <*64718>\n%! adj = false (5);\n%! p = symrcm (adj);\n%! assert (p, 1:5);\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/numeric/trexc.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lapack-proto.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (trexc, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{U}, @var{T}] =} trexc (@var{U}, @var{T}, @var{M})\nReorder the Schur factorization using @sc{LAPACK} function @code{ZTREXC}.\n\nGiven a unitary matrix @var{U} and an upper triangular Schur form @var{T}\nfrom the Schur decomposition @code{A = U*T*U'}, this function reorders\nthe diagonal elements of @var{T} according to the swap specifications\nin @var{M}.\n\nEach row of @var{M} contains two indices @code{[IFST, ILST]} specifying\nthat the diagonal element at position @code{IFST} should be moved to\nposition @code{ILST}.  The swaps are performed sequentially.\n\n@seealso{schur, ordschur}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  ComplexMatrix U = args(0).complex_matrix_value ();\n  ComplexMatrix T = args(1).complex_matrix_value ();\n  Matrix M = args(2).matrix_value ();\n\n  F77_INT n = octave::to_f77_int (T.rows ());\n\n  if (T.rows () != T.cols ())\n    error (\"trexc: T must be a square matrix\");\n\n  if (U.rows () != n || U.cols () != n)\n    error (\"trexc: U must have the same dimensions as T\");\n\n  if (M.cols () != 2)\n    error (\"trexc: M must have exactly 2 columns [IFST, ILST]\");\n\n  F77_INT ldt = n;\n  F77_INT ldq = n;\n  F77_INT info = 0;\n\n  // Process each swap specified in M\n  octave_idx_type n_swaps = M.rows ();\n\n  for (octave_idx_type k = 0; k < n_swaps; k++)\n    {\n      F77_INT ifst = octave::to_f77_int (static_cast<int> (M(k, 0)));\n      F77_INT ilst = octave::to_f77_int (static_cast<int> (M(k, 1)));\n\n      // Validate indices\n      if (ifst < 1 || ifst > n || ilst < 1 || ilst > n)\n        error (\"trexc: indices in M must be between 1 and %d\", n);\n\n      F77_XFCN (ztrexc, ZTREXC,\n                (F77_CONST_CHAR_ARG (\"V\"),\n                 n,\n                 F77_DBLE_CMPLX_ARG (T.fortran_vec ()),\n                 ldt,\n                 F77_DBLE_CMPLX_ARG (U.fortran_vec ()),\n                 ldq,\n                 ifst,\n                 ilst,\n                 info\n                 F77_CHAR_ARG_LEN (1)));\n\n      if (info != 0)\n        error (\"trexc: ZTREXC failed with info = %d\", info);\n    }\n\n  return ovl (U, T);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n/*\n%!test\n%! A = [1 2 3; 0 4 5; 0 0 6];\n%! [U, T] = schur (A, \"complex\");\n%! M = [1, 2];\n%! [U2, T2] = trexc (U, T, M);\n%! assert (U2 * T2 * U2', A, 4*eps);\n\n%!test\n%! v = randn (\"state\");\n%! randn (\"state\", 42);\n%! A = randn (4) + 1i * randn (4);\n%! randn (\"state\", v);\n%! [U, T] = schur (A, \"complex\");\n%! M = [1, 3; 2, 4];\n%! [U2, T2] = trexc (U, T, M);\n%! assert (norm (U2 * T2 * U2' - A, \"fro\"), 0, 65 * eps (norm (A, \"fro\")));\n\n%!error <must be a square matrix> trexc (eye (2), [1 2; 3 4; 5 6], [1 2])\n%!error <must have exactly 2 columns> trexc (eye (2), eye (2), [1 2 3])\n*/\n"
  },
  {
    "path": "libinterp/corefcn/numeric/tsearch.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ninline double\nmax (double a, double b, double c)\n{\n  return (a > b) ? (a > c ? a : c) : (b > c ? b : c);\n}\n\ninline double\nmin (double a, double b, double c)\n{\n  return (a < b) ? (a < c ? a : c) : (b < c ? b : c);\n}\n\n#define REF(x,k,i) x(static_cast<octave_idx_type> (elem((k), (i))) - 1)\n\n// The algorithm is O(M*N) for M points and N triangles.\n// Faster performance (closer to linear) happens if the points form a\n// contiguous path, such as a person on a walk recording their position every\n// few seconds and querying which map sector they are in.\n\nDEFUN (tsearch, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{idx} =} tsearch (@var{x}, @var{y}, @var{t}, @var{xi}, @var{yi})\nSearch for the enclosing Delaunay convex hull.\n\nFor @code{@var{t} = delaunay (@var{x}, @var{y})}, finds the index in @var{t}\ncontaining the points @code{(@var{xi}, @var{yi})}.  For points outside the\nconvex hull, @var{idx} is NaN.\n\nProgramming Note: The algorithm is @qcode{O}(@var{M}*@var{N}) for locating\n@var{M} points in @var{N} triangles.  Performance is typically much faster if\nthe points to be located are in a single continuous path; a point is first\nchecked against the region its predecessor was found in, speeding up lookups\nfor points along a continuous path.\n\n@seealso{delaunay, delaunayn}\n@end deftypefn */)\n{\n  if (args.length () != 5)\n    print_usage ();\n\n  const double eps = 1.0e-12;\n\n  const ColumnVector x (args(0).vector_value ());\n  const ColumnVector y (args(1).vector_value ());\n  const Matrix elem (args(2).matrix_value ());\n  const ColumnVector xi (args(3).vector_value ());\n  const ColumnVector yi (args(4).vector_value ());\n\n  const octave_idx_type nelem = elem.rows ();\n\n  ColumnVector minx (nelem);\n  ColumnVector maxx (nelem);\n  ColumnVector miny (nelem);\n  ColumnVector maxy (nelem);\n  for (octave_idx_type k = 0; k < nelem; k++)\n    {\n      minx(k) = min (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) - eps;\n      maxx(k) = max (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) + eps;\n      miny(k) = min (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) - eps;\n      maxy(k) = max (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) + eps;\n    }\n\n  const octave_idx_type np = xi.numel ();\n  ColumnVector values (np);\n\n  double x0 = 0.0, y0 = 0.0;\n  double a11 = 0.0, a12 = 0.0, a21 = 0.0, a22 = 0.0, det = 0.0;\n  double xt = 0.0, yt = 0.0;\n  double dx1 = 0.0, dx2 = 0.0, c1 = 0.0, c2 = 0.0;\n\n  octave_idx_type k = nelem;   // k is more than just an index variable.\n\n  for (octave_idx_type kp = 0; kp < np; kp++)   // for each point\n    {\n      xt = xi (kp);\n      yt = yi (kp);\n\n      // Check if point (xt,yt) is in the triangle that was last examined.\n      // This is for inputs where points are in contiguous order,\n      // like when the points are sampled from a continuous path.\n      if (k < nelem)  // This check will be false for the very first point.\n        {\n          // If we are here, then x0, y0, det all exist from before.\n          dx1 = xt - x0;\n          dx2 = yt - y0;\n          c1 = (a22 * dx1 - a21 * dx2) / det;\n          c2 = (-a12 * dx1 + a11 * dx2) / det;\n          if (c1 >= -eps && c2 >= -eps && (c1 + c2) <= 1 + eps)\n            {\n              values (kp) = k+1;\n              continue;\n            }\n        }\n\n      // The point is not in the same triangle, so go through all triangles.\n      for (k = 0; k < nelem; k++)\n        {\n          if (xt >= minx(k) && xt <= maxx(k) && yt >= miny(k) && yt <= maxy(k))\n            {\n              // Point is inside the triangle's bounding rectangle:\n              // See if it's inside the triangle itself.\n              x0  = REF (x, k, 0);\n              y0  = REF (y, k, 0);\n              a11 = REF (x, k, 1) - x0;\n              a12 = REF (y, k, 1) - y0;\n              a21 = REF (x, k, 2) - x0;\n              a22 = REF (y, k, 2) - y0;\n              det = a11 * a22 - a21 * a12;\n\n              // solve the system\n              dx1 = xt - x0;\n              dx2 = yt - y0;\n              c1 = (a22 * dx1 - a21 * dx2) / det;\n              c2 = (-a12 * dx1 + a11 * dx2) / det;\n              if (c1 >= -eps && c2 >= -eps && (c1 + c2) <= 1 + eps)\n                {\n                  values (kp) = k+1;\n                  break;\n                }\n            } //end see if it's inside the triangle itself\n        } //end for each triangle\n\n      if (k == nelem)\n        values (kp) = lo_ieee_nan_value ();\n\n    } //end for each point\n\n  return ovl (values);\n}\n\n/*\n%!shared x, y, tri\n%! x = [-1;-1;1];\n%! y = [-1;1;-1];\n%! tri = [1, 2, 3];\n%!assert (tsearch (x,y,tri,-1,-1), 1)\n%!assert (tsearch (x,y,tri, 1,-1), 1)\n%!assert (tsearch (x,y,tri,-1, 1), 1)\n%!assert (tsearch (x,y,tri,-1/3, -1/3), 1)\n%!assert (tsearch (x,y,tri, 1, 1), NaN)\n\n%!error tsearch ()\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-errno.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_errno_h)\n#define octave_oct_errno_h 1\n\n#include \"octave-config.h\"\n\n#include <cerrno>\n#include <map>\n#include <string>\n\n#include \"oct-map.h\"\n\nclass octave_errno\n{\nprotected:\n\n  octave_errno ();\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_errno)\n\n  ~octave_errno () = default;\n\n  static bool instance_ok ();\n\n  static void cleanup_instance ()\n  { delete s_instance; s_instance = nullptr; }\n\n  static int lookup (const std::string& name);\n\n  static octave_scalar_map list ();\n\n  static int get () { return errno; }\n\n  static int set (int val)\n  {\n    int retval = errno;\n    errno = val;\n    return retval;\n  }\n\nprivate:\n\n  int do_lookup (const std::string& name);\n\n  octave_scalar_map do_list ();\n\n  //--------\n\n  std::map<std::string, int> m_errno_tbl;\n\n  static octave_errno *s_instance;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-fstrm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n#include <cstring>\n\n#include \"error.h\"\n#include \"oct-fstrm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstream\nfstream::create (const std::string& nm_arg, std::ios::openmode arg_md,\n                 mach_info::float_format ff)\n{\n  return stream (new fstream (nm_arg, arg_md, ff));\n}\n\nfstream::fstream (const std::string& nm_arg, std::ios::openmode arg_md,\n                  mach_info::float_format ff)\n  : base_stream (arg_md, ff), m_name (nm_arg)\n{\n  m_fstream.open (m_name.c_str (), arg_md);\n\n  if (! m_fstream)\n    // Note: error is inherited from base_stream, not ::error.\n    error (std::strerror (errno));\n}\n\n// Position a stream at OFFSET relative to ORIGIN.\n\nint\nfstream::seek (off_t, int)\n{\n  // Note: error is inherited from base_stream, not ::error.\n  // This error function does not halt execution so \"return ...\" must exist.\n  error (\"fseek: invalid_operation\");\n  return -1;\n}\n\n// Return current stream position.\n\noff_t\nfstream::tell ()\n{\n  // Note: error is inherited from base_stream, not ::error.\n  // This error function does not halt execution so \"return ...\" must exist.\n  error (\"ftell: invalid_operation\");\n  return -1;\n}\n\n// Return nonzero if EOF has been reached on this stream.\n\nbool\nfstream::eof () const\n{\n  return m_fstream.eof ();\n}\n\nvoid\nfstream::do_close ()\n{\n  m_fstream.close ();\n}\n\nstd::istream *\nfstream::input_stream ()\n{\n  std::istream *retval = nullptr;\n\n  if (mode () & std::ios::in)\n    retval = &m_fstream;\n\n  return retval;\n}\n\nstd::ostream *\nfstream::output_stream ()\n{\n  std::ostream *retval = nullptr;\n\n  if (mode () & std::ios::out)\n    retval = &m_fstream;\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-fstrm.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_fstrm_h)\n#define octave_oct_fstrm_h 1\n\n#include \"octave-config.h\"\n\n#include <fstream>\n#include <string>\n\n#include \"oct-stream.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass fstream : public base_stream\n{\npublic:\n\n  fstream (const std::string& nm_arg,\n           std::ios::openmode arg_md = std::ios::in | std::ios::out,\n           mach_info::float_format flt_fmt = mach_info::native_float_format ());\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (fstream)\n\n  static stream\n  create (const std::string& nm_arg,\n          std::ios::openmode arg_md = std::ios::in | std::ios::out,\n          mach_info::float_format flt_fmt = mach_info::native_float_format ());\n\n  // Position a stream at OFFSET relative to ORIGIN.\n\n  int seek (off_t offset, int origin);\n\n  // Return current stream position.\n\n  off_t tell ();\n\n  // Return nonzero if EOF has been reached on this stream.\n\n  bool eof () const;\n\n  void do_close ();\n\n  // The name of the file.\n\n  std::string name () const { return m_name; }\n\n  std::istream * input_stream ();\n\n  std::ostream * output_stream ();\n\nprotected:\n\n  ~fstream () = default;\n\nprivate:\n\n  std::string m_name;\n\n  std::fstream m_fstream;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-handle.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_handle_h)\n#define octave_oct_handle_h 1\n\n#include \"octave-config.h\"\n\n#include \"dMatrix.h\"\n#include \"lo-ieee.h\"\n\n#include \"error.h\"\n#include \"ov.h\"\n\n// ---------------------------------------------------------------------\n\nclass octave_handle\n{\npublic:\n  octave_handle () : m_dval (octave::numeric_limits<double>::NaN ()) { }\n\n  octave_handle (const octave_value& a)\n    : m_dval (octave::numeric_limits<double>::NaN ())\n  {\n    if (a.isempty ())\n      ; // do nothing\n    else\n      {\n        try\n          {\n            m_dval = a.double_value ();\n          }\n        catch (octave::execution_exception& ee)\n          {\n            error (ee, \"invalid handle\");\n          }\n      }\n  }\n\n  octave_handle (int a) : m_dval (a) { }\n\n  octave_handle (double a) : m_dval (a) { }\n\n  octave_handle (const octave_handle& a) : m_dval (a.m_dval) { }\n\n  octave_handle& operator = (const octave_handle& a)\n  {\n    if (&a != this)\n      m_dval = a.m_dval;\n\n    return *this;\n  }\n\n  ~octave_handle () = default;\n\n  double value () const { return m_dval; }\n\n  octave_value as_octave_value () const\n  {\n    return ok () ? octave_value (m_dval) : octave_value (Matrix ());\n  }\n\n  // Prefix increment/decrement operators.\n  octave_handle& operator ++ ()\n  {\n    ++m_dval;\n    return *this;\n  }\n\n  octave_handle& operator -- ()\n  {\n    --m_dval;\n    return *this;\n  }\n\n  // Postfix increment/decrement operators.\n  const octave_handle operator ++ (int)\n  {\n    octave_handle old_value = *this;\n    ++(*this);\n    return old_value;\n  }\n\n  const octave_handle operator -- (int)\n  {\n    octave_handle old_value = *this;\n    --(*this);\n    return old_value;\n  }\n\n  bool ok () const { return ! octave::math::isnan (m_dval); }\n\nprivate:\n  double m_dval;\n};\n\ninline bool\noperator == (const octave_handle& a, const octave_handle& b)\n{\n  return a.value () == b.value ();\n}\n\ninline bool\noperator != (const octave_handle& a, const octave_handle& b)\n{\n  return a.value () != b.value ();\n}\n\ninline bool\noperator < (const octave_handle& a, const octave_handle& b)\n{\n  return a.value () < b.value ();\n}\n\ninline bool\noperator <= (const octave_handle& a, const octave_handle& b)\n{\n  return a.value () <= b.value ();\n}\n\ninline bool\noperator >= (const octave_handle& a, const octave_handle& b)\n{\n  return a.value () >= b.value ();\n}\n\ninline bool\noperator > (const octave_handle& a, const octave_handle& b)\n{\n  return a.value () > b.value ();\n}\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-hdf5-types.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-hdf5.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nbool\ncheck_hdf5_types (bool warn)\n{\n  static bool checked = false;\n  static bool ok = false;\n\n  if (! checked)\n    {\n#if defined (HAVE_HDF5)\n\n      ok = sizeof (octave_hdf5_id) >= sizeof (hid_t);\n\n      if (warn && ! ok)\n        warning_with_id\n        (\"Octave:internal\",\n         \"the size of octave_hdf5_id is smaller than the size of HDF5 hid_t\");\n\n      ok = sizeof (octave_hdf5_err) >= sizeof (herr_t);\n\n      if (warn && ! ok)\n        warning_with_id\n        (\"Octave:internal\",\n         \"the size of octave_hdf5_err is smaller than the size of HDF5 herr_t\");\n#else\n\n      octave_unused_parameter (warn);\n\n      warn_disabled_feature (\"check_hdf5_id_type\", \"HDF5\");\n\n#endif\n\n      checked = true;\n    }\n\n  return ok;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-hdf5-types.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_hdf5_types_h)\n#define octave_oct_hdf5_types_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\n\n// This function only needs to be defined for C++.\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern bool check_hdf5_types (bool warn = true);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n\n// Available for C and C++.\n\ntypedef int64_t octave_hdf5_id;\ntypedef int octave_hdf5_err;\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n// These are defined in a C file, so they should have C-linkage in\n// both C and C++ source files.\n\nextern const octave_hdf5_id octave_H5E_DEFAULT;\nextern const octave_hdf5_id octave_H5P_DEFAULT;\nextern const octave_hdf5_id octave_H5S_ALL;\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-hdf5.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_hdf5_h)\n#define octave_oct_hdf5_h 1\n\n#include \"octave-config.h\"\n\n#if defined (HAVE_HDF5)\n\n#  if defined (HAVE_HDF5_H)\n#    include <hdf5.h>\n#  endif\n\n#  include \"oct-hdf5-types.h\"\n\n#  if defined (OCTAVE_ENABLE_64)\n#    define H5T_NATIVE_IDX H5T_NATIVE_INT64\n#  else\n#    define H5T_NATIVE_IDX H5T_NATIVE_INT\n#  endif\n\n#endif\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-hist.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nThe functions listed below were adapted from similar functions from\nGNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991 Free\nSoftware Foundation, Inc.\n\n  do_history         edit_history_readline\n  do_edit_history    edit_history_add_hist\n\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n#include <cstring>\n\n#include <fstream>\n#include <string>\n\n#include \"cmd-hist.h\"\n#include \"file-ops.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-sysdep.h\"\n#include \"oct-time.h\"\n#include \"str-vec.h\"\n#include \"unistd-wrappers.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"event-manager.h\"\n#include \"input.h\"\n#include \"oct-hist.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"sighandlers.h\"\n#include \"sysdep.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Read the edited history lines from STREAM and return them\n// one at a time.  This can read unlimited length lines.  The\n// caller should free the storage.\n\nstatic char *\nedit_history_readline (std::fstream& stream)\n{\n  char c;\n  int line_len = 128;\n  int lindex = 0;\n  char *line = new char [line_len];\n  line[0] = '\\0';\n\n  while (stream.get (c))\n    {\n      if (lindex + 2 >= line_len)\n        {\n          char *tmp_line = new char [line_len += 128];\n          strcpy (tmp_line, line);\n          delete [] line;\n          line = tmp_line;\n        }\n\n      if (c == '\\n')\n        {\n          line[lindex++] = '\\n';\n          line[lindex++] = '\\0';\n          return line;\n        }\n      else\n        line[lindex++] = c;\n    }\n\n  if (! lindex)\n    {\n      delete [] line;\n      return nullptr;\n    }\n\n  if (lindex + 2 >= line_len)\n    {\n      char *tmp_line = new char [lindex+3];\n      strcpy (tmp_line, line);\n      delete [] line;\n      line = tmp_line;\n    }\n\n  // Finish with newline if none in file.\n\n  line[lindex++] = '\\n';\n  line[lindex++] = '\\0';\n  return line;\n}\n\nstatic void\nedit_history_add_hist (const std::string& line)\n{\n  if (! line.empty ())\n    {\n      std::string tmp = line;\n\n      int len = tmp.length ();\n\n      if (len > 0 && tmp[len-1] == '\\n')\n        tmp.resize (len - 1);\n\n      if (! tmp.empty ())\n        {\n          if (command_history::add (tmp))\n            {\n              event_manager& evmgr = __get_event_manager__ ();\n\n              evmgr.append_history (tmp);\n            }\n        }\n    }\n}\n\nstatic bool\nget_int_arg (const octave_value& arg, int& val)\n{\n  bool ok = true;\n\n  if (arg.is_string ())\n    {\n      std::string tmp = arg.string_value ();\n\n      ok = sscanf (tmp.c_str (), \"%d\", &val) == 1;\n    }\n  else if (arg.isnumeric ())\n    val = arg.int_value ();\n  else\n    ok = false;\n\n  return ok;\n}\n\nstatic std::string\nmk_tmp_hist_file (const octave_value_list& args,\n                  bool insert_curr, const char *warn_for)\n{\n  string_vector hlist = command_history::list ();\n\n  int hist_count = hlist.numel () - 1;  // switch to zero-based indexing\n\n  // The current command line is already part of the history list by\n  // the time we get to this point.  Delete the cmd from the list when\n  // executing 'edit_history' so that it doesn't show up in the history\n  // but the actual commands performed will.\n\n  if (! insert_curr)\n    command_history::remove (hist_count);\n\n  hist_count--;  // skip last entry in history list\n\n  // If no numbers have been specified, the default is to edit the\n  // last command in the history list.\n\n  int hist_beg = hist_count;\n  int hist_end = hist_count;\n\n  bool reverse = false;\n\n  // Process options.\n\n  int nargin = args.length ();\n\n  if (nargin == 2)\n    {\n      if (! get_int_arg (args(0), hist_beg)\n          || ! get_int_arg (args(1), hist_end))\n        error (\"%s: arguments must be integers\", warn_for);\n\n      if (hist_beg < 0)\n        hist_beg += (hist_count + 1);\n      else\n        hist_beg--;\n      if (hist_end < 0)\n        hist_end += (hist_count + 1);\n      else\n        hist_end--;\n    }\n  else if (nargin == 1)\n    {\n      if (! get_int_arg (args(0), hist_beg))\n        error (\"%s: argument must be an integer\", warn_for);\n\n      if (hist_beg < 0)\n        hist_beg += (hist_count + 1);\n      else\n        hist_beg--;\n\n      hist_end = hist_beg;\n    }\n\n  if (hist_beg > hist_count || hist_end > hist_count)\n    error (\"%s: history specification out of range\", warn_for);\n\n  if (hist_end < hist_beg)\n    {\n      std::swap (hist_end, hist_beg);\n      reverse = true;\n    }\n\n  std::string name = sys::tempnam (\"\", \"oct-\");\n\n  std::ofstream file = sys::ofstream (name.c_str (), std::ios::out);\n\n  if (! file)\n    error (\"%s: couldn't open temporary file '%s'\", warn_for,\n           name.c_str ());\n\n  if (reverse)\n    {\n      for (int i = hist_end; i >= hist_beg; i--)\n        file << hlist[i] << \"\\n\";\n    }\n  else\n    {\n      for (int i = hist_beg; i <= hist_end; i++)\n        file << hlist[i] << \"\\n\";\n    }\n\n  file.close ();\n\n  return name;\n}\n\nhistory_system::history_system (interpreter& interp)\n  : m_interpreter (interp), m_input_from_tmp_file (false),\n    m_timestamp_format_string (default_timestamp_format ())\n{ }\n\nvoid\nhistory_system::initialize (bool read_history_file)\n{\n  command_history::initialize (read_history_file, default_file (),\n                               default_size (),\n                               sys::env::getenv (\"OCTAVE_HISTCONTROL\"));\n\n  event_manager& evmgr = m_interpreter.get_event_manager ();\n\n  evmgr.set_history (command_history::list ());\n}\n\nvoid\nhistory_system::write_timestamp ()\n{\n  sys::localtime now;\n\n  std::string timestamp = now.strftime (m_timestamp_format_string);\n\n  if (! timestamp.empty ())\n    {\n      if (command_history::add (timestamp))\n        {\n          event_manager& evmgr = m_interpreter.get_event_manager ();\n\n          evmgr.append_history (timestamp);\n        }\n    }\n}\n\noctave_value\nhistory_system::input_from_tmp_file (const octave_value_list& args,\n                                     int nargout)\n{\n  return set_internal_variable (m_input_from_tmp_file, args, nargout,\n                                \"input_from_tmp_file\");\n}\n\noctave_value\nhistory_system::timestamp_format_string (const octave_value_list& args,\n                                         int nargout)\n{\n  return set_internal_variable (m_timestamp_format_string, args, nargout,\n                                \"timestamp_format_string\");\n}\n\n// Display, save, or load history.  Stolen and modified from bash.\n//\n// Arg of -w FILENAME means write file, arg of -r FILENAME\n// means read file, arg of -q means don't number lines.  Arg of N\n// means only display that many items.\n\nstring_vector\nhistory_system::do_history (const octave_value_list& args,\n                            int nargout)\n{\n  bool numbered_output = nargout == 0;\n\n  unwind_action restore_history_filename\n  ([] (const std::string& old_filename)\n  {\n    command_history::set_file (old_filename);\n  }, command_history::file ());\n\n  string_vector hlist;\n\n  int nargin = args.length ();\n\n  // Number of history lines to show (-1 = all)\n  int limit = -1;\n\n  for (octave_idx_type i = 0; i < nargin; i++)\n    {\n      octave_value arg = args(i);\n\n      std::string option;\n\n      if (arg.is_string ())\n        option = arg.string_value ();\n      else if (arg.isnumeric ())\n        {\n          limit = arg.int_value ();\n          if (limit < 0)\n            limit = -limit;\n          continue;\n        }\n      else\n        err_wrong_type_arg (\"history\", arg);\n\n      event_manager& evmgr = m_interpreter.get_event_manager ();\n\n      if (option == \"-r\" || option == \"-w\" || option == \"-a\"\n          || option == \"-n\")\n        {\n          if (i < nargin - 1)\n            {\n              std::string fname\n                = args(++i).xstring_value (\"history: filename must be a string for %s option\",\n                                           option.c_str ());\n\n              command_history::set_file (fname);\n            }\n          else\n            command_history::set_file (default_file ());\n\n          if (option == \"-a\")\n            // Append 'new' lines to file.\n            command_history::append ();\n\n          else if (option == \"-w\")\n            // Write entire history.\n            command_history::write ();\n\n          else if (option == \"-r\")\n            {\n              // Read entire file.\n              command_history::read ();\n              evmgr.set_history (command_history::list ());\n            }\n\n          else if (option == \"-n\")\n            {\n              // Read 'new' history from file.\n              command_history::read_range ();\n              evmgr.set_history (command_history::list ());\n            }\n\n          else\n            error (\"history: invalid option '%s' - please report this bug\", option.c_str ());\n\n          return hlist;\n        }\n      else if (option == \"-c\")\n        {\n          command_history::clear ();\n          evmgr.clear_history ();\n        }\n      else if (option == \"-q\")\n        numbered_output = false;\n      else if (option == \"--\")\n        {\n          i++;\n          break;\n        }\n      else\n        {\n          // The last argument found in the command list that looks like\n          // an integer will be used\n          int tmp;\n\n          if (sscanf (option.c_str (), \"%d\", &tmp) == 1)\n            {\n              if (tmp > 0)\n                limit = tmp;\n              else\n                limit = -tmp;\n            }\n\n          else\n            {\n              if (option.length () > 0 && option[0] == '-')\n                error (\"history: unrecognized option '%s'\", option.c_str ());\n              else\n                error (\"history: bad non-numeric arg '%s'\", option.c_str ());\n            }\n        }\n    }\n\n  hlist = command_history::list (limit, numbered_output);\n\n  int len = hlist.numel ();\n\n  if (nargout == 0)\n    {\n      for (octave_idx_type i = 0; i < len; i++)\n        octave_stdout << hlist[i] << \"\\n\";\n    }\n\n  return hlist;\n}\n\nvoid\nhistory_system::do_edit_history (const octave_value_list& args)\n{\n  std::string name = mk_tmp_hist_file (args, false, \"edit_history\");\n\n  if (name.empty ())\n    return;\n\n  // Call up our favorite editor on the file of commands.\n\n  environment& env = m_interpreter.get_environment ();\n  std::string cmd = env.editor ();\n  cmd.append (R\"( \")\" + name + '\"');\n\n  // Ignore interrupts while we are off editing commands.  Should we\n  // maybe avoid using system()?\n\n  interrupt_handler old_interrupt_handler = ignore_interrupts ();\n\n  int status = sys::system (cmd);\n\n  set_interrupt_handler (old_interrupt_handler);\n\n  // Check if text edition was successful.  Abort the operation\n  // in case of failure.\n  if (status != EXIT_SUCCESS)\n    error (\"edit_history: text editor command failed\");\n\n  // Write the commands to the history file since source_file\n  // disables command line history while it executes.\n\n  std::fstream file = sys::fstream (name.c_str (), std::ios::in);\n\n  char *line;\n  //int first = 1;\n  while ((line = edit_history_readline (file)) != nullptr)\n    {\n      // Skip blank lines.\n\n      if (line[0] == '\\n')\n        {\n          delete [] line;\n          continue;\n        }\n\n      edit_history_add_hist (line);\n\n      delete [] line;\n    }\n\n  file.close ();\n\n  int(*unlink_fptr)(const std::string&) = sys::unlink;\n  unwind_action unlink_action (unlink_fptr, name);\n  unwind_protect_var<bool> upv (m_input_from_tmp_file, true);\n\n  // FIXME: instead of sourcing a file, we should just iterate through\n  // the list of commands, parsing and executing them one at a time as\n  // if they were entered interactively.\n\n  source_file (name);\n}\n\nvoid\nhistory_system::do_run_history (const octave_value_list& args)\n{\n  std::string name = mk_tmp_hist_file (args, false, \"run_history\");\n\n  if (name.empty ())\n    return;\n\n  int(*unlink_fptr)(const std::string&) = sys::unlink;\n  unwind_action unlink_action (unlink_fptr, name);\n  unwind_protect_var<bool> upv (m_input_from_tmp_file, true);\n\n  // FIXME: instead of sourcing a file, we should just iterate through\n  // the list of commands, parsing and executing them one at a time as\n  // if they were entered interactively.\n\n  source_file (name);\n}\n\nstd::string\nhistory_system::default_file ()\n{\n  std::string file;\n\n  std::string env_file = sys::env::getenv (\"OCTAVE_HISTFILE\");\n\n  if (! env_file.empty ())\n    file = env_file;\n\n  if (file.empty ())\n    {\n      // Default to $DATA/octave/history, where $DATA is the platform-\n      // dependent location for (roaming) user data files.\n\n      std::string user_data_dir = sys::env::get_user_data_directory ();\n\n      std::string hist_dir = user_data_dir + sys::file_ops::dir_sep_str ()\n                             + \"octave\";\n\n      file = sys::env::make_absolute (\"history\", hist_dir);\n    }\n\n\n  return file;\n}\n\nint\nhistory_system::default_size ()\n{\n  int size = 1000;\n\n  std::string env_size = sys::env::getenv (\"OCTAVE_HISTSIZE\");\n\n  if (! env_size.empty ())\n    {\n      int val;\n\n      if (sscanf (env_size.c_str (), \"%d\", &val) == 1)\n        size = (val > 0 ? val : 0);\n    }\n\n  return size;\n}\n\nstd::string\nhistory_system::default_timestamp_format ()\n{\n  return \"# Octave \" OCTAVE_VERSION \", %a %b %d %H:%M:%S %Y %Z\";\n}\n\nDEFMETHOD (edit_history, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} edit_history\n@deftypefnx {} {} edit_history @var{cmd_number}\n@deftypefnx {} {} edit_history @var{first} @var{last}\nEdit the history list using the editor named by the variable @env{EDITOR}.\n\nThe commands to be edited are first copied to a temporary file.  When you\nexit the editor, Octave executes the commands that remain in the file.  It\nis often more convenient to use @code{edit_history} to define functions\nrather than attempting to enter them directly on the command line.\nThe block of commands is executed as soon as you exit the editor.\nTo avoid executing any commands, simply delete all the lines from the buffer\nbefore leaving the editor.\n\nWhen invoked with no arguments, edit the previously executed command;\nWith one argument, edit the specified command @var{cmd_number};\nWith two arguments, edit the list of commands between @var{first} and\n@var{last}.  Command number specifiers may also be negative where -1\nrefers to the most recently executed command.\nThe following are equivalent and edit the most recently executed command.\n\n@example\n@group\nedit_history\nedit_history -1\n@end group\n@end example\n\nWhen using ranges, specifying a larger number for the first command than the\nlast command reverses the list of commands before they are placed in the\nbuffer to be edited.\n@seealso{run_history, history}\n@end deftypefn */)\n{\n  // FIXME: should this be limited to the top-level context?\n  if (args.length () > 2)\n    print_usage ();\n\n  history_system& history_sys = interp.get_history_system ();\n\n  history_sys.do_edit_history (args);\n\n  return ovl ();\n}\n\nDEFMETHOD (history, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} history\n@deftypefnx {} {} history @var{opt1} @dots{}\n@deftypefnx {} {@var{H} =} history ()\n@deftypefnx {} {@var{H} =} history (@var{opt1}, @dots{})\nIf invoked with no arguments, @code{history} displays a list of commands that\nyou have executed.\n\nValid options are:\n\n@table @code\n@item   @var{n}\n@itemx -@var{n}\nDisplay only the most recent @var{n} lines of history.\n\n@item -c\nClear the history list.\n\n@item -q\nDon't number the displayed lines of history.  This is useful for cutting and\npasting commands using the X Window System.\n\n@item -r @var{file}\nRead the file @var{file}, appending its contents to the current history list.\nIf the name is omitted, use the default history file\n(@pxref{XREFhistory_file,,@code{history_file}}).\n\n@item -w @var{file}\nWrite the current history to the file @var{file}.  If the name is omitted, use\nthe default history file (@pxref{XREFhistory_file,,@code{history_file}}).\n@end table\n\nFor example, to display the five most recent commands that you have typed\nwithout displaying line numbers, use the command @kbd{history -q 5}.\n\nIf invoked with a single output argument, the history will be saved to that\nargument as a cell string and will not be output to screen.\n@seealso{edit_history, run_history, history_file, history_save}\n@end deftypefn */)\n{\n  // FIXME: should this be limited to the top-level context?\n\n  history_system& history_sys = interp.get_history_system ();\n\n  // Call do_history even if nargout is zero to display history list.\n\n  string_vector hlist = history_sys.do_history (args, nargout);\n\n  return nargout > 0 ? ovl (Cell (hlist)) : ovl ();\n}\n\nDEFMETHOD (run_history, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} run_history\n@deftypefnx {} {} run_history @var{cmd_number}\n@deftypefnx {} {} run_history @var{first} @var{last}\nRun commands from the history list.\n\nWhen invoked with no arguments, run the previously executed command;\n\nWith one argument, run the specified command @var{cmd_number};\n\nWith two arguments, run the list of commands between @var{first} and\n@var{last}.  Command number specifiers may also be negative where -1\nrefers to the most recently executed command.  For example, the command\n\n@example\n@group\nrun_history\n     OR\nrun_history -1\n@end group\n@end example\n\n@noindent\nexecutes the most recent command again.\nThe command\n\n@example\nrun_history 13 169\n@end example\n\n@noindent\nexecutes commands 13 through 169.\n\nSpecifying a larger number for the first command than the last command\nreverses the list of commands before executing them.\nFor example:\n\n@example\n@group\ndisp (1)\ndisp (2)\nrun_history -1 -2\n@xresult{}\n 2\n 1\n@end group\n@end example\n\n@seealso{edit_history, history}\n@end deftypefn */)\n{\n  // FIXME: should this be limited to the top-level context?\n\n  history_system& history_sys = interp.get_history_system ();\n\n  if (args.length () > 2)\n    print_usage ();\n\n  history_sys.do_run_history (args);\n\n  return ovl ();\n}\n\nDEFUN (history_control, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} history_control ()\n@deftypefnx {} {@var{old_val} =} history_control (@var{new_val})\nQuery or set the internal variable that specifies how commands are saved\nto the history list.\n\nThe default value is an empty character string, but may be overridden by the\nenvironment variable @w{@env{OCTAVE_HISTCONTROL}}.\n\nThe value of @code{history_control} is a colon-separated list of values\ncontrolling how commands are saved on the history list.  If the list\nof values includes @code{ignorespace}, lines which begin with a space\ncharacter are not saved in the history list.  A value of @code{ignoredups}\ncauses lines matching the previous history entry to not be saved.\nA value of @code{ignoreboth} is shorthand for @code{ignorespace} and\n@code{ignoredups}.  A value of @code{erasedups} causes all previous lines\nmatching the current line to be removed from the history list before that\nline is saved.  Any value not in the above list is ignored.  If\n@code{history_control} is the empty string, all commands are saved on\nthe history list, subject to the value of @code{history_save}.\n@seealso{history_file, history_size, history_timestamp_format_string,\nhistory_save}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  std::string old_history_control = command_history::histcontrol ();\n\n  std::string tmp = old_history_control;\n\n  retval = set_internal_variable (tmp, args, nargout, \"history_control\");\n\n  if (tmp != old_history_control)\n    command_history::process_histcontrol (tmp);\n\n  return retval;\n}\n\nDEFUN (history_size, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} history_size ()\n@deftypefnx {} {@var{old_val} =} history_size (@var{new_val})\nQuery or set the internal variable that specifies how many entries\nto store in the history file.\n\nThe default value is @code{1000}, but may be overridden by the environment\nvariable @w{@env{OCTAVE_HISTSIZE}}.\n@seealso{history_file, history_timestamp_format_string, history_save}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  int old_history_size = command_history::size ();\n\n  int tmp = old_history_size;\n\n  retval = set_internal_variable (tmp, args, nargout,\n                                  \"history_size\", -1,\n                                  std::numeric_limits<int>::max ());\n\n  if (tmp != old_history_size)\n    command_history::set_size (tmp);\n\n  return retval;\n}\n\nDEFUN (history_file, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} history_file ()\n@deftypefnx {} {@var{old_val} =} history_file (@var{new_val})\nQuery or set the internal variable that specifies the name of the file used to\nstore command history.\n\nAll future commands issued during the current Octave session will be written to\nthis new file (if the current setting of @code{history_save} allows for this).\n\nThe default value is @file{@w{@env{$DATA}}/octave/history}, where\n@w{@env{$DATA}}@ is the platform-specific location for (roaming) user data files\n(e.g., @w{@env{$XDG_DATA_HOME}}@ or, if that is not set, @file{~/.local/share}\non Unix-like operating systems or @w{@env{%APPDATA%}}@ on Windows).  The\ndefault value may be overridden by the environment variable\n@w{@env{OCTAVE_HISTFILE}}.\n\nProgramming Notes:\n\nIf you want to permanently change the location of Octave's history file you\nneed to issue the @code{history_file} command in every new Octave session.\nThis can be achieved by using Octave's @file{.octaverc} startup file.\n\nIf you also want to read the saved history commands of past Octave sessions\nfrom this different history file, then you need to use the additional command\n@code{history -r} after setting the new value of the history file.  Example\ncode in Octave's startup file to do this might look like this:\n\n@example\n@group\nhistory_file (\"~/new/.octave_hist\");\nif (exist (history_file ()))\n  history (\"-r\", history_file());\nendif\n@end group\n@end example\n\n@seealso{history, history_control, history_save, history_size,\nhistory_timestamp_format_string}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  std::string old_history_file = command_history::file ();\n\n  std::string tmp = old_history_file;\n\n  retval = set_internal_variable (tmp, args, nargout, \"history_file\");\n\n  if (tmp != old_history_file)\n    command_history::set_file (tmp);\n\n  return retval;\n}\n\nDEFMETHOD (history_timestamp_format_string, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} history_timestamp_format_string ()\n@deftypefnx {} {@var{old_val} =} history_timestamp_format_string (@var{new_val})\n@deftypefnx {} {@var{old_val} =} history_timestamp_format_string (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the format string\nfor the comment line that is written to the history file when Octave\nexits.\n\nThe format string is passed to @code{strftime}.  The default value is\n\n@example\n\"# Octave VERSION, %a %b %d %H:%M:%S %Y %Z\"\n@end example\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{strftime, history_file, history_size, history_save}\n@end deftypefn */)\n{\n  history_system& history_sys = interp.get_history_system ();\n\n  return history_sys.timestamp_format_string (args, nargout);\n}\n\n/*\n%!test\n%! history_timestamp_format_string (\"# Example history marker\", \"local\");\n%! assert (history_timestamp_format_string (), \"# Example history marker\");\n%!test <*57843>\n%! history_timestamp_format_string (\"\", \"local\");\n%! assert (history_timestamp_format_string (), \"\");\n*/\n\nDEFUN (history_save, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} history_save ()\n@deftypefnx {} {@var{old_val} =} history_save (@var{new_val})\n@deftypefnx {} {@var{old_val} =} history_save (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether commands entered\non the command line are saved in the history file.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{history_control, history_file, history_size,\nhistory_timestamp_format_string}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  bool old_history_save = ! command_history::ignoring_entries ();\n\n  bool tmp = old_history_save;\n\n  retval = set_internal_variable (tmp, args, nargout, \"history_save\");\n\n  if (tmp != old_history_save)\n    command_history::ignore_entries (! tmp);\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-hist.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_hist_h)\n#define octave_oct_hist_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"cmd-hist.h\"\n\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass OCTINTERP_API history_system\n{\npublic:\n\n  history_system (interpreter& interp);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (history_system)\n\n  ~history_system () = default;\n\n  void initialize (bool read_history_file = false);\n\n  void write_timestamp ();\n\n  octave_value input_from_tmp_file (const octave_value_list& args,\n                                    int nargout);\n\n  bool input_from_tmp_file () const\n  {\n    return m_input_from_tmp_file;\n  }\n\n  bool input_from_tmp_file (bool flag)\n  {\n    return set (m_input_from_tmp_file, flag);\n  }\n\n  octave_value timestamp_format_string (const octave_value_list& args,\n                                        int nargout);\n\n  std::string timestamp_format_string () const\n  {\n    return m_timestamp_format_string;\n  }\n\n  std::string timestamp_format_string (const std::string& file)\n  {\n    return set (m_timestamp_format_string, file);\n  }\n\n  string_vector\n  do_history (const octave_value_list& args = octave_value_list (),\n              int nargout = 0);\n\n  void do_edit_history (const octave_value_list& args = octave_value_list ());\n\n  void do_run_history (const octave_value_list& args = octave_value_list ());\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  // TRUE means input is coming from temporary history file.\n  bool m_input_from_tmp_file;\n\n  // The format of the timestamp marker written to the history file when\n  // Octave exits.\n  std::string m_timestamp_format_string;\n\n  static std::string default_file ();\n\n  static int default_size ();\n\n  static std::string default_timestamp_format ();\n\n  template <typename T>\n  T set (T& var, const T& new_val)\n  {\n    T old_val = var;\n    var = new_val;\n    return old_val;\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-iostrm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"error.h\"\n#include \"oct-iostrm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Position a stream at OFFSET relative to ORIGIN.\n\nint\nbase_iostream::seek (off_t, int)\n{\n  invalid_operation ();\n  return -1;\n}\n\n// Return current stream position.\n\noff_t\nbase_iostream::tell ()\n{\n  invalid_operation ();\n  return -1;\n}\n\n// Return nonzero if EOF has been reached on this stream.\n\nbool\nbase_iostream::eof () const\n{\n  invalid_operation ();\n  return false;\n}\n\nvoid\nbase_iostream::invalid_operation () const\n{\n  // Note: use ::error to get error from error.h which halts operation.\n  ::error (\"%s: invalid operation\", stream_type ());\n}\n\n// Return nonzero if EOF has been reached on this stream.\n\nbool\nistream::eof () const\n{\n  return m_istream && m_istream->eof ();\n}\n\noctave::stream\nistream::create (std::istream *arg, const std::string& n)\n{\n  return octave::stream (new istream (arg, n));\n}\n\n// Return nonzero if EOF has been reached on this stream.\n\nbool\nostream::eof () const\n{\n  return m_ostream && m_ostream->eof ();\n}\n\noctave::stream\nostream::create (std::ostream *arg, const std::string& n)\n{\n  return octave::stream (new ostream (arg, n));\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-iostrm.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_iostrm_h)\n#define octave_oct_iostrm_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n#include \"oct-stream.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_iostream : public base_stream\n{\npublic:\n\n  base_iostream (const std::string& n = \"\",\n                 std::ios::openmode m = std::ios::in | std::ios::out,\n                 mach_info::float_format ff = mach_info::native_float_format ())\n    : base_stream (m, ff), m_name (n) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (base_iostream)\n\nprotected:\n\n  ~base_iostream () = default;\n\npublic:\n\n  // Position a stream at OFFSET relative to ORIGIN.\n\n  int seek (off_t offset, int origin);\n\n  // Return current stream position.\n\n  off_t tell ();\n\n  // Return nonzero if EOF has been reached on this stream.\n\n  bool eof () const;\n\n  // The name of the file.\n\n  std::string name () const { return m_name; }\n\nprotected:\n\n  void invalid_operation () const;\n\nprivate:\n\n  std::string m_name;\n\n  virtual const char * stream_type () const = 0;\n};\n\nclass istream : public base_iostream\n{\npublic:\n\n  istream (std::istream *arg = nullptr, const std::string& n = \"\")\n    : base_iostream (n, std::ios::in, mach_info::native_float_format ()),\n      m_istream (arg)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (istream)\n\n  static stream\n  create (std::istream *arg = nullptr, const std::string& n = \"\");\n\n  // Return nonzero if EOF has been reached on this stream.\n\n  bool eof () const;\n\n  std::istream * input_stream () { return m_istream; }\n\n  std::ostream * output_stream () { return nullptr; }\n\nprotected:\n\n  ~istream () = default;\n\nprivate:\n\n  std::istream *m_istream;\n\n  const char * stream_type () const { return \"istream\"; }\n};\n\nclass ostream : public base_iostream\n{\npublic:\n\n  ostream (std::ostream *arg, const std::string& n = \"\")\n    : base_iostream (n, std::ios::out, mach_info::native_float_format ()),\n      m_ostream (arg)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (ostream)\n\n  static stream\n  create (std::ostream *arg, const std::string& n = \"\");\n\n  // Return nonzero if EOF has been reached on this stream.\n\n  bool eof () const;\n\n  std::istream * input_stream () { return nullptr; }\n\n  std::ostream * output_stream () { return m_ostream; }\n\nprotected:\n\n  ~ostream () = default;\n\nprivate:\n\n  std::ostream *m_ostream;\n\n  const char * stream_type () const { return \"ostream\"; }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-map.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-util.h\"\n#include \"error.h\"\n#include \"oct-locbuf.h\"\n#include \"str-vec.h\"\n\n#include \"oct-map.h\"\n#include \"utils.h\"\n\noctave_fields::fields_rep *\noctave_fields::nil_rep ()\n{\n  static fields_rep nr;\n  return &nr;\n}\n\noctave_fields::octave_fields (const string_vector& fields)\n  : m_rep (new fields_rep)\n{\n  octave_idx_type n = fields.numel ();\n  for (octave_idx_type i = 0; i < n; i++)\n    (*m_rep)[fields(i)] = i;\n}\n\noctave_fields::octave_fields (const char *const *fields)\n  : m_rep (new fields_rep)\n{\n  octave_idx_type n = 0;\n  while (*fields)\n    (*m_rep)[std::string (*fields++)] = n++;\n}\n\nbool\noctave_fields::isfield (const std::string& field) const\n{\n  return m_rep->find (field) != m_rep->end ();\n}\n\noctave_idx_type\noctave_fields::getfield (const std::string& field) const\n{\n  auto p = m_rep->find (field);\n  return (p != m_rep->end ()) ? p->second : -1;\n}\n\noctave_idx_type\noctave_fields::getfield (const std::string& field)\n{\n  auto p = m_rep->find (field);\n  if (p != m_rep->end ())\n    return p->second;\n  else\n    {\n      make_unique ();\n      octave_idx_type n = m_rep->size ();\n      return (*m_rep)[field] = n;\n    }\n}\n\noctave_idx_type\noctave_fields::rmfield (const std::string& field)\n{\n  auto p = m_rep->find (field);\n  if (p == m_rep->end ())\n    return -1;\n  else\n    {\n      octave_idx_type n = p->second;\n      make_unique ();\n      m_rep->erase (field);\n      for (auto& fld_idx : *m_rep)\n        {\n          if (fld_idx.second >= n)\n            fld_idx.second--;\n        }\n\n      return n;\n    }\n}\n\nvoid\noctave_fields::orderfields (Array<octave_idx_type>& perm)\n{\n  octave_idx_type n = m_rep->size ();\n  perm.clear (n, 1);\n\n  make_unique ();\n  octave_idx_type i = 0;\n  for (auto& fld_idx : *m_rep)\n    {\n      octave_idx_type j = fld_idx.second;\n      fld_idx.second = i;\n      perm(i++) = j;\n    }\n}\n\nbool\noctave_fields::equal_up_to_order (const octave_fields& other,\n                                  octave_idx_type *perm) const\n{\n  bool retval;\n\n  auto p = begin ();\n  auto q = other.begin ();\n  for (; p != end () && q != other.end (); p++, q++)\n    {\n      if (p->first == q->first)\n        perm[p->second] = q->second;\n      else\n        return false;\n    }\n\n  retval = (p == end () && q == other.end ());\n\n  return retval;\n}\n\nbool\noctave_fields::equal_up_to_order (const octave_fields& other,\n                                  Array<octave_idx_type>& perm) const\n{\n  octave_idx_type n = nfields ();\n  if (perm.numel () != n)\n    perm.clear (1, n);\n\n  return equal_up_to_order (other, perm.rwdata ());\n}\n\nstring_vector\noctave_fields::fieldnames () const\n{\n  octave_idx_type n = nfields ();\n  string_vector retval(n);\n\n  for (auto& fld_idx : *this)\n    retval.xelem (fld_idx.second) = fld_idx.first;\n\n  return retval;\n}\n\noctave_scalar_map::octave_scalar_map\n(const std::map<std::string, octave_value>& m)\n{\n  std::size_t sz = m.size ();\n  m_vals.resize (sz);\n  std::size_t i = 0;\n  for (const auto& k_v : m)\n    {\n      m_keys.getfield (k_v.first);\n      m_vals[i++] = k_v.second;\n    }\n}\n\noctave_value\noctave_scalar_map::getfield (const std::string& k) const\n{\n  octave_idx_type idx = m_keys.getfield (k);\n  return (idx >= 0) ? m_vals[idx] : octave_value ();\n}\n\nvoid\noctave_scalar_map::setfield (const std::string& k, const octave_value& val)\n{\n  octave_idx_type idx = m_keys.getfield (k);\n  if (idx < static_cast<octave_idx_type> (m_vals.size ()))\n    m_vals[idx] = val;\n  else\n    m_vals.push_back (val);\n}\n\nvoid\noctave_scalar_map::rmfield (const std::string& k)\n{\n  octave_idx_type idx = m_keys.rmfield (k);\n  if (idx >= 0)\n    m_vals.erase (m_vals.begin () + idx);\n}\n\noctave_scalar_map\noctave_scalar_map::orderfields () const\n{\n  Array<octave_idx_type> perm;\n  return orderfields (perm);\n}\n\noctave_scalar_map\noctave_scalar_map::orderfields (Array<octave_idx_type>& perm) const\n{\n  octave_scalar_map retval (m_keys);\n  retval.m_keys.orderfields (perm);\n\n  octave_idx_type nf = nfields ();\n  for (octave_idx_type i = 0; i < nf; i++)\n    retval.m_vals[i] = m_vals[perm.xelem (i)];\n\n  return retval;\n}\n\noctave_scalar_map\noctave_scalar_map::orderfields (const octave_scalar_map& other,\n                                Array<octave_idx_type>& perm) const\n{\n  if (m_keys.is_same (other.m_keys))\n    return *this;\n  else\n    {\n      octave_scalar_map retval (other.m_keys);\n      if (! other.m_keys.equal_up_to_order (m_keys, perm))\n        error (\"orderfields: structs must have same fields up to order\");\n\n      octave_idx_type nf = nfields ();\n      for (octave_idx_type i = 0; i < nf; i++)\n        retval.m_vals[i] = m_vals[perm.xelem (i)];\n\n      return retval;\n    }\n}\n\noctave_value\noctave_scalar_map::contents (const std::string& k) const\n{\n  return getfield (k);\n}\n\noctave_value&\noctave_scalar_map::contents (const std::string& k)\n{\n  octave_idx_type idx = m_keys.getfield (k);\n  if (idx >= static_cast<octave_idx_type> (m_vals.size ()))\n    m_vals.resize (idx+1);\n  return m_vals[idx];\n}\n\nstd::size_t\noctave_scalar_map::byte_size () const\n{\n  std::size_t retval = 0;\n\n  for (octave_idx_type i = 0; i < nfields (); i++)\n    retval += m_vals[i].byte_size ();\n\n  return retval;\n}\n\noctave_map::octave_map (const octave_scalar_map& m)\n  : m_keys (m.m_keys), m_vals (), m_dimensions (1, 1)\n{\n  octave_idx_type nf = m.nfields ();\n  m_vals.reserve (nf);\n  for (octave_idx_type i = 0; i < nf; i++)\n    {\n      m_vals.push_back (Cell (m_dimensions));\n      m_vals[i].xelem (0) = m.m_vals[i];\n    }\n}\n\nCell\noctave_map::getfield (const std::string& k) const\n{\n  octave_idx_type idx = m_keys.getfield (k);\n  return (idx >= 0) ? m_vals[idx] : Cell ();\n}\n\nvoid\noctave_map::setfield (const std::string& k, const Cell& val)\n{\n  if (nfields () == 0)\n    m_dimensions = val.dims ();\n\n  if (val.dims () != m_dimensions)\n    error (\"octave_map::setfield: internal error\");\n\n  octave_idx_type idx = m_keys.getfield (k);\n  if (idx < static_cast<octave_idx_type> (m_vals.size ()))\n    m_vals[idx] = val;\n  else\n    m_vals.push_back (val);\n}\n\nvoid\noctave_map::rmfield (const std::string& k)\n{\n  octave_idx_type idx = m_keys.rmfield (k);\n  if (idx >= 0)\n    m_vals.erase (m_vals.begin () + idx);\n}\n\noctave_map\noctave_map::orderfields () const\n{\n  Array<octave_idx_type> perm;\n  return orderfields (perm);\n}\n\noctave_map\noctave_map::orderfields (Array<octave_idx_type>& perm) const\n{\n  octave_map retval (m_keys);\n  retval.m_keys.orderfields (perm);\n\n  octave_idx_type nf = nfields ();\n  for (octave_idx_type i = 0; i < nf; i++)\n    retval.m_vals[i] = m_vals[perm.xelem (i)];\n\n  return retval;\n}\n\noctave_map\noctave_map::orderfields (const octave_map& other,\n                         Array<octave_idx_type>& perm) const\n{\n  if (m_keys.is_same (other.m_keys))\n    return *this;\n  else\n    {\n      octave_map retval (other.m_keys);\n      if (! other.m_keys.equal_up_to_order (m_keys, perm))\n        error (\"orderfields: structs must have same fields up to order\");\n\n      octave_idx_type nf = nfields ();\n      for (octave_idx_type i = 0; i < nf; i++)\n        retval.m_vals[i] = m_vals[perm.xelem (i)];\n\n      return retval;\n    }\n}\n\nCell\noctave_map::contents (const std::string& k) const\n{\n  return getfield (k);\n}\n\nCell&\noctave_map::contents (const std::string& k)\n{\n  octave_idx_type idx = m_keys.getfield (k);\n  if (idx >= static_cast<octave_idx_type> (m_vals.size ()))\n    m_vals.push_back (Cell (m_dimensions)); // auto-set correct dims.\n  return m_vals[idx];\n}\n\nstd::size_t\noctave_map::byte_size () const\n{\n  std::size_t retval = 0;\n\n  for (auto p = cbegin (); p != cend (); p++)\n    retval += octave_value (contents (key (p))).byte_size ();\n\n  return retval;\n}\n\nvoid\noctave_map::extract_scalar (octave_scalar_map& dest,\n                            octave_idx_type idx) const\n{\n  octave_idx_type nf = nfields ();\n  for (octave_idx_type i = 0; i < nf; i++)\n    dest.m_vals[i] = m_vals[i](idx);\n}\n\noctave_scalar_map\noctave_map::elem (octave_idx_type n) const\n{\n  octave_scalar_map retval (m_keys);\n\n  // Optimize this so that there is just one check.\n  extract_scalar (retval, compute_index (n, m_dimensions));\n\n  return retval;\n}\n\noctave_scalar_map\noctave_map::elem (octave_idx_type i, octave_idx_type j) const\n{\n  octave_scalar_map retval (m_keys);\n\n  // Optimize this so that there is just one check.\n  extract_scalar (retval, compute_index (i, j, m_dimensions));\n\n  return retval;\n}\n\noctave_scalar_map\noctave_map::elem (const Array<octave_idx_type>& ra_idx) const\n{\n  octave_scalar_map retval (m_keys);\n\n  // Optimize this so that there is just one check.\n  extract_scalar (retval, compute_index (ra_idx, m_dimensions));\n\n  return retval;\n}\n\noctave_scalar_map\noctave_map::fast_elem_extract (octave_idx_type n) const\n{\n  octave_scalar_map retval (m_keys);\n\n  extract_scalar (retval, n);\n\n  return retval;\n}\n\nbool\noctave_map::fast_elem_insert (octave_idx_type n,\n                              const octave_scalar_map& rhs)\n{\n  bool retval = false;\n\n  octave_idx_type nf = nfields ();\n  if (rhs.m_keys.is_same (m_keys))\n    {\n      for (octave_idx_type i = 0; i < nf; i++)\n        m_vals[i](n) = rhs.m_vals[i];\n\n      retval = true;\n    }\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, nf);\n      if (m_keys.equal_up_to_order (rhs.m_keys, perm))\n        {\n          for (octave_idx_type i = 0; i < nf; i++)\n            m_vals[i](n) = rhs.m_vals[perm[i]];\n\n          retval = true;\n        }\n    }\n\n  return retval;\n}\n\noctave_map\noctave_map::squeeze () const\n{\n  octave_map retval (*this);\n  octave_idx_type nf = nfields ();\n\n  retval.m_dimensions = m_dimensions.squeeze ();\n\n  for (octave_idx_type i = 0; i < nf; i++)\n    retval.m_vals[i] = m_vals[i].squeeze ();\n\n  retval.optimize_dimensions ();\n\n  return retval;\n}\n\n/*\n## test preservation of m_keys by squeeze\n%!test\n%! x(1,1,1,1).d = 10;  x(3,5,1,7).a = \"b\";  x(2,4,1,7).f = 27;\n%! assert (fieldnames (squeeze (x)), {\"d\"; \"a\"; \"f\"});\n*/\n\noctave_map\noctave_map::permute (const Array<int>& vec, bool inv) const\n{\n  octave_map retval (m_keys);\n  octave_idx_type nf = nfields ();\n\n  for (octave_idx_type i = 0; i < nf; i++)\n    retval.m_vals[i] = m_vals[i].permute (vec, inv);\n\n  // FIXME:\n  // There is no dim_vector::permute for technical reasons.\n  // We pick the dim vector from results if possible, otherwise use a dummy\n  // array to get it.  Need (?) a better solution to this problem.\n  if (nf > 0)\n    retval.m_dimensions = retval.m_vals[0].dims ();\n  else\n    {\n      Array<char> dummy (m_dimensions);\n      dummy = dummy.permute (vec, inv);\n      retval.m_dimensions = dummy.dims ();\n    }\n\n  retval.optimize_dimensions ();\n\n  return retval;\n}\n\n/*\n## test preservation of key order by permute\n%!test\n%! x(1,1,1,1).d = 10;  x(3,5,1,7).a = \"b\";  x(2,4,1,7).f = 27;\n%! assert (fieldnames (permute (x, [3, 4, 1, 2])), {\"d\"; \"a\"; \"f\"});\n*/\n\noctave_map\noctave_map::transpose () const\n{\n  octave_map retval (m_keys);\n\n  retval.m_dimensions = dim_vector (m_dimensions (1), m_dimensions (0));\n\n  octave_idx_type nf = nfields ();\n  for (octave_idx_type i = 0; i < nf; i++)\n    retval.m_vals[i] = m_vals[i].transpose ();\n\n  retval.optimize_dimensions ();\n\n  return retval;\n}\n\n/*\n## test preservation of key order by transpose\n%!test\n%! x(1,1).d = 10;  x(3,5).a = \"b\";  x(2,4).f = 27;\n%! assert (fieldnames (transpose (x)), {\"d\"; \"a\"; \"f\"});\n%! assert (fieldnames (x'), {\"d\"; \"a\"; \"f\"});\n%! assert (fieldnames (x.'), {\"d\"; \"a\"; \"f\"});\n*/\n\noctave_map\noctave_map::reshape (const dim_vector& dv) const\n{\n  octave_map retval (m_keys);\n  retval.m_dimensions = dv;\n\n  // When reshaping m_vals the Array constructor chops trailing singletons,\n  // hence we need to do the same for the whole map.\n  retval.m_dimensions.chop_trailing_singletons ();\n\n  octave_idx_type nf = nfields ();\n  if (nf > 0)\n    {\n      retval.m_vals.reserve (nf);\n      for (octave_idx_type i = 0; i < nf; i++)\n        retval.m_vals[i] = m_vals[i].reshape (dv);\n    }\n  else\n    {\n      // FIXME: Do it with a dummy array, to reuse error message.\n      // Need (?) a better solution.\n      Array<char> dummy (m_dimensions);\n      dummy.reshape (dv);\n    }\n\n  retval.optimize_dimensions ();\n\n  return retval;\n}\n\n/*\n## test preservation of key order by reshape\n%!test\n%! x(1,1).d = 10;  x(4,6).a = \"b\";  x(2,4).f = 27;\n%! assert (fieldnames (reshape (x, 3, 8)), {\"d\"; \"a\"; \"f\"});\n\n## test chopping of trailing singletons\n%!test <*51634>\n%! x(1,1).d = 10;  x(4,6).a = \"b\";  x(2,4).f = 27;\n%! reshape (x, 3, 8, 1, 1);\n\n%!test <*46385>\n%! M = repmat (struct ('a', ones (100), 'b', true), 1, 2);\n%! M = repmat (M, 1, 2);\n%! assert (size (M), [1, 4]);\n\nlibinterp/corefcn/oct-map.cc\n\n*/\n\nvoid\noctave_map::resize (const dim_vector& dv, bool fill)\n{\n  octave_idx_type nf = nfields ();\n  if (nf > 0)\n    {\n      for (octave_idx_type i = 0; i < nf; i++)\n        {\n          if (fill)\n            m_vals[i].resize (dv, Matrix ());\n          else\n            m_vals[i].resize (dv);\n        }\n    }\n  else\n    {\n      // FIXME: Do it with a dummy array, to reuse error message.\n      // Need (?) a better solution.\n      Array<char> dummy (m_dimensions);\n      dummy.resize (dv);\n    }\n\n  m_dimensions = dv;\n  optimize_dimensions ();\n}\n\nvoid\noctave_map::do_cat (int dim, octave_idx_type n,\n                    const octave_scalar_map *map_list,\n                    octave_map& retval)\n{\n  octave_idx_type nf = retval.nfields ();\n  retval.m_vals.reserve (nf);\n\n  dim_vector& rd = retval.m_dimensions;\n  rd.resize (dim+1, 1);\n  rd(0) = rd(1) = 1;\n  rd(dim) = n;\n\n  for (octave_idx_type j = 0; j < nf; j++)\n    {\n      retval.m_vals.push_back (Cell (rd));\n      panic_unless (retval.m_vals[j].numel () == n);\n      for (octave_idx_type i = 0; i < n; i++)\n        retval.m_vals[j].xelem (i) = map_list[i].m_vals[j];\n    }\n}\n\nvoid\noctave_map::do_cat (int dim, octave_idx_type n, const octave_map *map_list,\n                    octave_map& retval)\n{\n  octave_idx_type nf = retval.nfields ();\n  retval.m_vals.reserve (nf);\n\n  OCTAVE_LOCAL_BUFFER (Array<octave_value>, field_list, n);\n\n  for (octave_idx_type j = 0; j < nf; j++)\n    {\n      for (octave_idx_type i = 0; i < n; i++)\n        field_list[i] = map_list[i].m_vals[j];\n\n      retval.m_vals.push_back (Array<octave_value>::cat (dim, n, field_list));\n      if (j == 0)\n        retval.m_dimensions = retval.m_vals[j].dims ();\n    }\n}\n\n// This is just a wrapper.\nvoid\npermute_to_correct_order1 (const octave_scalar_map& ref,\n                           const octave_scalar_map& src,\n                           octave_scalar_map& dest,\n                           Array<octave_idx_type>& perm)\n{\n  dest = src.orderfields (ref, perm);\n}\n\n// In nonscalar case, we also promote empty structs without fields.\nvoid\npermute_to_correct_order1 (const octave_map& ref, const octave_map& src,\n                           octave_map& dest, Array<octave_idx_type>& perm)\n{\n  if (src.nfields () == 0 && src.isempty ())\n    dest = octave_map (src.dims (), ref.keys ());\n  else\n    dest = src.orderfields (ref, perm);\n}\n\ntemplate <typename map>\nstatic void\npermute_to_correct_order (octave_idx_type n, octave_idx_type nf,\n                          octave_idx_type idx, const map *map_list,\n                          map *new_map_list)\n{\n  new_map_list[idx] = map_list[idx];\n\n  Array<octave_idx_type> perm (dim_vector (1, nf));\n\n  try\n    {\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          if (i == idx)\n            continue;\n\n          permute_to_correct_order1 (map_list[idx], map_list[i],\n                                     new_map_list[i], perm);\n        }\n    }\n  catch (octave::execution_exception& ee)\n    {\n      error (ee, \"cat: field names mismatch in concatenating structs\");\n    }\n}\n\noctave_map\noctave_map::cat (int dim, octave_idx_type n, const octave_scalar_map *map_list)\n{\n  octave_map retval;\n\n  // Allow dim = -1, -2 for compatibility, though it makes no difference here.\n  if (dim == -1 || dim == -2)\n    dim = -dim - 1;\n  else if (dim < 0)\n    error (\"cat: invalid dimension\");\n\n  if (n == 1)\n    retval = map_list[0];\n  else if (n > 1)\n    {\n      octave_idx_type idx, nf = 0;\n      for (idx = 0; idx < n; idx++)\n        {\n          nf = map_list[idx].nfields ();\n          if (nf > 0)\n            {\n              retval.m_keys = map_list[idx].m_keys;\n              break;\n            }\n        }\n\n      if (nf > 0)\n        {\n          // Try the fast case.\n          bool all_same = true;\n          for (octave_idx_type i = 0; i < n; i++)\n            {\n              all_same = map_list[idx].m_keys.is_same (map_list[i].m_keys);\n              if (! all_same)\n                break;\n            }\n\n          if (all_same)\n            do_cat (dim, n, map_list, retval);\n          else\n            {\n              // permute all structures to common order.\n              OCTAVE_LOCAL_BUFFER (octave_scalar_map, new_map_list, n);\n\n              permute_to_correct_order (n, nf, idx, map_list, new_map_list);\n\n              do_cat (dim, n, new_map_list, retval);\n            }\n\n        }\n      else\n        {\n          dim_vector& rd = retval.m_dimensions;\n          rd.resize (dim+1, 1);\n          rd(0) = rd(1) = 1;\n          rd(dim) = n;\n        }\n\n      retval.optimize_dimensions ();\n    }\n\n  return retval;\n}\n\noctave_map\noctave_map::cat (int dim, octave_idx_type n, const octave_map *map_list)\n{\n  octave_map retval;\n\n  // Allow dim = -1, -2 for compatibility, though it makes no difference here.\n  if (dim == -1 || dim == -2)\n    dim = -dim - 1;\n  else if (dim < 0)\n    error (\"cat: invalid dimension\");\n\n  if (n == 1)\n    retval = map_list[0];\n  else if (n > 1)\n    {\n      octave_idx_type idx, nf = 0;\n\n      for (idx = 0; idx < n; idx++)\n        {\n          nf = map_list[idx].nfields ();\n          if (nf > 0)\n            {\n              retval.m_keys = map_list[idx].m_keys;\n              break;\n            }\n        }\n\n      // Try the fast case.\n      bool all_same = true;\n\n      if (nf > 0)\n        {\n          for (octave_idx_type i = 0; i < n; i++)\n            {\n              all_same = map_list[idx].m_keys.is_same (map_list[i].m_keys);\n\n              if (! all_same)\n                break;\n            }\n        }\n\n      if (all_same && nf > 0)\n        do_cat (dim, n, map_list, retval);\n      else\n        {\n          if (nf > 0)\n            {\n              // permute all structures to correct order.\n              OCTAVE_LOCAL_BUFFER (octave_map, new_map_list, n);\n\n              permute_to_correct_order (n, nf, idx, map_list, new_map_list);\n\n              do_cat (dim, n, new_map_list, retval);\n            }\n          else\n            {\n              dim_vector dv = map_list[0].m_dimensions;\n\n              for (octave_idx_type i = 1; i < n; i++)\n                {\n                  if (! dv.concat (map_list[i].m_dimensions, dim))\n                    error (\"dimension mismatch in struct concatenation\");\n                }\n\n              retval.m_dimensions = dv;\n            }\n        }\n\n      retval.optimize_dimensions ();\n    }\n\n  return retval;\n}\n\n/*\n## test preservation of key order by concatenation\n%!test\n%! x(1, 1).d = 10;  x(4, 6).a = \"b\";  x(2, 4).f = 27;\n%! y(1, 6).f = 11;  y(1, 6).a = \"c\";  y(1, 6).d = 33;\n%! assert (fieldnames ([x; y]), {\"d\"; \"a\"; \"f\"});\n\n%!test\n%! s = struct ();\n%! sr = [s,s];\n%! sc = [s;s];\n%! sm = [s,s;s,s];\n%! assert (numfields (sr), 0);\n%! assert (numfields (sc), 0);\n%! assert (numfields (sm), 0);\n%! assert (size (sr), [1, 2]);\n%! assert (size (sc), [2, 1]);\n%! assert (size (sm), [2, 2]);\n*/\n\noctave_map\noctave_map::index (const octave::idx_vector& i, bool resize_ok) const\n{\n  octave_map retval (m_keys);\n  octave_idx_type nf = nfields ();\n\n  for (octave_idx_type k = 0; k < nf; k++)\n    retval.m_vals[k] = m_vals[k].index (i, resize_ok);\n\n  if (nf > 0)\n    retval.m_dimensions = retval.m_vals[0].dims ();\n  else\n    {\n      // Use dummy array.  FIXME: Need(?) a better solution.\n      Array<char> dummy (m_dimensions);\n      dummy = dummy.index (i, resize_ok);\n      retval.m_dimensions = dummy.dims ();\n    }\n\n  retval.optimize_dimensions ();\n\n  return retval;\n}\n\noctave_map\noctave_map::index (const octave::idx_vector& i, const octave::idx_vector& j,\n                   bool resize_ok) const\n{\n  octave_map retval (m_keys);\n  octave_idx_type nf = nfields ();\n\n  for (octave_idx_type k = 0; k < nf; k++)\n    retval.m_vals[k] = m_vals[k].index (i, j, resize_ok);\n\n  if (nf > 0)\n    retval.m_dimensions = retval.m_vals[0].dims ();\n  else\n    {\n      // Use dummy array.  FIXME: Need(?) a better solution.\n      Array<char> dummy (m_dimensions);\n      dummy = dummy.index (i, j, resize_ok);\n      retval.m_dimensions = dummy.dims ();\n    }\n\n  retval.optimize_dimensions ();\n\n  return retval;\n}\n\noctave_map\noctave_map::index (const Array<octave::idx_vector>& ia, bool resize_ok) const\n{\n  octave_map retval (m_keys);\n  octave_idx_type nf = nfields ();\n\n  for (octave_idx_type k = 0; k < nf; k++)\n    retval.m_vals[k] = m_vals[k].index (ia, resize_ok);\n\n  if (nf > 0)\n    retval.m_dimensions = retval.m_vals[0].dims ();\n  else\n    {\n      // Use dummy array.  FIXME: Need(?) a better solution.\n      Array<char> dummy (m_dimensions);\n      dummy = dummy.index (ia, resize_ok);\n      retval.m_dimensions = dummy.dims ();\n    }\n\n  retval.optimize_dimensions ();\n\n  return retval;\n}\n\noctave_map\noctave_map::index (const octave_value_list& idx, bool resize_ok) const\n{\n  octave_idx_type n_idx = idx.length ();\n  octave_map retval;\n\n  // If we catch an indexing error in index_vector, we flag an error in\n  // index k.  Ensure it is the right value before each idx_vector call.\n  // Same variable as used in the for loop in the default case.\n\n  octave_idx_type k = 0;\n\n  try\n    {\n      switch (n_idx)\n        {\n        case 1:\n          {\n            octave::idx_vector i = idx(0).index_vector ();\n\n            retval = index (i, resize_ok);\n          }\n          break;\n\n        case 2:\n          {\n            octave::idx_vector i = idx(0).index_vector ();\n\n            k = 1;\n            octave::idx_vector j = idx(1).index_vector ();\n\n            retval = index (i, j, resize_ok);\n          }\n          break;\n\n        default:\n          {\n            Array<octave::idx_vector> ia (dim_vector (n_idx, 1));\n\n            for (k = 0; k < n_idx; k++)\n              ia(k) = idx(k).index_vector ();\n\n            retval = index (ia, resize_ok);\n          }\n          break;\n        }\n    }\n  catch (octave::index_exception& ie)\n    {\n      // Rethrow to allow more info to be reported later.\n      ie.set_pos_if_unset (n_idx, k+1);\n      throw;\n    }\n\n  return retval;\n}\n\n// Perhaps one day these will be optimized.  Right now, they just call index.\noctave_map\noctave_map::column (octave_idx_type k) const\n{\n  return index (octave::idx_vector::colon, k);\n}\n\noctave_map\noctave_map::page (octave_idx_type k) const\n{\n  static Array<octave::idx_vector> ia (dim_vector (3, 1),\n                                       octave::idx_vector::colon);\n\n  ia(2) = k;\n  return index (ia);\n}\n\nvoid\noctave_map::assign (const octave::idx_vector& i, const octave_map& rhs)\n{\n  if (rhs.m_keys.is_same (m_keys))\n    {\n      octave_idx_type nf = nfields ();\n\n      for (octave_idx_type k = 0; k < nf; k++)\n        m_vals[k].assign (i, rhs.m_vals[k], Matrix ());\n\n      if (nf > 0)\n        m_dimensions = m_vals[0].dims ();\n      else\n        {\n          // Use dummy array.  FIXME: Need(?) a better solution.\n          Array<char> dummy (m_dimensions), rhs_dummy (rhs.m_dimensions);\n          dummy.assign (i, rhs_dummy);\n          m_dimensions = dummy.dims ();\n        }\n\n      optimize_dimensions ();\n    }\n  else if (nfields () == 0)\n    {\n      octave_map tmp (m_dimensions, rhs.m_keys);\n      tmp.assign (i, rhs);\n      *this = tmp;\n    }\n  else\n    {\n      Array<octave_idx_type> perm;\n      octave_map rhs1;\n\n      try\n        {\n          rhs1 = rhs.orderfields (*this, perm);\n        }\n      catch (octave::execution_exception& ee)\n        {\n          error (ee, \"incompatible fields in struct assignment\");\n        }\n\n      panic_unless (rhs1.m_keys.is_same (m_keys));\n      assign (i, rhs1);\n    }\n}\n\nvoid\noctave_map::assign (const octave::idx_vector& i, const octave::idx_vector& j,\n                    const octave_map& rhs)\n{\n  if (rhs.m_keys.is_same (m_keys))\n    {\n      octave_idx_type nf = nfields ();\n\n      for (octave_idx_type k = 0; k < nf; k++)\n        m_vals[k].assign (i, j, rhs.m_vals[k], Matrix ());\n\n      if (nf > 0)\n        m_dimensions = m_vals[0].dims ();\n      else\n        {\n          // Use dummy array.  FIXME: Need(?) a better solution.\n          Array<char> dummy (m_dimensions), rhs_dummy (rhs.m_dimensions);\n          dummy.assign (i, j, rhs_dummy);\n          m_dimensions = dummy.dims ();\n        }\n\n      optimize_dimensions ();\n    }\n  else if (nfields () == 0)\n    {\n      octave_map tmp (m_dimensions, rhs.m_keys);\n      tmp.assign (i, j, rhs);\n      *this = tmp;\n    }\n  else\n    {\n      Array<octave_idx_type> perm;\n      octave_map rhs1;\n\n      try\n        {\n          rhs1 = rhs.orderfields (*this, perm);\n        }\n      catch (octave::execution_exception& ee)\n        {\n          error (ee, \"incompatible fields in struct assignment\");\n        }\n\n      panic_unless (rhs1.m_keys.is_same (m_keys));\n      assign (i, j, rhs1);\n    }\n}\n\nvoid\noctave_map::assign (const Array<octave::idx_vector>& ia,\n                    const octave_map& rhs)\n{\n  if (rhs.m_keys.is_same (m_keys))\n    {\n      octave_idx_type nf = nfields ();\n\n      for (octave_idx_type k = 0; k < nf; k++)\n        m_vals[k].assign (ia, rhs.m_vals[k], Matrix ());\n\n      if (nf > 0)\n        m_dimensions = m_vals[0].dims ();\n      else\n        {\n          // Use dummy array.  FIXME: Need(?) a better solution.\n          Array<char> dummy (m_dimensions), rhs_dummy (rhs.m_dimensions);\n          dummy.assign (ia, rhs_dummy);\n          m_dimensions = dummy.dims ();\n        }\n\n      optimize_dimensions ();\n    }\n  else if (nfields () == 0)\n    {\n      octave_map tmp (m_dimensions, rhs.m_keys);\n      tmp.assign (ia, rhs);\n      *this = tmp;\n    }\n  else\n    {\n      Array<octave_idx_type> perm;\n      octave_map rhs1;\n\n      try\n        {\n          rhs1 = rhs.orderfields (*this, perm);\n        }\n      catch (octave::execution_exception& ee)\n        {\n          error (ee, \"incompatible fields in struct assignment\");\n        }\n\n      panic_unless (rhs1.m_keys.is_same (m_keys));\n      assign (ia, rhs1);\n    }\n}\n\nvoid\noctave_map::assign (const octave_value_list& idx, const octave_map& rhs)\n{\n  octave_idx_type n_idx = idx.length ();\n\n  // If we catch an indexing error in index_vector, we flag an error in\n  // index k.  Ensure it is the right value before each idx_vector call.\n  // Same variable as used in the for loop in the default case.\n\n  octave_idx_type k = 0;\n\n  try\n    {\n      switch (n_idx)\n        {\n        case 1:\n          {\n            octave::idx_vector i = idx(0).index_vector ();\n\n            assign (i, rhs);\n          }\n          break;\n\n        case 2:\n          {\n            octave::idx_vector i = idx(0).index_vector ();\n\n            k = 1;\n            octave::idx_vector j = idx(1).index_vector ();\n\n            assign (i, j, rhs);\n          }\n          break;\n\n        default:\n          {\n            Array<octave::idx_vector> ia (dim_vector (n_idx, 1));\n\n            for (k = 0; k < n_idx; k++)\n              ia(k) = idx(k).index_vector ();\n\n            assign (ia, rhs);\n          }\n          break;\n        }\n    }\n  catch (octave::index_exception& ie)\n    {\n      // Rethrow to allow more info to be reported later.\n      ie.set_pos_if_unset (n_idx, k+1);\n      throw;\n    }\n}\n\nvoid\noctave_map::assign (const octave_value_list& idx, const std::string& k,\n                    const Cell& rhs)\n{\n  Cell tmp;\n  auto p = seek (k);\n  Cell& ref = (p != end () ? contents (p) : tmp);\n\n  if (&ref == &tmp)\n    ref = Cell (m_dimensions);\n\n  ref.assign (idx, rhs);\n\n  if (ref.dims () != m_dimensions)\n    {\n      m_dimensions = ref.dims ();\n\n      octave_idx_type nf = nfields ();\n      for (octave_idx_type i = 0; i < nf; i++)\n        {\n          if (&m_vals[i] != &ref)\n            m_vals[i].resize (m_dimensions, Matrix ());\n        }\n\n      optimize_dimensions ();\n    }\n\n  if (&ref == &tmp)\n    setfield (k, tmp);\n}\n\n/*\n%!test\n%! rhs.b = 1;\n%! a(3) = rhs;\n%! assert ({a.b}, {[], [], 1});\n*/\n\nvoid\noctave_map::delete_elements (const octave::idx_vector& i)\n{\n  octave_idx_type nf = nfields ();\n  for (octave_idx_type k = 0; k < nf; k++)\n    m_vals[k].delete_elements (i);\n\n  if (nf > 0)\n    m_dimensions = m_vals[0].dims ();\n  else\n    {\n      // Use dummy array.  FIXME: Need(?) a better solution.\n      Array<char> dummy (m_dimensions);\n      dummy.delete_elements (i);\n      m_dimensions = dummy.dims ();\n    }\n\n  optimize_dimensions ();\n}\n\nvoid\noctave_map::delete_elements (int dim, const octave::idx_vector& i)\n{\n  octave_idx_type nf = nfields ();\n  for (octave_idx_type k = 0; k < nf; k++)\n    m_vals[k].delete_elements (dim, i);\n\n  if (nf > 0)\n    m_dimensions = m_vals[0].dims ();\n  else\n    {\n      // Use dummy array.  FIXME: Need(?) a better solution.\n      Array<char> dummy (m_dimensions);\n      dummy.delete_elements (dim, i);\n      m_dimensions = dummy.dims ();\n    }\n\n  optimize_dimensions ();\n}\n\nvoid\noctave_map::delete_elements (const Array<octave::idx_vector>& ia)\n{\n  octave_idx_type nf = nfields ();\n  for (octave_idx_type k = 0; k < nf; k++)\n    m_vals[k].delete_elements (ia);\n\n  if (nf > 0)\n    m_dimensions = m_vals[0].dims ();\n  else\n    {\n      // Use dummy array.  FIXME: Need(?) a better solution.\n      Array<char> dummy (m_dimensions);\n      dummy.delete_elements (ia);\n      m_dimensions = dummy.dims ();\n    }\n\n  optimize_dimensions ();\n}\n\nvoid\noctave_map::delete_elements (const octave_value_list& idx)\n{\n  octave_idx_type n_idx = idx.length ();\n\n  Array<octave::idx_vector> ia (dim_vector (n_idx, 1));\n\n  for (octave_idx_type i = 0; i < n_idx; i++)\n    {\n      try\n        {\n          ia(i) = idx(i).index_vector ();\n        }\n      catch (octave::index_exception& ie)\n        {\n          // Rethrow to allow more info to be reported later.\n          ie.set_pos_if_unset (n_idx, i+1);\n          throw;\n        }\n    }\n\n  delete_elements (ia);\n}\n\n/*\n## test preservation of key order by indexing\n%!test\n%! x(1, 1).d = 10;  x(4, 6).a = \"b\";  x(2, 4).f = 27;\n%! assert (fieldnames (x([1, 2], [2:5])), {\"d\"; \"a\"; \"f\"});\n*/\n\noctave_map\noctave_map::concat (const octave_map& rb, const Array<octave_idx_type>& ra_idx)\n{\n  if (nfields () == rb.nfields ())\n    {\n      for (auto pa = cbegin (); pa != cend (); pa++)\n        {\n          auto pb = rb.seek (key (pa));\n\n          if (pb == rb.cend ())\n            error (\"field name mismatch in structure concatenation\");\n\n          contents(pa).insert (rb.contents (pb), ra_idx);\n        }\n    }\n  else\n    {\n      const dim_vector& dv = dims ();\n\n      if (dv.all_zero ())\n        *this = rb;\n      else if (! rb.dims ().all_zero ())\n        error (\"invalid structure concatenation\");\n    }\n\n  return *this;\n}\n\nvoid\noctave_map::optimize_dimensions ()\n{\n  octave_idx_type nf = nfields ();\n\n  for (octave_idx_type i = 0; i < nf; i++)\n    {\n      if (! m_vals[i].optimize_dimensions (m_dimensions))\n        error (\"internal error: dimension mismatch across fields in struct\");\n    }\n\n}\n"
  },
  {
    "path": "libinterp/corefcn/oct-map.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_map_h)\n#define octave_oct_map_h 1\n\n#include \"octave-config.h\"\n\n#include <algorithm>\n#include <map>\n\n#include \"oct-refcount.h\"\n\n#include \"Cell.h\"\n#include \"ovl.h\"\n\nclass string_vector;\n\n// A class holding a map field->index.  Supports reference-counting.\nclass OCTINTERP_API\noctave_fields\n{\n  class fields_rep : public std::map<std::string, octave_idx_type>\n  {\n  public:\n\n    fields_rep () : std::map<std::string, octave_idx_type> (), m_count (1) { }\n\n    fields_rep (const fields_rep& other)\n      : std::map<std::string, octave_idx_type> (other), m_count (1) { }\n\n    fields_rep& operator = (const fields_rep&) = delete;\n\n    ~fields_rep () = default;\n\n    octave::refcount<octave_idx_type> m_count;\n  };\n\n  fields_rep *m_rep;\n\n  static fields_rep * nil_rep ();\n\npublic:\n\n  octave_fields () : m_rep (nil_rep ()) { m_rep->m_count++; }\n  octave_fields (const string_vector&);\n  octave_fields (const char *const *);\n\n  ~octave_fields ()\n  {\n    if (--m_rep->m_count == 0)\n      delete m_rep;\n  }\n\n  void make_unique ()\n  {\n    if (m_rep->m_count > 1)\n      {\n        fields_rep *r = new fields_rep (*m_rep);\n\n        if (--m_rep->m_count == 0)\n          delete m_rep;\n\n        m_rep = r;\n      }\n  }\n\n  octave_fields (const octave_fields& o) : m_rep (o.m_rep) { m_rep->m_count++; }\n\n  octave_fields&\n  operator = (const octave_fields& o)\n  {\n    if (&o != this)\n      {\n        o.m_rep->m_count++;\n        if (--m_rep->m_count == 0)\n          delete m_rep;\n        m_rep = o.m_rep;\n      }\n\n    return *this;\n  }\n\n  // constant iteration support.  non-const iteration intentionally unsupported.\n\n  typedef std::map<std::string, octave_idx_type>::const_iterator const_iterator;\n  typedef const_iterator iterator;\n\n  const_iterator begin () const { return m_rep->begin (); }\n  const_iterator end () const { return m_rep->end (); }\n\n  const_iterator cbegin () const { return m_rep->cbegin (); }\n  const_iterator cend () const { return m_rep->cend (); }\n\n  std::string key (const_iterator p) const { return p->first; }\n  octave_idx_type index (const_iterator p) const { return p->second; }\n\n  const_iterator seek (const std::string& k) const\n  { return m_rep->find (k); }\n\n  // high-level methods.\n\n  // number of fields.\n  octave_idx_type nfields () const { return m_rep->size (); }\n\n  // check whether a field exists.\n  bool isfield (const std::string& name) const;\n\n  // get index of field.  return -1 if not exist\n  octave_idx_type getfield (const std::string& name) const;\n  // get index of field.  add if not exist\n  octave_idx_type getfield (const std::string& name);\n  // remove field and return the index.  return -1 if didn't exist.\n  octave_idx_type rmfield (const std::string& name);\n\n  // order the fields of this map.\n  // creates a permutation used to order the fields.\n  void orderfields (Array<octave_idx_type>& perm);\n\n  // compares two instances for equality up to order of fields.\n  // returns a permutation needed to bring the fields of *other*\n  // into the order of *this*.\n  bool equal_up_to_order (const octave_fields& other,\n                          octave_idx_type *perm) const;\n\n  bool equal_up_to_order (const octave_fields& other,\n                          Array<octave_idx_type>& perm) const;\n\n  bool is_same (const octave_fields& other) const\n  { return m_rep == other.m_rep; }\n\n  // Returns the fields as a vector of strings.\n  string_vector fieldnames () const;\n\n  void clear ()\n  {\n    *this = octave_fields ();\n  }\n};\n\nclass OCTINTERP_API\noctave_scalar_map\n{\npublic:\n\n  octave_scalar_map (const octave_fields& k)\n    : m_keys (k), m_vals (k.nfields ()) { }\n\n  octave_scalar_map (const string_vector& k)\n    : m_keys (k), m_vals (k.numel ()) { }\n\n  octave_scalar_map (const std::map<std::string, octave_value>& m);\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (octave_scalar_map)\n\n  // iteration support.\n  // note that both const and non-const iterators are the same.\n  // The const/non-const distinction is made by the key & contents method.\n  typedef octave_fields::const_iterator const_iterator;\n  typedef const_iterator iterator;\n\n  const_iterator begin () const { return m_keys.begin (); }\n  const_iterator end () const { return m_keys.end (); }\n\n  const_iterator cbegin () const { return m_keys.cbegin (); }\n  const_iterator cend () const { return m_keys.cend (); }\n\n  const_iterator seek (const std::string& k) const { return m_keys.seek (k); }\n\n  std::string key (const_iterator p) const\n  { return m_keys.key (p); }\n  octave_idx_type index (const_iterator p) const\n  { return m_keys.index (p); }\n\n  const octave_value& contents (const_iterator p) const\n  { return m_vals[m_keys.index (p)]; }\n\n  octave_value& contents (iterator p)\n  { return m_vals[m_keys.index (p)]; }\n\n  const octave_value& contents (octave_idx_type i) const\n  { return m_vals[i]; }\n\n  octave_value& contents (octave_idx_type i)\n  { return m_vals[i]; }\n\n  // number of fields.\n  octave_idx_type nfields () const { return m_keys.nfields (); }\n\n  // check whether a field exists.\n  bool isfield (const std::string& name) const\n  { return m_keys.isfield (name); }\n\n  bool contains (const std::string& name) const\n  { return isfield (name); }\n\n  string_vector fieldnames () const\n  { return m_keys.fieldnames (); }\n\n  string_vector keys () const\n  { return fieldnames (); }\n\n  // get contents of a given field.  empty value if not exist.\n  octave_value getfield (const std::string& key) const;\n\n  // set contents of a given field.  add if not exist.\n  void setfield (const std::string& key, const octave_value& val);\n  void assign (const std::string& k, const octave_value& val)\n  { setfield (k, val); }\n\n  // remove a given field.  do nothing if not exist.\n  void rmfield (const std::string& key);\n  void del (const std::string& k) { rmfield (k); }\n\n  // return a copy with fields ordered, optionally along with permutation.\n  octave_scalar_map orderfields () const;\n  octave_scalar_map orderfields (Array<octave_idx_type>& perm) const;\n  octave_scalar_map orderfields (const octave_scalar_map& other,\n                                 Array<octave_idx_type>& perm) const;\n\n  // aka getfield/setfield, but the latter returns a reference.\n  octave_value contents (const std::string& k) const;\n  octave_value& contents (const std::string& k);\n\n  std::size_t byte_size () const;\n\n  void clear ()\n  {\n    m_keys.clear ();\n    m_vals.clear ();\n  }\n\n  friend class octave_map;\n\nprivate:\n\n  octave_fields m_keys;\n  std::vector<octave_value> m_vals;\n};\n\ntemplate <>\ninline octave_scalar_map\noctave_value_extract<octave_scalar_map> (const octave_value& v)\n{ return v.scalar_map_value (); }\n\nclass OCTINTERP_API\noctave_map\n{\npublic:\n\n  octave_map (const octave_fields& k)\n    : m_keys (k), m_vals (k.nfields ()), m_dimensions () { }\n\n  octave_map (const dim_vector& dv, const octave_fields& k)\n    : m_keys (k), m_vals (k.nfields (), Cell (dv)), m_dimensions (dv) { }\n\n  typedef octave_scalar_map element_type;\n\n  octave_map (const dim_vector& dv) : m_keys (), m_vals (), m_dimensions (dv) { }\n\n  octave_map (const string_vector& k)\n    : m_keys (k), m_vals (k.numel (), Cell (1, 1)), m_dimensions (1, 1) { }\n\n  octave_map (const dim_vector& dv, const string_vector& k)\n    : m_keys (k), m_vals (k.numel (), Cell (dv)), m_dimensions (dv) { }\n\n  octave_map (const octave_scalar_map& m);\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (octave_map)\n\n  // iteration support.\n  // note that both const and non-const iterators are the same.\n  // The const/non-const distinction is made by the key & contents method.\n  typedef octave_fields::const_iterator const_iterator;\n  typedef const_iterator iterator;\n\n  const_iterator begin () const { return m_keys.begin (); }\n  const_iterator end () const { return m_keys.end (); }\n\n  const_iterator cbegin () const { return m_keys.cbegin (); }\n  const_iterator cend () const { return m_keys.cend (); }\n\n  const_iterator seek (const std::string& k) const { return m_keys.seek (k); }\n\n  std::string key (const_iterator p) const\n  { return m_keys.key (p); }\n  octave_idx_type index (const_iterator p) const\n  { return m_keys.index (p); }\n\n  const Cell& contents (const_iterator p) const\n  { return m_vals[m_keys.index (p)]; }\n\n  Cell& contents (iterator p)\n  { return m_vals[m_keys.index (p)]; }\n\n  const Cell& contents (octave_idx_type i) const\n  { return m_vals[i]; }\n\n  Cell& contents (octave_idx_type i)\n  { return m_vals[i]; }\n\n  // number of fields.\n  octave_idx_type nfields () const { return m_keys.nfields (); }\n\n  // check whether a field exists.\n  bool isfield (const std::string& name) const\n  { return m_keys.isfield (name); }\n\n  bool contains (const std::string& name) const\n  { return isfield (name); }\n\n  string_vector fieldnames () const\n  { return m_keys.fieldnames (); }\n\n  string_vector keys () const\n  { return fieldnames (); }\n\n  // get contents of a given field.  empty value if not exist.\n  Cell getfield (const std::string& key) const;\n\n  // set contents of a given field.  add if not exist.  checks for\n  // correct m_dimensions.\n  void setfield (const std::string& key, const Cell& val);\n  void assign (const std::string& k, const Cell& val)\n  { setfield (k, val); }\n\n  // remove a given field.  do nothing if not exist.\n  void rmfield (const std::string& key);\n  void del (const std::string& k) { rmfield (k); }\n\n  // return a copy with fields ordered, optionally along with permutation.\n  octave_map orderfields () const;\n  octave_map orderfields (Array<octave_idx_type>& perm) const;\n  octave_map orderfields (const octave_map& other,\n                          Array<octave_idx_type>& perm) const;\n\n  // aka getfield/setfield, but the latter returns a reference.\n  Cell contents (const std::string& k) const;\n  Cell& contents (const std::string& k);\n\n  std::size_t byte_size () const;\n\n  void clear ()\n  {\n    m_keys.clear ();\n    m_vals.clear ();\n  }\n\n  // The Array-like methods.\n  octave_idx_type numel () const { return m_dimensions.numel (); }\n  octave_idx_type length () const { return numel (); }\n  bool isempty () const { return m_dimensions.any_zero (); }\n\n  octave_idx_type rows () const { return m_dimensions(0); }\n  octave_idx_type cols () const { return m_dimensions(1); }\n  octave_idx_type columns () const { return m_dimensions(1); }\n\n  // Extract a scalar substructure.\n  // FIXME: actually check something.\n  octave_scalar_map checkelem (octave_idx_type n) const\n  { return elem (n); }\n\n  // FIXME: actually check something.\n  octave_scalar_map checkelem (octave_idx_type i, octave_idx_type j) const\n  { return elem (i, j); }\n\n  // FIXME: actually check something.\n  octave_scalar_map checkelem (const Array<octave_idx_type>& ra_idx) const\n  { return elem (ra_idx); }\n\n  octave_scalar_map elem (octave_idx_type n) const;\n\n  octave_scalar_map elem (octave_idx_type i, octave_idx_type j) const;\n\n  octave_scalar_map elem (const Array<octave_idx_type>& ra_idx) const;\n\n  octave_scalar_map operator () (octave_idx_type n) const\n  { return elem (n); }\n\n  octave_scalar_map operator () (octave_idx_type i, octave_idx_type j) const\n  { return elem (i, j); }\n\n  octave_scalar_map\n  operator () (const Array<octave_idx_type>& ra_idx) const\n  { return elem (ra_idx); }\n\n  octave_map squeeze () const;\n\n  octave_map permute (const Array<int>& vec, bool inv = false) const;\n\n  dim_vector dims () const { return m_dimensions; }\n\n  int ndims () const { return m_dimensions.ndims (); }\n\n  octave_map transpose () const;\n\n  octave_map reshape (const dim_vector& dv) const;\n\n  void resize (const dim_vector& dv, bool fill = false);\n\n  static octave_map\n  cat (int dim, octave_idx_type n, const octave_scalar_map *map_list);\n\n  static octave_map\n  cat (int dim, octave_idx_type n, const octave_map *map_list);\n\n  octave_map index (const octave::idx_vector& i, bool resize_ok = false) const;\n\n  octave_map index (const octave::idx_vector& i, const octave::idx_vector& j,\n                    bool resize_ok = false) const;\n\n  octave_map index (const Array<octave::idx_vector>& ia,\n                    bool resize_ok = false) const;\n\n  octave_map index (const octave_value_list&, bool resize_ok = false) const;\n\n  octave_map column (octave_idx_type k) const;\n  octave_map page (octave_idx_type k) const;\n\n  void assign (const octave::idx_vector& i, const octave_map& rhs);\n\n  void assign (const octave::idx_vector& i, const octave::idx_vector& j,\n               const octave_map& rhs);\n\n  void assign (const Array<octave::idx_vector>& ia, const octave_map& rhs);\n\n  void assign (const octave_value_list&, const octave_map& rhs);\n\n  void assign (const octave_value_list& idx, const std::string& k,\n               const Cell& rhs);\n\n  void delete_elements (const octave::idx_vector& i);\n\n  void delete_elements (int dim, const octave::idx_vector& i);\n\n  void delete_elements (const Array<octave::idx_vector>& ia);\n\n  void delete_elements (const octave_value_list&);\n\n  octave_map concat (const octave_map& rb,\n                     const Array<octave_idx_type>& ra_idx);\n\n  // like checkelem, but no check.\n  octave_scalar_map fast_elem_extract (octave_idx_type n) const;\n\n  // element assignment, no bounds check\n  bool fast_elem_insert (octave_idx_type n, const octave_scalar_map& rhs);\n\nprivate:\n\n  octave_fields m_keys;\n  std::vector<Cell> m_vals;\n  dim_vector m_dimensions;\n\n  void optimize_dimensions ();\n  void extract_scalar (octave_scalar_map& dest,\n                       octave_idx_type index) const;\n  static void do_cat (int dim, octave_idx_type n,\n                      const octave_scalar_map *map_list, octave_map& retval);\n  static void do_cat (int dim, octave_idx_type n,\n                      const octave_map *map_list, octave_map& retval);\n};\n\ntemplate <>\ninline octave_map octave_value_extract<octave_map> (const octave_value& v)\n{ return v.map_value (); }\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-opengl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_opengl_h)\n#define octave_oct_opengl_h 1\n\n#include \"octave-config.h\"\n\n#if defined (HAVE_OPENGL)\n\n#  if defined (HAVE_GL_GL_H)\n#    include <GL/gl.h>\n#  elif defined (HAVE_OPENGL_GL_H) || defined (HAVE_FRAMEWORK_OPENGL)\n#    include <OpenGL/gl.h>\n#  endif\n\n#  if defined (HAVE_GL_GLU_H)\n#    include <GL/glu.h>\n#  elif defined (HAVE_OPENGL_GLU_H) || defined (HAVE_FRAMEWORK_OPENGL)\n#    include <OpenGL/glu.h>\n#  endif\n\n#  if defined (HAVE_GL_GLEXT_H)\n#    include <GL/glext.h>\n#  elif defined (HAVE_OPENGL_GLEXT_H) || defined (HAVE_FRAMEWORK_OPENGL)\n#    include <OpenGL/glext.h>\n#  endif\n\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass opengl_functions\n{\npublic:\n\n  opengl_functions () { }\n\n  opengl_functions (const opengl_functions&) = default;\n\n  opengl_functions& operator = (const opengl_functions&) = default;\n\n  virtual ~opengl_functions () = default;\n\n#if defined (HAVE_OPENGL)\n\n  // If OpenGL is not available, opengl_functions will be a dummy\n  // class that does nothing.  This makes the implementation of\n  // other things that rely on this class slightly simpler.\n\n  virtual void glAlphaFunc (GLenum fcn, GLclampf ref)\n  {\n    ::glAlphaFunc (fcn, ref);\n  }\n\n  virtual void glBegin (GLenum mode)\n  {\n    ::glBegin (mode);\n  }\n\n  virtual void glBindTexture (GLenum target, GLuint texture)\n  {\n    ::glBindTexture (target, texture);\n  }\n\n  virtual void glBitmap (GLsizei width, GLsizei height, GLfloat xorig,\n                         GLfloat yorig, GLfloat xmove, GLfloat ymove,\n                         const GLubyte *bitmap)\n  {\n    ::glBitmap (width, height, xorig, yorig, xmove, ymove, bitmap);\n  }\n\n  virtual void glBlendFunc (GLenum sfactor, GLenum dfactor)\n  {\n    ::glBlendFunc (sfactor, dfactor);\n  }\n\n#if defined (HAVE_GLBLENDFUNCSEPARATE)\n  virtual void glBlendFuncSeparate (GLenum sfactor, GLenum dfactor,\n                                    GLenum salpha, GLenum dalpha)\n  {\n    ::glBlendFuncSeparate (sfactor, dfactor, salpha, dalpha);\n  }\n#endif\n\n  virtual void glCallList (GLuint list)\n  {\n    ::glCallList (list);\n  }\n\n  virtual void glClearColor (GLclampf red, GLclampf green, GLclampf blue,\n                             GLclampf alpha)\n  {\n    ::glClearColor (red, green, blue, alpha);\n  }\n\n  virtual void glClear (GLbitfield mask)\n  {\n    ::glClear (mask);\n  }\n\n  virtual void glClipPlane (GLenum plane, const GLdouble *equation)\n  {\n    ::glClipPlane (plane, equation);\n  }\n\n  virtual void glColor3dv (const GLdouble *v)\n  {\n    ::glColor3dv (v);\n  }\n\n  virtual void glColor3f (GLfloat red, GLfloat green, GLfloat blue)\n  {\n    ::glColor3f (red, green, blue);\n  }\n\n  virtual void glColor3fv (const GLfloat *v)\n  {\n    ::glColor3fv (v);\n  }\n\n  virtual void glColor4d (GLdouble red, GLdouble green, GLdouble blue,\n                          GLdouble alpha)\n  {\n    ::glColor4d (red, green, blue, alpha);\n  }\n\n  virtual void glColor4f (GLfloat red, GLfloat green, GLfloat blue,\n                          GLfloat alpha)\n  {\n    ::glColor4f (red, green, blue, alpha);\n  }\n\n  virtual void glColor4fv (const GLfloat *v)\n  {\n    ::glColor4fv (v);\n  }\n\n  virtual void glDeleteLists (GLuint list, GLsizei range)\n  {\n    ::glDeleteLists (list, range);\n  }\n\n  virtual void glDeleteTextures (GLsizei n, const GLuint *textures)\n  {\n    ::glDeleteTextures (n, textures);\n  }\n\n  virtual void glDepthFunc (GLenum fcn)\n  {\n    ::glDepthFunc (fcn);\n  }\n\n  virtual void glDisable (GLenum cap)\n  {\n    ::glDisable (cap);\n  }\n\n  virtual void glDrawPixels (GLsizei width, GLsizei height, GLenum format,\n                             GLenum type, const GLvoid *pixels)\n  {\n    ::glDrawPixels (width, height, format, type, pixels);\n  }\n\n  virtual void glEdgeFlag (GLboolean flag)\n  {\n    ::glEdgeFlag (flag);\n  }\n\n  virtual void glEnable (GLenum cap)\n  {\n    ::glEnable (cap);\n  }\n\n  virtual void glEndList ()\n  {\n    ::glEndList ();\n  }\n\n  virtual void glEnd ()\n  {\n    ::glEnd ();\n  }\n\n  virtual void glFinish ()\n  {\n    ::glFinish ();\n  }\n\n  virtual GLuint glGenLists (GLsizei range)\n  {\n    return ::glGenLists (range);\n  }\n\n  virtual void glGenTextures (GLsizei n, GLuint *textures)\n  {\n    ::glGenTextures (n, textures);\n  }\n\n  virtual void glGetBooleanv (GLenum pname, GLboolean *data)\n  {\n    ::glGetBooleanv (pname, data);\n  }\n\n  virtual void glGetDoublev (GLenum pname, GLdouble *data)\n  {\n    ::glGetDoublev (pname, data);\n  }\n\n  virtual GLenum glGetError ()\n  {\n    return ::glGetError ();\n  }\n\n  virtual void glGetFloatv (GLenum pname, GLfloat *data)\n  {\n    ::glGetFloatv (pname, data);\n  }\n\n  virtual void glGetIntegerv (GLenum pname, GLint *data)\n  {\n    ::glGetIntegerv (pname, data);\n  }\n\n  virtual const GLubyte * glGetString (GLenum name)\n  {\n    return ::glGetString (name);\n  }\n\n  virtual void glHint (GLenum target, GLenum mode)\n  {\n    ::glHint (target, mode);\n  }\n\n  virtual void glInitNames ()\n  {\n    ::glInitNames ();\n  }\n\n  virtual GLboolean glIsEnabled (GLenum cap)\n  {\n    return ::glIsEnabled (cap);\n  }\n\n  virtual void glLightfv (GLenum light, GLenum pname, const GLfloat *params)\n  {\n    ::glLightfv (light, pname, params);\n  }\n\n  virtual void glLineStipple (GLint factor, GLushort pattern)\n  {\n    ::glLineStipple (factor, pattern);\n  }\n\n  virtual void glLineWidth (GLfloat width)\n  {\n    ::glLineWidth (width);\n  }\n\n  virtual void glLoadIdentity ()\n  {\n    ::glLoadIdentity ();\n  }\n\n  virtual void glMaterialf (GLenum face, GLenum pname, GLfloat param)\n  {\n    ::glMaterialf (face, pname, param);\n  }\n\n  virtual void glMaterialfv (GLenum face, GLenum pname, const GLfloat *params)\n  {\n    ::glMaterialfv (face, pname, params);\n  }\n\n  virtual void glMatrixMode (GLenum mode)\n  {\n    ::glMatrixMode (mode);\n  }\n\n  virtual void glMultMatrixd (const GLdouble *m)\n  {\n    ::glMultMatrixd (m);\n  }\n\n  virtual void glNewList (GLuint list, GLenum mode)\n  {\n    ::glNewList (list, mode);\n  }\n\n  virtual void glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz)\n  {\n    ::glNormal3d (nx, ny, nz);\n  }\n\n  virtual void glNormal3dv (const GLdouble *v)\n  {\n    ::glNormal3dv (v);\n  }\n\n  virtual void glOrtho (GLdouble left, GLdouble right, GLdouble bottom,\n                        GLdouble top, GLdouble near_val, GLdouble far_val)\n  {\n    ::glOrtho (left, right, bottom, top, near_val, far_val);\n  }\n\n  virtual void glPixelStorei (GLenum pname, GLint param)\n  {\n    ::glPixelStorei (pname, param);\n  }\n\n  virtual void glPixelZoom (GLfloat xfactor, GLfloat yfactor)\n  {\n    ::glPixelZoom (xfactor, yfactor);\n  }\n\n  virtual void glPolygonMode (GLenum face, GLenum mode)\n  {\n    ::glPolygonMode (face, mode);\n  }\n\n  virtual void glPolygonOffset (GLfloat factor, GLfloat units)\n  {\n    ::glPolygonOffset (factor, units);\n  }\n\n  virtual void glPopAttrib ()\n  {\n    ::glPopAttrib ();\n  }\n\n  virtual void glPopMatrix ()\n  {\n    ::glPopMatrix ();\n  }\n\n  virtual void glPopName ()\n  {\n    ::glPopName ();\n  }\n\n  virtual void glPushAttrib (GLbitfield mask)\n  {\n    ::glPushAttrib (mask);\n  }\n\n  virtual void glPushMatrix ()\n  {\n    ::glPushMatrix ();\n  }\n\n  virtual void glPushName (GLuint name)\n  {\n    ::glPushName (name);\n  }\n\n  virtual void glRasterPos3d (GLdouble x, GLdouble y, GLdouble z)\n  {\n    ::glRasterPos3d (x, y, z);\n  }\n\n  virtual void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height,\n                             GLenum format, GLenum type, GLvoid *pixels)\n  {\n    ::glReadPixels (x, y, width, height, format, type, pixels);\n  }\n\n  virtual GLint glRenderMode (GLenum mode)\n  {\n    return ::glRenderMode (mode);\n  }\n\n  virtual void glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)\n  {\n    ::glRotated (angle, x, y, z);\n  }\n\n  virtual void glScaled (GLdouble x, GLdouble y, GLdouble z)\n  {\n    ::glScaled (x, y, z);\n  }\n\n  virtual void glScalef (GLfloat x, GLfloat y, GLfloat z)\n  {\n    ::glScalef (x, y, z);\n  }\n\n  virtual void glSelectBuffer (GLsizei size, GLuint *buffer)\n  {\n    ::glSelectBuffer (size, buffer);\n  }\n\n  virtual void glShadeModel (GLenum mode)\n  {\n    ::glShadeModel (mode);\n  }\n\n  virtual void glTexCoord2d (GLdouble s, GLdouble t)\n  {\n    ::glTexCoord2d (s, t);\n  }\n\n  virtual void glTexImage2D (GLenum target, GLint level, GLint internalFormat,\n                             GLsizei width, GLsizei height, GLint border,\n                             GLenum format, GLenum type, const GLvoid *pixels)\n  {\n    ::glTexImage2D (target, level, internalFormat, width, height, border,\n                    format, type, pixels);\n  }\n\n  virtual void glTexParameteri (GLenum target, GLenum pname, GLint param)\n  {\n    ::glTexParameteri (target, pname, param);\n  }\n\n  virtual void glTranslated (GLdouble x, GLdouble y, GLdouble z)\n  {\n    ::glTranslated (x, y, z);\n  }\n\n  virtual void glTranslatef (GLfloat x, GLfloat y, GLfloat z)\n  {\n    ::glTranslatef (x, y, z);\n  }\n\n  virtual void glVertex2d (GLdouble x, GLdouble y)\n  {\n    ::glVertex2d (x, y);\n  }\n\n  virtual void glVertex3d (GLdouble x, GLdouble y, GLdouble z)\n  {\n    ::glVertex3d (x, y, z);\n  }\n\n  virtual void glVertex3dv (const GLdouble *v)\n  {\n    ::glVertex3dv (v);\n  }\n\n  virtual void glViewport (GLint x, GLint y, GLsizei width, GLsizei height)\n  {\n    ::glViewport (x, y, width, height);\n  }\n\n#endif\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-prcstrm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-prcstrm.h\"\n#include \"sysdep.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\noctave::stream\noctave_iprocstream::create (const std::string& n, std::ios::openmode arg_md,\n                            octave::mach_info::float_format ff,\n                            const std::string& encoding)\n{\n  return octave::stream (new octave_iprocstream (n, arg_md, ff, encoding));\n}\n\noctave_iprocstream::octave_iprocstream (const std::string& n,\n                                        std::ios::openmode arg_md,\n                                        octave::mach_info::float_format ff,\n                                        const std::string& encoding)\n  : octave::stdiostream (n, octave::popen (n.c_str (), \"r\"),\n                         arg_md, ff, encoding, octave::pclose)\n{ }\n\noctave_iprocstream::~octave_iprocstream ()\n{\n  do_close ();\n}\n\noctave::stream\noctave_oprocstream::create (const std::string& n, std::ios::openmode arg_md,\n                            octave::mach_info::float_format ff,\n                            const std::string& encoding)\n{\n  return octave::stream (new octave_oprocstream (n, arg_md, ff, encoding));\n}\n\noctave_oprocstream::octave_oprocstream (const std::string& n,\n                                        std::ios::openmode arg_md,\n                                        octave::mach_info::float_format ff,\n                                        const std::string& encoding)\n  : octave::stdiostream (n, octave::popen (n.c_str (), \"w\"),\n                         arg_md, ff, encoding, octave::pclose)\n{ }\n\noctave_oprocstream::~octave_oprocstream ()\n{\n  do_close ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-prcstrm.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_prcstrm_h)\n#define octave_oct_prcstrm_h 1\n\n#include \"octave-config.h\"\n\n#include \"oct-stdstrm.h\"\n\n// FIXME: why don't these classes use iprocstream and oprocstream,\n//        which in turn use the octave_procbuf class?\n\n// Note: Even though these classes are now inside the octave namespace,\n// we can't rename them to iprocstream and oprocstream because we\n// already have classes with those names (see procstream.h).  We need to\n// find a way to resolve this naming issue.\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass octave_iprocstream : public octave::stdiostream\n{\npublic:\n\n  octave_iprocstream (const std::string& n,\n                      std::ios::openmode arg_md = std::ios::in,\n                      octave::mach_info::float_format flt_fmt\n                      = octave::mach_info::native_float_format (),\n                      const std::string& encoding = \"utf-8\");\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (octave_iprocstream)\n\n  static octave::stream\n  create (const std::string& n, std::ios::openmode arg_md = std::ios::in,\n          octave::mach_info::float_format flt_fmt\n          = octave::mach_info::native_float_format (),\n          const std::string& encoding = \"utf-8\");\n\nprotected:\n\n  ~octave_iprocstream ();\n};\n\nclass octave_oprocstream : public octave::stdiostream\n{\npublic:\n\n  octave_oprocstream (const std::string& n,\n                      std::ios::openmode arg_md = std::ios::out,\n                      octave::mach_info::float_format flt_fmt\n                      = octave::mach_info::native_float_format (),\n                      const std::string& encoding = \"utf-8\");\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (octave_oprocstream)\n\n  static octave::stream\n  create (const std::string& n, std::ios::openmode arg_md = std::ios::out,\n          octave::mach_info::float_format flt_fmt\n          = octave::mach_info::native_float_format (),\n          const std::string& encoding = \"utf-8\");\n\nprotected:\n\n  ~octave_oprocstream ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-procbuf.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n#include <cstdlib>\n\n// FIXME: we would prefer to avoid including these directly in Octave\n// sources, but eliminating them is complicated by the mingling of\n// octave_procbuf_list and the calls to system library functions like\n// execl.\n\n#if defined (HAVE_UNISTD_H)\n#  if defined (HAVE_SYS_TYPES_H)\n#    include <sys/types.h>\n#  endif\n#  include <unistd.h>\n#endif\n\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"oct-procbuf.h\"\n#include \"oct-syscalls.h\"\n#include \"sysdep.h\"\n#include \"unistd-wrappers.h\"\n#include \"variables.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if ! defined (SHELL_PATH)\n#  define SHELL_PATH \"/bin/sh\"\n#endif\n\n// This class is based on the procbuf class from libg++, written by\n// Per Bothner, Copyright (C) 1993 Free Software Foundation.\n\n#if (! (defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)) \\\n     && defined (HAVE_UNISTD_H))\n\nstatic procbuf *procbuf_list = nullptr;\n\n#endif\n\n#if ! defined (BUFSIZ)\n#  define BUFSIZ 1024\n#endif\n\nprocbuf *\nprocbuf::open (const char *command, int mode)\n{\n#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)\n\n  if (is_open ())\n    return 0;\n\n  m_f = (octave::popen (command, (mode & std::ios::in) ? \"r\" : \"w\"));\n\n  if (! m_f)\n    return 0;\n\n  // Oops... popen doesn't return the associated pid, so fake it for now\n\n  m_proc_pid = 1;\n\n  m_open_p = true;\n\n  if (mode & std::ios::out)\n    ::setvbuf (m_f, nullptr, _IOLBF, BUFSIZ);\n\n  return this;\n\n#elif defined (HAVE_UNISTD_H)\n\n  int pipe_fds[2];\n\n  int child_std_end = (mode & std::ios::in) ? 1 : 0;\n\n  int parent_end, child_end;\n\n  if (is_open ())\n    return nullptr;\n\n  if (octave::sys::pipe (pipe_fds) < 0)\n    return nullptr;\n\n  if (mode & std::ios::in)\n    {\n      parent_end = pipe_fds[0];\n      child_end = pipe_fds[1];\n    }\n  else\n    {\n      parent_end = pipe_fds[1];\n      child_end = pipe_fds[0];\n    }\n\n  m_proc_pid = ::fork ();\n\n  if (m_proc_pid == 0)\n    {\n      octave_close_wrapper (parent_end);\n\n      if (child_end != child_std_end)\n        {\n          octave_dup2_wrapper (child_end, child_std_end);\n          octave_close_wrapper (child_end);\n        }\n\n      while (procbuf_list)\n        {\n          FILE *fp = procbuf_list->m_f;\n\n          if (fp)\n            {\n              std::fclose (fp);\n              fp = nullptr;\n            }\n\n          procbuf_list = procbuf_list->m_next;\n        }\n\n      execl (SHELL_PATH, \"sh\", \"-c\", command, static_cast<void *> (nullptr));\n\n      std::exit (127);\n    }\n\n  octave_close_wrapper (child_end);\n\n  if (m_proc_pid < 0)\n    {\n      octave_close_wrapper (parent_end);\n      return nullptr;\n    }\n\n  m_f = (::fdopen (parent_end, (mode & std::ios::in) ? \"r\" : \"w\"));\n\n  if (mode & std::ios::out)\n    ::setvbuf (m_f, nullptr, _IOLBF, BUFSIZ);\n\n  m_open_p = true;\n\n  m_next = procbuf_list;\n  procbuf_list = this;\n\n  return this;\n\n#else\n\n  return 0;\n\n#endif\n}\n\nprocbuf *\nprocbuf::close ()\n{\n#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)\n\n  if (m_f)\n    {\n      m_wstatus = octave::pclose (m_f);\n      m_f = 0;\n    }\n\n  m_open_p = false;\n\n  return this;\n\n#elif defined (HAVE_UNISTD_H)\n\n  if (m_f)\n    {\n      pid_t wait_pid;\n\n      int status = -1;\n\n      for (procbuf **ptr = &procbuf_list;\n           *ptr != nullptr;\n           ptr = &(*ptr)->m_next)\n        {\n          if (*ptr == this)\n            {\n              *ptr = (*ptr)->m_next;\n              status = 0;\n              break;\n            }\n        }\n\n      if (status == 0 && std::fclose (m_f) == 0)\n        {\n          using namespace std;\n\n          do\n            {\n              wait_pid = octave::sys::waitpid (m_proc_pid, &m_wstatus, 0);\n            }\n          while (wait_pid == -1 && errno == EINTR);\n        }\n\n      m_f = nullptr;\n    }\n\n  m_open_p = false;\n\n  return this;\n\n#else\n\n  return 0;\n\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-procbuf.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This class is based on the procbuf class from libg++, written by\n// Per Bothner, Copyright (C) 1993 Free Software Foundation.\n\n#if ! defined (octave_oct_procbuf_h)\n#define octave_oct_procbuf_h 1\n\n#include \"octave-config.h\"\n\n#include <sys/types.h>\n\n#include \"c-file-ptr-stream.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass procbuf : public c_file_ptr_buf\n{\npublic:\n\n  procbuf ()\n    : c_file_ptr_buf (nullptr), m_wstatus (-1), m_open_p (false),\n      m_proc_pid (-1), m_next (nullptr)\n  { }\n\n  procbuf (const char *command, int mode)\n    : c_file_ptr_buf (nullptr), m_wstatus (-1), m_open_p (false),\n      m_proc_pid (-1), m_next (nullptr)\n  { open (command, mode); }\n\n  OCTAVE_DISABLE_COPY_MOVE (procbuf)\n\n  ~procbuf () { close (); }\n\n  procbuf * open (const char *command, int mode);\n\n  procbuf * close ();\n\n  int wait_status () const { return m_wstatus; }\n\n  bool is_open () const { return m_open_p; }\n\n  pid_t pid () const { return m_proc_pid; }\n\nprotected:\n\n  int m_wstatus;\n\n  bool m_open_p;\n\n  pid_t m_proc_pid;\n\n  procbuf *m_next;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-process.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#include <iostream>\n#include <sstream>\n\n#include \"oct-process.h\"\n#include \"procstream.h\"\n#include \"sysdep.h\"\n#include \"oct-syscalls.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nprocess_execution_result\nprocess_execution_result::of_success (int exit_status,\n                                      const std::string& stdout_output)\n{\n  return process_execution_result (0, exit_status, stdout_output, \"\");\n}\n\nprocess_execution_result\nprocess_execution_result::of_error (int status, const std::string& err_msg)\n{\n  return process_execution_result (status, -1, \"\", err_msg);\n}\n\n// Execute a shell command, returning results as a C++ object\nprocess_execution_result\nrun_command_and_return_output (const std::string& cmd_str)\n{\n  iprocstream cmd (cmd_str.c_str ());\n\n  if (! cmd)\n    {\n      std::string msg = \"unable to start subprocess for '\" + cmd_str + \"'\";\n\n      return process_execution_result::of_error (-1, msg);\n    }\n\n  std::ostringstream output_buf;\n\n  char ch;\n\n  for (;;)\n    {\n      if (cmd.get (ch))\n        output_buf.put (ch);\n      else\n        {\n          if (! cmd.eof () && errno == EAGAIN)\n            cmd.clear ();\n          else\n            break;\n        }\n    }\n\n  int cmd_status = cmd.close ();\n\n  if (sys::wifexited (cmd_status))\n    cmd_status = sys::wexitstatus (cmd_status);\n  else\n    cmd_status = 127;\n\n  return process_execution_result::of_success (cmd_status, output_buf.str ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-process.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (oct_process_h)\n#define oct_process_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass process_execution_result\n{\npublic:\n\n  process_execution_result ()\n    : m_status (-1), m_err_msg (), m_exit_status (-1), m_stdout_output ()\n  { }\n\n  process_execution_result (int status, int exit_status,\n                            const std::string& stdout_output,\n                            const std::string& err_msg)\n    : m_status (status), m_err_msg (err_msg), m_exit_status (exit_status),\n      m_stdout_output (stdout_output)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (process_execution_result)\n\n  static OCTINTERP_API process_execution_result\n  of_success (int exit_status, const std::string& stdout_output);\n\n  static OCTINTERP_API process_execution_result\n  of_error (int status, const std::string& err_msg);\n\n  int status () const { return m_status; }\n\n  int exit_status () const { return m_exit_status; }\n\n  std::string err_msg () const { return m_err_msg; }\n\n  std::string stdout_output () const { return m_stdout_output; }\n\nprivate:\n\n  // Launch status of the process, 0 for success, nonzero for error.\n  int m_status;\n\n  // Error message if executing command failed.\n  std::string m_err_msg;\n\n  // Exit status of the process.\n  int m_exit_status;\n\n  // Collected stdout output of the process.\n  std::string m_stdout_output;\n};\n\nextern OCTINTERP_API process_execution_result\nrun_command_and_return_output (const std::string& cmd_str);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-rl-edit.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (USE_READLINE)\n\n#include <stdio.h>\n#include <stdlib.h>\n\n#include <readline/readline.h>\n\n#include \"oct-rl-edit.h\"\n\n#define OCTAVE_RL_SAVE_STRING(ss, s) \\\n  static char *ss = 0; \\\n \\\n  if (ss) \\\n    { \\\n      free (ss); \\\n      ss = 0; \\\n    } \\\n \\\n  ss = malloc (strlen (s) + 1); \\\n \\\n  if (ss) \\\n    strcpy (ss, s)\n\nvoid\noctave_rl_redisplay (void)\n{\n  rl_redisplay ();\n}\n\nint\noctave_rl_screen_height (void)\n{\n  int rows, cols;\n  rl_get_screen_size (&rows, &cols);\n  return rows;\n}\n\nint\noctave_rl_screen_width (void)\n{\n  int rows, cols;\n  rl_get_screen_size (&rows, &cols);\n  return cols;\n}\n\nvoid\noctave_rl_enable_paren_matching (int val)\n{\n  rl_variable_bind (\"blink-matching-paren\", val ? \"1\" : \"0\");\n}\n\nint\noctave_rl_erase_empty_line (int val)\n{\n  int retval = rl_erase_empty_line;\n  rl_erase_empty_line = val;\n  return retval;\n}\n\n/* It would be much simpler if we could just call _rl_clear_screen to\n   only clear the screen, but it is not a public function, and on some\n   systems, it is not exported from shared library versions of\n   readline, so we can't use it.\n\n   Instead, temporarily redefine the redisplay function to do nothing.\n\n   FIXME: It would be safer to do this when protected from interrupts... */\n\nstatic void\nflush_stdout (void)\n{\n  fflush (stdout);\n}\n\nvoid\noctave_rl_clear_screen (int skip_redisplay)\n{\n  int ignore1 = 0;\n  int ignore2 = 0;\n\n  if (skip_redisplay)\n    {\n      rl_voidfunc_t *saved_redisplay_function = rl_redisplay_function;\n\n      rl_redisplay_function = flush_stdout;\n\n      rl_clear_screen (ignore1, ignore2);\n\n      rl_redisplay_function = saved_redisplay_function;\n    }\n  else\n    rl_clear_screen (ignore1, ignore2);\n}\n\nvoid\noctave_rl_resize_terminal (void)\n{\n  rl_resize_terminal ();\n}\n\nvoid\noctave_rl_set_screen_size (int ht, int wd)\n{\n  rl_set_screen_size (ht, wd);\n}\n\nvoid\noctave_rl_restore_terminal_state (void)\n{\n  if (rl_deprep_term_function)\n    rl_deprep_term_function ();\n}\n\nchar *\noctave_rl_copy_line (void)\n{\n  return rl_copy_text (0, rl_end);\n}\n\nvoid\noctave_rl_replace_line (const char *s, int clear_undo)\n{\n  rl_replace_line (s, clear_undo);\n}\n\nvoid\noctave_rl_kill_full_line (void)\n{\n  rl_kill_full_line (0, 0);\n}\n\nvoid\noctave_rl_insert_text (const char *s)\n{\n  rl_insert_text (s);\n}\n\nint\noctave_rl_newline (int count, int key)\n{\n  return rl_newline (count, key);\n}\n\nconst char *\noctave_rl_line_buffer (void)\n{\n  return rl_line_buffer;\n}\n\nint\noctave_rl_point (void)\n{\n  return rl_point;\n}\n\nint\noctave_rl_do_undo (void)\n{\n  return rl_do_undo ();\n}\n\nvoid\noctave_rl_clear_undo_list (void)\n{\n  if (rl_undo_list)\n    {\n      rl_free_undo_list ();\n\n      rl_undo_list = 0;\n    }\n}\n\nvoid\noctave_rl_set_name (const char *n)\n{\n  OCTAVE_RL_SAVE_STRING (nm, n);\n\n  rl_readline_name = nm;\n\n  /* Since we've already called rl_initialize, we need to re-read the\n     init file to take advantage of the conditional parsing feature\n     based on rl_readline_name; */\n\n  rl_re_read_init_file (0, 0);\n}\n\nchar *\noctave_rl_readline (const char *prompt)\n{\n  return readline (prompt);\n}\n\nvoid\noctave_rl_set_input_stream (FILE *f)\n{\n  rl_instream = f;\n}\n\nFILE *\noctave_rl_get_input_stream (void)\n{\n  return rl_instream;\n}\n\nvoid\noctave_rl_set_output_stream (FILE *f)\n{\n  rl_outstream = f;\n}\n\nFILE *\noctave_rl_get_output_stream (void)\n{\n  return rl_outstream;\n}\n\nvoid\noctave_rl_read_init_file (const char *f)\n{\n  rl_read_init_file (f);\n}\n\nvoid\noctave_rl_re_read_init_file (void)\n{\n  rl_re_read_init_file (0, 0);\n}\n\nint\noctave_rl_filename_completion_desired (int arg)\n{\n  int retval = rl_filename_completion_desired;\n  rl_filename_completion_desired = arg;\n  return retval;\n}\n\nint\noctave_rl_filename_quoting_desired (int arg)\n{\n  int retval = rl_filename_quoting_desired;\n  rl_filename_quoting_desired = arg;\n  return retval;\n}\n\nint\noctave_rl_prefer_env_winsize (int arg)\n{\n  int retval = rl_prefer_env_winsize;\n  rl_prefer_env_winsize = arg;\n  return retval;\n}\n\nvoid\noctave_rl_done (int arg)\n{\n  rl_done = arg;\n}\n\nchar *\noctave_rl_filename_completion_function (const char *text, int state)\n{\n  return rl_filename_completion_function (text, state);\n}\n\nvoid\noctave_rl_set_basic_word_break_characters (const char *s)\n{\n  OCTAVE_RL_SAVE_STRING (ss, s);\n\n  rl_basic_word_break_characters = ss;\n}\n\nvoid\noctave_rl_set_completer_word_break_characters (const char *s)\n{\n  OCTAVE_RL_SAVE_STRING (ss, s);\n\n  rl_completer_word_break_characters = ss;\n}\n\nconst char *\noctave_rl_get_completer_word_break_characters (void)\n{\n  return rl_completer_word_break_characters;\n}\n\nvoid\noctave_rl_set_completion_word_break_hook (rl_completion_hook_fcn_ptr f)\n{\n  rl_completion_word_break_hook = f;\n}\n\nvoid\noctave_rl_set_basic_quote_characters (const char *s)\n{\n  OCTAVE_RL_SAVE_STRING (ss, s);\n\n  rl_basic_quote_characters = ss;\n}\n\nvoid\noctave_rl_set_filename_quote_characters (const char *s)\n{\n  OCTAVE_RL_SAVE_STRING (ss, s);\n\n  rl_filename_quote_characters = ss;\n}\n\nvoid\noctave_rl_set_completer_quote_characters (const char *s)\n{\n  OCTAVE_RL_SAVE_STRING (ss, s);\n\n  rl_completer_quote_characters = ss;\n}\n\nvoid\noctave_rl_set_completion_append_character (char c)\n{\n  rl_completion_append_character = c;\n}\n\nvoid\noctave_rl_set_completion_function (rl_attempted_completion_fcn_ptr f)\n{\n  rl_attempted_completion_function = f;\n}\n\nvoid\noctave_rl_set_quoting_function (rl_quoting_fcn_ptr f)\n{\n  rl_filename_quoting_function = f;\n}\n\nvoid\noctave_rl_set_dequoting_function (rl_dequoting_fcn_ptr f)\n{\n  rl_filename_dequoting_function = f;\n}\n\nvoid\noctave_rl_set_char_is_quoted_function (rl_char_is_quoted_fcn_ptr f)\n{\n  rl_char_is_quoted_p = f;\n}\n\nvoid\noctave_rl_set_startup_hook (rl_startup_hook_fcn_ptr f)\n{\n  rl_startup_hook = f;\n}\n\nrl_startup_hook_fcn_ptr\noctave_rl_get_startup_hook (void)\n{\n  return rl_startup_hook;\n}\n\nvoid\noctave_rl_set_pre_input_hook (rl_pre_input_hook_fcn_ptr f)\n{\n  rl_pre_input_hook = f;\n}\n\nrl_pre_input_hook_fcn_ptr\noctave_rl_get_pre_input_hook (void)\n{\n  return rl_pre_input_hook;\n}\n\nvoid\noctave_rl_set_event_hook (rl_event_hook_fcn_ptr f)\n{\n  rl_event_hook = f;\n}\n\nrl_event_hook_fcn_ptr\noctave_rl_get_event_hook (void)\n{\n  return rl_event_hook;\n}\n\nchar **\noctave_rl_completion_matches (const char *text, rl_completer_fcn_ptr f)\n{\n  return rl_completion_matches (text, f);\n}\n\nchar\noctave_rl_prompt_start_ignore (void)\n{\n  return RL_PROMPT_START_IGNORE;\n}\n\nchar\noctave_rl_prompt_end_ignore (void)\n{\n  return RL_PROMPT_END_IGNORE;\n}\n\nvoid\noctave_rl_add_defun (const char *name, rl_fcn_ptr f, int key)\n{\n  rl_add_defun (name, f, key);\n}\n\nvoid\noctave_rl_set_terminal_name (const char *term)\n{\n  OCTAVE_RL_SAVE_STRING (saved_term, term);\n\n  rl_terminal_name = saved_term;\n}\n\nvoid\noctave_rl_initialize (void)\n{\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n  rl_catch_signals = 0;\n#endif\n\n  rl_initialize ();\n}\n\nint\noctave_rl_history_search_forward (int count, int ignore)\n{\n  return rl_history_search_forward (count, ignore);\n}\n\nint\noctave_rl_history_search_backward (int count, int ignore)\n{\n  return rl_history_search_backward (count, ignore);\n}\n\nint\noctave_rl_ctrl (char c)\n{\n  return CTRL (c);\n}\n\nint\noctave_rl_meta (char c)\n{\n  return META (c);\n}\n\nvoid\noctave_rl_recover_from_interrupt (void)\n{\n  rl_free_line_state ();\n  rl_cleanup_after_signal ();\n  rl_reset_after_signal ();\n}\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-rl-edit.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_rl_edit_h)\n#define octave_oct_rl_edit_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\n#  include <cstdio>\n#else\n#  include <stdio.h>\n#endif\n\ntypedef int (*rl_startup_hook_fcn_ptr) (void);\n\ntypedef int (*rl_pre_input_hook_fcn_ptr) (void);\n\ntypedef int (*rl_event_hook_fcn_ptr) (void);\n\ntypedef int (*rl_fcn_ptr) (int, int);\n\ntypedef char ** (*rl_attempted_completion_fcn_ptr) (const char *, int, int);\n\ntypedef char * (*rl_completer_fcn_ptr) (const char *, int);\n\ntypedef char * (*rl_completion_hook_fcn_ptr) (void);\n\ntypedef char * (*rl_quoting_fcn_ptr) (char *, int, char *);\n\ntypedef char * (*rl_dequoting_fcn_ptr) (char *, int);\n\ntypedef int (*rl_char_is_quoted_fcn_ptr) (char *, int);\n\ntypedef int (*rl_command_fcn_ptr) (int, int);\n\n#if defined (__cplusplus)\nextern \"C\"\n{\n#endif\n\nextern void octave_rl_redisplay (void);\n\nextern int octave_rl_screen_height (void);\n\nextern int octave_rl_screen_width (void);\n\nextern void octave_rl_enable_paren_matching (int);\n\nextern int octave_rl_erase_empty_line (int);\n\nextern void octave_rl_clear_screen (int skip_redisplay);\n\nextern void octave_rl_resize_terminal (void);\n\nextern void octave_rl_resize_terminal (void);\n\nextern void octave_rl_set_screen_size (int ht, int wd);\n\nextern void octave_rl_restore_terminal_state (void);\n\nextern char * octave_rl_copy_line (void);\n\nextern void octave_rl_replace_line (const char *s, int clear_undo);\n\nextern void octave_rl_kill_full_line (void);\n\nextern void octave_rl_insert_text (const char *);\n\nextern int octave_rl_newline (int, int);\n\nextern const char * octave_rl_line_buffer (void);\n\nextern int octave_rl_point (void);\n\nextern int octave_rl_do_undo (void);\n\nextern void octave_rl_clear_undo_list (void);\n\nextern void octave_rl_set_name (const char *);\n\nextern char * octave_rl_readline (const char *);\n\nextern void octave_rl_set_input_stream (FILE *);\n\nextern FILE * octave_rl_get_input_stream (void);\n\nextern void octave_rl_set_output_stream (FILE *);\n\nextern FILE * octave_rl_get_output_stream (void);\n\nextern void octave_rl_read_init_file (const char *);\n\nextern void octave_rl_re_read_init_file (void);\n\nextern int octave_rl_filename_completion_desired (int);\n\nextern int octave_rl_filename_quoting_desired (int);\n\nextern int octave_rl_prefer_env_winsize (int);\n\nextern void octave_rl_done (int);\n\nextern char * octave_rl_filename_completion_function (const char *, int);\n\nextern void octave_rl_set_basic_word_break_characters (const char *);\n\nextern void octave_rl_set_completer_word_break_characters (const char *);\n\nextern const char * octave_rl_get_completer_word_break_characters (void);\n\nextern void octave_rl_set_completion_word_break_hook (rl_completion_hook_fcn_ptr);\n\nextern void octave_rl_set_basic_quote_characters (const char *);\n\nextern void octave_rl_set_filename_quote_characters (const char *);\n\nextern void octave_rl_set_completer_quote_characters (const char *);\n\nextern void octave_rl_set_completion_append_character (char);\n\nextern void\noctave_rl_set_completion_function (rl_attempted_completion_fcn_ptr);\n\nextern void\noctave_rl_set_quoting_function (rl_quoting_fcn_ptr);\n\nextern void\noctave_rl_set_dequoting_function (rl_dequoting_fcn_ptr);\n\nextern void octave_rl_set_char_is_quoted_function (rl_char_is_quoted_fcn_ptr);\n\nextern void octave_rl_set_startup_hook (rl_startup_hook_fcn_ptr);\n\nextern rl_startup_hook_fcn_ptr octave_rl_get_startup_hook (void);\n\nextern void octave_rl_set_pre_input_hook (rl_startup_hook_fcn_ptr);\n\nextern rl_pre_input_hook_fcn_ptr octave_rl_get_pre_input_hook (void);\n\nextern void octave_rl_set_event_hook (rl_event_hook_fcn_ptr f);\n\nextern rl_event_hook_fcn_ptr octave_rl_get_event_hook (void);\n\nextern char **\noctave_rl_completion_matches (const char *, rl_completer_fcn_ptr);\n\nextern char octave_rl_prompt_start_ignore (void);\n\nextern char octave_rl_prompt_end_ignore (void);\n\nextern void octave_rl_add_defun (const char *, rl_fcn_ptr, int);\n\nextern void octave_rl_set_terminal_name (const char *);\n\nextern void octave_rl_initialize (void);\n\nextern int octave_rl_history_search_forward (int, int);\n\nextern int octave_rl_history_search_backward (int, int);\n\nextern int octave_rl_ctrl (char);\n\nextern int octave_rl_meta (char);\n\nextern void octave_rl_recover_from_interrupt (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-rl-hist.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-rl-hist.h\"\n\n#if defined (USE_READLINE)\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <readline/history.h>\n\n/* check_history_control, hc_erasedup, and the core of\n   octave_add_history were borrowed from Bash.  */\n\n/* Check LINE against what HISTCONTROL says to do.  Returns 1 if the line\n   should be saved; 0 if it should be discarded.  */\nstatic int\ncheck_history_control (const char *line, int history_control)\n{\n  HIST_ENTRY *temp;\n  int r;\n\n  if (history_control == 0)\n    return 1;\n\n  /* ignorespace or ignoreboth */\n  if ((history_control & HC_IGNSPACE) && *line == ' ')\n    return 0;\n\n  /* ignoredups or ignoreboth */\n  if (history_control & HC_IGNDUPS)\n    {\n      using_history ();\n      temp = previous_history ();\n\n      r = (temp == 0 || strcmp (temp->line, line));\n\n      using_history ();\n\n      if (r == 0)\n        return r;\n    }\n\n  return 1;\n}\n\n/* Remove all entries matching LINE from the history list.  Triggered when\n   HISTCONTROL includes 'erasedups'.  */\n\nstatic void\nhc_erasedups (const char *line)\n{\n  HIST_ENTRY *temp;\n  int r;\n\n  using_history ();\n  while ((temp = previous_history ()))\n    {\n      if (! strcmp (temp->line, line))\n        {\n          r = where_history ();\n          remove_history (r);\n        }\n    }\n  using_history ();\n}\n\n/* Check LINE against HISTCONTROL and add it to the history if it's OK.\n   Returns 1 if the line was saved in the history, 0 otherwise.  */\n\nint\noctave_add_history (const char *line, int history_control)\n{\n  if (check_history_control (line, history_control))\n    {\n      /* We're committed to saving the line.  If the user has requested it,\n         remove other matching lines from the history.  */\n\n      if (history_control & HC_ERASEDUPS)\n        hc_erasedups (line);\n\n      add_history (line);\n\n      return 1;\n    }\n\n  return 0;\n}\n\nint\noctave_where_history (void)\n{\n  return where_history ();\n}\n\nint\noctave_history_length (void)\n{\n  return history_length;\n}\n\nint\noctave_max_input_history (void)\n{\n  return max_input_history;\n}\n\nint\noctave_history_base (void)\n{\n  return history_base;\n}\n\nvoid\noctave_stifle_history (int n)\n{\n  stifle_history (n);\n}\n\nint\noctave_unstifle_history (void)\n{\n  return unstifle_history ();\n}\n\nint\noctave_history_is_stifled (void)\n{\n  return history_is_stifled ();\n}\n\nint\noctave_history_set_pos (int n)\n{\n  return history_set_pos (n);\n}\n\nint\noctave_read_history (const char *f)\n{\n  return read_history (f);\n}\n\nvoid\noctave_using_history (void)\n{\n  using_history ();\n}\n\nint\noctave_read_history_range (const char *f, int b, int e)\n{\n  return read_history_range (f, b, e);\n}\n\nint\noctave_write_history (const char *f)\n{\n  return write_history (f);\n}\n\nint\noctave_append_history (int n, const char *f)\n{\n  return append_history (n, f);\n}\n\nint\noctave_history_truncate_file (const char *f, int n)\n{\n  return history_truncate_file (f, n);\n}\n\nvoid\noctave_remove_history (int n)\n{\n  HIST_ENTRY *discard = remove_history (n);\n\n  if (discard)\n    free (discard->line);\n\n  free (discard);\n}\n\nvoid\noctave_clear_history (void)\n{\n  clear_history ();\n}\n\nchar *\noctave_history_goto_mark (int n)\n{\n  HIST_ENTRY *h;\n\n  char *retval = 0;\n\n  if (history_set_pos (n))\n    {\n      h = current_history ();\n\n      if (h)\n        retval = h->line;\n    }\n\n  return retval;\n}\n\nchar *\noctave_history_get (int n)\n{\n  char *retval = 0;\n\n  HIST_ENTRY *h = history_get (n);\n\n  if (h)\n    retval = h->line;\n\n  return retval;\n}\n\nchar **\noctave_history_list (int limit, int number_lines)\n{\n  static char **retval = 0;\n\n  HIST_ENTRY **hlist = 0;\n\n  if (retval)\n    {\n      char **p = retval;\n\n      while (*p)\n        free (*p++);\n\n      free (retval);\n\n      retval = 0;\n    }\n\n  hlist = history_list ();\n\n  if (hlist)\n    {\n      int i, k;\n\n      int beg = 0;\n      int end = 0;\n      while (hlist[end])\n        end++;\n\n      beg = (limit < 0 || end < limit) ? 0 : (end - limit);\n\n      retval = malloc ((size_t) (end - beg + 1) * sizeof (char *));\n      // FIXME: Should this call current_liboctave_error_handler instead?\n      if (! retval)\n        return retval;\n\n      k = 0;\n      for (i = beg; i < end; i++)\n        {\n          char *line = hlist[i]->line;\n          size_t len = line ? strlen (line) : 0;\n          char *tmp = malloc (len + 64);\n\n          if (tmp)\n            {\n              if (number_lines)\n                sprintf (tmp, \"%5d %s\", i + history_base,\n                         line ? line : \"\");\n              else\n                strcpy (tmp, line ? line : \"\");\n\n              retval[k++] = tmp;\n            }\n        }\n\n      retval[k] = 0;\n    }\n\n  return retval;\n}\n\nvoid\noctave_replace_history_entry (int which, const char *line)\n{\n  HIST_ENTRY *discard = replace_history_entry (which, line, 0);\n\n  if (discard)\n    free (discard->line);\n\n  free (discard);\n}\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-rl-hist.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_rl_hist_h)\n#define octave_oct_rl_hist_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\nextern \"C\"\n{\n#endif\n\nenum\n{\n  HC_IGNSPACE = 0x01,\n  HC_IGNDUPS = 0x02,\n  HC_ERASEDUPS = 0x04\n};\n\nextern int octave_add_history (const char *, int);\n\nextern int octave_where_history (void);\n\nextern int octave_history_length (void);\n\nextern int octave_max_input_history (void);\n\nextern int octave_history_base (void);\n\nextern void octave_stifle_history (int);\n\nextern int octave_unstifle_history (void);\n\nextern int octave_history_is_stifled (void);\n\nextern int octave_history_set_pos (int);\n\nextern int octave_read_history (const char *);\n\nextern void octave_using_history (void);\n\nextern int octave_read_history_range (const char *, int, int);\n\nextern int octave_write_history (const char *);\n\nextern int octave_append_history (int, const char *);\n\nextern int octave_history_truncate_file (const char *, int);\n\nextern void octave_remove_history (int);\n\nextern void octave_clear_history (void);\n\nextern char * octave_history_goto_mark (int n);\n\nextern char * octave_history_get (int n);\n\nextern char ** octave_history_list (int, int);\n\nextern void octave_replace_history_entry (int, const char *);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-stdstrm.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_stdstrm_h)\n#define octave_oct_stdstrm_h 1\n\n#include \"octave-config.h\"\n\n#include <iomanip>\n\n#include \"oct-stream.h\"\n#include \"c-file-ptr-stream.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename BUF_T, typename STREAM_T, typename FILE_T>\nclass tstdiostream : public base_stream\n{\npublic:\n\n  tstdiostream (const std::string& n, FILE_T f = 0, int fid = 0,\n                std::ios::openmode m = std::ios::in | std::ios::out,\n                mach_info::float_format ff = mach_info::native_float_format (),\n                const std::string& encoding = \"utf-8\",\n                typename BUF_T::close_fcn cf = BUF_T::file_close)\n    : base_stream (m, ff, encoding), m_name (n), m_mode (m),\n      m_stream (f ? new STREAM_T (f, cf) : nullptr), m_fnum (fid)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tstdiostream)\n\n  // Position a stream at OFFSET relative to ORIGIN.\n\n  int seek (off_t offset, int origin)\n  {\n    return m_stream ? m_stream->seek (offset, origin) : -1;\n  }\n\n  // Return current stream position.\n\n  off_t tell () { return m_stream ? m_stream->tell () : -1; }\n\n  // Return nonzero if EOF has been reached on this stream.\n\n  bool eof () const { return m_stream ? m_stream->eof () : true; }\n\n  // The name of the file.\n\n  std::string name () const { return m_name; }\n\n  std::istream * input_stream ()\n  {\n    return (m_mode & std::ios::in) ? m_stream : nullptr;\n  }\n\n  std::ostream * output_stream ()\n  {\n    return (m_mode & std::ios::out) ? m_stream : nullptr;\n  }\n\n  // FIXME: should not have to cast away const here.\n  BUF_T * rdbuf () const\n  {\n    return m_stream ? (const_cast<STREAM_T *> (m_stream))->rdbuf () : nullptr;\n  }\n\n  int file_number () const { return m_fnum; }\n\n  bool bad () const { return m_stream ? m_stream->bad () : true; }\n\n  void clear ()\n  {\n    if (m_stream)\n      m_stream->clear ();\n  }\n\n  void do_close ()\n  {\n    if (m_stream)\n      m_stream->stream_close ();\n  }\n\nprotected:\n\n  ~tstdiostream () { delete m_stream; }\n\n  //--------\n\n  std::string m_name;\n\n  std::ios::openmode m_mode;\n\n  STREAM_T *m_stream;\n\n  // The file number associated with this file.\n  int m_fnum;\n};\n\nclass stdiostream\n  : public tstdiostream<c_file_ptr_buf, io_c_file_ptr_stream, FILE *>\n{\npublic:\n\n  stdiostream (const std::string& n, FILE *f = nullptr,\n               std::ios::openmode m = std::ios::in | std::ios::out,\n               mach_info::float_format ff = mach_info::native_float_format (),\n               const std::string& encoding = \"utf-8\",\n               c_file_ptr_buf::close_fcn cf = c_file_ptr_buf::file_close)\n    : tstdiostream<c_file_ptr_buf, io_c_file_ptr_stream, FILE *>\n      (n, f, f ? fileno (f) : -1, m, ff, encoding, cf) { }\n\n  static stream\n  create (const std::string& n, FILE *f = nullptr,\n          std::ios::openmode m = std::ios::in | std::ios::out,\n          mach_info::float_format ff = mach_info::native_float_format (),\n          const std::string& encoding = \"utf-8\",\n          c_file_ptr_buf::close_fcn cf = c_file_ptr_buf::file_close)\n  {\n    return stream (new stdiostream (n, f, m, ff, encoding, cf));\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (stdiostream)\n\nprotected:\n\n  ~stdiostream () = default;\n};\n\n#if defined (HAVE_ZLIB)\n\nclass zstdiostream\n  : public tstdiostream<c_zfile_ptr_buf, io_c_zfile_ptr_stream, gzFile>\n{\npublic:\n\n  zstdiostream (const std::string& n, gzFile f = nullptr, int fid = 0,\n                std::ios::openmode m = std::ios::in | std::ios::out,\n                mach_info::float_format ff = mach_info::native_float_format (),\n                const std::string& encoding = \"utf-8\",\n                c_zfile_ptr_buf::close_fcn cf = c_zfile_ptr_buf::file_close)\n    : tstdiostream<c_zfile_ptr_buf, io_c_zfile_ptr_stream, gzFile>\n      (n, f, fid, m, ff, encoding, cf) { }\n\n  static stream\n  create (const std::string& n, gzFile f = nullptr, int fid = 0,\n          std::ios::openmode m = std::ios::in | std::ios::out,\n          mach_info::float_format ff = mach_info::native_float_format (),\n          const std::string& encoding = \"utf-8\",\n          c_zfile_ptr_buf::close_fcn cf = c_zfile_ptr_buf::file_close)\n  {\n    return stream (new zstdiostream (n, f, fid, m, ff, encoding, cf));\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (zstdiostream)\n\nprotected:\n\n  ~zstdiostream () = default;\n};\n\n#endif\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-stream.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cctype>\n#include <cstring>\n\n#include <algorithm>\n#include <deque>\n#include <limits>\n#include <iomanip>\n#include <iostream>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"Array.h\"\n#include \"Cell.h\"\n#include \"byte-swap.h\"\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"oct-locbuf.h\"\n#include \"octave-preserve-stream-state.h\"\n#include \"quit.h\"\n#include \"str-vec.h\"\n#include \"strcase-wrappers.h\"\n\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"octave.h\"\n#include \"oct-iostrm.h\"\n#include \"oct-stdstrm.h\"\n#include \"oct-string.h\"\n#include \"oct-stream.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Programming Note: There are two very different error functions used\n// in the stream code.  When invoked with \"error (...)\" the member\n// function from stream or base_stream is called.  This\n// function sets the error state on the stream AND returns control to\n// the caller.  The caller must then return a value at the end of the\n// function.  When invoked with \"::error (...)\" the exception-based\n// error function from error.h is used.  This function will throw an\n// exception and not return control to the caller.  BE CAREFUL and\n// invoke the correct error function!\n\n// Possible values for conv_err:\n//\n//   1 : not a real scalar\n//   2 : value is NaN\n//   3 : value is not an integer\n\nstatic int\nconvert_to_valid_int (const octave_value& tc, int& conv_err)\n{\n  conv_err = 0;\n\n  int retval = 0;\n\n  double dval = 0.0;\n\n  try\n    {\n      dval = tc.double_value ();\n    }\n  catch (const execution_exception&)\n    {\n      interpreter& interp = __get_interpreter__ ();\n\n      interp.recover_from_exception ();\n\n      conv_err = 1;\n    }\n\n  if (! conv_err)\n    {\n      if (! math::isnan (dval))\n        {\n          int ival = math::nint (dval);\n\n          if (ival == dval)\n            retval = ival;\n          else\n            conv_err = 3;\n        }\n      else\n        conv_err = 2;\n    }\n\n  return retval;\n}\n\nstatic octave_idx_type\nget_size (double d, const std::string& who)\n{\n  octave_idx_type retval = -1;\n\n  if (math::isnan (d))\n    ::error (\"%s: NaN invalid as size specification\", who.c_str ());\n\n  if (math::isinf (d))\n    retval = -1;\n  else\n    {\n      if (d < 0.0)\n        ::error (\"%s: negative value invalid as size specification\",\n                 who.c_str ());\n\n      static constexpr double out_of_range_top\n        = static_cast<double> (std::numeric_limits<octave_idx_type>::max ()) + 1.0;\n      if (d >= out_of_range_top)\n        ::error (\"%s: dimension too large for Octave's index type\",\n                 who.c_str ());\n\n      retval = math::nint_big (d);\n    }\n\n  return retval;\n}\n\nstatic void\nget_size (const Array<double>& size,\n          octave_idx_type& nr, octave_idx_type& nc,\n          bool& one_elt_size_spec, const std::string& who)\n{\n  nr = -1;\n  nc = -1;\n\n  one_elt_size_spec = false;\n\n  double dnr = -1.0;\n  double dnc = -1.0;\n\n  octave_idx_type sz_len = size.numel ();\n\n  if (sz_len == 1)\n    {\n      one_elt_size_spec = true;\n\n      dnr = size(0);\n\n      dnc = (dnr == 0.0) ? 0.0 : 1.0;\n    }\n  else if (sz_len == 2)\n    {\n      dnr = size(0);\n\n      if (math::isinf (dnr))\n        ::error (\"%s: infinite value invalid as size specification\",\n                 who.c_str ());\n\n      dnc = size(1);\n    }\n  else\n    ::error (\"%s: invalid size specification (must be 2-D)\", who.c_str ());\n\n  nr = get_size (dnr, who);\n\n  if (dnc >= 0.0)\n    {\n      nc = get_size (dnc, who);\n\n      // Check for overflow.\n      if (nr > 0 && nc > 0\n          && nc > std::numeric_limits<octave_idx_type>::max () / nr)\n        ::error (\"%s: size too large for Octave's index type\", who.c_str ());\n    }\n}\n\nstatic std::string\nexpand_char_class (const std::string& s)\n{\n  std::string retval;\n\n  std::size_t len = s.length ();\n\n  std::size_t i = 0;\n\n  while (i < len)\n    {\n      unsigned char c = s[i++];\n\n      if (c == '-' && i > 1 && i < len\n          && (   static_cast<unsigned char> (s[i-2])\n                 <= static_cast<unsigned char> (s[i])))\n        {\n          // Add all characters from the range except the first (we\n          // already added it below).\n\n          for (c = s[i-2]+1; c < s[i]; c++)\n            retval += c;\n        }\n      else\n        {\n          // Add the character to the class.  Only add '-' if it is\n          // the last character in the class.\n\n          if (c != '-' || i == len)\n            retval += c;\n        }\n    }\n\n  return retval;\n}\n\nclass scanf_format_elt\n{\npublic:\n\n  enum special_conversion\n  {\n    whitespace_conversion = 1,\n    literal_conversion = 2,\n    null = 3\n  };\n\n  scanf_format_elt (const std::string& txt = \"\", int w = 0, bool d = false,\n                    char typ = '\\0', char mod = '\\0',\n                    const std::string& ch_class = \"\")\n    : text (txt), width (w), discard (d), type (typ),\n      modifier (mod), char_class (ch_class)\n  { }\n\n  scanf_format_elt (const scanf_format_elt&) = default;\n\n  scanf_format_elt& operator = (const scanf_format_elt&) = default;\n\n  ~scanf_format_elt () = default;\n\n  // The C-style format string.\n  std::string text;\n\n  // The maximum field width.\n  int width;\n\n  // TRUE if we are not storing the result of this conversion.\n  bool discard;\n\n  // Type of conversion -- 'd', 'i', 'o', 'u', 'x', 'e', 'f', 'g',\n  // 'c', 's', 'p', '%', or '['.\n  char type;\n\n  // A length modifier -- 'h', 'l', or 'L'.\n  char modifier;\n\n  // The class of characters in a '[' format.\n  std::string char_class;\n};\n\nclass scanf_format_list\n{\npublic:\n\n  scanf_format_list (const std::string& fmt = \"\");\n\n  OCTAVE_DISABLE_COPY_MOVE (scanf_format_list)\n\n  ~scanf_format_list ();\n\n  octave_idx_type num_conversions () { return m_nconv; }\n\n  // The length can be different than the number of conversions.\n  // For example, \"x %d y %d z\" has 2 conversions but the length of\n  // the list is 3 because of the characters that appear after the\n  // last conversion.\n\n  std::size_t length () const { return m_fmt_elts.size (); }\n\n  const scanf_format_elt * first ()\n  {\n    m_curr_idx = 0;\n    return current ();\n  }\n\n  const scanf_format_elt * current () const\n  {\n    return length () > 0 ? m_fmt_elts[m_curr_idx] : nullptr;\n  }\n\n  const scanf_format_elt * next (bool cycle = true)\n  {\n    static scanf_format_elt dummy\n      (\"\", 0, false, scanf_format_elt::null, '\\0', \"\");\n\n    m_curr_idx++;\n\n    if (m_curr_idx >= length ())\n      {\n        if (cycle)\n          m_curr_idx = 0;\n        else\n          return &dummy;\n      }\n\n    return current ();\n  }\n\n  void printme () const;\n\n  bool ok () const { return (m_nconv >= 0); }\n\n  operator bool () const { return ok (); }\n\n  bool all_character_conversions ();\n\n  bool all_numeric_conversions ();\n\nprivate:\n\n  void add_elt_to_list (int width, bool discard, char type, char modifier,\n                        const std::string& char_class = \"\");\n\n  void process_conversion (const std::string& s, std::size_t& i,\n                           std::size_t n, int& width, bool& discard,\n                           char& type, char& modifier);\n\n  int finish_conversion (const std::string& s, std::size_t& i, std::size_t n,\n                         int width, bool discard, char& type,\n                         char modifier);\n\n  //--------\n\n  // Number of conversions specified by this format string, or -1 if\n  // invalid conversions have been found.\n  octave_idx_type m_nconv;\n\n  // Index to current element;\n  std::size_t m_curr_idx;\n\n  // List of format elements.\n  std::deque<scanf_format_elt *> m_fmt_elts;\n\n  // Temporary buffer.\n  std::ostringstream m_buf;\n\n};\n\nscanf_format_list::scanf_format_list (const std::string& s)\n  : m_nconv (0), m_curr_idx (0), m_fmt_elts (), m_buf ()\n{\n  std::size_t n = s.length ();\n\n  std::size_t i = 0;\n\n  int width = 0;\n  bool discard = false;\n  char modifier = '\\0';\n  char type = '\\0';\n\n  bool have_more = true;\n\n  while (i < n)\n    {\n      have_more = true;\n\n      if (s[i] == '%')\n        {\n          // Process percent-escape conversion type.\n\n          process_conversion (s, i, n, width, discard, type, modifier);\n\n          have_more = (m_buf.tellp () != 0);\n        }\n      else if (isspace (s[i]))\n        {\n          type = scanf_format_elt::whitespace_conversion;\n\n          width = 0;\n          discard = false;\n          modifier = '\\0';\n          m_buf << ' ';\n\n          while (++i < n && isspace (s[i]))\n            ; // skip whitespace\n\n          add_elt_to_list (width, discard, type, modifier);\n\n          have_more = false;\n        }\n      else\n        {\n          type = scanf_format_elt::literal_conversion;\n\n          width = 0;\n          discard = false;\n          modifier = '\\0';\n\n          while (i < n && ! isspace (s[i]) && s[i] != '%')\n            m_buf << s[i++];\n\n          add_elt_to_list (width, discard, type, modifier);\n\n          have_more = false;\n        }\n\n      if (m_nconv < 0)\n        {\n          have_more = false;\n          break;\n        }\n    }\n\n  if (have_more)\n    add_elt_to_list (width, discard, type, modifier);\n\n  m_buf.clear ();\n  m_buf.str (\"\");\n}\n\nscanf_format_list::~scanf_format_list ()\n{\n  std::size_t n = m_fmt_elts.size ();\n\n  for (std::size_t i = 0; i < n; i++)\n    {\n      scanf_format_elt *elt = m_fmt_elts[i];\n      delete elt;\n    }\n}\n\nvoid\nscanf_format_list::add_elt_to_list (int width, bool discard, char type,\n                                    char modifier,\n                                    const std::string& char_class)\n{\n  std::string text = m_buf.str ();\n\n  if (! text.empty ())\n    {\n      scanf_format_elt *elt\n        = new scanf_format_elt (text, width, discard, type,\n                                modifier, char_class);\n\n      m_fmt_elts.push_back (elt);\n    }\n\n  m_buf.clear ();\n  m_buf.str (\"\");\n}\n\nvoid\nscanf_format_list::process_conversion (const std::string& s, std::size_t& i,\n                                       std::size_t n, int& width,\n                                       bool& discard, char& type,\n                                       char& modifier)\n{\n  width = 0;\n  discard = false;\n  modifier = '\\0';\n  type = '\\0';\n\n  m_buf << s[i++];\n\n  bool have_width = false;\n\n  while (i < n)\n    {\n      switch (s[i])\n        {\n        case '*':\n          if (discard)\n            m_nconv = -1;\n          else\n            {\n              discard = true;\n              m_buf << s[i++];\n            }\n          break;\n\n        case '0': case '1': case '2': case '3': case '4':\n        case '5': case '6': case '7': case '8': case '9':\n          if (have_width)\n            m_nconv = -1;\n          else\n            {\n              char c = s[i++];\n              width = 10 * width + c - '0';\n              have_width = true;\n              m_buf << c;\n              while (i < n && isdigit (s[i]))\n                {\n                  c = s[i++];\n                  width = 10 * width + c - '0';\n                  m_buf << c;\n                }\n            }\n          break;\n\n        case 'h': case 'l': case 'L':\n          if (modifier != '\\0')\n            m_nconv = -1;\n          else\n            modifier = s[i++];\n          break;\n\n        // We accept X for compatibility with undocumented Matlab behavior.\n        case 'd': case 'i': case 'o': case 'u': case 'x':\n        case 'X':\n          if (modifier == 'L')\n            {\n              m_nconv = -1;\n              break;\n            }\n          goto fini;\n\n        // We accept E and G for compatibility with undocumented\n        // Matlab behavior.\n        case 'e': case 'f': case 'g':\n        case 'E': case 'G':\n          if (modifier == 'h')\n            {\n              m_nconv = -1;\n              break;\n            }\n\n          // No float or long double conversions, thanks.\n          m_buf << 'l';\n\n          goto fini;\n\n        case 'c': case 's': case 'p': case '%': case '[':\n          if (modifier != '\\0')\n            {\n              m_nconv = -1;\n              break;\n            }\n          goto fini;\n\n        fini:\n          {\n            if (finish_conversion (s, i, n, width, discard,\n                                   type, modifier) == 0)\n              return;\n          }\n          break;\n\n        default:\n          m_nconv = -1;\n          break;\n        }\n\n      if (m_nconv < 0)\n        break;\n    }\n\n  m_nconv = -1;\n}\n\nint\nscanf_format_list::finish_conversion (const std::string& s, std::size_t& i,\n                                      std::size_t n, int width, bool discard,\n                                      char& type, char modifier)\n{\n  int retval = 0;\n\n  std::string char_class;\n\n  std::size_t beg_idx = std::string::npos;\n  std::size_t end_idx = std::string::npos;\n\n  if (s[i] == '%')\n    {\n      type = '%';\n      m_buf << s[i++];\n    }\n  else\n    {\n      type = s[i];\n\n      if (s[i] == '[')\n        {\n          m_buf << s[i++];\n\n          if (i < n)\n            {\n              beg_idx = i;\n\n              if (s[i] == '^')\n                {\n                  type = '^';\n                  m_buf << s[i++];\n\n                  if (i < n)\n                    {\n                      beg_idx = i;\n\n                      if (s[i] == ']')\n                        m_buf << s[i++];\n                    }\n                }\n              else if (s[i] == ']')\n                m_buf << s[i++];\n            }\n\n          while (i < n && s[i] != ']')\n            m_buf << s[i++];\n\n          if (i < n && s[i] == ']')\n            {\n              end_idx = i-1;\n              m_buf << s[i++];\n            }\n\n          if (s[i-1] != ']')\n            retval = m_nconv = -1;\n        }\n      else\n        m_buf << s[i++];\n\n      m_nconv++;\n    }\n\n  if (m_nconv >= 0)\n    {\n      if (beg_idx != std::string::npos && end_idx != std::string::npos)\n        char_class = expand_char_class (s.substr (beg_idx,\n                                                  end_idx - beg_idx + 1));\n\n      add_elt_to_list (width, discard, type, modifier, char_class);\n    }\n\n  return retval;\n}\n\nvoid\nscanf_format_list::printme () const\n{\n  std::size_t n = m_fmt_elts.size ();\n\n  for (std::size_t i = 0; i < n; i++)\n    {\n      scanf_format_elt *elt = m_fmt_elts[i];\n\n      std::cerr\n        << \"width:      \" << elt->width << \"\\n\"\n        << \"discard:    \" << elt->discard << \"\\n\"\n        << \"type:       \";\n\n      if (elt->type == scanf_format_elt::literal_conversion)\n        std::cerr << \"literal text\\n\";\n      else if (elt->type == scanf_format_elt::whitespace_conversion)\n        std::cerr << \"whitespace\\n\";\n      else\n        std::cerr << elt->type << \"\\n\";\n\n      std::cerr\n        << \"modifier:   \" << elt->modifier << \"\\n\"\n        << \"char_class: '\" << undo_string_escapes (elt->char_class) << \"'\\n\"\n        << \"text:       '\" << undo_string_escapes (elt->text) << \"'\\n\\n\";\n    }\n}\n\nbool\nscanf_format_list::all_character_conversions ()\n{\n  std::size_t n = m_fmt_elts.size ();\n\n  if (n > 0)\n    {\n      for (std::size_t i = 0; i < n; i++)\n        {\n          scanf_format_elt *elt = m_fmt_elts[i];\n\n          switch (elt->type)\n            {\n            case 'c': case 's': case '%': case '[': case '^':\n            case scanf_format_elt::literal_conversion:\n            case scanf_format_elt::whitespace_conversion:\n              break;\n\n            default:\n              return false;\n              break;\n            }\n        }\n\n      return true;\n    }\n  else\n    return false;\n}\n\nbool\nscanf_format_list::all_numeric_conversions ()\n{\n  std::size_t n = m_fmt_elts.size ();\n\n  if (n > 0)\n    {\n      for (std::size_t i = 0; i < n; i++)\n        {\n          scanf_format_elt *elt = m_fmt_elts[i];\n\n          switch (elt->type)\n            {\n            case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':\n            case 'e': case 'f': case 'g': case 'E': case 'G':\n              break;\n\n            default:\n              return false;\n              break;\n            }\n        }\n\n      return true;\n    }\n  else\n    return false;\n}\n\nclass printf_format_elt\n{\npublic:\n\n  printf_format_elt (const std::string& txt = \"\", int n = 0, int w = -1,\n                     int p = -1, const std::string& f = \"\",\n                     char typ = '\\0', char mod = '\\0')\n    : text (txt), args (n), fw (w), prec (p), flags (f),\n      type (typ), modifier (mod)\n  { }\n\n  printf_format_elt (const printf_format_elt&) = default;\n\n  printf_format_elt& operator = (const printf_format_elt&) = default;\n\n  ~printf_format_elt () = default;\n\n  // The C-style format string.\n  std::string text;\n\n  // How many args do we expect to consume?\n  int args;\n\n  // Field width.\n  int fw;\n\n  // Precision.\n  int prec;\n\n  // Flags -- '-', '+', ' ', '0', or '#'.\n  std::string flags;\n\n  // Type of conversion -- 'd', 'i', 'o', 'x', 'X', 'u', 'c', 's',\n  // 'f', 'e', 'E', 'g', 'G', 'p', or '%'\n  char type;\n\n  // A length modifier -- 'h', 'l', or 'L'.\n  char modifier;\n};\n\nclass printf_format_list\n{\npublic:\n\n  printf_format_list (const std::string& fmt = \"\");\n\n  OCTAVE_DISABLE_COPY_MOVE (printf_format_list)\n\n  ~printf_format_list ();\n\n  octave_idx_type num_conversions () { return m_nconv; }\n\n  const printf_format_elt * first ()\n  {\n    m_curr_idx = 0;\n    return current ();\n  }\n\n  const printf_format_elt * current () const\n  {\n    return length () > 0 ? m_fmt_elts[m_curr_idx] : nullptr;\n  }\n\n  std::size_t length () const { return m_fmt_elts.size (); }\n\n  const printf_format_elt * next (bool cycle = true)\n  {\n    m_curr_idx++;\n\n    if (m_curr_idx >= length ())\n      {\n        if (cycle)\n          m_curr_idx = 0;\n        else\n          return nullptr;\n      }\n\n    return current ();\n  }\n\n  bool last_elt_p () { return (m_curr_idx + 1 == length ()); }\n\n  void printme () const;\n\n  bool ok () const { return (m_nconv >= 0); }\n\n  operator bool () const { return ok (); }\n\nprivate:\n\n  void add_elt_to_list (int args, const std::string& flags, int fw,\n                        int prec, char type, char modifier);\n\n  void process_conversion (const std::string& s, std::size_t& i,\n                           std::size_t n,\n                           int& args, std::string& flags, int& fw,\n                           int& prec, char& modifier, char& type);\n\n  void finish_conversion (const std::string& s, std::size_t& i, int args,\n                          const std::string& flags, int fw, int prec,\n                          char modifier, char& type);\n\n  //--------\n\n  // Number of conversions specified by this format string, or -1 if\n  // invalid conversions have been found.\n  octave_idx_type m_nconv;\n\n  // Index to current element;\n  std::size_t m_curr_idx;\n\n  // List of format elements.\n  std::deque<printf_format_elt *> m_fmt_elts;\n\n  // Temporary buffer.\n  std::ostringstream m_buf;\n\n};\n\nprintf_format_list::printf_format_list (const std::string& s)\n  : m_nconv (0), m_curr_idx (0), m_fmt_elts (), m_buf ()\n{\n  std::size_t n = s.length ();\n\n  std::size_t i = 0;\n\n  int args = 0;\n  std::string flags;\n  int fw = -1;\n  int prec = -1;\n  char modifier = '\\0';\n  char type = '\\0';\n\n  bool have_more = true;\n  bool empty_buf = true;\n\n  if (n == 0)\n    {\n      printf_format_elt *elt\n        = new printf_format_elt (\"\", args, fw, prec, flags, type, modifier);\n\n      m_fmt_elts.push_back (elt);\n    }\n  else\n    {\n      while (i < n)\n        {\n          have_more = true;\n\n          empty_buf = (m_buf.tellp () == 0);\n\n          switch (s[i])\n            {\n            case '%':\n              {\n                if (empty_buf)\n                  {\n                    process_conversion (s, i, n, args, flags, fw, prec,\n                                        modifier, type);\n\n                    // If there is nothing in the buffer, then\n                    // add_elt_to_list must have just been called, so we\n                    // are already done with the current element and we\n                    // don't need to call add_elt_to_list if this is our\n                    // last trip through the loop.\n\n                    have_more = (m_buf.tellp () != 0);\n                  }\n                else\n                  add_elt_to_list (args, flags, fw, prec, type, modifier);\n              }\n              break;\n\n            default:\n              {\n                args = 0;\n                flags = \"\";\n                fw = -1;\n                prec = -1;\n                modifier = '\\0';\n                type = '\\0';\n                m_buf << s[i++];\n              }\n              break;\n            }\n\n          if (m_nconv < 0)\n            {\n              have_more = false;\n              break;\n            }\n        }\n\n      if (have_more)\n        add_elt_to_list (args, flags, fw, prec, type, modifier);\n\n      m_buf.clear ();\n      m_buf.str (\"\");\n    }\n}\n\nprintf_format_list::~printf_format_list ()\n{\n  std::size_t n = m_fmt_elts.size ();\n\n  for (std::size_t i = 0; i < n; i++)\n    {\n      printf_format_elt *elt = m_fmt_elts[i];\n      delete elt;\n    }\n}\n\nvoid\nprintf_format_list::add_elt_to_list (int args, const std::string& flags,\n                                     int fw, int prec, char type,\n                                     char modifier)\n{\n  std::string text = m_buf.str ();\n\n  if (! text.empty ())\n    {\n      printf_format_elt *elt\n        = new printf_format_elt (text, args, fw, prec, flags,\n                                 type, modifier);\n\n      m_fmt_elts.push_back (elt);\n    }\n\n  m_buf.clear ();\n  m_buf.str (\"\");\n}\n\nvoid\nprintf_format_list::process_conversion (const std::string& s, std::size_t& i,\n                                        std::size_t n, int& args,\n                                        std::string& flags, int& fw,\n                                        int& prec, char& modifier,\n                                        char& type)\n{\n  args = 0;\n  flags = \"\";\n  fw = -1;\n  prec = -1;\n  modifier = '\\0';\n  type = '\\0';\n\n  m_buf << s[i++];\n\n  bool nxt = false;\n\n  while (i < n)\n    {\n      switch (s[i])\n        {\n        case '-': case '+': case ' ': case '0': case '#':\n          flags += s[i];\n          m_buf << s[i++];\n          break;\n\n        default:\n          nxt = true;\n          break;\n        }\n\n      if (nxt)\n        break;\n    }\n\n  if (i < n)\n    {\n      if (s[i] == '*')\n        {\n          fw = -2;\n          args++;\n          m_buf << s[i++];\n        }\n      else\n        {\n          if (isdigit (s[i]))\n            {\n              int nn = 0;\n              std::string tmp = s.substr (i);\n              sscanf (tmp.c_str (), \"%d%n\", &fw, &nn);\n            }\n\n          while (i < n && isdigit (s[i]))\n            m_buf << s[i++];\n        }\n    }\n\n  if (i < n && s[i] == '.')\n    {\n      // nothing before the . means 0.\n      if (fw == -1)\n        fw = 0;\n\n      // . followed by nothing is 0.\n      prec = 0;\n\n      m_buf << s[i++];\n\n      if (i < n)\n        {\n          if (s[i] == '*')\n            {\n              prec = -2;\n              args++;\n              m_buf << s[i++];\n            }\n          else\n            {\n              if (isdigit (s[i]))\n                {\n                  int nn = 0;\n                  std::string tmp = s.substr (i);\n                  sscanf (tmp.c_str (), \"%d%n\", &prec, &nn);\n                }\n\n              while (i < n && isdigit (s[i]))\n                m_buf << s[i++];\n            }\n        }\n    }\n\n  if (i < n)\n    {\n      // Accept and record modifier, but don't place it in the format\n      // item text.  All integer conversions are handled as 64-bit\n      // integers.\n\n      switch (s[i])\n        {\n        case 'h': case 'l': case 'L':\n          modifier = s[i++];\n          break;\n\n        default:\n          break;\n        }\n    }\n\n  if (i < n)\n    finish_conversion (s, i, args, flags, fw, prec, modifier, type);\n  else\n    m_nconv = -1;\n}\n\nvoid\nprintf_format_list::finish_conversion (const std::string& s, std::size_t& i,\n                                       int args, const std::string& flags,\n                                       int fw, int prec, char modifier,\n                                       char& type)\n{\n  switch (s[i])\n    {\n    case 'd': case 'i': case 'o': case 'x': case 'X':\n    case 'u': case 'c':\n      if (modifier == 'L')\n        {\n          m_nconv = -1;\n          break;\n        }\n      goto fini;\n\n    case 'f': case 'e': case 'E': case 'g': case 'G':\n      if (modifier == 'h' || modifier == 'l')\n        {\n          m_nconv = -1;\n          break;\n        }\n      goto fini;\n\n    case 's': case 'p': case '%':\n      if (modifier != '\\0')\n        {\n          m_nconv = -1;\n          break;\n        }\n      goto fini;\n\n    fini:\n\n      type = s[i];\n\n      m_buf << s[i++];\n\n      if (type != '%' || args != 0)\n        m_nconv++;\n\n      if (type != '%')\n        args++;\n\n      add_elt_to_list (args, flags, fw, prec, type, modifier);\n\n      break;\n\n    default:\n      m_nconv = -1;\n      break;\n    }\n}\n\nvoid\nprintf_format_list::printme () const\n{\n  std::size_t n = m_fmt_elts.size ();\n\n  for (std::size_t i = 0; i < n; i++)\n    {\n      printf_format_elt *elt = m_fmt_elts[i];\n\n      std::cerr\n        << \"args:     \" << elt->args << \"\\n\"\n        << \"flags:    '\" << elt->flags << \"'\\n\"\n        << \"width:    \" << elt->fw << \"\\n\"\n        << \"prec:     \" << elt->prec << \"\\n\"\n        << \"type:     '\" << elt->type << \"'\\n\"\n        << \"modifier: '\" << elt->modifier << \"'\\n\"\n        << \"text:     '\" << undo_string_escapes (elt->text) << \"'\\n\\n\";\n    }\n}\n\n// Calculate x^n.  Used for ...e+nn so that, for example, 1e2 is\n// exactly 100 and 5e-1 is 1/2\n\nstatic double\npown (double x, unsigned int n)\n{\n  double retval = 1;\n\n  for (unsigned int d = n; d; d >>= 1)\n    {\n      if (d & 1)\n        retval *= x;\n      x *= x;\n    }\n\n  return retval;\n}\n\nstatic Cell\ninit_inf_nan ()\n{\n  Cell retval (dim_vector (1, 2));\n\n  retval(0) = Cell (octave_value (\"inf\"));\n  retval(1) = Cell (octave_value (\"nan\"));\n\n  return retval;\n}\n\n// Delimited stream, optimized to read strings of characters separated\n// by single-character delimiters.\n//\n// The reason behind this class is that octstream doesn't provide\n// seek/tell, but the opportunity has been taken to optimise for the\n// textscan workload.\n//\n// The function reads chunks into a 4kiB buffer, and marks where the\n// last delimiter occurs.  Reads up to this delimiter can be fast.\n// After that last delimiter, the remaining text is moved to the front\n// of the buffer and the buffer is refilled.  This also allows cheap\n// seek and tell operations within a \"fast read\" block.\n\nclass delimited_stream\n{\npublic:\n\n  delimited_stream (std::istream& is, const std::string& delimiters,\n                    int longest_lookahead, octave_idx_type bsize = 4096);\n\n  delimited_stream (std::istream& is, const delimited_stream& ds);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (delimited_stream)\n\n  ~delimited_stream ();\n\n  // Called when optimized sequence of get is finished.  Ensures that\n  // there is a remaining delimiter in buf, or loads more data in.\n  void field_done ()\n  {\n    if (m_idx >= m_last)\n      refresh_buf ();\n  }\n\n  // Load new data into buffer, and set eob, last, idx.\n  // Return EOF at end of file, 0 otherwise.\n  int refresh_buf (bool initialize = false);\n\n  // Get a character, relying on caller to call field_done if\n  // a delimiter has been reached.\n  int get ()\n  {\n    if (m_delimited)\n      return eof () ? std::istream::traits_type::eof () : *m_idx++;\n    else\n      return get_undelim ();\n  }\n\n  // Get a character, checking for underrun of the buffer.\n  int get_undelim ();\n\n  // Read character that will be got by the next get.\n  // FIXME: This will not set EOF if delimited stream is at EOF and a peek\n  // is attempted.  This does *NOT* behave like C++ input stream.\n  // For a compatible peek function, use peek_undelim.  See bug #56917.\n  int peek ()\n  { return eof () ? std::istream::traits_type::eof () : *m_idx; }\n\n  // Read character that will be got by the next get.\n  int peek_undelim ();\n\n  // Undo a 'get' or 'get_undelim'.  It is the caller's responsibility\n  // to avoid overflow by calling putbacks only for a character got by\n  // get() or get_undelim(), with no intervening\n  // get, get_delim, field_done, refresh_buf, getline, read or seekg.\n  void putback (char /*ch*/ = 0) { if (! eof ()) --m_idx; }\n\n  int getline  (std::string& dest, char delim);\n\n  // int skipline (char delim);\n\n  char * read (char *buffer, int size, char *&new_start);\n\n  // Return a position suitable to \"seekg\", valid only within this\n  // block between calls to field_done.\n  char * tellg () { return m_idx; }\n\n  void seekg (char *old_idx) { m_idx = old_idx; }\n\n  bool eof ()\n  {\n    return ((m_eob - m_buf) == m_overlap && m_i_stream.eof ())\n            || (m_flags & std::ios_base::eofbit);\n  }\n\n  operator const void *()\n  { return (! eof () && ! m_flags) ? this : nullptr; }\n\n  bool fail () { return m_flags & std::ios_base::failbit; }\n\n  std::ios_base::iostate rdstate () { return m_flags; }\n\n  void setstate (std::ios_base::iostate m) { m_flags = m_flags | m; }\n\n  void clear (std::ios_base::iostate m\n              = (std::ios_base::eofbit & ~std::ios_base::eofbit))\n  {\n    m_flags = m_flags & m;\n  }\n\n  // Report if any characters have been consumed.\n  // (get, read, etc. not cancelled by putback or seekg)\n\n  void progress_benchmark () { m_progress_marker = m_idx; }\n\n  bool no_progress () { return m_progress_marker == m_idx; }\n\n  // Number of characters remaining until end of stream if it is already\n  // buffered.  Otherwise, return int_max.\n\n  std::ptrdiff_t remaining ()\n  {\n    if (m_eob < m_buf + m_bufsize)\n      return m_eob - m_idx;\n    else\n      return std::numeric_limits<std::ptrdiff_t>::max ();\n  }\n\nprivate:\n\n  // Number of characters to read from the file at once.\n  int m_bufsize;\n\n  // Stream to read from.\n  std::istream& m_i_stream;\n\n  // Temporary storage for a \"chunk\" of data.\n  char *m_buf;\n\n  // Current read pointer.\n  char *m_idx;\n\n  // Location of last delimiter in the buffer at buf (undefined if\n  // delimited is false).\n  char *m_last;\n\n  // Position after last character in buffer.\n  char *m_eob;\n\n  // Overlap with old content when refreshing buffer.\n  std::ptrdiff_t m_overlap;\n\n  // True if there is delimiter in the buffer after idx.\n  bool m_delimited;\n\n  // Longest lookahead required.\n  int m_longest;\n\n  // Sequence of single-character delimiters.\n  const std::string m_delims;\n\n  // Position of start of buf in original stream.\n  std::streampos m_buf_in_file;\n\n  // Marker to see if a read consumes any characters.\n  char *m_progress_marker;\n\n  std::ios_base::iostate m_flags;\n};\n\n// Create a delimited stream, reading from is, with delimiters delims,\n// and allowing reading of up to tellg + longest_lookeahead.  When is\n// is at EOF, lookahead may be padded by ASCII nuls.\n\ndelimited_stream::delimited_stream (std::istream& is,\n                                    const std::string& delimiters,\n                                    int longest_lookahead,\n                                    octave_idx_type bsize)\n  : m_bufsize (bsize), m_i_stream (is), m_longest (longest_lookahead),\n    m_delims (delimiters),\n    m_flags (std::ios::failbit & ~std::ios::failbit) // can't cast 0\n{\n  m_buf = new char[m_bufsize];\n  m_eob = m_buf + m_bufsize;\n  m_idx = m_eob;                // refresh_buf shouldn't try to copy old data\n  m_overlap = 0;                // initialize value for eof() test\n  m_progress_marker = m_idx;\n  refresh_buf (true);           // load the first batch of data\n}\n\n// Used to create a stream from a strstream from data read from a dstr.\ndelimited_stream::delimited_stream (std::istream& is,\n                                    const delimited_stream& ds)\n  : delimited_stream (is, ds.m_delims, ds.m_longest, ds.m_bufsize)\n{ }\n\ndelimited_stream::~delimited_stream ()\n{\n  // Seek to the correct position in i_stream.\n  if (! eof ())\n    {\n      m_i_stream.clear ();\n      m_i_stream.seekg (m_buf_in_file);\n      m_i_stream.read (m_buf, m_idx - m_buf - m_overlap);\n    }\n\n  delete [] m_buf;\n}\n\n// Read a character from the buffer, refilling the buffer from the file\n// if necessary.\n\nint\ndelimited_stream::get_undelim ()\n{\n  int retval;\n  if (eof ())\n    {\n      setstate (std::ios_base::failbit);\n      return std::istream::traits_type::eof ();\n    }\n\n  if (m_idx < m_eob)\n    retval = *m_idx++;\n  else\n    {\n      refresh_buf ();\n\n      if (eof ())\n        {\n          setstate (std::ios_base::eofbit);\n          retval = std::istream::traits_type::eof ();\n        }\n      else\n        retval = *m_idx++;\n    }\n\n  if (m_idx >= m_last)\n    m_delimited = false;\n\n  return retval;\n}\n\n// Return the next character to be read without incrementing the\n// pointer, refilling the buffer from the file if necessary.\n\nint\ndelimited_stream::peek_undelim ()\n{\n  int retval = get_undelim ();\n  putback ();\n\n  return retval;\n}\n\n// Copy remaining unprocessed data to the start of the buffer and load\n// new data to fill it.  Return EOF if the file is at EOF before\n// reading any data and all of the data that has been read has been\n// processed.\n\nint\ndelimited_stream::refresh_buf (bool initialize)\n{\n  if (eof ())\n    return std::istream::traits_type::eof ();\n\n  int retval;\n\n  if (m_eob < m_idx)\n    m_idx = m_eob;\n\n  std::size_t old_remaining = m_eob - m_idx;\n  std::size_t old_overlap = 0;\n\n  if (initialize || (m_idx - m_buf <= 0))\n    m_overlap = 0;\n  else\n    {\n      old_overlap = m_overlap;\n      // Retain the last 25 bytes in the buffer.  That should be more than\n      // enough to putback an entire double precision floating point number in\n      // decimal including 3 digit exponent and signs.  Do we ever need to\n      // putback more than that?\n      m_overlap = 25;\n      // Assure we don't \"underflow\" with the overlap\n      m_overlap = std::min (m_overlap, m_idx - m_buf - 1);\n    }\n\n  octave_quit ();                       // allow Ctrl-C\n\n  if (old_remaining + m_overlap > 0)\n    {\n      m_buf_in_file += (m_idx - old_overlap - m_buf);\n      std::memmove (m_buf, m_idx - m_overlap, m_overlap + old_remaining);\n    }\n  else\n    m_buf_in_file = m_i_stream.tellg ();  // record for destructor\n\n  // where original idx would have been\n  m_progress_marker -= m_idx - m_overlap - m_buf;\n  m_idx = m_buf + m_overlap;\n\n  int gcount;   // chars read\n  if (! m_i_stream.eof ())\n    {\n      m_i_stream.read (m_buf + m_overlap + old_remaining,\n                       m_bufsize - m_overlap - old_remaining);\n      gcount = m_i_stream.gcount ();\n    }\n  else\n    gcount = 0;\n\n  m_eob = m_buf + m_overlap + old_remaining + gcount;\n  m_last = m_eob;\n  if (gcount == 0)\n    {\n      m_delimited = false;\n\n      if (m_eob != m_buf + m_overlap)\n        // no more data in file, but still some to go\n        retval = 0;\n      else\n        // file and buffer are both done.\n        retval = std::istream::traits_type::eof ();\n    }\n  else\n    {\n      m_delimited = true;\n\n      for (m_last = m_eob - m_longest; m_last - m_buf - m_overlap >= 0;\n           m_last--)\n        {\n          if (m_delims.find (*m_last) != std::string::npos)\n            break;\n        }\n\n      if (m_last < m_buf + m_overlap)\n        m_delimited = false;\n\n      retval = 0;\n    }\n\n  // Ensure fast peek doesn't give valid char\n  if (retval == std::istream::traits_type::eof ())\n    *m_idx = '\\0';    // FIXME: check that no TreatAsEmpty etc starts w. \\0?\n\n  return retval;\n}\n\n// Return a pointer to a block of data of size size, assuming that a\n// sufficiently large buffer is available in buffer, if required.\n// If called when delimited == true, and size is no greater than\n// longest_lookahead then this will not call refresh_buf, so seekg\n// still works.  Otherwise, seekg may be invalidated.\n\nchar *\ndelimited_stream::read (char *buffer, int size, char *&prior_tell)\n{\n  char *retval;\n\n  if (m_eob - m_idx >= size)\n    {\n      retval = m_idx;\n      m_idx += size;\n      if (m_idx > m_last)\n        m_delimited = false;\n    }\n  else\n    {\n      // If there was a tellg pointing to an earlier point than the current\n      // read position, try to keep it in the active buffer.\n      // In the current code, prior_tell==idx for each call,\n      // so this is not necessary, just a precaution.\n\n      if (m_eob - prior_tell + size < m_bufsize)\n        {\n          octave_idx_type gap = m_idx - prior_tell;\n          m_idx = prior_tell;\n          refresh_buf ();\n          m_idx += gap;\n        }\n      else      // can't keep the tellg in range.  May skip some data.\n        {\n          refresh_buf ();\n        }\n\n      prior_tell = m_buf;\n\n      if (m_eob - m_idx > size)\n        {\n          retval = m_idx;\n          m_idx += size;\n          if (m_idx > m_last)\n            m_delimited = false;\n        }\n      else\n        {\n          if (size <= m_bufsize)          // small read, but reached EOF\n            {\n              retval = m_idx;\n              memset (m_eob, 0, size + (m_idx - m_buf));\n              m_idx += size;\n            }\n          else  // Reading more than the whole buf; return it in buffer\n            {\n              retval = buffer;\n              // FIXME: read bufsize at a time\n              int i;\n              for (i = 0; i < size && ! eof (); i++)\n                *buffer++ = get_undelim ();\n              if (eof ())\n                memset (buffer, 0, size - i);\n            }\n        }\n    }\n\n  return retval;\n}\n\n// Return in OUT an entire line, terminated by delim.  On input, OUT\n// must have length at least 1.\n\nint\ndelimited_stream::getline (std::string& out, char delim)\n{\n  int len = out.length ();\n  int used = 0;\n  int ch;\n  while ((ch = get_undelim ()) != delim\n         && ch != std::istream::traits_type::eof ())\n    {\n      out[used++] = ch;\n      if (used == len)\n        {\n          len <<= 1;\n          out.resize (len);\n        }\n    }\n  out.resize (used);\n  field_done ();\n\n  return ch;\n}\n\n// A single conversion specifier, such as %f or %c.\n\nclass textscan_format_elt\n{\npublic:\n\n  enum special_conversion\n  {\n    whitespace_conversion = 1,\n    literal_conversion = 2\n  };\n\n  textscan_format_elt () = delete;\n\n  textscan_format_elt (const std::string& txt, int w = 0, int p = -1,\n                       int bw = 0, bool dis = false, char typ = '\\0',\n                       const std::string& ch_class = std::string ())\n    : text (txt), width (w), prec (p), bitwidth (bw),\n      char_class (ch_class), type (typ), discard (dis),\n      numeric (typ == 'd' || typ == 'u' || type == 'f' || type == 'n')\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (textscan_format_elt)\n\n  // The C-style format string.\n  std::string text;\n\n  // The maximum field width.\n  unsigned int width;\n\n  // The maximum number of digits to read after the decimal in a\n  // floating point conversion.\n  int prec;\n\n  // The size of the result.  For integers, bitwidth may be 8, 16, 34,\n  // or 64.  For floating point values, bitwidth may be 32 or 64.\n  int bitwidth;\n\n  // The class of characters in a '[' or '^' format.\n  std::string char_class;\n\n  // Type of conversion\n  //  -- 'd', 'u', 'f', 'n', 's', 'q', 'c', '%', 'C', 'D', '[' or '^'.\n  char type;\n\n  // TRUE if we are not storing the result of this conversion.\n  bool discard;\n\n  // TRUE if the type is 'd', 'u', 'f', 'n'\n  bool numeric;\n};\n\n// The (parsed) sequence of format specifiers.\n\nclass textscan;\n\nclass textscan_format_list\n{\npublic:\n\n  textscan_format_list (const std::string& fmt = std::string (),\n                        const std::string& who = \"textscan\");\n\n  OCTAVE_DISABLE_COPY_MOVE (textscan_format_list)\n\n  ~textscan_format_list ();\n\n  octave_idx_type num_conversions () const { return m_nconv; }\n\n  // The length can be different than the number of conversions.\n  // For example, \"x %d y %d z\" has 2 conversions but the length of\n  // the list is 3 because of the characters that appear after the\n  // last conversion.\n\n  std::size_t numel () const { return m_fmt_elts.size (); }\n\n  const textscan_format_elt * first ()\n  {\n    m_curr_idx = 0;\n    return current ();\n  }\n\n  const textscan_format_elt * current () const\n  {\n    return numel () > 0 ? m_fmt_elts[m_curr_idx] : nullptr;\n  }\n\n  const textscan_format_elt * next (bool cycle = true)\n  {\n    m_curr_idx++;\n\n    if (m_curr_idx >= numel ())\n      {\n        if (cycle)\n          m_curr_idx = 0;\n        else\n          return nullptr;\n      }\n\n    return current ();\n  }\n\n  void printme () const;\n\n  bool ok () const { return (m_nconv >= 0); }\n\n  operator const void *() const { return ok () ? this : nullptr; }\n\n  // What function name should be shown when reporting errors.\n  std::string who;\n\n  // True if number of %f to be set from data file.\n  bool set_from_first;\n\n  // At least one conversion specifier is s,q,c, or [...].\n  bool has_string;\n\n  int read_first_row (delimited_stream& is, textscan& ts);\n\n  std::list<octave_value> out_buf () const\n  { return (m_output_container); }\n\nprivate:\n\n  void add_elt_to_list (unsigned int width, int prec, int bitwidth,\n                        octave_value val_type, bool discard,\n                        char type,\n                        const std::string& char_class = std::string ());\n\n  void process_conversion (const std::string& s, std::size_t& i,\n                           std::size_t n);\n\n  std::string parse_char_class (const std::string& pattern) const;\n\n  int finish_conversion (const std::string& s, std::size_t& i, std::size_t n,\n                         unsigned int width, int prec, int bitwidth,\n                         octave_value& val_type,\n                         bool discard, char& type);\n\n  //--------\n\n  // Number of conversions specified by this format string, or -1 if\n  // invalid conversions have been found.\n  octave_idx_type m_nconv;\n\n  // Index to current element;\n  std::size_t m_curr_idx;\n\n  // List of format elements.\n  std::deque<textscan_format_elt *> m_fmt_elts;\n\n  // list holding column arrays of types specified by conversions\n  std::list<octave_value> m_output_container;\n\n  // Temporary buffer.\n  std::ostringstream m_buf;\n\n};\n\n// Main class to implement textscan.  Read data and parse it\n// according to a format.\n//\n// The calling sequence is\n//\n//   textscan scanner ();\n//   scanner.scan (...);\n\nclass OCTINTERP_API textscan\n{\npublic:\n\n  textscan (const std::string& who_arg = \"textscan\",\n            const std::string& encoding = \"utf-8\");\n\n  OCTAVE_DISABLE_COPY_MOVE (textscan)\n\n  ~textscan () = default;\n\n  octave_value scan (std::istream& isp, const std::string& fmt,\n                     octave_idx_type ntimes,\n                     const octave_value_list& options,\n                     octave_idx_type& read_count);\n\nprivate:\n\n  friend class textscan_format_list;\n\n  octave_value do_scan (std::istream& isp, textscan_format_list& fmt_list,\n                        octave_idx_type ntimes);\n\n  void parse_options (const octave_value_list& args,\n                      textscan_format_list& fmt_list);\n\n  int read_format_once (delimited_stream& isp, textscan_format_list& fmt_list,\n                        std::list<octave_value>& retval,\n                        Array<octave_idx_type> row, int& done_after);\n\n  void scan_one (delimited_stream& is, const textscan_format_elt& fmt,\n                 octave_value& ov, Array<octave_idx_type> row);\n\n  // Methods to process a particular conversion specifier.\n  double read_double (delimited_stream& is,\n                      const textscan_format_elt& fmt) const;\n\n  void scan_complex (delimited_stream& is, const textscan_format_elt& fmt,\n                     Complex& val) const;\n\n  int scan_bracket (delimited_stream& is, const std::string& pattern,\n                    std::string& val) const;\n\n  int scan_caret (delimited_stream& is, const std::string& pattern,\n                  std::string& val) const;\n\n  void scan_string (delimited_stream& is, const textscan_format_elt& fmt,\n                    std::string& val) const;\n\n  void scan_cstring (delimited_stream& is, const textscan_format_elt& fmt,\n                     std::string& val) const;\n\n  void scan_qstring (delimited_stream& is, const textscan_format_elt& fmt,\n                     std::string& val);\n\n  // Helper methods.\n  std::string read_until (delimited_stream& is, const Cell& delimiters,\n                          const std::string& ends) const;\n\n  int lookahead (delimited_stream& is, const Cell& targets, int max_len,\n                 bool case_sensitive = true) const;\n\n  bool match_literal (delimited_stream& isp, const textscan_format_elt& elem);\n\n  int skip_whitespace (delimited_stream& is, bool EOLstop = true);\n\n  int skip_delim (delimited_stream& is);\n\n  bool is_delim (unsigned char ch) const\n  {\n    return ((m_delim_table.empty ()\n             && (isspace (ch) || ch == m_eol1 || ch == m_eol2))\n            || m_delim_table[ch] != '\\0');\n  }\n\n  bool isspace (unsigned int ch) const\n  { return m_whitespace_table[ch & 0xff]; }\n\n  // True if the only delimiter is whitespace.\n  bool whitespace_delim () const { return m_delim_table.empty (); }\n\n  //--------\n\n  // What function name should be shown when reporting errors.\n  std::string m_who;\n\n  std::string m_encoding;\n\n  std::string m_buf;\n\n  // Three cases for delim_table and delim_list\n  // 1. delim_table empty, delim_list empty: whitespace delimiters\n  // 2. delim_table = look-up table of delim chars, delim_list empty.\n  // 3. delim_table non-empty, delim_list = Cell array of delim strings\n\n  std::string m_whitespace_table;\n\n  // delim_table[i] == '\\0' if i is not a delimiter.\n  std::string m_delim_table;\n\n  // String of delimiter characters.\n  std::string m_delims;\n\n  Cell m_comment_style;\n\n  // How far ahead to look to detect an open comment.\n  int m_comment_len;\n\n  // First character of open comment.\n  int m_comment_char;\n\n  octave_idx_type m_buffer_size;\n\n  std::string m_date_locale;\n\n  // 'inf' and 'nan' for formatted_double.\n  Cell m_inf_nan;\n\n  // Array of strings of delimiters.\n  Cell m_delim_list;\n\n  // Longest delimiter.\n  int m_delim_len;\n\n  octave_value m_empty_value;\n  std::string m_exp_chars;\n  int m_header_lines;\n  Cell m_treat_as_empty;\n\n  // Longest string to treat as \"N/A\".\n  int m_treat_as_empty_len;\n\n  std::string m_whitespace;\n\n  short m_eol1;\n  short m_eol2;\n  short m_return_on_error;\n\n  bool m_collect_output;\n  bool m_multiple_delims_as_one;\n  bool m_default_exp;\n\n  octave_idx_type m_lines;\n};\n\ntextscan_format_list::textscan_format_list (const std::string& s,\n                                            const std::string& who_arg)\n  : who (who_arg), set_from_first (false), has_string (false),\n    m_nconv (0), m_curr_idx (0), m_fmt_elts (), m_buf ()\n{\n  std::size_t n = s.length ();\n\n  std::size_t i = 0;\n\n  unsigned int width = -1;    // Unspecified width = max (except %c)\n  int prec = -1;\n  int bitwidth = 0;\n  bool discard = false;\n  char type = '\\0';\n\n  bool have_more = true;\n\n  if (s.empty ())\n    {\n      m_buf.clear ();\n      m_buf.str (\"\");\n\n      m_buf << \"%f\";\n\n      bitwidth = 64;\n      type = 'f';\n      add_elt_to_list (width, prec, bitwidth, octave_value (NDArray ()),\n                       discard, type);\n      have_more = false;\n      set_from_first = true;\n      m_nconv = 1;\n    }\n  else\n    {\n      set_from_first = false;\n\n      while (i < n)\n        {\n          have_more = true;\n\n          if (s[i] == '%' && (i+1 == n || s[i+1] != '%'))\n            {\n              // Process percent-escape conversion type.\n\n              process_conversion (s, i, n);\n\n              // If there is nothing in the buffer, then add_elt_to_list\n              // must have just been called, so we are already done with\n              // the current element and we don't need to call\n              // add_elt_to_list if this is our last trip through the\n              // loop.\n\n              have_more = (m_buf.tellp () != 0);\n            }\n          else if (isspace (s[i]))\n            {\n              while (++i < n && isspace (s[i]))\n                /* skip whitespace */;\n\n              have_more = false;\n            }\n          else\n            {\n              type = textscan_format_elt::literal_conversion;\n\n              width = 0;\n              prec = -1;\n              bitwidth = 0;\n              discard = true;\n\n              while (i < n && ! isspace (s[i])\n                     && (s[i] != '%' || (i+1 < n && s[i+1] == '%')))\n                {\n                  if (s[i] == '%')      // if double %, skip one\n                    i++;\n                  m_buf << s[i++];\n                  width++;\n                }\n\n              add_elt_to_list (width, prec, bitwidth, octave_value (),\n                               discard, type);\n\n              have_more = false;\n            }\n\n          if (m_nconv < 0)\n            {\n              have_more = false;\n              break;\n            }\n        }\n    }\n\n  if (have_more)\n    add_elt_to_list (width, prec, bitwidth, octave_value (), discard, type);\n\n  m_buf.clear ();\n  m_buf.str (\"\");\n}\n\ntextscan_format_list::~textscan_format_list ()\n{\n  std::size_t n = numel ();\n\n  for (std::size_t i = 0; i < n; i++)\n    {\n      textscan_format_elt *elt = m_fmt_elts[i];\n      delete elt;\n    }\n}\n\nvoid\ntextscan_format_list::add_elt_to_list (unsigned int width, int prec,\n                                       int bitwidth, octave_value val_type,\n                                       bool discard, char type,\n                                       const std::string& char_class)\n{\n  std::string text = m_buf.str ();\n\n  if (! text.empty ())\n    {\n      textscan_format_elt *elt\n        = new textscan_format_elt (text, width, prec, bitwidth, discard,\n                                   type, char_class);\n\n      if (! discard)\n        m_output_container.push_back (val_type);\n\n      m_fmt_elts.push_back (elt);\n    }\n\n  m_buf.clear ();\n  m_buf.str (\"\");\n}\n\nvoid\ntextscan_format_list::process_conversion (const std::string& s,\n                                          std::size_t& i, std::size_t n)\n{\n  unsigned width = 0;\n  int prec = -1;\n  int bitwidth = 0;\n  bool discard = false;\n  octave_value val_type;\n  char type = '\\0';\n\n  m_buf << s[i++];\n\n  bool have_width = false;\n\n  while (i < n)\n    {\n      switch (s[i])\n        {\n        case '*':\n          if (discard)\n            m_nconv = -1;\n          else\n            {\n              discard = true;\n              m_buf << s[i++];\n            }\n          break;\n\n        case '0': case '1': case '2': case '3': case '4':\n        case '5': case '6': case '7': case '8': case '9':\n          if (have_width)\n            m_nconv = -1;\n          else\n            {\n              char c = s[i++];\n              width = width * 10 + c - '0';\n              have_width = true;\n              m_buf << c;\n              while (i < n && isdigit (s[i]))\n                {\n                  c = s[i++];\n                  width = width * 10 + c - '0';\n                  m_buf << c;\n                }\n\n              if (i < n && s[i] == '.')\n                {\n                  m_buf << s[i++];\n                  prec = 0;\n                  while (i < n && isdigit (s[i]))\n                    {\n                      c = s[i++];\n                      prec = prec * 10 + c - '0';\n                      m_buf << c;\n                    }\n                }\n            }\n          break;\n\n        case 'd': case 'u':\n          {\n            bool done = true;\n            m_buf << (type = s[i++]);\n            if (i < n)\n              {\n                if (s[i] == '8')\n                  {\n                    bitwidth = 8;\n                    if (type == 'd')\n                      val_type = octave_value (int8NDArray ());\n                    else\n                      val_type = octave_value (uint8NDArray ());\n                    m_buf << s[i++];\n                  }\n                else if (s[i] == '1' && i+1 < n && s[i+1] == '6')\n                  {\n                    bitwidth = 16;\n                    if (type == 'd')\n                      val_type = octave_value (int16NDArray ());\n                    else\n                      val_type = octave_value (uint16NDArray ());\n                    m_buf << s[i++];\n                    m_buf << s[i++];\n                  }\n                else if (s[i] == '3' && i+1 < n && s[i+1] == '2')\n                  {\n                    done = false;       // use default size below\n                    m_buf << s[i++];\n                    m_buf << s[i++];\n                  }\n                else if (s[i] == '6' && i+1 < n && s[i+1] == '4')\n                  {\n                    bitwidth = 64;\n                    if (type == 'd')\n                      val_type = octave_value (int64NDArray ());\n                    else\n                      val_type = octave_value (uint64NDArray ());\n                    m_buf << s[i++];\n                    m_buf << s[i++];\n                  }\n                else\n                  done = false;\n              }\n            else\n              done = false;\n\n            if (! done)\n              {\n                bitwidth = 32;\n                if (type == 'd')\n                  val_type = octave_value (int32NDArray ());\n                else\n                  val_type = octave_value (uint32NDArray ());\n              }\n            goto fini;\n          }\n\n        case 'f':\n          m_buf << (type = s[i++]);\n          bitwidth = 64;\n          if (i < n)\n            {\n              if (s[i] == '3' && i+1 < n && s[i+1] == '2')\n                {\n                  bitwidth = 32;\n                  val_type = octave_value (FloatNDArray ());\n                  m_buf << s[i++];\n                  m_buf << s[i++];\n                }\n              else if (s[i] == '6' && i+1 < n && s[i+1] == '4')\n                {\n                  val_type = octave_value (NDArray ());\n                  m_buf << s[i++];\n                  m_buf << s[i++];\n                }\n              else\n                val_type = octave_value (NDArray ());\n            }\n          else\n            val_type = octave_value (NDArray ());\n          goto fini;\n\n        case 'n':\n          m_buf << (type = s[i++]);\n          bitwidth = 64;\n          val_type = octave_value (NDArray ());\n          goto fini;\n\n        case 's': case 'q': case '[': case 'c':\n          if (! discard)\n            val_type = octave_value (Cell ());\n          m_buf << (type = s[i++]);\n          has_string = true;\n          goto fini;\n\n        fini:\n          {\n            if (! have_width)\n              {\n                if (type == 'c')        // %c defaults to one character\n                  width = 1;\n                else\n                  width = static_cast<unsigned int> (-1); // others: unlimited\n              }\n\n            if (finish_conversion (s, i, n, width, prec, bitwidth, val_type,\n                                   discard, type) == 0)\n              return;\n          }\n          break;\n\n        default:\n          error (\"%s: '%%%c' is not a valid format specifier\",\n                 who.c_str (), s[i]);\n        }\n\n      if (m_nconv < 0)\n        break;\n    }\n\n  m_nconv = -1;\n}\n\n// Parse [...] and [^...]\n//\n// Matlab does not expand expressions like A-Z, but they are useful, and\n// so we parse them \"carefully\".  We treat '-' as a usual character\n// unless both start and end characters are from the same class (uppercase,\n// lowercase, numeric), or this is not the first '-' in the\n// pattern.\n//\n// Keep both a running list of characters and a mask of which chars have\n// occurred.  The first is efficient for patterns with few characters.\n// The latter is efficient for [^...] patterns.\n\nstd::string\ntextscan_format_list::parse_char_class (const std::string& pattern) const\n{\n  int len = pattern.length ();\n  if (len == 0)\n    return \"\";\n\n  std::string retval (256, '\\0');\n  std::string mask   (256, '\\0');       // number of times chr has been seen\n\n  int in = 0, out = 0;\n  unsigned char ch, prev = 0;\n  bool flip = false;\n\n  ch = pattern[in];\n  if (ch == '^')\n    {\n      in++;\n      flip = true;\n    }\n  mask[pattern[in]] = '\\1';\n  retval[out++] = pattern[in++];        // even copy ']' if it is first\n\n  bool prev_was_range = false;          // disallow \"a-m-z\" as a pattern\n  bool prev_prev_was_range = false;\n  for (; in < len; in++)\n    {\n      bool was_range = false;\n      ch = pattern[in];\n      if (ch == ']')\n        break;\n\n      if (prev == '-' && in > 1 && isalnum (ch) && ! prev_prev_was_range)\n        {\n          unsigned char start_of_range = pattern[in-2];\n          if (start_of_range < ch\n              && ((isupper (ch) && isupper (start_of_range))\n                  || (islower (ch) && islower (start_of_range))\n                  || (isdigit (ch) && isdigit (start_of_range))\n                  || mask['-'] > 1))    // not the first '-'\n            {\n              was_range = true;\n              out--;\n              mask['-']--;\n              for (int i = start_of_range; i <= ch; i++)\n                {\n                  if (mask[i] == '\\0')\n                    {\n                      mask[i] = '\\1';\n                      retval[out++] = i;\n                    }\n                }\n            }\n        }\n      if (! was_range)\n        {\n          if (mask[ch]++ == 0)\n            retval[out++] = ch;\n          else if (ch != '-')\n            warning_with_id (\"Octave:textscan-pattern\",\n                             \"%s: [...] contains two '%c's\",\n                             who.c_str (), ch);\n\n          if (prev == '-' && mask['-'] >= 2)\n            warning_with_id\n              (\"Octave:textscan-pattern\",\n               \"%s: [...] contains two '-'s outside range expressions\",\n               who.c_str ());\n        }\n      prev = ch;\n      prev_prev_was_range = prev_was_range;\n      prev_was_range = was_range;\n    }\n\n  if (flip)                             // [^...]\n    {\n      out = 0;\n      for (int i = 0; i < 256; i++)\n        if (! mask[i])\n          retval[out++] = i;\n    }\n\n  retval.resize (out);\n\n  return retval;\n}\n\nint\ntextscan_format_list::finish_conversion (const std::string& s, std::size_t& i,\n                                         std::size_t n, unsigned int width,\n                                         int prec, int bitwidth,\n                                         octave_value& val_type, bool discard,\n                                         char& type)\n{\n  int retval = 0;\n\n  std::string char_class;\n\n  std::size_t beg_idx = std::string::npos;\n  std::size_t end_idx = std::string::npos;\n\n  if (type != '%')\n    {\n      m_nconv++;\n      if (type == '[')\n        {\n          if (i < n)\n            {\n              beg_idx = i;\n\n              if (s[i] == '^')\n                {\n                  type = '^';\n                  m_buf << s[i++];\n\n                  if (i < n)\n                    {\n                      beg_idx = i;\n\n                      if (s[i] == ']')\n                        m_buf << s[i++];\n                    }\n                }\n              else if (s[i] == ']')\n                m_buf << s[i++];\n            }\n\n          while (i < n && s[i] != ']')\n            m_buf << s[i++];\n\n          if (i < n && s[i] == ']')\n            {\n              end_idx = i-1;\n              m_buf << s[i++];\n            }\n\n          if (s[i-1] != ']')\n            retval = m_nconv = -1;\n        }\n    }\n\n  if (m_nconv >= 0)\n    {\n      if (beg_idx != std::string::npos && end_idx != std::string::npos)\n        char_class = parse_char_class (s.substr (beg_idx,\n                                                 end_idx - beg_idx + 1));\n\n      add_elt_to_list (width, prec, bitwidth, val_type, discard, type,\n                       char_class);\n    }\n\n  return retval;\n}\n\nvoid\ntextscan_format_list::printme () const\n{\n  std::size_t n = numel ();\n\n  for (std::size_t i = 0; i < n; i++)\n    {\n      textscan_format_elt *elt = m_fmt_elts[i];\n\n      std::cerr\n        << \"width:      \" << elt->width << \"\\n\"\n        << \"digits      \" << elt->prec << \"\\n\"\n        << \"bitwidth:   \" << elt->bitwidth << \"\\n\"\n        << \"discard:    \" << elt->discard << \"\\n\"\n        << \"type:       \";\n\n      if (elt->type == textscan_format_elt::literal_conversion)\n        std::cerr << \"literal text\\n\";\n      else if (elt->type == textscan_format_elt::whitespace_conversion)\n        std::cerr << \"whitespace\\n\";\n      else\n        std::cerr << elt->type << \"\\n\";\n\n      std::cerr\n        << \"char_class: '\" << undo_string_escapes (elt->char_class) << \"'\\n\"\n        << \"text:       '\" << undo_string_escapes (elt->text) << \"'\\n\\n\";\n    }\n}\n\n// If FORMAT is explicitly \"\", it is assumed to be \"%f\" repeated enough\n// times to read the first row of the file.  Set it now.\n\nint\ntextscan_format_list::read_first_row (delimited_stream& is, textscan& ts)\n{\n  // Read first line and strip end-of-line, which may be two characters\n  std::string first_line (20, ' ');\n\n  is.getline (first_line, static_cast<char> (ts.m_eol2));\n\n  if (! first_line.empty () && first_line.back () == ts.m_eol1)\n    first_line.pop_back ();\n\n  std::istringstream strstr (first_line);\n  delimited_stream ds (strstr, is);\n\n  dim_vector dv (1, 1);     // initial size of each output_container\n  Complex val;\n  octave_value val_type;\n  m_nconv = 0;\n  int max_empty = 1000;     // failsafe, if ds fails but not with eof\n  int retval = 0;\n\n  // read line, creating output_container as we go\n  while (! ds.eof ())\n    {\n      bool already_skipped_delim = false;\n      ts.skip_whitespace (ds, false);\n      ds.progress_benchmark ();\n      ts.scan_complex (ds, *m_fmt_elts[0], val);\n      if (ds.fail ())\n        {\n          ds.clear (ds.rdstate () & ~std::ios::failbit);\n\n          if (ds.eof ())\n            break;\n\n          // Unless this was a missing value (i.e., followed by a delimiter),\n          // return with an error status.\n          ts.skip_delim (ds);\n          if (ds.no_progress ())\n            {\n              retval = 4;\n              break;\n            }\n          already_skipped_delim = true;\n\n          val = ts.m_empty_value.scalar_value ();\n\n          if (! --max_empty)\n            break;\n        }\n\n      if (val.imag () == 0)\n        val_type = octave_value (NDArray (dv, val.real ()));\n      else\n        val_type = octave_value (ComplexNDArray (dv, val));\n\n      m_output_container.push_back (val_type);\n\n      if (! already_skipped_delim)\n        ts.skip_delim (ds);\n\n      if (ds.no_progress ())\n        break;\n\n      m_nconv++;\n    }\n\n  m_output_container.pop_front (); // discard empty element from constructor\n\n  // Create fmt_list now that the size is known\n  for (octave_idx_type i = 1; i < m_nconv; i++)\n    m_fmt_elts.push_back (new textscan_format_elt (*m_fmt_elts[0]));\n\n  return retval;             // May have returned 4 above.\n}\n\ntextscan::textscan (const std::string& who_arg, const std::string& encoding)\n  : m_who (who_arg), m_encoding (encoding), m_buf (), m_whitespace_table (),\n    m_delim_table (), m_delims (), m_comment_style (), m_comment_len (0),\n    m_comment_char (-2), m_buffer_size (0), m_date_locale (),\n    m_inf_nan (init_inf_nan ()),\n    m_empty_value (numeric_limits<double>::NaN ()),\n    m_exp_chars (\"edED\"), m_header_lines (0), m_treat_as_empty (),\n    m_treat_as_empty_len (0), m_whitespace (\" \\b\\t\"), m_eol1 ('\\r'),\n    m_eol2 ('\\n'), m_return_on_error (1), m_collect_output (false),\n    m_multiple_delims_as_one (false), m_default_exp (true), m_lines (0)\n{ }\n\noctave_value\ntextscan::scan (std::istream& isp, const std::string& fmt,\n                octave_idx_type ntimes, const octave_value_list& options,\n                octave_idx_type& count)\n{\n  textscan_format_list fmt_list (fmt);\n\n  parse_options (options, fmt_list);\n\n  octave_value result = do_scan (isp, fmt_list, ntimes);\n\n  // FIXME: this is probably not the best way to get count.  The\n  // position could easily be larger than octave_idx_type when using\n  // 32-bit indexing.\n\n  std::ios::iostate state = isp.rdstate ();\n  isp.clear ();\n  count = static_cast<octave_idx_type> (isp.tellg ());\n  isp.setstate (state);\n\n  return result;\n}\n\noctave_value\ntextscan::do_scan (std::istream& isp, textscan_format_list& fmt_list,\n                   octave_idx_type ntimes)\n{\n  octave_value retval;\n\n  if (fmt_list.num_conversions () == -1)\n    error (\"%s: invalid format specified\", m_who.c_str ());\n\n  if (fmt_list.num_conversions () == 0)\n    error (\"%s: no valid format conversion specifiers\", m_who.c_str ());\n\n  // skip the first header_lines\n  std::string dummy;\n  for (int i = 0; i < m_header_lines && isp; i++)\n    getline (isp, dummy, static_cast<char> (m_eol2));\n\n  // Create our own buffered stream, for fast get/putback/tell/seek.\n\n  // First, see how far ahead it should let us look.\n  int max_lookahead = std::max ({m_comment_len, m_treat_as_empty_len,\n                                 m_delim_len, 3});  // 3 for NaN and Inf\n\n  // Next, choose a buffer size to avoid reading too much, or too often.\n  octave_idx_type buf_size = 4096;\n  if (m_buffer_size)\n    buf_size = m_buffer_size;\n  else if (ntimes > 0)\n    {\n      // Avoid overflow of 80*ntimes...\n      buf_size = std::min (buf_size, std::max (ntimes, 80 * ntimes));\n      buf_size = std::max (buf_size, ntimes);\n    }\n  // Finally, create the stream.\n  delimited_stream is (isp,\n                       (m_delims.empty () ? m_whitespace + \"\\r\\n\"\n                                          : m_delims),\n                       max_lookahead, buf_size);\n\n  // Grow retval dynamically.  \"size\" is half the initial size\n  // (FIXME: Should we start smaller if ntimes is large?)\n  octave_idx_type size = ((ntimes < 8 && ntimes >= 0) ? ntimes : 1);\n  Array<octave_idx_type> row_idx (dim_vector (1, 2));\n  row_idx(1) = 0;\n\n  int err = 0;\n  octave_idx_type row = 0;\n\n  if (m_multiple_delims_as_one)           // bug #44750?\n    skip_delim (is);\n\n  int done_after;  // Number of columns read when EOF seen.\n\n  // If FORMAT explicitly \"\", read first line and see how many \"%f\" match\n  if (fmt_list.set_from_first)\n    {\n      err = fmt_list.read_first_row (is, *this);\n      m_lines = 1;\n\n      done_after = fmt_list.numel () + 1;\n      if (! err)\n        row = 1;  // the above puts the first line into fmt_list.out_buf ()\n    }\n  else\n    done_after = fmt_list.out_buf ().size () + 1;\n\n  std::list<octave_value> out = fmt_list.out_buf ();\n\n  // We will later merge adjacent columns of the same type.\n  // Check now which columns to merge.\n  // Reals may become complex, and so we can't trust types\n  // after reading in data.\n  // If the format was \"\", that conversion may already have happened,\n  // so force all to be merged (as all are %f).\n  std::vector<bool> merge_with_prev (fmt_list.numel ());\n  int conv = 0;\n  if (m_collect_output)\n    {\n      int prev_type = -1;\n      for (const auto& col : out)\n        {\n          if (col.type_id () == prev_type\n              || (fmt_list.set_from_first && prev_type != -1))\n            merge_with_prev[conv++] = true;\n          else\n            merge_with_prev[conv++] = false;\n\n          prev_type = col.type_id ();\n        }\n    }\n\n  // This should be caught by earlier code, but this avoids a possible\n  // infinite loop below.\n  if (fmt_list.num_conversions () == 0)\n    error (\"%s: No conversions specified\", m_who.c_str ());\n\n  // Read the data.  This is the main loop.\n  if (! err)\n    {\n      for (/* row set ~30 m_lines above */;\n           row < ntimes || ntimes == -1;\n           row++)\n        {\n          if (row == 0 || row >= size)\n            {\n              size += (size+1);\n              for (auto& col : out)\n                col = col.resize (dim_vector (size, 1), 0);\n            }\n\n          row_idx(0) = row;\n          err = read_format_once (is, fmt_list, out, row_idx, done_after);\n\n          if ((err & ~1) > 0 || ! is || (m_lines >= ntimes && ntimes > -1))\n            break;\n        }\n    }\n\n  if ((err & 4) && ! m_return_on_error)\n    error (\"%s: Read error in field %d of row %\" OCTAVE_IDX_TYPE_FORMAT,\n           m_who.c_str (), done_after + 1, row + 1);\n\n  // If file does not end in EOL, do not pad columns with NaN.\n  bool uneven_columns = false;\n  if (err & 4)\n    uneven_columns = true;\n  else if (isp.eof ())\n    {\n      isp.clear ();\n      isp.seekg (-1, std::ios_base::end);\n      int last_char = isp.get ();\n      isp.setstate (isp.eofbit);\n      uneven_columns = (last_char != m_eol1 && last_char != m_eol2);\n    }\n\n  // convert return value to Cell array\n  Array<octave_idx_type> ra_idx (dim_vector (1, 2));\n\n  // (err & 1) means \"error, and no columns read this row\n  // FIXME: This may redundant now that done_after=0 says the same\n  if (err & 1)\n    done_after = out.size () + 1;\n\n  int valid_rows = (row == ntimes\n                    ? ntimes\n                    : ((err & 1) && (err & 8)) ? row : row+1);\n  dim_vector dv (valid_rows, 1);\n\n  ra_idx(0) = 0;\n  int i = 0;\n  if (! m_collect_output)\n    {\n      retval = Cell (dim_vector (1, out.size ()));\n      for (auto& col : out)\n        {\n          // trim last columns if that was requested\n          if (i == done_after && uneven_columns)\n            dv = dim_vector (std::max (valid_rows - 1, 0), 1);\n\n          ra_idx(1) = i;\n          retval = cat_op (retval, octave_value (Cell (col.resize (dv, 0))),\n                           ra_idx);\n          i++;\n        }\n    }\n  else  // group adjacent cells of the same type into a single cell\n    {\n      octave_value cur;                // current cell, accumulating columns\n      octave_idx_type group_size = 0;  // columns in this cell\n      int prev_type = -1;\n\n      conv = 0;\n      retval = Cell ();\n      for (auto& col : out)\n        {\n          if (! merge_with_prev[conv++])  // including first time\n            {\n              if (prev_type != -1)\n                {\n                  ra_idx(1) = i++;\n                  retval = cat_op (retval, octave_value (Cell (cur)), ra_idx);\n                }\n              cur = octave_value (col.resize (dv, 0));\n              group_size = 1;\n              prev_type = col.type_id ();\n            }\n          else\n            {\n              ra_idx(1) = group_size++;\n              cur = cat_op (cur, octave_value (col.resize (dv, 0)), ra_idx);\n            }\n        }\n      ra_idx(1) = i;\n      retval = cat_op (retval, octave_value (Cell (cur)), ra_idx);\n    }\n\n  return retval;\n}\n\n// Read a double considering the \"precision\" field of FMT and the\n// EXP_CHARS option of OPTIONS.\n\ndouble\ntextscan::read_double (delimited_stream& is,\n                       const textscan_format_elt& fmt) const\n{\n  int sign = 1;\n  unsigned int width_left = fmt.width;\n  double retval = 0;\n  bool valid = false;         // syntactically correct double?\n\n  int ch = is.peek_undelim ();\n\n  if (ch == '+')\n    {\n      is.get ();\n      ch = is.peek_undelim ();\n      if (width_left)\n        width_left--;\n    }\n  else if (ch == '-')\n    {\n      sign = -1;\n      is.get ();\n      ch = is.peek_undelim ();\n      if (width_left)\n        width_left--;\n    }\n\n  // Read integer part\n  if (ch != '.')\n    {\n      if (ch >= '0' && ch <= '9')       // valid if at least one digit\n        valid = true;\n      while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')\n        retval = retval * 10 + (ch - '0');\n      width_left++;\n    }\n\n  // Read fractional part, up to specified precision\n  if (ch == '.' && width_left)\n    {\n      double multiplier = 1;\n      int precision = fmt.prec;\n      int i;\n\n      width_left--;                  // Consider width of '.'\n\n      if (precision == -1)\n        precision = 1<<30;           // FIXME: Should be MAXINT\n\n      if (! valid)                   // if there was nothing before '.'...\n        is.get ();                   // ...ch was a \"peek\", not \"get\".\n\n      for (i = 0; i < precision; i++)\n        {\n          if (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')\n            retval += (ch - '0') * (multiplier *= 0.1);\n          else\n            {\n              width_left++;\n              break;\n            }\n        }\n\n      // round up if we truncated and the next digit is >= 5\n      if ((i == precision || ! width_left) && (ch = is.get ()) >= '5'\n          && ch <= '9')\n        retval += multiplier;\n\n      if (i > 0)\n        valid = true;           // valid if at least one digit after '.'\n      else if (! valid)         // if there was nothing before and after '.'\n        {\n          is.putback (ch);\n          ch = '.';\n        }\n\n      // skip remainder after '.', to field width, to look for exponent\n      if (i == precision)\n        while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')\n          ;  // discard\n\n      width_left++;\n    }\n\n  // look for exponent part in, e.g., 6.023E+23\n  bool used_exp = false;\n  if (valid && width_left > 1 && m_exp_chars.find (ch) != std::string::npos)\n    {\n      int ch1 = is.peek_undelim ();\n      if (ch1 == '-' || ch1 == '+' || (ch1 >= '0' && ch1 <= '9'))\n        {\n          // if 1.0e+$ or some such, this will set failbit, as we want\n          width_left--;                         // count \"E\"\n          int exp = 0;\n          int exp_sign = 1;\n          if (ch1 == '+')\n            {\n              width_left--;\n              is.get ();\n            }\n          else if (ch1 == '-')\n            {\n              width_left--;\n              exp_sign = -1;\n              is.get ();\n            }\n          valid = false;\n          while (width_left-- && is && (ch = is.get_undelim ()) >= '0' && ch <= '9')\n            {\n              exp = exp*10 + ch - '0';\n              valid = true;\n            }\n          width_left++;\n          if (ch != std::istream::traits_type::eof () && width_left)\n            is.putback (ch);\n\n          double multiplier = pown (10, exp);\n          if (exp_sign > 0)\n            retval *= multiplier;\n          else\n            retval /= multiplier;\n\n          used_exp = true;\n        }\n    }\n  is.clear ();\n  if (! used_exp && ch != std::istream::traits_type::eof () && width_left)\n    is.putback (ch);\n\n  // Check for +/- inf and NaN\n  if (! valid && width_left >= 3 && is.remaining () >= 3)\n    {\n      int i = lookahead (is, m_inf_nan, 3, false);  // false->case insensitive\n      if (i == 0)\n        {\n          retval = numeric_limits<double>::Inf ();\n          valid = true;\n        }\n      else if (i == 1)\n        {\n          retval = numeric_limits<double>::NaN ();\n          valid = true;\n        }\n    }\n\n  if (! valid)\n    is.setstate (std::ios::failbit);\n  else\n    is.setstate (is.rdstate () & ~std::ios::failbit);\n\n  return retval * sign;\n}\n\n// Read a single number: real, complex, inf, NaN, possibly with limited\n// precision.  Calls to this should be preceded by skip_whitespace.\n// Calling that inside scan_complex would violate its const declaration.\n\nvoid\ntextscan::scan_complex (delimited_stream& is, const textscan_format_elt& fmt,\n                        Complex& val) const\n{\n  double im = 0;\n  double re = 0;\n  bool as_empty = false;  // did we fail but match a \"treat_as_empty\" string?\n  bool inf = false;\n\n  int ch = is.peek_undelim ();\n  if (ch == '+' || ch == '-')   // check for [+-][ij] with no coefficients\n    {\n      ch = is.get ();\n      int ch2 = is.peek_undelim ();\n      if (ch2 == 'i' || ch2 == 'j')\n        {\n          double value = 1;\n          is.get ();\n          // Check not -inf\n          if (is.peek_undelim () == 'n')\n            {\n              char *pos = is.tellg ();\n              std::ios::iostate state = is.rdstate ();\n\n              is.get ();\n              ch2 = is.get_undelim ();\n              if (ch2 == 'f')\n                {\n                  inf = true;\n                  re = (ch == '+' ? numeric_limits<double>::Inf ()\n                                  : -numeric_limits<double>::Inf ());\n                  value = 0;\n                }\n              else\n                {\n                  is.clear (state);\n                  // FIXME: Buffer might have refreshed.\n                  //        pos might no longer be valid.\n                  is.seekg (pos);   // reset to position before look-ahead\n                }\n            }\n\n          im = (ch == '+') ? value : -value;\n        }\n      else\n        is.putback (ch);\n    }\n\n  if (! im && ! inf)        // if not [+-][ij] or [+-]inf, read real normally\n    {\n      char *pos = is.tellg ();\n      std::ios::iostate state = is.rdstate ();\n      //re = read_value<double> (is);\n      // FIXME: read_double might refresh the buffer.  So seekg might be off.\n      re = read_double (is, fmt);\n\n      // check for \"treat as empty\" string\n      if (m_treat_as_empty.numel ()\n          && (is.fail () || math::is_NaN_or_NA (Complex (re))\n              || re == numeric_limits<double>::Inf ()))\n        {\n\n          for (int i = 0; i < m_treat_as_empty.numel (); i++)\n            {\n              if (ch == m_treat_as_empty (i).string_value ()[0])\n                {\n                  as_empty = true;  // first char matches, so read the lot\n                  break;\n                }\n            }\n          if (as_empty)             // if first char matched...\n            {\n              as_empty = false;     // ...look for the whole string\n\n              is.clear (state);     // treat_as_empty \"-\" causes partial read\n              is.seekg (pos);       // reset to position before failed read\n\n              // treat_as_empty strings may be different sizes.\n              // Read ahead longest, put it all back, then re-read the string\n              // that matches.\n              std::string look_buf (m_treat_as_empty_len, '\\0');\n              char *look = is.read (&look_buf[0], look_buf.size (), pos);\n\n              is.clear (state);\n              is.seekg (pos);        // reset to position before look-ahead\n                                     // FIXME: is.read could invalidate pos\n\n              for (int i = 0; i < m_treat_as_empty.numel (); i++)\n                {\n                  std::string s = m_treat_as_empty (i).string_value ();\n                  if (! strncmp (s.c_str (), look, s.size ()))\n                    {\n                      as_empty = true;\n                      // read just the right amount\n                      is.read (&look_buf[0], s.size (), pos);\n                      break;\n                    }\n                }\n            }\n        }\n\n      if (! is.eof () && ! as_empty)\n        {\n          state = is.rdstate ();   // before tellg, since that fails at EOF\n\n          ch = is.peek_undelim ();\n          // ch == EOF if read failed; no need to chk fail\n          if (ch == 'i' || ch == 'j')           // pure imaginary\n            {\n              is.get ();\n              im = re;\n              re = 0;\n            }\n          else if (ch == '+' || ch == '-')      // see if it is real+imag[ij]\n            {\n              // save stream state in case we have to restore it\n              pos   = is.tellg ();\n              state = is.rdstate ();\n\n              //im = read_value<double> (is);\n              // FIXME: read_double might refresh the buffer.\n              //        So seekg might be off after this.\n              im = read_double (is, fmt);\n              if (is.fail ())\n                im = 1;\n\n              if (is.peek_undelim () == 'i' || is.peek_undelim () == 'j')\n                is.get ();\n              else\n                {\n                  im = 0;           // no valid imaginary part.  Restore state\n                  is.clear (state); // eof shouldn't cause fail.\n                  is.seekg (pos);\n                }\n            }\n          else if (is.eof ())       // we've read enough to be a \"valid\" read\n            is.clear (state);       // failed peek shouldn't cause fail\n        }\n    }\n  if (as_empty)\n    val = m_empty_value.scalar_value ();\n  else\n    val = Complex (re, im);\n}\n\n// Return in VAL the run of characters from IS NOT contained in PATTERN.\n\nint\ntextscan::scan_caret (delimited_stream& is, const std::string& pattern,\n                      std::string& val) const\n{\n  int c1 = std::istream::traits_type::eof ();\n  std::ostringstream obuf;   // FIXME: is this optimized for growing?\n\n  while (is && ((c1 = (is && ! is.eof ())\n                      ? is.get_undelim ()\n                      : std::istream::traits_type::eof ())\n                != std::istream::traits_type::eof ())\n         && pattern.find (c1) == std::string::npos)\n    obuf << static_cast<char> (c1);\n\n  val = obuf.str ();\n\n  if (c1 != std::istream::traits_type::eof ())\n    is.putback (c1);\n\n  return c1;\n}\n\n// Read until one of the strings in DELIMITERS is found.  For\n// efficiency, ENDS is a list of the last character of each delimiter.\n\nstd::string\ntextscan::read_until (delimited_stream& is, const Cell& delimiters,\n                      const std::string& ends) const\n{\n  std::string retval (\"\");\n  bool done = false;\n  do\n    {\n      // find sequence ending with an ending char\n      std::string next;\n      scan_caret (is, ends.c_str (), next);\n      retval = retval + next;   // FIXME: could use repeated doubling of size\n\n      int last = (! is.eof ()\n                  ? is.get_undelim () : std::istream::traits_type::eof ());\n\n      if (last != std::istream::traits_type::eof ())\n        {\n          if (last == m_eol1 || last == m_eol2)\n            break;\n\n          retval = retval + static_cast<char> (last);\n          for (int i = 0; i < delimiters.numel (); i++)\n            {\n              std::string delim = delimiters(i).string_value ();\n              std::size_t start = (retval.length () > delim.length ()\n                                   ? retval.length () - delim.length ()\n                                   : 0);\n              std::string may_match = retval.substr (start);\n              if (may_match == delim)\n                {\n                  done = true;\n                  retval = retval.substr (0, start);\n                  if (start == 0)\n                    is.putback (last);\n                  break;\n                }\n            }\n        }\n    }\n  while (! done && is && ! is.eof ());\n\n  return retval;\n}\n\n// Read stream until either fmt.width chars have been read, or\n// options.delimiter has been found.  Does *not* rely on fmt being 's'.\n// Used by formats like %6f to limit to 6.\n\nvoid\ntextscan::scan_string (delimited_stream& is, const textscan_format_elt& fmt,\n                       std::string& val) const\n{\n  if (m_delim_list.isempty ())\n    {\n      unsigned int i = 0;\n      unsigned int width = fmt.width;\n\n      for (i = 0; i < width; i++)\n        {\n          // Grow string in an exponential fashion if necessary.\n          if (i >= val.length ())\n            val.append (std::max (val.length (),\n                                  static_cast<std::size_t> (16)), '\\0');\n\n          int ch = is.get_undelim ();\n          if (is_delim (ch) || ch == std::istream::traits_type::eof ())\n            {\n              is.putback (ch);\n              break;\n            }\n          else\n            val[i] = ch;\n        }\n      val = val.substr (0, i);          // trim pre-allocation\n    }\n  else  // Cell array of multi-character delimiters\n    {\n      std::string ends (m_delim_list.numel () + 2, '\\0');\n      int i;\n      for (i = 0; i < m_delim_list.numel (); i++)\n        {\n          std::string tmp = m_delim_list(i).string_value ();\n          ends[i] = tmp.back ();\n        }\n      ends[i++] = m_eol1;\n      ends[i++] = m_eol2;\n      val = textscan::read_until (is, m_delim_list, ends);\n    }\n\n  // convert from codepage\n  if (m_encoding.compare (\"utf-8\"))\n    val = string::u8_from_encoding (\"textscan\", val, m_encoding);\n}\n\n// Return in VAL the run of characters from IS contained in PATTERN.\n\nint\ntextscan::scan_bracket (delimited_stream& is, const std::string& pattern,\n                        std::string& val) const\n{\n  int c1 = std::istream::traits_type::eof ();\n  std::ostringstream obuf;              // Is this optimized for growing?\n\n  while (is && pattern.find (c1 = is.get_undelim ()) != std::string::npos)\n    obuf << static_cast<char> (c1);\n\n  val = obuf.str ();\n  if (c1 != std::istream::traits_type::eof ())\n    is.putback (c1);\n  return c1;\n}\n\n// Return in VAL a string, either delimited by whitespace/delimiters, or\n// enclosed in a pair of double quotes (\"...\").  Enclosing quotes are\n// removed.  A consecutive pair \"\" is inserted into VAL as a single \".\n\nvoid\ntextscan::scan_qstring (delimited_stream& is, const textscan_format_elt& fmt,\n                        std::string& val)\n{\n  skip_whitespace (is);\n\n  if (is.peek_undelim () != '\"')\n    scan_string (is, fmt, val);\n  else\n    {\n      is.get ();\n      scan_caret (is, R\"(\")\", val);     // read everything until \"\n      is.get ();                        // swallow \"\n\n      while (is && is.peek_undelim () == '\"')  // if double \",\n        {                                      // insert one in stream,\n          is.get ();                           // keep looking for single \"\n          std::string val1;\n          scan_caret (is, R\"(\")\", val1);\n          val = val + '\"' + val1;\n          is.get_undelim ();\n        }\n    }\n\n  // convert from codepage\n  if (m_encoding.compare (\"utf-8\"))\n    val = string::u8_from_encoding (\"textscan\", val, m_encoding);\n}\n\n// Read from IS into VAL a string of the next fmt.width characters,\n// including any whitespace or delimiters.\n\nvoid\ntextscan::scan_cstring (delimited_stream& is, const textscan_format_elt& fmt,\n                        std::string& val) const\n{\n  val.resize (fmt.width);\n\n  for (unsigned int i = 0; is && i < fmt.width; i++)\n    {\n      int ch = is.get_undelim ();\n      if (ch != std::istream::traits_type::eof ())\n        val[i] = ch;\n      else\n        {\n          val.resize (i);\n          break;\n        }\n    }\n\n  // convert from codepage\n  if (m_encoding.compare (\"utf-8\"))\n    val = string::u8_from_encoding (\"textscan\", val, m_encoding);\n}\n\n//  Read a single '%...' conversion and place it in position ROW of OV.\n\nvoid\ntextscan::scan_one (delimited_stream& is, const textscan_format_elt& fmt,\n                    octave_value& ov, Array<octave_idx_type> row)\n{\n  skip_whitespace (is);\n\n  is.clear ();\n\n  octave_value val;\n  if (fmt.numeric)\n    {\n      if (fmt.type == 'f' || fmt.type == 'n')\n        {\n          Complex v;\n          skip_whitespace (is);\n          scan_complex (is, fmt, v);\n\n          if (! fmt.discard && ! is.fail ())\n            {\n              if (fmt.bitwidth == 64)\n                {\n                  if (ov.isreal () && v.imag () == 0)\n                    ov.internal_rep ()->fast_elem_insert (row(0), v.real ());\n                  else\n                    {\n                      if (ov.isreal ())  // cat does type conversion\n                        ov = cat_op (ov, octave_value (v), row);\n                      else\n                        ov.internal_rep ()->fast_elem_insert (row(0), v);\n                    }\n                }\n              else\n                {\n                  if (ov.isreal () && v.imag () == 0)\n                    ov.internal_rep ()->fast_elem_insert (row(0),\n                                                          float (v.real ()));\n                  else\n                    {\n                      if (ov.isreal ())  // cat does type conversion\n                        ov = cat_op (ov, octave_value (v), row);\n                      else\n                        ov.internal_rep ()->fast_elem_insert (row(0),\n                                                              FloatComplex (v));\n                    }\n                }\n            }\n        }\n      else\n        {\n          double v;    // Matlab docs say 1e30 etc should be valid for %d and\n                       // 1000 as a %d8 should be 127, so read as double.\n                       // Some loss of precision for d64 and u64.\n          skip_whitespace (is);\n          v = read_double (is, fmt);\n          if (! fmt.discard && ! is.fail ())\n            switch (fmt.bitwidth)\n              {\n              case 64:\n                switch (fmt.type)\n                  {\n                  case 'd':\n                    {\n                      octave_int64 vv = v;\n                      ov.internal_rep ()->fast_elem_insert (row(0), vv);\n                    }\n                    break;\n\n                  case 'u':\n                    {\n                      octave_uint64 vv = v;\n                      ov.internal_rep ()->fast_elem_insert (row(0), vv);\n                    }\n                    break;\n                  }\n                break;\n\n              case 32:\n                switch (fmt.type)\n                  {\n                  case 'd':\n                    {\n                      octave_int32 vv = v;\n                      ov.internal_rep ()->fast_elem_insert (row(0), vv);\n                    }\n                    break;\n\n                  case 'u':\n                    {\n                      octave_uint32 vv = v;\n                      ov.internal_rep ()->fast_elem_insert (row(0), vv);\n                    }\n                    break;\n                  }\n                break;\n\n              case 16:\n                if (fmt.type == 'd')\n                  {\n                    octave_int16 vv = v;\n                    ov.internal_rep ()->fast_elem_insert (row(0), vv);\n                  }\n                else\n                  {\n                    octave_uint16 vv = v;\n                    ov.internal_rep ()->fast_elem_insert (row(0), vv);\n                  }\n                break;\n\n              case 8:\n                if (fmt.type == 'd')\n                  {\n                    octave_int8 vv = v;\n                    ov.internal_rep ()->fast_elem_insert (row(0), vv);\n                  }\n                else\n                  {\n                    octave_uint8 vv = v;\n                    ov.internal_rep ()->fast_elem_insert (row(0), vv);\n                  }\n                break;\n              }\n        }\n\n      if (is.fail () & ! fmt.discard)\n        ov = cat_op (ov, m_empty_value, row);\n    }\n  else\n    {\n      std::string vv (\"        \");      // initial buffer.  Grows as needed\n      switch (fmt.type)\n        {\n        case 's':\n          scan_string (is, fmt, vv);\n          break;\n\n        case 'q':\n          scan_qstring (is, fmt, vv);\n          break;\n\n        case 'c':\n          scan_cstring (is, fmt, vv);\n          break;\n\n        case '[':\n          scan_bracket (is, fmt.char_class.c_str (), vv);\n          break;\n\n        case '^':\n          scan_caret   (is, fmt.char_class.c_str (), vv);\n          break;\n        }\n\n      if (! fmt.discard)\n        ov.internal_rep ()->fast_elem_insert (row (0),\n                                              Cell (octave_value (vv)));\n\n      // FIXME: why does failbit get set at EOF, instead of eofbit?\n      if (! vv.empty ())\n        is.clear (is.rdstate () & ~std::ios_base::failbit);\n    }\n\n  is.field_done ();\n}\n\n// Read data corresponding to the entire format string once, placing the\n// values in row ROW of retval.\n\nint\ntextscan::read_format_once (delimited_stream& is,\n                            textscan_format_list& fmt_list,\n                            std::list<octave_value>& retval,\n                            Array<octave_idx_type> row, int& done_after)\n{\n  const textscan_format_elt *elem = fmt_list.first ();\n  auto out = retval.begin ();\n  bool no_conversions = true;\n  bool done = false;\n  bool conversion_failed = false;       // Record for ReturnOnError\n  bool nothing_worked = true;\n\n  octave_quit ();\n\n  for (std::size_t i = 0; i < fmt_list.numel (); i++)\n    {\n      bool this_conversion_failed = false;\n\n      // Clear fail of previous numeric conversions.\n      is.clear ();\n\n      switch (elem->type)\n        {\n        case 'C':\n        case 'D':\n          warning (\"%s: conversion %c not yet implemented\",\n                   m_who.c_str (), elem->type);\n          break;\n\n        case 'u':\n        case 'd':\n        case 'f':\n        case 'n':\n        case 's':\n        case '[':\n        case '^':\n        case 'q':\n        case 'c':\n          scan_one (is, *elem, *out, row);\n          break;\n\n        case textscan_format_elt::literal_conversion :\n          match_literal (is, *elem);\n          break;\n\n        default:\n          error (\"Unknown format element '%c'\", elem->type);\n        }\n\n      if (! is.fail ())\n        {\n          if (! elem->discard)\n            no_conversions = false;\n        }\n      else\n        {\n          is.clear (is.rdstate () & ~std::ios::failbit);\n\n          if (! is.eof ())\n            {\n              if (m_delim_list.isempty ())\n                {\n                  if (! is_delim (is.peek_undelim ()))\n                    this_conversion_failed = true;\n                }\n              else  // Cell array of multi-character delimiters\n                {\n                  char *pos = is.tellg ();\n                  if (-1 == lookahead (is, m_delim_list, m_delim_len))\n                    this_conversion_failed = true;\n                  is.clear ();\n                  is.seekg (pos);     // reset to position before look-ahead\n                }\n            }\n        }\n\n      if (! elem->discard)\n        out++;\n\n      elem = fmt_list.next ();\n      char *pos = is.tellg ();\n\n      // Skip delimiter before reading the next fmt conversion,\n      // unless the fmt is a string literal which begins with a delimiter,\n      // in which case the literal must match everything.  Bug #58008\n      if (elem->type != textscan_format_elt::literal_conversion)\n        skip_delim (is);\n      else if (! is_delim (elem->text[0]))\n        skip_delim (is);\n\n      if (is.eof ())\n        {\n          if (! done)\n            done_after = i+1;\n\n          // note EOF, but process others to get empty_val.\n          done = true;\n        }\n\n      if (this_conversion_failed)\n        {\n          if (is.tellg () == pos && ! conversion_failed)\n            {\n              // done_after = first failure\n              done_after = i; // note fail, but parse others to get empty_val\n              conversion_failed = true;\n            }\n          else\n            this_conversion_failed = false;\n        }\n      else if (! done && ! conversion_failed)\n        nothing_worked = false;\n    }\n\n  if (done)\n    is.setstate (std::ios::eofbit);\n\n  return no_conversions\n         + (is.eof () ? 2 : 0)\n         + (conversion_failed ? 4 : 0)\n         + (nothing_worked ? 8 : 0);\n\n}\n\nvoid\ntextscan::parse_options (const octave_value_list& args,\n                         textscan_format_list& fmt_list)\n{\n  int last = args.length ();\n  int n = last;\n\n  if (n & 1)\n    error (\"%s: %d parameters given, but only %d values\",\n           m_who.c_str (), n-n/2, n/2);\n\n  m_delim_len = 1;\n  bool have_delims = false;\n  for (int i = 0; i < last; i += 2)\n    {\n      std::string param = args(i).xstring_value (\"%s: Invalid parameter type <%s> for parameter %d\",\n                                                 m_who.c_str (),\n                                                 args(i).type_name ().c_str (),\n                                                 i/2 + 1);\n      std::transform (param.begin (), param.end (), param.begin (), ::tolower);\n\n      if (param == \"delimiter\")\n        {\n          bool invalid = true;\n          if (args(i+1).is_string ())\n            {\n              invalid = false;\n              have_delims = true;\n              m_delims = args(i+1).string_value ();\n              if (args(i+1).is_sq_string ())\n                m_delims = do_string_escapes (m_delims);\n            }\n          else if (args(i+1).iscell ())\n            {\n              invalid = false;\n              m_delim_list = args(i+1).cell_value ();\n              m_delim_table = \" \";  // non-empty, to flag non-default delim\n\n              // Check that all elements are strings, and find max length\n              for (int j = 0; j < m_delim_list.numel (); j++)\n                {\n                  if (! m_delim_list(j).is_string ())\n                    invalid = true;\n                  else\n                    {\n                      if (m_delim_list(j).is_sq_string ())\n                        m_delim_list(j) = do_string_escapes (m_delim_list(j)\n                                                             .string_value ());\n                      octave_idx_type len = m_delim_list(j).string_value ()\n                                            .length ();\n                      m_delim_len = std::max (static_cast<int> (len),\n                                              m_delim_len);\n                    }\n                }\n            }\n          if (invalid)\n            error (\"%s: Delimiters must be either a string or cell array of strings\",\n                   m_who.c_str ());\n        }\n      else if (param == \"commentstyle\")\n        {\n          if (args(i+1).is_string ())\n            {\n              // check here for names like \"C++\", \"C\", \"shell\", ...?\n              m_comment_style = Cell (args(i+1));\n            }\n          else if (args(i+1).iscell ())\n            {\n              m_comment_style = args(i+1).cell_value ();\n              int len = m_comment_style.numel ();\n              if ((len >= 1 && ! m_comment_style (0).is_string ())\n                  || (len >= 2 && ! m_comment_style (1).is_string ())\n                  || (len >= 3))\n                error (\"%s: CommentStyle must be either a string or cell array of one or two strings\",\n                       m_who.c_str ());\n            }\n          else\n            error (\"%s: CommentStyle must be either a string or cell array of one or two strings\",\n                   m_who.c_str ());\n\n          // How far ahead do we need to look to detect an open comment\n          // and which character do we look for?\n          if (m_comment_style.numel () >= 1)\n            {\n              m_comment_len  = m_comment_style (0).string_value ().size ();\n              m_comment_char = m_comment_style (0).string_value ()[0];\n            }\n        }\n      else if (param == \"treatasempty\")\n        {\n          bool invalid = false;\n          if (args(i+1).is_string ())\n            {\n              m_treat_as_empty = Cell (args(i+1));\n              m_treat_as_empty_len = args(i+1).string_value ().size ();\n            }\n          else if (args(i+1).iscell ())\n            {\n              m_treat_as_empty = args(i+1).cell_value ();\n              for (int j = 0; j < m_treat_as_empty.numel (); j++)\n                if (! m_treat_as_empty (j).is_string ())\n                  invalid = true;\n                else\n                  {\n                    int k = m_treat_as_empty (j).string_value ().size ();\n                    if (k > m_treat_as_empty_len)\n                      m_treat_as_empty_len = k;\n                  }\n            }\n          if (invalid)\n            error (\"%s: TreatAsEmpty must be either a string or cell array of one or two strings\",\n                   m_who.c_str ());\n\n          // FIXME: Ensure none is a prefix of a later one.  Sort by length?\n        }\n      else if (param == \"collectoutput\")\n        {\n          m_collect_output = args(i+1).strict_bool_value (\"%s: CollectOutput must be logical or numeric\", m_who.c_str ());\n        }\n      else if (param == \"emptyvalue\")\n        {\n          m_empty_value = args(i+1).xscalar_value (\"%s: EmptyValue must be numeric\", m_who.c_str ());\n        }\n      else if (param == \"headerlines\")\n        {\n          m_header_lines = args(i+1).xscalar_value (\"%s: HeaderLines must be numeric\", m_who.c_str ());\n        }\n      else if (param == \"bufsize\")\n        {\n          m_buffer_size = args(i+1).xscalar_value (\"%s: BufSize must be numeric\", m_who.c_str ());\n        }\n      else if (param == \"multipledelimsasone\")\n        {\n          m_multiple_delims_as_one = args(i+1).strict_bool_value (\"%s: MultipleDelimsAsOne must be logical or numeric\", m_who.c_str ());\n        }\n      else if (param == \"returnonerror\")\n        {\n          m_return_on_error = args(i+1).strict_bool_value (\"%s: ReturnOnError must be logical or numeric\", m_who.c_str ());\n        }\n      else if (param == \"whitespace\")\n        {\n          m_whitespace = args(i+1).xstring_value (\"%s: Whitespace must be a character string\", m_who.c_str ());\n        }\n      else if (param == \"expchars\")\n        {\n          m_exp_chars = args(i+1).xstring_value (\"%s: ExpChars must be a character string\", m_who.c_str ());\n          m_default_exp = false;\n        }\n      else if (param == \"endofline\")\n        {\n          bool valid = true;\n          std::string s = args(i+1).xstring_value (R\"(%s: EndOfLine must be at most one character or '\\r\\n')\",\n                                                   m_who.c_str ());\n          if (args(i+1).is_sq_string ())\n            s = do_string_escapes (s);\n          int l = s.length ();\n          if (l == 0)\n            m_eol1 = m_eol2 = -2;\n          else if (l == 1)\n            m_eol1 = m_eol2 = s.c_str ()[0];\n          else if (l == 2)\n            {\n              m_eol1 = s.c_str ()[0];\n              m_eol2 = s.c_str ()[1];\n              if (m_eol1 != '\\r' || m_eol2 != '\\n')    // Why limit it?\n                valid = false;\n            }\n          else\n            valid = false;\n\n          if (! valid)\n            error (R\"(%s: EndOfLine must be at most one character or '\\r\\n')\",\n                   m_who.c_str ());\n        }\n      else\n        error (\"%s: unrecognized option '%s'\", m_who.c_str (), param.c_str ());\n    }\n\n  // Remove any user-supplied delimiter from whitespace list\n  for (unsigned int j = 0; j < m_delims.length (); j++)\n    {\n      m_whitespace.erase (std::remove (m_whitespace.begin (),\n                                       m_whitespace.end (),\n                                       m_delims[j]),\n                          m_whitespace.end ());\n    }\n  for (int j = 0; j < m_delim_list.numel (); j++)\n    {\n      std::string delim = m_delim_list(j).string_value ();\n      if (delim.length () == 1)\n        m_whitespace.erase (std::remove (m_whitespace.begin (),\n                                         m_whitespace.end (),\n                                         delim[0]),\n                            m_whitespace.end ());\n    }\n\n  m_whitespace_table = std::string (256, '\\0');\n  for (unsigned int i = 0; i < m_whitespace.length (); i++)\n    m_whitespace_table[m_whitespace[i]] = '1';\n\n  // For Matlab compatibility, add 0x20 to whitespace, unless\n  // whitespace is explicitly ignored.\n  if (! (m_whitespace.empty () && fmt_list.has_string))\n    m_whitespace_table[' '] = '1';\n\n  // Create look-up table of delimiters, based on 'delimiter'\n  m_delim_table = std::string (256, '\\0');\n  if (m_eol1 >= 0 && m_eol1 < 256)\n    m_delim_table[m_eol1] = '1';        // EOL is always a delimiter\n  if (m_eol2 >= 0 && m_eol2 < 256)\n    m_delim_table[m_eol2] = '1';        // EOL is always a delimiter\n  if (! have_delims)\n    for (unsigned int i = 0; i < 256; i++)\n      {\n        if (isspace (i))\n          m_delim_table[i] = '1';\n      }\n  else\n    for (unsigned int i = 0; i < m_delims.length (); i++)\n      m_delim_table[m_delims[i]] = '1';\n}\n\n// Skip comments, and characters specified by the \"Whitespace\" option.\n// If EOLstop == true, don't skip end of line.\n\nint\ntextscan::skip_whitespace (delimited_stream& is, bool EOLstop)\n{\n  int c1 = std::istream::traits_type::eof ();\n  bool found_comment = false;\n\n  do\n    {\n      found_comment = false;\n      int prev = -1;\n      while (is\n             && (c1 = is.get_undelim ()) != std::istream::traits_type::eof ()\n             && ( ( (c1 == m_eol1 || c1 == m_eol2) && ++m_lines && ! EOLstop)\n                  || isspace (c1)))\n        {\n          if (prev == m_eol1 && m_eol1 != m_eol2 && c1 == m_eol2)\n            m_lines--;\n          prev = c1;\n        }\n\n      if (c1 == m_comment_char)           // see if we match an open comment\n        {\n          // save stream state in case we have to restore it\n          char *pos = is.tellg ();\n          std::ios::iostate state = is.rdstate ();\n\n          std::string tmp (m_comment_len, '\\0');\n          char *look = is.read (&tmp[0], m_comment_len-1, pos); // already read first char\n          if (is && m_comment_style.numel () > 0\n              && ! strncmp (m_comment_style(0).string_value ().substr (1).c_str (),\n                            look, m_comment_len-1))\n            {\n              found_comment = true;\n\n              std::string dummy;\n              if (m_comment_style.numel () == 1)  // skip to end of line\n                {\n                  std::string eol (3, '\\0');\n                  eol[0] = m_eol1;\n                  eol[1] = m_eol2;\n\n                  scan_caret (is, eol, dummy);\n                  c1 = is.get_undelim ();\n                  if (c1 == m_eol1 && m_eol1 != m_eol2\n                      && is.peek_undelim () == m_eol2)\n                    is.get_undelim ();\n                  m_lines++;\n                }\n              else      // matching pair\n                {\n                  std::string end_c = m_comment_style(1).string_value ();\n                  // last char of end-comment sequence\n                  std::string last = end_c.substr (end_c.size () - 1);\n                  std::string may_match (\"\");\n                  do\n                    {\n                      // find sequence ending with last char\n                      scan_caret (is, last, dummy);\n                      is.get_undelim ();        // (read LAST itself)\n\n                      may_match = may_match + dummy + last;\n                      if (may_match.length () > end_c.length ())\n                        {\n                          std::size_t start = may_match.length ()\n                                              - end_c.length ();\n                          may_match = may_match.substr (start);\n                        }\n                    }\n                  while (may_match != end_c && is && ! is.eof ());\n                }\n            }\n          else  // wasn't really a comment; restore state\n            {\n              is.clear (state);\n              is.seekg (pos);\n            }\n        }\n    }\n  while (found_comment);\n\n  if (c1 != std::istream::traits_type::eof ())\n    is.putback (c1);\n\n  return c1;\n}\n\n// See if the next few characters match one of the strings in target.\n// For efficiency, MAX_LEN is the cached longest length of any target.\n// Return -1 if none is found, or the index of the match.\n\nint\ntextscan::lookahead (delimited_stream& is, const Cell& targets, int max_len,\n                     bool case_sensitive) const\n{\n  // target strings may be different sizes.\n  // Read ahead longest, put it all back, then re-read the string\n  // that matches.\n\n  char *pos = is.tellg ();\n\n  std::string tmp (max_len, '\\0');\n  char *look = is.read (&tmp[0], tmp.size (), pos);\n\n  is.clear ();\n  is.seekg (pos);              // reset to position before read\n                               // FIXME: pos may be corrupted by is.read\n\n  int i;\n  int (*compare)(const char *, const char *, std::size_t);\n  compare = (case_sensitive ? strncmp : octave_strncasecmp);\n\n  for (i = 0; i < targets.numel (); i++)\n    {\n      std::string s = targets (i).string_value ();\n      if (! (*compare) (s.c_str (), look, s.size ()))\n        {\n          is.read (&tmp[0], s.size (), pos); // read just the right amount\n          break;\n        }\n    }\n\n  if (i == targets.numel ())\n    i = -1;\n\n  return i;\n}\n\n// Skip delimiters -- multiple if MultipleDelimsAsOne specified.\nint\ntextscan::skip_delim (delimited_stream& is)\n{\n  int c1 = skip_whitespace (is);  // Stop once EOL is read\n  if (m_delim_list.numel () == 0)   // single character delimiter\n    {\n      if (is_delim (c1) || c1 == m_eol1 || c1 == m_eol2)\n        {\n          is.get ();\n          if (c1 == m_eol1 && is.peek_undelim () == m_eol2)\n            is.get ();          // if \\r\\n, skip the \\n too.\n\n          if (m_multiple_delims_as_one)\n            {\n              int prev = -1;\n              // skip multiple delims.\n              // Increment lines for each end-of-line seen;\n              // Decrement for \\r\\n\n              while (is && ((c1 = is.get_undelim ())\n                            != std::istream::traits_type::eof ())\n                     && (((c1 == m_eol1 || c1 == m_eol2) && ++m_lines)\n                         || isspace (c1) || is_delim (c1)))\n                {\n                  if (prev == m_eol1 && m_eol1 != m_eol2 && c1 == m_eol2)\n                    m_lines--;\n                  prev = c1;\n                }\n              if (c1 != std::istream::traits_type::eof ())\n                is.putback (c1);\n            }\n        }\n    }\n  else                                  // multi-character delimiter\n    {\n      int first_match;\n\n      if (c1 == m_eol1 || c1 == m_eol2\n          || (-1 != (first_match = lookahead (is, m_delim_list, m_delim_len))))\n        {\n          if (c1 == m_eol1)\n            {\n              is.get_undelim ();\n              if (is.peek_undelim () == m_eol2)\n                is.get_undelim ();\n            }\n          else if (c1 == m_eol2)\n            {\n              is.get_undelim ();\n            }\n\n          if (m_multiple_delims_as_one)\n            {\n              int prev = -1;\n              // skip multiple delims.\n              // Increment lines for each end-of-line seen;\n              // decrement for \\r\\n.\n              while (is && ((c1 = skip_whitespace (is))\n                            != std::istream::traits_type::eof ())\n                     && (((c1 == m_eol1 || c1 == m_eol2) && ++m_lines)\n                         || -1 != lookahead (is, m_delim_list, m_delim_len)))\n                {\n                  if (prev == m_eol1 && m_eol1 != m_eol2 && c1 == m_eol2)\n                    m_lines--;\n                  prev = c1;\n                }\n            }\n        }\n    }\n\n  return c1;\n}\n\n// Read in as much of the input as coincides with the literal in the\n// format string.  Return \"true\" if the entire literal is matched, else\n// false (and set failbit).\n\nbool\ntextscan::match_literal (delimited_stream& is,\n                         const textscan_format_elt& fmt)\n{\n  // \"false\" -> treat EOL as normal space\n  // since a delimiter at the start of a line is a mismatch, not empty field\n  skip_whitespace (is, false);\n\n  for (unsigned int i = 0; i < fmt.width; i++)\n    {\n      int ch = is.get_undelim ();\n      if (ch != fmt.text[i])\n        {\n          if (ch != std::istream::traits_type::eof ())\n            is.putback (ch);\n          is.setstate (std::ios::failbit);\n          return false;\n        }\n    }\n  return true;\n}\n\n// The std::wbuffer_convert template is deprecated in C++17.\n// A deprecation warning is emitted when using STL headers from LLVM libc++ or\n// GCC libstdc++ (for GCC 15 or newer).  If we used it directly as the type of\n// \"m_converter\", it would be included in many compilation units which would\n// result in a torrent of deprecation warnings when building Octave or anything\n// else that includes the header with those implementations of the STL.\n// Mask the type by deriving a class and silence these deprecation warning here\n// to have a more digestable build output.\n// FIXME: Implement alternative for stream encoding conversion that does not\n//        rely on deprecated features.\n\n#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n#endif\ntypedef string::deletable_facet<string::codecvt_u8> convfacet_u8;\ntypedef std::wbuffer_convert<convfacet_u8, char> converter;\n\nclass wbuffer_u8_converter : public converter\n{\n  public:\n    // inherit constructors\n    using converter::wbuffer_convert;\n};\n#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC\n#  pragma GCC diagnostic pop\n#endif\n\nbase_stream::~base_stream ()\n{\n  delete m_converter;\n}\n\nstd::ostream *\nbase_stream::create_converter_stream ()\n{\n  // wrap the output stream with encoding conversion facet\n  std::ostream *os = output_stream ();\n  if (os && *os && ! m_converter)\n    {\n      m_converter\n        = new wbuffer_u8_converter\n           (os->rdbuf (), new convfacet_u8 (m_encoding));\n      // FIXME: Using std::make_unique could simplify the following\n      //        expression once we require C++14.\n      m_conv_ostream\n        = std::unique_ptr<std::ostream> (new std::ostream (m_converter));\n    }\n\n  return (m_conv_ostream ? m_conv_ostream.get () : output_stream ());\n}\n\nvoid\nbase_stream::error (const std::string& msg)\n{\n  m_fail = true;\n  m_errmsg = msg;\n}\n\nvoid\nbase_stream::error (const std::string& who, const std::string& msg)\n{\n  m_fail = true;\n  m_errmsg = who + \": \" + msg;\n}\n\nvoid\nbase_stream::clear ()\n{\n  m_fail = false;\n  m_errmsg = \"\";\n}\n\nvoid\nbase_stream::clearerr ()\n{\n  std::istream *is = input_stream ();\n  std::ostream *os = preferred_output_stream ();\n\n  if (is)\n    is->clear ();\n\n  if (os)\n    os->clear ();\n}\n\n// Functions that are defined for all input streams (input streams\n// are those that define is).\n\nstd::string\nbase_stream::do_gets (octave_idx_type max_len, bool& err,\n                      bool strip_newline, const std::string& who)\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  if (interp.interactive () && file_number () == 0)\n    ::error (\"%s: unable to read from stdin while running interactively\",\n             who.c_str ());\n\n  std::string retval;\n\n  err = false;\n\n  std::istream *isp = input_stream ();\n\n  if (! isp)\n    {\n      err = true;\n      invalid_operation (who, \"reading\");\n    }\n  else\n    {\n      std::istream& is = *isp;\n\n      std::ostringstream buf;\n\n      int c = 0;\n      int char_count = 0;\n\n      if (max_len != 0)\n        {\n          while (is && (c = is.get ()) != std::istream::traits_type::eof ())\n            {\n              char_count++;\n\n              // Handle CRLF, CR, or LF as line ending.\n              if (c == '\\r')\n                {\n                  if (! strip_newline)\n                    buf << static_cast<char> (c);\n\n                  c = is.get ();\n\n                  if (c != std::istream::traits_type::eof ())\n                    {\n                      if (c == '\\n')\n                        {\n                          char_count++;\n\n                          if (! strip_newline)\n                            buf << static_cast<char> (c);\n                        }\n                      else\n                        is.putback (c);\n                    }\n\n                  break;\n                }\n              else if (c == '\\n')\n                {\n                  if (! strip_newline)\n                    buf << static_cast<char> (c);\n\n                  break;\n                }\n              else\n                buf << static_cast<char> (c);\n\n              if (max_len > 0 && char_count == max_len)\n                break;\n            }\n        }\n\n      if (! is.eof () && char_count > 0)\n        {\n          // GAGME.  Matlab seems to check for EOF even if the last character\n          // in a file is a newline character.  This is NOT what the\n          // corresponding C-library functions do.\n          int disgusting_compatibility_hack = is.get ();\n          if (! is.eof ())\n            is.putback (disgusting_compatibility_hack);\n        }\n\n      if (is.good () || (is.eof () && char_count > 0))\n        {\n          retval = buf.str ();\n          if (encoding ().compare (\"utf-8\"))\n            retval = string::u8_from_encoding (who, retval, encoding ());\n        }\n      else\n        {\n          err = true;\n\n          if (is.eof () && char_count == 0)\n            error (who, \"at end of file\");\n          else\n            error (who, \"read error\");\n        }\n    }\n\n  return retval;\n}\n\nstd::string\nbase_stream::getl (octave_idx_type max_len, bool& err,\n                   const std::string& who)\n{\n  return do_gets (max_len, err, true, who);\n}\n\nstd::string\nbase_stream::gets (octave_idx_type max_len, bool& err,\n                   const std::string& who)\n{\n  return do_gets (max_len, err, false, who);\n}\n\noff_t\nbase_stream::skipl (off_t num, bool& err, const std::string& who)\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  if (interp.interactive () && file_number () == 0)\n    ::error (\"%s: unable to read from stdin while running interactively\",\n             who.c_str ());\n\n  off_t cnt = -1;\n\n  err = false;\n\n  std::istream *isp = input_stream ();\n\n  if (! isp)\n    {\n      err = true;\n      invalid_operation (who, \"reading\");\n    }\n  else\n    {\n      std::istream& is = *isp;\n\n      int c = 0;\n      int lastc = -1;\n      cnt = 0;\n\n      while (is && (c = is.get ()) != std::istream::traits_type::eof ())\n        {\n          // Handle CRLF, CR, or LF as line ending.\n          if (c == '\\r' || (c == '\\n' && lastc != '\\r'))\n            {\n              if (++cnt == num)\n                break;\n            }\n\n          lastc = c;\n        }\n\n      // Maybe eat the following \\n if \\r was just met.\n      if (c == '\\r' && is.peek () == '\\n')\n        is.get ();\n\n      if (is.bad ())\n        {\n          err = true;\n          error (who, \"read error\");\n        }\n\n      if (err)\n        cnt = -1;\n    }\n\n  return cnt;\n}\n\ntemplate <typename T>\nstatic std::istream&\noctave_scan_1 (std::istream& is, const scanf_format_elt& fmt,\n               T *valptr)\n{\n  T value = T ();\n\n  is >> std::ws;  // skip through whitespace and advance stream pointer\n  std::streampos pos = is.tellg ();\n\n  switch (fmt.type)\n    {\n    case 'o':\n      is >> std::oct >> value >> std::dec;\n      break;\n\n    case 'x':\n    case 'X':\n      is >> std::hex >> value >> std::dec;\n      break;\n\n    case 'i':\n      {\n        int c1 = is.get ();\n\n        if (c1 != std::istream::traits_type::eof ())\n          {\n            if (c1 == '0')\n              {\n                int c2 = is.peek ();\n\n                if (c2 == 'x' || c2 == 'X')\n                  {\n                    is.ignore ();\n                    if (std::isxdigit (is.peek ()))\n                      is >> std::hex >> value >> std::dec;\n                    else\n                      value = 0;\n                  }\n                else\n                  {\n                    if (c2 == '0' || c2 == '1' || c2 == '2'\n                        || c2 == '3' || c2 == '4' || c2 == '5'\n                        || c2 == '6' || c2 == '7')\n                      is >> std::oct >> value >> std::dec;\n                    else if (c2 == '8' || c2 == '9')\n                      {\n                        // FIXME: Would like to set error state on octave\n                        // stream.  See bug #46493.  But only std::istream is\n                        // input to fcn.\n                        // error (\"internal failure to match octal format\");\n                        value = 0;\n                      }\n                    else\n                      value = 0;\n                  }\n              }\n            else\n              {\n                is.putback (c1);\n\n                is >> value;\n              }\n          }\n      }\n      break;\n\n    default:\n      is >> value;\n      break;\n    }\n\n  std::ios::iostate status = is.rdstate ();\n  if (! (status & std::ios::failbit))\n    {\n      // Copy the converted value if the stream is in a good state\n      *valptr = value;\n    }\n  else\n    {\n      if (value != T ())\n        {\n          // If conversion produces an integer that overflows, failbit is set\n          // but value is nonzero.  We want to treat this case as success,\n          // so clear failbit from the stream state to keep going.\n          // FIXME: Maybe set error state on octave stream?  Matlab does\n          // *not* indicate an error message on overflow.\n          is.clear (status & ~std::ios::failbit);\n          *valptr = value;\n        }\n      else\n        {\n          // True error.\n          // Reset stream to original position, clear eof bit, pass status on.\n          is.clear ();\n          is.seekg (pos);\n          is.setstate (status & ~std::ios_base::eofbit);\n        }\n    }\n\n  return is;\n}\n\ntemplate <typename T>\nstatic std::istream&\noctave_scan (std::istream& is, const scanf_format_elt& fmt, T *valptr)\n{\n  if (fmt.width)\n    {\n      // Limit input to fmt.width characters by reading into a\n      // temporary stringstream buffer.\n      std::string strbuf;\n\n      auto orig_pos = is.tellg ();\n\n      is.width (fmt.width);\n      is >> strbuf;\n\n      std::istringstream ss (strbuf);\n\n      octave_scan_1 (ss, fmt, valptr);\n\n      if (! ss.eof ())\n        {\n          // If fewer characters than width were used to read a number then\n          // the original istream object positioning is incorrect.\n          // Rather than attempt to update istream state and positioning,\n          // just redo the '>>' operation with the correct width so that\n          // all flags get set correctly.\n\n          is.clear ();  // Clear EOF, FAILBIT, BADBIT\n          is.seekg (orig_pos, is.beg);\n\n          int chars_read = ss.tellg ();\n          if (chars_read > 0)\n            {\n              is.width (chars_read);\n              is >> strbuf;\n            }\n        }\n\n      // If pattern failed to match then propagate fail bit to 'is' stream.\n      if (ss.fail ())\n        is.setstate (std::ios::failbit);\n\n    }\n  else\n    octave_scan_1 (is, fmt, valptr);\n\n  return is;\n}\n\ntemplate <>\nstd::istream&\noctave_scan<> (std::istream& is, const scanf_format_elt& fmt, double *valptr)\n{\n  switch (fmt.type)\n    {\n    case 'e':\n    case 'f':\n    case 'g':\n    case 'E':\n    case 'G':\n      {\n        is >> std::ws;  // skip through whitespace and advance stream pointer\n\n        std::streampos pos = is.tellg ();\n\n        double value = read_value<double> (is);\n\n        std::ios::iostate status = is.rdstate ();\n        if (! (status & std::ios::failbit))\n          {\n            // Copy the converted value if the stream is in a good state\n            *valptr = value;\n          }\n        else\n          {\n            // True error.\n            // Reset stream to original position, clear eof bit, pass status on.\n            is.clear ();\n            is.seekg (pos);\n            is.setstate (status & ~std::ios_base::eofbit);\n          }\n      }\n      break;\n\n    default:\n      error (\"expecting format type to be one of 'e', 'f', 'g', 'E', or 'G' but found '%c' - please report this bug\", fmt.type);\n      break;\n    }\n\n  return is;\n}\n\ntemplate <typename T>\nstatic void\ndo_scanf_conv (std::istream& is, const scanf_format_elt& fmt,\n               T valptr, Matrix& mval, double *data, octave_idx_type& idx,\n               octave_idx_type& conversion_count, octave_idx_type nr,\n               octave_idx_type max_size, bool discard)\n{\n  octave_scan (is, fmt, valptr);\n\n  if (! is)\n    return;\n\n  if (idx == max_size && ! discard)\n    {\n      max_size *= 2;\n\n      if (nr > 0)\n        mval.resize (nr, max_size / nr, 0.0);\n      else\n        mval.resize (max_size, 1, 0.0);\n\n      data = mval.rwdata ();\n    }\n\n  if (! discard)\n    {\n      conversion_count++;\n      data[idx++] = *(valptr);\n    }\n}\n\ntemplate void\ndo_scanf_conv (std::istream&, const scanf_format_elt&, double *,\n               Matrix&, double *, octave_idx_type&, octave_idx_type&,\n               octave_idx_type, octave_idx_type, bool);\n\n#define DO_WHITESPACE_CONVERSION()                                      \\\n  do                                                                    \\\n    {                                                                   \\\n      int c = std::istream::traits_type::eof ();                        \\\n                                                                        \\\n      /* get all whitespace characters */                               \\\n      while (is && (c = is.get ()) != std::istream::traits_type::eof () \\\n             && isspace (c))                                            \\\n        { /* skip whitespace */ }                                       \\\n                                                                        \\\n      if (c == std::istream::traits_type::eof ())                       \\\n        /* reset failbit at eof */                                      \\\n        is.clear (is.rdstate () & (~std::ios::failbit));                \\\n      else                                                              \\\n        /* put back non-whitespace character */                         \\\n        is.putback (c);                                                 \\\n    }                                                                   \\\n  while (0)\n\n#define DO_LITERAL_CONVERSION()                                         \\\n  do                                                                    \\\n    {                                                                   \\\n      int c = std::istream::traits_type::eof ();                        \\\n                                                                        \\\n      int n = fmt.length ();                                            \\\n      int i = 0;                                                        \\\n                                                                        \\\n      while (i < n && is                                                \\\n             && (c = is.get ()) != std::istream::traits_type::eof ())   \\\n        {                                                               \\\n          if (c == static_cast<unsigned char> (fmt[i]))                 \\\n            {                                                           \\\n              i++;                                                      \\\n              continue;                                                 \\\n            }                                                           \\\n          else                                                          \\\n            {                                                           \\\n              is.putback (c);                                           \\\n              break;                                                    \\\n            }                                                           \\\n        }                                                               \\\n                                                                        \\\n      if (i != n)                                                       \\\n        is.setstate (std::ios::failbit);                                \\\n    }                                                                   \\\n  while (0)\n\n#define DO_PCT_CONVERSION()                             \\\n  do                                                    \\\n    {                                                   \\\n      int c = is.get ();                                \\\n                                                        \\\n      if (c != std::istream::traits_type::eof ())       \\\n        {                                               \\\n          if (c != '%')                                 \\\n            {                                           \\\n              is.putback (c);                           \\\n              is.setstate (std::ios::failbit);          \\\n            }                                           \\\n        }                                               \\\n      else                                              \\\n        is.setstate (std::ios::failbit);                \\\n    }                                                   \\\n  while (0)\n\n#define BEGIN_C_CONVERSION()                                            \\\n  is.unsetf (std::ios::skipws);                                         \\\n                                                                        \\\n  int width = (elt->width ? elt->width : 1);                            \\\n                                                                        \\\n  std::string tmp (width, '\\0');                                        \\\n                                                                        \\\n  int c = std::istream::traits_type::eof ();                            \\\n  int n = 0;                                                            \\\n                                                                        \\\n  while (is && n < width                                                \\\n         && (c = is.get ()) != std::istream::traits_type::eof ())       \\\n    tmp[n++] = static_cast<char> (c);                                   \\\n                                                                        \\\n  if (c == std::istream::traits_type::eof ())                           \\\n    is.clear (is.rdstate () & (~std::ios::failbit));                    \\\n                                                                        \\\n  tmp.resize (n)\n\n// For a '%s' format, skip initial whitespace and then read until the\n// next whitespace character or until WIDTH characters have been read.\n#define BEGIN_S_CONVERSION()                                            \\\n  int width = elt->width;                                               \\\n                                                                        \\\n  std::string tmp;                                                      \\\n                                                                        \\\n  do                                                                    \\\n    {                                                                   \\\n      if (width)                                                        \\\n        {                                                               \\\n          tmp = std::string (width, '\\0');                              \\\n                                                                        \\\n          int c = std::istream::traits_type::eof ();                    \\\n                                                                        \\\n          int n = 0;                                                    \\\n                                                                        \\\n          while (is && (c = is.get ()) != std::istream::traits_type::eof ()) \\\n            {                                                           \\\n              if (! isspace (c))                                        \\\n                {                                                       \\\n                  tmp[n++] = static_cast<char> (c);                     \\\n                  break;                                                \\\n                }                                                       \\\n            }                                                           \\\n                                                                        \\\n          while (is && n < width                                        \\\n                 && (c = is.get ()) != std::istream::traits_type::eof ()) \\\n            {                                                           \\\n              if (isspace (c))                                          \\\n                {                                                       \\\n                  is.putback (c);                                       \\\n                  break;                                                \\\n                }                                                       \\\n              else                                                      \\\n                tmp[n++] = static_cast<char> (c);                       \\\n            }                                                           \\\n                                                                        \\\n          if (c == std::istream::traits_type::eof ())                   \\\n            is.clear (is.rdstate () & (~std::ios::failbit));            \\\n                                                                        \\\n          tmp.resize (n);                                               \\\n        }                                                               \\\n      else                                                              \\\n        {                                                               \\\n          is >> std::ws >> tmp;                                         \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\n// This format must match a nonempty sequence of characters.\n#define BEGIN_CHAR_CLASS_CONVERSION()                                   \\\n  int width = (elt->width ? elt->width                                  \\\n                          : std::numeric_limits<int>::max ());          \\\n                                                                        \\\n  std::string tmp;                                                      \\\n                                                                        \\\n  do                                                                    \\\n    {                                                                   \\\n      std::ostringstream buf;                                           \\\n                                                                        \\\n      std::string char_class = elt->char_class;                         \\\n                                                                        \\\n      int c = std::istream::traits_type::eof ();                        \\\n                                                                        \\\n      if (elt->type == '[')                                             \\\n        {                                                               \\\n          int chars_read = 0;                                           \\\n          while (is && chars_read++ < width                             \\\n                 && (c = is.get ()) != std::istream::traits_type::eof ()) \\\n            {                                                           \\\n              if (char_class.find (c) != std::string::npos)             \\\n                buf << static_cast<char> (c);                           \\\n              else                                                      \\\n                {                                                       \\\n                  is.putback (c);                                       \\\n                  break;                                                \\\n                }                                                       \\\n            }                                                           \\\n        }                                                               \\\n      else                                                              \\\n        {                                                               \\\n          int chars_read = 0;                                           \\\n          while (is && chars_read++ < width                             \\\n                 && (c = is.get ()) != std::istream::traits_type::eof ()) \\\n            {                                                           \\\n              if (char_class.find (c) == std::string::npos)             \\\n                buf << static_cast<char> (c);                           \\\n              else                                                      \\\n                {                                                       \\\n                  is.putback (c);                                       \\\n                  break;                                                \\\n                }                                                       \\\n            }                                                           \\\n        }                                                               \\\n                                                                        \\\n      tmp = buf.str ();                                                 \\\n                                                                        \\\n      if (tmp.empty ())                                                 \\\n        is.setstate (std::ios::failbit);                                \\\n      else if (c == std::istream::traits_type::eof ())                  \\\n        is.clear (is.rdstate () & (~std::ios::failbit));                \\\n                                                                        \\\n    }                                                                   \\\n  while (0)\n\n#define FINISH_CHARACTER_CONVERSION()                                   \\\n  do                                                                    \\\n    {                                                                   \\\n      if (encoding ().compare (\"utf-8\"))                                \\\n        tmp = string::u8_from_encoding (who, tmp, encoding ());         \\\n      width = tmp.length ();                                            \\\n                                                                        \\\n      if (is && width > 0)                                              \\\n        {                                                               \\\n          int i = 0;                                                    \\\n                                                                        \\\n          if (! discard)                                                \\\n            {                                                           \\\n              conversion_count++;                                       \\\n                                                                        \\\n              while (i < width)                                         \\\n                {                                                       \\\n                  if (data_index == max_size)                           \\\n                    {                                                   \\\n                      max_size *= 2;                                    \\\n                                                                        \\\n                      if (all_char_conv)                                \\\n                        {                                               \\\n                          if (one_elt_size_spec)                        \\\n                            mval.resize (1, max_size, 0.0);             \\\n                          else if (nr > 0)                              \\\n                            mval.resize (nr, max_size / nr, 0.0);       \\\n                          else                                          \\\n                            error (\"unexpected size in character conversion - please report this bug\"); \\\n                        }                                               \\\n                      else if (nr > 0)                                  \\\n                        mval.resize (nr, max_size / nr, 0.0);           \\\n                      else                                              \\\n                        mval.resize (max_size, 1, 0.0);                 \\\n                                                                        \\\n                      data = mval.rwdata ();                       \\\n                    }                                                   \\\n                                                                        \\\n                  data[data_index++] = static_cast<unsigned char>       \\\n                                                  (tmp[i++]);           \\\n                }                                                       \\\n            }                                                           \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\noctave_value\nbase_stream::do_scanf (scanf_format_list& fmt_list,\n                       octave_idx_type nr, octave_idx_type nc,\n                       bool one_elt_size_spec,\n                       octave_idx_type& conversion_count,\n                       const std::string& who)\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  if (interp.interactive () && file_number () == 0)\n    ::error (\"%s: unable to read from stdin while running interactively\",\n             who.c_str ());\n\n  octave_value retval = Matrix ();\n\n  conversion_count = 0;\n\n  octave_idx_type m_nconv = fmt_list.num_conversions ();\n\n  octave_idx_type data_index = 0;\n\n  if (nr == 0 || nc == 0)\n    {\n      if (one_elt_size_spec)\n        nc = 0;\n\n      return Matrix (nr, nc, 0.0);\n    }\n\n  std::istream *isp = input_stream ();\n\n  bool all_char_conv = fmt_list.all_character_conversions ();\n\n  Matrix mval;\n  octave_idx_type max_size = 0;\n  octave_idx_type max_conv = 0;\n\n  octave_idx_type final_nr = 0;\n  octave_idx_type final_nc = 0;\n\n  if (all_char_conv)\n    {\n      // Any of these could be resized later (if we have %s conversions,\n      // we may read more than one element for each conversion).\n      if (one_elt_size_spec)\n        {\n          max_size = 512;\n          mval.resize (1, max_size, 0.0);\n\n          if (nr > 0)\n            max_conv = nr;\n        }\n      else if (nr > 0)\n        {\n          if (nc > 0)\n            {\n              mval.resize (nr, nc, 0.0);\n              max_size = max_conv = nr * nc;\n            }\n          else\n            {\n              mval.resize (nr, 32, 0.0);\n              max_size = nr * 32;\n            }\n        }\n      else\n        error (\"unexpected size in character conversion - please report this bug\");\n    }\n  else if (nr > 0)\n    {\n      if (nc > 0)\n        {\n          // Will not resize later.\n          mval.resize (nr, nc, 0.0);\n          max_size = nr * nc;\n          max_conv = max_size;\n        }\n      else\n        {\n          // Maybe resize later.\n          mval.resize (nr, 32, 0.0);\n          max_size = nr * 32;\n        }\n    }\n  else\n    {\n      // Maybe resize later.\n      mval.resize (32, 1, 0.0);\n      max_size = 32;\n    }\n\n  double *data = mval.rwdata ();\n\n  if (isp)\n    {\n      std::istream& is = *isp;\n\n      const scanf_format_elt *elt = fmt_list.first ();\n\n      std::ios::fmtflags flags = is.flags ();\n\n      octave_idx_type trips = 0;\n\n      octave_idx_type num_fmt_elts = fmt_list.length ();\n\n      for (;;)\n        {\n          octave_quit ();\n\n          if (elt)\n            {\n              if (elt->type == scanf_format_elt::null\n                  || (! (elt->type == scanf_format_elt::whitespace_conversion\n                         || elt->type == scanf_format_elt::literal_conversion\n                         || elt->type == '%')\n                      && max_conv > 0 && conversion_count == max_conv))\n                {\n                  // We are done, either because we have reached the end of\n                  // the format string and are not cycling through the format\n                  // again or because we've converted all the values that\n                  // have been requested and the next format element is a\n                  // conversion.  Determine final array size and exit.\n                  if (all_char_conv && one_elt_size_spec)\n                    {\n                      final_nr = 1;\n                      final_nc = data_index;\n                    }\n                  else\n                    {\n                      final_nr = nr;\n                      final_nc = (data_index - 1) / nr + 1;\n                    }\n\n                  break;\n                }\n              else if (data_index == max_size)\n                {\n                  max_size *= 2;\n\n                  if (all_char_conv)\n                    {\n                      if (one_elt_size_spec)\n                        mval.resize (1, max_size, 0.0);\n                      else if (nr > 0)\n                        mval.resize (nr, max_size / nr, 0.0);\n                      else\n                        error (\"unexpected size in character conversion - please report this bug\");\n                    }\n                  else if (nr > 0)\n                    mval.resize (nr, max_size / nr, 0.0);\n                  else\n                    mval.resize (max_size, 1, 0.0);\n\n                  data = mval.rwdata ();\n                }\n\n              std::string fmt = elt->text;\n\n              bool discard = elt->discard;\n\n              switch (elt->type)\n                {\n                case scanf_format_elt::whitespace_conversion:\n                  DO_WHITESPACE_CONVERSION ();\n                  break;\n\n                case scanf_format_elt::literal_conversion:\n                  DO_LITERAL_CONVERSION ();\n                  break;\n\n                case '%':\n                  DO_PCT_CONVERSION ();\n                  break;\n\n                case 'd': case 'i':\n                  {\n                    switch (elt->modifier)\n                      {\n                      case 'h':\n                        {\n                          int16_t tmp;\n                          do_scanf_conv (is, *elt, &tmp, mval, data,\n                                         data_index, conversion_count,\n                                         nr, max_size, discard);\n                        }\n                        break;\n\n                      case 'l':\n                        {\n                          int64_t tmp;\n                          do_scanf_conv (is, *elt, &tmp, mval, data,\n                                         data_index, conversion_count,\n                                         nr, max_size, discard);\n                        }\n                        break;\n\n                      default:\n                        {\n                          int32_t tmp;\n                          do_scanf_conv (is, *elt, &tmp, mval, data,\n                                         data_index, conversion_count,\n                                         nr, max_size, discard);\n                        }\n                        break;\n                      }\n                  }\n                  break;\n\n                case 'o': case 'u': case 'x': case 'X':\n                  {\n                    switch (elt->modifier)\n                      {\n                      case 'h':\n                        {\n                          uint16_t tmp;\n                          do_scanf_conv (is, *elt, &tmp, mval, data,\n                                         data_index, conversion_count,\n                                         nr, max_size, discard);\n                        }\n                        break;\n\n                      case 'l':\n                        {\n                          uint64_t tmp;\n                          do_scanf_conv (is, *elt, &tmp, mval, data,\n                                         data_index, conversion_count,\n                                         nr, max_size, discard);\n                        }\n                        break;\n\n                      default:\n                        {\n                          uint32_t tmp;\n                          do_scanf_conv (is, *elt, &tmp, mval, data,\n                                         data_index, conversion_count,\n                                         nr, max_size, discard);\n                        }\n                        break;\n                      }\n                  }\n                  break;\n\n                case 'e': case 'f': case 'g':\n                case 'E': case 'G':\n                  {\n                    double tmp;\n\n                    do_scanf_conv (is, *elt, &tmp, mval, data,\n                                   data_index, conversion_count,\n                                   nr, max_size, discard);\n                  }\n                  break;\n\n                case 'c':\n                  {\n                    BEGIN_C_CONVERSION ();\n\n                    FINISH_CHARACTER_CONVERSION ();\n\n                    is.setf (flags);\n                  }\n                  break;\n\n                case 's':\n                  {\n                    BEGIN_S_CONVERSION ();\n\n                    FINISH_CHARACTER_CONVERSION ();\n                  }\n                  break;\n\n                case '[': case '^':\n                  {\n                    BEGIN_CHAR_CLASS_CONVERSION ();\n\n                    FINISH_CHARACTER_CONVERSION ();\n                  }\n                  break;\n\n                case 'p':\n                  error (who, \"unsupported format specifier\");\n                  break;\n\n                default:\n                  error (who, \"internal format error\");\n                  break;\n                }\n\n              if (! ok ())\n                {\n                  break;\n                }\n              else if (is.eof () || ! is)\n                {\n                  if (all_char_conv)\n                    {\n                      if (one_elt_size_spec)\n                        {\n                          final_nr = 1;\n                          final_nc = data_index;\n                        }\n                      else if (data_index > nr)\n                        {\n                          final_nr = nr;\n                          final_nc = (data_index - 1) / nr + 1;\n                        }\n                      else\n                        {\n                          final_nr = data_index;\n                          final_nc = 1;\n                        }\n                    }\n                  else if (nr > 0)\n                    {\n                      if (data_index > nr)\n                        {\n                          final_nr = nr;\n                          final_nc = (data_index - 1) / nr + 1;\n                        }\n                      else\n                        {\n                          final_nr = data_index;\n                          final_nc = 1;\n                        }\n                    }\n                  else\n                    {\n                      final_nr = data_index;\n                      final_nc = 1;\n                    }\n\n                  // If it looks like we have a matching failure, then\n                  // reset the failbit in the stream state.\n                  if (is.rdstate () & std::ios::failbit)\n                    {\n                      is.clear (is.rdstate () & (~std::ios::failbit));\n                      error (who, \"format failed to match\");\n                    }\n\n                  // FIXME: is this the right thing to do?\n                  if (interp.interactive ()\n                      && ! application::forced_interactive ()\n                      && name () == \"stdin\")\n                    {\n                      is.clear ();\n\n                      // Skip to end of line.\n                      bool err;\n                      do_gets (-1, err, false, who);\n                    }\n\n                  break;\n                }\n            }\n          else\n            {\n              error (who, \"internal format error\");\n              break;\n            }\n\n          if (m_nconv == 0 && ++trips == num_fmt_elts)\n            {\n              if (all_char_conv && one_elt_size_spec)\n                {\n                  final_nr = 1;\n                  final_nc = data_index;\n                }\n              else\n                {\n                  final_nr = nr;\n                  final_nc = (data_index - 1) / nr + 1;\n                }\n\n              break;\n            }\n          else\n            {\n              // Cycle through the format list more than once if we have some\n              // conversions to make and we haven't reached the limit on the\n              // number of values to convert (possibly because there is no\n              // specified limit).\n              elt = fmt_list.next (m_nconv > 0\n                                   && (max_conv == 0\n                                       || conversion_count < max_conv));\n            }\n        }\n    }\n\n  mval.resize (final_nr, final_nc, 0.0);\n\n  retval = mval;\n\n  if (all_char_conv)\n    retval = retval.convert_to_str (false, true);\n\n  return retval;\n}\n\noctave_value\nbase_stream::scanf (const std::string& fmt, const Array<double>& size,\n                    octave_idx_type& conversion_count,\n                    const std::string& who)\n{\n  octave_value retval = Matrix ();\n\n  conversion_count = 0;\n\n  std::istream *isp = input_stream ();\n\n  if (! isp)\n    invalid_operation (who, \"reading\");\n  else\n    {\n      scanf_format_list fmt_list (fmt);\n\n      if (fmt_list.num_conversions () == -1)\n        ::error (\"%s: invalid format specified\", who.c_str ());\n\n      octave_idx_type nr = -1;\n      octave_idx_type nc = -1;\n\n      bool one_elt_size_spec;\n\n      get_size (size, nr, nc, one_elt_size_spec, who);\n\n      retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec,\n                         conversion_count, who);\n    }\n\n  return retval;\n}\n\nbool\nbase_stream::do_oscanf (const scanf_format_elt *elt,\n                        octave_value& retval, const std::string& who)\n{\n  std::istream *isp = input_stream ();\n\n  if (! isp)\n    return false;\n\n  bool quit = false;\n\n  std::istream& is = *isp;\n\n  std::ios::fmtflags flags = is.flags ();\n\n  if (elt)\n    {\n      std::string fmt = elt->text;\n\n      bool discard = elt->discard;\n\n      switch (elt->type)\n        {\n        case scanf_format_elt::whitespace_conversion:\n          DO_WHITESPACE_CONVERSION ();\n          break;\n\n        case scanf_format_elt::literal_conversion:\n          DO_LITERAL_CONVERSION ();\n          break;\n\n        case '%':\n          {\n            DO_PCT_CONVERSION ();\n\n            if (! is)\n              quit = true;\n          }\n          break;\n\n        case 'd': case 'i':\n          {\n            switch (elt->modifier)\n              {\n              case 'h':\n                {\n                  int16_t tmp;\n                  if (octave_scan (is, *elt, &tmp))\n                    {\n                      if (! discard)\n                        retval = tmp;\n                    }\n                  else\n                    quit = true;\n                }\n                break;\n\n              case 'l':\n                {\n                  int64_t tmp;\n                  if (octave_scan (is, *elt, &tmp))\n                    {\n                      if (! discard)\n                        retval = tmp;\n                    }\n                  else\n                    quit = true;\n                }\n                break;\n\n              default:\n                {\n                  int32_t tmp;\n                  if (octave_scan (is, *elt, &tmp))\n                    {\n                      if (! discard)\n                        retval = tmp;\n                    }\n                  else\n                    quit = true;\n                }\n                break;\n              }\n          }\n          break;\n\n        case 'o': case 'u': case 'x': case 'X':\n          {\n            switch (elt->modifier)\n              {\n              case 'h':\n                {\n                  uint16_t tmp;\n                  if (octave_scan (is, *elt, &tmp))\n                    {\n                      if (! discard)\n                        retval = tmp;\n                    }\n                  else\n                    quit = true;\n                }\n                break;\n\n              case 'l':\n                {\n                  uint64_t tmp;\n                  if (octave_scan (is, *elt, &tmp))\n                    {\n                      if (! discard)\n                        retval = tmp;\n                    }\n                  else\n                    quit = true;\n                }\n                break;\n\n              default:\n                {\n                  uint32_t tmp;\n                  if (octave_scan (is, *elt, &tmp))\n                    {\n                      if (! discard)\n                        retval = tmp;\n                    }\n                  else\n                    quit = true;\n                }\n                break;\n              }\n          }\n          break;\n\n        case 'e': case 'f': case 'g':\n        case 'E': case 'G':\n          {\n            double tmp;\n\n            if (octave_scan (is, *elt, &tmp))\n              {\n                if (! discard)\n                  retval = tmp;\n              }\n            else\n              quit = true;\n          }\n          break;\n\n        case 'c':\n          {\n            BEGIN_C_CONVERSION ();\n\n            if (! discard)\n              retval = tmp;\n\n            if (! is)\n              quit = true;\n\n            is.setf (flags);\n          }\n          break;\n\n        case 's':\n          {\n            BEGIN_S_CONVERSION ();\n\n            if (! discard)\n              retval = tmp;\n\n            if (! is)\n              quit = true;\n          }\n          break;\n\n        case '[':\n        case '^':\n          {\n            BEGIN_CHAR_CLASS_CONVERSION ();\n\n            if (! discard)\n              retval = tmp;\n\n            if (! is)\n              quit = true;\n          }\n          break;\n\n        case 'p':\n          error (who, \"unsupported format specifier\");\n          break;\n\n        default:\n          error (who, \"internal format error\");\n          break;\n        }\n    }\n\n  if (ok () && is.fail ())\n    {\n      error (\"%s: read error\", who.c_str ());\n\n      // FIXME: is this the right thing to do?\n\n      interpreter& interp = __get_interpreter__ ();\n\n      if (interp.interactive () && ! application::forced_interactive ()\n          && name () == \"stdin\")\n        {\n          // Skip to end of line.\n          bool err;\n          do_gets (-1, err, false, who);\n        }\n    }\n\n  return quit;\n}\n\noctave_value_list\nbase_stream::oscanf (const std::string& fmt, const std::string& who)\n{\n  octave_value_list retval;\n\n  std::istream *isp = input_stream ();\n\n  if (! isp)\n    invalid_operation (who, \"reading\");\n  else\n    {\n      std::istream& is = *isp;\n\n      scanf_format_list fmt_list (fmt);\n\n      octave_idx_type m_nconv = fmt_list.num_conversions ();\n\n      if (m_nconv == -1)\n        ::error (\"%s: invalid format specified\", who.c_str ());\n\n      is.clear ();\n\n      octave_idx_type len = fmt_list.length ();\n\n      retval.resize (m_nconv+2, Matrix ());\n\n      const scanf_format_elt *elt = fmt_list.first ();\n\n      int num_values = 0;\n\n      bool quit = false;\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          octave_value tmp;\n\n          quit = do_oscanf (elt, tmp, who);\n\n          if (quit)\n            break;\n          else\n            {\n              if (tmp.is_defined ())\n                retval(num_values++) = tmp;\n\n              if (! ok ())\n                break;\n\n              elt = fmt_list.next (m_nconv > 0);\n            }\n        }\n\n      retval(m_nconv) = num_values;\n\n      int err_num;\n      retval(m_nconv+1) = error (false, err_num);\n\n      if (! quit)\n        {\n          // Pick up any trailing stuff.\n          if (ok () && len > m_nconv)\n            {\n              octave_value tmp;\n\n              elt = fmt_list.next ();\n\n              do_oscanf (elt, tmp, who);\n            }\n        }\n    }\n\n  return retval;\n}\n\noctave_value\nbase_stream::do_textscan (const std::string& fmt,\n                          octave_idx_type ntimes,\n                          const octave_value_list& options,\n                          const std::string& who,\n                          octave_idx_type& read_count)\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  if (interp.interactive () && file_number () == 0)\n    ::error (\"%s: unable to read from stdin while running interactively\",\n             who.c_str ());\n\n  octave_value retval = Cell (dim_vector (1, 1), Matrix (0, 1));\n\n  std::istream *isp = input_stream ();\n\n  if (! isp)\n    invalid_operation (who, \"reading\");\n  else\n    {\n      textscan scanner (who, encoding ());\n\n      retval = scanner.scan (*isp, fmt, ntimes, options, read_count);\n    }\n\n  return retval;\n}\n\n// Functions that are defined for all output streams\n// (output streams are those that define os).\n\nint\nbase_stream::flush ()\n{\n  int retval = -1;\n\n  std::ostream *os = preferred_output_stream ();\n\n  if (! os)\n    invalid_operation (\"fflush\", \"writing\");\n  else\n    {\n      os->flush ();\n\n      if (os->good ())\n        retval = 0;\n    }\n\n  return retval;\n}\n\nclass printf_value_cache\n{\npublic:\n\n  enum state { ok, conversion_error };\n\n  printf_value_cache (const octave_value_list& args, const std::string& who)\n    : m_values (args), m_val_idx (0), m_elt_idx (0),\n      m_n_vals (m_values.length ()), m_n_elts (0), m_have_data (false),\n      m_curr_state (ok)\n  {\n    for (octave_idx_type i = 0; i < m_values.length (); i++)\n      {\n        octave_value val = m_values(i);\n\n        if (val.isstruct () || val.iscell () || val.isobject ())\n          err_wrong_type_arg (who, val);\n      }\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (printf_value_cache)\n\n  ~printf_value_cache () = default;\n\n  // Get the current value as a double and advance the internal pointer.\n  octave_value get_next_value (char type = 0);\n\n  // Get the current value as an int and advance the internal\n  // pointer.  Value before conversion to int must be >= 0 and less\n  // than std::numeric_limits<int>::max ().\n\n  int int_value ();\n\n  operator bool () const { return (m_curr_state == ok); }\n\n  bool exhausted () { return (m_val_idx >= m_n_vals); }\n\nprivate:\n\n  // Must create value cache with values!\n  printf_value_cache ();\n\n  //--------\n\n  const octave_value_list m_values;\n  octave_idx_type m_val_idx;\n  octave_idx_type m_elt_idx;\n  octave_idx_type m_n_vals;\n  octave_idx_type m_n_elts;\n  bool m_have_data;\n  octave_value m_curr_val;\n  state m_curr_state;\n};\n\noctave_value\nprintf_value_cache::get_next_value (char type)\n{\n  octave_value retval;\n\n  if (exhausted ())\n    m_curr_state = conversion_error;\n\n  while (! exhausted ())\n    {\n      if (! m_have_data)\n        {\n          m_curr_val = m_values (m_val_idx);\n\n          m_elt_idx = 0;\n          m_n_elts = m_curr_val.numel ();\n          m_have_data = true;\n        }\n\n      if (m_elt_idx < m_n_elts)\n        {\n          if (type == 's')\n            {\n              if (m_curr_val.is_string ())\n                {\n                  dim_vector dv (1, m_curr_val.numel ());\n                  octave_value tmp = m_curr_val.reshape (dv);\n\n                  std::string sval = tmp.string_value ();\n\n                  retval = sval.substr (m_elt_idx);\n\n                  // We've consumed the rest of the value.\n                  m_elt_idx = m_n_elts;\n                }\n              else\n                {\n                  // Convert to character string while values are\n                  // integers in the range [0 : char max]\n                  const NDArray val = m_curr_val.array_value ();\n\n                  octave_idx_type idx = m_elt_idx;\n\n                  for (; idx < m_n_elts; idx++)\n                    {\n                      double dval = val(idx);\n\n                      if (! math::is_integer (dval)\n                          || dval < 0 || dval > 255)\n                        break;\n                    }\n\n                  octave_idx_type n = idx - m_elt_idx;\n\n                  if (n > 0)\n                    {\n                      std::string sval (n, '\\0');\n\n                      for (octave_idx_type i = 0; i < n; i++)\n                        sval[i] = val(m_elt_idx++);\n\n                      retval = sval;\n                    }\n                  else\n                    retval = m_curr_val.fast_elem_extract (m_elt_idx++);\n                }\n            }\n          else\n            {\n              retval = m_curr_val.fast_elem_extract (m_elt_idx++);\n\n              if (type == 'c' && ! retval.is_string ())\n                {\n                  double dval = retval.double_value ();\n\n                  if (math::is_integer (dval) && dval >= 0 && dval < 256)\n                    retval = static_cast<char> (dval);\n                }\n            }\n\n          if (m_elt_idx >= m_n_elts)\n            {\n              m_elt_idx = 0;\n              m_val_idx++;\n              m_have_data = false;\n            }\n\n          break;\n        }\n      else\n        {\n          m_val_idx++;\n          m_have_data = false;\n\n          if (m_n_elts == 0)\n            {\n              if (m_elt_idx == 0)\n                {\n                  if (type == 's' || type == 'c')\n                    retval = \"\";\n                  else\n                    retval = Matrix ();\n\n                  break;\n                }\n\n              if (exhausted ())\n                m_curr_state = conversion_error;\n            }\n        }\n    }\n\n  return retval;\n}\n\nint\nprintf_value_cache::int_value ()\n{\n  octave_value val = get_next_value ();\n\n  double dval = val.double_value (true);\n\n  if (dval < 0 || dval > std::numeric_limits<int>::max ()\n      || ! math::is_integer (dval))\n    {\n      m_curr_state = conversion_error;\n      return -1;\n    }\n\n  return math::nint (dval);\n}\n\n// Ugh again and again.\n\ntemplate <typename T>\nstatic int\ndo_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1,\n                int sa_2, T arg, const std::string& who)\n{\n  int retval = 0;\n\n  switch (nsa)\n    {\n    case 2:\n      retval = format (os, fmt, sa_1, sa_2, arg);\n      break;\n\n    case 1:\n      retval = format (os, fmt, sa_1, arg);\n      break;\n\n    case 0:\n      retval = format (os, fmt, arg);\n      break;\n\n    default:\n      ::error (\"%s: internal error handling format\", who.c_str ());\n      break;\n    }\n\n  return retval;\n}\n\nstatic std::size_t\ndo_printf_string (std::ostream& os, const printf_format_elt *elt,\n                  int nsa, int sa_1, int sa_2, const std::string& arg,\n                  const std::string& who)\n{\n  if (nsa > 2)\n    ::error (\"%s: internal error handling format\", who.c_str ());\n\n  std::string flags = elt->flags;\n\n  bool left = flags.find ('-') != std::string::npos;\n\n  std::size_t len = arg.length ();\n\n  std::size_t prec = (nsa > 1 ? sa_2 : (elt->prec == -1 ? len : elt->prec));\n\n  std::string print_str = prec < arg.length () ? arg.substr (0, prec) : arg;\n\n  std::size_t fw = (nsa > 0 ? sa_1 : (elt->fw == -1 ? len : elt->fw));\n\n  os << std::setw (fw) << (left ? std::left : std::right) << print_str;\n\n  return len > fw ? len : fw;\n}\n\nstatic bool\nis_nan_or_inf (const octave_value& val)\n{\n  octave_value ov_isnan = val.isnan ();\n  octave_value ov_isinf = val.isinf ();\n\n  return (ov_isnan.is_true () || ov_isinf.is_true ());\n}\n\nstatic bool\nok_for_signed_int_conv (const octave_value& val)\n{\n  uint64_t limit = std::numeric_limits<int64_t>::max ();\n\n  if (val.is_string ())\n    return true;\n  else if (val.isinteger ())\n    {\n      if (val.is_uint64_type ())\n        {\n          octave_uint64 ival = val.uint64_scalar_value ();\n\n          if (ival.value () <= limit)\n            return true;\n        }\n      else\n        return true;\n    }\n  else\n    {\n      double dval = val.double_value (true);\n\n      if (dval == math::fix (dval) && dval <= limit)\n        return true;\n    }\n\n  return false;\n}\n\nstatic bool\nok_for_unsigned_int_conv (const octave_value& val)\n{\n  if (val.is_string ())\n    return true;\n  else if (val.isinteger ())\n    {\n      // Easier than dispatching here...\n\n      octave_value ov_is_ge_zero\n        = binary_op (octave_value::op_ge, val, octave_value (0.0));\n\n      return ov_is_ge_zero.is_true ();\n    }\n  else\n    {\n      double dval = val.double_value (true);\n\n      uint64_t limit = std::numeric_limits<uint64_t>::max ();\n\n      if (dval == math::fix (dval) && dval >= 0 && dval <= limit)\n        return true;\n    }\n\n  return false;\n}\n\nstatic std::string\nswitch_to_g_format (const printf_format_elt *elt)\n{\n  std::string tfmt = elt->text;\n\n  tfmt.replace (tfmt.rfind (elt->type), 1, \"g\");\n\n  return tfmt;\n}\n\nint\nbase_stream::do_numeric_printf_conv (std::ostream& os,\n                                     const printf_format_elt *elt,\n                                     int nsa, int sa_1, int sa_2,\n                                     const octave_value& val,\n                                     const std::string& who)\n{\n  int retval = 0;\n\n  std::string tfmt = elt->text;\n\n  if (is_nan_or_inf (val))\n    {\n      double dval = val.double_value ();\n\n      std::string::size_type i1, i2;\n\n      tfmt.replace ((i1 = tfmt.rfind (elt->type)), 1, 1, 's');\n\n      if ((i2 = tfmt.rfind ('.')) != std::string::npos && i2 < i1)\n        {\n          tfmt.erase (i2, i1-i2);\n          if (elt->prec == -2)\n            nsa--;\n        }\n\n      const char *tval;\n      if (math::isinf (dval))\n        {\n          if (elt->flags.find ('+') != std::string::npos)\n            tval = (dval < 0 ? \"-Inf\" : \"+Inf\");\n          else\n            tval = (dval < 0 ? \"-Inf\" : \"Inf\");\n        }\n      else\n        {\n          if (elt->flags.find ('+') != std::string::npos)\n            tval = (lo_ieee_is_NA (dval) ? \"+NA\" : \"+NaN\");\n          else\n            tval = (lo_ieee_is_NA (dval) ? \"NA\" : \"NaN\");\n        }\n\n      retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval,\n                                who);\n    }\n  else\n    {\n      static std::string llmod\n        = (sizeof (long) == sizeof (int64_t) ? \"l\" : \"ll\");\n\n      char type = elt->type;\n\n      switch (type)\n        {\n        case 'd': case 'i': case 'c':\n          if (ok_for_signed_int_conv (val))\n            {\n              octave_int64 tval = val.int64_scalar_value ();\n\n              // Insert \"long\" modifier.\n              tfmt.replace (tfmt.rfind (type), 1, llmod + type);\n\n              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,\n                                        tval.value (), who);\n            }\n          else\n            {\n              tfmt = switch_to_g_format (elt);\n\n              double dval = val.double_value (true);\n\n              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,\n                                        dval, who);\n            }\n          break;\n\n        case 'o': case 'x': case 'X': case 'u':\n          if (ok_for_unsigned_int_conv (val))\n            {\n              octave_uint64 tval = val.uint64_scalar_value ();\n\n              // Insert \"long\" modifier.\n              tfmt.replace (tfmt.rfind (type), 1, llmod + type);\n\n              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,\n                                        tval.value (), who);\n            }\n          else\n            {\n              tfmt = switch_to_g_format (elt);\n\n              double dval = val.double_value (true);\n\n              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,\n                                        dval, who);\n            }\n          break;\n\n        case 'f': case 'e': case 'E':\n        case 'g': case 'G':\n          {\n            double dval = val.double_value (true);\n\n            retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,\n                                      dval, who);\n          }\n          break;\n\n        default:\n          // Note: error is member fcn from base_stream, not ::error.\n          // This error does not halt execution so \"return ...\" must exist.\n          error (who, \"invalid format specifier\");\n          return -1;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nvoid\nbase_stream::field_width_error (const std::string& who) const\n{\n  ::error (\"%s: invalid field width, must be integer >= 0 and <= INT_MAX\",\n           who.c_str ());\n}\n\nint\nbase_stream::do_printf (printf_format_list& fmt_list,\n                        const octave_value_list& args,\n                        const std::string& who)\n{\n  int retval = 0;\n\n  octave_idx_type m_nconv = fmt_list.num_conversions ();\n\n  std::ostream *osp = preferred_output_stream ();\n\n  if (! osp)\n    invalid_operation (who, \"writing\");\n  else\n    {\n      std::ostream& os = *osp;\n\n      preserve_stream_state stream_state (os);\n\n      const printf_format_elt *elt = fmt_list.first ();\n\n      printf_value_cache val_cache (args, who);\n\n      for (;;)\n        {\n          octave_quit ();\n\n          if (! elt)\n            ::error (\"%s: internal error handling format\", who.c_str ());\n\n          // NSA is the number of 'star' args to convert.\n          int nsa = (elt->fw == -2) + (elt->prec == -2);\n\n          int sa_1 = 0;\n          int sa_2 = 0;\n\n          if (nsa > 0)\n            {\n              sa_1 = val_cache.int_value ();\n\n              if (! val_cache)\n                {\n                  field_width_error (who);\n                  break;\n                }\n              else\n                {\n                  if (nsa > 1)\n                    {\n                      sa_2 = val_cache.int_value ();\n\n                      if (! val_cache)\n                        {\n                          field_width_error (who);\n                          break;\n                        }\n                    }\n                }\n            }\n\n          if (elt->type == '%')\n            {\n              os << '%';\n              retval++;\n            }\n          else if (elt->args == 0 && ! elt->text.empty ())\n            {\n              os << elt->text;\n              retval += (elt->text.length ());\n            }\n          else if (elt->type == 's' || elt->type == 'c')\n            {\n              octave_value val = val_cache.get_next_value (elt->type);\n\n              if (val_cache)\n                {\n                  if (val.is_string ())\n                    {\n                      std::string sval = val.string_value ();\n\n                      retval += do_printf_string (os, elt, nsa, sa_1,\n                                                  sa_2, sval, who);\n                    }\n                  else\n                    retval += do_numeric_printf_conv (os, elt, nsa, sa_1,\n                                                      sa_2, val, who);\n                }\n              else\n                break;\n            }\n          else\n            {\n              octave_value val = val_cache.get_next_value ();\n\n              if (val_cache)\n                {\n                  if (! val.isempty ())\n                    retval += do_numeric_printf_conv (os, elt, nsa, sa_1,\n                                                      sa_2, val, who);\n                }\n              else\n                break;\n            }\n\n          if (! os)\n            {\n              error (who, \"write error\");\n              break;\n            }\n\n          elt = fmt_list.next (m_nconv > 0 && ! val_cache.exhausted ());\n\n          if (! elt || (val_cache.exhausted () && elt->args > 0))\n            break;\n        }\n    }\n\n  return retval;\n}\n\nint\nbase_stream::printf (const std::string& fmt,\n                     const octave_value_list& args,\n                     const std::string& who)\n{\n  printf_format_list fmt_list (fmt);\n\n  if (fmt_list.num_conversions () == -1)\n    ::error (\"%s: invalid format specified\", who.c_str ());\n\n  return do_printf (fmt_list, args, who);\n}\n\nint\nbase_stream::puts (const std::string& s, const std::string& who)\n{\n  int retval = -1;\n\n  std::ostream *osp = preferred_output_stream ();\n\n  if (! osp)\n    invalid_operation (who, \"writing\");\n  else\n    {\n      std::ostream& os = *osp;\n\n      os << s;\n\n      if (! os)\n        error (who, \"write error\");\n      else\n        {\n          // FIXME: why does this seem to be necessary?\n          // Without it, output from a loop like\n          //\n          //   for i = 1:100, fputs (stdout, \"foo\\n\"); endfor\n          //\n          // doesn't seem to go to the pager immediately.\n          os.flush ();\n\n          if (os)\n            retval = 0;\n          else\n            error (who, \"write error\");\n        }\n    }\n\n  return retval;\n}\n\n// Return current error message for this stream.\n\nstd::string\nbase_stream::error (bool clear_err, int& err_num)\n{\n  err_num = (m_fail ? -1 : 0);\n\n  std::string tmp = m_errmsg;\n\n  if (clear_err)\n    clear ();\n\n  return tmp;\n}\n\nvoid\nbase_stream::invalid_operation (const std::string& who, const char *rw)\n{\n  // Note: This calls the member fcn error, not ::error from error.h.\n  error (who, std::string (\"stream not open for \") + rw);\n}\n\nint\nstream::flush ()\n{\n  int retval = -1;\n\n  if (stream_ok ())\n    retval = m_rep->flush ();\n\n  return retval;\n}\n\nstd::string\nstream::getl (octave_idx_type max_len, bool& err, const std::string& who)\n{\n  std::string retval;\n\n  if (stream_ok ())\n    retval = m_rep->getl (max_len, err, who);\n\n  return retval;\n}\n\nstd::string\nstream::getl (const octave_value& tc_max_len, bool& err,\n              const std::string& who)\n{\n  err = false;\n\n  int conv_err = 0;\n\n  int max_len = -1;\n\n  if (tc_max_len.is_defined ())\n    {\n      max_len = convert_to_valid_int (tc_max_len, conv_err);\n\n      if (conv_err || max_len < 0)\n        {\n          err = true;\n          ::error (\"%s: invalid maximum length specified\", who.c_str ());\n        }\n    }\n\n  return getl (max_len, err, who);\n}\n\nstd::string\nstream::gets (octave_idx_type max_len, bool& err, const std::string& who)\n{\n  std::string retval;\n\n  if (stream_ok ())\n    retval = m_rep->gets (max_len, err, who);\n\n  return retval;\n}\n\nstd::string\nstream::gets (const octave_value& tc_max_len, bool& err,\n              const std::string& who)\n{\n  err = false;\n\n  int conv_err = 0;\n\n  int max_len = -1;\n\n  if (tc_max_len.is_defined ())\n    {\n      max_len = convert_to_valid_int (tc_max_len, conv_err);\n\n      if (conv_err || max_len < 0)\n        {\n          err = true;\n          ::error (\"%s: invalid maximum length specified\", who.c_str ());\n        }\n    }\n\n  return gets (max_len, err, who);\n}\n\noff_t\nstream::skipl (off_t count, bool& err, const std::string& who)\n{\n  off_t retval = -1;\n\n  if (stream_ok ())\n    retval = m_rep->skipl (count, err, who);\n\n  return retval;\n}\n\noff_t\nstream::skipl (const octave_value& tc_count, bool& err,\n               const std::string& who)\n{\n  err = false;\n\n  int conv_err = 0;\n\n  int count = 1;\n\n  if (tc_count.is_defined ())\n    {\n      if (tc_count.is_scalar_type ()\n          && math::isinf (tc_count.scalar_value ()))\n        count = -1;\n      else\n        {\n          count = convert_to_valid_int (tc_count, conv_err);\n\n          if (conv_err || count < 0)\n            {\n              err = true;\n              ::error (\"%s: invalid number of lines specified\",\n                       who.c_str ());\n            }\n        }\n    }\n\n  return skipl (count, err, who);\n}\n\nint\nstream::seek (off_t offset, int origin)\n{\n  int status = -1;\n\n  if (stream_ok ())\n    {\n      clearerr ();\n\n      // Find current position so we can return to it if needed.\n      off_t orig_pos = m_rep->tell ();\n\n      // Move to end of file.  If successful, find the offset of the end.\n      status = m_rep->seek (0, SEEK_END);\n\n      if (status == 0)\n        {\n          off_t eof_pos = m_rep->tell ();\n\n          if (origin == SEEK_CUR)\n            {\n              // Move back to original position, otherwise we will be seeking\n              // from the end of file which is probably not the original\n              // location.\n              m_rep->seek (orig_pos, SEEK_SET);\n            }\n\n          // Attempt to move to desired position; may be outside bounds of\n          // existing file.\n          status = m_rep->seek (offset, origin);\n\n          if (status == 0)\n            {\n              // Where are we after moving to desired position?\n              off_t desired_pos = m_rep->tell ();\n\n              // I don't think save_pos can be less than zero,\n              // but we'll check anyway...\n              if (desired_pos > eof_pos || desired_pos < 0)\n                {\n                  // Seek outside bounds of file.\n                  // Failure should leave position unchanged.\n                  m_rep->seek (orig_pos, SEEK_SET);\n\n                  status = -1;\n                }\n            }\n          else\n            {\n              // Seeking to the desired position failed.\n              // Move back to original position and return failure status.\n              m_rep->seek (orig_pos, SEEK_SET);\n\n              status = -1;\n            }\n        }\n    }\n\n  return status;\n}\n\nint\nstream::seek (const octave_value& tc_offset,\n              const octave_value& tc_origin)\n{\n  int retval = -1;\n\n  // FIXME: should we have octave_value methods that handle off_t explicitly?\n  octave_int64 val = tc_offset.xint64_scalar_value (\"fseek: invalid value for offset\");\n  off_t xoffset = val.value ();\n\n  int conv_err = 0;\n\n  int origin = SEEK_SET;\n\n  if (tc_origin.is_string ())\n    {\n      std::string xorigin = tc_origin.xstring_value (\"fseek: invalid value for origin\");\n\n      if (xorigin == \"bof\")\n        origin = SEEK_SET;\n      else if (xorigin == \"cof\")\n        origin = SEEK_CUR;\n      else if (xorigin == \"eof\")\n        origin = SEEK_END;\n      else\n        conv_err = -1;\n    }\n  else\n    {\n      int xorigin = convert_to_valid_int (tc_origin, conv_err);\n\n      if (! conv_err)\n        {\n          if (xorigin == -1)\n            origin = SEEK_SET;\n          else if (xorigin == 0)\n            origin = SEEK_CUR;\n          else if (xorigin == 1)\n            origin = SEEK_END;\n          else\n            conv_err = -1;\n        }\n    }\n\n  if (conv_err)\n    ::error (\"fseek: invalid value for origin\");\n\n  retval = seek (xoffset, origin);\n\n  if (retval != 0)\n    // Note: error is member fcn from stream, not ::error.\n    error (\"fseek: failed to seek to requested position\");\n\n  return retval;\n}\n\noff_t\nstream::tell ()\n{\n  off_t retval = -1;\n\n  if (stream_ok ())\n    retval = m_rep->tell ();\n\n  return retval;\n}\n\nint\nstream::rewind ()\n{\n  return seek (0, SEEK_SET);\n}\n\nbool\nstream::is_open () const\n{\n  bool retval = false;\n\n  if (stream_ok ())\n    retval = m_rep->is_open ();\n\n  return retval;\n}\n\nvoid\nstream::close ()\n{\n  if (stream_ok ())\n    {\n      m_rep->flush ();\n      m_rep->close ();\n    }\n}\n\ntemplate <typename SRC_T, typename DST_T>\nstatic octave_value\nconvert_and_copy (std::list<void *>& input_buf_list,\n                  octave_idx_type input_buf_elts,\n                  octave_idx_type elts_read,\n                  octave_idx_type nr, octave_idx_type nc, bool swap,\n                  bool do_float_fmt_conv, bool do_NA_conv,\n                  mach_info::float_format from_flt_fmt)\n{\n  typedef typename DST_T::element_type dst_elt_type;\n\n  DST_T conv (dim_vector (nr, nc));\n\n  dst_elt_type *conv_data = conv.rwdata ();\n\n  octave_idx_type j = 0;\n\n  for (auto it = input_buf_list.cbegin (); it != input_buf_list.cend (); it++)\n    {\n      SRC_T *data = static_cast<SRC_T *> (*it);\n\n      if (swap || do_float_fmt_conv)\n        {\n          if (do_NA_conv)\n            {\n              for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;\n                   i++, j++)\n                {\n                  if (swap)\n                    swap_bytes<sizeof (SRC_T)> (&data[i]);\n                  else if (do_float_fmt_conv)\n                    do_float_format_conversion (&data[i], sizeof (SRC_T),\n                                                1, from_flt_fmt,\n                                                mach_info::native_float_format ());\n\n                  // FIXME: Potentially add conversion code for MIPS NA here\n                  //        Bug #59830.\n                  // dst_elt_type tmp (data[i]);\n                  // if (is_MIPS_NA (tmp))\n                  //  tmp = replace_MIPS_NA (tmp);\n                  // conv_data[j] = tmp;\n\n                  conv_data[j] = data[i];\n                }\n            }\n          else\n            {\n              for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;\n                   i++, j++)\n                {\n                  if (swap)\n                    swap_bytes<sizeof (SRC_T)> (&data[i]);\n                  else if (do_float_fmt_conv)\n                    do_float_format_conversion (&data[i], sizeof (SRC_T),\n                                                1, from_flt_fmt,\n                                                mach_info::native_float_format ());\n\n                  conv_data[j] = data[i];\n                }\n            }\n        }\n      else\n        {\n          if (do_NA_conv)\n            {\n              for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;\n                   i++, j++)\n                {\n                  // FIXME: Potentially add conversion code for MIPS NA here\n                  conv_data[j] = data[i];\n                }\n            }\n          else\n            {\n              for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;\n                   i++, j++)\n                conv_data[j] = data[i];\n            }\n        }\n\n      delete [] data;\n    }\n\n  input_buf_list.clear ();\n\n  for (octave_idx_type i = elts_read; i < nr * nc; i++)\n    conv_data[i] = dst_elt_type (0);\n\n  return conv;\n}\n\ntypedef octave_value (*conv_fptr)\n  (std::list<void *>& input_buf_list, octave_idx_type input_buf_elts,\n   octave_idx_type elts_read, octave_idx_type nr, octave_idx_type nc,\n   bool swap, bool do_float_fmt_conv, bool do_NA_conv,\n   mach_info::float_format from_flt_fmt);\n\n#define TABLE_ELT(T, U, V, W)                                           \\\n  conv_fptr_table[oct_data_conv::T][oct_data_conv::U] = convert_and_copy<V, W>\n\n#define FILL_TABLE_ROW(T, V)                    \\\n  TABLE_ELT (T, dt_int8, V, int8NDArray);       \\\n  TABLE_ELT (T, dt_uint8, V, uint8NDArray);     \\\n  TABLE_ELT (T, dt_int16, V, int16NDArray);     \\\n  TABLE_ELT (T, dt_uint16, V, uint16NDArray);   \\\n  TABLE_ELT (T, dt_int32, V, int32NDArray);     \\\n  TABLE_ELT (T, dt_uint32, V, uint32NDArray);   \\\n  TABLE_ELT (T, dt_int64, V, int64NDArray);     \\\n  TABLE_ELT (T, dt_uint64, V, uint64NDArray);   \\\n  TABLE_ELT (T, dt_single, V, FloatNDArray);    \\\n  TABLE_ELT (T, dt_double, V, NDArray);         \\\n  TABLE_ELT (T, dt_char, V, charNDArray);       \\\n  TABLE_ELT (T, dt_schar, V, charNDArray);      \\\n  TABLE_ELT (T, dt_uchar, V, charNDArray);      \\\n  TABLE_ELT (T, dt_logical, V, boolNDArray);\n\noctave_value\nstream::finalize_read (std::list<void *>& input_buf_list,\n                       octave_idx_type input_buf_elts,\n                       octave_idx_type elts_read,\n                       octave_idx_type nr, octave_idx_type nc,\n                       oct_data_conv::data_type input_type,\n                       oct_data_conv::data_type output_type,\n                       mach_info::float_format ffmt)\n{\n  octave_value retval;\n\n  static bool initialized = false;\n\n  // Table function pointers for return types x read types.\n\n  static conv_fptr conv_fptr_table[oct_data_conv::dt_unknown][14];\n\n  if (! initialized)\n    {\n      for (int i = 0; i < oct_data_conv::dt_unknown; i++)\n        for (int j = 0; j < 14; j++)\n          conv_fptr_table[i][j] = nullptr;\n\n      FILL_TABLE_ROW (dt_int8, int8_t);\n      FILL_TABLE_ROW (dt_uint8, uint8_t);\n      FILL_TABLE_ROW (dt_int16, int16_t);\n      FILL_TABLE_ROW (dt_uint16, uint16_t);\n      FILL_TABLE_ROW (dt_int32, int32_t);\n      FILL_TABLE_ROW (dt_uint32, uint32_t);\n      FILL_TABLE_ROW (dt_int64, int64_t);\n      FILL_TABLE_ROW (dt_uint64, uint64_t);\n      FILL_TABLE_ROW (dt_single, float);\n      FILL_TABLE_ROW (dt_double, double);\n      FILL_TABLE_ROW (dt_char, char);\n      FILL_TABLE_ROW (dt_schar, signed char);\n      FILL_TABLE_ROW (dt_uchar, unsigned char);\n      FILL_TABLE_ROW (dt_logical, bool);\n\n      initialized = true;\n    }\n\n  bool swap = false;\n\n  if (ffmt == mach_info::flt_fmt_unknown)\n    ffmt = float_format ();\n\n  if (mach_info::words_big_endian ())\n    swap = (ffmt == mach_info::flt_fmt_ieee_little_endian);\n  else\n    swap = (ffmt == mach_info::flt_fmt_ieee_big_endian);\n\n  bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double\n                             || input_type == oct_data_conv::dt_single)\n                            && ffmt != float_format ());\n\n  bool do_NA_conv = (output_type == oct_data_conv::dt_double);\n\n  switch (output_type)\n    {\n    case oct_data_conv::dt_int8:\n    case oct_data_conv::dt_uint8:\n    case oct_data_conv::dt_int16:\n    case oct_data_conv::dt_uint16:\n    case oct_data_conv::dt_int32:\n    case oct_data_conv::dt_uint32:\n    case oct_data_conv::dt_int64:\n    case oct_data_conv::dt_uint64:\n    case oct_data_conv::dt_single:\n    case oct_data_conv::dt_double:\n    case oct_data_conv::dt_char:\n    case oct_data_conv::dt_schar:\n    case oct_data_conv::dt_uchar:\n    case oct_data_conv::dt_logical:\n      {\n        conv_fptr fptr = conv_fptr_table[input_type][output_type];\n\n        retval = fptr (input_buf_list, input_buf_elts, elts_read,\n                       nr, nc, swap, do_float_fmt_conv, do_NA_conv, ffmt);\n      }\n      break;\n\n    default:\n      ::error (\"read: invalid type specification\");\n    }\n\n  return retval;\n}\n\noctave_value\nstream::read (const Array<double>& size, octave_idx_type block_size,\n              oct_data_conv::data_type input_type,\n              oct_data_conv::data_type output_type,\n              octave_idx_type skip, mach_info::float_format ffmt,\n              octave_idx_type& count)\n{\n  octave_value retval;\n\n  if (! stream_ok ())\n    return retval;\n\n  octave_idx_type nr = -1;\n  octave_idx_type nc = -1;\n\n  bool one_elt_size_spec = false;\n\n  // FIXME: We may eventually want to make this extensible.\n\n  // FIXME: We need a better way to ensure that this numbering stays\n  // consistent with the order of the elements in the data_type enum in the\n  // oct_data_conv class.\n\n  std::ptrdiff_t tmp_count = 0;\n\n  try\n    {\n      get_size (size, nr, nc, one_elt_size_spec, \"fread\");\n    }\n  catch (const execution_exception&)\n    {\n      invalid_operation (\"fread\", \"reading\");\n\n      return retval;\n    }\n\n  if (one_elt_size_spec)\n    {\n      // If NR == 0, Matlab returns [](0x0).\n\n      // If NR > 0, the result will be a column vector with the given\n      // number of rows.\n\n      // If NR < 0, then we have Inf and the result will be a column\n      // vector but we have to wait to see how big NR will be.\n\n      if (nr == 0)\n        nr = nc = 0;\n      else\n        nc = 1;\n    }\n  else\n    {\n      // Matlab returns [] even if there are two elements in the size\n      // specification and one is nonzero.\n\n      // If NC < 0 we have [NR, Inf] and we'll wait to decide how big NC\n      // should be.\n\n      if (nr == 0 || nc == 0)\n        nr = nc = 0;\n    }\n\n  octave_idx_type elts_to_read = nr * nc;\n\n  bool read_to_eof = elts_to_read < 0;\n\n  octave_idx_type input_buf_elts = -1;\n\n  if (skip == 0)\n    {\n      if (read_to_eof)\n        input_buf_elts = 1024 * 1024;\n      else\n        input_buf_elts = elts_to_read;\n    }\n  else\n    input_buf_elts = block_size;\n\n  octave_idx_type input_elt_size\n    = oct_data_conv::data_type_size (input_type);\n\n  std::ptrdiff_t input_buf_size\n    = static_cast<std::ptrdiff_t> (input_buf_elts) * input_elt_size;\n\n  panic_if (input_buf_size < 0);\n\n  // Must also work and return correct type object for 0 elements to read.\n  std::istream *isp = input_stream ();\n\n  if (! isp)\n    error (\"fread: invalid input stream\");\n  else\n    {\n      std::istream& is = *isp;\n\n      // Initialize eof_pos variable just once per function call\n      off_t eof_pos = 0;\n      off_t cur_pos = 0;\n      if (skip != 0 && is && ! is.eof ())\n        {\n          cur_pos = is.tellg ();\n          is.seekg (0, is.end);\n          eof_pos = is.tellg ();\n          is.seekg (cur_pos, is.beg);\n        }\n\n      std::list<void *> input_buf_list;\n\n      while (is && ! is.eof ()\n             && (read_to_eof || tmp_count < elts_to_read))\n        {\n          if (! read_to_eof)\n            {\n              octave_idx_type remaining_elts = elts_to_read - tmp_count;\n\n              if (remaining_elts < input_buf_elts)\n                input_buf_size = remaining_elts * input_elt_size;\n            }\n\n          char *input_buf = new char [input_buf_size];\n\n          is.read (input_buf, input_buf_size);\n\n          std::size_t gcount = is.gcount ();\n\n          cur_pos += gcount;\n\n          octave_idx_type nel = gcount / input_elt_size;\n\n          tmp_count += nel;\n\n          input_buf_list.push_back (input_buf);\n\n          if (skip != 0 && nel == block_size && is)\n            {\n              // Attempt to skip.\n              // If skip would move past EOF, position at EOF.\n              off_t remaining = eof_pos - cur_pos;\n\n              if (remaining < skip)\n                {\n                  is.seekg (0, is.end);\n                  cur_pos = eof_pos;\n                }\n              else\n                {\n                  is.seekg (skip, is.cur);\n                  cur_pos += skip;\n                }\n            }\n        }\n\n      if (read_to_eof)\n        {\n          if (nc < 0)\n            {\n              nc = tmp_count / nr;\n\n              if (tmp_count % nr != 0)\n                nc++;\n            }\n          else\n            nr = tmp_count;\n        }\n      else if (tmp_count == 0)\n        {\n          nr = 0;\n          nc = 0;\n        }\n      else if (tmp_count != nr * nc)\n        {\n          if (tmp_count % nr != 0)\n            nc = tmp_count / nr + 1;\n          else\n            nc = tmp_count / nr;\n\n          if (tmp_count < nr)\n            nr = tmp_count;\n        }\n\n      if (tmp_count > std::numeric_limits<octave_idx_type>::max ())\n        error (\"fread: number of elements read exceeds max index size\");\n      else\n        count = static_cast<octave_idx_type> (tmp_count);\n\n      retval = finalize_read (input_buf_list, input_buf_elts, count,\n                              nr, nc, input_type, output_type, ffmt);\n    }\n\n  return retval;\n}\n\noctave_idx_type\nstream::write (const octave_value& data, octave_idx_type block_size,\n               oct_data_conv::data_type output_type,\n               octave_idx_type skip, mach_info::float_format flt_fmt)\n{\n  octave_idx_type retval = -1;\n\n  if (! stream_ok ())\n    invalid_operation (\"fwrite\", \"writing\");\n  else\n    {\n      if (flt_fmt == mach_info::flt_fmt_unknown)\n        flt_fmt = float_format ();\n\n      octave_idx_type status = data.write (*this, block_size, output_type,\n                                           skip, flt_fmt);\n\n      if (status < 0)\n        error (\"fwrite: write error\");\n      else\n        retval = status;\n    }\n\n  return retval;\n}\n\ntemplate <typename T, typename V>\nstatic void\nconvert_chars (const void *data, void *conv_data, octave_idx_type n_elts)\n{\n  const T *tt_data = static_cast<const T *> (data);\n\n  V *vt_data = static_cast<V *> (conv_data);\n\n  for (octave_idx_type i = 0; i < n_elts; i++)\n    vt_data[i] = tt_data[i];\n}\n\ntemplate <typename T, typename V>\nstatic void\nconvert_ints (const T *data, void *conv_data, octave_idx_type n_elts,\n              bool swap)\n{\n  typedef typename V::val_type val_type;\n\n  val_type *vt_data = static_cast<val_type *> (conv_data);\n\n  for (octave_idx_type i = 0; i < n_elts; i++)\n    {\n      // Yes, we want saturation semantics when converting to an integer type.\n      V val (data[i]);\n\n      vt_data[i] = val.value ();\n\n      if (swap)\n        swap_bytes<sizeof (val_type)> (&vt_data[i]);\n    }\n}\n\ntemplate <typename T>\nclass ultimate_element_type\n{\npublic:\n  typedef T type;\n};\n\ntemplate <typename T>\nclass ultimate_element_type<octave_int<T>>\n{\npublic:\n  typedef T type;\n};\n\ntemplate <typename T>\nstatic bool\nconvert_data (const T *data, void *conv_data, octave_idx_type n_elts,\n              oct_data_conv::data_type output_type,\n              mach_info::float_format flt_fmt)\n{\n  bool retval = true;\n\n  bool swap = false;\n\n  if (mach_info::words_big_endian ())\n    swap = (flt_fmt == mach_info::flt_fmt_ieee_little_endian);\n  else\n    swap = (flt_fmt == mach_info::flt_fmt_ieee_big_endian);\n\n  bool do_float_conversion = flt_fmt != mach_info::float_format ();\n\n  typedef typename ultimate_element_type<T>::type ult_elt_type;\n\n  switch (output_type)\n    {\n    case oct_data_conv::dt_char:\n      convert_chars<ult_elt_type, char> (data, conv_data, n_elts);\n      break;\n\n    case oct_data_conv::dt_schar:\n      convert_chars<ult_elt_type, signed char> (data, conv_data, n_elts);\n      break;\n\n    case oct_data_conv::dt_uchar:\n      convert_chars<ult_elt_type, unsigned char> (data, conv_data, n_elts);\n      break;\n\n    case oct_data_conv::dt_int8:\n      convert_ints<T, octave_int8> (data, conv_data, n_elts, swap);\n      break;\n\n    case oct_data_conv::dt_uint8:\n      convert_ints<T, octave_uint8> (data, conv_data, n_elts, swap);\n      break;\n\n    case oct_data_conv::dt_int16:\n      convert_ints<T, octave_int16> (data, conv_data, n_elts, swap);\n      break;\n\n    case oct_data_conv::dt_uint16:\n      convert_ints<T, octave_uint16> (data, conv_data, n_elts, swap);\n      break;\n\n    case oct_data_conv::dt_int32:\n      convert_ints<T, octave_int32> (data, conv_data, n_elts, swap);\n      break;\n\n    case oct_data_conv::dt_uint32:\n      convert_ints<T, octave_uint32> (data, conv_data, n_elts, swap);\n      break;\n\n    case oct_data_conv::dt_int64:\n      convert_ints<T, octave_int64> (data, conv_data, n_elts, swap);\n      break;\n\n    case oct_data_conv::dt_uint64:\n      convert_ints<T, octave_uint64> (data, conv_data, n_elts, swap);\n      break;\n\n    case oct_data_conv::dt_single:\n      {\n        float *vt_data = static_cast<float *> (conv_data);\n\n        for (octave_idx_type i = 0; i < n_elts; i++)\n          {\n            vt_data[i] = data[i];\n\n            if (do_float_conversion)\n              do_float_format_conversion (&vt_data[i], 1, flt_fmt);\n          }\n      }\n      break;\n\n    case oct_data_conv::dt_double:\n      {\n        double *vt_data = static_cast<double *> (conv_data);\n\n        for (octave_idx_type i = 0; i < n_elts; i++)\n          {\n            vt_data[i] = data[i];\n\n            if (do_float_conversion)\n              do_double_format_conversion (&vt_data[i], 1, flt_fmt);\n          }\n      }\n      break;\n\n    default:\n      ::error (\"write: invalid type specification\");\n    }\n\n  return retval;\n}\n\nbool\nstream::write_bytes (const void *data, std::size_t nbytes)\n{\n  bool status = false;\n\n  std::ostream *osp = output_stream ();\n\n  if (osp)\n    {\n      std::ostream& os = *osp;\n\n      if (os)\n        {\n          os.write (static_cast<const char *> (data), nbytes);\n\n          if (os)\n            status = true;\n        }\n    }\n\n  return status;\n}\n\nbool\nstream::skip_bytes (std::size_t skip)\n{\n  bool status = false;\n\n  std::ostream *osp = output_stream ();\n\n  if (! osp)\n    return false;\n\n  std::ostream& os = *osp;\n\n  // Seek to skip when inside bounds of existing file.\n  // Otherwise, write NUL to skip.\n  off_t orig_pos = tell ();\n\n  seek (0, SEEK_END);\n\n  off_t eof_pos = tell ();\n\n  // Is it possible for this to fail to return us to the original position?\n  seek (orig_pos, SEEK_SET);\n\n  std::size_t remaining = eof_pos - orig_pos;\n\n  if (remaining < skip)\n    {\n      seek (0, SEEK_END);\n\n      // FIXME: probably should try to write larger blocks...\n      unsigned char zero = 0;\n      for (std::size_t j = 0; j < skip - remaining; j++)\n        os.write (reinterpret_cast<const char *> (&zero), 1);\n    }\n  else\n    seek (skip, SEEK_CUR);\n\n  if (os)\n    status = true;\n\n  return status;\n}\n\ntemplate <typename T>\noctave_idx_type\nstream::write (const Array<T>& data, octave_idx_type block_size,\n               oct_data_conv::data_type output_type,\n               octave_idx_type skip,\n               mach_info::float_format flt_fmt)\n{\n  bool swap = false;\n\n  if (mach_info::words_big_endian ())\n    swap = (flt_fmt == mach_info::flt_fmt_ieee_little_endian);\n  else\n    swap = (flt_fmt == mach_info::flt_fmt_ieee_big_endian);\n\n  bool do_data_conversion = (swap || ! is_equivalent_type<T> (output_type)\n                             || flt_fmt != mach_info::float_format ());\n\n  octave_idx_type nel = data.numel ();\n\n  octave_idx_type chunk_size;\n\n  if (skip != 0)\n    chunk_size = block_size;\n  else if (do_data_conversion)\n    chunk_size = 1024 * 1024;\n  else\n    chunk_size = nel;\n\n  octave_idx_type i = 0;\n\n  const T *pdata = data.data ();\n\n  while (i < nel)\n    {\n      if (skip != 0)\n        {\n          if (! skip_bytes (skip))\n            return -1;\n        }\n\n      octave_idx_type remaining_nel = nel - i;\n\n      if (chunk_size > remaining_nel)\n        chunk_size = remaining_nel;\n\n      bool status = false;\n\n      if (do_data_conversion)\n        {\n          std::size_t output_size\n            = chunk_size * oct_data_conv::data_type_size (output_type);\n\n          OCTAVE_LOCAL_BUFFER (unsigned char, conv_data, output_size);\n\n          status = convert_data (&pdata[i], conv_data, chunk_size,\n                                 output_type, flt_fmt);\n\n          if (status)\n            status = write_bytes (conv_data, output_size);\n        }\n      else\n        status = write_bytes (pdata, sizeof (T) * chunk_size);\n\n      if (! status)\n        return -1;\n\n      i += chunk_size;\n    }\n\n  return nel;\n}\n\n#define INSTANTIATE_WRITE(T)                                            \\\n  template                                                              \\\n  OCTINTERP_API octave_idx_type                                         \\\n  stream::write (const Array<T>& data, octave_idx_type block_size,      \\\n                 oct_data_conv::data_type output_type,                  \\\n                 octave_idx_type skip,                                  \\\n                 mach_info::float_format flt_fmt)\n\nINSTANTIATE_WRITE (octave_int8);\nINSTANTIATE_WRITE (octave_uint8);\nINSTANTIATE_WRITE (octave_int16);\nINSTANTIATE_WRITE (octave_uint16);\nINSTANTIATE_WRITE (octave_int32);\nINSTANTIATE_WRITE (octave_uint32);\nINSTANTIATE_WRITE (octave_int64);\nINSTANTIATE_WRITE (octave_uint64);\nINSTANTIATE_WRITE (int8_t);\nINSTANTIATE_WRITE (uint8_t);\nINSTANTIATE_WRITE (int16_t);\nINSTANTIATE_WRITE (uint16_t);\nINSTANTIATE_WRITE (int32_t);\nINSTANTIATE_WRITE (uint32_t);\nINSTANTIATE_WRITE (int64_t);\nINSTANTIATE_WRITE (uint64_t);\nINSTANTIATE_WRITE (bool);\n#if defined (OCTAVE_HAVE_OVERLOAD_CHAR_INT8_TYPES)\nINSTANTIATE_WRITE (char);\n#endif\nINSTANTIATE_WRITE (float);\nINSTANTIATE_WRITE (double);\n\noctave_value\nstream::scanf (const std::string& fmt, const Array<double>& size,\n               octave_idx_type& count, const std::string& who)\n{\n  octave_value retval;\n\n  if (stream_ok ())\n    retval = m_rep->scanf (fmt, size, count, who);\n\n  return retval;\n}\n\noctave_value\nstream::scanf (const octave_value& fmt, const Array<double>& size,\n               octave_idx_type& count, const std::string& who)\n{\n  octave_value retval = Matrix ();\n\n  if (fmt.is_string ())\n    {\n      std::string sfmt = fmt.string_value ();\n\n      if (fmt.is_sq_string ())\n        sfmt = do_string_escapes (sfmt);\n\n      retval = scanf (sfmt, size, count, who);\n    }\n  else\n    {\n      // Note: error is member fcn from stream, not ::error.\n      error (who + \": format must be a string\");\n    }\n\n  return retval;\n}\n\noctave_value_list\nstream::oscanf (const std::string& fmt, const std::string& who)\n{\n  octave_value_list retval;\n\n  if (stream_ok ())\n    retval = m_rep->oscanf (fmt, who);\n\n  return retval;\n}\n\noctave_value_list\nstream::oscanf (const octave_value& fmt, const std::string& who)\n{\n  octave_value_list retval;\n\n  if (fmt.is_string ())\n    {\n      std::string sfmt = fmt.string_value ();\n\n      if (fmt.is_sq_string ())\n        sfmt = do_string_escapes (sfmt);\n\n      retval = oscanf (sfmt, who);\n    }\n  else\n    {\n      // Note: error is member fcn from stream, not ::error.\n      error (who + \": format must be a string\");\n    }\n\n  return retval;\n}\n\noctave_value\nstream::textscan (const std::string& fmt, octave_idx_type ntimes,\n                  const octave_value_list& options,\n                  const std::string& who, octave_idx_type& count)\n{\n  return (stream_ok ()\n          ? m_rep->do_textscan (fmt, ntimes, options, who, count)\n          : octave_value ());\n}\n\nint\nstream::printf (const std::string& fmt, const octave_value_list& args,\n                const std::string& who)\n{\n  int retval = -1;\n\n  if (stream_ok ())\n    retval = m_rep->printf (fmt, args, who);\n\n  return retval;\n}\n\nint\nstream::printf (const octave_value& fmt, const octave_value_list& args,\n                const std::string& who)\n{\n  int retval = 0;\n\n  if (fmt.is_string ())\n    {\n      std::string sfmt = fmt.string_value ();\n\n      if (fmt.is_sq_string ())\n        sfmt = do_string_escapes (sfmt);\n\n      retval = printf (sfmt, args, who);\n    }\n  else\n    {\n      // Note: error is member fcn from stream, not ::error.\n      error (who + \": format must be a string\");\n    }\n\n  return retval;\n}\n\nint\nstream::puts (const std::string& s, const std::string& who)\n{\n  int retval = -1;\n\n  if (stream_ok ())\n    retval = m_rep->puts (s, who);\n\n  return retval;\n}\n\n// FIXME: maybe this should work for string arrays too.\n\nint\nstream::puts (const octave_value& tc_s, const std::string& who)\n{\n  int retval = -1;\n\n  if (tc_s.is_string ())\n    {\n      std::string s = tc_s.string_value ();\n      retval = puts (s, who);\n    }\n  else\n    {\n      // Note: error is member fcn from stream, not ::error.\n      error (who + \": argument must be a string\");\n    }\n\n  return retval;\n}\n\nbool\nstream::eof () const\n{\n  int retval = -1;\n\n  if (stream_ok ())\n    retval = m_rep->eof ();\n\n  return retval;\n}\n\nstd::string\nstream::error (bool clear, int& err_num)\n{\n  std::string retval = \"invalid stream object\";\n\n  if (stream_ok (false))\n    retval = m_rep->error (clear, err_num);\n\n  return retval;\n}\n\nstd::string\nstream::name () const\n{\n  std::string retval;\n\n  if (stream_ok ())\n    retval = m_rep->name ();\n\n  return retval;\n}\n\nint\nstream::mode () const\n{\n  int retval = 0;\n\n  if (stream_ok ())\n    retval = m_rep->mode ();\n\n  return retval;\n}\n\nmach_info::float_format\nstream::float_format () const\n{\n  mach_info::float_format retval = mach_info::flt_fmt_unknown;\n\n  if (stream_ok ())\n    retval = m_rep->float_format ();\n\n  return retval;\n}\n\nstd::string\nstream::mode_as_string (int mode)\n{\n  std::string retval = \"???\";\n  std::ios::openmode in_mode = static_cast<std::ios::openmode> (mode);\n\n  if (in_mode == std::ios::in)\n    retval = \"r\";\n  else if (in_mode == std::ios::out\n           || in_mode == (std::ios::out | std::ios::trunc))\n    retval = \"w\";\n  else if (in_mode == (std::ios::out | std::ios::app))\n    retval = \"a\";\n  else if (in_mode == (std::ios::in | std::ios::out))\n    retval = \"r+\";\n  else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc))\n    retval = \"w+\";\n  else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate))\n    retval = \"a+\";\n  else if (in_mode == (std::ios::in | std::ios::binary))\n    retval = \"rb\";\n  else if (in_mode == (std::ios::out | std::ios::binary)\n           || in_mode == (std::ios::out | std::ios::trunc | std::ios::binary))\n    retval = \"wb\";\n  else if (in_mode == (std::ios::out | std::ios::app | std::ios::binary))\n    retval = \"ab\";\n  else if (in_mode == (std::ios::in | std::ios::out | std::ios::binary))\n    retval = \"r+b\";\n  else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc\n                       | std::ios::binary))\n    retval = \"w+b\";\n  else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate\n                       | std::ios::binary))\n    retval = \"a+b\";\n\n  return retval;\n}\n\nstream_list::stream_list (interpreter& interp)\n  : m_list (), m_lookup_cache (m_list.end ()), m_stdin_file (-1),\n    m_stdout_file (-1), m_stderr_file (-1)\n{\n  stream stdin_stream = istream::create (&std::cin, \"stdin\");\n\n  // This uses octave_stdout (see pager.h), not std::cout so that\n  // Octave's standard output stream will pass through the pager.\n\n  // FIXME: we should be accessing octave_stdout from the interpreter.\n\n  output_system& output_sys = interp.get_output_system ();\n\n  stream stdout_stream\n    = ostream::create (&(output_sys.__stdout__ ()), \"stdout\");\n\n  stream stderr_stream = ostream::create (&std::cerr, \"stderr\");\n\n  m_stdin_file = insert (stdin_stream);\n  m_stdout_file = insert (stdout_stream);\n  m_stderr_file = insert (stderr_stream);\n}\n\nstream_list::~stream_list ()\n{\n  clear ();\n}\n\nint\nstream_list::insert (stream& os)\n{\n  // Insert item with key corresponding to file-descriptor.\n\n  int stream_number = os.file_number ();\n\n  if (stream_number == -1)\n    return stream_number;\n\n  // Should we test for\n  //\n  //  (m_list.find (stream_number) != m_list.end ()\n  //   && m_list[stream_number].is_open ())\n  //\n  // and respond with \"error (\"internal error: ...\")\"?  It should not\n  // happen except for some bug or if the user has opened a stream with\n  // an interpreted command, but closed it directly with a system call\n  // in an oct-file; then the kernel knows the fd is free, but Octave\n  // does not know.  If it happens, it should not do harm here to simply\n  // overwrite this entry, although the wrong entry might have done harm\n  // before.\n\n  if (m_list.size () >= m_list.max_size ())\n    ::error (\"could not create file id\");\n\n  m_list[stream_number] = os;\n\n  return stream_number;\n}\n\nOCTAVE_NORETURN static void\nerr_invalid_file_id (int fid, const std::string& who)\n{\n  if (who.empty ())\n    ::error (\"invalid stream number = %d\", fid);\n  else\n    ::error (\"%s: invalid stream number = %d\", who.c_str (), fid);\n}\n\nstream\nstream_list::lookup (int fid, const std::string& who) const\n{\n  stream retval;\n\n  if (fid < 0)\n    err_invalid_file_id (fid, who);\n\n  if (m_lookup_cache != m_list.end () && m_lookup_cache->first == fid)\n    retval = m_lookup_cache->second;\n  else\n    {\n      ostrl_map::const_iterator iter = m_list.find (fid);\n\n      if (iter == m_list.end ())\n        err_invalid_file_id (fid, who);\n\n      retval = iter->second;\n      m_lookup_cache = iter;\n    }\n\n  return retval;\n}\n\nstream\nstream_list::lookup (const octave_value& fid, const std::string& who) const\n{\n  int i = get_file_number (fid);\n\n  return lookup (i, who);\n}\n\nint\nstream_list::remove (int fid, const std::string& who)\n{\n  // Can't remove stdin (std::cin), stdout (std::cout), or stderr (std::cerr).\n  if (fid < 3)\n    err_invalid_file_id (fid, who);\n\n  auto iter = m_list.find (fid);\n\n  if (iter == m_list.end ())\n    err_invalid_file_id (fid, who);\n\n  stream os = iter->second;\n  m_list.erase (iter);\n  m_lookup_cache = m_list.end ();\n\n  // FIXME: is this check redundant?\n  if (! os.is_valid ())\n    err_invalid_file_id (fid, who);\n\n  os.close ();\n\n  return 0;\n}\n\nint\nstream_list::remove (const octave_value& fid, const std::string& who)\n{\n  int retval = -1;\n\n  if (fid.is_string () && fid.string_value () == \"all\")\n    {\n      clear (false);\n\n      retval = 0;\n    }\n  else\n    {\n      int i = get_file_number (fid);\n\n      retval = remove (i, who);\n    }\n\n  return retval;\n}\n\nvoid\nstream_list::clear (bool flush)\n{\n  if (flush)\n    {\n      // Flush stdout and stderr.\n      m_list[1].flush ();\n      m_list[2].flush ();\n    }\n\n  for (auto iter = m_list.begin (); iter != m_list.end (); )\n    {\n      int fid = iter->first;\n      if (fid < 3)  // Don't delete stdin, stdout, stderr\n        {\n          iter++;\n          continue;\n        }\n\n      stream os = iter->second;\n\n      std::string name = os.name ();\n      std::transform (name.begin (), name.end (), name.begin (), tolower);\n\n      // FIXME: This test for gnuplot is hardly foolproof.\n      if (name.find (\"gnuplot\") != std::string::npos)\n        {\n          // Don't close down pipes to gnuplot\n          iter++;\n          continue;\n        }\n\n      // Normal file handle.  Close and delete from m_list.\n      if (os.is_valid ())\n        os.close ();\n\n      m_list.erase (iter++);\n    }\n\n  m_lookup_cache = m_list.end ();\n}\n\nstring_vector\nstream_list::get_info (int fid) const\n{\n  string_vector retval (4);\n\n  if (fid < 0)\n    return retval;\n\n  stream os;\n  if (m_lookup_cache != m_list.end () && m_lookup_cache->first == fid)\n    os = m_lookup_cache->second;\n  else\n    {\n      ostrl_map::const_iterator iter = m_list.find (fid);\n\n      if (iter == m_list.end ())\n        return retval;\n\n      os = iter->second;\n      m_lookup_cache = iter;\n    }\n\n  if (! os.is_valid ())\n    return retval;\n\n  retval(0) = os.name ();\n  retval(1) = stream::mode_as_string (os.mode ());\n  retval(2) = mach_info::float_format_as_string (os.float_format ());\n  retval(3) = os.encoding ();\n\n  return retval;\n}\n\nstring_vector\nstream_list::get_info (const octave_value& fid) const\n{\n  int conv_err = 0;\n\n  if (fid.is_single_type ())\n    ::error (\"file id must be a file object or integer value\");\n\n  int int_fid = convert_to_valid_int (fid, conv_err);\n\n  if (conv_err)\n    ::error (\"file id must be a file object or integer value\");\n\n  return get_info (int_fid);\n}\n\nstd::string\nstream_list::list_open_files () const\n{\n  std::ostringstream buf;\n\n  buf << \"\\n\"\n      << \"  number  mode  arch       name\\n\"\n      << \"  ------  ----  ----       ----\\n\";\n\n  for (const auto& fid_strm : m_list)\n    {\n      stream os = fid_strm.second;\n\n      buf << \"  \"\n          << std::setiosflags (std::ios::right)\n          << std::setw (4) << fid_strm.first << \"     \"\n          // reset necessary in addition to setiosflags since this is one stmt.\n          << std::resetiosflags (std::ios::adjustfield)\n          << std::setiosflags (std::ios::left)\n          << std::setw (3)\n          << stream::mode_as_string (os.mode ())\n          << \"  \"\n          << std::setw (9)\n          << mach_info::float_format_as_string (os.float_format ())\n          << \"  \"\n          << os.name () << \"\\n\";\n    }\n\n  buf << \"\\n\";\n\n  return buf.str ();\n}\n\noctave_value\nstream_list::open_file_numbers () const\n{\n  Matrix retval (1, m_list.size (), 0.0);\n\n  int num_open = 0;\n\n  for (const auto& fid_strm : m_list)\n    {\n      // Skip stdin, stdout, and stderr.\n      if (fid_strm.first > 2 && fid_strm.second)\n        retval(0, num_open++) = fid_strm.first;\n    }\n\n  retval.resize ((num_open > 0), num_open);\n\n  return retval;\n}\n\nint\nstream_list::get_file_number (const octave_value& fid) const\n{\n  int retval = -1;\n\n  if (fid.is_string ())\n    {\n      std::string nm = fid.string_value ();\n\n      for (const auto& fid_strm : m_list)\n        {\n          // stdin, stdout, and stderr are unnamed.\n          if (fid_strm.first > 2)\n            {\n              stream os = fid_strm.second;\n\n              if (os && os.name () == nm)\n                {\n                  retval = fid_strm.first;\n                  break;\n                }\n            }\n        }\n    }\n  else if (fid.is_single_type ())\n    ::error (\"file id must be a file object, std::string, or integer value\");\n  else\n    {\n      int conv_err = 0;\n\n      int int_fid = convert_to_valid_int (fid, conv_err);\n\n      if (conv_err)\n        ::error (\"file id must be a file object, std::string, or integer value\");\n\n      retval = int_fid;\n    }\n\n  return retval;\n}\n\noctave_value\nstream_list::stdin_file () const\n{\n  return octave_value (m_stdin_file);\n}\n\noctave_value\nstream_list::stdout_file () const\n{\n  return octave_value (m_stdout_file);\n}\n\noctave_value\nstream_list::stderr_file () const\n{\n  return octave_value (m_stderr_file);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-stream.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_stream_h)\n#define octave_oct_stream_h 1\n\n#include \"octave-config.h\"\n\n#include <ios>\n#include <iosfwd>\n#include <list>\n#include <map>\n#include <memory>\n#include <string>\n\n#include \"oct-string.h\"\n\n// These only appear as reference arguments or return values.\n\nclass Cell;\nclass octave_value;\nclass octave_value_list;\nclass string_vector;\n\n#include \"Array.h\"\n#include \"data-conv.h\"\n#include \"mach-info.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\n// These are only needed as arguments to private functions, so they\n// are also treated as private.\n\nclass scanf_format_elt;\nclass scanf_format_list;\n\nclass printf_format_elt;\nclass printf_format_list;\n\n// This is a class that inherits from with std::wbuffer_convert which is\n// deprecated in C++17.\nclass OCTINTERP_API wbuffer_u8_converter;\n\n// Provide an interface for Octave streams.\n\nclass OCTINTERP_API base_stream\n{\n  friend class stream;\n\npublic:\n\n  base_stream (std::ios::openmode arg_md = std::ios::in | std::ios::out,\n               mach_info::float_format ff = mach_info::native_float_format (),\n               const std::string& encoding = \"utf-8\")\n    : m_mode (arg_md), m_flt_fmt (ff), m_encoding (encoding),\n      m_converter (nullptr), m_conv_ostream (nullptr), m_fail (false),\n      m_open_state (true), m_errmsg ()\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (base_stream)\n\n  virtual OCTINTERP_API ~base_stream ();\n\n  // The remaining functions are not specific to input or output only,\n  // and must be provided by the derived classes.\n\n  // Position a stream at OFFSET relative to ORIGIN.\n\n  virtual int seek (off_t offset, int origin) = 0;\n\n  // Return current stream position.\n\n  virtual off_t tell () = 0;\n\n  // Return TRUE if EOF has been reached on this stream.\n\n  virtual bool eof () const = 0;\n\n  // The name of the file.\n\n  virtual std::string name () const = 0;\n\n  // If the derived class provides this function and it returns a\n  // pointer to a valid istream, scanf(), read(), getl(), and gets()\n  // will automatically work for this stream.\n\n  virtual std::istream * input_stream () { return nullptr; }\n\n  // If the derived class provides this function and it returns a\n  // pointer to a valid ostream, flush(), write(), and printf() will\n  // automatically work for this stream.\n\n  virtual std::ostream * output_stream () { return nullptr; }\n\n  // Return either the original output stream or one wrapped with the\n  // encoding facet.\n\n  std::ostream * preferred_output_stream ()\n  {\n    if (! m_encoding.compare (\"utf-8\"))\n      return output_stream ();\n\n    if (m_conv_ostream)\n      return m_conv_ostream.get ();\n\n    return create_converter_stream ();\n  }\n\n  // Return TRUE if this stream is open.\n\n  bool is_open () const { return m_open_state; }\n\n  virtual void do_close () { }\n\n  void close ()\n  {\n    if (is_open ())\n      {\n        m_open_state = false;\n        do_close ();\n      }\n  }\n\n  virtual int file_number () const\n  {\n    // Kluge alert!\n\n    if (name () == \"stdin\")\n      return 0;\n    else if (name () == \"stdout\")\n      return 1;\n    else if (name () == \"stderr\")\n      return 2;\n    else\n      return -1;\n  }\n\n  bool ok () const { return ! m_fail; }\n\n  // Return current error message for this stream.\n\n  std::string error (bool clear, int& err_num);\n\nprotected:\n\n  int mode () const { return m_mode; }\n\n  mach_info::float_format float_format () const { return m_flt_fmt; }\n\n  std::string encoding () const { return m_encoding; }\n\n  // Set current error state and set fail to TRUE.\n\n  OCTINTERP_API void error (const std::string& msg);\n  OCTINTERP_API void error (const std::string& who, const std::string& msg);\n\n  // Clear any error message and set fail to FALSE.\n\n  OCTINTERP_API void clear ();\n\n  // Clear stream state.\n\n  OCTINTERP_API void clearerr ();\n\nprivate:\n\n  // The permission bits for the file.  Should be some combination of\n  // std::ios::open_mode bits.\n  int m_mode;\n\n  // Data format.\n  mach_info::float_format m_flt_fmt;\n\n  // Code page\n  std::string m_encoding;\n\n  // encoding conversion facet\n  wbuffer_u8_converter *m_converter;\n\n  // wrappers for encoding conversion\n  // std::unique_ptr<std::istream> m_conv_istream;\n\n  std::unique_ptr<std::ostream> m_conv_ostream;\n\n  // TRUE if an error has occurred.\n  bool m_fail;\n\n  // TRUE if this stream is open.\n  bool m_open_state;\n\n  // Should contain error message if fail is TRUE.\n  std::string m_errmsg;\n\n  OCTINTERP_API std::ostream * create_converter_stream ();\n\n  // Functions that are defined for all input streams (input streams\n  // are those that define is).\n\n  OCTINTERP_API std::string\n  do_gets (octave_idx_type max_len, bool& err, bool strip_newline,\n           const std::string& who /* = \"gets\" */);\n\n  OCTINTERP_API std::string\n  getl (octave_idx_type max_len, bool& err,\n        const std::string& who /* = \"getl\" */);\n  OCTINTERP_API std::string\n  gets (octave_idx_type max_len, bool& err,\n        const std::string& who /* = \"gets\" */);\n  OCTINTERP_API off_t\n  skipl (off_t count, bool& err, const std::string& who /* = \"skipl\" */);\n\n  OCTINTERP_API octave_value\n  do_scanf (scanf_format_list& fmt_list, octave_idx_type nr,\n            octave_idx_type nc, bool one_elt_size_spec,\n            octave_idx_type& count, const std::string& who /* = \"scanf\" */);\n\n  OCTINTERP_API octave_value\n  scanf (const std::string& fmt, const Array<double>& size,\n         octave_idx_type& count, const std::string& who /* = \"scanf\" */);\n\n  OCTINTERP_API bool\n  do_oscanf (const scanf_format_elt *elt, octave_value&,\n             const std::string& who /* = \"scanf\" */);\n\n  OCTINTERP_API octave_value_list\n  oscanf (const std::string& fmt, const std::string& who /* = \"scanf\" */);\n\n  OCTINTERP_API octave_value\n  do_textscan (const std::string& fmt, octave_idx_type ntimes,\n               const octave_value_list& options,\n               const std::string& who, octave_idx_type& count);\n\n  // Functions that are defined for all output streams (output streams\n  // are those that define os).\n\n  OCTINTERP_API int flush ();\n\n  OCTINTERP_API int\n  do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt,\n                          int nsa, int sa_1, int sa_2,\n                          const octave_value& val,\n                          const std::string& who);\n\n  OCTINTERP_API void field_width_error (const std::string& who) const;\n\n  OCTINTERP_API int\n  do_printf (printf_format_list& fmt_list, const octave_value_list& args,\n             const std::string& who /* = \"printf\" */);\n\n  OCTINTERP_API int\n  printf (const std::string& fmt, const octave_value_list& args,\n          const std::string& who /* = \"printf\" */);\n\n  OCTINTERP_API int\n  puts (const std::string& s, const std::string& who /* = \"puts\" */);\n\n  // We can always do this in terms of seek(), so the derived class\n  // only has to provide that.\n\n  OCTINTERP_API void\n  invalid_operation (const std::string& who, const char *rw);\n};\n\nclass OCTINTERP_API stream\n{\npublic:\n\n  // BS must be allocated with new or nullptr.\n  stream (base_stream *bs = nullptr) : m_rep (bs) { }\n\n  stream (const stream&) = default;\n\n  stream& operator = (const stream&) = default;\n\n  ~stream () = default;\n\n  OCTINTERP_API int flush ();\n\n  OCTINTERP_API std::string\n  getl (octave_idx_type max_len, bool& err,\n        const std::string& who /* = \"getl\" */);\n\n  OCTINTERP_API std::string\n  getl (const octave_value& max_len, bool& err,\n        const std::string& who /* = \"getl\" */);\n\n  OCTINTERP_API std::string\n  gets (octave_idx_type max_len, bool& err,\n        const std::string& who /* = \"gets\" */);\n\n  OCTINTERP_API std::string\n  gets (const octave_value& max_len, bool& err,\n        const std::string& who /* = \"gets\" */);\n\n  OCTINTERP_API off_t\n  skipl (off_t count, bool& err, const std::string& who /* = \"skipl\" */);\n\n  OCTINTERP_API off_t\n  skipl (const octave_value& count, bool& err,\n         const std::string& who /* = \"skipl\" */);\n\n  OCTINTERP_API int seek (off_t offset, int origin);\n\n  OCTINTERP_API int\n  seek (const octave_value& offset, const octave_value& origin);\n\n  OCTINTERP_API off_t tell ();\n\n  OCTINTERP_API int rewind ();\n\n  OCTINTERP_API bool is_open () const;\n\n  OCTINTERP_API void close ();\n\n  OCTINTERP_API octave_value\n  read (const Array<double>& size, octave_idx_type block_size,\n        oct_data_conv::data_type input_type,\n        oct_data_conv::data_type output_type,\n        octave_idx_type skip, mach_info::float_format flt_fmt,\n        octave_idx_type& count);\n\n  OCTINTERP_API octave_idx_type\n  write (const octave_value& data, octave_idx_type block_size,\n         oct_data_conv::data_type output_type,\n         octave_idx_type skip, mach_info::float_format flt_fmt);\n\n  OCTINTERP_API bool write_bytes (const void *data, std::size_t n_elts);\n\n  OCTINTERP_API bool skip_bytes (std::size_t n_elts);\n\n  template <typename T>\n  OCTINTERP_API octave_idx_type\n  write (const Array<T>& data, octave_idx_type block_size,\n         oct_data_conv::data_type output_type,\n         octave_idx_type skip, mach_info::float_format flt_fmt);\n\n  OCTINTERP_API octave_value\n  scanf (const std::string& fmt, const Array<double>& size,\n         octave_idx_type& count, const std::string& who /* = \"scanf\" */);\n\n  OCTINTERP_API octave_value\n  scanf (const octave_value& fmt, const Array<double>& size,\n         octave_idx_type& count, const std::string& who /* = \"scanf\" */);\n\n  OCTINTERP_API octave_value_list\n  oscanf (const std::string& fmt, const std::string& who /* = \"scanf\" */);\n\n  OCTINTERP_API octave_value_list\n  oscanf (const octave_value& fmt, const std::string& who /* = \"scanf\" */);\n\n  OCTINTERP_API octave_value\n  textscan (const std::string& fmt, octave_idx_type ntimes,\n            const octave_value_list& options,\n            const std::string& who, octave_idx_type& count);\n\n  OCTINTERP_API int\n  printf (const std::string& fmt, const octave_value_list& args,\n          const std::string& who /* = \"printf\" */);\n\n  OCTINTERP_API int\n  printf (const octave_value& fmt, const octave_value_list& args,\n          const std::string& who /* = \"printf\" */);\n\n  OCTINTERP_API int\n  puts (const std::string& s, const std::string& who /* = \"puts\" */);\n  OCTINTERP_API int\n  puts (const octave_value& s, const std::string& who /* = \"puts\" */);\n\n  OCTINTERP_API bool eof () const;\n\n  OCTINTERP_API std::string error (bool clear, int& err_num);\n\n  std::string error (bool clear = false)\n  {\n    int err_num;\n    return error (clear, err_num);\n  }\n\n  // Set the error message and state.\n\n  void error (const std::string& msg)\n  {\n    if (m_rep)\n      m_rep->error (msg);\n  }\n\n  void error (const char *msg) { error (std::string (msg)); }\n\n  int file_number () { return m_rep ? m_rep->file_number () : -1; }\n\n  bool is_valid () const { return bool (m_rep); }\n\n  bool ok () const { return m_rep && m_rep->ok (); }\n\n  operator bool () const { return ok (); }\n\n  OCTINTERP_API std::string name () const;\n\n  OCTINTERP_API int mode () const;\n\n  OCTINTERP_API mach_info::float_format float_format () const;\n\n  OCTINTERP_API static std::string mode_as_string (int mode);\n\n  std::string encoding ()\n  {\n    return m_rep ? m_rep->encoding () : std::string ();\n  }\n\n  std::istream * input_stream ()\n  {\n    return m_rep ? m_rep->input_stream () : nullptr;\n  }\n\n  std::ostream * output_stream ()\n  {\n    return (m_rep ? m_rep->output_stream () : nullptr);\n  }\n\n  std::ostream * preferred_output_stream ()\n  {\n    // return output stream with encoding facet if applicable\n    return (m_rep ? m_rep->preferred_output_stream () : nullptr);\n  }\n\n  void clearerr () { if (m_rep) m_rep->clearerr (); }\n\nprivate:\n\n  // The actual representation of this stream.\n  std::shared_ptr<base_stream> m_rep;\n\n  bool stream_ok (bool clear = true) const\n  {\n    bool retval = true;\n\n    if (m_rep)\n      {\n        if (clear)\n          m_rep->clear ();\n      }\n    else\n      retval = false;\n\n    return retval;\n  }\n\n  void invalid_operation (const std::string& who, const char *rw)\n  {\n    if (m_rep)\n      m_rep->invalid_operation (who, rw);\n  }\n\n  OCTINTERP_API octave_value\n  finalize_read (std::list<void *>& input_buf_list,\n                 octave_idx_type input_buf_elts,\n                 octave_idx_type elts_read,\n                 octave_idx_type nr, octave_idx_type nc,\n                 oct_data_conv::data_type input_type,\n                 oct_data_conv::data_type output_type,\n                 mach_info::float_format ffmt);\n};\n\nclass OCTINTERP_API stream_list\n{\npublic:\n\n  OCTINTERP_API stream_list (interpreter& interp);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (stream_list)\n\n  OCTINTERP_API ~stream_list ();\n\n  OCTINTERP_API int insert (stream& os);\n\n  OCTINTERP_API stream lookup (int fid, const std::string& who = \"\") const;\n  OCTINTERP_API stream\n  lookup (const octave_value& fid, const std::string& who = \"\") const;\n\n  OCTINTERP_API int remove (int fid, const std::string& who = \"\");\n  OCTINTERP_API int remove (const octave_value& fid,\n                            const std::string& who = \"\");\n\n  OCTINTERP_API void clear (bool flush = true);\n\n  OCTINTERP_API string_vector get_info (int fid) const;\n  OCTINTERP_API string_vector get_info (const octave_value& fid) const;\n\n  OCTINTERP_API std::string list_open_files () const;\n\n  OCTINTERP_API octave_value open_file_numbers () const;\n\n  OCTINTERP_API int get_file_number (const octave_value& fid) const;\n\n  OCTINTERP_API octave_value stdin_file () const;\n  OCTINTERP_API octave_value stdout_file () const;\n  OCTINTERP_API octave_value stderr_file () const;\n\nprivate:\n\n  typedef std::map<int, stream> ostrl_map;\n\n  ostrl_map m_list;\n\n  mutable ostrl_map::const_iterator m_lookup_cache;\n\n  int m_stdin_file;\n  int m_stdout_file;\n  int m_stderr_file;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-strstrm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-strstrm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Position a stream at OFFSET relative to ORIGIN.\n\nint\nbase_strstream::seek (off_t, int)\n{\n  // Note: error is inherited from base_stream, not ::error.\n  // This error function does not halt execution so \"return ...\" must exist.\n  error (\"fseek: invalid operation\");\n  return -1;\n}\n\n// Return current stream position.\n\noff_t\nbase_strstream::tell ()\n{\n  // Note: error is inherited from base_stream, not ::error.\n  // This error function does not halt execution so \"return ...\" must exist.\n  error (\"ftell: invalid operation\");\n  return -1;\n}\n\nstream\nistrstream::create (const char *data, std::ios::openmode arg_md,\n                    mach_info::float_format flt_fmt,\n                    const std::string& encoding)\n{\n  return stream (new istrstream (data, arg_md, flt_fmt, encoding));\n}\n\nstream\nistrstream::create (const std::string& data, std::ios::openmode arg_md,\n                    mach_info::float_format flt_fmt,\n                    const std::string& encoding)\n{\n  return stream (new istrstream (data, arg_md, flt_fmt, encoding));\n}\n\nstream\nostrstream::create (std::ios::openmode arg_md,\n                    mach_info::float_format flt_fmt,\n                    const std::string& encoding)\n{\n  return stream (new ostrstream (arg_md, flt_fmt, encoding));\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-strstrm.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_strstrm_h)\n#define octave_oct_strstrm_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n#include <sstream>\n\n#include \"oct-stream.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_strstream : public base_stream\n{\npublic:\n\n  base_strstream (std::ios::openmode m = std::ios::out,\n                  mach_info::float_format ff\n                  = mach_info::native_float_format (),\n                  const std::string& encoding = \"utf-8\")\n    : base_stream (m, ff, encoding) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (base_strstream)\n\nprotected:\n\n  ~base_strstream () = default;\n\npublic:\n\n  // Position a stream at OFFSET relative to ORIGIN.\n\n  int seek (off_t, int);\n\n  // Return current stream position.\n\n  virtual off_t tell ();\n\n  // The name of the file.\n\n  std::string name () const { return \"\"; }\n\n  virtual std::streambuf * rdbuf () = 0;\n\n  virtual bool bad () const = 0;\n\n  virtual void clear () = 0;\n};\n\nclass istrstream : public base_strstream\n{\npublic:\n\n  istrstream (const char *data,\n              std::ios::openmode arg_md = std::ios::out,\n              mach_info::float_format ff = mach_info::native_float_format (),\n              const std::string& encoding = \"utf-8\")\n    : base_strstream (arg_md, ff, encoding), m_istream (data) { }\n\n  istrstream (const std::string& data,\n              std::ios::openmode arg_md = std::ios::out,\n              mach_info::float_format ff = mach_info::native_float_format (),\n              const std::string& encoding = \"utf-8\")\n    : base_strstream (arg_md, ff, encoding), m_istream (data) { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (istrstream)\n\nprotected:\n\n  ~istrstream () = default;\n\npublic:\n\n\n  static stream\n  create (const char *data, std::ios::openmode arg_md = std::ios::out,\n          mach_info::float_format ff = mach_info::native_float_format (),\n          const std::string& encoding = \"utf-8\");\n\n  static stream\n  create (const std::string& data, std::ios::openmode arg_md = std::ios::out,\n          mach_info::float_format ff = mach_info::native_float_format (),\n          const std::string& encoding = \"utf-8\");\n\n  // Return nonzero if EOF has been reached on this stream.\n\n  bool eof () const { return m_istream.eof (); }\n\n  std::istream * input_stream () { return &m_istream; }\n\n  std::ostream * output_stream () { return nullptr; }\n\n  off_t tell () { return m_istream.tellg (); }\n\n  std::streambuf * rdbuf ()\n  {\n    return m_istream ? m_istream.rdbuf () : nullptr;\n  }\n\n  bool bad () const { return m_istream.bad (); }\n\n  void clear () { m_istream.clear (); }\n\nprivate:\n\n  std::istringstream m_istream;\n};\n\nclass ostrstream : public base_strstream\n{\npublic:\n\n  ostrstream (std::ios::openmode arg_md = std::ios::out,\n              mach_info::float_format ff = mach_info::native_float_format (),\n              const std::string& encoding = \"utf-8\")\n    : base_strstream (arg_md, ff, encoding), m_ostream () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (ostrstream)\n\nprotected:\n\n  ~ostrstream () = default;\n\npublic:\n\n  static stream\n  create (std::ios::openmode arg_md = std::ios::out,\n          mach_info::float_format ff = mach_info::native_float_format (),\n          const std::string& encoding = \"utf-8\");\n\n  // Return nonzero if EOF has been reached on this stream.\n\n  bool eof () const { return m_ostream.eof (); }\n\n  std::istream * input_stream () { return nullptr; }\n\n  std::ostream * output_stream () { return &m_ostream; }\n\n  std::string str () { return m_ostream.str (); }\n\n  std::streambuf * rdbuf ()\n  {\n    return m_ostream ? m_ostream.rdbuf () : nullptr;\n  }\n\n  bool bad () const { return m_ostream.bad (); }\n\n  void clear () { m_ostream.clear (); }\n\nprivate:\n\n  std::ostringstream m_ostream;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/oct-tex-lexer.in.ll",
    "content": "%top {\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// #define OCTAVE_TEX_DEBUG 1\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // This one needs to be global.\n#  pragma GCC diagnostic ignored \"-Wunused-function\"\n\n   // Disable these warnings for code that is generated by flex, including\n   // pattern rules.  Push the current state so we can restore the warning\n   // state prior to functions we define at the bottom of the file.\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#  pragma GCC diagnostic ignored \"-Wsign-compare\"\n#  pragma GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"\n#endif\n\n// Define away the deprecated register storage class specifier to avoid\n// potential warnings about it.\n#if ! defined (register)\n#  define register\n#endif\n\n}\n\n%option prefix = \"octave_tex_\"\n%option noyywrap\n%option reentrant\n%option bison-bridge\n\n%option noyyalloc\n%option noyyrealloc\n%option noyyfree\n\n%x NUM_MODE\n%x MAYBE_NUM_MODE\n\n%{\n\n#include \"unistd-wrappers.h\"\n\n#include \"text-engine.h\"\n// oct-tex-parser.h must be included after text-engine.h\n#include \"oct-tex-parser.h\"\n\n// FIXME: with bison 3.x, OCTAVE_TEX_STYPE appears in the generated\n// oct-parse.h file, but there is no definition for YYSTYPE, which is\n// needed by the code that is generated by flex.  I can't seem to find\n// a way to tell flex to use OCTAVE_TEX_STYPE instead of YYSTYPE in\n// the code it generates, or to tell bison to provide the definition\n// of YYSTYPE in the generated oct-parse.h file.\n\n#if defined (OCTAVE_TEX_STYPE_IS_DECLARED) && ! defined YYSTYPE\n#  define YYSTYPE OCTAVE_TEX_STYPE\n#endif\n\n#define YY_NO_UNISTD_H 1\n#define isatty octave_isatty_wrapper\n#define yyguts_t octave_tex_yyguts_t\n\n%}\n\nD   [0-9]\nNUM (({D}+\\.?{D}*)|(\\.{D}+))\n\n%%\n\n%{\n// Numeric values.\n%}\n\n<NUM_MODE>{NUM} {\n    int nread = sscanf (yytext, \"%lf\", &(yylval->num));\n\n    if (nread == 1)\n      return NUM;\n  }\n\n<NUM_MODE>[, \\t]+ { }\n\n<NUM_MODE>\"\\n\"|. {\n    yyless (0);\n    BEGIN (INITIAL);\n  }\n\n<MAYBE_NUM_MODE>\"{\" {\n    BEGIN (NUM_MODE);\n    return START;\n  }\n\n<MAYBE_NUM_MODE>\"\\n\"|. {\n    yyless (0);\n    BEGIN (INITIAL);\n  }\n\n%{\n// Simple commands.\n%}\n\n\"\\\\bf\" { return BF; }\n\"\\\\it\" { return IT; }\n\"\\\\sl\" { return SL; }\n\"\\\\rm\" { return RM; }\n\n%{\n// Generic font commands.\n%}\n\n\"\\\\fontname\" { return FONTNAME; }\n\n\"\\\\fontsize\" {\n    BEGIN (MAYBE_NUM_MODE);\n    return FONTSIZE;\n  }\n\n\"\\\\color[rgb]\" {\n    BEGIN (MAYBE_NUM_MODE);\n    return COLOR_RGB;\n  }\n\n\"\\\\color\" { return COLOR; }\n\n%{\n// Special characters.\n%}\n\n\"{\" { return START; }\n\"}\" { return END; }\n\"^\" { return SUPER; }\n\"_\" { return SUB; }\n\n\"\\\\{\"  |\n\"\\\\}\"  |\n\"\\\\^\"  |\n\"\\\\_\"  |\n\"\\\\\\\\\" {\n    yylval->ch = yytext[1];\n    return CH;\n  }\n\n%{\n// Symbols.\n%}\n\n@SYMBOL_RULES@\n\n%{\n// Generic character.\n%}\n\n\"\\n\" |\n.    {\n    yylval->ch = yytext[0];\n    return CH;\n  }\n\n%{\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // Also disable this warning for functions that are generated by flex\n   // after the pattern rules.\n#  pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#endif\n%}\n\n%%\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // Restore prevailing warning state for remainder of the file.\n#  pragma GCC diagnostic pop\n#endif\n\nvoid *\noctave_tex_alloc (yy_size_t size, yyscan_t)\n{\n  return malloc (size);\n}\n\nvoid *\noctave_tex_realloc (void *ptr, yy_size_t size, yyscan_t)\n{\nreturn realloc (ptr, size);\n}\n\nvoid\noctave_tex_free (void *ptr, yyscan_t)\n{\n  free (ptr);\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nbool text_parser_tex::init_lexer (const std::string& s)\n{\n  if (! m_scanner)\n    octave_tex_lex_init (&m_scanner);\n\n  if (m_scanner)\n    {\n      if (m_buffer_state)\n        {\n          octave_tex__delete_buffer (reinterpret_cast<YY_BUFFER_STATE> (m_buffer_state),\n                                     m_scanner);\n          m_buffer_state = nullptr;\n        }\n\n      m_buffer_state = octave_tex__scan_bytes (s.data (), s.length (),\n                                               m_scanner);\n    }\n\n  return (m_scanner && m_buffer_state);\n}\n\nvoid text_parser_tex::destroy_lexer ()\n{\n  if (m_buffer_state)\n    {\n      octave_tex__delete_buffer (reinterpret_cast<YY_BUFFER_STATE> (m_buffer_state),\n                                 m_scanner);\n      m_buffer_state = nullptr;\n    }\n\n  if (m_scanner)\n    {\n      octave_tex_lex_destroy (m_scanner);\n      m_scanner = nullptr;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/oct-tex-parser.yy",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n%{\n\n// #define OCTAVE_TEX_DEBUG 1\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"text-engine.h\"\n// oct-tex-parser.h must be included after text-engine.h\n#include \"oct-tex-parser.h\"\n\nextern int octave_tex_lex (YYSTYPE *, void *);\nstatic void yyerror (octave::text_parser_tex& parser, const char *s);\n\n#define m_scanner parser.get_scanner ()\n#define yyalloc octave_tex_yyalloc\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // Disable this warning for code that is generated by Bison, including\n   // grammar rules.  Push the current state so we can restore the warning\n   // state prior to functions we define at the bottom of the file.\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n%}\n\n%define api.pure\n// No spaces inside the braces for the prefix definition!\n%define api.prefix {octave_tex_}\n%define api.push-pull both\n%parse-param { octave::text_parser_tex& parser }\n%lex-param { void *m_scanner }\n\n%code requires {#include <string>}\n\n%union\n{\n  // Leaf symbols produced by the scanner.\n  char ch;\n  double num;\n  int sym;\n\n  // Used for string buffering.\n  std::string *str;\n\n  // Objects produced by the parser.\n  octave::text_element *e_base;\n  octave::text_element_list *e_list;\n}\n\n%token BF IT SL RM\n%token FONTNAME FONTSIZE\n%token COLOR COLOR_RGB\n%token START END SUPER SUB\n%token<ch> CH\n%token<num> NUM\n%token<sym> SYM\n\n%type<str> simple_string\n%type<e_base> string_element symbol_element\n%type<e_base> superscript_element subscript_element combined_script_element\n%type<e_base> font_modifier_element fontname_element fontsize_element\n%type<e_base> color_element\n%type<e_list> string_element_list scoped_string_element_list\n\n// Make sure there's no memory leak on parse error.\n%destructor { } <ch> <num> <sym>\n%destructor { delete $$; } <*>\n\n%nonassoc SCRIPT\n%nonassoc SUB SUPER\n\n%nonassoc STR\n%nonassoc CH\n\n%start string\n\n%%\n\nsimple_string           : CH\n                          { $$ = new std::string (1, $1); }\n                        | simple_string CH\n                          { $1->append (1, $2); $$ = $1; }\n                        ;\n\nsymbol_element          : SYM\n                          { $$ = new octave::text_element_symbol ($1); }\n                        ;\n\nfont_modifier_element   : BF\n                          { $$ = new octave::text_element_fontstyle (octave::text_element_fontstyle::bold); }\n                        | IT\n                          { $$ = new octave::text_element_fontstyle (octave::text_element_fontstyle::italic); }\n                        | SL\n                          { $$ = new octave::text_element_fontstyle (octave::text_element_fontstyle::oblique); }\n                        | RM\n                          { $$ = new octave::text_element_fontstyle (octave::text_element_fontstyle::normal); }\n                        ;\n\nfontsize_element        : FONTSIZE START NUM END\n                          { $$ = new octave::text_element_fontsize ($3); }\n                        ;\n\nfontname_element        : FONTNAME START simple_string END\n                          {\n                            $$ = new octave::text_element_fontname (*$3);\n                            delete $3;\n                          }\n                        ;\n\ncolor_element           : COLOR START simple_string END\n                          {\n                            $$ = new octave::text_element_color (*$3);\n                            delete $3;\n                          }\n                        | COLOR_RGB START NUM NUM NUM END\n                          {\n                            $$ = new octave::text_element_color ($3, $4, $5);\n                          }\n                        ;\n\nstring_element          : simple_string %prec STR\n                          {\n                            $$ = new octave::text_element_string (*$1);\n                            delete $1;\n                          }\n                        | scoped_string_element_list\n                          { $$ = $1; }\n                        | symbol_element\n                        | font_modifier_element\n                        | fontsize_element\n                        | fontname_element\n                        | color_element\n                        | superscript_element %prec SCRIPT\n                        | subscript_element %prec SCRIPT\n                        | combined_script_element\n                        ;\n\nsuperscript_element     : SUPER CH\n                          { $$ = new octave::text_element_superscript ($2); }\n                        | SUPER scoped_string_element_list\n                          { $$ = new octave::text_element_superscript ($2); }\n                        | SUPER symbol_element\n                          { $$ = new octave::text_element_superscript ($2); }\n                        ;\n\nsubscript_element       : SUB CH\n                          { $$ = new octave::text_element_subscript ($2); }\n                        | SUB scoped_string_element_list\n                          { $$ = new octave::text_element_subscript ($2); }\n                        | SUB symbol_element\n                          { $$ = new octave::text_element_subscript ($2); }\n                        ;\n\ncombined_script_element : subscript_element superscript_element\n                          { $$ = new octave::text_element_combined ($1, $2); }\n                        | superscript_element subscript_element\n                          { $$ = new octave::text_element_combined ($1, $2); }\n                        ;\n\nstring_element_list     : string_element\n                          { $$ = new octave::text_element_list ($1); }\n                        | string_element_list string_element\n                          { $1->push_back ($2); $$ = $1; }\n                        ;\n\nscoped_string_element_list\n                        : START string_element_list END\n                          { $$ = $2; }\n                        | START END\n                          { $$ = new octave::text_element_list (); }\n                        ;\n\nstring                  : // empty\n                          { parser.set_parse_result (new octave::text_element_string (\"\")); }\n                        | string_element_list\n                          { parser.set_parse_result ($1); }\n                        ;\n\n%%\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n  // Restore prevailing warning state for remainder of the file.\n  #pragma GCC diagnostic pop\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntext_element *\ntext_parser_tex::parse (const std::string& s)\n{\n#if OCTAVE_TEX_DEBUG\n  octave_tex_debug = 1;\n#endif\n\n  if (init_lexer (s))\n    {\n      m_result = nullptr;\n\n      if (octave_tex_parse (*this) == 0)\n        return m_result;\n    }\n\n  return new text_element_string (s);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\nstatic void\nyyerror (octave::text_parser_tex&, const char *s)\n{\n  fprintf (stderr, \"TeX parse error: %s\\n\", s);\n}\n"
  },
  {
    "path": "libinterp/corefcn/oct-tex-symbols.in",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# List of supported symbols for the TeX interpreter\n# Reference: http://www.mathworks.com/help/matlab/ref/text_props.html\n#\n# Column 1 : symbol name\n# Column 2 : Unicode code\n# Column 3 : MS symbol code (http://www.kostis.net/charsets/symbol.htm)\n#\n# Arranged by listings in The TeXbook, Appendix F:\n# Greek lowercase letters, Greek uppercase, Misc Symbols type Ord,\n# \"Large\" operators, Binary operators, Relations, Negated relations, Arrows,\n# Openings, Closings, Alternate names, and Other (not in Appendix F Tables).\n\nalpha           0x03B1  0xF061\nbeta            0x03B2  0xF062\ngamma           0x03B3  0xF067\ndelta           0x03B4  0xF064\nepsilon         0x03B5  0xF065\nzeta            0x03B6  0xF07A\neta             0x03B7  0xF068\ntheta           0x03B8  0xF071\nvartheta        0x03D1  0xF04A\niota            0x03B9  0xF069\nkappa           0x03BA  0xF06B\nlambda          0x03BB  0xF06C\nmu              0x03BC  0xF06D\nnu              0x03BD  0xF06E\nxi              0x03BE  0xF078\no               0x03BF  0xF0B0\npi              0x03C0  0xF070\nvarpi           0x03D6  0xF076\nrho             0x03C1  0xF072\nsigma           0x03C3  0xF073\nvarsigma        0x03C2  0xF056\ntau             0x03C4  0xF074\nupsilon         0x03C5  0xF075\nphi             0x03C6  0xF066\nchi             0x03C7  0xF063\npsi             0x03C8  0xF079\nomega           0x03C9  0xF077\nGamma           0x0393  0xF047\nDelta           0x0394  0xF044\nTheta           0x0398  0xF051\nLambda          0x039B  0xF04C\nXi              0x039E  0xF058\nPi              0x03A0  0xF050\nSigma           0x03A3  0xF053\nUpsilon         0x03D2  0xF055\nPhi             0x03A6  0xF046\nPsi             0x03A8  0xF059\nOmega           0x03A9  0xF057\naleph           0x2135  0xF0C0\nwp              0x2118  0xF0C3\nRe              0x211C  0xF0C2\nIm              0x2111  0xF0C1\npartial         0x2202  0xF0B6\ninfty           0x221E  0xF0A5\nprime           0x2032  0xF0A2\nnabla           0x2207  0xF0D1\nsurd            0x221A  0xF0D6\nangle           0x2220  0xF0D0\nforall          0x2200  0xF022\nexists          0x2203  0xF024\nneg             0x00AC  0xF0D8\nclubsuit        0x2663  0xF0A7\ndiamondsuit     0x2666  0xF0A8\nheartsuit       0x2665  0xF0A9\nspadesuit       0x2660  0xF0AA\nint             0x222B  0xF0F2\npm              0x00B1  0xF0B1\ncdot            0x22C5  0xF0D7\ntimes           0x00D7  0xF0B4\nast             0x2217  0xF02A\ncirc            0x2218  0xF0B0\nbullet          0x2219  0xF0B7\ndiv             0x00F7  0xF0B8\ncap             0x2229  0xF0C7\ncup             0x222A  0xF0C8\nvee             0x2228  0xF0DA\nwedge           0x2227  0xF0D9\noplus           0x2295  0xF0C5\notimes          0x2297  0xF0C4\noslash          0x2298  0xF0C6\nleq             0x2264  0xF0A3\nsubset          0x2282  0xF0CC\nsubseteq        0x2286  0xF0CD\nin              0x2208  0xF0CE\ngeq             0x2265  0xF0B3\nsupset          0x2283  0xF0C9\nsupseteq        0x2287  0xF0CA\nni              0x220B  0xF027\nmid             0x2223  0xF0BD\nequiv           0x2261  0xF0BA\nsim             0x223C  0xF07E\napprox          0x2248  0xF0BB\ncong            0x2245  0xF040\npropto          0x221D  0xF0B5\nperp            0x22A5  0xF05E\nleftarrow       0x2190  0xF0AC\nLeftarrow       0x21D0  0xF0DC\nrightarrow      0x2192  0xF0AE\nRightarrow      0x21D2  0xF0DE\nleftrightarrow  0x2194  0xF0AB\nuparrow         0x2191  0xF0AD\ndownarrow       0x2193  0xF0AF\nlfloor          0x230A  0xF0EB\nlangle          0x27E8  0xF0E1\nlceil           0x2308  0xF0E9\nrfloor          0x230B  0xF0FB\nrangle          0x27E9  0xF0F1\nrceil           0x2309  0xF0F9\nneq             0x2260  0xF0B9\nldots           0x2026  0xF0BC\n0               0x2205  0xF0C6\ncopyright       0x00A9  0xF0E3\ndeg             0x00B0  0xF0B0\n"
  },
  {
    "path": "libinterp/corefcn/oct.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_h)\n#define octave_oct_h 1\n\n#include \"octave-config.h\"\n\n// Things that are often included to create .oct files.\n\n#include \"Array.h\"\n#include \"Matrix.h\"\n#include \"oct-locbuf.h\"\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"help.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/octave-default-image.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2014-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_octave_default_image_h)\n#define octave_octave_default_image_h 1\n\n#include \"octave-config.h\"\n\nstatic char default_im_data[] =\n{\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 40, 47, 50, 50, 46, 30, 26, 26, 38, 50, 47, 26, 26, 26, 50,\n  46, 26, 50, 46, 26, 26, 26, 50, 46, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 43, 55, 54, 50, 51, 55,\n  51, 26, 26, 40, 55, 55, 41, 26, 26, 55, 50, 26, 55, 50, 26, 26, 26, 55,\n  50, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 30, 54, 52, 30, 26, 26, 46, 55, 43, 26, 40, 55, 55, 52, 30,\n  26, 55, 50, 26, 55, 50, 26, 26, 26, 55, 50, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 43, 55, 44, 26, 26,\n  26, 26, 26, 26, 26, 40, 55, 47, 55, 46, 26, 55, 50, 26, 55, 50, 26, 26,\n  26, 55, 50, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 46, 55, 40, 26, 26, 50, 50, 50, 43, 26, 40, 55, 46,\n  46, 54, 34, 55, 50, 26, 55, 50, 26, 26, 26, 55, 50, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 44, 55, 43,\n  26, 26, 50, 50, 55, 46, 26, 40, 55, 46, 30, 52, 48, 55, 50, 26, 55, 50,\n  26, 26, 26, 55, 50, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 38, 55, 50, 26, 26, 26, 40, 55, 46, 26, 40,\n  55, 46, 26, 43, 55, 55, 50, 26, 55, 50, 26, 26, 26, 55, 50, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  48, 55, 48, 40, 43, 54, 55, 46, 26, 40, 55, 46, 26, 26, 50, 55, 50, 26,\n  52, 55, 43, 40, 47, 55, 46, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 30, 48, 55, 55, 55, 47, 48, 46,\n  26, 40, 55, 46, 26, 26, 38, 55, 50, 26, 38, 52, 55, 55, 55, 50, 30, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 34, 40, 38, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 38, 40, 34, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 62, 62, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  59, 62, 62, 59, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 59, 55, 59, 59, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 59, 55, 55, 53, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 53, 52, 55, 55, 52, 52, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 53, 48, 55, 48, 52, 52, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 45, 48, 55, 48, 52,\n  53, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 44, 48, 48, 48, 52, 45, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 44, 44, 48, 44,\n  48, 44, 45, 52, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 45, 44, 41, 44, 48, 41, 45, 44, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 45, 44,\n  37, 44, 37, 41, 45, 44, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 37, 41, 37, 44, 37, 41, 36, 36, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 44,\n  36, 32, 37, 44, 37, 41, 36, 36, 41, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 36, 36, 32, 37, 37, 37, 32, 36, 37,\n  41, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 20,\n  20, 36, 36, 32, 37, 37, 37, 32, 36, 37, 32, 18, 20, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 20, 18, 18, 16, 17, 17, 27, 36, 32, 37, 31, 37, 32,\n  36, 37, 32, 17, 17, 18, 18, 18, 20, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 20, 18, 18, 18, 16, 16,\n  16, 15, 15, 27, 26, 28, 31, 31, 28, 32, 36, 27, 36, 15, 16, 17, 16, 17,\n  17, 18, 18, 20, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 18, 20, 17, 17, 16, 16, 16, 16, 15, 15, 32, 27, 24, 28, 24, 31,\n  28, 28, 24, 27, 26, 24, 16, 15, 16, 17, 16, 16, 18, 18, 20, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 20, 20, 18, 18, 17, 17, 16,\n  16, 14, 14, 15, 24, 27, 24, 28, 24, 31, 28, 28, 24, 27, 26, 28, 12, 14,\n  15, 15, 16, 16, 16, 16, 18, 18, 20, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 20, 18, 18, 18, 17, 16, 15, 14, 14, 14, 14, 12, 26, 26, 24, 22,\n  24, 24, 28, 22, 24, 26, 26, 22, 12, 12, 12, 12, 14, 14, 16, 16, 16, 18,\n  18, 20, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 20, 20, 18, 18, 17, 16, 12,\n  15, 12, 10, 10, 10, 12, 26, 18, 24, 22, 24, 24, 24, 22, 24, 26, 26, 22,\n  10, 10, 12, 12, 10, 14, 14, 15, 17, 18, 18, 20, 20, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 17, 20, 20, 20, 17, 16, 15, 14, 12, 12, 10, 10, 10, 18, 18, 18,\n  16, 17, 24, 24, 24, 22, 16, 18, 18, 24, 18, 6, 9, 10, 10, 14, 14, 15,\n  16, 18, 20, 18, 20, 18, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 16, 18, 20, 20, 18, 17, 16,\n  15, 10, 10, 7, 6, 6, 6, 15, 18, 18, 15, 17, 18, 24, 17, 22, 16, 18,\n  18, 24, 24, 6, 7, 6, 10, 10, 10, 12, 16, 17, 18, 20, 20, 18, 16, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 12, 15, 17, 18, 18, 20, 18, 16, 15, 10, 10, 7, 6, 6, 6, 16,\n  18, 16, 15, 17, 18, 18, 17, 22, 16, 18, 18, 16, 17, 5, 4, 6, 6, 10,\n  7, 14, 15, 17, 20, 20, 20, 18, 17, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 9, 10, 16, 17, 18, 18, 18,\n  18, 15, 10, 10, 6, 5, 4, 4, 4, 10, 12, 16, 15, 17, 12, 18, 17, 12,\n  15, 18, 18, 18, 12, 4, 4, 4, 6, 6, 9, 12, 15, 18, 20, 18, 18, 17,\n  16, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 9, 9, 12, 15, 16, 17, 18, 18, 20, 15, 10, 10, 4, 5, 4, 4,\n  12, 12, 12, 10, 15, 17, 12, 18, 17, 12, 15, 10, 12, 18, 15, 3, 1, 4,\n  4, 4, 5, 10, 16, 20, 18, 18, 17, 17, 16, 12, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 7, 7, 9, 9, 12, 15, 26, 26,\n  26, 18, 18, 18, 20, 5, 4, 4, 3, 1, 6, 12, 12, 10, 12, 7, 12, 12,\n  12, 12, 9, 10, 12, 12, 9, 12, 1, 1, 4, 4, 6, 20, 18, 18, 18, 17,\n  16, 16, 15, 12, 10, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 18, 18, 18, 4, 1,\n  1, 1, 9, 12, 12, 9, 12, 7, 9, 12, 12, 12, 9, 10, 12, 12, 9, 12,\n  1, 1, 3, 4, 18, 18, 18, 18, 17, 16, 16, 16, 14, 10, 9, 9, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 18, 18, 18, 18, 18, 4, 10, 5, 5, 9, 6, 7,\n  9, 7, 12, 6, 9, 10, 5, 5, 10, 6, 5, 18, 18, 18, 18, 18, 26, 26,\n  26, 26, 16, 15, 12, 10, 9, 9, 9, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 14,\n  17, 17, 16, 18, 18, 20, 18, 20, 6, 7, 9, 9, 7, 6, 9, 5, 20, 18,\n  18, 18, 18, 18, 18, 15, 14, 26, 26, 26, 26, 26, 26, 26, 12, 10, 9, 9,\n  7, 7, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 10, 16, 16, 16, 16, 17, 18, 17,\n  18, 17, 17, 18, 18, 17, 18, 17, 17, 17, 17, 17, 14, 14, 14, 12, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 1, 10, 15, 16, 15, 16, 15, 15, 16, 15, 16, 15, 16, 16, 16, 15,\n  16, 16, 17, 14, 14, 10, 12, 1, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 1, 10, 15, 15, 14,\n  15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 12, 12, 10, 10, 10, 1, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 6, 12, 12, 12, 12, 15, 12, 12, 12, 12, 12, 12,\n  12, 15, 10, 9, 7, 6, 6, 1, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  12, 12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 7, 10, 7, 6, 1, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 10, 10, 12, 10, 10, 10, 10,\n  12, 10, 1, 1, 1, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 10, 9, 9, 9, 9, 9, 9, 10, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 9, 9, 9, 9,\n  9, 9, 9, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 7, 7, 7, 7, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 40, 48, 50, 50, 44, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 43, 55, 54, 50, 52, 55,\n  48, 26, 26, 26, 26, 26, 26, 26, 26, 26, 55, 50, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 30, 54, 52, 30, 26, 26, 47, 55, 43, 26, 30, 44, 46, 43, 26,\n  26, 38, 55, 51, 34, 26, 34, 46, 46, 43, 26, 43, 46, 26, 26, 40, 46, 34,\n  26, 30, 44, 46, 40, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 43, 55, 44, 26, 26,\n  26, 34, 55, 48, 30, 51, 55, 50, 55, 48, 26, 46, 55, 54, 43, 34, 55, 54,\n  51, 55, 46, 46, 55, 38, 26, 47, 55, 30, 30, 54, 54, 51, 55, 46, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 46, 55, 40, 26, 26, 26, 26, 55, 50, 43, 55, 43, 26,\n  46, 55, 34, 26, 55, 50, 26, 43, 50, 34, 26, 51, 50, 34, 55, 46, 26, 52,\n  48, 26, 46, 55, 34, 26, 48, 55, 30, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 46, 55, 41,\n  26, 26, 26, 26, 55, 50, 46, 55, 30, 26, 26, 26, 26, 26, 55, 50, 26, 26,\n  44, 50, 54, 55, 50, 26, 51, 51, 38, 55, 43, 26, 50, 55, 50, 50, 52, 55,\n  40, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 38, 55, 48, 26, 26, 26, 43, 55, 46, 46, 55,\n  34, 26, 34, 40, 30, 26, 55, 50, 26, 46, 55, 44, 38, 50, 50, 26, 44, 55,\n  46, 55, 30, 26, 50, 55, 40, 40, 40, 40, 30, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  50, 55, 47, 40, 43, 54, 54, 34, 41, 55, 47, 30, 48, 55, 30, 26, 55, 50,\n  26, 48, 55, 38, 40, 55, 50, 26, 34, 55, 55, 48, 26, 26, 44, 55, 41, 26,\n  46, 48, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 30, 50, 55, 55, 55, 52, 38, 26,\n  26, 47, 55, 55, 55, 43, 26, 26, 52, 55, 46, 41, 55, 55, 52, 52, 54, 30,\n  26, 50, 55, 43, 26, 26, 30, 50, 55, 55, 54, 43, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 34, 40, 40, 26, 26, 26, 26, 26, 38, 40, 34, 26, 26, 26,\n  30, 40, 34, 26, 34, 40, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  38, 40, 30, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n  26, 26, 26, 26, 26, 26, 26, 26, 26, 26\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/pager.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <fstream>\n#include <iostream>\n#include <string>\n\n#include \"child-list.h\"\n#include \"cmd-edit.h\"\n#include \"oct-env.h\"\n#include \"oct-syscalls.h\"\n\n#include \"defaults.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"input.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"octave.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"procstream.h\"\n#include \"sighandlers.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic bool\npager_event_handler (pid_t pid, int status)\n{\n  bool retval = false;\n\n  if (pid > 0)\n    {\n      if (sys::wifexited (status) || sys::wifsignaled (status))\n        {\n          // Avoid warning() since that will put us back in the pager,\n          // which would be bad news.\n\n          std::cerr << \"warning: connection to external pager lost (pid = \"\n                    << pid << ')' << std::endl;\n          std::cerr << \"warning: flushing pending output (please wait)\"\n                    << std::endl;\n\n          // Request removal of this PID from the list of child\n          // processes.\n\n          retval = true;\n        }\n    }\n\n  return retval;\n}\n\n// Assume our terminal wraps long lines.\n\nstatic bool\nmore_than_a_screenful (const char *s, int len)\n{\n  if (s)\n    {\n      int available_rows = command_editor::terminal_rows () - 2;\n\n      int cols = command_editor::terminal_cols ();\n\n      int count = 0;\n\n      int chars_this_line = 0;\n\n      for (int i = 0; i < len; i++)\n        {\n          if (*s++ == '\\n')\n            {\n              count += chars_this_line / cols + 1;\n              chars_this_line = 0;\n            }\n          else\n            chars_this_line++;\n        }\n\n      if (count > available_rows)\n        return true;\n    }\n\n  return false;\n}\n\nstatic std::string\ndefault_pager ()\n{\n  std::string pager_binary = sys::env::getenv (\"PAGER\");\n\n  if (pager_binary.empty ())\n    pager_binary = config::default_pager ();\n\n  return pager_binary;\n}\n\nint\npager_buf::sync ()\n{\n  output_system& output_sys = __get_output_system__ ();\n\n  char *buf = pbase ();\n\n  int len = pptr () - buf;\n\n  if (output_sys.sync (buf, len))\n    {\n      flush_current_contents_to_diary ();\n\n      seekoff (0, std::ios::beg);\n    }\n\n  return 0;\n}\n\nvoid\npager_buf::flush_current_contents_to_diary ()\n{\n  char *buf = pbase () + m_diary_skip;\n\n  std::size_t len = pptr () - buf;\n\n  octave_diary.write (buf, len);\n\n  m_diary_skip = 0;\n}\n\nvoid\npager_buf::set_diary_skip ()\n{\n  m_diary_skip = pptr () - pbase ();\n}\n\nint\ndiary_buf::sync ()\n{\n  output_system& output_sys = __get_output_system__ ();\n\n  std::ofstream& external_diary_file = output_sys.external_diary_file ();\n\n  if (output_sys.write_to_diary_file () && external_diary_file)\n    {\n      char *buf = pbase ();\n\n      int len = pptr () - buf;\n\n      if (len > 0)\n        external_diary_file.write (buf, len);\n    }\n\n  seekoff (0, std::ios::beg);\n\n  return 0;\n}\n\npager_stream::pager_stream () : std::ostream (nullptr), m_pb (nullptr)\n{\n  m_pb = new pager_buf ();\n  rdbuf (m_pb);\n  setf (unitbuf);\n}\n\npager_stream::~pager_stream ()\n{\n  flush ();\n  delete m_pb;\n}\n\nstd::ostream&\npager_stream::stream ()\n{\n  return *this;\n}\n\nvoid\npager_stream::flush_current_contents_to_diary ()\n{\n  if (m_pb)\n    m_pb->flush_current_contents_to_diary ();\n}\n\nvoid\npager_stream::set_diary_skip ()\n{\n  if (m_pb)\n    m_pb->set_diary_skip ();\n}\n\n// Reinitialize the pager buffer to avoid hanging on to large internal\n// buffers when they might not be needed.  This function should only be\n// called when the pager is not in use.  For example, just before\n// getting command-line input.\n\nvoid\npager_stream::reset ()\n{\n  delete m_pb;\n  m_pb = new pager_buf ();\n  rdbuf (m_pb);\n  setf (unitbuf);\n}\n\ndiary_stream::diary_stream () : std::ostream (nullptr), m_db (nullptr)\n{\n  m_db = new diary_buf ();\n  rdbuf (m_db);\n  setf (unitbuf);\n}\n\ndiary_stream::~diary_stream ()\n{\n  flush ();\n  delete m_db;\n}\n\nstd::ostream&\ndiary_stream::stream ()\n{\n  return *this;\n}\n\n// Reinitialize the diary buffer to avoid hanging on to large internal\n// buffers when they might not be needed.  This function should only be\n// called when the pager is not in use.  For example, just before\n// getting command-line input.\n\nvoid\ndiary_stream::reset ()\n{\n  delete m_db;\n  m_db = new diary_buf ();\n  rdbuf (m_db);\n  setf (unitbuf);\n}\n\nvoid\nflush_stdout ()\n{\n  output_system& output_sys = __get_output_system__ ();\n\n  output_sys.flush_stdout ();\n}\n\noutput_system::output_system (interpreter& interp)\n  : m_interpreter (interp), m_pager_stream (), m_diary_stream (),\n    m_external_pager (nullptr), m_external_diary_file (),\n    m_diary_file_name (\"diary\"), m_PAGER (default_pager ()),\n    m_PAGER_FLAGS (), m_page_output_immediately (false),\n    m_page_screen_output (false), m_write_to_diary_file (false),\n    m_really_flush_to_pager (false), m_flushing_output_to_pager (false)\n{ }\n\noctave_value\noutput_system::PAGER (const octave_value_list& args,\n                      int nargout)\n{\n  return set_internal_variable (m_PAGER, args, nargout, \"PAGER\", false);\n}\n\noctave_value\noutput_system::PAGER_FLAGS (const octave_value_list& args,\n                            int nargout)\n{\n  return set_internal_variable (m_PAGER_FLAGS, args, nargout,\n                                \"PAGER_FLAGS\", false);\n}\n\noctave_value\noutput_system::page_output_immediately (const octave_value_list& args,\n                                        int nargout)\n{\n  return set_internal_variable (m_page_output_immediately, args, nargout,\n                                \"page_output_immediately\");\n}\n\noctave_value\noutput_system::page_screen_output (const octave_value_list& args,\n                                   int nargout)\n{\n  return set_internal_variable (m_page_screen_output, args, nargout,\n                                \"page_screen_output\");\n}\n\nbool\noutput_system::page_screen_output (bool flag)\n{\n#if defined (_WIN32) || defined (__CYGWIN__)\n  // On Windows, the GUI does not support the pager if the console was created\n  // with ALLOC_CONSOLE_MODE_NO_WINDOW.\n  if (flag && application::is_gui_running ())\n    warning_with_id (\"Octave:no-pager\",\n                     \"more: enabling the pager is not supported using the GUI\");\n#endif\n\n  bool val = m_page_screen_output;\n  m_page_screen_output = flag;\n  return val;\n}\n\nstd::string\noutput_system::pager_command () const\n{\n  std::string cmd = m_PAGER;\n\n  if (! (cmd.empty () || m_PAGER_FLAGS.empty ()))\n    cmd += ' ' + m_PAGER_FLAGS;\n\n  return cmd;\n}\n\nvoid\noutput_system::reset ()\n{\n  flush_stdout ();\n\n  m_pager_stream.reset ();\n  m_diary_stream.reset ();\n}\n\nvoid\noutput_system::flush_stdout ()\n{\n  if (! m_flushing_output_to_pager)\n    {\n      unwind_protect_var<bool> restore_var1 (m_really_flush_to_pager);\n      unwind_protect_var<bool> restore_var2 (m_flushing_output_to_pager);\n\n      m_really_flush_to_pager = true;\n      m_flushing_output_to_pager = true;\n\n      std::ostream& pager_ostream = m_pager_stream.stream ();\n\n      pager_ostream.flush ();\n\n      clear_external_pager ();\n    }\n}\n\nvoid\noutput_system::close_diary ()\n{\n  // Try to flush the current buffer to the diary now, so that things\n  // like\n  //\n  // function foo ()\n  //   diary on;\n  //   ...\n  //   diary off;\n  // endfunction\n  //\n  // will do the right thing.\n\n  m_pager_stream.flush_current_contents_to_diary ();\n\n  if (m_external_diary_file.is_open ())\n    {\n      octave_diary.flush ();\n      m_external_diary_file.close ();\n    }\n}\n\nvoid\noutput_system::open_diary ()\n{\n  close_diary ();\n\n  // If there is pending output in the pager buf, it should not go\n  // into the diary file.\n\n  m_pager_stream.set_diary_skip ();\n\n  m_external_diary_file.open (m_diary_file_name.c_str (), std::ios::app);\n\n  if (! m_external_diary_file)\n    error (\"diary: can't open diary file '%s'\", m_diary_file_name.c_str ());\n}\n\nbool\noutput_system::sync (const char *buf, int len)\n{\n  // FIXME: The following seems to be a bit of a mess.\n\n  if (m_interpreter.server_mode ()\n      || ! m_interpreter.interactive ()\n      || application::forced_interactive ()\n      || m_really_flush_to_pager\n      || (m_page_screen_output && m_page_output_immediately)\n      || ! m_page_screen_output)\n    {\n      bool bypass_pager = (m_interpreter.server_mode ()\n                           || ! m_interpreter.interactive ()\n                           || application::forced_interactive ()\n                           || ! m_page_screen_output\n                           || (m_really_flush_to_pager\n                               && m_page_screen_output\n                               && ! m_page_output_immediately\n                               && ! more_than_a_screenful (buf, len))\n#if defined (_WIN32) || defined (__CYGWIN__)\n                           // On Windows, the GUI does not support the pager if\n                           // the console was created with\n                           // ALLOC_CONSOLE_MODE_NO_WINDOW.\n                           || application::is_gui_running ()\n#endif\n                           );\n\n      if (len > 0)\n        {\n          do_sync (buf, len, bypass_pager);\n\n          return true;\n        }\n    }\n\n  return false;\n}\n\nvoid\noutput_system::clear_external_pager ()\n{\n  if (m_external_pager)\n    {\n      child_list& kids = m_interpreter.get_child_list ();\n\n      kids.remove (m_external_pager->pid ());\n\n      delete m_external_pager;\n      m_external_pager = nullptr;\n    }\n}\n\nvoid\noutput_system::start_external_pager ()\n{\n  if (m_external_pager)\n    return;\n\n  std::string pgr = pager_command ();\n\n  if (! pgr.empty ())\n    {\n      m_external_pager = new oprocstream (pgr.c_str ());\n\n      child_list& kids = m_interpreter.get_child_list ();\n\n      kids.insert (m_external_pager->pid (),\n                   pager_event_handler);\n    }\n}\n\nvoid\noutput_system::do_sync (const char *msg, int len, bool bypass_pager)\n{\n  if (msg && len > 0)\n    {\n      if (bypass_pager)\n        {\n          if (m_interpreter.server_mode ())\n            {\n              event_manager& evmgr = m_interpreter.get_event_manager ();\n\n              evmgr.interpreter_output (std::string (msg, len));\n            }\n          else\n            {\n              std::cout.write (msg, len);\n              std::cout.flush ();\n            }\n        }\n      else\n        {\n          start_external_pager ();\n\n          if (m_external_pager && m_external_pager->good ())\n            {\n              m_external_pager->write (msg, len);\n              m_external_pager->flush ();\n\n#if defined (EPIPE)\n              if (errno == EPIPE)\n                m_external_pager->setstate (std::ios::failbit);\n#endif\n            }\n          else\n            {\n              // Pager missing or not working properly\n              std::cout.write (msg, len);\n              std::cout.flush ();\n            }\n        }\n    }\n}\n\nstd::ostream&\n__stdout__ ()\n{\n  output_system& output_sys = __get_output_system__ ();\n\n  return output_sys.__stdout__ ();\n}\n\nstd::ostream&\n__diary__ ()\n{\n  output_system& output_sys = __get_output_system__ ();\n\n  return output_sys.__diary__ ();\n}\n\nDEFMETHOD (diary, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} diary\n@deftypefnx {} {} diary on\n@deftypefnx {} {} diary off\n@deftypefnx {} {} diary @var{filename}\n@deftypefnx {} {[@var{status}, @var{diaryfile}] =} diary\nRecord a list of all commands @emph{and} the output they produce, mixed\ntogether just as they appear on the terminal.\n\nValid options are:\n\n@table @asis\n@item on\nStart or resume recording a session.  If no @var{filename} has previously been\nspecified recording will take place in a file called @file{diary} in the\ncurrent working directory.\n\n@item off\nStop recording the session in the diary file.\n\n@item @var{filename}\nStart or resume recording the session in the file named @var{filename}.\n@end table\n\nWith no input or output arguments, @code{diary} toggles the current diary\nstate.\n\nIf output arguments are requested, @code{diary} ignores inputs and returns\nthe current status.  The boolean @var{status} indicates whether recording is on\nor off, and @var{diaryfile} is the name of the file where the session is\nstored.\n@seealso{history, evalc}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  output_system& output_sys = interp.get_output_system ();\n\n  if (nargout > 0)\n    {\n      // Querying diary variables\n      if (nargout == 1)\n        return ovl (output_sys.write_to_diary_file ());\n      else\n        return ovl (output_sys.write_to_diary_file (),\n                    output_sys.diary_file_name ());\n    }\n\n  if (nargin == 0)\n    {\n      output_sys.write_to_diary_file (! output_sys.write_to_diary_file ());\n      output_sys.open_diary ();\n    }\n  else\n    {\n      std::string arg = args(0).xstring_value (\"diary: argument must be a string\");\n\n      if (arg == \"on\")\n        {\n          output_sys.write_to_diary_file (true);\n          output_sys.open_diary ();\n        }\n      else if (arg == \"off\")\n        {\n          output_sys.close_diary ();\n          output_sys.write_to_diary_file (false);\n        }\n      else\n        {\n          output_sys.diary_file_name (arg);\n          output_sys.write_to_diary_file (true);\n          output_sys.open_diary ();\n        }\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (more, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} more\n@deftypefnx {} {} more on\n@deftypefnx {} {} more off\nTurn output pagination on or off.\n\nWithout an argument, @code{more} toggles the current state.\n\nThe current state can be determined via @code{page_screen_output}.\n\nUsing the pager is not supported on Windows in the GUI.\n@seealso{page_screen_output, page_output_immediately, PAGER, PAGER_FLAGS}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  output_system& output_sys = interp.get_output_system ();\n\n  if (nargin > 0)\n    {\n      std::string arg = args(0).xstring_value (R\"(more: argument must be string \"on\" or \"off\")\");\n\n      if (arg == \"on\")\n        output_sys.page_screen_output (true);\n      else if (arg == \"off\")\n        output_sys.page_screen_output (false);\n      else\n        error (R\"(more: argument must be \"on\" or \"off\")\");\n    }\n  else\n    output_sys.page_screen_output (! output_sys.page_screen_output ());\n\n  return ovl ();\n}\n\nDEFUN (terminal_size, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{rows}, @var{cols}] =} terminal_size ()\n@deftypefnx {} {} terminal_size ([@var{rows}, @var{cols}])\nQuery or set the size of the terminal window.  If called with no arguments,\nreturn a two-element row vector containing the current size of the terminal\nwindow in characters (rows and columns).  If called with a two-element vector\nof integer values, set the terminal size and return the previous setting.\nSetting the size manually should not be needed when using readline for\ncommand-line editing.\n@seealso{list_in_columns}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  RowVector size (2, 0.0);\n\n  size(0) = command_editor::terminal_rows ();\n  size(1) = command_editor::terminal_cols ();\n\n  if (nargin == 1)\n    {\n      Matrix m = args(0).xmatrix_value (\"argument must be a 2-element array\");\n\n      if (m.numel () != 2)\n        error (\"terminal_size: argument must be a 2-element array\");\n\n      int rows = math::round (m(0));\n      int cols = math::round (m(1));\n\n      if (rows <= 0 || cols <= 0)\n        error (\"terminal_size: rows and columns must be positive integers\");\n\n      command_editor::set_screen_size (rows, cols);\n    }\n\n  return ovl (size);\n}\n\nDEFMETHOD (page_output_immediately, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} page_output_immediately ()\n@deftypefnx {} {@var{old_val} =} page_output_immediately (@var{new_val})\n@deftypefnx {} {@var{old_val} =} page_output_immediately (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave sends\noutput to the pager as soon as it is available.\n\nWhen the value is @code{false}, Octave buffers its output and waits until just\nbefore the prompt is printed to flush it to the pager.  This is the default.\n\nWhen @code{page_screen_output} is @code{false}, this variable has no effect.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{page_screen_output, more, PAGER, PAGER_FLAGS}\n@end deftypefn */)\n{\n  output_system& output_sys = interp.get_output_system ();\n\n  return output_sys.page_output_immediately (args, nargout);\n}\n\nDEFMETHOD (page_screen_output, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} page_screen_output ()\n@deftypefnx {} {@var{old_val} =} page_screen_output (@var{new_val})\n@deftypefnx {} {@var{old_val} =} page_screen_output (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether output intended\nfor the terminal window that is longer than one page is sent through a\npager.\n\nThis allows you to view one screenful at a time.  Some pagers\n(such as @code{less}---@pxref{Installing Octave}) are also capable of moving\nbackward on the output.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{more, page_output_immediately, PAGER, PAGER_FLAGS}\n@end deftypefn */)\n{\n  output_system& output_sys = interp.get_output_system ();\n\n  return output_sys.page_screen_output (args, nargout);\n}\n\nDEFMETHOD (PAGER, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} PAGER ()\n@deftypefnx {} {@var{old_val} =} PAGER (@var{new_val})\n@deftypefnx {} {@var{old_val} =} PAGER (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the program to use\nto display terminal output on your system.\n\nThe default value is normally @qcode{\"less\"}, @qcode{\"more\"}, or\n@qcode{\"pg\"}, depending on what programs are installed on your system.\n@xref{Installing Octave}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{PAGER_FLAGS, page_output_immediately, more, page_screen_output}\n@end deftypefn */)\n{\n  output_system& output_sys = interp.get_output_system ();\n\n  return output_sys.PAGER (args, nargout);\n}\n\nDEFMETHOD (PAGER_FLAGS, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} PAGER_FLAGS ()\n@deftypefnx {} {@var{old_val} =} PAGER_FLAGS (@var{new_val})\n@deftypefnx {} {@var{old_val} =} PAGER_FLAGS (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the options to pass\nto the pager.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{PAGER, more, page_screen_output, page_output_immediately}\n@end deftypefn */)\n{\n  output_system& output_sys = interp.get_output_system ();\n\n  return output_sys.PAGER_FLAGS (args, nargout);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/pager.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pager_h)\n#define octave_pager_h 1\n\n#include \"octave-config.h\"\n\n#include <fstream>\n#include <iosfwd>\n#include <sstream>\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\nclass oprocstream;\n\nclass OCTINTERP_API pager_buf : public std::stringbuf\n{\npublic:\n\n  pager_buf () : std::stringbuf (), m_diary_skip (0) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (pager_buf)\n\n  ~pager_buf () = default;\n\n  void flush_current_contents_to_diary ();\n\n  void set_diary_skip ();\n\nprotected:\n\n  int sync ();\n\nprivate:\n\n  std::size_t m_diary_skip;\n};\n\nclass OCTINTERP_API pager_stream : public std::ostream\n{\npublic:\n\n  pager_stream ();\n\n  OCTAVE_DISABLE_COPY_MOVE (pager_stream)\n\n  ~pager_stream ();\n\n  void flush_current_contents_to_diary ();\n\n  void set_diary_skip ();\n\n  std::ostream& stream ();\n\n  void reset ();\n\nprivate:\n\n  pager_buf *m_pb;\n};\n\nclass OCTINTERP_API diary_buf : public std::stringbuf\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_DELETE (diary_buf)\n  OCTAVE_DISABLE_COPY_MOVE (diary_buf)\n\nprotected:\n\n  int sync ();\n};\n\nclass OCTINTERP_API diary_stream : public std::ostream\n{\npublic:\n\n  diary_stream ();\n\n  OCTAVE_DISABLE_COPY_MOVE (diary_stream)\n\n  ~diary_stream ();\n\n  std::ostream& stream ();\n\n  void reset ();\n\nprivate:\n\n  diary_buf *m_db;\n};\n\nextern OCTINTERP_API void flush_stdout ();\n\nclass output_system\n{\npublic:\n\n  output_system (interpreter& interp);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (output_system)\n\n  ~output_system () = default;\n\n  pager_stream& pager () { return m_pager_stream; }\n\n  diary_stream& diary () { return m_diary_stream; }\n\n  std::string diary_file_name () const { return m_diary_file_name; }\n\n  std::string diary_file_name (const std::string& nm)\n  {\n    std::string val = m_diary_file_name;\n    m_diary_file_name = nm.empty () ? \"diary\" : nm;\n    return val;\n  }\n\n  octave_value PAGER (const octave_value_list& args, int nargout);\n\n  std::string PAGER () const { return m_PAGER; }\n\n  std::string PAGER (const std::string& s)\n  {\n    std::string val = m_PAGER;\n    m_PAGER = s;\n    return val;\n  }\n\n  octave_value PAGER_FLAGS (const octave_value_list& args, int nargout);\n\n  std::string PAGER_FLAGS () const { return m_PAGER_FLAGS; }\n\n  std::string PAGER_FLAGS (const std::string& s)\n  {\n    std::string val = m_PAGER_FLAGS;\n    m_PAGER_FLAGS = s;\n    return val;\n  }\n\n  octave_value page_output_immediately (const octave_value_list& args,\n                                        int nargout);\n\n  bool page_output_immediately () const\n  {\n    return m_page_output_immediately;\n  }\n\n  bool page_output_immediately (bool flag)\n  {\n    bool val = m_page_output_immediately;\n    m_page_output_immediately = flag;\n    return val;\n  }\n\n  octave_value page_screen_output (const octave_value_list& args,\n                                   int nargout);\n\n  bool page_screen_output () const { return m_page_screen_output; }\n\n  bool page_screen_output (bool flag);\n\n  bool write_to_diary_file () const\n  {\n    return m_write_to_diary_file;\n  }\n\n  bool write_to_diary_file (bool flag)\n  {\n    bool val = m_write_to_diary_file;\n    m_write_to_diary_file = flag;\n    return val;\n  }\n\n  bool really_flush_to_pager () const\n  {\n    return m_really_flush_to_pager;\n  }\n\n  bool really_flush_to_pager (bool flag)\n  {\n    bool val = m_really_flush_to_pager;\n    m_really_flush_to_pager = flag;\n    return val;\n  }\n\n  bool flushing_output_to_pager () const\n  {\n    return m_flushing_output_to_pager;\n  }\n\n  bool flushing_output_to_pager (bool flag)\n  {\n    bool val = m_flushing_output_to_pager;\n    m_flushing_output_to_pager = flag;\n    return val;\n  }\n\n  std::string pager_command () const;\n\n  std::ofstream& external_diary_file () { return m_external_diary_file; }\n\n  void reset ();\n\n  void flush_stdout ();\n\n  bool sync (const char *msg, int len);\n\n  void clear_external_pager ();\n\n  void open_diary ();\n\n  void close_diary ();\n\n  std::ostream& __stdout__ () { return m_pager_stream.stream (); }\n\n  std::ostream& __diary__ () { return m_diary_stream.stream (); }\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  pager_stream m_pager_stream;\n\n  diary_stream m_diary_stream;\n\n  // Our actual connection to the external pager.\n  oprocstream *m_external_pager = nullptr;\n\n  // The diary file.\n  std::ofstream m_external_diary_file;\n\n  // The name of the current diary file.\n  std::string m_diary_file_name;\n\n  // The shell command to run as the pager.\n  std::string m_PAGER;\n\n  // The options to pass to the pager.\n  std::string m_PAGER_FLAGS;\n\n  // TRUE means that if output is going to the pager, it is sent as soon\n  // as it is available.  Otherwise, it is buffered and only sent to the\n  // pager when it is time to print another prompt.\n  bool m_page_output_immediately;\n\n  // TRUE means all output intended for the screen should be passed\n  // through the pager.\n  bool m_page_screen_output;\n\n  // TRUE means we write to the diary file.\n  bool m_write_to_diary_file;\n\n  bool m_really_flush_to_pager;\n\n  bool m_flushing_output_to_pager;\n\n  void start_external_pager ();\n\n  void do_sync (const char *msg, int len, bool bypass_pager);\n};\n\nextern OCTINTERP_API std::ostream& __stdout__ ();\n\nextern OCTINTERP_API std::ostream& __diary__ ();\n\nOCTAVE_END_NAMESPACE(octave)\n\n#define octave_stdout (octave::__stdout__ ())\n\n#define octave_diary (octave::__diary__ ())\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/panic.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"panic.h\"\n\nOCTAVE_NORETURN\nvoid\nvpanic (const char *fmt, va_list args)\n{\n  octave::error_system& es = octave::__get_error_system__ ();\n\n  es.vpanic (fmt, args);\n}\n\nOCTAVE_NORETURN\nvoid\npanic (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  vpanic (fmt, args);\n  va_end (args);\n}\n"
  },
  {
    "path": "libinterp/corefcn/panic.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_panic_h)\n#define octave_panic_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdarg>\n\nOCTAVE_NORETURN\nextern OCTINTERP_API void vpanic (const char *fmt, va_list args);\n\nOCTAVE_FORMAT_PRINTF (1, 2)\nOCTAVE_NORETURN\nextern OCTINTERP_API void panic (const char *fmt, ...);\n\n// To allow the __FILE__ and __LINE__ macros to work as expected, the\n// panic_impossible, panic_if, and panic_unless symbols must be defined\n// as macros.\n\n#if defined (NDEBUG)\n\n#  define panic_impossible() do { } while (0)\n\n#  define panic_if(cond) do { } while (0)\n\n#  define panic_unless(cond) do { } while (0)\n\n#else\n\n#  define panic_impossible()                                                            \\\n  ::panic (\"impossible state reached in file '%s' at line %d\", __FILE__, __LINE__)\n\n#  define panic_if(cond) do { if (cond) panic_impossible (); } while (0)\n\n#  define panic_unless(cond) panic_if (! (cond))\n\n#endif\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/pr-flt-fmt.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"pr-flt-fmt.h\"\n#include \"variables.h\"\n\n// The precision of the numbers printed by the default output\n// routines.\nstatic int Voutput_precision = 5;\n\nint\noutput_precision ()\n{\n  return Voutput_precision;\n}\n\nvoid\nset_output_prec (int prec)\n{\n  Voutput_precision = prec;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (output_precision, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} output_precision ()\n@deftypefnx {} {@var{old_val} =} output_precision (@var{new_val})\n@deftypefnx {} {@var{old_val} =} output_precision (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the minimum number of\nsignificant figures to display for numeric output.\n\nNote that regardless of the value set for @code{output_precision}, the\nnumber of digits of precision displayed is limited to 16 for double\nprecision values and 7 for single precision values.  Also, calls to the\n@code{format} function that change numeric display can also change the set\nvalue for @code{output_precision}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n\n@seealso{format, fixed_point_format}\n@end deftypefn */)\n{\n  return set_internal_variable (Voutput_precision, args, nargout,\n                                \"output_precision\", 0, 16);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/pr-flt-fmt.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pr_flt_fmt_h)\n#define octave_pr_flt_fmt_h 1\n\n#include \"octave-config.h\"\n\n#include <iomanip>\n#include <iosfwd>\n\ntemplate <typename T>\nclass pr_engineering_float;\n\ntemplate <typename T>\nclass pr_formatted_float;\n\ntemplate <typename T>\nclass pr_rational_float;\n\nextern OCTINTERP_API int output_precision ();\n\nextern OCTINTERP_API void set_output_prec (int prec);\n\nclass OCTINTERP_API float_format\n{\npublic:\n\n  float_format (int w = 0, int p = output_precision (), int f = 0)\n    : m_fw (w), m_ex (0), m_prec (p), m_fmt (f), m_up (0), m_sp (0) { }\n\n  float_format (int w, int e, int p, int f)\n    : m_fw (w), m_ex (e), m_prec (p), m_fmt (f), m_up (0), m_sp (0) { }\n\n  float_format (const float_format&) = default;\n\n  float_format& operator = (const float_format&) = default;\n\n  ~float_format () = default;\n\n  float_format& scientific ()\n  {\n    m_fmt = std::ios::scientific;\n    return *this;\n  }\n\n  float_format& fixed ()\n  {\n    m_fmt = std::ios::fixed;\n    return *this;\n  }\n\n  float_format& general ()\n  {\n    m_fmt = 0;\n    return *this;\n  }\n\n  float_format& uppercase ()\n  {\n    m_up = std::ios::uppercase;\n    return *this;\n  }\n\n  float_format& lowercase ()\n  {\n    m_up = 0;\n    return *this;\n  }\n\n  float_format& precision (int p)\n  {\n    m_prec = p;\n    return *this;\n  }\n\n  float_format& width (int w)\n  {\n    m_fw = w;\n    return *this;\n  }\n\n  float_format& exponent_width (int w)\n  {\n    m_ex = w;\n    return *this;\n  }\n\n  float_format& trailing_zeros (bool tz = true)\n\n  {\n    m_sp = (tz ? std::ios::showpoint : 0);\n    return *this;\n  }\n\n  std::ios::fmtflags format_flags () const\n  {\n    return static_cast<std::ios::fmtflags> (m_fmt | m_up | m_sp);\n  }\n\n  int format () const\n  {\n    return m_fmt;\n  }\n\n  bool is_scientific () const\n  {\n    return m_fmt == std::ios::scientific;\n  }\n\n  bool is_fixed () const\n  {\n    return m_fmt == std::ios::fixed;\n  }\n\n  bool is_general () const\n  {\n    return m_fmt == 0;\n  }\n\n  bool is_uppercase () const\n  {\n    return m_up == std::ios::uppercase;\n  }\n\n  bool is_lowercase () const\n  {\n    return m_up == 0;\n  }\n\n  int precision () const\n  {\n    return m_prec;\n  }\n\n  int width () const\n  {\n    return m_fw;\n  }\n\n  int exponent_width () const\n  {\n    return m_ex;\n  }\n\n  bool show_trailing_zeros () const\n  {\n    return m_sp == std::ios::showpoint;\n  }\n\n  template <typename T>\n  friend std::ostream&\n  operator << (std::ostream& os, const pr_engineering_float<T>& pef);\n\n  template <typename T>\n  friend std::ostream&\n  operator << (std::ostream& os, const pr_formatted_float<T>& pff);\n\n  template <typename T>\n  friend std::ostream&\n  operator << (std::ostream& os, const pr_rational_float<T>& prf);\n\nprivate:\n\n  // Field width.  Zero means as wide as necessary.\n  int m_fw;\n\n  // Exponent Field width.  Zero means as wide as necessary.\n  int m_ex;\n\n  // Precision.\n  int m_prec;\n\n  // Format.\n  int m_fmt;\n\n  // E or e.\n  int m_up;\n\n  // Show trailing zeros.\n  int m_sp;\n};\n\nclass OCTINTERP_API float_display_format\n{\npublic:\n\n  float_display_format () = default;\n\n  float_display_format (double scale, const float_format& real_fmt,\n                        const float_format& imag_fmt = float_format ())\n    : m_scale (scale), m_real_fmt (real_fmt), m_imag_fmt (imag_fmt)\n  { }\n\n  explicit float_display_format (const float_format& real_fmt,\n                                 const float_format& imag_fmt = float_format ())\n    : m_scale (1.0), m_real_fmt (real_fmt), m_imag_fmt (imag_fmt)\n  { }\n\n  float_display_format (const float_display_format&) = default;\n\n  float_display_format& operator = (const float_display_format&) = default;\n\n  ~float_display_format () = default;\n\n  double scale_factor () const { return m_scale; }\n\n  float_format real_format () const { return m_real_fmt; }\n\n  float_format imag_format () const { return m_imag_fmt; }\n\n  void set_precision (int prec)\n  {\n    m_real_fmt.precision (prec);\n    m_imag_fmt.precision (prec);\n  }\n\nprivate:\n\n  double m_scale = 1.0;\n\n  float_format m_real_fmt;\n\n  float_format m_imag_fmt;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/pr-output.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <iomanip>\n#include <limits>\n#include <list>\n#include <sstream>\n#include <string>\n\n#include \"Array-util.h\"\n#include \"CMatrix.h\"\n#include \"Range.h\"\n#include \"cmd-edit.h\"\n#include \"dMatrix.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-string.h\"\n#include \"quit.h\"\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter.h\"\n#include \"ovl.h\"\n#include \"oct-stream.h\"\n#include \"octave-preserve-stream-state.h\"\n#include \"pager.h\"\n#include \"pr-flt-fmt.h\"\n#include \"pr-output.h\"\n#include \"sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n// TRUE means use a scaled fixed point format for 'format long' and\n// 'format short'.\nstatic bool Vfixed_point_format = false;\n\n// TRUE means that the dimensions of empty objects should be printed\n// like this: x = [](2x0).\nbool Vprint_empty_dimensions = true;\n\n// TRUE means that the rows of big matrices should be split into\n// smaller slices that fit on the screen.\nstatic bool Vsplit_long_rows = true;\n\n// TRUE means don't do any fancy formatting.\nstatic bool free_format = false;\n\n// TRUE means print plus sign for nonzero, blank for zero.\nstatic bool plus_format = false;\n\n// First char for > 0, second for < 0, third for == 0.\nstatic std::string plus_format_chars = \"+- \";\n\n// TRUE means always print in a rational approximation\nstatic bool rat_format = false;\n\n// Used to force the length of the rational approximation string for Frats\nstatic int rat_string_len = -1;\n\n// TRUE means always print like dollars and cents.\nstatic bool bank_format = false;\n\n// TRUE means print data in hexadecimal format.\nstatic int hex_format = 0;\n\n// TRUE means print data in binary-bit-pattern format.\nstatic int bit_format = 0;\n\n// TRUE means don't put newlines around the column number headers.\nbool Vcompact_format = false;\n\n// TRUE means use an e format.\nstatic bool print_e = false;\n\n// TRUE means use a g format.\nstatic bool print_g = false;\n\n// TRUE means print uppercase E in exponent field and A-F in hex format.\nstatic bool uppercase_format = false;\n\n// TRUE means use an engineering format.\nstatic bool print_eng = false;\n\nstatic int\ncalc_scale_exp (const int& x)\n{\n  if (! print_eng)\n    return x;\n  else\n    return x - 3*static_cast<int> (x/3);\n\n  // The expression above is equivalent to x - (x % 3).\n\n  // According to the ISO specification for C++ the modulo operator is\n  // compiler dependent if any of the arguments are negative.  Since\n  // this function will need to work on negative arguments, and we want\n  // to avoid portability issues, we re-implement the modulo function to\n  // the desired behavior (truncation).  There may be a gnulib replacement.\n\n  // ISO/IEC 14882:2003 : Programming languages -- C++. 5.6.4: ISO,\n  // IEC. 2003.  \"the binary % operator yields the remainder from the\n  // division of the first expression by the second.  .... If both\n  // operands are nonnegative then the remainder is nonnegative; if not,\n  // the sign of the remainder is implementation-defined\".\n}\n\ntemplate <typename T>\nstatic inline int\nengineering_exponent (T x)\n{\n  int ex = 0;\n\n  if (x != 0)\n    {\n      T absval = (x < 0 ? -x : x);\n      int logabsval = static_cast<int> (std::floor (log10 (absval)));\n\n      // Avoid using modulo function with negative arguments for\n      // portability.  See extended comment at calc_scale_exp\n\n      if (logabsval < 0)\n        ex = logabsval - 2 + ((-logabsval + 2) % 3);\n      else\n        ex = logabsval - (logabsval % 3);\n    }\n\n  return ex;\n}\n\ntemplate <typename T>\nstatic inline int\nnum_digits (T x)\n{\n  return 1 + (print_eng\n              ? engineering_exponent (x)\n              : static_cast<int> (std::floor (log10 (x))));\n}\n\ntemplate <typename T>\nint\npr_engineering_float<T>::exponent () const\n{\n  return engineering_exponent (m_val);\n}\n\ntemplate <typename T>\nT\npr_engineering_float<T>::mantissa () const\n{\n  return m_val / std::pow (static_cast<T> (10), exponent ());\n}\n\ntemplate <typename T>\nstd::ostream&\noperator << (std::ostream& os, const pr_engineering_float<T>& pef)\n{\n  octave::preserve_stream_state stream_state (os);\n\n  float_format real_fmt = pef.m_ff;\n\n  if (real_fmt.width () >= 0)\n    os << std::setw (real_fmt.width () - real_fmt.exponent_width ());\n\n  if (real_fmt.precision () >= 0)\n    os << std::setprecision (real_fmt.precision ());\n\n  os.flags (real_fmt.format_flags ());\n\n  os << pef.mantissa ();\n\n  int ex = pef.exponent ();\n  if (ex < 0)\n    {\n      if (uppercase_format)\n        os << std::setw (0) << \"E-\";\n      else\n        os << std::setw (0) << \"e-\";\n      ex = -ex;\n    }\n  else\n    {\n      if (uppercase_format)\n        os << std::setw (0) << \"E+\";\n      else\n        os << std::setw (0) << \"e+\";\n    }\n\n  os << std::setw (real_fmt.exponent_width () - 2)\n     << std::setfill ('0') << ex;\n\n  return os;\n}\n\ntemplate <typename T>\nstd::ostream&\noperator << (std::ostream& os, const pr_formatted_float<T>& pff)\n{\n  octave::preserve_stream_state stream_state (os);\n\n  float_format real_fmt = pff.m_ff;\n\n  if (real_fmt.width () >= 0)\n    os << std::setw (real_fmt.width ());\n\n  if (real_fmt.precision () >= 0)\n    os << std::setprecision (real_fmt.precision ());\n\n  os.flags (real_fmt.format_flags ());\n\n  os << pff.m_val;\n\n  return os;\n}\n\ntemplate <typename T>\nstd::ostream&\noperator << (std::ostream& os, const pr_rational_float<T>& prf)\n{\n  octave::preserve_stream_state stream_state (os);\n\n  float_format real_fmt = prf.m_ff;\n  bool have_neg_sign = prf.m_val < 0;\n\n  int fw = (rat_string_len > 0 ? rat_string_len : real_fmt.width ());\n  std::string s;\n\n  if (have_neg_sign)\n    s = rational_approx (prf.m_val, fw);\n  else\n    s = rational_approx (prf.m_val, fw-1);\n\n  if (fw >= 0)\n    os << std::setw (fw);\n\n  os.flags (real_fmt.format_flags ());\n\n  if (s == \"0\")\n    s = '*';\n  else if (fw > 0)\n    {\n      if (s.find ('/') != std::string::npos)\n        {\n          if (s.length () > (static_cast<unsigned int> (fw)))\n            s = '*';\n        }\n      else\n        {\n          if (have_neg_sign)\n            {\n              if (s.length () > (static_cast<unsigned int> (fw) - 2))\n                s = '*';\n            }\n          else\n            {\n              if (s.length () > (static_cast<unsigned int> (fw) - 3))\n                s = '*';\n            }\n        }\n    }\n\n  os << s;\n\n  return os;\n}\n\ntemplate <typename T>\nstatic inline T\npr_max_internal (const MArray<T>& m)\n{\n  // We expect a 2-D array.\n  panic_unless (m.ndims () == 2);\n\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  T result = std::numeric_limits<T>::lowest ();\n\n  bool all_inf_or_nan = true;\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        T val = m(i, j);\n        if (! octave::math::isfinite (val))\n          continue;\n\n        all_inf_or_nan = false;\n\n        if (val > result)\n          result = val;\n      }\n\n  if (all_inf_or_nan)\n    result = 0;\n\n  return result;\n}\n\ntemplate <typename T>\nstatic inline T\npr_min_internal (const MArray<T>& m)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  T result = std::numeric_limits<T>::max ();\n\n  bool all_inf_or_nan = true;\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        T val = m(i, j);\n        if (! octave::math::isfinite (val))\n          continue;\n\n        all_inf_or_nan = false;\n\n        if (val < result)\n          result = val;\n      }\n\n  if (all_inf_or_nan)\n    result = 0;\n\n  return result;\n}\n\ntemplate <typename>\nstruct pr_output_traits\n{\n  static const int DIGITS10;\n  static const int MAX_FIELD_WIDTH;\n};\n\ntemplate <>\nstruct pr_output_traits<double>\n{\n  static const int DIGITS10;\n  static const int MAX_FIELD_WIDTH;\n};\n\nconst int pr_output_traits<double>::DIGITS10 = 16;\nconst int pr_output_traits<double>::MAX_FIELD_WIDTH = 21;\n\ntemplate <>\nstruct pr_output_traits<float>\n{\n  static const int DIGITS10;\n  static const int MAX_FIELD_WIDTH;\n};\n\nconst int pr_output_traits<float>::DIGITS10 = 8;\nconst int pr_output_traits<float>::MAX_FIELD_WIDTH = 13;\n\n// FIXME: it would be nice to share more code among these functions,..\n\n// Works for double and float.\n\ntemplate <typename T>\nstatic inline float_display_format\nmake_real_format (int digits, bool inf_or_nan, bool int_only)\n{\n  float_format fmt;\n\n  int prec = std::min (output_precision (), pr_output_traits<T>::DIGITS10);\n\n  int fw = 0, ld = 0, rd = 0;\n\n  if (rat_format)\n    {\n      fw = 0;\n      rd = 0;\n    }\n  else if (bank_format)\n    {\n      fw = (digits < 0 ? 4 : digits + 3);\n      if (inf_or_nan)\n        fw = 3;\n      rd = 2;\n    }\n  else if (hex_format)\n    {\n      fw = 2 * sizeof (T);\n      rd = 0;\n    }\n  else if (bit_format)\n    {\n      fw = 8 * sizeof (T);\n      rd = 0;\n    }\n  else if (inf_or_nan)\n    {\n      fw = 3;\n    }\n  else if (int_only)\n    {\n      fw = digits;\n      ld = digits;\n      rd = 0;\n    }\n  else\n    {\n      if (digits > 0)\n        {\n          ld = digits;\n          rd = (prec > digits ? prec - digits : prec);\n        }\n      else if (digits < 0)\n        {\n          ld = 1;\n          rd = (prec > digits ? prec - digits : prec);\n        }\n      else\n        {\n          ld = 1;\n          rd = (prec > digits ? prec - 1 : prec);\n        }\n\n      fw = ld + 1 + rd;\n    }\n\n  if (! (rat_format || bank_format || hex_format || bit_format)\n      && (print_e || print_g || print_eng\n          || ld + rd > pr_output_traits<T>::DIGITS10\n          || fw > pr_output_traits<T>::MAX_FIELD_WIDTH\n          || ld + rd > (1.5 * prec)))\n    {\n      if (print_g)\n        fmt = float_format (prec, prec);\n      else\n        {\n          // e+ddd\n          int ex = 5;\n\n          if (print_eng)\n            {\n              // -ddd.\n              fw = 1 + prec + ex;\n              if (inf_or_nan)\n                {\n                  fw = 3;\n                  ex = 0;\n                }\n              fmt = float_format (fw, ex, prec - 1, std::ios::fixed);\n            }\n          else\n            {\n              // -d.\n              fw = prec + ex;\n              if (inf_or_nan)\n                {\n                  fw = 3;\n                  ex = 0;\n                }\n              fmt = float_format (fw, ex, prec - 1, std::ios::scientific);\n            }\n        }\n    }\n  else if (! bank_format && (inf_or_nan || int_only))\n    fmt = float_format (fw, ld);\n  else\n    fmt = float_format (fw, rd, std::ios::fixed);\n\n  if (uppercase_format)\n    fmt.uppercase ();\n\n  return float_display_format (fmt);\n}\n\n// Works for double and float.\n\ntemplate <typename T>\nfloat_display_format\nmake_scalar_format (const T& val)\n{\n  if (free_format)\n    return float_display_format ();\n\n  bool inf_or_nan = (octave::math::isinf (val) || octave::math::isnan (val));\n\n  bool int_only = (! inf_or_nan && octave::math::is_integer (val));\n\n  T val_abs = (val < 0 ? -val : val);\n\n  int digits = (inf_or_nan || val_abs == 0) ? 0 : num_digits (val_abs);\n\n  return make_real_format<T> (digits, inf_or_nan, int_only);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const double& d)\n{\n  return make_scalar_format (d);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const float& f)\n{\n  return make_scalar_format (f);\n}\n\ntemplate <typename T>\nstatic inline float_display_format\nmake_real_matrix_format (int x_max, int x_min, bool inf_or_nan,\n                         int int_or_inf_or_nan)\n{\n  T scale = ((x_max == 0 || int_or_inf_or_nan)\n             ? 1 : std::pow (10.0, calc_scale_exp (x_max - 1)));\n\n  float_format fmt;\n\n  int prec = std::min (output_precision (), pr_output_traits<T>::DIGITS10);\n\n  int fw = 0, ld = 0, rd = 0;\n\n  if (rat_format)\n    {\n      fw = 9;\n      rd = 0;\n    }\n  else if (bank_format)\n    {\n      int digits = (x_max > x_min ? x_max : x_min);\n      fw = (digits <= 0 ? 5 : digits + 4);\n      rd = 2;\n    }\n  else if (hex_format)\n    {\n      fw = 2 * sizeof (T);\n      rd = 0;\n    }\n  else if (bit_format)\n    {\n      fw = 8 * sizeof (T);\n      rd = 0;\n    }\n  else if (Vfixed_point_format && ! print_g)\n    {\n      rd = prec - 1;\n      fw = rd + 3;\n      if (inf_or_nan && fw < 4)\n        fw = 4;\n    }\n  else if (int_or_inf_or_nan)\n    {\n      int digits = (x_max > x_min ? x_max : x_min);\n      fw = (digits <= 0 ? 2 : digits + 1);\n      if (inf_or_nan && fw < 4)\n        fw = 4;\n      rd = fw;\n    }\n  else\n    {\n      int ld_max, rd_max;\n      if (x_max > 0)\n        {\n          ld_max = x_max;\n          rd_max = (prec > x_max ? prec - x_max : prec);\n          x_max++;\n        }\n      else if (x_max < 0)\n        {\n          ld_max = 1;\n          rd_max = (prec > x_max ? prec - x_max : prec);\n          x_max = -x_max + 1;\n        }\n      else\n        {\n          ld_max = 1;\n          rd_max = (prec > 1 ? prec - 1 : prec);\n          x_max = 1;\n        }\n\n      int ld_min, rd_min;\n      if (x_min > 0)\n        {\n          ld_min = x_min;\n          rd_min = (prec > x_min ? prec - x_min : prec);\n          x_min++;\n        }\n      else if (x_min < 0)\n        {\n          ld_min = 1;\n          rd_min = (prec > x_min ? prec - x_min : prec);\n          x_min = -x_min + 1;\n        }\n      else\n        {\n          ld_min = 1;\n          rd_min = (prec > 1 ? prec - 1 : prec);\n          x_min = 1;\n        }\n\n      ld = (ld_max > ld_min ? ld_max : ld_min);\n      rd = (rd_max > rd_min ? rd_max : rd_min);\n\n      fw = 1 + ld + 1 + rd;\n      if (inf_or_nan && fw < 4)\n        fw = 4;\n    }\n\n  if (! (rat_format || bank_format || hex_format || bit_format)\n      && (print_e || print_eng || print_g\n          || (! Vfixed_point_format\n              && (ld + rd > pr_output_traits<T>::DIGITS10\n                  || fw > pr_output_traits<T>::MAX_FIELD_WIDTH\n                  || ld + rd > (1.5 * prec)))))\n    {\n      if (print_g)\n        fmt = float_format (prec+6, prec);\n      else\n        {\n          int ex = 4;\n          if (x_max > 100 || x_min > 100)\n            ex++;\n\n          if (print_eng)\n            {\n              fw = 4 + prec + ex;\n              if (inf_or_nan && fw < 6)\n                fw = 6;\n              fmt = float_format (fw, ex, prec - 1, std::ios::fixed);\n            }\n          else\n            {\n              fw = 2 + prec + ex;\n              if (inf_or_nan && fw < 4)\n                fw = 4;\n              fmt = float_format (fw, prec - 1, std::ios::scientific);\n            }\n        }\n    }\n  else if (! bank_format && int_or_inf_or_nan)\n    fmt = float_format (fw, rd);\n  else\n    fmt = float_format (fw, rd, std::ios::fixed);\n\n  if (uppercase_format)\n    fmt.uppercase ();\n\n  return float_display_format (scale, fmt);\n}\n\ntemplate <typename MT>\nstatic inline float_display_format\nmake_matrix_format (const MT& m)\n{\n  // We expect a 2-D array.\n  panic_unless (m.ndims () == 2);\n\n  if (free_format)\n    return float_display_format ();\n\n  bool inf_or_nan = m.any_element_is_inf_or_nan ();\n\n  bool int_or_inf_or_nan = m.all_elements_are_int_or_inf_or_nan ();\n\n  MT m_abs = m.abs ();\n\n  typedef typename MT::element_type ELT_T;\n\n  ELT_T max_abs = pr_max_internal (m_abs);\n  ELT_T min_abs = pr_min_internal (m_abs);\n\n  int x_max = ((inf_or_nan || max_abs == 0) ? 0 : num_digits (max_abs));\n\n  int x_min = ((inf_or_nan || min_abs == 0) ? 0 : num_digits (min_abs));\n\n  return make_real_matrix_format<ELT_T> (x_max, x_min, inf_or_nan,\n                                         int_or_inf_or_nan);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const Matrix& m)\n{\n  return make_matrix_format (m);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const FloatMatrix& m)\n{\n  return make_matrix_format (m);\n}\n\ntemplate <typename T>\nstatic inline float_display_format\nmake_complex_format (int x_max, int x_min, int r_x,\n                     bool inf_or_nan, int int_only)\n{\n  float_format r_fmt;\n  float_format i_fmt;\n\n  int prec = std::min (output_precision (), pr_output_traits<T>::DIGITS10);\n\n  int i_fw = 0, r_fw = 0, ld = 0, rd = 0;\n\n  if (rat_format)\n    {\n      i_fw = 0;\n      r_fw = 0;\n      rd = 0;\n    }\n  else if (bank_format)\n    {\n      int digits = r_x;\n      i_fw = 0;\n      r_fw = (digits <= 0 ? 5 : digits + 4);\n      rd = 2;\n    }\n  else if (hex_format)\n    {\n      r_fw = 2 * sizeof (T);\n      i_fw = 2 * sizeof (T);\n      rd = 0;\n    }\n  else if (bit_format)\n    {\n      r_fw = 8 * sizeof (T);\n      i_fw = 8 * sizeof (T);\n      rd = 0;\n    }\n  else if (int_only)\n    {\n      int digits = (x_max > x_min ? x_max : x_min);\n      i_fw = (digits <= 0 ? 1 : digits);\n      r_fw = i_fw + 1;\n      if (inf_or_nan && i_fw < 3)\n        {\n          i_fw = 3;\n          r_fw = 4;\n        }\n      ld = r_fw;\n    }\n  else  // ordinary case of floating point numeric values\n    {\n      int ld_max, rd_max;\n      if (x_max > 0)\n        {\n          ld_max = x_max;\n          rd_max = (prec > x_max ? prec - x_max : prec);\n          x_max++;\n        }\n      else if (x_max < 0)\n        {\n          ld_max = 1;\n          rd_max = (prec > x_max ? prec - x_max : prec);\n          x_max = -x_max + 1;\n        }\n      else\n        {\n          ld_max = 1;\n          rd_max = (prec > 1 ? prec - 1 : prec);\n          x_max = 1;\n        }\n\n      int ld_min, rd_min;\n      if (x_min > 0)\n        {\n          ld_min = x_min;\n          rd_min = (prec > x_min ? prec - x_min : prec);\n          x_min++;\n        }\n      else if (x_min < 0)\n        {\n          ld_min = 1;\n          rd_min = (prec > x_min ? prec - x_min : prec);\n          x_min = -x_min + 1;\n        }\n      else\n        {\n          ld_min = 1;\n          rd_min = (prec > 1 ? prec - 1 : prec);\n          x_min = 1;\n        }\n\n      ld = (ld_max > ld_min ? ld_max : ld_min);\n      rd = (rd_max > rd_min ? rd_max : rd_min);\n\n      i_fw = ld + 1 + rd;\n      r_fw = i_fw + 1;\n      if (inf_or_nan && i_fw < 3)\n        {\n          i_fw = 3;\n          r_fw = 4;\n        }\n    }\n\n  if (! (rat_format || bank_format || hex_format || bit_format)\n      && (print_e || print_eng || print_g\n          || ld + rd > pr_output_traits<T>::DIGITS10\n          || r_fw > pr_output_traits<T>::MAX_FIELD_WIDTH\n          || i_fw > pr_output_traits<T>::MAX_FIELD_WIDTH\n          || ld + rd > (1.5 * prec)))\n    {\n      if (print_g)\n        {\n          int width = prec + 6;\n          r_fmt = float_format (width, prec);\n          i_fmt = float_format (width, prec);\n        }\n      else\n        {\n          int ex = 4;\n          if (x_max > 100 || x_min > 100)\n            ex++;\n\n          if (print_eng)\n            {\n              i_fw = 3 + prec + ex;\n              r_fw = i_fw + 1;\n              if (inf_or_nan && i_fw < 5)\n                {\n                  i_fw = 5;\n                  r_fw = 6;\n                }\n              r_fmt = float_format (r_fw, ex, prec - 1, std::ios::fixed);\n              i_fmt = float_format (i_fw, ex, prec - 1, std::ios::fixed);\n            }\n          else\n            {\n              i_fw = 1 + prec + ex;\n              r_fw = i_fw + 1;\n              if (inf_or_nan && i_fw < 3)\n                {\n                  i_fw = 3;\n                  r_fw = 4;\n                }\n              r_fmt = float_format (r_fw, prec - 1, std::ios::scientific);\n              i_fmt = float_format (i_fw, prec - 1, std::ios::scientific);\n            }\n        }\n\n      if (uppercase_format)\n        {\n          r_fmt.uppercase ();\n          i_fmt.uppercase ();\n        }\n    }\n  else if (! bank_format && int_only)\n    {\n      r_fmt = float_format (r_fw, ld);\n      i_fmt = float_format (i_fw, ld);\n    }\n  else\n    {\n      r_fmt = float_format (r_fw, rd, std::ios::fixed);\n      i_fmt = float_format (i_fw, rd, std::ios::fixed);\n    }\n\n  return float_display_format (r_fmt, i_fmt);\n}\n\ntemplate <typename T>\nfloat_display_format\nmake_complex_scalar_format (const std::complex<T>& c)\n{\n  if (free_format)\n    return float_display_format ();\n\n  T rp = c.real ();\n  T ip = c.imag ();\n\n  bool r_inf_or_nan = (octave::math::isinf (rp) || octave::math::isnan (rp));\n  bool i_inf_or_nan = (octave::math::isinf (ip) || octave::math::isnan (ip));\n  bool inf_or_nan = r_inf_or_nan || i_inf_or_nan;\n\n  bool int_only = ((r_inf_or_nan || octave::math::is_integer (rp))\n                   && (i_inf_or_nan || octave::math::is_integer (ip)));\n\n  T r_abs = (rp < 0 ? -rp : rp);\n  T i_abs = (ip < 0 ? -ip : ip);\n\n  int r_x = ((r_inf_or_nan || r_abs == 0) ? 0 : num_digits (r_abs));\n  int i_x = ((i_inf_or_nan || i_abs == 0) ? 0 : num_digits (i_abs));\n\n  int x_max, x_min;\n\n  if (r_x > i_x)\n    {\n      x_max = r_x;\n      x_min = i_x;\n    }\n  else\n    {\n      x_max = i_x;\n      x_min = r_x;\n    }\n\n  return make_complex_format<T> (x_max, x_min, r_x, inf_or_nan, int_only);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const std::complex<double>& c)\n{\n  return make_complex_scalar_format (c);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const std::complex<float>& fc)\n{\n  return make_complex_scalar_format (fc);\n}\n\ntemplate <typename T>\nstatic inline float_display_format\nmake_complex_matrix_format (int x_max, int x_min, int r_x_max,\n                            int r_x_min, bool inf_or_nan,\n                            int int_or_inf_or_nan)\n{\n  T scale = ((x_max == 0 || int_or_inf_or_nan)\n             ? 1 : std::pow (10.0, calc_scale_exp (x_max - 1)));\n\n  float_format r_fmt;\n  float_format i_fmt;\n\n  int prec = std::min (output_precision (), pr_output_traits<T>::DIGITS10);\n\n  int i_fw = 0, r_fw = 0, ld = 0, rd = 0;\n\n  if (rat_format)\n    {\n      i_fw = 9;\n      r_fw = 9;\n      rd = 0;\n    }\n  else if (bank_format)\n    {\n      int digits = (r_x_max > r_x_min ? r_x_max : r_x_min);\n      i_fw = 0;\n      r_fw = (digits <= 0 ? 5 : digits + 4);\n      rd = 2;\n    }\n  else if (hex_format)\n    {\n      r_fw = 2 * sizeof (T);\n      i_fw = 2 * sizeof (T);\n      rd = 0;\n    }\n  else if (bit_format)\n    {\n      r_fw = 8 * sizeof (T);\n      i_fw = 8 * sizeof (T);\n      rd = 0;\n    }\n  else if (Vfixed_point_format && ! print_g)\n    {\n      rd = prec - 1;\n      i_fw = rd + 1;\n      r_fw = i_fw + 2;\n      if (inf_or_nan && i_fw < 3)\n        {\n          i_fw = 3;\n          r_fw = 4;\n        }\n    }\n  else if (int_or_inf_or_nan)\n    {\n      int digits = (x_max > x_min ? x_max : x_min);\n      i_fw = (digits <= 0 ? 1 : digits);\n      r_fw = i_fw + 1;\n      if (inf_or_nan && i_fw < 3)\n        {\n          i_fw = 3;\n          r_fw = 4;\n        }\n      rd = r_fw;\n    }\n  else\n    {\n      int ld_max, rd_max;\n      if (x_max > 0)\n        {\n          ld_max = x_max;\n          rd_max = (prec > x_max ? prec - x_max : prec);\n          x_max++;\n        }\n      else if (x_max < 0)\n        {\n          ld_max = 1;\n          rd_max = (prec > x_max ? prec - x_max : prec);\n          x_max = -x_max + 1;\n        }\n      else\n        {\n          ld_max = 1;\n          rd_max = (prec > 1 ? prec - 1 : prec);\n          x_max = 1;\n        }\n\n      int ld_min, rd_min;\n      if (x_min > 0)\n        {\n          ld_min = x_min;\n          rd_min = (prec > x_min ? prec - x_min : prec);\n          x_min++;\n        }\n      else if (x_min < 0)\n        {\n          ld_min = 1;\n          rd_min = (prec > x_min ? prec - x_min : prec);\n          x_min = -x_min + 1;\n        }\n      else\n        {\n          ld_min = 1;\n          rd_min = (prec > 1 ? prec - 1 : prec);\n          x_min = 1;\n        }\n\n      ld = (ld_max > ld_min ? ld_max : ld_min);\n      rd = (rd_max > rd_min ? rd_max : rd_min);\n\n      i_fw = ld + 1 + rd;\n      r_fw = i_fw + 1;\n      if (inf_or_nan && i_fw < 3)\n        {\n          i_fw = 3;\n          r_fw = 4;\n        }\n    }\n\n  if (! (rat_format || bank_format || hex_format || bit_format)\n      && (print_e || print_eng || print_g\n          || (! Vfixed_point_format\n              && (ld + rd > pr_output_traits<T>::DIGITS10\n                  || r_fw > pr_output_traits<T>::MAX_FIELD_WIDTH\n                  || i_fw > pr_output_traits<T>::MAX_FIELD_WIDTH\n                  || ld + rd > (1.5 * prec)))))\n    {\n      if (print_g)\n        {\n          int width = prec + 6;\n          r_fmt = float_format (width, prec);\n          i_fmt = float_format (width, prec);\n        }\n      else\n        {\n          int ex = 4;\n          if (x_max > 100 || x_min > 100)\n            ex++;\n\n          if (print_eng)\n            {\n              i_fw = 3 + prec + ex;\n              r_fw = i_fw + 1;\n              if (inf_or_nan && i_fw < 5)\n                {\n                  i_fw = 5;\n                  r_fw = 6;\n                }\n              r_fmt = float_format (r_fw, ex, prec - 1, std::ios::fixed);\n              i_fmt = float_format (i_fw, ex, prec - 1, std::ios::fixed);\n            }\n          else\n            {\n              i_fw = 1 + prec + ex;\n              r_fw = i_fw + 1;\n              if (inf_or_nan && i_fw < 3)\n                {\n                  i_fw = 3;\n                  r_fw = 4;\n                }\n              r_fmt = float_format (r_fw, prec - 1, std::ios::scientific);\n              i_fmt = float_format (i_fw, prec - 1, std::ios::scientific);\n            }\n        }\n\n      if (uppercase_format)\n        {\n          r_fmt.uppercase ();\n          i_fmt.uppercase ();\n        }\n    }\n  else if (! bank_format && int_or_inf_or_nan)\n    {\n      r_fmt = float_format (r_fw, rd);\n      i_fmt = float_format (i_fw, rd);\n    }\n  else\n    {\n      r_fmt = float_format (r_fw, rd, std::ios::fixed);\n      i_fmt = float_format (i_fw, rd, std::ios::fixed);\n    }\n\n  return float_display_format (scale, r_fmt, i_fmt);\n}\n\ntemplate <typename CMT>\nstatic inline float_display_format\nmake_complex_matrix_format (const CMT& cm)\n{\n  if (free_format)\n    return float_display_format ();\n\n  typedef typename CMT::real_matrix_type RMT;\n  typedef typename CMT::real_elt_type ELT_T;\n\n  RMT rp = real (cm);\n  RMT ip = imag (cm);\n\n  bool inf_or_nan = cm.any_element_is_inf_or_nan ();\n\n  bool int_or_inf_or_nan = (rp.all_elements_are_int_or_inf_or_nan ()\n                            && ip.all_elements_are_int_or_inf_or_nan ());\n\n  RMT r_m_abs = rp.abs ();\n  ELT_T r_max_abs = pr_max_internal (r_m_abs);\n  ELT_T r_min_abs = pr_min_internal (r_m_abs);\n\n  RMT i_m_abs = ip.abs ();\n  ELT_T i_max_abs = pr_max_internal (i_m_abs);\n  ELT_T i_min_abs = pr_min_internal (i_m_abs);\n\n  int r_x_max = ((r_max_abs == 0 || octave::math::isinf (r_max_abs)\n                  || octave::math::isnan (r_max_abs))\n                 ? 0 : num_digits (r_max_abs));\n\n  int r_x_min = ((r_min_abs == 0 || octave::math::isinf (r_min_abs)\n                  || octave::math::isnan (r_min_abs))\n                 ? 0 : num_digits (r_min_abs));\n\n  int i_x_max = ((i_max_abs == 0 || octave::math::isinf (i_max_abs)\n                  || octave::math::isnan (i_max_abs))\n                 ? 0 : num_digits (i_max_abs));\n\n  int i_x_min = ((i_min_abs == 0 || octave::math::isinf (i_min_abs)\n                  || octave::math::isnan (i_min_abs))\n                 ? 0 : num_digits (i_min_abs));\n\n  int x_max = (r_x_max > i_x_max ? r_x_max : i_x_max);\n  int x_min = (r_x_min > i_x_min ? r_x_min : i_x_min);\n\n  return make_complex_matrix_format<ELT_T> (x_max, x_min, r_x_max, r_x_min,\n         inf_or_nan, int_or_inf_or_nan);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const ComplexMatrix& cm)\n{\n  return make_complex_matrix_format (cm);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const FloatComplexMatrix& cm)\n{\n  return make_complex_matrix_format (cm);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const boolNDArray&)\n{\n  return float_display_format (float_format (1, 1));\n}\n\ntemplate <typename T>\nstatic inline float_display_format\nmake_range_format (int x_max, int x_min, int all_ints)\n{\n  double scale = ((x_max == 0 || all_ints)\n                  ? 1 : std::pow (10.0, calc_scale_exp (x_max - 1)));\n\n  float_format fmt;\n\n  int prec = std::min (output_precision (), pr_output_traits<T>::DIGITS10);\n\n  int fw = 0, ld = 0, rd = 0;\n\n  if (rat_format)\n    {\n      fw = 9;\n      rd = 0;\n    }\n  else if (bank_format)\n    {\n      int digits = (x_max > x_min ? x_max : x_min);\n      fw = (digits < 0 ? 5 : digits + 4);\n      rd = 2;\n    }\n  else if (hex_format)\n    {\n      fw = 2 * sizeof (T);\n      rd = 0;\n    }\n  else if (bit_format)\n    {\n      fw = 8 * sizeof (T);\n      rd = 0;\n    }\n  else if (all_ints)\n    {\n      int digits = (x_max > x_min ? x_max : x_min);\n      fw = digits + 1;\n      rd = fw;\n    }\n  else if (Vfixed_point_format && ! print_g)\n    {\n      rd = prec - 1;\n      fw = rd + 3;\n    }\n  else\n    {\n      int ld_max, rd_max;\n      if (x_max > 0)\n        {\n          ld_max = x_max;\n          rd_max = (prec > x_max ? prec - x_max : prec);\n          x_max++;\n        }\n      else if (x_max < 0)\n        {\n          ld_max = 1;\n          rd_max = (prec > x_max ? prec - x_max : prec);\n          x_max = -x_max + 1;\n        }\n      else\n        {\n          ld_max = 1;\n          rd_max = (prec > 1 ? prec - 1 : prec);\n          x_max = 1;\n        }\n\n      int ld_min, rd_min;\n      if (x_min > 0)\n        {\n          ld_min = x_min;\n          rd_min = (prec > x_min ? prec - x_min : prec);\n          x_min++;\n        }\n      else if (x_min < 0)\n        {\n          ld_min = 1;\n          rd_min = (prec > x_min ? prec - x_min : prec);\n          x_min = -x_min + 1;\n        }\n      else\n        {\n          ld_min = 1;\n          rd_min = (prec > 1 ? prec - 1 : prec);\n          x_min = 1;\n        }\n\n      ld = (ld_max > ld_min ? ld_max : ld_min);\n      rd = (rd_max > rd_min ? rd_max : rd_min);\n\n      fw = ld + rd + 3;\n    }\n\n  if (! (rat_format || bank_format || hex_format || bit_format)\n      && (print_e || print_eng || print_g\n          || (! Vfixed_point_format\n              && (ld + rd > pr_output_traits<T>::DIGITS10\n                  || fw > pr_output_traits<T>::MAX_FIELD_WIDTH\n                  || ld + rd > (1.5 * prec)))))\n    {\n      if (print_g)\n        fmt = float_format (prec+6, prec);\n      else\n        {\n          int ex = 4;\n          if (x_max > 100 || x_min > 100)\n            ex++;\n\n          if (print_eng)\n            {\n              fw = 5 + prec + ex;\n              fmt = float_format (fw, ex, prec - 1, std::ios::fixed);\n            }\n          else\n            {\n              fw = 3 + prec + ex;\n              fmt = float_format (fw, prec - 1, std::ios::scientific);\n            }\n        }\n    }\n  else if (! bank_format && all_ints)\n    fmt = float_format (fw, rd);\n  else\n    fmt = float_format (fw, rd, std::ios::fixed);\n\n  if (uppercase_format)\n    fmt.uppercase ();\n\n  return float_display_format (scale, fmt);\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const octave::range<double>& r)\n{\n  if (free_format)\n    return float_display_format ();\n\n  double r_min = r.base ();\n  double r_max = r.limit ();\n\n  if (r_max < r_min)\n    {\n      double tmp = r_max;\n      r_max = r_min;\n      r_min = tmp;\n    }\n\n  bool all_ints = r.all_elements_are_ints ();\n\n  double max_abs = (r_max < 0 ? -r_max : r_max);\n  double min_abs = (r_min < 0 ? -r_min : r_min);\n\n  int x_max = ((max_abs == 0 || octave::math::isinf (max_abs)\n                || octave::math::isnan (max_abs))\n               ? 0 : num_digits (max_abs));\n\n  int x_min = ((min_abs == 0 || octave::math::isinf (min_abs)\n                || octave::math::isnan (min_abs))\n               ? 0 : num_digits (min_abs));\n\n  return make_range_format<double> (x_max, x_min, all_ints);\n}\n\ntemplate <typename T>\nunion equiv\n{\n  T val;\n  unsigned char i[sizeof (T)];\n};\n\n#define PRINT_CHAR_BITS(os, c)                  \\\n  do                                            \\\n    {                                           \\\n      unsigned char ctmp = c;                   \\\n      char stmp[9];                             \\\n      stmp[0] = (ctmp & 0x80) ? '1' : '0';      \\\n      stmp[1] = (ctmp & 0x40) ? '1' : '0';      \\\n      stmp[2] = (ctmp & 0x20) ? '1' : '0';      \\\n      stmp[3] = (ctmp & 0x10) ? '1' : '0';      \\\n      stmp[4] = (ctmp & 0x08) ? '1' : '0';      \\\n      stmp[5] = (ctmp & 0x04) ? '1' : '0';      \\\n      stmp[6] = (ctmp & 0x02) ? '1' : '0';      \\\n      stmp[7] = (ctmp & 0x01) ? '1' : '0';      \\\n      stmp[8] = '\\0';                           \\\n      os << stmp;                               \\\n    }                                           \\\n  while (0)\n\n#define PRINT_CHAR_BITS_SWAPPED(os, c)          \\\n  do                                            \\\n    {                                           \\\n      unsigned char ctmp = c;                   \\\n      char stmp[9];                             \\\n      stmp[0] = (ctmp & 0x01) ? '1' : '0';      \\\n      stmp[1] = (ctmp & 0x02) ? '1' : '0';      \\\n      stmp[2] = (ctmp & 0x04) ? '1' : '0';      \\\n      stmp[3] = (ctmp & 0x08) ? '1' : '0';      \\\n      stmp[4] = (ctmp & 0x10) ? '1' : '0';      \\\n      stmp[5] = (ctmp & 0x20) ? '1' : '0';      \\\n      stmp[6] = (ctmp & 0x40) ? '1' : '0';      \\\n      stmp[7] = (ctmp & 0x80) ? '1' : '0';      \\\n      stmp[8] = '\\0';                           \\\n      os << stmp;                               \\\n    }                                           \\\n  while (0)\n\ntemplate <typename T>\nstatic inline void\npr_any_float (std::ostream& os, const float_format& fmt, T val)\n{\n  // Unless explicitly asked for, always print in big-endian format\n  // for hex and bit formats.\n  //\n  //   {bit,hex}_format == 1: print big-endian\n  //   {bit,hex}_format == 2: print native\n\n  int fw = fmt.width ();\n\n  if (hex_format)\n    {\n      octave::preserve_stream_state stream_state (os);\n\n      equiv<T> tmp;\n      tmp.val = val;\n\n      // Unless explicitly asked for, always print in big-endian format.\n\n      // FIXME: Will bad things happen if we are interrupted before resetting\n      //        the format flags and fill character?\n\n      octave::mach_info::float_format flt_fmt\n        = octave::mach_info::native_float_format ();\n\n      os.fill ('0');\n      if (uppercase_format)\n        os.flags (std::ios::right | std::ios::hex | std::ios::uppercase);\n      else\n        os.flags (std::ios::right | std::ios::hex);\n\n      if (hex_format > 1\n          || flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian)\n        {\n          for (std::size_t i = 0; i < sizeof (T); i++)\n            os << std::setw (2) << static_cast<int> (tmp.i[i]);\n        }\n      else\n        {\n          for (int i = sizeof (T) - 1; i >= 0; i--)\n            os << std::setw (2) << static_cast<int> (tmp.i[i]);\n        }\n    }\n  else if (bit_format)\n    {\n      equiv<T> tmp;\n      tmp.val = val;\n\n      octave::mach_info::float_format flt_fmt\n        = octave::mach_info::native_float_format ();\n\n      if (flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian)\n        {\n          for (std::size_t i = 0; i < sizeof (T); i++)\n            PRINT_CHAR_BITS (os, tmp.i[i]);\n        }\n      else\n        {\n          if (bit_format > 1)\n            {\n              for (std::size_t i = 0; i < sizeof (T); i++)\n                PRINT_CHAR_BITS (os, tmp.i[i]);\n            }\n          else\n            {\n              for (int i = sizeof (T) - 1; i >= 0; i--)\n                PRINT_CHAR_BITS (os, tmp.i[i]);\n            }\n        }\n    }\n  else if (val == 0)\n    {\n      octave::preserve_stream_state stream_state (os);\n\n      if (fw > 0)\n        os << std::setw (fw) << \"0\";\n      else\n        os << \"0\";\n    }\n  else if (octave::math::isna (val))\n    {\n      octave::preserve_stream_state stream_state (os);\n\n      if (fw > 0)\n        os << std::setw (fw) << \"NA\";\n      else\n        os << \"NA\";\n    }\n  else if (rat_format)\n    os << pr_rational_float<T> (fmt, val);\n  else if (octave::math::isinf (val))\n    {\n      octave::preserve_stream_state stream_state (os);\n\n      const char *s;\n      if (val < 0)\n        s = \"-Inf\";\n      else\n        s = \"Inf\";\n\n      if (fw > 0)\n        os << std::setw (fw) << s;\n      else\n        os << s;\n    }\n  else if (octave::math::isnan (val))\n    {\n      octave::preserve_stream_state stream_state (os);\n\n      if (fw > 0)\n        os << std::setw (fw) << \"NaN\";\n      else\n        os << \"NaN\";\n    }\n  else if (print_eng)\n    os << pr_engineering_float<T> (fmt, val);\n  else\n    os << pr_formatted_float<T> (fmt, val);\n}\n\ntemplate <typename T>\nstatic inline void\npr_float (std::ostream& os, const float_display_format& fmt, T val)\n{\n  double scale = fmt.scale_factor ();\n\n  if (Vfixed_point_format && ! (print_g || print_e) && scale != 1)\n    val /= scale;\n\n  pr_any_float (os, fmt.real_format (), val);\n}\n\ntemplate <typename T>\nstatic inline void\npr_imag_float (std::ostream& os, const float_display_format& fmt, T val)\n{\n  double scale = fmt.scale_factor ();\n\n  if (Vfixed_point_format && ! (print_g || print_e) && scale != 1)\n    val /= scale;\n\n  pr_any_float (os, fmt.imag_format (), val);\n}\n\ntemplate <typename T>\nstatic inline void\npr_float (std::ostream& os, const float_display_format& fmt,\n          const std::complex<T>& cval)\n{\n  T r = cval.real ();\n\n  pr_float (os, fmt, r);\n\n  if (! bank_format)\n    {\n      T i = cval.imag ();\n      if (! (hex_format || bit_format) && std::signbit (i))\n        {\n          os << \" - \";\n          i = -i;\n          pr_imag_float (os, fmt, i);\n        }\n      else\n        {\n          if (hex_format || bit_format)\n            os << \"  \";\n          else\n            os << \" + \";\n\n          pr_imag_float (os, fmt, i);\n        }\n      os << 'i';\n    }\n}\n\nstatic inline void\nprint_empty_matrix (std::ostream& os, octave_idx_type nr, octave_idx_type nc,\n                    bool pr_as_read_syntax)\n{\n  panic_unless (nr == 0 || nc == 0);\n\n  if (pr_as_read_syntax)\n    {\n      if (nr == 0 && nc == 0)\n        os << \"[]\";\n      else\n        os << \"zeros (\" << nr << \", \" << nc << ')';\n    }\n  else\n    {\n      os << \"[]\";\n\n      if (Vprint_empty_dimensions)\n        os << '(' << nr << 'x' << nc << ')';\n    }\n}\n\nstatic inline void\nprint_empty_nd_array (std::ostream& os, const dim_vector& dims,\n                      bool pr_as_read_syntax)\n{\n  panic_unless (dims.any_zero ());\n\n  if (pr_as_read_syntax)\n    os << \"zeros (\" << dims.str (',') << ')';\n  else\n    {\n      os << \"[]\";\n\n      if (Vprint_empty_dimensions)\n        os << '(' << dims.str () << ')';\n    }\n}\n\nstatic inline void\npr_scale_header (std::ostream& os, double scale)\n{\n  if (Vfixed_point_format && ! (print_g || print_e) && scale != 1)\n    {\n      octave::preserve_stream_state stream_state (os);\n\n      os << \"  \"\n         << std::setw (8) << std::setprecision (1)\n         << std::setiosflags (std::ios::scientific | std::ios::left)\n         << scale\n         << \"*\\n\";\n\n      if (! Vcompact_format)\n        os << \"\\n\";\n    }\n}\n\nstatic inline void\npr_col_num_header (std::ostream& os, octave_idx_type total_width, int max_width,\n                   octave_idx_type lim, octave_idx_type col, int extra_indent)\n{\n  if (total_width > max_width && Vsplit_long_rows)\n    {\n      octave::preserve_stream_state stream_state (os);\n\n      if (col != 0)\n        {\n          if (Vcompact_format)\n            os << \"\\n\";\n          else\n            os << \"\\n\\n\";\n        }\n\n      octave_idx_type num_cols = lim - col;\n\n      os << std::setw (extra_indent) << \"\";\n\n      if (num_cols == 1)\n        os << \" Column \" << col + 1 << \":\\n\";\n      else if (num_cols == 2)\n        os << \" Columns \" << col + 1 << \" and \" << lim << \":\\n\";\n      else\n        os << \" Columns \" << col + 1 << \" through \" << lim << \":\\n\";\n\n      if (! Vcompact_format)\n        os << \"\\n\";\n    }\n}\n\ntemplate <typename T>\nstatic inline void\npr_plus_format (std::ostream& os, const T& val)\n{\n  if (val > T (0))\n    os << plus_format_chars[0];\n  else if (val < T (0))\n    os << plus_format_chars[1];\n  else\n    os << plus_format_chars[2];\n}\n\n// FIXME: all this mess with abs is an attempt to avoid seeing\n//\n//   warning: comparison of unsigned expression < 0 is always false\n//\n// from GCC.  Isn't there a better way?\n\ntemplate <typename T>\nstatic inline T\nabs (T x)\n{\n  return x < 0 ? -x : x;\n}\n\n#define INSTANTIATE_ABS(T)                      \\\n  template T abs (T)\n\nINSTANTIATE_ABS(int8_t);\nINSTANTIATE_ABS(int16_t);\nINSTANTIATE_ABS(int32_t);\nINSTANTIATE_ABS(int64_t);\n\n#define SPECIALIZE_UABS(T)                      \\\n  template <>                                   \\\n  inline T                                      \\\n  abs (T x)                                     \\\n  {                                             \\\n    return x;                                   \\\n  }\n\nSPECIALIZE_UABS(uint8_t)\nSPECIALIZE_UABS(uint16_t)\nSPECIALIZE_UABS(uint32_t)\nSPECIALIZE_UABS(uint64_t)\n\n#define MAKE_INT_MATRIX_FORMAT(TYPE)                                    \\\n  template <>                                                           \\\n  float_display_format                                                  \\\n  make_format (const intNDArray<TYPE>& nda)                             \\\n  {                                                                     \\\n    bool isneg = false;                                                 \\\n    int digits = 0;                                                     \\\n                                                                        \\\n    for (octave_idx_type i = 0; i < nda.numel (); i++)                  \\\n      {                                                                 \\\n        int new_digits                                                  \\\n          = static_cast<int>                                            \\\n          (std::floor (log10 (double (abs (nda(i).value ()))) + 1));  \\\n                                                                        \\\n        if (new_digits > digits)                                        \\\n          digits = new_digits;                                          \\\n                                                                        \\\n        if (! isneg)                                                    \\\n          isneg = (abs (nda(i).value ()) != nda(i).value ());           \\\n      }                                                                 \\\n                                                                        \\\n    return float_display_format (float_format (digits + isneg, 0, 0));  \\\n  }\n\nMAKE_INT_MATRIX_FORMAT (octave_int8)\nMAKE_INT_MATRIX_FORMAT (octave_uint8)\nMAKE_INT_MATRIX_FORMAT (octave_int16)\nMAKE_INT_MATRIX_FORMAT (octave_uint16)\nMAKE_INT_MATRIX_FORMAT (octave_int32)\nMAKE_INT_MATRIX_FORMAT (octave_uint32)\nMAKE_INT_MATRIX_FORMAT (octave_int64)\nMAKE_INT_MATRIX_FORMAT (octave_uint64)\n\n#define MAKE_INT_SCALAR_FORMAT(TYPE)                                    \\\n  template <>                                                           \\\n  float_display_format                                                  \\\n  make_format (const octave_int<TYPE>& val)                             \\\n  {                                                                     \\\n    bool isneg = false;                                                 \\\n    int digits                                                          \\\n      = static_cast<int>                                                \\\n      (std::floor (log10 (double (abs (val.value ()))) + 1));         \\\n                                                                        \\\n    isneg = (abs (val.value ()) != val.value ());                       \\\n                                                                        \\\n    return float_display_format (float_format (digits + isneg, 0, 0));  \\\n  }\n\nMAKE_INT_SCALAR_FORMAT (int8_t)\nMAKE_INT_SCALAR_FORMAT (uint8_t)\nMAKE_INT_SCALAR_FORMAT (int16_t)\nMAKE_INT_SCALAR_FORMAT (uint16_t)\nMAKE_INT_SCALAR_FORMAT (int32_t)\nMAKE_INT_SCALAR_FORMAT (uint32_t)\nMAKE_INT_SCALAR_FORMAT (int64_t)\nMAKE_INT_SCALAR_FORMAT (uint64_t)\n\nvoid\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       bool d, bool pr_as_read_syntax)\n{\n  octave_print_internal (os, fmt, octave_uint8 (d), pr_as_read_syntax);\n}\n\nvoid\noctave_print_internal (std::ostream& os, bool d, bool pr_as_read_syntax)\n{\n  octave_print_internal (os, octave_uint8 (d), pr_as_read_syntax);\n}\n\nvoid\noctave_print_internal (std::ostream&, const float_display_format&,\n                       char, bool)\n{\n  error (\"unexpected call to 'octave_print_internal (std::ostream&, const float_display_format&, char, bool)' - please report this bug\");\n}\n\nvoid\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       double d, bool pr_as_read_syntax)\n{\n  if (pr_as_read_syntax)\n    os << d;\n  else if (plus_format)\n    pr_plus_format (os, d);\n  else\n    {\n      if (free_format)\n        os << d;\n      else\n        pr_float (os, fmt, d);\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       float d, bool pr_as_read_syntax)\n{\n  if (pr_as_read_syntax)\n    os << d;\n  else if (plus_format)\n    pr_plus_format (os, d);\n  else\n    {\n      if (free_format)\n        os << d;\n      else\n        pr_float (os, fmt, d);\n    }\n}\n\ntemplate <typename MT>\nstatic inline void\noctave_print_free (std::ostream& os, const MT& m, bool pr_as_read_syntax)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  if (pr_as_read_syntax)\n    os << \"[\\n\";\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    {\n      for (octave_idx_type j = 0; j < nc; j++)\n        os << ' ' << m.elem (i, j);\n\n      if (i < nr - 1)\n        os << \"\\n\";\n    }\n\n  if (pr_as_read_syntax)\n    os << ']';\n}\n\ntemplate <typename MT>\nstatic inline void\npr_plus_format_matrix (std::ostream& os, const MT& m)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    {\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          pr_plus_format (os, m(i, j));\n        }\n\n      if (i < nr - 1)\n        os << \"\\n\";\n    }\n}\n\nstatic inline int\nget_column_width (const float_display_format& fmt)\n{\n  int r_fw = fmt.real_format().width ();\n  int i_fw = fmt.imag_format().width ();\n\n  int retval = r_fw + i_fw + 2;\n\n  if (i_fw && ! (rat_format || bank_format || hex_format || bit_format))\n    retval += 5;\n\n  return retval;\n}\n\ntemplate <typename MT>\nstatic void\noctave_print_matrix_internal (std::ostream& os, const MT& m,\n                              bool pr_as_read_syntax, int extra_indent)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  if (nr == 0 || nc == 0)\n    print_empty_matrix (os, nr, nc, pr_as_read_syntax);\n  else if (plus_format && ! pr_as_read_syntax)\n    pr_plus_format_matrix (os, m);\n  else\n    {\n      float_display_format fmt = make_format (m);\n      int column_width = get_column_width (fmt);\n      octave_idx_type total_width = nc * column_width;\n      octave_idx_type max_width = octave::command_editor::terminal_cols ();\n\n      if (pr_as_read_syntax)\n        max_width -= 4;\n      else\n        max_width -= extra_indent;\n\n      if (max_width < 0)\n        max_width = 0;\n\n      if (free_format)\n        {\n          octave_print_free (os, m, pr_as_read_syntax);\n          return;\n        }\n\n      octave_idx_type inc = nc;\n      if (total_width > max_width && Vsplit_long_rows)\n        {\n          inc = max_width / column_width;\n          if (inc == 0)\n            inc++;\n        }\n\n      if (pr_as_read_syntax)\n        {\n          for (octave_idx_type i = 0; i < nr; i++)\n            {\n              octave_idx_type col = 0;\n              while (col < nc)\n                {\n                  octave_idx_type lim = (col + inc < nc ? col + inc : nc);\n\n                  for (octave_idx_type j = col; j < lim; j++)\n                    {\n                      octave_quit ();\n\n                      if (i == 0 && j == 0)\n                        os << \"[ \";\n                      else\n                        {\n                          if (j > col)\n                            os << \", \";\n                          else\n                            os << \"  \";\n                        }\n\n                      pr_float (os, fmt, m(i, j));\n                    }\n\n                  col += inc;\n\n                  if (col >= nc)\n                    {\n                      if (i == nr - 1)\n                        os << \" ]\";\n                      else\n                        os << \";\\n\";\n                    }\n                  else\n                    os << \" ...\\n\";\n                }\n            }\n        }\n      else\n        {\n          octave::preserve_stream_state stream_state (os);\n\n          pr_scale_header (os, fmt.scale_factor ());\n\n          for (octave_idx_type col = 0; col < nc; col += inc)\n            {\n              octave_idx_type lim = (col + inc < nc ? col + inc : nc);\n\n              pr_col_num_header (os, total_width, max_width, lim, col,\n                                 extra_indent);\n\n              for (octave_idx_type i = 0; i < nr; i++)\n                {\n                  os << std::setw (extra_indent) << \"\";\n\n                  for (octave_idx_type j = col; j < lim; j++)\n                    {\n                      octave_quit ();\n\n                      os << \"  \";\n\n                      pr_float (os, fmt, m(i, j));\n                    }\n\n                  if (i < nr - 1)\n                    os << \"\\n\";\n                }\n            }\n        }\n    }\n}\n\ntemplate <typename DMT>\nstatic void\noctave_print_diag_matrix_internal (std::ostream& os, const DMT& m,\n                                   bool pr_as_read_syntax, int extra_indent)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  if (nr == 0 || nc == 0)\n    print_empty_matrix (os, nr, nc, pr_as_read_syntax);\n  else if (plus_format && ! pr_as_read_syntax)\n    pr_plus_format_matrix (os, m);\n  else\n    {\n      float_display_format fmt\n        = make_format (typename DMT::full_matrix_type (m.diag ()));\n      int column_width = get_column_width (fmt);\n      octave_idx_type total_width = nc * column_width;\n      octave_idx_type max_width = octave::command_editor::terminal_cols ();\n\n      if (pr_as_read_syntax)\n        max_width -= 4;\n      else\n        max_width -= extra_indent;\n\n      if (max_width < 0)\n        max_width = 0;\n\n      if (free_format)\n        {\n          octave_print_free (os, m, pr_as_read_syntax);\n          return;\n        }\n\n      octave_idx_type inc = nc;\n      if (total_width > max_width && Vsplit_long_rows)\n        {\n          inc = max_width / column_width;\n          if (inc == 0)\n            inc++;\n        }\n\n      if (pr_as_read_syntax)\n        {\n          os << \"diag (\";\n\n          octave_idx_type col = 0;\n          while (col < nc)\n            {\n              octave_idx_type lim = (col + inc < nc ? col + inc : nc);\n\n              for (octave_idx_type j = col; j < lim; j++)\n                {\n                  octave_quit ();\n\n                  if (j == 0)\n                    os << \"[ \";\n                  else\n                    {\n                      if (j > col)\n                        os << \", \";\n                      else\n                        os << \"  \";\n                    }\n\n                  pr_float (os, fmt, m(j, j));\n                }\n\n              col += inc;\n\n              if (col >= nc)\n                os << \" ]\";\n              else\n                os << \" ...\\n\";\n            }\n          os << ')';\n        }\n      else\n        {\n          octave::preserve_stream_state stream_state (os);\n\n          os << \"Diagonal Matrix\\n\";\n          if (! Vcompact_format)\n            os << \"\\n\";\n\n          pr_scale_header (os, fmt.scale_factor ());\n\n          // kluge.  Get the true width of a number.\n          int zero_fw;\n          {\n            std::ostringstream tmp_oss;\n            typename DMT::element_type zero = 0;\n            pr_float (tmp_oss, fmt, zero);\n            zero_fw = tmp_oss.str ().length ();\n          }\n\n          for (octave_idx_type col = 0; col < nc; col += inc)\n            {\n              octave_idx_type lim = (col + inc < nc ? col + inc : nc);\n\n              pr_col_num_header (os, total_width, max_width, lim, col,\n                                 extra_indent);\n\n              for (octave_idx_type i = 0; i < nr; i++)\n                {\n                  os << std::setw (extra_indent) << \"\";\n\n                  for (octave_idx_type j = col; j < lim; j++)\n                    {\n                      octave_quit ();\n\n                      os << \"  \";\n\n                      if (i == j)\n                        pr_float (os, fmt, m(i, j));\n                      else\n                        os << std::setw (zero_fw) << '0';\n                    }\n\n                  if (i < nr - 1)\n                    os << \"\\n\";\n                }\n            }\n        }\n    }\n}\n\ntemplate <typename NDA_T, typename ELT_T, typename MAT_T>\nvoid\nprint_nd_array (std::ostream& os, const NDA_T& nda,\n                bool pr_as_read_syntax)\n{\n\n  if (nda.isempty ())\n    print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);\n  else\n    {\n\n      int ndims = nda.ndims ();\n\n      const dim_vector& dims = nda.dims ();\n\n      Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);\n\n      octave_idx_type m = 1;\n\n      for (int i = 2; i < ndims; i++)\n        m *= dims(i);\n\n      octave_idx_type nr = dims(0);\n      octave_idx_type nc = dims(1);\n\n      for (octave_idx_type i = 0; i < m; i++)\n        {\n          octave_quit ();\n\n          std::string nm = \"ans\";\n\n          if (m > 1)\n            {\n              nm += \"(:,:,\";\n\n              std::ostringstream buf;\n\n              for (int k = 2; k < ndims; k++)\n                {\n                  buf << ra_idx(k) + 1;\n\n                  if (k < ndims - 1)\n                    buf << ',';\n                  else\n                    buf << ')';\n                }\n\n              nm += buf.str ();\n            }\n\n          Array<octave::idx_vector> idx (dim_vector (ndims, 1));\n\n          idx(0) = octave::idx_vector (':');\n          idx(1) = octave::idx_vector (':');\n\n          for (int k = 2; k < ndims; k++)\n            idx(k) = octave::idx_vector (ra_idx(k));\n\n          octave_value page\n            = MAT_T (Array<ELT_T> (nda.index (idx), dim_vector (nr, nc)));\n\n          if (i != m - 1)\n            {\n              page.print_with_name (os, nm);\n            }\n          else\n            {\n              page.print_name_tag (os, nm);\n              page.print_raw (os);\n            }\n\n          NDA_T::increment_index (ra_idx, dims, 2);\n        }\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const NDArray& nda,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  switch (nda.ndims ())\n    {\n    case 1:\n    case 2:\n      octave_print_internal (os, Matrix (nda),\n                             pr_as_read_syntax, extra_indent);\n      break;\n\n    default:\n      print_nd_array<NDArray, double, Matrix> (os, nda, pr_as_read_syntax);\n      break;\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const FloatNDArray& nda,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  switch (nda.ndims ())\n    {\n    case 1:\n    case 2:\n      octave_print_internal (os, FloatMatrix (nda),\n                             pr_as_read_syntax, extra_indent);\n      break;\n\n    default:\n      print_nd_array<FloatNDArray, float, FloatMatrix> (os, nda, pr_as_read_syntax);\n      break;\n    }\n}\n\ntemplate <typename T>\nstatic inline void\npr_plus_format (std::ostream& os, const std::complex<T>& c)\n{\n  T rp = c.real ();\n  T ip = c.imag ();\n\n  if (rp == 0)\n    {\n      if (ip == 0)\n        os << ' ';\n      else\n        os << 'i';\n    }\n  else if (ip == 0)\n    pr_plus_format (os, rp);\n  else\n    os << 'c';\n}\n\nextern void\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       const Complex& c, bool pr_as_read_syntax)\n{\n  if (pr_as_read_syntax)\n    os << c;\n  else if (plus_format)\n    pr_plus_format (os, c);\n  else\n    {\n      if (free_format)\n        os << c;\n      else\n        pr_float (os, fmt, c);\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       const FloatComplex& c, bool pr_as_read_syntax)\n{\n  if (pr_as_read_syntax)\n    os << c;\n  else if (plus_format)\n    pr_plus_format (os, c);\n  else\n    {\n      if (free_format)\n        os << c;\n      else\n        pr_float (os, fmt, c);\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const PermMatrix& m,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  if (nr == 0 || nc == 0)\n    print_empty_matrix (os, nr, nc, pr_as_read_syntax);\n  else if (plus_format && ! pr_as_read_syntax)\n    pr_plus_format_matrix (os, m);\n  else\n    {\n      int fw = 2;\n      int column_width = fw + 2;\n      octave_idx_type total_width = nc * column_width;\n      octave_idx_type max_width = octave::command_editor::terminal_cols ();\n\n      if (pr_as_read_syntax)\n        max_width -= 4;\n      else\n        max_width -= extra_indent;\n\n      if (max_width < 0)\n        max_width = 0;\n\n      if (free_format)\n        {\n          octave_print_free (os, m, pr_as_read_syntax);\n          return;\n        }\n\n      octave_idx_type inc = nc;\n      if (total_width > max_width && Vsplit_long_rows)\n        {\n          inc = max_width / column_width;\n          if (inc == 0)\n            inc++;\n        }\n\n      if (pr_as_read_syntax)\n        {\n          Array<octave_idx_type> pvec = m.col_perm_vec ();\n\n          os << \"eye (\";\n          os << \":, \";\n\n          octave_idx_type col = 0;\n          while (col < nc)\n            {\n              octave_idx_type lim = (col + inc < nc ? col + inc : nc);\n\n              for (octave_idx_type j = col; j < lim; j++)\n                {\n                  octave_quit ();\n\n                  if (j == 0)\n                    os << \"[ \";\n                  else\n                    {\n                      if (j > col)\n                        os << \", \";\n                      else\n                        os << \"  \";\n                    }\n\n                  os << pvec (j);\n                }\n\n              col += inc;\n\n              if (col >= nc)\n                os << \" ]\";\n              else\n                os << \" ...\\n\";\n            }\n          os << ')';\n        }\n      else\n        {\n          octave::preserve_stream_state stream_state (os);\n\n          os << \"Permutation Matrix\\n\";\n          if (! Vcompact_format)\n            os << \"\\n\";\n\n          for (octave_idx_type col = 0; col < nc; col += inc)\n            {\n              octave_idx_type lim = (col + inc < nc ? col + inc : nc);\n\n              pr_col_num_header (os, total_width, max_width, lim, col,\n                                 extra_indent);\n\n              for (octave_idx_type i = 0; i < nr; i++)\n                {\n                  os << std::setw (extra_indent) << \"\";\n\n                  for (octave_idx_type j = col; j < lim; j++)\n                    {\n                      octave_quit ();\n\n                      os << \"  \";\n\n                      os << std::setw (fw) << m(i, j);\n                    }\n\n                  if (i < nr - 1)\n                    os << \"\\n\";\n                }\n            }\n        }\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const ComplexNDArray& nda,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  switch (nda.ndims ())\n    {\n    case 1:\n    case 2:\n      octave_print_internal (os, ComplexMatrix (nda),\n                             pr_as_read_syntax, extra_indent);\n      break;\n\n    default:\n      print_nd_array<ComplexNDArray, Complex, ComplexMatrix>\n      (os, nda, pr_as_read_syntax);\n      break;\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const FloatComplexNDArray& nda,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  switch (nda.ndims ())\n    {\n    case 1:\n    case 2:\n      octave_print_internal (os, FloatComplexMatrix (nda),\n                             pr_as_read_syntax, extra_indent);\n      break;\n\n    default:\n      print_nd_array<FloatComplexNDArray, FloatComplex, FloatComplexMatrix>\n      (os, nda, pr_as_read_syntax);\n      break;\n    }\n}\n\n// FIXME: write single precision versions of the printing functions.\n\nvoid\noctave_print_internal (std::ostream& os, const Matrix& m,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  octave_print_matrix_internal (os, m, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const FloatMatrix& m,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  octave_print_matrix_internal (os, m, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const DiagMatrix& m,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  octave_print_diag_matrix_internal (os, m, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const FloatDiagMatrix& m,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  octave_print_diag_matrix_internal (os, m, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const ComplexMatrix& cm,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  octave_print_matrix_internal (os, cm, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const FloatComplexMatrix& cm,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  octave_print_matrix_internal (os, cm, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const ComplexDiagMatrix& cm,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  octave_print_diag_matrix_internal (os, cm, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const FloatComplexDiagMatrix& cm,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  octave_print_diag_matrix_internal (os, cm, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const octave::range<double>& r,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  double base = r.base ();\n  double increment = r.increment ();\n  double limit = r.limit ();\n  double final_value = r.final_value ();\n  octave_idx_type num_elem = r.numel ();\n\n  if (plus_format && ! pr_as_read_syntax)\n    pr_plus_format_matrix (os, r);\n  else\n    {\n      float_display_format fmt = make_format (r);\n\n      if (pr_as_read_syntax)\n        {\n          if (free_format)\n            {\n              os << base << \" : \";\n              if (increment != 1)\n                os << increment << \" : \";\n              os << limit;\n            }\n          else\n            {\n              pr_float (os, fmt, base);\n              os << \" : \";\n              if (increment != 1)\n                {\n                  pr_float (os, fmt, increment);\n                  os << \" : \";\n                }\n              pr_float (os, fmt, limit);\n            }\n        }\n      else\n        {\n          octave::preserve_stream_state stream_state (os);\n\n          int column_width = get_column_width (fmt);\n          octave_idx_type total_width = num_elem * column_width;\n          octave_idx_type max_width = octave::command_editor::terminal_cols ();\n\n          if (free_format)\n            {\n              os << ' ';\n              for (octave_idx_type i = 0; i < num_elem; i++)\n                os << ' ' << r.elem (i);\n              return;\n            }\n\n          octave_idx_type inc = num_elem;\n          if (total_width > max_width && Vsplit_long_rows)\n            {\n              inc = max_width / column_width;\n              if (inc == 0)\n                inc++;\n            }\n\n          max_width -= extra_indent;\n\n          if (max_width < 0)\n            max_width = 0;\n\n          pr_scale_header (os, fmt.scale_factor ());\n\n          octave_idx_type col = 0;\n          while (col < num_elem)\n            {\n              octave_idx_type lim = (col + inc < num_elem ? col + inc\n                                     : num_elem);\n\n              pr_col_num_header (os, total_width, max_width, lim, col,\n                                 extra_indent);\n\n              os << std::setw (extra_indent) << \"\";\n\n              for (octave_idx_type i = col; i < lim; i++)\n                {\n                  octave_quit ();\n\n                  double val;\n                  if (i == 0)\n                    val = base;\n                  else\n                    val = base + i * increment;\n\n                  if (i == num_elem - 1)\n                    val = final_value;\n\n                  os << \"  \";\n\n                  pr_float (os, fmt, val);\n                }\n\n              col += inc;\n            }\n        }\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const boolMatrix& bm,\n                       bool pr_as_read_syntax,\n                       int extra_indent)\n{\n  uint8NDArray tmp (bm);\n  octave_print_internal (os, tmp, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const boolNDArray& nda,\n                       bool pr_as_read_syntax,\n                       int extra_indent)\n{\n  switch (nda.ndims ())\n    {\n    case 1:\n    case 2:\n      octave_print_internal (os, boolMatrix (nda),\n                             pr_as_read_syntax, extra_indent);\n      break;\n\n    default:\n      print_nd_array<boolNDArray, bool,\n                     boolMatrix> (os, nda, pr_as_read_syntax);\n      break;\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const charMatrix& chm,\n                       bool pr_as_read_syntax,\n                       int /* FIXME: extra_indent */,\n                       bool pr_as_string)\n{\n  if (pr_as_string)\n    {\n      octave_idx_type nstr = chm.rows ();\n\n      if (pr_as_read_syntax && nstr > 1)\n        os << \"[ \";\n\n      if (nstr != 0)\n        {\n          for (octave_idx_type i = 0; i < nstr; i++)\n            {\n              octave_quit ();\n\n              std::string row = chm.row_as_string (i);\n\n              if (pr_as_read_syntax)\n                {\n                  os << '\"' << octave::undo_string_escapes (row) << '\"';\n\n                  if (i < nstr - 1)\n                    os << \"; \";\n                }\n              else\n                {\n                  os << row;\n\n                  if (i < nstr - 1)\n                    os << \"\\n\";\n                }\n            }\n        }\n\n      if (pr_as_read_syntax && nstr > 1)\n        os << \" ]\";\n    }\n  else\n    {\n      os << \"sorry, printing char matrices not implemented yet\\n\";\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const charNDArray& nda,\n                       bool pr_as_read_syntax, int extra_indent,\n                       bool pr_as_string)\n{\n  switch (nda.ndims ())\n    {\n    case 1:\n    case 2:\n      octave_print_internal (os, charMatrix (nda),\n                             pr_as_read_syntax, extra_indent, pr_as_string);\n      break;\n\n    default:\n      print_nd_array<charNDArray, char, charMatrix> (os, nda,\n                                                     pr_as_read_syntax);\n      break;\n    }\n}\n\nvoid\noctave_print_internal (std::ostream& os, const std::string& s,\n                       bool pr_as_read_syntax, int extra_indent)\n{\n  Array<std::string> nda (dim_vector (1, 1), s);\n\n  octave_print_internal (os, nda, pr_as_read_syntax, extra_indent);\n}\n\nvoid\noctave_print_internal (std::ostream& os, const Array<std::string>& nda,\n                       bool pr_as_read_syntax, int /* extra_indent */)\n{\n  // FIXME: this mostly duplicates the code in the print_nd_array<>\n  // function.  Can fix this with std::is_same from C++11.\n\n  if (nda.isempty ())\n    print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);\n  else if (nda.numel () == 1)\n    {\n      os << nda(0);\n    }\n  else\n    {\n      int ndims = nda.ndims ();\n\n      const dim_vector& dims = nda.dims ();\n\n      Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);\n\n      octave_idx_type m = 1;\n\n      for (int i = 2; i < ndims; i++)\n        m *= dims(i);\n\n      octave_idx_type nr = dims(0);\n      octave_idx_type nc = dims(1);\n\n      for (octave_idx_type i = 0; i < m; i++)\n        {\n          std::string nm = \"ans\";\n\n          if (m > 1)\n            {\n              nm += \"(:,:,\";\n\n              std::ostringstream buf;\n\n              for (int k = 2; k < ndims; k++)\n                {\n                  buf << ra_idx(k) + 1;\n\n                  if (k < ndims - 1)\n                    buf << ',';\n                  else\n                    buf << ')';\n                }\n\n              nm += buf.str ();\n            }\n\n          Array<octave::idx_vector> idx (dim_vector (ndims, 1));\n\n          idx(0) = octave::idx_vector (':');\n          idx(1) = octave::idx_vector (':');\n\n          for (int k = 2; k < ndims; k++)\n            idx(k) = octave::idx_vector (ra_idx(k));\n\n          Array<std::string> page (nda.index (idx), dim_vector (nr, nc));\n\n          // FIXME: need to do some more work to put these\n          //        in neatly aligned columns...\n\n          octave_idx_type n_rows = page.rows ();\n          octave_idx_type n_cols = page.cols ();\n\n          os << nm << \" =\\n\";\n          if (! Vcompact_format)\n            os << \"\\n\";\n\n          for (octave_idx_type ii = 0; ii < n_rows; ii++)\n            {\n              for (octave_idx_type jj = 0; jj < n_cols; jj++)\n                os << \"  \" << page(ii, jj);\n\n              os << \"\\n\";\n            }\n\n          if (i < m - 1)\n            os << \"\\n\";\n\n          increment_index (ra_idx, dims, 2);\n        }\n    }\n}\n\ntemplate <typename T>\nclass octave_print_conv\n{\npublic:\n  typedef T print_conv_type;\n};\n\n#define PRINT_CONV(T1, T2)                      \\\n  template <>                                   \\\n  class                                         \\\n  octave_print_conv<T1>                         \\\n  {                                             \\\n  public:                                       \\\n    typedef T2 print_conv_type;                 \\\n  }\n\nPRINT_CONV (octave_int8, octave_int16);\nPRINT_CONV (octave_uint8, octave_uint16);\n\n#undef PRINT_CONV\n\ntemplate <typename T>\nstatic inline void\npr_int (std::ostream& os, const T& d, int fw = 0)\n{\n  std::size_t sz = d.byte_size ();\n  const unsigned char *tmpi = d.iptr ();\n\n  // Unless explicitly asked for, always print in big-endian\n  // format for hex and bit formats.\n  //\n  //   {bit,hex}_format == 1: print big-endian\n  //   {bit,hex}_format == 2: print native\n\n  if (hex_format)\n    {\n      octave::preserve_stream_state stream_state (os);\n\n      os.fill ('0');\n      if (uppercase_format)\n        os.flags (std::ios::right | std::ios::hex | std::ios::uppercase);\n      else\n        os.flags (std::ios::right | std::ios::hex);\n\n      if (hex_format > 1 || octave::mach_info::words_big_endian ())\n        {\n          for (std::size_t i = 0; i < sz; i++)\n            os << std::setw (2) << static_cast<int> (tmpi[i]);\n        }\n      else\n        {\n          for (int i = sz - 1; i >= 0; i--)\n            os << std::setw (2) << static_cast<int> (tmpi[i]);\n        }\n    }\n  else if (bit_format)\n    {\n      if (octave::mach_info::words_big_endian ())\n        {\n          for (std::size_t i = 0; i < sz; i++)\n            PRINT_CHAR_BITS (os, tmpi[i]);\n        }\n      else\n        {\n          if (bit_format > 1)\n            {\n              for (std::size_t i = 0; i < sz; i++)\n                PRINT_CHAR_BITS (os, tmpi[i]);\n            }\n          else\n            {\n              for (int i = sz - 1; i >= 0; i--)\n                PRINT_CHAR_BITS (os, tmpi[i]);\n            }\n        }\n    }\n  else\n    {\n      octave::preserve_stream_state stream_state (os);\n\n      os << std::setw (fw)\n         << typename octave_print_conv<T>::print_conv_type (d);\n\n      if (bank_format)\n        os << \".00\";\n    }\n}\n\ntemplate void\npr_int (std::ostream&, const octave_int8&, int);\n\ntemplate void\npr_int (std::ostream&, const octave_int16&, int);\n\ntemplate void\npr_int (std::ostream&, const octave_int32&, int);\n\ntemplate void\npr_int (std::ostream&, const octave_int64&, int);\n\ntemplate void\npr_int (std::ostream&, const octave_uint8&, int);\n\ntemplate void\npr_int (std::ostream&, const octave_uint16&, int);\n\ntemplate void\npr_int (std::ostream&, const octave_uint32&, int);\n\ntemplate void\npr_int (std::ostream&, const octave_uint64&, int);\n\ntemplate <typename T>\nvoid\noctave_print_internal_template (std::ostream& os,\n                                const float_display_format& fmt,\n                                const octave_int<T>& val, bool)\n{\n  if (plus_format)\n    pr_plus_format (os, val);\n  else\n    {\n      if (free_format)\n        os << typename octave_print_conv<octave_int<T>>::print_conv_type (val);\n      else\n        {\n          float_format r_fmt = fmt.real_format ();\n\n          pr_int (os, val, r_fmt.width ());\n        }\n    }\n}\n\n#define PRINT_INT_SCALAR_INTERNAL(TYPE)                                 \\\n  void                                                                  \\\n  octave_print_internal (std::ostream& os,                              \\\n                         const float_display_format& fmt,               \\\n                         const octave_int<TYPE>& val, bool dummy)       \\\n  {                                                                     \\\n    octave_print_internal_template (os, fmt, val, dummy);               \\\n  }\n\nPRINT_INT_SCALAR_INTERNAL (int8_t)\nPRINT_INT_SCALAR_INTERNAL (uint8_t)\nPRINT_INT_SCALAR_INTERNAL (int16_t)\nPRINT_INT_SCALAR_INTERNAL (uint16_t)\nPRINT_INT_SCALAR_INTERNAL (int32_t)\nPRINT_INT_SCALAR_INTERNAL (uint32_t)\nPRINT_INT_SCALAR_INTERNAL (int64_t)\nPRINT_INT_SCALAR_INTERNAL (uint64_t)\n\ntemplate <typename T>\nstatic inline void\noctave_print_internal_template (std::ostream& os, const intNDArray<T>& nda,\n                                bool pr_as_read_syntax, int extra_indent)\n{\n  // FIXME: this mostly duplicates the code in the print_nd_array<>\n  // function.  Can fix this with std::is_same from C++11.\n\n  if (nda.isempty ())\n    print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);\n  else if (nda.numel () == 1)\n    octave_print_internal_template (os, float_display_format (), nda(0),\n                                    pr_as_read_syntax);\n  else if (plus_format && ! pr_as_read_syntax)\n    {\n      int ndims = nda.ndims ();\n\n      Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);\n\n      const dim_vector& dims = nda.dims ();\n\n      octave_idx_type m = 1;\n\n      for (int i = 2; i < ndims; i++)\n        m *= dims(i);\n\n      octave_idx_type nr = dims(0);\n      octave_idx_type nc = dims(1);\n\n      for (octave_idx_type i = 0; i < m; i++)\n        {\n          if (m > 1)\n            {\n              std::string nm = \"ans(:,:,\";\n\n              std::ostringstream buf;\n\n              for (int k = 2; k < ndims; k++)\n                {\n                  buf << ra_idx(k) + 1;\n\n                  if (k < ndims - 1)\n                    buf << ',';\n                  else\n                    buf << ')';\n                }\n\n              nm += buf.str ();\n\n              os << nm << \" =\\n\";\n              if (! Vcompact_format)\n                os << \"\\n\";\n            }\n\n          Array<octave::idx_vector> idx (dim_vector (ndims, 1));\n\n          idx(0) = octave::idx_vector (':');\n          idx(1) = octave::idx_vector (':');\n\n          for (int k = 2; k < ndims; k++)\n            idx(k) = octave::idx_vector (ra_idx(k));\n\n          Array<T> page (nda.index (idx), dim_vector (nr, nc));\n\n          for (octave_idx_type ii = 0; ii < nr; ii++)\n            {\n              for (octave_idx_type jj = 0; jj < nc; jj++)\n                {\n                  octave_quit ();\n\n                  pr_plus_format (os, page(ii, jj));\n                }\n\n              if ((ii < nr - 1) || (i < m -1))\n                os << \"\\n\";\n            }\n\n          if (i < m - 1)\n            {\n              os << \"\\n\";\n              increment_index (ra_idx, dims, 2);\n            }\n        }\n    }\n  else\n    {\n      int ndims = nda.ndims ();\n\n      const dim_vector& dims = nda.dims ();\n\n      Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);\n\n      octave_idx_type m = 1;\n\n      for (int i = 2; i < ndims; i++)\n        m *= dims(i);\n\n      octave_idx_type nr = dims(0);\n      octave_idx_type nc = dims(1);\n\n      int fw = 0;\n      if (hex_format)\n        fw = 2 * nda(0).byte_size ();\n      else if (bit_format)\n        fw = nda(0).nbits ();\n      else\n        {\n          bool isneg = false;\n          int digits = 0;\n\n          for (octave_idx_type i = 0; i < dims.numel (); i++)\n            {\n              int new_digits\n                = static_cast<int>\n                  (std::floor (log10 (double (abs (nda(i).value ()))) + 1));\n\n              if (new_digits > digits)\n                digits = new_digits;\n\n              if (! isneg)\n                isneg = (abs (nda(i).value ()) != nda(i).value ());\n            }\n\n          fw = digits + isneg;\n        }\n\n      int column_width = fw + (rat_format ?  0 : (bank_format ? 5 : 2));\n      octave_idx_type total_width = nc * column_width;\n      int max_width = octave::command_editor::terminal_cols () - extra_indent;\n      octave_idx_type inc = nc;\n      if (total_width > max_width && Vsplit_long_rows)\n        {\n          inc = max_width / column_width;\n          if (inc == 0)\n            inc++;\n        }\n\n      for (octave_idx_type i = 0; i < m; i++)\n        {\n          if (m > 1)\n            {\n              std::string nm = \"ans(:,:,\";\n\n              std::ostringstream buf;\n\n              for (int k = 2; k < ndims; k++)\n                {\n                  buf << ra_idx(k) + 1;\n\n                  if (k < ndims - 1)\n                    buf << ',';\n                  else\n                    buf << ')';\n                }\n\n              nm += buf.str ();\n\n              os << nm << \" =\\n\";\n              if (! Vcompact_format)\n                os << \"\\n\";\n            }\n\n          Array<octave::idx_vector> idx (dim_vector (ndims, 1));\n\n          idx(0) = octave::idx_vector (':');\n          idx(1) = octave::idx_vector (':');\n\n          for (int k = 2; k < ndims; k++)\n            idx(k) = octave::idx_vector (ra_idx(k));\n\n          Array<T> page (nda.index (idx), dim_vector (nr, nc));\n\n          if (free_format)\n            {\n              if (pr_as_read_syntax)\n                os << \"[\\n\";\n\n              for (octave_idx_type ii = 0; ii < nr; ii++)\n                {\n                  for (octave_idx_type jj = 0; jj < nc; jj++)\n                    {\n                      octave_quit ();\n                      os << \"  \";\n                      os << typename octave_print_conv<T>::print_conv_type (page(ii, jj));\n                    }\n                  os << \"\\n\";\n                }\n\n              if (pr_as_read_syntax)\n                os << ']';\n            }\n          else\n            {\n              octave::preserve_stream_state stream_state (os);\n\n              octave_idx_type n_rows = page.rows ();\n              octave_idx_type n_cols = page.cols ();\n\n              for (octave_idx_type col = 0; col < n_cols; col += inc)\n                {\n                  octave_idx_type lim = (col + inc < n_cols ? col + inc\n                                         : n_cols);\n\n                  pr_col_num_header (os, total_width, max_width, lim, col,\n                                     extra_indent);\n\n                  for (octave_idx_type ii = 0; ii < n_rows; ii++)\n                    {\n                      os << std::setw (extra_indent) << \"\";\n\n                      for (octave_idx_type jj = col; jj < lim; jj++)\n                        {\n                          octave_quit ();\n                          os << \"  \";\n                          pr_int (os, page(ii, jj), fw);\n                        }\n                      if ((ii < n_rows - 1) || (i < m -1))\n                        os << \"\\n\";\n                    }\n                }\n            }\n\n          if (i < m - 1)\n            {\n              os << \"\\n\";\n              increment_index (ra_idx, dims, 2);\n            }\n        }\n    }\n}\n\n#define PRINT_INT_ARRAY_INTERNAL(TYPE)                                  \\\n  OCTINTERP_API void                                                    \\\n  octave_print_internal (std::ostream& os, const intNDArray<TYPE>& nda, \\\n                         bool pr_as_read_syntax, int extra_indent)      \\\n  {                                                                     \\\n    octave_print_internal_template (os, nda, pr_as_read_syntax, extra_indent); \\\n  }\n\nPRINT_INT_ARRAY_INTERNAL (octave_int8)\nPRINT_INT_ARRAY_INTERNAL (octave_uint8)\nPRINT_INT_ARRAY_INTERNAL (octave_int16)\nPRINT_INT_ARRAY_INTERNAL (octave_uint16)\nPRINT_INT_ARRAY_INTERNAL (octave_int32)\nPRINT_INT_ARRAY_INTERNAL (octave_uint32)\nPRINT_INT_ARRAY_INTERNAL (octave_int64)\nPRINT_INT_ARRAY_INTERNAL (octave_uint64)\n\nvoid\noctave_print_internal (std::ostream&, const Cell&, bool, int, bool)\n{\n  error (\"unexpected call to 'octave_print_internal (std::ostream&, const Cell&, bool, int, bool)' - please report this bug\");\n}\n\nvoid\noctave_print_internal (std::ostream&, const octave_value&, bool)\n{\n  error (\"unexpected call to 'octave_print_internal (std::ostream&, const octave_value&, bool)' - please report this bug\");\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (rats, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{s} =} rats (@var{x})\n@deftypefnx {} {@var{s} =} rats (@var{x}, @var{len})\nConvert @var{x} into a rational approximation represented as a string.\n\nA rational approximation to a floating point number is a simple fraction\nwith numerator @var{N} and denominator @var{D} such that\n@code{@var{x} = @var{N}/@var{D}}.\n\nThe optional second argument defines the maximum length of the string\nrepresenting the elements of @var{x}.  By default, @var{len} is 13.\n\nIf the length of the smallest possible rational approximation exceeds\n@var{len}, an asterisk (*) padded with spaces will be returned instead.\n\nExample conversion from matrix to string, and back again.\n\n@example\n@group\nr = rats (hilb (4));\nx = str2num (r)\n@end group\n@end example\n\n@seealso{rat, format}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  if (! arg.isnumeric ())\n    error (\"rats: X must be numeric\");\n\n  if (arg.isempty ())\n    return ovl (octave_value (\"\"));\n\n  // Convert to N-D arrays to 2-D arrays for Matlab compatibility\n  if (arg.ndims () > 2)\n    {\n      dim_vector dv (arg.rows (), arg.numel () / arg.rows ());\n      arg = arg.reshape (dv);\n    }\n\n  unwind_protect frame;\n\n  frame.protect_var (rat_string_len);\n\n  rat_string_len = 13;\n  if (nargin == 2)\n    rat_string_len = args(1).strict_int_value ();\n\n  frame.protect_var (rat_format);\n\n  rat_format = true;\n\n  std::ostringstream buf;\n  arg.print (buf);\n  std::string s = buf.str ();\n\n  std::list<std::string> lst;\n\n  std::size_t n = 0;\n  std::size_t s_len = s.length ();\n\n  while (n < s_len)\n    {\n      std::size_t m = s.find ('\\n', n);\n\n      if (m == std::string::npos)\n        {\n          lst.push_back (s.substr (n));\n          break;\n        }\n      else\n        {\n          lst.push_back (s.substr (n, m - n));\n          n = m + 1;\n        }\n    }\n\n  return ovl (string_vector (lst));\n}\n\n/*\n%!test <*56941>\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format short;\n%!   assert (rats (-2.0005, 10), \"-4001/2000\");\n%!   assert (strtrim (rats (2.0005, 30)), \"4001/2000\");\n%!   assert (pi - str2num (rats (pi, 30)), 0, 4 * eps);\n%!   assert (e - str2num (rats (e, 30)), 0, 4 * eps);\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n\n%!test <*57003>\n%! x = ones (2,1,3);\n%! s = rats (x,4);\n%! assert (ndims (s) == 2);\n%! assert (rows (s) == 2);\n%! assert (columns (s) == 3 * 6);\n\n%!assert <*57004> (rats ([]), '')\n\n%!test <57704>\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format short;\n%!   assert (rats (2.0005, 9), \"4001/2000\");\n%!   assert (rats (123, 2), \" *\");\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n\n*/\n\nDEFUN (disp, args, nargout,\n       classes: cell char double function_handle int8 int16 int32 int64 logical single struct uint8 uint16 uint32 uint64\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} disp (@var{x})\n@deftypefnx {} {@var{str} =} disp (@var{x})\nDisplay the value of @var{x}.\n\nFor example:\n\n@example\n@group\ndisp (\"The value of pi is:\"), disp (pi)\n\n     @print{} the value of pi is:\n     @print{} 3.1416\n@end group\n@end example\n\n@noindent\nNote that the output from @code{disp} always ends with a newline.\n\nIf an output value is requested, @code{disp} prints nothing and returns the\nformatted output in a string.\n@seealso{fdisp}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value_list retval;\n\n  octave_value arg = args(0);\n\n  if (nargout == 0)\n    arg.print (octave_stdout);\n  else\n    {\n      std::ostringstream buf;\n      arg.print (buf);\n      retval = (octave_value (buf.str (), arg.is_dq_string () ? '\"' : '\\''));\n    }\n\n  return retval;\n}\n\nDEFMETHOD (fdisp, interp, args, ,\n           classes: cell char double function_handle int8 int16 int32 int64 logical single struct uint8 uint16 uint32 uint64\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} fdisp (@var{fid}, @var{x})\nDisplay the value of @var{x} on the stream @var{fid}.\n\nFor example:\n\n@example\n@group\nfdisp (stdout, \"The value of pi is:\"), fdisp (stdout, pi)\n\n     @print{} the value of pi is:\n     @print{} 3.1416\n@end group\n@end example\n\n@noindent\nNote that the output from @code{fdisp} always ends with a newline.\n@seealso{disp}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  stream_list& streams = interp.get_stream_list ();\n\n  int fid = streams.get_file_number (args(0));\n\n  stream os = streams.lookup (fid, \"fdisp\");\n\n  std::ostream *osp = os.preferred_output_stream ();\n\n  if (! osp)\n    error (\"fdisp: stream FID not open for writing\");\n\n  octave_value arg = args(1);\n  arg.print (*osp);\n\n  return ovl ();\n}\n\n/*\n## FIXME: This test writes values to a file, but then never checks them.\n%!test\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format short\n%!   fd = tmpfile ();\n%!   for r = [0, Inf -Inf, NaN]\n%!     for i = [0, Inf -Inf, NaN]\n%!       fdisp (fd, complex (r, i));\n%!     endfor\n%!   endfor\n%!   fclose (fd);\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n\n%!test\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   foo.real = pi * ones (3,20,3);\n%!   foo.complex = pi * ones (3,20,3) + 1i;\n%!   foo.char = repmat (\"- Hello World -\", [3, 20]);\n%!   foo.cell = {foo.real, foo.complex, foo.char};\n%!   fields = fieldnames (foo);\n%!   for f = 1:numel (fields)\n%!     format loose;\n%!     loose = disp (foo.(fields{f}));\n%!     format compact;\n%!     compact = disp (foo.(fields{f}));\n%!     expected = strrep (loose, \"\\n\\n\", \"\\n\");\n%!     assert (expected, compact);\n%!   endfor\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n*/\n\nDEFMETHOD (display, interp, args, ,\n           classes: cell char double function_handle int8 int16 int32 int64 logical single struct uint8 uint16 uint32 uint64\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} display (@var{obj})\nDisplay the contents of the object @var{obj} prepended by its name.\n\nThe Octave interpreter calls the @code{display} function whenever it needs\nto present a class on-screen.  Typically, this would be a statement which\ndoes not end in a semicolon to suppress output.  For example:\n\n@example\nmyclass (@dots{})\n@end example\n\nOr:\n\n@example\nmyobj = myclass (@dots{})\n@end example\n\nIn general, user-defined classes should overload the @code{disp} method to\navoid the default output:\n\n@example\n@group\nmyobj = myclass (@dots{})\n  @xresult{} myobj =\n\n  <class myclass>\n@end group\n@end example\n\nWhen overloading the @code{display} method instead, one has to take care\nof properly displaying the object's name.  This can be done by using the\n@code{inputname} function.\n\n@seealso{disp, class, subsref, subsasgn}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  // Matlab apparently accepts two arguments with the second set to the\n  // inputname of the first.  This is undocumented, but we'll use it.\n  // However, we never call display methods for classes with more than\n  // one argument.\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string name;\n\n  if (nargin == 2)\n    name = args(1).xstring_value (\"NAME must be a string\");\n  else\n    {\n      string_vector names = args.name_tags ();\n      name = names(0);\n    }\n\n  // We are here because there is no overloaded display method for this\n  // object type.\n\n  octave_value value = args(0);\n\n  // If print_name_tag displays a newline, then also print one after\n  // disp is done.\n\n  bool print_newlines = false;\n  if (valid_identifier (name))\n    print_newlines = value.print_name_tag (octave_stdout, name);\n\n  // Use feval so that dispatch will also work for disp.\n\n  interp.feval (\"disp\", ovl (value));\n\n  if (print_newlines)\n    octave_stdout << std::endl;\n\n  return ovl ();\n}\n\n/*\n%!test\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format short;\n%!   str = evalc (\"x = 1.1; display (x)\");\n%!   assert (str, \"x = 1.1000\\n\");\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n\n%!test\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format short;\n%!   str = evalc (\"display (1.1)\");\n%!   assert (str, \"1.1000\\n\");\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n\n## Test input validation\n%!error display ()\n%!error display (1,2)\n*/\n\nstatic inline void\ninit_format_state ()\n{\n  free_format = false;\n  plus_format = false;\n  rat_format = false;\n  bank_format = false;\n  hex_format = 0;\n  bit_format = 0;\n  print_e = false;\n  print_g = false;\n  print_eng = false;\n}\n\nstatic std::string format_string (\"short\");\n\nstatic inline void\nset_format_style (int argc, const string_vector& argv)\n{\n  if (--argc == 0)\n    {\n      // Special case of no options, reset to default values\n      init_format_state ();\n      set_output_prec (5);\n      format_string = \"short\";\n      Vcompact_format = false;\n      uppercase_format = false;\n      return;\n    }\n\n  int idx = 1;\n  std::string format;\n\n  unwind_protect frame;\n\n  frame.protect_var (bank_format);\n  frame.protect_var (bit_format);\n  frame.protect_var (free_format);\n  frame.protect_var (hex_format);\n  frame.protect_var (plus_format);\n  frame.protect_var (plus_format_chars);\n  frame.protect_var (rat_format);\n  frame.protect_var (print_e);\n  frame.protect_var (print_eng);\n  frame.protect_var (print_g);\n  frame.protect_var (format_string);\n  frame.protect_var (Vcompact_format);\n  frame.protect_var (uppercase_format);\n  int prec = output_precision ();\n  frame.add ([prec] () { set_output_prec (prec); });\n\n  format = format_string;   // Initialize with existing value\n  while (argc-- > 0)\n    {\n      std::string arg = argv[idx++];\n      std::transform (arg.begin (), arg.end (), arg.begin (), tolower);\n\n      if (arg == \"default\")\n        {\n          format = \"short\";\n          init_format_state ();\n          set_output_prec (5);\n          Vcompact_format = false;\n          uppercase_format = false;\n        }\n      else if (arg == \"short\")\n        {\n          format = arg;\n          init_format_state ();\n          if (argc > 0)\n            {\n              arg = argv[idx];\n              if (arg == \"e\")\n                {\n                  print_e = true;\n                  format.append (arg);\n                  argc--; idx++;\n                }\n              else if (arg == \"g\")\n                {\n                  init_format_state ();\n                  print_g = true;\n                  format.append (arg);\n                  argc--; idx++;\n                }\n              else if (arg == \"eng\")\n                {\n                  init_format_state ();\n                  print_eng = true;\n                  format.append (arg);\n                  argc--; idx++;\n                }\n            }\n          set_output_prec (5);\n        }\n      else if (arg == \"shorte\")\n        {\n          format = arg;\n          init_format_state ();\n          print_e = true;\n          set_output_prec (5);\n        }\n      else if (arg == \"shortg\")\n        {\n          format = arg;\n          init_format_state ();\n          print_g = true;\n          set_output_prec (5);\n        }\n      else if (arg == \"shorteng\")\n        {\n          format = arg;\n          init_format_state ();\n          print_eng = true;\n          set_output_prec (5);\n        }\n      else if (arg == \"long\")\n        {\n          format = arg;\n          init_format_state ();\n          if (argc > 0)\n            {\n              arg = argv[idx];\n\n              if (arg == \"e\")\n                {\n                  print_e = true;\n                  format.append (arg);\n                  argc--; idx++;\n                }\n              else if (arg == \"g\")\n                {\n                  print_g = true;\n                  format.append (arg);\n                  argc--; idx++;\n                }\n              else if (arg == \"eng\")\n                {\n                  print_eng = true;\n                  format.append (arg);\n                  argc--; idx++;\n                }\n            }\n          set_output_prec (16);\n        }\n      else if (arg == \"longe\")\n        {\n          format = arg;\n          init_format_state ();\n          print_e = true;\n          set_output_prec (16);\n        }\n      else if (arg == \"longg\")\n        {\n          format = arg;\n          init_format_state ();\n          print_g = true;\n          set_output_prec (16);\n        }\n      else if (arg == \"longeng\")\n        {\n          format = arg;\n          init_format_state ();\n          print_eng = true;\n          set_output_prec (16);\n        }\n      else if (arg == \"hex\")\n        {\n          format = arg;\n          init_format_state ();\n          hex_format = 1;\n        }\n      else if (arg == \"native-hex\")\n        {\n          format = arg;\n          init_format_state ();\n          hex_format = 2;\n        }\n      else if (arg == \"bit\")\n        {\n          format = arg;\n          init_format_state ();\n          bit_format = 1;\n        }\n      else if (arg == \"native-bit\")\n        {\n          format = arg;\n          init_format_state ();\n          bit_format = 2;\n        }\n      else if (arg == \"+\" || arg == \"plus\")\n        {\n          format = arg;\n          init_format_state ();\n          plus_format = true;\n          if (argc > 0)\n            {\n              arg = argv[idx];\n\n              if (arg.length () == 3)\n                {\n                  plus_format_chars = arg;\n                  format.append (arg);\n                  argc--; idx++;\n                }\n              else\n                plus_format_chars = \"+- \";\n            }\n          else\n            plus_format_chars = \"+- \";\n        }\n      else if (arg == \"rat\")\n        {\n          format = arg;\n          init_format_state ();\n          rat_format = true;\n        }\n      else if (arg == \"bank\")\n        {\n          format = arg;\n          init_format_state ();\n          bank_format = true;\n        }\n      else if (arg == \"free\")\n        {\n          format = arg;\n          init_format_state ();\n          free_format = true;\n        }\n      else if (arg == \"none\")\n        {\n          format = arg;\n          init_format_state ();\n          free_format = true;\n        }\n      else if (arg == \"compact\")\n        Vcompact_format = true;\n      else if (arg == \"loose\")\n        Vcompact_format = false;\n      else if (arg == \"lowercase\")\n        uppercase_format = false;\n      else if (arg == \"uppercase\")\n        uppercase_format = true;\n      else\n        error (\"format: unrecognized format state '%s'\", arg.c_str ());\n    }\n\n  format_string = format;\n\n  // If successful, discard unwind state information\n  frame.discard ();\n}\n\nDEFUN (format, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} format\n@deftypefnx {} {} format options\n@deftypefnx {} {} format (@var{options})\n@deftypefnx {} {[@var{format}, @var{formatspacing}, @var{uppercase}] =} format\nReset or specify the format of the output produced by @code{disp} and Octave's\nnormal echoing mechanism.\n\nThis command only affects the display of numbers, not how they are stored\nor computed.  To change the internal representation from the default double use\none of the conversion functions such as @code{single}, @code{uint8},\n@code{int64}, etc.  Any @code{format} options that change the number of\ndisplayed significant digits will also be reflected by the\n@code{output_precision} function.\n\nBy default, Octave displays 5 significant digits in a human readable form\n(option @samp{short}, option @samp{lowercase}, and option @samp{loose} format\nfor matrices).  If @code{format} is invoked without any options, or the option\n@samp{default} is specified, then this default format is restored.\n\nValid format options for floating point numbers are listed in the following\ntable.\n\n@table @code\n@item default\nRestore the default format state described above.\n\n@item short\nFixed point format with 5 significant figures (default).\n\n@item long\nFixed point format with 16 significant figures.\n\nAs with the @samp{short} format, Octave will switch to an exponential @samp{e}\nformat if it is unable to format a matrix properly using the current format.\n\n@item  shorte\n@itemx longe\nExponential format.  The number to be represented is split between a mantissa\nand an exponent (power of 10).  The mantissa has 5 significant digits in the\nshort format.  In the long format, double values are displayed with 16\nsignificant digits and single values are displayed with 8.  For example,\nwith the @samp{shorte} format, @code{pi} is displayed as @code{3.1416e+00}.\nOptionally, the trailing @samp{e} can be split into a second argument.\n\n@item  shortg\n@itemx longg\nOptimally choose between fixed point and exponential format based on the\nmagnitude of the number.  For example, with the @samp{shortg} format,\n@w{@code{pi .^ [2; 4; 8; 16; 32]}} is displayed as\n\n@example\n@group\nans =\n\n      9.8696\n      97.409\n      9488.5\n  9.0032e+07\n  8.1058e+15\n@end group\n@end example\n\nOptionally, the trailing @samp{g} can be split into a second argument.\n\n@item  shorteng\n@itemx longeng\nIdentical to @samp{shorte} or @samp{longe} but displays the value using an\nengineering format, where the exponent is divisible by 3.  For example, with\nthe @samp{shorteng} format, @code{10 * pi} is displayed as @code{31.416e+00}.\nOptionally, the trailing @samp{eng} can be split into a second argument.\n\n@item  free\n@itemx none\nPrint output in free format, without trying to line up columns of matrices on\nthe decimal point.  This is a raw format equivalent to the C++ code\n@code{std::cout << @var{variable}}.  In general, the result is a presentation\nwith 6 significant digits where unnecessary precision (such as trailing zeros\nfor integers) is suppressed.  Complex numbers are formatted as numeric pairs\nlike this @code{(0.60419, 0.60709)} instead of like this\n@code{0.60419 + 0.60709i}.\n@end table\n\nThe following formats affect all numeric output (floating point and integer\ntypes).\n\n@table @asis\n@item  @qcode{\"+\"}\n@itemx @qcode{\"+\"} @qcode{\"@var{chars}\"}\n@itemx @code{plus}\n@itemx @code{plus @var{chars}}\nPrint a @samp{+} symbol for matrix elements greater than zero, a @samp{-}\nsymbol for elements less than zero, and a space for zero matrix elements.  This\nformat can be useful for examining the sparsity structure of a large matrix.\nFor very large matrices the function @code{spy} which plots the sparsity\npattern will be clearer.\n\nThe optional argument @var{chars} specifies a list of 3 characters to use for\nprinting values greater than zero, less than zero, and equal to zero.  For\nexample, with the format @qcode{\"+\" \"+-.\"}, the matrix\n@code{[1, 0, -1; -1, 0, 1]} is displayed as\n\n@example\n@group\nans =\n\n+.-\n-.+\n@end group\n@end example\n\n@end table\n\n@table @code\n@item bank\nPrint variable in a format appropriate for a currency (fixed format with two\ndigits to the right of the decimal point).  Only the real part of a variable is\ndisplayed, as the imaginary part makes no sense for a currency.\n\n@item bit\nPrint the bit representation of numbers in memory, always with the\nmost significant bit first.  For example, @code{pi} is printed like this:\n\n@smallformat\n@code{0 10000000000 1001001000011111101101010100010001000010110100011000}\n@end smallformat\n\n@noindent\nwhere spaces have been added for clarity to show the sign bit, the 11-bit\nexponent, and the 52-bit mantissa, in that order.  Together they represent\n@code{pi} as an IEEE@tie{}754 double precision floating point number in the\nnormal form.  Single precision floating point numbers are analogous.\n\n@item native-bit\nPrint the bit representation of numbers as stored in memory.  For big-endian\nmachines, this is identical to the @code{format bit} layout seen above.\nFor little-endian machines, it will print the bytes in the opposite order,\nthough bits within a byte will still be presented with the most significant\nbit on the left.\n\nFor example, the value of @code{pi} in this format on x86-64 is:\n\n@smallformat\n@code{00011000 00101101 01000100 01010100 11111011 00100001 00001001 01000000}\n@end smallformat\n\n@noindent\nshown here with spaces added for clarity.  Compare with the previous bit string\nfrom @code{format bit} to see the grouping into bytes and their ordering.\n\n@item hex\nThe same as @code{format bit} above, except that bits are grouped four at a\ntime into hexadecimal digits for brevity.  Thus @code{pi} is represented as:\n\n@example\n400921fb54442d18\n@end example\n\n@item native-hex\nThe same as @code{format native-bit} above, except that bits are grouped four\nat a time into hexadecimal digits for brevity.  Thus @code{pi} is represented\non an x86-64 as:\n\n@example\n182d4454fb210940\n@end example\n\n@item rat\nPrint a rational approximation, i.e., values are approximated as the ratio of\nsmall integers.  For example, with the @samp{rat} format, @code{pi} is\ndisplayed as @code{355/113}.\n@end table\n\nThe following two options affect the display of scientific and hex notations.\n\n@table @code\n@item lowercase (default)\nUse a lowercase @samp{e} for the exponent character in scientific notation and\nlowercase @samp{a-f} for the hex digits representing 10-15.\n\n@item uppercase\nUse an uppercase @samp{E} for the exponent character in scientific notation and\nuppercase @samp{A-F} for the hex digits representing 10-15.\n@end table\n\nThe following two options affect the display of all matrices.\n\n@table @code\n@item compact\nRemove blank lines around column number labels and between matrices producing\nmore compact output with more data per page.\n\n@item loose (default)\nInsert blank lines above and below column number labels and between matrices to\nproduce a more readable output with less data per page.\n@end table\n\nIf @code{format} is called with multiple competing options, the rightmost one\nis used, except for @samp{default} which will override all other options.  In\ncase of an error the format remains unchanged.\n\nIf called with one to three output arguments, and no inputs, return the current\nformat, format spacing, and uppercase preference.  Specifying both outputs and\ninputs will produce an error.\n\n@seealso{fixed_point_format, output_precision, split_long_rows,\nprint_empty_dimensions, rats}\n@end deftypefn */)\n{\n  octave_value_list retval (std::min (nargout, 2));\n\n  int nargin = args.length ();\n\n  if (nargout == 0)\n    {\n      int argc = nargin + 1;\n\n      string_vector argv = args.make_argv (\"format\");\n\n      set_format_style (argc, argv);\n    }\n  else\n    {\n      if (nargin > 0)\n        warning (\"format: cannot query and set format at the same time, ignoring set operation\");\n\n      if (nargout >= 3)\n        retval(2) = (uppercase_format ? \"uppercase\" : \"lowercase\");\n\n      if (nargout >= 2)\n        retval(1) = (Vcompact_format ? \"compact\" : \"loose\");\n\n      retval(0) = format_string;\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! [old_fmt, old_spacing, old_uppercase] = format ();\n%! unwind_protect\n%!   ## Test one of the formats\n%!   format long e;\n%!   format uppercase;\n%!   str = disp (pi);\n%!   assert (str, \"3.141592653589793E+00\\n\");\n%!   str = disp (single (pi));\n%!   assert (str, \"3.1415927E+00\\n\");\n%!   new_fmt = format ();\n%!   assert (new_fmt, \"longe\");\n%!   ## Test resetting format (method #1)\n%!   format compact;\n%!   [~, new_spacing] = format ();\n%!   assert (new_spacing, \"compact\");\n%!   format;\n%!   [new_fmt, new_spacing, new_case] = format ();\n%!   assert (new_fmt, \"short\");\n%!   assert (new_spacing, \"loose\");\n%!   assert (new_case, \"lowercase\");\n%!   ## Test resetting format (method #2)\n%!   format compact uppercase long e;\n%!   [new_fmt, new_spacing, new_case] = format ();\n%!   assert (new_fmt, \"longe\");\n%!   assert (new_spacing, \"compact\");\n%!   assert (new_case, \"uppercase\");\n%!   format (\"default\");\n%!   [new_fmt, new_spacing, new_case] = format ();\n%!   assert (new_fmt, \"short\");\n%!   assert (new_spacing, \"loose\");\n%!   assert (new_case, \"lowercase\");\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%!   format (old_uppercase);\n%! end_unwind_protect\n\n%!test <*53427>\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format;          # reset format to short and loose\n%!   format compact;  # set compact format\n%!   format long;     # set long format\n%!   [fmt, spacing] = format ();\n%!   assert (fmt, \"long\");\n%!   assert (spacing, \"compact\");\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n\n## Test input validation\n%!test\n%! fail (\"fmt = format ('long')\", \"warning\", \"cannot query and set format\");\n\n*/\n\nDEFUN (fixed_point_format, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} fixed_point_format ()\n@deftypefnx {} {@var{old_val} =} fixed_point_format (@var{new_val})\n@deftypefnx {} {@var{old_val} =} fixed_point_format (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave will\nuse a scaled format to print matrix values.\n\nThe scaled format prints a scaling factor on the first line of output chosen\nsuch that the largest matrix element can be written with a single leading\ndigit.  For example:\n\n@example\n@group\nfixed_point_format (true)\nlogspace (1, 7, 5)'\nans =\n\n  1.0e+07  *\n\n  0.00000\n  0.00003\n  0.00100\n  0.03162\n  1.00000\n@end group\n@end example\n\n@noindent\nNotice that the first value appears to be 0 when it is actually 1.  Because\nof the possibility for confusion you should be careful about enabling\n@code{fixed_point_format}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{format, output_precision}\n@end deftypefn */)\n{\n  return set_internal_variable (Vfixed_point_format, args, nargout,\n                                \"fixed_point_format\");\n}\n\nDEFUN (print_empty_dimensions, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} print_empty_dimensions ()\n@deftypefnx {} {@var{old_val} =} print_empty_dimensions (@var{new_val})\n@deftypefnx {} {@var{old_val} =} print_empty_dimensions (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether the dimensions of\nempty matrices are printed along with the empty matrix symbol, @samp{[]}.\n\nFor example, the expression\n\n@example\nzeros (3, 0)\n@end example\n\n@noindent\nwill print\n\n@example\nans = [](3x0)\n@end example\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{format}\n@end deftypefn */)\n{\n  return set_internal_variable (Vprint_empty_dimensions, args, nargout,\n                                \"print_empty_dimensions\");\n}\n\nDEFUN (split_long_rows, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} split_long_rows ()\n@deftypefnx {} {@var{old_val} =} split_long_rows (@var{new_val})\n@deftypefnx {} {@var{old_val} =} split_long_rows (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether rows of a matrix\nmay be split when displayed to a terminal window.\n\nIf the rows are split, Octave will display the matrix in a series of smaller\npieces, each of which can fit within the limits of your terminal width and\neach set of rows is labeled so that you can easily see which columns are\ncurrently being displayed.  For example:\n\n@example\n@group\noctave:13> rand (2,10)\nans =\n\n Columns 1 through 6:\n\n  0.75883  0.93290  0.40064  0.43818  0.94958  0.16467\n  0.75697  0.51942  0.40031  0.61784  0.92309  0.40201\n\n Columns 7 through 10:\n\n  0.90174  0.11854  0.72313  0.73326\n  0.44672  0.94303  0.56564  0.82150\n@end group\n@end example\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{format}\n@end deftypefn */)\n{\n  return set_internal_variable (Vsplit_long_rows, args, nargout,\n                                \"split_long_rows\");\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/pr-output.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pr_output_h)\n#define octave_pr_output_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n#include \"Array.h\"\n#include \"intNDArray-fwd.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-inttypes-fwd.h\"\n#include \"range-fwd.h\"\n\n#include \"pr-flt-fmt.h\"\n\nclass ComplexMatrix;\nclass FloatComplexMatrix;\nclass ComplexDiagMatrix;\nclass FloatComplexDiagMatrix;\nclass ComplexNDArray;\nclass FloatComplexNDArray;\nclass Matrix;\nclass FloatMatrix;\nclass DiagMatrix;\nclass FloatDiagMatrix;\nclass NDArray;\nclass FloatNDArray;\nclass boolMatrix;\nclass boolNDArray;\nclass charMatrix;\nclass charNDArray;\nclass PermMatrix;\nclass Cell;\nclass octave_value;\n\ntemplate <typename T>\nfloat_display_format\nmake_format (const std::complex<T>&)\n{\n  return float_display_format ();\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const std::complex<double>& c);\n\ntemplate <>\nfloat_display_format\nmake_format (const std::complex<float>& fc);\n\ntemplate <typename T>\nfloat_display_format\nmake_format (const T&)\n{\n  return float_display_format ();\n}\n\ntemplate <>\nfloat_display_format\nmake_format (const double& d);\n\ntemplate <>\nfloat_display_format\nmake_format (const float& f);\n\ntemplate <>\nfloat_display_format\nmake_format (const octave::range<double>& r);\n\ntemplate <>\nfloat_display_format\nmake_format (const Matrix& m);\n\ntemplate <>\nfloat_display_format\nmake_format (const FloatMatrix& m);\n\ntemplate <>\nfloat_display_format\nmake_format (const ComplexMatrix& m);\n\ntemplate <>\nfloat_display_format\nmake_format (const FloatComplexMatrix& m);\n\ntemplate <>\nfloat_display_format\nmake_format (const boolNDArray& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const intNDArray<octave_int8>& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const intNDArray<octave_int16>& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const intNDArray<octave_int32>& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const intNDArray<octave_int64>& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const intNDArray<octave_uint8>& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const intNDArray<octave_uint16>& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const intNDArray<octave_uint32>& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const intNDArray<octave_uint64>& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const octave_int8& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const octave_int16& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const octave_int32& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const octave_int64& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const octave_uint8& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const octave_uint16& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const octave_uint32& nda);\n\ntemplate <>\nfloat_display_format\nmake_format (const octave_uint64& nda);\n\n// FIXME: templates plus specializations might help here.\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       bool d, bool pr_as_read_syntax = false);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, bool d,\n                       bool pr_as_read_syntax = false);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       char c, bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, char c,\n                       bool pr_as_read_syntax = false)\n{\n  float_display_format fmt (float_format (0, 0));\n  octave_print_internal (os, fmt, c, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       double d, bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, double d,\n                       bool pr_as_read_syntax = false)\n{\n  octave_print_internal (os, make_format (d), d, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       float d, bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, float d,\n                       bool pr_as_read_syntax = false)\n{\n  octave_print_internal (os, make_format (d), d, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const Matrix& m,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const FloatMatrix& m,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const DiagMatrix& m,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const FloatDiagMatrix& m,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const NDArray& nda,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const FloatNDArray& nda,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       const Complex& c, bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const Complex& c,\n                       bool pr_as_read_syntax = false)\n{\n  octave_print_internal (os, make_format (c), c, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format& fmt,\n                       const FloatComplex& c, bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const FloatComplex& c,\n                       bool pr_as_read_syntax = false)\n{\n  octave_print_internal (os, make_format (c), c, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const ComplexMatrix& cm,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const ComplexDiagMatrix& cm,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const FloatComplexMatrix& cm,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const FloatComplexDiagMatrix& cm,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const ComplexNDArray& nda,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const FloatComplexNDArray& nda,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const PermMatrix& m,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const octave::range<double>& r,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const boolMatrix& m,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const boolNDArray& m,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const charMatrix& chm,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0,\n                       bool pr_as_string = false);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const charNDArray& nda,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0,\n                       bool pr_as_string = false);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const std::string& s,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const Array<std::string>& sa,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const intNDArray<octave_int8>& sa,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const intNDArray<octave_uint8>& sa,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const intNDArray<octave_int16>& sa,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const intNDArray<octave_uint16>& sa,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const intNDArray<octave_int32>& sa,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const intNDArray<octave_uint32>& sa,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const intNDArray<octave_int64>& sa,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const intNDArray<octave_uint64>& sa,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0);\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format&,\n                       const octave_int<int8_t>& sa,\n                       bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const octave_int<int8_t>& sa,\n                       bool pr_as_read_syntax = false)\n{\n  float_display_format fmt (float_format (0, 0));\n  octave_print_internal (os, fmt, sa, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format&,\n                       const octave_int<uint8_t>& sa,\n                       bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const octave_int<uint8_t>& sa,\n                       bool pr_as_read_syntax = false)\n{\n  float_display_format fmt (float_format (0, 0));\n  octave_print_internal (os, fmt, sa, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format&,\n                       const octave_int<int16_t>& sa,\n                       bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const octave_int<int16_t>& sa,\n                       bool pr_as_read_syntax = false)\n{\n  float_display_format fmt (float_format (0, 0));\n  octave_print_internal (os, fmt, sa, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format&,\n                       const octave_int<uint16_t>& sa,\n                       bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const octave_int<uint16_t>& sa,\n                       bool pr_as_read_syntax = false)\n{\n  float_display_format fmt (float_format (0, 0));\n  octave_print_internal (os, fmt, sa, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format&,\n                       const octave_int<int32_t>& sa,\n                       bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const octave_int<int32_t>& sa,\n                       bool pr_as_read_syntax = false)\n{\n  float_display_format fmt (float_format (0, 0));\n  octave_print_internal (os, fmt, sa, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format&,\n                       const octave_int<uint32_t>& sa,\n                       bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const octave_int<uint32_t>& sa,\n                       bool pr_as_read_syntax = false)\n{\n  float_display_format fmt (float_format (0, 0));\n  octave_print_internal (os, fmt, sa, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format&,\n                       const octave_int<int64_t>& sa,\n                       bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const octave_int<int64_t>& sa,\n                       bool pr_as_read_syntax = false)\n{\n  float_display_format fmt (float_format (0, 0));\n  octave_print_internal (os, fmt, sa, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const float_display_format&,\n                       const octave_int<uint64_t>& sa,\n                       bool pr_as_read_syntax = false);\n\ninline void\noctave_print_internal (std::ostream& os, const octave_int<uint64_t>& sa,\n                       bool pr_as_read_syntax = false)\n{\n  float_display_format fmt (float_format (0, 0));\n  octave_print_internal (os, fmt, sa, pr_as_read_syntax);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const Cell& cell,\n                       bool pr_as_read_syntax = false,\n                       int extra_indent = 0,\n                       bool pr_as_string = false);\n\ninline void\noctave_print_internal (std::ostream& os, const float_display_format&,\n                       const Cell& cell, bool pr_as_read_syntax = false,\n                       int extra_indent = 0, bool pr_as_string = false)\n{\n  octave_print_internal (os, cell, pr_as_read_syntax, extra_indent,\n                         pr_as_string);\n}\n\nextern OCTINTERP_API void\noctave_print_internal (std::ostream& os, const octave_value& ov,\n                       bool pr_as_read_syntax = false);\n\ntemplate <typename T>\nclass pr_engineering_float\n{\npublic:\n\n  const float_format m_ff;\n\n  T m_val;\n\n  int exponent () const;\n\n  T mantissa () const;\n\n  pr_engineering_float (const float_format& ff, T val)\n    : m_ff (ff), m_val (val) { }\n\n  pr_engineering_float (const float_display_format& fdf, T val)\n    : m_ff (fdf.real_format ()), m_val (val) { }\n};\n\ntemplate <typename T>\nclass pr_formatted_float\n{\npublic:\n\n  const float_format m_ff;\n\n  T m_val;\n\n  pr_formatted_float (const float_format& ff, T val)\n    : m_ff (ff), m_val (val) { }\n\n  pr_formatted_float (const float_display_format& fdf, T val)\n    : m_ff (fdf.real_format ()), m_val (val) { }\n};\n\ntemplate <typename T>\nclass pr_rational_float\n{\npublic:\n\n  const float_format m_ff;\n\n  T m_val;\n\n  pr_rational_float (const float_format& ff, T val)\n    : m_ff (ff), m_val (val) { }\n\n  pr_rational_float (const float_display_format& fdf, T val)\n    : m_ff (fdf.real_format ()), m_val (val) { }\n};\n\ntemplate <typename T>\nextern std::ostream&\noperator << (std::ostream& os, const pr_engineering_float<T>& pef);\n\ntemplate <typename T>\nextern std::ostream&\noperator << (std::ostream& os, const pr_formatted_float<T>& pff);\n\ntemplate <typename T>\nextern std::ostream&\noperator << (std::ostream& os, const pr_rational_float<T>& prf);\n\n// TRUE means that the dimensions of empty objects should be printed\n// like this: x = [](2x0).\nextern bool Vprint_empty_dimensions;\n\n// TRUE means don't put empty lines in output\nextern bool Vcompact_format;\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/procstream.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"procstream.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nprocstreambase::procstreambase (const std::string& command, int mode)\n{\n  pb_init ();\n\n  if (! m_pb.open (command.c_str (), mode))\n    std::ios::setstate (std::ios::badbit);\n}\n\nprocstreambase::procstreambase (const char *command, int mode)\n{\n  pb_init ();\n\n  if (! m_pb.open (command, mode))\n    std::ios::setstate (std::ios::badbit);\n}\n\nvoid\nprocstreambase::open (const char *command, int mode)\n{\n  clear ();\n\n  if (! m_pb.open (command, mode))\n    std::ios::setstate (std::ios::badbit);\n}\n\nint\nprocstreambase::close ()\n{\n  int status = 0;\n\n  if (is_open ())\n    {\n      if (! m_pb.close ())\n        std::ios::setstate (std::ios::failbit);\n\n      status = m_pb.wait_status ();\n    }\n\n  return status;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/procstream.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_procstream_h)\n#define octave_procstream_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\n#include <sys/types.h>\n\n#include \"oct-procbuf.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API procstreambase : virtual public std::ios\n{\npublic:\n\n  procstreambase () : m_pb () { pb_init (); }\n\n  procstreambase (const std::string& name, int mode);\n\n  procstreambase (const char *name, int mode);\n\n  OCTAVE_DISABLE_COPY_MOVE (procstreambase)\n\n  ~procstreambase () { close (); }\n\n  void open (const std::string& name, int mode)\n  {\n    open (name.c_str (), mode);\n  }\n\n  void open (const char *name, int mode);\n\n  int is_open () const { return m_pb.is_open (); }\n\n  int close ();\n\n  pid_t pid () const { return m_pb.pid (); }\n\n  int file_number () const { return m_pb.file_number (); }\n\nprivate:\n\n  procbuf m_pb;\n\n  void pb_init ()\n  {\n    // Explicit initialization of the std::ios object is needed.\n    // FIXME: is there a better way to organize these classes?\n    init (&m_pb);\n  }\n};\n\nclass OCTINTERP_API iprocstream : public std::istream, public procstreambase\n{\npublic:\n\n  iprocstream () : std::istream (nullptr), procstreambase () { }\n\n  iprocstream (const std::string& name, int mode = std::ios::in)\n    : std::istream (nullptr), procstreambase (name, mode)\n  { }\n\n  iprocstream (const char *name, int mode = std::ios::in)\n    : std::istream (nullptr), procstreambase (name, mode)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (iprocstream)\n\n  ~iprocstream () = default;\n\n  void open (const std::string& name, int mode = std::ios::in)\n  {\n    procstreambase::open (name, mode);\n  }\n\n  void open (const char *name, int mode = std::ios::in)\n  {\n    procstreambase::open (name, mode);\n  }\n};\n\nclass OCTINTERP_API oprocstream : public std::ostream, public procstreambase\n{\npublic:\n\n  oprocstream () : std::ostream (nullptr), procstreambase () { }\n\n  oprocstream (const std::string& name, int mode = std::ios::out)\n    : std::ostream (nullptr), procstreambase (name, mode) { }\n\n  oprocstream (const char *name, int mode = std::ios::out)\n    : std::ostream (nullptr), procstreambase (name, mode) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (oprocstream)\n\n  ~oprocstream () = default;\n\n  void open (const std::string& name, int mode = std::ios::out)\n  {\n    procstreambase::open (name, mode);\n  }\n\n  void open (const char *name, int mode = std::ios::out)\n  {\n    procstreambase::open (name, mode);\n  }\n};\n\nclass OCTINTERP_API procstream : public std::iostream, public procstreambase\n{\npublic:\n\n  procstream () : std::iostream (nullptr), procstreambase () { }\n\n  procstream (const std::string& name, int mode)\n    : std::iostream (nullptr), procstreambase (name, mode)\n  { }\n\n  procstream (const char *name, int mode)\n    : std::iostream (nullptr), procstreambase (name, mode)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (procstream)\n\n  ~procstream () = default;\n\n  void open (const std::string& name, int mode)\n  {\n    procstreambase::open (name, mode);\n  }\n\n  void open (const char *name, int mode)\n  {\n    procstreambase::open (name, mode);\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/sighandlers.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <csignal>\n#include <cstdlib>\n\n#include <atomic>\n#include <iostream>\n#include <new>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  define WIN32_LEAN_AND_MEAN\n#  include <windows.h>\n#endif\n\n#include \"child-list.h\"\n#include \"cmd-edit.h\"\n#include \"oct-syscalls.h\"\n#include \"quit.h\"\n#include \"signal-wrappers.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-save.h\"\n#include \"octave.h\"\n#include \"oct-map.h\"\n#include \"pager.h\"\n#include \"sighandlers.h\"\n#include \"sysdep.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Nonzero means we have already printed a message for this series of\n// SIGPIPES.  We assume that the writer will eventually give up.\nint pipe_handler_error_count = 0;\n\n// TRUE means we can be interrupted.\nstd::atomic<bool> can_interrupt {false};\n\n// TRUE means we should try to enter the debugger on SIGINT.\nbool Vdebug_on_interrupt = false;\n\n// Allow users to avoid writing octave-workspace for SIGHUP (sent by\n// closing gnome-terminal, for example).  Note that this variable has\n// no effect if Vcrash_dumps_octave_core is FALSE.\nstatic bool Vsighup_dumps_octave_core = true;\n\n// Similar to Vsighup_dumps_octave_core, but for SIGQUIT signal.\nstatic bool Vsigquit_dumps_octave_core = true;\n\n// Similar to Vsighup_dumps_octave_core, but for SIGTERM signal.\nstatic bool Vsigterm_dumps_octave_core = true;\n\n// List of signals we have caught since last call to signal_handler.\nstatic std::atomic<bool> *signals_caught = nullptr;\n\nstatic void\nmy_friendly_exit (int sig, bool save_vars = true)\n{\n  std::cerr << \"fatal: caught signal \"\n            << octave_strsignal_wrapper (sig)\n            << \" -- stopping myself...\" << std::endl;\n\n  if (save_vars)\n    {\n      load_save_system& load_save_sys = __get_load_save_system__ ();\n\n      load_save_sys.dump_octave_core ();\n    }\n\n  sysdep_cleanup ();\n\n  throw exit_exception (1);\n}\n\n// Called from octave_quit () to actually do something about the signals\n// we have caught.\n\nvoid\nrespond_to_pending_signals ()\n{\n  // The list of signals is relatively short, so we will just go\n  // linearly through the list.\n\n  // Interrupt signals are currently handled separately.\n\n  static int sigint;\n  static const bool have_sigint\n    = octave_get_sig_number (\"SIGINT\", &sigint);\n\n  static int sigbreak;\n  static const bool have_sigbreak\n    = octave_get_sig_number (\"SIGBREAK\", &sigbreak);\n\n  // Termination signals.\n\n  static int sighup;\n  static const bool have_sighup\n    = octave_get_sig_number (\"SIGHUP\", &sighup);\n\n  static int sigquit;\n  static const bool have_sigquit\n    = octave_get_sig_number (\"SIGQUIT\", &sigquit);\n\n  static int sigterm;\n  static const bool have_sigterm\n    = octave_get_sig_number (\"SIGTERM\", &sigterm);\n\n  // Alarm signals.\n\n  static int sigalrm;\n  static const bool have_sigalrm\n    = octave_get_sig_number (\"SIGALRM\", &sigalrm);\n\n  static int sigvtalrm;\n  static const bool have_sigvtalrm\n    = octave_get_sig_number (\"SIGVTALRM\", &sigvtalrm);\n\n  // I/O signals.\n\n  static int sigio;\n  static const bool have_sigio\n    = octave_get_sig_number (\"SIGIO\", &sigio);\n\n  static int siglost;\n  static const bool have_siglost\n    = octave_get_sig_number (\"SIGLOST\", &siglost);\n\n  static int sigpipe;\n  static const bool have_sigpipe\n    = octave_get_sig_number (\"SIGPIPE\", &sigpipe);\n\n  // Job control signals.\n\n  static int sigchld;\n  static const bool have_sigchld\n    = octave_get_sig_number (\"SIGCHLD\", &sigchld);\n\n  static int sigcld;\n  static const bool have_sigcld\n    = octave_get_sig_number (\"SIGCLD\", &sigcld);\n\n  // Resource limit signals.\n\n  static int sigxcpu;\n  static const bool have_sigxcpu\n    = octave_get_sig_number (\"SIGXCPU\", &sigxcpu);\n\n  static int sigxfsz;\n  static const bool have_sigxfsz\n    = octave_get_sig_number (\"SIGXFSZ\", &sigxfsz);\n\n  // User signals.\n\n  static int sigusr1;\n  static const bool have_sigusr1\n    = octave_get_sig_number (\"SIGUSR1\", &sigusr1);\n\n  static int sigusr2;\n  static const bool have_sigusr2\n    = octave_get_sig_number (\"SIGUSR2\", &sigusr2);\n\n  child_list& kids = __get_child_list__ ();\n\n  for (int sig = 0; sig < octave_num_signals (); sig++)\n    {\n      bool expected = true;\n\n      if (signals_caught[sig].compare_exchange_strong (expected, false))\n        {\n          if ((have_sigchld && sig == sigchld)\n              || (have_sigcld && sig == sigcld))\n            {\n              // FIXME: should we block or ignore?\n              interrupt_handler saved_interrupt_handler = ignore_interrupts ();\n\n              void *context = octave_block_child ();\n\n              kids.wait ();\n\n              set_interrupt_handler (saved_interrupt_handler);\n\n              octave_unblock_child (context);\n\n              kids.reap ();\n            }\n          else if (have_sigpipe && sig == sigpipe)\n            {\n              std::cerr << \"warning: broken pipe\" << std::endl;\n\n              // Don't loop forever on account of this.\n              // FIXME: is this really needed?  Does it do anything\n              // useful now?\n\n              if (pipe_handler_error_count++ > 100\n                  && octave_interrupt_state >= 0)\n                octave_interrupt_state++;\n            }\n          else if (have_sighup && sig == sighup)\n            my_friendly_exit (sighup, Vsighup_dumps_octave_core);\n          else if (have_sigquit && sig == sigquit)\n            my_friendly_exit (sigquit, Vsigquit_dumps_octave_core);\n          else if (have_sigterm && sig == sigterm)\n            my_friendly_exit (sigterm, Vsigterm_dumps_octave_core);\n          else if ((have_sigalrm && sig == sigalrm)\n                   || (have_sigvtalrm && sig == sigvtalrm)\n                   || (have_sigio && sig == sigio)\n                   || (have_siglost && sig == siglost)\n                   || (have_sigxcpu && sig == sigxcpu)\n                   || (have_sigxfsz && sig == sigxfsz)\n                   || (have_sigusr1 && sig == sigusr1)\n                   || (have_sigusr2 && sig == sigusr2))\n            std::cerr << \"warning: ignoring signal: \"\n                      << octave_strsignal_wrapper (sig)\n                      << std::endl;\n          else if ((have_sigint && sig == sigint)\n                   || (have_sigbreak && sig == sigbreak))\n            ; // Handled separately; do nothing.\n          else\n            std::cerr << \"warning: ignoring unexpected signal: \"\n                      << octave_strsignal_wrapper (sig)\n                      << std::endl;\n        }\n    }\n}\n\nsig_handler *\nset_signal_handler (int sig, sig_handler *handler, bool restart_syscalls)\n{\n  return octave_set_signal_handler_internal (sig, handler, restart_syscalls);\n}\n\nsig_handler *\nset_signal_handler (const char *signame, sig_handler *handler,\n                    bool restart_syscalls)\n{\n  return octave_set_signal_handler_by_name (signame, handler,\n         restart_syscalls);\n}\n\nstatic void\ngeneric_sig_handler (int sig)\n{\n  // FIXME: this function may execute in a separate signal handler or\n  // signal watcher thread so it should probably be more careful about\n  // how it accesses global objects.\n\n  octave_signal_caught = true;\n\n  signals_caught[sig] = true;\n\n  static int sigint;\n  static const bool have_sigint\n    = octave_get_sig_number (\"SIGINT\", &sigint);\n\n  static int sigbreak;\n  static const bool have_sigbreak\n    = octave_get_sig_number (\"SIGBREAK\", &sigbreak);\n\n  if ((have_sigint && sig == sigint)\n      || (have_sigbreak && sig == sigbreak))\n    {\n      if (! octave_initialized)\n        std::exit (EXIT_FAILURE);\n\n      if (can_interrupt)\n        {\n          octave_signal_caught = true;\n          octave_interrupt_state++;\n        }\n    }\n}\n\nstatic void\ndeadly_sig_handler (int sig)\n{\n  std::cerr << \"fatal: caught signal \"\n            << octave_strsignal_wrapper (sig)\n            << \" -- stopping myself...\" << std::endl;\n\n  octave_set_default_signal_handler (sig);\n\n  octave_raise_wrapper (sig);\n}\n\nstatic void\nfpe_sig_handler (int)\n{\n  // FIXME: is there something better we can do?\n\n  std::cerr << \"warning: floating point exception\" << std::endl;\n}\n\ninterrupt_handler\ncatch_interrupts ()\n{\n  interrupt_handler retval;\n\n  retval.int_handler = set_signal_handler (\"SIGINT\", generic_sig_handler);\n  retval.brk_handler = set_signal_handler (\"SIGBREAK\", generic_sig_handler);\n\n  return retval;\n}\n\ninterrupt_handler\nignore_interrupts ()\n{\n  interrupt_handler retval;\n\n  retval.int_handler = set_signal_handler (\"SIGINT\", SIG_IGN);\n  retval.brk_handler = set_signal_handler (\"SIGBREAK\", SIG_IGN);\n\n  return retval;\n}\n\ninterrupt_handler\nset_interrupt_handler (const interrupt_handler& h, bool restart_syscalls)\n{\n  interrupt_handler retval;\n\n  retval.int_handler = set_signal_handler (\"SIGINT\", h.int_handler,\n                       restart_syscalls);\n\n  retval.brk_handler = set_signal_handler (\"SIGBREAK\", h.brk_handler,\n                       restart_syscalls);\n\n  return retval;\n}\n\n// Install all the handlers for the signals we might care about.\n\nvoid\ninstall_signal_handlers ()\n{\n  if (! signals_caught)\n    signals_caught = new std::atomic<bool> [octave_num_signals ()];\n\n  for (int i = 0; i < octave_num_signals (); i++)\n    signals_caught[i] = false;\n\n  // Interrupt signals.\n\n  catch_interrupts ();\n\n  // Program Error signals.  These are most likely unrecoverable for\n  // us.\n\n  set_signal_handler (\"SIGABRT\", deadly_sig_handler);\n  set_signal_handler (\"SIGBUS\", deadly_sig_handler);\n  set_signal_handler (\"SIGEMT\", deadly_sig_handler);\n  set_signal_handler (\"SIGILL\", deadly_sig_handler);\n  // SIGIOT is normally another name for SIGABRT.\n  set_signal_handler (\"SIGIOT\", deadly_sig_handler);\n  set_signal_handler (\"SIGSEGV\", deadly_sig_handler);\n  set_signal_handler (\"SIGSYS\", deadly_sig_handler);\n  set_signal_handler (\"SIGTRAP\", deadly_sig_handler);\n\n  // Handle SIGFPE separately.\n\n  set_signal_handler (\"SIGFPE\", fpe_sig_handler);\n\n  // Handle other signals for which the default action is to terminate\n  // the program.\n\n  // Termination signals.\n\n  set_signal_handler (\"SIGHUP\", generic_sig_handler);\n  set_signal_handler (\"SIGQUIT\", generic_sig_handler);\n  set_signal_handler (\"SIGTERM\", generic_sig_handler);\n\n  // Alarm signals.\n\n  set_signal_handler (\"SIGALRM\", generic_sig_handler);\n  set_signal_handler (\"SIGVTALRM\", generic_sig_handler);\n\n  // I/O signals.\n\n  set_signal_handler (\"SIGLOST\", generic_sig_handler);\n  set_signal_handler (\"SIGPIPE\", generic_sig_handler);\n\n  // Job control signals.  We only recognize signals about child\n  // processes.\n\n  set_signal_handler (\"SIGCHLD\", generic_sig_handler);\n  set_signal_handler (\"SIGCLD\", generic_sig_handler);\n\n  // Resource limit signals.\n\n  // FIXME: does it really make sense to try to handle the CPU limit\n  // signal?\n\n  set_signal_handler (\"SIGXCPU\", generic_sig_handler);\n  set_signal_handler (\"SIGXFSZ\", generic_sig_handler);\n\n  // User signals.\n\n  set_signal_handler (\"SIGUSR1\", generic_sig_handler);\n  set_signal_handler (\"SIGUSR2\", generic_sig_handler);\n\n  // This does nothing on Windows systems.\n  octave_create_interrupt_watcher_thread (generic_sig_handler);\n}\n\nstatic void\nset_sig_struct_field (octave_scalar_map& m, const char *signame)\n{\n  int signum;\n\n  // The names in the struct do not include the leading \"SIG\" prefix.\n\n  if (octave_get_sig_number (signame, &signum))\n    m.assign (&signame[3], signum);\n}\n\nstatic octave_scalar_map\nmake_sig_struct ()\n{\n  octave_scalar_map m;\n\n  set_sig_struct_field (m, \"SIGABRT\");\n  set_sig_struct_field (m, \"SIGALRM\");\n  set_sig_struct_field (m, \"SIGBUS\");\n  set_sig_struct_field (m, \"SIGCHLD\");\n  set_sig_struct_field (m, \"SIGCLD\");\n  set_sig_struct_field (m, \"SIGCONT\");\n  set_sig_struct_field (m, \"SIGEMT\");\n  set_sig_struct_field (m, \"SIGFPE\");\n  set_sig_struct_field (m, \"SIGHUP\");\n  set_sig_struct_field (m, \"SIGILL\");\n  set_sig_struct_field (m, \"SIGINFO\");\n  set_sig_struct_field (m, \"SIGINT\");\n  set_sig_struct_field (m, \"SIGIO\");\n  set_sig_struct_field (m, \"SIGIOT\");\n  set_sig_struct_field (m, \"SIGKILL\");\n  set_sig_struct_field (m, \"SIGLOST\");\n  set_sig_struct_field (m, \"SIGPIPE\");\n  set_sig_struct_field (m, \"SIGPOLL\");\n  set_sig_struct_field (m, \"SIGPROF\");\n  set_sig_struct_field (m, \"SIGPWR\");\n  set_sig_struct_field (m, \"SIGQUIT\");\n  set_sig_struct_field (m, \"SIGSEGV\");\n  set_sig_struct_field (m, \"SIGSTKFLT\");\n  set_sig_struct_field (m, \"SIGSTOP\");\n  set_sig_struct_field (m, \"SIGSYS\");\n  set_sig_struct_field (m, \"SIGTERM\");\n  set_sig_struct_field (m, \"SIGTRAP\");\n  set_sig_struct_field (m, \"SIGTSTP\");\n  set_sig_struct_field (m, \"SIGTTIN\");\n  set_sig_struct_field (m, \"SIGTTOU\");\n  set_sig_struct_field (m, \"SIGUNUSED\");\n  set_sig_struct_field (m, \"SIGURG\");\n  set_sig_struct_field (m, \"SIGUSR1\");\n  set_sig_struct_field (m, \"SIGUSR2\");\n  set_sig_struct_field (m, \"SIGVTALRM\");\n  set_sig_struct_field (m, \"SIGWINCH\");\n  set_sig_struct_field (m, \"SIGXCPU\");\n  set_sig_struct_field (m, \"SIGXFSZ\");\n\n  return m;\n}\n\nDEFUN (SIG, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{S} =} SIG ()\nReturn a structure containing Unix signal names and their defined values.\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  static octave_scalar_map m = make_sig_struct ();\n\n  return ovl (m);\n}\n\n/*\n%!assert (isstruct (SIG ()))\n%!assert (! isempty (SIG ()))\n\n%!error SIG (1)\n*/\n\nDEFUN (debug_on_interrupt, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} debug_on_interrupt ()\n@deftypefnx {} {@var{old_val} =} debug_on_interrupt (@var{new_val})\n@deftypefnx {} {@var{old_val} =} debug_on_interrupt (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave will try\nto enter debugging mode when it receives an interrupt signal (typically\ngenerated with @kbd{C-c}).\n\nIf a second interrupt signal is received before reaching the debugging mode,\na normal interrupt will occur.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{debug_on_error, debug_on_warning}\n@end deftypefn */)\n{\n  return set_internal_variable (Vdebug_on_interrupt, args, nargout,\n                                \"debug_on_interrupt\");\n}\n\n/*\n%!test\n%! orig_val = debug_on_interrupt ();\n%! old_val = debug_on_interrupt (! orig_val);\n%! assert (orig_val, old_val);\n%! assert (debug_on_interrupt (), ! orig_val);\n%! debug_on_interrupt (orig_val);\n%! assert (debug_on_interrupt (), orig_val);\n\n%!error debug_on_interrupt (1, 2)\n*/\n\nDEFUN (sighup_dumps_octave_core, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} sighup_dumps_octave_core ()\n@deftypefnx {} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})\n@deftypefnx {} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave tries\nto save all current variables to the file @file{octave-workspace} if it\nreceives a hangup signal.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  return set_internal_variable (Vsighup_dumps_octave_core,\n                                args, nargout,\n                                \"sighup_dumps_octave_core\");\n}\n\n/*\n%!test\n%! orig_val = sighup_dumps_octave_core ();\n%! old_val = sighup_dumps_octave_core (! orig_val);\n%! assert (orig_val, old_val);\n%! assert (sighup_dumps_octave_core (), ! orig_val);\n%! sighup_dumps_octave_core (orig_val);\n%! assert (sighup_dumps_octave_core (), orig_val);\n\n%!error sighup_dumps_octave_core (1, 2)\n*/\n\nDEFUN (sigquit_dumps_octave_core, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} sigquit_dumps_octave_core ()\n@deftypefnx {} {@var{old_val} =} sigquit_dumps_octave_core (@var{new_val})\n@deftypefnx {} {@var{old_val} =} sigquit_dumps_octave_core (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave tries\nto save all current variables to the file @file{octave-workspace} if it\nreceives a quit signal.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  return set_internal_variable (Vsigquit_dumps_octave_core,\n                                args, nargout,\n                                \"sigquit_dumps_octave_core\");\n}\n\n/*\n%!test\n%! orig_val = sigquit_dumps_octave_core ();\n%! old_val = sigquit_dumps_octave_core (! orig_val);\n%! assert (orig_val, old_val);\n%! assert (sigquit_dumps_octave_core (), ! orig_val);\n%! sigquit_dumps_octave_core (orig_val);\n%! assert (sigquit_dumps_octave_core (), orig_val);\n\n%!error sigquit_dumps_octave_core (1, 2)\n*/\n\nDEFUN (sigterm_dumps_octave_core, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} sigterm_dumps_octave_core ()\n@deftypefnx {} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})\n@deftypefnx {} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave tries\nto save all current variables to the file @file{octave-workspace} if it\nreceives a terminate signal.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  return set_internal_variable (Vsigterm_dumps_octave_core,\n                                args, nargout,\n                                \"sigterm_dumps_octave_core\");\n}\n\n/*\n%!test\n%! orig_val = sigterm_dumps_octave_core ();\n%! old_val = sigterm_dumps_octave_core (! orig_val);\n%! assert (orig_val, old_val);\n%! assert (sigterm_dumps_octave_core (), ! orig_val);\n%! sigterm_dumps_octave_core (orig_val);\n%! assert (sigterm_dumps_octave_core (), orig_val);\n\n%!error sigterm_dumps_octave_core (1, 2)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/sighandlers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nThe signal blocking macros defined below were adapted from similar\nfunctions from GNU Bash, the Bourne Again SHell, copyright (C) 1994\nFree Software Foundation, Inc.\n\n*/\n\n// This file should always be included after config.h!\n\n#if ! defined (octave_sighandlers_h)\n#define octave_sighandlers_h 1\n\n#include <atomic>\n\n#include \"octave-config.h\"\n\n#include \"child-list.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// This type must match the typedef in signal-wrappers.h.\ntypedef void sig_handler (int);\n\nstruct interrupt_handler\n{\n  sig_handler *int_handler;\n  sig_handler *brk_handler;\n};\n\n// Nonzero means we have already printed a message for this series of\n// SIGPIPES.  We assume that the writer will eventually give up.\nextern int pipe_handler_error_count;\n\n// TRUE means we can be interrupted.\nextern OCTINTERP_API std::atomic<bool> can_interrupt;\n\nextern OCTINTERP_API sig_handler *\nset_signal_handler (int sig, sig_handler *h,\n                    bool restart_syscalls = true);\n\nextern OCTINTERP_API sig_handler *\nset_signal_handler (const char *signame, sig_handler *h,\n                    bool restart_syscalls = true);\n\nextern OCTINTERP_API void install_signal_handlers ();\n\nextern OCTINTERP_API void respond_to_pending_signals ();\n\nextern OCTINTERP_API interrupt_handler catch_interrupts ();\n\nextern OCTINTERP_API interrupt_handler ignore_interrupts ();\n\nextern OCTINTERP_API interrupt_handler\nset_interrupt_handler (const interrupt_handler& h,\n                       bool restart_syscalls = true);\n\n// TRUE means we should try to enter the debugger on SIGINT.\nextern OCTINTERP_API bool Vdebug_on_interrupt;\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/sparse-xdiv.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-util.h\"\n#include \"lo-array-errwarn.h\"\n#include \"oct-cmplx.h\"\n#include \"quit.h\"\n#include \"error.h\"\n#include \"lo-ieee.h\"\n\n#include \"dSparse.h\"\n#include \"dDiagMatrix.h\"\n#include \"CSparse.h\"\n#include \"CDiagMatrix.h\"\n#include \"oct-spparms.h\"\n#include \"sparse-xdiv.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic void\nsolve_singularity_warning (double rcond)\n{\n  octave::warn_singular_matrix (rcond);\n}\n\ntemplate <typename T1, typename T2>\nbool\nmx_leftdiv_conform (const T1& a, const T2& b)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type b_nr = b.rows ();\n\n  if (a_nr != b_nr)\n    {\n      octave_idx_type a_nc = a.cols ();\n      octave_idx_type b_nc = b.cols ();\n\n      octave::err_nonconformant (R\"(operator \\)\", a_nr, a_nc, b_nr, b_nc);\n    }\n\n  return true;\n}\n\n#define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2)                  \\\n  template bool mx_leftdiv_conform (const T1&, const T2&)\n\nINSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseComplexMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, Matrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, ComplexMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, Matrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, ComplexMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseComplexMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseComplexMatrix);\n\ntemplate <typename T1, typename T2>\nbool\nmx_div_conform (const T1& a, const T2& b)\n{\n  octave_idx_type a_nc = a.cols ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nc)\n    {\n      octave_idx_type a_nr = a.rows ();\n      octave_idx_type b_nr = b.rows ();\n\n      octave::err_nonconformant (\"operator /\", a_nr, a_nc, b_nr, b_nc);\n    }\n\n  return true;\n}\n\n#define INSTANTIATE_MX_DIV_CONFORM(T1, T2)              \\\n  template bool mx_div_conform (const T1&, const T2&)\n\nINSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseMatrix);\nINSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseComplexMatrix);\nINSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseMatrix);\nINSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);\nINSTANTIATE_MX_DIV_CONFORM (Matrix, SparseMatrix);\nINSTANTIATE_MX_DIV_CONFORM (Matrix, SparseComplexMatrix);\nINSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseMatrix);\nINSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseComplexMatrix);\nINSTANTIATE_MX_DIV_CONFORM (SparseMatrix, DiagMatrix);\nINSTANTIATE_MX_DIV_CONFORM (SparseMatrix, ComplexDiagMatrix);\nINSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, DiagMatrix);\nINSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, ComplexDiagMatrix);\n\n// Right division functions.  X / Y = X * inv (Y) = (inv (Y') * X')'\n//\n//                  Y / X:   m   cm   sm  scm\n//                   +--   +---+----+----+----+\n//   sparse matrix         | 1 |  3 |  5 |  7 |\n//                         +---+----+----+----+\n//   sparse complex_matrix | 2 |  4 |  6 |  8 |\n//                         +---+----+----+----+\n//   diagonal matrix                |  9 | 11 |\n//                                  +----+----+\n//   complex diag. matrix           | 10 | 12 |\n//                                  +----+----+\n\n// -*- 1 -*-\nMatrix\nxdiv (const Matrix& a, const SparseMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return Matrix ();\n\n  Matrix atmp = a.transpose ();\n  SparseMatrix btmp = b.transpose ();\n  MatrixType btyp = typ.transpose ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  Matrix result = btmp.solve (btyp, atmp, info, rcond,\n                              solve_singularity_warning);\n\n  typ = btyp.transpose ();\n  return result.transpose ();\n}\n\n// -*- 2 -*-\nComplexMatrix\nxdiv (const Matrix& a, const SparseComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return ComplexMatrix ();\n\n  Matrix atmp = a.transpose ();\n  SparseComplexMatrix btmp = b.hermitian ();\n  MatrixType btyp = typ.transpose ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  ComplexMatrix result\n    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);\n\n  typ = btyp.transpose ();\n  return result.hermitian ();\n}\n\n// -*- 3 -*-\nComplexMatrix\nxdiv (const ComplexMatrix& a, const SparseMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return ComplexMatrix ();\n\n  ComplexMatrix atmp = a.hermitian ();\n  SparseMatrix btmp = b.transpose ();\n  MatrixType btyp = typ.transpose ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  ComplexMatrix result\n    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);\n\n  typ = btyp.transpose ();\n  return result.hermitian ();\n}\n\n// -*- 4 -*-\nComplexMatrix\nxdiv (const ComplexMatrix& a, const SparseComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return ComplexMatrix ();\n\n  ComplexMatrix atmp = a.hermitian ();\n  SparseComplexMatrix btmp = b.hermitian ();\n  MatrixType btyp = typ.transpose ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  ComplexMatrix result\n    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);\n\n  typ = btyp.transpose ();\n  return result.hermitian ();\n}\n\n// -*- 5 -*-\nSparseMatrix\nxdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return SparseMatrix ();\n\n  SparseMatrix atmp = a.transpose ();\n  SparseMatrix btmp = b.transpose ();\n  MatrixType btyp = typ.transpose ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  SparseMatrix result = btmp.solve (btyp, atmp, info, rcond,\n                                    solve_singularity_warning);\n\n  typ = btyp.transpose ();\n  return result.transpose ();\n}\n\n// -*- 6 -*-\nSparseComplexMatrix\nxdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return SparseComplexMatrix ();\n\n  SparseMatrix atmp = a.transpose ();\n  SparseComplexMatrix btmp = b.hermitian ();\n  MatrixType btyp = typ.transpose ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  SparseComplexMatrix result\n    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);\n\n  typ = btyp.transpose ();\n  return result.hermitian ();\n}\n\n// -*- 7 -*-\nSparseComplexMatrix\nxdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return SparseComplexMatrix ();\n\n  SparseComplexMatrix atmp = a.hermitian ();\n  SparseMatrix btmp = b.transpose ();\n  MatrixType btyp = typ.transpose ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  SparseComplexMatrix result\n    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);\n\n  typ = btyp.transpose ();\n  return result.hermitian ();\n}\n\n// -*- 8 -*-\nSparseComplexMatrix\nxdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n      MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return SparseComplexMatrix ();\n\n  SparseComplexMatrix atmp = a.hermitian ();\n  SparseComplexMatrix btmp = b.hermitian ();\n  MatrixType btyp = typ.transpose ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  SparseComplexMatrix result\n    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);\n\n  typ = btyp.transpose ();\n  return result.hermitian ();\n}\n\ntemplate <typename RT, typename SM, typename DM>\nRT\ndo_rightdiv_sm_dm (const SM& a, const DM& d)\n{\n  const octave_idx_type d_nr = d.rows ();\n\n  const octave_idx_type a_nr = a.rows ();\n  const octave_idx_type a_nc = a.cols ();\n\n  using std::min;\n  const octave_idx_type nc = min (d_nr, a_nc);\n\n  if (! mx_div_conform (a, d))\n    return RT ();\n\n  const octave_idx_type nz = a.nnz ();\n  RT r (a_nr, nc, nz);\n\n  typedef typename DM::element_type DM_elt_type;\n  const DM_elt_type zero = DM_elt_type ();\n\n  octave_idx_type k_result = 0;\n  for (octave_idx_type j = 0; j < nc; ++j)\n    {\n      octave_quit ();\n      const DM_elt_type s = d.dgelem (j);\n      const octave_idx_type colend = a.cidx (j+1);\n      r.xcidx (j) = k_result;\n      if (s != zero)\n        for (octave_idx_type k = a.cidx (j); k < colend; ++k)\n          {\n            r.xdata (k_result) = a.data (k) / s;\n            r.xridx (k_result) = a.ridx (k);\n            ++k_result;\n          }\n    }\n  r.xcidx (nc) = k_result;\n\n  r.maybe_compress (true);\n  return r;\n}\n\n// -*- 9 -*-\nSparseMatrix\nxdiv (const SparseMatrix& a, const DiagMatrix& b, MatrixType&)\n{\n  return do_rightdiv_sm_dm<SparseMatrix> (a, b);\n}\n\n// -*- 10 -*-\nSparseComplexMatrix\nxdiv (const SparseMatrix& a, const ComplexDiagMatrix& b, MatrixType&)\n{\n  return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);\n}\n\n// -*- 11 -*-\nSparseComplexMatrix\nxdiv (const SparseComplexMatrix& a, const DiagMatrix& b, MatrixType&)\n{\n  return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);\n}\n\n// -*- 12 -*-\nSparseComplexMatrix\nxdiv (const SparseComplexMatrix& a, const ComplexDiagMatrix& b, MatrixType&)\n{\n  return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);\n}\n\n// Funny element by element division operations.\n//\n//       op2 \\ op1:   s   cs\n//            +--   +---+----+\n//   matrix         | 1 |  3 |\n//                  +---+----+\n//   complex_matrix | 2 |  4 |\n//                  +---+----+\n\nMatrix\nelem_xdiv (double a, const SparseMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  Matrix result;\n  if (octave::math::isnan (a))\n    {\n      result = Matrix (nr, nc, octave::numeric_limits<double>::NaN ());\n      return result;\n    }\n  if (a == 0.)\n    result = Matrix (nr, nc, octave::numeric_limits<double>::NaN ());\n  else if (a > 0.)\n    result = Matrix (nr, nc, octave::numeric_limits<double>::Inf ());\n  else\n    result = Matrix (nr, nc, -octave::numeric_limits<double>::Inf ());\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n      {\n        octave_quit ();\n        result.elem (b.ridx (i), j) = a / b.data (i);\n      }\n\n  return result;\n}\n\nComplexMatrix\nelem_xdiv (double a, const SparseComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  ComplexMatrix result;\n  if (octave::math::isnan (a))\n    {\n      result = ComplexMatrix (nr, nc,\n                              Complex (octave::numeric_limits<double>::NaN (),\n                                       octave::numeric_limits<double>::NaN ()));\n      return result;\n    }\n  if (a == 0.)\n    result = ComplexMatrix (nr, nc,\n                            Complex (octave::numeric_limits<double>::NaN (),\n                                     octave::numeric_limits<double>::NaN ()));\n  else if (a > 0.)\n    result = ComplexMatrix (nr, nc,\n                            Complex (octave::numeric_limits<double>::Inf (),\n                                     octave::numeric_limits<double>::Inf ()));\n  else\n    result = ComplexMatrix (nr, nc,\n                            Complex (-octave::numeric_limits<double>::Inf (),\n                                     -octave::numeric_limits<double>::Inf ()));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n      {\n        octave_quit ();\n        result.elem (b.ridx (i), j) = a / b.data (i);\n      }\n\n  return result;\n}\n\nComplexMatrix\nelem_xdiv (const Complex& a, const SparseMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  ComplexMatrix result (nr, nc, (a / 0.0));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n      {\n        octave_quit ();\n        result.elem (b.ridx (i), j) = a / b.data (i);\n      }\n\n  return result;\n}\n\nComplexMatrix\nelem_xdiv (const Complex& a, const SparseComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  ComplexMatrix result (nr, nc, (a / 0.0));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n      {\n        octave_quit ();\n        result.elem (b.ridx (i), j) = a / b.data (i);\n      }\n\n  return result;\n}\n\n// Left division functions.  X \\ Y = inv (X) * Y\n//\n//               Y  \\  X :   sm  scm  dm  dcm\n//                   +--   +---+----+\n//   matrix                | 1 |  5 |\n//                         +---+----+\n//   complex_matrix        | 2 |  6 |\n//                         +---+----+----+----+\n//   sparse matrix         | 3 |  7 |  9 | 11 |\n//                         +---+----+----+----+\n//   sparse complex_matrix | 4 |  8 | 10 | 12 |\n//                         +---+----+----+----+\n\n// -*- 1 -*-\nMatrix\nxleftdiv (const SparseMatrix& a, const Matrix& b, MatrixType& typ)\n{\n  if (! mx_leftdiv_conform (a, b))\n    return Matrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning);\n}\n\n// -*- 2 -*-\nComplexMatrix\nxleftdiv (const SparseMatrix& a, const ComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_leftdiv_conform (a, b))\n    return ComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning);\n}\n\n// -*- 3 -*-\nSparseMatrix\nxleftdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType& typ)\n{\n  if (! mx_leftdiv_conform (a, b))\n    return SparseMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning);\n}\n\n// -*- 4 -*-\nSparseComplexMatrix\nxleftdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_leftdiv_conform (a, b))\n    return SparseComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning);\n}\n\n// -*- 5 -*-\nComplexMatrix\nxleftdiv (const SparseComplexMatrix& a, const Matrix& b, MatrixType& typ)\n{\n  if (! mx_leftdiv_conform (a, b))\n    return ComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning);\n}\n\n// -*- 6 -*-\nComplexMatrix\nxleftdiv (const SparseComplexMatrix& a, const ComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_leftdiv_conform (a, b))\n    return ComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning);\n}\n\n// -*- 7 -*-\nSparseComplexMatrix\nxleftdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType& typ)\n{\n  if (! mx_leftdiv_conform (a, b))\n    return SparseComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning);\n}\n\n// -*- 8 -*-\nSparseComplexMatrix\nxleftdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n          MatrixType& typ)\n{\n  if (! mx_leftdiv_conform (a, b))\n    return SparseComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning);\n}\n\ntemplate <typename RT, typename DM, typename SM>\nRT\ndo_leftdiv_dm_sm (const DM& d, const SM& a)\n{\n  const octave_idx_type a_nr = a.rows ();\n  const octave_idx_type a_nc = a.cols ();\n\n  const octave_idx_type d_nc = d.cols ();\n\n  using std::min;\n  const octave_idx_type nr = min (d_nc, a_nr);\n\n  if (! mx_leftdiv_conform (d, a))\n    return RT ();\n\n  const octave_idx_type nz = a.nnz ();\n  RT r (nr, a_nc, nz);\n\n  typedef typename DM::element_type DM_elt_type;\n  const DM_elt_type zero = DM_elt_type ();\n\n  octave_idx_type k_result = 0;\n  for (octave_idx_type j = 0; j < a_nc; ++j)\n    {\n      octave_quit ();\n      const octave_idx_type colend = a.cidx (j+1);\n      r.xcidx (j) = k_result;\n      for (octave_idx_type k = a.cidx (j); k < colend; ++k)\n        {\n          const octave_idx_type i = a.ridx (k);\n          if (i < nr)\n            {\n              const DM_elt_type s = d.dgelem (i);\n              if (s != zero)\n                {\n                  r.xdata (k_result) = a.data (k) / s;\n                  r.xridx (k_result) = i;\n                  ++k_result;\n                }\n            }\n        }\n    }\n  r.xcidx (a_nc) = k_result;\n\n  r.maybe_compress (true);\n  return r;\n}\n\n// -*- 9 -*-\nSparseMatrix\nxleftdiv (const DiagMatrix& d, const SparseMatrix& a, MatrixType&)\n{\n  return do_leftdiv_dm_sm<SparseMatrix> (d, a);\n}\n\n// -*- 10 -*-\nSparseComplexMatrix\nxleftdiv (const DiagMatrix& d, const SparseComplexMatrix& a, MatrixType&)\n{\n  return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);\n}\n\n// -*- 11 -*-\nSparseComplexMatrix\nxleftdiv (const ComplexDiagMatrix& d, const SparseMatrix& a, MatrixType&)\n{\n  return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);\n}\n\n// -*- 12 -*-\nSparseComplexMatrix\nxleftdiv (const ComplexDiagMatrix& d, const SparseComplexMatrix& a,\n          MatrixType&)\n{\n  return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/sparse-xdiv.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_sparse_xdiv_h)\n#define octave_sparse_xdiv_h 1\n\n#include \"octave-config.h\"\n\n#include \"oct-cmplx.h\"\n#include \"MatrixType.h\"\n\nclass DiagMatrix;\nclass ComplexDiagMatrix;\nclass SparseMatrix;\nclass SparseComplexMatrix;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern Matrix xdiv (const Matrix& a, const SparseMatrix& b, MatrixType& typ);\nextern ComplexMatrix xdiv (const Matrix& a, const SparseComplexMatrix& b,\n                           MatrixType& typ);\nextern ComplexMatrix xdiv (const ComplexMatrix& a, const SparseMatrix& b,\n                           MatrixType& typ);\nextern ComplexMatrix xdiv (const ComplexMatrix& a,\n                           const SparseComplexMatrix& b, MatrixType& typ);\n\nextern SparseMatrix xdiv (const SparseMatrix& a, const SparseMatrix& b,\n                          MatrixType& typ);\nextern SparseComplexMatrix xdiv (const SparseMatrix& a,\n                                 const SparseComplexMatrix& b, MatrixType& typ);\nextern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,\n                                 const SparseMatrix& b, MatrixType& typ);\nextern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,\n                                 const SparseComplexMatrix& b, MatrixType& typ);\n\nextern SparseMatrix xdiv (const SparseMatrix& a,\n                          const DiagMatrix& b, MatrixType& typ);\nextern SparseComplexMatrix xdiv (const SparseMatrix& a,\n                                 const ComplexDiagMatrix& b, MatrixType& typ);\nextern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,\n                                 const DiagMatrix& b, MatrixType& typ);\nextern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,\n                                 const ComplexDiagMatrix& b, MatrixType& typ);\n\nextern Matrix elem_xdiv (double a, const SparseMatrix& b);\nextern ComplexMatrix elem_xdiv (double a, const SparseComplexMatrix& b);\nextern ComplexMatrix elem_xdiv (const Complex& a, const SparseMatrix& b);\nextern ComplexMatrix elem_xdiv (const Complex& a,\n                                const SparseComplexMatrix& b);\n\nextern Matrix xleftdiv (const SparseMatrix& a, const Matrix& b,\n                        MatrixType& typ);\nextern ComplexMatrix xleftdiv (const SparseMatrix& a, const ComplexMatrix& b,\n                               MatrixType& typ);\nextern ComplexMatrix xleftdiv (const SparseComplexMatrix& a, const Matrix& b,\n                               MatrixType& typ);\nextern ComplexMatrix xleftdiv (const SparseComplexMatrix& a,\n                               const ComplexMatrix& b, MatrixType& typ);\n\nextern SparseMatrix xleftdiv (const SparseMatrix& a, const SparseMatrix& b,\n                              MatrixType& typ);\nextern SparseComplexMatrix xleftdiv (const SparseMatrix& a,\n                                     const SparseComplexMatrix& b,\n                                     MatrixType& typ);\nextern SparseComplexMatrix xleftdiv (const SparseComplexMatrix& a,\n                                     const SparseMatrix& b, MatrixType& typ);\nextern SparseComplexMatrix xleftdiv (const SparseComplexMatrix& a,\n                                     const SparseComplexMatrix& b,\n                                     MatrixType& typ);\n\nextern SparseMatrix xleftdiv (const DiagMatrix&, const SparseMatrix&,\n                              MatrixType&);\nextern SparseComplexMatrix xleftdiv (const ComplexDiagMatrix&,\n                                     const SparseMatrix&,\n                                     MatrixType&);\nextern SparseComplexMatrix xleftdiv (const DiagMatrix&,\n                                     const SparseComplexMatrix&,\n                                     MatrixType&);\nextern SparseComplexMatrix xleftdiv (const ComplexDiagMatrix&,\n                                     const SparseComplexMatrix&,\n                                     MatrixType&);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/sparse-xpow.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <limits>\n\n#include \"Array-util.h\"\n#include \"oct-cmplx.h\"\n#include \"quit.h\"\n\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\n#include \"dSparse.h\"\n#include \"CSparse.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n#include \"sparse-xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic inline bool\nxisint (double x)\n{\n  // FIXME: If we return *only* octave::math::is_integer (x)\n  // and delete the lines with numeric_limits<int>,\n  // then that works on MacOS but not on Linux.\n  // It fails a test in sparse.tst that requires this calculation:\n  // Complex (realmin, realmin) .^ realmax.\n  // On MacOS it correctly gives zero, matching Matlab.\n  // On Linux it gives Inf + Nani.\n  // If we can make both platforms work without the extra check with\n  // numeric_limits<int>, then we should do so.\n  return (octave::math::is_integer (x)\n          && ((x >= 0 && x < std::numeric_limits<int>::max ())\n              || (x <= 0 && x > std::numeric_limits<int>::min ())));\n}\n\n// Safer pow functions.  Only two make sense for sparse matrices, the\n// others should all promote to full matrices.\n\ntemplate<typename T>\nstatic octave_value\nxpow_private (const T& a, double b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return T ();\n\n  // If we are here, A is not empty ==> A needs to be square.\n  if (nr != nc)\n    error (\"for A^b, A must be a square matrix.  Use .^ for elementwise power.\");\n\n  if (! xisint (b))\n    error (\"use full(a) ^ full(b)\");\n\n  int btmp = static_cast<int> (b);\n  if (btmp == 0)\n    {\n      // Return sparse identity matrix, so it's always type SparseMatrix\n      // and does not have to be templated by typename T.\n      SparseMatrix tmp = SparseMatrix (nr, nr, nr);\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          tmp.data (i) = 1.0;\n          tmp.ridx (i) = i;\n        }\n      for (octave_idx_type i = 0; i < nr + 1; i++)\n        tmp.cidx (i) = i;\n\n      retval = tmp;\n    }\n  else\n    {\n      T atmp;\n      if (btmp < 0)\n        {\n          btmp = -btmp;\n\n          octave_idx_type info;\n          double rcond = 0.0;\n          MatrixType mattyp (a);\n\n          // FIXME: This causes an error if the input sparse matrix is all-zeros.\n          // That behavior is inconsistent with A ^ b when A is a full all-zeros\n          // matrix, which just returns Inf of the same size with a warning.\n          atmp = a.inverse (mattyp, info, rcond, 1);\n\n          if (info == -1)\n            warning (\"inverse: matrix singular to machine precision, rcond = %g\", rcond);\n        }\n      else\n        atmp = a;\n\n      if (atmp.nnz () == 0)  // Fast return for all-zeros matrix\n        return atmp;\n\n      T result (atmp);\n\n      btmp--;\n\n      // There are two approaches to the actual exponentiation.\n      // Exponentiation by squaring uses only a logarithmic number\n      // of multiplications but the matrices it multiplies tend to be dense\n      // towards the end.\n      // Linear multiplication uses a linear number of multiplications\n      // but one of the matrices it uses will be as sparse as the original\n      // matrix.\n      //\n      // The time to multiply fixed-size matrices is strongly affected by their\n      // sparsity.  Denser matrices take much longer to multiply together.\n      // See this URL for a worked-through example:\n      // https://octave.discourse.group/t/3216/4\n      //\n      // The tradeoff is between many fast multiplications or a few slow ones.\n      //\n      // Large exponents favor the squaring technique, and sparse matrices\n      // favor linear multiplication.\n      //\n      // We calculate a threshold based on the sparsity of the input\n      // and use squaring for exponents larger than that.\n      //\n      // FIXME: Improve this threshold calculation.\n\n      uint64_t sparsity = atmp.numel () / atmp.nnz (); // reciprocal of density\n      int threshold = (sparsity >= 1000) ? 40\n                      : (sparsity >=  100) ? 20\n                      : 3;\n\n      if (btmp > threshold) // use squaring technique\n        {\n          while (btmp > 0)\n            {\n              if (btmp & 1)\n                result = result * atmp;\n\n              btmp >>= 1;\n\n              if (btmp > 0)\n                atmp = atmp * atmp;\n            }\n        }\n      else // use linear multiplication\n        {\n          for (int i = 0; i < btmp; i++)\n            result = result * atmp;\n        }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\noctave_value\nxpow (const SparseMatrix& a, double b)\n{\n  return xpow_private<SparseMatrix> (a, b);\n}\n\noctave_value\nxpow (const SparseComplexMatrix& a, double b)\n{\n  return xpow_private<SparseComplexMatrix> (a, b);\n}\n\n// Safer pow functions that work elementwise for matrices.\n//\n//       op2 \\ op1:   s   m   cs   cm\n//            +--   +---+---+----+----+\n//   scalar   |     | * | 3 |  * |  9 |\n//                  +---+---+----+----+\n//   matrix         | 1 | 4 |  7 | 10 |\n//                  +---+---+----+----+\n//   complex_scalar | * | 5 |  * | 11 |\n//                  +---+---+----+----+\n//   complex_matrix | 2 | 6 |  8 | 12 |\n//                  +---+---+----+----+\n//\n//   * -> not needed.\n\n// FIXME: these functions need to be fixed so that things\n// like\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b\n//\n// and\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end\n//\n// produce identical results.  Also, it would be nice if -1^0.5\n// produced a pure imaginary result instead of a complex number with a\n// small real part.  But perhaps that's really a problem with the math\n// library...\n\n// Handle special case of scalar-sparse-matrix .^ sparse-matrix.\n// Forwarding to the scalar elem_xpow function and then converting the\n// result back to a sparse matrix is a bit wasteful but it does not\n// seem worth the effort to optimize -- how often does this case come up\n// in practice?\n\ntemplate <typename S, typename SM>\ninline octave_value\nscalar_xpow (const S& a, const SM& b)\n{\n  octave_value val = elem_xpow (a, b);\n\n  if (val.iscomplex ())\n    return SparseComplexMatrix (val.complex_matrix_value ());\n  else\n    return SparseMatrix (val.matrix_value ());\n}\n\n/*\n%!assert (sparse (2) .^ [3, 4], sparse ([8, 16]))\n%!assert <47775> (sparse (2i) .^ [3, 4], sparse ([-0-8i, 16]))\n\n%!test <*63080>\n%! Z = sparse ([]);\n%! A = sparse (zeros (0, 2));\n%! B = sparse (zeros (2, 0));\n%! assert (Z ^  1, Z);\n%! assert (Z ^  0, Z);\n%! assert (Z ^ -1, Z);\n%! assert (A ^  1, Z);\n%! assert (A ^  0, Z);\n%! assert (A ^ -1, Z);\n%! assert (B ^  1, Z);\n%! assert (B ^  0, Z);\n%! assert (B ^ -1, Z);\n\n%!test <*63080>\n%! A = sparse (zeros (2, 2));\n%! assert (A ^  1, A);\n%! assert (A ^  0, sparse (eye (2, 2)));\n\n%!test <63080>\n%! A = sparse (zeros (2, 2));\n%! assert (A ^ -1, sparse (inf (2, 2)));\n\n*/\n\n// -*- 1 -*-\noctave_value\nelem_xpow (double a, const SparseMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  double d1, d2;\n\n  if (a < 0.0 && ! b.all_integers (d1, d2))\n    {\n      Complex atmp (a);\n      ComplexMatrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          for (octave_idx_type i = 0; i < nr; i++)\n            {\n              octave_quit ();\n              result(i, j) = std::pow (atmp, b(i, j));\n            }\n        }\n\n      retval = result;\n    }\n  else\n    {\n      Matrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          for (octave_idx_type i = 0; i < nr; i++)\n            {\n              octave_quit ();\n              result(i, j) = std::pow (a, b(i, j));\n            }\n        }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 2 -*-\noctave_value\nelem_xpow (double a, const SparseComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  Complex atmp (a);\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_quit ();\n          result(i, j) = std::pow (atmp, b(i, j));\n        }\n    }\n\n  return result;\n}\n\n// -*- 3 -*-\noctave_value\nelem_xpow (const SparseMatrix& a, double b)\n{\n  // FIXME: What should a .^ 0 give?  Matlab gives a\n  // sparse matrix with same structure as a, which is strictly\n  // incorrect.  Keep compatibility.\n\n  octave_value retval;\n\n  octave_idx_type nz = a.nnz ();\n\n  if (b <= 0.0)\n    {\n      octave_idx_type nr = a.rows ();\n      octave_idx_type nc = a.cols ();\n\n      if (! xisint (b) && a.any_element_is_negative ())\n        {\n          ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n              {\n                octave_quit ();\n                result(a.ridx (i), j) = std::pow (a.data (i), b);\n              }\n\n          retval = octave_value (result);\n        }\n      else\n        {\n          Matrix result (nr, nc, (std::pow (0.0, b)));\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n              {\n                octave_quit ();\n                result(a.ridx (i), j) = std::pow (a.data (i), b);\n              }\n\n          retval = octave_value (result);\n        }\n    }\n  else if (! xisint (b) && a.any_element_is_negative ())\n    {\n      SparseComplexMatrix result (a);\n\n      for (octave_idx_type i = 0; i < nz; i++)\n        {\n          octave_quit ();\n          result.data (i) = std::pow (a.data (i), b);\n        }\n\n      result.maybe_compress (true);\n\n      retval = result;\n    }\n  else\n    {\n      SparseMatrix result (a);\n\n      for (octave_idx_type i = 0; i < nz; i++)\n        {\n          octave_quit ();\n          result.data (i) = std::pow (a.data (i), b);\n        }\n\n      result.maybe_compress (true);\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 4 -*-\noctave_value\nelem_xpow (const SparseMatrix& a, const SparseMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a.numel () == 1 && b.numel () > 1)\n    return scalar_xpow (a(0), b);\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  int convert_to_complex = 0;\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n      {\n        if (a.data(i) < 0.0)\n          {\n            double btmp = b (a.ridx (i), j);\n            if (! xisint (btmp))\n              {\n                convert_to_complex = 1;\n                goto done;\n              }\n          }\n      }\n\ndone:\n\n  // This is a dumb operator for sparse matrices anyway, and there is\n  // no sensible way to handle the 0.^0 versus the 0.^x cases.  Therefore\n  // allocate a full matrix filled for the 0.^0 case and shrink it later\n  // as needed.\n\n  if (convert_to_complex)\n    {\n      SparseComplexMatrix complex_result (nr, nc, Complex (1.0, 0.0));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n            {\n              octave_quit ();\n              complex_result.xelem (a.ridx (i), j)\n                = std::pow (Complex (a.data (i)), Complex (b(a.ridx (i), j)));\n            }\n        }\n      complex_result.maybe_compress (true);\n      retval = complex_result;\n    }\n  else\n    {\n      SparseMatrix result (nr, nc, 1.0);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n            {\n              octave_quit ();\n              result.xelem (a.ridx (i), j) = std::pow (a.data (i),\n                                             b(a.ridx (i), j));\n            }\n        }\n      result.maybe_compress (true);\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 5 -*-\noctave_value\nelem_xpow (const SparseMatrix& a, const Complex& b)\n{\n  octave_value retval;\n\n  if (b == 0.0)\n    // Can this case ever happen, due to automatic retyping with maybe_mutate?\n    retval = octave_value (NDArray (a.dims (), 1));\n  else\n    {\n      octave_idx_type nz = a.nnz ();\n      SparseComplexMatrix result (a);\n\n      for (octave_idx_type i = 0; i < nz; i++)\n        {\n          octave_quit ();\n          result.data (i) = std::pow (Complex (a.data (i)), b);\n        }\n\n      result.maybe_compress (true);\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 6 -*-\noctave_value\nelem_xpow (const SparseMatrix& a, const SparseComplexMatrix& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a.numel () == 1 && b.numel () > 1)\n    return scalar_xpow (a(0), b);\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n        {\n          octave_quit ();\n          result.xelem (a.ridx(i), j) = std::pow (a.data (i), b(a.ridx (i), j));\n        }\n    }\n\n  result.maybe_compress (true);\n\n  return result;\n}\n\n// -*- 7 -*-\noctave_value\nelem_xpow (const Complex& a, const SparseMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_quit ();\n          double btmp = b (i, j);\n          if (xisint (btmp))\n            result (i, j) = std::pow (a, static_cast<int> (btmp));\n          else\n            result (i, j) = std::pow (a, btmp);\n        }\n    }\n\n  return result;\n}\n\n// -*- 8 -*-\noctave_value\nelem_xpow (const Complex& a, const SparseComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  ComplexMatrix result (nr, nc);\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result (i, j) = std::pow (a, b (i, j));\n      }\n\n  return result;\n}\n\n// -*- 9 -*-\noctave_value\nelem_xpow (const SparseComplexMatrix& a, double b)\n{\n  octave_value retval;\n\n  if (b <= 0)\n    {\n      octave_idx_type nr = a.rows ();\n      octave_idx_type nc = a.cols ();\n\n      ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));\n\n      if (xisint (b))\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n              {\n                octave_quit ();\n                result (a.ridx (i), j)\n                  = std::pow (a.data (i), static_cast<int> (b));\n              }\n        }\n      else\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n              {\n                octave_quit ();\n                result (a.ridx (i), j) = std::pow (a.data (i), b);\n              }\n        }\n\n      retval = result;\n    }\n  else\n    {\n      octave_idx_type nz = a.nnz ();\n\n      SparseComplexMatrix result (a);\n\n      if (xisint (b))\n        {\n          for (octave_idx_type i = 0; i < nz; i++)\n            {\n              octave_quit ();\n              result.data (i) = std::pow (a.data (i), static_cast<int> (b));\n            }\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < nz; i++)\n            {\n              octave_quit ();\n              result.data (i) = std::pow (a.data (i), b);\n            }\n        }\n\n      result.maybe_compress (true);\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 10 -*-\noctave_value\nelem_xpow (const SparseComplexMatrix& a, const SparseMatrix& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a.numel () == 1 && b.numel () > 1)\n    return scalar_xpow (a(0), b);\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n        {\n          octave_quit ();\n          double btmp = b(a.ridx (i), j);\n\n          if (xisint (btmp))\n            result.xelem (a.ridx (i), j) = std::pow (a.data (i),\n                                           static_cast<int> (btmp));\n          else\n            result.xelem (a.ridx (i), j) = std::pow (a.data (i), btmp);\n        }\n    }\n\n  result.maybe_compress (true);\n\n  return result;\n}\n\n// -*- 11 -*-\noctave_value\nelem_xpow (const SparseComplexMatrix& a, const Complex& b)\n{\n  octave_value retval;\n\n  if (b == 0.0)\n    // Can this case ever happen, due to automatic retyping with maybe_mutate?\n    retval = octave_value (NDArray (a.dims (), 1));\n  else\n    {\n\n      octave_idx_type nz = a.nnz ();\n\n      SparseComplexMatrix result (a);\n\n      for (octave_idx_type i = 0; i < nz; i++)\n        {\n          octave_quit ();\n          result.data (i) = std::pow (a.data (i), b);\n        }\n\n      result.maybe_compress (true);\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 12 -*-\noctave_value\nelem_xpow (const SparseComplexMatrix& a, const SparseComplexMatrix& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a.numel () == 1 && b.numel () > 1)\n    return scalar_xpow (a(0), b);\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n        {\n          octave_quit ();\n          result.xelem (a.ridx (i), j) = std::pow (a.data (i),\n                                         b(a.ridx (i), j));\n        }\n    }\n  result.maybe_compress (true);\n\n  return result;\n}\n\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/sparse-xpow.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_sparse_xpow_h)\n#define octave_sparse_xpow_h 1\n\n#include \"octave-config.h\"\n\n#include \"oct-cmplx.h\"\n\nclass SparseMatrix;\nclass SparseComplexMatrix;\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern octave_value xpow (const SparseMatrix& a, double b);\nextern octave_value xpow (const SparseComplexMatrix& a, double b);\n\nextern octave_value elem_xpow (double a, const SparseMatrix& b);\nextern octave_value elem_xpow (double a, const SparseComplexMatrix& b);\n\nextern octave_value elem_xpow (const SparseMatrix& a, double b);\nextern octave_value elem_xpow (const SparseMatrix& a, const SparseMatrix& b);\nextern octave_value elem_xpow (const SparseMatrix& a, const Complex& b);\nextern octave_value elem_xpow (const SparseMatrix& a,\n                               const SparseComplexMatrix& b);\n\nextern octave_value elem_xpow (const Complex& a, const SparseMatrix& b);\nextern octave_value elem_xpow (const Complex& a,\n                               const SparseComplexMatrix& b);\n\nextern octave_value elem_xpow (const SparseComplexMatrix& a, double b);\nextern octave_value elem_xpow (const SparseComplexMatrix& a,\n                               const SparseMatrix& b);\nextern octave_value elem_xpow (const SparseComplexMatrix& a,\n                               const Complex& b);\nextern octave_value elem_xpow (const SparseComplexMatrix& a,\n                               const SparseComplexMatrix& b);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/stack-frame.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n\n#include \"oct-regexp.h\"\n#include \"oct-sysdep.h\"\n#include \"str-vec.h\"\n\n#include \"cmd-edit.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ov-fcn.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"pt-eval.h\"\n#include \"stack-frame.h\"\n#include \"syminfo.h\"\n#include \"symrec.h\"\n#include \"symscope.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// FIXME: There should probably be a display method for the script,\n// fcn, and scope objects and the script and function objects should\n// be responsible for displaying the scopes they contain.\n\nstatic void display_scope (std::ostream& os, const symbol_scope& scope)\n{\n  if (scope)\n    {\n      os << \"scope: \" << scope.name () << std::endl;\n\n      if (scope.num_symbols () > 0)\n        {\n          os << \"name (frame offset, data offset, storage class):\"\n             << std::endl;\n\n          std::list<symbol_record> symbols = scope.symbol_list ();\n\n          for (auto& sym : symbols)\n            {\n              os << \"  \" << sym.name () << \" (\" << sym.frame_offset ()\n                 << \", \" << sym.data_offset () << \", \" << sym.storage_class ()\n                 << \")\" << std::endl;\n            }\n        }\n    }\n}\n\nclass compiled_fcn_stack_frame;\nclass script_stack_frame;\nclass user_fcn_stack_frame;\nclass scope_stack_frame;\n\nclass stack_frame_walker\n{\nprotected:\n\n  stack_frame_walker () { }\n\n  virtual ~stack_frame_walker () = default;\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (stack_frame_walker)\n\n  virtual void\n  visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame&) = 0;\n\n  virtual void\n  visit_script_stack_frame (script_stack_frame&) = 0;\n\n  virtual void\n  visit_user_fcn_stack_frame (user_fcn_stack_frame&) = 0;\n\n  virtual void\n  visit_scope_stack_frame (scope_stack_frame&) = 0;\n};\n\nclass compiled_fcn_stack_frame : public stack_frame\n{\npublic:\n\n  compiled_fcn_stack_frame () = delete;\n\n  compiled_fcn_stack_frame (tree_evaluator& tw, octave_function *fcn,\n                            std::size_t index,\n                            const std::shared_ptr<stack_frame>& parent_link,\n                            const std::shared_ptr<stack_frame>& static_link)\n    : stack_frame (tw, index, parent_link, static_link,\n                   static_link->access_link ()),\n      m_fcn (fcn)\n  { }\n\n  compiled_fcn_stack_frame (const compiled_fcn_stack_frame& elt) = default;\n\n  compiled_fcn_stack_frame&\n  operator = (const compiled_fcn_stack_frame& elt) = delete;\n\n  ~compiled_fcn_stack_frame () = default;\n\n  bool is_compiled_fcn_frame () const { return true; }\n\n  symbol_scope get_scope () const\n  {\n    return m_static_link->get_scope ();\n  }\n\n  octave_function * function () const { return m_fcn; }\n\n  symbol_record lookup_symbol (const std::string& name) const\n  {\n    return m_static_link->lookup_symbol (name);\n  }\n\n  symbol_record insert_symbol (const std::string& name)\n  {\n    return m_static_link->insert_symbol (name);\n  }\n\n  stack_frame::scope_flags scope_flag (const symbol_record& sym) const\n  {\n    // Look in closest stack frame that contains values (either the\n    // top scope, or a user-defined function or script).\n\n    return m_static_link->scope_flag (sym);\n  }\n\n  void set_auto_fcn_var (auto_var_type avt, const octave_value& val)\n  {\n    m_static_link->set_auto_fcn_var (avt, val);\n  }\n\n  octave_value get_auto_fcn_var (auto_var_type avt) const\n  {\n    return m_static_link->get_auto_fcn_var (avt);\n  }\n\n  // We only need to override one of each of these functions.  The\n  // using declaration will avoid warnings about partially-overloaded\n  // virtual functions.\n  using stack_frame::varval;\n  using stack_frame::varref;\n\n  octave_value varval (const symbol_record& sym) const\n  {\n    // Look in closest stack frame that contains values (either the\n    // top scope, or a user-defined function or script).\n\n    return m_static_link->varval (sym);\n  }\n\n  octave_value& varref (const symbol_record& sym)\n  {\n    // Look in closest stack frame that contains values (either the\n    // top scope, or a user-defined function or script).\n\n    return m_static_link->varref (sym);\n  }\n\n  std::string inputname (int n, bool ids_only) const\n  {\n    // Look in closest stack frame that contains values (either the\n    // top scope, or a user-defined function or script).\n\n    return m_static_link->inputname (n, ids_only);\n  }\n\n  void mark_scope (const symbol_record& sym, scope_flags flag)\n  {\n    // Look in closest stack frame that contains values (either the\n    // top scope, or a user-defined function or script).\n\n    m_static_link->mark_scope (sym, flag);\n  }\n\n  void display (bool follow = true) const;\n\n  void accept (stack_frame_walker& sfw);\n\nprivate:\n\n  // Compiled function object associated with this stack frame.\n  // Should always be a built-in, .oct or .mex file function and\n  // should always be valid.\n  octave_function *m_fcn;\n};\n\n// Scripts have a symbol_scope object to store the set of variables\n// in the script, but values for those variables are stored in the\n// stack frame corresponding to the nearest calling function or in\n// the top-level scope (the evaluation stack frame).\n//\n// Accessing values in a scope requires a mapping from the index of\n// the variable for the script scope to the list of values in the\n// evaluation frame(s).  The frame offset tells us how many access\n// links we must follow to find the stack frame that holds the\n// value.  The value offset is the index into the vector of values\n// in that stack frame that we should use to find the value.\n//\n// Frame and value offsets are set in this stack frame when it is\n// created using information from the script and enclosing scopes.\n//\n// If a script is invoked in a nested function context, the frame\n// offsets for individual values may be different.  Some may be\n// accessed from the invoking function and some may come from a\n// parent function.\n\nclass script_stack_frame : public stack_frame\n{\npublic:\n\n  script_stack_frame () = delete;\n\n  script_stack_frame (tree_evaluator& tw, octave_user_script *script,\n                      std::size_t index,\n                      const std::shared_ptr<stack_frame>& parent_link,\n                      const std::shared_ptr<stack_frame>& static_link);\n\n  script_stack_frame (const script_stack_frame& elt) = default;\n\n  script_stack_frame& operator = (const script_stack_frame& elt) = delete;\n\n  ~script_stack_frame ()\n  {\n    delete m_unwind_protect_frame;\n  }\n\n  bool is_user_script_frame () const { return true; }\n\n  static std::shared_ptr<stack_frame>\n  get_access_link (const std::shared_ptr<stack_frame>& static_link);\n\n  static std::size_t get_num_symbols (octave_user_script *script);\n\n  void set_script_offsets ();\n\n  void set_script_offsets_internal (const std::map<std::string,\n                                    symbol_record>& symbols);\n\n  void resize_and_update_script_offsets (const symbol_record& sym);\n\n  symbol_scope get_scope () const { return m_script->scope (); }\n\n  octave_function * function () const { return m_script; }\n\n  unwind_protect * unwind_protect_frame ();\n\n  symbol_record lookup_symbol (const std::string& name) const;\n\n  symbol_record insert_symbol (const std::string&);\n\n  std::size_t size () const { return m_lexical_frame_offsets.size (); }\n\n  void resize (std::size_t size)\n  {\n    m_lexical_frame_offsets.resize (size, 0);\n    m_value_offsets.resize (size, 0);\n  }\n\n  void get_val_offsets_with_insert (const symbol_record& sym,\n                                    std::size_t& frame_offset,\n                                    std::size_t& data_offset);\n\n  bool get_val_offsets_internal (const symbol_record& sym,\n                                 std::size_t& frame_offset,\n                                 std::size_t& data_offset) const;\n\n  bool get_val_offsets (const symbol_record& sym, std::size_t& frame_offset,\n                        std::size_t& data_offset) const;\n\n  scope_flags scope_flag (const symbol_record& sym) const;\n\n  void set_auto_fcn_var (auto_var_type avt, const octave_value& val)\n  {\n    m_access_link->set_auto_fcn_var (avt, val);\n  }\n\n  octave_value get_auto_fcn_var (auto_var_type avt) const\n  {\n    return m_access_link->get_auto_fcn_var (avt);\n  }\n\n  // We only need to override one of each of these functions.  The\n  // using declaration will avoid warnings about partially-overloaded\n  // virtual functions.\n  using stack_frame::varval;\n  using stack_frame::varref;\n\n  octave_value varval (const symbol_record& sym) const;\n\n  octave_value& varref (const symbol_record& sym);\n\n  std::string inputname (int n, bool ids_only) const\n  {\n    return m_access_link->inputname (n, ids_only);\n  }\n\n  void mark_scope (const symbol_record& sym, scope_flags flag);\n\n  void display (bool follow = true) const;\n\n  void accept (stack_frame_walker& sfw);\n\nprivate:\n\n  // Script object associated with this stack frame.  Should always\n  // be valid.\n  octave_user_script *m_script;\n\n  // The nearest unwind protect frame that was active when this\n  // stack frame was created.  Should always be valid.\n  unwind_protect *m_unwind_protect_frame;\n\n  // Mapping between the symbols in the symbol_scope object of the\n  // script to the stack frame in which the script is executed.  The\n  // frame offsets may be greater than one if the script is executed\n  // in a nested function context.\n\n  std::vector<std::size_t> m_lexical_frame_offsets;\n  std::vector<std::size_t> m_value_offsets;\n};\n\n// Base class for values and offsets shared by user_fcn and scope\n// frames.\n\nclass base_value_stack_frame : public stack_frame\n{\npublic:\n\n  base_value_stack_frame () = delete;\n\n  base_value_stack_frame (tree_evaluator& tw, std::size_t num_symbols,\n                          std::size_t index,\n                          const std::shared_ptr<stack_frame>& parent_link,\n                          const std::shared_ptr<stack_frame>& static_link,\n                          const std::shared_ptr<stack_frame>& access_link)\n    : stack_frame (tw, index, parent_link, static_link, access_link),\n      m_values (num_symbols, octave_value ()),\n      m_flags (num_symbols, LOCAL),\n      m_auto_vars (NUM_AUTO_VARS, octave_value ())\n  { }\n\n  base_value_stack_frame (const base_value_stack_frame& elt) = default;\n\n  base_value_stack_frame&\n  operator = (const base_value_stack_frame& elt) = delete;\n\n  ~base_value_stack_frame ()\n  {\n    // The C++ standard doesn't guarantee in which order the elements of a\n    // std::vector are destroyed.  GNU libstdc++ and LLVM libc++ seem to\n    // destroy them in a different order.  So, erase elements manually\n    // from first to last to be able to guarantee a destructor call order\n    // independent of the used STL, e.g., for classdef objects.\n\n    // Member dtor order is last to first.  So, m_auto_vars before m_values.\n\n    for (auto auto_vars_iter = m_auto_vars.begin ();\n         auto_vars_iter != m_auto_vars.end ();)\n      auto_vars_iter = m_auto_vars.erase (auto_vars_iter);\n\n    for (auto values_iter = m_values.begin ();\n         values_iter != m_values.end ();)\n      values_iter = m_values.erase (values_iter);\n  }\n\n  std::size_t size () const\n  {\n    return m_values.size ();\n  }\n\n  void resize (std::size_t size)\n  {\n    m_values.resize (size, octave_value ());\n    m_flags.resize (size, LOCAL);\n  }\n\n  stack_frame::scope_flags get_scope_flag (std::size_t data_offset) const\n  {\n    return m_flags.at (data_offset);\n  }\n\n  void set_scope_flag (std::size_t data_offset, scope_flags flag)\n  {\n    m_flags.at (data_offset) = flag;\n  }\n\n  octave_value get_auto_fcn_var (auto_var_type avt) const\n  {\n    return m_auto_vars.at (avt);\n  }\n\n  void set_auto_fcn_var (auto_var_type avt, const octave_value& val)\n  {\n    m_auto_vars.at (avt) = val;\n  }\n\n  // We only need to override one of each of these functions.  The\n  // using declaration will avoid warnings about partially-overloaded\n  // virtual functions.\n  using stack_frame::varval;\n  using stack_frame::varref;\n\n  octave_value varval (std::size_t data_offset) const\n  {\n    return m_values.at (data_offset);\n  }\n\n  octave_value& varref (std::size_t data_offset)\n  {\n    return m_values.at (data_offset);\n  }\n\n  void display (bool follow = true) const;\n\nprotected:\n\n  // Variable values.  This array is indexed by the data_offset\n  // value stored in the symbol_record objects of the scope\n  // associated with this stack frame.\n  std::vector<octave_value> m_values;\n\n  // The type of each variable (local, global, persistent) of each\n  // value.  This array is indexed by the data_offset value stored\n  // in the symbol_record objects of the scope associated with this\n  // stack frame.  Local values are found in the M_VALUES array.\n  // Global values are stored in the tree_evaluator object that contains\n  // the stack frame.  Persistent values are stored in the function\n  // scope corresponding to the stack frame.\n  std::vector<scope_flags> m_flags;\n\n  // A fixed list of Automatic variables created for this function.\n  // The elements of this vector correspond to the auto_var_type\n  // enum.\n  std::vector<octave_value> m_auto_vars;\n};\n\n// User-defined functions have a symbol_scope object to store the set\n// of variables in the function and values are stored in the stack\n// frame corresponding to the invocation of the function or one of\n// its parents.  The frame offset tells us how many access links we\n// must follow to find the stack frame that holds the value.  The\n// value offset is the index into the vector of values in that stack\n// frame that we should use to find the value.\n//\n// Frame and value offsets are determined when the corresponding\n// function is parsed.\n\nclass user_fcn_stack_frame : public base_value_stack_frame\n{\npublic:\n\n  user_fcn_stack_frame () = delete;\n\n  user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn,\n                        std::size_t index,\n                        const std::shared_ptr<stack_frame>& parent_link,\n                        const std::shared_ptr<stack_frame>& static_link,\n                        const std::shared_ptr<stack_frame>& access_link = std::shared_ptr<stack_frame> ())\n    : base_value_stack_frame (tw, get_num_symbols (fcn), index,\n                              parent_link, static_link,\n                              (access_link\n                               ? access_link\n                               : get_access_link (fcn, static_link))),\n      m_fcn (fcn), m_unwind_protect_frame (nullptr)\n  { }\n\n  user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn,\n                        std::size_t index,\n                        const std::shared_ptr<stack_frame>& parent_link,\n                        const std::shared_ptr<stack_frame>& static_link,\n                        const local_vars_map& local_vars,\n                        const std::shared_ptr<stack_frame>& access_link = std::shared_ptr<stack_frame> ())\n    : base_value_stack_frame (tw, get_num_symbols (fcn), index,\n                              parent_link, static_link,\n                              (access_link\n                               ? access_link\n                               : get_access_link (fcn, static_link))),\n      m_fcn (fcn), m_unwind_protect_frame (nullptr)\n  {\n    // Initialize local variable values.\n\n    for (const auto& nm_ov : local_vars)\n      assign (nm_ov.first, nm_ov.second);\n  }\n\n  user_fcn_stack_frame (const user_fcn_stack_frame& elt) = default;\n\n  user_fcn_stack_frame&\n  operator = (const user_fcn_stack_frame& elt) = delete;\n\n  ~user_fcn_stack_frame ()\n  {\n    delete m_unwind_protect_frame;\n  }\n\n  bool is_user_fcn_frame () const { return true; }\n\n  static std::shared_ptr<stack_frame>\n  get_access_link (octave_user_function *fcn,\n                   const std::shared_ptr<stack_frame>& static_link);\n\n  static std::size_t get_num_symbols (octave_user_function *fcn)\n  {\n    symbol_scope fcn_scope = fcn->scope ();\n\n    return fcn_scope.num_symbols ();\n  }\n\n  void clear_values ();\n\n  symbol_scope get_scope () const { return m_fcn->scope (); }\n\n  octave_function * function () const { return m_fcn; }\n\n  unwind_protect * unwind_protect_frame ();\n\n  symbol_record lookup_symbol (const std::string& name) const;\n\n  symbol_record insert_symbol (const std::string&);\n\n  scope_flags scope_flag (const symbol_record& sym) const;\n\n  // We only need to override one of each of these functions.  The\n  // using declaration will avoid warnings about partially-overloaded\n  // virtual functions.\n  using base_value_stack_frame::varval;\n  using base_value_stack_frame::varref;\n\n  octave_value varval (const symbol_record& sym) const;\n\n  octave_value& varref (const symbol_record& sym);\n\n  std::string inputname (int n, bool ids_only) const;\n\n  void mark_scope (const symbol_record& sym, scope_flags flag);\n\n  void display (bool follow = true) const;\n\n  void accept (stack_frame_walker& sfw);\n\n  void break_closure_cycles (const std::shared_ptr<stack_frame>& frame);\n\nprivate:\n\n  // User-defined object associated with this stack frame.  Should\n  // always be valid.\n  octave_user_function *m_fcn;\n\n  // The nearest unwind protect frame that was active when this\n  // stack frame was created.  Should always be valid.\n  unwind_protect *m_unwind_protect_frame;\n};\n\n// Pure scope stack frames (primarily the top-level workspace) have\n// a set of variables and values are stored in the stack frame.  All\n// variable accesses are direct as there are no parent stack frames.\n//\n// Value offsets are determined when the corresponding variable is\n// entered into the symbol_scope object corresponding to the frame.\n\nclass scope_stack_frame : public base_value_stack_frame\n{\npublic:\n\n  scope_stack_frame () = delete;\n\n  scope_stack_frame (tree_evaluator& tw, const symbol_scope& scope,\n                     std::size_t index,\n                     const std::shared_ptr<stack_frame>& parent_link,\n                     const std::shared_ptr<stack_frame>& static_link)\n    : base_value_stack_frame (tw, scope.num_symbols (), index,\n                              parent_link, static_link, nullptr),\n      m_scope (scope)\n  { }\n\n  scope_stack_frame (const scope_stack_frame& elt) = default;\n\n  scope_stack_frame& operator = (const scope_stack_frame& elt) = delete;\n\n  ~scope_stack_frame () = default;\n\n  bool is_scope_frame () const { return true; }\n\n  symbol_scope get_scope () const { return m_scope; }\n\n  symbol_record lookup_symbol (const std::string& name) const\n  {\n    return m_scope.lookup_symbol (name);\n  }\n\n  symbol_record insert_symbol (const std::string&);\n\n  scope_flags scope_flag (const symbol_record& sym) const;\n\n  // We only need to override one of each of these functions.  The\n  // using declaration will avoid warnings about partially-overloaded\n  // virtual functions.\n  using base_value_stack_frame::varval;\n  using base_value_stack_frame::varref;\n\n  octave_value varval (const symbol_record& sym) const;\n\n  octave_value& varref (const symbol_record& sym);\n\n  std::string inputname (int, bool) const\n  {\n    if (m_index == 0)\n      error (\"invalid call to inputname outside of a function\");\n\n    return \"\";\n  }\n\n  void mark_scope (const symbol_record& sym, scope_flags flag);\n\n  void display (bool follow = true) const;\n\n  void accept (stack_frame_walker& sfw);\n\nprivate:\n\n  // The scope object associated with this stack frame.\n  symbol_scope m_scope;\n};\n\nclass symbol_cleaner : public stack_frame_walker\n{\npublic:\n\n  symbol_cleaner (const std::string& pattern, bool have_regexp = false)\n    : stack_frame_walker (), m_patterns (pattern),\n      m_clear_all_names (false), m_clear_objects (false),\n      m_have_regexp (have_regexp), m_cleared_names ()\n  { }\n\n  symbol_cleaner (const string_vector& patterns, bool have_regexp = false)\n    : stack_frame_walker (), m_patterns (patterns),\n      m_clear_all_names (false), m_clear_objects (false),\n      m_have_regexp (have_regexp), m_cleared_names ()\n  { }\n\n  symbol_cleaner (bool clear_all_names = true, bool clear_objects = false)\n    : stack_frame_walker (), m_patterns (),\n      m_clear_all_names (clear_all_names), m_clear_objects (clear_objects),\n      m_have_regexp (false), m_cleared_names ()\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (symbol_cleaner)\n\n  ~symbol_cleaner () = default;\n\n  void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame)\n  {\n    // This one follows static link always.  Hmm, should the access\n    // link for a compiled_fcn_stack_frame be the same as the static\n    // link?\n\n    std::shared_ptr<stack_frame> slink = frame.static_link ();\n\n    if (slink)\n      slink->accept (*this);\n  }\n\n  void visit_script_stack_frame (script_stack_frame& frame)\n  {\n    std::shared_ptr<stack_frame> alink = frame.access_link ();\n\n    if (alink)\n      alink->accept (*this);\n  }\n\n  void visit_user_fcn_stack_frame (user_fcn_stack_frame& frame)\n  {\n    clean_frame (frame);\n\n    std::shared_ptr<stack_frame> alink = frame.access_link ();\n\n    if (alink)\n      alink->accept (*this);\n  }\n\n  void visit_scope_stack_frame (scope_stack_frame& frame)\n  {\n    clean_frame (frame);\n\n    std::shared_ptr<stack_frame> alink = frame.access_link ();\n\n    if (alink)\n      alink->accept (*this);\n  }\n\nprivate:\n\n  void maybe_clear_symbol (stack_frame& frame, const symbol_record& sym)\n  {\n    std::string name = sym.name ();\n\n    if (m_cleared_names.find (name) == m_cleared_names.end ())\n      {\n        // FIXME: Should we check that the name is defined and skip if\n        // it is not?  Is it possible for another symbol with the same\n        // name to appear in a later stack frame?\n\n        // FIXME: If we are clearing objects and a symbol is found,\n        // should we add it to the list of cleared names (since\n        // we did find a symbol) but skip clearing the object?\n\n        if (m_clear_objects && ! frame.is_object (sym))\n          return;\n\n        m_cleared_names.insert (name);\n\n        frame.clear (sym);\n      }\n  }\n\n  // FIXME: It would be nice to avoid the duplication in the following\n  // function.\n\n  void clear_symbols (stack_frame& frame,\n                      const std::list<symbol_record>& symbols)\n  {\n    if (m_clear_all_names)\n      {\n        for (const auto& sym : symbols)\n          maybe_clear_symbol (frame, sym);\n      }\n    else if (m_have_regexp)\n      {\n        octave_idx_type npatterns = m_patterns.numel ();\n\n        for (octave_idx_type j = 0; j < npatterns; j++)\n          {\n            std::string pattern = m_patterns[j];\n\n            regexp pat (pattern);\n\n            for (const auto& sym : symbols)\n              {\n                if (pat.is_match (sym.name ()))\n                  maybe_clear_symbol (frame, sym);\n              }\n          }\n      }\n    else\n      {\n        octave_idx_type npatterns = m_patterns.numel ();\n\n        for (octave_idx_type j = 0; j < npatterns; j++)\n          {\n            std::string pattern = m_patterns[j];\n\n            symbol_match pat (pattern);\n\n            for (const auto& sym : symbols)\n              {\n                if (pat.match (sym.name ()))\n                  maybe_clear_symbol (frame, sym);\n              }\n          }\n      }\n  }\n\n  void clean_frame (stack_frame& frame)\n  {\n    symbol_scope scope = frame.get_scope ();\n\n    std::list<symbol_record> symbols = scope.symbol_list ();\n\n    if (m_clear_all_names || ! m_patterns.empty ())\n      clear_symbols (frame, symbols);\n  }\n\n  string_vector m_patterns;\n\n  bool m_clear_all_names;\n  bool m_clear_objects;\n  bool m_have_regexp;\n\n  std::set<std::string> m_cleared_names;\n};\n\nclass symbol_info_accumulator : public stack_frame_walker\n{\npublic:\n\n  symbol_info_accumulator (const std::string& pattern,\n                           bool have_regexp = false)\n    : stack_frame_walker (), m_patterns (pattern), m_match_all (false),\n      m_first_only (false), m_have_regexp (have_regexp), m_sym_inf_list (),\n      m_found_names ()\n  { }\n\n  symbol_info_accumulator (const string_vector& patterns,\n                           bool have_regexp = false)\n    : stack_frame_walker (), m_patterns (patterns), m_match_all (false),\n      m_first_only (false), m_have_regexp (have_regexp), m_sym_inf_list (),\n      m_found_names ()\n  { }\n\n  symbol_info_accumulator (bool match_all = true, bool first_only = true)\n    : stack_frame_walker (), m_patterns (), m_match_all (match_all),\n      m_first_only (first_only), m_have_regexp (false),\n      m_sym_inf_list (), m_found_names ()\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (symbol_info_accumulator)\n\n  ~symbol_info_accumulator () = default;\n\n  bool is_empty  () const\n  {\n    for (const auto& nm_sil : m_sym_inf_list)\n      {\n        const symbol_info_list& lst = nm_sil.second;\n\n        if (! lst.empty ())\n          return false;\n      }\n\n    return true;\n  }\n\n  std::list<std::string> names () const\n  {\n    std::list<std::string> retval;\n\n    for (const auto& nm_sil : m_sym_inf_list)\n      {\n        const symbol_info_list& lst = nm_sil.second;\n\n        std::list<std::string> nm_list = lst.names ();\n\n        for (const auto& nm : nm_list)\n          retval.push_back (nm);\n      }\n\n    return retval;\n  }\n\n  symbol_info_list symbol_info () const\n  {\n    symbol_info_list retval;\n\n    for (const auto& nm_sil : m_sym_inf_list)\n      {\n        const symbol_info_list& lst = nm_sil.second;\n\n        for (const auto& syminf : lst)\n          retval.push_back (syminf);\n      }\n\n    return retval;\n  }\n\n  octave_map map_value () const\n  {\n    octave_map retval;\n\n    // FIXME: is there a better way to concatenate structures?\n\n    std::size_t n_frames = m_sym_inf_list.size ();\n\n    OCTAVE_LOCAL_BUFFER (octave_map, map_list, n_frames);\n\n    std::size_t j = 0;\n    for (const auto& nm_sil : m_sym_inf_list)\n      {\n        std::string scope_name = nm_sil.first;\n        const symbol_info_list& lst = nm_sil.second;\n\n        map_list[j] = lst.map_value (scope_name, n_frames-j);\n\n        j++;\n      }\n\n    return octave_map::cat (-1, n_frames, map_list);\n  }\n\n  void display (std::ostream& os, const std::string& format) const\n  {\n    for (const auto& nm_sil : m_sym_inf_list)\n      {\n        os << \"\\nvariables in scope: \" << nm_sil.first << \"\\n\\n\";\n\n        const symbol_info_list& lst = nm_sil.second;\n\n        lst.display (os, format);\n      }\n  }\n\n  void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame)\n  {\n    // This one follows static link always.  Hmm, should the access\n    // link for a compiled_fcn_stack_frame be the same as the static\n    // link?\n\n    std::shared_ptr<stack_frame> slink = frame.static_link ();\n\n    if (slink)\n      slink->accept (*this);\n  }\n\n  void visit_script_stack_frame (script_stack_frame& frame)\n  {\n    std::shared_ptr<stack_frame> alink = frame.access_link ();\n\n    if (alink)\n      alink->accept (*this);\n  }\n\n  void visit_user_fcn_stack_frame (user_fcn_stack_frame& frame)\n  {\n    append_list (frame);\n\n    std::shared_ptr<stack_frame> alink = frame.access_link ();\n\n    if (alink)\n      alink->accept (*this);\n  }\n\n  void visit_scope_stack_frame (scope_stack_frame& frame)\n  {\n    append_list (frame);\n\n    std::shared_ptr<stack_frame> alink = frame.access_link ();\n\n    if (alink)\n      alink->accept (*this);\n  }\n\nprivate:\n\n  typedef std::pair<std::string, symbol_info_list> syminf_list_elt;\n\n  // FIXME: the following is too complex and duplicates too much\n  // code.  Maybe it should be split up so we have separate classes\n  // that do each job that is needed?\n\n  std::list<symbol_record>\n  filter (stack_frame& frame, const std::list<symbol_record>& symbols)\n  {\n    std::list<symbol_record> new_symbols;\n\n    if (m_match_all)\n      {\n        for (const auto& sym : symbols)\n          {\n            if (frame.is_defined (sym))\n              {\n                std::string name = sym.name ();\n\n                if (m_first_only\n                    && m_found_names.find (name) != m_found_names.end ())\n                  continue;\n\n                m_found_names.insert (name);\n\n                new_symbols.push_back (sym);\n              }\n          }\n      }\n    else if (m_have_regexp)\n      {\n        octave_idx_type npatterns = m_patterns.numel ();\n\n        for (octave_idx_type j = 0; j < npatterns; j++)\n          {\n            std::string pattern = m_patterns[j];\n\n            regexp pat (pattern);\n\n            for (const auto& sym : symbols)\n              {\n                std::string name = sym.name ();\n\n                if (pat.is_match (name) && frame.is_defined (sym))\n                  {\n                    if (m_first_only\n                        && m_found_names.find (name) != m_found_names.end ())\n                      continue;\n\n                    m_found_names.insert (name);\n\n                    new_symbols.push_back (sym);\n                  }\n              }\n          }\n      }\n    else\n      {\n        octave_idx_type npatterns = m_patterns.numel ();\n\n        for (octave_idx_type j = 0; j < npatterns; j++)\n          {\n            std::string pattern = m_patterns[j];\n\n            symbol_match pat (pattern);\n\n            for (const auto& sym : symbols)\n              {\n                std::string name = sym.name ();\n\n                if (pat.match (name) && frame.is_defined (sym))\n                  {\n                    if (m_first_only\n                        && m_found_names.find (name) == m_found_names.end ())\n                      continue;\n\n                    m_found_names.insert (name);\n\n                    new_symbols.push_back (sym);\n                  }\n              }\n          }\n      }\n\n    return new_symbols;\n  }\n\n  void append_list (stack_frame& frame)\n  {\n    symbol_scope scope = frame.get_scope ();\n\n    std::list<symbol_record> symbols = scope.symbol_list ();\n\n    if (m_match_all || ! m_patterns.empty ())\n      symbols = filter (frame, symbols);\n\n    symbol_info_list syminf_list = frame.make_symbol_info_list (symbols);\n\n    m_sym_inf_list.push_back (syminf_list_elt (scope.name (), syminf_list));\n  }\n\n  string_vector m_patterns;\n\n  bool m_match_all;\n  bool m_first_only;\n  bool m_have_regexp;\n\n  std::list<std::pair<std::string, symbol_info_list>> m_sym_inf_list;\n\n  std::set<std::string> m_found_names;\n};\n\nstack_frame *\nstack_frame::create (tree_evaluator& tw, octave_function *fcn,\n                     std::size_t index,\n                     const std::shared_ptr<stack_frame>& parent_link,\n                     const std::shared_ptr<stack_frame>& static_link)\n{\n  return new compiled_fcn_stack_frame (tw, fcn, index,\n                                       parent_link, static_link);\n}\n\nstack_frame *\nstack_frame::create (tree_evaluator& tw,\n                     octave_user_script *script,\n                     std::size_t index,\n                     const std::shared_ptr<stack_frame>& parent_link,\n                     const std::shared_ptr<stack_frame>& static_link)\n{\n  return new script_stack_frame (tw, script, index, parent_link, static_link);\n}\n\nstack_frame *\nstack_frame::create (tree_evaluator& tw,\n                     octave_user_function *fcn, std::size_t index,\n                     const std::shared_ptr<stack_frame>& parent_link,\n                     const std::shared_ptr<stack_frame>& static_link,\n                     const std::shared_ptr<stack_frame>& access_link)\n{\n  return new user_fcn_stack_frame (tw, fcn, index,\n                                   parent_link, static_link, access_link);\n}\n\nstack_frame *\nstack_frame::create (tree_evaluator& tw,\n                     octave_user_function *fcn, std::size_t index,\n                     const std::shared_ptr<stack_frame>& parent_link,\n                     const std::shared_ptr<stack_frame>& static_link,\n                     const local_vars_map& local_vars,\n                     const std::shared_ptr<stack_frame>& access_link)\n{\n  return new user_fcn_stack_frame (tw, fcn, index,\n                                   parent_link, static_link, local_vars,\n                                   access_link);\n}\n\nstack_frame *\nstack_frame::create (tree_evaluator& tw,\n                     const symbol_scope& scope, std::size_t index,\n                     const std::shared_ptr<stack_frame>& parent_link,\n                     const std::shared_ptr<stack_frame>& static_link)\n{\n  return new scope_stack_frame (tw, scope, index, parent_link, static_link);\n}\n\n// This function is only implemented and should only be called for\n// user_fcn stack frames.  Anything else indicates an error in the\n// implementation, but we'll simply warn if that happens.\n\nvoid\nstack_frame::clear_values ()\n{\n  warning (\"invalid call to stack_frame::clear_values; please report\");\n}\n\nsymbol_info_list\nstack_frame::make_symbol_info_list (const std::list<symbol_record>& symrec_list) const\n{\n  symbol_info_list symbol_stats;\n\n  for (const auto& sym : symrec_list)\n    {\n      octave_value value = varval (sym);\n\n      if (! value.is_defined ()\n          || (is_user_fcn_frame () && sym.frame_offset () > 0))\n        continue;\n\n      symbol_info syminf (sym.name (), value, sym.is_formal (),\n                          is_global (sym), is_persistent (sym));\n\n      symbol_stats.push_back (syminf);\n    }\n\n  return symbol_stats;\n}\n\noctave_value\nstack_frame::who (const string_vector& patterns,\n                  bool have_regexp, bool return_list,\n                  bool verbose, const std::string& whos_line_fmt,\n                  const std::string& msg)\n{\n  symbol_info_accumulator sym_inf_accum (patterns, have_regexp);\n\n  accept (sym_inf_accum);\n\n  if (return_list)\n    {\n      if (verbose)\n        return sym_inf_accum.map_value ();\n      else\n        return Cell (string_vector (sym_inf_accum.names ()));\n    }\n  else if (! sym_inf_accum.is_empty ())\n    {\n\n      if (msg.empty ())\n        octave_stdout << \"Variables visible from the current scope:\\n\";\n      else\n        octave_stdout << msg;\n\n      if (verbose)\n        sym_inf_accum.display (octave_stdout, whos_line_fmt);\n      else\n        {\n          octave_stdout << \"\\n\";\n          string_vector names (sym_inf_accum.names ());\n          const int width = command_editor::terminal_cols ();\n          names.list_in_columns (octave_stdout, width);\n        }\n\n      octave_stdout << \"\\n\";\n    }\n\n  return octave_value ();\n}\n\n// Return first occurrence of variables in current stack frame and any\n// parent frames reachable through access links.\n\nsymbol_info_list\nstack_frame::all_variables ()\n{\n  symbol_info_accumulator sia (true, true);\n\n  accept (sia);\n\n  return sia.symbol_info ();\n}\n\noctave_value\nstack_frame::workspace ()\n{\n  std::list<octave_scalar_map> ws_list;\n\n  stack_frame *frame = this;\n\n  while (frame)\n    {\n      symbol_info_list symbols = frame->all_variables ();\n\n      octave_scalar_map ws;\n\n      for (const auto& sym_name : symbols.names ())\n        {\n          octave_value val = symbols.varval (sym_name);\n\n          if (val.is_defined ())\n            ws.assign (sym_name, val);\n        }\n\n      ws_list.push_back (ws);\n\n      std::shared_ptr<stack_frame> nxt = frame->access_link ();\n      frame = nxt.get ();\n    }\n\n  Cell ws_frames (ws_list.size (), 1);\n\n  octave_idx_type i = 0;\n  for (const auto& elt : ws_list)\n    ws_frames(i++) = elt;\n\n  return ws_frames;\n}\n\n// FIXME: Should this function also find any variables in parent\n// scopes accessible through access_links?\n\nstd::list<std::string>\nstack_frame::variable_names () const\n{\n  std::list<std::string> retval;\n\n  symbol_scope scope = get_scope ();\n\n  const std::map<std::string, symbol_record>& symbols = scope.symbols ();\n\n  for (const auto& nm_sr : symbols)\n    {\n      if (is_variable (nm_sr.second))\n        retval.push_back (nm_sr.first);\n    }\n\n  retval.sort ();\n\n  return retval;\n}\n\nsymbol_info_list\nstack_frame::glob_symbol_info (const std::string& pattern)\n{\n  symbol_info_accumulator sia (pattern, false);\n\n  accept (sia);\n\n  return sia.symbol_info ();\n}\n\nsymbol_info_list\nstack_frame::regexp_symbol_info (const std::string& pattern)\n{\n  symbol_info_accumulator sia (pattern, true);\n\n  accept (sia);\n\n  return sia.symbol_info ();\n}\n\nstd::size_t\nstack_frame::size () const\n{\n  // This function should only be called for user_fcn_stack_frame or\n  // scope_stack_frame objects.  Anything else indicates an error in\n  // the implementation.\n\n  error (\"unexpected call to stack_frame::size () - please report this bug\");\n}\n\nvoid\nstack_frame::resize (std::size_t)\n{\n  // This function should only be called for user_fcn_stack_frame or\n  // scope_stack_frame objects.  Anything else indicates an error in\n  // the implementation.\n\n  error (\"unexpected call to stack_frame::resize () - please report this bug\");\n}\n\nstack_frame::scope_flags\nstack_frame::get_scope_flag (std::size_t) const\n{\n  // This function should only be called for user_fcn_stack_frame or\n  // scope_stack_frame objects.  Anything else indicates an error in\n  // the implementation.\n\n  error (\"unexpected call to stack_frame::get_scope_flag (std::size_t) - please report this bug\");\n}\n\nvoid\nstack_frame::set_scope_flag (std::size_t, scope_flags)\n{\n  // This function should only be called for user_fcn_stack_frame or\n  // scope_stack_frame objects.  Anything else indicates an error in\n  // the implementation.\n\n  error (\"unexpected call to stack_frame::get_scope_flag (std::size_t, scope_flags) - please report this bug\");\n}\n\nvoid\nstack_frame::install_variable (const symbol_record& sym,\n                               const octave_value& value, bool global)\n{\n  if (global && ! is_global (sym))\n    {\n      octave_value val = varval (sym);\n\n      if (val.is_defined ())\n        {\n          std::string nm = sym.name ();\n\n          warning_with_id (\"Octave:global-local-conflict\",\n                           \"global: '%s' is defined in the current scope.\\n\",\n                           nm.c_str ());\n          warning_with_id (\"Octave:global-local-conflict\",\n                           \"global: in a future version, global variables must be declared before use.\\n\");\n\n          // If the symbol is defined in the local but not the\n          // global scope, then use the local value as the\n          // initial value.  This value will also override any\n          // initializer in the global statement.\n          octave_value global_val = m_evaluator.global_varval (nm);\n\n          if (global_val.is_defined ())\n            {\n              warning_with_id (\"Octave:global-local-conflict\",\n                               \"global: global value overrides existing local value\");\n\n              clear (sym);\n            }\n          else\n            {\n              warning_with_id (\"Octave:global-local-conflict\",\n                               \"global: existing local value used to initialize global variable\");\n\n              m_evaluator.global_varref (nm) = val;\n            }\n        }\n\n      mark_global (sym);\n    }\n\n  if (value.is_defined ())\n    assign (sym, value);\n}\n\noctave_value\nstack_frame::varval (std::size_t) const\n{\n  // This function should only be called for user_fcn_stack_frame or\n  // scope_stack_frame objects.  Anything else indicates an error in\n  // the implementation.\n\n  error (\"unexpected call to stack_frame::varval (std::size_t) - please report this bug\");\n}\n\noctave_value&\nstack_frame::varref (std::size_t)\n{\n  // This function should only be called for user_fcn_stack_frame or\n  // scope_stack_frame objects.  Anything else indicates an error in\n  // the implementation.\n\n  error (\"unexpected call to stack_frame::varref (std::size_t) - please report this bug\");\n}\n\nstd::string\nstack_frame::inputname (int, bool) const\n{\n  // This function should only be called for user_fcn_stack_frame.\n  // Anything else indicates an error in the implementation.\n\n  error (\"unexpected call to stack_frame::inputname (int, bool) - please report this bug\");\n}\n\nvoid\nstack_frame::clear_objects ()\n{\n  symbol_cleaner sc (true, true);\n\n  accept (sc);\n}\n\nvoid\nstack_frame::clear_variable (const std::string& name)\n{\n  symbol_cleaner sc (name);\n\n  accept (sc);\n}\n\nvoid\nstack_frame::clear_variable_pattern (const std::string& pattern)\n{\n  symbol_cleaner sc (pattern);\n\n  accept (sc);\n}\n\nvoid\nstack_frame::clear_variable_pattern (const string_vector& patterns)\n{\n  symbol_cleaner sc (patterns);\n\n  accept (sc);\n}\n\nvoid\nstack_frame::clear_variable_regexp (const std::string& pattern)\n{\n  symbol_cleaner sc (pattern, true);\n\n  accept (sc);\n}\n\nvoid\nstack_frame::clear_variable_regexp (const string_vector& patterns)\n{\n  symbol_cleaner sc (patterns, true);\n\n  accept (sc);\n}\n\nvoid\nstack_frame::clear_variables ()\n{\n  symbol_cleaner sc;\n\n  accept (sc);\n}\n\nvoid\nstack_frame::display_stopped_in_message (std::ostream& os) const\n{\n  if (index () == 0)\n    os << \"at top level\" << std::endl;\n  else\n    {\n      os << \"stopped in \" << fcn_name ();\n\n      int l = line ();\n      if (l > 0)\n        os << \" at line \" << line ();\n\n      os << \" [\" << fcn_file_name () << \"] \" << std::endl;\n    }\n}\n\nvoid\nstack_frame::debug_list (std::ostream& os, int num_lines) const\n{\n  std::string file_name = fcn_file_name ();\n\n  int target_line = line ();\n  int start = std::max (target_line - num_lines/2, 0);\n  int end = target_line + num_lines/2;\n\n  display_file_lines (os, fcn_file_name (), start, end, target_line, \"-->\", \"dblist\");\n}\n\nvoid\nstack_frame::debug_type (std::ostream& os, int start_line, int end_line) const\n{\n  display_file_lines (os, fcn_file_name (), start_line, end_line, -1, \"\", \"dbtype\");\n}\n\nvoid\nstack_frame::display (bool follow) const\n{\n  std::ostream& os = octave_stdout;\n\n  os << \"-- [stack_frame] (\" << this << \") --\" << std::endl;\n\n  os << \"parent link: \";\n  if (m_parent_link)\n    os << m_parent_link.get ();\n  else\n    os << \"NULL\";\n  os << std::endl;\n\n  os << \"static link: \";\n  if (m_static_link)\n    os << m_static_link.get ();\n  else\n    os << \"NULL\";\n  os << std::endl;\n\n  os << \"access link: \";\n  if (m_access_link)\n    os << m_access_link.get ();\n  else\n    os << \"NULL\";\n  os << std::endl;\n\n  os << \"line: \" << m_line << std::endl;\n  os << \"column: \" << m_column << std::endl;\n  os << \"index: \" << m_index << std::endl;\n\n  os << std::endl;\n\n  if (! follow)\n    return;\n\n  os << \"FOLLOWING ACCESS LINKS:\" << std::endl;\n  std::shared_ptr<stack_frame> frm = access_link ();\n  while (frm)\n    {\n      frm->display (false);\n      os << std::endl;\n\n      frm = frm->access_link ();\n    }\n}\n\nvoid\ncompiled_fcn_stack_frame::display (bool follow) const\n{\n  std::ostream& os = octave_stdout;\n\n  os << \"-- [compiled_fcn_stack_frame] (\" << this << \") --\" << std::endl;\n  stack_frame::display (follow);\n\n  os << \"fcn: \" << m_fcn->name ()\n     << \" (\" << m_fcn->type_name () << \")\" << std::endl;\n}\n\nvoid\ncompiled_fcn_stack_frame::accept (stack_frame_walker& sfw)\n{\n  sfw.visit_compiled_fcn_stack_frame (*this);\n}\n\nscript_stack_frame::script_stack_frame (tree_evaluator& tw,\n                                        octave_user_script *script,\n                                        std::size_t index,\n                                        const std::shared_ptr<stack_frame>& parent_link,\n                                        const std::shared_ptr<stack_frame>& static_link)\n  : stack_frame (tw, index, parent_link, static_link,\n                 get_access_link (static_link)),\n    m_script (script), m_unwind_protect_frame (nullptr),\n    m_lexical_frame_offsets (get_num_symbols (script), 1),\n    m_value_offsets (get_num_symbols (script), 0)\n{\n  set_script_offsets ();\n}\n\nstd::size_t\nscript_stack_frame::get_num_symbols (octave_user_script *script)\n{\n  symbol_scope script_scope = script->scope ();\n\n  return script_scope.num_symbols ();\n}\n\nvoid\nscript_stack_frame::set_script_offsets ()\n{\n  // Set frame and data offsets inside stack frame based on enclosing\n  // scope(s).\n\n  symbol_scope script_scope = m_script->scope ();\n\n  std::size_t num_script_symbols = script_scope.num_symbols ();\n\n  resize (num_script_symbols);\n\n  const std::map<std::string, symbol_record>& script_symbols\n    = script_scope.symbols ();\n\n  set_script_offsets_internal (script_symbols);\n}\n\nvoid script_stack_frame::set_script_offsets_internal\n(const std::map<std::string, symbol_record>& script_symbols)\n{\n  // This scope will be used to evaluate the script.  Find (or\n  // possibly insert) symbols from the dummy script scope here.\n\n  symbol_scope eval_scope = m_access_link->get_scope ();\n\n  if (eval_scope.is_nested ())\n    {\n      bool found = false;\n\n      for (const auto& nm_sr : script_symbols)\n        {\n          std::string name = nm_sr.first;\n          symbol_record script_sr = nm_sr.second;\n\n          symbol_scope parent_scope = eval_scope;\n\n          std::size_t count = 1;\n\n          while (parent_scope)\n            {\n              const std::map<std::string, symbol_record>& parent_scope_symbols\n                = parent_scope.symbols ();\n\n              auto p = parent_scope_symbols.find (name);\n\n              if (p != parent_scope_symbols.end ())\n                {\n                  found = true;\n                  symbol_record parent_scope_sr = p->second;\n\n                  std::size_t script_sr_data_offset = script_sr.data_offset ();\n\n                  m_lexical_frame_offsets.at (script_sr_data_offset)\n                    = parent_scope_sr.frame_offset () + count;\n\n                  m_value_offsets.at (script_sr_data_offset)\n                    = parent_scope_sr.data_offset ();\n\n                  break;\n                }\n              else\n                {\n                  count++;\n                  parent_scope = parent_scope.parent_scope ();\n                }\n            }\n\n          if (! found)\n            error (\"symbol '%s' cannot be added to static scope\",\n                   name.c_str ());\n        }\n    }\n  else\n    {\n      const std::map<std::string, symbol_record>& eval_scope_symbols\n        = eval_scope.symbols ();\n\n      for (const auto& nm_sr : script_symbols)\n        {\n          std::string name = nm_sr.first;\n          symbol_record script_sr = nm_sr.second;\n\n          auto p = eval_scope_symbols.find (name);\n\n          symbol_record eval_scope_sr;\n\n          if (p == eval_scope_symbols.end ())\n            eval_scope_sr = eval_scope.insert (name);\n          else\n            eval_scope_sr = p->second;\n\n          std::size_t script_sr_data_offset = script_sr.data_offset ();\n\n          // The +1 is for going from the script frame to the eval\n          // frame.  Only one access_link should need to be followed.\n\n          m_lexical_frame_offsets.at (script_sr_data_offset)\n            = eval_scope_sr.frame_offset () + 1;\n\n          m_value_offsets.at (script_sr_data_offset)\n            = eval_scope_sr.data_offset ();\n        }\n    }\n}\n\nvoid\nscript_stack_frame::resize_and_update_script_offsets (const symbol_record& sym)\n{\n  std::size_t data_offset = sym.data_offset ();\n\n  // This function is called when adding new symbols to a script\n  // scope.  If the symbol wasn't present before, it should be outside\n  // the range so we need to resize then update offsets.\n\n  if (data_offset < size ())\n    error (\"unexpected: data_offset < size () in script_stack_frame::resize_and_update_script_offsets - please report this bug\");\n\n  resize (data_offset+1);\n\n  // FIXME: We should be able to avoid creating the map object and the\n  // looping in the set_scripts_offsets_internal function.  Can we do\n  // that without (or with minimal) code duplication?\n\n  std::map<std::string, symbol_record> tmp_symbols;\n  tmp_symbols[sym.name ()] = sym;\n  set_script_offsets_internal (tmp_symbols);\n}\n\n// If this is a nested scope, set access_link to nearest parent\n// stack frame that corresponds to the lexical parent of this scope.\n\nstd::shared_ptr<stack_frame>\nscript_stack_frame::get_access_link (const std::shared_ptr<stack_frame>& static_link)\n{\n  // If this script is called from another script, set access\n  // link to ultimate parent stack frame.\n\n  std::shared_ptr<stack_frame> alink = static_link;\n\n  while (alink->is_user_script_frame ())\n    {\n      if (alink->access_link ())\n        alink = alink->access_link ();\n      else\n        break;\n    }\n\n  return alink;\n}\n\nunwind_protect *\nscript_stack_frame::unwind_protect_frame ()\n{\n  if (! m_unwind_protect_frame)\n    m_unwind_protect_frame = new unwind_protect ();\n\n  return m_unwind_protect_frame;\n}\n\nsymbol_record\nscript_stack_frame::lookup_symbol (const std::string& name) const\n{\n  symbol_scope scope = get_scope ();\n\n  symbol_record sym = scope.lookup_symbol (name);\n\n  if (sym)\n    {\n      if (sym.frame_offset () != 0)\n        error (\"unexpected: sym.frame_offset () != 0 in script_stack_frame::lookup_symbol - please report this bug\");\n\n      return sym;\n    }\n\n  sym = m_access_link->lookup_symbol (name);\n\n  // Return symbol record with adjusted frame offset.\n  symbol_record new_sym = sym.dup ();\n\n  new_sym.set_frame_offset (sym.frame_offset () + 1);\n\n  return new_sym;\n}\n\nsymbol_record\nscript_stack_frame::insert_symbol (const std::string& name)\n{\n  // If the symbols is already in the immediate scope, there is\n  // nothing more to do.\n\n  symbol_scope scope = get_scope ();\n\n  symbol_record sym = scope.lookup_symbol (name);\n\n  if (sym)\n    {\n      // All symbol records in a script scope should have zero offset,\n      // which means we redirect our lookup using\n      // lexical_frame_offsets and values_offets.\n\n      if (sym.frame_offset () != 0)\n        error (\"unexpected: sym.frame_offset () != 0 in script_stack_frame::insert_symbol - please report this bug\");\n\n      return sym;\n    }\n\n  // Insert the symbol in the current scope then resize and update\n  // offsets.  This operation should never fail.\n\n  sym = scope.find_symbol (name);\n\n  if (! sym.is_valid ())\n    error (\"unexpected: sym is not valid in script_stack_frame::insert_symbol - please report this bug\");\n\n  resize_and_update_script_offsets (sym);\n\n  return sym;\n}\n\n// Similar to set_script_offsets_internal except that we only return\n// frame and data offsets for symbols found by name in parent scopes\n// instead of updating the offsets stored in the script frame itself.\n\nbool\nscript_stack_frame::get_val_offsets_internal (const symbol_record& script_sr,\n    std::size_t& frame_offset,\n    std::size_t& data_offset) const\n{\n  bool found = false;\n\n  // This scope will be used to evaluate the script.  Find symbols\n  // here by name.\n\n  symbol_scope eval_scope = m_access_link->get_scope ();\n\n  if (eval_scope.is_nested ())\n    {\n      std::string name = script_sr.name ();\n\n      symbol_scope parent_scope = eval_scope;\n\n      std::size_t count = 1;\n\n      while (parent_scope)\n        {\n          const std::map<std::string, symbol_record>& parent_scope_symbols\n            = parent_scope.symbols ();\n\n          auto p = parent_scope_symbols.find (name);\n\n          if (p != parent_scope_symbols.end ())\n            {\n              found = true;\n              symbol_record parent_scope_sr = p->second;\n\n              frame_offset = parent_scope_sr.frame_offset () + count;\n\n              data_offset = parent_scope_sr.data_offset ();\n\n              break;\n            }\n          else\n            {\n              count++;\n              parent_scope = parent_scope.parent_scope ();\n            }\n        }\n    }\n  else\n    {\n      const std::map<std::string, symbol_record>& eval_scope_symbols\n        = eval_scope.symbols ();\n\n      std::string name = script_sr.name ();\n\n      auto p = eval_scope_symbols.find (name);\n\n      symbol_record eval_scope_sr;\n\n      if (p != eval_scope_symbols.end ())\n        {\n          found = true;\n          eval_scope_sr = p->second;\n\n          // The +1 is for going from the script frame to the eval\n          // frame.  Only one access_link should need to be followed.\n\n          frame_offset = eval_scope_sr.frame_offset () + 1;\n\n          data_offset = eval_scope_sr.data_offset ();\n        }\n    }\n\n  return found;\n}\n\nbool\nscript_stack_frame::get_val_offsets (const symbol_record& sym,\n                                     std::size_t& frame_offset,\n                                     std::size_t& data_offset) const\n{\n  data_offset = sym.data_offset ();\n  frame_offset = sym.frame_offset ();\n\n  if (frame_offset == 0)\n    {\n      // An out of range data_offset value here means that we have a\n      // symbol that was not originally in the script.  But this\n      // function is called in places where we can't insert a new\n      // symbol, so we fail and it is up to the caller to decide what\n      // to do.\n\n      if (data_offset >= size ())\n        return get_val_offsets_internal (sym, frame_offset, data_offset);\n\n      // Use frame and value offsets stored in this stack frame,\n      // indexed by data_offset from the symbol_record to find the\n      // values.  These offsets were determined by\n      // script_stack_frame::set_script_offsets when this script was\n      // invoked.\n\n      frame_offset = m_lexical_frame_offsets.at (data_offset);\n\n      if (frame_offset == 0)\n        {\n          // If the frame offset stored in m_lexical_frame_offsets is\n          // zero, then the data offset in the evaluation scope has\n          // not been determined so try to do that now.  The symbol\n          // may have been added by eval and without calling\n          // resize_and_update_script_offsets.\n\n          return get_val_offsets_internal (sym, frame_offset, data_offset);\n        }\n\n      data_offset = m_value_offsets.at (data_offset);\n    }\n  else\n    {\n      // If frame_offset is not zero, then we must have a symbol\n      // that was not originally in the script.  The values should\n      // have been determined by the script_stack_frame::lookup function.\n    }\n\n  return true;\n}\n\nvoid\nscript_stack_frame::get_val_offsets_with_insert (const symbol_record& sym,\n    std::size_t& frame_offset,\n    std::size_t& data_offset)\n{\n  data_offset = sym.data_offset ();\n  frame_offset = sym.frame_offset ();\n\n  if (frame_offset == 0)\n    {\n      if (data_offset >= size ())\n        {\n          // If the data_offset is out of range, then we must have a\n          // symbol that was not originally in the script.  Resize and\n          // update the offsets.\n\n          resize_and_update_script_offsets (sym);\n        }\n\n      // Use frame and value offsets stored in this stack frame,\n      // indexed by data_offset from the symbol_record to find the\n      // values.  These offsets were determined by\n      // script_stack_frame::set_script_offsets when this script was\n      // invoked.\n\n      frame_offset = m_lexical_frame_offsets.at (data_offset);\n\n      if (frame_offset == 0)\n        {\n          // If the frame offset stored in m_lexical_frame_offsets is\n          // zero, then the data offset in the evaluation scope has\n          // not been determined so try to do that now.  The symbol\n          // may have been added by eval and without calling\n          // resize_and_update_script_offsets.\n\n          // We don't need to resize here.  That case is handled above.\n\n          // FIXME: We should be able to avoid creating the map object\n          // and the looping in the set_scripts_offsets_internal\n          // function.  Can we do that without (or with minimal) code\n          // duplication?\n\n          std::map<std::string, symbol_record> tmp_symbols;\n          tmp_symbols[sym.name ()] = sym;\n          set_script_offsets_internal (tmp_symbols);\n\n          // set_script_offsets_internal may have modified\n          // m_lexical_frame_offsets and m_value_offsets.\n\n          frame_offset = m_lexical_frame_offsets.at (data_offset);\n        }\n\n      data_offset = m_value_offsets.at (data_offset);\n    }\n  else\n    {\n      // If frame_offset is not zero, then we must have a symbol\n      // that was not originally in the script.  The values were\n      // determined by the script_stack_frame::lookup function.\n    }\n}\n\nstack_frame::scope_flags\nscript_stack_frame::scope_flag (const symbol_record& sym) const\n{\n  std::size_t frame_offset;\n  std::size_t data_offset;\n\n  bool found = get_val_offsets (sym, frame_offset, data_offset);\n\n  // It can't be global or persistent, so call it local.\n  if (! found)\n    return LOCAL;\n\n  // Follow frame_offset access links to stack frame that holds\n  // the value.\n\n  const stack_frame *frame = this;\n\n  for (std::size_t i = 0; i < frame_offset; i++)\n    {\n      std::shared_ptr<stack_frame> nxt = frame->access_link ();\n      frame = nxt.get ();\n    }\n\n  if (! frame)\n    error (\"internal error: invalid access link in function call stack\");\n\n  if (data_offset >= frame->size ())\n    return LOCAL;\n\n  return frame->get_scope_flag (data_offset);\n}\n\noctave_value\nscript_stack_frame::varval (const symbol_record& sym) const\n{\n  std::size_t frame_offset;\n  std::size_t data_offset;\n\n  bool found = get_val_offsets (sym, frame_offset, data_offset);\n\n  if (! found)\n    return octave_value ();\n\n  // Follow frame_offset access links to stack frame that holds\n  // the value.\n\n  const stack_frame *frame = this;\n\n  for (std::size_t i = 0; i < frame_offset; i++)\n    {\n      std::shared_ptr<stack_frame> nxt = frame->access_link ();\n      frame = nxt.get ();\n    }\n\n  if (! frame)\n    error (\"internal error: invalid access link in function call stack\");\n\n  if (data_offset >= frame->size ())\n    return octave_value ();\n\n  switch (frame->get_scope_flag (data_offset))\n    {\n    case LOCAL:\n      return frame->varval (data_offset);\n\n    case PERSISTENT:\n      {\n        symbol_scope scope = frame->get_scope ();\n\n        return scope.persistent_varval (data_offset);\n      }\n\n    case GLOBAL:\n      return m_evaluator.global_varval (sym.name ());\n    }\n\n  error (\"internal error: invalid switch case\");\n}\n\noctave_value&\nscript_stack_frame::varref (const symbol_record& sym)\n{\n  std::size_t frame_offset;\n  std::size_t data_offset;\n  get_val_offsets_with_insert (sym, frame_offset, data_offset);\n\n  // Follow frame_offset access links to stack frame that holds\n  // the value.\n\n  stack_frame *frame = this;\n\n  for (std::size_t i = 0; i < frame_offset; i++)\n    {\n      std::shared_ptr<stack_frame> nxt = frame->access_link ();\n      frame = nxt.get ();\n    }\n\n  if (data_offset >= frame->size ())\n    frame->resize (data_offset+1);\n\n  switch (frame->get_scope_flag (data_offset))\n    {\n    case LOCAL:\n      return frame->varref (data_offset);\n\n    case PERSISTENT:\n      {\n        symbol_scope scope = frame->get_scope ();\n\n        return scope.persistent_varref (data_offset);\n      }\n\n    case GLOBAL:\n      return m_evaluator.global_varref (sym.name ());\n    }\n\n  error (\"internal error: invalid switch case\");\n}\n\nvoid\nscript_stack_frame::mark_scope (const symbol_record& sym,\n                                scope_flags flag)\n{\n  std::size_t data_offset = sym.data_offset ();\n\n  if (data_offset >= size ())\n    resize_and_update_script_offsets (sym);\n\n  // Redirection to evaluation context for the script.\n\n  std::size_t frame_offset = m_lexical_frame_offsets.at (data_offset);\n  data_offset = m_value_offsets.at (data_offset);\n\n  if (frame_offset > 1)\n    error (\"variables must be made PERSISTENT or GLOBAL in the first scope in which they are used\");\n\n  std::shared_ptr<stack_frame> frame = access_link ();\n\n  if (data_offset >= frame->size ())\n    frame->resize (data_offset+1);\n\n  frame->set_scope_flag (data_offset, flag);\n}\n\nvoid\nscript_stack_frame::display (bool follow) const\n{\n  std::ostream& os = octave_stdout;\n\n  os << \"-- [script_stack_frame] (\" << this << \") --\" << std::endl;\n  stack_frame::display (follow);\n\n  os << \"script: \" << m_script->name ()\n     << \" (\" << m_script->type_name () << \")\" << std::endl;\n\n  os << \"lexical_offsets: \" << m_lexical_frame_offsets.size ()\n     << \" elements:\";\n\n  for (std::size_t i = 0; i < m_lexical_frame_offsets.size (); i++)\n    os << \"  \" << m_lexical_frame_offsets.at (i);\n  os << std::endl;\n\n  os << \"value_offsets: \" << m_value_offsets.size () << \" elements:\";\n  for (std::size_t i = 0; i < m_value_offsets.size (); i++)\n    os << \"  \" << m_value_offsets.at (i);\n  os << std::endl;\n\n  display_scope (os, get_scope ());\n}\n\nvoid\nscript_stack_frame::accept (stack_frame_walker& sfw)\n{\n  sfw.visit_script_stack_frame (*this);\n}\n\nvoid\nbase_value_stack_frame::display (bool follow) const\n{\n  std::ostream& os = octave_stdout;\n\n  os << \"-- [base_value_stack_frame] (\" << this << \") --\" << std::endl;\n  stack_frame::display (follow);\n\n  os << \"values: \" << m_values.size ()\n     << \" elements (idx, scope flag, type):\" << std::endl;\n\n  for (std::size_t i = 0; i < m_values.size (); i++)\n    {\n      os << \"  (\" << i << \", \" << m_flags.at (i) << \", \";\n\n      octave_value val = varval (i);\n\n      os << (val.is_defined () ? val.type_name () : \" UNDEFINED\") << \")\"\n         << std::endl;\n    }\n}\n\n// If this is a nested scope, set access_link to nearest parent\n// stack frame that corresponds to the lexical parent of this scope.\n\nstd::shared_ptr<stack_frame>\nuser_fcn_stack_frame::get_access_link (octave_user_function *fcn,\n                                       const std::shared_ptr<stack_frame>& static_link)\n{\n  std::shared_ptr<stack_frame> alink;\n\n  symbol_scope fcn_scope = fcn->scope ();\n\n  if (fcn_scope.is_nested ())\n    {\n      if (! static_link)\n        error (\"internal call stack error (invalid static link)\");\n\n      symbol_scope caller_scope = static_link->get_scope ();\n\n      int nesting_depth = fcn_scope.nesting_depth ();\n      int caller_nesting_depth = caller_scope.nesting_depth ();\n\n      if (caller_nesting_depth < nesting_depth)\n        {\n          // FIXME: do we need to ensure that the called\n          // function is a child of the caller?  Does it hurt\n          // to panic_unless this condition, at least for now?\n\n          alink = static_link;\n        }\n      else\n        {\n          // FIXME: do we need to check that the parent of the\n          // called function is also a parent of the caller?\n          // Does it hurt to panic_unless this condition, at least\n          // for now?\n\n          int links_to_follow = caller_nesting_depth - nesting_depth + 1;\n\n          alink = static_link;\n\n          while (alink && --links_to_follow >= 0)\n            alink = alink->access_link ();\n\n          if (! alink)\n            error (\"internal function nesting error (invalid access link)\");\n        }\n    }\n\n  return alink;\n}\n\nvoid\nuser_fcn_stack_frame::clear_values ()\n{\n  symbol_scope fcn_scope = m_fcn->scope ();\n\n  const std::list<symbol_record>& symbols = fcn_scope.symbol_list ();\n\n  if (size () == 0)\n    return;\n\n  for (const auto& sym : symbols)\n    {\n      std::size_t frame_offset = sym.frame_offset ();\n\n      if (frame_offset > 0)\n        continue;\n\n      std::size_t data_offset = sym.data_offset ();\n\n      if (data_offset >= size ())\n        continue;\n\n      if (get_scope_flag (data_offset) == LOCAL)\n        {\n          octave_value& ref = m_values.at (data_offset);\n\n          if (ref.get_count () == 1)\n            {\n              ref.call_object_destructor ();\n              ref = octave_value ();\n            }\n        }\n    }\n}\n\nunwind_protect *\nuser_fcn_stack_frame::unwind_protect_frame ()\n{\n  if (! m_unwind_protect_frame)\n    m_unwind_protect_frame = new unwind_protect ();\n\n  return m_unwind_protect_frame;\n}\n\nsymbol_record\nuser_fcn_stack_frame::lookup_symbol (const std::string& name) const\n{\n  const stack_frame *frame = this;\n\n  while (frame)\n    {\n      symbol_scope scope = frame->get_scope ();\n\n      symbol_record sym = scope.lookup_symbol (name);\n\n      if (sym)\n        return sym;\n\n      std::shared_ptr<stack_frame> nxt = frame->access_link ();\n      frame = nxt.get ();\n    }\n\n  return symbol_record ();\n}\n\nsymbol_record\nuser_fcn_stack_frame::insert_symbol (const std::string& name)\n{\n  // If the symbols is already in the immediate scope, there is\n  // nothing more to do.\n\n  symbol_scope scope = get_scope ();\n\n  symbol_record sym = scope.lookup_symbol (name);\n\n  if (sym)\n    return sym;\n\n  // FIXME: This needs some thought... We may need to add a symbol to\n  // a static workspace, but the symbol can never be defined as a\n  // variable.  This currently works by tagging the added symbol as\n  // \"added_static\".  Aside from the bad name, this doesn't seem like\n  // the best solution.  Maybe scopes should have a separate set of\n  // symbols that may only be defined as functions?\n\n  // Insert the symbol in the current scope.  This is not possible for\n  // anonymous functions, nested functions, or functions that contain\n  // nested functions (their scopes will all be marked static).\n\n  //    if (scope.is_static ())\n  //      error (\"can not add variable '%s' to a static workspace\",\n  //             name.c_str ());\n\n  // At this point, non-local references are not possible so we only\n  // need to look in the current scope and insert there.  This\n  // operation should never fail.\n\n  sym = scope.find_symbol (name);\n\n  if (! sym.is_valid ())\n    error (\"unexpected: sym is not valid in user_fcn_stack_frame::insert_symbol - please report this bug\");\n\n  return sym;\n}\n\nstack_frame::scope_flags\nuser_fcn_stack_frame::scope_flag (const symbol_record& sym) const\n{\n  std::size_t frame_offset = sym.frame_offset ();\n  std::size_t data_offset = sym.data_offset ();\n\n  // Follow frame_offset access links to stack frame that holds\n  // the value.\n\n  const stack_frame *frame = this;\n\n  for (std::size_t i = 0; i < frame_offset; i++)\n    {\n      std::shared_ptr<stack_frame> nxt = frame->access_link ();\n      frame = nxt.get ();\n    }\n\n  if (! frame)\n    error (\"internal error: invalid access link in function call stack\");\n\n  if (data_offset >= frame->size ())\n    return LOCAL;\n\n  return frame->get_scope_flag (data_offset);\n}\n\noctave_value\nuser_fcn_stack_frame::varval (const symbol_record& sym) const\n{\n  std::size_t frame_offset = sym.frame_offset ();\n  std::size_t data_offset = sym.data_offset ();\n\n  // Follow frame_offset access links to stack frame that holds\n  // the value.\n\n  const stack_frame *frame = this;\n\n  for (std::size_t i = 0; i < frame_offset; i++)\n    {\n      std::shared_ptr<stack_frame> nxt = frame->access_link ();\n      frame = nxt.get ();\n    }\n\n  if (! frame)\n    error (\"internal error: invalid access link in function call stack\");\n\n  if (data_offset >= frame->size ())\n    return octave_value ();\n\n  switch (frame->get_scope_flag (data_offset))\n    {\n    case LOCAL:\n      return frame->varval (data_offset);\n\n    case PERSISTENT:\n      {\n        symbol_scope scope = frame->get_scope ();\n\n        return scope.persistent_varval (data_offset);\n      }\n\n    case GLOBAL:\n      return m_evaluator.global_varval (sym.name ());\n    }\n\n  error (\"internal error: invalid switch case\");\n}\n\noctave_value&\nuser_fcn_stack_frame::varref (const symbol_record& sym)\n{\n  std::size_t frame_offset = sym.frame_offset ();\n  std::size_t data_offset = sym.data_offset ();\n\n  // Follow frame_offset access links to stack frame that holds\n  // the value.\n\n  stack_frame *frame = this;\n\n  for (std::size_t i = 0; i < frame_offset; i++)\n    {\n      std::shared_ptr<stack_frame> nxt = frame->access_link ();\n      frame = nxt.get ();\n    }\n\n  if (data_offset >= frame->size ())\n    frame->resize (data_offset+1);\n\n  switch (frame->get_scope_flag (data_offset))\n    {\n    case LOCAL:\n      return frame->varref (data_offset);\n\n    case PERSISTENT:\n      {\n        symbol_scope scope = frame->get_scope ();\n\n        return scope.persistent_varref (data_offset);\n      }\n\n    case GLOBAL:\n      return m_evaluator.global_varref (sym.name ());\n    }\n\n  error (\"internal error: invalid switch case\");\n}\n\nstd::string\nuser_fcn_stack_frame::inputname (int n, bool ids_only) const\n{\n  std::string name;\n\n  Array<std::string> arg_names\n    = m_auto_vars.at (stack_frame::ARG_NAMES).cellstr_value ();\n\n  if (n >= 0 && n < arg_names.numel ())\n    {\n      name = arg_names(n);\n\n      if (ids_only && ! m_static_link->is_variable (name))\n        name = \"\";\n    }\n\n  return name;\n}\n\nvoid\nuser_fcn_stack_frame::mark_scope (const symbol_record& sym, scope_flags flag)\n{\n  std::size_t frame_offset = sym.frame_offset ();\n\n  if (frame_offset > 0 && (flag == PERSISTENT || flag == GLOBAL))\n    error (\"variables must be made PERSISTENT or GLOBAL in the first scope in which they are used\");\n\n  std::size_t data_offset = sym.data_offset ();\n\n  if (data_offset >= size ())\n    resize (data_offset+1);\n\n  set_scope_flag (data_offset, flag);\n}\n\nvoid\nuser_fcn_stack_frame::display (bool follow) const\n{\n  std::ostream& os = octave_stdout;\n\n  os << \"-- [user_fcn_stack_frame] (\" << this << \") --\" << std::endl;\n  base_value_stack_frame::display (follow);\n\n  os << \"fcn: \" << m_fcn->name ()\n     << \" (\" << m_fcn->type_name () << \")\" << std::endl;\n\n  display_scope (os, get_scope ());\n}\n\nvoid\nuser_fcn_stack_frame::accept (stack_frame_walker& sfw)\n{\n  sfw.visit_user_fcn_stack_frame (*this);\n}\n\nvoid\nuser_fcn_stack_frame::break_closure_cycles (const std::shared_ptr<stack_frame>& frame)\n{\n  for (auto& val : m_values)\n    val.break_closure_cycles (frame);\n\n  if (m_access_link)\n    m_access_link->break_closure_cycles (frame);\n}\n\nsymbol_record\nscope_stack_frame::insert_symbol (const std::string& name)\n{\n  // There is no access link for scope frames, so there is no other\n  // frame to search in and the offset must be zero.\n\n  symbol_record sym = m_scope.lookup_symbol (name);\n\n  if (sym)\n    return sym;\n\n  // If the symbol is not found, insert it.  We only need to search in\n  // the local scope object.  This operation should never fail.\n\n  sym = m_scope.find_symbol (name);\n\n  if (! sym.is_valid ())\n    error (\"unexpected: sym is not valid in scope_stack_frame::insert_symbol - please report this bug\");\n\n  return sym;\n}\n\nstack_frame::scope_flags\nscope_stack_frame::scope_flag (const symbol_record& sym) const\n{\n  // There is no access link for scope frames, so the frame\n  // offset must be zero.\n\n  std::size_t data_offset = sym.data_offset ();\n\n  if (data_offset >= size ())\n    return LOCAL;\n\n  return get_scope_flag (data_offset);\n}\n\noctave_value\nscope_stack_frame::varval (const symbol_record& sym) const\n{\n  // There is no access link for scope frames, so the frame\n  // offset must be zero.\n\n  std::size_t data_offset = sym.data_offset ();\n\n  if (data_offset >= size ())\n    return octave_value ();\n\n  switch (get_scope_flag (data_offset))\n    {\n    case LOCAL:\n      return m_values.at (data_offset);\n\n    case PERSISTENT:\n      return m_scope.persistent_varval (data_offset);\n\n    case GLOBAL:\n      return m_evaluator.global_varval (sym.name ());\n    }\n\n  error (\"internal error: invalid switch case\");\n}\n\noctave_value&\nscope_stack_frame::varref (const symbol_record& sym)\n{\n  // There is no access link for scope frames, so the frame\n  // offset must be zero.\n\n  std::size_t data_offset = sym.data_offset ();\n\n  if (data_offset >= size ())\n    resize (data_offset+1);\n\n  switch (get_scope_flag (data_offset))\n    {\n    case LOCAL:\n      return m_values.at (data_offset);\n\n    case PERSISTENT:\n      return m_scope.persistent_varref (data_offset);\n\n    case GLOBAL:\n      return m_evaluator.global_varref (sym.name ());\n    }\n\n  error (\"internal error: invalid switch case\");\n}\n\nvoid\nscope_stack_frame::mark_scope (const symbol_record& sym,\n                               scope_flags flag)\n{\n  // There is no access link for scope frames, so the frame\n  // offset must be zero.\n\n  std::size_t data_offset = sym.data_offset ();\n\n  if (data_offset >= size ())\n    resize (data_offset+1);\n\n  set_scope_flag (data_offset, flag);\n}\n\nvoid\nscope_stack_frame::display (bool follow) const\n{\n  std::ostream& os = octave_stdout;\n\n  os << \"-- [scope_stack_frame] (\" << this << \") --\" << std::endl;\n  base_value_stack_frame::display (follow);\n\n  display_scope (os, m_scope);\n}\n\nvoid\nscope_stack_frame::accept (stack_frame_walker& sfw)\n{\n  sfw.visit_scope_stack_frame (*this);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/stack-frame.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_stack_frame_h)\n#define octave_stack_frame_h 1\n\n#include \"octave-config.h\"\n\n#include <deque>\n#include <iosfwd>\n#include <list>\n#include <map>\n#include <memory>\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\n\n#include \"error.h\"\n#include \"ov-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"syminfo.h\"\n#include \"symscope.h\"\n\n// Variable values are stored in the stack_frame objects that make up\n// the call_stack.  There are four separate stack_frame objects\n// corresponding to the following language elements:\n//\n//  * user-defined functions\n//\n//    These are .m files.  They have local variables.\n//\n//  * scripts\n//\n//    These are .m files, but not functions.  They access variables,\n//    but do not store any values directly.  All values are stored in\n//    the stack frame corresponding to the scope in which they are\n//    executed.\n//\n//  * scopes that do not correspond to functions\n//\n//    This is primarily used by the top-level scope but the\n//    interpreter may also create temporary scopes in which to\n//    evaluate functions or scripts.\n//\n// * compiled functions\n//\n//   These are built-in functions and dynamically-loaded compiled\n//   functions (.mex and .oct files) and do not contain variable\n//   values of their own.  They are skipped when Octave displays a\n//   stack trace.\n//\n// All stack frames also contain the following data:\n//\n//  * a reference to the evaluator that contains the frame\n//\n//    Global variables are now stored in the evaluator and this link\n//    gives us immediate access to them.\n//\n//  * line and column in the source file where the stack frame was created\n//\n//    These values are used to print stack traces.\n//\n//  * A pointer to the nearest parent frame that contains variable\n//    info (the \"static\" link)\n//\n//    A frame that contains variable info may be a user-defined\n//    function, script, or scope frame.  This pointer should never\n//    point to a compiled function stack frame.\n//\n//  * A pointer to the nearest lexical parent frame (the \"access\" link)\n//\n//    Used to access non-local variables for nested and anonymous\n//    functions or as a link to the parent frame in which a script is\n//    executed.  This pointer should only point to a parent function\n//    stack frame.\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_evaluator;\nclass symbol_info_list;\nclass unwind_protect;\n\nclass stack_frame_walker;\n\nclass stack_frame\n{\npublic:\n\n  typedef std::map<std::string, octave_value> local_vars_map;\n\n  // Markers indicating the type of a variable.  Values for local\n  // variables are stored in the stack frame.  Values for\n  // global variables are stored in the tree_evaluator object that\n  // contains the stack frame.  Values for persistent variables are\n  // stored in the function scope corresponding to the stack frame.\n\n  enum scope_flags\n  {\n    LOCAL,\n    GLOBAL,\n    PERSISTENT\n  };\n\n  // Index into the list of automatic variables for user-defined\n  // function stack frames.\n\n  enum auto_var_type\n  {\n    ARG_NAMES,\n    IGNORED,\n    NARGIN,\n    NARGOUT,\n    SAVED_WARNING_STATES,\n    NUM_AUTO_VARS\n  };\n\n  stack_frame () = delete;\n\n  stack_frame (tree_evaluator& tw, std::size_t index,\n               const std::shared_ptr<stack_frame>& parent_link,\n               const std::shared_ptr<stack_frame>& static_link,\n               const std::shared_ptr<stack_frame>& access_link)\n    : m_evaluator (tw), m_is_closure_context (false),\n      m_line (-1), m_column (-1), m_index (index),\n      m_parent_link (parent_link), m_static_link (static_link),\n      m_access_link (access_link), m_dispatch_class ()\n  { }\n\n  // Compiled function.\n  static stack_frame *\n  create (tree_evaluator& tw, octave_function *fcn, std::size_t index,\n          const std::shared_ptr<stack_frame>& parent_link,\n          const std::shared_ptr<stack_frame>& static_link);\n\n  // Script.\n  static stack_frame *\n  create (tree_evaluator& tw, octave_user_script *script, std::size_t index,\n          const std::shared_ptr<stack_frame>& parent_link,\n          const std::shared_ptr<stack_frame>& static_link);\n\n  // User-defined function.\n  static stack_frame *\n  create (tree_evaluator& tw, octave_user_function *fcn, std::size_t index,\n          const std::shared_ptr<stack_frame>& parent_link,\n          const std::shared_ptr<stack_frame>& static_link,\n          const std::shared_ptr<stack_frame>& access_link = std::shared_ptr<stack_frame> ());\n\n  // Anonymous user-defined function with init vars.\n  static stack_frame *\n  create (tree_evaluator& tw, octave_user_function *fcn, std::size_t index,\n          const std::shared_ptr<stack_frame>& parent_link,\n          const std::shared_ptr<stack_frame>& static_link,\n          const local_vars_map& local_vars,\n          const std::shared_ptr<stack_frame>& access_link = std::shared_ptr<stack_frame> ());\n\n  // Scope.\n  static stack_frame *\n  create (tree_evaluator& tw, const symbol_scope& scope, std::size_t index,\n          const std::shared_ptr<stack_frame>& parent_link,\n          const std::shared_ptr<stack_frame>& static_link);\n\n  stack_frame (const stack_frame& elt) = default;\n\n  stack_frame& operator = (const stack_frame& elt) = delete;\n\n  virtual ~stack_frame () = default;\n\n  // FIXME: It would be nice to eliminate these but there are a few\n  // places where we still need to know the specific type of the\n  // stack frame that we are handling.\n\n  virtual bool is_compiled_fcn_frame () const { return false; }\n  virtual bool is_user_script_frame () const { return false; }\n  virtual bool is_user_fcn_frame () const { return false; }\n  virtual bool is_scope_frame () const { return false; }\n\n  virtual void clear_values ();\n\n  std::size_t index () const { return m_index; }\n\n  void line (int l) { m_line = l; }\n  virtual int line () const { return m_line; }\n\n  void column (int c) { m_column = c; }\n  virtual int column () const { return m_column; }\n\n  std::string fcn_file_name () const\n  {\n    octave_function *fcn = function ();\n\n    return fcn ? fcn->fcn_file_name () : \"\";\n  }\n\n  std::string fcn_name (bool print_subfn = true) const\n  {\n    std::string retval;\n\n    octave_function *fcn = function ();\n\n    if (fcn)\n      {\n        std::string parent_fcn_name = fcn->parent_fcn_name ();\n\n        if (print_subfn && ! parent_fcn_name.empty ())\n          retval = parent_fcn_name + '>';\n\n        if (fcn->is_anonymous_function ())\n          retval += \"@<anonymous>\";\n        else\n          retval += fcn->name ();\n      }\n    else\n      retval = \"<unknown>\";\n\n    return retval;\n  }\n\n  virtual symbol_scope get_scope () const = 0;\n\n  virtual octave_function * function () const { return nullptr; }\n\n  virtual unwind_protect * unwind_protect_frame () { return nullptr; }\n\n  symbol_info_list\n  make_symbol_info_list (const std::list<symbol_record>& symrec_list) const;\n\n  octave_value who (const string_vector& patterns, bool have_regexp,\n                    bool return_list, bool verbose,\n                    const std::string& whos_line_fmt,\n                    const std::string& msg);\n\n  symbol_info_list all_variables ();\n\n  octave_value workspace ();\n\n  std::list<std::string> variable_names () const;\n\n  // Look for named symbol visible from current scope.  Don't\n  // attempt to insert if missing.\n  virtual symbol_record lookup_symbol (const std::string&) const = 0;\n\n  // Look for named symbol visible from current scope.  Attempt to\n  // insert if missing.\n  virtual symbol_record insert_symbol (const std::string&) = 0;\n\n  symbol_info_list glob_symbol_info (const std::string& pattern);\n\n  symbol_info_list regexp_symbol_info (const std::string& pattern);\n\n  symbol_info_list get_symbol_info ()\n  {\n    return all_variables ();\n  }\n\n  void make_persistent (const symbol_record& sym)\n  {\n    if (sym.is_formal ())\n      {\n        std::string nm = sym.name ();\n        error (\"can't make function parameter %s persistent\", nm.c_str ());\n      }\n\n    if (is_global (sym))\n      {\n        std::string nm = sym.name ();\n        error (\"can't make global variable '%s' persistent\", nm.c_str ());\n      }\n\n    install_variable (sym, octave_value (), false);\n\n    mark_persistent (sym);\n  }\n\n  void make_global (const symbol_record& sym)\n  {\n    if (is_persistent (sym))\n      {\n        std::string nm = sym.name ();\n        error (\"can't make persistent variable '%s' global\", nm.c_str ());\n      }\n\n    install_variable (sym, octave_value (), true);\n\n    mark_global (sym);\n  }\n\n  void clear_parent_static_link ()\n  {\n    m_parent_link = nullptr;\n    m_static_link = nullptr;\n  }\n\n  std::size_t\n  parent_frame_index () const { return m_parent_link->index (); }\n\n  std::shared_ptr<stack_frame>\n  parent_link () const {return m_parent_link; }\n\n  std::shared_ptr<stack_frame>\n  static_link () const {return m_static_link; }\n\n  std::shared_ptr<stack_frame>\n  access_link () const {return m_access_link; }\n\n  virtual std::size_t size () const;\n\n  virtual void resize (std::size_t);\n\n  void mark_global (const symbol_record& sym)\n  {\n    mark_scope (sym, GLOBAL);\n  }\n\n  void unmark_global (const symbol_record& sym)\n  {\n    mark_scope (sym, LOCAL);\n  }\n\n  void mark_persistent (const symbol_record& sym)\n  {\n    mark_scope (sym, PERSISTENT);\n  }\n\n  void unmark_persistent (const symbol_record& sym)\n  {\n    mark_scope (sym, LOCAL);\n  }\n\n  bool is_defined (const symbol_record& sym) const\n  {\n    octave_value val = varval (sym);\n\n    return val.is_defined ();\n  }\n\n  bool is_variable (const symbol_record& sym) const\n  {\n    octave_value val = varval (sym);\n\n    return val.is_defined ();\n  }\n\n  bool is_variable (const std::string& name) const\n  {\n    symbol_record sym = lookup_symbol (name);\n\n    return sym ? is_variable (sym) : false;\n  }\n\n  bool is_local_variable (const std::string& name) const\n  {\n    symbol_record sym = lookup_symbol (name);\n\n    return sym ? (is_variable (sym) && ! is_global (sym)) : false;\n  }\n\n  bool is_object (const symbol_record& sym) const\n  {\n    octave_value val = varval (sym);\n\n    return val.isobject ();\n  }\n\n  bool is_object (const std::string& name) const\n  {\n    symbol_record sym = lookup_symbol (name);\n\n    return sym ? is_object (sym) : false;\n  }\n\n  virtual scope_flags scope_flag (const symbol_record&) const = 0;\n\n  virtual scope_flags get_scope_flag (std::size_t) const;\n\n  virtual void set_scope_flag (std::size_t, scope_flags);\n\n  bool is_global (const symbol_record& sym) const\n  {\n    return scope_flag (sym) == GLOBAL;\n  }\n\n  bool is_global (const std::string& name) const\n  {\n    symbol_record sym = lookup_symbol (name);\n\n    return sym ? is_global (sym) : false;\n  }\n\n  bool is_persistent (const symbol_record& sym) const\n  {\n    return scope_flag (sym) == PERSISTENT;\n  }\n\n  bool is_persistent (const std::string& name) const\n  {\n    symbol_record sym = lookup_symbol (name);\n\n    return sym ? is_persistent (sym) : false;\n  }\n\n  void install_variable (const symbol_record& sym,\n                         const octave_value& value, bool global);\n\n  void install_variable (const std::string& name,\n                         const octave_value& value, bool global)\n  {\n    symbol_record sym = insert_symbol (name);\n\n    install_variable (sym, value, global);\n  }\n\n  virtual octave_value get_auto_fcn_var (auto_var_type) const = 0;\n\n  virtual void set_auto_fcn_var (auto_var_type, const octave_value&) = 0;\n\n  virtual void set_nargin (int nargin) { set_auto_fcn_var (NARGIN, nargin); }\n  virtual void set_nargout (int nargout) { set_auto_fcn_var (NARGOUT, nargout); }\n\n  virtual octave_value varval (const symbol_record& sym) const = 0;\n\n  virtual octave_value varval (std::size_t data_offset) const;\n\n  octave_value varval (const std::string& name) const\n  {\n    symbol_record sym = lookup_symbol (name);\n\n    return sym ? varval (sym) : octave_value ();\n  }\n\n\n  virtual octave_value& varref (const symbol_record& sym) = 0;\n\n  virtual octave_value& varref (std::size_t data_offset);\n\n  virtual std::string inputname (int n, bool ids_only) const;\n\n  void assign (const symbol_record& sym, const octave_value& val)\n  {\n    octave_value& lhs = varref (sym);\n\n    if (lhs.get_count () == 1)\n      lhs.call_object_destructor ();\n\n    // Regularize a null matrix if stored into a variable.\n    lhs = val.storable_value ();\n  }\n\n  void assign (const std::string& name, const octave_value& val)\n  {\n    symbol_record sym = insert_symbol (name);\n\n    assign (sym, val);\n  }\n\n  void assign (octave_value::assign_op op, const symbol_record& sym,\n               const std::string& type,\n               const std::list<octave_value_list>& idx,\n               const octave_value& rhs)\n  {\n    if (idx.empty ())\n      {\n        if (op == octave_value::op_asn_eq)\n          assign (sym, rhs);\n        else\n          varref (sym).assign (op, rhs);\n      }\n    else\n      varref (sym).assign (op, type, idx, rhs);\n  }\n\n  void non_const_unary_op (octave_value::unary_op op,\n                           const symbol_record& sym,\n                           const std::string& type,\n                           const std::list<octave_value_list>& idx)\n  {\n    if (idx.empty ())\n      varref (sym).non_const_unary_op (op);\n    else\n      varref (sym).non_const_unary_op (op, type, idx);\n  }\n\n  octave_value value (const symbol_record& sym, const std::string& type,\n                      const std::list<octave_value_list>& idx) const\n  {\n    octave_value retval = varval (sym);\n\n    if (! idx.empty ())\n      {\n        if (retval.is_constant ())\n          retval = retval.subsref (type, idx);\n        else\n          {\n            octave_value_list t = retval.subsref (type, idx, 1);\n\n            retval = t.length () > 0 ? t(0) : octave_value ();\n          }\n      }\n\n    return retval;\n  }\n\n  octave_value find_subfunction (const std::string& name) const\n  {\n    symbol_scope scope = get_scope ();\n\n    return scope.find_subfunction (name);\n  }\n\n  void clear (const symbol_record& sym)\n  {\n    if (is_global (sym))\n      unmark_global (sym);\n\n    assign (sym, octave_value ());\n\n    if (is_persistent (sym))\n      unmark_persistent (sym);\n  }\n\n  void clear_objects ();\n\n  void clear_variable (const std::string& name);\n\n  void clear_variable_pattern (const std::string& pattern);\n  void clear_variable_pattern (const string_vector& patterns);\n\n  void clear_variable_regexp (const std::string& pattern);\n  void clear_variable_regexp (const string_vector& patterns);\n\n  void clear_variables ();\n\n  std::string get_dispatch_class () const { return m_dispatch_class; }\n\n  void set_dispatch_class (const std::string& class_name)\n  {\n    m_dispatch_class = class_name;\n  }\n\n  void display_stopped_in_message (std::ostream& os) const;\n\n  void debug_where (std::ostream& os) const\n  {\n    display_stopped_in_message (os);\n  }\n\n  void debug_list (std::ostream& os, int num_lines) const;\n\n  void debug_type (std::ostream& os, int start_line, int end_line) const;\n\n  virtual void mark_scope (const symbol_record&, scope_flags) = 0;\n\n  virtual void display (bool follow = true) const;\n\n  virtual void accept (stack_frame_walker& sfw) = 0;\n\n  virtual void break_closure_cycles (const std::shared_ptr<stack_frame>&) { }\n\n  void mark_closure_context ()\n  {\n    m_is_closure_context = true;\n\n    // Mark any access linked frames as closure contexts too,\n    // so that they'll make any function handle on its stack frame\n    // weak when the frame itself is being popped.\n    auto nxt = access_link ();\n    while (nxt)\n      {\n        nxt->m_is_closure_context = true;\n        nxt = nxt->access_link ();\n      }\n  }\n\n  bool is_closure_context () const { return m_is_closure_context; }\n\nprotected:\n\n  // Reference to the call stack that contains this frame.  Global\n  // variables are stored in the call stack.  This link gives us\n  // immediate access to them.\n  tree_evaluator& m_evaluator;\n\n  // TRUE if this stack frame is saved with a handle to a nested\n  // function (closure).\n  bool m_is_closure_context;\n\n  // The line and column of the source file where this stack frame\n  // was created.  Used to print stack traces.\n  int m_line;\n  int m_column;\n\n  // Index in call stack.\n  std::size_t m_index;\n\n  // Pointer to the nearest parent frame.  May include compiled\n  // functions.\n  std::shared_ptr<stack_frame> m_parent_link;\n\n  // Pointer to the nearest parent frame that contains variable\n  // information (script, function, or scope).  This link skips over\n  // compiled function parent frames.\n  std::shared_ptr<stack_frame> m_static_link;\n\n  // Pointer to the nearest lexical parent frame.  Used to access\n  // non-local variables for nested and anonymous functions or as a\n  // link to the parent frame in which a script is executed.\n  std::shared_ptr<stack_frame> m_access_link;\n\n  // Allow function handles to temporarily store their dispatch class\n  // in the call stack.\n  std::string m_dispatch_class;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/syminfo.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iomanip>\n#include <list>\n#include <ostream>\n#include <sstream>\n\n#include \"Cell.h\"\n#include \"error.h\"\n#include \"octave-preserve-stream-state.h\"\n#include \"ov.h\"\n#include \"oct-map.h\"\n#include \"pager.h\"\n#include \"syminfo.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\nsymbol_info::display_line (std::ostream& os,\n                           const std::list<whos_parameter>& params) const\n{\n  std::string dims_str = m_value.get_dims_str ();\n\n  auto i = params.begin ();\n\n  preserve_stream_state stream_state (os);\n\n  while (i != params.end ())\n    {\n      whos_parameter param = *i;\n\n      if (param.command != '\\0')\n        {\n          // Do the actual printing.\n\n          switch (param.modifier)\n            {\n            case 'l':\n              os << std::setiosflags (std::ios::left)\n                 << std::setw (param.parameter_length);\n              break;\n\n            case 'r':\n              os << std::setiosflags (std::ios::right)\n                 << std::setw (param.parameter_length);\n              break;\n\n            case 'c':\n              if (param.command == 's')\n                {\n                  int front = param.first_parameter_length\n                              - dims_str.find ('x');\n                  int back = param.parameter_length\n                             - dims_str.length ()\n                             - front;\n                  front = (front > 0) ? front : 0;\n                  back = (back > 0) ? back : 0;\n\n                  os << std::setiosflags (std::ios::left)\n                     << std::setw (front)\n                     << \"\"\n                     << std::resetiosflags (std::ios::left)\n                     << dims_str\n                     << std::setiosflags (std::ios::left)\n                     << std::setw (back)\n                     << \"\"\n                     << std::resetiosflags (std::ios::left);\n                }\n              else\n                {\n                  os << std::setiosflags (std::ios::left)\n                     << std::setw (param.parameter_length);\n                }\n              break;\n\n            default:\n              error (\"whos_line_format: modifier '%c' unknown\",\n                     param.modifier);\n            }\n\n          switch (param.command)\n            {\n            case 'a':\n              {\n                char tmp[6];\n\n                tmp[0] = (m_is_complex ? 'c' : ' ');\n                tmp[1] = (m_is_sparse ? 's' : ' ');\n                tmp[2] = (m_is_formal ? 'f' : ' ');\n                tmp[3] = (m_is_global ? 'g' : ' ');\n                tmp[4] = (m_is_persistent ? 'p' : ' ');\n                tmp[5] = 0;\n\n                os << tmp;\n              }\n              break;\n\n            case 'b':\n              os << m_value.byte_size ();\n              break;\n\n            case 'c':\n              os << m_value.class_name ();\n              break;\n\n            case 'e':\n              os << m_value.numel ();\n              break;\n\n            case 'n':\n              os << m_name;\n              break;\n\n            case 's':\n              if (param.modifier != 'c')\n                os << dims_str;\n              break;\n\n            case 't':\n              os << m_value.type_name ();\n              break;\n\n            default:\n              error (\"whos_line_format: command '%c' unknown\",\n                     param.command);\n            }\n\n          os << std::resetiosflags (std::ios::left)\n             << std::resetiosflags (std::ios::right);\n          i++;\n        }\n      else\n        {\n          os << param.text;\n          i++;\n        }\n    }\n}\n\n// FIXME: should we be using std::map<symbol_info> instead of a list?\n\noctave_value\nsymbol_info_list::varval (const std::string& name) const\n{\n  for (const auto& syminfo : *this)\n    {\n      if (name == syminfo.name ())\n        return syminfo.value ();\n    }\n\n  return octave_value ();\n}\n\nstd::list<std::string>\nsymbol_info_list::names () const\n{\n  std::list<std::string> retval;\n\n  for (const auto& syminfo : *this)\n    retval.push_back (syminfo.name ());\n\n  return retval;\n}\n\noctave_map\nsymbol_info_list::map_value (const std::string& caller_function_name,\n                             int nesting_level) const\n{\n  std::size_t len = size ();\n\n  Cell name_info (len, 1);\n  Cell size_info (len, 1);\n  Cell bytes_info (len, 1);\n  Cell class_info (len, 1);\n  Cell global_info (len, 1);\n  Cell sparse_info (len, 1);\n  Cell complex_info (len, 1);\n  Cell nesting_info (len, 1);\n  Cell persistent_info (len, 1);\n\n  std::size_t j = 0;\n\n  for (const auto& syminfo : *this)\n    {\n      octave_scalar_map ni;\n\n      ni.assign (\"function\", caller_function_name);\n      ni.assign (\"level\", nesting_level);\n\n      name_info(j) = syminfo.name ();\n      global_info(j) = syminfo.is_global ();\n      persistent_info(j) = syminfo.is_persistent ();\n\n      octave_value val = syminfo.value ();\n\n      size_info(j) = val.size ();\n      bytes_info(j) = val.byte_size ();\n      class_info(j) = val.class_name ();\n      sparse_info(j) = val.issparse ();\n      complex_info(j) = val.iscomplex ();\n      nesting_info(j) = ni;\n\n      j++;\n    }\n\n  octave_map info;\n\n  info.assign (\"name\", name_info);\n  info.assign (\"size\", size_info);\n  info.assign (\"bytes\", bytes_info);\n  info.assign (\"class\", class_info);\n  info.assign (\"global\", global_info);\n  info.assign (\"sparse\", sparse_info);\n  info.assign (\"complex\", complex_info);\n  info.assign (\"nesting\", nesting_info);\n  info.assign (\"persistent\", persistent_info);\n\n  return info;\n}\n\nvoid\nsymbol_info_list::print_descriptor (std::ostream& os,\n                                    const std::list<whos_parameter> params) const\n{\n  std::ostringstream param_buf;\n\n  preserve_stream_state stream_state (os);\n\n  for (const auto& param : params)\n    {\n      if (param.command != '\\0')\n        {\n          // Do the actual printing\n          switch (param.modifier)\n            {\n            case 'l':\n              os << std::setiosflags (std::ios::left)\n                 << std::setw (param.parameter_length);\n              param_buf << std::setiosflags (std::ios::left)\n                        << std::setw (param.parameter_length);\n              break;\n\n            case 'r':\n              os << std::setiosflags (std::ios::right)\n                 << std::setw (param.parameter_length);\n              param_buf << std::setiosflags (std::ios::right)\n                        << std::setw (param.parameter_length);\n              break;\n\n            case 'c':\n              if (param.command != 's')\n                {\n                  os << std::setiosflags (std::ios::left)\n                     << std::setw (param.parameter_length);\n                  param_buf << std::setiosflags (std::ios::left)\n                            << std::setw (param.parameter_length);\n                }\n              break;\n\n            default:\n              os << std::setiosflags (std::ios::left)\n                 << std::setw (param.parameter_length);\n              param_buf << std::setiosflags (std::ios::left)\n                        << std::setw (param.parameter_length);\n            }\n\n          if (param.command == 's' && param.modifier == 'c')\n            {\n              int a = param.first_parameter_length - param.balance;\n              a = (a < 0 ? 0 : a);\n              int b = param.parameter_length - a - param.text.length ();\n              b = (b < 0 ? 0 : b);\n              os << std::setiosflags (std::ios::left) << std::setw (a)\n                 << \"\" << std::resetiosflags (std::ios::left) << param.text\n                 << std::setiosflags (std::ios::left)\n                 << std::setw (b) << \"\"\n                 << std::resetiosflags (std::ios::left);\n              param_buf << std::setiosflags (std::ios::left)\n                        << std::setw (a)\n                        << \"\" << std::resetiosflags (std::ios::left)\n                        << param.line\n                        << std::setiosflags (std::ios::left)\n                        << std::setw (b) << \"\"\n                        << std::resetiosflags (std::ios::left);\n            }\n          else\n            {\n              os << param.text;\n              param_buf << param.line;\n            }\n          os << std::resetiosflags (std::ios::left)\n             << std::resetiosflags (std::ios::right);\n          param_buf << std::resetiosflags (std::ios::left)\n                    << std::resetiosflags (std::ios::right);\n        }\n      else\n        {\n          os << param.text;\n          param_buf << param.line;\n        }\n    }\n\n  os << param_buf.str ();\n}\n\nvoid\nsymbol_info_list::display (std::ostream& os,\n                           const std::string& format) const\n{\n  if (! empty ())\n    {\n      std::size_t bytes = 0;\n      std::size_t elements = 0;\n\n      std::list<whos_parameter> params = parse_whos_line_format (format);\n\n      print_descriptor (os, params);\n\n      octave_stdout << \"\\n\";\n\n      for (const auto& syminfo : *this)\n        {\n          syminfo.display_line (os, params);\n\n          octave_value val = syminfo.value ();\n\n          elements += val.numel ();\n          bytes += val.byte_size ();\n        }\n\n      os << \"\\nTotal is \" << elements\n         << (elements == 1 ? \" element\" : \" elements\")\n         << \" using \" << bytes << (bytes == 1 ? \" byte\" : \" bytes\")\n         << \"\\n\";\n    }\n}\n\nstd::list<whos_parameter>\nsymbol_info_list::parse_whos_line_format (const std::string& format) const\n{\n  int idx;\n  std::size_t format_len = format.length ();\n  char garbage;\n  std::list<whos_parameter> params;\n\n  std::size_t bytes1;\n  int elements1;\n\n  std::string param_string = \"abcenst\";\n  Array<int> param_length (dim_vector (param_string.length (), 1));\n  Array<std::string> param_names (dim_vector (param_string.length (), 1));\n  std::size_t pos_a, pos_b, pos_c, pos_e, pos_n, pos_s, pos_t;\n\n  pos_a = param_string.find ('a'); // Attributes\n  pos_b = param_string.find ('b'); // Bytes\n  pos_c = param_string.find ('c'); // Class\n  pos_e = param_string.find ('e'); // Elements\n  pos_n = param_string.find ('n'); // Name\n  pos_s = param_string.find ('s'); // Size\n  pos_t = param_string.find ('t'); // Type\n\n  param_names(pos_a) = \"Attr\";\n  param_names(pos_b) = \"Bytes\";\n  param_names(pos_c) = \"Class\";\n  param_names(pos_e) = \"Elements\";\n  param_names(pos_n) = \"Name\";\n  param_names(pos_s) = \"Size\";\n  param_names(pos_t) = \"Type\";\n\n  for (std::size_t i = 0; i < param_string.length (); i++)\n    param_length(i) = param_names(i).length ();\n\n  // The attribute column needs size 6.\n  param_length(pos_a) = 6;\n\n  // Calculating necessary spacing for name column,\n  // bytes column, elements column and class column\n\n  for (const auto& syminfo : *this)\n    {\n      std::stringstream ss1, ss2;\n      std::string str;\n\n      str = syminfo.name ();\n      param_length(pos_n) = ((str.length ()\n                              > static_cast<std::size_t> (param_length(pos_n)))\n                             ? str.length () : param_length(pos_n));\n\n      octave_value val = syminfo.value ();\n\n      str = val.type_name ();\n      param_length(pos_t) = ((str.length ()\n                              > static_cast<std::size_t> (param_length(pos_t)))\n                             ? str.length () : param_length(pos_t));\n\n      elements1 = val.numel ();\n      ss1 << elements1;\n      str = ss1.str ();\n      param_length(pos_e) = ((str.length ()\n                              > static_cast<std::size_t> (param_length(pos_e)))\n                             ? str.length () : param_length(pos_e));\n\n      bytes1 = val.byte_size ();\n      ss2 << bytes1;\n      str = ss2.str ();\n      param_length(pos_b) = ((str.length ()\n                              > static_cast<std::size_t> (param_length(pos_b)))\n                             ? str.length () : param_length (pos_b));\n    }\n\n  idx = 0;\n  while (static_cast<std::size_t> (idx) < format_len)\n    {\n      whos_parameter param;\n      param.command = '\\0';\n\n      if (format[idx] == '%')\n        {\n          param.modifier = 'r';\n          param.parameter_length = 0;\n\n          int a = 0;\n          int b = -1;\n          int balance = 1;\n          unsigned int items;\n          std::size_t pos;\n          std::string cmd;\n\n          // Parse one command from format\n          cmd = format.substr (idx, format.length ());\n          pos = cmd.find (';');\n          if (pos == std::string::npos)\n            error (\"parameter without ; in format\");\n\n          cmd = cmd.substr (0, pos+1);\n\n          idx += cmd.length ();\n\n          // FIXME: use iostream functions instead of sscanf!\n\n          if (cmd.find_first_of (\"crl\") != 1)\n            items = sscanf (cmd.c_str (), \"%c%c:%d:%d:%d;\",\n                            &garbage, &param.command, &a, &b, &balance);\n          else\n            items = sscanf (cmd.c_str (), \"%c%c%c:%d:%d:%d;\",\n                            &garbage, &param.modifier, &param.command,\n                            &a, &b, &balance) - 1;\n\n          if (items < 2)\n            error (\"whos_line_format: found parameter structure without command\");\n\n          // Exception case of bare class command 'c' without modifier 'l/r'\n          if (param.modifier == 'c'\n              && param_string.find (param.command) == std::string::npos)\n            {\n              param.modifier = 'r';\n              param.command = 'c';\n            }\n\n          // Insert data into parameter\n          param.first_parameter_length = 0;\n          pos = param_string.find (param.command);\n          if (pos == std::string::npos)\n            error (\"whos_line_format: '%c' is not a command\", param.command);\n\n          param.parameter_length = param_length(pos);\n          param.text = param_names(pos);\n          param.line.assign (param_names(pos).length (), '=');\n\n          param.parameter_length = (a > param.parameter_length\n                                    ? a : param.parameter_length);\n          if (param.command == 's' && param.modifier == 'c' && b > 0)\n            param.first_parameter_length = b;\n\n          if (param.command == 's')\n            {\n              // Have to calculate space needed for printing\n              // matrix dimensions Space needed for Size column is\n              // hard to determine in prior, because it depends on\n              // dimensions to be shown.  That is why it is\n              // recalculated for each Size-command int first,\n              // rest = 0, total;\n              int rest = 0;\n              int first = param.first_parameter_length;\n              int total = param.parameter_length;\n\n              for (const auto& syminfo : *this)\n                {\n                  octave_value val = syminfo.value ();\n                  std::string dims_str = val.get_dims_str ();\n                  int first1 = dims_str.find ('x');\n                  int total1 = dims_str.length ();\n                  int rest1 = total1 - first1;\n                  rest = (rest1 > rest ? rest1 : rest);\n                  first = (first1 > first ? first1 : first);\n                  total = (total1 > total ? total1 : total);\n                }\n\n              if (param.modifier == 'c')\n                {\n                  if (first < balance)\n                    first += balance - first;\n                  if (rest + balance < param.parameter_length)\n                    rest += param.parameter_length - rest - balance;\n\n                  param.parameter_length = first + rest;\n                  param.first_parameter_length = first;\n                  param.balance = balance;\n                }\n              else\n                {\n                  param.parameter_length = total;\n                  param.first_parameter_length = 0;\n                }\n            }\n          else if (param.modifier == 'c')\n            error (\"whos_line_format: modifier 'c' not available for command '%c'\",\n                   param.command);\n\n          // What happens if format contains negative numbers\n          // at param_length positions?\n          param.balance = (b < 0 ? 0 : param.balance);\n          param.first_parameter_length = (b < 0\n                                          ? 0\n                                          : param.first_parameter_length);\n          param.parameter_length = (a < 0\n                                    ? 0\n                                    : (param.parameter_length\n                                       < param_length(pos_s)\n                                       ? param_length(pos_s)\n                                       : param.parameter_length));\n\n          params.push_back (param);\n        }\n      else\n        {\n          // Text string, to be printed as it is ...\n          std::string text;\n          std::size_t pos;\n          text = format.substr (idx, format.length ());\n          pos = text.find ('%');\n          if (pos != std::string::npos)\n            text = text.substr (0, pos);\n\n          // Push parameter into list ...\n          idx += text.length ();\n          param.text=text;\n          param.line.assign (text.length (), ' ');\n          params.push_back (param);\n        }\n    }\n\n  return params;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/syminfo.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_syminfo_h)\n#define octave_syminfo_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <list>\n#include <string>\n\n#include \"ov.h\"\n\nclass octave_map;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstruct whos_parameter\n{\n  char command;\n  char modifier;\n  int parameter_length;\n  int first_parameter_length;\n  int balance;\n  std::string text;\n  std::string line;\n};\n\nclass OCTINTERP_API symbol_info\n{\npublic:\n\n  symbol_info (const std::string& name, const octave_value& value,\n               bool is_formal, bool is_global, bool is_persistent)\n    : m_name (name), m_value (value), m_is_complex (value.iscomplex ()),\n      m_is_sparse (value.issparse ()), m_is_formal (is_formal),\n      m_is_global (is_global), m_is_persistent (is_persistent)\n  { }\n\n  std::string name () const { return m_name; }\n\n  octave_value value () const { return m_value; }\n\n  bool is_complex () const { return m_is_complex; }\n\n  bool is_sparse () const { return m_is_sparse; }\n\n  bool is_formal () const { return m_is_formal; }\n\n  bool is_global () const { return m_is_global; }\n\n  bool is_persistent () const { return m_is_persistent; }\n\n  void display_line (std::ostream& os,\n                     const std::list<whos_parameter>& params) const;\nprivate:\n\n  std::string m_name;\n  octave_value m_value;\n  bool m_is_complex;\n  bool m_is_sparse;\n  bool m_is_formal;\n  bool m_is_global;\n  bool m_is_persistent;\n};\n\nclass OCTINTERP_API symbol_info_list : public std::list<symbol_info>\n{\npublic:\n\n  symbol_info_list () = default;\n\n  symbol_info_list (const symbol_info_list&) = default;\n\n  symbol_info_list& operator = (const symbol_info_list&) = default;\n\n  ~symbol_info_list () = default;\n\n  octave_value varval (const std::string& name) const;\n\n  std::list<std::string> names () const;\n\n  octave_map map_value (const std::string& caller_function_name,\n                        int nesting_level) const;\n\n  // Print a line of information for a given symbol.\n  void print_descriptor (std::ostream& os,\n                         const std::list<whos_parameter> params) const;\n\n  void display (std::ostream& os, const std::string& format) const;\n\n  // Parse FORMAT, and return a parameter list,\n  // containing all information needed to print the given\n  // attributes of the symbols.\n  std::list<whos_parameter>\n  parse_whos_line_format (const std::string& format) const;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/symrec.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"oct-env.h\"\n#include \"oct-time.h\"\n\n#include \"fcn-info.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"symrec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstd::shared_ptr<symbol_record::symbol_record_rep>\nsymbol_record::symbol_record_rep::dup () const\n{\n  return std::shared_ptr<symbol_record::symbol_record_rep> (new symbol_record_rep (*this));\n}\n\noctave_value\nsymbol_record::symbol_record_rep::dump () const\n{\n  std::map<std::string, octave_value> m\n  = {{ \"frame_offset\", m_frame_offset },\n    { \"data_offset\", m_data_offset },\n    { \"name\", m_name },\n    { \"local\", is_local () },\n    { \"formal\", is_formal () }\n  };\n\n  return octave_value (m);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/symrec.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_symrec_h)\n#define octave_symrec_h 1\n\n#include \"octave-config.h\"\n\n#include <deque>\n#include <list>\n#include <memory>\n#include <string>\n\nclass octave_user_function;\n\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API symbol_record\n{\npublic:\n\n  typedef std::size_t context_id;\n\n  enum symrec_t : unsigned char\n  {\n    // generic variable\n    LOCAL = 1,\n    // formal parameter\n    FORMAL = 2,\n    // this symbol may NOT become a variable.\n    // (symbol added to a static workspace)\n    ADDED_STATIC = 4,\n    // this symbol was recognized as a variable from syntax\n    VARIABLE = 8\n  };\n\nprivate:\n\n  class symbol_record_rep\n  {\n  public:\n\n    symbol_record_rep () = delete;\n\n    symbol_record_rep (const std::string& nm, symrec_t sc)\n      : m_frame_offset (0), m_data_offset (0), m_storage_class (sc),\n        m_name (nm)\n    { }\n\n    OCTAVE_DEFAULT_COPY_MOVE_DELETE (symbol_record_rep)\n\n    // FIXME: use special storage class instead?\n    bool is_valid () const { return ! m_name.empty (); }\n\n    void set_frame_offset (std::size_t offset) { m_frame_offset = offset; }\n\n    std::size_t frame_offset () const { return m_frame_offset; }\n\n    void set_data_offset (std::size_t offset) { m_data_offset = offset; }\n\n    std::size_t data_offset () const { return m_data_offset; }\n\n    bool is_local () const\n    {\n      return m_storage_class & LOCAL;\n    }\n\n    bool is_formal () const\n    {\n      return m_storage_class & FORMAL;\n    }\n\n    bool is_added_static () const\n    {\n      return m_storage_class & ADDED_STATIC;\n    }\n\n    bool is_variable () const\n    {\n      return m_storage_class & VARIABLE;\n    }\n\n    void mark_local ()\n    {\n      m_storage_class = static_cast<symrec_t> (m_storage_class | LOCAL);\n    }\n\n    void mark_formal ()\n    {\n      // Formal parameters are also variables.\n      m_storage_class = static_cast<symrec_t> (m_storage_class\n                        | FORMAL | VARIABLE);\n    }\n\n    void mark_added_static ()\n    {\n      m_storage_class = static_cast<symrec_t> (m_storage_class\n                        | ADDED_STATIC);\n    }\n\n    void mark_variable ()\n    {\n      m_storage_class = static_cast<symrec_t> (m_storage_class | VARIABLE);\n    }\n\n    void unmark_local ()\n    {\n      m_storage_class = static_cast<symrec_t> (m_storage_class & ~LOCAL);\n    }\n\n    void unmark_formal ()\n    {\n      m_storage_class = static_cast<symrec_t> (m_storage_class & ~FORMAL);\n    }\n\n    void unmark_added_static ()\n    {\n      m_storage_class = static_cast<symrec_t> (m_storage_class\n                        & ~ADDED_STATIC);\n    }\n\n    void unmark_variable ()\n    {\n      m_storage_class = static_cast<symrec_t> (m_storage_class & ~VARIABLE);\n    }\n\n    unsigned int storage_class () const { return m_storage_class; }\n\n    std::shared_ptr<symbol_record_rep> dup () const;\n\n    octave_value dump () const;\n\n    std::string name () const { return m_name; }\n\n    void rename (const std::string& new_name) { m_name = new_name; }\n\n  private:\n\n    std::size_t m_frame_offset;\n    std::size_t m_data_offset;\n\n    symrec_t m_storage_class;\n\n    std::string m_name;\n  };\n\npublic:\n\n  symbol_record (const std::string& nm = \"\", symrec_t sc = LOCAL)\n    : m_rep (new symbol_record_rep (nm, sc))\n  { }\n\n  symbol_record (const std::string& nm, const octave_value&,\n                 symrec_t sc = LOCAL)\n    : m_rep (new symbol_record_rep (nm, sc))\n  { }\n\n  symbol_record (const symbol_record&) = default;\n\n  symbol_record& operator = (const symbol_record&) = default;\n\n  ~symbol_record () = default;\n\n  bool is_valid () const { return m_rep->is_valid (); }\n\n  explicit operator bool () const { return is_valid (); }\n\n  void set_frame_offset (std::size_t offset)\n  { m_rep->set_frame_offset (offset); }\n\n  std::size_t frame_offset () const { return m_rep->frame_offset (); }\n\n  void set_data_offset (std::size_t offset)\n  { m_rep->set_data_offset (offset); }\n\n  std::size_t data_offset () const { return m_rep->data_offset (); }\n\n  symbol_record dup () const { return symbol_record (m_rep->dup ()); }\n\n  std::string name () const { return m_rep->name (); }\n\n  void rename (const std::string& new_name) { m_rep->rename (new_name); }\n\n  bool is_local () const { return m_rep->is_local (); }\n  bool is_formal () const { return m_rep->is_formal (); }\n  bool is_added_static () const { return m_rep->is_added_static (); }\n  bool is_variable () const { return m_rep->is_variable (); }\n\n  void mark_local () { m_rep->mark_local (); }\n  void mark_formal () { m_rep->mark_formal (); }\n  void mark_added_static () { m_rep->mark_added_static (); }\n  void mark_variable () { m_rep->mark_variable (); }\n\n  void unmark_local () { m_rep->unmark_local (); }\n  void unmark_formal () { m_rep->unmark_formal (); }\n  void unmark_added_static () { m_rep->unmark_added_static (); }\n  void unmark_variable () { m_rep->unmark_variable (); }\n\n  unsigned int storage_class () const { return m_rep->storage_class (); }\n\n  octave_value dump () const { return m_rep->dump (); }\n\nprivate:\n\n  std::shared_ptr<symbol_record_rep> m_rep;\n\n  // NEW_REP must be dynamically allocated or nullptr.\n  symbol_record (const std::shared_ptr<symbol_record_rep>& new_rep)\n    : m_rep (new_rep)\n  { }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/symscope.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"file-ops.h\"\n\n#include \"fcn-info.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ov-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"symrec.h\"\n#include \"symscope.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nsymbol_record symbol_scope::symbol_scope_rep::insert_local (const std::string& name)\n{\n  symbol_record sym (name);\n\n  insert_symbol_record (sym);\n\n  return sym;\n}\n\nvoid\nsymbol_scope::symbol_scope_rep::insert_symbol_record (symbol_record& sr)\n{\n  std::size_t data_offset = num_symbols ();\n  std::string name = sr.name ();\n\n  sr.set_data_offset (data_offset);\n\n  m_symbols[name] = sr;\n}\n\nsymbol_record\nsymbol_scope::symbol_scope_rep::insert (const std::string& name)\n{\n  table_iterator p = m_symbols.find (name);\n\n  if (p == m_symbols.end ())\n    {\n      symbol_record ret (name);\n\n      std::size_t data_offset = num_symbols ();\n\n      ret.set_data_offset (data_offset);\n\n      auto t_parent = m_parent.lock ();\n\n      std::size_t offset = 0;\n\n      if (is_nested () && t_parent\n          && t_parent->look_nonlocal (name, offset, ret))\n        return m_symbols[name] = ret;\n      else\n        {\n          if (m_is_static)\n            ret.mark_added_static ();\n\n          return m_symbols[name] = ret;\n        }\n    }\n  else\n    return p->second;\n}\n\nstd::list<octave_value>\nsymbol_scope::symbol_scope_rep::localfunctions () const\n{\n  std::list<octave_value> retval;\n\n  // Find the subfunctions of this function (which should be the\n  // primary parent function for this scope).\n\n  // 1) m_subfunction_names contains only valid subfunctions\n  // 2) m_subfunctions contains both nested functions and subfunctions\n\n  // loop over them.\n\n  for (const auto& nm : m_subfunction_names)\n    {\n      auto nm_fcn_iter = m_subfunctions.find (nm);\n\n      if (nm_fcn_iter != m_subfunctions.end ())\n        {\n          octave_value ov_fcn = nm_fcn_iter->second;\n          octave_user_code *fcn = ov_fcn.user_code_value ();\n\n          if (! fcn)\n            continue;\n\n          symbol_scope scope = fcn->scope ();\n\n          std::list<std::string> plst = scope.parent_fcn_names ();\n\n          octave_fcn_handle *fh = new octave_fcn_handle (ov_fcn, nm, plst);\n\n          retval.push_back (octave_value (fh));\n        }\n    }\n\n  return retval;\n}\n\noctave_value\nsymbol_scope::symbol_scope_rep::dump () const\n{\n  std::map<std::string, octave_value> m\n  = {{ \"name\", m_name },\n    { \"nesting_depth\", m_nesting_depth },\n    { \"is_static\", m_is_static },\n    { \"symbols\", dump_symbols_map () },\n    { \"subfunction_names\", string_vector (m_subfunction_names) },\n    { \"subfunctions\", dump_function_map (m_subfunctions) }\n  };\n\n  return octave_value (m);\n}\n\noctave_value\nsymbol_scope::symbol_scope_rep::dump_symbols_map () const\n{\n  std::map<std::string, octave_value> info_map;\n\n  for (const auto& nm_sr : m_symbols)\n    {\n      std::string nm = nm_sr.first;\n      symbol_record sr = nm_sr.second;\n      info_map[nm] = sr.dump ();\n    }\n\n  return octave_value (info_map);\n}\n\nstd::list<symbol_record>\nsymbol_scope::symbol_scope_rep::symbol_list () const\n{\n  std::list<symbol_record> retval;\n\n  for (const auto& nm_sr : m_symbols)\n    retval.push_back (nm_sr.second);\n\n  return retval;\n}\n\noctave_value\nsymbol_scope::symbol_scope_rep::find_subfunction (const std::string& name) const\n{\n  subfunctions_const_iterator p = m_subfunctions.find (name);\n\n  if (p != m_subfunctions.end ())\n    return p->second;\n\n  auto t_parent = m_parent.lock ();\n\n  if (t_parent)\n    return t_parent->find_subfunction (name);\n\n  return octave_value ();\n}\n\nvoid\nsymbol_scope::symbol_scope_rep::mark_subfunctions_in_scope_as_private (const std::string& class_name)\n{\n  for (auto& nm_sf : m_subfunctions)\n    {\n      octave_function *fcn = nm_sf.second.function_value ();\n\n      if (fcn)\n        fcn->mark_as_private_function (class_name);\n    }\n}\n\nstd::list<std::string>\nsymbol_scope::symbol_scope_rep::parent_fcn_names () const\n{\n  std::list<std::string> retval;\n\n  auto pscope = parent_scope_rep ();\n\n  while (pscope)\n    {\n      retval.push_back (pscope->fcn_name ());\n\n      pscope = pscope->parent_scope_rep ();\n    }\n\n  return retval;\n}\n\nvoid\nsymbol_scope::symbol_scope_rep::set_parent (const std::shared_ptr<symbol_scope::symbol_scope_rep>& parent)\n{\n  m_parent = std::weak_ptr<symbol_scope::symbol_scope_rep> (parent);\n}\n\nvoid\nsymbol_scope::symbol_scope_rep::set_primary_parent (const std::shared_ptr<symbol_scope::symbol_scope_rep>& parent)\n{\n  m_primary_parent = std::weak_ptr<symbol_scope::symbol_scope_rep> (parent);\n}\n\nvoid\nsymbol_scope::symbol_scope_rep::cache_dir_name (const std::string& name)\n{\n  m_dir_name = sys::canonicalize_file_name (name);\n}\n\nbool\nsymbol_scope::symbol_scope_rep::is_relative (const std::shared_ptr<symbol_scope::symbol_scope_rep>& scope) const\n{\n  if (is_nested ())\n    {\n      // Since is_nested is true, the following should always return a\n      // valid scope.\n\n      auto t_parent = m_parent.lock ();\n\n      if (t_parent)\n        {\n          // SCOPE is the parent of this scope: this scope is a child\n          // of SCOPE.\n\n          if (t_parent == scope)\n            return true;\n        }\n\n      auto t_primary_parent = m_primary_parent.lock ();\n\n      if (t_primary_parent)\n        {\n          // SCOPE is the primary parent of this scope: this scope is a\n          // child (or grandchild) of SCOPE.\n          if (t_primary_parent == scope)\n            return true;\n\n          // SCOPE and this scope share the same primary parent: they are\n          // siblings (or cousins)\n          auto scope_primary_parent = scope->primary_parent_scope_rep ();\n          if (t_primary_parent == scope_primary_parent)\n            return true;\n        }\n    }\n\n  return false;\n}\n\nvoid\nsymbol_scope::symbol_scope_rep::mark_as_variable (const std::string& nm)\n{\n  table_iterator p = m_symbols.find (nm);\n\n  if (p != m_symbols.end ())\n    p->second.mark_variable ();\n}\n\nvoid\nsymbol_scope::symbol_scope_rep::mark_as_variables (const std::list<std::string>& lst)\n{\n  for (const auto& nm : lst)\n    mark_as_variable (nm);\n}\n\nbool\nsymbol_scope::symbol_scope_rep::is_variable (const std::string& nm) const\n{\n  table_const_iterator p = m_symbols.find (nm);\n\n  // FIXME: maybe we should also mark formal parameters as variables?\n\n  if (p != m_symbols.end () && p->second.is_variable ())\n    return true;\n\n  if (is_nested ())\n    {\n      auto t_parent = m_parent.lock ();\n\n      return t_parent ? t_parent->is_variable (nm) : false;\n    }\n\n  return false;\n}\n\nvoid\nsymbol_scope::symbol_scope_rep::update_nest ()\n{\n  auto t_parent = m_parent.lock ();\n\n  if (t_parent)\n    {\n      // fix bad symbol_records\n      for (auto& nm_sr : m_symbols)\n        {\n          symbol_record& ours = nm_sr.second;\n\n          std::size_t offset = 0;\n\n          if (! ours.is_formal () && is_nested ())\n            t_parent->look_nonlocal (nm_sr.first, offset, ours);\n        }\n\n      // The scopes of nested functions are static.\n      if (is_nested ())\n        m_is_static = true;\n    }\n  else if (m_children.size ())\n    {\n      // Parents of nested functions have static scopes.\n      m_is_static = true;\n    }\n\n  for (auto& scope_obj : m_children)\n    scope_obj.update_nest ();\n}\n\nbool\nsymbol_scope::symbol_scope_rep::look_nonlocal (const std::string& name,\n                                               std::size_t offset,\n                                               symbol_record& result)\n{\n  offset++;\n\n  table_iterator p = m_symbols.find (name);\n\n  if (p == m_symbols.end ())\n    {\n      auto t_parent = m_parent.lock ();\n\n      if (is_nested () && t_parent)\n        return t_parent->look_nonlocal (name, offset, result);\n    }\n  else\n    {\n      // Add scope offsets because the one we found may be used in\n      // this scope but initially from another parent scope beyond\n      // that.  The parent offset will already point to the first\n      // occurrence because we do the overall nesting update from the\n      // parent function down through the lists of all children.\n\n      std::size_t t_frame_offset = offset + p->second.frame_offset ();\n      std::size_t t_data_offset = p->second.data_offset ();\n\n      result.set_frame_offset (t_frame_offset);\n      result.set_data_offset (t_data_offset);\n\n      return true;\n    }\n\n  return false;\n}\n\nstd::list<octave_value>\nsymbol_scope::localfunctions () const\n{\n  if (! m_rep)\n    return std::list<octave_value> ();\n\n  if (is_primary_fcn_scope ())\n    return m_rep->localfunctions ();\n\n  std::shared_ptr<symbol_scope::symbol_scope_rep> ppsr\n    = m_rep->primary_parent_scope_rep ();\n\n  if (! ppsr)\n    return std::list<octave_value> ();\n\n  return ppsr->localfunctions ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/symscope.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_symscope_h)\n#define octave_symscope_h 1\n\n#include \"octave-config.h\"\n\n#include <deque>\n#include <list>\n#include <map>\n#include <memory>\n#include <set>\n#include <string>\n\n#include \"glob-match.h\"\n#include \"oct-refcount.h\"\n#include \"oct-regexp.h\"\n\nclass tree_argument_list;\nclass octave_user_code;\n\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"symrec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API symbol_scope\n{\nprivate:\n\n  class symbol_scope_rep\n    : public std::enable_shared_from_this<symbol_scope_rep>\n  {\n  public:\n\n    typedef std::map<std::string, symbol_record>::const_iterator\n      table_const_iterator;\n    typedef std::map<std::string, symbol_record>::iterator\n      table_iterator;\n\n    typedef std::map<std::string, octave_value>::const_iterator\n      subfunctions_const_iterator;\n    typedef std::map<std::string, octave_value>::iterator\n      subfunctions_iterator;\n\n    symbol_scope_rep (const std::string& name = \"\", bool add_ans = true)\n      : m_name (name), m_symbols (), m_subfunctions (),\n        m_persistent_values (), m_code (nullptr), m_fcn_name (),\n        m_fcn_file_name (), m_dir_name (), m_parent (),\n        m_primary_parent (), m_children (), m_nesting_depth (0),\n        m_is_static (false), m_is_primary_fcn_scope (false)\n    {\n      // Most scopes have ans as the first symbol, initially undefined.\n      if (add_ans)\n        insert_local (\"ans\");\n    }\n\n    OCTAVE_DISABLE_COPY_MOVE (symbol_scope_rep)\n\n    ~symbol_scope_rep () = default;\n\n    std::size_t num_symbols () const { return m_symbols.size (); }\n\n    // Simply inserts symbol.  No non-local searching.\n\n    symbol_record insert_local (const std::string& name);\n\n    void insert_symbol_record (symbol_record& sr);\n\n    bool is_nested () const { return m_nesting_depth > 0; }\n\n    std::size_t nesting_depth () const { return m_nesting_depth; }\n\n    void set_nesting_depth (std::size_t depth) { m_nesting_depth = depth; }\n\n    bool is_parent () const { return ! m_children.empty (); }\n\n    bool is_static () const { return m_is_static; }\n\n    void mark_static () { m_is_static = true; }\n\n    std::shared_ptr<symbol_scope_rep> parent_scope_rep () const\n    {\n      return m_parent.lock ();\n    }\n\n    std::shared_ptr<symbol_scope_rep> primary_parent_scope_rep () const\n    {\n      return m_primary_parent.lock ();\n    }\n\n    std::shared_ptr<symbol_scope_rep> dup () const\n    {\n      std::shared_ptr<symbol_scope_rep> new_sid\n        = std::shared_ptr<symbol_scope_rep> (new symbol_scope_rep (m_name));\n\n      for (const auto& nm_sr : m_symbols)\n        new_sid->m_symbols[nm_sr.first] = nm_sr.second.dup ();\n\n      new_sid->m_subfunctions = m_subfunctions;\n      new_sid->m_persistent_values = m_persistent_values;\n      new_sid->m_subfunction_names = m_subfunction_names;\n      new_sid->m_code = m_code;\n      new_sid->m_fcn_name = m_fcn_name;\n      new_sid->m_fcn_file_name = m_fcn_file_name;\n      new_sid->m_dir_name = m_dir_name;\n      new_sid->m_parent = m_parent;\n      new_sid->m_primary_parent = m_primary_parent;\n      new_sid->m_children = m_children;\n      new_sid->m_nesting_depth = m_nesting_depth;\n      new_sid->m_is_static = m_is_static;\n      new_sid->m_is_primary_fcn_scope = m_is_primary_fcn_scope;\n\n      return new_sid;\n    }\n\n    octave_value& persistent_varref (std::size_t data_offset)\n    {\n      return m_persistent_values[data_offset];\n    }\n\n    octave_value persistent_varval (std::size_t data_offset) const\n    {\n      auto p = m_persistent_values.find (data_offset);\n\n      return p == m_persistent_values.end () ? octave_value () : p->second;\n    }\n\n    symbol_record find_symbol (const std::string& name)\n    {\n      auto p = m_symbols.find (name);\n\n      if (p == m_symbols.end ())\n        return insert (name);\n      else\n        return p->second;\n    }\n\n    symbol_record lookup_symbol (const std::string& name) const\n    {\n      auto p = m_symbols.find (name);\n\n      return p == m_symbols.end () ? symbol_record () : p->second;\n    }\n\n    symbol_record insert (const std::string& name);\n\n    void rename (const std::string& old_name, const std::string& new_name)\n    {\n      auto p = m_symbols.find (old_name);\n\n      if (p != m_symbols.end ())\n        {\n          symbol_record sr = p->second;\n\n          sr.rename (new_name);\n\n          m_symbols.erase (p);\n\n          m_symbols[new_name] = sr;\n        }\n    }\n\n    void install_subfunction (const std::string& name,\n                              const octave_value& fval)\n    {\n      m_subfunctions[name] = fval;\n    }\n\n    void install_nestfunction (const std::string& name,\n                               const octave_value& fval,\n                               const symbol_scope& fcn_scope)\n    {\n      m_subfunctions[name] = fval;\n\n      m_children.push_back (fcn_scope);\n    }\n\n    octave_value find_subfunction (const std::string& name) const;\n\n    void lock_subfunctions ()\n    {\n      for (auto& nm_sf : m_subfunctions)\n        nm_sf.second.lock ();\n    }\n\n    void unlock_subfunctions ()\n    {\n      for (auto& nm_sf : m_subfunctions)\n        nm_sf.second.unlock ();\n    }\n\n    // Pairs of name, function objects.\n    std::map<std::string, octave_value> subfunctions () const\n    {\n      return m_subfunctions;\n    }\n\n    void erase_subfunctions ()\n    {\n      m_subfunctions.clear ();\n    }\n\n    void mark_subfunctions_in_scope_as_private (const std::string& class_name);\n\n    bool has_subfunctions () const\n    {\n      return ! m_subfunction_names.empty ();\n    }\n\n    void stash_subfunction_names (const std::list<std::string>& names)\n    {\n      m_subfunction_names = names;\n    }\n\n    std::list<std::string> subfunction_names () const\n    {\n      return m_subfunction_names;\n    }\n\n    std::list<octave_value> localfunctions () const;\n\n    octave_value dump () const;\n\n    std::string name () const { return m_name; }\n\n    void cache_name (const std::string& name) { m_name = name; }\n\n    std::string fcn_name () const { return m_fcn_name; }\n\n    void cache_fcn_name (const std::string& name) { m_fcn_name = name; }\n\n    std::list<std::string> parent_fcn_names () const;\n\n    octave_user_code * user_code () const { return m_code; }\n\n    void set_user_code (octave_user_code *code) { m_code = code; }\n\n    void set_parent (const std::shared_ptr<symbol_scope_rep>& parent);\n\n    void set_primary_parent (const std::shared_ptr<symbol_scope_rep>& parent);\n\n    void cache_fcn_file_name (const std::string& name)\n    {\n      m_fcn_file_name = name;\n    }\n\n    std::string fcn_file_name () const { return m_fcn_file_name; }\n\n    void cache_dir_name (const std::string& name);\n\n    std::string dir_name () const { return m_dir_name; }\n\n    void mark_primary_fcn_scope () { m_is_primary_fcn_scope = true; }\n\n    bool is_primary_fcn_scope () const { return m_is_primary_fcn_scope; }\n\n    bool is_relative (const std::shared_ptr<symbol_scope_rep>& scope) const;\n\n    void mark_as_variable (const std::string& nm);\n    void mark_as_variables (const std::list<std::string>& lst);\n\n    bool is_variable (const std::string& nm) const;\n\n    void update_nest ();\n\n    bool look_nonlocal (const std::string& name, std::size_t offset,\n                        symbol_record& result);\n\n    octave_value dump_symbols_map () const;\n\n    const std::map<std::string, symbol_record>& symbols () const\n    {\n      return m_symbols;\n    }\n\n    std::map<std::string, symbol_record>& symbols ()\n    {\n      return m_symbols;\n    }\n\n    std::list<symbol_record> symbol_list () const;\n\n  private:\n\n    //! Name for this scope (usually the corresponding filename of the\n    //! function corresponding to the scope).\n\n    std::string m_name;\n\n    //! Map from symbol names to symbol info.\n\n    std::map<std::string, symbol_record> m_symbols;\n\n    //! Map from symbol names to subfunctions.\n\n    std::map<std::string, octave_value> m_subfunctions;\n\n    //! Map from data offset to persistent values in this scope.\n    std::map<std::size_t, octave_value> m_persistent_values;\n\n    //! The list of subfunctions (if any) in the order they appear in\n    //! the function file.\n\n    std::list<std::string> m_subfunction_names;\n\n    //! The associated user code (may be null).\n\n    octave_user_code *m_code;\n\n    //! Simple name of the function corresponding to this scope.\n\n    std::string m_fcn_name;\n\n    //! The file name associated with m_code.\n\n    std::string m_fcn_file_name;\n\n    //! The directory associated with m_code.\n\n    std::string m_dir_name;\n\n    //! Parent of nested function (may be null).\n\n    std::weak_ptr<symbol_scope_rep> m_parent;\n\n    //! Primary (top) parent of nested function (may be null).  Used\n    //! to determine whether two nested functions are related.\n\n    std::weak_ptr<symbol_scope_rep> m_primary_parent;\n\n    //! Child nested functions.\n\n    std::vector<symbol_scope> m_children;\n\n    //! If true, then this scope belongs to a nested function.\n\n    std::size_t m_nesting_depth;\n\n    //! If true then no variables can be added.\n\n    bool m_is_static;\n\n    //! If true, this is the scope of a primary function.\n    bool m_is_primary_fcn_scope;\n  };\n\npublic:\n\n  symbol_scope () = delete;\n\n  // Create a valid but possibly anonymous scope.  If NAME is empty, the\n  // scope is anonymous, but it is better to state that intent clearly\n  // by using the symbol_scope::anonymous function instead.\n  symbol_scope (const std::string& name)\n    : m_rep (new symbol_scope_rep (name))\n  { }\n\n  // FIXME: is there a way to make the following constructor private and\n  // not expose the symbol_scope_rep object in the interface (see the\n  // parent_scope, primary_parent_scope, and get_rep functions)?\n\n  // If NEW_REP is nullptr, the scope is invalid.  But if you wish to\n  // create an invalid scope, it is probably better to state that intent\n  // clearly by using the symbol_scope::invalid function instead.\n  symbol_scope (const std::shared_ptr<symbol_scope_rep> new_rep)\n    : m_rep (new_rep)\n  { }\n\n  symbol_scope (const symbol_scope&) = default;\n\n  symbol_scope& operator = (const symbol_scope&) = default;\n\n  ~symbol_scope () = default;\n\n  static symbol_scope invalid ()\n  {\n    return symbol_scope (std::shared_ptr<symbol_scope_rep> (nullptr));\n  }\n\n  static symbol_scope anonymous ()\n  {\n    return symbol_scope (\"\");\n  }\n\n  bool is_valid () const { return bool (m_rep); }\n\n  explicit operator bool () const { return is_valid (); }\n\n  std::size_t num_symbols () const\n  {\n    return m_rep ? m_rep->num_symbols () : 0;\n  }\n\n  symbol_record insert_local (const std::string& name)\n  {\n    return m_rep ? m_rep->insert_local (name) : symbol_record ();\n  }\n\n  void insert_symbol_record (symbol_record& sr)\n  {\n    if (m_rep)\n      m_rep->insert_symbol_record (sr);\n  }\n\n  bool is_nested () const\n  {\n    return m_rep ? m_rep->is_nested () : false;\n  }\n\n  bool is_parent () const\n  {\n    return m_rep ? m_rep->is_parent () : false;\n  }\n\n  void set_nesting_depth (std::size_t depth)\n  {\n    if (m_rep)\n      m_rep->set_nesting_depth (depth);\n  }\n\n  std::size_t nesting_depth () const\n  {\n    return m_rep ? m_rep->nesting_depth () : 0;\n  }\n\n  bool is_static () const\n  {\n    return m_rep ? m_rep->is_static () : false;\n  }\n\n  void mark_static ()\n  {\n    if (m_rep)\n      m_rep->mark_static ();\n  }\n\n  std::shared_ptr<symbol_scope_rep> parent_scope () const\n  {\n    return m_rep ? m_rep->parent_scope_rep () : nullptr;\n  }\n\n  std::shared_ptr<symbol_scope_rep> primary_parent_scope () const\n  {\n    return m_rep ? m_rep->primary_parent_scope_rep () : nullptr;\n  }\n\n  symbol_scope dup () const\n  {\n    return symbol_scope (m_rep ? m_rep->dup () : nullptr);\n  }\n\n  octave_value& persistent_varref (std::size_t data_offset)\n  {\n    static octave_value dummy_value;\n\n    return m_rep ? m_rep->persistent_varref (data_offset) : dummy_value;\n  }\n\n  octave_value persistent_varval (std::size_t data_offset) const\n  {\n    return m_rep ? m_rep->persistent_varval (data_offset) : octave_value ();\n  }\n\n  symbol_record find_symbol (const std::string& name)\n  {\n    return m_rep ? m_rep->find_symbol (name) : symbol_record ();\n  }\n\n  // Like find_symbol, but does not insert.\n  symbol_record lookup_symbol (const std::string& name) const\n  {\n    return m_rep ? m_rep->lookup_symbol (name) : symbol_record ();\n  }\n\n  symbol_record insert (const std::string& name)\n  {\n    return m_rep ? m_rep->insert (name) : symbol_record ();\n  }\n\n  void rename (const std::string& old_name, const std::string& new_name)\n  {\n    if (m_rep)\n      m_rep->rename (old_name, new_name);\n  }\n\n  void install_subfunction (const std::string& name,\n                            const octave_value& fval)\n  {\n    if (m_rep)\n      m_rep->install_subfunction (name, fval);\n  }\n\n  void install_nestfunction (const std::string& name,\n                             const octave_value& fval,\n                             const symbol_scope& fcn_scope)\n  {\n    if (m_rep)\n      m_rep->install_nestfunction (name, fval, fcn_scope);\n  }\n\n  octave_value find_subfunction (const std::string& name) const\n  {\n    return m_rep ? m_rep->find_subfunction (name) : octave_value ();\n  }\n\n  void lock_subfunctions ()\n  {\n    if (m_rep)\n      m_rep->lock_subfunctions ();\n  }\n\n  void unlock_subfunctions ()\n  {\n    if (m_rep)\n      m_rep->unlock_subfunctions ();\n  }\n\n  std::map<std::string, octave_value> subfunctions () const\n  {\n    return (m_rep\n            ? m_rep->subfunctions ()\n            : std::map<std::string, octave_value> ());\n  }\n\n  void erase_subfunctions ()\n  {\n    if (m_rep)\n      m_rep->erase_subfunctions ();\n  }\n\n  void mark_subfunctions_in_scope_as_private (const std::string& class_name)\n  {\n    if (m_rep)\n      m_rep->mark_subfunctions_in_scope_as_private (class_name);\n  }\n\n  bool has_subfunctions () const\n  {\n    return m_rep ? m_rep->has_subfunctions () : false;\n  }\n\n  void stash_subfunction_names (const std::list<std::string>& names)\n  {\n    if (m_rep)\n      m_rep->stash_subfunction_names (names);\n  }\n\n  std::list<std::string> subfunction_names () const\n  {\n    return m_rep ? m_rep->subfunction_names () : std::list<std::string> ();\n  }\n\n  // List of function handle objects.\n  std::list<octave_value> localfunctions () const;\n\n  octave_value dump () const\n  {\n    return m_rep ? m_rep->dump () : octave_value ();\n  }\n\n  std::string name () const\n  {\n    return m_rep ? m_rep->name () : \"\";\n  }\n\n  void cache_name (const std::string& name)\n  {\n    if (m_rep)\n      m_rep->cache_name (name);\n  }\n\n  std::string fcn_name () const\n  {\n    return m_rep ? m_rep->fcn_name () : \"\";\n  }\n\n  void cache_fcn_name (const std::string& name)\n  {\n    if (m_rep)\n      m_rep->cache_fcn_name (name);\n  }\n\n  std::list<std::string> parent_fcn_names () const\n  {\n    return m_rep ? m_rep->parent_fcn_names () : std::list<std::string> ();\n  }\n\n  octave_user_code * user_code () const\n  {\n    return m_rep ? m_rep->user_code () : nullptr;\n  }\n\n  void set_user_code (octave_user_code *code)\n  {\n    if (m_rep)\n      m_rep->set_user_code (code);\n  }\n\n  void set_parent (const symbol_scope& p)\n  {\n    if (m_rep)\n      m_rep->set_parent (p.get_rep ());\n  }\n\n  void set_primary_parent (const symbol_scope& p)\n  {\n    if (m_rep)\n      m_rep->set_primary_parent (p.get_rep ());\n  }\n\n  void cache_fcn_file_name (const std::string& name)\n  {\n    if (m_rep)\n      m_rep->cache_fcn_file_name (name);\n  }\n\n  void cache_dir_name (const std::string& name)\n  {\n    if (m_rep)\n      m_rep->cache_dir_name (name);\n  }\n\n  std::string fcn_file_name () const\n  {\n    return m_rep ? m_rep->fcn_file_name () : \"\";\n  }\n\n  std::string dir_name () const\n  {\n    return m_rep ? m_rep->dir_name () : \"\";\n  }\n\n  void mark_primary_fcn_scope ()\n  {\n    if (m_rep)\n      m_rep->mark_primary_fcn_scope ();\n  }\n\n  bool is_primary_fcn_scope () const\n  {\n    return m_rep ? m_rep->is_primary_fcn_scope () : false;\n  }\n\n  bool is_relative (const symbol_scope& scope) const\n  {\n    return m_rep ? m_rep->is_relative (scope.get_rep ()) : false;\n  }\n\n  void mark_as_variable (const std::string& nm)\n  {\n    if (m_rep)\n      m_rep->mark_as_variable (nm);\n  }\n\n  void mark_as_variables (const std::list<std::string>& lst)\n  {\n    if (m_rep)\n      m_rep->mark_as_variables (lst);\n  }\n\n  bool is_variable (const std::string& nm) const\n  {\n    return m_rep ? m_rep->is_variable (nm) : false;\n  }\n\n  void update_nest ()\n  {\n    if (m_rep)\n      m_rep->update_nest ();\n  }\n\n  bool look_nonlocal (const std::string& name, std::size_t offset,\n                      symbol_record& result)\n  {\n    return m_rep ? m_rep->look_nonlocal (name, offset, result) : false;\n  }\n\n  std::shared_ptr<symbol_scope_rep> get_rep () const\n  {\n    return m_rep;\n  }\n\n  friend bool operator == (const symbol_scope& a, const symbol_scope& b)\n  {\n    return a.m_rep == b.m_rep;\n  }\n\n  friend bool operator != (const symbol_scope& a, const symbol_scope& b)\n  {\n    return a.m_rep != b.m_rep;\n  }\n\n  const std::map<std::string, symbol_record>& symbols () const\n  {\n    static const std::map<std::string, symbol_record> empty_map;\n\n    return m_rep ? m_rep->symbols () : empty_map;\n  }\n\n  std::map<std::string, symbol_record>& symbols ()\n  {\n    static std::map<std::string, symbol_record> empty_map;\n\n    return m_rep ? m_rep->symbols () : empty_map;\n  }\n\n  std::list<symbol_record> symbol_list () const\n  {\n    static const std::list<symbol_record> empty_list;\n\n    return m_rep ? m_rep->symbol_list () : empty_list;\n  }\n\nprivate:\n\n  std::shared_ptr<symbol_scope_rep> m_rep;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/symtab.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n\n#include \"oct-time.h\"\n\n#include \"bp-table.h\"\n#include \"defun.h\"\n#include \"fcn-info.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ov-classdef.h\"\n#include \"ov-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"pt-pr-code.h\"\n#include \"symscope.h\"\n#include \"symtab.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nsymbol_table::symbol_table (interpreter& interp)\n  : m_interpreter (interp), m_fcn_table (), m_class_precedence_table (),\n    m_parent_map ()\n{\n  install_builtins ();\n}\n\nsymbol_scope\nsymbol_table::current_scope () const\n{\n  tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n  return tw.get_current_scope ();\n}\n\nbool\nsymbol_table::is_built_in_function_name (const std::string& name)\n{\n  octave_value val = find_built_in_function (name);\n\n  return val.is_defined ();\n}\n\noctave_value\nsymbol_table::find_scoped_function (const std::string& name,\n                                    const symbol_scope& search_scope)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  fcn_table_const_iterator p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    return p->second.find_scoped_function (search_scope);\n  else\n    {\n      fcn_info finfo (name);\n\n      octave_value fcn = finfo.find_scoped_function (search_scope);\n\n      if (fcn.is_defined ())\n        m_fcn_table[name] = finfo;\n\n      return fcn;\n    }\n}\n\noctave_value\nsymbol_table::find_private_function (const std::string& dir_name,\n                                     const std::string& name)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  fcn_table_const_iterator p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    return p->second.find_private_function (dir_name);\n  else\n    {\n      fcn_info finfo (name);\n\n      octave_value fcn = finfo.find_private_function (dir_name);\n\n      if (fcn.is_defined ())\n        m_fcn_table[name] = finfo;\n\n      return fcn;\n    }\n}\n\n// FIXME: this function only finds legacy class methods, not\n// classdef methods.\n\noctave_value\nsymbol_table::find_method (const std::string& name,\n                           const std::string& dispatch_type)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  fcn_table_const_iterator p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    return p->second.find_method (dispatch_type);\n  else\n    {\n      fcn_info finfo (name);\n\n      octave_value fcn = finfo.find_method (dispatch_type);\n\n      if (fcn.is_defined ())\n        m_fcn_table[name] = finfo;\n\n      return fcn;\n    }\n}\n\noctave_value\nsymbol_table::find_built_in_function (const std::string& name)\n{\n  fcn_table_const_iterator p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    return p->second.find_built_in_function ();\n  else\n    {\n      fcn_info finfo (name);\n\n      octave_value fcn = finfo.find_built_in_function ();\n\n      if (fcn.is_defined ())\n        m_fcn_table[name] = finfo;\n\n      return fcn;\n    }\n}\n\noctave_value\nsymbol_table::find_autoload (const std::string& name)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    return p->second.find_autoload ();\n  else\n    {\n      fcn_info finfo (name);\n\n      octave_value fcn = finfo.find_autoload ();\n\n      if (fcn.is_defined ())\n        m_fcn_table[name] = finfo;\n\n      return fcn;\n    }\n}\n\noctave_value\nsymbol_table::builtin_find (const std::string& name,\n                            const symbol_scope& search_scope_arg)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  fcn_table_iterator p = m_fcn_table.find (name);\n\n  symbol_scope search_scope\n    = (search_scope_arg ? search_scope_arg : current_scope ());\n\n  if (p != m_fcn_table.end ())\n    return p->second.builtin_find (search_scope);\n  else\n    {\n      fcn_info finfo (name);\n\n      octave_value fcn = finfo.builtin_find (search_scope);\n\n      if (fcn.is_defined ())\n        m_fcn_table[name] = finfo;\n\n      return fcn;\n    }\n\n  return octave_value ();\n}\n\noctave_value\nsymbol_table::fcn_table_find (const std::string& name,\n                              const octave_value_list& args,\n                              const symbol_scope& search_scope_arg)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  fcn_table_iterator p = m_fcn_table.find (name);\n\n  symbol_scope search_scope\n    = (search_scope_arg ? search_scope_arg : current_scope ());\n\n  if (p != m_fcn_table.end ())\n    return p->second.find (search_scope, args);\n  else\n    {\n      fcn_info finfo (name);\n\n      octave_value fcn = finfo.find (search_scope, args);\n\n      if (fcn.is_defined ())\n        m_fcn_table[name] = finfo;\n\n      return fcn;\n    }\n\n  return octave_value ();\n}\n\noctave_value\nsymbol_table::find_function (const std::string& name,\n                             const symbol_scope& search_scope_arg)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  if (name[0] == '@')\n    {\n      std::size_t pos = name.find_first_of ('/');\n\n      if (pos == std::string::npos)\n        return octave_value ();\n\n      std::string method = name.substr (pos+1);\n      std::string dispatch_type = name.substr (1, pos-1);\n\n      return find_method (method, dispatch_type);\n    }\n  else\n    {\n      symbol_scope search_scope\n        = (search_scope_arg ? search_scope_arg : current_scope ());\n\n      return find_function (name, ovl (), search_scope);\n    }\n}\n\noctave_value\nsymbol_table::find_function (const std::string& name,\n                             const octave_value_list& args,\n                             const symbol_scope& search_scope)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  return fcn_table_find (name, args, search_scope);\n}\n\noctave_value\nsymbol_table::find_user_function (const std::string& name)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    return p->second.find_user_function ();\n  else\n    {\n      fcn_info finfo (name);\n\n      octave_value fcn = finfo.find_user_function ();\n\n      if (fcn.is_defined ())\n        m_fcn_table[name] = finfo;\n\n      return fcn;\n    }\n}\n\noctave_value\nsymbol_table::find_cmdline_function (const std::string& name)\n{\n  if (name.empty ())\n    return octave_value ();\n\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    return p->second.find_cmdline_function ();\n  else\n    {\n      fcn_info finfo (name);\n\n      octave_value fcn = finfo.find_cmdline_function ();\n\n      if (fcn.is_defined ())\n        m_fcn_table[name] = finfo;\n\n      return fcn;\n    }\n}\n\nvoid\nsymbol_table::install_cmdline_function (const std::string& name,\n                                        const octave_value& fcn)\n{\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    {\n      fcn_info& finfo = p->second;\n\n      finfo.install_cmdline_function (fcn);\n    }\n  else\n    {\n      fcn_info finfo (name);\n\n      finfo.install_cmdline_function (fcn);\n\n      m_fcn_table[name] = finfo;\n    }\n}\n\n// Install local function FCN named NAME.  FILE_NAME is the name of\n// the file containing the local function.\n\nvoid\nsymbol_table::install_local_function (const std::string& name,\n                                      const octave_value& fcn,\n                                      const std::string& file_name)\n{\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    {\n      fcn_info& finfo = p->second;\n\n      finfo.install_local_function (fcn, file_name);\n    }\n  else\n    {\n      fcn_info finfo (name);\n\n      finfo.install_local_function (fcn, file_name);\n\n      m_fcn_table[name] = finfo;\n    }\n}\n\nvoid\nsymbol_table::install_user_function (const std::string& name,\n                                     const octave_value& fcn)\n{\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    {\n      fcn_info& finfo = p->second;\n\n      finfo.install_user_function (fcn);\n    }\n  else\n    {\n      fcn_info finfo (name);\n\n      finfo.install_user_function (fcn);\n\n      m_fcn_table[name] = finfo;\n    }\n}\n\n// FIXME: should we ensure that FCN really is a built-in function\n// object?\nvoid\nsymbol_table::install_built_in_function (const std::string& name,\n    const octave_value& fcn)\n{\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    {\n      fcn_info& finfo = p->second;\n\n      finfo.install_built_in_function (fcn);\n    }\n  else\n    {\n      fcn_info finfo (name);\n\n      finfo.install_built_in_function (fcn);\n\n      m_fcn_table[name] = finfo;\n    }\n}\n\n// This is written as two separate functions instead of a single\n// function with default values so that it will work properly with\n// unwind_protect.\n\nvoid\nsymbol_table::clear_functions (bool force)\n{\n  auto p = m_fcn_table.begin ();\n\n  while (p != m_fcn_table.end ())\n    (p++)->second.clear (force);\n}\n\nvoid\nsymbol_table::clear_function (const std::string& name)\n{\n  clear_user_function (name);\n}\n\nvoid\nsymbol_table::clear_function_pattern (const std::string& pat)\n{\n  symbol_match pattern (pat);\n\n  auto p = m_fcn_table.begin ();\n\n  while (p != m_fcn_table.end ())\n    {\n      if (pattern.match (p->first))\n        (p++)->second.clear_user_function ();\n      else\n        p++;\n    }\n}\n\nvoid\nsymbol_table::clear_function_regexp (const std::string& pat)\n{\n  regexp pattern (pat);\n\n  auto p = m_fcn_table.begin ();\n\n  while (p != m_fcn_table.end ())\n    {\n      if (pattern.is_match (p->first))\n        (p++)->second.clear_user_function ();\n      else\n        p++;\n    }\n}\n\nvoid\nsymbol_table::clear_user_function (const std::string& name)\n{\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    {\n      fcn_info& finfo = p->second;\n\n      finfo.clear_user_function ();\n    }\n  // FIXME: is this necessary, or even useful?\n  // else\n  //   error (\"clear: no such function '%s'\", name.c_str ());\n}\n\n// This clears oct and mex files, including autoloads.\nvoid\nsymbol_table::clear_dld_function (const std::string& name)\n{\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    {\n      fcn_info& finfo = p->second;\n\n      finfo.clear_autoload_function ();\n      finfo.clear_user_function ();\n    }\n}\n\nvoid\nsymbol_table::clear_mex_functions ()\n{\n  auto p = m_fcn_table.begin ();\n\n  while (p != m_fcn_table.end ())\n    (p++)->second.clear_mex_function ();\n}\n\n// Insert INF_CLASS in the set of class names that are considered\n// inferior to SUP_CLASS.  Return FALSE if INF_CLASS is currently\n// marked as superior to SUP_CLASS.\n\nbool\nsymbol_table::set_class_relationship (const std::string& sup_class,\n                                      const std::string& inf_class)\n{\n  if (is_superiorto (inf_class, sup_class))\n    return false;\n\n  // If sup_class doesn't have an entry in the precedence table,\n  // this will automatically create it, and associate to it a\n  // singleton set {inf_class} of inferior classes.\n  m_class_precedence_table[sup_class].insert (inf_class);\n\n  return true;\n}\n\n// Has class A been marked as superior to class B?  Also returns\n// TRUE if B has been marked as inferior to A, since we only keep\n// one table, and convert inferiorto information to a superiorto\n// relationship.  Two calls are required to determine whether there\n// is no relationship between two classes:\n//\n//  if (symbol_table::is_superiorto (a, b))\n//    // A is superior to B, or B has been marked inferior to A.\n//  else if (symbol_table::is_superiorto (b, a))\n//    // B is superior to A, or A has been marked inferior to B.\n//  else\n//    // No relation.\n\nbool\nsymbol_table::is_superiorto (const std::string& a, const std::string& b)\n{\n  class_precedence_table_const_iterator p = m_class_precedence_table.find (a);\n  // If a has no entry in the precedence table, return false\n  if (p == m_class_precedence_table.end ())\n    return false;\n\n  const std::set<std::string>& inferior_classes = p->second;\n  std::set<std::string>::const_iterator q = inferior_classes.find (b);\n  return (q != inferior_classes.end ());\n}\n\nvoid\nsymbol_table::alias_built_in_function (const std::string& alias,\n                                       const std::string& name)\n{\n  octave_value fcn = find_built_in_function (name);\n\n  if (fcn.is_defined ())\n    {\n      fcn_info finfo (alias);\n\n      finfo.install_built_in_function (fcn);\n\n      m_fcn_table[alias] = finfo;\n    }\n  else\n    panic (\"alias: '%s' is undefined\", name.c_str ());\n}\n\nvoid\nsymbol_table::install_built_in_dispatch (const std::string& name,\n    const std::string& klass)\n{\n  auto p = m_fcn_table.find (name);\n\n  if (p != m_fcn_table.end ())\n    {\n      fcn_info& finfo = p->second;\n\n      finfo.install_built_in_dispatch (klass);\n    }\n  else\n    error (\"install_built_in_dispatch: '%s' is undefined\", name.c_str ());\n}\n\nstd::list<std::string>\nsymbol_table::user_function_names ()\n{\n  std::list<std::string> retval;\n\n  for (const auto& nm_finfo : m_fcn_table)\n    {\n      if (nm_finfo.second.is_user_function_defined ())\n        retval.push_back (nm_finfo.first);\n    }\n\n  if (! retval.empty ())\n    retval.sort ();\n\n  return retval;\n}\n\nstd::list<std::string>\nsymbol_table::built_in_function_names ()\n{\n  std::list<std::string> retval;\n\n  for (const auto& nm_finfo : m_fcn_table)\n    {\n      octave_value fcn = nm_finfo.second.find_built_in_function ();\n\n      if (fcn.is_defined ())\n        retval.push_back (nm_finfo.first);\n    }\n\n  if (! retval.empty ())\n    retval.sort ();\n\n  return retval;\n}\n\nstd::list<std::string>\nsymbol_table::cmdline_function_names ()\n{\n  std::list<std::string> retval;\n\n  for (const auto& nm_finfo : m_fcn_table)\n    {\n      octave_value fcn = nm_finfo.second.find_cmdline_function ();\n\n      if (fcn.is_defined ())\n        retval.push_back (nm_finfo.first);\n    }\n\n  if (! retval.empty ())\n    retval.sort ();\n\n  return retval;\n}\n\ntemplate <template <typename, typename...> class C, typename V,\n          typename... A>\nstatic octave_value\ndump_container_map (const std::map<std::string, C<V, A...>>& container_map)\n{\n  if (container_map.empty ())\n    return octave_value (Matrix ());\n\n  std::map<std::string, octave_value> info_map;\n\n  for (const auto& nm_container : container_map)\n    {\n      std::string nm = nm_container.first;\n      const C<V, A...>& container = nm_container.second;\n      info_map[nm] = Cell (container);\n    }\n\n  return octave_value (info_map);\n}\n\noctave_value\nsymbol_table::dump () const\n{\n  std::map<std::string, octave_value> m\n  = {{ \"function_info\", dump_fcn_table_map () },\n    { \"precedence_table\", dump_container_map (m_class_precedence_table) },\n    { \"parent_classes\", dump_container_map (m_parent_map) }\n  };\n\n  return octave_value (m);\n}\n\nvoid\nsymbol_table::add_to_parent_map (const std::string& classname,\n                                 const std::list<std::string>& parent_list)\n{\n  m_parent_map[classname] = parent_list;\n}\n\nstd::list<std::string>\nsymbol_table::parent_classes (const std::string& dispatch_type)\n{\n  std::list<std::string> retval;\n\n  const_parent_map_iterator it = m_parent_map.find (dispatch_type);\n\n  if (it != m_parent_map.end ())\n    retval = it->second;\n\n  for (const auto& nm : retval)\n    {\n      // Search for parents of parents and append them to the list.\n\n      // FIXME: should we worry about a circular inheritance graph?\n\n      std::list<std::string> parents = parent_classes (nm);\n\n      if (! parents.empty ())\n        retval.insert (retval.end (), parents.begin (), parents.end ());\n    }\n\n  return retval;\n}\n\nvoid\nsymbol_table::cleanup ()\n{\n  clear_functions ();\n\n  m_fcn_table.clear ();\n  m_class_precedence_table.clear ();\n  m_parent_map.clear ();\n}\n\nfcn_info *\nsymbol_table::get_fcn_info (const std::string& name)\n{\n  auto p = m_fcn_table.find (name);\n  return p != m_fcn_table.end () ? &p->second : nullptr;\n}\n\noctave_value\nsymbol_table::dump_fcn_table_map () const\n{\n  if (m_fcn_table.empty ())\n    return octave_value (Matrix ());\n\n  std::map<std::string, octave_value> info_map;\n\n  for (const auto& nm_finfo : m_fcn_table)\n    {\n      std::string nm = nm_finfo.first;\n      const fcn_info& finfo = nm_finfo.second;\n      info_map[nm] = finfo.dump ();\n    }\n\n  return octave_value (info_map);\n}\n\nDEFMETHOD (__dump_symtab_info__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{S} =} __dump_symtab_info__ ()\n@deftypefnx {} {@var{S} =} __dump_symtab_info__ (@var{function})\nReturn a structure with information from the symbol table.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  if (nargin == 0)\n    return symtab.dump ();\n  else\n    {\n      std::string fname = args(0).xstring_value (\"__dump_symtab_info__: argument must be a function name\");\n\n      fcn_info *finfo = symtab.get_fcn_info (fname);\n\n      if (finfo)\n        return finfo->dump ();\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (__get_cmdline_fcn_txt__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{str} =} __get_cmdline_fcn_txt__ (@var{name})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"__get_cmdline_fcn_txt__: first argument must be function name\");\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value ov = symtab.find_cmdline_function (name);\n\n  octave_user_function *f = ov.user_function_value ();\n\n  octave_value_list retval;\n\n  if (f)\n    {\n      std::ostringstream buf;\n\n      tree_print_code tpc (buf);\n\n      f->accept (tpc);\n\n      retval = ovl (buf.str ());\n    }\n\n  return retval;\n}\n\n// FIXME: should we have functions like this in Octave?\n//\n// DEFMETHOD (set_variable, interp, args, , \"set_variable (NAME, VALUE)\")\n// {\n//   if (args.length () != 2)\n//     print_usage ();\n//\n//   std::string name = args(0).xstring_value (\"set_variable: variable NAME must be a string\");\n//\n//   symbol_table& symtab = interp.get_symbol_table ();\n//\n//   symtab.assign (name, args(1));\n//\n//   return ovl ();\n// }\n//\n// DEFMETHOD (variable_value, interp, args, , \"VALUE = variable_value (NAME)\")\n// {\n//   if (args.length () != 1)\n//     print_usage ();\n//\n//   octave_value retval;\n//\n//   std::string name = args(0).xstring_value (\"variable_value: variable NAME must be a string\");\n//\n//   symbol_table& symtab = interp.get_symbol_table ();\n//\n//   retval = symtab.varval (name);\n//\n//   if (retval.is_undefined ())\n//     error (\"variable_value: '%s' is not a variable in the current scope\",\n//            name.c_str ());\n//\n//   return retval;\n// }\n\n/*\nbug #34497: 'clear -f' does not work for command line functions\n\nThis test relies on bar being a core function that is implemented in an m-file.\nIf the first assert fails, this is no longer the case and the tests need to be\nupdated to use some other function.\n\n%!assert <34497> (! strcmp (which (\"bar\"), \"\"))\n\n%!function x = bar ()\n%!  x = 5;\n%!endfunction\n%!test\n%! assert (bar == 5);\n%! assert (strcmp (which (\"bar\"), \"command-line function\"));\n%! clear -f bar;\n%! assert (! strcmp (which (\"bar\"), \"\"));\n\n%!function x = bar ()\n%!  x = 5;\n%!endfunction\n%!test\n%! assert (bar == 5);\n%! assert (strcmp (which (\"bar\"), \"command-line function\"));\n%! clear bar;\n%! assert (! strcmp (which (\"bar\"), \"\"));\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/symtab.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_symtab_h)\n#define octave_symtab_h 1\n\n#include \"octave-config.h\"\n\n#include <deque>\n#include <list>\n#include <map>\n#include <set>\n#include <string>\n\n#include \"glob-match.h\"\n#include \"oct-refcount.h\"\n#include \"oct-regexp.h\"\n\nclass tree_argument_list;\nclass octave_user_function;\n\n#include \"fcn-info.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"symscope.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass OCTINTERP_API symbol_table\n{\npublic:\n\n  // Make symbol_table::scope and symbol_table::fcn_info valid type names.\n  typedef octave::symbol_scope scope;\n  typedef octave::fcn_info fcn_info;\n\n  symbol_table (interpreter& interp);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (symbol_table)\n\n  ~symbol_table () = default;\n\n  symbol_scope current_scope () const;\n\n  bool is_built_in_function_name (const std::string& name);\n\n  octave_value find_scoped_function (const std::string& name,\n                                     const symbol_scope& search_scope);\n\n  octave_value find_private_function (const std::string& dir_name,\n                                      const std::string& name);\n\n  // FIXME: this function only finds legacy class methods, not\n  // classdef methods.\n  octave_value find_method (const std::string& name,\n                            const std::string& dispatch_type);\n\n  octave_value find_built_in_function (const std::string& name);\n\n  octave_value find_autoload (const std::string& name);\n\n  octave_value\n  builtin_find (const std::string& name,\n                const symbol_scope& search_scope = symbol_scope::invalid ());\n\n  octave_value\n  fcn_table_find (const std::string& name,\n                  const octave_value_list& args = ovl (),\n                  const symbol_scope& search_scope = symbol_scope::invalid ());\n\n  // If NAME is of the form @CLASS/FUNCTION, call\n  //\n  //   find_method (FUNCTION, CLASS)\n  //\n  // otherwise call\n  //\n  //   find_function (NAME, ovl ())\n\n  octave_value\n  find_function (const std::string& name,\n                 const symbol_scope& search_scope = symbol_scope::invalid ());\n\n  // NAME should just be function name; dispatch type determined\n  // from types of ARGS.\n\n  octave_value\n  find_function (const std::string& name,\n                 const octave_value_list& args,\n                 const symbol_scope& search_scope = symbol_scope::invalid ());\n\n  octave_value find_user_function (const std::string& name);\n\n  octave_value find_cmdline_function (const std::string& name);\n\n  void install_cmdline_function (const std::string& name,\n                                 const octave_value& fcn);\n\n  // Install local function FCN named NAME.  FILE_NAME is the name of\n  // the file containing the local function.\n\n  void install_local_function (const std::string& name,\n                               const octave_value& fcn,\n                               const std::string& file_name);\n\n  void install_user_function (const std::string& name,\n                              const octave_value& fcn);\n\n  // FIXME: should we ensure that FCN really is a built-in function\n  // object?\n  void install_built_in_function (const std::string& name,\n                                  const octave_value& fcn);\n\n  // This is written as two separate functions instead of a single\n  // function with default values so that it will work properly with\n  // unwind_protect.\n\n  void clear_functions (bool force = false);\n\n  void clear_function (const std::string& name);\n\n  void clear_function_pattern (const std::string& pat);\n\n  void clear_function_regexp (const std::string& pat);\n\n  void clear_user_function (const std::string& name);\n\n  // This clears oct and mex files, including autoloads.\n  void clear_dld_function (const std::string& name);\n\n  void clear_mex_functions ();\n\n  bool set_class_relationship (const std::string& sup_class,\n                               const std::string& inf_class);\n\n  bool is_superiorto (const std::string& a, const std::string& b);\n\n  void alias_built_in_function (const std::string& alias,\n                                const std::string& name);\n\n  void install_built_in_dispatch (const std::string& name,\n                                  const std::string& klass);\n\n  std::list<std::string> user_function_names ();\n\n  std::list<std::string> built_in_function_names ();\n\n  std::list<std::string> cmdline_function_names ();\n\n  octave_value dump () const;\n\n  void add_to_parent_map (const std::string& classname,\n                          const std::list<std::string>& parent_list);\n\n  std::list<std::string> parent_classes (const std::string& dispatch_type);\n\n  void cleanup ();\n\n  fcn_info * get_fcn_info (const std::string& name);\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  typedef std::map<std::string, octave_value>::const_iterator\n    global_symbols_const_iterator;\n  typedef std::map<std::string, octave_value>::iterator\n    global_symbols_iterator;\n\n  typedef std::map<std::string, fcn_info>::const_iterator\n    fcn_table_const_iterator;\n  typedef std::map<std::string, fcn_info>::iterator\n    fcn_table_iterator;\n\n  // Map from function names to function info (private\n  // functions, class constructors, class methods, etc.)\n  // Note that subfunctions are defined in the scope that contains\n  // them.\n  std::map<std::string, fcn_info> m_fcn_table;\n\n  // Map from class names to set of classes that have lower\n  // precedence.\n  std::map<std::string, std::set<std::string>> m_class_precedence_table;\n\n  typedef std::map<std::string, std::set<std::string>>::const_iterator\n      class_precedence_table_const_iterator;\n  typedef std::map<std::string, std::set<std::string>>::iterator\n      class_precedence_table_iterator;\n\n  // Map from class names to parent class names.\n  std::map<std::string, std::list<std::string>> m_parent_map;\n\n  typedef std::map<std::string, std::list<std::string>>::const_iterator\n      const_parent_map_iterator;\n  typedef std::map<std::string, std::list<std::string>>::iterator\n      parent_map_iterator;\n\n  octave_value dump_fcn_table_map () const;\n\n  // This function is generated automatically by mk-builtins.pl.\n  void install_builtins ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/sysdep.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n#include <string>\n\n#if defined (HAVE_TERMIOS_H)\n#  include <termios.h>\n#elif defined (HAVE_TERMIO_H)\n#  include <termio.h>\n#elif defined (HAVE_SGTTY_H)\n#  include <sgtty.h>\n#endif\n\n#if defined (HAVE_CONIO_H)\n#  include <conio.h>\n#endif\n\n#if defined (HAVE_SYS_IOCTL_H)\n#  include <sys/ioctl.h>\n#endif\n\n#if defined (HAVE_FLOATINGPOINT_H)\n#  include <floatingpoint.h>\n#endif\n\n#if defined (HAVE_IEEEFP_H)\n#  include <ieeefp.h>\n#endif\n\n#if defined (HAVE_OMP_H)\n#  include <omp.h>\n#endif\n\n#include \"cmd-edit.h\"\n#include \"file-ops.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-env.h\"\n#include \"oct-sysinfo.h\"\n#include \"uniconv-wrappers.h\"\n#include \"unistd-wrappers.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"octave.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"sighandlers.h\"\n#include \"sysdep.h\"\n#include \"interpreter.h\"\n#include \"utils.h\"\n#include \"file-stat.h\"\n\n#if ! defined (STDIN_FILENO)\n#  define STDIN_FILENO 1\n#endif\n\n#if defined (__MINGW32__) || defined (_MSC_VER)\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <fcntl.h>\n#include <io.h>\n#include <tlhelp32.h>\n#include <psapi.h>\n#include <shellapi.h>\n#include <shobjidl.h>\n\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (__386BSD__) || defined (__FreeBSD__) || defined (__NetBSD__)\n\nstatic void\nBSD_init ()\n{\n#  if defined (HAVE_FLOATINGPOINT_H)\n  // Disable trapping on common exceptions.\n#    if ! defined (FP_X_DNML)\n#      define FP_X_DNML 0\n#    endif\n  fpsetmask (~(FP_X_OFL|FP_X_INV|FP_X_DZ|FP_X_DNML|FP_X_UFL|FP_X_IMP));\n#  endif\n}\n\n#endif\n\n#if defined (__MINGW32__) || defined (_MSC_VER)\n\nstatic void\nw32_set_octave_home ()\n{\n  std::string bin_dir;\n\n  HANDLE h = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE\n#if defined (TH32CS_SNAPMODULE32)\n                                       | TH32CS_SNAPMODULE32\n#endif\n                                       , 0);\n\n  if (h != INVALID_HANDLE_VALUE)\n    {\n      MODULEENTRY32W mod_info;\n\n      ZeroMemory (&mod_info, sizeof (mod_info));\n      mod_info.dwSize = sizeof (mod_info);\n\n      if (Module32FirstW (h, &mod_info))\n        {\n          do\n            {\n              std::string mod_name (sys::u8_from_wstring (mod_info.szModule));\n\n              if (mod_name.find (\"octinterp\") != std::string::npos)\n                {\n                  bin_dir = sys::u8_from_wstring (mod_info.szExePath);\n                  if (! bin_dir.empty () && bin_dir.back () != '\\\\')\n                    bin_dir.push_back ('\\\\');\n                  break;\n                }\n            }\n          while (Module32NextW (h, &mod_info));\n        }\n\n      CloseHandle (h);\n    }\n\n  if (! bin_dir.empty ())\n    {\n      std::size_t pos = bin_dir.rfind (R\"(\\bin\\)\");\n\n      if (pos != std::string::npos)\n        sys::env::putenv (\"OCTAVE_HOME\", bin_dir.substr (0, pos));\n    }\n}\n\nstatic void\nw32_init ()\n{\n  w32_set_octave_home ();\n\n  command_editor::prefer_env_winsize (true);\n}\n\n#endif\n\nvoid\nset_application_id ()\n{\n#if defined (__MINGW32__) || defined (_MSC_VER)\n\n  SetCurrentProcessExplicitAppUserModelID (L\"gnu.octave.\" VERSION);\n\n#endif\n}\n\nDEFUN (__open_with_system_app__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __open_with_system_app__ (@var{file})\nReturn 1 on successful system call and 0 otherwise.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string file = args(0).xstring_value (\"__open_with_system_app__: argument must be a filename\");\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::wstring wfile = sys::u8_to_wstring (file);\n  HINSTANCE status = ShellExecuteW (0, 0, wfile.c_str (), 0, 0, SW_SHOWNORMAL);\n\n  // ShellExecute returns a value greater than 32 if successful.\n  return octave_value (reinterpret_cast<std::ptrdiff_t> (status) > 32);\n#else\n  // Quote file path\n  file = '\"' + file + '\"';\n\n#  if defined (__APPLE__)\n#    define FSYSTEM_OPEN_STR \"open \"\n#  else\n#    define FSYSTEM_OPEN_STR \"xdg-open \"\n#  endif\n  octave_value_list tmp\n    = Fsystem (ovl (FSYSTEM_OPEN_STR + file + \" 2> /dev/null\",\n                    false, \"async\"),\n               1);\n#  undef FSYSTEM_OPEN_STR\n\n  // Asynchronous Fsystem calls return the new child process identifier,\n  // which must be greater than 1 if successful.\n  return octave_value (tmp(0).double_value () > 1);\n#endif\n}\n\nDEFUN (__is_elevated_process__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{retval} =} __is_elevated_process__ ()\nCheck if current process has elevated rights.\n\nOn Windows, return true if the current process has elevated right.  Otherwise,\nreturn false.\nOn non-Windows platforms, this function fails with an error.\n@end deftypefn */)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  if (args.length () != 0)\n    print_usage ();\n\n  bool retval = false;\n  HANDLE h_token = nullptr;\n\n  if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &h_token))\n    {\n      TOKEN_ELEVATION elevation;\n      DWORD return_length = sizeof (TOKEN_ELEVATION);\n      if (GetTokenInformation (h_token, TokenElevation, &elevation,\n                               sizeof (elevation), &return_length))\n        retval = elevation.TokenIsElevated;\n    }\n\n  if (h_token)\n    CloseHandle (h_token);\n\n  return ovl (retval);\n\n#else\n  octave_unused_parameter (args);\n  error (\"__is_elevated_process__: \"\n         \"Function is only supported on Windows platforms.\");\n#endif\n}\n\nDEFUN (__wmemory__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{proc}, @var{sys}] =} __wmemory__ ()\nReturn memory information on Windows.\n\nOn non-Windows platforms, this function fails with an error.\n@end deftypefn */)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  if (args.length () != 0)\n    print_usage ();\n\n  // Get memory usage of the current process\n  octave_scalar_map proc_struct;\n\n  HANDLE h_proc = GetCurrentProcess ();\n  if (h_proc == nullptr)\n    error (\"__wmemory__: Couldn't open handle to own process\");\n\n  PROCESS_MEMORY_COUNTERS proc_mem_count;\n  if (GetProcessMemoryInfo (h_proc, &proc_mem_count, sizeof (proc_mem_count)))\n    {\n      proc_struct.setfield (\"PageFaultCount\",\n                            proc_mem_count.PageFaultCount);\n      proc_struct.setfield (\"PeakWorkingSetSize\",\n                            proc_mem_count.PeakWorkingSetSize);\n      proc_struct.setfield (\"WorkingSetSize\",\n                            proc_mem_count.WorkingSetSize);\n      proc_struct.setfield (\"QuotaPeakPagedPoolUsage\",\n                            proc_mem_count.QuotaPeakPagedPoolUsage);\n      proc_struct.setfield (\"QuotaPagedPoolUsage\",\n                            proc_mem_count.QuotaPagedPoolUsage);\n      proc_struct.setfield (\"QuotaPeakNonPagedPoolUsage\",\n                            proc_mem_count.QuotaPeakNonPagedPoolUsage);\n      proc_struct.setfield (\"QuotaNonPagedPoolUsage\",\n                            proc_mem_count.QuotaNonPagedPoolUsage);\n      proc_struct.setfield (\"PagefileUsage\",\n                            proc_mem_count.PagefileUsage);\n      proc_struct.setfield (\"PeakPagefileUsage\",\n                            proc_mem_count.PeakPagefileUsage);\n    }\n  else\n    {\n      proc_struct.setfield (\"PageFaultCount\", 0);\n      proc_struct.setfield (\"PeakWorkingSetSize\", 0);\n      proc_struct.setfield (\"WorkingSetSize\", 0);\n      proc_struct.setfield (\"QuotaPeakPagedPoolUsage\", 0);\n      proc_struct.setfield (\"QuotaPagedPoolUsage\", 0);\n      proc_struct.setfield (\"QuotaPeakNonPagedPoolUsage\", 0);\n      proc_struct.setfield (\"QuotaNonPagedPoolUsage\", 0);\n      proc_struct.setfield (\"PagefileUsage\", 0);\n      proc_struct.setfield (\"PeakPagefileUsage\", 0);\n    }\n\n  CloseHandle (h_proc);\n\n  // Get system memory usage\n  octave_scalar_map sys_struct;\n\n  MEMORYSTATUSEX mem_stat;\n\n  mem_stat.dwLength = sizeof (mem_stat);\n\n  if (GlobalMemoryStatusEx (&mem_stat))\n    {\n      sys_struct.setfield (\"MemoryLoad\", mem_stat.dwMemoryLoad);\n      sys_struct.setfield (\"TotalPhys\", mem_stat.ullTotalPhys);\n      sys_struct.setfield (\"AvailPhys\", mem_stat.ullAvailPhys);\n      sys_struct.setfield (\"TotalPageFile\", mem_stat.ullTotalPageFile);\n      sys_struct.setfield (\"AvailPageFile\", mem_stat.ullAvailPageFile);\n      sys_struct.setfield (\"TotalVirtual\", mem_stat.ullTotalVirtual);\n      sys_struct.setfield (\"AvailVirtual\", mem_stat.ullAvailVirtual);\n      sys_struct.setfield (\"AvailExtendedVirtual\",\n                           mem_stat.ullAvailExtendedVirtual);\n    }\n  else\n    {\n      sys_struct.setfield (\"MemoryLoad\", 0);\n      sys_struct.setfield (\"TotalPhys\", 0);\n      sys_struct.setfield (\"AvailPhys\", 0);\n      sys_struct.setfield (\"TotalPageFile\", 0);\n      sys_struct.setfield (\"AvailPageFile\", 0);\n      sys_struct.setfield (\"TotalVirtual\", 0);\n      sys_struct.setfield (\"AvailVirtual\", 0);\n      sys_struct.setfield (\"AvailExtendedVirtual\", 0);\n    }\n\n  return ovl (proc_struct, sys_struct);\n\n#else\n  octave_unused_parameter (args);\n  error (\"__wmemory__: Function is only supported on Windows platforms\");\n#endif\n}\n\n#if defined (__MINGW32__)\n\nstatic void\nMINGW_init ()\n{\n  w32_init ();\n}\n\n#endif\n\n#if defined (_MSC_VER)\n\nstatic void\nMSVC_init ()\n{\n  w32_init ();\n}\n\n#endif\n\n// Return TRUE if NAME refers to an existing drive letter or UNC share\n\nbool\ndrive_or_unc_share (const std::string& name)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::size_t len = name.length ();\n  bool candidate = false;\n  if (len > 1 && isalpha(name[0]) && name[1]==':'\n      && (len == 2 || (len == 3 && name[2] == '\\\\')))\n    candidate = true;\n  if (len > 4 && name[0] == '\\\\' && name[1] == '\\\\')\n    {\n      // It starts with two slashes.  Find the next slash.\n      std::size_t next_slash = name.find ('\\\\', 3);\n      if (next_slash != std::string::npos && len > next_slash+1)\n        {\n          // Check if it ends with the share\n          std::size_t last_slash = name.find ('\\\\', next_slash+1);\n          if (last_slash == std::string::npos\n              || (len > next_slash+2 && last_slash == len-1))\n            candidate = true;\n        }\n    }\n\n  if (candidate)\n    {\n      // Open a handle to the file.\n      std::wstring wname = sys::u8_to_wstring (name);\n      HANDLE h\n        = CreateFileW (wname.c_str (), FILE_READ_ATTRIBUTES,\n                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,\n                       nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,\n                       nullptr);\n      if (h != INVALID_HANDLE_VALUE)\n        {\n          CloseHandle (h);\n          return true;\n        }\n    }\n\n  return false;\n\n#else\n\n  octave_unused_parameter (name);\n\n  return false;\n\n#endif\n}\n\nvoid\nsysdep_init ()\n{\n  static bool initialized = false;\n\n  if (initialized)\n    return;\n\n  // Use a function from libgomp to force loading of OpenMP library.\n  // Otherwise, a dynamically loaded library making use of OpenMP such\n  // as GraphicsMagick will segfault on exit (bug #41699).\n#if defined (HAVE_OMP_GET_NUM_THREADS)\n  omp_get_num_threads ();\n#endif\n\n#if defined (__386BSD__) || defined (__FreeBSD__) || defined (__NetBSD__)\n  BSD_init ();\n#elif defined (__MINGW32__)\n  MINGW_init ();\n#elif defined (_MSC_VER)\n  MSVC_init ();\n#endif\n\n  initialized = true;\n}\n\nvoid\nsysdep_cleanup ()\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  // Let us fail immediately without displaying any dialog.\n  SetProcessShutdownParameters (0x280, SHUTDOWN_NORETRY);\n#endif\n}\n\n// Set terminal in raw mode.  From less-177.\n//\n// Change terminal to \"raw mode\", or restore to \"normal\" mode.\n// \"Raw mode\" means\n//      1. An outstanding read will complete on receipt of a single keystroke.\n//      2. Input is not echoed.\n//      3. On output, \\n is mapped to \\r\\n.\n//      4. \\t is NOT expanded into spaces.\n//      5. Signal-causing characters such as ctrl-C (interrupt),\n//         etc. are NOT disabled.\n// It doesn't matter whether an input \\n is mapped to \\r, or vice versa.\n\nvoid\nraw_mode (bool on, bool wait)\n{\n  static bool curr_on = false;\n\n  int tty_fd = STDIN_FILENO;\n  if (! octave_isatty_wrapper (tty_fd))\n    {\n      interpreter& interp = __get_interpreter__ ();\n\n      if (interp.interactive () && ! application::forced_interactive ())\n        error (\"stdin is not a tty!\");\n    }\n\n  if (on == curr_on)\n    return;\n\n#if defined (HAVE_TERMIOS_H)\n  {\n    struct termios s;\n    static struct termios save_term;\n\n    if (on)\n      {\n        // Get terminal modes.\n\n        tcgetattr (tty_fd, &s);\n\n        // Save modes and set certain variables dependent on modes.\n\n        save_term = s;\n        //      ospeed = s.c_cflag & CBAUD;\n        //      erase_char = s.c_cc[VERASE];\n        //      kill_char = s.c_cc[VKILL];\n\n        // Set the modes to the way we want them.\n\n        s.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);\n        s.c_oflag |=  (OPOST | ONLCR);\n#if defined (OCRNL)\n        s.c_oflag &= ~(OCRNL);\n#endif\n#if defined (ONOCR)\n        s.c_oflag &= ~(ONOCR);\n#endif\n#if defined (ONLRET)\n        s.c_oflag &= ~(ONLRET);\n#endif\n        s.c_cc[VMIN] = (wait ? 1 : 0);\n        s.c_cc[VTIME] = 0;\n      }\n    else\n      {\n        // Restore saved modes.\n\n        s = save_term;\n      }\n\n    tcsetattr (tty_fd, wait ? TCSAFLUSH : TCSADRAIN, &s);\n  }\n#elif defined (HAVE_TERMIO_H)\n  {\n    struct termio s;\n    static struct termio save_term;\n\n    if (on)\n      {\n        // Get terminal modes.\n\n        ioctl (tty_fd, TCGETA, &s);\n\n        // Save modes and set certain variables dependent on modes.\n\n        save_term = s;\n        //      ospeed = s.c_cflag & CBAUD;\n        //      erase_char = s.c_cc[VERASE];\n        //      kill_char = s.c_cc[VKILL];\n\n        // Set the modes to the way we want them.\n\n        s.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);\n        s.c_oflag |=  (OPOST | ONLCR);\n#if defined (OCRNL)\n        s.c_oflag &= ~(OCRNL);\n#endif\n#if defined (ONOCR)\n        s.c_oflag &= ~(ONOCR);\n#endif\n#if defined (ONLRET)\n        s.c_oflag &= ~(ONLRET);\n#endif\n        s.c_cc[VMIN] = (wait ? 1 : 0);\n      }\n    else\n      {\n        // Restore saved modes.\n\n        s = save_term;\n      }\n\n    ioctl (tty_fd, TCSETAW, &s);\n  }\n#elif defined (HAVE_SGTTY_H)\n  {\n    octave_unused_parameter (wait);\n\n    struct sgttyb s;\n    static struct sgttyb save_term;\n\n    if (on)\n      {\n        // Get terminal modes.\n\n        ioctl (tty_fd, TIOCGETP, &s);\n\n        // Save modes and set certain variables dependent on modes.\n\n        save_term = s;\n        //      ospeed = s.sg_ospeed;\n        //      erase_char = s.sg_erase;\n        //      kill_char = s.sg_kill;\n\n        // Set the modes to the way we want them.\n\n        s.sg_flags |= CBREAK;\n        s.sg_flags &= ~(ECHO);\n      }\n    else\n      {\n        // Restore saved modes.\n\n        s = save_term;\n      }\n\n    ioctl (tty_fd, TIOCSETN, &s);\n  }\n#else\n\n  octave_unused_parameter (wait);\n\n  warn_disabled_feature (\"\", \"raw mode console I/O\");\n\n  // Make sure the current mode doesn't toggle.\n  on = curr_on;\n#endif\n\n  curr_on = on;\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n// map that stores process handle for each pipe file pointer\nstd::map<FILE *, HANDLE> pipe_handle_map;\n#endif\n\nFILE *\npopen (const char *command, const char *mode)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  if (application::is_gui_running ())\n    {\n      // On Windows (non-Cygwin), child processes need to be created with a new\n      // console to avoid desynchronization of the console that is used by the\n      // command window widget of the GUI.\n\n      bool is_write = (mode[0] == 'w');\n      // use binary mode on Windows if unspecified\n      bool is_binary = ((strlen (mode) == 1) || mode[1] == 'b');\n\n      HANDLE h_read;\n      HANDLE h_write;\n      SECURITY_ATTRIBUTES sa {};\n      sa.nLength = sizeof (sa);\n      sa.bInheritHandle = TRUE;  // child can inherit\n\n      if (! CreatePipe (&h_read, &h_write, &sa, 0))\n        return nullptr;\n\n      HANDLE parent_end = is_write ? h_write : h_read;\n      HANDLE child_end = is_write ? h_read : h_write;\n\n      // prevent child from inheriting the wrong end\n      SetHandleInformation (parent_end, HANDLE_FLAG_INHERIT, 0);\n\n      // spawn child with one end of pipe as stdin or stdout/stderr\n      STARTUPINFOW si {};\n      si.cb = sizeof (si);\n      si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;\n      si.wShowWindow = SW_HIDE;  // avoid flashing black window\n      if (is_write)\n        si.hStdInput = child_end;\n      else\n        {\n          si.hStdOutput = child_end;\n          si.hStdError = child_end;\n        }\n      PROCESS_INFORMATION pi {};\n\n      std::wstring wcommand {L\"cmd.exe /C \\\"\"};\n      wcommand.append (sys::u8_to_wstring (command));\n      wcommand.push_back (L'\"');\n      BOOL ok = CreateProcessW (nullptr, &wcommand[0], nullptr, nullptr, TRUE,\n                                CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi);\n      if (! ok)\n        {\n          CloseHandle (h_read);\n          CloseHandle (h_write);\n          return nullptr;\n        }\n\n      CloseHandle (pi.hThread);\n\n      // close child's end of pipe\n      CloseHandle (child_end);\n\n      // convert pipe read or write handle to FILE *\n      int flags = (is_write ? _O_WRONLY : _O_RDONLY);\n      if (is_binary)\n        flags |= _O_BINARY;\n\n      int fd = _open_osfhandle (reinterpret_cast<intptr_t> (parent_end), flags);\n\n      if (fd == -1)\n        {\n          CloseHandle (parent_end);\n          CloseHandle (pi.hProcess);\n          return nullptr;\n        }\n\n      FILE *f = _fdopen (fd, mode);\n      if (! f)\n        {\n          _close (fd);  // handle to parent end of pipe is owned by OS file handle\n          CloseHandle (pi.hProcess);\n          return nullptr;\n        }\n\n      pipe_handle_map[f] = pi.hProcess;\n\n      return f;\n    }\n  else\n    {\n      std::wstring wcommand {L\"\\\"\"};\n      wcommand.append (sys::u8_to_wstring (command));\n      wcommand.push_back (L'\"');\n      std::wstring wmode = sys::u8_to_wstring (mode);\n\n      // Use binary mode on Windows if unspecified\n      if (wmode.length () < 2)\n        wmode += L'b';\n\n      return _wpopen (wcommand.c_str (), wmode.c_str ());\n    }\n\n#else\n  return ::popen (command, mode);\n#endif\n}\n\nint\npclose (FILE *f)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  if (application::is_gui_running ())\n    {\n      auto it = pipe_handle_map.find (f);\n      if (it != pipe_handle_map.end ())\n        {\n          HANDLE h_process = it->second;\n          pipe_handle_map.erase (it);\n\n          // close FILE pointer before waiting for child process\n          ::fclose (f);\n\n          // wait for child to finish\n          WaitForSingleObject (h_process, INFINITE);\n          DWORD exitcode;\n          if (! GetExitCodeProcess (h_process, &exitcode))\n            exitcode = -1;\n\n          // close handle to child process\n          CloseHandle (h_process);\n\n          return static_cast<int> (exitcode);\n        }\n\n      // This should not be happening.\n      return ::fclose (f);\n    }\n  else\n    return ::_pclose (f);\n\n#else\n  return ::pclose (f);\n#endif\n}\n\n// Read one character from the terminal.\n\nint\nkbhit (bool wait)\n{\n#if defined (HAVE__KBHIT) && defined (HAVE__GETCH)\n  // This essentially means we are on a Windows system.\n\n  // The value to return when wait is false and no input is ready.\n  static constexpr int eof = std::istream::traits_type::eof ();\n\n  int c;\n\n  if (wait)\n    c = _getch ();\n  else\n    c = (! _kbhit ()) ? eof : _getch ();\n\n#else\n  raw_mode (true, wait);\n\n  // Get current handler.\n  interrupt_handler saved_interrupt_handler\n    = ignore_interrupts ();\n\n  // Restore it, disabling system call restarts (if possible) so the\n  // read can be interrupted.\n\n  set_interrupt_handler (saved_interrupt_handler, false);\n\n  int c = std::cin.get ();\n\n  if (std::cin.fail () || std::cin.eof ())\n    {\n      std::cin.clear ();\n      clearerr (stdin);\n    }\n\n  // Restore it, enabling system call restarts (if possible).\n  set_interrupt_handler (saved_interrupt_handler, true);\n\n  raw_mode (false, true);\n#endif\n\n  return c;\n}\n\nstd::string\nget_P_tmpdir ()\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  std::string retval;\n\n#if defined (P_tmpdir)\n  retval = P_tmpdir;\n#endif\n\n  // Apparently some versions of MinGW and MSVC either don't define\n  // P_tmpdir, or they define it to a single backslash, neither of which\n  // is particularly helpful.\n\n  if (retval.empty () || retval == R\"(\\)\")\n    {\n      retval = sys::env::getenv (\"TEMP\");\n\n      if (retval.empty ())\n        retval = sys::env::getenv (\"TMP\");\n\n      if (retval.empty ())\n        retval = R\"(c:\\temp)\";\n    }\n\n  return retval;\n\n#elif defined (P_tmpdir)\n\n  return P_tmpdir;\n\n#else\n\n  return \"/tmp\";\n\n#endif\n}\n\nDEFUN (clc, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} clc ()\n@deftypefnx {} {} home ()\nClear the terminal screen and move the cursor to the upper left corner.\n\nProgramming Note: @code{home} is an alias for @code{clc} and can be used\ninterchangeably.\n@end deftypefn */)\n{\n  bool skip_redisplay = true;\n\n  command_editor::clear_screen (skip_redisplay);\n\n  return ovl ();\n}\n\nDEFALIAS (home, clc);\n\nDEFUN (getenv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{val} =} getenv (\"@var{var}\")\nReturn the value of the environment variable @var{var}.\n\nFor example,\n\n@example\ngetenv (\"PATH\")\n@end example\n\n@noindent\nreturns a string containing the value of your path.\n@seealso{setenv, unsetenv, isenv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string name = args(0).string_value ();\n\n  return ovl (sys::env::getenv (name));\n}\n\n/*\n%!assert (ischar (getenv (\"OCTAVE_HOME\")))\n*/\n\nDEFUN (isenv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isenv (@var{var})\nReturn true if the variable @var{var} is an environment variable, and false\notherwise.\n\nFor example,\n\n@example\ntf = isenv (\"PATH\")\n@end example\n\n@noindent\nwill typically return true on UNIX systems because @qcode{\"PATH\"} is an\nenvironment variable for UNIX.\n@seealso{getenv, setenv, unsetenv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"isenv: VAR must be a string\");\n\n  return ovl (sys::env::isenv (name));\n}\n\n/*\n%!test\n%! setenv (\"dummy_variable_that_cannot_matter\", \"foobar\");\n%! assert (isenv (\"dummy_variable_that_cannot_matter\"), true);\n%! unsetenv (\"dummy_variable_that_cannot_matter\");\n%! assert (isenv (\"dummy_variable_that_cannot_matter\"), false);\n\n%!error <VAR must be a string> isenv (struct ())\n*/\n\nDEFUN (setenv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} setenv (\"@var{var}\", @var{value})\n@deftypefnx {} {} setenv (@var{var})\n@deftypefnx {} {} putenv (@dots{})\nSet the value of the environment variable @var{var} to @var{value}.\n\nIf no @var{value} is specified then the variable will be assigned the null\nstring.\n\nProgramming Note: @code{putenv} is an alias for @code{setenv} and can be used\ninterchangeably.\n@seealso{unsetenv, getenv, isenv}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string var = args(0).xstring_value (\"setenv: VAR must be a string\");\n\n  std::string val = (nargin == 2\n                     ? args(1).xstring_value (\"setenv: VALUE must be a string\")\n                     : \"\");\n\n  sys::env::putenv (var, val);\n\n  return ovl ();\n}\n\nDEFALIAS (putenv, setenv);\n\n/*\n%!test\n%! setenv (\"dummy_variable_that_cannot_matter\", \"foobar\");\n%! assert (getenv (\"dummy_variable_that_cannot_matter\"), \"foobar\");\n%! unsetenv (\"dummy_variable_that_cannot_matter\");\n%! assert (getenv (\"dummy_variable_that_cannot_matter\"), \"\");\n*/\n\nDEFUN (unsetenv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} unsetenv (\"@var{var}\")\n@deftypefnx {} {@var{status} =} unsetenv (\"@var{var}\")\nDelete the environment variable @var{var}.\n\nReturn 0 if the variable was deleted, or did not exist, and -1 if an error\noccurred.\n@seealso{setenv, getenv, isenv}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string tmp = args(0).string_value ();\n\n  return ovl (sys::unsetenv_wrapper (tmp));\n}\n\n/*\n## Test for unsetenv is in setenv test\n*/\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\nstatic void\nreg_close_key_wrapper (HKEY key)\n{\n  RegCloseKey (key);\n}\n\n// This function is also used in ov-java.cc, so don't declare static.\n// Maybe the functions that use it should be here instead?\n\nLONG\nget_regkey_value (HKEY h_rootkey, const std::string subkey,\n                  const std::string name, octave_value& value)\n{\n  LONG result;\n  HKEY h_subkey;\n\n  std::wstring wsubkey = sys::u8_to_wstring (subkey);\n  result = RegOpenKeyExW (h_rootkey, wsubkey.c_str (), 0, KEY_READ,\n                          &h_subkey);\n\n  if (result != ERROR_SUCCESS)\n    return result;\n\n  unwind_action restore_keys ([h_subkey] () { reg_close_key_wrapper (h_subkey); });\n\n  std::wstring wname = sys::u8_to_wstring (name);\n  DWORD length = 0;\n  result = RegQueryValueExW (h_subkey, wname.c_str (), nullptr, nullptr,\n                             nullptr, &length);\n  if (result != ERROR_SUCCESS)\n    return result;\n\n  DWORD type = 0;\n  OCTAVE_LOCAL_BUFFER (BYTE, data, length);\n  result = RegQueryValueExW (h_subkey, wname.c_str (), nullptr, &type,\n                             data, &length);\n  if (result != ERROR_SUCCESS)\n    return result;\n\n  if (type == REG_DWORD)\n    value = octave_int32 (*(reinterpret_cast<DWORD *> (data)));\n  else if (type == REG_SZ || type == REG_EXPAND_SZ)\n    {\n      // strings in registry might not be zero terminated\n      wchar_t *dataw = reinterpret_cast<wchar_t *> (data);\n      DWORD lengthw = length / sizeof (wchar_t);\n      std::wstring reg_string\n        = std::wstring (dataw, lengthw - (dataw[lengthw-1]==0));\n      value = string_vector (sys::u8_from_wstring (reg_string));\n    }\n\n  return result;\n}\n\nstatic LONG\nget_regkey_names (HKEY h_rootkey, const std::string subkey,\n                  std::list<std::string>& fields)\n{\n  LONG retval;\n  HKEY h_subkey;\n\n  fields.clear ();\n\n  std::wstring wsubkey = sys::u8_to_wstring (subkey);\n  retval = RegOpenKeyExW (h_rootkey, wsubkey.c_str (), 0, KEY_READ,\n                          &h_subkey);\n  if (retval != ERROR_SUCCESS)\n    return retval;\n\n  DWORD idx = 0;\n  const int MAX_VALUE_NAME_SIZE = 32766;\n  wchar_t value_name[MAX_VALUE_NAME_SIZE+1];\n  DWORD value_name_size = MAX_VALUE_NAME_SIZE;\n\n  while (true)\n    {\n      retval = RegEnumValueW (h_subkey, idx, value_name, &value_name_size,\n                              nullptr, nullptr, nullptr, nullptr);\n      if (retval != ERROR_SUCCESS)\n        break;\n      fields.push_back (sys::u8_from_wstring (value_name));\n      value_name_size = MAX_VALUE_NAME_SIZE;\n      idx++;\n    }\n\n  if (retval == ERROR_NO_MORE_ITEMS)\n    retval = ERROR_SUCCESS;\n\n  RegCloseKey (h_subkey);\n\n  return retval;\n}\n\n#endif\n\nDEFUN (winqueryreg, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{value} =} winqueryreg (@var{rootkey}, @var{subkey}, @var{valuename})\n@deftypefnx {} {@var{value} =} winqueryreg (@var{rootkey}, @var{subkey})\n@deftypefnx {} {@var{names} =} winqueryreg (@code{\"name\"}, @var{rootkey}, @var{subkey})\n\nQuery names or value from the Windows registry.\n\nOn Windows, return the value of the registry key @var{subkey} from the root key\n@var{rootkey}.  You can specify the name of the queried registry value with the\noptional argument @var{valuename}.  Otherwise, if called with only two\narguments or @var{valuename} is empty, then the default value of @var{subkey}\nis returned.  If the registry value is of type @nospell{@qcode{\"REG_DWORD\"}}\nthen @var{value} is of class int32.  If the value is of the type\n@nospell{@qcode{\"REG_SZ\"}} or @nospell{@qcode{\"REG_EXPAND_SZ\"}} a string is\nreturned.\n\nIf the first argument is @qcode{\"name\"}, a cell array of strings with the names\nof the values at that key is returned.\n\nThe variable @var{rootkey} must be a string with a valid root key identifier:\n\n@table @asis\n@item  @nospell{HKCR}\n@itemx @nospell{HKEY_CLASSES_ROOT}\n\n@item @nospell{HKEY_CURRENT_CONFIG}\n\n@item  @nospell{HKCU}\n@itemx @nospell{HKEY_CURRENT_USER}\n\n@item  @nospell{HKLM}\n@itemx @nospell{HKEY_LOCAL_MACHINE}\n\n\n@item  @nospell{HKU}\n@itemx @nospell{HKEY_USERS}\n\n\n@item @nospell{HKEY_PERFORMANCE_DATA}\n\n@end table\n\nExamples:\n\nGet a list of value names at the key\n@nospell{@qcode{'HKCU@backslashchar{}Environment'}}:\n\n@example\n@group\n@var{valuenames} = winqueryreg (\"name\", \"HKEY_CURRENT_USER\", ...\n                          \"Environment\");\n@end group\n@end example\n\nFor each @var{valuenames}, display the value:\n\n@example\n@group\nfor @var{k} = 1:numel (@var{valuenames})\n  @var{val} = winqueryreg (\"HKEY_CURRENT_USER\", \"Environment\", ...\n                     @var{valuenames}@{@var{k}@});\n  @var{str} = sprintf (\"%s = %s\", @var{valuenames}@{@var{k}@}, num2str (@var{val}));\n  disp (@var{str});\nendfor\n@end group\n@end example\n\nOn non-Windows platforms this function fails with an error.\n@end deftypefn */)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  if ((args.length () < 2) || (args.length () > 3))\n    print_usage ();\n\n  // Input check\n  std::string rootkey_name\n    = args(0).xstring_value (\"winqueryreg: the first argument must be 'name' \"\n                             \"or a valid ROOTKEY identifier\");\n  std::string subkey_name = \"\";\n  std::string value_name = \"\";\n  bool get_names = false;\n  if (rootkey_name.compare (\"name\") == 0)\n    {\n      if (args.length () < 3)\n        error (\"winqueryreg: if the first argument is 'name', \"\n               \"ROOTKEY and SUBKEY must be given\");\n      get_names = true;\n      rootkey_name\n        = args(1).xstring_value (\"winqueryreg: ROOTKEY must be a string\");\n      subkey_name\n        = args(2).xstring_value (\"winqueryreg: SUBKEY must be a string\");\n    }\n  else\n    {\n      subkey_name\n        = args(1).xstring_value (\"winqueryreg: SUBKEY must be a string\");\n\n      if (args.length () == 3)\n        value_name\n          = args(2).xstring_value (\"winqueryreg: VALUENAME must be a string\");\n    }\n\n  // Get rootkey handle\n  HKEY h_rootkey;\n  if (rootkey_name == \"HKEY_CLASSES_ROOT\" || rootkey_name == \"HKCR\")\n    h_rootkey = HKEY_CLASSES_ROOT;\n  else if (rootkey_name == \"HKEY_CURRENT_CONFIG\")\n    h_rootkey = HKEY_CURRENT_CONFIG;\n  else if (rootkey_name == \"HKEY_CURRENT_USER\" || rootkey_name == \"HKCU\")\n    h_rootkey = HKEY_CURRENT_USER;\n  else if (rootkey_name == \"HKEY_LOCAL_MACHINE\" || rootkey_name == \"HKLM\")\n    h_rootkey = HKEY_LOCAL_MACHINE;\n  else if (rootkey_name == \"HKEY_PERFORMANCE_DATA\")\n    h_rootkey = HKEY_PERFORMANCE_DATA;\n  else if (rootkey_name == \"HKEY_USERS\" || rootkey_name == \"HKU\")\n    h_rootkey = HKEY_USERS;\n  else\n    error (\"winqueryreg: ROOTKEY is not a valid root key identifier\");\n\n  if (get_names)\n    {\n      std::list<std::string> fields;\n\n      LONG retval = get_regkey_names (h_rootkey, subkey_name, fields);\n      if (retval != ERROR_SUCCESS)\n        error (\"winqueryreg: error %ld reading names from registry\", retval);\n\n      Cell fieldnames (dim_vector (1, fields.size ()));\n      std::size_t i = 0;\n      for (const auto& it : fields)\n        fieldnames(i++) = it;\n\n      return ovl (fieldnames);\n    }\n  else\n    {\n      octave_value key_val;\n      LONG retval = get_regkey_value (h_rootkey, subkey_name,\n                                      value_name, key_val);\n      if (retval == ERROR_FILE_NOT_FOUND)\n        error (\"winqueryreg: no value found for '%s' at %s\\\\%s\",\n               value_name.c_str (), rootkey_name.c_str (),\n               subkey_name.c_str ());\n      if (retval != ERROR_SUCCESS)\n        error (\"winqueryreg: error %ld reading the specified key\", retval);\n\n      return ovl (key_val);\n    }\n#else\n\n  octave_unused_parameter (args);\n\n  error (\"winqueryreg: function is only supported on Windows platforms\");\n\n#endif\n}\n\n/*\n%!testif ; ispc ()\n%! assert (ischar (winqueryreg (\"HKEY_LOCAL_MACHINE\",\n%!                              'SOFTWARE\\Microsoft\\Windows\\CurrentVersion',\n%!                              \"ProgramFilesDir\")));\n%!testif ; ispc ()\n%! assert (isa (winqueryreg (\"HKEY_LOCAL_MACHINE\",\n%!                           'SYSTEM\\CurrentControlSet\\Control\\FileSystem',\n%!                           \"Win31FileSystem\"), \"int32\"));\n%!testif ; ispc ()\n%! assert (iscellstr (winqueryreg (\"name\", \"HKEY_LOCAL_MACHINE\",\n%!                                 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion')));\n%!testif ; ispc ()\n%! fail ('winqueryreg (1, ''SOFTWARE\\Microsoft\\Windows\\CurrentVersion'')',\n%!       \"first argument must be 'name' or a valid ROOTKEY identifier\");\n%!testif ; ispc ()\n%! fail ('winqueryreg (\"HKEY_LOCAL_MACHINE\", 1)', \"SUBKEY must be a string\");\n%!testif ; ispc ()\n%! fail (['winqueryreg (\"HKEY_LOCAL_MACHINE\", ', ...\n%!        '''SOFTWARE\\Microsoft\\Windows\\CurrentVersion'', 1)'],\n%!       \"VALUENAME must be a string\");\n%!testif ; ispc ()\n%! fail (['winqueryreg (\"FOO\", ', ...\n%!        '''SOFTWARE\\Microsoft\\Windows\\CurrentVersion'')'],\n%!       \"ROOTKEY is not a valid root key identifier\");\n%!testif ; ispc ()\n%! fail ('winqueryreg (\"HKEY_LOCAL_MACHINE\", ''FOO\\bar'')',\n%!       \"no value found for\");\n%!testif ; ispc ()\n%! fail (['winqueryreg (\"HKEY_LOCAL_MACHINE\", ', ...\n%!        '''SOFTWARE\\Microsoft\\Windows\\CurrentVersion'', \"foo\")'],\n%!       \"no value found for\");\n%!testif ; ispc ()\n%! fail ('winqueryreg (\"name\", \"HKEY_LOCAL_MACHINE\")',\n%!       \"if the first argument is 'name', ROOTKEY and SUBKEY must be given\");\n%!testif ; ispc ()\n%! fail (['winqueryreg (\"name\", 1, ', ...\n%!        '''SOFTWARE\\Microsoft\\Windows\\CurrentVersion'')'],\n%!       \"ROOTKEY must be a string\");\n%!testif ; ispc ()\n%! fail ('winqueryreg (\"name\", \"HKEY_LOCAL_MACHINE\", 1)',\n%!       \"SUBKEY must be a string\");\n*/\n\n// FIXME: perhaps kbhit should also be able to print a prompt?\n\nDEFMETHOD (kbhit, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{c} =} kbhit ()\n@deftypefnx {} {@var{c} =} kbhit (1)\nRead a single keystroke from the keyboard.\n\nIf called with an argument (typically 1), don't wait for a keypress and\nimmediately return the next keystroke in the keyboard input buffer or an empty\nstring (\"\") if no keystroke is available.\n\nFor example,\n\n@example\nc = kbhit ();\n@end example\n\n@noindent\nwill set @var{c} to the next character typed at the keyboard as soon as it is\ntyped.\n\n@example\nc = kbhit (1);\n@end example\n\n@noindent\nis identical to the above example, but doesn't wait for a keypress, returning\nthe empty string if no key is available.\n@seealso{input, pause}\n@end deftypefn */)\n{\n  // FIXME: add timeout and default value args?\n\n  Fdrawnow (interp);\n\n  int c = kbhit (args.length () == 0);\n\n  if (c == -1)\n    c = 0;\n\n  char s[2] = { static_cast<char> (c), '\\0' };\n\n  return octave_value (s);\n}\n\n// State of the pause system\nstatic bool Vpause_enabled = true;\n\nDEFMETHOD (pause, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} pause ()\n@deftypefnx {} {} pause (@var{n})\n@deftypefnx {} {@var{old_state} =} pause (\"on\")\n@deftypefnx {} {@var{old_state} =} pause (\"off\")\n@deftypefnx {} {@var{old_state} =} pause (\"query\")\nSuspend the execution of the program or change the state of the pause function.\n\nIf invoked without an input arguments then the program is suspended until a\ncharacter is typed.  If argument @var{n} is a positive real value, it indicates\nthe number of seconds the program shall be suspended, for example:\n\n@example\n@group\ntic; pause (0.05); toc\n     @print{} Elapsed time is 0.05039 seconds.\n@end group\n@end example\n\nThe following example prints a message and then waits 5 seconds before clearing\nthe screen.\n\n@example\n@group\ndisp (\"wait please...\");\npause (5);\nclc;\n@end group\n@end example\n\nIf invoked with a string argument @qcode{\"on\"}, @qcode{\"off\"}, or\n@qcode{\"query\"}, the state of the pause function is changed or queried.  When\nthe state is @qcode{\"off\"}, the pause function returns immediately.  The\noptional return value contains the previous state of the pause function.  In\nthe following example pause is disabled locally:\n\n@example\n@group\nold_state = pause (\"off\");\ntic; pause (0.05); toc\n     @print{} Elapsed time is 3.00407e-05 seconds.\npause (old_state);\n@end group\n@end example\n\nWhile the program is suspended Octave still handles figures painting and\ngraphics callbacks execution.\n\n@seealso{kbhit}\n@end deftypefn */)\n{\n  octave_value_list retval;\n\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1 && args(0).is_string ())\n    {\n      bool saved_state = Vpause_enabled;\n      std::string state = args(0).string_value ();\n\n      if (state == \"on\")\n        Vpause_enabled = true;\n      else if (state == \"off\")\n        Vpause_enabled = false;\n      else if (state == \"query\")\n        ;// Do nothing\n      else\n        error (R\"(pause: first argument must be \"on\", \"off\", or \"query\")\");\n\n      if (nargout > 0 || state == \"query\")\n        retval.append (saved_state ? \"on\" : \"off\");\n    }\n  else if (Vpause_enabled)\n    {\n      double dval;\n\n      if (nargin == 0)\n        dval = octave_Inf;\n      else\n        dval = args(0).xdouble_value (\"pause: N must be a scalar real value\");\n\n      if (math::isnan (dval))\n        warning (\"pause: NaN is an invalid delay\");\n      else\n        {\n          Fdrawnow (interp);\n\n          sleep (dval, true);\n        }\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! pause (1);\n\n%!error pause (1, 2)\n*/\n\n// FIXME: maybe this should only return 1 if IEEE floating\n// point functions really work.\n\nDEFUN (isieee, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isieee ()\nReturn true if your computer @emph{claims} to conform to the IEEE@tie{}754\nstandard for floating point calculations.\n\nNo actual tests are performed.\n@end deftypefn */)\n{\n  mach_info::float_format flt_fmt = mach_info::native_float_format ();\n\n  return ovl (flt_fmt == mach_info::flt_fmt_ieee_little_endian\n              || flt_fmt == mach_info::flt_fmt_ieee_big_endian);\n}\n\n/*\n%!assert (islogical (isieee ()))\n*/\n\nDEFUN (native_float_format, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fmtstr} =} native_float_format ()\nReturn the native floating point format as a string.\n@end deftypefn */)\n{\n  mach_info::float_format flt_fmt = mach_info::native_float_format ();\n\n  return ovl (mach_info::float_format_as_string (flt_fmt));\n}\n\n/*\n%!assert (ischar (native_float_format ()))\n*/\n\nDEFUN (tilde_expand, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{newstr} =} tilde_expand (@var{string})\n@deftypefnx {} {@var{newcstr} =} tilde_expand (@var{cellstr})\nPerform tilde expansion on @var{string}.\n\nIf @var{string} begins with a tilde character, (@samp{~}), all of the\ncharacters preceding the first slash (or all characters, if there is no\nslash) are treated as a possible user name, and the tilde and the following\ncharacters up to the slash are replaced by the home directory of the named\nuser.  If the tilde is followed immediately by a slash, the tilde is\nreplaced by the home directory of the user running Octave.\n\nIf the input is a cell array of strings @var{cellstr} then tilde expansion\nis performed on each string element.\n\nExamples:\n\n@example\n@group\ntilde_expand (\"~joeuser/bin\")\n     @xresult{} \"/home/joeuser/bin\"\ntilde_expand (\"~/bin\")\n     @xresult{} \"/home/jwe/bin\"\n@end group\n@end example\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  string_vector sv =\n    arg.xstring_vector_value (\"tilde_expand: argument must be char or cellstr object\");\n\n  sv = sys::file_ops::tilde_expand (sv);\n\n  if (arg.iscellstr ())\n    return ovl (Cell (arg.dims (), sv));\n  else\n    return ovl (sv);\n}\n\n/*\n%!testif ; isfolder (\"~\")\n%! home = get_home_directory ();\n%! assert (tilde_expand (\"~/foobar\"), [home \"/foobar\"]);\n%! assert (tilde_expand (\"/foo/bar\"), \"/foo/bar\");\n%! assert (tilde_expand (\"foo/bar\"), \"foo/bar\");\n*/\n\nDEFUN (get_home_directory, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{homedir} =} get_home_directory ()\nReturn the current home directory.\n\nOn most systems, this is equivalent to @code{getenv (\"HOME\")}.  On Windows\nsystems, if the environment variable @env{HOME} is not set then it is\nequivalent to\n@code{fullfile (getenv (\"HOMEDRIVE\"), getenv (\"HOMEPATH\"))}\n@seealso{getenv}\n@end deftypefn */)\n{\n  return ovl (sys::env::get_home_directory ());\n}\n\n/*\n%!test\n%! HOME = getenv (\"HOME\");\n%! unwind_protect\n%!   setenv (\"HOME\", P_tmpdir ());\n%!   assert (get_home_directory (), getenv (\"HOME\"));\n%! unwind_protect_cleanup\n%!   if (isempty (HOME))\n%!     unsetenv (\"HOME\");\n%!   else\n%!     setenv (\"HOME\", HOME);\n%!   endif\n%! end_unwind_protect\n*/\n\nDEFUN (__blas_version__, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{verstr} =} __blas_version__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  return ovl (sys::blas_version ());\n}\n\nDEFUN (__lapack_version__, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{verstr} =} __lapack_version__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  return ovl (sys::lapack_version ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/sysdep.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_sysdep_h)\n#define octave_sysdep_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdio>\n\n#include <string>\n\n#include \"lo-ieee.h\"\n#include \"oct-sysdep.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API void sysdep_init ();\n\nextern OCTINTERP_API void set_application_id ();\n\nextern OCTINTERP_API void sysdep_cleanup ();\n\nextern OCTINTERP_API void raw_mode (bool, bool wait = true);\n\nextern OCTINTERP_API FILE * popen (const char *command, const char *mode);\n\nextern OCTINTERP_API int pclose (FILE *f);\n\nextern OCTINTERP_API int kbhit (bool wait = true);\n\nextern OCTINTERP_API std::string get_P_tmpdir ();\n\nextern OCTINTERP_API bool drive_or_unc_share (const std::string&);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/system/__ftp__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n#include <fstream>\n\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"glob-match.h\"\n#include \"oct-env.h\"\n#include \"oct-handle.h\"\n#include \"oct-sysdep.h\"\n#include \"url-transfer.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"oct-refcount.h\"\n#include \"ov-cell.h\"\n#include \"ov-classdef.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"unwind-prot.h\"\n#include \"url-handle-manager.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFMETHOD (__ftp__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{handle} =} __ftp__ (@var{host})\n@deftypefnx {} {@var{handle} =} __ftp__ (@var{host}, @var{username}, @var{password})\nUndocumented internal function\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  std::string host = args(0).xstring_value (\"__ftp__: HOST must be a string\");\n\n  std::string user = (nargin > 1)\n                     ? args(1).xstring_value (\"__ftp__: USER must be a string\")\n                     : \"anonymous\";\n\n  std::string passwd = (nargin > 2)\n                       ? args(2).xstring_value (\"__ftp__: PASSWD must be a string\")\n                       : \"\";\n\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_handle uh = uhm.make_url_handle (host, user, passwd, octave_stdout);\n\n  return ovl (uh.value ());\n}\n\nDEFMETHOD (__ftp_pwd__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{pwd} =} __ftp_pwd__ (@var{handle})\nUndocumented internal function\n@end deftypefn */)\n{\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_pwd__: invalid ftp handle\");\n\n  return ovl (url_xfer.pwd ());\n}\n\nDEFMETHOD (__ftp_cwd__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __ftp_cwd__ (@var{handle}, @var{path})\nUndocumented internal function\n@end deftypefn */)\n{\n  std::string path = \"\";\n  if (args.length () > 1)\n    path = args(1).xstring_value (\"__ftp_cwd__: PATH must be a string\");\n\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_cwd__: invalid ftp handle\");\n\n  url_xfer.cwd (path);\n\n  return ovl ();\n}\n\nDEFMETHOD (__ftp_dir__, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __ftp_dir__ (@var{handle})\n@deftypefnx {} {@var{S} =} __ftp_dir__ (@var{handle})\nUndocumented internal function\n@end deftypefn */)\n{\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_dir__: invalid ftp handle\");\n\n  octave_value retval;\n\n  if (nargout == 0)\n    url_xfer.dir ();\n  else\n    {\n      string_vector sv = url_xfer.list ();\n      octave_idx_type n = sv.numel ();\n\n      if (n == 0)\n        {\n          string_vector flds (5);\n\n          flds(0) = \"name\";\n          flds(1) = \"date\";\n          flds(2) = \"bytes\";\n          flds(3) = \"isdir\";\n          flds(4) = \"datenum\";\n\n          retval = octave_map (flds);\n        }\n      else\n        {\n          octave_map st;\n\n          Cell filectime (dim_vector (n, 1));\n          Cell filesize (dim_vector (n, 1));\n          Cell fileisdir (dim_vector (n, 1));\n          Cell filedatenum (dim_vector (n, 1));\n\n          st.assign (\"name\", Cell (sv));\n\n          for (octave_idx_type i = 0; i < n; i++)\n            {\n              OCTAVE_TIME_T ftime;\n              bool fisdir;\n              double fsize;\n\n              url_xfer.get_fileinfo (sv(i), fsize, ftime, fisdir);\n\n              fileisdir(i) = fisdir;\n              time_t ftime_t = ftime;\n              filectime(i) = ctime (&ftime_t);\n              filesize(i)  = fsize;\n              filedatenum(i) = double (ftime);\n            }\n\n          st.assign (\"date\", filectime);\n          st.assign (\"bytes\", filesize);\n          st.assign (\"isdir\", fileisdir);\n          st.assign (\"datenum\", filedatenum);\n\n          retval = st;\n        }\n    }\n\n  return retval;\n}\n\nDEFMETHOD (__ftp_ascii__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __ftp_ascii__ (@var{handle})\nUndocumented internal function\n@end deftypefn */)\n{\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_ascii__: invalid ftp handle\");\n\n  url_xfer.ascii ();\n\n  return ovl ();\n}\n\nDEFMETHOD (__ftp_binary__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __ftp_binary__ (@var{handle})\nUndocumented internal function\n@end deftypefn */)\n{\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_binary__: invalid ftp handle\");\n\n  url_xfer.binary ();\n\n  return ovl ();\n}\n\nDEFMETHOD (__ftp_close__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __ftp_close__ (@var{handle})\nUndocumented internal function\n@end deftypefn */)\n{\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_handle h = uhm.lookup (args(0));\n\n  if (! h.ok ())\n    error (\"__ftp_close__: invalid ftp handle\");\n\n  uhm.free (h);\n\n  return ovl ();\n}\n\nDEFMETHOD (__ftp_mode__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{mode} =} __ftp_mode__ (@var{handle})\nUndocumented internal function\n@end deftypefn */)\n{\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_binary__: invalid ftp handle\");\n\n  return ovl (url_xfer.is_ascii () ? \"ascii\" : \"binary\");\n}\n\nDEFMETHOD (__ftp_delete__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __ftp_delete__ (@var{handle}, @var{path})\nUndocumented internal function\n@end deftypefn */)\n{\n  std::string file = args(1).xstring_value (\"__ftp_delete__: FILE must be a string\");\n\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_delete__: invalid ftp handle\");\n\n  url_xfer.del (file);\n\n  return ovl ();\n}\n\nDEFMETHOD (__ftp_rmdir__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __ftp_rmdir__ (@var{handle}, @var{path})\nUndocumented internal function\n@end deftypefn */)\n{\n  std::string dir = args(1).xstring_value (\"__ftp_rmdir__: DIR must be a string\");\n\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_rmdir__: invalid ftp handle\");\n\n  url_xfer.rmdir (dir);\n\n  return ovl ();\n}\n\nDEFMETHOD (__ftp_mkdir__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __ftp_mkdir__ (@var{handle}, @var{path})\nUndocumented internal function\n@end deftypefn */)\n{\n  std::string dir = args(1).xstring_value (\"__ftp_mkdir__: DIR must be a string\");\n\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_mkdir__: invalid ftp handle\");\n\n  url_xfer.mkdir (dir);\n\n  return ovl ();\n}\n\nDEFMETHOD (__ftp_rename__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __ftp_rename__ (@var{handle}, @var{path})\nUndocumented internal function\n@end deftypefn */)\n{\n  std::string oldname = args(1).xstring_value (\"__ftp_rename__: OLDNAME must be a string\");\n  std::string newname = args(2).xstring_value (\"__ftp_rename__: NEWNAME must be a string\");\n\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (url_xfer.is_valid ())\n    error (\"__ftp_rename__: invalid ftp handle\");\n\n  url_xfer.rename (oldname, newname);\n\n  return ovl ();\n}\n\nDEFMETHOD (__ftp_mput__, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __ftp_mput__ (@var{handle}, @var{files})\n@deftypefnx {} {@var{filelist} =} __ftp_mput__ (@var{handle}, @var{files})\nUndocumented internal function\n@end deftypefn */)\n{\n  std::string pat = args(1).xstring_value (\"__ftp_mput__: PATTERN must be a string\");\n\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_mput__: invalid ftp handle\");\n\n  string_vector file_list;\n\n  glob_match pattern (sys::file_ops::tilde_expand (pat));\n  string_vector files = pattern.glob ();\n\n  for (octave_idx_type i = 0; i < files.numel (); i++)\n    {\n      std::string file = files(i);\n\n      if (! sys::file_exists (file))\n        error (\"__ftp__mput: file does not exist\");\n\n      if (sys::dir_exists (file))\n        {\n          file_list.append (url_xfer.mput_directory (\"\", file));\n\n          if (! url_xfer.good ())\n            error (\"__ftp_mput__: %s\", url_xfer.lasterror ().c_str ());\n        }\n      else\n        {\n          // FIXME: Does ascii mode need to be flagged here?\n          std::ifstream ifile =\n            sys::ifstream (file.c_str (),\n                           std::ios::in | std::ios::binary);\n\n          if (! ifile.is_open ())\n            error (\"__ftp_mput__: unable to open file\");\n\n          url_xfer.put (file, ifile);\n\n          ifile.close ();\n\n          if (! url_xfer.good ())\n            error (\"__ftp_mput__: %s\", url_xfer.lasterror ().c_str ());\n\n          file_list.append (file);\n        }\n    }\n\n  if (nargout > 0)\n    return ovl (file_list);\n  else\n    return ovl ();\n}\n\nDEFMETHOD (__ftp_mget__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __ftp_mget__ (@var{handle}, @var{pattern})\n@deftypefnx {} {} __ftp_mget__ (@var{handle}, @var{pattern}, @var{target})\nUndocumented internal function\n@end deftypefn */)\n{\n  std::string file = args(1).xstring_value (\"__ftp_mget__: PATTERN must be a string\");\n\n  std::string target;\n\n  if (args.length () == 3 && ! args(2).isempty ())\n    target = args(2).xstring_value (\"__ftp_mget__: TARGET must be a string\")\n             + sys::file_ops::dir_sep_str ();\n\n  url_handle_manager& uhm = interp.get_url_handle_manager ();\n\n  url_transfer url_xfer = uhm.get_object (args(0));\n\n  if (! url_xfer.is_valid ())\n    error (\"__ftp_mget__: invalid ftp handle\");\n\n  string_vector sv = url_xfer.list ();\n  octave_idx_type n = 0;\n  glob_match pattern (file);\n\n  for (octave_idx_type i = 0; i < sv.numel (); i++)\n    {\n      if (pattern.match (sv(i)))\n        {\n          n++;\n\n          OCTAVE_TIME_T ftime;\n          bool fisdir;\n          double fsize;\n\n          url_xfer.get_fileinfo (sv(i), fsize, ftime, fisdir);\n\n          if (fisdir)\n            url_xfer.mget_directory (sv(i), target);\n          else\n            {\n              std::ofstream ofile =\n                sys::ofstream ((target + sv(i)).c_str (),\n                               std::ios::out | std::ios::binary);\n\n              if (! ofile.is_open ())\n                error (\"__ftp_mget__: unable to open file\");\n\n              int(*unlink_fptr)(const std::string&) = sys::unlink;\n              unwind_action_safe delete_file (unlink_fptr, target + sv(i));\n\n              url_xfer.get (sv(i), ofile);\n\n              ofile.close ();\n\n              if (url_xfer.good ())\n                delete_file.discard ();\n            }\n\n          if (! url_xfer.good ())\n            error (\"__ftp_mget__: %s\", url_xfer.lasterror ().c_str ());\n        }\n    }\n\n  if (n == 0)\n    error (\"__ftp_mget__: file not found\");\n\n  return ovl ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/system/dirfns.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"glob-match.h\"\n#include \"oct-env.h\"\n#include \"oct-glob.h\"\n#include \"oct-sysdep.h\"\n#include \"pathsearch.h\"\n#include \"str-vec.h\"\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"dir-ops.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"event-manager.h\"\n#include \"input.h\"\n#include \"load-path.h\"\n#include \"octave.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"procstream.h\"\n#include \"sysdep.h\"\n#include \"interpreter.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// TRUE means we ask for confirmation before recursively removing a\n// directory tree.\nstatic bool Vconfirm_recursive_rmdir = true;\n\nDEFMETHOD (cd, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} cd @var{dir}\n@deftypefnx {} {} cd\n@deftypefnx {} {@var{old_dir} =} cd\n@deftypefnx {} {@var{old_dir} =} cd (@var{dir})\n@deftypefnx {} {} chdir @dots{}\nChange the current working directory to @var{dir}.\n\nIf called with no input or output arguments, the current directory is\nchanged to the user's home directory (@qcode{\"~\"}).\n\nFor example,\n\n@example\ncd ~/octave\n@end example\n\n@noindent\nchanges the current working directory to @file{~/octave}.  If the\ndirectory does not exist, an error message is printed and the working\ndirectory is not changed.\n\nProgramming Note: @code{chdir} is an alias for @code{cd} and can be used with\nall of the same calling formats.\n\nCompatibility Note: When called with no arguments, @sc{matlab} prints the\npresent working directory rather than changing to the user's home directory.\n@seealso{pwd, mkdir, rmdir, dir, ls}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  octave_value_list retval;\n\n  if (nargout > 0)\n    retval = octave_value (sys::env::get_current_directory ());\n\n  if (nargin == 1)\n    {\n      std::string dirname = args(0).xstring_value (\"cd: DIR must be a string\");\n\n      if (! dirname.empty ())\n        interp.chdir (dirname);\n    }\n  else if (nargout == 0)\n    {\n      std::string home_dir = sys::env::get_home_directory ();\n\n      if (! home_dir.empty ())\n        interp.chdir (home_dir);\n    }\n\n  return retval;\n}\n\nDEFALIAS (chdir, cd);\n\nDEFUN (pwd, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{dir} =} pwd ()\nReturn the current working directory.\n@seealso{cd, dir, ls, mkdir, rmdir}\n@end deftypefn */)\n{\n  return ovl (sys::env::get_current_directory ());\n}\n\nDEFUN (readdir, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{files} =} readdir (@var{dir})\n@deftypefnx {} {[@var{files}, @var{err}, @var{msg}] =} readdir (@var{dir})\nReturn the names of files in the directory @var{dir} as a cell array of\nstrings.\n\nIf an error occurs, return an empty cell array in @var{files}.\nIf successful, @var{err} is 0 and @var{msg} is an empty string.\nOtherwise, @var{err} is nonzero and @var{msg} contains a system-dependent\nerror message.\n@seealso{ls, dir, glob, what}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string dirname = args(0).xstring_value (\"readdir: DIR must be a string\");\n\n  octave_value_list retval = ovl (Cell (), -1.0, \"\");\n\n  dirname = sys::file_ops::tilde_expand (dirname);\n\n  string_vector dirlist;\n  std::string msg;\n\n  if (sys::get_dirlist (dirname, dirlist, msg))\n    {\n      retval(0) = Cell (dirlist.sort ());\n      retval(1) = 0.0;\n    }\n  else\n    retval(2) = msg;\n\n  return retval;\n}\n\n// FIXME: should maybe also allow second arg to specify mode?\n//        OTOH, that might cause trouble with compatibility later...\n\nDEFUN (__mkdir__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} __mkdir__ (@var{dir})\n@deftypefnx {} {} __mkdir__ (@var{parent}, @var{dir})\n@deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} __mkdir__ (@dots{})\nInternal function called by mkdir.m.\n@seealso{mkdir, rmdir, pwd, cd, umask}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage (\"mkdir\");\n\n  std::string dirname;\n\n  if (nargin == 2)\n    {\n      std::string parent = args(0).xstring_value (\"mkdir: PARENT must be a string\");\n      std::string dir = args(1).xstring_value (\"mkdir: DIR must be a string\");\n\n      dirname = sys::file_ops::concat (parent, dir);\n    }\n  else if (nargin == 1)\n    dirname = args(0).xstring_value (\"mkdir: DIR must be a string\");\n\n  dirname = sys::file_ops::tilde_expand (dirname);\n\n  if (sys::dir_exists (dirname))\n    {\n      // For Matlab compatibility, return true when directory already exists.\n      return ovl (true, \"directory exists\", \"mkdir\");\n    }\n  else\n    {\n      std::string msg;\n\n      int status = sys::mkdir (dirname, 0777, msg);\n\n      if (status < 0)\n        return ovl (false, msg, \"mkdir\");\n      else\n        return ovl (true, \"\", \"\");\n    }\n}\n\nDEFMETHODX (\"rmdir\", Frmdir, interp, args, nargout,\n            doc: /* -*- texinfo -*-\n@deftypefn  {} {} rmdir @var{dir}\n@deftypefnx {} {} rmdir (@var{dir}, \"s\")\n@deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} rmdir (@dots{})\nRemove the directory named @var{dir}.\n\nIf the optional second parameter is supplied with value @qcode{\"s\"},\nrecursively remove all subdirectories as well.\n\nIf successful, @var{status} is logical 1, and @var{msg}, @var{msgid} are empty\ncharacter strings (\"\").  Otherwise, @var{status} is logical 0, @var{msg}\ncontains a system-dependent error message, and @var{msgid} contains a unique\nmessage identifier.\n\n@seealso{mkdir, confirm_recursive_rmdir, pwd}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string dirname = args(0).xstring_value (\"rmdir: DIR must be a string\");\n\n  std::string fulldir = sys::file_ops::tilde_expand (dirname);\n  octave_value_list retval;\n  int status = -1;\n  std::string msg;\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  if (nargin == 2)\n    {\n      if (args(1).string_value () != \"s\")\n        error (R\"(rmdir: second argument must be \"s\" for recursive removal)\");\n\n      bool doit = true;\n\n      if (interp.interactive ()\n          && ! application::forced_interactive ()\n          && Vconfirm_recursive_rmdir)\n        {\n          input_system& input_sys = interp.get_input_system ();\n\n          std::string prompt = \"remove entire contents of \" + fulldir + \"? \";\n\n          doit = input_sys.yes_or_no (prompt);\n        }\n\n      if (doit)\n        {\n          evmgr.file_remove (fulldir, \"\");\n          status = sys::recursive_rmdir (fulldir, msg);\n        }\n    }\n  else\n    {\n      evmgr.file_remove (fulldir, \"\");\n      status = sys::rmdir (fulldir, msg);\n    }\n\n  evmgr.file_renamed (status >= 0);\n\n  if (nargout == 0)\n    {\n      if (status < 0)\n        error (\"rmdir: operation failed: %s\", msg.c_str ());\n    }\n  else\n    {\n      if (status < 0)\n        retval = ovl (false, msg, \"rmdir\");\n      else\n        retval = ovl (true, \"\", \"\");\n    }\n\n  return retval;\n}\n\nDEFUNX (\"link\", Flink, args, nargout,\n        doc: /* -*- texinfo -*-\n@deftypefn  {} {} link @var{old} @var{new}\n@deftypefnx {} {[@var{status}, @var{msg}] =} link (@var{old}, @var{new})\nCreate a new link (also known as a hard link) to an existing file.\n\nIf successful, @var{status} is 0 and @var{msg} is an empty string.\nOtherwise, @var{status} is -1 and @var{msg} contains a system-dependent\nerror message.\n@seealso{symlink, unlink, readlink, lstat}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string from = args(0).xstring_value (\"link: OLD must be a string\");\n  std::string to = args(1).xstring_value (\"link: NEW must be a string\");\n\n  from = sys::file_ops::tilde_expand (from);\n  to = sys::file_ops::tilde_expand (to);\n\n  octave_value_list retval;\n  std::string msg;\n\n  int status = sys::link (from, to, msg);\n\n  if (nargout == 0)\n    {\n      if (status < 0)\n        error (\"link: operation failed: %s\", msg.c_str ());\n    }\n  else\n    {\n      if (status < 0)\n        retval = ovl (-1.0, msg);\n      else\n        retval = ovl (0.0, \"\");\n    }\n\n  return retval;\n}\n\nDEFUNX (\"symlink\", Fsymlink, args, nargout,\n        doc: /* -*- texinfo -*-\n@deftypefn  {} {} symlink @var{old} @var{new}\n@deftypefnx {} {[@var{status}, @var{msg}] =} symlink (@var{old}, @var{new})\nCreate a symbolic link @var{new} which contains the string @var{old}.\n\nIf successful, @var{status} is 0 and @var{msg} is an empty string.\nOtherwise, @var{status} is -1 and @var{msg} contains a system-dependent\nerror message.\n@seealso{link, unlink, readlink, lstat}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string from = args(0).xstring_value (\"symlink: OLD must be a string\");\n  std::string to = args(1).xstring_value (\"symlink: NEW must be a string\");\n\n  from = sys::file_ops::tilde_expand (from);\n  to = sys::file_ops::tilde_expand (to);\n\n  octave_value_list retval;\n  std::string msg;\n\n  int status = sys::symlink (from, to, msg);\n\n  if (nargout == 0)\n    {\n      if (status < 0)\n        error (\"symlink: operation failed: %s\", msg.c_str ());\n    }\n  else\n    {\n      if (status < 0)\n        retval = ovl (-1.0, msg);\n      else\n        retval = ovl (0.0, \"\");\n    }\n\n  return retval;\n}\n\nDEFUNX (\"readlink\", Freadlink, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{result} =} readlink @var{symlink}\n@deftypefnx {} {[@var{result}, @var{err}, @var{msg}] =} readlink (@var{symlink})\nRead the value of the symbolic link @var{symlink}.\n\nIf successful, @var{result} contains the contents of the symbolic link\n@var{symlink}, @var{err} is 0, and @var{msg} is an empty string.\nOtherwise, @var{err} is nonzero and @var{msg} contains a system-dependent\nerror message.\n@seealso{lstat, symlink, link, unlink, delete}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string symlink = args(0).xstring_value (\"readlink: SYMLINK must be a string\");\n\n  symlink = sys::file_ops::tilde_expand (symlink);\n\n  std::string result, msg;\n\n  int status = sys::readlink (symlink, result, msg);\n\n  if (status < 0)\n    return ovl (\"\", -1.0, msg);\n  else\n    return ovl (result, status, \"\");\n}\n\nDEFMETHODX (\"rename\", Frename, interp, args, nargout,\n            doc: /* -*- texinfo -*-\n@deftypefn  {} {} rename @var{old} @var{new}\n@deftypefnx {} {[@var{status}, @var{msg}] =} rename (@var{old}, @var{new})\nChange the name of file @var{old} to @var{new}.\n\nIf successful, @var{status} is 0 and @var{msg} is an empty string.\nOtherwise, @var{status} is -1 and @var{msg} contains a system-dependent\nerror message.\n@seealso{movefile, copyfile, ls, dir}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string from = args(0).xstring_value (\"rename: OLD must be a string\");\n  std::string to = args(1).xstring_value (\"rename: NEW must be a string\");\n\n  from = sys::file_ops::tilde_expand (from);\n  to = sys::file_ops::tilde_expand (to);\n\n  octave_value_list retval;\n  std::string msg;\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.file_remove (from, to);\n\n  int status = sys::rename (from, to, msg);\n\n  evmgr.file_renamed (status >= 0);\n\n  if (nargout == 0)\n    {\n      if (status < 0)\n        error (\"rename: operation failed: %s\", msg.c_str ());\n    }\n  else\n    {\n      if (status < 0)\n        retval = ovl (-1.0, msg);\n      else\n        retval = ovl (0.0, \"\");\n    }\n\n  return retval;\n}\n\nDEFUN (glob, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{cstr} =} glob (@var{pattern})\nGiven an array of pattern strings (as a char array or a cell array) in\n@var{pattern}, return a cell array of filenames that match any of\nthem, or an empty cell array if no patterns match.\n\nThe pattern strings are interpreted as filename globbing patterns (as they\nare used by Unix shells).\n\nWithin a pattern\n\n@table @code\n@item *\nmatches any string, including the null string,\n\n@item ?\nmatches any single character, and\n\n@item [@dots{}]\nmatches any of the enclosed characters.\n@end table\n\nTilde expansion is performed on each of the patterns before looking for\nmatching filenames.  For example:\n\n@example\nls\n   @xresult{}\n      file1  file2  file3  myfile1 myfile1b\nglob (\"*file1\")\n   @xresult{}\n      @{\n        [1,1] = file1\n        [2,1] = myfile1\n      @}\nglob (\"myfile?\")\n   @xresult{}\n      @{\n        [1,1] = myfile1\n      @}\nglob (\"file[12]\")\n   @xresult{}\n      @{\n        [1,1] = file1\n        [2,1] = file2\n      @}\n@end example\n\nNote: On Windows, patterns that contain non-ASCII characters are not\nsupported.\n\n@seealso{ls, dir, readdir, what}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  string_vector pat\n    = args(0).xstring_vector_value (\"glob: PATTERN must be a string\");\n\n  glob_match pattern (sys::file_ops::tilde_expand (pat));\n\n  return ovl (Cell (pattern.glob ()));\n}\n\n/*\n%!test\n%! tmpdir = tempname ();\n%! filename = {\"file1\", \"file2\", \"file3\", \"myfile1\", \"myfile1b\"};\n%! if (mkdir (tmpdir))\n%!   cwd = pwd ();\n%!   cd (tmpdir);\n%!   if (strcmp (canonicalize_file_name (pwd), canonicalize_file_name (tmpdir)))\n%!     a = 0;\n%!     for n = 1:5\n%!       save (filename{n}, \"a\");\n%!     endfor\n%!   else\n%!     sts = rmdir (tmpdir);\n%!     error (\"Couldn't change to temporary directory\");\n%!   endif\n%! else\n%!   error (\"Couldn't create temporary directory\");\n%! endif\n%! result1 = glob (\"*file1\");\n%! result2 = glob (\"myfile?\");\n%! result3 = glob (\"file[12]\");\n%! for n = 1:5\n%!   delete (filename{n});\n%! endfor\n%! cd (cwd);\n%! sts = rmdir (tmpdir);\n%! assert (result1, {\"file1\"; \"myfile1\"});\n%! assert (result2, {\"myfile1\"});\n%! assert (result3, {\"file1\"; \"file2\"});\n\n## Check backslash handling on Windows\n%!testif ; ispc ()\n%! win_dir = getenv (\"WINDIR\");\n%! assert (glob (win_dir), {win_dir});\n%! assert (glob ([win_dir, filesep]), {[win_dir, filesep]});\n%! win_dir2 = strrep(win_dir, filesep, '/');\n%! assert (glob (win_dir2), {win_dir});\n%! assert (glob ([win_dir2, '/']), {[win_dir, filesep]});\n*/\n\nDEFUN (__wglob__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{cstr} =} __wglob__ (@var{pattern})\nWindows-like glob for dir.\n\nGiven an array of pattern strings (as a char array or a cell array) in\n@var{pattern}, return a cell array of filenames that match any of\nthem, or an empty cell array if no patterns match.\n\nThe pattern strings are interpreted as filename globbing patterns\n(roughly as they are used by Windows dir).\n\nWithin a pattern\n\n@table @code\n@item *\nmatches any string, including the null string,\n\n@item ?\nmatches any single character, and\n\n@item *.*\nmatches any string, even if no . is present.\n@end table\n\nTilde expansion is performed on each of the patterns before looking for\nmatching filenames.  For example:\n\n@example\nls\n   @xresult{}\n      file1  file2  file3  myfile1 myfile1b\nglob (\"*file1\")\n   @xresult{}\n      @{\n        [1,1] = file1\n        [2,1] = myfile1\n      @}\nglob (\"myfile?\")\n   @xresult{}\n      @{\n        [1,1] = myfile1\n      @}\nglob (\"*.*\")\n   @xresult{}\n      @{\n        [1,1] = file1\n        [2,1] = file2\n        [3,1] = file3\n        [4,1] = myfile1\n        [5,1] = myfile1b\n      @}\n@end example\n@seealso{glob, dir}\n@end deftypefn */)\n{\n  if (args.length () == 0)\n    return ovl ();\n\n  string_vector pat = args(0).string_vector_value ();\n\n  string_vector pattern (sys::file_ops::tilde_expand (pat));\n\n  return ovl (Cell (sys::windows_glob (pattern)));\n}\n\n/*\n%!test <*62414>\n%! ## get name of current directory and one file in it\n%! [~, curr_dir, ext] = fileparts (pwd ());\n%! curr_dir = [curr_dir, ext];\n%! files = dir ();\n%! if (numel (files) < 3)\n%!   return;\n%! endif\n%! ## check some patterns including \".\" and \"..\"\n%! file_in_pwd = files(3).name;\n%! assert (__wglob__ (file_in_pwd), {file_in_pwd});\n%! glob_pattern = fullfile (\".\", file_in_pwd);\n%! assert (__wglob__ (glob_pattern), {glob_pattern});\n%! glob_pattern = fullfile (\"..\", curr_dir, file_in_pwd);\n%! assert (__wglob__ (glob_pattern), {glob_pattern});\n%! glob_pattern = fullfile (\"..\", curr_dir, \"..\", \".\", curr_dir, \".\", file_in_pwd);\n%! assert (__wglob__ (glob_pattern), {glob_pattern});\n\n%!test <*62414>\n%! old_dir = cd (fileparts (which (\"plot.m\")));\n%! unwind_protect\n%!   assert (__wglob__ (fullfile (\".\", \"*.m\")), ...\n%!           fullfile (\".\", __wglob__ (\"*.m\")));\n%! unwind_protect_cleanup\n%!   cd (old_dir);\n%! end_unwind_protect\n\n## retain trailing file separator\n%!test <*62414>\n%! old_dir = cd (fileparts (which (\"plot.m\")));\n%! unwind_protect\n%!   assert (__wglob__ (\"private\"), {\"private\"});\n%!   assert (__wglob__ (\"private/\"), {[\"private\", filesep()]});\n%!   assert (__wglob__ (\"private///\"), {[\"private\", filesep()]});\n%!   assert (__wglob__ (\"./private\"), {fullfile(\".\", \"private\")});\n%!   assert (__wglob__ (\"./private/\"), ...\n%!           {[fullfile(\".\", \"private\"), filesep()]});\n%!   assert (__wglob__ (\"./private///\"), ...\n%!           {[fullfile(\".\", \"private\"), filesep()]});\n%!   assert (__wglob__ ([\"./p*\",\"/\"]), ...\n%!           {[fullfile(\".\", \"private\"), filesep()]});\n%! unwind_protect_cleanup\n%!   cd (old_dir);\n%! end_unwind_protect\n*/\n\nDEFUN (__fnmatch__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{TF} =} fnmatch (@var{pattern}, @var{string})\nReturn true or false for each element of @var{string} that matches any of\nthe elements of the string array @var{pattern}, using the rules of\nfilename pattern matching.\n\nFor example:\n\n@example\n@group\nfnmatch (\"a*b\", @{\"ab\"; \"axyzb\"; \"xyzab\"@})\n     @xresult{} [ 1; 1; 0 ]\n@end group\n@end example\n@seealso{glob, regexp}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  string_vector pat = args(0).string_vector_value ();\n  string_vector str = args(1).string_vector_value ();\n\n  glob_match pattern (sys::file_ops::tilde_expand (pat));\n\n  return ovl (pattern.match (str));\n}\n\nDEFUN (filesep, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{sep} =} filesep ()\n@deftypefnx {} {} filesep (\"all\")\nReturn the system-dependent character used to separate directory names.\n\nIf @qcode{\"all\"} is given, the function returns all valid file separators\nin the form of a string.  The list of file separators is system-dependent.\nIt is @samp{/} (forward slash) under UNIX or @w{Mac OS X}, @samp{/} and\n@samp{\\} (forward and backward slashes) under Windows.\n@seealso{pathsep}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 0)\n    retval = sys::file_ops::dir_sep_str ();\n  else\n    {\n      std::string s = args(0).xstring_value (\"filesep: argument must be a string\");\n      if (s != \"all\")\n        error (R\"(filesep: argument must be \"all\")\");\n\n      retval = sys::file_ops::dir_sep_chars ();\n    }\n\n  return retval;\n}\n\nDEFUN (pathsep, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{val} =} pathsep ()\nQuery the character used to separate directories in a path.\n@seealso{filesep}\n@end deftypefn */)\n{\n  if (args.length () > 0)\n    print_usage ();\n\n  return ovl (directory_path::path_sep_str ());\n}\n\nDEFUN (confirm_recursive_rmdir, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} confirm_recursive_rmdir ()\n@deftypefnx {} {@var{old_val} =} confirm_recursive_rmdir (@var{new_val})\n@deftypefnx {} {@var{old_val} =} confirm_recursive_rmdir (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Octave\nwill ask for confirmation before recursively removing a directory tree.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{rmdir}\n@end deftypefn */)\n{\n  return set_internal_variable (Vconfirm_recursive_rmdir, args, nargout,\n                                \"confirm_recursive_rmdir\");\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/system/dlmread.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Adapted from previous version of dlmread.occ as authored by Kai\n// Habel, but core code has been completely re-written.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <clocale>\n#include <cmath>\n#include <cctype>\n#include <fstream>\n#include <limits>\n\n#include \"file-ops.h\"\n#include \"lo-ieee.h\"\n#include \"oct-sysdep.h\"\n\n#include \"defun.h\"\n#include \"interpreter.h\"\n#include \"oct-stream.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nstatic constexpr octave_idx_type IDX_MAX\n  = std::numeric_limits<octave_idx_type>::max () - 1;\n\nstatic constexpr double IDX_MAX_DBL = double (IDX_MAX);\n\nstatic bool\nread_cell_spec (std::istream& is, octave_idx_type& row, octave_idx_type& col)\n{\n  bool stat = false;\n\n  if (is.peek () == std::istream::traits_type::eof ())\n    stat = true;\n  else\n    {\n      if (::isalpha (is.peek ()))\n        {\n          col = 0;\n          while (is && ::isalpha (is.peek ()))\n            {\n              char ch = is.get ();\n              col *= 26;\n              if (ch >= 'a')\n                col += ch - 'a' + 1;\n              else\n                col += ch - 'A' + 1;\n            }\n          col--;\n\n          if (is)\n            {\n              is >> row;\n              row--;\n              if (is)\n                stat = true;\n            }\n        }\n    }\n\n  return stat;\n}\n\nstatic bool\nparse_range_spec (const octave_value& range_spec,\n                  octave_idx_type& rlo, octave_idx_type& clo,\n                  octave_idx_type& rup, octave_idx_type& cup)\n{\n  bool stat = true;\n\n  if (range_spec.is_string ())\n    {\n      std::istringstream is (range_spec.string_value ());\n      char ch = is.peek ();\n\n      if (ch == '.' || ch == ':')\n        {\n          rlo = 0;\n          clo = 0;\n          ch = is.get ();\n          if (ch == '.')\n            {\n              ch = is.get ();\n              if (ch != '.')\n                stat = false;\n            }\n        }\n      else\n        {\n          stat = read_cell_spec (is, rlo, clo);\n\n          if (stat)\n            {\n              ch = is.peek ();\n\n              if (ch == '.' || ch == ':')\n                {\n                  ch = is.get ();\n                  if (ch == '.')\n                    {\n                      ch = is.get ();\n                      if (! is || ch != '.')\n                        stat = false;\n                    }\n\n                  rup = IDX_MAX;\n                  cup = IDX_MAX;\n                }\n              else\n                {\n                  rup = rlo;\n                  cup = clo;\n                  if (! is || ! is.eof ())\n                    stat = false;\n                }\n            }\n        }\n\n      if (stat && is && ! is.eof ())\n        stat = read_cell_spec (is, rup, cup);\n\n      if (! is || ! is.eof ())\n        stat = false;\n    }\n  else if (range_spec.is_real_matrix () && range_spec.numel () == 4)\n    {\n      NDArray range (range_spec.array_value ());\n      if (range.any_element_is_nan ())\n        error (\"dlmread: NaN is not a valid row or column specifier\");\n\n      // Reject negative indices\n      for (octave_idx_type k = 0; k < 4; k++)\n        {\n          if (range(k) < 0)\n            error (\"dlmread: RANGE indices must be non-negative\");\n        }\n      // Safe type converter double to octave_idx_type\n      auto safe_idx_cast = [] (double val)\n        {\n          if (val >= IDX_MAX_DBL)\n            return IDX_MAX;\n          else\n            return static_cast<octave_idx_type> (val);\n        };\n\n      rlo = safe_idx_cast (range(0));\n      clo = safe_idx_cast (range(1));\n      rup = safe_idx_cast (range(2));\n      cup = safe_idx_cast (range(3));\n    }\n  else\n    stat = false;\n\n  return stat;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFMETHOD (dlmread, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{data} =} dlmread (@var{file})\n@deftypefnx {} {@var{data} =} dlmread (@var{file}, @var{sep})\n@deftypefnx {} {@var{data} =} dlmread (@var{file}, @var{sep}, @var{r0}, @var{c0})\n@deftypefnx {} {@var{data} =} dlmread (@var{file}, @var{sep}, @var{range})\n@deftypefnx {} {@var{data} =} dlmread (@dots{}, \"emptyvalue\", @var{EMPTYVAL})\nRead numeric data from the text file @var{file} which uses the delimiter\n@var{sep} between data values.\n\nIf @var{sep} is not defined the separator between fields is determined from\nthe file itself.\n\nThe optional scalar arguments @var{r0} and @var{c0} define the starting row\nand column of the data to be read.  These values are indexed from zero,\ni.e., the first data row corresponds to an index of zero.\n\nThe @var{range} parameter specifies exactly which data elements are read.\nThe first form of the parameter is a 4-element vector containing the upper\nleft and lower right corners @code{[@var{R0},@var{C0},@var{R1},@var{C1}]}\nwhere the indices are zero-based.  To specify the last column---the equivalent\nof @code{end} when indexing---use the specifier @code{Inf}.  Alternatively, a\nspreadsheet style form such as @qcode{\"A2..Q15\"} or @qcode{\"T1:AA5\"} can be\nused.  The lowest alphabetical index @qcode{'A'} refers to the first column.\nThe lowest row index is 1.\n\n@var{file} should be a filename or a file id given by @code{fopen}.  In the\nlatter case, the file is read until end of file is reached.\n\nThe @qcode{\"emptyvalue\"} option may be used to specify the value used to\nfill empty fields.  The default is zero.  Note that any non-numeric values,\nsuch as text, are also replaced by the @qcode{\"emptyvalue\"}.\n@seealso{csvread, textscan, dlmwrite}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  double empty_value = 0.0;\n\n  if (nargin > 2 && args(nargin-2).is_string ()\n      && args(nargin-2).string_value () == \"emptyvalue\")\n    {\n      empty_value = args(nargin-1).double_value ();\n\n      nargin -= 2;\n    }\n\n  if (nargin < 1 || nargin > 4)\n    print_usage ();\n\n  std::istream *input = nullptr;\n  std::ifstream input_file;\n\n  if (args(0).is_string ())\n    {\n      // Filename.\n      std::string fname (args(0).string_value ());\n\n      std::string tname = sys::file_ops::tilde_expand (fname);\n\n      tname = find_data_file_in_load_path (\"dlmread\", tname);\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n      std::wstring wname = sys::u8_to_wstring (tname);\n      input_file.open (wname.c_str (), std::ios::in);\n#else\n      input_file.open (tname.c_str (), std::ios::in);\n#endif\n\n      if (! input_file)\n        error (\"dlmread: unable to open file '%s'\", fname.c_str ());\n\n      input = &input_file;\n    }\n  else if (args(0).is_scalar_type ())\n    {\n      stream_list& streams = interp.get_stream_list ();\n\n      stream is = streams.lookup (args(0), \"dlmread\");\n\n      input = is.input_stream ();\n\n      if (! input)\n        error (\"dlmread: stream FILE not open for input\");\n    }\n  else\n    error (\"dlmread: FILE argument must be a string or file id\");\n\n  // Set default separator.\n  std::string sep;\n  if (nargin > 1)\n    {\n      if (args(1).is_sq_string ())\n        sep = do_string_escapes (args(1).string_value ());\n      else\n        sep = args(1).string_value ();\n    }\n\n  // Take a subset if a range was given.\n  octave_idx_type r0 = 0;\n  octave_idx_type c0 = 0;\n  octave_idx_type r1 = IDX_MAX;\n  octave_idx_type c1 = IDX_MAX;\n  if (nargin > 2)\n    {\n      if (nargin == 3)\n        {\n          if (! parse_range_spec (args(2), r0, c0, r1, c1))\n            error (\"dlmread: error parsing RANGE\");\n        }\n      else if (nargin == 4)\n        {\n          r0 = args(2).idx_type_value ();\n          c0 = args(3).idx_type_value ();\n        }\n\n      if (r0 < 0 || c0 < 0)\n        error (\"dlmread: left (R0) and top (C0) must be positive\");\n\n      // Short-circuit and return if range is empty\n      if (r1 < r0 || c1 < c0)\n        return ovl (Matrix (0, 0));\n    }\n\n  octave_idx_type i = 0;\n  octave_idx_type j = 0;\n  octave_idx_type r = 1;\n  octave_idx_type c = 1;\n  // Start with a reasonable size to avoid constant resizing of matrix.\n  octave_idx_type rmax = 32;\n  octave_idx_type cmax = 0;\n\n  Matrix rdata (rmax, cmax, empty_value);\n  ComplexMatrix cdata;\n\n  bool iscmplx = false;\n  bool sep_is_wspace = (sep.find_first_of (\" \\t\") != std::string::npos);\n  bool auto_sep_is_wspace = false;\n\n  if (r0 == 0)\n    {\n      // Peek into stream and potentially strip Byte Order Mark (BOM)\n      const char BOM[3] = {'\\xEF', '\\xBB', '\\xBF'};\n      char buf[3];\n      int i_bom;\n      bool found_bom = true;\n      for (i_bom = 0; i_bom < 3; i_bom++)\n        {\n          char ch_p = input->peek ();\n          if (ch_p == BOM[i_bom])\n            buf[i_bom] = input->get ();\n          else\n            {\n              found_bom = false;\n              break;\n            }\n        }\n      // Put back read characters if it wasn't a BOM\n      if (! found_bom)\n        {\n          for (int i_ret = i_bom-1; i_ret >= 0; i_ret--)\n            input->putback (buf[i_ret]);\n        }\n    }\n\n  // Set \"C\" locale for the remainder of this function to avoid the performance\n  // panelty of frequently switching the locale when reading floating point\n  // values from the stream.\n  char *prev_locale = std::setlocale (LC_ALL, nullptr);\n  std::string old_locale (prev_locale ? prev_locale : \"\");\n  std::setlocale (LC_ALL, \"C\");\n  unwind_action act\n  ([old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); });\n\n  std::string line;\n\n  // Skip the r0 leading lines\n  octave_idx_type rcnt = r0;\n  while (rcnt > 0 && getline (*input, line))\n    rcnt--;\n\n  if (rcnt > 0)\n    return ovl (Matrix (0, 0)); // Not enough lines in file to satisfy RANGE\n  else\n    r1 -= r0;\n\n  std::istringstream tmp_stream;\n\n  // Read the data one field at a time, growing the data matrix as needed.\n  while (getline (*input, line))\n    {\n      // Skip blank lines for compatibility.\n      if ((! sep_is_wspace || auto_sep_is_wspace)\n          && line.find_first_not_of (\" \\t\") == std::string::npos)\n        continue;\n\n      // Infer separator from file if delimiter is blank.\n      if (sep.empty ())\n        {\n          // Skip leading whitespace.\n          std::size_t pos1 = line.find_first_not_of (\" \\t\");\n\n          // For Matlab compatibility, blank delimiter should\n          // correspond to whitespace (space and tab).\n          std::size_t n = line.find_first_of (\",:; \\t\", pos1);\n          if (n == std::string::npos)\n            {\n              sep = \" \\t\";\n              auto_sep_is_wspace = true;\n            }\n          else\n            {\n              char ch = line.at (n);\n\n              switch (line.at (n))\n                {\n                case ' ':\n                case '\\t':\n                  sep = \" \\t\";\n                  auto_sep_is_wspace = true;\n                  break;\n\n                default:\n                  sep = ch;\n                  break;\n                }\n            }\n        }\n\n      // Estimate the number of columns from first line of data.\n      if (cmax == 0)\n        {\n          std::size_t pos1, pos2;\n          if (auto_sep_is_wspace)\n            pos1 = line.find_first_not_of (\" \\t\");\n          else\n            pos1 = 0;\n\n          do\n            {\n              pos2 = line.find_first_of (sep, pos1);\n\n              if (auto_sep_is_wspace && pos2 != std::string::npos)\n                {\n                  // Treat consecutive separators as one.\n                  pos2 = line.find_first_not_of (sep, pos2);\n                  if (pos2 != std::string::npos)\n                    pos2 -= 1;\n                }\n\n              // Separator followed by EOL doesn't generate extra column\n              if (pos2 != std::string::npos)\n                cmax++;\n\n              pos1 = pos2 + 1;\n            }\n          while (pos2 != std::string::npos);\n\n          // FIXME: Should always be the case that iscmplx == false.\n          //        Flag is initialized that way and no data has been read.\n          if (iscmplx)\n            cdata.resize (rmax, cmax, empty_value);\n          else\n            rdata.resize (rmax, cmax, empty_value);\n        }\n\n      r = (r > i + 1 ? r : i + 1);\n      j = 0;\n\n      std::size_t pos1, pos2;\n      if (auto_sep_is_wspace)\n        pos1 = line.find_first_not_of (\" \\t\");  // Skip leading whitespace.\n      else\n        pos1 = 0;\n\n      do\n        {\n          octave_quit ();\n\n          pos2 = line.find_first_of (sep, pos1);\n          std::string str = line.substr (pos1, pos2 - pos1);\n\n          if (auto_sep_is_wspace && pos2 != std::string::npos)\n            {\n              // Treat consecutive separators as one.\n              pos2 = line.find_first_not_of (sep, pos2);\n              if (pos2 != std::string::npos)\n                pos2 -= 1;\n              else\n                pos2 = line.length () - 1;\n            }\n\n          // Separator followed by EOL doesn't generate extra column\n          if (pos2 == std::string::npos && str.empty ())\n            break;\n\n          c = (c > j + 1 ? c : j + 1);\n          if (r > rmax || c > cmax)\n            {\n              // Use resize_and_fill for the case of unequal length rows.\n              // Keep rmax a power of 2.\n              rmax = std::max (2*(r-1), rmax);\n              cmax = std::max (c, cmax);\n              if (iscmplx)\n                cdata.resize (rmax, cmax, empty_value);\n              else\n                rdata.resize (rmax, cmax, empty_value);\n            }\n\n          tmp_stream.str (str);\n          tmp_stream.clear ();\n\n          double x = read_value<double> (tmp_stream);\n          if (tmp_stream)\n            {\n              if (tmp_stream.eof ())\n                {\n                  if (iscmplx)\n                    cdata(i, j++) = x;\n                  else\n                    rdata(i, j++) = x;\n                }\n              else\n                {\n                  int next_char = tmp_stream.peek ();\n                  if (next_char == 'i' || next_char == 'j'\n                      || next_char == 'I' || next_char == 'J')\n                    {\n                      // Process pure imaginary numbers.\n                      tmp_stream.get ();\n                      next_char = tmp_stream.peek ();\n                      if (next_char == std::istringstream::traits_type::eof ())\n                        {\n                          if (! iscmplx)\n                            {\n                              iscmplx = true;\n                              cdata = ComplexMatrix (rdata);\n                            }\n\n                          cdata(i, j++) = Complex (0, x);\n                        }\n                      else\n                        {\n                          // Parsing failed, <number>i|j<extra text>\n                          j++;  // Leave data initialized to empty_value\n                        }\n                    }\n                  else if (std::isalpha (next_char) && ! std::isfinite (x))\n                    {\n                      // Parsing failed, <Inf|NA|NaN><extra text>\n                      j++;  // Leave data initialized to empty_value\n                    }\n                  else\n                    {\n                      double y = read_value<double> (tmp_stream);\n\n                      if (! iscmplx && y != 0.0)\n                        {\n                          iscmplx = true;\n                          cdata = ComplexMatrix (rdata);\n                        }\n\n                      if (iscmplx)\n                        cdata(i, j++) = Complex (x, y);\n                      else\n                        rdata(i, j++) = x;\n                    }\n                }\n            }\n          else\n            {\n              // read_value<double>() parsing failed\n              j++;  // Leave data initialized to empty_value\n            }\n\n          pos1 = pos2 + 1;\n        }\n      while (pos2 != std::string::npos);\n\n      if (i == r1)\n        break;  // Stop early if the desired range has been read.\n\n      i++;\n    }\n\n  // Clip selection indices to actual size of data\n  if (r1 >= r)\n    r1 = r - 1;\n  if (c1 >= c)\n    c1 = c - 1;\n\n  if (iscmplx)\n    {\n      if ((i == 0 && j == 0) || (c0 > c1))\n        return ovl (ComplexMatrix (0, 0));\n\n      cdata = cdata.extract (0, c0, r1, c1);\n      return ovl (cdata);\n    }\n  else\n    {\n      if ((i == 0 && j == 0) || (c0 > c1))\n        return ovl (Matrix (0, 0));\n\n      rdata = rdata.extract (0, c0, r1, c1);\n      return ovl (rdata);\n    }\n}\n\n/*\n%!test\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"1, 2, 3\\n4, 5, 6\\n7, 8, 9\\n10, 11, 12\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, 2, 3; 4, 5, 6; 7, 8, 9;10, 11, 12]);\n%!   assert (dlmread (file, \",\"), [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12]);\n%!   assert (dlmread (file, \",\", [1, 0, 2, 1]), [4, 5; 7, 8]);\n%!   assert (dlmread (file, \",\", \"B1..C2\"), [2, 3; 5, 6]);\n%!   assert (dlmread (file, \",\", \"B1:C2\"), [2, 3; 5, 6]);\n%!   assert (dlmread (file, \",\", \"..C2\"), [1, 2, 3; 4, 5, 6]);\n%!   assert (dlmread (file, \",\", 0, 1), [2, 3; 5, 6; 8, 9; 11, 12]);\n%!   assert (dlmread (file, \",\", \"B1..\"), [2, 3; 5, 6; 8, 9; 11, 12]);\n%!   assert (dlmread (file, \",\", 10, 0), []);\n%!   assert (dlmread (file, \",\", 0, 10), []);\n%!   fail ('dlmread (file, \",\", [0 1])', \"error parsing RANGE\");\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"1, 2, 3\\n4+4i, 5, 6\\n7, 8, 9\\n10, 11, 12\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, 2, 3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);\n%!   assert (dlmread (file, \",\"), [1,2,3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);\n%!   assert (dlmread (file, \",\", [1, 0, 2, 1]), [4 + 4i, 5; 7, 8]);\n%!   assert (dlmread (file, \",\", \"A2..B3\"), [4 + 4i, 5; 7, 8]);\n%!   assert (dlmread (file, \",\", \"A2:B3\"), [4 + 4i, 5; 7, 8]);\n%!   assert (dlmread (file, \",\", \"..B3\"), [1, 2; 4 + 4i, 5; 7, 8]);\n%!   assert (dlmread (file, \",\", 1, 0), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);\n%!   assert (dlmread (file, \",\", \"A2..\"), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);\n%!   assert (dlmread (file, \",\", 10, 0), []);\n%!   assert (dlmread (file, \",\", 0, 10), []);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n%!testif HAVE_LLVM_LIBCXX  <47413>\n%! ## Same test code as above, intended only for test statistics with libc++.\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"1, 2, 3\\n4+4i, 5, 6\\n7, 8, 9\\n10, 11, 12\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, 2, 3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);\n%!   assert (dlmread (file, \",\"), [1,2,3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);\n%!   assert (dlmread (file, \",\", [1, 0, 2, 1]), [4 + 4i, 5; 7, 8]);\n%!   assert (dlmread (file, \",\", \"A2..B3\"), [4 + 4i, 5; 7, 8]);\n%!   assert (dlmread (file, \",\", \"A2:B3\"), [4 + 4i, 5; 7, 8]);\n%!   assert (dlmread (file, \",\", \"..B3\"), [1, 2; 4 + 4i, 5; 7, 8]);\n%!   assert (dlmread (file, \",\", 1, 0), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);\n%!   assert (dlmread (file, \",\", \"A2..\"), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);\n%!   assert (dlmread (file, \",\", 10, 0), []);\n%!   assert (dlmread (file, \",\", 0, 10), []);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n%!test <*42025>\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"    \\n 1 2\\n11 22\\n \");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, 2; 11, 22]);\n%!   assert (dlmread (file, \" \"), [ 0,  0, 0, 0\n%!                                  0,  1, 2, 0\n%!                                 11, 22, 0, 0\n%!                                  0,  0, 0, 0]);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")  <*50589>\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"1;2;3\\n\");\n%!   fwrite (fid, \"1i;2I;3j;4J\\n\");\n%!   fwrite (fid, \"4;5;6\\n\");\n%!   fwrite (fid, \"-4i;+5I;-6j;+7J\\n\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, 2, 3, 0; 1i, 2i, 3i, 4i;\n%!                            4, 5, 6, 0; -4i, 5i, -6i, 7i]);\n%!   assert (dlmread (file, \"\", [0 0 0 3]), [1, 2, 3]);\n%!   assert (dlmread (file, \"\", [1 0 1 3]), [1i, 2i, 3i, 4i]);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n%!testif HAVE_LLVM_LIBCXX  <47413>\n%! ## Same test code as above, intended only for test statistics with libc++.\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"1;2;3\\n\");\n%!   fwrite (fid, \"1i;2I;3j;4J\\n\");\n%!   fwrite (fid, \"4;5;6\\n\");\n%!   fwrite (fid, \"-4i;+5I;-6j;+7J\\n\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, 2, 3, 0; 1i, 2i, 3i, 4i;\n%!                            4, 5, 6, 0; -4i, 5i, -6i, 7i]);\n%!   assert (dlmread (file, \"\", [0 0 0 3]), [1, 2, 3]);\n%!   assert (dlmread (file, \"\", [1 0 1 3]), [1i, 2i, 3i, 4i]);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n## NA was not properly read from a file\n%!test\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"1,NA,3\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, NA, 3]);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n## \"Name\" was read as NA rather than parse error\n%!test <*54029>\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"NaNe,bNa,Name,c\\n1,NaN,3,Inftest\\n-Inf,6,NA,8\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [0, 0, 0, 0; 1, NaN, 3, 0; -Inf, 6, NA, 8]);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n## Infinity incorrectly changed matrix to complex, rather than parse error\n%!test\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"1,Infinity,3\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, 0, 3]);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n## Purely complex numbers with trailing garbage produced complex matrix\n%!test\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, \"1,2jack,3\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, 0, 3]);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n## Verify UTF-8 Byte Order Mark does not cause problems with reading\n%!test <*58813>\n%! file = tempname ();\n%! unwind_protect\n%!   fid = fopen (file, \"wt\");\n%!   fwrite (fid, char ([0xEF, 0xBB, 0xBF]));  # UTF-8 BOM\n%!   fwrite (fid, \"1,2\\n3,4\");\n%!   fclose (fid);\n%!\n%!   assert (dlmread (file), [1, 2; 3, 4]);\n%! unwind_protect_cleanup\n%!   unlink (file);\n%! end_unwind_protect\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/system/getgrent.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include <sys/types.h>\n\n#include \"oct-group.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Group file functions.  (Why not?)\n\nstatic octave_value\nmk_gr_map (const sys::group& gr)\n{\n  if (gr)\n    {\n      octave_scalar_map m;\n\n      m.assign (\"name\", gr.name ());\n      m.assign (\"passwd\", gr.passwd ());\n      m.assign (\"gid\", static_cast<double> (gr.gid ()));\n      m.assign (\"mem\", octave_value (gr.mem ()));\n\n      return octave_value (m);\n    }\n  else\n    return octave_value (0);\n}\n\nDEFUN (getgrent, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{grp_struct} =} getgrent ()\nReturn an entry from the group database, opening it if necessary.\n\nOnce the end of data has been reached, @code{getgrent} returns 0.\n@seealso{setgrent, endgrent}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  std::string msg;\n\n  // sys::group::getgrent may set msg.\n  octave_value val = mk_gr_map (sys::group::getgrent (msg));\n\n  return ovl (val, msg);\n}\n\nDEFUN (getgrgid, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{grp_struct} =} getgrgid (@var{gid}).\nReturn the first entry from the group database with the group ID\n@var{gid}.\n\nIf the group ID does not exist in the database, @code{getgrgid} returns 0.\n@seealso{getgrnam}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double dval = args(0).double_value ();\n\n  if (math::round (dval) != dval)\n    error (\"getgrgid: GID must be an integer\");\n\n  gid_t gid = static_cast<gid_t> (dval);\n\n  std::string msg;\n\n  // sys::group::getgrgid may set msg.\n  octave_value val = mk_gr_map (sys::group::getgrgid (gid, msg));\n\n  return ovl (val, msg);\n}\n\nDEFUN (getgrnam, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{grp_struct} =} getgrnam (@var{name})\nReturn the first entry from the group database with the group name\n@var{name}.\n\nIf the group name does not exist in the database, @code{getgrnam} returns 0.\n@seealso{getgrgid}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string s = args(0).string_value ();\n\n  std::string msg;\n\n  // sys::group::getgrnam may set msg.\n  octave_value val = mk_gr_map (sys::group::getgrnam (s.c_str (), msg));\n\n  return ovl (val, msg);\n}\n\nDEFUN (setgrent, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{status}, @var{msg}] =} setgrent ()\nReturn the internal pointer to the beginning of the group database.\n@seealso{getgrent, endgrent}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  std::string msg;\n\n  // sys::group::setgrent may set msg.\n  int status = sys::group::setgrent (msg);\n\n  return ovl (static_cast<double> (status), msg);\n}\n\nDEFUN (endgrent, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{status}, @var{msg}] =} endgrent ()\nClose the group database.\n@seealso{getgrent, setgrent}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  std::string msg;\n\n  // sys::group::endgrent may set msg.\n  int status = sys::group::endgrent (msg);\n\n  return ovl (static_cast<double> (status), msg);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/system/getpwent.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include <sys/types.h>\n\n#include \"oct-password.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Password file functions.  (Why not?)\n\nstatic octave_value\nmk_pw_map (const sys::password& pw)\n{\n  octave_value retval;\n\n  if (pw)\n    {\n      octave_scalar_map m;\n\n      m.assign (\"name\", pw.name ());\n      m.assign (\"passwd\", pw.passwd ());\n      m.assign (\"uid\", static_cast<double> (pw.uid ()));\n      m.assign (\"gid\", static_cast<double> (pw.gid ()));\n      m.assign (\"gecos\", pw.gecos ());\n      m.assign (\"dir\", pw.dir ());\n      m.assign (\"shell\", pw.shell ());\n\n      return octave_value (m);\n    }\n  else\n    return octave_value (0);\n}\n\nDEFUN (getpwent, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{pw_struct} =} getpwent ()\nReturn a structure containing an entry from the password database,\nopening it if necessary.\n\nOnce the end of the data has been reached, @code{getpwent} returns 0.\n@seealso{setpwent, endpwent}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  std::string msg;\n\n  // sys::password::getpwent may set msg.\n  octave_value val = mk_pw_map (sys::password::getpwent (msg));\n\n  return ovl (val, msg);\n}\n\nDEFUN (getpwuid, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{pw_struct} =} getpwuid (@var{uid}).\nReturn a structure containing the first entry from the password database\nwith the user ID @var{uid}.\n\nIf the user ID does not exist in the database, @code{getpwuid} returns 0.\n@seealso{getpwnam}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double dval = args(0).double_value ();\n\n  if (math::round (dval) != dval)\n    error (\"getpwuid: UID must be an integer\");\n\n  uid_t uid = static_cast<uid_t> (dval);\n\n  std::string msg;\n\n  // sys::password::getpwuid may set msg.\n  octave_value val = mk_pw_map (sys::password::getpwuid (uid, msg));\n\n  return ovl (val, msg);\n}\n\nDEFUN (getpwnam, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{pw_struct} =} getpwnam (@var{name})\nReturn a structure containing the first entry from the password database\nwith the user name @var{name}.\n\nIf the user name does not exist in the database, @code{getpwname} returns 0.\n@seealso{getpwuid}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string s = args(0).string_value ();\n\n  std::string msg;\n\n  // sys::password::getpwnam may set msg.\n  octave_value val = mk_pw_map (sys::password::getpwnam (s, msg));\n\n  return ovl (val, msg);\n}\n\nDEFUN (setpwent, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{status}, @var{msg}] =} setpwent ()\nReturn the internal pointer to the beginning of the password database.\n@seealso{getpwent, endpwent}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  std::string msg;\n\n  // sys::password::setpwent may set msg.\n  int status = sys::password::setpwent (msg);\n\n  return ovl (static_cast<double> (status), msg);\n}\n\nDEFUN (endpwent, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{status}, @var{msg}] =} endpwent ()\nClose the password database.\n@seealso{getpwent, setpwent}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  std::string msg;\n\n  // sys::password::endpwent may set msg.\n  int status = sys::password::endpwent (msg);\n\n  return ovl (static_cast<double> (status), msg);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/system/getrusage.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-time.h\"\n\n#include \"defun.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (getrusage, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{procstats} =} getrusage ()\nReturn a structure containing a number of statistics about the current\nOctave process.\n\nNot all fields are available on all systems.  If it is not possible to get\nCPU time statistics, the CPU time slots are set to zero.  Other missing data\nare replaced by NaN@.  The list of possible fields is:\n\n@table @code\n@item idrss\nUnshared data size.\n\n@item inblock\nNumber of block input operations.\n\n@item isrss\nUnshared stack size.\n\n@item ixrss\nShared memory size.\n\n@item majflt\nNumber of major page faults.\n\n@item maxrss\nMaximum data size.\n\n@item minflt\nNumber of minor page faults.\n\n@item msgrcv\nNumber of messages received.\n\n@item msgsnd\nNumber of messages sent.\n\n@item nivcsw\nNumber of involuntary context switches.\n\n@item nsignals\nNumber of signals received.\n\n@item nswap\nNumber of swaps.\n\n@item nvcsw\nNumber of voluntary context switches.\n\n@item oublock\nNumber of block output operations.\n\n@item stime\nA structure containing the system CPU time used.  The structure has the\nelements @code{sec} (seconds) @code{usec} (microseconds).\n\n@item utime\nA structure containing the user CPU time used.  The structure has the\nelements @code{sec} (seconds) @code{usec} (microseconds).\n@end table\n@end deftypefn */)\n{\n  octave_scalar_map ru_map;\n  octave_scalar_map tv_map;\n\n  sys::resource_usage rusage;\n\n  sys::cpu_time cpu = rusage.cpu ();\n\n  tv_map.assign (\"sec\", cpu.user_sec ());\n  tv_map.assign (\"usec\", cpu.user_usec ());\n  ru_map.assign (\"utime\", octave_value (tv_map));\n\n  tv_map.assign (\"sec\", cpu.system_sec ());\n  tv_map.assign (\"usec\", cpu.system_usec ());\n  ru_map.assign (\"stime\", octave_value (tv_map));\n\n  ru_map.assign (\"maxrss\", static_cast<double> (rusage.maxrss ()));\n  ru_map.assign (\"ixrss\", static_cast<double> (rusage.ixrss ()));\n  ru_map.assign (\"idrss\", static_cast<double> (rusage.idrss ()));\n  ru_map.assign (\"isrss\", static_cast<double> (rusage.isrss ()));\n  ru_map.assign (\"minflt\", static_cast<double> (rusage.minflt ()));\n  ru_map.assign (\"majflt\", static_cast<double> (rusage.majflt ()));\n  ru_map.assign (\"nswap\", static_cast<double> (rusage.nswap ()));\n  ru_map.assign (\"inblock\", static_cast<double> (rusage.inblock ()));\n  ru_map.assign (\"oublock\", static_cast<double> (rusage.oublock ()));\n  ru_map.assign (\"msgsnd\", static_cast<double> (rusage.msgsnd ()));\n  ru_map.assign (\"msgrcv\", static_cast<double> (rusage.msgrcv ()));\n  ru_map.assign (\"nsignals\", static_cast<double> (rusage.nsignals ()));\n  ru_map.assign (\"nvcsw\", static_cast<double> (rusage.nvcsw ()));\n  ru_map.assign (\"nivcsw\", static_cast<double> (rusage.nivcsw ()));\n\n  return ovl (ru_map);\n}\n\n/*\n%!test\n%! r = getrusage ();\n%! assert (isstruct (r));\n%! assert (isfield (r, \"idrss\"));\n%! assert (isfield (r, \"inblock\"));\n%! assert (isfield (r, \"isrss\"));\n%! assert (isfield (r, \"ixrss\"));\n%! assert (isfield (r, \"majflt\"));\n%! assert (isfield (r, \"maxrss\"));\n%! assert (isfield (r, \"minflt\"));\n%! assert (isfield (r, \"msgrcv\"));\n%! assert (isfield (r, \"msgsnd\"));\n%! assert (isfield (r, \"nivcsw\"));\n%! assert (isfield (r, \"nsignals\"));\n%! assert (isfield (r, \"nswap\"));\n%! assert (isfield (r, \"nvcsw\"));\n%! assert (isfield (r, \"oublock\"));\n%! assert (isfield (r, \"stime\"));\n%! assert (isfield (r, \"utime\"));\n%! assert (isfield (r.stime, \"sec\"));\n%! assert (isfield (r.stime, \"usec\"));\n%! assert (isfield (r.utime, \"sec\"));\n%! assert (isfield (r.utime, \"usec\"));\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/system/mk-errno-list.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nif [ $# -ne 2 ]; then\n  echo \"usage: get-errno-list [--perl PERL|--python PYTHON|--sed SED]\" 1>&2\n  exit 1\nfi\n\nif [ $1 = \"--perl\" ]; then\n  PERL=\"$2\"\n  $PERL -e 'foreach $key (sort (keys (%!))) {\n    $x .= \"#if defined ($key)\\n    { \\\"$key\\\", $key },\\n#endif\\n\";\n  }\n  while (<>) {\n    s/^ *\\@SYSDEP_ERRNO_LIST\\@/$x/;\n    s/\\@NO_EDIT_WARNING\\@/DO NOT EDIT!  Generated automatically from oct-errno.in.cc by mk-errno-list.sh/;\n    print;\n  }'\n\nelif [ $1 = \"--python\" ]; then\n  PYTHON=\"$2\"\n  $PYTHON -c '\nfrom errno import errorcode\nfrom sys import stdin, stdout\n\nt = \"#if defined (%s)\\n    { \\\"%s\\\", %s },\\n#endif\\n\"\nerrstr = \"\"\nfor v in sorted (errorcode.values ()):\n    errstr += t % tuple (3 * [v])\n\nnoedit = \"DO NOT EDIT!  Generated automatically from oct-errno.in.cc by mk-errno-list.sh\"\n\nrepls = (\"@SYSDEP_ERRNO_LIST@\", errstr), (\"@NO_EDIT_WARNING@\", noedit)\n\nfor l in stdin:\n  stdout.write (reduce (lambda a, kv: a.replace (*kv), repls, l))\n'\nelif [ $1 = \"--sed\" ]; then\n  SED=\"$2\"\n  $SED -e '/@SYSDEP_ERRNO_LIST@/D' \\\n       -e 's/@NO_EDIT_WARNING@/DO NOT EDIT!  Generated automatically from oct-errno.in.cc by mk-errno-list.sh/'\nfi\n\nexit $?\n"
  },
  {
    "path": "libinterp/corefcn/system/module.mk",
    "content": "DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nCOREFCN_SYSTEM_SRC = \\\n  %reldir%/__ftp__.cc \\\n  %reldir%/dirfns.cc \\\n  %reldir%/dlmread.cc \\\n  %reldir%/getgrent.cc \\\n  %reldir%/getpwent.cc \\\n  %reldir%/getrusage.cc \\\n  %reldir%/nproc.cc \\\n  %reldir%/syscalls.cc \\\n  %reldir%/time.cc \\\n  %reldir%/urlwrite.cc\n\n%reldir%/oct-errno.cc: %reldir%/oct-errno.in.cc %reldir%/mk-errno-list.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t && \\\n\tif test -n \"$(PERL)\"; then \\\n\t  $(SHELL) $(srcdir)/%reldir%/mk-errno-list.sh --perl \"$(PERL)\" < $< > $@-t; \\\n\telif test -n \"$(PYTHON)\"; then \\\n\t  $(SHELL) $(srcdir)/%reldir%/mk-errno-list.sh --python \"$(PYTHON)\" < $< > $@-t; \\\n\telse \\\n\t  $(SHELL) $(srcdir)/%reldir%/mk-errno-list.sh --sed \"$(SED)\" < $< > $@-t; \\\n\tfi && \\\n\tmv $@-t $@\n\nnoinst_LTLIBRARIES += \\\n  %reldir%/libsystem.la\n\n%canon_reldir%_libsystem_la_SOURCES = $(COREFCN_SYSTEM_SRC)\n\n%canon_reldir%_libsystem_la_CPPFLAGS = \\\n  $(libinterp_liboctinterp_la_CPPFLAGS)\n\nlibinterp_EXTRA_DIST += \\\n  %reldir%/mk-errno-list.sh \\\n  %reldir%/oct-errno.in.cc\n\nlibinterp_liboctinterp_la_LIBADD += %reldir%/libsystem.la\n"
  },
  {
    "path": "libinterp/corefcn/system/nproc.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"nproc-wrapper.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (nproc, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{n} =} nproc ()\n@deftypefnx {} {@var{n} =} nproc (@var{query})\nReturn the current number of available (logical) processors.\n\nThis returns the number of logical processors.  For processors with\nhyperthreading, this is larger than the number of physical cores.\n\nIf called with the optional argument @var{query}, modify how processors\nare counted as follows:\n\n@table @code\n@item all\ntotal number of processors.\n\n@item current\nprocessors available to the current process.\n\n@item overridable\nsame as @code{current}, but overridable through the\n@w{@env{OMP_NUM_THREADS}}@ environment variable.\n@end table\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  octave_nproc_query query = OCTAVE_NPROC_CURRENT_OVERRIDABLE;\n\n  if (nargin == 1)\n    {\n      std::string arg = args(0).string_value ();\n\n      std::transform (arg.begin (), arg.end (), arg.begin (), tolower);\n\n      if (arg == \"all\")\n        query = OCTAVE_NPROC_ALL;\n      else if (arg == \"current\")\n        query = OCTAVE_NPROC_CURRENT;\n      else if (arg == \"overridable\")\n        query = OCTAVE_NPROC_CURRENT_OVERRIDABLE;\n      else\n        error (\"nproc: invalid value for QUERY\");\n    }\n\n  return ovl (octave_num_processors_wrapper (query));\n}\n\n/*\n## Must always report at least 1 cpu available\n%!assert (nproc () >= 1)\n%!assert (nproc (\"all\") >= 1)\n%!assert (nproc (\"current\") >= 1)\n\n## Test that \"overridable\" is the default\n%!assert (nproc (\"overridable\"), nproc ())\n\n%!test\n%! c = nproc (\"current\");\n%! unwind_protect\n%!   old_val = getenv (\"OMP_NUM_THREADS\");\n%!   new_val = c + 1;\n%!   setenv (\"OMP_NUM_THREADS\", num2str (new_val));\n%!   assert (nproc (\"overridable\"), new_val);\n%! unwind_protect_cleanup\n%!   if (! isempty (old_val))\n%!     setenv (\"OMP_NUM_THREADS\", old_val);\n%!   else\n%!     unsetenv (\"OMP_NUM_THREADS\");\n%!   endif\n%! end_unwind_protect\n\n%!error nproc (\"no_valid_option\")\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/system/oct-errno.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n\n#include \"singleton-cleanup.h\"\n\n#include \"oct-errno.h\"\n#include \"oct-map.h\"\n#include \"error.h\"\n\noctave_errno *octave_errno::s_instance = nullptr;\n\noctave_errno::octave_errno ()\n{\n  struct errno_struct\n  {\n    const char *name;\n    int value;\n  };\n\n  static errno_struct errno_codes[] =\n  {\n    // POSIX.\n\n#if defined (E2BIG)\n    { \"E2BIG\", E2BIG },\n#endif\n#if defined (EACCES)\n    { \"EACCES\", EACCES },\n#endif\n#if defined (EADDRINUSE)\n    { \"EADDRINUSE\", EADDRINUSE },\n#endif\n#if defined (EADDRNOTAVAIL)\n    { \"EADDRNOTAVAIL\", EADDRNOTAVAIL },\n#endif\n#if defined (EAFNOSUPPORT)\n    { \"EAFNOSUPPORT\", EAFNOSUPPORT },\n#endif\n#if defined (EAGAIN)\n    { \"EAGAIN\", EAGAIN },\n#endif\n#if defined (EALREADY)\n    { \"EALREADY\", EALREADY },\n#endif\n#if defined (EBADF)\n    { \"EBADF\", EBADF },\n#endif\n#if defined (EBUSY)\n    { \"EBUSY\", EBUSY },\n#endif\n#if defined (ECHILD)\n    { \"ECHILD\", ECHILD },\n#endif\n#if defined (ECONNABORTED)\n    { \"ECONNABORTED\", ECONNABORTED },\n#endif\n#if defined (ECONNREFUSED)\n    { \"ECONNREFUSED\", ECONNREFUSED },\n#endif\n#if defined (ECONNRESET)\n    { \"ECONNRESET\", ECONNRESET },\n#endif\n#if defined (EDEADLK)\n    { \"EDEADLK\", EDEADLK },\n#endif\n#if defined (EDESTADDRREQ)\n    { \"EDESTADDRREQ\", EDESTADDRREQ },\n#endif\n#if defined (EDOM)\n    { \"EDOM\", EDOM },\n#endif\n#if defined (EDQUOT)\n    { \"EDQUOT\", EDQUOT },\n#endif\n#if defined (EEXIST)\n    { \"EEXIST\", EEXIST },\n#endif\n#if defined (EFAULT)\n    { \"EFAULT\", EFAULT },\n#endif\n#if defined (EFBIG)\n    { \"EFBIG\", EFBIG },\n#endif\n#if defined (EHOSTDOWN)\n    { \"EHOSTDOWN\", EHOSTDOWN },\n#endif\n#if defined (EHOSTUNREACH)\n    { \"EHOSTUNREACH\", EHOSTUNREACH },\n#endif\n#if defined (EINPROGRESS)\n    { \"EINPROGRESS\", EINPROGRESS },\n#endif\n#if defined (EINTR)\n    { \"EINTR\", EINTR },\n#endif\n#if defined (EINVAL)\n    { \"EINVAL\", EINVAL },\n#endif\n#if defined (EIO)\n    { \"EIO\", EIO },\n#endif\n#if defined (EISCONN)\n    { \"EISCONN\", EISCONN },\n#endif\n#if defined (EISDIR)\n    { \"EISDIR\", EISDIR },\n#endif\n#if defined (ELOOP)\n    { \"ELOOP\", ELOOP },\n#endif\n#if defined (EMFILE)\n    { \"EMFILE\", EMFILE },\n#endif\n#if defined (EMLINK)\n    { \"EMLINK\", EMLINK },\n#endif\n#if defined (EMSGSIZE)\n    { \"EMSGSIZE\", EMSGSIZE },\n#endif\n#if defined (ENAMETOOLONG)\n    { \"ENAMETOOLONG\", ENAMETOOLONG },\n#endif\n#if defined (ENETDOWN)\n    { \"ENETDOWN\", ENETDOWN },\n#endif\n#if defined (ENETRESET)\n    { \"ENETRESET\", ENETRESET },\n#endif\n#if defined (ENETUNREACH)\n    { \"ENETUNREACH\", ENETUNREACH },\n#endif\n#if defined (ENFILE)\n    { \"ENFILE\", ENFILE },\n#endif\n#if defined (ENOBUFS)\n    { \"ENOBUFS\", ENOBUFS },\n#endif\n#if defined (ENODEV)\n    { \"ENODEV\", ENODEV },\n#endif\n#if defined (ENOENT)\n    { \"ENOENT\", ENOENT },\n#endif\n#if defined (ENOEXEC)\n    { \"ENOEXEC\", ENOEXEC },\n#endif\n#if defined (ENOLCK)\n    { \"ENOLCK\", ENOLCK },\n#endif\n#if defined (ENOMEM)\n    { \"ENOMEM\", ENOMEM },\n#endif\n#if defined (ENOPROTOOPT)\n    { \"ENOPROTOOPT\", ENOPROTOOPT },\n#endif\n#if defined (ENOSPC)\n    { \"ENOSPC\", ENOSPC },\n#endif\n#if defined (ENOSYS)\n    { \"ENOSYS\", ENOSYS },\n#endif\n#if defined (ENOTBLK)\n    { \"ENOTBLK\", ENOTBLK },\n#endif\n#if defined (ENOTCONN)\n    { \"ENOTCONN\", ENOTCONN },\n#endif\n#if defined (ENOTDIR)\n    { \"ENOTDIR\", ENOTDIR },\n#endif\n#if defined (ENOTEMPTY)\n    { \"ENOTEMPTY\", ENOTEMPTY },\n#endif\n#if defined (ENOTSOCK)\n    { \"ENOTSOCK\", ENOTSOCK },\n#endif\n#if defined (ENOTTY)\n    { \"ENOTTY\", ENOTTY },\n#endif\n#if defined (ENXIO)\n    { \"ENXIO\", ENXIO },\n#endif\n#if defined (EOPNOTSUPP)\n    { \"EOPNOTSUPP\", EOPNOTSUPP },\n#endif\n#if defined (EPERM)\n    { \"EPERM\", EPERM },\n#endif\n#if defined (EPFNOSUPPORT)\n    { \"EPFNOSUPPORT\", EPFNOSUPPORT },\n#endif\n#if defined (EPIPE)\n    { \"EPIPE\", EPIPE },\n#endif\n#if defined (EPROTONOSUPPORT)\n    { \"EPROTONOSUPPORT\", EPROTONOSUPPORT },\n#endif\n#if defined (EPROTOTYPE)\n    { \"EPROTOTYPE\", EPROTOTYPE },\n#endif\n#if defined (ERANGE)\n    { \"ERANGE\", ERANGE },\n#endif\n#if defined (EREMOTE)\n    { \"EREMOTE\", EREMOTE },\n#endif\n#if defined (ERESTART)\n    { \"ERESTART\", ERESTART },\n#endif\n#if defined (EROFS)\n    { \"EROFS\", EROFS },\n#endif\n#if defined (ESHUTDOWN)\n    { \"ESHUTDOWN\", ESHUTDOWN },\n#endif\n#if defined (ESOCKTNOSUPPORT)\n    { \"ESOCKTNOSUPPORT\", ESOCKTNOSUPPORT },\n#endif\n#if defined (ESPIPE)\n    { \"ESPIPE\", ESPIPE },\n#endif\n#if defined (ESRCH)\n    { \"ESRCH\", ESRCH },\n#endif\n#if defined (ESTALE)\n    { \"ESTALE\", ESTALE },\n#endif\n#if defined (ETIMEDOUT)\n    { \"ETIMEDOUT\", ETIMEDOUT },\n#endif\n#if defined (ETOOMANYREFS)\n    { \"ETOOMANYREFS\", ETOOMANYREFS },\n#endif\n#if defined (ETXTBSY)\n    { \"ETXTBSY\", ETXTBSY },\n#endif\n#if defined (EUSERS)\n    { \"EUSERS\", EUSERS },\n#endif\n#if defined (EWOULDBLOCK)\n    { \"EWOULDBLOCK\", EWOULDBLOCK },\n#endif\n#if defined (EXDEV)\n    { \"EXDEV\", EXDEV },\n#endif\n\n    // Others (duplicates are OK).\n\n    @SYSDEP_ERRNO_LIST@\n\n    { nullptr, 0 },\n  };\n\n  // Stuff them all in a map for fast access.\n\n  errno_struct *ptr = errno_codes;\n\n  while (ptr->name)\n    {\n      m_errno_tbl[ptr->name] = ptr->value;\n      ptr++;\n    }\n}\n\nbool\noctave_errno::instance_ok ()\n{\n  bool retval = true;\n\n  if (! s_instance)\n    {\n      s_instance = new octave_errno ();\n      singleton_cleanup_list::add (cleanup_instance);\n    }\n\n  return retval;\n}\n\nint\noctave_errno::lookup (const std::string& name)\n{\n  return (instance_ok ()) ? s_instance->do_lookup (name) : -1;\n}\n\noctave_scalar_map\noctave_errno::list ()\n{\n  return (instance_ok ()) ? s_instance->do_list () : octave_scalar_map ();\n}\n\nint\noctave_errno::do_lookup (const std::string& name)\n{\n  return (m_errno_tbl.find (name) != m_errno_tbl.end ()) ? m_errno_tbl[name]\n         : -1;\n}\n\noctave_scalar_map\noctave_errno::do_list ()\n{\n  octave_scalar_map retval;\n\n  for (const auto& p : m_errno_tbl)\n    {\n      retval.assign (p.first, p.second);\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/corefcn/system/syscalls.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Thomas Baier <baier@ci.tuwien.ac.at> added the original versions of\n// the following functions:\n//\n//   mkfifo  unlink  waitpid\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdio>\n#include <cstdlib>\n\n#include \"_Exit-wrapper.h\"\n#include \"cmd-hist.h\"\n#include \"fcntl-wrappers.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"lo-utils.h\"\n#include \"oct-env.h\"\n#include \"oct-syscalls.h\"\n#include \"oct-uname.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"event-manager.h\"\n#include \"input.h\"\n#include \"interpreter.h\"\n#include \"oct-hist.h\"\n#include \"oct-map.h\"\n#include \"oct-stdstrm.h\"\n#include \"oct-stream.h\"\n#include \"ovl.h\"\n#include \"sysdep.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic octave_scalar_map\nmk_stat_map (const sys::base_file_stat& fs)\n{\n  static bool have_rdev\n    = sys::base_file_stat::have_struct_stat_st_rdev ();\n  static bool have_blksize\n    = sys::base_file_stat::have_struct_stat_st_blksize ();\n  static bool have_blocks\n    = sys::base_file_stat::have_struct_stat_st_blocks ();\n\n  static double nan = numeric_limits<double>::NaN ();\n\n  octave_scalar_map m;\n\n  m.assign (\"dev\", static_cast<double> (fs.dev ()));\n  m.assign (\"ino\", fs.ino ());\n  m.assign (\"mode\", fs.mode ());\n  m.assign (\"modestr\", fs.mode_as_string ());\n  m.assign (\"nlink\", fs.nlink ());\n  m.assign (\"uid\", fs.uid ());\n  m.assign (\"gid\", fs.gid ());\n  m.assign (\"rdev\", have_rdev ? static_cast<double> (fs.rdev ()) : nan);\n  m.assign (\"size\", fs.size ());\n  m.assign (\"atime\", fs.atime ());\n  m.assign (\"mtime\", fs.mtime ());\n  m.assign (\"ctime\", fs.ctime ());\n\n  if (have_blksize)\n    m.assign (\"blksize\", fs.blksize ());\n  else\n    m.assign (\"blksize\", nan);\n\n  if (have_blocks)\n    m.assign (\"blocks\", fs.blocks ());\n  else\n    m.assign (\"blocks\", nan);\n\n  return m;\n}\n\nstatic octave_value_list\nmk_stat_result (const sys::base_file_stat& fs)\n{\n  if (fs)\n    return ovl (octave_value (mk_stat_map (fs)), 0, \"\");\n  else\n    return ovl (Matrix (), -1, fs.error ());\n}\n\nDEFMETHODX (\"dup2\", Fdup2, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{fid}, @var{msg}] =} dup2 (@var{old}, @var{new})\nDuplicate a file descriptor.\n\nIf successful, @var{fid} is greater than zero and contains the new file ID@.\nOtherwise, @var{fid} is negative and @var{msg} contains a system-dependent\nerror message.\n@seealso{fopen, fclose, fcntl}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  int i_old, i_new;\n  try\n    {\n      // Look up FID in Octave's list of open streams.\n      stream_list& streams = interp.get_stream_list ();\n\n      stream old_stream = streams.lookup (args(0), \"dup2\");\n      stream new_stream = streams.lookup (args(1), \"dup2\");\n\n      i_old = old_stream.file_number ();\n      i_new = new_stream.file_number ();\n    }\n  catch (execution_exception& ee)\n    {\n      // If the FIDs are not known to Octave, try the provided FIDs directly.\n      i_old = args(0).int_value (true);\n      i_new = args(1).int_value (true);\n    }\n\n  if (i_old < 0 || i_new < 0)\n    // Bad FIDs, return error immediately\n    return ovl (-1, \"\");\n\n  std::string msg;\n\n  int status = sys::dup2 (i_old, i_new, msg);\n\n  return ovl (status, msg);\n}\n\nDEFMETHODX (\"exec\", Fexec, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{err}, @var{msg}] =} exec (@var{file}, @var{args})\nReplace current process with a new process.\n\nCalling @code{exec} without first calling @code{fork} will terminate your\ncurrent Octave process and replace it with the program named by @var{file}.\nFor example,\n\n@example\nexec (\"ls\", \"-l\")\n@end example\n\n@noindent\nwill run @code{ls} and return you to your shell prompt.\n\nIf successful, @code{exec} does not return.  If @code{exec} does return,\n@var{err} will be nonzero, and @var{msg} will contain a system-dependent\nerror message.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string exec_file = args(0).xstring_value (\"exec: FILE must be a string\");\n\n  string_vector exec_args;\n\n  if (nargin == 2)\n    {\n      string_vector tmp = args(1).xstring_vector_value (\"exec: all arguments must be strings\");\n\n      int len = tmp.numel ();\n\n      exec_args.resize (len + 1);\n\n      exec_args[0] = exec_file;\n\n      for (int i = 0; i < len; i++)\n        exec_args[i+1] = tmp[i];\n    }\n  else\n    {\n      exec_args.resize (1);\n\n      exec_args[0] = exec_file;\n    }\n\n  history_system& history_sys = interp.get_history_system ();\n\n  history_sys.write_timestamp ();\n\n  if (! command_history::ignoring_entries ())\n    command_history::clean_up_and_save ();\n\n  std::string msg;\n\n  int status = sys::execvp (exec_file, exec_args, msg);\n\n  return ovl (status, msg);\n}\n\nDEFMETHODX (\"popen2\", Fpopen2, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{in}, @var{out}, @var{pid}] =} popen2 (@var{command}, @var{args})\nStart a subprocess with two-way communication.\n\nThe name of the process is given by @var{command}, and @var{args} is an\narray or cell array of strings containing options for the command.\n\nThe file identifiers for the input and output streams of the subprocess are\nreturned in @var{in} and @var{out}.  If execution of the command is\nsuccessful, @var{pid} contains the process ID of the subprocess.  Otherwise,\n@var{pid} is @minus{}1.\n\nFor example:\n\n@example\n[in, out, pid] = popen2 (\"sort\", \"-r\");\nfputs (in, \"these\\nare\\nsome\\nstrings\\n\");\nfclose (in);\nEAGAIN = errno (\"EAGAIN\");\ndone = false;\ndo\n  s = fgets (out);\n  if (ischar (s))\n    fputs (stdout, s);\n  elseif (errno () == EAGAIN)\n    pause (0.1);\n    fclear (out);\n  else\n    done = true;\n  endif\nuntil (done)\nfclose (out);\nwaitpid (pid);\n\n   @print{} these\n   @print{} strings\n   @print{} some\n   @print{} are\n@end example\n\nNote that @code{popen2}, unlike @code{popen}, will not @nospell{\"reap\"}\nthe child process.  If you don't use @code{waitpid} to check the child's\nexit status, it will linger until Octave exits.\n@seealso{popen, waitpid}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  std::string exec_file = args(0).xstring_value (\"popen2: COMMAND argument must be a string\");\n\n  string_vector arg_list;\n\n  if (nargin >= 2)\n    {\n      string_vector tmp = args(1).xstring_vector_value (\"popen2: all arguments must be strings\");\n\n      int len = tmp.numel ();\n\n      arg_list.resize (len + 1);\n\n      arg_list[0] = exec_file;\n\n      for (int i = 0; i < len; i++)\n        arg_list[i+1] = tmp[i];\n    }\n  else\n    {\n      arg_list.resize (1);\n\n      arg_list[0] = exec_file;\n    }\n\n  bool sync_mode = (nargin == 3 ? args(2).bool_value () : false);\n\n  int filedesc[2];\n  std::string msg;\n  pid_t pid;\n\n  pid = sys::popen2 (exec_file, arg_list, sync_mode, filedesc, msg);\n\n  if (pid < 0)\n    error (\"%s\", msg.c_str ());\n\n  FILE *ifile = fdopen (filedesc[1], \"r\");\n  FILE *ofile = fdopen (filedesc[0], \"w\");\n\n  stream is = stdiostream::create (exec_file + \"-in\", ifile, std::ios::in);\n\n  stream os = stdiostream::create (exec_file + \"-out\", ofile, std::ios::out);\n\n  stream_list& streams = interp.get_stream_list ();\n\n  return ovl (streams.insert (os), streams.insert (is), pid);\n}\n\n/*\n\n%!testif ; isunix ()\n%! [in, out, pid] = popen2 (\"sort\", \"-r\");\n%! EAGAIN = errno (\"EAGAIN\");\n%! fputs (in, \"these\\nare\\nsome\\nstrings\\n\");\n%! fclose (in);\n%! done = false;\n%! str = {};\n%! idx = 0;\n%! errs = 0;\n%! do\n%!   s = fgets (out);\n%!   if (ischar (s))\n%!     idx++;\n%!     str{idx} = s;\n%!   elseif (errno () == EAGAIN)\n%!     fclear (out);\n%!     pause (0.1);\n%!     if (++errs == 100)\n%!       done = true;\n%!     endif\n%!   else\n%!     done = true;\n%!   endif\n%! until (done)\n%! fclose (out);\n%! waitpid (pid);\n%! assert (str, {\"these\\n\",\"strings\\n\",\"some\\n\",\"are\\n\"});\n\n%!testif ; ispc ()\n%! [in, out, pid] = popen2 ('C:\\Windows\\system32\\sort.exe', \"/R\");\n%! EAGAIN = errno (\"EINVAL\");\n%! fputs (in, \"these\\r\\nare\\r\\nsome\\r\\nstrings\\r\\n\");\n%! fclose (in);\n%! done = false;\n%! str = {};\n%! idx = 0;\n%! errs = 0;\n%! do\n%!   errno (0);\n%!   s = fgets (out);\n%!   if (ischar (s))\n%!     idx++;\n%!     str{idx} = s;\n%!   elseif (errno () == EAGAIN)\n%!     fclear (out);\n%!     pause (0.1);\n%!     if (++errs == 100)\n%!       done = true;\n%!     endif\n%!   else\n%!     done = true;\n%!   endif\n%! until (done)\n%! fclose (out);\n%! waitpid (pid);\n%! assert (str, {\"these\\r\\n\",\"strings\\r\\n\",\"some\\r\\n\",\"are\\r\\n\"});\n\n*/\n\nDEFMETHODX (\"fcntl\", Ffcntl, interp, args, nargout,\n            doc: /* -*- texinfo -*-\n@deftypefn  {} {} fcntl (@var{fid}, @var{request}, @var{arg})\n@deftypefnx {} {[@var{status}, @var{msg}] =} fcntl (@var{fid}, @var{request}, @var{arg})\nChange the properties of the open file @var{fid}.\n\nThe following values may be passed as @var{request}:\n\n@vtable @code\n@item F_DUPFD\nReturn a duplicate file descriptor.\n\n@item F_GETFD\nReturn the file descriptor flags for @var{fid}.\n\n@item F_SETFD\nSet the file descriptor flags for @var{fid}.\n\n@item F_GETFL\nReturn the file status flags for @var{fid}.  The following codes may be\nreturned (some of the flags may be undefined on some systems).\n\n@vtable @code\n@item O_RDONLY\nOpen for reading only.\n\n@item O_WRONLY\nOpen for writing only.\n\n@item O_RDWR\nOpen for reading and writing.\n\n@item O_APPEND\nAppend on each write.\n\n@item O_CREAT\nCreate the file if it does not exist.\n\n@item O_NONBLOCK\nNon-blocking mode.\n\n@item O_SYNC\nWait for writes to complete.\n\n@item O_ASYNC\nAsynchronous I/O.\n@end vtable\n\n@item F_SETFL\nSet the file status flags for @var{fid} to the value specified by @var{arg}.\nThe only flags that can be changed are @w{@code{O_APPEND}}@ and\n@w{@code{O_NONBLOCK}}.\n@end vtable\n\nIf successful, @var{status} is 0 and @var{msg} is an empty string.  Otherwise,\n@var{status} is -1 and @var{msg} contains a system-dependent error\nmessage.\n@seealso{fopen, dup2}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  int fid;\n  try\n    {\n      // Look up FID in Octave's list of open streams.\n      stream_list& streams = interp.get_stream_list ();\n      stream strm = streams.lookup (args(0), \"fcntl\");\n      fid = strm.file_number ();\n    }\n  catch (execution_exception& ee)\n    {\n      // If the file is not known to Octave, try the provided file ID directly.\n      fid = args(0).int_value (true);\n    }\n\n  if (fid < 0)\n    error (\"fcntl: invalid file id FID\");\n\n  int req = args(1).strict_int_value (\"fcntl: REQUEST must be an integer\");\n  int arg = args(2).strict_int_value (\"fcntl: ARG must be an integer\");\n\n  octave_value_list retval;\n  std::string msg;\n\n  int status = sys::fcntl (fid, req, arg, msg);\n\n  if (nargout == 0)\n    {\n      if (status < 0)\n        error (\"fcntl: operation failed: %s\", msg.c_str ());\n    }\n  else\n    {\n      if (status < 0)\n        retval = ovl (-1.0, msg);\n      else\n        retval = ovl (status, \"\");\n    }\n\n  return retval;\n}\n\nDEFMETHODX (\"fork\", Ffork, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{pid}, @var{msg}] =} fork ()\nCreate a copy of the current process.\n\nFork can return one of the following values:\n\n@table @asis\n@item > 0\nYou are in the parent process.  The value returned from @code{fork} is the\nprocess id of the child process.  You should probably arrange to wait for any\nchild processes to exit by using @code{waitpid}.\n\n@item 0\nYou are in the child process.  You can call @code{exec} to start another\nprocess.  If that fails, you should probably call @code{_Exit} to terminate the\nchild.\n\n@item < 0\nThe call to @code{fork} failed for some reason.  You must take evasive action.\nA system-dependent error message will be waiting in @var{msg}.\n@end table\n@seealso{exec, _Exit}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  if (interp.at_top_level ())\n    error (\"fork: cannot be called from command line\");\n\n  std::string msg;\n\n  pid_t pid = sys::fork (msg);\n\n  return ovl (pid, msg);\n}\n\nDEFUNX (\"_Exit\", F_Exit, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn  {} {} _Exit ()\n@deftypefnx {} {} _Exit (@var{status})\nExit the currently running process with exit code @var{status}.\n\nIf called with no arguments, exit with status @code{0} indicating success.\n\nThe optional integer argument @var{status} specifies the exit code.\n\nProgramming Note: This function maps to the C++ function @code{quick_exit}.\nThe calling process is stopped and any open file descriptors are closed.  This\nis the correct function to call to end a child process started from Octave.\nThe ordinary C library function `exit` will not work.\n@seealso{fork}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n  if (nargin > 1)\n    print_usage ();\n\n  int status = EXIT_SUCCESS;\n\n  if (nargin == 1)\n    status = args(0).xint_value (\"_Exit: STATUS must be an integer\");\n\n  octave__Exit_wrapper (status);\n\n  // This function never returns.  Silent compiler warning.\n  return ovl ();\n}\n\nDEFUNX (\"getpgrp\", Fgetpgrp, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {pgid =} getpgrp ()\nReturn the process group id of the current process.\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  std::string msg;\n\n  pid_t pid = sys::getpgrp (msg);\n\n  return ovl (pid, msg);\n}\n\nDEFUNX (\"getpid\", Fgetpid, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {pid =} getpid ()\nReturn the process id of the current process.\n@seealso{getppid}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::getpid ());\n}\n\nDEFUNX (\"getppid\", Fgetppid, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {pid =} getppid ()\nReturn the process id of the parent process.\n@seealso{getpid}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::getppid ());\n}\n\nDEFUNX (\"getegid\", Fgetegid, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {egid =} getegid ()\nReturn the effective group id of the current process.\n@seealso{getgid}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::getegid ());\n}\n\nDEFUNX (\"getgid\", Fgetgid, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {gid =} getgid ()\nReturn the real group id of the current process.\n@seealso{getegid}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::getgid ());\n}\n\nDEFUNX (\"geteuid\", Fgeteuid, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {euid =} geteuid ()\nReturn the effective user id of the current process.\n@seealso{getuid}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::geteuid ());\n}\n\nDEFUNX (\"getuid\", Fgetuid, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {uid =} getuid ()\nReturn the real user id of the current process.\n@seealso{geteuid}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::getuid ());\n}\n\nDEFUNX (\"kill\", Fkill, args, nargout,\n        doc: /* -*- texinfo -*-\n@deftypefn  {} {} kill (@var{pid}, @var{sig})\n@deftypefnx {} {[@var{status}, @var{msg}] =} kill (@var{pid}, @var{sig})\nSend signal @var{sig} to process @var{pid}.\n\nIf @var{pid} is positive, then signal @var{sig} is sent to @var{pid}.\n\nIf @var{pid} is 0, then signal @var{sig} is sent to every process in the\nprocess group of the current process.\n\nIf @var{pid} is -1, then signal @var{sig} is sent to every process except\nprocess 1.\n\nIf @var{pid} is less than -1, then signal @var{sig} is sent to every process in\nthe process group @var{-pid}.\n\nIf @var{sig} is 0, then no signal is sent, but error checking is still\nperformed.\n\nIf successful, @var{status} is 0 and @var{msg} is an empty string.\nOtherwise, @var{status} is -1 and @var{msg} contains a system-dependent\nerror message.\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  pid_t pid = args(0).int_value (true);\n\n  int sig = args(1).int_value (true);\n\n  octave_value_list retval;\n  std::string msg;\n\n  int status = sys::kill (pid, sig, msg);\n\n  if (nargout == 0)\n    {\n      if (status < 0)\n        error (\"kill: operation failed: %s\", msg.c_str ());\n    }\n  else\n    {\n      if (status < 0)\n        retval = ovl (-1.0, msg);\n      else\n        retval = ovl (0.0, \"\");\n    }\n\n  return retval;\n}\n\nDEFUNX (\"lstat\", Flstat, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{info} =} lstat (@var{symlink})\n@deftypefnx {} {[@var{info}, @var{err}, @var{msg}] =} lstat (@var{symlink})\nReturn a structure @var{info} containing information about the symbolic link\n@var{symlink}.\n\nThe function outputs are described in the documentation for @code{stat}.\n@seealso{stat, symlink}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string fname = args(0).xstring_value (\"lstat: NAME must be a string\");\n\n  sys::file_stat fs (fname, false);\n\n  return mk_stat_result (fs);\n}\n\n// FIXME: This routine also exists verbatim in file-io.cc.\n//        Maybe change to be a general utility routine.\nstatic int\nconvert (int x, int ibase, int obase)\n{\n  int retval = 0;\n\n  int tmp = x % obase;\n\n  if (tmp > ibase - 1)\n    error (\"mkfifo: invalid digit\");\n\n  retval = tmp;\n  int mult = ibase;\n  while ((x = (x - tmp) / obase))\n    {\n      tmp = x % obase;\n\n      if (tmp > ibase - 1)\n        error (\"mkfifo: invalid digit\");\n\n      retval += mult * tmp;\n      mult *= ibase;\n    }\n\n  return retval;\n}\n\nDEFUNX (\"mkfifo\", Fmkfifo, args, nargout,\n        doc: /* -*- texinfo -*-\n@deftypefn  {} {} mkfifo (@var{name}, @var{mode})\n@deftypefnx {} {[@var{status}, @var{msg}] =} mkfifo (@var{name}, @var{mode})\nCreate a FIFO special file named @var{name} with file mode @var{mode}.\n\n@var{mode} is interpreted as an octal number and is subject to umask\nprocessing.  The final calculated mode is @code{@var{mode} - @var{umask}}.\n\nIf successful, @var{status} is 0 and @var{msg} is an empty string.\nOtherwise, @var{status} is -1 and @var{msg} contains a system-dependent\nerror message.\n@seealso{pipe, umask}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"mkfifo: FILE must be a string\");\n\n  int octal_mode = args(1).strict_int_value (\"mkfifo: MODE must be an integer\");\n\n  if (octal_mode < 0)\n    error (\"mkfifo: MODE must be a positive integer value\");\n\n  int mode = convert (octal_mode, 8, 10);\n\n  octave_value_list retval;\n  std::string msg;\n\n  int status = sys::mkfifo (name, mode, msg);\n\n  if (nargout == 0)\n    {\n      if (status < 0)\n        error (\"mkfifo: operation failed: %s\", msg.c_str ());\n    }\n  else\n    {\n      if (status < 0)\n        retval = ovl (-1.0, msg);\n      else\n        retval = ovl (0.0, \"\");\n    }\n\n  return retval;\n}\n\n/*\n\n## Test input validation\n%!error mkfifo ()\n%!error mkfifo (\"abc\")\n%!error mkfifo (\"abc\", 777, 123)\n%!error <FILE must be a string> mkfifo (123, 456)\n## FIXME: These tests should work, but lasterr is not being set correctly.\n#%!error <MODE must be an integer> mkfifo (\"abc\", {456})\n#%!error <MODE must be a positive integer value> mkfifo (\"abc\", -1)\n\n*/\n\nDEFMETHODX (\"pipe\", Fpipe, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{read_fd}, @var{write_fd}, @var{err}, @var{msg}] =} pipe ()\nCreate a pipe and return the reading and writing ends of the pipe into\n@var{read_fd} and @var{write_fd} respectively.\n\nIf successful, @var{err} is 0 and @var{msg} is an empty string.\nOtherwise, @var{err} is nonzero and @var{msg} contains a system-dependent\nerror message.\n@seealso{mkfifo}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  int fid[2];\n  std::string msg;\n\n  int status = sys::pipe (fid, msg);\n\n  if (status < 0)\n    return ovl (-1, -1, -1, msg);\n  else\n    {\n      FILE *ifile = fdopen (fid[0], \"r\");\n      FILE *ofile = fdopen (fid[1], \"w\");\n\n      stream is = stdiostream::create (\"pipe-in\", ifile, std::ios::in);\n\n      stream os = stdiostream::create (\"pipe-out\", ofile, std::ios::out);\n\n      stream_list& streams = interp.get_stream_list ();\n\n      return ovl (streams.insert (is), streams.insert (os), status, msg);\n    }\n}\n\nDEFMETHODX (\"stat\", Fstat, interp, args, ,\n            doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{info}, @var{err}, @var{msg}] =} stat (@var{file})\n@deftypefnx {} {[@var{info}, @var{err}, @var{msg}] =} stat (@var{fid})\n@deftypefnx {} {[@var{info}, @var{err}, @var{msg}] =} lstat (@var{file})\n@deftypefnx {} {[@var{info}, @var{err}, @var{msg}] =} lstat (@var{fid})\nReturn a structure @var{info} containing the following information about\n@var{file} or file identifier @var{fid}.\n\n@table @code\n@item dev\nID of device containing a directory entry for this file.\n\n@item ino\nFile number of the file.\n\n@item mode\nFile mode, as an integer.  Use the functions @w{@code{S_ISREG}},\n@w{@code{S_ISDIR}}, @w{@code{S_ISCHR}}, @w{@code{S_ISBLK}},\n@w{@code{S_ISFIFO}}, @w{@code{S_ISLNK}}, or @w{@code{S_ISSOCK}}@ to extract\ninformation from this value.\n\n@item modestr\nFile mode, as a string of ten letters or dashes as would be returned by\n@kbd{ls -l}.\n\n@item nlink\nNumber of links.\n\n@item uid\nUser ID of file's owner.\n\n@item gid\nGroup ID of file's group.\n\n@item rdev\nID of device for block or character special files.\n\n@item size\nSize in bytes.\n\n@item atime\nTime of last access in the same form as time values returned from\n@code{time}.  @xref{Timing Utilities}.\n\n@item mtime\nTime of last modification in the same form as time values returned from\n@code{time}.  @xref{Timing Utilities}.\n\n@item ctime\nTime of last file status change in the same form as time values\nreturned from @code{time}.  @xref{Timing Utilities}.\n\n@item blksize\nSize of blocks in the file.\n\n@item blocks\nNumber of blocks allocated for file.\n@end table\n\nIf the call is successful @var{err} is 0 and @var{msg} is an empty string.\nIf the file does not exist, or some other error occurs, @var{info} is an\nempty matrix, @var{err} is @minus{}1, and @var{msg} contains the\ncorresponding system error message.\n\nIf @var{file} is a symbolic link, @code{stat} will return information about\nthe actual file that is referenced by the link.  Use @code{lstat} if you\nwant information about the symbolic link itself.\n\nFor example:\n\n@example\n[info, err, msg] = stat (\"/vmlinuz\")\n  @xresult{} info =\n     @{\n       atime = 855399756\n       rdev = 0\n       ctime = 847219094\n       uid = 0\n       size = 389218\n       blksize = 4096\n       mtime = 847219094\n       gid = 6\n       nlink = 1\n       blocks = 768\n       mode = -rw-r--r--\n       modestr = -rw-r--r--\n       ino = 9316\n       dev = 2049\n     @}\n  @xresult{} err = 0\n  @xresult{} msg =\n@end example\n@seealso{lstat, ls, dir, isfile, isfolder}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value_list retval;\n\n  if (args(0).is_scalar_type ())\n    {\n      int fid;\n      try\n        {\n          // Look up FID in Octave's list of open streams.\n          stream_list& streams = interp.get_stream_list ();\n          fid = streams.get_file_number (args(0));\n        }\n      catch (execution_exception& ee)\n        {\n          // If the file is not known to Octave, try provided file ID directly.\n          fid = args(0).int_value (true);\n        }\n\n      if (fid < 0)\n        error (\"stat: invalid file id FID\");\n\n      sys::file_fstat fs (fid);\n\n      retval = mk_stat_result (fs);\n    }\n  else\n    {\n      std::string fname = args(0).xstring_value (\"stat: NAME must be a string\");\n\n      sys::file_stat fs (fname);\n\n      retval = mk_stat_result (fs);\n    }\n\n  return retval;\n}\n\nDEFUNX (\"S_ISREG\", FS_ISREG, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} S_ISREG (@var{mode})\nReturn true if @var{mode} corresponds to a regular file.\n\nThe value of @var{mode} is assumed to be returned from a call to\n@code{stat}.\n@seealso{stat, lstat}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double mode = args(0).xdouble_value (\"S_ISREG: invalid MODE value\");\n\n  return ovl (sys::file_stat::is_reg (static_cast<mode_t> (mode)));\n}\n\nDEFUNX (\"S_ISDIR\", FS_ISDIR, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} S_ISDIR (@var{mode})\nReturn true if @var{mode} corresponds to a directory.\n\nThe value of @var{mode} is assumed to be returned from a call to\n@code{stat}.\n@seealso{stat, lstat}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double mode = args(0).xdouble_value (\"S_ISDIR: invalid MODE value\");\n\n  return ovl (sys::file_stat::is_dir (static_cast<mode_t> (mode)));\n}\n\nDEFUNX (\"S_ISCHR\", FS_ISCHR, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} S_ISCHR (@var{mode})\nReturn true if @var{mode} corresponds to a character device.\n\nThe value of @var{mode} is assumed to be returned from a call to\n@code{stat}.\n@seealso{stat, lstat}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double mode = args(0).xdouble_value (\"S_ISCHR: invalid MODE value\");\n\n  return ovl (sys::file_stat::is_chr (static_cast<mode_t> (mode)));\n}\n\nDEFUNX (\"S_ISBLK\", FS_ISBLK, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} S_ISBLK (@var{mode})\nReturn true if @var{mode} corresponds to a block device.\n\nThe value of @var{mode} is assumed to be returned from a call to\n@code{stat}.\n@seealso{stat, lstat}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double mode = args(0).xdouble_value (\"S_ISBLK: invalid MODE value\");\n\n  return ovl (sys::file_stat::is_blk (static_cast<mode_t> (mode)));\n}\n\nDEFUNX (\"S_ISFIFO\", FS_ISFIFO, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} S_ISFIFO (@var{mode})\nReturn true if @var{mode} corresponds to a fifo.\n\nThe value of @var{mode} is assumed to be returned from a call to\n@code{stat}.\n@seealso{stat, lstat}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double mode = args(0).xdouble_value (\"S_ISFIFO: invalid MODE value\");\n\n  return ovl (sys::file_stat::is_fifo (static_cast<mode_t> (mode)));\n}\n\nDEFUNX (\"S_ISLNK\", FS_ISLNK, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} S_ISLNK (@var{mode})\nReturn true if @var{mode} corresponds to a symbolic link.\n\nThe value of @var{mode} is assumed to be returned from a call to\n@code{stat}.\n@seealso{stat, lstat}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double mode = args(0).xdouble_value (\"S_ISLNK: invalid MODE value\");\n\n  return ovl (sys::file_stat::is_lnk (static_cast<mode_t> (mode)));\n}\n\nDEFUNX (\"S_ISSOCK\", FS_ISSOCK, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} S_ISSOCK (@var{mode})\nReturn true if @var{mode} corresponds to a socket.\n\nThe value of @var{mode} is assumed to be returned from a call to\n@code{stat}.\n@seealso{stat, lstat}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  double mode = args(0).xdouble_value (\"S_ISSOCK: invalid MODE value\");\n\n  return ovl (sys::file_stat::is_sock (static_cast<mode_t> (mode)));\n}\n\nDEFUN (gethostname, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{name} =} gethostname ()\nReturn the hostname of the system where Octave is running.\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::env::get_host_name ());\n}\n\nDEFUN (uname, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{uts}, @var{err}, @var{msg}] =} uname ()\nReturn system information in the structure.\n\nFor example:\n\n@example\n@group\nuname ()\n   @xresult{} @{\n         sysname = x86_64\n         nodename = segfault\n         release = 2.6.15-1-amd64-k8-smp\n         version = Linux\n         machine = #2 SMP Thu Feb 23 04:57:49 UTC 2006\n      @}\n@end group\n@end example\n\nIf successful, @var{err} is 0 and @var{msg} is an empty string.\nOtherwise, @var{err} is nonzero and @var{msg} contains a\nsystem-dependent error message.\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  sys::uname sysinfo;\n\n  octave_scalar_map m;\n\n  m.assign (\"sysname\", sysinfo.sysname ());\n  m.assign (\"nodename\", sysinfo.nodename ());\n  m.assign (\"release\", sysinfo.release ());\n  m.assign (\"version\", sysinfo.version ());\n  m.assign (\"machine\", sysinfo.machine ());\n\n  return ovl (m, sysinfo.error (), sysinfo.message ());\n}\n\n/*\n%!test <*51869>\n%! [info, status, msg] = uname ();\n%! if (status == 0)\n%!   assert (isstruct (info));\n%!   assert (ischar (msg) && isempty (msg));\n%! endif\n*/\n\nDEFMETHODX (\"unlink\", Funlink, interp, args, nargout,\n            doc: /* -*- texinfo -*-\n@deftypefn  {} {} unlink (@var{file})\n@deftypefnx {} {[@var{status}, @var{msg}] =} unlink (@var{file})\nDelete the file named @var{file}.\n\nIf successful, @var{status} is 0 and @var{msg} is an empty string.\nOtherwise, @var{status} is -1 and @var{msg} contains a system-dependent\nerror message.\n@seealso{delete, rmdir}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"unlink: FILE must be a string\");\n\n  octave_value_list retval;\n  std::string msg;\n\n  event_manager& evmgr = interp.get_event_manager ();\n\n  evmgr.file_remove (name, \"\");\n\n  int status = sys::unlink (name, msg);\n\n  evmgr.file_renamed (status == 0);\n\n  if (nargout == 0)\n    {\n      if (status < 0)\n        error (\"unlink: operation failed: %s\", msg.c_str ());\n    }\n  else\n    {\n      if (status < 0)\n        retval = ovl (-1.0, msg);\n      else\n        retval = ovl (0.0, \"\");\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! file = tempname ();\n%! fid = fopen (file, \"wt\");\n%! if (fid < 0)\n%!   error (\"Could not open temporary file for unlink BIST test\");\n%! endif\n%! fdisp (fid, pi);\n%! fclose (fid);\n%! [status, msg] = unlink (file);\n%! assert (status, 0);\n%! assert (msg, \"\");\n\n## Test input validation\n%!error <Invalid call> unlink ()\n%!error <Invalid call> unlink (\"a\", \"b\")\n%!error <FILE must be a string> unlink (123)\n*/\n\nDEFUNX (\"waitpid\", Fwaitpid, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{pid}, @var{status}, @var{msg}] =} waitpid (@var{pid}, @var{options})\nWait for process @var{pid} to terminate.\n\nThe @var{pid} argument can be:\n\n@table @asis\n@item @minus{}1\nWait for any child process.\n\n@item 0\nWait for any child process whose process group ID is equal to that of the\nOctave interpreter process.\n\n@item > 0\nWait for termination of the child process with ID @var{pid}.\n@end table\n\nThe @var{options} argument can be a bitwise OR of zero or more of the\nfollowing constants:\n\n@table @code\n@item 0\nWait until signal is received or a child process exits (this is the default\nif the @var{options} argument is missing).\n\n@item WNOHANG\nDo not hang if status is not immediately available.\n\n@item WUNTRACED\nReport the status of any child processes that are stopped, and whose status\nhas not yet been reported since they stopped.\n\n@item WCONTINUE\nReturn if a stopped child has been resumed by delivery of @code{SIGCONT}.\nThis value may not be meaningful on all systems.\n@end table\n\nIf the returned value of @var{pid} is greater than 0, it is the process ID\nof the child process that exited.  If an error occurs, @var{pid} will be\nless than zero and @var{msg} will contain a system-dependent error message.\nThe value of @var{status} contains additional system-dependent information\nabout the subprocess that exited.\n@seealso{WCONTINUE, WCOREDUMP, WEXITSTATUS, WIFCONTINUED, WIFSIGNALED,\nWIFSTOPPED, WNOHANG, WSTOPSIG, WTERMSIG, WUNTRACED}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin != 1 && nargin != 2)\n    print_usage ();\n\n  pid_t pid = args(0).strict_int_value (\"waitpid: OPTIONS must be an integer\");\n\n  int options = 0;\n\n  if (nargin == 2)\n    options = args(1).strict_int_value (\"waitpid: PID must be an integer value\");\n\n  std::string msg;\n  int status;\n\n  pid_t result = sys::waitpid (pid, &status, options, msg);\n\n  return ovl (result, status, msg);\n}\n\nDEFUNX (\"WIFEXITED\", FWIFEXITED, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} WIFEXITED (@var{status})\nGiven @var{status} from a call to @code{waitpid}, return\ntrue if the child terminated normally.\n@seealso{waitpid, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP, WIFSTOPPED,\nWSTOPSIG, WIFCONTINUED}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int status = args(0).strict_int_value (\"WIFEXITED: STATUS must be an integer\");\n\n  return ovl (sys::wifexited (status));\n}\n\nDEFUNX (\"WEXITSTATUS\", FWEXITSTATUS, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} WEXITSTATUS (@var{status})\nGiven @var{status} from a call to @code{waitpid}, return\nthe exit status of the child.\n\nThis function should only be employed if @code{WIFEXITED} returned true.\n@seealso{waitpid, WIFEXITED, WIFSIGNALED, WTERMSIG, WCOREDUMP, WIFSTOPPED,\nWSTOPSIG, WIFCONTINUED}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int status = args(0).strict_int_value (\"WEXITSTATUS: STATUS must be an integer\");\n\n  return ovl (sys::wexitstatus (status));\n}\n\nDEFUNX (\"WIFSIGNALED\", FWIFSIGNALED, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} WIFSIGNALED (@var{status})\nGiven @var{status} from a call to @code{waitpid}, return\ntrue if the child process was terminated by a signal.\n@seealso{waitpid, WIFEXITED, WEXITSTATUS, WTERMSIG, WCOREDUMP, WIFSTOPPED,\nWSTOPSIG, WIFCONTINUED}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int status = args(0).strict_int_value (\"WIFSIGNALED: STATUS must be an integer\");\n\n  return ovl (sys::wifsignaled (status));\n}\n\nDEFUNX (\"WTERMSIG\", FWTERMSIG, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} WTERMSIG (@var{status})\nGiven @var{status} from a call to @code{waitpid}, return\nthe number of the signal that caused the child process to terminate.\n\nThis function should only be employed if @code{WIFSIGNALED} returned true.\n@seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WCOREDUMP, WIFSTOPPED,\nWSTOPSIG, WIFCONTINUED}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int status = args(0).strict_int_value (\"WTERMSIG: STATUS must be an integer\");\n\n  return ovl (sys::wtermsig (status));\n}\n\nDEFUNX (\"WCOREDUMP\", FWCOREDUMP, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} WCOREDUMP (@var{status})\nGiven @var{status} from a call to @code{waitpid}, return\ntrue if the child produced a core dump.\n\nThis function should only be employed if @code{WIFSIGNALED} returned true.\nThe macro used to implement this function is not specified in POSIX.1-2001\nand is not available on some Unix implementations (e.g., @nospell{AIX, SunOS}).\n@seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WIFSTOPPED,\nWSTOPSIG, WIFCONTINUED}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int status = args(0).strict_int_value (\"WCOREDUMP: STATUS must be an integer\");\n\n  return ovl (sys::wcoredump (status));\n}\n\nDEFUNX (\"WIFSTOPPED\", FWIFSTOPPED, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} WIFSTOPPED (@var{status})\nGiven @var{status} from a call to @code{waitpid}, return\ntrue if the child process was stopped by delivery of a signal.\n\nThis is only possible if the call was done using @code{WUNTRACED} or when\nthe child is being traced (see ptrace(2)).\n@seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP,\nWSTOPSIG, WIFCONTINUED}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int status = args(0).strict_int_value (\"WIFSTOPPED: STATUS must be an integer\");\n\n  return ovl (sys::wifstopped (status));\n}\n\nDEFUNX (\"WSTOPSIG\", FWSTOPSIG, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} WSTOPSIG (@var{status})\nGiven @var{status} from a call to @code{waitpid}, return\nthe number of the signal which caused the child to stop.\n\nThis function should only be employed if @code{WIFSTOPPED} returned true.\n@seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP,\nWIFSTOPPED, WIFCONTINUED}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int status = args(0).strict_int_value (\"WSTOPSIG: STATUS must be an integer\");\n\n  return ovl (sys::wstopsig (status));\n}\n\nDEFUNX (\"WIFCONTINUED\", FWIFCONTINUED, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} WIFCONTINUED (@var{status})\nGiven @var{status} from a call to @code{waitpid}, return\ntrue if the child process was resumed by delivery of @code{SIGCONT}.\n@seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP,\nWIFSTOPPED, WSTOPSIG}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  int status = args(0).strict_int_value (\"WIFCONTINUED: STATUS must be an integer\");\n\n  return ovl (sys::wifcontinued (status));\n}\n\nDEFUNX (\"canonicalize_file_name\", Fcanonicalize_file_name, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{cname}, @var{status}, @var{msg}] =} canonicalize_file_name (@var{fname})\nReturn the canonical name of file @var{fname}.\n\nIf the file does not exist the empty string (\"\") is returned.  No tilde\nexpansion of @var{fname} is performed.\n@seealso{make_absolute_filename, is_absolute_filename,\nis_rooted_relative_filename, is_same_file, tilde_expand}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"canonicalize_file_name: NAME must be a string\");\n\n  std::string msg;\n\n  std::string result = sys::canonicalize_file_name (name, msg);\n\n  return ovl (result, msg.empty () ? 0 : -1, msg);\n}\n\nstatic inline octave_value\nconst_value (const octave_value_list& args, int val)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return octave_value (val);\n}\n\nDEFUNX (\"F_DUPFD\", FF_DUPFD, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} F_DUPFD ()\nReturn the numerical value to pass to @code{fcntl} to return\na duplicate file descriptor.\n@seealso{fcntl, F_GETFD, F_GETFL, F_SETFD, F_SETFL}\n@end deftypefn */)\n{\n  static const int val = octave_f_dupfd_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"F_DUPFD\", \"F_DUPFD\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"F_GETFD\", FF_GETFD, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} F_GETFD ()\nReturn the numerical value to pass to @code{fcntl} to return\nthe file descriptor flags.\n@seealso{fcntl, F_DUPFD, F_GETFL, F_SETFD, F_SETFL}\n@end deftypefn */)\n{\n  static const int val = octave_f_getfd_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"F_GETFD\", \"F_GETFD\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"F_GETFL\", FF_GETFL, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} F_GETFL ()\nReturn the numerical value to pass to @code{fcntl} to return\nthe file status flags.\n@seealso{fcntl, F_DUPFD, F_GETFD, F_SETFD, F_SETFL}\n@end deftypefn */)\n{\n  static const int val = octave_f_getfl_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"F_GETFL\", \"F_GETFL\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"F_SETFD\", FF_SETFD, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} F_SETFD ()\nReturn the numerical value to pass to @code{fcntl} to set the file\ndescriptor flags.\n@seealso{fcntl, F_DUPFD, F_GETFD, F_GETFL, F_SETFL}\n@end deftypefn */)\n{\n  static const int val = octave_f_setfd_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"F_SETFD\", \"F_SETFD\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"F_SETFL\", FF_SETFL, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} F_SETFL ()\nReturn the numerical value to pass to @code{fcntl} to set the file\nstatus flags.\n@seealso{fcntl, F_DUPFD, F_GETFD, F_GETFL, F_SETFD}\n@end deftypefn */)\n{\n  static const int val = octave_f_setfl_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"F_SETFL\", \"F_SETFL\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_APPEND\", FO_APPEND, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_APPEND ()\nReturn the numerical value of the @code{O_APPEND} macro.\n\n@code{O_APPEND} is file status flag that may be returned by @code{fcntl}\nto indicate each write operation appends, or that may be passed to\n@code{fcntl} to set the write mode to append.\n@seealso{fcntl, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC,\nO_TRUNC, O_WRONLY}\n@end deftypefn */)\n{\n  static const int val = octave_o_append_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_APPEND\", \"O_APPEND\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_ASYNC\", FO_ASYNC, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_ASYNC ()\nReturn the numerical value of the @code{O_ASYNC} macro.\n\n@code{O_ASYNC} is the file status flag that may be returned by\n@code{fcntl} to indicate asynchronous I/O.\n@seealso{fcntl, O_APPEND, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC,\nO_TRUNC, O_WRONLY}\n@end deftypefn */)\n{\n  static const int val = octave_o_async_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_ASYNC\", \"O_ASYNC\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_CREAT\", FO_CREAT, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_CREAT ()\nReturn the numerical value of the @code{O_CREAT}.\n\n@code{O_CREAT} is the file status flag that may be returned by\n@code{fcntl} to indicate that a file should be created if it does not\nexist.\n@seealso{fcntl, O_APPEND, O_ASYNC, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC,\nO_TRUNC, O_WRONLY}\n@end deftypefn */)\n{\n  static const int val = octave_o_creat_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_CREAT\", \"O_CREAT\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_EXCL\", FO_EXCL, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_EXCL ()\nReturn the numerical value of the @code{O_EXCL}.\n\n@code{O_EXCL} is the file status flag that may be returned by\n@code{fcntl} to indicate that file locking is used.\n@seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_NONBLOCK, O_RDONLY, O_RDWR,\nO_SYNC, O_TRUNC, O_WRONLY}\n@end deftypefn */)\n{\n  static const int val = octave_o_excl_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_EXCL\", \"O_EXCL\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_NONBLOCK\", FO_NONBLOCK, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_NONBLOCK ()\nReturn the numerical value of the @code{O_NONBLOCK}.\n\n@code{O_NONBLOCK} is the file status flag that may be returned by\n@code{fcntl} to indicate that non-blocking I/O is in use, or that may be\npasssed to @code{fcntl} to set non-blocking I/O.\n@seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC,\nO_TRUNC, O_WRONLY}\n@end deftypefn */)\n{\n  static const int val = octave_o_nonblock_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_NONBLOCK\", \"O_NONBLOCK\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_RDONLY\", FO_RDONLY, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_RDONLY ()\nReturn the numerical value of the @code{O_RDONLY}.\n\n@code{O_RDONLY} is the file status flag that may be returned by\n@code{fcntl} to indicate that a file is open for reading only.\n@seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDWR, O_SYNC,\nO_TRUNC, O_WRONLY}\n@end deftypefn */)\n{\n  static const int val = octave_o_rdonly_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_RDONLY\", \"O_RDONLY\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_RDWR\", FO_RDWR, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_RDWR ()\nReturn the numerical value of the @code{O_RDWR}.\n\n@code{O_RDWR} is the file status flag that may be returned by\n@code{fcntl} to indicate that a file is open for both reading and\nwriting.\n@seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY,\nO_SYNC, O_TRUNC, O_WRONLY}\n@end deftypefn */)\n{\n  static const int val = octave_o_rdwr_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_RDWR\", \"O_RDWR\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_SYNC\", FO_SYNC, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_SYNC ()\nReturn the numerical value of the @code{O_SYNC}.\n\n@code{O_SYNC} is the file status flag that may be returned by\n@code{fcntl} to indicate that a file is open for synchronous I/O\n@seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY,\nO_RDWR, O_TRUNC, O_WRONLY}\n@end deftypefn */)\n{\n  static const int val = octave_o_sync_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_SYNC\", \"O_SYNC\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_TRUNC\", FO_TRUNC, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_TRUNC ()\nReturn the numerical value of the @code{O_TRUNC}.\n\n@code{O_TRUNC} is the file status flag that may be returned by\n@code{fcntl} to indicate that if file exists, it should be truncated\nwhen writing.\n@seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY,\nO_RDWR, O_SYNC, O_WRONLY}\n@end deftypefn */)\n{\n  static const int val = octave_o_trunc_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_TRUNC\", \"O_TRUNC\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"O_WRONLY\", FO_WRONLY, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} O_WRONLY ()\nReturn the numerical value of the @code{O_WRONLY}.\n\n@code{O_WRONLY} is the file status flag that may be returned by\n@code{fcntl} to indicate that a file is open for writing only\n@seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY,\nO_RDWR, O_SYNC, O_TRUNC}\n@end deftypefn */)\n{\n  static const int val = octave_o_wronly_wrapper ();\n\n  if (val < 0)\n    err_disabled_feature (\"O_WRONLY\", \"O_WRONLY\");\n\n  return const_value (args, val);\n}\n\nDEFUNX (\"WNOHANG\", FWNOHANG, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} WNOHANG ()\nReturn the numerical value of the @code{WNOHANG} macro.\n\n@code{WNOHANG} is the option argument that may be passed to\n@code{waitpid} to indicate that it should return its status immediately\ninstead of waiting for a process to exit.\n@seealso{waitpid, WUNTRACED, WCONTINUE}\n@end deftypefn */)\n{\n  return const_value (args, sys::wnohang ());\n}\n\nDEFUNX (\"WUNTRACED\", FWUNTRACED, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} WUNTRACED ()\nReturn the numerical value of the @code{WUNTRACED} macro.\n\n@code{WUNTRACED} is the option argument that may be passed to\n@code{waitpid} to indicate that it should also return if the child\nprocess has stopped but is not traced via the @code{ptrace} system call\n@seealso{waitpid, WNOHANG, WCONTINUE}\n@end deftypefn */)\n{\n  return const_value (args, sys::wuntraced ());\n}\n\nDEFUNX (\"WCONTINUE\", FWCONTINUE, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{v} =} WCONTINUE ()\nReturn the numerical value of the @code{WCONTINUE} macro.\n\n@code{WCONTINUE} is the option argument that may be passed to\n@code{waitpid} to indicate that it should also return if a stopped child\nhas been resumed by delivery of a @code{SIGCONT} signal.\n@seealso{waitpid, WNOHANG, WUNTRACED}\n@end deftypefn */)\n{\n  return const_value (args, sys::wcontinue ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/system/time.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"oct-map.h\"\n#include \"oct-time.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Date and time functions.\n\nstatic octave_scalar_map\nmk_tm_map (const sys::base_tm& t)\n{\n  octave_scalar_map m;\n\n  m.assign (\"usec\", static_cast<double> (t.usec ()));\n  m.assign (\"sec\", static_cast<double> (t.sec ()));\n  m.assign (\"min\", static_cast<double> (t.min ()));\n  m.assign (\"hour\", static_cast<double> (t.hour ()));\n  m.assign (\"mday\", static_cast<double> (t.mday ()));\n  m.assign (\"mon\", static_cast<double> (t.mon ()));\n  m.assign (\"year\", static_cast<double> (t.year ()));\n  m.assign (\"wday\", static_cast<double> (t.wday ()));\n  m.assign (\"yday\", static_cast<double> (t.yday ()));\n  m.assign (\"isdst\", static_cast<double> (t.isdst ()));\n  m.assign (\"gmtoff\", static_cast<double> (t.gmtoff ()));\n  m.assign (\"zone\", t.zone ());\n\n  return m;\n}\n\nstatic inline int\nintfield (const octave_scalar_map& m, const std::string& k, const char *who)\n{\n  int retval = 0;\n\n  octave_value v = m.getfield (k);\n\n  if (! v.isempty ())\n    retval = v.strict_int_value (\"%s: invalid TM_STRUCT argument\", who);\n\n  return retval;\n}\n\nstatic inline std::string\nstringfield (const octave_scalar_map& m, const std::string& k, const char *who)\n{\n  std::string retval;\n\n  octave_value v = m.getfield (k);\n\n  if (! v.isempty ())\n    retval = v.xstring_value (\"%s: invalid TM_STRUCT argument\", who);\n\n  return retval;\n}\n\nstatic sys::base_tm\nextract_tm (const octave_scalar_map& m, const char *who)\n{\n  sys::base_tm tm;\n\n  tm.usec (intfield (m, \"usec\", who));\n  tm.sec (intfield (m, \"sec\", who));\n  tm.min (intfield (m, \"min\", who));\n  tm.hour (intfield (m, \"hour\", who));\n  tm.mday (intfield (m, \"mday\", who));\n  tm.mon (intfield (m, \"mon\", who));\n  tm.year (intfield (m, \"year\", who));\n  tm.wday (intfield (m, \"wday\", who));\n  tm.yday (intfield (m, \"yday\", who));\n  tm.isdst (intfield (m, \"isdst\", who));\n  tm.gmtoff (intfield (m, \"gmtoff\", who));\n  tm.zone (stringfield (m, \"zone\", who));\n\n  return tm;\n}\n\nDEFUN (time, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{seconds} =} time ()\nReturn the current time as the number of seconds since the epoch.\n\nThe epoch is referenced to 00:00:00 UTC (Coordinated Universal Time) 1 Jan\n1970.  For example, on Monday February 17, 1997 at 07:15:06 UTC, the value\nreturned by @code{time} was 856163706.\n@seealso{strftime, strptime, localtime, gmtime, mktime, now, date, clock,\ndatenum, datestr, datevec, calendar, weekday}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (sys::time ());\n}\n\n/*\n%!assert (time () > 0)\n\n%!error time (1)\n*/\n\nDEFUN (gmtime, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tm_struct} =} gmtime (@var{t})\nGiven a value returned from @code{time}, or any non-negative integer,\nreturn a time structure corresponding to UTC (Coordinated Universal Time).\n\nFor example:\n\n@example\n@group\ngmtime (time ())\n     @xresult{} @{\n           usec = 0\n           sec = 6\n           min = 15\n           hour = 7\n           mday = 17\n           mon = 1\n           year = 97\n           wday = 1\n           yday = 47\n           isdst = 0\n           gmtoff = 0\n           zone = GMT\n        @}\n@end group\n@end example\n@seealso{strftime, strptime, localtime, mktime, time, now, date, clock, datenum,\ndatestr, datevec, calendar, weekday}\n@end deftypefn */)\n{\n  if (args.length () != 1 || args(0).numel () != 1)\n    print_usage ();\n\n  double tmp = args(0).double_value ();\n\n  return ovl (mk_tm_map (sys::gmtime (tmp)));\n}\n\n/*\n%!test\n%! ts = gmtime (time ());\n%! assert (isstruct (ts));\n%! assert (isfield (ts, \"usec\"));\n%! assert (isfield (ts, \"year\"));\n%! assert (isfield (ts, \"mon\"));\n%! assert (isfield (ts, \"mday\"));\n%! assert (isfield (ts, \"sec\"));\n%! assert (isfield (ts, \"min\"));\n%! assert (isfield (ts, \"wday\"));\n%! assert (isfield (ts, \"hour\"));\n%! assert (isfield (ts, \"isdst\"));\n%! assert (isfield (ts, \"yday\"));\n\n%!error gmtime ()\n%!error gmtime (1, 2)\n*/\n\nDEFUN (localtime, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tm_struct} =} localtime (@var{t})\nGiven a value returned from @code{time}, or any non-negative integer,\nreturn a time structure corresponding to the local time zone.\n\n@example\n@group\nlocaltime (time ())\n     @xresult{} @{\n           usec = 0\n           sec = 6\n           min = 15\n           hour = 1\n           mday = 17\n           mon = 1\n           year = 97\n           wday = 1\n           yday = 47\n           isdst = 0\n           gmtoff = -21600\n           zone = CST\n        @}\n@end group\n@end example\n@seealso{strftime, strptime, gmtime, mktime, time, now, date, clock, datenum,\ndatestr, datevec, calendar, weekday}\n@end deftypefn */)\n{\n  if (args.length () != 1 || args(0).numel () != 1)\n    print_usage ();\n\n  double tmp = args(0).double_value ();\n\n  return ovl (mk_tm_map (sys::localtime (tmp)));\n}\n\n/*\n%!test\n%! ts = localtime (time ());\n%! assert (isstruct (ts));\n%! assert (isfield (ts, \"usec\"));\n%! assert (isfield (ts, \"year\"));\n%! assert (isfield (ts, \"mon\"));\n%! assert (isfield (ts, \"mday\"));\n%! assert (isfield (ts, \"sec\"));\n%! assert (isfield (ts, \"min\"));\n%! assert (isfield (ts, \"wday\"));\n%! assert (isfield (ts, \"hour\"));\n%! assert (isfield (ts, \"isdst\"));\n%! assert (isfield (ts, \"yday\"));\n\n%!error localtime ()\n%!error localtime (1, 2)\n*/\n\nDEFUN (mktime, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{seconds} =} mktime (@var{tm_struct})\nConvert a time structure corresponding to the local time to the number of\nseconds since the epoch.\n\nFor example:\n\n@example\n@group\nmktime (localtime (time ()))\n     @xresult{} 856163706\n@end group\n@end example\n@seealso{strftime, strptime, localtime, gmtime, time, now, date, clock, datenum,\ndatestr, datevec, calendar, weekday}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_scalar_map map = args(0).xscalar_map_value (\"mktime: TM_STRUCT argument must be a structure\");\n\n  sys::base_tm tm = extract_tm (map, \"mktime\");\n\n  return ovl (sys::time (tm));\n}\n\n/*\n%!test\n%! t = time ();\n%! assert (fix (mktime (localtime (t))) == fix (t));\n\n## These tests fail on systems with mktime functions of limited\n## intelligence:\n%!assert (datestr (datenum (1969, 1, 1), 0), \"01-Jan-1969 00:00:00\")\n%!assert (datestr (datenum (1901, 1, 1), 0), \"01-Jan-1901 00:00:00\")\n%!assert (datestr (datenum (1795, 1, 1), 0), \"01-Jan-1795 00:00:00\")\n\n%!error mktime ()\n%!error mktime (1)\n%!error mktime (1, 2, 3)\n%!error mktime (struct (\"year\", \"foo\"))\n*/\n\nDEFUN (strftime, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{str} =} strftime (@var{fmt}, @var{tm_struct})\nFormat the time structure @var{tm_struct} in a flexible way using the format\nstring @var{fmt} that contains @samp{%} substitutions similar to those in\n@code{printf}.\n\nExcept where noted, substituted fields have a fixed size; numeric fields are\npadded if necessary.  Padding is with zeros by default; for fields that\ndisplay a single number, padding can be changed or inhibited by following\nthe @samp{%} with one of the modifiers described below.  Unknown field\nspecifiers are copied as normal characters.  All other characters are copied\nto the output without change.  For example:\n\n@example\n@group\nstrftime (\"%r (%Z) %A %e %B %Y\", localtime (time ()))\n      @xresult{} \"01:15:06 AM (CST) Monday 17 February 1997\"\n@end group\n@end example\n\nOctave's @code{strftime} function supports a superset of the ANSI C field\nspecifiers.\n\n@noindent\nLiteral character fields:\n\n@table @code\n@item %%\n% character.\n\n@item %n\nNewline character.\n\n@item %t\nTab character.\n@end table\n\n@noindent\nNumeric modifiers (a nonstandard extension):\n\n@table @code\n@item - (dash)\nDo not pad the field.\n\n@item _ (underscore)\nPad the field with spaces.\n@end table\n\n@noindent\nTime fields:\n\n@table @code\n@item %H\nHour (00-23).\n\n@item %I\nHour (01-12).\n\n@item %k\nHour (0-23).\n\n@item %l\nHour (1-12).\n\n@item %M\nMinute (00-59).\n\n@item %p\nLocale's AM or PM.\n\n@item %r\nTime, 12-hour (hh:mm:ss [AP]M).\n\n@item %R\nTime, 24-hour (hh:mm).\n\n@item %s\nTime in seconds since 00:00:00, Jan 1, 1970 (a nonstandard extension).\n\n@item %S\nSecond (00-61).\n\n@item %T\nTime, 24-hour (hh:mm:ss).\n\n@item %X\nLocale's time representation (%H:%M:%S).\n\n@item %z\nOffset from UTC (±@nospell{hhmm}), or nothing if no time zone is\ndeterminable.\n\n@item %Z\nTime zone (EDT), or nothing if no time zone is determinable.\n@end table\n\n@noindent\nDate fields:\n\n@table @code\n@item %a\nLocale's abbreviated weekday name (Sun-Sat).\n\n@item %A\nLocale's full weekday name, variable length (Sunday-Saturday).\n\n@item %b\nLocale's abbreviated month name (Jan-Dec).\n\n@item %B\nLocale's full month name, variable length (January-December).\n\n@item %c\nLocale's date and time (Sat Nov 04 12:02:33 EST 1989).\n\n@item %C\nCentury (00-99).\n\n@item %d\nDay of month (01-31).\n\n@item %e\nDay of month ( 1-31).\n\n@item %D\nDate (mm/dd/yy).\n\n@item %h\nSame as %b.\n\n@item %j\nDay of year (001-366).\n\n@item %m\nMonth (01-12).\n\n@item %U\nWeek number of year with Sunday as first day of week (00-53).\n\n@item %w\nDay of week (0-6).\n\n@item %W\nWeek number of year with Monday as first day of week (00-53).\n\n@item %x\nLocale's date representation (mm/dd/yy).\n\n@item %y\nLast two digits of year (00-99).\n\n@item %Y\nYear (1970-).\n@end table\n@seealso{strptime, localtime, gmtime, mktime, time, now, date, clock, datenum,\ndatestr, datevec, calendar, weekday}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string fmt = args(0).xstring_value (\"strftime: FMT must be a string\");\n\n  octave_scalar_map map = args(1).xscalar_map_value (\"strftime: TM_STRUCT must be a structure\");\n\n  sys::base_tm tm = extract_tm (map, \"strftime\");\n\n  return ovl (tm.strftime (fmt));\n}\n\n/*\n%!assert (ischar (strftime (\"%%%n%t%H%I%k%l\", localtime (time ()))))\n%!assert (ischar (strftime (\"%M%p%r%R%s%S%T\", localtime (time ()))))\n%!assert (ischar (strftime (\"%X%Z%z%a%A%b%B\", localtime (time ()))))\n%!assert (ischar (strftime (\"%c%C%d%e%D%h%j\", localtime (time ()))))\n%!assert (ischar (strftime (\"%m%U%w%W%x%y%Y\", localtime (time ()))))\n\n%!error strftime ()\n%!error strftime (\"foo\", 1)\n%!error strftime (\"foo\", struct (\"year\", \"foo\"))\n%!error strftime (\"foo\", localtime (time ()), 1)\n*/\n\nDEFUN (strptime, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{tm_struct}, @var{nchars}] =} strptime (@var{str}, @var{fmt})\nConvert the string @var{str} to the time structure @var{tm_struct} under\nthe control of the format string @var{fmt}.\n\nIf @var{fmt} fails to match, @var{nchars} is 0; otherwise, it is set to the\nposition of last matched character plus 1.  Always check for this unless\nyou're absolutely sure the date string will be parsed correctly.\n@seealso{strftime, localtime, gmtime, mktime, time, now, date, clock, datenum,\ndatestr, datevec, calendar, weekday}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string str = args(0).xstring_value (\"strptime: argument STR must be a string\");\n\n  std::string fmt = args(1).xstring_value (\"strptime: FMT must be a string\");\n\n  sys::strptime t (str, fmt);\n\n  return ovl (mk_tm_map (t), t.characters_converted ());\n}\n\n/*\n%!test\n%! fmt = \"%Y-%m-%d %H:%M:%S\";\n%! s = strftime (fmt, localtime (time ()));\n%! ts = strptime  (s, fmt);\n%! assert (isstruct (ts));\n%! assert (isfield (ts, \"usec\"));\n%! assert (isfield (ts, \"year\"));\n%! assert (isfield (ts, \"mon\"));\n%! assert (isfield (ts, \"mday\"));\n%! assert (isfield (ts, \"sec\"));\n%! assert (isfield (ts, \"min\"));\n%! assert (isfield (ts, \"wday\"));\n%! assert (isfield (ts, \"hour\"));\n%! assert (isfield (ts, \"isdst\"));\n%! assert (isfield (ts, \"yday\"));\n\n%!error strptime ()\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/system/urlwrite.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n#include <fstream>\n#include <algorithm>\n\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"glob-match.h\"\n#include \"oct-env.h\"\n#include \"oct-handle.h\"\n#include \"oct-sysdep.h\"\n#include \"url-transfer.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"oct-refcount.h\"\n#include \"ov-cell.h\"\n#include \"ov-classdef.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"unwind-prot.h\"\n#include \"url-handle-manager.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Helper function to parse property/value pairs into weboptions struct\nstatic void\nparse_property_value_pairs (const octave_value_list& args, int start_idx,\n                            struct weboptions& options,\n                            std::string& method, Array<std::string>& param,\n                            const std::string& who)\n{\n  int nargin = args.length ();\n\n  if ((nargin - start_idx) % 2 != 0)\n    error (\"%s: property/value arguments must occur in pairs\", who.c_str ());\n\n  // Parse property/value pairs\n  for (int i = start_idx; i < nargin; i += 2)\n    {\n      if (! args(i).is_string ())\n        error (\"%s: property names must be strings\", who.c_str ());\n\n      std::string property = args(i).string_value ();\n\n      // Convert property name to lowercase for case-insensitive comparison\n      std::transform (property.begin (), property.end (), property.begin (),\n                     [] (unsigned char c) { return std::tolower(c); });\n\n      if (property == \"get\")\n        {\n          method = \"get\";\n          std::string err_msg = who + \": 'Get' value must be a cell array of strings\";\n          param = args(i+1).xcellstr_value (err_msg.c_str ());\n          if (param.numel () % 2 == 1)\n            error (\"%s: number of elements in 'Get' cell array must be even\", who.c_str ());\n        }\n      else if (property == \"post\")\n        {\n          method = \"post\";\n          std::string err_msg = who + \": 'Post' value must be a cell array of strings\";\n          param = args(i+1).xcellstr_value (err_msg.c_str ());\n          if (param.numel () % 2 == 1)\n            error (\"%s: number of elements in 'Post' cell array must be even\", who.c_str ());\n        }\n      else if (property == \"timeout\")\n        {\n          std::string err_msg = who + \": 'Timeout' value must be numeric\";\n          double timeout = args(i+1).xdouble_value (err_msg.c_str ());\n          if (timeout <= 0)\n            error (\"%s: 'Timeout' value must be positive\", who.c_str ());\n          // Convert to milliseconds\n          options.Timeout = static_cast<long> (timeout * 1000);\n        }\n      else if (property == \"useragent\")\n        {\n          std::string err_msg = who + \": 'UserAgent' value must be a string\";\n          options.UserAgent = args(i+1).xstring_value (err_msg.c_str ());\n        }\n      else if (property == \"username\")\n        {\n          std::string err_msg = who + \": 'Username' value must be a string\";\n          options.Username = args(i+1).xstring_value (err_msg.c_str ());\n        }\n      else if (property == \"password\")\n        {\n          std::string err_msg = who + \": 'Password' value must be a string\";\n          options.Password = args(i+1).xstring_value (err_msg.c_str ());\n        }\n      else if (property == \"charset\")\n        {\n          // Store for potential future use, but not used by curl_transfer yet\n          std::string err_msg = who + \": 'Charset' value must be a string\";\n          options.CharacterEncoding = args(i+1).xstring_value (err_msg.c_str ());\n        }\n      else\n        {\n          error (\"%s: unknown property '%s'\", who.c_str (), args(i).string_value ().c_str ());\n        }\n    }\n}\n\nDEFUN (urlwrite, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} urlwrite (@var{url}, @var{localfile})\n@deftypefnx {} {} urlwrite (@var{url}, @var{localfile}, @var{Name}, @var{Value}, @dots{})\n@deftypefnx {} {@var{f} =} urlwrite (@var{url}, @var{localfile}, @dots{})\n@deftypefnx {} {[@var{f}, @var{success}] =} urlwrite (@var{url}, @var{localfile}, @dots{})\n@deftypefnx {} {[@var{f}, @var{success}, @var{message}] =} urlwrite (@var{url}, @var{localfile}, @dots{})\nDownload a remote file specified by its @var{url} and save it as\n@var{localfile}.\n\nFor example:\n\n@example\n@group\nurlwrite (\"http://ftp.octave.org/pub/README\",\n          \"README.txt\");\n@end group\n@end example\n\nThe full path of the downloaded file is returned in @var{f}.\n\nThe variable @var{success} is 1 if the download was successful,\notherwise it is 0 in which case @var{message} contains an error message.\n\nIf no output argument is specified and an error occurs, then the error is\nsignaled through Octave's error handling mechanism.\n\nThis function uses libcurl.  The curl library supports, among others, the HTTP,\nFTP, and FILE protocols.  Username and password may be specified in the URL,\nfor example:\n\n@example\n@group\nurlwrite (\"http://username:password@@example.com/file.txt\",\n          \"file.txt\");\n@end group\n@end example\n\nAdditional options can be specified using property/value pairs:\n\n@table @code\n@item Get\nCell array of name/value pairs for GET request parameters.\n\n@item Post\nCell array of name/value pairs for POST request parameters.\n\n@item Timeout\nTimeout value in seconds.\n\n@item UserAgent\nUser agent string for the request.\n\n@item Username\nUsername for authentication.\n\n@item Password\nPassword for authentication.\n@end table\n\nExample with property/value pairs:\n\n@example\n@group\nurlwrite (\"http://www.example.com/data.txt\", \"data.txt\",\n          \"Timeout\", 10, \"UserAgent\", \"Octave\");\n@end group\n@end example\n\nFor backward compatibility, the old calling form is also supported:\n\n@example\n@group\nurlwrite (\"http://www.google.com/search\", \"search.html\",\n          \"get\", @{\"query\", \"octave\"@});\n@end group\n@end example\n@seealso{urlread, weboptions}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  // verify arguments\n  if (nargin < 2)\n    print_usage ();\n\n  std::string url = args(0).xstring_value (\"urlwrite: URL must be a string\");\n\n  // name to store the file if download is successful\n  std::string filename = args(1).xstring_value (\"urlwrite: LOCALFILE must be a string\");\n\n  std::string method = \"get\";\n  Array<std::string> param;\n\n  // Create a weboptions struct to hold option values\n  struct weboptions options;\n  // Set default timeout to match weboptions default\n  options.Timeout = 5000;  // 5 seconds in milliseconds\n\n  // Check if old calling form with 4 arguments (backward compatibility)\n  if (nargin == 4 && args(2).is_string ()\n      && (args(2).string_value () == \"get\" || args(2).string_value () == \"post\"))\n    {\n      // Old calling form: urlwrite(url, file, method, param)\n      method = args(2).xstring_value (\"urlwrite: METHOD must be a string\");\n\n      if (method != \"get\" && method != \"post\")\n        error (R\"(urlwrite: METHOD must be \"get\" or \"post\")\");\n\n      param = args(3).xcellstr_value (\"urlwrite: parameters (PARAM) for get and post requests must be given as a cell array of strings\");\n\n      if (param.numel () % 2 == 1)\n        error (\"urlwrite: number of elements in PARAM must be even\");\n    }\n  else if (nargin > 2)\n    {\n      // New property/value pairs form\n      parse_property_value_pairs (args, 2, options, method, param, \"urlwrite\");\n    }\n\n  // The file should only be deleted if it doesn't initially exist, we\n  // create it, and the download fails.  We use unwind_protect to do\n  // it so that the deletion happens no matter how we exit the function.\n\n  std::ofstream ofile =\n    sys::ofstream (filename.c_str (), std::ios::out | std::ios::binary);\n\n  if (! ofile.is_open ())\n    error (\"urlwrite: unable to open file\");\n\n  int(*unlink_fptr)(const std::string&) = sys::unlink;\n  unwind_action_safe unlink_action (unlink_fptr, filename);\n\n  url_transfer url_xfer (url, ofile);\n\n  octave_value_list retval;\n\n  if (! url_xfer.is_valid ())\n    error (\"support for URL transfers was disabled when Octave was built\");\n\n  // Apply weboptions if any were set\n  url_xfer.set_weboptions (options);\n\n  // Perform the HTTP action\n  url_xfer.http_action (param, method);\n\n  ofile.close ();\n\n  if (url_xfer.good ())\n    unlink_action.discard ();\n\n  if (nargout > 0)\n    {\n      if (url_xfer.good ())\n        retval = ovl (sys::env::make_absolute (filename), true, \"\");\n      else\n        retval = ovl (\"\", false, url_xfer.lasterror ());\n    }\n\n  if (nargout < 2 && ! url_xfer.good ())\n    error (\"urlwrite: %s\", url_xfer.lasterror ().c_str ());\n\n  return retval;\n}\n\nDEFUN (urlread, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{s} =} urlread (@var{url})\n@deftypefnx {} {@var{s} =} urlread (@var{url}, @var{Name}, @var{Value}, @dots{})\n@deftypefnx {} {[@var{s}, @var{success}] =} urlread (@var{url}, @dots{})\n@deftypefnx {} {[@var{s}, @var{success}, @var{message}] =} urlread (@var{url}, @dots{})\nDownload a remote file specified by its @var{url} and return its content\nin string @var{s}.\n\nFor example:\n\n@example\ns = urlread (\"http://ftp.octave.org/pub/README\");\n@end example\n\nThe variable @var{success} is 1 if the download was successful,\notherwise it is 0 in which case @var{message} contains an error\nmessage.\n\nIf no output argument is specified and an error occurs, then the error is\nsignaled through Octave's error handling mechanism.\n\nThis function uses libcurl.  The curl library supports, among others, the HTTP,\nFTP, and FILE protocols.  Username and password may be specified in the URL@.\nFor example:\n\n@example\ns = urlread (\"http://user:password@@example.com/file.txt\");\n@end example\n\nAdditional options can be specified using property/value pairs:\n\n@table @code\n@item Get\nCell array of name/value pairs for GET request parameters.\n\n@item Post\nCell array of name/value pairs for POST request parameters.\n\n@item Timeout\nTimeout value in seconds.\n\n@item UserAgent\nUser agent string for the request.\n\n@item Username\nUsername for authentication.\n\n@item Password\nPassword for authentication.\n\n@item Charset\nCharacter encoding (stored but not currently used).\n@end table\n\nExample with property/value pairs:\n\n@example\n@group\ns = urlread (\"http://www.example.com/data\",\n             \"Get\", @{\"term\", \"octave\"@}, \"Timeout\", 10);\n@end group\n@end example\n\nFor backward compatibility, the old calling form is also supported:\n\n@example\n@group\ns = urlread (\"http://www.google.com/search\",\n             \"get\", @{\"query\", \"octave\"@});\n@end group\n@end example\n@seealso{urlwrite, weboptions}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  // verify arguments\n  if (nargin < 1)\n    print_usage ();\n\n  std::string url = args(0).xstring_value (\"urlread: URL must be a string\");\n\n  std::string method = \"get\";\n  Array<std::string> param;\n\n  // Create a weboptions struct to hold option values\n  struct weboptions options;\n  // Set default timeout to match weboptions default\n  options.Timeout = 5000;  // 5 seconds in milliseconds\n\n  // Check if old calling form with 3 arguments (backward compatibility)\n  if (nargin == 3 && args(1).is_string ()\n      && (args(1).string_value () == \"get\" || args(1).string_value () == \"post\"))\n    {\n      // Old calling form: urlread(url, method, param)\n      method = args(1).xstring_value (\"urlread: METHOD must be a string\");\n\n      if (method != \"get\" && method != \"post\")\n        error (R\"(urlread: METHOD must be \"get\" or \"post\")\");\n\n      param = args(2).xcellstr_value (\"urlread: parameters (PARAM) for get and post requests must be given as a cell array of strings\");\n\n      if (param.numel () % 2 == 1)\n        error (\"urlread: number of elements in PARAM must be even\");\n    }\n  else if (nargin > 1)\n    {\n      // New property/value pairs form\n      parse_property_value_pairs (args, 1, options, method, param, \"urlread\");\n    }\n\n  std::ostringstream buf;\n\n  url_transfer url_xfer = url_transfer (url, buf);\n\n  if (! url_xfer.is_valid ())\n    error (\"support for URL transfers was disabled when Octave was built\");\n\n  // Apply weboptions if any were set\n  url_xfer.set_weboptions (options);\n\n  // Perform the HTTP action\n  url_xfer.http_action (param, method);\n\n  if (nargout < 2 && ! url_xfer.good ())\n    error (\"urlread: %s\", url_xfer.lasterror ().c_str ());\n\n  octave_value_list retval (std::max (1, std::min (nargout, 3)));\n\n  retval(0) = buf.str ();\n  if (nargout > 1)\n    retval(1) = url_xfer.good ();\n  if (nargout > 2)\n    retval(2) = url_xfer.good () ? \"\" : url_xfer.lasterror ();\n\n  return retval;\n}\n\nDEFUN (__restful_service__, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{response} =} __restful_service__ (@var{url}, @var{param}, @var{weboptions})\nUndocumented internal function.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1)\n    print_usage ();\n\n  std::string url = args(0).xstring_value (\"__restful_service__: URL must be a string\");\n\n  std::ostringstream content;\n\n  url_transfer url_xfer (url, content);\n\n  if (! url_xfer.is_valid ())\n    error (\"support for URL transfers was disabled when Octave was built\");\n\n  Array<std::string> param = args(1).cellstr_value ();\n\n  std::string data, method;\n\n  struct weboptions options;\n\n  cdef_object webopt\n    = args (nargin - 1).classdef_object_value () -> get_object ();\n\n  // We could have used webopt.map_value () instead to return a map, but that\n  // shows a warning about overriding access restrictions.\n  // Nevertheless, we are keeping checking that here if the keys are not\n  // equal to \"delete\" and \"display\", getting away with the warning.\n  string_vector keys = webopt.map_keys ();\n\n  for (int i = 0; i < keys.numel (); i++)\n    {\n      const std::string key = keys(i);\n      if (key == \"UserAgent\")\n        {\n          options.UserAgent = webopt.get (key).string_value ();\n        }\n      else if (key == \"Timeout\")\n        {\n          float timeout = webopt.get (key).float_value ();\n          // Convert milliseconds to seconds.\n          options.Timeout = static_cast<long> (timeout * 1000);\n        }\n      else if (key == \"Username\")\n        {\n          options.Username = webopt.get (key).string_value ();\n        }\n      else if (key == \"Password\")\n        {\n          options.Password = webopt.get (key).string_value ();\n        }\n      else if (key == \"ContentReader\")\n        {\n          // Unimplemented.  Only for MATLAB compatibility.\n          options.ContentReader = \"\";\n        }\n      else if (key == \"RequestMethod\")\n        {\n          method = webopt.get (key).string_value ();\n        }\n      else if (key == \"ArrayFormat\")\n        {\n          options.ArrayFormat = webopt.get (key).string_value ();\n        }\n      else if (key == \"HeaderFields\")\n        {\n          options.HeaderFields = webopt.get (key).cellstr_value ();\n        }\n      else if (key == \"CertificateFilename\")\n        {\n          options.CertificateFilename = webopt.get (key).string_value ();\n        }\n    }\n\n  url_xfer.set_weboptions (options);\n\n  url_xfer.http_action (param, method);\n\n  if (nargout < 2 && ! url_xfer.good ())\n    error (\"__restful_service__: %s\", url_xfer.lasterror ().c_str ());\n\n  return ovl (content.str ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/text-engine.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"text-engine.h\"\n#include \"oct-tex-symbols.cc\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nuint32_t\ntext_element_symbol::get_symbol_code () const\n{\n  uint32_t code = invalid_code;\n\n  if (0 <= m_symbol && m_symbol < num_symbol_codes)\n    code = symbol_codes[m_symbol][0];\n\n  return code;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/text-engine.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_text_engine_h)\n#define octave_text_engine_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <memory>\n#include <string>\n\n#include \"caseless-str.h\"\n#include \"dMatrix.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass text_element;\nclass text_element_string;\nclass text_element_symbol;\nclass text_element_list;\nclass text_element_subscript;\nclass text_element_superscript;\nclass text_element_combined;\nclass text_element_fontname;\nclass text_element_fontsize;\nclass text_element_fontstyle;\nclass text_element_color;\n\nclass text_processor;\n\nclass OCTINTERP_API text_element\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (text_element)\n\n  virtual ~text_element () = default;\n\n  virtual void accept (text_processor& p) = 0;\n};\n\nclass OCTINTERP_API text_element_string : public text_element\n{\npublic:\n\n  text_element_string (const std::string& s = \"\")\n    : text_element (), m_str (s) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_string)\n\n  std::string string_value () const { return m_str; }\n\n  void accept (text_processor& p);\n\nprivate:\n\n  std::string m_str;\n};\n\nclass OCTINTERP_API text_element_symbol : public text_element\n{\npublic:\n\n  enum { invalid_code = 0xFFFFFFFFU };\n\n  text_element_symbol () = delete;\n\n  text_element_symbol (int sym)\n    : text_element (), m_symbol (sym) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_symbol)\n\n  int get_symbol () const { return m_symbol; }\n\n  uint32_t get_symbol_code () const;\n\n  void accept (text_processor& p);\n\nprivate:\n  int m_symbol;\n};\n\nclass OCTINTERP_API text_element_list\n  : public text_element, public std::list<text_element *>\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (text_element_list)\n\n  text_element_list (text_element *e)\n    : text_element (), std::list<text_element*> ()\n  {\n    push_back (e);\n  }\n\n  ~text_element_list ()\n  {\n    while (! empty ())\n      {\n        auto it = begin ();\n        delete (*it);\n        erase (it);\n      }\n  }\n\n  void accept (text_processor& p);\n};\n\nclass OCTINTERP_API text_element_subscript : public text_element\n{\npublic:\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (text_element_subscript)\n\n  text_element_subscript (text_element *e)\n    : text_element (), m_elem (e) { }\n\n  text_element_subscript (char c)\n    : text_element ()\n  { m_elem = new text_element_string (std::string (1, c)); }\n\n  ~text_element_subscript ()\n  { delete m_elem; }\n\n  void accept (text_processor& p);\n\n  text_element * get_element () { return m_elem; }\n\nprivate:\n\n  text_element *m_elem;\n};\n\nclass OCTINTERP_API text_element_superscript : public text_element\n{\npublic:\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (text_element_superscript)\n\n  text_element_superscript (text_element *e)\n    : text_element (), m_elem (e) { }\n\n  text_element_superscript (char c)\n    : text_element ()\n  { m_elem = new text_element_string (std::string (1, c)); }\n\n  ~text_element_superscript ()\n  { delete m_elem; }\n\n  void accept (text_processor& p);\n\n  text_element * get_element () { return m_elem; }\n\nprivate:\n\n  text_element *m_elem;\n};\n\nclass OCTINTERP_API text_element_combined : public text_element_list\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (text_element_combined)\n\n  text_element_combined (text_element *e)\n    : text_element_list (e) { }\n\n  text_element_combined (text_element *e1, text_element *e2)\n    : text_element_list(e1)\n  { push_back (e2); }\n\n  void accept (text_processor& p);\n};\n\nclass OCTINTERP_API text_element_fontstyle : public text_element\n{\npublic:\n\n  enum fontstyle\n  {\n    normal,\n    bold,\n    italic,\n    oblique\n  };\n\n  text_element_fontstyle () = delete;\n\n  text_element_fontstyle (fontstyle st)\n    : text_element (), m_style (st) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_fontstyle)\n\n  fontstyle get_fontstyle () const { return m_style; }\n\n  void accept (text_processor& p);\n\nprivate:\n\n  fontstyle m_style;\n};\n\nclass OCTINTERP_API text_element_fontname : public text_element\n{\npublic:\n\n  text_element_fontname () = delete;\n\n  text_element_fontname (const std::string& fname)\n    : text_element (), m_name (fname) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_fontname)\n\n  const std::string& get_fontname () const { return m_name; }\n\n  void accept (text_processor& p);\n\nprivate:\n\n  std::string m_name;\n};\n\nclass OCTINTERP_API text_element_fontsize : public text_element\n{\npublic:\n\n  text_element_fontsize () = delete;\n\n  text_element_fontsize (double fsize)\n    : text_element (), m_size (fsize) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_fontsize)\n\n  double get_fontsize () const { return m_size; }\n\n  void accept (text_processor& p);\n\nprivate:\n\n  double m_size;\n};\n\nclass OCTINTERP_API text_element_color : public text_element\n{\npublic:\n\n  text_element_color () = delete;\n\n  text_element_color (double r, double g, double b)\n    : text_element (), m_rgb (1, 3, 0.0)\n  {\n    m_rgb(0) = r;\n    m_rgb(1) = g;\n    m_rgb(2) = b;\n  }\n\n  text_element_color (const std::string& cname)\n    : text_element (), m_rgb (1, 3, 0.0)\n  {\n#define ASSIGN_COLOR(r,g,b) { m_rgb(0) = r; m_rgb(1) = g; m_rgb(2) = b; }\n    if (cname == \"red\") ASSIGN_COLOR(1, 0, 0)\n      else if (cname == \"green\") ASSIGN_COLOR(0, 1, 0)\n        else if (cname == \"yellow\") ASSIGN_COLOR(1, 1, 0)\n          else if (cname == \"magenta\") ASSIGN_COLOR(1, 0, 1)\n            else if (cname == \"blue\") ASSIGN_COLOR(0, 0, 1)\n              else if (cname == \"black\") ASSIGN_COLOR(0, 0, 0)\n                else if (cname == \"white\") ASSIGN_COLOR(1, 1, 1)\n                  else if (cname == \"gray\") ASSIGN_COLOR(.5, .5, .5)\n                    else if (cname == \"darkGreen\") ASSIGN_COLOR(0, .5, 0)\n                      else if (cname == \"orange\") ASSIGN_COLOR(1, .65, 0)\n                        else if (cname == \"lightBlue\") ASSIGN_COLOR(0.68, .85, .9)\n#undef ASSIGN_COLOR\n                        }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_color)\n\n  Matrix get_color () { return m_rgb; }\n\n  void accept (text_processor& p);\n\nprivate:\n\n  Matrix m_rgb;\n};\n\nclass OCTINTERP_API text_processor\n{\npublic:\n\n  virtual void visit (text_element_string&) { }\n\n  virtual void visit (text_element_symbol&) { }\n\n  virtual void visit (text_element_list& e)\n  {\n    for (auto& el_p : e)\n      {\n        el_p->accept (*this);\n      }\n  }\n\n  virtual void visit (text_element_subscript& e)\n  { e.get_element ()->accept (*this); }\n\n  virtual void visit (text_element_superscript& e)\n  { e.get_element ()->accept (*this); }\n\n  virtual void visit (text_element_combined&) { }\n\n  virtual void visit (text_element_fontstyle&) { }\n\n  virtual void visit (text_element_fontname&) { }\n\n  virtual void visit (text_element_fontsize&) { }\n\n  virtual void visit (text_element_color&) { }\n\n  virtual void reset () { }\n\nprotected:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (text_processor)\n\n  virtual ~text_processor () = default;\n};\n\n#define TEXT_ELEMENT_ACCEPT(cls)                \\\n  inline void                                   \\\n  cls::accept (text_processor& p)               \\\n  {                                             \\\n    p.visit (*this);                            \\\n  }\n\nTEXT_ELEMENT_ACCEPT(text_element_string)\nTEXT_ELEMENT_ACCEPT(text_element_symbol)\nTEXT_ELEMENT_ACCEPT(text_element_list)\nTEXT_ELEMENT_ACCEPT(text_element_subscript)\nTEXT_ELEMENT_ACCEPT(text_element_superscript)\nTEXT_ELEMENT_ACCEPT(text_element_combined)\nTEXT_ELEMENT_ACCEPT(text_element_fontstyle)\nTEXT_ELEMENT_ACCEPT(text_element_fontname)\nTEXT_ELEMENT_ACCEPT(text_element_fontsize)\nTEXT_ELEMENT_ACCEPT(text_element_color)\n\nclass OCTINTERP_API text_parser\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (text_parser)\n\n  virtual ~text_parser () = default;\n\n  virtual text_element * parse (const std::string& s) = 0;\n\npublic:\n  static text_element * parse (const std::string& s,\n                              const caseless_str& interpreter);\n};\n\nclass OCTINTERP_API text_parser_none : public text_parser\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (text_parser_none)\n\n  // FIXME: is it possible to use reference counting to manage the\n  // memory for the object returned by the text parser?  That would be\n  // preferable to having to know when and where to delete the object it\n  // creates...\n\n  text_element * parse (const std::string& s)\n  {\n    return new text_element_string (s);\n  }\n};\n\nclass OCTINTERP_API text_parser_tex : public text_parser\n{\npublic:\n\n  text_parser_tex ()\n    : text_parser (), m_scanner (nullptr), m_buffer_state (nullptr),\n      m_result (nullptr)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (text_parser_tex)\n\n  ~text_parser_tex ()\n  { destroy_lexer (); }\n\n  text_element * parse (const std::string& s);\n\n  void * get_scanner () { return m_scanner; }\n\n  void set_parse_result (text_element *e) { m_result = e; }\n\n  text_element * get_parse_result () { return m_result; }\n\nprivate:\n  bool init_lexer (const std::string& s);\n\n  void destroy_lexer ();\n\n  //--------\n\n  void *m_scanner;\n\n  void *m_buffer_state;\n\n  text_element *m_result;\n};\n\ninline text_element *\ntext_parser::parse (const std::string& s, const caseless_str& interpreter)\n{\n  std::unique_ptr<text_parser> parser;\n\n  if (interpreter.compare (\"tex\"))\n    parser.reset (new text_parser_tex ());\n  else\n    parser.reset (new text_parser_none ());\n\n  return parser->parse (s);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/text-renderer.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"base-text-renderer.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ft-text-renderer.h\"\n#include \"latex-text-renderer.h\"\n#include \"text-renderer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntext_renderer::text_renderer ()\n  : m_rep (make_ft_text_renderer ()),\n    m_latex_rep (make_latex_text_renderer ())\n{ }\n\ntext_renderer::~text_renderer ()\n{\n  delete m_rep;\n  delete m_latex_rep;\n}\n\nbool\ntext_renderer::ok () const\n{\n  static bool warned = false;\n\n  if (! m_rep)\n    {\n      if (! warned)\n        {\n          warn_disabled_feature (\"opengl_renderer::render_text\",\n                                 \"rendering text (FreeType)\");\n\n          warned = true;\n        }\n    }\n\n  return m_rep != nullptr;\n}\n\nMatrix\ntext_renderer::get_extent (text_element *elt, double rotation)\n{\n  static Matrix empty_extent (1, 4, 0.0);\n\n  return ok () ? m_rep->get_extent (elt, rotation) : empty_extent;\n}\n\nMatrix\ntext_renderer::get_extent (const std::string& txt, double rotation,\n                           const caseless_str& interpreter)\n{\n  static Matrix retval (1, 4, 0.0);\n\n  if (interpreter == \"latex\" && m_latex_rep->ok ())\n    retval = m_latex_rep->get_extent (txt, rotation, interpreter);\n  else if (ok ())\n    retval = m_rep->get_extent (txt, rotation, interpreter);\n\n  return retval;\n}\n\nvoid\ntext_renderer::set_anti_aliasing (bool val)\n{\n  if (ok ())\n    m_rep->set_anti_aliasing (val);\n}\n\noctave_map\ntext_renderer::get_system_fonts ()\n{\n  octave_map retval;\n\n  if (ok ())\n    retval = m_rep->get_system_fonts ();\n\n  return retval;\n}\n\nvoid\ntext_renderer::set_font (const std::string& name, const std::string& weight,\n                         const std::string& angle, double size)\n{\n  if (ok ())\n    {\n      m_rep->set_font (name, weight, angle, size);\n      m_latex_rep->set_font (name, weight, angle, size);\n    }\n}\n\nvoid\ntext_renderer::set_color (const Matrix& c)\n{\n  if (ok ())\n    {\n      m_rep->set_color (c);\n      m_latex_rep->set_color (c);\n    }\n}\n\nvoid\ntext_renderer::text_to_pixels (const std::string& txt,\n                               uint8NDArray& pxls, Matrix& bbox,\n                               int halign, int valign, double rotation,\n                               const caseless_str& interpreter,\n                               bool handle_rotation)\n{\n  static Matrix empty_bbox (1, 4, 0.0);\n  static uint8NDArray empty_pxls;\n\n  if (interpreter == \"latex\" && m_latex_rep->ok ())\n    m_latex_rep->text_to_pixels (txt, pxls, bbox, halign, valign, rotation,\n                                 interpreter, handle_rotation);\n  else if (ok ())\n    m_rep->text_to_pixels (txt, pxls, bbox, halign, valign, rotation,\n                           interpreter, handle_rotation);\n  else\n    {\n      bbox = empty_bbox;\n      pxls = empty_pxls;\n    }\n}\n\nvoid\ntext_renderer::text_to_strlist (const std::string& txt,\n                                std::list<text_renderer::string>& lst,\n                                Matrix& bbox, int halign, int valign,\n                                double rotation,\n                                const caseless_str& interpreter)\n{\n  static Matrix empty_bbox (1, 4, 0.0);\n  static std::list<text_renderer::string> empty_lst;\n\n  if (interpreter == \"latex\" && m_latex_rep->ok ())\n    m_latex_rep->text_to_strlist (txt, lst, bbox, halign, valign, rotation,\n                                  interpreter);\n  else if (ok ())\n    m_rep->text_to_strlist (txt, lst, bbox, halign, valign, rotation,\n                            interpreter);\n  else\n    {\n      bbox = empty_bbox;\n      lst = empty_lst;\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/text-renderer.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_text_renderer_h)\n#define octave_text_renderer_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n#include <vector>\n\n#include \"caseless-str.h\"\n#include \"dMatrix.h\"\n#include \"uint8NDArray.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_text_renderer;\nclass text_element;\n\nclass OCTINTERP_API text_renderer\n{\npublic:\n\n  text_renderer ();\n\n  OCTAVE_DISABLE_COPY_MOVE (text_renderer)\n\n  ~text_renderer ();\n\n  bool ok () const;\n\n  Matrix get_extent (text_element *elt, double rotation = 0.0);\n\n  Matrix get_extent (const std::string& txt, double rotation = 0.0,\n                     const caseless_str& interpreter = \"tex\");\n\n  void set_anti_aliasing (bool val);\n\n  void set_font (const std::string& name, const std::string& weight,\n                 const std::string& angle, double size);\n\n  octave_map get_system_fonts ();\n\n  void set_color (const Matrix& c);\n\n  void text_to_pixels (const std::string& txt,\n                       uint8NDArray& pxls, Matrix& bbox,\n                       int halign, int valign, double rotation = 0.0,\n                       const caseless_str& interpreter = \"tex\",\n                       bool handle_rotation = true);\n\n  class font\n  {\n  public:\n\n    font ()\n      : m_name (), m_weight (), m_angle (), m_size (0)\n    { }\n\n    font (const std::string& nm, const std::string& wt,\n          const std::string& ang, double sz)\n      : m_name (nm), m_weight (wt), m_angle (ang), m_size (sz)\n    { }\n\n    font (const font& ft)\n      : m_name (ft.m_name), m_weight (ft.m_weight), m_angle (ft.m_angle),\n        m_size (ft.m_size)\n    { }\n\n    ~font () = default;\n\n    font& operator = (const font& ft)\n    {\n      if (&ft != this)\n        {\n          m_name = ft.m_name;\n          m_weight = ft.m_weight;\n          m_angle = ft.m_angle;\n          m_size = ft.m_size;\n        }\n\n      return *this;\n    }\n\n    std::string get_name () const { return m_name; }\n\n    std::string get_weight () const { return m_weight; }\n\n    std::string get_angle () const { return m_angle; }\n\n    double get_size () const { return m_size; }\n\n  protected:\n\n    std::string m_name;\n    std::string m_weight;\n    std::string m_angle;\n    double m_size;\n  };\n\n  // Container for substrings after parsing.\n\n  class string\n  {\n  public:\n\n    string () = delete;\n\n    string (const std::string& s, const font& f, double x, double y)\n      : m_str (s), m_family (f.get_name ()), m_fnt (f), m_x (x), m_y (y),\n        m_z (0.0), m_xdata (), m_code (0), m_color (Matrix (1, 3, 0.0)),\n        m_svg_element ()\n    { }\n\n    OCTAVE_DEFAULT_COPY_MOVE_DELETE (string)\n\n    void set_string (const std::string& s) { m_str = s; }\n\n    std::string get_string () const { return m_str; }\n\n    std::string get_name () const { return m_fnt.get_name (); }\n\n    std::string get_family () const { return m_family; }\n\n    void set_family (const std::string& nm) { m_family = nm; }\n\n    std::string get_weight () const { return m_fnt.get_weight (); }\n\n    std::string get_angle () const { return m_fnt.get_angle (); }\n\n    double get_size () const { return m_fnt.get_size (); }\n\n    void set_x (const double x) { m_x = x; }\n\n    double get_x () const { return m_x; }\n\n    void set_xdata (const std::vector<double>& x) { m_xdata = x; }\n\n    std::vector<double> get_xdata () const { return m_xdata; }\n\n    void set_y (const double y) { m_y = y; }\n\n    double get_y () const { return m_y; }\n\n    void set_z (const double z) { m_z = z; }\n\n    double get_z () const { return m_z; }\n\n    void set_code (const uint32_t code) { m_code = code; }\n\n    uint32_t get_code () const { return m_code; }\n\n    void set_svg_element (const std::string& svg) { m_svg_element = svg; }\n\n    std::string get_svg_element () const { return m_svg_element; }\n\n    void set_color (const uint8NDArray& c)\n    {\n      m_color(0) = static_cast<double> (c(0)) / 255;\n      m_color(1) = static_cast<double> (c(1)) / 255;\n      m_color(2) = static_cast<double> (c(2)) / 255;\n    }\n\n    Matrix get_color () const { return m_color; }\n\n  private:\n\n    std::string m_str;\n    std::string m_family;\n    font m_fnt;\n    double m_x, m_y, m_z;\n    std::vector<double> m_xdata;\n    uint32_t m_code;\n    Matrix m_color;\n    std::string m_svg_element;\n  };\n\n  void text_to_strlist (const std::string& txt,\n                        std::list<string>& lst, Matrix& box,\n                        int halign, int valign, double rotation = 0.0,\n                        const caseless_str& interpreter = \"tex\");\n\nprivate:\n\n  base_text_renderer *m_rep;\n  base_text_renderer *m_latex_rep;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/toplev.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n#include <new>\n#include <sstream>\n#include <string>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  define WIN32_LEAN_AND_MEAN 1\n#  include <windows.h>\n#endif\n\n#include \"async-system-wrapper.h\"\n#include \"child-list.h\"\n#include \"oct-error.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-syscalls.h\"\n#include \"signal-wrappers.h\"\n#include \"str-vec.h\"\n#include \"wait-for-input.h\"\n\n#include \"build-env.h\"\n#include \"liboctinterp-build-info.h\"\n#include \"defaults.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"help.h\"\n#include \"interpreter-private.h\"\n#include \"octave.h\"\n#include \"oct-map.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"pager.h\"\n#include \"procstream.h\"\n#include \"sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"version.h\"\n\n#if ! defined (SHELL_PATH)\n#  define SHELL_PATH \"/bin/sh\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#define STRINGIFY(s) STRINGIFY1(s)\n#define STRINGIFY1(s) #s\n\nDEFUN (warranty, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {} warranty ()\nDescribe the conditions for copying and distributing Octave.\n@end deftypefn */)\n{\n  octave_stdout << \"\\n\" << octave_name_version_copyright () << \"\\n\\\n\\n\\\nGNU Octave is free software: you can redistribute it and/or modify it\\n\\\nunder the terms of the GNU General Public License as published by\\n\\\nthe Free Software Foundation, either version 3 of the License, or\\n\\\n(at your option) any later version.\\n\\\n\\n\\\nGNU Octave is distributed in the hope that it will be useful, but\\n\\\nWITHOUT ANY WARRANTY; without even the implied warranty of\\n\\\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n\\\nGNU General Public License for more details.\\n\\\n\\n\\\nYou should have received a copy of the GNU General Public License\\n\\\nalong with GNU Octave; see the file COPYING.  If not, see\\n\\\n<https://gnu.org/licenses/gpl.html>.\\n\\\n\\n\";\n\n  return ovl ();\n}\n\n// Execute a shell command.\n\nstatic octave_value_list\nrun_command_and_return_output (const std::string& cmd_str)\n{\n  octave_value_list retval;\n  unwind_protect frame;\n\n  iprocstream *cmd = new iprocstream (cmd_str.c_str ());\n  frame.add_delete (cmd);\n\n  child_list& kids = __get_child_list__ ();\n  frame.add (&child_list::remove, kids, cmd->pid ());\n\n  if (! *cmd)\n    error (\"system: unable to start subprocess for '%s'\", cmd_str.c_str ());\n\n  int fid = cmd->file_number ();\n\n  std::ostringstream output_buf;\n\n  char ch;\n\n  for (;;)\n    {\n      if (cmd->get (ch))\n        output_buf.put (ch);\n      else\n        {\n          if (! cmd->eof () && errno == EAGAIN)\n            {\n              cmd->clear ();\n\n              if (octave_wait_for_input (fid) != 1)\n                break;\n            }\n          else\n            break;\n        }\n    }\n\n  int cmd_status = cmd->close ();\n\n  if (sys::wifexited (cmd_status))\n    cmd_status = sys::wexitstatus (cmd_status);\n  else\n    cmd_status = 127;\n\n  retval = ovl (cmd_status, output_buf.str ());\n\n  return retval;\n}\n\n// Combine alloc+get in one action.\n\nstatic void *\nget_signal_mask ()\n{\n  void *mask = octave_alloc_signal_mask ();\n\n  octave_get_signal_mask (mask);\n\n  return mask;\n}\n\n// Combine set+free in one action.\n\nstatic void\nrestore_signal_mask (void *mask)\n{\n  octave_set_signal_mask (mask);\n\n  octave_free_signal_mask (mask);\n}\n\nenum system_exec_type { et_sync, et_async };\n\nDEFUN (system, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} system (\"@var{string}\")\n@deftypefnx {} {} system (\"@var{string}\", @var{return_output})\n@deftypefnx {} {} system (\"@var{string}\", @var{return_output}, @var{type})\n@deftypefnx {} {[@var{status}, @var{output}] =} system (@dots{})\nExecute a shell command specified by @var{string}.\n\nIf @var{system} is called with one or more output arguments, or if the optional\nargument @var{return_output} is true and the subprocess is started\nsynchronously, then the output from the command is returned as a variable.\nOtherwise, if the subprocess is executed synchronously, its output is sent to\nthe standard output.  To send the output of a command executed with\n@code{system} through the pager, use a command like\n\n@example\n@group\n[~, text] = system (\"cmd\");\nmore on;\ndisp (text);\n@end group\n@end example\n\n@noindent\nor\n\n@example\n@group\nmore on;\nprintf (\"%s\\n\", nthargout (2, \"system\", \"cmd\"));\n@end group\n@end example\n\nIf the optional argument @var{type} is @qcode{\"async\"}, the process is started\nin the background and the process ID of the child process is returned\nimmediately.  Otherwise, the child process is started and Octave waits until it\nexits.  If the @var{type} argument is omitted, it defaults to the value\n@qcode{\"sync\"}.\n\nThe @code{system} function can return two values.  The first is the exit status\nof the command and the second is any output from the command that was written\nto the standard output stream.  For example,\n\n@example\n[status, output] = system (\"echo foo & exit 2\");\n@end example\n\n@noindent\nwill set the variable @var{output} to the string @samp{foo}, and the variable\n@var{status} to the integer @samp{2}.\n\nFor commands run asynchronously, @var{status} is the process id of the command\nshell that is started to run the command.\n\nThe shell used for executing commands varies with operating system and is\ntypically @file{/bin/sh} for UNIX systems and @nospell{@file{cmd.exe}} for\nWindows systems.\n@seealso{unix, dos}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0 || nargin > 3)\n    print_usage ();\n\n  std::string cmd_str = args(0).xstring_value (\"system: first argument must be a string\");\n\n  bool return_output = (nargin == 1 && nargout > 1);\n  if (nargin > 1)\n    return_output = args(1).strict_bool_value (\"system: RETURN_OUTPUT must be boolean value true or false\");\n\n  system_exec_type type = et_sync;\n  if (nargin == 3)\n    {\n      std::string type_str = args(2).xstring_value (\"system: TYPE must be a string\");\n\n      if (type_str == \"sync\")\n        type = et_sync;\n      else if (type_str == \"async\")\n        type = et_async;\n      else\n        error (R\"(system: TYPE must be \"sync\" or \"async\")\");\n    }\n\n  if (return_output && type == et_async)\n    error (\"system: can't return output from commands run asynchronously\");\n\n  octave_value_list retval;\n\n  unwind_action restore_mask\n  ([] (void *mask) { restore_signal_mask (mask); }, get_signal_mask ());\n\n  octave_unblock_async_signals ();\n  octave_unblock_signal_by_name (\"SIGTSTP\");\n\n  if (type == et_async)\n    retval(0) = octave_async_system_wrapper (cmd_str.c_str ());\n  else if (return_output)\n    retval = run_command_and_return_output (cmd_str);\n  else\n    {\n      int status = sys::system (cmd_str);\n\n      // The value in status is as returned by waitpid.  If the process exited\n      // normally, extract the actual exit status of the command.  Otherwise,\n      // return 127 as a failure code.\n\n      if (sys::wifexited (status))\n        status = sys::wexitstatus (status);\n\n      retval(0) = status;\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! cmd = ls_command ();\n%! [status, output] = system (cmd);\n%! assert (status, 0);\n%! assert (ischar (output));\n%! assert (! isempty (output));\n\n%!shared octave_exe_path, nul_device\n%! exe_ext = __octave_config_info__ (\"EXEEXT\");\n%! octave_path = getenv (\"OCTAVE_BINDIR\");\n%! if (isempty (octave_path))\n%!   octave_path = EXEC_PATH;\n%! endif\n%! octave_exe_path = file_in_path (octave_path, [\"octave\", exe_ext]);\n%! if (ispc ())\n%!   nul_device = \"nul\";\n%! else\n%!   nul_device = \"/dev/null\";\n%! endif\n\n## Test double-quoted commands and redirecting output\n%!test <*68033>\n%! status = system (sprintf ('\"%s\" \"--version\" 1>%s 2>&1', ...\n%!                           octave_exe_path, nul_device));\n%! assert (status, 0);\n\n## Test double-quoted commands and redirecting output capturing output\n%!test <*68033>\n%! [status, output] = system (sprintf ('\"%s\" \"--version\" 1>%s 2>&1', ...\n%!                                     octave_exe_path, nul_device));\n%! assert (status, 0);\n%! assert (ischar (output));\n%! assert (output, \"\");\n\n## Test double-quoted commands capturing output\n%!test <*68033>\n%! [status, output] = system (sprintf ('\"%s\" \"--version\" 2>&1', ...\n%!                                     octave_exe_path));\n%! assert (status, 0);\n%! assert (ischar (output));\n%! assert (! isempty (output));\n\n%!error <Invalid call> system ()\n%!error <Invalid call> system (1, 2, 3, 4)\n%!error <first argument must be a string> system (1)\n%!error <RETURN_OUTPUT must be boolean value> system (\"cd\", \"foo\")\n%!error <TYPE must be a string> system (\"cd\", true, 1)\n%!error <TYPE must be .*sync.* or .*async> system (\"cd\", true, \"foo\")\n%!warning <converted to logical 1> system (ls_command (), 0.5);\n*/\n\nstatic octave_value\nfind_config_info (const octave_scalar_map& m, const std::string& key)\n{\n  if (m.isfield (key))\n    {\n      Cell c = m.contents (key);\n\n      if (! c.isempty ())\n        return c(0);\n    }\n\n  return octave_value ();\n}\n\nDEFUN (__octave_config_info__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{S} =} __octave_config_info__ ()\n@deftypefnx {} {@var{S} =} __octave_config_info__ (@var{option})\nReturn a structure containing configuration and installation information for\nOctave.\n\nIf @var{option} is a string, return the configuration information for the\nspecified option.\n\n@seealso{computer}\n@end deftypefn */)\n{\n  static octave_scalar_map config;\n  static octave_scalar_map build_env;\n  static octave_scalar_map build_features;\n\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n      std::map<std::string, octave_value> conf_info_map\n      = {{ \"DEFAULT_PAGER\", config::default_pager () },\n\n#if defined (OCTAVE_ENABLE_64)\n        { \"ENABLE_64\", true },\n#else\n        { \"ENABLE_64\", false },\n#endif\n\n#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)\n        { \"ENABLE_COMMAND_LINE_PUSH_PARSER\", true },\n#else\n        { \"ENABLE_COMMAND_LINE_PUSH_PARSER\", false },\n#endif\n\n#if defined (ENABLE_DOCS)\n        { \"ENABLE_DOCS\", true },\n#else\n        { \"ENABLE_DOCS\", false },\n#endif\n\n#if defined (OCTAVE_ENABLE_OPENMP)\n        { \"ENABLE_OPENMP\", true },\n#else\n        { \"ENABLE_OPENMP\", false },\n#endif\n\n        { \"api_version\", OCTAVE_API_VERSION },\n        { \"archlibdir\", config::arch_lib_dir () },\n        { \"bindir\", config::bin_dir () },\n        { \"canonical_host_type\", config::canonical_host_type () },\n        { \"datadir\", config::data_dir () },\n        { \"datarootdir\", config::dataroot_dir () },\n        { \"fcnfiledir\", config::fcn_file_dir () },\n        { \"fftw_version\", fftw_version () },\n        { \"fftwf_version\", fftwf_version () },\n        { \"imagedir\", config::image_dir () },\n        { \"includedir\", config::include_dir () },\n        { \"infodir\", config::info_dir () },\n        { \"libdir\", config::lib_dir () },\n        { \"libexecdir\", config::libexec_dir () },\n        // Each library and executable has its own definition of the hg\n        // id.  We check for consistency when Octave starts so we just\n        // store and report one of them here.\n        { \"hg_id\", liboctinterp_hg_id () },\n        { \"localapiarchlibdir\", config::local_api_arch_lib_dir () },\n        { \"localapifcnfiledir\", config::local_api_fcn_file_dir () },\n        { \"localapioctfiledir\", config::local_api_oct_file_dir () },\n        { \"localapipkgdir\", config::local_api_pkg_dir () },\n        { \"localarchlibdir\", config::local_arch_lib_dir () },\n        { \"localfcnfiledir\", config::local_fcn_file_dir () },\n        { \"localoctfiledir\", config::local_oct_file_dir () },\n        { \"localstartupfiledir\", config::local_startupfile_dir () },\n        { \"localverarchlibdir\", config::local_ver_arch_lib_dir () },\n        { \"localverfcnfiledir\", config::local_ver_fcn_file_dir () },\n        { \"localveroctfiledir\", config::local_ver_oct_file_dir () },\n        { \"major_version\", STRINGIFY (OCTAVE_MAJOR_VERSION) },\n        { \"man1dir\", config::man1_dir () },\n        { \"man1ext\", config::man1_ext () },\n        { \"mandir\", config::man_dir () },\n        { \"minor_version\", STRINGIFY (OCTAVE_MINOR_VERSION) },\n        { \"octdatadir\", config::oct_data_dir () },\n        { \"octdocdir\", config::oct_doc_dir () },\n        { \"octetcdir\", config::oct_etc_dir () },\n        { \"octfiledir\", config::oct_file_dir () },\n        { \"octfontsdir\", config::oct_fonts_dir () },\n        { \"octincludedir\", config::oct_include_dir () },\n        { \"octlibdir\", config::oct_lib_dir () },\n        { \"octtestsdir\", config::oct_tests_dir () },\n        { \"patch_version\", STRINGIFY (OCTAVE_PATCH_VERSION) },\n        { \"release_date\", OCTAVE_RELEASE_DATE },\n        { \"startupfiledir\", config::startupfile_dir () },\n        { \"version\", OCTAVE_VERSION }\n      };\n\n      std::map<std::string, octave_value> build_env_map\n      = {{ \"AMD_CPPFLAGS\", build_env::AMD_CPPFLAGS },\n        { \"AMD_LDFLAGS\", build_env::AMD_LDFLAGS },\n        { \"AMD_LIBS\", build_env::AMD_LIBS },\n        { \"AR\", build_env::AR },\n        { \"ARFLAGS\", build_env::ARFLAGS },\n        { \"ARPACK_CPPFLAGS\", build_env::ARPACK_CPPFLAGS },\n        { \"ARPACK_LDFLAGS\", build_env::ARPACK_LDFLAGS },\n        { \"ARPACK_LIBS\", build_env::ARPACK_LIBS },\n        { \"BLAS_LIBS\", build_env::BLAS_LIBS },\n        { \"CAMD_CPPFLAGS\", build_env::CAMD_CPPFLAGS },\n        { \"CAMD_LDFLAGS\", build_env::CAMD_LDFLAGS },\n        { \"CAMD_LIBS\", build_env::CAMD_LIBS },\n        { \"CARBON_LIBS\", build_env::CARBON_LIBS },\n        { \"CC\", build_env::CC },\n        { \"CCOLAMD_CPPFLAGS\", build_env::CCOLAMD_CPPFLAGS },\n        { \"CCOLAMD_LDFLAGS\", build_env::CCOLAMD_LDFLAGS },\n        { \"CCOLAMD_LIBS\", build_env::CCOLAMD_LIBS },\n        { \"CFLAGS\", build_env::CFLAGS },\n        { \"CHOLMOD_CPPFLAGS\", build_env::CHOLMOD_CPPFLAGS },\n        { \"CHOLMOD_LDFLAGS\", build_env::CHOLMOD_LDFLAGS },\n        { \"CHOLMOD_LIBS\", build_env::CHOLMOD_LIBS },\n        { \"COLAMD_CPPFLAGS\", build_env::COLAMD_CPPFLAGS },\n        { \"COLAMD_LDFLAGS\", build_env::COLAMD_LDFLAGS },\n        { \"COLAMD_LIBS\", build_env::COLAMD_LIBS },\n        { \"CPICFLAG\", build_env::CPICFLAG },\n        { \"CPPFLAGS\", build_env::CPPFLAGS },\n        { \"CURL_CPPFLAGS\", build_env::CURL_CPPFLAGS },\n        { \"CURL_LDFLAGS\", build_env::CURL_LDFLAGS },\n        { \"CURL_LIBS\", build_env::CURL_LIBS },\n        { \"CXSPARSE_CPPFLAGS\", build_env::CXSPARSE_CPPFLAGS },\n        { \"CXSPARSE_LDFLAGS\", build_env::CXSPARSE_LDFLAGS },\n        { \"CXSPARSE_LIBS\", build_env::CXSPARSE_LIBS },\n        { \"CXX\", build_env::CXX },\n        { \"CXXCPP\", build_env::CXXCPP },\n        { \"CXXFLAGS\", build_env::CXXFLAGS },\n        { \"CXXPICFLAG\", build_env::CXXPICFLAG },\n        { \"DEFS\", build_env::DEFS },\n        { \"DL_LDFLAGS\", build_env::DL_LDFLAGS },\n        { \"GCC_VERSION\", build_env::GCC_VERSION },\n        { \"GXX_VERSION\", build_env::GXX_VERSION },\n        { \"EXEEXT\", build_env::EXEEXT },\n        { \"F77\", build_env::F77 },\n        { \"F77_FLOAT_STORE_FLAG\", build_env::F77_FLOAT_STORE_FLAG },\n        { \"F77_INTEGER_8_FLAG\", build_env::F77_INTEGER_8_FLAG },\n        { \"FFLAGS\", build_env::FFLAGS },\n        { \"FFTW3_CPPFLAGS\", build_env::FFTW3_CPPFLAGS },\n        { \"FFTW3_LDFLAGS\", build_env::FFTW3_LDFLAGS },\n        { \"FFTW3_LIBS\", build_env::FFTW3_LIBS },\n        { \"FFTW3F_CPPFLAGS\", build_env::FFTW3F_CPPFLAGS },\n        { \"FFTW3F_LDFLAGS\", build_env::FFTW3F_LDFLAGS },\n        { \"FFTW3F_LIBS\", build_env::FFTW3F_LIBS },\n        { \"FLIBS\", build_env::FLIBS },\n        { \"FLTK_CPPFLAGS\", build_env::FLTK_CPPFLAGS },\n        { \"FLTK_LDFLAGS\", build_env::FLTK_LDFLAGS },\n        { \"FLTK_LIBS\", build_env::FLTK_LIBS },\n        { \"FONTCONFIG_CPPFLAGS\", build_env::FONTCONFIG_CPPFLAGS },\n        { \"FONTCONFIG_LIBS\", build_env::FONTCONFIG_LIBS },\n        { \"FPICFLAG\", build_env::FPICFLAG },\n        { \"FT2_CPPFLAGS\", build_env::FT2_CPPFLAGS },\n        { \"FT2_LIBS\", build_env::FT2_LIBS },\n        { \"GLPK_CPPFLAGS\", build_env::GLPK_CPPFLAGS },\n        { \"GLPK_LDFLAGS\", build_env::GLPK_LDFLAGS },\n        { \"GLPK_LIBS\", build_env::GLPK_LIBS },\n        { \"GNUPLOT\", build_env::GNUPLOT },\n        { \"HDF5_CPPFLAGS\", build_env::HDF5_CPPFLAGS },\n        { \"HDF5_LDFLAGS\", build_env::HDF5_LDFLAGS },\n        { \"HDF5_LIBS\", build_env::HDF5_LIBS },\n        { \"LAPACK_LIBS\", build_env::LAPACK_LIBS },\n        { \"LDFLAGS\", build_env::LDFLAGS },\n        { \"LD_STATIC_FLAG\", build_env::LD_STATIC_FLAG },\n        { \"LEX\", build_env::LEX },\n        { \"LEXLIB\", build_env::LEXLIB },\n        { \"LFLAGS\", build_env::LFLAGS },\n        { \"LIBOCTAVE\", build_env::LIBOCTAVE },\n        { \"LIBOCTINTERP\", build_env::LIBOCTINTERP },\n        { \"LIBS\", build_env::LIBS },\n        { \"LN_S\", build_env::LN_S },\n        { \"MAGICK_CPPFLAGS\", build_env::MAGICK_CPPFLAGS },\n        { \"MAGICK_LDFLAGS\", build_env::MAGICK_LDFLAGS },\n        { \"MAGICK_LIBS\", build_env::MAGICK_LIBS },\n        { \"MKOCTFILE_DL_LDFLAGS\", build_env::MKOCTFILE_DL_LDFLAGS },\n        { \"OCTAVE_LINK_DEPS\", build_env::OCTAVE_LINK_DEPS },\n        { \"OCTAVE_LINK_OPTS\", build_env::OCTAVE_LINK_OPTS },\n        { \"OCT_LINK_DEPS\", build_env::OCT_LINK_DEPS },\n        { \"OCT_LINK_OPTS\", build_env::OCT_LINK_OPTS },\n        { \"OPENGL_LIBS\", build_env::OPENGL_LIBS },\n        { \"PCRE_CPPFLAGS\", build_env::PCRE_CPPFLAGS },\n        { \"PCRE_LDFLAGS\", build_env::PCRE_LDFLAGS },\n        { \"PCRE_LIBS\", build_env::PCRE_LIBS },\n        { \"PTHREAD_CFLAGS\", build_env::PTHREAD_CFLAGS },\n        { \"PTHREAD_LIBS\", build_env::PTHREAD_LIBS },\n        { \"QHULL_CPPFLAGS\", build_env::QHULL_CPPFLAGS },\n        { \"QHULL_LDFLAGS\", build_env::QHULL_LDFLAGS },\n        { \"QHULL_LIBS\", build_env::QHULL_LIBS },\n        { \"QRUPDATE_CPPFLAGS\", build_env::QRUPDATE_CPPFLAGS },\n        { \"QRUPDATE_LDFLAGS\", build_env::QRUPDATE_LDFLAGS },\n        { \"QRUPDATE_LIBS\", build_env::QRUPDATE_LIBS },\n        { \"QT_CPPFLAGS\", build_env::QT_CPPFLAGS },\n        { \"QT_LDFLAGS\", build_env::QT_LDFLAGS },\n        { \"QT_LIBS\", build_env::QT_LIBS },\n        { \"RANLIB\", build_env::RANLIB },\n        { \"RDYNAMIC_FLAG\", build_env::RDYNAMIC_FLAG },\n        { \"READLINE_LIBS\", build_env::READLINE_LIBS },\n        { \"SHARED_LIBS\", build_env::SHARED_LIBS },\n        { \"SH_LDFLAGS\", build_env::SH_LDFLAGS },\n        { \"STATIC_LIBS\", build_env::STATIC_LIBS },\n        { \"SUITESPARSECONFIG_LIBS\", build_env::SUITESPARSECONFIG_LIBS },\n        { \"UMFPACK_CPPFLAGS\", build_env::UMFPACK_CPPFLAGS },\n        { \"UMFPACK_LDFLAGS\", build_env::UMFPACK_LDFLAGS },\n        { \"UMFPACK_LIBS\", build_env::UMFPACK_LIBS },\n        { \"WARN_CFLAGS\", build_env::WARN_CFLAGS },\n        { \"WARN_CXXFLAGS\", build_env::WARN_CXXFLAGS },\n        { \"X11_INCFLAGS\", build_env::X11_INCFLAGS },\n        { \"X11_LIBS\", build_env::X11_LIBS },\n        { \"XTRA_CFLAGS\", build_env::XTRA_CFLAGS },\n        { \"XTRA_CXXFLAGS\", build_env::XTRA_CXXFLAGS },\n        { \"YACC\", build_env::YACC },\n        { \"YFLAGS\", build_env::YFLAGS },\n        { \"Z_CPPFLAGS\", build_env::Z_CPPFLAGS },\n        { \"Z_LDFLAGS\", build_env::Z_LDFLAGS },\n        { \"Z_LIBS\", build_env::Z_LIBS },\n        { \"config_opts\", build_env::config_opts }\n      };\n\n      config = octave_scalar_map (conf_info_map);\n      build_env = octave_scalar_map (build_env_map);\n      build_features = build_env::features ();\n\n      bool unix_system = true;\n      bool mac_system = false;\n      bool windows_system = false;\n\n#if defined (__WIN32__)\n      windows_system = true;\n#if ! defined (__CYGWIN__)\n      unix_system = false;\n#endif\n#endif\n\n#if defined (OCTAVE_USE_OS_X_API)\n      mac_system = true;\n#endif\n\n      config.assign (\"unix\", octave_value (unix_system));\n      config.assign (\"mac\", octave_value (mac_system));\n      config.assign (\"windows\", octave_value (windows_system));\n\n      mach_info::float_format ff = mach_info::native_float_format ();\n      config.assign (\"float_format\",\n                     octave_value (mach_info::float_format_as_string (ff)));\n\n      config.assign (\"words_big_endian\",\n                     octave_value (mach_info::words_big_endian ()));\n\n      config.assign (\"words_little_endian\",\n                     octave_value (mach_info::words_little_endian ()));\n\n      config.assign (\"nan_with_payload\",\n                     octave_value (mach_info::nan_with_payload ()));\n\n      config.assign (\"build_environment\", octave_value (build_env));\n\n      config.assign (\"build_features\", octave_value (build_features));\n\n      initialized = true;\n    }\n\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  octave_value_list retval;\n\n  if (nargin == 1)\n    {\n      std::string arg = args(0).xstring_value (\"__octave_config_info__: OPTION argument must be a string\");\n\n      octave_value info = find_config_info (config, arg);\n\n      if (info.is_undefined ())\n        info = find_config_info (build_env, arg);\n\n      if (info.is_undefined ())\n        info = find_config_info (build_features, arg);\n\n      if (info.is_undefined ())\n        error (\"__octave_config_info__: no info for '%s'\", arg.c_str ());\n\n      return info;\n    }\n  else\n    retval = ovl (config);\n\n  return retval;\n}\n\n/*\n%!assert (ischar (__octave_config_info__ (\"version\")))\n%!assert (__octave_config_info__ (\"version\"), OCTAVE_VERSION ())\n%!test\n%! x = __octave_config_info__ ();\n%! assert (isstruct (x));\n%! assert (! isempty (x));\n%! assert (x.version, OCTAVE_VERSION ());\n\n%!error __octave_config_info__ (1, 2)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/url-handle-manager.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Extracted from urlwrite.cc.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include \"url-handle-manager.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic double\nmake_handle_fraction ()\n{\n  static double maxrand = RAND_MAX + 2.0;\n\n  return (rand () + 1.0) / maxrand;\n}\n\nurl_handle\nurl_handle_manager::get_handle ()\n{\n  url_handle retval;\n\n  // Curl handles are negative integers plus some random fractional\n  // part.  To avoid running out of integers, we recycle the integer\n  // part but tack on a new random part each time.\n\n  auto p = m_handle_free_list.begin ();\n\n  if (p != m_handle_free_list.end ())\n    {\n      retval = *p;\n      m_handle_free_list.erase (p);\n    }\n  else\n    {\n      retval = url_handle (m_next_handle);\n\n      m_next_handle = std::ceil (m_next_handle) - 1.0 - make_handle_fraction ();\n    }\n\n  return retval;\n}\n\nvoid\nurl_handle_manager::free (const url_handle& h)\n{\n  if (h.ok ())\n    {\n      auto p = m_handle_map.find (h);\n\n      if (p == m_handle_map.end ())\n        error (\"url_handle_manager::free: invalid object %g\", h.value ());\n\n      // Curl handles are negative integers plus some random\n      // fractional part.  To avoid running out of integers, we\n      // recycle the integer part but tack on a new random part\n      // each time.\n\n      m_handle_map.erase (p);\n\n      if (h.value () < 0)\n        m_handle_free_list.insert\n        (std::ceil (h.value ()) - make_handle_fraction ());\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/url-handle-manager.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Extracted from urlwrite.cc.\n\n#if ! defined (octave_url_handle_manager)\n#define octave_url_handle_manager 1\n\n#include \"octave-config.h\"\n\n#include <cmath>\n\n#include <map>\n#include <set>\n\n#include \"mappers.h\"\n\n#include \"oct-handle.h\"\n#include \"url-transfer.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntypedef octave_handle url_handle;\n\nclass OCTINTERP_API url_handle_manager\n{\npublic:\n\n  url_handle_manager ()\n    : m_handle_map (), m_handle_free_list (),\n      m_next_handle (-1.0 - (rand () + 1.0) / (RAND_MAX + 2.0)) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (url_handle_manager)\n\n  ~url_handle_manager () = default;\n\n  url_handle get_handle ();\n\n  void free (const url_handle& h);\n\n  url_handle lookup (double val)\n  {\n    iterator p = (math::isnan (val) ? m_handle_map.end ()\n                  : m_handle_map.find (val));\n\n    return (p != m_handle_map.end ()) ? p->first : url_handle ();\n  }\n\n  url_handle lookup (const octave_value& val)\n  {\n    return val.is_real_scalar () ? lookup (val.double_value ())\n           : url_handle ();\n  }\n\n  url_transfer get_object (double val)\n  {\n    return get_object (lookup (val));\n  }\n\n  url_transfer get_object (const octave_value& val)\n  {\n    return get_object (lookup (val));\n  }\n\n  url_transfer get_object (const url_handle& h)\n  {\n    iterator p = (h.ok () ? m_handle_map.find (h) : m_handle_map.end ());\n\n    return (p != m_handle_map.end ()) ? p->second : url_transfer ();\n  }\n\n  url_handle make_url_handle (const std::string& host,\n                              const std::string& user,\n                              const std::string& passwd,\n                              std::ostream& os)\n  {\n    url_handle h = get_handle ();\n\n    url_transfer obj (host, user, passwd, os);\n\n    if (! obj.is_valid ())\n      error (\"support for URL transfers was disabled when Octave was built\");\n\n    m_handle_map[h] = obj;\n\n    return h;\n  }\n\n  Matrix handle_list ()\n  {\n    Matrix retval (1, m_handle_map.size ());\n\n    octave_idx_type i = 0;\n    for (const auto& h_obj : m_handle_map)\n      {\n        url_handle h = h_obj.first;\n\n        retval(i++) = h.value ();\n      }\n\n    return retval;\n  }\n\n\nprivate:\n\n  typedef std::map<url_handle, url_transfer>::iterator iterator;\n  typedef std::map<url_handle, url_transfer>::const_iterator const_iterator;\n\n  typedef std::set<url_handle>::iterator free_list_iterator;\n  typedef std::set<url_handle>::const_iterator const_free_list_iterator;\n\n  // A map of handles to curl objects.\n  std::map<url_handle, url_transfer> m_handle_map;\n\n  // The available curl handles.\n  std::set<url_handle> m_handle_free_list;\n\n  // The next handle available if handle_free_list is empty.\n  double m_next_handle;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/util/bsxfun.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"mappers.h\"\n\n#include \"defun.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"ov-colon.h\"\n#include \"ov-fcn-handle.h\"\n#include \"unwind-prot.h\"\n#include \"variables.h\"\n\n// Optimized bsxfun operations\nenum bsxfun_builtin_op\n{\n  bsxfun_builtin_plus = 0,\n  bsxfun_builtin_minus,\n  bsxfun_builtin_times,\n  bsxfun_builtin_divide,\n  bsxfun_builtin_max,\n  bsxfun_builtin_min,\n  bsxfun_builtin_eq,\n  bsxfun_builtin_ne,\n  bsxfun_builtin_lt,\n  bsxfun_builtin_le,\n  bsxfun_builtin_gt,\n  bsxfun_builtin_ge,\n  bsxfun_builtin_and,\n  bsxfun_builtin_or,\n  bsxfun_builtin_power,\n  bsxfun_builtin_unknown,\n  bsxfun_num_builtin_ops = bsxfun_builtin_unknown\n};\n\nconst char *bsxfun_builtin_names[] =\n{\n  \"plus\",\n  \"minus\",\n  \"times\",\n  \"rdivide\",\n  \"max\",\n  \"min\",\n  \"eq\",\n  \"ne\",\n  \"lt\",\n  \"le\",\n  \"gt\",\n  \"ge\",\n  \"and\",\n  \"or\",\n  \"power\"\n};\n\nstatic bsxfun_builtin_op\nbsxfun_builtin_lookup (const std::string& name)\n{\n  for (int i = 0; i < bsxfun_num_builtin_ops; i++)\n    if (name == bsxfun_builtin_names[i])\n      return static_cast<bsxfun_builtin_op> (i);\n\n  return bsxfun_builtin_unknown;\n}\n\ntypedef octave_value (*bsxfun_handler) (const octave_value&,\n                                        const octave_value&);\n\n// Static table of handlers.\nbsxfun_handler bsxfun_handler_table[bsxfun_num_builtin_ops][btyp_num_types];\n\ntemplate <typename NDA, NDA (bsxfun_op) (const NDA&, const NDA&)>\nstatic octave_value\nbsxfun_forward_op (const octave_value& x, const octave_value& y)\n{\n  NDA xa = octave_value_extract<NDA> (x);\n  NDA ya = octave_value_extract<NDA> (y);\n  return octave_value (bsxfun_op (xa, ya));\n}\n\ntemplate <typename NDA, boolNDArray (bsxfun_rel) (const NDA&, const NDA&)>\nstatic octave_value\nbsxfun_forward_rel (const octave_value& x, const octave_value& y)\n{\n  NDA xa = octave_value_extract<NDA> (x);\n  NDA ya = octave_value_extract<NDA> (y);\n  return octave_value (bsxfun_rel (xa, ya));\n}\n\n// pow() needs a special handler for reals\n// because of the potentially complex result.\ntemplate <typename NDA, typename CNDA>\nstatic octave_value\ndo_bsxfun_real_pow (const octave_value& x, const octave_value& y)\n{\n  NDA xa = octave_value_extract<NDA> (x);\n  NDA ya = octave_value_extract<NDA> (y);\n  if (! ya.all_integers () && xa.any_element_is_negative ())\n    return octave_value (bsxfun_pow (CNDA (xa), ya));\n  else\n    return octave_value (bsxfun_pow (xa, ya));\n}\n\nstatic void\nmaybe_fill_table ()\n{\n  static bool filled = false;\n  if (filled)\n    return;\n\n#define REGISTER_OP_HANDLER(OP, BTYP, NDA, FUNOP)                       \\\n  bsxfun_handler_table[OP][BTYP] = bsxfun_forward_op<NDA, FUNOP>\n\n#define REGISTER_REL_HANDLER(REL, BTYP, NDA, FUNREL)                    \\\n  bsxfun_handler_table[REL][BTYP] = bsxfun_forward_rel<NDA, FUNREL>\n\n#define REGISTER_STD_HANDLERS(BTYP, NDA)                                \\\n  REGISTER_OP_HANDLER (bsxfun_builtin_plus, BTYP, NDA, bsxfun_add);     \\\n  REGISTER_OP_HANDLER (bsxfun_builtin_minus, BTYP, NDA, bsxfun_sub);    \\\n  REGISTER_OP_HANDLER (bsxfun_builtin_times, BTYP, NDA, bsxfun_mul);    \\\n  REGISTER_OP_HANDLER (bsxfun_builtin_divide, BTYP, NDA, bsxfun_div);   \\\n  REGISTER_OP_HANDLER (bsxfun_builtin_max, BTYP, NDA, bsxfun_max);      \\\n  REGISTER_OP_HANDLER (bsxfun_builtin_min, BTYP, NDA, bsxfun_min);      \\\n  REGISTER_REL_HANDLER (bsxfun_builtin_eq, BTYP, NDA, bsxfun_eq);       \\\n  REGISTER_REL_HANDLER (bsxfun_builtin_ne, BTYP, NDA, bsxfun_ne);       \\\n  REGISTER_REL_HANDLER (bsxfun_builtin_lt, BTYP, NDA, bsxfun_lt);       \\\n  REGISTER_REL_HANDLER (bsxfun_builtin_le, BTYP, NDA, bsxfun_le);       \\\n  REGISTER_REL_HANDLER (bsxfun_builtin_gt, BTYP, NDA, bsxfun_gt);       \\\n  REGISTER_REL_HANDLER (bsxfun_builtin_ge, BTYP, NDA, bsxfun_ge)\n\n  REGISTER_STD_HANDLERS (btyp_double, NDArray);\n  REGISTER_STD_HANDLERS (btyp_float, FloatNDArray);\n  REGISTER_STD_HANDLERS (btyp_complex, ComplexNDArray);\n  REGISTER_STD_HANDLERS (btyp_float_complex, FloatComplexNDArray);\n  REGISTER_STD_HANDLERS (btyp_int8,  int8NDArray);\n  REGISTER_STD_HANDLERS (btyp_int16, int16NDArray);\n  REGISTER_STD_HANDLERS (btyp_int32, int32NDArray);\n  REGISTER_STD_HANDLERS (btyp_int64, int64NDArray);\n  REGISTER_STD_HANDLERS (btyp_uint8,  uint8NDArray);\n  REGISTER_STD_HANDLERS (btyp_uint16, uint16NDArray);\n  REGISTER_STD_HANDLERS (btyp_uint32, uint32NDArray);\n  REGISTER_STD_HANDLERS (btyp_uint64, uint64NDArray);\n\n  // For bools, we register and/or.\n  REGISTER_OP_HANDLER (bsxfun_builtin_and, btyp_bool, boolNDArray, bsxfun_and);\n  REGISTER_OP_HANDLER (bsxfun_builtin_or, btyp_bool, boolNDArray, bsxfun_or);\n\n  // Register power handlers.\n  bsxfun_handler_table[bsxfun_builtin_power][btyp_double]\n    = do_bsxfun_real_pow<NDArray, ComplexNDArray>;\n  bsxfun_handler_table[bsxfun_builtin_power][btyp_float]\n    = do_bsxfun_real_pow<FloatNDArray, FloatComplexNDArray>;\n\n  REGISTER_OP_HANDLER (bsxfun_builtin_power, btyp_complex, ComplexNDArray,\n                       bsxfun_pow);\n  REGISTER_OP_HANDLER (bsxfun_builtin_power, btyp_float_complex,\n                       FloatComplexNDArray, bsxfun_pow);\n\n  // For chars, we want just relational handlers.\n  REGISTER_REL_HANDLER (bsxfun_builtin_eq, btyp_char, charNDArray, bsxfun_eq);\n  REGISTER_REL_HANDLER (bsxfun_builtin_ne, btyp_char, charNDArray, bsxfun_ne);\n  REGISTER_REL_HANDLER (bsxfun_builtin_lt, btyp_char, charNDArray, bsxfun_lt);\n  REGISTER_REL_HANDLER (bsxfun_builtin_le, btyp_char, charNDArray, bsxfun_le);\n  REGISTER_REL_HANDLER (bsxfun_builtin_gt, btyp_char, charNDArray, bsxfun_gt);\n  REGISTER_REL_HANDLER (bsxfun_builtin_ge, btyp_char, charNDArray, bsxfun_ge);\n\n  filled = true;\n}\n\nstatic octave_value\nmaybe_optimized_builtin (const std::string& name,\n                         const octave_value& a, const octave_value& b)\n{\n  octave_value retval;\n\n  maybe_fill_table ();\n\n  bsxfun_builtin_op op = bsxfun_builtin_lookup (name);\n  if (op != bsxfun_builtin_unknown)\n    {\n      builtin_type_t btyp_a = a.builtin_type ();\n      builtin_type_t btyp_b = b.builtin_type ();\n\n      // Simplify single/double combinations.\n      if (btyp_a == btyp_float && btyp_b == btyp_double)\n        btyp_b = btyp_float;\n      else if (btyp_a == btyp_double && btyp_b == btyp_float)\n        btyp_a = btyp_float;\n      else if (btyp_a == btyp_float_complex && btyp_b == btyp_complex)\n        btyp_b = btyp_float_complex;\n      else if (btyp_a == btyp_complex && btyp_b == btyp_float_complex)\n        btyp_a = btyp_float_complex;\n\n      if (btyp_a == btyp_b && btyp_a != btyp_unknown)\n        {\n          bsxfun_handler handler = bsxfun_handler_table[op][btyp_a];\n          if (handler)\n            retval = handler (a, b);\n        }\n    }\n\n  return retval;\n}\n\nstatic bool\nmaybe_update_column (octave_value& Ac, const octave_value& A,\n                     const dim_vector& dva, const dim_vector& dvc,\n                     octave_idx_type i, octave_value_list& idx)\n{\n  octave_idx_type nd = dva.ndims ();\n\n  if (i == 0)\n    {\n      idx(0) = octave_value (':');\n      for (octave_idx_type j = 1; j < nd; j++)\n        {\n          if (dva(j) == 1)\n            idx(j) = octave_value (1);\n          else\n            idx(j) = octave_value ((i % dvc(j)) + 1);\n\n          i /= dvc(j);\n        }\n\n      Ac = A;\n      Ac = Ac.single_subsref (\"(\", idx);\n      return true;\n    }\n  else\n    {\n      bool is_changed = false;\n      octave_idx_type k = i;\n      octave_idx_type k1 = i - 1;\n      for (octave_idx_type j = 1; j < nd; j++)\n        {\n          if (dva(j) != 1 && k % dvc(j) != k1 % dvc(j))\n            {\n              idx (j) = octave_value ((k % dvc(j)) + 1);\n              is_changed = true;\n            }\n\n          k /= dvc(j);\n          k1 /= dvc(j);\n        }\n\n      if (is_changed)\n        {\n          Ac = A;\n          Ac = Ac.single_subsref (\"(\", idx);\n          return true;\n        }\n      else\n        return false;\n    }\n}\n\nstatic void\nupdate_index (Array<int>& idx, const dim_vector& dv, octave_idx_type i)\n{\n  octave_idx_type nd = dv.ndims ();\n\n  idx(0) = 0;\n  for (octave_idx_type j = 1; j < nd; j++)\n    {\n      idx(j) = i % dv(j);\n      i /= dv(j);\n    }\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFMETHOD (bsxfun, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{C} =} bsxfun (@var{f}, @var{A}, @var{B})\nApply a binary function @var{f} element-by-element to two array arguments\n@var{A} and @var{B}, expanding singleton dimensions in either input argument as\nnecessary.\n\n@var{f} is a function handle, inline function, or string containing the name\nof the function to evaluate.  The function @var{f} must be capable of accepting\ntwo column-vector arguments of equal length, or one column vector argument and\na scalar.\n\nThe dimensions of @var{A} and @var{B} must be equal or singleton.  The\nsingleton dimensions of the arrays will be expanded to the same dimensionality\nas the other array.\n@seealso{arrayfun, cellfun}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  octave_value fcn = args(0);\n  if (fcn.is_string ())\n    {\n      std::string name = fcn.string_value ();\n\n      symbol_table& symtab = interp.get_symbol_table ();\n\n      fcn = symtab.find_function (name);\n\n      if (fcn.is_undefined ())\n        error (\"bsxfun: invalid function name: %s\", name.c_str ());\n    }\n  else if (! (args(0).is_function_handle () || args(0).is_inline_function ()))\n    error (\"bsxfun: F must be a string or function handle\");\n\n  octave_value_list retval;\n\n  const octave_value A = args(1);\n  const octave_value B = args(2);\n\n  if (fcn.is_builtin_function ()\n      || (fcn.is_function_handle () && ! A.isobject () && ! B.isobject ()))\n    {\n      // This may break if the default behavior is overridden.  But if you\n      // override arithmetic operators for builtin classes, you should expect\n      // mayhem anyway (constant folding etc).  Querying is_overloaded() may\n      // not be exactly what we need here.\n      octave_function *fcn_val = fcn.function_value ();\n      if (fcn_val)\n        {\n          octave_value tmp = maybe_optimized_builtin (fcn_val->name (), A, B);\n          if (tmp.is_defined ())\n            retval(0) = tmp;\n        }\n    }\n\n  if (retval.empty ())\n    {\n      dim_vector dva = A.dims ();\n      octave_idx_type nda = dva.ndims ();\n      dim_vector dvb = B.dims ();\n      octave_idx_type ndb = dvb.ndims ();\n      octave_idx_type nd = nda;\n\n      if (nda > ndb)\n        dvb.resize (nda, 1);\n      else if (nda < ndb)\n        {\n          dva.resize (ndb, 1);\n          nd = ndb;\n        }\n\n      for (octave_idx_type i = 0; i < nd; i++)\n        if (dva(i) != dvb(i) && dva(i) != 1 && dvb(i) != 1)\n          error (\"bsxfun: dimensions of A and B must match\");\n\n      // Find the size of the output\n      dim_vector dvc;\n      dvc.resize (nd);\n\n      for (octave_idx_type i = 0; i < nd; i++)\n        dvc(i) = (dva(i) < 1 ? dva(i)\n                  : (dvb(i) < 1 ? dvb(i)\n                     : (dva(i) > dvb(i) ? dva(i)\n                        : dvb(i))));\n\n      if (dva == dvb || dva.numel () == 1 || dvb.numel () == 1)\n        {\n          octave_value_list inputs (2);\n          inputs(0) = A;\n          inputs(1) = B;\n          retval = interp.feval (fcn, inputs, 1);\n        }\n      else if (dvc.numel () < 1)\n        {\n          octave_value_list inputs (2);\n          inputs(0) = A.resize (dvc);\n          inputs(1) = B.resize (dvc);\n          retval = interp.feval (fcn, inputs, 1);\n        }\n      else\n        {\n          octave_idx_type ncount = 1;\n          for (octave_idx_type i = 1; i < nd; i++)\n            ncount *= dvc(i);\n\n#define BSXDEF(T)                               \\\n          T result_ ## T;                       \\\n          bool have_ ## T = false;\n\n          BSXDEF(NDArray);\n          BSXDEF(ComplexNDArray);\n          BSXDEF(FloatNDArray);\n          BSXDEF(FloatComplexNDArray);\n          BSXDEF(boolNDArray);\n          BSXDEF(int8NDArray);\n          BSXDEF(int16NDArray);\n          BSXDEF(int32NDArray);\n          BSXDEF(int64NDArray);\n          BSXDEF(uint8NDArray);\n          BSXDEF(uint16NDArray);\n          BSXDEF(uint32NDArray);\n          BSXDEF(uint64NDArray);\n\n          octave_value Ac;\n          octave_value_list idxA;\n          octave_value Bc;\n          octave_value_list idxB;\n          octave_value C;\n          octave_value_list inputs (2);\n          Array<int> ra_idx (dim_vector (dvc.ndims (), 1), 0);\n\n          for (octave_idx_type i = 0; i < ncount; i++)\n            {\n              if (maybe_update_column (Ac, A, dva, dvc, i, idxA))\n                inputs(0) = Ac;\n\n              if (maybe_update_column (Bc, B, dvb, dvc, i, idxB))\n                inputs(1) = Bc;\n\n              octave_value_list tmp = interp.feval (fcn, inputs, 1);\n\n#define BSXINIT(T, CLS, EXTRACTOR)                                      \\\n              (result_type == CLS)                                      \\\n                {                                                       \\\n                  have_ ## T = true;                                    \\\n                  result_ ## T = tmp(0). EXTRACTOR ## _array_value ();  \\\n                  result_ ## T .resize (dvc);                           \\\n                }\n\n              if (i == 0)\n                {\n                  if (! tmp(0).issparse ())\n                    {\n                      std::string result_type = tmp(0).class_name ();\n                      if (result_type == \"double\")\n                        {\n                          if (tmp(0).isreal ())\n                            {\n                              have_NDArray = true;\n                              result_NDArray = tmp(0).array_value ();\n                              result_NDArray.resize (dvc);\n                            }\n                          else\n                            {\n                              have_ComplexNDArray = true;\n                              result_ComplexNDArray\n                                = tmp(0).complex_array_value ();\n                              result_ComplexNDArray.resize (dvc);\n                            }\n                        }\n                      else if (result_type == \"single\")\n                        {\n                          if (tmp(0).isreal ())\n                            {\n                              have_FloatNDArray = true;\n                              result_FloatNDArray\n                                = tmp(0).float_array_value ();\n                              result_FloatNDArray.resize (dvc);\n                            }\n                          else\n                            {\n                              have_FloatComplexNDArray = true;\n                              result_FloatComplexNDArray\n                                = tmp(0).float_complex_array_value ();\n                              result_FloatComplexNDArray.resize (dvc);\n                            }\n                        }\n                      else if BSXINIT(boolNDArray, \"logical\", bool)\n                        else if BSXINIT(int8NDArray, \"int8\", int8)\n                          else if BSXINIT(int16NDArray, \"int16\", int16)\n                            else if BSXINIT(int32NDArray, \"int32\", int32)\n                              else if BSXINIT(int64NDArray, \"int64\", int64)\n                                else if BSXINIT(uint8NDArray, \"uint8\", uint8)\n                                  else if BSXINIT(uint16NDArray, \"uint16\", uint16)\n                                    else if BSXINIT(uint32NDArray, \"uint32\", uint32)\n                                      else if BSXINIT(uint64NDArray, \"uint64\", uint64)\n                                        else\n                                          {\n                                            C = tmp(0);\n                                            C = C.resize (dvc);\n                                          }\n                    }\n                  else  // Skip semi-fast path for sparse matrices\n                    {\n                      C = tmp (0);\n                      C = C.resize (dvc);\n                    }\n                }\n              else\n                {\n                  update_index (ra_idx, dvc, i);\n\n                  if (have_NDArray)\n                    {\n                      if (! tmp(0).isfloat ())\n                        {\n                          have_NDArray = false;\n                          C = result_NDArray;\n                          C = cat_op (C, tmp(0), ra_idx);\n                        }\n                      else if (tmp(0).isreal ())\n                        result_NDArray.insert (tmp(0).array_value (), ra_idx);\n                      else\n                        {\n                          result_ComplexNDArray\n                            = ComplexNDArray (result_NDArray);\n                          result_ComplexNDArray.insert\n                          (tmp(0).complex_array_value (), ra_idx);\n                          have_NDArray = false;\n                          have_ComplexNDArray = true;\n                        }\n                    }\n                  else if (have_FloatNDArray)\n                    {\n                      if (! tmp(0).isfloat ())\n                        {\n                          have_FloatNDArray = false;\n                          C = result_FloatNDArray;\n                          C = cat_op (C, tmp(0), ra_idx);\n                        }\n                      else if (tmp(0).isreal ())\n                        result_FloatNDArray.insert\n                        (tmp(0).float_array_value (), ra_idx);\n                      else\n                        {\n                          result_FloatComplexNDArray\n                            = FloatComplexNDArray (result_FloatNDArray);\n                          result_FloatComplexNDArray.insert\n                          (tmp(0).float_complex_array_value (), ra_idx);\n                          have_FloatNDArray = false;\n                          have_FloatComplexNDArray = true;\n                        }\n                    }\n\n#define BSXLOOP(T, CLS, EXTRACTOR)                                      \\\n                  (have_ ## T)                                          \\\n                    {                                                   \\\n                      if (tmp(0).class_name () != CLS)                  \\\n                        {                                               \\\n                          have_ ## T = false;                           \\\n                          C = result_ ## T;                             \\\n                          C = cat_op (C, tmp(0), ra_idx);       \\\n                        }                                               \\\n                      else                                              \\\n                        result_ ## T .insert (tmp(0). EXTRACTOR ## _array_value (), ra_idx); \\\n                    }\n\n                  else if BSXLOOP(ComplexNDArray, \"double\", complex)\n                    else if BSXLOOP(FloatComplexNDArray, \"single\", float_complex)\n                      else if BSXLOOP(boolNDArray, \"logical\", bool)\n                        else if BSXLOOP(int8NDArray, \"int8\", int8)\n                          else if BSXLOOP(int16NDArray, \"int16\", int16)\n                            else if BSXLOOP(int32NDArray, \"int32\", int32)\n                              else if BSXLOOP(int64NDArray, \"int64\", int64)\n                                else if BSXLOOP(uint8NDArray, \"uint8\", uint8)\n                                  else if BSXLOOP(uint16NDArray, \"uint16\", uint16)\n                                    else if BSXLOOP(uint32NDArray, \"uint32\", uint32)\n                                      else if BSXLOOP(uint64NDArray, \"uint64\", uint64)\n                                        else\n                                          C = cat_op (C, tmp(0), ra_idx);\n                }\n            }\n\n#define BSXEND(T)                               \\\n          (have_ ## T)                          \\\n            retval(0) = result_ ## T;\n\n          if BSXEND(NDArray)\n            else if BSXEND(ComplexNDArray)\n              else if BSXEND(FloatNDArray)\n                else if BSXEND(FloatComplexNDArray)\n                  else if BSXEND(boolNDArray)\n                    else if BSXEND(int8NDArray)\n                      else if BSXEND(int16NDArray)\n                        else if BSXEND(int32NDArray)\n                          else if BSXEND(int64NDArray)\n                            else if BSXEND(uint8NDArray)\n                              else if BSXEND(uint16NDArray)\n                                else if BSXEND(uint32NDArray)\n                                  else if BSXEND(uint64NDArray)\n                                    else\n                                      retval(0) = C;\n        }\n    }\n\n  return retval;\n}\n\n/*\n\n%!shared a, b, c, f\n%! a = randn (4, 4);\n%! b = mean (a, 1);\n%! c = mean (a, 2);\n%! f = @minus;\n%!error bsxfun (f)\n%!error bsxfun (f, a)\n%!error bsxfun (a, b)\n%!error bsxfun (a, b, c)\n%!error bsxfun (f, a, b, c)\n%!error bsxfun (f, ones (4, 0), ones (4, 4))\n%!assert (bsxfun (f, ones (4, 0), ones (4, 1)), zeros (4, 0))\n%!assert (bsxfun (f, ones (1, 4), ones (4, 1)), zeros (4, 4))\n%!assert (bsxfun (f, a, b), a - repmat (b, 4, 1))\n%!assert (bsxfun (f, a, c), a - repmat (c, 1, 4))\n%!assert (bsxfun (\"minus\", ones (1, 4), ones (4, 1)), zeros (4, 4))\n\n%!shared a, b, c, f\n%! a = randn (4, 4);\n%! a(1) *= 1i;\n%! b = mean (a, 1);\n%! c = mean (a, 2);\n%! f = @minus;\n%!error bsxfun (f)\n%!error bsxfun (f, a)\n%!error bsxfun (a, b)\n%!error bsxfun (a, b, c)\n%!error bsxfun (f, a, b, c)\n%!error bsxfun (f, ones (4, 0), ones (4, 4))\n%!assert (bsxfun (f, ones (4, 0), ones (4, 1)), zeros (4, 0))\n%!assert (bsxfun (f, ones (1, 4), ones (4, 1)), zeros (4, 4))\n%!assert (bsxfun (f, a, b), a - repmat (b, 4, 1))\n%!assert (bsxfun (f, a, c), a - repmat (c, 1, 4))\n%!assert (bsxfun (\"minus\", ones (1, 4), ones (4, 1)), zeros (4, 4))\n\n%!shared a, b, c, f\n%! a = randn (4, 4);\n%! a(end) *= 1i;\n%! b = mean (a, 1);\n%! c = mean (a, 2);\n%! f = @minus;\n%!error bsxfun (f)\n%!error bsxfun (f, a)\n%!error bsxfun (a, b)\n%!error bsxfun (a, b, c)\n%!error bsxfun (f, a, b, c)\n%!error bsxfun (f, ones (4, 0), ones (4, 4))\n%!assert (bsxfun (f, ones (4, 0), ones (4, 1)), zeros (4, 0))\n%!assert (bsxfun (f, ones (1, 4), ones (4, 1)), zeros (4, 4))\n%!assert (bsxfun (f, a, b), a - repmat (b, 4, 1))\n%!assert (bsxfun (f, a, c), a - repmat (c, 1, 4))\n%!assert (bsxfun (\"minus\", ones (1, 4), ones (4, 1)), zeros (4, 4))\n\n%!shared a, b, c, f\n%! a = randn (4, 4);\n%! b = a (1, :);\n%! c = a (:, 1);\n%! f = @(x, y) x == y;\n%!error bsxfun (f)\n%!error bsxfun (f, a)\n%!error bsxfun (a, b)\n%!error bsxfun (a, b, c)\n%!error bsxfun (f, a, b, c)\n%!error bsxfun (f, ones (4, 0), ones (4, 4))\n%!assert (bsxfun (f, ones (4, 0), ones (4, 1)), zeros (4, 0, \"logical\"))\n%!assert (bsxfun (f, ones (1, 4), ones (4, 1)), ones (4, 4, \"logical\"))\n%!assert (bsxfun (f, a, b), a == repmat (b, 4, 1))\n%!assert (bsxfun (f, a, c), a == repmat (c, 1, 4))\n\n%!shared a, b, c, d, f\n%! a = randn (4, 4, 4);\n%! b = mean (a, 1);\n%! c = mean (a, 2);\n%! d = mean (a, 3);\n%! f = @minus;\n%!error bsxfun (f, ones ([4, 0, 4]), ones ([4, 4, 4]))\n%!assert (bsxfun (f, ones ([4, 0, 4]), ones ([4, 1, 4])), zeros ([4, 0, 4]))\n%!assert (bsxfun (f, ones ([4, 4, 0]), ones ([4, 1, 1])), zeros ([4, 4, 0]))\n%!assert (bsxfun (f, ones ([1, 4, 4]), ones ([4, 1, 4])), zeros ([4, 4, 4]))\n%!assert (bsxfun (f, ones ([4, 4, 1]), ones ([4, 1, 4])), zeros ([4, 4, 4]))\n%!assert (bsxfun (f, ones ([4, 1, 4]), ones ([1, 4, 4])), zeros ([4, 4, 4]))\n%!assert (bsxfun (f, ones ([4, 1, 4]), ones ([1, 4, 1])), zeros ([4, 4, 4]))\n%!assert (bsxfun (f, a, b), a - repmat (b, [4, 1, 1]))\n%!assert (bsxfun (f, a, c), a - repmat (c, [1, 4, 1]))\n%!assert (bsxfun (f, a, d), a - repmat (d, [1, 1, 4]))\n%!assert (bsxfun (\"minus\", ones ([4, 0, 4]), ones ([4, 1, 4])),\n%!        zeros ([4, 0, 4]))\n\n## The test below is a very hard case to treat\n%!assert (bsxfun (f, ones ([4, 1, 4, 1]), ones ([1, 4, 1, 4])),\n%!        zeros ([4, 4, 4, 4]))\n\n%!shared a, b, aa, bb\n%! ## FIXME: Set a known \"good\" random seed.  See bug #51779.\n%! old_nstate = randn (\"state\");\n%! restore_nstate = onCleanup (@() randn (\"state\", old_nstate));\n%! randn (\"state\", 42); # initialize generator to make behavior reproducible\n%! a = randn (3, 1, 3);\n%! aa = a(:, ones (1, 3), :, ones (1, 3));\n%! b = randn (1, 3, 3, 3);\n%! bb = b(ones (1, 3), :, :, :);\n%!assert (bsxfun (@plus, a, b), aa + bb)\n%!assert (bsxfun (@minus, a, b), aa - bb)\n%!assert (bsxfun (@times, a, b), aa .* bb)\n%!assert (bsxfun (@rdivide, a, b), aa ./ bb)\n%!assert (bsxfun (@ldivide, a, b), aa .\\ bb)\n%!assert (bsxfun (@power, a, b), aa .^ bb)\n%!assert (bsxfun (@power, abs (a), b), abs (aa) .^ bb)\n%!assert (bsxfun (@eq, round (a), round (b)), round (aa) == round (bb))\n%!assert (bsxfun (@ne, round (a), round (b)), round (aa) != round (bb))\n%!assert (bsxfun (@lt, a, b), aa < bb)\n%!assert (bsxfun (@le, a, b), aa <= bb)\n%!assert (bsxfun (@gt, a, b), aa > bb)\n%!assert (bsxfun (@ge, a, b), aa >= bb)\n%!assert (bsxfun (@min, a, b), min (aa, bb))\n%!assert (bsxfun (@max, a, b), max (aa, bb))\n%!assert (bsxfun (@and, a > 0, b > 0), (aa > 0) & (bb > 0))\n%!assert (bsxfun (@or, a > 0, b > 0), (aa > 0) | (bb > 0))\n\n## Test automatic bsxfun\n%\n%!test\n%! fcns = {@plus, @minus, @times, @rdivide, @ldivide, @power, @max, @min, ...\n%!         @rem, @mod, @atan2, @hypot, @eq, @ne, @lt, @le, @gt, @ge, ...\n%!         @and, @or, @xor };\n%!\n%! float_types = {@single, @double};\n%! int_types = {@int8, @int16, @int32, @int64, ...\n%!              @uint8, @uint16, @uint32, @uint64};\n%!\n%! ## FIXME: Set a known \"good\" random seed.  See bug #51779.\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 42);  # initialize generator to make behavior reproducible\n%!\n%! x = rand (3) * 10-5;\n%! y = rand (3,1) * 10-5;\n%!\n%! for i=1:length (fcns)\n%!   for j = 1:length (float_types)\n%!     for k = 1:length (int_types)\n%!\n%!       fcn = fcns{i};\n%!       f_type = float_types{j};\n%!       i_type = int_types{k};\n%!\n%!         assert (bsxfun (fcn, f_type (x), i_type (y)), ...\n%!                 fcn (f_type(x), i_type (y)));\n%!         assert (bsxfun (fcn, f_type (y), i_type (x)), ...\n%!                 fcn (f_type(y), i_type (x)));\n%!\n%!         assert (bsxfun (fcn, i_type (x), i_type (y)), ...\n%!                 fcn (i_type (x), i_type (y)));\n%!         assert (bsxfun (fcn, i_type (y), i_type (x)), ...\n%!                 fcn (i_type (y), i_type (x)));\n%!\n%!         assert (bsxfun (fcn, f_type (x), f_type (y)), ...\n%!                 fcn (f_type (x), f_type (y)));\n%!         assert (bsxfun (fcn, f_type(y), f_type(x)), ...\n%!                 fcn (f_type (y), f_type (x)));\n%!     endfor\n%!   endfor\n%! endfor\n\n## Automatic broadcasting with zero length dimensions\n%!assert <*47085> ([1 2 3] + zeros (0, 3), zeros (0, 3))\n%!assert <*47085> (rand (3, 3, 1) + rand (3, 3, 0), zeros (3, 3, 0))\n\n## In-place broadcasting with zero length dimensions\n%!test <*47085>\n%! a = zeros (0, 3);\n%! a += [1 2 3];\n%! assert (a, zeros (0, 3));\n\n%!test <*53179>\n%! im = ones (4,4,2) + single (i);\n%! mask = true (4,4);\n%! mask(:,1:2) = false;\n%! r = bsxfun (@times, im, mask);\n%! assert (r(:,:,1), repmat (single ([0, 0, 1+i, 1+i]), [4, 1]));\n\n## automatic broadcasting with inplace times operator\n%!test <*38466>\n%! a = ones (2, 2, 2);\n%! b = 2 * ones (2, 1);\n%! a .*= b;\n%! assert (a, 2 * ones (2, 2, 2));\n\n%!test <*38466>\n%! a = ones (2, 2, 2);\n%! b = 2 * ones (1, 2);\n%! a .*= b;\n%! assert (a, 2 * ones (2, 2, 2));\n\n%!test <*38466>\n%! a = ones (2, 2, 2);\n%! b = 2 * ones (2, 2);\n%! a .*= b;\n%! assert (a, 2 * ones (2, 2, 2));\n\n%!test <*38466>\n%! a = ones (2, 2, 2);\n%! b = 2 * ones (1, 1, 2);\n%! a .*= b;\n%! assert (a, 2 * ones (2, 2, 2));\n\n%!assert (ones (2,2,2) .* ones (1,2), ones (2,2,2))\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/cellfun.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <list>\n#include <string>\n\n#include \"mappers.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-string.h\"\n\n#include \"Cell.h\"\n#include \"oct-map.h\"\n#include \"defun.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"variables.h\"\n#include \"unwind-prot.h\"\n#include \"errwarn.h\"\n#include \"utils.h\"\n\n#include \"ov-bool.h\"\n#include \"ov-class.h\"\n#include \"ov-colon.h\"\n#include \"ov-complex.h\"\n#include \"ov-float.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-scalar.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n\n#include \"ov-fcn-handle.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic octave_value_list\nfcn_eval (interpreter& interp, const octave_idx_type count,\n          octave_idx_type nargout, const octave_value_list& inputlist,\n          const octave_value& fcn, const octave_value& error_handler)\n{\n  octave_value_list retval;\n\n  bool execution_error = false;\n\n  try\n    {\n      retval = interp.feval (fcn, inputlist, nargout);\n    }\n  catch (const execution_exception& ee)\n    {\n      if (error_handler.is_defined ())\n        {\n          error_system& es = interp.get_error_system ();\n\n          es.save_exception (ee);\n          interp.recover_from_exception ();\n\n          execution_error = true;\n        }\n      else\n        throw;\n    }\n\n  if (execution_error)\n    {\n      // ErrorHandler exists or this code would not have been reached.\n      // Call ErrorHandler() to create substitute output.\n      error_system& es = interp.get_error_system ();\n\n      octave_scalar_map msg;\n      msg.assign (\"identifier\", es.last_error_id ());\n      msg.assign (\"message\", es.last_error_message ());\n      msg.assign (\"index\",\n                  static_cast<double> (count\n                                       + static_cast<octave_idx_type> (1)));\n\n      octave_value_list errlist = inputlist;\n      errlist.prepend (msg);\n\n      retval = interp.feval (error_handler, errlist, nargout);\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\ntry_cellfun_accelfcns (const octave_value_list& args, const int nargin)\n{\n  octave_value_list retval;\n\n  std::string fcn_name = args(0).string_value ();\n\n  const Cell f_arg = args(1).cell_value ();\n\n  octave_idx_type nel = f_arg.numel ();\n\n  if (fcn_name == \"isempty\")\n    {\n      if (nargin > 2)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: accelerated function must be called with only one argument\");\n      boolNDArray result (f_arg.dims ());\n      for (octave_idx_type count = 0; count < nel; count++)\n        result(count) = f_arg.xelem (count).isempty ();\n      retval(0) = result;\n    }\n  else if (fcn_name == \"islogical\")\n    {\n      if (nargin > 2)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: accelerated function must be called with only one argument\");\n      boolNDArray result (f_arg.dims ());\n      for (octave_idx_type count= 0; count < nel; count++)\n        result(count) = f_arg.xelem (count).islogical ();\n      retval(0) = result;\n    }\n  else if (fcn_name == \"isnumeric\")\n    {\n      if (nargin > 2)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: accelerated function must be called with only one argument\");\n      boolNDArray result (f_arg.dims ());\n      for (octave_idx_type count= 0; count < nel; count++)\n        result(count) = f_arg.xelem (count).isnumeric ();\n      retval(0) = result;\n    }\n  else if (fcn_name == \"isreal\")\n    {\n      if (nargin > 2)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: accelerated function must be called with only one argument\");\n      boolNDArray result (f_arg.dims ());\n      for (octave_idx_type count= 0; count < nel; count++)\n        result(count) = f_arg.xelem (count).isreal ();\n      retval(0) = result;\n    }\n  else if (fcn_name == \"length\")\n    {\n      if (nargin > 2)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: accelerated function must be called with only one argument\");\n      NDArray result (f_arg.dims ());\n      for (octave_idx_type count= 0; count < nel; count++)\n        result(count) = static_cast<double> (f_arg.xelem (count).length ());\n      retval(0) = result;\n    }\n  else if (fcn_name == \"ndims\")\n    {\n      if (nargin > 2)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: accelerated function must be called with only one argument\");\n      NDArray result (f_arg.dims ());\n      for (octave_idx_type count = 0; count < nel; count++)\n        result(count) = static_cast<double> (f_arg.xelem (count).ndims ());\n      retval(0) = result;\n    }\n  else if (fcn_name == \"numel\" || fcn_name == \"prodofsize\")\n    {\n      if (nargin > 2)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: accelerated function must be called with only one argument\");\n      NDArray result (f_arg.dims ());\n      for (octave_idx_type count = 0; count < nel; count++)\n        result(count) = static_cast<double> (f_arg.xelem (count).numel ());\n      retval(0) = result;\n    }\n  else if (fcn_name == \"size\")\n    {\n      if (nargin != 3)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: accelerated function 'size' must be called with exactly two arguments\");\n\n      int d = args(2).strict_int_value () - 1;\n\n      if (d < 0)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: K must be a positive integer\");\n\n      NDArray result (f_arg.dims ());\n\n      for (octave_idx_type count = 0; count < nel; count++)\n        {\n          const dim_vector& dv = f_arg.xelem (count).dims ();\n          if (d < dv.ndims ())\n            result(count) = static_cast<double> (dv(d));\n          else\n            result(count) = 1.0;\n        }\n\n      retval(0) = result;\n    }\n  else if (fcn_name == \"isclass\")\n    {\n      if (nargin != 3)\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: accelerated function 'isclass' must be called with exactly two arguments\");\n\n      std::string class_name = args(2).xstring_value (\"cellfun: CLASS argument to 'isclass' must be a string\");\n      boolNDArray result (f_arg.dims ());\n      for (octave_idx_type count = 0; count < nel; count++)\n        result(count) = (f_arg.xelem (count).class_name () == class_name);\n\n      retval(0) = result;\n    }\n\n  return retval;\n}\n\nstatic void\nparse_options (symbol_table& symtab, const octave_value_list& args,\n               int& nargin, bool& uniform_output, octave_value& error_handler)\n{\n  while (nargin > 3 && args(nargin-2).is_string ())\n    {\n      std::string arg = args(nargin-2).string_value ();\n\n      std::size_t compare_len = std::max (arg.length (),\n                                          static_cast<std::size_t> (2));\n\n      if (string::strncmpi (arg, \"uniformoutput\", compare_len))\n        uniform_output = args(nargin-1).xbool_value (\"cellfun: UniformOutput value must be boolean\");\n      else if (string::strncmpi (arg, \"errorhandler\", compare_len))\n        {\n          if (args(nargin-1).is_function_handle ()\n              || args(nargin-1).is_inline_function ())\n            {\n              error_handler = args(nargin-1);\n            }\n          else if (args(nargin-1).is_string ())\n            {\n              std::string err_name = args(nargin-1).string_value ();\n\n              error_handler = symtab.find_function (err_name);\n\n              if (error_handler.is_undefined ())\n                error_with_id (\"Octave:invalid-input-arg\",\n                               \"cellfun: invalid function NAME: %s\",\n                               err_name.c_str ());\n            }\n          else\n            error_with_id (\"Octave:invalid-input-arg\",\n                           \"cellfun: invalid value for 'ErrorHandler' function\");\n        }\n      else\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: unrecognized parameter %s\", arg.c_str ());\n\n      nargin -= 2;\n    }\n\n  nargin -= 1;\n}\n\nDEFMETHOD (cellfun, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{A} =} cellfun (@@@var{fcn}, @var{C})\n@deftypefnx {} {@var{A} =} cellfun (\"@var{fcn}\", @var{C})\n@deftypefnx {} {@var{A} =} cellfun (@var{fcn}, @var{C})\n@deftypefnx {} {@var{A} =} cellfun (@var{fcn}, @var{C1}, @var{C2}, @dots{})\n@deftypefnx {} {[@var{A1}, @var{A2}, @dots{}] =} cellfun (@dots{})\n@deftypefnx {} {@var{A} =} cellfun (@dots{}, \"UniformOutput\", @var{val})\n@deftypefnx {} {@var{A} =} cellfun (@dots{}, \"ErrorHandler\", @var{errfcn})\n@deftypefnx {} {@var{A} =} cellfun ('isempty', @var{C})\n@deftypefnx {} {@var{A} =} cellfun ('islogical', @var{C})\n@deftypefnx {} {@var{A} =} cellfun ('isnumeric', @var{C})\n@deftypefnx {} {@var{A} =} cellfun ('isreal', @var{C})\n@deftypefnx {} {@var{A} =} cellfun ('length', @var{C})\n@deftypefnx {} {@var{A} =} cellfun ('numel', @var{C})\n@deftypefnx {} {@var{A} =} cellfun ('prodofsize', @var{C})\n@deftypefnx {} {@var{A} =} cellfun ('size', @var{C}, @var{dim})\n@deftypefnx {} {@var{A} =} cellfun ('isclass', @var{C}, @var{class})\n\nEvaluate the function @var{fcn} on the elements of the cell array @var{C}.\n\n@code{cellfun} accepts an arbitrary function @var{fcn} given as a name in a\ncharacter string, as a function handle, or as an inline function.  Specifying\n@var{fcn} with a character string is preferred as the performance is ~3X better\nfor builtin functions and equivalent for m-files.\n\n@code{cellfun} has a limited number of functions which have been\nspecially-coded for high-performance (~8X faster than a function handle).\nThese functions are only used if the function is specified by name as a string,\nand only the simplest calling form---@w{@code{cellfun ('@var{fcn}'),\n@var{C})}}---without options is supported.  If you need access to an\noverloaded version of a function, such as @code{numel} for a particular\n@code{classdef} file, then you cannot use the accelerated function name and\nmust use a function handle instead, e.g., @code{@@numel}.\n\nThe high-performance functions are\n\n@table @asis\n@item @qcode{'isempty'}\nReturn true for empty elements.\n\n@item @qcode{'islogical'}\nReturn true for logical elements.\n\n@item @qcode{'isnumeric'}\nReturn true for numeric elements.\n\n@item @qcode{'isreal'}\nReturn true for real elements.\n\n@item @qcode{'length'}\nReturn a vector of the lengths of cell elements.\n\n@item @qcode{'ndims'}\nReturn the number of dimensions of each element.\n\n@item  @qcode{'numel'}\n@itemx @qcode{'prodofsize'}\nReturn the number of elements contained within each cell element.  The\nnumber is the product of the dimensions of the object of each cell element.\n\n@item @qcode{'size'}\nReturn the size along dimension @var{dim}.\n\n@item @qcode{'isclass'}\nReturn true for elements which are of type @var{class}.\n@end table\n\nElements in @var{C} are passed to the function individually and the result of\neach function invocation is collected in the output.  The function can take\nmore than one argument with the inputs arguments given by @var{C1}, @var{C2},\netc.  Input arguments that are singleton (1x1) cells will be automatically\nexpanded to the size of the other arguments.  For example:\n\n@example\n@group\ncellfun (\"atan2\", @{1, 0@}, @{0, 1@})\n     @xresult{} [ 1.57080   0.00000 ]\n@end group\n@end example\n\nThe number of output arguments of @code{cellfun} matches the number of output\narguments of the function and can be greater than one.  When there are multiple\noutputs of the function they will be collected into the output arguments of\n@code{cellfun} like this:\n\n@example\n@group\nfunction [a, b] = twoouts (x)\n  a = x;\n  b = x*x;\nendfunction\n[aa, bb] = cellfun (@@twoouts, @{1, 2, 3@})\n     @xresult{}\n        aa =\n           1 2 3\n        bb =\n           1 4 9\n@end group\n@end example\n\nNote that, by default, the output argument(s) are arrays of the same size as\nthe input arguments.\n\nIf the parameter @qcode{\"UniformOutput\"} is set to true (the default), then the\nfunction must return scalars which will be concatenated into the return\narray(s).  If @qcode{\"UniformOutput\"} is false, the outputs are concatenated\ninto a cell array (or cell arrays).  For example:\n\n@example\n@group\ncellfun (\"lower\", @{\"Foo\", \"Bar\", \"FooBar\"@},\n         \"UniformOutput\", false)\n@xresult{} @{\"foo\", \"bar\", \"foobar\"@}\n@end group\n@end example\n\nThe parameter @qcode{\"ErrorHandler\"} specifies a function @var{errfcn} to call\nif @var{fcn} generates an error.  The form of the function is\n\n@example\nfunction [@dots{}] = errfcn (@var{s}, @dots{})\n@end example\n\n@noindent\nwhere there is an additional input argument to @var{errfcn} relative to\n@var{fcn}, given by @var{s}.  This is a structure with the elements\n@qcode{\"identifier\"}, @qcode{\"message\"}, and @qcode{\"index\"} giving\nrespectively the error identifier, the error message, and the index into the\ninput arguments of the element that caused the error.  For example:\n\n@example\n@group\nfunction y = errfcn (s, x), y = NaN; endfunction\ncellfun (\"factorial\", @{-1, 2@}, \"ErrorHandler\", @@errfcn)\n@xresult{} [NaN 2]\n@end group\n@end example\n\nProgramming Note: Use @code{cellfun} intelligently.  The @code{cellfun}\nfunction is a useful tool for avoiding loops.  It is often used with anonymous\nfunction handles; however, calling an anonymous function involves an overhead\nquite comparable to the overhead of an m-file function.  Passing a handle to a\nbuilt-in function is faster, because the interpreter is not involved in the\ninternal loop.  For example:\n\n@example\n@group\nC = @{@dots{}@}\nv = cellfun (@@(x) det (x), C); # compute determinants\nv = cellfun (@@det, C);         # 40% faster\n@end group\n@end example\n\n@seealso{arrayfun, structfun, spfun}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  if (! args(1).iscell ())\n    error_with_id (\"Octave:invalid-input-arg\",\n                   \"cellfun: C must be a cell array\");\n\n  octave_value_list retval;\n\n  octave_value fcn = args(0);\n\n  // Possibly try accelerated functions, and return immediately\n  if (fcn.is_string ())\n    {\n      retval = try_cellfun_accelfcns (args, nargin);\n\n      if (! retval.empty ())\n        return retval;\n    }\n\n  // Function is not accelerated.  Have to execute the full function.\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  if (fcn.is_string ())\n    {\n      // See if we can convert the string into a function.\n      std::string name = args(0).string_value ();\n\n      if (! valid_identifier (name))\n        fcn = get_function_handle (interp, args(0), \"x\");\n      else\n        {\n          fcn = symtab.find_function (name);\n\n          if (fcn.is_undefined ())\n            error_with_id (\"Octave:invalid-input-arg\",\n                           \"cellfun: invalid function NAME: %s\",\n                           name.c_str ());\n        }\n    }\n\n  if (! fcn.is_function_handle () && ! fcn.is_function ()\n      && ! fcn.is_inline_function ())\n    error_with_id (\"Octave:invalid-input-arg\",\n                   \"cellfun: argument NAME must be a string or function handle\");\n\n  // Parse remaining inputs (\"UniformOutput\" or \"ErrorHandler\" options)\n  bool uniform_output = true;\n  octave_value error_handler;\n  int nargout1 = (nargout < 1 ? 1 : nargout);\n\n  parse_options (symtab, args, nargin, uniform_output, error_handler);\n\n  // Optimize which function will be called in loop\n  if (fcn.is_function ())\n    {\n      // The symbol table can give a more specific function class for a general\n      // function, and this will result in fewer polymorphic function calls.\n      std::string name = fcn.function_value () -> name ();\n      octave_value f = symtab.find_function (name);\n      if (f.is_defined ())\n        fcn = f;\n    }\n  else  // fcn is a function handle or inline function\n    {\n      // FIXME: Should check whether the types of all the cell array elements\n      // are all the same, then lookup the function for that type just once.\n    }\n\n  // Extract cell arguments.\n  octave_value_list inputovl (nargin);\n\n  OCTAVE_LOCAL_BUFFER (Cell, inputs, nargin);\n  OCTAVE_LOCAL_BUFFER (bool, isarray, nargin);\n\n  // This is to prevent copy-on-write.\n  const Cell *cinputs = inputs;\n\n  octave_idx_type nel = 1;\n  dim_vector inputdims (1, 1);\n\n  // Collect and validate arguments.\n  // Pre-fill scalar elements of inputovl array.\n  for (int j = 0; j < nargin; j++)\n    {\n      if (! args(j+1).iscell ())\n        error_with_id (\"Octave:invalid-input-arg\",\n                       \"cellfun: arguments must be cells\");\n\n      inputs[j] = args(j+1).cell_value ();\n      isarray[j] = (inputs[j].numel () != 1);\n      if (isarray[j])\n        {\n          nel = inputs[j].numel ();\n          if (inputdims.numel () == 1)    // first time an array encountered\n            inputdims = inputs[j].dims ();\n          else if (inputs[j].dims () != inputdims)\n            error (\"cellfun: input cell dimensions mismatch\");\n        }\n      else\n        inputovl(j) = cinputs[j](0);  // scalar, pre-fill inputovl\n    }\n\n  // Apply function\n  if (uniform_output)\n    {\n      OCTAVE_LOCAL_BUFFER (octave_value, results, nargout1);\n\n      int expected_nargout = 0;\n      for (octave_idx_type count = 0; count < nel; count++)\n        {\n          // Initialize inputovl with this loop count's input data\n          for (int j = 0; j < nargin; j++)\n            {\n              if (isarray[j])\n                inputovl.xelem (j) = cinputs[j](count);\n            }\n\n          // Evaluate function\n          const octave_value_list y\n            = fcn_eval (interp, count, nargout, inputovl, fcn, error_handler);\n\n          // Validate number of generated results is correct\n          int y_nel = y.length ();\n          if (count == 0)\n            {\n              // First time through loop.  Initialize expected number of\n              // outputs based on nargout and output from first function\n              // evaluation.\n              if (nargout == 0)\n                expected_nargout = (y_nel > 0 && y(0).is_defined ()) ? 1 : 0;\n              else\n                expected_nargout = nargout;\n            }\n          if (y_nel < expected_nargout)\n            error (\"cellfun: function returned fewer than nargout values\");\n          else if (expected_nargout == 0 && y_nel > 0 && y(0).is_defined ())\n            error (\"cellfun: function returned unexpected number of values\");\n\n          // Copy loop results to output if necessary\n          if (expected_nargout > 0)\n            {\n              if (count == 0)\n                {\n                  // First time through loop create output with class of\n                  // function output and size of input cell arrays.\n                  // Predeclaring output is more efficient than growing array.\n                  for (int j = 0; j < expected_nargout; j++)\n                    {\n                      if (y(j).is_undefined ())\n                        error (\"cellfun: function returned fewer than nargout values\");\n                      octave_value val = y(j);\n\n                      if (val.numel () != 1)\n                        error (\"cellfun: all values must be scalars when UniformOutput = true\");\n\n                      results[j] = val.resize (inputdims);\n                    }\n                }\n              else\n                {\n                  for (int j = 0; j < expected_nargout; j++)\n                    {\n                      if (y(j).is_undefined ())\n                        error (\"cellfun: function returned fewer than nargout values\");\n                      octave_value val = y(j);\n\n                      if (! results[j].fast_elem_insert (count, val))\n                        {\n                          if (val.numel () != 1)\n                            error (\"cellfun: all values must be scalars when UniformOutput = true\");\n\n                          error (\"cellfun: all values should be of the same type when UniformOutput = true\");\n                        }\n                    }\n                }\n            }\n        }\n\n      // Resize return array and fill with collected results\n      retval.resize (nargout1);\n      for (int j = 0; j < nargout1; j++)\n        {\n          if (nargout > 0 && results[j].is_undefined ())\n            retval(j) = NDArray (inputdims);\n          else\n            retval(j) = results[j];\n        }\n    }\n  else  // UniformOutput = false (return Cells)\n    {\n      OCTAVE_LOCAL_BUFFER (Cell, results, nargout1);\n\n      for (int j = 0; j < nargout1; j++)\n        results[j].resize (inputdims);\n\n      bool have_output = false;\n\n      for (octave_idx_type count = 0; count < nel; count++)\n        {\n          for (int j = 0; j < nargin; j++)\n            {\n              if (isarray[j])\n                inputovl.xelem (j) = cinputs[j](count);\n            }\n\n          const octave_value_list y\n            = fcn_eval (interp, count, nargout, inputovl, fcn, error_handler);\n\n          int y_nel = y.length ();\n\n          if (nargout > 0 && y_nel < nargout)\n            error (\"cellfun: function returned fewer than nargout values\");\n\n          if (nargout > 0\n              || (nargout == 0 && y_nel > 0 && y(0).is_defined ()))\n            {\n              have_output = true;\n\n              int num_to_copy = std::min (y_nel, nargout1);\n\n              for (int j = 0; j < num_to_copy; j++)\n                {\n                  if (y(j).is_undefined ())\n                    error (\"cellfun: function returned fewer than nargout values\");\n                  results[j](count) = y(j);\n                }\n            }\n        }\n\n      if (have_output || inputdims.any_zero ())\n        {\n          retval.resize (nargout1);\n          for (int j = 0; j < nargout1; j++)\n            retval(j) = results[j];\n        }\n    }\n\n  return retval;\n}\n\n/*\n\n%!function r = __f11 (x)\n%!  r = x;\n%!endfunction\n\n%!function __f01 (x)\n%!  ## Empty function\n%!endfunction\n\n%!function varargout = __f02 (out)\n%!  if (out)\n%!    varargout{1} = out;\n%!  endif\n%!endfunction\n\n%!test\n%! __cellfun_test_num_outputs__ = -1;\n%!\n%! function r = __subf11 (x)\n%!   __cellfun_test_num_outputs__ = nargout;\n%!   r = x;\n%! endfunction\n%!\n%! cellfun (\"__subf11\", {1});\n%! assert (__cellfun_test_num_outputs__, 0);\n%!\n%! __cellfun_test_num_outputs__ = -1;\n%! x = cellfun (\"__subf11\", {1});\n%! assert (__cellfun_test_num_outputs__, 1);\n\n%!test\n%! __cellfun_test_num_outputs__ = -1;\n%! function __subf01 (x)\n%!   __cellfun_test_num_outputs__ = nargout;\n%! endfunction\n%! cellfun (\"__subf01\", {1});\n%! assert (__cellfun_test_num_outputs__, 0);\n\n%!error x = cellfun (@__f01, {1, 2})\n%!error x = cellfun (@__f01, {1, 2})\n\n%!error x = cellfun (@__f02, {0, 2}, \"uniformoutput\", false)\n%!error x = cellfun (@__f02, {0, 2}, \"uniformoutput\", true)\n\n%!test\n%! assert (cellfun (@__f11, {1, 2}), [1, 2]);\n%! assert (cellfun (@__f11, {1, 2}, 'uniformoutput', false), {1, 2});\n\n%!test\n%! [a,b] = cellfun (@(x) x, cell (2, 0));\n%! assert (a, zeros (2, 0));\n%! assert (b, zeros (2, 0));\n\n%!test\n%! [a,b] = cellfun (@(x) x, cell (2, 0), \"uniformoutput\", false);\n%! assert (a, cell (2, 0));\n%! assert (b, cell (2, 0));\n\n## Test function to check the \"Errorhandler\" option\n%!function z = __cellfunerror (S, varargin)\n%!  z = S;\n%!endfunction\n\n## First input argument can be a string, an inline function,\n## a function_handle or an anonymous function\n%!test\n%! A = cellfun (\"islogical\", {true, 0.1, false, i*2});\n%! assert (A, [true, false, true, false]);\n%!test\n%! warning ('off', 'Octave:legacy-function', 'local');\n%! A = cellfun (inline (\"islogical (x)\", \"x\"), {true, 0.1, false, i*2});\n%! assert (A, [true, false, true, false]);\n%!test\n%! A = cellfun ('islogical', {true, 0.1, false, i*2});\n%! assert (A, [true, false, true, false]);\n%!test\n%! A = cellfun (@(x) islogical (x), {true, 0.1, false, i*2});\n%! assert (A, [true, false, true, false]);\n\n## First input argument can be the special string \"isreal\",\n## \"isempty\", \"islogical\", \"isnumeric\", \"length\", \"ndims\" or \"prodofsize\"\n%!test\n%! A = cellfun (\"isreal\", {true, 0.1, {}, i*2, [], \"abc\"});\n%! assert (A, [true, true, false, false, true, true]);\n%!test\n%! A = cellfun (\"isempty\", {true, 0.1, false, i*2, [], \"abc\"});\n%! assert (A, [false, false, false, false, true, false]);\n%!test\n%! A = cellfun (\"islogical\", {true, 0.1, false, i*2, [], \"abc\"});\n%! assert (A, [true, false, true, false, false, false]);\n%!test\n%! A = cellfun (\"isnumeric\", {true, 0.1, false, i*2, [], \"abc\"});\n%! assert (A, [false, true, false, true, true, false]);\n%!test\n%! A = cellfun (\"length\", {true, 0.1, false, i*2, [], \"abc\"});\n%! assert (A, [1, 1, 1, 1, 0, 3]);\n%!test\n%! A = cellfun (\"ndims\", {[1, 2; 3, 4]; (cell (1,2,3,4))});\n%! assert (A, [2; 4]);\n%!test\n%! A = cellfun (\"prodofsize\", {[1, 2; 3, 4], (cell (1,2,3,4))});\n%! assert (A, [4, 24]);\n\n## Number of input and output arguments may not be limited to one\n%!test\n%! A = cellfun (@(x,y,z) x + y + z, {1, 1, 1}, {2, 2, 2}, {3, 4, 5});\n%! assert (A, [6, 7, 8]);\n%!test\n%! A = cellfun (@(x,y,z) x + y + z, {1, 1, 1}, {2, 2, 2}, {3, 4, 5}, ...\n%!              \"UniformOutput\", false);\n%! assert (A, {6, 7, 8});\n%!test  # Two input arguments of different types\n%! A = cellfun (@(x,y) islogical (x) && ischar (y), {false, true}, {\"a\", 3});\n%! assert (A, [true, false]);\n%!test  # Pass another variable to the anonymous function\n%! y = true;\n%! A = cellfun (@(x) islogical (x) && y, {false, 0.3});\n%! assert (A, [true, false]);\n%!test  # Three output arguments of different type\n%! [A, B, C] = cellfun ('find', {10, 11; 0, 12}, \"UniformOutput\", false);\n%! assert (isequal (A, {true, true; [], true}));\n%! assert (isequal (B, {true, true; [], true}));\n%! assert (isequal (C, {10, 11; [], 12}));\n\n## Input arguments can be of type cell array of logical\n%!test\n%! A = cellfun (@(x,y) x == y, {false, true}, {true, true});\n%! assert (A, [false, true]);\n%!test\n%! A = cellfun (@(x,y) x == y, {false; true}, {true; true}, ...\n%!              \"UniformOutput\", true);\n%! assert (A, [false; true]);\n%!test\n%! A = cellfun (@(x) x, {false, true; false, true}, \"UniformOutput\", false);\n%! assert (A, {false, true; false, true});\n%!test  # Three output arguments of same type\n%! [A, B, C] = cellfun ('find', {true, false; false, true}, ...\n%!                      \"UniformOutput\", false);\n%! assert (isequal (A, {true, []; [], true}));\n%! assert (isequal (B, {true, []; [], true}));\n%! assert (isequal (C, {true, []; [], true}));\n%!test\n%! A = cellfun (@(x,y) cell2str (x,y), {true}, {true}, ...\n%!              \"ErrorHandler\", @__cellfunerror);\n%! assert (isfield (A, \"identifier\"), true);\n%! assert (isfield (A, \"message\"), true);\n%! assert (isfield (A, \"index\"), true);\n%! assert (isempty (A.message), false);\n%! assert (A.index, 1);\n%!test  # Overwriting setting of \"UniformOutput\" true\n%! A = cellfun (@(x,y) cell2str (x,y), {true}, {true}, ...\n%!              \"UniformOutput\", true, \"ErrorHandler\", @__cellfunerror);\n%! assert (isfield (A, \"identifier\"), true);\n%! assert (isfield (A, \"message\"), true);\n%! assert (isfield (A, \"index\"), true);\n%! assert (isempty (A.message), false);\n%! assert (A.index, 1);\n\n## Input arguments can be of type cell array of numeric\n%!test\n%! A = cellfun (@(x,y) x>y, {1.1, 4.2}, {3.1, 2+3*i});\n%! assert (A, [false, true]);\n%!test\n%! A = cellfun (@(x,y) x>y, {1.1, 4.2; 2, 4}, {3.1, 2; 2, 4+2*i}, ...\n%!              \"UniformOutput\", true);\n%! assert (A, [false, true; false, false]);\n%!test\n%! A = cellfun (@(x,y) x:y, {1.1, 4}, {3.1, 6}, \"UniformOutput\", false);\n%! assert (isequal (A{1}, [1.1, 2.1, 3.1]));\n%! assert (isequal (A{2}, [4, 5, 6]));\n%!test  # Three output arguments of different type\n%! [A, B, C] = cellfun ('find', {10, 11; 0, 12}, \"UniformOutput\", false);\n%! assert (isequal (A, {true, true; [], true}));\n%! assert (isequal (B, {true, true; [], true}));\n%! assert (isequal (C, {10, 11; [], 12}));\n%!test\n%! A = cellfun (@(x,y) cell2str (x,y), {1.1, 4}, {3.1, 6}, ...\n%!              \"ErrorHandler\", @__cellfunerror);\n%! B = isfield (A(1), \"message\") && isfield (A(1), \"index\");\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n%!test  # Overwriting setting of \"UniformOutput\" true\n%! A = cellfun (@(x,y) cell2str (x,y), {1.1, 4}, {3.1, 6}, ...\n%!              \"UniformOutput\", true, \"ErrorHandler\", @__cellfunerror);\n%! B = isfield (A(1), \"message\") && isfield (A(1), \"index\");\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n\n## Input arguments can be of type cell arrays of character or strings\n%!error  # \"UniformOutput\" false should be used\n%! A = cellfun (@(x,y) x>y, {\"ad\", \"c\", \"ghi\"}, {\"cc\", \"d\", \"fgh\"});\n%!test\n%! A = cellfun (@(x,y) x>y, {\"a\"; \"f\"}, {\"c\"; \"d\"}, \"UniformOutput\", true);\n%! assert (A, [false; true]);\n%!test\n%! A = cellfun (@(x,y) x:y, {\"a\", \"d\"}, {\"c\", \"f\"}, \"UniformOutput\", false);\n%! assert (A, {\"abc\", \"def\"});\n%!test\n%! A = cellfun (@(x,y) cell2str (x,y), {\"a\", \"d\"}, {\"c\", \"f\"}, ...\n%!              \"ErrorHandler\", @__cellfunerror);\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n%!test  # Overwriting setting of \"UniformOutput\" true\n%! A = cellfun (@(x,y) cell2str (x,y), {\"a\", \"d\"}, {\"c\", \"f\"}, ...\n%!              \"UniformOutput\", true, \"ErrorHandler\", @__cellfunerror);\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n\n## Structures cannot be handled by cellfun\n%!error\n%! vst1.a = 1.1;  vst1.b = 4.2;  vst2.a = 3.1;  vst2.b = 2;\n%! A = cellfun (@(x,y) (x.a < y.a) && (x.b > y.b), vst1, vst2);\n\n## Input arguments can be of type cell array of cell arrays\n%!test\n%! A = cellfun (@(x,y) x{1} < y{1}, {{1.1}, {4.2}}, {{3.1}, {2}});\n%! assert (A, [1, 0], 1e-16);\n%!test\n%! A = cellfun (@(x,y) x{1} < y{1}, {{1.1}; {4.2}}, {{3.1}; {2}}, ...\n%!              \"UniformOutput\", true);\n%! assert (A, [1; 0], 1e-16);\n%!test\n%! A = cellfun (@(x,y) x{1} < y{1}, {{1.1}, {4.2}}, {{3.1}, {2}}, ...\n%!              \"UniformOutput\", false);\n%! assert (A, {true, false});\n%!test\n%! A = cellfun (@(x,y) mat2str (x,y), {{1.1}, {4.2}}, {{3.1}, {2}}, ...\n%!              \"ErrorHandler\", @__cellfunerror);\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n%!test  # Overwriting setting of \"UniformOutput\" true\n%! A = cellfun (@(x,y) mat2str (x,y), {{1.1}, {4.2}}, {{3.1}, {2}}, ...\n%!              \"UniformOutput\", true, \"ErrorHandler\", @__cellfunerror);\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n\n## Input arguments can be of type cell array of structure arrays\n%!test\n%! a = struct (\"a\", 1, \"b\", 2);  b = struct (\"a\", 1, \"b\", 3);\n%! A = cellfun (@(x,y) (x.a == y.a) && (x.b < y.b), {a}, {b});\n%! assert (A, true);\n%!test\n%! a = struct (\"a\", 1, \"b\", 2);  b = struct (\"a\", 1, \"b\", 3);\n%! A = cellfun (@(x,y) (x.a == y.a) && (x.b < y.b) , {a}, {b}, ...\n%!              \"UniformOutput\", true);\n%! assert (A, true);\n%!test\n%! a = struct (\"a\", 1, \"b\", 2);  b = struct (\"a\", 1, \"b\", 3);\n%! A = cellfun (@(x,y) (x.a == y.a) && (x.b < y.b) , {a}, {b}, ...\n%!              \"UniformOutput\", false);\n%! assert (A, {true});\n%!test\n%! a = struct (\"a\", 1, \"b\", 2);  b = struct (\"a\", 1, \"b\", 3);\n%! A = cellfun (@(x,y) cell2str (x.a, y.a), {a}, {b}, ...\n%!              \"ErrorHandler\", @__cellfunerror);\n%! assert (isfield (A, \"identifier\"), true);\n%! assert (isfield (A, \"message\"), true);\n%! assert (isfield (A, \"index\"), true);\n%! assert (isempty (A.message), false);\n%! assert (A.index, 1);\n%!test  # Overwriting setting of \"UniformOutput\" true\n%! a = struct (\"a\", 1, \"b\", 2);  b = struct (\"a\", 1, \"b\", 3);\n%! A = cellfun (@(x,y) cell2str (x.a, y.a), {a}, {b}, ...\n%!              \"UniformOutput\", true, \"ErrorHandler\", @__cellfunerror);\n%! assert (isfield (A, \"identifier\"), true);\n%! assert (isfield (A, \"message\"), true);\n%! assert (isfield (A, \"index\"), true);\n%! assert (isempty (A.message), false);\n%! assert (A.index, 1);\n\n## A lot of other tests\n%!assert (cellfun (@sin, {0,1}), sin ([0,1]))\n%!test\n%! warning ('off', 'Octave:legacy-function', 'local');\n%! assert (cellfun (inline (\"sin (x)\"), {0,1}), sin ([0,1]));\n%!assert (cellfun (\"sin\", {0,1}), sin ([0,1]))\n%!assert (cellfun (\"isempty\", {1,[]}), [false,true])\n%!assert (cellfun (\"islogical\", {false,pi}), [true,false])\n%!assert (cellfun (\"isnumeric\", {false,pi,struct()}), [false,true,false])\n%!assert (cellfun (\"isreal\", {1i,1}), [false,true])\n%!assert (cellfun (\"length\", {zeros(2,2),1}), [2,1])\n%!assert (cellfun (\"prodofsize\", {zeros(2,2),1}), [4,1])\n%!assert (cellfun (\"ndims\", {zeros([2,2,2]),1}), [3,2])\n%!assert (cellfun (\"isclass\", {zeros([2,2,2]),\"test\"}, \"double\"), [true,false])\n%!assert (cellfun (\"size\", {zeros([1,2,3]),1}, 1), [1,1])\n%!assert (cellfun (\"size\", {zeros([1,2,3]),1}, 2), [2,1])\n%!assert (cellfun (\"size\", {zeros([1,2,3]),1}, 3), [3,1])\n%!assert (cellfun ('atan2', {1,1}, {1,2}), [atan2(1,1), atan2(1,2)])\n%!assert (cellfun ('atan2', {1,1}, {1,2},\"UniformOutput\", false),\n%!        {atan2(1,1), atan2(1,2)})\n%!assert (cellfun ('sin', {1,2;3,4}), sin ([1,2;3,4]))\n%!assert (cellfun ('atan2', {1,1;1,1}, {1,2;1,2}), atan2 ([1,1;1,1],[1,2;1,2]))\n%!error cellfun ('factorial', {-1,3})\n%!assert (cellfun ('factorial', {-1,3}, \"ErrorHandler\", @(x,y) NaN), [NaN,6])\n%!assert (cellfun (@(x) x(2),{[1],[1,2]}, \"ErrorHandler\", @(x,y) NaN), [NaN,2])\n%!test\n%! [a,b,c] = cellfun ('fileparts', {fullfile(\"a\",\"b\",\"c.d\"), fullfile(\"e\",\"f\",\"g.h\")}, \"UniformOutput\", false);\n%! assert (a, {fullfile(\"a\",\"b\"), fullfile(\"e\",\"f\")});\n%! assert (b, {\"c\", \"g\"});\n%! assert (c, {\".d\", \".h\"});\n\n%!assert <*40467> (cellfun ('isreal', {1 inf NaN []}), [true, true, true, true])\n%!assert <*40467> (cellfun (@isreal, {1 inf NaN []}, \"UniformOutput\", false),\n%!                 {true, true, true, true})\n%!assert <*40467> (cellfun ('iscomplex', {1 inf NaN []}),\n%!                 [false, false, false, false])\n%!assert <*40467> (cellfun ('iscomplex', {1 inf NaN []}, \"UniformOutput\", false),\n%!                 {false, false, false, false})\n\n## Output values of different sizes\n%!test <*67217>\n%! fail (\"cellfun (@(x) x, {5, [1, 2]})\", \"all values must be scalars\");\n\n## Output values of different types\n%!test <*67217>\n%! fail (\"cellfun (@(x) x, {5, true})\", \"all values should be of the same type\");\n\n%!function retval = __errfcn (S, varargin)\n%!  global __errmsg;\n%!  __errmsg = S.message;\n%!  retval = NaN;\n%!endfunction\n%!test <*58411>\n%! global __errmsg;\n%! assert (cellfun ('factorial', {1, 2, -3}, \"ErrorHandler\", @__errfcn),\n%!         [1, 2, NaN]);\n%! assert (! isempty (__errmsg));\n%! clear -global __errmsg;\n\n## An error should occur if called function does not return requested outputs\n%!function [a, b] = __counterror (x)\n%!  a = x;\n%!  if (x > 0)\n%!    b = x;\n%!  endif\n%!endfunction\n%!test <*66642>  # First call returns fewer outputs\n%! fail (\"[a, b] = cellfun (@__counterror, {-1, 4})\",\n%!       \"function returned fewer than nargout values\");\n%!test <*66642>  # Subsequent call returns fewer outputs\n%! fail (\"[a, b] = cellfun (@__counterror, {1, -4})\",\n%!       \"function returned fewer than nargout values\");\n%!test <*66642>  # Non-uniform output with one call returning fewer outputs\n%! fail (\"[a, b] = cellfun (@__counterror, {1, -4}, 'UniformOutput', false)\",\n%!       \"function returned fewer than nargout values\");\n%!test  # It's OK to return more outputs than requested\n%! a = cellfun (@__counterror, {1, -4});\n%! assert (a, [1, -4]);\n%! a = cellfun (@__counterror, {-1, 4});\n%! assert (a, [-1, 4]);\n%! cellfun (@__counterror, {-1, 4});\n%! assert (ans, [-1, 4]);\n%! cellfun (@__counterror, {1, -4});\n%! assert (ans, [1, -4]);\n%!\n## Testing nargout=0\n%!function r = __counterror1 (x)\n%!  if (x > 0)\n%!    r = x;\n%!  endif\n%!endfunction\n## When nargout=0 and UniformOutput=true, either every call returns something,\n## or none does.\n%!test <*66642>\n%! fail (\"cellfun (@__counterror1, {1, -2})\",\n%!       \"cellfun: function returned fewer than nargout values\");\n%!test <*66642>\n%! fail (\"cellfun (@__counterror1, {-1, 2})\",\n%!       \"function returned unexpected number of values\");\n## When nargout=0 and UniformOutput=false, each function call can either\n## return something or not.\n%!test\n%! cellfun (@__counterror1, {1, -2}, \"UniformOutput\", false);\n%! assert (ans, {1, []});\n%!test\n%! cellfun (@__counterror1, {-1, 2}, \"UniformOutput\", false);\n%! assert (ans, {[], 2});\n%!\n%!function varargout = __fvarg (n)\n%!  varargout = num2cell (n:-1:1);\n%!endfunction\n%!\n%!test <*66642>  # varargout, with number of outputs >= nargout\n%! a = cellfun (@__fvarg, {2, 1, 3});\n%! assert (a, [2,1,3]);\n\n## Test input validation\n%!error <Invalid call> cellfun (1)\n%!error <C must be a cell array> cellfun (@sin, [1 2 3])\n%!error <accelerated function must be called with only one argument>\n%! cellfun ('isempty', {1}, {2});\n%!error <'isclass' must be called with exactly two arg> cellfun ('isclass', {1})\n%!error <CLASS argument .* must be a string> cellfun ('isclass', {1}, 1)\n%!error <'size' must be called with exactly two arg> cellfun ('size', {1})\n%!error <K must be a positive integer> cellfun ('size', {1}, -1)\n%!error <UniformOutput value must be boolean>\n%! cellfun (@sin, {1}, 'UniformOutput', {'Cell'})\n%!error <invalid function NAME> cellfun ('foo123bar567', {1})\n%!error <NAME must be a string or function handle> cellfun ([1 2 3], {1})\n%!error <arguments must be cells> cellfun (@atan2, {1}, [1])\n%!error <dimensions mismatch> cellfun (@atan2, {1; 2}, {1, 2})\n%!error <unrecognized parameter> cellfun ('sin', {1}, \"BadParam\", false)\n%!error cellfun ('sin', {[]}, \"UniformOuput\")\n%!error cellfun ('sin', {[]}, \"ErrorHandler\")\n\n*/\n\n\n// Arrayfun was originally a .m file written by Bill Denney and Jaroslav\n// Hajek.  It was converted to C++ by jwe so that it could properly\n// handle the nargout = 0 case.\n\n// FIXME: Function should be re-written to determine function calling form\n//        just once (since for an array the data type cannot change) and then\n//        execute that function repeatedly without the overhead of looking up\n//        the correct function in symbol table every time.\nDEFMETHOD (arrayfun, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{B} =} arrayfun (@var{fcn}, @var{A})\n@deftypefnx {} {@var{B} =} arrayfun (@var{fcn}, @var{A1}, @var{A2}, @dots{})\n@deftypefnx {} {[@var{B1}, @var{B2}, @dots{}] =} arrayfun (@var{fcn}, @var{A}, @dots{})\n@deftypefnx {} {@var{B} =} arrayfun (@dots{}, \"UniformOutput\", @var{val})\n@deftypefnx {} {@var{B} =} arrayfun (@dots{}, \"ErrorHandler\", @var{errfcn})\n\nExecute a function on each element of an array.\n\nThis is useful for functions that do not accept array arguments.  If the\nfunction does accept array arguments it is @emph{better} to call the function\ndirectly.\n\nThe first input argument @var{fcn} can be a string, a function handle, an\ninline function, or an anonymous function.  The input argument @var{A} can be a\nlogical array, a numeric array, a string array, a structure array, or a cell\narray.  @code{arrayfun} passes all elements of @var{A} individually to the\nfunction @var{fcn} and collects the results.  The equivalent pseudo-code is\n\n@example\n@group\ncls = class (@var{fcn} (@var{A}(1));\n@var{B} = zeros (size (@var{A}), cls);\nfor i = 1:numel (@var{A})\n  @var{B}(i) = @var{fcn} (@var{A}(i))\nendfor\n@end group\n@end example\n\nThe named function can also take more than two input arguments, with the input\narguments given as third input argument @var{A2}, fourth input argument\n@var{A2}, @enddots{}  If given more than one array input argument then all\ninput arguments must have the same sizes.  For example:\n\n@example\n@group\narrayfun (@@atan2, [1, 0], [0, 1])\n     @xresult{} [ 1.57080   0.00000 ]\n@end group\n@end example\n\nIf the parameter @var{val} after a further string input argument\n@qcode{\"UniformOutput\"} is set @code{true} (the default), then the named\nfunction @var{fcn} must return a single element which then will be concatenated\ninto the return value and is of type matrix.  Otherwise, if that parameter is\nset to @code{false}, then the outputs are concatenated in a cell array.  For\nexample:\n\n@example\n@group\narrayfun (@@(x,y) x:y, \"abc\", \"def\", \"UniformOutput\", false)\n@xresult{}\n   @{\n     [1,1] = abcd\n     [1,2] = bcde\n     [1,3] = cdef\n   @}\n@end group\n@end example\n\nIf more than one output arguments are given then the named function must return\nthe number of return values that also are expected, for example:\n\n@example\n@group\n[A, B, C] = arrayfun (@@find, [10; 0], \"UniformOutput\", false)\n@xresult{}\nA =\n@{\n   [1,1] =  1\n   [2,1] = [](0x0)\n@}\nB =\n@{\n   [1,1] =  1\n   [2,1] = [](0x0)\n@}\nC =\n@{\n   [1,1] =  10\n   [2,1] = [](0x0)\n@}\n@end group\n@end example\n\nIf the parameter @var{errfcn} after a further string input argument\n@qcode{\"ErrorHandler\"} is another string, a function handle, an inline\nfunction, or an anonymous function, then @var{errfcn} defines a function to\ncall in the case that @var{fcn} generates an error.  The definition of the\nfunction must be of the form\n\n@example\nfunction [@dots{}] = errfcn (@var{s}, @dots{})\n@end example\n\n@noindent\nwhere there is an additional input argument to @var{errfcn} relative to\n@var{fcn}, given by @var{s}.  This is a structure with the elements\n@qcode{\"identifier\"}, @qcode{\"message\"}, and @qcode{\"index\"} giving,\nrespectively, the error identifier, the error message, and the index of the\narray elements that caused the error.  The size of the output argument of\n@var{errfcn} must have the same size as the output argument of @var{fcn},\notherwise a real error is thrown.  For example:\n\n@example\n@group\nfunction y = ferr (s, x), y = \"MyString\"; endfunction\narrayfun (@@str2num, [1234],\n          \"UniformOutput\", false, \"ErrorHandler\", @@ferr)\n@xresult{}\n   @{\n     [1,1] = MyString\n   @}\n@end group\n@end example\n\n@seealso{spfun, cellfun, structfun}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  octave_value_list retval;\n  int nargout1 = (nargout < 1 ? 1 : nargout);\n  bool symbol_table_lookup = false;\n  octave_value fcn = args(0);\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  if (fcn.is_string ())\n    {\n      // See if we can convert the string into a function.\n      std::string name = args(0).string_value ();\n\n      if (! valid_identifier (name))\n        fcn = get_function_handle (interp, args(0), \"x\");\n      else\n        {\n          fcn = symtab.find_function (name);\n\n          if (fcn.is_undefined ())\n            error_with_id (\"Octave:invalid-input-arg\",\n                           \"arrayfun: invalid function NAME: %s\",\n                           name.c_str ());\n\n          symbol_table_lookup = true;\n        }\n    }\n\n  if (fcn.is_function_handle () || fcn.is_inline_function ()\n      || fcn.is_function ())\n    {\n      // The following is an optimization because the symbol table can give a\n      // more specific function class, so this can result in fewer polymorphic\n      // function calls as the function gets called for each value of the array.\n\n      if (! symbol_table_lookup)\n        {\n          if (fcn.is_function_handle () || fcn.class_name () == \"inline\")\n            {\n              // FIXME: instead of checking for overloaded functions as\n              // we did previously but is no longer possible, we could\n              // check whether the types of all the cell array elements\n              // are the same, then lookup the function for that type\n              // just once.\n\n              goto nevermind;\n            }\n\n          octave_value f\n            = symtab.find_function (fcn.function_value () -> name ());\n\n          if (f.is_defined ())\n            fcn = f;\n        }\n\n    nevermind:\n\n      bool uniform_output = true;\n      octave_value error_handler;\n\n      parse_options (symtab, args, nargin, uniform_output, error_handler);\n\n      octave_value_list inputlist (nargin, octave_value ());\n\n      OCTAVE_LOCAL_BUFFER (octave_value, inputs, nargin);\n      OCTAVE_LOCAL_BUFFER (bool, mask, nargin);\n\n      octave_idx_type k = 1;\n\n      dim_vector fdims (1, 1);\n\n      // Collect arguments.  Pre-fill scalar elements of inputlist array.\n\n      for (int j = 0; j < nargin; j++)\n        {\n          inputs[j] = args(j+1);\n          mask[j] = inputs[j].numel () != 1;\n\n          if (! mask[j])\n            inputlist(j) = inputs[j];\n        }\n\n      for (int j = 0; j < nargin; j++)\n        {\n          if (mask[j])\n            {\n              fdims = inputs[j].dims ();\n              k = inputs[j].numel ();\n\n              for (int i = j+1; i < nargin; i++)\n                {\n                  if (mask[i] && inputs[i].dims () != fdims)\n                    error_with_id (\"Octave:invalid-input-arg\",\n                                   \"arrayfun: dimensions mismatch\");\n                }\n              break;\n            }\n        }\n\n      // Apply functions.\n\n      if (uniform_output)\n        {\n          std::list<octave_value_list> idx_list (1);\n          idx_list.front ().resize (1);\n          std::string idx_type = \"(\";\n\n          OCTAVE_LOCAL_BUFFER (octave_value, retv, nargout1);\n\n          // FIXME: Initialized to prevent compiler warning.\n          // However, it would be better if the code guaranteed that variable\n          // was always assigned a valid value.\n          int expected_nargout = 0;\n          for (octave_idx_type count = 0; count < k; count++)\n            {\n              idx_list.front ()(0) = count + 1.0;\n\n              for (int j = 0; j < nargin; j++)\n                {\n                  if (mask[j])\n                    inputlist.xelem (j) = inputs[j].index_op (idx_list);\n                }\n\n              const octave_value_list y\n                = fcn_eval (interp, count, nargout, inputlist, fcn,\n                            error_handler);\n\n              // Validate number of generated results is correct\n              int y_nel = y.length ();\n              if (count == 0)\n                {\n                  // First time through loop.  Initialize expected number of\n                  // outputs based on output from first function evaluation.\n                  if (nargout == 0)\n                    expected_nargout = (y_nel > 0 && y(0).is_defined ())\n                                       ? 1 : 0;\n                  else\n                    expected_nargout = nargout;\n                }\n              if (y_nel < expected_nargout)\n                error_with_id (\"Octave:invalid-fun-call\",\n                               \"arrayfun: function returned fewer than nargout values\");\n              else if (expected_nargout == 0 && y_nel > 0 && y(0).is_defined ())\n                error (\"cellfun: function returned unexpected number of values\");\n\n              if (expected_nargout > 0)\n                {\n                  if (count == 0)\n                    {\n                      for (int j = 0; j < expected_nargout; j++)\n                        {\n                          if (y(j).is_defined ())\n                            {\n                              octave_value val = y(j);\n\n                              if (val.numel () == 1)\n                                retv[j] = val.resize (fdims);\n                              else\n                                error_with_id (\"Octave:invalid-fun-call\",\n                                               \"arrayfun: all values must be scalars when UniformOutput = true\");\n                            }\n                          else\n                            error (\"arrayfun: function returned fewer than nargout values\");\n                        }\n                    }\n                  else\n                    {\n                      for (int j = 0; j < expected_nargout; j++)\n                        {\n                          if (y(j).is_defined ())\n                            {\n                              octave_value val = y(j);\n\n                              if (! retv[j].fast_elem_insert (count, val))\n                                {\n                                  if (val.numel () == 1)\n                                    {\n                                      idx_list.front ()(0) = count + 1.0;\n                                      retv[j].assign (octave_value::op_asn_eq,\n                                                      idx_type, idx_list, val);\n                                    }\n                                  else\n                                    error_with_id (\"Octave:invalid-fun-call\",\n                                                   \"arrayfun: all values must be scalars when UniformOutput = true\");\n                                }\n                            }\n                          else\n                            error (\"arrayfun: function returned fewer than nargout values\");\n                        }\n                    }\n                }\n            }\n\n          retval.resize (nargout1);\n\n          for (int j = 0; j < nargout1; j++)\n            {\n              if (nargout > 0 && retv[j].is_undefined ())\n                retval(j) = NDArray (fdims);\n              else\n                retval(j) = retv[j];\n            }\n        }\n      else\n        {\n          std::list<octave_value_list> idx_list (1);\n          idx_list.front ().resize (1);\n          std::string idx_type = \"(\";\n\n          OCTAVE_LOCAL_BUFFER (Cell, results, nargout1);\n\n          for (int j = 0; j < nargout1; j++)\n            results[j].resize (fdims, Matrix ());\n\n          bool have_some_output = false;\n\n          for (octave_idx_type count = 0; count < k; count++)\n            {\n              idx_list.front ()(0) = count + 1.0;\n\n              for (int j = 0; j < nargin; j++)\n                {\n                  if (mask[j])\n                    inputlist.xelem (j) = inputs[j].index_op (idx_list);\n                }\n\n              const octave_value_list y\n                = fcn_eval (interp, count, nargout, inputlist, fcn,\n                            error_handler);\n\n              if (nargout > 0 && y.length () < nargout)\n                error_with_id (\"Octave:invalid-fun-call\",\n                               \"arrayfun: function returned fewer than nargout values\");\n\n              if (nargout > 0\n                  || (nargout == 0\n                      && y.length () > 0 && y(0).is_defined ()))\n                {\n                  int num_to_copy = y.length ();\n\n                  if (num_to_copy > nargout1)\n                    num_to_copy = nargout1;\n\n                  if (num_to_copy > 0)\n                    have_some_output = true;\n\n                  for (int j = 0; j < num_to_copy; j++)\n                    {\n                      if (y(j).is_undefined ())\n                        error (\"arrayfun: function returned fewer than nargout values\");\n                      results[j](count) = y(j);\n                    }\n                }\n            }\n\n          if (have_some_output || fdims.any_zero ())\n            {\n              retval.resize (nargout1);\n\n              for (int j = 0; j < nargout1; j++)\n                retval(j) = results[j];\n            }\n        }\n    }\n  else\n    error_with_id (\"Octave:invalid-fun-call\",\n                   \"arrayfun: argument NAME must be a string or function handle\");\n\n  return retval;\n}\n\n/*\n%!function r = __f11 (x)\n%!  r = x;\n%!endfunction\n\n%!function __f01 (x)\n%!  ## Empty function\n%!endfunction\n\n%!test\n%! __arrayfun_test_num_outputs__ = -1;\n%!\n%! function r = __subf11 (x)\n%!   __arrayfun_test_num_outputs__ = nargout;\n%!   r = x;\n%! endfunction\n%!\n%! arrayfun (\"__subf11\", {1});\n%! assert (__arrayfun_test_num_outputs__, 0);\n%!\n%! __arrayfun_test_num_outputs__ = -1;\n%! x = arrayfun (\"__subf11\", {1});\n%! assert (__arrayfun_test_num_outputs__, 1);\n\n%!test\n%! __arrayfun_test_num_outputs__ = -1;\n%!\n%! function __subf01 (x)\n%!   __arrayfun_test_num_outputs__ = nargout;\n%! endfunction\n%!\n%! arrayfun (\"__subf01\", {1});\n%! assert (__arrayfun_test_num_outputs__, 0);\n\n%!error x = arrayfun (@__f01, [1, 2])\n\n%!test\n%! assert (arrayfun (@__f11, [1, 2]), [1, 2]);\n%! assert (arrayfun (@__f11, [1, 2], \"uniformoutput\", false), {1, 2});\n%! assert (arrayfun (@__f11, {1, 2}), {1, 2});\n%! assert (arrayfun (@__f11, {1, 2}, \"uniformoutput\", false), {{1}, {2}});\n\n%!assert (arrayfun (@ones, 1, [2,3], \"uniformoutput\", false), {[1,1], [1,1,1]})\n\n## Test function to check the \"Errorhandler\" option\n%!function z = __arrayfunerror (S, varargin)\n%!  z = S;\n%!endfunction\n## First input argument can be a string, an inline function, a\n## function_handle or an anonymous function\n%!test\n%! arrayfun (@isequal, [false, true], [true, true]);  # No output argument\n%!error\n%! arrayfun (@isequal);  # One or less input arguments\n%!test\n%! A = arrayfun (\"isequal\", [false, true], [true, true]);\n%! assert (A, [false, true]);\n%!test\n%! warning ('off', 'Octave:legacy-function', 'local');\n%! A = arrayfun (inline (\"(x == y)\", \"x\", \"y\"), [false, true], [true, true]);\n%! assert (A, [false, true]);\n%!test\n%! A = arrayfun (@isequal, [false, true], [true, true]);\n%! assert (A, [false, true]);\n%!test\n%! A = arrayfun (@(x,y) isequal (x,y), [false, true], [true, true]);\n%! assert (A, [false, true]);\n\n## Number of input and output arguments may be greater than one\n%!test\n%! A = arrayfun (@(x) islogical (x), false);\n%! assert (A, true);\n%!test\n%! A = arrayfun (@(x,y,z) x + y + z, [1, 1, 1], [2, 2, 2], [3, 4, 5]);\n%! assert (A, [6, 7, 8], 1e-16);\n%!test  # Two input arguments of different types\n%! A = arrayfun (@(x,y) islogical (x) && ischar (y), false, \"a\");\n%! assert (A, true);\n%!test  # Pass another variable to the anonymous function\n%! y = true;\n%! A = arrayfun (@(x) islogical (x && y), false);\n%! assert (A, true);\n%!test  # Three output arguments of different type\n%! [A, B, C] = arrayfun (@find, [10, 11; 0, 12], \"UniformOutput\", false);\n%! assert (isequal (A, {true, true; [], true}));\n%! assert (isequal (B, {true, true; [], true}));\n%! assert (isequal (C, {10, 11; [], 12}));\n\n## Input arguments can be of type logical\n%!test\n%! A = arrayfun (@(x,y) x == y, [false, true], [true, true]);\n%! assert (A, [false, true]);\n%!test\n%! A = arrayfun (@(x,y) x == y, [false; true], [true; true], \"UniformOutput\", true);\n%! assert (A, [false; true]);\n%!test\n%! A = arrayfun (@(x) x, [false, true, false, true], \"UniformOutput\", false);\n%! assert (A, {false, true, false, true});\n%!test  # Three output arguments of same type\n%! [A, B, C] = arrayfun (@find, [true, false; false, true], \"UniformOutput\", false);\n%! assert (isequal (A, {true, []; [], true}));\n%! assert (isequal (B, {true, []; [], true}));\n%! assert (isequal (C, {true, []; [], true}));\n%!test\n%! A = arrayfun (@(x,y) array2str (x,y), true, true, ...\n%!               \"ErrorHandler\", @__arrayfunerror);\n%! assert (isfield (A, \"identifier\"), true);\n%! assert (isfield (A, \"message\"), true);\n%! assert (isfield (A, \"index\"), true);\n%! assert (isempty (A.message), false);\n%! assert (A.index, 1);\n%!test  # Overwriting setting of \"UniformOutput\" true\n%! A = arrayfun (@(x,y) array2str (x,y), true, true, \"UniformOutput\", true, ...\n%!               \"ErrorHandler\", @__arrayfunerror);\n%! assert (isfield (A, \"identifier\"), true);\n%! assert (isfield (A, \"message\"), true);\n%! assert (isfield (A, \"index\"), true);\n%! assert (isempty (A.message), false);\n%! assert (A.index, 1);\n\n## Input arguments can be of type numeric\n%!test\n%! A = arrayfun (@(x,y) x>y, [1.1, 4.2], [3.1, 2+3*i]);\n%! assert (A, [false, true]);\n%!test\n%! A = arrayfun (@(x,y) x>y, [1.1, 4.2; 2, 4], [3.1, 2; 2, 4+2*i], \"UniformOutput\", true);\n%! assert (A, [false, true; false, false]);\n%!test\n%! A = arrayfun (@(x,y) x:y, [1.1, 4], [3.1, 6], \"UniformOutput\", false);\n%! assert (isequal (A{1}, [1.1, 2.1, 3.1]));\n%! assert (isequal (A{2}, [4, 5, 6]));\n%!test  # Three output arguments of different type\n%! [A, B, C] = arrayfun (@find, [10, 11; 0, 12], \"UniformOutput\", false);\n%! assert (isequal (A, {true, true; [], true}));\n%! assert (isequal (B, {true, true; [], true}));\n%! assert (isequal (C, {10, 11; [], 12}));\n%!test\n%! A = arrayfun (@(x,y) array2str (x,y), {1.1, 4}, {3.1, 6}, ...\n%!               \"ErrorHandler\", @__arrayfunerror);\n%! B = isfield (A(1), \"message\") && isfield (A(1), \"index\");\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n%!test  # Overwriting setting of \"UniformOutput\" true\n%! A = arrayfun (@(x,y) array2str (x,y), {1.1, 4}, {3.1, 6}, ...\n%!               \"UniformOutput\", true, \"ErrorHandler\", @__arrayfunerror);\n%! B = isfield (A(1), \"message\") && isfield (A(1), \"index\");\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n\n## Input arguments can be of type character or strings\n%!test\n%! A = arrayfun (@(x,y) x>y, [\"ad\", \"c\", \"ghi\"], [\"cc\", \"d\", \"fgh\"]);\n%! assert (A, [false, true, false, true, true, true]);\n%!test\n%! A = arrayfun (@(x,y) x>y, [\"a\"; \"f\"], [\"c\"; \"d\"], \"UniformOutput\", true);\n%! assert (A, [false; true]);\n%!test\n%! A = arrayfun (@(x,y) x:y, [\"a\", \"d\"], [\"c\", \"f\"], \"UniformOutput\", false);\n%! assert (A, {\"abc\", \"def\"});\n%!test\n%! A = arrayfun (@(x,y) cell2str (x,y), [\"a\", \"d\"], [\"c\", \"f\"], ...\n%!               \"ErrorHandler\", @__arrayfunerror);\n%! B = isfield (A(1), \"identifier\") && isfield (A(1), \"message\") ...\n%!     && isfield (A(1), \"index\");\n%! assert (B, true);\n\n## Input arguments can be of type structure\n%!test\n%! a = struct (\"a\", 1.1, \"b\", 4.2);  b = struct (\"a\", 3.1, \"b\", 2);\n%! A = arrayfun (@(x,y) (x.a < y.a) && (x.b > y.b), a, b);\n%! assert (A, true);\n%!test\n%! a = struct (\"a\", 1.1, \"b\", 4.2);  b = struct (\"a\", 3.1, \"b\", 2);\n%! A = arrayfun (@(x,y) (x.a < y.a) && (x.b > y.b), a, b, \"UniformOutput\", true);\n%! assert (A, true);\n%!test\n%! a = struct (\"a\", 1.1, \"b\", 4.2);  b = struct (\"a\", 3.1, \"b\", 2);\n%! A = arrayfun (@(x,y) x.a:y.a, a, b, \"UniformOutput\", false);\n%! assert (isequal (A, {[1.1, 2.1, 3.1]}));\n%!test\n%! A = arrayfun (@(x) mat2str (x), \"a\", \"ErrorHandler\", @__arrayfunerror);\n%! assert (isfield (A, \"identifier\"), true);\n%! assert (isfield (A, \"message\"), true);\n%! assert (isfield (A, \"index\"), true);\n%! assert (isempty (A.message), false);\n%! assert (A.index, 1);\n%!test  # Overwriting setting of \"UniformOutput\" true\n%! A = arrayfun (@(x) mat2str (x), \"a\", \"UniformOutput\", true, ...\n%!               \"ErrorHandler\", @__arrayfunerror);\n%! assert (isfield (A, \"identifier\"), true);\n%! assert (isfield (A, \"message\"), true);\n%! assert (isfield (A, \"index\"), true);\n%! assert (isempty (A.message), false);\n%! assert (A.index, 1);\n\n## Input arguments can be of type cell array\n%!test\n%! A = arrayfun (@(x,y) x{1} < y{1}, {1.1, 4.2}, {3.1, 2});\n%! assert (A, [true, false]);\n%!test\n%! A = arrayfun (@(x,y) x{1} < y{1}, {1.1; 4.2}, {3.1; 2}, \"UniformOutput\", true);\n%! assert (A, [true; false]);\n%!test\n%! A = arrayfun (@(x,y) x{1} < y{1}, {1.1, 4.2}, {3.1, 2}, \"UniformOutput\", false);\n%! assert (A, {true, false});\n%!test\n%! A = arrayfun (@(x,y) num2str(x,y), {1.1, 4.2}, {3.1, 2}, \"ErrorHandler\", @__arrayfunerror);\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n%!test\n%! A = arrayfun (@(x,y) num2str (x,y), {1.1, 4.2}, {3.1, 2}, ...\n%!               \"UniformOutput\", true, \"ErrorHandler\", @__arrayfunerror);\n%! assert ([(isfield (A(1), \"identifier\")), (isfield (A(2), \"identifier\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"message\")), (isfield (A(2), \"message\"))],\n%!         [true, true]);\n%! assert ([(isfield (A(1), \"index\")), (isfield (A(2), \"index\"))],\n%!         [true, true]);\n%! assert ([(isempty (A(1).message)), (isempty (A(2).message))],\n%!         [false, false]);\n%! assert ([A(1).index, A(2).index], [1, 2]);\n\n## An error should occur if called function does not return requested outputs\n%!test <*66642>  # First call returns fewer outputs\n%! fail (\"[a, b] = arrayfun (@__counterror, [-1, 4])\",\n%!       \"function returned fewer than nargout values\");\n%!test <*66642>  # Subsequent call returns fewer outputs\n%! fail (\"[a, b] = arrayfun (@__counterror, [1, -4])\",\n%!       \"function returned fewer than nargout values\");\n%!test <*66642>  # Non-uniform output\n%! fail (\"[a, b] = arrayfun (@__counterror, [1, -4], 'UniformOutput', false)\",\n%!       \"function returned fewer than nargout values\");\n%!test  # It's OK to return more outputs than requested\n%! a = arrayfun (@__counterror, [1, -4]);\n%! assert (a, [1, -4]);\n%! a = arrayfun (@__counterror, [-1, 4]);\n%! assert (a, [-1, 4]);\n%! arrayfun (@__counterror, [-1, 4]);\n%! assert (ans, [-1, 4]);\n%! arrayfun (@__counterror, [1, -4]);\n%! assert (ans, [1, -4]);\n%!\n## Testing nargout=0\n##  With nargout=0 and UniformOutput=true, either every call returns something,\n##  or none does.\n%!test <*66642>\n%! fail (\"arrayfun (@__counterror1, [1, -2])\",\n%!       \"arrayfun: function returned fewer than nargout values\");\n%!test <*66642>\n%! fail (\"arrayfun (@__counterror1, [-1, 2])\",\n%!       \"function returned unexpected number of values\");\n## When nargout=0 and UniformOutput=false, each function call can either\n## return something or not.\n%!test\n%! arrayfun (@__counterror1, [1,-2], \"UniformOutput\", false);\n%! assert (ans, {1, []});\n%!test\n%! arrayfun (@__counterror1, [-1,2], \"UniformOutput\", false);\n%! assert (ans, {[], 2});\n%!\n%!function varargout = __fvarg (n)\n%!  varargout = num2cell (n:-1:1);\n%!endfunction\n%!\n%!test  # varargout, with number of outputs >= nargout\n%! a = arrayfun (@__fvarg, [2, 1, 3]);\n%! assert (a, [2, 1, 3]);\n*/\n\nstatic void\ndo_num2cell_helper (const dim_vector& dv,\n                    const Array<int>& dimv,\n                    dim_vector& celldv, dim_vector& arraydv,\n                    Array<int>& perm)\n{\n  int dvl = dimv.numel ();\n  int maxd = dv.ndims ();\n  celldv = dv;\n  for (int i = 0; i < dvl; i++)\n    maxd = std::max (maxd, dimv(i));\n  if (maxd > dv.ndims ())\n    celldv.resize (maxd, 1);\n  arraydv = celldv;\n\n  OCTAVE_LOCAL_BUFFER_INIT (bool, sing, maxd, false);\n\n  perm.clear (maxd, 1);\n  for (int i = 0; i < dvl; i++)\n    {\n      int k = dimv(i) - 1;\n      if (k < 0)\n        error (\"num2cell: dimension indices must be positive\");\n\n      if (i > 0 && k < dimv(i-1) - 1)\n        error (\"num2cell: dimension indices must be strictly increasing\");\n\n      sing[k] = true;\n      perm(i) = k;\n    }\n\n  for (int k = 0, i = dvl; k < maxd; k++)\n    if (! sing[k])\n      perm(i++) = k;\n\n  for (int i = 0; i < maxd; i++)\n    if (sing[i])\n      celldv(i) = 1;\n    else\n      arraydv(i) = 1;\n}\n\ntemplate <typename NDA>\nstatic inline typename NDA::element_type\ndo_num2cell_elem (const NDA& array, octave_idx_type i)\n{ return array(i); }\n\nstatic inline Cell\ndo_num2cell_elem (const Cell& array, octave_idx_type i)\n{ return Cell (array(i)); }\n\ntemplate <typename NDA>\nstatic Cell\ndo_num2cell (const NDA& array, const Array<int>& dimv)\n{\n  if (dimv.isempty ())\n    {\n      Cell retval (array.dims ());\n      octave_idx_type nel = array.numel ();\n      for (octave_idx_type i = 0; i < nel; i++)\n        retval.xelem (i) = do_num2cell_elem (array, i);\n\n      return retval;\n    }\n  else\n    {\n      dim_vector celldv, arraydv;\n      Array<int> perm;\n      do_num2cell_helper (array.dims (), dimv, celldv, arraydv, perm);\n\n      NDA parray = array.permute (perm);\n\n      octave_idx_type nela = arraydv.numel ();\n      octave_idx_type nelc = celldv.numel ();\n      parray = parray.reshape (dim_vector (nela, nelc));\n\n      Cell retval (celldv);\n      for (octave_idx_type i = 0; i < nelc; i++)\n        {\n          retval.xelem (i) = NDA (parray.column (i).reshape (arraydv));\n        }\n\n      return retval;\n    }\n}\n\n// FIXME: this is a mess, but if a size method for the object exists,\n// we have to call it to get the size of the object instead of using the\n// internal dims method.\n\nstatic dim_vector\nget_object_dims (octave_value& obj)\n{\n  dim_vector retval;\n\n  Matrix m = obj.size ();\n\n  int n = m.numel ();\n\n  retval.resize (n);\n\n  for (int i = 0; i < n; i++)\n    retval(i) = m(i);\n\n  return retval;\n}\n\nstatic Cell\ndo_object2cell (const octave_value& obj, const Array<int>& dimv)\n{\n  Cell retval;\n\n  // FIXME: this copy is only needed because the octave_value::size\n  // method is not const.\n  octave_value array = obj;\n\n  if (! dimv.isempty ())\n    error (\"num2cell (A, dim) not implemented for class objects\");\n\n  const dim_vector& dv = get_object_dims (array);\n\n  retval.resize (dv);\n\n  octave_value_list idx (1);\n\n  for (octave_idx_type i = 0; i < dv.numel (); i++)\n    {\n      octave_quit ();\n\n      idx(0) = double (i+1);\n\n      retval.xelem (i) = array.single_subsref (\"(\", idx);\n    }\n\n  return retval;\n}\n\nDEFUN (num2cell, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} num2cell (@var{A})\n@deftypefnx {} {@var{C} =} num2cell (@var{A}, @var{dim})\nConvert the numeric matrix @var{A} to a cell array.\n\nWhen no @var{dim} is specified, each element of @var{A} becomes a 1x1 element\nin the output @var{C}.\n\nIf @var{dim} is defined then individual elements of @var{C} contain all of the\nelements from @var{A} along the specified dimension.  @var{dim} may also be a\nvector of dimensions with the same rule applied.\n\nFor example:\n\n@example\nx = [1,2;3,4]\n@xresult{}\n    1    2\n    3    4\n\n## each element of A becomes a 1x1 element of C\nnum2cell (x)\n   @xresult{}\n      @{\n        [1,1] =  1\n        [2,1] =  3\n        [1,2] =  2\n        [2,2] =  4\n      @}\n## all rows (dim 1) of A appear in each element of C\nnum2cell (x, 1)\n   @xresult{}\n      @{\n        [1,1] =\n           1\n           3\n        [1,2] =\n           2\n           4\n      @}\n## all columns (dim 2) of A appear in each element of C\nnum2cell (x, 2)\n   @xresult{}\n      @{\n        [1,1] =\n           1   2\n        [2,1] =\n           3   4\n      @}\n## all rows and cols appear in each element of C\n## (hence, only 1 output)\nnum2cell (x, [1, 2])\n   @xresult{}\n      @{\n        [1,1] =\n           1   2\n           3   4\n      @}\n@end example\n\n@seealso{mat2cell}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value retval;\n\n  octave_value array = args(0);\n\n  Array<int> dimv;\n  if (nargin > 1)\n    dimv = args(1).int_vector_value (true);\n\n  if (array.islogical ())\n    retval = do_num2cell (array.bool_array_value (), dimv);\n  else if (array.is_char_matrix ())\n    retval = do_num2cell (array.char_array_value (), dimv);\n  else if (array.isnumeric ())\n    {\n      if (array.isinteger ())\n        {\n          if (array.is_int8_type ())\n            retval = do_num2cell (array.int8_array_value (), dimv);\n          else if (array.is_int16_type ())\n            retval = do_num2cell (array.int16_array_value (), dimv);\n          else if (array.is_int32_type ())\n            retval = do_num2cell (array.int32_array_value (), dimv);\n          else if (array.is_int64_type ())\n            retval = do_num2cell (array.int64_array_value (), dimv);\n          else if (array.is_uint8_type ())\n            retval = do_num2cell (array.uint8_array_value (), dimv);\n          else if (array.is_uint16_type ())\n            retval = do_num2cell (array.uint16_array_value (), dimv);\n          else if (array.is_uint32_type ())\n            retval = do_num2cell (array.uint32_array_value (), dimv);\n          else if (array.is_uint64_type ())\n            retval = do_num2cell (array.uint64_array_value (), dimv);\n        }\n      else if (array.iscomplex ())\n        {\n          if (array.is_single_type ())\n            retval = do_num2cell (array.float_complex_array_value (), dimv);\n          else\n            retval = do_num2cell (array.complex_array_value (), dimv);\n        }\n      else\n        {\n          if (array.is_single_type ())\n            retval = do_num2cell (array.float_array_value (), dimv);\n          else\n            retval = do_num2cell (array.array_value (), dimv);\n        }\n    }\n  else if (array.isobject ())\n    retval = do_object2cell (array, dimv);\n  else if (array.isstruct ())\n    retval = do_num2cell (array.map_value (), dimv);\n  else if (array.iscell ())\n    retval = do_num2cell (array.cell_value (), dimv);\n  else\n    err_wrong_type_arg (\"num2cell\", array);\n\n  return retval;\n}\n\n/*\n%!assert (num2cell ([1,2;3,4]), {1,2;3,4})\n%!assert (num2cell ([1,2;3,4], 1), {[1;3],[2;4]})\n%!assert (num2cell ([1,2;3,4], 2), {[1,2];[3,4]})\n*/\n\nstatic bool\nmat2cell_mismatch (const dim_vector& dv,\n                   const Array<octave_idx_type> *d, int nd)\n{\n  for (int i = 0; i < nd; i++)\n    {\n      octave_idx_type s = 0;\n      for (octave_idx_type j = 0; j < d[i].numel (); j++)\n        s += d[i](j);\n\n      octave_idx_type r = (i < dv.ndims () ? dv(i) : 1);\n\n      if (s != r)\n        error (\"mat2cell: mismatch on dimension %d (%\" OCTAVE_IDX_TYPE_FORMAT\n               \" != %\" OCTAVE_IDX_TYPE_FORMAT \")\", i+1, r, s);\n    }\n\n  return false;\n}\n\ntemplate <typename container>\nstatic void\nprepare_idx (container *idx, int idim, int nd,\n             const Array<octave_idx_type> *d)\n{\n  octave_idx_type nidx = (idim < nd ? d[idim].numel () : 1);\n  if (nidx == 1)\n    idx[0] = idx_vector::colon;\n  else\n    {\n      octave_idx_type l = 0;\n      for (octave_idx_type i = 0; i < nidx; i++)\n        {\n          octave_idx_type u = l + d[idim](i);\n          idx[i] = idx_vector (l, u);\n          l = u;\n        }\n    }\n}\n\n// 2-D specialization, works for Array, Sparse and octave_map.\n// Uses 1-D or 2-D indexing.\n\ntemplate <typename Array2D>\nstatic Cell\ndo_mat2cell_2d (const Array2D& a, const Array<octave_idx_type> *d, int nd)\n{\n  Cell retval;\n\n  panic_unless (nd == 1 || nd == 2);\n  panic_unless (a.ndims () == 2);\n\n  if (mat2cell_mismatch (a.dims (), d, nd))\n    return retval;\n\n  octave_idx_type nridx = d[0].numel ();\n  octave_idx_type ncidx = (nd == 1 ? 1 : d[1].numel ());\n  retval.clear (nridx, ncidx);\n\n  int ivec = -1;\n  if (a.rows () > 1 && a.cols () == 1 && ncidx == 1)\n    ivec = 0;\n  else if (a.rows () == 1 && nridx == 1 && nd == 2)\n    ivec = 1;\n\n  if (ivec >= 0)\n    {\n      // Vector split.  Use 1-D indexing.\n      octave_idx_type l = 0;\n      octave_idx_type nidx = (ivec == 0 ? nridx : ncidx);\n      for (octave_idx_type i = 0; i < nidx; i++)\n        {\n          octave_idx_type u = l + d[ivec](i);\n          if constexpr (std::is_same_v<Array2D, Cell>)\n            retval.xelem (i) = Cell (a.index (idx_vector (l, u)));\n          else\n            retval.xelem (i) = a.index (idx_vector (l, u));\n          l = u;\n        }\n    }\n  else\n    {\n      // General 2-D case.  Use 2-D indexing.\n      OCTAVE_LOCAL_BUFFER (idx_vector, ridx, nridx);\n      prepare_idx (ridx, 0, nd, d);\n\n      OCTAVE_LOCAL_BUFFER (idx_vector, cidx, ncidx);\n      prepare_idx (cidx, 1, nd, d);\n\n      for (octave_idx_type j = 0; j < ncidx; j++)\n        for (octave_idx_type i = 0; i < nridx; i++)\n          {\n            octave_quit ();\n\n            if constexpr (std::is_same_v<Array2D, Cell>)\n              retval.xelem (i, j) = Cell (a.index (ridx[i], cidx[j]));\n            else\n              retval.xelem (i, j) = a.index (ridx[i], cidx[j]);\n          }\n    }\n\n  return retval;\n}\n\n// N-D case.  Works for Arrays and octave_map.\n// Uses N-D indexing.\n\ntemplate <typename ArrayND>\nCell\ndo_mat2cell_nd (const ArrayND& a, const Array<octave_idx_type> *d, int nd)\n{\n  Cell retval;\n\n  panic_unless (nd >= 1);\n\n  if (mat2cell_mismatch (a.dims (), d, nd))\n    return retval;\n\n  // For each dimension, count the number of partitions specified.\n  // For example, \"mat2cell (A, [1 1 1], [2 2])\" has 3 partitions on dim1\n  // and 2 partitions on dim2.  Number of dimension (nd) is 2 for this example.\n  dim_vector retdv = dim_vector::alloc (nd);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, nidx, nd);\n  octave_idx_type idxtot = 0;   // Number of idx operations.  5 in example.\n  for (int i = 0; i < nd; i++)\n    {\n      retdv(i) = nidx[i] = d[i].numel ();\n      idxtot += nidx[i];\n    }\n\n  if (nd == 1)\n    retdv(1) = 1;        // All Octave arrays have at least two dimensions.\n  retval.clear (retdv);  // Resize retval based on calculated partitions.\n\n  OCTAVE_LOCAL_BUFFER (idx_vector, xidx, idxtot);\n  OCTAVE_LOCAL_BUFFER (idx_vector *, idx, nd);\n\n  // Loop over all dimensions (specified partitions) and prepare an idx_vector\n  // to retrieve the requested elements.  The partitions are specified in\n  // input parameter 'd' which is an Array of octave_idx_type.  In the example,\n  // d[0] = [1 1 1].\n  idxtot = 0;\n  for (int i = 0; i < nd; i++)\n    {\n      idx[i] = xidx + idxtot;\n      prepare_idx (idx[i], i, nd, d);\n      idxtot += nidx[i];\n    }\n\n  OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ridx, nd, 0);\n  // Declare array of index vectors which will perform indexing.\n  // Initialize to magic colon (':') so that dimensions that are not actually\n  // specified will be collapsed.\n  Array<idx_vector> ra_idx (dim_vector (1, std::max (nd, a.ndims ())),\n                            idx_vector::colon);\n\n  const octave_idx_type retnumel = retval.numel ();\n  for (octave_idx_type j = 0; j < retnumel; j++)\n    {\n      octave_quit ();\n\n      // Copy prepared indices for this iteration to ra_idx.\n      for (int i = 0; i < nd; i++)\n        ra_idx.xelem (i) = idx[i][ridx[i]];\n\n      // Perform indexing operation and store in output retval.\n      if constexpr (std::is_same_v<ArrayND, Cell>)\n        retval.xelem (j) = Cell (a.index (ra_idx));\n      else\n        retval.xelem (j) = a.index (ra_idx);\n\n      // DO NOT increment on last loop because it will overflow past\n      // declared size of ridx (bug #63682).\n      if (j < (retnumel - 1))\n        retdv.increment_index (ridx);\n    }\n\n  return retval;\n}\n\n// Dispatcher.\ntemplate <typename ArrayND>\nCell\ndo_mat2cell (const ArrayND& a, const Array<octave_idx_type> *d, int nd)\n{\n  if (a.ndims () == 2 && nd <= 2)\n    return do_mat2cell_2d (a, d, nd);\n  else\n    return do_mat2cell_nd (a, d, nd);\n}\n\n// General case.  Works for any class supporting do_index_op.\n// Uses N-D indexing.\n\nCell\ndo_mat2cell (octave_value& a, const Array<octave_idx_type> *d, int nd)\n{\n  Cell retval;\n\n  panic_unless (nd >= 1);\n\n  if (mat2cell_mismatch (a.dims (), d, nd))\n    return retval;\n\n  dim_vector rdv = dim_vector::alloc (nd);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, nidx, nd);\n  octave_idx_type idxtot = 0;\n  for (int i = 0; i < nd; i++)\n    {\n      rdv(i) = nidx[i] = d[i].numel ();\n      idxtot += nidx[i];\n    }\n\n  retval.clear (rdv);\n\n  OCTAVE_LOCAL_BUFFER (octave_value, xidx, idxtot);\n  OCTAVE_LOCAL_BUFFER (octave_value *, idx, nd);\n\n  idxtot = 0;\n  for (int i = 0; i < nd; i++)\n    {\n      idx[i] = xidx + idxtot;\n      prepare_idx (idx[i], i, nd, d);\n      idxtot += nidx[i];\n    }\n\n  OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ridx, nd, 0);\n  octave_value_list ra_idx (std::max (nd, a.ndims ()),\n                            octave_value::magic_colon_t);\n\n  for (octave_idx_type j = 0; j < retval.numel (); j++)\n    {\n      octave_quit ();\n\n      for (int i = 0; i < nd; i++)\n        ra_idx(i) = idx[i][ridx[i]];\n\n      retval.xelem (j) = a.index_op (ra_idx);\n\n      rdv.increment_index (ridx);\n    }\n\n  return retval;\n}\n\nDEFUN (mat2cell, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} mat2cell (@var{A}, @var{dim1}, @var{dim2}, @dots{}, @var{dimi}, @dots{}, @var{dimn})\n@deftypefnx {} {@var{C} =} mat2cell (@var{A}, @var{rowdim})\nConvert the matrix @var{A} to a cell array @var{C}.\n\nEach dimension argument (@var{dim1}, @var{dim2}, etc.@:) is a vector of\nintegers which specifies how to divide that dimension's elements amongst the\nnew elements in the output @var{C}.  The number of elements in the @var{i}-th\ndimension is @code{size (@var{A}, @var{i})}.  Because all elements in @var{A}\nmust be partitioned, there is a requirement that @code{sum (@var{dimi}) == size\n(@var{A}, i)}.  The size of the output cell @var{C} is numel (@var{dim1}) x\nnumel (@var{dim2}) x @dots{} x numel (@var{dimn}).\n\nGiven a single dimensional argument, @var{rowdim}, the output is divided into\nrows as specified.  All other dimensions are not divided and thus all\ncolumns (dim 2), pages (dim 3), etc.@: appear in each output element.\n\nExamples\n\n@example\nx = reshape (1:12, [3, 4])'\n@xresult{}\n    1    2    3\n    4    5    6\n    7    8    9\n   10   11   12\n\n@group\n## The 4 rows (dim1) are divided in to two cell elements\n## with 2 rows each.\n## The 3 cols (dim2) are divided in to three cell elements\n## with 1 col each.\nmat2cell (x, [2,2], [1,1,1])\n@xresult{}\n@{\n  [1,1] =\n\n     1\n     4\n\n  [2,1] =\n\n      7\n     10\n\n  [1,2] =\n\n     2\n     5\n\n  [2,2] =\n      8\n     11\n\n  [1,3] =\n\n     3\n     6\n\n  [2,3] =\n      9\n     12\n@}\n@end group\n\n@group\n## The 4 rows (dim1) are divided in to two cell elements\n## with a 3/1 split.\n## All columns appear in each output element.\nmat2cell (x, [3,1])\n@xresult{}\n@{\n  [1,1] =\n\n     1   2   3\n     4   5   6\n     7   8   9\n\n  [2,1] =\n\n     10   11   12\n@}\n@end group\n@end example\n\n@seealso{num2cell, cell2mat}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  octave_value retval;\n\n  // Prepare indices.\n  OCTAVE_LOCAL_BUFFER (Array<octave_idx_type>, d, nargin-1);\n\n  for (int i = 1; i < nargin; i++)\n    d[i-1] = args(i).octave_idx_type_vector_value (true);\n\n  octave_value a = args(0);\n  bool sparse = a.issparse ();\n  if (sparse && nargin > 3)\n    error (\"mat2cell: sparse arguments only support 2-D indexing\");\n\n  switch (a.builtin_type ())\n    {\n    case btyp_double:\n      {\n        if (sparse)\n          retval = do_mat2cell_2d (a.sparse_matrix_value (), d, nargin-1);\n        else\n          retval = do_mat2cell (a.array_value (), d, nargin - 1);\n      }\n      break;\n\n    case btyp_complex:\n      {\n        if (sparse)\n          retval = do_mat2cell_2d (a.sparse_complex_matrix_value (), d,\n                                   nargin-1);\n        else\n          retval = do_mat2cell (a.complex_array_value (), d, nargin - 1);\n      }\n      break;\n\n#define BTYP_BRANCH(X, Y)                                       \\\n      case btyp_ ## X:                                          \\\n        retval = do_mat2cell (a.Y ## _value (), d, nargin - 1); \\\n        break\n\n      BTYP_BRANCH (float, float_array);\n      BTYP_BRANCH (float_complex, float_complex_array);\n      BTYP_BRANCH (bool, bool_array);\n      BTYP_BRANCH (char, char_array);\n\n      BTYP_BRANCH (int8,  int8_array);\n      BTYP_BRANCH (int16, int16_array);\n      BTYP_BRANCH (int32, int32_array);\n      BTYP_BRANCH (int64, int64_array);\n      BTYP_BRANCH (uint8,  uint8_array);\n      BTYP_BRANCH (uint16, uint16_array);\n      BTYP_BRANCH (uint32, uint32_array);\n      BTYP_BRANCH (uint64, uint64_array);\n\n      BTYP_BRANCH (cell, cell);\n      BTYP_BRANCH (struct, map);\n\n#undef BTYP_BRANCH\n\n    case btyp_func_handle:\n      err_wrong_type_arg (\"mat2cell\", a);\n      break;\n\n    default:\n      retval = do_mat2cell (a, d, nargin-1);\n      break;\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! x = reshape (1:20, 5, 4);\n%! c = mat2cell (x, [3,2], [3,1]);\n%! assert (c, {[1,6,11;2,7,12;3,8,13],[16;17;18];[4,9,14;5,10,15],[19;20]});\n\n%!test\n%! x = \"abcdefghij\";\n%! c = mat2cell (x, 1, [0,4,2,0,4,0]);\n%! empty1by0str = resize (\"\", 1, 0);\n%! assert (c, {empty1by0str,\"abcd\",\"ef\",empty1by0str,\"ghij\",empty1by0str});\n\n## Omitted input for trailing dimensions means not splitting on them.\n%!test <*63682>\n%! x = reshape (1:16, 4, 2, 2);\n%! c1 = mat2cell (x, [2, 2], 2, 2);\n%! c2 = mat2cell (x, [2, 2]);\n%! assert (c1, c2);\n%! assert (c1, {cat(3, [1,5;2,6], [9,13;10,14]); ...\n%!              cat(3, [3,7;4,8], [11,15;12,16])});\n*/\n\n// FIXME: it would be nice to allow ranges being handled without a conversion.\ntemplate <typename NDA>\nstatic Cell\ndo_cellslices_nda (const NDA& array,\n                   const Array<octave_idx_type>& lb,\n                   const Array<octave_idx_type>& ub,\n                   int dim = -1)\n{\n  octave_idx_type n = lb.numel ();\n  Cell retval (1, n);\n  if (array.isvector () && (dim == -1\n                            || (dim == 0 && array.columns () == 1)\n                            || (dim == 1 && array.rows () == 1)))\n    {\n      for (octave_idx_type i = 0; i < n; i++)\n        retval.xelem (i) = array.index (idx_vector (lb(i) - 1, ub(i)));\n    }\n  else\n    {\n      const dim_vector dv = array.dims ();\n      int ndims = dv.ndims ();\n      if (dim < 0)\n        dim = dv.first_non_singleton ();\n      ndims = std::max (ndims, dim + 1);\n\n      Array<idx_vector> idx (dim_vector (ndims, 1), idx_vector::colon);\n\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          idx(dim) = idx_vector (lb(i) - 1, ub(i));\n          retval.xelem (i) = array.index (idx);\n        }\n    }\n\n  return retval;\n}\n\nDEFUN (cellslices, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{sl} =} cellslices (@var{x}, @var{lb}, @var{ub}, @var{dim})\nGiven an array @var{x}, this function produces a cell array of slices from\nthe array determined by the index vectors @var{lb}, @var{ub}, for lower and\nupper bounds, respectively.\n\nIn other words, it is equivalent to the following code:\n\n@example\n@group\nn = length (lb);\nsl = cell (1, n);\nfor i = 1:length (lb)\n  sl@{i@} = x(:,@dots{},lb(i):ub(i),@dots{},:);\nendfor\n@end group\n@end example\n\nThe position of the index is determined by @var{dim}.  If not specified,\nslicing is done along the first non-singleton dimension.\n@seealso{cell2mat, cellindexmat, cellfun}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 3 || nargin > 4)\n    print_usage ();\n\n  octave_value x = args(0);\n  Array<octave_idx_type> lb = args(1).octave_idx_type_vector_value ();\n  Array<octave_idx_type> ub = args(2).octave_idx_type_vector_value ();\n  int dim = -1;\n  if (nargin == 4)\n    {\n      dim = args(3).int_value () - 1;\n      if (dim < 0)\n        error (\"cellslices: DIM must be a valid dimension\");\n    }\n\n  if (lb.numel () != ub.numel ())\n    error (\"cellslices: the lengths of LB and UB must match\");\n\n  Cell retcell;\n  if (! x.issparse () && x.is_matrix_type ())\n    {\n      // specialize for some dense arrays.\n      if (x.islogical ())\n        retcell = do_cellslices_nda (x.bool_array_value (),\n                                     lb, ub, dim);\n      else if (x.is_char_matrix ())\n        retcell = do_cellslices_nda (x.char_array_value (),\n                                     lb, ub, dim);\n      else if (x.isinteger ())\n        {\n          if (x.is_int8_type ())\n            retcell = do_cellslices_nda (x.int8_array_value (),\n                                         lb, ub, dim);\n          else if (x.is_int16_type ())\n            retcell = do_cellslices_nda (x.int16_array_value (),\n                                         lb, ub, dim);\n          else if (x.is_int32_type ())\n            retcell = do_cellslices_nda (x.int32_array_value (),\n                                         lb, ub, dim);\n          else if (x.is_int64_type ())\n            retcell = do_cellslices_nda (x.int64_array_value (),\n                                         lb, ub, dim);\n          else if (x.is_uint8_type ())\n            retcell = do_cellslices_nda (x.uint8_array_value (),\n                                         lb, ub, dim);\n          else if (x.is_uint16_type ())\n            retcell = do_cellslices_nda (x.uint16_array_value (),\n                                         lb, ub, dim);\n          else if (x.is_uint32_type ())\n            retcell = do_cellslices_nda (x.uint32_array_value (),\n                                         lb, ub, dim);\n          else if (x.is_uint64_type ())\n            retcell = do_cellslices_nda (x.uint64_array_value (),\n                                         lb, ub, dim);\n        }\n      else if (x.iscomplex ())\n        {\n          if (x.is_single_type ())\n            retcell = do_cellslices_nda (x.float_complex_array_value (),\n                                         lb, ub, dim);\n          else\n            retcell = do_cellslices_nda (x.complex_array_value (),\n                                         lb, ub, dim);\n        }\n      else\n        {\n          if (x.is_single_type ())\n            retcell = do_cellslices_nda (x.float_array_value (),\n                                         lb, ub, dim);\n          else\n            retcell = do_cellslices_nda (x.array_value (),\n                                         lb, ub, dim);\n        }\n    }\n  else\n    {\n      // generic code.\n      octave_idx_type n = lb.numel ();\n      retcell = Cell (1, n);\n      const dim_vector dv = x.dims ();\n      int ndims = dv.ndims ();\n      if (dim < 0)\n        dim = dv.first_non_singleton ();\n      ndims = std::max (ndims, dim + 1);\n      octave_value_list idx (ndims, octave_value::magic_colon_t);\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          idx(dim) = range<double> (lb(i), ub(i));\n          retcell.xelem (i) = x.index_op (idx);\n        }\n    }\n\n  return ovl (retcell);\n}\n\n/*\n%!test\n%! m = [1, 2, 3, 4; 5, 6, 7, 8; 9, 10, 11, 12];\n%! c = cellslices (m, [1, 2], [2, 3], 2);\n%! assert (c, {[1, 2; 5, 6; 9, 10], [2, 3; 6, 7; 10, 11]});\n*/\n\nDEFUN (cellindexmat, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} cellindexmat (@var{x}, @var{varargin})\nPerform indexing of matrices in a cell array.\n\nGiven a cell array of matrices @var{x}, this function computes\n\n@example\n@group\nY = cell (size (X));\nfor i = 1:numel (X)\n  Y@{i@} = X@{i@}(varargin@{1@}, varargin@{2@}, @dots{}, varargin@{N@});\nendfor\n@end group\n@end example\n\nThe indexing arguments may be scalar (@code{2}), arrays (@code{[1, 3]}),\nranges (@code{1:3}), or the colon operator (@qcode{\":\"}).  However, the\nindexing keyword @code{end} is not available.\n@seealso{cellslices, cellfun}\n@end deftypefn */)\n{\n  if (args.length () == 0)\n    print_usage ();\n\n  const Cell x = args(0).xcell_value (\"cellindexmat: X must be a cell\");\n\n  Cell y (x.dims ());\n  octave_idx_type nel = x.numel ();\n  octave_value_list idx = args.slice (1, args.length () - 1);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      octave_quit ();\n\n      octave_value tmp = x(i);\n\n      y.xelem (i) = tmp.index_op (idx);\n    }\n\n  return octave_value (y);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/find.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Find at most N_TO_FIND nonzero elements in NDA.  Search forward if\n// DIRECTION is 1, backward if it is -1.  NARGOUT is the number of\n// output arguments.  If N_TO_FIND is -1, find all nonzero elements.\n\ntemplate <typename T>\noctave_value_list\nfind_nonzero_elem_idx (const Array<T>& nda, int nargout,\n                       octave_idx_type n_to_find, int direction)\n{\n  octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ());\n\n  Array<octave_idx_type> idx;\n  if (n_to_find >= 0)\n    idx = nda.find (n_to_find, direction == -1);\n  else\n    idx = nda.find ();\n\n  // The maximum element is always at the end.\n  octave_idx_type iext = (idx.isempty () ? 0\n                          : idx.xelem (idx.numel () - 1) + 1);\n\n  switch (nargout)\n    {\n    default:\n    case 3:\n      retval(2) = Array<T> (nda.index (idx_vector (idx)));\n      OCTAVE_FALLTHROUGH;\n\n    case 2:\n      {\n        Array<octave_idx_type> jdx (idx.dims ());\n        octave_idx_type n = idx.numel ();\n        octave_idx_type nr = nda.rows ();\n        for (octave_idx_type i = 0; i < n; i++)\n          {\n            jdx.xelem (i) = idx.xelem (i) / nr;\n            idx.xelem (i) %= nr;\n          }\n        iext = -1;\n        retval(1) = idx_vector (jdx, -1);\n      }\n      OCTAVE_FALLTHROUGH;\n\n    case 1:\n    case 0:\n      retval(0) = idx_vector (idx, iext);\n      break;\n    }\n\n  return retval;\n}\n\ntemplate <typename T>\noctave_value_list\nfind_nonzero_elem_idx (const DiagArray2<T>& v, int nargout,\n                       octave_idx_type n_to_find, int direction)\n{\n  octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ());\n\n  // get array with relevant elements (i.e., the matrix diagonal)\n  Array<T> nda = v.extract_diag ();\n\n  Array<octave_idx_type> idx;\n  if (n_to_find >= 0)\n    idx = nda.find (n_to_find, direction == -1);\n  else\n    idx = nda.find ();\n\n  // The maximum element is always at the end.\n  octave_idx_type iext = idx.isempty () ? 0 : idx.xelem (idx.numel () - 1) + 1;\n  switch (nargout)\n    {\n    default:\n    case 3:\n      retval(2) = Array<T> (nda.index (idx_vector (idx)));\n      OCTAVE_FALLTHROUGH;\n\n    case 2:\n      {\n        Array<octave_idx_type> jdx (idx.dims ());\n        octave_idx_type n = idx.numel ();\n        for (octave_idx_type i = 0; i < n; i++)\n          jdx.xelem(i) = idx.xelem(i);\n        iext = -1;\n        retval(1) = idx_vector (jdx, iext);\n        retval(0) = idx_vector (idx, iext);\n        break;\n      }\n\n    case 1:\n    case 0:\n      {\n        octave_idx_type n = idx.numel ();\n        octave_idx_type nr = v.rows ();\n        for (octave_idx_type i = 0; i < n; i++)\n          idx.xelem(i) = idx.xelem(i) * (nr + 1);\n        retval(0) = idx_vector (idx, iext);\n        break;\n      }\n    }\n\n  return retval;\n}\n\ntemplate <typename T>\noctave_value_list\nfind_nonzero_elem_idx (const Sparse<T>& v, int nargout,\n                       octave_idx_type n_to_find, int direction)\n{\n  nargout = std::min (nargout, 5);\n  octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ());\n\n  octave_idx_type nr = v.rows ();\n  octave_idx_type nc = v.cols ();\n  octave_idx_type nz = v.nnz ();\n\n  // Search in the default range.\n  octave_idx_type start_nc = -1;\n  octave_idx_type end_nc = -1;\n  octave_idx_type count;\n\n  // Search for the range to search\n  if (n_to_find < 0)\n    {\n      start_nc = 0;\n      end_nc = nc;\n      n_to_find = nz;\n    }\n  else if (direction > 0)\n    {\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          if (v.cidx (j) == 0 && v.cidx (j+1) != 0)\n            start_nc = j;\n          if (v.cidx (j+1) >= n_to_find)\n            {\n              end_nc = j + 1;\n              break;\n            }\n        }\n    }\n  else\n    {\n      for (octave_idx_type j = nc; j > 0; j--)\n        {\n          octave_quit ();\n\n          if (v.cidx (j) == nz && v.cidx (j-1) != nz)\n            end_nc = j;\n          if (nz - v.cidx (j-1) >= n_to_find)\n            {\n              start_nc = j - 1;\n              break;\n            }\n        }\n    }\n\n  count = (n_to_find > v.cidx (end_nc) - v.cidx (start_nc) ?\n           v.cidx (end_nc) - v.cidx (start_nc) : n_to_find);\n\n  octave_idx_type result_nr;\n  octave_idx_type result_nc;\n\n  // Default case is to return a column vector, however, if the original\n  // argument was a row vector, then force return of a row vector.\n  if (nr == 1)\n    {\n      result_nr = 1;\n      result_nc = count;\n    }\n  else\n    {\n      result_nr = count;\n      result_nc = 1;\n    }\n\n  Matrix idx (result_nr, result_nc);\n\n  Matrix i_idx (result_nr, result_nc);\n  Matrix j_idx (result_nr, result_nc);\n\n  Array<T> val (dim_vector (result_nr, result_nc));\n\n  if (count > 0)\n    {\n      // Search for elements to return.  Only search the region where there\n      // are elements to be found using the count that we want to find.\n      for (octave_idx_type j = start_nc, cx = 0; j < end_nc; j++)\n        for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++)\n          {\n            octave_quit ();\n\n            if (direction < 0 && i < nz - count)\n              continue;\n            i_idx(cx) = static_cast<double> (v.ridx (i) + 1);\n            j_idx(cx) = static_cast<double> (j + 1);\n            idx(cx) = j * nr + v.ridx (i) + 1;\n            val(cx) = v.data(i);\n            cx++;\n            if (cx == count)\n              break;\n          }\n    }\n  else\n    {\n      // No items found.  Fixup return dimensions for Matlab compatibility.\n      // The behavior to match is documented in Array.cc (Array<T>::find).\n      if ((nr == 0 && nc == 0) || (nr == 1 && nc == 1))\n        {\n          idx.resize (0, 0);\n\n          i_idx.resize (0, 0);\n          j_idx.resize (0, 0);\n\n          val.resize (dim_vector (0, 0));\n        }\n    }\n\n  switch (nargout)\n    {\n    case 0:\n    case 1:\n      retval(0) = idx;\n      break;\n\n    case 5:\n      retval(4) = nc;\n      OCTAVE_FALLTHROUGH;\n\n    case 4:\n      retval(3) = nr;\n      OCTAVE_FALLTHROUGH;\n\n    case 3:\n      retval(2) = val;\n      OCTAVE_FALLTHROUGH;\n\n    case 2:\n      retval(1) = j_idx;\n      retval(0) = i_idx;\n    }\n\n  return retval;\n}\n\noctave_value_list\nfind_nonzero_elem_idx (const PermMatrix& v, int nargout,\n                       octave_idx_type n_to_find, int direction)\n{\n  // There are far fewer special cases to handle for a PermMatrix.\n  nargout = std::min (nargout, 5);\n  octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ());\n\n  octave_idx_type nr = v.rows ();\n  octave_idx_type nc = v.cols ();\n  octave_idx_type start_nc, count;\n\n  // Determine the range to search.\n  if (n_to_find < 0 || n_to_find >= nc)\n    {\n      start_nc = 0;\n      count = nc;\n    }\n  else if (direction > 0)\n    {\n      start_nc = 0;\n      count = n_to_find;\n    }\n  else\n    {\n      start_nc = nc - n_to_find;\n      count = n_to_find;\n    }\n\n  Matrix idx (count, 1);\n  Matrix i_idx (count, 1);\n  Matrix j_idx (count, 1);\n  // Every value is 1.\n  Array<double> val (dim_vector (count, 1), 1.0);\n\n  if (count > 0)\n    {\n      const Array<octave_idx_type>& p = v.col_perm_vec ();\n      for (octave_idx_type k = 0; k < count; k++)\n        {\n          octave_quit ();\n\n          const octave_idx_type j = start_nc + k;\n          const octave_idx_type i = p(j);\n          i_idx(k) = static_cast<double> (1+i);\n          j_idx(k) = static_cast<double> (1+j);\n          idx(k) = j * nc + i + 1;\n        }\n    }\n  else\n    {\n      // FIXME: Is this case even possible?  A scalar permutation matrix seems\n      // to devolve to a scalar full matrix, at least from the Octave command\n      // line.  Perhaps this function could be called internally from C++ with\n      // such a matrix.\n      // No items found.  Fixup return dimensions for Matlab compatibility.\n      // The behavior to match is documented in Array.cc (Array<T>::find).\n      if ((nr == 0 && nc == 0) || (nr == 1 && nc == 1))\n        {\n          idx.resize (0, 0);\n\n          i_idx.resize (0, 0);\n          j_idx.resize (0, 0);\n\n          val.resize (dim_vector (0, 0));\n        }\n    }\n\n  switch (nargout)\n    {\n    case 0:\n    case 1:\n      retval(0) = idx;\n      break;\n\n    case 5:\n      retval(4) = nc;\n      OCTAVE_FALLTHROUGH;\n\n    case 4:\n      retval(3) = nc;\n      OCTAVE_FALLTHROUGH;\n\n    case 3:\n      retval(2) = val;\n      OCTAVE_FALLTHROUGH;\n\n    case 2:\n      retval(1) = j_idx;\n      retval(0) = i_idx;\n    }\n\n  return retval;\n}\n\nDEFUN (find, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{idx} =} find (@var{x})\n@deftypefnx {} {@var{idx} =} find (@var{x}, @var{n})\n@deftypefnx {} {@var{idx} =} find (@var{x}, @var{n}, @var{direction})\n@deftypefnx {} {[i, j] =} find (@dots{})\n@deftypefnx {} {[i, j, v] =} find (@dots{})\nReturn a vector of indices of nonzero elements of a matrix, as a row if\n@var{x} is a row vector or as a column otherwise.\n\nTo obtain a single index for each matrix element, Octave pretends that the\ncolumns of a matrix form one long vector (like Fortran arrays are stored).\nFor example:\n\n@example\n@group\nfind (eye (2))\n  @xresult{} [ 1; 4 ]\n@end group\n@end example\n\nIf two inputs are given, @var{n} indicates the maximum number of elements to\nfind from the beginning of the matrix or vector.\n\nIf three inputs are given, @var{direction} should be one of\n@qcode{\"first\"} or @qcode{\"last\"}, requesting only the first or last\n@var{n} indices, respectively.  However, the indices are always returned in\nascending order.\n\nIf two outputs are requested, @code{find} returns the row and column\nindices of nonzero elements of a matrix.  For example:\n\n@example\n@group\n[i, j] = find (2 * eye (2))\n    @xresult{} i = [ 1; 2 ]\n    @xresult{} j = [ 1; 2 ]\n@end group\n@end example\n\nIf three outputs are requested, @code{find} also returns a vector\ncontaining the nonzero values.  For example:\n\n@example\n@group\n[i, j, v] = find (3 * eye (2))\n       @xresult{} i = [ 1; 2 ]\n       @xresult{} j = [ 1; 2 ]\n       @xresult{} v = [ 3; 3 ]\n@end group\n@end example\n\nIf @var{x} is a multi-dimensional array of size m x n x p x @dots{}, @var{j}\ncontains the column locations as if @var{x} was flattened into a\ntwo-dimensional matrix of size m x (n + p + @dots{}).\n\nNote that this function is particularly useful for sparse matrices, as\nit extracts the nonzero elements as vectors, which can then be used to\ncreate the original matrix.  For example:\n\n@example\n@group\nsz = size (a);\n[i, j, v] = find (a);\nb = sparse (i, j, v, sz(1), sz(2));\n@end group\n@end example\n@seealso{nonzeros}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  // Setup the default options.\n  octave_idx_type n_to_find = -1;\n  if (nargin > 1)\n    {\n      double val = args(1).xscalar_value (\"find: N must be an integer\");\n\n      if (val < 0 || (! math::isinf (val)\n                      && val != math::fix (val)))\n        error (\"find: N must be a non-negative integer\");\n      else if (! math::isinf (val))\n        n_to_find = val;\n    }\n\n  // Direction to do the searching (1 == forward, -1 == reverse).\n  int direction = 1;\n  if (nargin > 2)\n    {\n      std::string s_arg = args(2).string_value ();\n\n      if (s_arg == \"first\")\n        direction = 1;\n      else if (s_arg == \"last\")\n        direction = -1;\n      else\n        error (R\"(find: DIRECTION must be \"first\" or \"last\")\");\n    }\n\n  octave_value_list retval;\n\n  octave_value arg = args(0);\n\n  if (arg.islogical ())\n    {\n      if (arg.issparse ())\n        {\n          SparseBoolMatrix v = arg.sparse_bool_matrix_value ();\n\n          retval = find_nonzero_elem_idx (v, nargout, n_to_find, direction);\n        }\n      else if (nargout <= 1 && n_to_find == -1 && direction == 1)\n        {\n          // This case is equivalent to extracting indices from a logical\n          // matrix.  Try to reuse the possibly cached index vector.\n\n          // No need to catch index_exception, since arg is bool.\n          // Out-of-range errors have already set pos, and will be\n          // caught later.\n\n          octave_value result = arg.index_vector ().unmask ();\n\n          const dim_vector& dv = result.dims ();\n\n          retval(0) = (dv.all_zero () || dv.isvector ()\n                       ? result : result.reshape (dv.as_column ()));\n        }\n      else\n        {\n          boolNDArray v = arg.bool_array_value ();\n\n          retval = find_nonzero_elem_idx (v, nargout, n_to_find, direction);\n        }\n    }\n  else if (arg.isinteger ())\n    {\n#define DO_INT_BRANCH(INTT)                                             \\\n      else if (arg.is_ ## INTT ## _type ())                             \\\n        {                                                               \\\n          INTT ## NDArray v = arg.INTT ## _array_value ();              \\\n                                                                        \\\n          retval = find_nonzero_elem_idx (v, nargout, n_to_find, direction); \\\n        }\n\n      if (false)\n        ;\n      DO_INT_BRANCH (int8)\n      DO_INT_BRANCH (int16)\n      DO_INT_BRANCH (int32)\n      DO_INT_BRANCH (int64)\n      DO_INT_BRANCH (uint8)\n      DO_INT_BRANCH (uint16)\n      DO_INT_BRANCH (uint32)\n      DO_INT_BRANCH (uint64)\n      else\n        error (\"find: unexpected integer type - please report this bug\");\n    }\n  else if (arg.issparse ())\n    {\n      if (arg.isreal ())\n        {\n          SparseMatrix v = arg.sparse_matrix_value ();\n\n          retval = find_nonzero_elem_idx (v, nargout, n_to_find, direction);\n        }\n      else if (arg.iscomplex ())\n        {\n          SparseComplexMatrix v = arg.sparse_complex_matrix_value ();\n\n          retval = find_nonzero_elem_idx (v, nargout, n_to_find, direction);\n        }\n      else\n        err_wrong_type_arg (\"find\", arg);\n    }\n  else if (arg.is_perm_matrix ())\n    {\n      PermMatrix P = arg.perm_matrix_value ();\n\n      retval = find_nonzero_elem_idx (P, nargout, n_to_find, direction);\n    }\n  else if (arg.is_diag_matrix ())\n    {\n      // diagonal logical matrices are handled above\n      if (arg.is_single_type ())\n        {\n          if (arg.isreal ())\n            {\n              FloatDiagMatrix D = arg.diag_matrix_value ();\n\n              retval = find_nonzero_elem_idx (D, nargout, n_to_find, direction);\n            }\n          else if (arg.iscomplex ())\n            {\n              FloatComplexDiagMatrix D = arg.complex_diag_matrix_value ();\n\n              retval = find_nonzero_elem_idx (D, nargout, n_to_find, direction);\n            }\n        }\n      else if (arg.isreal ())\n        {\n          DiagMatrix D = arg.diag_matrix_value ();\n\n          retval = find_nonzero_elem_idx (D, nargout, n_to_find, direction);\n        }\n      else if (arg.iscomplex ())\n        {\n          ComplexDiagMatrix D = arg.complex_diag_matrix_value ();\n\n          retval = find_nonzero_elem_idx (D, nargout, n_to_find, direction);\n        }\n    }\n  else if (arg.is_string ())\n    {\n      charNDArray chnda = arg.char_array_value ();\n\n      retval = find_nonzero_elem_idx (chnda, nargout, n_to_find, direction);\n    }\n  else if (arg.is_single_type ())\n    {\n      if (arg.isreal ())\n        {\n          FloatNDArray nda = arg.float_array_value ();\n\n          retval = find_nonzero_elem_idx (nda, nargout, n_to_find, direction);\n        }\n      else if (arg.iscomplex ())\n        {\n          FloatComplexNDArray cnda = arg.float_complex_array_value ();\n\n          retval = find_nonzero_elem_idx (cnda, nargout, n_to_find, direction);\n        }\n    }\n  else if (arg.isreal ())\n    {\n      NDArray nda = arg.array_value ();\n\n      retval = find_nonzero_elem_idx (nda, nargout, n_to_find, direction);\n    }\n  else if (arg.iscomplex ())\n    {\n      ComplexNDArray cnda = arg.complex_array_value ();\n\n      retval = find_nonzero_elem_idx (cnda, nargout, n_to_find, direction);\n    }\n  else\n    err_wrong_type_arg (\"find\", arg);\n\n  return retval;\n}\n\n/*\n%!assert (find (char ([0, 97])), 2)\n%!assert (find ([1, 0, 1, 0, 1]), [1, 3, 5])\n%!assert (find ([1; 0; 3; 0; 1]), [1; 3; 5])\n%!assert (find ([0, 0, 2; 0, 3, 0; -1, 0, 0]), [3; 5; 7])\n%!assert (find (diag ([5, 0, 4, 0, 2])), [1; 13; 25])\n%!assert (find (diag ([5, 0, 4, 0, 2], 7, 6)), [1; 17; 33])\n\n%!assert <*53603> (find (ones (1,1,2) > 0), [1;2])\n%!assert <*53603> (find (ones (1,1,1,3) > 0), [1;2;3])\n\n%!test\n%! [i, j, v] = find ([0, 0, 2; 0, 3, 0; -1, 0, 0]);\n%!\n%! assert (i, [3; 2; 1]);\n%! assert (j, [1; 2; 3]);\n%! assert (v, [-1; 3; 2]);\n\n%!assert (find (single ([1, 0, 1, 0, 1])), [1, 3, 5])\n%!assert (find (single ([1; 0; 3; 0; 1])), [1; 3; 5])\n%!assert (find (single ([0, 0, 2; 0, 3, 0; -1, 0, 0])), [3; 5; 7])\n\n%!test\n%! [i, j, v] = find (single ([0, 0, 2; 0, 3, 0; -1, 0, 0]));\n%!\n%! assert (i, [3; 2; 1]);\n%! assert (j, [1; 2; 3]);\n%! assert (v, single ([-1; 3; 2]));\n\n%!test\n%! pcol = [5 1 4 3 2];\n%! P = eye (5) (:, pcol);\n%! [i, j, v] = find (P);\n%! [ifull, jfull, vfull] = find (full (P));\n%! assert (i, ifull);\n%! assert (j, jfull);\n%! assert (all (v == 1));\n\n%!test\n%! prow = [5 1 4 3 2];\n%! P = eye (5) (prow, :);\n%! [i, j, v] = find (P);\n%! [ifull, jfull, vfull] = find (full (P));\n%! assert (i, ifull);\n%! assert (j, jfull);\n%! assert (all (v == 1));\n\n%!test\n%! D = diag ([5, 0, 4, 0, 2]);\n%! [i, j] = find (D);\n%! [ifull, jfull] = find (full (D));\n%! assert (i, ifull);\n%! assert (j, jfull);\n\n%!test\n%! D = diag ([5, 0, 4, 0, 2], 6, 5);\n%! [i, j, v] = find (D);\n%! [ifull, jfull, vfull] = find (full (D));\n%! assert (i, ifull);\n%! assert (j, jfull);\n%! assert (v, vfull);\n\n%!test <*61986>\n%! P = cat (3, eye(3), eye(3));\n%! loc = find (P);\n%! [i, j, v] = find(P);\n%! assert (loc, [1, 5, 9, 10, 14, 18]');\n%! assert (i, [1, 2, 3, 1, 2, 3]');\n%! assert (j, [1, 2, 3, 4, 5, 6]');\n%! assert (v, [1, 1, 1, 1, 1, 1]');\n\n%!assert <*53655> (find (false), zeros (0, 0))\n%!assert <*53655> (find ([false, false]), zeros (1, 0))\n%!assert <*53655> (find ([false; false]), zeros (0, 1))\n%!assert <*53655> (find ([false, false; false, false]), zeros (0, 1))\n\n%!assert (find ([2 0 1 0 5 0], 1), 1)\n%!assert (find ([2 0 1 0 5 0], 2, \"last\"), [3, 5])\n\n%!assert (find ([2 0 1 0 5 0], Inf), [1, 3, 5])\n%!assert (find ([2 0 1 0 5 0], Inf, \"last\"), [1, 3, 5])\n\n%!error find ()\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/jsondecode.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-string.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\n#if defined (HAVE_RAPIDJSON)\n#  include <rapidjson/document.h>\n#  include <rapidjson/error/en.h>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_RAPIDJSON)\n\nstatic octave_value\ndecode (const rapidjson::Value& val,\n        const octave::make_valid_name_options *options);\n\n//! Decodes a numerical JSON value into a scalar number.\n//!\n//! @param val JSON value that is guaranteed to be a numerical value.\n//!\n//! @return @ref octave_value that contains the numerical value of @p val.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"123\");\n//! octave_value num = decode_number (d);\n//! @endcode\n\nstatic octave_value\ndecode_number (const rapidjson::Value& val)\n{\n  if (val.IsUint ())\n    return octave_value (val.GetUint ());\n  else if (val.IsInt ())\n    return octave_value (val.GetInt ());\n  else if (val.IsUint64 ())\n    return octave_value (val.GetUint64 ());\n  else if (val.IsInt64 ())\n    return octave_value (val.GetInt64 ());\n  else if (val.IsDouble ())\n    return octave_value (val.GetDouble ());\n  else\n    error (\"jsondecode: unidentified type\");\n}\n\n//! Decodes a JSON object into a scalar struct.\n//!\n//! @param val JSON value that is guaranteed to be a JSON object.\n//! @param options @c ReplacementStyle and @c Prefix options with their values.\n//!\n//! @return @ref octave_value that contains the equivalent scalar struct of @p val.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"{\\\"a\\\": 1, \\\"b\\\": 2}\");\n//! octave_value struct = decode_object (d, octave_value_list ());\n//! @endcode\n\nstatic octave_value\ndecode_object (const rapidjson::Value& val,\n               const octave::make_valid_name_options *options)\n{\n  octave_scalar_map retval;\n\n  for (const auto& pair : val.GetObject ())\n    {\n      // Validator function \"matlab.lang.makeValidName\" to guarantee legitimate\n      // variable name.\n      std::string varname = pair.name.GetString ();\n      if (options != nullptr)\n        octave::make_valid_name (varname, *options);\n      retval.assign (varname, decode (pair.value, options));\n    }\n\n  return retval;\n}\n\n//! Decodes a JSON array that contains only numerical or null values\n//! into an NDArray.\n//!\n//! @param val JSON value that is guaranteed to be a numeric array.\n//!\n//! @return @ref octave_value that contains the equivalent NDArray of @p val.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[1, 2, 3, 4]\");\n//! octave_value numeric_array = decode_numeric_array (d);\n//! @endcode\n\nstatic octave_value\ndecode_numeric_array (const rapidjson::Value& val)\n{\n  NDArray retval (dim_vector (val.Size (), 1));\n  octave_idx_type index = 0;\n  for (const auto& elem : val.GetArray ())\n    retval(index++) = elem.IsNull () ? octave_NaN\n                      : decode_number (elem).double_value ();\n  return retval;\n}\n\n//! Decodes a JSON array that contains only boolean values into a boolNDArray.\n//!\n//! @param val JSON value that is guaranteed to be a boolean array.\n//!\n//! @return @ref octave_value that contains the equivalent boolNDArray of @p val.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[true, false, true]\");\n//! octave_value boolean_array = decode_boolean_array (d);\n//! @endcode\n\nstatic octave_value\ndecode_boolean_array (const rapidjson::Value& val)\n{\n  boolNDArray retval (dim_vector (val.Size (), 1));\n  octave_idx_type index = 0;\n  for (const auto& elem : val.GetArray ())\n    retval(index++) = elem.GetBool ();\n  return retval;\n}\n\n//! Decodes a JSON array that contains different types\n//! or string values only into a Cell.\n//!\n//! @param val JSON value that is guaranteed to be a mixed or string array.\n//! @param options @c ReplacementStyle and @c Prefix options with their values.\n//!\n//! @return @ref octave_value that contains the equivalent Cell of @p val.\n//!\n//! @b Example (decoding a string array):\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[\\\"foo\\\", \\\"bar\\\", \\\"baz\\\"]\");\n//! octave_value cell = decode_string_and_mixed_array (d, octave_value_list ());\n//! @endcode\n//!\n//! @b Example (decoding a mixed array):\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[\\\"foo\\\", 123, true]\");\n//! octave_value cell = decode_string_and_mixed_array (d, octave_value_list ());\n//! @endcode\n\nstatic octave_value\ndecode_string_and_mixed_array (const rapidjson::Value& val,\n                               const octave::make_valid_name_options *options)\n{\n  Cell retval (dim_vector (val.Size (), 1));\n  octave_idx_type index = 0;\n  for (const auto& elem : val.GetArray ())\n    retval(index++) = decode (elem, options);\n  return retval;\n}\n\n//! Decodes a JSON array that contains only objects into a Cell or struct array\n//! depending on the similarity of the objects' keys.\n//!\n//! @param val JSON value that is guaranteed to be an object array.\n//! @param options @c ReplacementStyle and @c Prefix options with their values.\n//!\n//! @return @ref octave_value that contains the equivalent Cell\n//! or struct array of @p val.\n//!\n//! @b Example (returns a struct array):\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[{\\\"a\\\":1,\\\"b\\\":2},{\\\"a\\\":3,\\\"b\\\":4}]\");\n//! octave_value object_array = decode_object_array (d, octave_value_list ());\n//! @endcode\n//!\n//! @b Example (returns a Cell):\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[{\\\"a\\\":1,\\\"b\\\":2},{\\\"b\\\":3,\\\"a\\\":4}]\");\n//! octave_value object_array = decode_object_array (d, octave_value_list ());\n//! @endcode\n\nstatic octave_value\ndecode_object_array (const rapidjson::Value& val,\n                     const octave::make_valid_name_options *options)\n{\n  Cell struct_cell = decode_string_and_mixed_array (val, options).cell_value ();\n  string_vector field_names = struct_cell(0).scalar_map_value ().fieldnames ();\n\n  bool same_field_names = true;\n  for (octave_idx_type i = 1; i < struct_cell.numel (); ++i)\n    if (field_names.std_list ()\n        != struct_cell(i).scalar_map_value ().fieldnames ().std_list ())\n      {\n        same_field_names = false;\n        break;\n      }\n\n  if (same_field_names)\n    {\n      octave_map struct_array;\n      const dim_vector& struct_array_dims = dim_vector (struct_cell.numel (), 1);\n\n      if (field_names.numel ())\n        {\n          Cell value (struct_array_dims);\n          for (octave_idx_type i = 0; i < field_names.numel (); ++i)\n            {\n              for (octave_idx_type k = 0; k < struct_cell.numel (); ++k)\n                value(k) = struct_cell(k).scalar_map_value ()\n                           .getfield (field_names(i));\n              struct_array.assign (field_names(i), value);\n            }\n        }\n      else\n        struct_array.resize (struct_array_dims, true);\n\n      return struct_array;\n    }\n  else\n    return struct_cell;\n}\n\n//! Decodes a JSON array that contains only arrays into a Cell or an NDArray\n//! depending on the dimensions and element types of the sub-arrays.\n//!\n//! @param val JSON value that is guaranteed to be an array of arrays.\n//! @param options @c ReplacementStyle and @c Prefix options with their values.\n//!\n//! @return @ref octave_value that contains the equivalent Cell\n//! or NDArray of @p val.\n//!\n//! @b Example (returns an NDArray):\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[[1, 2], [3, 4]]\");\n//! octave_value array = decode_array_of_arrays (d, octave_value_list ());\n//! @endcode\n//!\n//! @b Example (returns a Cell):\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[[1, 2], [3, 4, 5]]\");\n//! octave_value cell = decode_array_of_arrays (d, octave_value_list ());\n//! @endcode\n\nstatic octave_value\ndecode_array_of_arrays (const rapidjson::Value& val,\n                        const octave::make_valid_name_options *options)\n{\n  // Some arrays should be decoded as NDArrays and others as cell arrays\n  Cell cell = decode_string_and_mixed_array (val, options).cell_value ();\n\n  // Only arrays with sub-arrays of booleans and numericals will return NDArray\n  bool is_bool = cell(0).is_bool_matrix ();\n  bool is_struct = cell(0).isstruct ();\n  string_vector field_names = is_struct ? cell(0).map_value ().fieldnames ()\n                              : string_vector ();\n  const dim_vector& sub_array_dims = cell(0).dims ();\n  octave_idx_type sub_array_ndims = cell(0).ndims ();\n  octave_idx_type cell_numel = cell.numel ();\n  for (octave_idx_type i = 0; i < cell_numel; ++i)\n    {\n      // If one element is cell return the cell array as at least one of the\n      // sub-arrays area either an array of: strings, objects or mixed array\n      if (cell(i).iscell ())\n        return cell;\n      // If not the same dim of elements or dim = 0, return cell array\n      if (cell(i).dims () != sub_array_dims || sub_array_dims == dim_vector ())\n        return cell;\n      // If not numeric sub-arrays only or bool sub-arrays only,\n      // return cell array\n      if (cell(i).is_bool_matrix () != is_bool)\n        return cell;\n      // If not struct arrays only, return cell array\n      if (cell(i).isstruct () != is_struct)\n        return cell;\n      // If struct arrays have different fields, return cell array\n      if (is_struct && (field_names.std_list ()\n                        != cell(i).map_value ().fieldnames ().std_list ()))\n        return cell;\n    }\n\n  // Calculate the dims of the output array\n  dim_vector array_dims;\n  array_dims.resize (sub_array_ndims + 1);\n  array_dims(0) = cell_numel;\n  for (auto i = 1; i < sub_array_ndims + 1; i++)\n    array_dims(i) = sub_array_dims(i-1);\n\n  if (is_struct)\n    {\n      octave_map struct_array;\n      array_dims.chop_trailing_singletons ();\n\n      if (field_names.numel ())\n        {\n          Cell value (array_dims);\n          octave_idx_type sub_array_numel = sub_array_dims.numel ();\n\n          for (octave_idx_type j = 0; j < field_names.numel (); ++j)\n            {\n              // Populate the array with specific order to generate\n              // MATLAB-identical output.\n              for (octave_idx_type k = 0; k < cell_numel; ++k)\n                {\n                  Cell sub_array_value = cell(k).map_value ()\n                                         .getfield (field_names(j));\n                  for (octave_idx_type i = 0; i < sub_array_numel; ++i)\n                    value(k + i * cell_numel) = sub_array_value(i);\n                }\n              struct_array.assign (field_names(j), value);\n            }\n        }\n      else\n        struct_array.resize(array_dims, true);\n\n      return struct_array;\n    }\n  else\n    {\n      NDArray array (array_dims);\n\n      // Populate the array with specific order to generate MATLAB-identical\n      // output.\n      octave_idx_type sub_array_numel = array.numel () / cell_numel;\n      for (octave_idx_type k = 0; k < cell_numel; ++k)\n        {\n          NDArray sub_array_value = cell(k).array_value ();\n          for (octave_idx_type i = 0; i < sub_array_numel; ++i)\n            array(k + i * cell_numel) = sub_array_value(i);\n        }\n\n      if (is_bool)\n        return boolNDArray (array);\n      else\n        return array;\n    }\n}\n\n//! Decodes any type of JSON arrays.  This function only serves as an interface\n//! by choosing which function to call from the previous functions.\n//!\n//! @param val JSON value that is guaranteed to be an array.\n//! @param options @c ReplacementStyle and @c Prefix options with their values.\n//!\n//! @return @ref octave_value that contains the output of decoding @p val.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[[1, 2], [3, 4, 5]]\");\n//! octave_value array = decode_array (d, octave_value_list ());\n//! @endcode\n\nstatic octave_value\ndecode_array (const rapidjson::Value& val,\n              const octave::make_valid_name_options *options)\n{\n  // Handle empty arrays\n  if (val.Empty ())\n    return NDArray ();\n\n  // Compare with other elements to know if the array has multiple types\n  rapidjson::Type array_type = val[0].GetType ();\n  // Check if the array is numeric and if it has multiple types\n  bool same_type = true;\n  bool is_numeric = true;\n  for (const auto& elem : val.GetArray ())\n    {\n      rapidjson::Type current_elem_type = elem.GetType ();\n      if (is_numeric && ! (current_elem_type == rapidjson::kNullType\n                           || current_elem_type == rapidjson::kNumberType))\n        is_numeric = false;\n      if (same_type && (current_elem_type != array_type))\n        // RapidJSON doesn't have kBoolean Type it has kTrueType and kFalseType\n        if (! ((current_elem_type == rapidjson::kTrueType\n                && array_type == rapidjson::kFalseType)\n               || (current_elem_type == rapidjson::kFalseType\n                   && array_type == rapidjson::kTrueType)))\n          same_type = false;\n    }\n\n  if (is_numeric)\n    return decode_numeric_array (val);\n\n  if (same_type && (array_type != rapidjson::kStringType))\n    {\n      if (array_type == rapidjson::kTrueType\n          || array_type == rapidjson::kFalseType)\n        return decode_boolean_array (val);\n      else if (array_type == rapidjson::kObjectType)\n        return decode_object_array (val, options);\n      else if (array_type == rapidjson::kArrayType)\n        return decode_array_of_arrays (val, options);\n      else\n        error (\"jsondecode: unidentified type\");\n    }\n  else\n    return decode_string_and_mixed_array (val, options);\n}\n\n//! Decodes any JSON value.  This function only serves as an interface\n//! by choosing which function to call from the previous functions.\n//!\n//! @param val JSON value.\n//! @param options @c ReplacementStyle and @c Prefix options with their values.\n//!\n//! @return @ref octave_value that contains the output of decoding @p val.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! rapidjson::Document d;\n//! d.Parse (\"[{\\\"a\\\":1,\\\"b\\\":2},{\\\"b\\\":3,\\\"a\\\":4}]\");\n//! octave_value value = decode (d, octave_value_list ());\n//! @endcode\n\nstatic octave_value\ndecode (const rapidjson::Value& val,\n        const octave::make_valid_name_options *options)\n{\n  if (val.IsBool ())\n    return val.GetBool ();\n  else if (val.IsNumber ())\n    return decode_number (val);\n  else if (val.IsString ())\n    return val.GetString ();\n  else if (val.IsObject ())\n    return decode_object (val, options);\n  else if (val.IsNull ())\n    return NDArray ();\n  else if (val.IsArray ())\n    return decode_array (val, options);\n  else\n    error (\"jsondecode: unidentified type\");\n}\n\n#endif\n\nDEFUN (jsondecode, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{object} =} jsondecode (@var{JSON_txt})\n@deftypefnx {} {@var{object} =} jsondecode (@dots{}, \"ReplacementStyle\", @var{rs})\n@deftypefnx {} {@var{object} =} jsondecode (@dots{}, \"Prefix\", @var{pfx})\n@deftypefnx {} {@var{object} =} jsondecode (@dots{}, \"makeValidName\", @var{TF})\n\nDecode text that is formatted in JSON.\n\nThe input @var{JSON_txt} is a string that contains JSON text.\n\nThe output @var{object} is an Octave object that contains the result of\ndecoding @var{JSON_txt}.\n\nFor more information about the options @qcode{\"ReplacementStyle\"} and\n@qcode{\"Prefix\"},\n@pxref{XREFmatlab_lang_makeValidName,,@code{matlab.lang.makeValidName}}.\n\nIf the value of the option @qcode{\"makeValidName\"} is false then names\nwill not be changed by @code{matlab.lang.makeValidName} and the\n@qcode{\"ReplacementStyle\"} and @qcode{\"Prefix\"} options will be ignored.\n\nNOTE: Decoding and encoding JSON text is not guaranteed to reproduce the\noriginal text as some names may be changed by @code{matlab.lang.makeValidName}.\n\nThis table shows the conversions from JSON data types to Octave data types:\n\n@multitable @columnfractions 0.50 0.50\n@headitem JSON data type @tab Octave data type\n@item Boolean @tab scalar logical\n@item Number @tab scalar double\n@item String @tab vector of characters\n@item Object @tab scalar struct (field names of the struct may be different from the keys of the JSON object due to @code{matlab_lang_makeValidName}\n@item null, inside a numeric array @tab @code{NaN}\n@item null, inside a non-numeric array @tab empty double array @code{[]}\n@item Array, of different data types @tab cell array\n@item Array, of Booleans @tab logical array\n@item Array, of Numbers @tab double array\n@item Array, of Strings @tab cell array of character vectors (@code{cellstr})\n@item Array of Objects, same field names @tab struct array\n@item Array of Objects, different field names @tab cell array of scalar structs\n@end multitable\n\nExamples:\n\n@example\n@group\njsondecode ('[1, 2, null, 3]')\n    @xresult{} ans =\n\n      1\n      2\n    NaN\n      3\n@end group\n\n@group\njsondecode ('[\"foo\", \"bar\", [\"foo\", \"bar\"]]')\n    @xresult{} ans =\n       @{\n         [1,1] = foo\n         [2,1] = bar\n         [3,1] =\n         @{\n           [1,1] = foo\n           [2,1] = bar\n         @}\n\n       @}\n@end group\n\n@group\njsondecode ('@{\"nu#m#ber\": 7, \"s#tr#ing\": \"hi\"@}', ...\n            'ReplacementStyle', 'delete')\n    @xresult{} scalar structure containing the fields:\n\n         number = 7\n         string = hi\n@end group\n\n@group\njsondecode ('@{\"nu#m#ber\": 7, \"s#tr#ing\": \"hi\"@}', ...\n            'makeValidName', false)\n    @xresult{} scalar structure containing the fields:\n\n         nu#m#ber = 7\n         s#tr#ing = hi\n@end group\n\n@group\njsondecode ('@{\"1\": \"one\", \"2\": \"two\"@}', 'Prefix', 'm_')\n    @xresult{} scalar structure containing the fields:\n\n         m_1 = one\n         m_2 = two\n@end group\n@end example\n\n@seealso{jsonencode, matlab.lang.makeValidName}\n@end deftypefn */)\n{\n#if defined (HAVE_RAPIDJSON)\n\n  int nargin = args.length ();\n\n  // makeValidName options are pairs, the number of arguments must be odd.\n  if (! (nargin % 2))\n    print_usage ();\n\n  // Detect if the user wants to use makeValidName\n  bool use_makeValidName = true;\n  octave_value_list make_valid_name_params;\n  for (auto i = 1; i < nargin; i = i + 2)\n    {\n      std::string parameter = args(i).xstring_value (\"jsondecode: \"\n                              \"option argument must be a string\");\n      if (string::strcmpi (parameter, \"makeValidName\"))\n        {\n          use_makeValidName = args(i + 1).strict_bool_value (\"jsondecode: \"\n                              \"'makeValidName' value must be a bool\");\n        }\n      else\n        make_valid_name_params.append (args.slice(i, 2));\n    }\n\n  make_valid_name_options *options\n    = use_makeValidName ? new make_valid_name_options (make_valid_name_params)\n      : nullptr;\n\n  unwind_action del_opts ([options] () { if (options) delete options; });\n\n  if (! args(0).is_string ())\n    error (\"jsondecode: JSON_TXT must be a character string\");\n\n  std::string json = args(0).string_value ();\n  rapidjson::Document d;\n  // DOM is chosen instead of SAX as SAX publishes events to a handler that\n  // decides what to do depending on the event only.  This will cause a\n  // problem in decoding JSON arrays as the output may be an array or a cell\n  // and that doesn't only depend on the event (startArray) but also on the\n  // types of the elements inside the array.\n  d.Parse<rapidjson::kParseNanAndInfFlag> (json.c_str ());\n\n  if (d.HasParseError ())\n    error (\"jsondecode: parse error at offset %u: %s\\n\",\n           static_cast<unsigned int> (d.GetErrorOffset ()) + 1,\n           rapidjson::GetParseError_En (d.GetParseError ()));\n\n  return decode (d, options);\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"jsondecode\", \"JSON decoding through RapidJSON\");\n\n#endif\n}\n\n/*\nFunctional BIST tests are located in test/json/jsondecode_BIST.tst\n\n## Input validation tests\n%!testif HAVE_RAPIDJSON\n%! fail (\"jsondecode ()\");\n%! fail (\"jsondecode ('1', 2)\");\n%! fail (\"jsondecode (1)\", \"JSON_TXT must be a character string\");\n%! fail (\"jsondecode ('12-')\", \"parse error at offset 3\");\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/jsonencode.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-string.h\"\n#include \"ovl.h\"\n\n#if defined (HAVE_RAPIDJSON)\n#  include <rapidjson/stringbuffer.h>\n#  include <rapidjson/writer.h>\n#  if defined (HAVE_RAPIDJSON_PRETTYWRITER)\n#    include <rapidjson/prettywriter.h>\n#  endif\n#endif\n\n#if defined (HAVE_RAPIDJSON)\n\n//! Encodes a scalar Octave value into a numerical JSON value.\n//!\n//! @param writer RapidJSON's writer that is responsible for generating JSON.\n//! @param obj scalar Octave value.\n//! @param ConvertInfAndNaN @c bool that converts @c Inf and @c NaN to @c null.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! octave_value obj (7);\n//! encode_numeric (writer, obj, true);\n//! @endcode\n\ntemplate <typename T> void\nencode_numeric (T& writer, const octave_value& obj,\n                const bool& ConvertInfAndNaN)\n{\n  if (obj.isfloat ())\n    {\n      double value = obj.scalar_value ();\n\n      // Detect floating point numbers which are actually integers by checking\n      // whether the number and the integer portion of the number are the same\n      // to within eps.\n      // FIXME: If value > 999999, MATLAB will encode it in scientific\n      // notation, but rapidJSON will output all digits.\n      if (fabs (trunc (value) - value) < std::numeric_limits<double>::epsilon ())\n\n        writer.Int64 (value);\n      // Possibly write NULL for non-finite values (-Inf, Inf, NaN, NA)\n      else if (ConvertInfAndNaN && ! octave::math::isfinite (value))\n        writer.Null ();\n      else\n        writer.Double (value);\n    }\n  else if (obj.isinteger ())\n    {\n      if (obj.is_uint64_type ())\n        {\n          uint64_t value = obj.uint64_value ();\n          writer.Uint64 (value);\n        }\n      else\n        {\n          // Write all other integers as 64-bit values and let RapidJSON\n          // determine number of digits to keep.\n          int64_t value = obj.int64_value ();\n          writer.Int64 (value);\n        }\n    }\n  else if (obj.is_bool_scalar ())\n    writer.Bool (obj.bool_value ());\n  else\n    error (\"jsonencode: unsupported type\");\n}\n\n//! Encodes character vectors and arrays into JSON strings.\n//!\n//! @param writer RapidJSON's writer that is responsible for generating JSON.\n//! @param obj character vectors or character arrays.\n//! @param original_dims The original dimensions of the array being encoded.\n//! @param level The level of recursion for the function.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! octave_value obj (\"foo\");\n//! encode_string (writer, obj, true);\n//! @endcode\n\ntemplate <typename T> void\nencode_string (T& writer, const octave_value& obj,\n               const dim_vector& original_dims, int level = 0)\n{\n  charNDArray array = obj.char_array_value ();\n\n  if (array.isempty ())\n    writer.String (\"\");\n  else if (array.isvector ())\n    {\n      // Handle the special case where the input is a vector with more than\n      // 2 dimensions (e.g., cat (8, ['a'], ['c'])).  In this case, we don't\n      // split the inner vectors of the input; we merge them into one.\n      if (level == 0)\n        {\n          std::string char_vector = \"\";\n          for (octave_idx_type i = 0; i < array.numel (); ++i)\n            char_vector += array(i);\n          writer.String (char_vector.c_str ());\n        }\n      else\n        for (octave_idx_type i = 0; i < array.numel () / original_dims(1); ++i)\n          {\n            std::string char_vector = \"\";\n            for (octave_idx_type k = 0; k < original_dims(1); ++k)\n              char_vector += array(i * original_dims(1) + k);\n            writer.String (char_vector.c_str ());\n          }\n    }\n  else\n    {\n      octave_idx_type idx;\n      octave_idx_type ndims = array.ndims ();\n      dim_vector dims = array.dims ();\n\n      // In this case, we already have a vector.  So, we transform it to 2-D\n      // vector in order to be detected by \"isvector\" in the recursive call\n      if (dims.num_ones () == ndims - 1)\n        {\n          // Handle the special case when the input is a vector with more than\n          // 2 dimensions (e.g., cat (8, ['a'], ['c'])).  In this case, we\n          // don't add dimension brackets and treat it as if it is a vector\n          if (level != 0)\n            // Place an opening and a closing bracket (represents a dimension)\n            // for every dimension that equals 1 until we reach the 2-D vector\n            for (int i = level; i < ndims - 1; ++i)\n              writer.StartArray ();\n\n          encode_string (writer, array.as_row (), original_dims, level);\n\n          if (level != 0)\n            for (int i = level; i < ndims - 1; ++i)\n              writer.EndArray ();\n        }\n      else\n        {\n          // We place an opening and a closing bracket for each dimension\n          // that equals 1 to preserve the number of dimensions when decoding\n          // the array after encoding it.\n          if (original_dims(level) == 1 && level != 1)\n            {\n              writer.StartArray ();\n              encode_string (writer, array, original_dims, level + 1);\n              writer.EndArray ();\n            }\n          else\n            {\n              // The second dimension contains the number of the chars in\n              // the char vector.  We want to treat them as a one object,\n              // so we replace it with 1\n              dims(1) = 1;\n\n              for (idx = 0; idx < ndims; ++idx)\n                if (dims(idx) != 1)\n                  break;\n              // Create the dimensions that will be used to call \"num2cell\"\n              // We called \"num2cell\" to divide the array to smaller sub-arrays\n              // in order to encode it recursively.\n              // The recursive encoding is necessary to support encoding of\n              // higher-dimensional arrays.\n              RowVector conversion_dims;\n              conversion_dims.resize (ndims - 1);\n              for (octave_idx_type i = 0; i < idx; ++i)\n                conversion_dims(i) = i + 1;\n              for (octave_idx_type i = idx ; i < ndims - 1; ++i)\n                conversion_dims(i) = i + 2;\n\n              octave_value_list args (obj);\n              args.append (conversion_dims);\n\n              Cell sub_arrays = octave::Fnum2cell (args)(0).cell_value ();\n\n              writer.StartArray ();\n\n              for (octave_idx_type i = 0; i < sub_arrays.numel (); ++i)\n                encode_string (writer, sub_arrays(i), original_dims,\n                               level + 1);\n\n              writer.EndArray ();\n            }\n        }\n    }\n}\n\n//! Encodes a struct Octave value into a JSON object or a JSON array depending\n//! on the type of the struct (scalar struct or struct array.)\n//!\n//! @param writer RapidJSON's writer that is responsible for generating JSON.\n//! @param obj struct Octave value.\n//! @param ConvertInfAndNaN @c bool that converts @c Inf and @c NaN to @c null.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! octave_value obj (octave_map ());\n//! encode_struct (writer, obj,true);\n//! @endcode\n\ntemplate <typename T> void\nencode_struct (T& writer, const octave_value& obj, const bool& ConvertInfAndNaN)\n{\n  octave_map struct_array = obj.map_value ();\n  octave_idx_type numel = struct_array.numel ();\n  bool is_array = (numel != 1);\n  string_vector keys = struct_array.keys ();\n\n  if (is_array)\n    writer.StartArray ();\n\n  for (octave_idx_type i = 0; i < numel; ++i)\n    {\n      writer.StartObject ();\n      for (octave_idx_type k = 0; k < keys.numel (); ++k)\n        {\n          writer.Key (keys(k).c_str ());\n          encode (writer, struct_array(i).getfield (keys(k)), ConvertInfAndNaN);\n        }\n      writer.EndObject ();\n    }\n\n  if (is_array)\n    writer.EndArray ();\n}\n\n//! Encodes a Cell Octave value into a JSON array\n//!\n//! @param writer RapidJSON's writer that is responsible for generating JSON.\n//! @param obj Cell Octave value.\n//! @param ConvertInfAndNaN @c bool that converts @c Inf and @c NaN to @c null.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! octave_value obj (cell ());\n//! encode_cell (writer, obj,true);\n//! @endcode\n\ntemplate <typename T> void\nencode_cell (T& writer, const octave_value& obj, const bool& ConvertInfAndNaN)\n{\n  Cell cell = obj.cell_value ();\n\n  writer.StartArray ();\n\n  for (octave_idx_type i = 0; i < cell.numel (); ++i)\n    encode (writer, cell(i), ConvertInfAndNaN);\n\n  writer.EndArray ();\n}\n\n//! Encodes a numeric or logical Octave array into a JSON array\n//!\n//! @param writer RapidJSON's writer that is responsible for generating JSON.\n//! @param obj numeric or logical Octave array.\n//! @param ConvertInfAndNaN @c bool that converts @c Inf and @c NaN to @c null.\n//! @param original_dims The original dimensions of the array being encoded.\n//! @param level The level of recursion for the function.\n//! @param is_logical optional @c bool that indicates if the array is logical.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! octave_value obj (NDArray ());\n//! encode_array (writer, obj,true);\n//! @endcode\n\ntemplate <typename T> void\nencode_array (T& writer, const octave_value& obj, const bool& ConvertInfAndNaN,\n              const dim_vector& original_dims, int level = 0,\n              bool is_logical = false)\n{\n  NDArray array = obj.array_value ();\n  // is_logical is assigned at level 0.  I think this is better than changing\n  // many places in the code, and it makes the function more modular.\n  if (level == 0)\n    is_logical = obj.islogical ();\n\n  if (array.isempty ())\n    {\n      writer.StartArray ();\n      writer.EndArray ();\n    }\n  else if (array.isvector ())\n    {\n      writer.StartArray ();\n      for (octave_idx_type i = 0; i < array.numel (); ++i)\n        {\n          if (is_logical)\n            encode_numeric (writer, bool (array(i)), ConvertInfAndNaN);\n          else\n            encode_numeric (writer, array(i), ConvertInfAndNaN);\n        }\n      writer.EndArray ();\n    }\n  else\n    {\n      octave_idx_type idx;\n      octave_idx_type ndims = array.ndims ();\n      const dim_vector& dims = array.dims ();\n\n      // In this case, we already have a vector.  So, we transform it to 2-D\n      // vector in order to be detected by \"isvector\" in the recursive call\n      if (dims.num_ones () == ndims - 1)\n        {\n          // Handle the special case when the input is a vector with more than\n          // 2 dimensions (e.g., ones ([1 1 1 1 1 6])).  In this case, we don't\n          // add dimension brackets and treat it as if it is a vector\n          if (level != 0)\n            // Place an opening and a closing bracket (represents a dimension)\n            // for every dimension that equals 1 till we reach the 2-D vector\n            for (int i = level; i < ndims - 1; ++i)\n              writer.StartArray ();\n\n          encode_array (writer, array.as_row (), ConvertInfAndNaN,\n                        original_dims, level + 1, is_logical);\n\n          if (level != 0)\n            for (int i = level; i < ndims - 1; ++i)\n              writer.EndArray ();\n        }\n      else\n        {\n          // We place an opening and a closing bracket for each dimension\n          // that equals 1 to preserve the number of dimensions when decoding\n          // the array after encoding it.\n          if (original_dims (level) == 1)\n            {\n              writer.StartArray ();\n              encode_array (writer, array, ConvertInfAndNaN,\n                            original_dims, level + 1, is_logical);\n              writer.EndArray ();\n            }\n          else\n            {\n              for (idx = 0; idx < ndims; ++idx)\n                if (dims(idx) != 1)\n                  break;\n\n              // Create the dimensions that will be used to call \"num2cell\"\n              // We called \"num2cell\" to divide the array to smaller sub-arrays\n              // in order to encode it recursively.\n              // The recursive encoding is necessary to support encoding of\n              // higher-dimensional arrays.\n              RowVector conversion_dims;\n              conversion_dims.resize (ndims - 1);\n              for (octave_idx_type i = 0; i < idx; ++i)\n                conversion_dims(i) = i + 1;\n              for (octave_idx_type i = idx ; i < ndims - 1; ++i)\n                conversion_dims(i) = i + 2;\n\n              octave_value_list args (obj);\n              args.append (conversion_dims);\n\n              Cell sub_arrays = octave::Fnum2cell (args)(0).cell_value ();\n\n              writer.StartArray ();\n\n              for (octave_idx_type i = 0; i < sub_arrays.numel (); ++i)\n                encode_array (writer, sub_arrays(i), ConvertInfAndNaN,\n                              original_dims, level + 1, is_logical);\n\n              writer.EndArray ();\n            }\n        }\n    }\n}\n\n//! Encodes any Octave object.  This function only serves as an interface\n//! by choosing which function to call from the previous functions.\n//!\n//! @param writer RapidJSON's writer that is responsible for generating JSON.\n//! @param obj any @ref octave_value that is supported.\n//! @param ConvertInfAndNaN @c bool that converts @c Inf and @c NaN to @c null.\n//!\n//! @b Example:\n//!\n//! @code{.cc}\n//! octave_value obj (true);\n//! encode (writer, obj,true);\n//! @endcode\n\ntemplate <typename T> void\nencode (T& writer, const octave_value& obj, const bool& ConvertInfAndNaN)\n{\n  if (obj.is_real_scalar ())\n    // Numeric scalars.\n    encode_numeric (writer, obj, ConvertInfAndNaN);\n  else if (obj.isnumeric () || obj.islogical ())\n    // Numeric and logical arrays.\n    encode_array (writer, obj, ConvertInfAndNaN, obj.dims ());\n  else if (obj.is_string ())\n    encode_string (writer, obj, obj.dims ());\n  else if (obj.isstruct ())\n    encode_struct (writer, obj, ConvertInfAndNaN);\n  else if (obj.iscell ())\n    encode_cell (writer, obj, ConvertInfAndNaN);\n  else if (obj.class_name () == \"containers.Map\")\n    // To extract the data in containers.Map, convert it to a struct.\n    // The struct will have a \"map\" field whose value is a struct that\n    // contains the desired data.\n    // To avoid warnings due to that conversion, disable the\n    // \"Octave:classdef-to-struct\" warning and re-enable it.\n    {\n      octave::unwind_action restore_warning_state\n      ([] (const octave_value_list& old_warning_state)\n      {\n        octave::set_warning_state (old_warning_state);\n      }, octave::set_warning_state (\"Octave:classdef-to-struct\", \"off\"));\n\n      encode_struct (writer, obj.scalar_map_value ().getfield (\"map\"),\n                     ConvertInfAndNaN);\n    }\n  else if (obj.isobject ())\n    {\n      octave::unwind_action restore_warning_state\n      ([] (const octave_value_list& old_warning_state)\n      {\n        octave::set_warning_state (old_warning_state);\n      }, octave::set_warning_state (\"Octave:classdef-to-struct\", \"off\"));\n\n      encode_struct (writer, obj.scalar_map_value (), ConvertInfAndNaN);\n    }\n  else\n    error (\"jsonencode: unsupported type\");\n}\n\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (jsonencode, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{JSON_txt} =} jsonencode (@var{object})\n@deftypefnx {} {@var{JSON_txt} =} jsonencode (@dots{}, \"ConvertInfAndNaN\", @var{TF})\n@deftypefnx {} {@var{JSON_txt} =} jsonencode (@dots{}, \"PrettyPrint\", @var{TF})\n\nEncode Octave data types into JSON text.\n\nThe input @var{object} is an Octave variable to encode.\n\nThe output @var{JSON_txt} is the JSON text that contains the result of encoding\n@var{object}.\n\nIf the value of the option @qcode{\"ConvertInfAndNaN\"} is true then @code{NaN},\n@code{NA}, @code{-Inf}, and @code{Inf} values will be converted to\n@qcode{\"null\"} in the output.  If it is false then they will remain as their\noriginal values.  The default value for this option is true.\n\nIf the value of the option @qcode{\"PrettyPrint\"} is true, the output text will\nhave indentations and line feeds.  If it is false, the output will be condensed\nand written without whitespace.  The default value for this option is false.\n\nProgramming Notes:\n\n@itemize @bullet\n@item\nComplex numbers are not supported.\n\n@item\nclassdef objects are first converted to structs and then encoded.\n\n@item\nTo preserve escape characters (e.g., @qcode{\"@backslashchar{}n\"}), use\nsingle-quoted strings.\n\n@item\nEvery character after the null character (@qcode{\"@backslashchar{}0\"}) in a\ndouble-quoted string will be dropped during encoding.\n\n@item\nEncoding and decoding an array is not guaranteed to preserve the dimensions\nof the array.  In particular, row vectors will be reshaped to column vectors.\n\n@item\nEncoding and decoding is not guaranteed to preserve the Octave data type\nbecause JSON supports fewer data types than Octave.  For example, if you\nencode an @code{int8} and then decode it, you will get a @code{double}.\n@end itemize\n\nThis table shows the conversions from Octave data types to JSON data types:\n\n@multitable @columnfractions 0.50 0.50\n@headitem Octave data type @tab JSON data type\n@item logical scalar @tab Boolean\n@item logical vector @tab Array of Boolean, reshaped to row vector\n@item logical array  @tab nested Array of Boolean\n@item numeric scalar @tab Number\n@item numeric vector @tab Array of Number, reshaped to row vector\n@item numeric array  @tab nested Array of Number\n@item @code{NaN}, @code{NA}, @code{Inf}, @code{-Inf}@*\nwhen @qcode{\"ConvertInfAndNaN\" = true} @tab @qcode{\"null\"}\n@item @code{NaN}, @code{NA}, @code{Inf}, @code{-Inf}@*\nwhen @qcode{\"ConvertInfAndNaN\" = false} @tab @qcode{\"NaN\"}, @qcode{\"NaN\"},\n@qcode{\"Infinity\"}, @qcode{\"-Infinity\"}\n@item empty array    @tab @qcode{\"[]\"}\n@item character vector @tab String\n@item character array @tab Array of String\n@item empty character array @tab @qcode{\"\"}\n@item cell scalar @tab Array\n@item cell vector @tab Array, reshaped to row vector\n@item cell array @tab Array, flattened to row vector\n@item struct scalar @tab Object\n@item struct vector @tab Array of Object, reshaped to row vector\n@item struct array  @tab nested Array of Object\n@item classdef object @tab Object\n@end multitable\n\nExamples:\n\n@smallexample\n@group\njsonencode ([1, NaN; 3, 4])\n@xresult{} [[1,null],[3,4]]\n@end group\n\n@group\njsonencode ([1, NaN; 3, 4], \"ConvertInfAndNaN\", false)\n@xresult{} [[1,NaN],[3,4]]\n@end group\n\n@group\n## Escape characters inside a single-quoted string\njsonencode ('\\0\\a\\b\\t\\n\\v\\f\\r')\n@xresult{} \"\\\\0\\\\a\\\\b\\\\t\\\\n\\\\v\\\\f\\\\r\"\n@end group\n\n@group\n## Escape characters inside a double-quoted string\njsonencode (\"\\a\\b\\t\\n\\v\\f\\r\")\n@xresult{} \"\\u0007\\b\\t\\n\\u000B\\f\\r\"\n@end group\n\n@group\njsonencode ([true; false], \"PrettyPrint\", true)\n@xresult{} ans = [\n     true,\n     false\n   ]\n@end group\n\n@group\njsonencode (['foo', 'bar'; 'foo', 'bar'])\n@xresult{} [\"foobar\",\"foobar\"]\n@end group\n\n@group\njsonencode (struct ('a', Inf, 'b', [], 'c', struct ()))\n@xresult{} @{\"a\":null,\"b\":[],\"c\":@{@}@}\n@end group\n\n@group\njsonencode (struct ('structarray', struct ('a', @{1; 3@}, 'b', @{2; 4@})))\n@xresult{} @{\"structarray\":[@{\"a\":1,\"b\":2@},@{\"a\":3,\"b\":4@}]@}\n@end group\n\n@group\njsonencode (@{'foo'; 'bar'; @{'foo'; 'bar'@}@})\n@xresult{} [\"foo\",\"bar\",[\"foo\",\"bar\"]]\n@end group\n\n@group\njsonencode (containers.Map(@{'foo'; 'bar'; 'baz'@}, [1, 2, 3]))\n@xresult{} @{\"bar\":2,\"baz\":3,\"foo\":1@}\n@end group\n@end smallexample\n\n@seealso{jsondecode}\n@end deftypefn */)\n{\n#if defined (HAVE_RAPIDJSON)\n\n  int nargin = args.length ();\n  // jsonencode has two options 'ConvertInfAndNaN' and 'PrettyPrint'\n  if (nargin != 1 && nargin != 3 && nargin != 5)\n    print_usage ();\n\n  // Initialize options with their default values\n  bool ConvertInfAndNaN = true;\n  bool PrettyPrint = false;\n\n  for (octave_idx_type i = 1; i < nargin; ++i)\n    {\n      if (! args(i).is_string ())\n        error (\"jsonencode: option must be a string\");\n      if (! args(i+1).is_bool_scalar ())\n        error (\"jsonencode: option value must be a logical scalar\");\n\n      std::string option_name = args(i++).string_value ();\n      if (string::strcmpi (option_name, \"ConvertInfAndNaN\"))\n        ConvertInfAndNaN = args(i).bool_value ();\n      else if (string::strcmpi (option_name, \"PrettyPrint\"))\n        PrettyPrint = args(i).bool_value ();\n      else\n        error (\"jsonencode: \"\n               R\"(Valid options are \"ConvertInfAndNaN\" and \"PrettyPrint\")\");\n    }\n\n# if ! defined (HAVE_RAPIDJSON_PRETTYWRITER)\n  if (PrettyPrint)\n    {\n      warn_disabled_feature (\"jsonencode\",\n                             R\"(the \"PrettyPrint\" option of RapidJSON)\");\n      PrettyPrint = false;\n    }\n# endif\n\n  rapidjson::StringBuffer json;\n  if (PrettyPrint)\n    {\n# if defined (HAVE_RAPIDJSON_PRETTYWRITER)\n      rapidjson::PrettyWriter<rapidjson::StringBuffer, rapidjson::UTF8<>,\n                rapidjson::UTF8<>, rapidjson::CrtAllocator,\n                rapidjson::kWriteNanAndInfFlag> writer (json);\n      writer.SetIndent (' ', 2);\n      encode (writer, args(0), ConvertInfAndNaN);\n# endif\n    }\n  else\n    {\n      rapidjson::Writer<rapidjson::StringBuffer, rapidjson::UTF8<>,\n                rapidjson::UTF8<>, rapidjson::CrtAllocator,\n                rapidjson::kWriteNanAndInfFlag> writer (json);\n      encode (writer, args(0), ConvertInfAndNaN);\n    }\n\n  return octave_value (json.GetString ());\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"jsonencode\", \"JSON encoding through RapidJSON\");\n\n#endif\n}\n\n/*\nFunctional BIST tests are located in test/json/jsonencode_BIST.tst\n\n## Input validation tests\n%!testif HAVE_RAPIDJSON\n%! fail (\"jsonencode ()\");\n%! fail (\"jsonencode (1, 2)\");\n%! fail (\"jsonencode (1, 2, 3, 4)\");\n%! fail (\"jsonencode (1, 2, 3, 4, 5, 6)\");\n%! fail (\"jsonencode (1, 2, true)\", \"option must be a string\");\n%! fail (\"jsonencode (1, 'string', ones (2,2))\", ...\n%!       \"option value must be a logical scalar\");\n%! fail (\"jsonencode (1, 'foobar', true)\", ...\n%!       'Valid options are \"ConvertInfAndNaN\"');\n\n%!testif HAVE_RAPIDJSON; ! __have_feature__ (\"RAPIDJSON_PRETTYWRITER\")\n%! fail (\"jsonencode (1, 'PrettyPrint', true)\", ...\n%!       \"warning\", 'the \"PrettyPrint\" option of RapidJSON was unavailable');\n\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/lookup.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cctype>\n#include <algorithm>\n\n#include \"dNDArray.h\"\n#include \"CNDArray.h\"\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic\nbool\ncontains_char (const std::string& str, char c)\n{\n  return (str.find (c) != std::string::npos\n          || str.find (std::toupper (c)) != std::string::npos);\n}\n\ntemplate <typename T>\ninline sortmode\nget_sort_mode (const Array<T>& array,\n               typename octave_sort<T>::compare_fcn_type desc_comp\n               = octave_sort<T>::descending_compare)\n{\n  octave_idx_type n = array.numel ();\n  if (n > 1 && desc_comp (array (0), array (n-1)))\n    return DESCENDING;\n  else\n    return ASCENDING;\n}\n\n// FIXME: perhaps there should be octave_value::lookup?\n// The question is, how should it behave w.r.t. the second argument's type.\n// We'd need a dispatch on two arguments.  Hmmm...\n\n#define INT_ARRAY_LOOKUP(TYPE)                                  \\\n  (table.is_ ## TYPE ## _type () && y.is_ ## TYPE ## _type ())  \\\n    retval = do_numeric_lookup (table.TYPE ## _array_value (),  \\\n                                y.TYPE ## _array_value (),      \\\n                                left_inf, right_inf,            \\\n                                match_idx, match_bool);\ntemplate <typename ArrayT>\nstatic octave_value\ndo_numeric_lookup (const ArrayT& array, const ArrayT& values,\n                   bool left_inf, bool right_inf,\n                   bool match_idx, bool match_bool)\n{\n  octave_value retval;\n\n  Array<octave_idx_type> idx = array.lookup (values);\n  octave_idx_type n = array.numel ();\n  octave_idx_type nval = values.numel ();\n\n  // Post-process.\n  if (match_bool)\n    {\n      boolNDArray match (idx.dims ());\n      for (octave_idx_type i = 0; i < nval; i++)\n        {\n          octave_idx_type j = idx.xelem (i);\n          match.xelem (i) = j != 0 && values(i) == array(j-1);\n        }\n\n      retval = match;\n    }\n  else if (match_idx || left_inf || right_inf)\n    {\n      if (match_idx)\n        {\n          NDArray ridx (idx.dims ());\n\n          for (octave_idx_type i = 0; i < nval; i++)\n            {\n              octave_idx_type j = idx.xelem (i);\n              ridx.xelem (i) = (j != 0 && values(i) == array(j-1)) ? j : 0;\n            }\n\n          retval = ridx;\n        }\n      else if (left_inf && right_inf)\n        {\n          // Results in valid indices.  Optimize using lazy index.\n          octave_idx_type zero = 0;\n          for (octave_idx_type i = 0; i < nval; i++)\n            {\n              octave_idx_type j = idx.xelem (i) - 1;\n              idx.xelem (i) = std::max (zero, std::min (j, n-2));\n            }\n\n          retval = idx_vector (idx);\n        }\n      else if (left_inf)\n        {\n          // Results in valid indices.  Optimize using lazy index.\n          octave_idx_type zero = 0;\n          for (octave_idx_type i = 0; i < nval; i++)\n            {\n              octave_idx_type j = idx.xelem (i) - 1;\n              idx.xelem (i) = std::max (zero, j);\n            }\n\n          retval = idx_vector (idx);\n        }\n      else if (right_inf)\n        {\n          NDArray ridx (idx.dims ());\n\n          for (octave_idx_type i = 0; i < nval; i++)\n            {\n              octave_idx_type j = idx.xelem (i);\n              ridx.xelem (i) = std::min (j, n-1);\n            }\n\n          retval = ridx;\n        }\n    }\n  else\n    retval = idx;\n\n  return retval;\n}\n\nDEFUN (lookup, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{idx} =} lookup (@var{table}, @var{y})\n@deftypefnx {} {@var{idx} =} lookup (@var{table}, @var{y}, @var{opt})\nLookup values in a @strong{sorted} table.\n\nThis function is usually used as a prelude to interpolation.\n\nIf table is increasing, of length N and @code{idx = lookup (table, y)}, then\n@code{table(idx(i)) <= y(i) < table(idx(i+1))} for all @code{y(i)} within the\ntable.  If @code{y(i) < table(1)} then @code{idx(i)} is 0.  If\n@code{y(i) >= table(end)} or @code{isnan (y(i))} then @code{idx(i)} is N.\n\nIf the table is decreasing, then the tests are reversed.  For non-strictly\nmonotonic tables, empty intervals are always skipped.  The result is undefined\nif @var{table} is not monotonic, or if @var{table} contains a NaN.\n\nThe complexity of the lookup is O(M*log(N)) where M is the size of @var{y}.\nIn the special case when @var{y} is also sorted, the complexity is\nO(min (M*log(N), M+N)).\n\n@var{table} and @var{y} can also be cell arrays of strings (or @var{y} can be a\nsingle string).  In this case, string lookup is performed using lexicographical\ncomparison.\n\nIf @var{opts} is specified, it must be a string with letters indicating\nadditional options.\n\n@table @code\n@item m\nMatch.  @code{table(idx(i)) == y(i)} if @code{y(i)} occurs in table;\notherwise, @code{idx(i)} is zero.\n\n@item b\nBoolean.  @code{idx(i)} is a logical 1 or 0, indicating whether @code{y(i)}\nis contained in table or not.\n\n@item l\nLeft.  For numeric lookups the leftmost subinterval shall be extended to\nminus infinity (i.e., all indices at least 1).\n\n@item r\nRight.  For numeric lookups the rightmost subinterval shall be extended to\ninfinity (i.e., all indices at most N-1).\n@end table\n\n@strong{Note}: If @var{table} is not sorted the results from @code{lookup}\nwill be unpredictable.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  octave_value table = args(0);\n  octave_value y = args(1);\n  if (table.ndims () > 2 || (table.columns () > 1 && table.rows () > 1))\n    warning (\"lookup: table is not a vector\");\n\n  octave_value retval;\n\n  bool num_case = ((table.isnumeric () && y.isnumeric ())\n                   || (table.is_char_matrix () && y.is_char_matrix ()));\n  bool str_case = table.iscellstr () && (y.is_string () || y.iscellstr ());\n  bool left_inf = false;\n  bool right_inf = false;\n  bool match_idx = false;\n  bool match_bool = false;\n\n  if (nargin == 3)\n    {\n      std::string opt = args(2).xstring_value (\"lookup: OPT must be a string\");\n      left_inf = contains_char (opt, 'l');\n      right_inf = contains_char (opt, 'r');\n      match_idx = contains_char (opt, 'm');\n      match_bool = contains_char (opt, 'b');\n      if (opt.find_first_not_of (\"lrmb\") != std::string::npos)\n        error (\"lookup: unrecognized option: %c\",\n               opt[opt.find_first_not_of (\"lrmb\")]);\n    }\n\n  if ((match_idx || match_bool) && (left_inf || right_inf))\n    error (\"lookup: m, b cannot be specified with l or r\");\n  else if (match_idx && match_bool)\n    error (\"lookup: only one of m or b can be specified\");\n  else if (str_case && (left_inf || right_inf))\n    error (\"lookup: l, r are not recognized for string lookups\");\n\n  if (num_case)\n    {\n      // In the case of a complex array, absolute values will be used for\n      // compatibility (though it's not too meaningful).\n      if (table.iscomplex ())\n        table = table.abs ();\n\n      if (y.iscomplex ())\n        y = y.abs ();\n\n      Array<octave_idx_type> idx;\n\n      // PS: I learned this from data.cc\n      if INT_ARRAY_LOOKUP (int8)\n        else if INT_ARRAY_LOOKUP (int16)\n          else if INT_ARRAY_LOOKUP (int32)\n            else if INT_ARRAY_LOOKUP (int64)\n              else if INT_ARRAY_LOOKUP (uint8)\n                else if INT_ARRAY_LOOKUP (uint16)\n                  else if INT_ARRAY_LOOKUP (uint32)\n                    else if INT_ARRAY_LOOKUP (uint64)\n                      else if (table.is_char_matrix () && y.is_char_matrix ())\n                        retval = do_numeric_lookup (table.char_array_value (),\n                                                    y.char_array_value (),\n                                                    left_inf, right_inf,\n                                                    match_idx, match_bool);\n                      else if (table.is_single_type () || y.is_single_type ())\n                        retval = do_numeric_lookup (table.float_array_value (),\n                                                    y.float_array_value (),\n                                                    left_inf, right_inf,\n                                                    match_idx, match_bool);\n                      else\n                        retval = do_numeric_lookup (table.array_value (),\n                                                    y.array_value (),\n                                                    left_inf, right_inf,\n                                                    match_idx, match_bool);\n    }\n  else if (str_case)\n    {\n      Array<std::string> str_table = table.cellstr_value ();\n      Array<std::string> str_y (dim_vector (1, 1));\n\n      if (y.iscellstr ())\n        str_y = y.cellstr_value ();\n      else\n        str_y(0) = y.string_value ();\n\n      Array<octave_idx_type> idx = str_table.lookup (str_y);\n      octave_idx_type nval = str_y.numel ();\n\n      // Post-process.\n      if (match_bool)\n        {\n          boolNDArray match (idx.dims ());\n          for (octave_idx_type i = 0; i < nval; i++)\n            {\n              octave_idx_type j = idx.xelem (i);\n              match.xelem (i) = j != 0 && str_y(i) == str_table(j-1);\n            }\n\n          retval = match;\n        }\n      else if (match_idx)\n        {\n          NDArray ridx (idx.dims ());\n          for (octave_idx_type i = 0; i < nval; i++)\n            {\n              octave_idx_type j = idx.xelem (i);\n              ridx.xelem (i) = (j != 0 && str_y(i) == str_table(j-1) ? j : 0);\n            }\n\n          retval = ridx;\n        }\n      else\n        retval = idx;\n    }\n  else\n    print_usage ();\n\n  return retval;\n}\n\n/*\n%!assert (lookup (1:3, 0.5), 0)     # value before table\n%!assert (lookup (1:3, 3.5), 3)     # value after table error\n%!assert (lookup (1:3, 1.5), 1)     # value within table error\n%!assert (lookup (1:3, [3,2,1]), [3,2,1])\n%!assert (lookup ([1:4]', [1.2, 3.5]'), [1, 3]')\n%!assert (lookup ([1:4], [1.2, 3.5]'), [1, 3]')\n%!assert (lookup ([1:4]', [1.2, 3.5]), [1, 3])\n%!assert (lookup ([1:4], [1.2, 3.5]), [1, 3])\n%!assert (lookup (1:3, [3, 2, 1]), [3, 2, 1])\n%!assert (lookup ([3:-1:1], [3.5, 3, 1.2, 2.5, 2.5]), [0, 1, 2, 1, 1])\n%!assert (isempty (lookup ([1:3], [])))\n%!assert (isempty (lookup ([1:3]', [])))\n%!assert (lookup (1:3, [1, 2; 3, 0.5]), [1, 2; 3, 0])\n%!assert (lookup (1:4, [1, 1.2; 3, 2.5], \"m\"), [1, 0; 3, 0])\n%!assert (lookup (4:-1:1, [1, 1.2; 3, 2.5], \"m\"), [4, 0; 2, 0])\n%!assert (lookup (1:4, [1, 1.2; 3, 2.5], \"b\"), logical ([1, 0; 3, 0]))\n%!assert (lookup (4:-1:1, [1, 1.2; 3, 2.5], \"b\"), logical ([4, 0; 2, 0]))\n%!\n%!assert (lookup ({\"apple\",\"lemon\",\"orange\"}, {\"banana\",\"kiwi\"; \"ananas\",\"mango\"}), [1,1;0,2])\n%!assert (lookup ({\"apple\",\"lemon\",\"orange\"}, \"potato\"), 3)\n%!assert (lookup ({\"orange\",\"lemon\",\"apple\"}, \"potato\"), 0)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/matrix_type.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n\n#include \"ov.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n#include \"MatrixType.h\"\n#include \"oct-locbuf.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (matrix_type, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{type} =} matrix_type (@var{A})\n@deftypefnx {} {@var{type} =} matrix_type (@var{A}, \"nocompute\")\n@deftypefnx {} {@var{A} =} matrix_type (@var{A}, @var{type})\n@deftypefnx {} {@var{A} =} matrix_type (@var{A}, \"upper\", @var{perm})\n@deftypefnx {} {@var{A} =} matrix_type (@var{A}, \"lower\", @var{perm})\n@deftypefnx {} {@var{A} =} matrix_type (@var{A}, \"banded\", @var{nl}, @var{nu})\nIdentify the matrix type or mark a matrix as a particular type.\n\nThis allows more rapid solutions of linear equations involving @var{A} to be\nperformed.\n\nCalled with a single argument, @code{matrix_type} returns the type of the\nmatrix and caches it for future use.\n\nCalled with more than one argument, @code{matrix_type} allows the type of\nthe matrix to be defined.\n\nIf the option @qcode{\"nocompute\"} is given, the function will not attempt\nto guess the type if it is still unknown.  This is useful for debugging\npurposes.\n\nThe possible matrix types depend on whether the matrix is full or sparse,\nand can be one of the following\n\n@table @asis\n@item @qcode{\"unknown\"}\nRemove any previously cached matrix type, and mark type as unknown.\n\n@item @qcode{\"full\"}\nMark the matrix as full.\n\n@item @qcode{\"positive definite\"}\nProbable full positive definite matrix.\n\n@item @qcode{\"diagonal\"}\nDiagonal matrix.  (Sparse matrices only)\n\n@item @qcode{\"permuted diagonal\"}\nPermuted Diagonal matrix.  The permutation does not need to be specifically\nindicated, as the structure of the matrix explicitly gives this.  (Sparse\nmatrices only)\n\n@item @qcode{\"upper\"}\nUpper triangular.  If the optional third argument @var{perm} is given, the\nmatrix is assumed to be a permuted upper triangular with the permutations\ndefined by the vector @var{perm}.\n\n@item @qcode{\"lower\"}\nLower triangular.  If the optional third argument @var{perm} is given, the\nmatrix is assumed to be a permuted lower triangular with the permutations\ndefined by the vector @var{perm}.\n\n@item  @qcode{\"banded\"}\n@itemx @qcode{\"banded positive definite\"}\nBanded matrix with the band size of @var{nl} below the diagonal and @var{nu}\nabove it.  If @var{nl} and @var{nu} are 1, then the matrix is tridiagonal\nand treated with specialized code.  In addition the matrix can be marked as\nprobably a positive definite.  (Sparse matrices only)\n\n@item @qcode{\"singular\"}\nThe matrix is assumed to be singular and will be treated with a minimum norm\nsolution.\n\n@end table\n\nNote that the matrix type will be discovered automatically on the first\nattempt to solve a linear equation involving @var{A}.  Therefore\n@code{matrix_type} is only useful to give Octave hints of the matrix type.\nIncorrectly defining the matrix type will result in incorrect results from\nsolutions of linear equations; it is entirely @strong{the responsibility of\nthe user} to correctly identify the matrix type.\n\nAlso, the test for positive definiteness is a low-cost test for a Hermitian\nmatrix with a real positive diagonal.  This does not guarantee that the\nmatrix is positive definite, but only that it is a probable candidate.  When\nsuch a matrix is factorized, a Cholesky@tie{}factorization is first\nattempted, and if that fails the matrix is then treated with an\nLU@tie{}factorization.  Once the matrix has been factorized,\n@code{matrix_type} will return the correct classification of the matrix.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0 || nargin > 4)\n    print_usage ();\n\n  bool autocomp = true;\n  if (nargin == 2 && args(1).is_string ()\n      && args(1).string_value () == \"nocompute\")\n    {\n      nargin = 1;\n      autocomp = false;\n    }\n\n  octave_value retval;\n\n  if (args(0).is_scalar_type ())\n    {\n      if (nargin == 1)\n        retval = octave_value (\"Diagonal\");\n      else\n        retval = args(0);\n    }\n  else if (args(0).issparse ())\n    {\n      if (nargin == 1)\n        {\n          MatrixType mattyp;\n\n          if (args(0).iscomplex ())\n            {\n              mattyp = args(0).matrix_type ();\n\n              if (mattyp.is_unknown () && autocomp)\n                {\n                  SparseComplexMatrix m\n                    = args(0).sparse_complex_matrix_value ();\n\n                  mattyp = MatrixType (m);\n                  args(0).matrix_type (mattyp);\n                }\n            }\n          else\n            {\n              mattyp = args(0).matrix_type ();\n\n              if (mattyp.is_unknown () && autocomp)\n                {\n                  SparseMatrix m = args(0).sparse_matrix_value ();\n\n                  mattyp = MatrixType (m);\n                  args(0).matrix_type (mattyp);\n                }\n            }\n\n          int typ = mattyp.type ();\n\n          if (typ == MatrixType::Diagonal)\n            retval = octave_value (\"Diagonal\");\n          else if (typ == MatrixType::Permuted_Diagonal)\n            retval = octave_value (\"Permuted Diagonal\");\n          else if (typ == MatrixType::Upper)\n            retval = octave_value (\"Upper\");\n          else if (typ == MatrixType::Permuted_Upper)\n            retval = octave_value (\"Permuted Upper\");\n          else if (typ == MatrixType::Lower)\n            retval = octave_value (\"Lower\");\n          else if (typ == MatrixType::Permuted_Lower)\n            retval = octave_value (\"Permuted Lower\");\n          else if (typ == MatrixType::Banded)\n            retval = octave_value (\"Banded\");\n          else if (typ == MatrixType::Banded_Hermitian)\n            retval = octave_value (\"Banded Positive Definite\");\n          else if (typ == MatrixType::Tridiagonal)\n            retval = octave_value (\"Tridiagonal\");\n          else if (typ == MatrixType::Tridiagonal_Hermitian)\n            retval = octave_value (\"Tridiagonal Positive Definite\");\n          else if (typ == MatrixType::Hermitian)\n            retval = octave_value (\"Positive Definite\");\n          else if (typ == MatrixType::Rectangular)\n            {\n              if (args(0).rows () == args(0).columns ())\n                retval = octave_value (\"Singular\");\n              else\n                retval = octave_value (\"Rectangular\");\n            }\n          else if (typ == MatrixType::Full)\n            retval = octave_value (\"Full\");\n          else\n            retval = octave_value (\"Unknown\");\n        }\n      else\n        {\n          // Ok, we're changing the matrix type\n          std::string str_typ = args(1).xstring_value (\"matrix_type: TYPE must be a string\");\n\n          // FIXME: why do I have to explicitly call the constructor?\n          MatrixType mattyp = MatrixType ();\n\n          octave_idx_type nl = 0;\n          octave_idx_type nu = 0;\n\n          // Use STL function to convert to lowercase\n          std::transform (str_typ.begin (), str_typ.end (),\n                          str_typ.begin (), tolower);\n\n          if (str_typ == \"diagonal\")\n            mattyp.mark_as_diagonal ();\n          if (str_typ == \"permuted diagonal\")\n            mattyp.mark_as_permuted_diagonal ();\n          else if (str_typ == \"upper\")\n            mattyp.mark_as_upper_triangular ();\n          else if (str_typ == \"lower\")\n            mattyp.mark_as_lower_triangular ();\n          else if (str_typ == \"banded\"\n                   || str_typ == \"banded positive definite\")\n            {\n              if (nargin != 4)\n                error (\"matrix_type: banded matrix type requires 4 arguments\");\n\n              nl = args(2).xnint_value (\"matrix_type: band size NL, NU must be integers\");\n              nu = args(3).xnint_value (\"matrix_type: band size NL, NU must be integers\");\n\n              if (nl == 1 && nu == 1)\n                mattyp.mark_as_tridiagonal ();\n              else\n                mattyp.mark_as_banded (nu, nl);\n\n              if (str_typ == \"banded positive definite\")\n                mattyp.mark_as_symmetric ();\n            }\n          else if (str_typ == \"positive definite\")\n            {\n              mattyp.mark_as_full ();\n              mattyp.mark_as_symmetric ();\n            }\n          else if (str_typ == \"singular\")\n            mattyp.mark_as_rectangular ();\n          else if (str_typ == \"full\")\n            mattyp.mark_as_full ();\n          else if (str_typ == \"unknown\")\n            mattyp.invalidate_type ();\n          else\n            error (\"matrix_type: Unknown matrix type %s\", str_typ.c_str ());\n\n          if (nargin == 3\n              && (str_typ == \"upper\" || str_typ == \"lower\"))\n            {\n              const ColumnVector perm = args(2).xvector_value (\"matrix_type: Invalid permutation vector PERM\");\n\n              octave_idx_type len = perm.numel ();\n              const dim_vector& dv = args(0).dims ();\n\n              if (len != dv(0))\n                error (\"matrix_type: Invalid permutation vector PERM\");\n\n              OCTAVE_LOCAL_BUFFER (octave_idx_type, p, len);\n\n              for (octave_idx_type i = 0; i < len; i++)\n                p[i] = static_cast<octave_idx_type> (perm (i)) - 1;\n\n              mattyp.mark_as_permuted (len, p);\n            }\n          else if (nargin != 2\n                   && str_typ != \"banded positive definite\"\n                   && str_typ != \"banded\")\n            error (\"matrix_type: Invalid number of arguments\");\n\n          // Set the matrix type\n          if (args(0).iscomplex ())\n            retval = octave_value (args(0).sparse_complex_matrix_value (),\n                                   mattyp);\n          else\n            retval = octave_value (args(0).sparse_matrix_value (),\n                                   mattyp);\n        }\n    }\n  else\n    {\n      if (nargin == 1)\n        {\n          MatrixType mattyp;\n\n          if (args(0).iscomplex ())\n            {\n              mattyp = args(0).matrix_type ();\n\n              if (mattyp.is_unknown () && autocomp)\n                {\n                  if (args(0).is_single_type ())\n                    {\n                      FloatComplexMatrix m;\n                      m = args(0).float_complex_matrix_value ();\n\n                      mattyp = MatrixType (m);\n                      args(0).matrix_type (mattyp);\n                    }\n                  else\n                    {\n                      ComplexMatrix m = args(0).complex_matrix_value ();\n\n                      mattyp = MatrixType (m);\n                      args(0).matrix_type (mattyp);\n                    }\n                }\n            }\n          else\n            {\n              mattyp = args(0).matrix_type ();\n\n              if (mattyp.is_unknown () && autocomp)\n                {\n                  if (args(0).is_single_type ())\n                    {\n                      FloatMatrix m = args(0).float_matrix_value ();\n\n                      mattyp = MatrixType (m);\n                      args(0).matrix_type (mattyp);\n                    }\n                  else\n                    {\n                      Matrix m = args(0).matrix_value ();\n\n                      mattyp = MatrixType (m);\n                      args(0).matrix_type (mattyp);\n                    }\n                }\n            }\n\n          int typ = mattyp.type ();\n\n          if (typ == MatrixType::Upper)\n            retval = octave_value (\"Upper\");\n          else if (typ == MatrixType::Permuted_Upper)\n            retval = octave_value (\"Permuted Upper\");\n          else if (typ == MatrixType::Lower)\n            retval = octave_value (\"Lower\");\n          else if (typ == MatrixType::Permuted_Lower)\n            retval = octave_value (\"Permuted Lower\");\n          else if (typ == MatrixType::Hermitian)\n            retval = octave_value (\"Positive Definite\");\n          else if (typ == MatrixType::Rectangular)\n            {\n              if (args(0).rows () == args(0).columns ())\n                retval = octave_value (\"Singular\");\n              else\n                retval = octave_value (\"Rectangular\");\n            }\n          else if (typ == MatrixType::Full)\n            retval = octave_value (\"Full\");\n          else\n            retval = octave_value (\"Unknown\");\n        }\n      else\n        {\n          // Ok, we're changing the matrix type\n          std::string str_typ = args(1).xstring_value (\"matrix_type: TYPE must be a string\");\n\n          // FIXME: why do I have to explicitly call the constructor?\n          MatrixType mattyp = MatrixType (MatrixType::Unknown, true);\n\n          // Use STL function to convert to lowercase\n          std::transform (str_typ.begin (), str_typ.end (),\n                          str_typ.begin (), tolower);\n\n          if (str_typ == \"upper\")\n            mattyp.mark_as_upper_triangular ();\n          else if (str_typ == \"lower\")\n            mattyp.mark_as_lower_triangular ();\n          else if (str_typ == \"positive definite\")\n            {\n              mattyp.mark_as_full ();\n              mattyp.mark_as_symmetric ();\n            }\n          else if (str_typ == \"singular\")\n            mattyp.mark_as_rectangular ();\n          else if (str_typ == \"full\")\n            mattyp.mark_as_full ();\n          else if (str_typ == \"unknown\")\n            mattyp.invalidate_type ();\n          else\n            error (\"matrix_type: Unknown matrix type %s\", str_typ.c_str ());\n\n          if (nargin == 3 && (str_typ == \"upper\" || str_typ == \"lower\"))\n            {\n              const ColumnVector perm = args(2).xvector_value (\"matrix_type: Invalid permutation vector PERM\");\n\n              octave_idx_type len = perm.numel ();\n              const dim_vector& dv = args(0).dims ();\n\n              if (len != dv(0))\n                error (\"matrix_type: Invalid permutation vector PERM\");\n\n              OCTAVE_LOCAL_BUFFER (octave_idx_type, p, len);\n\n              for (octave_idx_type i = 0; i < len; i++)\n                p[i] = static_cast<octave_idx_type> (perm (i)) - 1;\n\n              mattyp.mark_as_permuted (len, p);\n            }\n          else if (nargin != 2)\n            error (\"matrix_type: Invalid number of arguments\");\n\n          // Set the matrix type\n          if (args(0).is_single_type ())\n            {\n              if (args(0).iscomplex ())\n                retval = octave_value (args(0).float_complex_matrix_value (),\n                                       mattyp);\n              else\n                retval = octave_value (args(0).float_matrix_value (),\n                                       mattyp);\n            }\n          else\n            {\n              if (args(0).iscomplex ())\n                retval = octave_value (args(0).complex_matrix_value (),\n                                       mattyp);\n              else\n                retval = octave_value (args(0).matrix_value (), mattyp);\n            }\n        }\n    }\n\n  return retval;\n}\n\n/*\n## FIXME:\n## Disable tests for lower under-determined and upper over-determined\n## matrices as this detection is disabled in MatrixType due to issues\n## of non minimum norm solution being found.\n\n%!assert (matrix_type (speye (10,10)), \"Diagonal\")\n%!assert (matrix_type (speye (10,10)([2:10,1],:)), \"Permuted Diagonal\")\n%!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1;sparse(9,1);1]]),\n%!        \"Upper\")\n%!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1;sparse(9,1);1]](:,[2,1,3:11])),\n%!        \"Permuted Upper\")\n%!assert (matrix_type ([speye(10,10),sparse(10,1);1,sparse(1,9),1]), \"Lower\")\n%!assert (matrix_type ([speye(10,10),sparse(10,1);1,sparse(1,9),1]([2,1,3:11],:)),\n%!        \"Permuted Lower\")\n\n%!test\n%! bnd = spparms (\"bandden\");\n%! spparms (\"bandden\", 0.5);\n%! a = spdiags (rand (10,3)-0.5,[-1,0,1],10,10);\n%! assert (matrix_type (a), \"Tridiagonal\");\n%! assert (matrix_type (a'+a+2* speye (10)), \"Tridiagonal Positive Definite\");\n%! spparms (\"bandden\", bnd);\n%!test\n%! bnd=spparms (\"bandden\");\n%! spparms (\"bandden\", 0.5);\n%! a = spdiags (randn (10,4),[-2:1],10,10);\n%! assert (matrix_type (a), \"Banded\");\n%! assert (matrix_type (a'*a), \"Banded Positive Definite\");\n%! spparms (\"bandden\", bnd);\n%!test\n%! a = [speye(10,10),[sparse(9,1);1];-1,sparse(1,9),1];\n%! assert (matrix_type (a), \"Full\");\n%! assert (matrix_type (a'*a), \"Positive Definite\");\n\n%!assert (matrix_type (speye (10,11)), \"Diagonal\")\n%!assert (matrix_type (speye (10,11)([2:10,1],:)), \"Permuted Diagonal\")\n%!assert (matrix_type (speye (11,10)), \"Diagonal\")\n%!assert (matrix_type (speye (11,10)([2:11,1],:)), \"Permuted Diagonal\")\n%!#assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]]), \"Upper\")\n%!#assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]](:,[2,1,3:12])), \"Permuted Upper\")\n%!assert (matrix_type ([speye(11,9),[1;sparse(8,1);1;0]]), \"Upper\")\n%!assert (matrix_type ([speye(11,9),[1;sparse(8,1);1;0]](:,[2,1,3:10])),\n%!        \"Permuted Upper\")\n\n%!#assert (matrix_type ([speye(10,10),sparse(10,1);[1;1],sparse(2,9),[1;1]]),\n%!         \"Lower\")\n%!#assert (matrix_type ([speye(10,10),sparse(10,1);[1;1],sparse(2,9),[1;1]]([2,1,3:12],:)),\n%!         \"Permuted Lower\")\n%!assert (matrix_type ([speye(9,11);[1,sparse(1,8),1,0]]), \"Lower\")\n%!assert (matrix_type ([speye(9,11);[1,sparse(1,8),1,0]]([2,1,3:10],:)),\n%!        \"Permuted Lower\")\n%!assert (matrix_type (spdiags (randn (10,4),[-2:1],10,9)), \"Rectangular\")\n\n%!assert (matrix_type (1i* speye (10,10)), \"Diagonal\")\n%!assert (matrix_type (1i* speye (10,10)([2:10,1],:)), \"Permuted Diagonal\")\n%!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1i;sparse(9,1);1]]),\n%!        \"Upper\")\n%!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1i;sparse(9,1);1]](:,[2,1,3:11])),\n%!        \"Permuted Upper\")\n%!assert (matrix_type ([speye(10,10),sparse(10,1);1i,sparse(1,9),1]), \"Lower\")\n%!assert (matrix_type ([speye(10,10),sparse(10,1);1i,sparse(1,9),1]([2,1,3:11],:)),\n%!        \"Permuted Lower\")\n\n%!test\n%! bnd = spparms (\"bandden\");\n%! spparms (\"bandden\", 0.5);\n%! assert (matrix_type (spdiags (1i* randn (10,3),[-1,0,1],10,10)),\n%!         \"Tridiagonal\");\n%! a = 1i*(rand (9,1)-0.5);\n%! a = [[a;0],ones(10,1),[0;-a]];\n%! assert (matrix_type (spdiags (a,[-1,0,1],10,10)),\n%!         \"Tridiagonal Positive Definite\");\n%! spparms (\"bandden\", bnd);\n%!test\n%! bnd = spparms (\"bandden\");\n%! spparms (\"bandden\", 0.5);\n%! assert (matrix_type (spdiags (1i* randn (10,4),[-2:1],10,10)), \"Banded\");\n%! a = 1i*(rand (9,2)-0.5);\n%! a = [[a;[0,0]],ones(10,1),[[0;-a(:,2)],[0;0;-a(1:8,1)]]];\n%! assert (matrix_type (spdiags (a,[-2:2],10,10)), \"Banded Positive Definite\");\n%! spparms (\"bandden\", bnd);\n%!test\n%! a = [speye(10,10),[sparse(9,1);1i];-1,sparse(1,9),1];\n%! assert (matrix_type (a), \"Full\");\n%! assert (matrix_type (a'*a), \"Positive Definite\");\n\n%!assert (matrix_type (1i* speye (10,11)), \"Diagonal\")\n%!assert (matrix_type (1i* speye (10,11)([2:10,1],:)), \"Permuted Diagonal\")\n%!assert (matrix_type (1i* speye (11,10)), \"Diagonal\")\n%!assert (matrix_type (1i* speye (11,10)([2:11,1],:)), \"Permuted Diagonal\")\n%!#assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]]), \"Upper\")\n%!#assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]](:,[2,1,3:12])), \"Permuted Upper\")\n%!assert (matrix_type ([speye(11,9),[1i;sparse(8,1);1i;0]]), \"Upper\")\n%!assert (matrix_type ([speye(11,9),[1i;sparse(8,1);1i;0]](:,[2,1,3:10])),\n%!        \"Permuted Upper\")\n%!#assert (matrix_type ([speye(10,10),sparse(10,1);[1i;1i],sparse(2,9),[1i;1i]]), \"Lower\")\n%!#assert (matrix_type ([speye(10,10),sparse(10,1);[1i;1i],sparse(2,9),[1i;1i]]([2,1,3:12],:)), \"Permuted Lower\")\n%!assert (matrix_type ([speye(9,11);[1i,sparse(1,8),1i,0]]), \"Lower\")\n%!assert (matrix_type ([speye(9,11);[1i,sparse(1,8),1i,0]]([2,1,3:10],:)),\n%!        \"Permuted Lower\")\n%!assert (matrix_type (1i*spdiags(randn(10,4),[-2:1],10,9)), \"Rectangular\")\n\n%!test\n%! a = matrix_type (spdiags (randn (10,3),[-1,0,1],10,10), \"Singular\");\n%! assert (matrix_type (a), \"Singular\");\n\n%!assert (matrix_type (triu (ones (10,10))), \"Upper\")\n%!assert (matrix_type (triu (ones (10,10),-1)), \"Full\")\n%!assert (matrix_type (tril (ones (10,10))), \"Lower\")\n%!assert (matrix_type (tril (ones (10,10),1)), \"Full\")\n%!assert (matrix_type (10* eye (10,10) + ones (10,10)), \"Positive Definite\")\n%!assert (matrix_type (ones (11,10)), \"Rectangular\")\n%!test\n%! a = matrix_type (ones (10,10), \"Singular\");\n%! assert (matrix_type (a), \"Singular\");\n\n%!assert (matrix_type (triu (1i* ones (10,10))), \"Upper\")\n%!assert (matrix_type (triu (1i* ones (10,10),-1)), \"Full\")\n%!assert (matrix_type (tril (1i* ones (10,10))), \"Lower\")\n%!assert (matrix_type (tril (1i* ones (10,10),1)), \"Full\")\n%!assert (matrix_type (10* eye (10,10) + 1i*triu (ones (10,10),1) -1i*tril (ones (10,10),-1)), \"Positive Definite\")\n%!assert (matrix_type (ones (11,10)), \"Rectangular\")\n%!test\n%! a = matrix_type (ones (10,10), \"Singular\");\n%! assert (matrix_type (a), \"Singular\");\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/module.mk",
    "content": "DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nCOREFCN_UTIL_SRC = \\\n  %reldir%/bsxfun.cc \\\n  %reldir%/cellfun.cc \\\n  %reldir%/find.cc \\\n  %reldir%/jsondecode.cc \\\n  %reldir%/jsonencode.cc \\\n  %reldir%/lookup.cc \\\n  %reldir%/matrix_type.cc \\\n  %reldir%/regexp.cc \\\n  %reldir%/strfind.cc \\\n  %reldir%/strfns.cc \\\n  %reldir%/sub2ind.cc \\\n  %reldir%/tril.cc \\\n  %reldir%/typecast.cc\n\nnoinst_LTLIBRARIES += \\\n  %reldir%/libutil.la\n\n%canon_reldir%_libutil_la_SOURCES = $(COREFCN_UTIL_SRC)\n\n%canon_reldir%_libutil_la_CPPFLAGS = \\\n  $(libinterp_liboctinterp_la_CPPFLAGS)\n\nlibinterp_liboctinterp_la_LIBADD += %reldir%/libutil.la\n"
  },
  {
    "path": "libinterp/corefcn/util/regexp.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-locbuf.h\"\n#include \"oct-regexp.h\"\n#include \"str-vec.h\"\n\n#include \"defun.h\"\n#include \"Cell.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-map.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Replace backslash escapes in a string with the real values.  We need\n// two special functions instead of the one in utils.cc because the set\n// of escape sequences used for regexp patterns and replacement strings\n// is different from those used in the *printf functions.\n\nstatic std::string\ndo_regexp_ptn_string_escapes (const std::string& s, bool is_sq_str)\n{\n  std::string retval;\n\n  std::size_t i = 0;\n  std::size_t j = 0;\n  std::size_t len = s.length ();\n\n  retval.resize (len);\n\n  while (j < len)\n    {\n      if (s[j] == '\\\\' && j+1 < len)\n        {\n          switch (s[++j])\n            {\n            case 'b': // backspace\n              if (is_sq_str)\n                retval[i] = '\\b';\n              else\n                {\n                  // Pass escape sequence through\n                  retval[i] = '\\\\';\n                  retval[++i] = 'b';\n                }\n              break;\n\n            // Translate \\< and \\> to PCRE patterns for pseudo-word boundary\n            case '<': // begin word boundary\n              retval.insert (i, \"(?<=\\\\W|^)\");\n              i += 8;\n              break;\n\n            case '>': // end word boundary\n              retval.insert (i, \"(?=\\\\W|$)\");\n              i += 7;\n              break;\n\n            case 'o': // octal input\n              {\n                bool bad_esc_seq = (j+1 >= len);\n\n                bool brace = false;\n                if (! bad_esc_seq && s[++j] == '{')\n                  {\n                    brace = true;\n                    j++;\n                  }\n\n                int tmpi = 0;\n                std::size_t k;\n                for (k = j; k < std::min (j+3+brace, len); k++)\n                  {\n                    int digit = s[k] - '0';\n                    if (digit < 0 || digit > 7)\n                      break;\n                    tmpi <<= 3;\n                    tmpi += digit;\n                  }\n                if (bad_esc_seq || (brace && s[k++] != '}'))\n                  {\n                    tmpi = 0;\n                    warning (R\"(malformed octal escape sequence '\\o' -- converting to '\\0')\");\n                  }\n                retval[i] = tmpi;\n                j = k - 1;\n                break;\n              }\n\n            default:  // pass escape sequence through\n              retval[i] = '\\\\';\n              retval[++i] = s[j];\n              break;\n            }\n        }\n      else\n        {\n          retval[i] = s[j];\n        }\n\n      i++;\n      j++;\n    }\n\n  retval.resize (i);\n\n  return retval;\n}\n\nstatic std::string\ndo_regexp_rep_string_escapes (const std::string& s)\n{\n  std::string retval;\n\n  std::size_t i = 0;\n  std::size_t j = 0;\n  std::size_t len = s.length ();\n\n  retval.resize (len);\n\n  while (j < len)\n    {\n      if (s[j] == '\\\\' && j+1 < len)\n        {\n          switch (s[++j])\n            {\n            case 'a': // alarm\n              retval[i] = '\\a';\n              break;\n\n            case 'b': // backspace\n              retval[i] = '\\b';\n              break;\n\n            case 'f': // formfeed\n              retval[i] = '\\f';\n              break;\n\n            case 'n': // newline\n              retval[i] = '\\n';\n              break;\n\n            case 'r': // carriage return\n              retval[i] = '\\r';\n              break;\n\n            case 't': // horizontal tab\n              retval[i] = '\\t';\n              break;\n\n            case 'v': // vertical tab\n              retval[i] = '\\v';\n              break;\n\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7': // octal input\n              {\n                std::size_t k;\n                int tmpi = s[j] - '0';\n                for (k = j+1; k < std::min (j+3, len); k++)\n                  {\n                    int digit = s[k] - '0';\n                    if (digit < 0 || digit > 7)\n                      break;\n                    tmpi <<= 3;\n                    tmpi += digit;\n                  }\n                retval[i] = tmpi;\n                j = k - 1;\n                break;\n              }\n\n            case 'o': // octal input\n              {\n                bool bad_esc_seq = (j+1 >= len);\n\n                bool brace = false;\n                if (! bad_esc_seq && s[++j] == '{')\n                  {\n                    brace = true;\n                    j++;\n                  }\n\n                int tmpi = 0;\n                std::size_t k;\n                for (k = j; k < std::min (j+3+brace, len); k++)\n                  {\n                    int digit = s[k] - '0';\n                    if (digit < 0 || digit > 7)\n                      break;\n                    tmpi <<= 3;\n                    tmpi += digit;\n                  }\n                if (bad_esc_seq || (brace && s[k++] != '}'))\n                  {\n                    warning (R\"(malformed octal escape sequence '\\o' -- converting to '\\0')\");\n                    tmpi = 0;\n                  }\n                retval[i] = tmpi;\n                j = k - 1;\n                break;\n              }\n\n            case 'x': // hex input\n              {\n                bool bad_esc_seq = (j+1 >= len);\n\n                bool brace = false;\n                if (! bad_esc_seq && s[++j] == '{')\n                  {\n                    brace = true;\n                    j++;\n                  }\n\n                int tmpi = 0;\n                std::size_t k;\n                for (k = j; k < std::min (j+2+brace, len); k++)\n                  {\n                    if (! isxdigit (s[k]))\n                      break;\n\n                    tmpi <<= 4;\n                    int digit = s[k];\n                    if (digit >= 'a')\n                      tmpi += digit - 'a' + 10;\n                    else if (digit >= 'A')\n                      tmpi += digit - 'A' + 10;\n                    else\n                      tmpi += digit - '0';\n                  }\n                if (bad_esc_seq || (brace && s[k++] != '}'))\n                  {\n                    warning (R\"(malformed hex escape sequence '\\x' -- converting to '\\0')\");\n                    tmpi = 0;\n                  }\n                retval[i] = tmpi;\n                j = k - 1;\n                break;\n              }\n\n            // Both dollar sign (for capture buffer) and backslash are\n            // passed through with their escape backslash.  The processing\n            // for these must occur during the actual replacement operation\n            // in oct-regexp.cc.\n            case '$':  // pass dollar sign through with escape\n              retval[i] = '\\\\'; retval[++i] = '$';\n              break;\n\n            case '\\\\': // pass backslash through with escape\n              retval[i] = '\\\\'; retval[++i] = '\\\\';\n              break;\n\n            default:   // convert escaped character to unescaped char\n              retval[i] = s[j];\n              break;\n            }\n        }\n      else\n        {\n          retval[i] = s[j];\n        }\n\n      i++;\n      j++;\n    }\n\n  retval.resize (i);\n\n  return retval;\n}\n\nstatic void\nparse_options (regexp::opts& options, const octave_value_list& args,\n               const std::string& who, int skip, bool& extra_args)\n{\n  extra_args = false;\n\n  for (int i = skip; i < args.length (); i++)\n    {\n      std::string str;\n\n      str = args(i).xstring_value (\"%s: optional arguments must be strings\", who.c_str ());\n\n      std::transform (str.begin (), str.end (), str.begin (), tolower);\n\n      if (str.find (\"once\", 0) == 0)\n        options.once (true);\n      else if (str.find (\"matchcase\", 0) == 0)\n        options.case_insensitive (false);\n      else if (str.find (\"ignorecase\", 0) == 0)\n        options.case_insensitive (true);\n      else if (str.find (\"dotall\", 0) == 0)\n        options.dotexceptnewline (false);\n      else if (str.find (\"stringanchors\", 0) == 0)\n        options.lineanchors (false);\n      else if (str.find (\"literalspacing\", 0) == 0)\n        options.freespacing (false);\n      else if (str.find (\"noemptymatch\", 0) == 0)\n        options.emptymatch (false);\n      else if (str.find (\"dotexceptnewline\", 0) == 0)\n        options.dotexceptnewline (true);\n      else if (str.find (\"lineanchors\", 0) == 0)\n        options.lineanchors (true);\n      else if (str.find (\"freespacing\", 0) == 0)\n        options.freespacing (true);\n      else if (str.find (\"emptymatch\", 0) == 0)\n        options.emptymatch (true);\n      else if (str.find (\"start\", 0) == 0\n               || str.find (\"end\", 0) == 0\n               || str.find (\"tokenextents\", 0) == 0\n               || str.find (\"match\", 0) == 0\n               || str.find (\"tokens\", 0) == 0\n               || str.find (\"names\", 0) == 0\n               || str.find (\"split\", 0) == 0)\n        extra_args = true;\n      else\n        error (\"%s: unrecognized option\", who.c_str ());\n    }\n}\n\nstatic octave_value_list\noctregexp (const octave_value_list& args, int nargout,\n           const std::string& who, bool case_insensitive = false)\n{\n  octave_value_list retval;\n\n  int nargin = args.length ();\n\n  // Make sure we have string, pattern\n  const std::string buffer = args(0).string_value ();\n\n  std::string pattern = args(1).string_value ();\n\n  // Rewrite pattern for PCRE\n  pattern = do_regexp_ptn_string_escapes (pattern, args(1).is_sq_string ());\n\n  regexp::opts options;\n  options.case_insensitive (case_insensitive);\n  bool extra_options = false;\n  parse_options (options, args, who, 2, extra_options);\n\n  const regexp::match_data rx_lst\n    = regexp::match (pattern, buffer, options, who);\n\n  string_vector named_pats = rx_lst.named_patterns ();\n\n  std::size_t sz = rx_lst.size ();\n\n  // Converted the linked list in the correct form for the return values\n\n  octave_map nmap (dim_vector ((sz == 0 ? 0 : 1), sz), named_pats);\n\n  retval.resize (7);\n\n  if (sz != 0)\n    {\n      for (int j = 0; j < named_pats.numel (); j++)\n        {\n          Cell ctmp (dim_vector (1, sz));\n          octave_idx_type i = 0;\n\n          for (const auto& match_data : rx_lst)\n            {\n              string_vector named_tokens = match_data.named_tokens ();\n\n              ctmp(i++) = named_tokens(j);\n            }\n\n          nmap.assign (named_pats(j), ctmp);\n        }\n    }\n  retval(5) = nmap;\n\n  if (options.once ())\n    {\n      auto p = rx_lst.begin ();\n\n      retval(4) = (sz ? p->tokens () : Cell ());\n      retval(3) = (sz ? p->match_string () : \"\");\n      retval(2) = (sz ? p->token_extents () : Matrix ());\n\n      if (sz)\n        {\n          double start = p->start ();\n          double end = p->end ();\n\n          Cell split (dim_vector (1, 2));\n          split(0) = buffer.substr (0, start-1);\n          split(1) = buffer.substr (end);\n\n          retval(6) = split;\n          retval(1) = end;\n          retval(0) = start;\n        }\n      else\n        {\n          retval(6) = buffer;\n          retval(1) = Matrix ();\n          retval(0) = Matrix ();\n        }\n    }\n  else\n    {\n      Cell tokens (dim_vector (1, sz));\n      Cell match_string (dim_vector (1, sz));\n      Cell token_extents (dim_vector (1, sz));\n      NDArray end (dim_vector (1, sz));\n      NDArray start (dim_vector (1, sz));\n      Cell split (dim_vector (1, sz+1));\n      std::size_t sp_start = 0;\n\n      octave_idx_type i = 0;\n      for (const auto& match_data : rx_lst)\n        {\n          double s = match_data.start ();\n          double e = match_data.end ();\n\n          string_vector tmp = match_data.tokens ();\n          tokens(i) = Cell (dim_vector (1, tmp.numel ()), tmp);\n          match_string(i) = match_data.match_string ();\n          token_extents(i) = match_data.token_extents ();\n          end(i) = e;\n          start(i) = s;\n          split(i) = buffer.substr (sp_start, s-sp_start-1);\n          sp_start = e;\n          i++;\n        }\n\n      split(i) = buffer.substr (sp_start);\n\n      retval(6) = split;\n      retval(4) = tokens;\n      retval(3) = match_string;\n      retval(2) = token_extents;\n      retval(1) = end;\n      retval(0) = start;\n    }\n\n  // Alter the order of the output arguments\n\n  if (extra_options)\n    {\n      int n = 0;\n      octave_value_list new_retval;\n      new_retval.resize (nargout);\n\n      bool arg_used[7] {};\n\n      for (int j = 2; j < nargin; j++)\n        {\n          int k = 0;\n          std::string str = args(j).string_value ();\n          std::transform (str.begin (), str.end (), str.begin (), tolower);\n\n          if (str.find (\"once\", 0) == 0\n              || str.find (\"stringanchors\", 0) == 0\n              || str.find (\"lineanchors\", 0) == 0\n              || str.find (\"matchcase\", 0) == 0\n              || str.find (\"ignorecase\", 0) == 0\n              || str.find (\"dotall\", 0) == 0\n              || str.find (\"dotexceptnewline\", 0) == 0\n              || str.find (\"literalspacing\", 0) == 0\n              || str.find (\"freespacing\", 0) == 0\n              || str.find (\"noemptymatch\", 0) == 0\n              || str.find (\"emptymatch\", 0) == 0)\n            continue;\n          else if (str.find (\"start\", 0) == 0)\n            k = 0;\n          else if (str.find (\"end\", 0) == 0)\n            k = 1;\n          else if (str.find (\"tokenextents\", 0) == 0)\n            k = 2;\n          else if (str.find (\"match\", 0) == 0)\n            k = 3;\n          else if (str.find (\"tokens\", 0) == 0)\n            k = 4;\n          else if (str.find (\"names\", 0) == 0)\n            k = 5;\n          else if (str.find (\"split\", 0) == 0)\n            k = 6;\n\n          new_retval(n++) = retval(k);\n          arg_used[k] = true;\n\n          if (n == nargout)\n            break;\n        }\n\n      // Fill in the rest of the arguments\n      if (n < nargout)\n        {\n          for (int j = 0; j < 7; j++)\n            {\n              if (! arg_used[j])\n                new_retval(n++) = retval(j);\n            }\n        }\n\n      retval = new_retval;\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\noctcellregexp (const octave_value_list& args, int nargout,\n               const std::string& who, bool case_insensitive = false)\n{\n  octave_value_list retval;\n\n  if (args(0).iscell ())\n    {\n      OCTAVE_LOCAL_BUFFER (Cell, newretval, nargout);\n      octave_value_list new_args = args;\n      Cell cellstr = args(0).cell_value ();\n      if (args(1).iscell ())\n        {\n          Cell cellpat = args(1).cell_value ();\n\n          if (cellpat.numel () == 1)\n            {\n              for (int j = 0; j < nargout; j++)\n                newretval[j].resize (cellstr.dims ());\n\n              new_args(1) = cellpat(0);\n\n              for (octave_idx_type i = 0; i < cellstr.numel (); i++)\n                {\n                  new_args(0) = cellstr(i);\n                  octave_value_list tmp = octregexp (new_args, nargout, who,\n                                                     case_insensitive);\n\n                  for (int j = 0; j < nargout; j++)\n                    newretval[j](i) = tmp(j);\n                }\n            }\n          else if (cellstr.numel () == 1)\n            {\n              for (int j = 0; j < nargout; j++)\n                newretval[j].resize (cellpat.dims ());\n\n              new_args(0) = cellstr(0);\n\n              for (octave_idx_type i = 0; i < cellpat.numel (); i++)\n                {\n                  new_args(1) = cellpat(i);\n                  octave_value_list tmp = octregexp (new_args, nargout, who,\n                                                     case_insensitive);\n\n                  for (int j = 0; j < nargout; j++)\n                    newretval[j](i) = tmp(j);\n                }\n            }\n          else if (cellstr.numel () == cellpat.numel ())\n            {\n              if (cellstr.dims () != cellpat.dims ())\n                error (\"%s: inconsistent cell array dimensions\", who.c_str ());\n\n              for (int j = 0; j < nargout; j++)\n                newretval[j].resize (cellstr.dims ());\n\n              for (octave_idx_type i = 0; i < cellstr.numel (); i++)\n                {\n                  new_args(0) = cellstr(i);\n                  new_args(1) = cellpat(i);\n\n                  octave_value_list tmp = octregexp (new_args, nargout, who,\n                                                     case_insensitive);\n\n                  for (int j = 0; j < nargout; j++)\n                    newretval[j](i) = tmp(j);\n                }\n            }\n          else\n            error (\"regexp: cell array arguments must be scalar or equal size\");\n        }\n      else\n        {\n          for (int j = 0; j < nargout; j++)\n            newretval[j].resize (cellstr.dims ());\n\n          for (octave_idx_type i = 0; i < cellstr.numel (); i++)\n            {\n              new_args(0) = cellstr(i);\n              octave_value_list tmp = octregexp (new_args, nargout, who,\n                                                 case_insensitive);\n\n              for (int j = 0; j < nargout; j++)\n                newretval[j](i) = tmp(j);\n            }\n        }\n\n      for (int j = 0; j < nargout; j++)\n        retval(j) = octave_value (newretval[j]);\n    }\n  else if (args(1).iscell ())\n    {\n      OCTAVE_LOCAL_BUFFER (Cell, newretval, nargout);\n      octave_value_list new_args = args;\n      Cell cellpat = args(1).cell_value ();\n\n      for (int j = 0; j < nargout; j++)\n        newretval[j].resize (cellpat.dims ());\n\n      for (octave_idx_type i = 0; i < cellpat.numel (); i++)\n        {\n          new_args(1) = cellpat(i);\n          octave_value_list tmp = octregexp (new_args, nargout, who,\n                                             case_insensitive);\n\n          for (int j = 0; j < nargout; j++)\n            newretval[j](i) = tmp(j);\n        }\n\n      for (int j = 0; j < nargout; j++)\n        retval(j) = octave_value (newretval[j]);\n    }\n  else\n    retval = octregexp (args, nargout, who, case_insensitive);\n\n  return retval;\n\n}\n\nDEFUN (regexp, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{s}, @var{e}, @var{te}, @var{m}, @var{t}, @var{nm}, @var{sp}] =} regexp (@var{str}, @var{pat})\n@deftypefnx {} {[@dots{}] =} regexp (@var{str}, @var{pat}, \"@var{opt1}\", @dots{})\nRegular expression string matching.\n\nSearch for @var{pat} in UTF-8 encoded @var{str} and return the positions and\nsubstrings of any matches, or empty values if there are none.\n\nThe matched pattern @var{pat} can include any of the standard regex\noperators, including:\n\n@table @code\n@item .\nMatch any character\n\n@item * + ? @{@}\nRepetition operators, representing\n\n@table @code\n@item *\nMatch zero or more times\n\n@item +\nMatch one or more times\n\n@item ?\nMatch zero or one times\n\n@item @{@var{n}@}\nMatch exactly @var{n} times\n\n@item @{@var{n},@}\nMatch @var{n} or more times\n\n@item @{@var{m},@var{n}@}\nMatch between @var{m} and @var{n} times\n@end table\n\n@item [@dots{}] [^@dots{}]\n\nList operators.  The pattern will match any character listed between\n@qcode{\"[\"} and @qcode{\"]\"}.  If the first character is @qcode{\"^\"} then the\npattern is inverted and any character except those listed between brackets\nwill match.\n\nEscape sequences defined below can also be used inside list operators.  For\nexample, a template for a floating point number might be @code{[-+.\\d]+}.\n\n@item () (?:)\nGrouping operator.  The first form, parentheses only, also creates a token.\n\n@item |\nAlternation operator.  Match one of a choice of regular expressions.  The\nalternatives must be delimited by the grouping operator @code{()} above.\n\n@item ^ $\nAnchoring operators.  Requires pattern to occur at the start (@code{^}) or\nend (@code{$}) of the string.\n@end table\n\nIn addition, the following escaped characters have special meaning.\n\n@table @code\n\n@item \\d\nMatch any digit\n\n@item \\D\nMatch any non-digit\n\n@item \\s\nMatch any whitespace character\n\n@item \\S\nMatch any non-whitespace character\n\n@item \\w\nMatch any word character\n\n@item \\W\nMatch any non-word character\n\n@item \\<\nMatch the beginning of a word\n\n@item \\>\nMatch the end of a word\n\n@item \\B\nMatch within a word\n@end table\n\nImplementation Note: For compatibility with @sc{matlab}, escape sequences\nin @var{pat} (e.g., @qcode{\"@backslashchar{}n\"} => newline) are expanded\neven when @var{pat} has been defined with single quotes.  To disable\nexpansion use a second backslash before the escape sequence (e.g.,\n\"@backslashchar{}@backslashchar{}n\") or use the @code{regexptranslate}\nfunction.\n\nThe outputs of @code{regexp} default to the order given below\n\n@table @var\n@item s\nThe start indices of each matching substring\n\n@item e\nThe end indices of each matching substring\n\n@item te\nThe extents of each matched token surrounded by @code{(@dots{})} in\n@var{pat}\n\n@item m\nA cell array of the text of each match\n\n@item t\nA cell array of the text of each token matched\n\n@item nm\nA structure containing the text of each matched named token, with the name\nbeing used as the fieldname.  A named token is denoted by\n@code{(?<name>@dots{})}.\n\n@item sp\nA cell array of the text not returned by match, i.e., what remains if you\nsplit the string based on @var{pat}.\n@end table\n\nParticular output arguments, or the order of the output arguments, can be\nselected by additional @var{opt} arguments.  These are strings and the\ncorrespondence between the output arguments and the optional argument\nare\n\n@multitable @columnfractions 0.2 0.3 0.3 0.2\n@item @tab @qcode{'start'}        @tab @var{s}  @tab\n@item @tab @qcode{'end'}          @tab @var{e}  @tab\n@item @tab @qcode{'tokenExtents'} @tab @var{te} @tab\n@item @tab @qcode{'match'}        @tab @var{m}  @tab\n@item @tab @qcode{'tokens'}       @tab @var{t}  @tab\n@item @tab @qcode{'names'}        @tab @var{nm} @tab\n@item @tab @qcode{'split'}        @tab @var{sp} @tab\n@end multitable\n\nAdditional arguments are summarized below.\n\n@table @samp\n@item once\nReturn only the first occurrence of the pattern.\n\n@item matchcase\nMake the matching case sensitive.  (default)\n\nAlternatively, use (?-i) in the pattern.\n\n@item ignorecase\nIgnore case when matching the pattern to the string.\n\nAlternatively, use (?i) in the pattern.\n\n@item stringanchors\nMatch the anchor characters at the beginning and end of the string.\n(default)\n\nAlternatively, use (?-m) in the pattern.\n\n@item lineanchors\nMatch the anchor characters at the beginning and end of the line.\n\nAlternatively, use (?m) in the pattern.\n\n@item dotall\nThe pattern @code{.} matches all characters including the newline character.\n (default)\n\nAlternatively, use (?s) in the pattern.\n\n@item dotexceptnewline\nThe pattern @code{.} matches all characters except the newline character.\n\nAlternatively, use (?-s) in the pattern.\n\n@item literalspacing\nAll characters in the pattern, including whitespace, are significant and are\nused in pattern matching.  (default)\n\nAlternatively, use (?-x) in the pattern.\n\n@item freespacing\nThe pattern may include arbitrary whitespace and also comments beginning\nwith the character @samp{#}.\n\nAlternatively, use (?x) in the pattern.\n\n@item noemptymatch\nZero-length matches are not returned.  (default)\n\n@item emptymatch\nReturn zero-length matches.\n\n@code{regexp ('a', 'b*', 'emptymatch')} returns @code{[1 2]} because there\nare zero or more @qcode{'b'} characters at positions 1 and end-of-string.\n\n@end table\n\nStack Limitation Note: Pattern searches are done with a recursive function\nwhich can overflow the program stack when there are a high number of matches.\nFor example,\n\n@example\n@code{regexp (repmat ('a', 1, 1e5), '(a)+')}\n@end example\n\n@noindent\nmay lead to a segfault.  As an alternative, consider constructing pattern\nsearches that reduce the number of matches (e.g., by creatively using set\ncomplement), and then further processing the return variables (now reduced in\nsize) with successive @code{regexp} searches.\n\nOctave's @code{regexp} implementation is based on the Perl Compatible\nRegular Expressions library (@url{https://www.pcre.org/}).  For a more\ncomprehensive list of @code{regexp} operator syntax see the\n@url{https://www.pcre.org/current/doc/html/pcre2syntax.html,,\n\"PCRE Syntax quick-reference summary\"}.\n\n@seealso{regexpi, strfind, regexprep}\n@end deftypefn */)\n{\n  if (args.length () < 2)\n    print_usage ();\n\n  octave_value_list retval;\n\n  if (args(0).iscell () || args(1).iscell ())\n    retval = (octcellregexp (args, (nargout > 0 ? nargout : 1), \"regexp\"));\n  else\n    retval = octregexp (args, nargout, \"regexp\");\n\n  return retval;\n}\n\n/*\n## PCRE_ERROR_MATCHLIMIT test\n%!test\n%! s = sprintf ('\\t4\\n0000\\t-0.00\\t-0.0000\\t4\\t-0.00\\t-0.0000\\t4\\n0000\\t-0.00\\t-0.0000\\t0\\t-0.00\\t-');\n%! ws = warning (\"query\");\n%! unwind_protect\n%!   warning (\"off\");\n%!   regexp (s, '(\\s*-*\\d+[.]*\\d*\\s*)+\\n');\n%! unwind_protect_cleanup\n%!   warning (ws);\n%! end_unwind_protect\n\n## segfault test\n%!assert (regexp (\"abcde\", \".\"), [1,2,3,4,5])\n%!assert <*62704> (regexpi('(', '\\(?'), 1)\n## Infinite loop test\n%!assert (isempty (regexp (\"abcde\", \"\")))\n\n## Check that anchoring of pattern works correctly\n%!assert (regexp ('abcabc', '^abc'), 1)\n%!assert (regexp ('abcabc', 'abc$'), 4)\n%!assert (regexp ('abcabc', '^abc$'), zeros (1,0))\n\n## UTF-8 test with character vector \"âé🙂ïõù\"\n%!assert (regexp (char ([195, 162, 195, 169, 240, 159, 153, 130, 195, 175, ...\n%!                       195, 181, 195, 185]), \".\"), [1, 3, 5, 9, 11, 13])\n\n%!test\n%! [s, e, te, m, t] = regexp (' No Match ', 'f(.*)uck');\n%! assert (s, zeros (1,0));\n%! assert (e, zeros (1,0));\n%! assert (te, cell (1,0));\n%! assert (m, cell (1,0));\n%! assert (t, cell (1,0));\n\n%!test\n%! [s, e, te, m, t] = regexp (' FiRetrUck ', 'f(.*)uck');\n%! assert (s, zeros (1,0));\n%! assert (e, zeros (1,0));\n%! assert (te, cell (1,0));\n%! assert (m, cell (1,0));\n%! assert (t, cell (1,0));\n\n%!test\n%! [s, e, te, m, t] = regexp (' firetruck ', 'f(.*)uck');\n%! assert (s, 2);\n%! assert (e, 10);\n%! assert (te{1}, [3, 7]);\n%! assert (m{1}, 'firetruck');\n%! assert (t{1}{1}, 'iretr');\n\n%!test\n%! [s, e, te, m, t] = regexp ('short test string', '\\w*r\\w*');\n%! assert (s, [1, 12]);\n%! assert (e, [5, 17]);\n%! assert (size (te), [1, 2]);\n%! assert (isempty (te{1}));\n%! assert (isempty (te{2}));\n%! assert (m{1}, 'short');\n%! assert (m{2}, 'string');\n%! assert (size (t), [1, 2]);\n%! assert (isempty (t{1}));\n%! assert (isempty (t{2}));\n\n%!test\n%! [s, e, te, m, t] = regexp ('short test string', '\\w*r\\w*', 'once');\n%! assert (s, 1);\n%! assert (e, 5);\n%! assert (isempty (te));\n%! assert (m, 'short');\n%! assert (isempty (t));\n\n%!test\n%! [m, te, e, s, t] = regexp ('short test string', '\\w*r\\w*', 'once', 'match', 'tokenExtents', 'end', 'start', 'tokens');\n%! assert (s, 1);\n%! assert (e, 5);\n%! assert (isempty (te));\n%! assert (m, 'short');\n%! assert (isempty (t));\n\n%!test\n%! [s, e, te, m, t, nm] = regexp ('short test string', '(?<word1>\\w*t)\\s*(?<word2>\\w*t)');\n%! assert (s, 1);\n%! assert (e, 10);\n%! assert (size (te), [1, 1]);\n%! assert (te{1}, [1,5; 7,10]);\n%! assert (m{1}, 'short test');\n%! assert (size (t), [1, 1]);\n%! assert (t{1}{1}, 'short');\n%! assert (t{1}{2}, 'test');\n%! assert (size (nm), [1, 1]);\n%! assert (! isempty (fieldnames (nm)));\n%! assert (sort (fieldnames (nm)), {'word1';'word2'});\n%! assert (nm.word1, 'short');\n%! assert (nm.word2, 'test');\n\n%!test\n%! [nm, m, te, e, s, t] = regexp ('short test string', '(?<word1>\\w*t)\\s*(?<word2>\\w*t)', 'names', 'match', 'tokenExtents', 'end', 'start', 'tokens');\n%! assert (s, 1);\n%! assert (e, 10);\n%! assert (size (te), [1, 1]);\n%! assert (te{1}, [1,5; 7,10]);\n%! assert (m{1}, 'short test');\n%! assert (size (t), [1, 1]);\n%! assert (t{1}{1}, 'short');\n%! assert (t{1}{2}, 'test');\n%! assert (size (nm), [1, 1]);\n%! assert (! isempty (fieldnames (nm)));\n%! assert (sort (fieldnames (nm)), {'word1';'word2'});\n%! assert (nm.word1, 'short');\n%! assert (nm.word2, 'test');\n\n%!test\n%! [t, nm] = regexp (\"John Davis\\nRogers, James\", '(?<first>\\w+)\\s+(?<last>\\w+)|(?<last>\\w+),\\s+(?<first>\\w+)', 'tokens', 'names');\n%! assert (size (t), [1, 2]);\n%! assert (t{1}{1}, \"John\");\n%! assert (t{1}{2}, \"Davis\");\n%! assert (t{2}{1}, \"Rogers\");\n%! assert (t{2}{2}, \"James\");\n%! assert (size (nm), [1, 2]);\n%! assert (nm(1).first, \"John\");\n%! assert (nm(1).last, \"Davis\");\n%! assert (nm(2).first, \"James\");\n%! assert (nm(2).last, \"Rogers\");\n\n## Tests for nulls in strings properly matching\n%!test\n%! str = \"A\\0B\\0\\0C\";\n%! ptn = '(\\0+)';  # also test null in single-quote pattern\n%! M = regexp (str, ptn, \"match\");\n%! assert (size (M), [1, 2]);\n%! assert (double (M{1}), [0]);\n%! assert (double (M{2}), [0, 0]);\n\n%!test\n%! str = \"A\\0B\\0\\0C\";\n%! ptn = \"(\\0+)\";  # also test null in double-quote pattern\n%! T = regexp (str, ptn, \"tokens\");\n%! assert (size (T), [1, 2]);\n%! assert (double (T{1}{1}), [0]);\n%! assert (double (T{2}{1}), [0, 0]);\n\n%!test\n%! str = \"A\\0B\\0\\0C\";\n%! ptn = '(?<namedtoken>\\0+)';\n%! NT = regexp (str, ptn, \"names\");\n%! assert (size (NT), [1, 2]);\n%! assert (double (NT(1).namedtoken), [0]);\n%! assert (double (NT(2).namedtoken), [0, 0]);\n\n## Tests for named tokens\n%!test\n%! ## Parenthesis in named token (ie (int)) causes a problem\n%! assert (regexp ('qwe int asd', ['(?<typestr>(int))'], 'names'),\n%!         struct ('typestr', 'int'));\n\n%!test <*35683>\n%! ## Mix of named and unnamed tokens can cause segfault\n%! str = \"abcde\";\n%! ptn = '(?<T1>a)(\\w+)(?<T2>d\\w+)';\n%! tokens = regexp (str, ptn, \"names\");\n%! assert (isstruct (tokens) && numel (tokens) == 1);\n%! assert (tokens.T1, \"a\");\n%! assert (tokens.T2, \"de\");\n\n## Test options to regexp\n%!assert (regexp (\"abc\\nabc\", '.'), [1:7])\n%!assert (regexp (\"abc\\nabc\", '.', 'dotall'), [1:7])\n%!test\n%! assert (regexp (\"abc\\nabc\", '(?s).'), [1:7]);\n%! assert (regexp (\"abc\\nabc\", '.', 'dotexceptnewline'), [1,2,3,5,6,7]);\n%! assert (regexp (\"abc\\nabc\", '(?-s).'), [1,2,3,5,6,7]);\n\n%!assert (regexp (\"caseCaSe\", 'case'), 1)\n%!assert (regexp (\"caseCaSe\", 'case', \"matchcase\"), 1)\n%!assert (regexp (\"caseCaSe\", 'case', \"ignorecase\"), [1,5])\n%!test\n%! assert (regexp (\"caseCaSe\", '(?-i)case'), 1);\n%! assert (regexp (\"caseCaSe\", '(?i)case'), [1, 5]);\n\n%!assert (regexp (\"abc\\nabc\", 'c$'), 7)\n%!assert (regexp (\"abc\\nabc\", 'c$', \"stringanchors\"), 7)\n%!test\n%! assert (regexp (\"abc\\nabc\", '(?-m)c$'), 7);\n%! assert (regexp (\"abc\\nabc\", 'c$',\"lineanchors\"), [3, 7]);\n%! assert (regexp (\"abc\\nabc\", '(?m)c$'), [3,7]);\n\n%!assert (regexp (\"this word\", 's w'), 4)\n%!assert (regexp (\"this word\", 's w', 'literalspacing'), 4)\n%!test\n%! assert (regexp (\"this word\", '(?-x)s w', 'literalspacing'), 4);\n%! assert (regexp (\"this word\", 's w', 'freespacing'), zeros (1,0));\n%! assert (regexp (\"this word\", '(?x)s w'), zeros (1,0));\n\n%!test\n%! [s, e, te, m, t, nm, sp] = regexp ('OCTAVE', '[VOCT]*', 'noemptymatch');\n%! assert (s, [1 5]);\n%! assert (e, [3 5]);\n%! assert (te, { zeros(0,2), zeros(0,2) });\n%! assert (m, { \"OCT\", \"V\" });\n%! assert (t, { cell(1,0), cell(1,0) });\n%! assert (isempty (fieldnames (nm)));\n%! assert (sp, { \"\", \"A\", \"E\" });\n\n%!test\n%! [s, e, te, m, t, nm, sp] = regexp ('OCTAVE', '([VOCT]*)', 'noemptymatch');\n%! assert (s, [1 5]);\n%! assert (e, [3 5]);\n%! assert (te, { [1 3], [5 5] });\n%! assert (m, { \"OCT\", \"V\" });\n%! assert (t, { {\"OCT\"}, {\"V\"} });\n%! assert (isempty (fieldnames (nm)));\n%! assert (sp, { \"\", \"A\", \"E\" });\n\n%!test\n%! [s, e, te, m, t, nm, sp] = regexp ('OCTAVE', '[VOCT]*', 'emptymatch');\n%! assert (s, [1 4 5 6 7]);\n%! assert (e, [3 3 5 5 6]);\n%! assert (te, repmat ({zeros(0,2)}, [1, 5]));\n%! assert (m, { \"OCT\", \"\", \"V\", \"\", \"\" });\n%! assert (t, repmat({cell(1,0)}, [1, 5]));\n%! assert (isempty (fieldnames (nm)));\n%! assert (sp, { \"\", \"\", \"A\", \"\", \"E\", \"\" });\n\n%!test\n%! [s, e, te, m, t, nm, sp] = regexp ('OCTAVE', '([VOCT]*)', 'emptymatch');\n%! assert (s, [1 4 5 6 7]);\n%! assert (e, [3 3 5 5 6]);\n%! assert (te, { [1 3], [4 3], [5 5], [6 5], [7 6] });\n%! assert (m, { \"OCT\", \"\", \"V\", \"\", \"\" });\n%! assert (t, { {\"OCT\"}, {\"\"}, {\"V\"}, {\"\"}, {\"\"} });\n%! assert (isempty (fieldnames (nm)));\n%! assert (sp, { \"\", \"\", \"A\", \"\", \"E\", \"\" });\n\n%!assert (regexp ({'asdfg-dfd';'-dfd-dfd-';'qasfdfdaq'}, '-'),\n%!        {6;[1,5,9];zeros(1,0)})\n%!assert (regexp ({'asdfg-dfd';'-dfd-dfd-';'qasfdfdaq'}, {'-';'f';'q'}),\n%!        {6;[3,7];[1,9]})\n%!assert (regexp ('Strings', {'t','s'}), {2, 7})\n\n## Test case for lookaround operators\n%!test\n%! assert (regexp ('Iraq', 'q(?!u)'), 4);\n%! assert (regexp ('quit', 'q(?!u)'), zeros (1, 0));\n%! assert (regexp ('quit', 'q(?=u)' , 'match'), {'q'});\n%! assert (regexp (\"quit\", 'q(?=u+)', 'match'), {'q'});\n%! assert (regexp (\"qit\",  'q(?=u+)', 'match'), cell (1, 0));\n%! assert (regexp (\"qit\",  'q(?=u*)', 'match'), {'q'});\n%! assert (regexp ('thingamabob', '(?<=a)b'), 9);\n\n## Tests for split option.\n%!shared str\n%! str = \"foo bar foo\";\n%!test\n%! [a, b] = regexp (str, \"f..\", \"match\", \"split\");\n%! assert (a, {\"foo\", \"foo\"});\n%! assert (b, {\"\", \" bar \", \"\"});\n%!test\n%! [a, b] = regexp (str, \"f..\", \"match\", \"split\", \"once\");\n%! assert (a, \"foo\");\n%! assert (b, {\"\", \" bar foo\"});\n%!test\n%! [a, b] = regexp (str, \"fx.\", \"match\", \"split\");\n%! assert (a, cell (1, 0));\n%! assert (b, {\"foo bar foo\"});\n%!test\n%! [a, b] = regexp (str, \"fx.\", \"match\", \"split\", \"once\");\n%! assert (a, \"\");\n%! assert (b, \"foo bar foo\");\n\n%!shared str\n%! str = \"foo bar\";\n%!test\n%! [a, b] = regexp (str, \"f..\", \"match\", \"split\");\n%! assert (a, {\"foo\"});\n%! assert (b, {\"\", \" bar\"});\n%!test\n%! [a, b] = regexp (str, \"b..\", \"match\", \"split\");\n%! assert (a, {\"bar\"});\n%! assert (b, {\"foo \", \"\"});\n%!test\n%! [a, b] = regexp (str, \"x\", \"match\", \"split\");\n%! assert (a, cell (1, 0));\n%! assert (b, {\"foo bar\"});\n%!test\n%! [a, b] = regexp (str, \"[o]+\", \"match\", \"split\");\n%! assert (a, {\"oo\"});\n%! assert (b, {\"f\", \" bar\"});\n\n## Test escape sequences are expanded even in single-quoted strings\n%!assert (regexp (\"\\n\", '\\n'), 1)\n%!assert (regexp (\"\\n\", \"\\n\"), 1)\n\n## Test escape sequences are silently converted\n%!test <*45407>\n%! assert (regexprep ('s', 's', 'x\\.y'), 'x.y');\n%! assert (regexprep ('s', '(s)', 'x\\$1y'), 'x$1y');\n%! assert (regexprep ('s', '(s)', 'x\\\\$1y'), 'x\\sy');\n\n## Test start-of-word / end-of-word patterns for Matlab compatibility\n%!test <*59992>\n%! assert (regexp ('foo!+bar', '\\<\\w'), [1, 6]);\n%! assert (regexp ('foo!+bar', '.\\>'), [3, 4, 8]);\n%! assert (regexp ('foo!+bar\\nbar!+foo', '.\\>'), [3, 4, 8, 13, 14, 18]);\n%! assert (regexp ('foo!+bar\\nbar!+foo', '\\<\\w'), [1, 6, 10, 16]);\n\n## Test \"incomplete\" named patterns\n%!assert <*62705> (regexpi ('<', '\\(?<'), 1)\n%!assert <*62705> (regexpi ('<n>', '\\(?<n\\>'), 1)\n%!assert <*62705> (regexpi ('<n>', '\\(?<n\\>\\)?'), 1)\n%!assert <62705> (regexpi ('<n>a', '\\(?<n\\>a\\)?'), 1)\n\n## Test input validation\n%!error regexp ('string', 'tri', 'BadArg')\n%!error regexp ('string')\n\n*/\n\nDEFUN (regexpi, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{s}, @var{e}, @var{te}, @var{m}, @var{t}, @var{nm}, @var{sp}] =} regexpi (@var{str}, @var{pat})\n@deftypefnx {} {[@dots{}] =} regexpi (@var{str}, @var{pat}, \"@var{opt1}\", @dots{})\n\nCase insensitive regular expression string matching.\n\nSearch for @var{pat} in UTF-8 encoded @var{str} and return the positions and\nsubstrings of any matches, or empty values if there are none.\n@xref{XREFregexp,,regexp}, for details on the syntax of the search pattern.\n@seealso{regexp}\n@end deftypefn */)\n{\n  if (args.length () < 2)\n    print_usage ();\n\n  if (args(0).iscell () || args(1).iscell ())\n    return octcellregexp (args, (nargout > 0 ? nargout : 1), \"regexpi\", true);\n  else\n    return octregexp (args, nargout, \"regexpi\", true);\n}\n\n/*\n## segfault test\n%!assert (regexpi (\"abcde\", \".\"), [1,2,3,4,5])\n\n## Check that anchoring of pattern works correctly\n%!assert (regexpi ('abcabc', '^ABC'), 1)\n%!assert (regexpi ('abcabc', 'ABC$'), 4)\n%!assert (regexpi ('abcabc', '^ABC$'), zeros (1,0))\n\n%!test\n%! [s, e, te, m, t] = regexpi (' No Match ', 'f(.*)uck');\n%! assert (s, zeros (1,0));\n%! assert (e, zeros (1,0));\n%! assert (te, cell (1,0));\n%! assert (m, cell (1,0));\n%! assert (t, cell (1,0));\n\n%!test\n%! [s, e, te, m, t] = regexpi (' FiRetrUck ', 'f(.*)uck');\n%! assert (s, 2);\n%! assert (e, 10);\n%! assert (te{1}, [3, 7]);\n%! assert (m{1}, 'FiRetrUck');\n%! assert (t{1}{1}, 'iRetr');\n\n%!test\n%! [s, e, te, m, t] = regexpi (' firetruck ', 'f(.*)uck');\n%! assert (s, 2);\n%! assert (e, 10);\n%! assert (te{1}, [3, 7]);\n%! assert (m{1}, 'firetruck');\n%! assert (t{1}{1}, 'iretr');\n\n%!test\n%! [s, e, te, m, t] = regexpi ('ShoRt Test String', '\\w*r\\w*');\n%! assert (s, [1, 12]);\n%! assert (e, [5, 17]);\n%! assert (size (te), [1, 2]);\n%! assert (isempty (te{1}));\n%! assert (isempty (te{2}));\n%! assert (m{1}, 'ShoRt');\n%! assert (m{2}, 'String');\n%! assert (size (t), [1, 2]);\n%! assert (isempty (t{1}));\n%! assert (isempty (t{2}));\n\n%!test\n%! [s, e, te, m, t] = regexpi ('ShoRt Test String', '\\w*r\\w*', 'once');\n%! assert (s, 1);\n%! assert (e, 5);\n%! assert (isempty (te));\n%! assert (m, 'ShoRt');\n%! assert (isempty (t));\n\n%!test\n%! [m, te, e, s, t] = regexpi ('ShoRt Test String', '\\w*r\\w*', 'once', 'match', 'tokenExtents', 'end', 'start', 'tokens');\n%! assert (s, 1);\n%! assert (e, 5);\n%! assert (isempty (te));\n%! assert (m, 'ShoRt');\n%! assert (isempty (t));\n\n%!test\n%! [s, e, te, m, t, nm] = regexpi ('ShoRt Test String', '(?<word1>\\w*t)\\s*(?<word2>\\w*t)');\n%! assert (s, 1);\n%! assert (e, 10);\n%! assert (size (te), [1, 1]);\n%! assert (te{1}, [1,5; 7,10]);\n%! assert (m{1}, 'ShoRt Test');\n%! assert (size (t), [1, 1]);\n%! assert (t{1}{1}, 'ShoRt');\n%! assert (t{1}{2}, 'Test');\n%! assert (size (nm), [1, 1]);\n%! assert (! isempty (fieldnames (nm)));\n%! assert (sort (fieldnames (nm)), {'word1';'word2'});\n%! assert (nm.word1, 'ShoRt');\n%! assert (nm.word2, 'Test');\n\n%!test\n%! [nm, m, te, e, s, t] = regexpi ('ShoRt Test String', '(?<word1>\\w*t)\\s*(?<word2>\\w*t)', 'names', 'match', 'tokenExtents', 'end', 'start', 'tokens');\n%! assert (s, 1);\n%! assert (e, 10);\n%! assert (size (te), [1, 1]);\n%! assert (te{1}, [1,5; 7,10]);\n%! assert (m{1}, 'ShoRt Test');\n%! assert (size (t), [1, 1]);\n%! assert (t{1}{1}, 'ShoRt');\n%! assert (t{1}{2}, 'Test');\n%! assert (size (nm), [1, 1]);\n%! assert (! isempty (fieldnames (nm)));\n%! assert (sort (fieldnames (nm)), {'word1';'word2'});\n%! assert (nm.word1, 'ShoRt');\n%! assert (nm.word2, 'Test');\n\n%!assert (regexpi (\"abc\\nabc\", '.'), [1:7])\n%!assert (regexpi (\"abc\\nabc\", '.', 'dotall'), [1:7])\n%!test\n%! assert (regexpi (\"abc\\nabc\", '(?s).'), [1:7]);\n%! assert (regexpi (\"abc\\nabc\", '.', 'dotexceptnewline'), [1,2,3,5,6,7]);\n%! assert (regexpi (\"abc\\nabc\", '(?-s).'), [1,2,3,5,6,7]);\n\n%!assert (regexpi (\"caseCaSe\", 'case'), [1, 5])\n%!assert (regexpi (\"caseCaSe\", 'case', \"matchcase\"), 1)\n%!assert (regexpi (\"caseCaSe\", 'case', \"ignorecase\"), [1, 5])\n%!test\n%! assert (regexpi (\"caseCaSe\", '(?-i)case'), 1);\n%! assert (regexpi (\"caseCaSe\", '(?i)case'), [1, 5]);\n\n%!assert (regexpi (\"abc\\nabc\", 'C$'), 7)\n%!assert (regexpi (\"abc\\nabc\", 'C$', \"stringanchors\"), 7)\n%!test\n%! assert (regexpi (\"abc\\nabc\", '(?-m)C$'), 7);\n%! assert (regexpi (\"abc\\nabc\", 'C$', \"lineanchors\"), [3, 7]);\n%! assert (regexpi (\"abc\\nabc\", '(?m)C$'), [3, 7]);\n\n%!assert (regexpi (\"this word\", 'S w'), 4)\n%!assert (regexpi (\"this word\", 'S w', 'literalspacing'), 4)\n%!test\n%! assert (regexpi (\"this word\", '(?-x)S w', 'literalspacing'), 4);\n%! assert (regexpi (\"this word\", 'S w', 'freespacing'), zeros (1,0));\n%! assert (regexpi (\"this word\", '(?x)S w'), zeros (1,0));\n\n%!error regexpi ('string', 'tri', 'BadArg')\n%!error regexpi ('string')\n\n%!assert (regexpi ({'asdfg-dfd';'-dfd-dfd-';'qasfdfdaq'}, '-'),\n%!        {6;[1,5,9];zeros(1, 0)})\n%!assert (regexpi ({'asdfg-dfd', '-dfd-dfd-', 'qasfdfdaq'}, '-'),\n%!        {6, [1,5,9], zeros(1,0)})\n%!assert (regexpi ({'asdfg-dfd';'-dfd-dfd-';'qasfdfdaq'}, {'-';'f';'q'}),\n%!        {6;[3,7];[1,9]})\n%!assert (regexpi ('Strings', {'t', 's'}), {2, [1, 7]})\n\n%!assert (regexpi (\"\\n\", '\\n'), 1)\n%!assert (regexpi (\"\\n\", \"\\n\"), 1)\n*/\n\nstatic octave_value\noctregexprep (const octave_value_list& args, const std::string& who)\n{\n  int nargin = args.length ();\n\n  // Make sure we have string, pattern, replacement\n  const std::string buffer = args(0).string_value ();\n\n  std::string pattern = args(1).string_value ();\n\n  // Rewrite pattern for PCRE\n  pattern = do_regexp_ptn_string_escapes (pattern, args(1).is_sq_string ());\n\n  std::string replacement = args(2).string_value ();\n\n  // Matlab compatibility.\n  if (args(2).is_sq_string ())\n    replacement = do_regexp_rep_string_escapes (replacement);\n\n  // Pack options excluding 'tokenize' and various output\n  // reordering strings into regexp arg list\n  octave_value_list regexpargs (nargin-3, octave_value ());\n\n  int len = 0;\n  for (int i = 3; i < nargin; i++)\n    {\n      const std::string opt = args(i).string_value ();\n      if (opt != \"tokenize\" && opt != \"start\" && opt != \"end\"\n          && opt != \"tokenextents\" && opt != \"match\" && opt != \"tokens\"\n          && opt != \"names\"  && opt != \"split\" && opt != \"warnings\")\n        {\n          regexpargs(len++) = args(i);\n        }\n    }\n  regexpargs.resize (len);\n\n  regexp::opts options;\n  bool extra_args = false;\n  parse_options (options, regexpargs, who, 0, extra_args);\n\n  return regexp::replace (pattern, buffer, replacement, options, who);\n}\n\nDEFUN (regexprep, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{outstr} =} regexprep (@var{string}, @var{pat}, @var{repstr})\n@deftypefnx {} {@var{outstr} =} regexprep (@var{string}, @var{pat}, @var{repstr}, \"@var{opt1}\", @dots{})\nReplace occurrences of pattern @var{pat} in @var{string} with @var{repstr}.\n\nThe pattern is a regular expression as documented for @code{regexp}.\n@xref{XREFregexp,,regexp}.\n\nAll strings must be UTF-8 encoded.\n\nThe replacement string may contain @code{$i}, which substitutes for the ith\nset of parentheses in the match string.  For example,\n\n@example\nregexprep (\"Bill Dunn\", '(\\w+) (\\w+)', '$2, $1')\n@end example\n\n@noindent\nreturns @qcode{\"Dunn, Bill\"}\n\nOptions in addition to those of @code{regexp} are\n\n@table @samp\n\n@item once\nReplace only the first occurrence of @var{pat} in the result.\n\n@item warnings\nThis option is present for compatibility but is ignored.\n\n@end table\n\nImplementation Note: For compatibility with @sc{matlab}, escape sequences\nin @var{pat} (e.g., @qcode{\"@backslashchar{}n\"} => newline) are expanded\neven when @var{pat} has been defined with single quotes.  To disable\nexpansion use a second backslash before the escape sequence (e.g.,\n\"@backslashchar{}@backslashchar{}n\") or use the @code{regexptranslate}\nfunction.\n@seealso{regexp, regexpi, strrep}\n@end deftypefn */)\n{\n  if (args.length () < 3)\n    print_usage ();\n\n  octave_value_list retval;\n\n  if (args(0).iscell () || args(1).iscell () || args(2).iscell ())\n    {\n      Cell str, pat, rep;\n      dim_vector dv0;\n      dim_vector dv1 (1, 1);\n\n      if (args(0).iscell ())\n        str = args(0).cell_value ();\n      else\n        str = Cell (args(0));\n\n      if (args(1).iscell ())\n        pat = args(1).cell_value ();\n      else\n        pat = Cell (args(1));\n\n      if (args(2).iscell ())\n        rep = args(2).cell_value ();\n      else\n        rep = Cell (args(2));\n\n      dv0 = str.dims ();\n      if (pat.numel () != 1)\n        {\n          dv1 = pat.dims ();\n          if (rep.numel () != 1 && dv1 != rep.dims ())\n            error (\"regexprep: inconsistent cell array dimensions\");\n        }\n      else if (rep.numel () != 1)\n        dv1 = rep.dims ();\n\n      Cell ret (dv0);\n      octave_value_list new_args = args;\n\n      for (octave_idx_type i = 0; i < dv0.numel (); i++)\n        {\n          new_args(0) = str(i);\n          if (pat.numel () == 1)\n            new_args(1) = pat(0);\n          if (rep.numel () == 1)\n            new_args(2) = rep(0);\n\n          for (octave_idx_type j = 0; j < dv1.numel (); j++)\n            {\n              if (pat.numel () != 1)\n                new_args(1) = pat(j);\n              if (rep.numel () != 1)\n                new_args(2) = rep(j);\n              new_args(0) = octregexprep (new_args, \"regexprep\");\n            }\n\n          ret(i) = new_args(0);\n        }\n\n      retval = (args(0).iscell () ? ovl (ret) : ovl (ret(0)));\n    }\n  else\n    retval = octregexprep (args, \"regexprep\");\n\n  return retval;\n}\n\n/*\n%!test  # Replace with empty\n%! xml = '<!-- This is some XML --> <tag v=\"hello\">some stuff<!-- sample tag--></tag>';\n%! t = regexprep (xml, '<[!?][^>]*>', '');\n%! assert (t, ' <tag v=\"hello\">some stuff</tag>');\n\n%!test  # Replace with non-empty\n%! xml = '<!-- This is some XML --> <tag v=\"hello\">some stuff<!-- sample tag--></tag>';\n%! t = regexprep (xml, '<[!?][^>]*>', '?');\n%! assert (t, '? <tag v=\"hello\">some stuff?</tag>');\n\n%!test  # Check that 'tokenize' is ignored\n%! xml = '<!-- This is some XML --> <tag v=\"hello\">some stuff<!-- sample tag--></tag>';\n%! t = regexprep (xml, '<[!?][^>]*>', '', 'tokenize');\n%! assert (t, ' <tag v=\"hello\">some stuff</tag>');\n\n## Test capture replacement\n%!test\n%! data = \"Bob Smith\\nDavid Hollerith\\nSam Jenkins\";\n%! result = \"Smith, Bob\\nHollerith, David\\nJenkins, Sam\";\n%! t = regexprep (data, '(?m)^(\\w+)\\s+(\\w+)$', '$2, $1');\n%! assert (t, result);\n\n## Return the original if no match\n%!assert (regexprep ('hello', 'world', 'earth'), 'hello')\n\n## Test emptymatch option\n%!assert (regexprep ('World', '^', 'Hello '), 'World')\n%!assert (regexprep ('World', '^', 'Hello ', 'emptymatch'), 'Hello World')\n\n## Test a general replacement\n%!assert (regexprep (\"a[b]c{d}e-f=g\", \"[^A-Za-z0-9_]\", \"_\"), \"a_b_c_d_e_f_g\")\n\n## Make sure replacements work at the beginning and end of string\n%!assert (regexprep (\"a[b]c{d}e-f=g\", \"a\", \"_\"), \"_[b]c{d}e-f=g\")\n%!assert (regexprep (\"a[b]c{d}e-f=g\", \"g\", \"_\"), \"a[b]c{d}e-f=_\")\n\n## Test options \"once\" and \"ignorecase\"\n%!assert (regexprep (\"a[b]c{d}e-f=g\", \"[^A-Za-z0-9_]\", \"_\", \"once\"),\n%!        \"a_b]c{d}e-f=g\")\n%!assert (regexprep (\"a[b]c{d}e-f=g\", \"[^A-Z0-9_]\", \"_\", \"ignorecase\"),\n%!        \"a_b_c_d_e_f_g\")\n\n## Option combinations\n%!assert (regexprep (\"a[b]c{d}e-f=g\", \"[^A-Z0-9_]\", \"_\", \"once\", \"ignorecase\"),\n%!        \"a_b]c{d}e-f=g\")\n\n## End conditions on replacement\n%!assert (regexprep (\"abc\", \"(b)\", \".$1\"), \"a.bc\")\n%!assert (regexprep (\"abc\", \"(b)\", \"$1\"), \"abc\")\n%!assert (regexprep (\"abc\", \"(b)\", \"$1.\"), \"ab.c\")\n%!assert (regexprep (\"abc\", \"(b)\", \"$1..\"), \"ab..c\")\n\n## Test cell array arguments\n%!assert (regexprep (\"abc\", {\"b\",\"a\"}, \"?\"), \"??c\")\n%!assert (regexprep ({\"abc\",\"cba\"}, \"b\", \"?\"), {\"a?c\",\"c?a\"})\n%!assert (regexprep ({\"abc\",\"cba\"}, {\"b\",\"a\"}, {\"?\",\"!\"}), {\"!?c\",\"c?!\"})\n\n## Nasty lookbehind expression\n%!test\n%! warning (\"off\", \"Octave:regexp-lookbehind-limit\", \"local\");\n%! assert (regexprep ('x^(-1)+y(-1)+z(-1)=0', '(?<=[a-z]+)\\(\\-[1-9]*\\)',\n%!         '_minus1'),'x^(-1)+y_minus1+z_minus1=0');\n\n## Verify escape sequences in pattern\n%!assert (regexprep (\"\\n\", '\\n', \"X\"), \"X\")\n%!assert (regexprep (\"\\n\", \"\\n\", \"X\"), \"X\")\n\n## Verify NULLs in pattern and replacement string\n%!assert (regexprep (\"A\\0A\", \"\\0\", \",\"), \"A,A\")\n%!assert (regexprep (\"A\\0A\", '\\0', \",\"), \"A,A\")\n%!assert (regexprep (\"A,A\", \"A\", \"B\\0B\"), \"B\\0B,B\\0B\")\n%!assert (regexprep (\"A,A\", \"A\", 'B\\0B'), \"B\\0B,B\\0B\")\n\n## Empty matches were broken on ARM architecture\n%!test <*52810>\n%! assert (strcmp (regexprep (\"\\nabc\", \"^(\\t*)(abc)$\", \"$1$2\", \"lineanchors\"),\n%!                 \"\\nabc\"));\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/strfind.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <deque>\n#include <limits>\n#include <string>\n\n#include \"oct-locbuf.h\"\n\n#include \"Cell.h\"\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"error.h\"\n#include \"ov.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// This allows safe indexing with char.\n// In C++, char may be (and often is) signed!\n#define ORD(ch) static_cast<unsigned char> (ch)\n#define TABSIZE (std::numeric_limits<unsigned char>::max () + 1)\n\n// This is the quick search algorithm, as described at\n// http://www-igm.univ-mlv.fr/~lecroq/string/node19.html\nstatic void\nqs_preprocess (const Array<char>& needle,\n               octave_idx_type *table)\n{\n  const char *x = needle.data ();\n  octave_idx_type m = needle.numel ();\n\n  for (octave_idx_type i = 0; i < TABSIZE; i++)\n    table[i] = m + 1;\n  for (octave_idx_type i = 0; i < m; i++)\n    table[ORD(x[i])] = m - i;\n}\n\nstatic Array<octave_idx_type>\nqs_search (const Array<char>& needle,\n           const Array<char>& haystack,\n           const octave_idx_type *table,\n           bool overlaps = true)\n{\n  const char *x = needle.data ();\n  octave_idx_type m = needle.numel ();\n  const char *y = haystack.data ();\n  octave_idx_type n = haystack.numel ();\n\n  // We'll use deque because it typically has the most favorable properties for\n  // the operation we need.\n  std::deque<octave_idx_type> accum;\n  if (m == 1)\n    {\n      // Looking for a single character.\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          if (y[i] == x[0])\n            accum.push_back (i);\n        }\n    }\n  else if (m == 2)\n    {\n      // Two characters.\n      if (overlaps)\n        {\n          for (octave_idx_type i = 0; i < n-1; i++)\n            {\n              if (y[i] == x[0] && y[i+1] == x[1])\n                accum.push_back (i);\n            }\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < n-1; i++)\n            {\n              if (y[i] == x[0] && y[i+1] == x[1])\n                accum.push_back (i++);\n            }\n        }\n    }\n  else if (n >= m)\n    {\n      // General case.\n      octave_idx_type j = 0;\n\n      if (overlaps)\n        {\n          while (j < n - m)\n            {\n              if (std::equal (x, x + m, y + j))\n                accum.push_back (j);\n              j += table[ORD(y[j + m])];\n            }\n        }\n      else\n        {\n          while (j < n - m)\n            {\n              if (std::equal (x, x + m, y + j))\n                {\n                  accum.push_back (j);\n                  j += m;\n                }\n              else\n                j += table[ORD(y[j + m])];\n            }\n        }\n\n      if (j == n - m && std::equal (x, x + m, y + j))\n        accum.push_back (j);\n    }\n\n  octave_idx_type nmatch = accum.size ();\n  octave_idx_type one = 1;\n  Array<octave_idx_type> result (dim_vector (std::min (one, nmatch), nmatch));\n  octave_idx_type k = 0;\n  for (const auto& idx : accum)\n    result.xelem (k++) = idx;\n\n  return result;\n}\n\nDEFUN (strfind, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{idx} =} strfind (@var{str}, @var{pattern})\n@deftypefnx {} {@var{idx} =} strfind (@var{cellstr}, @var{pattern})\n@deftypefnx {} {@var{idx} =} strfind (@dots{}, \"overlaps\", @var{val})\n@deftypefnx {} {@var{idx} =} strfind (@dots{}, \"forcecelloutput\", @var{val})\nSearch for @var{pattern} in the string @var{str} and return the starting\nindex of every such occurrence in the vector @var{idx}.\n\nIf there is no such occurrence, or if @var{pattern} is longer than\n@var{str}, or if @var{pattern} itself is empty, then @var{idx} is the empty\narray @code{[]}.\n\nThe optional argument @qcode{\"overlaps\"} determines whether the pattern\ncan match at every position in @var{str} (true), or only for unique\noccurrences of the complete pattern (false).  The default is true.\n\nIf a cell array of strings @var{cellstr} is specified then @var{idx} is a\ncell array of vectors, as specified above.\n\nThe optional argument @qcode{\"forcecelloutput\"} forces @var{idx} to be\nreturned as a cell array of vectors.  The default is false.\n\nExamples:\n\n@example\n@group\nstrfind (\"abababa\", \"aba\")\n     @xresult{} [1, 3, 5]\n@end group\n\n@group\nstrfind (\"abababa\", \"aba\", \"overlaps\", false)\n     @xresult{} [1, 5]\n@end group\n\n@group\nstrfind (@{\"abababa\", \"bebebe\", \"ab\"@}, \"aba\")\n     @xresult{}\n        @{\n          [1,1] =\n\n             1   3   5\n\n          [1,2] = [](1x0)\n          [1,3] = [](1x0)\n        @}\n@end group\n\n@group\nstrfind (\"abababa\", \"aba\", \"forcecelloutput\", true)\n     @xresult{}\n        @{\n          [1,1] =\n\n             1   3   5\n        @}\n@end group\n@end example\n@seealso{regexp, regexpi, find}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin != 4 && nargin != 2)\n    print_usage ();\n\n  bool overlaps = true;\n  bool forcecelloutput = false;\n  if (nargin == 4)\n    {\n      if (! args(2).is_string () || ! args(3).is_scalar_type ())\n        error (\"strfind: invalid optional arguments\");\n\n      std::string opt = args(2).string_value ();\n      std::transform (opt.begin (), opt.end (), opt.begin (), tolower);\n\n      if (opt == \"overlaps\")\n        overlaps = args(3).bool_value ();\n      else if (opt == \"forcecelloutput\")\n        forcecelloutput = args(3).bool_value ();\n      else\n        error (\"strfind: unknown option: %s\", opt.c_str ());\n    }\n\n  octave_value retval;\n\n  octave_value argstr = args(0);\n  octave_value argpat = args(1);\n\n  if (argpat.is_string ())\n    {\n      Array<char> needle = argpat.char_array_value ();\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, table, TABSIZE);\n      qs_preprocess (needle, table);\n\n      if (argstr.is_string ())\n        {\n          if (argpat.isempty ())\n            // Return a null matrix for null pattern for MW compatibility\n            retval = Matrix ();\n          else\n            retval = octave_value (qs_search (needle,\n                                              argstr.char_array_value (),\n                                              table, overlaps),\n                                   true, true);\n          if (forcecelloutput)\n            retval = Cell (retval);\n        }\n      else if (argstr.iscell ())\n        {\n          const Cell argsc = argstr.cell_value ();\n          Cell retc (argsc.dims ());\n          octave_idx_type ns = argsc.numel ();\n\n          for (octave_idx_type i = 0; i < ns; i++)\n            {\n              octave_value argse = argsc(i);\n              if (! argse.is_string ())\n                error (\"strfind: each element of CELLSTR must be a string\");\n\n              if (argpat.isempty ())\n                retc(i) = Matrix ();\n              else\n                retc(i) = octave_value (qs_search (needle,\n                                                   argse.char_array_value (),\n                                                   table, overlaps),\n                                        true, true);\n            }\n\n          retval = retc;\n        }\n      else\n        error (\"strfind: first argument must be a string or cell array of strings\");\n    }\n  else if (argpat.iscell ())\n    retval = do_simple_cellfun (Fstrfind, \"strfind\", args);\n  else\n    error (\"strfind: PATTERN must be a string or cell array of strings\");\n\n  return retval;\n}\n\n/*\n%!assert (strfind (\"abababa\", \"aba\"), [1, 3, 5])\n%!assert (strfind (\"abababa\", \"aba\", \"overlaps\", false), [1, 5])\n%!assert (strfind (\"abababa\", \"aba\", \"forcecelloutput\", false), [1, 3, 5])\n%!assert (strfind (\"abababa\", \"aba\", \"forcecelloutput\", true), {[1, 3, 5]})\n%!assert (strfind ({\"abababa\", \"bla\", \"bla\"}, \"a\"), {[1, 3, 5, 7], 3, 3})\n%!assert (strfind ({\"abababa\", \"bla\", \"bla\"}, \"a\", \"forcecelloutput\", false),\n%!        {[1, 3, 5, 7], 3, 3})\n%!assert (strfind ({\"abababa\", \"bla\", \"bla\"}, \"a\", \"forcecelloutput\", true),\n%!        {[1, 3, 5, 7], 3, 3})\n%!assert (strfind (\"Linux _is_ user-friendly. It just isn't ignorant-friendly or idiot-friendly.\", \"friendly\"), [17, 50, 68])\n%!assert (strfind (\"abc\", \"\"), [])\n%!assert (strfind (\"abc\", {\"\", \"b\", \"\"}), {[], 2, []})\n%!assert (strfind ({\"abc\", \"def\"}, \"\"), {[], []})\n\n%!error strfind ()\n%!error strfind (\"foo\", \"bar\", 1)\n%!error <unknown option: foobar> strfind (\"foo\", 100, \"foobar\", 1)\n%!error <each element of CELLSTR must be a string> strfind ({\"A\", 1}, \"foo\")\n%!error <first argument must be a string> strfind (100, \"foo\")\n%!error <PATTERN must be a string> strfind (\"foo\", 100)\n*/\n\nstatic Array<char>\nqs_replace (const Array<char>& str, const Array<char>& pat,\n            const Array<char>& rep,\n            const octave_idx_type *table,\n            bool overlaps = true)\n{\n  Array<char> ret = str;\n\n  octave_idx_type siz = str.numel ();\n  octave_idx_type psiz = pat.numel ();\n  octave_idx_type rsiz = rep.numel ();\n\n  if (psiz != 0)\n    {\n      // Look up matches, without overlaps.\n      const Array<octave_idx_type> idx = qs_search (pat, str, table, overlaps);\n      octave_idx_type nidx = idx.numel ();\n\n      if (nidx)\n        {\n          // Compute result size.\n          octave_idx_type retsiz;\n          if (overlaps)\n            {\n              retsiz = 0;\n              // OMG.  Is this the \"right answer\" MW always looks for, or\n              // someone was just lazy?\n              octave_idx_type k = 0;\n              for (octave_idx_type i = 0; i < nidx; i++)\n                {\n                  octave_idx_type j = idx(i);\n                  if (j >= k)\n                    retsiz += j - k;\n                  retsiz += rsiz;\n                  k = j + psiz;\n                }\n\n              retsiz += siz - k;\n            }\n          else\n            retsiz = siz + nidx * (rsiz - psiz);\n\n          if (retsiz == 0)\n            ret.clear (dim_vector (0, 0));\n          else\n            {\n              ret.clear (dim_vector (1, retsiz));\n              const char *src = str.data ();\n              const char *reps = rep.data ();\n              char *dest = ret.rwdata ();\n\n              octave_idx_type k = 0;\n              for (octave_idx_type i = 0; i < nidx; i++)\n                {\n                  octave_idx_type j = idx(i);\n                  if (j >= k)\n                    dest = std::copy (src + k, src + j, dest);\n                  dest = std::copy (reps, reps + rsiz, dest);\n                  k = j + psiz;\n                }\n\n              std::copy (src + k, src + siz, dest);\n            }\n        }\n    }\n\n  return ret;\n}\n\nDEFUN (strrep, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{newstr} =} strrep (@var{str}, @var{ptn}, @var{rep})\n@deftypefnx {} {@var{newstr} =} strrep (@var{cellstr}, @var{ptn}, @var{rep})\n@deftypefnx {} {@var{newstr} =} strrep (@dots{}, \"overlaps\", @var{val})\nReplace all occurrences of the pattern @var{ptn} in the string @var{str}\nwith the string @var{rep} and return the result.\n\nThe optional argument @qcode{\"overlaps\"} determines whether the pattern\ncan match at every position in @var{str} (true), or only for unique\noccurrences of the complete pattern (false).  The default is true.\n\n@var{s} may also be a cell array of strings, in which case the replacement\nis done for each element and a cell array is returned.\n\nExample:\n\n@example\n@group\nstrrep (\"This is a test string\", \"is\", \"&%$\")\n    @xresult{}  \"Th&%$ &%$ a test string\"\n@end group\n@end example\n\n@seealso{regexprep, strfind}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin != 3 && nargin != 5)\n    print_usage ();\n\n  bool overlaps = true;\n\n  if (nargin == 5)\n    {\n      if (! args(3).is_string () || ! args(4).is_scalar_type ())\n        error (\"strrep: invalid optional argument\");\n\n      std::string opt = args(3).string_value ();\n      if (opt != \"overlaps\")\n        error (\"strrep: unknown option: %s\", opt.c_str ());\n\n      overlaps = args(4).bool_value ();\n    }\n\n  octave_value retval;\n\n  // Aliasing for better code readability\n  octave_value argstr = args(0);\n  octave_value argpat = args(1);\n  octave_value argrep = args(2);\n\n  if (argpat.is_string () && argrep.is_string ())\n    {\n      const Array<char> pat = argpat.char_array_value ();\n      const Array<char> rep = argrep.char_array_value ();\n\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, table, TABSIZE);\n      qs_preprocess (pat, table);\n\n      if (argstr.is_string ())\n        if (argstr.rows () == 1)  // most common case of a single string\n          retval = qs_replace (argstr.char_array_value (), pat, rep,\n                               table, overlaps);\n        else\n          {\n            const charMatrix argchm = argstr.char_matrix_value ();\n            octave_idx_type nel = argchm.rows ();\n            octave_idx_type nc = argchm.columns ();\n            charMatrix retchm (nel, 0);\n\n            for (octave_idx_type i = 0; i < nel; i++)\n              {\n                charMatrix rowchm;\n                rowchm = qs_replace (argchm.extract (i, 0, i, nc-1),\n                                     pat, rep, table, overlaps);\n                retchm.insert (rowchm, i, 0);\n              }\n\n            retval = retchm;\n          }\n      else if (argstr.iscell ())\n        {\n          const Cell argcell = argstr.cell_value ();\n          if (! argcell.iscellstr ())\n            error (\"strrep: each element of S must be a string\");\n\n          Cell retcell (argcell.dims ());\n          octave_idx_type nel = argcell.numel ();\n\n          for (octave_idx_type i = 0; i < nel; i++)\n            {\n              retcell(i) = qs_replace (argcell(i).char_array_value (),\n                                       pat, rep, table, overlaps);\n            }\n\n          retval = retcell;\n        }\n      else\n        error (\"strrep: S must be a string or cell array of strings\");\n    }\n  else if (argpat.iscell () || argrep.iscell ())\n    retval = do_simple_cellfun (Fstrrep, \"strrep\", args);\n  else\n    error (\"strrep: PTN and REP arguments must be strings or cell arrays of strings\");\n\n  return retval;\n}\n\n/*\n%!assert (strrep (\"This is a test string\", \"is\", \"&%$\"),\n%!                \"Th&%$ &%$ a test string\")\n%!assert (strrep (\"abababc\", \"abab\", \"xyz\"), \"xyzxyzc\")\n%!assert (strrep (\"abababc\", \"abab\", \"xyz\", \"overlaps\", false), \"xyzabc\")\n%!assert (strrep ({\"Hello World\"; \"Goodbye World\"}, \"World\", \"Jane\"),\n%!                {\"Hello Jane\"; \"Goodbye Jane\"})\n%!assert (strrep (char (\"Hello World\", \"Goodbye World\"), \"World\", \"Jane\"),\n%!                char (\"Hello Jane\", \"Goodbye Jane\"))\n\n%!assert (size (strrep (\"a\", \"a\", \"\")), [0 0])\n\n%!error strrep ()\n%!error strrep (\"A\")\n%!error strrep (\"A\", \"B\")\n%!error strrep (\"A\", \"B\", \"C\", \"D\")\n%!error strrep (\"A\", \"B\", \"C\", \"D\", \"E\", \"F\")\n%!error <invalid optional argument> strrep (\"A\", \"B\", \"C\", 3, true)\n%!error <invalid optional argument> strrep (\"A\", \"B\", \"C\", \"str\", ones (2,2))\n%!error <unknown option: foobar> strrep (\"A\", \"B\", \"C\", \"foobar\", true)\n%!error <each element of S must be a string> strrep ({\"A\", 1.0}, \"B\", \"C\")\n%!error <S must be a string or cell array of strings> strrep (1.0, \"B\", \"C\")\n%!error <PTN and REP arguments must be strings> strrep (\"A\", 1.0, \"C\")\n%!error <PTN and REP arguments must be strings> strrep (\"A\", \"B\", 1.0)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/strfns.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <queue>\n#include <sstream>\n\n#include \"dMatrix.h\"\n#include \"localcharset-wrapper.h\"\n#include \"uniconv-wrappers.h\"\n#include \"unistr-wrappers.h\"\n\n#include \"Cell.h\"\n#include \"cmd-edit.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n\n#include \"oct-string.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (char, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} char (@var{A})\n@deftypefnx {} {@var{C} =} char (@var{A}, @dots{})\n@deftypefnx {} {@var{C} =} char (@var{str1}, @var{str2}, @dots{})\n@deftypefnx {} {@var{C} =} char (@var{cell_array})\n@deftypefnx {} {'' =} char ()\n\nCreate a string array from one or more numeric matrices, character\nmatrices, or cell arrays.\n\nArguments are concatenated vertically.  The returned values are padded with\nblanks as needed to make each row of the string array have the same length.\nEmpty input strings are significant and will concatenated in the output.\n\nFor numerical input, each element is converted to the corresponding ASCII\ncharacter.  A range error results if an input is outside the ASCII range\n(0-255).\n\nFor cell arrays, each element is concatenated separately.  Cell arrays\nconverted through @code{char} can mostly be converted back with\n@code{cellstr}.  For example:\n\n@example\n@group\nchar ([97, 98, 99], \"\", @{\"98\", \"99\", 100@}, \"str1\", [\"ha\", \"lf\"])\n   @xresult{} [\"abc \"\n       \"    \"\n       \"98  \"\n       \"99  \"\n       \"d   \"\n       \"str1\"\n       \"half\"]\n@end group\n@end example\n@seealso{strvcat, cellstr}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    retval = \"\";  // required for Matlab compatibility\n  else if (nargin == 1)\n    retval = args(0).convert_to_str (true, true,\n                                     args(0).is_dq_string () ? '\"' : '\\'');\n  else\n    {\n      int n_elts = 0;\n\n      int max_len = 0;\n\n      std::queue<string_vector> args_as_strings;\n\n      for (int i = 0; i < nargin; i++)\n        {\n          string_vector s = args(i).xstring_vector_value (\"char: unable to convert some args to strings\");\n\n          if (s.numel () > 0)\n            n_elts += s.numel ();\n          else\n            n_elts += 1;\n\n          int s_max_len = s.max_length ();\n\n          if (s_max_len > max_len)\n            max_len = s_max_len;\n\n          args_as_strings.push (s);\n        }\n\n      string_vector result (n_elts);\n\n      int k = 0;\n\n      for (int i = 0; i < nargin; i++)\n        {\n          string_vector s = args_as_strings.front ();\n          args_as_strings.pop ();\n\n          int n = s.numel ();\n\n          if (n > 0)\n            {\n              for (int j = 0; j < n; j++)\n                {\n                  std::string t = s[j];\n                  int t_len = t.length ();\n\n                  if (max_len > t_len)\n                    t += std::string (max_len - t_len, ' ');\n\n                  result[k++] = t;\n                }\n            }\n          else\n            result[k++] = std::string (max_len, ' ');\n        }\n\n      retval = octave_value (result, '\\'');\n    }\n\n  return retval;\n}\n\n/*\n%!assert (char (), '')\n%!assert (char (100), \"d\")\n%!assert (char (100,100), [\"d\";\"d\"])\n%!assert (char ({100,100}), [\"d\";\"d\"])\n%!assert (char ([100,100]), [\"dd\"])\n%!assert (char ({100,{100}}), [\"d\";\"d\"])\n%!assert (char (100, [], 100), [\"d\";\" \";\"d\"])\n%!assert (char ({100, [], 100}), [\"d\";\" \";\"d\"])\n%!assert (char ({100,{100, {\"\"}}}), [\"d\";\"d\";\" \"])\n%!assert (char ([\"a \";\"be\"], {\"c\", 100}), [\"a \";\"be\";\"c \";\"d \"])\n%!assert (char (\"a\", \"bb\", \"ccc\"), [\"a  \"; \"bb \"; \"ccc\"])\n%!assert (char ([65, 83, 67, 73, 73]), \"ASCII\")\n\n%!test\n%! x = char (\"foo\", \"bar\", \"foobar\");\n%! assert (x(1,:), \"foo   \");\n%! assert (x(2,:), \"bar   \");\n%! assert (x(3,:), \"foobar\");\n*/\n\nDEFUN (strvcat, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} strvcat (@var{A})\n@deftypefnx {} {@var{C} =} strvcat (@var{A}, @dots{})\n@deftypefnx {} {@var{C} =} strvcat (@var{str1}, @var{str2}, @dots{})\n@deftypefnx {} {@var{C} =} strvcat (@var{cell_array})\nCreate a character array from one or more numeric matrices, character\nmatrices, or cell arrays.\n\nArguments are concatenated vertically.  The returned values are padded with\nblanks as needed to make each row of the string array have the same length.\nUnlike @code{char}, empty strings are removed and will not appear in the\noutput.\n\nFor numerical input, each element is converted to the corresponding ASCII\ncharacter.  A range error results if an input is outside the ASCII range\n(0-255).\n\nFor cell arrays, each element is concatenated separately.  Cell arrays\nconverted through @code{strvcat} can mostly be converted back with\n@code{cellstr}.  For example:\n\n@example\n@group\nstrvcat ([97, 98, 99], \"\", @{\"98\", \"99\", 100@}, \"str1\", [\"ha\", \"lf\"])\n      @xresult{} [\"abc \"\n          \"98  \"\n          \"99  \"\n          \"d   \"\n          \"str1\"\n          \"half\"]\n@end group\n@end example\n@seealso{char, strcat, cstrcat}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n  int n_elts = 0;\n  std::size_t max_len = 0;\n  std::queue<string_vector> args_as_strings;\n\n  for (int i = 0; i < nargin; i++)\n    {\n      string_vector s = args(i).xstring_vector_value (\"strvcat: unable to convert some args to strings\");\n\n      std::size_t n = s.numel ();\n\n      // do not count empty strings in calculation of number of elements\n      if (n > 0)\n        {\n          for (std::size_t j = 0; j < n; j++)\n            {\n              if (! s[j].empty ())\n                n_elts++;\n            }\n        }\n\n      std::size_t s_max_len = s.max_length ();\n\n      if (s_max_len > max_len)\n        max_len = s_max_len;\n\n      args_as_strings.push (s);\n    }\n\n  string_vector result (n_elts);\n\n  octave_idx_type k = 0;\n\n  for (int i = 0; i < nargin; i++)\n    {\n      string_vector s = args_as_strings.front ();\n      args_as_strings.pop ();\n\n      std::size_t n = s.numel ();\n\n      if (n > 0)\n        {\n          for (std::size_t j = 0; j < n; j++)\n            {\n              std::string t = s[j];\n              if (t.length () > 0)\n                {\n                  std::size_t t_len = t.length ();\n\n                  if (max_len > t_len)\n                    t += std::string (max_len - t_len, ' ');\n\n                  result[k++] = t;\n                }\n            }\n        }\n    }\n\n  // Cannot use ovl.  Relies on overloaded octave_value call.\n  return octave_value (result, '\\'');\n}\n\n/*\n%!assert (strvcat (\"\"), \"\")\n%!assert (strvcat (100) == \"d\")\n%!assert (strvcat (100,100), [\"d\";\"d\"])\n%!assert (strvcat ({100,100}), [\"d\";\"d\"])\n%!assert (strvcat ([100,100]), [\"dd\"])\n%!assert (strvcat ({100,{100}}), [\"d\";\"d\"])\n%!assert (strvcat (100, [], 100), [\"d\";\"d\"])\n%!assert (strvcat ({100, [], 100}), [\"d\";\"d\"])\n%!assert (strvcat ({100,{100, {\"\"}}}), [\"d\";\"d\"])\n%!assert (strvcat ([\"a \";\"be\"], {\"c\", 100}), [\"a \";\"be\";\"c \";\"d \"])\n%!assert (strvcat (\"a\", \"bb\", \"ccc\"), [\"a  \"; \"bb \"; \"ccc\"])\n%!assert (strvcat (), \"\")\n*/\n\nDEFUN (ischar, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} ischar (@var{x})\nReturn true if @var{x} is a character array.\n@seealso{isfloat, isinteger, islogical, isnumeric, isstring, iscellstr, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).is_string ());\n}\n\n/*\n%!assert (ischar (\"a\"), true)\n%!assert (ischar ([\"ab\";\"cd\"]), true)\n%!assert (ischar ({\"ab\"}), false)\n%!assert (ischar (1), false)\n%!assert (ischar ([1, 2]), false)\n%!assert (ischar ([]), false)\n%!assert (ischar ([1, 2; 3, 4]), false)\n%!assert (ischar (\"\"), true)\n%!assert (ischar (\"test\"), true)\n%!assert (ischar ([\"test\"; \"ing\"]), true)\n%!assert (ischar (struct (\"foo\", \"bar\")), false)\n\n%!error ischar ()\n%!error ischar (\"test\", 1)\n*/\n\nstatic octave_value\ndo_strcmp_fcn (const octave_value& arg0, const octave_value& arg1,\n               octave_idx_type n, const char *fcn_name,\n               bool (*array_op) (const Array<char>&, const Array<char>&,\n                                 octave_idx_type),\n               bool (*str_op) (const std::string&, const std::string&,\n                               std::string::size_type))\n\n{\n  octave_value retval;\n\n  bool s1_string = arg0.is_string ();\n  bool s1_cell = arg0.iscell ();\n  bool s2_string = arg1.is_string ();\n  bool s2_cell = arg1.iscell ();\n\n  if (s1_string && s2_string)\n    retval = array_op (arg0.char_array_value (), arg1.char_array_value (), n);\n  else if ((s1_string && s2_cell) || (s1_cell && s2_string))\n    {\n      octave_value str_val, cell_val;\n\n      if (s1_string)\n        {\n          str_val = arg0;\n          cell_val = arg1;\n        }\n      else\n        {\n          str_val = arg1;\n          cell_val = arg0;\n        }\n\n      const Cell cell = cell_val.cell_value ();\n      const string_vector str = str_val.string_vector_value ();\n      octave_idx_type r = str.numel ();\n\n      if (r == 0 || r == 1)\n        {\n          // Broadcast the string.\n\n          boolNDArray output (cell_val.dims (), false);\n\n          std::string s = (r == 0 ? \"\" : str[0]);\n\n          if (cell_val.iscellstr ())\n            {\n              const Array<std::string> cellstr = cell_val.cellstr_value ();\n              for (octave_idx_type i = 0; i < cellstr.numel (); i++)\n                output(i) = str_op (cellstr(i), s, n);\n            }\n          else\n            {\n              // FIXME: should we warn here?\n              for (octave_idx_type i = 0; i < cell.numel (); i++)\n                {\n                  if (cell(i).is_string ())\n                    output(i) = str_op (cell(i).string_value (), s, n);\n                }\n            }\n\n          retval = output;\n        }\n      else if (r > 1)\n        {\n          if (cell.numel () == 1)\n            {\n              // Broadcast the cell.\n\n              const dim_vector dv (r, 1);\n              boolNDArray output (dv, false);\n\n              if (cell(0).is_string ())\n                {\n                  const std::string str2 = cell(0).string_value ();\n\n                  for (octave_idx_type i = 0; i < r; i++)\n                    output(i) = str_op (str[i], str2, n);\n                }\n\n              retval = output;\n            }\n          else\n            {\n              // Must match in all dimensions.\n\n              boolNDArray output (cell.dims (), false);\n\n              if (cell.numel () == r)\n                {\n                  if (cell_val.iscellstr ())\n                    {\n                      const Array<std::string> cellstr\n                        = cell_val.cellstr_value ();\n                      for (octave_idx_type i = 0; i < cellstr.numel (); i++)\n                        output(i) = str_op (str[i], cellstr(i), n);\n                    }\n                  else\n                    {\n                      // FIXME: should we warn here?\n                      for (octave_idx_type i = 0; i < r; i++)\n                        {\n                          if (cell(i).is_string ())\n                            output(i) = str_op (str[i],\n                                                cell(i).string_value (), n);\n                        }\n                    }\n\n                  retval = output;\n                }\n              else\n                retval = false;\n            }\n        }\n    }\n  else if (s1_cell && s2_cell)\n    {\n      octave_value cell1_val, cell2_val;\n      octave_idx_type r1 = arg0.numel (), r2;\n\n      if (r1 == 1)\n        {\n          // Make the singleton cell2.\n\n          cell1_val = arg1;\n          cell2_val = arg0;\n        }\n      else\n        {\n          cell1_val = arg0;\n          cell2_val = arg1;\n        }\n\n      const Cell cell1 = cell1_val.cell_value ();\n      const Cell cell2 = cell2_val.cell_value ();\n      r1 = cell1.numel ();\n      r2 = cell2.numel ();\n\n      const dim_vector size1 = cell1.dims ();\n      const dim_vector size2 = cell2.dims ();\n\n      boolNDArray output (size1, false);\n\n      if (r2 == 1)\n        {\n          // Broadcast cell2.\n\n          if (cell2(0).is_string ())\n            {\n              const std::string str2 = cell2(0).string_value ();\n\n              if (cell1_val.iscellstr ())\n                {\n                  const Array<std::string> cellstr = cell1_val.cellstr_value ();\n                  for (octave_idx_type i = 0; i < cellstr.numel (); i++)\n                    output(i) = str_op (cellstr(i), str2, n);\n                }\n              else\n                {\n                  // FIXME: should we warn here?\n                  for (octave_idx_type i = 0; i < r1; i++)\n                    {\n                      if (cell1(i).is_string ())\n                        {\n                          const std::string str1 = cell1(i).string_value ();\n                          output(i) = str_op (str1, str2, n);\n                        }\n                    }\n                }\n            }\n        }\n      else\n        {\n          if (size1 != size2)\n            error (\"%s: nonconformant cell arrays\", fcn_name);\n\n          if (cell1.iscellstr () && cell2.iscellstr ())\n            {\n              const Array<std::string> cellstr1 = cell1_val.cellstr_value ();\n              const Array<std::string> cellstr2 = cell2_val.cellstr_value ();\n              for (octave_idx_type i = 0; i < r1; i++)\n                output (i) = str_op (cellstr1(i), cellstr2(i), n);\n            }\n          else\n            {\n              // FIXME: should we warn here?\n              for (octave_idx_type i = 0; i < r1; i++)\n                {\n                  if (cell1(i).is_string () && cell2(i).is_string ())\n                    {\n                      const std::string str1 = cell1(i).string_value ();\n                      const std::string str2 = cell2(i).string_value ();\n                      output(i) = str_op (str1, str2, n);\n                    }\n                }\n            }\n        }\n\n      retval = output;\n    }\n  else\n    retval = false;\n\n  return retval;\n}\n\n\n// These are required so that they match the same signature as strncmp\n// and strncmpi and can therefore be used in do_strcmp_fcn.\n\ntemplate <typename T, typename T_size_type>\nstatic bool\nstrcmp_ignore_n (const T& s1, const T& s2, T_size_type)\n{ return string::strcmp (s1, s2); }\n\ntemplate <typename T, typename T_size_type>\nstatic bool\nstrcmpi_ignore_n (const T& s1, const T& s2, T_size_type)\n{ return string::strcmpi (s1, s2); }\n\n\nDEFUN (strcmp, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} strcmp (@var{str1}, @var{str2})\nReturn 1 if the character strings @var{str1} and @var{str2} are the same,\nand 0 otherwise.\n\nIf either @var{str1} or @var{str2} is a cell array of strings, then an array\nof the same size is returned, containing the values described above for\nevery member of the cell array.  The other argument may also be a cell\narray of strings (of the same size or with only one element), char matrix\nor character string.\n\n@strong{Caution:} For compatibility with @sc{matlab}, Octave's strcmp\nfunction returns 1 if the character strings are equal, and 0 otherwise.\nThis is just the opposite of the corresponding C library function.\n@seealso{strcmpi, strncmp, strncmpi}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  return ovl (do_strcmp_fcn (args(0), args(1), 0, \"strcmp\",\n                             strcmp_ignore_n, strcmp_ignore_n));\n}\n\n/*\n%!shared x\n%! x = char (zeros (0, 2));\n%!assert (strcmp (\"\", x), false)\n%!assert (strcmp (x, \"\"), false)\n%!assert (strcmp (x, x), true)\n## %!assert (strcmp ({\"\"}, x), true)\n## %!assert (strcmp ({x}, \"\"), false)\n## %!assert (strcmp ({x}, x), true)\n## %!assert (strcmp (\"\", {x}), false)\n## %!assert (strcmp (x, {\"\"}), false)\n## %!assert (strcmp (x, {x}), true)\n## %!assert (strcmp ({x; x}, \"\"), [false; false])\n## %!assert (strcmp ({x; x}, {\"\"}), [false; false])\n## %!assert (strcmp (\"\", {x; x}), [false; false])\n## %!assert (strcmp ({\"\"}, {x; x}), [false; false])\n%!assert (strcmp ({\"foo\"}, x), false)\n%!assert (strcmp ({\"foo\"}, \"foo\"), true)\n%!assert (strcmp ({\"foo\"}, x), false)\n%!assert (strcmp (x, {\"foo\"}), false)\n%!assert (strcmp (\"foo\", {\"foo\"}), true)\n%!assert (strcmp (x, {\"foo\"}), false)\n%!shared y\n%! y = char (zeros (2, 0));\n%!assert (strcmp (\"\", y), false)\n%!assert (strcmp (y, \"\"), false)\n%!assert (strcmp (y, y), true)\n%!assert (strcmp ({\"\"}, y), [true; true])\n%!assert (strcmp ({y}, \"\"), true)\n%!assert (strcmp ({y}, y), [true; true])\n%!assert (strcmp (\"\", {y}), true)\n%!assert (strcmp (y, {\"\"}), [true; true])\n%!assert (strcmp (y, {y}), [true; true])\n%!assert (strcmp ({y; y}, \"\"), [true; true])\n%!assert (strcmp ({y; y}, {\"\"}), [true; true])\n%!assert (strcmp (\"\", {y; y}), [true; true])\n%!assert (strcmp ({\"\"}, {y; y}), [true; true])\n%!assert (strcmp ({\"foo\"}, y), [false; false])\n%!assert (strcmp ({\"foo\"}, y), [false; false])\n%!assert (strcmp (y, {\"foo\"}), [false; false])\n%!assert (strcmp (y, {\"foo\"}), [false; false])\n%!assert (strcmp (\"foobar\", \"foobar\"), true)\n%!assert (strcmp (\"foobar\", \"fooBar\"), false)\n%!assert (strcmp (\"fooba\", \"foobar\"), false)\n\n%!error strcmp ()\n%!error strcmp (\"foo\", \"bar\", 3)\n*/\n\nDEFUN (strncmp, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} strncmp (@var{str1}, @var{str2}, @var{n})\nReturn 1 if the first @var{n} characters of strings @var{str1} and @var{str2}\nare the same, and 0 otherwise.\n\n@example\n@group\nstrncmp (\"abce\", \"abcd\", 3)\n      @xresult{} 1\n@end group\n@end example\n\nIf either @var{str1} or @var{str2} is a cell array of strings, then an array\nof the same size is returned, containing the values described above for\nevery member of the cell array.  The other argument may also be a cell\narray of strings (of the same size or with only one element), char matrix\nor character string.\n\n@example\n@group\nstrncmp (\"abce\", @{\"abcd\", \"bca\", \"abc\"@}, 3)\n     @xresult{} [1, 0, 1]\n@end group\n@end example\n\n@strong{Caution:} For compatibility with @sc{matlab}, Octave's strncmp\nfunction returns true if the character strings are equal, and false\notherwise.  This is just the opposite of the corresponding C library\nfunction.  In addition Octave's strncmp function returns true if N = 0.\n\n@sc{matlab} incompatibility : Octave's strncmp function produces an error if\nN < 0, while @sc{matlab} treats N < 0 the same as N = 0, always returning\ntrue.\n\n@seealso{strncmpi, strcmp, strcmpi}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  octave_idx_type n = args(2).idx_type_value ();\n\n  if (n >= 0)\n    return ovl (do_strcmp_fcn (args(0), args(1), n, \"strncmp\",\n                               string::strncmp,\n                               string::strncmp));\n  else\n    error (\"strncmp: N must be greater than or equal to 0\");\n}\n\n/*\n%!assert (strncmp (\"abce\", \"abc\", 3), true)\n%!assert (strncmp (\"abce\", \"aBc\", 3), false)\n%!assert (strncmp (100, 100, 1), false)\n%!assert (strncmp (\"abce\", {\"abcd\", \"bca\", \"abc\"}, 3), logical ([1, 0, 1]))\n%!assert (strncmp (\"abc\",  {\"abcd\", \"bca\", \"abc\"}, 4), logical ([0, 0, 1]))\n%!assert (strncmp ({\"abcd\", \"bca\", \"abc\"},\"abce\", 3), logical ([1, 0, 1]))\n%!assert (strncmp ({\"abcd\", \"bca\", \"abc\"},{\"abcd\", \"bca\", \"abe\"}, 3),\n%!        logical ([1, 1, 0]))\n%!assert (strncmp (\"abc\", {\"abcd\", 10}, 2), logical ([1, 0]))\n\n%!assert <*54373> (strncmp (\"abc\", \"abc\", 100))\n%!assert <*57879> (strncmp (\"abc\", \"abc\", 0))\n%!assert <*57879> (strncmp (\"abc\", \"def\", 0))\n%!assert <*57879> (strncmp (\"abc\", \"ac\", 0))\n\n%!error strncmp ()\n%!error strncmp (\"abc\", \"def\")\n%!error <N must be greater than or equal> strncmp (\"abc\", \"abc\", -1)\n*/\n\nDEFUNX (\"strcmpi\", Fstrcmpi, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} strcmpi (@var{str1}, @var{str2})\nReturn 1 if the character strings @var{str1} and @var{str2} are the same,\ndisregarding case of alphabetic characters, and 0 otherwise.\n\nIf either @var{str1} or @var{str2} is a cell array of strings, then an array\nof the same size is returned, containing the values described above for\nevery member of the cell array.  The other argument may also be a cell\narray of strings (of the same size or with only one element), char matrix\nor character string.\n\n@strong{Caution:} For compatibility with @sc{matlab}, Octave's strcmpi\nfunction returns 1 if the character strings are equal, and 0 otherwise.\nThis is just the opposite of the corresponding C library function.\n\n@strong{Caution:} National alphabets are not supported.\n@seealso{strcmp, strncmp, strncmpi}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  return ovl (do_strcmp_fcn (args(0), args(1), 0, \"strcmpi\",\n                             strcmpi_ignore_n, strcmpi_ignore_n));\n}\n\n/*\n%!assert (strcmpi (\"abc123\", \"ABC123\"), true)\n*/\n\nDEFUNX (\"strncmpi\", Fstrncmpi, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} strncmpi (@var{str1}, @var{str2}, @var{n})\nReturn 1 if the first @var{n} character of @var{s1} and @var{s2} are the\nsame, disregarding case of alphabetic characters, and 0 otherwise.\n\nIf either @var{str1} or @var{str2} is a cell array of strings, then an array\nof the same size is returned, containing the values described above for\nevery member of the cell array.  The other argument may also be a cell\narray of strings (of the same size or with only one element), char matrix\nor character string.\n\n@strong{Caution:} For compatibility with @sc{matlab}, Octave's strncmpi\nfunction returns true if the character strings are equal, and false\notherwise.  This is just the opposite of the corresponding C library\nfunction.  In addition Octave's strncmpi function returns true if N = 0.\n\n@sc{matlab} incompatibility : Octave's strncmpi function produces an error if\nN < 0, while @sc{matlab} treats N < 0 the same as N = 0, always returning\ntrue.\n\n@strong{Caution:} National alphabets are not supported.\n@seealso{strncmp, strcmp, strcmpi}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  octave_idx_type n = args(2).idx_type_value ();\n\n  if (n >= 0)\n    return ovl (do_strcmp_fcn (args(0), args(1), n, \"strncmpi\",\n                               string::strncmpi,\n                               string::strncmpi));\n  else\n    error (\"strncmpi: N must be greater than or equal to 0\");\n}\n\n/*\n%!assert (strncmpi (\"abc123\", \"ABC456\", 3))\n%!assert <*57879> (strncmpi (\"abc\", \"abc\", 0))\n%!assert <*57879> (strncmpi (\"abc\", \"def\", 0))\n%!assert <*57879> (strncmpi (\"abc\", \"ac\", 0))\n%!error <N must be greater than or equal> strncmpi (\"abc\", \"abc\", -1)\n*/\n\nDEFUN (str2double, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{d} =} str2double (@var{str})\nConvert a string to a real or complex number.\n\nThe string must be in one of the following formats where a and b are real\nnumbers and the complex unit is @qcode{'i'} or @qcode{'j'}:\n\n@itemize\n@item a + bi\n\n@item a + b*i\n\n@item a + i*b\n\n@item bi + a\n\n@item b*i + a\n\n@item i*b + a\n@end itemize\n\nIf present, a and/or b are of the form @nospell{[+-]d[,.]d[[eE][+-]d]} where\nthe brackets indicate optional arguments and @qcode{'d'} indicates zero or\nmore digits.  The special input values @code{Inf}, @code{NaN}, and @code{NA}\nare also accepted.\n\n@var{str} may be a character string, character matrix, or cell array.  For\ncharacter arrays the conversion is repeated for every row, and a double or\ncomplex array is returned.  Empty rows in @var{s} are deleted and not\nreturned in the numeric array.  For cell arrays each character string\nelement is processed and a double or complex array of the same dimensions as\n@var{str} is returned.\n\nFor unconvertible scalar or character string input @code{str2double} returns\na NaN@.  Similarly, for character array input @code{str2double} returns a\nNaN for any row of @var{s} that could not be converted.  For a cell array,\n@code{str2double} returns a NaN for any element of @var{s} for which\nconversion fails.  Note that numeric elements in a mixed string/numeric\ncell array are not strings and the conversion will fail for these elements\nand return NaN.\n\nProgramming Note: @code{str2double} can replace @code{str2num}, is more\nefficient, and avoids the security risk of using @code{eval} on unknown data.\n@seealso{str2num}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value retval;\n\n  if (args(0).is_string ())\n    {\n      if (args(0).rows () == 0 || args(0).columns () == 0)\n        retval = Matrix (1, 1, numeric_limits<double>::NaN ());\n      else if (args(0).rows () == 1 && args(0).ndims () == 2)\n        retval = string::str2double (args(0).string_value ());\n      else\n        {\n          const string_vector sv = args(0).string_vector_value ();\n\n          retval = sv.map<Complex> (string::str2double);\n        }\n    }\n  else if (args(0).iscell ())\n    {\n      const Cell cell = args(0).cell_value ();\n\n      ComplexNDArray output (cell.dims (), numeric_limits<double>::NaN ());\n\n      for (octave_idx_type i = 0; i < cell.numel (); i++)\n        {\n          if (cell(i).is_string ())\n            output(i) = string::str2double (cell(i).string_value ());\n        }\n      retval = output;\n    }\n  else\n    retval = Matrix (1, 1, numeric_limits<double>::NaN ());\n\n  return retval;\n}\n\n/*\n%!assert (str2double (\"1\"), 1)\n%!assert (str2double (\"-.1e-5\"), -1e-6)\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! assert (str2double (char (\"1\", \"2 3\", \"4i\")), [1; NaN; 4i]);\n%!testif HAVE_LLVM_LIBCXX  <47413>\n%! ## Same test code as above, intended only for test statistics with libc++.\n%! assert (str2double (char (\"1\", \"2 3\", \"4i\")), [1; NaN; 4i]);\n%!assert (str2double (\"1,222.5\"), 1222.5)\n%!assert (str2double (\"i\"), i)\n%!assert (str2double (\"2j\"), 2i)\n%!assert (str2double (\"2 + j\"), 2+j)\n%!assert (str2double (\"i*2 + 3\"), 3+2i)\n%!assert (str2double (\".5*i + 3.5\"), 3.5+0.5i)\n%!assert (str2double (\"1e-3 + i*.25\"), 1e-3 + 0.25i)\n%!assert (str2double (char (\"2 + j\",\"1.25e-3\",\"-05\")), [2+i; 1.25e-3; -5])\n%!assert (str2double ({\"2 + j\",\"1.25e-3\",\"-05\"}), [2+i, 1.25e-3, -5])\n%!assert (str2double (1), NaN)\n%!assert (str2double (\"1 2 3 4\"), NaN)\n%!assert (str2double (\"Hello World\"), NaN)\n%!assert (str2double (\"NaN\"), NaN)\n%!assert (str2double (\"NA\"), NA)\n%!assert (str2double (\"Inf\"), Inf)\n%!assert (str2double (\"iNF\"), Inf)\n%!assert (str2double (\"-Inf\"), -Inf)\n%!assert (str2double (\"Inf*i\"), complex (0, Inf))\n%!assert (str2double (\"iNF*i\"), complex (0, Inf))\n%!assert (str2double (\"NaN + Inf*i\"), complex (NaN, Inf))\n%!assert (str2double (\"Inf - Inf*i\"), complex (Inf, -Inf))\n%!assert (str2double (\"-i*NaN - Inf\"), complex (-Inf, -NaN))\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! assert (str2double ({\"abc\", \"4i\"}), [NaN + 0i, 4i]);\n%!testif HAVE_LLVM_LIBCXX  <47413>\n%! assert (str2double ({\"abc\", \"4i\"}), [NaN + 0i, 4i]);\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! assert (str2double ({2, \"4i\"}), [NaN + 0i, 4i]);\n%!testif HAVE_LLVM_LIBCXX  <47413>\n%! assert (str2double ({2, \"4i\"}), [NaN + 0i, 4i]);\n%!assert (str2double (zeros (3,1,2)), NaN)\n%!assert (str2double (''), NaN)\n%!assert (str2double ([]), NaN)\n%!assert (str2double (char (zeros (3,0))), NaN)\n%!assert (str2double (\"1.000444\"), 1.000444)\n%!assert (str2double (\"1e999\"), Inf)\n%!assert (str2double (\"-1e999\"), -Inf)\n*/\n\nDEFUN (__native2unicode__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{utf8_str} =} __native2unicode__ (@var{native_bytes}, @var{codepage})\nConvert byte stream @var{native_bytes} to UTF-8 using @var{codepage}.\n\n@seealso{native2unicode, __unicode2native__}\n@end deftypefn */)\n{\n  if (args(0).is_string ())\n    return ovl (args(0));\n\n  std::string tmp = args(1).string_value ();\n  const char *codepage\n    = (tmp.empty () ? octave_locale_charset_wrapper () : tmp.c_str ());\n\n  charNDArray native_bytes = args(0).char_array_value ();\n\n  const char *src = native_bytes.data ();\n  std::size_t srclen = native_bytes.numel ();\n\n  std::size_t length;\n  uint8_t *utf8_str = nullptr;\n\n  utf8_str = octave_u8_conv_from_encoding (codepage, src, srclen, &length);\n\n  if (! utf8_str)\n    {\n      if (errno == ENOSYS)\n        error (\"native2unicode: iconv() is not supported.  Installing GNU \"\n               \"libiconv and then re-compiling Octave could fix this.\");\n      else\n        error (\"native2unicode: converting from codepage '%s' to UTF-8: %s\",\n               codepage, std::strerror (errno));\n    }\n\n  unwind_action free_utf8_str ([utf8_str] () { ::free (utf8_str); });\n\n  octave_idx_type len = length;\n\n  charNDArray retval (dim_vector (1, len));\n\n  for (octave_idx_type i = 0; i < len; i++)\n    retval.xelem (i) = utf8_str[i];\n\n  return ovl (retval);\n}\n\nDEFUN (__unicode2native__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{native_bytes} =} __unicode2native__ (@var{utf8_str}, @var{codepage})\nConvert UTF-8 string @var{utf8_str} to byte stream @var{native_bytes} using\n@var{codepage}.\n\n@seealso{unicode2native, __native2unicode__}\n@end deftypefn */)\n{\n  std::string tmp = args(1).string_value ();\n  const char *codepage\n    = (tmp.empty () ? octave_locale_charset_wrapper () : tmp.c_str ());\n\n  charNDArray utf8_str = args(0).char_array_value ();\n\n  const uint8_t *src = reinterpret_cast<const uint8_t *> (utf8_str.data ());\n  std::size_t srclen = utf8_str.numel ();\n\n  std::size_t length;\n  char *native_bytes = nullptr;\n\n  native_bytes = octave_u8_conv_to_encoding (codepage, src, srclen, &length);\n\n  if (! native_bytes)\n    {\n      if (errno == ENOSYS)\n        error (\"unicode2native: iconv() is not supported.  Installing GNU \"\n               \"libiconv and then re-compiling Octave could fix this.\");\n      else\n        error (\"unicode2native: converting from UTF-8 to codepage '%s': %s\",\n               codepage, std::strerror (errno));\n    }\n\n  unwind_action free_native_bytes ([native_bytes] () { ::free (native_bytes); });\n\n  octave_idx_type len = length;\n\n  uint8NDArray retval (dim_vector (1, len));\n\n  for (octave_idx_type i = 0; i < len; i++)\n    retval.xelem (i) = native_bytes[i];\n\n  return ovl (retval);\n}\n\nDEFUN (__locale_charset__, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{charset} =} __locale_charset__ ()\nReturn the identifier for the charset used if the encoding is set to\n@qcode{\"locale\"}.\n@end deftypefn */)\n{\n  const char *charset = octave_locale_charset_wrapper ();\n  std::string charset_str (charset);\n  return ovl (charset_str);\n}\n\nDEFUN (unicode_idx, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{idx} =} unicode_idx (@var{str})\nReturn an array with the indices for each UTF-8 encoded character in @var{str}.\n\n@example\n@group\nunicode_idx (\"aäbc\")\n     @xresult{} [1, 2, 2, 3, 4]\n@end group\n@end example\n\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  charNDArray str = args(0).xchar_array_value (\"STR must be a string\");\n  Array<octave_idx_type> p (dim_vector (str.ndims (), 1));\n  charNDArray str_p;\n  if (str.ndims () > 1)\n    {\n      for (octave_idx_type i=0; i < str.ndims (); i++)\n        p(i) = i;\n      p(0) = 1;\n      p(1) = 0;\n      str_p = str.permute (p);\n    }\n\n  const uint8_t *src = reinterpret_cast<const uint8_t *> (str_p.data ());\n  octave_idx_type srclen = str.numel ();\n\n  NDArray idx (str_p.dims ());\n\n  octave_idx_type u8_char_num = 1;\n  for (octave_idx_type i = 0; i < srclen; u8_char_num++)\n    {\n      int mblen = octave_u8_strmblen_wrapper (src + i);\n      if (mblen < 1)\n        mblen = 1;\n      for (octave_idx_type j = 0; j < mblen; j++)\n        idx(i+j) = u8_char_num;\n      i += mblen;\n    }\n\n  return ovl (str.ndims () > 1 ? idx.permute (p, true) : idx);\n}\n\n/*\n%!assert (unicode_idx ([\"aäou\"; \"Ä∞\"]), [1 2 2 3 4; 5 5 6 6 6])\n*/\n\nDEFUN (__unicode_length__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{len} =} __unicode_length__ (@var{str})\nReturn number of Unicode code points in @var{str}.\n\nThe input @var{str} must be a UTF-8 encoded character vector or cell string.\n\n@example\n@group\nlength (\"aäbc\")\n     @xresult{} 5\n__unicode_length__ (\"aäbc\")\n     @xresult{} 4\n@end group\n@end example\n\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  bool arg_char = args(0).is_char_matrix ();\n\n  if (! arg_char && ! args(0).iscellstr ())\n    error (\"STR must be a character array or cell string.\");\n\n  octave_value_list retval;\n\n  if (arg_char)\n    {\n      charNDArray str = args(0).char_array_value ();\n      Array<octave_idx_type> p (dim_vector (str.ndims (), 1));\n      if (str.ndims () > 1)\n        {\n          for (octave_idx_type i=0; i < str.ndims (); i++)\n            p(i) = i;\n          p(0) = 1;\n          p(1) = 0;\n          str = str.permute (p);\n        }\n\n      const uint8_t *src = reinterpret_cast<const uint8_t *> (str.data ());\n      octave_idx_type mbsnlen = octave_u8_mbsnlen_wrapper (src, str.numel ());\n\n      retval = ovl (mbsnlen);\n    }\n  else\n    {\n      const Array<std::string> cellstr = args(0).cellstr_value ();\n      NDArray output (args(0).dims (), false);\n      for (octave_idx_type i = 0; i < cellstr.numel (); i++)\n        {\n          const uint8_t *src\n            = reinterpret_cast<const uint8_t *> (cellstr(i).c_str ());\n          output(i) = octave_u8_mbsnlen_wrapper (src, cellstr(i).size ());\n        }\n\n      retval = ovl (output);\n    }\n\n  return retval;\n}\n\n/*\n%!assert (__unicode_length__ (\"\"), 0)\n%!assert (__unicode_length__ (\"aäbc\"), 4)\n%!assert (__unicode_length__ ([\"aä\"; \"öo\"]), 4)\n%!assert (__unicode_length__ ({\"aäbc\", \"abc\"}), [4, 3])\n*/\n\nDEFUN (__u8_validate__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{out_str} =} __u8_validate__ (in_str, mode)\nReturn string with valid UTF-8.\n\nOn encountering invalid UTF-8 in @var{in_str}, the bytes are either replaced by\nthe replacement character @qcode{\"�\"} (if @var{mode} is omitted or is the\nstring @qcode{\"replace\"}) or interpreted as the Unicode code points\nU+0080–U+00FF with the same value as the byte (if @var{mode} is the string\n@qcode{\"unicode\"}), thus interpreting the bytes according to ISO-8859-1.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  // Input check\n  std::string in_str =\n    args(0).xstring_value (\"__u8_validate__: IN_STR must be a string\");\n\n  std::string mode = \"replace\";\n  if (nargin == 2)\n    mode = args(1).xstring_value (\"__u8_validate__: MODE must be a string\");\n\n  string::u8_fallback_type fb_type;\n  if (mode == \"replace\")\n    fb_type = string::U8_REPLACEMENT_CHAR;\n  else if (mode == \"unicode\")\n    fb_type = string::U8_ISO_8859_1;\n  else\n    error (R\"(__u8_validate__: MODE must be either \"replace\" or \"unicode\")\");\n\n  string::u8_validate (\"__u8_validate__\", in_str, fb_type);\n\n  return ovl (in_str);\n}\n\nDEFUN (newline, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{c} =} newline\nReturn the character corresponding to a newline.\n\nThis is equivalent to @qcode{\"@backslashchar{}n\"}.\n\nExample Code\n\n@example\n@group\njoined_string = [newline \"line1\" newline \"line2\"]\n@xresult{}\nline1\nline2\n@end group\n@end example\n\n@seealso{strcat, strjoin, strsplit}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  static octave_value_list retval = ovl (\"\\n\");\n\n  return retval;\n}\n\n/*\n%!assert (newline (), \"\\n\")\n\n%!error newline (1)\n## FIXME: The next error() test requires a semicolon at EOL until\n##        bug #59265 is resolved.\n%!error [a, b] = newline ();\n*/\n\nDEFUN (list_in_columns, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{str} =} list_in_columns (@var{arg}, @var{width}, @var{prefix})\nReturn a string containing the elements of @var{arg} listed in columns with\nan overall maximum width of @var{width} and optional prefix @var{prefix}.\n\nThe argument @var{arg} must be a cell array of character strings or a\ncharacter array.\n\nIf @var{width} is not specified or is an empty matrix, or less than or equal\nto zero, the width of the terminal screen is used.  Newline characters are\nused to break the lines in the output string.  For example:\n@c Set example in small font to prevent overfull line\n\n@smallexample\n@group\nlist_in_columns (@{\"abc\", \"def\", \"ghijkl\", \"mnop\", \"qrs\", \"tuv\"@}, 20)\n     @xresult{} abc     mnop\n        def     qrs\n        ghijkl  tuv\n\nwhos ans\n     @xresult{}\n     Variables in the current scope:\n\n       Attr Name        Size                     Bytes  Class\n       ==== ====        ====                     =====  =====\n            ans         1x37                        37  char\n\n     Total is 37 elements using 37 bytes\n@end group\n@end smallexample\n\n@seealso{terminal_size}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  string_vector s = args(0).xstring_vector_value (\"list_in_columns: ARG must be a cellstr or char array\");\n\n  int width;\n\n  if (nargin > 1 && ! args(1).isempty ())\n    width = args(1).strict_int_value (\"list_in_columns: WIDTH must be an integer\");\n  else\n    width = command_editor::terminal_cols ();\n\n  std::string prefix;\n\n  if (nargin > 2)\n    prefix = args(2).xstring_value (\"list_in_columns: PREFIX must be a string\");\n\n  std::ostringstream buf;\n\n  s.list_in_columns (buf, width, prefix);\n\n  return ovl (buf.str ());\n}\n\n/*\n%!test\n%! input  = {\"abc\", \"def\", \"ghijkl\", \"mnop\", \"qrs\", \"tuv\"};\n%! result = \"abc     mnop\\ndef     qrs\\nghijkl  tuv\\n\";\n%! assert (list_in_columns (input, 20), result);\n%!test\n%! input  = char (\"abc\", \"def\", \"ghijkl\", \"mnop\", \"qrs\", \"tuv\");\n%! result = \"abc     mnop  \\ndef     qrs   \\nghijkl  tuv   \\n\";\n%! assert (list_in_columns (input, 20), result);\n%!test\n%! input  = char (\"abc\", \"def\", \"ghijkl\", \"mnop\", \"qrs\", \"tuv\");\n%! result = \"  abc     mnop  \\n  def     qrs   \\n  ghijkl  tuv   \\n\";\n%! assert (list_in_columns (input, 20, \"  \"), result);\n\n%!error list_in_columns ()\n%!error list_in_columns ([\"abc\", \"def\"], 20, 2)\n%!error list_in_columns ([\"abc\", \"def\"], 20, \"  \", 3)\n%!error <list_in_columns: WIDTH must be an integer> list_in_columns ([\"abc\", \"def\"], \"a\")\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/sub2ind.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <utility>\n\n#include \"Array-util.h\"\n#include \"oct-locbuf.h\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic dim_vector\nget_dim_vector (const octave_value& val, const char *name)\n{\n  RowVector dimsv = val.row_vector_value (false, true);\n  dim_vector dv;\n  octave_idx_type n = dimsv.numel ();\n\n  if (n < 1)\n    error (\"%s: dimension vector DIMS must not be empty\", name);\n\n  dv.resize (std::max (n, static_cast<octave_idx_type> (2)));\n  dv(1) = 1;\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      octave_idx_type ii = dimsv(i);\n      if (ii == dimsv(i) && ii >= 0)\n        dv(i) = ii;\n      else\n        error (\"%s: dimension vector DIMS must contain integers\", name);\n    }\n\n  return dv;\n}\n\nDEFUN (sub2ind, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{ind} =} sub2ind (@var{dims}, @var{i}, @var{j})\n@deftypefnx {} {@var{ind} =} sub2ind (@var{dims}, @var{s1}, @var{s2}, @dots{}, @var{sN})\nConvert subscripts to linear indices.\n\nThe input @var{dims} is a dimension vector where each element is the size of\nthe array in the respective dimension (@pxref{XREFsize,,@code{size}}).  The\nremaining inputs are scalars or vectors of subscripts to be converted.\n\nThe output vector @var{ind} contains the converted linear indices.\n\nBackground: Array elements can be specified either by a linear index which\nstarts at 1 and runs through the number of elements in the array, or they may\nbe specified with subscripts for the row, column, page, etc.  The functions\n@code{ind2sub} and @code{sub2ind} interconvert between the two forms.\n\nThe linear index traverses dimension 1 (rows), then dimension 2 (columns), then\ndimension 3 (pages), etc.@: until it has numbered all of the elements.\nConsider the following 3-by-3 matrices:\n\n@example\n@group\n[(1,1), (1,2), (1,3)]     [1, 4, 7]\n[(2,1), (2,2), (2,3)] ==> [2, 5, 8]\n[(3,1), (3,2), (3,3)]     [3, 6, 9]\n@end group\n@end example\n\n@noindent\nThe left matrix contains the subscript tuples for each matrix element.  The\nright matrix shows the linear indices for the same matrix.\n\nThe following example shows how to convert the two-dimensional indices\n@code{(2,1)} and @code{(2,3)} of a 3-by-3 matrix to linear indices with a\nsingle call to @code{sub2ind}.\n\n@example\n@group\ns1 = [2, 2];\ns2 = [1, 3];\nind = sub2ind ([3, 3], s1, s2)\n    @xresult{} ind =  2   8\n@end group\n@end example\n@seealso{ind2sub, size}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2)\n    print_usage ();\n\n  const dim_vector& dv = get_dim_vector (args(0), \"sub2ind\");\n\n  Array<idx_vector> idxa (dim_vector (nargin-1, 1));\n\n  for (int j = 0; j < nargin - 1; j++)\n    {\n      if (! args(j+1).isnumeric ())\n        error (\"sub2ind: subscripts must be numeric\");\n\n      try\n        {\n          idxa(j) = args(j+1).index_vector ();\n\n          if (j > 0 && args(j+1).dims () != args(1).dims ())\n            error (\"sub2ind: all subscripts must be of the same size\");\n        }\n      catch (index_exception& ie)\n        {\n          ie.set_pos_if_unset (nargin-1, j+1);\n          ie.set_var ();\n          std::string msg = ie.message ();\n          error_with_id (ie.err_id (), \"%s\", msg.c_str ());\n        }\n    }\n\n  return ovl (sub2ind (dv, idxa));\n}\n\n/*\n## Test evaluation\n%!test\n%! s1 = [ 1   1   1   1 ; 2   2   2   2 ];\n%! s2 = [ 1   1   2   2 ; 1   1   2   2 ];\n%! s3 = [ 1   2   1   2 ; 1   2   1   2 ];\n%! in = [ 1 101  11 111 ; 2 102  12 112 ];\n%! assert (sub2ind ([10 10 10], s1, s2, s3), in);\n\n# Test low index\n%!assert (sub2ind ([10 10 10], 1, 1, 1), 1)\n%!error <index \\(0,_,_\\)> sub2ind ([10 10 10], 0, 1, 1)\n%!error <index \\(_,0,_\\)> sub2ind ([10 10 10], 1, 0, 1)\n%!error <index \\(_,_,0\\)> sub2ind ([10 10 10], 1, 1, 0)\n\n# Test high index\n%!assert (sub2ind ([10 10 10], 10, 10, 10), 1000)\n%!error <index \\(11,_,_\\): out of bound 10> sub2ind ([10 10 10], 11, 10, 10)\n%!error <index \\(_,11,_\\): out of bound 10> sub2ind ([10 10 10], 10, 11, 10)\n%!error <index \\(_,_,11\\): out of bound 10> sub2ind ([10 10 10], 10, 10, 11)\n\n# Test high index in the trailing dimensions\n%!assert (sub2ind ([10, 1], 2, 1, 1), 2)\n%!error <index \\(_,2,_\\): out of bound 1> sub2ind ([10, 1], 1, 2, 1)\n%!error <index \\(_,_,2\\): out of bound 1> sub2ind ([10, 1], 1, 1, 2)\n%!assert (sub2ind ([10 10], 2, 2, 1), 12)\n%!error <index \\(_,_,2\\): out of bound 1> sub2ind ([10 10], 2, 1, 2)\n%!error <index \\(_,_,2\\): out of bound 1> sub2ind ([10 10], 1, 2, 2)\n\n# Test handling of empty arguments\n%!assert (sub2ind ([10 10], zeros (0,0), zeros (0,0)), zeros (0,0))\n%!assert (sub2ind ([10 10], zeros (2,0), zeros (2,0)), zeros (2,0))\n%!assert (sub2ind ([10 10], zeros (0,2), zeros (0,2)), zeros (0,2))\n%!error <all subscripts .* same size> sub2ind ([10 10 10], zeros (0,2), zeros (2,0))\n\n# Test handling of arguments of different size\n%!error <all subscripts .* same size> sub2ind ([10 10], ones (1,2), ones (1,3))\n%!error <all subscripts .* same size> sub2ind ([10 10], ones (1,2), ones (2,1))\n\n## Test input validation\n%!error <dimension vector> sub2ind ([10 10.5], 1, 1)\n%!error <index \\(1.5,_\\)> sub2ind ([10 10], 1.5, 1)\n%!error <index \\(_,1.5\\)> sub2ind ([10 10], 1, 1.5)\n*/\n\nDEFUN (ind2sub, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{s1}, @var{s2}, @dots{}, @var{sN}] =} ind2sub (@var{dims}, @var{ind})\nConvert linear indices to subscripts.\n\nThe input @var{dims} is a dimension vector where each element is the size of\nthe array in the respective dimension (@pxref{XREFsize,,@code{size}}).  The\nsecond input @var{ind} contains linear indices to be converted.\n\nThe outputs @var{s1}, @dots{}, @var{sN} contain the converted subscripts.\n\nBackground: Array elements can be specified either by a linear index which\nstarts at 1 and runs through the number of elements in the array, or they may\nbe specified with subscripts for the row, column, page, etc.  The functions\n@code{ind2sub} and @code{sub2ind} interconvert between the two forms.\n\nThe linear index traverses dimension 1 (rows), then dimension 2 (columns), then\ndimension 3 (pages), etc.@: until it has numbered all of the elements.\nConsider the following 3-by-3 matrices:\n\n@example\n@group\n[1, 4, 7]     [(1,1), (1,2), (1,3)]\n[2, 5, 8] ==> [(2,1), (2,2), (2,3)]\n[3, 6, 9]     [(3,1), (3,2), (3,3)]\n@end group\n@end example\n\n@noindent\nThe left matrix contains the linear indices for each matrix element.  The right\nmatrix shows the subscript tuples for the same matrix.\n\nThe following example shows how to convert the linear indices @code{2} and\n@code{8} to appropriate subscripts of a 3-by-3 matrix.\n\n@example\n@group\nind = [2, 8];\n[r, c] = ind2sub ([3, 3], ind)\n    @xresult{} r =  2   2\n    @xresult{} c =  1   3\n@end group\n@end example\n\nIf the number of output subscripts exceeds the number of dimensions, the\nexceeded dimensions are set to @code{1}.  On the other hand, if fewer\nsubscripts than dimensions are provided, the exceeding dimensions are merged\ninto the final requested dimension.  For clarity, consider the following\nexamples:\n\n@example\n@group\nind  = [2, 8];\ndims = [3, 3];\n## same as dims = [3, 3, 1]\n[r, c, s] = ind2sub (dims, ind)\n    @xresult{} r =  2   2\n    @xresult{} c =  1   3\n    @xresult{} s =  1   1\n## same as dims = [9]\nr = ind2sub (dims, ind)\n    @xresult{} r =  2   8\n@end group\n@end example\n@seealso{sub2ind, size}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value_list retval;\n\n  int nd = (nargout == 0) ? 1 : nargout;\n\n  dim_vector dv = get_dim_vector (args(0), \"ind2sub\").redim (nargout);\n\n  // Redim for 1 will give us a column vector but we want a row vector.\n  if (nd == 1)\n    std::swap (dv(0), dv(1));\n\n  try\n    {\n      retval = Array<octave_value> (ind2sub (dv, args(1).index_vector ()));\n\n      if (nd == 1)\n        retval(0) = retval(1);\n    }\n  catch (const index_exception& ie)\n    {\n      error (\"ind2sub: invalid index %s\", ie.what ());\n    }\n\n  return retval;\n}\n\n/*\n## Examples\n%!test\n%! [r, c] = ind2sub ([3, 3], [2, 8]);\n%! assert (r, [2, 2]);\n%! assert (c, [1, 3]);\n\n%!test\n%! [r, c, s] = ind2sub ([3, 3], [2, 8]);\n%! assert (r, [2, 2]);\n%! assert (c, [1, 3]);\n%! assert (s, [1, 1]);\n%! [r, c, s] = ind2sub ([3, 3, 1], [2, 8]);\n%! assert (r, [2, 2]);\n%! assert (c, [1, 3]);\n%! assert (s, [1, 1]);\n\n%!test\n%! r = ind2sub ([3, 3], [2, 8]);\n%! assert (r, [2, 8]);\n%! r = ind2sub (9, [2, 8]);\n%! assert (r, [2, 8]);\n\n## 3-dimensional test\n%!test\n%! [r, c, s] = ind2sub ([2, 2, 2], 1:8);\n%! assert (r, [1, 2, 1, 2, 1, 2, 1, 2]);\n%! assert (c, [1, 1, 2, 2, 1, 1, 2, 2]);\n%! assert (s, [1, 1, 1, 1, 2, 2, 2, 2]);\n%! [r, c] = ind2sub ([2, 2, 2], 1:8);\n%! assert (r, [1, 2, 1, 2, 1, 2, 1, 2]);\n%! assert (c, [1, 1, 2, 2, 3, 3, 4, 4]);\n%! r = ind2sub ([2, 2, 2], 1:8);\n%! assert (r, 1:8);\n\n## Indexing beyond specified size (bug #62184)\n%!assert <*62184> (ind2sub (1, 2), 2)\n%!assert <*62184> (ind2sub ([3,3], 10), 10)\n%!test <*62184>\n%! [r,c] = ind2sub ([3,3], 10);\n%! assert ([r, c], [1, 4]);\n%!test <*62184>\n%! [r,c,p] = ind2sub ([3,3], 10);\n%! assert ([r, c, p], [1, 1, 2]);\n\n## Test input validation\n%!error <DIMS must contain integers> ind2sub ([2, -2], 3)\n%!error <invalid index> ind2sub ([2, 2, 2], -1:8)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/tril.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include \"Array.h\"\n#include \"Sparse.h\"\n#include \"mx-base.h\"\n\n#include \"ov.h\"\n#include \"Cell.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// The bulk of the work.\ntemplate <typename T>\nstatic Array<T>\ndo_tril (const Array<T>& a, octave_idx_type k, bool pack)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n  const T *avec = a.data ();\n  octave_idx_type zero = 0;\n\n  if (pack)\n    {\n      octave_idx_type j1 = std::min (std::max (zero, k), nc);\n      octave_idx_type j2 = std::min (std::max (zero, nr + k), nc);\n      octave_idx_type n = j1 * nr + ((j2 - j1) * (nr-(j1-k) + nr-(j2-1-k))) / 2;\n      Array<T> r (dim_vector (n, 1));\n      T *rvec = r.rwdata ();\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_idx_type ii = std::min (std::max (zero, j - k), nr);\n          rvec = std::copy (avec + ii, avec + nr, rvec);\n          avec += nr;\n        }\n\n      return r;\n    }\n  else\n    {\n      Array<T> r (a.dims ());\n      T *rvec = r.rwdata ();\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_idx_type ii = std::min (std::max (zero, j - k), nr);\n          std::fill (rvec, rvec + ii, T ());\n          std::copy (avec + ii, avec + nr, rvec + ii);\n          avec += nr;\n          rvec += nr;\n        }\n\n      return r;\n    }\n}\n\ntemplate <typename T>\nstatic Array<T>\ndo_triu (const Array<T>& a, octave_idx_type k, bool pack)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n  const T *avec = a.data ();\n  octave_idx_type zero = 0;\n\n  if (pack)\n    {\n      octave_idx_type j1 = std::min (std::max (zero, k), nc);\n      octave_idx_type j2 = std::min (std::max (zero, nr + k), nc);\n      octave_idx_type n\n        = ((j2 - j1) * ((j1+1-k) + (j2-k))) / 2 + (nc - j2) * nr;\n      Array<T> r (dim_vector (n, 1));\n      T *rvec = r.rwdata ();\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_idx_type ii = std::min (std::max (zero, j + 1 - k), nr);\n          rvec = std::copy (avec, avec + ii, rvec);\n          avec += nr;\n        }\n\n      return r;\n    }\n  else\n    {\n      Array<T> r (a.dims ());\n      T *rvec = r.rwdata ();\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_idx_type ii = std::min (std::max (zero, j + 1 - k), nr);\n          std::copy (avec, avec + ii, rvec);\n          std::fill (rvec + ii, rvec + nr, T ());\n          avec += nr;\n          rvec += nr;\n        }\n\n      return r;\n    }\n}\n\n// These two are by David Bateman.\n// FIXME: optimizations possible.  \"pack\" support missing.\n\ntemplate <typename T>\nstatic Sparse<T>\ndo_tril (const Sparse<T>& a, octave_idx_type k, bool pack)\n{\n  if (pack) // FIXME\n    error (R\"(tril: \"pack\" not implemented for sparse matrices)\");\n\n  Sparse<T> m = a;\n  octave_idx_type nc = m.cols ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n      if (m.ridx (i) < j-k)\n        m.data(i) = 0.;\n\n  m.maybe_compress (true);\n\n  return m;\n}\n\ntemplate <typename T>\nstatic Sparse<T>\ndo_triu (const Sparse<T>& a, octave_idx_type k, bool pack)\n{\n  if (pack) // FIXME\n    error (R\"(triu: \"pack\" not implemented for sparse matrices)\");\n\n  Sparse<T> m = a;\n  octave_idx_type nc = m.cols ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n      if (m.ridx (i) > j-k)\n        m.data(i) = 0.;\n\n  m.maybe_compress (true);\n  return m;\n}\n\n// Convenience dispatchers.\ntemplate <typename T>\nstatic Array<T>\ndo_trilu (const Array<T>& a, octave_idx_type k, bool lower, bool pack)\n{\n  return lower ? do_tril (a, k, pack) : do_triu (a, k, pack);\n}\n\ntemplate <typename T>\nstatic Sparse<T>\ndo_trilu (const Sparse<T>& a, octave_idx_type k, bool lower, bool pack)\n{\n  return lower ? do_tril (a, k, pack) : do_triu (a, k, pack);\n}\n\nstatic octave_value\ndo_trilu (const std::string& name,\n          const octave_value_list& args)\n{\n  bool lower = (name == \"tril\");\n\n  int nargin = args.length ();\n  bool pack = false;\n\n  if (nargin >= 2 && args(nargin-1).is_string ())\n    {\n      pack = (args(nargin-1).string_value () == \"pack\");\n      nargin--;\n    }\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_idx_type k = 0;\n  if (nargin == 2)\n    k = args(1).idx_type_value (true);\n\n  octave_value arg = args(0);\n\n  const dim_vector& dims = arg.dims ();\n  if (dims.ndims () != 2)\n    error (\"%s: need a 2-D matrix\", name.c_str ());\n  else if (k < -dims(0))\n    k = -dims(0);\n  else if (k > dims(1))\n    k = dims(1);\n\n  octave_value retval;\n\n  switch (arg.builtin_type ())\n    {\n    case btyp_double:\n      if (arg.issparse ())\n        retval = do_trilu (arg.sparse_matrix_value (), k, lower, pack);\n      else\n        retval = do_trilu (arg.array_value (), k, lower, pack);\n      break;\n\n    case btyp_complex:\n      if (arg.issparse ())\n        retval = do_trilu (arg.sparse_complex_matrix_value (), k, lower,\n                           pack);\n      else\n        retval = do_trilu (arg.complex_array_value (), k, lower, pack);\n      break;\n\n    case btyp_bool:\n      if (arg.issparse ())\n        retval = do_trilu (arg.sparse_bool_matrix_value (), k, lower,\n                           pack);\n      else\n        retval = do_trilu (arg.bool_array_value (), k, lower, pack);\n      break;\n\n#define ARRAYCASE(TYP)                                                  \\\n      case btyp_ ## TYP:                                                \\\n        retval = do_trilu (arg.TYP ## _array_value (), k, lower, pack); \\\n        break\n\n      ARRAYCASE (float);\n      ARRAYCASE (float_complex);\n      ARRAYCASE (int8);\n      ARRAYCASE (int16);\n      ARRAYCASE (int32);\n      ARRAYCASE (int64);\n      ARRAYCASE (uint8);\n      ARRAYCASE (uint16);\n      ARRAYCASE (uint32);\n      ARRAYCASE (uint64);\n      ARRAYCASE (char);\n\n#undef ARRAYCASE\n\n    default:\n      {\n        // Generic code that works on octave-values, that is slow\n        // but will also work on arbitrary user types\n        if (pack) // FIXME\n          error (R\"(%s: \"pack\" not implemented for class %s)\",\n                 name.c_str (), arg.class_name ().c_str ());\n\n        octave_value tmp = arg;\n        if (arg.isempty ())\n          return arg;\n\n        octave_idx_type nr = dims(0);\n        octave_idx_type nc = dims(1);\n\n        // The sole purpose of this code is to force the correct matrix size.\n        // This would not be necessary if the octave_value resize function\n        // allowed a fill_value.  It also allows odd attributes in some user\n        // types to be handled.  With a fill_value, it should be replaced with\n        //\n        // octave_value_list ov_idx;\n        // tmp = tmp.resize(dim_vector (0,0)).resize (dims, fill_value);\n\n        octave_value_list ov_idx;\n        std::list<octave_value_list> idx_tmp;\n        ov_idx(1) = static_cast<double> (nc+1);\n        ov_idx(0) = range<double> (1, nr);\n        idx_tmp.push_back (ov_idx);\n        ov_idx(1) = static_cast<double> (nc);\n        tmp = tmp.resize (dim_vector (0, 0));\n        tmp = tmp.subsasgn (\"(\", idx_tmp, arg.index_op (ov_idx));\n        tmp = tmp.resize (dims);\n\n        octave_idx_type one = 1;\n\n        if (lower)\n          {\n            octave_idx_type st = std::min (nc, nr + k);\n\n            for (octave_idx_type j = 1; j <= st; j++)\n              {\n                octave_idx_type nr_limit = std::max (one, j - k);\n                ov_idx(1) = static_cast<double> (j);\n                ov_idx(0) = range<double> (nr_limit, nr);\n                std::list<octave_value_list> idx;\n                idx.push_back (ov_idx);\n\n                tmp = tmp.subsasgn (\"(\", idx, arg.index_op (ov_idx));\n              }\n          }\n        else\n          {\n            octave_idx_type st = std::max (k + 1, one);\n\n            for (octave_idx_type j = st; j <= nc; j++)\n              {\n                octave_idx_type nr_limit = std::min (nr, j - k);\n                ov_idx(1) = static_cast<double> (j);\n                ov_idx(0) = range<double> (1, nr_limit);\n                std::list<octave_value_list> idx;\n                idx.push_back (ov_idx);\n\n                tmp = tmp.subsasgn (\"(\", idx, arg.index_op (ov_idx));\n              }\n          }\n\n        retval = tmp;\n      }\n    }\n\n  return retval;\n}\n\nDEFUN (tril, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{A_LO} =} tril (@var{A})\n@deftypefnx {} {@var{A_LO} =} tril (@var{A}, @var{k})\n@deftypefnx {} {@var{A_LO} =} tril (@var{A}, @var{k}, @var{pack})\nReturn a new matrix formed by extracting the lower triangular part of the\nmatrix @var{A}, and setting all other elements to zero.\n\nThe optional second argument specifies how many diagonals above or below the\nmain diagonal should also be set to zero.  The default value of @var{k} is\nzero which includes the main diagonal as part of the result.  If the value of\n@var{k} is a nonzero integer then the selection of elements starts at an offset\nof @var{k} diagonals above the main diagonal for positive @var{k} or below the\nmain diagonal for negative @var{k}.  The absolute value of @var{k} may not be\ngreater than the number of subdiagonals or superdiagonals.\n\nExample 1 : exclude main diagonal\n\n@example\n@group\ntril (ones (3), -1)\n     @xresult{}  0  0  0\n         1  0  0\n         1  1  0\n@end group\n@end example\n\n@noindent\n\nExample 2 : include first superdiagonal\n\n@example\n@group\ntril (ones (3), 1)\n     @xresult{}  1  1  0\n         1  1  1\n         1  1  1\n@end group\n@end example\n\nIf the optional third argument @qcode{\"pack\"} is given then the extracted\nelements are not inserted into a matrix, but instead stacked column-wise one\nabove another, and returned as a column vector.\n@seealso{triu, istril, diag}\n@end deftypefn */)\n{\n  return do_trilu (\"tril\", args);\n}\n\nDEFUN (triu, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{A_UP} =} triu (@var{A})\n@deftypefnx {} {@var{A_UP} =} triu (@var{A}, @var{k})\n@deftypefnx {} {@var{A_UP} =} triu (@var{A}, @var{k}, @var{pack})\nReturn a new matrix formed by extracting the upper triangular part of the\nmatrix @var{A}, and setting all other elements to zero.\n\nThe optional second argument specifies how many diagonals above or below the\nmain diagonal should also be set to zero.  The default value of @var{k} is\nzero which includes the main diagonal as part of the result.  If the value of\n@var{k} is a nonzero integer then the selection of elements starts at an offset\nof @var{k} diagonals above the main diagonal for positive @var{k} or below the\nmain diagonal for negative @var{k}.  The absolute value of @var{k} may not be\ngreater than the number of subdiagonals or superdiagonals.\n\nExample 1 : exclude main diagonal\n\n@example\n@group\ntriu (ones (3), 1)\n     @xresult{}  0  1  1\n         0  0  1\n         0  0  0\n@end group\n@end example\n\n@noindent\n\nExample 2 : include first subdiagonal\n\n@example\n@group\ntriu (ones (3), -1)\n     @xresult{}  1  1  1\n         1  1  1\n         0  1  1\n@end group\n@end example\n\nIf the optional third argument @qcode{\"pack\"} is given then the extracted\nelements are not inserted into a matrix, but instead stacked column-wise one\nabove another, and returned as a column vector.\n@seealso{tril, istriu, diag}\n@end deftypefn */)\n{\n  return do_trilu (\"triu\", args);\n}\n\n/*\n%!shared a, l2, l1, l0, lm1, lm2, lm3, lm4\n%! a = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12];\n%!\n%! l2 = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12];\n%! l1 = [1, 2, 0; 4, 5, 6; 7, 8, 9; 10, 11, 12];\n%! l0 = [1, 0, 0; 4, 5, 0; 7, 8, 9; 10, 11, 12];\n%! lm1 = [0, 0, 0; 4, 0, 0; 7, 8, 0; 10, 11, 12];\n%! lm2 = [0, 0, 0; 0, 0, 0; 7, 0, 0; 10, 11, 0];\n%! lm3 = [0, 0, 0; 0, 0, 0; 0, 0, 0; 10, 0, 0];\n%! lm4 = [0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0];\n%!\n%!assert (tril (a, 3), l2)\n%!assert (tril (a, 2), l2)\n%!assert (tril (a, 1), l1)\n%!assert (tril (a, 0), l0)\n%!assert (tril (a), l0)\n%!assert (tril (a, -1), lm1)\n%!assert (tril (a, -2), lm2)\n%!assert (tril (a, -3), lm3)\n%!assert (tril (a, -4), lm4)\n%!assert (tril (a, -5), lm4)\n\n%!shared a, u3, u2, u1, u0, um1, um2, um3\n%!\n%! a = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12];\n%!\n%! u3 = [0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0];\n%! u2 = [0, 0, 3; 0, 0, 0; 0, 0, 0; 0, 0, 0];\n%! u1 = [0, 2, 3; 0, 0, 6; 0, 0, 0; 0, 0, 0];\n%! u0 = [1, 2, 3; 0, 5, 6; 0, 0, 9; 0, 0, 0];\n%! um1 = [1, 2, 3; 4, 5, 6; 0, 8, 9; 0, 0, 12];\n%! um2 = [1, 2, 3; 4, 5, 6; 7, 8, 9; 0, 11, 12];\n%! um3 = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12];\n%!\n%!assert (triu (a, 4), u3)\n%!assert (triu (a, 3), u3)\n%!assert (triu (a, 2), u2)\n%!assert (triu (a, 1), u1)\n%!assert (triu (a, 0), u0)\n%!assert (triu (a), u0)\n%!assert (triu (a, -1), um1)\n%!assert (triu (a, -2), um2)\n%!assert (triu (a, -3), um3)\n%!assert (triu (a, -4), um3)\n\n%!error tril ()\n%!error triu ()\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/util/typecast.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <limits>\n\n#include \"mx-base.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"unwind-prot.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic dim_vector\nget_vec_dims (const dim_vector& old_dims, octave_idx_type n)\n{\n  if (old_dims.ndims () == 2 && old_dims(0) == 1)\n    return dim_vector (1, n);\n  else if (old_dims.ndims () == 2 && old_dims(0) == 0 && old_dims(1) == 0)\n    return dim_vector ();\n  else\n    return dim_vector (n, 1);\n}\n\ntemplate <typename ArrayType>\nstatic void\nget_data_and_bytesize (const ArrayType& array,\n                       const void *&data,\n                       octave_idx_type& byte_size,\n                       dim_vector& old_dims,\n                       unwind_protect& frame)\n{\n  // The array given may be a temporary, constructed from a scalar or sparse\n  // array.  This will ensure the data will be deallocated after we exit.\n  frame.add_delete (new ArrayType (array));\n\n  data = reinterpret_cast<const void *> (array.data ());\n  byte_size = array.byte_size ();\n\n  old_dims = array.dims ();\n}\n\ntemplate <typename ArrayType>\nstatic ArrayType\nreinterpret_copy (const void *data, octave_idx_type byte_size,\n                  const dim_vector& old_dims)\n{\n  typedef typename ArrayType::element_type T;\n  octave_idx_type n = byte_size / sizeof (T);\n\n  if (n * static_cast<int> (sizeof (T)) != byte_size)\n    error (\"typecast: incorrect number of input values to make output value\");\n\n  ArrayType retval (get_vec_dims (old_dims, n));\n  T *dest = retval.rwdata ();\n  std::memcpy (dest, data, n * sizeof (T));\n\n  return retval;\n}\n\ntemplate <typename ArrayType>\nstatic ArrayType\nreinterpret_int_copy (const void *data, octave_idx_type byte_size,\n                      const dim_vector& old_dims)\n{\n  typedef typename ArrayType::element_type T;\n  typedef typename T::val_type VT;\n  octave_idx_type n = byte_size / sizeof (T);\n\n  if (n * static_cast<int> (sizeof (T)) != byte_size)\n    error (\"typecast: incorrect number of input values to make output value\");\n\n  ArrayType retval (get_vec_dims (old_dims, n));\n  VT *dest = reinterpret_cast<VT *> (retval.rwdata ());\n  std::memcpy (dest, data, n * sizeof (VT));\n\n  return retval;\n}\n\nDEFUN (typecast, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} typecast (@var{x}, \"@var{class}\")\nReturn a new array @var{y} resulting from interpreting the data of @var{x}\nin memory as data of the numeric class @var{class}.\n\nBoth the class of @var{x} and @var{class} must be one of the built-in\nnumeric classes:\n\n@example\n@group\n\"logical\"\n\"char\"\n\"int8\"\n\"int16\"\n\"int32\"\n\"int64\"\n\"uint8\"\n\"uint16\"\n\"uint32\"\n\"uint64\"\n\"double\"\n\"single\"\n\"double complex\"\n\"single complex\"\n@end group\n@end example\n\n@noindent\nthe last two are only used with @var{class}; they indicate that a\ncomplex-valued result is requested.  Complex arrays are stored in memory as\nconsecutive pairs of real numbers.  The sizes of integer types are given by\ntheir bit counts.  Both logical and char are typically one byte wide;\nhowever, this is not guaranteed by C++.  If your system is IEEE@tie{}754\nconformant, single and double will be 4 bytes and 8 bytes wide, respectively.\n@qcode{\"logical\"} is not allowed for @var{class}.\n\nIf the input is a row vector, the return value is a row vector, otherwise it\nis a column vector.\n\nIf the bit length of @var{x} is not divisible by that of @var{class}, an\nerror occurs.\n\nAn example of the use of typecast on a little-endian machine is\n\n@example\n@group\n@var{x} = uint16 ([1, 65535]);\ntypecast (@var{x}, \"uint8\")\n@xresult{} [   1,   0, 255, 255]\n@end group\n@end example\n@seealso{cast, bitpack, bitunpack, swapbytes}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value retval;\n\n  unwind_protect frame;\n\n  const void *data = nullptr;\n  octave_idx_type byte_size = 0;\n  dim_vector old_dims;\n\n  octave_value array = args(0);\n\n  if (array.islogical ())\n    get_data_and_bytesize (array.bool_array_value (), data, byte_size,\n                           old_dims, frame);\n  else if (array.is_string ())\n    get_data_and_bytesize (array.char_array_value (), data, byte_size,\n                           old_dims, frame);\n  else if (array.isinteger ())\n    {\n      if (array.is_int8_type ())\n        get_data_and_bytesize (array.int8_array_value (), data, byte_size,\n                               old_dims, frame);\n      else if (array.is_int16_type ())\n        get_data_and_bytesize (array.int16_array_value (), data, byte_size,\n                               old_dims, frame);\n      else if (array.is_int32_type ())\n        get_data_and_bytesize (array.int32_array_value (), data, byte_size,\n                               old_dims, frame);\n      else if (array.is_int64_type ())\n        get_data_and_bytesize (array.int64_array_value (), data, byte_size,\n                               old_dims, frame);\n      else if (array.is_uint8_type ())\n        get_data_and_bytesize (array.uint8_array_value (), data, byte_size,\n                               old_dims, frame);\n      else if (array.is_uint16_type ())\n        get_data_and_bytesize (array.uint16_array_value (), data, byte_size,\n                               old_dims, frame);\n      else if (array.is_uint32_type ())\n        get_data_and_bytesize (array.uint32_array_value (), data, byte_size,\n                               old_dims, frame);\n      else if (array.is_uint64_type ())\n        get_data_and_bytesize (array.uint64_array_value (), data, byte_size,\n                               old_dims, frame);\n    }\n  else if (array.iscomplex ())\n    {\n      if (array.is_single_type ())\n        get_data_and_bytesize (array.float_complex_array_value (), data,\n                               byte_size, old_dims, frame);\n      else\n        get_data_and_bytesize (array.complex_array_value (), data,\n                               byte_size, old_dims, frame);\n    }\n  else if (array.isreal ())\n    {\n      if (array.is_single_type ())\n        get_data_and_bytesize (array.float_array_value (), data, byte_size,\n                               old_dims, frame);\n      else\n        get_data_and_bytesize (array.array_value (), data, byte_size,\n                               old_dims, frame);\n    }\n  else\n    error (\"typecast: invalid input CLASS: %s\",\n           array.class_name ().c_str ());\n\n  std::string numclass = args(1).string_value ();\n  std::transform (numclass.begin (), numclass.end (), numclass.begin (),\n                  tolower);\n\n  if (numclass.size () == 0)\n    ;\n  else if (numclass == \"char\")\n    retval = octave_value (reinterpret_copy<charNDArray>\n                           (data, byte_size, old_dims),\n                           array.is_dq_string () ? '\"' : '\\'');\n  else if (numclass[0] == 'i')\n    {\n      if (numclass == \"int8\")\n        retval = reinterpret_int_copy<int8NDArray> (data, byte_size, old_dims);\n      else if (numclass == \"int16\")\n        retval = reinterpret_int_copy<int16NDArray> (data, byte_size, old_dims);\n      else if (numclass == \"int32\")\n        retval = reinterpret_int_copy<int32NDArray> (data, byte_size, old_dims);\n      else if (numclass == \"int64\")\n        retval = reinterpret_int_copy<int64NDArray> (data, byte_size, old_dims);\n    }\n  else if (numclass[0] == 'u')\n    {\n      if (numclass == \"uint8\")\n        retval = reinterpret_int_copy<uint8NDArray> (data, byte_size, old_dims);\n      else if (numclass == \"uint16\")\n        retval = reinterpret_int_copy<uint16NDArray> (data, byte_size,\n                 old_dims);\n      else if (numclass == \"uint32\")\n        retval = reinterpret_int_copy<uint32NDArray> (data, byte_size,\n                 old_dims);\n      else if (numclass == \"uint64\")\n        retval = reinterpret_int_copy<uint64NDArray> (data, byte_size,\n                 old_dims);\n    }\n  else if (numclass == \"single\")\n    retval = reinterpret_copy<FloatNDArray> (data, byte_size, old_dims);\n  else if (numclass == \"double\")\n    retval = reinterpret_copy<NDArray> (data, byte_size, old_dims);\n  else if (numclass == \"single complex\")\n    retval = reinterpret_copy<FloatComplexNDArray> (data, byte_size,\n             old_dims);\n  else if (numclass == \"double complex\")\n    retval = reinterpret_copy<ComplexNDArray> (data, byte_size, old_dims);\n\n  if (retval.is_undefined ())\n    error (\"typecast: cannot convert to %s class\", numclass.c_str ());\n\n  return retval;\n}\n\n/*\n%!assert (typecast (int64 (0), \"char\"),   char (zeros (1, 8)))\n%!assert (typecast (int64 (0), \"int8\"),   zeros (1, 8, \"int8\"))\n%!assert (typecast (int64 (0), \"uint8\"),  zeros (1, 8, \"uint8\"))\n%!assert (typecast (int64 (0), \"int16\"),  zeros (1, 4, \"int16\"))\n%!assert (typecast (int64 (0), \"uint16\"), zeros (1, 4, \"uint16\"))\n%!assert (typecast (int64 (0), \"int32\"),  zeros (1, 2, \"int32\"))\n%!assert (typecast (int64 (0), \"uint32\"), zeros (1, 2, \"uint32\"))\n%!assert (typecast (int64 (0), \"int64\"),  zeros (1, 1, \"int64\"))\n%!assert (typecast (int64 (0), \"uint64\"), zeros (1, 1, \"uint64\"))\n%!assert (typecast (int64 (0), \"single\"), zeros (1, 2, \"single\"))\n%!assert (typecast (int64 (0), \"double\"), 0)\n%!assert (typecast (int64 (0), \"single complex\"), single (0))\n%!assert (typecast (int64 ([0 0]), \"double complex\"), 0)\n\n%!assert (typecast ([],   \"double\"), [])\n%!assert (typecast (0,    \"double\"), 0)\n%!assert (typecast (inf,  \"double\"), inf)\n%!assert (typecast (-inf, \"double\"), -inf)\n%!assert (typecast (NaN,  \"double\"), NaN)\n\n%!error typecast ()\n%!error typecast (1)\n%!error typecast (1, 2, 3)\n%!error typecast (1, \"invalid\")\n%!error typecast (int8 (0), \"double\")\n*/\n\ntemplate <typename ArrayType>\nArrayType\ndo_bitpack (const boolNDArray& bitp)\n{\n  typedef typename ArrayType::element_type T;\n  octave_idx_type n\n    = bitp.numel () / (sizeof (T) * std::numeric_limits<unsigned char>::digits);\n\n  if (n * static_cast<int> (sizeof (T)) *\n      std::numeric_limits<unsigned char>::digits != bitp.numel ())\n    error (\"bitpack: incorrect number of bits to make up output value\");\n\n  ArrayType retval (get_vec_dims (bitp.dims (), n));\n\n  const bool *bits = bitp.data ();\n  char *packed = reinterpret_cast<char *> (retval.rwdata ());\n\n  octave_idx_type m = n * sizeof (T);\n\n  for (octave_idx_type i = 0; i < m; i++)\n    {\n      char c = bits[0];\n      for (int j = 1; j < std::numeric_limits<unsigned char>::digits; j++)\n        c |= bits[j] << j;\n\n      packed[i] = c;\n      bits += std::numeric_limits<unsigned char>::digits;\n    }\n\n  return retval;\n}\n\nDEFUN (bitpack, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} bitpack (@var{x}, @var{class})\nReturn a new array @var{y} resulting from interpreting the logical array\n@var{x} as raw bit patterns for data of the numeric class @var{class}.\n\n@var{class} must be one of the built-in numeric classes:\n\n@example\n@group\n\"double\"\n\"single\"\n\"double complex\"\n\"single complex\"\n\"char\"\n\"int8\"\n\"int16\"\n\"int32\"\n\"int64\"\n\"uint8\"\n\"uint16\"\n\"uint32\"\n\"uint64\"\n@end group\n@end example\n\nThe number of elements of @var{x} should be divisible by the bit length of\n@var{class}.  If it is not, excess bits are discarded.  Bits come in\nincreasing order of significance, i.e., @code{x(1)} is bit 0, @code{x(2)} is\nbit 1, etc.\n\nThe result is a row vector if @var{x} is a row vector, otherwise it is a\ncolumn vector.\n@seealso{bitunpack, typecast}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  if (! args(0).islogical ())\n    error (\"bitpack: X must be a logical array\");\n\n  octave_value retval;\n\n  boolNDArray bitp = args(0).bool_array_value ();\n\n  std::string numclass = args(1).string_value ();\n\n  if (numclass.size () == 0)\n    ;\n  else if (numclass == \"char\")\n    retval = octave_value (do_bitpack<charNDArray> (bitp), '\\'');\n  else if (numclass[0] == 'i')\n    {\n      if (numclass == \"int8\")\n        retval = do_bitpack<int8NDArray> (bitp);\n      else if (numclass == \"int16\")\n        retval = do_bitpack<int16NDArray> (bitp);\n      else if (numclass == \"int32\")\n        retval = do_bitpack<int32NDArray> (bitp);\n      else if (numclass == \"int64\")\n        retval = do_bitpack<int64NDArray> (bitp);\n    }\n  else if (numclass[0] == 'u')\n    {\n      if (numclass == \"uint8\")\n        retval = do_bitpack<uint8NDArray> (bitp);\n      else if (numclass == \"uint16\")\n        retval = do_bitpack<uint16NDArray> (bitp);\n      else if (numclass == \"uint32\")\n        retval = do_bitpack<uint32NDArray> (bitp);\n      else if (numclass == \"uint64\")\n        retval = do_bitpack<uint64NDArray> (bitp);\n    }\n  else if (numclass == \"single\")\n    retval = do_bitpack<FloatNDArray> (bitp);\n  else if (numclass == \"double\")\n    retval = do_bitpack<NDArray> (bitp);\n  else if (numclass == \"single complex\")\n    retval = do_bitpack<FloatComplexNDArray> (bitp);\n  else if (numclass == \"double complex\")\n    retval = do_bitpack<ComplexNDArray> (bitp);\n\n  if (retval.is_undefined ())\n    error (\"bitpack: cannot pack to %s class\", numclass.c_str ());\n\n  return retval;\n}\n\n/*\n%!assert (bitpack (zeros (1, 8,   \"logical\"), \"char\"),   \"\\0\")\n%!assert (bitpack (zeros (1, 8,   \"logical\"), \"int8\"),   int8 (0))\n%!assert (bitpack (zeros (1, 8,   \"logical\"), \"uint8\"),  uint8 (0))\n%!assert (bitpack (zeros (1, 16,  \"logical\"), \"int16\"),  int16 (0))\n%!assert (bitpack (zeros (1, 16,  \"logical\"), \"uint16\"), uint16 (0))\n%!assert (bitpack (zeros (1, 32,  \"logical\"), \"int32\"),  int32 (0))\n%!assert (bitpack (zeros (1, 32,  \"logical\"), \"uint32\"), uint32 (0))\n%!assert (bitpack (zeros (1, 64,  \"logical\"), \"int64\"),  int64 (0))\n%!assert (bitpack (zeros (1, 64,  \"logical\"), \"uint64\"), uint64 (0))\n%!assert (bitpack (zeros (1, 32,  \"logical\"), \"single\"), single (0))\n%!assert (bitpack (zeros (1, 64,  \"logical\"), \"double\"), double (0))\n%!assert (bitpack (zeros (1, 64,  \"logical\"), \"single complex\"), single (0))\n%!assert (bitpack (zeros (1, 128, \"logical\"), \"double complex\"), double (0))\n\n%!test <54931>\n%! x = false (1, 32);\n%! x(1) = true;\n%! assert (bitpack (x, \"uint32\"), uint32 (1));\n%! x([1, 9]) = true;\n%! assert (bitpack (x, \"uint32\"), uint32 (257));\n\n%!error bitpack ()\n%!error bitpack (1)\n%!error bitpack (1, 2, 3)\n%!error bitpack (1, \"invalid\")\n%!error bitpack (1, \"double\")\n%!error bitpack (false, \"invalid\")\n%!error bitpack (false, \"double\")\n*/\n\ntemplate <typename ArrayType>\nboolNDArray\ndo_bitunpack (const ArrayType& array)\n{\n  typedef typename ArrayType::element_type T;\n  octave_idx_type n = array.numel () * sizeof (T)\n                      * std::numeric_limits<unsigned char>::digits;\n\n  boolNDArray retval (get_vec_dims (array.dims (), n));\n\n  const char *packed = reinterpret_cast<const char *> (array.data ());\n  bool *bits = retval.rwdata ();\n\n  octave_idx_type m = n / std::numeric_limits<unsigned char>::digits;\n\n  for (octave_idx_type i = 0; i < m; i++)\n    {\n      char c = packed[i];\n      bits[0] = c & 1;\n      for (int j = 1; j < std::numeric_limits<unsigned char>::digits; j++)\n        bits[j] = (c >>= 1) & 1;\n      bits += std::numeric_limits<unsigned char>::digits;\n    }\n\n  return retval;\n}\n\nDEFUN (bitunpack, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} bitunpack (@var{x})\nReturn a logical array @var{y} corresponding to the raw bit patterns of\n@var{x}.\n\n@var{x} must belong to one of the built-in numeric classes:\n\n@example\n@group\n\"double\"\n\"single\"\n\"char\"\n\"int8\"\n\"int16\"\n\"int32\"\n\"int64\"\n\"uint8\"\n\"uint16\"\n\"uint32\"\n\"uint64\"\n@end group\n@end example\n\nThe result is a row vector if @var{x} is a row vector; otherwise, it is a\ncolumn vector.\n@seealso{bitpack, typecast}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  if (! (args(0).isnumeric () || args(0).is_string ()))\n    error (\"bitunpack: argument must be a number or a string\");\n\n  octave_value retval;\n\n  octave_value array = args(0);\n\n  if (array.is_string ())\n    retval = do_bitunpack (array.char_array_value ());\n  else if (array.isinteger ())\n    {\n      if (array.is_int8_type ())\n        retval = do_bitunpack (array.int8_array_value ());\n      else if (array.is_int16_type ())\n        retval = do_bitunpack (array.int16_array_value ());\n      else if (array.is_int32_type ())\n        retval = do_bitunpack (array.int32_array_value ());\n      else if (array.is_int64_type ())\n        retval = do_bitunpack (array.int64_array_value ());\n      else if (array.is_uint8_type ())\n        retval = do_bitunpack (array.uint8_array_value ());\n      else if (array.is_uint16_type ())\n        retval = do_bitunpack (array.uint16_array_value ());\n      else if (array.is_uint32_type ())\n        retval = do_bitunpack (array.uint32_array_value ());\n      else if (array.is_uint64_type ())\n        retval = do_bitunpack (array.uint64_array_value ());\n    }\n  else if (array.iscomplex ())\n    {\n      if (array.is_single_type ())\n        retval = do_bitunpack (array.float_complex_array_value ());\n      else\n        retval = do_bitunpack (array.complex_array_value ());\n    }\n  else if (array.isreal ())\n    {\n      if (array.is_single_type ())\n        retval = do_bitunpack (array.float_array_value ());\n      else\n        retval = do_bitunpack (array.array_value ());\n    }\n  else\n    error (\"bitunpack: invalid input class: %s\",\n           array.class_name ().c_str ());\n\n  return retval;\n}\n\n/*\n%!assert (bitunpack (\"\\0\"),       zeros (1, 8,  \"logical\"))\n%!assert (bitunpack (int8 (0)),   zeros (1, 8,  \"logical\"))\n%!assert (bitunpack (uint8 (0)),  zeros (1, 8,  \"logical\"))\n%!assert (bitunpack (int16 (0)),  zeros (1, 16, \"logical\"))\n%!assert (bitunpack (uint16 (0)), zeros (1, 16, \"logical\"))\n%!assert (bitunpack (int32 (0)),  zeros (1, 32, \"logical\"))\n%!assert (bitunpack (uint32 (0)), zeros (1, 32, \"logical\"))\n%!assert (bitunpack (int64 (0)),  zeros (1, 64, \"logical\"))\n%!assert (bitunpack (uint64 (0)), zeros (1, 64, \"logical\"))\n%!assert (bitunpack (single (0)), zeros (1, 32, \"logical\"))\n%!assert (bitunpack (double (0)), zeros (1, 64, \"logical\"))\n%!assert (bitunpack (complex (single (0))), zeros (1, 64, \"logical\"))\n%!assert (bitunpack (complex (double (0))), zeros (1, 128, \"logical\"))\n\n%!error bitunpack ()\n%!error bitunpack (1, 2)\n%!error bitunpack ({})\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/utils.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstring>\n\n#include <fstream>\n#include <ostream>\n#include <string>\n\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"nanosleep-wrapper.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-string.h\"\n#include \"oct-sysdep.h\"\n#include \"pathsearch.h\"\n#include \"quit.h\"\n#include \"str-vec.h\"\n#include \"strcase-wrappers.h\"\n#include \"vasprintf-wrapper.h\"\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"graphics.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"lex.h\"\n#include \"load-path.h\"\n#include \"oct-errno.h\"\n#include \"oct-hist.h\"\n#include \"ovl.h\"\n#include \"ov-range.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Return TRUE if S is a valid identifier.\n\nbool valid_identifier (const char *s)\n{\n  if (! s || ! (isalpha (*s) || *s == '_'))\n    return false;\n\n  while (*++s != '\\0')\n    if (! (isalnum (*s) || *s == '_'))\n      return false;\n\n  return true;\n}\n\nbool\nvalid_identifier (const std::string& s)\n{\n  return valid_identifier (s.c_str ());\n}\n\nDEFUN (isvarname, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isvarname (@var{name})\nReturn true if @var{name} is a valid variable name.\n\nA valid variable name is composed of letters, digits, and underscores (\"_\"),\nand the first character must not be a digit.\n@seealso{iskeyword, exist, who}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value retval = false;\n\n  if (args(0).is_string ())\n    {\n      std::string varname = args(0).string_value ();\n\n      retval = (valid_identifier (varname)\n                && ! iskeyword (varname));\n    }\n\n  return retval;\n}\n\n/*\n%!assert (isvarname (\"foo\"), true)\n%!assert (isvarname (\"_foo\"), true)\n%!assert (isvarname (\"_1\"), true)\n%!assert (isvarname (\"1foo\"), false)\n%!assert (isvarname (\"\"), false)\n%!assert (isvarname (12), false)\n%!assert (isvarname (\"foo+bar\"), false)\n\n%!error isvarname ()\n%!error isvarname (\"foo\", \"bar\")\n*/\n\nbool\nmake_valid_name (std::string& str, const make_valid_name_options& options)\n{\n  // If `isvarname (str)`, no modifications necessary.\n  if (valid_identifier (str) && ! iskeyword (str))\n    return false;\n\n  // Change whitespace followed by lowercase letter to uppercase, except\n  // for the first\n  bool previous = false;\n  bool any_non_space = false;\n  for (char& c : str)\n    {\n      c = ((any_non_space && previous && std::isalpha (c)) ? std::toupper (c)\n           : c);\n      previous = std::isspace (c);\n      any_non_space |= (! previous);  // once true, always true\n    }\n\n  // Remove any whitespace.\n  str.erase (std::remove_if (str.begin(), str.end(),\n                             [] (unsigned char x)\n  { return std::isspace(x); }),\n  str.end());\n  if (str.empty ())\n    str = options.get_prefix ();\n\n  // Add prefix and capitalize first character, if `str` is a reserved\n  // keyword.\n  if (iskeyword (str))\n    {\n      str[0] = std::toupper (str[0]);\n      str = options.get_prefix () + str;\n    }\n\n  // Add prefix if first character is not a letter or underscore.\n  if (! std::isalpha (str[0]) && str[0] != '_')\n    str = options.get_prefix () + str;\n\n  // Replace non alphanumerics or underscores\n  if (options.get_replacement_style () == \"underscore\")\n    for (char& c : str)\n      c = (std::isalnum (c) ? c : '_');\n  else if (options.get_replacement_style () == \"delete\")\n    str.erase (std::remove_if (str.begin(), str.end(),\n                               [] (unsigned char x)\n    { return ! std::isalnum (x) && x != '_'; }),\n  str.end());\n  else if (options.get_replacement_style () == \"hex\")\n    {\n      const std::string permitted_chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n                                          \"abcdefghijklmnopqrstuvwxyz\"\n                                          \"_0123456789\";\n      // Get the first non-permitted char.\n      std::size_t pos = str.find_first_not_of (permitted_chars);\n      // Buffer for hex string \"0xFF\" (+1 for null terminator).\n      char hex_str[5];\n      // Repeat until end of string.\n      while (pos != std::string::npos)\n        {\n          // Replace non-permitted char by it's hex value.\n          std::snprintf (hex_str, sizeof (hex_str), \"0x%02X\", str[pos]);\n          str.replace (pos, 1, hex_str);\n          // Get the next occurrence from the last position.\n          // (-1 for null terminator)\n          pos = str.find_first_not_of (permitted_chars,\n                                       pos + sizeof (hex_str) - 1);\n        }\n    }\n\n  return true;\n}\n\nmake_valid_name_options::make_valid_name_options\n(const octave_value_list& args)\n{\n  auto nargs = args.length ();\n  if (nargs == 0)\n    return;\n\n  // nargs = 2, 4, 6, ... permitted\n  if (nargs % 2)\n    error (\"makeValidName: property/value options must occur in pairs\");\n\n  auto str_to_lower = [] (std::string& s)\n  {\n    std::transform (s.begin(), s.end(), s.begin(),\n                    [] (unsigned char c)\n    { return std::tolower(c); });\n  };\n\n  for (auto i = 0; i < nargs; i = i + 2)\n    {\n      std::string parameter = args(i).xstring_value (\"makeValidName: \"\n                              \"option argument must be a string\");\n      str_to_lower (parameter);\n      if (parameter == \"replacementstyle\")\n        {\n          m_replacement_style = args(i + 1).xstring_value (\"makeValidName: \"\n                                \"'ReplacementStyle' value must be a string\");\n          str_to_lower (m_replacement_style);\n          if ((m_replacement_style != \"underscore\")\n              && (m_replacement_style != \"delete\")\n              && (m_replacement_style != \"hex\"))\n            error (\"makeValidName: invalid 'ReplacementStyle' value '%s'\",\n                   m_replacement_style.c_str ());\n        }\n      else if (parameter == \"prefix\")\n        {\n          m_prefix = args(i + 1).xstring_value (\"makeValidName: \"\n                                                \"'Prefix' value must be a string\");\n          if (! valid_identifier (m_prefix)\n              || iskeyword (m_prefix))\n            error (\"makeValidName: invalid 'Prefix' value '%s'\",\n                   m_prefix.c_str ());\n        }\n      else\n        error (\"makeValidName: unknown property '%s'\", parameter.c_str ());\n    }\n}\n\nDEFUN (__make_valid_name__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{varname} =} __make_valid_name__ (@var{str})\n@deftypefnx {} {@var{varname} =} __make_valid_name__ (@var{str}, @qcode{\"ReplacementStyle\"})\n@deftypefnx {} {@var{varname} =} __make_valid_name__ (@var{str}, @qcode{\"ReplacementStyle\"}, @qcode{\"Prefix\"})\n@deftypefnx {} {[@var{varname}, @var{ismodified}] =} __make_valid_name__ (@dots{})\nReturn a valid variable name @var{varname} from input @var{str}.\n\nFor more documentation, see @code{matlab.lang.makeValidName}.\n\n@seealso{isvarname, matlab.lang.makeValidName}\n@end deftypefn */)\n{\n  auto nargin = args.length ();\n  if (nargin < 1)\n    print_usage ();\n\n  make_valid_name_options options (args.slice (1, nargin - 1));\n\n  if (args(0).is_string ())\n    {\n      std::string varname = args(0).string_value ();\n      bool is_modified = make_valid_name (varname, options);\n      return ovl (varname, is_modified);\n    }\n  else if (args(0).iscellstr ())\n    {\n      Array<std::string> varnames = args(0).cellstr_value ();\n      Array<bool> is_modified (varnames.dims ());\n      for (auto i = 0; i < varnames.numel (); i++)\n        is_modified(i) = make_valid_name (varnames(i), options);\n      return ovl (varnames, is_modified);\n    }\n  else\n    error (\"makeValidName: STR must be a string or cellstr\");\n}\n\n// Return TRUE if F and G are both names for the same file.\n\nbool\nsame_file (const std::string& f, const std::string& g)\n{\n  return sys::same_file (f, g);\n}\n\nDEFUN (is_same_file, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{same} =} is_same_file (@var{filepath1}, @var{filepath2})\nReturn true if @var{filepath1} and @var{filepath2} refer to the same file.\n\nIf either @var{filepath1} or @var{filepath2} is a cell array of strings, then\nan array of the same size is returned, containing the values described above\nfor every member of the cell array.  The other argument may also be a cell\narray of strings (of the same size) or a string.\n\nProgramming Notes: Depending on the operating system and file system, the same\nfile or folder can be referred to with different paths.  In particular, paths\non the Windows platform may differ in case (@file{file1} vs.@: @file {FILE1}),\nfile separator (@samp{\\} vs.@: @samp{/}), and format (@file{A~spaces.txt} (8.3\nconvention) vs.@: @file{A filename with spaces.txt}).  This function returns\ntrue if the paths in @var{filepath1} and @var{filepath2} actually refer to the\nsame file or folder, and false otherwise.\n\nNote that unlike @code{strcmp}, this function requires that @var{filepath1}\nand @var{filepath2} exist, as well as point to the same location, in order to\nreturn true.\n\n@seealso{canonicalize_file_name, strcmp}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value retval;\n\n  bool s1_string = args(0).is_string ();\n  bool s1_cellstr = args(0).iscellstr ();\n  bool s2_string = args(1).is_string ();\n  bool s2_cellstr = args(1).iscellstr ();\n\n  if (s1_string && s2_string)\n    {\n      std::string file1 = args(0).string_value ();\n      std::string file2 = args(1).string_value ();\n\n      retval = sys::same_file (file1, file2);\n    }\n  else if ((s1_string && s2_cellstr) || (s1_cellstr && s2_string))\n    {\n      octave_value str_arg, cellstr_arg;\n\n      if (s1_string)\n        {\n          str_arg = args(0);\n          cellstr_arg = args(1);\n        }\n      else\n        {\n          str_arg = args(1);\n          cellstr_arg = args(0);\n        }\n\n      const Array<std::string> cellstr = cellstr_arg.cellstr_value ();\n      const std::string str = str_arg.string_value ();\n\n      boolNDArray output (cellstr.dims (), false);\n\n      for (octave_idx_type idx = 0; idx < cellstr.numel (); idx++)\n        output(idx) = sys::same_file (str, cellstr(idx));\n\n      retval = output;\n    }\n  else if (s1_cellstr && s2_cellstr)\n    {\n      const Array<std::string> cellstr1 = args(0).cellstr_value ();\n      const Array<std::string> cellstr2 = args(1).cellstr_value ();\n\n      const dim_vector size1 = cellstr1.dims ();\n      const dim_vector size2 = cellstr2.dims ();\n\n      if (size1 != size2)\n        error (\"is_same_file: cellstr arrays FILEPATH1 and FILEPATH2 must be the same size\");\n\n      boolNDArray output (size1, false);\n\n      for (octave_idx_type idx = 0; idx < cellstr1.numel (); idx++)\n        output(idx) = sys::same_file (cellstr1(idx), cellstr2(idx));\n\n      retval = output;\n    }\n  else\n    error (\"is_same_file: FILEPATH1 and FILEPATH2 must be strings or cell arrays of strings\");\n\n  return retval;\n}\n\n/*\n%!testif ; ! ispc () && isfolder (\"~\")\n%! assert (is_same_file (\"~\", tilde_expand (\"~\")));\n%!testif ; ispc ()\n%! assert (is_same_file (lower (tempdir ()), upper (tempdir ())), true);\n%!assert (is_same_file ({pwd(), \".\", tempdir()}, canonicalize_file_name (\".\")),\n%!        [true, true, false])\n\n%!error is_same_file ()\n%!error is_same_file (\"foo\")\n%!error is_same_file (\"foo\", \"bar\", \"baz\")\n%!error <must be strings or cell arrays of strings> is_same_file (\"foo\", 1)\n%!error <must be strings or cell arrays of strings> is_same_file (1, \"foo\")\n%!error <must be strings or cell arrays of strings> is_same_file (\"foo\", {1})\n%!error <must be strings or cell arrays of strings> is_same_file ({1}, \"foo\")\n%!error <arrays .* must be the same size> is_same_file ({\"1\", \"2\"}, {\"1\"; \"2\"})\n*/\n\nint\nalmost_match (const std::string& std, const std::string& s,\n              int min_match_len, int case_sens)\n{\n  int stdlen = std.length ();\n  int slen = s.length ();\n\n  return (slen <= stdlen\n          && slen >= min_match_len\n          && (case_sens\n              ? (strncmp (std.c_str (), s.c_str (), slen) == 0)\n              : (octave_strncasecmp (std.c_str (), s.c_str (), slen) == 0)));\n}\n\n// Ugh.\n\nint\nkeyword_almost_match (const char *const *std, int *min_len,\n                      const std::string& s,\n                      int min_toks_to_match, int max_toks)\n{\n  int status = 0;\n  int tok_count = 0;\n  int toks_matched = 0;\n\n  if (s.empty () || max_toks < 1)\n    return status;\n\n  char *kw = strsave (s.c_str ());\n\n  char *t = kw;\n  while (*t != '\\0')\n    {\n      if (*t == '\\t')\n        *t = ' ';\n      t++;\n    }\n\n  char *beg = kw;\n  while (*beg == ' ')\n    beg++;\n\n  if (*beg == '\\0')\n    return status;\n\n  const char **to_match = new const char *[max_toks + 1];\n  const char *const *s1 = std;\n  const char **s2 = to_match;\n\n  if (! s1 || ! s2)\n    goto done;\n\n  s2[tok_count] = beg;\n  char *end;\n  while ((end = strchr (beg, ' ')) != nullptr)\n    {\n      *end = '\\0';\n      beg = end + 1;\n\n      while (*beg == ' ')\n        beg++;\n\n      if (*beg == '\\0')\n        break;\n\n      tok_count++;\n      if (tok_count >= max_toks)\n        goto done;\n\n      s2[tok_count] = beg;\n    }\n  s2[tok_count+1] = nullptr;\n\n  s2 = to_match;\n\n  for (;;)\n    {\n      if (! almost_match (*s1, *s2, min_len[toks_matched], 0))\n        goto done;\n\n      toks_matched++;\n\n      s1++;\n      s2++;\n\n      if (! *s2)\n        {\n          status = (toks_matched >= min_toks_to_match);\n          goto done;\n        }\n\n      if (! *s1)\n        goto done;\n    }\n\ndone:\n\n  delete [] kw;\n  delete [] to_match;\n\n  return status;\n}\n\n// See if the given file is in the path.\n\nstd::string\nsearch_path_for_file (const std::string& path,\n                      const string_vector& names)\n{\n  directory_path p (path);\n\n  return sys::env::make_absolute (p.find_first_of (names.std_list ()));\n}\n\n// Find all locations of the given file in the path.\n\nstring_vector\nsearch_path_for_all_files (const std::string& path,\n                           const string_vector& names)\n{\n  directory_path p (path);\n\n  string_vector sv = p.find_all_first_of (names.std_list ());\n\n  octave_idx_type len = sv.numel ();\n\n  for (octave_idx_type i = 0; i < len; i++)\n    sv[i] = sys::env::make_absolute (sv[i]);\n\n  return sv;\n}\n\nstatic string_vector\nmake_absolute (const string_vector& sv)\n{\n  octave_idx_type len = sv.numel ();\n\n  string_vector retval (len);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    retval[i] = sys::env::make_absolute (sv[i]);\n\n  return retval;\n}\n\nDEFMETHOD (file_in_loadpath, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{fname} =} file_in_loadpath (@var{file})\n@deftypefnx {} {@var{fname} =} file_in_loadpath (@var{file}, \"all\")\nReturn the absolute name of @var{file} if it can be found in the list of\ndirectories specified by @code{path}.\n\nIf no file is found, return an empty character string.\n\nWhen @var{file} is already an absolute name, the name is checked against the\nfile system instead of Octave's loadpath.  In this case, if @var{file} exists\nit will be returned in @var{fname}, otherwise an empty string is returned.\n\nIf the first argument is a cell array of strings, search each directory of\nthe loadpath for element of the cell array and return the first that\nmatches.\n\nIf the second optional argument @qcode{\"all\"} is supplied, return a cell\narray containing the list of all files that have the same name in the path.\nIf no files are found, return an empty cell array.\n@seealso{file_in_path, dir_in_loadpath, path}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  string_vector names = args(0).xstring_vector_value (\"file_in_loadpath: FILE argument must be a string\");\n\n  if (names.empty ())\n    error (\"file_in_loadpath: FILE argument must not be empty\");\n\n  load_path& lp = interp.get_load_path ();\n\n  if (nargin == 1)\n    return ovl (sys::env::make_absolute (lp.find_first_of (names)));\n  else\n    {\n      std::string opt = args(1).xstring_value (\"file_in_loadpath: optional second argument must be a string\");\n\n      if (opt != \"all\")\n        error (R\"(file_in_loadpath: \"all\" is only valid second argument)\");\n\n      return ovl (Cell (make_absolute (lp.find_all_first_of (names))));\n    }\n}\n\n/*\n%!test\n%! f = file_in_loadpath (\"plot.m\");\n%! assert (ischar (f));\n%! assert (! isempty (f));\n\n%!test\n%! f = file_in_loadpath (\"$$probably_!! _not_&&_a_!! _file$$\");\n%! assert (f, \"\");\n\n%!test\n%! lst = file_in_loadpath (\"$$probably_!! _not_&&_a_!! _file$$\", \"all\");\n%! assert (lst, {});\n\n%!error file_in_loadpath ()\n%!error file_in_loadpath (\"foo\", \"bar\", 1)\n%!error file_in_loadpath ([])\n%!error file_in_loadpath (\"plot.m\", \"bar\")\n*/\n\nDEFUN (file_in_path, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{fname} =} file_in_path (@var{path}, @var{file})\n@deftypefnx {} {@var{fname} =} file_in_path (@var{path}, @var{file}, \"all\")\nReturn the absolute name of @var{file} if it can be found in @var{path}.\n\nThe value of @var{path} should be a colon-separated list of directories in\nthe format described for @code{path}.  If no file is found, return an empty\ncharacter string.  For example:\n\n@example\n@group\nfile_in_path (EXEC_PATH, \"sh\")\n     @xresult{} \"/bin/sh\"\n@end group\n@end example\n\nIf the second argument is a cell array of strings, search each directory of\nthe path for element of the cell array and return the first that matches.\n\nIf the third optional argument @qcode{\"all\"} is supplied, return a cell\narray containing the list of all files that have the same name in the path.\nIf no files are found, return an empty cell array.\n@seealso{file_in_loadpath, dir_in_loadpath, path}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  std::string path = args(0).xstring_value (\"file_in_path: PATH must be a string\");\n\n  string_vector names = args(1).xstring_vector_value (\"file_in_path: FILE argument must be a string\");\n\n  if (names.empty ())\n    error (\"file_in_path: FILE argument must not be empty\");\n\n  if (nargin == 2)\n    return ovl (search_path_for_file (path, names));\n  else\n    {\n      std::string opt = args(2).xstring_value (\"file_in_path: optional third argument must be a string\");\n\n      if (opt != \"all\")\n        error (R\"(file_in_path: \"all\" is only valid third argument)\");\n\n      return ovl (Cell (make_absolute (search_path_for_all_files (path, names))));\n    }\n}\n\n/*\n%!test\n%! f = file_in_path (path (), \"plot.m\");\n%! assert (ischar (f));\n%! assert (! isempty (f));\n\n%!test\n%! f = file_in_path (path (), \"$$probably_!! _not_&&_a_!! _file$$\");\n%! assert (f, \"\");\n\n%!test\n%! lst = file_in_path (path (), \"$$probably_!! _not_&&_a_!! _file$$\", \"all\");\n%! assert (lst, {});\n\n%!error file_in_path ()\n%!error file_in_path (\"foo\")\n%!error file_in_path (\"foo\", \"bar\", \"baz\", 1)\n%!error file_in_path ([])\n%!error file_in_path (path (), [])\n%!error file_in_path (path (), \"plot.m\", \"bar\")\n*/\n\nstd::string\nfile_in_path (const std::string& name, const std::string& suffix)\n{\n  std::string nm = name;\n\n  if (! suffix.empty ())\n    nm.append (suffix);\n\n  load_path& lp = __get_load_path__ ();\n\n  return sys::env::make_absolute (lp.find_file (nm));\n}\n\nstd::string\nfind_data_file_in_load_path  (const std::string& fcn,\n                              const std::string& file,\n                              bool require_regular_file)\n{\n  std::string fname = file;\n\n  if (! (sys::env::absolute_pathname (fname)\n         || sys::env::rooted_relative_pathname (fname)))\n    {\n      // Load path will also search \".\" first, but we don't want to\n      // issue a warning if the file is found in the current directory,\n      // so do an explicit check for that.\n      bool local_file_ok\n        = sys::file_exists (fname, ! require_regular_file);\n\n      if (! local_file_ok)\n        {\n          load_path& lp = __get_load_path__ ();\n\n          // Not directly found; search load path.\n          std::string tmp = sys::env::make_absolute (lp.find_file (fname));\n\n          if (! tmp.empty ())\n            {\n              warn_data_file_in_path (fcn, tmp);\n\n              fname = tmp;\n            }\n        }\n    }\n\n  return fname;\n}\n\n// See if there is a function file in the path.\n// If so, return the full path to the file.\n\nstd::string\nfcn_file_in_path (const std::string& name)\n{\n  std::string retval;\n\n  int len = name.length ();\n\n  if (len > 0)\n    {\n      if (sys::env::absolute_pathname (name))\n        {\n          if (sys::file_exists (name, false))\n            retval = name;\n        }\n      else if (len > 2 && name[len - 2] == '.' && name[len - 1] == 'm')\n        {\n          load_path& lp = __get_load_path__ ();\n\n          retval = lp.find_fcn_file (name.substr (0, len-2));\n        }\n      else\n        {\n          std::string fname = name;\n          std::size_t pos = name.find_first_of ('>');\n          if (pos != std::string::npos)\n            fname = name.substr (0, pos);\n\n          load_path& lp = __get_load_path__ ();\n\n          retval = lp.find_fcn_file (fname);\n        }\n    }\n\n  return retval;\n}\n\n// See if there is a directory called \"name\" in the path and if it\n// contains a Contents.m file.  If so, return the full path to this file.\n\nstd::string\ncontents_file_in_path (const std::string& dir)\n{\n  std::string retval;\n\n  if (! dir.empty ())\n    {\n      load_path& lp = __get_load_path__ ();\n\n      std::string tcontents\n        = sys::file_ops::concat (lp.find_dir (dir), \"Contents.m\");\n\n      if (sys::file_exists (tcontents))\n        retval = sys::env::make_absolute (tcontents);\n    }\n\n  return retval;\n}\n\nvoid\ndisplay_file_lines (std::ostream& os, const std::string& file_name, int start, int end, int target_line, const std::string& marker, const std::string& who)\n{\n  std::ifstream fs = octave::sys::ifstream (file_name.c_str (), std::ios::in);\n\n  if (! fs)\n    os << who << \": unable to open '\" << file_name << \"' for reading!\\n\";\n  else\n    {\n      int line_num = 1;\n      std::string text;\n\n      while (std::getline (fs, text) && line_num <= end)\n        {\n          if (line_num >= start)\n            {\n              os << line_num;\n\n              if (line_num == target_line)\n                os << marker;\n\n              os << \"\\t\" << text << \"\\n\";\n            }\n\n          line_num++;\n        }\n    }\n}\n\n// Replace backslash escapes in a string with the real values.\n\nstd::string\ndo_string_escapes (const std::string& s)\n{\n  std::string retval;\n\n  std::size_t i = 0;\n  std::size_t j = 0;\n  std::size_t len = s.length ();\n\n  retval.resize (len);\n\n  while (j < len)\n    {\n      if (s[j] == '\\\\' && j+1 < len)\n        {\n          switch (s[++j])\n            {\n            case 'a': // alarm\n              retval[i] = '\\a';\n              break;\n\n            case 'b': // backspace\n              retval[i] = '\\b';\n              break;\n\n            case 'f': // formfeed\n              retval[i] = '\\f';\n              break;\n\n            case 'n': // newline\n              retval[i] = '\\n';\n              break;\n\n            case 'r': // carriage return\n              retval[i] = '\\r';\n              break;\n\n            case 't': // horizontal tab\n              retval[i] = '\\t';\n              break;\n\n            case 'v': // vertical tab\n              retval[i] = '\\v';\n              break;\n\n            case '\\\\': // backslash\n              retval[i] = '\\\\';\n              break;\n\n            case '\\'': // quote\n              retval[i] = '\\'';\n              break;\n\n            case '\"': // double quote\n              retval[i] = '\"';\n              break;\n\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7': // octal input\n              {\n                std::size_t k;\n                int tmpi = s[j] - '0';\n                for (k = j+1; k < std::min (j+3, len); k++)\n                  {\n                    int digit = s[k] - '0';\n                    if (digit < 0 || digit > 7)\n                      break;\n                    tmpi <<= 3;\n                    tmpi += digit;\n                  }\n                retval[i] = tmpi;\n                j = k - 1;\n                break;\n              }\n\n            case 'x': // hex input\n              {\n                std::size_t k;\n                int tmpi = 0;\n                for (k = j+1; k < std::min (j+3, len); k++)\n                  {\n                    if (! isxdigit (s[k]))\n                      break;\n\n                    tmpi <<= 4;\n                    int digit = s[k];\n                    if (digit >= 'a')\n                      tmpi += digit - 'a' + 10;\n                    else if (digit >= 'A')\n                      tmpi += digit - 'A' + 10;\n                    else\n                      tmpi += digit - '0';\n                  }\n\n                if (k == j+1)\n                  warning (R\"(malformed hex escape sequence '\\x' -- converting to '\\0')\");\n\n                retval[i] = tmpi;\n                j = k - 1;\n                break;\n              }\n\n            default:\n              warning (R\"(unrecognized escape sequence '\\%c' -- converting to '%c')\", s[j], s[j]);\n              retval[i] = s[j];\n              break;\n            }\n        }\n      else\n        retval[i] = s[j];\n\n      i++;\n      j++;\n    }\n\n  retval.resize (i);\n\n  return retval;\n}\n\nDEFUN (do_string_escapes, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{newstr} =} do_string_escapes (@var{string})\nConvert escape sequences in @var{string} to the characters they represent.\n\nEscape sequences begin with a leading backslash\n(@qcode{'@backslashchar{}'}) followed by 1--3 characters\n(.e.g., @qcode{\"@backslashchar{}n\"} => newline).\n@seealso{undo_string_escapes}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string str = args(0).xstring_value (\"do_string_escapes: STRING argument must be of type string\");\n\n  return ovl (do_string_escapes (str));\n}\n\n/*\n%!assert (do_string_escapes ('foo\\nbar'), \"foo\\nbar\")\n%!assert (do_string_escapes (\"foo\\\\nbar\"), \"foo\\nbar\")\n%!assert (do_string_escapes (\"foo\\\\nbar\"), [\"foo\", char(10), \"bar\"])\n%!assert (\"foo\\nbar\", [\"foo\", char(10), \"bar\"])\n\n%!assert (do_string_escapes ('\\0\\a\\b\\f\\n\\r\\t\\v'), \"\\0\\a\\b\\f\\n\\r\\t\\v\")\n%!assert (do_string_escapes (\"\\\\0\\\\a\\\\b\\\\f\\\\n\\\\r\\\\t\\\\v\"), \"\\0\\a\\b\\f\\n\\r\\t\\v\")\n%!assert (do_string_escapes (\"\\\\0\\\\a\\\\b\\\\f\\\\n\\\\r\\\\t\\\\v\"),\n%!        char ([0, 7, 8, 12, 10, 13, 9, 11]))\n%!assert (\"\\0\\a\\b\\f\\n\\r\\t\\v\", char ([0, 7, 8, 12, 10, 13, 9, 11]))\n\n%!assert (do_string_escapes ('\\\\'), \"\\\\\")\n%!assert (do_string_escapes (\"\\\\\\\\\"), \"\\\\\")\n%!assert (do_string_escapes (\"\\\\\\\\\"), char (92))\n\n%!assert (do_string_escapes ('\\''single-quoted\\'''), \"'single-quoted'\")\n%!assert (do_string_escapes (\"\\\\'single-quoted\\\\'\"), \"'single-quoted'\")\n%!assert (do_string_escapes ('\\\"double-quoted\\\"'), \"\\\"double-quoted\\\"\")\n%!assert (do_string_escapes (\"\\\\\\\"double-quoted\\\\\\\"\"), \"\\\"double-quoted\\\"\")\n\n%!assert (do_string_escapes ('A\\4B'), [\"A\" char(4) \"B\"])\n%!assert (do_string_escapes ('A\\45B'), [\"A\" char(37) \"B\"])\n%!assert (do_string_escapes ('A\\123B'), [\"A\" char(83) \"B\"])\n%!assert (sprintf ('\\117\\143\\164\\141\\166\\145'), \"Octave\")\n\n%!assert (do_string_escapes ('A\\x4G'), [\"A\" char(4) \"G\"])\n%!assert (do_string_escapes ('A\\x4AG'), [\"A\" char(74) \"G\"])\n%!assert (sprintf ('\\x4f\\x63\\x74\\x61\\x76\\x65'), \"Octave\")\n\n%!error do_string_escapes ()\n%!error do_string_escapes (\"foo\", \"bar\")\n%!error <STRING argument> do_string_escapes (3)\n%!warning <malformed hex escape sequence> do_string_escapes ('\\xG');\n%!warning <unrecognized escape sequence> do_string_escapes ('\\G');\n*/\n\nconst char *\nundo_string_escape (char c)\n{\n  switch (c)\n    {\n    case '\\0': // NUL byte\n      return R\"(\\0)\";\n\n    case '\\a': // alarm\n      return R\"(\\a)\";\n\n    case '\\b': // backspace\n      return R\"(\\b)\";\n\n    case '\\f': // formfeed\n      return R\"(\\f)\";\n\n    case '\\n': // newline\n      return R\"(\\n)\";\n\n    case '\\r': // carriage return\n      return R\"(\\r)\";\n\n    case '\\t': // horizontal tab\n      return R\"(\\t)\";\n\n    case '\\v': // vertical tab\n      return R\"(\\v)\";\n\n    case '\\\\': // backslash\n      return R\"(\\\\)\";\n\n    case '\"': // double quote\n      return R\"(\\\")\";\n\n    default:\n      {\n        static char retval[2] {'\\0', '\\0'};\n\n        retval[0] = c;\n        return retval;\n      }\n    }\n}\n\nstd::string\nundo_string_escapes (const std::string& s)\n{\n  std::string retval;\n\n  for (std::size_t i = 0; i < s.length (); i++)\n    retval.append (undo_string_escape (s[i]));\n\n  return retval;\n}\n\nDEFUN (undo_string_escapes, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{newstr} =} undo_string_escapes (@var{string})\nConvert special characters in @var{string} back to their escaped forms.\n\nFor example, the expression\n\n@example\n@var{bell} = \"\\a\";\n@end example\n\n@noindent\nassigns the value of the alert character (control-g, ASCII code 7) to the\nstring variable @code{bell}.  If this string is printed, the system will\nring the terminal bell (if it is possible).  This is normally the desired\noutcome.  However, sometimes it is useful to be able to print the original\nrepresentation of the string, with the special characters replaced by their\nescape sequences.  For example,\n\n@example\n@group\noctave:13> undo_string_escapes (bell)\nans = \\a\n@end group\n@end example\n\n@noindent\nreplaces the unprintable alert character with its printable representation.\n@seealso{do_string_escapes}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string str = args(0).xstring_value (\"undo_string_escapes: STRING argument must be a string\");\n\n  return ovl (undo_string_escapes (str));\n}\n\n/*\n%!assert (undo_string_escapes (\"foo\\nbar\"), 'foo\\nbar')\n%!assert (undo_string_escapes (\"foo\\nbar\"), \"foo\\\\nbar\")\n%!assert (undo_string_escapes ([\"foo\", char(10), \"bar\"]), \"foo\\\\nbar\")\n\n%!assert (undo_string_escapes (\"\\0\\a\\b\\f\\n\\r\\t\\v\"), '\\0\\a\\b\\f\\n\\r\\t\\v')\n%!assert (undo_string_escapes (\"\\0\\a\\b\\f\\n\\r\\t\\v\"), \"\\\\0\\\\a\\\\b\\\\f\\\\n\\\\r\\\\t\\\\v\")\n%!assert (undo_string_escapes (char ([0, 7, 8, 12, 10, 13, 9, 11])),\n%!        \"\\\\0\\\\a\\\\b\\\\f\\\\n\\\\r\\\\t\\\\v\")\n\n%!assert (undo_string_escapes (\"\\\\\"), '\\\\')\n%!assert (undo_string_escapes (\"\\\\\"), \"\\\\\\\\\")\n%!assert (undo_string_escapes (char (92)), \"\\\\\\\\\")\n\n%!assert (undo_string_escapes (\"\\\"double-quoted\\\"\"), '\\\"double-quoted\\\"')\n%!assert (undo_string_escapes (\"\\\"double-quoted\\\"\"), \"\\\\\\\"double-quoted\\\\\\\"\")\n\n%!error <Invalid call> undo_string_escapes ()\n%!error <Invalid call> undo_string_escapes (\"foo\", \"bar\")\n%!error <STRING argument> undo_string_escapes (3)\n*/\n\nDEFUN (is_absolute_filename, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} is_absolute_filename (@var{file})\nReturn true if @var{file} is an absolute filename.\n@seealso{is_rooted_relative_filename, make_absolute_filename, isfolder}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).is_string ()\n              && sys::env::absolute_pathname (args(0).string_value ()));\n}\n\n/*\n## FIXME: We need system-dependent tests here.\n\n%!error is_absolute_filename ()\n%!error is_absolute_filename (\"foo\", \"bar\")\n*/\n\nDEFUN (is_rooted_relative_filename, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} is_rooted_relative_filename (@var{file})\nReturn true if @var{file} is a rooted-relative filename.\n@seealso{is_absolute_filename, make_absolute_filename, isfolder}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).is_string ()\n              && sys::env::rooted_relative_pathname (args(0).string_value ()));\n}\n\n/*\n## FIXME: We need system-dependent tests here.\n\n%!error is_rooted_relative_filename ()\n%!error is_rooted_relative_filename (\"foo\", \"bar\")\n*/\n\nDEFUN (make_absolute_filename, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{abs_fname} =} make_absolute_filename (@var{file})\nReturn the full name of @var{file} beginning from the root of the file system.\n\nNo check is done for the existence of @var{file}.  No tilde expansion of\n@var{file} is performed.\n@seealso{canonicalize_file_name, is_absolute_filename,\nis_rooted_relative_filename, isfolder, tilde_expand}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string nm = args(0).xstring_value (\"make_absolute_filename: FILE argument must be a filename\");\n\n  return ovl (sys::env::make_absolute (nm));\n}\n\n/*\n## FIXME: We need system-dependent tests here.\n\n%!error make_absolute_filename ()\n%!error make_absolute_filename (\"foo\", \"bar\")\n*/\n\nDEFMETHOD (dir_in_loadpath, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{dirname} =} dir_in_loadpath (@var{dir})\n@deftypefnx {} {@var{dirname} =} dir_in_loadpath (@var{dir}, \"all\")\nReturn the absolute name of the loadpath element matching @var{dir} if it can\nbe found in the list of directories specified by @code{path}.\n\nIf no match is found, return an empty character string.\n\nThe match is performed at the end of each path element.  For example, if\n@var{dir} is @qcode{\"foo/bar\"}, it matches the path element\n@nospell{@qcode{\"/some/dir/foo/bar\"}}, but not\n@nospell{@qcode{\"/some/dir/foo/bar/baz\"}}\n@nospell{@qcode{\"/some/dir/allfoo/bar\"}}.  When @var{dir} is an absolute name,\nrather than just a path fragment, it is matched against the file system\ninstead of Octave's loadpath.  In this case, if @var{dir} exists it will be\nreturned in @var{dirname}, otherwise an empty string is returned.\n\nIf the optional second argument is supplied, return a cell array containing\nall name matches rather than just the first.\n@seealso{file_in_path, file_in_loadpath, path}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string dir;\n\n  dir = args(0).xstring_value (\"dir_in_loadpath: DIR must be a directory name\");\n\n  load_path& lp = interp.get_load_path ();\n\n  if (nargin == 1)\n    return ovl (lp.find_dir (dir));\n  else\n    return ovl (Cell (lp.find_matching_dirs (dir)));\n}\n\n/*\n%!test\n%! f = dir_in_loadpath (\"plot\");\n%! assert (ischar (f));\n%! assert (! isempty (f));\n\n%!test\n%! f = dir_in_loadpath (\"$$probably_!! _not_&&_a_!! _dir$$\");\n%! assert (f, \"\");\n\n%!test\n%! lst = dir_in_loadpath (\"$$probably_!! _not_&&_a_!! _dir$$\", \"all\");\n%! assert (lst, {});\n\n%!error dir_in_loadpath ()\n%!error dir_in_loadpath (\"foo\", \"bar\", 1)\n*/\n\nDEFUNX (\"errno\", Ferrno, args, ,\n        doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{err} =} errno ()\n@deftypefnx {} {@var{err} =} errno (@var{val})\n@deftypefnx {} {@var{err} =} errno (@var{name})\nQuery or set the system-dependent variable errno.\n\nWhen called with no inputs, return the current value of errno.\n\nWhen called with a numeric input @var{val}, set the current value of errno\nto the specified value.  The previous value of errno is returned as @var{err}.\n\nWhen called with a character string @var{name}, return the numeric value of\nerrno which corresponds to the specified error code.  If @var{name} is not\na recognized error code then -1 is returned.\n\n@seealso{errno_list}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 1)\n    {\n      if (args(0).is_string ())\n        {\n          std::string nm = args(0).string_value ();\n\n          retval = octave_errno::lookup (nm);\n        }\n      else\n        {\n          int val = args(0).strict_int_value (\"errno: argument must be string or integer\");\n\n          retval = octave_errno::set (val);\n        }\n    }\n  else\n    retval = octave_errno::get ();\n\n  return retval;\n}\n\n/*\n%!assert (isnumeric (errno ()))\n\n%!test\n%! lst = errno_list ();\n%! fns = fieldnames (lst);\n%! oldval = errno (fns{1});\n%! assert (isnumeric (oldval));\n%! errno (oldval);\n%! newval = errno ();\n%! assert (oldval, newval);\n\n%!error errno (\"foo\", 1)\n*/\n\nDEFUN (errno_list, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{S} =} errno_list ()\nReturn a structure containing the system-dependent errno values.\n@seealso{errno}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (octave_errno::list ());\n}\n\n/*\n%!assert (isstruct (errno_list ()))\n\n%!error errno_list (\"foo\")\n*/\n\nstatic void\ncheck_dimensions (octave_idx_type& nr, octave_idx_type& nc,\n                  const char *warnfor)\n{\n  if (nr < 0 || nc < 0)\n    {\n      warning_with_id (\"Octave:neg-dim-as-zero\",\n                       \"%s: converting negative dimension to zero\", warnfor);\n\n      nr = (nr < 0) ? 0 : nr;\n      nc = (nc < 0) ? 0 : nc;\n    }\n}\n\nvoid\ncheck_dimensions (dim_vector& dim, const char *warnfor)\n{\n  bool neg = false;\n\n  for (int i = 0; i < dim.ndims (); i++)\n    {\n      if (dim(i) < 0)\n        {\n          dim(i) = 0;\n          neg = true;\n        }\n    }\n\n  if (neg)\n    warning_with_id (\"Octave:neg-dim-as-zero\",\n                     \"%s: converting negative dimension to zero\", warnfor);\n}\n\nvoid\nget_dimensions (const octave_value& a, const char *warn_for,\n                dim_vector& dim)\n{\n  // We support dimensions to be specified by a vector, even if it's empty.\n  // If the vector is empty, the final dimensions end up being 0x0.\n  if (! a.dims ().isvector () && a.dims ().numel () != 0)\n    error (\"%s (A): use %s (size (A)) instead\", warn_for, warn_for);\n\n  const Array<octave_idx_type> v = a.octave_idx_type_vector_value (true);\n  const octave_idx_type n = v.numel ();\n\n  dim.resize (n); // even if n < 2, resize sets it back to 2\n  if (n == 0)\n    {\n      dim(0) = 0;\n      dim(1) = 0;\n    }\n  else if (n == 1)\n    {\n      dim(0) = v(0);\n      dim(1) = v(0);\n    }\n  else\n    for (octave_idx_type i = 0; i < n; i++)\n      dim(i) = v(i);\n\n  check_dimensions (dim, warn_for);\n}\n\nvoid\nget_dimensions (const octave_value& a, const char *warn_for,\n                octave_idx_type& nr, octave_idx_type& nc)\n{\n  if (a.is_scalar_type ())\n    {\n      nr = nc = a.idx_type_value (true);\n    }\n  else\n    {\n      nr = a.rows ();\n      nc = a.columns ();\n\n      if ((nr != 1 || nc != 2) && (nr != 2 || nc != 1))\n        error (\"%s (A): use %s (size (A)) instead\", warn_for, warn_for);\n\n      Array<octave_idx_type> v = a.octave_idx_type_vector_value (true);\n      nr = v(0);\n      nc = v(1);\n    }\n\n  check_dimensions (nr, nc, warn_for);\n}\n\nvoid\nget_dimensions (const octave_value& a, const octave_value& b,\n                const char *warn_for, octave_idx_type& nr,\n                octave_idx_type& nc)\n{\n  nr = (a.isempty () ? 0 : a.idx_type_value (true));\n  nc = (b.isempty () ? 0 : b.idx_type_value (true));\n\n  check_dimensions (nr, nc, warn_for);\n}\n\noctave_idx_type\ndims_to_numel (const dim_vector& dims,\n               const octave_value_list& idx_arg)\n{\n  octave_idx_type retval;\n\n  octave_idx_type len = idx_arg.length ();\n\n  if (len == 0)\n    retval = dims.numel ();\n  else\n    {\n      const dim_vector dv = dims.redim (len);\n      retval = 1;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          octave_value idxi = idx_arg(i);\n          if (idxi.is_magic_colon ())\n            retval *= dv(i);\n          else if (idxi.isnumeric ())\n            retval *= idxi.numel ();\n          else\n            {\n              try\n                {\n                  idx_vector jdx = idxi.index_vector ();\n\n                  retval *= jdx.length (dv(i));\n                }\n              catch (const index_exception& ie)\n                {\n                  error (\"dims_to_numel: invalid index %s\", ie.what ());\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\nMatrix\nidentity_matrix (octave_idx_type nr, octave_idx_type nc)\n{\n  Matrix m (nr, nc, 0.0);\n\n  if (nr > 0 && nc > 0)\n    {\n      octave_idx_type n = std::min (nr, nc);\n\n      for (octave_idx_type i = 0; i < n; i++)\n        m (i, i) = 1.0;\n    }\n\n  return m;\n}\n\nFloatMatrix\nfloat_identity_matrix (octave_idx_type nr, octave_idx_type nc)\n{\n  FloatMatrix m (nr, nc, 0.0);\n\n  if (nr > 0 && nc > 0)\n    {\n      octave_idx_type n = std::min (nr, nc);\n\n      for (octave_idx_type i = 0; i < n; i++)\n        m (i, i) = 1.0;\n    }\n\n  return m;\n}\n\nstd::size_t\nformat (std::ostream& os, const char *fmt, ...)\n{\n  std::size_t retval;\n\n  va_list args;\n  va_start (args, fmt);\n\n  retval = vformat (os, fmt, args);\n\n  va_end (args);\n\n  return retval;\n}\n\nstd::size_t\nvformat (std::ostream& os, const char *fmt, va_list args)\n{\n  std::string s = vasprintf (fmt, args);\n\n  os << s;\n\n  return s.length ();\n}\n\nstd::string\nvasprintf (const char *fmt, va_list args)\n{\n  std::string retval;\n\n  char *result;\n\n  int status = octave_vasprintf_wrapper (&result, fmt, args);\n\n  if (status >= 0)\n    {\n      retval = result;\n      ::free (result);\n    }\n\n  return retval;\n}\n\nstd::string\nasprintf (const char *fmt, ...)\n{\n  std::string retval;\n\n  va_list args;\n  va_start (args, fmt);\n\n  retval = vasprintf (fmt, args);\n\n  va_end (args);\n\n  return retval;\n}\n\n// FIXME: sleep is complicated because we want it to be interruptible.\n// With the way this program handles signals, the sleep system call\n// won't respond to SIGINT.  Maybe there is a better way than\n// breaking this up into multiple shorter intervals?\n\nvoid\nsleep (double seconds, bool do_graphics_events)\n{\n  if (seconds <= 0)\n    return;\n\n  // Allow free access to graphics resources while the interpreter thread\n  // is asleep\n\n  gh_manager& gh_mgr = __get_gh_manager__ ();\n\n  if (do_graphics_events)\n    gh_mgr.unlock ();\n\n  if (math::isinf (seconds))\n    {\n      // Wait for kbhit\n      int c = -1;\n      flush_stdout ();\n\n      struct timespec one_tenth = { 0, 100000000 };\n\n      while (c < 0)\n        {\n          octave_nanosleep_wrapper (&one_tenth, nullptr);\n\n          octave_quit ();\n\n          if (do_graphics_events)\n            gh_mgr.process_events ();\n\n          c = kbhit (false);\n        }\n    }\n  else\n    {\n      sys::time now;\n      double end_time = now.double_value () + seconds;\n      double remaining_time = seconds;\n\n      // Split pause into 100 ms time steps to allow the execution of\n      // graphics events and interrupts.\n      struct timespec nano_laps = { 0, 100000000 };\n\n      while (remaining_time > 0.1)\n        {\n          octave_quit ();\n\n          if (do_graphics_events)\n            {\n              gh_mgr.process_events ();\n\n              now.stamp ();\n              remaining_time = end_time - now.double_value ();\n\n              if (remaining_time < 0.1)\n                break;\n            }\n\n          octave_nanosleep_wrapper (&nano_laps, nullptr);\n\n          now.stamp ();\n          remaining_time = end_time - now.double_value ();\n        }\n\n      if (remaining_time > 0.0)\n        {\n          nano_laps = { 0, static_cast<int> (remaining_time * 1e9) };\n          octave_nanosleep_wrapper (&nano_laps, nullptr);\n        }\n    }\n}\n\nDEFMETHOD (isindex, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{tf} =} isindex (@var{ind})\n@deftypefnx {} {@var{tf} =} isindex (@var{ind}, @var{n})\nReturn true if @var{ind} is a valid index.\n\nValid indices are either positive integers (although possibly of real data\ntype), or logical arrays.\n\nIf present, @var{n} specifies the maximum extent of the dimension to be\nindexed.  When possible the internal result is cached so that subsequent\nindexing using @var{ind} will not perform the check again.\n\nImplementation Note: Strings are first converted to double values before the\nchecks for valid indices are made.  Unless a string contains the NULL\ncharacter @nospell{\"@backslashchar{}0\"}, it will always be a valid index.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_idx_type n = 0;\n  if (nargin == 2)\n    n = args(1).idx_type_value ();\n\n  octave_value retval;\n\n  try\n    {\n      idx_vector idx = args(0).index_vector (true);\n\n      if (nargin == 2)\n        retval = idx.extent (n) <= n;\n      else\n        retval = true;\n    }\n  catch (const execution_exception&)\n    {\n      interp.recover_from_exception ();\n\n      retval = false;\n    }\n\n  return retval;\n}\n\n/*\n%!assert (isindex ([1, 2, 3]))\n%!assert (isindex (1:3))\n%!assert (isindex (1:3, 2), false)\n%!assert (isindex ([1, 2, -3]), false)\n\n%!error isindex ()\n%!error isindex (1:3, 2, 3)\n*/\n\noctave_value_list\ndo_simple_cellfun (octave_value_list (*fcn) (const octave_value_list&, int),\n                   const char *fcn_name, const octave_value_list& args,\n                   int nargout)\n{\n  octave_value_list new_args = args;\n  octave_value_list retval;\n  int nargin = args.length ();\n  OCTAVE_LOCAL_BUFFER (bool, iscell, nargin);\n  OCTAVE_LOCAL_BUFFER (Cell, cells, nargin);\n  OCTAVE_LOCAL_BUFFER (Cell, rcells, nargout);\n\n  const Cell *ccells = cells;\n\n  octave_idx_type numel = 1;\n  dim_vector dims (1, 1);\n\n  for (int i = 0; i < nargin; i++)\n    {\n      octave_value arg = new_args(i);\n      iscell[i] = arg.iscell ();\n      if (iscell[i])\n        {\n          cells[i] = arg.cell_value ();\n          octave_idx_type n = ccells[i].numel ();\n          if (n == 1)\n            {\n              iscell[i] = false;\n              new_args(i) = ccells[i](0);\n            }\n          else if (numel == 1)\n            {\n              numel = n;\n              dims = ccells[i].dims ();\n            }\n          else if (dims != ccells[i].dims ())\n            error (\"%s: cell arguments must have matching sizes\", fcn_name);\n        }\n    }\n\n  for (int i = 0; i < nargout; i++)\n    rcells[i].clear (dims);\n\n  for (octave_idx_type j = 0; j < numel; j++)\n    {\n      for (int i = 0; i < nargin; i++)\n        if (iscell[i])\n          new_args(i) = ccells[i](j);\n\n      octave_quit ();\n\n      const octave_value_list tmp = fcn (new_args, nargout);\n\n      if (tmp.length () < nargout)\n        error (\"%s: do_simple_cellfun: internal error\", fcn_name);\n\n      for (int i = 0; i < nargout; i++)\n        rcells[i](j) = tmp(i);\n    }\n\n  retval.resize (nargout);\n\n  for (int i = 0; i < nargout; i++)\n    retval(i) = rcells[i];\n\n  return retval;\n}\n\noctave_value\ndo_simple_cellfun (octave_value_list (*fcn) (const octave_value_list&, int),\n                   const char *fcn_name, const octave_value_list& args)\n{\n  octave_value retval;\n\n  const octave_value_list tmp = do_simple_cellfun (fcn, fcn_name, args, 1);\n\n  if (tmp.length () > 0)\n    retval = tmp(0);\n\n  return retval;\n}\n\nDEFUN (isstudent, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isstudent ()\nReturn true if running in the student edition of @sc{matlab}.\n\n@code{isstudent} always returns false in Octave.\n@seealso{false}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (false);\n}\n\n/*\n%!assert (isstudent (), false)\n\n%!error isstudent (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/utils.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_utils_h)\n#define octave_utils_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdarg>\n\n#include <iosfwd>\n#include <string>\n#include <list>\n\n#include \"dMatrix.h\"\n#include \"lo-utils.h\"\n\nclass octave_value;\nclass octave_value_list;\nclass string_vector;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API bool valid_identifier (const char *s);\nextern OCTINTERP_API bool valid_identifier (const std::string& s);\n\n//! Helper class for `make_valid_name` function calls.\n//!\n//! Extracting options separately for multiple (e.g., 1000+) function calls\n//! avoids expensive repetitive parsing of the very same options.\n\nclass OCTINTERP_API make_valid_name_options\n{\npublic:\n\n  //! Default options for `make_valid_name` function calls.\n  //!\n  //! Calling the constructor without arguments is equivalent to:\n  //!\n  //! @code{.cc}\n  //! make_valid_name_options (ovl (\"ReplacementStyle\", \"underscore\",\n  //!                               \"Prefix\", \"x\"));\n  //! @endcode\n\n  make_valid_name_options () = default;\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (make_valid_name_options)\n\n  //! Extract attribute-value-pairs from an octave_value_list of strings.\n  //!\n  //! If attributes occur multiple times, the rightmost pair is chosen.\n  //!\n  //! @code{.cc}\n  //! make_valid_name_options (ovl (\"ReplacementStyle\", \"hex\", ...));\n  //! @endcode\n\n  make_valid_name_options (const octave_value_list& args);\n\n  //! @return ReplacementStyle, see `help matlab.lang.makeValidName`.\n\n  const std::string&\n  get_replacement_style () const { return m_replacement_style; }\n\n  //! @return Prefix, see `help matlab.lang.makeValidName`.\n\n  const std::string& get_prefix () const { return m_prefix; }\n\nprivate:\n\n  std::string m_replacement_style{\"underscore\"};\n  std::string m_prefix{\"x\"};\n};\n\n//! Modify @p str to be a valid variable name.\n//!\n//! @param str input string\n//! @param options see also `help matlab.lang.makeValidName`.\n//!\n//! @return true, if @p str was modified.\n\nextern OCTINTERP_API bool\nmake_valid_name (std::string& str, const make_valid_name_options& options);\n\nextern OCTINTERP_API int almost_match (const std::string& std,\n                                       const std::string& s,\n                                       int min_match_len = 1,\n                                       int case_sens = 1);\n\nextern OCTINTERP_API int\nkeyword_almost_match (const char *const *std, int *min_len,\n                      const std::string& s, int min_toks_to_match,\n                      int max_toks);\n\nextern OCTINTERP_API std::string\nsearch_path_for_file (const std::string&, const string_vector&);\n\nextern OCTINTERP_API string_vector\nsearch_path_for_all_files (const std::string&, const string_vector&);\n\nextern OCTINTERP_API std::string\nfile_in_path (const std::string&, const std::string&);\n\nextern OCTINTERP_API std::string\nfind_data_file_in_load_path  (const std::string& fcn,\n                              const std::string& file,\n                              bool require_regular_file = false);\n\nextern OCTINTERP_API std::string contents_file_in_path (const std::string&);\n\nextern OCTINTERP_API std::string fcn_file_in_path (const std::string&);\n\nextern OCTINTERP_API void\ndisplay_file_lines (std::ostream& os, const std::string& file_name, int start, int end, int target_line, const std::string& marker, const std::string& who);\n\nextern OCTINTERP_API std::string do_string_escapes (const std::string& s);\n\nextern OCTINTERP_API const char * undo_string_escape (char c);\n\nextern OCTINTERP_API std::string undo_string_escapes (const std::string& s);\n\nextern OCTINTERP_API void\ncheck_dimensions (dim_vector& dim, const char *warnfor);\n\nextern OCTINTERP_API void\nget_dimensions (const octave_value& a, const char *warn_for,\n                dim_vector& dim);\n\nextern OCTINTERP_API void\nget_dimensions (const octave_value& a, const octave_value& b,\n                const char *warn_for, octave_idx_type& nr,\n                octave_idx_type& nc);\n\nextern OCTINTERP_API void\nget_dimensions (const octave_value& a, const char *warn_for,\n                octave_idx_type& nr, octave_idx_type& nc);\n\nextern OCTINTERP_API octave_idx_type\ndims_to_numel (const dim_vector& dims, const octave_value_list& idx);\n\nextern OCTINTERP_API Matrix\nidentity_matrix (octave_idx_type nr, octave_idx_type nc);\n\nextern OCTINTERP_API FloatMatrix\nfloat_identity_matrix (octave_idx_type nr, octave_idx_type nc);\n\nextern OCTINTERP_API std::size_t\nformat (std::ostream& os, const char *fmt, ...);\n\nextern OCTINTERP_API std::size_t\nvformat (std::ostream& os, const char *fmt, va_list args);\n\nextern OCTINTERP_API std::string\nvasprintf (const char *fmt, va_list args);\n\nextern OCTINTERP_API std::string asprintf (const char *fmt, ...);\n\nextern OCTINTERP_API void sleep (double seconds,\n                                 bool do_graphics_events = false);\n\nextern OCTINTERP_API\noctave_value_list\ndo_simple_cellfun (octave_value_list (*fcn) (const octave_value_list&, int),\n                   const char *fcn_name, const octave_value_list& args,\n                   int nargout);\n\nextern OCTINTERP_API\noctave_value\ndo_simple_cellfun (octave_value_list (*fcn) (const octave_value_list&, int),\n                   const char *fcn_name, const octave_value_list& args);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/variables.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdio>\n#include <cstring>\n\n#include <list>\n#include <string>\n\n#include \"file-stat.h\"\n#include \"oct-env.h\"\n#include \"file-ops.h\"\n#include \"glob-match.h\"\n#include \"oct-regexp.h\"\n#include \"str-vec.h\"\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"event-manager.h\"\n#include \"help.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"lex.h\"\n#include \"load-path.h\"\n#include \"octave-preserve-stream-state.h\"\n#include \"oct-map.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-class.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"pt-eval.h\"\n#include \"syminfo.h\"\n#include \"symtab.h\"\n#include \"sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n// Attributes of variables and functions.\n\n// Is this octave_value a valid function?\n\noctave_function *\nis_valid_function (const std::string& fcn_name,\n                   const std::string& warn_for, bool warn)\n{\n  octave_function *ans = nullptr;\n\n  if (! fcn_name.empty ())\n    {\n      octave::symbol_table& symtab = octave::__get_symbol_table__ ();\n\n      octave_value val = symtab.find_function (fcn_name);\n\n      if (val.is_defined ())\n        ans = val.function_value (true);\n    }\n\n  // FIXME: Should this be \"err\" and \"error_for\", rather than warn?\n  if (! ans && warn)\n    error (\"%s: the symbol '%s' is not valid as a function\",\n           warn_for.c_str (), fcn_name.c_str ());\n\n  return ans;\n}\n\noctave_function *\nis_valid_function (const octave_value& arg,\n                   const std::string& warn_for, bool warn)\n{\n  octave_function *ans = nullptr;\n\n  std::string fcn_name;\n\n  if (arg.is_string ())\n    {\n      fcn_name = arg.string_value ();\n\n      ans = is_valid_function (fcn_name, warn_for, warn);\n    }\n  else if (warn)\n    // FIXME: Should this be \"err\" and \"error_for\", rather than warn?\n    error (\"%s: argument must be a string containing function name\",\n           warn_for.c_str ());\n\n  return ans;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFMETHOD (isglobal, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isglobal (@var{name})\nReturn true if @var{name} is a globally visible variable.\n\nFor example:\n\n@example\n@group\nglobal x\nisglobal (\"x\")\n   @xresult{} 1\n@end group\n@end example\n@seealso{isvarname, exist}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"isglobal: NAME must be a string\");\n\n  return ovl (interp.isglobal (name));\n}\n\n/*\n%!test\n%! global x;\n%! assert (isglobal (\"x\"), true);\n%! clear -global x;  # cleanup after test\n\n%!error isglobal ()\n%!error isglobal (\"a\", \"b\")\n%!error isglobal (1)\n*/\n\nstatic int\nsymbol_exist (interpreter& interp, const std::string& name,\n              const std::string& type = \"any\")\n{\n  if (iskeyword (name))\n    return 0;\n\n  bool search_any = type == \"any\";\n  bool search_var = type == \"var\";\n  bool search_dir = type == \"dir\";\n  bool search_file = type == \"file\";\n  bool search_builtin = type == \"builtin\";\n  bool search_class = type == \"class\";\n\n  if (! (search_any || search_var || search_dir || search_file\n         || search_builtin || search_class))\n    error (R\"(exist: unrecognized type argument \"%s\")\", type.c_str ());\n\n  if (search_any || search_var)\n    {\n      octave_value val = interp.varval (name);\n\n      if (val.is_constant () || val.isobject ()\n          || val.is_function_handle ()\n          || val.is_anonymous_function ()\n          || val.is_inline_function ())\n        return 1;\n\n      if (search_var)\n        return 0;\n    }\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  // We shouldn't need to look in the global symbol table, since any name\n  // that is visible in the current scope will be in the local symbol table.\n\n  if (search_any || search_file || search_dir || search_class)\n    {\n      bool have_fcn_ext = false;\n\n      std::string xname = name;\n      std::string ext;\n\n      std::size_t pos = name.rfind ('.');\n\n      if (pos != std::string::npos)\n        {\n          ext = name.substr (pos+1);\n\n          if (ext == \"m\" || ext == \"oct\" || ext == \"mex\")\n            {\n              xname = name.substr (0, pos);\n              have_fcn_ext = true;\n            }\n        }\n\n      std::string file_name;\n\n      if (search_any || search_file || search_class)\n        {\n          load_path& lp = interp.get_load_path ();\n\n          // Look for class constructor first\n          file_name = lp.find_method (xname, xname);\n\n          if (have_fcn_ext && ! file_name.empty ())\n            {\n              // Verify extension of file_name found matches ext of name.\n              pos = file_name.rfind ('.');\n\n              if (pos != std::string::npos)\n                {\n                  std::string fext = file_name.substr (pos+1);\n\n                  if (ext != fext)\n                    file_name = \"\";\n                }\n            }\n\n          if (search_any && file_name.empty ())\n            {\n              // Command line function which Matlab does not support\n              octave_value val = symtab.find_cmdline_function (xname);\n\n              if (val.is_defined ())\n                return 103;\n            }\n\n          // Autoloads can only have simple names without extensions.\n          if (! have_fcn_ext && file_name.empty ())\n            {\n              tree_evaluator& tw = interp.get_evaluator ();\n\n              file_name = tw.lookup_autoload (name);\n            }\n\n          // If nothing found, look for function using original name.\n          if (file_name.empty ())\n            file_name = lp.find_fcn (name);\n        }\n\n      std::size_t len = file_name.length ();\n\n      if (len > 0 && (search_any || search_file || search_class))\n        {\n          if (search_any || search_file)\n            {\n              if (len > 4 && (file_name.substr (len-4) == \".oct\"\n                              || file_name.substr (len-4) == \".mex\"))\n                return 3;\n            }\n\n          if (search_class)\n            {\n              octave_value oval = symtab.find_function (name);\n              if (oval.is_defined () && oval.is_classdef_meta ())\n                return 8;\n              else\n                return 0;\n            }\n\n          return 2;\n        }\n\n      // Nothing found in symbol table, try searching in path\n      file_name = file_in_path (name, \"\");\n\n      if (file_name.empty ())\n        file_name = name;\n\n      // \"stat\" doesn't work on UNC shares and drive letters.\n      if ((search_any || search_file) && drive_or_unc_share (file_name))\n        return 7;\n\n      sys::file_stat fs (file_name);\n\n      if (fs)\n        {\n          if (search_any || search_file)\n            {\n              if (fs.is_dir ())\n                return 7;\n\n              len = file_name.length ();\n\n              if (len > 4 && (file_name.substr (len-4) == \".oct\"\n                              || file_name.substr (len-4) == \".mex\"))\n                return 3;\n              else\n                return 2;\n            }\n          else if (search_dir && fs.is_dir ())\n            return 7;\n        }\n\n      if (search_file || search_dir)\n        return 0;\n    }\n\n  if ((search_any || search_builtin)\n      && symtab.is_built_in_function_name (name))\n    return 5;\n\n  return 0;\n}\n\nint\nsymbol_exist (const std::string& name, const std::string& type)\n{\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  return octave::symbol_exist (interp, name, type);\n}\n\n\n#define GET_IDX(LEN)                                                    \\\n  static_cast<int> (((LEN)-1) * static_cast<double> (rand ()) / RAND_MAX)\n\nstd::string\nunique_symbol_name (const std::string& basename)\n{\n  static const std::string alpha\n    = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\n  static std::size_t len = alpha.length ();\n\n  std::string nm = basename + alpha[GET_IDX (len)];\n\n  std::size_t pos = nm.length ();\n\n  if (nm.substr (0, 2) == \"__\")\n    nm.append (\"__\");\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  while (symbol_exist (interp, nm, \"any\"))\n    nm.insert (pos++, 1, alpha[GET_IDX (len)]);\n\n  return nm;\n}\n\nDEFMETHOD (exist, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{c} =} exist (@var{name})\n@deftypefnx {} {@var{c} =} exist (@var{name}, @var{type})\nCheck for the existence of @var{name} as a variable, function, file, directory,\nor class.\n\nThe return code @var{c} is one of\n\n@table @asis\n@item 1\n@var{name} is a variable.\n\n@item 2\n@var{name} is an absolute filename, an ordinary file in Octave's @code{path},\nor (after appending @samp{.m}) a function file in Octave's @code{path}.\n\n@item 3\n@var{name} is a @samp{.oct} or @samp{.mex} file in Octave's @code{path}.\n\n@item 5\n@var{name} is a built-in function.\n\n@item 7\n@var{name} is a directory.\n\n@item 8\n@var{name} is a classdef class.\n\n@item 103\n@var{name} is a function not associated with a file (entered on the command\nline).\n\n@item 0\n@var{name} does not exist.\n@end table\n\nIf the optional argument @var{type} is supplied, check only for symbols of the\nspecified type.  Valid types are\n\n@table @asis\n@item @qcode{\"var\"}\nCheck only for variables.\n\n@item @qcode{\"builtin\"}\nCheck only for built-in functions.\n\n@item @qcode{\"dir\"}\nCheck only for directories.\n\n@item @qcode{\"file\"}\nCheck only for files and directories.\n\n@item @qcode{\"class\"}\nCheck only for classdef classes.\n@end table\n\nIf no type is given, and there are multiple possible matches for name,\n@code{exist} will return a code according to the following priority list:\nvariable, built-in function, oct-file, directory, file, class.\n\n@code{exist} returns 2 if a regular file called @var{name} is present in\nOctave's search path.  For information about other types of files not on the\nsearch path use some combination of the functions @code{file_in_path} and\n@code{stat} instead.\n\nProgramming Note: If @var{name} is implemented by a buggy .oct/.mex file,\ncalling @var{exist} may cause Octave to crash.  To maintain high performance,\nOctave trusts .oct/.mex files instead of @nospell{sandboxing} them.\n\n@seealso{file_in_loadpath, file_in_path, dir_in_loadpath, stat}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  // For compatibility with undocumented Matlab behavior, return 0 if\n  // there is an empty built-in object as the only argument.\n  if (args(0).builtin_type () != btyp_unknown && args(0).isempty ())\n    return ovl (0);\n\n  // Also for compatibility, return 0 if the second argument is an empty\n  // built-in object.\n  if (nargin == 2 && args(1).builtin_type () != btyp_unknown\n      && args(1).isempty ())\n    return ovl (0);\n\n  std::string name = args(0).xstring_value (\"exist: NAME must be a string\");\n\n  if (nargin == 2)\n    {\n      std::string type\n        = args(1).xstring_value (\"exist: TYPE must be a string\");\n\n      return ovl (symbol_exist (interp, name, type));\n    }\n  else\n    return ovl (symbol_exist (interp, name));\n}\n\n/*\n%!shared dirtmp, __var1\n%! dirtmp = P_tmpdir ();\n%! __var1 = 1;\n\n%!assert (exist (\"__%Highly_unlikely_name%__\"), 0)\n%!assert (exist (\"__var1\"), 1)\n%!assert (exist (\"__var1\", \"var\"), 1)\n%!assert (exist (\"__var1\", \"builtin\"), 0)\n%!assert (exist (\"__var1\", \"dir\"), 0)\n%!assert (exist (\"__var1\", \"file\"), 0)\n%!assert (exist (\"__var1\", \"class\"), 0)\n\n%!testif ; isunix ()\n%! assert (exist (\"/bin/sh\"), 2);\n%! assert (exist (\"/bin/sh\", \"file\"), 2);\n%! assert (exist (\"/bin/sh\", \"dir\"), 0);\n%! assert (exist (\"/dev/null\"), 2);\n%! assert (exist (\"/dev/null\", \"file\"), 2);\n%! assert (exist (\"/dev/null\", \"dir\"), 0);\n\n%!assert (exist (\"print_usage\"), 2)\n%!assert (exist (\"print_usage.m\"), 2)\n%!assert (exist (\"print_usage\", \"file\"), 2)\n%!assert (exist (\"print_usage\", \"dir\"), 0)\n\n## Don't search path for rooted relative filenames\n%!assert (exist (\"plot.m\", \"file\"), 2)\n%!assert (exist (\"./plot.m\", \"file\"), 0)\n%!assert (exist (\"./%nonexistentfile%\", \"file\"), 0)\n%!assert (exist (\"%nonexistentfile%\", \"file\"), 0)\n\n## Don't search path for absolute filenames\n%!test\n%! tname = tempname ();\n%! unwind_protect\n%!   ## open/close file to create it, equivalent of touch\n%!   fid = fopen (tname, \"w\");\n%!   fclose (fid);\n%!   [~, fname] = fileparts (tname);\n%!   assert (exist (fullfile (tempdir (), fname), \"file\"), 2);\n%! unwind_protect_cleanup\n%!   unlink (tname);\n%! end_unwind_protect\n%! assert (exist (fullfile (pwd (), \"%nonexistentfile%\"), \"file\"), 0);\n\n%!assert (exist (\"fftw\"), 3)\n%!assert (exist (\"fftw.oct\"), 3)\n%!assert (exist (\"fftw\", \"file\"), 3)\n%!assert (exist (\"fftw\", \"builtin\"), 0)\n\n%!assert (exist (\"ftp\"), 2)\n%!assert (exist (\"ftp.m\"), 2)\n%!assert (exist (\"@ftp/ftp\"), 2)\n%!assert (exist (\"@ftp/ftp.m\"), 2)\n%!assert (exist (\"ftp\", \"class\"), 0)\n\n%!assert (exist (\"inputParser\"), 2)\n%!assert (exist (\"inputParser.m\"), 2)\n%!assert (exist (\"inputParser\", \"class\"), 8)\n\n%!assert (exist (\"sin\"), 5)\n%!assert (exist (\"sin\", \"builtin\"), 5)\n%!assert (exist (\"sin\", \"file\"), 0)\n\n%!assert (exist (dirtmp), 7)\n%!assert (exist (dirtmp, \"dir\"), 7)\n%!assert (exist (dirtmp, \"file\"), 7)\n\n%!error exist ()\n%!error exist (1,2,3)\n%!error <TYPE must be a string> exist (\"a\", 1)\n%!error <NAME must be a string> exist (1)\n%!error <unrecognized type argument \"foobar\"> exist (\"a\", \"foobar\")\n\n*/\n\n// Variable values.\n\nstatic bool\nwants_local_change (const octave_value_list& args, int& nargin)\n{\n  bool retval = false;\n\n  if (nargin == 2)\n    {\n      if (! args(1).is_string () || args(1).string_value () != \"local\")\n        error_with_cfn (R\"(second argument must be \"local\")\");\n\n      nargin = 1;\n      retval = true;\n    }\n\n  return retval;\n}\n\nstatic octave::unwind_protect *\ncurr_fcn_unwind_protect_frame ()\n{\n  octave::tree_evaluator& tw = octave::__get_evaluator__ ();\n\n  return tw.curr_fcn_unwind_protect_frame ();\n}\n\ntemplate <typename T>\nstatic bool\ntry_local_protect (T& var)\n{\n  octave::unwind_protect *frame = curr_fcn_unwind_protect_frame ();\n\n  if (frame)\n    {\n      frame->protect_var (var);\n      return true;\n    }\n  else\n    return false;\n}\n\noctave_value\nset_internal_variable (bool& var, const octave_value_list& args,\n                       int nargout, const char *nm)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  if (nargout > 0 || nargin == 0)\n    retval = var;\n\n  if (wants_local_change (args, nargin))\n    {\n      if (! try_local_protect (var))\n        warning (R\"(\"local\" has no effect outside a function)\");\n    }\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      bool bval = args(0).strict_bool_value (\"%s: argument must be a logical value\", nm);\n\n      var = bval;\n    }\n\n  return retval;\n}\n\noctave_value\nset_internal_variable (char& var, const octave_value_list& args,\n                       int nargout, const char *nm)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  if (nargout > 0 || nargin == 0)\n    retval = var;\n\n  if (wants_local_change (args, nargin))\n    {\n      if (! try_local_protect (var))\n        warning (R\"(\"local\" has no effect outside a function)\");\n    }\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      std::string sval = args(0).xstring_value (\"%s: argument must be a single character\", nm);\n\n      switch (sval.length ())\n        {\n        case 1:\n          var = sval[0];\n          break;\n\n        case 0:\n          var = '\\0';\n          break;\n\n        default:\n          error (\"%s: argument must be a single character\", nm);\n          break;\n        }\n    }\n\n  return retval;\n}\n\noctave_value\nset_internal_variable (int& var, const octave_value_list& args,\n                       int nargout, const char *nm,\n                       int minval, int maxval)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  if (nargout > 0 || nargin == 0)\n    retval = var;\n\n  if (wants_local_change (args, nargin))\n    {\n      if (! try_local_protect (var))\n        warning (R\"(\"local\" has no effect outside a function)\");\n    }\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      int ival = args(0).strict_int_value (\"%s: argument must be an integer value\", nm);\n\n      if (ival < minval)\n        error (\"%s: arg must be greater than %d\", nm, minval);\n      if (ival > maxval)\n        error (\"%s: arg must be less than or equal to %d\", nm, maxval);\n\n      var = ival;\n    }\n\n  return retval;\n}\n\noctave_value\nset_internal_variable (double& var, const octave_value_list& args,\n                       int nargout, const char *nm,\n                       double minval, double maxval)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  if (nargout > 0 || nargin == 0)\n    retval = var;\n\n  if (wants_local_change (args, nargin))\n    {\n      if (! try_local_protect (var))\n        warning (R\"(\"local\" has no effect outside a function)\");\n    }\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      double dval = args(0).xscalar_value (\"%s: argument must be a scalar value\", nm);\n\n      if (dval < minval)\n        error (\"%s: argument must be greater than %g\", nm, minval);\n      if (dval > maxval)\n        error (\"%s: argument must be less than or equal to %g\", nm, maxval);\n\n      var = dval;\n    }\n\n  return retval;\n}\n\noctave_value\nset_internal_variable (std::string& var, const octave_value_list& args,\n                       int nargout, const char *nm, bool empty_ok)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  if (nargout > 0 || nargin == 0)\n    retval = var;\n\n  if (wants_local_change (args, nargin))\n    {\n      if (! try_local_protect (var))\n        warning (R\"(\"local\" has no effect outside a function)\");\n    }\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      std::string sval = args(0).xstring_value (\"%s: first argument must be a string\", nm);\n\n      if (! empty_ok && sval.empty ())\n        error (\"%s: value must not be empty\", nm);\n\n      var = sval;\n    }\n\n  return retval;\n}\n\noctave_value\nset_internal_variable (int& var, const octave_value_list& args,\n                       int nargout, const char *nm, const char **choices)\n{\n  octave_value retval;\n  int nchoices = 0;\n  while (choices[nchoices] != nullptr)\n    nchoices++;\n\n  int nargin = args.length ();\n\n  panic_unless (var < nchoices);\n\n  if (nargout > 0 || nargin == 0)\n    retval = choices[var];\n\n  if (wants_local_change (args, nargin))\n    {\n      if (! try_local_protect (var))\n        warning (R\"(\"local\" has no effect outside a function)\");\n    }\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      std::string sval = args(0).xstring_value (\"%s: first argument must be a string\", nm);\n\n      int i = 0;\n      for (; i < nchoices; i++)\n        {\n          if (sval == choices[i])\n            {\n              var = i;\n              break;\n            }\n        }\n      if (i == nchoices)\n        error (R\"(%s: value not allowed (\"%s\"))\", nm, sval.c_str ());\n    }\n\n  return retval;\n}\n\noctave_value\nset_internal_variable (std::string& var, const octave_value_list& args,\n                       int nargout, const char *nm, const char **choices)\n{\n  octave_value retval;\n  int nchoices = 0;\n  while (choices[nchoices] != nullptr)\n    nchoices++;\n\n  int nargin = args.length ();\n\n  if (nargout > 0 || nargin == 0)\n    retval = var;\n\n  if (wants_local_change (args, nargin))\n    {\n      if (! try_local_protect (var))\n        warning (R\"(\"local\" has no effect outside a function)\");\n    }\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      std::string sval = args(0).xstring_value (\"%s: first argument must be a string\", nm);\n\n      int i = 0;\n      for (; i < nchoices; i++)\n        {\n          if (sval == choices[i])\n            {\n              var = sval;\n              break;\n            }\n        }\n      if (i == nchoices)\n        error (R\"(%s: value not allowed (\"%s\"))\", nm, sval.c_str ());\n    }\n\n  return retval;\n}\n\n// NOTE: Calling Fmlock directly (without an associated stack frame)\n// will probably not do what you expect because it will lock the calling\n// function.  You should use interpreter::mlock directly if you want to\n// lock a .oct function.  For .mex, you would normally use mexLock.\n//\n// FIXME: with the current implementation, calling \"builtin ('mlock')\"\n// will also not do what you expect.  Is there any reasonable way to fix\n// that?\n\nDEFMETHOD (mlock, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} mlock ()\nLock the current function into memory so that it can't be removed with\n@code{clear}.\n@seealso{munlock, mislocked, persistent, clear}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  interp.mlock (true);\n\n  return ovl ();\n}\n\nDEFMETHOD (munlock, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} munlock ()\n@deftypefnx {} {} munlock (@var{fcn})\nUnlock the named function @var{fcn} so that it may be removed from memory with\n@code{clear}.\n\nIf no function is named then unlock the current function.\n@seealso{mlock, mislocked, persistent, clear}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      std::string name\n        = args(0).xstring_value (\"munlock: FCN must be a string\");\n\n      interp.munlock (name);\n    }\n  else\n    interp.munlock (true);\n\n  return ovl ();\n}\n\nDEFMETHOD (mislocked, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{tf} =} mislocked ()\n@deftypefnx {} {@var{tf} =} mislocked (@var{fcn})\nReturn true if the named function @var{fcn} is locked in memory.\n\nIf no function is named then return true if the current function is locked.\n@seealso{mlock, munlock, persistent, clear}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 1)\n    {\n      std::string name\n        = args(0).xstring_value (\"mislocked: FCN must be a string\");\n\n      return ovl (interp.mislocked (name));\n    }\n  else\n    return ovl (interp.mislocked (true));\n}\n\n// Deleting names from the symbol tables.\n\nstatic inline bool\nname_matches_any_pattern (const std::string& nm, const string_vector& argv,\n                          int argc, int idx, bool have_regexp = false)\n{\n  bool retval = false;\n\n  for (int k = idx; k < argc; k++)\n    {\n      std::string patstr = argv[k];\n      if (! patstr.empty ())\n        {\n          if (have_regexp)\n            {\n              if (regexp::is_match (patstr, nm))\n                {\n                  retval = true;\n                  break;\n                }\n            }\n          else\n            {\n              symbol_match pattern (patstr);\n\n              if (pattern.match (nm))\n                {\n                  retval = true;\n                  break;\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\nstatic inline void\nmaybe_warn_exclusive (bool exclusive)\n{\n  if (exclusive)\n    warning (\"clear: ignoring --exclusive option\");\n}\n\nstatic void\ndo_clear_functions (interpreter& interp,\n                    const string_vector& argv, int argc, int idx,\n                    bool exclusive = false)\n{\n  if (idx == argc)\n    interp.clear_functions ();\n  else\n    {\n      if (exclusive)\n        {\n          std::list<std::string> fcns = interp.user_function_names ();\n\n          for (const auto& name : fcns)\n            {\n              if (! name_matches_any_pattern (name, argv, argc, idx))\n                interp.clear_function (name);\n            }\n        }\n      else\n        {\n          while (idx < argc)\n            interp.clear_function_pattern (argv[idx++]);\n        }\n    }\n}\n\nstatic void\ndo_clear_globals (interpreter& interp,\n                  const string_vector& argv, int argc, int idx,\n                  bool exclusive = false)\n{\n  if (idx == argc)\n    {\n      std::list<std::string> gvars = interp.global_variable_names ();\n\n      for (const auto& name : gvars)\n        {\n          interp.clear_variable (name);\n          interp.clear_global_variable (name);\n        }\n    }\n  else\n    {\n      if (exclusive)\n        {\n          std::list<std::string> gvars = interp.global_variable_names ();\n\n          for (const auto& name : gvars)\n            {\n              if (! name_matches_any_pattern (name, argv, argc, idx))\n                {\n                  interp.clear_variable (name);\n                  interp.clear_global_variable (name);\n                }\n            }\n        }\n      else\n        {\n          while (idx < argc)\n            {\n              std::string pattern = argv[idx++];\n\n              interp.clear_variable_pattern (pattern);\n              interp.clear_global_variable_pattern (pattern);\n            }\n        }\n    }\n}\n\nstatic void\ndo_clear_variables (interpreter& interp,\n                    const string_vector& argv, int argc, int idx,\n                    bool exclusive = false, bool have_regexp = false)\n{\n  if (idx == argc)\n    interp.clear_variables ();\n  else\n    {\n      if (exclusive)\n        {\n          std::list<std::string> lvars = interp.variable_names ();\n\n          for (const auto& name : lvars)\n            {\n              if (! name_matches_any_pattern (name, argv, argc, idx,\n                                              have_regexp))\n                interp.clear_variable (name);\n            }\n        }\n      else\n        {\n          if (have_regexp)\n            while (idx < argc)\n              interp.clear_variable_regexp (argv[idx++]);\n          else\n            while (idx < argc)\n              interp.clear_variable_pattern (argv[idx++]);\n        }\n    }\n}\n\nstatic void\ndo_clear_symbols (interpreter& interp,\n                  const string_vector& argv, int argc, int idx,\n                  bool exclusive = false)\n{\n  if (idx == argc)\n    {\n      interp.clear_variables ();\n    }\n  else\n    {\n      if (exclusive)\n        {\n          // FIXME: is this really what we want, or do we\n          // somehow want to only clear the functions that are not\n          // shadowed by local variables?  It seems that would be a\n          // bit harder to do.\n\n          do_clear_variables (interp, argv, argc, idx, exclusive);\n          do_clear_functions (interp, argv, argc, idx, exclusive);\n        }\n      else\n        {\n          while (idx < argc)\n            interp.clear_symbol_pattern (argv[idx++]);\n        }\n    }\n}\n\nstatic void\ndo_matlab_compatible_clear (interpreter& interp,\n                            const string_vector& argv, int argc, int idx)\n{\n  // This is supposed to be mostly Matlab compatible.\n\n  for (; idx < argc; idx++)\n    {\n      if (argv[idx] == \"all\" && ! interp.is_local_variable (\"all\"))\n        {\n          interp.clear_all ();\n        }\n      else if (argv[idx] == \"functions\"\n               && ! interp.is_local_variable (\"functions\"))\n        {\n          do_clear_functions (interp, argv, argc, ++idx);\n        }\n      else if (argv[idx] == \"global\"\n               && ! interp.is_local_variable (\"global\"))\n        {\n          do_clear_globals (interp, argv, argc, ++idx);\n        }\n      else if (argv[idx] == \"variables\"\n               && ! interp.is_local_variable (\"variables\"))\n        {\n          interp.clear_variables ();\n        }\n      else if (argv[idx] == \"classes\"\n               && ! interp.is_local_variable (\"classes\"))\n        {\n          interp.clear_objects ();\n          octave_class::clear_exemplar_map ();\n          interp.clear_all ();\n        }\n      else\n        {\n          interp.clear_symbol_pattern (argv[idx]);\n        }\n    }\n}\n\nDEFMETHOD (clear, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} clear\n@deftypefnx {} {} clear @var{pattern} @dots{}\n@deftypefnx {} {} clear @var{options} @var{pattern} @dots{}\nDelete the names matching the given @var{pattern}s thereby freeing memory.\n\nThe @var{pattern} may contain the following special characters:\n\n@table @code\n@item ?\nMatch any single character.\n\n@item *\nMatch zero or more characters.\n\n@item [ @var{list} ]\nMatch the list of characters specified by @var{list}.  If the first character\nis @code{!} or @code{^}, match all characters except those specified by\n@var{list}.  For example, the pattern @code{[a-zA-Z]} will match all lowercase\nand uppercase alphabetic characters.  On Windows, square brackets are matched\nliterally and are not used to group characters.\n@end table\n\nFor example, the command\n\n@example\nclear foo b*r\n@end example\n\n@noindent\nclears the name @code{foo} and all names that begin with the letter @samp{b}\nand end with the letter @samp{r}.\n\nIf @code{clear} is called without any arguments, all user-defined variables\nare cleared from the current workspace (i.e., local variables).  Any global\nvariables present will no longer be visible in the current workspace, but they\nwill continue to exist in the global workspace.  Functions are unaffected by\nthis form of @code{clear}.\n\nThe following options are available in both long and short form\n\n@table @code\n@item all, -all, -a\nClear all local and global user-defined variables, and all functions from the\nsymbol table.\n\n@item -exclusive, -x\nClear variables that do @strong{not} match the following pattern.\n\n@item functions, -functions, -f\nClear function names from the function symbol table.  Persistent variables\nwill be re-initialized to their default value unless the function has been\nlocked in memory with @code{mlock}.\n\n@item global, -global, -g\nClear global variable names.\n\n@item variables, -variables, -v\nClear local variable names.\n\n@item classes, -classes, -c\nClear the class structure table and all objects.\n\n@item -regexp, -r\nThe @var{pattern} arguments are treated as regular expressions and any matches\nwill be cleared.\n@end table\n\nWith the exception of @option{-exclusive} and @option{-regexp}, all long\noptions can be used without the dash as well.  Note that, aside from\n@option{-exclusive}, only one other option may appear.  All options must\nappear before any patterns.\n\nProgramming Notes: The command @code{clear @var{name}} only clears the variable\n@var{name} when both a variable and a (shadowed) function named @var{name}\nare currently defined.  For example, suppose you have defined a function\n@code{foo}, and then hidden it by performing the assignment @code{foo = 2}.\nExecuting the command @code{clear foo} once will clear the variable\ndefinition and restore the definition of @code{foo} as a function.\nExecuting @code{clear foo} a second time will clear the function definition.\n\nWhen a local variable name, which is linked to a global variable, is cleared\nonly the local copy of the variable is removed.  The global copy is untouched\nand can be restored with @code{global @var{global_varname}}.  Conversely,\n@code{clear -g @var{global_varname}} will remove both the local and global\nvariables.\n\n@seealso{clearvars, who, whos, exist, mlock}\n@end deftypefn */)\n{\n  int argc = args.length () + 1;\n\n  string_vector argv = args.make_argv (\"clear\");\n\n  if (argc == 1)\n    {\n      do_clear_variables (interp, argv, argc, true);\n\n      event_manager& evmgr = interp.get_event_manager ();\n\n      evmgr.clear_workspace ();\n    }\n  else\n    {\n      int idx = 0;\n\n      bool clear_all = false;\n      bool clear_functions = false;\n      bool clear_globals = false;\n      bool clear_variables = false;\n      bool clear_objects = false;\n      bool exclusive = false;\n      bool have_regexp = false;\n      bool have_dash_option = false;\n\n      while (++idx < argc)\n        {\n          if (argv[idx] == \"-all\" || argv[idx] == \"-a\")\n            {\n              if (have_dash_option)\n                print_usage ();\n\n              have_dash_option = true;\n              clear_all = true;\n            }\n          else if (argv[idx] == \"-exclusive\" || argv[idx] == \"-x\")\n            {\n              exclusive = true;\n            }\n          else if (argv[idx] == \"-functions\" || argv[idx] == \"-f\")\n            {\n              if (have_dash_option)\n                print_usage ();\n\n              have_dash_option = true;\n              clear_functions = true;\n            }\n          else if (argv[idx] == \"-global\" || argv[idx] == \"-g\")\n            {\n              if (have_dash_option)\n                print_usage ();\n\n              have_dash_option = true;\n              clear_globals = true;\n            }\n          else if (argv[idx] == \"-variables\" || argv[idx] == \"-v\")\n            {\n              if (have_dash_option)\n                print_usage ();\n\n              have_dash_option = true;\n              clear_variables = true;\n            }\n          else if (argv[idx] == \"-classes\" || argv[idx] == \"-c\")\n            {\n              if (have_dash_option)\n                print_usage ();\n\n              have_dash_option = true;\n              clear_objects = true;\n            }\n          else if (argv[idx] == \"-regexp\" || argv[idx] == \"-r\")\n            {\n              if (have_dash_option)\n                print_usage ();\n\n              have_dash_option = true;\n              have_regexp = true;\n            }\n          else\n            break;\n        }\n\n      if (idx <= argc)\n        {\n          if (! have_dash_option && ! exclusive)\n            do_matlab_compatible_clear (interp, argv, argc, idx);\n          else\n            {\n              if (clear_all)\n                {\n                  maybe_warn_exclusive (exclusive);\n\n                  if (++idx < argc)\n                    warning (\"clear: ignoring extra arguments after -all\");\n\n                  interp.clear_all ();\n                }\n              else if (have_regexp)\n                {\n                  do_clear_variables (interp, argv, argc, idx, exclusive, true);\n                }\n              else if (clear_functions)\n                {\n                  do_clear_functions (interp, argv, argc, idx, exclusive);\n                }\n              else if (clear_globals)\n                {\n                  do_clear_globals (interp, argv, argc, idx, exclusive);\n                }\n              else if (clear_variables)\n                {\n                  do_clear_variables (interp, argv, argc, idx, exclusive);\n                }\n              else if (clear_objects)\n                {\n                  interp.clear_objects ();\n                  octave_class::clear_exemplar_map ();\n                  interp.clear_all ();\n                }\n              else\n                {\n                  do_clear_symbols (interp, argv, argc, idx, exclusive);\n                }\n            }\n        }\n    }\n\n  return ovl ();\n}\n\n/*\n## This test must be wrapped in its own function or the 'clear' command will\n## break the %!test environment.\n%!function __test_clear_no_args__ ()\n%!  global x;\n%!  x = 3;\n%!  clear\n%!  assert (! exist (\"x\", \"var\"));  # x is not in the current workspace anymore\n%!  global x;                       # but still lives in the global workspace\n%!  assert (exist (\"x\", \"var\"));\n%!endfunction\n\n%!test\n%! unwind_protect\n%!   __test_clear_no_args__ ();\n%! unwind_protect_cleanup\n%!   clear -g x\n%! end_unwind_protect\n\n## Test that multiple options cannot be given\n%!error clear -f -g\n*/\n\nstatic std::string Vmissing_function_hook = \"__unimplemented__\";\n\nDEFUN (missing_function_hook, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} missing_function_hook ()\n@deftypefnx {} {@var{old_val} =} missing_function_hook (@var{new_val})\n@deftypefnx {} {@var{old_val} =} missing_function_hook (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the function to call\nto provide extra information when an unknown identifier is referenced.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{missing_component_hook}\n@end deftypefn */)\n{\n  return set_internal_variable (Vmissing_function_hook, args, nargout,\n                                \"missing_function_hook\");\n}\n\nstd::string\nmaybe_missing_function_hook (const std::string& name)\n{\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  // Don't do this if we're handling errors.\n  if (Vmissing_function_hook.empty ())\n    return \"\";\n\n  octave::symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value val = symtab.find_function (Vmissing_function_hook);\n\n  if (val.is_defined ())\n    {\n      // Ensure auto-restoration.\n      octave::unwind_protect_var<std::string>\n      restore_var (Vmissing_function_hook);\n\n      // Clear the variable prior to calling the function.\n      const std::string fcn_name = Vmissing_function_hook;\n      Vmissing_function_hook.clear ();\n\n      // Call.\n      octave_value_list tmp = interp.feval (fcn_name, octave_value (name), 1);\n\n      if (tmp.length () == 1 && tmp(0).is_string ())\n        return tmp(0).string_value ();\n    }\n\n  return \"\";\n}\n\nDEFMETHOD (__varval__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{value} =} __varval__ (@var{name})\nReturn the value of the variable @var{name} directly from the symbol table.\n\nIf @var{name} does not exist then nothing is returned, not even an empty matrix\n(@code{[]}), since there would be no way to distinguish between a variable\nnot found in the symbol table and a variable who's value was @code{[]}.\n\nA standard usage pattern is to code a @code{try}/@code{catch} block around a\ncall to @code{__varval__}.\n\nExample Code\n\n@example\n@group\ntry\n  @var{val} = __varval__ (@var{name});\ncatch\n  ## No variable @var{name} found in symbol table\n  @var{val} = NA;                  # Substitute Not Available (NA)\n  error (\"@var{name} not found\");  # or, throw an error.\nend_try_catch\n@end group\n@end example\n\nProgramming Note: The magic @var{name} @qcode{\".argn.\"} will retrieve the text\nof input arguments to a function and is used by @code{inputname} internally.\n@seealso{inputname}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string name = args(0).xstring_value (\"__varval__: NAME must be a string\");\n\n  // We need this kluge to implement inputname in a .m file.\n  if (name == \".argn.\")\n    {\n      tree_evaluator& tw = interp.get_evaluator ();\n\n      return tw.get_auto_fcn_var (stack_frame::ARG_NAMES);\n    }\n\n  return interp.varval (name);\n}\n\nstatic std::string Vmissing_component_hook;\n\nDEFUN (missing_component_hook, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} missing_component_hook ()\n@deftypefnx {} {@var{old_val} =} missing_component_hook (@var{new_val})\n@deftypefnx {} {@var{old_val} =} missing_component_hook (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the function to call when\na component of Octave is missing.\n\nThis can be useful for packagers that may split the Octave installation into\nmultiple sub-packages, for example, to provide a hint to users for how to\ninstall the missing components.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n\nThe hook function is expected to be of the form\n\n@example\n@var{fcn} (@var{component})\n@end example\n\nOctave will call @var{fcn} with the name of the function that requires the\ncomponent and a string describing the missing component.  The hook function\nshould return an error message to be displayed.\n@seealso{missing_function_hook}\n@end deftypefn */)\n{\n  return set_internal_variable (Vmissing_component_hook, args, nargout,\n                                \"missing_component_hook\");\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/variables.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_variables_h)\n#define octave_variables_h 1\n\n#include \"octave-config.h\"\n\nclass octave_function;\nclass octave_user_function;\n\nclass octave_value;\nclass octave_value_list;\nclass octave_builtin;\nclass string_vector;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_identifier;\n\nOCTAVE_END_NAMESPACE(octave)\n\n#include <limits>\n#include <string>\n\n#include \"lo-ieee.h\"\n\n#include \"ov-builtin.h\"\n\n// The following two functions should be removed or the return type\n// should be changed when we remove octave_function from the interpreter\n// interface.  See the discussion about this topic here:\n// https://octave.discourse.group/t/refactoring-octave-value-function-objects-backward-incompatible-change/971\n\nextern OCTINTERP_API octave_function *\nis_valid_function (const octave_value&, const std::string& = \"\",\n                   bool warn = false);\n\nextern OCTINTERP_API octave_function *\nis_valid_function (const std::string&, const std::string& = \"\",\n                   bool warn = false);\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API int\nsymbol_exist (const std::string& name, const std::string& type = \"any\");\n\nextern OCTINTERP_API std::string\nunique_symbol_name (const std::string& basename);\n\nextern OCTINTERP_API octave_value\nset_internal_variable (bool& var, const octave_value_list& args,\n                       int nargout, const char *nm);\n\nextern OCTINTERP_API octave_value\nset_internal_variable (char& var, const octave_value_list& args,\n                       int nargout, const char *nm);\n\nextern OCTINTERP_API octave_value\nset_internal_variable (int& var, const octave_value_list& args,\n                       int nargout, const char *nm,\n                       int minval = std::numeric_limits<int>::min (),\n                       int maxval = std::numeric_limits<int>::max ());\n\nextern OCTINTERP_API octave_value\nset_internal_variable (double& var, const octave_value_list& args,\n                       int nargout, const char *nm,\n                       double minval = -octave::numeric_limits<double>::Inf (),\n                       double maxval = octave::numeric_limits<double>::Inf ());\n\nextern OCTINTERP_API octave_value\nset_internal_variable (std::string& var, const octave_value_list& args,\n                       int nargout, const char *nm, bool empty_ok = true);\n\nextern OCTINTERP_API octave_value\nset_internal_variable (std::string& var, const octave_value_list& args,\n                       int nargout, const char *nm, const char **choices);\n\nextern OCTINTERP_API octave_value\nset_internal_variable (int& var, const octave_value_list& args,\n                       int nargout, const char *nm, const char **choices);\n\nextern OCTINTERP_API std::string\nmaybe_missing_function_hook (const std::string& name);\n\nOCTAVE_END_NAMESPACE(octave)\n\n// The following macros should also be considered obsolete.\n\n#define SET_INTERNAL_VARIABLE(NM)                       \\\n  set_internal_variable (V ## NM, args, nargout, #NM)\n\n#define SET_NONEMPTY_INTERNAL_STRING_VARIABLE(NM)               \\\n  set_internal_variable (V ## NM, args, nargout, #NM, false)\n\n#define SET_INTERNAL_VARIABLE_WITH_LIMITS(NM, MINVAL, MAXVAL)           \\\n  set_internal_variable (V ## NM, args, nargout, #NM, MINVAL, MAXVAL)\n\n// in the following, CHOICES must be a C string array terminated by null.\n#define SET_INTERNAL_VARIABLE_CHOICES(NM, CHOICES)              \\\n  set_internal_variable (V ## NM, args, nargout, #NM, CHOICES)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/xdiv.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-util.h\"\n#include \"CMatrix.h\"\n#include \"dMatrix.h\"\n#include \"CNDArray.h\"\n#include \"dNDArray.h\"\n#include \"fCMatrix.h\"\n#include \"fMatrix.h\"\n#include \"fCNDArray.h\"\n#include \"fNDArray.h\"\n#include \"oct-cmplx.h\"\n#include \"dDiagMatrix.h\"\n#include \"fDiagMatrix.h\"\n#include \"CDiagMatrix.h\"\n#include \"fCDiagMatrix.h\"\n#include \"lo-array-errwarn.h\"\n#include \"quit.h\"\n\n#include \"error.h\"\n#include \"xdiv.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic void\nsolve_singularity_warning (double rcond)\n{\n  octave::warn_singular_matrix (rcond);\n}\n\ntemplate <typename T1, typename T2>\nbool\nmx_leftdiv_conform (const T1& a, const T2& b, blas_trans_type blas_trans)\n{\n  octave_idx_type a_nr = (blas_trans == blas_no_trans ? a.rows () : a.cols ());\n  octave_idx_type b_nr = b.rows ();\n\n  if (a_nr != b_nr)\n    {\n      octave_idx_type a_nc = (blas_trans == blas_no_trans ? a.cols ()\n                              : a.rows ());\n      octave_idx_type b_nc = b.cols ();\n\n      octave::err_nonconformant (R\"(operator \\)\", a_nr, a_nc, b_nr, b_nc);\n    }\n\n  return true;\n}\n\n#define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2)                          \\\n  template bool mx_leftdiv_conform (const T1&, const T2&, blas_trans_type)\n\nINSTANTIATE_MX_LEFTDIV_CONFORM (Matrix, Matrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (Matrix, ComplexMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (ComplexMatrix, Matrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (ComplexMatrix, ComplexMatrix);\n\ntemplate <typename T1, typename T2>\nbool\nmx_div_conform (const T1& a, const T2& b)\n{\n  octave_idx_type a_nc = a.cols ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nc)\n    {\n      octave_idx_type a_nr = a.rows ();\n      octave_idx_type b_nr = b.rows ();\n\n      octave::err_nonconformant (\"operator /\", a_nr, a_nc, b_nr, b_nc);\n    }\n\n  return true;\n}\n\n#define INSTANTIATE_MX_DIV_CONFORM(T1, T2)              \\\n  template bool mx_div_conform (const T1&, const T2&)\n\nINSTANTIATE_MX_DIV_CONFORM (Matrix, Matrix);\nINSTANTIATE_MX_DIV_CONFORM (Matrix, ComplexMatrix);\nINSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, Matrix);\nINSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, ComplexMatrix);\n\n// Right division functions.\n//\n//       op2 / op1:   m   cm\n//            +--   +---+----+\n//   matrix         | 1 |  3 |\n//                  +---+----+\n//   complex_matrix | 2 |  4 |\n//                  +---+----+\n\n// -*- 1 -*-\nMatrix\nxdiv (const Matrix& a, const Matrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return Matrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n\n  Matrix result\n    = b.solve (typ, a.transpose (), info, rcond,\n               solve_singularity_warning, true, blas_trans);\n\n  return result.transpose ();\n}\n\n// -*- 2 -*-\nComplexMatrix\nxdiv (const Matrix& a, const ComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return ComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n\n  ComplexMatrix result\n    = b.solve (typ, a.transpose (), info, rcond,\n               solve_singularity_warning, true, blas_trans);\n\n  return result.transpose ();\n}\n\n// -*- 3 -*-\nComplexMatrix\nxdiv (const ComplexMatrix& a, const Matrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return ComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n\n  ComplexMatrix result\n    = b.solve (typ, a.transpose (), info, rcond,\n               solve_singularity_warning, true, blas_trans);\n\n  return result.transpose ();\n}\n\n// -*- 4 -*-\nComplexMatrix\nxdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return ComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n\n  ComplexMatrix result\n    = b.solve (typ, a.transpose (), info, rcond,\n               solve_singularity_warning, true, blas_trans);\n\n  return result.transpose ();\n}\n\n// Funny element by element division operations.\n//\n//       op2 \\ op1:   s   cs\n//            +--   +---+----+\n//   matrix         | 1 |  3 |\n//                  +---+----+\n//   complex_matrix | 2 |  4 |\n//                  +---+----+\n\nMatrix\nelem_xdiv (double a, const Matrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.columns ();\n\n  Matrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result (i, j) = a / b (i, j);\n      }\n\n  return result;\n}\n\nComplexMatrix\nelem_xdiv (double a, const ComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.columns ();\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result (i, j) = a / b (i, j);\n      }\n\n  return result;\n}\n\nComplexMatrix\nelem_xdiv (const Complex a, const Matrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.columns ();\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result (i, j) = a / b (i, j);\n      }\n\n  return result;\n}\n\nComplexMatrix\nelem_xdiv (const Complex a, const ComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.columns ();\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result (i, j) = a / b (i, j);\n      }\n\n  return result;\n}\n\n// Funny element by element division operations.\n//\n//          op2 \\ op1:   s   cs\n//               +--   +---+----+\n//   N-D array         | 1 |  3 |\n//                     +---+----+\n//   complex N-D array | 2 |  4 |\n//                     +---+----+\n\nNDArray\nelem_xdiv (double a, const NDArray& b)\n{\n  NDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result (i) = a / b (i);\n    }\n\n  return result;\n}\n\nComplexNDArray\nelem_xdiv (double a, const ComplexNDArray& b)\n{\n  ComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result (i) = a / b (i);\n    }\n\n  return result;\n}\n\nComplexNDArray\nelem_xdiv (const Complex a, const NDArray& b)\n{\n  ComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result (i) = a / b (i);\n    }\n\n  return result;\n}\n\nComplexNDArray\nelem_xdiv (const Complex a, const ComplexNDArray& b)\n{\n  ComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result (i) = a / b (i);\n    }\n\n  return result;\n}\n\n// Left division functions.\n//\n//       op2 \\ op1:   m   cm\n//            +--   +---+----+\n//   matrix         | 1 |  3 |\n//                  +---+----+\n//   complex_matrix | 2 |  4 |\n//                  +---+----+\n\n// -*- 1 -*-\nMatrix\nxleftdiv (const Matrix& a, const Matrix& b, MatrixType& typ,\n          blas_trans_type transt)\n{\n  if (! mx_leftdiv_conform (a, b, transt))\n    return Matrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);\n}\n\n// -*- 2 -*-\nComplexMatrix\nxleftdiv (const Matrix& a, const ComplexMatrix& b, MatrixType& typ,\n          blas_trans_type transt)\n{\n  if (! mx_leftdiv_conform (a, b, transt))\n    return ComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n\n  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);\n}\n\n// -*- 3 -*-\nComplexMatrix\nxleftdiv (const ComplexMatrix& a, const Matrix& b, MatrixType& typ,\n          blas_trans_type transt)\n{\n  if (! mx_leftdiv_conform (a, b, transt))\n    return ComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);\n}\n\n// -*- 4 -*-\nComplexMatrix\nxleftdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType& typ,\n          blas_trans_type transt)\n{\n  if (! mx_leftdiv_conform (a, b, transt))\n    return ComplexMatrix ();\n\n  octave_idx_type info;\n  double rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);\n}\n\nstatic void\nsolve_singularity_warning (float rcond)\n{\n  octave::warn_singular_matrix (rcond);\n}\n\nINSTANTIATE_MX_LEFTDIV_CONFORM (FloatMatrix, FloatMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (FloatMatrix, FloatComplexMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (FloatComplexMatrix, FloatMatrix);\nINSTANTIATE_MX_LEFTDIV_CONFORM (FloatComplexMatrix, FloatComplexMatrix);\n\nINSTANTIATE_MX_DIV_CONFORM (FloatMatrix, FloatMatrix);\nINSTANTIATE_MX_DIV_CONFORM (FloatMatrix, FloatComplexMatrix);\nINSTANTIATE_MX_DIV_CONFORM (FloatComplexMatrix, FloatMatrix);\nINSTANTIATE_MX_DIV_CONFORM (FloatComplexMatrix, FloatComplexMatrix);\n\n// Right division functions.\n//\n//       op2 / op1:   m   cm\n//            +--   +---+----+\n//   matrix         | 1 |  3 |\n//                  +---+----+\n//   complex_matrix | 2 |  4 |\n//                  +---+----+\n\n// -*- 1 -*-\nFloatMatrix\nxdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return FloatMatrix ();\n\n  octave_idx_type info;\n  float rcond = 0.0;\n\n  FloatMatrix result\n    = b.solve (typ, a.transpose (), info, rcond,\n               solve_singularity_warning, true, blas_trans);\n\n  return result.transpose ();\n}\n\n// -*- 2 -*-\nFloatComplexMatrix\nxdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return FloatComplexMatrix ();\n\n  octave_idx_type info;\n  float rcond = 0.0;\n\n  FloatComplexMatrix result\n    = b.solve (typ, a.transpose (), info, rcond,\n               solve_singularity_warning, true, blas_trans);\n\n  return result.transpose ();\n}\n\n// -*- 3 -*-\nFloatComplexMatrix\nxdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return FloatComplexMatrix ();\n\n  octave_idx_type info;\n  float rcond = 0.0;\n\n  FloatComplexMatrix result\n    = b.solve (typ, a.transpose (), info, rcond,\n               solve_singularity_warning, true, blas_trans);\n\n  return result.transpose ();\n}\n\n// -*- 4 -*-\nFloatComplexMatrix\nxdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, MatrixType& typ)\n{\n  if (! mx_div_conform (a, b))\n    return FloatComplexMatrix ();\n\n  octave_idx_type info;\n  float rcond = 0.0;\n\n  FloatComplexMatrix result\n    = b.solve (typ, a.transpose (), info, rcond,\n               solve_singularity_warning, true, blas_trans);\n\n  return result.transpose ();\n}\n\n// Funny element by element division operations.\n//\n//       op2 \\ op1:   s   cs\n//            +--   +---+----+\n//   matrix         | 1 |  3 |\n//                  +---+----+\n//   complex_matrix | 2 |  4 |\n//                  +---+----+\n\nFloatMatrix\nelem_xdiv (float a, const FloatMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.columns ();\n\n  FloatMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result (i, j) = a / b (i, j);\n      }\n\n  return result;\n}\n\nFloatComplexMatrix\nelem_xdiv (float a, const FloatComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.columns ();\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result (i, j) = a / b (i, j);\n      }\n\n  return result;\n}\n\nFloatComplexMatrix\nelem_xdiv (const FloatComplex a, const FloatMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.columns ();\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result (i, j) = a / b (i, j);\n      }\n\n  return result;\n}\n\nFloatComplexMatrix\nelem_xdiv (const FloatComplex a, const FloatComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.columns ();\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result (i, j) = a / b (i, j);\n      }\n\n  return result;\n}\n\n// Funny element by element division operations.\n//\n//          op2 \\ op1:   s   cs\n//               +--   +---+----+\n//   N-D array         | 1 |  3 |\n//                     +---+----+\n//   complex N-D array | 2 |  4 |\n//                     +---+----+\n\nFloatNDArray\nelem_xdiv (float a, const FloatNDArray& b)\n{\n  FloatNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result (i) = a / b (i);\n    }\n\n  return result;\n}\n\nFloatComplexNDArray\nelem_xdiv (float a, const FloatComplexNDArray& b)\n{\n  FloatComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result (i) = a / b (i);\n    }\n\n  return result;\n}\n\nFloatComplexNDArray\nelem_xdiv (const FloatComplex a, const FloatNDArray& b)\n{\n  FloatComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result (i) = a / b (i);\n    }\n\n  return result;\n}\n\nFloatComplexNDArray\nelem_xdiv (const FloatComplex a, const FloatComplexNDArray& b)\n{\n  FloatComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result (i) = a / b (i);\n    }\n\n  return result;\n}\n\n// Left division functions.\n//\n//       op2 \\ op1:   m   cm\n//            +--   +---+----+\n//   matrix         | 1 |  3 |\n//                  +---+----+\n//   complex_matrix | 2 |  4 |\n//                  +---+----+\n\n// -*- 1 -*-\nFloatMatrix\nxleftdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType& typ,\n          blas_trans_type transt)\n{\n  if (! mx_leftdiv_conform (a, b, transt))\n    return FloatMatrix ();\n\n  octave_idx_type info;\n  float rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);\n}\n\n// -*- 2 -*-\nFloatComplexMatrix\nxleftdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType& typ,\n          blas_trans_type transt)\n{\n  if (! mx_leftdiv_conform (a, b, transt))\n    return FloatComplexMatrix ();\n\n  octave_idx_type info;\n  float rcond = 0.0;\n\n  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);\n}\n\n// -*- 3 -*-\nFloatComplexMatrix\nxleftdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType& typ,\n          blas_trans_type transt)\n{\n  if (! mx_leftdiv_conform (a, b, transt))\n    return FloatComplexMatrix ();\n\n  octave_idx_type info;\n  float rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);\n}\n\n// -*- 4 -*-\nFloatComplexMatrix\nxleftdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n          MatrixType& typ, blas_trans_type transt)\n{\n  if (! mx_leftdiv_conform (a, b, transt))\n    return FloatComplexMatrix ();\n\n  octave_idx_type info;\n  float rcond = 0.0;\n  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);\n}\n\n// Diagonal matrix division.\n\ntemplate <typename MT, typename DMT>\nMT\nmdm_div_impl (const MT& a, const DMT& d)\n{\n  if (! mx_div_conform (a, d))\n    return MT ();\n\n  octave_idx_type m = a.rows ();\n  octave_idx_type n = d.rows ();\n  octave_idx_type l = d.length ();\n  MT x (m, n);\n  typedef typename DMT::element_type S;\n  typedef typename MT::element_type T;\n  const T *aa = a.data ();\n  const S *dd = d.data ();\n  T *xx = x.rwdata ();\n\n  for (octave_idx_type j = 0; j < l; j++)\n    {\n      const S del = dd[j];\n      if (del != S ())\n        for (octave_idx_type i = 0; i < m; i++)\n          xx[i] = aa[i] / del;\n      else\n        for (octave_idx_type i = 0; i < m; i++)\n          xx[i] = T ();\n      aa += m; xx += m;\n    }\n\n  for (octave_idx_type i = l*m; i < n*m; i++)\n    xx[i] = T ();\n\n  return x;\n}\n\n// Right division functions.\n//\n//       op2 / op1:   dm  cdm\n//            +--   +---+----+\n//   matrix         | 1 |    |\n//                  +---+----+\n//   complex_matrix | 2 |  3 |\n//                  +---+----+\n\n// -*- 1 -*-\nMatrix\nxdiv (const Matrix& a, const DiagMatrix& b)\n{ return mdm_div_impl (a, b); }\n\n// -*- 2 -*-\nComplexMatrix\nxdiv (const ComplexMatrix& a, const DiagMatrix& b)\n{ return mdm_div_impl (a, b); }\n\n// -*- 3 -*-\nComplexMatrix\nxdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b)\n{ return mdm_div_impl (a, b); }\n\n// Right division functions, float type.\n//\n//       op2 / op1:   dm  cdm\n//            +--   +---+----+\n//   matrix         | 1 |    |\n//                  +---+----+\n//   complex_matrix | 2 |  3 |\n//                  +---+----+\n\n// -*- 1 -*-\nFloatMatrix\nxdiv (const FloatMatrix& a, const FloatDiagMatrix& b)\n{ return mdm_div_impl (a, b); }\n\n// -*- 2 -*-\nFloatComplexMatrix\nxdiv (const FloatComplexMatrix& a, const FloatDiagMatrix& b)\n{ return mdm_div_impl (a, b); }\n\n// -*- 3 -*-\nFloatComplexMatrix\nxdiv (const FloatComplexMatrix& a, const FloatComplexDiagMatrix& b)\n{ return mdm_div_impl (a, b); }\n\ntemplate <typename MT, typename DMT>\nMT\ndmm_leftdiv_impl (const DMT& d, const MT& a)\n{\n  if (! mx_leftdiv_conform (d, a, blas_no_trans))\n    return MT ();\n\n  octave_idx_type m = d.cols ();\n  octave_idx_type n = a.cols ();\n  octave_idx_type k = a.rows ();\n  octave_idx_type l = d.length ();\n  MT x (m, n);\n  typedef typename DMT::element_type S;\n  typedef typename MT::element_type T;\n  const T *aa = a.data ();\n  const S *dd = d.data ();\n  T *xx = x.rwdata ();\n\n  for (octave_idx_type j = 0; j < n; j++)\n    {\n      for (octave_idx_type i = 0; i < l; i++)\n        xx[i] = (dd[i] != S () ? aa[i] / dd[i] : T ());\n      for (octave_idx_type i = l; i < m; i++)\n        xx[i] = T ();\n      aa += k; xx += m;\n    }\n\n  return x;\n}\n\n// Left division functions.\n//\n//       op2 \\ op1:         m   cm\n//                        +---+----+\n//   diag_matrix          | 1 |  2 |\n//                        +---+----+\n//   complex_diag_matrix  |   |  3 |\n//                        +---+----+\n\n// -*- 1 -*-\nMatrix\nxleftdiv (const DiagMatrix& a, const Matrix& b)\n{ return dmm_leftdiv_impl (a, b); }\n\n// -*- 2 -*-\nComplexMatrix\nxleftdiv (const DiagMatrix& a, const ComplexMatrix& b)\n{ return dmm_leftdiv_impl (a, b); }\n\n// -*- 3 -*-\nComplexMatrix\nxleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b)\n{ return dmm_leftdiv_impl (a, b); }\n\n// Left division functions, float type.\n//\n//       op2 \\ op1:         m   cm\n//                        +---+----+\n//   diag_matrix          | 1 |  2 |\n//                        +---+----+\n//   complex_diag_matrix  |   |  3 |\n//                        +---+----+\n\n// -*- 1 -*-\nFloatMatrix\nxleftdiv (const FloatDiagMatrix& a, const FloatMatrix& b)\n{ return dmm_leftdiv_impl (a, b); }\n\n// -*- 2 -*-\nFloatComplexMatrix\nxleftdiv (const FloatDiagMatrix& a, const FloatComplexMatrix& b)\n{ return dmm_leftdiv_impl (a, b); }\n\n// -*- 3 -*-\nFloatComplexMatrix\nxleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexMatrix& b)\n{ return dmm_leftdiv_impl (a, b); }\n\n// Diagonal by diagonal matrix division.\n\ntemplate <typename MT, typename DMT>\nMT\ndmdm_div_impl (const MT& a, const DMT& d)\n{\n  if (! mx_div_conform (a, d))\n    return MT ();\n\n  octave_idx_type m = a.rows ();\n  octave_idx_type n = d.rows ();\n  octave_idx_type k = d.cols ();\n  octave_idx_type l = std::min (m, n);\n  octave_idx_type lk = std::min (l, k);\n  MT x (m, n);\n  typedef typename DMT::element_type S;\n  typedef typename MT::element_type T;\n  const T *aa = a.data ();\n  const S *dd = d.data ();\n  T *xx = x.rwdata ();\n\n  for (octave_idx_type i = 0; i < lk; i++)\n    xx[i] = (dd[i] != S () ? aa[i] / dd[i] : T ());\n  for (octave_idx_type i = lk; i < l; i++)\n    xx[i] = T ();\n\n  return x;\n}\n\n// Right division functions.\n//\n//       op2 / op1:        dm  cdm\n//            +--        +---+----+\n//   diag_matrix         | 1 |    |\n//                       +---+----+\n//   complex_diag_matrix | 2 |  3 |\n//                       +---+----+\n\n// -*- 1 -*-\nDiagMatrix\nxdiv (const DiagMatrix& a, const DiagMatrix& b)\n{ return dmdm_div_impl (a, b); }\n\n// -*- 2 -*-\nComplexDiagMatrix\nxdiv (const ComplexDiagMatrix& a, const DiagMatrix& b)\n{ return dmdm_div_impl (a, b); }\n\n// -*- 3 -*-\nComplexDiagMatrix\nxdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)\n{ return dmdm_div_impl (a, b); }\n\n// Right division functions, float type.\n//\n//       op2 / op1:        dm  cdm\n//            +--        +---+----+\n//   diag_matrix         | 1 |    |\n//                       +---+----+\n//   complex_diag_matrix | 2 |  3 |\n//                       +---+----+\n\n// -*- 1 -*-\nFloatDiagMatrix\nxdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)\n{ return dmdm_div_impl (a, b); }\n\n// -*- 2 -*-\nFloatComplexDiagMatrix\nxdiv (const FloatComplexDiagMatrix& a, const FloatDiagMatrix& b)\n{ return dmdm_div_impl (a, b); }\n\n// -*- 3 -*-\nFloatComplexDiagMatrix\nxdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)\n{ return dmdm_div_impl (a, b); }\n\ntemplate <typename MT, typename DMT>\nMT\ndmdm_leftdiv_impl (const DMT& d, const MT& a)\n{\n  if (! mx_leftdiv_conform (d, a, blas_no_trans))\n    return MT ();\n\n  octave_idx_type m = d.cols ();\n  octave_idx_type n = a.cols ();\n  octave_idx_type k = d.rows ();\n  octave_idx_type l = std::min (m, n);\n  octave_idx_type lk = std::min (l, k);\n  MT x (m, n);\n  typedef typename DMT::element_type S;\n  typedef typename MT::element_type T;\n  const T *aa = a.data ();\n  const S *dd = d.data ();\n  T *xx = x.rwdata ();\n\n  for (octave_idx_type i = 0; i < lk; i++)\n    xx[i] = (dd[i] != S () ? aa[i] / dd[i] : T ());\n  for (octave_idx_type i = lk; i < l; i++)\n    xx[i] = T ();\n\n  return x;\n}\n\n// Left division functions.\n//\n//       op2 \\ op1:         dm  cdm\n//                        +---+----+\n//   diag_matrix          | 1 |  2 |\n//                        +---+----+\n//   complex_diag_matrix  |   |  3 |\n//                        +---+----+\n\n// -*- 1 -*-\nDiagMatrix\nxleftdiv (const DiagMatrix& a, const DiagMatrix& b)\n{ return dmdm_leftdiv_impl (a, b); }\n\n// -*- 2 -*-\nComplexDiagMatrix\nxleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b)\n{ return dmdm_leftdiv_impl (a, b); }\n\n// -*- 3 -*-\nComplexDiagMatrix\nxleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)\n{ return dmdm_leftdiv_impl (a, b); }\n\n// Left division functions, float type.\n//\n//       op2 \\ op1:         dm  cdm\n//                        +---+----+\n//   diag_matrix          | 1 |  2 |\n//                        +---+----+\n//   complex_diag_matrix  |   |  3 |\n//                        +---+----+\n\n// -*- 1 -*-\nFloatDiagMatrix\nxleftdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)\n{ return dmdm_leftdiv_impl (a, b); }\n\n// -*- 2 -*-\nFloatComplexDiagMatrix\nxleftdiv (const FloatDiagMatrix& a, const FloatComplexDiagMatrix& b)\n{ return dmdm_leftdiv_impl (a, b); }\n\n// -*- 3 -*-\nFloatComplexDiagMatrix\nxleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)\n{ return dmdm_leftdiv_impl (a, b); }\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/xdiv.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_xdiv_h)\n#define octave_xdiv_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-defs.h\"\n#include \"MatrixType.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern Matrix xdiv (const Matrix& a, const Matrix& b, MatrixType& typ);\nextern ComplexMatrix xdiv (const Matrix& a, const ComplexMatrix& b,\n                           MatrixType& typ);\nextern ComplexMatrix xdiv (const ComplexMatrix& a, const Matrix& b,\n                           MatrixType& typ);\nextern ComplexMatrix xdiv (const ComplexMatrix& a, const ComplexMatrix& b,\n                           MatrixType& typ);\n\nextern Matrix elem_xdiv (double a, const Matrix& b);\nextern ComplexMatrix elem_xdiv (double a, const ComplexMatrix& b);\nextern ComplexMatrix elem_xdiv (const Complex a, const Matrix& b);\nextern ComplexMatrix elem_xdiv (const Complex a, const ComplexMatrix& b);\n\nextern NDArray elem_xdiv (double a, const NDArray& b);\nextern ComplexNDArray elem_xdiv (double a, const ComplexNDArray& b);\nextern ComplexNDArray elem_xdiv (const Complex a, const NDArray& b);\nextern ComplexNDArray elem_xdiv (const Complex a, const ComplexNDArray& b);\n\nextern Matrix xleftdiv (const Matrix& a, const Matrix& b, MatrixType& typ,\n                        blas_trans_type transt = blas_no_trans);\nextern ComplexMatrix xleftdiv (const Matrix& a, const ComplexMatrix& b,\n                               MatrixType& typ,\n                               blas_trans_type transt = blas_no_trans);\nextern ComplexMatrix xleftdiv (const ComplexMatrix& a, const Matrix& b,\n                               MatrixType& typ,\n                               blas_trans_type transt = blas_no_trans);\nextern ComplexMatrix xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b,\n                               MatrixType& typ,\n                               blas_trans_type transt = blas_no_trans);\n\nextern FloatMatrix xdiv (const FloatMatrix& a, const FloatMatrix& b,\n                         MatrixType& typ);\nextern FloatComplexMatrix xdiv (const FloatMatrix& a,\n                                const FloatComplexMatrix& b,\n                                MatrixType& typ);\nextern FloatComplexMatrix xdiv (const FloatComplexMatrix& a,\n                                const FloatMatrix& b,\n                                MatrixType& typ);\nextern FloatComplexMatrix xdiv (const FloatComplexMatrix& a,\n                                const FloatComplexMatrix& b,\n                                MatrixType& typ);\n\nextern FloatMatrix elem_xdiv (float a, const FloatMatrix& b);\nextern FloatComplexMatrix elem_xdiv (float a, const FloatComplexMatrix& b);\nextern FloatComplexMatrix elem_xdiv (const FloatComplex a,\n                                     const FloatMatrix& b);\nextern FloatComplexMatrix elem_xdiv (const FloatComplex a,\n                                     const FloatComplexMatrix& b);\n\nextern FloatNDArray elem_xdiv (float a, const FloatNDArray& b);\nextern FloatComplexNDArray elem_xdiv (float a, const FloatComplexNDArray& b);\nextern FloatComplexNDArray elem_xdiv (const FloatComplex a,\n                                      const FloatNDArray& b);\nextern FloatComplexNDArray elem_xdiv (const FloatComplex a,\n                                      const FloatComplexNDArray& b);\n\nextern FloatMatrix xleftdiv (const FloatMatrix& a, const FloatMatrix& b,\n                             MatrixType& typ,\n                             blas_trans_type transt = blas_no_trans);\nextern FloatComplexMatrix xleftdiv (const FloatMatrix& a,\n                                    const FloatComplexMatrix& b,\n                                    MatrixType& typ,\n                                    blas_trans_type transt = blas_no_trans);\nextern FloatComplexMatrix xleftdiv (const FloatComplexMatrix& a,\n                                    const FloatMatrix& b,\n                                    MatrixType& typ,\n                                    blas_trans_type transt = blas_no_trans);\nextern FloatComplexMatrix xleftdiv (const FloatComplexMatrix& a,\n                                    const FloatComplexMatrix& b,\n                                    MatrixType& typ,\n                                    blas_trans_type transt = blas_no_trans);\n\nextern Matrix xdiv (const Matrix& a, const DiagMatrix& b);\nextern ComplexMatrix xdiv (const ComplexMatrix& a, const DiagMatrix& b);\nextern ComplexMatrix xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b);\n\nextern DiagMatrix xdiv (const DiagMatrix& a, const DiagMatrix& b);\nextern ComplexDiagMatrix xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b);\nextern ComplexDiagMatrix xdiv (const ComplexDiagMatrix& a,\n                               const ComplexDiagMatrix& b);\n\nextern FloatMatrix xdiv (const FloatMatrix& a, const FloatDiagMatrix& b);\nextern FloatComplexMatrix xdiv (const FloatComplexMatrix& a,\n                                const FloatDiagMatrix& b);\nextern FloatComplexMatrix xdiv (const FloatMatrix& a,\n                                const FloatComplexDiagMatrix& b);\nextern FloatComplexMatrix xdiv (const FloatComplexMatrix& a,\n                                const FloatComplexDiagMatrix& b);\n\nextern FloatDiagMatrix xdiv (const FloatDiagMatrix& a,\n                             const FloatDiagMatrix& b);\nextern FloatComplexDiagMatrix xdiv (const FloatComplexDiagMatrix& a,\n                                    const FloatDiagMatrix& b);\nextern FloatComplexDiagMatrix xdiv (const FloatComplexDiagMatrix& a,\n                                    const FloatComplexDiagMatrix& b);\n\nextern Matrix xleftdiv (const DiagMatrix& a, const Matrix& b);\nextern ComplexMatrix xleftdiv (const DiagMatrix& a, const ComplexMatrix& b);\nextern ComplexMatrix xleftdiv (const ComplexDiagMatrix& a,\n                               const ComplexMatrix& b);\n\nextern DiagMatrix xleftdiv (const DiagMatrix& a, const DiagMatrix& b);\nextern ComplexDiagMatrix xleftdiv (const DiagMatrix& a,\n                                   const ComplexDiagMatrix& b);\nextern ComplexDiagMatrix xleftdiv (const ComplexDiagMatrix& a,\n                                   const ComplexDiagMatrix& b);\n\nextern FloatMatrix xleftdiv (const FloatDiagMatrix& a,\n                             const FloatMatrix& b);\nextern FloatComplexMatrix xleftdiv (const FloatDiagMatrix& a,\n                                    const FloatComplexMatrix& b);\nextern FloatComplexMatrix xleftdiv (const FloatComplexDiagMatrix& a,\n                                    const FloatComplexMatrix& b);\n\nextern FloatDiagMatrix xleftdiv (const FloatDiagMatrix& a,\n                                 const FloatDiagMatrix& b);\nextern FloatComplexDiagMatrix xleftdiv (const FloatDiagMatrix& a,\n                                        const FloatComplexDiagMatrix& b);\nextern FloatComplexDiagMatrix xleftdiv (const FloatComplexDiagMatrix& a,\n                                        const FloatComplexDiagMatrix& b);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/xnorm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-norm.h\"\n\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"xnorm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\noctave_value xnorm (const octave_value& x, const octave_value& p)\n{\n  octave_value retval;\n\n  bool isvector = (x.columns () == 1 || x.rows () == 1);\n  bool iscomplex = x.iscomplex ();\n  bool issparse = x.issparse ();\n  bool isfloat = x.is_single_type ();\n\n  if (! isfloat && ! x.is_double_type ())\n    err_wrong_type_arg (\"xnorm\", x);\n\n  if (x.isempty ())\n    retval = octave_value (0);\n  else if (isvector)\n    {\n      if (isfloat && iscomplex)\n        retval = octave::xnorm (x.float_complex_column_vector_value (),\n                                p.float_value ());\n      else if (isfloat)\n        retval = octave::xnorm (x.float_column_vector_value (),\n                                p.float_value ());\n      else if (iscomplex)\n        retval = octave::xnorm (x.complex_column_vector_value (),\n                                p.double_value ());\n      else\n        retval = octave::xnorm (x.column_vector_value (),\n                                p.double_value ());\n    }\n  else if (issparse)\n    {\n      if (iscomplex)\n        retval = octave::xnorm (x.sparse_complex_matrix_value (),\n                                p.double_value ());\n      else\n        retval = octave::xnorm (x.sparse_matrix_value (),\n                                p.double_value ());\n    }\n  else\n    {\n      if (isfloat && iscomplex)\n        retval = octave::xnorm (x.float_complex_matrix_value (),\n                                p.float_value ());\n      else if (isfloat)\n        retval = octave::xnorm (x.float_matrix_value (),\n                                p.float_value ());\n      else if (iscomplex)\n        retval = octave::xnorm (x.complex_matrix_value (),\n                                p.double_value ());\n      else\n        retval = octave::xnorm (x.matrix_value (),\n                                p.double_value ());\n    }\n\n  return retval;\n}\n\noctave_value\nxcolnorms (const octave_value& x, const octave_value& p)\n{\n  octave_value retval;\n\n  bool iscomplex = x.iscomplex ();\n  bool issparse = x.issparse ();\n  bool isfloat = x.is_single_type ();\n\n  if (! isfloat && ! x.is_double_type ())\n    err_wrong_type_arg (\"xcolnorms\", x);\n\n  if (issparse)\n    {\n      if (iscomplex)\n        retval = octave::xcolnorms (x.sparse_complex_matrix_value (),\n                                    p.double_value ());\n      else\n        retval = octave::xcolnorms (x.sparse_matrix_value (),\n                                    p.double_value ());\n    }\n  else\n    {\n      if (isfloat && iscomplex)\n        retval = octave::xcolnorms (x.float_complex_matrix_value (),\n                                    p.float_value ());\n      else if (isfloat)\n        retval = octave::xcolnorms (x.float_matrix_value (),\n                                    p.float_value ());\n      else if (iscomplex)\n        retval = octave::xcolnorms (x.complex_matrix_value (),\n                                    p.double_value ());\n      else\n        retval = octave::xcolnorms (x.matrix_value (),\n                                    p.double_value ());\n    }\n\n  return retval;\n}\n\noctave_value\nxrownorms (const octave_value& x, const octave_value& p)\n{\n  octave_value retval;\n\n  bool iscomplex = x.iscomplex ();\n  bool issparse = x.issparse ();\n  bool isfloat = x.is_single_type ();\n\n  if (! isfloat && ! x.is_double_type ())\n    err_wrong_type_arg (\"xrownorms\", x);\n\n  if (issparse)\n    {\n      if (iscomplex)\n        retval = octave::xrownorms (x.sparse_complex_matrix_value (),\n                                    p.double_value ());\n      else\n        retval = octave::xrownorms (x.sparse_matrix_value (),\n                                    p.double_value ());\n    }\n  else\n    {\n      if (isfloat && iscomplex)\n        retval = octave::xrownorms (x.float_complex_matrix_value (),\n                                    p.float_value ());\n      else if (isfloat)\n        retval = octave::xrownorms (x.float_matrix_value (),\n                                    p.float_value ());\n      else if (iscomplex)\n        retval = octave::xrownorms (x.complex_matrix_value (),\n                                    p.double_value ());\n      else\n        retval = octave::xrownorms (x.matrix_value (),\n                                    p.double_value ());\n    }\n\n  return retval;\n}\n\noctave_value\nxfrobnorm (const octave_value& x)\n{\n  octave_value retval;\n\n  bool iscomplex = x.iscomplex ();\n  bool issparse = x.issparse ();\n  bool isfloat = x.is_single_type ();\n\n  if (! isfloat && ! x.is_double_type ())\n    err_wrong_type_arg (\"xfrobnorm\", x);\n\n  if (issparse)\n    {\n      if (iscomplex)\n        retval = octave::xfrobnorm (x.sparse_complex_matrix_value ());\n      else\n        retval = octave::xfrobnorm (x.sparse_matrix_value ());\n    }\n  else\n    {\n      if (isfloat && iscomplex)\n        retval = octave::xfrobnorm (x.float_complex_matrix_value ());\n      else if (isfloat)\n        retval = octave::xfrobnorm (x.float_matrix_value ());\n      else if (iscomplex)\n        retval = octave::xfrobnorm (x.complex_matrix_value ());\n      else\n        retval = octave::xfrobnorm (x.matrix_value ());\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/xnorm.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_xnorm_h)\n#define octave_xnorm_h 1\n\n#include \"octave-config.h\"\n\n#include \"oct-norm.h\"\n\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API octave_value\nxnorm (const octave_value& x, const octave_value& p);\n\nextern OCTINTERP_API octave_value\nxcolnorms (const octave_value& x, const octave_value& p);\n\nextern OCTINTERP_API octave_value\nxrownorms (const octave_value& x, const octave_value& p);\n\nextern OCTINTERP_API octave_value\nxfrobnorm (const octave_value& x);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/corefcn/xpow.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <limits>\n\n#include \"Array-util.h\"\n#include \"CColVector.h\"\n#include \"CDiagMatrix.h\"\n#include \"fCDiagMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"CMatrix.h\"\n#include \"EIG.h\"\n#include \"fEIG.h\"\n#include \"dDiagMatrix.h\"\n#include \"fDiagMatrix.h\"\n#include \"dMatrix.h\"\n#include \"PermMatrix.h\"\n#include \"mx-cm-cdm.h\"\n#include \"mx-fcm-fcdm.h\"\n#include \"oct-cmplx.h\"\n#include \"Range.h\"\n#include \"quit.h\"\n\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n#include \"xpow.h\"\n\n#include \"bsxfun.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic void\nerr_failed_diagonalization ()\n{\n  error (\"Failed to diagonalize matrix while calculating matrix exponential\");\n}\n\nstatic void\nerr_nonsquare_matrix ()\n{\n  error (\"for x^y, only square matrix arguments are permitted and one \" \\\n         \"argument must be scalar.  Use .^ for elementwise power.\");\n}\n\ntemplate <typename T>\nstatic inline bool\nxisint (T x)\n{\n  return (octave::math::is_integer (x)\n          && x <= std::numeric_limits<int>::max ()\n          && x >= std::numeric_limits<int>::min ());\n}\n\nstatic inline bool\nxisint (float x)\n{\n  static constexpr float out_of_range_top\n    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.0;\n\n  // FIXME: If we return *only* octave::math::is_integer (x)\n  // and delete the lines with numeric_limits<int>,\n  // then that works on MacOS but not on Linux.\n  // A simple test is:    Complex (realmin, realmin) .^ realmax.\n  // On MacOS it gives zero.  On Linux it gives Inf - Nani.\n  // If we can make both platforms work without the extra check with\n  // numeric_limits<int>, then we should do so.\n\n  return (octave::math::is_integer (x)\n          && x < out_of_range_top\n          && x >= std::numeric_limits<int>::min ());\n}\n\n// Safer pow functions.\n//\n//       op2 \\ op1:   s   m   cs   cm\n//            +--   +---+---+----+----+\n//   scalar   |     | 1 | 5 |  7 | 11 |\n//                  +---+---+----+----+\n//   matrix         | 2 | * |  8 |  * |\n//                  +---+---+----+----+\n//   complex_scalar | 3 | 6 |  9 | 12 |\n//                  +---+---+----+----+\n//   complex_matrix | 4 | * | 10 |  * |\n//                  +---+---+----+----+\n\n// -*- 1 -*-\noctave_value\nxpow (double a, double b)\n{\n  double retval;\n\n  if (a < 0.0 && ! xisint (b))\n    {\n      Complex acplx (a);\n\n      return std::pow (acplx, b);\n    }\n  else\n    retval = std::pow (a, b);\n\n  return retval;\n}\n\n// -*- 2 -*-\noctave_value\nxpow (double a, const Matrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  EIG b_eig (b);\n\n  try\n    {\n      ComplexColumnVector lambda (b_eig.eigenvalues ());\n      ComplexMatrix Q (b_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (a, lambda(i));\n\n      ComplexDiagMatrix D (lambda);\n\n      ComplexMatrix C = Q * D * Q.inverse ();\n      if (a > 0)\n        retval = real (C);\n      else\n        retval = C;\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 3 -*-\noctave_value\nxpow (double a, const Complex& b)\n{\n  Complex result = std::pow (a, b);\n  return result;\n}\n\n// -*- 4 -*-\noctave_value\nxpow (double a, const ComplexMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  EIG b_eig (b);\n\n  try\n    {\n      ComplexColumnVector lambda (b_eig.eigenvalues ());\n      ComplexMatrix Q (b_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (a, lambda(i));\n\n      ComplexDiagMatrix D (lambda);\n\n      retval = ComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 5 -*-\noctave_value\nxpow (const Matrix& a, double b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      if (bint == 0)\n        {\n          retval = DiagMatrix (nr, nr, 1.0);\n        }\n      else\n        {\n          // Too much copying?\n          // FIXME: we shouldn't do this if the exponent is large...\n\n          Matrix atmp;\n          if (bint < 0)\n            {\n              bint = -bint;\n\n              octave_idx_type info;\n              double rcond = 0.0;\n              MatrixType mattype (a);\n\n              atmp = a.inverse (mattype, info, rcond, 1);\n\n              if (info == -1)\n                warning (\"inverse: matrix singular to machine precision, rcond = %g\", rcond);\n            }\n          else\n            atmp = a;\n\n          Matrix result (atmp);\n\n          bint--;\n\n          while (bint > 0)\n            {\n              if (bint & 1)\n                // Use atmp * result instead of result * atmp\n                // for ML compatibility (bug #52706).\n                result = atmp * result;\n\n              bint >>= 1;\n\n              if (bint > 0)\n                atmp = atmp * atmp;\n            }\n\n          retval = result;\n        }\n    }\n  else\n    {\n      EIG a_eig (a);\n\n      try\n        {\n          ComplexColumnVector lambda (a_eig.eigenvalues ());\n          ComplexMatrix Q (a_eig.right_eigenvectors ());\n\n          for (octave_idx_type i = 0; i < nr; i++)\n            lambda(i) = std::pow (lambda(i), b);\n\n          ComplexDiagMatrix D (lambda);\n\n          retval = ComplexMatrix (Q * D * Q.inverse ());\n        }\n      catch (const octave::execution_exception&)\n        {\n          err_failed_diagonalization ();\n        }\n    }\n\n  return retval;\n}\n\n// -*- 5d -*-\noctave_value\nxpow (const DiagMatrix& a, double b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      DiagMatrix r (nr, nc);\n      for (octave_idx_type i = 0; i < nc; i++)\n        r.dgxelem (i) = std::pow (a.dgxelem (i), bint);\n      retval = r;\n    }\n  else\n    {\n      ComplexDiagMatrix r (nr, nc);\n      for (octave_idx_type i = 0; i < nc; i++)\n        r.dgxelem (i) = std::pow (static_cast<Complex> (a.dgxelem (i)), b);\n      retval = r;\n    }\n\n  return retval;\n}\n\n// -*- 5p -*-\noctave_value\nxpow (const PermMatrix& a, double b)\n{\n  if (xisint (b))\n    return a.power (static_cast<int> (b));\n  else\n    return xpow (Matrix (a), b);\n}\n\n// -*- 6 -*-\noctave_value\nxpow (const Matrix& a, const Complex& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  EIG a_eig (a);\n\n  try\n    {\n      ComplexColumnVector lambda (a_eig.eigenvalues ());\n      ComplexMatrix Q (a_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (lambda(i), b);\n\n      ComplexDiagMatrix D (lambda);\n\n      retval = ComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 7 -*-\noctave_value\nxpow (const Complex& a, double b)\n{\n  Complex result;\n\n  if (xisint (b))\n    result = std::pow (a, static_cast<int> (b));\n  else\n    result = std::pow (a, b);\n\n  return result;\n}\n\n// -*- 8 -*-\noctave_value\nxpow (const Complex& a, const Matrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  EIG b_eig (b);\n\n  try\n    {\n      ComplexColumnVector lambda (b_eig.eigenvalues ());\n      ComplexMatrix Q (b_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (a, lambda(i));\n\n      ComplexDiagMatrix D (lambda);\n\n      retval = ComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 9 -*-\noctave_value\nxpow (const Complex& a, const Complex& b)\n{\n  Complex result;\n  result = std::pow (a, b);\n  return result;\n}\n\n// -*- 10 -*-\noctave_value\nxpow (const Complex& a, const ComplexMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  EIG b_eig (b);\n\n  try\n    {\n      ComplexColumnVector lambda (b_eig.eigenvalues ());\n      ComplexMatrix Q (b_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (a, lambda(i));\n\n      ComplexDiagMatrix D (lambda);\n\n      retval = ComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 11 -*-\noctave_value\nxpow (const ComplexMatrix& a, double b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      if (bint == 0)\n        {\n          retval = DiagMatrix (nr, nr, 1.0);\n        }\n      else\n        {\n          // Too much copying?\n          // FIXME: we shouldn't do this if the exponent is large...\n\n          ComplexMatrix atmp;\n          if (bint < 0)\n            {\n              bint = -bint;\n\n              octave_idx_type info;\n              double rcond = 0.0;\n              MatrixType mattype (a);\n\n              atmp = a.inverse (mattype, info, rcond, 1);\n\n              if (info == -1)\n                warning (\"inverse: matrix singular to machine precision, rcond = %g\", rcond);\n            }\n          else\n            atmp = a;\n\n          ComplexMatrix result (atmp);\n\n          bint--;\n\n          while (bint > 0)\n            {\n              if (bint & 1)\n                // Use atmp * result instead of result * atmp\n                // for ML compatibility (bug #52706).\n                result = atmp * result;\n\n              bint >>= 1;\n\n              if (bint > 0)\n                atmp = atmp * atmp;\n            }\n\n          retval = result;\n        }\n    }\n  else\n    {\n      EIG a_eig (a);\n\n      try\n        {\n          ComplexColumnVector lambda (a_eig.eigenvalues ());\n          ComplexMatrix Q (a_eig.right_eigenvectors ());\n\n          for (octave_idx_type i = 0; i < nr; i++)\n            lambda(i) = std::pow (lambda(i), b);\n\n          ComplexDiagMatrix D (lambda);\n\n          retval = ComplexMatrix (Q * D * Q.inverse ());\n        }\n      catch (const octave::execution_exception&)\n        {\n          err_failed_diagonalization ();\n        }\n    }\n\n  return retval;\n}\n\n// -*- 12 -*-\noctave_value\nxpow (const ComplexMatrix& a, const Complex& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  EIG a_eig (a);\n\n  try\n    {\n      ComplexColumnVector lambda (a_eig.eigenvalues ());\n      ComplexMatrix Q (a_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (lambda(i), b);\n\n      ComplexDiagMatrix D (lambda);\n\n      retval = ComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 12d -*-\noctave_value\nxpow (const ComplexDiagMatrix& a, const Complex& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return Matrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  ComplexDiagMatrix r (nr, nc);\n  for (octave_idx_type i = 0; i < nc; i++)\n    r.dgxelem (i) = std::pow (a.dgxelem (i), b);\n  retval = r;\n\n  return retval;\n}\n\n// mixed\noctave_value\nxpow (const ComplexDiagMatrix& a, double b)\n{\n  return xpow (a, static_cast<Complex> (b));\n}\n\noctave_value\nxpow (const DiagMatrix& a, const Complex& b)\n{\n  return xpow (ComplexDiagMatrix (a), b);\n}\n\n// Safer pow functions that work elementwise for matrices.\n//\n//       op2 \\ op1:   s   m   cs   cm\n//            +--   +---+---+----+----+\n//   scalar   |     | * | 3 |  * |  9 |\n//                  +---+---+----+----+\n//   matrix         | 1 | 4 |  7 | 10 |\n//                  +---+---+----+----+\n//   complex_scalar | * | 5 |  * | 11 |\n//                  +---+---+----+----+\n//   complex_matrix | 2 | 6 |  8 | 12 |\n//                  +---+---+----+----+\n//\n//   * -> not needed.\n\n// FIXME: these functions need to be fixed so that things like\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b\n//\n// and\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end\n//\n// produce identical results.  Also, it would be nice if -1^0.5\n// produced a pure imaginary result instead of a complex number with a\n// small real part.  But perhaps that's really a problem with the math\n// library...\n\n// -*- 1 -*-\noctave_value\nelem_xpow (double a, const Matrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  double d1, d2;\n\n  if (a < 0.0 && ! b.all_integers (d1, d2))\n    {\n      Complex acplx (a);\n      ComplexMatrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (acplx, b(i, j));\n          }\n\n      retval = result;\n    }\n  else\n    {\n      Matrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a, b(i, j));\n          }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 2 -*-\noctave_value\nelem_xpow (double a, const ComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  ComplexMatrix result (nr, nc);\n  Complex acplx (a);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (acplx, b(i, j));\n      }\n\n  return result;\n}\n\nstatic inline bool\nsame_sign (double a, double b)\n{\n  return (a >= 0 && b >= 0) || (a <= 0 && b <= 0);\n}\n\noctave_value\nelem_xpow (double a, const octave::range<double>& r)\n{\n  octave_value retval;\n\n  // Only optimize powers with ranges that are integer and monotonic in\n  // magnitude.\n  if (r.numel () > 1 && r.all_elements_are_ints ()\n      && same_sign (r.base (), r.limit ()))\n    {\n      octave_idx_type n = r.numel ();\n      Matrix result (1, n);\n      if (same_sign (r.base (), r.increment ()))\n        {\n          double base = std::pow (a, r.base ());\n          double inc = std::pow (a, r.increment ());\n          result(0) = base;\n          for (octave_idx_type i = 1; i < n; i++)\n            result(i) = (base *= inc);\n        }\n      else\n        {\n          double limit = std::pow (a, r.final_value ());\n          double inc = std::pow (a, -r.increment ());\n          result(n-1) = limit;\n          for (octave_idx_type i = n-2; i >= 0; i--)\n            result(i) = (limit *= inc);\n        }\n\n      retval = result;\n    }\n  else\n    {\n      Matrix tmp = r.array_value ();\n      retval = elem_xpow (a, tmp);\n    }\n\n  return retval;\n}\n\n// -*- 3 -*-\noctave_value\nelem_xpow (const Matrix& a, double b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (! xisint (b) && a.any_element_is_negative ())\n    {\n      ComplexMatrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n\n            Complex acplx (a(i, j));\n\n            result(i, j) = std::pow (acplx, b);\n          }\n\n      retval = result;\n    }\n  else\n    {\n      Matrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a(i, j), b);\n          }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 4 -*-\noctave_value\nelem_xpow (const Matrix& a, const Matrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  bool convert_to_complex = false;\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        double atmp = a(i, j);\n        double btmp = b(i, j);\n        if (atmp < 0.0 && ! xisint (btmp))\n          {\n            convert_to_complex = true;\n            goto done;\n          }\n      }\n\ndone:\n\n  if (convert_to_complex)\n    {\n      ComplexMatrix complex_result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            Complex acplx (a(i, j));\n            Complex bcplx (b(i, j));\n            complex_result(i, j) = std::pow (acplx, bcplx);\n          }\n\n      retval = complex_result;\n    }\n  else\n    {\n      Matrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a(i, j), b(i, j));\n          }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 5 -*-\noctave_value\nelem_xpow (const Matrix& a, const Complex& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (Complex (a(i, j)), b);\n      }\n\n  return result;\n}\n\n// -*- 6 -*-\noctave_value\nelem_xpow (const Matrix& a, const ComplexMatrix& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (Complex (a(i, j)), b(i, j));\n      }\n\n  return result;\n}\n\n// -*- 7 -*-\noctave_value\nelem_xpow (const Complex& a, const Matrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        double btmp = b(i, j);\n        if (xisint (btmp))\n          result(i, j) = std::pow (a, static_cast<int> (btmp));\n        else\n          result(i, j) = std::pow (a, btmp);\n      }\n\n  return result;\n}\n\n// -*- 8 -*-\noctave_value\nelem_xpow (const Complex& a, const ComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (a, b(i, j));\n      }\n\n  return result;\n}\n\noctave_value\nelem_xpow (const Complex& a, const octave::range<double>& r)\n{\n  octave_value retval;\n\n  // Only optimize powers with ranges that are integer and monotonic in\n  // magnitude.\n  if (r.numel () > 1 && r.all_elements_are_ints ()\n      && same_sign (r.base (), r.limit ()))\n    {\n      octave_idx_type n = r.numel ();\n      ComplexMatrix result (1, n);\n\n      if (same_sign (r.base (), r.increment ()))\n        {\n          Complex base = std::pow (a, r.base ());\n          Complex inc = std::pow (a, r.increment ());\n          result(0) = base;\n          for (octave_idx_type i = 1; i < n; i++)\n            result(i) = (base *= inc);\n        }\n      else\n        {\n          Complex limit = std::pow (a, r.final_value ());\n          Complex inc = std::pow (a, -r.increment ());\n          result(n-1) = limit;\n          for (octave_idx_type i = n-2; i >= 0; i--)\n            result(i) = (limit *= inc);\n        }\n\n      retval = result;\n    }\n  else\n    {\n      Matrix tmp = r.array_value ();\n      retval = elem_xpow (a, tmp);\n    }\n\n  return retval;\n}\n\n// -*- 9 -*-\noctave_value\nelem_xpow (const ComplexMatrix& a, double b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  ComplexMatrix result (nr, nc);\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a(i, j), bint);\n          }\n    }\n  else\n    {\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a(i, j), b);\n          }\n    }\n\n  return result;\n}\n\n// -*- 10 -*-\noctave_value\nelem_xpow (const ComplexMatrix& a, const Matrix& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        double btmp = b(i, j);\n        if (xisint (btmp))\n          result(i, j) = std::pow (a(i, j), static_cast<int> (btmp));\n        else\n          result(i, j) = std::pow (a(i, j), btmp);\n      }\n\n  return result;\n}\n\n// -*- 11 -*-\noctave_value\nelem_xpow (const ComplexMatrix& a, const Complex& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (a(i, j), b);\n      }\n\n  return result;\n}\n\n// -*- 12 -*-\noctave_value\nelem_xpow (const ComplexMatrix& a, const ComplexMatrix& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (a(i, j), b(i, j));\n      }\n\n  return result;\n}\n\n// Safer pow functions that work elementwise for N-D arrays.\n//\n//       op2 \\ op1:   s   nd  cs   cnd\n//            +--   +---+---+----+----+\n//   scalar   |     | * | 3 |  * |  9 |\n//                  +---+---+----+----+\n//   N_d            | 1 | 4 |  7 | 10 |\n//                  +---+---+----+----+\n//   complex_scalar | * | 5 |  * | 11 |\n//                  +---+---+----+----+\n//   complex_N_d    | 2 | 6 |  8 | 12 |\n//                  +---+---+----+----+\n//\n//   * -> not needed.\n\n// FIXME: these functions need to be fixed so that things like\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b\n//\n// and\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end\n//\n// produce identical results.  Also, it would be nice if -1^0.5\n// produced a pure imaginary result instead of a complex number with a\n// small real part.  But perhaps that's really a problem with the math\n// library...\n\n// -*- 1 -*-\noctave_value\nelem_xpow (double a, const NDArray& b)\n{\n  octave_value retval;\n\n  if (a < 0.0 && ! b.all_integers ())\n    {\n      Complex acplx (a);\n      ComplexNDArray result (b.dims ());\n      for (octave_idx_type i = 0; i < b.numel (); i++)\n        {\n          octave_quit ();\n          result(i) = std::pow (acplx, b(i));\n        }\n\n      retval = result;\n    }\n  else\n    {\n      NDArray result (b.dims ());\n      for (octave_idx_type i = 0; i < b.numel (); i++)\n        {\n          octave_quit ();\n          result(i) = std::pow (a, b(i));\n        }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 2 -*-\noctave_value\nelem_xpow (double a, const ComplexNDArray& b)\n{\n  ComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a, b(i));\n    }\n\n  return result;\n}\n\n// -*- 3 -*-\noctave_value\nelem_xpow (const NDArray& a, double b)\n{\n  octave_value retval;\n\n  if (xisint (b))\n    {\n      NDArray result (a.dims ());\n\n      int bint = static_cast<int> (b);\n      if (bint == 2)\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            result.xelem (i) = a(i) * a(i);\n        }\n      else if (bint == 3)\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            result.xelem (i) = a(i) * a(i) * a(i);\n        }\n      else if (bint == -1)\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            result.xelem (i) = 1.0 / a(i);\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              octave_quit ();\n              result.xelem (i) = std::pow (a(i), bint);\n            }\n        }\n\n      retval = result;\n    }\n  else\n    {\n      if (a.any_element_is_negative ())\n        {\n          ComplexNDArray result (a.dims ());\n\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              octave_quit ();\n              Complex acplx (a(i));\n              result(i) = std::pow (acplx, b);\n            }\n\n          retval = result;\n        }\n      else\n        {\n          NDArray result (a.dims ());\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              octave_quit ();\n              result(i) = std::pow (a(i), b);\n            }\n\n          retval = result;\n        }\n    }\n\n  return retval;\n}\n\n// -*- 4 -*-\noctave_value\nelem_xpow (const NDArray& a, const NDArray& b)\n{\n  octave_value retval;\n\n  const dim_vector& a_dims = a.dims ();\n  const dim_vector& b_dims = b.dims ();\n\n  if (a_dims != b_dims)\n    {\n      if (! is_valid_bsxfun (a_dims, b_dims))\n        octave::err_nonconformant (\"operator .^\", a_dims, b_dims);\n\n      // Potentially complex results\n      NDArray xa = octave_value_extract<NDArray> (a);\n      NDArray xb = octave_value_extract<NDArray> (b);\n      if (! xb.all_integers () && xa.any_element_is_negative ())\n        return octave_value (bsxfun_pow (ComplexNDArray (xa), xb));\n      else\n        return octave_value (bsxfun_pow (xa, xb));\n    }\n\n  int len = a.numel ();\n\n  bool convert_to_complex = false;\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      octave_quit ();\n      double atmp = a(i);\n      double btmp = b(i);\n      if (atmp < 0.0 && ! xisint (btmp))\n        {\n          convert_to_complex = true;\n          goto done;\n        }\n    }\n\ndone:\n\n  if (convert_to_complex)\n    {\n      ComplexNDArray complex_result (a_dims);\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          octave_quit ();\n          Complex acplx (a(i));\n          complex_result(i) = std::pow (acplx, b(i));\n        }\n\n      retval = complex_result;\n    }\n  else\n    {\n      NDArray result (a_dims);\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          octave_quit ();\n          result(i) = std::pow (a(i), b(i));\n        }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 5 -*-\noctave_value\nelem_xpow (const NDArray& a, const Complex& b)\n{\n  ComplexNDArray result (a.dims ());\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a(i), b);\n    }\n\n  return result;\n}\n\n// -*- 6 -*-\noctave_value\nelem_xpow (const NDArray& a, const ComplexNDArray& b)\n{\n  const dim_vector& a_dims = a.dims ();\n  const dim_vector& b_dims = b.dims ();\n\n  if (a_dims != b_dims)\n    {\n      if (! is_valid_bsxfun (a_dims, b_dims))\n        octave::err_nonconformant (\"operator .^\", a_dims, b_dims);\n\n      return bsxfun_pow (a, b);\n    }\n\n  ComplexNDArray result (a_dims);\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a(i), b(i));\n    }\n\n  return result;\n}\n\n// -*- 7 -*-\noctave_value\nelem_xpow (const Complex& a, const NDArray& b)\n{\n  ComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      double btmp = b(i);\n      if (xisint (btmp))\n        result(i) = std::pow (a, static_cast<int> (btmp));\n      else\n        result(i) = std::pow (a, btmp);\n    }\n\n  return result;\n}\n\n// -*- 8 -*-\noctave_value\nelem_xpow (const Complex& a, const ComplexNDArray& b)\n{\n  ComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a, b(i));\n    }\n\n  return result;\n}\n\n// -*- 9 -*-\noctave_value\nelem_xpow (const ComplexNDArray& a, double b)\n{\n  ComplexNDArray result (a.dims ());\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      if (bint == -1)\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            result.xelem (i) = 1.0 / a(i);\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              octave_quit ();\n              result(i) = std::pow (a(i), bint);\n            }\n        }\n    }\n  else\n    {\n      for (octave_idx_type i = 0; i < a.numel (); i++)\n        {\n          octave_quit ();\n          result(i) = std::pow (a(i), b);\n        }\n    }\n\n  return result;\n}\n\n// -*- 10 -*-\noctave_value\nelem_xpow (const ComplexNDArray& a, const NDArray& b)\n{\n  const dim_vector& a_dims = a.dims ();\n  const dim_vector& b_dims = b.dims ();\n\n  if (a_dims != b_dims)\n    {\n      if (! is_valid_bsxfun (a_dims, b_dims))\n        octave::err_nonconformant (\"operator .^\", a_dims, b_dims);\n\n      return bsxfun_pow (a, b);\n    }\n\n  ComplexNDArray result (a_dims);\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      double btmp = b(i);\n      if (xisint (btmp))\n        result(i) = std::pow (a(i), static_cast<int> (btmp));\n      else\n        result(i) = std::pow (a(i), btmp);\n    }\n\n  return result;\n}\n\n// -*- 11 -*-\noctave_value\nelem_xpow (const ComplexNDArray& a, const Complex& b)\n{\n  ComplexNDArray result (a.dims ());\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a(i), b);\n    }\n\n  return result;\n}\n\n// -*- 12 -*-\noctave_value\nelem_xpow (const ComplexNDArray& a, const ComplexNDArray& b)\n{\n  const dim_vector& a_dims = a.dims ();\n  const dim_vector& b_dims = b.dims ();\n\n  if (a_dims != b_dims)\n    {\n      if (! is_valid_bsxfun (a_dims, b_dims))\n        octave::err_nonconformant (\"operator .^\", a_dims, b_dims);\n\n      return bsxfun_pow (a, b);\n    }\n\n  ComplexNDArray result (a_dims);\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a(i), b(i));\n    }\n\n  return result;\n}\n\n// Safer pow functions.\n//\n//       op2 \\ op1:   s   m   cs   cm\n//            +--   +---+---+----+----+\n//   scalar   |     | 1 | 5 |  7 | 11 |\n//                  +---+---+----+----+\n//   matrix         | 2 | * |  8 |  * |\n//                  +---+---+----+----+\n//   complex_scalar | 3 | 6 |  9 | 12 |\n//                  +---+---+----+----+\n//   complex_matrix | 4 | * | 10 |  * |\n//                  +---+---+----+----+\n\n// -*- 1 -*-\noctave_value\nxpow (float a, float b)\n{\n  float retval;\n\n  if (a < 0.0 && ! xisint (b))\n    {\n      FloatComplex acplx (a);\n\n      return std::pow (acplx, b);\n    }\n  else\n    retval = std::pow (a, b);\n\n  return retval;\n}\n\n// -*- 2 -*-\noctave_value\nxpow (float a, const FloatMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  FloatEIG b_eig (b);\n\n  try\n    {\n      FloatComplexColumnVector lambda (b_eig.eigenvalues ());\n      FloatComplexMatrix Q (b_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (a, lambda(i));\n\n      FloatComplexDiagMatrix D (lambda);\n\n      FloatComplexMatrix C = Q * D * Q.inverse ();\n\n      if (a > 0)\n        retval = real (C);\n      else\n        retval = C;\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 3 -*-\noctave_value\nxpow (float a, const FloatComplex& b)\n{\n  FloatComplex result = std::pow (a, b);\n  return result;\n}\n\n// -*- 4 -*-\noctave_value\nxpow (float a, const FloatComplexMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  FloatEIG b_eig (b);\n\n  try\n    {\n      FloatComplexColumnVector lambda (b_eig.eigenvalues ());\n      FloatComplexMatrix Q (b_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (a, lambda(i));\n\n      FloatComplexDiagMatrix D (lambda);\n\n      retval = FloatComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 5 -*-\noctave_value\nxpow (const FloatMatrix& a, float b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      if (bint == 0)\n        {\n          retval = FloatDiagMatrix (nr, nr, 1.0f);\n        }\n      else\n        {\n          // Too much copying?\n          // FIXME: we shouldn't do this if the exponent is large...\n\n          FloatMatrix atmp;\n          if (bint < 0)\n            {\n              bint = -bint;\n\n              octave_idx_type info;\n              float rcond = 0.0;\n              MatrixType mattype (a);\n\n              atmp = a.inverse (mattype, info, rcond, 1);\n\n              if (info == -1)\n                warning (\"inverse: matrix singular to machine precision, rcond = %g\", rcond);\n            }\n          else\n            atmp = a;\n\n          FloatMatrix result (atmp);\n\n          bint--;\n\n          while (bint > 0)\n            {\n              if (bint & 1)\n                // Use atmp * result instead of result * atmp\n                // for ML compatibility (bug #52706).\n                result = atmp * result;\n\n              bint >>= 1;\n\n              if (bint > 0)\n                atmp = atmp * atmp;\n            }\n\n          retval = result;\n        }\n    }\n  else\n    {\n      FloatEIG a_eig (a);\n\n      try\n        {\n          FloatComplexColumnVector lambda (a_eig.eigenvalues ());\n          FloatComplexMatrix Q (a_eig.right_eigenvectors ());\n\n          for (octave_idx_type i = 0; i < nr; i++)\n            lambda(i) = std::pow (lambda(i), b);\n\n          FloatComplexDiagMatrix D (lambda);\n\n          retval = FloatComplexMatrix (Q * D * Q.inverse ());\n        }\n      catch (const octave::execution_exception&)\n        {\n          err_failed_diagonalization ();\n        }\n    }\n\n  return retval;\n}\n\n// -*- 5d -*-\noctave_value\nxpow (const FloatDiagMatrix& a, float b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      FloatDiagMatrix r (nr, nc);\n      for (octave_idx_type i = 0; i < nc; i++)\n        r.dgxelem (i) = std::pow (a.dgxelem (i), bint);\n      retval = r;\n    }\n  else\n    {\n      FloatComplexDiagMatrix r (nr, nc);\n      for (octave_idx_type i = 0; i < nc; i++)\n        r.dgxelem (i) = std::pow (static_cast<FloatComplex> (a.dgxelem (i)), b);\n      retval = r;\n    }\n\n  return retval;\n}\n\n// -*- 6 -*-\noctave_value\nxpow (const FloatMatrix& a, const FloatComplex& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  FloatEIG a_eig (a);\n\n  try\n    {\n      FloatComplexColumnVector lambda (a_eig.eigenvalues ());\n      FloatComplexMatrix Q (a_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (lambda(i), b);\n\n      FloatComplexDiagMatrix D (lambda);\n\n      retval = FloatComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 7 -*-\noctave_value\nxpow (const FloatComplex& a, float b)\n{\n  FloatComplex result;\n\n  if (xisint (b))\n    result = std::pow (a, static_cast<int> (b));\n  else\n    result = std::pow (a, b);\n\n  return result;\n}\n\n// -*- 8 -*-\noctave_value\nxpow (const FloatComplex& a, const FloatMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  FloatEIG b_eig (b);\n\n  try\n    {\n      FloatComplexColumnVector lambda (b_eig.eigenvalues ());\n      FloatComplexMatrix Q (b_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (a, lambda(i));\n\n      FloatComplexDiagMatrix D (lambda);\n\n      retval = FloatComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 9 -*-\noctave_value\nxpow (const FloatComplex& a, const FloatComplex& b)\n{\n  FloatComplex result;\n  result = std::pow (a, b);\n  return result;\n}\n\n// -*- 10 -*-\noctave_value\nxpow (const FloatComplex& a, const FloatComplexMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  FloatEIG b_eig (b);\n\n  try\n    {\n      FloatComplexColumnVector lambda (b_eig.eigenvalues ());\n      FloatComplexMatrix Q (b_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (a, lambda(i));\n\n      FloatComplexDiagMatrix D (lambda);\n\n      retval = FloatComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 11 -*-\noctave_value\nxpow (const FloatComplexMatrix& a, float b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      if (bint == 0)\n        {\n          retval = FloatDiagMatrix (nr, nr, 1.0);\n        }\n      else\n        {\n          // Too much copying?\n          // FIXME: we shouldn't do this if the exponent is large...\n\n          FloatComplexMatrix atmp;\n          if (bint < 0)\n            {\n              bint = -bint;\n\n              octave_idx_type info;\n              float rcond = 0.0;\n              MatrixType mattype (a);\n\n              atmp = a.inverse (mattype, info, rcond, 1);\n\n              if (info == -1)\n                warning (\"inverse: matrix singular to machine precision, rcond = %g\", rcond);\n            }\n          else\n            atmp = a;\n\n          FloatComplexMatrix result (atmp);\n\n          bint--;\n\n          while (bint > 0)\n            {\n              if (bint & 1)\n                // Use atmp * result instead of result * atmp\n                // for ML compatibility (bug #52706).\n                result = atmp * result;\n\n              bint >>= 1;\n\n              if (bint > 0)\n                atmp = atmp * atmp;\n            }\n\n          retval = result;\n        }\n    }\n  else\n    {\n      FloatEIG a_eig (a);\n\n      try\n        {\n          FloatComplexColumnVector lambda (a_eig.eigenvalues ());\n          FloatComplexMatrix Q (a_eig.right_eigenvectors ());\n\n          for (octave_idx_type i = 0; i < nr; i++)\n            lambda(i) = std::pow (lambda(i), b);\n\n          FloatComplexDiagMatrix D (lambda);\n\n          retval = FloatComplexMatrix (Q * D * Q.inverse ());\n        }\n      catch (const octave::execution_exception&)\n        {\n          err_failed_diagonalization ();\n        }\n    }\n\n  return retval;\n}\n\n// -*- 12 -*-\noctave_value\nxpow (const FloatComplexMatrix& a, const FloatComplex& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  FloatEIG a_eig (a);\n\n  try\n    {\n      FloatComplexColumnVector lambda (a_eig.eigenvalues ());\n      FloatComplexMatrix Q (a_eig.right_eigenvectors ());\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        lambda(i) = std::pow (lambda(i), b);\n\n      FloatComplexDiagMatrix D (lambda);\n\n      retval = FloatComplexMatrix (Q * D * Q.inverse ());\n    }\n  catch (const octave::execution_exception&)\n    {\n      err_failed_diagonalization ();\n    }\n\n  return retval;\n}\n\n// -*- 12d -*-\noctave_value\nxpow (const FloatComplexDiagMatrix& a, const FloatComplex& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr == 0 || nc == 0)\n    return FloatMatrix ();\n\n  if (nr != nc)\n    err_nonsquare_matrix ();\n\n  FloatComplexDiagMatrix r (nr, nc);\n  for (octave_idx_type i = 0; i < nc; i++)\n    r.dgxelem (i) = std::pow (a.dgxelem (i), b);\n  retval = r;\n\n  return retval;\n}\n\n// mixed\noctave_value\nxpow (const FloatComplexDiagMatrix& a, float b)\n{\n  return xpow (a, static_cast<FloatComplex> (b));\n}\n\noctave_value\nxpow (const FloatDiagMatrix& a, const FloatComplex& b)\n{\n  return xpow (FloatComplexDiagMatrix (a), b);\n}\n\n// Safer pow functions that work elementwise for matrices.\n//\n//       op2 \\ op1:   s   m   cs   cm\n//            +--   +---+---+----+----+\n//   scalar   |     | * | 3 |  * |  9 |\n//                  +---+---+----+----+\n//   matrix         | 1 | 4 |  7 | 10 |\n//                  +---+---+----+----+\n//   complex_scalar | * | 5 |  * | 11 |\n//                  +---+---+----+----+\n//   complex_matrix | 2 | 6 |  8 | 12 |\n//                  +---+---+----+----+\n//\n//   * -> not needed.\n\n// FIXME: these functions need to be fixed so that things like\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b\n//\n// and\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end\n//\n// produce identical results.  Also, it would be nice if -1^0.5\n// produced a pure imaginary result instead of a complex number with a\n// small real part.  But perhaps that's really a problem with the math\n// library...\n\n// -*- 1 -*-\noctave_value\nelem_xpow (float a, const FloatMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  float d1, d2;\n\n  if (a < 0.0 && ! b.all_integers (d1, d2))\n    {\n      FloatComplex acplx (a);\n      FloatComplexMatrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (acplx, b(i, j));\n          }\n\n      retval = result;\n    }\n  else\n    {\n      FloatMatrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a, b(i, j));\n          }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 2 -*-\noctave_value\nelem_xpow (float a, const FloatComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  FloatComplexMatrix result (nr, nc);\n  FloatComplex acplx (a);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (acplx, b(i, j));\n      }\n\n  return result;\n}\n\n// -*- 3 -*-\noctave_value\nelem_xpow (const FloatMatrix& a, float b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (! xisint (b) && a.any_element_is_negative ())\n    {\n      FloatComplexMatrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n\n            FloatComplex acplx (a(i, j));\n\n            result(i, j) = std::pow (acplx, b);\n          }\n\n      retval = result;\n    }\n  else\n    {\n      FloatMatrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a(i, j), b);\n          }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 4 -*-\noctave_value\nelem_xpow (const FloatMatrix& a, const FloatMatrix& b)\n{\n  octave_value retval;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  bool convert_to_complex = false;\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        float atmp = a(i, j);\n        float btmp = b(i, j);\n        if (atmp < 0.0 && ! xisint (btmp))\n          {\n            convert_to_complex = true;\n            goto done;\n          }\n      }\n\ndone:\n\n  if (convert_to_complex)\n    {\n      FloatComplexMatrix complex_result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            FloatComplex acplx (a(i, j));\n            FloatComplex bcplx (b(i, j));\n            complex_result(i, j) = std::pow (acplx, bcplx);\n          }\n\n      retval = complex_result;\n    }\n  else\n    {\n      FloatMatrix result (nr, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a(i, j), b(i, j));\n          }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 5 -*-\noctave_value\nelem_xpow (const FloatMatrix& a, const FloatComplex& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (FloatComplex (a(i, j)), b);\n      }\n\n  return result;\n}\n\n// -*- 6 -*-\noctave_value\nelem_xpow (const FloatMatrix& a, const FloatComplexMatrix& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (FloatComplex (a(i, j)), b(i, j));\n      }\n\n  return result;\n}\n\n// -*- 7 -*-\noctave_value\nelem_xpow (const FloatComplex& a, const FloatMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        float btmp = b(i, j);\n        if (xisint (btmp))\n          result(i, j) = std::pow (a, static_cast<int> (btmp));\n        else\n          result(i, j) = std::pow (a, btmp);\n      }\n\n  return result;\n}\n\n// -*- 8 -*-\noctave_value\nelem_xpow (const FloatComplex& a, const FloatComplexMatrix& b)\n{\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (a, b(i, j));\n      }\n\n  return result;\n}\n\n// -*- 9 -*-\noctave_value\nelem_xpow (const FloatComplexMatrix& a, float b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  FloatComplexMatrix result (nr, nc);\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a(i, j), bint);\n          }\n    }\n  else\n    {\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          {\n            octave_quit ();\n            result(i, j) = std::pow (a(i, j), b);\n          }\n    }\n\n  return result;\n}\n\n// -*- 10 -*-\noctave_value\nelem_xpow (const FloatComplexMatrix& a, const FloatMatrix& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        float btmp = b(i, j);\n        if (xisint (btmp))\n          result(i, j) = std::pow (a(i, j), static_cast<int> (btmp));\n        else\n          result(i, j) = std::pow (a(i, j), btmp);\n      }\n\n  return result;\n}\n\n// -*- 11 -*-\noctave_value\nelem_xpow (const FloatComplexMatrix& a, const FloatComplex& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (a(i, j), b);\n      }\n\n  return result;\n}\n\n// -*- 12 -*-\noctave_value\nelem_xpow (const FloatComplexMatrix& a, const FloatComplexMatrix& b)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (nr != b_nr || nc != b_nc)\n    octave::err_nonconformant (\"operator .^\", nr, nc, b_nr, b_nc);\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = std::pow (a(i, j), b(i, j));\n      }\n\n  return result;\n}\n\n// Safer pow functions that work elementwise for N-D arrays.\n//\n//       op2 \\ op1:   s   nd  cs   cnd\n//            +--   +---+---+----+----+\n//   scalar   |     | * | 3 |  * |  9 |\n//                  +---+---+----+----+\n//   N_d            | 1 | 4 |  7 | 10 |\n//                  +---+---+----+----+\n//   complex_scalar | * | 5 |  * | 11 |\n//                  +---+---+----+----+\n//   complex_N_d    | 2 | 6 |  8 | 12 |\n//                  +---+---+----+----+\n//\n//   * -> not needed.\n\n// FIXME: these functions need to be fixed so that things like\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b\n//\n// and\n//\n//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end\n//\n// produce identical results.  Also, it would be nice if -1^0.5\n// produced a pure imaginary result instead of a complex number with a\n// small real part.  But perhaps that's really a problem with the math\n// library...\n\n// -*- 1 -*-\noctave_value\nelem_xpow (float a, const FloatNDArray& b)\n{\n  octave_value retval;\n\n  if (a < 0.0 && ! b.all_integers ())\n    {\n      FloatComplex acplx (a);\n      FloatComplexNDArray result (b.dims ());\n      for (octave_idx_type i = 0; i < b.numel (); i++)\n        {\n          octave_quit ();\n          result(i) = std::pow (acplx, b(i));\n        }\n\n      retval = result;\n    }\n  else\n    {\n      FloatNDArray result (b.dims ());\n      for (octave_idx_type i = 0; i < b.numel (); i++)\n        {\n          octave_quit ();\n          result(i) = std::pow (a, b(i));\n        }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 2 -*-\noctave_value\nelem_xpow (float a, const FloatComplexNDArray& b)\n{\n  FloatComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a, b(i));\n    }\n\n  return result;\n}\n\n// -*- 3 -*-\noctave_value\nelem_xpow (const FloatNDArray& a, float b)\n{\n  octave_value retval;\n\n  if (xisint (b))\n    {\n      FloatNDArray result (a.dims ());\n\n      int bint = static_cast<int> (b);\n      if (bint == 2)\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            result.xelem (i) = a(i) * a(i);\n        }\n      else if (bint == 3)\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            result.xelem (i) = a(i) * a(i) * a(i);\n        }\n      else if (bint == -1)\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            result.xelem (i) = 1.0f / a(i);\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              octave_quit ();\n              result.xelem (i) = std::pow (a(i), bint);\n            }\n        }\n\n      retval = result;\n    }\n  else\n    {\n      if (a.any_element_is_negative ())\n        {\n          FloatComplexNDArray result (a.dims ());\n\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              octave_quit ();\n\n              FloatComplex acplx (a(i));\n\n              result(i) = std::pow (acplx, b);\n            }\n\n          retval = result;\n        }\n      else\n        {\n          FloatNDArray result (a.dims ());\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              octave_quit ();\n              result(i) = std::pow (a(i), b);\n            }\n\n          retval = result;\n        }\n    }\n\n  return retval;\n}\n\n// -*- 4 -*-\noctave_value\nelem_xpow (const FloatNDArray& a, const FloatNDArray& b)\n{\n  octave_value retval;\n\n  const dim_vector& a_dims = a.dims ();\n  const dim_vector& b_dims = b.dims ();\n\n  if (a_dims != b_dims)\n    {\n      if (! is_valid_bsxfun (a_dims, b_dims))\n        octave::err_nonconformant (\"operator .^\", a_dims, b_dims);\n\n      // Potentially complex results\n      FloatNDArray xa = octave_value_extract<FloatNDArray> (a);\n      FloatNDArray xb = octave_value_extract<FloatNDArray> (b);\n      if (! xb.all_integers () && xa.any_element_is_negative ())\n        return octave_value (bsxfun_pow (FloatComplexNDArray (xa), xb));\n      else\n        return octave_value (bsxfun_pow (xa, xb));\n    }\n\n  int len = a.numel ();\n\n  bool convert_to_complex = false;\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      octave_quit ();\n      float atmp = a(i);\n      float btmp = b(i);\n      if (atmp < 0.0 && ! xisint (btmp))\n        {\n          convert_to_complex = true;\n          goto done;\n        }\n    }\n\ndone:\n\n  if (convert_to_complex)\n    {\n      FloatComplexNDArray complex_result (a_dims);\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          octave_quit ();\n          FloatComplex acplx (a(i));\n          complex_result(i) = std::pow (acplx, b(i));\n        }\n\n      retval = complex_result;\n    }\n  else\n    {\n      FloatNDArray result (a_dims);\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          octave_quit ();\n          result(i) = std::pow (a(i), b(i));\n        }\n\n      retval = result;\n    }\n\n  return retval;\n}\n\n// -*- 5 -*-\noctave_value\nelem_xpow (const FloatNDArray& a, const FloatComplex& b)\n{\n  FloatComplexNDArray result (a.dims ());\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a(i), b);\n    }\n\n  return result;\n}\n\n// -*- 6 -*-\noctave_value\nelem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b)\n{\n  const dim_vector& a_dims = a.dims ();\n  const dim_vector& b_dims = b.dims ();\n\n  if (a_dims != b_dims)\n    {\n      if (! is_valid_bsxfun (a_dims, b_dims))\n        octave::err_nonconformant (\"operator .^\", a_dims, b_dims);\n\n      return bsxfun_pow (a, b);\n    }\n\n  FloatComplexNDArray result (a_dims);\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a(i), b(i));\n    }\n\n  return result;\n}\n\n// -*- 7 -*-\noctave_value\nelem_xpow (const FloatComplex& a, const FloatNDArray& b)\n{\n  FloatComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      float btmp = b(i);\n      if (xisint (btmp))\n        result(i) = std::pow (a, static_cast<int> (btmp));\n      else\n        result(i) = std::pow (a, btmp);\n    }\n\n  return result;\n}\n\n// -*- 8 -*-\noctave_value\nelem_xpow (const FloatComplex& a, const FloatComplexNDArray& b)\n{\n  FloatComplexNDArray result (b.dims ());\n\n  for (octave_idx_type i = 0; i < b.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a, b(i));\n    }\n\n  return result;\n}\n\n// -*- 9 -*-\noctave_value\nelem_xpow (const FloatComplexNDArray& a, float b)\n{\n  FloatComplexNDArray result (a.dims ());\n\n  if (xisint (b))\n    {\n      int bint = static_cast<int> (b);\n      if (bint == -1)\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            result.xelem (i) = 1.0f / a(i);\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              octave_quit ();\n              result(i) = std::pow (a(i), bint);\n            }\n        }\n    }\n  else\n    {\n      for (octave_idx_type i = 0; i < a.numel (); i++)\n        {\n          octave_quit ();\n          result(i) = std::pow (a(i), b);\n        }\n    }\n\n  return result;\n}\n\n// -*- 10 -*-\noctave_value\nelem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b)\n{\n  const dim_vector& a_dims = a.dims ();\n  const dim_vector& b_dims = b.dims ();\n\n  if (a_dims != b_dims)\n    {\n      if (! is_valid_bsxfun (a_dims, b_dims))\n        octave::err_nonconformant (\"operator .^\", a_dims, b_dims);\n\n      return bsxfun_pow (a, b);\n    }\n\n  FloatComplexNDArray result (a_dims);\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      float btmp = b(i);\n      if (xisint (btmp))\n        result(i) = std::pow (a(i), static_cast<int> (btmp));\n      else\n        result(i) = std::pow (a(i), btmp);\n    }\n\n  return result;\n}\n\n// -*- 11 -*-\noctave_value\nelem_xpow (const FloatComplexNDArray& a, const FloatComplex& b)\n{\n  FloatComplexNDArray result (a.dims ());\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a(i), b);\n    }\n\n  return result;\n}\n\n// -*- 12 -*-\noctave_value\nelem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b)\n{\n  const dim_vector& a_dims = a.dims ();\n  const dim_vector& b_dims = b.dims ();\n\n  if (a_dims != b_dims)\n    {\n      if (! is_valid_bsxfun (a_dims, b_dims))\n        octave::err_nonconformant (\"operator .^\", a_dims, b_dims);\n\n      return bsxfun_pow (a, b);\n    }\n\n  FloatComplexNDArray result (a_dims);\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    {\n      octave_quit ();\n      result(i) = std::pow (a(i), b(i));\n    }\n\n  return result;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/corefcn/xpow.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_xpow_h)\n#define octave_xpow_h 1\n\n#include \"octave-config.h\"\n\n#include \"oct-cmplx.h\"\n\nclass Matrix;\nclass ComplexMatrix;\nclass FloatMatrix;\nclass FloatComplexMatrix;\nclass DiagMatrix;\nclass ComplexDiagMatrix;\nclass FloatDiagMatrix;\nclass FloatComplexDiagMatrix;\nclass PermMatrix;\nclass NDArray;\nclass FloatNDArray;\nclass ComplexNDArray;\nclass FloatComplexNDArray;\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API octave_value xpow (double a, double b);\nextern OCTINTERP_API octave_value xpow (double a, const Matrix& b);\nextern OCTINTERP_API octave_value xpow (double a, const Complex& b);\nextern OCTINTERP_API octave_value xpow (double a, const ComplexMatrix& b);\n\nextern OCTINTERP_API octave_value xpow (const Matrix& a, double b);\nextern OCTINTERP_API octave_value xpow (const Matrix& a, const Complex& b);\n\nextern OCTINTERP_API octave_value xpow (const DiagMatrix& a, double b);\nextern OCTINTERP_API octave_value xpow (const DiagMatrix& a, const Complex& b);\n\nextern OCTINTERP_API octave_value xpow (const PermMatrix& a, double b);\n\nextern OCTINTERP_API octave_value xpow (const Complex& a, double b);\nextern OCTINTERP_API octave_value xpow (const Complex& a, const Matrix& b);\nextern OCTINTERP_API octave_value xpow (const Complex& a, const Complex& b);\nextern OCTINTERP_API octave_value xpow (const Complex& a,\n                                        const ComplexMatrix& b);\n\nextern OCTINTERP_API octave_value xpow (const ComplexMatrix& a, double b);\nextern OCTINTERP_API octave_value xpow (const ComplexMatrix& a,\n                                        const Complex& b);\n\nextern OCTINTERP_API octave_value xpow (const ComplexDiagMatrix& a, double b);\nextern OCTINTERP_API octave_value xpow (const ComplexDiagMatrix& a,\n                                        const Complex& b);\n\nextern OCTINTERP_API octave_value elem_xpow (double a, const Matrix& b);\nextern OCTINTERP_API octave_value elem_xpow (double a, const ComplexMatrix& b);\nextern OCTINTERP_API octave_value elem_xpow (double a,\n                                             const octave::range<double>& r);\n\nextern OCTINTERP_API octave_value elem_xpow (const Matrix& a, double b);\nextern OCTINTERP_API octave_value elem_xpow (const Matrix& a, const Matrix& b);\nextern OCTINTERP_API octave_value elem_xpow (const Matrix& a, const Complex& b);\nextern OCTINTERP_API octave_value elem_xpow (const Matrix& a,\n                                             const ComplexMatrix& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const Complex& a, const Matrix& b);\nextern OCTINTERP_API octave_value elem_xpow (const Complex& a,\n                                             const ComplexMatrix& b);\nextern OCTINTERP_API octave_value elem_xpow (const Complex& a,\n                                             const octave::range<double>& r);\n\nextern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, double b);\nextern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a,\n                                             const Matrix& b);\nextern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a,\n                                             const Complex& b);\nextern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a,\n                                             const ComplexMatrix& b);\n\nextern OCTINTERP_API octave_value elem_xpow (double a, const NDArray& b);\nextern OCTINTERP_API octave_value elem_xpow (double a, const ComplexNDArray& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const NDArray& a, double b);\nextern OCTINTERP_API octave_value elem_xpow (const NDArray& a,\n                                             const NDArray& b);\nextern OCTINTERP_API octave_value elem_xpow (const NDArray& a,\n                                             const Complex& b);\nextern OCTINTERP_API octave_value elem_xpow (const NDArray& a,\n                                             const ComplexNDArray& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const Complex& a,\n                                             const NDArray& b);\nextern OCTINTERP_API octave_value elem_xpow (const Complex& a,\n                                             const ComplexNDArray& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a,\n                                             double b);\nextern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a,\n                                             const NDArray& b);\nextern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a,\n                                             const Complex& b);\nextern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a,\n                                             const ComplexNDArray& b);\n\nextern OCTINTERP_API octave_value xpow (float a, float b);\nextern OCTINTERP_API octave_value xpow (float a, const FloatMatrix& b);\nextern OCTINTERP_API octave_value xpow (float a, const FloatComplex& b);\nextern OCTINTERP_API octave_value xpow (float a, const FloatComplexMatrix& b);\n\nextern OCTINTERP_API octave_value xpow (const FloatMatrix& a, float b);\nextern OCTINTERP_API octave_value xpow (const FloatMatrix& a,\n                                        const FloatComplex& b);\n\nextern OCTINTERP_API octave_value xpow (const FloatDiagMatrix& a, float b);\nextern OCTINTERP_API octave_value xpow (const FloatDiagMatrix& a,\n                                        const FloatComplex& b);\n\nextern OCTINTERP_API octave_value xpow (const FloatComplex& a, float b);\nextern OCTINTERP_API octave_value xpow (const FloatComplex& a,\n                                        const FloatMatrix& b);\nextern OCTINTERP_API octave_value xpow (const FloatComplex& a,\n                                        const FloatComplex& b);\nextern OCTINTERP_API octave_value xpow (const FloatComplex& a,\n                                        const FloatComplexMatrix& b);\n\nextern OCTINTERP_API octave_value xpow (const FloatComplexMatrix& a, float b);\nextern OCTINTERP_API octave_value xpow (const FloatComplexMatrix& a,\n                                        const FloatComplex& b);\n\nextern OCTINTERP_API octave_value xpow (const FloatComplexDiagMatrix& a,\n                                        float b);\nextern OCTINTERP_API octave_value xpow (const FloatComplexDiagMatrix& a,\n                                        const FloatComplex& b);\n\nextern OCTINTERP_API octave_value elem_xpow (float a, const FloatMatrix& b);\nextern OCTINTERP_API octave_value elem_xpow (float a,\n                                             const FloatComplexMatrix& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a, float b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a,\n                                             const FloatMatrix& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a,\n                                             const FloatComplex& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a,\n                                             const FloatComplexMatrix& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a,\n                                             const FloatMatrix& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a,\n                                             const FloatComplexMatrix& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a,\n                                             float b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a,\n                                             const FloatMatrix& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a,\n                                             const FloatComplex& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a,\n                                             const FloatComplexMatrix& b);\n\nextern OCTINTERP_API octave_value elem_xpow (float a, const FloatNDArray& b);\nextern OCTINTERP_API octave_value elem_xpow (float a,\n                                             const FloatComplexNDArray& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a, float b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a,\n                                             const FloatNDArray& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a,\n                                             const FloatComplex& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a,\n                                             const FloatComplexNDArray& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a,\n                                             const FloatNDArray& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a,\n                                             const FloatComplexNDArray& b);\n\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a,\n                                             float b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a,\n                                             const FloatNDArray& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a,\n                                             const FloatComplex& b);\nextern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a,\n                                             const FloatComplexNDArray& b);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/dldfcn/__delaunayn__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n  16. July 2000 - Kai Habel: first release\n\n  25. September 2002 - Changes by Rafael Laboissiere <rafael@laboissiere.net>\n\n  * Added Qbb option to normalize the input and avoid crashes in Octave.\n  * delaunayn accepts now a second (optional) argument that must be a string\n  containing extra options to the qhull command.\n  * Fixed doc string.  The dimension of the result matrix is [m, dim+1], and\n  not [n, dim-1].\n\n  6. June 2006: Changes by Alexander Barth <abarth@marine.usf.edu>\n\n  * triangulate non-simplicial facets\n  * allow options to be specified as cell array of strings\n  * change the default options (for compatibility with matlab)\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdio>\n\n#include <limits>\n#include <string>\n\n#include \"Array.h\"\n#include \"dMatrix.h\"\n#include \"dRowVector.h\"\n#include \"oct-locbuf.h\"\n#include \"unwind-prot.h\"\n\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n\n#if defined (HAVE_QHULL)\n#  include \"oct-qhull.h\"\n#  if defined (NEED_QHULL_R_VERSION)\nchar qh_version[] = \"__delaunayn__.oct 2007-08-21\";\n#  endif\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_QHULL)\n\nstatic void\nfree_qhull_memory (qhT *qh)\n{\n  qh_freeqhull (qh, ! qh_ALL);\n\n  int curlong, totlong;\n  qh_memfreeshort (qh, &curlong, &totlong);\n\n  if (curlong || totlong)\n    warning (\"__delaunayn__: did not free %d bytes of long memory (%d pieces)\",\n             totlong, curlong);\n}\n\nstatic bool\noctave_qhull_dims_ok (octave_idx_type dim, octave_idx_type n, const char *who)\n{\n  if (sizeof (octave_idx_type) > sizeof (int))\n    {\n      int maxval = std::numeric_limits<int>::max ();\n\n      if (dim > maxval || n > maxval)\n        error (\"%s: dimension too large for Qhull\", who);\n    }\n\n  return true;\n}\n\n#endif\n\nDEFUN_DLD (__delaunayn__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{T} =} __delaunayn__ (@var{pts})\n@deftypefnx {} {@var{T} =} __delaunayn__ (@var{pts}, @var{options})\nUndocumented internal function.\n@end deftypefn */)\n\n{\n#if defined (HAVE_QHULL)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value_list retval;\n\n  retval(0) = 0.0;\n\n  Matrix p (args(0).matrix_value ());\n  const octave_idx_type dim = p.columns ();\n  const octave_idx_type n = p.rows ();\n\n  if (! octave_qhull_dims_ok (dim, n, \"__delaynayn__\"))\n    return retval;\n\n  // Default options\n  std::string options;\n  if (dim <= 3)\n    options = \"Qt Qbb Qc\";\n  else\n    options = \"Qt Qbb Qc Qx\";\n\n  if (nargin == 2)\n    {\n      if (args(1).is_string ())\n        options = args(1).string_value ();\n      else if (args(1).isempty ())\n        ;  // Use default options\n      else if (args(1).iscellstr ())\n        {\n          options = \"\";\n          Array<std::string> tmp = args(1).cellstr_value ();\n\n          for (octave_idx_type i = 0; i < tmp.numel (); i++)\n            options += tmp(i) + ' ';\n        }\n      else\n        error (\"__delaunayn__: OPTIONS argument must be a string, cell array of strings, or empty\");\n    }\n\n  if (n > dim + 1)\n    {\n      p = p.transpose ();\n      double *pt_array = p.rwdata ();\n      boolT ismalloc = false;\n\n      std::string cmd = \"qhull d \" + options;\n\n      // Set the outfile pointer to stdout for status information.\n      FILE *outfile = nullptr;\n\n      // Set the errfile pointer to stderr for errors and summary information.\n      // Note: pointer cannot be NULL to disable reporting, unlike outfile.\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)\n      FILE *errfile = std::fopen (\"NUL\", \"w\");\n#else\n      FILE *errfile = std::fopen (\"/dev/null\", \"w\");\n#endif\n\n      if (! errfile)\n        error (\"__delaunayn__: unable to redirect Qhull errors to /dev/null\");\n\n      unwind_action close_errfile ([errfile] () { std::fclose (errfile); });\n\n      qhT context = { };\n      qhT *qh = &context;\n\n      int exitcode = qh_new_qhull (qh, dim, n, pt_array, ismalloc, &cmd[0],\n                                   outfile, errfile);\n\n      unwind_action free_memory ([qh] () { free_qhull_memory (qh); });\n\n      if (exitcode)\n        error (\"__delaunayn__: qhull failed\");\n\n      // triangulate non-simplicial facets\n      qh_triangulate (qh);\n\n      facetT *facet;\n      vertexT *vertex, **vertexp;\n      octave_idx_type nf = 0;\n      octave_idx_type i = 0;\n\n      FORALLfacets\n      {\n        if (! facet->upperdelaunay)\n          nf++;\n\n        // Double check.  Non-simplicial facets will cause segfault below\n        if (! facet->simplicial)\n          error (\"__delaunayn__: Qhull returned non-simplicial facets -- try delaunayn with different options\");\n      }\n\n      Matrix simpl (nf, dim+1);\n\n      FORALLfacets\n      {\n        if (! facet->upperdelaunay)\n          {\n            octave_idx_type j = 0;\n\n            FOREACHvertex_ (facet->vertices)\n            {\n              simpl(i, j++) = 1 + qh_pointid(qh, vertex->point);\n            }\n            i++;\n          }\n      }\n\n      retval(0) = simpl;\n    }\n  else if (n == dim + 1)\n    {\n      // FIXME: One should check if nx points span a simplex.\n      //        I will look at this later.\n      RowVector vec (n);\n      for (octave_idx_type i = 0; i < n; i++)\n        vec(i) = i + 1.0;\n\n      retval(0) = vec;\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__delaunayn__\", \"Qhull\");\n\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/__fltk_uigetfile__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_FLTK)\n\n#  if defined (WIN32)\n#    define WIN32_LEAN_AND_MEAN\n#  endif\n\n#  include <string>\n\n#  include <FL/Fl.H>\n#  include <FL/Fl_File_Chooser.H>\n\n// FLTK headers may include X11/X.h which defines Complex, and that\n// conflicts with Octave's Complex typedef.  We don't need the X11\n// Complex definition in this file, so remove it before including Octave\n// headers which may require Octave's Complex typedef.\n#  undef Complex\n\n#endif\n\n#include \"dMatrix.h\"\n#include \"file-ops.h\"\n\n#include \"Cell.h\"\n#include \"defun-dld.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN_DLD (__fltk_uigetfile__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} __fltk_uigetfile__ (@dots{})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_FLTK)\n\n  // Expected argument list:\n  //\n  //   args(0) ... FileFilter in fltk format\n  //   args(1) ... Title\n  //   args(2) ... Default Filename\n  //   args(3) ... SelectValue \"on\"/\"off\"/\"dir\"/\"create\"\n\n  octave_value_list retval (3, octave_value (0));\n\n  std::string file_filter = args(0).string_value ();\n  std::string title = args(1).string_value ();\n  std::string default_name = args(2).string_value ();\n\n  int multi_type = Fl_File_Chooser::SINGLE;\n  std::string flabel = \"Filename:\";\n\n  std::string multi = args(3).string_value ();\n  if (multi == \"on\")\n    multi_type = Fl_File_Chooser::MULTI;\n  else if (multi == \"dir\")\n    {\n      multi_type = Fl_File_Chooser::DIRECTORY;\n      flabel = \"Directory:\";\n    }\n  else if (multi == \"create\")\n    multi_type = Fl_File_Chooser::CREATE;\n\n  Fl_File_Chooser::filename_label = flabel.c_str ();\n\n  Fl_File_Chooser fc (default_name.c_str (), file_filter.c_str (),\n                      multi_type, title.c_str ());\n\n  fc.preview (0);\n\n  if (multi_type == Fl_File_Chooser::CREATE)\n    fc.ok_label (\"Save\");\n\n  fc.show ();\n\n  while (fc.shown ())\n    Fl::wait ();\n\n  if (fc.value ())\n    {\n      int file_count = fc.count ();\n      std::string fname;\n\n      // FLTK uses forward slash even for Windows\n      std::string sep = \"/\";\n      std::size_t idx;\n\n      if (file_count == 1 && multi_type != Fl_File_Chooser::DIRECTORY)\n        {\n          fname = fc.value ();\n          idx = fname.find_last_of (sep);\n          retval(0) = fname.substr (idx + 1);\n        }\n      else\n        {\n          Cell file_cell = Cell (file_count, 1);\n          for (octave_idx_type n = 1; n <= file_count; n++)\n            {\n              fname = fc.value (n);\n              idx = fname.find_last_of (sep);\n              file_cell(n - 1) = fname.substr (idx + 1);\n            }\n          retval(0) = file_cell;\n        }\n\n      if (multi_type == Fl_File_Chooser::DIRECTORY)\n        retval(0) = sys::file_ops::native_separator_path (std::string (fc.value ()));\n      else\n        {\n          retval(1) = sys::file_ops::native_separator_path (std::string (fc.directory ()) + sep);\n          retval(2) = fc.filter_value () + 1;\n        }\n    }\n\n  fc.hide ();\n  Fl::flush ();\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__fltk_uigetfile__\", \"OpenGL and FLTK\");\n\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/__glpk__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ctime>\n\n#include <limits>\n\n#include \"Array.h\"\n#include \"chMatrix.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"dSparse.h\"\n#include \"lo-ieee.h\"\n\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\n#if defined (HAVE_GLPK)\n\nextern \"C\"\n{\n#if defined (HAVE_GLPK_GLPK_H)\n#  include <glpk/glpk.h>\n#else\n#  include <glpk.h>\n#endif\n}\n\nstruct control_params\n{\n  int msglev;\n  int dual;\n  int price;\n  int itlim;\n  int outfrq;\n  int branch;\n  int btrack;\n  int presol;\n  int rtest;\n  int tmlim;\n  int outdly;\n  double tolbnd;\n  double toldj;\n  double tolpiv;\n  double objll;\n  double objul;\n  double tolint;\n  double tolobj;\n};\n\nstatic int\nglpk (int sense, int n, int m, double *c, int nz, int *rn, int *cn,\n      double *a, double *b, char *ctype, int *freeLB, double *lb,\n      int *freeUB, double *ub, int *vartype, int isMIP, int lpsolver,\n      int save_pb, int scale, const control_params& par,\n      double *xmin, double& fmin, int& status,\n      double *lambda, double *redcosts, double& time)\n{\n  int typx = 0;\n  int errnum = 0;\n  int tout = 0;  // to save and restore msglev settings\n\n  time = 0.0;\n  status = -1;    // Initialize status to \"bad\" value\n\n  clock_t t_start = clock ();\n\n  glp_prob *lp = glp_create_prob ();\n\n  // Set the sense of optimization\n  if (sense == 1)\n    glp_set_obj_dir (lp, GLP_MIN);\n  else\n    glp_set_obj_dir (lp, GLP_MAX);\n\n  glp_add_cols (lp, n);\n  for (int i = 0; i < n; i++)\n    {\n      // Define type of the structural variables\n      if (! freeLB[i] && ! freeUB[i])\n        {\n          if (lb[i] != ub[i])\n            glp_set_col_bnds (lp, i+1, GLP_DB, lb[i], ub[i]);\n          else\n            glp_set_col_bnds (lp, i+1, GLP_FX, lb[i], ub[i]);\n        }\n      else\n        {\n          if (! freeLB[i] && freeUB[i])\n            glp_set_col_bnds (lp, i+1, GLP_LO, lb[i], ub[i]);\n          else\n            {\n              if (freeLB[i] && ! freeUB[i])\n                glp_set_col_bnds (lp, i+1, GLP_UP, lb[i], ub[i]);\n              else\n                glp_set_col_bnds (lp, i+1, GLP_FR, lb[i], ub[i]);\n            }\n        }\n\n      // -- Set the objective coefficient of the corresponding\n      // -- structural variable.  No constant term is assumed.\n      glp_set_obj_coef(lp, i+1, c[i]);\n\n      if (isMIP)\n        glp_set_col_kind (lp, i+1, vartype[i]);\n    }\n\n  glp_add_rows (lp, m);\n\n  for (int i = 0; i < m; i++)\n    {\n      // If the i-th row has no lower bound (types F,U), the\n      // corrispondent parameter will be ignored.  If the i-th row has\n      // no upper bound (types F,L), the corrispondent parameter will be\n      // ignored.  If the i-th row is of S type, the i-th LB is used,\n      // but the i-th UB is ignored.\n\n      switch (ctype[i])\n        {\n        case 'F':\n          typx = GLP_FR;\n          break;\n\n        case 'U':\n          typx = GLP_UP;\n          break;\n\n        case 'L':\n          typx = GLP_LO;\n          break;\n\n        case 'S':\n          typx = GLP_FX;\n          break;\n\n        case 'D':\n          typx = GLP_DB;\n          break;\n        }\n\n      glp_set_row_bnds (lp, i+1, typx, typx == GLP_DB ? -b[i] : b[i], b[i]);\n\n    }\n\n  glp_load_matrix (lp, nz, rn, cn, a);\n\n  // sort the constraints for better presolving analogue to the code\n  // sample provided by glpk\n  glp_sort_matrix (lp);\n\n  if (save_pb)\n    {\n      static char tmp[] = \"outpb.lp\";\n      if (glp_write_lp (lp, nullptr, tmp) != 0)\n        error (\"__glpk__: unable to write problem\");\n    }\n\n  // direct calling glp_subroutines requires explicit msglev setting\n  if (par.msglev < 3)\n    tout = glp_term_out (GLP_OFF);\n  else\n    tout = glp_term_out (GLP_ON);\n\n  // scale the problem data\n  if (! par.presol || lpsolver != 1)\n    glp_scale_prob (lp, scale);\n\n  // build advanced initial basis (if required)\n  if (lpsolver == 1 && ! par.presol)\n    glp_adv_basis (lp, 0);\n\n  glp_term_out (tout);  // restore previous msglev status\n\n  // For MIP problems without a presolver, a first pass with glp_simplex\n  // is required\n  if ((! isMIP && lpsolver == 1)\n      || (isMIP && ! par.presol))\n    {\n      glp_smcp smcp;\n      glp_init_smcp (&smcp);\n      smcp.msg_lev = par.msglev;\n      smcp.meth = par.dual;\n      smcp.pricing = par.price;\n      smcp.r_test = par.rtest;\n      smcp.tol_bnd = par.tolbnd;\n      smcp.tol_dj = par.toldj;\n      smcp.tol_piv = par.tolpiv;\n      smcp.obj_ll = par.objll;\n      smcp.obj_ul = par.objul;\n      smcp.it_lim = par.itlim;\n      smcp.tm_lim = par.tmlim;\n      smcp.out_frq = par.outfrq;\n      smcp.out_dly = par.outdly;\n      smcp.presolve = par.presol;\n      errnum = glp_simplex (lp, &smcp);\n    }\n\n  if (isMIP)\n    {\n      glp_iocp iocp;\n      glp_init_iocp (&iocp);\n      iocp.msg_lev = par.msglev;\n      iocp.br_tech = par.branch;\n      iocp.bt_tech = par.btrack;\n      iocp.tol_int = par.tolint;\n      iocp.tol_obj = par.tolobj;\n      iocp.tm_lim = par.tmlim;\n      iocp.out_frq = par.outfrq;\n      iocp.out_dly = par.outdly;\n      iocp.presolve = par.presol;\n      errnum = glp_intopt (lp, &iocp);\n    }\n\n  if (! isMIP && lpsolver == 2)\n    {\n      glp_iptcp iptcp;\n      glp_init_iptcp (&iptcp);\n      iptcp.msg_lev = par.msglev;\n      errnum = glp_interior (lp, &iptcp);\n    }\n\n  if (errnum == 0)\n    {\n      if (isMIP)\n        {\n          status = glp_mip_status (lp);\n          fmin = glp_mip_obj_val (lp);\n        }\n      else\n        {\n          if (lpsolver == 1)\n            {\n              status = glp_get_status (lp);\n              fmin = glp_get_obj_val (lp);\n            }\n          else\n            {\n              status = glp_ipt_status (lp);\n              fmin = glp_ipt_obj_val (lp);\n            }\n        }\n\n      if (isMIP)\n        {\n          for (int i = 0; i < n; i++)\n            xmin[i] = glp_mip_col_val (lp, i+1);\n        }\n      else\n        {\n          // Primal values\n          for (int i = 0; i < n; i++)\n            {\n              if (lpsolver == 1)\n                xmin[i] = glp_get_col_prim (lp, i+1);\n              else\n                xmin[i] = glp_ipt_col_prim (lp, i+1);\n            }\n\n          // Dual values\n          for (int i = 0; i < m; i++)\n            {\n              if (lpsolver == 1)\n                lambda[i] = glp_get_row_dual (lp, i+1);\n              else\n                lambda[i] = glp_ipt_row_dual (lp, i+1);\n            }\n\n          // Reduced costs\n          for (int i = 0; i < glp_get_num_cols (lp); i++)\n            {\n              if (lpsolver == 1)\n                redcosts[i] = glp_get_col_dual (lp, i+1);\n              else\n                redcosts[i] = glp_ipt_col_dual (lp, i+1);\n            }\n        }\n    }\n\n  time = (clock () - t_start) / CLOCKS_PER_SEC;\n\n  glp_delete_prob (lp);\n  // Request that GLPK free all memory resources.\n  // This prevents reported memory leaks, but isn't strictly necessary.\n  // The memory blocks used are allocated once and don't grow with further\n  // calls to glpk so they would be reclaimed anyways when Octave exits.\n  glp_free_env ();\n\n  return errnum;\n}\n\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#define OCTAVE_GLPK_GET_REAL_PARAM(NAME, VAL)                           \\\n  do                                                                    \\\n    {                                                                   \\\n      octave_value tmp = PARAM.getfield (NAME);                         \\\n                                                                        \\\n      if (tmp.is_defined ())                                            \\\n        {                                                               \\\n          if (! tmp.isempty ())                                        \\\n            VAL = tmp.xscalar_value (\"glpk: invalid value in PARAM\" NAME); \\\n          else                                                          \\\n            error (\"glpk: invalid value in PARAM\" NAME);                \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\n#define OCTAVE_GLPK_GET_INT_PARAM(NAME, VAL)                            \\\n  do                                                                    \\\n    {                                                                   \\\n      octave_value tmp = PARAM.getfield (NAME);                         \\\n                                                                        \\\n      if (tmp.is_defined ())                                            \\\n        {                                                               \\\n          if (! tmp.isempty ())                                        \\\n            VAL = tmp.strict_int_value (\"glpk: invalid value in PARAM\" NAME); \\\n          else                                                          \\\n            error (\"glpk: invalid value in PARAM\" NAME);                \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\nDEFUN_DLD (__glpk__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@var{values}] =} __glpk__ (@var{args})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_GLPK)\n\n  // FIXME: Should we even need checking for an internal function?\n  if (args.length () != 9)\n    print_usage ();\n\n  // 1st Input.  A column array containing the objective function coefficients.\n  int mrowsc = args(0).rows ();\n\n  Matrix C = args(0).xmatrix_value (\"__glpk__: invalid value of C\");\n\n  double *c = C.rwdata ();\n  Array<int> rn;\n  Array<int> cn;\n  ColumnVector a;\n  int mrowsA;\n  int nz = 0;\n\n  // 2nd Input.  A matrix containing the constraints coefficients.\n  // If matrix A is NOT a sparse matrix\n  if (args(1).issparse ())\n    {\n      SparseMatrix A = args(1).xsparse_matrix_value (\"__glpk__: invalid value of A\");\n\n      mrowsA = A.rows ();\n      octave_idx_type Anc = A.cols ();\n      octave_idx_type Anz = A.nnz ();\n      rn.resize (dim_vector (Anz+1, 1));\n      cn.resize (dim_vector (Anz+1, 1));\n      a.resize (Anz+1, 0.0);\n\n      if (Anc != mrowsc)\n        error (\"__glpk__: invalid value of A\");\n\n      for (octave_idx_type j = 0; j < Anc; j++)\n        for (octave_idx_type i = A.cidx (j); i < A.cidx (j+1); i++)\n          {\n            nz++;\n            rn(nz) = A.ridx (i) + 1;\n            cn(nz) = j + 1;\n            a(nz) = A.data(i);\n          }\n    }\n  else\n    {\n      Matrix A = args(1).xmatrix_value (\"__glpk__: invalid value of A\");\n\n      mrowsA = A.rows ();\n      rn.resize (dim_vector (mrowsA*mrowsc+1, 1));\n      cn.resize (dim_vector (mrowsA*mrowsc+1, 1));\n      a.resize (mrowsA*mrowsc+1, 0.0);\n\n      for (int i = 0; i < mrowsA; i++)\n        {\n          for (int j = 0; j < mrowsc; j++)\n            {\n              if (A(i, j) != 0)\n                {\n                  nz++;\n                  rn(nz) = i + 1;\n                  cn(nz) = j + 1;\n                  a(nz) = A(i, j);\n                }\n            }\n        }\n\n    }\n\n  // 3rd Input.  A column array containing the right-hand side value\n  //             for each constraint in the constraint matrix.\n  Matrix B = args(2).xmatrix_value (\"__glpk__: invalid value of B\");\n\n  double *b = B.rwdata ();\n\n  // 4th Input.  An array of length mrowsc containing the lower\n  //             bound on each of the variables.\n  Matrix LB = args(3).xmatrix_value (\"__glpk__: invalid value of LB\");\n\n  if (LB.numel () < mrowsc)\n    error (\"__glpk__: invalid dimensions for LB\");\n\n  double *lb = LB.rwdata ();\n\n  // LB argument, default: Free\n  Array<int> freeLB (dim_vector (mrowsc, 1));\n  for (int i = 0; i < mrowsc; i++)\n    {\n      if (math::isinf (lb[i]))\n        {\n          freeLB(i) = 1;\n          lb[i] = -numeric_limits<double>::Inf ();\n        }\n      else\n        freeLB(i) = 0;\n    }\n\n  // 5th Input.  An array of at least length numcols containing the upper\n  //             bound on each of the variables.\n  Matrix UB = args(4).xmatrix_value (\"__glpk__: invalid value of UB\");\n\n  if (UB.numel () < mrowsc)\n    error (\"__glpk__: invalid dimensions for UB\");\n\n  double *ub = UB.rwdata ();\n\n  Array<int> freeUB (dim_vector (mrowsc, 1));\n  for (int i = 0; i < mrowsc; i++)\n    {\n      if (math::isinf (ub[i]))\n        {\n          freeUB(i) = 1;\n          ub[i] = numeric_limits<double>::Inf ();\n        }\n      else\n        freeUB(i) = 0;\n    }\n\n  // 6th Input.  A column array containing the sense of each constraint\n  //             in the constraint matrix.\n  charMatrix CTYPE = args(5).xchar_matrix_value (\"__glpk__: invalid value of CTYPE\");\n\n  char *ctype = CTYPE.rwdata ();\n\n  // 7th Input.  A column array containing the types of the variables.\n  charMatrix VTYPE = args(6).xchar_matrix_value (\"__glpk__: invalid value of VARTYPE\");\n\n  Array<int> vartype (dim_vector (mrowsc, 1));\n  int isMIP = 0;\n  for (int i = 0; i < mrowsc ; i++)\n    {\n      if (VTYPE(i, 0) == 'I')\n        {\n          isMIP = 1;\n          vartype(i) = GLP_IV;\n        }\n      else\n        vartype(i) = GLP_CV;\n    }\n\n  // 8th Input.  Sense of optimization.\n  int sense;\n  double SENSE = args(7).xscalar_value (\"__glpk__: invalid value of SENSE\");\n\n  if (SENSE >= 0)\n    sense = 1;\n  else\n    sense = -1;\n\n  // 9th Input.  A structure containing the control parameters.\n  octave_scalar_map PARAM = args(8).xscalar_map_value (\"__glpk__: invalid value of PARAM\");\n\n  control_params par;\n\n  // Integer parameters\n\n  // Level of messages output by the solver\n  par.msglev = 1;\n  OCTAVE_GLPK_GET_INT_PARAM (\"msglev\", par.msglev);\n  if (par.msglev < 0 || par.msglev > 3)\n    error (\"__glpk__: PARAM.msglev must be 0 (no output) or 1 (error and warning messages only [default]) or 2 (normal output) or 3 (full output)\");\n\n  // scaling option\n  int scale = 16;\n  OCTAVE_GLPK_GET_INT_PARAM (\"scale\", scale);\n  if (scale < 0 || scale > 128)\n    error (\"__glpk__: PARAM.scale must either be 128 (automatic selection of scaling options), or a bitwise or of: 1 (geometric mean scaling), 16 (equilibration scaling), 32 (round scale factors to power of two), 64 (skip if problem is well scaled\");\n\n  // Dual simplex option\n  par.dual = 1;\n  OCTAVE_GLPK_GET_INT_PARAM (\"dual\", par.dual);\n  if (par.dual < 1 || par.dual > 3)\n    error (\"__glpk__: PARAM.dual must be 1 (use two-phase primal simplex [default]) or 2 (use two-phase dual simplex) or 3 (use two-phase dual simplex, and if it fails, switch to the primal simplex)\");\n\n  // Pricing option\n  par.price = 34;\n  OCTAVE_GLPK_GET_INT_PARAM (\"price\", par.price);\n  if (par.price != 17 && par.price != 34)\n    error (\"__glpk__: PARAM.price must be 17 (textbook pricing) or 34 (steepest edge pricing [default])\");\n\n  // Simplex iterations limit\n  par.itlim = std::numeric_limits<int>::max ();\n  OCTAVE_GLPK_GET_INT_PARAM (\"itlim\", par.itlim);\n\n  // Output frequency, in iterations\n  par.outfrq = 200;\n  OCTAVE_GLPK_GET_INT_PARAM (\"outfrq\", par.outfrq);\n\n  // Branching heuristic option\n  par.branch = 4;\n  OCTAVE_GLPK_GET_INT_PARAM (\"branch\", par.branch);\n  if (par.branch < 1 || par.branch > 5)\n    error (\"__glpk__: PARAM.branch must be 1 (first fractional variable) or 2 (last fractional variable) or 3 (most fractional variable) or 4 (heuristic by Driebeck and Tomlin [default]) or 5 (hybrid pseudocost heuristic)\");\n\n  // Backtracking heuristic option\n  par.btrack = 4;\n  OCTAVE_GLPK_GET_INT_PARAM (\"btrack\", par.btrack);\n  if (par.btrack < 1 || par.btrack > 4)\n    error (\"__glpk__: PARAM.btrack must be 1 (depth first search) or 2 (breadth first search) or 3 (best local bound) or 4 (best projection heuristic [default]\");\n\n  // Presolver option\n  par.presol = 1;\n  OCTAVE_GLPK_GET_INT_PARAM (\"presol\", par.presol);\n  if (par.presol < 0 || par.presol > 1)\n    error (\"__glpk__: PARAM.presol must be 0 (do NOT use LP presolver) or 1 (use LP presolver [default])\");\n\n  // LPsolver option\n  int lpsolver = 1;\n  OCTAVE_GLPK_GET_INT_PARAM (\"lpsolver\", lpsolver);\n  if (lpsolver < 1 || lpsolver > 2)\n    error (\"__glpk__: PARAM.lpsolver must be 1 (simplex method) or 2 (interior point method)\");\n\n  // Ratio test option\n  par.rtest = 34;\n  OCTAVE_GLPK_GET_INT_PARAM (\"rtest\", par.rtest);\n  if (par.rtest != 17 && par.rtest != 34)\n    error (\"__glpk__: PARAM.rtest must be 17 (standard ratio test) or 34 (Harris' two-pass ratio test [default])\");\n\n  par.tmlim = std::numeric_limits<int>::max ();\n  OCTAVE_GLPK_GET_INT_PARAM (\"tmlim\", par.tmlim);\n\n  par.outdly = 0;\n  OCTAVE_GLPK_GET_INT_PARAM (\"outdly\", par.outdly);\n\n  // Save option\n  int save_pb = 0;\n  OCTAVE_GLPK_GET_INT_PARAM (\"save\", save_pb);\n  save_pb = save_pb != 0;\n\n  // Real parameters\n\n  // Relative tolerance used to check if the current basic solution\n  // is primal feasible\n  par.tolbnd = 1e-7;\n  OCTAVE_GLPK_GET_REAL_PARAM (\"tolbnd\", par.tolbnd);\n\n  // Absolute tolerance used to check if the current basic solution\n  // is dual feasible\n  par.toldj = 1e-7;\n  OCTAVE_GLPK_GET_REAL_PARAM (\"toldj\", par.toldj);\n\n  // Relative tolerance used to choose eligible pivotal elements of\n  // the simplex table in the ratio test\n  par.tolpiv = 1e-9;\n  OCTAVE_GLPK_GET_REAL_PARAM (\"tolpiv\", par.tolpiv);\n\n  par.objll = -std::numeric_limits<double>::max ();\n  OCTAVE_GLPK_GET_REAL_PARAM (\"objll\", par.objll);\n\n  par.objul = std::numeric_limits<double>::max ();\n  OCTAVE_GLPK_GET_REAL_PARAM (\"objul\", par.objul);\n\n  par.tolint = 1e-5;\n  OCTAVE_GLPK_GET_REAL_PARAM (\"tolint\", par.tolint);\n\n  par.tolobj = 1e-7;\n  OCTAVE_GLPK_GET_REAL_PARAM (\"tolobj\", par.tolobj);\n\n  // Assign pointers to the output parameters\n  ColumnVector xmin (mrowsc, octave_NA);\n  double fmin = octave_NA;\n  ColumnVector lambda (mrowsA, octave_NA);\n  ColumnVector redcosts (mrowsc, octave_NA);\n\n  double time = 0.0;\n  int status = -1;\n\n  int errnum = glpk (sense, mrowsc, mrowsA, c, nz, rn.rwdata (),\n                     cn.rwdata (), a.rwdata (), b, ctype,\n                     freeLB.rwdata (), lb, freeUB.rwdata (),\n                     ub, vartype.rwdata (), isMIP, lpsolver,\n                     save_pb, scale, par, xmin.rwdata (), fmin,\n                     status, lambda.rwdata (),\n                     redcosts.rwdata (), time);\n\n  octave_scalar_map extra;\n\n  if (! isMIP)\n    {\n      extra.assign (\"lambda\", lambda);\n      extra.assign (\"redcosts\", redcosts);\n    }\n\n  extra.assign (\"time\", time);\n  extra.assign (\"status\", status);\n\n  return ovl (xmin, fmin, errnum, extra);\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"glpk\", \"GNU Linear Programming Kit\");\n\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/__init_fltk__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nTo initialize:\n\n  graphics_toolkit (\"fltk\");\n  plot (randn (1e3, 1));\n\n*/\n\n// PKG_ADD: if (__have_feature__ (\"FLTK\") && __have_feature__ (\"OPENGL\") && have_window_system () && ! (ismac () && __is_multi_threaded__ ())) register_graphics_toolkit (\"fltk\"); endif\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n\n#if defined (HAVE_X_WINDOWS)\n#  include <X11/Xlib.h>\n#endif\n\n#include <cmath>\n\n#include <locale>\n#include <map>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#if defined (WIN32)\n#  define WIN32_LEAN_AND_MEAN\n#endif\n\n#if defined (HAVE_FLTK)\n#  include <FL/Fl.H>\n#  include <FL/Fl_Box.H>\n#  include <FL/Fl_Button.H>\n#  include <FL/Fl_Choice.H>\n#  include <FL/Fl_File_Chooser.H>\n#  include <FL/Fl_Gl_Window.H>\n#  include <FL/names.h>\n#  include <FL/Fl_Menu_Bar.H>\n#  include <FL/Fl_Menu_Button.H>\n#  include <FL/Fl_Output.H>\n#  include <FL/Fl_Window.H>\n#  include <FL/fl_ask.H>\n#  include <FL/fl_draw.H>\n#  include <FL/gl.h>\n#endif\n\n// FLTK headers may include X11/X.h which defines Complex, and that\n// conflicts with Octave's Complex typedef.  We don't need the X11\n// Complex definition in this file, so remove it before including Octave\n// headers which may require Octave's Complex typedef.\n#undef Complex\n\n#include \"Array.h\"\n#include \"cmd-edit.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"lo-ieee.h\"\n#include \"oct-env.h\"\n\n#include \"Cell.h\"\n#include \"builtin-defun-decls.h\"\n#include \"display.h\"\n#include \"gl-render.h\"\n#include \"gl2ps-print.h\"\n#include \"graphics.h\"\n#include \"gtk-manager.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"oct-opengl.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_FLTK)\n\n#define FLTK_GRAPHICS_TOOLKIT_NAME \"fltk\"\n\nconst char *help_text = \"\\\nKeyboard Shortcuts\\n\\\na - autoscale\\n\\\np - pan/zoom\\n\\\nr - rotate\\n\\\ng - toggle grid\\n\\\n\\n\\\nMouse\\n\\\nleft drag - pan\\n\\\nmouse wheel - zoom\\n\\\nright drag - rectangle zoom\\n\\\nleft double click - autoscale\\n\\\n\";\n\n#if ! defined (HAVE_OPENGL)\n\nOCTAVE_NORETURN static void\nerror_unexpected (const char *name)\n{\n  error (\"unexpected call to %s when HAVE_OPENGL is not defined - please report this bug\", name);\n}\n\n#endif\n\nclass OpenGL_fltk : public Fl_Gl_Window\n{\npublic:\n\n  OpenGL_fltk (int xx, int yy, int ww, int hh, double num)\n    : Fl_Gl_Window (xx, yy, ww, hh, nullptr), m_number (num),\n      m_glfcns (), m_renderer (m_glfcns), m_in_zoom (false), m_zoom_box ()\n  {\n#if defined (HAVE_OPENGL)\n\n    // Ask for double buffering and a depth buffer.\n    mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE);\n\n#else\n\n    err_disabled_feature (\"OpenGL_fltk\", \"OpenGL\");\n\n#endif\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (OpenGL_fltk)\n\n  ~OpenGL_fltk () = default;\n\n  void zoom (bool z)\n  {\n    m_in_zoom = z;\n    if (! m_in_zoom)\n      hide_overlay ();\n  }\n\n  bool zoom () { return m_in_zoom; }\n  void set_zoom_box (const Matrix& zb) { m_zoom_box = zb; }\n\n  void print (const std::string& cmd, const std::string& term)\n  {\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    octave::gl2ps_print (m_glfcns, gh_mgr.get_object (m_number), cmd, term);\n  }\n\n  uint8NDArray get_pixels ()\n  {\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    m_renderer.draw (gh_mgr.get_object (m_number));\n\n    return m_renderer.get_pixels (w (), h ());\n  }\n\n  void resize (int xx, int yy, int ww, int hh)\n  {\n#if defined (HAVE_OPENGL)\n\n    Fl_Gl_Window::resize (xx, yy, ww, hh);\n\n#else\n\n    octave_unused_parameter (xx);\n    octave_unused_parameter (yy);\n    octave_unused_parameter (ww);\n    octave_unused_parameter (hh);\n\n    error_unexpected (\"OpenGL_fltk::resize\");\n\n#endif\n  }\n\n  bool renumber (double new_number)\n  {\n    bool retval = false;\n\n    if (m_number != new_number)\n      {\n        m_number = new_number;\n        retval = true;\n      }\n\n    return retval;\n  }\n\nprivate:\n\n  double m_number;\n\n  octave::opengl_functions m_glfcns;\n  octave::opengl_renderer m_renderer;\n\n  bool m_in_zoom;\n\n  // (x1,y1,x2,y2)\n  Matrix m_zoom_box;\n\n  void draw ()\n  {\n#if defined (HAVE_OPENGL)\n\n    if (! valid ())\n      {\n        m_glfcns.glMatrixMode (GL_PROJECTION);\n        m_glfcns.glLoadIdentity ();\n        m_glfcns.glViewport (0, 0, w (), h ());\n      }\n\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    m_renderer.draw (gh_mgr.get_object (m_number));\n\n    if (zoom ())\n      overlay ();\n\n#else\n\n    // This shouldn't happen because construction of Opengl_fltk\n    // objects is supposed to be impossible if OpenGL is not available.\n\n    error_unexpected (\"OpenGL_fltk::draw\");\n\n#endif\n  }\n\n  void overlay ()\n  {\n    Matrix overlaycolor (3, 1);\n    overlaycolor(0) = 0.45;\n    overlaycolor(1) = 0.62;\n    overlaycolor(2) = 0.81;\n    double overlayalpha = 0.1;\n    Matrix bordercolor = overlaycolor;\n    double borderalpha = 0.9;\n    double borderwidth = 1.5;\n\n    m_renderer.draw_zoom_box (w (), h (),\n                              m_zoom_box(0), m_zoom_box(1),\n                              m_zoom_box(2), m_zoom_box(3),\n                              overlaycolor, overlayalpha,\n                              bordercolor, borderalpha, borderwidth);\n  }\n\n  int handle (int event)\n  {\n#if defined (HAVE_OPENGL)\n\n    switch (event)\n      {\n      case FL_ENTER:\n        cursor (FL_CURSOR_CROSS);\n        return 1;\n\n      case FL_LEAVE:\n        cursor (FL_CURSOR_DEFAULT);\n        return 1;\n      }\n\n    return Fl_Gl_Window::handle (event);\n\n#else\n\n    octave_unused_parameter (event);\n\n    error_unexpected (\"OpenGL_fltk::handle\");\n\n#endif\n  }\n};\n\nstatic void\nscript_cb (Fl_Widget *, void *data)\n{\n  static_cast<uimenu::properties *> (data)->execute_menuselectedfcn ();\n}\n\nclass fltk_uimenu\n{\npublic:\n\n  fltk_uimenu (int xx, int yy, int ww, int hh)\n    : m_menubar (new Fl_Menu_Bar (xx, yy, ww, hh))\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (fltk_uimenu)\n\n  ~fltk_uimenu () = default;\n\n  int items_to_show ()\n  {\n    //returns the number of visible menu items\n    int len = m_menubar->size ();\n    int n = 0;\n    for (int t = 0; t < len; t++)\n      {\n        const Fl_Menu_Item *m\n          = static_cast<const Fl_Menu_Item *> (&(m_menubar->menu ()[t]));\n\n        if (m->label () && m->visible ())\n          n++;\n      }\n\n    return n;\n  }\n\n  void show ()\n  {\n    m_menubar->show ();\n    m_menubar->redraw ();\n  }\n\n  void hide ()\n  {\n    m_menubar->hide ();\n    m_menubar->redraw ();\n  }\n\n  bool is_visible ()\n  {\n    return m_menubar->visible ();\n  }\n\n  int find_index_by_name (const std::string& findname)\n  {\n    // This function is derived from Greg Ercolano's function\n    // int GetIndexByName(...), see:\n    // http://seriss.com/people/erco/fltk/#Menu_ChangeLabel\n    // He agreed via PM that it can be included in octave using GPLv3\n    // Kai Habel (14.10.2010)\n\n    std::string menupath;\n    for (int t = 0; t < m_menubar->size (); t++)\n      {\n        Fl_Menu_Item *m = const_cast<Fl_Menu_Item *> (&(m_menubar->menu ()[t]));\n        if (m->submenu ())\n          {\n            // item has submenu\n            if (! menupath.empty ())\n              menupath += '/';\n            menupath += m->label ();\n\n            if (menupath == findname)\n              return (t);\n          }\n        else\n          {\n            // End of submenu? Pop back one level.\n            if (! m->label ())\n              {\n                std::size_t idx = menupath.find_last_of ('/');\n                if (idx != std::string::npos)\n                  menupath.erase (idx);\n                else\n                  menupath.clear ();\n                continue;\n              }\n            // Menu item?\n            std::string itempath = menupath;\n            if (! itempath.empty ())\n              itempath += '/';\n            itempath += m->label ();\n\n            if (itempath == findname)\n              return (t);\n          }\n      }\n    return (-1);\n  }\n\n  Matrix find_uimenu_children (uimenu::properties& uimenup) const\n  {\n    Matrix uimenu_childs = uimenup.get_all_children ();\n    Matrix retval = do_find_uimenu_children (uimenu_childs);\n    return retval;\n  }\n\n  Matrix find_uimenu_children (figure::properties& figp) const\n  {\n    Matrix uimenu_childs = figp.get_all_children ();\n    Matrix retval = do_find_uimenu_children (uimenu_childs);\n    return retval;\n  }\n\n  Matrix do_find_uimenu_children (Matrix uimenu_childs) const\n  {\n    octave_idx_type k = 0;\n\n    Matrix pos = Matrix (uimenu_childs.numel (), 1);\n\n    for (octave_idx_type ii = 0; ii < uimenu_childs.numel (); ii++)\n      {\n        gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n        graphics_object kidgo = gh_mgr.get_object (uimenu_childs (ii));\n\n        if (kidgo.valid_object () && kidgo.isa (\"uimenu\"))\n          {\n            uimenu_childs(k) = uimenu_childs(ii);\n            pos(k++) = dynamic_cast<uimenu::properties&> (kidgo.get_properties ()).get_position ();\n          }\n      }\n\n    uimenu_childs.resize (k, 1);\n    pos.resize (k, 1);\n    Matrix retval = Matrix (k, 1);\n    // Don't know if this is the best method to sort.\n    // Can we avoid the for loop?\n    Array<octave_idx_type> sidx = pos.sort_rows_idx (DESCENDING);\n    for (octave_idx_type ii = 0; ii < k; ii++)\n      retval(ii) = uimenu_childs (sidx(ii));\n\n    return retval;\n  }\n\n  void delete_entry (uimenu::properties& uimenup)\n  {\n    std::string fltk_label = uimenup.get___fltk_label__ ();\n    int idx = find_index_by_name (fltk_label.c_str ());\n\n    if (idx >= 0)\n      m_menubar->remove (idx);\n  }\n\n  void update_accelerator (uimenu::properties& uimenup)\n  {\n    std::string fltk_label = uimenup.get___fltk_label__ ();\n    if (! fltk_label.empty ())\n      {\n        Fl_Menu_Item *item = const_cast<Fl_Menu_Item *> (m_menubar->find_item (fltk_label.c_str ()));\n\n        if (item)\n          {\n            std::string acc = uimenup.get_accelerator ();\n            if (acc.length () > 0)\n              {\n                int key = FL_CTRL + acc[0];\n                item->shortcut (key);\n              }\n          }\n      }\n  }\n\n  void update_menuselectedfcn (uimenu::properties& uimenup)\n  {\n    std::string fltk_label = uimenup.get___fltk_label__ ();\n    if (! fltk_label.empty ())\n      {\n        Fl_Menu_Item *item\n          = const_cast<Fl_Menu_Item *> (m_menubar->find_item (fltk_label.c_str ()));\n        if (item)\n          {\n            if (! uimenup.get_menuselectedfcn ().isempty ())\n              item->callback (static_cast<Fl_Callback *> (script_cb),\n                              static_cast<void *> (&uimenup));\n            else\n              item->callback (nullptr, static_cast<void *> (nullptr));\n          }\n      }\n  }\n\n  void update_enable (uimenu::properties& uimenup)\n  {\n    std::string fltk_label = uimenup.get___fltk_label__ ();\n    if (! fltk_label.empty ())\n      {\n        Fl_Menu_Item *item\n          = const_cast<Fl_Menu_Item *> (m_menubar->find_item (fltk_label.c_str ()));\n        if (item)\n          {\n            if (uimenup.is_enable ())\n              item->activate ();\n            else\n              item->deactivate ();\n          }\n      }\n  }\n\n  void update_foregroundcolor (uimenu::properties& uimenup)\n  {\n    std::string fltk_label = uimenup.get___fltk_label__ ();\n    if (! fltk_label.empty ())\n      {\n        Fl_Menu_Item *item\n          = const_cast<Fl_Menu_Item *> (m_menubar->find_item (fltk_label.c_str ()));\n        if (item)\n          {\n            Matrix rgb = uimenup.get_foregroundcolor_rgb ();\n\n            uchar r = static_cast<uchar> (std::floor (rgb (0) * 255));\n            uchar g = static_cast<uchar> (std::floor (rgb (1) * 255));\n            uchar b = static_cast<uchar> (std::floor (rgb (2) * 255));\n\n            item->labelcolor (fl_rgb_color (r, g, b));\n          }\n      }\n  }\n\n  void update_seperator (const uimenu::properties& uimenup)\n  {\n    // Matlab places the separator before the current\n    // menu entry, while fltk places it after.  So we need to find\n    // the previous item in this menu/submenu. (Kai)\n    std::string fltk_label = uimenup.get___fltk_label__ ();\n    if (! fltk_label.empty ())\n      {\n        int itemflags = 0, idx;\n        int curr_idx = find_index_by_name (fltk_label.c_str ());\n\n        for (idx = curr_idx - 1; idx >= 0; idx--)\n          {\n            Fl_Menu_Item *item\n              = const_cast<Fl_Menu_Item *> (&m_menubar->menu () [idx]);\n            itemflags = item->flags;\n            if (item->label ())\n              break;\n          }\n\n        if (idx >= 0 && idx < m_menubar->size ())\n          {\n            if (uimenup.is_separator ())\n              {\n                if (! (itemflags & FL_SUBMENU))\n                  m_menubar->mode (idx, itemflags | FL_MENU_DIVIDER);\n              }\n            else\n              m_menubar->mode (idx, itemflags & (~FL_MENU_DIVIDER));\n          }\n      }\n  }\n\n  void update_visible (uimenu::properties& uimenup)\n  {\n    std::string fltk_label = uimenup.get___fltk_label__ ();\n    if (! fltk_label.empty ())\n      {\n        Fl_Menu_Item *item\n          = const_cast<Fl_Menu_Item *> (m_menubar->find_item (fltk_label.c_str ()));\n        if (item)\n          {\n            if (uimenup.is_visible ())\n              item->show ();\n            else\n              item->hide ();\n          }\n      }\n  }\n\n  void update_position (uimenu::properties& uimenup, int pos)\n  {\n    uimenup.get_property (\"position\").set (octave_value (static_cast<double> (pos)),\n                                           true, false);\n  }\n\n  void add_entry (uimenu::properties& uimenup)\n  {\n\n    std::string fltk_label = uimenup.get___fltk_label__ ();\n\n    if (! fltk_label.empty ())\n      {\n        bool item_added = false;\n        do\n          {\n            const Fl_Menu_Item *item\n              = m_menubar->find_item (fltk_label.c_str ());\n\n            if (item)\n              {\n                //avoid duplicate menulabels\n                std::size_t idx1 = fltk_label.find_last_of ('(');\n                std::size_t idx2 = fltk_label.find_last_of (')');\n                int len = idx2 - idx1;\n                int val = 1;\n                if (len > 0)\n                  {\n                    std::string valstr = fltk_label.substr (idx1 + 1, len - 1);\n                    fltk_label.erase (idx1, len + 1);\n\n                    // FIXME: Should we warn or error on invalid or out\n                    // of range values in VALSTR?  When atoi was used\n                    // for conversion instead of std::stoi we did not.\n                    // Was that intentional?\n\n                    try\n                      {\n                        val = std::stoi (valstr);\n\n                        if (val > 0 && val < 99)\n                          val++;\n                      }\n                    catch (const std::invalid_argument&) { }\n                    catch (const std::out_of_range&) { }\n                  }\n                std::ostringstream valstream;\n                valstream << val;\n                fltk_label += '(' + valstream.str () + ')';\n              }\n            else\n              {\n                Matrix uimenu_ch = find_uimenu_children (uimenup);\n                int len = uimenu_ch.numel ();\n                int flags = 0;\n                if (len > 0)\n                  flags = FL_SUBMENU;\n                if (len == 0 && uimenup.is_checked ())\n                  flags += FL_MENU_TOGGLE + FL_MENU_VALUE;\n                m_menubar->add (fltk_label.c_str (),\n                                0, nullptr, nullptr, flags);\n                item_added = true;\n              }\n          }\n        while (! item_added);\n        uimenup.set___fltk_label__ (fltk_label);\n      }\n  }\n\n  void add_to_menu (uimenu::properties& uimenup)\n  {\n    std::vector<int> delayed_menus;\n    Matrix kids = find_uimenu_children (uimenup);\n    int len = kids.numel ();\n    std::string fltk_label = uimenup.get___fltk_label__ ();\n    int count = 0;\n\n    add_entry (uimenup);\n    update_foregroundcolor (uimenup);\n    update_menuselectedfcn (uimenup);\n    update_accelerator (uimenup);\n    update_enable (uimenup);\n    update_visible (uimenup);\n    update_seperator (uimenup);\n\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    for (octave_idx_type ii = 0; ii < len; ii++)\n      {\n        graphics_object kgo = gh_mgr.get_object (kids (len - (ii + 1)));\n\n        if (kgo.valid_object ())\n          {\n            uimenu::properties& kprop\n              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());\n\n            // if no pos yet, delay adding menu until after other menus\n            int pos = kprop.get_position ();\n            if (pos <= 0)\n              delayed_menus.push_back ((len - (ii + 1)));\n            else\n              {\n                add_to_menu (kprop);\n              }\n          }\n      }\n\n    // create any delayed menus\n    for (std::size_t ii = 0; ii < delayed_menus.size (); ii++)\n      {\n        graphics_object kgo = gh_mgr.get_object (kids (delayed_menus[ii]));\n\n        if (kgo.valid_object ())\n          {\n            uimenu::properties& kprop\n              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());\n            add_to_menu (kprop);\n            update_position (kprop, ++count);\n          }\n      }\n  }\n\n  void add_to_menu (figure::properties& figp)\n  {\n    std::vector<int> delayed_menus;\n    Matrix kids = find_uimenu_children (figp);\n    int len = kids.numel ();\n    int count = 0;\n\n    m_menubar->clear ();\n\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    for (octave_idx_type ii = 0; ii < len; ii++)\n      {\n        graphics_object kgo = gh_mgr.get_object (kids (len - (ii + 1)));\n\n        if (kgo.valid_object ())\n          {\n            uimenu::properties& kprop\n              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());\n\n            // if no pos yet, delay adding menu until after other menus\n            int pos = kprop.get_position ();\n            if (pos <= 0)\n              delayed_menus.push_back ((len - (ii + 1)));\n            else\n              {\n                add_to_menu (kprop);\n                update_position (kprop, ++count);\n              }\n          }\n      }\n\n    // create any delayed menus\n    for (std::size_t ii = 0; ii < delayed_menus.size (); ii++)\n      {\n        graphics_object kgo = gh_mgr.get_object (kids (delayed_menus[ii]));\n\n        if (kgo.valid_object ())\n          {\n            uimenu::properties& kprop\n              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());\n            add_to_menu (kprop);\n            update_position (kprop, ++count);\n          }\n      }\n  }\n\n  template <typename T_prop>\n  void remove_from_menu (T_prop& prop)\n  {\n    Matrix kids;\n    std::string type = prop.get_type ();\n    kids = find_uimenu_children (prop);\n    int len = kids.numel ();\n\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    for (octave_idx_type ii = 0; ii < len; ii++)\n      {\n        graphics_object kgo = gh_mgr.get_object (kids (len - (ii + 1)));\n\n        if (kgo.valid_object ())\n          {\n            uimenu::properties& kprop\n              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());\n            remove_from_menu (kprop);\n          }\n      }\n\n    if (type == \"uimenu\")\n      delete_entry (dynamic_cast<uimenu::properties&> (prop));\n    else if (type == \"figure\")\n      m_menubar->clear ();\n  }\n\nprivate:\n\n  Fl_Menu_Bar *m_menubar;\n};\n\n#if defined (HAVE_X_WINDOWS)\nstatic int\nxerror_handler (Display *, XErrorEvent *)\n{\n  return 0;\n}\n#endif\n\nclass plot_window : public Fl_Window\n{\n  friend class fltk_uimenu;\n\npublic:\n\n  plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp,\n               bool internal)\n    : Fl_Window (xx, yy, ww, hh + MENU_H + STATUS_H + 2, \"octave\"),\n      m_window_label (), m_fp (xfp), m_uimenu (nullptr), m_canvas (nullptr),\n      m_autoscale (nullptr), m_togglegrid (nullptr), m_panzoom (nullptr),\n      m_rotate (nullptr), m_help (nullptr), m_status (nullptr),\n      m_resize_dummy (nullptr), m_ax_obj (), m_pos_x (0), m_pos_y (0)\n  {\n    callback (window_close, static_cast<void *> (this));\n\n    // The size of the resize_dummy box also determines the minimum\n    // window size.\n    m_resize_dummy = new Fl_Box (5 * STATUS_H, MENU_H,\n                                 ww - 5 * STATUS_H, hh);\n\n    // See http://fltk.org/articles.php?L415+I0+T+M1000+P1\n                // for how resizable works\n    resizable (m_resize_dummy);\n\n    // FIXME: The function below is only available in FLTK >= 1.3\n    // At some point support for FLTK 1.1 will be dropped in Octave.\n    // At that point this function should be uncommented.\n    // The current solution is to call xclass() before show() for each window.\n    // Set WM_CLASS which allows window managers to properly group related\n    // windows.  Otherwise, the class is just \"FLTK\"\n    //default_xclass (\"Octave\");\n\n    m_uimenu = new fltk_uimenu (0, 0, ww, MENU_H);\n    m_canvas = new OpenGL_fltk (0, MENU_H, ww, hh, number ());\n\n    // The bottom toolbar is a composite of \"autoscale\", \"togglegrid\",\n    // \"panzoom\", \"rotate\", \"help\", and \"status\".\n    // Only \"status\" should be resized.\n\n    int toolbar_y = MENU_H + hh + 1;\n    m_status = new Fl_Output (5 * STATUS_H, toolbar_y,\n                              ww - 5 * STATUS_H, STATUS_H, \"\");\n\n    m_status->textcolor (FL_BLACK);\n    m_status->color (FL_GRAY);\n    m_status->textfont (FL_COURIER);\n    m_status->textsize (10);\n    m_status->box (FL_ENGRAVED_BOX);\n\n    m_autoscale = new Fl_Button (0, toolbar_y, STATUS_H, STATUS_H, \"A\");\n    m_autoscale->callback (button_callback, static_cast<void *> (this));\n    m_autoscale->tooltip (\"Autoscale\");\n\n    m_togglegrid = new Fl_Button (STATUS_H, toolbar_y, STATUS_H, STATUS_H, \"G\");\n    m_togglegrid->callback (button_callback, static_cast<void *> (this));\n    m_togglegrid->tooltip (\"Toggle Grid\");\n\n    m_panzoom = new Fl_Button (2* STATUS_H, toolbar_y, STATUS_H, STATUS_H, \"P\");\n    m_panzoom->callback (button_callback, static_cast<void *> (this));\n    m_panzoom->tooltip (\"Mouse Pan/Zoom\");\n\n    m_rotate = new Fl_Button (3 * STATUS_H, toolbar_y, STATUS_H, STATUS_H, \"R\");\n    m_rotate->callback (button_callback, static_cast<void *> (this));\n    m_rotate->tooltip (\"Mouse Rotate\");\n\n    m_help = new Fl_Button (4 * STATUS_H, toolbar_y, STATUS_H, STATUS_H, \"?\");\n    m_help->callback (button_callback, static_cast<void *> (this));\n    m_help->tooltip (\"Help\");\n\n    end ();\n\n    set_name ();\n    m_uimenu->add_to_menu (m_fp);\n    if (m_fp.menubar_is (\"none\") || ! m_uimenu->items_to_show ())\n      hide_menubar ();\n\n    update_boundingbox (internal);\n\n    if (m_fp.is_visible ())\n      {\n        // FIXME: This code should be removed when Octave drops support\n        // for FLTK 1.1.  Search for default_xclass in this file to find\n        // code that should be uncommented to take its place.\n        //\n        // Set WM_CLASS which allows window managers to properly group\n        // related windows.  Otherwise, the class is just \"FLTK\"\n        xclass (\"Octave\");\n\n        show ();\n\n#if defined (HAVE_X_WINDOWS)\n        std::string show_gui_msgs\n          = octave::sys::env::getenv (\"OCTAVE_SHOW_GUI_MESSAGES\");\n\n        // Installing our handler suppresses the messages.\n        if (show_gui_msgs.empty ())\n          XSetErrorHandler (xerror_handler);\n#endif\n\n        if (m_fp.get_currentaxes ().ok ())\n          show_canvas ();\n        else\n          hide_canvas ();\n      }\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (plot_window)\n\n  ~plot_window ()\n  {\n    this->hide ();\n    Fl::check ();\n\n    delete m_uimenu;\n\n    // FLTK is supposed to manage memory for widgets.\n  }\n\n  double number () { return m_fp.get___myhandle__ ().value (); }\n\n  void renumber (double new_number)\n  {\n    if (! m_canvas)\n      error (\"unable to renumber figure\");\n\n    if (m_canvas->renumber (new_number))\n      mark_modified ();\n  }\n\n  void print (const std::string& cmd, const std::string& term)\n  {\n    m_canvas->print (cmd, term);\n  }\n\n  uint8NDArray get_pixels ()\n  {\n    return m_canvas->get_pixels ();\n  }\n\n  void show_menubar ()\n  {\n    m_uimenu->show ();\n    update_toolbar_position ();\n  }\n\n  void hide_menubar ()\n  {\n    m_uimenu->hide ();\n    update_toolbar_position ();\n  }\n\n  void uimenu_update (const graphics_handle& gh, int id)\n  {\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    graphics_object uimenu_obj = gh_mgr.get_object (gh);\n\n    if (uimenu_obj.valid_object () && uimenu_obj.isa (\"uimenu\"))\n      {\n        uimenu::properties& uimenup\n          = dynamic_cast<uimenu::properties&> (uimenu_obj.get_properties ());\n        std::string fltk_label = uimenup.get___fltk_label__ ();\n        graphics_object fig = uimenu_obj.get_ancestor (\"figure\");\n        figure::properties& figp\n          = dynamic_cast<figure::properties&> (fig.get_properties ());\n\n        switch (id)\n          {\n          case base_properties::ID_BEINGDELETED:\n            m_uimenu->remove_from_menu (uimenup);\n            break;\n\n          case base_properties::ID_VISIBLE:\n            m_uimenu->update_visible (uimenup);\n            break;\n\n          case uimenu::properties::ID_ACCELERATOR:\n            m_uimenu->update_accelerator (uimenup);\n            break;\n\n          case uimenu::properties::ID_MENUSELECTEDFCN:\n            m_uimenu->update_menuselectedfcn (uimenup);\n            break;\n\n          case uimenu::properties::ID_CHECKED:\n            m_uimenu->add_to_menu (figp);//rebuilding entire menu\n            break;\n\n          case uimenu::properties::ID_ENABLE:\n            m_uimenu->update_enable (uimenup);\n            break;\n\n          case uimenu::properties::ID_FOREGROUNDCOLOR:\n            m_uimenu->update_foregroundcolor (uimenup);\n            break;\n\n          case uimenu::properties::ID_LABEL:\n            m_uimenu->add_to_menu (figp);//rebuilding entire menu\n            break;\n\n          case uimenu::properties::ID_POSITION:\n            m_uimenu->add_to_menu (figp);//rebuilding entire menu\n            break;\n\n          case uimenu::properties::ID_SEPARATOR:\n            m_uimenu->update_seperator (uimenup);\n            break;\n          }\n\n        if (m_uimenu->items_to_show ())\n          show_menubar ();\n        else\n          hide_menubar ();\n      }\n  }\n\n  void show_canvas ()\n  {\n    if (! m_canvas->can_do ())\n      error (\"unable to plot due to insufficient OpenGL support\");\n    else if (m_fp.is_visible ())\n      {\n        m_canvas->show ();\n        m_canvas->make_current ();\n      }\n  }\n\n  void hide_canvas ()\n  {\n    m_canvas->hide ();\n  }\n\n  // Move the toolbar at the bottom of the plot_window.\n  // The only reason for moving the toolbar is hiding and\n  // showing the menubar.  All other resizing is done by fltk.\n\n  void update_toolbar_position ()\n  {\n    int old_canvas_h = m_canvas->h ();\n\n    // keep position fix, change outerposition accordingly\n    update_boundingbox (true);\n    m_canvas->resize (0, menu_dy (), w (), old_canvas_h);\n\n    int toolbar_y = m_canvas->h () + menu_dy () + 1;\n    m_autoscale->position (0, toolbar_y);\n    m_togglegrid->position (STATUS_H, toolbar_y);\n    m_panzoom->position (2 * STATUS_H, toolbar_y);\n    m_rotate->position (3 * STATUS_H, toolbar_y);\n    m_help->position (4 * STATUS_H, toolbar_y);\n    m_status->resize (5 * STATUS_H, toolbar_y,\n                      w () - 5 * STATUS_H, STATUS_H);\n    init_sizes ();\n    redraw ();\n  }\n\n  Matrix outerposition2position (const Matrix& outerpos)\n  {\n    Matrix pos = outerpos;\n    pos(1) += menu_dy ();\n    pos(3) -= menu_dy () + STATUS_H + 2;\n    return pos;\n  }\n\n  Matrix position2outerposition (const Matrix& pos)\n  {\n    Matrix outerpos = pos;\n    outerpos(1) -= menu_dy ();\n    outerpos(3) += menu_dy () + STATUS_H + 2;\n    return outerpos;\n  }\n\n  // Called from figure::properties::ID_POSITION if internal = true\n  // or ID_OUTERPOSITION if false.\n  // (someone has requested a position change with set (h, \"position\", [...])\n  // or set (h, \"outerposition\", [...])\n\n  void update_boundingbox (bool internal)\n  {\n    Matrix bb = m_fp.get_boundingbox (internal);\n    if (internal)\n      bb = position2outerposition (bb);\n    resize (bb(0), bb(1), bb(2), bb(3));\n  }\n\n  void mark_modified ()\n  {\n    m_canvas->redraw ();\n  }\n\n  void set_name ()\n  {\n    m_window_label = m_fp.get_title ();\n    label (m_window_label.c_str ());\n  }\n\nprivate:\n\n  // window name -- this must exists for the duration of the window's\n  // life\n  std::string m_window_label;\n\n  // Figure properties.\n  figure::properties& m_fp;\n\n  // Status area height.\n  static const int STATUS_H = 20;\n\n  // Menu height\n  static const int MENU_H = 25;\n\n  fltk_uimenu *m_uimenu;\n\n  OpenGL_fltk *m_canvas;\n\n  Fl_Button *m_autoscale;\n  Fl_Button *m_togglegrid;\n  Fl_Button *m_panzoom;\n  Fl_Button *m_rotate;\n  Fl_Button *m_help;\n  Fl_Output *m_status;\n\n  Fl_Box *m_resize_dummy;\n\n  graphics_object m_ax_obj;\n\n  int m_pos_x;\n  int m_pos_y;\n\n  // Window callback.\n  static void window_close (Fl_Widget *, void *data)\n  {\n    interpreter& interp = __get_interpreter__ ();\n\n    octave_value_list args;\n    args(0) = static_cast<plot_window *> (data)->number ();\n\n    interp.feval (\"close\", args);\n  }\n\n  // Button callbacks.\n  static void button_callback (Fl_Widget *ww, void *data)\n  {\n    static_cast<plot_window *> (data)->button_press (ww, data);\n  }\n\n  void button_press (Fl_Widget *widg, void *)\n  {\n    if (widg == m_autoscale)\n      axis_auto ();\n    else if (widg == m_togglegrid)\n      toggle_grid ();\n    else if (widg == m_panzoom)\n      m_fp.set___mouse_mode__ (\"pan\");\n    else if (widg == m_rotate)\n      m_fp.set___mouse_mode__ (\"rotate\");\n    else if (widg == m_help)\n      fl_message (\"%s\", help_text);\n  }\n\n  void set_on_ax_obj (const std::string& name, const std::string& value)\n  {\n    // ax_obj is the last clicked axes object\n    if (m_ax_obj && m_ax_obj.isa (\"axes\")\n        && m_ax_obj.get_properties ().get_tag () != \"legend\"\n        && m_ax_obj.get_properties ().get_tag () != \"colorbar\")\n      {\n        axes::properties& ap\n          = dynamic_cast<axes::properties&> (m_ax_obj.get_properties ());\n        ap.set (name, value);\n      }\n    else // no axes object clicked so far, take currentaxes\n      {\n        graphics_handle gh = m_fp.get_currentaxes ();\n        if (gh.ok ())\n          {\n            gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n            graphics_object go = gh_mgr.get_object (gh);\n\n            axes::properties& ap\n              = dynamic_cast<axes::properties&> (go.get_properties ());\n\n            ap.set (name, value);\n          }\n      }\n  }\n\n  void axis_auto ()\n  {\n    octave_value_list args;\n    if (m_fp.get_currentaxes ().ok ())\n      {\n        interpreter& interp = __get_interpreter__ ();\n\n        args(0) = m_fp.get_currentaxes ().as_octave_value ();\n        args(1) = \"auto\";\n\n        interp.feval (\"axis\", args);\n\n        mark_modified ();\n      }\n  }\n\n  void toggle_grid ()\n  {\n    interpreter& interp = __get_interpreter__ ();\n\n    octave_value_list args;\n    if (m_fp.get_currentaxes ().ok ())\n      args(0) = m_fp.get_currentaxes ().as_octave_value ();\n\n    interp.feval (\"grid\", args);\n\n    mark_modified ();\n  }\n\n  void pixel2pos (const graphics_handle& ax, int px, int py, double& xx,\n                  double& yy) const\n  {\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    pixel2pos (gh_mgr.get_object (ax), px, py, xx, yy);\n  }\n\n  void pixel2pos (graphics_object ax, int px, int py, double& xx,\n                  double& yy) const\n  {\n    if (ax && ax.isa (\"axes\"))\n      {\n        axes::properties& ap\n          = dynamic_cast<axes::properties&> (ax.get_properties ());\n        ColumnVector pp = ap.pixel2coord (px, py);\n        xx = pp(0);\n        yy = pp(1);\n      }\n  }\n\n  graphics_handle pixel2axes_or_ca (int px, int py)\n  {\n    Matrix kids = m_fp.get_children ();\n    int len = kids.numel ();\n\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    for (int k = 0; k < len; k++)\n      {\n        graphics_handle hnd = gh_mgr.lookup (kids(k));\n\n        if (hnd.ok ())\n          {\n            graphics_object kid = gh_mgr.get_object (hnd);\n\n            if (kid.valid_object () && kid.isa (\"axes\"))\n              {\n                Matrix bb = kid.get_properties ().get_boundingbox (false);\n\n                if (bb(0) <= px && px < (bb(0)+bb(2))\n                    && bb(1) <= py && py < (bb(1)+bb(3)))\n                  {\n                    return hnd;\n                  }\n              }\n          }\n      }\n    return m_fp.get_currentaxes ();\n  }\n\n  void pixel2status (const graphics_handle& ax, int px0, int py0,\n                     int px1 = -1, int py1 = -1)\n  {\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    pixel2status (gh_mgr.get_object (ax), px0, py0, px1, py1);\n  }\n\n  void pixel2status (graphics_object ax, int px0, int py0,\n                     int px1 = -1, int py1 = -1)\n  {\n    double x0, y0, x1, y1;\n    x0 = y0 = x1 = y1 = octave::numeric_limits<double>::NaN ();\n    std::stringstream cbuf;\n    cbuf.precision (4);\n    cbuf.width (6);\n    pixel2pos (ax, px0, py0, x0, y0);\n    cbuf << '[' << x0 << \", \" << y0 << ']';\n    if (px1 >= 0)\n      {\n        pixel2pos (ax, px1, py1, x1, y1);\n        cbuf << \" -> [\"<< x1 << \", \" << y1 << ']';\n      }\n\n    m_status->value (cbuf.str ().c_str ());\n  }\n\n  void view2status (graphics_object ax)\n  {\n    if (ax && ax.isa (\"axes\"))\n      {\n        axes::properties& ap\n          = dynamic_cast<axes::properties&> (ax.get_properties ());\n        std::stringstream cbuf;\n        cbuf.precision (4);\n        cbuf.width (6);\n        Matrix v (1, 2, 0);\n        v = ap.get (\"view\").matrix_value ();\n        cbuf << \"[azimuth: \" << v(0) << \", elevation: \" << v(1) << ']';\n\n        m_status->value (cbuf.str ().c_str ());\n      }\n  }\n\n  void set_currentpoint (int px, int py)\n  {\n    if (! m_fp.is_beingdeleted ())\n      {\n        Matrix pos = m_fp.map_from_boundingbox (px, py);\n        m_fp.set_currentpoint (pos);\n\n        gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n        graphics_object robj = gh_mgr.get_object (m_fp.get_parent ());\n\n        root_figure::properties& rp\n          = dynamic_cast<root_figure::properties&> (robj.get_properties ());\n\n        rp.set_currentfigure (m_fp.get___myhandle__ ().value ());\n      }\n  }\n\n  void set_axes_currentpoint (graphics_object ax, int px, int py)\n  {\n    if (ax.valid_object () && ax.isa (\"axes\"))\n      {\n        axes::properties& ap\n          = dynamic_cast<axes::properties&> (ax.get_properties ());\n\n        Matrix x_zlim = ap.get_transform_zlim ();\n        Matrix pos (2, 3, 0.0);\n\n        // front point (nearest to the viewer)\n        ColumnVector tmp = ap.get_transform ().untransform (px, py, x_zlim(0));\n        pos(0, 0) = tmp(0);\n        pos(0, 1) = tmp(1);\n        pos(0, 2) = tmp(2);\n\n        // back point (furthest from the viewer)\n        tmp = ap.get_transform ().untransform (px, py, x_zlim(1));\n        pos(1, 0) = tmp(0);\n        pos(1, 1) = tmp(1);\n        pos(1, 2) = tmp(2);\n\n        ap.set_currentpoint (pos);\n        if (ap.get_tag () != \"legend\" && ap.get_tag () != \"colorbar\")\n          m_fp.set_currentaxes (ap.get___myhandle__ ().value ());\n      }\n  }\n\n  int menu_dy ()\n  {\n    if (m_uimenu->is_visible ())\n      return MENU_H;\n    else\n      return 0;\n  }\n\n  octave_scalar_map format_key_event (int e_key, const char *e_text,\n                                      int e_state)\n  {\n    octave_scalar_map evt;\n\n    evt.assign (\"Character\", octave_value (e_text));\n    evt.assign (\"Modifier\", octave_value (modifier2cell (e_state)));\n\n    std::string key_str;\n    std::ostringstream tmp_str;\n\n    if (e_key == FL_Escape)\n      key_str = \"escape\";\n    else if (e_key == FL_Tab)\n      key_str = \"tab\";\n    else if (e_key == FL_Caps_Lock)\n      key_str = \"capslock\";\n    else if (e_key == FL_Shift_L || e_key == FL_Shift_R)\n      key_str = \"shift\";\n    else if (e_key == FL_Control_L || e_key == FL_Control_R)\n      key_str = \"control\";\n    else if (e_key == FL_Meta_L || e_key == FL_Meta_R)\n      key_str = \"windows\";\n    else if (e_key == FL_Alt_L || e_key == FL_Alt_R)\n      key_str = \"alt\";\n    else if (e_key == 32)\n      key_str = \"space\";\n    else if (e_key == FL_Enter)\n      key_str = \"return\";\n    else if (e_key == FL_BackSpace)\n      key_str = \"backspace\";\n    else if (e_key == FL_Print)\n      key_str = \"printscreen\";\n    else if (e_key == FL_Pause)\n      key_str = \"pause\";\n    else if (e_key == FL_Home)\n      key_str = \"home\";\n    else if (e_key == FL_End)\n      key_str = \"end\";\n    else if (e_key == FL_Insert)\n      key_str = \"insert\";\n    else if (e_key == FL_Page_Up)\n      key_str = \"pageup\";\n    else if (e_key == FL_Delete)\n      key_str = \"delete\";\n    else if (e_key == FL_Page_Down)\n      key_str = \"pagedown\";\n    else if (e_key == FL_Left)\n      key_str = \"leftarrow\";\n    else if (e_key == FL_Up)\n      key_str = \"uparrow\";\n    else if (e_key == FL_Right)\n      key_str = \"rightarrow\";\n    else if (e_key == FL_Down)\n      key_str = \"downarrow\";\n    else if (e_key == FL_Num_Lock)\n      key_str = \"numlock\";\n    else if (e_key == 0xffaf)\n      key_str = \"divide\";\n    else if (e_key == 0xffaa)\n      key_str = \"multiply\";\n    else if (e_key == 0xffad)\n      key_str = \"subtract\";\n    else if (e_key == 0xffab)\n      key_str = \"add\";\n    else if (e_key == 0xff8d)\n      key_str = \"return\";\n    else if (e_key == 0xffac)\n      key_str = \"separator\";\n    else if (e_key >= 0xffb0 && e_key <= 0xffb9)\n      {\n        tmp_str << \"numpad\" << (e_key - 0xffb0);\n        key_str = tmp_str.str ();\n      }\n    else if (e_key >= (FL_F + 1) && e_key <= (FL_F + 12))\n      {\n        tmp_str << 'f' << (e_key - FL_F);\n        key_str = tmp_str.str ();\n      }\n    else if (e_key == ',')\n      key_str = \"comma\";\n    else if (e_key == '.')\n      key_str = \"period\";\n    else if (e_key == '-')\n      key_str = \"hyphen\";\n    else if (e_key == '^' || e_key == '+' || e_key == '#'\n             || e_key == '<' || e_key == 0xfe03 /*AltGr*/)\n      key_str = \"0\";\n    else if (isalnum (e_key))\n      key_str = std::tolower (e_key);\n    else if (isprint (e_text[0]))\n      key_str = \"0\";\n\n    evt.assign (\"Key\", octave_value (key_str));\n    return evt;\n  }\n\n  Cell modifier2cell (int e_state)\n  {\n    string_vector mod;\n\n    if (e_state & FL_SHIFT)\n      mod.append (std::string (\"shift\"));\n    if (e_state & FL_CTRL)\n      mod.append (std::string (\"control\"));\n    if (e_state & FL_ALT)\n      mod.append (std::string (\"alt\"));\n    if (e_state & FL_COMMAND)\n      mod.append (std::string (\"command\"));\n    return Cell (mod);\n  }\n\n  void resize (int xx, int yy, int ww, int hh)\n  {\n    Fl_Window::resize (xx, yy, ww, hh);\n\n    Matrix bb (1, 4);\n    bb(0) = xx;\n    bb(1) = yy;\n    bb(2) = ww;\n    bb(3) = hh;\n\n    // update outerposition\n    m_fp.set_boundingbox (bb, false, false);\n\n    // update position\n    m_fp.set_boundingbox (outerposition2position (bb), true, false);\n  }\n\n  bool pan_enabled ()\n  {\n    // Getting pan mode property:\n    octave_value ov_pm = m_fp.get___pan_mode__ ();\n\n    octave_scalar_map pm = ov_pm.scalar_map_value ();\n\n    return pm.contents (\"Enable\").string_value () == \"on\";\n  }\n\n  std::string pan_mode ()\n  {\n    // Getting pan mode property:\n    octave_value ov_pm = m_fp.get___pan_mode__ ();\n\n    octave_scalar_map pm = ov_pm.scalar_map_value ();\n\n    return pm.contents (\"Motion\").string_value ();\n  }\n\n  bool rotate_enabled ()\n  {\n    // Getting rotate mode property:\n    octave_value ov_rm = m_fp.get___rotate_mode__ ();\n\n    octave_scalar_map rm = ov_rm.scalar_map_value ();\n\n    return rm.contents (\"Enable\").string_value () == \"on\";\n  }\n\n  int handle (int event)\n  {\n    if (event == FL_FOCUS)\n      return 1;\n\n    graphics_handle gh;\n\n    if (! m_fp.is_beingdeleted ())\n      {\n        // FLTK resends keyboard events with flipped case if all\n        // widgets rejects the event.\n        // See Event Propagation http://www.fltk.org/doc-1.3/events.html\n        static bool key_resent_detected = false;\n\n        gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n        switch (event)\n          {\n          case FL_SHORTCUT:\n            {\n              // check if it a resent event with switched case\n              static int last_event_key = 0;\n              static char last_event_text = 0;\n\n              int e_key = Fl::event_key ();\n              char e_text = Fl::event_text ()[0];\n              key_resent_detected = (e_key == last_event_key\n                                     && std::tolower (last_event_text) == std::tolower (e_text)\n                                     && ((islower (last_event_text) && isupper (e_text))\n                                         || (isupper (last_event_text) && islower (e_text))));\n\n              last_event_key = e_key;\n              last_event_text = e_text;\n            }\n            break;\n\n          case FL_KEYDOWN:\n            {\n              int e_key = Fl::event_key ();\n              const char *e_text = Fl::event_text ();\n              int e_state = Fl::event_state ();\n              octave_scalar_map evt = format_key_event (e_key, e_text, e_state);\n              // FIXME: This should return the graphics handle of the object\n              evt.assign (\"Source\", \"\");\n              evt.assign (\"EventName\", \"KeyPress\");\n\n              m_fp.set_currentcharacter (std::string (e_text));\n\n              if (! m_fp.get_keypressfcn ().isempty ()\n                  && (evt.contents (\"Key\").length () > 0))\n                {\n                  // Update CurrentPoint before callback\n                  if (Fl::event_inside (m_canvas))\n                    {\n                      m_pos_x = Fl::event_x ();\n                      m_pos_y = Fl::event_y () - menu_dy ();\n\n                      set_currentpoint (m_pos_x, m_pos_y);\n\n                      gh = pixel2axes_or_ca (m_pos_x, m_pos_y);\n\n                      if (gh.ok ())\n                        {\n                          m_ax_obj = gh_mgr.get_object (gh);\n                          set_axes_currentpoint (m_ax_obj, m_pos_x, m_pos_y);\n                        }\n                    }\n\n                  m_fp.execute_keypressfcn (evt);\n                }\n\n              // Handle special keys used in toolbar\n              switch (e_key)\n                {\n                case 'a':\n                case 'A':\n                  axis_auto ();\n                  return 1;\n\n                case 'g':\n                case 'G':\n                  toggle_grid ();\n                  return 1;\n\n                case 'p':\n                case 'P':\n                  m_fp.set___mouse_mode__ (\"pan\");\n                  return 1;\n\n                case 'r':\n                case 'R':\n                  m_fp.set___mouse_mode__ (\"rotate\");\n                  return 1;\n                }\n            }\n            break;\n\n          case FL_KEYUP:\n            {\n              int e_key = Fl::event_key ();\n              int e_state = Fl::event_state ();\n              octave_scalar_map evt;\n              if (key_resent_detected && Fl::event_length () == 1)\n                {\n                  // FLTK flipped the case of Fl::event_text because no\n                  // widget wanted the FL_KEYDOWN event.\n                  char tmp_e_text[2];\n                  tmp_e_text[0] = Fl::event_text ()[0];\n                  tmp_e_text[1] = 0;\n                  // Undo the case flip\n                  if (std::islower (tmp_e_text[0]))\n                    tmp_e_text[0] = std::toupper (tmp_e_text[0]);\n                  else\n                    tmp_e_text[0] = std::tolower (tmp_e_text[0]);\n                  evt = format_key_event (e_key, tmp_e_text, e_state);\n                }\n              else\n                {\n                  const char *e_text = Fl::event_text ();\n                  evt = format_key_event (e_key, e_text, e_state);\n                }\n              // FIXME: This should return the graphics handle of the object\n              evt.assign (\"Source\", \"\");\n              evt.assign (\"EventName\", \"KeyRelease\");\n\n              if (! m_fp.get_keyreleasefcn ().isempty ()\n                  && (evt.contents (\"Key\").length () > 0))\n                m_fp.execute_keyreleasefcn (evt);\n              return 1;\n            }\n            break;\n          }\n\n        // Events we only handle if they are in the canvas area.\n        if (Fl::event_inside (m_canvas))\n          switch (event)\n            {\n            case FL_MOVE:\n              pixel2status (pixel2axes_or_ca (Fl::event_x (),\n                                              Fl::event_y () - menu_dy ()),\n                            Fl::event_x (), Fl::event_y () - menu_dy ());\n              return 1;\n\n            case FL_PUSH:\n              m_pos_x = Fl::event_x ();\n              m_pos_y = Fl::event_y () - menu_dy ();\n\n              set_currentpoint (m_pos_x, m_pos_y);\n\n              if (Fl::event_clicks ())\n                m_fp.set_selectiontype (\"open\");\n              else if (Fl::event_button () == FL_MIDDLE_MOUSE\n                       || (Fl::event_button () == FL_LEFT_MOUSE\n                           && Fl::event_shift ()))\n                m_fp.set_selectiontype (\"extend\");\n              else if (Fl::event_button () == FL_RIGHT_MOUSE\n                       || (Fl::event_button () == FL_LEFT_MOUSE\n                           && Fl::event_ctrl ()))\n                m_fp.set_selectiontype (\"alt\");\n              else\n                m_fp.set_selectiontype (\"normal\");\n\n              gh = pixel2axes_or_ca (m_pos_x, m_pos_y);\n\n              if (gh.ok ())\n                {\n                  m_ax_obj = gh_mgr.get_object (gh);\n                  set_axes_currentpoint (m_ax_obj, m_pos_x, m_pos_y);\n                }\n\n              // Ensure windowbuttondownfcn is called after currentpoint\n              // is updated but before calling buttondownfcn.\n              if (! m_fp.get_windowbuttondownfcn ().isempty ())\n                m_fp.execute_windowbuttondownfcn (Fl::event_button ());\n\n              if (gh.ok ())\n                {\n                  m_fp.set_currentobject (m_ax_obj.get_handle ().value ());\n\n                  base_properties& props = m_ax_obj.get_properties ();\n                  if (! props.get_buttondownfcn ().isempty ())\n                    props.execute_buttondownfcn (Fl::event_button ());\n\n                  return 1;\n                }\n              else if (! m_fp.get_buttondownfcn ().isempty ())\n                m_fp.execute_buttondownfcn (Fl::event_button ());\n\n              break;\n\n            case FL_DRAG:\n              if (! m_fp.get_windowbuttonmotionfcn ().isempty ())\n                {\n                  set_currentpoint (Fl::event_x (), Fl::event_y () - menu_dy ());\n                  m_fp.execute_windowbuttonmotionfcn ();\n                }\n\n              if (Fl::event_button () == 1)\n                {\n                  if (m_ax_obj && m_ax_obj.isa (\"axes\"))\n                    {\n                      axes::properties& ap = dynamic_cast<axes::properties&> (m_ax_obj.get_properties ());\n\n                      // Don't pan or rotate legend\n                      if (ap.get_tag () != \"legend\")\n                        {\n                          if (rotate_enabled ())\n                            view2status (m_ax_obj);\n                          else\n                            pixel2status (m_ax_obj, m_pos_x, m_pos_y,\n                                          Fl::event_x (),\n                                          Fl::event_y () - menu_dy ());\n\n                          double x0, y0, x1, y1;\n                          Matrix pos = m_fp.get_boundingbox (true);\n                          pixel2pos (m_ax_obj, m_pos_x, m_pos_y, x0, y0);\n                          pixel2pos (m_ax_obj, Fl::event_x (),\n                                     Fl::event_y () - menu_dy (),\n                                     x1, y1);\n\n                          if (pan_enabled ())\n                            {\n                              std::string mode = pan_mode ();\n\n                              ap.translate_view (mode, x0, x1, y0, y1);\n                            }\n                          else if (rotate_enabled ())\n                            {\n                              double daz, del;\n                              daz = (Fl::event_x () - m_pos_x) / pos(2) * 360;\n                              del = (Fl::event_y () - menu_dy () - m_pos_y)\n                                    / pos(3) * 360;\n                              ap.rotate_view (del, daz);\n                            }\n                        }\n                      else\n                        {\n                          // move the position of the legend\n                          Matrix pos = ap.get_position ().matrix_value ();\n                          pos(0) += double (Fl::event_x () - m_pos_x)\n                                    / m_canvas->w ();\n                          pos(1) -= double (Fl::event_y () - menu_dy () - m_pos_y)\n                                    / m_canvas->h ();\n                          ap.set_position (pos);\n                        }\n\n                      m_pos_x = Fl::event_x ();\n                      m_pos_y = Fl::event_y () - menu_dy ();\n                      mark_modified ();\n                    }\n                  return 1;\n                }\n              else if (Fl::event_button () == 3)\n                {\n                  pixel2status (m_ax_obj, m_pos_x, m_pos_y,\n                                Fl::event_x (), Fl::event_y () - menu_dy ());\n                  Matrix zoom_box (1, 4, 0);\n                  zoom_box(0) = m_pos_x;\n                  zoom_box(1) = m_pos_y;\n                  zoom_box(2) = Fl::event_x ();\n                  zoom_box(3) = Fl::event_y () - menu_dy ();\n                  m_canvas->set_zoom_box (zoom_box);\n                  m_canvas->zoom (true);\n                  mark_modified ();\n                  return 1;\n                }\n\n              break;\n\n            case FL_MOUSEWHEEL:\n              {\n                graphics_object ax\n                  = gh_mgr.get_object (pixel2axes_or_ca (Fl::event_x (),\n                                       Fl::event_y ()\n                                       - menu_dy ()));\n                if (ax && ax.isa (\"axes\"))\n                  {\n                    axes::properties& ap\n                      = dynamic_cast<axes::properties&> (ax.get_properties ());\n\n                    // Control how fast to zoom when using scroll wheel.\n                    double wheel_zoom_speed = ap.get_mousewheelzoom ();\n\n                    // Determine if we're zooming in or out.\n                    const double factor = (Fl::event_dy () < 0\n                                           ? 1 / (1.0 - wheel_zoom_speed)\n                                           : 1.0 - wheel_zoom_speed);\n\n                    // Get the point we're zooming about.\n                    double x1, y1;\n                    pixel2pos (ax, Fl::event_x (), Fl::event_y () - menu_dy (),\n                               x1, y1);\n\n                    // FIXME: should we only zoom about point for 2-D plots?\n\n                    ap.zoom_about_point (\"both\", x1, y1, factor, false);\n                    mark_modified ();\n                    return 1;\n                  }\n              }\n\n              break;\n\n            case FL_RELEASE:\n              if (! m_fp.get_windowbuttonupfcn ().isempty ())\n                {\n                  set_currentpoint (Fl::event_x (),\n                                    Fl::event_y () - menu_dy ());\n                  m_fp.execute_windowbuttonupfcn ();\n                }\n\n              if ((Fl::event_button () == 1) && Fl::event_clicks ())\n                {\n                  // Double click\n                  set_on_ax_obj (\"xlimmode\", \"auto\");\n                  set_on_ax_obj (\"ylimmode\", \"auto\");\n                  set_on_ax_obj (\"zlimmode\", \"auto\");\n                  mark_modified ();\n                  return 1;\n                }\n              if (Fl::event_button () == 3)\n                {\n                  // End of drag -- zoom.\n                  if (m_canvas->zoom ())\n                    {\n                      m_canvas->zoom (false);\n                      double x0, y0, x1, y1;\n                      if (m_ax_obj && m_ax_obj.isa (\"axes\"))\n                        {\n                          axes::properties& ap = dynamic_cast<axes::properties&>\n                                                 (m_ax_obj.get_properties ());\n                          pixel2pos (m_ax_obj, m_pos_x, m_pos_y, x0, y0);\n                          int pos_x1 = Fl::event_x ();\n                          int pos_y1 = Fl::event_y () - menu_dy ();\n                          pixel2pos (m_ax_obj, pos_x1, pos_y1, x1, y1);\n                          Matrix xl (1, 2, 0);\n                          Matrix yl (1, 2, 0);\n                          int dx = abs (m_pos_x - pos_x1);\n                          int dy = abs (m_pos_y - pos_y1);\n                          // Smallest zoom box must be 4 pixels square\n                          if ((dx > 4) && (dy > 4))\n                            {\n                              if (x0 < x1)\n                                {\n                                  xl(0) = x0;\n                                  xl(1) = x1;\n                                }\n                              else\n                                {\n                                  xl(0) = x1;\n                                  xl(1) = x0;\n                                }\n                              if (y0 < y1)\n                                {\n                                  yl(0) = y0;\n                                  yl(1) = y1;\n                                }\n                              else\n                                {\n                                  yl(0) = y1;\n                                  yl(1) = y0;\n                                }\n                              ap.zoom (\"both\", xl, yl);\n                            }\n                          mark_modified ();\n                          return 1;\n                        }\n                    }\n                }\n              break;\n            }\n      }\n\n    return Fl_Window::handle (event);\n  }\n};\n\nclass figure_manager\n{\nprivate:\n\n  figure_manager () = default;\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (figure_manager)\n\n  ~figure_manager ()\n  {\n    close_all ();\n  }\n\n  static bool instance_ok ()\n  {\n    bool retval = true;\n\n    if (! s_instance)\n      s_instance = new figure_manager ();\n\n    return retval;\n  }\n\n  static void close_all ()\n  {\n    if (instance_ok ())\n      s_instance->do_close_all ();\n  }\n\n  static void new_window (figure::properties& fp)\n  {\n    if (instance_ok ())\n      s_instance->do_new_window (fp);\n  }\n\n  static void delete_window (int idx)\n  {\n    if (instance_ok ())\n      s_instance->do_delete_window (idx);\n  }\n\n  static void delete_window (const std::string& idx_str)\n  {\n    delete_window (str2idx (idx_str));\n  }\n\n  static void renumber_figure (const std::string& idx_str, double new_number)\n  {\n    if (instance_ok ())\n      s_instance->do_renumber_figure (str2idx (idx_str), new_number);\n  }\n\n  static void toggle_window_visibility (int idx, bool is_visible)\n  {\n    if (instance_ok ())\n      s_instance->do_toggle_window_visibility (idx, is_visible);\n  }\n\n  static void toggle_window_visibility (const std::string& idx_str,\n                                        bool is_visible)\n  {\n    toggle_window_visibility (str2idx (idx_str), is_visible);\n  }\n\n  static void mark_modified (int idx)\n  {\n    if (instance_ok ())\n      s_instance->do_mark_modified (idx);\n  }\n\n  static void mark_modified (const graphics_handle& gh)\n  {\n    mark_modified (hnd2idx (gh));\n  }\n\n  static void set_name (int idx)\n  {\n    if (instance_ok ())\n      s_instance->do_set_name (idx);\n  }\n\n  static void set_name (const std::string& idx_str)\n  {\n    set_name (str2idx (idx_str));\n  }\n\n  static Matrix get_size (int idx)\n  {\n    return instance_ok () ? s_instance->do_get_size (idx) : Matrix ();\n  }\n\n  static Matrix get_size (const graphics_handle& gh)\n  {\n    return get_size (hnd2idx (gh));\n  }\n\n  static void print (const graphics_handle& gh, const std::string& cmd,\n                     const std::string& term)\n  {\n    if (instance_ok ())\n      s_instance->do_print (hnd2idx (gh), cmd, term);\n  }\n\n  static uint8NDArray get_pixels (const graphics_handle& gh)\n  {\n    uint8NDArray retval;\n    if (instance_ok ())\n      retval = s_instance->do_get_pixels (hnd2idx (gh));\n\n    return retval;\n  }\n\n  static void uimenu_update (const graphics_handle& figh,\n                             const graphics_handle& uimenuh, int id)\n  {\n    if (instance_ok ())\n      s_instance->do_uimenu_update (hnd2idx (figh), uimenuh, id);\n  }\n\n  static void update_canvas (const graphics_handle& gh,\n                             const graphics_handle& ca)\n  {\n    if (instance_ok ())\n      s_instance->do_update_canvas (hnd2idx (gh), ca);\n  }\n\n  static void update_boundingbox (const std::string& fig_idx_str,\n                                  bool internal)\n  {\n    if (instance_ok ())\n      s_instance->do_update_boundingbox (str2idx (fig_idx_str), internal);\n  }\n\n  static void toggle_menubar_visibility (const std::string& fig_idx_str,\n                                         bool menubar_is_figure)\n  {\n    if (instance_ok ())\n      s_instance->do_toggle_menubar_visibility (str2idx (fig_idx_str),\n                                                menubar_is_figure);\n  }\n\nprivate:\n\n  static figure_manager *s_instance;\n\n  // Singleton -- hide all of the above.\n\n  static int s_curr_index;\n\n  typedef std::map<int, plot_window *> window_map;\n\n  typedef window_map::iterator wm_iterator;\n\n  window_map m_windows;\n\n  static std::string s_fltk_idx_header;\n\n  void do_close_all ()\n  {\n    for (auto& win : m_windows)\n      delete win.second;\n    m_windows.clear ();\n  }\n\n  void do_new_window (figure::properties& fp)\n  {\n    int idx = figprops2idx (fp);\n\n    if (idx >= 0 && m_windows.find (idx) == m_windows.end ())\n      {\n        Matrix pos = fp.get_outerposition ().matrix_value ();\n        bool internal = false;\n        // check if figure::properties::outerposition is default -1.0\n        if (pos(2) != -1.0 && pos(3) != -1.0)\n          {\n            pos = fp.get_boundingbox (internal);\n          }\n        else\n          {\n            // use position\n            internal = true;\n            pos = fp.get_boundingbox (internal);\n          }\n\n        idx2figprops (s_curr_index, fp);\n\n        m_windows[s_curr_index++] = new plot_window (pos(0), pos(1), pos(2), pos(3),\n            fp, internal);\n      }\n  }\n\n  void do_delete_window (int idx)\n  {\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      {\n        delete win->second;\n        m_windows.erase (win);\n      }\n  }\n\n  void do_renumber_figure (int idx, double new_number)\n  {\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      win->second->renumber (new_number);\n  }\n\n  void do_toggle_window_visibility (int idx, bool is_visible)\n  {\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      {\n        if (is_visible)\n          {\n            win->second->show ();\n            win->second->show_canvas ();\n          }\n        else\n          win->second->hide ();\n\n      }\n  }\n\n  void do_toggle_menubar_visibility (int fig_idx, bool menubar_is_figure)\n  {\n    wm_iterator win = m_windows.find (fig_idx);\n\n    if (win != m_windows.end ())\n      {\n        if (menubar_is_figure)\n          win->second->show_menubar ();\n        else\n          win->second->hide_menubar ();\n\n        win->second->redraw ();\n      }\n  }\n\n  void do_mark_modified (int idx)\n  {\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      {\n        win->second->mark_modified ();\n      }\n  }\n\n  void do_set_name (int idx)\n  {\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      win->second->set_name ();\n  }\n\n  Matrix do_get_size (int idx)\n  {\n    Matrix sz (1, 2, 0.0);\n\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      {\n        sz(0) = win->second->w ();\n        sz(1) = win->second->h ();\n      }\n\n    return sz;\n  }\n\n  void do_print (int idx, const std::string& cmd, const std::string& term)\n  {\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      win->second->print (cmd, term);\n  }\n\n  uint8NDArray do_get_pixels (int idx)\n  {\n    uint8NDArray retval;\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      retval = win->second->get_pixels ();\n\n    return retval;\n  }\n\n  void do_uimenu_update (int idx, const graphics_handle& gh, int id)\n  {\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      win->second->uimenu_update (gh, id);\n  }\n\n  void do_update_canvas (int idx, const graphics_handle& ca)\n  {\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      {\n        if (ca.ok ())\n          win->second->show_canvas ();\n        else\n          win->second->hide_canvas ();\n      }\n  }\n\n  void do_update_boundingbox (int idx, bool internal)\n  {\n    wm_iterator win = m_windows.find (idx);\n\n    if (win != m_windows.end ())\n      win->second->update_boundingbox (internal);\n  }\n\n  static int str2idx (const caseless_str& clstr)\n  {\n    int ind;\n    if (clstr.find (s_fltk_idx_header, 0) == 0)\n      {\n        std::istringstream istr (clstr.substr (s_fltk_idx_header.size ()));\n        if (istr >> ind)\n          return ind;\n      }\n\n    error (\"figure_manager: could not recognize fltk index\");\n  }\n\n  void idx2figprops (int idx, figure::properties& fp)\n  {\n    std::ostringstream ind_str;\n    ind_str << s_fltk_idx_header << idx;\n    fp.set___plot_stream__ (ind_str.str ());\n  }\n\n  static int figprops2idx (const figure::properties& fp)\n  {\n    if (fp.get___graphics_toolkit__ () == FLTK_GRAPHICS_TOOLKIT_NAME)\n      {\n        octave_value ps = fp.get___plot_stream__ ();\n        if (ps.is_string ())\n          return str2idx (ps.string_value ());\n        else\n          return 0;\n      }\n\n    error (\"figure_manager: figure is not fltk\");\n  }\n\n  static int hnd2idx (double h)\n  {\n    gh_manager& gh_mgr = octave::__get_gh_manager__ ();\n\n    graphics_object fobj = gh_mgr.get_object (h);\n\n    if (fobj &&  fobj.isa (\"figure\"))\n      {\n        figure::properties& fp\n          = dynamic_cast<figure::properties&> (fobj.get_properties ());\n        return figprops2idx (fp);\n      }\n\n    error (\"figure_manager: H (= %g) is not a figure\", h);\n  }\n\n  static int hnd2idx (const graphics_handle& fh)\n  {\n    return hnd2idx (fh.value ());\n  }\n};\n\nfigure_manager *figure_manager::s_instance = nullptr;\n\nstd::string figure_manager::s_fltk_idx_header=\"fltk index=\";\nint figure_manager::s_curr_index = 1;\n\nstatic bool toolkit_loaded = false;\n\nclass fltk_graphics_toolkit : public octave::base_graphics_toolkit\n{\npublic:\n\n  fltk_graphics_toolkit (octave::interpreter& interp)\n    : octave::base_graphics_toolkit (FLTK_GRAPHICS_TOOLKIT_NAME),\n      m_interpreter (interp), m_input_event_hook_fcn_id ()\n  {\n    static bool warned = false;\n\n    if (! warned)\n      {\n        warning_with_id\n        (\"Octave:fltk-graphics\",\n         \"using the fltk graphics toolkit is discouraged\\n\\\n\\n\\\nThe FLTK graphics toolkit is not actively maintained and has a number\\n\\\nof limitations that are unlikely to be fixed.\\n\\\nThe qt toolkit is recommended instead.\\n\");\n\n        warned = true;\n      }\n\n    Fl::visual (FL_RGB);\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (fltk_graphics_toolkit)\n\n  ~fltk_graphics_toolkit () = default;\n\n  bool is_valid () const { return true; }\n\n  bool initialize (const graphics_object& go)\n  {\n    if (go.isa (\"figure\")\n        || go.isa (\"uimenu\"))\n      {\n        if (go.isa (\"uimenu\"))\n          update (go, uimenu::properties::ID_LABEL);\n\n        return true;\n      }\n\n    return false;\n  }\n\n  void finalize (const graphics_object& go)\n  {\n    if (go.isa (\"figure\"))\n      {\n        octave_value ov = go.get (caseless_str (\"__plot_stream__\"));\n\n        if (! ov.isempty ())\n          figure_manager::delete_window (ov.string_value ());\n      }\n  }\n\n  void uimenu_set___fltk_label__ (graphics_object uimenu_obj)\n  {\n    if (uimenu_obj.valid_object ())\n      {\n        uimenu::properties& uimenup\n          = dynamic_cast<uimenu::properties&> (uimenu_obj.get_properties ());\n        std::string fltk_label = uimenup.get_label ();\n\n        gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n        graphics_object go = gh_mgr.get_object (uimenu_obj.get_parent ());\n\n        if (go.isa (\"uimenu\"))\n          fltk_label = dynamic_cast<const uimenu::properties&>\n                       (go.get_properties ()).get___fltk_label__ ()\n                       + '/'\n                       + fltk_label;\n        else if (go.isa (\"figure\") || go.isa (\"uicontextmenu\"))\n          ;\n        else\n          error (\"invalid parent object\\n\");\n\n        uimenup.set___fltk_label__ (fltk_label);\n      }\n  }\n\n  void update (const graphics_object& go, int id)\n  {\n    if (go.isa (\"figure\"))\n      {\n        octave_value ov = go.get (caseless_str (\"__plot_stream__\"));\n\n        if (! ov.isempty ())\n          {\n            const figure::properties& fp\n              = dynamic_cast<const figure::properties&> (go.get_properties ());\n\n            switch (id)\n              {\n              case base_properties::ID_VISIBLE:\n                figure_manager::toggle_window_visibility (ov.string_value (),\n                    fp.is_visible ());\n                break;\n\n              case figure::properties::ID_MENUBAR:\n                figure_manager::toggle_menubar_visibility\n                (ov.string_value (), fp.menubar_is (\"figure\"));\n                break;\n\n              case figure::properties::ID_CURRENTAXES:\n                figure_manager::update_canvas (go.get_handle (),\n                                               fp.get_currentaxes ());\n                break;\n\n              case figure::properties::ID_NAME:\n              case figure::properties::ID_NUMBERTITLE:\n                figure_manager::set_name (ov.string_value ());\n                break;\n\n              case figure::properties::ID_INTEGERHANDLE:\n                {\n                  std::string tmp = ov.string_value ();\n                  graphics_handle gh = fp.get___myhandle__ ();\n                  figure_manager::renumber_figure (tmp, gh.value ());\n                  figure_manager::set_name (tmp);\n                }\n                break;\n\n              case figure::properties::ID_POSITION:\n                figure_manager::update_boundingbox (ov.string_value (), true);\n                break;\n\n              case figure::properties::ID_OUTERPOSITION:\n                figure_manager::update_boundingbox (ov.string_value (), false);\n                break;\n              }\n          }\n      }\n    else if (go.isa (\"uimenu\"))\n      {\n        if (id == uimenu::properties::ID_LABEL)\n          uimenu_set___fltk_label__ (go);\n\n        graphics_object fig = go.get_ancestor (\"figure\");\n        figure_manager::uimenu_update (fig.get_handle (), go.get_handle (), id);\n      }\n  }\n\n  void redraw_figure (const graphics_object& go) const\n  {\n    // We scan all figures and add those which use FLTK.\n\n    gh_manager& gh_mgr = m_interpreter.get_gh_manager ();\n\n    graphics_object obj = gh_mgr.get_object (0);\n\n    if (obj && obj.isa (\"root\"))\n      {\n        base_properties& props = obj.get_properties ();\n        Matrix children = props.get_all_children ();\n\n        for (octave_idx_type n = 0; n < children.numel (); n++)\n          {\n            graphics_object fobj = gh_mgr.get_object (children (n));\n\n            if (fobj && fobj.isa (\"figure\"))\n              {\n                figure::properties& fp\n                  = dynamic_cast<figure::properties&> (fobj.get_properties ());\n\n                if (fp.get___graphics_toolkit__ ()\n                    == FLTK_GRAPHICS_TOOLKIT_NAME)\n                  figure_manager::new_window (fp);\n              }\n          }\n      }\n\n    figure_manager::mark_modified (go.get_handle ());\n    Fl::check ();\n  }\n\n  void print_figure (const graphics_object& go,\n                     const std::string& term,\n                     const std::string& file_cmd,\n                     const std::string& /*debug_file*/) const\n  {\n    figure_manager::print (go.get_handle (), file_cmd, term);\n  }\n\n  uint8NDArray get_pixels (const graphics_object& go) const\n  {\n    return figure_manager::get_pixels (go.get_handle ());\n  }\n\n  Matrix get_canvas_size (const graphics_handle& fh) const\n  {\n    return figure_manager::get_size (fh);\n  }\n\n  /*\n    double get_screen_resolution () const\n    {\n      // FLTK doesn't give this info.\n      return 72.0;\n\n      // FIXME: FLTK >= 1.3.0 could do this with Fl::screen_dpi (h, v, n)\n      // but do we need it?\n    }\n  */\n\n  Matrix get_screen_size () const\n  {\n    Matrix sz (1, 2, 0.0);\n    sz(0) = Fl::w ();\n    sz(1) = Fl::h ();\n    return sz;\n  }\n\n  void close ()\n  {\n    if (toolkit_loaded)\n      {\n        m_interpreter.munlock (\"__init_fltk__\");\n\n        octave_value_list args = m_input_event_hook_fcn_id;\n        args.append (false);\n        Fremove_input_event_hook (m_interpreter, args);\n        m_input_event_hook_fcn_id = octave_value_list ();\n\n        figure_manager::close_all ();\n      }\n  }\n\n  void set_input_event_hook_id (const octave_value_list& id)\n  {\n    m_input_event_hook_fcn_id = id;\n  }\n\nprivate:\n\n  octave::interpreter& m_interpreter;\n\n  octave_value_list m_input_event_hook_fcn_id;\n};\n\n#endif\n\nDEFMETHOD_DLD (__fltk_check__, interp, , ,\n               doc: /* -*- texinfo -*-\n@deftypefn {} {} __fltk_check__ ()\nUndocumented internal function.  Calls Fl::check ()\n@end deftypefn */)\n{\n#if defined (HAVE_FLTK)\n  Fl::check ();\n\n  if (Vdrawnow_requested)\n    Fdrawnow (interp);\n\n  return octave_value_list ();\n#else\n  octave_unused_parameter (interp);\n\n  err_disabled_feature (\"__fltk_check__\", \"OpenGL and FLTK\");\n#endif\n}\n\n// Initialize the fltk graphics toolkit.\n\nDEFMETHOD_DLD (__init_fltk__, interp, , ,\n               doc: /* -*- texinfo -*-\n@deftypefn {} {} __init_fltk__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_FLTK)\n  octave::display_info& dpy_info = interp.get_display_info ();\n\n  if (! dpy_info.display_available ())\n    error (\"__init_fltk__: no graphics DISPLAY available\");\n  else if (! toolkit_loaded)\n    {\n      interp.mlock ();\n\n      octave::gtk_manager& gtk_mgr = interp.get_gtk_manager ();\n\n      fltk_graphics_toolkit *fltk = new fltk_graphics_toolkit (interp);\n      octave::graphics_toolkit tk (fltk);\n      gtk_mgr.load_toolkit (tk);\n      toolkit_loaded = true;\n\n      octave_value fcn (new octave_builtin (F__fltk_check__));\n      octave_value fcn_handle (new octave_fcn_handle (fcn));\n\n      octave_value_list id = Fadd_input_event_hook (interp,\n                             ovl (fcn_handle), 1);\n\n      fltk->set_input_event_hook_id (id);\n    }\n\n  return octave_value_list ();\n\n#else\n  octave_unused_parameter (interp);\n\n  err_disabled_feature (\"__init_fltk__\", \"OpenGL and FLTK\");\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/__init_gnuplot__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nTo initialize:\n\n  graphics_toolkit (\"gnuplot\");\n  plot (randn (1e3, 1));\n\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"dMatrix.h\"\n#include \"file-stat.h\"\n#include \"oct-env.h\"\n\n#include \"build-env.h\"\n#include \"builtin-defun-decls.h\"\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"graphics.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n// PKG_ADD: if (__have_gnuplot__ ()) register_graphics_toolkit (\"gnuplot\"); endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass gnuplot_graphics_toolkit : public octave::base_graphics_toolkit\n{\npublic:\n\n  gnuplot_graphics_toolkit (octave::interpreter& interp)\n    : octave::base_graphics_toolkit (\"gnuplot\"), m_interpreter (interp)\n  {\n    static bool warned = false;\n\n    if (! warned)\n      {\n        warning_with_id\n        (\"Octave:gnuplot-graphics\",\n         \"using the gnuplot graphics toolkit is discouraged\\n\\\n\\n\\\nThe gnuplot graphics toolkit is not actively maintained and has a number\\n\\\nof limitations that are unlikely to be fixed.  Communication with gnuplot\\n\\\nuses a one-directional pipe and limited information is passed back to the\\n\\\nOctave interpreter so most changes made interactively in the plot window\\n\\\nwill not be reflected in the graphics properties managed by Octave.  For\\n\\\nexample, if the plot window is closed with a mouse click, Octave will not\\n\\\nbe notified and will not update its internal list of open figure windows.\\n\\\nThe qt toolkit is recommended instead.\\n\");\n\n        warned = true;\n      }\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (gnuplot_graphics_toolkit)\n\n  ~gnuplot_graphics_toolkit () = default;\n\n  bool is_valid () const { return true; }\n\n  bool initialize (const graphics_object& go)\n  {\n    return go.isa (\"figure\");\n  }\n\n  void finalize (const graphics_object& go)\n  {\n    if (go.isa (\"figure\"))\n      {\n        const figure::properties& props\n          = dynamic_cast<const figure::properties&> (go.get_properties ());\n\n        send_quit (props.get___plot_stream__ ());\n      }\n  }\n\n  void update (const graphics_object& go, int id)\n  {\n    if (go.isa (\"figure\"))\n      {\n        graphics_object obj (go);\n\n        figure::properties& props\n          = dynamic_cast<figure::properties&> (obj.get_properties ());\n\n        switch (id)\n          {\n          case base_properties::ID_VISIBLE:\n            if (! props.is_visible ())\n              {\n                send_quit (props.get___plot_stream__ ());\n                props.set___plot_stream__ (Matrix ());\n                props.set_graphicssmoothing (false);\n              }\n            break;\n          }\n      }\n  }\n\n  void redraw_figure (const graphics_object& go) const\n  {\n    static bool drawnow_executing = false;\n\n    // Prevent recursion\n    if (! drawnow_executing)\n      {\n        octave::unwind_protect_var<bool> restore_var (drawnow_executing, true);\n\n        octave_value_list args;\n        args(0) = go.get_handle ().as_octave_value ();\n        m_interpreter.feval (\"__gnuplot_drawnow__\", args);\n      }\n  }\n\n  void print_figure (const graphics_object& go, const std::string& term,\n                     const std::string& file,\n                     const std::string& debug_file) const\n  {\n    octave_value_list args;\n    if (! debug_file.empty ())\n      args(3) = debug_file;\n    args(2) = file;\n    args(1) = term;\n    args(0) = go.get_handle ().as_octave_value ();\n    m_interpreter.feval (\"__gnuplot_drawnow__\", args);\n  }\n\n  Matrix get_canvas_size (const graphics_handle&) const\n  {\n    Matrix sz (1, 2, 0.0);\n    return sz;\n  }\n\n  double get_screen_resolution () const\n  { return 72.0; }\n\n  Matrix get_screen_size () const\n  { return Matrix (1, 2, 0.0); }\n\n  void close ()\n  {\n    if (m_interpreter.mislocked (\"__init_gnuplot__\"))\n      m_interpreter.munlock (\"__init_gnuplot__\");\n  }\n\nprivate:\n\n  void send_quit (const octave_value& pstream) const\n  {\n    if (! pstream.isempty ())\n      {\n        octave_value_list args;\n        Matrix fids = pstream.matrix_value ();\n\n        octave::Ffputs (m_interpreter, ovl (fids(0), \"\\nquit;\\n\"));\n\n        octave::Ffflush (m_interpreter, ovl (fids(0)));\n        octave::Fpclose (m_interpreter, ovl (fids(0)));\n\n        if (fids.numel () > 1)\n          {\n            octave::Fpclose (m_interpreter, ovl (fids(1)));\n\n            if (fids.numel () > 2)\n              octave::Fwaitpid (ovl (fids(2)));\n          }\n      }\n  }\n\n  octave::interpreter& m_interpreter;\n};\n\nstatic bool\nhave_gnuplot_binary (interpreter& interp)\n{\n  const std::string exeext = octave::build_env::EXEEXT;\n  const std::string path = octave::sys::env::getenv (\"PATH\");\n  bool retval = false;\n\n  try\n    {\n      octave_value_list tmp\n        = interp.feval (\"gnuplot_binary\", octave_value_list ());\n\n      if (tmp(0).is_string () && ! tmp(0).isempty ())\n        {\n          std::string gnuplot_binary = tmp(0).string_value ();\n\n          string_vector args (gnuplot_binary);\n          std::string gnuplot_path = octave::search_path_for_file (path, args);\n\n          octave::sys::file_stat fs (gnuplot_path);\n\n          if (! fs.exists () && ! exeext.empty ())\n            {\n              args[0] += exeext;\n\n              gnuplot_path = octave::search_path_for_file (path, args);\n\n              fs = octave::sys::file_stat (gnuplot_path);\n            }\n\n          retval = fs.exists ();\n        }\n    }\n  catch (const octave::execution_exception&)\n    {\n      interp.recover_from_exception ();\n    }\n\n  return retval;\n}\n\n// Initialize the gnuplot graphics toolkit.\n\nDEFMETHOD_DLD (__init_gnuplot__, interp, , ,\n               doc: /* -*- texinfo -*-\n@deftypefn {} {} __init_gnuplot__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (! have_gnuplot_binary (interp))\n    error (\"__init_gnuplot__: the gnuplot program is not available, see 'gnuplot_binary'\");\n  else if (! interp.mislocked (\"__init_gnuplot__\"))\n    {\n      gtk_manager& gtk_mgr = interp.get_gtk_manager ();\n\n      graphics_toolkit tk (new gnuplot_graphics_toolkit (interp));\n      gtk_mgr.load_toolkit (tk);\n\n      interp.mlock ();\n    }\n\n  return octave_value_list ();\n}\n\nDEFMETHOD_DLD (__have_gnuplot__, interp, , ,\n               doc: /* -*- texinfo -*-\n@deftypefn {} {@var{gnuplot_available} =} __have_gnuplot__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  return ovl (have_gnuplot_binary (interp));\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/__ode15__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"dSparse.h\"\n#include \"f77-fcn.h\"\n#include \"lo-utils.h\"\n\n#include \"Cell.h\"\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n\n#if defined (HAVE_SUNDIALS)\n\n#  if defined (HAVE_NVECTOR_NVECTOR_SERIAL_H)\n#    include <nvector/nvector_serial.h>\n#  endif\n\n#  if defined (HAVE_IDA_IDA_H)\n#    include <ida/ida.h>\n#  elif defined (HAVE_IDA_H)\n#    include <ida.h>\n#  endif\n#  if defined (HAVE_IDA_IDA_DIRECT_H)\n#    include <ida/ida_direct.h>\n#  elif defined (HAVE_IDA_DIRECT_H)\n#    include <ida_direct.h>\n#  endif\n\n#  if defined (HAVE_SUNLINSOL_SUNLINSOL_DENSE_H)\n#    include <sunlinsol/sunlinsol_dense.h>\n#  endif\n\n#  if defined (HAVE_SUNLINSOL_SUNLINSOL_KLU_H)\n#    if defined (HAVE_KLU_H)\n#      include <klu.h>\n#    endif\n#    if defined (HAVE_KLU_KLU_H)\n#      include <klu/klu.h>\n#    endif\n#    if defined (HAVE_SUITESPARSE_KLU_H)\n#      include <suitesparse/klu.h>\n#    endif\n#    include <sunlinsol/sunlinsol_klu.h>\n#  endif\n\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_SUNDIALS)\n\n#  if ! defined (HAVE_IDASETJACFN) && defined (HAVE_IDADLSSETJACFN)\nstatic inline int\nIDASetJacFn (void *ida_mem, IDADlsJacFn jac)\n{\n  return IDADlsSetJacFn (ida_mem, jac);\n}\n#  endif\n\n#  if ! defined (HAVE_IDASETLINEARSOLVER) && defined (HAVE_IDADLSSETLINEARSOLVER)\nstatic inline int\nIDASetLinearSolver (void *ida_mem, SUNLinearSolver LS, SUNMatrix A)\n{\n  return IDADlsSetLinearSolver (ida_mem, LS, A);\n}\n#  endif\n\n#  if ! defined (HAVE_SUNLINSOL_DENSE) && defined (HAVE_SUNDENSELINEARSOLVER)\nstatic inline SUNLinearSolver\nSUNLinSol_Dense (N_Vector y, SUNMatrix A)\n{\n  return SUNDenseLinearSolver (y, A);\n}\n#  endif\n\n#  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)\n#    if ! defined (HAVE_SUNLINSOL_KLU) && defined (HAVE_SUNKLU)\nstatic inline SUNLinearSolver\nSUNLinSol_KLU (N_Vector y, SUNMatrix A)\n{\n  return SUNKLU (y, A);\n}\n#    endif\n#  endif\n\nstatic inline OCTAVE_SUNREALTYPE *\nnv_data_s (N_Vector& v)\n{\n#  if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n  // Disable warning from GCC about old-style casts in Sundials\n  // macro expansions.  Do this in a function so that this\n  // diagnostic may still be enabled for the rest of the file.\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#  endif\n\n  return NV_DATA_S (v);\n\n#  if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n  // Restore prevailing warning state for remainder of the file.\n#   pragma GCC diagnostic pop\n#  endif\n}\n\nclass IDA\n{\npublic:\n\n  typedef\n  ColumnVector (*DAERHSFuncIDA) (const ColumnVector& x,\n                                 const ColumnVector& xdot,\n                                 OCTAVE_SUNREALTYPE t,\n                                 const octave_value& idaf);\n\n  typedef\n  Matrix (*DAEJacFuncDense) (const ColumnVector& x,\n                             const ColumnVector& xdot, OCTAVE_SUNREALTYPE t,\n                             OCTAVE_SUNREALTYPE cj, const octave_value& idaj);\n\n  typedef\n  SparseMatrix (*DAEJacFuncSparse) (const ColumnVector& x,\n                                    const ColumnVector& xdot,\n                                    OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj,\n                                    const octave_value& idaj);\n\n  typedef\n  Matrix (*DAEJacCellDense) (Matrix *dfdy, Matrix *dfdyp,\n                             OCTAVE_SUNREALTYPE cj);\n\n  typedef\n  SparseMatrix (*DAEJacCellSparse) (SparseMatrix *dfdy,\n                                    SparseMatrix *dfdyp, OCTAVE_SUNREALTYPE cj);\n\n  //Default\n  IDA ()\n    : m_t0 (0.0), m_y0 (), m_yp0 (), m_havejac (false), m_havejacfcn (false),\n      m_havejacsparse (false), m_mem (nullptr), m_num (), m_ida_fcn (),\n      m_ida_jac (), m_dfdy (nullptr), m_dfdyp (nullptr), m_spdfdy (nullptr),\n      m_spdfdyp (nullptr), m_fcn (nullptr), m_jacfcn (nullptr),\n      m_jacspfcn (nullptr), m_jacdcell (nullptr), m_jacspcell (nullptr),\n      m_sunJacMatrix (nullptr), m_sunLinearSolver (nullptr)\n  { }\n\n\n  IDA (OCTAVE_SUNREALTYPE t, ColumnVector y, ColumnVector yp,\n       const octave_value& ida_fcn, DAERHSFuncIDA daefun)\n    : m_t0 (t), m_y0 (y), m_yp0 (yp), m_havejac (false), m_havejacfcn (false),\n      m_havejacsparse (false), m_mem (nullptr), m_num (), m_ida_fcn (ida_fcn),\n      m_ida_jac (), m_dfdy (nullptr), m_dfdyp (nullptr), m_spdfdy (nullptr),\n      m_spdfdyp (nullptr), m_fcn (daefun), m_jacfcn (nullptr),\n      m_jacspfcn (nullptr), m_jacdcell (nullptr), m_jacspcell (nullptr),\n      m_sunJacMatrix (nullptr), m_sunLinearSolver (nullptr)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (IDA)\n\n  ~IDA ()\n  {\n    IDAFree (&m_mem);\n    SUNLinSolFree (m_sunLinearSolver);\n    SUNMatDestroy (m_sunJacMatrix);\n#  if defined (HAVE_SUNDIALS_SUNCONTEXT)\n    SUNContext_Free (&m_sunContext);\n#  endif\n  }\n\n  IDA&\n  set_jacobian (const octave_value& jac, DAEJacFuncDense j)\n  {\n    m_jacfcn = j;\n    m_ida_jac = jac;\n    m_havejac = true;\n    m_havejacfcn = true;\n    m_havejacsparse = false;\n\n    return *this;\n  }\n\n  IDA&\n  set_jacobian (const octave_value& jac, DAEJacFuncSparse j)\n  {\n    m_jacspfcn = j;\n    m_ida_jac = jac;\n    m_havejac = true;\n    m_havejacfcn = true;\n    m_havejacsparse = true;\n\n    return *this;\n  }\n\n  IDA&\n  set_jacobian (Matrix *dy, Matrix *dyp, DAEJacCellDense j)\n  {\n    m_jacdcell = j;\n    m_dfdy = dy;\n    m_dfdyp = dyp;\n    m_havejac = true;\n    m_havejacfcn = false;\n    m_havejacsparse = false;\n\n    return *this;\n  }\n\n  IDA&\n  set_jacobian (SparseMatrix *dy, SparseMatrix *dyp,\n                DAEJacCellSparse j)\n  {\n    m_jacspcell = j;\n    m_spdfdy = dy;\n    m_spdfdyp = dyp;\n    m_havejac = true;\n    m_havejacfcn = false;\n    m_havejacsparse = true;\n\n    return *this;\n  }\n\n  void set_userdata ();\n\n  void initialize ();\n\n  static ColumnVector NVecToCol (N_Vector& v, octave_f77_int_type n);\n\n#  if defined (HAVE_SUNDIALS_SUNCONTEXT)\n  N_Vector ColToNVec (const ColumnVector& data, octave_f77_int_type n);\n#  else\n  static N_Vector ColToNVec (const ColumnVector& data, octave_f77_int_type n);\n#  endif\n\n  void\n  set_up (const ColumnVector& y);\n\n  void\n  set_tolerance (ColumnVector& abstol, OCTAVE_SUNREALTYPE reltol);\n\n  void\n  set_tolerance (OCTAVE_SUNREALTYPE abstol, OCTAVE_SUNREALTYPE reltol);\n\n  static int\n  resfun (OCTAVE_SUNREALTYPE t, N_Vector yy, N_Vector yyp,\n          N_Vector rr, void *user_data);\n\n  void\n  resfun_impl (OCTAVE_SUNREALTYPE t, N_Vector& yy,\n               N_Vector& yyp, N_Vector& rr);\n  static int\n  jacdense (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj, N_Vector yy,\n            N_Vector yyp, N_Vector, SUNMatrix JJ, void *user_data, N_Vector,\n            N_Vector, N_Vector)\n  {\n    IDA *self = static_cast<IDA *> (user_data);\n    self->jacdense_impl (t, cj, yy, yyp, JJ);\n    return 0;\n  }\n\n  void\n  jacdense_impl (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj,\n                 N_Vector& yy, N_Vector& yyp, SUNMatrix& JJ);\n\n#  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)\n  static int\n  jacsparse (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj, N_Vector yy,\n             N_Vector yyp, N_Vector, SUNMatrix Jac, void *user_data, N_Vector,\n             N_Vector, N_Vector)\n  {\n    IDA *self = static_cast<IDA *> (user_data);\n    self->jacsparse_impl (t, cj, yy, yyp, Jac);\n    return 0;\n  }\n\n  void\n  jacsparse_impl (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj,\n                  N_Vector& yy, N_Vector& yyp, SUNMatrix& Jac);\n#  endif\n\n  void set_maxstep (OCTAVE_SUNREALTYPE maxstep);\n\n  void set_initialstep (OCTAVE_SUNREALTYPE initialstep);\n\n  bool\n  interpolate (octave_idx_type& cont, Matrix& output, ColumnVector& tout,\n               int refine, OCTAVE_SUNREALTYPE tend, bool haveoutputfcn,\n               bool haveoutputsel, const octave_value& output_fcn,\n               ColumnVector& outputsel, bool haveeventfunction,\n               const octave_value& event_fcn, ColumnVector& te,\n               Matrix& ye, ColumnVector& ie, ColumnVector& oldval,\n               ColumnVector& oldisterminal, ColumnVector& olddir,\n               octave_idx_type& temp, ColumnVector& yold,\n               const octave_idx_type num_event_args);\n\n  bool\n  outputfun (const octave_value& output_fcn, bool haveoutputsel,\n             const ColumnVector& output, OCTAVE_SUNREALTYPE tout,\n             OCTAVE_SUNREALTYPE tend, ColumnVector& outputsel,\n             const std::string& flag);\n\n\n  bool\n  event (const octave_value& event_fcn,\n         ColumnVector& te, Matrix& ye, ColumnVector& ie,\n         OCTAVE_SUNREALTYPE tsol, const ColumnVector& y,\n         const std::string& flag, const ColumnVector& yp, ColumnVector& oldval,\n         ColumnVector& oldisterminal, ColumnVector& olddir,\n         octave_idx_type cont, octave_idx_type& temp, OCTAVE_SUNREALTYPE told,\n         ColumnVector& yold,\n         const octave_idx_type num_event_args);\n\n  void set_maxorder (int maxorder);\n\n  octave_value_list\n  integrate (const octave_idx_type numt, const ColumnVector& tt,\n             const ColumnVector& y0, const ColumnVector& yp0,\n             const int refine, bool haverefine, bool haveoutputfcn,\n             const octave_value& output_fcn, bool haveoutputsel,\n             ColumnVector& outputsel, bool haveeventfunction,\n             const octave_value& event_fcn,\n             const octave_idx_type num_event_args);\n\n  void print_stat ();\n\nprivate:\n\n  OCTAVE_SUNREALTYPE m_t0;\n  ColumnVector m_y0;\n  ColumnVector m_yp0;\n  bool m_havejac;\n  bool m_havejacfcn;\n  bool m_havejacsparse;\n  void *m_mem;\n  octave_f77_int_type m_num;\n  octave_value m_ida_fcn;\n  octave_value m_ida_jac;\n  Matrix *m_dfdy;\n  Matrix *m_dfdyp;\n  SparseMatrix *m_spdfdy;\n  SparseMatrix *m_spdfdyp;\n  DAERHSFuncIDA m_fcn;\n  DAEJacFuncDense m_jacfcn;\n  DAEJacFuncSparse m_jacspfcn;\n  DAEJacCellDense m_jacdcell;\n  DAEJacCellSparse m_jacspcell;\n#  if defined (HAVE_SUNDIALS_SUNCONTEXT)\n  SUNContext m_sunContext;\n#  endif\n  SUNMatrix m_sunJacMatrix;\n  SUNLinearSolver m_sunLinearSolver;\n};\n\nint\nIDA::resfun (OCTAVE_SUNREALTYPE t, N_Vector yy, N_Vector yyp, N_Vector rr,\n             void *user_data)\n{\n  IDA *self = static_cast<IDA *> (user_data);\n  self->resfun_impl (t, yy, yyp, rr);\n  return 0;\n}\n\nvoid\nIDA::resfun_impl (OCTAVE_SUNREALTYPE t, N_Vector& yy,\n                  N_Vector& yyp, N_Vector& rr)\n{\n  ColumnVector y = IDA::NVecToCol (yy, m_num);\n\n  ColumnVector yp = IDA::NVecToCol (yyp, m_num);\n\n  ColumnVector res = (*m_fcn) (y, yp, t, m_ida_fcn);\n\n  OCTAVE_SUNREALTYPE *puntrr = nv_data_s (rr);\n\n  for (octave_idx_type i = 0; i < m_num; i++)\n    puntrr[i] = res(i);\n}\n\n#  if defined (HAVE_SUNDIALS_SUNCONTEXT)\n#    define OCTAVE_SUNCONTEXT , m_sunContext\n#  else\n#    define OCTAVE_SUNCONTEXT\n#  endif\n\nvoid\nIDA::set_up (const ColumnVector& y)\n{\n  N_Vector yy = ColToNVec (y, m_num);\n  octave::unwind_action act ([&yy] () { N_VDestroy_Serial (yy); });\n\n  if (m_havejacsparse)\n    {\n#  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)\n#    if defined (HAVE_SUNSPARSEMATRIX_REALLOCATE)\n      // Initially allocate memory for 0 entries.  We will reallocate when we\n      // get the Jacobian matrix from the user and know the actual number of\n      // entries.\n      m_sunJacMatrix = SUNSparseMatrix (m_num, m_num, 0, CSC_MAT\n                                        OCTAVE_SUNCONTEXT);\n#    else\n      octave_f77_int_type max_elems;\n      if (math::int_multiply_overflow (m_num, m_num, &max_elems))\n        error (\"Unable to allocate memory for sparse Jacobian\");\n\n      m_sunJacMatrix = SUNSparseMatrix (m_num, m_num, max_elems, CSC_MAT\n                                        OCTAVE_SUNCONTEXT);\n#    endif\n      if (! m_sunJacMatrix)\n        error (\"Unable to create sparse Jacobian for Sundials\");\n\n      m_sunLinearSolver = SUNLinSol_KLU (yy, m_sunJacMatrix\n                                         OCTAVE_SUNCONTEXT);\n      if (! m_sunLinearSolver)\n        error (\"Unable to create KLU sparse solver\");\n\n      if (IDASetLinearSolver (m_mem, m_sunLinearSolver, m_sunJacMatrix))\n        error (\"Unable to set sparse linear solver\");\n\n      IDASetJacFn (m_mem, IDA::jacsparse);\n\n#  else\n      error (\"SUNDIALS SUNLINSOL KLU was unavailable or disabled when \"\n             \"Octave was built\");\n\n#  endif\n\n    }\n  else\n    {\n      m_sunJacMatrix = SUNDenseMatrix (m_num, m_num OCTAVE_SUNCONTEXT);\n      if (! m_sunJacMatrix)\n        error (\"Unable to create dense Jacobian for Sundials\");\n\n      m_sunLinearSolver = SUNLinSol_Dense (yy, m_sunJacMatrix\n                                           OCTAVE_SUNCONTEXT);\n      if (! m_sunLinearSolver)\n        error (\"Unable to create dense linear solver\");\n\n      if (IDASetLinearSolver (m_mem, m_sunLinearSolver, m_sunJacMatrix))\n        error (\"Unable to set dense linear solver\");\n\n      if (m_havejac && IDASetJacFn (m_mem, IDA::jacdense) != 0)\n        error (\"Unable to set dense Jacobian function\");\n    }\n}\n\nvoid\nIDA::jacdense_impl (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj,\n                    N_Vector& yy, N_Vector& yyp, SUNMatrix& JJ)\n\n{\n  octave_f77_int_type Neq = NV_LENGTH_S (yy);\n\n  ColumnVector y = NVecToCol (yy, Neq);\n\n  ColumnVector yp = NVecToCol (yyp, Neq);\n\n  Matrix jac;\n\n  if (m_havejacfcn)\n    jac = (*m_jacfcn) (y, yp, t, cj, m_ida_jac);\n  else\n    jac = (*m_jacdcell) (m_dfdy, m_dfdyp, cj);\n\n  octave_f77_int_type num_jac = to_f77_int (jac.numel ());\n  std::copy (jac.rwdata (),\n             jac.rwdata () + num_jac,\n             SUNDenseMatrix_Data (JJ));\n}\n\n#  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)\nvoid\nIDA::jacsparse_impl (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj, N_Vector& yy,\n                     N_Vector& yyp, SUNMatrix& Jac)\n\n{\n  ColumnVector y = NVecToCol (yy, m_num);\n\n  ColumnVector yp = NVecToCol (yyp, m_num);\n\n  SparseMatrix jac;\n\n  if (m_havejacfcn)\n    jac = (*m_jacspfcn) (y, yp, t, cj, m_ida_jac);\n  else\n    jac = (*m_jacspcell) (m_spdfdy, m_spdfdyp, cj);\n\n#     if defined (HAVE_SUNSPARSEMATRIX_REALLOCATE)\n  octave_f77_int_type nnz = to_f77_int (jac.nnz ());\n  if (nnz > SUNSparseMatrix_NNZ (Jac))\n    {\n      // Allocate memory for sparse Jacobian defined in user function.\n      // This will always be required at least once since we set the number\n      // of nonzero elements to zero initially.\n      if (SUNSparseMatrix_Reallocate (Jac, nnz))\n        error (\"Unable to allocate sufficient memory for IDA sparse matrix\");\n    }\n#     endif\n\n  SUNMatZero_Sparse (Jac);\n  // We have to use \"sunindextype *\" here but still need to check that\n  // conversion of each element to \"octave_f77_int_type\" is save.\n  sunindextype *colptrs = SUNSparseMatrix_IndexPointers (Jac);\n  sunindextype *rowvals = SUNSparseMatrix_IndexValues (Jac);\n\n  for (octave_f77_int_type i = 0; i < m_num + 1; i++)\n    colptrs[i] = to_f77_int (jac.cidx (i));\n\n  double *d = SUNSparseMatrix_Data (Jac);\n  for (octave_f77_int_type i = 0; i < to_f77_int (jac.nnz ()); i++)\n    {\n      rowvals[i] = to_f77_int (jac.ridx (i));\n      d[i] = jac.data (i);\n    }\n}\n#  endif\n\nColumnVector\nIDA::NVecToCol (N_Vector& v, octave_f77_int_type n)\n{\n  ColumnVector data (n);\n  OCTAVE_SUNREALTYPE *punt = nv_data_s (v);\n\n  for (octave_f77_int_type i = 0; i < n; i++)\n    data(i) = punt[i];\n\n  return data;\n}\n\nN_Vector\nIDA::ColToNVec (const ColumnVector& data, octave_f77_int_type n)\n{\n  N_Vector v = N_VNew_Serial (n OCTAVE_SUNCONTEXT);\n\n  OCTAVE_SUNREALTYPE *punt = nv_data_s (v);\n\n  for (octave_f77_int_type i = 0; i < n; i++)\n    punt[i] = data(i);\n\n  return v;\n}\n\nvoid\nIDA::set_userdata ()\n{\n  void *userdata = this;\n\n  if (IDASetUserData (m_mem, userdata) != 0)\n    error (\"User data not set\");\n}\n\nvoid\nIDA::initialize ()\n{\n  m_num = to_f77_int (m_y0.numel ());\n#  if defined (HAVE_SUNDIALS_SUNCONTEXT)\n#    if ! defined (SUN_COMM_NULL)\n#      define SUN_COMM_NULL nullptr\n#    endif\n  if (SUNContext_Create (SUN_COMM_NULL, &m_sunContext) < 0)\n    error (\"__ode15__: unable to create context for SUNDIALS\");\n  m_mem = IDACreate (m_sunContext);\n#  else\n  m_mem = IDACreate ();\n#  endif\n\n  N_Vector yy = ColToNVec (m_y0, m_num);\n  N_Vector yyp = ColToNVec (m_yp0, m_num);\n  octave::unwind_action act ([&yy, &yyp] ()\n                             { N_VDestroy_Serial (yy);\n                               N_VDestroy_Serial (yyp);\n                             });\n\n  IDA::set_userdata ();\n\n  if (IDAInit (m_mem, IDA::resfun, m_t0, yy, yyp) != 0)\n    error (\"IDA not initialized\");\n}\n\nvoid\nIDA::set_tolerance (ColumnVector& abstol, OCTAVE_SUNREALTYPE reltol)\n{\n  N_Vector abs_tol = ColToNVec (abstol, m_num);\n  octave::unwind_action act ([&abs_tol] () { N_VDestroy_Serial (abs_tol); });\n\n  if (IDASVtolerances (m_mem, reltol, abs_tol) != 0)\n    error (\"IDA: Tolerance not set\");\n}\n\nvoid\nIDA::set_tolerance (OCTAVE_SUNREALTYPE abstol, OCTAVE_SUNREALTYPE reltol)\n{\n  if (IDASStolerances (m_mem, reltol, abstol) != 0)\n    error (\"IDA: Tolerance not set\");\n}\n\noctave_value_list\nIDA::integrate (const octave_idx_type numt, const ColumnVector& tspan,\n                const ColumnVector& y, const ColumnVector& yp,\n                const int refine, bool haverefine, bool haveoutputfcn,\n                const octave_value& output_fcn, bool haveoutputsel,\n                ColumnVector& outputsel, bool haveeventfunction,\n                const octave_value& event_fcn,\n                const octave_idx_type num_event_args)\n{\n  // Set up output\n  ColumnVector tout, yout (m_num), ypout (m_num), ysel (outputsel.numel ());\n  ColumnVector ie, te, oldval, oldisterminal, olddir;\n  Matrix output, ye;\n  octave_idx_type cont = 0, temp = 0;\n  bool status = false;\n  std::string string = \"\";\n  ColumnVector yold = y;\n\n  OCTAVE_SUNREALTYPE tsol = tspan(0);\n  OCTAVE_SUNREALTYPE tend = tspan(numt-1);\n\n  N_Vector yyp = ColToNVec (yp, m_num);\n  N_Vector yy = ColToNVec (y, m_num);\n  octave::unwind_action act ([&yyp, &yy] ()\n                             { N_VDestroy_Serial (yyp);\n                               N_VDestroy_Serial (yy);\n                             });\n\n  // Initialize OutputFcn\n  if (haveoutputfcn)\n    status = IDA::outputfun (output_fcn, haveoutputsel, y,\n                             tsol, tend, outputsel, \"init\");\n\n  // Initialize Events\n  if (haveeventfunction)\n    status = IDA::event (event_fcn, te, ye, ie, tsol, y,\n                         \"init\", yp, oldval, oldisterminal,\n                         olddir, cont, temp, tsol, yold, num_event_args);\n\n  if (numt > 2)\n    {\n      // First output value\n      tout.resize (numt);\n      tout(0) = tsol;\n      output.resize (numt, m_num);\n\n      for (octave_idx_type i = 0; i < m_num; i++)\n        output.elem (0, i) = y.elem (i);\n\n      //Main loop\n      for (octave_idx_type j = 1; j < numt && status == 0; j++)\n        {\n          // IDANORMAL already interpolates tspan(j)\n\n          if (IDASolve (m_mem, tspan (j), &tsol, yy, yyp, IDA_NORMAL) != 0)\n            error (\"IDASolve failed\");\n\n          yout = NVecToCol (yy, m_num);\n          ypout = NVecToCol (yyp, m_num);\n          tout(j) = tsol;\n\n          for (octave_idx_type i = 0; i < m_num; i++)\n            output.elem (j, i) = yout.elem (i);\n\n          if (haveoutputfcn)\n            status = IDA::outputfun (output_fcn, haveoutputsel, yout, tsol,\n                                     tend, outputsel, string);\n\n          if (haveeventfunction)\n            status = IDA::event (event_fcn, te, ye, ie, tout(j), yout,\n                                 string, ypout, oldval, oldisterminal,\n                                 olddir, j, temp, tout(j-1), yold,\n                                 num_event_args);\n\n          // If integration is stopped, return only the reached steps\n          if (status == 1)\n            {\n              output.resize (j + 1, m_num);\n              tout.resize (j + 1);\n            }\n\n        }\n    }\n  else // numel (tspan) == 2\n    {\n      // First output value\n      tout.resize (1);\n      tout(0) = tsol;\n      output.resize (1, m_num);\n\n      for (octave_idx_type i = 0; i < m_num; i++)\n        output.elem (0, i) = y.elem (i);\n\n      bool posdirection = (tend > tsol);\n\n      //main loop\n      while (((posdirection == 1 && tsol < tend)\n              || (posdirection == 0 && tsol > tend))\n             && status == 0)\n        {\n          if (IDASolve (m_mem, tend, &tsol, yy, yyp, IDA_ONE_STEP) != 0)\n            error (\"IDASolve failed\");\n\n          if (haverefine)\n            status = IDA::interpolate (cont, output, tout, refine, tend,\n                                       haveoutputfcn, haveoutputsel,\n                                       output_fcn, outputsel,\n                                       haveeventfunction, event_fcn, te,\n                                       ye, ie, oldval, oldisterminal,\n                                       olddir, temp, yold,\n                                       num_event_args);\n\n          ypout = NVecToCol (yyp, m_num);\n          cont += 1;\n          output.resize (cont + 1, m_num); // This may be not efficient\n          tout.resize (cont + 1);\n          tout(cont) = tsol;\n          yout = NVecToCol (yy, m_num);\n\n          for (octave_idx_type i = 0; i < m_num; i++)\n            output.elem (cont, i) = yout.elem (i);\n\n          if (haveoutputfcn && ! haverefine && tout(cont) < tend)\n            status = IDA::outputfun (output_fcn, haveoutputsel, yout, tsol,\n                                     tend, outputsel, string);\n\n          if (haveeventfunction && ! haverefine && tout(cont) < tend)\n            status = IDA::event (event_fcn, te, ye, ie, tout(cont), yout,\n                                 string, ypout, oldval, oldisterminal,\n                                 olddir, cont, temp, tout(cont-1), yold,\n                                 num_event_args);\n        }\n\n      if (status == 0)\n        {\n          // Interpolate in tend\n          N_Vector dky = N_VNew_Serial (m_num OCTAVE_SUNCONTEXT);\n          octave::unwind_action act2 ([&dky] () { N_VDestroy_Serial (dky); });\n\n          if (IDAGetDky (m_mem, tend, 0, dky) != 0)\n            error (\"IDA failed to interpolate y\");\n\n          tout(cont) = tend;\n          yout = NVecToCol (dky, m_num);\n\n          for (octave_idx_type i = 0; i < m_num; i++)\n            output.elem (cont, i) = yout.elem (i);\n\n          // Plot final value\n          if (haveoutputfcn)\n            {\n              status = IDA::outputfun (output_fcn, haveoutputsel, yout,\n                                       tend, tend, outputsel, string);\n\n              // Events during last step\n              if (haveeventfunction)\n                status = IDA::event (event_fcn, te, ye, ie, tend, yout,\n                                     string, ypout, oldval, oldisterminal,\n                                     olddir, cont, temp, tout(cont-1),\n                                     yold, num_event_args);\n            }\n        }\n\n      // Cleanup plotter\n      status = IDA::outputfun (output_fcn, haveoutputsel, yout, tend, tend,\n                               outputsel, \"done\");\n    }\n\n  // Index of Events (ie) variable must use 1-based indexing\n  return ovl (tout, output, te, ye, ie + 1.0);\n}\n\nbool\nIDA::event (const octave_value& event_fcn,\n            ColumnVector& te, Matrix& ye, ColumnVector& ie,\n            OCTAVE_SUNREALTYPE tsol, const ColumnVector& y,\n            const std::string& flag, const ColumnVector& yp,\n            ColumnVector& oldval, ColumnVector& oldisterminal,\n            ColumnVector& olddir, octave_idx_type cont, octave_idx_type& temp,\n            OCTAVE_SUNREALTYPE told, ColumnVector& yold,\n            const octave_idx_type num_event_args)\n{\n  bool status = false;\n\n  octave_value_list args;\n  if (num_event_args == 2)\n    args = ovl (tsol, y);\n  else\n    args = ovl (tsol, y, yp);\n\n  // cont is the number of steps reached by the solver\n  // temp is the number of events registered\n\n  interpreter& interp = __get_interpreter__ ();\n\n  if (flag == \"init\")\n    {\n      octave_value_list output = interp.feval (event_fcn, args, 3);\n      oldval = output(0).vector_value ();\n      oldisterminal = output(1).vector_value ();\n      olddir = output(2).vector_value ();\n    }\n  else if (flag == \"\")\n    {\n      ColumnVector index (0);\n      octave_value_list output = interp.feval (event_fcn, args, 3);\n      ColumnVector val = output(0).vector_value ();\n      ColumnVector isterminal = output(1).vector_value ();\n      ColumnVector dir = output(2).vector_value ();\n\n      // Get the index of the changed values\n      for (octave_idx_type i = 0; i < val.numel (); i++)\n        {\n          // Check for sign change and whether a rising / falling edge\n          // either passes through zero or detaches from zero (bug #59063)\n          if ((dir(i) != -1\n               && ((val(i) >= 0 && oldval(i) < 0)\n                   || (val(i) > 0 && oldval(i) <= 0))) // increasing\n              || (dir(i) != 1\n                  && ((val(i) <= 0 && oldval(i) > 0)\n                      || (val(i) < 0 && oldval(i) >= 0)))) // decreasing\n            {\n              index.resize (index.numel () + 1);\n              index (index.numel () - 1) = i;\n            }\n        }\n\n      if (cont == 1 && index.numel () > 0)  // Events in first step\n        {\n          temp = 1; // register only the first event\n          te.resize (1);\n          ye.resize (1, m_num);\n          ie.resize (1);\n\n          // Linear interpolation\n          ie(0) = index(0);\n          te(0) = tsol - val (index(0)) * (tsol - told)\n                  / (val (index(0)) - oldval (index(0)));\n\n          ColumnVector ytemp\n            = y - ((tsol - te(0)) * (y - yold) / (tsol - told));\n\n          for (octave_idx_type i = 0; i < m_num; i++)\n            ye.elem (0, i) = ytemp.elem (i);\n\n        }\n      else if (index.numel () > 0)\n        // Not first step: register all events and test\n        // if stop integration or not\n        {\n          te.resize (temp + index.numel ());\n          ye.resize (temp + index.numel (), m_num);\n          ie.resize (temp + index.numel ());\n\n          for (octave_idx_type i = 0; i < index.numel (); i++)\n            {\n\n              if (isterminal (index(i)) == 1)\n                status = 1; // Stop integration\n\n              // Linear interpolation\n              ie(temp+i) = index(i);\n              te(temp+i) = tsol - val(index(i)) * (tsol - told)\n                           / (val(index(i)) - oldval(index(i)));\n\n              ColumnVector ytemp\n                = y - (tsol - te (temp + i)) * (y - yold) / (tsol - told);\n\n              for (octave_idx_type j = 0; j < m_num; j++)\n                ye.elem (temp + i, j) = ytemp.elem (j);\n\n            }\n\n          temp += index.numel ();\n        }\n\n      // Update variables\n      yold = y;\n      told = tsol;\n      olddir = dir;\n      oldval = val;\n      oldisterminal = isterminal;\n    }\n\n  return status;\n}\n\nbool\nIDA::interpolate (octave_idx_type& cont, Matrix& output, ColumnVector& tout,\n                  int refine, OCTAVE_SUNREALTYPE tend, bool haveoutputfcn,\n                  bool haveoutputsel, const octave_value& output_fcn,\n                  ColumnVector& outputsel, bool haveeventfunction,\n                  const octave_value& event_fcn, ColumnVector& te,\n                  Matrix& ye, ColumnVector& ie, ColumnVector& oldval,\n                  ColumnVector& oldisterminal, ColumnVector& olddir,\n                  octave_idx_type& temp, ColumnVector& yold,\n                  const octave_idx_type num_event_args)\n{\n  OCTAVE_SUNREALTYPE h = 0, tcur = 0;\n  bool status = false;\n\n  N_Vector dky = N_VNew_Serial (m_num OCTAVE_SUNCONTEXT);\n  N_Vector dkyp = N_VNew_Serial (m_num OCTAVE_SUNCONTEXT);\n  octave::unwind_action act ([&dky, &dkyp] ()\n                             { N_VDestroy_Serial (dky);\n                               N_VDestroy_Serial (dkyp);\n                             });\n\n  ColumnVector yout (m_num);\n  ColumnVector ypout (m_num);\n  std::string string = \"\";\n\n  if (IDAGetLastStep (m_mem, &h) != 0)\n    error (\"IDA failed to return last step\");\n\n  if (IDAGetCurrentTime (m_mem, &tcur) != 0)\n    error (\"IDA failed to return the current time\");\n\n  OCTAVE_SUNREALTYPE tin = tcur - h;\n\n  OCTAVE_SUNREALTYPE step = h / refine;\n\n  for (octave_idx_type i = 1;\n       i < refine && tin + step * i < tend && status == 0;\n       i++)\n    {\n      if (IDAGetDky (m_mem, tin + step*i, 0, dky) != 0)\n        error (\"IDA failed to interpolate y\");\n\n      if (IDAGetDky (m_mem, tin + step*i, 1, dkyp) != 0)\n        error (\"IDA failed to interpolate yp\");\n\n      cont += 1;\n      output.resize (cont + 1, m_num);\n      tout.resize (cont + 1);\n\n      tout(cont) = tin + step * i;\n      yout = NVecToCol (dky, m_num);\n      ypout = NVecToCol (dkyp, m_num);\n\n      for (octave_idx_type j = 0; j < m_num; j++)\n        output.elem (cont, j) = yout.elem (j);\n\n      if (haveoutputfcn)\n        status = IDA::outputfun (output_fcn, haveoutputsel, yout,\n                                 tout(cont), tend, outputsel, \"\");\n\n      if (haveeventfunction)\n        status = IDA::event (event_fcn, te, ye, ie, tout(cont),\n                             yout, string, ypout, oldval,\n                             oldisterminal, olddir, cont, temp,\n                             tout(cont-1), yold, num_event_args);\n    }\n\n  return status;\n}\n\nbool\nIDA::outputfun (const octave_value& output_fcn, bool haveoutputsel,\n                const ColumnVector& yout, OCTAVE_SUNREALTYPE tsol,\n                OCTAVE_SUNREALTYPE tend, ColumnVector& outputsel,\n                const std::string& flag)\n{\n  bool status = false;\n\n  octave_value_list output;\n  output(2) = flag;\n\n  ColumnVector ysel (outputsel.numel ());\n  if (haveoutputsel)\n    {\n      for (octave_idx_type i = 0; i < outputsel.numel (); i++)\n        ysel(i) = yout(outputsel(i));\n\n      output(1) = ysel;\n    }\n  else\n    output(1) = yout;\n\n  interpreter& interp = __get_interpreter__ ();\n\n  if (flag == \"init\")\n    {\n      ColumnVector toutput (2);\n      toutput(0) = tsol;\n      toutput(1) = tend;\n      output(0) = toutput;\n\n      interp.feval (output_fcn, output, 0);\n    }\n  else if (flag == \"\")\n    {\n      output(0) = tsol;\n      octave_value_list val = interp.feval (output_fcn, output, 1);\n      status = val(0).bool_value ();\n    }\n  else\n    {\n      // Cleanup plotter\n      output(0) = tend;\n      interp.feval (output_fcn, output, 0);\n    }\n\n  return status;\n}\n\nvoid\nIDA::set_maxstep (OCTAVE_SUNREALTYPE maxstep)\n{\n  if (IDASetMaxStep (m_mem, maxstep) != 0)\n    error (\"IDA: Max Step not set\");\n}\n\nvoid\nIDA::set_initialstep (OCTAVE_SUNREALTYPE initialstep)\n{\n  if (IDASetInitStep (m_mem, initialstep) != 0)\n    error (\"IDA: Initial Step not set\");\n}\n\nvoid\nIDA::set_maxorder (int maxorder)\n{\n  if (IDASetMaxOrd (m_mem, maxorder) != 0)\n    error (\"IDA: Max Order not set\");\n}\n\nvoid\nIDA::print_stat ()\n{\n  long int nsteps = 0, netfails = 0, nrevals = 0;\n\n  if (IDAGetNumSteps (m_mem, &nsteps) != 0)\n    error (\"IDA failed to return the number of internal steps\");\n\n  if (IDAGetNumErrTestFails (m_mem, &netfails) != 0)\n    error (\"IDA failed to return the number of internal errors\");\n\n  if (IDAGetNumResEvals (m_mem, &nrevals) != 0)\n    error (\"IDA failed to return the number of residual evaluations\");\n\n  octave_stdout << nsteps << \" successful steps\\n\";\n  octave_stdout << netfails << \" failed attempts\\n\";\n  octave_stdout << nrevals << \" function evaluations\\n\";\n  // octave_stdout << \" partial derivatives\\n\";\n  // octave_stdout << \" LU decompositions\\n\";\n  // octave_stdout << \" solutions of linear systems\\n\";\n}\n\nstatic ColumnVector\nida_user_function (const ColumnVector& x, const ColumnVector& xdot,\n                   double t, const octave_value& ida_fc)\n{\n  octave_value_list tmp;\n\n  try\n    {\n      interpreter& interp = __get_interpreter__ ();\n\n      tmp = interp.feval (ida_fc, ovl (t, x, xdot), 1);\n    }\n  catch (execution_exception& ee)\n    {\n      err_user_supplied_eval (ee, \"__ode15__\");\n    }\n\n  return tmp(0).vector_value ();\n}\n\nstatic Matrix\nida_dense_jac (const ColumnVector& x, const ColumnVector& xdot,\n               double t, double cj, const octave_value& ida_jc)\n{\n  octave_value_list tmp;\n\n  try\n    {\n      interpreter& interp = __get_interpreter__ ();\n\n      tmp = interp.feval (ida_jc, ovl (t, x, xdot), 2);\n    }\n  catch (execution_exception& ee)\n    {\n      err_user_supplied_eval (ee, \"__ode15__\");\n    }\n\n  return tmp(0).matrix_value () + cj * tmp(1).matrix_value ();\n}\n\nstatic SparseMatrix\nida_sparse_jac (const ColumnVector& x, const ColumnVector& xdot,\n                double t, double cj, const octave_value& ida_jc)\n{\n  octave_value_list tmp;\n\n  try\n    {\n      interpreter& interp = __get_interpreter__ ();\n\n      tmp = interp.feval (ida_jc, ovl (t, x, xdot), 2);\n    }\n  catch (execution_exception& ee)\n    {\n      err_user_supplied_eval (ee, \"__ode15__\");\n    }\n\n  return tmp(0).sparse_matrix_value () + cj * tmp(1).sparse_matrix_value ();\n}\n\nstatic Matrix\nida_dense_cell_jac (Matrix *dfdy, Matrix *dfdyp, double cj)\n{\n  return (*dfdy) + cj * (*dfdyp);\n}\n\nstatic SparseMatrix\nida_sparse_cell_jac (SparseMatrix *spdfdy, SparseMatrix *spdfdyp,\n                     double cj)\n{\n  return (*spdfdy) + cj * (*spdfdyp);\n}\n\nstatic octave_value_list\ndo_ode15 (const octave_value& ida_fcn,\n          const ColumnVector& tspan,\n          const octave_idx_type numt,\n          const OCTAVE_SUNREALTYPE t0,\n          const ColumnVector& y0,\n          const ColumnVector& yp0,\n          const octave_scalar_map& options,\n          const octave_idx_type num_event_args)\n{\n  octave_value_list retval;\n\n  // Create object\n  IDA dae (t0, y0, yp0, ida_fcn, ida_user_function);\n\n  // Set Jacobian\n  bool havejac = options.getfield (\"havejac\").bool_value ();\n\n  bool havejacsparse = options.getfield (\"havejacsparse\").bool_value ();\n\n  bool havejacfcn = options.getfield (\"havejacfcn\").bool_value ();\n\n  Matrix ida_dfdy, ida_dfdyp;\n  SparseMatrix ida_spdfdy, ida_spdfdyp;\n\n  if (havejac)\n    {\n      if (havejacfcn)\n        {\n          octave_value ida_jac = options.getfield (\"Jacobian\");\n\n          if (havejacsparse)\n            dae.set_jacobian (ida_jac, ida_sparse_jac);\n          else\n            dae.set_jacobian (ida_jac, ida_dense_jac);\n        }\n      else\n        {\n          Cell jaccell = options.getfield (\"Jacobian\").cell_value ();\n\n          if (havejacsparse)\n            {\n              ida_spdfdy = jaccell(0).sparse_matrix_value ();\n              ida_spdfdyp = jaccell(1).sparse_matrix_value ();\n\n              dae.set_jacobian (&ida_spdfdy, &ida_spdfdyp,\n                                ida_sparse_cell_jac);\n            }\n          else\n            {\n              ida_dfdy = jaccell(0).matrix_value ();\n              ida_dfdyp = jaccell(1).matrix_value ();\n\n              dae.set_jacobian (&ida_dfdy, &ida_dfdyp, ida_dense_cell_jac);\n            }\n        }\n    }\n\n  // Initialize IDA\n  dae.initialize ();\n\n  // Set tolerances\n  OCTAVE_SUNREALTYPE rel_tol = options.getfield (\"RelTol\").double_value ();\n\n  bool haveabstolvec = options.getfield (\"haveabstolvec\").bool_value ();\n\n  if (haveabstolvec)\n    {\n      ColumnVector abs_tol = options.getfield (\"AbsTol\").vector_value ();\n\n      dae.set_tolerance (abs_tol, rel_tol);\n    }\n  else\n    {\n      OCTAVE_SUNREALTYPE abs_tol = options.getfield (\"AbsTol\").double_value ();\n\n      dae.set_tolerance (abs_tol, rel_tol);\n    }\n\n  //Set max step\n  OCTAVE_SUNREALTYPE maxstep = options.getfield (\"MaxStep\").double_value ();\n\n  dae.set_maxstep (maxstep);\n\n  //Set initial step\n  if (! options.getfield (\"InitialStep\").isempty ())\n    {\n      OCTAVE_SUNREALTYPE initialstep = options.getfield (\"InitialStep\").double_value ();\n\n      dae.set_initialstep (initialstep);\n    }\n\n  //Set max order FIXME: it doesn't work\n  int maxorder = options.getfield (\"MaxOrder\").int_value ();\n\n  dae.set_maxorder (maxorder);\n\n  //Set Refine\n  const int refine = options.getfield (\"Refine\").int_value ();\n\n  bool haverefine = (refine > 1);\n\n  octave_value output_fcn;\n  ColumnVector outputsel;\n\n  // OutputFcn\n  bool haveoutputfunction\n    = options.getfield (\"haveoutputfunction\").bool_value ();\n\n  if (haveoutputfunction)\n    output_fcn = options.getfield (\"OutputFcn\");\n\n  // OutputSel\n  bool haveoutputsel = options.getfield (\"haveoutputselection\").bool_value ();\n\n  if (haveoutputsel)\n    outputsel = options.getfield (\"OutputSel\").vector_value ();\n\n  octave_value event_fcn;\n\n  // Events\n  bool haveeventfunction\n    = options.getfield (\"haveeventfunction\").bool_value ();\n\n  if (haveeventfunction)\n    event_fcn = options.getfield (\"Events\");\n\n  // Set up linear solver\n  dae.set_up (y0);\n\n  // Integrate\n  retval = dae.integrate (numt, tspan, y0, yp0, refine,\n                          haverefine, haveoutputfunction,\n                          output_fcn, haveoutputsel, outputsel,\n                          haveeventfunction, event_fcn, num_event_args);\n\n  // Statistics\n  bool havestats = options.getfield (\"havestats\").bool_value ();\n\n  if (havestats)\n    dae.print_stat ();\n\n  return retval;\n}\n\n#endif\n\nDEFUN_DLD (__ode15__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{t}, @var{y} =} __ode15__ (@var{fcn}, @var{tspan}, @var{y0}, @var{yp0}, @var{ode_opt}, @var{num_event_args})\nUndocumented internal function.\n@end deftypefn */)\n{\n\n#if defined (HAVE_SUNDIALS)\n\n  // Check number of parameters\n  if (args.length () != 6)\n    print_usage ();\n\n  // Check ODE function\n  octave_value ida_fcn = args(0);\n\n  if (! ida_fcn.is_function_handle ())\n    error (\"__ode15__: FCN must be a function handle\");\n\n  // Check input tspan\n  ColumnVector tspan\n    = args(1).xvector_value (\"__ode15__: TRANGE must be a vector of numbers\");\n\n  octave_idx_type numt = tspan.numel ();\n\n  OCTAVE_SUNREALTYPE t0 = tspan(0);\n\n  if (numt < 2)\n    error (\"__ode15__: TRANGE must contain at least 2 elements\");\n  else if (tspan.issorted () == UNSORTED || tspan(0) == tspan(numt - 1))\n    error (\"__ode15__: TRANGE must be strictly monotonic\");\n\n  // input y0 and yp0\n  ColumnVector y0\n    = args(2).xvector_value (\"__ode15__: initial state Y0 must be a vector\");\n\n  ColumnVector yp0\n    = args(3).xvector_value (\"__ode15__: initial state YP0 must be a vector\");\n\n\n  if (y0.numel () != yp0.numel ())\n    error (\"__ode15__: initial state Y0 and YP0 must have the same length\");\n  else if (y0.numel () < 1)\n    error (\"__ode15__: initial state YP0 must be a vector or a scalar\");\n\n\n  if (! args(4).isstruct ())\n    error (\"__ode15__: ODE_OPT argument must be a structure\");\n\n  octave_scalar_map options\n    = args(4).xscalar_map_value (\"__ode15__: ODE_OPT argument must be a scalar structure\");\n\n  // Provided number of arguments in the ode callback function\n  octave_idx_type num_event_args\n    = args(5).strict_idx_type_value (\"__ode15__: NUM_EVENT_ARGS must be an integer\");\n\n  if (num_event_args != 2 && num_event_args != 3)\n    error (\"__ode15__: number of input arguments in event callback must be 2 or 3\");\n\n  return do_ode15 (ida_fcn, tspan, numt, t0, y0, yp0, options, num_event_args);\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__ode15__\", \"sundials_ida, sundials_nvecserial\");\n\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/__voronoi__.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n20. Augiust 2000 - Kai Habel: first release\n*/\n\n/*\n2003-12-14 Rafael Laboissiere <rafael@laboissiere.net>\nAdded optional second argument to pass options to the underlying\nqhull command\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdio>\n\n#include <limits>\n#include <string>\n\n#include \"Array.h\"\n#include \"boolMatrix.h\"\n#include \"dMatrix.h\"\n#include \"dRowVector.h\"\n#include \"oct-locbuf.h\"\n#include \"unwind-prot.h\"\n\n#include \"Cell.h\"\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\n#if defined (HAVE_QHULL)\n#  include \"oct-qhull.h\"\n#  if defined (NEED_QHULL_R_VERSION)\nchar qh_version[] = \"__voronoi__.oct 2007-07-24\";\n#  endif\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_QHULL)\n\nstatic void\nfree_qhull_memory (qhT *qh)\n{\n  qh_freeqhull (qh, ! qh_ALL);\n\n  int curlong, totlong;\n  qh_memfreeshort (qh, &curlong, &totlong);\n\n  if (curlong || totlong)\n    warning (\"__voronoi__: did not free %d bytes of long memory (%d pieces)\",\n             totlong, curlong);\n}\n\nstatic bool\noctave_qhull_dims_ok (octave_idx_type dim, octave_idx_type n, const char *who)\n{\n  if (sizeof (octave_idx_type) > sizeof (int))\n    {\n      int maxval = std::numeric_limits<int>::max ();\n\n      if (dim > maxval || n > maxval)\n        error (\"%s: dimension too large for Qhull\", who);\n    }\n\n  return true;\n}\n\n#endif\n\nDEFUN_DLD (__voronoi__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C}, @var{F} =} __voronoi__ (@var{caller}, @var{pts})\n@deftypefnx {} {@var{C}, @var{F} =} __voronoi__ (@var{caller}, @var{pts}, @var{options})\n@deftypefnx {} {@var{C}, @var{F}, @var{Inf_Pts} =} __voronoi__ (@dots{})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_QHULL)\n\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  std::string caller = args(0).xstring_value (\"__voronoi__: CALLER must be a string\");\n\n  octave_value_list retval;\n\n  Matrix points = args(1).matrix_value ();\n  const octave_idx_type dim = points.columns ();\n  const octave_idx_type num_points = points.rows ();\n\n  if (! octave_qhull_dims_ok (dim, num_points, \"__voronoi__\"))\n    return ovl (0.0);\n\n  points = points.transpose ();\n\n  std::string options;\n\n  if (dim <= 3)\n    options = \" Qbb\";\n  else\n    options = \" Qbb Qx\";\n\n  if (nargin == 3)\n    {\n      octave_value opt_arg = args(2);\n\n      if (opt_arg.is_string ())\n        options = ' ' + opt_arg.string_value ();\n      else if (opt_arg.isempty ())\n        ; // Use default options.\n      else if (opt_arg.iscellstr ())\n        {\n          options = \"\";\n\n          Array<std::string> tmp = opt_arg.cellstr_value ();\n\n          for (octave_idx_type i = 0; i < tmp.numel (); i++)\n            options += ' ' + tmp(i);\n        }\n      else\n        error (\"%s: OPTIONS must be a string, cell array of strings, or empty\",\n               caller.c_str ());\n    }\n\n  boolT ismalloc = false;\n\n  // Set the outfile pointer to stdout for status information.\n  FILE *outfile = nullptr;\n  FILE *errfile = stderr;\n\n  qhT context = { };\n  qhT *qh = &context;\n\n  std::string cmd = \"qhull v\" + options;\n\n  int exitcode = qh_new_qhull (qh, dim, num_points, points.rwdata (),\n                               ismalloc, &cmd[0], outfile, errfile);\n\n  unwind_action free_memory ([qh] () { free_qhull_memory (qh); });\n\n  if (exitcode)\n    error (\"%s: qhull failed\", caller.c_str ());\n\n  // Calling findgood_all provides the number of Voronoi vertices\n  // (sets qh->num_good).\n\n  qh_findgood_all (qh, qh->facet_list);\n\n  octave_idx_type num_voronoi_regions\n    = qh->num_vertices - qh_setsize (qh, qh->del_vertices);\n\n  octave_idx_type num_voronoi_vertices = qh->num_good;\n\n  // Find the voronoi centers for all facets.\n\n  qh_setvoronoi_all (qh);\n\n  facetT *facet;\n  vertexT *vertex;\n  octave_idx_type k;\n\n  // Find the number of Voronoi vertices for each Voronoi cell and\n  // store them in NI so we can use them later to set the dimensions\n  // of the RowVector objects used to collect them.\n\n  FORALLfacets\n  {\n    facet->seen = false;\n  }\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, ni, num_voronoi_regions);\n  for (octave_idx_type i = 0; i < num_voronoi_regions; i++)\n    ni[i] = 0;\n\n  k = 0;\n\n  FORALLvertices\n  {\n    if (qh->hull_dim == 3)\n      qh_order_vertexneighbors (qh, vertex);\n\n    bool infinity_seen = false;\n\n    facetT *neighbor, * *neighborp;\n\n    FOREACHneighbor_ (vertex)\n    {\n      if (neighbor->upperdelaunay)\n        {\n          if (! infinity_seen)\n            {\n              infinity_seen = true;\n              ni[k]++;\n            }\n        }\n      else\n        {\n          neighbor->seen = true;\n          ni[k]++;\n        }\n    }\n\n    k++;\n  }\n\n  // If Qhull finds fewer regions than points, we will pad the end\n  // of the at_inf and C arrays so that they always contain at least\n  // as many elements as the given points array.\n\n  // FIXME: is it possible (or does it make sense) for\n  // num_voronoi_regions to ever be larger than num_points?\n\n  octave_idx_type nr = (num_points > num_voronoi_regions\n                        ? num_points : num_voronoi_regions);\n\n  boolMatrix at_inf (nr, 1, false);\n\n  // The list of Voronoi vertices.  The first element is always\n  // Inf.\n  Matrix F (num_voronoi_vertices+1, dim);\n\n  for (octave_idx_type d = 0; d < dim; d++)\n    F(0, d) = numeric_limits<double>::Inf ();\n\n  // The cell array of vectors of indices into F that represent the\n  // vertices of the Voronoi regions (cells).\n\n  Cell C (nr, 1);\n\n  // Now loop through the list of vertices again and store the\n  // coordinates of the Voronoi vertices and the lists of indices\n  // for the cells.\n\n  FORALLfacets\n  {\n    facet->seen = false;\n  }\n\n  octave_idx_type i = 0;\n  k = 0;\n\n  FORALLvertices\n  {\n    if (qh->hull_dim == 3)\n      qh_order_vertexneighbors (qh, vertex);\n\n    bool infinity_seen = false;\n\n    octave_idx_type idx = qh_pointid (qh, vertex->point);\n\n    octave_idx_type num_vertices = ni[k++];\n\n    // Qhull seems to sometimes produces regions with a single\n    // vertex.  Is that a bug?  How can a region have just one\n    // vertex?  Let's skip it.\n\n    if (num_vertices == 1)\n      continue;\n\n    RowVector facet_list (num_vertices);\n\n    octave_idx_type m = 0;\n\n    facetT *neighbor, * *neighborp;\n\n    FOREACHneighbor_(vertex)\n    {\n      if (neighbor->upperdelaunay)\n        {\n          if (! infinity_seen)\n            {\n              infinity_seen = true;\n              facet_list(m++) = 1;\n              at_inf(idx) = true;\n            }\n        }\n      else\n        {\n          if (! neighbor->seen)\n            {\n              i++;\n              for (octave_idx_type d = 0; d < dim; d++)\n                F(i, d) = neighbor->center[d];\n\n              neighbor->seen = true;\n              neighbor->visitid = i;\n            }\n\n          facet_list(m++) = neighbor->visitid + 1;\n        }\n    }\n\n    C(idx) = facet_list;\n  }\n\n  retval = ovl (F, C, at_inf);\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n\n  std::string caller\n    = (args.length () > 0\n       ? args(0).xstring_value (\"__voronoi__: CALLER must be a string\")\n       : \"__voronoi__\");\n\n  err_disabled_feature (caller, \"Qhull\");\n\n#endif\n}\n\n/*\n## No test needed for internal helper function.\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/audiodevinfo.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdint>\n\n#include <algorithm>\n#include <iostream>\n#include <memory>\n#include <ostream>\n#include <string>\n#include <vector>\n\n#include \"Matrix.h\"\n#include \"mach-info.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-syscalls.h\"\n#include \"quit.h\"\n#include \"unwind-prot.h\"\n\n#include \"Cell.h\"\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"oct-map.h\"\n#include \"ov-int32.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\n#if defined (HAVE_PORTAUDIO)\n#  include <portaudio.h>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_PORTAUDIO)\n\nstatic PaSampleFormat\nbits_to_format (int bits)\n{\n  if (bits == 8)\n    return paInt8;\n  else if (bits == 16)\n    return paInt16;\n  else if (bits == 24)\n    return paInt24;\n  else if (bits == 32)\n    return paInt32;\n  else if (bits == -1)\n    return paFloat32;\n  else\n    return 0;\n}\n\n#endif\n\nDEFUN_DLD (audiodevinfo, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{devinfo} =} audiodevinfo ()\n\n@deftypefnx {} {@var{devs} =} audiodevinfo (@var{io})\n@deftypefnx {} {@var{name} =} audiodevinfo (@var{io}, @var{id})\n@deftypefnx {} {@var{id} =} audiodevinfo (@var{io}, @var{name})\n@deftypefnx {} {@var{driverversion} =} audiodevinfo (@var{io}, @var{id}, \"DriverVersion\")\n@deftypefnx {} {@var{id} =} audiodevinfo (@var{io}, @var{rate}, @var{bits}, @var{chans})\n@deftypefnx {} {@var{supports} =} audiodevinfo (@var{io}, @var{id}, @var{rate}, @var{bits}, @var{chans})\n\nReturn a structure describing the available audio input and output devices.\n\nThe @var{devinfo} structure has two fields @qcode{\"input\"} and\n@qcode{\"output\"}.  The value of each field is a structure array with fields\n@qcode{\"Name\"}, @nospell{@qcode{\"DriverVersion\"}} and @qcode{\"ID\"} describing\nan audio device.\n\nIf the optional argument @var{io} is 1, return information about input devices\nonly.  If it is 0, return information about output devices only.  If @var{io}\nis the only argument supplied, return the number of input or output devices\navailable.\n\nIf the optional argument @var{id} is provided, return information about the\ncorresponding device.\n\nIf the optional argument @var{name} is provided, return the ID of the named\ndevice.\n\nIf the optional argument @nospell{@qcode{\"DriverVersion\"}} is given, return the\nname of the driver for the specified device.\n\nGiven a sampling rate, bits per sample, and number of channels for an input or\noutput device, return the ID of the first device that supports playback or\nrecording using the specified parameters.\n\nIf also given a device ID, return true if the device supports playback or\nrecording using those parameters.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n\n  int nargin = args.length ();\n\n  if (nargin > 5)\n    print_usage ();\n\n  octave_scalar_map devinfo;\n  octave_value_list input;\n  octave_value_list output;\n\n  std::string errstr;\n  PaError err = sys::capture_stderr ([] { return Pa_Initialize (); }, errstr);\n\n  if (err != paNoError)\n    {\n      std::cerr << errstr << std::endl;\n      error (\"audiodevinfo: PortAudio initialization failed\");\n    }\n\n  // Guarantee PortAudio cleanup code is executed\n  octave::unwind_action portaudio_cleanup ([] () { Pa_Terminate (); } );\n\n  int num_devices = Pa_GetDeviceCount ();\n\n  if (num_devices < 0)\n    num_devices = 0;\n\n  octave_idx_type numinput, numoutput;\n  numinput = numoutput = 0;\n  for (int i = 0; i < num_devices; i++)\n    {\n      const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);\n\n      if (! device_info)\n        {\n          warning_with_id (\"Octave:invalid-audio-device\",\n                           \"invalid audio device ID = %d\", i);\n          continue;\n        }\n\n      if (device_info->maxInputChannels != 0)\n        numinput++;\n\n      if (device_info->maxOutputChannels != 0)\n        numoutput++;\n    }\n\n  Cell input_name (dim_vector (1, numinput));\n  Cell input_driver_version (dim_vector (1, numinput));\n  Cell input_id (dim_vector (1, numinput));\n  Cell output_name (dim_vector (1, numoutput));\n  Cell output_driver_version (dim_vector (1, numoutput));\n  Cell output_id (dim_vector (1, numoutput));\n\n  octave_idx_type idx_i, idx_o;\n  idx_i = idx_o = 0;\n  for (int i = 0; i < num_devices; i++)\n    {\n      const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);\n\n      if (! device_info)\n        {\n          warning_with_id (\"Octave:invalid-audio-device\",\n                           \"invalid audio device ID = %d\", i);\n          continue;\n        }\n\n      const PaHostApiInfo *api_info = Pa_GetHostApiInfo (device_info->hostApi);\n\n      const char *driver = (api_info ? api_info->name : \"\");\n\n      char name[256];\n      snprintf (name, 256, \"%s (%s)\", device_info->name, driver);\n\n      if (device_info->maxInputChannels != 0)\n        {\n          input_name(idx_i) = name;\n          input_driver_version(idx_i) = driver;\n          input_id(idx_i) = i;\n          idx_i++;\n        }\n\n      if (device_info->maxOutputChannels != 0)\n        {\n          output_name(idx_o) = name;\n          output_driver_version(idx_o) = driver;\n          output_id(idx_o) = i;\n          idx_o++;\n        }\n    }\n\n  octave_map inputdev, outputdev;\n  inputdev.setfield (\"Name\", input_name);\n  inputdev.setfield (\"DriverVersion\", input_driver_version);\n  inputdev.setfield (\"ID\", input_id);\n  outputdev.setfield (\"Name\", output_name);\n  outputdev.setfield (\"DriverVersion\", output_driver_version);\n  outputdev.setfield (\"ID\", output_id);\n  devinfo.setfield (\"input\", inputdev);\n  devinfo.setfield (\"output\", outputdev);\n\n  octave_value retval;\n\n  // Return information about input & output audio devices and their properties.\n  if (nargin == 0)\n    {\n      retval = devinfo;\n    }\n  // Return the number of input or output devices\n  else if (nargin == 1)\n    {\n      if (args(0).int_value () == 0)\n        retval = numoutput;\n      else if (args(0).int_value () == 1)\n        retval = numinput;\n      else\n        error (\"audiodevinfo: specify 0 for output and 1 for input devices\");\n    }\n  // Return device name when given id or id when given device name.\n  else if (nargin == 2)\n    {\n      bool found = false;\n      int outin = args(0).int_value ();\n      if (args(1).is_string ())\n        {\n          std::string name = args(1).string_value ();\n          if (outin == 0)\n            {\n              for (int i = 0; i < numoutput; i++)\n                {\n                  if (output_name(i).string_value () == name)\n                    {\n                      retval = output_id(i);\n                      found = true;\n                      break;\n                    }\n                }\n            }\n          else if (outin == 1)\n            {\n              for (int i = 0; i < numinput; i++)\n                {\n                  if (input_name(i).string_value () == name)\n                    {\n                      retval = input_id(i);\n                      found = true;\n                      break;\n                    }\n                }\n            }\n          else\n            error (\"audiodevinfo: specify 0 for output and 1 for input devices\");\n        }\n      else\n        {\n          if (outin == 0)\n            {\n              for (int i = 0; i < numoutput; i++)\n                {\n                  if (output_id(i).int_value () == args(1).int_value ())\n                    {\n                      retval = output_name(i);\n                      found = true;\n                      break;\n                    }\n                }\n            }\n          else if (outin == 1)\n            {\n              for (int i = 0; i < numinput; i++)\n                {\n                  if (input_id(i).int_value () == args(1).int_value ())\n                    {\n                      retval = input_name(i);\n                      found = true;\n                      break;\n                    }\n                }\n            }\n          else\n            error (\"audiodevinfo: specify 0 for output and 1 for input devices\");\n        }\n\n      if (! found)\n        error (\"audiodevinfo: no device found for the specified criteria\");\n    }\n  // Return the DriverVersion (really, name of driver) of the specified device\n  else if (nargin == 3)\n    {\n      bool found = false;\n      int outin = args(0).int_value ();\n      int m_id = args(1).int_value ();\n\n      std::string arg3 = args(2).string_value ();\n      std::transform (arg3.begin (), arg3.end (), arg3.begin (), tolower);\n      if (arg3 != \"driverversion\")\n        error (R\"(audiodevinfo: third argument must be \"DriverVersion\")\");\n\n      if (outin == 0)\n        {\n          for (int i = 0; i < numoutput; i++)\n            {\n              if (output_id(i).int_value () == m_id)\n                {\n                  found = true;\n                  retval = output_driver_version(i);\n                  break;\n                }\n            }\n        }\n      else if (outin == 1)\n        {\n          for (int i = 0; i < numinput; i++)\n            {\n              if (input_id(i).int_value () == m_id)\n                {\n                  found = true;\n                  retval = input_driver_version(i);\n                  break;\n                }\n            }\n        }\n      else\n        error (\"audiodevinfo: specify 0 for output and 1 for input devices\");\n\n      if (! found)\n        error (\"audiodevinfo: no device found for the specified criteria\");\n    }\n  // Return the ID of the first device meeting specified criteria.\n  else if (nargin == 4)\n    {\n      int io = args(0).int_value ();\n      int rate = args(1).int_value ();\n      int bits = args(2).int_value ();\n      int chans = args(3).int_value ();\n\n      for (int i = 0; i < num_devices; i++)\n        {\n          PaStreamParameters stream_parameters;\n          stream_parameters.device = i;\n          stream_parameters.channelCount = chans;\n          PaSampleFormat format = bits_to_format (bits);\n\n          if (format != 0)\n            stream_parameters.sampleFormat = format;\n          else\n            error (\"audiodevinfo: invalid bits per sample format\");\n\n          const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);\n\n          if (! device_info)\n            {\n              warning_with_id (\"Octave:invalid-audio-device\",\n                               \"invalid audio device ID = %d\", i);\n              continue;\n            }\n\n          stream_parameters.suggestedLatency\n            = device_info->defaultLowInputLatency;\n\n          stream_parameters.hostApiSpecificStreamInfo = nullptr;\n\n          if (io == 0)\n            {\n              if (device_info->maxOutputChannels < chans)\n                continue;\n\n              err = Pa_IsFormatSupported (nullptr, &stream_parameters, rate);\n\n              if (err == paFormatIsSupported)\n                {\n                  retval = i;\n                  return retval;\n                }\n            }\n          else if (io == 1)\n            {\n              if (device_info->maxInputChannels < chans)\n                continue;\n\n              err = Pa_IsFormatSupported (&stream_parameters, nullptr, rate);\n              if (err == paFormatIsSupported)\n                {\n                  retval = i;\n                  return retval;\n                }\n            }\n        }\n      retval = -1;\n    }\n  // Check if given device supports specified playback or recording modes.\n  else if (nargin == 5)\n    {\n      int io = args(0).int_value ();\n      int m_id = args(1).int_value ();\n      int rate = args(2).int_value ();\n      int bits = args(3).int_value ();\n      int chans = args(4).int_value ();\n      PaStreamParameters stream_parameters;\n      stream_parameters.device = m_id;\n      stream_parameters.channelCount = chans;\n      PaSampleFormat format = bits_to_format (bits);\n      if (format != 0)\n        stream_parameters.sampleFormat = format;\n      else\n        error (\"audiodevinfo: invalid bits per sample format\");\n\n      const PaDeviceInfo *device_info = Pa_GetDeviceInfo (m_id);\n\n      if (! device_info)\n        error (\"audiodevinfo: invalid audio device ID = %d\", m_id);\n\n      stream_parameters.suggestedLatency\n        = device_info->defaultLowInputLatency;\n\n      stream_parameters.hostApiSpecificStreamInfo = nullptr;\n      if (io == 0)\n        {\n          if (device_info->maxOutputChannels < chans)\n            {\n              retval = false;\n              return retval;\n            }\n          err = Pa_IsFormatSupported (nullptr, &stream_parameters, rate);\n          if (err == paFormatIsSupported)\n            {\n              retval = true;\n              return retval;\n            }\n        }\n      else if (io == 1)\n        {\n          if (device_info->maxInputChannels < chans)\n            {\n              retval = false;\n              return retval;\n            }\n          err = Pa_IsFormatSupported (&stream_parameters, nullptr, rate);\n          if (err == paFormatIsSupported)\n            {\n              retval = true;\n              return retval;\n            }\n        }\n      else\n        error (\"audiodevinfo: specify 0 for output and 1 for input devices\");\n\n      retval = false;\n    }\n\n  return retval;\n\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"audiodevinfo\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\n/*\n%!testif HAVE_PORTAUDIO\n%! devinfo = audiodevinfo;\n%! assert (rows (devinfo.input), 1);\n%! assert (rows (devinfo.output), 1);\n\n%!testif HAVE_PORTAUDIO\n%! devinfo = audiodevinfo;\n%! nout = audiodevinfo (0);\n%! nin = audiodevinfo (1);\n%! assert (columns (devinfo.output), nout);\n%! assert (columns (devinfo.input), nin);\n\n%!testif HAVE_PORTAUDIO\n%! devinfo = audiodevinfo;\n%! nout = audiodevinfo (0);\n%! nin = audiodevinfo (1);\n%! for i = 1:nout\n%!   assert (devinfo.output(i).Name, audiodevinfo (0, devinfo.output(i).ID));\n%! endfor\n%! for i=1:nin\n%!   assert (devinfo.input (i).Name, audiodevinfo (1, devinfo.input (i).ID));\n%! endfor\n\n%!testif HAVE_PORTAUDIO\n%! devinfo = audiodevinfo;\n%! nout = audiodevinfo (0);\n%! nin = audiodevinfo (1);\n%! ## There might be multiple devices with the same name\n%! ## (e.g., on Windows WDM-KS)\n%! ## Check only the first of each unique device name.\n%! [unq_out_name, idx_unique] = unique ({devinfo.output(:).Name});\n%! unq_out_id = [devinfo.output(idx_unique).ID];\n%! for i = 1:numel (unq_out_name)\n%!   assert (audiodevinfo (0, unq_out_name{i}), unq_out_id(i));\n%! endfor\n%! [unq_in_name, idx_unique] = unique ({devinfo.input(:).Name});\n%! unq_in_id = [devinfo.input(idx_unique).ID];\n%! for i = 1:numel (unq_in_name)\n%!   assert (audiodevinfo (1, unq_in_name{i}), unq_in_id(i));\n%! endfor\n*/\n\n#if defined (HAVE_PORTAUDIO)\n\nenum audio_type { TYPE_INT8, TYPE_UINT8, TYPE_UINT16, TYPE_DOUBLE };\n\nclass audioplayer : public octave_base_dld_value\n{\npublic:\n\n  audioplayer ();\n\n  OCTAVE_DISABLE_COPY_MOVE (audioplayer)\n\n  ~audioplayer ();\n\n  // Overloaded base functions\n  double player_value () const { return 0; }\n  virtual double scalar_value (bool = false) const { return 0; }\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n  void print_raw (std::ostream& os, bool pr_as_read_syntax) const;\n\n  // Properties\n  bool is_constant () const { return true; }\n  bool is_defined () const { return true; }\n  bool print_as_scalar () const { return true; }\n\n  void init ();\n  void set_y (const octave_value& m_y);\n  void set_y (octave_function *fcn);\n  void set_y (std::string fcn);\n  Matrix& get_y ();\n  RowVector get_left () const;\n  RowVector get_right () const;\n  void set_fs (int m_fs);\n  int get_fs ();\n  void set_nbits (int m_nbits);\n  int get_nbits ();\n  void set_id (int m_id);\n  int get_id ();\n  int get_channels ();\n  audio_type get_type ();\n\n  void set_sample_number (unsigned int sample);\n  unsigned int get_sample_number ();\n  unsigned int get_total_samples ();\n  void set_end_sample (unsigned int sample);\n  unsigned int get_end_sample ();\n  void reset_end_sample ();\n  void set_tag (const charMatrix& m_tag);\n  charMatrix get_tag ();\n  void set_userdata (const octave_value& m_userdata);\n  octave_value get_userdata ();\n  PaStream * get_stream ();\n\n  void play ();\n  void playblocking ();\n  void pause ();\n  void resume ();\n  void stop ();\n  bool isplaying ();\n\n  octave_function *octave_callback_function;\n\nprivate:\n  int m_id;\n  int m_fs;\n  int m_nbits;\n  int m_channels;\n  unsigned int m_sample_number;\n  unsigned int m_end_sample;\n  charMatrix m_tag;\n  Matrix m_y;\n  octave_value m_userdata;\n  RowVector m_left;\n  RowVector m_right;\n  PaStream *m_stream;\n  PaStreamParameters m_output_parameters;\n  audio_type m_type;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA\n};\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audioplayer, \"audioplayer\", \"audioplayer\");\n\nstatic int\noctave_play_callback (const void *, void *output, unsigned long frames,\n                      const PaStreamCallbackTimeInfo *,\n                      PaStreamCallbackFlags, void *data)\n{\n  audioplayer *player = static_cast<audioplayer *> (data);\n\n  if (! player)\n    error (\"audioplayer callback function called without player\");\n\n  interpreter& interp = __get_interpreter__ ();\n\n  octave_value_list retval\n    = interp.feval (player->octave_callback_function,\n                    ovl (static_cast<double> (frames)), 1);\n\n  if (retval.length () < 2)\n    error (\"audioplayer callback function failed\");\n\n  const Matrix sound = retval(0).matrix_value ();\n  int return_status = retval(1).int_value ();\n\n  if (frames - sound.rows () != 0 || sound.columns () < 1\n      || sound.columns () > 2)\n    error (\"audioplayer callback function failed\");\n\n  // Don't multiply the audio data by scale_factor here.  Although it\n  // does move the operation outside of the loops below, it also causes\n  // a second copy of the data array to be made.\n\n  const ColumnVector sound_l = sound.column (0);\n  const ColumnVector sound_r = (sound.columns () == 1\n                                ? sound_l : sound.column (1));\n\n  const double *p_l = sound_l.data ();\n  const double *p_r = sound_r.data ();\n\n  switch (player->get_nbits ())\n    {\n    case 8:\n      {\n        static double scale_factor = std::pow (2.0, 7) - 1.0;\n\n        int8_t *buffer = static_cast<int8_t *> (output);\n\n        for (unsigned long i = 0; i < frames; i++)\n          {\n            buffer[2*i] = p_l[i] * scale_factor;\n            buffer[2*i+1] = p_r[i] * scale_factor;\n          }\n      }\n      break;\n\n    case 16:\n      {\n        static double scale_factor = std::pow (2.0, 15) - 1.0;\n\n        int16_t *buffer = static_cast<int16_t *> (output);\n\n        for (unsigned long i = 0; i < frames; i++)\n          {\n            buffer[2*i] = p_l[i] * scale_factor;\n            buffer[2*i+1] = p_r[i] * scale_factor;\n          }\n      }\n      break;\n\n    case 24:\n      {\n        static double scale_factor = std::pow (2.0, 23) - 1.0;\n\n        static int big_endian = mach_info::words_big_endian ();\n\n        uint8_t *buffer = static_cast<uint8_t *> (output);\n\n        for (unsigned long i = 0; i < frames; i++)\n          {\n            int32_t sample_l = p_l[i];\n            int32_t sample_r = p_r[i];\n\n            sample_l &= 0x00ffffff;\n            sample_r &= 0x00ffffff;\n\n            uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);\n            uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);\n\n            unsigned long offset = i * 6;\n\n            buffer[offset+0] = _sample_l[0+big_endian] * scale_factor;\n            buffer[offset+1] = _sample_l[1+big_endian] * scale_factor;\n            buffer[offset+2] = _sample_l[2+big_endian] * scale_factor;\n\n            buffer[offset+3] = _sample_r[0+big_endian] * scale_factor;\n            buffer[offset+4] = _sample_r[1+big_endian] * scale_factor;\n            buffer[offset+5] = _sample_r[2+big_endian] * scale_factor;\n          }\n      }\n      break;\n\n    default:\n      error (\"invalid bit depth in audioplayer callback function\");\n    }\n\n  return return_status;\n}\n\nstatic int\nportaudio_play_callback (const void *, void *output, unsigned long frames,\n                         const PaStreamCallbackTimeInfo *,\n                         PaStreamCallbackFlags, void *data)\n{\n  audioplayer *player = static_cast<audioplayer *> (data);\n\n  if (! player)\n    error (\"audioplayer callback function called without player\");\n\n  // Don't multiply the audio data by scale_factor here.  Although it would\n  // move the operation outside of the loops below, it also causes a second\n  // copy of the *entire* data array to be made when only a small portion\n  // (buffer_size elements) is usually needed for this callback.\n\n  const RowVector sound_l = player->get_left ();\n  const RowVector sound_r = player->get_right ();\n\n  const double *pl = sound_l.data ();\n  const double *pr = sound_r.data ();\n\n  if (player->get_type () == TYPE_DOUBLE)\n    {\n      switch (player->get_nbits ())\n        {\n        case 8:\n          {\n            static double scale_factor = std::pow (2.0, 7) - 1.0;\n\n            int8_t *buffer = static_cast<int8_t *> (output);\n\n            for (unsigned long j = 0; j < frames; j++)\n              {\n                unsigned int m_sample_number = player->get_sample_number ();\n\n                if (m_sample_number >= player->get_end_sample ())\n                  return paComplete;\n\n                unsigned long offset = j * 2;\n\n                buffer[offset+0] = pl[m_sample_number] * scale_factor;\n                buffer[offset+1] = pr[m_sample_number] * scale_factor;\n\n                player->set_sample_number (m_sample_number + 1);\n              }\n          }\n          break;\n\n        case 16:\n          {\n            static double scale_factor = std::pow (2.0, 15) - 1.0;\n\n            int16_t *buffer = static_cast<int16_t *> (output);\n\n            for (unsigned long j = 0; j < frames; j++)\n              {\n                unsigned int m_sample_number = player->get_sample_number ();\n\n                if (m_sample_number >= player->get_end_sample ())\n                  return paComplete;\n\n                unsigned long offset = j * 2;\n\n                buffer[offset+0] = pl[m_sample_number] * scale_factor;\n                buffer[offset+1] = pr[m_sample_number] * scale_factor;\n\n                player->set_sample_number (m_sample_number + 1);\n              }\n          }\n          break;\n\n        case 24:\n          {\n            static double scale_factor = std::pow (2.0, 23) - 1.0;\n\n            static int big_endian = mach_info::words_big_endian ();\n\n            uint8_t *buffer = static_cast<uint8_t *> (output);\n\n            for (unsigned long j = 0; j < frames; j++)\n              {\n                unsigned int m_sample_number = player->get_sample_number ();\n\n                if (m_sample_number >= player->get_end_sample ())\n                  return paComplete;\n\n                int32_t sample_l = pl[m_sample_number] * scale_factor;\n                int32_t sample_r = pr[m_sample_number] * scale_factor;\n\n                sample_l &= 0x00ffffff;\n                sample_r &= 0x00ffffff;\n\n                uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);\n                uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);\n\n                unsigned long offset = j * 6;\n\n                buffer[offset+0] = _sample_l[0+big_endian];\n                buffer[offset+1] = _sample_l[1+big_endian];\n                buffer[offset+2] = _sample_l[2+big_endian];\n\n                buffer[offset+3] = _sample_r[0+big_endian];\n                buffer[offset+4] = _sample_r[1+big_endian];\n                buffer[offset+5] = _sample_r[2+big_endian];\n\n                player->set_sample_number (m_sample_number + 1);\n              }\n          }\n          break;\n\n        default:\n          error (\"invalid bit depth in audioplayer callback function\");\n        }\n    }\n  else if (player->get_type () == TYPE_INT8)\n    {\n      int8_t *buffer = static_cast<int8_t *> (output);\n\n      for (unsigned long j = 0; j < frames; j++)\n        {\n          unsigned int m_sample_number = player->get_sample_number ();\n\n          if (m_sample_number >= player->get_end_sample ())\n            return paComplete;\n\n          unsigned long offset = j * 2;\n\n          buffer[offset+0] = pl[m_sample_number];\n          buffer[offset+1] = pr[m_sample_number];\n\n          player->set_sample_number (m_sample_number + 1);\n        }\n    }\n  else if (player->get_type () == TYPE_UINT8)\n    {\n      uint8_t *buffer = static_cast<uint8_t *> (output);\n\n      for (unsigned long j = 0; j < frames; j++)\n        {\n          unsigned int m_sample_number = player->get_sample_number ();\n\n          if (m_sample_number >= player->get_end_sample ())\n            return paComplete;\n\n          unsigned long offset = j * 2;\n\n          buffer[offset+0] = pl[m_sample_number];\n          buffer[offset+1] = pr[m_sample_number];\n\n          player->set_sample_number (m_sample_number + 1);\n        }\n    }\n  else if (player->get_type () == TYPE_UINT16)\n    {\n      int16_t *buffer = static_cast<int16_t *> (output);\n\n      for (unsigned long j = 0; j < frames; j++)\n        {\n          unsigned int m_sample_number = player->get_sample_number ();\n\n          if (m_sample_number >= player->get_end_sample ())\n            return paComplete;\n\n          unsigned long offset = j * 2;\n\n          buffer[offset+0] = pl[m_sample_number];\n          buffer[offset+1] = pr[m_sample_number];\n\n          player->set_sample_number (m_sample_number + 1);\n        }\n    }\n\n  return paContinue;\n}\n\naudioplayer::audioplayer ()\n  : octave_callback_function (nullptr),\n    m_id (-1), m_fs (0), m_nbits (16), m_channels (0), m_sample_number (0),\n    m_end_sample (-1), m_tag (\"\"), m_y (), m_userdata (Matrix ()),\n    m_left (), m_right (), m_stream (nullptr), m_output_parameters (), m_type ()\n{ }\n\naudioplayer::~audioplayer ()\n{\n  if (isplaying ())\n    {\n      warning_with_id (\"Octave:audio-interrupt\",\n                       \"interrupting audioplayer during playback\");\n      stop ();\n    }\n\n  Pa_Terminate ();  // PortAudio required cleanup\n}\n\nvoid\naudioplayer::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\n\nvoid\naudioplayer::print_raw (std::ostream& os, bool) const\n{\n  os << 0;\n}\n\nvoid\naudioplayer::init ()\n{\n  // FIXME: Both of these variables are unused.\n  // Should they be eliminated or is something not yet implemented?\n  //\n  // int channels = y.rows ();\n  // RowVector *sound_l = get_left ();\n\n  std::string errstr;\n  PaError err = octave::sys::capture_stderr ([] { return Pa_Initialize (); },\n                                             errstr);\n  if (err != paNoError)\n    {\n      std::cerr << errstr << std::endl;\n      error (\"audioplayer: initialization error\");\n    }\n\n  if (Pa_GetDeviceCount () < 1)\n    error (\"audioplayer: no audio devices found or available\");\n\n  int device = get_id ();\n\n  if (device == -1)\n    device = Pa_GetDefaultOutputDevice ();\n\n  m_output_parameters.device = device;\n  m_output_parameters.channelCount = 2;\n\n  if (m_type == TYPE_DOUBLE)\n    m_output_parameters.sampleFormat = bits_to_format (get_nbits ());\n  else if (m_type == TYPE_INT8)\n    m_output_parameters.sampleFormat = paInt8;\n  else if (m_type == TYPE_UINT8)\n    m_output_parameters.sampleFormat = paUInt8;\n  else if (m_type == TYPE_UINT16)\n    m_output_parameters.sampleFormat = paInt16;\n\n  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);\n\n  if (! device_info)\n    warning_with_id (\"Octave:invalid-default-audio-device\",\n                     \"invalid default audio device ID = %d\", device);\n\n  m_output_parameters.suggestedLatency\n    = (device_info ? device_info->defaultHighOutputLatency : -1);\n\n  m_output_parameters.hostApiSpecificStreamInfo = nullptr;\n}\n\nvoid\naudioplayer::set_y (const octave_value& y_arg)\n{\n  if (y_arg.is_int8_type ())\n    m_type = TYPE_INT8;\n  else if (y_arg.is_uint8_type ())\n    m_type = TYPE_UINT8;\n  else if (y_arg.is_int16_type ())\n    m_type = TYPE_UINT16;\n  else\n    m_type = TYPE_DOUBLE;\n\n  m_y = y_arg.matrix_value ();\n\n  if (m_y.rows () > 2)\n    m_y = m_y.transpose ();\n\n  m_channels = m_y.rows ();\n  m_left = m_y.row (0);\n\n  if (m_channels == 2)\n    m_right = m_y.row (1);\n\n  reset_end_sample ();\n}\n\nvoid\naudioplayer::set_y (octave_function *fcn)\n{\n  octave_callback_function = fcn;\n  m_channels = 2;\n  reset_end_sample ();\n}\n\nMatrix&\naudioplayer::get_y ()\n{\n  return m_y;\n}\n\nRowVector\naudioplayer::get_left () const\n{\n  return m_left;\n}\n\nRowVector\naudioplayer::get_right () const\n{\n  return m_channels == 1 ? m_left : m_right;\n}\n\nvoid\naudioplayer::set_fs (int fs_arg)\n{\n  m_fs = fs_arg;\n}\n\nint\naudioplayer::get_fs ()\n{\n  return m_fs;\n}\n\nvoid\naudioplayer::set_nbits (int nbits_arg)\n{\n  m_nbits = nbits_arg;\n}\n\nint\naudioplayer::get_nbits ()\n{\n  return m_nbits;\n}\n\nvoid\naudioplayer::set_id (int id_arg)\n{\n  m_id = id_arg;\n}\n\nint\naudioplayer::get_id ()\n{\n  return m_id;\n}\n\nint\naudioplayer::get_channels ()\n{\n  return m_channels;\n}\n\naudio_type\naudioplayer::get_type ()\n{\n  return m_type;\n}\n\nvoid\naudioplayer::set_sample_number (unsigned int sample_number_arg)\n{\n  m_sample_number = sample_number_arg;\n}\n\nunsigned int\naudioplayer::get_sample_number ()\n{\n  return m_sample_number;\n}\n\nunsigned int\naudioplayer::get_total_samples ()\n{\n  return m_left.numel ();\n}\n\nvoid\naudioplayer::set_end_sample (unsigned int end_sample_arg)\n{\n  m_end_sample = end_sample_arg;\n}\n\nunsigned int\naudioplayer::get_end_sample ()\n{\n  return m_end_sample;\n}\n\nvoid\naudioplayer::reset_end_sample ()\n{\n  set_end_sample (m_left.numel ());\n}\n\nvoid\naudioplayer::set_tag (const charMatrix& tag_arg)\n{\n  m_tag = tag_arg;\n}\n\ncharMatrix\naudioplayer::get_tag ()\n{\n  return m_tag;\n}\n\nvoid\naudioplayer::set_userdata (const octave_value& userdata_arg)\n{\n  m_userdata = userdata_arg;\n}\n\noctave_value\naudioplayer::get_userdata ()\n{\n  return m_userdata;\n}\n\nvoid\naudioplayer::playblocking ()\n{\n  if (get_stream ())\n    stop ();\n\n  const unsigned int buffer_size = get_fs () / 20;\n  OCTAVE_LOCAL_BUFFER (uint32_t, buffer, buffer_size * 2);\n\n  PaError err;\n  err = Pa_OpenStream (&m_stream, nullptr, &(m_output_parameters), get_fs (),\n                       buffer_size, paClipOff, nullptr, nullptr);\n  if (err != paNoError)\n    error (\"audioplayer: unable to open audio playback stream\");\n\n  err = Pa_StartStream (m_stream);\n  if (err != paNoError)\n    error (\"audioplayer: unable to start audio playback stream\");\n\n  unsigned int start, end;\n  start = get_sample_number ();\n  end = get_end_sample ();\n\n  unwind_action stop_audioplayer ([this] () { stop (); });\n\n  for (unsigned int i = start; i < end; i += buffer_size)\n    {\n      octave_quit ();\n\n      if (octave_callback_function != nullptr)\n        octave_play_callback (nullptr, buffer, buffer_size, nullptr, 0, this);\n      else\n        portaudio_play_callback (nullptr, buffer, buffer_size, nullptr, 0, this);\n\n      err = Pa_WriteStream (m_stream, buffer, buffer_size);\n    }\n}\n\nvoid\naudioplayer::play ()\n{\n  if (get_stream ())\n    stop ();\n\n  const unsigned int buffer_size = get_fs () / 20;\n\n  PaError err;\n  if (octave_callback_function != nullptr)\n    err = Pa_OpenStream (&m_stream, nullptr, &(m_output_parameters),\n                         get_fs (), buffer_size, paClipOff,\n                         octave_play_callback, this);\n  else\n    err = Pa_OpenStream (&m_stream, nullptr, &(m_output_parameters),\n                         get_fs (), buffer_size, paClipOff,\n                         portaudio_play_callback, this);\n\n  if (err != paNoError)\n    error (\"audioplayer: failed to open audio playback stream\");\n\n  err = Pa_StartStream (m_stream);\n  if (err != paNoError)\n    error (\"audioplayer: failed to start audio playback stream\");\n}\n\nvoid\naudioplayer::pause ()\n{\n  if (get_stream () == nullptr)\n    return;\n\n  PaError err;\n  err = Pa_StopStream (m_stream);\n  if (err != paNoError)\n    error (\"audioplayer: failed to stop audio playback stream\");\n}\n\nvoid\naudioplayer::resume ()\n{\n  if (get_stream () == nullptr)\n    return;\n\n  PaError err;\n  err = Pa_StartStream (m_stream);\n  if (err != paNoError)\n    error (\"audioplayer: failed to start audio playback stream\");\n}\n\nPaStream *\naudioplayer::get_stream ()\n{\n  return m_stream;\n}\n\nvoid\naudioplayer::stop ()\n{\n  if (get_stream () == nullptr)\n    return;\n\n  PaError err;\n  set_sample_number (0);\n  reset_end_sample ();\n  if (! Pa_IsStreamStopped (get_stream ()))\n    {\n      err = Pa_AbortStream (get_stream ());\n      if (err != paNoError)\n        error (\"audioplayer: failed to stop audio playback stream\");\n    }\n\n  err = Pa_CloseStream (get_stream ());\n  if (err != paNoError)\n    error (\"audioplayer: failed to close audio playback stream\");\n\n  m_stream = nullptr;\n}\n\nbool\naudioplayer::isplaying ()\n{\n  if (get_stream () == nullptr)\n    return false;\n\n  PaError err;\n  err = Pa_IsStreamActive (m_stream);\n  if (err != 0 && err != 1)\n    error (\"audioplayer: checking stream activity status failed\");\n\n  return (err == 1);\n}\n\nclass audiorecorder : public octave_base_dld_value\n{\npublic:\n\n  audiorecorder ();\n\n  OCTAVE_DISABLE_COPY_MOVE (audiorecorder)\n\n  ~audiorecorder ();\n\n  // Overloaded base functions\n  double player_value () const { return 0; }\n  virtual double scalar_value (bool = false) const { return 0; }\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n  void print_raw (std::ostream& os, bool pr_as_read_syntax) const;\n\n  // Properties\n  bool is_constant () const { return true; }\n  bool is_defined () const { return true; }\n  bool print_as_scalar () const { return true; }\n\n  void init ();\n  void set_fs (int m_fs);\n  int get_fs ();\n  void set_nbits (int m_nbits);\n  int get_nbits ();\n  PaSampleFormat get_sampleFormat ();\n  void set_id (int m_id);\n  int get_id ();\n  void set_channels (int m_channels);\n  int get_channels ();\n  audio_type get_type ();\n\n  void set_sample_number (unsigned int sample);\n  unsigned int get_sample_number ();\n  unsigned int get_total_samples ();\n  void set_end_sample (unsigned int sample);\n  unsigned int get_end_sample ();\n  void reset_end_sample ();\n  void set_tag (const charMatrix& m_tag);\n  charMatrix get_tag ();\n  void set_userdata (const octave_value& m_userdata);\n  octave_value get_userdata ();\n  PaStream * get_stream ();\n\n  octave_value getaudiodata ();\n  audioplayer * getplayer ();\n  bool isrecording ();\n  audioplayer play ();\n  void record ();\n  void recordblocking (float seconds);\n  void pause ();\n  void resume ();\n  void stop ();\n  void append (float sample_l, float sample_r);\n\n  octave_function *octave_callback_function;\n\nprivate:\n  int m_id;\n  int m_fs;\n  int m_nbits;\n  int m_channels;\n  unsigned int m_sample_number;\n  unsigned int m_end_sample;\n  charMatrix m_tag;\n  Matrix m_y;\n  octave_value m_userdata;\n  std::vector<float> m_left;\n  std::vector<float> m_right;\n  PaStream *m_stream;\n  PaStreamParameters m_input_parameters;\n  audio_type m_type;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA\n};\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audiorecorder, \"audiorecorder\", \"audiorecorder\");\n\nstatic int\noctave_record_callback (const void *input, void *, unsigned long frames,\n                        const PaStreamCallbackTimeInfo *,\n                        PaStreamCallbackFlags, void *data)\n{\n  audiorecorder *recorder = static_cast<audiorecorder *> (data);\n\n  if (! recorder)\n    error (\"audiorecorder callback function called without recorder\");\n\n  int m_channels = recorder->get_channels ();\n\n  Matrix sound (frames, 2);\n  sound.resize (frames, 2);\n\n  if (recorder->get_sampleFormat () == bits_to_format (8))\n    {\n      static double scale_factor = std::pow (2.0, 7) - 1.0;\n\n      const int8_t *input8 = static_cast<const int8_t *> (input);\n\n      for (unsigned long i = 0; i < frames; i++)\n        {\n          float sample_l = input8[i*m_channels] / scale_factor;\n          float sample_r = input8[i*m_channels + (m_channels - 1)] / scale_factor;\n\n          sound(i, 0) = sample_l;\n          sound(i, 1) = sample_r;\n        }\n    }\n  // FIXME: This is a workaround for a bug in PortAudio affecting 8-Bit\n  //        recording (see Octave bug #44305).\n  //        Remove this clause once the bug in PortAudio has been fixed.\n  else if (recorder->get_sampleFormat () == bits_to_format (16)\n           && recorder->get_nbits () == 8)\n    {\n      static double scale_factor = std::pow (2.0, 7) - 1.0;\n\n      const int16_t *input16 = static_cast<const int16_t *> (input);\n\n      for (unsigned long i = 0; i < frames; i++)\n        {\n          float sample_l = (input16[i*m_channels] >> 8) / scale_factor;\n          float sample_r = (input16[i*m_channels + (m_channels - 1)] >> 8)\n                           / scale_factor;\n\n          sound(i, 0) = sample_l;\n          sound(i, 1) = sample_r;\n        }\n    }\n  else if (recorder->get_sampleFormat () == bits_to_format (16))\n    {\n      static double scale_factor = std::pow (2.0, 15) - 1.0;\n\n      const int16_t *input16 = static_cast<const int16_t *> (input);\n\n      for (unsigned long i = 0; i < frames; i++)\n        {\n          float sample_l = input16[i*m_channels] / scale_factor;\n          float sample_r = input16[i*m_channels + (m_channels - 1)] / scale_factor;\n\n          sound(i, 0) = sample_l;\n          sound(i, 1) = sample_r;\n        }\n    }\n  else if (recorder->get_sampleFormat () == bits_to_format (24))\n    {\n      static double scale_factor = std::pow (2.0, 23);\n\n      // FIXME: Is there a better way?\n      // Could use union of int32_t, uint8_t[3:0]?  (12/31/19)\n      const uint8_t *input24 = static_cast<const uint8_t *> (input);\n\n      int32_t sample_l32, sample_r32;\n\n      uint8_t *sample_l = reinterpret_cast<uint8_t *> (&sample_l32);\n      uint8_t *sample_r = reinterpret_cast<uint8_t *> (&sample_r32);\n\n      for (unsigned long i = 0; i < frames; i++)\n        {\n          sample_l32 = sample_r32 = 0;\n          for (int j = 0; j < 3; j++)\n            {\n              sample_l[j] = input24[i*m_channels*3 + j];\n              sample_r[j] = input24[i*m_channels*3 + (m_channels - 1)*3 + j];\n            }\n\n          if (sample_l32 & 0x00800000)\n            sample_l32 |= 0xff000000;\n\n          if (sample_r32 & 0x00800000)\n            sample_r32 |= 0xff000000;\n\n          sound(i, 0) = sample_l32 / scale_factor;\n          sound(i, 1) = sample_r32 / scale_factor;\n        }\n    }\n\n  interpreter& interp = __get_interpreter__ ();\n\n  octave_value_list retval\n    = interp.feval (recorder->octave_callback_function, ovl (sound), 1);\n\n  return retval(0).int_value ();\n}\n\nstatic int\nportaudio_record_callback (const void *input, void *, unsigned long frames,\n                           const PaStreamCallbackTimeInfo *,\n                           PaStreamCallbackFlags, void *data)\n{\n  audiorecorder *recorder = static_cast<audiorecorder *> (data);\n\n  if (! recorder)\n    error (\"audiorecorder callback function called without recorder\");\n\n  int m_channels = recorder->get_channels ();\n\n  if (recorder->get_sampleFormat () == bits_to_format (8))\n    {\n      static float scale_factor = std::pow (2.0f, 7) - 1.0f;\n\n      const int8_t *input8 = static_cast<const int8_t *> (input);\n\n      for (unsigned long i = 0; i < frames; i++)\n        {\n          float sample_l = input8[i*m_channels] / scale_factor;\n          float sample_r = input8[i*m_channels + (m_channels - 1)] / scale_factor;\n\n          recorder->append (sample_l, sample_r);\n        }\n    }\n  // FIXME: This is a workaround for a bug in PortAudio affecting 8-Bit\n  //        recording (see Octave bug #44305).\n  //        Remove this clause once the bug in PortAudio has been fixed.\n  else if (recorder->get_sampleFormat () == bits_to_format (16)\n           && recorder->get_nbits () == 8)\n    {\n      static double scale_factor = std::pow (2.0, 7) - 1.0;\n\n      const int16_t *input16 = static_cast<const int16_t *> (input);\n\n      for (unsigned long i = 0; i < frames; i++)\n        {\n          float sample_l = (input16[i*m_channels] >> 8) / scale_factor;\n          float sample_r = (input16[i*m_channels + (m_channels - 1)] >> 8)\n                           / scale_factor;\n\n          recorder->append (sample_l, sample_r);\n        }\n    }\n  else if (recorder->get_sampleFormat () == bits_to_format (16))\n    {\n      static float scale_factor = std::pow (2.0f, 15) - 1.0f;\n\n      const int16_t *input16 = static_cast<const int16_t *> (input);\n\n      for (unsigned long i = 0; i < frames; i++)\n        {\n          float sample_l = input16[i*m_channels] / scale_factor;\n          float sample_r = input16[i*m_channels + (m_channels - 1)] / scale_factor;\n\n          recorder->append (sample_l, sample_r);\n        }\n    }\n  else if (recorder->get_sampleFormat () == bits_to_format (24))\n    {\n      static float scale_factor = std::pow (2.0f, 23);\n\n      // FIXME: Is there a better way?\n      // Could use union of int32_t, uint8_t[3:0]?  (12/31/19)\n      const uint8_t *input24 = static_cast<const uint8_t *> (input);\n\n      int32_t sample_l32, sample_r32;\n\n      uint8_t *sample_l = reinterpret_cast<uint8_t *> (&sample_l32);\n      uint8_t *sample_r = reinterpret_cast<uint8_t *> (&sample_r32);\n\n      for (unsigned long i = 0; i < frames; i++)\n        {\n          sample_l32 = sample_r32 = 0;\n          for (int j = 0; j < 3; j++)\n            {\n              sample_l[j] = input24[i*m_channels*3 + j];\n              sample_r[j] = input24[i*m_channels*3 + (m_channels - 1)*3 + j];\n            }\n\n          if (sample_l32 & 0x00800000)\n            sample_l32 |= 0xff000000;\n\n          if (sample_r32 & 0x00800000)\n            sample_r32 |= 0xff000000;\n\n          recorder->append (sample_l32 / scale_factor,\n                            sample_r32 / scale_factor);\n        }\n    }\n\n  if (recorder->get_sample_number () >= recorder->get_end_sample ())\n    return paComplete;\n\n  return paContinue;\n}\n\naudiorecorder::audiorecorder ()\n  : octave_callback_function (nullptr),\n    m_id (-1), m_fs (8000), m_nbits (8), m_channels (1), m_sample_number (0),\n    m_end_sample (-1), m_tag (\"\"), m_y (), m_userdata (Matrix ()),\n    m_left (), m_right (), m_stream (nullptr), m_input_parameters (), m_type ()\n{ }\n\naudiorecorder::~audiorecorder ()\n{\n  if (isrecording ())\n    {\n      warning_with_id (\"Octave:audio-interrupt\",\n                       \"interrupting audiorecorder during recording\");\n      stop ();\n    }\n\n  Pa_Terminate ();  // PortAudio required cleanup\n}\n\nvoid\naudiorecorder::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\n\nvoid\naudiorecorder::print_raw (std::ostream& os, bool) const\n{\n  os << 0;\n}\n\nvoid\naudiorecorder::init ()\n{\n  std::string errstr;\n  PaError err = octave::sys::capture_stderr ([] { return Pa_Initialize (); },\n                                             errstr);\n  if (err != paNoError)\n    {\n      std::cerr << errstr << std::endl;\n      error (\"audiorecorder: initialization error\");\n    }\n\n  if (Pa_GetDeviceCount () < 1)\n    error (\"audiorecorder: no audio devices found or available\");\n\n  int device = get_id ();\n\n  if (device == -1)\n    device = Pa_GetDefaultInputDevice ();\n\n  m_input_parameters.device = device;\n  m_input_parameters.channelCount = get_channels ();\n  m_input_parameters.sampleFormat = bits_to_format (get_nbits ());\n\n  // FIXME: This is a workaround for a bug in PortAudio affecting 8-Bit\n  //        recording (see Octave bug #44305).\n  //        Remove this clause once the bug in PortAudio has been fixed.\n  if (get_nbits () == 8)\n    m_input_parameters.sampleFormat = bits_to_format (16);\n\n  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);\n\n  if (! device_info)\n    warning_with_id (\"Octave:invalid-default-audio-device\",\n                     \"invalid default audio device ID = %d\", device);\n\n  m_input_parameters.suggestedLatency\n    = (device_info ? device_info->defaultHighInputLatency : -1);\n\n  m_input_parameters.hostApiSpecificStreamInfo = nullptr;\n}\n\nvoid\naudiorecorder::set_fs (int fs_arg)\n{\n  m_fs = fs_arg;\n}\n\nint\naudiorecorder::get_fs ()\n{\n  return m_fs;\n}\n\nvoid\naudiorecorder::set_nbits (int nbits_arg)\n{\n  m_nbits = nbits_arg;\n}\n\nint\naudiorecorder::get_nbits ()\n{\n  return m_nbits;\n}\n\nPaSampleFormat\naudiorecorder::get_sampleFormat ()\n{\n  return m_input_parameters.sampleFormat;\n}\n\nvoid\naudiorecorder::set_id (int id_arg)\n{\n  m_id = id_arg;\n}\n\nint\naudiorecorder::get_id ()\n{\n  return m_id;\n}\n\nvoid\naudiorecorder::set_channels (int channels_arg)\n{\n  if (channels_arg != 1 && channels_arg != 2)\n    error (\"audiorecorder: number of channels must be 1 or 2\");\n\n  m_channels = channels_arg;\n}\n\nint\naudiorecorder::get_channels ()\n{\n  return m_channels;\n}\n\naudio_type\naudiorecorder::get_type ()\n{\n  return m_type;\n}\n\nvoid\naudiorecorder::set_sample_number (unsigned int sample_number_arg)\n{\n  m_sample_number = sample_number_arg;\n}\n\nunsigned int\naudiorecorder::get_sample_number ()\n{\n  return m_sample_number;\n}\n\nunsigned int\naudiorecorder::get_total_samples ()\n{\n  return m_left.size ();\n}\n\nvoid\naudiorecorder::set_end_sample (unsigned int end_sample_arg)\n{\n  m_end_sample = end_sample_arg;\n}\n\nunsigned int\naudiorecorder::get_end_sample ()\n{\n  return m_end_sample;\n}\n\nvoid\naudiorecorder::reset_end_sample ()\n{\n  set_end_sample (m_left.size ());\n}\n\nvoid\naudiorecorder::set_tag (const charMatrix& tag_arg)\n{\n  m_tag = tag_arg;\n}\n\ncharMatrix\naudiorecorder::get_tag ()\n{\n  return m_tag;\n}\n\nvoid\naudiorecorder::set_userdata (const octave_value& userdata_arg)\n{\n  m_userdata = userdata_arg;\n}\n\noctave_value\naudiorecorder::get_userdata ()\n{\n  return m_userdata;\n}\n\noctave_value\naudiorecorder::getaudiodata ()\n{\n  // Must get size before entering loop as the value of left.size() may change\n  // during loop with simultaneous recording and playback (bug #50674).\n  unsigned int ls = m_left.size ();\n  Matrix audio (2, ls);\n\n  for (unsigned int i = 0; i < ls; i++)\n    {\n      audio(0, i) = m_left[i];\n      audio(1, i) = m_right[i];\n    }\n\n  return audio;\n}\n\naudioplayer *\naudiorecorder::getplayer ()\n{\n  std::unique_ptr<audioplayer> player (new audioplayer ());\n\n  player->set_y (getaudiodata ());\n  player->set_fs (get_fs ());\n  player->set_nbits (get_nbits ());\n  player->init ();\n\n  return player.release ();\n}\n\nbool\naudiorecorder::isrecording ()\n{\n  if (get_stream () == nullptr)\n    return false;\n\n  PaError err;\n  err = Pa_IsStreamActive (m_stream);\n  if (err != 0 && err != 1)\n    error (\"audiorecorder: checking stream activity status failed\");\n\n  return (err == 1);\n}\n\nvoid\naudiorecorder::record ()\n{\n  if (get_stream ())\n    stop ();\n\n  m_left.clear ();\n  m_right.clear ();\n\n  const unsigned int buffer_size = get_fs () / 20;\n\n  PaError err;\n  if (octave_callback_function != nullptr)\n    {\n      err = Pa_OpenStream (&m_stream, &(m_input_parameters), nullptr,\n                           get_fs (), buffer_size, paClipOff,\n                           octave_record_callback, this);\n    }\n  else\n    {\n      err = Pa_OpenStream (&m_stream, &(m_input_parameters), nullptr,\n                           get_fs (), buffer_size, paClipOff,\n                           portaudio_record_callback, this);\n    }\n  if (err != paNoError)\n    error (\"audiorecorder: unable to open audio recording stream\");\n\n  err = Pa_StartStream (m_stream);\n  if (err != paNoError)\n    error (\"audiorecorder: unable to start audio recording stream\");\n}\n\nvoid\naudiorecorder::recordblocking (float seconds)\n{\n  if (get_stream ())\n    stop ();\n\n  m_left.clear ();\n  m_right.clear ();\n\n  const unsigned int buffer_size = get_fs () / 20;\n  OCTAVE_LOCAL_BUFFER (uint8_t, buffer, buffer_size * 2 * 3);\n\n  PaError err;\n  err = Pa_OpenStream (&m_stream, &(m_input_parameters), nullptr,\n                       get_fs (), buffer_size, paClipOff, nullptr, this);\n  if (err != paNoError)\n    error (\"audiorecorder: unable to open audio recording stream\");\n\n  err = Pa_StartStream (m_stream);\n  if (err != paNoError)\n    error (\"audiorecorder: unable to start audio recording stream\");\n\n  unsigned int frames = seconds * get_fs ();\n\n  unwind_action stop_audiorecorder ([this] () { stop (); });\n\n  for (unsigned int i = 0; i < frames; i += buffer_size)\n    {\n      octave_quit ();\n\n      Pa_ReadStream (get_stream (), buffer, buffer_size);\n\n      if (octave_callback_function != nullptr)\n        octave_record_callback (buffer, nullptr, buffer_size, nullptr, 0, this);\n      else\n        portaudio_record_callback (buffer, nullptr, buffer_size, nullptr, 0, this);\n    }\n}\n\nvoid\naudiorecorder::pause ()\n{\n  if (get_stream () == nullptr)\n    return;\n\n  PaError err;\n  err = Pa_StopStream (m_stream);\n  if (err != paNoError)\n    error (\"audiorecorder: unable to stop audio recording stream\");\n}\n\nvoid\naudiorecorder::resume ()\n{\n  if (get_stream () == nullptr)\n    return;\n\n  PaError err;\n  err = Pa_StartStream (m_stream);\n  if (err != paNoError)\n    error (\"audiorecorder: unable to start audio recording stream\");\n}\n\nvoid\naudiorecorder::stop ()\n{\n  if (get_stream () == nullptr)\n    return;\n\n  PaError err;\n  if (! Pa_IsStreamStopped (get_stream ()))\n    {\n      err = Pa_AbortStream (get_stream ());\n      if (err != paNoError)\n        error (\"audioplayer: unable to stop audio playback stream\");\n    }\n\n  err = Pa_CloseStream (m_stream);\n  if (err != paNoError)\n    error (\"audiorecorder: unable to close audio recording stream\");\n\n  set_sample_number (0);\n  reset_end_sample ();\n  m_stream = nullptr;\n}\n\nvoid\naudiorecorder::append (float sample_l, float sample_r)\n{\n  m_left.push_back (sample_l);\n  m_right.push_back (sample_r);\n  set_sample_number (get_sample_number () + 1);\n}\n\nPaStream *\naudiorecorder::get_stream ()\n{\n  return m_stream;\n}\n\n#endif\n\nDEFUN_DLD (__recorder_audiorecorder__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{recorder} =} __recorder_audiorecorder__ (@var{fs}, @var{nbits}, @var{channels})\n@deftypefnx {} {@var{recorder} =} __recorder_audiorecorder__ (@var{fs}, @var{nbits}, @var{channels}, @var{id})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n\n  int nargin = args.length ();\n\n  std::unique_ptr<audiorecorder> recorder (new audiorecorder ());\n\n  if (nargin >= 3)\n    {\n      recorder->set_fs (args(0).int_value ());\n      recorder->set_nbits (args(1).int_value ());\n      recorder->set_channels (args(2).int_value ());\n    }\n\n  if (nargin == 4)\n    {\n      recorder->set_id (args(3).int_value ());\n    }\n\n  recorder->init ();\n  retval = recorder.release ();\n\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_audiorecorder__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\n#if defined (HAVE_PORTAUDIO)\n\nstatic audiorecorder *\nget_recorder (const octave_value& ov)\n{\n  const octave_base_value& rep = ov.get_rep ();\n\n  octave_base_value *ncrep = const_cast<octave_base_value *> (&rep);\n\n  audiorecorder *rec = dynamic_cast<audiorecorder *> (ncrep);\n  if (! rec)\n    error (\"audiodevinfo.cc (get_recorder): dynamic_cast to audiorecorder failed\");\n\n  return rec;\n}\n\n#endif\n\nDEFUN_DLD (__recorder_getaudiodata__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{data} =} __recorder_getaudiodata__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->getaudiodata ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_getaudiodata__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_get_channels__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} __recorder_get_channels__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->get_channels ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_get_channels__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_get_fs__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fs} =} __recorder_get_fs__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->get_fs ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_get_fs__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_get_id__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{id} =} __recorder_get_id__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->get_id ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_get_id__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_get_nbits__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{nbits} =} __recorder_get_nbits__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->get_nbits ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_get_nbits__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_get_sample_number__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} __recorder_get_sample_number__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->get_sample_number ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_get_sample_number__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_get_tag__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tag} =} __recorder_get_tag__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->get_tag ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_get_tag__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_get_total_samples__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} __recorder_get_total_samples__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->get_total_samples ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_get_total_samples__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_get_userdata__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{data} =} __recorder_get_userdata__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->get_userdata ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_get_userdata__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_isrecording__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} __recorder_isrecording__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  retval = get_recorder (args(0))->isrecording ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_isrecording__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__recorder_pause__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __recorder_pause__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  get_recorder (args(0))->pause ();\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_pause__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__recorder_recordblocking__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __recorder_recordblocking__ (@var{recorder}, @var{seconds})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  float seconds = args(1).float_value ();\n  get_recorder (args(0))->recordblocking (seconds);\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_recordblocking__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__recorder_record__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __recorder_record__ (@var{recorder})\n@deftypefnx {} {} __recorder_record__ (@var{recorder}, @var{seconds})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  audiorecorder *recorder = get_recorder (args(0));\n\n  if (args.length () == 2)\n    recorder->set_end_sample (args(1).int_value () * recorder->get_fs ());\n\n  recorder->record ();\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_record__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__recorder_resume__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __recorder_resume__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    get_recorder (args(0))->resume ();\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_resume__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__recorder_set_fs__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __recorder_set_fs__ (@var{recorder}, @var{fs})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 2)\n    get_recorder (args(0))->set_fs (args(1).int_value ());\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_set_fs__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__recorder_set_tag__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __recorder_set_tag__ (@var{recorder}, @var{tag})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 2)\n    get_recorder (args(0))->set_tag (args(1).char_matrix_value ());\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_set_tag__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__recorder_set_userdata__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __recorder_set_userdata__ (@var{recorder}, @var{data})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 2)\n    get_recorder (args(0))->set_userdata (args(1));\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_set_userdata__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__recorder_stop__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __recorder_stop__ (@var{recorder})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    get_recorder (args(0))->stop ();\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__recorder_stop__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__player_audioplayer__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs})\n@deftypefnx {} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs}, @var{nbits})\n@deftypefnx {} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs}, @var{nbits}, @var{id})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n\n  std::unique_ptr<audioplayer> player (new audioplayer ());\n\n  player->set_y (args(0));\n  player->set_fs (args(1).int_value ());\n\n  if (args.length () > 2)\n    {\n      // FIXME: Should be able to support 32-bit streams (bug #57939)\n      int m_nbits = args(2).int_value ();\n      if (m_nbits != 8 && m_nbits != 16 && m_nbits != 24)\n        error (\"audioplayer: NBITS must be 8, 16, or 24\");\n\n      switch (args.length ())\n        {\n        case 3:\n          player->set_nbits (m_nbits);\n          break;\n\n        case 4:\n          player->set_nbits (m_nbits);\n          player->set_id (args(3).int_value ());\n          break;\n        }\n    }\n\n  player->init ();\n\n  retval = player.release ();\n\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_audioplayer__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\n#if defined (HAVE_PORTAUDIO)\n\nstatic audioplayer *\nget_player (const octave_value& ov)\n{\n  const octave_base_value& rep = ov.get_rep ();\n\n  octave_base_value *ncrep = const_cast<octave_base_value *> (&rep);\n\n  audioplayer *pl = dynamic_cast<audioplayer *> (ncrep);\n  if (! pl)\n    error (\"audiodevinfo.cc (get_player): dynamic_cast to audioplayer failed\");\n\n  return pl;\n}\n\n#endif\n\nDEFUN_DLD (__player_get_channels__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} __player_get_channels__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    retval = get_player (args(0))->get_channels ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_get_channels__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__player_get_fs__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{fs} =} __player_get_fs__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    retval = get_player (args(0))->get_fs ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_get_fs__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__player_get_id__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{id} =} __player_get_id__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    retval = get_player (args(0))->get_id ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_get_id__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__player_get_nbits__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{nbits} =} __player_get_nbits__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    retval = get_player (args(0))->get_nbits ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_get_nbits__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__player_get_sample_number__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} __player_get_sample_number__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    retval = get_player (args(0))->get_sample_number ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_get_sample_number__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__player_get_tag__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tag} =} __player_get_tag__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    retval = get_player (args(0))->get_tag ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_get_tag__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__player_get_total_samples__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} __player_get_total_samples__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    retval = get_player (args(0))->get_total_samples ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_get_total_samples__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__player_get_userdata__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{data} =} __player_get_userdata__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    retval = get_player (args(0))->get_userdata ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_get_userdata__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__player_isplaying__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} __player_isplaying__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    retval = get_player (args(0))->isplaying ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_isplaying__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n\n  return retval;\n}\n\nDEFUN_DLD (__player_pause__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __player_pause__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    get_player (args(0))->pause ();\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_pause__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__player_playblocking__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __player_playblocking__ (@var{player})\n@deftypefnx {} {} __player_playblocking__ (@var{player}, @var{start})\n@deftypefnx {} {} __player_playblocking__ (@var{player}, [@var{start}, @var{end}])\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n\n  audioplayer *player = get_player (args(0));\n\n  if (args.length () == 1)\n    {\n      player->playblocking ();\n    }\n  else if (args.length () == 2)\n    {\n      if (args(1).is_matrix_type ())\n        {\n          RowVector range = args(1).row_vector_value ();\n\n          unsigned int start = range.elem (0) - 1;\n          unsigned int end = range.elem (1) - 1;\n\n          if (start > player->get_total_samples ()\n              || start > end || end > player->get_total_samples ())\n            error (\"audioplayer: invalid range specified for playback\");\n\n          player->set_sample_number (start);\n          player->set_end_sample (end);\n        }\n      else\n        {\n          unsigned int start = args(1).int_value () - 1;\n\n          if (start > player->get_total_samples ())\n            error (\"audioplayer: invalid range specified for playback\");\n\n          player->set_sample_number (start);\n        }\n\n      player->playblocking ();\n    }\n\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_playblocking__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__player_play__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} __player_play__ (@var{player})\n@deftypefnx {} {} __player_play__ (@var{player}, @var{start})\n@deftypefnx {} {} __player_play__ (@var{player}, [@var{start}, @var{end}])\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n\n  if (args.length () == 1)\n    {\n      get_player (args(0))->play ();\n    }\n  else if (args.length () == 2)\n    {\n      audioplayer *player = get_player (args(0));\n\n      if (args(1).is_matrix_type ())\n        {\n          RowVector range = args(1).row_vector_value ();\n\n          unsigned int start = range.elem (0) - 1;\n          unsigned int end = range.elem (1) - 1;\n\n          if (start > player->get_total_samples ()\n              || start > end || end > player->get_total_samples ())\n            error (\"audioplayer: invalid range specified for playback\");\n\n          player->set_sample_number (start);\n          player->set_end_sample (end);\n        }\n      else\n        {\n          unsigned int start = args(1).int_value () - 1;\n\n          if (start > player->get_total_samples ())\n            error (\"audioplayer: invalid range specified for playback\");\n\n          player->set_sample_number (start);\n        }\n\n      player->play ();\n    }\n\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_play__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__player_resume__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __player_resume__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    get_player (args(0))->resume ();\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_resume__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__player_set_fs__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __player_set_fs__ (@var{player}, @var{fs})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 2)\n    get_player (args(0))->set_fs (args(1).int_value ());\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_set_fs__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__player_set_tag__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __player_set_tag__ (@var{player}, @var{tag})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 2)\n    get_player (args(0))->set_tag (args(1).char_matrix_value ());\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_set_tag__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__player_set_userdata__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __player_set_userdata__ (@var{player}, @var{data})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 2)\n    get_player (args(0))->set_userdata (args(1));\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_set_userdata__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nDEFUN_DLD (__player_stop__, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __player_stop__ (@var{player})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_PORTAUDIO)\n  if (args.length () == 1)\n    get_player (args(0))->stop ();\n  return ovl ();\n#else\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__player_stop__\",\n                        \"audio playback and recording through PortAudio\");\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/audioread.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <map>\n#include <string>\n\n#include \"dMatrix.h\"\n#include \"dRowVector.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"oct-locbuf.h\"\n#include \"unwind-prot.h\"\n\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n\n#if defined (HAVE_SNDFILE)\n#  include <sndfile.h>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN_DLD (audioread, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{y}, @var{fs}] =} audioread (@var{filename})\n@deftypefnx {} {[@var{y}, @var{fs}] =} audioread (@var{filename}, @var{samples})\n\n@deftypefnx {} {[@var{y}, @var{fs}] =} audioread (@var{filename}, @var{datatype})\n@deftypefnx {} {[@var{y}, @var{fs}] =} audioread (@var{filename}, @var{samples}, @var{datatype})\nRead the audio file @var{filename} and return the audio data @var{y} and\nsampling rate @var{fs}.\n\nThe audio data is stored as matrix with rows corresponding to audio frames\nand columns corresponding to channels.\n\nThe optional two-element vector argument @var{samples} specifies starting\nand ending frames.\n\nThe optional argument @var{datatype} specifies the datatype to return.\nIf it is @qcode{\"native\"}, then the type of data depends on how the data\nis stored in the audio file.\n@seealso{audiowrite, audioformats, audioinfo}\n@end deftypefn */)\n{\n#if defined (HAVE_SNDFILE)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n\n  std::string filename = args(0).xstring_value (\"audioread: FILENAME must be a string\");\n\n  SF_INFO info;\n  info.format = 0;\n  SNDFILE *file = sf_open (filename.c_str (), SFM_READ, &info);\n\n  if (! file)\n    error (\"audioread: failed to open input file '%s': %s\",\n           filename.c_str (), sf_strerror (file));\n\n  unwind_action close_open_file ([file] () { sf_close (file); });\n\n  // FIXME: It would be nicer to use a C++ expandable data container and\n  // read a file of unknown length into memory in chunks and determine the\n  // number of samples after reading.  See bug #60888.\n  if (info.frames == SF_COUNT_MAX)\n    error (\"audioread: malformed header does not specify number of samples\");\n\n  OCTAVE_LOCAL_BUFFER (double, data, info.frames * info.channels);\n\n  sf_read_double (file, data, info.frames * info.channels);\n\n  sf_count_t start = 0;\n  sf_count_t end = info.frames;\n\n  if ((nargin == 2 && ! args(1).is_string ()) || nargin == 3)\n    {\n      RowVector range = args(1).row_vector_value ();\n\n      if (range.numel () != 2)\n        error (\"audioread: invalid specification for range of frames\");\n\n      double dstart = (math::isinf (range(0)) ? info.frames : range(0));\n      double dend = (math::isinf (range(1)) ? info.frames : range(1));\n\n      if (dstart < 1 || dstart > dend || dend > info.frames\n          || math::round (dstart) != dstart\n          || math::round (dend) != dend)\n        error (\"audioread: invalid specification for range of frames\");\n\n      start = dstart - 1;\n      end = dend;\n    }\n\n  sf_count_t items = end - start;\n\n  Matrix audio (items, info.channels);\n\n  double *paudio = audio.rwdata ();\n\n  data += start * info.channels;\n\n  for (int i = 0; i < items; i++)\n    {\n      for (int channel = 0; channel < info.channels; channel++)\n        paudio[items*channel+i] = *data++;\n    }\n\n  octave_value ret_audio;\n\n  if ((nargin == 2 && args(1).is_string ()) || nargin == 3)\n    {\n      std::string type;\n      if (nargin == 3)\n        type = args(2).string_value ();\n      else\n        type = args(1).string_value ();\n\n      if (type == \"native\")\n        {\n          switch (info.format & SF_FORMAT_SUBMASK)\n            {\n            case SF_FORMAT_PCM_S8:\n              ret_audio = int8NDArray (audio * 128);\n              break;\n            case SF_FORMAT_PCM_U8:\n              ret_audio = uint8NDArray (audio * 128 + 128);\n              break;\n            case SF_FORMAT_PCM_16:\n              ret_audio = int16NDArray (audio * 32768);\n              break;\n            case SF_FORMAT_PCM_24:\n              ret_audio = int32NDArray (audio * 8388608);\n              break;\n            case SF_FORMAT_PCM_32:\n              ret_audio = int32NDArray (audio * 2147483648);\n              break;\n            case SF_FORMAT_FLOAT:\n              ret_audio = FloatNDArray (audio);\n              break;\n            default:\n              ret_audio = audio;\n              break;\n            }\n        }\n      else\n        ret_audio = audio;\n    }\n  else\n    ret_audio = audio;\n\n  return ovl (ret_audio, info.samplerate);\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"audioread\",\n                        \"reading and writing sound files through libsndfile\");\n\n#endif\n}\n\n#if defined (HAVE_SNDFILE)\n\nstatic int\nextension_to_format (const std::string& ext)\n{\n  static bool initialized = false;\n\n  static std::map<std::string, int> table;\n\n  if (! initialized)\n    {\n      table[\"wav\"] = SF_FORMAT_WAV;\n      table[\"aiff\"] = SF_FORMAT_AIFF;\n      table[\"au\"] = SF_FORMAT_AU;\n      table[\"raw\"] = SF_FORMAT_RAW;\n      table[\"paf\"] = SF_FORMAT_PAF;\n      table[\"svx\"] = SF_FORMAT_SVX;\n      table[\"nist\"] = SF_FORMAT_NIST;\n      table[\"voc\"] = SF_FORMAT_VOC;\n      table[\"ircam\"] = SF_FORMAT_IRCAM;\n      table[\"w64\"] = SF_FORMAT_W64;\n      table[\"mat4\"] = SF_FORMAT_MAT4;\n      table[\"mat5\"] = SF_FORMAT_MAT5;\n      table[\"pvf\"] = SF_FORMAT_PVF;\n      table[\"xi\"] = SF_FORMAT_XI;\n      table[\"htk\"] = SF_FORMAT_HTK;\n      table[\"sds\"] = SF_FORMAT_SDS;\n      table[\"avr\"] = SF_FORMAT_AVR;\n      table[\"wavex\"] = SF_FORMAT_WAVEX;\n      table[\"sd2\"] = SF_FORMAT_SD2;\n      table[\"flac\"] = SF_FORMAT_FLAC;\n      table[\"caf\"] = SF_FORMAT_CAF;\n      table[\"wve\"] = SF_FORMAT_WVE;\n      table[\"ogg\"] = SF_FORMAT_OGG;\n      table[\"mpc2k\"] = SF_FORMAT_MPC2K;\n      table[\"rf64\"] = SF_FORMAT_RF64;\n#if defined (HAVE_LIB_SNDFILE_FORMAT_MP3)\n      table[\"m1a\"] = SF_FORMAT_MPEG;\n#endif\n\n      initialized = true;\n    }\n\n  std::map<std::string, int>::const_iterator it = table.find (ext);\n\n  return (it != table.end ()) ? it->second : 0;\n}\n\n#endif\n\nDEFUN_DLD (audiowrite, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} audiowrite (@var{filename}, @var{y}, @var{fs})\n@deftypefnx {} {} audiowrite (@var{filename}, @var{y}, @var{fs}, @var{name}, @var{value}, @dots{})\n\nWrite audio data from the matrix @var{y} to @var{filename} at sampling rate\n@var{fs} with the file format determined by the file extension.\n\nAdditional name/value argument pairs may be used to specify the\nfollowing options:\n\n@table @samp\n@item BitsPerSample\nNumber of bits per sample.  Valid values are 8, 16, 24, and 32.  Default is\n16.\n\n@item BitRate\nValid argument name, but ignored.  Left for compatibility with @sc{matlab}.\n\n@item Quality\nQuality setting for the Ogg Vorbis compressor.  Values can range between 0\nand 100 with 100 being the highest quality setting.  Default is 75.\n\n@item Title\nTitle for the audio file.\n\n@item Artist\nArtist name.\n\n@item Comment\nComment.\n@end table\n@seealso{audioread, audioformats, audioinfo}\n@end deftypefn */)\n{\n#if defined (HAVE_SNDFILE)\n\n  int nargin = args.length ();\n\n  if (nargin < 3)\n    print_usage ();\n\n  std::string filename = args(0).xstring_value (\"audiowrite: FILENAME must be a string\");\n\n  double bias = 0.0;\n  double scale = 1.0;\n\n  if (args(1).is_uint8_type ())\n    bias = scale = 127.5;\n  else if (args(1).is_int16_type ())\n    scale = 32768;       // 2^15\n  else if (args(1).is_int32_type ())\n    scale = 2147483648;  // 2^31\n  else if (args(1).isinteger ())\n    err_wrong_type_arg (\"audiowrite\", args(1));\n\n  Matrix audio = args(1).matrix_value ();\n\n  if (! args(2).is_scalar_type () || ! args(2).isnumeric ())\n    error (\"audiowrite: sample rate FS must be a positive scalar integer\");\n  int samplerate = args(2).int_value ();\n  if (samplerate < 1)\n    error (\"audiowrite: sample rate FS must be a positive scalar integer\");\n\n  std::string ext;\n  std::size_t dotpos = filename.find_last_of ('.');\n  if (dotpos != std::string::npos)\n    ext = filename.substr (dotpos + 1);\n  std::transform (ext.begin (), ext.end (), ext.begin (), ::tolower);\n\n  sf_count_t items_to_write = audio.rows () * audio.columns ();\n\n  if (audio.rows () == 1)\n    audio = audio.transpose ();\n\n  OCTAVE_LOCAL_BUFFER (double, data, items_to_write);\n\n  sf_count_t idx = 0;\n  for (int i = 0; i < audio.rows (); i++)\n    {\n      for (int j = 0; j < audio.columns (); j++)\n        {\n          double elem = (audio.xelem (i, j) - bias) / scale;\n          data[idx++] = std::min (std::max (elem, -1.0), 1.0);\n        }\n    }\n\n  SF_INFO info;\n\n  memset (&info, 0, sizeof (info));\n\n  sf_count_t chunk_size = 0;\n\n  if (ext == \"ogg\")\n    {\n      info.format = SF_FORMAT_VORBIS;\n\n      // FIXME: There seems to be a bug writing ogg files in one shot that\n      // causes a segfault: https://bugs.debian.org/760898.\n      // Breaking it up into a series of smaller chunks appears to avoid the\n      // problem and produces valid files.\n      chunk_size = 0x100000;\n    }\n#if defined (HAVE_LIB_SNDFILE_FORMAT_MP3)\n  else if (ext == \"mp1\")\n    info.format = SF_FORMAT_MPEG|SF_FORMAT_MPEG_LAYER_I;\n  else if (ext == \"mp2\")\n    info.format = SF_FORMAT_MPEG|SF_FORMAT_MPEG_LAYER_II;\n  else if (ext == \"mp3\")\n    info.format = SF_FORMAT_MPEG|SF_FORMAT_MPEG_LAYER_III;\n#endif\n  else\n    info.format = SF_FORMAT_PCM_16;\n\n  info.channels = audio.columns ();\n  info.samplerate = samplerate;\n  info.format |= extension_to_format (ext);\n\n  std::string title = \"\";\n  std::string artist = \"\";\n  std::string comment = \"\";\n  double quality = 0.75;\n\n  for (int i = 3; i < nargin; i += 2)\n    {\n      if (i >= nargin - 1)\n        error (\"audiowrite: invalid number of arguments\");\n\n      std::string keyword_orig = args(i).string_value ();\n      std::string keyword = args(i).xtolower ().string_value ();\n      octave_value value_arg = args(i+1);\n\n      if (keyword == \"bitspersample\")\n        {\n          info.format &= ~SF_FORMAT_SUBMASK;\n          int bits = value_arg.int_value ();\n          if (bits == 8)\n            {\n              if ((info.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)\n                info.format |= SF_FORMAT_PCM_U8;\n              else\n                info.format |= SF_FORMAT_PCM_S8;\n            }\n          else if (bits == 16)\n            info.format |= SF_FORMAT_PCM_16;\n          else if (bits == 24)\n            {\n              if ((info.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)\n                info.format |= SF_FORMAT_PCM_32;\n              else\n                info.format |= SF_FORMAT_PCM_24;\n            }\n          else if (bits == 32)\n            {\n              if ((info.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV\n                  && args(1).isfloat ())\n                info.format |= SF_FORMAT_FLOAT;\n              else\n                info.format |= SF_FORMAT_PCM_32;\n            }\n          else if (bits == 64)\n            info.format |= SF_FORMAT_DOUBLE;\n          else\n            error (\"audiowrite: wrong number of bits specified\");\n        }\n      else if (keyword == \"bitrate\")\n        warning_with_id (\"Octave:audiowrite:unused-parameter\",\n                         \"audiowrite: 'BitRate' accepted for Matlab \"\n                         \"compatibility, but is ignored\");\n      else if (keyword == \"quality\")\n        {\n          if (! value_arg.is_scalar_type ())\n            error (\"audiowrite: Quality value must be a scalar\");\n\n          double value =\n            value_arg.xdouble_value (\"audiowrite: Quality value must be a numeric scalar between 0 and 100\");\n\n          if (math::isnan (value) || value < 0 || value > 100)\n            error (\"audiowrite: Quality value must be a number between 0 and 100\");\n\n          quality = value / 100;\n        }\n      else if (keyword == \"title\")\n        title = value_arg.string_value ();\n      else if (keyword == \"artist\")\n        artist = value_arg.string_value ();\n      else if (keyword == \"comment\")\n        comment = value_arg.string_value ();\n      else\n        error (\"audiowrite: unrecognized option: '%s'\", keyword_orig.c_str ());\n    }\n\n  SNDFILE *file = sf_open (filename.c_str (), SFM_WRITE, &info);\n\n  if (! file)\n    error (\"audiowrite: failed to open output file '%s': %s\",\n           filename.c_str (), sf_strerror (file));\n\n  unwind_action close_open_file ([file] () { sf_close (file); });\n\n  sf_command (file, SFC_SET_NORM_DOUBLE, nullptr, SF_TRUE);\n  sf_command (file, SFC_SET_CLIPPING, nullptr, SF_TRUE) ;\n  sf_command (file, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof (quality));\n\n  if (title != \"\")\n    sf_set_string (file, SF_STR_TITLE, title.c_str ());\n\n  if (artist != \"\")\n    sf_set_string (file, SF_STR_ARTIST, artist.c_str ());\n\n  if (comment != \"\")\n    sf_set_string (file, SF_STR_COMMENT, comment.c_str ());\n\n  sf_count_t total_items_written = 0;\n  sf_count_t offset = 0;\n\n  if (chunk_size == 0)\n    chunk_size = items_to_write;\n\n  while (total_items_written < items_to_write)\n    {\n      if (items_to_write - offset < chunk_size)\n        chunk_size = items_to_write - offset;\n\n      sf_count_t items_written = sf_write_double (file, data+offset, chunk_size);\n\n      if (items_written != chunk_size)\n        error (\"audiowrite: write failed, wrote %\" PRId64 \" of %\" PRId64\n               \" items\\n\", items_written, chunk_size);\n\n      total_items_written += items_written;\n      offset += chunk_size;\n    }\n\n  // FIXME: Shouldn't we return something to indicate whether the file\n  //        was written successfully?  On the other hand, Matlab doesn't\n  //        return anything.\n  return ovl ();\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"audiowrite\",\n                        \"reading and writing sound files through libsndfile\");\n\n#endif\n}\n\n/*\n## Joint audiowrite/audioread tests\n## 8-bit Unsigned PCM\n%!testif HAVE_SNDFILE <*56889>\n%! fname = [tempname() \".wav\"];\n%! unwind_protect\n%!   y1 = uint8 ([0, 1, 2, 253, 254, 255]);\n%!   audiowrite (fname, y1, 8000, \"BitsPerSample\", 8);\n%!   y2 = audioread (fname, \"native\");\n%! unwind_protect_cleanup\n%!   unlink (fname);\n%! end_unwind_protect\n%! assert (y1(:), y2);\n\n## 8-bit Signed PCM\n%!testif HAVE_SNDFILE <*56889>\n%! fname = [tempname() \".au\"];\n%! unwind_protect\n%!   y1 = uint8 ([0, 1, 2, 253, 254, 255]);\n%!   audiowrite (fname, y1, 8000, \"BitsPerSample\", 8);\n%!   y2 = audioread (fname, \"native\");\n%! unwind_protect_cleanup\n%!   unlink (fname);\n%! end_unwind_protect\n%! assert (y2, int8 ([-128; -127; -126; 125; 126; 127]));\n\n## 16-bit Signed PCM\n%!testif HAVE_SNDFILE <*56889>\n%! fname = [tempname() \".wav\"];\n%! unwind_protect\n%!   y1 = int16 ([-32768, -32767, -32766, 32765, 32766, 32767]);\n%!   audiowrite (fname, y1, 8000, \"BitsPerSample\", 16);\n%!   y2 = audioread (fname, \"native\");\n%! unwind_protect_cleanup\n%!   unlink (fname);\n%! end_unwind_protect\n%! assert (y1(:), y2);\n\n## 24-bit Signed PCM\n%!testif HAVE_SNDFILE <*56889>\n%! fname = [tempname() \".au\"];\n%! unwind_protect\n%!   y1 = [-8388608, -8388607, -8388606, 8388605, 8388606, 8388607] / 8388608;\n%!   audiowrite (fname, y1, 8000, \"BitsPerSample\", 24);\n%!   y2 = audioread (fname, \"native\");\n%! unwind_protect_cleanup\n%!   unlink (fname);\n%! end_unwind_protect\n%! assert (int32 ([-8388608; -8388607; -8388606; 8388605; 8388606; 8388607]),\n%!         y2);\n\n## 32-bit Signed PCM\n%!testif HAVE_SNDFILE <*56889>\n%! fname = [tempname() \".wav\"];\n%! unwind_protect\n%!   y1 = int32 ([-2147483648, -2147483647, -2147483646, 2147483645, 2147483646, 2147483647 ]);\n%!   audiowrite (fname, y1, 8000, \"BitsPerSample\", 32);\n%!   y2 = audioread (fname, \"native\");\n%! unwind_protect_cleanup\n%!   unlink (fname);\n%! end_unwind_protect\n%! assert (y1(:), y2);\n\n## Test input validation\n%!testif HAVE_SNDFILE\n%! fail (\"audiowrite (1, 1, 8e3)\", \"FILENAME must be a string\");\n%! fail (\"audiowrite ('foo', int64 (1), 8e3)\",\n%!       \"wrong type argument 'int64 scalar'\");\n%! fail (\"audiowrite ('foo', [0 1], [8e3, 8e3])\",\n%!       \"FS must be a positive scalar\");\n%! fail (\"audiowrite ('foo', 1, {8e3})\", \"FS must be a .* integer\");\n%! fail (\"audiowrite ('foo', 1, -8e3)\", \"FS must be a positive\");\n%! fail (\"audiowrite ('foo', 1, 8e3, 'bitspersample')\",\n%!       \"invalid number of arguments\");\n%! fail (\"audiowrite ('foo', 1, 8e3, 'bitspersample', 48)\",\n%!       \"wrong number of bits specified\");\n%! fail (\"audiowrite ('foo', 1, 8e3, 'quality', [2 3 4])\",\n%!       \"Quality value must be a scalar\");\n%! fail (\"audiowrite ('foo', 1, 8e3, 'quality', NaN)\",\n%!       \"Quality value must be .* between 0 and 100\");\n%! fail (\"audiowrite ('foo', 1, 8e3, 'quality', -1)\",\n%!       \"Quality value must be .* between 0 and 100\");\n%! fail (\"audiowrite ('foo', 1, 8e3, 'quality', 101)\",\n%!       \"Quality value must be .* between 0 and 100\");\n%! fail (\"audiowrite ('foo', 1, 8e3, 'foo', 'bar')\",\n%!       \"unrecognized option: 'foo'\");\n*/\n\nDEFUN_DLD (audioinfo, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{info} =} audioinfo (@var{filename})\nReturn information about an audio file specified by @var{filename}.\n\nThe output @var{info} is a structure containing the following fields:\n\n@table @samp\n@item Filename\nName of the audio file.\n\n@item CompressionMethod\nAudio compression method.  Unused, only present for compatibility with\n@sc{matlab}.\n\n@item NumChannels\nNumber of audio channels.\n\n@item SampleRate\nSample rate of the audio, in Hertz.\n\n@item TotalSamples\nNumber of samples in the file.\n\n@item Duration\nDuration of the audio, in seconds.\n\n@item BitsPerSample\nNumber of bits per sample.\n\n@item BitRate\nAudio bit rate.  Unused, only present for compatibility with @sc{matlab}.\n\n@item Title\n@qcode{\"Title\"} audio metadata value as a string, or empty if not present.\n\n@item Artist\n@qcode{\"Artist\"} audio metadata value as a string, or empty if not present.\n\n@item Comment\n@qcode{\"Comment\"} audio metadata value as a string, or empty if not present.\n@end table\n@seealso{audioread, audiowrite}\n@end deftypefn */)\n{\n#if defined (HAVE_SNDFILE)\n\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string filename = args(0).xstring_value (\"audioinfo: FILENAME must be a string\");\n\n  sys::file_stat fs (filename);\n  if (! fs.exists ())\n    error (\"audioinfo: FILENAME '%s' not found\", filename.c_str ());\n\n  SF_INFO info;\n  info.format = 0;\n  SNDFILE *file = sf_open (filename.c_str (), SFM_READ, &info);\n\n  if (! file)\n    error (\"audioinfo: failed to open input file '%s': %s\",\n           filename.c_str (), sf_strerror (file));\n\n  unwind_action close_open_file ([file] () { sf_close (file); });\n\n  octave_scalar_map result;\n\n  std::string full_name = sys::canonicalize_file_name (filename);\n\n  result.assign (\"Filename\", full_name);\n  result.assign (\"CompressionMethod\", \"\");\n  result.assign (\"NumChannels\", info.channels);\n  result.assign (\"SampleRate\", info.samplerate);\n  double dframes;\n  if (info.frames != SF_COUNT_MAX)\n    dframes = info.frames;\n  else\n    dframes = -1;\n  result.assign (\"TotalSamples\", dframes);\n\n  if (dframes != -1)\n    {\n      double drate = info.samplerate;\n      result.assign (\"Duration\", dframes / drate);\n    }\n  else\n    result.assign (\"Duration\", -1);\n\n  int bits;\n  switch (info.format & SF_FORMAT_SUBMASK)\n    {\n    case SF_FORMAT_PCM_S8:\n      bits = 8;\n      break;\n    case SF_FORMAT_PCM_U8:\n      bits = 8;\n      break;\n    case SF_FORMAT_PCM_16:\n      bits = 16;\n      break;\n    case SF_FORMAT_PCM_24:\n      bits = 24;\n      break;\n    case SF_FORMAT_PCM_32:\n      bits = 32;\n      break;\n    case SF_FORMAT_FLOAT:\n      bits = 32;\n      break;\n    case SF_FORMAT_DOUBLE:\n      bits = 64;\n      break;\n    default:\n      bits = -1;\n      break;\n    }\n\n  result.assign (\"BitsPerSample\", bits);\n  result.assign (\"BitRate\", -1);\n  result.assign (\"Title\", sf_get_string (file, SF_STR_TITLE));\n  result.assign (\"Artist\", sf_get_string (file, SF_STR_ARTIST));\n  result.assign (\"Comment\", sf_get_string (file, SF_STR_COMMENT));\n\n  return ovl (result);\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"audioinfo\",\n                        \"reading and writing sound files through libsndfile\");\n\n#endif\n}\n\n#if defined (HAVE_SNDFILE)\n\nstatic void\naudio_sub_formats (int format)\n{\n  int count;\n  sf_command (nullptr, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int));\n\n  for (int i = 0; i < count; i++)\n    {\n      SF_FORMAT_INFO info;\n      info.format = i;\n      sf_command (nullptr, SFC_GET_FORMAT_SUBTYPE, &info, sizeof (info));\n\n      SF_INFO sfinfo;\n      memset (&sfinfo, 0, sizeof (sfinfo));\n      sfinfo.channels = 1;\n      sfinfo.format = (format & SF_FORMAT_TYPEMASK) | info.format;\n\n      if (sf_format_check (&sfinfo))\n        octave_stdout << \"  \" << info.name << std::endl;\n    }\n}\n\n#endif\n\nDEFUN_DLD (audioformats, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} audioformats ()\n@deftypefnx {} {} audioformats (@var{format})\nDisplay information about all supported audio formats.\n\nIf the optional argument @var{format} is given, then display only formats\nwith names that start with @var{format}.\n@seealso{audioread, audiowrite}\n@end deftypefn */)\n{\n#if defined (HAVE_SNDFILE)\n\n  if (args.length () > 1)\n    print_usage ();\n\n  std::string search = \"\";\n  if (args.length () > 0)\n    {\n      search = args(0).string_value ();\n      std::transform (search.begin (), search.end (), search.begin (), tolower);\n    }\n\n  int count;\n  sf_command (nullptr, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof (int));\n\n  for (int i = 0; i < count; i++)\n    {\n      SF_FORMAT_INFO info;\n      info.format = i;\n      sf_command (nullptr, SFC_GET_FORMAT_MAJOR, &info, sizeof (info));\n      bool match = true;\n\n      if (! search.empty ())\n        {\n          std::string nm = info.name;\n          std::transform (nm.begin (), nm.end (), nm.begin (), tolower);\n          match = nm.compare (0, search.length (), search) == 0;\n        }\n\n      if (match)\n        {\n          octave_stdout << \"name: \" << info.name << std::endl;\n          octave_stdout << \"extension: \" << info.extension << std::endl;\n          octave_stdout << \"id: \" << info.format << std::endl;\n          octave_stdout << \"subformats:\" << std::endl;\n\n          audio_sub_formats (info.format);\n        }\n    }\n\n  return octave_value_list ();\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"audioformats\",\n                        \"getting sound formats through libsndfile\");\n\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/config-module.awk",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nBEGIN {\n  FS = \"|\";\n  nfiles = 0;\n\n  print \"## DO NOT EDIT -- generated from module-files by config-module.awk\";\n  print \"\"\n  print \"EXTRA_DIST += \\\\\"\n  print \"  %reldir%/config-module.sh \\\\\"\n  print \"  %reldir%/config-module.awk \\\\\"\n  print \"  %reldir%/module-files \\\\\"\n  print \"  %reldir%/oct-qhull.h\"\n  print \"\"\n}\n/^#.*/ { next; }\n{\n  nfiles++;\n  files[nfiles] = $1;\n  cppflags[nfiles] = $2;\n  ldflags[nfiles] = $3;\n  libraries[nfiles] = $4;\n} END {\n  sep = \" \\\\\\n\";\n  print \"DLDFCN_SRC = \\\\\";\n  for (i = 1; i <= nfiles; i++) {\n    if (i == nfiles)\n      sep = \"\\n\";\n    printf (\"  %%reldir%%/%s%s\", files[i], sep);\n  }\n  print \"\";\n\n  sep = \" \\\\\\n\";\n  print \"DLDFCN_LIBS = $(DLDFCN_SRC:.cc=.la)\";\n  print \"\";\n  print \"octlib_LTLIBRARIES += $(DLDFCN_LIBS)\";\n  print \"\";\n  print \"## Use stamp files to avoid problems with checking timestamps\";\n  print \"## of symbolic links\";\n  print \"\";\n  print \"%.oct : %.la\"\n  print \"\\t$(AM_V_GEN)$(INSTALL_PROGRAM) %reldir%/.libs/$(shell $(SED) -n -e \\\"s/dlname='\\\\([^']*\\\\)'/\\\\1/p\\\" < $<) $@\"\n\n  for (i = 1; i <= nfiles; i++) {\n    basename = files[i];\n    sub (/\\.cc$/, \"\", basename);\n    print \"\";\n    printf (\"%%canon_reldir%%_%s_la_SOURCES = %%reldir%%/%s\\n\",\n            basename, files[i]);\n    if (cppflags[i])\n      {\n        printf (\"%%canon_reldir%%_%s_la_CPPFLAGS = $(libinterp_liboctinterp_la_CPPFLAGS) %s\\n\",\n                basename, cppflags[i]);\n      }\n    printf (\"%%canon_reldir%%_%s_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -module $(NO_UNDEFINED_LDFLAG) %s $(OCT_LINK_OPTS) $(OCT_LINK_DEPS) $(WARN_LDFLAGS)\\n\",\n            basename, ldflags[i]);\n    printf (\"%%canon_reldir%%_%s_la_LIBADD = $(DLD_LIBOCTINTERP_LIBADD) %s\\n\",\n            basename, libraries[i]);\n    printf (\"%%canon_reldir%%_%s_la_DEPENDENCIES = $(OCT_LTLINK_DEPS)\\n\",\n            basename);\n  }\n\n  print \"\";\n  print \"$(srcdir)/%reldir%/module.mk: $(srcdir)/%reldir%/config-module.sh $(srcdir)/%reldir%/config-module.awk $(srcdir)/%reldir%/module-files\";\n  print \"\\t$(AM_V_GEN)$(SHELL) $(srcdir)/%reldir%/config-module.sh $(srcdir)\";\n\n  print \"\";\n  print \"DLDFCN_OCT_FILES = $(DLDFCN_LIBS:.la=.oct)\";\n  print \"\";\n  print \"DLDFCN_DEFUN_FILES = $(DLDFCN_SRC)\";\n  print \"\";\n  print \"DLDFCN_PKG_ADD_FILE = %reldir%/PKG_ADD\";\n  print \"\";\n  print \"%reldir%/PKG_ADD: $(DLDFCN_DEFUN_FILES) $(srcdir)/build-aux/mk-pkg-add.sh | %reldir%/$(octave_dirstamp)\";\n  print \"\t$(AM_V_GEN)rm -f $@-t && \\\\\"\n  print \"\t$(SHELL) $(srcdir)/build-aux/mk-pkg-add.sh \\\"$(srcdir)\\\" $(DLDFCN_DEFUN_FILES) > $@-t && \\\\\";\n  print \"\tmv $@-t $@\";\n  print \"\";\n  print \"LIBINTERP_DEFUN_FILES += \\\\\";\n  print \"  $(DLDFCN_DEFUN_FILES)\";\n  print \"\";\n  print \"OCT_FILE_PKG_ADD_FILES += \\\\\";\n  print \"  $(DLDFCN_PKG_ADD_FILE)\";\n  print \"\";\n  print \"OCTAVE_INTERPRETER_TARGETS += \\\\\";\n  print \"  $(DLDFCN_OCT_FILES)\";\n  print \"\";\n  print \"OCT_FILE_LIBS += \\\\\";\n  print \" $(DLDFCN_LIBS)\";\n  print \"\";\n  print \"OCT_FILES += \\\\\";\n  print \" $(DLDFCN_OCT_FILES)\";\n  print \"\";\n  print \"DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\";\n\n  print \"\";\n  print \"libinterp_CLEANFILES += \\\\\";\n  print \"  $(DLDFCN_PKG_ADD_FILE) \\\\\";\n  print \"  $(DLDFCN_OCT_FILES)\";\n  print \"\";\n  print \"libinterp_MAINTAINERCLEANFILES += \\\\\";\n  print \"  $(srcdir)/%reldir%/module.mk\";\n}\n"
  },
  {
    "path": "libinterp/dldfcn/config-module.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nset -e\n\nAWK=${AWK:-awk}\nSHELL=${SHELL:-/bin/sh}\n\nif [ $# -eq 1 ]; then\n  top_srcdir=\"$1\"\nelse\n  top_srcdir=\"../..\"\nfi\n\nmove_if_change=\"$top_srcdir/build-aux/move-if-change\"\n\ndld_dir=$top_srcdir/libinterp/dldfcn\n\n$AWK -f $dld_dir/config-module.awk < $dld_dir/module-files > $dld_dir/module.mk-t\n\n$SHELL $move_if_change $dld_dir/module.mk-t $dld_dir/module.mk\n"
  },
  {
    "path": "libinterp/dldfcn/convhulln.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n29. July 2000 - Kai Habel: first release\n2002-04-22 Paul Kienzle\n* Use warning(...) function rather than writing to cerr\n2006-05-01 Tom Holroyd\n* add support for consistent winding in all dimensions; output is\n* guaranteed to be simplicial.\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <limits>\n#include <string>\n\n#include \"Array.h\"\n#include \"dMatrix.h\"\n#include \"oct-locbuf.h\"\n#include \"unwind-prot.h\"\n\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n\n#if defined (HAVE_QHULL)\n\n#  include \"oct-qhull.h\"\n\n#  if defined (NEED_QHULL_R_VERSION)\nchar qh_version[] = \"convhulln.oct 2007-07-24\";\n#  endif\n\nstatic void\nfree_qhull_memory (qhT *qh)\n{\n  qh_freeqhull (qh, ! qh_ALL);\n\n  int curlong, totlong;\n  qh_memfreeshort (qh, &curlong, &totlong);\n\n  if (curlong || totlong)\n    warning (\"convhulln: did not free %d bytes of long memory (%d pieces)\",\n             totlong, curlong);\n}\n\nstatic bool\noctave_qhull_dims_ok (octave_idx_type dim, octave_idx_type n, const char *who)\n{\n  if (sizeof (octave_idx_type) > sizeof (int))\n    {\n      int maxval = std::numeric_limits<int>::max ();\n\n      if (dim > maxval || n > maxval)\n        error (\"%s: dimension too large for Qhull\", who);\n    }\n\n  return true;\n}\n\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN_DLD (convhulln, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{h} =} convhulln (@var{pts})\n@deftypefnx {} {@var{h} =} convhulln (@var{pts}, @var{options})\n@deftypefnx {} {[@var{h}, @var{v}] =} convhulln (@dots{})\nCompute the convex hull of the set of points @var{pts}.\n\n@var{pts} is a matrix of size [n, dim] containing n points in a space of\ndimension dim.\n\nThe hull @var{h} is an index vector into the set of points and specifies\nwhich points form the enclosing hull.\n\nAn optional second argument, which must be a string or cell array of\nstrings, contains options passed to the underlying qhull command.  See the\ndocumentation for the Qhull library for details\n@url{http://www.qhull.org/html/qh-quick.htm#options}.\nThe default options depend on the dimension of the input:\n\n@itemize\n@item 2-D, 3-D, 4-D: @var{options} = @code{@{\"Qt\"@}}\n\n@item 5-D and higher: @var{options} = @code{@{\"Qt\", \"Qx\"@}}\n@end itemize\n\nIf @var{options} is not present or @code{[]} then the default arguments are\nused.  Otherwise, @var{options} replaces the default argument list.\nTo append user options to the defaults it is necessary to repeat the\ndefault arguments in @var{options}.  Use a null string to pass no arguments.\n\nIf the second output @var{v} is requested the volume of the enclosing\nconvex hull is calculated.\n@seealso{convhull, delaunayn, voronoin}\n@end deftypefn */)\n{\n#if defined (HAVE_QHULL)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value_list retval;\n\n  Matrix points (args(0).matrix_value ());\n  const octave_idx_type dim = points.columns ();\n  const octave_idx_type num_points = points.rows ();\n\n  if (! octave_qhull_dims_ok (dim, num_points, \"convhulln\"))\n    return retval;\n\n  points = points.transpose ();\n\n  std::string options;\n\n  if (dim <= 4)\n    options = \" Qt\";\n  else\n    options = \" Qt Qx\";\n\n  if (nargin == 2)\n    {\n      if (args(1).is_string ())\n        options = ' ' + args(1).string_value ();\n      else if (args(1).isempty ())\n        ; // Use default options.\n      else if (args(1).iscellstr ())\n        {\n          options = \"\";\n\n          Array<std::string> tmp = args(1).cellstr_value ();\n\n          for (octave_idx_type i = 0; i < tmp.numel (); i++)\n            options += ' ' + tmp(i);\n        }\n      else\n        error (\"convhulln: OPTIONS must be a string, cell array of strings, or empty\");\n    }\n\n  boolT ismalloc = false;\n\n  // Set the outfile pointer to stdout for status information.\n  FILE *outfile = nullptr;\n  FILE *errfile = stderr;\n\n  qhT context = { };\n  qhT *qh = &context;\n\n  std::string cmd = \"qhull\" + options;\n\n  int exitcode = qh_new_qhull (qh, dim, num_points, points.rwdata (),\n                               ismalloc, &cmd[0], outfile, errfile);\n\n  unwind_action free_memory ([qh] () { free_qhull_memory (qh); });\n\n  if (exitcode)\n    error (\"convhulln: qhull failed\");\n\n  bool nonsimp_seen = false;\n\n  octave_idx_type nf = qh->num_facets;\n\n  Matrix idx (nf, dim + 1);\n\n  facetT *facet;\n\n  octave_idx_type i = 0;\n\n  FORALLfacets\n  {\n    octave_idx_type j = 0;\n\n    if (! (nonsimp_seen || facet->simplicial || qh->hull_dim == 2))\n      {\n        nonsimp_seen = true;\n\n        if (cmd.find (\"QJ\") != std::string::npos)\n          // Should never happen with QJ.\n          error (\"convhulln: qhull failed: option 'QJ' returned non-simplicial facet\");\n      }\n\n    if (dim == 3)\n      {\n        setT *vertices = qh_facet3vertex (qh, facet);\n\n        vertexT *vertex, **vertexp;\n\n        FOREACHvertex_ (vertices)\n        idx(i, j++) = 1 + qh_pointid(qh, vertex->point);\n\n        qh_settempfree (qh, &vertices);\n      }\n    else\n      {\n        if (facet->toporient ^ qh_ORIENTclock)\n          {\n            vertexT *vertex, **vertexp;\n\n            FOREACHvertex_ (facet->vertices)\n            idx(i, j++) = 1 + qh_pointid(qh, vertex->point);\n          }\n        else\n          {\n            vertexT *vertex, **vertexp;\n\n            FOREACHvertexreverse12_ (facet->vertices)\n            idx(i, j++) = 1 + qh_pointid(qh, vertex->point);\n          }\n      }\n    if (j < dim)\n      warning (\"convhulln: facet %\" OCTAVE_IDX_TYPE_FORMAT\n               \" only has %\" OCTAVE_IDX_TYPE_FORMAT\n               \" vertices\", i, j);\n\n    i++;\n  }\n\n  // Remove extra dimension if all facets were simplicial.\n\n  if (! nonsimp_seen)\n    idx.resize (nf, dim, 0.0);\n\n  if (nargout == 2)\n    {\n      // Calculate volume of convex hull, taken from qhull src/geom2.c.\n\n      realT area;\n      realT dist;\n\n      FORALLfacets\n      {\n        if (! facet->normal)\n          continue;\n\n        if (facet->upperdelaunay && qh->ATinfinity)\n          continue;\n\n        facet->f.area = area = qh_facetarea (qh, facet);\n        facet->isarea = True;\n\n        if (qh->DELAUNAY)\n          {\n            if (facet->upperdelaunay == qh->UPPERdelaunay)\n              qh->totarea += area;\n          }\n        else\n          {\n            qh->totarea += area;\n            qh_distplane (qh, qh->interior_point, facet, &dist);\n            qh->totvol += -dist * area / qh->hull_dim;\n          }\n      }\n\n      retval(1) = octave_value (qh->totvol);\n    }\n\n  retval(0) = idx;\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"convhulln\", \"Qhull\");\n\n#endif\n}\n\n/*\n%!testif HAVE_QHULL\n%! cube = [0 0 0;1 0 0;1 1 0;0 1 0;0 0 1;1 0 1;1 1 1;0 1 1];\n%! [h, v] = convhulln (cube, \"Qt\");\n%! assert (size (h), [12 3]);\n%! h = sortrows (sort (h, 2), [1:3]);\n%! assert (h,\n%!         [1 2 4; 1 2 6; 1 4 8; 1 5 6; 1 5 8; 2 3 4; 2 3 7; 2 6 7; 3 4 7; 4 7 8; 5 6 7; 5 7 8]);\n%! assert (v, 1, 10*eps);\n%! [h2, v2] = convhulln (cube);  # Test default option = \"Qt\"\n%! assert (size (h2), size (h));\n%! h2 = sortrows (sort (h2, 2), [1:3]);\n%! assert (h2, h);\n%! assert (v2, v, 10*eps);\n\n%!testif HAVE_QHULL\n%! cube = [0 0 0;1 0 0;1 1 0;0 1 0;0 0 1;1 0 1;1 1 1;0 1 1];\n%! [h, v] = convhulln (cube, \"QJ\");\n%! assert (size (h), [12 3]);\n%! assert (sortrows (sort (h, 2), [1:3]),\n%!         [1 2 4; 1 2 5; 1 4 5; 2 3 4; 2 3 6; 2 5 6; 3 4 8; 3 6 7; 3 7 8; 4 5 8; 5 6 8; 6 7 8]);\n%! assert (v, 1.0, 1e6*eps);\n\n%!testif HAVE_QHULL\n%! tetrahedron = [1 1 1;-1 -1 1;-1 1 -1;1 -1 -1];\n%! [h, v] = convhulln (tetrahedron);\n%! h = sortrows (sort (h, 2), [1 2 3]);\n%! assert (h, [1 2 3;1 2 4; 1 3 4; 2 3 4]);\n%! assert (v, 8/3, 10*eps);\n\n%!testif HAVE_QHULL\n%! triangle = [0 0; 1 1; 1 0; 1 2];\n%! h = convhulln (triangle);\n%! assert (size (h), [3 2]);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/fftw.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <string>\n\n#if defined (HAVE_FFTW3_H)\n#  include <fftw3.h>\n#endif\n\n#include \"oct-fftw.h\"\n\n#include \"defun-dld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN_DLD (fftw, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{method} =} fftw (\"planner\")\n@deftypefnx {} {} fftw (\"planner\", @var{method})\n@deftypefnx {} {@var{wisdom} =} fftw (\"dwisdom\")\n@deftypefnx {} {} fftw (\"dwisdom\", @var{wisdom})\n@deftypefnx {} {@var{nthreads} =} fftw (\"threads\")\n@deftypefnx {} {} fftw (\"threads\", @var{nthreads})\n\nManage @sc{fftw} wisdom data.\n\nWisdom data can be used to significantly accelerate the calculation of the\nFFTs, but implies an initial cost in its calculation.  When the @sc{fftw}\nlibraries are initialized, they read a system wide wisdom file (typically in\n@file{/etc/fftw/wisdom}), allowing wisdom to be shared between applications\nother than Octave.  Alternatively, the @code{fftw} function can be used to\nimport wisdom.  For example,\n\n@example\n@var{wisdom} = fftw (\"dwisdom\")\n@end example\n\n@noindent\nwill save the existing wisdom used by Octave to the string @var{wisdom}.\nThis string can then be saved to a file and restored using the @code{save}\nand @code{load} commands respectively.  This existing wisdom can be\nre-imported as follows\n\n@example\nfftw (\"dwisdom\", @var{wisdom})\n@end example\n\nIf @var{wisdom} is an empty string, then the wisdom used is cleared.\n\nDuring the calculation of Fourier transforms further wisdom is generated.\nThe fashion in which this wisdom is generated is also controlled by\nthe @code{fftw} function.  There are five different manners in which the\nwisdom can be treated:\n\n@table @asis\n@item @qcode{\"estimate\"}\nSpecifies that no run-time measurement of the optimal means of\ncalculating a particular is performed, and a simple heuristic is used\nto pick a (probably sub-optimal) plan.  The advantage of this method is\nthat there is little or no overhead in the generation of the plan, which\nis appropriate for a Fourier transform that will be calculated once.\n\n@item @qcode{\"measure\"}\nIn this case a range of algorithms to perform the transform is considered\nand the best is selected based on their execution time.\n\n@item @qcode{\"patient\"}\nSimilar to @qcode{\"measure\"}, but a wider range of algorithms is\nconsidered.\n\n@item @qcode{\"exhaustive\"}\nLike @qcode{\"measure\"}, but all possible algorithms that may be used to\ntreat the transform are considered.\n\n@item @qcode{\"hybrid\"}\nAs run-time measurement of the algorithm can be expensive, this is a\ncompromise where @qcode{\"measure\"} is used for transforms up to the size\nof 8192 and beyond that the @qcode{\"estimate\"} method is used.\n@end table\n\nThe default method is @qcode{\"estimate\"}.  The current method can\nbe queried with\n\n@example\n@var{method} = fftw (\"planner\")\n@end example\n\n@noindent\nor set by using\n\n@example\nfftw (\"planner\", @var{method})\n@end example\n\nNote that calculated wisdom will be lost when restarting Octave.  However,\nthe wisdom data can be reloaded if it is saved to a file as described\nabove.  Saved wisdom files should not be used on different platforms since\nthey will not be efficient and the point of calculating the wisdom is lost.\n\nThe number of threads used for computing the plans and executing the\ntransforms can be set with\n\n@example\nfftw (\"threads\", @var{NTHREADS})\n@end example\n\nNote that Octave must be compiled with multi-threaded @sc{fftw} support for\nthis feature.  By default, the number of (logical) processors available to the\ncurrent process or @var{3} is used (whichever is smaller).\n\n@seealso{fft, ifft, fft2, ifft2, fftn, ifftn}\n@end deftypefn */)\n{\n#if defined (HAVE_FFTW)\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  octave_value retval;\n\n  std::string arg0 = args(0).xstring_value (\"fftw: first argument must be a string\");\n\n  if (arg0 == \"planner\")\n    {\n      if (nargin == 2)  // planner setter\n        {\n          // Use STL function to convert to lowercase\n          std::transform (arg0.begin (), arg0.end (), arg0.begin (), tolower);\n\n          std::string arg1 = args(1).xstring_value (\"fftw: METHOD must be a string\");\n\n          std::transform (arg1.begin (), arg1.end (), arg1.begin (), tolower);\n          fftw_planner::FftwMethod meth\n            = fftw_planner::UNKNOWN;\n          float_fftw_planner::FftwMethod methf\n            = float_fftw_planner::UNKNOWN;\n\n          if (arg1 == \"estimate\")\n            {\n              meth = fftw_planner::ESTIMATE;\n              methf = float_fftw_planner::ESTIMATE;\n            }\n          else if (arg1 == \"measure\")\n            {\n              meth = fftw_planner::MEASURE;\n              methf = float_fftw_planner::MEASURE;\n            }\n          else if (arg1 == \"patient\")\n            {\n              meth = fftw_planner::PATIENT;\n              methf = float_fftw_planner::PATIENT;\n            }\n          else if (arg1 == \"exhaustive\")\n            {\n              meth = fftw_planner::EXHAUSTIVE;\n              methf = float_fftw_planner::EXHAUSTIVE;\n            }\n          else if (arg1 == \"hybrid\")\n            {\n              meth = fftw_planner::HYBRID;\n              methf = float_fftw_planner::HYBRID;\n            }\n          else\n            error (\"fftw: unrecognized planner METHOD\");\n\n          meth = fftw_planner::method (meth);\n          float_fftw_planner::method (methf);\n\n          if (meth == fftw_planner::MEASURE)\n            retval = octave_value (\"measure\");\n          else if (meth == fftw_planner::PATIENT)\n            retval = octave_value (\"patient\");\n          else if (meth == fftw_planner::EXHAUSTIVE)\n            retval = octave_value (\"exhaustive\");\n          else if (meth == fftw_planner::HYBRID)\n            retval = octave_value (\"hybrid\");\n          else\n            retval = octave_value (\"estimate\");\n        }\n      else //planner getter\n        {\n          fftw_planner::FftwMethod meth\n            = fftw_planner::method ();\n\n          if (meth == fftw_planner::MEASURE)\n            retval = octave_value (\"measure\");\n          else if (meth == fftw_planner::PATIENT)\n            retval = octave_value (\"patient\");\n          else if (meth == fftw_planner::EXHAUSTIVE)\n            retval = octave_value (\"exhaustive\");\n          else if (meth == fftw_planner::HYBRID)\n            retval = octave_value (\"hybrid\");\n          else\n            retval = octave_value (\"estimate\");\n        }\n    }\n  else if (arg0 == \"dwisdom\")\n    {\n      if (nargin == 2)  //dwisdom setter\n        {\n          // Use STL function to convert to lowercase\n          std::transform (arg0.begin (), arg0.end (), arg0.begin (),\n                          tolower);\n\n          std::string arg1 = args(1).xstring_value (\"fftw: WISDOM must be a string\");\n\n          char *str = fftw_export_wisdom_to_string ();\n          if (! str)\n            error (\"fftw: could not get current FFTW wisdom\");\n\n          std::string wisdom_str (str);\n          free (str);\n\n          if (arg1.length () < 1)\n            fftw_forget_wisdom ();\n          else if (! fftw_import_wisdom_from_string (arg1.c_str ()))\n            error (\"fftw: could not import supplied WISDOM\");\n\n          retval = octave_value (wisdom_str);\n        }\n      else //dwisdom getter\n        {\n          char *str = fftw_export_wisdom_to_string ();\n          if (! str)\n            error (\"fftw: could not get current FFTW wisdom\");\n\n          std::string wisdom_str (str);\n          free (str);\n          retval = octave_value (wisdom_str);\n        }\n    }\n  else if (arg0 == \"swisdom\")\n    {\n      //swisdom uses fftwf_ functions (float), dwisdom fftw_ (real)\n      if (nargin == 2)  //swisdom setter\n        {\n          // Use STL function to convert to lowercase\n          std::transform (arg0.begin (), arg0.end (), arg0.begin (),\n                          tolower);\n\n          std::string arg1 = args(1).xstring_value (\"fftw: WISDOM must be a string\");\n\n          char *str = fftwf_export_wisdom_to_string ();\n          if (! str)\n            error (\"fftw: could not get current FFTW wisdom\");\n\n          std::string wisdom_str (str);\n          free (str);\n\n          if (arg1.length () < 1)\n            fftwf_forget_wisdom ();\n          else if (! fftwf_import_wisdom_from_string (arg1.c_str ()))\n            error (\"fftw: could not import supplied WISDOM\");\n\n          retval = octave_value (wisdom_str);\n        }\n      else //swisdom getter\n        {\n          char *str = fftwf_export_wisdom_to_string ();\n          if (! str)\n            error (\"fftw: could not get current FFTW wisdom\");\n\n          std::string wisdom_str (str);\n          free (str);\n          retval = octave_value (wisdom_str);\n        }\n    }\n  else if (arg0 == \"threads\")\n    {\n      if (nargin == 2)  //threads setter\n        {\n          if (! args(1).is_real_scalar ())\n            error (\"fftw: setting threads needs one integer argument\");\n\n          int nthreads = args(1).int_value();\n          if (nthreads < 1)\n            error (\"fftw: number of threads must be >=1\");\n\n#if defined (HAVE_FFTW3_THREADS)\n          fftw_planner::threads (nthreads);\n#else\n          err_disabled_feature (\"fftw\", \"multithreaded FFTW\");\n#endif\n#if defined (HAVE_FFTW3F_THREADS)\n          float_fftw_planner::threads (nthreads);\n#else\n          err_disabled_feature (\"fftw\", \"multithreaded FFTW\");\n#endif\n        }\n      else //threads getter\n#if defined (HAVE_FFTW3_THREADS)\n        retval = octave_value (fftw_planner::threads());\n#else\n        retval = 1;\n#endif\n    }\n  else\n    error (\"fftw: unrecognized argument\");\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"fftw\", \"the FFTW3 planner\");\n\n#endif\n}\n\n/*\n%!testif HAVE_FFTW\n%! def_method = fftw (\"planner\");\n%! unwind_protect\n%!   method = \"estimate\";\n%!   fftw (\"planner\", method);\n%!   assert (fftw (\"planner\"), method);\n%!   method = \"measure\";\n%!   fftw (\"planner\", method);\n%!   assert (fftw (\"planner\"), method);\n%!   method = \"patient\";\n%!   fftw (\"planner\", method);\n%!   assert (fftw (\"planner\"), method);\n%!   method = \"exhaustive\";\n%!   fftw (\"planner\", method);\n%!   assert (fftw (\"planner\"), method);\n%!   method = \"hybrid\";\n%!   fftw (\"planner\", method);\n%!   assert (fftw (\"planner\"), method);\n%! unwind_protect_cleanup\n%!   fftw (\"planner\", def_method);\n%! end_unwind_protect\n\n%!testif HAVE_FFTW\n%! def_dwisdom = fftw (\"dwisdom\");\n%! def_swisdom = fftw (\"swisdom\");\n%! unwind_protect\n%!   wisdom = fftw (\"dwisdom\");\n%!   assert (ischar (wisdom));\n%!   fftw (\"dwisdom\", wisdom);\n%!   assert (fftw (\"dwisdom\"), wisdom);\n%!   wisdom = fftw (\"swisdom\");\n%!   assert (ischar (wisdom));\n%!   fftw (\"swisdom\", wisdom);\n%!   assert (fftw (\"swisdom\"), wisdom);\n%! unwind_protect_cleanup\n%!   fftw (\"dwisdom\", def_dwisdom);\n%!   fftw (\"swisdom\", def_swisdom);\n%! end_unwind_protect\n\n%!testif HAVE_FFTW3_THREADS\n%! n = fftw (\"threads\");\n%! unwind_protect\n%!   fftw (\"threads\", 3);\n%!   assert (fftw (\"threads\"), 3);\n%! unwind_protect_cleanup\n%!   fftw (\"threads\", n);\n%! end_unwind_protect\n\n%!error <Invalid call to fftw|was unavailable or disabled> fftw ()\n%!error <Invalid call to fftw|was unavailable or disabled> fftw (\"planner\", \"estimate\", \"measure\")\n%!error fftw (3)\n%!error fftw (\"invalid\")\n%!error fftw (\"planner\", \"invalid\")\n%!error fftw (\"planner\", 2)\n%!error fftw (\"dwisdom\", \"invalid\")\n%!error fftw (\"swisdom\", \"invalid\")\n%!error fftw (\"threads\", \"invalid\")\n%!error fftw (\"threads\", -3)\n */\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/gzip.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n//! @file gzip.cc\n//! Octave interface to the compression and uncompression libraries.\n//!\n//! This was originally implemented as an m file which directly called\n//! bzip2 and gzip applications.  This may look simpler but causes some\n//! issues (see bug #43431) because we have no control over the output\n//! file:\n//!\n//!   - created file is always in the same directory as the original file;\n//!   - automatically skip files that already have gz/bz2/etc extension;\n//!   - some older versions lack the --keep option.\n//!\n//! In addition, because system() does not have a method that allows\n//! passing a list of arguments, there is the issue of having to escape\n//! filenames.\n//!\n//! A solution is to pipe file contents into the applications instead of\n//! filenames.  However, that solution causes:\n//!\n//!   # missing file header with original file information;\n//!   # implementing ourselves the recursive transversion of directories;\n//!   # do the above in a m file which will be slow;\n//!   # popen2 is frail on windows.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdio>\n#include <cstring>\n\n#include <functional>\n#include <list>\n#include <stdexcept>\n#include <string>\n\n#include \"Array.h\"\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"glob-match.h\"\n#include \"oct-env.h\"\n#include \"oct-sysdep.h\"\n#include \"str-vec.h\"\n\n#include \"Cell.h\"\n#include \"defun-dld.h\"\n#include \"defun-int.h\"\n#include \"errwarn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\n#if defined (HAVE_BZLIB_H)\n#  include <bzlib.h>\n#endif\n\n#if defined (HAVE_ZLIB_H)\n#  include <zlib.h>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n//! RIIA wrapper for std::FILE*.\n//!\n//! If error handling is available for failing to close the file, use\n//! the close method which throws.\n//!\n//! If the file has been closed, fp is set to nullptr.  Remember that\n//! behavior is undefined if the value of the pointer stream is used\n//! after fclose.\n\nclass CFile\n{\npublic:\n\n  CFile () = delete;\n\n  CFile (const std::string& path, const std::string& mode)\n    : m_fp (sys::fopen (path, mode))\n  {\n    if (! m_fp)\n      throw std::runtime_error (\"unable to open file\");\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (CFile)\n\n  ~CFile ()\n  {\n    if (m_fp)\n      std::fclose (m_fp);\n  }\n\n  void close ()\n  {\n    if (std::fclose (m_fp))\n      throw std::runtime_error (\"unable to close file\");\n\n    m_fp = nullptr;\n  }\n\n  std::FILE *m_fp;\n};\n\n#if defined (HAVE_BZ2)\n\nclass bz2\n{\npublic:\n\n  static const constexpr char *extension = \".bz2\";\n\n  static void zip (const std::string& source_path,\n                   const std::string& dest_path)\n  {\n    bz2::zipper z (source_path, dest_path);\n    z.deflate ();\n    z.close ();\n  }\n\nprivate:\n\n  class zipper\n  {\n  public:\n\n    zipper () = delete;\n\n    zipper (const std::string& source_path, const std::string& dest_path)\n      : m_status (BZ_OK), m_source (source_path, \"rb\"),\n        m_dest (dest_path, \"wb\"),\n        m_bz (BZ2_bzWriteOpen (&m_status, m_dest.m_fp, 9, 0, 30))\n    {\n      if (m_status != BZ_OK)\n        throw std::runtime_error (\"failed to open bzip2 stream\");\n    }\n\n    OCTAVE_DISABLE_COPY_MOVE (zipper)\n\n    ~zipper ()\n    {\n      if (m_bz != nullptr)\n        BZ2_bzWriteClose (&m_status, m_bz, 1, nullptr, nullptr);\n    }\n\n    void deflate ()\n    {\n      const std::size_t buf_len = 8192;\n      char buf[buf_len];\n      std::size_t n_read;\n      while ((n_read = std::fread (buf, sizeof (buf[0]), buf_len, m_source.m_fp)) != 0)\n        {\n          if (std::ferror (m_source.m_fp))\n            throw std::runtime_error (\"failed to read from source file\");\n          BZ2_bzWrite (&m_status, m_bz, buf, n_read);\n          if (m_status == BZ_IO_ERROR)\n            throw std::runtime_error (\"failed to write or compress\");\n        }\n      if (std::ferror (m_source.m_fp))\n        throw std::runtime_error (\"failed to read from source file\");\n    }\n\n    void close ()\n    {\n      int abandon = (m_status == BZ_IO_ERROR) ? 1 : 0;\n      BZ2_bzWriteClose (&m_status, m_bz, abandon, nullptr, nullptr);\n      if (m_status != BZ_OK)\n        throw std::runtime_error (\"failed to close bzip2 stream\");\n      m_bz = nullptr;\n\n      // We have no error handling for failing to close source, let\n      // the destructor close it.\n      m_dest.close ();\n    }\n\n  private:\n\n    int m_status;\n    CFile m_source;\n    CFile m_dest;\n    BZFILE *m_bz;\n  };\n};\n\n#endif\n\n// Note about zlib and gzip\n//\n// gzip is a format for compressed single files.  zlib is a format\n// designed for in-memory and communication channel applications.\n// gzip uses the same format internally for the compressed data but\n// has different headers and trailers.\n//\n// zlib is also a library but gzip is not.  Very old versions of zlib do\n// not include functions to create useful gzip headers and trailers:\n//\n//      Note that you cannot specify special gzip header contents (e.g.,\n//      a file name or modification date), nor will inflate tell you what\n//      was in the gzip header.  If you need to customize the header or\n//      see what's in it, you can use the raw deflate and inflate\n//      operations and the crc32() function and roll your own gzip\n//      encoding and decoding.  Read the gzip RFC 1952 for details of the\n//      header and trailer format.\n//                                                          zlib FAQ\n//\n// Recent versions (on which we are already dependent) have deflateInit2()\n// to do it.  We still need to get the right metadata for the header\n// ourselves though.\n//\n// The header is defined in RFC #1952\n// GZIP file format specification version 4.3\n\n\n#if defined (HAVE_Z)\n\nclass gz\n{\npublic:\n\n  static const constexpr char *extension = \".gz\";\n\n  static void zip (const std::string& source_path,\n                   const std::string& dest_path)\n  {\n    gz::zipper z (source_path, dest_path);\n    z.deflate ();\n    z.close ();\n  }\n\nprivate:\n\n  // Util class to get a non-const char*\n  class uchar_array\n  {\n  public:\n\n    // Bytef is a typedef for unsigned char\n    unsigned char *p;\n\n    uchar_array () = delete;\n\n    uchar_array (const std::string& str)\n    {\n      p = new Bytef[str.length () + 1];\n      std::strcpy (reinterpret_cast<char *> (p), str.c_str ());\n    }\n\n    OCTAVE_DISABLE_COPY_MOVE (uchar_array)\n\n    ~uchar_array () { delete[] p; }\n  };\n\n  class gzip_header : public gz_header\n  {\n  public:\n\n    gzip_header () = delete;\n\n    gzip_header (const std::string& source_path)\n      : m_basename (sys::env::base_pathname (source_path))\n    {\n      const sys::file_stat source_stat (source_path);\n      if (! source_stat)\n        throw std::runtime_error (\"unable to stat source file\");\n\n      // time_t may be a signed int in which case it will be a\n      // positive number so it is safe to uLong.  Or is it?  Can\n      // unix_time really never be negative?\n      time = uLong (source_stat.mtime ().unix_time ());\n\n      //  If FNAME is set, an original file name is present,\n      //  terminated by a zero byte.  The name must consist of ISO\n      //  8859-1 (LATIN-1) characters; on operating systems using\n      //  EBCDIC or any other character set for file names, the name\n      //  must be translated to the ISO LATIN-1 character set.  This\n      //  is the original name of the file being compressed, with any\n      //  directory components removed, and, if the file being\n      //  compressed is on a file system with case insensitive names,\n      //  forced to lowercase.\n      name = m_basename.p;\n\n      // If we don't set it to Z_NULL, then it will set FCOMMENT (4th bit)\n      // on the FLG byte, and then write {0, 3} comment.\n      comment = Z_NULL;\n\n      // Seems to already be the default but we are not taking chances.\n      extra = Z_NULL;\n\n      // We do not want a CRC for the header.  That would be only 2 more\n      // bytes, and maybe it would be a good thing but we want to generate\n      // gz files similar to the default gzip application.\n      hcrc = 0;\n\n      // OS (Operating System):\n      //      0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)\n      //      1 - Amiga\n      //      2 - VMS (or OpenVMS)\n      //      3 - Unix\n      //      4 - VM/CMS\n      //      5 - Atari TOS\n      //      6 - HPFS filesystem (OS/2, NT)\n      //      7 - Macintosh\n      //      8 - Z-System\n      //      9 - CP/M\n      //     10 - TOPS-20\n      //     11 - NTFS filesystem (NT)\n      //     12 - QDOS\n      //     13 - Acorn RISCOS\n      //    255 - unknown\n      //\n      // The list is problematic because it mixes OS and filesystem.  It\n      // also does not specify whether filesystem relates to source or\n      // destination file.\n\n#if defined (__WIN32__)\n      // Or should it be 11?\n      os = 0;\n#elif defined (__APPLE__)\n      os = 7;\n#else\n      // Unix by default?\n      os = 3;\n#endif\n    }\n\n    OCTAVE_DISABLE_COPY_MOVE (gzip_header)\n\n    ~gzip_header () = default;\n\n  private:\n\n    // This must be kept for gz_header.name\n    uchar_array m_basename;\n  };\n\n  class zipper\n  {\n  public:\n\n    zipper () = delete;\n\n    zipper (const std::string& source_path, const std::string& dest_path)\n      : m_source (source_path, \"rb\"), m_dest (dest_path, \"wb\"),\n        m_header (source_path), m_strm (new z_stream)\n    {\n      m_strm->zalloc = Z_NULL;\n      m_strm->zfree = Z_NULL;\n      m_strm->opaque = Z_NULL;\n    }\n\n    OCTAVE_DISABLE_COPY_MOVE (zipper)\n\n    ~zipper ()\n    {\n      if (m_strm)\n        deflateEnd (m_strm);\n      delete m_strm;\n    }\n\n    void deflate ()\n    {\n      // int deflateInit2 (z_streamp m_strm,\n      //                   int  level,      // compression level (default is 8)\n      //                   int  method,\n      //                   int  windowBits, // 15 (default) + 16 (gzip format)\n      //                   int  memLevel,   // memory usage (default is 8)\n      //                   int  strategy);\n      int status = deflateInit2 (m_strm, 8, Z_DEFLATED, 31, 8,\n                                 Z_DEFAULT_STRATEGY);\n      if (status != Z_OK)\n        throw std::runtime_error (\"failed to open zlib stream\");\n\n      deflateSetHeader (m_strm, &m_header);\n\n      const std::size_t buf_len = 8192;\n      unsigned char buf_in[buf_len];\n      unsigned char buf_out[buf_len];\n\n      int flush;\n\n      do\n        {\n          m_strm->avail_in = std::fread (buf_in, sizeof (buf_in[0]),\n                                         buf_len, m_source.m_fp);\n\n          if (std::ferror (m_source.m_fp))\n            throw std::runtime_error (\"failed to read source file\");\n\n          m_strm->next_in = buf_in;\n          flush = (std::feof (m_source.m_fp) ? Z_FINISH : Z_NO_FLUSH);\n\n          // If deflate returns Z_OK and with zero avail_out, it must be\n          // called again after making room in the output buffer because\n          // there might be more output pending.\n          do\n            {\n              m_strm->avail_out = buf_len;\n              m_strm->next_out = buf_out;\n              status = ::deflate (m_strm, flush);\n              if (status == Z_STREAM_ERROR)\n                throw std::runtime_error (\"failed to deflate\");\n\n              std::fwrite (buf_out, sizeof (buf_out[0]),\n                           buf_len - m_strm->avail_out, m_dest.m_fp);\n              if (std::ferror (m_dest.m_fp))\n                throw std::runtime_error (\"failed to write file\");\n            }\n          while (m_strm->avail_out == 0);\n\n          if (m_strm->avail_in != 0)\n            throw std::runtime_error (\"failed to write file\");\n\n        }\n      while (flush != Z_FINISH);\n\n      if (status != Z_STREAM_END)\n        throw std::runtime_error (\"failed to write file\");\n    }\n\n    void close ()\n    {\n      if (deflateEnd (m_strm) != Z_OK)\n        throw std::runtime_error (\"failed to close zlib stream\");\n      delete m_strm;\n      m_strm = nullptr;\n\n      // We have no error handling for failing to close source, let\n      // the destructor close it.\n      m_dest.close ();\n    }\n\n  private:\n\n    CFile m_source;\n    CFile m_dest;\n    gzip_header m_header;\n    z_stream *m_strm;\n  };\n};\n\n#endif\n\n\ntemplate<typename X>\nstring_vector\nxzip (const Array<std::string>& source_patterns,\n      const std::function<std::string(const std::string&)>& mk_dest_path)\n{\n  std::list<std::string> dest_paths;\n\n  std::function<void(const std::string&)> walk;\n  walk = [&walk, &mk_dest_path, &dest_paths] (const std::string& path) -> void\n  {\n    const sys::file_stat fs (path);\n    // is_dir and is_reg will return false if failed to stat.\n    if (fs.is_dir ())\n      {\n        string_vector dirlist;\n        std::string msg;\n\n        // Collect the whole list of filenames first, before recursion\n        // to avoid issues with infinite loop if the action generates\n        // files in the same directory (highly likely).\n        if (sys::get_dirlist (path, dirlist, msg))\n          {\n            for (octave_idx_type i = 0; i < dirlist.numel (); i++)\n              if (dirlist(i) != \".\" && dirlist(i) != \"..\")\n                walk (sys::file_ops::concat (path, dirlist(i)));\n          }\n        // Note that we skip any problem with directories.\n      }\n    else if (fs.is_reg ())\n      {\n        const std::string dest_path = mk_dest_path (path);\n        try\n          {\n            X::zip (path, dest_path);\n          }\n        catch (const interrupt_exception&)\n          {\n            throw;  // interrupts are special, just re-throw.\n          }\n        catch (...)\n          {\n            // Error \"handling\" is not including filename on the output list.\n            // Also, remove created file which may not have been created\n            // in the first place.  Note that it is possible for the file\n            // to exist before the call to X::zip and that X::zip has not\n            // clobber it yet, but we remove it anyway.\n            sys::unlink (dest_path);\n            return;\n          }\n        dest_paths.push_front (dest_path);\n      }\n    // Skip all other file types and errors.\n    return;\n  };\n\n  for (octave_idx_type i = 0; i < source_patterns.numel (); i++)\n    {\n      const glob_match pattern (sys::file_ops::tilde_expand (source_patterns(i)));\n      const string_vector filepaths = pattern.glob ();\n      for (octave_idx_type j = 0; j < filepaths.numel (); j++)\n        walk (filepaths(j));\n    }\n  return string_vector (dest_paths);\n}\n\n\ntemplate<typename X>\nstring_vector\nxzip (const Array<std::string>& source_patterns)\n{\n  const std::string ext = X::extension;\n  const std::function<std::string(const std::string&)> mk_dest_path\n  = [&ext] (const std::string& source_path) -> std::string\n  {\n    return source_path + ext;\n  };\n  return xzip<X> (source_patterns, mk_dest_path);\n}\n\ntemplate<typename X>\nstring_vector\nxzip (const Array<std::string>& source_patterns, const std::string& out_dir)\n{\n  const std::string ext = X::extension;\n  const std::function<std::string(const std::string&)> mk_dest_path\n  = [&out_dir, &ext] (const std::string& source_path) -> std::string\n  {\n    // Strip any relative path (bug #58547)\n    std::size_t pos = source_path.find_last_of (sys::file_ops::dir_sep_str ());\n    const std::string basename =\n    (pos == std::string::npos ? source_path : source_path.substr (pos+1));\n    return sys::file_ops::concat (out_dir, basename + ext);\n  };\n\n  // We don't care if mkdir fails.  Maybe it failed because it already\n  // exists, or maybe it can't be created.  If the first, then there's\n  // nothing to do, if the later, then it will be handled later.  Any\n  // is to be handled by not listing files in the output.\n  sys::mkdir (out_dir, 0777);\n  return xzip<X> (source_patterns, mk_dest_path);\n}\n\ntemplate<typename X>\nstatic octave_value_list\nxzip (const std::string& fcn_name, const octave_value_list& args)\n{\n  const octave_idx_type nargin = args.length ();\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  const Array<std::string> source_patterns\n    = args(0).xcellstr_value (\"%s: FILES must be a character array or cellstr\",\n                              fcn_name.c_str ());\n  if (nargin == 1)\n    return octave_value (Cell (xzip<X> (source_patterns)));\n  else // nargin == 2\n    {\n      const std::string out_dir = args(1).string_value ();\n      return octave_value (Cell (xzip<X> (source_patterns, out_dir)));\n    }\n}\n\nDEFUN_DLD (gzip, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{filelist} =} gzip (@var{files})\n@deftypefnx {} {@var{filelist} =} gzip (@var{files}, @var{dir})\nCompress the list of files and directories specified in @var{files}.\n\n@var{files} is a character array or cell array of strings.  Shell wildcards\nin the filename such as @samp{*} or @samp{?} are accepted and expanded.\nEach file is compressed separately and a new file with a @file{\".gz\"}\nextension is created.  The original files are not modified, but existing\ncompressed files will be silently overwritten.  If a directory is\nspecified then @code{gzip} recursively compresses all files in the\ndirectory.\n\nIf @var{dir} is defined the compressed files are placed in this directory,\nrather than the original directory where the uncompressed file resides.\nNote that this does not replicate a directory tree in @var{dir} which may\nlead to files overwriting each other if there are multiple files with the\nsame name.\n\nIf @var{dir} does not exist it is created.\n\nThe optional output @var{filelist} is a list of the compressed files.\n@seealso{gunzip, unpack, bzip2, zip, tar}\n@end deftypefn */)\n{\n#if defined (HAVE_Z)\n\n  octave_value_list retval = xzip<gz> (\"gzip\", args);\n\n  return (nargout > 0 ? retval : octave_value_list ());\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"gzip\", \"gzip\");\n\n#endif\n}\n\n/*\n%!error gzip ()\n%!error gzip (\"1\", \"2\", \"3\")\n%!error <FILES must be a character array or cellstr|was unavailable or disabled> gzip (1)\n*/\n\nDEFUN_DLD (bzip2, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{filelist} =} bzip2 (@var{files})\n@deftypefnx {} {@var{filelist} =} bzip2 (@var{files}, @var{dir})\nCompress the list of files specified in @var{files}.\n\n@var{files} is a character array or cell array of strings.  Shell wildcards\nin the filename such as @samp{*} or @samp{?} are accepted and expanded.\nEach file is compressed separately and a new file with a @file{\".bz2\"}\nextension is created.  The original files are not modified, but existing\ncompressed files will be silently overwritten.\n\nIf @var{dir} is defined the compressed files are placed in this directory,\nrather than the original directory where the uncompressed file resides.\nNote that this does not replicate a directory tree in @var{dir} which may\nlead to files overwriting each other if there are multiple files with the\nsame name.\n\nIf @var{dir} does not exist it is created.\n\nThe optional output @var{filelist} is a list of the compressed files.\n@seealso{bunzip2, unpack, gzip, zip, tar}\n@end deftypefn */)\n{\n#if defined (HAVE_BZ2)\n\n  octave_value_list retval = xzip<bz2> (\"bzip2\", args);\n\n  return (nargout > 0 ? retval : octave_value_list ());\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"bzip2\", \"bzip2\");\n\n#endif\n}\n\n// Tests for both gzip/bzip2 and gunzip/bunzip2\n/*\n\n## Takes a single argument, a function handle for the test.  This other\n## function must accept two arguments, a directory for the tests, and\n## a cell array with zip function, unzip function, and file extension.\n\n%!function run_test_function (test_function)\n%!  enabled_zippers = struct (\"zip\", {}, \"unzip\", {}, \"ext\", {});\n%!  if (__octave_config_info__ ().build_features.BZ2)\n%!    enabled_zippers(end+1).zip = @bzip2;\n%!    enabled_zippers(end).unzip = @bunzip2;\n%!    enabled_zippers(end).ext = \".bz2\";\n%!  endif\n%!  if (__octave_config_info__ ().build_features.Z)\n%!    enabled_zippers(end+1).zip = @gzip;\n%!    enabled_zippers(end).unzip = @gunzip;\n%!    enabled_zippers(end).ext = \".gz\";\n%!  endif\n%!\n%!  for z = enabled_zippers\n%!    test_dir = tempname ();\n%!    if (! mkdir (test_dir))\n%!      error (\"unable to create directory for tests\");\n%!    endif\n%!    unwind_protect\n%!      test_function (test_dir, z)\n%!    unwind_protect_cleanup\n%!      confirm_recursive_rmdir (false, \"local\");\n%!      sts = rmdir (test_dir, \"s\");\n%!    end_unwind_protect\n%!  endfor\n%!endfunction\n\n%!function create_file (fpath, data)\n%!  fid = fopen (fpath, \"wb\");\n%!  if (fid < 0)\n%!    error (\"unable to open file for writing\");\n%!  endif\n%!  if (fwrite (fid, data, class (data)) != numel (data))\n%!    error (\"unable to write to file\");\n%!  endif\n%!  if (fflush (fid) || fclose (fid))\n%!    error (\"unable to flush or close file\");\n%!  endif\n%!endfunction\n\n%!function unlink_or_error (filepath)\n%!  [err, msg] = unlink (filepath);\n%!  if (err)\n%!    error (\"unable to remove file required for the test\");\n%!  endif\n%!endfunction\n\n## Test with large files because of varied buffer size\n%!function test_large_file (test_dir, z)\n%!  test_file = tempname (test_dir);\n%!  create_file (test_file, rand (500000, 1));\n%!  md5 = hash (\"md5\", fileread (test_file));\n%!\n%!  z_file = [test_file z.ext];\n%!  z_filelist = z.zip (test_file);\n%!  assert (is_same_file (z_filelist, {z_file}));\n%!\n%!  unlink_or_error (test_file);\n%!  uz_filelist = z.unzip (z_file);\n%!  assert (is_same_file (uz_filelist, {test_file}));\n%!\n%!  assert (hash (\"md5\", fileread (test_file)), md5);\n%!endfunction\n%!test run_test_function (@test_large_file)\n\n## Test that xzipped files are rexzipped (hits bug #43206, #48598)\n%!function test_z_z (test_dir, z)\n%!  ori_file = tempname (test_dir);\n%!  create_file (ori_file, rand (100, 1));\n%!  md5_ori = hash (\"md5\", fileread (ori_file));\n%!\n%!  z_file = [ori_file z.ext];\n%!  z_filelist = z.zip (ori_file);\n%!  assert (is_same_file (z_filelist, {z_file}));  # check output\n%!  assert (exist (z_file), 2);  # confirm file exists\n%!  assert (exist (ori_file), 2);  # and did not remove original file\n%!\n%!  unlink_or_error (ori_file);\n%!  uz_filelist = z.unzip (z_file);\n%!  assert (is_same_file (uz_filelist, {ori_file}));  # bug #48598\n%!  assert (hash (\"md5\", fileread (ori_file)), md5_ori);\n%!  assert (exist (z_file), 2);  # bug #48597\n%!\n%!  ## xzip should preserve original files.\n%!  z_z_file = [z_file z.ext];\n%!  z_z_filelist = z.zip (z_file);\n%!  assert (is_same_file (z_z_filelist, {z_z_file}));  # check output\n%!  assert (exist (z_z_file), 2);  # confirm file exists\n%!  assert (exist (z_file), 2);\n%!\n%!  md5_z = hash (\"md5\", fileread (z_file));\n%!  unlink_or_error (z_file);\n%!  uz_z_filelist = z.unzip (z_z_file);\n%!  assert (is_same_file (uz_z_filelist, {z_file}));  # bug #48598\n%!  assert (exist (z_z_file), 2);  # bug #43206\n%!  assert (hash (\"md5\", fileread (z_file)), md5_z);\n%!endfunction\n%!test <43206> run_test_function (@test_z_z)\n\n%!function test_xzip_dir (test_dir, z) # bug #43431\n%!  fpaths = fullfile (test_dir, {\"test1\", \"test2\", \"test3\"});\n%!  md5s = cell (1, 3);\n%!  for idx = 1:numel (fpaths)\n%!    create_file (fpaths{idx}, rand (100, 1));\n%!    md5s(idx) = hash (\"md5\", fileread (fpaths{idx}));\n%!  endfor\n%!\n%!  test_dir = [test_dir filesep()];\n%!\n%!  z_files = strcat (fpaths, z.ext);\n%!  z_filelist = z.zip (test_dir);\n%!  assert (sort (z_filelist), z_files(:));\n%!  for idx = 1:numel (fpaths)\n%!    assert (exist (z_files{idx}), 2);\n%!    unlink_or_error (fpaths{idx});\n%!  endfor\n%!\n%!  ## only gunzip handles directory (bunzip2 should too though)\n%!  if (z.unzip == @gunzip)\n%!    uz_filelist = z.unzip (test_dir);\n%!  else\n%!    uz_filelist = cell (1, numel (z_filelist));\n%!    for idx = 1:numel (z_filelist)\n%!      uz_filelist(idx) = z.unzip (z_filelist{idx});\n%!    endfor\n%!  endif\n%!  uz_filelist = sort (uz_filelist);\n%!  fpaths = sort (fpaths);\n%!  assert (is_same_file (uz_filelist(:), fpaths(:)));  # bug #48598\n%!  for idx = 1:numel (fpaths)\n%!    assert (hash (\"md5\", fileread (fpaths{idx})), md5s{idx});\n%!  endfor\n%!endfunction\n%!test <48598> run_test_function (@test_xzip_dir)\n\n%!function test_save_to_dir (test_dir, z)\n%!  filename = \"test-file\";\n%!  filepath = fullfile (test_dir, filename);\n%!  create_file (filepath, rand (100, 1));\n%!  md5 = hash (\"md5\", fileread (filepath));\n%!\n%!  ## test with existing and non-existing directory\n%!  out_dirs = {tempname (test_dir), tempname (test_dir)};\n%!  if (! mkdir (out_dirs{1}))\n%!    error (\"unable to create directory for test\");\n%!  endif\n%!  unwind_protect\n%!    for idx = 1:numel (out_dirs)\n%!      out_dir = out_dirs{idx};\n%!      uz_file = fullfile (out_dir, filename);\n%!      z_file = [uz_file z.ext];\n%!\n%!      z_filelist = z.zip (filepath, out_dir);\n%!      assert (z_filelist, {z_file});\n%!      assert (exist (z_file, \"file\"), 2);\n%!\n%!      uz_filelist = z.unzip (z_file);\n%!      assert (is_same_file (uz_filelist, {uz_file}));  # bug #48598\n%!\n%!      assert (hash (\"md5\", fileread (uz_file)), md5);\n%!    endfor\n%!  unwind_protect_cleanup\n%!    confirm_recursive_rmdir (false, \"local\");\n%!    for idx = 1:numel (out_dirs)\n%!      sts = rmdir (out_dirs{idx}, \"s\");\n%!    endfor\n%!  end_unwind_protect\n%!endfunction\n%!test run_test_function (@test_save_to_dir)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/dldfcn/module-files",
    "content": "# FILE|CPPFLAGS|LDFLAGS|LIBRARIES\n__delaunayn__.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)\n__fltk_uigetfile__.cc|$(FLTK_CPPFLAGS) $(FT2_CPPFLAGS)|$(FLTK_LDFLAGS) $(FT2_LDFLAGS)|$(FLTK_LIBS) $(FT2_LIBS)\n__glpk__.cc|$(GLPK_CPPFLAGS)|$(GLPK_LDFLAGS)|$(GLPK_LIBS)\n__init_fltk__.cc|$(FLTK_CPPFLAGS) $(FT2_CPPFLAGS) $(FONTCONFIG_CPPFLAGS)|$(FLTK_LDFLAGS) $(FT2_LDFLAGS)|$(FLTK_LIBS) $(FT2_LIBS) $(OPENGL_LIBS)\n__init_gnuplot__.cc|$(FT2_CPPFLAGS) $(FONTCONFIG_CPPFLAGS)||\n__ode15__.cc|$(SUNDIALS_XCPPFLAGS)|$(SUNDIALS_XLDFLAGS)|$(SUNDIALS_XLIBS)\n__voronoi__.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)\naudiodevinfo.cc|$(PORTAUDIO_CPPFLAGS)|$(PORTAUDIO_LDFLAGS)|$(PORTAUDIO_LIBS)\naudioread.cc|$(SNDFILE_CPPFLAGS)|$(SNDFILE_LDFLAGS)|$(SNDFILE_LIBS)\nconvhulln.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)\nfftw.cc|$(FFTW_XCPPFLAGS)|$(FFTW_XLDFLAGS)|$(FFTW_XLIBS)\ngzip.cc|$(Z_CPPFLAGS) $(BZ2_CPPFLAGS)|$(Z_LDFLAGS) $(BZ2_LDFLAGS)|$(Z_LIBS) $(BZ2_LIBS)\n"
  },
  {
    "path": "libinterp/dldfcn/oct-qhull.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_qhull_h)\n#define octave_oct_qhull_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdio>\n\nextern \"C\" {\n\n#if defined (HAVE_LIBQHULL_R_LIBQHULL_R_H)\n#  include <libqhull_r/libqhull_r.h>\n#  include <libqhull_r/qset_r.h>\n#  include <libqhull_r/geom_r.h>\n#  include <libqhull_r/poly_r.h>\n#  include <libqhull_r/io_r.h>\n#elif defined (HAVE_LIBQHULL_R_H)\n#  include <libqhull_r.h>\n#  include <qset_r.h>\n#  include <geom_r.h>\n#  include <poly_r.h>\n#  include <io_r.h>\n#endif\n\n}\n\n#endif\n"
  },
  {
    "path": "libinterp/liboctinterp-build-info.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_liboctinterp_build_info_h)\n#define octave_liboctinterp_build_info_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nextern OCTINTERP_API std::string liboctinterp_hg_id ();\n\n#endif\n"
  },
  {
    "path": "libinterp/liboctinterp-build-info.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"liboctinterp-build-info.h\"\n\nstd::string\nliboctinterp_hg_id ()\n{\n  return \"%OCTAVE_HG_ID%\";\n}\n"
  },
  {
    "path": "libinterp/mk-build-env-features.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Attempt to get traditional sort behavior based on byte values.\nLC_ALL=C\nexport LC_ALL\n\nset -e\n\nAWK=${AWK:-awk}\n\ncat << EOF\n// DO NOT EDIT!  Generated automatically from $conffile by Make.\"\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"build-env.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(build_env)\n\n    octave_scalar_map\n    features ()\n    {\n      static bool initialized = false;\n\n      static octave_scalar_map m;\n\n      if (! initialized)\n        {\n          static octave_value ov_true = (true);\n          static octave_value ov_false = (false);\n\nEOF\n\nfor conffile in \"$@\"; do\n  $AWK \\\n    '/# *define *(OCTAVE_HAVE|HAVE)_/ {\n       sub (/# *define */, \"\", $0);\n       sub (/(OCTAVE_HAVE|HAVE)_/, \"\", $1)\n       printf (\"          m.assign (\\\"%s\\\", ov_true);\\n\", $1);\n     }\n     /\\/\\* #undef (OCTAVE_HAVE|HAVE)_/ {\n       sub (/(OCTAVE_HAVE|HAVE)_/, \"\", $3);\n       printf (\"          m.assign (\\\"%s\\\", ov_false);\\n\", $3);\n     } {\n     }' $conffile\ndone | sort\n\ncat << EOF\n\n          initialized = true;\n        }\n\n      return m;\n    }\n\nOCTAVE_END_NAMESPACE(build_env)\nOCTAVE_END_NAMESPACE(octave)\nEOF\n"
  },
  {
    "path": "libinterp/mk-builtins.pl",
    "content": "#! /usr/bin/perl -w\n\n########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n$make_header = 0;\n$make_source = 0;\n\n$have_options = 1;\n\nwhile ($have_options)\n{\n  $opt = shift (@ARGV);\n\n  if ($opt eq \"--header\")\n    {\n      die \"mk-builtins.pl: only one of --header or --source may be specified\" if ($make_source);\n\n      $make_header = 1;\n    }\n  elsif ($opt eq \"--source\")\n    {\n      die \"mk-builtins.pl: only one of --header or --source may be specified\" if ($make_header);\n\n      $make_source = 1;\n    }\n  else\n    {\n      $srcdir = \"$opt\";\n      $opt = shift (@ARGV);\n      die \"mk-builtins.pl: '--' must separate SRCDIR from other file names\" if ($opt ne \"--\");\n      $have_options = 0;\n    }\n}\n\ndie \"usage: mk-builtins.pl --header|--source SRCDIR -- f1 f2 ...\" if (! @ARGV);\n\ndie \"mk-builtins.pl: one of --header or --source must be specified\" if (! $make_header && ! $make_source);\n\nif ($make_header)\n{\n  @method_names = ();\n  @fcn_names = ();\n\n  while ($file = shift (@ARGV))\n  {\n    if (! -f $file)\n    {\n      $file = \"$srcdir/$file\";\n    }\n\n    ## Generate a list of function names to declare.  We could do\n    ## this in one step, but this way keeps the sed patterns a\n    ## bit smaller.\n\n    open($fh, \"<\", $file) || die \"mk-builtins.pl: failed to open file $file\\n\";\n\n    while (<$fh>)\n    {\n      if (/^[ \\t]*DEF(METHOD|UN)[ \\t]*\\( *([^ ,]*).*$/)\n      {\n        $name = \"F$2\";\n        $is_method = ($1 eq \"METHOD\");\n      }\n      elsif (/^[ \\t]*DEF(METHOD|UN)X[ \\t]*\\( *\"[^\"]*\" *, *([^ ,]*).*$/)\n      {\n        $name = $2;\n        $is_method = ($1 eq \"METHOD\");\n      }\n\n      if ($name)\n      {\n        if ($is_method)\n        {\n          push (@method_names, $name);\n        }\n        else\n        {\n          push (@fcn_names, $name);\n        }\n\n        $name = \"\";\n        $is_method = 0;\n      }\n    }\n  }\n\n  print \"// DO NOT EDIT!  Generated automatically by mk-builtins.pl.\n\n#if ! defined (octave_builtin_defun_decls_h)\n#define octave_builtin_defun_decls_h 1\n\n#include \\\"octave-config.h\\\"\n\n#include \\\"ovl.h\\\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\n\";\n\n  if ($#method_names)\n  {\n    print \"// Methods\\n\\n\";\n  }\n\n  foreach $name (sort (@method_names))\n  {\n    print \"extern OCTINTERP_API octave_value_list\n$name (octave::interpreter&, const octave_value_list& = octave_value_list (), int = 0);\n\n\";\n  }\n\n  if ($#fcn_names)\n  {\n    print \"// Functions\\n\\n\";\n  }\n\n  foreach $name (sort (@fcn_names))\n  {\n    print \"extern OCTINTERP_API octave_value_list\n$name (const octave_value_list& = octave_value_list (), int = 0);\n\n\";\n  }\n\n  print \"\\nOCTAVE_END_NAMESPACE(octave)\\n\";\n\n  print \"\\n#endif\\n\";\n}\nelsif ($make_source)\n{\n  print \"// DO NOT EDIT!  Generated automatically by mk-builtins.pl.\n\n#if defined (HAVE_CONFIG_H)\n#  include \\\"config.h\\\"\n#endif\n\n#include \\\"builtin-defun-decls.h\\\"\n#include \\\"help.h\\\"\n#include \\\"ovl.h\\\"\n#include \\\"symtab.h\\\"\n#include \\\"variables.h\\\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n\";\n\n  @installer_functions = ();\n\n  foreach $arg (@ARGV)\n  {\n    $file = $arg;\n\n    if (! -f $file)\n    {\n      $file = \"$srcdir/$file\";\n    }\n\n    ($fcn = $arg) =~ s,.*/,,;\n    $fcn =~ s/\\.(cc|cpp|in\\.cc|yy|ll)$//;\n    $fcn =~ s/-/_/g;\n    $fcn = \"install_${fcn}_fcns\";\n\n    $fcn_header = \"\\n  static void\n  $fcn (symbol_table& symtab)\n  {\n    std::string file = \\\"$arg\\\";\";\n\n    open($fh, \"<\", $file) || die \"mk-builtins.pl: failed to open file $file\\n\";\n\n    ## Find DEFUN or DEFALIAS macros and generate the function calls that\n    ## install the built-in functions or function aliases.\n\n    $type = \"\";\n    $const_param = \"\";\n    $fname = \"\";\n    $name = \"\";\n    $alias = \"\";\n    $fcn_body = \"\";\n\n    %dispatch_map = ();\n\n    while ($line = <$fh>)\n    {\n      if ($line =~ /^ *DEF(METHOD|UN) *\\( *([^ ,]*) *,.*$/)\n      {\n        $type = \"fun\";\n        $fname = \"F$2\";\n        $name = \"$2\";\n      }\n      elsif ($line =~ /^ *DEF(METHOD|UN)X *\\( *\"([^\"]*)\" *, *([^ ,]*) *,.*$/)\n      {\n        $type = \"fun\";\n        $fname = \"$3\";\n        $name = \"$2\";\n      }\n      elsif ($line =~ /^ *DEFALIAS *\\( *([^ ,]*) *, *([^ )]*) *\\).*$/)\n      {\n        $type = \"alias\";\n        $alias = \"$1\";\n        $name = \"$2\";\n      }\n\n      if ($type eq \"fun\")\n      {\n        if (($line = <$fh>) =~ /^ *classes:/)\n        {\n          $line =~ s/\\s*classes:\\s*//;\n          $line =~ s/\\s*$//;\n          @classes = split (/\\s+/, $line);\n\n          $dispatch_map{$name} = [@classes];\n        }\n\n        ## We use the name appended to the \"external-doc\" tag to find\n        ## the docstring for aliases to this function.\n\n        $fcn_body .= \"\\n    symtab.install_built_in_function (\\\"$name\\\", octave_value (new octave_builtin ($fname, \\\"$name\\\", file, \\\"external-doc:$name\\\")));\";\n\n        $type = \"\";\n        $fname = \"\";\n        $name = \"\";\n        $const_param = \"\";\n      }\n      elsif ($type eq \"alias\")\n      {\n        $fcn_body .= \"\\n    symtab.alias_built_in_function (\\\"$alias\\\", \\\"$name\\\");\";\n\n        ## Preserve dispatch info (if any) that we have for the\n        ## original function.\n\n        if (exists $dispatch_map{$name})\n        {\n          @classes = @{$dispatch_map{$name}};\n\n          if (@classes)\n          {\n            $dispatch_map{$alias} = [@classes];\n          }\n        }\n\n        $type = \"\";\n        $name = \"\";\n        $alias = \"\";\n      }\n    }\n\n    foreach $fcn (sort (keys (%dispatch_map)))\n    {\n      $dispatch_code = \"\";\n\n      @classes =  @{$dispatch_map{$fcn}};\n\n      foreach $class (@classes)\n      {\n        $dispatch_code .= \"\\n    symtab.install_built_in_dispatch (\\\"$fcn\\\", \\\"$class\\\");\";\n      }\n\n    if ($dispatch_code)\n      {\n        $fcn_body .= \"\\n$dispatch_code\";\n      }\n    }\n\n    if ($fcn_body)\n      {\n        push (@installer_functions, $fcn);\n\n        print \"$fcn_header\\n$fcn_body\\n  }\\n\";\n      }\n  }\n\n  print \"\n  void\n  symbol_table::install_builtins ()\n  {\n\";\n\n  foreach $fcn (@installer_functions)\n  {\n    print \"    $fcn (*this);\\n\"\n  }\n\n  print \"  }\\n\";\n  print \"OCTAVE_END_NAMESPACE(octave)\\n\";\n}\n"
  },
  {
    "path": "libinterp/mk-doc.pl",
    "content": "#! /usr/bin/perl -w\n\n########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nunless (@ARGV > 1) { die \"Usage: $0 SRCDIR src-file1 ...\" }\n\n$srcdir = shift (@ARGV);\n\nprint <<__END_OF_MSG__;\n### DO NOT EDIT!\n###\n### This file is generated automatically from Octave source files.\n### Edit source files directly and run make to update this file.\n\n__END_OF_MSG__\n\nFILE: foreach $fname (@ARGV)\n{\n  if (-f \"$fname\")\n  {\n    $src_fname = \"$fname\";\n  }\n  else\n  {\n    $src_fname = \"$srcdir/$fname\";\n  }\n\n  open (SRC_FH, $src_fname) or die \"Unable to open $src_fname\";\n\n  @func_list = ();\n  @docstr = ();\n\n  LINE: while (my $line = <SRC_FH>)\n  {\n    if ($line =~ /^\\s*DEF(?:METHOD|METHOD_(|STATIC_)DLD|METHODX|METHODX_(|STATIC_)DLD|UN|UN_(|STATIC_)DLD|UNX|UNX_(|STATIC_)DLD)\\s*\\(/)\n    {\n      ($func) = $line =~ /\\(\"?(\\w+)\"?,/;\n      unless ($func) { die \"Unable to parse $src_fname at line $.\\n\" }\n      push (@func_list, $func);\n\n      ## Skip optional line that declares list of classes that this\n      ## function accepts.\n      $line = <SRC_FH>;\n      if ($line =~ m#\\s*classes:#)\n      {\n        $line = <SRC_FH>;\n      }\n\n      if ($line =~ m#\\s*doc:\\s+\\Q/*\\E\\s+\\Q-*- texinfo -*-\\E\\s*$#)\n      {\n        $str = \"-*- texinfo -*-\\n\";\n        $reading_docstring = 1;\n      }\n      else\n      {\n        print STDERR \"mk-doc.pl: undocumented function $func from $fname\\n\";\n        push (@docstr, \"Undocumented.\");\n      }\n    }\n    elsif ($reading_docstring)\n    {\n      if ($line =~ /^.*\\s+\\*\\/\\s*\\)\\s*$/)\n      {\n        $line =~ s#\\s+\\*/\\s*\\)\\s*$##;\n        push (@docstr, $str . $line);\n        $reading_docstring = 0;\n      }\n      else\n      {\n        $str .= $line;\n      }\n    }\n  }\n  close (SRC_FH);\n\n  ## Print results in DOCSTRING format\n  foreach $i (0 .. $#func_list)\n  {\n    $func = $func_list[$i];\n    print \"\\x{1d}$func\\n\";\n    print \"\\@c $func $fname\\n\";\n    print $docstr[$i],\"\\n\";\n  }\n\n}\n"
  },
  {
    "path": "libinterp/module.mk",
    "content": "LIBINTERP_DEFUN_FILES =\n\n%canon_reldir%_EXTRA_DIST =\n\n%canon_reldir%_CLEANFILES =\n%canon_reldir%_DISTCLEANFILES =\n%canon_reldir%_MAINTAINERCLEANFILES =\n\n## Search local directories before those specified by the user.\n%canon_reldir%_liboctinterp_la_CPPFLAGS = \\\n  @OCTINTERP_DLL_DEFS@ \\\n  -Iliboctave -I$(srcdir)/liboctave \\\n  -I$(srcdir)/liboctave/array \\\n  -Iliboctave/numeric -I$(srcdir)/liboctave/numeric \\\n  -Iliboctave/operators -I$(srcdir)/liboctave/operators \\\n  -I$(srcdir)/liboctave/system \\\n  -I$(srcdir)/liboctave/util \\\n  -I$(srcdir)/%reldir%/octave-value \\\n  -I%reldir% -I$(srcdir)/%reldir% \\\n  -I$(srcdir)/%reldir%/operators \\\n  -I%reldir%/parse-tree -I$(srcdir)/%reldir%/parse-tree \\\n  -I$(srcdir)/%reldir%/template-inst \\\n  -I%reldir%/corefcn -I$(srcdir)/%reldir%/corefcn \\\n  -I$(srcdir)/liboctave/wrappers \\\n  $(HDF5_CPPFLAGS) \\\n  $(MAGICK_CPPFLAGS)\n\noctlib_LTLIBRARIES += %reldir%/liboctinterp.la\n\n%canon_reldir%_pkgconfig_DATA = %reldir%/octinterp.pc\n\nBUILT_SOURCES += \\\n  %reldir%/builtin-defun-decls.h \\\n  %reldir%/corefcn/default-defs.h \\\n  %reldir%/corefcn/graphics-props.cc \\\n  %reldir%/corefcn/graphics.h \\\n  %reldir%/corefcn/mxtypes.h \\\n  %reldir%/corefcn/oct-tex-parser.h \\\n  %reldir%/corefcn/oct-tex-symbols.cc \\\n  %reldir%/parse-tree/oct-gperf.h \\\n  %reldir%/parse-tree/oct-parse.h\n\nULT_PARSER_SRC := \\\n  %reldir%/corefcn/oct-tex-lexer.in.ll\n\nGENERATED_PARSER_FILES := \\\n  %reldir%/corefcn/oct-tex-lexer.ll \\\n  %reldir%/corefcn/oct-tex-parser.h \\\n  %reldir%/parse-tree/oct-parse.h\n\n## These generated files are included in the source distribution to\n## avoid needing certain tools to build from a distribution tarball.\n\nLIBINTERP_BUILT_DISTFILES = \\\n  $(GENERATED_PARSER_FILES) \\\n  $(OPT_HANDLERS) \\\n  %reldir%/corefcn/oct-tex-symbols.cc \\\n  %reldir%/parse-tree/oct-gperf.h\n\n## Files that are created during build process and installed,\n## BUT not distributed in tarball.\nLIBINTERP_BUILT_NODISTFILES = \\\n  %reldir%/build-env-features.cc \\\n  %reldir%/build-env.cc \\\n  %reldir%/builtin-defun-decls.h \\\n  %reldir%/builtins.cc \\\n  %reldir%/corefcn/default-defs.h \\\n  %reldir%/corefcn/graphics-props.cc \\\n  %reldir%/corefcn/graphics.h \\\n  %reldir%/corefcn/mxtypes.h \\\n  %reldir%/corefcn/system/oct-errno.cc \\\n  %reldir%/liboctinterp-build-info.cc \\\n  %reldir%/operators/ops.cc\n\n## C++ files with templates that are #included, not compiled\nLIBINTERP_TEMPLATE_SRC =\n\n%canon_reldir%_EXTRA_DIST += \\\n  %reldir%/DOCSTRINGS \\\n  %reldir%/build-env.in.cc \\\n  %reldir%/liboctinterp-build-info.in.cc \\\n  %reldir%/mk-build-env-features.sh \\\n  %reldir%/mk-builtins.pl \\\n  %reldir%/mk-doc.pl \\\n  %reldir%/op-kw-docs \\\n  $(LIBINTERP_BUILT_DISTFILES)\n\noctinclude_HEADERS += \\\n  %reldir%/build-env.h \\\n  %reldir%/liboctinterp-build-info.h \\\n  %reldir%/octave.h \\\n  $(COREFCN_INC) \\\n  $(LIBINTERP_OPERATORS_INC) \\\n  $(LIBINTERP_TEMPLATE_SRC) \\\n  $(OCTAVE_VALUE_INC) \\\n  $(PARSE_TREE_INC) \\\n  $(PARSER_INC) \\\n  $(TEMPLATE_INST_INC)\n\nnoinst_HEADERS += \\\n  %reldir%/options.h \\\n  %reldir%/usage.h \\\n  $(NOINSTALL_LIBINTERP_OPERATORS_INC)\n\nnodist_octinclude_HEADERS += \\\n  %reldir%/builtin-defun-decls.h \\\n  %reldir%/corefcn/graphics.h \\\n  %reldir%/corefcn/mxtypes.h\n\nDIST_SRC += \\\n  %reldir%/octave.cc \\\n  $(LIBINTERP_TEMPLATE_SRC) \\\n  $(OCTAVE_VALUE_SRC) \\\n  $(PARSE_TREE_SRC) \\\n  $(COREFCN_SRC) \\\n  $(COREFCN_NUMERIC_SRC) \\\n  $(COREFCN_SYSTEM_SRC) \\\n  $(COREFCN_UTIL_SRC)\n\n%canon_reldir%_liboctinterp_la_LIBADD =\n\ninclude %reldir%/parse-tree/module.mk\ninclude %reldir%/octave-value/module.mk\ninclude %reldir%/operators/module.mk\ninclude %reldir%/template-inst/module.mk\ninclude %reldir%/corefcn/module.mk\ninclude %reldir%/dldfcn/module.mk\n\nDLD_LIBOCTINTERP_LIBADD = $(OCT_LTLINK_DEPS)\nLIBINTERP_DLDFCN_LIBADD =\n\n%canon_reldir%_liboctinterp_la_SOURCES = \\\n  %reldir%/octave.cc \\\n  $(LIBINTERP_OPERATORS_SRC) \\\n  $(TEMPLATE_INST_SRC)\n\nnodist_%canon_reldir%_liboctinterp_la_SOURCES = \\\n  %reldir%/build-env-features.cc \\\n  %reldir%/build-env.cc \\\n  %reldir%/builtin-defun-decls.h \\\n  %reldir%/builtins.cc \\\n  %reldir%/corefcn/default-defs.h \\\n  %reldir%/corefcn/graphics.h \\\n  %reldir%/corefcn/mxtypes.h \\\n  %reldir%/corefcn/system/oct-errno.cc \\\n  %reldir%/liboctinterp-build-info.cc \\\n  %reldir%/operators/ops.cc\n\n%canon_reldir%_liboctinterp_la_LIBADD += \\\n  $(LIBINTERP_DLDFCN_LIBADD) \\\n  liboctave/liboctave.la \\\n  $(LIBOCTINTERP_LINK_DEPS)\n\nif AMCOND_BUILD_EXTERNAL_LIBXERBLA\n  %canon_reldir%_liboctinterp_la_LIBADD += \\\n    liboctave/external/blas-xtra/libxerbla.la\nendif\n\n## Increment the following version numbers as needed and according\n## to the rules in the etc/HACKING.md file:\n\n%canon_reldir%_liboctinterp_current = 15\n%canon_reldir%_liboctinterp_revision = 0\n%canon_reldir%_liboctinterp_age = 0\n\n%canon_reldir%_liboctinterp_version_info = $(%canon_reldir%_liboctinterp_current):$(%canon_reldir%_liboctinterp_revision):$(%canon_reldir%_liboctinterp_age)\n\n%canon_reldir%_liboctinterp_la_LDFLAGS = \\\n  $(AM_LDFLAGS) \\\n  -version-info $(%canon_reldir%_liboctinterp_version_info) \\\n  $(NO_UNDEFINED_LDFLAG) \\\n  -bindir $(bindir) \\\n  $(LIBOCTINTERP_LINK_OPTS) \\\n  $(WARN_LDFLAGS)\n\nULT_DIST_SRC := \\\n  $(filter-out $(GENERATED_PARSER_FILES), $(DIST_SRC)) \\\n  $(ULT_PARSER_SRC)\n\nLIBINTERP_FOUND_DEFUN_FILES := \\\n  $(shell $(SHELL) build-aux/find-defun-files.sh \"$(srcdir)\" $(ULT_DIST_SRC))\n\nBUILT_IN_DEFUN_FILES := $(OPT_HANDLERS) $(LIBINTERP_FOUND_DEFUN_FILES)\n\nLIBINTERP_DEFUN_FILES += \\\n  $(BUILT_IN_DEFUN_FILES)\n\n## Rules to build test files\n\nLIBINTERP_TST_FILES_SRC := $(shell $(SHELL) build-aux/find-files-with-tests.sh \"$(srcdir)\" $(ULT_DIST_SRC) $(DLDFCN_SRC))\n\nLIBINTERP_TST_FILES := $(addsuffix -tst,$(LIBINTERP_TST_FILES_SRC))\n\nlibinterptestsdir := $(octtestsdir)\n\nnobase_libinterptests_DATA = $(LIBINTERP_TST_FILES)\n\n## Cancel the suffix rule and use a pattern rule instead.\n.yy.cc:\n\n%.cc %.h : %.yy\n\t$(AM_V_BISON)$(am__skipbison) $(BISONCOMPILE) --defines=\"$*.h\" --output=\"$*.cc\" $<\n\n## Special rules:\n## Mostly for sources which must be built before rest of compilation.\n\n%reldir%/build-env.cc: %reldir%/build-env.in.cc build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)\n\n%reldir%/build-env-features.cc: config.h %reldir%/mk-build-env-features.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t && \\\n\t$(SHELL) $(srcdir)/%reldir%/mk-build-env-features.sh $< > $@-t && \\\n\tmv $@-t $@\n\n%reldir%/liboctinterp-build-info.cc: %reldir%/liboctinterp-build-info.in.cc HG-ID | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(build-info-commands)\n\nmkbuiltins_dld_opt =\n\n%reldir%/builtins.cc: $(LIBINTERP_DEFUN_FILES) %reldir%/mk-builtins.pl | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t && \\\n\t$(PERL) $(srcdir)/%reldir%/mk-builtins.pl --source $(mkbuiltins_dld_opt) \"$(srcdir)\" -- $(LIBINTERP_DEFUN_FILES) > $@-t && \\\n\tmv $@-t $@\n\n%reldir%/builtin-defun-decls.h: $(LIBINTERP_DEFUN_FILES) %reldir%/mk-builtins.pl | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t && \\\n\t$(PERL) $(srcdir)/%reldir%/mk-builtins.pl --header $(mkbuiltins_dld_opt) \"$(srcdir)\" -- $(LIBINTERP_DEFUN_FILES) > $@-t && \\\n\t$(simple_move_if_change_rule)\n\nDOCSTRING_FILES += %reldir%/DOCSTRINGS\n\n%reldir%/DOCSTRINGS: $(LIBINTERP_DEFUN_FILES) %reldir%/op-kw-docs | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f %reldir%/DOCSTRINGS-t && \\\n\t( $(PERL) $(srcdir)/%reldir%/mk-doc.pl \"$(srcdir)\" $(LIBINTERP_DEFUN_FILES); $(SED) -ne '/^\\x1d/,$$p' $(srcdir)/%reldir%/op-kw-docs ) > %reldir%/DOCSTRINGS-t && \\\n\t$(call move_if_change_rule,%reldir%/DOCSTRINGS-t,$@)\n\nOCTAVE_INTERPRETER_TARGETS += \\\n  $(LIBINTERP_TST_FILES)\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\ninstall-data-hook: install-oct install-built-in-docstrings\n\nuninstall-local: uninstall-oct uninstall-built-in-docstrings\n\ninstall-built-in-docstrings: %reldir%/DOCSTRINGS\n\t$(MKDIR_P) $(DESTDIR)$(octetcdir)\n\t$(INSTALL_DATA) $< $(DESTDIR)$(octetcdir)/built-in-docstrings\n.PHONY: install-built-in-docstrings\n\nuninstall-built-in-docstrings:\n\trm -f $(DESTDIR)$(octetcdir)/built-in-docstrings\n.PHONY: uninstall-built-in-docstrings\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n\n%canon_reldir%_CLEANFILES += \\\n  $(LIBINTERP_BUILT_NODISTFILES) \\\n  $(LIBINTERP_TST_FILES) \\\n  %reldir%/corefcn/oct-tex-parser.output \\\n  %reldir%/parse-tree/oct-parse.output\n\n%canon_reldir%_DISTCLEANFILES += \\\n  $(%canon_reldir%_pkgconfig_DATA)\n\n%canon_reldir%_MAINTAINERCLEANFILES += \\\n  %reldir%/DOCSTRINGS \\\n  $(LIBINTERP_BUILT_DISTFILES)\n\nBUILT_DISTFILES += $(LIBINTERP_BUILT_DISTFILES)\nBUILT_NODISTFILES += $(LIBINTERP_BUILT_NODISTFILES)\n\nCLEANFILES += $(%canon_reldir%_CLEANFILES)\nDISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)\nMAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)\n\nlibinterp-clean:\n\trm -f $(%canon_reldir%_CLEANFILES)\n\nlibinterp-distclean: libinterp-clean\n\trm -f $(%canon_reldir%_DISTCLEANFILES)\n\nlibinterp-maintainer-clean: libinterp-distclean\n\trm -f $(%canon_reldir%_MAINTAINERCLEANFILES)\n"
  },
  {
    "path": "libinterp/octave-value/cdef-class.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"cdef-class.h\"\n#include \"cdef-manager.h\"\n#include \"cdef-method.h\"\n#include \"cdef-package.h\"\n#include \"cdef-property.h\"\n#include \"cdef-utils.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ov-builtin.h\"\n#include \"ov-classdef.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-usr-fcn.h\"\n#include \"parse.h\"\n#include \"pt-assign.h\"\n#include \"pt-classdef.h\"\n#include \"pt-eval.h\"\n#include \"pt-idx.h\"\n#include \"pt-misc.h\"\n#include \"pt-stmt.h\"\n#include \"pt-walk.h\"\n#include \"unwind-prot.h\"\n\n#define OCTAVE_CDEF_CLASS_DEBUG 0\n#if OCTAVE_CDEF_CLASS_DEBUG\n#  include <iostream>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic octave_value\nmake_fcn_handle (const octave_value& fcn, const std::string& meth_name,\n                 const std::string& class_name)\n{\n  octave_value retval;\n\n  if (fcn.is_defined ())\n    {\n      // FCN_HANDLE: METHOD\n      octave_fcn_handle *fh\n        = new octave_fcn_handle (fcn, class_name, meth_name);\n\n      retval = octave_value (fh);\n    }\n\n  return retval;\n}\n\ncdef_class::cdef_class_rep::cdef_class_rep (const std::list<cdef_class>& superclasses)\n  : cdef_meta_object_rep (), m_member_count (0), m_handle_class (false),\n    m_meta (false)\n{\n  put (\"SuperClasses\", to_ov (superclasses));\n  m_implicit_ctor_list = superclasses;\n}\n\ncdef_method\ncdef_class::cdef_class_rep::find_method (const std::string& nm, bool local)\n{\n  auto it = m_method_map.find (nm);\n\n  if (it == m_method_map.end ())\n    {\n      // FIXME: look into class directory\n    }\n  else\n    {\n      cdef_method& meth = it->second;\n\n      // FIXME: check if method reload needed\n\n      if (meth.ok ())\n        return meth;\n    }\n\n  if (! local)\n    {\n      // Look into superclasses\n\n      Cell super_classes = get (\"SuperClasses\").cell_value ();\n      cdef_class cls1;\n      int nfnd = 0;\n\n      for (int i = 0; i < super_classes.numel (); i++)\n        {\n          cdef_class cls = lookup_class (super_classes(i));\n\n          cdef_method meth = cls.find_method (nm);\n\n          if (meth.ok ())\n            {\n              nfnd++;\n              if (nfnd == 1)\n                cls1 = cls;\n              else if (nfnd == 2)\n                // FIXME: This error is emitted when a method with conflicting\n                //        definitions is attempted to be used.  Ideally, this\n                //        error would be emitted on construction of the object.\n                error (\"method %s: conflicting definitions in classes '%s' and '%s'\",\n                       nm.c_str (), cls1.get_name ().c_str (),\n                       cls.get_name ().c_str ());\n            }\n        }\n\n      if (nfnd == 1)\n        return cls1.find_method (nm);\n    }\n\n  return cdef_method ();\n}\n\nclass ctor_analyzer : public tree_walker\n{\npublic:\n\n  ctor_analyzer () = delete;\n\n  ctor_analyzer (const std::string& ctor, const std::string& obj)\n    : tree_walker (), m_who (ctor), m_obj_name (obj) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (ctor_analyzer)\n\n  ~ctor_analyzer () = default;\n\n  void visit_statement (tree_statement& t)\n  {\n    if (t.is_expression ())\n      t.expression ()->accept (*this);\n  }\n\n  void visit_simple_assignment (tree_simple_assignment& t)\n  {\n    t.right_hand_side ()->accept (*this);\n  }\n\n  void visit_multi_assignment (tree_multi_assignment& t)\n  {\n    t.right_hand_side ()->accept (*this);\n  }\n\n  void visit_index_expression (tree_index_expression& t)\n  {\n    t.expression ()->accept (*this);\n  }\n\n  std::list<cdef_class> get_constructor_list () const\n  { return m_ctor_list; }\n\n  // NO-OP\n\n  void visit_anon_fcn_handle (tree_anon_fcn_handle&) { }\n  void visit_argument_list (tree_argument_list&) { }\n  void visit_binary_expression (tree_binary_expression&) { }\n  void visit_break_command (tree_break_command&) { }\n  void visit_colon_expression (tree_colon_expression&) { }\n  void visit_continue_command (tree_continue_command&) { }\n  void visit_decl_command (tree_decl_command&) { }\n  void visit_decl_init_list (tree_decl_init_list&) { }\n  void visit_decl_elt (tree_decl_elt&) { }\n  void visit_simple_for_command (tree_simple_for_command&) { }\n  void visit_complex_for_command (tree_complex_for_command&) { }\n  void visit_octave_user_script (octave_user_script&) { }\n  void visit_octave_user_function (octave_user_function&) { }\n  void visit_function_def (tree_function_def&) { }\n  void visit_identifier (tree_identifier&) { }\n  void visit_if_clause (tree_if_clause&) { }\n  void visit_if_command (tree_if_command&) { }\n  void visit_if_command_list (tree_if_command_list&) { }\n  void visit_switch_case (tree_switch_case&) { }\n  void visit_switch_case_list (tree_switch_case_list&) { }\n  void visit_switch_command (tree_switch_command&) { }\n  void visit_matrix (tree_matrix&) { }\n  void visit_cell (tree_cell&) { }\n  void visit_no_op_command (tree_no_op_command&) { }\n  void visit_constant (tree_constant&) { }\n  void visit_fcn_handle (tree_fcn_handle&) { }\n  void visit_parameter_list (tree_parameter_list&) { }\n  void visit_postfix_expression (tree_postfix_expression&) { }\n  void visit_prefix_expression (tree_prefix_expression&) { }\n  void visit_return_command (tree_return_command&) { }\n  void visit_try_catch_command (tree_try_catch_command&) { }\n  void visit_unwind_protect_command (tree_unwind_protect_command&) { }\n  void visit_while_command (tree_while_command&) { }\n  void visit_do_until_command (tree_do_until_command&) { }\n\n  void visit_superclass_ref (tree_superclass_ref& t)\n  {\n    if (t.method_name () == m_obj_name)\n      {\n        std::string class_name = t.class_name ();\n\n        cdef_class cls = lookup_class (class_name, false);\n\n        if (cls.ok ())\n          m_ctor_list.push_back (cls);\n      }\n  }\n\nprivate:\n\n  // The name of the constructor being analyzed.\n  std::string m_who;\n\n  // The name of the first output argument of the constructor.\n  std::string m_obj_name;\n\n  // The list of superclass constructors that are explicitly called.\n  std::list<cdef_class> m_ctor_list;\n};\n\nvoid\ncdef_class::cdef_class_rep::install_method (const cdef_method& meth)\n{\n  std::string method_name = meth.get_name ();\n  auto it = m_method_map.find (method_name);\n  //  Check if a method with the same name already exists before\n  //  installing a new one.\n  if (it != m_method_map.end ())\n    {\n      std::string class_file = file_name ();\n      error (\"duplicate method '%s' in class '%s' in file '%s'\",\n             method_name.c_str (), get_name ().c_str (), class_file.c_str ());\n    }\n\n  // Now safely install the new method\n  m_method_map[method_name] = meth;\n\n  m_member_count++;\n\n  if (meth.is_constructor ())\n    {\n      // Analyze the constructor code to determine what superclass\n      // constructors are called explicitly.\n\n      octave_value ov_fcn = meth.get_function ();\n\n      if (ov_fcn.is_defined ())\n        {\n          octave_user_function *uf = ov_fcn.user_function_value (true);\n\n          if (uf)\n            {\n              tree_parameter_list *ret_list = uf->return_list ();\n              tree_statement_list *body = uf->body ();\n\n              if (! ret_list || ret_list->size () < 1)\n                error (\"%s: invalid constructor output arguments\",\n                       meth.get_name ().c_str ());\n\n              std::string m_obj_name = ret_list->front ()->name ();\n              ctor_analyzer a (meth.get_name (), m_obj_name);\n\n              body->accept (a);\n\n              std::list<cdef_class> explicit_ctor_list\n                = a.get_constructor_list ();\n\n              for (const auto& cdef_cls : explicit_ctor_list)\n                {\n#if OCTAVE_CDEF_CLASS_DEBUG\n                  std::cerr << \"explicit superclass constructor: \"\n                            << cdef_cls.get_name () << std::endl;\n#endif\n\n                  m_implicit_ctor_list.remove (cdef_cls);\n                }\n            }\n        }\n    }\n}\n\nvoid\ncdef_class::cdef_class_rep::load_all_methods ()\n{\n  // FIXME: re-scan class directory\n}\n\nCell\ncdef_class::cdef_class_rep::get_methods (bool include_ctor)\n{\n  std::map<std::string, cdef_method> meths;\n\n  find_methods (meths, false, include_ctor);\n\n  Cell c (meths.size (), 1);\n\n  int idx = 0;\n\n  for (const auto& nm_mthd : meths)\n    c(idx++, 0) = to_ov (nm_mthd.second);\n\n  return c;\n}\n\nstd::map<std::string, cdef_method>\ncdef_class::cdef_class_rep::get_method_map (bool only_inherited,\n    bool include_ctor)\n{\n  std::map<std::string, cdef_method> methods;\n\n  find_methods (methods, only_inherited, include_ctor);\n\n  return methods;\n}\n\nvoid\ncdef_class::cdef_class_rep::find_methods (std::map<std::string,\n    cdef_method>& meths,\n    bool only_inherited,\n    bool include_ctor)\n{\n  load_all_methods ();\n\n  for (const auto& it : m_method_map)\n    {\n      if (include_ctor || ! it.second.is_constructor ())\n        {\n          std::string nm = it.second.get_name ();\n\n          if (meths.find (nm) == meths.end ())\n            {\n              if (only_inherited)\n                {\n                  octave_value acc = it.second.get (\"Access\");\n\n                  if (! acc.is_string ()\n                      || acc.string_value () == \"private\")\n                    continue;\n                }\n\n              meths[nm] = it.second;\n            }\n        }\n    }\n\n  // Look into superclasses\n\n  Cell super_classes = get (\"SuperClasses\").cell_value ();\n\n  for (int i = 0; i < super_classes.numel (); i++)\n    {\n      cdef_class cls = lookup_class (super_classes(i));\n\n      cls.get_rep ()->find_methods (meths, true, false);\n    }\n}\n\ncdef_property\ncdef_class::cdef_class_rep::find_property (const std::string& nm)\n{\n  auto it = m_property_map.find (nm);\n\n  if (it != m_property_map.end ())\n    {\n      cdef_property& prop = it->second;\n\n      if (prop.ok ())\n        return prop;\n    }\n\n  // Look into superclasses\n\n  Cell super_classes = get (\"SuperClasses\").cell_value ();\n  cdef_class cls1;\n  int nfnd = 0;\n\n  for (int i = 0; i < super_classes.numel (); i++)\n    {\n      cdef_class cls = lookup_class (super_classes(i));\n\n      cdef_property prop = cls.find_property (nm);\n\n      if (prop.ok ())\n        {\n          nfnd++;\n          if (nfnd == 1)\n            cls1 = cls;\n          else if (nfnd == 2)\n            // FIXME: This error is emitted when a property with conflicting\n            //        definitions is attempted to be used.  Ideally, this\n            //        error would be emitted on construction of the object.\n            error (\"property %s: conflicting definitions in classes '%s' and '%s'\",\n                   nm.c_str (), cls1.get_name ().c_str (),\n                   cls.get_name ().c_str ());\n        }\n     }\n\n  if (nfnd == 1)\n    return cls1.find_property (nm);\n\n  return cdef_property ();\n}\n\nvoid\ncdef_class::cdef_class_rep::install_property (const cdef_property& prop)\n{\n  std::string prop_name = prop.get_name ();\n  auto it = m_property_map.find (prop_name);\n  //  Check if a property with the same name already exists before\n  //  installing a new one.\n  if (it != m_property_map.end ())\n    {\n      std::string class_file = file_name ();\n      error (\"duplicate property '%s' in class '%s' in file '%s'\",\n             prop_name.c_str (), get_name ().c_str (), class_file.c_str ());\n    }\n\n  m_property_map[prop_name] = prop;\n\n  // Register the insertion rank of this property\n  m_property_rank_map[prop.get_name ()] = m_member_count;\n\n  m_member_count++;\n}\n\nCell\ncdef_class::cdef_class_rep::get_properties (int mode)\n{\n  std::map<property_key, cdef_property> props;\n\n  props = get_property_map (mode);\n\n  Cell c (props.size (), 1);\n\n  int idx = 0;\n\n  for (const auto& pname_prop : props)\n    c(idx++, 0) = to_ov (pname_prop.second);\n\n  return c;\n}\n\nstd::map<property_key, cdef_property>\ncdef_class::cdef_class_rep::get_property_map (int mode)\n{\n  std::map<property_key, cdef_property> props;\n\n  find_properties (props, mode);\n\n  return props;\n}\n\nvoid\ncdef_class::cdef_class_rep::find_properties\n  (std::map<property_key, cdef_property>& props, int mode)\n{\n  std::set<std::string> prop_names;\n\n  // The only reason we are introducing 'prop_names' is to keep\n  // track of property names and avoid returning duplicates.\n  // There is no easy way to do it based on 'props', which is going\n  // to use complex keys of type 'property_key'.\n  find_properties_aux (props, prop_names, mode);\n}\n\nvoid\ncdef_class::cdef_class_rep::find_properties_aux\n  (std::map<property_key, cdef_property>& props,\n   std::set<std::string>& prop_names, int mode)\n{\n  // 'offset' starts at 0 and is incremented whenever we move\n  // in the class ancestry list.\n  static unsigned int property_offset {0};\n\n  for (const auto& it : m_property_map)\n    {\n      std::string nm = it.second.get_name ();\n\n      if (prop_names.find (nm) == prop_names.end ())\n        {\n          if (mode == property_inherited)\n            {\n              octave_value acc = it.second.get (\"GetAccess\");\n\n              if (! acc.is_string ()\n                  || acc.string_value () == \"private\")\n                continue;\n            }\n\n          const property_key pk =\n            std::make_pair (property_offset + m_property_rank_map[nm], nm);\n          props[pk] = it.second;\n          prop_names.insert (nm);\n        }\n    }\n\n  property_offset += m_member_count;\n\n  // Look into superclasses\n\n  Cell super_classes = get (\"SuperClasses\").cell_value ();\n\n  for (int i = 0; i < super_classes.numel (); i++)\n    {\n      cdef_class cls = lookup_class (super_classes(i));\n\n      cls.get_rep ()->find_properties_aux (props, prop_names,\n                                           (mode == property_all\n                                            ? property_all\n                                            : property_inherited));\n    }\n\n  property_offset = 0;\n}\n\nvoid\ncdef_class::cdef_class_rep::find_names (std::set<std::string>& names,\n                                        bool all)\n{\n  load_all_methods ();\n\n  for (const auto& cls_fnmap : m_method_map)\n    {\n      if (! cls_fnmap.second.is_constructor ())\n        {\n          std::string nm = cls_fnmap.second.get_name ();\n\n          if (! all)\n            {\n              octave_value acc = cls_fnmap.second.get (\"Access\");\n\n              if (! acc.is_string()\n                  || acc.string_value () != \"public\")\n                continue;\n            }\n\n          names.insert (nm);\n        }\n    }\n\n  for (const auto& pname_prop : m_property_map)\n    {\n      std::string nm = pname_prop.second.get_name ();\n\n      if (! all)\n        {\n          octave_value acc = pname_prop.second.get (\"GetAccess\");\n\n          if (! acc.is_string()\n              || acc.string_value () != \"public\")\n            continue;\n        }\n\n      names.insert (nm);\n    }\n\n  // Look into superclasses\n\n  Cell super_classes = get (\"SuperClasses\").cell_value ();\n\n  for (int i = 0; i < super_classes.numel (); i++)\n    {\n      cdef_class cls = lookup_class (super_classes(i));\n\n      cls.get_rep ()->find_names (names, all);\n    }\n}\n\nstring_vector\ncdef_class::cdef_class_rep::get_names ()\n{\n  std::set<std::string> names;\n\n  find_names (names, false);\n\n  string_vector v (names);\n\n  return v.sort (true);\n}\n\nvoid\ncdef_class::cdef_class_rep::delete_object (const cdef_object& obj)\n{\n  cdef_method dtor = find_method (\"delete\");\n\n  // FIXME: would it be better to tell find_method above to not find\n  // overloaded functions?\n\n  if (dtor.ok () && dtor.is_defined_in_class (get_name ()))\n    dtor.execute (obj, octave_value_list (), 0, true, \"destructor\");\n\n  // FIXME: should we destroy corresponding properties here?\n\n  // Call \"delete\" in super classes\n\n  Cell super_classes = get (\"SuperClasses\").cell_value ();\n\n  for (int i = 0; i < super_classes.numel (); i++)\n    {\n      cdef_class cls = lookup_class (super_classes(i));\n\n      if (cls.get_name () != \"handle\")\n        cls.delete_object (obj);\n    }\n}\n\noctave_value_list\ncdef_class::cdef_class_rep::meta_subsref (const std::string& type,\n    const std::list<octave_value_list>& idx,\n    int nargout)\n{\n  std::size_t skip = 1;\n\n  octave_value_list retval;\n\n  switch (type[0])\n    {\n    case '(':\n      // Constructor call\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n      std::cerr << \"constructor\" << std::endl;\n#endif\n\n      retval = construct_object (idx.front (), nargout);\n      break;\n\n    case '.':\n      {\n        // Static method, constant (or property?)\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n        std::cerr << \"static method/property\" << std::endl;\n#endif\n\n        if (idx.front ().length () != 1)\n          error (\"invalid meta.class indexing\");\n\n        std::string nm = idx.front ()(0).xstring_value (\"invalid meta.class indexing, expected a method or property name\");\n\n        cdef_method meth = find_method (nm);\n\n        if (meth.ok ())\n          {\n            if (! meth.is_static ())\n              error (\"method '%s' is not static\", nm.c_str ());\n\n            octave_value_list args;\n\n            if (type.length () > 1 && idx.size () > 1 && type[1] == '(')\n              {\n                args = *(++(idx.begin ()));\n                skip++;\n              }\n\n            retval = meth.execute (args, (type.length () > skip\n                                          ? 1 : nargout), true,\n                                   \"meta.class\");\n          }\n        else\n          {\n            cdef_property prop = find_property (nm);\n\n            if (! prop.ok ())\n              error (\"no such method or property '%s'\", nm.c_str ());\n\n            if (! prop.is_constant ())\n              error (\"property '%s' is not constant\", nm.c_str ());\n\n            retval(0) = prop.get_value (true, \"meta.class\");\n          }\n      }\n      break;\n\n    default:\n      error (\"invalid meta.class indexing\");\n      break;\n    }\n\n  if (type.length () > skip && idx.size () > skip && ! retval.empty ())\n    retval = retval(0).next_subsref (nargout, type, idx, skip);\n\n  return retval;\n}\n\nvoid\ncdef_class::cdef_class_rep::meta_release ()\n{\n  cdef_manager& cdm = __get_cdef_manager__ ();\n\n  cdm.unregister_class (wrap ());\n}\n\nvoid\ncdef_class::cdef_class_rep::initialize_object (cdef_object& obj)\n{\n  // Populate the object with default property values\n\n  std::list<cdef_class> super_classes\n    = lookup_classes (get (\"SuperClasses\").cell_value ());\n\n  for (auto& cls : super_classes)\n    cls.initialize_object (obj);\n\n  for (const auto& pname_prop : m_property_map)\n    {\n      if (! pname_prop.second.get (\"Dependent\").bool_value ())\n        {\n          octave_value pvalue = pname_prop.second.get (\"DefaultValue\");\n\n          if (pvalue.is_defined ())\n            obj.put (pname_prop.first, pvalue);\n          else\n            obj.put (pname_prop.first, octave_value (Matrix ()));\n        }\n    }\n\n  m_count++;\n  obj.mark_for_construction (cdef_class (this));\n}\n\noctave_value_list\ncdef_class::cdef_class_rep::run_constructor (cdef_object& obj,\n    const octave_value_list& args,\n    const int nargout,\n    bool default_initialize)\n{\n  octave_value_list retval;\n\n  if (! default_initialize)\n    {\n      octave_value_list empty_args;\n\n      for (const auto& cls : m_implicit_ctor_list)\n        {\n          cdef_class supcls = lookup_class (cls);\n\n          supcls.run_constructor (obj, empty_args);\n        }\n\n      std::string cls_name = get_name ();\n      std::string ctor_name = get_base_name (cls_name);\n\n      cdef_method ctor = find_method (ctor_name);\n\n      if (ctor.ok ())\n        {\n          octave_value_list ctor_args (args);\n\n          ctor_args.prepend (to_ov (obj));\n          retval = ctor.execute (ctor_args, nargout, true, \"constructor\");\n\n          if (retval.length () < 1)\n            error (\"%s: invalid number of output arguments for classdef constructor\",\n                   ctor_name.c_str ());\n\n          obj = to_cdef (retval(0));\n        }\n    }\n\n  obj.mark_as_constructed (wrap ());\n\n  if (retval.empty ())\n    retval.resize (1);\n\n  retval(0) = to_ov (obj);\n\n  return retval;\n}\n\noctave_value\ncdef_class::cdef_class_rep::get_method (const std::string& name) const\n{\n  auto p = m_method_map.find (name);\n\n  if (p == m_method_map.end ())\n    return octave_value ();\n\n  return p->second.get_function ();\n}\n\noctave_value\ncdef_class::cdef_class_rep::get_method (int line) const\n{\n  octave_value closest_match;\n  int closest_match_end_line = std::numeric_limits<int>::max ();\n  // Since we have a dynamic cast, performance could be an issue if this is\n  // called from a critical path.  If performance is an issue, we can cache\n  // an ordered version of the method map\n  for (auto i = m_method_map.cbegin (); i != m_method_map.cend (); ++i)\n    {\n      const octave_value& fcn = i->second.get_function ();\n      octave_user_code *user_code = fcn.user_code_value ();\n\n      if (! user_code)\n        continue;\n\n      octave_user_function *pfcn\n        = dynamic_cast<octave_user_function *> (user_code);\n\n      if (! pfcn)\n        continue;\n\n      octave::filepos end_pos = pfcn->end_pos ();\n\n      int end_line = end_pos.line ();\n\n      if (line <= end_line && end_line <= closest_match_end_line\n          && pfcn->is_defined () && pfcn->is_user_code ())\n        {\n          closest_match = fcn;\n          closest_match_end_line = end_line;\n        }\n    }\n\n  // repeat the same for set and get methods of properties\n  for (auto i = m_property_map.cbegin (); i != m_property_map.cend (); ++i)\n    {\n      const octave_value& get_meth = i->second.get (\"GetMethod\");\n      if (get_meth.is_function_handle ())\n        {\n          octave_user_function *pfcn\n            = get_meth.user_function_value ();\n\n          if (! pfcn)\n            continue;\n\n          octave::filepos end_pos = pfcn->end_pos ();\n\n          int end_line = end_pos.line ();\n\n          if (line <= end_line && end_line <= closest_match_end_line\n              && pfcn->is_defined () && pfcn->is_user_code ())\n            {\n              closest_match = get_meth;\n              closest_match_end_line = end_line;\n            }\n        }\n\n      const octave_value& set_meth = i->second.get (\"SetMethod\");\n      if (set_meth.is_function_handle ())\n        {\n          octave_user_function *pfcn\n            = set_meth.user_function_value ();\n\n          if (! pfcn)\n            continue;\n\n          octave::filepos end_pos = pfcn->end_pos ();\n\n          int end_line = end_pos.line ();\n\n          if (line <= end_line && end_line <= closest_match_end_line\n              && pfcn->is_defined () && pfcn->is_user_code ())\n            {\n              closest_match = set_meth;\n              closest_match_end_line = end_line;\n            }\n        }\n    }\n\n  return closest_match;\n}\n\noctave_value\ncdef_class::cdef_class_rep::construct (const octave_value_list& args,\n                                       const bool default_initialize)\n{\n  octave_value_list retval = construct_object (args, 1, default_initialize);\n\n  return retval(0);\n}\n\noctave_value_list\ncdef_class::cdef_class_rep::construct_object (const octave_value_list& args,\n                                              const int nargout,\n                                              const bool default_initialize)\n{\n  if (is_abstract ())\n    error (\"cannot instantiate object for abstract class '%s'\",\n           get_name ().c_str ());\n\n  cdef_object obj;\n  octave_value_list retval (std::max (nargout, 1));\n\n  if (is_meta_class ())\n    {\n      // This code path is only used to create empty meta objects\n      // as filler for the empty values within a meta object array.\n\n      cdef_class this_cls = wrap ();\n\n      static cdef_object empty_class;\n\n      cdef_manager& cdm = __get_cdef_manager__ ();\n\n      if (this_cls == cdm.meta_class ())\n        {\n          if (! empty_class.ok ())\n            empty_class = cdm.make_class (\"\", std::list<cdef_class> ());\n          obj = empty_class;\n        }\n      else if (this_cls == cdm.meta_property ())\n        {\n          static cdef_property empty_property;\n\n          if (! empty_class.ok ())\n            empty_class = cdm.make_class (\"\", std::list<cdef_class> ());\n          if (! empty_property.ok ())\n            empty_property = cdm.make_property (empty_class, \"\");\n          obj = empty_property;\n        }\n      else if (this_cls == cdm.meta_method ())\n        {\n          static cdef_method empty_method;\n\n          if (! empty_class.ok ())\n            empty_class = cdm.make_class (\"\", std::list<cdef_class> ());\n          if (! empty_method.ok ())\n            empty_method = cdm.make_method (empty_class, \"\", octave_value ());\n          obj = empty_method;\n        }\n      else if (this_cls == cdm.meta_package ())\n        {\n          static cdef_package empty_package;\n\n          if (! empty_package.ok ())\n            empty_package = cdm.make_package (\"\");\n          obj = empty_package;\n        }\n      else\n        error (\"expecting meta class, property, method, or package in cdef_class::cdef_class_rep::construct_object - please report this bug\");\n\n      retval(0) = to_ov (obj);\n    }\n  else\n    {\n      if (is_handle_class ())\n        obj = cdef_object (new handle_cdef_object ());\n      else\n        obj = cdef_object (new value_cdef_object ());\n      obj.set_class (wrap ());\n\n      initialize_object (obj);\n\n      retval = run_constructor (obj, args, nargout, default_initialize);\n    }\n\n  return retval;\n}\n\nstatic octave_value\ncompute_attribute_value (tree_evaluator& tw,\n                         tree_classdef_attribute *t)\n{\n  tree_expression *expr = t->expression ();\n\n  if (expr)\n    {\n      if (expr->is_identifier ())\n        {\n          std::string s = expr->name ();\n\n          if (s == \"public\")\n            return std::string (\"public\");\n          else if (s == \"protected\")\n            return std::string (\"protected\");\n          else if (s == \"private\")\n            return std::string (\"private\");\n        }\n\n      return expr->evaluate (tw);\n    }\n  else\n    return octave_value (true);\n}\n\ntemplate <typename T>\nstatic std::string\nattribute_value_to_string (T *t, octave_value v)\n{\n  if (v.is_string ())\n    return v.string_value ();\n  else if (t->expression ())\n    return t->expression ()->original_text ();\n  else\n    return \"true\";\n}\n\ncdef_class\ncdef_class::make_meta_class (interpreter& interp,\n                             tree_classdef *t, bool is_at_folder)\n{\n  cdef_class retval;\n\n  // Class creation\n\n  std::string class_name = t->ident ()->name ();\n  std::string full_class_name = class_name;\n  if (! t->package_name ().empty ())\n    full_class_name = t->package_name () + '.' + full_class_name;\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n  std::cerr << \"class: \" << full_class_name << std::endl;\n#endif\n\n  // Push a dummy scope frame on the call stack that corresponds to\n  // the scope that was used when parsing classdef object.  Without\n  // this, we may pick up stray values from the current scope when\n  // evaluating expressions found in things like attribute lists.\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  tw.push_dummy_scope (full_class_name);\n  unwind_action pop_scope (&tree_evaluator::pop_scope, &tw);\n\n  std::list<cdef_class> slist;\n\n  if (t->superclass_list ())\n    {\n      for (auto& scls : (*t->superclass_list ()))\n        {\n          std::string sclass_name = (scls)->class_name ();\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n          std::cerr << \"superclass: \" << sclass_name << std::endl;\n#endif\n\n          cdef_class sclass = lookup_class (sclass_name);\n\n          if (sclass.get (\"Sealed\").bool_value ())\n            error (\"'%s' cannot inherit from '%s', because it is sealed\",\n                   full_class_name.c_str (), sclass_name.c_str ());\n\n          slist.push_back (sclass);\n        }\n    }\n\n  cdef_manager& cdm = __get_cdef_manager__ ();\n\n  retval = cdm.make_class (full_class_name, slist);\n\n  retval.doc_string (t->doc_string ());\n  retval.file_name (t->file_name ());\n\n  // Package owning this class\n\n  if (! t->package_name ().empty ())\n    {\n      cdef_package pack = cdm.find_package (t->package_name ());\n\n      if (pack.ok ())\n        retval.put (\"ContainingPackage\", to_ov (pack));\n    }\n\n  // FIXME: instead of attaching attributes here, pass them to\n  // cdef_manager::make_method.  The classdef manager contains a meta\n  // object with a list of all valid properties that can be used to\n  // validate the attribute list (see bug #60593).\n\n  // Class attributes\n\n  if (t->attribute_list ())\n    {\n      for (const auto& attr : (*t->attribute_list ()))\n        {\n          std::string aname = attr->ident ()->name ();\n          octave_value avalue = compute_attribute_value (tw, attr);\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n          std::cerr << \"class attribute: \" << aname << \" = \"\n                    << attribute_value_to_string (attr, avalue) << std::endl;\n#endif\n\n          retval.put (aname, avalue);\n        }\n    }\n\n  tree_classdef_body *b = t->body ();\n\n  if (b)\n    {\n      // Keep track of the get/set accessor methods.  They will be used\n      // later on when creating properties.\n\n      std::map<std::string, octave_value> get_methods;\n      std::map<std::string, octave_value> set_methods;\n\n      // Method blocks\n\n      std::list<tree_classdef_methods_block *> mb_list = b->method_list ();\n\n      load_path& lp = interp.get_load_path ();\n\n      for (auto& mb_p : mb_list)\n        {\n          std::map<std::string, octave_value> amap;\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n          std::cerr << \"method block\" << std::endl;\n#endif\n\n          // Method attributes\n\n          if (mb_p->attribute_list ())\n            {\n              for (auto& attr_p : *mb_p->attribute_list ())\n                {\n                  std::string aname = attr_p->ident ()->name ();\n                  octave_value avalue = compute_attribute_value (tw, attr_p);\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n                  std::cerr << \"method attribute: \" << aname << \" = \"\n                            << attribute_value_to_string (attr_p, avalue)\n                            << std::endl;\n#endif\n\n                  amap[aname] = avalue;\n                }\n            }\n\n          // Methods\n\n          if (mb_p->element_list ())\n            {\n              for (auto& mtd : *mb_p->element_list ())\n                {\n                  std::string mname = mtd.function_value ()->name ();\n                  std::string mprefix = mname.substr (0, 4);\n\n                  if (mprefix == \"get.\")\n                    get_methods[mname.substr (4)]\n                      = make_fcn_handle (mtd, mname, full_class_name);\n                  else if (mprefix == \"set.\")\n                    set_methods[mname.substr (4)]\n                      = make_fcn_handle (mtd, mname, full_class_name);\n                  else\n                    {\n                      cdef_method meth = cdm.make_method (retval, mname, mtd);\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n                      std::cerr << (mname == class_name ? \"constructor\"\n                                                        : \"method\")\n                                << \": \" << mname << std::endl;\n#endif\n\n                      // FIXME: instead of attaching attributes here,\n                      // pass them to cdef_manager::make_method.  The\n                      // classdef manager contains a meta object with\n                      // a list of all valid properties that can be\n                      // used to validate the attribute list (see bug\n                      // #60593).\n\n                      for (auto& attrnm_val : amap)\n                        meth.put (attrnm_val.first, attrnm_val.second);\n\n                      retval.install_method (meth);\n                    }\n                }\n            }\n        }\n\n      if (is_at_folder)\n        {\n          // Look for all external methods visible on octave path at the\n          // time of loading of the class.\n          //\n          // FIXME: This is an \"extension\" to Matlab behavior, which only\n          // looks in the @-folder containing the original classdef file.\n          // However, this is easier to implement it that way at the moment.\n\n          std::list<std::string> external_methods\n            = lp.methods (full_class_name);\n\n          for (const auto& mtdnm : external_methods)\n            {\n              // FIXME: should we issue a warning if the method is already\n              // defined in the classdef file?\n\n              if (mtdnm != class_name\n                  && ! retval.find_method (mtdnm, true).ok ())\n                {\n                  // Create a dummy method that is used until the actual\n                  // method is loaded.\n                  octave_user_function *fcn = new octave_user_function ();\n\n                  fcn->stash_function_name (mtdnm);\n\n                  cdef_method meth\n                    = cdm.make_method (retval, mtdnm, octave_value (fcn));\n\n                  retval.install_method (meth);\n                }\n            }\n        }\n\n      // Property blocks\n\n      // FIXME: default property expression should be able to call static\n      //        methods of the class being constructed.  A restricted\n      //        CLASSNAME symbol should be added to the scope before\n      //        evaluating default value expressions.\n\n      std::list<tree_classdef_properties_block *> pb_list\n        = b->property_list ();\n\n      for (auto& pb_p : pb_list)\n        {\n          std::map<std::string, octave_value> amap;\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n          std::cerr << \"property block\" << std::endl;\n#endif\n\n          // Property attributes\n\n          if (pb_p->attribute_list ())\n            {\n              for (auto& attr_p : *pb_p->attribute_list ())\n                {\n                  std::string aname = attr_p->ident ()->name ();\n                  octave_value avalue = compute_attribute_value (tw, attr_p);\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n                  std::cerr << \"property attribute: \" << aname << \" = \"\n                            << attribute_value_to_string (attr_p, avalue)\n                            << std::endl;\n#endif\n\n                  if (aname == \"Access\")\n                    {\n                      amap[\"GetAccess\"] = avalue;\n                      amap[\"SetAccess\"] = avalue;\n                    }\n                  else\n                    amap[aname] = avalue;\n                }\n            }\n\n          // Properties\n\n          if (pb_p->element_list ())\n            {\n              for (auto& prop_p : *pb_p->element_list ())\n                {\n                  std::string prop_name = prop_p->ident ()->name ();\n\n                  cdef_property prop = cdm.make_property (retval, prop_name);\n\n                  prop.doc_string (prop_p->doc_string ());\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n                  std::cerr << \"property: \" << prop_p->ident ()->name ()\n                            << std::endl;\n#endif\n\n                  tree_expression *expr = prop_p->expression ();\n                  if (expr)\n                    {\n                      octave_value pvalue = expr->evaluate (tw);\n\n#if OCTAVE_CDEF_CLASS_DEBUG\n                      std::cerr << \"property default: \"\n                                << attribute_value_to_string (prop_p, pvalue)\n                                << std::endl;\n#endif\n\n                      prop.put (\"DefaultValue\", pvalue);\n                    }\n\n                  // FIXME: instead of attaching attributes here, pass\n                  // them to cdef_manager::make_property.  The\n                  // classdef manager contains a meta object with a\n                  // list of all valid properties that can be used to\n                  // validate the attribute list (see bug #60593).\n\n                  // Install property attributes.  This is done before\n                  // assigning the property accessors so we can do validation\n                  // by using cdef_property methods.\n\n                  for (auto& attrnm_val : amap)\n                    prop.put (attrnm_val.first, attrnm_val.second);\n\n                  // Install property access methods, if any.  Remove the\n                  // accessor methods from the temporary storage map, so we\n                  // can detect which ones are invalid and do not correspond\n                  // to a defined property.\n\n                  auto git = get_methods.find (prop_name);\n\n                  if (git != get_methods.end ())\n                    {\n                      make_function_of_class (retval, git->second);\n                      prop.put (\"GetMethod\", git->second);\n                      get_methods.erase (git);\n                    }\n\n                  auto sit = set_methods.find (prop_name);\n\n                  if (sit != set_methods.end ())\n                    {\n                      make_function_of_class (retval, sit->second);\n                      prop.put (\"SetMethod\", sit->second);\n                      set_methods.erase (sit);\n                    }\n\n                  retval.install_property (prop);\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\noctave_value\ncdef_class::get_method_function (const std::string& /* nm */)\n{\n  return octave_value (new octave_classdef_meta (*this));\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/cdef-class.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cdef_class_h)\n#define octave_cdef_class_h 1\n\n#include \"octave-config.h\"\n\n#include <map>\n#include <set>\n#include <string>\n#include <utility>\n\n#include \"oct-refcount.h\"\n\n#include \"cdef-fwd.h\"\n#include \"cdef-method.h\"\n#include \"cdef-object.h\"\n#include \"cdef-package.h\"\n#include \"cdef-property.h\"\n#include \"error.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\nclass tree_classdef;\n\n// When we want to preserve the order in which properties were first defined,\n// we index them with a std::pair key made of:\n// - first, their rank in the property list;\n// - and second, their name.\ntypedef std::pair<unsigned int, std::string> property_key;\n\nclass OCTINTERP_API cdef_class : public cdef_meta_object\n{\nprivate:\n\n  class cdef_class_rep : public cdef_meta_object_rep\n  {\n  public:\n    cdef_class_rep ()\n      : cdef_meta_object_rep (), m_member_count (0), m_handle_class (false),\n        m_meta (false)\n    { }\n\n    OCTINTERP_API cdef_class_rep (const std::list<cdef_class>& superclasses);\n\n    cdef_class_rep& operator = (const cdef_class_rep&) = delete;\n\n    ~cdef_class_rep () = default;\n\n    cdef_object_rep * copy () const { return new cdef_class_rep (*this); }\n\n    bool is_class () const { return true; }\n\n    std::string get_name () const\n    { return get (\"Name\").string_value (); }\n\n    void set_name (const std::string& nm) { put (\"Name\", nm); }\n\n    bool is_abstract () const { return get (\"Abstract\").bool_value (); }\n\n    bool is_sealed () const { return get (\"Sealed\").bool_value (); }\n\n    OCTINTERP_API cdef_method\n    find_method (const std::string& nm, bool local = false);\n\n    OCTINTERP_API void\n    install_method (const cdef_method& meth);\n\n    OCTINTERP_API Cell\n    get_methods (bool include_ctor);\n\n    OCTINTERP_API std::map<std::string, cdef_method>\n    get_method_map (bool only_inherited, bool include_ctor);\n\n    OCTINTERP_API cdef_property find_property (const std::string& nm);\n\n    OCTINTERP_API void install_property (const cdef_property& prop);\n\n    OCTINTERP_API Cell get_properties (int mode);\n\n    OCTINTERP_API std::map<property_key, cdef_property>\n    get_property_map (int mode);\n\n    OCTINTERP_API string_vector get_names ();\n\n    void set_directory (const std::string& dir) { m_directory = dir; }\n\n    std::string get_directory () const { return m_directory; }\n\n    OCTINTERP_API void delete_object (const cdef_object& obj);\n\n    OCTINTERP_API octave_value_list\n    meta_subsref (const std::string& type,\n                  const std::list<octave_value_list>& idx, int nargout);\n\n    OCTINTERP_API void meta_release ();\n\n    bool meta_accepts_postfix_index (char type) const\n    {\n      return (type == '(' || type == '.');\n    }\n\n    OCTINTERP_API octave_value get_method (const std::string& name) const;\n\n    OCTINTERP_API octave_value get_method (int line) const;\n\n    OCTINTERP_API octave_value\n    construct (const octave_value_list& args,\n               const bool default_initialize = false);\n\n    OCTINTERP_API octave_value_list\n    construct_object (const octave_value_list& args,\n                      const int nargout = 1,\n                      const bool default_initialize = false);\n\n    OCTINTERP_API void initialize_object (cdef_object& obj);\n\n    OCTINTERP_API octave_value_list\n    run_constructor (cdef_object& obj, const octave_value_list& args,\n                     const int nargout = 1,\n                     bool default_initialize = false);\n\n    void mark_as_handle_class () { m_handle_class = true; }\n\n    bool is_handle_class () const { return m_handle_class; }\n\n    octave_idx_type static_count () const { return m_member_count; }\n\n    void destroy ()\n    {\n      if (m_member_count)\n        {\n          m_count++;\n          cdef_class lock (this);\n\n          m_member_count = 0;\n          m_method_map.clear ();\n          m_property_map.clear ();\n          m_property_rank_map.clear ();\n        }\n      else\n        delete this;\n    }\n\n    void mark_as_meta_class () { m_meta = true; }\n\n    bool is_meta_class () const { return m_meta; }\n\n    void file_name (const std::string& nm) { m_file_name = nm; }\n\n    std::string file_name () const { return m_file_name; }\n\n  private:\n\n    OCTINTERP_API void load_all_methods ();\n\n    OCTINTERP_API void find_names (std::set<std::string>& names, bool all);\n\n    OCTINTERP_API void\n    find_properties (std::map<property_key, cdef_property>& props,\n                     int mode = 0);\n\n    OCTINTERP_API void\n    find_properties_aux (std::map<property_key, cdef_property>& props,\n                         std::set<std::string>& prop_names,\n                         int mode = 0);\n\n    OCTINTERP_API void\n    find_methods (std::map<std::string, cdef_method>& meths,\n                  bool only_inherited, bool include_ctor = false);\n\n    cdef_class wrap ()\n    {\n      m_count++;\n      return cdef_class (this);\n    }\n\n    // The @-directory were this class is loaded from.\n    // (not used yet)\n\n    std::string m_directory;\n\n    std::string m_file_name;\n\n    // The methods defined by this class.\n\n    std::map<std::string, cdef_method> m_method_map;\n\n    // The properties defined by this class.\n\n    std::map<std::string, cdef_property> m_property_map;\n    std::map<std::string, unsigned int> m_property_rank_map;\n\n    // The number of members in this class (methods, properties...)\n\n    octave_idx_type m_member_count;\n\n    // TRUE if this class is a handle class.  A class is a handle\n    // class when the abstract \"handle\" class is one of its superclasses.\n\n    bool m_handle_class;\n\n    // The list of super-class constructors that are called implicitly by the\n    // classdef engine when creating an object.  These constructors are not\n    // called explicitly by the class constructor.\n\n    std::list<cdef_class> m_implicit_ctor_list;\n\n    // TRUE if this class is a built-in meta class.\n\n    bool m_meta;\n\n    // Utility iterator typedefs.\n\n    typedef std::map<std::string, cdef_method>::iterator method_iterator;\n    typedef std::map<std::string, cdef_method>::const_iterator method_const_iterator;\n    typedef std::map<property_key, cdef_property>::iterator property_iterator;\n    typedef std::map<property_key, cdef_property>::const_iterator property_const_iterator;\n\n    cdef_class_rep (const cdef_class_rep& c) = default;\n  };\n\npublic:\n\n  // Create an invalid class object.\n\n  cdef_class () : cdef_meta_object () { }\n\n  cdef_class (const std::string& nm,\n              const std::list<cdef_class>& superclasses)\n    : cdef_meta_object (new cdef_class_rep (superclasses))\n  {\n    get_rep ()->set_name (nm);\n  }\n\n  cdef_class (const cdef_class& cls) : cdef_meta_object (cls) { }\n\n  cdef_class (const cdef_object& obj)\n    : cdef_meta_object (obj)\n  {\n    // This should never happen...\n    if (! is_class ())\n      error (\"internal error: invalid assignment from %s to meta.class object\",\n             class_name ().c_str ());\n  }\n\n  cdef_class& operator = (const cdef_class& cls)\n  {\n    cdef_object::operator = (cls);\n\n    return *this;\n  }\n\n  ~cdef_class () = default;\n\n  OCTINTERP_API cdef_method\n  find_method (const std::string& nm, bool local = false);\n\n  void install_method (const cdef_method& meth)\n  {\n    get_rep ()->install_method (meth);\n  }\n\n  Cell get_methods (bool include_ctor = false)\n  {\n    return get_rep ()->get_methods (include_ctor);\n  }\n\n  std::map<std::string, cdef_method>\n  get_method_map (bool only_inherited = false, bool include_ctor = false)\n  {\n    return get_rep ()->get_method_map (only_inherited, include_ctor);\n  }\n\n  OCTINTERP_API cdef_property find_property (const std::string& nm);\n\n  void install_property (const cdef_property& prop)\n  {\n    get_rep ()->install_property (prop);\n  }\n\n  Cell get_properties (int mode = property_normal)\n  {\n    return get_rep ()->get_properties (mode);\n  }\n\n  std::map<property_key, cdef_property>\n  get_property_map (int mode = property_normal)\n  {\n    return get_rep ()->get_property_map (mode);\n  }\n\n  string_vector get_names () { return get_rep ()->get_names (); }\n\n  bool is_abstract () const { return get_rep ()->is_abstract (); }\n\n  bool is_sealed () const { return get_rep ()->is_sealed (); }\n\n  void set_directory (const std::string& dir)\n  {\n    get_rep ()->set_directory (dir);\n  }\n\n  std::string get_directory () const\n  {\n    return get_rep ()->get_directory ();\n  }\n\n  std::string get_name () const { return get_rep ()->get_name (); }\n\n  bool is_builtin () const { return get_directory ().empty (); }\n\n  void delete_object (const cdef_object& obj)\n  {\n    get_rep ()->delete_object (obj);\n  }\n\n  //! Analyze the tree_classdef tree and transform it to a cdef_class\n  //!\n  //! <b>All attribute validation should occur here.</b>\n  //!\n  //! Classdef attribute values can be given in the form of\n  //! expressions.  These expressions must be evaluated before\n  //! assigning them as attribute values.  Evaluating them as they are\n  //! parsed causes trouble with possible recursion in the parser so we\n  //! do it here.  For example\n  //!\n  //! @code\n  //! classdef recursion_class\n  //!   methods (Access = ?recursion_class)\n  //!   endmethods\n  //! endclassdef\n  //! @endcode\n  //!\n  //! will fail because each attempt to compute the metaclass of\n  //! recursion_class will cause recursion_class to be parsed again.\n\n  static OCTINTERP_API cdef_class\n  make_meta_class (interpreter& interp, tree_classdef *t,\n                   bool is_at_folder = false);\n\n  octave_value get_method (const std::string& nm) const\n  {\n    return get_rep ()->get_method (nm);\n  }\n\n  octave_value get_method (int ln) const\n  {\n    return get_rep ()->get_method (ln);\n  }\n\n  OCTINTERP_API octave_value get_method_function (const std::string& nm);\n\n  octave_value get_constructor_function ()\n  {\n    return get_method_function (get_name ());\n  }\n\n  //! Wrapper for `construct_object` that returns only the constructed\n  //! object. Ignores all other constructor return parameters.\n  octave_value construct (const octave_value_list& args,\n                          const bool default_initialize = false)\n  {\n    return get_rep ()->construct (args, default_initialize);\n  }\n\n  //! The proper method to call for object construction.\n  //!\n  //! @return The first index slot in the octave_value_list contains the\n  //! constructed classdef object. All the other slots contain (possible)\n  //! extra constructor return outputs.\n  octave_value_list\n  construct_object (const octave_value_list& args, const int nargout = 1,\n                    const bool default_initialize = false)\n  {\n    return get_rep ()->construct_object (args, nargout, default_initialize);\n  }\n\n  void initialize_object (cdef_object& obj)\n  {\n    get_rep ()->initialize_object (obj);\n  }\n\n  //! The method to call to run a classdef's constructor.\n  //!\n  //! @param <obj> The classdef object being constructed is passed by\n  //! reference. If a derived classdef is calling a superclass constructor,\n  //! then the derived `cdef_object` is being passed in, and not a brand\n  //! new superclass `cdef_object`.\n  //!\n  //! @return The first slot in the `octave_value_list` is a copy of the\n  //! `cdef_object` being passed in.\n  octave_value_list\n  run_constructor (cdef_object& obj, const octave_value_list& args,\n                   int nargout = 1, bool default_initialize = false)\n  {\n    return get_rep ()->run_constructor (obj, args, nargout, default_initialize);\n  }\n\n  void mark_as_handle_class ()\n  {\n    get_rep ()->mark_as_handle_class ();\n  }\n\n  bool is_handle_class () const\n  {\n    return get_rep ()->is_handle_class ();\n  }\n\n  void mark_as_meta_class () { get_rep ()->mark_as_meta_class (); }\n\n  bool is_meta_class () const { return get_rep ()->is_meta_class (); }\n\n  void file_name (const std::string& nm) { get_rep ()->file_name (nm); }\n\n  std::string file_name () const { return get_rep ()->file_name (); }\n\npublic:\n\n  enum\n  {\n    property_normal,\n    property_inherited,\n    property_all\n  };\n\nprivate:\n\n  cdef_class_rep * get_rep ()\n  {\n    return dynamic_cast<cdef_class_rep *> (cdef_object::get_rep ());\n  }\n\n  const cdef_class_rep * get_rep () const\n  {\n    return dynamic_cast<const cdef_class_rep *> (cdef_object::get_rep ());\n  }\n\n  friend OCTINTERP_API bool operator == (const cdef_class&, const cdef_class&);\n  friend OCTINTERP_API bool operator != (const cdef_class&, const cdef_class&);\n  friend OCTINTERP_API bool operator < (const cdef_class&, const cdef_class&);\n\n  friend void install_classdef (octave::interpreter& interp);\n};\n\ninline bool\noperator == (const cdef_class& clsa, const cdef_class& clsb)\n{\n  // FIXME: is this really the right way to check class equality?\n\n  return (clsa.get_rep () == clsb.get_rep ());\n}\n\ninline bool\noperator != (const cdef_class& clsa, const cdef_class& clsb)\n{\n  return ! (clsa == clsb);\n}\n\n// This is only to be able to use cdef_class as map keys.\n\ninline bool\noperator < (const cdef_class& clsa, const cdef_class& clsb)\n{\n  return clsa.get_rep () < clsb.get_rep ();\n}\n\ninline cdef_method\ncdef_class::find_method (const std::string& nm, bool local)\n{\n  return get_rep ()->find_method (nm, local);\n}\n\ninline cdef_property\ncdef_class::find_property (const std::string& nm)\n{\n  return get_rep ()->find_property (nm);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/cdef-fwd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cdef_fwd_h)\n#define octave_cdef_fwd_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API cdef_class;\nclass OCTINTERP_API cdef_object;\nclass OCTINTERP_API cdef_package;\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/cdef-manager.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"cdef-manager.h\"\n#include \"cdef-utils.h\"\n#include \"interpreter.h\"\n#include \"ov-classdef.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic octave_value\nmake_fcn_handle (octave_builtin::fcn ff, const std::string& nm)\n{\n  octave_value fcn (new octave_builtin (ff, nm));\n\n  return octave_value (new octave_fcn_handle (fcn));\n}\n\nstatic octave_value_list\nclass_get_properties (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval;\n\n  if (args.length () == 1 && args(0).type_name () == \"object\")\n    {\n      cdef_class cls (to_cdef (args(0)));\n\n      retval(0) = cls.get_properties ();\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\nclass_get_methods (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval;\n\n  if (args.length () == 1 && args(0).type_name () == \"object\")\n    {\n      cdef_class cls (to_cdef (args(0)));\n\n      retval(0) = cls.get_methods ();\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\nclass_get_superclasses (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval;\n\n  if (args.length () == 1 && args(0).type_name () == \"object\"\n      && args(0).class_name () == \"meta.class\")\n    {\n      cdef_class cls (to_cdef (args(0)));\n\n      Cell classes = cls.get (\"SuperClasses\").cell_value ();\n\n      retval(0) = to_ov (lookup_classes (classes));\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\nclass_get_inferiorclasses (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval;\n\n  if (args.length () == 1 && args(0).type_name () == \"object\"\n      && args(0).class_name () == \"meta.class\")\n    {\n      cdef_class cls (to_cdef (args(0)));\n\n      Cell classes = cls.get (\"InferiorClasses\").cell_value ();\n\n      retval(0) = to_ov (lookup_classes (classes));\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\nclass_fromName (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval;\n\n  if (args.length () != 1)\n    error (\"fromName: invalid number of parameters\");\n\n  std::string name = args(0).xstring_value (\"fromName: CLASS_NAME must be a string\");\n\n  retval(0) = to_ov (lookup_class (name, false));\n\n  return retval;\n}\n\nstatic octave_value_list\nclass_fevalStatic (const octave_value_list& args, int nargout)\n{\n  if (args.length () <= 1 || args(0).type_name () != \"object\")\n    error (\"fevalStatic: first argument must be a meta.class object\");\n\n  cdef_class cls (to_cdef (args(0)));\n\n  std::string meth_name = args(1).xstring_value (\"fevalStatic: method name must be a string\");\n\n  cdef_method meth = cls.find_method (meth_name);\n\n  if (! meth.ok ())\n    error (\"fevalStatic: method not found: %s\", meth_name.c_str ());\n\n  if (! meth.is_static ())\n    error (\"fevalStatic: method '%s' is not static\", meth_name.c_str ());\n\n  return meth.execute (args.splice (0, 2), nargout, true, \"fevalStatic\");\n}\n\nstatic octave_value_list\nclass_getConstant (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval;\n\n  if (args.length () != 2 || args(0).type_name () != \"object\"\n      || args(0).class_name () != \"meta.class\")\n    error (\"getConstant: first argument must be a meta.class object\");\n\n  cdef_class cls = to_cdef (args(0));\n\n  std::string prop_name = args(1).xstring_value (\"getConstant: property name must be a string\");\n\n  cdef_property prop = cls.find_property (prop_name);\n\n  if (! prop.ok ())\n    error (\"getConstant: property not found: %s\",\n           prop_name.c_str ());\n\n  if (! prop.is_constant ())\n    error (\"getConstant: property '%s' is not constant\",\n           prop_name.c_str ());\n\n  retval(0) = prop.get_value (true, \"getConstant\");\n\n  return retval;\n}\n\n#define META_CLASS_CMP(OP, CLSA, CLSB, FCN)                             \\\n  static octave_value_list                                              \\\n  class_ ## OP (const octave_value_list& args, int /* nargout */)       \\\n  {                                                                     \\\n    octave_value_list retval;                                           \\\n                                                                        \\\n    if (args.length () != 2                                             \\\n        || args(0).type_name () != \"object\"                             \\\n        || args(1).type_name () != \"object\"                             \\\n        || args(0).class_name () != \"meta.class\"                        \\\n        || args(1).class_name () != \"meta.class\")                       \\\n      error (#OP \": invalid arguments\");                                \\\n                                                                        \\\n    cdef_class clsa = to_cdef (args(0));                                \\\n                                                                        \\\n    cdef_class clsb = to_cdef (args(1));                                \\\n                                                                        \\\n    retval(0) = FCN (CLSA, CLSB);                                       \\\n                                                                        \\\n    return retval;                                                      \\\n  }\n\nMETA_CLASS_CMP (lt, clsb, clsa, is_strict_superclass)\nMETA_CLASS_CMP (le, clsb, clsa, is_superclass)\nMETA_CLASS_CMP (gt, clsa, clsb, is_strict_superclass)\nMETA_CLASS_CMP (ge, clsa, clsb, is_superclass)\nMETA_CLASS_CMP (eq, clsa, clsb, operator==)\nMETA_CLASS_CMP (ne, clsa, clsb, operator!=)\n\nstatic octave_value_list\nproperty_get_defaultvalue (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval;\n\n  if (args.length () == 1 && args(0).type_name () == \"object\")\n    {\n      cdef_property prop (to_cdef (args(0)));\n\n      retval(0) = prop.get (\"DefaultValue\");\n\n      if (! retval(0).is_defined ())\n        error_with_id (\"Octave:class:NoDefaultDefined\",\n                       \"no default value for property '%s'\",\n                       prop.get_name ().c_str ());\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\nhandle_delete (const octave_value_list& /* args */, int /* nargout */)\n{\n  octave_value_list retval;\n\n  // FIXME: implement this.  Wait, what is this supposed to do?\n\n  return retval;\n}\n\nstatic octave_value_list\npackage_get_classes (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval (1, Matrix ());\n\n  if (args.length () == 1 && args(0).type_name () == \"object\"\n      && args(0).class_name () == \"meta.package\")\n    {\n      cdef_package pack (to_cdef (args(0)));\n\n      retval(0) = pack.get_classes ();\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\npackage_get_functions (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval (1, Matrix ());\n\n  if (args.length () == 0 && args(0).type_name () == \"object\"\n      && args(0).class_name () == \"meta.package\")\n    {\n      cdef_package pack (to_cdef (args(0)));\n\n      retval(0) = pack.get_functions ();\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\npackage_get_packages (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval (1, Matrix ());\n\n  if (args.length () == 0 && args(0).type_name () == \"object\"\n      && args(0).class_name () == \"meta.package\")\n    {\n      cdef_package pack (to_cdef (args(0)));\n\n      retval(0) = pack.get_packages ();\n    }\n\n  return retval;\n}\n\nstatic octave_value_list\npackage_getAllPackages (interpreter& interp,\n                        const octave_value_list& /* args */,\n                        int /* nargout */)\n{\n  std::map<std::string, cdef_package> toplevel_packages;\n\n  load_path& lp = interp.get_load_path ();\n\n  std::list<std::string> names = lp.get_all_package_names ();\n\n  cdef_manager& cdm = interp.get_cdef_manager ();\n\n  toplevel_packages[\"meta\"] = cdm.find_package (\"meta\", false, false);\n\n  for (const auto& nm : names)\n    toplevel_packages[nm] = cdm.find_package (nm, false, true);\n\n  Cell c (toplevel_packages.size (), 1);\n\n  int i = 0;\n\n  for (const auto& nm_pkg : toplevel_packages)\n    c(i++, 0) = to_ov (nm_pkg.second);\n\n  return octave_value_list (octave_value (c));\n}\n\nstatic octave_value_list\npackage_fromName (const octave_value_list& args, int /* nargout */)\n{\n  octave_value_list retval;\n\n  if (args.length () != 1)\n    error (\"fromName: invalid number of parameters\");\n\n  std::string name = args(0).xstring_value (\"fromName: PACKAGE_NAME must be a string\");\n\n  retval(0) = to_ov (lookup_package (name, false));\n\n  return retval;\n}\n\ncdef_manager::cdef_manager (interpreter& interp)\n  : m_interpreter (interp), m_all_classes (), m_all_packages (),\n    m_meta_class (), m_meta_property (), m_meta_method (),\n    m_meta_package (), m_meta ()\n{\n  type_info& ti = m_interpreter.get_type_info ();\n\n  octave_classdef::register_type (ti);\n\n  // bootstrap\n  cdef_class tmp_handle = make_class (\"handle\");\n\n  m_meta_class = make_meta_class (\"meta.class\", tmp_handle);\n\n  tmp_handle.set_class (m_meta_class);\n  m_meta_class.set_class (m_meta_class);\n\n  // meta classes\n  m_meta_property = make_meta_class (\"meta.property\", tmp_handle);\n\n  m_meta_method = make_meta_class (\"meta.method\", tmp_handle);\n\n  m_meta_package = make_meta_class (\"meta.package\", tmp_handle);\n\n  cdef_class tmp_meta_event\n    = make_meta_class (\"meta.event\", tmp_handle);\n\n  cdef_class tmp_meta_dynproperty\n    = make_meta_class (\"meta.dynamicproperty\", tmp_handle);\n\n  // meta.class properties\n  m_meta_class.install_property\n  (make_attribute (m_meta_class, \"Abstract\"));\n\n  m_meta_class.install_property\n  (make_attribute (m_meta_class, \"ConstructOnLoad\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"ContainingPackage\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"Description\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"DetailedDescription\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"Events\"));\n\n  m_meta_class.install_property\n  (make_attribute (m_meta_class, \"HandleCompatible\"));\n\n  m_meta_class.install_property\n  (make_attribute (m_meta_class, \"Hidden\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"InferiorClasses\",\n                  make_fcn_handle (class_get_inferiorclasses,\n                                   \"meta.class>get.InferiorClasses\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"Methods\",\n                  make_fcn_handle (class_get_methods,\n                                   \"meta.class>get.Methods\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"MethodList\",\n                  make_fcn_handle (class_get_methods,\n                                   \"meta.class>get.MethodList\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_class.install_property (make_attribute (m_meta_class, \"Name\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"Properties\",\n                  make_fcn_handle (class_get_properties,\n                                   \"meta.class>get.Properties\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"PropertyList\",\n                  make_fcn_handle (class_get_properties,\n                                   \"meta.class>get.PropertyList\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_class.install_property (make_attribute (m_meta_class, \"Sealed\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"SuperClasses\",\n                  make_fcn_handle (class_get_superclasses,\n                                   \"meta.class>get.SuperClasses\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"SuperclassList\",\n                  make_fcn_handle (class_get_superclasses,\n                                   \"meta.class>get.SuperclassList\"),\n                  \"public\", Matrix (), \"private\"));\n\n  // FIXME: Matlab supports this property under \"SuperclassList\".\n  //        Octave, however, has supported this under \"SuperClassList\".\n  //        Alias the property.  Remove in Octave version 8.1.\n  m_meta_class.install_property\n  (make_property (m_meta_class, \"SuperClassList\",\n                  make_fcn_handle (class_get_superclasses,\n                                   \"meta.class>get.SuperclassList\"),\n                  \"public\", Matrix (), \"private\"));\n\n  // meta.class methods\n  m_meta_class.install_method\n  (make_method (m_meta_class, \"fromName\", class_fromName, \"public\", true));\n\n  m_meta_class.install_method\n  (make_method (m_meta_class, \"fevalStatic\", class_fevalStatic, \"public\",\n                false));\n\n  m_meta_class.install_method\n  (make_method (m_meta_class, \"getConstant\", class_getConstant, \"public\",\n                false));\n\n  m_meta_class.install_method (make_method (m_meta_class, \"eq\", class_eq));\n  m_meta_class.install_method (make_method (m_meta_class, \"ne\", class_ne));\n  m_meta_class.install_method (make_method (m_meta_class, \"lt\", class_lt));\n  m_meta_class.install_method (make_method (m_meta_class, \"le\", class_le));\n  m_meta_class.install_method (make_method (m_meta_class, \"gt\", class_gt));\n  m_meta_class.install_method (make_method (m_meta_class, \"ge\", class_ge));\n\n  // meta.method properties\n  m_meta_method.install_property\n  (make_attribute (m_meta_method, \"Abstract\"));\n\n  m_meta_method.install_property\n  (make_attribute (m_meta_method, \"Access\"));\n\n  m_meta_method.install_property\n  (make_attribute (m_meta_method, \"DefiningClass\"));\n\n  m_meta_method.install_property\n  (make_attribute (m_meta_method, \"Description\"));\n\n  m_meta_method.install_property\n  (make_attribute (m_meta_method, \"DetailedDescription\"));\n\n  m_meta_method.install_property\n  (make_attribute (m_meta_method, \"Hidden\"));\n\n  m_meta_method.install_property\n  (make_attribute (m_meta_method, \"Name\"));\n\n  m_meta_method.install_property\n  (make_attribute (m_meta_method, \"Sealed\"));\n\n  m_meta_method.install_property\n  (make_attribute (m_meta_method, \"Static\"));\n\n  // meta.property properties\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"Name\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"Description\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"DetailedDescription\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"Abstract\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"Constant\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"GetAccess\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"SetAccess\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"Dependent\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"Transient\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"Hidden\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"GetObservable\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"SetObservable\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"GetMethod\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"SetMethod\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"DefiningClass\"));\n\n  m_meta_property.install_property\n  (make_property (m_meta_property, \"DefaultValue\",\n                  make_fcn_handle (property_get_defaultvalue,\n                                   \"meta.property>get.DefaultValue\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_property.install_property\n  (make_attribute (m_meta_property, \"HasDefault\"));\n\n  // meta.property events\n  // FIXME: add events\n\n  // handle methods\n\n  tmp_handle.install_method\n  (make_method (tmp_handle, \"delete\", handle_delete));\n\n  // meta.package properties\n\n  m_meta_package.install_property\n  (make_attribute (m_meta_package, \"Name\"));\n\n  m_meta_package.install_property\n  (make_property (m_meta_package, \"ContainingPackage\"));\n\n  m_meta_package.install_property\n  (make_property (m_meta_package, \"ClassList\",\n                  make_fcn_handle (package_get_classes,\n                                   \"meta.package>get.ClassList\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_package.install_property\n  (make_property (m_meta_package, \"Classes\",\n                  make_fcn_handle (package_get_classes,\n                                   \"meta.package>get.Classes\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_package.install_property\n  (make_property (m_meta_package, \"FunctionList\",\n                  make_fcn_handle (package_get_functions,\n                                   \"meta.package>get.FunctionList\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_package.install_property\n  (make_property (m_meta_package, \"Functions\",\n                  make_fcn_handle (package_get_functions,\n                                   \"meta.package>get.Functions\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_package.install_property\n  (make_property (m_meta_package, \"PackageList\",\n                  make_fcn_handle (package_get_packages,\n                                   \"meta.package>get.PackageList\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_package.install_property\n  (make_property (m_meta_package, \"Packages\",\n                  make_fcn_handle (package_get_packages,\n                                   \"meta.package>get.Packages\"),\n                  \"public\", Matrix (), \"private\"));\n\n  m_meta_package.install_method\n  (make_method (m_meta_package, \"fromName\", package_fromName,\n                \"public\", true));\n\n  m_meta_package.install_method\n  (make_method (m_meta_package, \"getAllPackages\", package_getAllPackages,\n                \"public\", true));\n\n  // create \"meta\" package\n  cdef_package package_meta\n    = m_meta\n      = make_package (\"meta\");\n\n  package_meta.install_class (m_meta_class, \"class\");\n  package_meta.install_class (m_meta_property, \"property\");\n  package_meta.install_class (m_meta_method, \"method\");\n  package_meta.install_class (m_meta_package, \"package\");\n  package_meta.install_class (tmp_meta_event, \"event\");\n  package_meta.install_class (tmp_meta_dynproperty, \"dynproperty\");\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  // install built-in classes into the symbol table\n  symtab.install_built_in_function\n  (\"meta.class\", m_meta_class.get_constructor_function ());\n\n  symtab.install_built_in_function\n  (\"meta.method\", m_meta_method.get_constructor_function ());\n\n  symtab.install_built_in_function\n  (\"meta.property\", m_meta_property.get_constructor_function ());\n\n  symtab.install_built_in_function\n  (\"meta.package\", m_meta_package.get_constructor_function ());\n\n  // FIXME: meta.event and meta.dynproperty are not implemented\n  //        and should not be installed into symbol table.\n\n  //  symtab.install_built_in_function\n  //    (\"meta.event\", tmp_meta_event.get_constructor_function ());\n\n  //  symtab.install_built_in_function\n  //    (\"meta.dynproperty\", tmp_meta_dynproperty.get_constructor_function ());\n}\n\ncdef_class\ncdef_manager::find_class (const std::string& name, bool error_if_not_found,\n                          bool load_if_not_found)\n{\n  auto it = m_all_classes.find (name);\n\n  if (it == m_all_classes.end ())\n    {\n      if (load_if_not_found)\n        {\n          octave_value ov_cls;\n\n          std::size_t pos = name.rfind ('.');\n\n          if (pos == std::string::npos)\n            ov_cls = m_interpreter.find (name);\n          else\n            {\n              std::string pack_name = name.substr (0, pos);\n\n              cdef_package pack = find_package (pack_name, false, true);\n\n              if (pack.ok ())\n                ov_cls = pack.find (name.substr (pos+1));\n            }\n\n          if (ov_cls.is_defined ())\n            it = m_all_classes.find (name);\n        }\n    }\n\n  if (it == m_all_classes.end ())\n    {\n      if (error_if_not_found)\n        error (\"class not found: %s\", name.c_str ());\n    }\n  else\n    {\n      cdef_class cls = it->second;\n\n      if (! cls.is_builtin ())\n        cls = lookup_class (cls);\n\n      if (cls.ok ())\n        return cls;\n      else\n        m_all_classes.erase (it);\n    }\n\n  return cdef_class ();\n}\n\noctave_value\ncdef_manager::find_method_symbol (const std::string& method_name,\n                                  const std::string& class_name)\n{\n  cdef_class cls = find_class (class_name, false, false);\n\n  if (cls.ok ())\n    {\n      cdef_method meth = cls.find_method (method_name);\n\n      if (meth.ok ())\n        return octave_value (new octave_classdef_meta (meth));\n    }\n\n  return octave_value ();\n}\n\ncdef_package\ncdef_manager::find_package (const std::string& name, bool error_if_not_found,\n                            bool load_if_not_found)\n{\n  cdef_package retval;\n\n  std::map<std::string, cdef_package>::const_iterator it\n    = m_all_packages.find (name);\n\n  if (it != m_all_packages.end ())\n    {\n      retval = it->second;\n\n      if (! retval.ok ())\n        error (\"invalid package '%s'\", name.c_str ());\n    }\n  else\n    {\n      load_path& lp = m_interpreter.get_load_path ();\n\n      if (load_if_not_found && lp.find_package (name))\n        {\n          std::size_t pos = name.rfind ('.');\n\n          if (pos == std::string::npos)\n            retval = make_package (name, \"\");\n          else\n            {\n              std::string parent_name = name.substr (0, pos);\n\n              retval = make_package (name, parent_name);\n            }\n        }\n      else if (error_if_not_found)\n        error (\"unknown package '%s'\", name.c_str ());\n    }\n\n  return retval;\n}\n\noctave_value\ncdef_manager::find_package_symbol (const std::string& pack_name)\n{\n  cdef_package pack = find_package (pack_name, false);\n\n  if (pack.ok ())\n    return octave_value (new octave_classdef_meta (pack));\n\n  return octave_value ();\n}\n\ncdef_class\ncdef_manager::make_class (const std::string& name,\n                          const std::list<cdef_class>& super_list)\n{\n  cdef_class cls (name, super_list);\n\n  cls.set_class (meta_class ());\n\n  cls.put (\"Abstract\", false);\n  cls.put (\"ConstructOnLoad\", false);\n  cls.put (\"ContainingPackage\", Matrix ());\n  cls.put (\"Description\", \"\");\n  cls.put (\"DetailedDescription\", \"\");\n  cls.put (\"Events\", Cell ());\n  cls.put (\"Hidden\", false);\n  cls.put (\"InferiorClasses\", Cell ());\n  cls.put (\"Methods\", Cell ());\n  cls.put (\"Properties\", Cell ());\n  cls.put (\"Sealed\", false);\n\n  if (name == \"handle\")\n    {\n      cls.put (\"HandleCompatible\", true);\n      cls.mark_as_handle_class ();\n    }\n  else if (super_list.empty ())\n    {\n      cls.put (\"HandleCompatible\", false);\n    }\n  else\n    {\n      bool all_handle_compatible = true;\n      bool has_handle_class = false;\n\n      for (const auto& cl : super_list)\n        {\n          all_handle_compatible = all_handle_compatible\n                                  && cl.get (\"HandleCompatible\").bool_value ();\n\n          has_handle_class = has_handle_class || cl.is_handle_class ();\n        }\n\n      if (has_handle_class && ! all_handle_compatible)\n        error (\"%s: cannot mix handle and non-HandleCompatible classes\",\n               name.c_str ());\n\n      cls.put (\"HandleCompatible\", all_handle_compatible);\n      if (has_handle_class)\n        cls.mark_as_handle_class ();\n    }\n\n  if (! name.empty ())\n    register_class (cls);\n\n  return cls;\n}\n\ncdef_class\ncdef_manager::make_class (const std::string& name,\n                          const cdef_class& super)\n{\n  return make_class (name, std::list<cdef_class> (1, super));\n}\n\ncdef_class\ncdef_manager::make_meta_class (const std::string& name,\n                               const cdef_class& super)\n{\n  cdef_class cls = make_class (name, super);\n\n  cls.put (\"Sealed\", true);\n  cls.mark_as_meta_class ();\n\n  return cls;\n}\n\ncdef_property\ncdef_manager::make_property (const cdef_class& cls, const std::string& name,\n                             const octave_value& get_method,\n                             const std::string& get_access,\n                             const octave_value& set_method,\n                             const std::string& set_access)\n{\n  cdef_property prop (name);\n\n  prop.set_class (meta_property ());\n\n  prop.put (\"Description\", \"\");\n  prop.put (\"DetailedDescription\", \"\");\n  prop.put (\"Abstract\", false);\n  prop.put (\"Constant\", false);\n  prop.put (\"GetAccess\", get_access);\n  prop.put (\"SetAccess\", set_access);\n  prop.put (\"Dependent\", false);\n  prop.put (\"Transient\", false);\n  prop.put (\"Hidden\", false);\n  prop.put (\"GetObservable\", false);\n  prop.put (\"SetObservable\", false);\n  prop.put (\"GetMethod\", get_method);\n  prop.put (\"SetMethod\", set_method);\n  prop.put (\"DefiningClass\", to_ov (cls));\n  prop.put (\"DefaultValue\", octave_value ());\n  prop.put (\"HasDefault\", false);\n\n  std::string class_name = cls.get_name ();\n\n  if (! get_method.isempty ())\n    make_function_of_class (class_name, get_method);\n  if (! set_method.isempty ())\n    make_function_of_class (class_name, set_method);\n\n  return prop;\n}\n\ncdef_property\ncdef_manager::make_attribute (const cdef_class& cls, const std::string& name)\n{\n  return make_property (cls, name, Matrix (), \"public\", Matrix (), \"private\");\n}\n\ncdef_method\ncdef_manager::make_method (const cdef_class& cls, const std::string& name,\n                           const octave_value& fcn,\n                           const std::string& m_access, bool is_static)\n{\n  cdef_method meth (name);\n\n  meth.set_class (meta_method ());\n\n  meth.put (\"Abstract\", false);\n  meth.put (\"Access\", m_access);\n  meth.put (\"DefiningClass\", to_ov (cls));\n  meth.put (\"Description\", \"\");\n  meth.put (\"DetailedDescription\", \"\");\n  meth.put (\"Hidden\", false);\n  meth.put (\"Sealed\", true);\n  meth.put (\"Static\", is_static);\n\n  if (fcn.is_defined ())\n    make_function_of_class (cls, fcn);\n\n  meth.set_function (fcn);\n\n  if (is_dummy_method (fcn))\n    meth.mark_as_external (cls.get_name ());\n\n  return meth;\n}\n\ncdef_method\ncdef_manager::make_method (const cdef_class& cls, const std::string& name,\n                           octave_builtin::fcn ff,\n                           const std::string& m_access, bool is_static)\n{\n  octave_value fcn (new octave_builtin (ff, name));\n\n  return make_method (cls, name, fcn, m_access, is_static);\n}\n\ncdef_method\ncdef_manager::make_method (const cdef_class& cls, const std::string& name,\n                           octave_builtin::meth mm,\n                           const std::string& m_access, bool is_static)\n{\n  octave_value fcn (new octave_builtin (mm, name));\n\n  return make_method (cls, name, fcn, m_access, is_static);\n}\n\ncdef_package\ncdef_manager::make_package (const std::string& nm, const std::string& parent)\n{\n  cdef_package pack (nm);\n\n  pack.set_class (meta_package ());\n\n  if (parent.empty ())\n    pack.put (\"ContainingPackage\", Matrix ());\n  else\n    pack.put (\"ContainingPackage\", to_ov (find_package (parent)));\n\n  if (! nm.empty ())\n    register_package (pack);\n\n  return pack;\n}\n\noctave_value\ncdef_manager::find_method (const std::string& class_name,\n                           const std::string& name) const\n{\n  cdef_class cls = lookup_class (class_name);\n\n  return cls.get_method (name);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/cdef-manager.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cdef_manager_h)\n#define octave_cdef_manager_h 1\n\n#include \"octave-config.h\"\n\n#include \"cdef-class.h\"\n#include \"cdef-fwd.h\"\n#include \"cdef-method.h\"\n#include \"cdef-package.h\"\n#include \"cdef-property.h\"\n#include \"ov-builtin.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass OCTINTERP_API cdef_manager\n{\npublic:\n\n  OCTINTERP_API cdef_manager (interpreter& interp);\n\n  OCTAVE_DISABLE_COPY_MOVE (cdef_manager)\n\n  ~cdef_manager () = default;\n\n  OCTINTERP_API cdef_class\n  find_class (const std::string& name, bool error_if_not_found = true,\n              bool load_if_not_found = true);\n\n  OCTINTERP_API octave_value\n  find_method_symbol (const std::string& method_name,\n                      const std::string& class_name);\n\n  OCTINTERP_API cdef_package\n  find_package (const std::string& name, bool error_if_not_found = true,\n                bool load_if_not_found = true);\n\n  OCTINTERP_API octave_value\n  find_package_symbol (const std::string& pack_name);\n\n  void register_class (const cdef_class& cls)\n  {\n    m_all_classes[cls.get_name ()] = cls;\n  }\n\n  void unregister_class (const cdef_class& cls)\n  {\n    m_all_classes.erase(cls.get_name ());\n  }\n\n  void register_package (const cdef_package& pkg)\n  {\n    m_all_packages[pkg.get_name ()] = pkg;\n  }\n\n  void unregister_package (const cdef_package& pkg)\n  {\n    m_all_packages.erase (pkg.get_name ());\n  }\n\n  const cdef_class& meta_class () const { return m_meta_class; }\n  const cdef_class& meta_property () const { return m_meta_property; }\n  const cdef_class& meta_method () const { return m_meta_method; }\n  const cdef_class& meta_package () const { return m_meta_package; }\n\n  const cdef_package& meta () const { return m_meta; }\n\n  OCTINTERP_API cdef_class\n  make_class (const std::string& name,\n              const std::list<cdef_class>& super_list = std::list<cdef_class> ());\n\n  OCTINTERP_API cdef_class\n  make_class (const std::string& name, const cdef_class& super);\n\n  OCTINTERP_API cdef_class\n  make_meta_class (const std::string& name, const cdef_class& super);\n\n  OCTINTERP_API cdef_property\n  make_property (const cdef_class& cls, const std::string& name,\n                 const octave_value& get_method = Matrix (),\n                 const std::string& get_access = \"public\",\n                 const octave_value& set_method = Matrix (),\n                 const std::string& set_access = \"public\");\n\n  OCTINTERP_API cdef_property\n  make_attribute (const cdef_class& cls, const std::string& name);\n\n  OCTINTERP_API cdef_method\n  make_method (const cdef_class& cls, const std::string& name,\n               const octave_value& fcn,\n               const std::string& m_access = \"public\",\n               bool is_static = false);\n\n  OCTINTERP_API cdef_method\n  make_method (const cdef_class& cls, const std::string& name,\n               octave_builtin::fcn ff,\n               const std::string& m_access = \"public\",\n               bool is_static = false);\n\n  OCTINTERP_API cdef_method\n  make_method (const cdef_class& cls, const std::string& name,\n               octave_builtin::meth mm,\n               const std::string& m_access = \"public\",\n               bool is_static = false);\n\n  OCTINTERP_API cdef_package\n  make_package (const std::string& nm, const std::string& parent = \"\");\n\n  OCTINTERP_API octave_value\n  find_method (const std::string& class_name,\n               const std::string& name) const;\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  // All registered/loaded classes\n  std::map<std::string, cdef_class> m_all_classes;\n\n  // All registered/loaded packages\n  std::map<std::string, cdef_package> m_all_packages;\n\n  cdef_class m_meta_class;\n  cdef_class m_meta_property;\n  cdef_class m_meta_method;\n  cdef_class m_meta_package;\n\n  cdef_package m_meta;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/cdef-method.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"cdef-class.h\"\n#include \"cdef-manager.h\"\n#include \"cdef-utils.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ov-builtin.h\"\n#include \"ov-classdef.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-usr-fcn.h\"\n#include \"parse.h\"\n#include \"pt-assign.h\"\n#include \"pt-classdef.h\"\n#include \"pt-idx.h\"\n#include \"pt-stmt.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_NORETURN static\nvoid\nerr_method_access (const std::string& from, const cdef_method& meth)\n{\n  octave_value acc = meth.get (\"Access\");\n  std::string acc_s;\n\n  if (acc.is_string ())\n    acc_s = acc.string_value ();\n  else\n    acc_s = \"class-restricted\";\n\n  error (\"%s: method '%s' has %s access and cannot be run in this context\",\n         from.c_str (), meth.get_name ().c_str (), acc_s.c_str ());\n}\n\nvoid\ncdef_method::cdef_method_rep::check_method ()\n{\n  if (is_external ())\n    {\n      if (is_dummy_method (m_function))\n        {\n          load_path& lp = __get_load_path__ ();\n\n          std::string name = get_name ();\n          std::string cls_name = m_dispatch_type;\n          std::string pack_name;\n\n          std::size_t pos = cls_name.rfind ('.');\n\n          if (pos != std::string::npos)\n            {\n              pack_name = cls_name.substr (0, pos);\n              cls_name = cls_name.substr (pos + 1);\n            }\n\n          std::string dir_name;\n          std::string file_name = lp.find_method (cls_name, name,\n                                                  dir_name, pack_name);\n\n          if (! file_name.empty ())\n            {\n              octave_value ov_fcn\n                = load_fcn_from_file (file_name, dir_name,\n                                      m_dispatch_type, pack_name);\n\n              if (ov_fcn.is_defined ())\n                {\n                  m_function = ov_fcn;\n\n                  make_function_of_class (m_dispatch_type, m_function);\n                }\n            }\n        }\n      else\n        {\n          // FIXME: check out-of-date status\n        }\n\n      if (is_dummy_method (m_function))\n        error (\"no definition found for method '%s' of class '%s'\",\n               get_name ().c_str (), m_dispatch_type.c_str ());\n    }\n}\n\noctave_value_list\ncdef_method::cdef_method_rep::execute (const octave_value_list& args,\n                                       int nargout, bool do_check_access,\n                                       const std::string& who)\n{\n  octave_value_list retval;\n\n  if (do_check_access && ! check_access ())\n    err_method_access (who, wrap ());\n\n  if (get (\"Abstract\").bool_value ())\n    error (\"%s: cannot execute abstract method\",\n           get (\"Name\").string_value ().c_str ());\n\n  check_method ();\n\n  if (m_function.is_defined ())\n    {\n      interpreter& interp = __get_interpreter__ ();\n\n      retval = interp.feval (m_function, args, nargout);\n    }\n\n  return retval;\n}\n\noctave_value_list\ncdef_method::cdef_method_rep::execute (const cdef_object& obj,\n                                       const octave_value_list& args,\n                                       int nargout, bool do_check_access,\n                                       const std::string& who)\n{\n  octave_value_list retval;\n\n  if (do_check_access && ! check_access ())\n    err_method_access (who, wrap ());\n\n  if (get (\"Abstract\").bool_value ())\n    error (\"%s: cannot execute abstract method\",\n           get (\"Name\").string_value ().c_str ());\n\n  check_method ();\n\n  if (m_function.is_defined ())\n    {\n      octave_value_list new_args;\n\n      new_args.resize (args.length () + 1);\n\n      new_args(0) = to_ov (obj);\n      for (int i = 0; i < args.length (); i++)\n        new_args(i+1) = args(i);\n\n      interpreter& interp = __get_interpreter__ ();\n\n      retval = interp.feval (m_function, new_args, nargout);\n    }\n\n  return retval;\n}\n\nbool\ncdef_method::cdef_method_rep::is_constructor () const\n{\n  if (m_function.is_function())\n    return m_function.function_value ()->is_classdef_constructor ();\n\n  return false;\n}\n\nbool\ncdef_method::cdef_method_rep::is_defined_in_class (const std::string& cname) const\n{\n  return (m_function.is_function ()\n          ? m_function.function_value ()->dispatch_class () == cname\n          : false);\n}\n\nstd::string\ncdef_method::cdef_method_rep::get_doc_string ()\n{\n  check_method ();\n\n  octave_function *fcn = m_function.function_value ();\n\n  return fcn ? fcn->doc_string () : \"\";\n}\n\nbool\ncdef_method::cdef_method_rep::check_access () const\n{\n  cdef_class cls (to_cdef (get (\"DefiningClass\")));\n\n  return octave::check_access (cls, get (\"Access\"), get_name ());\n}\n\noctave_value_list\ncdef_method::cdef_method_rep::meta_subsref\n(const std::string& type, const std::list<octave_value_list>& idx,\n int nargout)\n{\n  octave_value_list retval;\n\n  switch (type[0])\n    {\n    case '(':\n      retval = (execute (idx.front (),\n                         type.length () > 1 ? 1 : nargout, true));\n      break;\n\n    default:\n      error (\"invalid meta.method indexing\");\n      break;\n    }\n\n  if (type.length () > 1 && idx.size () > 1 && ! retval.empty ())\n    retval = retval(0).next_subsref (nargout, type, idx, 1);\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/cdef-method.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cdef_method_h)\n#define octave_cdef_method_h 1\n\n#include \"octave-config.h\"\n\n#include <map>\n#include <set>\n#include <string>\n\n#include \"oct-refcount.h\"\n\n#include \"cdef-object.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API cdef_method : public cdef_meta_object\n{\n  friend class cdef_class;\n\nprivate:\n\n  class cdef_method_rep : public cdef_meta_object_rep\n  {\n  public:\n\n    cdef_method_rep ()\n      : cdef_meta_object_rep (), m_function (), m_dispatch_type ()\n    { }\n\n    cdef_method_rep& operator = (const cdef_method_rep& m) = delete;\n\n    ~cdef_method_rep () = default;\n\n    cdef_object_rep * copy () const { return new cdef_method_rep(*this); }\n\n    bool is_method () const { return true; }\n\n    std::string get_name () const { return get(\"Name\").string_value (); }\n\n    void set_name (const std::string& nm) { put (\"Name\", nm); }\n\n    bool is_static () const { return get(\"Static\").bool_value (); }\n\n    octave_value get_function () const { return m_function; }\n\n    void set_function (const octave_value& fcn) { m_function = fcn; }\n\n    OCTINTERP_API std::string get_doc_string ();\n\n    OCTINTERP_API bool check_access () const;\n\n    bool is_external () const { return ! m_dispatch_type.empty (); }\n\n    void mark_as_external (const std::string& dtype)\n    {\n      m_dispatch_type = dtype;\n    }\n\n    OCTINTERP_API octave_value_list\n    execute (const octave_value_list& args, int nargout,\n             bool do_check_access = true, const std::string& who = \"\");\n\n    OCTINTERP_API octave_value_list\n    execute (const cdef_object& obj,\n             const octave_value_list& args, int nargout,\n             bool do_check_access = true, const std::string& who = \"\");\n\n    OCTINTERP_API bool is_constructor () const;\n\n    OCTINTERP_API bool is_defined_in_class (const std::string& cname) const;\n\n    octave_value_list\n    meta_subsref (const std::string& type,\n                  const std::list<octave_value_list>& idx, int nargout);\n\n    bool meta_accepts_postfix_index (char type) const\n    {\n      return (type == '(' || type == '.');\n    }\n\n  private:\n\n    cdef_method_rep (const cdef_method_rep& m)\n      : cdef_meta_object_rep (m), m_function (m.m_function),\n        m_dispatch_type (m.m_dispatch_type)\n    { }\n\n    OCTINTERP_API void check_method ();\n\n    cdef_method wrap ()\n    {\n      m_count++;\n      return cdef_method (this);\n    }\n\n    octave_value m_function;\n\n    // When non-empty, the method is externally defined and this member\n    // is used to cache the dispatch type to look for the method.\n\n    std::string m_dispatch_type;\n  };\n\npublic:\n\n  cdef_method () : cdef_meta_object () { }\n\n  cdef_method (const std::string& nm)\n    : cdef_meta_object (new cdef_method_rep ())\n  {\n    get_rep ()->set_name (nm);\n  }\n\n  cdef_method (const cdef_method& meth) : cdef_meta_object (meth) { }\n\n  cdef_method (const cdef_object& obj)\n    : cdef_meta_object (obj)\n  {\n    // This should never happen...\n    if (! is_method ())\n      error (\"internal error: invalid assignment from %s to meta.method object\",\n             class_name ().c_str ());\n  }\n\n  cdef_method& operator = (const cdef_method& meth)\n  {\n    cdef_object::operator = (meth);\n\n    return *this;\n  }\n\n  ~cdef_method () = default;\n\n  // normal invocation\n  octave_value_list execute (const octave_value_list& args, int nargout,\n                             bool do_check_access = true,\n                             const std::string& who = \"\")\n  {\n    return get_rep ()->execute (args, nargout, do_check_access, who);\n  }\n\n  // dot-invocation: object is pushed as 1st argument\n  octave_value_list execute (const cdef_object& obj,\n                             const octave_value_list& args, int nargout,\n                             bool do_check_access = true,\n                             const std::string& who = \"\")\n  {\n    return get_rep ()->execute (obj, args, nargout, do_check_access, who);\n  }\n\n  bool check_access () const { return get_rep ()->check_access (); }\n\n  std::string get_name () const { return get_rep ()->get_name (); }\n\n  bool is_static () const { return get_rep ()->is_static (); }\n\n  void set_function (const octave_value& fcn)\n  {\n    get_rep ()->set_function (fcn);\n  }\n\n  octave_value get_function () const\n  {\n    return get_rep ()->get_function ();\n  }\n\n  std::string get_doc_string ()\n  {\n    return get_rep ()->get_doc_string ();\n  }\n\n  bool is_constructor () const\n  {\n    return get_rep ()->is_constructor ();\n  }\n\n  bool is_defined_in_class (const std::string& cname) const\n  {\n    return get_rep ()->is_defined_in_class (cname);\n  }\n\n  bool is_external () const { return get_rep ()->is_external (); }\n\n  void mark_as_external (const std::string& dtype)\n  {\n    get_rep ()->mark_as_external (dtype);\n  }\n\nprivate:\n\n  cdef_method_rep * get_rep ()\n  {\n    return dynamic_cast<cdef_method_rep *> (cdef_object::get_rep ());\n  }\n\n  const cdef_method_rep * get_rep () const\n  {\n    return dynamic_cast<const cdef_method_rep *> (cdef_object::get_rep ());\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/cdef-object.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <memory>\n\n#include \"cdef-class.h\"\n#include \"cdef-object.h\"\n#include \"cdef-property.h\"\n#include \"cdef-utils.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"ov-classdef.h\"\n\n#define OCTAVE_CDEF_OBJECT_DEBUG 0\n#if OCTAVE_CDEF_OBJECT_DEBUG\n#  include <iostream>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\ncdef_object_rep::release (const cdef_object& obj)\n{\n  // We need to be careful to keep a reference to the object if we are\n  // calling the delete method.  The object is passed to the delete\n  // method as an argument and if the count is already zero when we\n  // do that, then we will increment the count while creating the\n  // argument list for the delete method and then it will be decremented\n  // back to zero and we'll find ourselves in an infinite loop.\n\n  if (m_count - 1 > static_count ())\n    {\n      --m_count;\n      return;\n    }\n\n  if (is_handle_object () && ! is_meta_object ())\n    {\n      unwind_protect frame;\n\n      // Clear interrupts.\n      frame.protect_var (octave_interrupt_state);\n      octave_interrupt_state = 0;\n\n      // Disallow quit().\n      frame.protect_var (quit_allowed);\n      quit_allowed = false;\n\n      interpreter& interp = __get_interpreter__ ();\n\n      interpreter_try (frame);\n\n      try\n        {\n          // Call classdef \"delete()\" method on object\n          get_class ().delete_object (obj);\n        }\n      catch (const interrupt_exception&)\n        {\n          interp.recover_from_exception ();\n\n          warning (\"interrupt occurred in handle class delete method\");\n        }\n      catch (const execution_exception& ee)\n        {\n          interp.recover_from_exception ();\n\n          std::string msg = ee.message ();\n\n          warning (\"error caught while executing handle class delete method:\\n%s\\n\",\n                   msg.c_str ());\n        }\n      catch (const exit_exception&)\n        {\n          // This shouldn't happen since we disabled quit above.\n          warning (\"exit disabled while executing handle class delete method\");\n        }\n      catch (...) // Yes, the black hole.  We're in a d-tor.\n        {\n          // This shouldn't happen, in theory.\n          warning (\"internal error: unhandled exception in handle class delete method\");\n        }\n    }\n\n  // Now it is safe to set the count to zero.\n  m_count--;\n\n  destroy ();\n}\n\ncdef_class\ncdef_object_rep::get_class () const\n{\n  err_invalid_object (\"get_class\");\n}\n\nstd::string\ncdef_object_rep::class_name () const\n{\n  return get_class ().get_name ();\n}\n\nstring_vector\ncdef_object_rep::map_keys () const\n{\n  cdef_class cls = get_class ();\n\n  if (cls.ok ())\n    return cls.get_names ();\n\n  return string_vector ();\n}\n\noctave_map\ncdef_object::map_value (bool warn, bool for_save) const\n{\n  octave_map retval;\n\n  if (warn)\n    warning_with_id (\"Octave:classdef-to-struct\",\n                     \"struct: converting a classdef object into a struct \"\n                     \"overrides the access restrictions defined for \"\n                     \"properties.  All properties are returned, including \"\n                     \"private and protected ones.\");\n\n  cdef_class cls = get_class ();\n\n  if (cls.ok ())\n    {\n      std::map<property_key, cdef_property> props;\n\n      props = cls.get_property_map (cdef_class::property_all);\n\n      // FIXME: Why not const here?\n      for (auto& prop_val : props)\n        {\n          // Do not include properties that have the \"Transient\" attribute\n          // when creating the map for saving the object to a file.\n          if (for_save && prop_val.second.get (\"Transient\").bool_value ())\n            continue;\n\n          if (is_array ())\n            {\n              Array<cdef_object> a_obj = array_value ();\n\n              Cell cvalue (a_obj.dims ());\n\n              for (octave_idx_type i = 0; i < a_obj.numel (); i++)\n                cvalue (i) = prop_val.second.get_value (a_obj(i), false);\n\n              retval.setfield (prop_val.second.get_name (), cvalue);\n            }\n          else\n            {\n              Cell cvalue (dim_vector (1, 1),\n                           prop_val.second.get_value (*this, false));\n\n              retval.setfield (prop_val.second.get_name (), cvalue);\n            }\n        }\n    }\n\n  return retval;\n}\n\ncdef_class\ncdef_object::get_class () const\n{\n  return m_rep->get_class ();\n}\n\ncdef_class\ncdef_object_base::get_class () const\n{\n  return cdef_class (m_klass);\n}\n\nvoid\ncdef_object_base::set_class (const cdef_class& cls)\n{\n  if ((m_klass.ok () && cls.ok () && cls != get_class ())\n      || (m_klass.ok () && ! cls.ok ())\n      || (! m_klass.ok () && cls.ok ()))\n    {\n      m_klass = cls;\n    }\n}\n\ncdef_object_rep *\ncdef_object_base::make_array () const\n{\n  cdef_object_rep *r = new cdef_object_array ();\n\n  r->set_class (get_class ());\n\n  return r;\n}\n\ncdef_object_rep *\ncdef_object_array::clone () const\n{\n  Array<cdef_object> new_array (m_array.dims ());\n\n  for (octave_idx_type i = 0; i < m_array.numel (); i++)\n    new_array(i) = m_array(i).clone ();\n\n  cdef_object_array *retval = new cdef_object_array (new_array);\n  retval->set_class (get_class ());\n  return retval;\n}\n\ncdef_object_rep *\ncdef_object_array::permute (const Array<int>& vec, bool inv) const\n{\n  Array<cdef_object> cpy_array = m_array.permute (vec, inv);\n\n  cdef_object_array *retval = new cdef_object_array (cpy_array);\n  retval->set_class (get_class ());\n  return retval;\n}\n\ncdef_object_rep *\ncdef_object_array::resize (const dim_vector& dv, bool fill) const\n{\n  cdef_object_array *retval = dynamic_cast<cdef_object_array *> (clone ());\n  std::unique_ptr<cdef_object_array> guard (retval);\n\n  retval->m_array.resize (dv, cdef_object ());\n\n  if (fill)\n    retval->fill_empty_values ();\n\n  return guard.release ();\n}\n\ncdef_object_rep *\ncdef_object_array::transpose () const\n{\n  if (m_array.ndims () > 2)\n    error (\"transpose not defined for N-D objects\");\n\n  auto perm_vec = Array<int> (std::vector<int> {1, 0}, dim_vector (1, 2));\n  return permute (perm_vec);\n}\n\noctave_value_list\ncdef_object_array::subsref (const std::string& type,\n                            const std::list<octave_value_list>& idx,\n                            int /* nargout */, std::size_t& skip,\n                            const cdef_class& /* context */, bool auto_add)\n{\n  octave_value_list retval;\n\n  skip = 1;\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        const octave_value_list& ival = idx.front ();\n\n        if (ival.empty ())\n          {\n            m_count++;\n            retval(0) = to_ov (cdef_object (this));\n            break;\n          }\n\n        bool is_scalar = true;\n        Array<idx_vector> iv (dim_vector (1, ival.length ()));\n\n        for (int i = 0; i < ival.length (); i++)\n          {\n            try\n              {\n                iv(i) = ival(i).index_vector ();\n              }\n            catch (index_exception& ie)\n              {\n                // Rethrow to allow more info to be reported later.\n                ie.set_pos_if_unset (ival.length (), i+1);\n                throw;\n              }\n\n            is_scalar = is_scalar && iv(i).is_scalar ();\n          }\n\n        Array<cdef_object> ires = m_array.index (iv, auto_add);\n\n        // If resizing is enabled (auto_add = true), it's possible\n        // indexing was out-of-bound and the result array contains\n        // invalid cdef_objects.\n\n        if (auto_add)\n          fill_empty_values (ires);\n\n        if (is_scalar)\n          retval(0) = to_ov (ires(0));\n        else\n          {\n            cdef_object array_obj (new cdef_object_array (ires));\n\n            array_obj.set_class (get_class ());\n\n            retval(0) = to_ov (array_obj);\n          }\n      }\n      break;\n\n    case '.':\n      if (m_array.numel () == 1)\n        {\n          // If there is only one element in the array, implicitly index the\n          // first element.  In this case, also allow indexing with more than\n          // one level.\n\n          // dummy variables\n          std::size_t dummy_skip;\n          cdef_class dummy_cls;\n          retval = m_array(0).subsref (type, idx, 1, dummy_skip, dummy_cls);\n\n          break;\n        }\n      else if (type.size () == 1 && idx.size () == 1)\n        {\n          Cell c (dims ());\n\n          octave_idx_type n = m_array.numel ();\n\n          // dummy variables\n          std::size_t dummy_skip;\n          cdef_class dummy_cls;\n\n          for (octave_idx_type i = 0; i < n; i++)\n            {\n              octave_value_list r = m_array(i).subsref (type, idx, 1,\n                                    dummy_skip,\n                                    dummy_cls);\n\n              if (r.length () > 0)\n                c(i) = r(0);\n            }\n\n          retval(0) = octave_value (c, true);\n\n          break;\n        }\n      OCTAVE_FALLTHROUGH;\n\n    default:\n      error (\"can't perform indexing operation on array of %s objects\",\n             class_name ().c_str ());\n      break;\n    }\n\n  return retval;\n}\n\noctave_value\ncdef_object_array::subsasgn (const std::string& type,\n                             const std::list<octave_value_list>& idx,\n                             const octave_value& rhs)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      if (type.length () == 1)\n        {\n          const octave_value_list& ival = idx.front ();\n          bool is_scalar = true;\n          Array<idx_vector> iv (dim_vector (1, ival.length ()));\n\n          for (int i = 0; i < ival.length (); i++)\n            {\n              try\n                {\n                  iv(i) = ival(i).index_vector ();\n                }\n              catch (index_exception& ie)\n                {\n                  ie.set_pos_if_unset (ival.length (), i+1);\n                  throw;   // var name set in pt-idx.cc / pt-assign.cc\n                }\n\n              is_scalar = is_scalar && iv(i).is_scalar ();\n            }\n\n          if (rhs.isempty ())\n            m_array.delete_elements (iv);\n          else\n            {\n              cdef_object rhs_obj = to_cdef (rhs);\n\n              if (rhs_obj.get_class () != get_class ())\n                error (\"can't assign %s object into array of %s objects\",\n                       rhs_obj.class_name ().c_str (),\n                       class_name ().c_str ());\n\n              Array<cdef_object> rhs_mat;\n\n              if (! rhs_obj.is_array ())\n                {\n                  rhs_mat = Array<cdef_object> (dim_vector (1, 1));\n                  rhs_mat(0) = rhs_obj;\n                }\n              else\n                rhs_mat = rhs_obj.array_value ();\n\n              octave_idx_type n = m_array.numel ();\n\n              m_array.assign (iv, rhs_mat, cdef_object ());\n\n              if (m_array.numel () > n)\n                fill_empty_values ();\n            }\n\n          m_count++;\n          retval = to_ov (cdef_object (this));\n        }\n      else\n        {\n          const octave_value_list& ival = idx.front ();\n\n          bool is_scalar = true;\n\n          Array<idx_vector> iv (dim_vector (1, ival.length ()));\n\n          for (int i = 0; i < ival.length (); i++)\n            {\n              try\n                {\n                  iv(i) = ival(i).index_vector ();\n                }\n              catch (index_exception& ie)\n                {\n                  // Rethrow to allow more info to be reported later.\n                  ie.set_pos_if_unset (ival.length (), i+1);\n                  throw;\n                }\n\n              is_scalar = is_scalar && iv(i).is_scalar ();\n\n              if (! is_scalar)\n                error (\"subsasgn: invalid indexing for object array assignment\"\n                       \", the index must reference a single object in the \"\n                       \"array.\");\n            }\n\n          Array<cdef_object> a = m_array.index (iv, true);\n\n          if (a.numel () != 1)\n            error (\"subsasgn: invalid indexing for object array assignment\");\n\n          cdef_object obj = a(0);\n\n          int ignore_copies = 0;\n\n          // If the object in 'a' is not valid, this means the index\n          // was out-of-bound and we need to create a new object.\n\n          if (! obj.ok ())\n            obj = to_cdef (get_class ().construct (octave_value_list ()));\n          else\n            // Optimize the subsasgn call to come.  There are 2 copies\n            // that we can safely ignore:\n            // - 1 in \"array\"\n            // - 1 in \"a\"\n            ignore_copies = 2;\n\n          std::list<octave_value_list> next_idx (std::next (idx.begin ()),\n                                                 idx.end ());\n\n          octave_value tmp = obj.subsasgn (type.substr (1), next_idx,\n                                           rhs, ignore_copies);\n\n          cdef_object robj = to_cdef (tmp);\n\n          if (! robj.ok ()\n              || robj.is_array ()\n              || robj.get_class () != get_class ())\n            error (\"subsasgn: invalid assignment into array of %s objects\",\n                   class_name ().c_str ());\n\n          // Small optimization, when dealing with handle\n          // objects, we don't need to re-assign the result\n          // of subsasgn back into the array.\n\n          if (! robj.is (a(0)))\n            {\n              Array<cdef_object> rhs_a (dim_vector (1, 1),\n                                        robj);\n\n              octave_idx_type n = m_array.numel ();\n\n              m_array.assign (iv, rhs_a);\n\n              if (m_array.numel () > n)\n                fill_empty_values ();\n            }\n\n          m_count++;\n\n          retval = to_ov (cdef_object (this));\n        }\n      break;\n\n    case '.':\n      if (m_array.numel () == 1)\n        {\n          // If there is only one element in the array, implicitly index the\n          // first element.\n\n          retval = m_array(0).subsasgn (type, idx, rhs);\n\n          break;\n        }\n      OCTAVE_FALLTHROUGH;\n\n    default:\n      error (\"can't perform indexing operation on array of %s objects\",\n             class_name ().c_str ());\n      break;\n    }\n\n  return retval;\n}\n\noctave_value\ncdef_object_array::reshape (const dim_vector& new_dims) const\n{\n  cdef_object_array retval = cdef_object_array (*this);\n  retval.m_array = Array<cdef_object> (m_array, new_dims);\n  return to_ov (cdef_object (new cdef_object_array (retval)));\n}\n\nvoid\ncdef_object_array::fill_empty_values (Array<cdef_object>& arr)\n{\n  cdef_class cls = get_class ();\n\n  cdef_object obj;\n\n  int n = arr.numel ();\n\n  for (int i = 0; i < n; i++)\n    {\n      if (! arr.xelem (i).ok ())\n        {\n          if (! obj.ok ())\n            {\n              obj = to_cdef (cls.construct (octave_value_list ()));\n\n              arr.xelem (i) = obj;\n            }\n          else\n            arr.xelem (i) = obj.copy ();\n        }\n    }\n}\n\nstd::size_t\ncdef_object_array::byte_size () const\n{\n  std::size_t retval = 0;\n\n  for (octave_idx_type i = 0; i < m_array.numel (); i++)\n    retval += m_array.xelem (i).byte_size ();\n\n  return retval;\n}\n\nvoid\ncdef_object_array::break_closure_cycles (const std::shared_ptr<stack_frame>& frame)\n{\n  for (octave_idx_type i = 0; i < m_array.numel (); i++)\n    m_array(i).break_closure_cycles (frame);\n}\n\nvoid\ncdef_object_array::mark_as_constructed ()\n{\n  for (octave_idx_type i = 0; i < m_array.numel (); i++)\n    m_array(i).mark_as_constructed ();\n}\n\nvoid\ncdef_object_array::mark_as_constructed (const cdef_class& cls)\n{\n  for (octave_idx_type i = 0; i < m_array.numel (); i++)\n    m_array(i).mark_as_constructed (cls);\n}\n\nvoid\ncdef_object_scalar::break_closure_cycles (const std::shared_ptr<stack_frame>& frame)\n{\n  for (octave_idx_type i = 0; i < m_map.nfields (); i++)\n    m_map.contents(i).break_closure_cycles (frame);\n}\n\noctave_value_list\ncdef_object_scalar::subsref (const std::string& type,\n                             const std::list<octave_value_list>& idx,\n                             int nargout, std::size_t& skip,\n                             const cdef_class& context, bool auto_add)\n{\n  skip = 0;\n\n  cdef_class cls = (context.ok () ? context : get_class ());\n\n  octave_value_list retval;\n\n  if (! cls.ok ())\n    return retval;\n\n  switch (type[0])\n    {\n    case '.':\n      {\n        std::string name = (idx.front ())(0).string_value ();\n\n        cdef_property prop = cls.find_property (name);\n\n        if (prop.ok ())\n          {\n            if (prop.is_constant ())\n              retval(0) = prop.get_value (true, \"subsref\");\n            else\n              {\n                m_count++;\n                retval(0) = prop.get_value (cdef_object (this),\n                                            true, \"subsref\");\n              }\n\n            skip = 1;\n          }\n\n        if (skip == 0)\n          {\n            cdef_method meth = cls.find_method (name);\n\n            if (! meth.ok ())\n              error (\"subsref: unknown method or property: %s\", name.c_str ());\n\n            // If the method call is followed by another index operation,\n            // the number of outputs of the call will be 1.\n            int nargout_mtd = (type.length () > 2\n                               || (type.length () == 2 && type[1] != '(')\n                               ? 1 : nargout);\n\n            octave_value_list args;\n\n            skip = 1;\n\n            if (type.length () > 1 && type[1] == '(')\n              {\n                auto it = idx.begin ();\n\n                args = *++it;\n\n                skip++;\n              }\n\n            if (meth.is_static ())\n              retval = meth.execute (args, nargout_mtd, true, \"subsref\");\n            else\n              {\n                m_count++;\n                retval = meth.execute (cdef_object (this), args, nargout_mtd,\n                                       true, \"subsref\");\n              }\n          }\n\n        break;\n      }\n\n    case '(':\n      {\n        const octave_value_list& ival = idx.front ();\n\n        m_count++;\n        cdef_object this_obj (this);\n\n        if (ival.empty ())\n          {\n            skip++;\n            retval(0) = to_ov (this_obj);\n          }\n        else\n          {\n            Array<cdef_object> arr (dim_vector (1, 1), this_obj);\n\n            cdef_object new_obj = cdef_object (new cdef_object_array (arr));\n\n            new_obj.set_class (get_class ());\n\n            retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add);\n          }\n      }\n      break;\n\n    default:\n      error (\"object cannot be indexed with '%c'\", type[0]);\n      break;\n    }\n\n  return retval;\n}\n\noctave_value\ncdef_object_scalar::subsasgn (const std::string& type,\n                              const std::list<octave_value_list>& idx,\n                              const octave_value& rhs)\n{\n  octave_value retval;\n\n  cdef_class cls = get_class ();\n\n  switch (type[0])\n    {\n    case '.':\n      {\n        std::string name = (idx.front ())(0).string_value ();\n\n        cdef_property prop = cls.find_property (name);\n\n        if (! prop.ok ())\n          error (\"subsasgn: unknown property: %s\", name.c_str ());\n\n        if (prop.is_constant ())\n          error (\"subsasgn: cannot assign constant property: %s\",\n                 name.c_str ());\n\n        m_count++;\n\n        cdef_object obj (this);\n\n        if (type.length () == 1)\n          {\n            prop.set_value (obj, rhs, true, \"subsasgn\");\n\n            retval = to_ov (obj);\n          }\n        else\n          {\n            octave_value val = prop.get_value (obj, true, \"subsasgn\");\n\n            std::list<octave_value_list> args (std::next (idx.begin ()),\n                                               idx.end ());\n\n            val = val.assign (octave_value::op_asn_eq,\n                              type.substr (1), args, rhs);\n\n            if (val.class_name () != \"object\"\n                || ! to_cdef (val).is_handle_object ())\n              prop.set_value (obj, val, true, \"subsasgn\");\n\n            retval = to_ov (obj);\n          }\n      }\n      break;\n\n    case '(':\n      {\n        m_count++;\n\n        cdef_object this_obj (this);\n\n        Array<cdef_object> arr (dim_vector (1, 1), this_obj);\n\n        cdef_object new_obj = cdef_object (new cdef_object_array (arr));\n\n        new_obj.set_class (get_class ());\n\n        octave_value tmp = new_obj.subsasgn (type, idx, rhs);\n\n        retval = tmp;\n      }\n      break;\n\n    default:\n      error (\"subsasgn: object cannot be index with '%c'\", type[0]);\n      break;\n    }\n\n  return retval;\n}\n\noctave_value\ncdef_object_scalar::reshape (const dim_vector& new_dims) const\n{\n  if (new_dims.numel () != 1)\n    {\n      std::string new_dims_str = new_dims.str ();\n      error (\"reshape: cannot reshape scalar classdef object to %s array\",\n             new_dims_str.c_str ());\n    }\n\n  return to_ov (cdef_object (clone()));\n}\n\ncdef_object_rep *\ncdef_object_scalar::resize (const dim_vector& dv, bool fill) const\n{\n  if (dv.numel () == 1)\n    return clone ();\n\n  Array<cdef_object> arr (dv);\n\n  // Need to guard against this statement being called when an empty array\n  // is generated\n  if (dv.numel () > 0)\n    arr(0) = cdef_object (const_cast<cdef_object_scalar *> (this)->clone ());\n\n  cdef_object_array *retval = new cdef_object_array (arr);\n  std::unique_ptr<cdef_object_array> guard (retval);\n\n  retval->set_class (get_class ());\n\n  if (fill)\n    retval->fill_empty_values ();\n\n  return guard.release ();\n}\n\nvoid\ncdef_object_scalar::mark_for_construction (const cdef_class& cls)\n{\n  std::string cls_name = cls.get_name ();\n\n  Cell supcls = cls.get (\"SuperClasses\").cell_value ();\n\n  std::list<cdef_class> supcls_list = lookup_classes (supcls);\n\n  m_ctor_list[cls] = supcls_list;\n}\n\nbool\ncdef_object_scalar::is_constructed_for (const cdef_class& cls) const\n{\n  return (is_constructed ()\n          || m_ctor_list.find (cls) == m_ctor_list.end ());\n}\n\nbool\ncdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const\n{\n  if (is_constructed ())\n    return true;\n\n  std::map<cdef_class, std::list<cdef_class>>::const_iterator it\n      = m_ctor_list.find (cls);\n\n  if (it == m_ctor_list.end () || it->second.empty ())\n    return true;\n\n  for (const auto& cdef_cls : it->second)\n    if (! is_partially_constructed_for (cdef_cls))\n      return false;\n\n  return true;\n}\n\nvoid\ncdef_object_scalar::mark_as_constructed (const cdef_class& cls)\n{\n  m_ctor_list.erase (cls);\n}\n\nhandle_cdef_object::~handle_cdef_object ()\n{\n#if OCTAVE_CDEF_OBJECT_DEBUG\n  std::cerr << \"deleting \" << get_class ().get_name ()\n            << \" object (handle)\" << std::endl;\n#endif\n}\n\nvalue_cdef_object::~value_cdef_object ()\n{\n#if OCTAVE_CDEF_OBJECT_DEBUG\n  std::cerr << \"deleting \" << get_class ().get_name ()\n            << \" object (value)\" << std::endl;\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/cdef-object.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cdef_object_h)\n#define octave_cdef_object_h 1\n\n#include \"octave-config.h\"\n\n#include <map>\n#include <string>\n\n#include \"oct-refcount.h\"\n\n#include \"cdef-fwd.h\"\n#include \"error.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// This is mainly a bootstrap class to declare the expected interface.\n// The actual base class is cdef_class_base, which is declared after\n// cdef_object, such that it can contain cdef_object objects.\n\nclass OCTINTERP_API cdef_object_rep\n{\npublic:\n\n  friend class cdef_object;\n\n  cdef_object_rep () : m_count (1) { }\n\n  cdef_object_rep& operator = (const cdef_object_rep&) = delete;\n\n  virtual ~cdef_object_rep () = default;\n\n  virtual cdef_class get_class () const;\n\n  virtual void set_class (const cdef_class&)\n  {\n    err_invalid_object (\"set_class\");\n  }\n\n  virtual cdef_object_rep * clone () const\n  {\n    err_invalid_object (\"clone\");\n  }\n\n  virtual cdef_object_rep * empty_clone () const\n  {\n    err_invalid_object (\"empty_clone\");\n  }\n\n  virtual cdef_object_rep * copy () const\n  {\n    err_invalid_object (\"copy\");\n  }\n\n  virtual cdef_object_rep * make_array () const\n  {\n    err_invalid_object (\"make_array\");\n  }\n\n  virtual bool is_array () const { return false; }\n\n  virtual bool is_value_object () const { return false; }\n\n  virtual bool is_handle_object () const { return false; }\n\n  virtual bool is_meta_object () const { return false; }\n\n  virtual Array<cdef_object> array_value () const\n  {\n    err_invalid_object (\"array_value\");\n  }\n\n  virtual void put (const std::string&, const octave_value&)\n  { err_invalid_object (\"put\"); }\n\n  virtual octave_value get (const std::string&) const\n  {\n    err_invalid_object (\"get\");\n  }\n\n  virtual void set_property (octave_idx_type, const std::string&,\n                             const octave_value&)\n  {\n    err_invalid_object (\"set_property\");\n  }\n\n  virtual octave_value get_property (octave_idx_type, const std::string&) const\n  {\n    err_invalid_object (\"get_property\");\n  }\n\n  virtual void break_closure_cycles (const std::shared_ptr<stack_frame>&)\n  {\n    err_invalid_object (\"break_closure_cycles\");\n  }\n\n  virtual octave_value_list\n  subsref (const std::string&, const std::list<octave_value_list>&,\n           int, std::size_t&, const cdef_class&, bool)\n  {\n    err_invalid_object (\"subsref\");\n  }\n\n  virtual octave_value\n  subsasgn (const std::string&, const std::list<octave_value_list>&,\n            const octave_value&)\n  {\n    err_invalid_object (\"subsasgn\");\n  }\n\n  virtual octave_value reshape (const dim_vector&) const\n  {\n    err_invalid_object (\"reshape\");\n  }\n\n  virtual string_vector map_keys () const;\n\n  virtual bool is_valid () const { return false; }\n\n  OCTINTERP_API std::string class_name () const;\n\n  virtual void mark_for_construction (const cdef_class&)\n  {\n    err_invalid_object (\"mark_for_construction\");\n  }\n\n  virtual bool is_constructed_for (const cdef_class&) const\n  {\n    err_invalid_object (\"is_constructed_for\");\n  }\n\n  virtual bool is_partially_constructed_for (const cdef_class&) const\n  {\n    err_invalid_object (\"is_partially_constructed_for\");\n  }\n\n  virtual void mark_as_constructed ()\n  {\n    err_invalid_object (\"mark_as_constructed\");\n  }\n\n  virtual void mark_as_constructed (const cdef_class&)\n  {\n    err_invalid_object (\"mark_as_constructed\");\n  }\n\n  virtual bool is_constructed () const\n  {\n    err_invalid_object (\"is_constructed\");\n  }\n\n  virtual octave_idx_type static_count () const { return 0; }\n\n  virtual void destroy () { delete this; }\n\n  OCTINTERP_API void release (const cdef_object& obj);\n\n  virtual dim_vector dims () const { return dim_vector (); }\n\n  virtual cdef_object_rep * permute (const Array<int>&, bool = false) const\n  {\n    err_invalid_object (\"permute\");\n  }\n\n  virtual cdef_object_rep * resize (const dim_vector&, bool = false) const\n  {\n    err_invalid_object (\"resize\");\n  }\n\n  virtual cdef_object_rep * transpose () const\n  {\n    err_invalid_object (\"transpose\");\n  }\n\n  virtual std::size_t byte_size () const\n  {\n    err_invalid_object (\"byte_size\");\n  }\n\nprotected:\n\n  // Reference count\n  refcount<octave_idx_type> m_count;\n\n  // Restricted copying.\n\n  cdef_object_rep (const cdef_object_rep&) : m_count (1) { }\n\nprivate:\n\n  OCTAVE_NORETURN void err_invalid_object (const char *who) const\n  {\n    error (\"%s: invalid object\", who);\n  }\n};\n\nclass OCTINTERP_API cdef_object\n{\npublic:\n\n  // FIXME: use a null object?\n  cdef_object () : m_rep (new cdef_object_rep ()) { }\n\n  cdef_object (const cdef_object& obj) : m_rep (obj.m_rep)\n  { m_rep->m_count++; }\n\n  cdef_object (cdef_object_rep *r) : m_rep (r) { }\n\n  virtual ~cdef_object () { m_rep->release (*this); }\n\n  cdef_object& operator = (const cdef_object& obj)\n  {\n    if (m_rep != obj.m_rep)\n      {\n        m_rep->release (*this);\n\n        m_rep = obj.m_rep;\n        m_rep->m_count++;\n      }\n\n    return *this;\n  }\n\n  OCTINTERP_API cdef_class get_class () const;\n\n  void set_class (const cdef_class& cls) { m_rep->set_class (cls); }\n\n  std::string class_name () const { return m_rep->class_name (); }\n\n  cdef_object clone () const { return cdef_object (m_rep->clone ()); }\n\n  cdef_object empty_clone () const\n  {\n    return cdef_object (m_rep->empty_clone ());\n  }\n\n  dim_vector dims () const { return m_rep->dims (); }\n\n  cdef_object make_array () const\n  {\n    return cdef_object (m_rep->make_array ());\n  }\n\n  cdef_object copy () const { return cdef_object (m_rep->copy ()); }\n\n  bool is_array () const { return m_rep->is_array (); }\n\n  bool is_value_object () const { return m_rep->is_value_object (); }\n\n  bool is_handle_object () const { return m_rep->is_handle_object (); }\n\n  bool is_meta_object () const { return m_rep->is_meta_object (); }\n\n  Array<cdef_object> array_value () const\n  { return m_rep->array_value (); }\n\n  void put (const std::string& pname, const octave_value& val)\n  {\n    m_rep->put (pname, val);\n  }\n\n  octave_value get (const std::string& pname) const\n  {\n    return m_rep->get (pname);\n  }\n\n  void set_property (octave_idx_type idx, const std::string& pname,\n                     const octave_value& pval)\n  {\n    return m_rep->set_property (idx, pname, pval);\n  }\n\n  octave_value\n  get_property (octave_idx_type idx, const std::string& pname) const\n  {\n    return m_rep->get_property (idx, pname);\n  }\n\n  void break_closure_cycles (const std::shared_ptr<stack_frame>& frame)\n  {\n    m_rep->break_closure_cycles (frame);\n  }\n\n  octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int nargout, std::size_t& skip, const cdef_class& context,\n           bool auto_add = false)\n  {\n    return m_rep->subsref (type, idx, nargout, skip, context, auto_add);\n  }\n\n  octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs, int ignore_copies = 0)\n  {\n    make_unique (ignore_copies);\n    return m_rep->subsasgn (type, idx, rhs);\n  }\n\n  octave_value reshape (const dim_vector& new_dims) const\n  {\n    return m_rep->reshape (new_dims);\n  }\n\n  string_vector map_keys () const { return m_rep->map_keys (); }\n\n  OCTINTERP_API octave_map\n  map_value (bool warn = true, bool for_save = false) const;\n\n  const cdef_object_rep * get_rep () const { return m_rep; }\n\n  bool ok () const { return m_rep->is_valid (); }\n\n  void mark_for_construction (const cdef_class& cls)\n  {\n    m_rep->mark_for_construction (cls);\n  }\n\n  bool is_constructed () const { return m_rep->is_constructed (); }\n\n  bool is_constructed_for (const cdef_class& cls) const\n  {\n    return m_rep->is_constructed_for (cls);\n  }\n\n  bool is_partially_constructed_for (const cdef_class& cls) const\n  {\n    return m_rep->is_partially_constructed_for (cls);\n  }\n\n  void mark_as_constructed () { m_rep->mark_as_constructed (); }\n\n  void mark_as_constructed (const cdef_class& cls)\n  { m_rep->mark_as_constructed (cls); }\n\n  bool is (const cdef_object& obj) const { return m_rep == obj.m_rep; }\n\n  cdef_object permute (const Array<int>& vec, bool inv = false) const\n  { return cdef_object (m_rep->permute (vec, inv)); }\n\n  cdef_object resize (const dim_vector& dv, bool fill = false) const\n  { return cdef_object (m_rep->resize (dv, fill)); }\n\n  cdef_object transpose () const\n  { return cdef_object (m_rep->transpose ()); }\n\n  std::size_t byte_size () const { return m_rep->byte_size (); }\n\nprotected:\n\n  cdef_object_rep * get_rep () { return m_rep; }\n\n  void make_unique (int ignore_copies)\n  {\n    if (m_rep->m_count > ignore_copies + 1)\n      *this = clone ();\n  }\n\nprivate:\n\n  cdef_object_rep *m_rep;\n};\n\nclass OCTINTERP_API cdef_object_base : public cdef_object_rep\n{\npublic:\n\n  cdef_object_base ()\n    : cdef_object_rep (), m_klass ()\n  { }\n\n  cdef_object_base& operator = (const cdef_object_base&) = delete;\n\n  ~cdef_object_base () { }\n\n  OCTINTERP_API cdef_class get_class () const;\n\n  OCTINTERP_API void set_class (const cdef_class& cls);\n\n  cdef_object_rep * empty_clone () const\n  {\n    return new cdef_object_base (*this);\n  }\n\n  OCTINTERP_API cdef_object_rep * make_array () const;\n\nprotected:\n\n  // Restricted copying!\n  cdef_object_base (const cdef_object_base& obj)\n    : cdef_object_rep (obj), m_klass (obj.m_klass)\n  { }\n\nprivate:\n\n  // The class of the object\n  cdef_object m_klass;\n};\n\nclass OCTINTERP_API cdef_object_array : public cdef_object_base\n{\npublic:\n\n  cdef_object_array () : cdef_object_base () { }\n\n  cdef_object_array (const Array<cdef_object>& a)\n    : cdef_object_base (), m_array (a)\n  { }\n\n  cdef_object_array& operator = (const cdef_object_array&) = delete;\n\n  ~cdef_object_array () = default;\n\n  OCTINTERP_API cdef_object_rep * clone () const;\n\n  dim_vector dims () const { return m_array.dims (); }\n\n  OCTINTERP_API void\n  break_closure_cycles (const std::shared_ptr<stack_frame>& frame);\n\n  bool is_valid () const { return true; }\n\n  bool is_array () const { return true; }\n\n  Array<cdef_object> array_value () const { return m_array; }\n\n  OCTINTERP_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int nargout, std::size_t& skip, const cdef_class& context,\n           bool auto_add);\n\n  OCTINTERP_API octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  OCTINTERP_API octave_value reshape (const dim_vector& new_dims) const;\n\n  void set_property (octave_idx_type idx, const std::string& pname,\n                     const octave_value& pval)\n  {\n    cdef_object& tmp = m_array.elem (idx);\n\n    return tmp.put (pname, pval);\n  }\n\n  octave_value\n  get_property (octave_idx_type idx, const std::string& pname) const\n  {\n    cdef_object tmp = m_array.elem (idx);\n\n    return tmp.get (pname);\n  }\n\n  OCTINTERP_API cdef_object_rep *\n  permute (const Array<int>& vec, bool inv = false) const;\n\n  OCTINTERP_API cdef_object_rep *\n  resize (const dim_vector& dv, bool fill = false) const;\n\n  cdef_object_rep * transpose () const;\n\n  void fill_empty_values () { fill_empty_values (m_array); }\n\n  OCTINTERP_API void fill_empty_values (Array<cdef_object>& arr);\n\n  OCTINTERP_API void mark_as_constructed ();\n\n  OCTINTERP_API void mark_as_constructed (const cdef_class& cls);\n\n  OCTINTERP_API std::size_t byte_size () const;\n\nprivate:\n\n  Array<cdef_object> m_array;\n\n  // Private copying!\n  cdef_object_array (const cdef_object_array& obj)\n    : cdef_object_base (obj), m_array (obj.m_array)\n  { }\n};\n\nclass OCTINTERP_API cdef_object_scalar : public cdef_object_base\n{\npublic:\n\n  cdef_object_scalar () : cdef_object_base () { }\n\n  cdef_object_scalar& operator = (const cdef_object_scalar&) = delete;\n\n  ~cdef_object_scalar () = default;\n\n  dim_vector dims () const { return dim_vector (1, 1); }\n\n  void break_closure_cycles (const std::shared_ptr<stack_frame>& frame);\n\n  void put (const std::string& pname, const octave_value& val)\n  {\n    m_map.assign (pname, val);\n  }\n\n  octave_value get (const std::string& pname) const\n  {\n    Cell val = m_map.contents (pname);\n\n    if (val.numel () < 1)\n      error (\"get: unknown slot: %s\", pname.c_str ());\n\n    return val(0, 0);\n  }\n\n  void set_property (octave_idx_type idx, const std::string& pname,\n                     const octave_value& pval)\n  {\n    if (idx != 0)\n      error (\"invalid index\");  // FIXME\n\n    put (pname, pval);\n  }\n\n  octave_value\n  get_property (octave_idx_type idx, const std::string& pname) const\n  {\n    if (idx != 0)\n      error (\"invalid index\");  // FIXME\n\n    return get (pname);\n  }\n\n  OCTINTERP_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int nargout, std::size_t& skip, const cdef_class& context,\n           bool auto_add);\n\n  OCTINTERP_API octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  octave_value reshape (const dim_vector& new_dims) const;\n\n  cdef_object_rep *\n  permute ([[maybe_unused]] const Array<int>& vec,\n           [[maybe_unused]] bool inv = false) const\n  {\n    return clone ();\n  }\n\n  OCTINTERP_API cdef_object_rep *\n  resize (const dim_vector& dv, bool fill = false) const;\n\n  cdef_object_rep * transpose () const\n  {\n    return clone ();\n  }\n\n  OCTINTERP_API void mark_for_construction (const cdef_class&);\n\n  OCTINTERP_API bool is_constructed_for (const cdef_class& cls) const;\n\n  OCTINTERP_API bool\n  is_partially_constructed_for (const cdef_class& cls) const;\n\n  void mark_as_constructed () { m_ctor_list.clear (); }\n\n  OCTINTERP_API void mark_as_constructed (const cdef_class& cls);\n\n  bool is_constructed () const { return m_ctor_list.empty (); }\n\n  std::size_t byte_size () const { return m_map.byte_size (); }\n\nprotected:\n\n  // Object property values\n  octave_scalar_map m_map;\n\n  // Internal/temporary structure used during object construction\n  std::map< cdef_class, std::list<cdef_class>> m_ctor_list;\n\nprotected:\n\n  // Restricted object copying!\n  cdef_object_scalar (const cdef_object_scalar& obj)\n    : cdef_object_base (obj), m_map (obj.m_map), m_ctor_list (obj.m_ctor_list)\n  { }\n};\n\nclass OCTINTERP_API handle_cdef_object : public cdef_object_scalar\n{\npublic:\n\n  handle_cdef_object () : cdef_object_scalar () { }\n\n  handle_cdef_object& operator = (const handle_cdef_object&) = delete;\n\n  OCTINTERP_API ~handle_cdef_object ();\n\n  cdef_object_rep * clone () const\n  {\n    handle_cdef_object *obj = const_cast<handle_cdef_object *> (this);\n    obj->m_count++;\n    return obj;\n  }\n\n  cdef_object_rep * copy () const\n  {\n    return new handle_cdef_object (*this);\n  }\n\n  bool is_valid () const { return true; }\n\n  bool is_handle_object () const { return true; }\n\n  std::size_t byte_size () const { return sizeof (void *); }\n\nprotected:\n\n  // Restricted copying!\n  handle_cdef_object (const handle_cdef_object& obj)\n    : cdef_object_scalar (obj)\n  { }\n};\n\nclass OCTINTERP_API value_cdef_object : public cdef_object_scalar\n{\npublic:\n\n  value_cdef_object () : cdef_object_scalar () { }\n\n  value_cdef_object& operator = (const value_cdef_object&) = delete;\n\n  OCTINTERP_API ~value_cdef_object ();\n\n  cdef_object_rep * clone () const\n  {\n    return new value_cdef_object (*this);\n  }\n\n  cdef_object_rep * copy () const { return clone (); }\n\n  bool is_valid () const { return true; }\n\n  bool is_value_object () const { return true; }\n\nprivate:\n\n  // Private copying!\n  value_cdef_object (const value_cdef_object& obj)\n    : cdef_object_scalar (obj)\n  { }\n};\n\nclass OCTINTERP_API cdef_meta_object_rep : public handle_cdef_object\n{\npublic:\n\n  cdef_meta_object_rep () : handle_cdef_object () { }\n\n  cdef_meta_object_rep& operator = (const cdef_meta_object_rep&) = delete;\n\n  ~cdef_meta_object_rep () = default;\n\n  cdef_object_rep * copy () const\n  { return new cdef_meta_object_rep (*this); }\n\n  bool is_meta_object () const { return true; }\n\n  virtual bool is_class () const { return false; }\n\n  virtual bool is_property () const { return false; }\n\n  virtual bool is_method () const { return false; }\n\n  virtual bool is_package () const { return false; }\n\n  void doc_string (const std::string& txt) { m_doc_string = txt; }\n\n  std::string doc_string () const { return m_doc_string; }\n\n  virtual octave_value_list\n  meta_subsref (const std::string& /* type */,\n                const std::list<octave_value_list>& /* idx */,\n                int /* nargout */)\n  {\n    error (\"subsref: invalid meta object\");\n  }\n\n  virtual void meta_release () { }\n\n  virtual bool meta_accepts_postfix_index (char /* type */) const\n  {\n    return false;\n  }\n\nprotected:\n\n  std::string m_doc_string;\n\n  // Restricted copying!\n  cdef_meta_object_rep (const cdef_meta_object_rep& obj)\n    : handle_cdef_object (obj)\n  { }\n};\n\nclass OCTINTERP_API cdef_meta_object : public cdef_object\n{\npublic:\n\n  cdef_meta_object () : cdef_object () { }\n\n  // Object consistency is checked in sub-classes.\n  cdef_meta_object (const cdef_meta_object& obj) : cdef_object (obj) { }\n\n  cdef_meta_object (cdef_meta_object_rep *r) : cdef_object (r) { }\n\n  cdef_meta_object (const cdef_object& obj) : cdef_object (obj) { }\n\n  cdef_meta_object& operator = (const cdef_object&) = delete;\n\n  ~cdef_meta_object () = default;\n\n  bool is_class () const { return get_rep ()->is_class (); }\n\n  bool is_property () const { return get_rep ()->is_property (); }\n\n  bool is_method () const { return get_rep ()->is_method (); }\n\n  bool is_package () const { return get_rep ()->is_package (); }\n\n  void doc_string (const std::string& txt) { get_rep ()->doc_string (txt); }\n\n  std::string doc_string () const { return get_rep ()->doc_string (); }\n\n  octave_value_list\n  meta_subsref (const std::string& type,\n                const std::list<octave_value_list>& idx, int nargout)\n  {\n    return get_rep ()->meta_subsref (type, idx, nargout);\n  }\n\n  void meta_release () { get_rep ()->meta_release (); }\n\n  bool meta_accepts_postfix_index (char type) const\n  {\n    return get_rep ()->meta_accepts_postfix_index (type);\n  }\n\nprivate:\n\n  cdef_meta_object_rep * get_rep ()\n  {\n    return dynamic_cast<cdef_meta_object_rep *> (cdef_object::get_rep ());\n  }\n\n  const cdef_meta_object_rep * get_rep () const\n  {\n    return dynamic_cast<const cdef_meta_object_rep *> (cdef_object::get_rep ());\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/cdef-package.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"cdef-class.h\"\n#include \"cdef-manager.h\"\n#include \"cdef-utils.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ov-builtin.h\"\n#include \"ov-classdef.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pt-assign.h\"\n#include \"pt-classdef.h\"\n#include \"pt-idx.h\"\n#include \"pt-misc.h\"\n#include \"pt-stmt.h\"\n\n#define OCTAVE_CDEF_PACKAGE_DEBUG 0\n#if OCTAVE_CDEF_PACKAGE_DEBUG\n#  include <iostream>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\ncdef_package::cdef_package_rep::install_class (const cdef_class& cls,\n    const std::string& nm)\n{\n  m_class_map[nm] = cls;\n\n  m_member_count++;\n}\n\nvoid\ncdef_package::cdef_package_rep::install_function (const octave_value& fcn,\n    const std::string& nm)\n{\n  m_function_map[nm] = fcn;\n}\n\nvoid\ncdef_package::cdef_package_rep::install_package (const cdef_package& pack,\n    const std::string& nm)\n{\n  m_package_map[nm] = pack;\n\n  m_member_count++;\n}\n\ntemplate <typename T1, typename T2>\nCell\nmap2Cell (const std::map<T1, T2>& m)\n{\n  Cell retval (1, m.size ());\n  int i = 0;\n\n  for (const auto& it : m)\n    retval(i++) = to_ov (it.second);\n\n  return retval;\n}\n\nCell\ncdef_package::cdef_package_rep::get_classes () const\n{\n  return map2Cell (m_class_map);\n}\n\nCell\ncdef_package::cdef_package_rep::get_functions () const\n{\n  return map2Cell (m_function_map);\n}\n\nCell\ncdef_package::cdef_package_rep::get_packages () const\n{\n  return map2Cell (m_package_map);\n}\n\noctave_value\ncdef_package::cdef_package_rep::find (const std::string& nm)\n{\n  std::string symbol_name = get_name () + '.' + nm;\n\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.find (symbol_name);\n}\n\noctave_value_list\ncdef_package::cdef_package_rep::meta_subsref\n(const std::string& type, const std::list<octave_value_list>& idx,\n int nargout)\n{\n  octave_value_list retval;\n\n  switch (type[0])\n    {\n    case '.':\n      {\n        if (idx.front ().length () != 1)\n          error (\"invalid meta.package indexing\");\n\n        std::string nm = idx.front ()(0).xstring_value (\"invalid meta.package indexing, expected a symbol name\");\n\n#if OCTAVE_CDEF_PACKAGE_DEBUG\n        std::cerr << \"meta.package query: \" << nm << std::endl;\n#endif\n\n        octave_value o = find (nm);\n\n        if (! o.is_defined ())\n          error (\"member '%s' in package '%s' does not exist\",\n                 nm.c_str (), get_name ().c_str ());\n\n        if (o.is_function ())\n          {\n            octave_function *fcn = o.function_value ();\n\n            // NOTE: the case where the package query is the last\n            // part of this subsref index is handled in the parse\n            // tree, because there is some logic to handle magic\n            // \"end\" that makes it impossible to execute the\n            // function call at this stage.\n\n            if (type.size () > 1\n                && ! fcn->accepts_postfix_index (type[1]))\n              {\n                octave_value_list tmp_args;\n\n                interpreter& interp = __get_interpreter__ ();\n\n                retval = interp.feval (o, tmp_args, nargout);\n              }\n            else\n              retval(0) = o;\n\n            if (type.size () > 1 && idx.size () > 1)\n              retval = retval(0).next_subsref (nargout, type,\n                                               idx, 1);\n          }\n        else if (type.size () > 1 && idx.size () > 1)\n          retval = o.next_subsref (nargout, type, idx, 1);\n        else\n          retval(0) = o;\n      }\n      break;\n\n    default:\n      error (\"invalid meta.package indexing\");\n      break;\n    }\n\n  return retval;\n}\n\nvoid\ncdef_package::cdef_package_rep::meta_release ()\n{\n  // FIXME: Do we really want to unregister the package, as it\n  //        could still be referenced by classes or sub-packages?\n  //        If the package object is recreated later on, it won't\n  //        match the one already referenced by those classes or\n  //        sub-packages.\n\n  cdef_manager& cdm = __get_cdef_manager__ ();\n\n  // Don't delete the \"meta\" package.\n  if (this != cdm.meta ().get_rep ())\n    cdm.unregister_package (wrap ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/cdef-package.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cdef_package_h)\n#define octave_cdef_package_h 1\n\n#include \"octave-config.h\"\n\n#include <map>\n#include <set>\n#include <string>\n\n#include \"oct-refcount.h\"\n\n#include \"cdef-fwd.h\"\n#include \"cdef-object.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\nclass OCTINTERP_API cdef_package : public cdef_meta_object\n{\n  friend class cdef_class;\n\nprivate:\n\n  class cdef_package_rep : public cdef_meta_object_rep\n  {\n  public:\n\n    cdef_package_rep () : cdef_meta_object_rep (), m_member_count (0) { }\n\n    cdef_package_rep& operator = (const cdef_package_rep&) = delete;\n\n    ~cdef_package_rep () = default;\n\n    cdef_object_rep * copy () const\n    { return new cdef_package_rep (*this); }\n\n    bool is_package () const { return true; }\n\n    std::string get_name () const { return get(\"Name\").string_value (); }\n\n    void set_name (const std::string& nm) { put (\"Name\", nm); }\n\n    OCTINTERP_API void\n    install_class (const cdef_class& cls, const std::string& nm);\n\n    OCTINTERP_API void\n    install_function (const octave_value& fcn, const std::string& nm);\n\n    OCTINTERP_API void\n    install_package (const cdef_package& pack, const std::string& nm);\n\n    OCTINTERP_API Cell get_classes () const;\n\n    OCTINTERP_API Cell get_functions () const;\n\n    OCTINTERP_API Cell get_packages () const;\n\n    octave_idx_type static_count () const { return m_member_count; }\n\n    void destroy ()\n    {\n      if (m_member_count)\n        {\n          m_count++;\n          cdef_package lock (this);\n\n          m_member_count = 0;\n          m_class_map.clear ();\n          m_package_map.clear ();\n        }\n      else\n        delete this;\n    }\n\n    OCTINTERP_API octave_value_list\n    meta_subsref (const std::string& type,\n                  const std::list<octave_value_list>& idx, int nargout);\n\n    OCTINTERP_API void meta_release ();\n\n    bool meta_accepts_postfix_index (char type) const\n    {\n      return (type == '.');\n    }\n\n    OCTINTERP_API octave_value find (const std::string& nm);\n\n  private:\n\n    std::string m_full_name;\n    std::map<std::string, cdef_class> m_class_map;\n    std::map<std::string, octave_value> m_function_map;\n    std::map<std::string, cdef_package> m_package_map;\n\n    // The number of registered members in this package (classes, packages).\n    // This only accounts for the members that back-reference to this package.\n    octave_idx_type m_member_count;\n\n    typedef std::map<std::string, cdef_class>::iterator class_iterator;\n    typedef std::map<std::string, cdef_class>::const_iterator class_const_iterator;\n    typedef std::map<std::string, octave_value>::iterator function_iterator;\n    typedef std::map<std::string, octave_value>::const_iterator\n      function_const_iterator;\n    typedef std::map<std::string, cdef_package>::iterator package_iterator;\n    typedef std::map<std::string, cdef_package>::const_iterator\n      package_const_iterator;\n\n    cdef_package_rep (const cdef_package_rep& p)\n      : cdef_meta_object_rep (p), m_full_name (p.m_full_name),\n        m_class_map (p.m_class_map), m_function_map (p.m_function_map),\n        m_package_map (p.m_package_map), m_member_count (p.m_member_count)\n    { }\n\n    cdef_package wrap ()\n    {\n      m_count++;\n      return cdef_package (this);\n    }\n  };\n\npublic:\n\n  cdef_package () : cdef_meta_object () { }\n\n  cdef_package (const std::string& nm)\n    : cdef_meta_object (new cdef_package_rep ())\n  {\n    get_rep ()->set_name (nm);\n  }\n\n  cdef_package (const cdef_package& pack) : cdef_meta_object (pack) { }\n\n  cdef_package (const cdef_object& obj)\n    : cdef_meta_object (obj)\n  {\n    // This should never happen...\n    if (! is_package ())\n      error (\"internal error: invalid assignment from %s to meta.package object\",\n             class_name ().c_str ());\n  }\n\n  cdef_package& operator = (const cdef_package& pack)\n  {\n    cdef_object::operator = (pack);\n\n    return *this;\n  }\n\n  ~cdef_package () = default;\n\n  void install_class (const cdef_class& cls, const std::string& nm)\n  {\n    get_rep ()->install_class (cls, nm);\n  }\n\n  void install_function (const octave_value& fcn, const std::string& nm)\n  {\n    get_rep ()->install_function (fcn, nm);\n  }\n\n  void install_package (const cdef_package& pack, const std::string& nm)\n  {\n    get_rep ()->install_package (pack, nm);\n  }\n\n  Cell get_classes () const\n  {\n    return get_rep ()->get_classes ();\n  }\n\n  Cell get_functions () const\n  {\n    return get_rep ()->get_functions ();\n  }\n\n  Cell get_packages () const\n  {\n    return get_rep ()->get_packages ();\n  }\n\n  std::string get_name () const { return get_rep ()->get_name (); }\n\n  octave_value find (const std::string& nm)\n  {\n    return get_rep ()->find (nm);\n  }\n\nprivate:\n\n  cdef_package_rep * get_rep ()\n  {\n    return dynamic_cast<cdef_package_rep *> (cdef_object::get_rep ());\n  }\n\n  const cdef_package_rep * get_rep () const\n  {\n    return dynamic_cast<const cdef_package_rep *> (cdef_object::get_rep ());\n  }\n\n  friend void install_classdef (octave::interpreter& interp);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/cdef-property.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"cdef-class.h\"\n#include \"cdef-manager.h\"\n#include \"cdef-utils.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ov-builtin.h\"\n#include \"ov-classdef.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pt-assign.h\"\n#include \"pt-classdef.h\"\n#include \"pt-eval.h\"\n#include \"pt-idx.h\"\n#include \"pt-misc.h\"\n#include \"pt-stmt.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic bool\nis_method_executing (const octave_value& ov, const cdef_object& obj)\n{\n  tree_evaluator& tw = __get_evaluator__ ();\n\n  octave_function *stack_fcn = tw.current_function ();\n\n  octave_function *method_fcn = ov.function_value (true);\n\n  // Does the top of the call stack match our target function?\n\n  if (stack_fcn && stack_fcn == method_fcn)\n    {\n      octave_user_function *uf = method_fcn->user_function_value (true);\n\n      // We can only check the context object for user-function (not builtin),\n      // where we have access to the parameters (arguments and return values).\n      // That's ok as there's no need to call this function for builtin\n      // methods.\n\n      if (uf)\n        {\n          // At this point, the method is executing, but we still need to\n          // check the context object for which the method is executing.  For\n          // methods, it's the first argument of the function; for ctors, it\n          // is the first return value.\n\n          tree_parameter_list *pl = uf->is_classdef_constructor ()\n                                    ? uf->return_list ()\n                                    : uf->parameter_list ();\n\n          if (pl && pl->size () > 0)\n            {\n              tree_decl_elt *elt = pl->front ();\n\n              octave_value arg0 = tw.evaluate (elt);\n\n              if (arg0.is_defined () && arg0.type_name () == \"object\")\n                {\n                  cdef_object arg0_obj = to_cdef (arg0);\n\n                  return obj.is (arg0_obj);\n                }\n            }\n        }\n    }\n\n  return false;\n}\n\noctave_value\ncdef_property::cdef_property_rep::get_value (const cdef_object& obj,\n    bool do_check_access,\n    const std::string& who) const\n{\n  octave_value retval;\n\n  if (do_check_access && ! check_get_access ())\n    err_property_access (who, false);\n\n  if (! obj.is_constructed ())\n    {\n      cdef_class cls (to_cdef (get (\"DefiningClass\")));\n\n      if (! obj.is_partially_constructed_for (cls))\n        error (\"cannot reference properties of class '%s' for non-constructed object\",\n               cls.get_name ().c_str ());\n    }\n\n  octave_value get_fcn = get (\"GetMethod\");\n\n  // FIXME: should check whether we're already in get accessor method\n\n  if (get_fcn.isempty () || is_method_executing (get_fcn, obj))\n    retval = obj.get (get (\"Name\").string_value ());\n  else\n    {\n      octave_value_list args;\n\n      args(0) = to_ov (obj);\n\n      interpreter& interp = __get_interpreter__ ();\n\n      args = interp.feval (get_fcn, args, 1);\n\n      retval = args(0);\n    }\n\n  return retval;\n}\n\noctave_value\ncdef_property::cdef_property_rep::get_value (bool do_check_access,\n    const std::string& who) const\n{\n  if (do_check_access && ! check_get_access ())\n    err_property_access (who, false);\n\n  return get (\"DefaultValue\");\n}\n\nbool\ncdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const\n{\n  // FIXME: implement\n  return false;\n}\n\nOCTAVE_NORETURN void\ncdef_property::cdef_property_rep::err_property_access\n(const std::string& from, bool is_set) const\n{\n  octave_value acc = get (is_set ? \"SetAccess\" : \"GetAccess\");\n  std::string acc_s;\n\n  if (acc.is_string ())\n    acc_s = acc.string_value ();\n  else\n    acc_s = \"class-restricted\";\n\n  if (is_set)\n    error (\"%s: property '%s' has %s access and cannot be set in this context\",\n           from.c_str (), get_name ().c_str (), acc_s.c_str ());\n  else\n    error (\"%s: property '%s' has %s access and cannot be obtained in this context\",\n           from.c_str (), get_name ().c_str (), acc_s.c_str ());\n}\n\nvoid\ncdef_property::cdef_property_rep::set_value (cdef_object& obj,\n    const octave_value& val,\n    bool do_check_access,\n    const std::string& who)\n{\n  if (do_check_access && ! check_set_access ())\n    err_property_access (who, true);\n\n  if (! obj.is_constructed ())\n    {\n      cdef_class cls (to_cdef (get (\"DefiningClass\")));\n\n      if (! obj.is_partially_constructed_for (cls))\n        error (\"cannot reference properties of class '%s' for non-constructed object\",\n               cls.get_name ().c_str ());\n    }\n\n  octave_value set_fcn = get (\"SetMethod\");\n\n  if (set_fcn.isempty () || is_method_executing (set_fcn, obj))\n    obj.put (get (\"Name\").string_value (), val);\n  else\n    {\n      octave_value_list args;\n\n      args(0) = to_ov (obj);\n      args(1) = val;\n\n      interpreter& interp = __get_interpreter__ ();\n\n      if (obj.is_handle_object ())\n        interp.feval (set_fcn, args, 0);\n      else\n        {\n          args = interp.feval (set_fcn, args, 1);\n\n          if (args.length () > 0 && args(0).is_defined ())\n            {\n              if (args(0).is_classdef_object ())\n                {\n                  cdef_object new_obj = to_cdef (args(0));\n\n                  obj = new_obj;\n                }\n              else\n                ::warning (\"set-method of property '%s' returned a non-classdef object\",\n                           get_name ().c_str ());\n            }\n        }\n    }\n}\n\nbool\ncdef_property::cdef_property_rep::check_get_access () const\n{\n  cdef_class cls (to_cdef (get (\"DefiningClass\")));\n\n  return check_access (cls, get (\"GetAccess\"), \"\", get_name (), false);\n\n  return false;\n}\n\nbool\ncdef_property::cdef_property_rep::check_set_access () const\n{\n  cdef_class cls (to_cdef (get (\"DefiningClass\")));\n\n  return check_access (cls, get (\"SetAccess\"), \"\", get_name (), true);\n\n  return false;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/cdef-property.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cdef_property_h)\n#define octave_cdef_property_h 1\n\n#include \"octave-config.h\"\n\n#include <map>\n#include <set>\n#include <string>\n\n#include \"oct-refcount.h\"\n\n#include \"cdef-object.h\"\n#include \"error.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API cdef_property : public cdef_meta_object\n{\n  friend class cdef_class;\n\nprivate:\n\n  class cdef_property_rep : public cdef_meta_object_rep\n  {\n  public:\n\n    cdef_property_rep () : cdef_meta_object_rep () { }\n\n    cdef_property_rep& operator = (const cdef_property_rep& p) = delete;\n\n    ~cdef_property_rep () = default;\n\n    cdef_object_rep * copy () const\n    {\n      return new cdef_property_rep (*this);\n    }\n\n    bool is_property () const { return true; }\n\n    std::string get_name () const { return get(\"Name\").string_value (); }\n\n    void set_name (const std::string& nm) { put (\"Name\", nm); }\n\n    bool is_constant () const { return get(\"Constant\").bool_value (); }\n\n    octave_value get_value (bool do_check_access = true,\n                            const std::string& who = \"\") const;\n\n    octave_value get_value (const cdef_object& obj,\n                            bool do_check_access = true,\n                            const std::string& who = \"\") const;\n\n    void set_value (cdef_object& obj, const octave_value& val,\n                    bool do_check_access = true,\n                    const std::string& who = \"\");\n\n    OCTINTERP_API bool check_get_access () const;\n\n    OCTINTERP_API bool check_set_access () const;\n\n  private:\n    cdef_property_rep (const cdef_property_rep& p)\n      : cdef_meta_object_rep (p)\n    { }\n\n    OCTINTERP_API bool is_recursive_set (const cdef_object& obj) const;\n\n    cdef_property wrap ()\n    {\n      m_count++;\n      return cdef_property (this);\n    }\n\n    OCTAVE_NORETURN OCTINTERP_API\n    void err_property_access (const std::string& from,\n                              bool is_set = false) const;\n  };\n\npublic:\n\n  cdef_property () : cdef_meta_object () { }\n\n  cdef_property (const std::string& nm)\n    : cdef_meta_object (new cdef_property_rep ())\n  {\n    get_rep ()->set_name (nm);\n  }\n\n  cdef_property (const cdef_property& prop) : cdef_meta_object (prop) { }\n\n  cdef_property (const cdef_object& obj)\n    : cdef_meta_object (obj)\n  {\n    // This should never happen...\n    if (! is_property ())\n      error (\"internal error: invalid assignment from %s to meta.property object\",\n             class_name ().c_str ());\n  }\n\n  cdef_property& operator = (const cdef_property& prop)\n  {\n    cdef_object::operator = (prop);\n\n    return *this;\n  }\n\n  ~cdef_property () = default;\n\n  octave_value get_value (const cdef_object& obj, bool do_check_access = true,\n                          const std::string& who = \"\") const\n  {\n    return get_rep ()->get_value (obj, do_check_access, who);\n  }\n\n  octave_value get_value (bool do_check_access = true,\n                          const std::string& who = \"\") const\n  {\n    return get_rep ()->get_value (do_check_access, who);\n  }\n\n  void set_value (cdef_object& obj, const octave_value& val,\n                  bool do_check_access = true,\n                  const std::string& who = \"\")\n  {\n    get_rep ()->set_value (obj, val, do_check_access, who);\n  }\n\n  bool check_get_access () const\n  {\n    return get_rep ()->check_get_access ();\n  }\n\n  bool check_set_access () const\n  {\n    return get_rep ()->check_set_access ();\n  }\n\n  std::string get_name () const { return get_rep ()->get_name (); }\n\n  bool is_constant () const { return get_rep ()->is_constant (); }\n\nprivate:\n\n  cdef_property_rep * get_rep ()\n  {\n    return dynamic_cast<cdef_property_rep *> (cdef_object::get_rep ());\n  }\n\n  const cdef_property_rep * get_rep () const\n  {\n    return dynamic_cast<const cdef_property_rep *> (cdef_object::get_rep ());\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/cdef-utils.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"cdef-class.h\"\n#include \"cdef-manager.h\"\n#include \"cdef-method.h\"\n#include \"cdef-package.h\"\n#include \"cdef-property.h\"\n#include \"cdef-utils.h\"\n#include \"interpreter-private.h\"\n#include \"ov-classdef.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pt-eval.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstd::string\nget_base_name (const std::string& nm)\n{\n  std::string::size_type pos = nm.find_last_of ('.');\n\n  if (pos != std::string::npos)\n    return nm.substr (pos + 1);\n\n  return nm;\n}\n\nvoid\nmake_function_of_class (const std::string& class_name,\n                        const octave_value& fcn)\n{\n  octave_function *of = fcn.function_value ();\n\n  of->stash_dispatch_class (class_name);\n\n  octave_user_function *uf = of->user_function_value (true);\n\n  if (uf)\n    {\n      if (get_base_name (class_name) == uf->name ())\n        uf->mark_as_classdef_constructor ();\n      else\n        uf->mark_as_classdef_method ();\n    }\n}\n\nvoid\nmake_function_of_class (const cdef_class& cls, const octave_value& fcn)\n{\n  make_function_of_class (cls.get_name (), fcn);\n}\n\ncdef_class\nlookup_class (const std::string& name, bool error_if_not_found,\n              bool load_if_not_found)\n{\n  cdef_manager& cdm = __get_cdef_manager__ ();\n\n  return cdm.find_class (name, error_if_not_found, load_if_not_found);\n}\n\ncdef_class\nlookup_class (const cdef_class& cls)\n{\n  // FIXME: placeholder for the time being, the purpose\n  //        is to centralized any class update activity here.\n\n  return cls;\n}\n\ncdef_class\nlookup_class (const octave_value& ov)\n{\n  if (ov.is_string())\n    return lookup_class (ov.string_value ());\n  else\n    {\n      cdef_class cls (to_cdef (ov));\n\n      return lookup_class (cls);\n    }\n\n  return cdef_class ();\n}\n\nstd::list<cdef_class>\nlookup_classes (const Cell& cls_list)\n{\n  std::list<cdef_class> retval;\n\n  for (int i = 0; i < cls_list.numel (); i++)\n    {\n      cdef_class c = lookup_class (cls_list(i));\n\n      retval.push_back (c);\n    }\n\n  return retval;\n}\n\noctave_value\nto_ov (const cdef_object& obj)\n{\n  if (obj.ok ())\n    return octave_value (new octave_classdef (obj));\n  else\n    return octave_value (Matrix ());\n}\n\noctave_value\nto_ov (const octave_value& ov)\n{\n  return ov;\n}\n\ncdef_object\nto_cdef (const octave_value& val)\n{\n  if (val.type_name () != \"object\")\n    error (\"cannot convert '%s' into 'object'\", val.type_name().c_str ());\n\n  return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object ();\n}\n\ncdef_object&\nto_cdef_ref (const octave_value& val)\n{\n  if (val.type_name () != \"object\")\n    error (\"cannot convert '%s' into 'object'\", val.type_name().c_str ());\n\n  return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object_ref ();\n}\n\ncdef_object\nto_cdef (const cdef_object& obj)\n{\n  return obj;\n}\n\noctave_value\nto_ov (const std::list<cdef_class>& class_list)\n{\n  Cell cls (class_list.size (), 1);\n  int i = 0;\n\n  for (const auto& cdef_cls : class_list)\n    cls(i++) = to_ov (cdef_cls);\n\n  return octave_value (cls);\n}\n\nbool\nis_dummy_method (const octave_value& fcn)\n{\n  bool retval = false;\n\n  if (fcn.is_defined ())\n    {\n      if (fcn.is_user_function ())\n        {\n          octave_user_function *uf = fcn.user_function_value (true);\n\n          if (! uf || ! uf->body ())\n            retval = true;\n        }\n    }\n  else\n    retval = true;\n\n  return retval;\n}\n\nbool\nis_superclass (const cdef_class& clsa, const cdef_class& clsb,\n               bool allow_equal, int max_depth)\n{\n  bool retval = false;\n\n  if (allow_equal && clsa == clsb)\n    retval = true;\n  else if (max_depth != 0)\n    {\n      Cell c = clsb.get (\"SuperClasses\").cell_value ();\n\n      for (int i = 0; ! retval && i < c.numel (); i++)\n        {\n          octave_classdef *metacls = c(i).classdef_object_value ();\n          std::string clsname = metacls->get_property (0, \"Name\").string_value ();\n          cdef_class cls = lookup_class (clsname);\n\n          retval = is_superclass (clsa, cls, true,\n                                  max_depth < 0 ? max_depth : max_depth-1);\n        }\n    }\n\n  return retval;\n}\n\nbool\nis_strict_superclass (const cdef_class& clsa, const cdef_class& clsb)\n{\n  return is_superclass (clsa, clsb, false);\n}\n\nbool\nis_direct_superclass (const cdef_class& clsa, const cdef_class& clsb)\n{\n  return is_superclass (clsa, clsb, false, 1);\n}\n\ncdef_package\nlookup_package (const std::string& name, bool error_if_not_found,\n                bool load_if_not_found)\n{\n  cdef_manager& cdm = __get_cdef_manager__ ();\n\n  return cdm.find_package (name, error_if_not_found, load_if_not_found);\n}\n\ncdef_class\nget_class_context (std::string& name, bool& in_constructor)\n{\n  name = \"\";\n  in_constructor = false;\n\n  cdef_class cls;\n\n  // If the dispatch class is set in the current stack frame it\n  // overrides whatever dispatch class there is for the currently\n  // executing function so that function handles returned from class\n  // methods will use the dispatch class of the class in which they\n  // are defined instead of the class in which they are executing.\n\n  tree_evaluator& tw = __get_evaluator__ ();\n\n  std::string dispatch_class = tw.get_dispatch_class ();\n\n  if (! dispatch_class.empty ())\n    return lookup_class (dispatch_class);\n\n  octave_function *fcn = tw.current_function ();\n\n  if (fcn && (fcn->is_class_method ()\n              || fcn->is_classdef_constructor ()\n              || fcn->is_anonymous_function_of_class ()\n              || (fcn->is_private_function ()\n                  && ! fcn->dispatch_class ().empty ())))\n    {\n      cls = lookup_class (fcn->dispatch_class ());\n\n      name = fcn->name ();\n      in_constructor = fcn->is_classdef_constructor ();\n    }\n\n  return cls;\n}\n\ncdef_class\nget_class_context ()\n{\n  std::string dummy_string;\n  bool dummy_bool;\n\n  return get_class_context (dummy_string, dummy_bool);\n}\n\nbool\ncheck_access (const cdef_class& cls, const octave_value& acc,\n              const std::string& meth_name, const std::string& prop_name,\n              bool is_prop_set)\n{\n  if (acc.is_string ())\n    {\n      std::string acc_s = acc.string_value ();\n\n      if (acc_s == \"public\")\n        return true;\n\n      cdef_class ctx = get_class_context ();\n\n      // The access is private or protected, this requires a\n      // valid class context.\n\n      if (ctx.ok ())\n        {\n          if (acc_s == \"private\")\n            return (ctx == cls);\n          else if (acc_s == \"protected\")\n            {\n              if (is_superclass (cls, ctx))\n                // Calling a protected method in a superclass.\n                return true;\n              else if (is_strict_superclass (ctx, cls))\n                {\n                  // Calling a protected method or property in a derived\n                  // class.  This is only allowed if the context class knows\n                  // about it and has access to it.\n\n                  if (! meth_name.empty ())\n                    {\n                      cdef_method m = ctx.find_method (meth_name);\n\n                      if (m.ok ())\n                        return check_access (ctx,\n                                             m.get (\"Access\"), meth_name);\n\n                      return false;\n                    }\n                  else if (! prop_name.empty ())\n                    {\n                      cdef_property p = ctx.find_property (prop_name);\n\n                      if (p.ok ())\n                        {\n                          octave_value p_access = p.get (is_prop_set ?\n                                                         \"SetAccess\" :\n                                                         \"GetAccess\");\n\n                          return check_access (ctx, p_access, meth_name,\n                                               prop_name, is_prop_set);\n                        }\n\n                      return false;\n                    }\n                  else\n                    error (\"check_access: expecting private or protected access specifier - please report this bug\");\n                }\n\n              return false;\n            }\n          else\n            error (\"check_access: expecting a method or property name - please report this bug\");\n        }\n    }\n  else if (acc.isobject ())\n    {\n      cdef_class ctx = get_class_context ();\n\n      // At this point, a class context is always required.\n      if (ctx.ok ())\n        {\n          if (ctx == cls)\n            return true;\n\n          cdef_class acc_cls (to_cdef (acc));\n\n          if (is_superclass (acc_cls, ctx))\n            return true;\n        }\n    }\n  else if (acc.iscell ())\n    {\n      Cell acc_c = acc.cell_value ();\n\n      cdef_class ctx = get_class_context ();\n\n      // At this point, a class context is always required.\n\n      if (ctx.ok ())\n        {\n          if (ctx == cls)\n            return true;\n\n          for (int i = 0; i < acc.numel (); i++)\n            {\n              cdef_class acc_cls (to_cdef (acc_c(i)));\n\n              if (is_superclass (acc_cls, ctx))\n                return true;\n            }\n        }\n    }\n  else\n    error (\"invalid property/method access in class '%s'\",\n           cls.get_name ().c_str ());\n\n  return false;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/cdef-utils.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cdef_utils_h)\n#define octave_cdef_utils_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n\n#include \"cdef-fwd.h\"\n\nclass octave_value;\nclass Cell;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API std::string\nget_base_name (const std::string& nm);\n\nextern OCTINTERP_API void\nmake_function_of_class (const std::string& class_name,\n                        const octave_value& fcn);\n\nextern OCTINTERP_API void\nmake_function_of_class (const cdef_class& cls, const octave_value& fcn);\n\nextern OCTINTERP_API cdef_class\nlookup_class (const std::string& name, bool error_if_not_found = true,\n              bool load_if_not_found = true);\n\nextern OCTINTERP_API cdef_class\nlookup_class (const cdef_class& cls);\n\nextern OCTINTERP_API cdef_class\nlookup_class (const octave_value& ov);\n\nextern OCTINTERP_API std::list<cdef_class>\nlookup_classes (const Cell& cls_list);\n\nextern OCTINTERP_API octave_value\nto_ov (const cdef_object& obj);\n\nextern OCTINTERP_API octave_value\nto_ov (const octave_value& ov);\n\nextern OCTINTERP_API cdef_object\nto_cdef (const octave_value& val);\n\nextern OCTINTERP_API cdef_object&\nto_cdef_ref (const octave_value& val);\n\nextern OCTINTERP_API cdef_object\nto_cdef (const cdef_object& obj);\n\nextern OCTINTERP_API octave_value\nto_ov (const std::list<cdef_class>& class_list);\n\nextern OCTINTERP_API bool\nis_dummy_method (const octave_value& fcn);\n\nextern OCTINTERP_API bool\nis_superclass (const cdef_class& clsa, const cdef_class& clsb,\n               bool allow_equal = true, int max_depth = -1);\nextern OCTINTERP_API bool\nis_strict_superclass (const cdef_class& clsa, const cdef_class& clsb);\n\nextern OCTINTERP_API bool\nis_direct_superclass (const cdef_class& clsa, const cdef_class& clsb);\n\nextern OCTINTERP_API cdef_package\nlookup_package (const std::string& name, bool error_if_not_found = true,\n                bool load_if_not_found = true);\n\nextern OCTINTERP_API cdef_class\nget_class_context (std::string& name, bool& in_constructor);\n\nextern OCTINTERP_API cdef_class\nget_class_context ();\n\nextern OCTINTERP_API bool\ncheck_access (const cdef_class& cls, const octave_value& acc,\n              const std::string& meth_name = \"\",\n              const std::string& prop_name = \"\",\n              bool is_prop_set = false);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/module.mk",
    "content": "OV_INTTYPE_INC = \\\n  %reldir%/ov-base-int.h \\\n  %reldir%/ov-int-traits.h \\\n  %reldir%/ov-int16.h \\\n  %reldir%/ov-int32.h \\\n  %reldir%/ov-int64.h \\\n  %reldir%/ov-int8.h \\\n  %reldir%/ov-intx.h \\\n  %reldir%/ov-uint16.h \\\n  %reldir%/ov-uint32.h \\\n  %reldir%/ov-uint64.h \\\n  %reldir%/ov-uint8.h\n\nOV_SPARSE_INC = \\\n  %reldir%/ov-base-sparse.h \\\n  %reldir%/ov-bool-sparse.h \\\n  %reldir%/ov-cx-sparse.h \\\n  %reldir%/ov-re-sparse.h\n\nOCTAVE_VALUE_INC = \\\n  %reldir%/cdef-class.h \\\n  %reldir%/cdef-fwd.h \\\n  %reldir%/cdef-manager.h \\\n  %reldir%/cdef-method.h \\\n  %reldir%/cdef-object.h \\\n  %reldir%/cdef-package.h \\\n  %reldir%/cdef-property.h \\\n  %reldir%/cdef-utils.h \\\n  %reldir%/ov-base-diag.h \\\n  %reldir%/ov-base-mat.h \\\n  %reldir%/ov-base-scalar.h \\\n  %reldir%/ov-base.h \\\n  %reldir%/ov-bool-mat.h \\\n  %reldir%/ov-bool.h \\\n  %reldir%/ov-builtin.h \\\n  %reldir%/ov-cell.h \\\n  %reldir%/ov-ch-mat.h \\\n  %reldir%/ov-class.h \\\n  %reldir%/ov-classdef.h \\\n  %reldir%/ov-colon.h \\\n  %reldir%/ov-complex.h \\\n  %reldir%/ov-cs-list.h \\\n  %reldir%/ov-cx-diag.h \\\n  %reldir%/ov-cx-mat.h \\\n  %reldir%/ov-dld-fcn.h \\\n  %reldir%/ov-fcn-handle.h \\\n  %reldir%/ov-fcn.h \\\n  %reldir%/ov-float.h \\\n  %reldir%/ov-flt-complex.h \\\n  %reldir%/ov-flt-cx-diag.h \\\n  %reldir%/ov-flt-cx-mat.h \\\n  %reldir%/ov-flt-re-diag.h \\\n  %reldir%/ov-flt-re-mat.h \\\n  %reldir%/ov-inline.h \\\n  %reldir%/ov-java.h \\\n  %reldir%/ov-lazy-idx.h \\\n  %reldir%/ov-legacy-range.h \\\n  %reldir%/ov-magic-int.h \\\n  %reldir%/ov-mex-fcn.h \\\n  %reldir%/ov-null-mat.h \\\n  %reldir%/ov-oncleanup.h \\\n  %reldir%/ov-perm.h \\\n  %reldir%/ov-range-traits.h \\\n  %reldir%/ov-range.h \\\n  %reldir%/ov-re-diag.h \\\n  %reldir%/ov-re-mat.h \\\n  %reldir%/ov-scalar.h \\\n  %reldir%/ov-str-mat.h \\\n  %reldir%/ov-struct.h \\\n  %reldir%/ov-typeinfo.h \\\n  %reldir%/ov-usr-fcn.h \\\n  %reldir%/ov.h \\\n  %reldir%/ovl.h \\\n  $(OV_INTTYPE_INC) \\\n  $(OV_SPARSE_INC)\n\nOV_INTTYPE_SRC = \\\n  %reldir%/ov-int16.cc \\\n  %reldir%/ov-int32.cc \\\n  %reldir%/ov-int64.cc \\\n  %reldir%/ov-int8.cc \\\n  %reldir%/ov-uint16.cc \\\n  %reldir%/ov-uint32.cc \\\n  %reldir%/ov-uint64.cc \\\n  %reldir%/ov-uint8.cc\n\nOV_SPARSE_SRC = \\\n  %reldir%/ov-bool-sparse.cc \\\n  %reldir%/ov-cx-sparse.cc \\\n  %reldir%/ov-re-sparse.cc\n\nOCTAVE_VALUE_SRC = \\\n  %reldir%/cdef-class.cc \\\n  %reldir%/cdef-manager.cc \\\n  %reldir%/cdef-method.cc \\\n  %reldir%/cdef-object.cc \\\n  %reldir%/cdef-package.cc \\\n  %reldir%/cdef-property.cc \\\n  %reldir%/cdef-utils.cc \\\n  %reldir%/ov-base-diag-inst.cc \\\n  %reldir%/ov-base-int-inst.cc \\\n  %reldir%/ov-base-mat-inst.cc \\\n  %reldir%/ov-base-scalar-inst.cc \\\n  %reldir%/ov-base-sparse-inst.cc \\\n  %reldir%/ov-base.cc \\\n  %reldir%/ov-bool-mat.cc \\\n  %reldir%/ov-bool.cc \\\n  %reldir%/ov-builtin.cc \\\n  %reldir%/ov-cell.cc \\\n  %reldir%/ov-ch-mat.cc \\\n  %reldir%/ov-class.cc \\\n  %reldir%/ov-classdef.cc \\\n  %reldir%/ov-colon.cc \\\n  %reldir%/ov-complex.cc \\\n  %reldir%/ov-cs-list.cc \\\n  %reldir%/ov-cx-diag.cc \\\n  %reldir%/ov-cx-mat.cc \\\n  %reldir%/ov-dld-fcn.cc \\\n  %reldir%/ov-fcn-handle.cc \\\n  %reldir%/ov-fcn.cc \\\n  %reldir%/ov-float.cc \\\n  %reldir%/ov-flt-complex.cc \\\n  %reldir%/ov-flt-cx-diag.cc \\\n  %reldir%/ov-flt-cx-mat.cc \\\n  %reldir%/ov-flt-re-diag.cc \\\n  %reldir%/ov-flt-re-mat.cc \\\n  %reldir%/ov-java.cc \\\n  %reldir%/ov-lazy-idx.cc \\\n  %reldir%/ov-legacy-range.cc \\\n  %reldir%/ov-magic-int.cc \\\n  %reldir%/ov-mex-fcn.cc \\\n  %reldir%/ov-null-mat.cc \\\n  %reldir%/ov-oncleanup.cc \\\n  %reldir%/ov-perm.cc \\\n  %reldir%/ov-range.cc \\\n  %reldir%/ov-re-diag.cc \\\n  %reldir%/ov-re-mat.cc \\\n  %reldir%/ov-scalar.cc \\\n  %reldir%/ov-str-mat.cc \\\n  %reldir%/ov-struct.cc \\\n  %reldir%/ov-typeinfo.cc \\\n  %reldir%/ov-usr-fcn.cc \\\n  %reldir%/ov.cc \\\n  %reldir%/ovl.cc \\\n  $(OV_INTTYPE_SRC) \\\n  $(OV_SPARSE_SRC)\n\n## These source files contain template definitions that are included\n## in other files.  They are not supposed to be compiled separately,\n## so they should not appear in the OCTAVE_VALUE_SRC list.\n\nLIBINTERP_TEMPLATE_SRC += \\\n  %reldir%/ov-base-diag.cc \\\n  %reldir%/ov-base-int.cc \\\n  %reldir%/ov-base-mat.cc \\\n  %reldir%/ov-base-scalar.cc \\\n  %reldir%/ov-base-sparse.cc\n\nnoinst_LTLIBRARIES += %reldir%/liboctave-value.la\n\n%canon_reldir%_liboctave_value_la_SOURCES = $(OCTAVE_VALUE_SRC)\n\n## FIXME: maybe it would be better to limit the JAVA flags to\n## the compile commands for ov-java.cc?  Does JAVA_LIBS need to be\n## added to LIBOCTINTERP_LINK_DEPS (see libinterp/link-deps.mk)?\n## Should we have a separate set of JAVA_LDFLAGS?\n\n%canon_reldir%_liboctave_value_la_CPPFLAGS = \\\n  $(libinterp_liboctinterp_la_CPPFLAGS) \\\n  $(HDF5_CPPFLAGS) \\\n  $(JAVA_CPPFLAGS)\n\n%canon_reldir%_liboctave_value_la_LIBADD = $(JAVA_LIBS)\n\nlibinterp_liboctinterp_la_LIBADD += %reldir%/liboctave-value.la\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-diag-inst.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ov-base-diag.cc\"\n\n// instantiate template class with types that need to be exported from library\n\ntemplate class OCTINTERP_API octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix>;\ntemplate class OCTINTERP_API octave_base_diag<FloatDiagMatrix, FloatMatrix>;\ntemplate class OCTINTERP_API octave_base_diag<ComplexDiagMatrix, ComplexMatrix>;\ntemplate class OCTINTERP_API octave_base_diag<DiagMatrix, Matrix>;\n\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-diag.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <istream>\n#include <ostream>\n#include <sstream>\n\n#include \"mach-info.h\"\n#include \"lo-ieee.h\"\n\n#include \"ov-base-diag.h\"\n#include \"mxarray.h\"\n#include \"ov-base.h\"\n#include \"ov-base-mat.h\"\n#include \"pr-output.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n\n#include \"ls-oct-text.h\"\n\ntemplate <typename DMT, typename MT>\noctave_value\noctave_base_diag<DMT, MT>::subsref (const std::string& type,\n                                    const std::list<octave_value_list>& idx)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      retval = do_index_op (idx.front ());\n      break;\n\n    case '{':\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_base_diag<DMT,MT>::subsref - please report this bug\");\n    }\n\n  return retval.next_subsref (type, idx);\n}\n\ntemplate <typename DMT, typename MT>\noctave_value\noctave_base_diag<DMT, MT>::diag (octave_idx_type k) const\n{\n  octave_value retval;\n  if (m_matrix.rows () == 1 || m_matrix.cols () == 1)\n    {\n      // Rather odd special case.  This is a row or column vector\n      // represented as a diagonal matrix with a single nonzero entry, but\n      // Fdiag semantics are to product a diagonal matrix for vector\n      // inputs.\n      if (k == 0)\n        // Returns Diag2Array<T> with nnz <= 1.\n        retval = m_matrix.build_diag_matrix ();\n      else\n        // Returns Array<T> matrix\n        retval = m_matrix.array_value ().diag (k);\n    }\n  else\n    // Returns Array<T> vector\n    retval = m_matrix.extract_diag (k);\n  return retval;\n}\n\ntemplate <typename DMT, typename MT>\noctave_value\noctave_base_diag<DMT, MT>::do_index_op (const octave_value_list& idx,\n                                        bool resize_ok)\n{\n  octave_value retval;\n\n  if (idx.length () == 2 && ! resize_ok)\n    {\n      int k = 0;        // index we're accessing when index_vector throws\n      try\n        {\n          octave::idx_vector idx0 = idx(0).index_vector ();\n          k = 1;\n          octave::idx_vector idx1 = idx(1).index_vector ();\n\n          if (idx0.is_scalar () && idx1.is_scalar ())\n            {\n              retval = m_matrix.checkelem (idx0(0), idx1(0));\n            }\n          else\n            {\n              octave_idx_type m = idx0.length (m_matrix.rows ());\n              octave_idx_type n = idx1.length (m_matrix.columns ());\n              if (idx0.is_colon_equiv (m) && idx1.is_colon_equiv (n)\n                  && m <= m_matrix.rows () && n <= m_matrix.rows ())\n                {\n                  DMT rm (m_matrix);\n                  rm.resize (m, n);\n                  retval = rm;\n                }\n              else\n                retval = to_dense ().index_op (idx, resize_ok);\n            }\n        }\n      catch (octave::index_exception& ie)\n        {\n          // Rethrow to allow more info to be reported later.\n          ie.set_pos_if_unset (2, k+1);\n          throw;\n        }\n    }\n  else\n    retval = to_dense ().index_op (idx, resize_ok);\n\n  return retval;\n}\n\ntemplate <typename DMT, typename MT>\noctave_value\noctave_base_diag<DMT, MT>::subsasgn (const std::string& type,\n                                     const std::list<octave_value_list>& idx,\n                                     const octave_value& rhs)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        if (type.length () != 1)\n          {\n            std::string nm = type_name ();\n            error (\"in indexed assignment of %s, last lhs index must be ()\",\n                   nm.c_str ());\n          }\n\n        octave_value_list jdx = idx.front ();\n\n        // FIXME: Mostly repeated code for cases 1 and 2 could be\n        //        consolidated for DRY (Don't Repeat Yourself).\n        // Check for assignments to diagonal elements which should not\n        // destroy the diagonal property of the matrix.\n        // If D is a diagonal matrix then the assignment can be\n        // 1) linear, D(i) = x, where ind2sub results in case #2 below\n        // 2) subscript D(i,i) = x, where both indices are equal.\n        if (jdx.length () == 1 && jdx(0).is_scalar_type ())\n          {\n            typename DMT::element_type val;\n            int k = 0;\n            try\n              {\n                octave::idx_vector ind = jdx(0).index_vector ();\n                k = 1;\n                dim_vector dv (m_matrix.rows (), m_matrix.cols ());\n                Array<octave::idx_vector> ivec = ind2sub (dv, ind);\n                octave::idx_vector i0 = ivec(0);\n                octave::idx_vector i1 = ivec(1);\n\n                if (i0(0) == i1(0)\n                    && chk_valid_scalar (rhs, val))\n                  {\n                    m_matrix.dgelem (i0(0)) = val;\n                    retval = this;\n                    this->m_count++;\n                    // invalidate cache\n                    m_dense_cache = octave_value ();\n                  }\n              }\n            catch (octave::index_exception& ie)\n              {\n                // Rethrow to allow more info to be reported later.\n                ie.set_pos_if_unset (2, k+1);\n                throw;\n              }\n          }\n        else if (jdx.length () == 2\n                 && jdx(0).is_scalar_type () && jdx(1).is_scalar_type ())\n          {\n            typename DMT::element_type val;\n            int k = 0;\n            try\n              {\n                octave::idx_vector i0 = jdx(0).index_vector ();\n                k = 1;\n                octave::idx_vector i1 = jdx(1).index_vector ();\n                if (i0(0) == i1(0)\n                    && i0(0) < m_matrix.rows () && i1(0) < m_matrix.cols ()\n                    && chk_valid_scalar (rhs, val))\n                  {\n                    m_matrix.dgelem (i0(0)) = val;\n                    retval = this;\n                    this->m_count++;\n                    // invalidate cache\n                    m_dense_cache = octave_value ();\n                  }\n              }\n            catch (octave::index_exception& ie)\n              {\n                // Rethrow to allow more info to be reported later.\n                ie.set_pos_if_unset (2, k+1);\n                throw;\n              }\n          }\n\n        if (! retval.is_defined ())\n          retval = numeric_assign (type, idx, rhs);\n      }\n      break;\n\n    case '{':\n    case '.':\n      {\n        if (! isempty ())\n          {\n            std::string nm = type_name ();\n            error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n          }\n\n        octave_value tmp = octave_value::empty_conv (type, rhs);\n\n        retval = tmp.subsasgn (type, idx, rhs);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_base_diag<DMT,MT>::subsasgn - please report this bug\");\n    }\n\n  return retval;\n}\n\ntemplate <typename DMT, typename MT>\noctave_value\noctave_base_diag<DMT, MT>::resize (const dim_vector& dv, bool fill) const\n{\n  octave_value retval;\n  if (dv.ndims () == 2)\n    {\n      DMT rm (m_matrix);\n      rm.resize (dv(0), dv(1));\n      retval = rm;\n    }\n  else\n    retval = to_dense ().resize (dv, fill);\n  return retval;\n}\n\n// Return true if this matrix has all true elements (nonzero, not NA/NaN).\ntemplate <typename DMT, typename MT>\nbool\noctave_base_diag<DMT, MT>::is_true () const\n{\n  if (dims ().numel () > 1)\n    {\n      warn_array_as_logical (dims ());\n      // Throw error if any NaN or NA by calling is_true().\n      octave_value (m_matrix.extract_diag ()).is_true ();\n      return false;                 // > 1x1 diagonal always has zeros\n    }\n  else\n    return to_dense ().is_true ();  // 0x0 or 1x1, handle NaN etc.\n}\n\n// FIXME: This should be achieveable using ::real\ntemplate <typename T> inline T helper_getreal (T x) { return x; }\ntemplate <typename T> inline T helper_getreal (std::complex<T> x)\n{ return x.real (); }\n// FIXME: We really need some traits so that ad hoc hooks like this\n//        are not necessary.\ntemplate <typename T> inline T helper_iscomplex (T) { return false; }\ntemplate <typename T> inline T helper_iscomplex (std::complex<T>)\n{ return true; }\n\ntemplate <typename DMT, typename MT>\ndouble\noctave_base_diag<DMT, MT>::double_value (bool force_conversion) const\n{\n  typedef typename DMT::element_type el_type;\n\n  if (helper_iscomplex (el_type ()) && ! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real scalar\");\n\n  if (isempty ())\n    err_invalid_conversion (type_name (), \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            type_name (), \"real scalar\");\n\n  return helper_getreal (el_type (m_matrix (0, 0)));\n}\n\ntemplate <typename DMT, typename MT>\nfloat\noctave_base_diag<DMT, MT>::float_value (bool force_conversion) const\n{\n  typedef typename DMT::element_type el_type;\n\n  if (helper_iscomplex (el_type ()) && ! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real scalar\");\n\n  if (! (numel () > 0))\n    err_invalid_conversion (type_name (), \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            type_name (), \"real scalar\");\n\n  return helper_getreal (el_type (m_matrix (0, 0)));\n}\n\ntemplate <typename DMT, typename MT>\nComplex\noctave_base_diag<DMT, MT>::complex_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (type_name (), \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            type_name (), \"complex scalar\");\n\n  return m_matrix(0, 0);\n}\n\ntemplate <typename DMT, typename MT>\nFloatComplex\noctave_base_diag<DMT, MT>::float_complex_value (bool) const\n{\n  float tmp = lo_ieee_float_nan_value ();\n\n  FloatComplex retval (tmp, tmp);\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (type_name (), \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            type_name (), \"complex scalar\");\n\n  retval = m_matrix (0, 0);\n\n  return retval;\n}\n\ntemplate <typename DMT, typename MT>\nMatrix\noctave_base_diag<DMT, MT>::matrix_value (bool) const\n{\n  return Matrix (diag_matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\nFloatMatrix\noctave_base_diag<DMT, MT>::float_matrix_value (bool) const\n{\n  return FloatMatrix (float_diag_matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\nComplexMatrix\noctave_base_diag<DMT, MT>::complex_matrix_value (bool) const\n{\n  return ComplexMatrix (complex_diag_matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\nFloatComplexMatrix\noctave_base_diag<DMT, MT>::float_complex_matrix_value (bool) const\n{\n  return FloatComplexMatrix (float_complex_diag_matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\nNDArray\noctave_base_diag<DMT, MT>::array_value (bool) const\n{\n  return NDArray (matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\nFloatNDArray\noctave_base_diag<DMT, MT>::float_array_value (bool) const\n{\n  return FloatNDArray (float_matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\nComplexNDArray\noctave_base_diag<DMT, MT>::complex_array_value (bool) const\n{\n  return ComplexNDArray (complex_matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\nFloatComplexNDArray\noctave_base_diag<DMT, MT>::float_complex_array_value (bool) const\n{\n  return FloatComplexNDArray (float_complex_matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\nboolNDArray\noctave_base_diag<DMT, MT>::bool_array_value (bool warn) const\n{\n  return to_dense ().bool_array_value (warn);\n}\n\ntemplate <typename DMT, typename MT>\ncharNDArray\noctave_base_diag<DMT, MT>::char_array_value (bool warn) const\n{\n  return to_dense ().char_array_value (warn);\n}\n\ntemplate <typename DMT, typename MT>\nSparseMatrix\noctave_base_diag<DMT, MT>::sparse_matrix_value (bool) const\n{\n  return SparseMatrix (diag_matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\nSparseComplexMatrix\noctave_base_diag<DMT, MT>::sparse_complex_matrix_value (bool) const\n{\n  return SparseComplexMatrix (complex_diag_matrix_value ());\n}\n\ntemplate <typename DMT, typename MT>\noctave::idx_vector\noctave_base_diag<DMT, MT>::index_vector (bool require_integers) const\n{\n  return to_dense ().index_vector (require_integers);\n}\n\ntemplate <typename DMT, typename MT>\noctave_value\noctave_base_diag<DMT, MT>::convert_to_str_internal (bool pad, bool force,\n    char type) const\n{\n  return to_dense ().convert_to_str_internal (pad, force, type);\n}\n\ntemplate <typename DMT, typename MT>\nfloat_display_format\noctave_base_diag<DMT, MT>::get_edit_display_format () const\n{\n  // FIXME\n  return float_display_format ();\n}\n\ntemplate <typename DMT, typename MT>\nstd::string\noctave_base_diag<DMT, MT>::edit_display (const float_display_format& fmt,\n    octave_idx_type i,\n    octave_idx_type j) const\n{\n  std::ostringstream buf;\n  octave_print_internal (buf, fmt, m_matrix(i, j));\n  return buf.str ();\n}\n\ntemplate <typename DMT, typename MT>\nbool\noctave_base_diag<DMT, MT>::save_ascii (std::ostream& os)\n{\n  os << \"# rows: \" << m_matrix.rows () << \"\\n\"\n     << \"# columns: \" << m_matrix.columns () << \"\\n\";\n\n  os << m_matrix.extract_diag ();\n\n  return true;\n}\n\ntemplate <typename DMT, typename MT>\nbool\noctave_base_diag<DMT, MT>::load_ascii (std::istream& is)\n{\n  octave_idx_type r = 0;\n  octave_idx_type c = 0;\n\n  if (! extract_keyword (is, \"rows\", r, true)\n      || ! extract_keyword (is, \"columns\", c, true))\n    error (\"load: failed to extract number of rows and columns\");\n\n  octave_idx_type l = (r < c ? r : c);\n  MT tmp (l, 1);\n  is >> tmp;\n\n  if (! is)\n    error (\"load: failed to load diagonal matrix constant\");\n\n  // This is a little tricky, as we have the Matrix type, but\n  // not ColumnVector type.  We need to help the compiler get\n  // through the inheritance tree.\n  typedef typename DMT::element_type el_type;\n  m_matrix = DMT (MDiagArray2<el_type> (MArray<el_type> (tmp)));\n  m_matrix.resize (r, c);\n\n  // Invalidate cache.  Probably not necessary, but safe.\n  m_dense_cache = octave_value ();\n\n  return true;\n}\n\ntemplate <typename DMT, typename MT>\nvoid\noctave_base_diag<DMT, MT>::print_raw (std::ostream& os,\n                                      bool pr_as_read_syntax) const\n{\n  return octave_print_internal (os, m_matrix, pr_as_read_syntax,\n                                current_print_indent_level ());\n}\n\ntemplate <typename DMT, typename MT>\nmxArray *\noctave_base_diag<DMT, MT>::as_mxArray (bool interleaved) const\n{\n  return to_dense ().as_mxArray (interleaved);\n}\n\ntemplate <typename DMT, typename MT>\nbool\noctave_base_diag<DMT, MT>::print_as_scalar () const\n{\n  const dim_vector& dv = dims ();\n\n  return (dv.all_ones () || dv.any_zero ());\n}\n\ntemplate <typename DMT, typename MT>\nvoid\noctave_base_diag<DMT, MT>::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\ntemplate <typename DMT, typename MT>\nint\noctave_base_diag<DMT, MT>::write (octave::stream& os, int block_size,\n                                  oct_data_conv::data_type output_type,\n                                  int skip,\n                                  octave::mach_info::float_format flt_fmt) const\n{\n  return to_dense ().write (os, block_size, output_type, skip, flt_fmt);\n}\n\ntemplate <typename DMT, typename MT>\nvoid\noctave_base_diag<DMT, MT>::print_info (std::ostream& os,\n                                       const std::string& prefix) const\n{\n  m_matrix.print_info (os, prefix);\n}\n\n// FIXME: this function is duplicated in octave_base_matrix<T>.  Could\n// it somehow be shared instead?\n\ntemplate <typename DMT, typename MT>\nvoid\noctave_base_diag<DMT, MT>::short_disp (std::ostream& os) const\n{\n  if (m_matrix.isempty ())\n    os << \"[]\";\n  else if (m_matrix.ndims () == 2)\n    {\n      // FIXME: should this be configurable?\n      octave_idx_type max_elts = 10;\n      octave_idx_type elts = 0;\n\n      octave_idx_type nr = m_matrix.rows ();\n      octave_idx_type nc = m_matrix.columns ();\n\n      os << '[';\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              std::ostringstream buf;\n              octave_print_internal (buf, m_matrix(i, j));\n              std::string tmp = buf.str ();\n              std::size_t pos = tmp.find_first_not_of (' ');\n              if (pos != std::string::npos)\n                os << tmp.substr (pos);\n              else if (! tmp.empty ())\n                os << tmp[0];\n              elts++;\n\n              if (j < nc - 1)\n                {\n                  os << \", \";\n\n                  if (elts >= max_elts)\n                    {\n                      os << \"...\";\n                      goto done;\n                    }\n                }\n            }\n\n          if (i < nr - 1)\n            {\n              os << \"; \";\n\n              if (elts >= max_elts)\n                {\n                  os << \"...\";\n                  goto done;\n                }\n            }\n        }\n\n    done:\n      os << ']';\n    }\n  else\n    octave_base_value::short_disp (os);\n}\n\ntemplate <typename DMT, typename MT>\noctave_value\noctave_base_diag<DMT, MT>::fast_elem_extract (octave_idx_type n) const\n{\n  if (n < m_matrix.numel ())\n    {\n      octave_idx_type nr = m_matrix.rows ();\n\n      octave_idx_type r = n % nr;\n      octave_idx_type c = n / nr;\n\n      return octave_value (m_matrix.elem (r, c));\n    }\n  else\n    return octave_value ();\n}\n\ntemplate <typename DMT, typename MT>\noctave_value\noctave_base_diag<DMT, MT>::to_dense () const\n{\n  if (! m_dense_cache.is_defined ())\n    m_dense_cache = MT (m_matrix);\n\n  return m_dense_cache;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-diag.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_base_diag_h)\n#define octave_ov_base_diag_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"ovl.h\"\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n\n// Real matrix values.\n\ntemplate <typename DMT, typename MT>\nclass OCTINTERP_TEMPLATE_API octave_base_diag : public octave_base_value\n{\n\npublic:\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_diag ()\n    : octave_base_value (), m_matrix (), m_dense_cache () { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_diag (const DMT& m)\n    : octave_base_value (), m_matrix (m), m_dense_cache () { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_diag (const octave_base_diag& m)\n    : octave_base_value (), m_matrix (m.m_matrix), m_dense_cache () { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API  ~octave_base_diag () = default;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API std::size_t byte_size () const\n  { return m_matrix.byte_size (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value squeeze () const\n  { return m_matrix; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value full_value () const\n  { return to_dense (); }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  OCTINTERP_API octave_value\n  subsref (const std::string& type, const std::list<octave_value_list>& idx);\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int)\n  { return subsref (type, idx); }\n\n  OCTINTERP_API octave_value\n  do_index_op (const octave_value_list& idx, bool resize_ok = false);\n\n  OCTINTERP_API octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  OCTINTERP_OVERRIDABLE_FUNC_API dim_vector dims () const\n  { return m_matrix.dims (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type nnz () const\n  { return diag ().nnz (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value reshape (const dim_vector& new_dims) const\n  { return to_dense ().reshape (new_dims); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  permute (const Array<int>& vec, bool inv = false) const\n  {\n    if (vec.numel () == 2\n        && ((vec.xelem (0) == 1 && vec.xelem (1) == 0)\n            || (vec.xelem (0) == 0 && vec.xelem (1) == 1)))\n      return DMT (m_matrix);\n    else\n      return to_dense ().permute (vec, inv);\n  }\n\n  OCTINTERP_API octave_value\n  resize (const dim_vector& dv, bool fill = false) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value all (int dim = 0) const\n  { return MT (m_matrix).all (dim); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value any (int dim = 0) const\n  { return MT (m_matrix).any (dim); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType matrix_type () const\n  { return MatrixType::Diagonal; }\n  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType matrix_type (const MatrixType&) const\n  { return matrix_type (); }\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::diag;\n\n  OCTINTERP_API octave_value diag (octave_idx_type k = 0) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const\n  { return to_dense ().sort (dim, mode); }\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n        sortmode mode = ASCENDING) const\n  { return to_dense ().sort (sidx, dim, mode); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API sortmode\n  issorted (sortmode mode = UNSORTED) const\n  { return to_dense ().issorted (mode); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API Array<octave_idx_type>\n  sort_rows_idx (sortmode mode = ASCENDING) const\n  { return to_dense ().sort_rows_idx (mode); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API sortmode\n  is_sorted_rows (sortmode mode = UNSORTED) const\n  { return to_dense ().is_sorted_rows (mode); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_matrix_type () const\n  { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool isnumeric () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_defined () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_constant () const { return true; }\n\n  OCTINTERP_API bool is_true () const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_diag_matrix () const { return true; }\n\n  OCTINTERP_API double double_value (bool = false) const;\n\n  OCTINTERP_API float float_value (bool = false) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API double\n  scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  OCTINTERP_API octave::idx_vector\n  index_vector (bool /* require_integers */ = false) const;\n\n  OCTINTERP_API Matrix matrix_value (bool = false) const;\n\n  OCTINTERP_API FloatMatrix float_matrix_value (bool = false) const;\n\n  OCTINTERP_API Complex complex_value (bool = false) const;\n\n  OCTINTERP_API FloatComplex float_complex_value (bool = false) const;\n\n  OCTINTERP_API ComplexMatrix complex_matrix_value (bool = false) const;\n\n  OCTINTERP_API FloatComplexMatrix\n  float_complex_matrix_value (bool = false) const;\n\n  OCTINTERP_API ComplexNDArray complex_array_value (bool = false) const;\n\n  OCTINTERP_API FloatComplexNDArray\n  float_complex_array_value (bool = false) const;\n\n  OCTINTERP_API boolNDArray bool_array_value (bool warn = false) const;\n\n  OCTINTERP_API charNDArray char_array_value (bool = false) const;\n\n  OCTINTERP_API NDArray array_value (bool = false) const;\n\n  OCTINTERP_API FloatNDArray float_array_value (bool = false) const;\n\n  OCTINTERP_API SparseMatrix sparse_matrix_value (bool = false) const;\n\n  OCTINTERP_API SparseComplexMatrix\n  sparse_complex_matrix_value (bool = false) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API int8NDArray int8_array_value () const\n  { return to_dense ().int8_array_value (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API int16NDArray int16_array_value () const\n  { return to_dense ().int16_array_value (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API int32NDArray int32_array_value () const\n  { return to_dense ().int32_array_value (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API int64NDArray int64_array_value () const\n  { return to_dense ().int64_array_value (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API uint8NDArray uint8_array_value () const\n  { return to_dense ().uint8_array_value (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API uint16NDArray uint16_array_value () const\n  { return to_dense ().uint16_array_value (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API uint32NDArray uint32_array_value () const\n  { return to_dense ().uint32_array_value (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API uint64NDArray uint64_array_value () const\n  { return to_dense ().uint64_array_value (); }\n\n  OCTINTERP_API octave_value\n  convert_to_str_internal (bool pad, bool force, char type) const;\n\n  OCTINTERP_API void\n  print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  OCTINTERP_API float_display_format get_edit_display_format () const;\n\n  OCTINTERP_API std::string\n  edit_display (const float_display_format& fmt,\n                octave_idx_type i, octave_idx_type j) const;\n\n  OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  OCTINTERP_API bool load_ascii (std::istream& is);\n\n  OCTINTERP_API int\n  write (octave::stream& os, int block_size,\n         oct_data_conv::data_type output_type, int skip,\n         octave::mach_info::float_format flt_fmt) const;\n\n  OCTINTERP_API mxArray * as_mxArray (bool interleaved) const;\n\n  OCTINTERP_API bool print_as_scalar () const;\n\n  OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  OCTINTERP_API void\n  print_info (std::ostream& os, const std::string& prefix) const;\n\n  OCTINTERP_API void short_disp (std::ostream& os) const;\n\n  OCTINTERP_API octave_value fast_elem_extract (octave_idx_type n) const;\n\nprotected:\n\n  DMT m_matrix;\n\n  OCTINTERP_API octave_value to_dense () const;\n\n  virtual bool chk_valid_scalar (const octave_value&,\n                                 typename DMT::element_type&) const = 0;\n\nprivate:\n\n  mutable octave_value m_dense_cache;\n\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-int-inst.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"int8NDArray.h\"\n#include \"int16NDArray.h\"\n#include \"int32NDArray.h\"\n#include \"int64NDArray.h\"\n#include \"uint8NDArray.h\"\n#include \"uint16NDArray.h\"\n#include \"uint32NDArray.h\"\n#include \"uint64NDArray.h\"\n\n#include \"ov-base-int.cc\"\n\n// instantiate template class with types that need to be exported from library\n\ntemplate class octave_base_int_matrix<int8NDArray>;\ntemplate class octave_base_int_matrix<int16NDArray>;\ntemplate class octave_base_int_matrix<int32NDArray>;\ntemplate class octave_base_int_matrix<int64NDArray>;\ntemplate class octave_base_int_matrix<uint8NDArray>;\ntemplate class octave_base_int_matrix<uint16NDArray>;\ntemplate class octave_base_int_matrix<uint32NDArray>;\ntemplate class octave_base_int_matrix<uint64NDArray>;\n\ntemplate class octave_base_int_scalar<octave_int8>;\ntemplate class octave_base_int_scalar<octave_int16>;\ntemplate class octave_base_int_scalar<octave_int32>;\ntemplate class octave_base_int_scalar<octave_int64>;\ntemplate class octave_base_int_scalar<octave_uint8>;\ntemplate class octave_base_int_scalar<octave_uint16>;\ntemplate class octave_base_int_scalar<octave_uint32>;\ntemplate class octave_base_int_scalar<octave_uint64>;\n\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-int.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <sstream>\n#include <vector>\n\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n#include \"int8NDArray.h\"\n#include \"int16NDArray.h\"\n#include \"int32NDArray.h\"\n#include \"int64NDArray.h\"\n#include \"uint8NDArray.h\"\n#include \"uint16NDArray.h\"\n#include \"uint32NDArray.h\"\n#include \"uint64NDArray.h\"\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"quit.h\"\n#include \"oct-locbuf.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n#include \"ov-base-int.h\"\n#include \"ov-int-traits.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\n// We have all the machinery below (octave_base_int_helper and\n// octave_base_int_helper_traits) to avoid a few warnings from GCC\n// about comparisons always false due to limited range of data types.\n// Ugh.  The cure may be worse than the disease.\n\ntemplate <typename T, bool is_signed = true, bool can_be_too_big = true>\nstruct octave_base_int_helper\n{\npublic:\n  static bool\n  char_value_out_of_range (T val)\n  {\n    return val < 0 || val > std::numeric_limits<unsigned char>::max ();\n  }\n};\n\ntemplate <typename T>\nstruct octave_base_int_helper<T, false, false>\n{\npublic:\n  static bool char_value_out_of_range (T) { return false; }\n};\n\ntemplate <typename T>\nstruct octave_base_int_helper<T, false, true>\n{\npublic:\n  static bool char_value_out_of_range (T val)\n  {\n    return val > std::numeric_limits<unsigned char>::max ();\n  }\n};\n\ntemplate <typename T>\nstruct octave_base_int_helper<T, true, false>\n{\npublic:\n  static bool char_value_out_of_range (T val) { return val < 0; }\n};\n\n// For all types other than char, signed char, and unsigned char, we\n// assume that the upper limit for the range of allowable values is\n// larger than the range for unsigned char.  If that's not true, we\n// are still OK, but will see the warnings again for any other types\n// that do not meet this assumption.\n\ntemplate <typename T>\nstruct octave_base_int_helper_traits\n{\n  static const bool can_be_larger_than_uchar_max = true;\n};\n\ntemplate <>\nstruct octave_base_int_helper_traits<char>\n{\n  static const bool can_be_larger_than_uchar_max = false;\n};\n\ntemplate <>\nstruct octave_base_int_helper_traits<signed char>\n{\n  static const bool can_be_larger_than_uchar_max = false;\n};\n\ntemplate <>\nstruct octave_base_int_helper_traits<unsigned char>\n{\n  static const bool can_be_larger_than_uchar_max = false;\n};\n\ntemplate <typename T>\noctave_base_value *\noctave_base_int_matrix<T>::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (this->m_matrix.numel () == 1)\n    retval = new typename octave_value_int_traits<T>::scalar_type\n    (this->m_matrix (0));\n\n  return retval;\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_matrix<T>::convert_to_str_internal (bool, bool, char type) const\n{\n  octave_value retval;\n  const dim_vector& dv = this->dims ();\n  octave_idx_type nel = dv.numel ();\n\n  charNDArray chm (dv);\n\n  bool warned = false;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      octave_quit ();\n\n      typename T::element_type tmp = this->m_matrix(i);\n\n      typedef typename T::element_type::val_type val_type;\n\n      val_type ival = tmp.value ();\n\n      static constexpr bool is_signed = std::numeric_limits<val_type>::is_signed;\n      static constexpr bool can_be_larger_than_uchar_max\n        = octave_base_int_helper_traits<val_type>::can_be_larger_than_uchar_max;\n\n      if (octave_base_int_helper<val_type, is_signed,\n          can_be_larger_than_uchar_max>::char_value_out_of_range (ival))\n        {\n          // FIXME: is there something better we could do?\n\n          ival = 0;\n\n          if (! warned)\n            {\n              ::warning (\"range error for conversion to character value\");\n              warned = true;\n            }\n        }\n      else\n        chm (i) = static_cast<char> (ival);\n    }\n\n  retval = octave_value (chm, type);\n\n  return retval;\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_double () const\n{\n  return NDArray (this->m_matrix);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_single () const\n{\n  return FloatNDArray (this->m_matrix);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_int8 () const\n{\n  return int8NDArray (this->m_matrix);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_int16 () const\n{\n  return int16NDArray (this->m_matrix);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_int32 () const\n{\n  return int32NDArray (this->m_matrix);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_int64 () const\n{\n  return int64NDArray (this->m_matrix);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_uint8 () const\n{\n  return uint8NDArray (this->m_matrix);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_uint16 () const\n{\n  return uint16NDArray (this->m_matrix);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_uint32 () const\n{\n  return uint32NDArray (this->m_matrix);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_int_matrix<MT>::as_uint64 () const\n{\n  return uint64NDArray (this->m_matrix);\n}\n\ntemplate <typename T>\nstd::string\noctave_base_int_matrix<T>::edit_display (const float_display_format& fmt,\n    octave_idx_type i,\n    octave_idx_type j) const\n{\n  std::ostringstream buf;\n  octave_print_internal (buf, fmt, this->m_matrix(i, j));\n  return buf.str ();\n}\n\ntemplate <typename T>\nbool\noctave_base_int_matrix<T>::save_ascii (std::ostream& os)\n{\n  const dim_vector& dv = this->dims ();\n\n  os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n  for (int i = 0; i < dv.ndims (); i++)\n    os << ' ' << dv(i);\n\n  os << \"\\n\" << this->m_matrix;\n\n  return true;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_matrix<T>::load_ascii (std::istream& is)\n{\n  int mdims = 0;\n\n  if (! extract_keyword (is, \"ndims\", mdims, true))\n    error (\"load: failed to extract number of dimensions\");\n\n  if (mdims < 0)\n    error (\"load: failed to extract number of rows and columns\");\n\n  dim_vector dv;\n  dv.resize (mdims);\n\n  for (int i = 0; i < mdims; i++)\n    is >> dv(i);\n\n  T tmp(dv);\n\n  is >> tmp;\n\n  if (! is)\n    error (\"load: failed to load matrix constant\");\n\n  this->m_matrix = tmp;\n\n  return true;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_matrix<T>::save_binary (std::ostream& os, bool)\n{\n  const dim_vector& dv = this->dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Use negative value for ndims to differentiate with old format!!\n  int32_t tmp = - dv.ndims ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  for (int i=0; i < dv.ndims (); i++)\n    {\n      tmp = dv(i);\n      os.write (reinterpret_cast<char *> (&tmp), 4);\n    }\n\n  os.write (reinterpret_cast<const char *> (this->m_matrix.data ()),\n            this->byte_size ());\n\n  return true;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_matrix<T>::load_binary (std::istream& is, bool swap,\n                                        octave::mach_info::float_format)\n{\n  int32_t mdims;\n  if (! is.read (reinterpret_cast<char *> (&mdims), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&mdims);\n  if (mdims >= 0)\n    return false;\n\n  mdims = - mdims;\n  int32_t di;\n  dim_vector dv;\n  dv.resize (mdims);\n\n  for (int i = 0; i < mdims; i++)\n    {\n      if (! is.read (reinterpret_cast<char *> (&di), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&di);\n      dv(i) = di;\n    }\n\n  // Convert an array with a single dimension to be a row vector.\n  // Octave should never write files like this, other software\n  // might.\n\n  if (mdims == 1)\n    {\n      mdims = 2;\n      dv.resize (mdims);\n      dv(1) = dv(0);\n      dv(0) = 1;\n    }\n\n  T m (dv);\n\n  if (! is.read (reinterpret_cast<char *> (m.rwdata ()), m.byte_size ()))\n    return false;\n\n  if (swap)\n    {\n      int nel = dv.numel ();\n      int bytes = nel / m.byte_size ();\n      for (int i = 0; i < nel; i++)\n        switch (bytes)\n          {\n          case 8:\n            swap_bytes<8> (&m(i));\n            break;\n          case 4:\n            swap_bytes<4> (&m(i));\n            break;\n          case 2:\n            swap_bytes<2> (&m(i));\n            break;\n          case 1:\n          default:\n            break;\n          }\n    }\n\n  this->m_matrix = m;\n  return true;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_matrix<T>::save_hdf5_internal (octave_hdf5_id loc_id,\n    octave_hdf5_id save_type,\n    const char *name, bool)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hid_t save_type_hid = save_type;\n  const dim_vector& dv = this->dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  int rank = dv.ndims ();\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  for (int i = 0; i < rank; i++)\n    hdims[i] = dv(rank-i-1);\n\n  space_hid = H5Screate_simple (rank, hdims, nullptr);\n\n  if (space_hid < 0) return false;\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n\n  retval = H5Dwrite (data_hid, save_type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, this->m_matrix.data ()) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (save_type);\n  octave_unused_parameter (name);\n\n  this->warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_matrix<T>::load_hdf5_internal (octave_hdf5_id loc_id,\n    octave_hdf5_id save_type,\n    const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hid_t save_type_hid = save_type;\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    this->m_matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank < 1)\n    {\n      H5Sclose (space_id);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_id, hdims, maxdims);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  if (rank == 1)\n    {\n      dv.resize (2);\n      dv(0) = 1;\n      dv(1) = hdims[0];\n    }\n  else\n    {\n      dv.resize (rank);\n      for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)\n        dv(j) = hdims[i];\n    }\n\n  T m (dv);\n  if (H5Dread (data_hid, save_type_hid, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, m.rwdata ()) >= 0)\n    {\n      retval = true;\n      this->m_matrix = m;\n    }\n\n  H5Sclose (space_id);\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (save_type);\n  octave_unused_parameter (name);\n\n  this->warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\ntemplate <typename T>\nvoid\noctave_base_int_matrix<T>::print_raw (std::ostream& os,\n                                      bool pr_as_read_syntax) const\n{\n  octave_print_internal (os, this->m_matrix, pr_as_read_syntax,\n                         this->current_print_indent_level ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::convert_to_str_internal (bool, bool, char type) const\n{\n  octave_value retval;\n\n  T tmp = this->scalar;\n\n  typedef typename T::val_type val_type;\n\n  val_type ival = tmp.value ();\n\n  static constexpr bool is_signed = std::numeric_limits<val_type>::is_signed;\n  static constexpr bool can_be_larger_than_uchar_max\n    = octave_base_int_helper_traits<val_type>::can_be_larger_than_uchar_max;\n\n  if (octave_base_int_helper<val_type, is_signed,\n      can_be_larger_than_uchar_max>::char_value_out_of_range (ival))\n    {\n      // FIXME: is there something better we could do?\n\n      ival = 0;\n\n      ::warning (\"range error for conversion to character value\");\n    }\n  else\n    retval = octave_value (std::string (1, static_cast<char> (ival)), type);\n\n  return retval;\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_double () const\n{\n  return static_cast<double> (this->scalar);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_single () const\n{\n  return static_cast<float> (this->scalar);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_int8 () const\n{\n  return octave_int8 (this->scalar);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_int16 () const\n{\n  return octave_int16 (this->scalar);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_int32 () const\n{\n  return octave_int32 (this->scalar);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_int64 () const\n{\n  return octave_int64 (this->scalar);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_uint8 () const\n{\n  return octave_uint8 (this->scalar);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_uint16 () const\n{\n  return octave_uint16 (this->scalar);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_uint32 () const\n{\n  return octave_uint32 (this->scalar);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_int_scalar<T>::as_uint64 () const\n{\n  return octave_uint64 (this->scalar);\n}\n\ntemplate <typename ST>\nstd::string\noctave_base_int_scalar<ST>::edit_display (const float_display_format& fmt,\n    octave_idx_type,\n    octave_idx_type) const\n{\n  std::ostringstream buf;\n  octave_print_internal (buf, fmt, this->scalar);\n  return buf.str ();\n}\n\ntemplate <typename T>\nbool\noctave_base_int_scalar<T>::save_ascii (std::ostream& os)\n{\n  os << this->scalar << \"\\n\";\n  return true;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_scalar<T>::load_ascii (std::istream& is)\n{\n  is >> this->scalar;\n  if (! is)\n    error (\"load: failed to load scalar constant\");\n\n  return true;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_scalar<T>::save_binary (std::ostream& os, bool)\n{\n  os.write (reinterpret_cast<char *> (&(this->scalar)), this->byte_size ());\n  return true;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_scalar<T>::load_binary (std::istream& is, bool swap,\n                                        octave::mach_info::float_format)\n{\n  T tmp;\n\n  if (! is.read (reinterpret_cast<char *> (&tmp), this->byte_size ()))\n    return false;\n\n  if (swap)\n    swap_bytes<sizeof (T)> (&tmp);\n\n  this->scalar = tmp;\n\n  return true;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_scalar<T>::save_hdf5_internal (octave_hdf5_id loc_id,\n    octave_hdf5_id save_type,\n    const char *name, bool)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hid_t save_type_hid = save_type;\n  hsize_t dimens[3] = {0};\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n\n  space_hid = H5Screate_simple (0, dimens, nullptr);\n  if (space_hid < 0) return false;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n\n  retval = H5Dwrite (data_hid, save_type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &(this->scalar)) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (save_type);\n  octave_unused_parameter (name);\n\n  this->warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\ntemplate <typename T>\nbool\noctave_base_int_scalar<T>::load_hdf5_internal (octave_hdf5_id loc_id,\n    octave_hdf5_id save_type,\n    const char *name)\n{\n#if defined (HAVE_HDF5)\n\n  hid_t save_type_hid = save_type;\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  T tmp;\n  if (H5Dread (data_hid, save_type_hid, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &tmp) < 0)\n    {\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  this->scalar = tmp;\n\n  H5Dclose (data_hid);\n\n  return true;\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (save_type);\n  octave_unused_parameter (name);\n\n  this->warn_load (\"hdf5\");\n\n  return false;\n#endif\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-int.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_base_int_h)\n#define octave_ov_base_int_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"ov-base.h\"\n#include \"ov-base-mat.h\"\n#include \"ov-base-scalar.h\"\n#include \"ov-typeinfo.h\"\n\n// base int matrix values.\n\nextern template class OCTINTERP_API octave_base_matrix<int8NDArray>;\nextern template class OCTINTERP_API octave_base_matrix<int16NDArray>;\nextern template class OCTINTERP_API octave_base_matrix<int32NDArray>;\nextern template class OCTINTERP_API octave_base_matrix<int64NDArray>;\nextern template class OCTINTERP_API octave_base_matrix<uint8NDArray>;\nextern template class OCTINTERP_API octave_base_matrix<uint16NDArray>;\nextern template class OCTINTERP_API octave_base_matrix<uint32NDArray>;\nextern template class OCTINTERP_API octave_base_matrix<uint64NDArray>;\n\ntemplate <typename T>\nclass OCTINTERP_TEMPLATE_API octave_base_int_matrix : public octave_base_matrix<T>\n{\npublic:\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_int_matrix ()\n    : octave_base_matrix<T> ()\n  { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_int_matrix (const T& nda)\n    : octave_base_matrix<T> (nda)\n  { }\n\n  ~octave_base_int_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_base_int_matrix (*this); }\n\n  octave_base_value * empty_clone () const\n  { return new octave_base_int_matrix (); }\n\n  OCTINTERP_API octave_base_value * try_narrowing_conversion ();\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool isreal () const { return true; }\n\n  //  void increment () { matrix += 1; }\n\n  //  void decrement () { matrix -= 1; }\n\n  OCTINTERP_API void\n  print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  OCTINTERP_API octave_value\n  convert_to_str_internal (bool, bool, char type) const;\n\n  OCTINTERP_API octave_value as_double () const;\n  OCTINTERP_API octave_value as_single () const;\n\n  OCTINTERP_API octave_value as_int8 () const;\n  OCTINTERP_API octave_value as_int16 () const;\n  OCTINTERP_API octave_value as_int32 () const;\n  OCTINTERP_API octave_value as_int64 () const;\n\n  OCTINTERP_API octave_value as_uint8 () const;\n  OCTINTERP_API octave_value as_uint16 () const;\n  OCTINTERP_API octave_value as_uint32 () const;\n  OCTINTERP_API octave_value as_uint64 () const;\n\n  OCTINTERP_API std::string\n  edit_display (const float_display_format& fmt,\n                octave_idx_type i, octave_idx_type j) const;\n\n  OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  OCTINTERP_API bool load_ascii (std::istream& is);\n\n  OCTINTERP_API bool save_binary (std::ostream& os, bool);\n\n  OCTINTERP_API bool\n  load_binary (std::istream& is, bool swap, octave::mach_info::float_format);\n\nprotected:\n\n  OCTINTERP_API bool\n  save_hdf5_internal (octave_hdf5_id loc_id, octave_hdf5_id save_type,\n                      const char *name, bool);\n\n  OCTINTERP_API bool\n  load_hdf5_internal (octave_hdf5_id loc_id, octave_hdf5_id save_type,\n                      const char *name);\n};\n\n// base int scalar values.\n\nextern template class OCTINTERP_API octave_base_scalar<octave_int8>;\nextern template class OCTINTERP_API octave_base_scalar<octave_int16>;\nextern template class OCTINTERP_API octave_base_scalar<octave_int32>;\nextern template class OCTINTERP_API octave_base_scalar<octave_int64>;\nextern template class OCTINTERP_API octave_base_scalar<octave_uint8>;\nextern template class OCTINTERP_API octave_base_scalar<octave_uint16>;\nextern template class OCTINTERP_API octave_base_scalar<octave_uint32>;\nextern template class OCTINTERP_API octave_base_scalar<octave_uint64>;\n\ntemplate <typename T>\nclass OCTINTERP_TEMPLATE_API octave_base_int_scalar : public octave_base_scalar<T>\n{\npublic:\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_int_scalar () : octave_base_scalar<T> () { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_int_scalar (const T& s) : octave_base_scalar<T> (s) { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API ~octave_base_int_scalar () = default;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_value * clone () const\n  { return new octave_base_int_scalar (*this); }\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_value * empty_clone () const\n  { return new octave_base_int_scalar (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_value *\n  try_narrowing_conversion ()\n  { return nullptr; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_maybe_function () const\n  { return false; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool isreal () const\n  { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_real_scalar () const\n  { return true; }\n\n  //  void increment () { scalar += 1; }\n\n  //  void decrement () { scalar -= 1; }\n\n  OCTINTERP_API octave_value\n  convert_to_str_internal (bool, bool, char type) const;\n\n  OCTINTERP_API octave_value as_double () const;\n  OCTINTERP_API octave_value as_single () const;\n\n  OCTINTERP_API octave_value as_int8 () const;\n  OCTINTERP_API octave_value as_int16 () const;\n  OCTINTERP_API octave_value as_int32 () const;\n  OCTINTERP_API octave_value as_int64 () const;\n\n  OCTINTERP_API octave_value as_uint8 () const;\n  OCTINTERP_API octave_value as_uint16 () const;\n  OCTINTERP_API octave_value as_uint32 () const;\n  OCTINTERP_API octave_value as_uint64 () const;\n\n  OCTINTERP_API std::string\n  edit_display (const float_display_format& fmt,\n                octave_idx_type i, octave_idx_type j) const;\n\n  OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  OCTINTERP_API bool load_ascii (std::istream& is);\n\n  OCTINTERP_API bool save_binary (std::ostream& os, bool);\n\n  OCTINTERP_API bool load_binary (std::istream& is, bool swap,\n                                  octave::mach_info::float_format);\nprotected:\n\n  OCTINTERP_API bool\n  save_hdf5_internal (octave_hdf5_id loc_id, octave_hdf5_id save_type,\n                      const char *name, bool);\n\n  OCTINTERP_API bool\n  load_hdf5_internal (octave_hdf5_id loc_id, octave_hdf5_id save_type,\n                      const char *name);\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-mat-inst.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ov-base-mat.cc\"\n\n// instantiate template class with types that need to be exported from library\n\ntemplate class OCTINTERP_API octave_base_matrix<boolNDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<charNDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<int8NDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<int16NDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<int32NDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<int64NDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<uint8NDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<uint16NDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<uint32NDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<uint64NDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<ComplexNDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<FloatComplexNDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<FloatNDArray>;\ntemplate class OCTINTERP_API octave_base_matrix<NDArray>;\n\n\n// Cell is able to handle octave_value indexing by itself, so just forward\n// everything.\n\ntemplate <>\noctave_value\noctave_base_matrix<Cell>::do_index_op (const octave_value_list& idx,\n                                       bool resize_ok)\n{\n  return m_matrix.index (idx, resize_ok);\n}\n\ntemplate <>\nvoid\noctave_base_matrix<Cell>::assign (const octave_value_list& idx, const Cell& rhs)\n{\n  m_matrix.assign (idx, rhs);\n}\n\ntemplate <>\nvoid\noctave_base_matrix<Cell>::assign (const octave_value_list& idx,\n                                  octave_value rhs)\n{\n  // FIXME: Really?\n  if (rhs.iscell ())\n    m_matrix.assign (idx, rhs.cell_value ());\n  else\n    m_matrix.assign (idx, Cell (rhs));\n}\n\ntemplate <>\nvoid\noctave_base_matrix<Cell>::delete_elements (const octave_value_list& idx)\n{\n  m_matrix.delete_elements (idx);\n}\n\n// FIXME: this list of specializations is becoming so long that we should\n// really ask whether octave_cell should inherit from octave_base_matrix at all.\n\ntemplate <>\nstd::string\noctave_base_matrix<Cell>::edit_display (const float_display_format&,\n                                        octave_idx_type i,\n                                        octave_idx_type j) const\n{\n  octave_value val = m_matrix(i, j);\n\n  std::string tname = val.type_name ();\n  dim_vector dv = val.dims ();\n  std::string dimstr = dv.str ();\n  return \"[\" + dimstr + \" \" + tname + \"]\";\n}\n\ntemplate <>\noctave_value\noctave_base_matrix<Cell>::fast_elem_extract (octave_idx_type n) const\n{\n  if (n < m_matrix.numel ())\n    return Cell (m_matrix(n));\n  else\n    return octave_value ();\n}\n\ntemplate <>\nbool\noctave_base_matrix<Cell>::fast_elem_insert (octave_idx_type n,\n                                            const octave_value& x)\n{\n  const octave_base_matrix<Cell> *xrep\n    = dynamic_cast<const octave_base_matrix<Cell> *> (&x.get_rep ());\n\n  bool retval = xrep && xrep->m_matrix.numel () == 1 && n < m_matrix.numel ();\n  if (retval)\n    m_matrix(n) = xrep->m_matrix(0);\n\n  return retval;\n}\n\n\n// FIXME: 2025-03-11: GCC emits the warning \"type attributes ignored after type\n// is already defined/[-Wattributes]\" for the following template class\n// instantiation.  The clang compiler does not issue a warning.  More\n// importantly Octave builds and runs correctly with \"-fvisibility=hidden\".\n// Therefore, this seems like a false positive that can be ignored.  Multiple\n// attempts have been made to try and locate the prior definition, but without\n// success.\n#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wattributes\"\ntemplate class OCTINTERP_API octave_base_matrix<Cell>;\n#  pragma GCC diagnostic pop\n#else\ntemplate class OCTINTERP_API octave_base_matrix<Cell>;\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <ostream>\n#include <sstream>\n\n#include \"Array-util.h\"\n\n#include \"Cell.h\"\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"oct-map.h\"\n#include \"ov-base.h\"\n#include \"ov-base-mat.h\"\n#include \"ov-base-scalar.h\"\n#include \"pr-output.h\"\n\ntemplate <typename MT>\noctave_value_list\noctave_base_matrix<MT>::simple_subsref (char type, octave_value_list& idx, int)\n{\n  switch (type)\n    {\n    case '(':\n      return do_index_op (idx);\n      break;\n\n    case '{':\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_base_matrix<T>::simple_subsref - please report this bug\");\n    }\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_matrix<MT>::subsref (const std::string& type,\n                                 const std::list<octave_value_list>& idx)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      retval = do_index_op (idx.front ());\n      break;\n\n    case '{':\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n      }\n      break;\n\n    default:\n      error (\"unpexpected: index not '(', '{', or '.' in - octave_base_matrix<MT>::subsref please report this bug\");\n    }\n\n  return retval.next_subsref (type, idx);\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_matrix<MT>::subsasgn (const std::string& type,\n                                  const std::list<octave_value_list>& idx,\n                                  const octave_value& rhs)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        if (type.length () == 1)\n          retval = numeric_assign (type, idx, rhs);\n        else if (isempty ())\n          {\n            // Allow conversion of empty matrix to some other type in\n            // cases like\n            //\n            //  x = []; x(i).f = rhs\n\n            if (type[1] != '.')\n              error (\"invalid assignment expression\");\n\n            octave_value tmp = octave_value::empty_conv (type, rhs);\n\n            retval = tmp.subsasgn (type, idx, rhs);\n          }\n        else\n          {\n            std::string nm = type_name ();\n            error (\"in indexed assignment of %s, last lhs index must be ()\",\n                   nm.c_str ());\n          }\n      }\n      break;\n\n    case '{':\n    case '.':\n      {\n        if (! isempty ())\n          {\n            std::string nm = type_name ();\n            error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n          }\n\n        octave_value tmp = octave_value::empty_conv (type, rhs);\n\n        retval = tmp.subsasgn (type, idx, rhs);\n      }\n      break;\n\n    default:\n      error (\"unpexpected: index not '(', '{', or '.' in - octave_base_matrix<MT>::subsasgn please report this bug\");\n    }\n\n  return retval;\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_matrix<MT>::do_index_op (const octave_value_list& idx,\n                                     bool resize_ok)\n{\n  octave_value retval;\n\n  octave_idx_type n_idx = idx.length ();\n\n  int nd = m_matrix.ndims ();\n  const MT& cmatrix = m_matrix;\n\n  // If we catch an indexing error in index_vector, we flag an error in\n  // index k.  Ensure it is the right value before each idx_vector call.\n  // Same variable as used in the for loop in the default case.\n\n  octave_idx_type k = 0;\n\n  try\n    {\n      switch (n_idx)\n        {\n        case 0:\n          warn_empty_index (type_name ());\n          retval = m_matrix;\n          break;\n\n        case 1:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            // optimize single scalar index.\n            if (! resize_ok && i.is_scalar ())\n              retval = cmatrix.checkelem (i(0));\n            else\n              retval = MT (m_matrix.index (i, resize_ok));\n          }\n          break;\n\n        case 2:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            k=1;\n            octave::idx_vector j = idx (1).index_vector ();\n\n            // optimize two scalar indices.\n            if (! resize_ok && i.is_scalar () && j.is_scalar ())\n              retval = cmatrix.checkelem (i(0), j(0));\n            else\n              retval = MT (m_matrix.index (i, j, resize_ok));\n          }\n          break;\n\n        default:\n          {\n            Array<octave::idx_vector> idx_vec (dim_vector (n_idx, 1));\n            bool scalar_opt = n_idx == nd && ! resize_ok;\n            const dim_vector dv = m_matrix.dims ();\n\n            for (k = 0; k < n_idx; k++)\n              {\n                idx_vec(k) = idx(k).index_vector ();\n\n                scalar_opt = (scalar_opt && idx_vec(k).is_scalar ());\n              }\n\n            if (scalar_opt)\n              retval = cmatrix.checkelem (conv_to_int_array (idx_vec));\n            else\n              retval = MT (m_matrix.index (idx_vec, resize_ok));\n          }\n          break;\n        }\n    }\n  catch (octave::index_exception& ie)\n    {\n      // Rethrow to allow more info to be reported later.\n      ie.set_pos_if_unset (n_idx, k+1);\n      throw;\n    }\n\n  return retval;\n}\n\n/*\n%% This behavior is required for Matlab compatibility.\n%!test\n%! a = [1, 2; 3, 4];\n%! assert (a(), a);\n*/\n\ntemplate <typename MT>\nvoid\noctave_base_matrix<MT>::assign (const octave_value_list& idx, const MT& rhs)\n{\n  octave_idx_type n_idx = idx.length ();\n\n  // If we catch an indexing error in index_vector, we flag an error in\n  // index k.  Ensure it is the right value before each idx_vector call.\n  // Same variable as used in the for loop in the default case.\n\n  octave_idx_type k = 0;\n\n  try\n    {\n      switch (n_idx)\n        {\n        case 0:\n          error (\"unexpected: zero indices in octave_base_matrix<MT>::assign - please report this bug\");\n          break;\n\n        case 1:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            m_matrix.assign (i, rhs);\n          }\n          break;\n\n        case 2:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            k = 1;\n            octave::idx_vector j = idx (1).index_vector ();\n\n            m_matrix.assign (i, j, rhs);\n          }\n          break;\n\n        default:\n          {\n            Array<octave::idx_vector> idx_vec (dim_vector (n_idx, 1));\n\n            for (k = 0; k < n_idx; k++)\n              idx_vec(k) = idx(k).index_vector ();\n\n            m_matrix.assign (idx_vec, rhs);\n          }\n          break;\n        }\n    }\n  catch (octave::index_exception& ie)\n    {\n      // Rethrow to allow more info to be reported later.\n      ie.set_pos_if_unset (n_idx, k+1);\n      throw;\n    }\n\n  // Clear cache.\n  clear_cached_info ();\n}\n\ntemplate <typename MT>\nMatrixType\noctave_base_matrix<MT>::matrix_type (const MatrixType& typ) const\n{\n  delete m_typ;\n  m_typ = new MatrixType (typ);\n  return *m_typ;\n}\n\ntemplate <typename MT>\nvoid\noctave_base_matrix<MT>::assign (const octave_value_list& idx,\n                                typename MT::element_type rhs)\n{\n  octave_idx_type n_idx = idx.length ();\n\n  int nd = m_matrix.ndims ();\n\n  // If we catch an indexing error in index_vector, we flag an error in\n  // index k.  Ensure it is the right value before each idx_vector call.\n  // Same variable as used in the for loop in the default case.\n\n  octave_idx_type k = 0;\n\n  try\n    {\n      switch (n_idx)\n        {\n        case 0:\n          error (\"unexpected: zero indices in octave_base_matrix<MT>::assign - please report this bug\");\n          break;\n\n        case 1:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            // optimize single scalar index.\n            if (i.is_scalar () && i(0) < m_matrix.numel ())\n              m_matrix(i(0)) = rhs;\n            else\n              {\n                MT mrhs (dim_vector (1, 1), rhs);\n                m_matrix.assign (i, mrhs);\n              }\n          }\n          break;\n\n        case 2:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            k = 1;\n            octave::idx_vector j = idx (1).index_vector ();\n\n            // optimize two scalar indices.\n            if (i.is_scalar () && j.is_scalar () && nd == 2\n                && i(0) < m_matrix.rows () && j(0) < m_matrix.columns ())\n              m_matrix(i(0), j(0)) = rhs;\n            else\n              {\n                MT mrhs (dim_vector (1, 1), rhs);\n                m_matrix.assign (i, j, mrhs);\n              }\n          }\n          break;\n\n        default:\n          {\n            Array<octave::idx_vector> idx_vec (dim_vector (n_idx, 1));\n            bool scalar_opt = n_idx == nd;\n            const dim_vector dv = m_matrix.dims ().redim (n_idx);\n\n            for (k = 0; k < n_idx; k++)\n              {\n                idx_vec(k) = idx(k).index_vector ();\n\n                scalar_opt = (scalar_opt && idx_vec(k).is_scalar ()\n                              && idx_vec(k)(0) < dv(k));\n              }\n\n            if (scalar_opt)\n              {\n                // optimize all scalar indices.  Don't construct\n                // an index array, but rather calc a scalar index directly.\n                octave_idx_type n = 1;\n                octave_idx_type j = 0;\n                for (octave_idx_type i = 0; i < n_idx; i++)\n                  {\n                    j += idx_vec(i)(0) * n;\n                    n *= dv (i);\n                  }\n                m_matrix(j) = rhs;\n              }\n            else\n              {\n                MT mrhs (dim_vector (1, 1), rhs);\n                m_matrix.assign (idx_vec, mrhs);\n              }\n          }\n          break;\n        }\n    }\n  catch (octave::index_exception& ie)\n    {\n      // Rethrow to allow more info to be reported later.\n      ie.set_pos_if_unset (n_idx, k+1);\n      throw;\n    }\n\n  // Clear cache.\n  clear_cached_info ();\n}\n\ntemplate <typename MT>\nvoid\noctave_base_matrix<MT>::delete_elements (const octave_value_list& idx)\n{\n  octave_idx_type len = idx.length ();\n\n  Array<octave::idx_vector> ra_idx (dim_vector (len, 1));\n\n  for (octave_idx_type i = 0; i < len; i++)\n    ra_idx(i) = idx(i).index_vector ();\n\n  m_matrix.delete_elements (ra_idx);\n\n  // Clear cache.\n  clear_cached_info ();\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_matrix<MT>::resize (const dim_vector& dv, bool fill) const\n{\n  MT retval (m_matrix);\n  if (fill)\n    retval.resize (dv, 0);\n  else\n    retval.resize (dv);\n  return retval;\n}\n\n// Return true if this matrix has all true elements (nonzero, not NA/NaN).\ntemplate <typename MT>\nbool\noctave_base_matrix<MT>::is_true () const\n{\n  bool retval = false;\n  const dim_vector& dv = m_matrix.dims ();\n  int nel = dv.numel ();\n\n  if (nel > 0)\n    {\n      MT t1 (m_matrix.reshape (dim_vector (nel, 1)));\n\n      if (t1.any_element_is_nan ())\n        octave::err_nan_to_logical_conversion ();\n\n      if (nel > 1)\n        warn_array_as_logical (dv);\n\n      boolNDArray t2 = t1.all ();\n\n      retval = t2(0);\n    }\n\n  return retval;\n}\n\ntemplate <typename MT>\nbool\noctave_base_matrix<MT>::print_as_scalar () const\n{\n  const dim_vector& dv = dims ();\n\n  return (dv.all_ones () || dv.any_zero ());\n}\n\ntemplate <typename MT>\nvoid\noctave_base_matrix<MT>::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\n\ntemplate <typename MT>\nvoid\noctave_base_matrix<MT>::print_info (std::ostream& os,\n                                    const std::string& prefix) const\n{\n  m_matrix.print_info (os, prefix);\n}\n\ntemplate <typename MT>\nvoid\noctave_base_matrix<MT>::short_disp (std::ostream& os) const\n{\n  if (m_matrix.isempty ())\n    os << \"[]\";\n  else if (m_matrix.ndims () == 2)\n    {\n      // FIXME: should this be configurable?\n      octave_idx_type max_elts = 10;\n      octave_idx_type elts = 0;\n\n      octave_idx_type nr = m_matrix.rows ();\n      octave_idx_type nc = m_matrix.columns ();\n\n      os << '[';\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              std::ostringstream buf;\n              octave_print_internal (buf, m_matrix(j*nr+i));\n              std::string tmp = buf.str ();\n              std::size_t pos = tmp.find_first_not_of (' ');\n              if (pos != std::string::npos)\n                os << tmp.substr (pos);\n              else if (! tmp.empty ())\n                os << tmp[0];\n              elts++;\n\n              if (j < nc - 1)\n                {\n                  os << \", \";\n\n                  if (elts >= max_elts)\n                    {\n                      os << \"...\";\n                      goto done;\n                    }\n                }\n            }\n\n          if (i < nr - 1)\n            {\n              os << \"; \";\n\n              if (elts >= max_elts)\n                {\n                  os << \"...\";\n                  goto done;\n                }\n            }\n        }\n\n    done:\n      os << ']';\n    }\n  else\n    octave_base_value::short_disp (os);\n}\n\ntemplate <typename MT>\nfloat_display_format\noctave_base_matrix<MT>::get_edit_display_format () const\n{\n  return make_format (m_matrix);\n}\n\ntemplate <typename MT>\nstd::string\noctave_base_matrix<MT>::edit_display (const float_display_format& fmt,\n                                      octave_idx_type i,\n                                      octave_idx_type j) const\n{\n  std::ostringstream buf;\n  octave_print_internal (buf, fmt, m_matrix(i, j));\n  return buf.str ();\n}\n\ntemplate <typename MT>\noctave_value\noctave_base_matrix<MT>::fast_elem_extract (octave_idx_type n) const\n{\n  if (n < m_matrix.numel ())\n    return m_matrix(n);\n  else\n    return octave_value ();\n}\n\ntemplate <typename MT>\nbool\noctave_base_matrix<MT>::fast_elem_insert (octave_idx_type n,\n    const octave_value& x)\n{\n  if (n < m_matrix.numel ())\n    {\n      // Don't use builtin_type () here to avoid an extra VM call.\n      typedef typename MT::element_type ET;\n      const builtin_type_t btyp = class_to_btyp<ET>::btyp;\n      if (btyp == btyp_unknown) // Dead branch?\n        return false;\n\n      // Set up the pointer to the proper place.\n      void *here = reinterpret_cast<void *> (&m_matrix(n));\n      // Ask x to store there if it can.\n      return x.get_rep ().fast_elem_insert_self (here, btyp);\n    }\n  else\n    return false;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_base_mat_h)\n#define octave_ov_base_mat_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n#include \"MatrixType.h\"\n\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n\n// Real matrix values.\n\ntemplate <typename MT>\nclass OCTINTERP_TEMPLATE_API octave_base_matrix : public octave_base_value\n{\npublic:\n\n  typedef MT object_type;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_matrix ()\n    : octave_base_value (), m_matrix (), m_typ (), m_idx_cache () { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_matrix (const MT& m, const MatrixType& t = MatrixType ())\n    : octave_base_value (), m_matrix (m),\n      m_typ (t.is_known () ? new MatrixType (t) : nullptr), m_idx_cache ()\n  {\n    if (m_matrix.ndims () == 0)\n      m_matrix.resize (dim_vector (0, 0));\n  }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_matrix (const octave_base_matrix& m)\n    : octave_base_value (), m_matrix (m.m_matrix),\n      m_typ (m.m_typ ? new MatrixType (*m.m_typ) : nullptr),\n      m_idx_cache (m.m_idx_cache ? new octave::idx_vector (*m.m_idx_cache)\n                   : nullptr)\n  { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  ~octave_base_matrix () { clear_cached_info (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  std::size_t byte_size () const { return m_matrix.byte_size (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_value squeeze () const { return MT (m_matrix.squeeze ()); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_value full_value () const { return m_matrix; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  void maybe_economize () { m_matrix.maybe_economize (); }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  OCTINTERP_API octave_value\n  subsref (const std::string& type, const std::list<octave_value_list>& idx);\n\n  OCTINTERP_API octave_value_list\n  simple_subsref (char type, octave_value_list& idx, int nargout);\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx, int)\n  { return subsref (type, idx); }\n\n  OCTINTERP_API octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  OCTINTERP_API octave_value\n  do_index_op (const octave_value_list& idx, bool resize_ok = false);\n\n  // FIXME: should we import the functions from the base class and\n  // overload them here, or should we use a different name so we don't\n  // have to do this?  Without the using declaration or a name change,\n  // the base class functions will be hidden.  That may be OK, but it\n  // can also cause some confusion.\n  using octave_base_value::assign;\n\n  OCTINTERP_API void assign (const octave_value_list& idx, const MT& rhs);\n\n  OCTINTERP_API void\n  assign (const octave_value_list& idx, typename MT::element_type rhs);\n\n  OCTINTERP_API void delete_elements (const octave_value_list& idx);\n\n  OCTINTERP_OVERRIDABLE_FUNC_API dim_vector\n  dims () const { return m_matrix.dims (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type\n  numel () const { return m_matrix.numel (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API int\n  ndims () const { return m_matrix.ndims (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type\n  nnz () const { return m_matrix.nnz (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  reshape (const dim_vector& new_dims) const\n  { return MT (m_matrix.reshape (new_dims)); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  permute (const Array<int>& vec, bool inv = false) const\n  { return MT (m_matrix.permute (vec, inv)); }\n\n  OCTINTERP_API octave_value\n  resize (const dim_vector& dv, bool fill = false) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType matrix_type () const\n  { return m_typ ? *m_typ : MatrixType (); }\n  OCTINTERP_API MatrixType matrix_type (const MatrixType& _typ) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  diag (octave_idx_type k = 0) const\n  { return octave_value (m_matrix.diag (k)); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  diag (octave_idx_type m, octave_idx_type n) const\n  { return octave_value (m_matrix.diag (m, n)); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const\n  {\n    if constexpr (std::is_same_v<MT, Cell>)\n      return octave_value (Cell (static_cast<Array<octave_value>>\n                                 (m_matrix.sort (dim, mode))));\n    else\n      return octave_value (m_matrix.sort (dim, mode));\n  }\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n        sortmode mode = ASCENDING) const\n  {\n    if constexpr (std::is_same_v<MT, Cell>)\n      return octave_value (Cell (static_cast<Array<octave_value>>\n                                 (m_matrix.sort (sidx, dim, mode))));\n    else\n      return octave_value (m_matrix.sort (sidx, dim, mode));\n  }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API sortmode issorted (sortmode mode = UNSORTED) const\n  { return m_matrix.issorted (mode); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API Array<octave_idx_type>\n  sort_rows_idx (sortmode mode = ASCENDING) const\n  { return m_matrix.sort_rows_idx (mode); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API sortmode\n  is_sorted_rows (sortmode mode = UNSORTED) const\n  { return m_matrix.is_sorted_rows (mode); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool\n  is_matrix_type () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool\n  is_full_num_matrix () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool isnumeric () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_defined () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_constant () const { return true; }\n\n  OCTINTERP_API bool is_true () const;\n\n  OCTINTERP_API bool print_as_scalar () const;\n\n  OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  OCTINTERP_API void\n  print_info (std::ostream& os, const std::string& prefix) const;\n\n  OCTINTERP_API void short_disp (std::ostream& os) const;\n\n  OCTINTERP_API float_display_format get_edit_display_format () const;\n\n  OCTINTERP_API std::string\n  edit_display (const float_display_format& fmt,\n                octave_idx_type i, octave_idx_type j) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API MT& matrix_ref ()\n  {\n    clear_cached_info ();\n    return m_matrix;\n  }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API const MT& matrix_ref () const\n  {\n    return m_matrix;\n  }\n\n  OCTINTERP_API octave_value\n  fast_elem_extract (octave_idx_type n) const;\n\n  OCTINTERP_API bool\n  fast_elem_insert (octave_idx_type n, const octave_value& x);\n\n  // This function exists to support the MEX interface.\n  // You should not use it anywhere else.\n  OCTINTERP_OVERRIDABLE_FUNC_API const void *\n  mex_get_data () const { return m_matrix.data (); }\n\nprotected:\n\n  MT m_matrix;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave::idx_vector\n  set_idx_cache (const octave::idx_vector& idx) const\n  {\n    delete m_idx_cache;\n    m_idx_cache = new octave::idx_vector (idx);\n    return idx;\n  }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API void clear_cached_info () const\n  {\n    delete m_typ; m_typ = nullptr;\n    delete m_idx_cache; m_idx_cache = nullptr;\n  }\n\n  mutable MatrixType *m_typ;\n  mutable octave::idx_vector *m_idx_cache;\n\nprivate:\n\n  // No assignment.\n\n  OCTINTERP_API octave_base_matrix& operator = (const octave_base_matrix&);\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-scalar-inst.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ov-base-scalar.cc\"\n\n// instantiate template class with types that need to be exported from library\n\ntemplate class OCTINTERP_API octave_base_scalar<bool>;\ntemplate class OCTINTERP_API octave_base_scalar<double>;\ntemplate class OCTINTERP_API octave_base_scalar<float>;\ntemplate class OCTINTERP_API octave_base_scalar<Complex>;\ntemplate class OCTINTERP_API octave_base_scalar<FloatComplex>;\ntemplate class OCTINTERP_API octave_base_scalar<octave_int8>;\ntemplate class OCTINTERP_API octave_base_scalar<octave_int16>;\ntemplate class OCTINTERP_API octave_base_scalar<octave_int32>;\ntemplate class OCTINTERP_API octave_base_scalar<octave_int64>;\ntemplate class OCTINTERP_API octave_base_scalar<octave_uint8>;\ntemplate class OCTINTERP_API octave_base_scalar<octave_uint16>;\ntemplate class OCTINTERP_API octave_base_scalar<octave_uint32>;\ntemplate class OCTINTERP_API octave_base_scalar<octave_uint64>;\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-scalar.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <ostream>\n#include <sstream>\n\n#include \"oct-inttypes-fwd.h\"\n\n#include \"ovl.h\"\n#include \"ov-base.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-base-scalar.h\"\n#include \"pr-output.h\"\n\ntemplate <typename ST>\noctave_value\noctave_base_scalar<ST>::subsref (const std::string& type,\n                                 const std::list<octave_value_list>& idx)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      retval = do_index_op (idx.front ());\n      break;\n\n    case '{':\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_base_scalar<T>::subsref - please report this bug\");\n    }\n\n  return retval.next_subsref (type, idx);\n}\n\ntemplate <typename ST>\noctave_value\noctave_base_scalar<ST>::subsasgn (const std::string& type,\n                                  const std::list<octave_value_list>& idx,\n                                  const octave_value& rhs)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        if (type.length () != 1)\n          {\n            std::string nm = type_name ();\n            error (\"in indexed assignment of %s, last rhs index must be ()\",\n                   nm.c_str ());\n          }\n\n        retval = numeric_assign (type, idx, rhs);\n      }\n      break;\n\n    case '{':\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_base_scalar<T>::subsasgn - please report this bug\");\n    }\n\n  return retval;\n}\n\ntemplate <typename ST>\ndim_vector\noctave_base_scalar<ST>::dims () const\n{\n  static dim_vector dv (1, 1);\n  return dv;\n}\n\ntemplate <typename ST>\noctave_value\noctave_base_scalar<ST>::permute (const Array<int>& vec, bool inv) const\n{\n  return Array<ST> (dim_vector (1, 1), scalar).permute (vec, inv);\n}\n\ntemplate <typename ST>\noctave_value\noctave_base_scalar<ST>::reshape (const dim_vector& new_dims) const\n{\n  return Array<ST> (dim_vector (1, 1), scalar).reshape (new_dims);\n}\n\ntemplate <typename ST>\noctave_value\noctave_base_scalar<ST>::diag (octave_idx_type k) const\n{\n  return Array<ST> (dim_vector (1, 1), scalar).diag (k);\n}\n\ntemplate <typename ST>\noctave_value\noctave_base_scalar<ST>::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return Array<ST> (dim_vector (1, 1), scalar).diag (m, n);\n}\n\ntemplate <typename ST>\nbool\noctave_base_scalar<ST>::is_true () const\n{\n  if (octave::math::isnan (scalar))\n    octave::err_nan_to_logical_conversion ();\n\n  return (scalar != ST ());\n}\n\ntemplate <typename ST>\nvoid\noctave_base_scalar<ST>::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\n\ntemplate <typename ST>\nvoid\noctave_base_scalar<ST>::print_raw (std::ostream& os,\n                                   bool pr_as_read_syntax) const\n{\n  indent (os);\n  octave_print_internal (os, scalar, pr_as_read_syntax);\n}\n\ntemplate <typename ST>\nbool\noctave_base_scalar<ST>::print_name_tag (std::ostream& os,\n                                        const std::string& name) const\n{\n  indent (os);\n  os << name << \" = \";\n  return false;\n}\n\ntemplate <typename ST>\nvoid\noctave_base_scalar<ST>::short_disp (std::ostream& os) const\n{\n  std::ostringstream buf;\n  octave_print_internal (buf, scalar);\n  std::string tmp = buf.str ();\n  std::size_t pos = tmp.find_first_not_of (' ');\n  if (pos != std::string::npos)\n    os << tmp.substr (pos);\n  else if (! tmp.empty ())\n    os << tmp[0];\n}\n\ntemplate <typename ST>\nfloat_display_format\noctave_base_scalar<ST>::get_edit_display_format () const\n{\n  return make_format (scalar);\n}\n\ntemplate <typename ST>\nstd::string\noctave_base_scalar<ST>::edit_display (const float_display_format& fmt,\n                                      octave_idx_type, octave_idx_type) const\n{\n  std::ostringstream buf;\n  octave_print_internal (buf, fmt, scalar);\n  return buf.str ();\n}\n\ntemplate <typename ST>\noctave_value\noctave_base_scalar<ST>::fast_elem_extract (octave_idx_type n) const\n{\n  return (n == 0) ? octave_value (scalar) : octave_value ();\n}\n\ntemplate <typename ST>\nbool\noctave_base_scalar<ST>::fast_elem_insert_self (void *where,\n    builtin_type_t btyp) const\n{\n\n  // Don't use builtin_type () here to avoid an extra VM call.\n  if (btyp == class_to_btyp<ST>::btyp)\n    {\n      *(reinterpret_cast<ST *> (where)) = scalar;\n      return true;\n    }\n  else\n    return false;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-scalar.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_base_scalar_h)\n#define octave_ov_base_scalar_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"MatrixType.h\"\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"str-vec.h\"\n\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n\n// Real scalar values.\n\ntemplate <typename ST>\nclass OCTINTERP_API octave_base_scalar : public octave_base_value\n{\npublic:\n\n  typedef ST scalar_type;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_scalar ()\n    : octave_base_value (), scalar () { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_scalar (const ST& s)\n    : octave_base_value (), scalar (s) { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_scalar (const octave_base_scalar& s)\n    : octave_base_value (), scalar (s.scalar) { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API ~octave_base_scalar () = default;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  squeeze () const { return scalar; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  full_value () const { return scalar; }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  OCTINTERP_API octave_value\n  subsref (const std::string& type, const std::list<octave_value_list>& idx);\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx, int)\n  { return subsref (type, idx); }\n\n  OCTINTERP_API octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_constant () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_defined () const { return true; }\n\n  OCTINTERP_API dim_vector dims () const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type numel () const { return 1; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API int ndims () const { return 2; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type\n  nnz () const { return (scalar != ST () ? 1 : 0); }\n\n  OCTINTERP_API octave_value permute (const Array<int>&, bool = false) const;\n\n  OCTINTERP_API octave_value reshape (const dim_vector& new_dims) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API std::size_t\n  byte_size () const { return sizeof (ST); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  all (int = 0) const { return (scalar != ST ()); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  any (int = 0) const { return (scalar != ST ()); }\n\n  OCTINTERP_API octave_value diag (octave_idx_type k = 0) const;\n\n  OCTINTERP_API octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  sort (octave_idx_type, sortmode) const\n  { return octave_value (scalar); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  sort (Array<octave_idx_type>& sidx, octave_idx_type, sortmode) const\n  {\n    sidx.resize (dim_vector (1, 1));\n    sidx(0) = 0;\n    return octave_value (scalar);\n  }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API sortmode\n  issorted (sortmode mode = UNSORTED) const\n  { return mode == UNSORTED ? ASCENDING : mode; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API Array<octave_idx_type>\n  sort_rows_idx (sortmode) const\n  {\n    return Array<octave_idx_type> (dim_vector (1, 1),\n                                   static_cast<octave_idx_type> (0));\n  }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API sortmode\n  is_sorted_rows (sortmode mode = UNSORTED) const\n  { return mode == UNSORTED ? ASCENDING : mode; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType\n  matrix_type () const\n  { return MatrixType::Diagonal; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType\n  matrix_type (const MatrixType&) const\n  { return matrix_type (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool\n  is_maybe_function () const { return false; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool\n  is_scalar_type () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool\n  isnumeric () const { return true; }\n\n  OCTINTERP_API bool is_true () const;\n\n  OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  OCTINTERP_API void\n  print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  OCTINTERP_API bool\n  print_name_tag (std::ostream& os, const std::string& name) const;\n\n  OCTINTERP_API void short_disp (std::ostream& os) const;\n\n  OCTINTERP_API float_display_format get_edit_display_format () const;\n\n  OCTINTERP_API std::string\n  edit_display (const float_display_format& fmt,\n                octave_idx_type i, octave_idx_type j) const;\n\n  // This function exists to support the MEX interface.\n  // You should not use it anywhere else.\n  OCTINTERP_OVERRIDABLE_FUNC_API const void *\n  mex_get_data () const { return &scalar; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API const ST& scalar_ref () const\n  { return scalar; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API ST& scalar_ref ()\n  { return scalar; }\n\n  OCTINTERP_API octave_value fast_elem_extract (octave_idx_type n) const;\n\n  OCTINTERP_API bool\n  fast_elem_insert_self (void *where, builtin_type_t btyp) const;\n\nprotected:\n\n  // The value of this scalar.\n  ST scalar;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-sparse-inst.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ov-base-sparse.cc\"\n\n// instantiate template class with types that need to be exported from library\n\ntemplate class OCTINTERP_API octave_base_sparse<SparseBoolMatrix>;\ntemplate class OCTINTERP_API octave_base_sparse<SparseComplexMatrix>;\ntemplate class OCTINTERP_API octave_base_sparse<SparseMatrix>;\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-sparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <iomanip>\n#include <istream>\n#include <ostream>\n#include <sstream>\n\n#include \"ovl.h\"\n#include \"ov-base.h\"\n#include \"quit.h\"\n#include \"pr-output.h\"\n\n#include \"byte-swap.h\"\n#include \"errwarn.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\n#include \"boolSparse.h\"\n#include \"ov-base-sparse.h\"\n#include \"octave-preserve-stream-state.h\"\n#include \"pager.h\"\n#include \"utils.h\"\n\n#include \"lo-array-errwarn.h\"\n\ntemplate <typename T>\noctave_value\noctave_base_sparse<T>::do_index_op (const octave_value_list& idx,\n                                    bool resize_ok)\n{\n  octave_value retval;\n\n  octave_idx_type n_idx = idx.length ();\n\n  // If we catch an indexing error in index_vector, we flag an error in\n  // index k.  Ensure it is the right value before each idx_vector call.\n  // Same variable as used in the for loop in the default case.\n\n  octave_idx_type k = 0;\n\n  try\n    {\n      switch (n_idx)\n        {\n        case 0:\n          retval = matrix;\n          break;\n\n        case 1:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            retval = octave_value (matrix.index (i, resize_ok));\n          }\n          break;\n\n        case 2:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            k = 1;\n            octave::idx_vector j = idx (1).index_vector ();\n\n            retval = octave_value (matrix.index (i, j, resize_ok));\n          }\n          break;\n\n        default:\n          error (\"only 2-D indexing is allowed for sparse arrays\");\n        }\n    }\n  catch (octave::index_exception& ie)\n    {\n      // Rethrow to allow more info to be reported later.\n      ie.set_pos_if_unset (n_idx, k+1);\n      throw;\n    }\n\n  return retval;\n}\n\ntemplate <typename T>\noctave_value\noctave_base_sparse<T>::subsref (const std::string& type,\n                                const std::list<octave_value_list>& idx)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      retval = do_index_op (idx.front ());\n      break;\n\n    case '{':\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_base_sparse<T>::subsref - please report this bug\");\n    }\n\n  return retval.next_subsref (type, idx);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_sparse<T>::subsasgn (const std::string& type,\n                                 const std::list<octave_value_list>& idx,\n                                 const octave_value& rhs)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        if (type.length () != 1)\n          {\n            std::string nm = type_name ();\n            error (\"in indexed assignment of %s, last lhs index must be ()\",\n                   nm.c_str ());\n          }\n\n        retval = numeric_assign (type, idx, rhs);\n      }\n      break;\n\n    case '{':\n    case '.':\n      {\n        if (! isempty ())\n          {\n            std::string nm = type_name ();\n            error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n          }\n\n        octave_value tmp = octave_value::empty_conv (type, rhs);\n\n        retval = tmp.subsasgn (type, idx, rhs);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_base_sparse<T>::subsasgn - please report this bug\");\n    }\n\n  return retval;\n}\n\ntemplate <typename MT>\nvoid\noctave_base_sparse<MT>::delete_elements (const octave_value_list& idx)\n{\n  octave_idx_type len = idx.length ();\n\n  // If we catch an indexing error in index_vector, we flag an error in\n  // index k.  Ensure it is the right value before each idx_vector call.\n  // Same variable as used in the for loop in the default case.\n\n  octave_idx_type k = 0;\n\n  try\n    {\n      switch (len)\n        {\n        case 1:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            matrix.delete_elements (i);\n\n            break;\n          }\n\n        case 2:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            k = 1;\n            octave::idx_vector j = idx (1).index_vector ();\n\n            matrix.delete_elements (i, j);\n\n            break;\n          }\n\n        default:\n          error (\"only 2-D indexing is allowed for sparse arrays\");\n        }\n    }\n  catch (octave::index_exception& ie)\n    {\n      // Rethrow to allow more info to be reported later.\n      ie.set_pos_if_unset (len, k+1);\n      throw;\n    }\n\n  // Invalidate the matrix type\n  typ.invalidate_type ();\n}\n\ntemplate <typename T>\noctave_value\noctave_base_sparse<T>::resize (const dim_vector& dv, bool) const\n{\n  T retval (matrix);\n  retval.resize (dv);\n  return retval;\n}\n\ntemplate <typename T>\nbool\noctave_base_sparse<T>::is_true () const\n{\n  bool retval = false;\n  const dim_vector& dv = matrix.dims ();\n  octave_idx_type nel = dv.numel ();\n  octave_idx_type nz = nnz ();\n\n  if (nel > 0)\n    {\n      T t1 (matrix.reshape (dim_vector (nel, 1)));\n\n      if (t1.any_element_is_nan ())\n        octave::err_nan_to_logical_conversion ();\n\n      if (nel > 1)\n        warn_array_as_logical (dv);\n\n      if (nz == nel)\n        {\n          SparseBoolMatrix t2 = t1.all ();\n\n          retval = t2(0);\n        }\n    }\n\n  return retval;\n}\n\ntemplate <typename T>\nbool\noctave_base_sparse<T>::print_as_scalar () const\n{\n  const dim_vector& dv = dims ();\n\n  return (dv.all_ones () || dv.any_zero ());\n}\n\ntemplate <typename T>\nvoid\noctave_base_sparse<T>::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\n\ntemplate <typename T>\nvoid\noctave_base_sparse<T>::print_info (std::ostream& os,\n                                   const std::string& prefix) const\n{\n  matrix.print_info (os, prefix);\n}\n\ntemplate <typename T>\nvoid\noctave_base_sparse<T>::print_raw (std::ostream& os,\n                                  bool pr_as_read_syntax) const\n{\n  octave::preserve_stream_state stream_state (os);\n\n  octave_idx_type nr = matrix.rows ();\n  octave_idx_type nc = matrix.cols ();\n  octave_idx_type nz = nnz ();\n\n  // FIXME: this should probably all be handled by a\n  // separate octave_print_internal function that can handle format\n  // compact, loose, etc.\n\n  os << \"Compressed Column Sparse (rows = \" << nr\n     << \", cols = \" << nc\n     << \", nnz = \" << nz;\n\n  // Avoid calling numel here since it can easily overflow\n  // octave_idx_type even when there is no real problem storing the\n  // sparse array.\n\n  double dnr = nr;\n  double dnc = nc;\n  double dnel = dnr * dnc;\n\n  if (dnel > 0)\n    {\n      double pct = (nz / dnel * 100);\n\n      // Display at least 2 significant digits, and up to 4 as we approach\n      // 100%.  Avoid having limited precision of the display result in\n      // reporting 100% for matrices that are not actually 100% full.\n      int prec;\n\n      if (pct <= 99)\n        prec = 2;\n      else if (pct <= 99.9 || pct == 100)\n        prec = 3;\n      else\n        {\n          // pct is in range (99.9, 100).\n          prec = 4;\n          if (pct > 99.99)\n            pct = 99.99;\n        }\n\n      os << \" [\" << std::setprecision (prec) << pct << \"%]\";\n    }\n\n  os << \")\\n\";\n\n  // add one to the printed indices to go from\n  //  zero-based to one-based arrays\n\n  if (nz != 0)\n    {\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          // FIXME: is there an easy way to get the max row\n          // and column indices so we can set the width appropriately\n          // and line up the columns here?  Similarly, we should look\n          // at all the nonzero values and display them with the same\n          // formatting rules that apply to columns of a matrix.\n\n          for (octave_idx_type i = matrix.cidx (j); i < matrix.cidx (j+1); i++)\n            {\n              os << \"\\n\";\n              os << \"  (\" << matrix.ridx (i)+1 << \", \"  << j+1 << \") -> \";\n\n              octave_print_internal (os, matrix.data (i), pr_as_read_syntax);\n            }\n        }\n    }\n}\n\ntemplate <typename MT>\nfloat_display_format\noctave_base_sparse<MT>::get_edit_display_format () const\n{\n  return float_display_format ();\n  //  return make_format (this->matrix);\n}\n\ntemplate <typename MT>\nstd::string\noctave_base_sparse<MT>::edit_display (const float_display_format& fmt,\n                                      octave_idx_type i,\n                                      octave_idx_type j) const\n{\n  std::ostringstream buf;\n  octave_print_internal (buf, fmt, this->matrix(i, j));\n  return buf.str ();\n}\n\ntemplate <typename T>\nbool\noctave_base_sparse<T>::save_ascii (std::ostream& os)\n{\n  const dim_vector& dv = this->dims ();\n\n  // Ensure that additional memory is deallocated\n  matrix.maybe_compress ();\n\n  os << \"# nnz: \"      << nnz () << \"\\n\";\n  os << \"# rows: \"     << dv(0) << \"\\n\";\n  os << \"# columns: \"  << dv(1) << \"\\n\";\n\n  os << this->matrix;\n\n  return true;\n}\n\ntemplate <typename T>\nbool\noctave_base_sparse<T>::load_ascii (std::istream& is)\n{\n  octave_idx_type nz = 0;\n  octave_idx_type nr = 0;\n  octave_idx_type nc = 0;\n\n  if (! extract_keyword (is, \"nnz\", nz, true)\n      || ! extract_keyword (is, \"rows\", nr, true)\n      || ! extract_keyword (is, \"columns\", nc, true))\n    error (\"load: failed to extract number of rows and columns\");\n\n  T tmp (nr, nc, nz);\n\n  if (nz > 0)\n    {\n      is >> tmp;\n\n      if (! is)\n        error (\"load: failed to load matrix constant\");\n    }\n\n  matrix = tmp;\n\n  return true;\n}\n\n/*\n%!test <64696>\n%! A = B = sparse (1, 2);\n%! assert (nnz (A), 0);\n%! assert (nnz (B), 0);\n%! txt_file = [tempname(), \".dat\"];\n%! unwind_protect\n%!   save (\"-text\", txt_file, \"A\", \"B\");\n%!   s = load (txt_file);\n%! unwind_protect_cleanup\n%!   delete ([txt_file, '*']);\n%! end_unwind_protect\n%! assert (s.A, A);\n%! assert (s.B, B);\n*/\n\ntemplate <typename T>\noctave_value\noctave_base_sparse<T>::fast_elem_extract (octave_idx_type n) const\n{\n  octave_idx_type nr = matrix.rows ();\n  octave_idx_type nc = matrix.cols ();\n\n  octave_idx_type i = n % nr;\n  octave_idx_type j = n / nr;\n\n  return (i < nr && j < nc) ? octave_value (matrix(i, j)) : octave_value ();\n}\n\ntemplate <typename T>\noctave_value\noctave_base_sparse<T>::map (octave_base_value::unary_mapper_t umap) const\n{\n  if (umap == umap_xtolower || umap == umap_xtoupper)\n    return matrix;\n\n  // Try the map on the dense value.\n  // FIXME: We should probably be smarter about this, especially for the\n  // cases that are expected to return sparse matrices.\n  octave_value retval = this->full_value ().map (umap);\n\n  // Sparsify the result if possible.\n\n  switch (umap)\n    {\n    case umap_xisalnum:\n    case umap_xisalpha:\n    case umap_xisascii:\n    case umap_xiscntrl:\n    case umap_xisdigit:\n    case umap_xisgraph:\n    case umap_xislower:\n    case umap_xisprint:\n    case umap_xispunct:\n    case umap_xisspace:\n    case umap_xisupper:\n    case umap_xisxdigit:\n      // FIXME: intentionally skip this step for string mappers.\n      // Is this wanted?\n      break;\n\n    default:\n      {\n        switch (retval.builtin_type ())\n          {\n          case btyp_double:\n            retval = retval.sparse_matrix_value ();\n            break;\n\n          case btyp_complex:\n            retval = retval.sparse_complex_matrix_value ();\n            break;\n\n          case btyp_bool:\n            retval = retval.sparse_bool_matrix_value ();\n            break;\n\n          default:\n            break;\n          }\n      }\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-base-sparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_base_sparse_h)\n#define octave_ov_base_sparse_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n\n#include \"boolSparse.h\"\n#include \"MatrixType.h\"\n\nclass octave_sparse_bool_matrix;\n\ntemplate <typename T>\nclass OCTINTERP_TEMPLATE_API octave_base_sparse : public octave_base_value\n{\npublic:\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_sparse ()\n    : octave_base_value (), matrix (), typ (MatrixType ())\n  { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_sparse (const T& a)\n    : octave_base_value (), matrix (a), typ (MatrixType ())\n  {\n    if (matrix.ndims () == 0)\n      matrix.resize (dim_vector (0, 0));\n  }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_sparse (const T& a, const MatrixType& t)\n    : octave_base_value (), matrix (a), typ (t)\n  {\n    if (matrix.ndims () == 0)\n      matrix.resize (dim_vector (0, 0));\n  }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API\n  octave_base_sparse (const octave_base_sparse& a)\n    : octave_base_value (), matrix (a.matrix), typ (a.typ) { }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API ~octave_base_sparse () = default;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type numel () const\n  { return dims ().safe_numel (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type nnz () const\n  { return matrix.nnz (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type nzmax () const\n  { return matrix.nzmax (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API std::size_t byte_size () const\n  { return matrix.byte_size (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value squeeze () const\n  { return matrix.squeeze (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value full_value () const\n  { return matrix.matrix_value (); }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  OCTINTERP_API octave_value\n  subsref (const std::string& type, const std::list<octave_value_list>& idx);\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int)\n  { return subsref (type, idx); }\n\n  OCTINTERP_API octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  // FIXME: should we import the functions from the base class and\n  // overload them here, or should we use a different name so we don't\n  // have to do this?  Without the using declaration or a name change,\n  // the base class functions will be hidden.  That may be OK, but it\n  // can also cause some confusion.\n  using octave_base_value::assign;\n\n  template <typename RHS_T>\n  void assign (const octave_value_list& idx, const RHS_T& rhs)\n  {\n    octave_idx_type len = idx.length ();\n\n    // If we catch an indexing error in index_vector, we flag an error in\n    // index k.  Ensure it is the right value before each idx_vector call.\n    // Same variable as used in the for loop in the default case.\n\n    octave_idx_type k = 0;\n\n    try\n      {\n        switch (len)\n          {\n          case 1:\n            {\n              octave::idx_vector i = idx (0).index_vector ();\n\n              matrix.assign (i, rhs);\n\n              break;\n            }\n\n          case 2:\n            {\n              octave::idx_vector i = idx (0).index_vector ();\n\n              k = 1;\n              octave::idx_vector j = idx (1).index_vector ();\n\n              matrix.assign (i, j, rhs);\n\n              break;\n            }\n\n          default:\n            error (\"only 2-D indexing is allowed for sparse arrays\");\n          }\n      }\n    catch (octave::index_exception& ie)\n      {\n        // Rethrow to allow more info to be reported later.\n        ie.set_pos_if_unset (len, k+1);\n        throw;\n      }\n\n    // Invalidate matrix type.\n    typ.invalidate_type ();\n  }\n\n  OCTINTERP_API void delete_elements (const octave_value_list& idx);\n\n  OCTINTERP_OVERRIDABLE_FUNC_API dim_vector dims () const\n  { return matrix.dims (); }\n\n  OCTINTERP_API octave_value\n  do_index_op (const octave_value_list& idx, bool resize_ok = false);\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value reshape (const dim_vector& new_dims) const\n  { return T (matrix.reshape (new_dims)); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  permute (const Array<int>& vec, bool inv = false) const\n  { return T (matrix.permute (vec, inv)); }\n\n  OCTINTERP_API octave_value resize (const dim_vector& dv, bool = false) const;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value all (int dim = 0) const\n  { return matrix.all (dim); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value any (int dim = 0) const\n  { return matrix.any (dim); }\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::diag;\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value diag (octave_idx_type k = 0) const\n  { return octave_value (matrix.diag (k)); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const\n  { return octave_value (matrix.sort (dim, mode)); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API octave_value\n  sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n        sortmode mode = ASCENDING) const\n  { return octave_value (matrix.sort (sidx, dim, mode)); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API sortmode\n  issorted (sortmode mode = UNSORTED) const\n  { return full_value ().issorted (mode); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType matrix_type () const\n  { return typ; }\n  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType\n  matrix_type (const MatrixType& _typ) const\n  { MatrixType ret = typ; typ = _typ; return ret; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_matrix_type () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool isnumeric () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool issparse () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_defined () const { return true; }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API bool is_constant () const { return true; }\n\n  OCTINTERP_API bool is_true () const;\n\n  OCTINTERP_API bool print_as_scalar () const;\n\n  OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  OCTINTERP_API void\n  print_info (std::ostream& os, const std::string& prefix) const;\n\n  OCTINTERP_API void\n  print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  OCTINTERP_API bool load_ascii (std::istream& is);\n\n  OCTINTERP_API float_display_format get_edit_display_format () const;\n\n  OCTINTERP_API std::string\n  edit_display (const float_display_format& fmt,\n                octave_idx_type i, octave_idx_type j) const;\n\n  // These functions exists to support the MEX interface.\n  // You should not use them anywhere else.\n  OCTINTERP_OVERRIDABLE_FUNC_API const void * mex_get_data () const\n  { return matrix.data (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API const octave_idx_type * mex_get_ir () const\n  { return matrix.ridx (); }\n\n  OCTINTERP_OVERRIDABLE_FUNC_API const octave_idx_type * mex_get_jc () const\n  { return matrix.cidx (); }\n\n  OCTINTERP_API octave_value fast_elem_extract (octave_idx_type n) const;\n\nprotected:\n\n  OCTINTERP_API octave_value\n  map (octave_base_value::unary_mapper_t umap) const;\n\n  T matrix;\n\n  mutable MatrixType typ;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-base.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"mxarray.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-map.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n#include \"ov-cell.h\"\n#include \"ov-ch-mat.h\"\n#include \"ov-classdef.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-range.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-str-mat.h\"\n#include \"ovl.h\"\n#include \"parse.h\"\n#include \"pr-flt-fmt.h\"\n#include \"pr-output.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"ov-inline.h\"\n\nbuiltin_type_t\nbtyp_mixed_numeric (builtin_type_t x, builtin_type_t y)\n{\n  builtin_type_t retval = btyp_unknown;\n\n  if (x == btyp_bool)\n    x = btyp_double;\n  if (y == btyp_bool)\n    y = btyp_double;\n\n  if (x <= btyp_float_complex && y <= btyp_float_complex)\n    retval = static_cast<builtin_type_t> (x | y);\n  else if (x <= btyp_uint64 && y <= btyp_float)\n    retval = x;\n  else if (x <= btyp_float && y <= btyp_uint64)\n    retval = y;\n  else if ((x >= btyp_int8 && x <= btyp_int64\n            && y >= btyp_int8 && y <= btyp_int64)\n           || (x >= btyp_uint8 && x <= btyp_uint64\n               && y >= btyp_uint8 && y <= btyp_uint64))\n    retval = (x > y) ? x : y;\n\n  return retval;\n}\n\nstd::string btyp_class_name[btyp_num_types+1] =\n{\n  \"double\", \"single\", \"double\", \"single\",\n  \"int8\", \"int16\", \"int32\", \"int64\",\n  \"uint8\", \"uint16\", \"uint32\", \"uint64\",\n  \"logical\", \"char\",\n  \"struct\", \"cell\", \"function_handle\", \"unknown\"\n};\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_base_value,\n                                     \"<unknown type>\", \"unknown\");\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // Disable this warning for the use of the \"count\" member variable in\n   // the default constructor.  Push the current state so we can restore\n   // the warning state.\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n#endif\n\noctave_base_value::octave_base_value () : m_count (1) { }\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n#  pragma GCC diagnostic pop\n#endif\n\noctave_base_value *\noctave_base_value::empty_clone () const\n{\n  return resize (dim_vector ()).clone ();\n}\n\n// FIXME: Unlike other virtual functions in the octave_base_value\n// class, the storable_value and make_storable_value functions defined\n// here are not used by the corresponding octave_value functions.  This\n// inconsistency is likely to cause some confusion.\noctave_value\noctave_base_value::storable_value ()\n{\n  return octave_value_factory::make_copy (this);\n}\n\noctave_base_value *\noctave_base_value::make_storable_value ()\n{\n  return this;\n}\n\noctave_value\noctave_base_value::squeeze () const\n{\n  std::string nm = type_name ();\n  error (\"squeeze: invalid operation for %s type\", nm.c_str ());\n}\n\noctave_value\noctave_base_value::full_value () const\n{\n  err_wrong_type_arg (\"full: invalid operation for %s type\", type_name ());\n}\n\noctave_value\noctave_base_value::as_double () const\n{\n  err_invalid_conversion (type_name (), \"double\");\n}\n\noctave_value\noctave_base_value::as_double_or_copy ()\n{\n  const octave_base_value *cthis = this;\n  return cthis->as_double ();\n}\n\noctave_value\noctave_base_value::as_single () const\n{\n  err_invalid_conversion (type_name (), \"single\");\n}\n\noctave_value\noctave_base_value::as_int8 () const\n{\n  err_invalid_conversion (type_name (), \"int8\");\n}\n\noctave_value\noctave_base_value::as_int16 () const\n{\n  err_invalid_conversion (type_name (), \"int16\");\n}\n\noctave_value\noctave_base_value::as_int32 () const\n{\n  err_invalid_conversion (type_name (), \"int32\");\n}\n\noctave_value\noctave_base_value::as_int64 () const\n{\n  err_invalid_conversion (type_name (), \"int64\");\n}\n\noctave_value\noctave_base_value::as_uint8 () const\n{\n  err_invalid_conversion (type_name (), \"uint8\");\n}\n\noctave_value\noctave_base_value::as_uint16 () const\n{\n  err_invalid_conversion (type_name (), \"uint16\");\n}\n\noctave_value\noctave_base_value::as_uint32 () const\n{\n  err_invalid_conversion (type_name (), \"uint32\");\n}\n\noctave_value\noctave_base_value::as_uint64 () const\n{\n  err_invalid_conversion (type_name (), \"uint64\");\n}\n\nMatrix\noctave_base_value::size ()\n{\n  const dim_vector dv = dims ();\n  Matrix mdv (1, dv.ndims ());\n  for (octave_idx_type i = 0; i < dv.ndims (); i++)\n    mdv(i) = dv(i);\n  return mdv;\n}\n\noctave_idx_type\noctave_base_value::xnumel (const octave_value_list& idx)\n{\n  return octave::dims_to_numel (dims (), idx);\n}\n\noctave_value_list\noctave_base_value::\nsimple_subsref (char type, octave_value_list& idx, int nargout)\n{\n  std::list<octave_value_list> idx_list;\n  idx_list.push_back (idx);\n  return subsref (std::string {type}, idx_list, nargout);\n}\n\noctave_value\noctave_base_value::subsref (const std::string&,\n                            const std::list<octave_value_list>&)\n{\n  std::string nm = type_name ();\n  error (\"can't perform indexing operations for %s type\", nm.c_str ());\n}\n\noctave_value_list\noctave_base_value::subsref (const std::string&,\n                            const std::list<octave_value_list>&, int)\n{\n  std::string nm = type_name ();\n  error (\"can't perform indexing operations for %s type\", nm.c_str ());\n}\n\noctave_value\noctave_base_value::subsref (const std::string& type,\n                            const std::list<octave_value_list>& idx,\n                            bool /* auto_add */)\n{\n  // This way we may get a more meaningful error message.\n  return subsref (type, idx);\n}\n\noctave_value\noctave_base_value::do_index_op (const octave_value_list&, bool)\n{\n  std::string nm = type_name ();\n  error (\"can't perform indexing operations for %s type\", nm.c_str ());\n}\n\noctave::idx_vector\noctave_base_value::index_vector (bool /* require_integers */) const\n{\n  std::string nm = '<' + type_name () + '>';\n  octave::err_invalid_index (nm.c_str ());\n}\n\noctave_value\noctave_base_value::simple_subsasgn (char type, octave_value_list& idx,\n                                    const octave_value& rhs)\n{\n  std::list<octave_value_list> idx_list;\n  idx_list.push_back (idx);\n\n  return subsasgn (std::string {type}, idx_list, rhs);\n}\n\noctave_value\noctave_base_value::subsasgn (const std::string& type,\n                             const std::list<octave_value_list>& idx,\n                             const octave_value& rhs)\n{\n  octave_value retval;\n\n  if (is_defined ())\n    {\n      if (! isnumeric ())\n        {\n          std::string nm = type_name ();\n          error (\"can't perform indexed assignment for %s type\", nm.c_str ());\n        }\n\n      switch (type[0])\n        {\n        case '(':\n          {\n            if (type.length () == 1)\n              retval = numeric_assign (type, idx, rhs);\n            else if (isempty ())\n              {\n                // Allow conversion of empty matrix to some other\n                // type in cases like\n                //\n                //  x = []; x(i).f = rhs\n\n                octave_value tmp = octave_value::empty_conv (type, rhs);\n\n                retval = tmp.subsasgn (type, idx, rhs);\n              }\n            else\n              {\n                std::string nm = type_name ();\n                error (\"in indexed assignment of %s, last rhs index must be ()\",\n                       nm.c_str ());\n              }\n          }\n          break;\n\n        case '{':\n        case '.':\n          {\n            std::string nm = type_name ();\n            error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n          }\n          break;\n\n        default:\n          error (\"unexpected: index not '(', '{', or '.' in octave_base_value::subsasgn - please report this bug\");\n        }\n    }\n  else\n    {\n      // Create new object of appropriate type for given index and rhs\n      // types and then call undef_subsasgn for that object.\n\n      octave_value tmp = octave_value::empty_conv (type, rhs);\n\n      retval = tmp.undef_subsasgn (type, idx, rhs);\n    }\n\n  return retval;\n}\n\noctave_value\noctave_base_value::undef_subsasgn (const std::string& type,\n                                   const std::list<octave_value_list>& idx,\n                                   const octave_value& rhs)\n{\n  // In most cases, undef_subsasgn is handled the sams as subsasgn.  One\n  // exception is octave_class objects.\n\n  return subsasgn (type, idx, rhs);\n}\n\noctave_idx_type\noctave_base_value::nnz () const\n{\n  err_wrong_type_arg (\"octave_base_value::nnz ()\", type_name ());\n}\n\noctave_idx_type\noctave_base_value::nzmax () const\n{\n  return numel ();\n}\n\noctave_idx_type\noctave_base_value::nfields () const\n{\n  err_wrong_type_arg (\"octave_base_value::nfields ()\", type_name ());\n}\n\noctave_value\noctave_base_value::reshape (const dim_vector&) const\n{\n  err_wrong_type_arg (\"octave_base_value::reshape ()\", type_name ());\n}\n\noctave_value\noctave_base_value::permute (const Array<int>&, bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::permute ()\", type_name ());\n}\n\noctave_value\noctave_base_value::resize (const dim_vector&, bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::resize ()\", type_name ());\n}\n\nMatrixType\noctave_base_value::matrix_type () const\n{\n  err_wrong_type_arg (\"octave_base_value::matrix_type ()\", type_name ());\n}\n\nMatrixType\noctave_base_value::matrix_type (const MatrixType&) const\n{\n  err_wrong_type_arg (\"octave_base_value::matrix_type ()\", type_name ());\n}\n\noctave_value\noctave_base_value::all (int) const\n{\n  err_wrong_type_arg (\"octave_base_value::all ()\", type_name ());\n}\n\noctave_value\noctave_base_value::any (int) const\n{\n  err_wrong_type_arg (\"octave_base_value::any ()\", type_name ());\n}\n\noctave_value\noctave_base_value::convert_to_str (bool pad, bool force, char type) const\n{\n  octave_value retval = convert_to_str_internal (pad, force, type);\n\n  if (! force && isnumeric ())\n    warn_implicit_conversion (\"Octave:num-to-str\",\n                              type_name (), retval.type_name ());\n\n  return retval;\n}\n\noctave_value\noctave_base_value::convert_to_str_internal (bool, bool, char) const\n{\n  err_wrong_type_arg (\"octave_base_value::convert_to_str_internal ()\",\n                      type_name ());\n}\n\nvoid\noctave_base_value::convert_to_row_or_column_vector ()\n{\n  err_wrong_type_arg\n  (\"octave_base_value::convert_to_row_or_column_vector ()\", type_name ());\n}\n\nvoid\noctave_base_value::print (std::ostream&, bool)\n{\n  err_wrong_type_arg (\"octave_base_value::print ()\", type_name ());\n}\n\nvoid\noctave_base_value::print_raw (std::ostream&, bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::print_raw ()\", type_name ());\n}\n\nbool\noctave_base_value::print_name_tag (std::ostream& os,\n                                   const std::string& name) const\n{\n  indent (os);\n\n  if (print_as_scalar ())\n    os << name << \" = \";\n  else\n    {\n      os << name << \" =\";\n      newline (os);\n      if (! Vcompact_format)\n        newline (os);\n\n      return true;\n    }\n\n  return false;\n}\n\nvoid\noctave_base_value::print_with_name (std::ostream& output_buf,\n                                    const std::string& name,\n                                    bool print_padding)\n{\n  bool pad_after = print_name_tag (output_buf, name);\n\n  print (output_buf);\n\n  if (print_padding && pad_after && ! Vcompact_format)\n    newline (output_buf);\n}\n\nfloat_display_format\noctave_base_value::get_edit_display_format () const\n{\n  return float_display_format ();\n}\n\nvoid\noctave_base_value::print_info (std::ostream& os,\n                               const std::string& /* prefix */) const\n{\n  os << \"no info for type: \" << type_name () << \"\\n\";\n}\n\n#define INT_CONV_METHOD(T, F)                                           \\\n  T                                                                     \\\n  octave_base_value::F ## _value (bool require_int, bool frc_str_conv) const \\\n  {                                                                     \\\n    T retval = 0;                                                       \\\n                                                                        \\\n    double d = 0.0;                                                     \\\n                                                                        \\\n    try                                                                 \\\n      {                                                                 \\\n        d = double_value (frc_str_conv);                                \\\n      }                                                                 \\\n    catch (octave::execution_exception& ee)                               \\\n      {                                                                 \\\n        err_wrong_type_arg (ee, \"octave_base_value::\" #F \"_value ()\", type_name ()); \\\n      }                                                                 \\\n                                                                        \\\n    static constexpr double out_of_range_top                            \\\n      = static_cast<double> (std::numeric_limits<T>::max ()) + 1.0;     \\\n    if (require_int && octave::math::round (d) != d)                    \\\n      error_with_cfn (\"conversion of %g to \" #T \" value failed\", d);    \\\n    else if (d < std::numeric_limits<T>::min ())                        \\\n      retval = std::numeric_limits<T>::min ();                          \\\n    else if (d >= out_of_range_top)                                     \\\n      retval = std::numeric_limits<T>::max ();                          \\\n    else                                                                \\\n      retval = static_cast<T> (octave::math::fix (d));                  \\\n                                                                        \\\n    return retval;                                                      \\\n  }\n\nINT_CONV_METHOD (short int, short)\nINT_CONV_METHOD (unsigned short int, ushort)\n\nINT_CONV_METHOD (int, int)\nINT_CONV_METHOD (unsigned int, uint)\n\nINT_CONV_METHOD (long int, long)\nINT_CONV_METHOD (unsigned long int, ulong)\n\nINT_CONV_METHOD (int64_t, int64)\nINT_CONV_METHOD (uint64_t, uint64)\n\nint\noctave_base_value::nint_value (bool frc_str_conv) const\n{\n  double d = 0.0;\n\n  try\n    {\n      d = double_value (frc_str_conv);\n    }\n  catch (octave::execution_exception& ee)\n    {\n      err_wrong_type_arg (ee, \"octave_base_value::nint_value ()\", type_name ());\n    }\n\n  if (octave::math::isnan (d))\n    error (\"conversion of NaN to integer value failed\");\n\n  return static_cast<int> (octave::math::fix (d));\n}\n\ndouble\noctave_base_value::double_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::double_value ()\", type_name ());\n}\n\nfloat\noctave_base_value::float_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::float_value ()\", type_name ());\n}\n\nCell\noctave_base_value::cell_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::cell_value()\", type_name ());\n}\n\nMatrix\noctave_base_value::matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::matrix_value()\", type_name ());\n}\n\nFloatMatrix\noctave_base_value::float_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::float_matrix_value()\", type_name ());\n}\n\nNDArray\noctave_base_value::array_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::array_value()\", type_name ());\n}\n\nFloatNDArray\noctave_base_value::float_array_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::float_array_value()\", type_name ());\n}\n\nComplex\noctave_base_value::complex_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::complex_value()\", type_name ());\n}\n\nFloatComplex\noctave_base_value::float_complex_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::float_complex_value()\", type_name ());\n}\n\nComplexMatrix\noctave_base_value::complex_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::complex_matrix_value()\",\n                      type_name ());\n}\n\nFloatComplexMatrix\noctave_base_value::float_complex_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::float_complex_matrix_value()\",\n                      type_name ());\n}\n\nComplexNDArray\noctave_base_value::complex_array_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::complex_array_value()\", type_name ());\n}\n\nFloatComplexNDArray\noctave_base_value::float_complex_array_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::float_complex_array_value()\",\n                      type_name ());\n}\n\nbool\noctave_base_value::bool_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::bool_value()\", type_name ());\n}\n\nboolMatrix\noctave_base_value::bool_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::bool_matrix_value()\", type_name ());\n}\n\nboolNDArray\noctave_base_value::bool_array_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::bool_array_value()\", type_name ());\n}\n\ncharMatrix\noctave_base_value::char_matrix_value (bool force) const\n{\n  octave_value tmp = convert_to_str (false, force);\n\n  return tmp.char_matrix_value ();\n}\n\ncharNDArray\noctave_base_value::char_array_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::char_array_value()\", type_name ());\n}\n\nSparseMatrix\noctave_base_value::sparse_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::sparse_matrix_value()\", type_name ());\n}\n\nSparseComplexMatrix\noctave_base_value::sparse_complex_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::sparse_complex_matrix_value()\",\n                      type_name ());\n}\n\nSparseBoolMatrix\noctave_base_value::sparse_bool_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::sparse_bool_matrix_value()\",\n                      type_name ());\n}\n\nDiagMatrix\noctave_base_value::diag_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::diag_matrix_value()\", type_name ());\n}\n\nFloatDiagMatrix\noctave_base_value::float_diag_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::float_diag_matrix_value()\",\n                      type_name ());\n}\n\nComplexDiagMatrix\noctave_base_value::complex_diag_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::complex_diag_matrix_value()\",\n                      type_name ());\n}\n\nFloatComplexDiagMatrix\noctave_base_value::float_complex_diag_matrix_value (bool) const\n{\n  err_wrong_type_arg (\"octave_base_value::float_complex_diag_matrix_value()\",\n                      type_name ());\n}\n\nPermMatrix\noctave_base_value::perm_matrix_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::perm_matrix_value()\", type_name ());\n}\n\noctave_int8\noctave_base_value::int8_scalar_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::int8_scalar_value()\", type_name ());\n}\n\noctave_int16\noctave_base_value::int16_scalar_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::int16_scalar_value()\", type_name ());\n}\n\noctave_int32\noctave_base_value::int32_scalar_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::int32_scalar_value()\", type_name ());\n}\n\noctave_int64\noctave_base_value::int64_scalar_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::int64_scalar_value()\", type_name ());\n}\n\noctave_uint8\noctave_base_value::uint8_scalar_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::uint8_scalar_value()\", type_name ());\n}\n\noctave_uint16\noctave_base_value::uint16_scalar_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::uint16_scalar_value()\", type_name ());\n}\n\noctave_uint32\noctave_base_value::uint32_scalar_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::uint32_scalar_value()\", type_name ());\n}\n\noctave_uint64\noctave_base_value::uint64_scalar_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::uint64_scalar_value()\", type_name ());\n}\n\nint8NDArray\noctave_base_value::int8_array_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::int8_array_value()\", type_name ());\n}\n\nint16NDArray\noctave_base_value::int16_array_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::int16_array_value()\", type_name ());\n}\n\nint32NDArray\noctave_base_value::int32_array_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::int32_array_value()\", type_name ());\n}\n\nint64NDArray\noctave_base_value::int64_array_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::int64_array_value()\", type_name ());\n}\n\nuint8NDArray\noctave_base_value::uint8_array_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::uint8_array_value()\", type_name ());\n}\n\nuint16NDArray\noctave_base_value::uint16_array_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::uint16_array_value()\", type_name ());\n}\n\nuint32NDArray\noctave_base_value::uint32_array_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::uint32_array_value()\", type_name ());\n}\n\nuint64NDArray\noctave_base_value::uint64_array_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::uint64_array_value()\", type_name ());\n}\n\nstring_vector\noctave_base_value::string_vector_value (bool pad) const\n{\n  octave_value tmp = convert_to_str (pad, true);\n\n  return tmp.string_vector_value ();\n}\n\nstd::string\noctave_base_value::string_value (bool force) const\n{\n  octave_value tmp = convert_to_str (force);\n\n  return tmp.string_value ();\n}\n\nstd::string\noctave_base_value::xstring_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::xstring_value()\", type_name ());\n}\n\nArray<std::string>\noctave_base_value::cellstr_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::cellstr_value()\", type_name ());\n}\n\noctave::range<double>\noctave_base_value::range_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::range_value()\", type_name ());\n}\n\n// For now, enable only range<double>.\n\noctave_map\noctave_base_value::map_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::map_value()\", type_name ());\n}\n\noctave_scalar_map\noctave_base_value::scalar_map_value () const\n{\n  octave_map tmp = map_value ();\n\n  if (tmp.numel () != 1)\n    error (\"invalid conversion of multi-dimensional struct to scalar struct\");\n\n  return octave_scalar_map (tmp.checkelem (0));\n}\n\nstring_vector\noctave_base_value::map_keys () const\n{\n  err_wrong_type_arg (\"octave_base_value::map_keys()\", type_name ());\n}\n\nbool\noctave_base_value::isfield (const std::string&) const\n{\n  err_wrong_type_arg (\"octave_base_value::isfield()\", type_name ());\n}\n\nstd::size_t\noctave_base_value::nparents () const\n{\n  err_wrong_type_arg (\"octave_base_value::nparents()\", type_name ());\n}\n\nstd::list<std::string>\noctave_base_value::parent_class_name_list () const\n{\n  err_wrong_type_arg (\"octave_base_value::parent_class_name_list()\",\n                      type_name ());\n}\n\nstring_vector\noctave_base_value::parent_class_names () const\n{\n  err_wrong_type_arg (\"octave_base_value::parent_class_names()\", type_name ());\n}\n\noctave_classdef *\noctave_base_value::classdef_object_value (bool silent)\n{\n  if (! silent)\n    err_wrong_type_arg (\"octave_base_value::classdef_object_value()\",\n                        type_name ());\n\n  return nullptr;\n}\n\noctave_function *\noctave_base_value::function_value (bool silent)\n{\n  if (! silent)\n    err_wrong_type_arg (\"octave_base_value::function_value()\", type_name ());\n\n  return nullptr;\n}\n\noctave_user_function *\noctave_base_value::user_function_value (bool silent)\n{\n  if (! silent)\n    err_wrong_type_arg (\"octave_base_value::user_function_value()\",\n                        type_name ());\n  return nullptr;\n}\n\noctave_user_script *\noctave_base_value::user_script_value (bool silent)\n{\n  if (! silent)\n    err_wrong_type_arg (\"octave_base_value::user_script_value()\", type_name ());\n\n  return nullptr;\n}\n\noctave_user_code *\noctave_base_value::user_code_value (bool silent)\n{\n  if (! silent)\n    err_wrong_type_arg (\"octave_base_value::user_code_value()\", type_name ());\n\n  return nullptr;\n}\n\noctave_fcn_handle *\noctave_base_value::fcn_handle_value (bool silent)\n{\n  if (! silent)\n    err_wrong_type_arg (\"octave_base_value::fcn_handle_value()\", type_name ());\n\n  return nullptr;\n}\n\noctave_value_list\noctave_base_value::list_value () const\n{\n  err_wrong_type_arg (\"octave_base_value::list_value()\", type_name ());\n}\n\nbool\noctave_base_value::save_ascii (std::ostream&)\n{\n  err_wrong_type_arg (\"octave_base_value::save_ascii()\", type_name ());\n}\n\nbool\noctave_base_value::load_ascii (std::istream&)\n{\n  err_wrong_type_arg (\"octave_base_value::load_ascii()\", type_name ());\n}\n\nbool\noctave_base_value::save_binary (std::ostream&, bool)\n{\n  err_wrong_type_arg (\"octave_base_value::save_binary()\", type_name ());\n}\n\nbool\noctave_base_value::load_binary (std::istream&, bool,\n                                octave::mach_info::float_format)\n{\n  err_wrong_type_arg (\"octave_base_value::load_binary()\", type_name ());\n}\n\nbool\noctave_base_value::save_hdf5 (octave_hdf5_id, const char *, bool)\n{\n  err_wrong_type_arg (\"octave_base_value::save_binary()\", type_name ());\n}\n\nbool\noctave_base_value::load_hdf5 (octave_hdf5_id, const char *)\n{\n  err_wrong_type_arg (\"octave_base_value::load_binary()\", type_name ());\n}\n\nint\noctave_base_value::write (octave::stream&, int, oct_data_conv::data_type,\n                          int, octave::mach_info::float_format) const\n{\n  err_wrong_type_arg (\"octave_base_value::write()\", type_name ());\n}\n\nmxArray *\noctave_base_value::as_mxArray (bool) const\n{\n  return nullptr;\n}\n\noctave_value\noctave_base_value::diag (octave_idx_type) const\n{\n  err_wrong_type_arg (\"octave_base_value::diag ()\", type_name ());\n}\n\noctave_value\noctave_base_value::diag (octave_idx_type, octave_idx_type) const\n{\n  err_wrong_type_arg (\"octave_base_value::diag ()\", type_name ());\n}\n\noctave_value\noctave_base_value::sort (octave_idx_type, sortmode) const\n{\n  err_wrong_type_arg (\"octave_base_value::sort ()\", type_name ());\n}\n\noctave_value\noctave_base_value::sort (Array<octave_idx_type>&,\n                         octave_idx_type, sortmode) const\n{\n  err_wrong_type_arg (\"octave_base_value::sort ()\", type_name ());\n}\n\nsortmode\noctave_base_value::issorted (sortmode) const\n{\n  err_wrong_type_arg (\"octave_base_value::issorted ()\", type_name ());\n}\n\nArray<octave_idx_type>\noctave_base_value::sort_rows_idx (sortmode) const\n{\n  err_wrong_type_arg (\"octave_base_value::sort_rows_idx ()\", type_name ());\n}\n\nsortmode\noctave_base_value::is_sorted_rows (sortmode) const\n{\n  err_wrong_type_arg (\"octave_base_value::is_sorted_rows ()\", type_name ());\n}\n\nconst char *\noctave_base_value::get_umap_name (unary_mapper_t umap)\n{\n  static const char *names[num_unary_mappers] =\n  {\n    \"abs\",\n    \"acos\",\n    \"acosh\",\n    \"angle\",\n    \"arg\",\n    \"asin\",\n    \"asinh\",\n    \"atan\",\n    \"atanh\",\n    \"cbrt\",\n    \"ceil\",\n    \"conj\",\n    \"cos\",\n    \"cosh\",\n    \"erf\",\n    \"erfinv\",\n    \"erfcinv\",\n    \"erfc\",\n    \"erfcx\",\n    \"erfi\",\n    \"dawson\",\n    \"exp\",\n    \"expm1\",\n    \"isfinite\",\n    \"fix\",\n    \"floor\",\n    \"gamma\",\n    \"imag\",\n    \"isinf\",\n    \"isna\",\n    \"isnan\",\n    \"lgamma\",\n    \"log\",\n    \"log2\",\n    \"log10\",\n    \"log1p\",\n    \"real\",\n    \"round\",\n    \"roundb\",\n    \"signum\",\n    \"sin\",\n    \"sinh\",\n    \"sqrt\",\n    \"tan\",\n    \"tanh\",\n    \"isalnum\",\n    \"isalpha\",\n    \"isascii\",\n    \"iscntrl\",\n    \"isdigit\",\n    \"isgraph\",\n    \"islower\",\n    \"isprint\",\n    \"ispunct\",\n    \"isspace\",\n    \"isupper\",\n    \"isxdigit\",\n    \"signbit\",\n    \"tolower\",\n    \"toupper\"\n  };\n\n  if (umap < 0 || umap >= num_unary_mappers)\n    return \"unknown\";\n  else\n    return names[umap];\n}\n\nvoid\noctave_base_value::warn_load (const char *type) const\n{\n  warning_with_id\n  (\"Octave:load-save-unavailable\",\n   \"%s: loading %s files not available in this version of Octave\",\n   s_t_name.c_str (), type);\n}\n\nvoid\noctave_base_value::warn_save (const char *type) const\n{\n  warning_with_id\n  (\"Octave:load-save-unavailable\",\n   \"%s: saving %s files not available in this version of Octave\",\n   s_t_name.c_str (), type);\n}\n\noctave_value\noctave_base_value::map (unary_mapper_t umap) const\n{\n  error (\"%s: not defined for %s\", get_umap_name (umap), type_name ().c_str ());\n}\n\nvoid\noctave_base_value::lock ()\n{\n  err_wrong_type_arg (\"octave_base_value::lock ()\", type_name ());\n}\n\nvoid\noctave_base_value::unlock ()\n{\n  err_wrong_type_arg (\"octave_base_value::unlock ()\", type_name ());\n}\n\noctave_value\noctave_base_value::dump () const\n{\n  std::map<std::string, octave_value> m\n  = {{ \"class\", this->class_name () },\n    { \"type\", this->type_name () },\n    { \"dims\", this->dims().as_array () }\n  };\n\n  return octave_value (m);\n}\n\nOCTAVE_NORETURN static\nvoid\nerr_indexed_assignment (const std::string& tn1, const std::string& tn2)\n{\n  error (\"assignment of '%s' to indexed '%s' not implemented\",\n         tn2.c_str (), tn1.c_str ());\n}\n\nOCTAVE_NORETURN static\nvoid\nerr_assign_conversion_failed (const std::string& tn1, const std::string& tn2)\n{\n  error (\"type conversion for assignment of '%s' to indexed '%s' failed\",\n         tn2.c_str (), tn1.c_str ());\n}\n\nOCTAVE_NORETURN static\nvoid\nerr_no_conversion (const std::string& on, const std::string& tn1,\n                   const std::string& tn2)\n{\n  error (\"operator %s: no conversion for assignment of '%s' to indexed '%s'\",\n         on.c_str (), tn2.c_str (), tn1.c_str ());\n}\n\noctave_value\noctave_base_value::numeric_assign (const std::string& type,\n                                   const std::list<octave_value_list>& idx,\n                                   const octave_value& rhs)\n{\n  octave_value retval;\n\n  if (idx.front ().empty ())\n    error (\"missing index in indexed assignment\");\n\n  int t_lhs = type_id ();\n  int t_rhs = rhs.type_id ();\n\n  octave::type_info& ti = octave::__get_type_info__ ();\n\n  octave::type_info::assign_op_fcn f\n    = ti.lookup_assign_op (octave_value::op_asn_eq, t_lhs, t_rhs);\n\n  bool done = false;\n\n  if (f)\n    {\n      f (*this, idx.front (), rhs.get_rep ());\n\n      done = true;\n    }\n\n  if (done)\n    {\n      m_count++;\n      retval = octave_value (this);\n    }\n  else\n    {\n      int t_result = ti.lookup_pref_assign_conv (t_lhs, t_rhs);\n\n      if (t_result >= 0)\n        {\n          octave_base_value::type_conv_fcn cf\n            = ti.lookup_widening_op (t_lhs, t_result);\n\n          if (! cf)\n            err_indexed_assignment (type_name (), rhs.type_name ());\n\n          octave_base_value *tmp = cf (*this);\n\n          if (! tmp)\n            err_assign_conversion_failed (type_name (), rhs.type_name ());\n\n          octave_value val (tmp);\n\n          retval = val.subsasgn (type, idx, rhs);\n\n          done = true;\n        }\n\n      if (! done)\n        {\n          octave_value tmp_rhs;\n\n          octave_base_value::type_conv_info cf_rhs\n            = rhs.numeric_conversion_function ();\n\n          octave_base_value::type_conv_info cf_this\n            = numeric_conversion_function ();\n\n          // Try biased (one-sided) conversions first.\n          if (cf_rhs.type_id () >= 0\n              && (ti.lookup_assign_op (octave_value::op_asn_eq,\n                                       t_lhs, cf_rhs.type_id ())\n                  || ti.lookup_pref_assign_conv (t_lhs,\n                                                 cf_rhs.type_id ()) >= 0))\n            cf_this = nullptr;\n          else if (cf_this.type_id () >= 0\n                   && (ti.lookup_assign_op (octave_value::op_asn_eq,\n                                            cf_this.type_id (), t_rhs)\n                       || ti.lookup_pref_assign_conv (cf_this.type_id (),\n                           t_rhs) >= 0))\n            cf_rhs = nullptr;\n\n          if (cf_rhs)\n            {\n              octave_base_value *tmp = cf_rhs (rhs.get_rep ());\n\n              if (! tmp)\n                err_assign_conversion_failed (type_name (), rhs.type_name ());\n\n              tmp_rhs = octave_value (tmp);\n            }\n          else\n            tmp_rhs = rhs;\n\n          m_count++;\n          octave_value tmp_lhs = octave_value (this);\n\n          if (cf_this)\n            {\n              octave_base_value *tmp = cf_this (*this);\n\n              if (! tmp)\n                err_assign_conversion_failed (type_name (), rhs.type_name ());\n\n              tmp_lhs = octave_value (tmp);\n            }\n\n          if (! cf_this && ! cf_rhs)\n            err_no_conversion (octave_value::assign_op_as_string\n                               (octave_value::op_asn_eq),\n                               type_name (), rhs.type_name ());\n\n          retval = tmp_lhs.subsasgn (type, idx, tmp_rhs);\n\n          done = true;\n        }\n    }\n\n  // The assignment may have converted to a type that is wider than necessary.\n\n  retval.maybe_mutate ();\n\n  return retval;\n}\n\n// Current indentation.\nint octave_base_value::s_curr_print_indent_level = 0;\n\n// TRUE means we are at the beginning of a line.\nbool octave_base_value::s_beginning_of_line = true;\n\n// Each print() function should call this before printing anything.\n//\n// This doesn't need to be fast, but isn't there a better way?\n\nvoid\noctave_base_value::indent (std::ostream& os) const\n{\n  panic_unless (s_curr_print_indent_level >= 0);\n\n  if (s_beginning_of_line)\n    {\n      // FIXME: do we need this?\n      // os << prefix;\n\n      for (int i = 0; i < s_curr_print_indent_level; i++)\n        os << ' ';\n\n      s_beginning_of_line = false;\n    }\n}\n\n// All print() functions should use this to print new lines.\n\nvoid\noctave_base_value::newline (std::ostream& os) const\n{\n  os << \"\\n\";\n\n  s_beginning_of_line = true;\n}\n\n// For resetting print state.\n\nvoid\noctave_base_value::reset () const\n{\n  s_beginning_of_line = true;\n  s_curr_print_indent_level = 0;\n}\n\noctave_value\noctave_base_value::fast_elem_extract (octave_idx_type) const\n{\n  return octave_value ();\n}\n\nbool\noctave_base_value::fast_elem_insert (octave_idx_type, const octave_value&)\n{\n  return false;\n}\n\nbool\noctave_base_value::fast_elem_insert_self (void *, builtin_type_t) const\n{\n  return false;\n}\n\nstatic octave_base_value *\noct_conv_matrix_conv (const octave_base_value&)\n{\n  return new octave_matrix ();\n}\n\nstatic octave_base_value *\noct_conv_complex_matrix_conv (const octave_base_value&)\n{\n  return new octave_complex_matrix ();\n}\n\nstatic octave_base_value *\noct_conv_string_conv (const octave_base_value&)\n{\n  return new octave_char_matrix_str ();\n}\n\nstatic octave_base_value *\noct_conv_cell_conv (const octave_base_value&)\n{\n  return new octave_cell ();\n}\n\nstatic inline octave_value_list\nsanitize (const octave_value_list& ovl)\n{\n  octave_value_list retval = ovl;\n\n  for (octave_idx_type i = 0; i < ovl.length (); i++)\n    {\n      if (retval(i).is_magic_colon ())\n        retval(i) = \":\";\n    }\n\n  return retval;\n}\n\noctave_value\nmake_idx_args (const std::string& type,\n               const std::list<octave_value_list>& idx,\n               const std::string& who)\n{\n  std::size_t len = type.length ();\n\n  if (len != idx.size ())\n    error (\"invalid index for %s\", who.c_str ());\n\n  Cell type_field (1, len);\n  Cell subs_field (1, len);\n\n  auto p = idx.begin ();\n\n  for (std::size_t i = 0; i < len; i++)\n    {\n      char t = type[i];\n\n      switch (t)\n        {\n        case '(':\n          type_field(i) = \"()\";\n          subs_field(i) = Cell (sanitize (*p++));\n          break;\n\n        case '{':\n          type_field(i) = \"{}\";\n          subs_field(i) = Cell (sanitize (*p++));\n          break;\n\n        case '.':\n          {\n            type_field(i) = \".\";\n\n            octave_value_list vlist = *p++;\n\n            if (vlist.length () != 1)\n              error (\"only single argument permitted for '.' index\");\n\n            octave_value val = vlist(0);\n\n            if (! val.is_string ())\n              error (\"string argument required for '.' index\");\n\n            subs_field(i) = val;\n          }\n          break;\n\n        default:\n          error (\"unexpected: index not '(', '{', or '.' in make_idx_args - please report this bug\");\n          break;\n        }\n    }\n\n  octave_map m;\n\n  m.assign (\"type\", type_field);\n  m.assign (\"subs\", subs_field);\n\n  return m;\n}\n\nbool\ncalled_from_builtin ()\n{\n  octave::tree_evaluator& tw = octave::__get_evaluator__ ();\n\n  octave_function *fcn = tw.caller_function ();\n\n  // FIXME: we probably need a better check here, or some other\n  // mechanism to avoid overloaded functions when builtin is used.\n  // For example, what if someone overloads the builtin function?\n  // Also, are there other places where using builtin is not properly\n  // avoiding dispatch?\n\n  return (fcn && fcn->name () == \"builtin\");\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\ninstall_base_type_conversions (octave::type_info& ti)\n{\n  INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_scalar, octave_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_matrix, octave_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_complex,\n                         octave_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_complex_matrix,\n                         octave_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_range, octave_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_char_matrix_str,\n                         octave_char_matrix_str);\n  INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_cell, octave_cell);\n\n  INSTALL_WIDENOP_TI (ti, octave_base_value, octave_matrix, matrix_conv);\n  INSTALL_WIDENOP_TI (ti, octave_base_value, octave_complex_matrix,\n                      complex_matrix_conv);\n  INSTALL_WIDENOP_TI (ti, octave_base_value, octave_char_matrix_str, string_conv);\n  INSTALL_WIDENOP_TI (ti, octave_base_value, octave_cell, cell_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-base.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_base_h)\n#define octave_ov_base_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <list>\n#include <memory>\n#include <string>\n\n#include \"Range.h\"\n#include \"data-conv.h\"\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"auto-shlib.h\"\n#include \"oct-hdf5-types.h\"\n#include \"oct-stream.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass stack_frame;\nclass type_info;\n\n// FIXME: This is not ideal, but it avoids including\n// interpreter-private.h here and bringing in a lot of unnecessary\n// symbols that require even more header files.  Since the typeinfo\n// object is required to load a user-defined octave_value object,\n// maybe this function should be declared in a public header file?\n\nextern OCTINTERP_API type_info& __get_type_info__ ();\n\n// For now just preserve the old interface and don't mark it as deprecated.\n// This function is currently an internal, private function.  Additional\n// changes may be made before version 8 is finally released.\ninline type_info& __get_type_info__ (const std::string&) { return __get_type_info__ (); }\n\nOCTAVE_END_NAMESPACE(octave)\n\nclass Cell;\nclass float_display_format;\nclass mxArray;\nclass octave_map;\nclass octave_scalar_map;\nclass octave_value;\nclass octave_value_list;\nclass octave_classdef;\nclass octave_function;\nclass octave_user_function;\nclass octave_user_script;\nclass octave_user_code;\nclass octave_fcn_handle;\nclass octave_value_list;\n\nenum builtin_type_t\n{\n  btyp_double,\n  btyp_float,\n  btyp_complex,\n  btyp_float_complex,\n  btyp_int8,\n  btyp_int16,\n  btyp_int32,\n  btyp_int64,\n  btyp_uint8,\n  btyp_uint16,\n  btyp_uint32,\n  btyp_uint64,\n  btyp_bool,\n  btyp_char,\n  btyp_struct,\n  btyp_cell,\n  btyp_func_handle,\n  btyp_unknown,\n  btyp_num_types = btyp_unknown\n};\n\nextern OCTINTERP_API std::string btyp_class_name [];\n\ninline bool btyp_isnumeric (builtin_type_t btyp)\n{ return btyp <= btyp_uint64; }\n\ninline bool btyp_isinteger (builtin_type_t btyp)\n{ return btyp >= btyp_int8 && btyp <= btyp_uint64; }\n\ninline bool btyp_isfloat (builtin_type_t btyp)\n{ return btyp <= btyp_float_complex; }\n\ninline bool btyp_isarray (builtin_type_t btyp)\n{ return btyp <= btyp_char; }\n\n//! Determine the resulting type for a possible mixed-type operation.\n//!\n//! Rules for the resulting type:\n//!   - bool -> double\n//!   - single + double -> single\n//!   - real + complex -> complex\n//!   - integer + real -> integer\n//!   - uint + uint -> uint (the bigger one)\n//!   - sint + sint -> sint (the bigger one)\n//!\n//! @return The resulting type or \"unknown type\", if the resulting type cannot\n//!         be determined.\n\nextern OCTINTERP_API\nbuiltin_type_t btyp_mixed_numeric (builtin_type_t x, builtin_type_t y);\n\ntemplate <typename T>\nstruct class_to_btyp\n{\n  static const builtin_type_t btyp = btyp_unknown;\n};\n\ntemplate <builtin_type_t BTYP>\nstruct btyp_to_class\n{\n  typedef void type;\n};\n\n#define DEF_BTYP_TRAITS(BTYP, CLASS)            \\\n  template <>                                   \\\n  struct class_to_btyp<CLASS>                   \\\n  {                                             \\\n    static const builtin_type_t btyp = BTYP;    \\\n  };                                            \\\n                                                \\\n  template <>                                   \\\n  struct btyp_to_class<BTYP>                    \\\n  {                                             \\\n    typedef CLASS type;                         \\\n  }\n\nDEF_BTYP_TRAITS (btyp_double, double);\nDEF_BTYP_TRAITS (btyp_float, float);\nDEF_BTYP_TRAITS (btyp_complex, Complex);\nDEF_BTYP_TRAITS (btyp_float_complex, FloatComplex);\nDEF_BTYP_TRAITS (btyp_int8, octave_int8);\nDEF_BTYP_TRAITS (btyp_int16, octave_int16);\nDEF_BTYP_TRAITS (btyp_int32, octave_int32);\nDEF_BTYP_TRAITS (btyp_int64, octave_int64);\nDEF_BTYP_TRAITS (btyp_uint8, octave_uint8);\nDEF_BTYP_TRAITS (btyp_uint16, octave_uint16);\nDEF_BTYP_TRAITS (btyp_uint32, octave_uint32);\nDEF_BTYP_TRAITS (btyp_uint64, octave_uint64);\nDEF_BTYP_TRAITS (btyp_bool, bool);\nDEF_BTYP_TRAITS (btyp_char, char);\n\n\n// T_ID is the type id of struct objects, set by register_type().\n// T_NAME is the type name of struct objects.\n\n#define OCTAVE_EMPTY_CPP_ARG /* empty */\n\n#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA                          \\\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (OCTAVE_EMPTY_CPP_ARG,        \\\n                                         OCTAVE_EMPTY_CPP_ARG)\n\n#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API(API)                 \\\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (OCTAVE_EMPTY_CPP_ARG, API)\n\n#define DECLARE_OV_BASE_TYPEID_FUNCTIONS_AND_DATA                     \\\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (virtual, OCTAVE_EMPTY_CPP_ARG)\n\n#define DECLARE_OV_BASE_TYPEID_FUNCTIONS_AND_DATA_API(API)            \\\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (virtual, API)\n\n#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2(VIRTUAL, API)           \\\n  public:                                                             \\\n    VIRTUAL int type_id () const { return s_t_id; }                   \\\n    VIRTUAL std::string type_name () const { return s_t_name; }       \\\n    VIRTUAL std::string class_name () const { return s_c_name; }      \\\n    static int static_type_id () { return s_t_id; }                   \\\n    static std::string static_type_name () { return s_t_name; }       \\\n    static std::string static_class_name () { return s_c_name; }      \\\n    API static void register_type ();                                 \\\n    API static void register_type (octave::type_info&);               \\\n                                                                      \\\n  private:                                                            \\\n    static API int s_t_id;                                            \\\n    static API const std::string s_t_name;                            \\\n    static API const std::string s_c_name;\n\n#define DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS(cls, type)         \\\n  DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS_API (cls, type,          \\\n                                                  OCTAVE_EMPTY_CPP_ARG)\n\n#define DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS_API(cls, type, API) \\\n  template <> API void cls<type>::register_type ();                   \\\n  template <> API void cls<type>::register_type (octave::type_info&); \\\n  template <> API int cls<type>::s_t_id;                              \\\n  template <> API const std::string cls<type>::s_t_name;              \\\n  template <> API const std::string cls<type>::s_c_name;\n\n// FIXME: The 'new' operator below creates an 8-byte memory leak for every\n// registered data type (of which there are 58 built-in to Octave, plus any\n// user-defined data types).  The problem is user-defined types creating\n// a crash on exit (see bug #53156).  See also the FIXME note in function\n// register_type() in ov-typeinfo.cc.\n\n#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA_INTERNAL(tspec, t, n, c)  \\\n  tspec int t::s_t_id (-1);                                           \\\n  tspec const std::string t::s_t_name (n);                            \\\n  tspec const std::string t::s_c_name (c);                            \\\n  tspec void t::register_type ()                                      \\\n  {                                                                   \\\n    octave::type_info& type_info = octave::__get_type_info__ ();      \\\n                                                                      \\\n    register_type (type_info);                                        \\\n  }                                                                   \\\n  tspec void t::register_type (octave::type_info& ti)                 \\\n  {                                                                   \\\n    octave_value v = (new t ());                                      \\\n    s_t_id = ti.register_type (t::s_t_name, t::s_c_name, v);          \\\n  }\n\n#define DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)         \\\n  DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA_INTERNAL (template <>, t, n, c)\n\n#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)                  \\\n  DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA_INTERNAL ( , t, n, c)\n\n// A base value type, so that derived types only have to redefine what\n// they need (if they are derived from octave_base_value instead of\n// octave_value).\n\nclass OCTINTERP_API octave_base_value\n{\npublic:\n\n  typedef octave_base_value *(*type_conv_fcn) (const octave_base_value&);\n\n  // type conversion, including result type information\n  class type_conv_info\n  {\n  public:\n    type_conv_info (type_conv_fcn f = nullptr, int t = -1)\n      : m_fcn (f), m_type_id (t) { }\n\n    operator type_conv_fcn () const { return m_fcn; }\n\n    octave_base_value * operator () (const octave_base_value& v) const\n    { return (*m_fcn) (v); }\n\n    int type_id () const { return m_type_id; }\n\n  private:\n    type_conv_fcn m_fcn;\n    int m_type_id;\n  };\n\n  friend class octave_value;\n\n  OCTINTERP_API octave_base_value ();\n\n  octave_base_value (const octave_base_value&) : octave_base_value () { }\n\n  virtual ~octave_base_value () = default;\n\n  // Unconditional clone.  Always clones.\n  virtual octave_base_value *\n  clone () const { return new octave_base_value (*this); }\n\n  // Empty clone.\n  virtual OCTINTERP_API octave_base_value *\n  empty_clone () const;\n\n  // Unique clone.  Usually clones, but may be overridden to fake the\n  // cloning when sharing copies is to be controlled from within an\n  // instance (see octave_class).\n  virtual octave_base_value *\n  unique_clone () { return clone (); }\n\n  virtual void break_closure_cycles (const std::shared_ptr<octave::stack_frame>&) { }\n\n  virtual type_conv_info\n  numeric_conversion_function () const\n  { return type_conv_info (); }\n\n  virtual type_conv_info\n  numeric_demotion_function () const\n  { return type_conv_info (); }\n\n  virtual OCTINTERP_API octave_value squeeze () const;\n\n  virtual OCTINTERP_API octave_value full_value () const;\n\n  // Will return a copy of it-self when the representation\n  // allready is a scalar (.i.e., double).  The const variant\n  // as_double () would allocate a new octave value.\n  virtual OCTINTERP_API octave_value as_double_or_copy ();\n\n  virtual OCTINTERP_API octave_value as_double () const;\n  virtual OCTINTERP_API octave_value as_single () const;\n\n  virtual OCTINTERP_API octave_value as_int8 () const;\n  virtual OCTINTERP_API octave_value as_int16 () const;\n  virtual OCTINTERP_API octave_value as_int32 () const;\n  virtual OCTINTERP_API octave_value as_int64 () const;\n\n  virtual OCTINTERP_API octave_value as_uint8 () const;\n  virtual OCTINTERP_API octave_value as_uint16 () const;\n  virtual OCTINTERP_API octave_value as_uint32 () const;\n  virtual OCTINTERP_API octave_value as_uint64 () const;\n\n  virtual octave_base_value * try_narrowing_conversion ()\n  { return nullptr; }\n\n  virtual void maybe_economize () { }\n\n  virtual OCTINTERP_API Matrix size ();\n\n  virtual OCTINTERP_API octave_idx_type xnumel (const octave_value_list&);\n\n  // FIXME: Do we really need all three of these versions of subsref?\n\n  virtual OCTINTERP_API octave_value\n  subsref (const std::string& type,\n           const std::list<octave_value_list>& idx);\n\n  virtual OCTINTERP_API octave_value_list\n  subsref (const std::string& type,\n           const std::list<octave_value_list>& idx,\n           int nargout);\n\n  virtual OCTINTERP_API octave_value\n  subsref (const std::string& type,\n           const std::list<octave_value_list>& idx,\n           bool auto_add);\n\n  virtual OCTINTERP_API octave_value_list\n  simple_subsref (char type, octave_value_list& idx, int nargout);\n\n  virtual OCTINTERP_API octave_value\n  do_index_op (const octave_value_list& idx, bool resize_ok = false);\n\n  virtual void assign (const std::string&, const octave_value&) { }\n\n  virtual OCTINTERP_API octave_value\n  subsasgn (const std::string& type,\n            const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  virtual OCTINTERP_API octave_value\n  simple_subsasgn (char type, octave_value_list& idx,\n                   const octave_value& rhs);\n\n  virtual OCTINTERP_API octave_value\n  undef_subsasgn (const std::string& type,\n                  const std::list<octave_value_list>& idx,\n                  const octave_value& rhs);\n\n  virtual OCTINTERP_API octave::idx_vector\n  index_vector (bool require_integers = false) const;\n\n  virtual dim_vector dims () const { return dim_vector (); }\n\n  octave_idx_type rows () const\n  {\n    const dim_vector dv = dims ();\n\n    return dv(0);\n  }\n\n  octave_idx_type columns () const\n  {\n    const dim_vector dv = dims ();\n\n    return dv(1);\n  }\n\n  virtual int ndims () const\n  { return dims ().ndims (); }\n\n  virtual octave_idx_type numel () const { return dims ().numel (); }\n\n  virtual std::size_t byte_size () const { return 0; }\n\n  virtual OCTINTERP_API octave_idx_type nnz () const;\n\n  virtual OCTINTERP_API octave_idx_type nzmax () const;\n\n  virtual OCTINTERP_API octave_idx_type nfields () const;\n\n  virtual OCTINTERP_API octave_value reshape (const dim_vector&) const;\n\n  virtual OCTINTERP_API octave_value\n  permute (const Array<int>& vec, bool = false) const;\n\n  virtual OCTINTERP_API octave_value\n  resize (const dim_vector&, bool fill = false) const;\n\n  virtual OCTINTERP_API MatrixType matrix_type () const;\n\n  virtual OCTINTERP_API MatrixType matrix_type (const MatrixType& typ) const;\n\n  virtual bool is_defined () const { return false; }\n\n  virtual bool is_storable () const { return true; }\n\n  virtual bool is_legacy_object () const { return false; }\n\n  bool isempty () const { return (dims ().any_zero ()); }\n\n  bool is_zero_by_zero () const { return dims().zero_by_zero (); }\n\n  virtual bool iscell () const { return false; }\n\n  virtual bool iscellstr () const { return false; }\n\n  virtual bool is_real_scalar () const { return false; }\n\n  virtual bool is_real_matrix () const { return false; }\n\n  virtual bool is_complex_scalar () const { return false; }\n\n  virtual bool is_complex_matrix () const { return false; }\n\n  virtual bool is_bool_scalar () const { return false; }\n\n  virtual bool is_bool_matrix () const { return false; }\n\n  virtual bool is_char_matrix () const { return false; }\n\n  virtual bool is_diag_matrix () const { return false; }\n\n  virtual bool is_perm_matrix () const { return false; }\n\n  virtual bool is_string () const { return false; }\n\n  virtual bool is_sq_string () const { return false; }\n\n  virtual bool is_range () const { return false; }\n\n  virtual bool isstruct () const { return false; }\n\n  virtual bool isobject () const { return false; }\n\n  virtual bool is_classdef_meta () const { return false; }\n\n  virtual bool is_classdef_superclass_ref () const { return false; }\n\n  virtual bool is_classdef_object () const { return false; }\n\n  virtual bool is_package () const { return false; }\n\n  virtual bool isjava () const { return false; }\n\n  virtual bool is_cs_list () const { return false; }\n\n  virtual bool is_magic_colon () const { return false; }\n\n  virtual bool is_all_va_args () const { return false; }\n\n  virtual OCTINTERP_API octave_value all (int = 0) const;\n\n  virtual OCTINTERP_API octave_value any (int = 0) const;\n\n  virtual builtin_type_t builtin_type () const { return btyp_unknown; }\n\n  virtual bool is_double_type () const { return false; }\n\n  virtual bool is_single_type () const { return false; }\n\n  virtual bool isfloat () const { return false; }\n\n  virtual bool is_int8_type () const { return false; }\n\n  virtual bool is_int16_type () const { return false; }\n\n  virtual bool is_int32_type () const { return false; }\n\n  virtual bool is_int64_type () const { return false; }\n\n  virtual bool is_uint8_type () const { return false; }\n\n  virtual bool is_uint16_type () const { return false; }\n\n  virtual bool is_uint32_type () const { return false; }\n\n  virtual bool is_uint64_type () const { return false; }\n\n  virtual bool islogical () const { return false; }\n\n  virtual bool isinteger () const { return false; }\n\n  virtual bool isreal () const { return false; }\n\n  virtual bool iscomplex () const { return false; }\n\n  // Would be nice to get rid of the next four functions:\n\n  virtual bool is_scalar_type () const { return false; }\n\n  virtual bool is_matrix_type () const { return false; }\n\n  virtual bool is_full_num_matrix () const { return false; }\n\n  virtual bool isnumeric () const { return false; }\n\n  virtual bool issparse () const { return false; }\n\n  virtual bool is_true () const { return false; }\n\n  virtual bool is_magic_int () const { return false; }\n\n  virtual bool isnull () const { return false; }\n\n  virtual bool is_constant () const { return false; }\n\n  virtual bool is_function_handle () const { return false; }\n\n  virtual bool is_anonymous_function () const { return false; }\n\n  virtual bool is_inline_function () const { return false; }\n\n  virtual bool is_function () const { return false; }\n\n  virtual bool is_user_script () const { return false; }\n\n  virtual bool is_user_function () const { return false; }\n\n  virtual bool is_user_code () const { return false; }\n\n  virtual bool is_builtin_function () const { return false; }\n\n  virtual bool is_dld_function () const { return false; }\n\n  virtual bool is_mex_function () const { return false; }\n\n  virtual bool is_function_cache () const { return false; }\n\n  // Checks if the ov could be a function.  If it is undefined,\n  // the name associated with the ov could be a function to call.\n  virtual bool is_maybe_function () const\n  { return !is_defined () || is_function (); }\n\n  virtual bool has_function_cache () const { return false; }\n\n  virtual octave_function * get_cached_fcn (const octave_value_list&) { return nullptr; }\n\n  virtual octave_function * get_cached_fcn (void *, void *) { return nullptr; }\n\n  virtual void erase_subfunctions () { }\n\n  virtual OCTINTERP_API short int\n  short_value (bool = false, bool = false) const;\n\n  virtual OCTINTERP_API unsigned short int\n  ushort_value (bool = false, bool = false) const;\n\n  virtual OCTINTERP_API int\n  int_value (bool = false, bool = false) const;\n\n  virtual OCTINTERP_API unsigned int\n  uint_value (bool = false, bool = false) const;\n\n  virtual OCTINTERP_API int nint_value (bool = false) const;\n\n  virtual OCTINTERP_API long int\n  long_value (bool = false, bool = false) const;\n\n  virtual OCTINTERP_API unsigned long int\n  ulong_value (bool = false, bool = false) const;\n\n  virtual OCTINTERP_API int64_t int64_value (bool = false, bool = false) const;\n\n  virtual OCTINTERP_API uint64_t uint64_value (bool = false, bool = false) const;\n\n  virtual OCTINTERP_API double double_value (bool = false) const;\n\n  virtual OCTINTERP_API float float_value (bool = false) const;\n\n  virtual double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  virtual float float_scalar_value (bool frc_str_conv = false) const\n  { return float_value (frc_str_conv); }\n\n  virtual OCTINTERP_API Cell cell_value () const;\n\n  virtual OCTINTERP_API Matrix matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API FloatMatrix float_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API NDArray array_value (bool = false) const;\n\n  virtual OCTINTERP_API FloatNDArray float_array_value (bool = false) const;\n\n  virtual OCTINTERP_API Complex complex_value (bool = false) const;\n\n  virtual OCTINTERP_API FloatComplex float_complex_value (bool = false) const;\n\n  virtual OCTINTERP_API ComplexMatrix complex_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API FloatComplexMatrix float_complex_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API ComplexNDArray complex_array_value (bool = false) const;\n\n  virtual OCTINTERP_API FloatComplexNDArray float_complex_array_value (bool = false) const;\n\n  virtual OCTINTERP_API bool bool_value (bool = false) const;\n\n  virtual OCTINTERP_API boolMatrix bool_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API boolNDArray bool_array_value (bool = false) const;\n\n  virtual OCTINTERP_API charMatrix char_matrix_value (bool force = false) const;\n\n  virtual OCTINTERP_API charNDArray char_array_value (bool = false) const;\n\n  virtual OCTINTERP_API SparseMatrix sparse_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API SparseBoolMatrix sparse_bool_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API DiagMatrix diag_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API FloatDiagMatrix float_diag_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API FloatComplexDiagMatrix\n  float_complex_diag_matrix_value (bool = false) const;\n\n  virtual OCTINTERP_API PermMatrix perm_matrix_value () const;\n\n  virtual OCTINTERP_API octave_int8 int8_scalar_value () const;\n\n  virtual OCTINTERP_API octave_int16 int16_scalar_value () const;\n\n  virtual OCTINTERP_API octave_int32 int32_scalar_value () const;\n\n  virtual OCTINTERP_API octave_int64 int64_scalar_value () const;\n\n  virtual OCTINTERP_API octave_uint8 uint8_scalar_value () const;\n\n  virtual OCTINTERP_API octave_uint16 uint16_scalar_value () const;\n\n  virtual OCTINTERP_API octave_uint32 uint32_scalar_value () const;\n\n  virtual OCTINTERP_API octave_uint64 uint64_scalar_value () const;\n\n  virtual OCTINTERP_API int8NDArray int8_array_value () const;\n\n  virtual OCTINTERP_API int16NDArray int16_array_value () const;\n\n  virtual OCTINTERP_API int32NDArray int32_array_value () const;\n\n  virtual OCTINTERP_API int64NDArray int64_array_value () const;\n\n  virtual OCTINTERP_API uint8NDArray uint8_array_value () const;\n\n  virtual OCTINTERP_API uint16NDArray uint16_array_value () const;\n\n  virtual OCTINTERP_API uint32NDArray uint32_array_value () const;\n\n  virtual OCTINTERP_API uint64NDArray uint64_array_value () const;\n\n  virtual OCTINTERP_API string_vector string_vector_value (bool pad = false) const;\n\n  virtual OCTINTERP_API std::string string_value (bool force = false) const;\n\n  virtual OCTINTERP_API Array<std::string> cellstr_value () const;\n\n  virtual OCTINTERP_API octave::range<double> range_value () const;\n\n  // For now, enable only range<double>.\n\n  virtual OCTINTERP_API octave_map map_value () const;\n\n  virtual OCTINTERP_API octave_scalar_map scalar_map_value () const;\n\n  virtual OCTINTERP_API string_vector map_keys () const;\n\n  virtual OCTINTERP_API bool isfield (const std::string&) const;\n\n  virtual OCTINTERP_API std::size_t nparents () const;\n\n  virtual OCTINTERP_API std::list<std::string> parent_class_name_list () const;\n\n  virtual OCTINTERP_API string_vector parent_class_names () const;\n\n  virtual octave_base_value * find_parent_class (const std::string&)\n  { return nullptr; }\n\n  virtual octave_base_value * unique_parent_class (const std::string&)\n  { return nullptr; }\n\n  virtual bool is_instance_of (const std::string&) const\n  { return false; }\n\n  virtual OCTINTERP_API octave_classdef * classdef_object_value (bool silent = false);\n\n  virtual OCTINTERP_API octave_function * function_value (bool silent = false);\n\n  virtual OCTINTERP_API octave_user_function * user_function_value (bool silent = false);\n\n  virtual OCTINTERP_API octave_user_script * user_script_value (bool silent = false);\n\n  virtual OCTINTERP_API octave_user_code * user_code_value (bool silent = false);\n\n  virtual OCTINTERP_API octave_fcn_handle * fcn_handle_value (bool silent = false);\n\n  virtual OCTINTERP_API octave_value_list list_value () const;\n\n  virtual OCTINTERP_API octave_value\n  convert_to_str (bool pad = false, bool force = false, char type = '\\'') const;\n  virtual OCTINTERP_API octave_value\n  convert_to_str_internal (bool pad, bool force, char type) const;\n\n  virtual OCTINTERP_API void convert_to_row_or_column_vector ();\n\n  // The following extractor functions don't perform any implicit type\n  // conversions.\n\n  virtual OCTINTERP_API std::string xstring_value () const;\n\n  virtual bool print_as_scalar () const { return false; }\n\n  virtual OCTINTERP_API void\n  print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  virtual OCTINTERP_API void\n  print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  virtual OCTINTERP_API bool\n  print_name_tag (std::ostream& os, const std::string& name) const;\n\n  virtual OCTINTERP_API void\n  print_with_name (std::ostream& output_buf, const std::string& name,\n                   bool print_padding = true);\n\n  virtual void short_disp (std::ostream& os) const\n  {\n    dim_vector dv = dims ();\n    os << \"[\" << dv.str () << \" \" << class_name () << \"]\";\n  }\n\n  virtual OCTINTERP_API float_display_format get_edit_display_format () const;\n\n  virtual std::string edit_display (const float_display_format&,\n                                    octave_idx_type, octave_idx_type) const\n  { return \"#VAL\"; }\n\n  virtual OCTINTERP_API void\n  print_info (std::ostream& os, const std::string& prefix) const;\n\n  virtual OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  virtual OCTINTERP_API bool load_ascii (std::istream& is);\n\n  virtual OCTINTERP_API bool save_binary (std::ostream& os, bool save_as_floats);\n\n  virtual OCTINTERP_API bool\n  load_binary (std::istream& is, bool swap, octave::mach_info::float_format fmt);\n\n  virtual OCTINTERP_API bool\n  save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  virtual OCTINTERP_API bool\n  load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  virtual OCTINTERP_API int\n  write (octave::stream& os, int block_size,\n         oct_data_conv::data_type output_type, int skip,\n         octave::mach_info::float_format flt_fmt) const;\n\n  virtual const void * mex_get_data () const { return nullptr; }\n\n  virtual const octave_idx_type * mex_get_ir () const { return nullptr; }\n\n  virtual const octave_idx_type * mex_get_jc () const { return nullptr; }\n\n  virtual OCTINTERP_API mxArray * as_mxArray (bool interleaved) const;\n\n  virtual OCTINTERP_API octave_value diag (octave_idx_type k = 0) const;\n\n  virtual OCTINTERP_API octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  virtual OCTINTERP_API octave_value\n  sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;\n\n  virtual OCTINTERP_API octave_value\n  sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n        sortmode mode = ASCENDING) const;\n\n  virtual OCTINTERP_API sortmode issorted (sortmode mode = UNSORTED) const;\n\n  virtual OCTINTERP_API Array<octave_idx_type>\n  sort_rows_idx (sortmode mode = ASCENDING) const;\n\n  virtual OCTINTERP_API sortmode is_sorted_rows (sortmode mode = UNSORTED) const;\n\n  virtual OCTINTERP_API void lock ();\n\n  virtual OCTINTERP_API void unlock ();\n\n  virtual bool islocked () const { return false; }\n\n  virtual void call_object_destructor () { }\n\n  virtual void maybe_call_dtor () { }\n\n  virtual OCTINTERP_API octave_value dump () const;\n\n  virtual OCTINTERP_API octave_value storable_value ();\n\n  virtual OCTINTERP_API octave_base_value * make_storable_value ();\n\n  // Standard mappers.  Register new ones here.\n  enum unary_mapper_t\n  {\n    umap_abs,\n    umap_acos,\n    umap_acosh,\n    umap_angle,\n    umap_arg,\n    umap_asin,\n    umap_asinh,\n    umap_atan,\n    umap_atanh,\n    umap_cbrt,\n    umap_ceil,\n    umap_conj,\n    umap_cos,\n    umap_cosh,\n    umap_erf,\n    umap_erfinv,\n    umap_erfcinv,\n    umap_erfc,\n    umap_erfcx,\n    umap_erfi,\n    umap_dawson,\n    umap_exp,\n    umap_expm1,\n    umap_isfinite,\n    umap_fix,\n    umap_floor,\n    umap_gamma,\n    umap_imag,\n    umap_isinf,\n    umap_isna,\n    umap_isnan,\n    umap_lgamma,\n    umap_log,\n    umap_log2,\n    umap_log10,\n    umap_log1p,\n    umap_real,\n    umap_round,\n    umap_roundb,\n    umap_signum,\n    umap_sin,\n    umap_sinh,\n    umap_sqrt,\n    umap_tan,\n    umap_tanh,\n    umap_xisalnum,\n    umap_xisalpha,\n    umap_xisascii,\n    umap_xiscntrl,\n    umap_xisdigit,\n    umap_xisgraph,\n    umap_xislower,\n    umap_xisprint,\n    umap_xispunct,\n    umap_xisspace,\n    umap_xisupper,\n    umap_xisxdigit,\n    umap_xsignbit,\n    umap_xtolower,\n    umap_xtoupper,\n    umap_unknown,\n    num_unary_mappers = umap_unknown\n  };\n\n  virtual OCTINTERP_API octave_value map (unary_mapper_t) const;\n\n  // These are fast indexing & assignment shortcuts for extracting\n  // or inserting a single scalar from/to an array.\n\n  // Extract the n-th element, aka val(n).  Result is undefined if val is not\n  // an array type or n is out of range.  Never error.\n  virtual OCTINTERP_API octave_value\n  fast_elem_extract (octave_idx_type n) const;\n\n  // Assign the n-th element, aka val(n) = x.  Returns false if val is not an\n  // array type, x is not a matching scalar type, or n is out of range.\n  // Never error.\n  virtual OCTINTERP_API bool\n  fast_elem_insert (octave_idx_type n, const octave_value& x);\n\n  // This is a helper for the above, to be overridden in scalar types.  The\n  // whole point is to handle the insertion efficiently with just *two* VM\n  // calls, which is basically the theoretical minimum.\n  virtual OCTINTERP_API bool\n  fast_elem_insert_self (void *where, builtin_type_t btyp) const;\n\nprotected:\n\n  // This should only be called for derived types.\n\n  OCTINTERP_API octave_value\n  numeric_assign (const std::string& type,\n                  const std::list<octave_value_list>& idx,\n                  const octave_value& rhs);\n\n  void reset_indent_level () const\n  { s_curr_print_indent_level = 0; }\n\n  void increment_indent_level () const\n  { s_curr_print_indent_level += 2; }\n\n  void decrement_indent_level () const\n  { s_curr_print_indent_level -= 2; }\n\n  int current_print_indent_level () const\n  { return s_curr_print_indent_level; }\n\n  OCTINTERP_API void indent (std::ostream& os) const;\n\n  OCTINTERP_API void newline (std::ostream& os) const;\n\n  OCTINTERP_API void reset () const;\n\n  // A reference count.\n  // NOTE: the declaration is octave_idx_type because with 64-bit indexing,\n  // it is well possible to have more than MAX_INT copies of a single value\n  // (think of an empty cell array with >2G elements).\n  octave::refcount<octave_idx_type> m_count;\n\n  OCTINTERP_API static const char * get_umap_name (unary_mapper_t);\n\n  OCTINTERP_API void warn_load (const char *type) const;\n  OCTINTERP_API void warn_save (const char *type) const;\n\nprivate:\n\n  //--------\n\n  static int s_curr_print_indent_level;\n  static bool s_beginning_of_line;\n\n  DECLARE_OV_BASE_TYPEID_FUNCTIONS_AND_DATA\n};\n\nclass OCTINTERP_TEMPLATE_API octave_base_dld_value : public octave_base_value\n{\npublic:\n\n  octave_base_dld_value () = default;\n\n  ~octave_base_dld_value ()\n  {\n    m_containing_dynamic_library.delete_later ();\n  }\n\n  octave_base_dld_value (const octave_base_dld_value&) = default;\n\nprivate:\n\n  octave::auto_shlib m_containing_dynamic_library;\n};\n\n// Utility function to convert C++ arguments used in subsref/subsasgn into an\n// octave_value_list object that can be used to call a function/method in the\n// interpreter.\nextern OCTINTERP_API octave_value\nmake_idx_args (const std::string& type,\n               const std::list<octave_value_list>& idx,\n               const std::string& who);\n\n// Tells whether some regular octave_value_base methods are being called from\n// within the \"builtin\" function.\nextern OCTINTERP_API bool called_from_builtin ();\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-bool-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n#include \"int8NDArray.h\"\n#include \"int16NDArray.h\"\n#include \"int32NDArray.h\"\n#include \"int64NDArray.h\"\n#include \"uint8NDArray.h\"\n#include \"uint16NDArray.h\"\n#include \"uint32NDArray.h\"\n#include \"uint64NDArray.h\"\n\n#include \"lo-ieee.h\"\n#include \"mx-base.h\"\n#include \"oct-locbuf.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"ops.h\"\n#include \"ov-bool.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"pr-output.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-utils.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_bool_matrix,\n                                     \"bool matrix\", \"logical\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_bool_matrix& v = dynamic_cast<const octave_bool_matrix&> (a);\n\n  return new octave_matrix (NDArray (v.bool_array_value ()));\n}\n\noctave_base_value::type_conv_info\noctave_bool_matrix::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n         octave_matrix::static_type_id ());\n}\n\noctave_base_value *\noctave_bool_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.ndims () == 2)\n    {\n      boolMatrix bm (m_matrix);\n\n      octave_idx_type nr = bm.rows ();\n      octave_idx_type nc = bm.cols ();\n\n      if (nr == 1 && nc == 1)\n        retval = new octave_bool (bm (0, 0));\n    }\n\n  return retval;\n}\n\ndouble\noctave_bool_matrix::double_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"bool matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"bool matrix\", \"real scalar\");\n\n  return m_matrix(0, 0);\n}\n\nfloat\noctave_bool_matrix::float_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"bool matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"bool matrix\", \"real scalar\");\n\n  return m_matrix(0, 0);\n}\n\nComplex\noctave_bool_matrix::complex_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"bool matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"bool matrix\", \"complex scalar\");\n\n  return Complex (m_matrix(0, 0), 0);\n}\n\nFloatComplex\noctave_bool_matrix::float_complex_value (bool) const\n{\n  float tmp = lo_ieee_float_nan_value ();\n\n  FloatComplex retval (tmp, tmp);\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"bool matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"bool matrix\", \"complex scalar\");\n\n  retval = m_matrix(0, 0);\n\n  return retval;\n}\n\noctave_value\noctave_bool_matrix::convert_to_str_internal (bool pad, bool force,\n    char type) const\n{\n  octave_value tmp = octave_value (array_value ());\n  return tmp.convert_to_str (pad, force, type);\n}\n\noctave_value\noctave_bool_matrix::as_double () const\n{\n  return NDArray (m_matrix);\n}\n\noctave_value\noctave_bool_matrix::as_single () const\n{\n  return FloatNDArray (m_matrix);\n}\n\noctave_value\noctave_bool_matrix::as_int8 () const\n{\n  return int8NDArray (m_matrix);\n}\n\noctave_value\noctave_bool_matrix::as_int16 () const\n{\n  return int16NDArray (m_matrix);\n}\n\noctave_value\noctave_bool_matrix::as_int32 () const\n{\n  return int32NDArray (m_matrix);\n}\n\noctave_value\noctave_bool_matrix::as_int64 () const\n{\n  return int64NDArray (m_matrix);\n}\n\noctave_value\noctave_bool_matrix::as_uint8 () const\n{\n  return uint8NDArray (m_matrix);\n}\n\noctave_value\noctave_bool_matrix::as_uint16 () const\n{\n  return uint16NDArray (m_matrix);\n}\n\noctave_value\noctave_bool_matrix::as_uint32 () const\n{\n  return uint32NDArray (m_matrix);\n}\n\noctave_value\noctave_bool_matrix::as_uint64 () const\n{\n  return uint64NDArray (m_matrix);\n}\n\nvoid\noctave_bool_matrix::print_raw (std::ostream& os,\n                               bool pr_as_read_syntax) const\n{\n  octave_print_internal (os, m_matrix, pr_as_read_syntax,\n                         current_print_indent_level ());\n}\n\nbool\noctave_bool_matrix::save_ascii (std::ostream& os)\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () > 2)\n    {\n      NDArray tmp = array_value ();\n      os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n      for (int i = 0; i < dv.ndims (); i++)\n        os << ' ' << dv(i);\n\n      os << \"\\n\" << tmp;\n    }\n  else\n    {\n      // Keep this case, rather than use generic code above for backward\n      // compatibility.  Makes load_ascii much more complex!!\n      os << \"# rows: \" << rows () << \"\\n\"\n         << \"# columns: \" << columns () << \"\\n\";\n\n      Matrix tmp = matrix_value ();\n\n      os << tmp;\n    }\n\n  return true;\n}\n\nbool\noctave_bool_matrix::load_ascii (std::istream& is)\n{\n  string_vector keywords (2);\n\n  keywords[0] = \"ndims\";\n  keywords[1] = \"rows\";\n\n  std::string kw;\n  octave_idx_type val = 0;\n\n  if (! extract_keyword (is, keywords, kw, val, true))\n    error (\"load: failed to extract number of rows and columns\");\n\n  if (kw == \"ndims\")\n    {\n      int mdims = static_cast<int> (val);\n\n      if (mdims < 0)\n        error (\"load: failed to extract number of dimensions\");\n\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        is >> dv(i);\n\n      if (! is)\n        error (\"load: failed to extract dimensions\");\n\n      boolNDArray btmp (dv);\n\n      if (btmp.isempty ())\n        m_matrix = btmp;\n      else\n        {\n          NDArray tmp(dv);\n          is >> tmp;\n\n          if (! is)\n            error (\"load: failed to load matrix constant\");\n\n          for (octave_idx_type i = 0; i < btmp.numel (); i++)\n            btmp.elem (i) = (tmp.elem (i) != 0.);\n\n          m_matrix = btmp;\n        }\n    }\n  else if (kw == \"rows\")\n    {\n      octave_idx_type nr = val;\n      octave_idx_type nc = 0;\n\n      if (nr < 0 || ! extract_keyword (is, \"columns\", nc) || nc < 0)\n        error (\"load: failed to extract number of rows and columns\");\n\n      if (nr > 0 && nc > 0)\n        {\n          Matrix tmp (nr, nc);\n          is >> tmp;\n          if (! is)\n            error (\"load: failed to load matrix constant\");\n\n          boolMatrix btmp (nr, nc);\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = 0; i < nr; i++)\n              btmp.elem (i, j) = (tmp.elem (i, j) != 0.);\n\n          m_matrix = btmp;\n        }\n      else if (nr == 0 || nc == 0)\n        m_matrix = boolMatrix (nr, nc);\n      else\n        error (\"unexpected dimensions in octave_bool_matrix::load_ascii - please report this bug\");\n    }\n  else\n    error (\"unexpected dimensions keyword (= '%s') octave_bool_matrix::load_ascii - please report this bug\", kw.c_str ());\n\n  return true;\n}\n\nbool\noctave_bool_matrix::save_binary (std::ostream& os, bool /* save_as_floats */)\n{\n\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Use negative value for ndims to differentiate with old format!!\n  int32_t tmp = - dv.ndims ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  for (int i = 0; i < dv.ndims (); i++)\n    {\n      tmp = dv(i);\n      os.write (reinterpret_cast<char *> (&tmp), 4);\n    }\n\n  const bool *mtmp = m_matrix.data ();\n  octave_idx_type nel = m_matrix.numel ();\n  os.write (reinterpret_cast<const char *> (mtmp), nel);\n\n  return true;\n}\n\nbool\noctave_bool_matrix::load_binary (std::istream& is, bool swap,\n                                 octave::mach_info::float_format /* fmt */)\n{\n  int32_t mdims;\n  if (! is.read (reinterpret_cast<char *> (&mdims), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&mdims);\n  if (mdims >= 0)\n    return false;\n\n  // mdims is negative for consistency with other matrices, where it is\n  // negative to allow the positive value to be used for rows/cols for\n  // backward compatibility\n  mdims = - mdims;\n  int32_t di;\n  dim_vector dv;\n  dv.resize (mdims);\n\n  for (int i = 0; i < mdims; i++)\n    {\n      if (! is.read (reinterpret_cast<char *> (&di), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&di);\n      dv(i) = di;\n    }\n\n  // Convert an array with a single dimension to be a row vector.\n  // Octave should never write files like this, other software\n  // might.\n\n  if (mdims == 1)\n    {\n      mdims = 2;\n      dv.resize (mdims);\n      dv(1) = dv(0);\n      dv(0) = 1;\n    }\n\n  octave_idx_type nel = dv.numel ();\n  OCTAVE_LOCAL_BUFFER (char, htmp, nel);\n  if (! is.read (htmp, nel))\n    return false;\n  boolNDArray m(dv);\n  bool *mtmp = m.rwdata ();\n  for (octave_idx_type i = 0; i < nel; i++)\n    mtmp[i] = (htmp[i] ? 1 : 0);\n  m_matrix = m;\n\n  return true;\n}\n\nbool\noctave_bool_matrix::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                               bool /* save_as_floats */)\n{\n  bool retval = true;\n\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  int rank = dv.ndims ();\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  for (int i = 0; i < rank; i++)\n    hdims[i] = dv(rank-i-1);\n\n  space_hid = H5Screate_simple (rank, hdims, nullptr);\n  if (space_hid < 0) return false;\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n\n  const bool *mtmp = m_matrix.data ();\n\n  retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT,\n                     reinterpret_cast<const char *> (mtmp)) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_bool_matrix::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    m_matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank < 1)\n    {\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_id, hdims, maxdims);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  if (rank == 1)\n    {\n      dv.resize (2);\n      dv(0) = 1;\n      dv(1) = hdims[0];\n    }\n  else\n    {\n      dv.resize (rank);\n      for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)\n        dv(j) = hdims[i];\n    }\n\n  octave_idx_type nel = dv.numel ();\n  OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);\n  if (H5Dread (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, htmp)\n      >= 0)\n    {\n      retval = true;\n\n      boolNDArray btmp (dv);\n      for (octave_idx_type i = 0; i < nel; i++)\n        btmp.elem (i) = htmp[i];\n\n      m_matrix = btmp;\n    }\n\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nmxArray *\noctave_bool_matrix::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxLOGICAL_CLASS, dims (), mxREAL);\n\n  mxLogical *pd = static_cast<mxLogical *> (retval->get_data ());\n\n  mwSize nel = numel ();\n\n  const bool *pdata = m_matrix.data ();\n\n  for (mwIndex i = 0; i < nel; i++)\n    pd[i] = pdata[i];\n\n  return retval;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (logical, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{TF} =} logical (@var{x})\nConvert the numeric object @var{x} to logical type.\n\nAny nonzero values will be converted to true (1) while zero values will be\nconverted to false (0).  The non-numeric value NaN cannot be converted and will\nproduce an error.\n\nCompatibility Note: Octave accepts complex values as input, whereas @sc{matlab}\nissues an error.\n@seealso{double, single, char}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value retval;\n\n  octave_value arg = args(0);\n\n  if (arg.islogical ())\n    retval = arg;\n  else if (arg.isnumeric ())\n    {\n      if (arg.issparse ())\n        retval = arg.sparse_bool_matrix_value ();\n      else if (arg.is_scalar_type ())\n        retval = arg.bool_value ();\n      else\n        retval = arg.bool_array_value ();\n    }\n  else if (arg.is_sq_string ())\n    retval = arg.bool_array_value ();\n  else\n    err_wrong_type_arg (\"logical\", arg);\n\n  return retval;\n}\n\n/*\n%!test\n%! m = eye (2) != 0;\n%! s = ! 0;\n%! c = {\"double\", \"single\", \"int8\", \"int16\", \"int32\", \"int64\", \"uint8\", \"uint16\", \"uint32\", \"uint64\", \"logical\"};\n%! for i = 1:numel (c)\n%!   assert (logical (eye (2, c{i})), m);\n%!   assert (logical (eye (1, c{i})), s);\n%! endfor\n\n%!test <*63515>\n%! s = 'str';\n%! assert (logical (s), [true, true, true]);\n%! s = ['abc'; ['de' \"\\0\"]];\n%! assert (logical (s), logical ([1 1 1; 1 1 0]));\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-bool-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_bool_mat_h)\n#define octave_ov_bool_mat_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-base-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n\n#include \"MatrixType.h\"\n\nclass octave_value_list;\n\n// Character matrix values.\n\nextern template class OCTINTERP_API octave_base_matrix<boolNDArray>;\n\nclass octave_bool_matrix : public octave_base_matrix<boolNDArray>\n{\npublic:\n\n  octave_bool_matrix ()\n    : octave_base_matrix<boolNDArray> () { }\n\n  octave_bool_matrix (const boolNDArray& bnda)\n    : octave_base_matrix<boolNDArray> (bnda) { }\n\n  octave_bool_matrix (const Array<bool>& bnda)\n    : octave_base_matrix<boolNDArray> (bnda) { }\n\n  octave_bool_matrix (const boolMatrix& bm)\n    : octave_base_matrix<boolNDArray> (bm) { }\n\n  octave_bool_matrix (const boolMatrix& bm, const MatrixType& t)\n    : octave_base_matrix<boolNDArray> (bm, t) { }\n\n  octave_bool_matrix (const boolNDArray& bm, const octave::idx_vector& cache)\n    : octave_base_matrix<boolNDArray> (bm)\n  {\n    set_idx_cache (cache);\n  }\n\n  octave_bool_matrix (const octave_bool_matrix& bm)\n    : octave_base_matrix<boolNDArray> (bm) { }\n\n  ~octave_bool_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_bool_matrix (*this); }\n\n  octave_base_value * empty_clone () const\n  { return new octave_bool_matrix (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  {\n    return m_idx_cache ? *m_idx_cache\n           : set_idx_cache (octave::idx_vector (m_matrix));\n  }\n\n  builtin_type_t builtin_type () const { return btyp_bool; }\n\n  bool is_bool_matrix () const { return true; }\n\n  bool islogical () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool isnumeric () const { return false; }\n\n  int8NDArray\n  int8_array_value () const { return int8NDArray (m_matrix); }\n\n  int16NDArray\n  int16_array_value () const { return int16NDArray (m_matrix); }\n\n  int32NDArray\n  int32_array_value () const { return int32NDArray (m_matrix); }\n\n  int64NDArray\n  int64_array_value () const { return int64NDArray (m_matrix); }\n\n  uint8NDArray\n  uint8_array_value () const { return uint8NDArray (m_matrix); }\n\n  uint16NDArray\n  uint16_array_value () const { return uint16NDArray (m_matrix); }\n\n  uint32NDArray\n  uint32_array_value () const { return uint32NDArray (m_matrix); }\n\n  uint64NDArray\n  uint64_array_value () const { return uint64NDArray (m_matrix); }\n\n  double double_value (bool = false) const;\n\n  float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  Matrix matrix_value (bool = false) const\n  { return Matrix (boolMatrix (m_matrix)); }\n\n  FloatMatrix float_matrix_value (bool = false) const\n  { return FloatMatrix (boolMatrix (m_matrix)); }\n\n  NDArray array_value (bool = false) const\n  { return NDArray (m_matrix); }\n\n  FloatNDArray float_array_value (bool = false) const\n  { return FloatNDArray (m_matrix); }\n\n  Complex complex_value (bool = false) const;\n\n  FloatComplex float_complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const\n  { return ComplexMatrix (boolMatrix (m_matrix)); }\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const\n  { return FloatComplexMatrix (boolMatrix (m_matrix)); }\n\n  ComplexNDArray complex_array_value (bool = false) const\n  { return ComplexNDArray (m_matrix); }\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const\n  { return FloatComplexNDArray (m_matrix); }\n\n  charNDArray\n  char_array_value (bool = false) const\n  {\n    charNDArray retval (dims ());\n\n    octave_idx_type nel = numel ();\n\n    for (octave_idx_type i = 0; i < nel; i++)\n      retval(i) = static_cast<char> (m_matrix(i));\n\n    return retval;\n  }\n\n  boolMatrix bool_matrix_value (bool = false) const\n  { return boolMatrix (m_matrix); }\n\n  boolNDArray bool_array_value (bool = false) const\n  { return m_matrix; }\n\n  SparseMatrix sparse_matrix_value (bool = false) const\n  { return SparseMatrix (Matrix (boolMatrix (m_matrix))); }\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  { return SparseComplexMatrix (ComplexMatrix (boolMatrix (m_matrix))); }\n\n  SparseBoolMatrix sparse_bool_matrix_value (bool = false) const\n  { return SparseBoolMatrix (boolMatrix (m_matrix)); }\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  octave_value all (int dim = 0) const { return m_matrix.all (dim); }\n  octave_value any (int dim = 0) const { return m_matrix.any (dim); }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  // Use matrix_ref here to clear index cache.\n  void invert () { matrix_ref ().invert (); }\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  { return os.write (m_matrix, block_size, output_type, skip, flt_fmt); }\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  // Mapper functions are converted to double for treatment\n  octave_value map (unary_mapper_t umap) const\n  {\n    octave_matrix m (array_value ());\n    return m.map (umap);\n  }\n\nprotected:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-bool-sparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"dim-vector.h\"\n\n#include \"mxarray.h\"\n#include \"errwarn.h\"\n#include \"ops.h\"\n#include \"oct-locbuf.h\"\n\n#include \"oct-hdf5.h\"\n\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n#include \"ov-bool-sparse.h\"\n\n#include \"ov-base-sparse.h\"\n#include \"ov-base-sparse.cc\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_sparse_bool_matrix,\n                                     \"sparse bool matrix\", \"logical\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_sparse_bool_matrix& v\n    = dynamic_cast<const octave_sparse_bool_matrix&> (a);\n\n  return\n    new octave_sparse_matrix (SparseMatrix (v.sparse_bool_matrix_value ()));\n}\n\noctave_base_value::type_conv_info\noctave_sparse_bool_matrix::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n         octave_sparse_matrix::static_type_id ());\n}\n\ndouble\noctave_sparse_bool_matrix::double_value (bool) const\n{\n  if (isempty ())\n    err_invalid_conversion (\"bool sparse matrix\", \"real scalar\");\n\n  if (numel () > 1)\n    warn_implicit_conversion (\"Octave:array-to-scalar\",\n                              \"bool sparse matrix\", \"real scalar\");\n\n  return matrix(0, 0);\n}\n\nComplex\noctave_sparse_bool_matrix::complex_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"bool sparse matrix\", \"complex scalar\");\n\n  if (numel () > 1)\n    warn_implicit_conversion (\"Octave:array-to-scalar\",\n                              \"bool sparse matrix\", \"complex scalar\");\n\n  return Complex (matrix(0, 0), 0);\n}\n\noctave_value\noctave_sparse_bool_matrix::convert_to_str_internal (bool pad, bool force,\n    char type) const\n{\n  octave_value tmp = octave_value (array_value ());\n  return tmp.convert_to_str (pad, force, type);\n}\n\n// FIXME: These are inefficient ways of creating full matrices\n\nMatrix\noctave_sparse_bool_matrix::matrix_value (bool) const\n{\n  return Matrix (matrix.matrix_value ());\n}\n\nComplexMatrix\noctave_sparse_bool_matrix::complex_matrix_value (bool) const\n{\n  return ComplexMatrix (matrix.matrix_value ());\n}\n\nComplexNDArray\noctave_sparse_bool_matrix::complex_array_value (bool) const\n{\n  return ComplexNDArray (ComplexMatrix (matrix.matrix_value ()));\n}\n\nNDArray\noctave_sparse_bool_matrix::array_value (bool) const\n{\n  return NDArray (Matrix (matrix.matrix_value ()));\n}\n\ncharNDArray\noctave_sparse_bool_matrix::char_array_value (bool) const\n{\n  charNDArray retval (dims (), 0);\n  octave_idx_type nc = matrix.cols ();\n  octave_idx_type nr = matrix.rows ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = matrix.cidx (j); i < matrix.cidx (j+1); i++)\n      retval(matrix.ridx (i) + nr * j) = static_cast<char> (matrix.data (i));\n\n  return retval;\n}\n\nboolMatrix\noctave_sparse_bool_matrix::bool_matrix_value (bool) const\n{\n  return matrix.matrix_value ();\n}\n\nboolNDArray\noctave_sparse_bool_matrix::bool_array_value (bool) const\n{\n  return boolNDArray (matrix.matrix_value ());\n}\n\nSparseMatrix\noctave_sparse_bool_matrix::sparse_matrix_value (bool) const\n{\n  return SparseMatrix (this->matrix);\n}\n\nSparseComplexMatrix\noctave_sparse_bool_matrix::sparse_complex_matrix_value (bool) const\n{\n  return SparseComplexMatrix (this->matrix);\n}\n\noctave_value\noctave_sparse_bool_matrix::as_double () const\n{\n  return SparseMatrix (this->matrix);\n}\n\nbool\noctave_sparse_bool_matrix::save_binary (std::ostream& os, bool)\n{\n  const dim_vector& dv = this->dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Ensure that additional memory is deallocated\n  matrix.maybe_compress ();\n\n  octave_idx_type nr = dv(0);\n  octave_idx_type nc = dv(1);\n  octave_idx_type nz = nnz ();\n\n  // For compatiblity, indices are always saved with 4 bytes\n#if OCTAVE_SIZEOF_IDX_TYPE == OCTAVE_SIZEOF_INT\n  if (nr < 0 || nc < 0 || nz < 0)\n    return false;\n#else\n  octave_idx_type max_val = std::numeric_limits<uint32_t>::max ();\n  if (nr < 0 || nr > max_val || nc < 0 || nc > max_val\n      || nz < 0 || nz > max_val)\n    return false;\n#endif\n\n  int32_t itmp;\n  // Use negative value for ndims to be consistent with other formats\n  itmp = -2;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  itmp = nr;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  itmp = nc;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  itmp = nz;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  // add one to the printed indices to go from\n  // zero-based to one-based arrays\n  for (int i = 0; i < nc+1; i++)\n    {\n      octave_quit ();\n      itmp = matrix.cidx (i);\n      os.write (reinterpret_cast<char *> (&itmp), 4);\n    }\n\n  for (int i = 0; i < nz; i++)\n    {\n      octave_quit ();\n      itmp = matrix.ridx (i);\n      os.write (reinterpret_cast<char *> (&itmp), 4);\n    }\n\n  OCTAVE_LOCAL_BUFFER (char, htmp, nz);\n\n  for (int i = 0; i < nz; i++)\n    htmp[i] = (matrix.data (i) ? 1 : 0);\n\n  os.write (htmp, nz);\n\n  return true;\n}\n\nbool\noctave_sparse_bool_matrix::load_binary (std::istream& is, bool swap,\n                                        octave::mach_info::float_format /* fmt */)\n{\n  int32_t nz, nc, nr, tmp;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n    return false;\n\n  if (swap)\n    swap_bytes<4> (&tmp);\n\n  if (tmp != -2)\n    error (\"load: only 2-D sparse matrices are supported\");\n\n  if (! is.read (reinterpret_cast<char *> (&nr), 4))\n    return false;\n  if (! is.read (reinterpret_cast<char *> (&nc), 4))\n    return false;\n  if (! is.read (reinterpret_cast<char *> (&nz), 4))\n    return false;\n\n  if (swap)\n    {\n      swap_bytes<4> (&nr);\n      swap_bytes<4> (&nc);\n      swap_bytes<4> (&nz);\n    }\n\n  SparseBoolMatrix m (static_cast<octave_idx_type> (nr),\n                      static_cast<octave_idx_type> (nc),\n                      static_cast<octave_idx_type> (nz));\n\n  for (int i = 0; i < nc+1; i++)\n    {\n      octave_quit ();\n      if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&tmp);\n      m.cidx (i) = tmp;\n    }\n\n  for (int i = 0; i < nz; i++)\n    {\n      octave_quit ();\n      if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&tmp);\n      m.ridx (i) = tmp;\n    }\n\n  if (! is)\n    return false;\n\n  OCTAVE_LOCAL_BUFFER (char, htmp, nz);\n\n  if (! is.read (htmp, nz))\n    return false;\n\n  for (int i = 0; i < nz; i++)\n    m.data(i) = (htmp[i] ? 1 : 0);\n\n  if (! m.indices_ok ())\n    return false;\n\n  matrix = m;\n\n  return true;\n}\n\nbool\noctave_sparse_bool_matrix::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                                      bool)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  // Ensure that additional memory is deallocated\n  matrix.maybe_compress ();\n#if defined (HAVE_HDF5_18)\n  hid_t group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT,\n                               octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n#else\n  hid_t group_hid = H5Gcreate (loc_id, name, 0);\n#endif\n  if (group_hid < 0)\n    return false;\n\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n  SparseBoolMatrix m = sparse_bool_matrix_value ();\n  octave_idx_type tmp;\n  hsize_t hdims[2];\n\n  space_hid = H5Screate_simple (0, hdims, nullptr);\n  if (space_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nr\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nr\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  tmp = m.rows ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL,\n                     octave_H5S_ALL, octave_H5P_DEFAULT, &tmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nc\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nc\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  tmp = m.cols ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nz\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nz\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  tmp = m.nnz ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n\n  hdims[0] = m.cols () + 1;\n  hdims[1] = 1;\n\n  space_hid = H5Screate_simple (2, hdims, nullptr);\n\n  if (space_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"cidx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"cidx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  octave_idx_type *itmp = m.xcidx ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, itmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n\n  hdims[0] = m.nnz ();\n  hdims[1] = 1;\n\n  space_hid = H5Screate_simple (2, hdims, nullptr);\n\n  if (space_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"ridx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"ridx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  itmp = m.xridx ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, itmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"data\", H5T_NATIVE_HBOOL, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"data\", H5T_NATIVE_HBOOL, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hbool_t, htmp, m.nnz ());\n  for (int i = 0; i < m.nnz (); i++)\n    htmp[i] = m.xdata(i);\n\n  retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, htmp) >= 0;\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n  H5Gclose (group_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_sparse_bool_matrix::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  octave_idx_type nr, nc, nz;\n  hid_t group_hid, data_hid, space_hid;\n  hsize_t rank;\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  group_hid = H5Gopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  group_hid = H5Gopen (loc_id, name);\n#endif\n  if (group_hid < 0) return false;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nr\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nr\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &nr)\n      < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nc\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nc\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &nc)\n      < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nz\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nz\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &nz)\n      < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n  SparseBoolMatrix m (static_cast<octave_idx_type> (nr),\n                      static_cast<octave_idx_type> (nc),\n                      static_cast<octave_idx_type> (nz));\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"cidx\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"cidx\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  if (static_cast<int> (hdims[0]) != nc + 1\n      || static_cast<int> (hdims[1]) != 1)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  octave_idx_type *itmp = m.xcidx ();\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, itmp)\n      < 0)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"ridx\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"ridx\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  if (static_cast<int> (hdims[0]) != nz\n      || static_cast<int> (hdims[1]) != 1)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  itmp = m.xridx ();\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, itmp) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"data\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"data\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  if (static_cast<int> (hdims[0]) != nz\n      || static_cast<int> (hdims[1]) != 1)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nz);\n\n  if (H5Dread (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, htmp) >= 0\n      && m.indices_ok ())\n    {\n      retval = true;\n\n      for (int i = 0; i < nz; i++)\n        m.xdata(i) = htmp[i];\n\n      matrix = m;\n    }\n\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n  H5Gclose (group_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nmxArray *\noctave_sparse_bool_matrix::as_mxArray (bool interleaved) const\n{\n  mwSize nz = nzmax ();\n  mwSize nr = rows ();\n  mwSize nc = columns ();\n\n  mxArray *retval = new mxArray (interleaved, mxLOGICAL_CLASS, nr, nc, nz,\n                                 mxREAL);\n\n  mxLogical *pd = static_cast<mxLogical *> (retval->get_data ());\n  mwIndex *ir = retval->get_ir ();\n\n  const bool *pdata = matrix.data ();\n  const octave_idx_type *pridx = matrix.ridx ();\n\n  for (mwIndex i = 0; i < nz; i++)\n    {\n      pd[i] = pdata[i];\n\n      ir[i] = pridx[i];\n    }\n\n  mwIndex *jc = retval->get_jc ();\n\n  const octave_idx_type *pcidx = matrix.cidx ();\n\n  for (mwIndex i = 0; i < nc + 1; i++)\n    jc[i] = pcidx[i];\n\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-bool-sparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_bool_sparse_h)\n#define octave_ov_bool_sparse_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n\n#include \"boolSparse.h\"\n#include \"ov-base-sparse.h\"\n#include \"ov-re-sparse.h\"\n\nclass octave_value_list;\n\nextern template class OCTINTERP_API octave_base_sparse<SparseBoolMatrix>;\n\nclass OCTINTERP_API octave_sparse_bool_matrix : public octave_base_sparse<SparseBoolMatrix>\n{\npublic:\n\n  octave_sparse_bool_matrix ()\n    : octave_base_sparse<SparseBoolMatrix> () { }\n\n  octave_sparse_bool_matrix (const SparseBoolMatrix& bnda)\n    : octave_base_sparse<SparseBoolMatrix> (bnda) { }\n\n  octave_sparse_bool_matrix (const SparseBoolMatrix& bnda,\n                             const MatrixType& t)\n    : octave_base_sparse<SparseBoolMatrix> (bnda, t) { }\n\n  octave_sparse_bool_matrix (const boolNDArray& m)\n    : octave_base_sparse<SparseBoolMatrix> (SparseBoolMatrix (m)) { }\n\n  octave_sparse_bool_matrix (const boolMatrix& m)\n    : octave_base_sparse<SparseBoolMatrix> (SparseBoolMatrix (m)) { }\n\n  octave_sparse_bool_matrix (const Sparse<bool>& a)\n    : octave_base_sparse<SparseBoolMatrix> (a) { }\n\n  octave_sparse_bool_matrix (const octave_sparse_bool_matrix& bm)\n    : octave_base_sparse<SparseBoolMatrix> (bm) { }\n\n  ~octave_sparse_bool_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_sparse_bool_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_sparse_bool_matrix (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  // FIXME: Adapt idx_vector to allow sparse logical indexing without overflow!\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  {\n    return octave::idx_vector (matrix);\n  }\n\n  builtin_type_t builtin_type () const { return btyp_bool; }\n\n  bool is_bool_matrix () const { return true; }\n\n  bool islogical () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool isnumeric () const { return false; }\n\n  double double_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  Matrix matrix_value (bool = false) const;\n\n  NDArray array_value (bool = false) const;\n\n  Complex complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const;\n\n  charNDArray char_array_value (bool = false) const;\n\n  boolMatrix bool_matrix_value (bool = false) const;\n\n  boolNDArray bool_array_value (bool = false) const;\n\n  SparseMatrix sparse_matrix_value (bool = false) const;\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;\n\n  SparseBoolMatrix sparse_bool_matrix_value (bool = false) const\n  { return matrix; }\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  octave_value as_double () const;\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  // Mapper functions are converted to double for treatment\n  octave_value map (unary_mapper_t umap) const\n  {\n    octave_sparse_matrix m (sparse_matrix_value ());\n    return m.map (umap);\n  }\n\nprotected:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-bool.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"oct-inttypes-fwd.h\"\n\n#include \"mx-base.h\"\n\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"oct-hdf5.h\"\n#include \"ovl.h\"\n#include \"ops.h\"\n#include \"ov-bool.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-base.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"pr-output.h\"\n\n#include \"ls-oct-text.h\"\n#include \"ls-hdf5.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_bool, \"bool\", \"logical\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_bool& v = dynamic_cast<const octave_bool&> (a);\n\n  return new octave_scalar (v.bool_value ());\n}\n\noctave_base_value::type_conv_info\noctave_bool::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n         octave_scalar::static_type_id ());\n\n}\n\noctave_value\noctave_bool::do_index_op (const octave_value_list& idx, bool resize_ok)\n{\n  // FIXME: this doesn't solve the problem of\n  //\n  //   a = 1; a([1,1], [1,1], [1,1])\n  //\n  // and similar constructions.  Hmm...\n\n  // FIXME: using this constructor avoids narrowing the\n  // 1x1 matrix back to a scalar value.  Need a better solution\n  // to this problem.\n\n  octave_value tmp (new octave_bool_matrix (bool_matrix_value ()));\n\n  return tmp.index_op (idx, resize_ok);\n}\n\noctave_value\noctave_bool::as_double () const\n{\n  return static_cast<double> (scalar);\n}\n\noctave_value\noctave_bool::as_single () const\n{\n  return static_cast<float> (scalar);\n}\n\noctave_value\noctave_bool::as_int8 () const\n{\n  return octave_int8 (scalar);\n}\n\noctave_value\noctave_bool::as_int16 () const\n{\n  return octave_int16 (scalar);\n}\n\noctave_value\noctave_bool::as_int32 () const\n{\n  return octave_int32 (scalar);\n}\n\noctave_value\noctave_bool::as_int64 () const\n{\n  return octave_int64 (scalar);\n}\n\noctave_value\noctave_bool::as_uint8 () const\n{\n  return octave_uint8 (scalar);\n}\n\noctave_value\noctave_bool::as_uint16 () const\n{\n  return octave_uint16 (scalar);\n}\n\noctave_value\noctave_bool::as_uint32 () const\n{\n  return octave_uint32 (scalar);\n}\n\noctave_value\noctave_bool::as_uint64 () const\n{\n  return octave_uint64 (scalar);\n}\n\noctave_value\noctave_bool::resize (const dim_vector& dv, bool fill) const\n{\n  if (fill)\n    {\n      boolNDArray retval (dv, false);\n      if (dv.numel ())\n        retval(0) = scalar;\n      return retval;\n    }\n  else\n    {\n      boolNDArray retval (dv);\n      if (dv.numel ())\n        retval(0) = scalar;\n      return retval;\n    }\n}\n\noctave_value\noctave_bool::convert_to_str_internal (bool, bool, char type) const\n{\n  char s[2];\n  s[0] = static_cast<char> (scalar);\n  s[1] = '\\0';\n\n  return octave_value (s, type);\n}\n\nbool\noctave_bool::save_ascii (std::ostream& os)\n{\n  double d = double_value ();\n\n  octave::write_value<double> (os, d);\n  os << \"\\n\";\n\n  return true;\n}\n\nbool\noctave_bool::load_ascii (std::istream& is)\n{\n  scalar = (octave::read_value<double> (is) != 0.0);\n\n  if (! is)\n    error (\"load: failed to load scalar constant\");\n\n  return true;\n}\n\nbool\noctave_bool::save_binary (std::ostream& os, bool /* save_as_floats */)\n{\n  char tmp = (scalar ? 1 : 0);\n  os.write (reinterpret_cast<char *> (&tmp), 1);\n\n  return true;\n}\n\nbool\noctave_bool::load_binary (std::istream& is, bool /* swap */,\n                          octave::mach_info::float_format /* fmt */)\n{\n  char tmp;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n    return false;\n  scalar = (tmp ? 1 : 0);\n  return true;\n}\n\nbool\noctave_bool::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                        bool /* save_as_floats */)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hsize_t dimens[3] = {0};\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n\n  space_hid = H5Screate_simple (0, dimens, nullptr);\n  if (space_hid < 0) return false;\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_DOUBLE, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_DOUBLE, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n\n  double tmp = double_value ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL,\n                     octave_H5S_ALL, octave_H5P_DEFAULT, &tmp) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_bool::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n#if defined (HAVE_HDF5)\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  double dtmp;\n  if (H5Dread (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &dtmp) < 0)\n    {\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  scalar = (dtmp != 0.0);\n\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return true;\n}\n\nmxArray *\noctave_bool::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxLOGICAL_CLASS, 1, 1, mxREAL);\n\n  mxLogical *pd = static_cast<mxLogical *> (retval->get_data ());\n\n  pd[0] = scalar;\n\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-bool.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_bool_h)\n#define octave_ov_bool_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-base-scalar.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Real scalar values.\n\nextern template class OCTINTERP_API octave_base_scalar<bool>;\n\nclass OCTINTERP_API octave_bool : public octave_base_scalar<bool>\n{\npublic:\n\n  octave_bool ()\n    : octave_base_scalar<bool> (false) { }\n\n  octave_bool (bool b)\n    : octave_base_scalar<bool> (b) { }\n\n  octave_bool (const octave_bool& s)\n    : octave_base_scalar<bool> (s) { }\n\n  ~octave_bool () = default;\n\n  octave_base_value * clone () const { return new octave_bool (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_bool_matrix (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  { return octave::idx_vector (scalar); }\n\n  builtin_type_t builtin_type () const { return btyp_bool; }\n\n  bool is_real_scalar () const { return true; }\n\n  bool is_bool_scalar () const { return true; }\n\n  bool islogical () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool isnumeric () const { return false; }\n\n  bool is_true () const { return scalar; }\n\n  int8NDArray\n  int8_array_value () const\n  { return int8NDArray (dim_vector (1, 1), scalar); }\n\n  int16NDArray\n  int16_array_value () const\n  { return int16NDArray (dim_vector (1, 1), scalar); }\n\n  int32NDArray\n  int32_array_value () const\n  { return int32NDArray (dim_vector (1, 1), scalar); }\n\n  int64NDArray\n  int64_array_value () const\n  { return int64NDArray (dim_vector (1, 1), scalar); }\n\n  uint8NDArray\n  uint8_array_value () const\n  { return uint8NDArray (dim_vector (1, 1), scalar); }\n\n  uint16NDArray\n  uint16_array_value () const\n  { return uint16NDArray (dim_vector (1, 1), scalar); }\n\n  uint32NDArray\n  uint32_array_value () const\n  { return uint32NDArray (dim_vector (1, 1), scalar); }\n\n  uint64NDArray\n  uint64_array_value () const\n  { return uint64NDArray (dim_vector (1, 1), scalar); }\n\n  octave_int8\n  int8_scalar_value () const { return octave_int8 (scalar); }\n\n  octave_int16\n  int16_scalar_value () const { return octave_int16 (scalar); }\n\n  octave_int32\n  int32_scalar_value () const { return octave_int32 (scalar); }\n\n  octave_int64\n  int64_scalar_value () const { return octave_int64 (scalar); }\n\n  octave_uint8\n  uint8_scalar_value () const { return octave_uint8 (scalar); }\n\n  octave_uint16\n  uint16_scalar_value () const { return octave_uint16 (scalar); }\n\n  octave_uint32\n  uint32_scalar_value () const { return octave_uint32 (scalar); }\n\n  octave_uint64\n  uint64_scalar_value () const { return octave_uint64 (scalar); }\n\n  double double_value (bool = false) const { return scalar; }\n\n  float float_value (bool = false) const { return scalar; }\n\n  double scalar_value (bool = false) const { return scalar; }\n\n  float float_scalar_value (bool = false) const { return scalar; }\n\n  Matrix matrix_value (bool = false) const\n  { return Matrix (1, 1, scalar); }\n\n  FloatMatrix float_matrix_value (bool = false) const\n  { return FloatMatrix (1, 1, scalar); }\n\n  NDArray array_value (bool = false) const\n  { return NDArray (dim_vector (1, 1), double_value ()); }\n\n  FloatNDArray float_array_value (bool = false) const\n  { return FloatNDArray (dim_vector (1, 1), float_value ()); }\n\n  Complex complex_value (bool = false) const { return scalar; }\n\n  FloatComplex float_complex_value (bool = false) const { return scalar; }\n\n  ComplexMatrix complex_matrix_value (bool = false) const\n  { return ComplexMatrix (1, 1, Complex (scalar)); }\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const\n  { return FloatComplexMatrix (1, 1, FloatComplex (scalar)); }\n\n  ComplexNDArray complex_array_value (bool = false) const\n  { return ComplexNDArray (dim_vector (1, 1), Complex (scalar)); }\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const\n  { return FloatComplexNDArray (dim_vector (1, 1), FloatComplex (scalar)); }\n\n  SparseMatrix sparse_matrix_value (bool = false) const\n  { return SparseMatrix (Matrix (1, 1, scalar)); }\n\n  // FIXME: Need SparseComplexMatrix (Matrix) constructor!\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  { return SparseComplexMatrix (sparse_matrix_value ()); }\n\n  SparseBoolMatrix sparse_bool_matrix_value (bool = false) const\n  { return SparseBoolMatrix (boolMatrix (1, 1, scalar)); }\n\n  charNDArray\n  char_array_value (bool = false) const\n  {\n    charNDArray retval (dim_vector (1, 1));\n    retval(0) = static_cast<char> (scalar);\n    return retval;\n  }\n\n  bool bool_value (bool = false) const { return scalar; }\n\n  boolMatrix bool_matrix_value (bool = false) const\n  { return boolMatrix (1, 1, scalar); }\n\n  boolNDArray bool_array_value (bool = false) const\n  { return boolNDArray (dim_vector (1, 1), scalar); }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const;\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    return os.write (bool_array_value (), block_size, output_type,\n                     skip, flt_fmt);\n  }\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  // Mapper functions are converted to double for treatment\n  octave_value map (unary_mapper_t umap) const\n  {\n    octave_scalar m (scalar_value ());\n    return m.map (umap);\n  }\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-builtin.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ov-builtin.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"profiler.h\"\n#include \"unwind-prot.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_builtin,\n                                     \"built-in function\",\n                                     \"built-in function\");\n\noctave_value_list\noctave_builtin::execute (octave::tree_evaluator& tw, int nargout,\n                         const octave_value_list& args)\n{\n  return tw.execute_builtin_function (*this, nargout, args);\n}\n\noctave_builtin::fcn\noctave_builtin::function () const\n{\n  return m_fcn;\n}\n\noctave_builtin::meth\noctave_builtin::method () const\n{\n  return m_meth;\n}\n\nvoid\noctave_builtin::push_dispatch_class (const std::string& dispatch_type)\n{\n  m_dispatch_classes.insert (dispatch_type);\n}\n\nbool\noctave_builtin::handles_dispatch_class (const std::string& dispatch_type) const\n{\n  return m_dispatch_classes.find (dispatch_type) != m_dispatch_classes.end ();\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-builtin.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_builtin_h)\n#define octave_ov_builtin_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <set>\n#include <string>\n\n#include \"ov-fcn.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value;\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_evaluator;\nclass interpreter;\n\nOCTAVE_END_NAMESPACE(octave)\n\n// Builtin functions.\n\nclass OCTINTERP_API octave_builtin : public octave_function\n{\npublic:\n\n  octave_builtin ()\n    : octave_function (), m_fcn (nullptr), m_meth (nullptr), m_file ()\n  { }\n\n  typedef octave_value_list (*meth) (octave::interpreter&,\n                                     const octave_value_list&, int);\n\n  typedef octave_value_list (*fcn) (const octave_value_list&, int);\n\n  octave_builtin (fcn ff, const std::string& nm = \"\",\n                  const std::string& ds = \"\")\n    : octave_function (nm, ds), m_fcn (ff), m_meth (nullptr), m_file ()\n  { }\n\n  octave_builtin (meth mm, const std::string& nm = \"\",\n                  const std::string& ds = \"\")\n    : octave_function (nm, ds), m_fcn (nullptr), m_meth (mm), m_file ()\n  { }\n\n  octave_builtin (fcn ff, const std::string& nm, const std::string& fnm,\n                  const std::string& ds)\n    : octave_function (nm, ds), m_fcn (ff), m_meth (nullptr), m_file (fnm)\n  { }\n\n  octave_builtin (meth mm, const std::string& nm, const std::string& fnm,\n                  const std::string& ds)\n    : octave_function (nm, ds), m_fcn (nullptr), m_meth (mm), m_file (fnm)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_builtin)\n\n  ~octave_builtin () = default;\n\n  std::string src_file_name () const { return m_file; }\n\n  octave_function * function_value (bool = false) { return this; }\n\n  bool is_builtin_function () const { return true; }\n\n  octave_value_list\n  execute (octave::tree_evaluator& tw, int nargout = 0,\n           const octave_value_list& args = octave_value_list ());\n\n  fcn function () const;\n\n  meth method () const;\n\n  void push_dispatch_class (const std::string& dispatch_type);\n\n  bool handles_dispatch_class (const std::string& dispatch_type) const;\n\nprotected:\n\n  // A pointer to the actual function.\n  fcn m_fcn;\n  meth m_meth;\n\n  // The name of the file where this function was defined.\n  std::string m_file;\n\n  // The types this function has been declared to handle (if any).\n  std::set<std::string> m_dispatch_classes;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-cell.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n#include <sstream>\n#include <queue>\n#include <iterator>\n\n#include \"Array-util.h\"\n#include \"byte-swap.h\"\n#include \"lo-utils.h\"\n#include \"quit.h\"\n#include \"oct-locbuf.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"mxarray.h\"\n#include \"ov-cell.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"pr-output.h\"\n#include \"ov-scalar.h\"\n#include \"errwarn.h\"\n\n#include \"ls-oct-text.h\"\n#include \"ls-oct-binary.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-utils.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_cell, \"cell\", \"cell\");\n\nvoid\noctave_cell::break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame)\n{\n  for (octave_idx_type i = 0; i < m_matrix.numel (); i++)\n    m_matrix(i).break_closure_cycles (frame);\n}\n\noctave_value_list\noctave_cell::simple_subsref (char type, octave_value_list& idx, int)\n{\n  octave_value_list retval;\n\n  switch (type)\n    {\n    case '(':\n      retval(0) = do_index_op (idx);\n      break;\n\n    case '{':\n      {\n        if (idx.empty ())\n          error (\"invalid empty index expression {}, use {:} instead\");\n\n        octave_value tmp = do_index_op (idx);\n\n        Cell tcell = tmp.cell_value ();\n\n        if (tcell.numel () == 1)\n          retval(0) = tcell(0, 0);\n        else\n          {\n            // Return a comma-separated list.\n            retval = octave_value (octave_value_list (tcell));\n          }\n      }\n      break;\n\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_cell::simple_subsref - please report this bug\");\n    }\n\n  return retval;\n}\n\noctave_value_list\noctave_cell::subsref (const std::string& type,\n                      const std::list<octave_value_list>& idx,\n                      int nargout)\n{\n  octave_value_list retval;\n\n  switch (type[0])\n    {\n    case '(':\n      retval(0) = do_index_op (idx.front ());\n      break;\n\n    case '{':\n      {\n        if (idx.front ().empty ())\n          error (\"invalid empty index expression {}, use {:} instead\");\n\n        octave_value tmp = do_index_op (idx.front ());\n\n        Cell tcell = tmp.cell_value ();\n\n        if (tcell.numel () == 1)\n          retval(0) = tcell(0, 0);\n        else\n          {\n            // Return a comma-separated list.\n            retval = octave_value (octave_value_list (tcell));\n          }\n      }\n      break;\n\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_cell::subsref - please report this bug\");\n    }\n\n  // FIXME: perhaps there should be an\n  // octave_value_list::next_subsref member function?  See also\n  // octave_user_function::subsref.\n\n  if (idx.size () > 1)\n    retval = retval(0).next_subsref (nargout, type, idx);\n\n  return retval;\n}\n\noctave_value\noctave_cell::subsref (const std::string& type,\n                      const std::list<octave_value_list>& idx,\n                      bool auto_add)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      retval = do_index_op (idx.front (), auto_add);\n      break;\n\n    case '{':\n      {\n        octave_value tmp = do_index_op (idx.front (), auto_add);\n\n        const Cell tcell = tmp.cell_value ();\n\n        if (tcell.numel () == 1)\n          retval = tcell(0, 0);\n        else\n          {\n            // Return a comma-separated list.\n            retval = octave_value (octave_value_list (tcell));\n          }\n      }\n      break;\n\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_cell::subsref - please report this bug\");\n    }\n\n  // FIXME: perhaps there should be an\n  // octave_value_list::next_subsref member function?  See also\n  // octave_user_function::subsref.\n\n  if (idx.size () > 1)\n    retval = retval.next_subsref (auto_add, type, idx);\n\n  return retval;\n}\n\noctave_value\noctave_cell::subsasgn (const std::string& type,\n                       const std::list<octave_value_list>& idx,\n                       const octave_value& rhs)\n{\n  octave_value retval;\n\n  int n = type.length ();\n\n  octave_value t_rhs = rhs;\n\n  clear_cellstr_cache ();\n\n  if (idx.front ().empty ())\n    error (\"missing index in indexed assignment\");\n\n  if (n > 1)\n    {\n      switch (type[0])\n        {\n        case '(':\n          {\n            if (isempty () && type[1] == '.')\n              {\n                // Allow conversion of empty cell array to some other\n                // type in cases like\n                //\n                //  x = {}; x(i).f = rhs\n\n                octave_value tmp = octave_value::empty_conv (type, rhs);\n\n                return tmp.subsasgn (type, idx, rhs);\n              }\n            else\n              {\n                octave_value tmp = do_index_op (idx.front (), true);\n\n                if (! tmp.is_defined ())\n                  tmp = octave_value::empty_conv (type.substr (1), rhs);\n\n                std::list<octave_value_list> next_idx (std::next (idx.begin ()), idx.end ());\n\n                tmp.make_unique ();\n\n                t_rhs = tmp.subsasgn (type.substr (1), next_idx, rhs);\n              }\n          }\n          break;\n\n        case '{':\n          {\n            m_matrix.make_unique ();\n            Cell tmpc = m_matrix.index (idx.front (), true);\n\n            std::list<octave_value_list> next_idx (std::next (idx.begin ()), idx.end ());\n\n            std::string next_type = type.substr (1);\n\n            if (tmpc.numel () != 1)\n              err_indexed_cs_list ();\n\n            octave_value tmp = tmpc(0);\n            tmpc = Cell ();\n\n            if (! tmp.is_defined () || tmp.is_zero_by_zero ())\n              {\n                tmp = octave_value::empty_conv (type.substr (1), rhs);\n                tmp.make_unique (); // probably a no-op.\n              }\n            else\n              // optimization: ignore copy still stored inside array.\n              tmp.make_unique (1);\n\n            t_rhs = tmp.subsasgn (next_type, next_idx, rhs);\n          }\n          break;\n\n        case '.':\n          {\n            if (! isempty ())\n              {\n                std::string nm = type_name ();\n                error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n              }\n\n            // Do nothing; the next branch will handle it.\n          }\n          break;\n\n        default:\n          error (\"unexpected: index not '(', '{', or '.' in octave_cell::subsasgn - please report this bug\");\n        }\n    }\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        octave_value_list i = idx.front ();\n\n        if (t_rhs.iscell ())\n          octave_base_matrix<Cell>::assign (i, t_rhs.cell_value ());\n        else if (t_rhs.isnull ())\n          octave_base_matrix<Cell>::delete_elements (i);\n        else\n          octave_base_matrix<Cell>::assign (i, Cell (t_rhs));\n\n        m_count++;\n        retval = octave_value (this);\n      }\n      break;\n\n    case '{':\n      {\n        octave_value_list idxf = idx.front ();\n\n        if (t_rhs.is_cs_list ())\n          {\n            Cell tmp_cell = Cell (t_rhs.list_value ());\n\n            // Inquire the proper shape of the RHS.\n\n            dim_vector didx = dims ().redim (idxf.length ());\n            for (octave_idx_type k = 0; k < idxf.length (); k++)\n              if (! idxf(k).is_magic_colon ()) didx(k) = idxf(k).numel ();\n\n            if (didx.numel () == tmp_cell.numel ())\n              tmp_cell = tmp_cell.reshape (didx);\n\n            octave_base_matrix<Cell>::assign (idxf, tmp_cell);\n          }\n        else if (idxf.all_scalars ()\n                 || do_index_op (idxf, true).numel () == 1)\n          // Regularize a null matrix if stored into a cell.\n          octave_base_matrix<Cell>::assign (idxf,\n                                            Cell (t_rhs.storable_value ()));\n        else\n          err_nonbraced_cs_list_assignment ();\n\n        m_count++;\n        retval = octave_value (this);\n      }\n      break;\n\n    case '.':\n      {\n        if (! isempty ())\n          {\n            std::string nm = type_name ();\n            error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n          }\n\n        // Allow conversion of empty cell array to some other\n        // type in cases like\n        //\n        //  x = {}; x.f = rhs\n\n        octave_value tmp = octave_value::empty_conv (type, rhs);\n\n        return tmp.subsasgn (type, idx, rhs);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_cell::subsasgn - please report this bug\");\n    }\n\n  return retval;\n}\n\nbool\noctave_cell::iscellstr () const\n{\n  bool retval;\n  if (m_cellstr_cache.get ())\n    retval = true;\n  else\n    {\n      retval = m_matrix.iscellstr ();\n      // Allocate empty cache to mark that this is indeed a cellstr.\n      if (retval)\n        m_cellstr_cache.reset (new Array<std::string> ());\n    }\n\n  return retval;\n}\n\nvoid\noctave_cell::assign (const octave_value_list& idx, const Cell& rhs)\n{\n  clear_cellstr_cache ();\n  octave_base_matrix<Cell>::assign (idx, rhs);\n}\n\nvoid\noctave_cell::assign (const octave_value_list& idx, const octave_value& rhs)\n{\n  clear_cellstr_cache ();\n  octave_base_matrix<Cell>::assign (idx, rhs);\n}\n\nvoid\noctave_cell::delete_elements (const octave_value_list& idx)\n{\n  clear_cellstr_cache ();\n  octave_base_matrix<Cell>::delete_elements (idx);\n}\n\nstd::size_t\noctave_cell::byte_size () const\n{\n  std::size_t retval = 0;\n\n  for (octave_idx_type i = 0; i < numel (); i++)\n    retval += m_matrix(i).byte_size ();\n\n  return retval;\n}\n\noctave_value\noctave_cell::sort (octave_idx_type dim, sortmode mode) const\n{\n  octave_value retval;\n\n  if (! iscellstr ())\n    error (\"sort: only cell arrays of character strings may be sorted\");\n\n  Array<std::string> tmp = cellstr_value ();\n\n  tmp = tmp.sort (dim, mode);\n\n  // We already have the cache.\n  retval = new octave_cell (tmp);\n\n  return retval;\n}\n\noctave_value\noctave_cell::sort (Array<octave_idx_type>& sidx, octave_idx_type dim,\n                   sortmode mode) const\n{\n  octave_value retval;\n\n  if (! iscellstr ())\n    error (\"sort: only cell arrays of character strings may be sorted\");\n\n  Array<std::string> tmp = cellstr_value ();\n\n  tmp = tmp.sort (sidx, dim, mode);\n\n  // We already have the cache.\n  retval = new octave_cell (tmp);\n\n  return retval;\n}\n\nsortmode\noctave_cell::issorted (sortmode mode) const\n{\n  sortmode retval = UNSORTED;\n\n  if (! iscellstr ())\n    error (\"issorted: A is not a cell array of strings\");\n\n  Array<std::string> tmp = cellstr_value ();\n\n  retval = tmp.issorted (mode);\n\n  return retval;\n}\n\nArray<octave_idx_type>\noctave_cell::sort_rows_idx (sortmode mode) const\n{\n  Array<octave_idx_type> retval;\n\n  if (! iscellstr ())\n    error (\"sortrows: only cell arrays of character strings may be sorted\");\n\n  Array<std::string> tmp = cellstr_value ();\n\n  retval = tmp.sort_rows_idx (mode);\n\n  return retval;\n}\n\nsortmode\noctave_cell::is_sorted_rows (sortmode mode) const\n{\n  sortmode retval = UNSORTED;\n\n  if (! iscellstr ())\n    error (\"issorted: A is not a cell array of strings\");\n\n  Array<std::string> tmp = cellstr_value ();\n\n  retval = tmp.is_sorted_rows (mode);\n\n  return retval;\n}\n\nbool\noctave_cell::is_true () const\n{\n  error (\"invalid conversion from cell array to logical value\");\n}\n\noctave_value_list\noctave_cell::list_value () const\n{\n  return octave_value_list (m_matrix);\n}\n\nstring_vector\noctave_cell::string_vector_value (bool pad) const\n{\n  string_vector retval;\n\n  octave_idx_type nel = numel ();\n\n  int n_elts = 0;\n\n  octave_idx_type max_len = 0;\n\n  std::queue<string_vector> strvec_queue;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      string_vector s = m_matrix(i).string_vector_value ();\n\n      octave_idx_type s_len = s.numel ();\n\n      n_elts += s_len ? s_len : 1;\n\n      octave_idx_type s_max_len = s.max_length ();\n\n      if (s_max_len > max_len)\n        max_len = s_max_len;\n\n      strvec_queue.push (s);\n    }\n\n  retval = string_vector (n_elts);\n\n  octave_idx_type k = 0;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      const string_vector s = strvec_queue.front ();\n      strvec_queue.pop ();\n\n      octave_idx_type s_len = s.numel ();\n\n      if (s_len)\n        {\n          for (octave_idx_type j = 0; j < s_len; j++)\n            {\n              std::string t = s[j];\n              int t_len = t.length ();\n\n              if (pad && max_len > t_len)\n                t += std::string (max_len - t_len, ' ');\n\n              retval[k++] = t;\n            }\n        }\n      else if (pad)\n        retval[k++] = std::string (max_len, ' ');\n      else\n        retval[k++] = \"\";\n    }\n\n  return retval;\n}\n\nArray<std::string>\noctave_cell::cellstr_value () const\n{\n  if (! iscellstr ())\n    error (\"invalid conversion from cell array to array of strings\");\n\n  if (m_cellstr_cache->isempty ())\n    *m_cellstr_cache = m_matrix.cellstr_value ();\n\n  return *m_cellstr_cache;\n}\n\nbool\noctave_cell::print_as_scalar () const\n{\n  return true;\n}\n\nvoid\noctave_cell::print (std::ostream& os, bool)\n{\n  print_raw (os);\n}\n\nvoid\noctave_cell::print_raw (std::ostream& os, bool) const\n{\n  int nd = m_matrix.ndims ();\n\n  if (nd == 2)\n    {\n      octave_idx_type nr = rows ();\n      octave_idx_type nc = columns ();\n\n      if (nr > 0 && nc > 0)\n        {\n          indent (os);\n          os << '{';\n          newline (os);\n\n          increment_indent_level ();\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                {\n                  octave_quit ();\n\n                  std::ostringstream buf;\n                  buf << '[' << i+1 << ',' << j+1 << ']';\n\n                  octave_value val = m_matrix(i, j);\n\n                  val.print_with_name (os, buf.str ());\n                }\n            }\n\n          decrement_indent_level ();\n\n          indent (os);\n          os << '}';\n          newline (os);\n        }\n      else\n        {\n          indent (os);\n          os << \"{}\";\n          if (Vprint_empty_dimensions)\n            os << '(' << nr << 'x' << nc << ')';\n          newline (os);\n        }\n    }\n  else\n    {\n      indent (os);\n      const dim_vector& dv = m_matrix.dims ();\n      os << '{' << dv.str () << \" Cell Array}\";\n      newline (os);\n    }\n}\n\nbool\noctave_cell::print_name_tag (std::ostream& os, const std::string& name) const\n{\n  bool retval = false;\n\n  indent (os);\n\n  if (isempty () || ndims () > 2)\n    os << name << \" = \";\n  else\n    {\n      os << name << \" =\";\n      newline (os);\n      retval = true;\n    }\n\n  return retval;\n}\n\nvoid\noctave_cell::short_disp (std::ostream& os) const\n{\n  // octave_base_matrix<octave_value>::short_disp is not appropriate for\n  // cell arrays.\n\n  octave_base_value::short_disp (os);\n}\n\n#define CELL_ELT_TAG \"<cell-element>\"\n\nbool\noctave_cell::save_ascii (std::ostream& os)\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () > 2)\n    {\n      os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n      for (int i = 0; i < dv.ndims (); i++)\n        os << ' ' << dv(i);\n      os << \"\\n\";\n\n      Cell tmp = cell_value ();\n\n      for (octave_idx_type i = 0; i < dv.numel (); i++)\n        {\n          octave_value o_val = tmp.elem (i);\n\n          // Recurse to save sub-value.\n          bool b = save_text_data (os, o_val, CELL_ELT_TAG, false, 0);\n\n          if (! b)\n            return ! os.fail ();\n        }\n    }\n  else\n    {\n      // Keep this case, rather than use generic code above for backward\n      // compatibility.  Makes load_ascii much more complex!!\n      os << \"# rows: \" << rows () << \"\\n\"\n         << \"# columns: \" << columns () << \"\\n\";\n\n      Cell tmp = cell_value ();\n\n      for (octave_idx_type j = 0; j < tmp.cols (); j++)\n        {\n          for (octave_idx_type i = 0; i < tmp.rows (); i++)\n            {\n              octave_value o_val = tmp.elem (i, j);\n\n              // Recurse to save sub-value.\n              bool b = save_text_data (os, o_val, CELL_ELT_TAG, false, 0);\n\n              if (! b)\n                return ! os.fail ();\n            }\n\n          os << \"\\n\";\n        }\n    }\n\n  return true;\n}\n\nbool\noctave_cell::load_ascii (std::istream& is)\n{\n  clear_cellstr_cache ();\n\n  string_vector keywords(2);\n\n  keywords[0] = \"ndims\";\n  keywords[1] = \"rows\";\n\n  std::string kw;\n  octave_idx_type val = 0;\n\n  if (! extract_keyword (is, keywords, kw, val, true))\n    error (\"load: failed to extract number of rows and columns\");\n\n  if (kw == \"ndims\")\n    {\n      int mdims = static_cast<int> (val);\n\n      if (mdims < 0)\n        error (\"load: failed to extract number of rows and columns\");\n\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        is >> dv(i);\n\n      Cell tmp(dv);\n\n      for (octave_idx_type i = 0; i < dv.numel (); i++)\n        {\n          octave_value t2;\n          bool dummy;\n\n          // recurse to read cell elements\n          std::string nm = read_text_data (is, \"\",\n                                           dummy, t2, i);\n\n          if (nm != CELL_ELT_TAG)\n            error (\"load: cell array element had unexpected name\");\n\n          if (is)\n            tmp.elem (i) = t2;\n        }\n\n      if (! is)\n        error (\"load: failed to load matrix constant\");\n\n      m_matrix = tmp;\n    }\n  else if (kw == \"rows\")\n    {\n      octave_idx_type nr = val;\n      octave_idx_type nc = 0;\n\n      if (nr < 0 || ! extract_keyword (is, \"columns\", nc) || nc < 0)\n        error (\"load: failed to extract number of rows and columns for cell array\");\n\n      if (nr > 0 && nc > 0)\n        {\n          Cell tmp (nr, nc);\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                {\n                  octave_value t2;\n                  bool dummy;\n\n                  // recurse to read cell elements\n                  std::string nm = read_text_data (is, \"\",\n                                                   dummy, t2, i);\n\n                  if (nm != CELL_ELT_TAG)\n                    error (\"load: cell array element had unexpected name\");\n\n                  if (is)\n                    tmp.elem (i, j) = t2;\n                }\n            }\n\n          if (! is)\n            error (\"load: failed to load cell element\");\n\n          m_matrix = tmp;\n        }\n      else if (nr == 0 || nc == 0)\n        m_matrix = Cell (nr, nc);\n      else\n        error (\"unexpected dimensions in octave_cell::load_ascii - please report this bug\");\n    }\n  else\n    error (\"unexpected dimensions keyword (= '%s') octave_cell::load_ascii - please report this bug\", kw.c_str ());\n\n  return true;\n}\n\nbool\noctave_cell::save_binary (std::ostream& os, bool save_as_floats)\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Use negative value for ndims\n  int32_t di = - dv.ndims ();\n  os.write (reinterpret_cast<char *> (&di), 4);\n  for (int i = 0; i < dv.ndims (); i++)\n    {\n      di = dv(i);\n      os.write (reinterpret_cast<char *> (&di), 4);\n    }\n\n  Cell tmp = cell_value ();\n\n  for (octave_idx_type i = 0; i < dv.numel (); i++)\n    {\n      octave_value o_val = tmp.elem (i);\n\n      // Recurse to save sub-value.\n      bool b = save_binary_data (os, o_val, CELL_ELT_TAG, \"\", 0,\n                                 save_as_floats);\n\n      if (! b)\n        return false;\n    }\n\n  return true;\n}\n\nbool\noctave_cell::load_binary (std::istream& is, bool swap,\n                          octave::mach_info::float_format fmt)\n{\n  clear_cellstr_cache ();\n\n  int32_t mdims;\n  if (! is.read (reinterpret_cast<char *> (&mdims), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&mdims);\n  if (mdims >= 0)\n    return false;\n\n  mdims = -mdims;\n  int32_t di;\n  dim_vector dv;\n  dv.resize (mdims);\n\n  for (int i = 0; i < mdims; i++)\n    {\n      if (! is.read (reinterpret_cast<char *> (&di), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&di);\n      dv(i) = di;\n    }\n\n  // Convert an array with a single dimension to be a row vector.\n  // Octave should never write files like this, other software\n  // might.\n\n  if (mdims == 1)\n    {\n      mdims = 2;\n      dv.resize (mdims);\n      dv(1) = dv(0);\n      dv(0) = 1;\n    }\n\n  octave_idx_type nel = dv.numel ();\n  Cell tmp(dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      octave_value t2;\n      bool dummy;\n      std::string doc;\n\n      // recurse to read cell elements\n      std::string nm = read_binary_data (is, swap, fmt, \"\",\n                                         dummy, t2, doc);\n\n      if (nm != CELL_ELT_TAG)\n        error (\"load: cell array element had unexpected name\");\n\n      if (is)\n        tmp.elem (i) = t2;\n    }\n\n  if (! is)\n    error (\"load: failed to load matrix constant\");\n\n  m_matrix = tmp;\n\n  return true;\n}\n\nconst void *\noctave_cell::mex_get_data () const\n{\n  clear_cellstr_cache ();\n  return m_matrix.data ();\n}\n\nbool\noctave_cell::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                        bool save_as_floats)\n{\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  hsize_t rank = dv.ndims ();\n  hid_t space_hid, data_hid, size_hid;\n  space_hid = data_hid = size_hid = -1;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Gcreate (loc_id, name, 0);\n#endif\n\n  if (data_hid < 0)\n    return false;\n\n  // Have to save cell array shape, since can't have a\n  // dataset of groups....\n\n  space_hid = H5Screate_simple (1, &rank, nullptr);\n\n  if (space_hid < 0)\n    {\n      H5Gclose (data_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, hdims, rank);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  for (hsize_t i = 0; i < rank; i++)\n    hdims[i] = dv(rank-i-1);\n\n#if defined (HAVE_HDF5_18)\n  size_hid = H5Dcreate (data_hid, \"dims\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  size_hid = H5Dcreate (data_hid, \"dims\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (size_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (data_hid);\n      return false;\n    }\n\n  if (H5Dwrite (size_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                octave_H5P_DEFAULT, hdims) < 0)\n    {\n      H5Dclose (size_hid);\n      H5Sclose (space_hid);\n      H5Gclose (data_hid);\n      return false;\n    }\n\n  H5Dclose (size_hid);\n  H5Sclose (space_hid);\n\n  // Recursively add each element of the cell to this group.\n\n  Cell tmp = cell_value ();\n\n  octave_idx_type nel = dv.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      std::ostringstream buf;\n      int digits = static_cast<int> (std::floor (::log10 (static_cast<double>\n                                     (nel)) + 1.0));\n      buf << '_' << std::setw (digits) << std::setfill ('0') << i;\n      std::string s = buf.str ();\n\n      if (! add_hdf5_data (data_hid, tmp.elem (i), s.c_str (), \"\", false,\n                           save_as_floats))\n        {\n          H5Gclose (data_hid);\n          return false;\n        }\n    }\n\n  H5Gclose (data_hid);\n\n  return true;\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n\n  return false;\n#endif\n}\n\nbool\noctave_cell::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  clear_cellstr_cache ();\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    m_matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  hid_t group_id = H5Gopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t group_id = H5Gopen (loc_id, name);\n#endif\n\n  if (group_id < 0)\n    return false;\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (group_id, \"dims\", octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (group_id, \"dims\");\n#endif\n  hid_t space_hid = H5Dget_space (data_hid);\n  hsize_t rank = H5Sget_simple_extent_ndims (space_hid);\n  if (rank != 1)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_id);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering.\n\n  dv.resize (hdims[0]);\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, hdims[0]);\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, tmp) < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_id);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n  H5Gclose (group_id);\n\n  for (hsize_t i = 0, j = hdims[0] - 1; i < hdims[0]; i++, j--)\n    dv(j) = tmp[i];\n\n  hdf5_callback_data dsub;\n\n  herr_t retval2 = -1;\n\n  Cell m (dv);\n\n  int current_item = 0;\n\n  hsize_t num_obj = 0;\n#if defined (HAVE_HDF5_18)\n  group_id = H5Gopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  group_id = H5Gopen (loc_id, name);\n#endif\n  H5Gget_num_objs (group_id, &num_obj);\n  H5Gclose (group_id);\n\n  for (octave_idx_type i = 0; i < dv.numel (); i++)\n    {\n\n      if (current_item >= static_cast<int> (num_obj))\n        retval2 = -1;\n      else\n        retval2 = hdf5_h5g_iterate (loc_id, name, &current_item, &dsub);\n\n      if (retval2 <= 0)\n        break;\n\n      octave_value ov = dsub.tc;\n      m.elem (i) = ov;\n\n    }\n\n  if (retval2 >= 0)\n    {\n      m_matrix = m;\n      retval = true;\n    }\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (iscell, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} iscell (@var{x})\nReturn true if @var{x} is a cell array object.\n@seealso{ismatrix, isstruct, iscellstr, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).iscell ());\n}\n\nDEFUN (cell, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{C} =} cell (@var{n})\n@deftypefnx {} {@var{C} =} cell (@var{m}, @var{n})\n@deftypefnx {} {@var{C} =} cell (@var{m}, @var{n}, @var{k}, @dots{})\n@deftypefnx {} {@var{C} =} cell ([@var{m} @var{n} @dots{}])\nCreate a new cell array object.\n\nIf invoked with a single scalar integer argument, return a square\n@nospell{NxN} cell array.  If invoked with two or more scalar integer\narguments, or a vector of integer values, return an array with the given\ndimensions.\n@seealso{cellstr, mat2cell, num2cell, struct2cell}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  dim_vector dims;\n\n  switch (nargin)\n    {\n    case 0:\n      dims = dim_vector (0, 0);\n      break;\n\n    case 1:\n      if (args(0).iscell ())\n        return args(0);  // shortcut path for input which is already a Cell\n      else\n        get_dimensions (args(0), \"cell\", dims);\n      break;\n\n    default:\n      {\n        dims.resize (nargin);\n\n        for (int i = 0; i < nargin; i++)\n          dims(i) = (args(i).isempty ()\n                     ? 0 : args(i).strict_idx_type_value (\"cell: dimension must be a scalar integer\"));\n      }\n      break;\n    }\n\n  dims.chop_trailing_singletons ();\n\n  check_dimensions (dims, \"cell\");\n\n  return ovl (Cell (dims));\n}\n\n/*\n## Note: Matlab compatibility requires using 0 for negative dimensions.\n%!assert (size (cell (2, -3)), [2, 0])\n\n%!test <*63132>\n%! x = {1, 3};\n%! y = cell (x);\n%! assert (x, y);\n%! x = cell (0, 3);\n%! y = cell (x);\n%! assert (x, y);\n\n## This might work on some system someday, but for now, who has a system\n## where a 16 yottabyte array can be allocated?  See bug #50934.\n%!error <out of memory> cell (1e24, 1)\n*/\n\nDEFUN (iscellstr, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} iscellstr (@var{cell})\nReturn true if every element of the cell array @var{cell} is a character\nstring.\n@seealso{ischar, isstring}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).iscellstr ());\n}\n\nDEFUN (cellstr, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{cstr} =} cellstr (@var{strmat})\nCreate a new cell array object from the elements of the string array\n@var{strmat}.\n\nEach row of @var{strmat} becomes an element of @var{cstr}.  Any trailing\nspaces in a row are deleted before conversion.\n\nTo convert back from a cellstr to a character array use @code{char}.\n@seealso{cell, char}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value_list tmp = Fiscellstr (args, 1);\n\n  if (tmp(0).is_true ())\n    return ovl (args(0));\n  else\n    {\n      string_vector s = args(0).xstring_vector_value (\"cellstr: argument STRING must be a 2-D character array\");\n\n      return ovl (s.isempty () ? Cell (octave_value (\"\"))\n                               : Cell (s, true));\n    }\n}\n\nDEFUN (struct2cell, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{c} =} struct2cell (@var{s})\nCreate a new cell array from the objects stored in the struct object.\n\nIf @var{f} is the number of fields in the structure, the resulting cell\narray will have a dimension vector corresponding to\n@code{[@var{f} size(@var{s})]}.  For example:\n\n@example\n@group\ns = struct (\"name\", @{\"Peter\", \"Hannah\", \"Robert\"@},\n           \"age\", @{23, 16, 3@});\nc = struct2cell (s)\n   @xresult{} c = @{2x1x3 Cell Array@}\nc(1,1,:)(:)\n   @xresult{}\n      @{\n        [1,1] = Peter\n        [2,1] = Hannah\n        [3,1] = Robert\n      @}\nc(2,1,:)(:)\n   @xresult{}\n      @{\n        [1,1] = 23\n        [2,1] = 16\n        [3,1] = 3\n      @}\n@end group\n@end example\n\n@seealso{cell2struct, namedargs2cell, fieldnames}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  const octave_map m = args(0).xmap_value (\"struct2cell: argument S must be a structure\");\n\n  const dim_vector m_dv = m.dims ();\n\n  octave_idx_type num_fields = m.nfields ();\n\n  // The resulting dim_vector should have dimensions:\n  // [numel(fields) size(struct)]\n  // except if the struct is a column vector.\n\n  dim_vector result_dv;\n  if (m_dv(m_dv.ndims () - 1) == 1)\n    result_dv.resize (m_dv.ndims ());\n  else\n    result_dv.resize (m_dv.ndims () + 1); // Add 1 for the fields.\n\n  result_dv(0) = num_fields;\n\n  for (int i = 1; i < result_dv.ndims (); i++)\n    result_dv(i) = m_dv(i-1);\n\n  Cell c (result_dv);\n\n  octave_idx_type n_elts = m.numel ();\n\n  // Fill c in one sweep.  Note that thanks to octave_map structure,\n  // we don't need a key lookup at all.\n  for (octave_idx_type j = 0; j < n_elts; j++)\n    for (octave_idx_type i = 0; i < num_fields; i++)\n      c.xelem (i, j) = m.contents(i)(j);\n\n  return ovl (c);\n}\n\n/*\n%!test\n%! keys = cellstr (char (floor (rand (11,10)*24+65)))';\n%! vals = cellfun (@(x) mat2cell (rand (19,1), ones (19,1), 1), ...\n%!          mat2cell ([1:11]', ones (11,1), 1), \"uniformoutput\", false)';\n%! s = struct ([keys; vals]{:});\n%! t = cell2struct ([vals{:}], keys, 2);\n%! assert (s, t);\n%! assert (struct2cell (s), [vals{:}]');\n%! assert (fieldnames (s), keys');\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n\nmxArray *\noctave_cell::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, dims ());\n\n  mxArray **elts = static_cast<mxArray **> (retval->get_data ());\n\n  mwSize nel = numel ();\n\n  const octave_value *p = m_matrix.data ();\n\n  for (mwIndex i = 0; i < nel; i++)\n    elts[i] = new mxArray (interleaved, p[i]);\n\n  return retval;\n}\n\noctave_value\noctave_cell::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n#define FORWARD_MAPPER(UMAP)                  \\\n    case umap_ ## UMAP:                       \\\n      return m_matrix.UMAP ()\n\n      FORWARD_MAPPER (xisalnum);\n      FORWARD_MAPPER (xisalpha);\n      FORWARD_MAPPER (xisascii);\n      FORWARD_MAPPER (xiscntrl);\n      FORWARD_MAPPER (xisdigit);\n      FORWARD_MAPPER (xisgraph);\n      FORWARD_MAPPER (xislower);\n      FORWARD_MAPPER (xisprint);\n      FORWARD_MAPPER (xispunct);\n      FORWARD_MAPPER (xisspace);\n      FORWARD_MAPPER (xisupper);\n      FORWARD_MAPPER (xisxdigit);\n      FORWARD_MAPPER (xtolower);\n      FORWARD_MAPPER (xtoupper);\n\n    default:\n      return octave_base_value::map (umap);\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-cell.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_cell_h)\n#define octave_ov_cell_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n#include <memory>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"Cell.h\"\n#include \"error.h\"\n#include \"ov-base-mat.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Cells.\n\nextern template class OCTINTERP_API octave_base_matrix<Cell>;\n\nclass octave_cell : public octave_base_matrix<Cell>\n{\npublic:\n\n  octave_cell ()\n    : octave_base_matrix<Cell> (), m_cellstr_cache () { }\n\n  octave_cell (const Cell& c)\n    : octave_base_matrix<Cell> (c), m_cellstr_cache () { }\n\n  octave_cell (const Array<std::string>& str)\n    : octave_base_matrix<Cell> (Cell (str)),\n      m_cellstr_cache (new Array<std::string> (str)) { }\n\n  octave_cell (const octave_cell& c)\n    : octave_base_matrix<Cell> (c), m_cellstr_cache () { }\n\n  ~octave_cell () = default;\n\n  octave_base_value * clone () const { return new octave_cell (*this); }\n  octave_base_value * empty_clone () const { return new octave_cell (); }\n\n  void break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame);\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx)\n  {\n    octave_value_list tmp = subsref (type, idx, 1);\n    return tmp.length () > 0 ? tmp(0) : octave_value ();\n  }\n\n  octave_value_list subsref (const std::string& type,\n                             const std::list<octave_value_list>& idx,\n                             int nargout);\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx,\n                        bool auto_add);\n\n  octave_value subsasgn (const std::string& type,\n                         const std::list<octave_value_list>& idx,\n                         const octave_value& rhs);\n\n  // FIXME: should we import the functions from the base class and\n  // overload them here, or should we use a different name so we don't\n  // have to do this?  Without the using declaration or a name change,\n  // the base class functions will be hidden.  That may be OK, but it\n  // can also cause some confusion.\n  using octave_base_value::assign;\n\n  void assign (const octave_value_list& idx, const Cell& rhs);\n\n  void assign (const octave_value_list& idx, const octave_value& rhs);\n\n  void delete_elements (const octave_value_list& idx);\n\n  std::size_t byte_size () const;\n\n  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;\n\n  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n                     sortmode mode = ASCENDING) const;\n\n  sortmode issorted (sortmode mode = UNSORTED) const;\n\n  Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const;\n\n  sortmode is_sorted_rows (sortmode mode = UNSORTED) const;\n\n  bool is_matrix_type () const { return false; }\n\n  bool isnumeric () const { return false; }\n\n  bool is_defined () const { return true; }\n\n  bool is_constant () const { return true; }\n\n  bool iscell () const { return true; }\n\n  builtin_type_t builtin_type () const { return btyp_cell; }\n\n  bool iscellstr () const;\n\n  bool is_true () const;\n\n  bool is_full_num_matrix () const { return false; }\n\n  Cell cell_value () const { return m_matrix; }\n\n  octave_value_list list_value () const;\n\n  octave_value convert_to_str_internal (bool pad, bool, char type) const\n  { return octave_value (string_vector_value (pad), type); }\n\n  string_vector string_vector_value (bool pad = false) const;\n\n  Array<std::string> cellstr_value () const;\n\n  Array<std::string> cellstr_value (const char *fmt, ...) const;\n\n  bool print_as_scalar () const;\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  bool print_name_tag (std::ostream& os, const std::string& name) const;\n\n  void short_disp (std::ostream& os) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  octave_value map (unary_mapper_t umap) const;\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  // This function exists to support the MEX interface.\n  // You should not use it anywhere else.\n  const void * mex_get_data () const;\n\n  octave_value_list\n  simple_subsref (char type, octave_value_list& idx, int nargout);\n\nprivate:\n\n  void clear_cellstr_cache () const\n  { m_cellstr_cache.reset (); }\n\n  //--------\n\n  mutable std::unique_ptr<Array<std::string>> m_cellstr_cache;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-ch-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cctype>\n#include <ostream>\n\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n#include \"int8NDArray.h\"\n#include \"int16NDArray.h\"\n#include \"int32NDArray.h\"\n#include \"int64NDArray.h\"\n#include \"uint8NDArray.h\"\n#include \"uint16NDArray.h\"\n#include \"uint32NDArray.h\"\n#include \"uint64NDArray.h\"\n\n#include \"lo-ieee.h\"\n#include \"mx-base.h\"\n#include \"unicase-wrappers.h\"\n#include \"unictype-wrappers.h\"\n#include \"unistr-wrappers.h\"\n\n#include \"mxarray.h\"\n#include \"ov-ch-mat.h\"\n#include \"errwarn.h\"\n#include \"pr-output.h\"\n\noctave::idx_vector\noctave_char_matrix::index_vector (bool /* require_integers */) const\n{\n  const char *p = m_matrix.data ();\n  if (numel () == 1 && *p == ':')\n    return octave::idx_vector (':');\n  else\n    return octave::idx_vector (array_value (true));\n}\n\ndouble\noctave_char_matrix::double_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"character matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"character matrix\", \"real scalar\");\n\n  return static_cast<unsigned char> (m_matrix(0, 0));\n}\n\nfloat\noctave_char_matrix::float_value (bool) const\n{\n  if (rows () == 0 && columns () == 0)\n    err_invalid_conversion (\"character matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"character matrix\", \"real scalar\");\n\n  return static_cast<unsigned char> (m_matrix(0, 0));\n}\n\noctave_int64\noctave_char_matrix::int64_scalar_value () const\n{\n  octave_int64 retval = 0;\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"character matrix\", \"int64 scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"character matrix\", \"int64 scalar\");\n\n  retval = octave_int64 (m_matrix(0, 0));\n\n  return retval;\n}\n\noctave_uint64\noctave_char_matrix::uint64_scalar_value () const\n{\n  octave_uint64 retval = 0;\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"character matrix\", \"uint64 scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"character matrix\", \"uint64 scalar\");\n\n  retval = octave_uint64 (m_matrix(0, 0));\n\n  return retval;\n}\n\nComplex\noctave_char_matrix::complex_value (bool) const\n{\n  if (rows () == 0 && columns () == 0)\n    err_invalid_conversion (\"character matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"character matrix\", \"complex scalar\");\n\n  return Complex (static_cast<unsigned char> (m_matrix(0, 0)), 0);\n}\n\nFloatComplex\noctave_char_matrix::float_complex_value (bool) const\n{\n  float tmp = lo_ieee_float_nan_value ();\n\n  FloatComplex retval (tmp, tmp);\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"character matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"character matrix\", \"complex scalar\");\n\n  retval = static_cast<unsigned char> (m_matrix(0, 0));\n\n  return retval;\n}\n\noctave_value\noctave_char_matrix::as_double () const\n{\n  return NDArray (m_matrix);\n}\n\noctave_value\noctave_char_matrix::as_single () const\n{\n  return FloatNDArray (m_matrix);\n}\n\noctave_value\noctave_char_matrix::as_int8 () const\n{\n  return int8NDArray (m_matrix);\n}\n\noctave_value\noctave_char_matrix::as_int16 () const\n{\n  return int16NDArray (m_matrix);\n}\n\noctave_value\noctave_char_matrix::as_int32 () const\n{\n  return int32NDArray (m_matrix);\n}\n\noctave_value\noctave_char_matrix::as_int64 () const\n{\n  return int64NDArray (m_matrix);\n}\n\noctave_value\noctave_char_matrix::as_uint8 () const\n{\n  return uint8NDArray (m_matrix);\n}\n\noctave_value\noctave_char_matrix::as_uint16 () const\n{\n  return uint16NDArray (m_matrix);\n}\n\noctave_value\noctave_char_matrix::as_uint32 () const\n{\n  return uint32NDArray (m_matrix);\n}\n\noctave_value\noctave_char_matrix::as_uint64 () const\n{\n  return uint64NDArray (m_matrix);\n}\n\nvoid\noctave_char_matrix::print_raw (std::ostream& os,\n                               bool pr_as_read_syntax) const\n{\n  octave_print_internal (os, m_matrix, pr_as_read_syntax,\n                         current_print_indent_level ());\n}\n\nmxArray *\noctave_char_matrix::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxCHAR_CLASS, dims (), mxREAL);\n\n  mxChar *pd = static_cast<mxChar *> (retval->get_data ());\n\n  mwSize nel = numel ();\n\n  const char *pdata = m_matrix.data ();\n\n  for (mwIndex i = 0; i < nel; i++)\n    pd[i] = pdata[i];\n\n  return retval;\n}\n\n// The C++ standard guarantees cctype defines functions, not macros (and\n// hence macros *CAN'T* be defined if only cctype is included) so\n// there's no need to fuck around.  The exceptions are isascii and\n// toascii, which are not C++.  Oddly enough, all those character\n// functions are int (*) (int), even in C++.  Wicked!\nstatic inline int\nxisascii (int c)\n{\n#if defined (HAVE_ISASCII)\n  return isascii (c);\n#else\n  return (c >= 0x00 && c <= 0x7f);\n#endif\n}\n\noctave_value\noctave_char_matrix::map (unary_mapper_t umap) const\n{\n  octave_value retval;\n\n  switch (umap)\n    {\n#define STRING_MAPPER(UMAP,FCN,TYPE)                                  \\\n    case umap_ ## UMAP:                                               \\\n      return octave_value (m_matrix.map<TYPE, int (&) (int)> (FCN))\n\n      STRING_MAPPER (xisascii, xisascii, bool);\n\n#define STRING_U8_MAPPER(UMAP,FCN)                                             \\\n    case umap_ ## UMAP:                                                        \\\n      {                                                                        \\\n        charNDArray in_m = m_matrix;                                           \\\n        Array<octave_idx_type> p (dim_vector (m_matrix.ndims (), 1));          \\\n        if (m_matrix.ndims () > 1)                                             \\\n          {                                                                    \\\n            for (octave_idx_type i=0; i < m_matrix.ndims (); i++)              \\\n              p(i) = i;                                                        \\\n            p(0) = 1;                                                          \\\n            p(1) = 0;                                                          \\\n            in_m = m_matrix.permute (p);                                       \\\n          }                                                                    \\\n        boolNDArray b_array = boolNDArray (in_m.dims ());                      \\\n        const uint8_t *in = reinterpret_cast<const uint8_t *> (in_m.data ());  \\\n        uint32_t uc;                                                           \\\n        for (octave_idx_type i = 0; i < in_m.numel (); )                       \\\n        {                                                                      \\\n          int mblen = octave_u8_strmbtouc_wrapper (&uc, in + i);               \\\n          if (mblen < 1)                                                       \\\n            mblen = 1;                                                         \\\n          bool is_upper = FCN (uc);                                            \\\n          for (int j = 0; j < mblen; j++)                                      \\\n            b_array(i+j) = is_upper;                                           \\\n          i += mblen;                                                          \\\n        }                                                                      \\\n        return octave_value ((m_matrix.ndims () > 1) ? b_array.permute (p, true) \\\n                                                     : b_array);               \\\n      }\n\n      STRING_U8_MAPPER (xisalnum, octave_uc_is_alnum_wrapper);\n      STRING_U8_MAPPER (xisalpha, octave_uc_is_alpha_wrapper);\n      STRING_U8_MAPPER (xiscntrl, octave_uc_is_cntrl_wrapper);\n      STRING_U8_MAPPER (xisdigit, octave_uc_is_digit_wrapper);\n      STRING_U8_MAPPER (xisgraph, octave_uc_is_graph_wrapper);\n      STRING_U8_MAPPER (xislower, octave_uc_is_lower_wrapper);\n      STRING_U8_MAPPER (xisprint, octave_uc_is_print_wrapper);\n      STRING_U8_MAPPER (xispunct, octave_uc_is_punct_wrapper);\n      STRING_U8_MAPPER (xisspace, octave_uc_is_space_wrapper);\n      STRING_U8_MAPPER (xisupper, octave_uc_is_upper_wrapper);\n      STRING_U8_MAPPER (xisxdigit, octave_uc_is_xdigit_wrapper);\n\n#define STRING_U8_FCN(UMAP,U8_FCN,STD_FCN)                                     \\\n    case umap_ ## UMAP:                                                        \\\n      {                                                                        \\\n        charNDArray in_m = m_matrix;                                           \\\n        Array<octave_idx_type> p (dim_vector (m_matrix.ndims (), 1));          \\\n        if (m_matrix.ndims () > 1)                                             \\\n          {                                                                    \\\n            for (octave_idx_type i=0; i < m_matrix.ndims (); i++)              \\\n              p(i) = i;                                                        \\\n            p(0) = 1;                                                          \\\n            p(1) = 0;                                                          \\\n            in_m = m_matrix.permute (p);                                       \\\n          }                                                                    \\\n        std::size_t output_length = in_m.numel ();                             \\\n        charNDArray ch_array = charNDArray (in_m.dims ());                     \\\n        const uint8_t *in = reinterpret_cast<const uint8_t *> (in_m.data ());  \\\n        uint8_t *buf = reinterpret_cast<uint8_t *> (ch_array.rwdata ());       \\\n        U8_FCN (in, m_matrix.numel (), nullptr, buf, &output_length);          \\\n        if (output_length != static_cast<std::size_t> (m_matrix.numel ()))     \\\n          {                                                                    \\\n            warning_with_id (\"Octave:multi_byte_char_length\",                  \\\n                             \"UMAP: Possible multi-byte error.\");              \\\n            return octave_value (m_matrix.map<char, int (&) (int)> (STD_FCN)); \\\n          }                                                                    \\\n        return octave_value ((m_matrix.ndims () > 1) ? ch_array.permute (p, true)\\\n                                                     : ch_array);              \\\n      }\n\n      STRING_U8_FCN (xtolower, octave_u8_tolower_wrapper, std::tolower);\n      STRING_U8_FCN (xtoupper, octave_u8_toupper_wrapper, std::toupper);\n\n    // For Matlab compatibility, these should work on ASCII values\n    // without error or warning.\n    case umap_abs:\n    case umap_ceil:\n    case umap_fix:\n    case umap_floor:\n    case umap_imag:\n    case umap_isfinite:\n    case umap_isinf:\n    case umap_isnan:\n    case umap_real:\n    case umap_round:\n      {\n        octave_matrix m (array_value (true));\n        return m.map (umap);\n      }\n\n    default:\n      error (\"%s: argument must be numeric\", get_umap_name (umap));\n      break;\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-ch-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_ch_mat_h)\n#define octave_ov_ch_mat_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"ov.h\"\n#include \"ov-base.h\"\n#include \"ov-base-mat.h\"\n#include \"ov-int64.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Character matrix values.\n\nextern template class OCTINTERP_API octave_base_matrix<charNDArray>;\n\nclass octave_char_matrix : public octave_base_matrix<charNDArray>\n{\nprotected:\n\n  octave_char_matrix ()\n    : octave_base_matrix<charNDArray> () { }\n\n  octave_char_matrix (const charMatrix& chm)\n    : octave_base_matrix<charNDArray> (chm) { }\n\n  octave_char_matrix (const charNDArray& chm)\n    : octave_base_matrix<charNDArray> (chm) { }\n\n  octave_char_matrix (const Array<char>& chm)\n    : octave_base_matrix<charNDArray> (chm) { }\n\n  octave_char_matrix (char c)\n    : octave_base_matrix<charNDArray> (c) { }\n\n  octave_char_matrix (const char *s)\n    : octave_base_matrix<charNDArray> (s) { }\n\n  octave_char_matrix (const std::string& s)\n    : octave_base_matrix<charNDArray> (s) { }\n\n  octave_char_matrix (const string_vector& s)\n    : octave_base_matrix<charNDArray> (s) { }\n\n  octave_char_matrix (const octave_char_matrix& chm)\n    : octave_base_matrix<charNDArray> (chm) { }\n\npublic:\n\n  ~octave_char_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_char_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_char_matrix (); }\n\n  octave::idx_vector index_vector (bool require_integers = false) const;\n\n  builtin_type_t builtin_type () const { return btyp_char; }\n\n  bool is_char_matrix () const { return true; }\n  bool is_real_matrix () const { return true; }\n\n  bool isreal () const { return true; }\n\n  double double_value (bool = false) const;\n\n  float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  float float_scalar_value (bool frc_str_conv = false) const\n  { return float_value (frc_str_conv); }\n\n  octave_int64 int64_scalar_value () const;\n  octave_uint64 uint64_scalar_value () const;\n\n  Matrix matrix_value (bool = false) const\n  { return Matrix (charMatrix (m_matrix)); }\n\n  FloatMatrix float_matrix_value (bool = false) const\n  { return FloatMatrix (charMatrix (m_matrix)); }\n\n  NDArray array_value (bool = false) const\n  { return NDArray (m_matrix); }\n\n  FloatNDArray float_array_value (bool = false) const\n  { return FloatNDArray (m_matrix); }\n\n  Complex complex_value (bool = false) const;\n\n  FloatComplex float_complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const\n  { return ComplexMatrix (charMatrix (m_matrix)); }\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const\n  { return FloatComplexMatrix (charMatrix (m_matrix)); }\n\n  ComplexNDArray complex_array_value (bool = false) const\n  { return ComplexNDArray (m_matrix); }\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const\n  { return FloatComplexNDArray (m_matrix); }\n\n  charMatrix char_matrix_value (bool = false) const\n  { return charMatrix (m_matrix); }\n\n  charNDArray char_array_value (bool = false) const\n  { return m_matrix; }\n\n  octave_value convert_to_str_internal (bool, bool, char type) const\n  { return octave_value (m_matrix, type); }\n\n  octave_value all (int dim = 0) const { return m_matrix.all (dim); }\n  octave_value any (int dim = 0) const { return m_matrix.any (dim); }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-class.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <memory>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"byte-swap.h\"\n#include \"mappers.h\"\n#include \"oct-locbuf.h\"\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"file-ops.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-oct-binary.h\"\n#include \"ls-utils.h\"\n#include \"mxarray.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ov-class.h\"\n#include \"ov-fcn.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"pr-output.h\"\n#include \"unwind-prot.h\"\n#include \"variables.h\"\n\n\nint octave_class::s_t_id (-1);\n\nconst std::string octave_class::s_t_name (\"class\");\n\nvoid\noctave_class::register_type (octave::type_info& ti)\n{\n  s_t_id = ti.register_type (octave_class::s_t_name, \"<unknown>\",\n                             octave_value (new octave_class ()));\n}\n\noctave_class::octave_class (const octave_map& m, const std::string& id,\n                            const octave_value_list& parents)\n  : octave_base_value (), m_map (m), m_c_name (id), m_obsolete_copies (0)\n{\n  octave_idx_type n = parents.length ();\n\n  for (octave_idx_type idx = 0; idx < n; idx++)\n    {\n      octave_value parent = parents(idx);\n\n      if (! parent.isobject ())\n        error (\"parents must be objects\");\n\n      std::string pcnm = parent.class_name ();\n\n      if (find_parent_class (pcnm))\n        error (\"duplicate class in parent tree\");\n\n      m_parent_list.push_back (pcnm);\n\n      octave_idx_type nel = m_map.numel ();\n      octave_idx_type p_nel = parent.numel ();\n\n      if (nel == 0)\n        {\n          if (p_nel == 0)\n            {\n              // No elements in MAP or the parent class object,\n              // so just add the field name.\n\n              m_map.assign (pcnm, Cell (m_map.dims ()));\n            }\n          else if (p_nel == 1)\n            {\n              if (m_map.nfields () == 0)\n                {\n                  // No elements or fields in MAP, but the\n                  // parent is class object with one element.\n                  // Resize to match size of parent class and\n                  // make the parent a field in MAP.\n\n                  m_map.resize (parent.dims ());\n\n                  m_map.assign (pcnm, parent);\n                }\n              else\n                {\n                  // No elements in MAP, but we have at least\n                  // one field.  So don't resize, just add the\n                  // field name.\n\n                  m_map.assign (pcnm, Cell (m_map.dims ()));\n                }\n            }\n          else if (m_map.nfields () == 0)\n            {\n              // No elements or fields in MAP and more than one\n              // element in the parent class object, so we can\n              // resize MAP to match parent dimsenions, then\n              // distribute the elements of the parent object to\n              // the elements of MAP.\n\n              const dim_vector& parent_dims = parent.dims ();\n\n              m_map.resize (parent_dims);\n\n              Cell c (parent_dims);\n\n              octave_map pmap = parent.map_value ();\n\n              std::list<std::string> plist\n                = parent.parent_class_name_list ();\n\n              for (octave_idx_type i = 0; i < p_nel; i++)\n                c(i) = octave_value (pmap.index (i), pcnm, plist);\n\n              m_map.assign (pcnm, c);\n            }\n          else\n            error (\"class: parent class dimension mismatch\");\n        }\n      else if (nel == 1 && p_nel == 1)\n        {\n          // Simple assignment.\n\n          m_map.assign (pcnm, parent);\n        }\n      else\n        {\n          if (p_nel == 1)\n            {\n              // Broadcast the scalar parent class object to\n              // each element of MAP.\n\n              Cell pcell (m_map.dims (), parent);\n\n              m_map.assign (pcnm, pcell);\n            }\n          else if (nel == p_nel)\n            {\n              // FIXME: is there a better way to do this?\n\n              // The parent class object has the same number of\n              // elements as the map we are using to create the\n              // new object, so distribute those elements to\n              // each element of the new object by first\n              // splitting the elements of the parent class\n              // object into a cell array with one element per\n              // cell.  Then do the assignment all at once.\n\n              Cell c (parent.dims ());\n\n              octave_map pmap = parent.map_value ();\n\n              std::list<std::string> plist\n                = parent.parent_class_name_list ();\n\n              for (octave_idx_type i = 0; i < p_nel; i++)\n                c(i) = octave_value (pmap.index (i), pcnm, plist);\n\n              m_map.assign (pcnm, c);\n            }\n          else\n            error (\"class: parent class dimension mismatch\");\n        }\n    }\n\n  octave::symbol_table& symtab = octave::__get_symbol_table__ ();\n\n  symtab.add_to_parent_map (id, m_parent_list);\n}\n\noctave_base_value *\noctave_class::unique_clone ()\n{\n  if (m_count == m_obsolete_copies)\n    {\n      // All remaining copies are obsolete.  We don't actually need to clone.\n      m_count++;\n      return this;\n    }\n  else\n    {\n      // In theory, this shouldn't be happening, but it's here just in case.\n      if (m_count < m_obsolete_copies)\n        m_obsolete_copies = 0;\n\n      return clone ();\n    }\n}\n\nstd::string\noctave_class::get_current_method_class ()\n{\n  std::string retval = class_name ();\n\n  if (nparents () > 0)\n    {\n      octave::tree_evaluator& tw = octave::__get_evaluator__ ();\n\n      octave_function *fcn = tw.current_function ();\n\n      // Here we are just looking to see if FCN is a method or constructor\n      // for any class, not specifically this one.\n      if (fcn && (fcn->is_class_method () || fcn->is_class_constructor ()))\n        retval = fcn->dispatch_class ();\n    }\n\n  return retval;\n}\n\nOCTAVE_NORETURN static\nvoid\nerr_invalid_index1 ()\n{\n  error (\"invalid index for class\");\n}\n\nOCTAVE_NORETURN static\nvoid\nerr_invalid_index_for_assignment ()\n{\n  error (\"invalid index for class assignment\");\n}\n\nOCTAVE_NORETURN static\nvoid\nerr_invalid_index_type (const std::string& nm, char t)\n{\n  error (\"%s cannot be indexed with %c\", nm.c_str (), t);\n}\n\nvoid\noctave_class::break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame)\n{\n  for (octave_idx_type j = 0; j < m_map.nfields (); j++)\n    {\n      Cell& c = m_map.contents (j);\n\n      for (octave_idx_type i = 0; i < c.numel (); i++)\n        c(i).break_closure_cycles (frame);\n    }\n}\n\nCell\noctave_class::dotref (const octave_value_list& idx)\n{\n  panic_if (idx.length () != 1);\n\n  std::string method_class = get_current_method_class ();\n\n  // Find the class in which this method resides before attempting to access\n  // the requested field.\n\n  octave_base_value *obvp = find_parent_class (method_class);\n\n  if (obvp == nullptr)\n    error (\"malformed class\");\n\n  octave_map my_map = (obvp != this) ? obvp->map_value () : m_map;\n\n  std::string nm = idx(0).xstring_value (\"invalid index for class\");\n\n  octave_map::const_iterator p = my_map.seek (nm);\n\n  if (p == my_map.end ())\n    error (\"class has no member '%s'\", nm.c_str ());\n\n  return my_map.contents (p);\n}\n\nMatrix\noctave_class::size ()\n{\n  if (in_class_method () || called_from_builtin ())\n    return octave_base_value::size ();\n\n  Matrix retval (1, 2, 1.0);\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value meth = symtab.find_method (\"size\", class_name ());\n\n  if (meth.is_defined ())\n    {\n      m_count++;\n      octave_value_list args (1, octave_value (this));\n\n      octave_value_list lv = interp.feval (meth.function_value (), args, 1);\n      if (lv.length () <= 0\n          || ! lv(0).is_matrix_type () || ! lv(0).dims ().isvector ())\n        error (\"@%s/size: invalid return value\", class_name ().c_str ());\n\n      retval = lv(0).matrix_value ();\n    }\n  else\n    {\n      const dim_vector& dv = dims ();\n\n      int nd = dv.ndims ();\n\n      retval.resize (1, nd);\n\n      for (int i = 0; i < nd; i++)\n        retval(i) = dv(i);\n    }\n\n  return retval;\n}\n\noctave_idx_type\noctave_class::xnumel (const octave_value_list& idx)\n{\n  if (in_class_method () || called_from_builtin ())\n    return octave_base_value::xnumel (idx);\n\n  octave_idx_type retval = -1;\n  const std::string cn = class_name ();\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value meth = symtab.find_method (\"numel\", cn);\n\n  if (meth.is_defined ())\n    {\n      octave_value_list args (idx.length () + 1, octave_value ());\n\n      m_count++;\n      args(0) = octave_value (this);\n\n      for (octave_idx_type i = 0; i < idx.length (); i++)\n        args(i+1) = idx(i);\n\n      octave_value_list lv = interp.feval (meth.function_value (), args, 1);\n      if (lv.length () != 1 || ! lv(0).is_scalar_type ())\n        error (\"@%s/numel: invalid return value\", cn.c_str ());\n\n      retval = lv(0).idx_type_value (true);\n    }\n  else\n    retval = octave_base_value::xnumel (idx);\n\n  return retval;\n}\n\noctave_value_list\noctave_class::subsref (const std::string& type,\n                       const std::list<octave_value_list>& idx,\n                       int nargout)\n{\n  octave_value_list retval;\n\n  if (in_class_method () || called_from_builtin ())\n    {\n      // FIXME: this block of code is the same as the body of\n      // octave_struct::subsref.  Maybe it could be shared instead of\n      // duplicated.\n\n      int skip = 1;\n\n      switch (type[0])\n        {\n        case '(':\n          {\n            if (type.length () > 1 && type[1] == '.')\n              {\n                const octave_value_list& key_idx = *std::next (idx.begin ());\n\n                Cell tmp = dotref (key_idx);\n\n                Cell t = tmp.index (idx.front ());\n\n                retval(0) = (t.numel () == 1 ? t(0)\n                             : octave_value (t, true));\n\n                // We handled two index elements, so tell\n                // next_subsref to skip both of them.\n                skip++;\n              }\n            else\n              retval(0) = octave_value (m_map.index (idx.front ()),\n                                        m_c_name, m_parent_list);\n          }\n          break;\n\n        case '.':\n          {\n            if (m_map.numel () > 0)\n              {\n                Cell t = dotref (idx.front ());\n\n                retval(0) = (t.numel () == 1) ? t(0) : octave_value (t, true);\n              }\n          }\n          break;\n\n        case '{':\n          err_invalid_index_type (type_name (), type[0]);\n          break;\n\n        default:\n          error (\"unpexpected: index not '(', '{', or '.' in - octave_class::subsref please report this bug\");\n        }\n\n      // FIXME: perhaps there should be an\n      // octave_value_list::next_subsref member function?  See also\n      // octave_user_function::subsref.\n\n      if (idx.size () > 1)\n        retval = retval(0).next_subsref (nargout, type, idx, skip);\n    }\n  else\n    {\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      octave::symbol_table& symtab = interp.get_symbol_table ();\n\n      octave_value meth = symtab.find_method (\"subsref\", class_name ());\n\n      if (meth.is_defined ())\n        {\n          octave_value_list args;\n\n          args(1) = make_idx_args (type, idx, \"subsref\");\n\n          m_count++;\n          args(0) = octave_value (this);\n\n          octave_value meth_nargout\n            = symtab.find_method (\"numArgumentsFromSubscript\", class_name ());\n          if (meth_nargout.is_defined ())\n            {\n              octave_value_list args_nargout (3);\n\n              args_nargout(0) = args(0);\n              args_nargout(1) = args(1);\n              // FIXME: Third argument should be one of the possible values of\n              //        the matlab.mixin.util.IndexingContext enumeration class.\n              args_nargout(2) = octave_value (Matrix ());\n              retval = interp.feval (meth_nargout.function_value (),\n                                     args_nargout, 1);\n\n              nargout = retval(0).strict_int_value\n                (\"subsref: return value of 'numArgumentsFromSubscript' must be integer\");\n            }\n          else if (nargout <= 0)\n            {\n              // If the number of output arguments is unknown, attempt to set up\n              // a proper value for nargout at least in the simple case where the\n              // cs-list-type expression - i.e., {} or ().x, is the leading one.\n              bool maybe_cs_list_query = (type[0] == '.' || type[0] == '{'\n                                          || (type.length () > 1 && type[0] == '('\n                                              && type[1] == '.'));\n\n              if (maybe_cs_list_query)\n                {\n                  // Set up a proper nargout for the subsref call by calling numel.\n                  octave_value_list tmp;\n                  int nout;\n                  if (type[0] != '.')\n                    tmp = idx.front ();\n\n                  nout = xnumel (tmp);\n                  // Take nout as nargout for subsref, unless the index expression\n                  // is a whole sentence starting with the form id.member and id is\n                  // one element (in that case, nargout remains 0).\n                  if (type[0] != '.' || nout != 1 || nargout < 0)\n                    nargout = nout;\n                }\n              else if (nargout < 0)\n                nargout = 1;\n            }\n\n          retval = interp.feval (meth.function_value (), args, nargout);\n\n          // Since we're handling subsref, if the list has more than one element\n          // and the caller to subsref accepts more that one output, return\n          // the elements as a comma-separated list so that we can pass it to the\n          // evaluator\n          if (retval.length () > 1 && (nargout < 0 || nargout > 1))\n            {\n              if (nargout <= 0 || nargout >= retval.length ())\n                // Take the whole list\n                retval = octave_value (retval);\n              else\n                // Take nargout elements of the list\n                retval = octave_value (retval.slice (0, nargout));\n            }\n        }\n      else\n        {\n          if (type.length () == 1 && type[0] == '(')\n            retval(0) = octave_value (m_map.index (idx.front ()), m_c_name,\n                                      m_parent_list);\n          else\n            err_invalid_index1 ();\n        }\n    }\n\n  return retval;\n}\n\noctave_value\noctave_class::numeric_conv (const Cell& val, const std::string& type)\n{\n  octave_value retval;\n\n  if (val.numel () != 1)\n    err_invalid_index_for_assignment ();\n\n  retval = val(0);\n\n  if (type.length () > 0 && type[0] == '.' && ! retval.isstruct ())\n    retval = octave_map ();\n\n  return retval;\n}\n\noctave_value\noctave_class::subsasgn (const std::string& type,\n                        const std::list<octave_value_list>& idx,\n                        const octave_value& rhs)\n{\n  m_count++;\n  return subsasgn_common (octave_value (this), type, idx, rhs);\n}\n\noctave_value\noctave_class::undef_subsasgn (const std::string& type,\n                              const std::list<octave_value_list>& idx,\n                              const octave_value& rhs)\n{\n  // For compatibility with Matlab, pass [] as the first argument to the\n  // the subsasgn function when the LHS of an indexed assignment is\n  // undefined.\n\n  return subsasgn_common (Matrix (), type, idx, rhs);\n}\n\noctave_value\noctave_class::subsasgn_common (const octave_value& obj,\n                               const std::string& type,\n                               const std::list<octave_value_list>& idx,\n                               const octave_value& rhs)\n{\n  octave_value retval;\n\n  if (! (in_class_method () || called_from_builtin ()))\n    {\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      octave::symbol_table& symtab = interp.get_symbol_table ();\n\n      octave_value meth = symtab.find_method (\"subsasgn\", class_name ());\n\n      if (meth.is_defined ())\n        {\n          octave_value_list args;\n\n          if (rhs.is_cs_list ())\n            {\n              octave_value_list lrhs = rhs.list_value ();\n              args.resize (2 + lrhs.length ());\n              for (octave_idx_type i = 0; i < lrhs.length (); i++)\n                args(2+i) = lrhs(i);\n            }\n          else\n            args(2) = rhs;\n\n          args(1) = make_idx_args (type, idx, \"subsasgn\");\n          args(0) = obj;\n\n          // Now comes the magic.  Count copies with me:\n          // 1. myself (obsolete)\n          // 2. the copy inside args (obsolete)\n          // 3. the copy in method's symbol table (working)\n          // ... possibly more (not obsolete).\n          //\n          // So we mark 2 copies as obsolete and hold our fingers crossed.\n          // But prior to doing that, check whether the routine is amenable\n          // to the optimization.\n          // It is essential that the handling function doesn't store extra\n          // copies anywhere.  If it does, things will not break but the\n          // optimization won't work.\n\n          octave_value_list tmp;\n\n          if (m_obsolete_copies == 0 && meth.is_user_function ()\n              && meth.user_function_value ()->subsasgn_optimization_ok ())\n            {\n              octave::unwind_protect_var<int> restore_var (m_obsolete_copies);\n              m_obsolete_copies = 2;\n\n              tmp = interp.feval (meth.function_value (), args);\n            }\n          else\n            tmp = interp.feval (meth.function_value (), args);\n\n          // FIXME: Should the subsasgn method be able to return\n          //        more than one value?\n\n          if (tmp.length () > 1)\n            error (\"@%s/subsasgn returned more than one value\",\n                   class_name ().c_str ());\n\n          else\n            retval = tmp(0);\n\n          return retval;\n        }\n    }\n\n  // Find the class in which this method resides before\n  // attempting to do the indexed assignment.\n\n  std::string method_class = get_current_method_class ();\n\n  octave_base_value *obvp = unique_parent_class (method_class);\n  if (obvp != this)\n    {\n\n      if (! obvp)\n        error (\"malformed class\");\n\n      obvp->subsasgn (type, idx, rhs);\n\n      m_count++;\n      retval = octave_value (this);\n\n      return retval;\n    }\n\n  // FIXME: this block of code is the same as the body of\n  // octave_struct::subsasgn.  Maybe it could be shared instead of\n  // duplicated.\n\n  int n = type.length ();\n\n  octave_value t_rhs = rhs;\n\n  if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))\n    {\n      switch (type[0])\n        {\n        case '(':\n          {\n            if (type.length () > 1 && type[1] == '.')\n              {\n                const octave_value_list& key_idx = *std::next (idx.begin ());\n\n                panic_if (key_idx.length () != 1);\n\n                std::string key = key_idx(0).xstring_value (\"invalid index for class assignment\");\n\n                octave_value u;\n\n                if (! m_map.contains (key))\n                  u = octave_value::empty_conv (type.substr (2), rhs);\n                else\n                  {\n                    Cell map_val = m_map.contents (key);\n\n                    Cell map_elt = map_val.index (idx.front (), true);\n\n                    u = numeric_conv (map_elt, type.substr (2));\n                  }\n\n                std::list<octave_value_list> next_idx (std::next (idx.begin (), 2),\n                                                       idx.end ());\n\n                // We handled two index elements, so subsasgn to\n                // needs to skip both of them.\n\n                u.make_unique ();\n\n                t_rhs = u.subsasgn (type.substr (2), next_idx, rhs);\n              }\n            else\n              err_invalid_index_for_assignment ();\n          }\n          break;\n\n        case '.':\n          {\n            const octave_value_list& key_idx = idx.front ();\n\n            panic_if (key_idx.length () != 1);\n\n            std::string key = key_idx(0).string_value ();\n\n            std::list<octave_value_list> next_idx (std::next (idx.begin ()),\n                                                   idx.end ());\n\n            std::string next_type = type.substr (1);\n\n            Cell tmpc (1, 1);\n            auto pkey = m_map.seek (key);\n            if (pkey != m_map.end ())\n              {\n                m_map.contents (pkey).make_unique ();\n                tmpc = m_map.contents (pkey);\n              }\n\n            // FIXME: better code reuse?\n            if (tmpc.numel () != 1)\n              err_indexed_cs_list ();\n\n            octave_value& tmp = tmpc(0);\n\n            if (! tmp.is_defined () || tmp.is_zero_by_zero ())\n              {\n                tmp = octave_value::empty_conv (next_type, rhs);\n                tmp.make_unique (); // probably a no-op.\n              }\n            else\n              // optimization: ignore copy still stored inside our map.\n              tmp.make_unique (1);\n\n            t_rhs = tmp.subsasgn (next_type, next_idx, rhs);\n          }\n          break;\n\n        case '{':\n          err_invalid_index_type (type_name (), type[0]);\n          break;\n\n        default:\n          error (\"unpexpected: index not '(', '{', or '.' in - octave_class::subsasgn_common please report this bug\");\n        }\n    }\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        if (n > 1 && type[1] == '.')\n          {\n            const octave_value_list& key_idx = *std::next (idx.begin ());\n\n            panic_if (key_idx.length () != 1);\n\n            std::string key = key_idx(0).xstring_value (\"assignment to class element failed\");\n\n            m_map.assign (idx.front (), key, t_rhs);\n\n            m_count++;\n            retval = octave_value (this);\n          }\n        else\n          {\n            if (t_rhs.isobject () || t_rhs.isstruct ())\n              {\n                octave_map rhs_map = t_rhs.xmap_value (\"invalid class assignment\");\n\n                m_map.assign (idx.front (), rhs_map);\n\n                m_count++;\n                retval = octave_value (this);\n              }\n            else\n              {\n                if (! t_rhs.isempty ())\n                  error (\"invalid class assignment\");\n\n                m_map.delete_elements (idx.front ());\n\n                m_count++;\n                retval = octave_value (this);\n              }\n          }\n      }\n      break;\n\n    case '.':\n      {\n        const octave_value_list& key_idx = idx.front ();\n\n        panic_if (key_idx.length () != 1);\n\n        std::string key = key_idx(0).string_value ();\n\n        if (t_rhs.is_cs_list ())\n          {\n            Cell tmp_cell = Cell (t_rhs.list_value ());\n\n            // The shape of the RHS is irrelevant, we just want\n            // the number of elements to agree and to preserve the\n            // shape of the left hand side of the assignment.\n\n            if (numel () == tmp_cell.numel ())\n              tmp_cell = tmp_cell.reshape (dims ());\n\n            m_map.setfield (key, tmp_cell);\n          }\n        else\n          {\n            Cell tmp_cell(1, 1);\n            tmp_cell(0) = t_rhs.storable_value ();\n            m_map.setfield (key, tmp_cell);\n          }\n\n        m_count++;\n        retval = octave_value (this);\n      }\n      break;\n\n    case '{':\n      err_invalid_index_type (type_name (), type[0]);\n      break;\n\n    default:\n      error (\"unpexpected: index not '(', '{', or '.' in - octave_class::subsref please report this bug\");\n    }\n\n  return retval;\n}\n\noctave::idx_vector\noctave_class::index_vector (bool require_integers) const\n{\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value meth = symtab.find_method (\"subsindex\", class_name ());\n\n  if (! meth.is_defined ())\n    error (\"no subsindex method defined for class %s\",\n           class_name ().c_str ());\n\n  octave_value_list args;\n  args(0) = octave_value (new octave_class (m_map, m_c_name, m_parent_list));\n\n  octave_value_list tmp = interp.feval (meth.function_value (), args, 1);\n\n  if (tmp(0).isobject ())\n    error (\"subsindex function must return a valid index vector\");\n\n  // Index vector returned by subsindex is zero based\n  // (why this inconsistency Mathworks?), and so we must\n  // add one to the value returned as the index_vector method\n  // expects it to be one based.\n  return octave::binary_op (octave_value::op_add, tmp (0),\n                            octave_value (1.0)).index_vector (require_integers);\n}\n\nstd::size_t\noctave_class::byte_size () const\n{\n  // Neglect the size of the fieldnames.\n\n  std::size_t retval = 0;\n\n  for (auto it = m_map.cbegin (); it != m_map.cend (); it++)\n    {\n      std::string key = m_map.key (it);\n\n      octave_value val = octave_value (m_map.contents (it));\n\n      retval += val.byte_size ();\n    }\n\n  return retval;\n}\n\nbool\noctave_class::is_true () const\n{\n  bool retval = false;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value meth = symtab.find_method (\"logical\", class_name ());\n\n  if (meth.is_defined ())\n    {\n      octave_value in = new octave_class (*this);\n\n      octave_value_list tmp = interp.feval (meth.function_value (), in, 1);\n      retval = tmp(0).is_true ();\n    }\n\n  return retval;\n}\n\nstring_vector\noctave_class::map_keys () const\n{\n  err_wrong_type_arg (\"octave_class::map_keys()\", type_name ());\n}\n\noctave_base_value *\noctave_class::find_parent_class (const std::string& parent_class_name)\n{\n  octave_base_value *retval = nullptr;\n\n  if (parent_class_name == class_name ())\n    retval = this;\n  else\n    {\n      for (auto& par : m_parent_list)\n        {\n          octave_map::const_iterator smap = m_map.seek (par);\n\n          const Cell& tmp = m_map.contents (smap);\n\n          octave_value vtmp = tmp(0);\n\n          octave_base_value *obvp = vtmp.internal_rep ();\n\n          retval = obvp->find_parent_class (parent_class_name);\n\n          if (retval)\n            break;\n        }\n    }\n\n  return retval;\n}\n\noctave_base_value *\noctave_class::unique_parent_class (const std::string& parent_class_name)\n{\n  octave_base_value *retval = nullptr;\n\n  if (parent_class_name == class_name ())\n    retval = this;\n  else\n    {\n      for (auto& par : m_parent_list)\n        {\n          auto smap = m_map.seek (par);\n\n          Cell& tmp = m_map.contents (smap);\n\n          octave_value& vtmp = tmp(0);\n\n          octave_base_value *obvp = vtmp.internal_rep ();\n\n          // Use find_parent_class first to avoid uniquifying if not necessary.\n          retval = obvp->find_parent_class (parent_class_name);\n\n          if (retval)\n            {\n              vtmp.make_unique ();\n              obvp = vtmp.internal_rep ();\n              retval = obvp->unique_parent_class (parent_class_name);\n\n              break;\n            }\n        }\n    }\n\n  return retval;\n}\n\nbool\noctave_class::is_instance_of (const std::string& cls_name) const\n{\n  bool retval = false;\n\n  if (cls_name == class_name ())\n    retval = true;\n  else\n    {\n      for (auto& par : m_parent_list)\n        {\n          octave_map::const_iterator smap = m_map.seek (par);\n\n          const Cell& tmp = m_map.contents (smap);\n\n          const octave_value& vtmp = tmp(0);\n\n          retval = vtmp.is_instance_of (cls_name);\n\n          if (retval)\n            break;\n        }\n    }\n\n  return retval;\n}\n\nstring_vector\noctave_class::string_vector_value (bool pad) const\n{\n  string_vector retval;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value meth = symtab.find_method (\"char\", class_name ());\n\n  if (! meth.is_defined ())\n    error (\"no char method defined for class %s\", class_name ().c_str ());\n\n  octave_value_list args;\n  args(0) = octave_value (new octave_class (m_map, m_c_name, m_parent_list));\n\n  octave_value_list tmp = interp.feval (meth.function_value (), args, 1);\n\n  if (tmp.length () >= 1)\n    {\n      if (! tmp(0).is_string ())\n        error (\"cname/char method did not return a string\");\n\n      retval = tmp(0).string_vector_value (pad);\n    }\n\n  return retval;\n}\n\nvoid\noctave_class::print (std::ostream& os, bool)\n{\n  print_raw (os);\n}\n\nvoid\noctave_class::print_raw (std::ostream& os, bool) const\n{\n  indent (os);\n  os << \"  <class \" << class_name () << '>';\n  newline (os);\n}\n\n// Loading a class properly requires an exemplar map entry for success.\n// If we don't have one, we attempt to create one by calling the constructor\n// with no arguments.\nbool\noctave_class::reconstruct_exemplar ()\n{\n  bool retval = false;\n\n  octave_class::exemplar_const_iterator it\n    = octave_class::exemplar_map.find (m_c_name);\n\n  if (it != octave_class::exemplar_map.end ())\n    retval = true;\n  else\n    {\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      octave::symbol_table& symtab = interp.get_symbol_table ();\n\n      octave_value ctor = symtab.find_method (m_c_name, m_c_name);\n\n      bool have_ctor = false;\n\n      if (ctor.is_defined () && ctor.is_function ())\n        {\n          octave_function *fcn = ctor.function_value ();\n\n          if (fcn && fcn->is_class_constructor (m_c_name))\n            have_ctor = true;\n\n          // Something has gone terribly wrong if\n          // symbol_table::find_method (c_name, c_name) does not return\n          // a class constructor for the class c_name...\n          panic_unless (have_ctor);\n        }\n\n      if (have_ctor)\n        {\n          octave::unwind_protect frame;\n\n          // Simulate try/catch.\n\n          octave::interpreter_try (frame);\n\n          bool execution_error = false;\n\n          octave_value_list result;\n\n          try\n            {\n              result = interp.feval (ctor, ovl (), 1);\n            }\n          catch (const octave::execution_exception&)\n            {\n              interp.recover_from_exception ();\n\n              execution_error = true;\n            }\n\n          if (! execution_error && result.length () == 1)\n            retval = true;\n        }\n      else\n        warning (\"no constructor for class %s\", m_c_name.c_str ());\n    }\n\n  return retval;\n}\n\nvoid\noctave_class::clear_exemplar_map ()\n{\n  exemplar_map.clear ();\n}\n\n//  Load/save does not provide enough information to reconstruct the\n//  class inheritance structure.  reconstruct_parents () attempts to\n//  do so.  If successful, a \"true\" value is returned.\n//\n//  Note that we don't check the loaded object structure against the\n//  class structure here so the user's loadobj method has a chance\n//  to do its magic.\nbool\noctave_class::reconstruct_parents ()\n{\n  bool retval = true;\n  bool might_have_inheritance = false;\n  std::string dbgstr = \"dork\";\n\n  // First, check to see if there might be an issue with inheritance.\n  for (auto it = m_map.cbegin (); it != m_map.cend (); it++)\n    {\n      std::string key = m_map.key (it);\n      Cell        val = m_map.contents (it);\n      if (val(0).isobject ())\n        {\n          dbgstr = \"blork\";\n          if (key == val(0).class_name ())\n            {\n              might_have_inheritance = true;\n              dbgstr = \"cork\";\n              break;\n            }\n        }\n    }\n\n  if (might_have_inheritance)\n    {\n      octave_class::exemplar_const_iterator it\n        = octave_class::exemplar_map.find (m_c_name);\n\n      if (it == octave_class::exemplar_map.end ())\n        retval = false;\n      else\n        {\n          octave_class::exemplar_info exmplr = it->second;\n          m_parent_list = exmplr.parents ();\n          for (auto& par : m_parent_list)\n            {\n              dbgstr = par;\n              bool dbgbool = m_map.contains (par);\n              if (! dbgbool)\n                {\n                  retval = false;\n                  break;\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\nbool\noctave_class::save_ascii (std::ostream& os)\n{\n  os << \"# classname: \" << class_name () << \"\\n\";\n  octave_map m;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::load_path& lp = interp.get_load_path ();\n\n  if (lp.find_method (class_name (), \"saveobj\") != \"\")\n    {\n      octave_value in = new octave_class (*this);\n\n      octave_value_list tmp = interp.feval (\"saveobj\", in, 1);\n\n      m = tmp(0).map_value ();\n    }\n  else\n    m = map_value ();\n\n  os << \"# length: \" << m.nfields () << \"\\n\";\n\n  auto i = m.begin ();\n  while (i != m.end ())\n    {\n      octave_value val = m.contents (i);\n\n      bool b = save_text_data (os, val, m.key (i), false, 0);\n\n      if (! b)\n        return ! os.fail ();\n\n      i++;\n    }\n\n  return true;\n}\n\nbool\noctave_class::load_ascii (std::istream& is)\n{\n  octave_idx_type len = 0;\n  std::string classname;\n\n  if (! extract_keyword (is, \"classname\", classname) || classname.empty ())\n    error (\"load: failed to extract name of class\");\n\n  if (! extract_keyword (is, \"length\", len) || len < 0)\n    error (\"load: failed to extract number of elements in class\");\n\n  if (len > 0)\n    {\n      octave_map m (m_map);\n\n      for (octave_idx_type j = 0; j < len; j++)\n        {\n          octave_value t2;\n          bool dummy;\n\n          // recurse to read cell elements\n          std::string nm\n            = read_text_data (is, \"\", dummy, t2, j);\n\n          if (! is)\n            break;\n\n          Cell tcell = (t2.iscell () ? t2.xcell_value (\"load: internal error loading class elements\") : Cell (t2));\n\n          m.assign (nm, tcell);\n        }\n\n      if (! is)\n        error (\"load: failed to load class\");\n\n      m_c_name = classname;\n      reconstruct_exemplar ();\n\n      m_map = m;\n\n      if (! reconstruct_parents ())\n        warning (\"load: unable to reconstruct object inheritance\");\n\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      octave::load_path& lp = interp.get_load_path ();\n\n      if (lp.find_method (classname, \"loadobj\") != \"\")\n        {\n          octave_value in = new octave_class (*this);\n          octave_value_list tmp = interp.feval (\"loadobj\", in, 1);\n\n          m_map = tmp(0).map_value ();\n        }\n    }\n  else if (len == 0)\n    {\n      m_map = octave_map (dim_vector (1, 1));\n      m_c_name = classname;\n    }\n  else\n    error (\"unexpected: len < 0 in octave_class::load_ascii - please report this bug\");\n\n  return true;\n}\n\nbool\noctave_class::save_binary (std::ostream& os, bool save_as_floats)\n{\n  int32_t classname_len = class_name ().length ();\n\n  os.write (reinterpret_cast<char *> (&classname_len), 4);\n  os << class_name ();\n\n  octave_map m;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::load_path& lp = interp.get_load_path ();\n\n  if (lp.find_method (class_name (), \"saveobj\") != \"\")\n    {\n      octave_value in = new octave_class (*this);\n      octave_value_list tmp = interp.feval (\"saveobj\", in, 1);\n\n      m = tmp(0).map_value ();\n    }\n  else\n    m = map_value ();\n\n  int32_t len = m.nfields ();\n  os.write (reinterpret_cast<char *> (&len), 4);\n\n  auto i = m.begin ();\n  while (i != m.end ())\n    {\n      octave_value val = m.contents (i);\n\n      bool b = save_binary_data (os, val, m.key (i), \"\", 0, save_as_floats);\n\n      if (! b)\n        return ! os.fail ();\n\n      i++;\n    }\n\n  return true;\n}\n\nbool\noctave_class::load_binary (std::istream& is, bool swap,\n                           octave::mach_info::float_format fmt)\n{\n  bool success = true;\n\n  int32_t classname_len;\n\n  is.read (reinterpret_cast<char *> (&classname_len), 4);\n  if (! is)\n    return false;\n  else if (swap)\n    swap_bytes<4> (&classname_len);\n\n  {\n    OCTAVE_LOCAL_BUFFER (char, classname, classname_len+1);\n    classname[classname_len] = '\\0';\n    if (! is.read (reinterpret_cast<char *> (classname), classname_len))\n      return false;\n    m_c_name = classname;\n  }\n  reconstruct_exemplar ();\n\n  int32_t len;\n  if (! is.read (reinterpret_cast<char *> (&len), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&len);\n\n  if (len > 0)\n    {\n      octave_map m (m_map);\n\n      for (octave_idx_type j = 0; j < len; j++)\n        {\n          octave_value t2;\n          bool dummy;\n          std::string doc;\n\n          // recurse to read cell elements\n          std::string nm = read_binary_data (is, swap, fmt, \"\",\n                                             dummy, t2, doc);\n\n          if (! is)\n            break;\n\n          Cell tcell = (t2.iscell () ? t2.xcell_value (\"load: internal error loading class elements\") : Cell (t2));\n\n          m.assign (nm, tcell);\n        }\n\n      if (is)\n        {\n          m_map = m;\n\n          if (! reconstruct_parents ())\n            warning (\"load: unable to reconstruct object inheritance\");\n\n          octave::interpreter& interp = octave::__get_interpreter__ ();\n\n          octave::load_path& lp = interp.get_load_path ();\n\n          if (lp.find_method (m_c_name, \"loadobj\") != \"\")\n            {\n              octave_value in = new octave_class (*this);\n              octave_value_list tmp = interp.feval (\"loadobj\", in, 1);\n\n              m_map = tmp(0).map_value ();\n            }\n        }\n      else\n        {\n          warning (\"load: failed to load class\");\n          success = false;\n        }\n    }\n  else if (len == 0)\n    m_map = octave_map (dim_vector (1, 1));\n  else\n    error (\"unexpected: len < 0 in octave_class::load_binary - please report this bug\");\n\n  return success;\n}\n\nbool\noctave_class::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                         bool save_as_floats)\n{\n#if defined (HAVE_HDF5)\n\n  hsize_t hdims[3];\n  hid_t group_hid = -1;\n  hid_t type_hid = -1;\n  hid_t space_hid = -1;\n  hid_t class_hid = -1;\n  hid_t data_hid = -1;\n  octave_map m;\n  octave_map::iterator i;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::load_path& lp = interp.get_load_path ();\n\n#if defined (HAVE_HDF5_18)\n  group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                         octave_H5P_DEFAULT);\n#else\n  group_hid = H5Gcreate (loc_id, name, 0);\n#endif\n  if (group_hid < 0)\n    goto error_cleanup;\n\n  // Add the class name to the group\n  type_hid = H5Tcopy (H5T_C_S1);\n  H5Tset_size (type_hid, m_c_name.length () + 1);\n  if (type_hid < 0)\n    goto error_cleanup;\n\n  hdims[0] = 0;\n  space_hid = H5Screate_simple (0, hdims, nullptr);\n  if (space_hid < 0)\n    goto error_cleanup;\n#if defined (HAVE_HDF5_18)\n  class_hid = H5Dcreate (group_hid, \"classname\", type_hid, space_hid,\n                         octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                         octave_H5P_DEFAULT);\n#else\n  class_hid = H5Dcreate (group_hid, \"classname\", type_hid, space_hid,\n                         octave_H5P_DEFAULT);\n#endif\n  if (class_hid < 0 || H5Dwrite (class_hid, type_hid, octave_H5S_ALL,\n                                 octave_H5S_ALL, octave_H5P_DEFAULT,\n                                 m_c_name.c_str ()) < 0)\n    goto error_cleanup;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Gcreate (group_hid, \"value\", octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n#else\n  data_hid = H5Gcreate (group_hid, \"value\", 0);\n#endif\n  if (data_hid < 0)\n    goto error_cleanup;\n\n  if (lp.find_method (class_name (), \"saveobj\") != \"\")\n    {\n      octave_value in = new octave_class (*this);\n      octave_value_list tmp = interp.feval (\"saveobj\", in, 1);\n\n      m = tmp(0).map_value ();\n    }\n  else\n    m = map_value ();\n\n  // recursively add each element of the class to this group\n  i = m.begin ();\n  while (i != m.end ())\n    {\n      octave_value val = m.contents (i);\n\n      bool retval2 = add_hdf5_data (data_hid, val, m.key (i), \"\", false,\n                                    save_as_floats);\n\n      if (! retval2)\n        break;\n\n      i++;\n    }\n\nerror_cleanup:\n\n  if (data_hid > 0)\n    H5Gclose (data_hid);\n\n  if (class_hid > 0)\n    H5Dclose (class_hid);\n\n  if (space_hid > 0)\n    H5Sclose (space_hid);\n\n  if (type_hid > 0)\n    H5Tclose (type_hid);\n\n  if (group_hid > 0)\n    H5Gclose (group_hid);\n\n  return true;\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n\n  return false;\n#endif\n}\n\nbool\noctave_class::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hid_t group_hid = -1;\n  hid_t data_hid = -1;\n  hid_t type_hid = -1;\n  hid_t type_class_hid = -1;\n  hid_t space_hid = -1;\n  hid_t subgroup_hid = -1;\n  hid_t st_id = -1;\n\n  hdf5_callback_data dsub;\n\n  herr_t retval2 = 0;\n  octave_map m (dim_vector (1, 1));\n  int current_item = 0;\n  hsize_t num_obj = 0;\n  int slen = 0;\n  hsize_t rank = 0;\n\n#if defined (HAVE_HDF5_18)\n  group_hid = H5Gopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  group_hid = H5Gopen (loc_id, name);\n#endif\n  if (group_hid < 0)\n    goto error_cleanup;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"classname\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"classname\");\n#endif\n\n  if (data_hid < 0)\n    goto error_cleanup;\n\n  type_hid = H5Dget_type (data_hid);\n\n  type_class_hid = H5Tget_class (type_hid);\n\n  if (type_class_hid != H5T_STRING)\n    goto error_cleanup;\n\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    goto error_cleanup;\n\n  slen = H5Tget_size (type_hid);\n  if (slen < 0)\n    goto error_cleanup;\n\n  // do-while loop here to prevent goto crossing initialization of classname\n  do\n    {\n      OCTAVE_LOCAL_BUFFER (char, classname, slen);\n\n      // create datatype for (null-terminated) string to read into:\n      st_id = H5Tcopy (H5T_C_S1);\n      H5Tset_size (st_id, slen);\n\n      if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL,\n                   octave_H5P_DEFAULT, classname)\n          < 0)\n        {\n          H5Tclose (st_id);\n          H5Dclose (data_hid);\n          H5Gclose (group_hid);\n          return false;\n        }\n\n      H5Tclose (st_id);\n      H5Dclose (data_hid);\n      data_hid = -1;\n\n      m_c_name = classname;\n    }\n  while (0);\n  reconstruct_exemplar ();\n\n#if defined (HAVE_HDF5_18)\n  subgroup_hid = H5Gopen (group_hid, name, octave_H5P_DEFAULT);\n#else\n  subgroup_hid = H5Gopen (group_hid, name);\n#endif\n  H5Gget_num_objs (subgroup_hid, &num_obj);\n  H5Gclose (subgroup_hid);\n\n  while (current_item < static_cast<int> (num_obj)\n         && (retval2 = hdf5_h5g_iterate (group_hid, name, &current_item,\n                                         &dsub)) > 0)\n    {\n      octave_value t2 = dsub.tc;\n\n      Cell tcell = (t2.iscell () ? t2.xcell_value (\"load: internal error loading class elements\") : Cell (t2));\n\n      m.assign (dsub.name, tcell);\n\n    }\n\n  if (retval2 >= 0)\n    {\n      m_map = m;\n\n      if (! reconstruct_parents ())\n        warning (\"load: unable to reconstruct object inheritance\");\n\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      octave::load_path& lp = interp.get_load_path ();\n\n      if (lp.find_method (m_c_name, \"loadobj\") != \"\")\n        {\n          octave_value in = new octave_class (*this);\n          octave_value_list tmp = interp.feval (\"loadobj\", in, 1);\n\n          m_map = tmp(0).map_value ();\n          retval = true;\n        }\n    }\n\nerror_cleanup:\n  if (data_hid > 0)\n    H5Dclose (data_hid);\n\n  if (data_hid > 0)\n    H5Gclose (group_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nmxArray *\noctave_class::as_mxArray (bool) const\n{\n  err_wrong_type_arg (\"octave_class::as_mxArray ()\", type_name ());\n}\n\nbool\noctave_class::in_class_method ()\n{\n  octave::tree_evaluator& tw = octave::__get_evaluator__ ();\n\n  octave_function *fcn = tw.current_function ();\n\n  return (fcn\n          && (fcn->is_class_method ()\n              || fcn->is_class_constructor ()\n              || fcn->is_anonymous_function_of_class ()\n              || fcn->is_private_function_of_class (class_name ()))\n          && find_parent_class (fcn->dispatch_class ()));\n}\n\noctave_class::exemplar_info::exemplar_info (const octave_value& obj)\n  : m_field_names (), m_parent_class_names ()\n{\n  if (! obj.isobject ())\n    error (\"invalid call to exemplar_info constructor\");\n\n  octave_map m = obj.map_value ();\n  m_field_names = m.keys ();\n\n  m_parent_class_names = obj.parent_class_name_list ();\n}\n\n// A map from class names to lists of fields.\nstd::map<std::string, octave_class::exemplar_info> octave_class::exemplar_map;\n\nbool\noctave_class::exemplar_info::compare (const octave_value& obj) const\n{\n\n  if (! obj.isobject ())\n    error (\"invalid comparison of class exemplar to non-class object\");\n\n  if (nfields () != obj.nfields ())\n    error (\"mismatch in number of fields\");\n\n  octave_map obj_map = obj.map_value ();\n  string_vector obj_fnames = obj_map.keys ();\n  string_vector fnames = fields ();\n\n  for (octave_idx_type i = 0; i < nfields (); i++)\n    {\n      if (obj_fnames[i] != fnames[i])\n        error (\"mismatch in field names\");\n    }\n\n  if (nparents () != obj.nparents ())\n    error (\"mismatch in number of parent classes\");\n\n  const std::list<std::string> obj_parents\n    = obj.parent_class_name_list ();\n  const std::list<std::string> pnames = parents ();\n\n  auto p = obj_parents.begin ();\n  auto q = pnames.begin ();\n\n  while (p != obj_parents.end ())\n    {\n      if (*p++ != *q++)\n        error (\"mismatch in parent classes\");\n    }\n\n  return true;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFMETHOD (class, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{classname} =} class (@var{obj})\n@deftypefnx {} {@var{cls} =} class (@var{s}, @var{classname})\n@deftypefnx {} {@var{cls} =} class (@var{s}, @var{classname}, @var{parent1}, @dots{})\nReturn the class of the object @var{obj}, or create a class with fields from\nstructure @var{s} and name (string) @var{classname}.\n\nAdditional arguments name a list of parent classes from which the new class is\nderived.\n@seealso{typeinfo, isa}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 1)\n    // Called for class of object\n    retval = args(0).class_name ();\n  else\n    {\n      // Called as class constructor\n      std::string id = args(1).xstring_value (\"class: ID (class name) must be a string\");\n\n      tree_evaluator& tw = interp.get_evaluator ();\n\n      octave_function *fcn = tw.caller_function ();\n\n      if (! fcn)\n        error (\"class: invalid call from outside class constructor or method\");\n\n      if (! fcn->is_class_constructor (id) && ! fcn->is_class_method (id))\n        error (\"class: '%s' is invalid as a class name in this context\",\n               id.c_str ());\n\n      octave_map m = args(0).xmap_value (\"class: S must be a valid structure\");\n\n      if (nargin == 2)\n        retval\n          = octave_value (new octave_class (m, id, std::list<std::string> ()));\n      else\n        {\n          octave_value_list parents = args.slice (2, nargin-2);\n\n          retval = octave_value (new octave_class (m, id, parents));\n        }\n\n      octave_class::exemplar_const_iterator it\n        = octave_class::exemplar_map.find (id);\n\n      if (it == octave_class::exemplar_map.end ())\n        octave_class::exemplar_map[id] = octave_class::exemplar_info (retval);\n      else if (! it->second.compare (retval))\n        error (\"class: object of class '%s' does not match previously constructed objects\",\n               id.c_str ());\n    }\n\n  return retval;\n}\n\n/*\n%!assert (class (1.1), \"double\")\n%!assert (class (single (1.1)), \"single\")\n%!assert (class (uint8 (1)), \"uint8\")\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! jobj = javaObject (\"java.lang.StringBuffer\");\n%! assert (class (jobj), \"java.lang.StringBuffer\");\n\n## Test Input Validation\n%!error class ()\n*/\n\nDEFUN (isa, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isa (@var{obj}, @var{classname})\nReturn true if @var{obj} is an object from the class @var{classname}.\n\n@var{classname} may also be one of the following class categories:\n\n@table @asis\n@item @qcode{\"float\"}\nFloating point value comprising classes @qcode{\"double\"} and\n@qcode{\"single\"}.\n\n@item @qcode{\"integer\"}\nInteger value comprising classes (u)int8, (u)int16, (u)int32, (u)int64.\n\n@item @qcode{\"numeric\"}\nNumeric value comprising either a floating point or integer value.\n@end table\n\nIf @var{classname} is a cell array of string, a logical array of the same\nsize is returned, containing true for each class to which @var{obj}\nbelongs to.\n\n@seealso{class, typeinfo}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value obj = args(0);  // not const because of find_parent_class ()\n  std::string obj_cls = obj.class_name ();\n  Array<std::string> clsnames = args(1).xcellstr_value (\"isa: CLASSNAME must be a string or cell array of strings\");\n\n  boolNDArray matches (clsnames.dims (), false);\n\n  for (octave_idx_type idx = 0; idx < clsnames.numel (); idx++)\n    {\n      std::string cls = clsnames(idx);\n      if (obj_cls == cls\n          || (cls == \"float\"   && obj.isfloat   ())\n          || (cls == \"integer\" && obj.isinteger ())\n          || (cls == \"numeric\" && obj.isnumeric ())\n          || obj.is_instance_of (cls))\n        matches(idx) = true;\n    }\n\n  return ovl (matches);\n}\n\n/*\n%!assert (isa (\"char\", \"float\"), false)\n%!assert (isa (logical (1), \"float\"), false)\n%!assert (isa (double (13), \"float\"), true)\n%!assert (isa (single (13), \"float\"), true)\n%!assert (isa (int8 (13), \"float\"), false)\n%!assert (isa (int16 (13), \"float\"), false)\n%!assert (isa (int32 (13), \"float\"), false)\n%!assert (isa (int64 (13), \"float\"), false)\n%!assert (isa (uint8 (13), \"float\"), false)\n%!assert (isa (uint16 (13), \"float\"), false)\n%!assert (isa (uint32 (13), \"float\"), false)\n%!assert (isa (uint64 (13), \"float\"), false)\n%!assert (isa (\"char\", \"numeric\"), false)\n%!assert (isa (logical (1), \"numeric\"), false)\n%!assert (isa (double (13), \"numeric\"), true)\n%!assert (isa (single (13), \"numeric\"), true)\n%!assert (isa (int8 (13), \"numeric\"), true)\n%!assert (isa (int16 (13), \"numeric\"), true)\n%!assert (isa (int32 (13), \"numeric\"), true)\n%!assert (isa (int64 (13), \"numeric\"), true)\n%!assert (isa (uint8 (13), \"numeric\"), true)\n%!assert (isa (uint16 (13), \"numeric\"), true)\n%!assert (isa (uint32 (13), \"numeric\"), true)\n%!assert (isa (uint64 (13), \"numeric\"), true)\n%!assert (isa (uint8 (13), \"integer\"), true)\n%!assert (isa (double (13), \"integer\"), false)\n%!assert (isa (single (13), \"integer\"), false)\n%!assert (isa (single (13), {\"integer\", \"float\", \"single\"}), [false true true])\n\n%!assert (isa (double (13), \"double\"))\n%!assert (isa (single (13), \"single\"))\n%!assert (isa (int8 (13), \"int8\"))\n%!assert (isa (int16 (13), \"int16\"))\n%!assert (isa (int32 (13), \"int32\"))\n%!assert (isa (int64 (13), \"int64\"))\n%!assert (isa (uint8 (13), \"uint8\"))\n%!assert (isa (uint16 (13), \"uint16\"))\n%!assert (isa (uint32 (13), \"uint32\"))\n%!assert (isa (uint64 (13), \"uint64\"))\n%!assert (isa (\"string\", \"char\"))\n%!assert (isa (true, \"logical\"))\n%!assert (isa (false, \"logical\"))\n%!assert (isa ({1, 2}, \"cell\"))\n%!assert (isa ({1, 2}, {\"numeric\", \"integer\", \"cell\"}), [false false true])\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! ## The first and last assert() are equal on purpose.  The assert() in\n%! ## the middle with an invalid class name will cause the java code to\n%! ## throw exceptions which we then must clear properly (or all other calls\n%! ## will fail).  So we test this too.\n%! assert (isa (javaObject (\"java.lang.Double\", 10), \"java.lang.Number\"));\n%! assert (isa (javaObject (\"java.lang.Double\", 10), \"not_a_class\"), false);\n%! assert (isa (javaObject (\"java.lang.Double\", 10), \"java.lang.Number\"));\n\n%!test\n%! a.b = 1;\n%! assert (isa (a, \"struct\"));\n*/\n\nDEFUN (__parent_classes__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{Ccls} =} __parent_classes__ (@var{x})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  if (arg.isobject ())\n    return ovl (Cell (arg.parent_class_names ()));\n  else\n    return ovl (Cell ());\n}\n\nDEFUN (isobject, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isobject (@var{x})\nReturn true if @var{x} is a class object.\n@seealso{class, typeinfo, isa, ismethod, isprop}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isobject ());\n}\n\nstatic bool\nis_built_in_class (const std::string& cn)\n{\n  static std::set<std::string> built_in_class_names;\n\n  if (built_in_class_names.empty ())\n    {\n      built_in_class_names.insert (\"double\");\n      built_in_class_names.insert (\"single\");\n      built_in_class_names.insert (\"cell\");\n      built_in_class_names.insert (\"struct\");\n      built_in_class_names.insert (\"logical\");\n      built_in_class_names.insert (\"char\");\n      built_in_class_names.insert (\"function handle\");\n      built_in_class_names.insert (\"int8\");\n      built_in_class_names.insert (\"uint8\");\n      built_in_class_names.insert (\"int16\");\n      built_in_class_names.insert (\"uint16\");\n      built_in_class_names.insert (\"int32\");\n      built_in_class_names.insert (\"uint32\");\n      built_in_class_names.insert (\"int64\");\n      built_in_class_names.insert (\"uint64\");\n    }\n\n  return built_in_class_names.find (cn) != built_in_class_names.end ();\n}\n\nDEFMETHOD (superiorto, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} superiorto (@var{class_name}, @dots{})\nWhen called from a class constructor, mark the object currently constructed\nas having a higher precedence than @var{class_name}.\n\nMore that one such class can be specified in a single call.  This function\nmay @emph{only} be called from a class constructor.\n@seealso{inferiorto}\n@end deftypefn */)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  octave_function *fcn = tw.caller_function ();\n\n  if (! fcn || ! fcn->is_class_constructor ())\n    error (\"superiorto: invalid call from outside class constructor\");\n\n  for (int i = 0; i < args.length (); i++)\n    {\n      std::string inf_class = args(i).xstring_value (\"superiorto: CLASS_NAME must be a string\");\n\n      // User defined classes always have higher precedence\n      // than built-in classes\n      if (is_built_in_class (inf_class))\n        break;\n\n      symbol_table& symtab = interp.get_symbol_table ();\n\n      std::string sup_class = fcn->name ();\n      if (! symtab.set_class_relationship (sup_class, inf_class))\n        error (\"superiorto: opposite precedence already set for %s and %s\",\n               sup_class.c_str (), inf_class.c_str ());\n    }\n\n  return ovl ();\n}\n\nDEFMETHOD (inferiorto, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} inferiorto (@var{class_name}, @dots{})\nWhen called from a class constructor, mark the object currently constructed\nas having a lower precedence than @var{class_name}.\n\nMore that one such class can be specified in a single call.  This function\nmay @emph{only} be called from a class constructor.\n@seealso{superiorto}\n@end deftypefn */)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  octave_function *fcn = tw.caller_function ();\n\n  if (! fcn || ! fcn->is_class_constructor ())\n    error (\"inferiorto: invalid call from outside class constructor\");\n\n  for (int i = 0; i < args.length (); i++)\n    {\n      std::string sup_class = args(i).xstring_value (\"inferiorto: CLASS_NAME must be a string\");\n\n      if (is_built_in_class (sup_class))\n        error (\"inferiorto: cannot give user-defined class lower \"\n               \"precedence than built-in class\");\n\n      symbol_table& symtab = interp.get_symbol_table ();\n\n      std::string inf_class = fcn->name ();\n      if (! symtab.set_class_relationship (sup_class, inf_class))\n        error (\"inferiorto: opposite precedence already set for %s and %s\",\n               inf_class.c_str (), sup_class.c_str ());\n    }\n\n  return ovl ();\n}\n\n// The following classes allow us to define \"inline\" function objects as\n// legacy @class objects (as they appear to be in Matlab) while\n// preserving the is_inline_function and function_value methods that\n// were previously available in the octave_fcn_inline class.  However,\n// inline function objects no longer behave as octave_fcn_handle objects\n// so calling is_function_handle for them no longer returns true.  I see\n// no reasonable way to preserve that behavior.  The goal here is to\n// allow most code that used the old octave_inline_fcn object to\n// continue to work while eliminating the octave_inline_fcn class that\n// was derived from the octave_fcn_handle class.  Making that change\n// appears to be necessary to properly fix function handle behavior and\n// improve Matlab compatibility.  It's unfortunate if this change causes\n// trouble, but I see no better fix.  Ultimately, we should replace all\n// uses of \"inline\" function objects with anonymous functions.\n\nclass octave_inline;\n\n// The following class can be removed once the\n// octave_value::function_value method is removed.\n\nclass octave_inline_fcn : public octave_function\n{\npublic:\n\n  octave_inline_fcn (octave_inline *obj) : m_inline_obj (obj) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_inline_fcn)\n\n  ~octave_inline_fcn () = default;\n\n  // Override default call method because we ultimately use feval to\n  // execute the inline function and that will push a stack frame.\n\n  octave_value_list\n  call (tree_evaluator& tw, int nargout = 0,\n        const octave_value_list& args = octave_value_list ())\n  {\n    return execute (tw, nargout, args);\n  }\n\n  octave_value_list\n  execute (tree_evaluator& tw, int nargout = 0,\n           const octave_value_list& args = octave_value_list ());\n\nprivate:\n\n  octave_inline *m_inline_obj;\n};\n\n// Once the octave_inline_fcn class is removed, we should also be able\n// to eliminate the octave_inline class below and replace the\n// octave_value::is_inline_function method with\n//\n// bool octave_value::is_inline_function () const\n// {\n//   return class_name () == \"inline\";\n// }\n\nclass octave_inline : public octave_class\n{\npublic:\n\n  octave_inline (const octave_map& m)\n    : octave_class (m, \"inline\"), m_fcn_obj (new octave_inline_fcn (this))\n  { }\n\n  octave_inline (const octave_inline&) = default;\n\n  ~octave_inline () = default;\n\n  octave_base_value * clone () const { return new octave_inline (*this); }\n\n  octave_base_value * empty_clone () const\n  {\n    return new octave_inline (octave_map (map_keys ()));\n  }\n\n  bool is_inline_function () const { return true; }\n\n  octave_function * function_value (bool)\n  {\n    return m_fcn_obj.get ();\n  }\n\nprivate:\n\n  std::shared_ptr<octave_inline_fcn> m_fcn_obj;\n};\n\noctave_value_list\noctave_inline_fcn::execute (tree_evaluator& tw, int nargout,\n                            const octave_value_list& args)\n{\n  interpreter& interp = tw.get_interpreter ();\n\n  return interp.feval (octave_value (m_inline_obj, true), args, nargout);\n}\n\n\nDEFUN (__inline_ctor__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{inline_obj} =} __inline_ctor__ (@var{prop_struct})\nImplement final construction for inline objects.\n@end deftypefn */)\n{\n  // Input validation has already been done in input.m.\n  return octave_value (new octave_inline (args(0).map_value ()));\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-class.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_class_h)\n#define octave_ov_class_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-map.h\"\n#include \"ov-base.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass type_info;\n\nOCTAVE_END_NAMESPACE(octave)\n\nclass octave_value_list;\n\n// Data structures.\n\nclass OCTINTERP_API octave_class : public octave_base_value\n{\npublic:\n\n  octave_class ()\n    : octave_base_value (), m_map (), m_c_name (),\n      m_parent_list (), m_obsolete_copies (0)\n  { }\n\n  octave_class (const octave_map& m, const std::string& id)\n    : octave_base_value (), m_map (m), m_c_name (id),\n      m_parent_list (), m_obsolete_copies (0)\n  { }\n\n  octave_class (const octave_map& m, const std::string& id,\n                const std::list<std::string>& plist)\n    : octave_base_value (), m_map (m), m_c_name (id),\n      m_parent_list (plist), m_obsolete_copies (0)\n  { }\n\n  OCTINTERP_API\n  octave_class (const octave_map& m, const std::string& id,\n                const octave_value_list& parents);\n\n  octave_class (const octave_class& s)\n    : octave_base_value (s), m_map (s.m_map), m_c_name (s.m_c_name),\n      m_parent_list (s.m_parent_list), m_obsolete_copies (0)  { }\n\n  ~octave_class () = default;\n\n  octave_base_value * clone () const { return new octave_class (*this); }\n\n  OCTINTERP_API octave_base_value * unique_clone ();\n\n  octave_base_value * empty_clone () const\n  {\n    return new octave_class (octave_map (m_map.keys ()), m_c_name, m_parent_list);\n  }\n\n  OCTINTERP_API void\n  break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame);\n\n  OCTINTERP_API Cell dotref (const octave_value_list& idx);\n\n  OCTINTERP_API Matrix size ();\n\n  OCTINTERP_API octave_idx_type xnumel (const octave_value_list&);\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx)\n  {\n    octave_value_list tmp = subsref (type, idx, 1);\n    return tmp.length () > 0 ? tmp(0) : octave_value ();\n  }\n\n  OCTINTERP_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int nargout);\n\n  static OCTINTERP_API octave_value\n  numeric_conv (const Cell& val, const std::string& type);\n\n  void assign(const std::string& k, const octave_value& rhs)\n  { m_map.assign (k, rhs); }\n\n  OCTINTERP_API octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  OCTINTERP_API octave_value\n  undef_subsasgn (const std::string& type,\n                  const std::list<octave_value_list>& idx,\n                  const octave_value& rhs);\n\n  OCTINTERP_API octave::idx_vector\n  index_vector (bool require_integers = false) const;\n\n  dim_vector dims () const { return m_map.dims (); }\n\n  OCTINTERP_API std::size_t byte_size () const;\n\n  // This is the number of elements in each field.  The total number\n  // of elements is numel () * nfields ().\n  octave_idx_type numel () const\n  {\n    const dim_vector& dv = dims ();\n    return dv.numel ();\n  }\n\n  octave_idx_type nfields () const { return m_map.nfields (); }\n\n  std::size_t nparents () const { return m_parent_list.size (); }\n\n  octave_value reshape (const dim_vector& new_dims) const\n  {\n    octave_class retval = octave_class (*this);\n    retval.m_map = retval.map_value ().reshape (new_dims);\n    return octave_value (new octave_class (retval));\n  }\n\n  octave_value resize (const dim_vector& dv, bool = false) const\n  {\n    octave_class retval = octave_class (*this);\n    retval.m_map.resize (dv);\n    return octave_value (new octave_class (retval));\n  }\n\n  bool is_defined () const { return true; }\n\n  bool isstruct () const { return false; }\n\n  bool isobject () const { return true; }\n\n  OCTINTERP_API bool is_true () const;\n\n  octave_map map_value () const { return m_map; }\n\n  OCTINTERP_API string_vector map_keys () const;\n\n  std::list<std::string> parent_class_name_list () const\n  { return m_parent_list; }\n\n  string_vector parent_class_names () const\n  { return string_vector (m_parent_list); }\n\n  OCTINTERP_API octave_base_value * find_parent_class (const std::string&);\n\n  OCTINTERP_API octave_base_value * unique_parent_class (const std::string&);\n\n  OCTINTERP_API bool is_instance_of (const std::string&) const;\n\n  OCTINTERP_API string_vector string_vector_value (bool pad) const;\n\n  OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  OCTINTERP_API void print_raw (std::ostream& os,\n                                bool pr_as_read_syntax = false) const;\n\n  OCTINTERP_API bool reconstruct_exemplar ();\n\n  OCTINTERP_API static void clear_exemplar_map ();\n\n  OCTINTERP_API bool reconstruct_parents ();\n\n  OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  OCTINTERP_API bool load_ascii (std::istream& is);\n\n  OCTINTERP_API bool save_binary (std::ostream& os, bool save_as_floats);\n\n  OCTINTERP_API bool\n  load_binary (std::istream& is, bool swap,\n               octave::mach_info::float_format fmt);\n\n  OCTINTERP_API bool\n  save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  OCTINTERP_API bool\n  load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  OCTINTERP_API mxArray * as_mxArray (bool interleaved) const;\n\nprivate:\n  octave_map m_map;\n\npublic:\n  int type_id () const { return s_t_id; }\n  std::string type_name () const { return s_t_name; }\n  std::string class_name () const { return m_c_name; }\n\n  static int static_type_id () { return s_t_id; }\n  static std::string static_type_name () { return s_t_name; }\n  static std::string static_class_name () { return \"<unknown>\"; }\n  static OCTINTERP_API void register_type (octave::type_info&);\n\nprivate:\n  static int s_t_id;\n\n  static const std::string s_t_name;\n  std::string m_c_name;\n  std::list<std::string> m_parent_list;\n\n  OCTINTERP_API bool in_class_method ();\n  OCTINTERP_API std::string get_current_method_class ();\n\n  OCTINTERP_API octave_value\n  subsasgn_common (const octave_value& obj, const std::string& type,\n                   const std::list<octave_value_list>& idx,\n                   const octave_value& rhs);\n\n  int m_obsolete_copies;\n\npublic:\n  // The list of field names and parent classes defines a class.  We\n  // keep track of each class that has been created so that we know\n  class exemplar_info\n  {\n  public:\n\n    exemplar_info () : m_field_names (), m_parent_class_names () { }\n\n    OCTINTERP_API exemplar_info (const octave_value& obj);\n\n    exemplar_info (const exemplar_info& x)\n      : m_field_names (x.m_field_names),\n        m_parent_class_names (x.m_parent_class_names) { }\n\n    exemplar_info& operator = (const exemplar_info& x)\n    {\n      if (&x != this)\n        {\n          m_field_names = x.m_field_names;\n          m_parent_class_names = x.m_parent_class_names;\n        }\n      return *this;\n    }\n\n    octave_idx_type nfields () const { return m_field_names.numel (); }\n\n    std::size_t nparents () const { return m_parent_class_names.size (); }\n\n    string_vector fields () const { return m_field_names; }\n\n    std::list<std::string> parents () const { return m_parent_class_names; }\n\n    OCTINTERP_API bool compare (const octave_value& obj) const;\n\n  private:\n\n    string_vector m_field_names;\n    std::list<std::string> m_parent_class_names;\n  };\n\n  // A map from class names to lists of fields.\n  static std::map<std::string, exemplar_info> exemplar_map;\n\n  typedef std::map<std::string, exemplar_info>::iterator\n    exemplar_iterator;\n  typedef std::map<std::string, exemplar_info>::const_iterator\n    exemplar_const_iterator;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-classdef.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <iomanip>\n\n#include \"cdef-class.h\"\n#include \"cdef-method.h\"\n#include \"cdef-package.h\"\n#include \"cdef-property.h\"\n#include \"cdef-utils.h\"\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"load-path.h\"\n#include \"ls-oct-text.h\"\n#include \"ov-classdef.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-usr-fcn.h\"\n#include \"parse.h\"\n#include \"pr-output.h\"\n#include \"pt-eval.h\"\n#include \"pt-misc.h\"\n#include \"oct-lvalue.h\"\n\nstd::vector<std::tuple<octave_map, uint32_t, bool>>\noctave_classdef::saveobj (std::vector<bool>& is_new)\n{\n  octave::cdef_class cls = m_object.get_class ();\n  octave::cdef_method meth = cls.find_method (\"saveobj\");\n\n  // Vector with tuples consisting of a map with property values, the object id,\n  // and an indicator whether the object has a custom return type\n  std::vector<std::tuple<octave_map, uint32_t, bool>> m (numel ());\n\n  octave::load_save_system& lss = octave::__get_load_save_system__ ();\n\n  // The saveobj method needs to be called separately for each element of\n  // N-D arrays.\n  for (octave_idx_type n = 0; n < numel (); n++)\n    {\n      octave_value retval;\n\n      octave_value_list ovl_idx;\n      std::list<octave_value_list> idx_tmp;\n      ovl_idx(0) = n+1;\n      idx_tmp.push_back (ovl_idx);\n      octave_value elem = (subsref (\"(\", idx_tmp, 1))(0);\n\n      // Check if the element is already in the cache of objects that are\n      // stored in this file.\n      // Use the address of the cdef_object_rep as the key.\n      const octave::cdef_object co = elem.classdef_object_value ()->get_object_ref ();\n      bool is_new_elem;\n      std::get<uint32_t> (m[n])\n        = lss.get_mcos_object_cache_id (co.get_rep (), is_new_elem);\n      is_new[n] = is_new_elem;\n\n      if (is_new[n])\n        {\n          // Default behavior of 'loadobj' is to return this object's\n          // map_value, including all protected, private and hidden properties.\n          if (! meth.ok () || meth.is_static ())\n            // Default behaviour of saving is triggered if saveobj is static\n            std::get<octave_map> (m[n])\n              = elem.classdef_object_value ()->map_value (false, true);\n          else\n            {\n              retval = (meth.execute (elem.classdef_object_value ()->get_object_ref (),\n                                      octave_value_list (), 1))(0);\n\n              // default: no custom return type\n              std::get<bool> (m[n]) = false;\n\n              if (! retval.is_defined ())\n                {\n                  warning (\"save: saveobj method does not return a value\");\n                  return m;\n                }\n              else if (! retval.is_classdef_object ()\n                       || retval.class_name () != class_name ())\n                {\n                  // If retval is not an object of the matching class, we put\n                  // the value in a map and set the 'custom_saveobj_ret_type'\n                  // flag, which has to be encoded in the file metadata.\n                  // It's the caller's responsibility to check the flag.\n                  std::get<octave_map> (m[n]).setfield (\"any\", retval);\n                  std::get<bool> (m[n]) = true;\n                }\n\n              else if (retval.is_classdef_object ())\n                std::get<octave_map> (m[n])\n                  = retval.classdef_object_value ()->map_value (false, true);\n              else\n                std::get<octave_map> (m[n]) = retval.map_value ();\n            }\n        }\n    }\n\n  return m;\n}\n\nvoid\noctave_classdef::loadobj (std::vector<std::tuple<octave_map, uint32_t, bool>>& m,\n                          dim_vector& dv)\n{\n  octave::cdef_object scalar_obj = m_object.copy ();\n  octave::cdef_class cls = m_object.get_class ();\n  octave::cdef_method meth = cls.find_method (\"loadobj\");\n\n  octave::load_save_system& lss = octave::__get_load_save_system__ ();\n\n  // The loadobj method needs to be called separately for each element of\n  // N-D arrays.\n  for (octave_idx_type n = 0; static_cast<size_t> (n) < m.size (); n++)\n    {\n      octave_value ovc;\n\n      // Check if object is already loaded in cache\n      uint32_t id = std::get<uint32_t> (m[n]);\n      bool in_obj_cache = lss.is_mcos_object_cache_entry (id);\n      if (in_obj_cache)\n        ovc = lss.get_mcos_object_cache_entry (id);\n\n      octave_map& prop_map = std::get<octave_map> (m[n]);\n\n      if (! in_obj_cache || prop_map.nfields () > 0)\n        {\n          // Default behaviour of loading is triggered if loadobj is not static\n          if (meth.ok () && meth.is_static () && prop_map.nfields () > 0)\n            {\n              octave_value ov;\n              if (std::get<bool> (m[n]))\n                {\n                  octave_value any = prop_map.contents (\"any\").elem (0);\n                  ov = (meth.execute (octave_value_list (any), 1))(0);\n                }\n              else\n                {\n                  // create object from saved properties\n                  octave::cdef_object new_object;\n                  if (in_obj_cache)\n                    new_object = ovc.classdef_object_value ()->m_object;\n                  else\n                    new_object = scalar_obj.copy ();\n\n                  bool props_changed = false;\n                  string_vector fnames = prop_map.fieldnames ();\n                  string_vector sv = map_keys ();\n                  for (octave_idx_type i = 0; i < prop_map.nfields (); i++)\n                    {\n                      octave_idx_type j;\n                      for (j = 0; j < sv.numel (); j++)\n                        {\n                          if (sv[j] == fnames(i))\n                            {\n                              new_object.set_property (0, sv[j], prop_map.contents (fnames(i)).xelem (0));\n                              break;\n                            }\n                        }\n                      if (j == sv.numel ())\n                        {\n                          // properties have been renamed or deleted\n                          props_changed = true;\n                          break;\n                        }\n                    }\n\n                  if (props_changed)\n                    // attempting to create the object failed\n                    // call loadobj with struct\n                    ov = (meth.execute (octave_value_list (prop_map), 1))(0);\n                  else\n                    {\n                      if (! in_obj_cache)\n                        ovc = octave::to_ov (new_object);\n\n                      // pass object to loadobj\n                      ov = (meth.execute (octave_value_list (ovc), 1))(0);\n                    }\n                }\n\n              if (! ov.is_defined ())\n                {\n                  warning (\"load: loadobj method does not return a value\");\n                  return;\n                }\n\n              // FIXME: A loadobj method can return any type. If the return\n              //        type is not a classdef object of the correct class,\n              //        then the loaded object must be replaced by whatever the\n              //        return type and contents are.\n              if (! ov.is_classdef_object ())\n                {\n                  std::string type = ov.type_name ();\n                  warning (\"load: loadobj method does not return correct type \"\n                           \"'%s'. This is currently not supported.\",\n                           type.c_str ());\n                  return;\n                }\n              else if (ov.class_name () != class_name ())\n                {\n                  std::string class_nm = ov.class_name ();\n                  warning (\"load: loadobj method does not return classdef object \"\n                           \"of correct class '%s'. This is currently not supported.\",\n                           class_nm.c_str ());\n                  return;\n                }\n\n              if (in_obj_cache)\n                // Copy the results from the loadobj methods to the object in\n                // the cache.\n                ovc.classdef_object_value ()->m_object = ov.classdef_object_value ()->m_object;\n              else\n                ovc = ov;\n            }\n          else\n            {\n              if (std::get<bool> (m[n]))\n                {\n                  // If saveobj is overloaded by this classdef and it returned\n                  // anything other than a classdef object of the correct\n                  // class, then a variable named 'any' is meant to be passed\n                  // to loadobj, but if loadobj is not overloaded, it should\n                  // not fill in any property 'any' in the loaded object.\n                  if (! prop_map.isfield (\"any\") || prop_map.numel () != 1)\n                    {\n                      warning (\"load: expected scalar value for custom type when loading object\");\n                      return;\n                    }\n\n                  // FIXME: What should be done here?\n                  octave_value any_val = (prop_map.getfield (\"any\"))(0);\n                  std::string type = any_val.type_name ();\n                  if (type != type_name ())\n                    {\n                      warning (\"load: cannot restore value of object that was saved as a different type (%s)\",\n                               type.c_str ());\n                      return;\n                    }\n\n                  std::string cls_nm = any_val.class_name ();\n                  if (cls_nm != class_name ())\n                    {\n                      warning (\"load: cannot restore value of object that was saved as a different class (%s)\",\n                               cls_nm.c_str ());\n                      return;\n                    }\n\n                  // If the value in the \"any\" field has the correct type and\n                  // class, we can load it like it were saved \"normally\".\n                  // FIXME: Can this ever happen?\n                  prop_map = any_val.classdef_object_value ()->map_value (false, true);\n                }\n\n              octave::cdef_object new_object;\n              if (in_obj_cache)\n                new_object = ovc.classdef_object_value ()->m_object;\n              else\n                new_object = scalar_obj.copy ();\n\n              string_vector fnames = prop_map.fieldnames ();\n              string_vector sv = map_keys ();\n              for (octave_idx_type i = 0; i < prop_map.nfields (); i++)\n                for (octave_idx_type j = 0; j < sv.numel (); j++)\n                  if (sv[j] == fnames(i))\n                    {\n                      new_object.set_property (0, sv[j], prop_map.contents (fnames(i)).xelem (0));\n                      break;\n                    }\n\n              if (! in_obj_cache)\n                ovc = octave::to_ov (new_object);\n            }\n\n          lss.set_mcos_object_cache_entry (id, ovc);\n        }\n\n      if (m.size () == 1)\n        m_object = ovc.classdef_object_value ()->m_object;\n      else\n        {\n          octave_value_list ovl_idx;\n          std::list<octave_value_list> idx_tmp;\n          ovl_idx(0) = n+1;\n          idx_tmp.push_back (ovl_idx);\n          octave_value tmp = subsasgn (\"(\", idx_tmp, ovc);\n\n          // FIXME: Is this assignment only needed for value classes?\n          m_object = tmp.classdef_object_value ()->m_object;\n        }\n    }\n\n  // Reshape to the correct dimensions.\n  if (dv != dims ())\n    {\n      octave_value ov_reshaped = reshape (dv);\n      m_object = ov_reshaped.classdef_object_value ()->m_object;\n    }\n}\n\nbool\noctave_classdef::save_ascii (std::ostream& os)\n{\n  os << \"# classname: \" << class_name () << \"\\n\";\n\n  const dim_vector dv = m_object.dims ();\n  os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n  for (int i = 0; i < dv.ndims (); i++)\n    os << ' ' << dv(i);\n  os << \"\\n\";\n\n  std::vector<bool> is_new (numel ());\n  std::vector<std::tuple<octave_map, uint32_t, bool>> m\n    = saveobj (is_new);\n\n  for (octave_idx_type n = 0; static_cast<size_t> (n) < m.size (); n++)\n    {\n      os << \"# id: \" << std::get<uint32_t> (m[n]) << \"\\n\";\n\n      // Check if this is a reference to an already existing object\n      if (! is_new[n])\n        {\n          os << \"# length: 0\\n\";\n          continue;\n        }\n\n      octave_idx_type nf = std::get<octave_map> (m[n]).nfields ();\n\n      os << \"# length: \" << nf << \"\\n\";\n\n      os << \"# metadata: \";\n      if (std::get<bool> (m[n]))\n        os << \"saveobj_defined\";\n      os << \"\\n\";\n\n      string_vector keys = std::get<octave_map> (m[n]).fieldnames ();\n\n      for (octave_idx_type i = 0; i < nf; i++)\n        {\n          std::string key = keys(i);\n\n          // querying values from an octave_map returns 'Cell' objects\n          octave_value val = (std::get<octave_map> (m[n]).contents (key))(0);\n\n          bool b = save_text_data (os, val, key, false, 0);\n\n          if (! b)\n            return ! os.fail ();\n        }\n    }\n\n  return true;\n}\n\nbool\noctave_classdef::load_ascii (std::istream& is)\n{\n  octave_idx_type len = 0;\n  dim_vector dv (1, 1);\n\n  if (extract_keyword (is, \"ndims\", len, true))\n    {\n      int mdims = std::max (static_cast<int> (len), 2);\n      dv.resize (mdims);\n      for (int i = 0; i < mdims; i++)\n        is >> dv(i);\n    }\n  else\n    error (\"load: failed to extract keyword 'ndims' for classdef object\");\n\n  // vector for each element in the array containing:\n  // * a map with the values of the class properties\n  // * a unique identifier of the object in the file\n  // * an indicator whether the object has a custom return type\n  std::vector<std::tuple<octave_map, uint32_t, bool>> m (dv.numel ());\n\n  for (octave_idx_type i = 0; i < dv.numel (); i++)\n    {\n      if (! extract_keyword (is, \"id\", std::get<uint32_t> (m[i]), true))\n        error (\"load: failed to extract keyword 'id' for classdef object\");\n\n      if (! extract_keyword (is, \"length\", len, true))\n        error (\"load: failed to extract keyword 'length' for classdef object\");\n\n      if (len < 0)\n        error (\"load: failed to extract number of properties for classdef object\");\n\n      if (len == 0)\n        continue;\n\n      std::string metadata;\n      if (! extract_keyword (is, \"metadata\", metadata, true))\n        error (\"load: failed to extract keyword 'metadata' for classdef object\");\n\n      size_t pos = metadata.find (\"saveobj_defined\");\n      std::get<bool> (m[i]) = (pos != std::string::npos);\n\n      for (octave_idx_type j = 0; j < len; j++)\n        {\n          octave_value t2;\n          bool dummy;\n\n          std::string nm = read_text_data (is, \"\", dummy, t2, j, false);\n\n          if (! is)\n            break;\n\n          // Set the field in the octave_map\n          std::get<octave_map> (m[i]).setfield (nm, t2);\n        }\n\n      if (! is)\n        error (\"load: failed to load classdef object\");\n    }\n\n  loadobj (m, dv);\n\n  return true;\n}\n\nstatic bool\nin_class_method (const octave::cdef_class& cls)\n{\n  octave::cdef_class ctx = octave::get_class_context ();\n\n  return (ctx.ok () && octave::is_superclass (ctx, cls));\n}\n\nint octave_classdef::s_t_id (-1);\n\nconst std::string octave_classdef::s_t_name (\"object\");\n\nvoid\noctave_classdef::register_type (octave::type_info& ti)\n{\n  s_t_id = ti.register_type (octave_classdef::s_t_name, \"<unknown>\",\n                             octave_value (new octave_classdef ()));\n}\n\noctave_value_list\noctave_classdef::subsref (const std::string& type,\n                          const std::list<octave_value_list>& idx,\n                          int nargout)\n{\n  std::size_t skip = 0;\n  octave_value_list retval;\n\n  octave::cdef_class cls = m_object.get_class ();\n\n  if (! in_class_method (cls) && ! called_from_builtin ())\n    {\n      octave::cdef_method meth = cls.find_method (\"subsref\");\n\n      if (meth.ok ())\n        {\n          octave_value_list args;\n\n          args(1) = make_idx_args (type, idx, \"subsref\");\n\n          m_count++;\n          args(0) = octave_value (this);\n\n          if (nargout <= 0)\n            {\n              // If the last index type is not '()', the final value of nargout is\n              // unknown.  Try to get its value\n              if (type.back () != '(')\n                {\n                  // See if method numArgumentsFromSubscript is defined\n                  octave::cdef_method meth_nargout\n                    = cls.find_method (\"numArgumentsFromSubscript\");\n\n                  if (meth_nargout.ok ())\n                    {\n                      octave_value_list args_nargout (3);\n\n                      args_nargout(0) = args(0);\n                      args_nargout(1) = args(1);\n                      // FIXME: Third argument should be one of the possible values of\n                      //        the matlab.mixin.util.IndexingContext enumeration class.\n                      args_nargout(2) = octave_value (Matrix ());\n                      retval = meth_nargout.execute (args_nargout, 1, true,\n                                                    \"numArgumentsFromSubscript\");\n\n                      nargout = retval(0).strict_int_value\n                        (\"subsref: return value of 'numArgumentsFromSubscript' must be integer\");\n                    }\n                  else\n                    {\n                      // Method numArgumentsFromSubscript undefined.  Attempt to set up\n                      // a proper value for nargout at least in the simple case where the\n                      // cs-list-type expression - i.e., {} or ().x, is the leading one.\n\n                      // Set up a proper nargout for the subsref call by calling numel.\n                      octave_value_list tmp;\n                      int nout;\n                      if (type[0] != '.')\n                        tmp = idx.front ();\n\n                      nout = xnumel (tmp);\n                      // Take nout as nargout for subsref, unless the index expression\n                      // is a whole sentence starting with the form id.member and id is\n                      // one element (in that case, nargout remains 0).\n                      if (type[0] != '.' || nout != 1 || nargout < 0)\n                        nargout = nout;\n                    }\n                }\n              else if (nargout < 0)\n                nargout = 1;\n            }\n\n          retval = meth.execute (args, nargout, true, \"subsref\");\n\n          // Since we're handling subsref, if the list has more than one element\n          // and the caller to subsref accepts more that one output, return\n          // the elements as a comma-separated list so that we can pass it to the\n          // evaluator\n          if (retval.length () > 1 && (nargout < 0 || nargout > 1))\n            {\n              if (nargout <= 0 || nargout >= retval.length ())\n                // Take the whole list\n                retval = octave_value (retval);\n              else\n                // Take nargout elements of the list\n                retval = octave_value (retval.slice (0, nargout));\n            }\n\n          return retval;\n        }\n    }\n\n  // At this point, the default subsref mechanism must be used.\n\n  retval = m_object.subsref (type, idx, nargout, skip, octave::cdef_class ());\n\n  if (type.length () > skip && idx.size () > skip)\n    retval = retval(0).next_subsref (nargout, type, idx, skip);\n\n  return retval;\n}\n\noctave_value\noctave_classdef::subsref (const std::string& type,\n                          const std::list<octave_value_list>& idx,\n                          bool auto_add)\n{\n  std::size_t skip = 0;\n  octave_value_list retval;\n\n  // This variant of subsref is used to create temporary values when doing\n  // assignment with multi-level indexing.  AFAIK this is only used for internal\n  // purpose (not sure we should even implement this).\n\n  octave::cdef_class cls = m_object.get_class ();\n\n  if (! in_class_method (cls))\n    {\n      octave::cdef_method meth = cls.find_method (\"subsref\");\n\n      if (meth.ok ())\n        {\n          octave_value_list args;\n\n          args(1) = make_idx_args (type, idx, \"subsref\");\n\n          m_count++;\n          args(0) = octave_value (this);\n\n          retval = meth.execute (args, 1, true, \"subsref\");\n\n          return retval.length () > 0 ? retval(0) : octave_value ();\n        }\n    }\n\n  retval = m_object.subsref (type, idx, 1, skip,\n                             octave::cdef_class (), auto_add);\n\n  if (type.length () > skip && idx.size () > skip)\n    retval = retval(0).next_subsref (1, type, idx, skip);\n\n  return retval.length () > 0 ? retval(0) : octave_value ();\n}\n\noctave_value\noctave_classdef::subsasgn (const std::string& type,\n                           const std::list<octave_value_list>& idx,\n                           const octave_value& rhs)\n{\n  octave_value retval;\n\n  octave::cdef_class cls = m_object.get_class ();\n\n  if (! in_class_method (cls) && ! called_from_builtin ())\n    {\n      octave::cdef_method meth = cls.find_method (\"subsasgn\");\n\n      if (meth.ok ())\n        {\n          octave_value_list args;\n\n          args(1) = make_idx_args (type, idx, \"subsasgn\");\n\n          m_count++;\n          args(0) = octave_value (this);\n          args(2) = rhs;\n\n          octave_value_list retlist;\n\n          retlist = meth.execute (args, 1, true, \"subsasgn\");\n\n          if (retlist.empty ())\n            error (\"overloaded method 'subsasgn' did not return any value\");\n\n          retval = retlist(0);\n        }\n    }\n\n  if (! retval.is_defined ())\n    retval = m_object.subsasgn (type, idx, rhs);\n\n  return retval;\n}\n\noctave_value\noctave_classdef::undef_subsasgn (const std::string& type,\n                                 const std::list<octave_value_list>& idx,\n                                 const octave_value& rhs)\n{\n  if (type.length () == 1 && type[0] == '(')\n    {\n      m_object = m_object.make_array ();\n\n      return subsasgn (type, idx, rhs);\n    }\n  else\n    return octave_base_value::undef_subsasgn (type, idx, rhs);\n\n  return octave_value ();\n}\n\nMatrix\noctave_classdef::size ()\n{\n  octave::cdef_class cls = m_object.get_class ();\n\n  if (! in_class_method (cls) && ! called_from_builtin ())\n    {\n      octave::cdef_method meth = cls.find_method (\"size\");\n\n      if (meth.ok ())\n        {\n          m_count++;\n          octave_value_list args (1, octave_value (this));\n\n          octave_value_list lv = meth.execute (args, 1, true, \"size\");\n          if (lv.length () <= 0\n              || ! lv(0).is_matrix_type () || ! lv(0).dims ().isvector ())\n            error (\"%s.size: invalid return value\", class_name ().c_str ());\n\n          return lv(0).matrix_value ();\n        }\n    }\n\n  return octave_base_value::size ();\n}\n\noctave_idx_type\noctave_classdef::xnumel (const octave_value_list& idx)\n{\n  octave_idx_type retval = -1;\n\n  // FIXME: This method is only used in subsref and subsasgn operations, to find\n  // out the number of elements in the cs-list corresponding to the subsref\n  // output or the subsasgn lvalue.\n  // This method currently calls the classdef's numel method to do its task, but\n  // this is incompatible with Matlab.  Matlab calls numArgumentsFromSubscript\n  // for that purpose.  We cannot call numArgumentsFromSubscript here because that\n  // method needs all the information about the indices of the subsref/subsasgn\n  // operation (possibly multiple levels of indexing of different types)\n\n  octave::cdef_class cls = m_object.get_class ();\n\n  if (! in_class_method (cls) && ! called_from_builtin ())\n    {\n      octave::cdef_method meth = cls.find_method (\"numel\");\n\n      if (meth.ok ())\n        {\n          octave_value_list args (idx.length () + 1, octave_value ());\n\n          m_count++;\n          args(0) = octave_value (this);\n\n          for (octave_idx_type i = 0; i < idx.length (); i++)\n            args(i+1) = idx(i);\n\n          // Temporarily set lvalue list of current statement to NULL, to avoid\n          // using that list for the execution of the method \"numel\"\n          octave::interpreter& interp = octave::__get_interpreter__ ();\n          octave::tree_evaluator& tw = interp.get_evaluator();\n\n          octave::unwind_action act ([&tw] (const std::list<octave::octave_lvalue> *lvl)\n          {\n            tw.set_lvalue_list (lvl);\n          }, tw.lvalue_list ());\n          tw.set_lvalue_list (nullptr);\n\n          octave_value_list lv = meth.execute (args, 1, true, \"numel\");\n          if (lv.length () != 1 || ! lv(0).is_scalar_type ())\n            error (\"@%s/numel: invalid return value\", cls.get_name ().c_str ());\n\n          retval = lv(0).idx_type_value (true);\n\n          return retval;\n        }\n    }\n\n  retval = octave_base_value::xnumel (idx);\n\n  return retval;\n}\n\noctave_value\noctave_classdef::reshape (const dim_vector& new_dims) const\n{\n  octave_value retval;\n\n  octave::cdef_class cls = m_object.get_class ();\n\n  if (! in_class_method (cls) && ! called_from_builtin ())\n    {\n      octave::cdef_method meth = cls.find_method (\"reshape\");\n\n      if (meth.ok ())\n        {\n          octave_value_list args;\n\n          args(0) = octave::to_ov (m_object.clone ());\n          args(1) = new_dims.as_array ();\n\n          octave_value_list retlist;\n\n          retlist = meth.execute (args, 1, true, \"reshape\");\n\n          if (retlist.empty ())\n            error (\"overloaded method 'reshape' did not return any value\");\n\n          retval = retlist(0);\n        }\n    }\n\n  if (! retval.is_defined ())\n    retval = m_object.reshape (new_dims);\n\n  return retval;\n}\n\nvoid\noctave_classdef::print (std::ostream& os, bool)\n{\n  print_raw (os);\n}\n\nvoid\noctave_classdef::print_raw (std::ostream& os, bool) const\n{\n  octave::cdef_class cls = m_object.get_class ();\n\n  if (cls.ok ())\n    {\n      bool is_array = m_object.is_array ();\n\n      increment_indent_level ();\n\n      indent (os);\n\n      dim_vector dv = dims ();\n      if (dv.ndims () > 4)\n        os << dv.ndims () << \"-D\";\n      else\n        os << dims().str();\n\n      os << \" \" << class_name () << \" object\";\n      if (is_array)\n        os << \" array\";\n      os << \" with properties:\";\n      newline (os);\n      if (! Vcompact_format)\n        newline (os);\n\n      increment_indent_level ();\n\n      std::map<octave::property_key, octave::cdef_property> property_map\n        = cls.get_property_map ();\n\n      std::size_t max_len = 0;\n      for (const auto& pname_prop : property_map)\n        {\n          // FIXME: this loop duplicates a significant portion of the\n          // loop below and the loop in Fproperties.\n\n          const octave::cdef_property& prop = pname_prop.second;\n\n          const std::string nm = prop.get_name ();\n\n          octave_value acc = prop.get (\"GetAccess\");\n\n          if (! acc.is_string () || acc.string_value () != \"public\")\n            continue;\n\n          octave_value hid = prop.get (\"Hidden\");\n\n          if (hid.bool_value ())\n            continue;\n\n          std::size_t sz = nm.size ();\n\n          if (sz > max_len)\n            max_len = sz;\n        }\n\n      for (auto& pname_prop : property_map)\n        {\n          const octave::cdef_property& prop = pname_prop.second;\n\n          const std::string nm = prop.get_name ();\n\n          octave_value acc = prop.get (\"GetAccess\");\n\n          if (! acc.is_string () || acc.string_value () != \"public\")\n            continue;\n\n          octave_value hid = prop.get (\"Hidden\");\n\n          if (hid.bool_value ())\n            continue;\n\n          indent (os);\n\n          if (is_array)\n            os << \"  \" << nm;\n          else\n            {\n              os << std::setw (max_len+2) << nm << \": \";\n\n              octave_value val = prop.get_value (m_object, false);\n\n              val.short_disp (os);\n            }\n\n          newline (os);\n        }\n\n      decrement_indent_level ();\n      decrement_indent_level ();\n    }\n}\n\nbool\noctave_classdef::is_instance_of (const std::string& cls_name) const\n{\n  octave::cdef_class cls = octave::lookup_class (cls_name, false, false);\n\n  if (cls.ok ())\n    return is_superclass (cls, m_object.get_class ());\n\n  return false;\n}\n\noctave_value\noctave_classdef::superclass_ref (const std::string& meth,\n                                 const std::string& cls)\n{\n  return octave_value (new octave_classdef_superclass_ref (meth, cls));\n}\n\noctave_value\noctave_classdef::metaclass_query (const std::string& cls)\n{\n  return octave::to_ov (octave::lookup_class (cls));\n}\n\nbool\noctave_classdef_meta::is_classdef_method (const std::string& cname) const\n{\n  bool retval = false;\n\n  if (m_object.is_method ())\n    {\n      if (cname.empty ())\n        retval = true;\n      else\n        {\n          octave::cdef_method meth (m_object);\n\n          return meth.is_defined_in_class (cname);\n        }\n    }\n\n  return retval;\n}\n\nbool\noctave_classdef_meta::is_classdef_constructor (const std::string& cname) const\n{\n  bool retval = false;\n\n  if (m_object.is_class ())\n    {\n      if (cname.empty ())\n        retval = true;\n      else\n        {\n          octave::cdef_class cls (m_object);\n\n          if (cls.get_name () == cname)\n            retval = true;\n        }\n    }\n  else if (m_object.is_method ())\n    {\n      octave::cdef_method meth (m_object);\n\n      if (meth.is_constructor ())\n        {\n          std::string meth_name = meth.get_name ();\n\n          // Only consider METH to be a constructor if the dispatch\n          // class CNAME is the same as or derived from the class of\n          // METH.\n\n          if (cname == meth_name)\n            retval = true;\n          else\n            {\n              octave::cdef_class meth_cls = octave::lookup_class (meth_name, false, false);\n              octave::cdef_class dispatch_cls = octave::lookup_class (cname, false, false);\n\n              retval = octave::is_superclass (meth_cls, dispatch_cls);\n            }\n        }\n    }\n\n  return retval;\n}\n\nstd::string\noctave_classdef_meta::doc_string (const std::string& meth_name) const\n{\n  if (m_object.is_class ())\n    {\n      octave::cdef_class cls (m_object);\n\n      if (meth_name.empty ())\n        return cls.doc_string ();\n\n      octave::cdef_method cdef_meth = cls.find_method (meth_name);\n\n      if (cdef_meth.ok ())\n        return cdef_meth.get_doc_string ();\n    }\n\n  return \"\";\n}\n\nstd::string\noctave_classdef_meta::file_name () const\n{\n  if (m_object.is_class ())\n    {\n      octave::cdef_class cls (m_object);\n\n      return cls.file_name ();\n    }\n\n  return \"\";\n}\n\noctave_value_list\noctave_classdef_superclass_ref::execute (octave::tree_evaluator& tw,\n    int nargout,\n    const octave_value_list& idx)\n{\n  octave_value_list retval;\n\n  std::string meth_name;\n  bool in_constructor;\n  octave::cdef_class ctx;\n\n  ctx = octave::get_class_context (meth_name, in_constructor);\n\n  if (! ctx.ok ())\n    error (\"superclass calls can only occur in methods or constructors\");\n\n  std::string mname = m_method_name;\n  std::string cname = m_class_name;\n\n  // CLS is the superclass.  The lookup_class function handles\n  // pkg.class names.\n\n  octave::cdef_class cls = octave::lookup_class (cname);\n\n  if (in_constructor)\n    {\n      if (! is_direct_superclass (cls, ctx))\n        error (\"'%s' is not a direct superclass of '%s'\",\n               cname.c_str (), ctx.get_name ().c_str ());\n\n      if (! is_constructed_object (tw, mname))\n        error (\"cannot call superclass constructor with variable '%s'\",\n               mname.c_str ());\n\n      octave_value sym = tw.varval (mname);\n\n      cls.run_constructor (octave::to_cdef_ref (sym), idx);\n\n      retval(0) = sym;\n    }\n  else\n    {\n      std::size_t pos = mname.find ('.');\n\n      octave::cdef_object obj;\n\n      if (pos != std::string::npos)\n        {\n          // We are looking at obj.meth.\n\n          std::string oname = m_method_name.substr (0, pos);\n          mname = mname.substr (pos + 1);\n\n          octave_value tval = tw.varval (oname);\n\n          // FIXME: Can we only call superclass methods on the current\n          // object?  If so, and we are looking at something like\n          //\n          //   function meth (obj, ...)\n          //     obj.meth@superclass (...)\n          //\n          // Do we need to verify that the object that was passed to\n          // meth is the same as the object we find when looking up\n          // obj in the expression obj.meth?  If so, what is the right\n          // way to perform that check?\n\n          if (tval.is_classdef_object ())\n            {\n              octave_classdef *cdobj = tval.classdef_object_value ();\n\n              obj = cdobj->get_object ();\n            }\n        }\n\n      if (mname != meth_name)\n        error (\"method name mismatch ('%s' != '%s')\",\n               mname.c_str (), meth_name.c_str ());\n\n      if (! is_strict_superclass (cls, ctx))\n        error (\"'%s' is not a superclass of '%s'\",\n               cname.c_str (), ctx.get_name ().c_str ());\n\n      // I see 2 possible implementations here:\n      // 1) use cdef_object::subsref with a different class\n      //    context; this avoids duplicating code, but\n      //    assumes the object is always the first argument\n      // 2) lookup the method manually and call\n      //    cdef_method::execute; this duplicates part of\n      //    logic in cdef_object::subsref, but avoid the\n      //    assumption of 1)\n      // Not being sure about the assumption of 1), I\n      // go with option 2) for the time being.\n\n      octave::cdef_method meth = cls.find_method (meth_name, false);\n\n      if (! meth.ok ())\n        error (\"no method '%s' found in superclass '%s'\",\n               meth_name.c_str (), cname.c_str ());\n\n      retval = (obj.ok ()\n                ? meth.execute (obj, idx, nargout, true, meth_name)\n                : meth.execute (idx, nargout, true, meth_name));\n    }\n\n  return retval;\n}\n\nbool\noctave_classdef_superclass_ref::is_constructed_object (octave::tree_evaluator& tw,\n    const std::string& nm)\n{\n  octave_function *of = tw.current_function ();\n\n  if (of->is_classdef_constructor ())\n    {\n      octave_user_function *uf = of->user_function_value (true);\n\n      if (uf)\n        {\n          octave::tree_parameter_list *ret_list = uf->return_list ();\n\n          if (ret_list && ret_list->size () >= 1)\n            return (ret_list->front ()->name () == nm);\n        }\n    }\n\n  return false;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (__meta_get_package__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{pkg} =} __meta_get_package__ (@var{pkg_name})\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  std::string cname = args(0).xstring_value (\"PKG_NAME must be a string\");\n\n  return to_ov (lookup_package (cname));\n}\n\nDEFUN (metaclass, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{metaclass_obj} =} metaclass (obj)\nReturn the meta.class object corresponding to the class of @var{obj}.\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  cdef_object obj = to_cdef (args(0));\n\n  return to_ov (obj.get_class ());\n}\n\n// FIXME: What about dynamic properties if obj is a scalar, or the\n// properties of the class of obj if obj is an array?  Probably there\n// should be a function to do this job so that the DEFUN is just a\n// simple wrapper.\n\nDEFUN (properties, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {} properties (@var{obj})\n@deftypefnx {} {} properties (@var{class_name})\n@deftypefnx {} {@var{proplist} =} properties (@dots{})\nDisplay or return the public properties for the classdef object @var{obj} or\nthe named class @var{class_name}.\n\nIf an output value is requested, return the list of property names in a cell\narray.\n\nProgramming Note: Property names are returned if the @code{GetAccess} attribute\nis public and if the @code{Hidden} attribute is false.\n@seealso{methods}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_value arg = args(0);\n\n  std::string class_name;\n\n  if (arg.isobject ())\n    class_name = arg.class_name ();\n  else if (arg.is_string ())\n    class_name = arg.string_value ();\n  else\n    err_wrong_type_arg (\"properties\", arg);\n\n  cdef_class cls;\n\n  cls = lookup_class (class_name, false, true);\n\n  if (! cls.ok ())\n    error (\"invalid class: %s\", class_name.c_str ());\n\n  std::map<octave::property_key, cdef_property> property_map =\n    cls.get_property_map ();\n\n  std::list<std::string> property_names;\n\n  for (const auto& pname_prop : property_map)\n    {\n      // FIXME: this loop duplicates a significant portion of the loops\n      // in octave_classdef::print_raw.\n      const cdef_property& prop = pname_prop.second;\n\n      octave_value acc = prop.get (\"GetAccess\");\n\n      if (! acc.is_string () || acc.string_value () != \"public\")\n        continue;\n\n      octave_value hid = prop.get (\"Hidden\");\n\n      if (hid.bool_value ())\n        continue;\n\n      property_names.push_back (pname_prop.second.get_name ());\n    }\n\n  if (nargout > 0)\n    return octave_value (Cell (string_vector (property_names)));\n\n  octave_stdout << \"properties for class \" << class_name << \":\\n\\n\";\n\n  for (const auto& nm : property_names)\n    octave_stdout << \"  \" << nm << \"\\n\";\n\n  octave_stdout << std::endl;\n\n  return octave_value ();\n}\n\n/*\n%!assert (properties (\"inputParser\"),\n%!        {\"CaseSensitive\"; \"FunctionName\"; \"KeepUnmatched\"; \"PartialMatching\";\n%!         \"StructExpand\"; \"Parameters\"; \"Results\"; \"Unmatched\";\n%!         \"UsingDefaults\"});\n*/\n\n// FIXME: Need to implement the -full option.\n\nDEFMETHOD (__methods__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{mtds}, @var{found}] =} __methods__ (@var{obj})\n@deftypefnx {} {[@var{mtds}, @var{found}] =} __methods__ (\"classname\")\nImplement @code{methods} for Octave class objects and classnames.\n@seealso{methods}\n@end deftypefn */)\n{\n  // Input validation has already been done in methods.m.\n  octave_value arg = args(0);\n\n  std::string class_name;\n\n  if (arg.isobject ())\n    class_name = arg.class_name ();\n  else if (arg.is_string ())\n    class_name = arg.string_value ();\n  else\n    err_wrong_type_arg (\"__methods__\", arg);\n\n  string_vector sv;\n  bool found = false;\n\n  cdef_class cls = lookup_class (class_name, false, true);\n\n  if (cls.ok ())\n    {\n      // Find methods for classdef objects.\n      std::map<std::string, cdef_method> method_map\n        = cls.get_method_map (false, true);\n\n      std::list<std::string> method_names;\n\n      for (const auto& nm_mthd : method_map)\n        {\n          const cdef_method& method = nm_mthd.second;\n\n          octave_value acc = method.get (\"Access\");\n\n          if (! acc.is_string () || acc.string_value () != \"public\")\n            continue;\n\n          octave_value hid = method.get (\"Hidden\");\n\n          if (hid.bool_value ())\n            continue;\n\n          method_names.push_back (nm_mthd.first);\n        }\n\n      sv = string_vector (method_names);\n      found = true;\n    }\n  else\n    {\n      // Find methods for legacy @CLASS objects.\n      load_path& lp = interp.get_load_path ();\n\n      sv = string_vector (lp.methods (class_name));\n      found = ! sv.empty ();\n    }\n\n  return ovl (Cell (sv), found);\n}\n\n/*\n// BIST tests are in file methods.m\n%!assert (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-classdef.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_classdef_h)\n#define octave_classdef_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"cdef-object.h\"\n#include \"ov-base.h\"\n#include \"ov-fcn.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass cdef_object;\nclass interpreter;\nclass tree_evaluator;\nclass type_info;\n\nOCTAVE_END_NAMESPACE(octave)\n\nclass octave_classdef : public octave_base_value\n{\npublic:\n\n  octave_classdef ()\n    : octave_base_value (), m_object () { }\n\n  octave_classdef (const octave::cdef_object& obj)\n    : octave_base_value (), m_object (obj) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_classdef)\n\n  ~octave_classdef () = default;\n\n  octave_base_value * clone () const\n  {\n    return new octave_classdef (m_object.clone ());\n  }\n\n  octave_base_value * empty_clone () const\n  {\n    return new octave_classdef (m_object.empty_clone ());\n  }\n\n  octave_classdef * classdef_object_value (bool = false) { return this; }\n\n  octave::cdef_object get_object () const { return m_object; }\n\n  octave::cdef_object& get_object_ref () { return m_object; }\n\n  bool is_defined () const { return true; }\n\n  bool isstruct () const { return false; }\n\n  bool isobject () const { return true; }\n\n  bool is_classdef_object () const { return true; }\n\n  OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  OCTINTERP_API void\n  print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  OCTINTERP_API bool is_instance_of (const std::string& cls_name) const;\n\n  void break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame)\n  {\n    m_object.break_closure_cycles (frame);\n  }\n\n  OCTINTERP_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int nargout);\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx)\n  {\n    octave_value_list retval = subsref (type, idx, 1);\n    return (retval.length () > 0 ? retval(0) : octave_value ());\n  }\n\n  OCTINTERP_API octave_value\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           bool auto_add);\n\n  OCTINTERP_API octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  OCTINTERP_API octave_value\n  undef_subsasgn (const std::string& type,\n                  const std::list<octave_value_list>& idx,\n                  const octave_value& rhs);\n\n  OCTINTERP_API Matrix size ();\n\n  OCTINTERP_API octave_value reshape (const dim_vector& new_dims) const;\n\n  OCTINTERP_API octave_idx_type xnumel (const octave_value_list&);\n\n  string_vector map_keys () const { return m_object.map_keys (); }\n\n  octave_map map_value () const { return m_object.map_value (true); }\n\n  octave_map map_value (bool warn) const { return m_object.map_value (warn); }\n\n  octave_map map_value (bool warn, bool for_save) const\n  { return m_object.map_value (warn, for_save); }\n\n  dim_vector dims () const { return m_object.dims (); }\n\n  void set_property (octave_idx_type idx, const std::string& name,\n                     const octave_value& pval)\n  {\n    m_object.set_property (idx, name, pval);\n  }\n\n  octave_value\n  get_property (octave_idx_type idx, const std::string& name) const\n  {\n    return m_object.get_property (idx, name);\n  }\n\n  static OCTINTERP_API octave_value\n  superclass_ref (const std::string& meth, const std::string& cls);\n\n  static OCTINTERP_API octave_value metaclass_query (const std::string& cls);\n\n  OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  OCTINTERP_API bool load_ascii (std::istream& is);\n\n  octave_value\n  permute (const Array<int>& vec, bool inv = false) const\n  {\n    return new octave_classdef (m_object.permute (vec, inv));\n  }\n\n  octave_value\n  resize (const dim_vector& dv, bool fill = false) const\n  {\n    return new octave_classdef (m_object.resize (dv, fill));\n  }\n\n  std::size_t byte_size () const { return m_object.byte_size (); }\n\npublic:\n\n  int type_id () const { return s_t_id; }\n  std::string type_name () const { return s_t_name; }\n  std::string class_name () const { return m_object.class_name (); }\n\n  static int static_type_id () { return s_t_id; }\n  static std::string static_type_name () { return s_t_name; }\n  static std::string static_class_name () { return \"<unknown>\"; }\n  static OCTINTERP_API void register_type (octave::type_info&);\n\n  // Load an array of the size dv using a vector with\n  // * a map with the values of the class properties\n  // * a unique identifier of the object in the file\n  // * an indicator whether the object has a custom return type\n  OCTINTERP_API void\n  loadobj (std::vector<std::tuple<octave_map, uint32_t, bool>>& m,\n           dim_vector& dv);\n\n  // Return a vector for each element in the array containing:\n  // * a map with the values of the class properties\n  // * a unique identifier of the object in the file\n  // * an indicator whether the object has a custom return type\n  OCTINTERP_API std::vector<std::tuple<octave_map, uint32_t, bool>>\n  saveobj (std::vector<bool>& is_new);\n\nprivate:\n\n  octave::cdef_object m_object;\n\n  static int s_t_id;\n\n  static const std::string s_t_name;\n};\n\nvoid install_classdef (octave::interpreter& interp);\n\nclass octave_classdef_meta : public octave_function\n{\npublic:\n\n  octave_classdef_meta (const octave::cdef_meta_object& obj)\n    : m_object (obj)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_classdef_meta)\n\n  ~octave_classdef_meta () { m_object.meta_release (); }\n\n  bool is_classdef_meta () const { return true; }\n\n  bool is_package () const { return m_object.is_package(); }\n\n  octave_function * function_value (bool = false) { return this; }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_function::subsref;\n\n  octave_value_list\n  subsref (const std::string& type,\n           const std::list<octave_value_list>& idx,\n           int nargout)\n  {\n    return m_object.meta_subsref (type, idx, nargout);\n  }\n\n  // Override default call method because we don't push a new stack\n  // frame for this operation on classdef_meta objects.\n\n  octave_value_list call (octave::tree_evaluator& tw, int nargout,\n                          const octave_value_list& args)\n  {\n    return execute (tw, nargout, args);\n  }\n\n  octave_value_list execute (octave::tree_evaluator&, int nargout,\n                             const octave_value_list& args)\n  {\n    // Emulate ()-type meta subsref\n\n    std::list<octave_value_list> idx (1, args);\n    std::string type (\"(\");\n\n    return subsref (type, idx, nargout);\n  }\n\n  bool accepts_postfix_index (char type) const\n  { return m_object.meta_accepts_postfix_index (type); }\n\n  OCTINTERP_API bool is_classdef_method (const std::string& cname = \"\") const;\n\n  OCTINTERP_API bool\n  is_classdef_constructor (const std::string& cname = \"\") const;\n\n  OCTINTERP_API std::string doc_string (const std::string& meth_name) const;\n\n  OCTINTERP_API std::string file_name () const;\n\nprivate:\n\n  octave::cdef_meta_object m_object;\n};\n\nclass octave_classdef_superclass_ref : public octave_function\n{\npublic:\n  octave_classdef_superclass_ref () = delete;\n\n  octave_classdef_superclass_ref (const std::string& meth,\n                                  const std::string& cls)\n    : octave_function (), m_method_name (meth), m_class_name (cls)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_classdef_superclass_ref)\n\n  ~octave_classdef_superclass_ref () = default;\n\n  bool is_classdef_superclass_ref () const { return true; }\n\n  octave_function * function_value (bool = false) { return this; }\n\n  // Override default call method because we don't push a new stack\n  // frame for this operation on classdef_superclass_ref objects.\n\n  octave_value_list call (octave::tree_evaluator& tw, int nargout,\n                          const octave_value_list& args)\n  {\n    return execute (tw, nargout, args);\n  }\n\n  OCTINTERP_API octave_value_list\n  execute (octave::tree_evaluator& tw, int nargout,\n           const octave_value_list& idx);\n\nprivate:\n\n  OCTINTERP_API bool\n  is_constructed_object (octave::tree_evaluator& tw, const std::string& nm);\n\nprivate:\n\n  std::string m_method_name;\n  std::string m_class_name;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-colon.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ostream>\n\n#include \"error.h\"\n#include \"pr-output.h\"\n#include \"ovl.h\"\n#include \"ov-colon.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_magic_colon,\n                                     \"magic-colon\", \"magic-colon\");\n\nvoid\noctave_magic_colon::print (std::ostream& os, bool)\n{\n  indent (os);\n  print_raw (os);\n}\n\nvoid\noctave_magic_colon::print_raw (std::ostream& os, bool) const\n{\n  os << ':';\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-colon.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_colon_h)\n#define octave_ov_colon_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// A type to represent ':' as used for indexing.\n\nclass octave_magic_colon : public octave_base_value\n{\npublic:\n\n  octave_magic_colon ()\n    : octave_base_value () { }\n\n  octave_magic_colon (const octave_magic_colon&)\n    : octave_base_value () { }\n\n  ~octave_magic_colon () = default;\n\n  octave_base_value * clone () const\n  { return new octave_magic_colon (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_magic_colon (); }\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  { return octave::idx_vector (':'); }\n\n  bool is_defined () const { return true; }\n\n  bool is_constant () const { return true; }\n\n  bool is_magic_colon () const { return true; }\n\n  OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  OCTINTERP_API void print_raw (std::ostream& os,\n                                bool pr_as_read_syntax = false) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-complex.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n#include <sstream>\n\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"oct-specfun.h\"\n\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-base.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-scalar.h\"\n#include \"errwarn.h\"\n#include \"pr-output.h\"\n#include \"ops.h\"\n\n#include \"ls-oct-text.h\"\n#include \"ls-hdf5.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_complex,\n                                     \"complex scalar\", \"double\");\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Complain if a complex value is used as a subscript.\n\nclass complex_index_exception : public index_exception\n{\npublic:\n\n  complex_index_exception (const std::string& value)\n    : index_exception (value)\n  {\n    // Virtual, but the one we want to call is defined in this class.\n    update_message ();\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE (complex_index_exception)\n\n  ~complex_index_exception () = default;\n\n  void update_message ()\n  {\n    set_message (expression ()\n                 + \": subscripts must be real (forgot to initialize i or j?)\");\n  }\n\n  // ID of error to throw.\n  const char * err_id () const\n  {\n    return \"Octave:invalid-index\";\n  }\n\n  index_exception * dup ()\n  {\n    complex_index_exception *retval = new complex_index_exception {*this};\n    retval->set_identifier (retval->err_id ());\n    return retval;\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\nstatic octave_base_value *\ndefault_numeric_demotion_function (const octave_base_value& a)\n{\n  const octave_complex& v = dynamic_cast<const octave_complex&> (a);\n\n  return new octave_float_complex (v.float_complex_value ());\n}\n\noctave_base_value::type_conv_info\noctave_complex::numeric_demotion_function () const\n{\n  return\n    octave_base_value::type_conv_info (default_numeric_demotion_function,\n                                       octave_float_complex::static_type_id ());\n}\n\noctave_base_value *\noctave_complex::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  double im = scalar.imag ();\n\n  if (im == 0.0)\n    retval = new octave_scalar (scalar.real ());\n\n  return retval;\n}\n\noctave_value\noctave_complex::do_index_op (const octave_value_list& idx, bool resize_ok)\n{\n  // FIXME: this doesn't solve the problem of\n  //\n  //   a = i; a([1,1], [1,1], [1,1])\n  //\n  // and similar constructions.  Hmm...\n\n  // FIXME: using this constructor avoids narrowing the\n  // 1x1 matrix back to a scalar value.  Need a better solution\n  // to this problem.\n\n  octave_value tmp (new octave_complex_matrix (complex_matrix_value ()));\n\n  return tmp.index_op (idx, resize_ok);\n}\n\n// Can't make an index_vector from a complex number.  Throw an error.\noctave::idx_vector\noctave_complex::index_vector (bool) const\n{\n  std::ostringstream buf;\n  buf << scalar.real () << std::showpos << scalar.imag () << 'i';\n  octave::complex_index_exception cie (buf.str ());\n\n  throw cie;\n}\n\ndouble\noctave_complex::double_value (bool force_conversion) const\n{\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real scalar\");\n\n  return scalar.real ();\n}\n\nfloat\noctave_complex::float_value (bool force_conversion) const\n{\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real scalar\");\n\n  return scalar.real ();\n}\n\nMatrix\noctave_complex::matrix_value (bool force_conversion) const\n{\n  Matrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real matrix\");\n\n  retval = Matrix (1, 1, scalar.real ());\n\n  return retval;\n}\n\nFloatMatrix\noctave_complex::float_matrix_value (bool force_conversion) const\n{\n  FloatMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real matrix\");\n\n  retval = FloatMatrix (1, 1, scalar.real ());\n\n  return retval;\n}\n\nNDArray\noctave_complex::array_value (bool force_conversion) const\n{\n  NDArray retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real matrix\");\n\n  retval = NDArray (dim_vector (1, 1), scalar.real ());\n\n  return retval;\n}\n\nFloatNDArray\noctave_complex::float_array_value (bool force_conversion) const\n{\n  FloatNDArray retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real matrix\");\n\n  retval = FloatNDArray (dim_vector (1, 1), scalar.real ());\n\n  return retval;\n}\n\nComplex\noctave_complex::complex_value (bool) const\n{\n  return scalar;\n}\n\nFloatComplex\noctave_complex::float_complex_value (bool) const\n{\n  return static_cast<FloatComplex> (scalar);\n}\n\nComplexMatrix\noctave_complex::complex_matrix_value (bool) const\n{\n  return ComplexMatrix (1, 1, scalar);\n}\n\nFloatComplexMatrix\noctave_complex::float_complex_matrix_value (bool) const\n{\n  return FloatComplexMatrix (1, 1, static_cast<FloatComplex> (scalar));\n}\n\nComplexNDArray\noctave_complex::complex_array_value (bool /* force_conversion */) const\n{\n  return ComplexNDArray (dim_vector (1, 1), scalar);\n}\n\nFloatComplexNDArray\noctave_complex::float_complex_array_value (bool /* force_conversion */) const\n{\n  return FloatComplexNDArray (dim_vector (1, 1),\n                              static_cast<FloatComplex> (scalar));\n}\n\noctave_value\noctave_complex::resize (const dim_vector& dv, bool fill) const\n{\n  if (fill)\n    {\n      ComplexNDArray retval (dv, Complex (0));\n\n      if (dv.numel ())\n        retval(0) = scalar;\n\n      return retval;\n    }\n  else\n    {\n      ComplexNDArray retval (dv);\n\n      if (dv.numel ())\n        retval(0) = scalar;\n\n      return retval;\n    }\n}\n\noctave_value\noctave_complex::as_double () const\n{\n  return scalar;\n}\n\noctave_value\noctave_complex::as_single () const\n{\n  return FloatComplex (scalar);\n}\n\noctave_value\noctave_complex::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return ComplexDiagMatrix (Array<Complex> (dim_vector (1, 1), scalar), m, n);\n}\n\nbool\noctave_complex::save_ascii (std::ostream& os)\n{\n  Complex c = complex_value ();\n\n  octave::write_value<Complex> (os, c);\n\n  os << \"\\n\";\n\n  return true;\n}\n\nbool\noctave_complex::load_ascii (std::istream& is)\n{\n  scalar = octave::read_value<Complex> (is);\n\n  if (! is)\n    error (\"load: failed to load complex scalar constant\");\n\n  return true;\n}\n\nbool\noctave_complex::save_binary (std::ostream& os, bool /* save_as_floats */)\n{\n  char tmp = static_cast<char> (LS_DOUBLE);\n  os.write (reinterpret_cast<char *> (&tmp), 1);\n  Complex ctmp = complex_value ();\n  os.write (reinterpret_cast<char *> (&ctmp), 16);\n\n  return true;\n}\n\nbool\noctave_complex::load_binary (std::istream& is, bool swap,\n                             octave::mach_info::float_format fmt)\n{\n  char tmp;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n    return false;\n\n  Complex ctmp;\n  read_doubles (is, reinterpret_cast<double *> (&ctmp),\n                static_cast<save_type> (tmp), 2, swap, fmt);\n\n  if (! is)\n    return false;\n\n  scalar = ctmp;\n  return true;\n}\n\nbool\noctave_complex::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                           bool /* save_as_floats */)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hsize_t dimens[3] = {0};\n  hid_t space_hid, type_hid, data_hid;\n  space_hid = type_hid = data_hid = -1;\n\n  space_hid = H5Screate_simple (0, dimens, nullptr);\n  if (space_hid < 0)\n    return false;\n\n  type_hid = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);\n  if (type_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      return false;\n    }\n\n  Complex tmp = complex_value ();\n  retval = H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n\n  H5Dclose (data_hid);\n  H5Tclose (type_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_complex::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t type_hid = H5Dget_type (data_hid);\n\n  hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);\n\n  if (! hdf5_types_compatible (type_hid, complex_type))\n    {\n      H5Tclose (complex_type);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  hid_t space_id = H5Dget_space (data_hid);\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank != 0)\n    {\n      H5Tclose (complex_type);\n      H5Sclose (space_id);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  // complex scalar:\n  Complex ctmp;\n  if (H5Dread (data_hid, complex_type, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &ctmp) >= 0)\n    {\n      retval = true;\n      scalar = ctmp;\n    }\n\n  H5Tclose (complex_type);\n  H5Sclose (space_id);\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nmxArray *\noctave_complex::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, 1, 1, mxCOMPLEX);\n\n  if (interleaved)\n    {\n      mxComplexDouble *pd\n        = reinterpret_cast<mxComplexDouble *> (retval->get_complex_doubles ());\n\n      pd[0].real = scalar.real ();\n      pd[0].imag = scalar.imag ();\n    }\n  else\n    {\n      mxDouble *pr = static_cast<mxDouble *> (retval->get_data ());\n      mxDouble *pi = static_cast<mxDouble *> (retval->get_imag_data ());\n\n      pr[0] = scalar.real ();\n      pi[0] = scalar.imag ();\n    }\n\n  return retval;\n}\n\noctave_value\noctave_complex::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n#define SCALAR_MAPPER(UMAP, FCN)              \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (FCN (scalar))\n\n      SCALAR_MAPPER (abs, std::abs);\n      SCALAR_MAPPER (acos, octave::math::acos);\n      SCALAR_MAPPER (acosh, octave::math::acosh);\n      SCALAR_MAPPER (angle, std::arg);\n      SCALAR_MAPPER (arg, std::arg);\n      SCALAR_MAPPER (asin, octave::math::asin);\n      SCALAR_MAPPER (asinh, octave::math::asinh);\n      SCALAR_MAPPER (atan, octave::math::atan);\n      SCALAR_MAPPER (atanh, octave::math::atanh);\n      SCALAR_MAPPER (erf, octave::math::erf);\n      SCALAR_MAPPER (erfc, octave::math::erfc);\n      SCALAR_MAPPER (erfcx, octave::math::erfcx);\n      SCALAR_MAPPER (erfi, octave::math::erfi);\n      SCALAR_MAPPER (dawson, octave::math::dawson);\n      SCALAR_MAPPER (ceil, octave::math::ceil);\n      SCALAR_MAPPER (conj, std::conj);\n      SCALAR_MAPPER (cos, std::cos);\n      SCALAR_MAPPER (cosh, std::cosh);\n      SCALAR_MAPPER (exp, std::exp);\n      SCALAR_MAPPER (expm1, octave::math::expm1);\n      SCALAR_MAPPER (fix, octave::math::fix);\n      SCALAR_MAPPER (floor, octave::math::floor);\n      SCALAR_MAPPER (imag, std::imag);\n      SCALAR_MAPPER (log, std::log);\n      SCALAR_MAPPER (log2, octave::math::log2);\n      SCALAR_MAPPER (log10, std::log10);\n      SCALAR_MAPPER (log1p, octave::math::log1p);\n      SCALAR_MAPPER (real, std::real);\n      SCALAR_MAPPER (round, octave::math::round);\n      SCALAR_MAPPER (roundb, octave::math::roundb);\n      SCALAR_MAPPER (signum, octave::math::signum);\n      SCALAR_MAPPER (sin, std::sin);\n      SCALAR_MAPPER (sinh, std::sinh);\n      SCALAR_MAPPER (sqrt, std::sqrt);\n      SCALAR_MAPPER (tan, std::tan);\n      SCALAR_MAPPER (tanh, std::tanh);\n      SCALAR_MAPPER (isfinite, octave::math::isfinite);\n      SCALAR_MAPPER (isinf, octave::math::isinf);\n      SCALAR_MAPPER (isna, octave::math::isna);\n      SCALAR_MAPPER (isnan, octave::math::isnan);\n\n    // Special cases for Matlab compatibility.\n    case umap_xtolower:\n    case umap_xtoupper:\n      return scalar;\n\n    default:\n      return octave_base_value::map (umap);\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-complex.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_complex_h)\n#define octave_ov_complex_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"errwarn.h\"\n#include \"error.h\"\n#include \"ov-base.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-base-scalar.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Complex scalar values.\n\nextern template class OCTINTERP_API octave_base_scalar<Complex>;\n\nclass OCTINTERP_API octave_complex : public octave_base_scalar<Complex>\n{\npublic:\n\n  octave_complex ()\n    : octave_base_scalar<Complex> () { }\n\n  octave_complex (const Complex& c)\n    : octave_base_scalar<Complex> (c) { }\n\n  octave_complex (const octave_complex& c)\n    : octave_base_scalar<Complex> (c) { }\n\n  ~octave_complex () = default;\n\n  octave_base_value * clone () const { return new octave_complex (*this); }\n\n  // We return an octave_complex_matrix object here instead of an\n  // octave_complex object so that in expressions like A(2,2,2) = 2\n  // (for A previously undefined), A will be empty instead of a 1x1\n  // object.\n  octave_base_value * empty_clone () const\n  { return new octave_complex_matrix (); }\n\n  type_conv_info numeric_demotion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  // Use this to give a more specific error message.\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const;\n\n  octave_value any (int = 0) const\n  {\n    return (scalar != Complex (0, 0)\n            && ! (octave::math::isnan (scalar.real ())\n                  || octave::math::isnan (scalar.imag ())));\n  }\n\n  builtin_type_t builtin_type () const { return btyp_complex; }\n\n  bool is_complex_scalar () const { return true; }\n\n  bool iscomplex () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  OCTINTERP_API double double_value (bool = false) const;\n\n  OCTINTERP_API float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  float float_scalar_value (bool frc_str_conv = false) const\n  { return float_value (frc_str_conv); }\n\n  OCTINTERP_API Matrix matrix_value (bool = false) const;\n\n  OCTINTERP_API FloatMatrix float_matrix_value (bool = false) const;\n\n  OCTINTERP_API NDArray array_value (bool = false) const;\n\n  OCTINTERP_API FloatNDArray float_array_value (bool = false) const;\n\n  SparseMatrix sparse_matrix_value (bool = false) const\n  { return SparseMatrix (matrix_value ()); }\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  { return SparseComplexMatrix (complex_matrix_value ()); }\n\n  OCTINTERP_API octave_value\n  resize (const dim_vector& dv, bool fill = false) const;\n\n  OCTINTERP_API Complex complex_value (bool = false) const;\n\n  OCTINTERP_API FloatComplex float_complex_value (bool = false) const;\n\n  OCTINTERP_API ComplexMatrix complex_matrix_value (bool = false) const;\n\n  OCTINTERP_API FloatComplexMatrix\n  float_complex_matrix_value (bool = false) const;\n\n  OCTINTERP_API ComplexNDArray complex_array_value (bool = false) const;\n\n  OCTINTERP_API FloatComplexNDArray\n  float_complex_array_value (bool = false) const;\n\n  bool bool_value (bool warn = false) const\n  {\n    if (octave::math::isnan (scalar))\n      octave::err_nan_to_logical_conversion ();\n    if (warn && scalar != 0.0 && scalar != 1.0)\n      warn_logical_conversion ();\n\n    return scalar != 0.0;\n  }\n\n  boolNDArray bool_array_value (bool warn = false) const\n  {\n    if (octave::math::isnan (scalar))\n      octave::err_nan_to_logical_conversion ();\n    if (warn && scalar != 0.0 && scalar != 1.0)\n      warn_logical_conversion ();\n\n    return boolNDArray (dim_vector (1, 1), scalar != 0.0);\n  }\n\n  OCTINTERP_API octave_value as_double () const;\n  OCTINTERP_API octave_value as_single () const;\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_scalar<Complex>::diag;\n\n  OCTINTERP_API octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  void increment () { scalar += 1.0; }\n\n  void decrement () { scalar -= 1.0; }\n\n  OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  OCTINTERP_API bool load_ascii (std::istream& is);\n\n  OCTINTERP_API bool save_binary (std::ostream& os, bool save_as_floats);\n\n  OCTINTERP_API bool\n  load_binary (std::istream& is, bool swap,\n               octave::mach_info::float_format fmt);\n\n  OCTINTERP_API bool\n  save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  OCTINTERP_API bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    // Yes, for compatibility, we drop the imaginary part here.\n    return os.write (array_value (true), block_size, output_type,\n                     skip, flt_fmt);\n  }\n\n  OCTINTERP_API mxArray * as_mxArray (bool interleaved) const;\n\n  OCTINTERP_API octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\ntypedef octave_complex octave_complex_scalar;\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-cs-list.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-utils.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ov-cs-list.h\"\n#include \"unwind-prot.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_cs_list, \"cs-list\", \"cs-list\");\n\noctave_cs_list::octave_cs_list (const Cell& c)\n  : octave_base_value (), m_list (c)\n{ }\n\noctave_value\noctave_cs_list::subsref (const std::string&,\n                         const std::list<octave_value_list>&)\n{\n  err_indexed_cs_list ();\n}\n\noctave_value_list\noctave_cs_list::subsref (const std::string&,\n                         const std::list<octave_value_list>&, int)\n{\n  err_indexed_cs_list ();\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-cs-list.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_cs_list_h)\n#define octave_ov_cs_list_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"Cell.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"ov-typeinfo.h\"\n\n// Lists.\n\nclass octave_cs_list : public octave_base_value\n{\npublic:\n\n  octave_cs_list ()\n    : octave_base_value (), m_list () { }\n\n  octave_cs_list (const octave_value_list& l)\n    : octave_base_value (), m_list (l) { }\n\n  octave_cs_list (const Cell& c);\n\n  octave_cs_list (const octave_cs_list& l)\n    : octave_base_value (), m_list (l.m_list) { }\n\n  ~octave_cs_list () = default;\n\n  octave_base_value * clone () const { return new octave_cs_list (*this); }\n  octave_base_value * empty_clone () const { return new octave_cs_list (); }\n\n  dim_vector dims () const { return dim_vector (1, m_list.length ()); }\n\n  bool is_defined () const { return true; }\n\n  bool is_constant () const { return true; }\n\n  bool is_cs_list () const { return true; }\n\n  octave_value_list list_value () const { return m_list; }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  OCTINTERP_API octave_value\n  subsref (const std::string& type, const std::list<octave_value_list>& idx);\n\n  OCTINTERP_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int);\n\nprivate:\n\n  // The list of Octave values.\n  octave_value_list m_list;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-cx-diag.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"byte-swap.h\"\n\n#include \"ov-cx-diag.h\"\n#include \"ov-flt-cx-diag.h\"\n#include \"ov-re-diag.h\"\n#include \"ov-complex.h\"\n#include \"ls-utils.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_complex_diag_matrix,\n                                     \"complex diagonal matrix\", \"double\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_complex_diag_matrix& v\n    = dynamic_cast<const octave_complex_diag_matrix&> (a);\n\n  return new octave_complex_matrix (v.complex_matrix_value ());\n}\n\noctave_base_value::type_conv_info\noctave_complex_diag_matrix::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info\n         (default_numeric_conversion_function,\n          octave_complex_matrix::static_type_id ());\n}\n\nstatic octave_base_value *\ndefault_numeric_demotion_function (const octave_base_value& a)\n{\n  const octave_complex_diag_matrix& v\n    = dynamic_cast<const octave_complex_diag_matrix&> (a);\n\n  return new octave_float_complex_diag_matrix\n         (v.float_complex_diag_matrix_value ());\n}\n\noctave_base_value::type_conv_info\noctave_complex_diag_matrix::numeric_demotion_function () const\n{\n  return\n    octave_base_value::type_conv_info (default_numeric_demotion_function,\n                                       octave_float_complex_diag_matrix::static_type_id ());\n}\n\noctave_base_value *\noctave_complex_diag_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.nelem () == 1)\n    {\n      retval = new octave_complex (m_matrix (0, 0));\n      octave_base_value *rv2 = retval->try_narrowing_conversion ();\n      if (rv2)\n        {\n          delete retval;\n          retval = rv2;\n        }\n    }\n  else if (m_matrix.all_elements_are_real ())\n    {\n      return new octave_diag_matrix (::real (m_matrix));\n    }\n\n  return retval;\n}\n\nDiagMatrix\noctave_complex_diag_matrix::diag_matrix_value (bool force_conversion) const\n{\n  DiagMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              type_name (), \"real matrix\");\n\n  retval = ::real (m_matrix);\n\n  return retval;\n}\n\nFloatDiagMatrix\noctave_complex_diag_matrix::float_diag_matrix_value (bool force_conversion) const\n{\n  DiagMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              type_name (), \"real matrix\");\n\n  retval = ::real (m_matrix);\n\n  return retval;\n}\n\nComplexDiagMatrix\noctave_complex_diag_matrix::complex_diag_matrix_value (bool) const\n{\n  return m_matrix;\n}\n\nFloatComplexDiagMatrix\noctave_complex_diag_matrix::float_complex_diag_matrix_value (bool) const\n{\n  return FloatComplexDiagMatrix (m_matrix);\n}\n\noctave_value\noctave_complex_diag_matrix::as_double () const\n{\n  return m_matrix;\n}\n\noctave_value\noctave_complex_diag_matrix::as_single () const\n{\n  return FloatComplexDiagMatrix (m_matrix);\n}\n\noctave_value\noctave_complex_diag_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    case umap_abs:\n      return m_matrix.abs ();\n    case umap_real:\n      return ::real (m_matrix);\n    case umap_conj:\n      return ::conj (m_matrix);\n    case umap_imag:\n      return ::imag (m_matrix);\n    case umap_sqrt:\n      {\n        ComplexColumnVector tmp\n          = m_matrix.extract_diag ().map<Complex> (std::sqrt);\n        ComplexDiagMatrix retval (tmp);\n        retval.resize (m_matrix.rows (), m_matrix.columns ());\n        return retval;\n      }\n    default:\n      return to_dense ().map (umap);\n    }\n}\n\nbool\noctave_complex_diag_matrix::save_binary (std::ostream& os, bool save_as_floats)\n{\n\n  int32_t r = m_matrix.rows ();\n  int32_t c = m_matrix.cols ();\n  os.write (reinterpret_cast<char *> (&r), 4);\n  os.write (reinterpret_cast<char *> (&c), 4);\n\n  ComplexMatrix m = ComplexMatrix (m_matrix.extract_diag ());\n  save_type st = LS_DOUBLE;\n  if (save_as_floats)\n    {\n      if (m.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        st = LS_FLOAT;\n    }\n  else if (m_matrix.length () > 4096) // FIXME: make this configurable.\n    {\n      double max_val, min_val;\n      if (m.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  const Complex *mtmp = m.data ();\n  write_doubles (os, reinterpret_cast<const double *> (mtmp), st,\n                 2 * m.numel ());\n\n  return true;\n}\n\nbool\noctave_complex_diag_matrix::load_binary (std::istream& is, bool swap,\n    octave::mach_info::float_format fmt)\n{\n  int32_t r, c;\n  char tmp;\n  if (! (is.read (reinterpret_cast<char *> (&r), 4)\n         && is.read (reinterpret_cast<char *> (&c), 4)\n         && is.read (reinterpret_cast<char *> (&tmp), 1)))\n    return false;\n  if (swap)\n    {\n      swap_bytes<4> (&r);\n      swap_bytes<4> (&c);\n    }\n\n  ComplexDiagMatrix m (r, c);\n  Complex *im = m.rwdata ();\n  octave_idx_type len = m.length ();\n  read_doubles (is, reinterpret_cast<double *> (im),\n                static_cast<save_type> (tmp), 2 * len, swap, fmt);\n\n  if (! is)\n    return false;\n\n  m_matrix = m;\n\n  return true;\n}\n\nbool\noctave_complex_diag_matrix::chk_valid_scalar (const octave_value& val,\n    Complex& x) const\n{\n  bool retval = val.is_complex_scalar () || val.is_real_scalar ();\n  if (retval)\n    x = val.complex_value ();\n  return retval;\n}\n\n/*\n%!assert <*36368> (diag ([1+i, 1-i])^2 , diag ([2i, -2i]), 4*eps)\n*/\n"
  },
  {
    "path": "libinterp/octave-value/ov-cx-diag.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_cx_diag_h)\n#define octave_ov_cx_diag_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov-base.h\"\n#include \"ov-base-diag.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n\n// Real diagonal matrix values.\n\nextern template class OCTINTERP_API\noctave_base_diag<ComplexDiagMatrix, ComplexMatrix>;\n\nclass octave_complex_diag_matrix\n  : public octave_base_diag<ComplexDiagMatrix, ComplexMatrix>\n{\npublic:\n\n  octave_complex_diag_matrix ()\n    : octave_base_diag<ComplexDiagMatrix, ComplexMatrix> () { }\n\n  octave_complex_diag_matrix (const ComplexDiagMatrix& m)\n    : octave_base_diag<ComplexDiagMatrix, ComplexMatrix> (m) { }\n\n  octave_complex_diag_matrix (const octave_complex_diag_matrix& m)\n    : octave_base_diag<ComplexDiagMatrix, ComplexMatrix> (m) { }\n\n  ~octave_complex_diag_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_complex_diag_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_complex_diag_matrix (); }\n\n  OCTINTERP_API type_conv_info numeric_conversion_function () const;\n\n  OCTINTERP_API type_conv_info numeric_demotion_function () const;\n\n  OCTINTERP_API octave_base_value * try_narrowing_conversion ();\n\n  builtin_type_t builtin_type () const { return btyp_complex; }\n\n  bool is_complex_matrix () const { return true; }\n\n  bool iscomplex () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  OCTINTERP_API DiagMatrix diag_matrix_value (bool = false) const;\n\n  OCTINTERP_API FloatDiagMatrix float_diag_matrix_value (bool = false) const;\n\n  OCTINTERP_API ComplexDiagMatrix\n  complex_diag_matrix_value (bool = false) const;\n\n  OCTINTERP_API FloatComplexDiagMatrix\n  float_complex_diag_matrix_value (bool = false) const;\n\n  OCTINTERP_API octave_value as_double () const;\n  OCTINTERP_API octave_value as_single () const;\n\n  OCTINTERP_API bool save_binary (std::ostream& os, bool save_as_floats);\n\n  OCTINTERP_API bool\n  load_binary (std::istream& is, bool swap,\n               octave::mach_info::float_format fmt);\n\n  OCTINTERP_API octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  OCTINTERP_API bool chk_valid_scalar (const octave_value&, Complex&) const;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-cx-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <clocale>\n#include <istream>\n#include <ostream>\n\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n\n#include \"data-conv.h\"\n#include \"lo-ieee.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"mx-base.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-specfun.h\"\n\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"pr-output.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-utils.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_complex_matrix,\n                                     \"complex matrix\", \"double\");\n\nstatic octave_base_value *\ndefault_numeric_demotion_function (const octave_base_value& a)\n{\n  const octave_complex_matrix& v = dynamic_cast<const octave_complex_matrix&> (a);\n\n  return new octave_float_complex_matrix (v.float_complex_array_value ());\n}\n\noctave_base_value::type_conv_info\noctave_complex_matrix::numeric_demotion_function () const\n{\n  return octave_base_value::type_conv_info\n         (default_numeric_demotion_function,\n          octave_float_complex_matrix::static_type_id ());\n}\n\noctave_base_value *\noctave_complex_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.numel () == 1)\n    {\n      Complex c = m_matrix (0);\n\n      if (c.imag () == 0.0)\n        retval = new octave_scalar (c.real ());\n      else\n        retval = new octave_complex (c);\n    }\n  else if (m_matrix.all_elements_are_real ())\n    retval = new octave_matrix (::real (m_matrix));\n\n  return retval;\n}\n\ndouble\noctave_complex_matrix::double_value (bool force_conversion) const\n{\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real scalar\");\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"complex matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"complex matrix\", \"real scalar\");\n\n  return std::real (m_matrix(0, 0));\n}\n\nfloat\noctave_complex_matrix::float_value (bool force_conversion) const\n{\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real scalar\");\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"complex matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"complex matrix\", \"real scalar\");\n\n  return std::real (m_matrix(0, 0));\n}\n\nNDArray\noctave_complex_matrix::array_value (bool force_conversion) const\n{\n  NDArray retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real matrix\");\n\n  retval = ::real (m_matrix);\n\n  return retval;\n}\n\nMatrix\noctave_complex_matrix::matrix_value (bool force_conversion) const\n{\n  Matrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real matrix\");\n\n  retval = ::real (ComplexMatrix (m_matrix));\n\n  return retval;\n}\n\nFloatMatrix\noctave_complex_matrix::float_matrix_value (bool force_conversion) const\n{\n  FloatMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real matrix\");\n\n  retval = ::real (ComplexMatrix (m_matrix));\n\n  return retval;\n}\n\nComplex\noctave_complex_matrix::complex_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"complex matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"complex matrix\", \"complex scalar\");\n\n  return m_matrix(0, 0);\n}\n\nFloatComplex\noctave_complex_matrix::float_complex_value (bool) const\n{\n  float tmp = lo_ieee_float_nan_value ();\n\n  FloatComplex retval (tmp, tmp);\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"complex matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"complex matrix\", \"complex scalar\");\n\n  retval = m_matrix(0, 0);\n\n  return retval;\n}\n\nComplexMatrix\noctave_complex_matrix::complex_matrix_value (bool) const\n{\n  return ComplexMatrix (m_matrix);\n}\n\nFloatComplexMatrix\noctave_complex_matrix::float_complex_matrix_value (bool) const\n{\n  return FloatComplexMatrix (ComplexMatrix (m_matrix));\n}\n\nboolNDArray\noctave_complex_matrix::bool_array_value (bool warn) const\n{\n  if (m_matrix.any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n  if (warn && (! m_matrix.all_elements_are_real ()\n               || real (m_matrix).any_element_not_one_or_zero ()))\n    warn_logical_conversion ();\n\n  return mx_el_ne (m_matrix, Complex (0.0));\n}\n\ncharNDArray\noctave_complex_matrix::char_array_value (bool frc_str_conv) const\n{\n  charNDArray retval;\n\n  if (! frc_str_conv)\n    warn_implicit_conversion (\"Octave:num-to-str\",\n                              \"complex matrix\", \"string\");\n  else\n    {\n      retval = charNDArray (dims ());\n      octave_idx_type nel = numel ();\n\n      for (octave_idx_type i = 0; i < nel; i++)\n        if (octave::math::isnan (std::real (m_matrix.elem (i))))\n          retval.elem (i) = 0;\n        else\n          retval.elem (i) = static_cast<char> (std::real (m_matrix.elem (i)));\n    }\n\n  return retval;\n}\n\nFloatComplexNDArray\noctave_complex_matrix::float_complex_array_value (bool) const\n{\n  return FloatComplexNDArray (m_matrix);\n}\n\nSparseMatrix\noctave_complex_matrix::sparse_matrix_value (bool force_conversion) const\n{\n  SparseMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real matrix\");\n\n  retval = SparseMatrix (::real (ComplexMatrix (m_matrix)));\n\n  return retval;\n}\n\nSparseComplexMatrix\noctave_complex_matrix::sparse_complex_matrix_value (bool) const\n{\n  return SparseComplexMatrix (ComplexMatrix (m_matrix));\n}\n\noctave_value\noctave_complex_matrix::as_double () const\n{\n  return m_matrix;\n}\n\noctave_value\noctave_complex_matrix::as_single () const\n{\n  return FloatComplexNDArray (m_matrix);\n}\n\noctave_value\noctave_complex_matrix::diag (octave_idx_type k) const\n{\n  octave_value retval;\n  if (k == 0 && m_matrix.ndims () == 2\n      && (m_matrix.rows () == 1 || m_matrix.columns () == 1))\n    retval = ComplexDiagMatrix (DiagArray2<Complex> (m_matrix));\n  else\n    retval = octave_base_matrix<ComplexNDArray>::diag (k);\n\n  return retval;\n}\n\noctave_value\noctave_complex_matrix::diag (octave_idx_type m, octave_idx_type n) const\n{\n  if (m_matrix.ndims () != 2\n      || (m_matrix.rows () != 1 && m_matrix.columns () != 1))\n    error (\"diag: expecting vector argument\");\n\n  ComplexMatrix mat (m_matrix);\n\n  return mat.diag (m, n);\n}\n\nbool\noctave_complex_matrix::save_ascii (std::ostream& os)\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () > 2)\n    {\n      ComplexNDArray tmp = complex_array_value ();\n\n      os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n      for (int i = 0; i < dv.ndims (); i++)\n        os << ' ' << dv(i);\n\n      os << \"\\n\" << tmp;\n    }\n  else\n    {\n      // Keep this case, rather than use generic code above for backward\n      // compatibility.  Makes load_ascii much more complex!!\n      os << \"# rows: \" << rows () << \"\\n\"\n         << \"# columns: \" << columns () << \"\\n\";\n\n      os << complex_matrix_value ();\n    }\n\n  return true;\n}\n\nbool\noctave_complex_matrix::load_ascii (std::istream& is)\n{\n  string_vector keywords(2);\n\n  keywords[0] = \"ndims\";\n  keywords[1] = \"rows\";\n\n  std::string kw;\n  octave_idx_type val = 0;\n\n  if (! extract_keyword (is, keywords, kw, val, true))\n    error (\"load: failed to extract number of rows and columns\");\n\n  // Set \"C\" locale for the duration of this function to avoid the performance\n  // panelty of frequently switching the locale when reading floating point\n  // values from the stream.\n  char *prev_locale = std::setlocale (LC_ALL, nullptr);\n  std::string old_locale (prev_locale ? prev_locale : \"\");\n  std::setlocale (LC_ALL, \"C\");\n  octave::unwind_action act\n  ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); });\n\n  if (kw == \"ndims\")\n    {\n      int mdims = static_cast<int> (val);\n\n      if (mdims < 0)\n        error (\"load: failed to extract number of dimensions\");\n\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        is >> dv(i);\n\n      if (! is)\n        error (\"load: failed to read dimensions\");\n\n      ComplexNDArray tmp(dv);\n\n      is >> tmp;\n\n      if (! is)\n        error (\"load: failed to load matrix constant\");\n\n      m_matrix = tmp;\n    }\n  else if (kw == \"rows\")\n    {\n      octave_idx_type nr = val;\n      octave_idx_type nc = 0;\n\n      if (nr < 0 || ! extract_keyword (is, \"columns\", nc) || nc < 0)\n        error (\"load: failed to extract number of rows and columns\");\n\n      if (nr > 0 && nc > 0)\n        {\n          ComplexMatrix tmp (nr, nc);\n          is >> tmp;\n          if (! is)\n            error (\"load: failed to load matrix constant\");\n\n          m_matrix = tmp;\n        }\n      else if (nr == 0 || nc == 0)\n        m_matrix = ComplexMatrix (nr, nc);\n      else\n        error (\"unexpected dimensions in octave_complex_matrix::load_ascii - please report this bug\");\n    }\n  else\n    error (\"unexpected dimensions keyword (= '%s') octave_complex_matrix::load_ascii - please report this bug\", kw.c_str ());\n\n  return true;\n}\n\nbool\noctave_complex_matrix::save_binary (std::ostream& os, bool save_as_floats)\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Use negative value for ndims to differentiate with old format!!\n  int32_t tmp = - dv.ndims ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  for (int i = 0; i < dv.ndims (); i++)\n    {\n      tmp = dv(i);\n      os.write (reinterpret_cast<char *> (&tmp), 4);\n    }\n\n  ComplexNDArray m = complex_array_value ();\n  save_type st = LS_DOUBLE;\n  if (save_as_floats)\n    {\n      if (m.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        st = LS_FLOAT;\n    }\n  else if (dv.numel () > 4096) // FIXME: make this configurable.\n    {\n      double max_val, min_val;\n      if (m.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  const Complex *mtmp = m.data ();\n  write_doubles (os, reinterpret_cast<const double *> (mtmp), st,\n                 2 * dv.numel ());\n\n  return true;\n}\n\nbool\noctave_complex_matrix::load_binary (std::istream& is, bool swap,\n                                    octave::mach_info::float_format fmt)\n{\n  char tmp;\n  int32_t mdims;\n  if (! is.read (reinterpret_cast<char *> (&mdims), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&mdims);\n  if (mdims < 0)\n    {\n      mdims = - mdims;\n      int32_t di;\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        {\n          if (! is.read (reinterpret_cast<char *> (&di), 4))\n            return false;\n          if (swap)\n            swap_bytes<4> (&di);\n          dv(i) = di;\n        }\n\n      // Convert an array with a single dimension to be a row vector.\n      // Octave should never write files like this, other software\n      // might.\n\n      if (mdims == 1)\n        {\n          mdims = 2;\n          dv.resize (mdims);\n          dv(1) = dv(0);\n          dv(0) = 1;\n        }\n\n      if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n        return false;\n\n      ComplexNDArray m(dv);\n      Complex *im = m.rwdata ();\n      read_doubles (is, reinterpret_cast<double *> (im),\n                    static_cast<save_type> (tmp), 2 * dv.numel (), swap, fmt);\n\n      if (! is)\n        return false;\n\n      m_matrix = m;\n    }\n  else\n    {\n      int32_t nr, nc;\n      nr = mdims;\n      if (! is.read (reinterpret_cast<char *> (&nc), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&nc);\n      if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n        return false;\n      ComplexMatrix m (nr, nc);\n      Complex *im = m.rwdata ();\n      octave_idx_type len = static_cast<octave_idx_type> (nr) * nc;\n      read_doubles (is, reinterpret_cast<double *> (im),\n                    static_cast<save_type> (tmp), 2*len, swap, fmt);\n\n      if (! is)\n        return false;\n\n      m_matrix = m;\n    }\n  return true;\n}\n\nbool\noctave_complex_matrix::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                                  bool save_as_floats)\n{\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  int rank = dv.ndims ();\n  hid_t space_hid, data_hid, type_hid;\n  space_hid = data_hid = type_hid = -1;\n  bool retval = true;\n  ComplexNDArray m = complex_array_value ();\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  for (int i = 0; i < rank; i++)\n    hdims[i] = dv(rank-i-1);\n\n  space_hid = H5Screate_simple (rank, hdims, nullptr);\n  if (space_hid < 0) return false;\n\n  hid_t save_type_hid = H5T_NATIVE_DOUBLE;\n\n  if (save_as_floats)\n    {\n      if (m.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        save_type_hid = H5T_NATIVE_FLOAT;\n    }\n#if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS)\n  // hdf5 currently doesn't support float/integer conversions\n  else\n    {\n      double max_val, min_val;\n\n      if (m.all_integers (max_val, min_val))\n        save_type_hid\n          = save_type_to_hdf5 (octave::get_save_type (max_val, min_val));\n    }\n#endif\n\n  type_hid = hdf5_make_complex_type (save_type_hid);\n  if (type_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      return false;\n    }\n\n  hid_t complex_type_hid = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);\n  if (complex_type_hid < 0) retval = false;\n\n  if (retval)\n    {\n      const Complex *mtmp = m.data ();\n      if (H5Dwrite (data_hid, complex_type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                    octave_H5P_DEFAULT, mtmp)\n          < 0)\n        {\n          H5Tclose (complex_type_hid);\n          retval = false;\n        }\n    }\n\n  H5Tclose (complex_type_hid);\n  H5Dclose (data_hid);\n  H5Tclose (type_hid);\n  H5Sclose (space_hid);\n\n  return retval;\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n\n  return false;\n#endif\n}\n\nbool\noctave_complex_matrix::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    m_matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t type_hid = H5Dget_type (data_hid);\n\n  hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);\n\n  if (! hdf5_types_compatible (type_hid, complex_type))\n    {\n      H5Tclose (complex_type);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank < 1)\n    {\n      H5Tclose (complex_type);\n      H5Sclose (space_id);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_id, hdims, maxdims);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  if (rank == 1)\n    {\n      dv.resize (2);\n      dv(0) = 1;\n      dv(1) = hdims[0];\n    }\n  else\n    {\n      dv.resize (rank);\n      for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)\n        dv(j) = hdims[i];\n    }\n\n  ComplexNDArray m (dv);\n  Complex *reim = m.rwdata ();\n  if (H5Dread (data_hid, complex_type, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, reim)\n      >= 0)\n    {\n      retval = true;\n      m_matrix = m;\n    }\n\n  H5Tclose (complex_type);\n  H5Sclose (space_id);\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nvoid\noctave_complex_matrix::print_raw (std::ostream& os,\n                                  bool pr_as_read_syntax) const\n{\n  octave_print_internal (os, m_matrix, pr_as_read_syntax,\n                         current_print_indent_level ());\n}\n\nmxArray *\noctave_complex_matrix::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, dims (),\n                                 mxCOMPLEX);\n\n  mwSize nel = numel ();\n\n  const Complex *pdata = m_matrix.data ();\n\n  if (interleaved)\n    {\n      mxComplexDouble *pd\n        = static_cast<mxComplexDouble *> (retval->get_data ());\n\n      for (mwIndex i = 0; i < nel; i++)\n        {\n          pd[i].real = pdata[i].real ();\n          pd[i].imag = pdata[i].imag ();\n        }\n    }\n  else\n    {\n      mxDouble *pr = static_cast<mxDouble *> (retval->get_data ());\n      mxDouble *pi = static_cast<mxDouble *> (retval->get_imag_data ());\n\n      for (mwIndex i = 0; i < nel; i++)\n        {\n          pr[i] = pdata[i].real ();\n          pi[i] = pdata[i].imag ();\n        }\n    }\n\n  return retval;\n}\n\noctave_value\noctave_complex_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    // Mappers handled specially.\n    case umap_real:\n      return ::real (m_matrix);\n    case umap_imag:\n      return ::imag (m_matrix);\n    case umap_conj:\n      return ::conj (m_matrix);\n\n    // Special cases for Matlab compatibility.\n    case umap_xtolower:\n    case umap_xtoupper:\n      return m_matrix;\n\n#define ARRAY_METHOD_MAPPER(UMAP, FCN)        \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (m_matrix.FCN ())\n\n      ARRAY_METHOD_MAPPER (abs, abs);\n      ARRAY_METHOD_MAPPER (isnan, isnan);\n      ARRAY_METHOD_MAPPER (isinf, isinf);\n      ARRAY_METHOD_MAPPER (isfinite, isfinite);\n\n#define ARRAY_MAPPER(UMAP, TYPE, FCN)                 \\\n    case umap_ ## UMAP:                               \\\n      return octave_value (m_matrix.map<TYPE> (FCN))\n\n      ARRAY_MAPPER (acos, Complex, octave::math::acos);\n      ARRAY_MAPPER (acosh, Complex, octave::math::acosh);\n      ARRAY_MAPPER (angle, double, std::arg);\n      ARRAY_MAPPER (arg, double, std::arg);\n      ARRAY_MAPPER (asin, Complex, octave::math::asin);\n      ARRAY_MAPPER (asinh, Complex, octave::math::asinh);\n      ARRAY_MAPPER (atan, Complex, octave::math::atan);\n      ARRAY_MAPPER (atanh, Complex, octave::math::atanh);\n      ARRAY_MAPPER (erf, Complex, octave::math::erf);\n      ARRAY_MAPPER (erfc, Complex, octave::math::erfc);\n      ARRAY_MAPPER (erfcx, Complex, octave::math::erfcx);\n      ARRAY_MAPPER (erfi, Complex, octave::math::erfi);\n      ARRAY_MAPPER (dawson, Complex, octave::math::dawson);\n      ARRAY_MAPPER (ceil, Complex, octave::math::ceil);\n      ARRAY_MAPPER (cos, Complex, std::cos);\n      ARRAY_MAPPER (cosh, Complex, std::cosh);\n      ARRAY_MAPPER (exp, Complex, std::exp);\n      ARRAY_MAPPER (expm1, Complex, octave::math::expm1);\n      ARRAY_MAPPER (fix, Complex, octave::math::fix);\n      ARRAY_MAPPER (floor, Complex, octave::math::floor);\n      ARRAY_MAPPER (log, Complex, std::log);\n      ARRAY_MAPPER (log2, Complex, octave::math::log2);\n      ARRAY_MAPPER (log10, Complex, std::log10);\n      ARRAY_MAPPER (log1p, Complex, octave::math::log1p);\n      ARRAY_MAPPER (round, Complex, octave::math::round);\n      ARRAY_MAPPER (roundb, Complex, octave::math::roundb);\n      ARRAY_MAPPER (signum, Complex, octave::math::signum);\n      ARRAY_MAPPER (sin, Complex, std::sin);\n      ARRAY_MAPPER (sinh, Complex, std::sinh);\n      ARRAY_MAPPER (sqrt, Complex, std::sqrt);\n      ARRAY_MAPPER (tan, Complex, std::tan);\n      ARRAY_MAPPER (tanh, Complex, std::tanh);\n      ARRAY_MAPPER (isna, bool, octave::math::isna);\n\n    default:\n      return octave_base_value::map (umap);\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-cx-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_cx_mat_h)\n#define octave_ov_cx_mat_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-base-mat.h\"\n#include \"ov-typeinfo.h\"\n\n#include \"MatrixType.h\"\n\nclass octave_value_list;\n\n// Complex matrix values.\n\nextern template class OCTINTERP_API octave_base_matrix<ComplexNDArray>;\n\nclass OCTINTERP_API octave_complex_matrix\n  : public octave_base_matrix<ComplexNDArray>\n{\npublic:\n\n  octave_complex_matrix ()\n    : octave_base_matrix<ComplexNDArray> () { }\n\n  octave_complex_matrix (const ComplexNDArray& m)\n    : octave_base_matrix<ComplexNDArray> (m) { }\n\n  octave_complex_matrix (const ComplexMatrix& m)\n    : octave_base_matrix<ComplexNDArray> (m) { }\n\n  octave_complex_matrix (const ComplexMatrix& m, const MatrixType& t)\n    : octave_base_matrix<ComplexNDArray> (m, t) { }\n\n  octave_complex_matrix (const Array<Complex>& m)\n    : octave_base_matrix<ComplexNDArray> (ComplexNDArray (m)) { }\n\n  octave_complex_matrix (const ComplexDiagMatrix& d)\n    : octave_base_matrix<ComplexNDArray> (ComplexMatrix (d)) { }\n\n  octave_complex_matrix (const ComplexRowVector& v)\n    : octave_base_matrix<ComplexNDArray> (ComplexMatrix (v)) { }\n\n  octave_complex_matrix (const ComplexColumnVector& v)\n    : octave_base_matrix<ComplexNDArray> (ComplexMatrix (v)) { }\n\n  octave_complex_matrix (const octave_complex_matrix& cm)\n    : octave_base_matrix<ComplexNDArray> (cm) { }\n\n  ~octave_complex_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_complex_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_complex_matrix (); }\n\n  type_conv_info numeric_demotion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  builtin_type_t builtin_type () const { return btyp_complex; }\n\n  octave_value all (int dim = 0) const { return m_matrix.all (dim); }\n  octave_value any (int dim = 0) const { return m_matrix.any (dim); }\n\n  bool is_complex_matrix () const { return true; }\n\n  bool iscomplex () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  double double_value (bool = false) const;\n\n  float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  float float_scalar_value (bool frc_str_conv = false) const\n  { return float_value (frc_str_conv); }\n\n  NDArray array_value (bool = false) const;\n\n  Matrix matrix_value (bool = false) const;\n\n  FloatMatrix float_matrix_value (bool = false) const;\n\n  Complex complex_value (bool = false) const;\n\n  FloatComplex float_complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const { return m_matrix; }\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const;\n\n  boolNDArray bool_array_value (bool warn = false) const;\n\n  charNDArray char_array_value (bool frc_str_conv = false) const;\n\n  SparseMatrix sparse_matrix_value (bool = false) const;\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value diag (octave_idx_type k = 0) const;\n\n  octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  void increment () { m_matrix += Complex (1.0); }\n\n  void decrement () { m_matrix -= Complex (1.0); }\n\n  void changesign () { m_matrix.changesign (); }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    // Yes, for compatibility, we drop the imaginary part here.\n    return os.write (matrix_value (true), block_size, output_type,\n                     skip, flt_fmt);\n  }\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-cx-sparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"mappers.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-specfun.h\"\n\n#include \"mxarray.h\"\n#include \"errwarn.h\"\n\n#include \"oct-hdf5.h\"\n\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\n#include \"ov-base-sparse.h\"\n#include \"ov-base-sparse.cc\"\n\n#include \"ov-bool-sparse.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_sparse_complex_matrix,\n                                     \"sparse complex matrix\", \"double\");\n\noctave_base_value *\noctave_sparse_complex_matrix::try_narrowing_conversion ()\n{\n  return (matrix.all_elements_are_real ()\n          ? new octave_sparse_matrix (::real (matrix)) : nullptr);\n}\n\ndouble\noctave_sparse_complex_matrix::double_value (bool force_conversion) const\n{\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex sparse matrix\", \"real scalar\");\n\n  // FIXME: maybe this should be a function, valid_as_scalar()\n  if (isempty ())\n    err_invalid_conversion (\"complex sparse matrix\", \"real scalar\");\n\n  if (numel () > 1)\n    warn_implicit_conversion (\"Octave:array-to-scalar\",\n                              \"complex sparse matrix\", \"real scalar\");\n\n  return std::real (matrix(0, 0));\n}\n\nMatrix\noctave_sparse_complex_matrix::matrix_value (bool force_conversion) const\n{\n  Matrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex sparse matrix\", \"real matrix\");\n\n  retval = ::real (matrix.matrix_value ());\n\n  return retval;\n}\n\nComplex\noctave_sparse_complex_matrix::complex_value (bool) const\n{\n  // FIXME: maybe this should be a function, valid_as_scalar()\n  if (isempty ())\n    err_invalid_conversion (\"complex sparse matrix\", \"real scalar\");\n\n  if (numel () > 1)\n    warn_implicit_conversion (\"Octave:array-to-scalar\",\n                              \"complex sparse matrix\", \"real scalar\");\n\n  return matrix(0, 0);\n}\n\nComplexMatrix\noctave_sparse_complex_matrix::complex_matrix_value (bool) const\n{\n  return matrix.matrix_value ();\n}\n\nComplexNDArray\noctave_sparse_complex_matrix::complex_array_value (bool) const\n{\n  return ComplexNDArray (matrix.matrix_value ());\n}\n\ncharNDArray\noctave_sparse_complex_matrix::char_array_value (bool frc_str_conv) const\n{\n  charNDArray retval;\n\n  if (! frc_str_conv)\n    warn_implicit_conversion (\"Octave:num-to-str\",\n                              \"sparse complex matrix\", \"string\");\n  else\n    {\n      retval = charNDArray (dims (), 0);\n      octave_idx_type nc = matrix.cols ();\n      octave_idx_type nr = matrix.rows ();\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = matrix.cidx (j); i < matrix.cidx (j+1); i++)\n          retval(matrix.ridx (i) + nr * j)\n            = static_cast<char> (std::real (matrix.data (i)));\n    }\n\n  return retval;\n}\n\nSparseMatrix\noctave_sparse_complex_matrix::sparse_matrix_value (bool force_conversion) const\n{\n  SparseMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex sparse matrix\",\n                              \"real sparse matrix\");\n\n  retval = ::real (matrix);\n\n  return retval;\n}\n\nSparseBoolMatrix\noctave_sparse_complex_matrix::sparse_bool_matrix_value (bool warn) const\n{\n  if (matrix.any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n  if (warn && (! matrix.all_elements_are_real ()\n               || real (matrix).any_element_not_one_or_zero ()))\n    warn_logical_conversion ();\n\n  return mx_el_ne (matrix, Complex (0.0));\n}\n\noctave_value\noctave_sparse_complex_matrix::as_double () const\n{\n  return this->matrix;\n}\n\nbool\noctave_sparse_complex_matrix::save_binary (std::ostream& os,\n    bool save_as_floats)\n{\n  const dim_vector& dv = this->dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Ensure that additional memory is deallocated\n  matrix.maybe_compress ();\n\n  int nr = dv(0);\n  int nc = dv(1);\n  int nz = nnz ();\n\n  int32_t itmp;\n  // Use negative value for ndims to be consistent with other formats\n  itmp = -2;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  itmp = nr;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  itmp = nc;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  itmp = nz;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  save_type st = LS_DOUBLE;\n  if (save_as_floats)\n    {\n      if (matrix.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        st = LS_FLOAT;\n    }\n  else if (matrix.nnz () > 8192) // FIXME: make this configurable.\n    {\n      double max_val, min_val;\n      if (matrix.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  // add one to the printed indices to go from\n  // zero-based to one-based arrays\n  for (int i = 0; i < nc+1; i++)\n    {\n      octave_quit ();\n      itmp = matrix.cidx (i);\n      os.write (reinterpret_cast<char *> (&itmp), 4);\n    }\n\n  for (int i = 0; i < nz; i++)\n    {\n      octave_quit ();\n      itmp = matrix.ridx (i);\n      os.write (reinterpret_cast<char *> (&itmp), 4);\n    }\n\n  write_doubles (os, reinterpret_cast<const double *> (matrix.data ()), st,\n                 2 * nz);\n\n  return true;\n}\n\nbool\noctave_sparse_complex_matrix::load_binary (std::istream& is, bool swap,\n    octave::mach_info::float_format fmt)\n{\n  int32_t nz, nc, nr, tmp;\n  char ctmp;\n\n  if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n    return false;\n\n  if (swap)\n    swap_bytes<4> (&tmp);\n\n  if (tmp != -2)\n    error (\"load: only 2-D sparse matrices are supported\");\n\n  if (! is.read (reinterpret_cast<char *> (&nr), 4))\n    return false;\n  if (! is.read (reinterpret_cast<char *> (&nc), 4))\n    return false;\n  if (! is.read (reinterpret_cast<char *> (&nz), 4))\n    return false;\n\n  if (swap)\n    {\n      swap_bytes<4> (&nr);\n      swap_bytes<4> (&nc);\n      swap_bytes<4> (&nz);\n    }\n\n  SparseComplexMatrix m (static_cast<octave_idx_type> (nr),\n                         static_cast<octave_idx_type> (nc),\n                         static_cast<octave_idx_type> (nz));\n\n  for (int i = 0; i < nc+1; i++)\n    {\n      octave_quit ();\n      if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&tmp);\n      m.cidx (i) = tmp;\n    }\n\n  for (int i = 0; i < nz; i++)\n    {\n      octave_quit ();\n      if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&tmp);\n      m.ridx (i) = tmp;\n    }\n\n  if (! is.read (reinterpret_cast<char *> (&ctmp), 1))\n    return false;\n\n  read_doubles (is, reinterpret_cast<double *> (m.data ()),\n                static_cast<save_type> (ctmp), 2 * nz, swap, fmt);\n\n  if (! is)\n    return false;\n\n  if (! m.indices_ok ())\n    return false;\n\n  matrix = m;\n\n  return true;\n}\n\nbool\noctave_sparse_complex_matrix::save_hdf5 (octave_hdf5_id loc_id,\n    const char *name,\n    bool save_as_floats)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  // Ensure that additional memory is deallocated\n  matrix.maybe_compress ();\n\n#if defined (HAVE_HDF5_18)\n  hid_t group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT,\n                               octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n#else\n  hid_t group_hid = H5Gcreate (loc_id, name, 0);\n#endif\n  if (group_hid < 0)\n    return false;\n\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n  SparseComplexMatrix m = sparse_complex_matrix_value ();\n  octave_idx_type tmp;\n  hsize_t hdims[2];\n\n  space_hid = H5Screate_simple (0, hdims, nullptr);\n  if (space_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nr\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nr\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  tmp = m.rows ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nc\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nc\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  tmp = m.cols ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nz\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nz\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  tmp = m.nnz ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n\n  hdims[0] = m.cols () + 1;\n  hdims[1] = 1;\n\n  space_hid = H5Screate_simple (2, hdims, nullptr);\n\n  if (space_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"cidx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"cidx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  octave_idx_type *itmp = m.xcidx ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, itmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n\n  hdims[0] = m.nnz ();\n  hdims[1] = 1;\n\n  space_hid = H5Screate_simple (2, hdims, nullptr);\n\n  if (space_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"ridx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"ridx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  itmp = m.xridx ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, itmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  hid_t save_type_hid = H5T_NATIVE_DOUBLE;\n\n  if (save_as_floats)\n    {\n      if (m.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        save_type_hid = H5T_NATIVE_FLOAT;\n    }\n#if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS)\n  // hdf5 currently doesn't support float/integer conversions\n  else\n    {\n      double max_val, min_val;\n\n      if (m.all_integers (max_val, min_val))\n        save_type_hid\n          = save_type_to_hdf5 (octave::get_save_type (max_val, min_val));\n    }\n#endif\n\n  hid_t type_hid = hdf5_make_complex_type (save_type_hid);\n  if (type_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"data\", type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"data\", type_hid, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  hid_t complex_type_hid = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);\n  retval = false;\n  if (complex_type_hid >= 0)\n    {\n      Complex *ctmp = m.xdata ();\n\n      retval = H5Dwrite (data_hid, complex_type_hid, octave_H5S_ALL,\n                         octave_H5S_ALL, octave_H5P_DEFAULT, ctmp) >= 0;\n    }\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n  H5Tclose (type_hid);\n  H5Gclose (group_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_sparse_complex_matrix::load_hdf5 (octave_hdf5_id loc_id,\n    const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  octave_idx_type nr, nc, nz;\n  hid_t group_hid, data_hid, space_hid;\n  hsize_t rank;\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  group_hid = H5Gopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  group_hid = H5Gopen (loc_id, name);\n#endif\n  if (group_hid < 0) return false;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nr\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nr\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL,\n               octave_H5S_ALL, octave_H5P_DEFAULT, &nr) < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nc\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nc\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL,\n               octave_H5S_ALL, octave_H5P_DEFAULT, &nc) < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nz\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nz\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL,\n               octave_H5S_ALL, octave_H5P_DEFAULT, &nz) < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n  SparseComplexMatrix m (static_cast<octave_idx_type> (nr),\n                         static_cast<octave_idx_type> (nc),\n                         static_cast<octave_idx_type> (nz));\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"cidx\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"cidx\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  if (static_cast<int> (hdims[0]) != nc + 1\n      || static_cast<int> (hdims[1]) != 1)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  octave_idx_type *itmp = m.xcidx ();\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL,\n               octave_H5S_ALL, octave_H5P_DEFAULT, itmp) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"ridx\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"ridx\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  if (static_cast<int> (hdims[0]) != nz\n      || static_cast<int> (hdims[1]) != 1)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  itmp = m.xridx ();\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL,\n               octave_H5S_ALL, octave_H5P_DEFAULT, itmp) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"data\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"data\");\n#endif\n  hid_t type_hid = H5Dget_type (data_hid);\n\n  hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);\n\n  if (! hdf5_types_compatible (type_hid, complex_type))\n    {\n      H5Tclose (complex_type);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  if (static_cast<int> (hdims[0]) != nz\n      || static_cast<int> (hdims[1]) != 1)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  Complex *ctmp = m.xdata ();\n\n  if (H5Dread (data_hid, complex_type, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, ctmp) >= 0\n      && m.indices_ok ())\n    {\n      retval = true;\n      matrix = m;\n    }\n\n  H5Tclose (complex_type);\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n  H5Gclose (group_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nmxArray *\noctave_sparse_complex_matrix::as_mxArray (bool interleaved) const\n{\n  mwSize nz = nzmax ();\n  mwSize nr = rows ();\n  mwSize nc = columns ();\n\n  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, nr, nc, nz,\n                                 mxCOMPLEX);\n\n  mwIndex *ir = retval->get_ir ();\n\n  const Complex *pdata = matrix.data ();\n  const octave_idx_type *pridx = matrix.ridx ();\n\n  if (interleaved)\n    {\n      mxComplexDouble *pd\n        = static_cast<mxComplexDouble *> (retval->get_data ());\n\n      for (mwIndex i = 0; i < nz; i++)\n        {\n          pd[i].real = pdata[i].real ();\n          pd[i].imag = pdata[i].imag ();\n\n          ir[i] = pridx[i];\n        }\n    }\n  else\n    {\n      mxDouble *pr = static_cast<mxDouble *> (retval->get_data ());\n      mxDouble *pi = static_cast<mxDouble *> (retval->get_imag_data ());\n\n      for (mwIndex i = 0; i < nz; i++)\n        {\n          pr[i] = pdata[i].real ();\n          pi[i] = pdata[i].imag ();\n\n          ir[i] = pridx[i];\n        }\n    }\n\n  mwIndex *jc = retval->get_jc ();\n\n  const octave_idx_type *pcidx = matrix.cidx ();\n\n  for (mwIndex i = 0; i < nc + 1; i++)\n    jc[i] = pcidx[i];\n\n  return retval;\n}\n\noctave_value\noctave_sparse_complex_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    // Mappers handled specially.\n    case umap_real:\n      return ::real (matrix);\n    case umap_imag:\n      return ::imag (matrix);\n\n#define ARRAY_METHOD_MAPPER(UMAP, FCN)        \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (matrix.FCN ())\n\n      ARRAY_METHOD_MAPPER (abs, abs);\n\n#define ARRAY_MAPPER(UMAP, TYPE, FCN)                 \\\n    case umap_ ## UMAP:                               \\\n      return octave_value (matrix.map<TYPE> (FCN))\n\n      ARRAY_MAPPER (acos, Complex, octave::math::acos);\n      ARRAY_MAPPER (acosh, Complex, octave::math::acosh);\n      ARRAY_MAPPER (angle, double, std::arg);\n      ARRAY_MAPPER (arg, double, std::arg);\n      ARRAY_MAPPER (asin, Complex, octave::math::asin);\n      ARRAY_MAPPER (asinh, Complex, octave::math::asinh);\n      ARRAY_MAPPER (atan, Complex, octave::math::atan);\n      ARRAY_MAPPER (atanh, Complex, octave::math::atanh);\n      ARRAY_MAPPER (erf, Complex, octave::math::erf);\n      ARRAY_MAPPER (erfc, Complex, octave::math::erfc);\n      ARRAY_MAPPER (erfcx, Complex, octave::math::erfcx);\n      ARRAY_MAPPER (erfi, Complex, octave::math::erfi);\n      ARRAY_MAPPER (dawson, Complex, octave::math::dawson);\n      ARRAY_MAPPER (ceil, Complex, octave::math::ceil);\n      ARRAY_MAPPER (conj, Complex, std::conj<double>);\n      ARRAY_MAPPER (cos, Complex, std::cos);\n      ARRAY_MAPPER (cosh, Complex, std::cosh);\n      ARRAY_MAPPER (exp, Complex, std::exp);\n      ARRAY_MAPPER (expm1, Complex, octave::math::expm1);\n      ARRAY_MAPPER (fix, Complex, octave::math::fix);\n      ARRAY_MAPPER (floor, Complex, octave::math::floor);\n      ARRAY_MAPPER (log, Complex, std::log);\n      ARRAY_MAPPER (log2, Complex, octave::math::log2);\n      ARRAY_MAPPER (log10, Complex, std::log10);\n      ARRAY_MAPPER (log1p, Complex, octave::math::log1p);\n      ARRAY_MAPPER (round, Complex, octave::math::round);\n      ARRAY_MAPPER (roundb, Complex, octave::math::roundb);\n      ARRAY_MAPPER (signum, Complex, octave::math::signum);\n      ARRAY_MAPPER (sin, Complex, std::sin);\n      ARRAY_MAPPER (sinh, Complex, std::sinh);\n      ARRAY_MAPPER (sqrt, Complex, std::sqrt);\n      ARRAY_MAPPER (tan, Complex, std::tan);\n      ARRAY_MAPPER (tanh, Complex, std::tanh);\n      ARRAY_MAPPER (isnan, bool, octave::math::isnan);\n      ARRAY_MAPPER (isna, bool, octave::math::isna);\n      ARRAY_MAPPER (isinf, bool, octave::math::isinf);\n      ARRAY_MAPPER (isfinite, bool, octave::math::isfinite);\n\n    default: // Attempt to go via dense matrix.\n      return octave_base_sparse<SparseComplexMatrix>::map (umap);\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-cx-sparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_cx_sparse_h)\n#define octave_ov_cx_sparse_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n\n#include \"CSparse.h\"\n#include \"ov-base-sparse.h\"\n#include \"ov-re-sparse.h\"\n\nclass octave_value_list;\n\nextern template class OCTINTERP_API\noctave_base_sparse<SparseComplexMatrix>;\n\nclass OCTINTERP_API octave_sparse_complex_matrix\n  : public octave_base_sparse<SparseComplexMatrix>\n{\npublic:\n\n  octave_sparse_complex_matrix ()\n    : octave_base_sparse<SparseComplexMatrix> () { }\n\n  octave_sparse_complex_matrix (const ComplexNDArray& m)\n    : octave_base_sparse<SparseComplexMatrix> (SparseComplexMatrix (m)) { }\n\n  octave_sparse_complex_matrix (const ComplexMatrix& m)\n    : octave_base_sparse<SparseComplexMatrix> (SparseComplexMatrix (m)) { }\n\n  octave_sparse_complex_matrix (const SparseComplexMatrix& m)\n    : octave_base_sparse<SparseComplexMatrix> (m) { }\n\n  octave_sparse_complex_matrix (const SparseComplexMatrix& m,\n                                const MatrixType& t)\n    : octave_base_sparse<SparseComplexMatrix> (m, t) { }\n\n  octave_sparse_complex_matrix (const MSparse<Complex>& m)\n    : octave_base_sparse<SparseComplexMatrix> (m) { }\n\n  octave_sparse_complex_matrix (const MSparse<Complex>& m,\n                                const MatrixType& t)\n    : octave_base_sparse<SparseComplexMatrix> (m, t) { }\n\n  octave_sparse_complex_matrix (const Sparse<Complex>& m,\n                                const MatrixType& t)\n    : octave_base_sparse<SparseComplexMatrix> (SparseComplexMatrix (m), t) { }\n\n  octave_sparse_complex_matrix (const Sparse<Complex>& m)\n    : octave_base_sparse<SparseComplexMatrix> (SparseComplexMatrix (m)) { }\n\n  octave_sparse_complex_matrix (const octave_sparse_complex_matrix& cm)\n    : octave_base_sparse<SparseComplexMatrix> (cm) { }\n\n  ~octave_sparse_complex_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_sparse_complex_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_sparse_complex_matrix (); }\n\n  octave_base_value * try_narrowing_conversion ();\n\n  builtin_type_t builtin_type () const { return btyp_complex; }\n\n  bool is_complex_matrix () const { return true; }\n\n  bool iscomplex () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  double double_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  Matrix matrix_value (bool = false) const;\n\n  Complex complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const;\n\n  charNDArray char_array_value (bool frc_str_conv = false) const;\n\n  SparseMatrix sparse_matrix_value (bool = false) const;\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  { return matrix; }\n\n  SparseBoolMatrix sparse_bool_matrix_value (bool warn = false) const;\n\n  octave_value as_double () const;\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-dld-fcn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"file-ops.h\"\n#include \"oct-shlib.h\"\n\n#include \"defaults.h\"\n#include \"dynamic-ld.h\"\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"ovl.h\"\n#include \"ov-dld-fcn.h\"\n#include \"ov.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_dld_function,\n                                     \"dynamically-linked function\",\n                                     \"dynamically-linked function\");\n\noctave_dld_function::octave_dld_function\n(octave_builtin::fcn ff, const octave::dynamic_library& shl,\n const std::string& nm, const std::string& ds)\n  : octave_builtin (ff, nm, ds), m_sh_lib (shl)\n{\n  mark_fcn_file_up_to_date (time_parsed ());\n\n  std::string file_name = fcn_file_name ();\n\n  static const std::string canonical_oct_file_dir\n    = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ());\n  static const std::string oct_file_dir\n    = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir ()\n      : canonical_oct_file_dir;\n\n  m_system_fcn_file\n    = (! file_name.empty ()\n       && oct_file_dir == file_name.substr (0, oct_file_dir.length ()));\n}\n\noctave_dld_function::octave_dld_function\n(octave_builtin::meth mm, const octave::dynamic_library& shl,\n const std::string& nm, const std::string& ds)\n  : octave_builtin (mm, nm, ds), m_sh_lib (shl)\n{\n  mark_fcn_file_up_to_date (time_parsed ());\n\n  std::string file_name = fcn_file_name ();\n\n  static const std::string canonical_oct_file_dir\n    = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ());\n  static const std::string oct_file_dir\n    = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir ()\n      : canonical_oct_file_dir;\n\n  m_system_fcn_file\n    = (! file_name.empty ()\n       && oct_file_dir == file_name.substr (0, oct_file_dir.length ()));\n}\n\noctave_dld_function::~octave_dld_function ()\n{\n  octave::dynamic_loader& dyn_loader = octave::__get_dynamic_loader__ ();\n\n  dyn_loader.remove_oct (m_name, m_sh_lib);\n}\n\nstd::string\noctave_dld_function::fcn_file_name () const\n{\n  return m_sh_lib.file_name ();\n}\n\noctave::sys::time\noctave_dld_function::time_parsed () const\n{\n  return m_sh_lib.time_loaded ();\n}\n\n// Note: this wrapper around the octave_dld_function constructor is\n//       necessary to work around a MSVC limitation handling in\n//       virtual destructors that prevents unloading a dynamic module\n//       before *all* objects (of class using a virtual dtor) have\n//       been fully deleted; indeed, MSVC attaches auto-generated code\n//       (scalar deleting destructor) to objects created in a dynamic\n//       module, and this code will be executed in the dynamic module\n//       context at object deletion; unloading the dynamic module\n//       before objects have been deleted will make the \"delete\" code\n//       of objects to point to an invalid code segment.\n\noctave_dld_function *\noctave_dld_function::create (octave_builtin::fcn ff,\n                             const octave::dynamic_library& shl,\n                             const std::string& nm, const std::string& ds)\n{\n  return new octave_dld_function (ff, shl, nm, ds);\n}\n\noctave_dld_function *\noctave_dld_function::create (octave_builtin::meth mm,\n                             const octave::dynamic_library& shl,\n                             const std::string& nm, const std::string& ds)\n{\n  return new octave_dld_function (mm, shl, nm, ds);\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-dld-fcn.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_dld_fcn_h)\n#define octave_ov_dld_fcn_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"oct-shlib.h\"\n\n#include \"ov-fcn.h\"\n#include \"ov-builtin.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value;\nclass octave_value_list;\n\n// Dynamically-linked functions.\n\nclass OCTINTERP_API octave_dld_function : public octave_builtin\n{\npublic:\n\n  octave_dld_function ()\n    : m_sh_lib (), m_time_checked (), m_system_fcn_file ()\n  { }\n\n  octave_dld_function (octave_builtin::fcn ff,\n                       const octave::dynamic_library& shl,\n                       const std::string& nm = \"\",\n                       const std::string& ds = \"\");\n\n  octave_dld_function (octave_builtin::meth mm,\n                       const octave::dynamic_library& shl,\n                       const std::string& nm = \"\",\n                       const std::string& ds = \"\");\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_dld_function)\n\n  ~octave_dld_function ();\n\n  void mark_fcn_file_up_to_date (const octave::sys::time& t)\n  { m_time_checked = t; }\n\n  std::string fcn_file_name () const;\n\n  octave::sys::time time_parsed () const;\n\n  octave::sys::time time_checked () const { return m_time_checked; }\n\n  bool is_system_fcn_file () const { return m_system_fcn_file; }\n\n  bool is_builtin_function () const { return false; }\n\n  bool is_dld_function () const { return true; }\n\n  static octave_dld_function * create (octave_builtin::fcn ff,\n                                      const octave::dynamic_library& shl,\n                                      const std::string& nm = \"\",\n                                      const std::string& ds = \"\");\n\n  static octave_dld_function * create (octave_builtin::meth mm,\n                                      const octave::dynamic_library& shl,\n                                      const std::string& nm = \"\",\n                                      const std::string& ds = \"\");\n\n  octave::dynamic_library get_shlib () const\n  { return m_sh_lib; }\n\nprivate:\n\n  octave::dynamic_library m_sh_lib;\n\n  // The time the file was last checked to see if it needs to be\n  // parsed again.\n  octave::sys::time m_time_checked;\n\n  // True if this function came from a file that is considered to be a\n  // system function.  This affects whether we check the time stamp\n  // on the file to see if it has changed.\n  bool m_system_fcn_file;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-fcn-handle.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <list>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"file-ops.h\"\n#include \"oct-locbuf.h\"\n\n#include \"defaults.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"file-stat.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"oct-env.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-map.h\"\n#include \"ov-base.h\"\n#include \"ov-cell.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-usr-fcn.h\"\n#include \"parse.h\"\n#include \"pr-output.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-assign.h\"\n#include \"pt-cmd.h\"\n#include \"pt-eval.h\"\n#include \"pt-exp.h\"\n#include \"pt-idx.h\"\n#include \"pt-misc.h\"\n#include \"pt-pr-code.h\"\n#include \"pt-stmt.h\"\n#include \"stack-frame.h\"\n#include \"syminfo.h\"\n#include \"symscope.h\"\n#include \"unwind-prot.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-ascii-helper.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-oct-binary.h\"\n#include \"ls-utils.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_fcn_handle,\n                                     \"function handle\",\n                                     \"function_handle\");\n\nconst std::string octave_fcn_handle::anonymous (\"@<anonymous>\");\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass invalid_fcn_handle : public base_fcn_handle\n{\npublic:\n\n  invalid_fcn_handle () : base_fcn_handle (\"<invalid>\") { }\n\n  invalid_fcn_handle (const invalid_fcn_handle&) = default;\n\n  ~invalid_fcn_handle () = default;\n\n  invalid_fcn_handle * clone () const\n  {\n    return new invalid_fcn_handle (*this);\n  }\n\n  std::string type () const { return \"<invalid>\"; }\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n};\n\n// Create a handle to an unnamed internal function.  There will be no\n// way to save and reload it.  See, for example, the F__fltk_check__\n// function in __init_fltk__.cc.\n\nclass internal_fcn_handle : public base_fcn_handle\n{\npublic:\n\n  internal_fcn_handle (const octave_value& fcn)\n    : base_fcn_handle (\"<internal>\"), m_fcn (fcn)\n  { }\n\n  internal_fcn_handle (const internal_fcn_handle&) = default;\n\n  ~internal_fcn_handle () = default;\n\n  internal_fcn_handle * clone () const\n  {\n    return new internal_fcn_handle (*this);\n  }\n\n  std::string type () const { return \"<internal>\"; }\n\n  bool is_internal () const { return true; }\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n\n  // FIXME: These must go away.  They don't do the right thing for\n  // scoping or overloads.\n  octave_function * function_value (bool = false)\n  {\n    return m_fcn.function_value ();\n  }\n\n  octave_user_function * user_function_value (bool = false)\n  {\n    return m_fcn.user_function_value ();\n  }\n\n  octave_value fcn_val () { return m_fcn; }\n\n  // Should be const.\n  octave_scalar_map info ();\n\n  friend bool is_equal_to (const internal_fcn_handle& fh1,\n                           const internal_fcn_handle& fh2);\n\nprivate:\n\n  octave_value m_fcn;\n};\n\nclass simple_fcn_handle : public base_fcn_handle\n{\npublic:\n\n  // FIXME: octaveroot is temporary information used when loading\n  // handles.  Can we avoid using it in the constructor?\n\n  simple_fcn_handle (const std::string& name = \"\",\n                     const std::string& file = \"\",\n                     const std::string& /*octaveroot*/ = \"\")\n    : base_fcn_handle (name, file), m_fcn ()\n  { }\n\n  simple_fcn_handle (const octave_value& fcn, const std::string& name)\n    : base_fcn_handle (name), m_fcn (fcn)\n  {\n    if (m_fcn.is_defined ())\n      {\n        octave_function *oct_fcn = m_fcn.function_value ();\n\n        if (oct_fcn)\n          m_file = oct_fcn->fcn_file_name ();\n      }\n  }\n\n  simple_fcn_handle (const simple_fcn_handle&) = default;\n\n  ~simple_fcn_handle () = default;\n\n  simple_fcn_handle * clone () const\n  {\n    return new simple_fcn_handle (*this);\n  }\n\n  std::string type () const { return \"simple\"; }\n\n  bool is_simple () const { return true; }\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n\n  // FIXME: These must go away.  They don't do the right thing for\n  // scoping or overloads.\n  octave_function * function_value (bool);\n\n  octave_user_function * user_function_value (bool);\n\n  octave_value fcn_val ();\n\n  // Should be const.\n  octave_scalar_map info ();\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_hid, const char *name,\n                  bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid,\n                  octave_hdf5_id& type_hid);\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax,\n                  int current_print_indent_level) const;\n\n  friend bool is_equal_to (const simple_fcn_handle& fh1,\n                           const simple_fcn_handle& fh2);\n\nprivate:\n\n  octave_value m_fcn;\n};\n\nclass scoped_fcn_handle : public base_fcn_handle\n{\npublic:\n\n  // FIXME: octaveroot is temporary information used when loading\n  // handles.  Can we avoid using it in the constructor?\n\n  scoped_fcn_handle (const std::string& name = \"\",\n                     const std::string& file = \"\",\n                     const std::string& /*octaveroot*/ = \"\")\n    : base_fcn_handle (name, file)\n  { }\n\n  scoped_fcn_handle (const octave_value& fcn, const std::string& name,\n                     const std::list<std::string>& parentage);\n\n  scoped_fcn_handle (const scoped_fcn_handle&) = default;\n\n  ~scoped_fcn_handle () = default;\n\n  scoped_fcn_handle * clone () const\n  {\n    return new scoped_fcn_handle (*this);\n  }\n\n  std::string type () const { return \"scopedfunction\"; }\n\n  bool is_scoped () const { return true; }\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n\n  // FIXME: These must go away.  They don't do the right thing for\n  // scoping or overloads.\n  octave_function * function_value (bool = false)\n  {\n    return m_fcn.function_value ();\n  }\n\n  octave_user_function * user_function_value (bool = false)\n  {\n    return m_fcn.user_function_value ();\n  }\n\n  octave_value fcn_val () { return m_fcn; }\n\n  // Should be const.\n  octave_scalar_map info ();\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                  bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid,\n                  octave_hdf5_id& type_hid);\n\n  void print_raw (std::ostream&, bool pr_as_read_syntax,\n                  int current_print_indent_level) const;\n\n  friend bool is_equal_to (const scoped_fcn_handle& fh1,\n                           const scoped_fcn_handle& fh2);\n\nprotected:\n\n  void find_function ();\n\n  // The function we are handling.\n  octave_value m_fcn;\n\n  // List of parent function names.  The first element is the name of\n  // m_fcn.\n  std::list<std::string> m_parentage;\n};\n\nclass base_nested_fcn_handle : public base_fcn_handle\n{\npublic:\n\n  // FIXME: octaveroot is temporary information used when loading\n  // handles.  Can we avoid using it in the constructor?\n\n  base_nested_fcn_handle (const std::string& name = \"\",\n                          const std::string& file = \"\",\n                          const std::string& /*octaveroot*/ = \"\")\n    : base_fcn_handle (name, file)\n  { }\n\n  base_nested_fcn_handle (const octave_value& fcn, const std::string& name)\n    : base_fcn_handle (name), m_fcn (fcn)\n  { }\n\n  std::string type () const { return \"nested\"; }\n\n  using base_fcn_handle::is_nested;\n\n  bool is_nested () const { return true; }\n\n  // FIXME: These must go away.  They don't do the right thing for\n  // scoping or overloads.\n  octave_function * function_value (bool = false)\n  {\n    return m_fcn.function_value ();\n  }\n\n  octave_user_function * user_function_value (bool = false)\n  {\n    return m_fcn.user_function_value ();\n  }\n\n  octave_value fcn_val () { return m_fcn; }\n\n  virtual octave_value workspace () const = 0;\n\n  // Should be const.\n  octave_scalar_map info ();\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                  bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid,\n                  octave_hdf5_id& type_hid);\n\n  void print_raw (std::ostream&, bool pr_as_read_syntax,\n                  int current_print_indent_level) const;\n\nprotected:\n\n  // The function we are handling.\n  octave_value m_fcn;\n};\n\nclass nested_fcn_handle : public base_nested_fcn_handle\n{\npublic:\n\n  // FIXME: octaveroot is temporary information used when loading\n  // handles.  Can we avoid using it in the constructor?\n\n  nested_fcn_handle (const std::string& name = \"\",\n                     const std::string& file = \"\",\n                     const std::string& octaveroot = \"\")\n    : base_nested_fcn_handle (name, file, octaveroot)\n  { }\n\n  nested_fcn_handle (const octave_value& fcn, const std::string& name,\n                     const std::shared_ptr<stack_frame>& stack_context)\n    : base_nested_fcn_handle (fcn, name), m_stack_context (stack_context)\n  {\n    if (m_stack_context)\n      m_stack_context->mark_closure_context ();\n  }\n\n  nested_fcn_handle (const nested_fcn_handle&) = default;\n\n  ~nested_fcn_handle () = default;\n\n  using base_nested_fcn_handle::is_nested;\n\n  bool is_nested (const std::shared_ptr<stack_frame>& frame) const\n  {\n    if (frame == m_stack_context)\n      return true;\n\n    // We need to check each of the access links of the context frame, for 'frame' too\n    auto nxt = m_stack_context->access_link ();\n    while (nxt)\n      {\n        if (nxt == frame)\n          return true;\n        nxt = nxt->access_link ();\n      }\n\n    return false;\n  }\n\n  nested_fcn_handle * clone () const\n  {\n    return new nested_fcn_handle (*this);\n  }\n\n  octave_value make_weak_nested_handle () const;\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n\n  octave_value workspace () const;\n\n  friend bool is_equal_to (const nested_fcn_handle& fh1,\n                           const nested_fcn_handle& fh2);\n\n  std::shared_ptr<stack_frame> stack_context () const\n  {\n    return m_stack_context;\n  }\n\nprotected:\n\n  // Pointer to closure stack frames.\n  std::shared_ptr<stack_frame> m_stack_context;\n};\n\nclass weak_nested_fcn_handle : public base_nested_fcn_handle\n{\npublic:\n\n  weak_nested_fcn_handle (const nested_fcn_handle& nfh)\n    : base_nested_fcn_handle (nfh), m_stack_context (nfh.stack_context ())\n  { }\n\n  weak_nested_fcn_handle (const weak_nested_fcn_handle&) = default;\n\n  ~weak_nested_fcn_handle () = default;\n\n  weak_nested_fcn_handle * clone () const\n  {\n    return new weak_nested_fcn_handle (*this);\n  }\n\n  bool is_weak_nested () const { return true; }\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n\n  octave_value workspace () const;\n\n  friend bool is_equal_to (const weak_nested_fcn_handle& fh1,\n                           const weak_nested_fcn_handle& fh2);\n\nprotected:\n\n  // Pointer to closure stack frames.\n  std::weak_ptr<stack_frame> m_stack_context;\n};\n\nclass class_simple_fcn_handle : public base_fcn_handle\n{\npublic:\n\n  // FIXME: octaveroot is temporary information used when loading\n  // handles.  Can we avoid using it in the constructor?\n\n  class_simple_fcn_handle (const std::string& name,\n                           const std::string& file,\n                           const std::string& /*octaveroot*/)\n    : base_fcn_handle (name, file)\n  { }\n\n  // FIXME: is the method name supposed to be just the method name or\n  // also contain the object name?\n\n  class_simple_fcn_handle (const std::string& class_nm,\n                           const std::string& meth_nm);\n\n  class_simple_fcn_handle (const octave_value& fcn,\n                           const std::string& class_nm,\n                           const std::string& meth_nm);\n\n  class_simple_fcn_handle (const octave_value& obj, const octave_value& fcn,\n                           const std::string& class_nm,\n                           const std::string& meth_nm);\n\n  class_simple_fcn_handle (const class_simple_fcn_handle&) = default;\n\n  ~class_simple_fcn_handle () = default;\n\n  class_simple_fcn_handle * clone () const\n  {\n    return new class_simple_fcn_handle (*this);\n  }\n\n  std::string type () const { return \"classsimple\"; }\n\n  bool is_class_simple () const { return true; }\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n\n  // FIXME: These must go away.  They don't do the right thing for\n  // scoping or overloads.\n  octave_function * function_value (bool = false)\n  {\n    // FIXME: Shouldn't the lookup rules here match those used in the\n    // call method?\n\n    if (m_fcn.is_defined ())\n      return m_fcn.function_value ();\n\n    symbol_table& symtab = __get_symbol_table__ ();\n\n    // FIXME: is caching the correct thing to do?\n    // Cache this value so that the pointer will be valid as long as the\n    // function handle object is valid.\n\n    // FIXME: This should probably dispatch to the respective class method.\n    // But that breaks if a function handle is used in a class method with,\n    // e.g., bsxfun with arguments of a different class (see bug #59661).\n    // m_fcn = symtab.find_method (m_name, m_dispatch_class);\n    m_fcn = symtab.find_function (m_name, octave_value_list ());\n\n    return m_fcn.is_defined () ? m_fcn.function_value () : nullptr;\n  }\n\n  octave_user_function * user_function_value (bool = false)\n  {\n    return m_fcn.user_function_value ();\n  }\n\n  octave_value fcn_val () { return m_fcn; }\n\n  // Should be const.\n  octave_scalar_map info ();\n\n  std::string dispatch_class () const { return m_dispatch_class; }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                  bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid,\n                  octave_hdf5_id& type_hid);\n\n  void print_raw (std::ostream&, bool pr_as_read_syntax,\n                  int current_print_indent_level) const;\n\n  friend bool is_equal_to (const class_simple_fcn_handle& fh1,\n                           const class_simple_fcn_handle& fh2);\n\nprotected:\n\n  // The object containing the method we are handing.\n  octave_value m_obj;\n\n  // The method we are handling.\n  octave_value m_fcn;\n\n  // Name of the class that m_fcn belongs to.\n  std::string m_dispatch_class;\n};\n\n// Handles to anonymous functions are similar to handles to nested\n// functions.  If they are created in a context that contains nested\n// functions, then they store a link to the parent call stack frames\n// that are active when they are created.  These call stack frames\n// (closure frames) provide access to variables needed by any nested\n// functions that are called from the anonymous function.  Anonymous\n// functions also store a list of values from their parent scope\n// corresponding to the symbols in the anonymous function.  This list\n// of values captures the variable values that are visible in the\n// scope where they are created.\n//\n// Note that because handles to anonymous and nested functions capture\n// call stack frames when they are created, they will cause deletion\n// of the values in those frames to be deferred until the handles to\n// the anonymous or nested functions are deleted.\n//\n// Would it be possible to avoid storing the closure frames for\n// handles to anonymous functions if we can determine that the\n// anonymous function has no unbound variables (or parameters, which\n// could be handles to nested functions?) or if it is not created in a\n// context that contains nested functions?\n//\n// Would it be possible to define anonymous functions as a special\n// type of nested function object that also has an variable\n// initialization list associated with it?\n\nclass base_anonymous_fcn_handle : public base_fcn_handle\n{\npublic:\n\n  static const std::string anonymous;\n\n  // Setting NAME here is a bit of a kluge to cope with a bad choice\n  // made to append the number of local variables to the @<anonymous>\n  // tag in the binary file format.  See also the save_binary and\n  // load_binary functions.\n\n  base_anonymous_fcn_handle (const std::string& name = \"\")\n    : base_fcn_handle (name)\n  { }\n\n  base_anonymous_fcn_handle (const octave_value& fcn,\n                             const stack_frame::local_vars_map& local_vars)\n    : base_fcn_handle (anonymous), m_fcn (fcn), m_local_vars (local_vars)\n  { }\n\n  base_anonymous_fcn_handle (const base_anonymous_fcn_handle&) = default;\n\n  ~base_anonymous_fcn_handle () = default;\n\n  std::string type () const { return \"anonymous\"; }\n\n  bool is_anonymous () const { return true; }\n\n  // FIXME: These must go away.  They don't do the right thing for\n  // scoping or overloads.\n  octave_function * function_value (bool = false)\n  {\n    return m_fcn.function_value ();\n  }\n\n  octave_user_function * user_function_value (bool = false)\n  {\n    return m_fcn.user_function_value ();\n  }\n\n  octave_value fcn_val () { return m_fcn; }\n\n  virtual octave_value workspace () const = 0;\n\n  // Should be const.\n  octave_scalar_map info ();\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                  bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid,\n                  octave_hdf5_id& type_hid);\n\n  void print_raw (std::ostream&, bool pr_as_read_syntax,\n                  int current_print_indent_level) const;\n\n  // Anonymous function handles are printed without a newline.\n  bool print_as_scalar () const { return false; }\n\n  bool parse (const std::string& fcn_text);\n\nprotected:\n\n  // The function we are handling.\n  octave_value m_fcn;\n\n  // List of captured variable values for anonymous fucntions.\n  stack_frame::local_vars_map m_local_vars;\n};\n\nclass anonymous_fcn_handle : public base_anonymous_fcn_handle\n{\npublic:\n\n  using base_anonymous_fcn_handle::anonymous;\n\n  // Setting NAME here is a bit of a kluge to cope with a bad choice\n  // made to append the number of local variables to the @<anonymous>\n  // tag in the binary file format.  See also the save_binary and\n  // load_binary functions.\n\n  anonymous_fcn_handle (const std::string& name = \"\")\n    : base_anonymous_fcn_handle (name), m_stack_context ()\n  { }\n\n  anonymous_fcn_handle (const octave_value& fcn,\n                        const stack_frame::local_vars_map& local_vars,\n                        const std::shared_ptr<stack_frame>& stack_context = std::shared_ptr<stack_frame> ());\n\n  anonymous_fcn_handle (const anonymous_fcn_handle&) = default;\n\n  ~anonymous_fcn_handle () = default;\n\n  anonymous_fcn_handle * clone () const\n  {\n    return new anonymous_fcn_handle (*this);\n  }\n\n  octave_value make_weak_anonymous_handle () const;\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n\n  octave_value workspace () const;\n\n  friend bool is_equal_to (const anonymous_fcn_handle& fh1,\n                           const anonymous_fcn_handle& fh2);\n\n  std::shared_ptr<stack_frame> stack_context () const\n  {\n    return m_stack_context;\n  }\n\nprotected:\n\n  // Pointer to closure stack frames.\n  std::shared_ptr<stack_frame> m_stack_context;\n};\n\nclass weak_anonymous_fcn_handle : public base_anonymous_fcn_handle\n{\npublic:\n\n  using base_anonymous_fcn_handle::anonymous;\n\n  weak_anonymous_fcn_handle (const anonymous_fcn_handle& afh)\n    : base_anonymous_fcn_handle (afh), m_stack_context (afh.stack_context ())\n  { }\n\n  weak_anonymous_fcn_handle (const weak_anonymous_fcn_handle&) = default;\n\n  ~weak_anonymous_fcn_handle () = default;\n\n  weak_anonymous_fcn_handle * clone () const\n  {\n    return new weak_anonymous_fcn_handle (*this);\n  }\n\n  bool is_weak_anonymous () const { return true; }\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n\n  octave_value workspace () const;\n\n  friend bool is_equal_to (const weak_anonymous_fcn_handle& fh1,\n                           const weak_anonymous_fcn_handle& fh2);\n\nprotected:\n\n  // Pointer to closure stack frames.\n  std::weak_ptr<stack_frame> m_stack_context;\n};\n\nextern bool is_equal_to (const anonymous_fcn_handle& fh1,\n                         const anonymous_fcn_handle& fh2);\n\nstatic void\nerr_invalid_fcn_handle (const std::string& name)\n{\n  error (\"invalid function handle, unable to find function for @%s\",\n         name.c_str ());\n}\n\noctave_value\nbase_fcn_handle::make_weak_nested_handle () const\n{\n  std::string type_str = type ();\n  error (\"invalid conversion from %s handle to weak nestead handle\",\n         type_str.c_str ());\n}\n\noctave_value\nbase_fcn_handle::make_weak_anonymous_handle () const\n{\n  std::string type_str = type ();\n  error (\"invalid conversion from %s handle to weak anonymous handle\",\n         type_str.c_str ());\n}\n\noctave_value_list\nbase_fcn_handle::subsref (const std::string& type,\n                          const std::list<octave_value_list>& idx,\n                          int nargout)\n{\n  octave_value_list retval;\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        int tmp_nargout = (type.length () > 1 && nargout == 0) ? 1 : nargout;\n\n        retval = call (tmp_nargout, idx.front ());\n      }\n      break;\n\n    case '{':\n    case '.':\n      error (\"function handle cannot be indexed with %c\", type[0]);\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in base_fcn_handle::subsref - please report this bug\");\n    }\n\n  // FIXME: perhaps there should be an\n  // octave_value_list::next_subsref member function?  See also\n  // octave_builtin::subsref.\n\n  if (idx.size () > 1)\n    retval = retval(0).next_subsref (nargout, type, idx);\n\n  return retval;\n}\n\noctave_value\nbase_fcn_handle::convert_to_str_internal (bool, bool, char type) const\n{\n  std::ostringstream buf;\n  print_raw (buf, true, 0);\n  return octave_value (buf.str (), type);\n}\n\nbool\nbase_fcn_handle::save_ascii (std::ostream&)\n{\n  unimplemented (\"save\", \"text\");\n\n  return true;\n}\n\nbool\nbase_fcn_handle::load_ascii (std::istream&)\n{\n  unimplemented (\"load\", \"text\");\n\n  return true;\n}\n\nbool\nbase_fcn_handle::save_binary (std::ostream&, bool)\n{\n  unimplemented (\"save\", \"binary\");\n\n  return true;\n}\n\nbool\nbase_fcn_handle::load_binary (std::istream&, bool, mach_info::float_format)\n{\n  unimplemented (\"load\", \"binary\");\n\n  return true;\n}\n\nbool\nbase_fcn_handle::save_hdf5 (octave_hdf5_id, const char *, bool)\n{\n  unimplemented (\"save\", \"hdf5\");\n\n  return true;\n}\n\nbool\nbase_fcn_handle::load_hdf5 (octave_hdf5_id&, octave_hdf5_id&, octave_hdf5_id&)\n{\n  unimplemented (\"load\", \"hdf5\");\n\n  return true;\n}\n\nvoid\nbase_fcn_handle::warn_load (const char *file_type) const\n{\n  std::string obj_type = type ();\n\n  warning_with_id\n  (\"Octave:load-save-unavailable\",\n   \"%s: loading %s files not available in this version of Octave\",\n   obj_type.c_str (), file_type);\n}\n\nvoid\nbase_fcn_handle::warn_save (const char *file_type) const\n{\n  std::string obj_type = type ();\n\n  warning_with_id\n  (\"Octave:load-save-unavailable\",\n   \"%s: saving %s files not available in this version of Octave\",\n   obj_type.c_str (), file_type);\n}\n\nvoid\nbase_fcn_handle::unimplemented (const char *op, const char *fmt) const\n{\n  std::string htype = type ();\n\n  warning (\"%s for %s handles with %s format is not implemented\",\n           op, htype.c_str (), fmt);\n}\n\noctave_value_list\ninvalid_fcn_handle::call (int, const octave_value_list&)\n{\n  error (\"invalid call to invalid function handle\");\n}\n\noctave_value_list\ninternal_fcn_handle::call (int nargout, const octave_value_list& args)\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  return interp.feval (m_fcn, args, nargout);\n}\n\noctave_scalar_map\ninternal_fcn_handle::info ()\n{\n  octave_scalar_map m;\n\n  m.setfield (\"function\", fcn_name ());\n  m.setfield (\"type\", type ());\n  m.setfield (\"file\", \"\");\n\n  return m;\n}\n\nbool\nis_equal_to (const internal_fcn_handle& fh1,\n             const internal_fcn_handle& fh2)\n{\n  if (fh1.m_name == fh2.m_name\n      && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ())\n    return fh1.m_fcn.is_copy_of (fh2.m_fcn);\n  else\n    return false;\n}\n\noctave_value_list\nsimple_fcn_handle::call (int nargout, const octave_value_list& args)\n{\n  // FIXME: if m_name has a '.' in the name, lookup first component.  If\n  // it is a classdef meta object, then build TYPE and IDX arguments and\n  // make a subsref call using them.\n\n  interpreter& interp = __get_interpreter__ ();\n\n  octave_value fcn_to_call;\n\n  // The following code is similar to part of\n  // tree_evaluator::visit_index_expression but simpler because it\n  // handles a more restricted case.\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  std::size_t pos = m_name.find ('.');\n\n  if (pos != std::string::npos)\n    {\n      // FIXME: check to see which of these cases actually work in\n      // Octave and Matlab.  For the last two, assume handle is\n      // created before object is defined as an object.\n      //\n      // We can have one of\n      //\n      //   pkg-list . fcn  (args)\n      //   pkg-list . cls . meth (args)\n      //   class-name . method  (args)\n      //   class-name . static-method  (args)\n      //   object . method  (args)\n      //   object . static-method  (args)\n\n      // Evaluate package elements until we find a function,\n      // classdef object, or classdef_meta object that is not a\n      // package.  An object may only appear as the first element,\n      // then it must be followed directly by a function name.\n\n      std::size_t beg = 0;\n      std::size_t end = pos;\n\n      std::vector<std::string> idx_elts;\n\n      while (true)\n        {\n          end = m_name.find ('.', beg);\n\n          idx_elts.push_back (m_name.substr (beg, end-beg));\n\n          if (end == std::string::npos)\n            break;\n\n          beg = end+1;\n        }\n\n      std::size_t n_elts = idx_elts.size ();\n\n      bool have_object = false;\n      octave_value partial_expr_val;\n\n      // Lazy evaluation.  The first element was not known to be defined\n      // as an object in the scope where the handle was created.  See if\n      // there is a definition in the current scope.\n\n      partial_expr_val = interp.varval (idx_elts[0]);\n\n      if (partial_expr_val.is_defined ())\n        {\n          if (! partial_expr_val.is_classdef_object () || n_elts != 2)\n            err_invalid_fcn_handle (m_name);\n\n          have_object = true;\n        }\n      else\n        partial_expr_val = symtab.find_function (idx_elts[0], ovl ());\n\n      std::string type;\n      std::list<octave_value_list> arg_list;\n\n      for (std::size_t i = 1; i < n_elts; i++)\n        {\n          if (partial_expr_val.is_package ())\n            {\n              if (have_object)\n                err_invalid_fcn_handle (m_name);\n\n              type = \".\";\n              arg_list.push_back (ovl (idx_elts[i]));\n\n              try\n                {\n                  // Silently ignore extra output values.\n\n                  octave_value_list tmp_list\n                    = partial_expr_val.subsref (type, arg_list, 0);\n\n                  partial_expr_val\n                    = tmp_list.length () ? tmp_list(0) : octave_value ();\n\n                  if (partial_expr_val.is_cs_list ())\n                    err_invalid_fcn_handle (m_name);\n\n                  arg_list.clear ();\n                }\n              catch (const index_exception&)\n                {\n                  err_invalid_fcn_handle (m_name);\n                }\n            }\n          else if (have_object || partial_expr_val.is_classdef_meta ())\n            {\n              // Object or class name must be the next to the last\n              // element (it was the previous one, so if this is the\n              // final element, it should be a classdef method,\n              // but we'll let the classdef or classdef_meta subsref\n              // function sort that out.\n\n              if (i != n_elts-1)\n                err_invalid_fcn_handle (m_name);\n\n              type = \".(\";\n              arg_list.push_back (ovl (idx_elts[i]));\n              arg_list.push_back (args);\n\n              return partial_expr_val.subsref (type, arg_list, nargout);\n            }\n          else\n            err_invalid_fcn_handle (m_name);\n        }\n\n      // If we get here, we must have a function to call.\n\n      if (! partial_expr_val.is_function ())\n        err_invalid_fcn_handle (m_name);\n\n      fcn_to_call = partial_expr_val;\n    }\n  else\n    {\n      // No \".\" in the name.\n\n      // Perform function lookup given current arguments.  We'll need\n      // to do this regardless of whether a function was found when\n      // the handle was created.\n\n      octave_value ov_fcn = symtab.find_function (m_name, args);\n\n      if (m_fcn.is_defined ())\n        {\n          // A simple function was found when the handle was created.\n          // Use that unless we find a class method to override it.\n\n          fcn_to_call = m_fcn;\n\n          if (ov_fcn.is_defined ())\n            {\n              octave_function *fcn = ov_fcn.function_value ();\n\n              std::string dispatch_class = fcn->dispatch_class ();\n\n              if (fcn->is_class_method ())\n                {\n                  // Function found through lookup is a class method\n                  // so use it instead of the simple one found when\n                  // the handle was created.\n\n                  fcn_to_call = ov_fcn;\n                }\n            }\n        }\n      else\n        {\n          // There was no simple function found when the handle was\n          // created so use the one found here (if any).\n\n          fcn_to_call = ov_fcn;\n        }\n    }\n\n  if (! fcn_to_call.is_defined ())\n    err_invalid_fcn_handle (m_name);\n\n  return interp.feval (fcn_to_call, args, nargout);\n}\n\noctave_function *\nsimple_fcn_handle::function_value (bool)\n{\n  // FIXME: Shouldn't the lookup rules here match those used in the\n  // call method?\n\n  if (m_fcn.is_defined ())\n    return m_fcn.function_value ();\n\n  symbol_table& symtab = __get_symbol_table__ ();\n\n  // FIXME: is caching the correct thing to do?\n  // Cache this value so that the pointer will be valid as long as the\n  // function handle object is valid.\n\n  m_fcn = symtab.find_function (m_name, octave_value_list ());\n\n  return m_fcn.is_defined () ? m_fcn.function_value () : nullptr;\n}\n\noctave_user_function *\nsimple_fcn_handle::user_function_value (bool)\n{\n  // FIXME: Shouldn't the lookup rules here match those used in the\n  // call method?\n\n  if (m_fcn.is_defined ())\n    return m_fcn.user_function_value ();\n\n  symbol_table& symtab = __get_symbol_table__ ();\n\n  // FIXME: is caching the correct thing to do?\n  // Cache this value so that the pointer will be valid as long as the\n  // function handle object is valid.\n\n  m_fcn = symtab.find_user_function (m_name);\n\n  return m_fcn.is_defined () ? m_fcn.user_function_value () : nullptr;\n}\n\noctave_value\nsimple_fcn_handle::fcn_val ()\n{\n  if (m_fcn.is_defined ())\n    return m_fcn;\n\n  symbol_table& symtab = __get_symbol_table__ ();\n\n  // FIXME: is caching the correct thing to do?\n  // Cache this value so that the pointer will be valid as long as the\n  // function handle object is valid.\n\n  m_fcn = symtab.find_user_function (m_name);\n\n  return m_fcn;\n}\n\noctave_scalar_map\nsimple_fcn_handle::info ()\n{\n  octave_scalar_map m;\n\n  m.setfield (\"function\", fcn_name ());\n  m.setfield (\"type\", type ());\n  // When is FILE defined for simple function handles?\n  m.setfield (\"file\", file ());\n\n  return m;\n}\n\nbool\nsimple_fcn_handle::save_ascii (std::ostream& os)\n{\n  os << \"# octaveroot: \" << config::octave_exec_home () << \"\\n\";\n\n  std::string fnm = file ();\n  if (! fnm.empty ())\n    os << \"# path: \" << fnm << \"\\n\";\n\n  os << \"# subtype: \" << type () << \"\\n\";\n\n  os << m_name << \"\\n\";\n\n  return true;\n}\n\nbool\nsimple_fcn_handle::load_ascii (std::istream& is)\n{\n  // FIXME: If m_file is not empty, try to load the file and define\n  // the function?  Is it an error if that fails?  Or should this job\n  // always be deferred until the handle is used?\n\n  return is.good ();\n}\n\nbool\nsimple_fcn_handle::save_binary (std::ostream& os, bool)\n{\n  std::ostringstream nmbuf;\n\n  // When is FILE defined for simple function handles?\n  std::string fnm;\n\n  nmbuf << m_name << \"@<simple>\\n\" << config::octave_exec_home ()\n        << \"\\n\" << fnm;\n\n  std::string buf_str = nmbuf.str ();\n  int32_t tmp = buf_str.length ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  os.write (buf_str.c_str (), buf_str.length ());\n\n  return true;\n}\n\nbool\nsimple_fcn_handle::load_binary (std::istream& is, bool,\n                                mach_info::float_format)\n{\n  return is.good ();\n}\n\nbool\nsimple_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                              bool)\n{\n#if defined (HAVE_HDF5)\n\n  bool retval = true;\n\n  octave_hdf5_id group_hid = -1;\n#if defined (HAVE_HDF5_18)\n  group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                         octave_H5P_DEFAULT);\n#else\n  group_hid = H5Gcreate (loc_id, name, 0);\n#endif\n  if (group_hid < 0)\n    return false;\n\n  octave_hdf5_id space_hid, data_hid, type_hid;\n  space_hid = data_hid = type_hid = -1;\n\n  // attach the type of the variable\n  type_hid = H5Tcopy (H5T_C_S1);\n  H5Tset_size (type_hid, m_name.length () + 1);\n  if (type_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2);\n  hdims[0] = 0;\n  hdims[1] = 0;\n  space_hid = H5Screate_simple (0, hdims, nullptr);\n  if (space_hid < 0)\n    {\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nm\", type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nm\", type_hid, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0\n      || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                   octave_H5P_DEFAULT, m_name.c_str ()) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n  H5Dclose (data_hid);\n\n  std::string octaveroot = config::octave_exec_home ();\n\n  // When is FILE defined for simple fucntion handles?\n  std::string fpath;\n\n  H5Sclose (space_hid);\n  hdims[0] = 1;\n  hdims[1] = octaveroot.length ();\n  space_hid = H5Screate_simple (0, hdims, nullptr);\n  if (space_hid < 0)\n    {\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Tclose (type_hid);\n  type_hid = H5Tcopy (H5T_C_S1);\n  H5Tset_size (type_hid, octaveroot.length () + 1);\n  octave_hdf5_id a_id;\n#if defined (HAVE_HDF5_18)\n  a_id = H5Acreate (group_hid, \"OCTAVEROOT\", type_hid, space_hid,\n                    octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n#else\n  a_id = H5Acreate (group_hid, \"OCTAVEROOT\", type_hid, space_hid,\n                    octave_H5P_DEFAULT);\n#endif\n\n  if (a_id >= 0)\n    {\n      retval = (H5Awrite (a_id, type_hid, octaveroot.c_str ()) >= 0);\n\n      H5Aclose (a_id);\n    }\n  else\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n  hdims[0] = 1;\n  hdims[1] = fpath.length ();\n  space_hid = H5Screate_simple (0, hdims, nullptr);\n  if (space_hid < 0)\n    {\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Tclose (type_hid);\n  type_hid = H5Tcopy (H5T_C_S1);\n  H5Tset_size (type_hid, fpath.length () + 1);\n\n#if defined (HAVE_HDF5_18)\n  a_id = H5Acreate (group_hid, \"FILE\", type_hid, space_hid,\n                    octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n#else\n  a_id = H5Acreate (group_hid, \"FILE\", type_hid, space_hid,\n                    octave_H5P_DEFAULT);\n#endif\n\n  if (a_id >= 0)\n    {\n      retval = (H5Awrite (a_id, type_hid, fpath.c_str ()) >= 0);\n\n      H5Aclose (a_id);\n    }\n  else\n    retval = false;\n\n  H5Sclose (space_hid);\n  H5Tclose (type_hid);\n  H5Gclose (group_hid);\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n\n  return false;\n\n#endif\n}\n\nbool\nsimple_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid,\n                              octave_hdf5_id& space_hid,\n                              octave_hdf5_id& type_hid)\n{\n#if defined (HAVE_HDF5)\n\n  unimplemented (\"load\", \"hdf5\");\n\n  octave_unused_parameter (group_hid);\n  octave_unused_parameter (space_hid);\n  octave_unused_parameter (type_hid);\n\n  return true;\n\n#else\n\n  octave_unused_parameter (group_hid);\n  octave_unused_parameter (space_hid);\n  octave_unused_parameter (type_hid);\n\n  return false;\n\n#endif\n}\n\nvoid\nsimple_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax,\n                              int current_print_indent_level) const\n{\n  octave_print_internal (os, '@' + m_name, pr_as_read_syntax,\n                         current_print_indent_level);\n}\n\nbool\nis_equal_to (const simple_fcn_handle& fh1, const simple_fcn_handle& fh2)\n{\n  if (fh1.m_name == fh2.m_name)\n    {\n      if (fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ())\n        return fh1.m_fcn.is_copy_of (fh2.m_fcn);\n\n      if (fh1.m_fcn.is_undefined () && fh2.m_fcn.is_undefined ())\n        return true;\n    }\n\n  return false;\n}\n\nscoped_fcn_handle::scoped_fcn_handle (const octave_value& fcn,\n                                      const std::string& name,\n                                      const std::list<std::string>& parentage)\n  : base_fcn_handle (name), m_fcn (fcn), m_parentage (parentage)\n{\n  // FIXME: should it be an error if FCN is undefined?\n\n  if (m_fcn.is_defined ())\n    {\n      octave_function *oct_fcn = m_fcn.function_value ();\n\n      if (oct_fcn)\n        m_file = oct_fcn->fcn_file_name ();\n    }\n\n  m_parentage.push_front (name);\n}\n\noctave_value_list\nscoped_fcn_handle::call (int nargout, const octave_value_list& args)\n{\n  // FIXME: we aren't really using the scope yet.  Hmm.\n\n  interpreter& interp = __get_interpreter__ ();\n\n  if (! m_fcn.is_defined ())\n    {\n      // Try to find it?\n\n      find_function ();\n    }\n\n  if (! m_fcn.is_defined ())\n    err_invalid_fcn_handle (m_name);\n\n  return interp.feval (m_fcn, args, nargout);\n}\n\noctave_scalar_map\nscoped_fcn_handle::info ()\n{\n  octave_scalar_map m;\n\n  m.setfield (\"function\", fcn_name ());\n  m.setfield (\"type\", type ());\n  m.setfield (\"file\", file ());\n\n  m.setfield (\"parentage\", Cell (m_parentage));\n\n  return m;\n}\n\nbool\nscoped_fcn_handle::save_ascii (std::ostream& os)\n{\n  os << \"# octaveroot: \" << config::octave_exec_home () << \"\\n\";\n\n  std::string fnm = file ();\n  if (! fnm.empty ())\n    os << \"# path: \" << fnm << \"\\n\";\n\n  os << \"# subtype: \" << type () << \"\\n\";\n\n  os << m_name << \"\\n\";\n\n  octave_value tmp = Cell (m_parentage);\n  tmp.save_ascii (os);\n\n  return os.good ();\n}\n\nbool\nscoped_fcn_handle::load_ascii (std::istream& is)\n{\n  octave_cell ov_cell;\n  ov_cell.load_ascii (is);\n\n  if (ov_cell.iscellstr ())\n    {\n      Array<std::string> cellstr_val = ov_cell.cellstr_value ();\n\n      for (octave_idx_type i = 0; i < cellstr_val.numel (); i++)\n        m_parentage.push_back (cellstr_val(i));\n    }\n\n  return is.good ();\n}\n\nbool\nscoped_fcn_handle::save_binary (std::ostream& os, bool save_as_floats)\n{\n  std::ostringstream nmbuf;\n\n  std::string fnm = file ();\n\n  nmbuf << m_name << \"@<scopedfunction>\\n\" << config::octave_exec_home ()\n        << \"\\n\" << fnm;\n\n  std::string buf_str = nmbuf.str ();\n  int32_t len = buf_str.length ();\n  os.write (reinterpret_cast<char *> (&len), 4);\n  os.write (buf_str.c_str (), buf_str.length ());\n\n  octave_value tmp = Cell (m_parentage);\n  tmp.save_binary (os, save_as_floats);\n\n  return os.good ();\n}\n\nbool\nscoped_fcn_handle::load_binary (std::istream& is, bool swap,\n                                mach_info::float_format fmt)\n{\n  octave_cell ov_cell;\n  ov_cell.load_binary (is, swap, fmt);\n\n  if (ov_cell.iscellstr ())\n    {\n      Array<std::string> cellstr_val = ov_cell.cellstr_value ();\n\n      for (octave_idx_type i = 0; i < cellstr_val.numel (); i++)\n        m_parentage.push_back (cellstr_val(i));\n    }\n\n  return is.good ();\n}\n\nbool\nscoped_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                              bool)\n{\n#if defined (HAVE_HDF5)\n\n  unimplemented (\"save\", \"hdf5\");\n\n  // FIXME: save parentage.\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  return true;\n\n#else\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n\n  return false;\n\n#endif\n}\n\nbool\nscoped_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid,\n                              octave_hdf5_id& space_hid,\n                              octave_hdf5_id& type_hid)\n{\n#if defined (HAVE_HDF5)\n\n  unimplemented (\"load\", \"hdf5\");\n\n  // FIXME: load parentage.\n\n  octave_unused_parameter (group_hid);\n  octave_unused_parameter (space_hid);\n  octave_unused_parameter (type_hid);\n\n  return true;\n\n#else\n\n  octave_unused_parameter (group_hid);\n  octave_unused_parameter (space_hid);\n  octave_unused_parameter (type_hid);\n\n  return false;\n\n#endif\n}\n\nvoid\nscoped_fcn_handle::print_raw (std::ostream& os,\n                              bool pr_as_read_syntax,\n                              int current_print_indent_level) const\n{\n  octave_print_internal (os, '@' + m_name, pr_as_read_syntax,\n                         current_print_indent_level);\n}\n\nbool\nis_equal_to (const scoped_fcn_handle& fh1, const scoped_fcn_handle& fh2)\n{\n  if (fh1.m_name == fh2.m_name\n      && fh2.m_parentage == fh2.m_parentage\n      && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ())\n    return fh1.m_fcn.is_copy_of (fh2.m_fcn);\n  else\n    return false;\n}\n\nvoid\nscoped_fcn_handle::find_function ()\n{\n  // Since a scoped function is not visible by itself, try to load the\n  // file named in m_file then find and define the scoped function.\n  // It is not an error if this fails.  We can report later that the\n  // handle is invalid.\n\n  symbol_table& symtab = __get_symbol_table__ ();\n\n  if (m_parentage.size () == 1)\n    {\n      std::string dir_name = sys::file_ops::dirname (m_file);\n\n      std::size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ());\n\n      if (pos != std::string::npos)\n        dir_name = dir_name.substr (0, pos);\n      else if (dir_name == \"private\")\n        dir_name = \".\";\n\n      std::string fcn_name = m_parentage.front ();\n\n      // FIXME: Does dir_name need to be in the load path for this to work?\n\n      m_fcn = symtab.find_private_function (dir_name, m_name);\n\n      // FIXME: Verify that it is a private function?\n    }\n  else\n    {\n      std::string primary_parent_name = m_parentage.back ();\n\n      octave_value ov_parent_fcn\n        = symtab.find_user_function (primary_parent_name);\n\n      if (ov_parent_fcn.is_defined ())\n        {\n          octave_user_function *fcn = ov_parent_fcn.user_function_value ();\n\n          if (fcn)\n            {\n              std::string file_name = fcn->fcn_file_name ();\n\n              std::string oct_home = config::octave_exec_home ();\n\n              if (file_name.substr (0, oct_home.size ()) == oct_home)\n                file_name = file_name.substr (oct_home.size ());\n\n              octave_value subfcn = fcn->find_subfunction (m_name);\n\n              if (subfcn.is_defined ())\n                m_fcn = subfcn;\n            }\n        }\n    }\n}\n\noctave_scalar_map\nbase_nested_fcn_handle::info ()\n{\n  octave_scalar_map m;\n\n  m.setfield (\"function\", fcn_name ());\n  m.setfield (\"type\", type ());\n  m.setfield (\"file\", \"\");\n  m.setfield (\"workspace\", workspace ());\n\n  return m;\n}\n\n// FIXME: For save, we need a way to save the (possibly shared)\n// workspace.  For load, we need a way to load and link to the\n// (possibly shared) workspace that was saved.\n//\n// Since a nested function is not visible by itself, do we need to try\n// to load the file named in m_file then find and define the function?\n// Is it an error if that fails?  Or should this job always be\n// deferred until the handle is used?\n\nbool\nbase_nested_fcn_handle::save_ascii (std::ostream& os)\n{\n  unimplemented (\"save\", \"text\");\n\n  octave_unused_parameter (os);\n\n  return true;\n}\n\nbool\nbase_nested_fcn_handle::load_ascii (std::istream& is)\n{\n  unimplemented (\"load\", \"text\");\n\n  octave_unused_parameter (is);\n\n  return true;\n}\n\nbool\nbase_nested_fcn_handle::save_binary (std::ostream& os,\n                                     bool save_as_floats)\n{\n  unimplemented (\"save\", \"binary\");\n\n  octave_unused_parameter (os);\n  octave_unused_parameter (save_as_floats);\n\n  return true;\n}\n\nbool\nbase_nested_fcn_handle::load_binary (std::istream& is, bool swap,\n                                     mach_info::float_format fmt)\n{\n  unimplemented (\"load\", \"binary\");\n\n  octave_unused_parameter (is);\n  octave_unused_parameter (swap);\n  octave_unused_parameter (fmt);\n\n  return true;\n}\n\nbool\nbase_nested_fcn_handle::save_hdf5 (octave_hdf5_id loc_id,\n                                   const char *name, bool)\n{\n#if defined (HAVE_HDF5)\n\n  unimplemented (\"save\", \"hdf5\");\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  return true;\n\n#else\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n\n  return false;\n\n#endif\n}\n\nbool\nbase_nested_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid,\n                                   octave_hdf5_id& space_hid,\n                                   octave_hdf5_id& type_hid)\n{\n#if defined (HAVE_HDF5)\n\n  unimplemented (\"load\", \"hdf5\");\n\n  octave_unused_parameter (group_hid);\n  octave_unused_parameter (space_hid);\n  octave_unused_parameter (type_hid);\n\n  return true;\n\n#else\n\n  octave_unused_parameter (group_hid);\n  octave_unused_parameter (space_hid);\n  octave_unused_parameter (type_hid);\n\n  return false;\n\n#endif\n}\n\nvoid\nbase_nested_fcn_handle::print_raw (std::ostream& os,\n                                   bool pr_as_read_syntax,\n                                   int current_print_indent_level) const\n{\n  octave_print_internal (os, '@' + m_name, pr_as_read_syntax,\n                         current_print_indent_level);\n}\n\noctave_value\nnested_fcn_handle::make_weak_nested_handle () const\n{\n  return octave_value (new octave_fcn_handle\n                       (new weak_nested_fcn_handle (*this)));\n}\n\noctave_value_list\nnested_fcn_handle::call (int nargout, const octave_value_list& args)\n{\n  tree_evaluator& tw = __get_evaluator__ ();\n\n  octave_user_function *oct_usr_fcn = m_fcn.user_function_value ();\n\n  tw.push_stack_frame (oct_usr_fcn, m_stack_context);\n\n  unwind_action act ([&tw] () { tw.pop_stack_frame (); });\n\n  return oct_usr_fcn->execute (tw, nargout, args);\n}\n\noctave_value\nnested_fcn_handle::workspace () const\n{\n  return m_stack_context->workspace ();\n}\n\nbool\nis_equal_to (const nested_fcn_handle& fh1, const nested_fcn_handle& fh2)\n{\n  if (fh1.m_name == fh2.m_name\n      && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ())\n    return fh1.m_fcn.is_copy_of (fh2.m_fcn);\n  else\n    return false;\n}\n\noctave_value_list\nweak_nested_fcn_handle::call (int nargout, const octave_value_list& args)\n{\n  tree_evaluator& tw = __get_evaluator__ ();\n\n  octave_user_function *oct_usr_fcn = m_fcn.user_function_value ();\n\n  std::shared_ptr<stack_frame> frames = m_stack_context.lock ();\n\n  tw.push_stack_frame (oct_usr_fcn, frames);\n\n  unwind_action act ([&tw] () { tw.pop_stack_frame (); });\n\n  return oct_usr_fcn->execute (tw, nargout, args);\n}\n\noctave_value\nweak_nested_fcn_handle::workspace () const\n{\n  std::shared_ptr<stack_frame> frames = m_stack_context.lock ();\n\n  return frames ? frames->workspace () : octave_value ();\n}\n\nbool\nis_equal_to (const weak_nested_fcn_handle& fh1,\n             const weak_nested_fcn_handle& fh2)\n{\n  if (fh1.m_name == fh2.m_name\n      && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ())\n    return fh1.m_fcn.is_copy_of (fh2.m_fcn);\n  else\n    return false;\n}\n\nclass_simple_fcn_handle::class_simple_fcn_handle (const std::string& class_nm,\n    const std::string& meth_nm)\n  : base_fcn_handle (meth_nm), m_obj (), m_fcn (),\n    m_dispatch_class (class_nm)\n{ }\n\nclass_simple_fcn_handle::class_simple_fcn_handle (const octave_value& fcn,\n    const std::string& class_nm,\n    const std::string& meth_nm)\n  : base_fcn_handle (meth_nm), m_obj (), m_fcn (fcn),\n    m_dispatch_class (class_nm)\n{ }\n\nclass_simple_fcn_handle::class_simple_fcn_handle (const octave_value& obj,\n    const octave_value& fcn,\n    const std::string& class_nm,\n    const std::string& meth_nm)\n  : base_fcn_handle (meth_nm), m_obj (obj), m_fcn (fcn),\n    m_dispatch_class (class_nm)\n{ }\n\noctave_value_list\nclass_simple_fcn_handle::call (int nargout, const octave_value_list& args)\n{\n  interpreter& interp = __get_interpreter__ ();\n\n  if (m_obj.is_defined ())\n    {\n      octave_value_list tmp_args = args;\n      tmp_args.prepend (m_obj);\n\n      return interp.feval (m_fcn, tmp_args, nargout);\n    }\n\n  // FIXME: is this the best approach?  Should we be saving current\n  // dispatch class and restoring that value instead of\n  // unconditionally setting it to \"\" when we return from this\n  // function?\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  unwind_action act ([&tw] () { tw.set_dispatch_class (\"\"); });\n\n  tw.set_dispatch_class (m_dispatch_class);\n\n  if (m_fcn.is_defined ())\n    return interp.feval (m_fcn, args, nargout);\n\n  return interp.feval (fcn_name (), args, nargout);\n}\n\noctave_scalar_map\nclass_simple_fcn_handle::info ()\n{\n  octave_scalar_map m;\n\n  m.setfield (\"function\", fcn_name ());\n  m.setfield (\"type\", type ());\n  m.setfield (\"file\", \"\");\n  m.setfield (\"class\", dispatch_class ());\n\n  return m;\n}\n\n// FIXME: Since a class method is not visible by itself, do we need to\n// try to load the file named in m_file then find and define the\n// function?  Is it an error if that fails?  Or should this job always\n// be deferred until the handle is used?\n\nbool\nclass_simple_fcn_handle::save_ascii (std::ostream& os)\n{\n  unimplemented (\"save\", \"text\");\n\n  octave_unused_parameter (os);\n\n  return true;\n}\n\nbool\nclass_simple_fcn_handle::load_ascii (std::istream& is)\n{\n  unimplemented (\"load\", \"text\");\n\n  octave_unused_parameter (is);\n\n  return true;\n}\n\nbool\nclass_simple_fcn_handle::save_binary (std::ostream& os,\n                                      bool save_as_floats)\n{\n  unimplemented (\"save\", \"binary\");\n\n  octave_unused_parameter (os);\n  octave_unused_parameter (save_as_floats);\n\n  return true;\n}\n\nbool\nclass_simple_fcn_handle::load_binary (std::istream& is, bool swap,\n                                      mach_info::float_format fmt)\n{\n  unimplemented (\"load\", \"binary\");\n\n  octave_unused_parameter (is);\n  octave_unused_parameter (swap);\n  octave_unused_parameter (fmt);\n\n  return true;\n}\n\nbool\nclass_simple_fcn_handle::save_hdf5 (octave_hdf5_id loc_id,\n                                    const char *name, bool)\n{\n#if defined (HAVE_HDF5)\n\n  unimplemented (\"save\", \"hdf5\");\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  return true;\n\n#else\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n\n  return false;\n\n#endif\n}\n\nbool\nclass_simple_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid,\n                                    octave_hdf5_id& space_hid,\n                                    octave_hdf5_id& type_hid)\n{\n#if defined (HAVE_HDF5)\n\n  unimplemented (\"load\", \"hdf5\");\n\n  octave_unused_parameter (group_hid);\n  octave_unused_parameter (space_hid);\n  octave_unused_parameter (type_hid);\n\n  return true;\n\n#else\n\n  octave_unused_parameter (group_hid);\n  octave_unused_parameter (space_hid);\n  octave_unused_parameter (type_hid);\n\n  return false;\n\n#endif\n}\n\nvoid\nclass_simple_fcn_handle::print_raw (std::ostream& os,\n                                    bool pr_as_read_syntax,\n                                    int current_print_indent_level) const\n{\n  octave_print_internal (os, '@' + m_name, pr_as_read_syntax,\n                         current_print_indent_level);\n}\n\nbool\nis_equal_to (const class_simple_fcn_handle& fh1,\n             const class_simple_fcn_handle& fh2)\n{\n  // FIXME: Also need to check object values are equivalent?\n\n  if (fh1.m_name == fh2.m_name\n      && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ())\n    return fh1.m_fcn.is_copy_of (fh2.m_fcn);\n  else\n    return false;\n}\n\nconst std::string base_anonymous_fcn_handle::anonymous (\"@<anonymous>\");\n\noctave_scalar_map\nbase_anonymous_fcn_handle::info ()\n{\n  octave_scalar_map m;\n\n  std::ostringstream buf;\n  print_raw (buf, true, 0);\n  m.setfield (\"function\", buf.str ());\n\n  m.setfield (\"type\", type ());\n  m.setfield (\"file\", \"\");\n  m.setfield (\"workspace\", workspace ());\n  m.setfield (\"within_file_path\", \"\");\n\n  return m;\n}\n\nbool\nbase_anonymous_fcn_handle::save_ascii (std::ostream& os)\n{\n  // FIXME: can we ensure that m_fcn is always defined?\n\n  if (m_fcn.is_undefined ())\n    return false;\n\n  os << m_name << \"\\n\";\n\n  print_raw (os, true, 0);\n  os << \"\\n\";\n\n  std::size_t varlen = m_local_vars.size ();\n\n  if (varlen > 0)\n    {\n      os << \"# length: \" << varlen << \"\\n\";\n\n      for (const auto& nm_val : m_local_vars)\n        {\n          if (! save_text_data (os, nm_val.second, nm_val.first, false, 0))\n            return ! os.fail ();\n        }\n    }\n\n  return true;\n}\n\nbool\nbase_anonymous_fcn_handle::load_ascii (std::istream& is)\n{\n  octave::skip_preceeding_newline (is);\n\n  std::string buf;\n\n  if (is)\n    {\n      // Get a line of text whitespace characters included, leaving\n      // newline in the stream.\n\n      buf = octave::read_until_newline (is, true);\n    }\n\n  std::streampos pos = is.tellg ();\n\n  // Set up temporary scope to use for evaluating the text that\n  // defines the anonymous function.\n\n  interpreter& interp = __get_interpreter__ ();\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  tw.push_dummy_scope (buf);\n  unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw);\n\n  octave_idx_type len = 0;\n\n  if (extract_keyword (is, \"length\", len, true) && len >= 0)\n    {\n      if (len > 0)\n        {\n          for (octave_idx_type i = 0; i < len; i++)\n            {\n              octave_value t2;\n              bool dummy;\n\n              std::string name = read_text_data (is, \"\", dummy, t2, i);\n\n              if (! is)\n                error (\"load: failed to load anonymous function handle\");\n\n              m_local_vars[name] = t2;\n            }\n        }\n    }\n  else\n    {\n      is.seekg (pos);\n      is.clear ();\n    }\n\n  if (is)\n    return parse (buf);\n\n  return false;\n}\n\nbool\nbase_anonymous_fcn_handle::save_binary (std::ostream& os,\n                                        bool save_as_floats)\n{\n  // FIXME: can we ensure that m_fcn is always defined?\n\n  if (m_fcn.is_undefined ())\n    return false;\n\n  std::ostringstream nmbuf;\n\n  std::size_t varlen = m_local_vars.size ();\n\n  nmbuf << anonymous;\n  if (varlen > 0)\n    nmbuf << ' ' << varlen;\n\n  std::string buf_str = nmbuf.str ();\n  int32_t tmp = buf_str.length ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  os.write (buf_str.c_str (), buf_str.length ());\n\n  std::ostringstream buf;\n  print_raw (buf, true, 0);\n  std::string stmp = buf.str ();\n  tmp = stmp.length ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  os.write (stmp.c_str (), stmp.length ());\n\n  if (varlen > 0)\n    {\n      for (const auto& nm_val : m_local_vars)\n        {\n          if (! save_binary_data (os, nm_val.second, nm_val.first,\n                                  \"\", 0, save_as_floats))\n            return ! os.fail ();\n        }\n    }\n\n  return true;\n}\n\nbool\nbase_anonymous_fcn_handle::load_binary (std::istream& is, bool swap,\n                                        mach_info::float_format fmt)\n{\n  // Read extra characters in m_name as the number of local variable\n  // values in this anonymous function.\n\n  octave_idx_type len = 0;\n  std::size_t anl = anonymous.length ();\n  if (m_name.length () > anl)\n    {\n      std::istringstream nm_is (m_name.substr (anl));\n      nm_is >> len;\n\n      // Anonymous functions don't have names.  We just used this\n      // string as temporary storage to pass the number of local\n      // variable values.\n\n      m_name = \"\";\n    }\n\n  int32_t tmp;\n\n  if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&tmp);\n\n  OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);\n  // is.get (ctmp2, tmp+1, 0); caused is.eof () to be true though\n  // effectively not reading over file end\n  is.read (ctmp2, tmp);\n  ctmp2[tmp] = 0;\n\n  // Set up temporary scope to use for evaluating the text that\n  // defines the anonymous function.\n\n  interpreter& interp = __get_interpreter__ ();\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  tw.push_dummy_scope (ctmp2);\n  unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw);\n\n  if (len > 0)\n    {\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          octave_value t2;\n          bool dummy;\n          std::string doc;\n\n          std::string name\n            = read_binary_data (is, swap, fmt, \"\", dummy, t2, doc);\n\n          if (! is)\n            error (\"load: failed to load anonymous function handle\");\n\n          m_local_vars[name] = t2;\n        }\n    }\n\n  if (is)\n    return parse (ctmp2);\n\n  return false;\n}\n\nbool\nbase_anonymous_fcn_handle::save_hdf5 (octave_hdf5_id loc_id,\n                                      const char *name,\n                                      bool save_as_floats)\n{\n#if defined (HAVE_HDF5)\n\n  bool retval = true;\n\n  octave_hdf5_id group_hid = -1;\n#if defined (HAVE_HDF5_18)\n  group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                         octave_H5P_DEFAULT);\n#else\n  group_hid = H5Gcreate (loc_id, name, 0);\n#endif\n  if (group_hid < 0)\n    return false;\n\n  octave_hdf5_id space_hid, data_hid, type_hid;\n  space_hid = data_hid = type_hid = -1;\n\n  // attach the type of the variable\n  type_hid = H5Tcopy (H5T_C_S1);\n  H5Tset_size (type_hid, m_name.length () + 1);\n  if (type_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2);\n  hdims[0] = 0;\n  hdims[1] = 0;\n  space_hid = H5Screate_simple (0, hdims, nullptr);\n  if (space_hid < 0)\n    {\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nm\", type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nm\", type_hid, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0\n      || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                   octave_H5P_DEFAULT, m_name.c_str ()) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n  H5Dclose (data_hid);\n\n  std::ostringstream buf;\n  print_raw (buf, true, 0);\n  std::string stmp = buf.str ();\n\n  // attach the type of the variable\n  H5Tset_size (type_hid, stmp.length () + 1);\n  if (type_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"fcn\", type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"fcn\", type_hid, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0\n      || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                   octave_H5P_DEFAULT, stmp.c_str ()) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n  std::size_t varlen = m_local_vars.size ();\n\n  if (varlen > 0)\n    {\n      octave_hdf5_id as_id = H5Screate (H5S_SCALAR);\n\n      if (as_id >= 0)\n        {\n          octave_hdf5_id a_id;\n#if defined (HAVE_HDF5_18)\n          a_id = H5Acreate (group_hid, \"SYMBOL_TABLE\", H5T_NATIVE_IDX, as_id,\n                            octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n\n#else\n          a_id = H5Acreate (group_hid, \"SYMBOL_TABLE\", H5T_NATIVE_IDX, as_id,\n                            octave_H5P_DEFAULT);\n#endif\n\n          if (a_id >= 0)\n            {\n              retval = (H5Awrite (a_id, H5T_NATIVE_IDX, &varlen) >= 0);\n\n              H5Aclose (a_id);\n            }\n          else\n            retval = false;\n\n          H5Sclose (as_id);\n        }\n      else\n        retval = false;\n#if defined (HAVE_HDF5_18)\n      data_hid = H5Gcreate (group_hid, \"symbol table\",\n                            octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                            octave_H5P_DEFAULT);\n#else\n      data_hid = H5Gcreate (group_hid, \"symbol table\", 0);\n#endif\n      if (data_hid < 0)\n        {\n          H5Sclose (space_hid);\n          H5Tclose (type_hid);\n          H5Gclose (group_hid);\n          return false;\n        }\n\n      for (const auto& nm_val : m_local_vars)\n        {\n          if (! add_hdf5_data (data_hid, nm_val.second, nm_val.first,\n                               \"\", false, save_as_floats))\n            break;\n        }\n\n      H5Gclose (data_hid);\n    }\n\n  H5Sclose (space_hid);\n  H5Tclose (type_hid);\n  H5Gclose (group_hid);\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n\n  return false;\n\n#endif\n}\n\nbool\nbase_anonymous_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid,\n                                      octave_hdf5_id& space_hid,\n                                      octave_hdf5_id& type_hid)\n{\n#if defined (HAVE_HDF5)\n\n  bool success = true;\n\n#if defined (HAVE_HDF5_18)\n  octave_hdf5_id data_hid = H5Dopen (group_hid, \"fcn\", octave_H5P_DEFAULT);\n#else\n  octave_hdf5_id data_hid = H5Dopen (group_hid, \"fcn\");\n#endif\n\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Tclose (type_hid);\n  type_hid = H5Dget_type (data_hid);\n  octave_hdf5_id type_class_hid = H5Tget_class (type_hid);\n\n  if (type_class_hid != H5T_STRING)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n  space_hid = H5Dget_space (data_hid);\n  hsize_t rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  int slen = H5Tget_size (type_hid);\n  if (slen < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (char, fcn_tmp, slen);\n\n  // create datatype for (null-terminated) string to read into:\n  octave_hdf5_id st_id = H5Tcopy (H5T_C_S1);\n  H5Tset_size (st_id, slen);\n\n  if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, fcn_tmp)\n      < 0)\n    {\n      H5Tclose (st_id);\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n  H5Tclose (st_id);\n  H5Dclose (data_hid);\n\n  octave_idx_type len = 0;\n\n  // we have to pull some shenanigans here to make sure\n  // HDF5 doesn't print out all sorts of error messages if we\n  // call H5Aopen for a non-existing attribute\n\n  H5E_auto_t err_fcn;\n  void *err_fcn_data;\n\n  // turn off error reporting temporarily, but save the error\n  // reporting function:\n#if defined (HAVE_HDF5_18)\n  H5Eget_auto (octave_H5E_DEFAULT, &err_fcn, &err_fcn_data);\n  H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr);\n#else\n  H5Eget_auto (&err_fcn, &err_fcn_data);\n  H5Eset_auto (nullptr, nullptr);\n#endif\n\n  octave_hdf5_id attr_id = H5Aopen_name (group_hid, \"SYMBOL_TABLE\");\n\n  if (attr_id >= 0)\n    {\n      if (H5Aread (attr_id, H5T_NATIVE_IDX, &len) < 0)\n        success = false;\n\n      H5Aclose (attr_id);\n    }\n\n  // restore error reporting:\n#if defined (HAVE_HDF5_18)\n  H5Eset_auto (octave_H5E_DEFAULT, err_fcn, err_fcn_data);\n#else\n  H5Eset_auto (err_fcn, err_fcn_data);\n#endif\n\n  // Set up temporary scope to use for evaluating the text that\n  // defines the anonymous function.\n\n  interpreter& interp = __get_interpreter__ ();\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  tw.push_dummy_scope (fcn_tmp);\n  unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw);\n\n  if (len > 0 && success)\n    {\n      hsize_t num_obj = 0;\n#if defined (HAVE_HDF5_18)\n      data_hid = H5Gopen (group_hid, \"symbol table\", octave_H5P_DEFAULT);\n#else\n      data_hid = H5Gopen (group_hid, \"symbol table\");\n#endif\n      H5Gget_num_objs (data_hid, &num_obj);\n      H5Gclose (data_hid);\n\n      if (num_obj != static_cast<hsize_t> (len))\n        error (\"load: failed to load anonymous function handle\");\n\n      hdf5_callback_data dsub;\n      int current_item = 0;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          if (hdf5_h5g_iterate (group_hid, \"symbol table\", &current_item,\n                                &dsub) <= 0)\n            error (\"load: failed to load anonymous function handle\");\n\n          m_local_vars[dsub.name] = dsub.tc;\n        }\n    }\n\n  if (success)\n    return parse (fcn_tmp);\n\n  return false;\n\n#else\n\n  octave_unused_parameter (group_hid);\n  octave_unused_parameter (space_hid);\n  octave_unused_parameter (type_hid);\n\n  return false;\n\n#endif\n}\n\nvoid\nbase_anonymous_fcn_handle::print_raw (std::ostream& os, bool, int) const\n{\n  tree_print_code tpc (os);\n\n  octave_user_function *f = m_fcn.user_function_value ();\n\n  if (! f)\n    error (\"invalid anonymous function handle\");\n\n  os << \"@\";\n\n  // The parameter list should always be valid for anonymous\n  // functions, so we should always call accept for it, and it will\n  // print the parens for us.\n\n  tree_parameter_list *p = f->parameter_list ();\n\n  if (p)\n    p->accept (tpc);\n\n  os << \" \";\n\n  tree_statement_list *b = f->body ();\n\n  panic_if (b->size () != 1);\n\n  tree_statement *s = b->front ();\n\n  if (! s)\n    error (\"invalid anonymous function handle\");\n\n  panic_unless (s->is_expression ());\n\n  tree_expression *e = s->expression ();\n\n  if (! e)\n    error (\"invalid anonymous function handle\");\n\n  tpc.print_fcn_handle_body (e);\n}\n\nbool\nbase_anonymous_fcn_handle::parse (const std::string& fcn_text)\n{\n  // FIXME: If evaluation of the string gives us an anonymous function\n  // handle object, then why extract the function and create a new\n  // anonymous function object?  Why not just attach the workspace\n  // values to the object returned by eval_string?  This code is also is\n  // duplicated in read_mat5_binary_element in ls-mat5.cc.\n\n  interpreter& interp = __get_interpreter__ ();\n\n  // Set up temporary scope to use for evaluating the text that defines\n  // the anonymous function so that we don't pick up values of random\n  // variables that might be in the current scope.\n\n  tree_evaluator& tw = interp.get_evaluator ();\n  tw.push_dummy_scope (\"read_mat5_binary_element\");\n\n  unwind_action act ([&tw] () { tw.pop_scope (); });\n\n  int parse_status;\n  octave_value anonymous_fcn_hdl\n    = interp.eval_string (fcn_text, true, parse_status);\n\n  if (parse_status != 0)\n    return false;\n\n  octave_fcn_handle *fh = anonymous_fcn_hdl.fcn_handle_value ();\n\n  if (! fh)\n    return false;\n\n  m_fcn = fh->fcn_val ();\n\n  octave_user_function *uf = m_fcn.user_function_value (true);\n\n  if (uf)\n    {\n      symbol_scope uf_scope = uf->scope ();\n\n      if (uf_scope)\n        uf_scope.cache_name (m_name);\n    }\n\n  return true;\n}\n\nanonymous_fcn_handle::anonymous_fcn_handle (const octave_value& fcn,\n    const stack_frame::local_vars_map& local_vars,\n    const std::shared_ptr<stack_frame>& stack_context)\n  : base_anonymous_fcn_handle (fcn, local_vars),\n    m_stack_context (stack_context)\n{\n  if (m_stack_context)\n    m_stack_context->mark_closure_context ();\n}\n\noctave_value\nanonymous_fcn_handle::make_weak_anonymous_handle () const\n{\n  return octave_value (new octave_fcn_handle\n                       (new weak_anonymous_fcn_handle (*this)));\n}\n\noctave_value_list\nanonymous_fcn_handle::call (int nargout, const octave_value_list& args)\n{\n  tree_evaluator& tw = __get_evaluator__ ();\n\n  octave_user_function *oct_usr_fcn = m_fcn.user_function_value ();\n\n  tw.push_stack_frame (oct_usr_fcn, m_local_vars, m_stack_context);\n\n  unwind_action act ([&tw] () { tw.pop_stack_frame (); });\n\n  return oct_usr_fcn->execute (tw, nargout, args);\n}\n\noctave_value\nanonymous_fcn_handle::workspace () const\n{\n  octave_scalar_map local_vars_map;\n\n  for (const auto& nm_val : m_local_vars)\n    local_vars_map.assign (nm_val.first, nm_val.second);\n\n  // FIXME: it would be more convenient if stack_frame::workspace\n  // returned a Cell object directly instead of a Cell in an\n  // octave_value object.\n\n  Cell cell_frames;\n\n  if (m_stack_context)\n    {\n      octave_value ov_frames = m_stack_context->workspace ();\n      cell_frames = ov_frames.cell_value ();\n    }\n\n  octave_idx_type num_frames = cell_frames.numel ();\n  // FIXME: It seems there should be a simple way to concatenate cells...\n  Cell retval = Cell (num_frames+1, 1);\n  retval(0) = m_local_vars;\n  for (octave_idx_type i = 0; i < num_frames; i++)\n    retval(i+1) = cell_frames(i);\n\n  return retval;\n}\n\nbool\nis_equal_to (const anonymous_fcn_handle& fh1,\n             const anonymous_fcn_handle& fh2)\n{\n  if (fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ())\n    return fh1.m_fcn.is_copy_of (fh2.m_fcn);\n  else\n    return false;\n}\n\noctave_value_list\nweak_anonymous_fcn_handle::call (int nargout, const octave_value_list& args)\n{\n  tree_evaluator& tw = __get_evaluator__ ();\n\n  octave_user_function *oct_usr_fcn = m_fcn.user_function_value ();\n\n  std::shared_ptr<stack_frame> frames = m_stack_context.lock ();\n\n  tw.push_stack_frame (oct_usr_fcn, m_local_vars, frames);\n\n  unwind_action act ([&tw] () { tw.pop_stack_frame (); });\n\n  return oct_usr_fcn->execute (tw, nargout, args);\n}\n\noctave_value\nweak_anonymous_fcn_handle::workspace () const\n{\n  octave_scalar_map local_vars_map;\n\n  for (const auto& nm_val : m_local_vars)\n    local_vars_map.assign (nm_val.first, nm_val.second);\n\n  // FIXME: it would be more convenient if stack_frame::workspace\n  // returned a Cell object directly instead of a Cell in an\n  // octave_value object.\n\n  std::shared_ptr<stack_frame> frames = m_stack_context.lock ();\n\n  Cell cell_frames;\n\n  if (frames)\n    {\n      octave_value ov_frames = frames->workspace ();\n      cell_frames = ov_frames.cell_value ();\n    }\n\n  octave_idx_type num_frames = cell_frames.numel ();\n\n  // FIXME: It seems there should be a simple way to concatenate\n  // cells...\n  Cell retval = Cell (num_frames+1, 1);\n  retval(0) = m_local_vars;\n  for (octave_idx_type i = 0; i < num_frames; i++)\n    retval(i+1) = cell_frames(i);\n\n  return retval;\n}\n\nbool\nis_equal_to (const weak_anonymous_fcn_handle& fh1,\n             const weak_anonymous_fcn_handle& fh2)\n{\n  if (fh1.m_name == fh2.m_name\n      && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ())\n    return fh1.m_fcn.is_copy_of (fh2.m_fcn);\n  else\n    return false;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\noctave_fcn_handle::octave_fcn_handle ()\n  : octave_base_value (), m_rep (new octave::invalid_fcn_handle ())\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const octave_value& fcn)\n  : octave_base_value (), m_rep (new octave::internal_fcn_handle (fcn))\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const std::string& name)\n  : octave_base_value (), m_rep (new octave::simple_fcn_handle (name))\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const octave_value& fcn,\n                                      const std::string& name)\n  : octave_base_value (), m_rep (new octave::simple_fcn_handle (fcn, name))\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const std::string& class_nm,\n                                      const std::string& meth_nm)\n  : octave_base_value (),\n    m_rep (new octave::class_simple_fcn_handle (class_nm, meth_nm))\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const octave_value& fcn,\n                                      const std::string& class_nm,\n                                      const std::string& meth_nm)\n  : octave_base_value (),\n    m_rep (new octave::class_simple_fcn_handle (fcn, class_nm, meth_nm))\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const octave_value& obj,\n                                      const octave_value& fcn,\n                                      const std::string& class_nm,\n                                      const std::string& meth_nm)\n  : octave_base_value (),\n    m_rep (new octave::class_simple_fcn_handle (obj, fcn, class_nm, meth_nm))\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const octave_value& fcn,\n                                      const std::string& name,\n                                      const std::list<std::string>& parentage)\n  : octave_base_value (),\n    m_rep (new octave::scoped_fcn_handle (fcn, name, parentage))\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const octave_value& fcn,\n                                      const std::string& name,\n                                      const std::shared_ptr<octave::stack_frame>& stack_context)\n  : octave_base_value (),\n    m_rep (new octave::nested_fcn_handle (fcn, name, stack_context))\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const octave_value& fcn,\n                                      const octave::stack_frame::local_vars_map& local_vars,\n                                      const std::shared_ptr<octave::stack_frame>& stack_context)\n  : octave_base_value (),\n    m_rep (new octave::anonymous_fcn_handle (fcn, local_vars, stack_context))\n{ }\n\noctave_fcn_handle::octave_fcn_handle (octave::base_fcn_handle *rep)\n  : octave_base_value (), m_rep (rep)\n{ }\n\noctave_fcn_handle::octave_fcn_handle (const octave_fcn_handle& fh)\n  : octave_base_value (fh)\n{\n  m_rep.reset (fh.m_rep->clone ());\n}\n\ndim_vector\noctave_fcn_handle::dims () const\n{\n  static dim_vector dv (1, 1);\n  return dv;\n}\n\nbool\noctave_fcn_handle::save_ascii (std::ostream& os)\n{\n  return m_rep->save_ascii (os);\n}\n\nbool\noctave_fcn_handle::load_ascii (std::istream& is)\n{\n  std::shared_ptr<octave::base_fcn_handle> new_rep;\n\n  // Read enough to detect type then create new rep object and dispatch\n  // to finish loading object.\n\n  std::streampos pos = is.tellg ();\n\n  std::string octaveroot = extract_keyword (is, \"octaveroot\", true);\n  if (octaveroot.empty ())\n    {\n      is.seekg (pos);\n      is.clear ();\n    }\n\n  pos = is.tellg ();\n\n  std::string fpath = extract_keyword (is, \"path\", true);\n  if (fpath.empty ())\n    {\n      is.seekg (pos);\n      is.clear ();\n    }\n\n  if (! (octaveroot.empty () || fpath.empty ()))\n    {\n      std::size_t len = octaveroot.size ();\n      if (octaveroot == fpath.substr (0, len))\n        fpath = octave::config::octave_exec_home () + fpath.substr (len);\n    }\n\n  pos = is.tellg ();\n\n  std::string subtype = extract_keyword (is, \"subtype\", true);\n  if (subtype.empty ())\n    {\n      is.seekg (pos);\n      is.clear ();\n\n      // We have a legacy file that can contain either an anonymous\n      // function or a simple function handle.\n\n      std::string name;\n      is >> name;\n\n      if (name == anonymous)\n        new_rep.reset (new octave::anonymous_fcn_handle ());\n      else\n        new_rep.reset (new octave::simple_fcn_handle (name, fpath, octaveroot));\n    }\n  else\n    {\n      // Load individual function handle types.\n\n      if (subtype == \"simple\")\n        {\n          std::string name;\n          is >> name;\n\n          new_rep.reset (new octave::simple_fcn_handle (name, fpath,\n                         octaveroot));\n        }\n      else if (subtype == \"scopedfunction\")\n        {\n          std::string name;\n          is >> name;\n\n          new_rep.reset (new octave::scoped_fcn_handle (name, fpath,\n                         octaveroot));\n        }\n      else if (subtype == \"anonymous\")\n        new_rep.reset (new octave::anonymous_fcn_handle ());\n      else if (subtype == \"nested\")\n        {\n          std::string name;\n          is >> name;\n\n          new_rep.reset (new octave::nested_fcn_handle (name, fpath,\n                         octaveroot));\n        }\n      else if (subtype == \"classsimple\")\n        {\n          std::string name;\n          is >> name;\n\n          new_rep.reset (new octave::class_simple_fcn_handle (name, fpath,\n                         octaveroot));\n        }\n    }\n\n  if (! new_rep)\n    return false;\n\n  if (! new_rep->load_ascii (is))\n    return false;\n\n  m_rep = new_rep;\n\n  return true;\n}\n\nbool\noctave_fcn_handle::save_binary (std::ostream& os, bool save_as_floats)\n{\n  return m_rep->save_binary (os, save_as_floats);\n}\n\nbool\noctave_fcn_handle::load_binary (std::istream& is, bool swap,\n                                octave::mach_info::float_format fmt)\n{\n  // Read enough to detect type then create new rep object and dispatch\n  // to finish loading object.\n\n  int32_t tmp;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&tmp);\n\n  OCTAVE_LOCAL_BUFFER (char, ctmp1, tmp+1);\n  // is.get (ctmp1, tmp+1, 0); caused is.eof () to be true though\n  // effectively not reading over file end\n  is.read (ctmp1, tmp);\n  ctmp1[tmp] = 0;\n  std::string name (ctmp1);\n\n  if (! is)\n    return false;\n\n  std::shared_ptr<octave::base_fcn_handle> new_rep;\n\n  std::size_t anl = anonymous.length ();\n\n  if (name.length () >= anl && name.substr (0, anl) == anonymous)\n    {\n      // Even with extra info stored in the function name, anonymous\n      // functions look the same.  Note that NAME here may have the\n      // number of local variables appended.  We decode that inside the\n      // load_binary function.\n\n      new_rep.reset (new octave::anonymous_fcn_handle (name));\n    }\n  else\n    {\n      // Unpack extra info stored with the function name and load\n      // individual function handle types.\n      // FIXME: is there a better way?\n\n      std::string octaveroot;\n      std::string fpath;\n      std::string subtype = \"simple\";\n\n      if (name.find_first_of ('\\n') != std::string::npos)\n        {\n          std::size_t pos1 = name.find_first_of ('\\n');\n          std::size_t pos2 = name.find_first_of ('\\n', pos1 + 1);\n          octaveroot = name.substr (pos1 + 1, pos2 - pos1 - 1);\n          fpath = name.substr (pos2 + 1);\n          name = name.substr (0, pos1);\n        }\n\n      std::size_t pos1 = name.find ('@');\n      if (pos1 != std::string::npos)\n        {\n          if (name[pos1+1] == '<')\n            {\n              std::size_t pos2 = name.find ('>', pos1 + 2);\n\n              if (pos2 != std::string::npos)\n                subtype = name.substr (pos1 + 2, pos2 - pos1 - 2);\n            }\n\n          name = name.substr (0, pos1);\n        }\n\n      // Anonymous should have been handled above so it is not in the\n      // following list.\n\n      if (subtype == \"simple\")\n        new_rep.reset (new octave::simple_fcn_handle (name, fpath, octaveroot));\n      else if (subtype == \"scopedfunction\")\n        new_rep.reset (new octave::scoped_fcn_handle (name, fpath, octaveroot));\n      else if (subtype == \"nested\")\n        new_rep.reset (new octave::nested_fcn_handle (name, fpath, octaveroot));\n      else if (subtype == \"classsimple\")\n        new_rep.reset (new octave::class_simple_fcn_handle (name, fpath,\n                       octaveroot));\n    }\n\n  if (! new_rep)\n    return false;\n\n  if (! new_rep->load_binary (is, swap, fmt))\n    return false;\n\n  m_rep = new_rep;\n\n  return true;\n}\n\nbool\noctave_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                              bool save_as_floats)\n{\n  return m_rep->save_hdf5 (loc_id, name, save_as_floats);\n}\n\nbool\noctave_fcn_handle::load_hdf5 (octave_hdf5_id loc_id, const char *name_arg)\n{\n#if defined (HAVE_HDF5)\n\n#if defined (HAVE_HDF5_18)\n  octave_hdf5_id group_hid = H5Gopen (loc_id, name_arg, octave_H5P_DEFAULT);\n#else\n  octave_hdf5_id group_hid = H5Gopen (loc_id, name_arg);\n#endif\n  if (group_hid < 0)\n    return false;\n\n#if defined (HAVE_HDF5_18)\n  octave_hdf5_id data_hid = H5Dopen (group_hid, \"nm\", octave_H5P_DEFAULT);\n#else\n  octave_hdf5_id data_hid = H5Dopen (group_hid, \"nm\");\n#endif\n\n  if (data_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  octave_hdf5_id type_hid = H5Dget_type (data_hid);\n  octave_hdf5_id type_class_hid = H5Tget_class (type_hid);\n\n  if (type_class_hid != H5T_STRING)\n    {\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  octave_hdf5_id space_hid = H5Dget_space (data_hid);\n  hsize_t rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  int slen = H5Tget_size (type_hid);\n  if (slen < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (char, nm_tmp, slen);\n\n  // create datatype for (null-terminated) string to read into:\n  octave_hdf5_id st_id = H5Tcopy (H5T_C_S1);\n  H5Tset_size (st_id, slen);\n\n  if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, nm_tmp)\n      < 0)\n    {\n      H5Tclose (st_id);\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n  H5Tclose (st_id);\n  H5Dclose (data_hid);\n\n  std::string name (nm_tmp);\n\n  std::shared_ptr<octave::base_fcn_handle> new_rep;\n\n  if (name == anonymous)\n    {\n      // Even with extra info stored in the function name, anonymous\n      // functions look the same.\n\n      new_rep.reset (new octave::anonymous_fcn_handle ());\n    }\n  else\n    {\n      // Unpack extra info stored with the function name and load\n      // individual function handle types.\n      // FIXME: is there a better way?\n\n      std::string octaveroot;\n      std::string fpath;\n      std::string subtype = \"simple\";\n\n      if (name.find_first_of ('\\n') != std::string::npos)\n        {\n          std::size_t pos1 = name.find_first_of ('\\n');\n          std::size_t pos2 = name.find_first_of ('\\n', pos1 + 1);\n          octaveroot = name.substr (pos1 + 1, pos2 - pos1 - 1);\n          fpath = name.substr (pos2 + 1);\n          name = name.substr (0, pos1);\n        }\n\n      std::size_t pos1 = name.find ('@');\n      if (pos1 != std::string::npos)\n        {\n          if (name[pos1+1] == '<')\n            {\n              std::size_t pos2 = name.find ('>', pos1 + 2);\n\n              if (pos2 != std::string::npos)\n                subtype = name.substr (pos1 + 2, pos2 - pos1 - 2);\n            }\n\n          name = name.substr (0, pos1);\n        }\n\n      // Anonymous should have been handled above so it is not in the\n      // following list.\n\n      if (subtype == \"simple\")\n        new_rep.reset (new octave::simple_fcn_handle (name, fpath, octaveroot));\n      else if (subtype == \"scopedfunction\")\n        new_rep.reset (new octave::scoped_fcn_handle (name, fpath, octaveroot));\n      else if (subtype == \"nested\")\n        new_rep.reset (new octave::nested_fcn_handle (name, fpath, octaveroot));\n      else if (subtype == \"classsimple\")\n        new_rep.reset (new octave::class_simple_fcn_handle (name, fpath,\n                       octaveroot));\n    }\n\n  bool status = false;\n\n  if (new_rep && new_rep->load_hdf5 (group_hid, space_hid, type_hid))\n    {\n      m_rep = new_rep;\n      status = true;\n    }\n\n  // FIXME: manage these with an unwind_action object?\n\n  H5Tclose (type_hid);\n  H5Sclose (space_hid);\n  H5Gclose (group_hid);\n\n  return status;\n\n#else\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name_arg);\n\n  warn_load (\"hdf5\");\n\n  return false;\n\n#endif\n}\n\n/*\n%!test <*33857>\n%! a = 2;\n%! f = @(x) a + x;\n%! g = @(x) 2 * x;\n%! hm = @version;\n%! hdld = @svd;\n%! hbi = @log2;\n%! f2 = f;\n%! g2 = g;\n%! hm2 = hm;\n%! hdld2 = hdld;\n%! hbi2 = hbi;\n%! modes = {\"-text\", \"-binary\"};\n%! if (isfield (__octave_config_info__, \"HAVE_HDF5\")\n%!     && __octave_config_info__ (\"HAVE_HDF5\"))\n%!   modes(end+1) = \"-hdf5\";\n%! endif\n%! for i = 1:numel (modes)\n%!   mode = modes{i};\n%!   nm = tempname ();\n%!   unwind_protect\n%!     f2 (1);\n%!     save (mode, nm, \"f2\", \"g2\", \"hm2\", \"hdld2\", \"hbi2\");\n%!     clear f2 g2 hm2 hdld2 hbi2\n%!     load (nm);\n%!     assert (f (2), f2 (2));\n%!     assert (g (2), g2 (2));\n%!     assert (g (3), g2 (3));\n%!     unlink (nm);\n%!     save (mode, nm, \"f2\", \"g2\", \"hm2\", \"hdld2\", \"hbi2\");\n%!   unwind_protect_cleanup\n%!     delete ([nm, '*']);\n%!   end_unwind_protect\n%! endfor\n*/\n\n/*\n%!function fcn_handle_save_recurse (n, mode, nm, f2, g2, hm2, hdld2, hbi2)\n%!  if (n == 0)\n%!    save (mode, nm, \"f2\", \"g2\", \"hm2\", \"hdld2\", \"hbi2\");\n%!  else\n%!    fcn_handle_save_recurse (n - 1, mode, nm, f2, g2, hm2, hdld2, hbi2);\n%!  endif\n%!endfunction\n%!function [f2, g2, hm2, hdld2, hbi2] = fcn_handle_load_recurse (n, nm)\n%!  if (n == 0)\n%!    load (nm);\n%!  else\n%!    [f2, g2, hm2, hdld2, hbi2] = fcn_handle_load_recurse (n - 1, nm);\n%!  endif\n%!endfunction\n\n%!test <*35876>\n%! a = 2;\n%! f = @(x) a + x;\n%! g = @(x) 2 * x;\n%! hm = @version;\n%! hdld = @svd;\n%! hbi = @log2;\n%! f2 = f;\n%! g2 = g;\n%! hm2 = hm;\n%! hdld2 = hdld;\n%! hbi2 = hbi;\n%! modes = {\"-text\", \"-binary\"};\n%! if (isfield (__octave_config_info__, \"HAVE_HDF5\")\n%!     && __octave_config_info__ (\"HAVE_HDF5\"))\n%!   modes(end+1) = \"-hdf5\";\n%! endif\n%! for i = 1:numel (modes)\n%!   mode = modes{i};\n%!   nm = tempname ();\n%!   unwind_protect\n%!     fcn_handle_save_recurse (2, mode, nm, f2, g2, hm2, hdld2, hbi2);\n%!     clear f2 g2 hm2 hdld2 hbi2\n%!     [f2, f2, hm2, hdld2, hbi2] = fcn_handle_load_recurse (2, nm);\n%!     load (nm);\n%!     assert (f (2), f2 (2));\n%!     assert (g (2), g2 (2));\n%!     assert (g (3), g2 (3));\n%!     unlink (nm);\n%!     fcn_handle_save_recurse (2, mode, nm, f2, g2, hm2, hdld2, hbi2);\n%!   unwind_protect_cleanup\n%!     delete ([nm, '*']);\n%!   end_unwind_protect\n%! endfor\n*/\n\nvoid\noctave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\n\nvoid\noctave_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax) const\n{\n  m_rep->print_raw (os, pr_as_read_syntax, current_print_indent_level ());\n}\n\nbool\nis_equal_to (const octave_fcn_handle& fh1, const octave_fcn_handle& fh2)\n{\n  // FIXME: Maybe there is a better way?  Possibly by using typeid or\n  // typeindex?\n\n  // Don't include invalid_fcn_handle in the list of types to compare.\n  // Consider them to be like NaN values so comparisons between any two\n  // invalid handles are always false.\n\n  if (fh1.is_internal () && fh2.is_internal ())\n    return is_equal_to (*dynamic_cast<octave::internal_fcn_handle *> (fh1.get_rep ()),\n                        *dynamic_cast<octave::internal_fcn_handle *> (fh2.get_rep ()));\n  else if (fh1.is_simple () && fh2.is_simple ())\n    return is_equal_to (*dynamic_cast<octave::simple_fcn_handle *> (fh1.get_rep ()),\n                        *dynamic_cast<octave::simple_fcn_handle *> (fh2.get_rep ()));\n  else if (fh1.is_scoped () && fh2.is_scoped ())\n    return is_equal_to (*dynamic_cast<octave::scoped_fcn_handle *> (fh1.get_rep ()),\n                        *dynamic_cast<octave::scoped_fcn_handle *> (fh2.get_rep ()));\n  else if (fh1.is_nested () && fh2.is_nested ())\n    return is_equal_to (*dynamic_cast<octave::nested_fcn_handle *> (fh1.get_rep ()),\n                        *dynamic_cast<octave::nested_fcn_handle *> (fh2.get_rep ()));\n  else if (fh1.is_class_simple () && fh2.is_class_simple ())\n    return is_equal_to (*dynamic_cast<octave::class_simple_fcn_handle *> (fh1.get_rep ()),\n                        *dynamic_cast<octave::class_simple_fcn_handle *> (fh2.get_rep ()));\n  else if (fh1.is_anonymous () && fh2.is_anonymous ())\n    return is_equal_to (*dynamic_cast<octave::anonymous_fcn_handle *> (fh1.get_rep ()),\n                        *dynamic_cast<octave::anonymous_fcn_handle *> (fh2.get_rep ()));\n  else\n    return false;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (functions, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{s} =} functions (@var{fcn_handle})\nReturn a structure containing information about the function handle\n@var{fcn_handle}.\n\nThe structure @var{s} always contains these three fields:\n\n@table @asis\n@item function\nThe function name.  For an anonymous function (no name) this will be the\nactual function definition.\n\n@item type\nType of the function.\n\n@table @asis\n@item anonymous\nThe function is anonymous.\n\n@item private\nThe function is private.\n\n@item overloaded\nThe function overloads an existing function.\n\n@item simple\nThe function is a built-in or m-file function.\n\n@item subfunction\nThe function is a subfunction within an m-file.\n@end table\n\n@item nested\nThe function is nested.\n\n@item file\nThe m-file that will be called to perform the function.  This field is empty\nfor anonymous and built-in functions.\n@end table\n\nIn addition, some function types may return more information in additional\nfields.\n\n@strong{Warning:} @code{functions} is provided for debugging purposes only.\nIts behavior may change in the future and programs should not depend on any\nparticular output format.\n\n@seealso{func2str, str2func}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_fcn_handle *fh = args(0).xfcn_handle_value (\"functions: FCN_HANDLE argument must be a function handle object\");\n\n  return ovl (fh->info ());\n}\n\nDEFUN (func2str, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{str} =} func2str (@var{fcn_handle})\nReturn a string containing the name of the function referenced by the function\nhandle @var{fcn_handle}.\n@seealso{str2func, functions}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  octave_fcn_handle *fh = args(0).xfcn_handle_value (\"func2str: FCN_HANDLE argument must be a function handle object\");\n\n  if (! fh)\n    error (\"func2str: FCN_HANDLE must be a valid function handle\");\n\n  octave_value retval;\n\n  std::string fh_nm = fh->fcn_name ();\n\n  if (fh->is_anonymous ())\n    {\n      std::ostringstream buf;\n\n      fh->print_raw (buf);\n\n      retval = buf.str ();\n    }\n  else\n    retval = fh_nm;\n\n  return retval;\n}\n\nDEFMETHOD (str2func, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{hfcn} =} str2func (@var{str})\nReturn a function handle constructed from the string @var{str}.\n\nThe input may be the name of a function such as @qcode{\"sin\"} or a string\ndefining a function such as @qcode{\"@@(x) sin (x + pi)\"}.\n\nProgramming Note: In most cases it will be better to use anonymous function\nsyntax and let the Octave parser create the function handle rather than use\n@code{str2func}.  For example:\n\n@example\n@group\nhfcn = @@sin ;\nhfcn = @@(x) sin (x + pi) ;\n@end group\n@end example\n\n@seealso{func2str, functions}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string nm = args(0).xstring_value (\"str2func: FCN_NAME must be a string\");\n\n  if (nm.empty ())\n    error (\"str2func: invalid function name\");\n\n  if (nm[0] == '@')\n    {\n      // Unlike the anonymous_fcn_handle::parse method, don't set up\n      // temporary scope to use for evaluating the text that defines\n      // the anonymous function.  Here we want\n      //\n      //   str2func (\"@(args) expr\")\n      //\n      // to behave the same as if\n      //\n      //   @(args) expr\n      //\n      // were evaluated in the current scope.\n\n      int parse_status;\n      octave_value afh = interp.eval_string (nm, true, parse_status);\n\n      if (parse_status == 0)\n        return afh;\n    }\n  else\n    {\n      if (nargin == 2)\n        warning_with_id (\"Octave:str2func-global-argument\",\n                         \"str2func: second argument ignored\");\n\n      tree_evaluator& tw = interp.get_evaluator ();\n\n      return tw.make_fcn_handle (nm);\n    }\n\n  return ovl ();\n}\n\n/*\n%!test\n%! f = str2func (\"<\");\n%! assert (class (f), \"function_handle\");\n%! assert (func2str (f), \"lt\");\n%! assert (f (1, 2), true);\n%! assert (f (2, 1), false);\n\n%!test\n%! f = str2func (\"@(x) sin (x)\");\n%! assert (func2str (f), \"@(x) sin (x)\");\n%! assert (f (0:3), sin (0:3));\n\n%!error <FCN_NAME must be a string> str2func ({\"sin\"})\n*/\n\n/*\n%!function y = __testrecursionfcn (f, x, n)\n%!  if (nargin < 3)\n%!    n = 0;\n%!  endif\n%!  if (n > 2)\n%!    y = f (x);\n%!  else\n%!    n++;\n%!    y = __testrecursionfcn (@(x) f (2*x), x, n);\n%!  endif\n%!endfunction\n%!\n%!assert (__testrecursionfcn (@(x) x, 1), 8)\n*/\n\nDEFUN (is_function_handle, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} is_function_handle (@var{x})\nReturn true if @var{x} is a function handle.\n@seealso{isa, typeinfo, class, functions}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).is_function_handle ());\n}\n\n/*\n%!shared fh\n%! fh = @(x) x;\n\n%!assert (is_function_handle (fh))\n%!assert (! is_function_handle ({fh}))\n%!assert (! is_function_handle (1))\n\n%!error is_function_handle ()\n%!error is_function_handle (1, 2)\n*/\n\n/*\n%!test\n%! f = @(t) eval ('2*t');\n%! assert (f (21), 42);\n*/\n\n/*\n%!test <*58389>\n%! s = \"x\";\n%! a.(s) = [e, pi];\n%! f = @(x) a.(s)(x);\n%! assert (f(1), e);\n%! assert (f(2), pi);\n%! assert (f([2,1]), [pi, e]);\n*/\n\n/*\n%!function r = __f (g, i)\n%!  r = g(i);\n%!endfunction\n%!test\n%! x = [1,2;3,4];\n%! assert (__f (@(i) x(:,i), 1), [1;3]);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-fcn-handle.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_fcn_handle_h)\n#define octave_ov_fcn_handle_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <list>\n#include <memory>\n#include <string>\n\n#include \"oct-map.h\"\n#include \"ov-base.h\"\n#include \"ov-fcn.h\"\n#include \"ov-typeinfo.h\"\n#include \"stack-frame.h\"\n#include \"symscope.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\nclass tree_evaluator;\n\n// Function handles.\n\nclass OCTINTERP_API base_fcn_handle\n{\npublic:\n\n  base_fcn_handle (const std::string& name = \"\",\n                   const std::string& file = \"\")\n    : m_name (name), m_file (file)\n  { }\n\n  base_fcn_handle (const base_fcn_handle&) = default;\n\n  virtual ~base_fcn_handle () = default;\n\n  virtual base_fcn_handle * clone () const = 0;\n\n  virtual std::string type () const = 0;\n\n  virtual bool is_internal () const { return false; }\n\n  virtual bool is_simple () const { return false; }\n\n  virtual bool is_scoped () const { return false; }\n\n  virtual bool is_nested () const { return false; }\n\n  virtual bool is_nested (const std::shared_ptr<stack_frame>&) const\n  {\n    return false;\n  }\n\n  virtual bool is_weak_nested () const { return false; }\n\n  virtual bool is_class_simple () const { return false; }\n\n  virtual bool is_anonymous () const { return false; }\n\n  virtual bool is_weak_anonymous () const { return false; }\n\n  virtual OCTINTERP_API octave_value make_weak_nested_handle () const;\n\n  virtual OCTINTERP_API octave_value make_weak_anonymous_handle () const;\n\n  std::string fcn_name () const { return m_name; }\n\n  std::string file () const { return m_file; }\n\n  OCTINTERP_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int nargout);\n\n  virtual octave_value_list\n  call (int nargout, const octave_value_list& args) = 0;\n\n  // FIXME: These must go away.  They don't do the right thing for\n  // scoping or overloads.\n  virtual octave_function * function_value (bool = false)\n  {\n    return nullptr;\n  }\n\n  virtual octave_user_function * user_function_value (bool = false)\n  {\n    return nullptr;\n  }\n\n  virtual octave_value fcn_val () { return octave_value (); }\n\n  virtual octave_value workspace () const { return octave_value (); }\n\n  // Should be const.\n  virtual octave_scalar_map info () { return octave_scalar_map (); }\n\n  virtual void set_dispatch_class (const std::string& /*class_name*/) { }\n\n  virtual std::string get_dispatch_class () const { return \"\"; }\n\n  OCTINTERP_API octave_value\n  convert_to_str_internal (bool pad, bool force, char type) const;\n\n  virtual OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  virtual OCTINTERP_API bool load_ascii (std::istream& is);\n\n  virtual OCTINTERP_API bool\n  save_binary (std::ostream& os, bool save_as_floats);\n\n  virtual OCTINTERP_API bool\n  load_binary (std::istream& is, bool swap, mach_info::float_format fmt);\n\n  virtual OCTINTERP_API bool\n  save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  virtual OCTINTERP_API bool\n  load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid,\n             octave_hdf5_id& type_hid);\n\n  virtual void print_raw (std::ostream&, bool /*pr_as_read_syntax*/,\n                          int /*current_print_indent_level*/) const\n  { }\n\n  // Function handles are printed without a newline by default.\n  virtual bool print_as_scalar () const { return true; }\n\n  virtual bool\n  set_fcn (const std::string& /*octaveroot*/, const std::string& /*fpath*/)\n  {\n    return false;\n  }\n\n  virtual octave_function *\n  get_cached_fcn (void *, void *) { return nullptr; }\n\n  virtual octave_function *\n  get_cached_fcn (const octave_value_list&) { return nullptr; }\n\n  virtual bool\n  has_function_cache () const { return false; }\n\n  virtual void compile () { }\n\nprotected:\n\n  OCTINTERP_API void warn_load (const char *file_type) const;\n  OCTINTERP_API void warn_save (const char *file_type) const;\n\n  OCTINTERP_API void unimplemented (const char *op, const char *fmt) const;\n\n  // The name of the handle, not including the \"@\", or the text of the\n  // anonymous function.\n  std::string m_name;\n\n  // The name of the file where the named function was defined.\n  std::string m_file;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\nclass OCTINTERP_API octave_fcn_handle : public octave_base_value\n{\npublic:\n\n  static const std::string anonymous;\n\n  // Creates an invalid function handle.  Used to create generic\n  // function handle objects when loading function handles.  Further\n  // dispatch happens in the octave_fcn_handle load/save functions.\n  octave_fcn_handle ();\n\n  // Create a handle to a built-in or internal function.\n  octave_fcn_handle (const octave_value& fcn);\n\n  // Create a simple function handle that is not bound to a function.\n  // Lookup happens when a function call is attempted.\n  octave_fcn_handle (const std::string& name);\n\n  // Create a simple function handle that is bound to a function.\n  octave_fcn_handle (const octave_value& fcn, const std::string& name);\n\n  // Create a function handle that might be bound to a class method.\n  octave_fcn_handle (const std::string& class_nm, const std::string& meth_nm);\n\n  // Create a function handle bound to a class method.\n  octave_fcn_handle (const octave_value& fcn, const std::string& class_nm,\n                     const std::string& meth_nm);\n\n  // Create a function handle bound to a class method.\n  octave_fcn_handle (const octave_value& obj, const octave_value& fcn,\n                     const std::string& class_nm,\n                     const std::string& meth_nm);\n\n  // Create a function handle bound to a scoped function.\n  octave_fcn_handle (const octave_value& fcn, const std::string& name,\n                     const std::list<std::string>& parentage);\n\n  // Create a handle to a nested function.\n  octave_fcn_handle (const octave_value& fcn, const std::string& name,\n                     const std::shared_ptr<octave::stack_frame>& closure_frames);\n\n  // Create an anonymous function handle with local variable values\n  // provided in LOCAL_VARS.\n  octave_fcn_handle (const octave_value& fcn,\n                     const octave::stack_frame::local_vars_map& local_vars,\n                     const std::shared_ptr<octave::stack_frame>& closure_frames\n                     = std::shared_ptr<octave::stack_frame> ());\n\n  // Create a simple function handle that is not bound to a function.\n  // Lookup happens when a function call is attempted and the function\n  // lookup is cached in a octave_fcn_cache.\n  octave_fcn_handle (const std::string& name, octave_value cache);\n\n  octave_fcn_handle (octave::base_fcn_handle *rep);\n\n  octave_fcn_handle (const octave_fcn_handle& fh);\n\n  ~octave_fcn_handle () = default;\n\n  octave_base_value * clone () const\n  {\n    return new octave_fcn_handle (*this);\n  }\n\n  octave_base_value * empty_clone () const\n  {\n    return new octave_fcn_handle ();\n  }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx)\n  {\n    octave_value_list tmp = subsref (type, idx, 1);\n    return tmp.length () > 0 ? tmp(0) : octave_value ();\n  }\n\n  octave_value_list subsref (const std::string& type,\n                             const std::list<octave_value_list>& idx,\n                             int nargout)\n  {\n    return m_rep->subsref (type, idx, nargout);\n  }\n\n  octave_value_list call (int nargout, const octave_value_list& args);\n\n  bool is_defined () const { return true; }\n\n  builtin_type_t builtin_type () const { return btyp_func_handle; }\n\n  bool is_function_handle () const { return true; }\n\n  bool is_internal () const { return m_rep->is_internal (); }\n\n  bool is_simple () const { return m_rep->is_simple (); }\n\n  bool is_scoped () const { return m_rep->is_scoped (); }\n\n  bool is_nested () const { return m_rep->is_nested (); }\n\n  bool is_nested (const std::shared_ptr<octave::stack_frame>& frame) const\n  {\n    return m_rep->is_nested (frame);\n  }\n\n  bool is_weak_nested () const { return m_rep->is_weak_nested (); }\n\n  bool is_class_simple () const { return m_rep->is_class_simple (); }\n\n  bool is_anonymous () const { return m_rep->is_anonymous (); }\n\n  bool is_weak_anonymous () const { return m_rep->is_weak_anonymous (); }\n\n  octave_value make_weak_nested_handle () const\n  {\n    return m_rep->make_weak_nested_handle ();\n  }\n\n  octave_value make_weak_anonymous_handle () const\n  {\n    return m_rep->make_weak_anonymous_handle ();\n  }\n\n  dim_vector dims () const;\n\n  // FIXME: These must go away.  They don't do the right thing for\n  // scoping or overloads.\n  octave_function * function_value (bool = false)\n  {\n    return m_rep->function_value ();\n  }\n\n  octave_user_function * user_function_value (bool = false)\n  {\n    return m_rep->user_function_value ();\n  }\n\n  octave_fcn_handle * fcn_handle_value (bool = false) { return this; }\n\n  octave_value fcn_val () { return m_rep->fcn_val (); }\n\n  // FCN_NAME should be eliminated.\n  std::string fcn_name () const { return m_rep->fcn_name (); }\n\n  octave_value workspace () const\n  {\n    return m_rep->workspace ();\n  }\n\n  octave_scalar_map info () { return m_rep->info (); }\n\n  void set_dispatch_class (const std::string& class_name)\n  {\n    m_rep->set_dispatch_class (class_name);\n  }\n\n  std::string get_dispatch_class () const\n  {\n    return m_rep->get_dispatch_class ();\n  }\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const\n  {\n    return m_rep->convert_to_str_internal (pad, force, type);\n  }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  // Simple function handles are printed without a newline.\n  bool print_as_scalar () const { return m_rep->print_as_scalar (); }\n\n  friend bool\n  is_equal_to (const octave_fcn_handle& fh1, const octave_fcn_handle& fh2);\n\nprivate:\n\n  std::shared_ptr<octave::base_fcn_handle> m_rep;\n\n  octave::base_fcn_handle * get_rep () const { return m_rep.get (); }\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\nextern bool\nis_equal_to (const octave_fcn_handle& fh1, const octave_fcn_handle& fh2);\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-fcn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-array-errwarn.h\"\n#include \"unwind-prot.h\"\n\n#include \"error.h\"\n#include \"filepos.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ov-fcn.h\"\n#include \"ovl.h\"\n#include \"pt-eval.h\"\n#include \"symtab.h\"\n\noctave_base_value *\noctave_function::clone () const\n{\n  error (\"unexpected call to octave_function::clone - please report this bug\");\n}\n\noctave_base_value *\noctave_function::empty_clone () const\n{\n  error (\"unexpected call to octave_function::empty_clone - please report this bug\");\n}\n\noctave::filepos\noctave_function::beg_pos () const\n{\n  error (\"unexpected call to octave_function::beg_pos - please report this bug\");\n}\n\noctave::filepos\noctave_function::end_pos () const\n{\n  error (\"unexpected call to octave_function::end_pos - please report this bug\");\n}\n\noctave::comment_list\noctave_function::leading_comments () const\n{\n  error (\"unexpected call to octave_function::leading_comments - please report this bug\");\n}\n\noctave::comment_list\noctave_function::trailing_comments () const\n{\n  error (\"unexpected call to octave_function::trailing_comments - please report this bug\");\n}\n\noctave_value_list\noctave_function::call (octave::tree_evaluator& tw, int nargout,\n                       const octave_value_list& args)\n{\n  tw.push_stack_frame (this);\n\n  octave::unwind_action act ([&tw] () { tw.pop_stack_frame (); });\n\n  return execute (tw, nargout, args);\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-fcn.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_fcn_h)\n#define octave_ov_fcn_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"oct-time.h\"\n#include \"str-vec.h\"\n\n#include \"comment-list.h\"\n#include \"ovl.h\"\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n#include \"symscope.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass filepos;\nclass stack_frame;\nclass tree_evaluator;\nclass tree_walker;\n\nOCTAVE_END_NAMESPACE(octave)\n\n// Functions.\n\nclass OCTINTERP_API octave_function : public octave_base_value\n{\npublic:\n\n  octave_function ()\n    : m_relative (false), m_locked (false), m_private (false),\n      m_dispatch_class (), m_package_name (), m_name (), m_dir_name (),\n      m_doc () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_function)\n\n  ~octave_function () = default;\n\n  octave_base_value * clone () const;\n  octave_base_value * empty_clone () const;\n\n  bool is_defined () const { return true; }\n\n  bool is_function () const { return true; }\n\n  virtual bool is_system_fcn_file () const { return false; }\n\n  virtual std::string fcn_file_name () const { return \"\"; }\n\n  virtual std::string src_file_name () const { return \"\"; }\n\n  virtual octave::filepos beg_pos () const;\n  virtual octave::filepos end_pos () const;\n\n  virtual octave::comment_list leading_comments () const;\n  virtual octave::comment_list trailing_comments () const;\n\n  // The name to show in the profiler (also used as map-key).\n  virtual std::string profiler_name () const { return name (); }\n\n  virtual std::string parent_fcn_name () const { return \"\"; }\n\n  virtual octave::symbol_scope parent_fcn_scope () const\n  { return octave::symbol_scope::invalid (); }\n\n  virtual std::list<std::string> parent_fcn_names () const\n  { return std::list<std::string> (); }\n\n  virtual void mark_fcn_file_up_to_date (const octave::sys::time&) { }\n\n  virtual octave::symbol_scope scope () { return octave::symbol_scope::invalid (); }\n\n  virtual octave::sys::time time_parsed () const\n  { return octave::sys::time (static_cast<OCTAVE_TIME_T> (0)); }\n\n  virtual octave::sys::time time_checked () const\n  { return octave::sys::time (static_cast<OCTAVE_TIME_T> (0)); }\n\n  virtual int call_depth () const { return 0; }\n\n  virtual bool is_nested_function () const { return false; }\n\n  virtual bool is_parent_function () const { return false; }\n\n  virtual bool is_subfunction () const { return false; }\n\n  virtual bool is_compiled () const { return false; }\n\n  bool is_class_constructor (const std::string& cname = \"\") const\n  {\n    return (is_classdef_constructor (cname) || is_legacy_constructor (cname));\n  }\n\n  bool is_class_method (const std::string& cname = \"\") const\n  {\n    return (is_classdef_method (cname) || is_legacy_method (cname));\n  }\n\n  virtual bool\n  is_legacy_constructor (const std::string& = \"\") const\n  { return false; }\n\n  virtual bool\n  is_classdef_constructor (const std::string& = \"\") const\n  { return false; }\n\n  virtual bool is_legacy_method (const std::string& = \"\") const\n  { return false; }\n\n  virtual bool is_classdef_method (const std::string& = \"\") const\n  { return false; }\n\n  virtual bool takes_varargs () const { return false; }\n\n  virtual bool takes_var_return () const { return false; }\n\n  // The next two functions are for dispatching to built-in\n  // functions given built-in classes.\n\n  virtual void push_dispatch_class (const std::string&) { }\n\n  virtual bool handles_dispatch_class (const std::string&) const\n  { return false; }\n\n  void stash_dispatch_class (const std::string& nm) { m_dispatch_class = nm; }\n\n  std::string dispatch_class () const { return m_dispatch_class; }\n\n  void stash_package_name (const std::string& pack) { m_package_name = pack; }\n\n  std::string package_name () const { return m_package_name; }\n\n  virtual void\n  mark_as_private_function (const std::string& cname = \"\")\n  {\n    m_private = true;\n    m_dispatch_class = cname;\n  }\n\n  bool is_private_function () const { return m_private; }\n\n  bool is_private_function_of_class (const std::string& nm) const\n  { return m_private && m_dispatch_class == nm; }\n\n  virtual bool\n  is_anonymous_function_of_class (const std::string& = \"\") const\n  { return false; }\n\n  std::string dir_name () const { return m_dir_name; }\n\n  void stash_dir_name (const std::string& dir) { m_dir_name = dir; }\n\n  void lock ()\n  {\n    this->lock_subfunctions ();\n    m_locked = true;\n  }\n\n  void unlock ()\n  {\n    this->unlock_subfunctions ();\n    m_locked = false;\n  }\n\n  bool islocked () const { return m_locked; }\n\n  virtual void lock_subfunctions () { }\n\n  virtual void unlock_subfunctions () { }\n\n  virtual void maybe_relocate_end () { }\n\n  // Not valid until after the function is completely parsed.\n  virtual bool has_subfunctions () const { return false; }\n\n  virtual void stash_subfunction_names (const std::list<std::string>&) { }\n\n  virtual std::list<std::string> subfunction_names () const\n  { return std::list<std::string> (); }\n\n  void mark_relative () { m_relative = true; }\n\n  bool is_relative () const { return m_relative; }\n\n  std::string name () const { return m_name; }\n\n  std::string canonical_name () const\n  {\n    if (m_package_name.empty ())\n      return m_name;\n    else\n      return m_package_name + '.' + m_name;\n  }\n\n  void document (const std::string& ds) { m_doc = ds; }\n\n  virtual std::string\n  doc_string (const std::string& /*meth_name*/ = \"\") const { return m_doc; }\n\n  virtual void unload () { }\n\n  virtual void accept (octave::tree_walker&) { }\n\n  virtual bool accepts_postfix_index (char type) const\n  { return (type == '('); }\n\n  // Push new stack frame (if necessary) and execute function.\n  virtual octave_value_list\n  call (octave::tree_evaluator& tw, int nargout = 0,\n        const octave_value_list& args = octave_value_list ());\n\n  // Execute function without pushing new stack frame (assumes that has\n  // already been done).\n  virtual octave_value_list\n  execute (octave::tree_evaluator& tw, int nargout = 0,\n           const octave_value_list& args = octave_value_list ()) = 0;\n\nprotected:\n\n  octave_function (const std::string& nm,\n                   const std::string& ds = \"\")\n    : m_relative (false), m_locked (false), m_private (false),\n      m_dispatch_class (), m_name (nm), m_dir_name (), m_doc (ds) { }\n\n  // TRUE if this function was found from a m_relative path element.\n  bool m_relative;\n\n  // TRUE if this function is tagged so that it can't be cleared.\n  bool m_locked;\n\n  // TRUE means this is a private function.\n  bool m_private;\n\n  // If this object is a class method or constructor, or a private\n  // function inside a class directory, this is the name of the class\n  // to which the method belongs.\n  std::string m_dispatch_class;\n\n  // If this function is part of a package, this is the full name\n  // of the package to which the function belongs.\n  std::string m_package_name;\n\n  // The name of this function.\n  std::string m_name;\n\n  // The name of the directory in the path where we found this\n  // function.  May be m_relative.\n  std::string m_dir_name;\n\n  // The help text for this function.\n  std::string m_doc;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-float.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"oct-inttypes-fwd.h\"\n\n#include \"data-conv.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-specfun.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-base.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"pr-output.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n#include \"ops.h\"\n\n#include \"ls-oct-text.h\"\n#include \"ls-hdf5.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_scalar, \"float scalar\",\n                                     \"single\");\n\noctave_value\noctave_float_scalar::do_index_op (const octave_value_list& idx, bool resize_ok)\n{\n  // FIXME: this doesn't solve the problem of\n  //\n  //   a = 1; a([1,1], [1,1], [1,1])\n  //\n  // and similar constructions.  Hmm...\n\n  // FIXME: using this constructor avoids narrowing the\n  // 1x1 matrix back to a scalar value.  Need a better solution\n  // to this problem.\n\n  octave_value tmp (new octave_float_matrix (float_matrix_value ()));\n\n  return tmp.index_op (idx, resize_ok);\n}\n\noctave_value\noctave_float_scalar::resize (const dim_vector& dv, bool fill) const\n{\n  if (fill)\n    {\n      FloatNDArray retval (dv, 0);\n\n      if (dv.numel ())\n        retval(0) = scalar;\n\n      return retval;\n    }\n  else\n    {\n      FloatNDArray retval (dv);\n\n      if (dv.numel ())\n        retval(0) = scalar;\n\n      return retval;\n    }\n}\n\noctave_value\noctave_float_scalar::as_double () const\n{\n  return static_cast<double> (scalar);\n}\n\noctave_value\noctave_float_scalar::as_single () const\n{\n  return scalar;\n}\n\noctave_value\noctave_float_scalar::as_int8 () const\n{\n  return octave_int8 (scalar);\n}\n\noctave_value\noctave_float_scalar::as_int16 () const\n{\n  return octave_int16 (scalar);\n}\n\noctave_value\noctave_float_scalar::as_int32 () const\n{\n  return octave_int32 (scalar);\n}\n\noctave_value\noctave_float_scalar::as_int64 () const\n{\n  return octave_int64 (scalar);\n}\n\noctave_value\noctave_float_scalar::as_uint8 () const\n{\n  return octave_uint8 (scalar);\n}\n\noctave_value\noctave_float_scalar::as_uint16 () const\n{\n  return octave_uint16 (scalar);\n}\n\noctave_value\noctave_float_scalar::as_uint32 () const\n{\n  return octave_uint32 (scalar);\n}\n\noctave_value\noctave_float_scalar::as_uint64 () const\n{\n  return octave_uint64 (scalar);\n}\n\noctave_value\noctave_float_scalar::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return FloatDiagMatrix (Array<float> (dim_vector (1, 1), scalar), m, n);\n}\n\noctave_value\noctave_float_scalar::convert_to_str_internal (bool, bool, char type) const\n{\n  octave_value retval;\n\n  if (octave::math::isnan (scalar))\n    octave::err_nan_to_character_conversion ();\n\n  int ival = octave::math::nint (scalar);\n\n  if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())\n    {\n      // FIXME: is there something better we could do?\n\n      ival = 0;\n\n      ::warning (\"range error for conversion to character value\");\n    }\n\n  retval = octave_value (std::string (1, static_cast<char> (ival)), type);\n\n  return retval;\n}\n\nbool\noctave_float_scalar::save_ascii (std::ostream& os)\n{\n  float d = float_value ();\n\n  octave::write_value<float> (os, d);\n\n  os << \"\\n\";\n\n  return true;\n}\n\nbool\noctave_float_scalar::load_ascii (std::istream& is)\n{\n  scalar = octave::read_value<float> (is);\n  if (! is)\n    error (\"load: failed to load scalar constant\");\n\n  return true;\n}\n\nbool\noctave_float_scalar::save_binary (std::ostream& os, bool /* save_as_floats */)\n{\n  char tmp = LS_FLOAT;\n  os.write (reinterpret_cast<char *> (&tmp), 1);\n  float dtmp = float_value ();\n  os.write (reinterpret_cast<char *> (&dtmp), 4);\n\n  return true;\n}\n\nbool\noctave_float_scalar::load_binary (std::istream& is, bool swap,\n                                  octave::mach_info::float_format fmt)\n{\n  char tmp;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n    return false;\n\n  float dtmp;\n  read_floats (is, &dtmp, static_cast<save_type> (tmp), 1, swap, fmt);\n\n  if (! is)\n    return false;\n\n  scalar = dtmp;\n  return true;\n}\n\nbool\noctave_float_scalar::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                                bool /* save_as_floats */)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hsize_t dimens[3] = {0};\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n\n  space_hid = H5Screate_simple (0, dimens, nullptr);\n  if (space_hid < 0) return false;\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_FLOAT, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_FLOAT, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n\n  float tmp = float_value ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_FLOAT, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_float_scalar::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n#if defined (HAVE_HDF5)\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  float dtmp;\n  if (H5Dread (data_hid, H5T_NATIVE_FLOAT, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &dtmp) < 0)\n    {\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  scalar = dtmp;\n\n  H5Dclose (data_hid);\n\n  return true;\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n\n  return false;\n#endif\n}\n\nmxArray *\noctave_float_scalar::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxSINGLE_CLASS, 1, 1, mxREAL);\n\n  mxSingle *pd = static_cast<mxSingle *> (retval->get_data ());\n\n  pd[0] = scalar;\n\n  return retval;\n}\n\noctave_value\noctave_float_scalar::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    case umap_imag:\n      return 0.0f;\n\n    case umap_real:\n    case umap_conj:\n      return scalar;\n\n#define SCALAR_MAPPER(UMAP, FCN)              \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (FCN (scalar))\n\n      SCALAR_MAPPER (abs, ::fabsf);\n      SCALAR_MAPPER (acos, octave::math::rc_acos);\n      SCALAR_MAPPER (acosh, octave::math::rc_acosh);\n      SCALAR_MAPPER (angle, std::arg);\n      SCALAR_MAPPER (arg, std::arg);\n      SCALAR_MAPPER (asin, octave::math::rc_asin);\n      SCALAR_MAPPER (asinh, octave::math::asinh);\n      SCALAR_MAPPER (atan, ::atanf);\n      SCALAR_MAPPER (atanh, octave::math::rc_atanh);\n      SCALAR_MAPPER (erf, octave::math::erf);\n      SCALAR_MAPPER (erfinv, octave::math::erfinv);\n      SCALAR_MAPPER (erfcinv, octave::math::erfcinv);\n      SCALAR_MAPPER (erfc, octave::math::erfc);\n      SCALAR_MAPPER (erfcx, octave::math::erfcx);\n      SCALAR_MAPPER (erfi, octave::math::erfi);\n      SCALAR_MAPPER (dawson, octave::math::dawson);\n      SCALAR_MAPPER (gamma, octave::math::gamma);\n      SCALAR_MAPPER (lgamma, octave::math::rc_lgamma);\n      SCALAR_MAPPER (cbrt, octave::math::cbrt);\n      SCALAR_MAPPER (ceil, ::ceilf);\n      SCALAR_MAPPER (cos, ::cosf);\n      SCALAR_MAPPER (cosh, ::coshf);\n      SCALAR_MAPPER (exp, ::expf);\n      SCALAR_MAPPER (expm1, octave::math::expm1);\n      SCALAR_MAPPER (fix, octave::math::fix);\n      SCALAR_MAPPER (floor, std::floor);\n      SCALAR_MAPPER (log, octave::math::rc_log);\n      SCALAR_MAPPER (log2, octave::math::rc_log2);\n      SCALAR_MAPPER (log10, octave::math::rc_log10);\n      SCALAR_MAPPER (log1p, octave::math::rc_log1p);\n      SCALAR_MAPPER (round, octave::math::round);\n      SCALAR_MAPPER (roundb, octave::math::roundb);\n      SCALAR_MAPPER (signum, octave::math::signum);\n      SCALAR_MAPPER (sin, ::sinf);\n      SCALAR_MAPPER (sinh, ::sinhf);\n      SCALAR_MAPPER (sqrt, octave::math::rc_sqrt);\n      SCALAR_MAPPER (tan, ::tanf);\n      SCALAR_MAPPER (tanh, ::tanhf);\n      SCALAR_MAPPER (isfinite, octave::math::isfinite);\n      SCALAR_MAPPER (isinf, octave::math::isinf);\n      SCALAR_MAPPER (isna, octave::math::isna);\n      SCALAR_MAPPER (isnan, octave::math::isnan);\n      SCALAR_MAPPER (xsignbit, octave::math::signbit);\n\n    // Special cases for Matlab compatibility.\n    case umap_xtolower:\n    case umap_xtoupper:\n      return scalar;\n\n    case umap_xisalnum:\n    case umap_xisalpha:\n    case umap_xisascii:\n    case umap_xiscntrl:\n    case umap_xisdigit:\n    case umap_xisgraph:\n    case umap_xislower:\n    case umap_xisprint:\n    case umap_xispunct:\n    case umap_xisspace:\n    case umap_xisupper:\n    case umap_xisxdigit:\n      {\n        octave_value str_conv = convert_to_str (true, true);\n        return str_conv.map (umap);\n      }\n\n    default:\n      return octave_base_value::map (umap);\n    }\n}\n\nbool\noctave_float_scalar::fast_elem_insert_self (void *where,\n    builtin_type_t btyp) const\n{\n\n  // Support inline real->complex conversion.\n  if (btyp == btyp_float)\n    {\n      *(reinterpret_cast<float *> (where)) = scalar;\n      return true;\n    }\n  else if (btyp == btyp_float_complex)\n    {\n      *(reinterpret_cast<FloatComplex *> (where)) = scalar;\n      return true;\n    }\n  else\n    return false;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-float.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_float_h)\n#define octave_ov_float_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mappers.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"errwarn.h\"\n#include \"ov-base.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-base-scalar.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Real scalar values.\n\nextern template class OCTINTERP_API octave_base_scalar<float>;\n\nclass OCTINTERP_API octave_float_scalar : public octave_base_scalar<float>\n{\npublic:\n\n  octave_float_scalar ()\n    : octave_base_scalar<float> (0.0) { }\n\n  octave_float_scalar (float d)\n    : octave_base_scalar<float> (d) { }\n\n  octave_float_scalar (const octave_float_scalar& s)\n    : octave_base_scalar<float> (s) { }\n\n  ~octave_float_scalar () = default;\n\n  octave_base_value * clone () const\n  { return new octave_float_scalar (*this); }\n\n  // We return an octave_matrix here instead of an octave_float_scalar so\n  // that in expressions like A(2,2,2) = 2 (for A previously\n  // undefined), A will be empty instead of a 1x1 object.\n  octave_base_value * empty_clone () const\n  { return new octave_float_matrix (); }\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  { return octave::idx_vector (scalar); }\n\n  octave_value any (int = 0) const\n  { return (scalar != 0 && ! octave::math::isnan (scalar)); }\n\n  builtin_type_t builtin_type () const { return btyp_float; }\n\n  bool is_real_scalar () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_single_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  int8NDArray\n  int8_array_value () const\n  { return int8NDArray (dim_vector (1, 1), scalar); }\n\n  int16NDArray\n  int16_array_value () const\n  { return int16NDArray (dim_vector (1, 1), scalar); }\n\n  int32NDArray\n  int32_array_value () const\n  { return int32NDArray (dim_vector (1, 1), scalar); }\n\n  int64NDArray\n  int64_array_value () const\n  { return int64NDArray (dim_vector (1, 1), scalar); }\n\n  uint8NDArray\n  uint8_array_value () const\n  { return uint8NDArray (dim_vector (1, 1), scalar); }\n\n  uint16NDArray\n  uint16_array_value () const\n  { return uint16NDArray (dim_vector (1, 1), scalar); }\n\n  uint32NDArray\n  uint32_array_value () const\n  { return uint32NDArray (dim_vector (1, 1), scalar); }\n\n  uint64NDArray\n  uint64_array_value () const\n  { return uint64NDArray (dim_vector (1, 1), scalar); }\n\n#define DEFINE_INT_SCALAR_VALUE(TYPE)         \\\n  octave_ ## TYPE                             \\\n  TYPE ## _scalar_value () const          \\\n  {                                           \\\n    return octave_ ## TYPE (scalar);          \\\n  }\n\n  DEFINE_INT_SCALAR_VALUE (int8)\n  DEFINE_INT_SCALAR_VALUE (int16)\n  DEFINE_INT_SCALAR_VALUE (int32)\n  DEFINE_INT_SCALAR_VALUE (int64)\n  DEFINE_INT_SCALAR_VALUE (uint8)\n  DEFINE_INT_SCALAR_VALUE (uint16)\n  DEFINE_INT_SCALAR_VALUE (uint32)\n  DEFINE_INT_SCALAR_VALUE (uint64)\n\n#undef DEFINE_INT_SCALAR_VALUE\n\n  double double_value (bool = false) const\n  { return static_cast<double> (scalar); }\n\n  float float_value (bool = false) const { return scalar; }\n\n  double scalar_value (bool = false) const\n  { return static_cast<double> (scalar); }\n\n  float float_scalar_value (bool = false) const { return scalar; }\n\n  Matrix matrix_value (bool = false) const\n  { return Matrix (1, 1, scalar); }\n\n  FloatMatrix float_matrix_value (bool = false) const\n  { return FloatMatrix (1, 1, scalar); }\n\n  NDArray array_value (bool = false) const\n  { return NDArray (dim_vector (1, 1), scalar); }\n\n  FloatNDArray float_array_value (bool = false) const\n  { return FloatNDArray (dim_vector (1, 1), scalar); }\n\n  SparseMatrix sparse_matrix_value (bool = false) const\n  { return SparseMatrix (Matrix (1, 1, scalar)); }\n\n  // FIXME: Need SparseComplexMatrix (Matrix) constructor!\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  { return SparseComplexMatrix (sparse_matrix_value ()); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const;\n\n  Complex complex_value (bool = false) const { return scalar; }\n\n  FloatComplex float_complex_value (bool = false) const { return scalar; }\n\n  ComplexMatrix complex_matrix_value (bool = false) const\n  { return ComplexMatrix (1, 1, Complex (scalar)); }\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const\n  { return FloatComplexMatrix (1, 1, FloatComplex (scalar)); }\n\n  ComplexNDArray complex_array_value (bool = false) const\n  { return ComplexNDArray (dim_vector (1, 1), Complex (scalar)); }\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const\n  { return FloatComplexNDArray (dim_vector (1, 1), FloatComplex (scalar)); }\n\n  charNDArray\n  char_array_value (bool = false) const\n  {\n    charNDArray retval (dim_vector (1, 1));\n    if (octave::math::isnan (scalar))\n      retval(0) = 0;\n    else\n      retval(0) = static_cast<char> (scalar);\n    return retval;\n  }\n\n  bool bool_value (bool warn = false) const\n  {\n    if (octave::math::isnan (scalar))\n      octave::err_nan_to_logical_conversion ();\n    if (warn && scalar != 0 && scalar != 1)\n      warn_logical_conversion ();\n\n    return scalar;\n  }\n\n  boolNDArray bool_array_value (bool warn = false) const\n  {\n    if (octave::math::isnan (scalar))\n      octave::err_nan_to_logical_conversion ();\n    if (warn && scalar != 0 && scalar != 1)\n      warn_logical_conversion ();\n\n    return boolNDArray (dim_vector (1, 1), scalar);\n  }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_scalar<float>::diag;\n\n  octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  void increment () { ++scalar; }\n\n  void decrement () { --scalar; }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    return os.write (array_value (), block_size, output_type,\n                     skip, flt_fmt);\n  }\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n\n  bool fast_elem_insert_self (void *where, builtin_type_t btyp) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-complex.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"oct-specfun.h\"\n\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-float.h\"\n#include \"ov-flt-complex.h\"\n#include \"errwarn.h\"\n#include \"pr-output.h\"\n#include \"ops.h\"\n\n#include \"ls-oct-text.h\"\n#include \"ls-hdf5.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_complex,\n                                     \"float complex scalar\", \"single\");\n\noctave_base_value *\noctave_float_complex::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  float im = scalar.imag ();\n\n  if (im == 0.0)\n    retval = new octave_float_scalar (scalar.real ());\n\n  return retval;\n}\n\noctave_value\noctave_float_complex::do_index_op (const octave_value_list& idx, bool resize_ok)\n{\n  // FIXME: this doesn't solve the problem of\n  //\n  //   a = i; a([1,1], [1,1], [1,1])\n  //\n  // and similar constructions.  Hmm...\n\n  // FIXME: using this constructor avoids narrowing the\n  // 1x1 matrix back to a scalar value.  Need a better solution\n  // to this problem.\n\n  octave_value tmp (new octave_float_complex_matrix (float_complex_matrix_value ()));\n\n  return tmp.index_op (idx, resize_ok);\n}\n\ndouble\noctave_float_complex::double_value (bool force_conversion) const\n{\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real scalar\");\n\n  return scalar.real ();\n}\n\nfloat\noctave_float_complex::float_value (bool force_conversion) const\n{\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real scalar\");\n\n  return scalar.real ();\n}\n\nMatrix\noctave_float_complex::matrix_value (bool force_conversion) const\n{\n  Matrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real matrix\");\n\n  retval = Matrix (1, 1, scalar.real ());\n\n  return retval;\n}\n\nFloatMatrix\noctave_float_complex::float_matrix_value (bool force_conversion) const\n{\n  FloatMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real matrix\");\n\n  retval = FloatMatrix (1, 1, scalar.real ());\n\n  return retval;\n}\n\nNDArray\noctave_float_complex::array_value (bool force_conversion) const\n{\n  NDArray retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real matrix\");\n\n  retval = NDArray (dim_vector (1, 1), scalar.real ());\n\n  return retval;\n}\n\nFloatNDArray\noctave_float_complex::float_array_value (bool force_conversion) const\n{\n  FloatNDArray retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex scalar\", \"real matrix\");\n\n  retval = FloatNDArray (dim_vector (1, 1), scalar.real ());\n\n  return retval;\n}\n\nComplex\noctave_float_complex::complex_value (bool) const\n{\n  return scalar;\n}\n\nFloatComplex\noctave_float_complex::float_complex_value (bool) const\n{\n  return static_cast<FloatComplex> (scalar);\n}\n\nComplexMatrix\noctave_float_complex::complex_matrix_value (bool) const\n{\n  return ComplexMatrix (1, 1, scalar);\n}\n\nFloatComplexMatrix\noctave_float_complex::float_complex_matrix_value (bool) const\n{\n  return FloatComplexMatrix (1, 1, scalar);\n}\n\nComplexNDArray\noctave_float_complex::complex_array_value (bool /* force_conversion */) const\n{\n  return ComplexNDArray (dim_vector (1, 1), scalar);\n}\n\nFloatComplexNDArray\noctave_float_complex::float_complex_array_value (bool /* force_conversion */) const\n{\n  return FloatComplexNDArray (dim_vector (1, 1), scalar);\n}\n\noctave_value\noctave_float_complex::resize (const dim_vector& dv, bool fill) const\n{\n  if (fill)\n    {\n      FloatComplexNDArray retval (dv, FloatComplex (0));\n\n      if (dv.numel ())\n        retval(0) = scalar;\n\n      return retval;\n    }\n  else\n    {\n      FloatComplexNDArray retval (dv);\n\n      if (dv.numel ())\n        retval(0) = scalar;\n\n      return retval;\n    }\n}\n\noctave_value\noctave_float_complex::as_double () const\n{\n  return Complex (scalar);\n}\n\noctave_value\noctave_float_complex::as_single () const\n{\n  return scalar;\n}\n\noctave_value\noctave_float_complex::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return\n    FloatComplexDiagMatrix (Array<FloatComplex> (dim_vector (1, 1), scalar),\n                            m, n);\n}\n\nbool\noctave_float_complex::save_ascii (std::ostream& os)\n{\n  FloatComplex c = float_complex_value ();\n\n  octave::write_value<FloatComplex> (os, c);\n\n  os << \"\\n\";\n\n  return true;\n}\n\nbool\noctave_float_complex::load_ascii (std::istream& is)\n{\n  scalar = octave::read_value<FloatComplex> (is);\n\n  if (! is)\n    error (\"load: failed to load complex scalar constant\");\n\n  return true;\n}\n\nbool\noctave_float_complex::save_binary (std::ostream& os, bool /* save_as_floats */)\n{\n  char tmp = static_cast<char> (LS_FLOAT);\n  os.write (reinterpret_cast<char *> (&tmp), 1);\n  FloatComplex ctmp = float_complex_value ();\n  os.write (reinterpret_cast<char *> (&ctmp), 8);\n\n  return true;\n}\n\nbool\noctave_float_complex::load_binary (std::istream& is, bool swap,\n                                   octave::mach_info::float_format fmt)\n{\n  char tmp;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n    return false;\n\n  FloatComplex ctmp;\n  read_floats (is, reinterpret_cast<float *> (&ctmp),\n               static_cast<save_type> (tmp), 2, swap, fmt);\n\n  if (! is)\n    return false;\n\n  scalar = ctmp;\n  return true;\n}\n\nbool\noctave_float_complex::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                                 bool /* save_as_floats */)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hsize_t dimens[3] = {0};\n  hid_t space_hid, type_hid, data_hid;\n  space_hid = type_hid = data_hid = -1;\n\n  space_hid = H5Screate_simple (0, dimens, nullptr);\n  if (space_hid < 0)\n    return false;\n\n  type_hid = hdf5_make_complex_type (H5T_NATIVE_FLOAT);\n  if (type_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      return false;\n    }\n\n  FloatComplex tmp = float_complex_value ();\n  retval = H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n\n  H5Dclose (data_hid);\n  H5Tclose (type_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_float_complex::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t type_hid = H5Dget_type (data_hid);\n\n  hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_FLOAT);\n\n  if (! hdf5_types_compatible (type_hid, complex_type))\n    {\n      H5Tclose (complex_type);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  hid_t space_id = H5Dget_space (data_hid);\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank != 0)\n    {\n      H5Tclose (complex_type);\n      H5Sclose (space_id);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  // complex scalar:\n  FloatComplex ctmp;\n  if (H5Dread (data_hid, complex_type, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &ctmp)\n      >= 0)\n    {\n      retval = true;\n      scalar = ctmp;\n    }\n\n  H5Tclose (complex_type);\n  H5Sclose (space_id);\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nmxArray *\noctave_float_complex::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxSINGLE_CLASS, 1, 1, mxCOMPLEX);\n\n  if (interleaved)\n    {\n      mxComplexSingle *pd\n        = static_cast<mxComplexSingle *> (retval->get_data ());\n\n      pd[0].real = scalar.real ();\n      pd[0].imag = scalar.imag ();\n    }\n  else\n    {\n      mxSingle *pr = static_cast<mxSingle *> (retval->get_data ());\n      mxSingle *pi = static_cast<mxSingle *> (retval->get_imag_data ());\n\n      pr[0] = scalar.real ();\n      pi[0] = scalar.imag ();\n    }\n\n  return retval;\n}\n\noctave_value\noctave_float_complex::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n#define SCALAR_MAPPER(UMAP, FCN)              \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (FCN (scalar))\n\n      SCALAR_MAPPER (abs, std::abs);\n      SCALAR_MAPPER (acos, octave::math::acos);\n      SCALAR_MAPPER (acosh, octave::math::acosh);\n      SCALAR_MAPPER (angle, std::arg);\n      SCALAR_MAPPER (arg, std::arg);\n      SCALAR_MAPPER (asin, octave::math::asin);\n      SCALAR_MAPPER (asinh, octave::math::asinh);\n      SCALAR_MAPPER (atan, octave::math::atan);\n      SCALAR_MAPPER (atanh, octave::math::atanh);\n      SCALAR_MAPPER (erf, octave::math::erf);\n      SCALAR_MAPPER (erfc, octave::math::erfc);\n      SCALAR_MAPPER (erfcx, octave::math::erfcx);\n      SCALAR_MAPPER (erfi, octave::math::erfi);\n      SCALAR_MAPPER (dawson, octave::math::dawson);\n      SCALAR_MAPPER (ceil, octave::math::ceil);\n      SCALAR_MAPPER (conj, std::conj);\n      SCALAR_MAPPER (cos, std::cos);\n      SCALAR_MAPPER (cosh, std::cosh);\n      SCALAR_MAPPER (exp, std::exp);\n      SCALAR_MAPPER (expm1, octave::math::expm1);\n      SCALAR_MAPPER (fix, octave::math::fix);\n      SCALAR_MAPPER (floor, octave::math::floor);\n      SCALAR_MAPPER (imag, std::imag);\n      SCALAR_MAPPER (log, std::log);\n      SCALAR_MAPPER (log2, octave::math::log2);\n      SCALAR_MAPPER (log10, std::log10);\n      SCALAR_MAPPER (log1p, octave::math::log1p);\n      SCALAR_MAPPER (real, std::real);\n      SCALAR_MAPPER (round, octave::math::round);\n      SCALAR_MAPPER (roundb, octave::math::roundb);\n      SCALAR_MAPPER (signum, octave::math::signum);\n      SCALAR_MAPPER (sin, std::sin);\n      SCALAR_MAPPER (sinh, std::sinh);\n      SCALAR_MAPPER (sqrt, std::sqrt);\n      SCALAR_MAPPER (tan, std::tan);\n      SCALAR_MAPPER (tanh, std::tanh);\n      SCALAR_MAPPER (isfinite, octave::math::isfinite);\n      SCALAR_MAPPER (isinf, octave::math::isinf);\n      SCALAR_MAPPER (isna, octave::math::isna);\n      SCALAR_MAPPER (isnan, octave::math::isnan);\n\n    // Special cases for Matlab compatibility\n    case umap_xtolower:\n    case umap_xtoupper:\n      return scalar;\n\n    default:\n      return octave_base_value::map (umap);\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-complex.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_flt_complex_h)\n#define octave_ov_flt_complex_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"errwarn.h\"\n#include \"error.h\"\n#include \"ov-base.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-base-scalar.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Complex scalar values.\n\nextern template class OCTINTERP_API octave_base_scalar<FloatComplex>;\n\nclass OCTINTERP_API octave_float_complex\n  : public octave_base_scalar<FloatComplex>\n{\npublic:\n\n  octave_float_complex ()\n    : octave_base_scalar<FloatComplex> () { }\n\n  octave_float_complex (const FloatComplex& c)\n    : octave_base_scalar<FloatComplex> (c) { }\n\n  octave_float_complex (const octave_float_complex& c)\n    : octave_base_scalar<FloatComplex> (c) { }\n\n  ~octave_float_complex () = default;\n\n  octave_base_value * clone () const\n  { return new octave_float_complex (*this); }\n\n  // We return an octave_float_complex_matrix object here instead of an\n  // octave_float_complex object so that in expressions like A(2,2,2) = 2\n  // (for A previously undefined), A will be empty instead of a 1x1\n  // object.\n  octave_base_value * empty_clone () const\n  { return new octave_float_complex_matrix (); }\n\n  octave_base_value * try_narrowing_conversion ();\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  octave_value any (int = 0) const\n  {\n    return (scalar != FloatComplex (0, 0)\n            && ! (octave::math::isnan (scalar.real ())\n                  || octave::math::isnan (scalar.imag ())));\n  }\n\n  builtin_type_t builtin_type () const { return btyp_float_complex; }\n\n  bool is_complex_scalar () const { return true; }\n\n  bool iscomplex () const { return true; }\n\n  bool is_single_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  double double_value (bool = false) const;\n\n  float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  float float_scalar_value (bool frc_str_conv = false) const\n  { return float_value (frc_str_conv); }\n\n  Matrix matrix_value (bool = false) const;\n\n  FloatMatrix float_matrix_value (bool = false) const;\n\n  NDArray array_value (bool = false) const;\n\n  FloatNDArray float_array_value (bool = false) const;\n\n  SparseMatrix sparse_matrix_value (bool = false) const\n  { return SparseMatrix (matrix_value ()); }\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  { return SparseComplexMatrix (complex_matrix_value ()); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const;\n\n  Complex complex_value (bool = false) const;\n\n  FloatComplex float_complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const;\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const;\n\n  bool bool_value (bool warn = false) const\n  {\n    if (octave::math::isnan (scalar))\n      octave::err_nan_to_logical_conversion ();\n    if (warn && scalar != 0.0f && scalar != 1.0f)\n      warn_logical_conversion ();\n\n    return scalar != 0.0f;\n  }\n\n  boolNDArray bool_array_value (bool warn = false) const\n  {\n    if (octave::math::isnan (scalar))\n      octave::err_nan_to_logical_conversion ();\n    if (warn && scalar != 0.0f && scalar != 1.0f)\n      warn_logical_conversion ();\n\n    return boolNDArray (dim_vector (1, 1), scalar != 1.0f);\n  }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_scalar<FloatComplex>::diag;\n\n  octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  void increment () { scalar += 1.0; }\n\n  void decrement () { scalar -= 1.0; }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    // Yes, for compatibility, we drop the imaginary part here.\n    return os.write (array_value (true), block_size, output_type,\n                     skip, flt_fmt);\n  }\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\ntypedef octave_float_complex octave_float_complex_scalar;\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-cx-diag.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"byte-swap.h\"\n\n#include \"ov-flt-cx-diag.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-flt-complex.h\"\n#include \"ls-utils.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_complex_diag_matrix,\n                                     \"float complex diagonal matrix\", \"single\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_float_complex_diag_matrix& v\n    = dynamic_cast<const octave_float_complex_diag_matrix&> (a);\n\n  return new octave_float_complex_matrix (v.float_complex_matrix_value ());\n}\n\noctave_base_value::type_conv_info\noctave_float_complex_diag_matrix::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n         octave_float_complex_matrix::static_type_id ());\n}\n\noctave_base_value *\noctave_float_complex_diag_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.nelem () == 1)\n    {\n      retval = new octave_float_complex (m_matrix (0, 0));\n      octave_base_value *rv2 = retval->try_narrowing_conversion ();\n      if (rv2)\n        {\n          delete retval;\n          retval = rv2;\n        }\n    }\n  else if (m_matrix.all_elements_are_real ())\n    {\n      return new octave_float_diag_matrix (::real (m_matrix));\n    }\n\n  return retval;\n}\n\nDiagMatrix\noctave_float_complex_diag_matrix::diag_matrix_value (bool force_conversion) const\n{\n  DiagMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              type_name (), \"real matrix\");\n\n  retval = ::real (m_matrix);\n\n  return retval;\n}\n\nFloatDiagMatrix\noctave_float_complex_diag_matrix::float_diag_matrix_value (bool force_conversion) const\n{\n  DiagMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              type_name (), \"real matrix\");\n\n  retval = ::real (m_matrix);\n\n  return retval;\n}\n\nComplexDiagMatrix\noctave_float_complex_diag_matrix::complex_diag_matrix_value (bool) const\n{\n  return ComplexDiagMatrix (m_matrix);\n}\n\nFloatComplexDiagMatrix\noctave_float_complex_diag_matrix::float_complex_diag_matrix_value (bool) const\n{\n  return m_matrix;\n}\n\noctave_value\noctave_float_complex_diag_matrix::as_double () const\n{\n  return ComplexDiagMatrix (m_matrix);\n}\n\noctave_value\noctave_float_complex_diag_matrix::as_single () const\n{\n  return m_matrix;\n}\n\noctave_value\noctave_float_complex_diag_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    case umap_abs:\n      return m_matrix.abs ();\n    case umap_real:\n      return ::real (m_matrix);\n    case umap_conj:\n      return ::conj (m_matrix);\n    case umap_imag:\n      return ::imag (m_matrix);\n    case umap_sqrt:\n      {\n        FloatComplexColumnVector tmp = m_matrix.extract_diag ().map<FloatComplex> (std::sqrt);\n        FloatComplexDiagMatrix retval (tmp);\n        retval.resize (m_matrix.rows (), m_matrix.columns ());\n        return retval;\n      }\n    default:\n      return to_dense ().map (umap);\n    }\n}\n\nbool\noctave_float_complex_diag_matrix::save_binary (std::ostream& os,\n    bool /* save_as_floats */)\n{\n\n  int32_t r = m_matrix.rows ();\n  int32_t c = m_matrix.cols ();\n  os.write (reinterpret_cast<char *> (&r), 4);\n  os.write (reinterpret_cast<char *> (&c), 4);\n\n  FloatComplexMatrix m = FloatComplexMatrix (m_matrix.extract_diag ());\n  save_type st = LS_FLOAT;\n  if (m_matrix.length () > 4096) // FIXME: make this configurable.\n    {\n      float max_val, min_val;\n      if (m.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  const FloatComplex *mtmp = m.data ();\n  write_floats (os, reinterpret_cast<const float *> (mtmp), st, 2 * m.numel ());\n\n  return true;\n}\n\nbool\noctave_float_complex_diag_matrix::load_binary (std::istream& is, bool swap,\n    octave::mach_info::float_format fmt)\n{\n  int32_t r, c;\n  char tmp;\n  if (! (is.read (reinterpret_cast<char *> (&r), 4)\n         && is.read (reinterpret_cast<char *> (&c), 4)\n         && is.read (reinterpret_cast<char *> (&tmp), 1)))\n    return false;\n  if (swap)\n    {\n      swap_bytes<4> (&r);\n      swap_bytes<4> (&c);\n    }\n\n  FloatComplexDiagMatrix m (r, c);\n  FloatComplex *re = m.rwdata ();\n  octave_idx_type len = m.length ();\n  read_floats (is, reinterpret_cast<float *> (re),\n               static_cast<save_type> (tmp), 2 * len, swap, fmt);\n\n  if (! is)\n    return false;\n\n  m_matrix = m;\n\n  return true;\n}\n\nbool\noctave_float_complex_diag_matrix::chk_valid_scalar (const octave_value& val,\n    FloatComplex& x) const\n{\n  bool retval = val.is_complex_scalar () || val.is_real_scalar ();\n  if (retval)\n    x = val.float_complex_value ();\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-cx-diag.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_flt_cx_diag_h)\n#define octave_ov_flt_cx_diag_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov-base.h\"\n#include \"ov-base-diag.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n\n// Real diagonal matrix values.\n\nextern template class OCTINTERP_API\noctave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix>;\n\nclass OCTINTERP_API octave_float_complex_diag_matrix\n  : public octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix>\n{\npublic:\n\n  octave_float_complex_diag_matrix ()\n    : octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix> () { }\n\n  octave_float_complex_diag_matrix (const FloatComplexDiagMatrix& m)\n    : octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix> (m) { }\n\n  octave_float_complex_diag_matrix (const octave_float_complex_diag_matrix& m)\n    : octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix> (m) { }\n\n  ~octave_float_complex_diag_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_float_complex_diag_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_float_complex_diag_matrix (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  builtin_type_t builtin_type () const { return btyp_float_complex; }\n\n  bool is_complex_matrix () const { return true; }\n\n  bool iscomplex () const { return true; }\n\n  bool is_single_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  DiagMatrix diag_matrix_value (bool = false) const;\n\n  FloatDiagMatrix float_diag_matrix_value (bool = false) const;\n\n  ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;\n\n  FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  bool chk_valid_scalar (const octave_value&,\n                         FloatComplex&) const;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-cx-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <clocale>\n#include <istream>\n#include <ostream>\n\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n\n#include \"data-conv.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"mach-info.h\"\n#include \"mx-base.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-specfun.h\"\n\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"pr-output.h\"\n#include \"ops.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-utils.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_complex_matrix,\n                                     \"float complex matrix\", \"single\");\n\noctave_base_value *\noctave_float_complex_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.numel () == 1)\n    {\n      FloatComplex c = m_matrix (0);\n\n      if (c.imag () == 0.0)\n        retval = new octave_float_scalar (c.real ());\n      else\n        retval = new octave_float_complex (c);\n    }\n  else if (m_matrix.all_elements_are_real ())\n    retval = new octave_float_matrix (::real (m_matrix));\n\n  return retval;\n}\n\ndouble\noctave_float_complex_matrix::double_value (bool force_conversion) const\n{\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real scalar\");\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"complex matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"complex matrix\", \"real scalar\");\n\n  return std::real (m_matrix(0, 0));\n}\n\nfloat\noctave_float_complex_matrix::float_value (bool force_conversion) const\n{\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real scalar\");\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"complex matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"complex matrix\", \"real scalar\");\n\n  return std::real (m_matrix(0, 0));\n}\n\nMatrix\noctave_float_complex_matrix::matrix_value (bool force_conversion) const\n{\n  Matrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real matrix\");\n\n  retval = ::real (FloatComplexMatrix (m_matrix));\n\n  return retval;\n}\n\nFloatMatrix\noctave_float_complex_matrix::float_matrix_value (bool force_conversion) const\n{\n  FloatMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real matrix\");\n\n  retval = ::real (FloatComplexMatrix (m_matrix));\n\n  return retval;\n}\n\nComplex\noctave_float_complex_matrix::complex_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"complex matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"complex matrix\", \"complex scalar\");\n\n  return m_matrix(0, 0);\n}\n\nFloatComplex\noctave_float_complex_matrix::float_complex_value (bool) const\n{\n  float tmp = lo_ieee_float_nan_value ();\n\n  FloatComplex retval (tmp, tmp);\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"complex matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"complex matrix\", \"complex scalar\");\n\n  retval = m_matrix(0, 0);\n\n  return retval;\n}\n\nComplexMatrix\noctave_float_complex_matrix::complex_matrix_value (bool) const\n{\n  return FloatComplexMatrix (m_matrix);\n}\n\nFloatComplexMatrix\noctave_float_complex_matrix::float_complex_matrix_value (bool) const\n{\n  return FloatComplexMatrix (m_matrix);\n}\n\nboolNDArray\noctave_float_complex_matrix::bool_array_value (bool warn) const\n{\n  if (m_matrix.any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n  if (warn && (! m_matrix.all_elements_are_real ()\n               || real (m_matrix).any_element_not_one_or_zero ()))\n    warn_logical_conversion ();\n\n  return mx_el_ne (m_matrix, FloatComplex (0.0));\n}\n\ncharNDArray\noctave_float_complex_matrix::char_array_value (bool frc_str_conv) const\n{\n  charNDArray retval;\n\n  if (! frc_str_conv)\n    warn_implicit_conversion (\"Octave:num-to-str\",\n                              \"complex matrix\", \"string\");\n  else\n    {\n      retval = charNDArray (dims ());\n      octave_idx_type nel = numel ();\n\n      for (octave_idx_type i = 0; i < nel; i++)\n        if (octave::math::isnan (std::real (m_matrix.elem (i))))\n          retval.elem (i) = 0;\n        else\n          retval.elem (i) = static_cast<char> (std::real (m_matrix.elem (i)));\n    }\n\n  return retval;\n}\n\nFloatComplexNDArray\noctave_float_complex_matrix::float_complex_array_value (bool) const\n{\n  return FloatComplexNDArray (m_matrix);\n}\n\nSparseMatrix\noctave_float_complex_matrix::sparse_matrix_value (bool force_conversion) const\n{\n  SparseMatrix retval;\n\n  if (! force_conversion)\n    warn_implicit_conversion (\"Octave:imag-to-real\",\n                              \"complex matrix\", \"real matrix\");\n\n  retval = SparseMatrix (::real (complex_matrix_value ()));\n\n  return retval;\n}\n\nSparseComplexMatrix\noctave_float_complex_matrix::sparse_complex_matrix_value (bool) const\n{\n  return SparseComplexMatrix (complex_matrix_value ());\n}\n\noctave_value\noctave_float_complex_matrix::as_double () const\n{\n  return ComplexNDArray (m_matrix);\n}\n\noctave_value\noctave_float_complex_matrix::as_single () const\n{\n  return m_matrix;\n}\n\noctave_value\noctave_float_complex_matrix::diag (octave_idx_type k) const\n{\n  octave_value retval;\n  if (k == 0 && m_matrix.ndims () == 2\n      && (m_matrix.rows () == 1 || m_matrix.columns () == 1))\n    retval = FloatComplexDiagMatrix (DiagArray2<FloatComplex> (m_matrix));\n  else\n    retval = octave_base_matrix<FloatComplexNDArray>::diag (k);\n\n  return retval;\n}\n\noctave_value\noctave_float_complex_matrix::diag (octave_idx_type m, octave_idx_type n) const\n{\n  if (m_matrix.ndims () != 2\n      || (m_matrix.rows () != 1 && m_matrix.columns () != 1))\n    error (\"diag: expecting vector argument\");\n\n  FloatComplexMatrix mat (m_matrix);\n\n  return mat.diag (m, n);\n}\n\nbool\noctave_float_complex_matrix::save_ascii (std::ostream& os)\n{\n  const dim_vector& dv = dims ();\n\n  if (dv.ndims () > 2)\n    {\n      FloatComplexNDArray tmp = complex_array_value ();\n\n      os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n      for (int i = 0; i < dv.ndims (); i++)\n        os << ' ' << dv(i);\n\n      os << \"\\n\" << tmp;\n    }\n  else\n    {\n      // Keep this case, rather than use generic code above for backward\n      // compatibility.  Makes load_ascii much more complex!!\n      os << \"# rows: \" << rows () << \"\\n\"\n         << \"# columns: \" << columns () << \"\\n\";\n\n      os << complex_matrix_value ();\n    }\n\n  return true;\n}\n\nbool\noctave_float_complex_matrix::load_ascii (std::istream& is)\n{\n  string_vector keywords(2);\n\n  keywords[0] = \"ndims\";\n  keywords[1] = \"rows\";\n\n  std::string kw;\n  octave_idx_type val = 0;\n\n  if (! extract_keyword (is, keywords, kw, val, true))\n    error (\"load: failed to extract number of rows and columns\");\n\n  // Set \"C\" locale for the duration of this function to avoid the performance\n  // panelty of frequently switching the locale when reading floating point\n  // values from the stream.\n  char *prev_locale = std::setlocale (LC_ALL, nullptr);\n  std::string old_locale (prev_locale ? prev_locale : \"\");\n  std::setlocale (LC_ALL, \"C\");\n  octave::unwind_action act\n  ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); });\n\n  if (kw == \"ndims\")\n    {\n      int mdims = static_cast<int> (val);\n\n      if (mdims < 0)\n        error (\"load: failed to extract number of dimensions\");\n\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        is >> dv(i);\n\n      if (! is)\n        error (\"load: failed to read dimensions\");\n\n      FloatComplexNDArray tmp(dv);\n\n      is >> tmp;\n\n      if (! is)\n        error (\"load: failed to load matrix constant\");\n\n      m_matrix = tmp;\n    }\n  else if (kw == \"rows\")\n    {\n      octave_idx_type nr = val;\n      octave_idx_type nc = 0;\n\n      if (nr < 0 || ! extract_keyword (is, \"columns\", nc) || nc < 0)\n        error (\"load: failed to extract number of rows and columns\");\n\n      if (nr > 0 && nc > 0)\n        {\n          FloatComplexMatrix tmp (nr, nc);\n          is >> tmp;\n          if (! is)\n            error (\"load: failed to load matrix constant\");\n\n          m_matrix = tmp;\n        }\n      else if (nr == 0 || nc == 0)\n        m_matrix = FloatComplexMatrix (nr, nc);\n      else\n        error (\"unexpected dimensions in octave_float_complex_matrix::load_ascii - please report this bug\");\n    }\n  else\n    error (\"unexpected dimensions keyword (= '%s') octave_float_complex_matrix::load_ascii - please report this bug\", kw.c_str ());\n\n  return true;\n}\n\nbool\noctave_float_complex_matrix::save_binary (std::ostream& os, bool)\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Use negative value for ndims to differentiate with old format!!\n  int32_t tmp = - dv.ndims ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  for (int i = 0; i < dv.ndims (); i++)\n    {\n      tmp = dv(i);\n      os.write (reinterpret_cast<char *> (&tmp), 4);\n    }\n\n  FloatComplexNDArray m = complex_array_value ();\n  save_type st = LS_FLOAT;\n  if (dv.numel () > 4096) // FIXME: make this configurable.\n    {\n      float max_val, min_val;\n      if (m.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  const FloatComplex *mtmp = m.data ();\n  write_floats (os, reinterpret_cast<const float *> (mtmp), st,\n                2 * dv.numel ());\n\n  return true;\n}\n\nbool\noctave_float_complex_matrix::load_binary (std::istream& is, bool swap,\n    octave::mach_info::float_format fmt)\n{\n  char tmp;\n  int32_t mdims;\n  if (! is.read (reinterpret_cast<char *> (&mdims), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&mdims);\n  if (mdims < 0)\n    {\n      mdims = - mdims;\n      int32_t di;\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        {\n          if (! is.read (reinterpret_cast<char *> (&di), 4))\n            return false;\n          if (swap)\n            swap_bytes<4> (&di);\n          dv(i) = di;\n        }\n\n      // Convert an array with a single dimension to be a row vector.\n      // Octave should never write files like this, other software\n      // might.\n\n      if (mdims == 1)\n        {\n          mdims = 2;\n          dv.resize (mdims);\n          dv(1) = dv(0);\n          dv(0) = 1;\n        }\n\n      if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n        return false;\n\n      FloatComplexNDArray m(dv);\n      FloatComplex *im = m.rwdata ();\n      read_floats (is, reinterpret_cast<float *> (im),\n                   static_cast<save_type> (tmp), 2 * dv.numel (), swap, fmt);\n\n      if (! is)\n        return false;\n\n      m_matrix = m;\n    }\n  else\n    {\n      int32_t nr, nc;\n      nr = mdims;\n      if (! is.read (reinterpret_cast<char *> (&nc), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&nc);\n      if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n        return false;\n      FloatComplexMatrix m (nr, nc);\n      FloatComplex *im = m.rwdata ();\n      octave_idx_type len = static_cast<octave_idx_type> (nr) * nc;\n      read_floats (is, reinterpret_cast<float *> (im),\n                   static_cast<save_type> (tmp), 2*len, swap, fmt);\n\n      if (! is)\n        return false;\n\n      m_matrix = m;\n    }\n  return true;\n}\n\nbool\noctave_float_complex_matrix::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                                        bool)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  int rank = dv.ndims ();\n  hid_t space_hid, data_hid, type_hid;\n  space_hid = data_hid = type_hid = -1;\n  FloatComplexNDArray m = complex_array_value ();\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  for (int i = 0; i < rank; i++)\n    hdims[i] = dv(rank-i-1);\n\n  space_hid = H5Screate_simple (rank, hdims, nullptr);\n  if (space_hid < 0) return false;\n\n  hid_t save_type_hid = H5T_NATIVE_FLOAT;\n\n#if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS)\n  // hdf5 currently doesn't support float/integer conversions\n  else\n    {\n      float max_val, min_val;\n\n      if (m.all_integers (max_val, min_val))\n        save_type_hid\n          = save_type_to_hdf5 (octave::get_save_type (max_val, min_val));\n    }\n#endif\n\n  type_hid = hdf5_make_complex_type (save_type_hid);\n  if (type_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      return false;\n    }\n\n  hid_t complex_type_hid = hdf5_make_complex_type (H5T_NATIVE_FLOAT);\n  if (complex_type_hid < 0) retval = false;\n\n  if (retval)\n    {\n      const FloatComplex *mtmp = m.data ();\n      if (H5Dwrite (data_hid, complex_type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                    octave_H5P_DEFAULT, mtmp)\n          < 0)\n        {\n          H5Tclose (complex_type_hid);\n          retval = false;\n        }\n    }\n\n  H5Tclose (complex_type_hid);\n  H5Dclose (data_hid);\n  H5Tclose (type_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_float_complex_matrix::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    m_matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t type_hid = H5Dget_type (data_hid);\n\n  hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_FLOAT);\n\n  if (! hdf5_types_compatible (type_hid, complex_type))\n    {\n      H5Tclose (complex_type);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank < 1)\n    {\n      H5Tclose (complex_type);\n      H5Sclose (space_id);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_id, hdims, maxdims);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  if (rank == 1)\n    {\n      dv.resize (2);\n      dv(0) = 1;\n      dv(1) = hdims[0];\n    }\n  else\n    {\n      dv.resize (rank);\n      for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)\n        dv(j) = hdims[i];\n    }\n\n  FloatComplexNDArray m (dv);\n  FloatComplex *reim = m.rwdata ();\n  if (H5Dread (data_hid, complex_type, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, reim)\n      >= 0)\n    {\n      retval = true;\n      m_matrix = m;\n    }\n\n  H5Tclose (complex_type);\n  H5Sclose (space_id);\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nvoid\noctave_float_complex_matrix::print_raw (std::ostream& os,\n                                        bool pr_as_read_syntax) const\n{\n  octave_print_internal (os, m_matrix, pr_as_read_syntax,\n                         current_print_indent_level ());\n}\n\nmxArray *\noctave_float_complex_matrix::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxSINGLE_CLASS, dims (),\n                                 mxCOMPLEX);\n\n  mwSize nel = numel ();\n\n  const FloatComplex *pdata = m_matrix.data ();\n\n  if (interleaved)\n    {\n      mxComplexSingle *pd\n        = static_cast<mxComplexSingle *> (retval->get_data ());\n\n      for (mwIndex i = 0; i < nel; i++)\n        {\n          pd[i].real = pdata[i].real ();\n          pd[i].imag = pdata[i].imag ();\n        }\n    }\n  else\n    {\n      mxSingle *pr = static_cast<mxSingle *> (retval->get_data ());\n      mxSingle *pi = static_cast<mxSingle *> (retval->get_imag_data ());\n\n      for (mwIndex i = 0; i < nel; i++)\n        {\n          pr[i] = pdata[i].real ();\n          pi[i] = pdata[i].imag ();\n        }\n    }\n\n  return retval;\n}\n\noctave_value\noctave_float_complex_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    // Mappers handled specially.\n    case umap_real:\n      return ::real (m_matrix);\n    case umap_imag:\n      return ::imag (m_matrix);\n    case umap_conj:\n      return ::conj (m_matrix);\n\n    // Special cases for Matlab compatibility.\n    case umap_xtolower:\n    case umap_xtoupper:\n      return m_matrix;\n\n#define ARRAY_METHOD_MAPPER(UMAP, FCN)        \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (m_matrix.FCN ())\n\n      ARRAY_METHOD_MAPPER (abs, abs);\n      ARRAY_METHOD_MAPPER (isnan, isnan);\n      ARRAY_METHOD_MAPPER (isinf, isinf);\n      ARRAY_METHOD_MAPPER (isfinite, isfinite);\n\n#define ARRAY_MAPPER(UMAP, TYPE, FCN)                 \\\n    case umap_ ## UMAP:                               \\\n      return octave_value (m_matrix.map<TYPE> (FCN))\n\n      ARRAY_MAPPER (acos, FloatComplex, octave::math::acos);\n      ARRAY_MAPPER (acosh, FloatComplex, octave::math::acosh);\n      ARRAY_MAPPER (angle, float, std::arg);\n      ARRAY_MAPPER (arg, float, std::arg);\n      ARRAY_MAPPER (asin, FloatComplex, octave::math::asin);\n      ARRAY_MAPPER (asinh, FloatComplex, octave::math::asinh);\n      ARRAY_MAPPER (atan, FloatComplex, octave::math::atan);\n      ARRAY_MAPPER (atanh, FloatComplex, octave::math::atanh);\n      ARRAY_MAPPER (erf, FloatComplex, octave::math::erf);\n      ARRAY_MAPPER (erfc, FloatComplex, octave::math::erfc);\n      ARRAY_MAPPER (erfcx, FloatComplex, octave::math::erfcx);\n      ARRAY_MAPPER (erfi, FloatComplex, octave::math::erfi);\n      ARRAY_MAPPER (dawson, FloatComplex, octave::math::dawson);\n      ARRAY_MAPPER (ceil, FloatComplex, octave::math::ceil);\n      ARRAY_MAPPER (cos, FloatComplex, std::cos);\n      ARRAY_MAPPER (cosh, FloatComplex, std::cosh);\n      ARRAY_MAPPER (exp, FloatComplex, std::exp);\n      ARRAY_MAPPER (expm1, FloatComplex, octave::math::expm1);\n      ARRAY_MAPPER (fix, FloatComplex, octave::math::fix);\n      ARRAY_MAPPER (floor, FloatComplex, octave::math::floor);\n      ARRAY_MAPPER (log, FloatComplex, std::log);\n      ARRAY_MAPPER (log2, FloatComplex, octave::math::log2);\n      ARRAY_MAPPER (log10, FloatComplex, std::log10);\n      ARRAY_MAPPER (log1p, FloatComplex, octave::math::log1p);\n      ARRAY_MAPPER (round, FloatComplex, octave::math::round);\n      ARRAY_MAPPER (roundb, FloatComplex, octave::math::roundb);\n      ARRAY_MAPPER (signum, FloatComplex, octave::math::signum);\n      ARRAY_MAPPER (sin, FloatComplex, std::sin);\n      ARRAY_MAPPER (sinh, FloatComplex, std::sinh);\n      ARRAY_MAPPER (sqrt, FloatComplex, std::sqrt);\n      ARRAY_MAPPER (tan, FloatComplex, std::tan);\n      ARRAY_MAPPER (tanh, FloatComplex, std::tanh);\n      ARRAY_MAPPER (isna, bool, octave::math::isna);\n\n    default:\n      return octave_base_value::map (umap);\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-cx-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_flt_cx_mat_h)\n#define octave_ov_flt_cx_mat_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-base-mat.h\"\n#include \"ov-typeinfo.h\"\n\n#include \"MatrixType.h\"\n\nclass octave_value_list;\n\n// Complex matrix values.\n\nextern template class OCTINTERP_API octave_base_matrix<FloatComplexNDArray>;\n\nclass OCTINTERP_API octave_float_complex_matrix\n  : public octave_base_matrix<FloatComplexNDArray>\n{\npublic:\n\n  octave_float_complex_matrix ()\n    : octave_base_matrix<FloatComplexNDArray> () { }\n\n  octave_float_complex_matrix (const FloatComplexNDArray& m)\n    : octave_base_matrix<FloatComplexNDArray> (m) { }\n\n  octave_float_complex_matrix (const FloatComplexMatrix& m)\n    : octave_base_matrix<FloatComplexNDArray> (m) { }\n\n  octave_float_complex_matrix (const FloatComplexMatrix& m, const MatrixType& t)\n    : octave_base_matrix<FloatComplexNDArray> (m, t) { }\n\n  octave_float_complex_matrix (const Array<FloatComplex>& m)\n    : octave_base_matrix<FloatComplexNDArray> (FloatComplexNDArray (m)) { }\n\n  octave_float_complex_matrix (const FloatComplexDiagMatrix& d)\n    : octave_base_matrix<FloatComplexNDArray> (FloatComplexMatrix (d)) { }\n\n  octave_float_complex_matrix (const FloatComplexRowVector& v)\n    : octave_base_matrix<FloatComplexNDArray> (FloatComplexMatrix (v)) { }\n\n  octave_float_complex_matrix (const FloatComplexColumnVector& v)\n    : octave_base_matrix<FloatComplexNDArray> (FloatComplexMatrix (v)) { }\n\n  octave_float_complex_matrix (const octave_float_complex_matrix& cm)\n    : octave_base_matrix<FloatComplexNDArray> (cm) { }\n\n  ~octave_float_complex_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_float_complex_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_float_complex_matrix (); }\n\n  octave_base_value * try_narrowing_conversion ();\n\n  builtin_type_t builtin_type () const { return btyp_float_complex; }\n\n  bool is_complex_matrix () const { return true; }\n\n  bool iscomplex () const { return true; }\n\n  bool is_single_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  double double_value (bool = false) const;\n\n  float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  float float_scalar_value (bool frc_str_conv = false) const\n  { return float_value (frc_str_conv); }\n\n  Matrix matrix_value (bool = false) const;\n\n  FloatMatrix float_matrix_value (bool = false) const;\n\n  Complex complex_value (bool = false) const;\n\n  FloatComplex float_complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const { return m_matrix; }\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const;\n\n  boolNDArray bool_array_value (bool warn = false) const;\n\n  charNDArray char_array_value (bool frc_str_conv = false) const;\n\n  SparseMatrix sparse_matrix_value (bool = false) const;\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;\n\n  octave_value all (int dim = 0) const { return m_matrix.all (dim); }\n  octave_value any (int dim = 0) const { return m_matrix.any (dim); }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value diag (octave_idx_type k = 0) const;\n\n  octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  void increment () { m_matrix += FloatComplex (1.0); }\n\n  void decrement () { m_matrix -= FloatComplex (1.0); }\n\n  void changesign () { m_matrix.changesign (); }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    // Yes, for compatibility, we drop the imaginary part here.\n    return os.write (matrix_value (true), block_size, output_type,\n                     skip, flt_fmt);\n  }\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-re-diag.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"byte-swap.h\"\n\n#include \"ov-flt-re-diag.h\"\n#include \"ov-float.h\"\n#include \"ls-utils.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_diag_matrix,\n                                     \"float diagonal matrix\", \"single\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_float_diag_matrix& v\n    = dynamic_cast<const octave_float_diag_matrix&> (a);\n\n  return new octave_float_matrix (v.float_matrix_value ());\n}\n\noctave_base_value::type_conv_info\noctave_float_diag_matrix::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n         octave_float_matrix::static_type_id ());\n}\n\noctave_base_value *\noctave_float_diag_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.nelem () == 1)\n    retval = new octave_float_scalar (m_matrix (0, 0));\n\n  return retval;\n}\n\nDiagMatrix\noctave_float_diag_matrix::diag_matrix_value (bool) const\n{\n  return DiagMatrix (m_matrix);\n}\n\nFloatDiagMatrix\noctave_float_diag_matrix::float_diag_matrix_value (bool) const\n{\n  return m_matrix;\n}\n\nComplexDiagMatrix\noctave_float_diag_matrix::complex_diag_matrix_value (bool) const\n{\n  return ComplexDiagMatrix (m_matrix);\n}\n\nFloatComplexDiagMatrix\noctave_float_diag_matrix::float_complex_diag_matrix_value (bool) const\n{\n  return FloatComplexDiagMatrix (m_matrix);\n}\n\noctave_value\noctave_float_diag_matrix::as_double () const\n{\n  return DiagMatrix (m_matrix);\n}\n\noctave_value\noctave_float_diag_matrix::as_single () const\n{\n  return m_matrix;\n}\n\noctave_value\noctave_float_diag_matrix::as_int8 () const\n{\n  return int8_array_value ();\n}\n\noctave_value\noctave_float_diag_matrix::as_int16 () const\n{\n  return int16_array_value ();\n}\n\noctave_value\noctave_float_diag_matrix::as_int32 () const\n{\n  return int32_array_value ();\n}\n\noctave_value\noctave_float_diag_matrix::as_int64 () const\n{\n  return int64_array_value ();\n}\n\noctave_value\noctave_float_diag_matrix::as_uint8 () const\n{\n  return uint8_array_value ();\n}\n\noctave_value\noctave_float_diag_matrix::as_uint16 () const\n{\n  return uint16_array_value ();\n}\n\noctave_value\noctave_float_diag_matrix::as_uint32 () const\n{\n  return uint32_array_value ();\n}\n\noctave_value\noctave_float_diag_matrix::as_uint64 () const\n{\n  return uint64_array_value ();\n}\n\noctave_value\noctave_float_diag_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    case umap_abs:\n      return m_matrix.abs ();\n    case umap_real:\n    case umap_conj:\n      return m_matrix;\n    case umap_imag:\n      return DiagMatrix (m_matrix.rows (), m_matrix.cols (), 0.0);\n    case umap_sqrt:\n      {\n        FloatComplexColumnVector tmp = m_matrix.extract_diag ().map<FloatComplex> (octave::math::rc_sqrt);\n        FloatComplexDiagMatrix retval (tmp);\n        retval.resize (m_matrix.rows (), m_matrix.columns ());\n        return retval;\n      }\n    default:\n      return to_dense ().map (umap);\n    }\n}\n\nbool\noctave_float_diag_matrix::save_binary (std::ostream& os,\n                                       bool /* save_as_floats*/)\n{\n\n  int32_t r = m_matrix.rows ();\n  int32_t c = m_matrix.cols ();\n  os.write (reinterpret_cast<char *> (&r), 4);\n  os.write (reinterpret_cast<char *> (&c), 4);\n\n  FloatMatrix m = FloatMatrix (m_matrix.extract_diag ());\n  save_type st = LS_FLOAT;\n  if (m_matrix.length () > 8192) // FIXME: make this configurable.\n    {\n      float max_val, min_val;\n      if (m.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  const float *mtmp = m.data ();\n  write_floats (os, mtmp, st, m.numel ());\n\n  return true;\n}\n\nbool\noctave_float_diag_matrix::load_binary (std::istream& is, bool swap,\n                                       octave::mach_info::float_format fmt)\n{\n  int32_t r, c;\n  char tmp;\n  if (! (is.read (reinterpret_cast<char *> (&r), 4)\n         && is.read (reinterpret_cast<char *> (&c), 4)\n         && is.read (reinterpret_cast<char *> (&tmp), 1)))\n    return false;\n  if (swap)\n    {\n      swap_bytes<4> (&r);\n      swap_bytes<4> (&c);\n    }\n\n  FloatDiagMatrix m (r, c);\n  float *re = m.rwdata ();\n  octave_idx_type len = m.length ();\n  read_floats (is, re, static_cast<save_type> (tmp), len, swap, fmt);\n\n  if (! is)\n    return false;\n\n  m_matrix = m;\n\n  return true;\n}\n\nbool\noctave_float_diag_matrix::chk_valid_scalar (const octave_value& val,\n    float& x) const\n{\n  bool retval = val.is_real_scalar ();\n  if (retval)\n    x = val.float_value ();\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-re-diag.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_flt_re_diag_h)\n#define octave_ov_flt_re_diag_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov-base.h\"\n#include \"ov-base-diag.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n\n// Real diagonal matrix values.\n\nextern template class OCTINTERP_API\noctave_base_diag<FloatDiagMatrix, FloatMatrix>;\n\nclass OCTINTERP_API octave_float_diag_matrix\n  : public octave_base_diag<FloatDiagMatrix, FloatMatrix>\n{\npublic:\n\n  octave_float_diag_matrix ()\n    : octave_base_diag<FloatDiagMatrix, FloatMatrix> () { }\n\n  octave_float_diag_matrix (const FloatDiagMatrix& m)\n    : octave_base_diag<FloatDiagMatrix, FloatMatrix> (m) { }\n\n  octave_float_diag_matrix (const octave_float_diag_matrix& m)\n    : octave_base_diag<FloatDiagMatrix, FloatMatrix> (m) { }\n\n  ~octave_float_diag_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_float_diag_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_float_diag_matrix (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  builtin_type_t builtin_type () const { return btyp_float; }\n\n  bool is_real_matrix () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_single_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  DiagMatrix diag_matrix_value (bool = false) const;\n\n  FloatDiagMatrix float_diag_matrix_value (bool = false) const;\n\n  ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;\n\n  FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  bool chk_valid_scalar (const octave_value&,\n                         float&) const;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-re-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <clocale>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n#include \"int8NDArray.h\"\n#include \"int16NDArray.h\"\n#include \"int32NDArray.h\"\n#include \"int64NDArray.h\"\n#include \"uint8NDArray.h\"\n#include \"uint16NDArray.h\"\n#include \"uint32NDArray.h\"\n#include \"uint64NDArray.h\"\n\n#include \"data-conv.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"lo-utils.h\"\n#include \"mach-info.h\"\n#include \"mx-base.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-specfun.h\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-flt-cx-diag.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n#include \"ops.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_matrix, \"float matrix\",\n                                     \"single\");\n\noctave_base_value *\noctave_float_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.numel () == 1)\n    retval = new octave_float_scalar (m_matrix (0));\n\n  return retval;\n}\n\ndouble\noctave_float_matrix::double_value (bool) const\n{\n  if (isempty ())\n    err_invalid_conversion (\"real matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"real matrix\", \"real scalar\");\n\n  return m_matrix(0, 0);\n}\n\nfloat\noctave_float_matrix::float_value (bool) const\n{\n  if (isempty ())\n    err_invalid_conversion (\"real matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"real matrix\", \"real scalar\");\n\n  return m_matrix(0, 0);\n}\n\n// FIXME\n\nMatrix\noctave_float_matrix::matrix_value (bool) const\n{\n  return Matrix (FloatMatrix (m_matrix));\n}\n\nFloatMatrix\noctave_float_matrix::float_matrix_value (bool) const\n{\n  return FloatMatrix (m_matrix);\n}\n\nComplex\noctave_float_matrix::complex_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"real matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"real matrix\", \"complex scalar\");\n\n  return Complex (m_matrix(0, 0), 0);\n}\n\nFloatComplex\noctave_float_matrix::float_complex_value (bool) const\n{\n  double tmp = lo_ieee_float_nan_value ();\n\n  FloatComplex retval (tmp, tmp);\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"real matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"real matrix\", \"complex scalar\");\n\n  retval = m_matrix(0, 0);\n\n  return retval;\n}\n\n// FIXME\n\nComplexMatrix\noctave_float_matrix::complex_matrix_value (bool) const\n{\n  return ComplexMatrix (FloatMatrix (m_matrix));\n}\n\nFloatComplexMatrix\noctave_float_matrix::float_complex_matrix_value (bool) const\n{\n  return FloatComplexMatrix (FloatMatrix (m_matrix));\n}\n\nComplexNDArray\noctave_float_matrix::complex_array_value (bool) const\n{\n  return ComplexNDArray (m_matrix);\n}\n\nFloatComplexNDArray\noctave_float_matrix::float_complex_array_value (bool) const\n{\n  return FloatComplexNDArray (m_matrix);\n}\n\nNDArray\noctave_float_matrix::array_value (bool) const\n{\n  return NDArray (m_matrix);\n}\n\nboolNDArray\noctave_float_matrix::bool_array_value (bool warn) const\n{\n  if (m_matrix.any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n  if (warn && m_matrix.any_element_not_one_or_zero ())\n    warn_logical_conversion ();\n\n  return boolNDArray (m_matrix);\n}\n\ncharNDArray\noctave_float_matrix::char_array_value (bool) const\n{\n  charNDArray retval (dims ());\n\n  octave_idx_type nel = numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    if (octave::math::isnan (m_matrix.elem (i)))\n      retval.elem (i) = 0;\n    else\n      retval.elem (i) = static_cast<char> (m_matrix.elem (i));\n\n  return retval;\n}\n\nSparseMatrix\noctave_float_matrix::sparse_matrix_value (bool) const\n{\n  return SparseMatrix (matrix_value ());\n}\n\nSparseComplexMatrix\noctave_float_matrix::sparse_complex_matrix_value (bool) const\n{\n  // FIXME: Need a SparseComplexMatrix (Matrix) constructor to make\n  // this function more efficient.  Then this should become\n  // return SparseComplexMatrix (matrix.matrix_value ());\n  return SparseComplexMatrix (sparse_matrix_value ());\n}\n\noctave_value\noctave_float_matrix::as_double () const\n{\n  return NDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::as_single () const\n{\n  return FloatNDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::as_int8 () const\n{\n  return int8NDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::as_int16 () const\n{\n  return int16NDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::as_int32 () const\n{\n  return int32NDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::as_int64 () const\n{\n  return int64NDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::as_uint8 () const\n{\n  return uint8NDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::as_uint16 () const\n{\n  return uint16NDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::as_uint32 () const\n{\n  return uint32NDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::as_uint64 () const\n{\n  return uint64NDArray (m_matrix);\n}\n\noctave_value\noctave_float_matrix::diag (octave_idx_type k) const\n{\n  octave_value retval;\n  if (k == 0 && m_matrix.ndims () == 2\n      && (m_matrix.rows () == 1 || m_matrix.columns () == 1))\n    retval = FloatDiagMatrix (DiagArray2<float> (m_matrix));\n  else\n    retval = octave_base_matrix<FloatNDArray>::diag (k);\n\n  return retval;\n}\n\noctave_value\noctave_float_matrix::diag (octave_idx_type m, octave_idx_type n) const\n{\n  if (m_matrix.ndims () != 2\n      || (m_matrix.rows () != 1 && m_matrix.columns () != 1))\n    error (\"diag: expecting vector argument\");\n\n  FloatMatrix mat (m_matrix);\n\n  return mat.diag (m, n);\n}\n\noctave_value\noctave_float_matrix::convert_to_str_internal (bool, bool, char type) const\n{\n  octave_value retval;\n  const dim_vector& dv = dims ();\n  octave_idx_type nel = dv.numel ();\n\n  charNDArray chm (dv);\n\n  bool warned = false;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      octave_quit ();\n\n      float d = m_matrix(i);\n\n      if (octave::math::isnan (d))\n        octave::err_nan_to_character_conversion ();\n\n      int ival = octave::math::nint (d);\n\n      if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())\n        {\n          // FIXME: is there something better we could do?\n\n          ival = 0;\n\n          if (! warned)\n            {\n              ::warning (\"range error for conversion to character value\");\n              warned = true;\n            }\n        }\n\n      chm(i) = static_cast<char> (ival);\n    }\n\n  retval = octave_value (chm, type);\n\n  return retval;\n}\n\nbool\noctave_float_matrix::save_ascii (std::ostream& os)\n{\n  const dim_vector& dv = dims ();\n\n  if (dv.ndims () > 2)\n    {\n      FloatNDArray tmp = float_array_value ();\n\n      os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n      for (int i=0; i < dv.ndims (); i++)\n        os << ' ' << dv(i);\n\n      os << \"\\n\" << tmp;\n    }\n  else\n    {\n      // Keep this case, rather than use generic code above for backward\n      // compatibility.  Makes load_ascii much more complex!!\n      os << \"# rows: \" << rows () << \"\\n\"\n         << \"# columns: \" << columns () << \"\\n\";\n\n      os << float_matrix_value ();\n    }\n\n  return true;\n}\n\nbool\noctave_float_matrix::load_ascii (std::istream& is)\n{\n  string_vector keywords(2);\n\n  keywords[0] = \"ndims\";\n  keywords[1] = \"rows\";\n\n  std::string kw;\n  octave_idx_type val = 0;\n\n  if (! extract_keyword (is, keywords, kw, val, true))\n    error (\"load: failed to extract number of rows and columns\");\n\n  // Set \"C\" locale for the duration of this function to avoid the performance\n  // panelty of frequently switching the locale when reading floating point\n  // values from the stream.\n  char *prev_locale = std::setlocale (LC_ALL, nullptr);\n  std::string old_locale (prev_locale ? prev_locale : \"\");\n  std::setlocale (LC_ALL, \"C\");\n  octave::unwind_action act\n  ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); });\n\n  if (kw == \"ndims\")\n    {\n      int mdims = static_cast<int> (val);\n\n      if (mdims < 0)\n        error (\"load: failed to extract number of dimensions\");\n\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        is >> dv(i);\n\n      if (! is)\n        error (\"load: failed to read dimensions\");\n\n      FloatNDArray tmp(dv);\n\n      is >> tmp;\n\n      if (! is)\n        error (\"load: failed to load matrix constant\");\n\n      m_matrix = tmp;\n    }\n  else if (kw == \"rows\")\n    {\n      octave_idx_type nr = val;\n      octave_idx_type nc = 0;\n\n      if (nr < 0 || ! extract_keyword (is, \"columns\", nc) || nc < 0)\n        error (\"load: failed to extract number of rows and columns\");\n\n      if (nr > 0 && nc > 0)\n        {\n          FloatMatrix tmp (nr, nc);\n          is >> tmp;\n          if (! is)\n            error (\"load: failed to load matrix constant\");\n\n          m_matrix = tmp;\n        }\n      else if (nr == 0 || nc == 0)\n        m_matrix = FloatMatrix (nr, nc);\n      else\n        error (\"unexpected dimensions in octave_float_matrix::load_ascii - please report this bug\");\n    }\n  else\n    error (\"unexpected dimensions keyword (= '%s') octave_float_matrix::load_ascii - please report this bug\", kw.c_str ());\n\n  return true;\n}\n\nbool\noctave_float_matrix::save_binary (std::ostream& os, bool)\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Use negative value for ndims to differentiate with old format!!\n  int32_t tmp = - dv.ndims ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  for (int i = 0; i < dv.ndims (); i++)\n    {\n      tmp = dv(i);\n      os.write (reinterpret_cast<char *> (&tmp), 4);\n    }\n\n  FloatNDArray m = float_array_value ();\n  save_type st = LS_FLOAT;\n  if (dv.numel () > 8192) // FIXME: make this configurable.\n    {\n      float max_val, min_val;\n      if (m.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  const float *mtmp = m.data ();\n  write_floats (os, mtmp, st, dv.numel ());\n\n  return true;\n}\n\nbool\noctave_float_matrix::load_binary (std::istream& is, bool swap,\n                                  octave::mach_info::float_format fmt)\n{\n  char tmp;\n  int32_t mdims;\n  if (! is.read (reinterpret_cast<char *> (&mdims), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&mdims);\n  if (mdims < 0)\n    {\n      mdims = - mdims;\n      int32_t di;\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        {\n          if (! is.read (reinterpret_cast<char *> (&di), 4))\n            return false;\n          if (swap)\n            swap_bytes<4> (&di);\n          dv(i) = di;\n        }\n\n      // Convert an array with a single dimension to be a row vector.\n      // Octave should never write files like this, other software\n      // might.\n\n      if (mdims == 1)\n        {\n          mdims = 2;\n          dv.resize (mdims);\n          dv(1) = dv(0);\n          dv(0) = 1;\n        }\n\n      if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n        return false;\n\n      FloatNDArray m(dv);\n      float *re = m.rwdata ();\n      read_floats (is, re, static_cast<save_type> (tmp), dv.numel (),\n                   swap, fmt);\n\n      if (! is)\n        return false;\n\n      m_matrix = m;\n    }\n  else\n    {\n      int32_t nr, nc;\n      nr = mdims;\n      if (! is.read (reinterpret_cast<char *> (&nc), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&nc);\n      if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n        return false;\n      FloatMatrix m (nr, nc);\n      float *re = m.rwdata ();\n      octave_idx_type len = static_cast<octave_idx_type> (nr) * nc;\n      read_floats (is, re, static_cast<save_type> (tmp), len, swap, fmt);\n\n      if (! is)\n        return false;\n\n      m_matrix = m;\n    }\n  return true;\n}\n\nbool\noctave_float_matrix::save_hdf5 (octave_hdf5_id loc_id, const char *name, bool)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  int rank = dv.ndims ();\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n  FloatNDArray m = array_value ();\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  for (int i = 0; i < rank; i++)\n    hdims[i] = dv(rank-i-1);\n\n  space_hid = H5Screate_simple (rank, hdims, nullptr);\n\n  if (space_hid < 0) return false;\n\n  hid_t save_type_hid = H5T_NATIVE_FLOAT;\n\n#if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS)\n  // hdf5 currently doesn't support float/integer conversions\n  else\n    {\n      float max_val, min_val;\n\n      if (m.all_integers (max_val, min_val))\n        save_type_hid\n          = save_type_to_hdf5 (octave::get_save_type (max_val, min_val));\n    }\n#endif\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n\n  const float *mtmp = m.data ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_FLOAT, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, mtmp) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_float_matrix::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    m_matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank < 1)\n    {\n      H5Sclose (space_id);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_id, hdims, maxdims);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  if (rank == 1)\n    {\n      dv.resize (2);\n      dv(0) = 1;\n      dv(1) = hdims[0];\n    }\n  else\n    {\n      dv.resize (rank);\n      for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)\n        dv(j) = hdims[i];\n    }\n\n  FloatNDArray m (dv);\n  float *re = m.rwdata ();\n  if (H5Dread (data_hid, H5T_NATIVE_FLOAT, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, re) >= 0)\n    {\n      retval = true;\n      m_matrix = m;\n    }\n\n  H5Sclose (space_id);\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nvoid\noctave_float_matrix::print_raw (std::ostream& os,\n                                bool pr_as_read_syntax) const\n{\n  octave_print_internal (os, m_matrix, pr_as_read_syntax,\n                         current_print_indent_level ());\n}\n\nmxArray *\noctave_float_matrix::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxSINGLE_CLASS, dims (), mxREAL);\n\n  mxSingle *pd = static_cast<mxSingle *> (retval->get_data ());\n\n  mwSize nel = numel ();\n\n  const float *pdata = m_matrix.data ();\n\n  for (mwIndex i = 0; i < nel; i++)\n    pd[i] = pdata[i];\n\n  return retval;\n}\n\n// This uses a smarter strategy for doing the complex->real mappers.  We\n// allocate an array for a real result and keep filling it until a complex\n// result is produced.\nstatic octave_value\ndo_rc_map (const FloatNDArray& a, FloatComplex (&fcn) (float))\n{\n  octave_idx_type n = a.numel ();\n  FloatNDArray rr (a.dims ());\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      octave_quit ();\n\n      FloatComplex tmp = fcn (a(i));\n      if (tmp.imag () == 0.0)\n        rr.xelem (i) = tmp.real ();\n      else\n        {\n          FloatComplexNDArray rc (a.dims ());\n\n          for (octave_idx_type j = 0; j < i; j++)\n            rc.xelem (j) = rr.xelem (j);\n\n          rc.xelem (i) = tmp;\n\n          for (octave_idx_type j = i+1; j < n; j++)\n            {\n              octave_quit ();\n\n              rc.xelem (j) = fcn (a(j));\n            }\n\n          return new octave_float_complex_matrix (rc);\n        }\n    }\n\n  return rr;\n}\n\noctave_value\noctave_float_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    case umap_imag:\n      return FloatNDArray (m_matrix.dims (), 0.0);\n\n    case umap_real:\n    case umap_conj:\n      return m_matrix;\n\n      // Mappers handled specially.\n#define ARRAY_METHOD_MAPPER(UMAP, FCN)        \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (m_matrix.FCN ())\n\n      ARRAY_METHOD_MAPPER (abs, abs);\n      ARRAY_METHOD_MAPPER (isnan, isnan);\n      ARRAY_METHOD_MAPPER (isinf, isinf);\n      ARRAY_METHOD_MAPPER (isfinite, isfinite);\n\n#define ARRAY_MAPPER(UMAP, TYPE, FCN)                 \\\n    case umap_ ## UMAP:                               \\\n      return octave_value (m_matrix.map<TYPE> (FCN))\n\n#define RC_ARRAY_MAPPER(UMAP, TYPE, FCN)      \\\n    case umap_ ## UMAP:                       \\\n      return do_rc_map (m_matrix, FCN)\n\n      RC_ARRAY_MAPPER (acos, FloatComplex, octave::math::rc_acos);\n      RC_ARRAY_MAPPER (acosh, FloatComplex, octave::math::rc_acosh);\n      ARRAY_MAPPER (angle, float, std::arg);\n      ARRAY_MAPPER (arg, float, std::arg);\n      RC_ARRAY_MAPPER (asin, FloatComplex, octave::math::rc_asin);\n      ARRAY_MAPPER (asinh, float, octave::math::asinh);\n      ARRAY_MAPPER (atan, float, ::atanf);\n      RC_ARRAY_MAPPER (atanh, FloatComplex, octave::math::rc_atanh);\n      ARRAY_MAPPER (erf, float, octave::math::erf);\n      ARRAY_MAPPER (erfinv, float, octave::math::erfinv);\n      ARRAY_MAPPER (erfcinv, float, octave::math::erfcinv);\n      ARRAY_MAPPER (erfc, float, octave::math::erfc);\n      ARRAY_MAPPER (erfcx, float, octave::math::erfcx);\n      ARRAY_MAPPER (erfi, float, octave::math::erfi);\n      ARRAY_MAPPER (dawson, float, octave::math::dawson);\n      ARRAY_MAPPER (gamma, float, octave::math::gamma);\n      RC_ARRAY_MAPPER (lgamma, FloatComplex, octave::math::rc_lgamma);\n      ARRAY_MAPPER (cbrt, float, octave::math::cbrt);\n      ARRAY_MAPPER (ceil, float, ::ceilf);\n      ARRAY_MAPPER (cos, float, ::cosf);\n      ARRAY_MAPPER (cosh, float, ::coshf);\n      ARRAY_MAPPER (exp, float, ::expf);\n      ARRAY_MAPPER (expm1, float, octave::math::expm1);\n      ARRAY_MAPPER (fix, float, octave::math::fix);\n      ARRAY_MAPPER (floor, float, ::floorf);\n      RC_ARRAY_MAPPER (log, FloatComplex, octave::math::rc_log);\n      RC_ARRAY_MAPPER (log2, FloatComplex, octave::math::rc_log2);\n      RC_ARRAY_MAPPER (log10, FloatComplex, octave::math::rc_log10);\n      RC_ARRAY_MAPPER (log1p, FloatComplex, octave::math::rc_log1p);\n      ARRAY_MAPPER (round, float, octave::math::round);\n      ARRAY_MAPPER (roundb, float, octave::math::roundb);\n      ARRAY_MAPPER (signum, float, octave::math::signum);\n      ARRAY_MAPPER (sin, float, ::sinf);\n      ARRAY_MAPPER (sinh, float, ::sinhf);\n      RC_ARRAY_MAPPER (sqrt, FloatComplex, octave::math::rc_sqrt);\n      ARRAY_MAPPER (tan, float, ::tanf);\n      ARRAY_MAPPER (tanh, float, ::tanhf);\n      ARRAY_MAPPER (isna, bool, octave::math::isna);\n      ARRAY_MAPPER (xsignbit, float, octave::math::signbit);\n\n    // Special cases for Matlab compatibility.\n    case umap_xtolower:\n    case umap_xtoupper:\n      return m_matrix;\n\n    case umap_xisalnum:\n    case umap_xisalpha:\n    case umap_xisascii:\n    case umap_xiscntrl:\n    case umap_xisdigit:\n    case umap_xisgraph:\n    case umap_xislower:\n    case umap_xisprint:\n    case umap_xispunct:\n    case umap_xisspace:\n    case umap_xisupper:\n    case umap_xisxdigit:\n      {\n        octave_value str_conv = convert_to_str (true, true);\n        return str_conv.map (umap);\n      }\n\n    default:\n      return octave_base_value::map (umap);\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-flt-re-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_flt_re_mat_h)\n#define octave_ov_flt_re_mat_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-base-mat.h\"\n#include \"ov-typeinfo.h\"\n\n#include \"MatrixType.h\"\n\nclass octave_value_list;\n\n// Real matrix values.\n\nextern template class OCTINTERP_API octave_base_matrix<FloatNDArray>;\n\nclass OCTINTERP_API octave_float_matrix\n  : public octave_base_matrix<FloatNDArray>\n{\npublic:\n\n  octave_float_matrix ()\n    : octave_base_matrix<FloatNDArray> () { }\n\n  octave_float_matrix (const FloatMatrix& m)\n    : octave_base_matrix<FloatNDArray> (m) { }\n\n  octave_float_matrix (const FloatMatrix& m, const MatrixType& t)\n    : octave_base_matrix<FloatNDArray> (m, t) { }\n\n  octave_float_matrix (const FloatNDArray& nda)\n    : octave_base_matrix<FloatNDArray> (nda) { }\n\n  octave_float_matrix (const Array<float>& m)\n    : octave_base_matrix<FloatNDArray> (FloatNDArray (m)) { }\n\n  octave_float_matrix (const FloatDiagMatrix& d)\n    : octave_base_matrix<FloatNDArray> (FloatMatrix (d)) { }\n\n  octave_float_matrix (const FloatRowVector& v)\n    : octave_base_matrix<FloatNDArray> (FloatMatrix (v)) { }\n\n  octave_float_matrix (const FloatColumnVector& v)\n    : octave_base_matrix<FloatNDArray> (FloatMatrix (v)) { }\n\n  octave_float_matrix (const octave_float_matrix& m)\n    : octave_base_matrix<FloatNDArray> (m) { }\n\n  ~octave_float_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_float_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_float_matrix (); }\n\n  octave_base_value * try_narrowing_conversion ();\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  {\n    return m_idx_cache ? *m_idx_cache\n           : set_idx_cache (octave::idx_vector (m_matrix));\n  }\n\n  builtin_type_t builtin_type () const { return btyp_float; }\n\n  bool is_real_matrix () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_single_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  int8NDArray\n  int8_array_value () const { return int8NDArray (m_matrix); }\n\n  int16NDArray\n  int16_array_value () const { return int16NDArray (m_matrix); }\n\n  int32NDArray\n  int32_array_value () const { return int32NDArray (m_matrix); }\n\n  int64NDArray\n  int64_array_value () const { return int64NDArray (m_matrix); }\n\n  uint8NDArray\n  uint8_array_value () const { return uint8NDArray (m_matrix); }\n\n  uint16NDArray\n  uint16_array_value () const { return uint16NDArray (m_matrix); }\n\n  uint32NDArray\n  uint32_array_value () const { return uint32NDArray (m_matrix); }\n\n  uint64NDArray\n  uint64_array_value () const { return uint64NDArray (m_matrix); }\n\n  double double_value (bool = false) const;\n\n  float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  float float_scalar_value (bool frc_str_conv = false) const\n  { return float_value (frc_str_conv); }\n\n  Matrix matrix_value (bool = false) const;\n\n  FloatMatrix float_matrix_value (bool = false) const;\n\n  Complex complex_value (bool = false) const;\n\n  FloatComplex float_complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const;\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const;\n\n  boolNDArray bool_array_value (bool warn = false) const;\n\n  charNDArray char_array_value (bool = false) const;\n\n  NDArray array_value (bool = false) const;\n\n  FloatNDArray float_array_value (bool = false) const { return m_matrix; }\n\n  SparseMatrix sparse_matrix_value (bool = false) const;\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;\n\n  octave_value all (int dim = 0) const { return m_matrix.all (dim); }\n  octave_value any (int dim = 0) const { return m_matrix.any (dim); }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  octave_value diag (octave_idx_type k = 0) const;\n\n  octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  // Use matrix_ref here to clear index cache.\n  void increment () { matrix_ref () += 1.0; }\n\n  void decrement () { matrix_ref () -= 1.0; }\n\n  void changesign () { matrix_ref ().changesign (); }\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  { return os.write (m_matrix, block_size, output_type, skip, flt_fmt); }\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-inline.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2023-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_inline_h)\n#define octave_ov_inline_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov.h\"\n\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-bool.h\"\n#include \"ov-base.h\"\n\n\n// class to construct octave_value:s inline\n\nclass octave_value_factory\n{\npublic:\n\n  static octave_value make (double d)\n  {\n    return octave_value (new octave_scalar (d));\n  }\n\n  static octave_value make (float d)\n  {\n    return octave_value (new octave_float_scalar (d));\n  }\n\n  static octave_value make (short int i)\n  {\n    return octave_value (new octave_scalar (i));\n  }\n\n  static octave_value make (unsigned short int i)\n  {\n    return octave_value (new octave_scalar (i));\n  }\n\n  static octave_value make (int i)\n  {\n    return octave_value (new octave_scalar (i));\n  }\n\n  static octave_value make (unsigned int i)\n  {\n    return octave_value (new octave_scalar (i));\n  }\n\n  static octave_value make (long int i)\n  {\n    return octave_value (new octave_scalar (i));\n  }\n\n  static octave_value make (unsigned long int i)\n  {\n    return octave_value (new octave_scalar (i));\n  }\n\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\n  static octave_value make (long long int i)\n  {\n    return octave_value (new octave_scalar (i));\n  }\n#endif\n\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\n  static octave_value make (unsigned long long int i)\n  {\n    return octave_value (new octave_scalar (i));\n  }\n#endif\n\n  static octave_value make (octave::sys::time t)\n  {\n    return octave_value (new octave_scalar (t.double_value ()));\n  }\n\n  static octave_value make (const Complex& C)\n  {\n    octave_value ov (new octave_complex (C));\n    ov.maybe_mutate (); // Fold, e.g., 1+0i to 1\n    return ov;\n  }\n\n  static octave_value make (const FloatComplex& C)\n  {\n    octave_value ov (new octave_float_complex (C));\n    ov.maybe_mutate ();\n    return ov;\n  }\n\n  static octave_value make (bool b)\n  {\n    return octave_value (new octave_bool (b));\n  }\n\n  // FIXME: The octave_value (octave_base_value *rep, bool) constructor\n  // is already defined in the ov.h header file so is the\n  // octave_value_factory::make_copy function really necessary?\n\n  static octave_value make_copy (octave_base_value *rep)\n  {\n    return octave_value (rep, true);\n  }\n\nprivate:\n\n  ~octave_value_factory () = delete;\n  octave_value_factory () = delete;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-int-traits.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_int_traits_h)\n#define octave_ov_int_traits_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov-int8.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n\n#include \"ov-uint8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n\ntemplate <typename T>\nclass octave_value_int_traits\n{\npublic:\n  typedef T scalar_type;\n};\n\n#define OCTAVE_VALUE_INT_TRAITS(MT, ST)         \\\n  template <>                                   \\\n  class                                         \\\n  octave_value_int_traits<MT>                   \\\n  {                                             \\\n  public:                                       \\\n    typedef ST scalar_type;                     \\\n  }\n\nOCTAVE_VALUE_INT_TRAITS(int8NDArray, octave_int8_scalar);\nOCTAVE_VALUE_INT_TRAITS(int16NDArray, octave_int16_scalar);\nOCTAVE_VALUE_INT_TRAITS(int32NDArray, octave_int32_scalar);\nOCTAVE_VALUE_INT_TRAITS(int64NDArray, octave_int64_scalar);\n\nOCTAVE_VALUE_INT_TRAITS(uint8NDArray, octave_uint8_scalar);\nOCTAVE_VALUE_INT_TRAITS(uint16NDArray, octave_uint16_scalar);\nOCTAVE_VALUE_INT_TRAITS(uint32NDArray, octave_uint32_scalar);\nOCTAVE_VALUE_INT_TRAITS(uint64NDArray, octave_uint64_scalar);\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-int16.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"quit.h\"\n\n#include \"errwarn.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n\n#if defined (HAVE_HDF5)\n#  define HDF5_SAVE_TYPE H5T_NATIVE_INT16\n#else\n// This value will not be used.\n#  define HDF5_SAVE_TYPE 0\n#endif\n\n#include \"ov-int16.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\noctave_hdf5_id octave_int16_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;\noctave_hdf5_id octave_int16_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int16_matrix,\n                                     \"int16 matrix\", \"int16\");\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int16_scalar,\n                                     \"int16 scalar\", \"int16\");\n"
  },
  {
    "path": "libinterp/octave-value/ov-int16.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_int16_h)\n#define octave_ov_int16_h 1\n\n#include \"octave-config.h\"\n\n#define OCTAVE_INT_T octave_int16\n\n#define OCTAVE_VALUE_INT_MATRIX_T octave_int16_matrix\n#define OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION int16_array_value\n\n#define OCTAVE_VALUE_INT_SCALAR_T octave_int16_scalar\n#define OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION int16_scalar_value\n\n#define OCTAVE_TYPE_PREDICATE_FUNCTION is_int16_type\n\n#define OCTAVE_INT_MX_CLASS mxINT16_CLASS\n\n#define OCTAVE_INT_BTYP btyp_int16\n\n#include \"ov-intx.h\"\n\n#undef OCTAVE_INT_T\n\n#undef OCTAVE_VALUE_INT_MATRIX_T\n#undef OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_VALUE_INT_SCALAR_T\n#undef OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_TYPE_PREDICATE_FUNCTION\n\n#undef OCTAVE_INT_MX_CLASS\n\n#undef OCTAVE_INT_BTYP\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-int32.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"quit.h\"\n\n#include \"errwarn.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n\n#if defined (HAVE_HDF5)\n#  define HDF5_SAVE_TYPE H5T_NATIVE_INT32\n#else\n// This value will not be used.\n#  define HDF5_SAVE_TYPE 0\n#endif\n\n#include \"ov-int32.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\noctave_hdf5_id octave_int32_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;\noctave_hdf5_id octave_int32_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int32_matrix,\n                                     \"int32 matrix\", \"int32\");\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int32_scalar,\n                                     \"int32 scalar\", \"int32\");\n"
  },
  {
    "path": "libinterp/octave-value/ov-int32.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_int32_h)\n#define octave_ov_int32_h 1\n\n#include \"octave-config.h\"\n\n#define OCTAVE_INT_T octave_int32\n\n#define OCTAVE_VALUE_INT_MATRIX_T octave_int32_matrix\n#define OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION int32_array_value\n\n#define OCTAVE_VALUE_INT_SCALAR_T octave_int32_scalar\n#define OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION int32_scalar_value\n\n#define OCTAVE_TYPE_PREDICATE_FUNCTION is_int32_type\n\n#define OCTAVE_INT_MX_CLASS mxINT32_CLASS\n\n#define OCTAVE_INT_BTYP btyp_int32\n\n#include \"ov-intx.h\"\n\n#undef OCTAVE_INT_T\n\n#undef OCTAVE_VALUE_INT_MATRIX_T\n#undef OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_VALUE_INT_SCALAR_T\n#undef OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_TYPE_PREDICATE_FUNCTION\n\n#undef OCTAVE_INT_MX_CLASS\n\n#undef OCTAVE_INT_BTYP\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-int64.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"quit.h\"\n\n#include \"errwarn.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n\n#if defined (HAVE_HDF5)\n#  define HDF5_SAVE_TYPE H5T_NATIVE_INT64\n#else\n// This value will not be used.\n#  define HDF5_SAVE_TYPE 0\n#endif\n\n#include \"ov-int64.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\noctave_hdf5_id octave_int64_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;\noctave_hdf5_id octave_int64_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int64_matrix,\n                                     \"int64 matrix\", \"int64\");\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int64_scalar,\n                                     \"int64 scalar\", \"int64\");\n"
  },
  {
    "path": "libinterp/octave-value/ov-int64.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_int64_h)\n#define octave_ov_int64_h 1\n\n#include \"octave-config.h\"\n\n#define OCTAVE_INT_T octave_int64\n\n#define OCTAVE_VALUE_INT_MATRIX_T octave_int64_matrix\n#define OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION int64_array_value\n\n#define OCTAVE_VALUE_INT_SCALAR_T octave_int64_scalar\n#define OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION int64_scalar_value\n\n#define OCTAVE_TYPE_PREDICATE_FUNCTION is_int64_type\n\n#define OCTAVE_INT_MX_CLASS mxINT64_CLASS\n\n#define OCTAVE_INT_BTYP btyp_int64\n\n#include \"ov-intx.h\"\n\n#undef OCTAVE_INT_T\n\n#undef OCTAVE_VALUE_INT_MATRIX_T\n#undef OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_VALUE_INT_SCALAR_T\n#undef OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_TYPE_PREDICATE_FUNCTION\n\n#undef OCTAVE_INT_MX_CLASS\n\n#undef OCTAVE_INT_BTYP\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-int8.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"quit.h\"\n\n#include \"errwarn.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n\n#if defined (HAVE_HDF5)\n#  define HDF5_SAVE_TYPE H5T_NATIVE_INT8\n#else\n// This value will not be used.\n#  define HDF5_SAVE_TYPE 0\n#endif\n\n#include \"ov-int8.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\noctave_hdf5_id octave_int8_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;\noctave_hdf5_id octave_int8_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int8_matrix,\n                                     \"int8 matrix\", \"int8\");\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int8_scalar,\n                                     \"int8 scalar\", \"int8\");\n"
  },
  {
    "path": "libinterp/octave-value/ov-int8.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_int8_h)\n#define octave_ov_int8_h 1\n\n#include \"octave-config.h\"\n\n#define OCTAVE_INT_T octave_int8\n\n#define OCTAVE_VALUE_INT_MATRIX_T octave_int8_matrix\n#define OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION int8_array_value\n\n#define OCTAVE_VALUE_INT_SCALAR_T octave_int8_scalar\n#define OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION int8_scalar_value\n\n#define OCTAVE_TYPE_PREDICATE_FUNCTION is_int8_type\n\n#define OCTAVE_INT_MX_CLASS mxINT8_CLASS\n\n#define OCTAVE_INT_BTYP btyp_int8\n\n#include \"ov-intx.h\"\n\n#undef OCTAVE_INT_T\n\n#undef OCTAVE_VALUE_INT_MATRIX_T\n#undef OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_VALUE_INT_SCALAR_T\n#undef OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_TYPE_PREDICATE_FUNCTION\n\n#undef OCTAVE_INT_MX_CLASS\n\n#undef OCTAVE_INT_BTYP\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-intx.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// FIXME: Do not uncomment these lines to have this file included only once.\n//        The build will break (2/6/2016).\n// #if ! defined (octave_ov_intx_h)\n// #define octave_ov_intx_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"mxarray.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-base-int.h\"\n#include \"ov-typeinfo.h\"\n#include \"errwarn.h\"\n\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n\nextern template class OCTINTERP_API\noctave_base_int_matrix<intNDArray<OCTAVE_INT_T>>;\n\nclass OCTINTERP_API OCTAVE_VALUE_INT_MATRIX_T\n  : public octave_base_int_matrix<intNDArray<OCTAVE_INT_T>>\n{\npublic:\n\n  OCTAVE_VALUE_INT_MATRIX_T ()\n    : octave_base_int_matrix<intNDArray<OCTAVE_INT_T>> () { }\n\n  OCTAVE_VALUE_INT_MATRIX_T (const intNDArray<OCTAVE_INT_T>& nda)\n    : octave_base_int_matrix<intNDArray<OCTAVE_INT_T>> (nda) { }\n\n  OCTAVE_VALUE_INT_MATRIX_T (const Array<OCTAVE_INT_T>& nda)\n    : octave_base_int_matrix<intNDArray<OCTAVE_INT_T>>\n      (intNDArray<OCTAVE_INT_T> (nda)) { }\n\n  ~OCTAVE_VALUE_INT_MATRIX_T () = default;\n\n  octave_base_value * clone () const\n  { return new OCTAVE_VALUE_INT_MATRIX_T (*this); }\n\n  octave_base_value * empty_clone () const\n  { return new OCTAVE_VALUE_INT_MATRIX_T (); }\n\n  bool OCTAVE_TYPE_PREDICATE_FUNCTION () const { return true; }\n\n  bool isinteger () const { return true; }\n\n  builtin_type_t builtin_type () const { return OCTAVE_INT_BTYP; }\n\npublic:\n\n  octave_value all (int dim = 0) const { return m_matrix.all (dim); }\n  octave_value any (int dim = 0) const { return m_matrix.any (dim); }\n\n  int8NDArray\n  int8_array_value () const { return int8NDArray (m_matrix); }\n\n  int16NDArray\n  int16_array_value () const { return int16NDArray (m_matrix); }\n\n  int32NDArray\n  int32_array_value () const { return int32NDArray (m_matrix); }\n\n  int64NDArray\n  int64_array_value () const { return int64NDArray (m_matrix); }\n\n  uint8NDArray\n  uint8_array_value () const { return uint8NDArray (m_matrix); }\n\n  uint16NDArray\n  uint16_array_value () const { return uint16NDArray (m_matrix); }\n\n  uint32NDArray\n  uint32_array_value () const { return uint32NDArray (m_matrix); }\n\n  uint64NDArray\n  uint64_array_value () const { return uint64NDArray (m_matrix); }\n\n  double\n  double_value (bool = false) const\n  {\n    double retval;\n\n    if (isempty ())\n      err_invalid_conversion (type_name (), \"real scalar\");\n\n    warn_implicit_conversion (\"Octave:array-to-scalar\",\n                              type_name (), \"real scalar\");\n\n    retval = m_matrix(0).double_value ();\n\n    return retval;\n  }\n\n  float\n  float_value (bool = false) const\n  {\n    float retval;\n\n    if (isempty ())\n      err_invalid_conversion (type_name (), \"real scalar\");\n\n    warn_implicit_conversion (\"Octave:array-to-scalar\",\n                              type_name (), \"real scalar\");\n\n    retval = m_matrix(0).float_value ();\n\n    return retval;\n  }\n\n  double scalar_value (bool = false) const { return double_value (); }\n\n  float float_scalar_value (bool = false) const { return float_value (); }\n\n  Matrix\n  matrix_value (bool = false) const\n  {\n    Matrix retval;\n    const dim_vector& dv = dims ();\n    if (dv.ndims () > 2)\n      error (\"invalid conversion of %s to Matrix\", type_name ().c_str ());\n\n    retval = Matrix (dv(0), dv(1));\n    double *vec = retval.rwdata ();\n    octave_idx_type nel = m_matrix.numel ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = m_matrix(i).double_value ();\n\n    return retval;\n  }\n\n  FloatMatrix\n  float_matrix_value (bool = false) const\n  {\n    FloatMatrix retval;\n    const dim_vector& dv = dims ();\n    if (dv.ndims () > 2)\n      error (\"invalid conversion of %s to FloatMatrix\", type_name ().c_str ());\n\n    retval = FloatMatrix (dv(0), dv(1));\n    float *vec = retval.rwdata ();\n    octave_idx_type nel = m_matrix.numel ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = m_matrix(i).float_value ();\n\n    return retval;\n  }\n\n  ComplexMatrix\n  complex_matrix_value (bool = false) const\n  {\n    ComplexMatrix retval;\n    const dim_vector& dv = dims ();\n    if (dv.ndims () > 2)\n      error (\"invalid conversion of %s to Matrix\", type_name ().c_str ());\n\n    retval = ComplexMatrix (dv(0), dv(1));\n    Complex *vec = retval.rwdata ();\n    octave_idx_type nel = m_matrix.numel ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = Complex (m_matrix(i).double_value ());\n\n    return retval;\n  }\n\n  FloatComplexMatrix\n  float_complex_matrix_value (bool = false) const\n  {\n    FloatComplexMatrix retval;\n    const dim_vector& dv = dims ();\n    if (dv.ndims () > 2)\n      error (\"invalid conversion of %s to FloatMatrix\", type_name ().c_str ());\n\n    retval = FloatComplexMatrix (dv(0), dv(1));\n    FloatComplex *vec = retval.rwdata ();\n    octave_idx_type nel = m_matrix.numel ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = FloatComplex (m_matrix(i).float_value ());\n\n    return retval;\n  }\n\n  NDArray\n  array_value (bool = false) const\n  {\n    NDArray retval (m_matrix.dims ());\n    double *vec = retval.rwdata ();\n    octave_idx_type nel = m_matrix.numel ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = m_matrix(i).double_value ();\n    return retval;\n  }\n\n  FloatNDArray\n  float_array_value (bool = false) const\n  {\n    FloatNDArray retval (m_matrix.dims ());\n    float *vec = retval.rwdata ();\n    octave_idx_type nel = m_matrix.numel ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = m_matrix(i).float_value ();\n    return retval;\n  }\n\n  ComplexNDArray\n  complex_array_value (bool = false) const\n  {\n    ComplexNDArray retval (m_matrix.dims ());\n    Complex *vec = retval.rwdata ();\n    octave_idx_type nel = m_matrix.numel ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = Complex (m_matrix(i).double_value ());\n    return retval;\n  }\n\n  FloatComplexNDArray\n  float_complex_array_value (bool = false) const\n  {\n    FloatComplexNDArray retval (m_matrix.dims ());\n    FloatComplex *vec = retval.rwdata ();\n    octave_idx_type nel = m_matrix.numel ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = FloatComplex (m_matrix(i).float_value ());\n    return retval;\n  }\n\n  boolNDArray\n  bool_array_value (bool warn = false) const\n  {\n    boolNDArray retval (dims ());\n\n    octave_idx_type nel = numel ();\n\n    if (warn && m_matrix.any_element_not_one_or_zero ())\n      warn_logical_conversion ();\n\n    bool *vec = retval.rwdata ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = m_matrix(i).bool_value ();\n\n    return retval;\n  }\n\n  charNDArray\n  char_array_value (bool = false) const\n  {\n    charNDArray retval (dims ());\n\n    octave_idx_type nel = numel ();\n\n    char *vec = retval.rwdata ();\n    for (octave_idx_type i = 0; i < nel; i++)\n      vec[i] = m_matrix(i).char_value ();\n\n    return retval;\n  }\n\n  // Use matrix_ref here to clear index cache.\n  void increment ()\n  {\n    matrix_ref () += OCTAVE_INT_T (1);\n  }\n\n  void decrement ()\n  {\n    matrix_ref () -= OCTAVE_INT_T (1);\n  }\n\n  void changesign ()\n  {\n    matrix_ref ().changesign ();\n  }\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  {\n    return m_idx_cache ? *m_idx_cache\n           : set_idx_cache (octave::idx_vector (m_matrix));\n  }\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  { return os.write (m_matrix, block_size, output_type, skip, flt_fmt); }\n\n  mxArray * as_mxArray (bool interleaved) const\n  {\n    mxArray *retval = new mxArray (interleaved, OCTAVE_INT_MX_CLASS, dims (),\n                                   mxREAL);\n\n    OCTAVE_INT_T::val_type *pd\n      = static_cast<OCTAVE_INT_T::val_type *> (retval->get_data ());\n\n    mwSize nel = numel ();\n\n    const OCTAVE_INT_T *pdata = m_matrix.data ();\n\n    for (mwIndex i = 0; i < nel; i++)\n      pd[i] = pdata[i].value ();\n\n    return retval;\n  }\n\n  octave_value map (unary_mapper_t umap) const\n  {\n    switch (umap)\n      {\n      case umap_abs:\n        return m_matrix.abs ();\n      case umap_signum:\n        return m_matrix.signum ();\n      case umap_ceil:\n      case umap_conj:\n      case umap_fix:\n      case umap_floor:\n      case umap_real:\n      case umap_round:\n        return m_matrix;\n      case umap_imag:\n        return intNDArray<OCTAVE_INT_T> (m_matrix.dims (), OCTAVE_INT_T ());\n      case umap_isnan:\n      case umap_isna:\n      case umap_isinf:\n        return boolNDArray (m_matrix.dims (), false);\n      case umap_isfinite:\n        return boolNDArray (m_matrix.dims (), true);\n\n      // Special cases for Matlab compatibility.\n      case umap_xtolower:\n      case umap_xtoupper:\n        return m_matrix;\n\n      default:\n        {\n          // FIXME: we should be able to do better than converting to\n          // double here.\n          octave_matrix m (array_value ());\n          return m.map (umap);\n        }\n      }\n  }\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool flag)\n  {\n    return save_hdf5_internal (loc_id, s_hdf5_save_type, name, flag);\n  }\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name)\n  {\n    return load_hdf5_internal (loc_id, s_hdf5_save_type, name);\n  }\n\nprivate:\n\n  static octave_hdf5_id s_hdf5_save_type;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\nextern template class OCTINTERP_API octave_base_int_scalar<OCTAVE_INT_T>;\n\nclass\nOCTINTERP_API\nOCTAVE_VALUE_INT_SCALAR_T\n  : public octave_base_int_scalar<OCTAVE_INT_T>\n{\npublic:\n\n  OCTAVE_VALUE_INT_SCALAR_T ()\n    : octave_base_int_scalar<OCTAVE_INT_T> () { }\n\n  OCTAVE_VALUE_INT_SCALAR_T (const OCTAVE_INT_T& nda)\n    : octave_base_int_scalar<OCTAVE_INT_T> (nda) { }\n\n  ~OCTAVE_VALUE_INT_SCALAR_T () = default;\n\n  octave_base_value * clone () const\n  { return new OCTAVE_VALUE_INT_SCALAR_T (*this); }\n\n  octave_base_value * empty_clone () const\n  { return new OCTAVE_VALUE_INT_MATRIX_T (); }\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false)\n  {\n    // FIXME: this doesn't solve the problem of\n    //\n    //   a = 1; a([1,1], [1,1], [1,1])\n    //\n    // and similar constructions.  Hmm...\n\n    // FIXME: using this constructor avoids narrowing the\n    // 1x1 matrix back to a scalar value.  Need a better solution\n    // to this problem.\n\n    octave_value tmp\n    (new OCTAVE_VALUE_INT_MATRIX_T\n     (OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION ()));\n\n    return tmp.index_op (idx, resize_ok);\n  }\n\n  bool OCTAVE_TYPE_PREDICATE_FUNCTION () const { return true; }\n\n  bool isinteger () const { return true; }\n\n  builtin_type_t builtin_type () const { return OCTAVE_INT_BTYP; }\n\npublic:\n\n  octave_int8\n  int8_scalar_value () const { return octave_int8 (scalar); }\n\n  octave_int16\n  int16_scalar_value () const { return octave_int16 (scalar); }\n\n  octave_int32\n  int32_scalar_value () const { return octave_int32 (scalar); }\n\n  octave_int64\n  int64_scalar_value () const { return octave_int64 (scalar); }\n\n  octave_uint8\n  uint8_scalar_value () const { return octave_uint8 (scalar); }\n\n  octave_uint16\n  uint16_scalar_value () const { return octave_uint16 (scalar); }\n\n  octave_uint32\n  uint32_scalar_value () const { return octave_uint32 (scalar); }\n\n  octave_uint64\n  uint64_scalar_value () const { return octave_uint64 (scalar); }\n\n  int8NDArray\n  int8_array_value () const\n  { return int8NDArray (dim_vector (1, 1), int8_scalar_value ()); }\n\n  int16NDArray\n  int16_array_value () const\n  { return int16NDArray (dim_vector (1, 1), int16_scalar_value ()); }\n\n  int32NDArray\n  int32_array_value () const\n  { return int32NDArray (dim_vector (1, 1), int32_scalar_value ()); }\n\n  int64NDArray\n  int64_array_value () const\n  { return int64NDArray (dim_vector (1, 1), int64_scalar_value ()); }\n\n  uint8NDArray\n  uint8_array_value () const\n  { return uint8NDArray (dim_vector (1, 1), uint8_scalar_value ()); }\n\n  uint16NDArray\n  uint16_array_value () const\n  { return uint16NDArray (dim_vector (1, 1), uint16_scalar_value ()); }\n\n  uint32NDArray\n  uint32_array_value () const\n  { return uint32NDArray (dim_vector (1, 1), uint32_scalar_value ()); }\n\n  uint64NDArray\n  uint64_array_value () const\n  { return uint64NDArray (dim_vector (1, 1), uint64_scalar_value ()); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const\n  {\n    if (fill)\n      {\n        intNDArray<OCTAVE_INT_T> retval (dv, 0);\n        if (dv.numel ())\n          retval(0) = scalar;\n        return retval;\n      }\n    else\n      {\n        intNDArray<OCTAVE_INT_T> retval (dv);\n        if (dv.numel ())\n          retval(0) = scalar;\n        return retval;\n      }\n  }\n\n  double double_value (bool = false) const { return scalar.double_value (); }\n\n  float float_value (bool = false) const { return scalar.float_value (); }\n\n  double scalar_value (bool = false) const { return scalar.double_value (); }\n\n  float float_scalar_value (bool = false) const\n  { return scalar.float_value (); }\n\n  Matrix\n  matrix_value (bool = false) const\n  {\n    Matrix retval (1, 1);\n    retval(0, 0) = scalar.double_value ();\n    return retval;\n  }\n\n  FloatMatrix\n  float_matrix_value (bool = false) const\n  {\n    FloatMatrix retval (1, 1);\n    retval(0, 0) = scalar.float_value ();\n    return retval;\n  }\n\n  ComplexMatrix\n  complex_matrix_value (bool = false) const\n  {\n    ComplexMatrix retval (1, 1);\n    retval(0, 0) = Complex (scalar.double_value ());\n    return retval;\n  }\n\n  FloatComplexMatrix\n  float_complex_matrix_value (bool = false) const\n  {\n    FloatComplexMatrix retval (1, 1);\n    retval(0, 0) = FloatComplex (scalar.float_value ());\n    return retval;\n  }\n\n  NDArray\n  array_value (bool = false) const\n  {\n    NDArray retval (dim_vector (1, 1));\n    retval(0) = scalar.double_value ();\n    return retval;\n  }\n\n  FloatNDArray\n  float_array_value (bool = false) const\n  {\n    FloatNDArray retval (dim_vector (1, 1));\n    retval(0) = scalar.float_value ();\n    return retval;\n  }\n\n  ComplexNDArray\n  complex_array_value (bool = false) const\n  {\n    ComplexNDArray retval (dim_vector (1, 1));\n    retval(0) = Complex (scalar.double_value ());\n    return retval;\n  }\n\n  FloatComplexNDArray\n  float_complex_array_value (bool = false) const\n  {\n    FloatComplexNDArray retval (dim_vector (1, 1));\n    retval(0) = FloatComplex (scalar.float_value ());\n    return retval;\n  }\n\n  bool bool_value (bool warn = false) const\n  {\n    if (warn && scalar != 0.0 && scalar != 1.0)\n      warn_logical_conversion ();\n\n    return scalar.bool_value ();\n  }\n\n  boolNDArray\n  bool_array_value (bool warn = false) const\n  {\n    boolNDArray retval (dim_vector (1, 1));\n\n    if (warn && scalar != 0.0 && scalar != 1.0)\n      warn_logical_conversion ();\n\n    retval(0) = scalar.bool_value ();\n\n    return retval;\n  }\n\n  charNDArray\n  char_array_value (bool = false) const\n  {\n    charNDArray retval (dim_vector (1, 1));\n    retval(0) = scalar.char_value ();\n    return retval;\n  }\n\n  void increment ()\n  {\n    scalar += OCTAVE_INT_T (1);\n  }\n\n  void decrement ()\n  {\n    scalar -= OCTAVE_INT_T (1);\n  }\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  { return octave::idx_vector (scalar); }\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    return os.write (OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION (),\n                     block_size, output_type, skip, flt_fmt);\n  }\n\n  mxArray * as_mxArray (bool interleaved) const\n  {\n    mxArray *retval = new mxArray (interleaved, OCTAVE_INT_MX_CLASS, 1, 1,\n                                   mxREAL);\n\n    OCTAVE_INT_T::val_type *pd\n      = static_cast<OCTAVE_INT_T::val_type *> (retval->get_data ());\n\n    pd[0] = scalar.value ();\n\n    return retval;\n  }\n\n  octave_value map (unary_mapper_t umap) const\n  {\n    switch (umap)\n      {\n      case umap_abs:\n        return scalar.abs ();\n      case umap_signum:\n        return scalar.signum ();\n      case umap_ceil:\n      case umap_conj:\n      case umap_fix:\n      case umap_floor:\n      case umap_real:\n      case umap_round:\n        return scalar;\n      case umap_imag:\n        return OCTAVE_INT_T ();\n      case umap_isnan:\n      case umap_isna:\n      case umap_isinf:\n        return false;\n      case umap_isfinite:\n        return true;\n\n      // Special cases for Matlab compatibility.\n      case umap_xtolower:\n      case umap_xtoupper:\n        return scalar;\n\n      default:\n        {\n          octave_scalar m (scalar_value ());\n          return m.map (umap);\n        }\n      }\n  }\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool flag)\n  {\n    return save_hdf5_internal (loc_id, s_hdf5_save_type, name, flag);\n  }\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name)\n  {\n    return load_hdf5_internal (loc_id, s_hdf5_save_type, name);\n  }\n\nprivate:\n\n  static octave_hdf5_id s_hdf5_save_type;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n"
  },
  {
    "path": "libinterp/octave-value/ov-java.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n\n//! @file ov-java.cc\n//!\n//! Provides Octave's Java interface.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_WINDOWS_H)\n#  include <windows.h>\n#endif\n\n#include <algorithm>\n#include <array>\n#include <clocale>\n#include <fstream>\n#include <map>\n#include <string>\n#include <vector>\n\n#include \"cmd-edit.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"fpucw-wrappers.h\"\n#include \"oct-env.h\"\n#include \"oct-shlib.h\"\n#include \"oct-sysdep.h\"\n\n#include \"Cell.h\"\n#include \"builtin-defun-decls.h\"\n#include \"defaults.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"oct-process.h\"\n#include \"ov-java.h\"\n#include \"variables.h\"\n\n#if defined (HAVE_JAVA)\n#include <jni.h>\n#endif\n\n#if defined (HAVE_JAVA)\n\n// FIXME: Should these values be configurable at run time?\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  define LIBJVM_FILE_NAME \"jvm.dll\"\n#elif defined (__APPLE__)\n#  define LIBJVM_FILE_NAME \"libjvm.dylib\"\n#  define JAVA_HOME_CMD \"/usr/libexec/java_home\"\n#else\n#  define LIBJVM_FILE_NAME \"libjvm.so\"\n#endif\n\n#define TO_JOBJECT(obj) reinterpret_cast<jobject> (obj)\n#define TO_JCLASS(obj) reinterpret_cast<jclass> (obj)\n\n#define TO_JNIENV(env) reinterpret_cast<JNIEnv *> (env)\n\ntypedef jint (JNICALL *JNI_CreateJavaVM_t) (JavaVM **pvm, JNIEnv **penv,\n    void *args);\n\ntypedef jint (JNICALL *JNI_GetCreatedJavaVMs_t) (JavaVM **pvm, jsize bufLen,\n    jsize *nVMs);\n\ntemplate <typename T>\nclass java_local_ref\n{\npublic:\n\n  java_local_ref (JNIEnv *env)\n    : m_jobj (nullptr), m_detached (false), m_env (env) { }\n\n  java_local_ref (JNIEnv *env, T obj)\n    : m_jobj (obj), m_detached (false), m_env (env) { }\n\n  ~java_local_ref () { release (); }\n\n  T& operator = (T obj)\n  {\n    release ();\n\n    m_jobj = obj;\n    m_detached = false;\n\n    return m_jobj;\n  }\n\n  operator bool () const { return (m_jobj != 0); }\n  operator T () { return m_jobj; }\n\n  void detach () { m_detached = true; }\n\nprotected:\n\n  T m_jobj;\n  bool m_detached;\n  JNIEnv *m_env;\n\nprivate:\n\n  java_local_ref ()\n    : m_jobj (0), m_detached (false), m_env (0)\n  { }\n\n  void release ()\n  {\n    if (m_env && m_jobj && ! m_detached)\n      m_env->DeleteLocalRef (m_jobj);\n\n    m_jobj = nullptr;\n  }\n\n};\n\ntypedef java_local_ref<jobject> jobject_ref;\ntypedef java_local_ref<jclass> jclass_ref;\ntypedef java_local_ref<jstring> jstring_ref;\ntypedef java_local_ref<jobjectArray> jobjectArray_ref;\ntypedef java_local_ref<jintArray> jintArray_ref;\ntypedef java_local_ref<jbyteArray> jbyteArray_ref;\ntypedef java_local_ref<jdoubleArray> jdoubleArray_ref;\ntypedef java_local_ref<jthrowable> jthrowable_ref;\n\nstatic std::string\njstring_to_string (JNIEnv *jni_env, jstring s);\n\nstatic std::string\njstring_to_string (JNIEnv *jni_env, jobject obj);\n\nstatic octave_value\nbox (JNIEnv *jni_env, void *jobj, void *jcls_arg = nullptr);\n\nstatic octave_value\nbox_more (JNIEnv *jni_env, void *jobj_arg, void *jcls_arg = nullptr);\n\nstatic bool\nunbox (JNIEnv *jni_env, const octave_value& val, jobject_ref& jobj,\n       jclass_ref& jcls);\n\nstatic bool\nunbox (JNIEnv *jni_env, const octave_value_list& args,\n       jobjectArray_ref& jobjs, jobjectArray_ref& jclss);\n\nextern \"C\"\n{\n  JNIEXPORT jboolean JNICALL\n  Java_org_octave_Octave_call (JNIEnv *, jclass, jstring, jobjectArray,\n                               jobjectArray);\n\n  JNIEXPORT void JNICALL\n  Java_org_octave_OctaveReference_doFinalize (JNIEnv *, jclass, jint);\n\n  JNIEXPORT void JNICALL\n  Java_org_octave_Octave_doInvoke (JNIEnv *, jclass, jint, jobjectArray);\n\n  JNIEXPORT void JNICALL\n  Java_org_octave_Octave_doEvalString (JNIEnv *, jclass, jstring);\n\n  JNIEXPORT jboolean JNICALL\n  Java_org_octave_Octave_needThreadedInvokation (JNIEnv *, jclass);\n}\n\n//! The pointer to a java virtual machine either created in the current thread\n//! or attached this thread to it.\n\nstatic JavaVM *jvm = nullptr;\n\n//! Whether the current thread is attached to the jvm given by #jvm.\n//! This is @c false also if no jvm exists, i.e., if #jvm is @c nullptr.\n//! @see #initialize_jvm()\n//! @see #terminate_jvm()\n\nstatic bool jvm_attached = false;\n\n//! Need to keep hold of the shared library handle until exit.\n//! @see #initialize_jvm()\n//! @see #terminate_jvm()\n\nstatic octave::dynamic_library jvm_lib;\n\nstatic std::map<int, octave_value> listener_map;\nstatic std::map<int, octave_value> octave_ref_map;\nstatic int octave_java_refcount = 0;\n\n//! The thread id of the currently executing thread or @c -1 if this is\n//! unknown.\n//! @see #initialize_java()\n\nstatic long octave_thread_ID = -1;\n\nbool Vjava_matrix_autoconversion = false;\nbool Vjava_unsigned_autoconversion = true;\nbool Vdebug_java = false;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass JVMArgs\n{\npublic:\n\n  JVMArgs ()\n  {\n    m_vm_args.version = JNI_VERSION_1_6;\n    m_vm_args.nOptions = 0;\n    m_vm_args.options = nullptr;\n    m_vm_args.ignoreUnrecognized = false;\n  }\n\n  ~JVMArgs ()\n  {\n    clean ();\n  }\n\n  JavaVMInitArgs * to_args ()\n  {\n    update ();\n    return &m_vm_args;\n  }\n\n  void add (const std::string& opt)\n  {\n    m_java_opts.push_back (opt);\n  }\n\n  void read_java_opts (const std::string& filename)\n  {\n    std::ifstream js = sys::ifstream (filename.c_str ());\n\n    if (! js.bad () && ! js.fail ())\n      {\n        std::string line;\n\n        while (! js.eof () && ! js.fail ())\n          {\n            std::getline (js, line);\n\n            if (line.find ('-') == 0)\n              m_java_opts.push_back (line);\n            else if (line.length () > 0 && Vdebug_java)\n              warning (\"invalid JVM option, skipping: %s\", line.c_str ());\n          }\n      }\n  }\n\nprivate:\n\n  void clean ()\n  {\n    if (m_vm_args.options != nullptr)\n      {\n        for (int i = 0; i < m_vm_args.nOptions; i++)\n          delete [] m_vm_args.options[i].optionString;\n\n        delete [] m_vm_args.options;\n\n        m_vm_args.options = nullptr;\n        m_vm_args.nOptions = 0;\n      }\n  }\n\n  void update ()\n  {\n    clean ();\n\n    if (m_java_opts.size () > 0)\n      {\n        int index = 0;\n\n        m_vm_args.nOptions = m_java_opts.size ();\n        m_vm_args.options = new JavaVMOption [m_vm_args.nOptions];\n\n        for (const auto& opt : m_java_opts)\n          {\n            if (Vdebug_java)\n              octave_stdout << opt << std::endl;\n            m_vm_args.options[index++].optionString = strsave (opt.c_str ());\n          }\n\n        m_java_opts.clear ();\n      }\n  }\n\nprivate:\n\n  JavaVMInitArgs m_vm_args;\n\n  std::list<std::string> m_java_opts;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n//! The java initialization directory is given by the environment variable\n//! @c OCTAVE_JAVA_DIR if defined; otherwise it is the directory of Octave's\n//! m-files defining Java functions.\n//!\n//! The Java initialization directory is the directory where resides:\n//!\n//! - @c octave.jar, defining the java classes implementing octave's java\n//!   interface,\n//! - @c javaclasspath.txt, defining the installation defined portion of the\n//!   (static) classpath,\n//! - @c java.opts, defining the configurable options of the java virtual\n//!   machine.\n//!\n//! Note that the (static) java classpath of the java virtual machine starts\n//! with @c octave.jar, and that the static java classpath ends with what\n//! is read from @c javaclasspath.txt located in the initial java directory.\n//! Moreover, the java virtual machine is created essentially with\n//! the options given by @c java.opts.\n\nstatic std::string\ninitial_java_dir ()\n{\n  static std::string java_dir;\n\n  if (java_dir.empty ())\n    {\n      java_dir = octave::sys::env::getenv (\"OCTAVE_JAVA_DIR\");\n\n      if (java_dir.empty ())\n        java_dir = (octave::config::fcn_file_dir ()\n                    + octave::sys::file_ops::dir_sep_str () + \"java\");\n    }\n\n  return java_dir;\n}\n\n//! Return the classpath in the given file @c filepath as a string.\n//!\n//! In the classpath file, each line which is neither empty nor a comment, is\n//! interpreted as a segment of a path.  Comment lines are those starting with\n//! a @c # or with a @c % in the very first column.\n//!\n//! @param filepath The path to the file (usually @c classpath.txt) containing\n//!   a portion of the classpath.\n//!\n//! @returns A string consisting of the lines of @c filepath which are neither\n//!   comments nor empty without trailing whitespace separated by\n//!   'octave::directory_path::path_sep_str()'.  The returned string also\n//!   starts with that path separator.\n\nstatic std::string\nread_classpath_txt (const std::string& filepath)\n{\n  std::string classpath;\n\n  std::ifstream fs = octave::sys::ifstream (filepath.c_str ());\n\n  if (! fs.bad () && ! fs.fail ())\n    {\n      std::string line;\n\n      while (! fs.eof () && ! fs.fail ())\n        {\n          std::getline (fs, line);\n          if (line.length () > 0 && line[0] != '#' && line[0] != '%')\n            {\n              // prepend separator character\n              classpath.append (octave::directory_path::path_sep_str ());\n\n              // append content of line without whitespace\n              int last = line.find_last_not_of (\" \\t\\f\\v\\r\\n\");\n\n              classpath.append (octave::sys::file_ops::tilde_expand (line.substr (0, last+1)));\n            }\n        }\n    }\n\n  return (classpath);\n}\n\n//! Return the initial classpath.\n//!\n//! The initial classpath starts with a pointer to @c octave.jar which is\n//! located in the initial java directory given by #initial_java_dir().\n//!\n//! @attention This is nowhere documented and also the script\n//! @c javaclasspath.m drops this.  On the other hand, this is vital because\n//! @c octave.jar contains the java core classes of octave's java interface.\n//!\n//! The rest of the classpath is read sequentially from files\n//! @c javaclasspath.txt located in either:\n//!\n//! - the current directory,\n//! - the user's home directory,\n//! - the initial java directory returned by #initial_java_dir()\n//!\n//! @returns The initial classpath.\n\nstatic std::string\ninitial_class_path ()\n{\n  std::string java_dir = initial_java_dir ();\n\n  std::string retval = java_dir;\n\n  // Find octave.jar file.\n  if (! retval.empty ())\n    {\n      std::string sep = octave::sys::file_ops::dir_sep_str ();\n\n      std::string jar_file = java_dir + sep + \"octave.jar\";\n\n      octave::sys::file_stat jar_exists (jar_file);\n\n      if (jar_exists)\n        {\n          // Initialize static classpath to octave.jar.\n          retval = jar_file;\n\n          // The base classpath has been set.\n          // Try to find an optional file specifying classpaths in 3 places.\n          // 1) Current directory\n          // 2) User's home directory\n          // 3) Octave installation directory where octave.jar resides\n\n          std::string cwd      = octave::sys::env::get_current_directory ();\n          std::string home_dir = octave::sys::env::get_home_directory ();\n\n          // The filename is \"javaclasspath.txt\", but historically has been\n          // \"classpath.txt\" so both are supported.\n          std::vector<std::string> cp_list = {\"javaclasspath.txt\",\n                                              \"classpath.txt\"\n                                             };\n\n          for (std::string filename : cp_list)\n            {\n              std::string cp_file = filename;\n              octave::sys::file_stat cp_exists;\n\n              // Try to find classpath file in the current directory.\n\n              cp_exists = octave::sys::file_stat (cp_file);\n              if (cp_exists)\n                {\n                  // File found.  Add its contents to the static classpath.\n                  std::string classpath = read_classpath_txt (cp_file);\n                  retval.append (classpath);\n                }\n\n              // Try to find classpath file in the user's home directory.\n\n              if (cwd != home_dir)\n                {\n                  cp_file = '~' + sep + filename;\n                  cp_file = octave::sys::file_ops::tilde_expand (cp_file);\n                  cp_exists = octave::sys::file_stat (cp_file);\n                  if (cp_exists)\n                    {\n                      // File found.  Add its contents to the static classpath.\n                      std::string classpath = read_classpath_txt (cp_file);\n                      retval.append (classpath);\n                    }\n                }\n\n              // Try to find classpath file in the Octave install directory.\n\n              if (cwd != java_dir)\n                {\n                  cp_file = java_dir + sep + filename;\n                  cp_exists = octave::sys::file_stat (cp_file);\n                  if (cp_exists)\n                    {\n                      // File found.  Add its contents to the static classpath.\n                      std::string classpath = read_classpath_txt (cp_file);\n                      retval.append (classpath);\n                    }\n                }\n            }\n        }\n      else\n        error (\"octave.jar does not exist: %s\", jar_file.c_str ());\n    }\n  else\n    error (\"initial java dir is empty\");\n\n  return retval;\n}\n\nstatic std::string\nget_jvm_lib_path_in_subdir (std::string java_home_path)\n{\n  // This assumes that whatever architectures are installed are appropriate for\n  // this machine\n#if defined (OCTAVE_USE_WINDOWS_API)\n  const std::array<const std::string, 2> subdirs = {\"bin/client\", \"bin/server\"};\n#else\n  const std::array<const std::string, 8> subdirs =\n  {\n    \"jre/lib/server\", \"jre/lib\", \"lib/client\", \"lib/server\",\n    \"jre/lib/amd64/client\", \"jre/lib/amd64/server\",\n    \"jre/lib/i386/client\", \"jre/lib/i386/server\"\n  };\n#endif\n\n  for (std::size_t i = 0; i < subdirs.size (); i++)\n    {\n      std::string candidate = java_home_path + \"/\" + subdirs[i]\n                              + \"/\" LIBJVM_FILE_NAME;\n      if (octave::sys::file_stat (candidate))\n        return candidate;\n    }\n  return \"\";\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n// Declare function defined in sysdep.cc\nextern LONG\nget_regkey_value (HKEY h_rootkey, const std::string subkey,\n                  const std::string name, octave_value& value);\nOCTAVE_END_NAMESPACE(octave)\n\nstatic std::string\nget_jvm_lib_path_from_registry ()\n{\n  // In Windows, find the location of the JRE from the registry\n  std::string key, jversion, value;\n\n  // First search for JRE >= 15\n  key = R\"(software\\javasoft\\jdk)\";\n\n  jversion = octave::sys::env::getenv (\"JAVA_VERSION\");\n  bool maybe_version_15_or_newer = true;\n  octave_value regval;\n  LONG retval;\n  if (jversion.empty ())\n    {\n      value = \"CurrentVersion\";\n      retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key, value,\n                                         regval);\n\n      if (retval != ERROR_SUCCESS)\n        {\n          // Search for JRE < 15\n          maybe_version_15_or_newer = false;\n          key = R\"(software\\javasoft\\jre)\";\n          retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key, value,\n                                             regval);\n\n          if (retval != ERROR_SUCCESS)\n            {\n              // Search for JRE < 9\n              key = R\"(software\\javasoft\\java runtime environment)\";\n              retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key,\n                                                 value, regval);\n            }\n        }\n\n      if (retval != ERROR_SUCCESS)\n        error (\"unable to find Java Runtime Environment: %s::%s\",\n               key.c_str (), value.c_str ());\n\n      jversion = regval.xstring_value (\"initialize_jvm: registry value \"\n                                       R\"(\"%s\" at \"%s\" must be a string)\",\n                                       value.c_str (), key.c_str ());\n    }\n\n  std::string jvm_lib_path;\n  if (maybe_version_15_or_newer)\n    {\n      // Look for value used by JRE >= 15\n      key = key + '\\\\' + jversion;\n      value = \"JavaHome\";\n      retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key, value,\n                                         regval);\n\n      if (retval != ERROR_SUCCESS)\n        error (\"unable to find Java Runtime Environment: %s::%s\",\n               key.c_str (), value.c_str ());\n\n      jvm_lib_path\n        = regval.xstring_value (R\"(initialize_jvm: registry value \"%s\" at )\"\n                                R\"(\"%s\" must be a string)\",\n                                value.c_str (), key.c_str ())\n          + R\"(\\bin\\server\\jvm.dll)\";\n\n      if (! jvm_lib_path.empty ())\n        return jvm_lib_path;\n\n    }\n\n  // Search for JRE < 15\n  key = R\"(software\\javasoft\\jre\\)\" + jversion;\n  value = \"RuntimeLib\";\n  retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key, value,\n                                     regval);\n\n  if (retval != ERROR_SUCCESS)\n    {\n      // Search for JRE < 9\n      key = R\"(software\\javasoft\\java runtime environment\\)\" + jversion;\n      retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key, value,\n                                         regval);\n    }\n\n  if (retval != ERROR_SUCCESS)\n    error (\"unable to find Java Runtime Environment: %s::%s\",\n           key.c_str (), value.c_str ());\n\n  jvm_lib_path\n    = regval.xstring_value (R\"(initialize_jvm: registry value \"%s\" at )\"\n                            R\"(\"%s\" must be a string)\",\n                            value.c_str (), key.c_str ());\n\n  if (jvm_lib_path.empty ())\n    error (\"unable to find Java Runtime Environment: %s::%s\",\n           key.c_str (), value.c_str ());\n\n  return jvm_lib_path;\n}\n\n#endif\n\n//! Initialize the java virtual machine (jvm) and field #jvm if necessary.\n//!\n//! If the jvm exists and is initialized, #jvm points to it, i.e., is not 0\n//! and there is nothing to do.\n//!\n//! If #jvm is 0 and if at least one jvm exists, attach the current thread to\n//! it by setting #jvm_attached.  Otherwise, create a #jvm with some hard-\n//! coded options:\n//!\n//! - '-Djava.class.path=classpath', where @c classpath is given by\n//!   #initial_class_path().\n//! - '-Xrs'\n//!\n//! Further options are read from the file @c java.opts in the directory given\n//! by #initial_java_dir().\n//!\n//! Note that #initial_class_path() determines the initial classpath.  This\n//! is the static classpath which cannot be changed.  Elements of the dynamic\n//! classpath can be added and removed using the m-file scripts\n//! @c javaaddpath.m and @c javarmpath.m.\n//!\n//! @see #terminate_jvm()\n\nstatic void\ninitialize_jvm ()\n{\n  // Most of the time JVM already exists and has been initialized.\n  // Also it seems, as if jvm is set, the jvm is already attached.\n  // This does not fit terminate_jvm.\n  if (jvm)\n    return;\n\n  JNIEnv *current_env;\n  const char *static_locale = setlocale (LC_ALL, nullptr);\n  std::string locale;\n  if (static_locale)\n    locale = std::string (static_locale);\n\n  octave::dynamic_library lib (\"\");\n  std::string jvm_lib_path;\n\n  // Check whether the Java VM library is already loaded or linked in.\n  JNI_CreateJavaVM_t create_vm = reinterpret_cast<JNI_CreateJavaVM_t>\n                                 (lib.search (\"JNI_CreateJavaVM\"));\n  JNI_GetCreatedJavaVMs_t get_vm = reinterpret_cast<JNI_GetCreatedJavaVMs_t>\n                                   (lib.search (\"JNI_GetCreatedJavaVMs\"));\n\n  if (create_vm && get_vm)\n    jvm_lib_path = \"linked in or loaded libraries\";\n  else\n    {\n      // JAVA_HOME environment variable takes precedence\n      std::string java_home_env = octave::sys::env::getenv (\"JAVA_HOME\");\n      if (! java_home_env.empty ())\n        {\n          jvm_lib_path = get_jvm_lib_path_in_subdir (java_home_env);\n\n          // If JAVA_HOME does not look like a Java directory, use it anyway\n          // to fail with a useful error message indicating the directory\n          if (jvm_lib_path.empty ())\n            jvm_lib_path = java_home_env + \"/\" LIBJVM_FILE_NAME;\n        }\n\n#  if defined (__APPLE__)\n      // Use standard /usr/libexec/java_home if available.\n      if (jvm_lib_path.empty ())\n        {\n          octave::sys::file_stat libexec_java_home_exists (JAVA_HOME_CMD);\n          if (libexec_java_home_exists)\n            {\n              // FIXME: Should this command be fully configurable at run\n              // time?  Or is it OK for the options to be fixed here?\n\n              std::string java_home_cmd = std::string (JAVA_HOME_CMD)\n                                          + \" --failfast --version 1.6+ 2>/dev/null\";\n\n              octave::process_execution_result rslt\n                = octave::run_command_and_return_output (java_home_cmd);\n\n              if (rslt.exit_status () == 0)\n                {\n                  std::string output = rslt.stdout_output ();\n                  std::string found_path = output.substr (0, output.length() - 1);\n                  std::string jvm_lib_found = get_jvm_lib_path_in_subdir (found_path);\n                  if (!jvm_lib_found.empty ())\n                    jvm_lib_path = jvm_lib_found;\n                }\n            }\n        }\n#  endif\n\n      if (jvm_lib_path.empty ())\n        {\n#if defined (OCTAVE_USE_WINDOWS_API)\n          jvm_lib_path = get_jvm_lib_path_from_registry ();\n#else\n          // Fall back to JAVA_LDPATH, determined by the build system\n          jvm_lib_path = std::string (JAVA_LDPATH) + \"/\" LIBJVM_FILE_NAME;\n#endif\n        }\n\n      lib = octave::dynamic_library (jvm_lib_path);\n\n      if (! lib)\n        error (\"unable to load Java Runtime Environment from %s\",\n               jvm_lib_path.c_str ());\n\n      create_vm = reinterpret_cast<JNI_CreateJavaVM_t>\n                  (lib.search (\"JNI_CreateJavaVM\"));\n      get_vm = reinterpret_cast<JNI_GetCreatedJavaVMs_t>\n               (lib.search (\"JNI_GetCreatedJavaVMs\"));\n\n      if (! create_vm)\n        error (\"unable to find JNI_CreateJavaVM in %s\", jvm_lib_path.c_str ());\n\n      if (! get_vm)\n        error (\"unable to find JNI_GetCreatedJavaVMs in %s\",\n               jvm_lib_path.c_str ());\n    }\n\n  //! The number of created jvm's.\n  jsize nVMs = 0;\n\n  if (get_vm (&jvm, 1, &nVMs) == 0 && nVMs > 0)\n    {\n      // At least one JVM exists, try to attach the current thread to it.\n\n      switch (jvm->GetEnv (reinterpret_cast<void **> (&current_env),\n                           JNI_VERSION_1_6))\n        {\n        case JNI_EDETACHED:\n          // Attach the current thread\n          JavaVMAttachArgs m_vm_args;\n          m_vm_args.version = JNI_VERSION_1_6;\n          m_vm_args.name = const_cast<char *> (\"octave\");\n          m_vm_args.group = nullptr;\n          if (jvm->AttachCurrentThread (reinterpret_cast<void **> (&current_env),\n                                        &m_vm_args) < 0)\n            error (\"JVM internal error, unable to attach octave to existing JVM\");\n          break;\n\n        case JNI_EVERSION:\n          error (\"JVM internal error, the required JNI version is not supported\");\n\n        case JNI_OK:\n          // Don't do anything, the current thread is already attached to JVM\n          break;\n        }\n\n      jvm_attached = true;\n    }\n  else\n    {\n      // No JVM exists, create one\n\n      octave::JVMArgs m_vm_args;\n\n      // Hard-coded options for the jvm.\n      m_vm_args.add (\"-Djava.class.path=\" + initial_class_path ());\n#if defined (HAVE_BROKEN_PTHREAD_STACKSIZE)\n      m_vm_args.add (\"-Djdk.lang.processReaperUseDefaultStackSize=true\");\n#endif\n      m_vm_args.add (\"-Xrs\");\n\n      // Additional options given by file java.opts.\n      m_vm_args.read_java_opts (initial_java_dir () +\n                                octave::sys::file_ops::dir_sep_str () +\n                                \"java.opts\");\n\n      if (create_vm (&jvm, &current_env, m_vm_args.to_args ()) != JNI_OK)\n        error (\"unable to start Java VM in %s\", jvm_lib_path.c_str ());\n    }\n\n  jvm_lib = lib;\n\n  setlocale (LC_ALL, locale.c_str ());\n}\n\n//! Terminate the current jvm, if there is any.\n//!\n//! Otherwise, detach the jvm if this thread is attached to it and unload it\n//! if this thread created it itself.\n//!\n//! @see #initialize_jvm()\n\nstatic void\nterminate_jvm ()\n{\n  // There is nothing to do if jvm is not set (= nullptr).\n  if (jvm)\n    {\n      // FIXME: Seems that if jvm_attached is always true if jvm is not null.\n      if (jvm_attached)\n        jvm->DetachCurrentThread ();\n      else\n        jvm->DestroyJavaVM ();\n\n      jvm = nullptr;\n      jvm_attached = false;\n\n      if (jvm_lib)\n        jvm_lib.close ();\n\n      octave_set_default_fpucw ();\n    }\n}\n\n//! Converts a Java string object to std::string.\n//!{\nstatic std::string\njstring_to_string (JNIEnv *jni_env, jstring s)\n{\n  std::string retval;\n\n  if (jni_env)\n    {\n      const char *cstr = jni_env->GetStringUTFChars (s, nullptr);\n      retval = cstr;\n      jni_env->ReleaseStringUTFChars (s, cstr);\n    }\n\n  return retval;\n}\n\nstatic std::string\njstring_to_string (JNIEnv *jni_env, jobject obj)\n{\n  std::string retval;\n\n  if (jni_env && obj)\n    {\n      jclass_ref cls (jni_env, jni_env->FindClass (\"java/lang/String\"));\n      if (cls)\n        {\n          if (jni_env->IsInstanceOf (obj, cls))\n            retval = jstring_to_string (jni_env,\n                                        reinterpret_cast<jstring> (obj));\n        }\n    }\n\n  return retval;\n}\n//!}\n\n//! Returns a reference to the jni (java native interface) environment of the\n//! Java virtual machine #jvm.\n//!\n//! @returns A reference to jni, if #jvm is present, otherwise @c nullptr.\n\nstatic inline JNIEnv *\nthread_jni_env ()\n{\n  JNIEnv *env = nullptr;\n\n  if (jvm)\n    jvm->GetEnv (reinterpret_cast<void **> (&env), JNI_VERSION_1_6);\n\n  return env;\n}\n\n#else\n\nOCTAVE_NORETURN static void\nerror_unexpected (const char *name)\n{\n  error (\"unexpected call to %s when HAVE_JAVA is not defined - please report this bug\", name);\n}\n\n#endif\n\nbool\noctave_java::is_java_string () const\n{\n#if defined (HAVE_JAVA)\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  if (current_env && m_java_object)\n    {\n      jclass_ref cls (current_env, current_env->FindClass (\"java/lang/String\"));\n      return current_env->IsInstanceOf (TO_JOBJECT (m_java_object), cls);\n    }\n\n  return false;\n\n#else\n\n  // This shouldn't happen because construction of octave_java objects is\n  // supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::is_java_string\");\n\n#endif\n}\n\nbool\noctave_java::is_instance_of (const std::string& cls_name) const\n{\n#if defined (HAVE_JAVA)\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  std::string cls_cpp = cls_name;\n  std::replace (cls_cpp.begin (), cls_cpp.end (), '.', '/');\n\n  if (current_env && m_java_object)\n    {\n      jclass_ref cls (current_env, current_env->FindClass (cls_cpp.c_str ()));\n      if (current_env->ExceptionCheck ())\n        current_env->ExceptionClear ();\n      else\n        return current_env->IsInstanceOf (TO_JOBJECT (m_java_object), cls);\n    }\n  return false;\n\n#else\n\n  octave_unused_parameter (cls_name);\n\n  // This shouldn't happen because construction of octave_java objects is\n  // supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::is_instance_of\");\n\n#endif\n}\n\n#if defined (HAVE_JAVA)\n\nstatic octave_value\ncheck_exception (JNIEnv *jni_env)\n{\n  octave_value retval;\n\n  jthrowable_ref ex (jni_env, jni_env->ExceptionOccurred ());\n\n  if (ex)\n    {\n      if (Vdebug_java)\n        jni_env->ExceptionDescribe ();\n\n      jni_env->ExceptionClear ();\n\n      jclass_ref jcls (jni_env, jni_env->GetObjectClass (ex));\n      jmethodID mID = jni_env->GetMethodID (jcls, \"toString\",\n                                            \"()Ljava/lang/String;\");\n      jstring_ref js (jni_env,\n                      reinterpret_cast<jstring> (jni_env->CallObjectMethod (ex,\n                          mID)));\n      std::string msg = jstring_to_string (jni_env, js);\n\n      error (\"[java] %s\", msg.c_str ());\n    }\n  else\n    retval = Matrix ();\n\n  return retval;\n}\n\nstatic jclass\nfind_octave_class (JNIEnv *jni_env, const char *name)\n{\n  static std::string class_loader;\n  static jclass uiClass = nullptr;\n\n  jclass jcls = jni_env->FindClass (name);\n\n  if (jcls == nullptr)\n    {\n      jni_env->ExceptionClear ();\n\n      if (! uiClass)\n        {\n          if (class_loader.empty ())\n            {\n              jclass_ref syscls (jni_env,\n                                 jni_env->FindClass (\"java/lang/System\"));\n              jmethodID mID = jni_env->GetStaticMethodID\n                              (syscls,\n                               \"getProperty\",\n                               \"(Ljava/lang/String;)Ljava/lang/String;\");\n              jstring_ref js (jni_env,\n                              jni_env->NewStringUTF (\"octave.class.loader\"));\n              js = reinterpret_cast<jstring> (jni_env->CallStaticObjectMethod\n                                              (syscls, mID, jstring (js)));\n              class_loader = jstring_to_string (jni_env, jstring (js));\n              std::replace (class_loader.begin (), class_loader.end (),\n                            '.', '/');\n            }\n\n          jclass_ref uicls (jni_env,\n                            jni_env->FindClass (class_loader.c_str ()));\n\n          if (! uicls)\n            {\n              jni_env->ExceptionClear ();\n\n              // Try the netbeans way\n              std::replace (class_loader.begin (), class_loader.end (),\n                            '/', '.');\n              jclass_ref jcls2 (jni_env,\n                                jni_env->FindClass (\"org/openide/util/Lookup\"));\n              jmethodID mID = jni_env->GetStaticMethodID\n                              (jcls2, \"getDefault\", \"()Lorg/openide/util/Lookup;\");\n              jobject_ref lObj (jni_env,\n                                jni_env->CallStaticObjectMethod (jcls2, mID));\n              mID = jni_env->GetMethodID (jcls2, \"lookup\",\n                                          \"(Ljava/lang/Class;)Ljava/lang/Object;\");\n              jclass_ref cLoaderCls (jni_env,\n                                     jni_env->FindClass (\"java/lang/ClassLoader\"));\n              jobject_ref cLoader (jni_env,\n                                   jni_env->CallObjectMethod\n                                   (lObj, mID, jclass (cLoaderCls)));\n              mID = jni_env->GetMethodID (cLoaderCls, \"loadClass\",\n                                          \"(Ljava/lang/String;)Ljava/lang/Class;\");\n              jstring_ref js (jni_env,\n                              jni_env->NewStringUTF (class_loader.c_str ()));\n              uicls = reinterpret_cast<jclass>\n                      (jni_env->CallObjectMethod (cLoader, mID, jstring (js)));\n            }\n\n          if (uicls)\n            uiClass = reinterpret_cast<jclass>\n                      (jni_env->NewGlobalRef (jclass (uicls)));\n        }\n\n      if (uiClass)\n        {\n          jmethodID mID = jni_env->GetStaticMethodID\n                          (uiClass, \"findClass\", \"(Ljava/lang/String;)Ljava/lang/Class;\");\n          jstring_ref js (jni_env, jni_env->NewStringUTF (name));\n          jcls = reinterpret_cast<jclass>\n                 (jni_env->CallStaticObjectMethod (uiClass, mID, jstring (js)));\n        }\n    }\n\n  return jcls;\n}\n\nstatic dim_vector\ncompute_array_dimensions (JNIEnv *jni_env, jobject obj)\n{\n  jobjectArray_ref jobj (jni_env, reinterpret_cast<jobjectArray> (obj));\n  jclass_ref jcls (jni_env, jni_env->GetObjectClass (obj));\n  jclass_ref ccls (jni_env, jni_env->GetObjectClass (jcls));\n  jmethodID isArray_ID = jni_env->GetMethodID (ccls, \"isArray\", \"()Z\");\n  jmethodID getComponentType_ID = jni_env->GetMethodID (ccls,\n                                  \"getComponentType\",\n                                  \"()Ljava/lang/Class;\");\n\n  dim_vector dv (1, 1);\n  int idx = 0;\n\n  jobj.detach ();\n  while (jcls && jni_env->CallBooleanMethod (jcls, isArray_ID))\n    {\n      int len = (jobj ? jni_env->GetArrayLength (jobj) : 0);\n      if (idx >= dv.ndims ())\n        dv.resize (idx+1);\n      dv(idx) = len;\n      jcls = reinterpret_cast<jclass>\n             (jni_env->CallObjectMethod (jcls, getComponentType_ID));\n      jobj = len > 0\n             ? reinterpret_cast<jobjectArray> (jni_env->GetObjectArrayElement (jobj,\n                 0))\n             : nullptr;\n      idx++;\n    }\n\n  octave_set_default_fpucw ();\n\n  return dv;\n}\n\nstatic jobject\nmake_java_index (JNIEnv *jni_env, const octave_value_list& idx)\n{\n  jclass_ref ocls (jni_env, jni_env->FindClass (\"[I\"));\n  jobjectArray retval = jni_env->NewObjectArray (idx.length (), ocls, nullptr);\n  // Here retval has the same length as idx\n\n  // Fill in entries of idx into retval\n  for (int i = 0; i < idx.length (); i++)\n    try\n      {\n        octave::idx_vector v = idx(i).index_vector ();\n\n        jintArray_ref i_array (jni_env, jni_env->NewIntArray (v.length ()));\n        jint *buf = jni_env->GetIntArrayElements (i_array, nullptr);\n        // Here, buf points to the beginning of i_array\n\n        // Copy v to buf.\n        for (int k = 0; k < v.length (); k++)\n          buf[k] = v(k);\n\n        // Set retval[i] = i_array\n        jni_env->ReleaseIntArrayElements (i_array, buf, 0);\n        jni_env->SetObjectArrayElement (retval, i, i_array);\n\n        check_exception (jni_env);\n      }\n    catch (octave::index_exception& ie)\n      {\n        // Rethrow to allow more info to be reported later.\n        ie.set_pos_if_unset (idx.length (), i + 1);\n        throw;\n      }\n\n  return retval;\n}\n\nstatic octave_value\nget_array_elements (JNIEnv *jni_env, jobject jobj,\n                    const octave_value_list& idx)\n{\n  octave_value retval;\n  jobject_ref resObj (jni_env);\n  jobject_ref java_idx (jni_env, make_java_index (jni_env, idx));\n\n  jclass_ref helperClass (jni_env,\n                          find_octave_class (jni_env,\n                              \"org/octave/ClassHelper\"));\n  jmethodID mID = jni_env\n                  ->GetStaticMethodID (helperClass, \"arraySubsref\",\n                                       \"(Ljava/lang/Object;[[I)Ljava/lang/Object;\");\n  resObj = jni_env->CallStaticObjectMethod\n           (helperClass, mID, jobj, jobject (java_idx));\n\n  if (resObj)\n    retval = box (jni_env, resObj);\n  else\n    retval = check_exception (jni_env);\n\n  octave_set_default_fpucw ();\n\n  return retval;\n}\n\nstatic octave_value\nset_array_elements (JNIEnv *jni_env, jobject jobj,\n                    const octave_value_list& idx, const octave_value& rhs)\n{\n  octave_value retval;\n\n  jclass_ref rhsCls (jni_env);\n  jobject_ref resObj (jni_env);\n  jobject_ref rhsObj (jni_env);\n  jobject_ref java_idx (jni_env, make_java_index (jni_env, idx));\n\n  if (unbox (jni_env, rhs, rhsObj, rhsCls))\n    {\n      jclass_ref helperClass (jni_env,\n                              find_octave_class (jni_env,\n                                  \"org/octave/ClassHelper\"));\n      jmethodID mID = jni_env->GetStaticMethodID (helperClass, \"arraySubsasgn\",\n                      \"(Ljava/lang/Object;[[ILjava/lang/Object;)\" \"Ljava/lang/Object;\");\n      resObj = jni_env->CallStaticObjectMethod\n               (helperClass, mID, jobj, jobject (java_idx), jobject (rhsObj));\n    }\n\n  if (resObj)\n    retval = box (jni_env, resObj);\n  else\n    retval = check_exception (jni_env);\n\n  octave_set_default_fpucw ();\n\n  return retval;\n}\n\nstatic string_vector\nget_invoke_list (JNIEnv *jni_env, void *jobj_arg)\n{\n  jobject jobj = TO_JOBJECT (jobj_arg);\n\n  std::list<std::string> name_list;\n\n  if (jni_env)\n    {\n      jclass_ref cls (jni_env, jni_env->GetObjectClass (jobj));\n      jclass_ref ccls (jni_env, jni_env->GetObjectClass (cls));\n      jmethodID getMethods_ID = jni_env->GetMethodID\n                                (ccls, \"getMethods\", \"()[Ljava/lang/reflect/Method;\");\n      jmethodID getFields_ID = jni_env->GetMethodID\n                               (ccls, \"getFields\", \"()[Ljava/lang/reflect/Field;\");\n      jobjectArray_ref mList (jni_env,\n                              reinterpret_cast<jobjectArray>\n                              (jni_env->CallObjectMethod (cls, getMethods_ID)));\n      jobjectArray_ref fList (jni_env,\n                              reinterpret_cast<jobjectArray>\n                              (jni_env->CallObjectMethod (cls, getFields_ID)));\n      int mLen = jni_env->GetArrayLength (mList);\n      int fLen = jni_env->GetArrayLength (fList);\n      jclass_ref mCls (jni_env,\n                       jni_env->FindClass (\"java/lang/reflect/Method\"));\n      jclass_ref fCls (jni_env,\n                       jni_env->FindClass (\"java/lang/reflect/Field\"));\n      jmethodID m_getName_ID = jni_env->GetMethodID (mCls, \"getName\",\n                               \"()Ljava/lang/String;\");\n      jmethodID f_getName_ID = jni_env->GetMethodID (fCls, \"getName\",\n                               \"()Ljava/lang/String;\");\n\n      for (int i = 0; i < mLen; i++)\n        {\n          jobject_ref meth (jni_env, jni_env->GetObjectArrayElement (mList, i));\n          jstring_ref methName (jni_env, reinterpret_cast<jstring>\n                                (jni_env->CallObjectMethod (meth,\n                                    m_getName_ID)));\n          name_list.push_back (jstring_to_string (jni_env, methName));\n        }\n\n      for (int i = 0; i < fLen; i++)\n        {\n          jobject_ref field (jni_env,\n                             jni_env->GetObjectArrayElement (fList, i));\n          jstring_ref fieldName (jni_env,\n                                 reinterpret_cast<jstring>\n                                 (jni_env->CallObjectMethod\n                                  (field, f_getName_ID)));\n          name_list.push_back (jstring_to_string (jni_env, fieldName));\n        }\n\n      octave_set_default_fpucw ();\n    }\n\n  string_vector v (name_list);\n\n  return v.sort (true);\n}\n\nstatic octave_value\nconvert_to_string (JNIEnv *jni_env, jobject m_java_object, bool force,\n                   char type)\n{\n  octave_value retval;\n\n  if (jni_env && m_java_object)\n    {\n      jclass_ref cls (jni_env, jni_env->FindClass (\"java/lang/String\"));\n\n      if (jni_env->IsInstanceOf (m_java_object, cls))\n        retval = octave_value (jstring_to_string (jni_env, m_java_object),\n                               type);\n      else if (force)\n        {\n          cls = jni_env->FindClass (\"[Ljava/lang/String;\");\n\n          if (jni_env->IsInstanceOf (m_java_object, cls))\n            {\n              jobjectArray array = reinterpret_cast<jobjectArray> (m_java_object);\n              int len = jni_env->GetArrayLength (array);\n              Cell c (len, 1);\n\n              for (int i = 0; i < len; i++)\n                {\n                  jstring_ref js (jni_env,\n                                  reinterpret_cast<jstring>\n                                  (jni_env->GetObjectArrayElement (array, i)));\n\n                  if (js)\n                    c(i) = octave_value (jstring_to_string (jni_env, js), type);\n                  else\n                    c(i) = check_exception (jni_env);\n                }\n\n              retval = octave_value (c);\n            }\n          else\n            {\n              cls = jni_env->FindClass (\"java/lang/Object\");\n              jmethodID mID = jni_env->GetMethodID (cls, \"toString\",\n                                                    \"()Ljava/lang/String;\");\n              jstring_ref js (jni_env,\n                              reinterpret_cast<jstring>\n                              (jni_env->CallObjectMethod (m_java_object,\n                                  mID)));\n\n              if (js)\n                retval = octave_value (jstring_to_string (jni_env, js), type);\n              else\n                retval = check_exception (jni_env);\n            }\n        }\n      else\n        error (\"unable to convert Java object to string\");\n\n      octave_set_default_fpucw ();\n    }\n\n  return retval;\n}\n\n#define TO_JAVA(obj) dynamic_cast<octave_java *> ((obj).internal_rep ())\n\n//! Return whether @c jobj shall be automatically converted to an Octave\n//! numeric value.\n//!\n//! If @c jobj is an instance of any of the numeric wrapper classes @c Byte,\n//! @c Integer, @c Long, @c Short, @c Float, or @c Double, then it will be\n//! converted using the @c java.lang.Number.doubleValue() method.\n//!\n//! @param jni_env JNI environment pointer.\n//! @param jobj Java object being returned to Octave\n//! @return @c true if @c jobj shall be converted into a numeric value\n//!         automatically, @c false otherwise\nstatic bool\nis_auto_convertible_number (JNIEnv *jni_env, jobject jobj)\n{\n  jclass_ref cls (jni_env);\n  cls = jni_env->FindClass (\"java/lang/Double\");\n  if (jni_env->IsInstanceOf (jobj, cls))\n    return true;\n  cls = jni_env->FindClass (\"java/lang/Float\");\n  if (jni_env->IsInstanceOf (jobj, cls))\n    return true;\n  cls = jni_env->FindClass (\"java/lang/Byte\");\n  if (jni_env->IsInstanceOf (jobj, cls))\n    return true;\n  cls = jni_env->FindClass (\"java/lang/Short\");\n  if (jni_env->IsInstanceOf (jobj, cls))\n    return true;\n  cls = jni_env->FindClass (\"java/lang/Integer\");\n  if (jni_env->IsInstanceOf (jobj, cls))\n    return true;\n  cls = jni_env->FindClass (\"java/lang/Long\");\n  if (jni_env->IsInstanceOf (jobj, cls))\n    return true;\n\n  return false;\n}\n\n//! Convert the Java object pointed to by @c jobj_arg with class @c jcls_arg\n//! to an Octave value.\n//!\n//! @param jni_env JNI environment pointer.\n//! @param jobj_arg Pointer to a Java object.\n//! @param jcls_arg Optional pointer to the Java class of @c jobj_arg.\n//!\n//! @return\n//!   @arg numeric value as a @c double if @c jobj_arg is of type @c Byte,\n//!     @c Short, @c Integer, @c Long, @c Float or @c Double\n//!   @arg logical value if @c jobj_arg is of type @c Boolean\n//!   @arg string value if @c jobj_arg is of type @c Character or @c String\n//!   @arg Octave array of numeric, logical, or char type if @c jobj_arg is\n//!     a Java array of primitive types\n//!   @arg Octave matrix if @c jobj_arg is of type @c org.octave.Matrix and\n//!     #Vjava_matrix_autoconversion is enabled\n//!   @arg Octave object if @c jobj_arg is of type\n//!     @c org.octave.OctaveReference\n//!   @arg @c octave_java object wrapping the Java object otherwise.\n\nstatic octave_value\nbox (JNIEnv *jni_env, void *jobj_arg, void *jcls_arg)\n{\n  octave_value retval;\n\n  jobject jobj = TO_JOBJECT (jobj_arg);\n  jclass jcls = TO_JCLASS (jcls_arg);\n\n  jclass_ref cls (jni_env);\n\n  if (! jobj)\n    retval = Matrix ();\n\n  while (retval.is_undefined ())\n    {\n      // Convert a scalar of any numeric class wrapping a primitive class\n      // (byte, short, integer, long, float, double) to a double value.\n      // Test whether java.lang.Number before testing for each type.\n      cls = jni_env->FindClass (\"java/lang/Number\");\n      if (jni_env->IsInstanceOf (jobj, cls)\n          && is_auto_convertible_number (jni_env, jobj))\n        {\n          jmethodID m = jni_env->GetMethodID (cls, \"doubleValue\", \"()D\");\n          retval = jni_env->CallDoubleMethod (jobj, m);\n          break;\n        }\n\n      cls = jni_env->FindClass (\"java/lang/Boolean\");\n      if (jni_env->IsInstanceOf (jobj, cls))\n        {\n          jmethodID m = jni_env->GetMethodID (cls, \"booleanValue\", \"()Z\");\n          retval = (jni_env->CallBooleanMethod (jobj, m) ? true : false);\n          break;\n        }\n\n      cls = jni_env->FindClass (\"java/lang/String\");\n      if (jni_env->IsInstanceOf (jobj, cls))\n        {\n          retval = jstring_to_string (jni_env, jobj);\n          break;\n        }\n\n      cls = jni_env->FindClass (\"java/lang/Character\");\n      if (jni_env->IsInstanceOf (jobj, cls))\n        {\n          jmethodID m = jni_env->GetMethodID (cls, \"charValue\", \"()C\");\n          retval = jni_env->CallCharMethod (jobj, m);\n          retval = retval.convert_to_str (false, true);\n          break;\n        }\n\n#define BOX_PRIMITIVE_ARRAY(JAVA_TYPE, JAVA_ID, JAVA_TYPE_CAP, OCTAVE_ID) \\\n      cls = jni_env->FindClass (JAVA_ID); \\\n      if (jni_env->IsInstanceOf (jobj, cls)) \\\n        { \\\n          const JAVA_TYPE ## Array jarr = reinterpret_cast<JAVA_TYPE ## Array> (jobj); \\\n          const jsize len = jni_env->GetArrayLength (jarr); \\\n          OCTAVE_ID ## NDArray d (dim_vector (len, 1)); \\\n          JAVA_TYPE *buffer = reinterpret_cast<JAVA_TYPE *> (d.rwdata ()); \\\n          jni_env->Get ## JAVA_TYPE_CAP ## ArrayRegion (jarr, 0, len, buffer); \\\n          retval = d; \\\n          break; \\\n        }\n\n      BOX_PRIMITIVE_ARRAY (jdouble,  \"[D\", Double,  )\n      BOX_PRIMITIVE_ARRAY (jboolean, \"[Z\", Boolean, bool)\n      BOX_PRIMITIVE_ARRAY (jfloat,   \"[F\", Float,   Float)\n      BOX_PRIMITIVE_ARRAY (jchar,    \"[C\", Char,    char)\n      BOX_PRIMITIVE_ARRAY (jbyte,    \"[B\", Byte,    int8)\n      BOX_PRIMITIVE_ARRAY (jshort,   \"[S\", Short,   int16)\n      BOX_PRIMITIVE_ARRAY (jint,     \"[I\", Int,     int32)\n      BOX_PRIMITIVE_ARRAY (jlong,    \"[J\", Long,    int64)\n\n#undef BOX_PRIMITIVE_ARRAY\n\n      if (Vjava_matrix_autoconversion)\n        {\n          cls = find_octave_class (jni_env, \"org/octave/Matrix\");\n\n          if (jni_env->IsInstanceOf (jobj, cls))\n            {\n              jmethodID mID = jni_env->GetMethodID (cls, \"getDims\", \"()[I\");\n              jintArray_ref iv (jni_env,\n                                reinterpret_cast<jintArray>\n                                (jni_env->CallObjectMethod (jobj, mID)));\n              jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv),\n                              nullptr);\n              dim_vector dims;\n              dims.resize (jni_env->GetArrayLength (jintArray (iv)));\n\n              for (int i = 0; i < dims.ndims (); i++)\n                dims(i) = iv_data[i];\n\n              jni_env->ReleaseIntArrayElements (jintArray (iv), iv_data, 0);\n              mID = jni_env->GetMethodID (cls, \"getClassName\",\n                                          \"()Ljava/lang/String;\");\n              jstring_ref js (jni_env,\n                              reinterpret_cast<jstring>\n                              (jni_env->CallObjectMethod (jobj, mID)));\n\n              std::string s = jstring_to_string (jni_env, js);\n\n              if (s == \"double\")\n                {\n                  NDArray m (dims);\n                  mID = jni_env->GetMethodID (cls, \"toDouble\", \"()[D\");\n                  jdoubleArray_ref dv (jni_env,\n                                       reinterpret_cast<jdoubleArray>\n                                       (jni_env->CallObjectMethod (jobj,\n                                           mID)));\n                  jni_env->GetDoubleArrayRegion (dv, 0, m.numel (),\n                                                 m.rwdata ());\n                  retval = m;\n                  break;\n                }\n              else if (s == \"byte\")\n                {\n                  if (Vjava_unsigned_autoconversion)\n                    {\n                      uint8NDArray m (dims);\n                      mID = jni_env->GetMethodID (cls, \"toByte\", \"()[B\");\n                      jbyteArray_ref dv (jni_env,\n                                         reinterpret_cast<jbyteArray>\n                                         (jni_env->CallObjectMethod (jobj,\n                                             mID)));\n                      jni_env->GetByteArrayRegion (dv, 0, m.numel (),\n                                                   reinterpret_cast<jbyte *>\n                                                   (m.rwdata ()));\n                      retval = m;\n                      break;\n                    }\n                  else\n                    {\n                      int8NDArray m (dims);\n                      mID = jni_env->GetMethodID (cls, \"toByte\", \"()[B\");\n                      jbyteArray_ref dv (jni_env,\n                                         reinterpret_cast<jbyteArray>\n                                         (jni_env->CallObjectMethod (jobj,\n                                             mID)));\n                      jni_env->GetByteArrayRegion (dv, 0, m.numel (),\n                                                   reinterpret_cast<jbyte *>\n                                                   (m.rwdata ()));\n                      retval = m;\n                      break;\n                    }\n                }\n              else if (s == \"integer\")\n                {\n                  if (Vjava_unsigned_autoconversion)\n                    {\n                      uint32NDArray m (dims);\n                      mID = jni_env->GetMethodID (cls, \"toInt\", \"()[I\");\n                      jintArray_ref dv (jni_env,\n                                        reinterpret_cast<jintArray>\n                                        (jni_env->CallObjectMethod (jobj,\n                                            mID)));\n                      jni_env->GetIntArrayRegion (dv, 0, m.numel (),\n                                                  reinterpret_cast<jint *>\n                                                  (m.rwdata ()));\n                      retval = m;\n                      break;\n                    }\n                  else\n                    {\n                      int32NDArray m (dims);\n                      mID = jni_env->GetMethodID (cls, \"toInt\", \"()[I\");\n                      jintArray_ref dv (jni_env,\n                                        reinterpret_cast<jintArray>\n                                        (jni_env->CallObjectMethod (jobj,\n                                            mID)));\n                      jni_env->GetIntArrayRegion (dv, 0, m.numel (),\n                                                  reinterpret_cast<jint *>\n                                                  (m.rwdata ()));\n                      retval = m;\n                      break;\n                    }\n                }\n            }\n        }\n\n      cls = find_octave_class (jni_env, \"org/octave/OctaveReference\");\n      if (jni_env->IsInstanceOf (jobj, cls))\n        {\n          jmethodID mID = jni_env->GetMethodID (cls, \"getID\", \"()I\");\n          int ID = jni_env->CallIntMethod (jobj, mID);\n          auto it = octave_ref_map.find (ID);\n\n          if (it != octave_ref_map.end ())\n            retval = it->second;\n          break;\n        }\n\n      // No suitable class found.  Return a generic octave_java object.\n      retval = octave_value (new octave_java (jobj, jcls));\n      break;\n    }\n\n  return retval;\n}\n\nstatic octave_value\nbox_more (JNIEnv *jni_env, void *jobj_arg, void *jcls_arg)\n{\n  jobject jobj = TO_JOBJECT (jobj_arg);\n  jclass jcls = TO_JCLASS (jcls_arg);\n\n  octave_value retval = box (jni_env, jobj, jcls);\n\n  if (retval.isjava ())\n    {\n      retval = octave_value ();\n\n      jclass_ref cls (jni_env);\n\n      if (retval.is_undefined ())\n        {\n          cls = jni_env->FindClass (\"[D\");\n\n          if (jni_env->IsInstanceOf (jobj, cls))\n            {\n              jdoubleArray jarr = reinterpret_cast<jdoubleArray> (jobj);\n              int len = jni_env->GetArrayLength (jarr);\n\n              if (len > 0)\n                {\n                  Matrix m (1, len);\n                  jni_env->GetDoubleArrayRegion (jarr, 0, len,\n                                                 m.rwdata ());\n                  retval = m;\n                }\n              else\n                retval = Matrix ();\n            }\n        }\n\n      if (retval.is_undefined ())\n        {\n          cls = jni_env->FindClass (\"[[D\");\n\n          if (jni_env->IsInstanceOf (jobj, cls))\n            {\n              jobjectArray jarr = reinterpret_cast<jobjectArray> (jobj);\n              int rows = jni_env->GetArrayLength (jarr);\n              int cols = 0;\n\n              if (rows > 0)\n                {\n                  Matrix m;\n\n                  for (int r = 0; r < rows; r++)\n                    {\n                      jdoubleArray_ref row (jni_env,\n                                            reinterpret_cast<jdoubleArray>\n                                            (jni_env->GetObjectArrayElement\n                                             (jarr, r)));\n\n                      if (m.isempty ())\n                        {\n                          cols = jni_env->GetArrayLength (row);\n                          m.resize (cols, rows);\n                        }\n                      jni_env->GetDoubleArrayRegion\n                      (row, 0, cols, m.rwdata () + r * cols);\n                    }\n                  retval = m.transpose ();\n                }\n              else\n                retval = Matrix ();\n            }\n        }\n\n      if (retval.is_undefined ())\n        {\n          cls = jni_env->FindClass (\"[Ljava/lang/String;\");\n\n          if (jni_env->IsInstanceOf (jobj, cls))\n            {\n              jobjectArray jarr = reinterpret_cast<jobjectArray> (jobj);\n              int len = jni_env->GetArrayLength (jarr);\n              Cell m (len, 1);\n\n              for (int i = 0; i < len; i++)\n                {\n                  jstring_ref js (jni_env,\n                                  reinterpret_cast<jstring>\n                                  (jni_env->GetObjectArrayElement (jarr, i)));\n                  m(i) = jstring_to_string (jni_env, js);\n                }\n\n              retval = m;\n            }\n        }\n    }\n\n  if (retval.is_undefined ())\n    retval = octave_value (new octave_java (jobj, jcls));\n\n  octave_set_default_fpucw ();\n\n  return retval;\n}\n\nstatic bool\nunbox (JNIEnv *jni_env, const octave_value& val, jobject_ref& jobj,\n       jclass_ref& jcls)\n{\n  bool found = true;\n\n  if (val.isjava ())\n    {\n      octave_java *ovj = TO_JAVA (val);\n      jobj = TO_JOBJECT (ovj->to_java ());\n      jobj.detach ();\n      jcls = jni_env->GetObjectClass (jobj);\n    }\n  else if (val.is_string ())\n    {\n      std::string s = val.string_value ();\n\n      jobj = jni_env->NewStringUTF (s.c_str ());\n      jcls = jni_env->GetObjectClass (jobj);\n    }\n  else if (val.iscellstr ())\n    {\n      const Array<std::string> str_arr = val.cellstr_value ();\n      const octave_idx_type n = str_arr.numel ();\n\n      jclass_ref scls (jni_env, jni_env->FindClass (\"java/lang/String\"));\n      jobjectArray array = jni_env->NewObjectArray (n, scls, nullptr);\n\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          jstring_ref jstr (jni_env, jni_env->NewStringUTF\n                            (str_arr(i).c_str ()));\n          jni_env->SetObjectArrayElement (array, i, jstr);\n        }\n\n      jobj = array;\n      jcls = jni_env->GetObjectClass (jobj);\n    }\n  else if (val.numel () > 1 && val.dims ().isvector ())\n    {\n      // FIXME: Is there any way to avoid code duplication here without\n      // using a macro?\n\n#define UNBOX_PRIMITIVE_ARRAY(METHOD_T, OCTAVE_T, JAVA_T, JAVA_T_CAP) \\\n  do \\\n    { \\\n      const OCTAVE_T ## NDArray v = val.METHOD_T ## array_value (); \\\n      JAVA_T ## Array jarr = jni_env->New ## JAVA_T_CAP ## Array (v.numel ()); \\\n      const JAVA_T *jv = reinterpret_cast<const JAVA_T *> (v.data ()); \\\n      jni_env->Set ## JAVA_T_CAP ## ArrayRegion (jarr, 0, v.numel (), jv); \\\n      jobj = reinterpret_cast<jobject> (jarr); \\\n      jcls = jni_env->GetObjectClass (jobj); \\\n    } \\\n  while (0)\n\n      // Note that we do NOT handle char here because they are unboxed\n      // into a String[], not into a char array\n\n      if (val.is_double_type ())\n        UNBOX_PRIMITIVE_ARRAY (,, jdouble, Double);\n      else if (val.islogical ())\n        UNBOX_PRIMITIVE_ARRAY (bool_, bool, jboolean, Boolean);\n      else if (val.isfloat ())\n        UNBOX_PRIMITIVE_ARRAY (float_, Float, jfloat, Float);\n      else if (val.is_int8_type ())\n        UNBOX_PRIMITIVE_ARRAY (int8_, int8, jbyte, Byte);\n      else if (val.is_uint8_type ())\n        UNBOX_PRIMITIVE_ARRAY (uint8_, uint8, jbyte, Byte);\n      else if (val.is_int16_type ())\n        UNBOX_PRIMITIVE_ARRAY (int16_, int16, jshort, Short);\n      else if (val.is_uint16_type ())\n        UNBOX_PRIMITIVE_ARRAY (uint16_, uint16, jshort, Short);\n      else if (val.is_int32_type ())\n        UNBOX_PRIMITIVE_ARRAY (int32_, int32, jint, Int);\n      else if (val.is_uint32_type ())\n        UNBOX_PRIMITIVE_ARRAY (uint32_, uint32, jint, Int);\n      else if (val.is_int64_type ())\n        UNBOX_PRIMITIVE_ARRAY (int64_, int64, jlong, Long);\n      else if (val.is_uint64_type ())\n        UNBOX_PRIMITIVE_ARRAY (uint64_, uint64, jlong, Long);\n\n#undef UNBOX_PRIMITIVE_ARRAY\n    }\n  else if (val.is_real_scalar () || val.is_bool_scalar ())\n    {\n      // FIXME: Is there any way to avoid code duplication here without\n      // using a macro?\n\n#define UNBOX_PRIMITIVE_SCALAR(OCTAVE_T, METHOD_T, JAVA_T, JAVA_CON)    \\\n  do \\\n    { \\\n      const OCTAVE_T ov = val.METHOD_T ## _value (); \\\n      jclass_ref dcls (jni_env, jni_env->FindClass (JAVA_T)); \\\n      const jfieldID fid = jni_env->GetStaticFieldID (dcls, \"TYPE\", \"Ljava/lang/Class;\"); \\\n      const jmethodID mid = jni_env->GetMethodID (dcls, \"<init>\", JAVA_CON); \\\n      jcls = reinterpret_cast<jclass> (jni_env->GetStaticObjectField (dcls, fid)); \\\n      jobj = jni_env->NewObject (dcls, mid, ov); \\\n     } \\\n   while (0)\n\n      if (val.is_double_type ())\n        UNBOX_PRIMITIVE_SCALAR (double, double, \"java/lang/Double\", \"(D)V\");\n      else if (val.islogical ())\n        UNBOX_PRIMITIVE_SCALAR (bool, bool, \"java/lang/Boolean\", \"(Z)V\");\n      else if (val.isfloat ())\n        UNBOX_PRIMITIVE_SCALAR (float, float, \"java/lang/Float\", \"(F)V\");\n      else if (val.is_int8_type ())\n        UNBOX_PRIMITIVE_SCALAR (int8_t, int8_scalar, \"java/lang/Byte\", \"(B)V\");\n      else if (val.is_uint8_type ())\n        UNBOX_PRIMITIVE_SCALAR (uint8_t, uint8_scalar, \"java/lang/Byte\", \"(B)V\");\n      else if (val.is_int16_type ())\n        UNBOX_PRIMITIVE_SCALAR (int16_t, int16_scalar, \"java/lang/Short\", \"(S)V\");\n      else if (val.is_uint16_type ())\n        UNBOX_PRIMITIVE_SCALAR (uint16_t, uint16_scalar, \"java/lang/Short\", \"(S)V\");\n      else if (val.is_int32_type ())\n        UNBOX_PRIMITIVE_SCALAR (int32_t, int32_scalar, \"java/lang/Integer\", \"(I)V\");\n      else if (val.is_uint32_type ())\n        UNBOX_PRIMITIVE_SCALAR (uint32_t, uint32_scalar, \"java/lang/Integer\", \"(I)V\");\n      else if (val.is_int64_type ())\n        UNBOX_PRIMITIVE_SCALAR (int64_t, int64_scalar, \"java/lang/Long\", \"(J)V\");\n      else if (val.is_uint64_type ())\n        UNBOX_PRIMITIVE_SCALAR (uint64_t, uint64_scalar, \"java/lang/Long\", \"(J)V\");\n\n#undef UNBOX_PRIMITIVE_SCALAR\n    }\n  else if (val.isempty ())\n    {\n      jobj = nullptr;\n      jcls = nullptr;\n      //jcls = jni_env->FindClass (\"java/lang/Object\");\n    }\n  else if (! Vjava_matrix_autoconversion\n           && ((val.is_real_matrix ()\n                && (val.rows () == 1 || val.columns () == 1))\n               || val.is_range ()))\n    {\n      Matrix m = val.matrix_value ();\n      jdoubleArray dv = jni_env->NewDoubleArray (m.numel ());\n      jni_env->SetDoubleArrayRegion (dv, 0, m.numel (), m.rwdata ());\n      jobj = dv;\n      jcls = jni_env->GetObjectClass (jobj);\n    }\n  else if (Vjava_matrix_autoconversion\n           && (val.is_matrix_type () || val.is_range ())\n           && val.isreal ())\n    {\n      jclass_ref mcls (jni_env, find_octave_class (jni_env,\n                       \"org/octave/Matrix\"));\n      const dim_vector& dims = val.dims ();\n      jintArray_ref iv (jni_env, jni_env->NewIntArray (dims.ndims ()));\n      jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), nullptr);\n\n      for (int i = 0; i < dims.ndims (); i++)\n        iv_data[i] = dims(i);\n\n      jni_env->ReleaseIntArrayElements (jintArray (iv), iv_data, 0);\n\n      if (val.is_double_type ())\n        {\n          NDArray m = val.array_value ();\n          jdoubleArray_ref dv (jni_env, jni_env->NewDoubleArray (m.numel ()));\n          jni_env->SetDoubleArrayRegion (jdoubleArray (dv), 0, m.numel (),\n                                         m.rwdata ());\n          jmethodID mID = jni_env->GetMethodID (mcls, \"<init>\", \"([D[I)V\");\n          jobj = jni_env->NewObject (jclass (mcls), mID, jdoubleArray (dv),\n                                     jintArray (iv));\n          jcls = jni_env->GetObjectClass (jobj);\n        }\n      else if (val.is_int8_type ())\n        {\n          int8NDArray m = val.int8_array_value ();\n          jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.numel ()));\n          jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.numel (),\n                                       reinterpret_cast<jbyte *>\n                                       (m.rwdata ()));\n          jmethodID mID = jni_env->GetMethodID (mcls, \"<init>\", \"([B[I)V\");\n          jobj = jni_env->NewObject\n                 (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));\n          jcls = jni_env->GetObjectClass (jobj);\n        }\n      else if (val.is_uint8_type ())\n        {\n          uint8NDArray m = val.uint8_array_value ();\n          jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.numel ()));\n          jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.numel (),\n                                       reinterpret_cast<jbyte *>\n                                       (m.rwdata ()));\n          jmethodID mID = jni_env->GetMethodID (mcls, \"<init>\", \"([B[I)V\");\n          jobj = jni_env->NewObject\n                 (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));\n          jcls = jni_env->GetObjectClass (jobj);\n        }\n      else if (val.is_int32_type ())\n        {\n          int32NDArray m = val.int32_array_value ();\n          jintArray_ref v (jni_env, jni_env->NewIntArray (m.numel ()));\n          jni_env->SetIntArrayRegion (jintArray (v), 0, m.numel (),\n                                      reinterpret_cast<jint *>\n                                      (m.rwdata ()));\n          jmethodID mID = jni_env->GetMethodID (mcls, \"<init>\", \"([I[I)V\");\n          jobj = jni_env->NewObject\n                 (jclass (mcls), mID, jintArray (v), jintArray (iv));\n          jcls = jni_env->GetObjectClass (jobj);\n        }\n      else\n        {\n          error (\"cannot convert matrix of type '%s'\",\n                 val.class_name ().c_str ());\n        }\n    }\n  else\n    {\n      jclass rcls = find_octave_class (jni_env, \"org/octave/OctaveReference\");\n      jmethodID mID = jni_env->GetMethodID (rcls, \"<init>\", \"(I)V\");\n      int ID = octave_java_refcount++;\n\n      jobj = jni_env->NewObject (rcls, mID, ID);\n      jcls = rcls;\n      octave_ref_map[ID] = val;\n    }\n\n  return found;\n}\n\nstatic bool\nunbox (JNIEnv *jni_env, const octave_value_list& args,\n       jobjectArray_ref& jobjs, jobjectArray_ref& jclss)\n{\n  bool found = true;\n\n  jclass_ref ocls (jni_env, jni_env->FindClass (\"java/lang/Object\"));\n  jclass_ref ccls (jni_env, jni_env->FindClass (\"java/lang/Class\"));\n\n  if (! jobjs)\n    jobjs = jni_env->NewObjectArray (args.length (), ocls, nullptr);\n\n  if (! jclss)\n    jclss = jni_env->NewObjectArray (args.length (), ccls, nullptr);\n\n  for (int i = 0; i < args.length (); i++)\n    {\n      jobject_ref jobj (jni_env);\n      jclass_ref jcls (jni_env);\n\n      found = unbox (jni_env, args(i), jobj, jcls);\n      if (! found)\n        break;\n\n      jni_env->SetObjectArrayElement (jobjs, i, jobj);\n      jni_env->SetObjectArrayElement (jclss, i, jcls);\n    }\n\n  return found;\n}\n\n//! Returns the id of the current thread.\n//!\n//! @param jni_env The current environment or @c nullptr.\n//!\n//! @returns The id of the current thread or -1 otherwise.  The latter happens\n//!   if @c jni_env is @c nullptr, for example.\n\nstatic long\nget_current_thread_ID (JNIEnv *jni_env)\n{\n  if (jni_env)\n    {\n      // Call Java method static Thread java.lang.Thread.currentThread().\n      jclass_ref cls (jni_env, jni_env->FindClass (\"java/lang/Thread\"));\n      jmethodID mID = jni_env->GetStaticMethodID (cls, \"currentThread\",\n                      \"()Ljava/lang/Thread;\");\n      jobject_ref jthread (jni_env, jni_env->CallStaticObjectMethod (cls, mID));\n\n      if (jthread)\n        {\n          // Call Java method long java.lang.Thread.getId().\n          jclass_ref jth_cls (jni_env, jni_env->GetObjectClass (jthread));\n          mID = jni_env->GetMethodID (jth_cls, \"getId\", \"()J\");\n          long result = jni_env->CallLongMethod (jthread, mID);\n          return result;\n        }\n    }\n\n  return -1;\n}\n\n//! Run the java method @c org.octave.Octave.checkPendingAction().\n//!\n//! @returns 0 in any case for good reason.\n\nstatic int\njava_event_hook ()\n{\n  JNIEnv *current_env = thread_jni_env ();\n\n  if (current_env)\n    {\n      // Invoke static void org.octave.Octave.checkPendingAction().\n      jclass_ref cls (current_env, find_octave_class (current_env,\n                      \"org/octave/Octave\"));\n      jmethodID mID = current_env->GetStaticMethodID\n                      (cls, \"checkPendingAction\", \"()V\");\n      current_env->CallStaticVoidMethod (cls, mID);\n\n      octave_set_default_fpucw ();\n    }\n\n  return 0;\n}\n\n//! Initialize java including the virtual machine (jvm) if necessary.\n//!\n//! Initializes the fields #jvm, #jvm_attached, #jvm_lib, and\n//! #octave_thread_ID.  To ensure that java is initialized, this method is\n//! used as part of octave functions @c javaObject, @c javaMethod,\n//! @c __java_get__, @c __java_set__, and @c __java2mat__.\n\nstatic void\ninitialize_java ()\n{\n  if (! jvm)\n    {\n      try\n        {\n          initialize_jvm ();\n\n          JNIEnv *current_env = thread_jni_env ();\n\n          octave::command_editor::add_event_hook (java_event_hook);\n\n          octave_thread_ID = get_current_thread_ID (current_env);\n        }\n      catch (const std::string msg)\n        {\n          error (\"%s\", msg.c_str ());\n        }\n\n      octave_set_default_fpucw ();\n    }\n}\n\nJNIEXPORT jboolean JNICALL\nJava_org_octave_Octave_call (JNIEnv *env, jclass, jstring fcnName,\n                             jobjectArray argin, jobjectArray argout)\n{\n  std::string fname = jstring_to_string (env, fcnName);\n\n  int nargout = env->GetArrayLength (argout);\n  int nargin = env->GetArrayLength (argin);\n\n  octave_value_list varargin;\n\n  for (int i = 0; i < nargin; i++)\n    varargin(i) = box (env, env->GetObjectArrayElement (argin, i), nullptr);\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave_value_list varargout = interp.feval (fname, varargin, nargout);\n\n  jobjectArray_ref out_objs (env, argout), out_clss (env);\n  out_objs.detach ();\n  return unbox (env, varargout, out_objs, out_clss);\n}\n\nJNIEXPORT void JNICALL\nJava_org_octave_OctaveReference_doFinalize (JNIEnv *, jclass, jint ID)\n{\n  octave_ref_map.erase (ID);\n}\n\nJNIEXPORT void JNICALL\nJava_org_octave_Octave_doInvoke (JNIEnv *env, jclass, jint ID,\n                                 jobjectArray args)\n{\n  auto it = octave_ref_map.find (ID);\n\n  if (it != octave_ref_map.end ())\n    {\n      octave_value val = it->second;\n      int len = env->GetArrayLength (args);\n      octave_value_list oct_args;\n\n      for (int i = 0; i < len; i++)\n        {\n          jobject_ref jobj (env, env->GetObjectArrayElement (args, i));\n          oct_args(i) = box (env, jobj, nullptr);\n        }\n\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      if (val.is_function_handle ())\n        {\n          octave_function *fcn = val.function_value ();\n          interp.feval (fcn, oct_args);\n        }\n      else if (val.iscell () && val.length () > 0\n               && (val.rows () == 1 || val.columns () == 1)\n               && val.cell_value()(0).is_function_handle ())\n        {\n          Cell c = val.cell_value ();\n          octave_function *fcn = c(0).function_value ();\n\n          for (int i=1; i<c.numel (); i++)\n            oct_args(len+i-1) = c(i);\n\n          interp.feval (fcn, oct_args);\n        }\n      else\n        error (\"trying to invoke non-invocable object\");\n    }\n}\n\nJNIEXPORT void JNICALL\nJava_org_octave_Octave_doEvalString (JNIEnv *env, jclass, jstring cmd)\n{\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  std::string s = jstring_to_string (env, cmd);\n  int pstatus;\n  interp.eval_string (s, false, pstatus, 0);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_org_octave_Octave_needThreadedInvokation (JNIEnv *env, jclass)\n{\n  return (get_current_thread_ID (env) != octave_thread_ID);\n}\n\n#endif\n\n//! Ctor.\n\noctave_java::octave_java ()\n  : octave_base_value (), m_java_object (nullptr), m_java_class (nullptr)\n{\n#if ! defined (HAVE_JAVA)\n\n  err_disabled_feature (\"Java Objects\", \"Java\");\n\n#endif\n}\n\noctave_java::octave_java (const voidptr& jobj, void *jcls)\n  : octave_base_value (), m_java_object (nullptr), m_java_class (nullptr)\n{\n#if defined (HAVE_JAVA)\n\n  init (jobj, jcls);\n\n#else\n\n  octave_unused_parameter (jobj);\n  octave_unused_parameter (jcls);\n\n  err_disabled_feature (\"Java Objects\", \"Java\");\n\n#endif\n}\n\nint octave_java::s_t_id (-1);\n\nconst std::string octave_java::s_t_name (\"octave_java\");\n\nvoid\noctave_java::register_type (octave::type_info& ti)\n{\n#if defined (HAVE_JAVA)\n\n  s_t_id = ti.register_type (octave_java::s_t_name, \"<unknown>\",\n                             octave_value (new octave_java ()));\n\n#else\n\n  octave_unused_parameter (ti);\n\n#endif\n}\n\ndim_vector\noctave_java::dims () const\n{\n#if defined (HAVE_JAVA)\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  if (current_env && m_java_object)\n    return compute_array_dimensions (current_env, TO_JOBJECT (m_java_object));\n  else\n    return dim_vector (1, 1);\n\n#else\n\n  // This shouldn't happen because construction of octave_java objects is\n  // supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::dims\");\n\n#endif\n}\n\noctave_value_list\noctave_java::subsref (const std::string& type,\n                      const std::list<octave_value_list>& idx, int nargout)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value_list retval;\n  int skip = 1;\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  switch (type[0])\n    {\n    case '.':\n      if (type.length () > 1 && type[1] == '(')\n        {\n          octave_value_list ovl (2);\n          m_count++;\n          ovl(0) = (idx.front ())(0);\n          ovl(1) = octave_value (this);\n          auto it = idx.begin ();\n          ovl.append (*++it);\n          retval = octave::FjavaMethod (ovl, 1);\n          skip++;\n        }\n      else\n        {\n          octave_value_list ovl (2);\n          m_count++;\n          ovl(0) = octave_value (this);\n          ovl(1) = (idx.front ())(0);\n          retval = octave::F__java_get__ (ovl, 1);\n        }\n      break;\n\n    case '(':\n      if (current_env)\n        retval = get_array_elements\n                 (current_env, TO_JOBJECT (to_java ()), idx.front ());\n      break;\n\n    default:\n      error (\"subsref: Java object cannot be indexed with %c\", type[0]);\n      break;\n    }\n\n  if (idx.size () > 1 && type.length () > 1)\n    retval = retval(0).next_subsref (nargout, type, idx, skip);\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (type);\n  octave_unused_parameter (idx);\n  octave_unused_parameter (nargout);\n\n  // This shouldn't happen because construction of octave_java objects is\n  // supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::subsref\");\n\n#endif\n}\n\noctave_value\noctave_java::subsasgn (const std::string& type,\n                       const std::list<octave_value_list>& idx,\n                       const octave_value& rhs)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value retval;\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  switch (type[0])\n    {\n    case '.':\n      if (type.length () == 1)\n        {\n          // field assignment\n          octave_value_list ovl (3);\n          m_count++;\n          ovl(0) = octave_value (this);\n          ovl(1) = (idx.front ())(0);\n          ovl(2) = rhs;\n          octave::F__java_set__ (ovl);\n\n          m_count++;\n          retval = octave_value (this);\n        }\n      else if (type.length () > 2 && type[1] == '(')\n        {\n          std::list<octave_value_list> new_idx;\n          auto it = idx.begin ();\n          new_idx.push_back (*it++);\n          new_idx.push_back (*it++);\n          octave_value_list u = subsref (type.substr (0, 2), new_idx, 1);\n\n          std::list<octave_value_list> next_idx (std::next (idx.begin (), 2),\n                                                 idx.end ());\n          u(0).subsasgn (type.substr (2), next_idx, rhs);\n\n          m_count++;\n          retval = octave_value (this);\n        }\n      else if (type[1] == '.')\n        {\n          octave_value_list u = subsref (type.substr (0, 1), idx, 1);\n\n          std::list<octave_value_list> next_idx (std::next (idx.begin ()),\n                                                 idx.end ());\n          u(0).subsasgn (type.substr (1), next_idx, rhs);\n\n          m_count++;\n          retval = octave_value (this);\n        }\n      else\n        error (\"invalid indexing/assignment on Java object\");\n      break;\n\n    case '(':\n      if (current_env)\n        {\n          set_array_elements (current_env, TO_JOBJECT (to_java ()),\n                              idx.front (), rhs);\n\n          m_count++;\n          retval = octave_value (this);\n        }\n      break;\n\n    default:\n      error (\"Java object cannot be indexed with %c\", type[0]);\n      break;\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (type);\n  octave_unused_parameter (idx);\n  octave_unused_parameter (rhs);\n\n  // This shouldn't happen because construction of octave_java objects is\n  // supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::subsasgn\");\n\n#endif\n}\n\nstring_vector\noctave_java::map_keys () const\n{\n#if defined (HAVE_JAVA)\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  if (current_env)\n    return get_invoke_list (current_env, to_java ());\n  else\n    return string_vector ();\n\n#else\n\n  // This shouldn't happen because construction of octave_java objects is\n  // supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::map_keys\");\n\n#endif\n}\n\noctave_value\noctave_java::convert_to_str_internal (bool, bool force, char type) const\n{\n#if defined (HAVE_JAVA)\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  if (current_env)\n    return convert_to_string (current_env, TO_JOBJECT (to_java ()), force,\n                              type);\n  else\n    return octave_value (\"\");\n\n#else\n\n  octave_unused_parameter (force);\n  octave_unused_parameter (type);\n\n  // This shouldn't happen because construction of octave_java objects is\n  // supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::convert_to_str_internal\");\n\n#endif\n}\n\nvoid\noctave_java::print (std::ostream& os, bool)\n{\n  print_raw (os);\n  newline (os);\n}\n\nvoid\noctave_java::print_raw (std::ostream& os, bool) const\n{\n  os << \"<Java object: \" << m_java_classname << '>';\n}\n\n// FIXME: Need routines to actually save/load java objects through Serialize.\n//        See bug #42112.\n\nbool\noctave_java::save_ascii (std::ostream& /* os */)\n{\n  warning (\"save: unable to save java objects, skipping\");\n\n  return true;\n}\n\nbool\noctave_java::load_ascii (std::istream& /* is */)\n{\n  // Silently skip over java object that was not saved\n  return true;\n}\n\nbool\noctave_java::save_binary (std::ostream& /* os */, bool /* save_as_floats */)\n{\n  warning (\"save: unable to save java objects, skipping\");\n\n  return true;\n}\n\nbool\noctave_java::load_binary (std::istream& /* is */, bool /* swap*/,\n                          octave::mach_info::float_format /* fmt */)\n{\n  // Silently skip over java object that was not saved\n  return true;\n}\n\nbool\noctave_java::save_hdf5 (octave_hdf5_id /* loc_id */, const char * /* name */,\n                        bool /* save_as_floats */)\n{\n  warning (\"save: unable to save java objects, skipping\");\n\n  return true;\n}\n\nbool\noctave_java::load_hdf5 (octave_hdf5_id /* loc_id */, const char * /* name */)\n{\n  // Silently skip object that was not saved\n  return true;\n}\n\noctave_value\noctave_java::do_javaMethod (void *jni_env_arg, const std::string& name,\n                            const octave_value_list& args)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value retval;\n\n  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);\n\n  if (jni_env)\n    {\n      jobjectArray_ref arg_objs (jni_env), arg_types (jni_env);\n      if (unbox (jni_env, args, arg_objs, arg_types))\n        {\n          jclass_ref helperClass (jni_env, find_octave_class (jni_env, \"org/octave/ClassHelper\"));\n          jmethodID mID = jni_env->GetStaticMethodID (helperClass, \"invokeMethod\",\n                          \"(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;\");\n          jstring_ref methName (jni_env, jni_env->NewStringUTF (name.c_str ()));\n          jobjectArray_ref resObj (jni_env,\n                                   reinterpret_cast<jobjectArray> (jni_env->CallStaticObjectMethod (helperClass, mID,\n                                       to_java (), jstring (methName), jobjectArray (arg_objs), jobjectArray (arg_types))));\n          if (resObj)\n            retval = box (jni_env, resObj);\n          else\n            retval = check_exception (jni_env);\n        }\n\n      octave_set_default_fpucw ();\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (jni_env_arg);\n  octave_unused_parameter (name);\n  octave_unused_parameter (args);\n\n  // This shouldn't happen because construction of octave_java objects is\n  // supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_javaMethod\");\n\n#endif\n}\n\noctave_value\noctave_java::do_javaMethod (const std::string& name,\n                            const octave_value_list& args)\n{\n#if defined (HAVE_JAVA)\n\n  return do_javaMethod (thread_jni_env (), name, args);\n\n#else\n\n  octave_unused_parameter (name);\n  octave_unused_parameter (args);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_javaMethod\");\n\n#endif\n}\n\noctave_value\noctave_java::do_javaMethod (void *jni_env_arg,\n                            const std::string& class_name,\n                            const std::string& name,\n                            const octave_value_list& args)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value retval;\n\n  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);\n\n  if (jni_env)\n    {\n      jobjectArray_ref arg_objs (jni_env), arg_types (jni_env);\n      if (unbox (jni_env, args, arg_objs, arg_types))\n        {\n          jclass_ref helperClass (jni_env,\n                                  find_octave_class (jni_env,\n                                      \"org/octave/ClassHelper\"));\n          jmethodID mID = jni_env->GetStaticMethodID (helperClass,\n                          \"invokeStaticMethod\",\n                          \"(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;\");\n          jstring_ref methName (jni_env,\n                                jni_env->NewStringUTF (name.c_str ()));\n          jstring_ref clsName (jni_env,\n                               jni_env->NewStringUTF (class_name.c_str ()));\n          jobject_ref resObj (jni_env,\n                              jni_env->CallStaticObjectMethod (helperClass,\n                                  mID,\n                                  jstring (clsName),\n                                  jstring (methName),\n                                  jobjectArray (arg_objs),\n                                  jobjectArray (arg_types)));\n          if (resObj)\n            retval = box (jni_env, resObj);\n          else\n            retval = check_exception (jni_env);\n        }\n\n      octave_set_default_fpucw ();\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (jni_env_arg);\n  octave_unused_parameter (class_name);\n  octave_unused_parameter (name);\n  octave_unused_parameter (args);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_javaMethod\");\n\n#endif\n}\n\noctave_value\noctave_java::do_javaMethod (const std::string& class_name,\n                            const std::string& name,\n                            const octave_value_list& args)\n{\n#if defined (HAVE_JAVA)\n\n  return do_javaMethod (thread_jni_env (), class_name, name, args);\n\n#else\n\n  octave_unused_parameter (class_name);\n  octave_unused_parameter (name);\n  octave_unused_parameter (args);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_javaMethod\");\n\n#endif\n}\n\noctave_value\noctave_java::do_javaObject (void *jni_env_arg, const std::string& name,\n                            const octave_value_list& args)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value retval;\n\n  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);\n\n  if (jni_env)\n    {\n      jobjectArray_ref arg_objs (jni_env), arg_types (jni_env);\n\n      if (unbox (jni_env, args, arg_objs, arg_types))\n        {\n          jclass_ref helperClass (jni_env,\n                                  find_octave_class (jni_env,\n                                      \"org/octave/ClassHelper\"));\n          jmethodID mID = jni_env->GetStaticMethodID (helperClass,\n                          \"invokeConstructor\",\n                          \"(Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;\");\n          jstring_ref clsName (jni_env,\n                               jni_env->NewStringUTF (name.c_str ()));\n          jobject_ref resObj (jni_env,\n                              jni_env->CallStaticObjectMethod (helperClass,\n                                  mID,\n                                  jstring (clsName),\n                                  jobjectArray (arg_objs),\n                                  jobjectArray (arg_types)));\n\n          if (resObj)\n            retval = octave_value (new octave_java (resObj, nullptr));\n          else\n            check_exception (jni_env);\n        }\n\n      octave_set_default_fpucw ();\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (jni_env_arg);\n  octave_unused_parameter (name);\n  octave_unused_parameter (args);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_javaObject\");\n\n#endif\n}\n\noctave_value\noctave_java::do_javaObject (const std::string& name,\n                            const octave_value_list& args)\n{\n#if defined (HAVE_JAVA)\n\n  return do_javaObject (thread_jni_env (), name, args);\n\n#else\n\n  octave_unused_parameter (name);\n  octave_unused_parameter (args);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_javaObject\");\n\n#endif\n}\n\noctave_value\noctave_java::do_java_get (void *jni_env_arg, const std::string& name)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value retval;\n\n  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);\n\n  if (jni_env)\n    {\n      jclass_ref helperClass (jni_env,\n                              find_octave_class (jni_env,\n                                  \"org/octave/ClassHelper\"));\n      jmethodID mID = jni_env->GetStaticMethodID (helperClass, \"getField\",\n                      \"(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;\");\n      jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));\n      jobject_ref resObj (jni_env,\n                          jni_env->CallStaticObjectMethod (helperClass,\n                              mID,\n                              to_java (),\n                              jstring (fName)));\n\n      if (resObj)\n        retval = box (jni_env, resObj);\n      else\n        retval = check_exception (jni_env);\n\n      octave_set_default_fpucw ();\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (jni_env_arg);\n  octave_unused_parameter (name);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_java_get\");\n\n#endif\n}\n\noctave_value\noctave_java::do_java_get (const std::string& name)\n{\n#if defined (HAVE_JAVA)\n\n  return do_java_get (thread_jni_env (), name);\n\n#else\n\n  octave_unused_parameter (name);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_java_get\");\n\n#endif\n}\n\noctave_value\noctave_java::do_java_get (void *jni_env_arg, const std::string& class_name,\n                          const std::string& name)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value retval;\n\n  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);\n\n  if (jni_env)\n    {\n      jclass_ref helperClass (jni_env,\n                              find_octave_class (jni_env,\n                                  \"org/octave/ClassHelper\"));\n      jmethodID mID = jni_env->GetStaticMethodID (helperClass,\n                      \"getStaticField\",\n                      \"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;\");\n      jstring_ref cName (jni_env, jni_env->NewStringUTF (class_name.c_str ()));\n      jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));\n      jobject_ref resObj (jni_env,\n                          jni_env->CallStaticObjectMethod (helperClass, mID,\n                              jstring (cName),\n                              jstring (fName)));\n      if (resObj)\n        retval = box (jni_env, resObj);\n      else\n        retval = check_exception (jni_env);\n\n      octave_set_default_fpucw ();\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (jni_env_arg);\n  octave_unused_parameter (class_name);\n  octave_unused_parameter (name);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_java_get\");\n\n#endif\n}\n\noctave_value\noctave_java::do_java_get (const std::string& class_name,\n                          const std::string& name)\n{\n#if defined (HAVE_JAVA)\n\n  return do_java_get (thread_jni_env (), class_name, name);\n\n#else\n\n  octave_unused_parameter (class_name);\n  octave_unused_parameter (name);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_java_get\");\n\n#endif\n}\n\noctave_value\noctave_java::do_java_set (void *jni_env_arg, const std::string& name,\n                          const octave_value& val)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value retval;\n\n  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);\n\n  if (jni_env)\n    {\n      jobject_ref jobj (jni_env);\n      jclass_ref jcls (jni_env);\n\n      if (unbox (jni_env, val, jobj, jcls))\n        {\n          jclass_ref helperClass (jni_env,\n                                  find_octave_class (jni_env,\n                                      \"org/octave/ClassHelper\"));\n          jmethodID mID = jni_env->GetStaticMethodID (helperClass, \"setField\",\n                          \"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V\");\n          jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));\n          jni_env->CallStaticObjectMethod (helperClass, mID, to_java (),\n                                           jstring (fName), jobject (jobj));\n          check_exception (jni_env);\n        }\n\n      octave_set_default_fpucw ();\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (jni_env_arg);\n  octave_unused_parameter (name);\n  octave_unused_parameter (val);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_java_set\");\n\n#endif\n}\n\noctave_value\noctave_java::do_java_set (const std::string& name, const octave_value& val)\n{\n#if defined (HAVE_JAVA)\n\n  return do_java_set (thread_jni_env (), name, val);\n\n#else\n\n  octave_unused_parameter (name);\n  octave_unused_parameter (val);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_java_set\");\n\n#endif\n}\n\noctave_value\noctave_java::do_java_set (void *jni_env_arg, const std::string& class_name,\n                          const std::string& name, const octave_value& val)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value retval;\n\n  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);\n\n  if (jni_env)\n    {\n      jobject_ref jobj (jni_env);\n      jclass_ref jcls (jni_env);\n\n      if (unbox (jni_env, val, jobj, jcls))\n        {\n          jclass_ref helperClass (jni_env,\n                                  find_octave_class (jni_env,\n                                      \"org/octave/ClassHelper\"));\n          jmethodID mID = jni_env->GetStaticMethodID (helperClass,\n                          \"setStaticField\",\n                          \"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V\");\n          jstring_ref cName (jni_env,\n                             jni_env->NewStringUTF (class_name.c_str ()));\n          jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));\n          jni_env->CallStaticObjectMethod (helperClass, mID, jstring (cName),\n                                           jstring (fName), jobject (jobj));\n          check_exception (jni_env);\n        }\n\n      octave_set_default_fpucw ();\n    }\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (jni_env_arg);\n  octave_unused_parameter (class_name);\n  octave_unused_parameter (name);\n  octave_unused_parameter (val);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_java_set\");\n\n#endif\n}\n\noctave_value\noctave_java::do_java_set (const std::string& class_name,\n                          const std::string& name,\n                          const octave_value& val)\n{\n#if defined (HAVE_JAVA)\n\n  return do_java_set (thread_jni_env (), class_name, name, val);\n\n#else\n\n  octave_unused_parameter (class_name);\n  octave_unused_parameter (name);\n  octave_unused_parameter (val);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::do_java_set\");\n\n#endif\n}\n\nvoid\noctave_java::init (void *jobj_arg, void *jcls_arg)\n{\n#if defined (HAVE_JAVA)\n\n  jobject jobj = TO_JOBJECT (jobj_arg);\n  jclass jcls = TO_JCLASS (jcls_arg);\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  if (current_env)\n    {\n      if (jobj)\n        m_java_object = current_env->NewGlobalRef (jobj);\n\n      if (jcls)\n        m_java_class = current_env->NewGlobalRef (jcls);\n      else if (m_java_object)\n        {\n          jclass_ref ocls (current_env,\n                           current_env->GetObjectClass(TO_JOBJECT (m_java_object)));\n          m_java_class = current_env->NewGlobalRef (jclass (ocls));\n        }\n\n      if (m_java_class)\n        {\n          jclass_ref clsCls (current_env,\n                             current_env->GetObjectClass (TO_JCLASS (m_java_class)));\n          jmethodID mID = current_env->GetMethodID (clsCls,\n                          \"getCanonicalName\",\n                          \"()Ljava/lang/String;\");\n          jobject_ref resObj (current_env,\n                              current_env->CallObjectMethod (TO_JCLASS (m_java_class), mID));\n          m_java_classname = jstring_to_string (current_env, resObj);\n        }\n    }\n\n#else\n\n  octave_unused_parameter (jobj_arg);\n  octave_unused_parameter (jcls_arg);\n\n  // This shouldn't happen because construction of octave_java\n  // objects is supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::init\");\n\n#endif\n}\n\nvoid\noctave_java::release ()\n{\n#if defined (HAVE_JAVA)\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  if (current_env)\n    {\n      if (m_java_object)\n        current_env->DeleteGlobalRef (TO_JOBJECT (m_java_object));\n\n      if (m_java_class)\n        current_env->DeleteGlobalRef (TO_JCLASS (m_java_class));\n\n      m_java_object = nullptr;\n      m_java_class = nullptr;\n    }\n\n#else\n\n  // This shouldn't happen because construction of octave_java objects is\n  // supposed to be impossible if Java is not available.\n\n  error_unexpected (\"octave_java::release\");\n\n#endif\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// DEFUN blocks below must be outside of HAVE_JAVA block so that documentation\n// strings are always available, even when functions are not.\n\nDEFUN (__java_init__, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{status} =} __java_init__ ()\nInternal function used @strong{only} when debugging the Java interface.\n\nThis function will directly call @code{initialize_java} to create an instance\nof a JVM.\n\nThe return variable @var{status} is 1 if the Java interface has been created,\nand 0 otherwise.\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  octave_value retval = 0;\n\n  initialize_java ();\n\n  retval = 1;\n\n  return retval;\n\n#else\n\n  err_disabled_feature (\"__java_init__\", \"Java\");\n\n#endif\n}\n\nDEFUN (__java_exit__, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {} __java_exit__ ()\nInternal function used @strong{only} when debugging Java interface.\n\nFunction will directly call terminate_jvm to destroy the current JVM instance.\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  terminate_jvm ();\n\n  return ovl ();\n\n#else\n\n  err_disabled_feature (\"__java_exit__\", \"Java\");\n\n#endif\n}\n\nDEFUN (javaObject, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{jobj} =} javaObject (@var{classname})\n@deftypefnx {} {@var{jobj} =} javaObject (@var{classname}, @var{arg1}, @dots{})\nCreate a Java object of class @var{classsname}, by calling the class\nconstructor with the arguments @var{arg1}, @enddots{}\n\nThe first example below creates an uninitialized object, while the second\nexample supplies an initial argument to the constructor.\n\n@example\n@group\nx = javaObject (\"java.lang.StringBuffer\")\nx = javaObject (\"java.lang.StringBuffer\", \"Initial string\")\n@end group\n@end example\n\n@seealso{javaMethod, javaArray}\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  if (args.length () == 0)\n    print_usage ();\n\n  std::string classname = args(0).xstring_value (\"javaObject: CLASSNAME must be a string\");\n\n  initialize_java ();\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  octave_value_list tmp;\n  for (int i=1; i<args.length (); i++)\n    tmp(i-1) = args(i);\n\n  return ovl (octave_java::do_javaObject (current_env, classname, tmp));\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"javaObject\", \"Java\");\n\n#endif\n}\n\n/*\n## The tests below merely check if javaObject works at all.  Whether\n## it works properly, i.e., creates the right values, is a matter of\n## Java itself.  Create a Short and check if it really is a short, i.e.,\n## whether it overflows.\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! assert (javaObject (\"java.lang.Short\", 40000).doubleValue < 0);\n*/\n\nDEFUN (javaMethod, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{ret} =} javaMethod (@var{methodname}, @var{obj})\n@deftypefnx {} {@var{ret} =} javaMethod (@var{methodname}, @var{obj}, @var{arg1}, @dots{})\nInvoke the method @var{methodname} on the Java object @var{obj} with the\narguments @var{arg1}, @enddots{}\n\nFor static methods, @var{obj} can be a string representing the fully\nqualified name of the corresponding class.\n\nWhen @var{obj} is a regular Java object, structure-like indexing can be\nused as a shortcut syntax.  For instance, the two following statements are\nequivalent\n\n@example\n@group\n  ret = javaMethod (\"method1\", x, 1.0, \"a string\")\n  ret = x.method1 (1.0, \"a string\")\n@end group\n@end example\n\n@code{javaMethod} returns the result of the method invocation.\n\n@seealso{methods, javaObject}\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  if (args.length () < 2)\n    print_usage ();\n\n  std::string methodname = args(0).xstring_value (\"javaMethod: METHODNAME must be a string\");\n\n  initialize_java ();\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  octave_value retval;\n\n  octave_value_list tmp;\n  for (int i=2; i<args.length (); i++)\n    tmp(i-2) = args(i);\n\n  if (args(1).isjava ())\n    {\n      octave_java *jobj = TO_JAVA (args(1));\n      retval = jobj->do_javaMethod (current_env, methodname, tmp);\n    }\n  else if (args(1).is_string ())\n    {\n      std::string cls = args(1).string_value ();\n      retval = octave_java::do_javaMethod (current_env, cls, methodname, tmp);\n    }\n  else\n    error (\"javaMethod: OBJ must be a Java object or a string\");\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"javaMethod\", \"Java\");\n\n#endif\n}\n\n/*\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! jver = javaMethod (\"getProperty\", \"java.lang.System\", \"java.version\");\n%! jver = strsplit (jver, \".\");\n%! if (numel (jver) > 1)\n%!   assert (isfinite (str2double (jver{1})));\n%!   assert (isfinite (str2double (jver{2})));\n%! else\n%!   assert (isfinite (str2double (jver{1})));\n%! endif\n*/\n\nDEFUN (__java_get__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{val} =} __java_get__ (@var{obj}, @var{name})\nGet the value of the field @var{name} of the Java object @var{obj}.\n\nFor static fields, @var{obj} can be a string representing the fully\nqualified name of the corresponding class.\n\nWhen @var{obj} is a regular Java object, structure-like indexing can be used\nas a shortcut syntax.  For instance, the two following statements are\nequivalent\n\n@example\n@group\n  __java_get__ (x, \"field1\")\n  x.field1\n@end group\n@end example\n\n@seealso{__java_set__, javaMethod, javaObject}\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string name = args(1).xstring_value (\"__java_get__: NAME must be a string\");\n\n  initialize_java ();\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  octave_value retval;\n\n  if (args(0).isjava ())\n    {\n      octave_java *jobj = TO_JAVA (args(0));\n      retval = jobj->do_java_get (current_env, name);\n    }\n  else if (args(0).is_string ())\n    {\n      std::string cls = args(0).string_value ();\n      retval = octave_java::do_java_get (current_env, cls, name);\n    }\n  else\n    error (\"__java_get__: OBJ must be a Java object or a string\");\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__java_get__\", \"Java\");\n\n#endif\n}\n\nDEFUN (__java_set__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{obj} =} __java_set__ (@var{obj}, @var{name}, @var{val})\nSet the value of the field @var{name} of the Java object @var{obj} to\n@var{val}.\n\nFor static fields, @var{obj} can be a string representing the fully\nqualified named of the corresponding Java class.\n\nWhen @var{obj} is a regular Java object, structure-like indexing can be\nused as a shortcut syntax.  For instance, the two following statements are\nequivalent\n\n@example\n@group\n  __java_set__ (x, \"field1\", val)\n  x.field1 = val\n@end group\n@end example\n\n@seealso{__java_get__, javaMethod, javaObject}\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  if (args.length () != 3)\n    print_usage ();\n\n  std::string name = args(1).xstring_value (\"__java_set__: NAME must be a string\");\n\n  initialize_java ();\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  octave_value retval;\n\n  if (args(0).isjava ())\n    {\n      octave_java *jobj = TO_JAVA (args(0));\n      retval = jobj->do_java_set (current_env, name, args(2));\n    }\n  else if (args(0).is_string ())\n    {\n      std::string cls = args(0).string_value ();\n      retval = octave_java::do_java_set (current_env, cls, name, args(2));\n    }\n  else\n    error (\"__java_set__: OBJ must be a Java object or a string\");\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__java_set__\", \"Java\");\n\n#endif\n}\n\nDEFUN (__java2mat__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{mat} =} __java2mat__ (@var{javaobj})\nUndocumented internal function.\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  if (args.length () != 1)\n    print_usage ();\n\n  initialize_java ();\n\n  JNIEnv *current_env = thread_jni_env ();\n\n  octave_value_list retval;\n\n  if (args(0).isjava ())\n    {\n      octave_java *jobj = TO_JAVA (args(0));\n      retval = ovl (box_more (current_env, jobj->to_java (), nullptr));\n    }\n  else\n    retval = ovl (args(0));\n\n  return retval;\n\n#else\n\n  octave_unused_parameter (args);\n\n  err_disabled_feature (\"__java2mat__\", \"Java\");\n\n#endif\n}\n\nDEFUN (java_matrix_autoconversion, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} java_matrix_autoconversion ()\n@deftypefnx {} {@var{old_val} =} java_matrix_autoconversion (@var{new_val})\n@deftypefnx {} {@var{old_val} =} java_matrix_autoconversion (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether Java arrays are\nautomatically converted to Octave matrices.\n\nThe default value is false.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{java_unsigned_autoconversion, debug_java}\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  return set_internal_variable (Vjava_matrix_autoconversion, args, nargout,\n                                \"java_matrix_autoconversion\");\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"java_matrix_autoconversion\", \"Java\");\n\n#endif\n}\n\nDEFUN (java_unsigned_autoconversion, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} java_unsigned_autoconversion ()\n@deftypefnx {} {@var{old_val} =} java_unsigned_autoconversion (@var{new_val})\n@deftypefnx {} {@var{old_val} =} java_unsigned_autoconversion (@var{new_val}, \"local\")\nQuery or set the internal variable that controls how integer classes are\nconverted when @code{java_matrix_autoconversion} is enabled.\n\nWhen enabled, Java arrays of class Byte or Integer are converted to matrices\nof class uint8 or uint32 respectively.  The default value is true.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{java_matrix_autoconversion, debug_java}\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  return set_internal_variable (Vjava_unsigned_autoconversion, args, nargout,\n                                \"java_unsigned_autoconversion\");\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"java_unsigned_autoconversion\", \"Java\");\n\n#endif\n}\n\nDEFUN (debug_java, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} debug_java ()\n@deftypefnx {} {@var{old_val} =} debug_java (@var{new_val})\n@deftypefnx {} {@var{old_val} =} debug_java (@var{new_val}, \"local\")\nQuery or set the internal variable that determines whether extra debugging\ninformation regarding the initialization of the JVM and any Java exceptions\nis printed.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{java_matrix_autoconversion, java_unsigned_autoconversion}\n@end deftypefn */)\n{\n#if defined (HAVE_JAVA)\n\n  return set_internal_variable (Vdebug_java, args, nargout, \"debug_java\");\n\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  err_disabled_feature (\"debug_java\", \"Java\");\n\n#endif\n}\n\n// Outside of #if defined (HAVE_JAVA) because it is desirable to be able\n// to test for the presence of a Java object without having Java\n// installed.\n\nDEFUN (isjava, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isjava (@var{x})\nReturn true if @var{x} is a Java object.\n@seealso{class, typeinfo, isa, javaObject}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isjava ());\n}\n\n/*\n## Check automatic conversion of java primitive arrays into octave types.\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! assert (javaObject (\"java.lang.String\", \"hello\").getBytes (),\n%!         int8 ([104 101 108 108 111]'));\n\n## Check automatic conversion of octave types into java primitive arrays.\n## Note that uint8 is casted to int8.\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! assert (javaMethod (\"binarySearch\", \"java.util.Arrays\", [90 100 255], 255), 2);\n%! assert (javaMethod (\"binarySearch\", \"java.util.Arrays\", uint8 ([90 100 255]), uint8 (255)) < 0);\n%! assert (javaMethod (\"binarySearch\", \"java.util.Arrays\", uint8 ([90 100 128]), uint8 (128)) < 0);\n%! assert (javaMethod (\"binarySearch\", \"java.util.Arrays\", uint8 ([90 100 127]), uint8 (127)), 2);\n%! assert (javaMethod (\"binarySearch\", \"java.util.Arrays\", uint16 ([90 100 128]), uint16 (128)), 2);\n\n## Check we can create objects that wrap java literals\n%!testif HAVE_JAVA; usejava (\"jvm\") <*38821>\n%! assert (class (javaObject (\"java.lang.Byte\",     uint8 (1))),\n%!         \"java.lang.Byte\");\n%! assert (class (javaObject (\"java.lang.Byte\",      int8 (1))),\n%!         \"java.lang.Byte\");\n%! assert (class (javaObject (\"java.lang.Short\",   uint16 (1))),\n%!         \"java.lang.Short\");\n%! assert (class (javaObject (\"java.lang.Short\",    int16 (1))),\n%!         \"java.lang.Short\");\n%! assert (class (javaObject (\"java.lang.Integer\", uint32 (1))),\n%!         \"java.lang.Integer\");\n%! assert (class (javaObject (\"java.lang.Integer\",  int32 (1))),\n%!         \"java.lang.Integer\");\n%! assert (class (javaObject (\"java.lang.Long\",    uint64 (1))),\n%!         \"java.lang.Long\");\n%! assert (class (javaObject (\"java.lang.Long\",     int64 (1))),\n%!         \"java.lang.Long\");\n\n## More checks of java numeric and boolean class instances\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! n = javaObject (\"java.lang.Double\", 1.35);\n%! assert (n.compareTo (1.0), 1);\n%! assert (n.compareTo (1.35), 0);\n%! assert (n.compareTo (10), -1);\n%! assert (n.isInfinite (), false);\n\n%!testif HAVE_JAVA; usejava (\"jvm\") <51804>\n%! n = javaObject (\"java.lang.Float\", 1.35);\n%! assert (n.compareTo (1.0), 1);\n%! assert (n.compareTo (1.35), 0);\n%! assert (n.compareTo (10), -1);\n%! assert (n.doubleValue (), 1.35, 1e7);\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! n = javaObject (\"java.lang.Long\", (int64 (1)));\n%! assert (n.compareTo (int64 (0)), 1);\n%! assert (n.compareTo (int64 (1)), 0);\n%! assert (n.compareTo (int64 (2)), -1);\n%! assert (n.toString (), \"1\");\n\n%!testif HAVE_JAVA; usejava (\"jvm\") <51804>\n%! n = javaObject (\"java.lang.Integer\", 1.35);\n%! assert (n.compareTo (0), 1);\n%! assert (n.compareTo (1), 0);\n%! assert (n.compareTo (2), -1);\n\n%!testif HAVE_JAVA; usejava (\"jvm\") <51804>\n%! n = javaObject (\"java.lang.Short\", 1.35);\n%! assert (n.compareTo (0), 1);\n%! assert (n.compareTo (1), 0);\n%! assert (n.compareTo (2), -1);\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! n = javaObject (\"java.lang.Byte\", int8 (17));\n%! assert (n.compareTo (int8 (20)), -3);\n%! assert (n.compareTo (int8 (10)), 7);\n%! assert (n.compareTo (int8 (17)), 0);\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! b = javaObject (\"java.lang.Boolean\", true);\n%! assert (b.compareTo (true), 0);\n%! assert (b.compareTo (false), 1);\n%! b = javaObject (\"java.lang.Boolean\", false);\n%! assert (b.compareTo (true), -1);\n%! assert (b.compareTo (false), 0);\n\n## Test for automatic conversion of specific numeric classes\n%!testif HAVE_JAVA; usejava (\"jvm\") <*48013>\n%! assert (javaMethod (\"valueOf\", \"java.lang.Byte\",     int8 (1)), 1);\n%! assert (javaMethod (\"valueOf\", \"java.lang.Short\",   int16 (1)), 1);\n%! assert (javaMethod (\"valueOf\", \"java.lang.Integer\", int32 (1)), 1);\n%! assert (javaMethod (\"valueOf\", \"java.lang.Long\",    int64 (1)), 1);\n%! assert (javaMethod (\"valueOf\", \"java.lang.Float\",  single (1)), 1);\n%! assert (javaMethod (\"valueOf\", \"java.lang.Double\", double (1)), 1);\n%! assert (class (javaMethod (\"valueOf\", \"java.math.BigDecimal\", double (1))),\n%!         \"java.math.BigDecimal\")\n%! assert (class (javaMethod (\"valueOf\", \"java.math.BigInteger\",  int64 (1))),\n%!         \"java.math.BigInteger\")\n\n## Automatic conversion from string cell array into String[]\n%!testif HAVE_JAVA; usejava (\"jvm\") <*45290>\n%! assert (javaMethod (\"binarySearch\", \"java.util.Arrays\", {\"aaa\", \"bbb\", \"ccc\", \"zzz\"}, \"aaa\"), 0);\n%! assert (javaMethod (\"binarySearch\", \"java.util.Arrays\", {\"aaa\", \"bbb\", \"ccc\", \"zzz\"}, \"zzz\"), 3);\n%! assert (javaMethod (\"binarySearch\", \"java.util.Arrays\", {\"aaa\", \"bbb\", \"ccc\", \"zzz\"}, \"hhh\") < 0);\n\n## Test that Octave index syntax allows Java object method calls with args\n%!testif HAVE_JAVA; usejava (\"jvm\") <*51152>\n%! s = javaObject (\"java.lang.String\", \"Octave\");\n%! assert (s.length (), 6);\n%! assert (s.charAt (0), \"O\");\n%! assert (s.charAt (5), \"e\");\n%! assert (s.matches (\"^Octave$\"));\n%! assert (s.startsWith (\"Oct\"));\n%! ## same tests with Java object as part of another indexing expression\n%! a(1).s = s;\n%! assert (! a(1).s.isEmpty ());\n%! assert (a(1).s.length (), 6);\n%! assert (a(1).s.charAt (0), \"O\");\n%! assert (a(1).s.charAt (5), \"e\");\n%! assert (a(1).s.matches (\"^Octave$\"));\n%! assert (a(1).s.startsWith (\"Oct\"));\n\n## Check for basic usability of the java awt library\n## FIXME: Removed runtime test to skip checking on Mac OS (22/08/2025).\n## IF problems are reported the \"! ismac ()\" runtime test can be re-instated.\n%!testif HAVE_JAVA; usejava (\"jvm\") && usejava (\"awt\") && have_window_system ()\n%! frame = javaObject (\"java.awt.Frame\");\n%! frame.setResizable (true);\n%! assert (frame.isResizable ());\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-java.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_java_h)\n#define octave_ov_java_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov.h\"\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass type_info;\n\nOCTAVE_END_NAMESPACE(octave)\n\ntypedef void *voidptr;\n\nclass OCTINTERP_API octave_java : public octave_base_value\n{\npublic:\n\n  octave_java ();\n\n  octave_java (const voidptr& obj, void *cls = nullptr);\n\n  octave_java (const octave_java& jobj)\n    : octave_base_value (jobj), m_java_object (nullptr), m_java_class (nullptr)\n  {\n    init (jobj.m_java_object, jobj.m_java_class);\n  }\n\n  ~octave_java () { release (); }\n\n  void * to_java () const { return m_java_object; }\n  void * to_class () const { return m_java_class; }\n\n  std::string java_class_name () const { return m_java_classname; }\n\n  octave_base_value * clone () const { return new octave_java (*this); }\n  octave_base_value * empty_clone () const { return new octave_java (); }\n\n  bool is_instance_of (const std::string&) const;\n\n  bool is_defined () const { return true; }\n\n  bool is_constant () const { return true; }\n\n  bool isstruct () const { return false; }\n\n  bool isjava () const { return true; }\n\n  string_vector map_keys () const;\n\n  dim_vector dims () const;\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                  bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  octave_value_list\n  subsref (const std::string& type,\n           const std::list<octave_value_list>& idx, int nargout);\n\n  octave_value\n  subsref (const std::string& type, const std::list<octave_value_list>& idx)\n  {\n    octave_value_list retval = subsref (type, idx, 1);\n    return (retval.length () > 0 ? retval(0) : octave_value ());\n  }\n\n  octave_value subsasgn (const std::string& type,\n                         const std::list<octave_value_list>& idx,\n                         const octave_value& rhs);\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  bool is_java_string () const;\n\n  octave_value do_javaMethod (void *jni_env, const std::string& name,\n                              const octave_value_list& args);\n\n  octave_value\n  do_javaMethod (const std::string& name, const octave_value_list& args);\n\n  static octave_value\n  do_javaMethod (void *jni_env, const std::string& class_name,\n                 const std::string& name, const octave_value_list& args);\n\n  static octave_value\n  do_javaMethod (const std::string& class_name, const std::string& name,\n                 const octave_value_list& args);\n\n  static octave_value\n  do_javaObject (void *jni_env, const std::string& name,\n                 const octave_value_list& args);\n\n  static octave_value\n  do_javaObject (const std::string& name, const octave_value_list& args);\n\n  octave_value do_java_get (void *jni_env, const std::string& name);\n\n  octave_value do_java_get (const std::string& name);\n\n  static octave_value\n  do_java_get (void *jni_env, const std::string& class_name,\n               const std::string& name);\n\n  static octave_value\n  do_java_get (const std::string& class_name, const std::string& name);\n\n  octave_value do_java_set (void *jni_env, const std::string& name,\n                            const octave_value& val);\n\n  octave_value do_java_set (const std::string& name, const octave_value& val);\n\n  static octave_value\n  do_java_set (void *jni_env, const std::string& class_name,\n               const std::string& name, const octave_value& val);\n\n  static octave_value\n  do_java_set (const std::string& class_name, const std::string& name,\n               const octave_value& val);\n\nprivate:\n\n  void init (void *jobj, void *jcls);\n\n  void release ();\n\nprivate:\n\n  void *m_java_object;\n\n  void *m_java_class;\n\n  std::string m_java_classname;\n\npublic:\n\n  int type_id () const { return s_t_id; }\n  std::string type_name () const { return s_t_name; }\n  std::string class_name () const { return m_java_classname; }\n\n  static int static_type_id () { return s_t_id; }\n  static std::string static_type_name () { return s_t_name; }\n  static std::string static_class_name () { return \"<unknown>\"; }\n  static void register_type (octave::type_info&);\n\nprivate:\n\n  static int s_t_id;\n  static const std::string s_t_name;\n};\n\nextern OCTINTERP_API bool Vjava_matrix_autoconversion;\n\nextern OCTINTERP_API bool Vjava_unsigned_autoconversion;\n\nextern OCTINTERP_API bool Vdebug_java;\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-lazy-idx.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ov-lazy-idx.h\"\n#include \"ops.h\"\n#include \"ov-scalar.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-oct-binary.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_lazy_index, \"lazy_index\", \"double\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_lazy_index& v = dynamic_cast<const octave_lazy_index&> (a);\n\n  return v.full_value ().clone ();\n}\n\noctave_base_value::type_conv_info\noctave_lazy_index::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n         octave_matrix::static_type_id ());\n}\n\noctave_base_value *\noctave_lazy_index::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  switch (m_index.length (0))\n    {\n    case 1:\n      retval = new octave_scalar (static_cast<double> (m_index(0) + 1));\n      break;\n\n    case 0:\n      retval = new octave_matrix (NDArray (m_index.orig_dimensions ()));\n      break;\n\n    default:\n      break;\n    }\n\n  return retval;\n}\n\noctave_value\noctave_lazy_index::fast_elem_extract (octave_idx_type n) const\n{\n  return double (m_index.checkelem (n) + 1);\n}\n\noctave_value\noctave_lazy_index::reshape (const dim_vector& new_dims) const\n{\n  return octave::idx_vector (m_index.as_array ().reshape (new_dims),\n                             m_index.extent (0));\n}\n\noctave_value\noctave_lazy_index::permute (const Array<int>& vec, bool inv) const\n{\n  // If the conversion has already been made, forward the operation.\n  if (m_value.is_defined ())\n    return m_value.permute (vec, inv);\n  else\n    return octave::idx_vector (m_index.as_array ().permute (vec, inv),\n                               m_index.extent (0));\n}\n\noctave_value\noctave_lazy_index::squeeze () const\n{\n  return octave::idx_vector (m_index.as_array ().squeeze (),\n                             m_index.extent (0));\n}\n\noctave_value\noctave_lazy_index::sort (octave_idx_type dim, sortmode mode) const\n{\n  const dim_vector odims = m_index.orig_dimensions ();\n  // index_vector can employ a more efficient sorting algorithm.\n  if (mode == ASCENDING && odims.ndims () == 2\n      && (dim >= 0 && dim <= 1) && odims(1-dim) == 1)\n    return index_vector ().sorted ();\n  else\n    return octave::idx_vector (m_index.as_array ().sort (dim, mode),\n                               m_index.extent (0));\n}\n\noctave_value\noctave_lazy_index::sort (Array<octave_idx_type>& sidx, octave_idx_type dim,\n                         sortmode mode) const\n{\n  const dim_vector odims = m_index.orig_dimensions ();\n  // index_vector can employ a more efficient sorting algorithm.\n  if (mode == ASCENDING && odims.ndims () == 2\n      && (dim >= 0 && dim <= 1) && odims(1-dim) == 1)\n    return index_vector ().sorted (sidx);\n  else\n    return octave::idx_vector (m_index.as_array ().sort (sidx, dim, mode),\n                               m_index.extent (0));\n}\n\nsortmode\noctave_lazy_index::issorted (sortmode mode) const\n{\n  if (m_index.is_range ())\n    {\n      // Avoid the array conversion.\n      octave_idx_type inc = m_index.increment ();\n      if (inc == 0)\n        return (mode == UNSORTED ? ASCENDING : mode);\n      else if (inc > 0)\n        return (mode == DESCENDING ? UNSORTED : ASCENDING);\n      else\n        return (mode == ASCENDING ? UNSORTED : DESCENDING);\n    }\n  else\n    return m_index.as_array ().issorted (mode);\n}\n\nArray<octave_idx_type>\noctave_lazy_index::sort_rows_idx (sortmode mode) const\n{\n  return m_index.as_array ().sort_rows_idx (mode);\n}\n\nsortmode\noctave_lazy_index::is_sorted_rows (sortmode mode) const\n{\n  return m_index.as_array ().is_sorted_rows (mode);\n}\n\noctave_value\noctave_lazy_index::as_double () const\n{\n  return array_value ();\n}\n\noctave_value\noctave_lazy_index::as_single () const\n{\n  return float_array_value ();\n}\n\noctave_value\noctave_lazy_index::as_int8 () const\n{\n  return int8_array_value  ();\n}\n\noctave_value\noctave_lazy_index::as_int16 () const\n{\n  return int16_array_value ();\n}\n\noctave_value\noctave_lazy_index::as_int32 () const\n{\n  return int32_array_value ();\n}\n\noctave_value\noctave_lazy_index::as_int64 () const\n{\n  return int64_array_value ();\n}\n\noctave_value\noctave_lazy_index::as_uint8 () const\n{\n  return uint8_array_value ();\n}\n\noctave_value\noctave_lazy_index::as_uint16 () const\n{\n  return uint16_array_value ();\n}\n\noctave_value\noctave_lazy_index::as_uint32 () const\n{\n  return uint32_array_value ();\n}\n\noctave_value\noctave_lazy_index::as_uint64 () const\n{\n  return uint64_array_value ();\n}\n\nstatic const std::string value_save_tag (\"index_value\");\n\nbool\noctave_lazy_index::save_ascii (std::ostream& os)\n{\n  return save_text_data (os, make_value (), value_save_tag, false, 0);\n}\n\nbool\noctave_lazy_index::load_ascii (std::istream& is)\n{\n  bool dummy;\n\n  std::string nm = read_text_data (is, \"\", dummy, m_value, 0);\n  if (nm != value_save_tag)\n    error (\"lazy_index: corrupted data on load\");\n\n  m_index = m_value.index_vector ();\n\n  return true;\n}\n\nbool\noctave_lazy_index::save_binary (std::ostream& os, bool save_as_floats)\n{\n  return save_binary_data (os, make_value (), value_save_tag,\n                           \"\", false, save_as_floats);\n}\n\nbool\noctave_lazy_index::load_binary (std::istream& is, bool swap,\n                                octave::mach_info::float_format fmt)\n{\n  bool dummy;\n  std::string doc;\n\n  std::string nm = read_binary_data (is, swap, fmt, \"\", dummy, m_value, doc);\n  if (nm != value_save_tag)\n    error (\"lazy_index: corrupted data on load\");\n\n  m_index = m_value.index_vector ();\n\n  return true;\n}\n\n/*\n%!shared x, y\n%! x = find ([-1, 0, -2, 1, 3, -4] < 0);\n%! y = [1, 3, 6];\n%!assert (typeinfo (x), \"lazy_index\")\n%!assert (double (x), y)\n%!assert (single (x), single (y))\n%!assert (int8 (x), int8 (y))\n%!assert (int16 (x), int16 (y))\n%!assert (int32 (x), int32 (y))\n%!assert (int64 (x), int64 (y))\n%!assert (uint8 (x), uint8 (y))\n%!assert (uint16 (x), uint16 (y))\n%!assert (uint32 (x), uint32 (y))\n%!assert (uint64 (x), uint64 (y))\n*/\n"
  },
  {
    "path": "libinterp/octave-value/ov-lazy-idx.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_lazy_idx_h)\n#define octave_ov_lazy_idx_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov-re-mat.h\"\n\n// Lazy indices that stay in idx_vector form until the conversion to NDArray is\n// actually needed.\n\nclass OCTINTERP_API octave_lazy_index : public octave_base_value\n{\npublic:\n\n  octave_lazy_index ()\n    : octave_base_value (), m_index (), m_value () { }\n\n  octave_lazy_index (const octave::idx_vector& idx)\n    : octave_base_value (), m_index (idx), m_value () { }\n\n  octave_lazy_index (const octave_lazy_index& i)\n    : octave_base_value (), m_index (i.m_index), m_value (i.m_value) { }\n\n  ~octave_lazy_index () = default;\n\n  octave_base_value * clone () const\n  { return new octave_lazy_index (*this); }\n  octave_base_value * empty_clone () const { return new octave_matrix (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  octave_value fast_elem_extract (octave_idx_type n) const;\n\n  std::size_t byte_size () const\n  { return numel () * sizeof (octave_idx_type); }\n\n  octave_value squeeze () const;\n\n  octave_value full_value () const { return make_value (); }\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  { return m_index; }\n\n  builtin_type_t builtin_type () const { return btyp_double; }\n\n  bool is_real_matrix () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx)\n  { return make_value ().subsref (type, idx); }\n\n  octave_value_list subsref (const std::string& type,\n                             const std::list<octave_value_list>& idx, int)\n  { return subsref (type, idx); }\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false)\n  { return make_value ().index_op (idx, resize_ok); }\n\n  dim_vector dims () const { return m_index.orig_dimensions (); }\n\n  octave_idx_type numel () const { return m_index.length (0); }\n\n  octave_idx_type nnz () const { return numel (); }\n\n  octave_value reshape (const dim_vector& new_dims) const;\n\n  octave_value permute (const Array<int>& vec, bool inv = false) const;\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const\n  { return make_value ().resize (dv, fill); }\n\n  octave_value all (int dim = 0) const { return make_value ().all (dim); }\n  octave_value any (int dim = 0) const { return make_value ().any (dim); }\n\n  MatrixType matrix_type () const { return make_value ().matrix_type (); }\n  MatrixType matrix_type (const MatrixType& _typ) const\n  { return make_value ().matrix_type (_typ); }\n\n  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;\n\n  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n                     sortmode mode = ASCENDING) const;\n\n  sortmode issorted (sortmode mode = UNSORTED) const;\n\n  Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const;\n\n  sortmode is_sorted_rows (sortmode mode = UNSORTED) const;\n\n  bool is_matrix_type () const { return true; }\n\n  bool isnumeric () const { return true; }\n\n  bool is_defined () const { return true; }\n\n  bool is_constant () const { return true; }\n\n  bool is_true () const\n  { return make_value ().is_true (); }\n\n  bool print_as_scalar () const\n  { return make_value ().print_as_scalar (); }\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false)\n  { make_value ().print (os, pr_as_read_syntax); }\n\n  std::string edit_display (const float_display_format& fmt,\n                            octave_idx_type i, octave_idx_type j) const\n  { return make_value ().edit_display (fmt, i, j); }\n\n  void print_info (std::ostream& os, const std::string& prefix) const\n  { make_value ().print_info (os, prefix); }\n\n#define FORWARD_VALUE_QUERY(TYPE, NAME)         \\\n  TYPE NAME () const                        \\\n  {                                             \\\n    return make_value ().NAME ();               \\\n  }\n\n  FORWARD_VALUE_QUERY (int8NDArray,  int8_array_value)\n  FORWARD_VALUE_QUERY (int16NDArray, int16_array_value)\n  FORWARD_VALUE_QUERY (int32NDArray, int32_array_value)\n  FORWARD_VALUE_QUERY (int64NDArray, int64_array_value)\n  FORWARD_VALUE_QUERY (uint8NDArray,  uint8_array_value)\n  FORWARD_VALUE_QUERY (uint16NDArray, uint16_array_value)\n  FORWARD_VALUE_QUERY (uint32NDArray, uint32_array_value)\n  FORWARD_VALUE_QUERY (uint64NDArray, uint64_array_value)\n\n#define FORWARD_VALUE_QUERY1(TYPE, NAME)        \\\n  TYPE NAME (bool flag = false) const           \\\n  {                                             \\\n    return make_value ().NAME (flag);           \\\n  }\n\n  FORWARD_VALUE_QUERY1 (double, double_value)\n  FORWARD_VALUE_QUERY1 (float, float_value)\n  FORWARD_VALUE_QUERY1 (double, scalar_value)\n  FORWARD_VALUE_QUERY1 (Matrix, matrix_value)\n  FORWARD_VALUE_QUERY1 (FloatMatrix, float_matrix_value)\n  FORWARD_VALUE_QUERY1 (Complex, complex_value)\n  FORWARD_VALUE_QUERY1 (FloatComplex, float_complex_value)\n  FORWARD_VALUE_QUERY1 (ComplexMatrix, complex_matrix_value)\n  FORWARD_VALUE_QUERY1 (FloatComplexMatrix, float_complex_matrix_value)\n  FORWARD_VALUE_QUERY1 (ComplexNDArray, complex_array_value)\n  FORWARD_VALUE_QUERY1 (FloatComplexNDArray, float_complex_array_value)\n  FORWARD_VALUE_QUERY1 (boolNDArray, bool_array_value)\n  FORWARD_VALUE_QUERY1 (charNDArray, char_array_value)\n  FORWARD_VALUE_QUERY1 (NDArray, array_value)\n  FORWARD_VALUE_QUERY1 (FloatNDArray, float_array_value)\n  FORWARD_VALUE_QUERY1 (SparseMatrix, sparse_matrix_value)\n  FORWARD_VALUE_QUERY1 (SparseComplexMatrix, sparse_complex_matrix_value)\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::diag;\n\n  octave_value diag (octave_idx_type k = 0) const\n  {\n    return make_value ().diag (k);\n  }\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const\n  {\n    return make_value ().convert_to_str_internal (pad, force, type);\n  }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const\n  {\n    return make_value ().print_raw (os, pr_as_read_syntax);\n  }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    return make_value ().write (os, block_size, output_type, skip, flt_fmt);\n  }\n\n  // This function exists to support the MEX interface.\n  // You should not use it anywhere else.\n  const void * mex_get_data () const\n  {\n    return make_value ().mex_get_data ();\n  }\n\n  mxArray * as_mxArray (bool interleaved) const\n  {\n    return make_value ().as_mxArray (interleaved);\n  }\n\n  octave_value map (unary_mapper_t umap) const\n  {\n    return make_value ().map (umap);\n  }\n\nprivate:\n\n  const octave_value& make_value () const\n  {\n    if (m_value.is_undefined ())\n      m_value = octave_value (m_index, false);\n\n    return m_value;\n  }\n\n  octave_value& make_value ()\n  {\n    if (m_value.is_undefined ())\n      m_value = octave_value (m_index, false);\n\n    return m_value;\n  }\n\n  octave::idx_vector m_index;\n  mutable octave_value m_value;\n\n  static octave_base_value *\n  numeric_conversion_function (const octave_base_value&);\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-legacy-range.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n\n#include \"Range.h\"\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n\n#include \"variables.h\"\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"ov-legacy-range.h\"\n#include \"ov-range.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"pr-output.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-ascii-helper.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-utils.h\"\n\nclass Range\n{\npublic:\n\n  Range ()\n    : m_base (0), m_limit (0), m_inc (0), m_numel (0)\n  { }\n\n  // Assume range is already properly constructed, so just copy internal\n  // values.  However, we set LIMIT to the computed final value because\n  // that mimics the behavior of the other Range class constructors that\n  // reset limit to the computed final value.\n\n  Range (const octave::range<double>& r)\n    : m_base (r.base ()), m_limit (r.final_value ()), m_inc (r.increment ()),\n      m_numel (r.numel ())\n  { }\n\n  Range (const Range& r) = default;\n\n  Range& operator = (const Range& r) = default;\n\n  ~Range () = default;\n\n  Range (double b, double l)\n    : m_base (b), m_limit (l), m_inc (1), m_numel (numel_internal ())\n  {\n    if (! octave::math::isinf (m_limit))\n      m_limit = limit_internal ();\n  }\n\n  Range (double b, double l, double i)\n    : m_base (b), m_limit (l), m_inc (i), m_numel (numel_internal ())\n  {\n    if (! octave::math::isinf (m_limit))\n      m_limit = limit_internal ();\n  }\n\n  // The range has a finite number of elements.\n  bool ok () const\n  {\n    return (octave::math::isfinite (m_limit)\n            && (m_numel >= 0 || m_numel == -2));\n  }\n\n  double base () const { return m_base; }\n  double limit () const { return m_limit; }\n  double increment () const { return m_inc; }\n\n  octave_idx_type numel () const { return m_numel; }\n\n  bool all_elements_are_ints () const;\n\n  Matrix matrix_value () const;\n\n  double min () const;\n  double max () const;\n\nprivate:\n\n  double m_base;\n  double m_limit;\n  double m_inc;\n\n  octave_idx_type m_numel;\n\n  octave_idx_type numel_internal () const;\n\n  double limit_internal () const;\n\n  void init ();\n};\n\nbool\nRange::all_elements_are_ints () const\n{\n  // If the base and increment are ints, the final value in the range will also\n  // be an integer, even if the limit is not.  If there is one or fewer\n  // elements only the base needs to be an integer.\n\n  return (! (octave::math::isnan (m_base) || octave::math::isnan (m_inc))\n          && (octave::math::nint_big (m_base) == m_base || m_numel < 1)\n          && (octave::math::nint_big (m_inc) == m_inc || m_numel <= 1));\n}\n\nMatrix\nRange::matrix_value () const\n{\n  Matrix retval (1, m_numel);\n\n  if (m_numel > 0)\n    {\n      // The first element must always be *exactly* the base.\n      // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment).\n      retval(0) = m_base;\n\n      double b = m_base;\n      double increment = m_inc;\n      for (octave_idx_type i = 1; i < m_numel - 1; i++)\n        retval.xelem (i) = b + i * increment;\n\n      retval.xelem (m_numel - 1) = m_limit;\n    }\n\n  return retval;\n}\n\n// NOTE: max and min only return useful values if numel > 0.\n//       do_minmax_body() in max.cc avoids calling Range::min/max if numel == 0.\n\ndouble\nRange::min () const\n{\n  double retval = 0.0;\n  if (m_numel > 0)\n    {\n      if (m_inc > 0)\n        retval = m_base;\n      else\n        {\n          retval = m_base + (m_numel - 1) * m_inc;\n\n          // Require '<=' test.  See note in max ().\n          if (retval <= m_limit)\n            retval = m_limit;\n        }\n\n    }\n  return retval;\n}\n\ndouble\nRange::max () const\n{\n  double retval = 0.0;\n  if (m_numel > 0)\n    {\n      if (m_inc > 0)\n        {\n          retval = m_base + (m_numel - 1) * m_inc;\n\n          // On some machines (x86 with extended precision floating point\n          // arithmetic, for example) it is possible that we can overshoot the\n          // limit by approximately the machine precision even though we were\n          // very careful in our calculation of the number of elements.\n          // Therefore, we clip the result to the limit if it overshoots.\n          // The test also includes equality (>= m_limit) to have expressions\n          // such as -5:1:-0 result in a -0 endpoint.\n          if (retval >= m_limit)\n            retval = m_limit;\n        }\n      else\n        retval = m_base;\n    }\n  return retval;\n}\n\n// C  See Knuth, Art Of Computer Programming, Vol. 1, Problem 1.2.4-5.\n// C\n// C===Tolerant FLOOR function.\n// C\n// C    X  -  is given as a Double Precision argument to be operated on.\n// C          It is assumed that X is represented with M mantissa bits.\n// C    CT -  is   given   as   a   Comparison   Tolerance   such   that\n// C          0.LT.CT.LE.3-SQRT(5)/2. If the relative difference between\n// C          X and A whole number is  less  than  CT,  then  TFLOOR  is\n// C          returned   as   this   whole   number.   By  treating  the\n// C          floating-point numbers as a finite ordered set  note  that\n// C          the  heuristic  EPS=2.**(-(M-1))   and   CT=3*EPS   causes\n// C          arguments  of  TFLOOR/TCEIL to be treated as whole numbers\n// C          if they are  exactly  whole  numbers  or  are  immediately\n// C          adjacent to whole number representations.  Since EPS,  the\n// C          \"distance\"  between  floating-point  numbers  on  the unit\n// C          interval, and M, the number of bits in X'S mantissa, exist\n// C          on  every  floating-point   computer,   TFLOOR/TCEIL   are\n// C          consistently definable on every floating-point computer.\n// C\n// C          For more information see the following references:\n// C    (1) P. E. Hagerty, \"More On Fuzzy Floor And Ceiling,\" APL  QUOTE\n// C        QUAD 8(4):20-24, June 1978. Note that TFLOOR=FL5.\n// C    (2) L. M. Breed, \"Definitions For Fuzzy Floor And Ceiling\",  APL\n// C        QUOTE QUAD 8(3):16-23, March 1978. This paper cites FL1 through\n// C        FL5, the history of five years of evolutionary development of\n// C        FL5 - the seven lines of code below - by open collaboration\n// C        and corroboration of the mathematical-computing community.\n// C\n// C  Penn State University Center for Academic Computing\n// C  H. D. Knoble - August, 1978.\n\nstatic inline double\ntfloor (double x, double ct)\n{\n// C---------FLOOR(X) is the largest integer algebraically less than\n// C         or equal to X; that is, the unfuzzy FLOOR function.\n\n//  DINT (X) = X - DMOD (X, 1.0);\n//  FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0);\n\n// C---------Hagerty's FL5 function follows...\n\n  double q = 1.0;\n\n  if (x < 0.0)\n    q = 1.0 - ct;\n\n  double rmax = q / (2.0 - ct);\n\n  double t1 = 1.0 + std::floor (x);\n  t1 = (ct / q) * (t1 < 0.0 ? -t1 : t1);\n  t1 = (rmax < t1 ? rmax : t1);\n  t1 = (ct > t1 ? ct : t1);\n  t1 = std::floor (x + t1);\n\n  if (x <= 0.0 || (t1 - x) < rmax)\n    return t1;\n  else\n    return t1 - 1.0;\n}\n\nstatic inline bool\nteq (double u, double v,\n     double ct = 3.0 * std::numeric_limits<double>::epsilon ())\n{\n  double tu = std::abs (u);\n  double tv = std::abs (v);\n\n  return std::abs (u - v) < ((tu > tv ? tu : tv) * ct);\n}\n\noctave_idx_type\nRange::numel_internal () const\n{\n  octave_idx_type retval = -1;\n\n  if (! octave::math::isfinite (m_base) || ! octave::math::isfinite (m_inc)\n      || octave::math::isnan (m_limit))\n    retval = -2;\n  else if (octave::math::isinf (m_limit)\n           && ((m_inc > 0 && m_limit > 0)\n               || (m_inc < 0 && m_limit < 0)))\n    retval = std::numeric_limits<octave_idx_type>::max () - 1;\n  else if (m_inc == 0\n           || (m_limit > m_base && m_inc < 0)\n           || (m_limit < m_base && m_inc > 0))\n    {\n      retval = 0;\n    }\n  else\n    {\n      double ct = 3.0 * std::numeric_limits<double>::epsilon ();\n\n      double tmp = tfloor ((m_limit - m_base + m_inc) / m_inc, ct);\n\n      octave_idx_type n_elt = (tmp > 0.0\n                               ? static_cast<octave_idx_type> (tmp) : 0);\n\n      // If the final element that we would compute for the range is equal to\n      // the limit of the range, or is an adjacent floating point number,\n      // accept it.  Otherwise, try a range with one fewer element.  If that\n      // fails, try again with one more element.\n      //\n      // I'm not sure this is very good, but it seems to work better than just\n      // using tfloor as above.  For example, without it, the expression\n      // 1.8:0.05:1.9 fails to produce the expected result of [1.8, 1.85, 1.9].\n\n      if (! teq (m_base + (n_elt - 1) * m_inc, m_limit))\n        {\n          if (teq (m_base + (n_elt - 2) * m_inc, m_limit))\n            n_elt--;\n          else if (teq (m_base + n_elt * m_inc, m_limit))\n            n_elt++;\n        }\n\n      retval = ((n_elt < std::numeric_limits<octave_idx_type>::max ())\n                ? n_elt : -1);\n    }\n\n  return retval;\n}\n\ndouble\nRange::limit_internal () const\n{\n  double new_limit = m_inc > 0 ? max () : min ();\n\n  // If result must be an integer then force the new_limit to be one.\n  if (all_elements_are_ints ())\n    new_limit = std::round (new_limit);\n\n  return new_limit;\n}\n\nvoid\nRange::init ()\n{\n  m_numel = numel_internal ();\n\n  if (! octave::math::isinf (m_limit))\n    m_limit = limit_internal ();\n}\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_legacy_range, \"range\", \"double\");\n\noctave_legacy_range::octave_legacy_range ()\n  : octave_base_value (), m_range (new Range ()) { }\n\noctave_legacy_range::octave_legacy_range (const Range& r)\n  : octave_base_value (), m_range (new Range (r))\n{\n  if (m_range->numel () < 0 && m_range->numel () != -2)\n    error (\"invalid range\");\n}\n\noctave_legacy_range::octave_legacy_range (const octave_legacy_range& r)\n  : octave_base_value (r), m_range ()\n{\n  m_range.reset (new Range (*(r.m_range)));\n}\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_legacy_range& v = dynamic_cast<const octave_legacy_range&> (a);\n\n  return new octave_matrix (v.matrix_value ());\n}\n\noctave_base_value::type_conv_info\noctave_legacy_range::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n                                            octave_matrix::static_type_id ());\n}\n\noctave_base_value *\noctave_legacy_range::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  switch (m_range->numel ())\n    {\n    case 1:\n      retval = new octave_scalar (m_range->base ());\n      break;\n\n    case 0:\n      retval = new octave_matrix (Matrix (1, 0));\n      break;\n\n    case -2:\n      retval = new octave_matrix (m_range->matrix_value ());\n      break;\n\n    default:\n      {\n        if (m_range->increment () == 0)\n          retval = new octave_matrix (m_range->matrix_value ());\n        else\n          retval = new octave_range\n            (octave::range<double> (m_range->base (), m_range->increment (),\n                                    m_range->limit (), m_range->numel ()));\n      }\n      break;\n    }\n\n  return retval;\n}\n\n// Skip white space and comments on stream IS.\n\nstatic void\nskip_comments (std::istream& is)\n{\n  char c = '\\0';\n  while (is.get (c))\n    {\n      if (c == ' ' || c == '\\t' || c == '\\n')\n        ; // Skip whitespace on way to beginning of next line.\n      else\n        break;\n    }\n\n  octave::skip_until_newline (is, false);\n}\n\nbool\noctave_legacy_range::load_ascii (std::istream& is)\n{\n  // # base, limit, range comment added by save ().\n  skip_comments (is);\n\n  double base, limit, inc;\n  is >> base >> limit >> inc;\n\n  if (! is)\n    error (\"load: failed to load range constant\");\n\n  if (inc != 0)\n    m_range.reset (new Range (base, limit, inc));\n  else\n    m_range.reset (new Range (base, inc, static_cast<octave_idx_type> (limit)));\n\n  return true;\n}\n\nbool\noctave_legacy_range::load_binary (std::istream& is, bool swap,\n                                  octave::mach_info::float_format /* fmt */)\n{\n  char tmp;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n    return false;\n  double bas, lim, inc;\n  if (! is.read (reinterpret_cast<char *> (&bas), 8))\n    return false;\n  if (swap)\n    swap_bytes<8> (&bas);\n  if (! is.read (reinterpret_cast<char *> (&lim), 8))\n    return false;\n  if (swap)\n    swap_bytes<8> (&lim);\n  if (! is.read (reinterpret_cast<char *> (&inc), 8))\n    return false;\n  if (swap)\n    swap_bytes<8> (&inc);\n  if (inc != 0)\n    m_range.reset (new Range (bas, lim, inc));\n  else\n    m_range.reset (new Range (bas, inc, static_cast<octave_idx_type> (lim)));\n\n  return true;\n}\n\n#if defined (HAVE_HDF5)\n\n// The following subroutines creates an HDF5 representation of the way\n// we will store Octave range types (triplets of floating-point numbers).\n// NUM_TYPE is the HDF5 numeric type to use for storage (e.g.,\n// H5T_NATIVE_DOUBLE to save as 'double').  Note that any necessary\n// conversions are handled automatically by HDF5.\n\nstatic hid_t\nhdf5_make_range_type (hid_t num_type)\n{\n  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 3);\n\n  H5Tinsert (type_id, \"base\", 0 * sizeof (double), num_type);\n  H5Tinsert (type_id, \"limit\", 1 * sizeof (double), num_type);\n  H5Tinsert (type_id, \"increment\", 2 * sizeof (double), num_type);\n\n  return type_id;\n}\n\n#endif\n\nbool\noctave_legacy_range::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t type_hid = H5Dget_type (data_hid);\n\n  hid_t range_type = hdf5_make_range_type (H5T_NATIVE_DOUBLE);\n\n  if (! hdf5_types_compatible (type_hid, range_type))\n    {\n      H5Tclose (range_type);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  hid_t space_hid = H5Dget_space (data_hid);\n  hsize_t rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Tclose (range_type);\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  double rangevals[3];\n  if (H5Dread (data_hid, range_type, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, rangevals)\n      >= 0)\n    {\n      retval = true;\n      octave_idx_type nel;\n      if (hdf5_get_scalar_attr (data_hid, H5T_NATIVE_IDX,\n                                \"OCTAVE_RANGE_NELEM\", &nel))\n        m_range.reset (new Range (rangevals[0], rangevals[2], nel));\n      else\n        {\n          if (rangevals[2] != 0)\n            m_range.reset (new Range (rangevals[0], rangevals[1], rangevals[2]));\n          else\n            m_range.reset (new Range (rangevals[0], rangevals[2],\n                                      static_cast<octave_idx_type> (rangevals[1])));\n        }\n    }\n\n  H5Tclose (range_type);\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-legacy-range.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_legacy_range_h)\n#define octave_ov_legacy_range_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <memory>\n#include <string>\n\n#include \"mappers.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n\nclass Range;\n\nclass octave_value_list;\n\n// Legacy Range values.\n\n// Provide enough of the old octave_range class to allow Range objects\n// to be loaded from files.  After loading, they are converted to some\n// other type by a call to octave_value::maybe_mutate in\n// load_save_system::load_vars so there should no longer be any values\n// of this type used by the interpreter.  The action of maybe_mutate is\n// performed by octave_legacy_range::try_narrowing_conversion.\n\nclass octave_legacy_range : public octave_base_value\n{\npublic:\n\n  octave_legacy_range ();\n\n  octave_legacy_range (const Range& r);\n\n  octave_legacy_range (const octave_legacy_range& r);\n\n  // No assignment.\n\n  octave_legacy_range& operator = (const octave_legacy_range&) = delete;\n\n  ~octave_legacy_range () = default;\n\n  octave_base_value * clone () const\n  {\n    return new octave_legacy_range (*this);\n  }\n\n  // A range is really just a special kind of real matrix object.  In\n  // the places where we need to call empty_clone, it makes more sense\n  // to create an empty matrix (0x0) instead of an empty range (1x0).\n  octave_base_value * empty_clone () const { return new octave_matrix (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  bool is_defined () const { return true; }\n\n  bool is_legacy_object () const { return true; }\n\n  bool is_constant () const { return true; }\n\n  bool load_ascii (std::istream& is);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\nprivate:\n\n  std::unique_ptr<Range> m_range;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-magic-int.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"oct-inttypes-fwd.h\"\n\n#include \"data-conv.h\"\n#include \"mappers.h\"\n#include \"mach-info.h\"\n#include \"oct-specfun.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-base.h\"\n#include \"ov-magic-int.h\"\n#include \"ov-base-scalar.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"pr-output.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n#include \"ops.h\"\n\n#include \"ls-oct-text.h\"\n#include \"ls-hdf5.h\"\n\n// NOTE: Although there is some additional overhead, for all but the\n// simplest data type extraction operations, we convert to an\n// octave_scalar object and forward the operation to avoid code\n// duplication and ensure that operations on magic_int objects are\n// identical to operations on octave_scalar objects.  We could also\n// avoid code duplication by deriving octave_magic_int from\n// octave_scalar, but then we would need to store both the double and\n// octave_uint64 or octave_int64 values, doubling the storage\n// requirement.\n\nstatic octave_base_value *\ndefault_numeric_conv_fcn (const octave_base_value& a)\n{\n  return new octave_scalar (a.double_value ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::do_index_op (const octave_value_list& idx,\n                                       bool resize_ok)\n{\n  octave_value tmp (double_value ());\n\n  return tmp.index_op (idx, resize_ok);\n}\n\ntemplate <typename T>\noctave::idx_vector\noctave_base_magic_int<T>::index_vector (bool require_integers) const\n{\n  octave_value tmp (double_value ());\n\n  return tmp.index_vector (require_integers);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::resize (const dim_vector& dv, bool fill) const\n{\n  octave_value tmp (double_value ());\n\n  return tmp.resize (dv, fill);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_double () const\n{\n  return static_cast<double> (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_single () const\n{\n  return static_cast<float> (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_int8 () const\n{\n  return octave_int8 (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_int16 () const\n{\n  return octave_int16 (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_int32 () const\n{\n  return octave_int32 (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_int64 () const\n{\n  return octave_int64 (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_uint8 () const\n{\n  return octave_uint8 (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_uint16 () const\n{\n  return octave_uint16 (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_uint32 () const\n{\n  return octave_uint32 (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::as_uint64 () const\n{\n  return octave_uint64 (scalar_ref ());\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::diag (octave_idx_type m, octave_idx_type n) const\n{\n  octave_value tmp (double_value ());\n\n  return tmp.diag (m, n);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::convert_to_str_internal (bool, bool, char type) const\n{\n  octave_value retval;\n\n  int ival;\n\n  if (scalar_ref ().value () > std::numeric_limits<unsigned char>::max ())\n    {\n      // FIXME: is there something better we could do?\n\n      ival = 0;\n\n      ::warning (\"range error for conversion to character value\");\n    }\n  else\n    ival = scalar_ref ().value ();\n\n  retval = octave_value (std::string (1, static_cast<char> (ival)), type);\n\n  return retval;\n}\n\n\ntemplate <typename T>\nbool\noctave_base_magic_int<T>::save_ascii (std::ostream& os)\n{\n  octave_value tmp (double_value ());\n\n  return tmp.save_ascii (os);\n}\n\ntemplate <typename T>\nbool\noctave_base_magic_int<T>::load_ascii (std::istream&)\n{\n  error (\"octave_base_magic_int<T>::load_ascii: internal error\");\n}\n\ntemplate <typename T>\nbool\noctave_base_magic_int<T>::save_binary (std::ostream& os, bool save_as_floats)\n{\n  octave_value tmp (double_value ());\n\n  return tmp.save_binary (os, save_as_floats);\n}\n\ntemplate <typename T>\nbool\noctave_base_magic_int<T>::load_binary (std::istream&, bool,\n                                       octave::mach_info::float_format)\n{\n  error (\"octave_base_magic_int<T>::load_binary: internal error\");\n}\n\ntemplate <typename T>\nbool\noctave_base_magic_int<T>::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                                     bool save_as_floats)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  octave_value tmp (double_value ());\n\n  return tmp.save_hdf5 (loc_id, name, save_as_floats);\n\n#else\n\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  octave_base_value::warn_save (\"hdf5\");\n\n#endif\n\n  return retval;\n}\n\ntemplate <typename T>\nbool\noctave_base_magic_int<T>::load_hdf5 (octave_hdf5_id, const char *)\n{\n#if defined (HAVE_HDF5)\n\n  error (\"octave_base_magic_int<T>::load_binary: internal error\");\n\n  return false;\n\n#else\n\n  octave_base_value::warn_load (\"hdf5\");\n\n  return false;\n\n#endif\n}\n\ntemplate <typename T>\nmxArray *\noctave_base_magic_int<T>::as_mxArray (bool interleaved) const\n{\n  octave_value tmp (double_value ());\n\n  return tmp.as_mxArray (interleaved);\n}\n\ntemplate <typename T>\noctave_value\noctave_base_magic_int<T>::map (octave_base_value::unary_mapper_t umap) const\n{\n  octave_value tmp (double_value ());\n\n  return tmp.map (umap);\n}\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_magic_uint, \"magic_uint\",\n                                     \"double\");\n\noctave_base_value::type_conv_info\noctave_magic_uint::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conv_fcn,\n         octave_scalar::static_type_id ());\n}\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_magic_int, \"magic_int\",\n                                     \"double\");\n\noctave_base_value::type_conv_info\noctave_magic_int::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conv_fcn,\n         octave_scalar::static_type_id ());\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-magic-int.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_magic_int_h)\n#define octave_ov_magic_int_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\n#include \"oct-inttypes-fwd.h\"\n\n#include \"ov-base.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-base-scalar.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Large integer scalar values.  The uint64 or int64 value they contain may be\n// accessed without loss of precision when needed (for example, when\n// directly converted to a uint64 or int64 value).  Otherwise, they\n// behave like real scalars, so any operation on them will result in\n// type conversion.\n\ntemplate <typename T>\nclass octave_base_magic_int : public octave_base_scalar<T>\n{\npublic:\n\n  octave_base_magic_int ()\n    : octave_base_scalar<T> (0) { }\n\n  octave_base_magic_int (const T& val)\n    : octave_base_scalar<T> (val) { }\n\n  ~octave_base_magic_int () = default;\n\n  // We return an octave_matrix here instead of an octave_scalar so\n  // that in expressions like A(2,2,2) = 2 (for A previously\n  // undefined), A will be empty instead of a 1x1 object.\n  octave_base_value * empty_clone () const { return new octave_matrix (); }\n\n  // Although SCALAR is a protected member of the base class, it is not\n  // directly visible here without the explicit octave_base_slalar<T>::\n  // qualification.  Why not?\n\n  const T& scalar_ref () const { return octave_base_scalar<T>::scalar; }\n\n  T& scalar_ref () { return octave_base_scalar<T>::scalar; }\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  octave::idx_vector index_vector (bool require_integers = false) const;\n\n  octave_value any (int = 0) const { return scalar_ref () != T (0); }\n\n  builtin_type_t builtin_type () const { return btyp_double; }\n\n  bool is_storable () const { return false; }\n\n  bool is_magic_int () const { return true; }\n\n  bool vm_need_storable_call () const { return true; }\n\n  bool is_real_scalar () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  int8NDArray int8_array_value () const\n  { return int8NDArray (dim_vector (1, 1), double_value ()); }\n\n  int16NDArray int16_array_value () const\n  { return int16NDArray (dim_vector (1, 1), double_value ()); }\n\n  int32NDArray int32_array_value () const\n  { return int32NDArray (dim_vector (1, 1), double_value ()); }\n\n  int64NDArray int64_array_value () const\n  { return int64NDArray (dim_vector (1, 1), double_value ()); }\n\n  uint8NDArray uint8_array_value () const\n  { return uint8NDArray (dim_vector (1, 1), double_value ()); }\n\n  uint16NDArray uint16_array_value () const\n  { return uint16NDArray (dim_vector (1, 1), double_value ()); }\n\n  uint32NDArray uint32_array_value () const\n  { return uint32NDArray (dim_vector (1, 1), double_value ()); }\n\n  uint64NDArray uint64_array_value () const\n  { return uint64NDArray (dim_vector (1, 1), double_value ()); }\n\n  octave_int8 int8_scalar_value () const\n  { return octave_int8 (double_value ()); }\n\n  octave_int16 int16_scalar_value () const\n  { return octave_int16 (double_value ()); }\n\n  octave_int32 int32_scalar_value () const\n  { return octave_int32 (double_value ()); }\n\n  octave_int64 int64_scalar_value () const\n  { return octave_int64 (double_value ()); }\n\n  octave_uint8 uint8_scalar_value () const\n  { return octave_uint8 (double_value ()); }\n\n  octave_uint16 uint16_scalar_value () const\n  { return octave_uint16 (double_value ()); }\n\n  octave_uint32 uint32_scalar_value () const\n  { return octave_uint32 (double_value ()); }\n\n  octave_uint64 uint64_scalar_value () const\n  { return octave_uint64 (double_value ()); }\n\n  double double_value (bool = false) const\n  {\n    return scalar_ref ().double_value ();\n  }\n\n  float float_value (bool = false) const\n  { return static_cast<float> (double_value ()); }\n\n  double scalar_value (bool = false) const\n  { return double_value (); }\n\n  float float_scalar_value (bool = false) const\n  { return float_value (); }\n\n  Matrix matrix_value (bool = false) const\n  { return Matrix (1, 1, double_value ()); }\n\n  FloatMatrix float_matrix_value (bool = false) const\n  { return FloatMatrix (1, 1, float_value ()); }\n\n  NDArray array_value (bool = false) const\n  { return NDArray (dim_vector (1, 1), double_value ()); }\n\n  FloatNDArray float_array_value (bool = false) const\n  { return FloatNDArray (dim_vector (1, 1), float_value ()); }\n\n  SparseMatrix sparse_matrix_value (bool = false) const\n  { return SparseMatrix (Matrix (1, 1, double_value ())); }\n\n  // FIXME: Need SparseComplexMatrix (Matrix) constructor!\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  { return SparseComplexMatrix (sparse_matrix_value ()); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const;\n\n  Complex complex_value (bool = false) const { return double_value (); }\n\n  FloatComplex float_complex_value (bool = false) const\n  { return FloatComplex (float_value ()); }\n\n  ComplexMatrix complex_matrix_value (bool = false) const\n  { return ComplexMatrix (1, 1, Complex (double_value ())); }\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const\n  { return FloatComplexMatrix (1, 1, FloatComplex (float_value ())); }\n\n  ComplexNDArray complex_array_value (bool = false) const\n  { return ComplexNDArray (dim_vector (1, 1), Complex (double_value ())); }\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const\n  {\n    return FloatComplexNDArray (dim_vector (1, 1),\n                                FloatComplex (float_value ()));\n  }\n\n  charNDArray\n  char_array_value (bool = false) const\n  {\n    charNDArray retval (dim_vector (1, 1));\n    retval(0) = static_cast<char> (double_value ());\n    return retval;\n  }\n\n  bool bool_value (bool warn = false) const\n  {\n    if (warn && scalar_ref () != T (0) && scalar_ref () != T (1))\n      warn_logical_conversion ();\n\n    return double_value ();\n  }\n\n  boolNDArray bool_array_value (bool warn = false) const\n  {\n    if (warn && scalar_ref () != T (0) && scalar_ref () != T (1))\n      warn_logical_conversion ();\n\n    return boolNDArray (dim_vector (1, 1), double_value ());\n  }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_scalar<T>::diag;\n\n  octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  void increment () { scalar_ref () += T (1); }\n\n  void decrement () { scalar_ref () -= T (1); }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    return os.write (array_value (), block_size, output_type,\n                     skip, flt_fmt);\n  }\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (octave_base_value::unary_mapper_t umap) const;\n};\n\nclass OCTINTERP_API octave_magic_uint : public octave_base_magic_int<octave_uint64>\n{\npublic:\n\n  octave_magic_uint ()\n    : octave_base_magic_int<octave_uint64> (0) { }\n\n  octave_magic_uint (const octave_uint64& val)\n    : octave_base_magic_int<octave_uint64> (val) { }\n\n  ~octave_magic_uint () = default;\n\n  octave_base_value * clone () const\n  {\n    return new octave_magic_uint (*this);\n  }\n\n  type_conv_info numeric_conversion_function () const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\nclass OCTINTERP_API octave_magic_int : public octave_base_magic_int<octave_int64>\n{\npublic:\n\n  octave_magic_int ()\n    : octave_base_magic_int<octave_int64> (0) { }\n\n  octave_magic_int (const octave_int64& val)\n    : octave_base_magic_int<octave_int64> (val) { }\n\n  ~octave_magic_int () = default;\n\n  octave_base_value * clone () const\n  {\n    return new octave_magic_int (*this);\n  }\n\n  type_conv_info numeric_conversion_function () const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-mex-fcn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"file-ops.h\"\n#include \"oct-shlib.h\"\n\n#include \"defaults.h\"\n#include \"dynamic-ld.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ov-mex-fcn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"profiler.h\"\n#include \"unwind-prot.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_mex_function,\n                                     \"mex function\", \"mex function\");\n\noctave_mex_function::octave_mex_function\n(void *fptr, bool interleaved, const octave::dynamic_library& shl,\n const std::string& nm)\n  : octave_function (nm), m_mex_fcn_ptr (fptr), m_exit_fcn_ptr (nullptr),\n    m_sh_lib (shl), m_interleaved (interleaved), m_is_system_fcn_file (false)\n{\n  mark_fcn_file_up_to_date (time_parsed ());\n\n  std::string file_name = fcn_file_name ();\n\n  static const std::string canonical_oct_file_dir\n    = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ());\n  static const std::string oct_file_dir\n    = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir ()\n      : canonical_oct_file_dir;\n\n  m_is_system_fcn_file\n    = (! file_name.empty ()\n       && oct_file_dir == file_name.substr (0, oct_file_dir.length ()));\n}\n\noctave_mex_function::~octave_mex_function ()\n{\n  if (m_exit_fcn_ptr)\n    (*m_exit_fcn_ptr) ();\n\n  octave::dynamic_loader& dyn_loader = octave::__get_dynamic_loader__ ();\n\n  dyn_loader.remove_mex (m_name, m_sh_lib);\n}\n\nstd::string\noctave_mex_function::fcn_file_name () const\n{\n  return m_sh_lib.file_name ();\n}\n\noctave::sys::time\noctave_mex_function::time_parsed () const\n{\n  return m_sh_lib.time_loaded ();\n}\n\noctave_value_list\noctave_mex_function::execute (octave::tree_evaluator& tw, int nargout,\n                              const octave_value_list& args)\n{\n  return tw.execute_mex_function (*this, nargout, args);\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-mex-fcn.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_mex_fcn_h)\n#define octave_ov_mex_fcn_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"oct-shlib.h\"\n\n#include \"ov-fcn.h\"\n#include \"ov-builtin.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value;\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_evaluator;\n\nOCTAVE_END_NAMESPACE(octave)\n\n// Dynamically-linked functions.\n\nclass OCTINTERP_API octave_mex_function : public octave_function\n{\npublic:\n\n  octave_mex_function ()\n    : m_mex_fcn_ptr (nullptr), m_exit_fcn_ptr (nullptr), m_sh_lib (),\n      m_time_checked (), m_interleaved (false), m_is_system_fcn_file (false)\n  { }\n\n  OCTINTERP_API\n  octave_mex_function (void *fptr, bool interleaved,\n                       const octave::dynamic_library& shl,\n                       const std::string& nm = \"\");\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_mex_function)\n\n  OCTINTERP_API ~octave_mex_function ();\n\n  octave_function * function_value (bool = false) { return this; }\n\n  const octave_function * function_value (bool = false) const { return this; }\n\n  void mark_fcn_file_up_to_date (const octave::sys::time& t)\n  {\n    m_time_checked = t;\n  }\n\n  OCTINTERP_API std::string fcn_file_name () const;\n\n  OCTINTERP_API octave::sys::time time_parsed () const;\n\n  octave::sys::time time_checked () const { return m_time_checked; }\n\n  bool is_system_fcn_file () const { return m_is_system_fcn_file; }\n\n  bool is_builtin_function () const { return false; }\n\n  bool is_mex_function () const { return true; }\n\n  bool use_interleaved_complex () const { return m_interleaved; }\n\n  octave_value_list\n  execute (octave::tree_evaluator& tw, int nargout = 0,\n           const octave_value_list& args = octave_value_list ());\n\n  void atexit (void (*fcn) ()) { m_exit_fcn_ptr = fcn; }\n\n  octave::dynamic_library get_shlib () const { return m_sh_lib; }\n\n  void * mex_fcn_ptr () const { return m_mex_fcn_ptr; }\n\nprivate:\n\n  void *m_mex_fcn_ptr;\n\n  void (*m_exit_fcn_ptr) ();\n\n  octave::dynamic_library m_sh_lib;\n\n  // The time the file was last checked to see if it needs to be\n  // parsed again.\n  octave::sys::time m_time_checked;\n\n  bool m_interleaved;\n\n  // True if this function came from a file that is considered to be a\n  // system function.  This affects whether we check the time stamp\n  // on the file to see if it has changed.\n  bool m_is_system_fcn_file;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-null-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"defun.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_null_matrix, \"null_matrix\",\n                                     \"double\");\n\nconst octave_value octave_null_matrix::instance (new octave_null_matrix ());\n\nstatic octave_base_value *\ndefault_null_matrix_numeric_conversion_function (const octave_base_value& a)\n{\n  // The cast is not necessary?\n  // const octave_null_matrix& v = dynamic_cast<const octave_null_matrix&> (a);\n\n  return a.empty_clone ();\n}\n\noctave_base_value::type_conv_info\noctave_null_matrix::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info\n         (default_null_matrix_numeric_conversion_function,\n          octave_matrix::static_type_id ());\n}\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_null_str, \"null_string\", \"char\");\n\nconst octave_value octave_null_str::instance (new octave_null_str ());\n\nstatic octave_base_value *\ndefault_null_str_numeric_conversion_function (const octave_base_value& a)\n{\n  // The cast is not necessary?\n  // const octave_null_str& v = dynamic_cast<const octave_null_str&> (a);\n\n  return a.empty_clone ();\n}\n\noctave_base_value::type_conv_info\noctave_null_str::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info\n         (default_null_str_numeric_conversion_function,\n          octave_char_matrix_str::static_type_id ());\n}\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_null_sq_str, \"null_sq_string\",\n                                     \"char\");\n\nconst octave_value octave_null_sq_str::instance (new octave_null_sq_str ());\n\nstatic octave_base_value *\ndefault_null_sq_str_numeric_conversion_function (const octave_base_value& a)\n{\n  // The cast is not necessary?\n  // const octave_null_sq_str& v = dynamic_cast<const octave_null_sq_str&> (a);\n\n  return a.empty_clone ();\n}\n\noctave_base_value::type_conv_info\noctave_null_sq_str::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info\n         (default_null_sq_str_numeric_conversion_function,\n          octave_char_matrix_sq_str::static_type_id ());\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (isnull, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isnull (@var{x})\nReturn true if @var{x} is a special null array, string, or single quoted\nstring.\n\nIndexed assignment with such a null value on the right-hand side should delete\narray elements.  This function is used in place of @code{isempty} when\noverloading the indexed assignment method (@code{subsasgn}) for user-defined\nclasses.  @code{isnull} is used to distinguish between these two cases:\n\n@code{@var{A}(@var{I}) = []}\n\nand\n\n@code{@var{X} = []; @var{A}(@var{I}) = @var{X}}\n\nIn the first assignment, the right-hand side is @code{[]} which is a special\nnull value.  As long as the index @var{I} is not empty, this code should\ndelete elements from @var{A} rather than perform assignment.\n\nIn the second assignment, the right-hand side is empty (because @var{X} is\n@code{[]}), but it is @strong{not} null.  This code should assign the empty\nvalue to elements in @var{A}.\n\nAn example from Octave's built-in char class demonstrates the interpreter\nbehavior when @code{isnull} is used correctly.\n\n@example\n@group\nstr = \"Hello World\";\nnm = \"Wally\";\nstr(7:end) = nm                # indexed assignment\n  @xresult{} str = Hello Wally\nstr(7:end) = \"\"                # indexed deletion\n  @xresult{} str = Hello\n@end group\n@end example\n@seealso{isempty, isindex}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isnull ());\n}\n\n/*\n%!assert (isnull ([]), true)\n%!assert (isnull ([1]), false)\n%!assert (isnull (zeros (0,3)), false)\n%!assert (isnull (\"\"), true)\n%!assert (isnull (\"A\"), false)\n%!assert (isnull (''), true)\n%!assert (isnull ('A'), false)\n%!test\n%! x = [];\n%! assert (isnull (x), false);\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-null-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_null_mat_h)\n#define octave_ov_null_mat_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-str-mat.h\"\n\n// Design rationale:\n// The constructors are hidden.  There is only one null matrix (or null string)\n// object, that can have shallow copies.  Cloning the object returns just a\n// normal empty matrix, so all the shallow copies are, in fact, read-only.\n// This conveniently ensures that any attempt to fiddle with the null matrix\n// destroys its special status.\n\n// The special [] value.\n\nclass OCTINTERP_API octave_null_matrix : public octave_matrix\n{\n  octave_null_matrix () : octave_matrix () { }\n\npublic:\n\n  static const octave_value instance;\n\n  bool isnull () const { return true; }\n  bool vm_need_storable_call () const { return true; }\n\n  type_conv_info numeric_conversion_function () const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n// The special \"\" value\n\nclass OCTINTERP_API octave_null_str : public octave_char_matrix_str\n{\n  octave_null_str () : octave_char_matrix_str () { }\n\npublic:\n\n  static const octave_value instance;\n\n  bool is_storable () const { return false; }\n\n  bool isnull () const { return true; }\n  bool vm_need_storable_call () const { return true; }\n\n  type_conv_info numeric_conversion_function () const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n// The special '' value\n\nclass OCTINTERP_API octave_null_sq_str : public octave_char_matrix_sq_str\n{\n  octave_null_sq_str () : octave_char_matrix_sq_str () { }\n\npublic:\n\n  static const octave_value instance;\n\n  bool is_storable () const { return false; }\n\n  bool isnull () const { return true; }\n\n  bool vm_need_storable_call () const { return true; }\n\n  type_conv_info numeric_conversion_function () const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-oncleanup.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"ov-oncleanup.h\"\n#include \"ov-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pt-misc.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_oncleanup, \"onCleanup\",\n                                     \"onCleanup\");\n\noctave_oncleanup::octave_oncleanup (const octave_value& f)\n  : m_fcn (f)\n{\n  if (f.is_function_handle ())\n    {\n      octave_function *fptr = f.function_value (true);\n      if (! fptr)\n        error (\"onCleanup: no default dispatch for function handle\");\n\n      octave_user_function *uptr\n        = dynamic_cast<octave_user_function *> (fptr);\n\n      if (uptr != nullptr)\n        {\n          octave::tree_parameter_list *pl = uptr->parameter_list ();\n\n          if (pl != nullptr && pl->size () > 0)\n            warning (\"onCleanup: cleanup action takes parameters\");\n        }\n    }\n  else\n    {\n      m_fcn = octave_value ();\n      error (\"onCleanup: argument must be a function handle\");\n    }\n}\n\noctave_oncleanup::~octave_oncleanup ()\n{\n  call_object_destructor ();\n}\n\noctave_scalar_map\noctave_oncleanup::scalar_map_value () const\n{\n  octave_scalar_map retval;\n  retval.setfield (\"task\", m_fcn);\n  return retval;\n}\n\nbool\noctave_oncleanup::save_ascii (std::ostream& /* os */)\n{\n  warning (\"save: unable to save onCleanup variables, skipping\");\n\n  return true;\n}\n\nbool\noctave_oncleanup::load_ascii (std::istream& /* is */)\n{\n  // Silently skip object that was not saved\n  return true;\n}\n\nbool\noctave_oncleanup::save_binary (std::ostream& /* os */,\n                               bool /* save_as_floats */)\n{\n  warning (\"save: unable to save onCleanup variables, skipping\");\n\n  return true;\n}\n\nbool\noctave_oncleanup::load_binary (std::istream& /* is */, bool /* swap */,\n                               octave::mach_info::float_format /* fmt */)\n{\n  // Silently skip object that was not saved\n  return true;\n}\n\nbool\noctave_oncleanup::save_hdf5 (octave_hdf5_id /* loc_id */,\n                             const char * /* name */,\n                             bool /* save_as_floats */)\n{\n  warning (\"save: unable to save onCleanup variables, skipping\");\n\n  return true;\n}\n\nbool\noctave_oncleanup::load_hdf5 (octave_hdf5_id /* loc_id */,\n                             const char * /* name */)\n{\n  // Silently skip object that was not saved\n  return true;\n}\n\nvoid\noctave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\n\nvoid\noctave_oncleanup::print_raw (std::ostream& os, bool pr_as_read_syntax) const\n{\n  os << \"onCleanup (\";\n  if (m_fcn.is_defined ())\n    m_fcn.print_raw (os, pr_as_read_syntax);\n  os << ')';\n}\n\nvoid\noctave_oncleanup::call_object_destructor ()\n{\n  if (m_fcn.is_undefined ())\n    return;\n\n  octave_value the_fcn = m_fcn;\n  m_fcn = octave_value ();\n\n  octave::unwind_protect frame;\n\n  // Clear interrupts.\n  frame.protect_var (octave_interrupt_state);\n  octave_interrupt_state = 0;\n\n  // Disallow quit().\n  frame.protect_var (quit_allowed);\n  quit_allowed = false;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::interpreter_try (frame);\n\n  try\n    {\n      // Run the actual code.\n      interp.feval (the_fcn);\n    }\n  catch (const octave::interrupt_exception&)\n    {\n      interp.recover_from_exception ();\n\n      warning (\"onCleanup: interrupt occurred in cleanup action\");\n    }\n  catch (const octave::execution_exception& ee)\n    {\n      interp.recover_from_exception ();\n\n      std::string msg = ee.message ();\n\n      warning (\"onCleanup: error caught while executing cleanup function:\\n%s\\n\",\n               msg.c_str ());\n\n    }\n  catch (const octave::exit_exception&)\n    {\n      // This shouldn't happen since we disabled quit above.\n      warning (\"onCleanup: exit disabled while executing cleanup function\");\n    }\n  catch (...) // Yes, the black hole.  We're in a d-tor.\n    {\n      // This shouldn't happen, in theory.\n      warning (\"onCleanup: internal error: unhandled exception in cleanup action\");\n    }\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (onCleanup, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{obj} =} onCleanup (@var{function})\nCreate a special object that executes a given @var{function} upon destruction.\n\nIf the object is copied to multiple variables (or cell or struct array\nelements) or returned from a function, then @var{function} will be executed\nonly after the last copy of the object is cleared.\n\nThe input @var{function} is a handle to a function.  The handle may point to an\nanonymous function in order to directly place commands in the @code{onCleanup}\ncall.\n\nProgramming Note: If multiple local @code{onCleanup} variables are created, the\norder in which they are called is unspecified.  For similar functionality\n@xref{The unwind_protect Statement}.\n\nExample\n\n@example\n@group\noctave:1> trigger = onCleanup (@@() disp ('onCleanup was executed'));\noctave:2> clear trigger\nonCleanup was executed\noctave:3\n@end group\n@end example\n\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (new octave_oncleanup (args(0)));\n}\n\n/*\n%!test\n%! old_wstate = warning (\"query\");\n%! unwind_protect\n%!   trigger = onCleanup (@() warning (\"on\", \"__MY_WARNING__\"));\n%!   warning (\"off\", \"__MY_WARNING__\");\n%!   assert ((warning (\"query\", \"__MY_WARNING__\")).state, \"off\");\n%!   clear trigger;\n%!   assert ((warning (\"query\", \"__MY_WARNING__\")).state, \"on\");\n%! unwind_protect_cleanup\n%!   warning (old_wstate);\n%! end_unwind_protect\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-oncleanup.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_oncleanup_h)\n#define octave_ov_oncleanup_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n#include \"ov-base.h\"\n#include \"ov-struct.h\"\n#include \"ov.h\"\n\n\nclass octave_oncleanup : public octave_base_value\n{\npublic:\n\n  octave_oncleanup () = default;\n\n  octave_oncleanup (const octave_value& m_fcn);\n\n  octave_base_value * clone () const\n  {\n    if (m_fcn.is_defined ())\n      error (\"onCleanup: internal error: cloning nonempty object\");\n\n    return empty_clone ();\n  }\n\n  octave_base_value * empty_clone () const\n  {\n    return new octave_oncleanup ();\n  }\n\n  ~octave_oncleanup ();\n\n  bool is_defined () const { return true; }\n\n  bool isobject () const { return true; } // do we want this?\n\n  octave_map map_value () const { return scalar_map_value (); }\n\n  octave_scalar_map scalar_map_value () const;\n\n  dim_vector dims () const\n  {\n    static dim_vector dv (1, 1);\n    return dv;\n  }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  void call_object_destructor ();\n\n  void maybe_call_dtor ()\n  {\n    if (m_count == 1)\n      call_object_destructor ();\n  }\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n\nprotected:\n\n  octave_value m_fcn;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-perm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"byte-swap.h\"\n#include \"dim-vector.h\"\n\n#include \"mxarray.h\"\n#include \"ov-perm.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"ops.h\"\n#include \"pr-output.h\"\n\n#include \"ls-oct-text.h\"\n\noctave_value\noctave_perm_matrix::subsref (const std::string& type,\n                             const std::list<octave_value_list>& idx)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      retval = do_index_op (idx.front ());\n      break;\n\n    case '{':\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_perm_matrix::subsref - please report this bug\");\n    }\n\n  return retval.next_subsref (type, idx);\n}\n\noctave_value\noctave_perm_matrix::do_index_op (const octave_value_list& idx,\n                                 bool resize_ok)\n{\n  octave_value retval;\n  octave_idx_type nidx = idx.length ();\n  octave::idx_vector idx0, idx1;\n  if (nidx == 2)\n    {\n      int k = 0;    // index we're processing when index_vector throws\n      try\n        {\n          idx0 = idx(0).index_vector ();\n          k = 1;\n          idx1 = idx(1).index_vector ();\n        }\n      catch (octave::index_exception& ie)\n        {\n          // Rethrow to allow more info to be reported later.\n          ie.set_pos_if_unset (2, k+1);\n          throw;\n        }\n    }\n\n  // This hack is to allow constructing permutation matrices using\n  // eye(n)(p,:), eye(n)(:,q) && eye(n)(p,q) where p & q are permutation\n  // vectors.\n  // Note that, for better consistency, eye(n)(:,:) still converts to a full\n  // matrix.\n  if (nidx == 2)\n    {\n      bool left = idx0.is_permutation (m_matrix.rows ());\n      bool right = idx1.is_permutation (m_matrix.cols ());\n\n      if (left && right)\n        {\n          if (idx0.is_colon ()) left = false;\n          if (idx1.is_colon ()) right = false;\n          if (left || right)\n            {\n              PermMatrix p = m_matrix;\n              if (left)\n                p = PermMatrix (idx0, false) * p;\n              if (right)\n                p = p * PermMatrix (idx1, true);\n              retval = p;\n            }\n          else\n            {\n              retval = this;\n              this->m_count++;\n            }\n        }\n    }\n\n  if (! retval.is_defined ())\n    {\n      if (nidx == 2 && ! resize_ok && idx0.is_scalar () && idx1.is_scalar ())\n        retval = m_matrix.checkelem (idx0(0), idx1(0));\n      else\n        retval = to_dense ().index_op (idx, resize_ok);\n    }\n\n  return retval;\n}\n\n// Return true if this matrix has all true elements (nonzero, not NaN/NA).\n// A permutation cannot have NaN/NA.\nbool\noctave_perm_matrix::is_true () const\n{\n  if (dims ().numel () > 1)\n    {\n      warn_array_as_logical (dims ());\n      return false;    // > 1x1 permutation always has zeros, and no NaN.\n    }\n  else\n    return dims ().numel ();    // 1x1 is [1] == true, 0x0 == false.\n}\n\ndouble\noctave_perm_matrix::double_value (bool) const\n{\n  if (isempty ())\n    err_invalid_conversion (type_name (), \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            type_name (), \"real scalar\");\n\n  return m_matrix(0, 0);\n}\n\nfloat\noctave_perm_matrix::float_value (bool) const\n{\n  if (isempty ())\n    err_invalid_conversion (type_name (), \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            type_name (), \"real scalar\");\n\n  return m_matrix(0, 0);\n}\n\nComplex\noctave_perm_matrix::complex_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (type_name (), \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            type_name (), \"complex scalar\");\n\n  return Complex (m_matrix(0, 0), 0);\n}\n\nFloatComplex\noctave_perm_matrix::float_complex_value (bool) const\n{\n  float tmp = lo_ieee_float_nan_value ();\n\n  FloatComplex retval (tmp, tmp);\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (type_name (), \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            type_name (), \"complex scalar\");\n\n  retval = m_matrix(0, 0);\n\n  return retval;\n}\n\n#define FORWARD_MATRIX_VALUE(TYPE, PREFIX)                              \\\n  TYPE                                                                  \\\n  octave_perm_matrix::PREFIX ## _value (bool frc_str_conv) const        \\\n  {                                                                     \\\n    return to_dense ().PREFIX ## _value (frc_str_conv);                 \\\n  }\n\nSparseMatrix\noctave_perm_matrix::sparse_matrix_value (bool) const\n{\n  return SparseMatrix (m_matrix);\n}\n\nSparseBoolMatrix\noctave_perm_matrix::sparse_bool_matrix_value (bool) const\n{\n  return SparseBoolMatrix (m_matrix);\n}\n\nSparseComplexMatrix\noctave_perm_matrix::sparse_complex_matrix_value (bool) const\n{\n  return SparseComplexMatrix (sparse_matrix_value ());\n}\n\nFORWARD_MATRIX_VALUE (Matrix, matrix)\nFORWARD_MATRIX_VALUE (FloatMatrix, float_matrix)\nFORWARD_MATRIX_VALUE (ComplexMatrix, complex_matrix)\nFORWARD_MATRIX_VALUE (FloatComplexMatrix, float_complex_matrix)\n\nFORWARD_MATRIX_VALUE (NDArray, array)\nFORWARD_MATRIX_VALUE (FloatNDArray, float_array)\nFORWARD_MATRIX_VALUE (ComplexNDArray, complex_array)\nFORWARD_MATRIX_VALUE (FloatComplexNDArray, float_complex_array)\n\nFORWARD_MATRIX_VALUE (boolNDArray, bool_array)\nFORWARD_MATRIX_VALUE (charNDArray, char_array)\n\noctave::idx_vector\noctave_perm_matrix::index_vector (bool require_integers) const\n{\n  return to_dense ().index_vector (require_integers);\n}\n\noctave_value\noctave_perm_matrix::convert_to_str_internal (bool pad, bool force,\n    char type) const\n{\n  return to_dense ().convert_to_str_internal (pad, force, type);\n}\n\noctave_value\noctave_perm_matrix::as_double () const\n{\n  return m_matrix;\n}\n\noctave_value\noctave_perm_matrix::as_single () const\n{\n  return float_array_value ();\n}\n\noctave_value\noctave_perm_matrix::as_int8 () const\n{\n  return int8_array_value  ();\n}\n\noctave_value\noctave_perm_matrix::as_int16 () const\n{\n  return int16_array_value ();\n}\n\noctave_value\noctave_perm_matrix::as_int32 () const\n{\n  return int32_array_value ();\n}\n\noctave_value\noctave_perm_matrix::as_int64 () const\n{\n  return int64_array_value ();\n}\n\noctave_value\noctave_perm_matrix::as_uint8 () const\n{\n  return uint8_array_value ();\n}\n\noctave_value\noctave_perm_matrix::as_uint16 () const\n{\n  return uint16_array_value ();\n}\n\noctave_value\noctave_perm_matrix::as_uint32 () const\n{\n  return uint32_array_value ();\n}\n\noctave_value\noctave_perm_matrix::as_uint64 () const\n{\n  return uint64_array_value ();\n}\n\nfloat_display_format\noctave_perm_matrix::get_edit_display_format () const\n{\n  return float_display_format (float_format (1, 0, 0));\n}\n\nstd::string\noctave_perm_matrix::edit_display (const float_display_format& fmt,\n                                  octave_idx_type i,\n                                  octave_idx_type j) const\n{\n  std::ostringstream buf;\n  octave_print_internal (buf, fmt, octave_int<octave_idx_type> (m_matrix(i, j)));\n  return buf.str ();\n}\n\nbool\noctave_perm_matrix::save_ascii (std::ostream& os)\n{\n  os << \"# size: \" << m_matrix.rows () << \"\\n\";\n  os << \"# orient: c\\n\";\n\n  Array<octave_idx_type> pvec = m_matrix.col_perm_vec ();\n  octave_idx_type n = pvec.numel ();\n  ColumnVector tmp (n);\n  for (octave_idx_type i = 0; i < n; i++) tmp(i) = pvec(i) + 1;\n  os << tmp;\n\n  return true;\n}\n\nbool\noctave_perm_matrix::load_ascii (std::istream& is)\n{\n  octave_idx_type n;\n  char orient;\n\n  if (! extract_keyword (is, \"size\", n, true)\n      || ! extract_keyword (is, \"orient\", orient, true))\n    error (\"load: failed to extract size & orientation\");\n\n  bool colp = orient == 'c';\n  ColumnVector tmp (n);\n  is >> tmp;\n  if (! is)\n    error (\"load: failed to load permutation matrix constant\");\n\n  Array<octave_idx_type> pvec (dim_vector (n, 1));\n  for (octave_idx_type i = 0; i < n; i++) pvec(i) = tmp(i) - 1;\n  m_matrix = PermMatrix (pvec, colp);\n\n  // Invalidate cache.  Probably not necessary, but safe.\n  m_dense_cache = octave_value ();\n\n  return true;\n}\n\nbool\noctave_perm_matrix::save_binary (std::ostream& os, bool)\n{\n\n  int32_t sz = m_matrix.rows ();\n  bool colp = true;\n  os.write (reinterpret_cast<char *> (&sz), 4);\n  os.write (reinterpret_cast<char *> (&colp), 1);\n  const Array<octave_idx_type>& col_perm = m_matrix.col_perm_vec ();\n  os.write (reinterpret_cast<const char *> (col_perm.data ()),\n            col_perm.byte_size ());\n\n  return true;\n}\n\nbool\noctave_perm_matrix::load_binary (std::istream& is, bool swap,\n                                 octave::mach_info::float_format)\n{\n  int32_t sz;\n  bool colp;\n  if (! (is.read (reinterpret_cast<char *> (&sz), 4)\n         && is.read (reinterpret_cast<char *> (&colp), 1)))\n    return false;\n\n  MArray<octave_idx_type> m (dim_vector (sz, 1));\n\n  if (! is.read (reinterpret_cast<char *> (m.rwdata ()), m.byte_size ()))\n    return false;\n\n  if (swap)\n    {\n      int nel = m.numel ();\n      for (int i = 0; i < nel; i++)\n        switch (sizeof (octave_idx_type))\n          {\n          case 8:\n            swap_bytes<8> (&m(i));\n            break;\n          case 4:\n            swap_bytes<4> (&m(i));\n            break;\n          case 2:\n            swap_bytes<2> (&m(i));\n            break;\n          case 1:\n          default:\n            break;\n          }\n    }\n\n  m_matrix = PermMatrix (m, colp);\n  return true;\n}\n\nvoid\noctave_perm_matrix::print_raw (std::ostream& os,\n                               bool pr_as_read_syntax) const\n{\n  return octave_print_internal (os, m_matrix, pr_as_read_syntax,\n                                current_print_indent_level ());\n}\n\nmxArray *\noctave_perm_matrix::as_mxArray (bool interleaved) const\n{\n  return to_dense ().as_mxArray (interleaved);\n}\n\nbool\noctave_perm_matrix::print_as_scalar () const\n{\n  const dim_vector& dv = dims ();\n\n  return (dv.all_ones () || dv.any_zero ());\n}\n\nvoid\noctave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\n\nint\noctave_perm_matrix::write (octave::stream& os, int block_size,\n                           oct_data_conv::data_type output_type, int skip,\n                           octave::mach_info::float_format flt_fmt) const\n{\n  return to_dense ().write (os, block_size, output_type, skip, flt_fmt);\n}\n\nvoid\noctave_perm_matrix::print_info (std::ostream& os,\n                                const std::string& prefix) const\n{\n  m_matrix.print_info (os, prefix);\n}\n\noctave_value\noctave_perm_matrix::to_dense () const\n{\n  if (! m_dense_cache.is_defined ())\n    m_dense_cache = Matrix (m_matrix);\n\n  return m_dense_cache;\n}\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_perm_matrix,\n                                     \"permutation matrix\", \"double\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_perm_matrix& v = dynamic_cast<const octave_perm_matrix&> (a);\n\n  return new octave_matrix (v.matrix_value ());\n}\n\noctave_base_value::type_conv_info\noctave_perm_matrix::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n         octave_matrix::static_type_id ());\n}\n\n// FIXME: This is duplicated from octave_base_matrix<T>.  Could\n// octave_perm_matrix be derived from octave_base_matrix<T>?\n\nvoid\noctave_perm_matrix::short_disp (std::ostream& os) const\n{\n  if (m_matrix.isempty ())\n    os << \"[]\";\n  else if (m_matrix.ndims () == 2)\n    {\n      // FIXME: should this be configurable?\n      octave_idx_type max_elts = 10;\n      octave_idx_type elts = 0;\n\n      octave_idx_type nr = m_matrix.rows ();\n      octave_idx_type nc = m_matrix.columns ();\n\n      os << '[';\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              std::ostringstream buf;\n              octave_int<octave_idx_type> tval (m_matrix(i, j));\n              octave_print_internal (buf, tval);\n              std::string tmp = buf.str ();\n              std::size_t pos = tmp.find_first_not_of (' ');\n              if (pos != std::string::npos)\n                os << tmp.substr (pos);\n              else if (! tmp.empty ())\n                os << tmp[0];\n              elts++;\n\n              if (j < nc - 1)\n                {\n                  os << \", \";\n\n                  if (elts >= max_elts)\n                    {\n                      os << \"...\";\n                      goto done;\n                    }\n                }\n            }\n\n          if (i < nr - 1)\n            {\n              os << \"; \";\n\n              if (elts >= max_elts)\n                {\n                  os << \"...\";\n                  goto done;\n                }\n            }\n        }\n\n    done:\n      os << ']';\n    }\n  else\n    octave_base_value::short_disp (os);\n}\n\noctave_base_value *\noctave_perm_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.numel () == 1)\n    retval = new octave_scalar (m_matrix (0, 0));\n\n  return retval;\n}\n\noctave_value\noctave_perm_matrix::fast_elem_extract (octave_idx_type n) const\n{\n  if (n < m_matrix.numel ())\n    {\n      octave_idx_type nr = m_matrix.rows ();\n\n      octave_idx_type r = n % nr;\n      octave_idx_type c = n / nr;\n\n      return octave_value (m_matrix.elem (r, c));\n    }\n  else\n    return octave_value ();\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-perm.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_perm_h)\n#define octave_ov_perm_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n#include \"ovl.h\"\n\nclass OCTINTERP_API octave_perm_matrix : public octave_base_value\n{\npublic:\n  octave_perm_matrix () : m_matrix (), m_dense_cache () { }\n\n  octave_perm_matrix (const PermMatrix& p) : m_matrix (p), m_dense_cache () { }\n\n  octave_base_value * clone () const\n  { return new octave_perm_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_perm_matrix (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  std::size_t byte_size () const { return m_matrix.byte_size (); }\n\n  octave_value squeeze () const { return m_matrix; }\n\n  octave_value full_value () const { return to_dense (); }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx);\n\n  octave_value_list subsref (const std::string& type,\n                             const std::list<octave_value_list>& idx, int)\n  { return subsref (type, idx); }\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  dim_vector dims () const { return m_matrix.dims (); }\n\n  octave_idx_type nnz () const { return m_matrix.rows (); }\n\n  octave_value reshape (const dim_vector& new_dims) const\n  { return to_dense ().reshape (new_dims); }\n\n  octave_value permute (const Array<int>& vec, bool inv = false) const\n  { return to_dense ().permute (vec, inv); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const\n  { return to_dense ().resize (dv, fill); }\n\n  octave_value all (int dim = 0) const { return to_dense ().all (dim); }\n  octave_value any (int dim = 0) const { return to_dense ().any (dim); }\n\n  MatrixType matrix_type () const { return MatrixType::Permuted_Diagonal; }\n  MatrixType matrix_type (const MatrixType&) const\n  { return matrix_type (); }\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::diag;\n\n  octave_value diag (octave_idx_type k = 0) const\n  { return to_dense () .diag (k); }\n\n  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const\n  { return to_dense ().sort (dim, mode); }\n  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n                     sortmode mode = ASCENDING) const\n  { return to_dense ().sort (sidx, dim, mode); }\n\n  sortmode issorted (sortmode mode = UNSORTED) const\n  { return to_dense ().issorted (mode); }\n\n  Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const\n  { return to_dense ().sort_rows_idx (mode); }\n\n  sortmode is_sorted_rows (sortmode mode = UNSORTED) const\n  { return to_dense ().is_sorted_rows (mode); }\n\n  builtin_type_t builtin_type () const { return btyp_double; }\n\n  bool is_perm_matrix () const { return true; }\n\n  bool is_matrix_type () const { return true; }\n\n  bool isnumeric () const { return true; }\n\n  bool is_defined () const { return true; }\n\n  bool is_constant () const { return true; }\n\n  bool is_real_matrix () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  bool is_true () const;\n\n  double double_value (bool = false) const;\n\n  float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  octave::idx_vector index_vector (bool require_integers = false) const;\n\n  PermMatrix perm_matrix_value () const\n  { return m_matrix; }\n\n  Matrix matrix_value (bool = false) const;\n\n  FloatMatrix float_matrix_value (bool = false) const;\n\n  Complex complex_value (bool = false) const;\n\n  FloatComplex float_complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const;\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const;\n\n  boolNDArray bool_array_value (bool warn = false) const;\n\n  charNDArray char_array_value (bool = false) const;\n\n  NDArray array_value (bool = false) const;\n\n  FloatNDArray float_array_value (bool = false) const;\n\n  SparseMatrix sparse_matrix_value (bool = false) const;\n\n  SparseBoolMatrix sparse_bool_matrix_value (bool = false) const;\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;\n\n  int8NDArray\n  int8_array_value () const { return to_dense ().int8_array_value (); }\n\n  int16NDArray\n  int16_array_value () const { return to_dense ().int16_array_value (); }\n\n  int32NDArray\n  int32_array_value () const { return to_dense ().int32_array_value (); }\n\n  int64NDArray\n  int64_array_value () const { return to_dense ().int64_array_value (); }\n\n  uint8NDArray\n  uint8_array_value () const { return to_dense ().uint8_array_value (); }\n\n  uint16NDArray\n  uint16_array_value () const { return to_dense ().uint16_array_value (); }\n\n  uint32NDArray\n  uint32_array_value () const { return to_dense ().uint32_array_value (); }\n\n  uint64NDArray\n  uint64_array_value () const { return to_dense ().uint64_array_value (); }\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  float_display_format get_edit_display_format () const;\n\n  std::string edit_display (const float_display_format& fmt,\n                            octave_idx_type i, octave_idx_type j) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const;\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  bool print_as_scalar () const;\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  void print_info (std::ostream& os, const std::string& prefix) const;\n\n  void short_disp (std::ostream& os) const;\n\n  octave_value map (unary_mapper_t umap) const\n  { return to_dense ().map (umap); }\n\n  octave_value fast_elem_extract (octave_idx_type n) const;\n\nprotected:\n\n  PermMatrix m_matrix;\n\n  virtual octave_value to_dense () const;\n\n  mutable octave_value m_dense_cache;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-range-traits.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_range_traits_h)\n#define octave_ov_range_traits_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov-bool-mat.h\"\n#include \"ov-bool.h\"\n#include \"ov-float.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n\ntemplate <typename T>\nclass octave_value_range_traits\n{\npublic:\n  typedef T scalar_type;\n  typedef T matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<bool>\n{\npublic:\n  typedef octave_bool scalar_type;\n  typedef octave_bool_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<float>\n{\npublic:\n  typedef octave_float_scalar scalar_type;\n  typedef octave_float_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<double>\n{\npublic:\n  typedef octave_scalar scalar_type;\n  typedef octave_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<octave_int8>\n{\npublic:\n  typedef octave_int8_scalar scalar_type;\n  typedef octave_int8_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<octave_int16>\n{\npublic:\n  typedef octave_int16_scalar scalar_type;\n  typedef octave_int16_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<octave_int32>\n{\npublic:\n  typedef octave_int32_scalar scalar_type;\n  typedef octave_int32_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<octave_int64>\n{\npublic:\n  typedef octave_int64_scalar scalar_type;\n  typedef octave_int64_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<octave_uint8>\n{\npublic:\n  typedef octave_uint8_scalar scalar_type;\n  typedef octave_uint8_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<octave_uint16>\n{\npublic:\n  typedef octave_uint16_scalar scalar_type;\n  typedef octave_uint16_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<octave_uint32>\n{\npublic:\n  typedef octave_uint32_scalar scalar_type;\n  typedef octave_uint32_matrix matrix_type;\n};\n\ntemplate <>\nclass octave_value_range_traits<octave_uint64>\n{\npublic:\n  typedef octave_uint64_scalar scalar_type;\n  typedef octave_uint64_matrix matrix_type;\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-range.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n#include <sstream>\n\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n#include \"int8NDArray.h\"\n#include \"int16NDArray.h\"\n#include \"int32NDArray.h\"\n#include \"int64NDArray.h\"\n#include \"uint8NDArray.h\"\n#include \"uint16NDArray.h\"\n#include \"uint32NDArray.h\"\n#include \"uint64NDArray.h\"\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n\n#include \"defun.h\"\n#include \"variables.h\"\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"mx-type-traits.h\"\n#include \"ops.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"ov-inline.h\"\n#include \"ov-range-traits.h\"\n#include \"ov-range.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"pr-output.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-ascii-helper.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-utils.h\"\n\n#if defined (HAVE_HDF5)\n\ntemplate <>\noctave_hdf5_id ov_range<double>::hdf5_save_type = H5T_NATIVE_DOUBLE;\n\n// For now, enable only ov_range<double>.\n\n#else\n\ntemplate <>\noctave_hdf5_id ov_range<double>::hdf5_save_type = 0;\n\n// For now, enable only ov_range<double>.\n\n#endif\n\nDEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<double>,\n    \"double_range\", \"double\");\n\n// For now, enable only ov_range<double>.\n\ntemplate <typename T>\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;\n\n  const ov_range<T>& v = dynamic_cast<const ov_range<T>&> (a);\n\n  return new ov_mx_type (v.raw_array_value ());\n}\n\ntemplate <typename T>\noctave_base_value::type_conv_info\nov_range<T>::numeric_conversion_function () const\n{\n  typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;\n\n  return octave_base_value::type_conv_info\n         (default_numeric_conversion_function<T>, ov_mx_type::static_type_id ());\n}\n\ntemplate <typename T>\noctave_base_value *\nov_range<T>::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  switch (numel ())\n    {\n    case 1:\n      retval = new typename octave_value_range_traits<T>::scalar_type (m_range.elem (0));\n      break;\n\n    case 0:\n      {\n        typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;\n        typename ov_mx_type::object_type m (dim_vector (1, 0));\n        retval = new ov_mx_type (m);\n      }\n      break;\n\n    case -2:\n      // FIXME: is this case possible now?  It would have to be due to\n      // conversion from Range to range<double>, but even in that case,\n      // is the invalid numel value preserved?\n      retval = new typename octave_value_range_traits<T>::matrix_type (raw_array_value ());\n      break;\n\n    default:\n      break;\n    }\n\n  return retval;\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::subsref (const std::string& type,\n                      const std::list<octave_value_list>& idx)\n{\n  octave_value retval;\n\n  switch (type[0])\n    {\n    case '(':\n      retval = do_index_op (idx.front ());\n      break;\n\n    case '{':\n    case '.':\n      {\n        std::string nm = type_name ();\n        error (\"%s cannot be indexed with %c\", nm.c_str (), type[0]);\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in ov_range<T>::subsref - please report this bug\");\n    }\n\n  return retval.next_subsref (type, idx);\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::do_index_op (const octave_value_list& idx,\n                          bool resize_ok)\n{\n  if (idx.length () == 1 && ! resize_ok)\n    {\n      octave_value retval;\n\n      // The range can handle a single subscript.\n\n      try\n        {\n          octave::idx_vector i = idx(0).index_vector ();\n\n          if (i.is_scalar () && i(0) < numel ())\n            retval = m_range.elem (i(0));\n          else\n            retval = m_range.index (i);\n        }\n      catch (octave::index_exception& ie)\n        {\n          // More info may be added later before displaying error.\n\n          ie.set_pos_if_unset (1, 1);\n          throw;\n        }\n\n      return retval;\n    }\n  else\n    {\n      octave_value tmp (new typename octave_value_range_traits<T>::matrix_type (raw_array_value ()));\n\n      return tmp.index_op (idx, resize_ok);\n    }\n}\n\ntemplate <typename T>\noctave::idx_vector\nov_range<T>::index_vector (bool require_integers) const\n{\n  octave_value tmp (raw_array_value ());\n  return tmp.index_vector (require_integers);\n}\n\ntemplate <typename T>\ndouble\nov_range<T>::double_value (bool) const\n{\n  octave_idx_type nel = numel ();\n\n  if (nel == 0)\n    err_invalid_conversion (\"range\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"range\", \"real scalar\");\n\n  return m_range.base ();\n}\n\ntemplate <typename T>\nfloat\nov_range<T>::float_value (bool) const\n{\n  octave_idx_type nel = numel ();\n\n  if (nel == 0)\n    err_invalid_conversion (\"range\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"range\", \"real scalar\");\n\n  return m_range.base ();\n}\n\ntemplate <typename T>\ncharNDArray\nov_range<T>::char_array_value (bool) const\n{\n  const Array<T> matrix = raw_array_value ();\n  charNDArray retval (dims ());\n\n  octave_idx_type nel = numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval.elem (i) = static_cast<char> (matrix.elem (i));\n\n  return retval;\n}\n\ntemplate <typename T>\nComplex\nov_range<T>::complex_value (bool) const\n{\n  octave_idx_type nel = numel ();\n\n  if (nel == 0)\n    err_invalid_conversion (\"range\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"range\", \"complex scalar\");\n\n  return Complex (m_range.base (), 0);\n}\n\ntemplate <typename T>\nFloatComplex\nov_range<T>::float_complex_value (bool) const\n{\n  float tmp = lo_ieee_float_nan_value ();\n\n  FloatComplex retval (tmp, tmp);\n\n  octave_idx_type nel = numel ();\n\n  if (nel == 0)\n    err_invalid_conversion (\"range\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"range\", \"complex scalar\");\n\n  retval = m_range.base ();\n\n  return retval;\n}\n\ntemplate <typename T>\nboolNDArray\nov_range<T>::bool_array_value (bool warn) const\n{\n  Array<T> matrix = raw_array_value ();\n\n  if (warn && ! matrix.test_all (octave::is_one_or_zero<T>))\n    warn_logical_conversion ();\n\n  return boolNDArray (matrix);\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::resize (const dim_vector& dv, bool fill) const\n{\n  Array<T> retval = raw_array_value ();\n  if (fill)\n    retval.resize (dv, 0);\n  else\n    retval.resize (dv);\n  return retval;\n}\n\ntemplate <typename T>\noctave::range<double>\nov_range<T>::range_value () const\n{\n  err_wrong_type_arg (\"ov_range<T>::range_value()\", type_name ());\n}\n\n// For now, enable only ov_range<double>.\n\ntemplate <typename T>\noctave_value\nov_range<T>::convert_to_str_internal (bool pad, bool force, char type) const\n{\n  octave_value tmp (raw_array_value ());\n  return tmp.convert_to_str (pad, force, type);\n}\n\n// FIXME: could most of these fucntions preserve range type now?\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_double () const\n{\n  return NDArray (raw_array_value ());\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_single () const\n{\n  return FloatMatrix (raw_array_value ());\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_int8 () const\n{\n  return int8NDArray (raw_array_value ());\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_int16 () const\n{\n  return int16NDArray (raw_array_value ());\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_int32 () const\n{\n  return int32NDArray (raw_array_value ());\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_int64 () const\n{\n  return int64NDArray (raw_array_value ());\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_uint8 () const\n{\n  return uint8NDArray (raw_array_value ());\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_uint16 () const\n{\n  return uint16NDArray (raw_array_value ());\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_uint32 () const\n{\n  return uint32NDArray (raw_array_value ());\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_uint64 () const\n{\n  return uint64NDArray (raw_array_value ());\n}\n\ntemplate <typename T>\nvoid\nov_range<T>::print (std::ostream& os, bool pr_as_read_syntax)\n{\n  print_raw (os, pr_as_read_syntax);\n  newline (os);\n}\n\ntemplate <typename T>\nvoid\nov_range<T>::print_raw (std::ostream& os, bool pr_as_read_syntax) const\n{\n  // FIXME: this is a potential waste of memory.\n\n  typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;\n  typename ov_mx_type::object_type tmp (raw_array_value ());\n\n  octave_print_internal (os, tmp, pr_as_read_syntax,\n                         current_print_indent_level ());\n}\n\ntemplate <typename T>\nbool\nov_range<T>::print_name_tag (std::ostream& os, const std::string& name) const\n{\n  bool retval = false;\n\n  octave_idx_type n = numel ();\n\n  indent (os);\n\n  if (n == 0 || n == 1)\n    os << name << \" = \";\n  else\n    {\n      os << name << \" =\";\n      newline (os);\n      if (! Vcompact_format)\n        newline (os);\n\n      retval = true;\n    }\n\n  return retval;\n}\n\ntemplate <typename T>\nvoid\nov_range<T>::short_disp (std::ostream& os) const\n{\n  octave_idx_type len = numel ();\n\n  if (len == 0)\n    os << \"[]\";\n  else\n    {\n      os << m_range.base () << ':';\n\n      if (len > 1)\n        {\n          if (m_range.increment () != T (1))\n            os << m_range.increment () << ':';\n\n          os << m_range.limit ();\n        }\n    }\n}\n\n// Skip white space and comments on stream IS.\n\nstatic void\nskip_comments (std::istream& is)\n{\n  char c = '\\0';\n  while (is.get (c))\n    {\n      if (c == ' ' || c == '\\t' || c == '\\n')\n        ; // Skip whitespace on way to beginning of next line.\n      else\n        break;\n    }\n\n  octave::skip_until_newline (is, false);\n}\n\ntemplate <typename T>\nfloat_display_format\nov_range<T>::get_edit_display_format () const\n{\n  return make_format (m_range);\n}\n\ntemplate <typename T>\nstd::string\nov_range<T>::edit_display (const float_display_format& fmt,\n                           octave_idx_type, octave_idx_type j) const\n{\n  std::ostringstream buf;\n  octave_print_internal (buf, fmt, m_range.elem (j));\n  return buf.str ();\n}\n\ntemplate <typename T>\nbool\nxsave_ascii (std::ostream& os, const octave::range<T>& r,\n             const bool with_reverse)\n{\n  T base = r.base ();\n  T limit = r.limit ();\n  T inc = r.increment ();\n  bool rev = r.reverse ();\n  octave_idx_type len = r.numel ();\n\n  if (inc != T (0))\n    os << \"# base, limit, increment\";\n  else\n    os << \"# base, length, increment\";\n\n  if (with_reverse)\n    os << \", reverse\\n\";\n  else\n    os << \"\\n\";\n\n  octave::write_value<T> (os, base);\n  os << ' ';\n  if (inc != T (0))\n    octave::write_value<T> (os, limit);\n  else\n    os << len;\n  os << ' ';\n  octave::write_value<T> (os, inc);\n  if (with_reverse)\n    os << ' ' << rev;\n  os << \"\\n\";\n\n  return true;\n}\n\ntemplate <typename T>\nbool\nov_range<T>::save_ascii (std::ostream& os)\n{\n  return xsave_ascii (os, m_range, false);\n}\n\n// specialize for saving with \"reverse\" flag\n\n// For now, enable only ov_range<double>.\n\ntemplate <typename T>\nbool\nxload_ascii (std::istream& is, octave::range<T>& r, const bool with_reverse)\n{\n  // # base, limit, range comment added by save ().\n  skip_comments (is);\n\n  T base, limit, inc;\n  bool rev = false;\n  is >> base >> limit >> inc;\n\n  if (with_reverse)\n    is >> rev;\n\n  if (! is)\n    error (\"load: failed to load range constant\");\n\n  r = octave::range<T> (base, inc, limit, rev);\n\n  return true;\n}\n\ntemplate <typename T>\nbool\nov_range<T>::load_ascii (std::istream& is)\n{\n  return xload_ascii (is, m_range, false);\n}\n\n// specialize for loading with \"reverse\" flag\n\n// For now, enable only ov_range<double>.\n\n/*\n%!test\n%! a = b = 1:4;\n%! sv_file = [tempname(), \".sav\"];\n%! unwind_protect\n%!   save (sv_file, \"a\", \"-text\");\n%!   clear a;\n%!   load (sv_file);\n%!   assert (a, b);\n%! unwind_protect_cleanup\n%!   delete ([sv_file, '*']);\n%! end_unwind_protect\n\n%!test\n%! a = b = uint8(5):-1:0;\n%! sv_file = [tempname(), \".sav\"];\n%! unwind_protect\n%!   save (sv_file, \"a\", \"-text\");\n%!   clear a;\n%!   load (sv_file);\n%!   assert (a, b);\n%! unwind_protect_cleanup\n%!   delete ([sv_file, '*']);\n%! end_unwind_protect\n*/\n\ntemplate <typename T>\nbool\nxsave_binary (std::ostream& os, bool /* save_as_floats */,\n              const octave::range<T>& r, const bool with_reverse)\n{\n  // FIXME: Not always double!\n\n  char tmp = LS_DOUBLE;\n  os.write (reinterpret_cast<char *> (&tmp), 1);\n  T bas = r.base ();\n  T lim = r.limit ();\n  T inc = r.increment ();\n  if (inc == T (0))\n    lim = r.numel ();\n\n  os.write (reinterpret_cast<char *> (&bas), sizeof (T));\n  os.write (reinterpret_cast<char *> (&lim), sizeof (T));\n  os.write (reinterpret_cast<char *> (&inc), sizeof (T));\n  if (with_reverse)\n    {\n      bool rev = r.reverse ();\n      os.write (reinterpret_cast<char *> (&rev), sizeof (bool));\n    }\n\n  return true;\n}\n\ntemplate <typename T>\nbool\nov_range<T>::save_binary (std::ostream& os, bool save_as_floats)\n{\n  return xsave_binary (os, save_as_floats, m_range, false);\n}\n\n// For now, enable only ov_range<double>.\n\ntemplate <typename T>\nbool\nxload_binary (std::istream& is, bool swap,\n              octave::mach_info::float_format /* fmt */,\n              octave::range<T>& r, const bool with_reverse)\n{\n  // FIXME: Not always double!\n\n  char tmp;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n    return false;\n  T bas, lim, inc;\n  if (! is.read (reinterpret_cast<char *> (&bas), sizeof (T)))\n    return false;\n  if (swap)\n    swap_bytes<sizeof (T)> (&bas);\n  if (! is.read (reinterpret_cast<char *> (&lim), sizeof (T)))\n    return false;\n  if (swap)\n    swap_bytes<sizeof (T)> (&lim);\n  if (! is.read (reinterpret_cast<char *> (&inc), sizeof (T)))\n    return false;\n  if (swap)\n    swap_bytes<sizeof (T)> (&inc);\n  bool rev = false;\n  if (with_reverse)\n    {\n      if (! is.read (reinterpret_cast<char *> (&rev), sizeof (bool)))\n        return false;\n      if (swap)\n        swap_bytes<sizeof (bool)> (&rev);\n    }\n\n  r = octave::range<T> (bas, inc, lim, rev);\n\n  return true;\n}\n\ntemplate <typename T>\nbool\nov_range<T>::load_binary (std::istream& is, bool swap,\n                          octave::mach_info::float_format fmt)\n{\n  return xload_binary (is, swap, fmt, m_range, false);\n}\n\n// For now, enable only ov_range<double>.\n\n/*\n%!test\n%! a = b = 1:4;\n%! sv_file = [tempname(), \".dat\"];\n%! unwind_protect\n%!   save (sv_file, \"a\", \"-binary\");\n%!   clear a;\n%!   load (sv_file);\n%!   assert (a, b);\n%! unwind_protect_cleanup\n%!   delete ([sv_file, '*']);\n%! end_unwind_protect\n\n%!test\n%! a = b = uint8(5):-1:0;\n%! sv_file = [tempname(), \".dat\"];\n%! unwind_protect\n%!   save (sv_file, \"a\", \"-binary\");\n%!   clear a;\n%!   load (sv_file);\n%!   assert (a, b);\n%! unwind_protect_cleanup\n%!   delete ([sv_file, '*']);\n%! end_unwind_protect\n*/\n\n#if defined (HAVE_HDF5)\n\n// The following subroutines creates an HDF5 representation of the way\n// we will store Octave range types (triplets of floating-point numbers).\n// NUM_TYPE is the HDF5 numeric type to use for storage (e.g.,\n// H5T_NATIVE_DOUBLE to save as 'double').  Note that any necessary\n// conversions are handled automatically by HDF5.\n\ntemplate <typename T>\nstatic hid_t\nhdf5_make_range_type (hid_t num_type)\n{\n  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (T) * 3);\n\n  H5Tinsert (type_id, \"base\", 0 * sizeof (T), num_type);\n  H5Tinsert (type_id, \"limit\", 1 * sizeof (T), num_type);\n  H5Tinsert (type_id, \"increment\", 2 * sizeof (T), num_type);\n\n  return type_id;\n}\n\ntemplate <typename T>\nstatic hid_t\nhdf5_make_range_rev_type (hid_t num_type)\n{\n  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (T) * 4);\n\n  H5Tinsert (type_id, \"base\", 0 * sizeof (T), num_type);\n  H5Tinsert (type_id, \"limit\", 1 * sizeof (T), num_type);\n  H5Tinsert (type_id, \"increment\", 2 * sizeof (T), num_type);\n  // FIXME: Storing \"reverse\" with the same width is inefficient.\n  H5Tinsert (type_id, \"reverse\", 3 * sizeof (T), num_type);\n\n  return type_id;\n}\n\ntemplate <typename T>\nbool\nxsave_hdf5 (octave_hdf5_id loc_id, const char *name,\n            bool /* save_as_floats */, const octave::range<T>& r,\n            const octave_hdf5_id h5_save_type, const bool with_reverse)\n{\n  bool retval = false;\n\n  hsize_t dimens[3] = {0};\n  hid_t space_hid, type_hid, data_hid;\n  space_hid = type_hid = data_hid = -1;\n\n  space_hid = H5Screate_simple (0, dimens, nullptr);\n  if (space_hid < 0) return false;\n\n  type_hid = with_reverse\n             ? hdf5_make_range_rev_type<T> (h5_save_type)\n             : hdf5_make_range_type<T> (h5_save_type);\n  if (type_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n#  if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#  else\n  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);\n#  endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Tclose (type_hid);\n      return false;\n    }\n\n  T range_vals[4];\n  range_vals[0] = r.base ();\n  if (r.increment () != T (0))\n    range_vals[1] = r.limit ();\n  else\n    range_vals[1] = r.numel ();\n  range_vals[2] = r.increment ();\n  range_vals[3] = r.reverse ();\n\n  if (H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,\n                octave_H5P_DEFAULT, range_vals)\n      >= 0)\n    {\n      octave_idx_type nel = r.numel ();\n      retval = hdf5_add_scalar_attr (data_hid, H5T_NATIVE_IDX,\n                                     \"OCTAVE_RANGE_NELEM\", &nel) >= 0;\n    }\n  else\n    retval = false;\n\n  H5Dclose (data_hid);\n  H5Tclose (type_hid);\n  H5Sclose (space_hid);\n\n  return retval;\n}\n\n#endif\n\ntemplate <typename T>\nbool\nov_range<T>::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                        bool save_as_floats)\n{\n#if defined (HAVE_HDF5)\n  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,\n                     false);\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n\n  return false;\n#endif\n}\n\n// For now, enable only ov_range<double>.\n\n#if defined (HAVE_HDF5)\n\ntemplate <typename T>\nbool\nxload_hdf5 (octave_hdf5_id loc_id, const char *name, octave::range<T>& r,\n            const octave_hdf5_id h5_save_type, const bool with_reverse)\n{\n  bool retval = false;\n\n#  if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#  else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#  endif\n  hid_t type_hid = H5Dget_type (data_hid);\n\n  hid_t range_type = with_reverse\n                     ? hdf5_make_range_rev_type<T> (h5_save_type)\n                     : hdf5_make_range_type<T> (h5_save_type);\n\n  if (! hdf5_types_compatible (type_hid, range_type))\n    {\n      H5Tclose (range_type);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  hid_t space_hid = H5Dget_space (data_hid);\n  hsize_t rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Tclose (range_type);\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  T rangevals[4];\n  if (H5Dread (data_hid, range_type, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, rangevals)\n      >= 0)\n    {\n      retval = true;\n\n      // Don't use OCTAVE_RANGE_NELEM attribute, just reconstruct the range.\n\n      bool rev = with_reverse ? static_cast<bool> (rangevals[3]) : false;\n\n      r = octave::range<T> (rangevals[0], rangevals[2], rangevals[1], rev);\n    }\n\n  H5Tclose (range_type);\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n\n  return retval;\n}\n\n#endif\n\ntemplate <typename T>\nbool\nov_range<T>::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n#if defined (HAVE_HDF5)\n  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, false);\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n\n  return false;\n#endif\n}\n\n// For now, enable only ov_range<double>.\n\n/*\n%!testif HAVE_HDF5\n%! a = b = 1:4;\n%! sv_file = [tempname(), \".h5\"];\n%! unwind_protect\n%!   save (sv_file, \"a\", \"-hdf5\");\n%!   clear a;\n%!   load (sv_file);\n%!   assert (a, b);\n%! unwind_protect_cleanup\n%!   delete ([sv_file, '*']);\n%! end_unwind_protect\n\n%!testif HAVE_HDF5\n%! a = b = uint8(5):-1:0;\n%! sv_file = [tempname(), \".h5\"];\n%! unwind_protect\n%!   save (sv_file, \"a\", \"-hdf5\");\n%!   clear a;\n%!   load (sv_file);\n%!   assert (a, b);\n%! unwind_protect_cleanup\n%!   delete ([sv_file, '*']);\n%! end_unwind_protect\n*/\n\ntemplate <typename T>\nmxArray *\nov_range<T>::as_mxArray (bool interleaved) const\n{\n  mxClassID mx_class = mx_type_traits<T>::mx_class;\n\n  mxArray *retval = new mxArray (interleaved, mx_class, dims (), mxREAL);\n\n  typedef typename mx_type_traits<T>::mx_type mx_type;\n  mx_type *pd = static_cast<mx_type *> (retval->get_data ());\n\n  mwSize nel = numel ();\n\n  Array<T> matrix = raw_array_value ();\n\n  const T *pdata = matrix.data ();\n\n  for (mwSize i = 0; i < nel; i++)\n    pd[i] = pdata[i];\n\n  return retval;\n}\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA  (octave_trivial_range,\n                                      \"trivial range\", \"double\");\n\ntemplate <typename T>\nbool\nov_range<T>::could_be_trivial_range () { return false; }\n\ntemplate <>\nbool\nov_range<double>::could_be_trivial_range ()\n{\n  octave_idx_type n = m_range.numel ();\n  if (n > std::numeric_limits<int>::max())\n    return false;\n  if (n <= 1)\n    return false;\n\n  if (m_range.final_value () > std::numeric_limits<int>::max ()\n      || m_range.final_value () < std::numeric_limits<int>::min ())\n    return false;\n  if (m_range.increment () > std::numeric_limits<int>::max ()\n      || m_range.increment () < std::numeric_limits<int>::min ())\n    return false;\n  if (m_range.base () > std::numeric_limits<int>::max ()\n      || m_range.base () < std::numeric_limits<int>::min ())\n    return false;\n  if (m_range.limit () > std::numeric_limits<int>::max ()\n      || m_range.limit () < std::numeric_limits<int>::min ())\n    return false;\n\n  if (std::isnan (m_range.final_value ()))\n    return false;\n  if (std::isnan (m_range.increment ()))\n    return false;\n  if (std::isnan (m_range.base ()))\n    return false;\n  if (std::isnan (m_range.limit ()))\n    return false;\n\n  if (static_cast<int> (m_range.final_value ()) != m_range.final_value ())\n    return false;\n  if (static_cast<int> (m_range.increment ()) != m_range.increment ())\n    return false;\n  if (static_cast<int> (m_range.base ()) != m_range.base ())\n    return false;\n  if (static_cast<int> (m_range.limit ()) != m_range.limit ())\n    return false;\n\n  if (m_range.reverse ())\n    return false;\n\n  return true;\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::as_trivial_range ()\n{\n  error (\"Type error returning trivial range\");\n}\n\ntemplate <>\noctave_value\nov_range<double>::as_trivial_range ()\n{\n  return octave_value (new octave_trivial_range (m_range.numel (), m_range.base (), m_range.increment ()));\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::fast_elem_extract (octave_idx_type n) const\n{\n  return (n < numel () ? octave_value (m_range.elem (n)) : octave_value ());\n}\n\n// Specializations.\n\ntemplate <>\noctave::range<double>\nov_range<double>::range_value () const\n{\n  return m_range;\n}\n\ntemplate <typename T>\noctave_value\nov_range<T>::vm_extract_forloop_value (octave_idx_type n)\n{\n  octave_value ov = octave_value_factory::make (m_range.elem (n));\n\n  return ov.as_double_or_copy ();\n}\n\ntemplate <>\noctave_value\nov_range<double>::vm_extract_forloop_value (octave_idx_type n)\n{\n  octave_value ov = octave_value_factory::make (m_range.elem (n));\n\n  return ov;\n}\n\n// For now, enable only ov_range<double>.\n\ntemplate <>\noctave::idx_vector\nov_range<double>::index_vector (bool require_integers) const\n{\n  if (m_idx_cache)\n    return *m_idx_cache;\n\n  if (require_integers || m_range.all_elements_are_ints ())\n    return set_idx_cache (octave::idx_vector (m_range));\n\n  warning_with_id (\"Octave:noninteger-range-as-index\",\n                   \"non-integer range used as index\");\n\n  return octave_value (matrix_value ()).round ().index_vector ();\n}\n\ntemplate <>\noctave_idx_type\nov_range<double>::nnz () const\n{\n  return m_range.nnz ();\n}\n\n// The following specialization is also historical baggage.  For double\n// ranges, we can produce special double-valued diagnoal matrix objects\n// but Octave currently provides only double and Complex diagonal matrix\n// objects.\n\ntemplate <>\noctave_value\nov_range<double>::diag (octave_idx_type k) const\n{\n  // FIXME: this is a potential waste of memory.\n\n  return\n    (k == 0\n     ? octave_value (DiagMatrix (DiagArray2<double> (matrix_value ())))\n     : octave_value (m_range.diag (k)));\n}\n\ntemplate <>\noctave_value\nov_range<double>::diag (octave_idx_type nr, octave_idx_type nc) const\n{\n  Matrix mat = matrix_value ();\n\n  return mat.diag (nr, nc);\n}\n\ntemplate <>\nvoid\nov_range<double>::print_raw (std::ostream& os, bool pr_as_read_syntax) const\n{\n  octave_print_internal (os, m_range, pr_as_read_syntax,\n                         current_print_indent_level ());\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-range.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_range_h)\n#define octave_ov_range_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n#include <type_traits>\n\n#include \"Array.h\"\n#include \"Range.h\"\n\n#include \"mappers.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-range-traits.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n\nclass octave_trivial_range : public octave_base_value\n{\npublic:\n\n  octave_trivial_range (octave_idx_type numel, int base, int incr)\n    : m_numel (numel), m_base (base), m_increment(incr) { }\n\n  octave_trivial_range () { }\n\n  octave_trivial_range (const octave_trivial_range&) = default;\n\n  OCTINTERP_API octave_value\n  vm_extract_forloop_value (octave_idx_type i)\n  {\n    if (i < m_numel - 1)\n      return m_base + static_cast<int> (i) * m_increment;\n    return m_base + (m_numel - 1) * m_increment;\n  }\n\n  double\n  vm_extract_forloop_double (octave_idx_type i)\n  {\n    if (i < m_numel - 1)\n      return m_base + static_cast<int> (i) * m_increment;\n    return m_base + (m_numel - 1) * m_increment;\n  }\n\n  bool is_trivial_range () const { return true; };\n\nprivate:\n  int m_numel = 0;\n  int m_base = 0;\n  int m_increment = 0;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n// For now, we only need ov_range<double> but we don't attempt to\n// enforce that restriction.\n\ntemplate <typename T>\nclass ov_range : public octave_base_value\n{\npublic:\n\n  ov_range ()\n    : octave_base_value (), m_range (), m_idx_cache () { }\n\n  ov_range (const octave::range<T>& r)\n    : octave_base_value (), m_range (r), m_idx_cache ()\n  {\n    if (numel () < 0 && numel () != -2)\n      error (\"invalid range\");\n  }\n\n  ov_range (const ov_range<T>& r)\n    : octave_base_value (), m_range (r.m_range),\n      m_idx_cache (r.m_idx_cache\n                   ? new octave::idx_vector (*r.m_idx_cache) : nullptr)\n  { }\n\n  ov_range (const octave::range<T>& r, const octave::idx_vector& cache)\n    : octave_base_value (), m_range (r), m_idx_cache ()\n  {\n    set_idx_cache (cache);\n  }\n\n  // No assignment.\n  ov_range& operator = (const ov_range&) = delete;\n\n  ~ov_range () { clear_cached_info (); }\n\n  octave_base_value * clone () const\n  {\n    return new ov_range (*this);\n  }\n\n  // A range is really just a special kind of real matrix object.  In\n  // the places where we need to call empty_clone, it makes more sense\n  // to create an empty matrix (0x0) instead of an empty range (1x0).\n\n  octave_base_value * empty_clone () const\n  {\n    return new typename octave_value_range_traits<T>::matrix_type ();\n  }\n\n  OCTINTERP_API type_conv_info numeric_conversion_function () const;\n\n  OCTINTERP_API octave_base_value * try_narrowing_conversion ();\n\n  builtin_type_t builtin_type () const { return class_to_btyp<T>::btyp; }\n\n  // We don't need to override all three forms of subsref.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_value::subsref;\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx);\n\n  octave_value_list subsref (const std::string& type,\n                             const std::list<octave_value_list>& idx, int)\n  { return subsref (type, idx); }\n\n  OCTINTERP_API octave_value\n  do_index_op (const octave_value_list& idx, bool resize_ok = false);\n\n  OCTINTERP_API octave::idx_vector index_vector (bool require_integers = false) const;\n\n  dim_vector dims () const\n  {\n    octave_idx_type n = numel ();\n    return dim_vector (n > 0, n);\n  }\n\n  OCTINTERP_API octave_value as_trivial_range ();\n  OCTINTERP_API bool could_be_trivial_range ();\n\n  OCTINTERP_API octave_value\n  vm_extract_forloop_value (octave_idx_type idx);\n\n  octave_idx_type numel () const { return m_range.numel (); }\n\n  octave_idx_type nnz () const\n  {\n    // FIXME: this is a potential waste of memory.\n\n    octave_value tmp (raw_array_value ());\n    return tmp.nnz ();\n  }\n\n  OCTINTERP_API octave_value\n  resize (const dim_vector& dv, bool fill = false) const;\n\n  std::size_t byte_size () const { return 3 * sizeof (T); }\n\n  octave_value reshape (const dim_vector& new_dims) const\n  {\n    return raw_array_value ().reshape (new_dims);\n  }\n\n  octave_value permute (const Array<int>& vec, bool inv = false) const\n  {\n    return raw_array_value ().permute (vec, inv);\n  }\n\n  octave_value squeeze () const { return m_range; }\n\n  octave_value full_value () const { return raw_array_value (); }\n\n  bool is_defined () const { return true; }\n\n  bool is_storable () const { return m_range.is_storable (); }\n\n  bool is_constant () const { return true; }\n\n  bool is_range () const { return true; }\n\n  bool vm_need_storable_call () const { return true; }\n\n  bool is_double_type () const { return builtin_type () == btyp_double; }\n\n  bool is_single_type () const { return builtin_type () == btyp_float; }\n\n  bool isfloat () const { return btyp_isfloat (builtin_type ()); }\n\n  bool is_int8_type () const { return builtin_type () == btyp_int8; }\n\n  bool is_int16_type () const { return builtin_type () == btyp_int16; }\n\n  bool is_int32_type () const { return builtin_type () == btyp_int32; }\n\n  bool is_int64_type () const { return builtin_type () == btyp_int64; }\n\n  bool is_uint8_type () const { return builtin_type () == btyp_uint8; }\n\n  bool is_uint16_type () const { return builtin_type () == btyp_uint16; }\n\n  bool is_uint32_type () const { return builtin_type () == btyp_uint32; }\n\n  bool is_uint64_type () const { return builtin_type () == btyp_uint64; }\n\n  bool isinteger () const\n  {\n    return btyp_isinteger (builtin_type ());\n  }\n\n  bool isreal () const { return true; }\n\n  bool isnumeric () const\n  {\n    return btyp_isnumeric (builtin_type ());\n  }\n\n  bool is_true () const { return nnz () == numel (); }\n\n  octave_value all (int dim = 0) const\n  {\n    // FIXME: this is a potential waste of memory.\n\n    typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;\n    typename ov_mx_type::object_type m (raw_array_value ());\n\n    return m.all (dim);\n  }\n\n  octave_value any (int dim = 0) const\n  {\n    // FIXME: this is a potential waste of memory.\n\n    typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;\n    typename ov_mx_type::object_type m (raw_array_value ());\n\n    return m.any (dim);\n  }\n\n  octave_value diag (octave_idx_type k = 0) const\n  {\n    // FIXME: this is a potential waste of memory.\n\n    return m_range.diag (k);\n  }\n\n  octave_value diag (octave_idx_type nr, octave_idx_type nc) const\n  {\n    // FIXME: this is a potential waste of memory.\n\n    typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;\n    typename ov_mx_type::object_type m (raw_array_value ());\n\n    return m.diag (nr, nc);\n  }\n\n  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const\n  {\n    Array<T> tmp = raw_array_value ();\n    return tmp.sort (dim, mode);\n  }\n\n  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n                     sortmode mode = ASCENDING) const\n  {\n    Array<T> tmp = raw_array_value ();\n    return tmp.sort (sidx, dim, mode);\n  }\n\n  sortmode issorted (sortmode mode = UNSORTED) const\n  {\n    return m_range.issorted (mode);\n  }\n\n  Array<octave_idx_type> sort_rows_idx (sortmode) const\n  {\n    return Array<octave_idx_type> (dim_vector (1, 0));\n  }\n\n  sortmode is_sorted_rows (sortmode mode = UNSORTED) const\n  {\n    return (mode == UNSORTED) ? ASCENDING : mode;\n  }\n\n  Array<T> raw_array_value () const { return m_range.array_value (); }\n\n  OCTINTERP_API double double_value (bool = false) const;\n\n  OCTINTERP_API float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  {\n    return double_value (frc_str_conv);\n  }\n\n  float float_scalar_value (bool frc_str_conv = false) const\n  {\n    return float_value (frc_str_conv);\n  }\n\n  Matrix matrix_value (bool = false) const\n  {\n    return raw_array_value ();\n  }\n\n  FloatMatrix float_matrix_value (bool = false) const\n  {\n    return raw_array_value ();\n  }\n\n  NDArray array_value (bool = false) const\n  {\n    return raw_array_value ();\n  }\n\n  FloatNDArray float_array_value (bool = false) const\n  {\n    return raw_array_value ();\n  }\n\n  OCTINTERP_API charNDArray char_array_value (bool = false) const;\n\n  // FIXME: it would be better to have Range::intXNDArray_value\n  // functions to avoid the intermediate conversion to a matrix\n  // object.\n\n  int8NDArray int8_array_value () const\n  {\n    return raw_array_value ();\n  }\n\n  int16NDArray int16_array_value () const\n  {\n    return raw_array_value ();\n  }\n\n  int32NDArray int32_array_value () const\n  {\n    return raw_array_value ();\n  }\n\n  int64NDArray int64_array_value () const\n  {\n    return raw_array_value ();\n  }\n\n  uint8NDArray uint8_array_value () const\n  {\n    return raw_array_value ();\n  }\n\n  uint16NDArray uint16_array_value () const\n  {\n    return raw_array_value ();\n  }\n\n  uint32NDArray uint32_array_value () const\n  {\n    return raw_array_value ();\n  }\n\n  uint64NDArray uint64_array_value () const\n  {\n    return raw_array_value ();\n  }\n\n  SparseMatrix sparse_matrix_value (bool = false) const\n  {\n    return SparseMatrix (matrix_value ());\n  }\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  {\n    return SparseComplexMatrix (complex_matrix_value ());\n  }\n\n  OCTINTERP_API Complex complex_value (bool = false) const;\n\n  OCTINTERP_API FloatComplex float_complex_value (bool = false) const;\n\n  OCTINTERP_API boolNDArray bool_array_value (bool warn = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const\n  {\n    return raw_array_value ();\n  }\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const\n  {\n    return raw_array_value ();\n  }\n\n  ComplexNDArray complex_array_value (bool = false) const\n  {\n    return raw_array_value ();\n  }\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const\n  {\n    return raw_array_value ();\n  }\n\n  OCTINTERP_API octave::range<double> range_value () const;\n\n// For now, enable only ov_range<double>.\n\n  OCTINTERP_API octave_value\n  convert_to_str_internal (bool pad, bool force, char type) const;\n\n  OCTINTERP_API octave_value as_double () const;\n  OCTINTERP_API octave_value as_single () const;\n\n  OCTINTERP_API octave_value as_int8 () const;\n  OCTINTERP_API octave_value as_int16 () const;\n  OCTINTERP_API octave_value as_int32 () const;\n  OCTINTERP_API octave_value as_int64 () const;\n\n  OCTINTERP_API octave_value as_uint8 () const;\n  OCTINTERP_API octave_value as_uint16 () const;\n  OCTINTERP_API octave_value as_uint32 () const;\n  OCTINTERP_API octave_value as_uint64 () const;\n\n  OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  OCTINTERP_API void\n  print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  OCTINTERP_API bool\n  print_name_tag (std::ostream& os, const std::string& name) const;\n\n  OCTINTERP_API void short_disp (std::ostream& os) const;\n\n  OCTINTERP_API float_display_format get_edit_display_format () const;\n\n  OCTINTERP_API std::string\n  edit_display (const float_display_format& fmt,\n                octave_idx_type i, octave_idx_type j) const;\n\n  OCTINTERP_API bool save_ascii (std::ostream& os);\n\n  OCTINTERP_API bool load_ascii (std::istream& is);\n\n  OCTINTERP_API bool save_binary (std::ostream& os, bool save_as_floats);\n\n  OCTINTERP_API bool\n  load_binary (std::istream& is, bool swap,\n               octave::mach_info::float_format fmt);\n\n  OCTINTERP_API bool\n  save_hdf5 (octave_hdf5_id loc_id, const char *name, bool flag);\n\n  OCTINTERP_API bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    // FIXME: could be more memory efficient by having a\n    // special case of the octave::stream::write method for ranges.\n\n    return os.write (matrix_value (), block_size, output_type, skip, flt_fmt);\n  }\n\n  OCTINTERP_API mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const\n  {\n    octave_value tmp (raw_array_value ());\n    return tmp.map (umap);\n  }\n\n  OCTINTERP_API octave_value fast_elem_extract (octave_idx_type n) const;\n\nprotected:\n\n  octave::range<T> m_range;\n\n  octave::idx_vector set_idx_cache (const octave::idx_vector& idx) const\n  {\n    delete m_idx_cache;\n    m_idx_cache = new octave::idx_vector (idx);\n    return idx;\n  }\n\n  void clear_cached_info () const\n  {\n    delete m_idx_cache; m_idx_cache = nullptr;\n  }\n\n  mutable octave::idx_vector *m_idx_cache;\n\n  static octave_hdf5_id hdf5_save_type;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\nDECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS_API (ov_range, double, OCTINTERP_API)\n\n// For now, enable only ov_range<double>.\n\n// Specializations.\n\ntemplate <>\nOCTINTERP_API octave::range<double>\nov_range<double>::range_value () const;\n\n// For now, enable only ov_range<double>.\n\n// The following specializations are here to preserve previous Range\n// performance until solutions can be generalized for other types.\n\ntemplate <>\nOCTINTERP_API octave::idx_vector\nov_range<double>::index_vector (bool require_integers) const;\n\ntemplate <>\nOCTINTERP_API octave_idx_type\nov_range<double>::nnz () const;\n\n// The following specialization is also historical baggage.  For double\n// ranges, we can produce special double-valued diagnoal matrix objects\n// but Octave currently provides only double and Complex diagonal matrix\n// objects.\n\ntemplate <>\nOCTINTERP_API octave_value\nov_range<double>::diag (octave_idx_type k) const;\n\ntemplate <>\nOCTINTERP_API octave_value\nov_range<double>::diag (octave_idx_type nr, octave_idx_type nc) const;\n\ntemplate <>\nOCTINTERP_API void\nov_range<double>::print_raw (std::ostream& os, bool pr_as_read_syntax) const;\n\ntypedef ov_range<double> octave_double_range;\n\n// For now, enable only ov_range<double>.\n\ntypedef octave_double_range octave_range;\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-re-diag.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"byte-swap.h\"\n\n#include \"ov-re-diag.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-scalar.h\"\n#include \"ls-utils.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_diag_matrix, \"diagonal matrix\",\n                                     \"double\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  const octave_diag_matrix& v = dynamic_cast<const octave_diag_matrix&> (a);\n\n  return new octave_matrix (v.matrix_value ());\n}\n\noctave_base_value::type_conv_info\noctave_diag_matrix::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n         octave_matrix::static_type_id ());\n}\n\nstatic octave_base_value *\ndefault_numeric_demotion_function (const octave_base_value& a)\n{\n  const octave_diag_matrix& v = dynamic_cast<const octave_diag_matrix&> (a);\n\n  return new octave_float_diag_matrix (v.float_diag_matrix_value ());\n}\n\noctave_base_value::type_conv_info\noctave_diag_matrix::numeric_demotion_function () const\n{\n  return octave_base_value::type_conv_info\n         (default_numeric_demotion_function,\n          octave_float_diag_matrix::static_type_id ());\n}\n\noctave_base_value *\noctave_diag_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.nelem () == 1)\n    retval = new octave_scalar (m_matrix (0, 0));\n\n  return retval;\n}\n\noctave_value\noctave_diag_matrix::do_index_op (const octave_value_list& idx,\n                                 bool resize_ok)\n{\n  octave_value retval;\n\n  // This hack is to allow constructing permutation matrices using\n  // eye(n)(p,:), eye(n)(:,q) && eye(n)(p,q) where p & q are permutation\n  // vectors.\n  if (! resize_ok && idx.length () == 2 && m_matrix.is_multiple_of_identity (1))\n    {\n      int k = 0;        // index we're accessing when index_vector throws\n      try\n        {\n          octave::idx_vector idx0 = idx(0).index_vector ();\n          k = 1;\n          octave::idx_vector idx1 = idx(1).index_vector ();\n\n          bool left = idx0.is_permutation (m_matrix.rows ());\n          bool right = idx1.is_permutation (m_matrix.cols ());\n\n          if (left && right)\n            {\n              if (idx0.is_colon ()) left = false;\n              if (idx1.is_colon ()) right = false;\n              if (left && right)\n                retval = PermMatrix (idx0, false) * PermMatrix (idx1, true);\n              else if (left)\n                retval = PermMatrix (idx0, false);\n              else if (right)\n                retval = PermMatrix (idx1, true);\n              else\n                {\n                  retval = this;\n                  this->m_count++;\n                }\n            }\n        }\n      catch (octave::index_exception& ie)\n        {\n          // Rethrow to allow more info to be reported later.\n          ie.set_pos_if_unset (2, k+1);\n          throw;\n        }\n    }\n\n  if (retval.is_undefined ())\n    retval = octave_base_diag<DiagMatrix, Matrix>::do_index_op (idx, resize_ok);\n\n  return retval;\n}\n\nDiagMatrix\noctave_diag_matrix::diag_matrix_value (bool) const\n{\n  return m_matrix;\n}\n\nFloatDiagMatrix\noctave_diag_matrix::float_diag_matrix_value (bool) const\n{\n  return FloatDiagMatrix (m_matrix);\n}\n\nComplexDiagMatrix\noctave_diag_matrix::complex_diag_matrix_value (bool) const\n{\n  return ComplexDiagMatrix (m_matrix);\n}\n\nFloatComplexDiagMatrix\noctave_diag_matrix::float_complex_diag_matrix_value (bool) const\n{\n  return FloatComplexDiagMatrix (m_matrix);\n}\n\noctave_value\noctave_diag_matrix::as_double () const\n{\n  return m_matrix;\n}\n\noctave_value\noctave_diag_matrix::as_single () const\n{\n  return FloatDiagMatrix (m_matrix);\n}\n\noctave_value\noctave_diag_matrix::as_int8 () const\n{\n  return int8_array_value ();\n}\n\noctave_value\noctave_diag_matrix::as_int16 () const\n{\n  return int16_array_value ();\n}\n\noctave_value\noctave_diag_matrix::as_int32 () const\n{\n  return int32_array_value ();\n}\n\noctave_value\noctave_diag_matrix::as_int64 () const\n{\n  return int64_array_value ();\n}\n\noctave_value\noctave_diag_matrix::as_uint8 () const\n{\n  return uint8_array_value ();\n}\n\noctave_value\noctave_diag_matrix::as_uint16 () const\n{\n  return uint16_array_value ();\n}\n\noctave_value\noctave_diag_matrix::as_uint32 () const\n{\n  return uint32_array_value ();\n}\n\noctave_value\noctave_diag_matrix::as_uint64 () const\n{\n  return uint64_array_value ();\n}\n\noctave_value\noctave_diag_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    case umap_abs:\n      return m_matrix.abs ();\n    case umap_real:\n    case umap_conj:\n      return m_matrix;\n    case umap_imag:\n      return DiagMatrix (m_matrix.rows (), m_matrix.cols (), 0.0);\n    case umap_sqrt:\n      {\n        ComplexColumnVector tmp;\n        tmp = m_matrix.extract_diag ().map<Complex> (octave::math::rc_sqrt);\n        ComplexDiagMatrix retval (tmp);\n        retval.resize (m_matrix.rows (), m_matrix.columns ());\n        return retval;\n      }\n    default:\n      return to_dense ().map (umap);\n    }\n}\n\nbool\noctave_diag_matrix::save_binary (std::ostream& os, bool save_as_floats)\n{\n\n  int32_t r = m_matrix.rows ();\n  int32_t c = m_matrix.cols ();\n  os.write (reinterpret_cast<char *> (&r), 4);\n  os.write (reinterpret_cast<char *> (&c), 4);\n\n  Matrix m = Matrix (m_matrix.extract_diag ());\n  save_type st = LS_DOUBLE;\n  if (save_as_floats)\n    {\n      if (m.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        st = LS_FLOAT;\n    }\n  else if (m_matrix.length () > 8192) // FIXME: make this configurable.\n    {\n      double max_val, min_val;\n      if (m.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  const double *mtmp = m.data ();\n  write_doubles (os, mtmp, st, m.numel ());\n\n  return true;\n}\n\nbool\noctave_diag_matrix::load_binary (std::istream& is, bool swap,\n                                 octave::mach_info::float_format fmt)\n{\n  int32_t r, c;\n  char tmp;\n  if (! (is.read (reinterpret_cast<char *> (&r), 4)\n         && is.read (reinterpret_cast<char *> (&c), 4)\n         && is.read (reinterpret_cast<char *> (&tmp), 1)))\n    return false;\n  if (swap)\n    {\n      swap_bytes<4> (&r);\n      swap_bytes<4> (&c);\n    }\n\n  DiagMatrix m (r, c);\n  double *re = m.rwdata ();\n  octave_idx_type len = m.length ();\n  read_doubles (is, re, static_cast<save_type> (tmp), len, swap, fmt);\n\n  if (! is)\n    return false;\n\n  m_matrix = m;\n\n  return true;\n}\n\nbool\noctave_diag_matrix::chk_valid_scalar (const octave_value& val,\n                                      double& x) const\n{\n  bool retval = val.is_real_scalar ();\n  if (retval)\n    x = val.double_value ();\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-re-diag.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_re_diag_h)\n#define octave_ov_re_diag_h 1\n\n#include \"octave-config.h\"\n\n#include \"ov-base.h\"\n#include \"ov-base-diag.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n\n// Real diagonal matrix values.\n\nextern template class OCTINTERP_API\noctave_base_diag<DiagMatrix, Matrix>;\n\nclass OCTINTERP_API octave_diag_matrix\n  : public octave_base_diag<DiagMatrix, Matrix>\n{\npublic:\n\n  octave_diag_matrix ()\n    : octave_base_diag<DiagMatrix, Matrix> () { }\n\n  octave_diag_matrix (const DiagMatrix& m)\n    : octave_base_diag<DiagMatrix, Matrix> (m) { }\n\n  octave_diag_matrix (const octave_diag_matrix& m)\n    : octave_base_diag<DiagMatrix, Matrix> (m) { }\n\n  ~octave_diag_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_diag_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_diag_matrix (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  type_conv_info numeric_demotion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  builtin_type_t builtin_type () const { return btyp_double; }\n\n  bool is_real_matrix () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  DiagMatrix diag_matrix_value (bool = false) const;\n\n  FloatDiagMatrix float_diag_matrix_value (bool = false) const;\n\n  ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;\n\n  FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  bool chk_valid_scalar (const octave_value&,\n                         double&) const;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-re-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <clocale>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n#include \"int16NDArray.h\"\n#include \"int32NDArray.h\"\n#include \"int64NDArray.h\"\n#include \"int8NDArray.h\"\n#include \"uint16NDArray.h\"\n#include \"uint32NDArray.h\"\n#include \"uint64NDArray.h\"\n#include \"uint8NDArray.h\"\n\n#include \"data-conv.h\"\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"mx-base.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-specfun.h\"\n#include \"quit.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n#include \"ov-scalar.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-re-diag.h\"\n#include \"ov-cx-diag.h\"\n#include \"ov-lazy-idx.h\"\n#include \"ov-perm.h\"\n#include \"pr-flt-fmt.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_matrix, \"matrix\", \"double\");\n\nstatic octave_base_value *\ndefault_numeric_demotion_function (const octave_base_value& a)\n{\n  const octave_matrix& v = dynamic_cast<const octave_matrix&> (a);\n\n  return new octave_float_matrix (v.float_array_value ());\n}\n\noctave_base_value::type_conv_info\noctave_matrix::numeric_demotion_function () const\n{\n  return octave_base_value::type_conv_info\n         (default_numeric_demotion_function,\n          octave_float_matrix::static_type_id ());\n}\n\noctave_base_value *\noctave_matrix::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (m_matrix.numel () == 1)\n    retval = new octave_scalar (m_matrix (0));\n\n  return retval;\n}\n\ndouble\noctave_matrix::double_value (bool) const\n{\n  if (isempty ())\n    err_invalid_conversion (\"real matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"real matrix\", \"real scalar\");\n\n  return m_matrix(0, 0);\n}\n\nfloat\noctave_matrix::float_value (bool) const\n{\n  if (isempty ())\n    err_invalid_conversion (\"real matrix\", \"real scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"real matrix\", \"real scalar\");\n\n  return m_matrix(0, 0);\n}\n\n// FIXME\n\nMatrix\noctave_matrix::matrix_value (bool) const\n{\n  return Matrix (m_matrix);\n}\n\nFloatMatrix\noctave_matrix::float_matrix_value (bool) const\n{\n  return FloatMatrix (Matrix (m_matrix));\n}\n\nComplex\noctave_matrix::complex_value (bool) const\n{\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"real matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"real matrix\", \"complex scalar\");\n\n  return Complex (m_matrix(0, 0), 0);\n}\n\nFloatComplex\noctave_matrix::float_complex_value (bool) const\n{\n  float tmp = lo_ieee_float_nan_value ();\n\n  FloatComplex retval (tmp, tmp);\n\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"real matrix\", \"complex scalar\");\n\n  warn_implicit_conversion (\"Octave:array-to-scalar\",\n                            \"real matrix\", \"complex scalar\");\n\n  retval = m_matrix(0, 0);\n\n  return retval;\n}\n\n// FIXME\n\nComplexMatrix\noctave_matrix::complex_matrix_value (bool) const\n{\n  return ComplexMatrix (Matrix (m_matrix));\n}\n\nFloatComplexMatrix\noctave_matrix::float_complex_matrix_value (bool) const\n{\n  return FloatComplexMatrix (Matrix (m_matrix));\n}\n\nComplexNDArray\noctave_matrix::complex_array_value (bool) const\n{\n  return ComplexNDArray (m_matrix);\n}\n\nFloatComplexNDArray\noctave_matrix::float_complex_array_value (bool) const\n{\n  return FloatComplexNDArray (m_matrix);\n}\n\nboolNDArray\noctave_matrix::bool_array_value (bool warn) const\n{\n  if (m_matrix.any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n  if (warn && m_matrix.any_element_not_one_or_zero ())\n    warn_logical_conversion ();\n\n  return boolNDArray (m_matrix);\n}\n\ncharNDArray\noctave_matrix::char_array_value (bool) const\n{\n  charNDArray retval (dims ());\n\n  octave_idx_type nel = numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    if (octave::math::isnan (m_matrix.elem (i)))\n      retval.elem (i) = 0;\n    else\n      retval.elem (i) = static_cast<char> (m_matrix.elem (i));\n\n  return retval;\n}\n\nSparseMatrix\noctave_matrix::sparse_matrix_value (bool) const\n{\n  return SparseMatrix (Matrix (m_matrix));\n}\n\nSparseComplexMatrix\noctave_matrix::sparse_complex_matrix_value (bool) const\n{\n  // FIXME: Need a SparseComplexMatrix (Matrix) constructor to make\n  // this function more efficient.  Then this should become\n  // return SparseComplexMatrix (matrix.matrix_value ());\n  return SparseComplexMatrix (sparse_matrix_value ());\n}\n\noctave_value\noctave_matrix::as_double () const\n{\n  return NDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::as_single () const\n{\n  return FloatNDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::as_int8 () const\n{\n  return int8NDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::as_int16 () const\n{\n  return int16NDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::as_int32 () const\n{\n  return int32NDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::as_int64 () const\n{\n  return int64NDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::as_uint8 () const\n{\n  return uint8NDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::as_uint16 () const\n{\n  return uint16NDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::as_uint32 () const\n{\n  return uint32NDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::as_uint64 () const\n{\n  return uint64NDArray (m_matrix);\n}\n\noctave_value\noctave_matrix::diag (octave_idx_type k) const\n{\n  octave_value retval;\n  if (k == 0 && m_matrix.ndims () == 2\n      && (m_matrix.rows () == 1 || m_matrix.columns () == 1))\n    retval = DiagMatrix (DiagArray2<double> (m_matrix));\n  else\n    retval = octave_base_matrix<NDArray>::diag (k);\n\n  return retval;\n}\n\noctave_value\noctave_matrix::diag (octave_idx_type m, octave_idx_type n) const\n{\n  if (m_matrix.ndims () != 2\n      || (m_matrix.rows () != 1 && m_matrix.columns () != 1))\n    error (\"diag: expecting vector argument\");\n\n  Matrix mat (m_matrix);\n\n  return mat.diag (m, n);\n}\n\n// We override these two functions to allow reshaping both\n// the matrix and the index cache.\noctave_value\noctave_matrix::reshape (const dim_vector& new_dims) const\n{\n  if (m_idx_cache)\n    {\n      return new octave_matrix (m_matrix.reshape (new_dims),\n                                octave::idx_vector (m_idx_cache->as_array ().reshape (new_dims),\n                                    m_idx_cache->extent (0)));\n    }\n  else\n    return octave_base_matrix<NDArray>::reshape (new_dims);\n}\n\noctave_value\noctave_matrix::squeeze () const\n{\n  if (m_idx_cache)\n    {\n      return new octave_matrix (m_matrix.squeeze (),\n                                octave::idx_vector (m_idx_cache->as_array ().squeeze (),\n                                    m_idx_cache->extent (0)));\n    }\n  else\n    return octave_base_matrix<NDArray>::squeeze ();\n}\n\noctave_value\noctave_matrix::sort (octave_idx_type dim, sortmode mode) const\n{\n  if (m_idx_cache)\n    {\n      // This is a valid index matrix, so sort via integers because it's\n      // generally more efficient.\n      return octave_lazy_index (*m_idx_cache).sort (dim, mode);\n    }\n  else\n    return octave_base_matrix<NDArray>::sort (dim, mode);\n}\n\noctave_value\noctave_matrix::sort (Array<octave_idx_type>& sidx, octave_idx_type dim,\n                     sortmode mode) const\n{\n  if (m_idx_cache)\n    {\n      // This is a valid index matrix, so sort via integers because it's\n      // generally more efficient.\n      return octave_lazy_index (*m_idx_cache).sort (sidx, dim, mode);\n    }\n  else\n    return octave_base_matrix<NDArray>::sort (sidx, dim, mode);\n}\n\nsortmode\noctave_matrix::issorted (sortmode mode) const\n{\n  if (m_idx_cache)\n    {\n      // This is a valid index matrix, so check via integers because it's\n      // generally more efficient.\n      return m_idx_cache->as_array ().issorted (mode);\n    }\n  else\n    return octave_base_matrix<NDArray>::issorted (mode);\n}\nArray<octave_idx_type>\noctave_matrix::sort_rows_idx (sortmode mode) const\n{\n  if (m_idx_cache)\n    {\n      // This is a valid index matrix, so sort via integers because it's\n      // generally more efficient.\n      return octave_lazy_index (*m_idx_cache).sort_rows_idx (mode);\n    }\n  else\n    return octave_base_matrix<NDArray>::sort_rows_idx (mode);\n}\n\nsortmode\noctave_matrix::is_sorted_rows (sortmode mode) const\n{\n  if (m_idx_cache)\n    {\n      // This is a valid index matrix, so check via integers because it's\n      // generally more efficient.\n      return m_idx_cache->as_array ().is_sorted_rows (mode);\n    }\n  else\n    return octave_base_matrix<NDArray>::is_sorted_rows (mode);\n}\n\noctave_value\noctave_matrix::convert_to_str_internal (bool, bool, char type) const\n{\n  octave_value retval;\n  const dim_vector& dv = dims ();\n  octave_idx_type nel = dv.numel ();\n\n  charNDArray chm (dv);\n\n  bool warned = false;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      octave_quit ();\n\n      double d = m_matrix(i);\n\n      if (octave::math::isnan (d))\n        octave::err_nan_to_character_conversion ();\n\n      int ival = octave::math::nint (d);\n\n      if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())\n        {\n          // FIXME: is there something better we could do?\n\n          ival = 0;\n\n          if (! warned)\n            {\n              ::warning (\"range error for conversion to character value\");\n              warned = true;\n            }\n        }\n\n      chm(i) = static_cast<char> (ival);\n    }\n\n  retval = octave_value (chm, type);\n\n  return retval;\n}\n\nbool\noctave_matrix::save_ascii (std::ostream& os)\n{\n  const dim_vector& dv = dims ();\n\n  if (dv.ndims () > 2)\n    {\n      NDArray tmp = array_value ();\n\n      os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n      for (int i=0; i < dv.ndims (); i++)\n        os << ' ' << dv(i);\n\n      os << \"\\n\" << tmp;\n    }\n  else\n    {\n      // Keep this case, rather than use generic code above for backward\n      // compatibility.  Makes load_ascii much more complex!!\n      os << \"# rows: \" << rows () << \"\\n\"\n         << \"# columns: \" << columns () << \"\\n\";\n\n      os << matrix_value ();\n    }\n\n  return true;\n}\n\nbool\noctave_matrix::load_ascii (std::istream& is)\n{\n  string_vector keywords(2);\n\n  keywords[0] = \"ndims\";\n  keywords[1] = \"rows\";\n\n  std::string kw;\n  octave_idx_type val = 0;\n\n  if (! extract_keyword (is, keywords, kw, val, true))\n    error (\"load: failed to extract number of rows and columns\");\n\n  // Set \"C\" locale for the duration of this function to avoid the performance\n  // panelty of frequently switching the locale when reading floating point\n  // values from the stream.\n  char *prev_locale = std::setlocale (LC_ALL, nullptr);\n  std::string old_locale (prev_locale ? prev_locale : \"\");\n  std::setlocale (LC_ALL, \"C\");\n  octave::unwind_action act\n  ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); });\n\n  if (kw == \"ndims\")\n    {\n      int mdims = static_cast<int> (val);\n\n      if (mdims < 0)\n        error (\"load: failed to extract number of dimensions\");\n\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        is >> dv(i);\n\n      if (! is)\n        error (\"load: failed to read dimensions\");\n\n      NDArray tmp(dv);\n\n      is >> tmp;\n\n      if (! is)\n        error (\"load: failed to load matrix constant\");\n\n      m_matrix = tmp;\n    }\n  else if (kw == \"rows\")\n    {\n      octave_idx_type nr = val;\n      octave_idx_type nc = 0;\n\n      if (nr < 0 || ! extract_keyword (is, \"columns\", nc) || nc < 0)\n        error (\"load: failed to extract number of rows and columns\");\n\n      if (nr > 0 && nc > 0)\n        {\n          Matrix tmp (nr, nc);\n          is >> tmp;\n          if (! is)\n            error (\"load: failed to load matrix constant\");\n\n          m_matrix = tmp;\n        }\n      else if (nr == 0 || nc == 0)\n        m_matrix = Matrix (nr, nc);\n      else\n        error (\"unexpected dimensions in octave_matrix::load_ascii - please report this bug\");\n    }\n  else\n    error (\"unexpected dimensions keyword (= '%s') octave_matrix::load_ascii - please report this bug\", kw.c_str ());\n\n  return true;\n}\n\nbool\noctave_matrix::save_binary (std::ostream& os, bool save_as_floats)\n{\n\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Use negative value for ndims to differentiate with old format!!\n  int32_t tmp = - dv.ndims ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  for (int i = 0; i < dv.ndims (); i++)\n    {\n      tmp = dv(i);\n      os.write (reinterpret_cast<char *> (&tmp), 4);\n    }\n\n  NDArray m = array_value ();\n  save_type st = LS_DOUBLE;\n  if (save_as_floats)\n    {\n      if (m.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        st = LS_FLOAT;\n    }\n  else if (dv.numel () > 8192) // FIXME: make this configurable.\n    {\n      double max_val, min_val;\n      if (m.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  const double *mtmp = m.data ();\n  write_doubles (os, mtmp, st, dv.numel ());\n\n  return true;\n}\n\nbool\noctave_matrix::load_binary (std::istream& is, bool swap,\n                            octave::mach_info::float_format fmt)\n{\n  char tmp;\n  int32_t mdims;\n  if (! is.read (reinterpret_cast<char *> (&mdims), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&mdims);\n  if (mdims < 0)\n    {\n      mdims = - mdims;\n      int32_t di;\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        {\n          if (! is.read (reinterpret_cast<char *> (&di), 4))\n            return false;\n          if (swap)\n            swap_bytes<4> (&di);\n          dv(i) = di;\n        }\n\n      // Convert an array with a single dimension to be a row vector.\n      // Octave should never write files like this, other software\n      // might.\n\n      if (mdims == 1)\n        {\n          mdims = 2;\n          dv.resize (mdims);\n          dv(1) = dv(0);\n          dv(0) = 1;\n        }\n\n      if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n        return false;\n\n      NDArray m(dv);\n      double *re = m.rwdata ();\n      read_doubles (is, re, static_cast<save_type> (tmp), dv.numel (),\n                    swap, fmt);\n\n      if (! is)\n        return false;\n\n      m_matrix = m;\n    }\n  else\n    {\n      int32_t nr, nc;\n      nr = mdims;\n      if (! is.read (reinterpret_cast<char *> (&nc), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&nc);\n      if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n        return false;\n      Matrix m (nr, nc);\n      double *re = m.rwdata ();\n      octave_idx_type len = static_cast<octave_idx_type> (nr) * nc;\n      read_doubles (is, re, static_cast<save_type> (tmp), len, swap, fmt);\n\n      if (! is)\n        return false;\n\n      m_matrix = m;\n    }\n  return true;\n}\n\nbool\noctave_matrix::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                          bool save_as_floats)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  int rank = dv.ndims ();\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n  NDArray m = array_value ();\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  for (int i = 0; i < rank; i++)\n    hdims[i] = dv(rank-i-1);\n\n  space_hid = H5Screate_simple (rank, hdims, nullptr);\n\n  if (space_hid < 0) return false;\n\n  hid_t save_type_hid = H5T_NATIVE_DOUBLE;\n\n  if (save_as_floats)\n    {\n      if (m.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        save_type_hid = H5T_NATIVE_FLOAT;\n    }\n#if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS)\n  // hdf5 currently doesn't support float/integer conversions\n  else\n    {\n      double max_val, min_val;\n\n      if (m.all_integers (max_val, min_val))\n        save_type_hid\n          = save_type_to_hdf5 (octave::get_save_type (max_val, min_val));\n    }\n#endif\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n\n  const double *mtmp = m.data ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL,\n                     octave_H5S_ALL, octave_H5P_DEFAULT, mtmp) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_matrix::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    m_matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank < 1)\n    {\n      H5Sclose (space_id);\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_id, hdims, maxdims);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  if (rank == 1)\n    {\n      dv.resize (2);\n      dv(0) = 1;\n      dv(1) = hdims[0];\n    }\n  else\n    {\n      dv.resize (rank);\n      for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)\n        dv(j) = hdims[i];\n    }\n\n  NDArray m (dv);\n  double *re = m.rwdata ();\n  if (H5Dread (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, re) >= 0)\n    {\n      retval = true;\n      m_matrix = m;\n    }\n\n  H5Sclose (space_id);\n  H5Dclose (data_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nvoid\noctave_matrix::print_raw (std::ostream& os,\n                          bool pr_as_read_syntax) const\n{\n  octave_print_internal (os, m_matrix, pr_as_read_syntax,\n                         current_print_indent_level ());\n}\n\nmxArray *\noctave_matrix::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, dims (), mxREAL);\n\n  mxDouble *pd = static_cast<mxDouble *> (retval->get_data ());\n\n  mwSize nel = numel ();\n\n  const double *pdata = m_matrix.data ();\n\n  for (mwIndex i = 0; i < nel; i++)\n    pd[i] = pdata[i];\n\n  return retval;\n}\n\n// This uses a smarter strategy for doing the complex->real mappers.  We\n// allocate an array for a real result and keep filling it until a complex\n// result is produced.\nstatic octave_value\ndo_rc_map (const NDArray& a, Complex (&fcn) (double))\n{\n  octave_idx_type n = a.numel ();\n  NDArray rr (a.dims ());\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      octave_quit ();\n\n      Complex tmp = fcn (a(i));\n      if (tmp.imag () == 0.0)\n        rr.xelem (i) = tmp.real ();\n      else\n        {\n          ComplexNDArray rc (a.dims ());\n\n          for (octave_idx_type j = 0; j < i; j++)\n            rc.xelem (j) = rr.xelem (j);\n\n          rc.xelem (i) = tmp;\n\n          for (octave_idx_type j = i+1; j < n; j++)\n            {\n              octave_quit ();\n\n              rc.xelem (j) = fcn (a(j));\n            }\n\n          return new octave_complex_matrix (rc);\n        }\n    }\n\n  return rr;\n}\n\noctave_value\noctave_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    case umap_imag:\n      return NDArray (m_matrix.dims (), 0.0);\n\n    case umap_real:\n    case umap_conj:\n      return m_matrix;\n\n      // Mappers handled specially.\n#define ARRAY_METHOD_MAPPER(UMAP, FCN)        \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (m_matrix.FCN ())\n\n      ARRAY_METHOD_MAPPER (abs, abs);\n      ARRAY_METHOD_MAPPER (isnan, isnan);\n      ARRAY_METHOD_MAPPER (isinf, isinf);\n      ARRAY_METHOD_MAPPER (isfinite, isfinite);\n\n#define ARRAY_MAPPER(UMAP, TYPE, FCN)                 \\\n    case umap_ ## UMAP:                               \\\n      return octave_value (m_matrix.map<TYPE> (FCN))\n\n#define RC_ARRAY_MAPPER(UMAP, TYPE, FCN)      \\\n    case umap_ ## UMAP:                       \\\n      return do_rc_map (m_matrix, FCN)\n\n      RC_ARRAY_MAPPER (acos, Complex, octave::math::rc_acos);\n      RC_ARRAY_MAPPER (acosh, Complex, octave::math::rc_acosh);\n      ARRAY_MAPPER (angle, double, std::arg);\n      ARRAY_MAPPER (arg, double, std::arg);\n      RC_ARRAY_MAPPER (asin, Complex, octave::math::rc_asin);\n      ARRAY_MAPPER (asinh, double, octave::math::asinh);\n      ARRAY_MAPPER (atan, double, ::atan);\n      RC_ARRAY_MAPPER (atanh, Complex, octave::math::rc_atanh);\n      ARRAY_MAPPER (erf, double, octave::math::erf);\n      ARRAY_MAPPER (erfinv, double, octave::math::erfinv);\n      ARRAY_MAPPER (erfcinv, double, octave::math::erfcinv);\n      ARRAY_MAPPER (erfc, double, octave::math::erfc);\n      ARRAY_MAPPER (erfcx, double, octave::math::erfcx);\n      ARRAY_MAPPER (erfi, double, octave::math::erfi);\n      ARRAY_MAPPER (dawson, double, octave::math::dawson);\n      ARRAY_MAPPER (gamma, double, octave::math::gamma);\n      RC_ARRAY_MAPPER (lgamma, Complex, octave::math::rc_lgamma);\n      ARRAY_MAPPER (cbrt, double, octave::math::cbrt);\n      ARRAY_MAPPER (ceil, double, ::ceil);\n      ARRAY_MAPPER (cos, double, ::cos);\n      ARRAY_MAPPER (cosh, double, ::cosh);\n      ARRAY_MAPPER (exp, double, ::exp);\n      ARRAY_MAPPER (expm1, double, octave::math::expm1);\n      ARRAY_MAPPER (fix, double, octave::math::fix);\n      ARRAY_MAPPER (floor, double, ::floor);\n      RC_ARRAY_MAPPER (log, Complex, octave::math::rc_log);\n      RC_ARRAY_MAPPER (log2, Complex, octave::math::rc_log2);\n      RC_ARRAY_MAPPER (log10, Complex, octave::math::rc_log10);\n      RC_ARRAY_MAPPER (log1p, Complex, octave::math::rc_log1p);\n      ARRAY_MAPPER (round, double, octave::math::round);\n      ARRAY_MAPPER (roundb, double, octave::math::roundb);\n      ARRAY_MAPPER (signum, double, octave::math::signum);\n      ARRAY_MAPPER (sin, double, ::sin);\n      ARRAY_MAPPER (sinh, double, ::sinh);\n      RC_ARRAY_MAPPER (sqrt, Complex, octave::math::rc_sqrt);\n      ARRAY_MAPPER (tan, double, ::tan);\n      ARRAY_MAPPER (tanh, double, ::tanh);\n      ARRAY_MAPPER (isna, bool, octave::math::isna);\n      ARRAY_MAPPER (xsignbit, double, octave::math::signbit);\n\n    // Special cases for Matlab compatibility.\n    case umap_xtolower:\n    case umap_xtoupper:\n      return m_matrix;\n\n    case umap_xisalnum:\n    case umap_xisalpha:\n    case umap_xisascii:\n    case umap_xiscntrl:\n    case umap_xisdigit:\n    case umap_xisgraph:\n    case umap_xislower:\n    case umap_xisprint:\n    case umap_xispunct:\n    case umap_xisspace:\n    case umap_xisupper:\n    case umap_xisxdigit:\n      {\n        octave_value str_conv = convert_to_str (true, true);\n        return str_conv.map (umap);\n      }\n\n    default:\n      return octave_base_value::map (umap);\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-re-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_re_mat_h)\n#define octave_ov_re_mat_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-base-mat.h\"\n#include \"ov-typeinfo.h\"\n\n#include \"MatrixType.h\"\n\nclass octave_value_list;\n\n// Real matrix values.\n\nextern template class OCTINTERP_API octave_base_matrix<NDArray>;\n\nclass OCTINTERP_API octave_matrix : public octave_base_matrix<NDArray>\n{\npublic:\n\n  octave_matrix ()\n    : octave_base_matrix<NDArray> () { }\n\n  octave_matrix (const Matrix& m)\n    : octave_base_matrix<NDArray> (m) { }\n\n  octave_matrix (const Matrix& m, const MatrixType& t)\n    : octave_base_matrix<NDArray> (m, t) { }\n\n  octave_matrix (const NDArray& nda)\n    : octave_base_matrix<NDArray> (nda) { }\n\n  octave_matrix (const Array<double>& m)\n    : octave_base_matrix<NDArray> (NDArray (m)) { }\n\n  octave_matrix (const DiagMatrix& d)\n    : octave_base_matrix<NDArray> (Matrix (d)) { }\n\n  octave_matrix (const RowVector& v)\n    : octave_base_matrix<NDArray> (Matrix (v)) { }\n\n  octave_matrix (const ColumnVector& v)\n    : octave_base_matrix<NDArray> (Matrix (v)) { }\n\n  octave_matrix (const octave_matrix& m)\n    : octave_base_matrix<NDArray> (m) { }\n\n  octave_matrix (const Array<octave_idx_type>& idx,\n                 bool zero_based = false, bool cache_index = false)\n    : octave_base_matrix<NDArray> (NDArray (idx, zero_based))\n  {\n    // Auto-create cache to speed up subsequent indexing.\n    if (zero_based && cache_index)\n      set_idx_cache (octave::idx_vector (idx));\n  }\n\n  octave_matrix (const NDArray& nda, const octave::idx_vector& cache)\n    : octave_base_matrix<NDArray> (nda)\n  {\n    set_idx_cache (cache);\n  }\n\n  ~octave_matrix () = default;\n\n  octave_base_value * clone () const { return new octave_matrix (*this); }\n  octave_base_value * empty_clone () const { return new octave_matrix (); }\n\n  type_conv_info numeric_demotion_function () const;\n\n  octave_base_value * try_narrowing_conversion ();\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  {\n    return m_idx_cache ? *m_idx_cache\n           : set_idx_cache (octave::idx_vector (m_matrix));\n  }\n\n  builtin_type_t builtin_type () const { return btyp_double; }\n\n  bool is_real_matrix () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  int8NDArray\n  int8_array_value () const { return int8NDArray (m_matrix); }\n\n  int16NDArray\n  int16_array_value () const { return int16NDArray (m_matrix); }\n\n  int32NDArray\n  int32_array_value () const { return int32NDArray (m_matrix); }\n\n  int64NDArray\n  int64_array_value () const { return int64NDArray (m_matrix); }\n\n  uint8NDArray\n  uint8_array_value () const { return uint8NDArray (m_matrix); }\n\n  uint16NDArray\n  uint16_array_value () const { return uint16NDArray (m_matrix); }\n\n  uint32NDArray\n  uint32_array_value () const { return uint32NDArray (m_matrix); }\n\n  uint64NDArray\n  uint64_array_value () const { return uint64NDArray (m_matrix); }\n\n  double double_value (bool = false) const;\n\n  float float_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  Matrix matrix_value (bool = false) const;\n\n  FloatMatrix float_matrix_value (bool = false) const;\n\n  Complex complex_value (bool = false) const;\n\n  FloatComplex float_complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const;\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const;\n\n  boolNDArray bool_array_value (bool warn = false) const;\n\n  charNDArray char_array_value (bool = false) const;\n\n  NDArray array_value (bool = false) const { return m_matrix; }\n\n  FloatNDArray float_array_value (bool = false) const { return m_matrix; }\n\n  SparseMatrix sparse_matrix_value (bool = false) const;\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;\n\n  octave_value all (int dim = 0) const { return m_matrix.all (dim); }\n  octave_value any (int dim = 0) const { return m_matrix.any (dim); }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  octave_value diag (octave_idx_type k = 0) const;\n\n  octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  octave_value reshape (const dim_vector& new_dims) const;\n\n  octave_value squeeze () const;\n\n  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;\n  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n                     sortmode mode = ASCENDING) const;\n\n  sortmode issorted (sortmode mode = UNSORTED) const;\n\n  Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const;\n\n  sortmode is_sorted_rows (sortmode mode = UNSORTED) const;\n\n  // Use matrix_ref here to clear index cache.\n  void increment () { matrix_ref () += 1.0; }\n\n  void decrement () { matrix_ref () -= 1.0; }\n\n  void changesign () { matrix_ref ().changesign (); }\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  { return os.write (m_matrix, block_size, output_type, skip, flt_fmt); }\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-re-sparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"mappers.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-specfun.h\"\n\n#include \"mxarray.h\"\n#include \"errwarn.h\"\n\n#include \"oct-hdf5.h\"\n#include \"ls-hdf5.h\"\n\n#include \"ov-re-sparse.h\"\n\n#include \"ov-base-sparse.h\"\n#include \"ov-base-sparse.cc\"\n\n#include \"ov-bool-sparse.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_sparse_matrix, \"sparse matrix\",\n                                     \"double\");\n\noctave::idx_vector\noctave_sparse_matrix::index_vector (bool /* require_integers */) const\n{\n  if (matrix.numel () == matrix.nnz ())\n    return octave::idx_vector (array_value ());\n  else\n    {\n      std::string nm = '<' + type_name () + '>';\n      octave::err_invalid_index (nm.c_str ());\n    }\n}\n\ndouble\noctave_sparse_matrix::double_value (bool) const\n{\n  if (isempty ())\n    err_invalid_conversion (\"real sparse matrix\", \"real scalar\");\n\n  if (numel () > 1)\n    warn_implicit_conversion (\"Octave:array-to-scalar\",\n                              \"real sparse matrix\", \"real scalar\");\n\n  return matrix(0, 0);\n}\n\nComplex\noctave_sparse_matrix::complex_value (bool) const\n{\n  // FIXME: maybe this should be a function, valid_as_scalar()\n  if (rows () == 0 || columns () == 0)\n    err_invalid_conversion (\"real sparse matrix\", \"complex scalar\");\n\n  if (numel () > 1)\n    warn_implicit_conversion (\"Octave:array-to-scalar\",\n                              \"real sparse matrix\", \"complex scalar\");\n\n  return Complex (matrix(0, 0), 0);\n}\n\nMatrix\noctave_sparse_matrix::matrix_value (bool) const\n{\n  return matrix.matrix_value ();\n}\n\nboolNDArray\noctave_sparse_matrix::bool_array_value (bool warn) const\n{\n  NDArray m = matrix.matrix_value ();\n\n  if (m.any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n  if (warn && m.any_element_not_one_or_zero ())\n    warn_logical_conversion ();\n\n  return boolNDArray (m);\n}\n\ncharNDArray\noctave_sparse_matrix::char_array_value (bool) const\n{\n  charNDArray retval (dims (), 0);\n  octave_idx_type nc = matrix.cols ();\n  octave_idx_type nr = matrix.rows ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = matrix.cidx (j); i < matrix.cidx (j+1); i++)\n      if (octave::math::isnan (matrix.data (i)))\n        retval(matrix.ridx (i) + nr * j) = 0;\n      else\n        retval(matrix.ridx (i) + nr * j) = static_cast<char> (matrix.data (i));\n\n  return retval;\n}\n\nComplexMatrix\noctave_sparse_matrix::complex_matrix_value (bool) const\n{\n  return ComplexMatrix (matrix.matrix_value ());\n}\n\nComplexNDArray\noctave_sparse_matrix::complex_array_value (bool) const\n{\n  return ComplexNDArray (ComplexMatrix (matrix.matrix_value ()));\n}\n\nNDArray\noctave_sparse_matrix::array_value (bool) const\n{\n  return NDArray (matrix.matrix_value ());\n}\n\nSparseBoolMatrix\noctave_sparse_matrix::sparse_bool_matrix_value (bool warn) const\n{\n  if (matrix.any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n  if (warn && matrix.any_element_not_one_or_zero ())\n    warn_logical_conversion ();\n\n  return mx_el_ne (matrix, 0.0);\n}\n\noctave_value\noctave_sparse_matrix::convert_to_str_internal (bool, bool, char type) const\n{\n  octave_value retval;\n  const dim_vector& dv = dims ();\n  octave_idx_type nel = dv.numel ();\n\n  if (nel == 0)\n    {\n      char s = '\\0';\n      retval = octave_value (&s, type);\n    }\n  else\n    {\n      octave_idx_type nr = matrix.rows ();\n      octave_idx_type nc = matrix.cols ();\n      charNDArray chm (dv, static_cast<char> (0));\n\n      bool warned = false;\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = matrix.cidx (j);\n             i < matrix.cidx (j+1); i++)\n          {\n            octave_quit ();\n\n            double d = matrix.data (i);\n\n            if (octave::math::isnan (d))\n              octave::err_nan_to_character_conversion ();\n\n            int ival = octave::math::nint (d);\n\n            if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())\n              {\n                // FIXME: is there something better we could do?\n\n                ival = 0;\n\n                if (! warned)\n                  {\n                    ::warning (\"range error for conversion to character value\");\n                    warned = true;\n                  }\n              }\n\n            chm(matrix.ridx (i) + j * nr) = static_cast<char> (ival);\n          }\n\n      retval = octave_value (chm, type);\n    }\n\n  return retval;\n}\n\noctave_value\noctave_sparse_matrix::as_double () const\n{\n  return this->matrix;\n}\n\nbool\noctave_sparse_matrix::save_binary (std::ostream& os, bool save_as_floats)\n{\n  const dim_vector& dv = this->dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Ensure that additional memory is deallocated\n  matrix.maybe_compress ();\n\n  int nr = dv(0);\n  int nc = dv(1);\n  int nz = nnz ();\n\n  int32_t itmp;\n  // Use negative value for ndims to be consistent with other formats\n  itmp = -2;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  itmp = nr;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  itmp = nc;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  itmp = nz;\n  os.write (reinterpret_cast<char *> (&itmp), 4);\n\n  save_type st = LS_DOUBLE;\n  if (save_as_floats)\n    {\n      if (matrix.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        st = LS_FLOAT;\n    }\n  else if (matrix.nnz () > 8192) // FIXME: make this configurable.\n    {\n      double max_val, min_val;\n      if (matrix.all_integers (max_val, min_val))\n        st = octave::get_save_type (max_val, min_val);\n    }\n\n  // add one to the printed indices to go from\n  // zero-based to one-based arrays\n  for (int i = 0; i < nc+1; i++)\n    {\n      octave_quit ();\n      itmp = matrix.cidx (i);\n      os.write (reinterpret_cast<char *> (&itmp), 4);\n    }\n\n  for (int i = 0; i < nz; i++)\n    {\n      octave_quit ();\n      itmp = matrix.ridx (i);\n      os.write (reinterpret_cast<char *> (&itmp), 4);\n    }\n\n  write_doubles (os, matrix.data (), st, nz);\n\n  return true;\n}\n\nbool\noctave_sparse_matrix::load_binary (std::istream& is, bool swap,\n                                   octave::mach_info::float_format fmt)\n{\n  int32_t nz, nc, nr, tmp;\n  char ctmp;\n\n  if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n    return false;\n\n  if (swap)\n    swap_bytes<4> (&tmp);\n\n  if (tmp != -2)\n    error (\"load: only 2-D sparse matrices are supported\");\n\n  if (! is.read (reinterpret_cast<char *> (&nr), 4))\n    return false;\n  if (! is.read (reinterpret_cast<char *> (&nc), 4))\n    return false;\n  if (! is.read (reinterpret_cast<char *> (&nz), 4))\n    return false;\n\n  if (swap)\n    {\n      swap_bytes<4> (&nr);\n      swap_bytes<4> (&nc);\n      swap_bytes<4> (&nz);\n    }\n\n  SparseMatrix m (static_cast<octave_idx_type> (nr),\n                  static_cast<octave_idx_type> (nc),\n                  static_cast<octave_idx_type> (nz));\n\n  for (int i = 0; i < nc+1; i++)\n    {\n      octave_quit ();\n      if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&tmp);\n      m.xcidx (i) = tmp;\n    }\n\n  for (int i = 0; i < nz; i++)\n    {\n      octave_quit ();\n      if (! is.read (reinterpret_cast<char *> (&tmp), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&tmp);\n      m.xridx (i) = tmp;\n    }\n\n  if (! is.read (reinterpret_cast<char *> (&ctmp), 1))\n    return false;\n\n  read_doubles (is, m.xdata (), static_cast<save_type> (ctmp), nz, swap, fmt);\n\n  if (! is)\n    return false;\n\n  if (! m.indices_ok ())\n    return false;\n\n  matrix = m;\n\n  return true;\n}\n\nbool\noctave_sparse_matrix::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                                 bool save_as_floats)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  // Ensure that additional memory is deallocated\n  matrix.maybe_compress ();\n\n#if defined (HAVE_HDF5_18)\n  hid_t group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT,\n                               octave_H5P_DEFAULT, octave_H5P_DEFAULT);\n#else\n  hid_t group_hid = H5Gcreate (loc_id, name, 0);\n#endif\n  if (group_hid < 0)\n    return false;\n\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n  SparseMatrix m = sparse_matrix_value ();\n  octave_idx_type tmp;\n  hsize_t hdims[2];\n\n  space_hid = H5Screate_simple (0, hdims, nullptr);\n  if (space_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nr\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nr\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  tmp = m.rows ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nc\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nc\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  tmp = m.cols ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"nz\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"nz\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  tmp = m.nnz ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, &tmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n\n  hdims[0] = m.cols () + 1;\n  hdims[1] = 1;\n\n  space_hid = H5Screate_simple (2, hdims, nullptr);\n\n  if (space_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"cidx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"cidx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  octave_idx_type *itmp = m.xcidx ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, itmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n\n  hdims[0] = m.nnz ();\n  hdims[1] = 1;\n\n  space_hid = H5Screate_simple (2, hdims, nullptr);\n\n  if (space_hid < 0)\n    {\n      H5Gclose (group_hid);\n      return false;\n    }\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"ridx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"ridx\", H5T_NATIVE_IDX, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  itmp = m.xridx ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, itmp) >= 0;\n  H5Dclose (data_hid);\n  if (! retval)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  hid_t save_type_hid = H5T_NATIVE_DOUBLE;\n\n  if (save_as_floats)\n    {\n      if (m.too_large_for_float ())\n        {\n          warning (\"save: some values too large to save as floats --\");\n          warning (\"save: saving as doubles instead\");\n        }\n      else\n        save_type_hid = H5T_NATIVE_FLOAT;\n    }\n#if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS)\n  // hdf5 currently doesn't support float/integer conversions\n  else\n    {\n      double max_val, min_val;\n\n      if (m.all_integers (max_val, min_val))\n        save_type_hid\n          = save_type_to_hdf5 (octave::get_save_type (max_val, min_val));\n    }\n#endif\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (group_hid, \"data\", save_type_hid, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (group_hid, \"data\", save_type_hid, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  double *dtmp = m.xdata ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL,\n                     octave_H5S_ALL, octave_H5P_DEFAULT, dtmp) >= 0;\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n  H5Gclose (group_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_sparse_matrix::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  octave_idx_type nr, nc, nz;\n  hid_t group_hid, data_hid, space_hid;\n  hsize_t rank;\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  group_hid = H5Gopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  group_hid = H5Gopen (loc_id, name);\n#endif\n  if (group_hid < 0) return false;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nr\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nr\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &nr) < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nc\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nc\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &nc) < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"nz\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"nz\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &nz) < 0)\n    {\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Dclose (data_hid);\n\n  SparseMatrix m (static_cast<octave_idx_type> (nr),\n                  static_cast<octave_idx_type> (nc),\n                  static_cast<octave_idx_type> (nz));\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"cidx\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"cidx\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  if (static_cast<int> (hdims[0]) != nc + 1\n      || static_cast<int> (hdims[1]) != 1)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  octave_idx_type *itmp = m.xcidx ();\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, itmp) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"ridx\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"ridx\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  if (static_cast<int> (hdims[0]) != nz || static_cast<int> (hdims[1]) != 1)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  itmp = m.xridx ();\n  if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, itmp) < 0)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dopen (group_hid, \"data\", octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dopen (group_hid, \"data\");\n#endif\n  space_hid = H5Dget_space (data_hid);\n  rank = H5Sget_simple_extent_ndims (space_hid);\n\n  if (rank != 2)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n  if (static_cast<int> (hdims[0]) != nz || static_cast<int> (hdims[1]) != 1)\n    {\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      H5Gclose (group_hid);\n      return false;\n    }\n\n  double *dtmp = m.xdata ();\n\n  if (H5Dread (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, dtmp) >= 0\n      && m.indices_ok ())\n    {\n      retval = true;\n      matrix = m;\n    }\n\n  H5Sclose (space_hid);\n  H5Dclose (data_hid);\n  H5Gclose (group_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nmxArray *\noctave_sparse_matrix::as_mxArray (bool interleaved) const\n{\n  mwSize nz = nzmax ();\n  mwSize nr = rows ();\n  mwSize nc = columns ();\n\n  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, nr, nc, nz,\n                                 mxREAL);\n\n  mxDouble *pd = static_cast<mxDouble *> (retval->get_data ());\n  mwIndex *ir = retval->get_ir ();\n\n  const double *pdata = matrix.data ();\n  const octave_idx_type *pridx = matrix.ridx ();\n\n  for (mwIndex i = 0; i < nz; i++)\n    {\n      pd[i] = pdata[i];\n\n      ir[i] = pridx[i];\n    }\n\n  mwIndex *jc = retval->get_jc ();\n\n  const octave_idx_type *pcidx = matrix.cidx ();\n\n  for (mwIndex i = 0; i < nc + 1; i++)\n    jc[i] = pcidx[i];\n\n  return retval;\n}\n\noctave_value\noctave_sparse_matrix::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    case umap_imag:\n      return SparseMatrix (matrix.rows (), matrix.cols (), 0.0);\n\n    case umap_real:\n    case umap_conj:\n      return matrix;\n\n      // Mappers handled specially.\n#define ARRAY_METHOD_MAPPER(UMAP, FCN)        \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (matrix.FCN ())\n\n      ARRAY_METHOD_MAPPER (abs, abs);\n\n#define ARRAY_MAPPER(UMAP, TYPE, FCN)                 \\\n    case umap_ ## UMAP:                               \\\n      return octave_value (matrix.map<TYPE> (FCN))\n\n      ARRAY_MAPPER (acos, Complex, octave::math::rc_acos);\n      ARRAY_MAPPER (acosh, Complex, octave::math::rc_acosh);\n      ARRAY_MAPPER (angle, double, std::arg);\n      ARRAY_MAPPER (arg, double, std::arg);\n      ARRAY_MAPPER (asin, Complex, octave::math::rc_asin);\n      ARRAY_MAPPER (asinh, double, octave::math::asinh);\n      ARRAY_MAPPER (atan, double, ::atan);\n      ARRAY_MAPPER (atanh, Complex, octave::math::rc_atanh);\n      ARRAY_MAPPER (erf, double, octave::math::erf);\n      ARRAY_MAPPER (erfinv, double, octave::math::erfinv);\n      ARRAY_MAPPER (erfcinv, double, octave::math::erfcinv);\n      ARRAY_MAPPER (erfc, double, octave::math::erfc);\n      ARRAY_MAPPER (erfcx, double, octave::math::erfcx);\n      ARRAY_MAPPER (erfi, double, octave::math::erfi);\n      ARRAY_MAPPER (dawson, double, octave::math::dawson);\n      ARRAY_MAPPER (gamma, double, octave::math::gamma);\n      ARRAY_MAPPER (lgamma, Complex, octave::math::rc_lgamma);\n      ARRAY_MAPPER (cbrt, double, octave::math::cbrt);\n      ARRAY_MAPPER (ceil, double, ::ceil);\n      ARRAY_MAPPER (cos, double, ::cos);\n      ARRAY_MAPPER (cosh, double, ::cosh);\n      ARRAY_MAPPER (exp, double, ::exp);\n      ARRAY_MAPPER (expm1, double, octave::math::expm1);\n      ARRAY_MAPPER (fix, double, octave::math::fix);\n      ARRAY_MAPPER (floor, double, ::floor);\n      ARRAY_MAPPER (log, Complex, octave::math::rc_log);\n      ARRAY_MAPPER (log2, Complex, octave::math::rc_log2);\n      ARRAY_MAPPER (log10, Complex, octave::math::rc_log10);\n      ARRAY_MAPPER (log1p, Complex, octave::math::rc_log1p);\n      ARRAY_MAPPER (round, double, octave::math::round);\n      ARRAY_MAPPER (roundb, double, octave::math::roundb);\n      ARRAY_MAPPER (signum, double, octave::math::signum);\n      ARRAY_MAPPER (sin, double, ::sin);\n      ARRAY_MAPPER (sinh, double, ::sinh);\n      ARRAY_MAPPER (sqrt, Complex, octave::math::rc_sqrt);\n      ARRAY_MAPPER (tan, double, ::tan);\n      ARRAY_MAPPER (tanh, double, ::tanh);\n      ARRAY_MAPPER (isnan, bool, octave::math::isnan);\n      ARRAY_MAPPER (isna, bool, octave::math::isna);\n      ARRAY_MAPPER (isinf, bool, octave::math::isinf);\n      ARRAY_MAPPER (isfinite, bool, octave::math::isfinite);\n\n    default: // Attempt to go via dense matrix.\n      return octave_base_sparse<SparseMatrix>::map (umap);\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-re-sparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_re_sparse_h)\n#define octave_ov_re_sparse_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n\n#include \"dSparse.h\"\n#include \"MatrixType.h\"\n#include \"ov-base-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\nclass octave_value_list;\n\nextern template class OCTINTERP_API\noctave_base_sparse<SparseMatrix>;\n\nclass OCTINTERP_API octave_sparse_matrix : public octave_base_sparse<SparseMatrix>\n{\npublic:\n\n  octave_sparse_matrix ()\n    : octave_base_sparse<SparseMatrix> () { }\n\n  octave_sparse_matrix (const Matrix& m)\n    : octave_base_sparse<SparseMatrix> (SparseMatrix (m)) { }\n\n  octave_sparse_matrix (const NDArray& m)\n    : octave_base_sparse<SparseMatrix> (SparseMatrix (m)) { }\n\n  octave_sparse_matrix (const SparseMatrix& m)\n    : octave_base_sparse<SparseMatrix> (m) { }\n\n  octave_sparse_matrix (const SparseMatrix& m, const MatrixType& t)\n    : octave_base_sparse<SparseMatrix> (m, t) { }\n\n  octave_sparse_matrix (const MSparse<double>& m)\n    : octave_base_sparse<SparseMatrix> (m) { }\n\n  octave_sparse_matrix (const MSparse<double>& m, const MatrixType& t)\n    : octave_base_sparse<SparseMatrix> (m, t) { }\n\n  octave_sparse_matrix (const Sparse<double>& m)\n    : octave_base_sparse<SparseMatrix> (SparseMatrix (m)) { }\n\n  octave_sparse_matrix (const Sparse<double>& m, const MatrixType& t)\n    : octave_base_sparse<SparseMatrix> (SparseMatrix (m), t) { }\n\n  octave_sparse_matrix (const octave_sparse_matrix& m)\n    : octave_base_sparse<SparseMatrix> (m) { }\n\n  ~octave_sparse_matrix () = default;\n\n  octave_base_value * clone () const\n  { return new octave_sparse_matrix (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_sparse_matrix (); }\n\n  octave::idx_vector index_vector (bool require_integers = false) const;\n\n  builtin_type_t builtin_type () const { return btyp_double; }\n\n  bool is_real_matrix () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  double double_value (bool = false) const;\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return double_value (frc_str_conv); }\n\n  Matrix matrix_value (bool = false) const;\n\n  Complex complex_value (bool = false) const;\n\n  boolNDArray bool_array_value (bool warn = false) const;\n\n  charNDArray char_array_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const;\n\n  NDArray array_value (bool = false) const;\n\n  SparseMatrix sparse_matrix_value (bool = false) const\n  { return matrix; }\n\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  { return SparseComplexMatrix (matrix); }\n\n  SparseBoolMatrix sparse_bool_matrix_value (bool warn = false) const;\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  octave_value as_double () const;\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n\nprivate:\n  octave_value map (double (*fcn) (double)) const;\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-scalar.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"oct-inttypes-fwd.h\"\n\n#include \"data-conv.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-specfun.h\"\n\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-base.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"pr-output.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n#include \"ops.h\"\n#include \"ov-inline.h\"\n\n#include \"ls-oct-text.h\"\n#include \"ls-hdf5.h\"\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_scalar, \"scalar\", \"double\");\n\nstatic octave_base_value *\ndefault_numeric_demotion_function (const octave_base_value& a)\n{\n  const octave_scalar& v = dynamic_cast<const octave_scalar&> (a);\n\n  return new octave_float_scalar (v.float_value ());\n}\n\noctave_base_value::type_conv_info\noctave_scalar::numeric_demotion_function () const\n{\n  return octave_base_value::type_conv_info\n         (default_numeric_demotion_function,\n          octave_float_scalar::static_type_id ());\n}\n\noctave_value\noctave_scalar::do_index_op (const octave_value_list& idx, bool resize_ok)\n{\n  // FIXME: this doesn't solve the problem of\n  //\n  //   a = 1; a([1,1], [1,1], [1,1])\n  //\n  // and similar constructions.  Hmm...\n\n  // FIXME: using this constructor avoids narrowing the\n  // 1x1 matrix back to a scalar value.  Need a better solution\n  // to this problem.\n\n  octave_value tmp (new octave_matrix (matrix_value ()));\n\n  return tmp.index_op (idx, resize_ok);\n}\n\noctave_value\noctave_scalar::resize (const dim_vector& dv, bool fill) const\n{\n  if (fill)\n    {\n      NDArray retval (dv, 0);\n\n      if (dv.numel ())\n        retval(0) = scalar;\n\n      return retval;\n    }\n  else\n    {\n      NDArray retval (dv);\n\n      if (dv.numel ())\n        retval(0) = scalar;\n\n      return retval;\n    }\n}\n\noctave_value\noctave_scalar::as_double_or_copy ()\n{\n  return octave_value_factory::make_copy (this);\n}\n\noctave_value\noctave_scalar::as_double () const\n{\n  return scalar;\n}\n\noctave_value\noctave_scalar::as_single () const\n{\n  return static_cast<float> (scalar);\n}\n\noctave_value\noctave_scalar::as_int8 () const\n{\n  return octave_int8 (scalar);\n}\n\noctave_value\noctave_scalar::as_int16 () const\n{\n  return octave_int16 (scalar);\n}\n\noctave_value\noctave_scalar::as_int32 () const\n{\n  return octave_int32 (scalar);\n}\n\noctave_value\noctave_scalar::as_int64 () const\n{\n  return octave_int64 (scalar);\n}\n\noctave_value\noctave_scalar::as_uint8 () const\n{\n  return octave_uint8 (scalar);\n}\n\noctave_value\noctave_scalar::as_uint16 () const\n{\n  return octave_uint16 (scalar);\n}\n\noctave_value\noctave_scalar::as_uint32 () const\n{\n  return octave_uint32 (scalar);\n}\n\noctave_value\noctave_scalar::as_uint64 () const\n{\n  return octave_uint64 (scalar);\n}\n\noctave_value\noctave_scalar::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return DiagMatrix (Array<double> (dim_vector (1, 1), scalar), m, n);\n}\n\noctave_value\noctave_scalar::convert_to_str_internal (bool, bool, char type) const\n{\n  octave_value retval;\n\n  if (octave::math::isnan (scalar))\n    octave::err_nan_to_character_conversion ();\n\n  int ival = octave::math::nint (scalar);\n\n  if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())\n    {\n      // FIXME: is there something better we could do?\n\n      ival = 0;\n\n      ::warning (\"range error for conversion to character value\");\n    }\n\n  retval = octave_value (std::string (1, static_cast<char> (ival)), type);\n\n  return retval;\n}\n\nbool\noctave_scalar::save_ascii (std::ostream& os)\n{\n  double d = double_value ();\n\n  octave::write_value<double> (os, d);\n\n  os << \"\\n\";\n\n  return true;\n}\n\nbool\noctave_scalar::load_ascii (std::istream& is)\n{\n  scalar = octave::read_value<double> (is);\n\n  if (! is)\n    error (\"load: failed to load scalar constant\");\n\n  return true;\n}\n\nbool\noctave_scalar::save_binary (std::ostream& os, bool /* save_as_floats */)\n{\n  char tmp = LS_DOUBLE;\n  os.write (reinterpret_cast<char *> (&tmp), 1);\n  double dtmp = double_value ();\n  os.write (reinterpret_cast<char *> (&dtmp), 8);\n\n  return true;\n}\n\nbool\noctave_scalar::load_binary (std::istream& is, bool swap,\n                            octave::mach_info::float_format fmt)\n{\n  char tmp;\n  if (! is.read (reinterpret_cast<char *> (&tmp), 1))\n    return false;\n\n  double dtmp;\n  read_doubles (is, &dtmp, static_cast<save_type> (tmp), 1, swap, fmt);\n\n  if (! is)\n    return false;\n\n  scalar = dtmp;\n  return true;\n}\n\nbool\noctave_scalar::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                          bool /* save_as_floats */)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hsize_t dimens[3] = {0};\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n\n  space_hid = H5Screate_simple (0, dimens, nullptr);\n  if (space_hid < 0) return false;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_DOUBLE, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_DOUBLE, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n\n  double tmp = double_value ();\n  retval = H5Dwrite (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL,\n                     octave_H5S_ALL, octave_H5P_DEFAULT, &tmp) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_scalar::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n#if defined (HAVE_HDF5)\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_id = H5Dget_space (data_hid);\n\n  hsize_t rank = H5Sget_simple_extent_ndims (space_id);\n\n  if (rank != 0)\n    {\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  double dtmp;\n  if (H5Dread (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL, octave_H5S_ALL,\n               octave_H5P_DEFAULT, &dtmp) < 0)\n    {\n      H5Dclose (data_hid);\n      return false;\n    }\n\n  scalar = dtmp;\n\n  H5Dclose (data_hid);\n\n  return true;\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n\n  return false;\n#endif\n}\n\nmxArray *\noctave_scalar::as_mxArray (bool interleaved) const\n{\n  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, 1, 1, mxREAL);\n\n  mxDouble *pd = static_cast<mxDouble *> (retval->get_data ());\n\n  pd[0] = scalar;\n\n  return retval;\n}\n\noctave_value\noctave_scalar::map (unary_mapper_t umap) const\n{\n  switch (umap)\n    {\n    case umap_imag:\n      return 0.0;\n\n    case umap_real:\n    case umap_conj:\n      return scalar;\n\n#define SCALAR_MAPPER(UMAP, FCN)              \\\n    case umap_ ## UMAP:                       \\\n      return octave_value (FCN (scalar))\n\n      SCALAR_MAPPER (abs, ::fabs);\n      SCALAR_MAPPER (acos, octave::math::rc_acos);\n      SCALAR_MAPPER (acosh, octave::math::rc_acosh);\n      SCALAR_MAPPER (angle, std::arg);\n      SCALAR_MAPPER (arg, std::arg);\n      SCALAR_MAPPER (asin, octave::math::rc_asin);\n      SCALAR_MAPPER (asinh, octave::math::asinh);\n      SCALAR_MAPPER (atan, ::atan);\n      SCALAR_MAPPER (atanh, octave::math::rc_atanh);\n      SCALAR_MAPPER (erf, octave::math::erf);\n      SCALAR_MAPPER (erfinv, octave::math::erfinv);\n      SCALAR_MAPPER (erfcinv, octave::math::erfcinv);\n      SCALAR_MAPPER (erfc, octave::math::erfc);\n      SCALAR_MAPPER (erfcx, octave::math::erfcx);\n      SCALAR_MAPPER (erfi, octave::math::erfi);\n      SCALAR_MAPPER (dawson, octave::math::dawson);\n      SCALAR_MAPPER (gamma, octave::math::gamma);\n      SCALAR_MAPPER (lgamma, octave::math::rc_lgamma);\n      SCALAR_MAPPER (cbrt, octave::math::cbrt);\n      SCALAR_MAPPER (ceil, ::ceil);\n      SCALAR_MAPPER (cos, ::cos);\n      SCALAR_MAPPER (cosh, ::cosh);\n      SCALAR_MAPPER (exp, ::exp);\n      SCALAR_MAPPER (expm1, octave::math::expm1);\n      SCALAR_MAPPER (fix, octave::math::fix);\n      SCALAR_MAPPER (floor, std::floor);\n      SCALAR_MAPPER (log, octave::math::rc_log);\n      SCALAR_MAPPER (log2, octave::math::rc_log2);\n      SCALAR_MAPPER (log10, octave::math::rc_log10);\n      SCALAR_MAPPER (log1p, octave::math::rc_log1p);\n      SCALAR_MAPPER (round, octave::math::round);\n      SCALAR_MAPPER (roundb, octave::math::roundb);\n      SCALAR_MAPPER (signum, octave::math::signum);\n      SCALAR_MAPPER (sin, ::sin);\n      SCALAR_MAPPER (sinh, ::sinh);\n      SCALAR_MAPPER (sqrt, octave::math::rc_sqrt);\n      SCALAR_MAPPER (tan, ::tan);\n      SCALAR_MAPPER (tanh, ::tanh);\n      SCALAR_MAPPER (isfinite, octave::math::isfinite);\n      SCALAR_MAPPER (isinf, octave::math::isinf);\n      SCALAR_MAPPER (isna, octave::math::isna);\n      SCALAR_MAPPER (isnan, octave::math::isnan);\n      SCALAR_MAPPER (xsignbit, octave::math::signbit);\n\n    // Special cases for Matlab compatibility.\n    case umap_xtolower:\n    case umap_xtoupper:\n      return scalar;\n\n    case umap_xisalnum:\n    case umap_xisalpha:\n    case umap_xisascii:\n    case umap_xiscntrl:\n    case umap_xisdigit:\n    case umap_xisgraph:\n    case umap_xislower:\n    case umap_xisprint:\n    case umap_xispunct:\n    case umap_xisspace:\n    case umap_xisupper:\n    case umap_xisxdigit:\n      {\n        octave_value str_conv = convert_to_str (true, true);\n        return str_conv.map (umap);\n      }\n\n    default:\n      return octave_base_value::map (umap);\n    }\n}\n\nbool\noctave_scalar::fast_elem_insert_self (void *where, builtin_type_t btyp) const\n{\n\n  // Support inline real->complex conversion.\n  if (btyp == btyp_double)\n    {\n      *(reinterpret_cast<double *> (where)) = scalar;\n      return true;\n    }\n  else if (btyp == btyp_complex)\n    {\n      *(reinterpret_cast<Complex *> (where)) = scalar;\n      return true;\n    }\n  else\n    return false;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-scalar.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_scalar_h)\n#define octave_ov_scalar_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"errwarn.h\"\n#include \"ov-base.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-base-scalar.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Real scalar values.\n\nextern template class OCTINTERP_API octave_base_scalar<double>;\n\nclass OCTINTERP_API octave_scalar : public octave_base_scalar<double>\n{\npublic:\n\n  octave_scalar ()\n    : octave_base_scalar<double> (0.0) { }\n\n  octave_scalar (double d)\n    : octave_base_scalar<double> (d) { }\n\n  octave_scalar (const octave_scalar& s)\n    : octave_base_scalar<double> (s) { }\n\n  ~octave_scalar () = default;\n\n  octave_base_value * clone () const { return new octave_scalar (*this); }\n\n  // We return an octave_matrix here instead of an octave_scalar so\n  // that in expressions like A(2,2,2) = 2 (for A previously\n  // undefined), A will be empty instead of a 1x1 object.\n  octave_base_value * empty_clone () const { return new octave_matrix (); }\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  type_conv_info numeric_demotion_function () const;\n\n  octave::idx_vector index_vector (bool /* require_integers */ = false) const\n  { return octave::idx_vector (scalar); }\n\n  octave_value any (int = 0) const\n  { return (scalar != 0 && ! octave::math::isnan (scalar)); }\n\n  builtin_type_t builtin_type () const { return btyp_double; }\n\n  bool is_real_scalar () const { return true; }\n\n  bool isreal () const { return true; }\n\n  bool is_double_type () const { return true; }\n\n  bool isfloat () const { return true; }\n\n  int8NDArray\n  int8_array_value () const\n  { return int8NDArray (dim_vector (1, 1), scalar); }\n\n  int16NDArray\n  int16_array_value () const\n  { return int16NDArray (dim_vector (1, 1), scalar); }\n\n  int32NDArray\n  int32_array_value () const\n  { return int32NDArray (dim_vector (1, 1), scalar); }\n\n  int64NDArray\n  int64_array_value () const\n  { return int64NDArray (dim_vector (1, 1), scalar); }\n\n  uint8NDArray\n  uint8_array_value () const\n  { return uint8NDArray (dim_vector (1, 1), scalar); }\n\n  uint16NDArray\n  uint16_array_value () const\n  { return uint16NDArray (dim_vector (1, 1), scalar); }\n\n  uint32NDArray\n  uint32_array_value () const\n  { return uint32NDArray (dim_vector (1, 1), scalar); }\n\n  uint64NDArray\n  uint64_array_value () const\n  { return uint64NDArray (dim_vector (1, 1), scalar); }\n\n#define DEFINE_INT_SCALAR_VALUE(TYPE)           \\\n  octave_ ## TYPE                               \\\n  TYPE ## _scalar_value () const            \\\n  {                                             \\\n    return octave_ ## TYPE (scalar);            \\\n  }\n\n  DEFINE_INT_SCALAR_VALUE (int8)\n  DEFINE_INT_SCALAR_VALUE (int16)\n  DEFINE_INT_SCALAR_VALUE (int32)\n  DEFINE_INT_SCALAR_VALUE (int64)\n  DEFINE_INT_SCALAR_VALUE (uint8)\n  DEFINE_INT_SCALAR_VALUE (uint16)\n  DEFINE_INT_SCALAR_VALUE (uint32)\n  DEFINE_INT_SCALAR_VALUE (uint64)\n\n#undef DEFINE_INT_SCALAR_VALUE\n\n  double double_value (bool = false) const { return scalar; }\n\n  float float_value (bool = false) const\n  { return static_cast<float> (scalar); }\n\n  double scalar_value (bool = false) const { return scalar; }\n\n  float float_scalar_value (bool = false) const\n  { return float_value (); }\n\n  Matrix matrix_value (bool = false) const\n  { return Matrix (1, 1, scalar); }\n\n  FloatMatrix float_matrix_value (bool = false) const\n  { return FloatMatrix (1, 1, float_value ()); }\n\n  NDArray array_value (bool = false) const\n  { return NDArray (dim_vector (1, 1), scalar); }\n\n  FloatNDArray float_array_value (bool = false) const\n  { return FloatNDArray (dim_vector (1, 1), float_value ()); }\n\n  SparseMatrix sparse_matrix_value (bool = false) const\n  { return SparseMatrix (Matrix (1, 1, scalar)); }\n\n  // FIXME: Need SparseComplexMatrix (Matrix) constructor!\n  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const\n  { return SparseComplexMatrix (sparse_matrix_value ()); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const;\n\n  Complex complex_value (bool = false) const { return scalar; }\n\n  FloatComplex float_complex_value (bool = false) const\n  { return FloatComplex (float_value ()); }\n\n  ComplexMatrix complex_matrix_value (bool = false) const\n  { return ComplexMatrix (1, 1, Complex (scalar)); }\n\n  FloatComplexMatrix float_complex_matrix_value (bool = false) const\n  { return FloatComplexMatrix (1, 1, FloatComplex (float_value ())); }\n\n  ComplexNDArray complex_array_value (bool = false) const\n  { return ComplexNDArray (dim_vector (1, 1), Complex (scalar)); }\n\n  FloatComplexNDArray float_complex_array_value (bool = false) const\n  {\n    return FloatComplexNDArray (dim_vector (1, 1),\n                                FloatComplex (float_value ()));\n  }\n\n  charNDArray\n  char_array_value (bool = false) const\n  {\n    charNDArray retval (dim_vector (1, 1));\n    if (octave::math::isnan (scalar))\n      retval(0) = 0;\n    else\n      retval(0) = static_cast<char> (scalar);\n    return retval;\n  }\n\n  bool bool_value (bool warn = false) const\n  {\n    if (octave::math::isnan (scalar))\n      octave::err_nan_to_logical_conversion ();\n    if (warn && scalar != 0 && scalar != 1)\n      warn_logical_conversion ();\n\n    return scalar;\n  }\n\n  boolNDArray bool_array_value (bool warn = false) const\n  {\n    if (octave::math::isnan (scalar))\n      octave::err_nan_to_logical_conversion ();\n    if (warn && scalar != 0 && scalar != 1)\n      warn_logical_conversion ();\n\n    return boolNDArray (dim_vector (1, 1), scalar);\n  }\n\n  octave_value as_double_or_copy ();\n\n  bool maybe_update_double (double d)\n  {\n    if (m_count != 1)\n      return false;\n    scalar = d;\n    return true;\n  }\n\n  octave_value as_double () const;\n  octave_value as_single () const;\n\n  octave_value as_int8 () const;\n  octave_value as_int16 () const;\n  octave_value as_int32 () const;\n  octave_value as_int64 () const;\n\n  octave_value as_uint8 () const;\n  octave_value as_uint16 () const;\n  octave_value as_uint32 () const;\n  octave_value as_uint64 () const;\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_base_scalar<double>::diag;\n\n  octave_value diag (octave_idx_type m, octave_idx_type n) const;\n\n  octave_value convert_to_str_internal (bool pad, bool force, char type) const;\n\n  void increment () { ++scalar; }\n\n  void decrement () { --scalar; }\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  {\n    return os.write (array_value (), block_size, output_type,\n                     skip, flt_fmt);\n  }\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value map (unary_mapper_t umap) const;\n\n  bool fast_elem_insert_self (void *where, builtin_type_t btyp) const;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-str-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"data-conv.h\"\n#include \"lo-ieee.h\"\n#include \"mach-info.h\"\n#include \"mx-base.h\"\n#include \"oct-locbuf.h\"\n\n#include \"byte-swap.h\"\n#include \"defun.h\"\n#include \"errwarn.h\"\n#include \"ls-ascii-helper.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ovl.h\"\n#include \"oct-hdf5.h\"\n#include \"oct-stream.h\"\n#include \"ops.h\"\n#include \"ov-scalar.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-str-mat.h\"\n#include \"pr-output.h\"\n#include \"utils.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_char_matrix_str, \"string\", \"char\");\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_char_matrix_sq_str, \"sq_string\",\n                                     \"char\");\n\nstatic octave_base_value *\ndefault_numeric_conversion_function (const octave_base_value& a)\n{\n  octave_base_value *retval = nullptr;\n\n  const octave_char_matrix_str& v\n    = dynamic_cast<const octave_char_matrix_str&> (a);\n\n  NDArray nda = v.array_value (true);\n\n  if (nda.numel () == 1)\n    retval = new octave_scalar (nda(0));\n  else\n    retval = new octave_matrix (nda);\n\n  return retval;\n}\n\noctave_base_value::type_conv_info\noctave_char_matrix_str::numeric_conversion_function () const\n{\n  return octave_base_value::type_conv_info (default_numeric_conversion_function,\n         octave_matrix::static_type_id ());\n}\n\noctave_value\noctave_char_matrix_str::do_index_op_internal (const octave_value_list& idx,\n    bool resize_ok, char type)\n{\n  octave_value retval;\n\n  octave_idx_type len = idx.length ();\n\n  // If we catch an indexing error in index_vector, we flag an error in\n  // index k.  Ensure it is the right value before each idx_vector call.\n  // Same variable as used in the for loop in the default case.\n\n  octave_idx_type k = 0;\n\n  try\n    {\n      switch (len)\n        {\n        case 0:\n          retval = octave_value (m_matrix, type);\n          break;\n\n        case 1:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n\n            retval = octave_value (charNDArray (m_matrix.index (i, resize_ok)),\n                                   type);\n          }\n          break;\n\n        case 2:\n          {\n            octave::idx_vector i = idx (0).index_vector ();\n            k = 1;\n            octave::idx_vector j = idx (1).index_vector ();\n\n            retval = octave_value (charNDArray (m_matrix.index (i, j, resize_ok)),\n                                   type);\n          }\n          break;\n\n        default:\n          {\n            Array<octave::idx_vector> idx_vec (dim_vector (len, 1));\n\n            for (k = 0; k < len; k++)\n              idx_vec(k) = idx(k).index_vector ();\n\n            retval = octave_value (charNDArray (m_matrix.index (idx_vec, resize_ok)), type);\n          }\n          break;\n        }\n    }\n  catch (octave::index_exception& ie)\n    {\n      // Rethrow to allow more info to be reported later.\n      ie.set_pos_if_unset (len, k+1);\n      throw;\n    }\n\n  return retval;\n}\n\noctave_value\noctave_char_matrix_str::resize (const dim_vector& dv, bool fill) const\n{\n  charNDArray retval (m_matrix);\n  if (fill)\n    retval.resize (dv, 0);\n  else\n    retval.resize (dv);\n  return octave_value (retval, is_sq_string () ? '\\'' : '\"');\n}\n\n#define CHAR_MATRIX_CONV(TNAME, FCN)                                    \\\n                                                                        \\\n  if (! force_string_conv)                                              \\\n    err_invalid_conversion (\"string\", TNAME);                           \\\n                                                                        \\\n  warn_implicit_conversion (\"Octave:str-to-num\", \"string\", TNAME);      \\\n                                                                        \\\n  return octave_char_matrix::FCN ()\n\ndouble\noctave_char_matrix_str::double_value (bool force_string_conv) const\n{\n  CHAR_MATRIX_CONV (\"real scalar\", double_value);\n}\n\nComplex\noctave_char_matrix_str::complex_value (bool force_string_conv) const\n{\n  CHAR_MATRIX_CONV (\"complex scalar\", complex_value);\n}\n\nMatrix\noctave_char_matrix_str::matrix_value (bool force_string_conv) const\n{\n  CHAR_MATRIX_CONV (\"real matrix\", matrix_value);\n}\n\nComplexMatrix\noctave_char_matrix_str::complex_matrix_value (bool force_string_conv) const\n{\n  CHAR_MATRIX_CONV (\"complex matrix\", complex_matrix_value);\n}\n\nNDArray\noctave_char_matrix_str::array_value (bool force_string_conv) const\n{\n  CHAR_MATRIX_CONV (\"real N-D array\", array_value);\n}\n\nComplexNDArray\noctave_char_matrix_str::complex_array_value (bool force_string_conv) const\n{\n  CHAR_MATRIX_CONV (\"complex N-D array\", complex_array_value);\n}\n\nstring_vector\noctave_char_matrix_str::string_vector_value (bool) const\n{\n  string_vector retval;\n\n  if (m_matrix.ndims () != 2)\n    error (\"invalid conversion of charNDArray to string_vector\");\n\n  charMatrix chm (m_matrix);\n\n  octave_idx_type n = chm.rows ();\n\n  retval.resize (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    retval[i] = chm.row_as_string (i);\n\n  return retval;\n}\n\nstd::string\noctave_char_matrix_str::string_value (bool) const\n{\n  if (m_matrix.ndims () != 2)\n    error (\"invalid conversion of charNDArray to string\");\n\n  charMatrix chm (m_matrix);\n\n  if (chm.rows () > 1)\n    warning_with_id (\"Octave:charmat-truncated\",\n                     \"multi-row character matrix converted to a string, only the first row is used\");\n\n  // FIXME: Is this correct?\n  return chm.row_as_string (0);\n}\n\n/*\n%!test <*49536>\n%! warning (\"on\", \"Octave:charmat-truncated\", \"local\");\n%! s = char (\"this\", \"is\", \"a\", \"char\", \"matrix\");\n%! fail (\"sprintf (s)\", ...\n%!       \"warning\",     ...\n%!       \"multi-row character matrix converted to a string\");\n*/\n\nArray<std::string>\noctave_char_matrix_str::cellstr_value () const\n{\n  Array<std::string> retval;\n\n  if (m_matrix.ndims () != 2)\n    error (\"cellstr: cannot convert multi-dimensional arrays\");\n\n  const charMatrix chm (m_matrix);\n  octave_idx_type nr = chm.rows ();\n  retval.clear (nr, 1);\n  for (octave_idx_type i = 0; i < nr; i++)\n    retval.xelem (i) = chm.row_as_string (i);\n\n  return retval;\n}\n\nvoid\noctave_char_matrix_str::print_raw (std::ostream& os,\n                                   bool pr_as_read_syntax) const\n{\n  octave_print_internal (os, m_matrix, pr_as_read_syntax,\n                         current_print_indent_level (), true);\n}\n\nvoid\noctave_char_matrix_str::short_disp (std::ostream& os) const\n{\n  if (m_matrix.ndims () == 2 && numel () > 0)\n    {\n      charMatrix chm (m_matrix);\n      std::string tmp = chm.row_as_string (0);\n\n      // FIXME: should this be configurable?\n      std::size_t max_len = 50;\n\n      char quote_char = is_sq_string () ? '\\'' : '\"';\n\n      os << quote_char;\n      if (tmp.length () > max_len)\n        os << tmp.substr (0, 50) << quote_char << \" (truncated)\";\n      else\n        os << tmp << quote_char;\n    }\n}\n\nstd::string\noctave_char_matrix_str::edit_display (const float_display_format&,\n                                      octave_idx_type i,\n                                      octave_idx_type) const\n{\n  if (i == 0)\n    {\n      if (rows () == 1)\n        {\n          std::string retval = string_value ();\n\n          if (! is_sq_string ())\n            retval = octave::undo_string_escapes (retval);\n\n          return retval;\n        }\n      else if (is_zero_by_zero ())\n        return \"\";\n    }\n\n  std::string tname = type_name ();\n  const dim_vector& dv = m_matrix.dims ();\n  std::string dimstr = dv.str ();\n  return \"[\" + dimstr + \" \" + tname + \"]\";\n}\n\nbool\noctave_char_matrix_str::save_ascii (std::ostream& os)\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () > 2)\n    {\n      charNDArray tmp = char_array_value ();\n      os << \"# ndims: \" << dv.ndims () << \"\\n\";\n      for (int i=0; i < dv.ndims (); i++)\n        os << ' ' << dv(i);\n      os << \"\\n\";\n      os.write (tmp.data (), dv.numel ());\n      os << \"\\n\";\n    }\n  else\n    {\n      // Keep this case, rather than use generic code above for\n      // backward compatibility.  Makes load_ascii much more complex!!\n      charMatrix chm = char_matrix_value ();\n      octave_idx_type elements = chm.rows ();\n      os << \"# elements: \" << elements << \"\\n\";\n      for (octave_idx_type i = 0; i < elements; i++)\n        {\n          unsigned len = chm.cols ();\n          os << \"# length: \" << len << \"\\n\";\n          std::string tstr = chm.row_as_string (i);\n          const char *tmp = tstr.data ();\n          panic_if (tstr.length () > len);\n          os.write (tmp, len);\n          os << \"\\n\";\n        }\n    }\n\n  return true;\n}\n\nbool\noctave_char_matrix_str::load_ascii (std::istream& is)\n{\n  string_vector keywords(3);\n\n  keywords[0] = \"ndims\";\n  keywords[1] = \"elements\";\n  keywords[2] = \"length\";\n\n  std::string kw;\n  int val = 0;\n\n  if (! extract_keyword (is, keywords, kw, val, true))\n    error (\"load: failed to extract number of rows and columns\");\n\n  if (kw == \"ndims\")\n    {\n      int mdims = val;\n\n      if (mdims < 0)\n        error (\"load: failed to extract matrix size\");\n\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        is >> dv(i);\n\n      if (! is)\n        error (\"load: failed to read dimensions\");\n\n      charNDArray tmp(dv);\n\n      if (tmp.isempty ())\n        m_matrix = tmp;\n      else\n        {\n          char *ftmp = tmp.rwdata ();\n\n          octave::skip_preceeding_newline (is);\n\n          if (! is.read (ftmp, dv.numel ()) || ! is)\n            error (\"load: failed to load string constant\");\n\n          m_matrix = tmp;\n        }\n    }\n  else if (kw == \"elements\")\n    {\n      int elements = val;\n\n      if (elements < 0)\n        error (\"load: failed to extract number of string elements\");\n\n      // FIXME: need to be able to get max length before doing anything.\n\n      charMatrix chm (elements, 0);\n      int max_len = 0;\n      for (int i = 0; i < elements; i++)\n        {\n          int len;\n          if (! extract_keyword (is, \"length\", len) || len < 0)\n            error (\"load: failed to extract string length for element %d\",\n                   i+1);\n\n          // Use this instead of a C-style character\n          // buffer so that we can properly handle\n          // embedded NUL characters.\n          charMatrix tmp (1, len);\n          char *ptmp = tmp.rwdata ();\n\n          if (len > 0 && ! is.read (ptmp, len))\n            error (\"load: failed to load string constant\");\n\n          if (len > max_len)\n            {\n              max_len = len;\n              chm.resize (elements, max_len, 0);\n            }\n\n          chm.insert (tmp, i, 0);\n        }\n\n      m_matrix = chm;\n    }\n  else if (kw == \"length\")\n    {\n      int len = val;\n\n      if (len >= 0)\n        {\n          // This is cruft for backward compatibility,\n          // but relatively harmless.\n\n          // Use this instead of a C-style character buffer so\n          // that we can properly handle embedded NUL characters.\n          charMatrix tmp (1, len);\n          char *ptmp = tmp.rwdata ();\n\n          if (len > 0 && ! is.read (ptmp, len))\n            error (\"load: failed to load string constant\");\n\n          if (! is)\n            error (\"load: failed to load string constant\");\n\n          m_matrix = tmp;\n        }\n    }\n  else\n    error (\"unexpected dimensions keyword (= '%s') octave_char_matrix::load_ascii - please report this bug\", kw.c_str ());\n\n  return true;\n}\n\nbool\noctave_char_matrix_str::save_binary (std::ostream& os,\n                                     bool /* save_as_floats */)\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Use negative value for ndims to differentiate with old format!!\n  int32_t tmp = - dv.ndims ();\n  os.write (reinterpret_cast<char *> (&tmp), 4);\n  for (int i=0; i < dv.ndims (); i++)\n    {\n      tmp = dv(i);\n      os.write (reinterpret_cast<char *> (&tmp), 4);\n    }\n\n  charNDArray m = char_array_value ();\n  os.write (m.data (), dv.numel ());\n  return true;\n}\n\nbool\noctave_char_matrix_str::load_binary (std::istream& is, bool swap,\n                                     octave::mach_info::float_format /* fmt */)\n{\n  int32_t elements;\n  if (! is.read (reinterpret_cast<char *> (&elements), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&elements);\n\n  if (elements < 0)\n    {\n      int32_t mdims = - elements;\n      int32_t di;\n      dim_vector dv;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        {\n          if (! is.read (reinterpret_cast<char *> (&di), 4))\n            return false;\n          if (swap)\n            swap_bytes<4> (&di);\n          dv(i) = di;\n        }\n\n      // Convert an array with a single dimension to be a row vector.\n      // Octave should never write files like this, other software\n      // might.\n\n      if (mdims == 1)\n        {\n          mdims = 2;\n          dv.resize (mdims);\n          dv(1) = dv(0);\n          dv(0) = 1;\n        }\n\n      charNDArray m(dv);\n      char *tmp = m.rwdata ();\n      is.read (tmp, dv.numel ());\n\n      if (! is)\n        return false;\n\n      m_matrix = m;\n    }\n  else\n    {\n      charMatrix chm (elements, 0);\n      int max_len = 0;\n      for (int i = 0; i < elements; i++)\n        {\n          int32_t len;\n          if (! is.read (reinterpret_cast<char *> (&len), 4))\n            return false;\n          if (swap)\n            swap_bytes<4> (&len);\n          charMatrix btmp (1, len);\n          char *pbtmp = btmp.rwdata ();\n          if (! is.read (pbtmp, len))\n            return false;\n          if (len > max_len)\n            {\n              max_len = len;\n              chm.resize (elements, max_len, 0);\n            }\n          chm.insert (btmp, i, 0);\n        }\n      m_matrix = chm;\n    }\n  return true;\n}\n\nbool\noctave_char_matrix_str::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                                   bool /* save_as_floats */)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  const dim_vector& dv = dims ();\n  int empty = save_hdf5_empty (loc_id, name, dv);\n  if (empty)\n    return (empty > 0);\n\n  int rank = dv.ndims ();\n  hid_t space_hid, data_hid;\n  space_hid = data_hid = -1;\n  charNDArray m = char_array_value ();\n\n  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n\n  // Octave uses column-major, while HDF5 uses row-major ordering\n  for (int i = 0; i < rank; i++)\n    hdims[i] = dv(rank-i-1);\n\n  space_hid = H5Screate_simple (rank, hdims, nullptr);\n  if (space_hid < 0)\n    return false;\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_CHAR, space_hid,\n                        octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_CHAR, space_hid,\n                        octave_H5P_DEFAULT);\n#endif\n  if (data_hid < 0)\n    {\n      H5Sclose (space_hid);\n      return false;\n    }\n\n  OCTAVE_LOCAL_BUFFER (char, s, dv.numel ());\n\n  for (int i = 0; i < dv.numel (); ++i)\n    s[i] = m(i);\n\n  retval = H5Dwrite (data_hid, H5T_NATIVE_CHAR, octave_H5S_ALL, octave_H5S_ALL,\n                     octave_H5P_DEFAULT, s) >= 0;\n\n  H5Dclose (data_hid);\n  H5Sclose (space_hid);\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_save (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nbool\noctave_char_matrix_str::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  dim_vector dv;\n  int empty = load_hdf5_empty (loc_id, name, dv);\n  if (empty > 0)\n    m_matrix.resize (dv);\n  if (empty)\n    return (empty > 0);\n\n#if defined (HAVE_HDF5_18)\n  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t data_hid = H5Dopen (loc_id, name);\n#endif\n  hid_t space_hid = H5Dget_space (data_hid);\n  hsize_t rank = H5Sget_simple_extent_ndims (space_hid);\n  hid_t type_hid = H5Dget_type (data_hid);\n  hid_t type_class_hid = H5Tget_class (type_hid);\n\n  if (type_class_hid == H5T_INTEGER)\n    {\n      if (rank < 1)\n        {\n          H5Tclose (type_hid);\n          H5Sclose (space_hid);\n          H5Dclose (data_hid);\n          return false;\n        }\n\n      OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);\n      OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);\n\n      H5Sget_simple_extent_dims (space_hid, hdims, maxdims);\n\n      // Octave uses column-major, while HDF5 uses row-major ordering\n      if (rank == 1)\n        {\n          dv.resize (2);\n          dv(0) = 1;\n          dv(1) = hdims[0];\n        }\n      else\n        {\n          dv.resize (rank);\n          for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)\n            dv(j) = hdims[i];\n        }\n\n      charNDArray m (dv);\n      char *str = m.rwdata ();\n      if (H5Dread (data_hid, H5T_NATIVE_CHAR, octave_H5S_ALL, octave_H5S_ALL,\n                   octave_H5P_DEFAULT, str) >= 0)\n        {\n          retval = true;\n          m_matrix = m;\n        }\n\n      H5Tclose (type_hid);\n      H5Sclose (space_hid);\n      H5Dclose (data_hid);\n      return true;\n    }\n  else\n    {\n      // This is cruft for backward compatibility and easy data importation\n      if (rank == 0)\n        {\n          // a single string:\n          int slen = H5Tget_size (type_hid);\n          if (slen < 0)\n            {\n              H5Tclose (type_hid);\n              H5Sclose (space_hid);\n              H5Dclose (data_hid);\n              return false;\n            }\n          else\n            {\n              OCTAVE_LOCAL_BUFFER (char, s, slen+1);\n              // create datatype for (null-terminated) string to read into:\n              hid_t st_id = H5Tcopy (H5T_C_S1);\n              H5Tset_size (st_id, slen+1);\n              if (H5Dread (data_hid, st_id, octave_H5S_ALL,\n                           octave_H5S_ALL, octave_H5P_DEFAULT, s) < 0)\n                {\n                  H5Tclose (st_id);\n                  H5Tclose (type_hid);\n                  H5Sclose (space_hid);\n                  H5Dclose (data_hid);\n                  return false;\n                }\n\n              m_matrix = charMatrix (s);\n\n              H5Tclose (st_id);\n              H5Tclose (type_hid);\n              H5Sclose (space_hid);\n              H5Dclose (data_hid);\n              return true;\n            }\n        }\n      else if (rank == 1)\n        {\n          // string vector\n          hsize_t elements, maxdim;\n          H5Sget_simple_extent_dims (space_hid, &elements, &maxdim);\n          int slen = H5Tget_size (type_hid);\n          if (slen < 0)\n            {\n              H5Tclose (type_hid);\n              H5Sclose (space_hid);\n              H5Dclose (data_hid);\n              return false;\n            }\n          else\n            {\n              // hdf5 string arrays store strings of all the\n              // same physical length (I think), which is\n              // slightly wasteful, but oh well.\n\n              OCTAVE_LOCAL_BUFFER (char, s, elements * (slen+1));\n\n              // create datatype for (null-terminated) string\n              // to read into:\n              hid_t st_id = H5Tcopy (H5T_C_S1);\n              H5Tset_size (st_id, slen+1);\n\n              if (H5Dread (data_hid, st_id, octave_H5S_ALL,\n                           octave_H5S_ALL, octave_H5P_DEFAULT, s) < 0)\n                {\n                  H5Tclose (st_id);\n                  H5Tclose (type_hid);\n                  H5Sclose (space_hid);\n                  H5Dclose (data_hid);\n                  return false;\n                }\n\n              charMatrix chm (elements, slen, ' ');\n              for (hsize_t i = 0; i < elements; ++i)\n                {\n                  chm.insert (s + i*(slen+1), i, 0);\n                }\n\n              m_matrix = chm;\n\n              H5Tclose (st_id);\n              H5Tclose (type_hid);\n              H5Sclose (space_hid);\n              H5Dclose (data_hid);\n              return true;\n            }\n        }\n      else\n        {\n          H5Tclose (type_hid);\n          H5Sclose (space_hid);\n          H5Dclose (data_hid);\n          return false;\n        }\n    }\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n"
  },
  {
    "path": "libinterp/octave-value/ov-str-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_str_mat_h)\n#define octave_ov_str_mat_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-stream.h\"\n#include \"ov.h\"\n#include \"ov-ch-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Character matrix values with special properties for use as\n// strings.\n\nclass OCTINTERP_API octave_char_matrix_str : public octave_char_matrix\n{\npublic:\n\n  octave_char_matrix_str ()\n    : octave_char_matrix () { }\n\n  octave_char_matrix_str (const charMatrix& chm)\n    : octave_char_matrix (chm) { }\n\n  octave_char_matrix_str (const charNDArray& chm)\n    : octave_char_matrix (chm) { }\n\n  octave_char_matrix_str (const Array<char>& chm)\n    : octave_char_matrix (chm) { }\n\n  octave_char_matrix_str (char c)\n    : octave_char_matrix (c) { }\n\n  octave_char_matrix_str (const char *s)\n    : octave_char_matrix (s) { }\n\n  octave_char_matrix_str (const std::string& s)\n    : octave_char_matrix (s) { }\n\n  octave_char_matrix_str (const string_vector& s)\n    : octave_char_matrix (s) { }\n\n  octave_char_matrix_str (const octave_char_matrix& chm)\n    : octave_char_matrix (chm) { }\n\n  octave_char_matrix_str (const octave_char_matrix_str& chms)\n    : octave_char_matrix (chms) { }\n\n  ~octave_char_matrix_str () = default;\n\n  octave_base_value * clone () const\n  { return new octave_char_matrix_str (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_char_matrix_str (); }\n\n  type_conv_info numeric_conversion_function () const;\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false)\n  { return do_index_op_internal (idx, resize_ok); }\n\n  octave_value squeeze () const\n  { return octave_value (charNDArray (m_matrix.squeeze ())); }\n\n  octave_value reshape (const dim_vector& new_dims) const\n  { return octave_value (charNDArray (m_matrix.reshape (new_dims))); }\n\n  octave_value permute (const Array<int>& vec, bool inv = false) const\n  { return octave_value (charNDArray (m_matrix.permute (vec, inv))); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const;\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_char_matrix::diag;\n\n  octave_value diag (octave_idx_type k = 0) const\n  { return octave_value (m_matrix.diag (k)); }\n\n  bool is_string () const { return true; }\n\n  bool isnumeric () const { return false; }\n\n  double double_value (bool = false) const;\n\n  Matrix matrix_value (bool = false) const;\n\n  NDArray array_value (bool = false) const;\n\n  boolNDArray bool_array_value (bool = false) const\n  { return boolNDArray (m_matrix); }\n\n  Complex complex_value (bool = false) const;\n\n  ComplexMatrix complex_matrix_value (bool = false) const;\n\n  ComplexNDArray complex_array_value (bool = false) const;\n\n  string_vector string_vector_value (bool pad = false) const;\n\n  std::string string_value (bool force = false) const;\n\n  std::string xstring_value () const { return string_value (); }\n\n  Array<std::string> cellstr_value () const;\n\n  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const\n  { return octave_value (m_matrix.sort (dim, mode)); }\n\n  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n                     sortmode mode = ASCENDING) const\n  { return octave_value (m_matrix.sort (sidx, dim, mode)); }\n\n  bool print_as_scalar () const { return (rows () <= 1); }\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  void short_disp (std::ostream& os) const;\n\n  std::string edit_display (const float_display_format& fmt,\n                            octave_idx_type i, octave_idx_type j) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  int write (octave::stream& os, int block_size,\n             oct_data_conv::data_type output_type, int skip,\n             octave::mach_info::float_format flt_fmt) const\n  { return os.write (m_matrix, block_size, output_type, skip, flt_fmt); }\n\nprotected:\n\n  octave_value do_index_op_internal (const octave_value_list& idx,\n                                     bool resize_ok, char type = '\"');\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\ntypedef octave_char_matrix_str octave_char_matrix_dq_str;\n\nclass octave_char_matrix_sq_str : public octave_char_matrix_str\n{\npublic:\n\n  octave_char_matrix_sq_str ()\n    : octave_char_matrix_str () { }\n\n  octave_char_matrix_sq_str (const charMatrix& chm)\n    : octave_char_matrix_str (chm) { }\n\n  octave_char_matrix_sq_str (const charNDArray& chm)\n    : octave_char_matrix_str (chm) { }\n\n  octave_char_matrix_sq_str (const Array<char>& chm)\n    : octave_char_matrix_str (chm) { }\n\n  octave_char_matrix_sq_str (char c)\n    : octave_char_matrix_str (c) { }\n\n  octave_char_matrix_sq_str (const char *s)\n    : octave_char_matrix_str (s) { }\n\n  octave_char_matrix_sq_str (const std::string& s)\n    : octave_char_matrix_str (s) { }\n\n  octave_char_matrix_sq_str (const string_vector& s)\n    : octave_char_matrix_str (s) { }\n\n  octave_char_matrix_sq_str (const octave_char_matrix_str& chm)\n    : octave_char_matrix_str (chm) { }\n\n  octave_char_matrix_sq_str (const octave_char_matrix_sq_str& chms)\n    : octave_char_matrix_str (chms) { }\n\n  ~octave_char_matrix_sq_str () = default;\n\n  octave_base_value * clone () const\n  { return new octave_char_matrix_sq_str (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_char_matrix_sq_str (); }\n\n  octave_value squeeze () const\n  { return octave_value (charNDArray (m_matrix.squeeze ()), '\\''); }\n\n  octave_value reshape (const dim_vector& new_dims) const\n  { return octave_value (charNDArray (m_matrix.reshape (new_dims)), '\\''); }\n\n  octave_value permute (const Array<int>& vec, bool inv = false) const\n  { return octave_value (charNDArray (m_matrix.permute (vec, inv)), '\\''); }\n\n  octave_value resize (const dim_vector& dv, bool = false) const\n  {\n    charNDArray retval (m_matrix);\n    retval.resize (dv);\n    return octave_value (retval, '\\'');\n  }\n\n  // We don't need to override both forms of the diag method.  The using\n  // declaration will avoid warnings about partially-overloaded virtual\n  // functions.\n  using octave_char_matrix_str::diag;\n\n  octave_value diag (octave_idx_type k = 0) const\n  { return octave_value (m_matrix.diag (k), '\\''); }\n\n  bool is_sq_string () const { return true; }\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false)\n  { return do_index_op_internal (idx, resize_ok, '\\''); }\n\n  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const\n  { return octave_value (m_matrix.sort (dim, mode), '\\''); }\n\n  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n                     sortmode mode = ASCENDING) const\n  { return octave_value (m_matrix.sort (sidx, dim, mode), '\\''); }\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-struct.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"Cell.h\"\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"mxarray.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ov-struct.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n#include \"Array-util.h\"\n#include \"oct-locbuf.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-oct-binary.h\"\n#include \"ls-hdf5.h\"\n#include \"ls-utils.h\"\n#include \"pr-output.h\"\n#include \"ov-inline.h\"\n\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_struct, \"struct\", \"struct\");\n\n// How many levels of structure elements should we print?\nstatic int Vstruct_levels_to_print = 2;\n\n// TRUE means print struct array contents, up to the number of levels\n// specified by struct_levels_to_print.\nstatic bool Vprint_struct_array_contents = false;\n\nvoid\noctave_struct::break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame)\n{\n  for (octave_idx_type j = 0; j < m_map.nfields (); j++)\n    {\n      Cell& c = m_map.contents (j);\n\n      for (octave_idx_type i = 0; i < c.numel (); i++)\n        c(i).break_closure_cycles (frame);\n    }\n}\n\noctave_base_value *\noctave_struct::try_narrowing_conversion ()\n{\n  octave_base_value *retval = nullptr;\n\n  if (numel () == 1)\n    retval = new octave_scalar_struct (m_map.checkelem (0));\n\n  return retval;\n}\n\nCell\noctave_struct::dotref (const octave_value_list& idx, bool auto_add)\n{\n  Cell retval;\n\n  panic_if (idx.length () != 1);\n\n  std::string nm = idx(0).string_value ();\n\n  octave_map::const_iterator p = m_map.seek (nm);\n\n  if (p != m_map.end ())\n    retval = m_map.contents (p);\n  else if (auto_add)\n    retval = (isempty ()) ? Cell (dim_vector (1, 1)) : Cell (dims ());\n  else\n    error_with_id (\"Octave:invalid-indexing\",\n                   \"structure has no member '%s'\", nm.c_str ());\n\n  return retval;\n}\n\nstatic void\nerr_invalid_index_for_assignment ()\n{\n  error (\"invalid index for structure array assignment\");\n}\n\nstatic void\nerr_invalid_index_type (const std::string& nm, char t)\n{\n  error (\"%s cannot be indexed with %c\", nm.c_str (), t);\n}\n\nstatic void\nmaybe_warn_invalid_field_name (const std::string& key, const char *who)\n{\n  if (! octave::valid_identifier (key))\n    {\n      if (who)\n        warning_with_id (\"Octave:language-extension\",\n                         \"%s: invalid structure field name '%s'\",\n                         who, key.c_str ());\n      else\n        warning_with_id (\"Octave:language-extension\",\n                         \"invalid structure field name '%s'\",\n                         key.c_str ());\n    }\n}\n\noctave_value_list\noctave_struct::subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx,\n                        int nargout)\n{\n  octave_value_list retval;\n\n  int skip = 1;\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        if (type.length () > 1 && type[1] == '.')\n          {\n            const octave_value_list& key_idx = *std::next (idx.begin ());\n\n            const Cell tmp = dotref (key_idx);\n\n            const Cell t = tmp.index (idx.front ());\n\n            // Avoid creating a comma-separated list if the result is a\n            // single element.\n\n            retval(0) = (t.numel () == 1) ? t(0) : octave_value (t, true);\n\n            // We handled two index elements, so tell\n            // next_subsref to skip both of them.\n\n            skip++;\n          }\n        else\n          retval(0) = do_index_op (idx.front ());\n      }\n      break;\n\n    case '.':\n      {\n        const Cell t = dotref (idx.front ());\n\n        // Avoid creating a comma-separated list if the result is a\n        // single element.\n\n        retval(0) = (t.numel () == 1) ? t(0) : octave_value (t, true);\n      }\n      break;\n\n    case '{':\n      err_invalid_index_type (type_name (), type[0]);\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_struct::subsref - please report this bug\");\n    }\n\n  // FIXME: perhaps there should be an\n  // octave_value_list::next_subsref member function?  See also\n  // octave_user_function::subsref.\n\n  if (idx.size () > 1)\n    retval = retval(0).next_subsref (nargout, type, idx, skip);\n\n  return retval;\n}\n\noctave_value\noctave_struct::subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx,\n                        bool auto_add)\n{\n  octave_value retval;\n\n  int skip = 1;\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        if (type.length () > 1 && type[1] == '.')\n          {\n            const octave_value_list& key_idx = *std::next (idx.begin ());\n\n            const Cell tmp = dotref (key_idx, auto_add);\n\n            const Cell t = tmp.index (idx.front (), auto_add);\n\n            // Avoid creating a comma-separated list if the result is a\n            // single element.\n\n            retval = (t.numel () == 1) ? t(0) : octave_value (t, true);\n\n            // We handled two index elements, so tell\n            // next_subsref to skip both of them.\n\n            skip++;\n          }\n        else\n          retval = do_index_op (idx.front (), auto_add);\n      }\n      break;\n\n    case '.':\n      {\n        if (m_map.numel () > 0)\n          {\n            const Cell t = dotref (idx.front (), auto_add);\n\n            // Avoid creating a comma-separated list if the result is a\n            // single element.\n\n            retval = (t.numel () == 1) ? t(0) : octave_value (t, true);\n          }\n      }\n      break;\n\n    case '{':\n      err_invalid_index_type (type_name (), type[0]);\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_struct::subsref - please report this bug\");\n    }\n\n  // FIXME: perhaps there should be an\n  // octave_value_list::next_subsref member function?  See also\n  // octave_user_function::subsref.\n\n  if (idx.size () > 1)\n    retval = retval.next_subsref (auto_add, type, idx, skip);\n\n  return retval;\n}\n\n/*\n%!test\n%! x(1).a.a = 1;\n%! x(2).a.a = 2;\n%! assert (size (x), [1, 2]);\n%! assert (x(1).a.a, 1);\n%! assert (x(2).a.a, 2);\n*/\n\noctave_value\noctave_struct::numeric_conv (const octave_value& val,\n                             const std::string& type)\n{\n  octave_value retval;\n\n  if (type.length () > 0 && type[0] == '.' && ! val.isstruct ())\n    retval = octave_map ();\n  else\n    retval = val;\n\n  return retval;\n}\n\noctave_value\noctave_struct::subsasgn (const std::string& type,\n                         const std::list<octave_value_list>& idx,\n                         const octave_value& rhs)\n{\n  octave_value retval;\n\n  int n = type.length ();\n\n  octave_value t_rhs = rhs;\n\n  if (idx.front ().empty ())\n    error (\"subsasgn: missing index in indexed assignment\");\n\n  if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))\n    {\n      switch (type[0])\n        {\n        case '(':\n          {\n            if (type.length () > 1 && type[1] == '.')\n              {\n                const octave_value_list& key_idx = *std::next (idx.begin ());\n\n                if (key_idx.length () != 1)\n                  error (\"subsasgn: dynamic structure field names must be strings\");\n\n                std::string key\n                  = key_idx(0).xstring_value (\"subsasgn: dynamic structure field names must be strings\");\n\n                maybe_warn_invalid_field_name (key, \"subsasgn\");\n\n                std::list<octave_value_list> next_idx (std::next (idx.begin (), 2),\n                                                       idx.end ());\n\n                // We handled two index elements, so subsasgn to\n                // needs to skip both of them.\n\n                std::string next_type = type.substr (2);\n\n                Cell tmpc (1, 1);\n                auto pkey = m_map.seek (key);\n                if (pkey != m_map.end ())\n                  {\n                    m_map.contents (pkey).make_unique ();\n                    tmpc = m_map.contents (pkey).index (idx.front (), true);\n                  }\n\n                // FIXME: better code reuse?\n                //        cf. octave_cell::subsasgn and the case below.\n                if (tmpc.numel () != 1)\n                  err_indexed_cs_list ();\n\n                octave_value& tmp = tmpc(0);\n\n                bool orig_undefined = tmp.is_undefined ();\n\n                if (orig_undefined || tmp.is_zero_by_zero ())\n                  {\n                    tmp = octave_value::empty_conv (next_type, rhs);\n                    tmp.make_unique (); // probably a no-op.\n                  }\n                else\n                  // optimization: ignore the copy\n                  // still stored inside our map.\n                  tmp.make_unique (1);\n\n                t_rhs =(orig_undefined\n                        ? tmp.undef_subsasgn (next_type, next_idx, rhs)\n                        : tmp.subsasgn (next_type, next_idx, rhs));\n              }\n            else\n              err_invalid_index_for_assignment ();\n          }\n          break;\n\n        case '.':\n          {\n            const octave_value_list& key_idx = idx.front ();\n\n            if (key_idx.length () != 1)\n              error (\"subsasgn: dynamic structure field names must be strings\");\n\n            std::string key\n              = key_idx(0).xstring_value (\"subsasgn: dynamic structure field names must be strings\");\n\n            maybe_warn_invalid_field_name (key, \"subsasgn\");\n\n            std::list<octave_value_list> next_idx (std::next (idx.begin ()),\n                                                   idx.end ());\n\n            std::string next_type = type.substr (1);\n\n            Cell tmpc (1, 1);\n            auto pkey = m_map.seek (key);\n            if (pkey != m_map.end ())\n              {\n                m_map.contents (pkey).make_unique ();\n                tmpc = m_map.contents (pkey);\n              }\n\n            // FIXME: better code reuse?\n\n            if (tmpc.numel () == 1)\n              {\n                octave_value& tmp = tmpc(0);\n\n                bool orig_undefined = tmp.is_undefined ();\n\n                if (orig_undefined || tmp.is_zero_by_zero ())\n                  {\n                    tmp = octave_value::empty_conv (next_type, rhs);\n                    tmp.make_unique (); // probably a no-op.\n                  }\n                else\n                  // optimization: ignore the copy\n                  // still stored inside our map.\n                  tmp.make_unique (1);\n\n                t_rhs = (orig_undefined\n                         ? tmp.undef_subsasgn (next_type, next_idx, rhs)\n                         : tmp.subsasgn (next_type, next_idx, rhs));\n              }\n            else\n              err_indexed_cs_list ();\n          }\n          break;\n\n        case '{':\n          err_invalid_index_type (type_name (), type[0]);\n          break;\n\n        default:\n          error (\"unexpected: index not '(', '{', or '.' in octave_struct::subsasgn - please report this bug\");\n        }\n    }\n\n  switch (type[0])\n    {\n    case '(':\n      {\n        if (n > 1 && type[1] == '.')\n          {\n            const octave_value_list& key_idx = *std::next (idx.begin ());\n            const octave_value_list& idxf = idx.front ();\n\n            if (key_idx.length () != 1)\n              error (\"subsasgn: dynamic structure field names must be strings\");\n\n            std::string key\n              = key_idx(0).xstring_value (\"subsasgn: dynamic structure field names must be strings\");\n\n            maybe_warn_invalid_field_name (key, \"subsasgn\");\n\n            if (t_rhs.is_cs_list ())\n              {\n                Cell tmp_cell = Cell (t_rhs.list_value ());\n\n                // Inquire the proper shape of the RHS.\n\n                dim_vector didx = dims ().redim (idxf.length ());\n                for (octave_idx_type k = 0; k < idxf.length (); k++)\n                  if (! idxf(k).is_magic_colon ())\n                    didx(k) = idxf(k).numel ();\n\n                if (didx.numel () == tmp_cell.numel ())\n                  tmp_cell = tmp_cell.reshape (didx);\n\n                m_map.assign (idxf, key, tmp_cell);\n\n                m_count++;\n                retval = octave_value (this);\n              }\n            else\n              {\n                const octave_map& cmap = const_cast<const octave_map&> (m_map);\n                // cast to const reference, avoid forced key insertion.\n                if (idxf.all_scalars ()\n                    || cmap.contents (key).index (idxf, true).numel () == 1)\n                  {\n                    m_map.assign (idxf,\n                                  key, Cell (t_rhs.storable_value ()));\n\n                    m_count++;\n                    retval = octave_value (this);\n                  }\n                else\n                  err_nonbraced_cs_list_assignment ();\n              }\n          }\n        else\n          {\n            if (t_rhs.isstruct () || t_rhs.isobject ())\n              {\n                octave_map rhs_map = t_rhs.xmap_value (\"invalid structure assignment\");\n\n                m_map.assign (idx.front (), rhs_map);\n\n                m_count++;\n                retval = octave_value (this);\n              }\n            else\n              {\n                if (! t_rhs.isnull ())\n                  error (\"invalid structure assignment\");\n\n                m_map.delete_elements (idx.front ());\n\n                m_count++;\n                retval = octave_value (this);\n              }\n          }\n      }\n      break;\n\n    case '.':\n      {\n        const octave_value_list& key_idx = idx.front ();\n\n        if (key_idx.length () != 1)\n          error (\"subsasgn: dynamic structure field names must be strings\");\n\n        std::string key\n          = key_idx(0).xstring_value (\"subsasgn: dynamic structure field names must be strings\");\n\n        maybe_warn_invalid_field_name (key, \"subsasgn\");\n\n        // assigning to a field of a struct array requires a cs-list on the RHS\n        if (! t_rhs.is_cs_list ())\n          err_nonbraced_cs_list_assignment ();\n\n        Cell tmp_cell = Cell (t_rhs.list_value ());\n\n        // The shape of the RHS is irrelevant, we just want\n        // the number of elements to agree and to preserve the\n        // shape of the left hand side of the assignment.\n\n        if (numel () == tmp_cell.numel ())\n          tmp_cell = tmp_cell.reshape (dims ());\n\n        m_map.setfield (key, tmp_cell);\n\n        m_count++;\n        retval = octave_value (this);\n      }\n      break;\n\n    case '{':\n      err_invalid_index_type (type_name (), type[0]);\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_struct::subsasgn - please report this bug\");\n    }\n\n  retval.maybe_mutate ();\n\n  return retval;\n}\n\n/*\n%!test\n%! x(1:2) = struct ();\n%! idx = struct (\"type\", {\"()\", \".\", \".\"}, \"subs\", {{1}, \"a\", \"b\"});\n%! x = subsasgn (x, idx, 42);\n%! assert (x(1).a.b, 42);\n%! assert (isempty (x(2).a));\n\n%!test <*64213>\n%! x(1:2) = struct ();\n%! idx = struct (\"type\", {\"()\", \".\"}, \"subs\", {{1}, {\"a\", \"b\"}});\n%! fail (\"x = subsasgn (x, idx, 42);\", ...\n%!       \"structure field names must be strings\");\n*/\n\noctave_value\noctave_struct::do_index_op (const octave_value_list& idx, bool resize_ok)\n{\n  if (idx.length () == 0)\n    {\n      warn_empty_index (type_name ());\n      return m_map;\n    }\n  else  // octave_map handles indexing itself.\n    return m_map.index (idx, resize_ok);\n}\n\nstd::size_t\noctave_struct::byte_size () const\n{\n  return m_map.byte_size ();\n}\n\nvoid\noctave_struct::print (std::ostream& os, bool)\n{\n  print_raw (os);\n}\n\nvoid\noctave_struct::print_raw (std::ostream& os, bool) const\n{\n  octave::unwind_protect_var<int> restore_var (Vstruct_levels_to_print);\n\n  if (Vstruct_levels_to_print >= 0)\n    {\n      bool max_depth_reached = (Vstruct_levels_to_print-- == 0);\n\n      bool print_fieldnames_only = (max_depth_reached\n                                    || ! Vprint_struct_array_contents);\n\n      increment_indent_level ();\n\n      indent (os);\n      const dim_vector& dv = dims ();\n      os << dv.str () << \" struct array containing the fields:\";\n      newline (os);\n\n      increment_indent_level ();\n\n      string_vector key_list = m_map.fieldnames ();\n\n      for (octave_idx_type i = 0; i < key_list.numel (); i++)\n        {\n          std::string key = key_list[i];\n\n          Cell val = m_map.contents (key);\n\n          if (i > 0 || ! Vcompact_format)\n            newline (os);\n\n          if (print_fieldnames_only)\n            {\n              indent (os);\n              os << key;\n            }\n          else\n            {\n              octave_value tmp (val);\n              tmp.print_with_name (os, key);\n            }\n        }\n\n      if (print_fieldnames_only)\n        newline (os);\n\n      decrement_indent_level ();\n      decrement_indent_level ();\n    }\n  else\n    {\n      indent (os);\n      os << \"<structure>\";\n      newline (os);\n    }\n}\n\nbool\noctave_struct::print_name_tag (std::ostream& os, const std::string& name) const\n{\n  bool retval = false;\n\n  indent (os);\n\n  if (Vstruct_levels_to_print < 0)\n    os << name << \" = \";\n  else\n    {\n      os << name << \" =\";\n      newline (os);\n      if (! Vcompact_format)\n        newline (os);\n\n      retval = true;\n    }\n\n  return retval;\n}\n\nstatic bool\nscalar (const dim_vector& dims)\n{\n  return dims.ndims () == 2 && dims(0) == 1 && dims(1) == 1;\n}\n\nstd::string\noctave_struct::edit_display (const float_display_format&,\n                             octave_idx_type r, octave_idx_type c) const\n{\n  octave_value val;\n  if (m_map.rows () == 1 || m_map.columns () == 1)\n    {\n      // Vector struct.  Columns are fields, rows are values.\n\n      Cell cval = m_map.contents (c);\n\n      val = cval(r);\n    }\n  else\n    {\n      // 2-D struct array.  Rows and columns index individual\n      // scalar structs.\n\n      val = m_map(r, c);\n    }\n\n  std::string tname = val.type_name ();\n  const dim_vector& dv = val.dims ();\n  std::string dimstr = dv.str ();\n  return \"[\" + dimstr + \" \" + tname + \"]\";\n}\n\n\nbool\noctave_struct::save_ascii (std::ostream& os)\n{\n  octave_map m = map_value ();\n\n  octave_idx_type nf = m.nfields ();\n\n  const dim_vector dv = dims ();\n\n  os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n  for (int i = 0; i < dv.ndims (); i++)\n    os << ' ' << dv(i);\n  os << \"\\n\";\n\n  os << \"# length: \" << nf << \"\\n\";\n\n  // Iterating over the list of keys will preserve the order of the\n  // fields.\n  string_vector keys = m.fieldnames ();\n\n  for (octave_idx_type i = 0; i < nf; i++)\n    {\n      std::string key = keys(i);\n\n      octave_value val = m_map.contents (key);\n\n      bool b = save_text_data (os, val, key, false, 0);\n\n      if (! b)\n        return ! os.fail ();\n    }\n\n  return true;\n}\n\nbool\noctave_struct::load_ascii (std::istream& is)\n{\n  octave_idx_type len = 0;\n  dim_vector dv (1, 1);\n  bool success = true;\n\n  // KLUGE: earlier Octave versions did not save extra dimensions with struct,\n  // and as a result did not preserve dimensions for empty structs.\n  // The default dimensions were 1x1, which we want to preserve.\n  string_vector keywords(2);\n\n  keywords[0] = \"ndims\";\n  keywords[1] = \"length\";\n\n  std::string kw;\n\n  if (extract_keyword (is, keywords, kw, len, true))\n    {\n      if (kw == keywords[0])\n        {\n          int mdims = std::max (static_cast<int> (len), 2);\n          dv.resize (mdims);\n          for (int i = 0; i < mdims; i++)\n            is >> dv(i);\n\n          success = extract_keyword (is, keywords[1], len);\n        }\n    }\n  else\n    success = false;\n\n  if (! success || len < 0)\n    error (\"load: failed to extract number of elements in structure\");\n\n  if (len > 0)\n    {\n      octave_map m (dv);\n\n      for (octave_idx_type j = 0; j < len; j++)\n        {\n          octave_value t2;\n          bool dummy;\n\n          // recurse to read cell elements\n          std::string nm = read_text_data (is, \"\", dummy, t2, j, false);\n\n          if (! is)\n            break;\n\n          Cell tcell = (t2.iscell () ? t2.xcell_value (\"load: internal error loading struct elements\") :\n                        Cell (t2));\n\n          m.setfield (nm, tcell);\n        }\n\n      if (! is)\n        error (\"load: failed to load structure\");\n\n      m_map = m;\n    }\n  else if (len == 0)\n    m_map = octave_map (dv);\n  else\n    error (\"unexpected: len < 0 in octave_struct::load_ascii - please report this bug\");\n\n  return success;\n}\n\nbool\noctave_struct::save_binary (std::ostream& os, bool save_as_floats)\n{\n  octave_map m = map_value ();\n\n  octave_idx_type nf = m.nfields ();\n\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 1)\n    return false;\n\n  // Use negative value for ndims\n  int32_t di = - dv.ndims ();\n  os.write (reinterpret_cast<char *> (&di), 4);\n  for (int i = 0; i < dv.ndims (); i++)\n    {\n      di = dv(i);\n      os.write (reinterpret_cast<char *> (&di), 4);\n    }\n\n  int32_t len = nf;\n  os.write (reinterpret_cast<char *> (&len), 4);\n\n  // Iterating over the list of keys will preserve the order of the\n  // fields.\n  string_vector keys = m.fieldnames ();\n\n  for (octave_idx_type i = 0; i < nf; i++)\n    {\n      std::string key = keys(i);\n\n      octave_value val = m_map.contents (key);\n\n      bool b = save_binary_data (os, val, key, \"\", 0, save_as_floats);\n\n      if (! b)\n        return ! os.fail ();\n    }\n\n  return true;\n}\n\nbool\noctave_struct::load_binary (std::istream& is, bool swap,\n                            octave::mach_info::float_format fmt)\n{\n  bool success = true;\n  int32_t len;\n  if (! is.read (reinterpret_cast<char *> (&len), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&len);\n\n  dim_vector dv (1, 1);\n\n  if (len < 0)\n    {\n      // We have explicit dimensions.\n      int mdims = -len;\n\n      int32_t di;\n      dv.resize (mdims);\n\n      for (int i = 0; i < mdims; i++)\n        {\n          if (! is.read (reinterpret_cast<char *> (&di), 4))\n            return false;\n          if (swap)\n            swap_bytes<4> (&di);\n          dv(i) = di;\n        }\n\n      if (! is.read (reinterpret_cast<char *> (&len), 4))\n        return false;\n      if (swap)\n        swap_bytes<4> (&len);\n    }\n\n  if (len > 0)\n    {\n      octave_map m (dv);\n\n      for (octave_idx_type j = 0; j < len; j++)\n        {\n          octave_value t2;\n          bool dummy;\n          std::string doc;\n\n          // recurse to read cell elements\n          std::string nm = read_binary_data (is, swap, fmt, \"\",\n                                             dummy, t2, doc);\n\n          if (! is)\n            break;\n\n          Cell tcell = (t2.iscell () ? t2.xcell_value (\"load: internal error loading struct elements\") :\n                        Cell (t2));\n\n          m.setfield (nm, tcell);\n        }\n\n      if (! is)\n        error (\"load: failed to load structure\");\n\n      m_map = m;\n    }\n  else if (len == 0)\n    m_map = octave_map (dv);\n  else\n    success = false;\n\n  return success;\n}\n\nbool\noctave_struct::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                          bool save_as_floats)\n{\n#if defined (HAVE_HDF5)\n\n  hid_t data_hid = -1;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Gcreate (loc_id, name, 0);\n#endif\n  if (data_hid < 0) return false;\n\n  // recursively add each element of the structure to this group\n  octave_map m = map_value ();\n\n  octave_idx_type nf = m.nfields ();\n\n  // Iterating over the list of keys will preserve the order of the\n  // fields.\n  string_vector keys = m.fieldnames ();\n\n  for (octave_idx_type i = 0; i < nf; i++)\n    {\n      std::string key = keys(i);\n\n      octave_value val = m_map.contents (key);\n\n      bool retval2 = add_hdf5_data (data_hid, val, key, \"\", false,\n                                    save_as_floats);\n\n      if (! retval2)\n        break;\n    }\n\n  H5Gclose (data_hid);\n\n  return true;\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n\n  return false;\n#endif\n}\n\nbool\noctave_struct::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hdf5_callback_data dsub;\n\n  herr_t retval2 = 0;\n  octave_map m (dim_vector (1, 1));\n  int current_item = 0;\n  hsize_t num_obj = 0;\n#if defined (HAVE_HDF5_18)\n  hid_t group_id = H5Gopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t group_id = H5Gopen (loc_id, name);\n#endif\n  H5Gget_num_objs (group_id, &num_obj);\n  H5Gclose (group_id);\n\n  // FIXME: fields appear to be sorted alphabetically on loading.\n  // Why is that happening?\n\n  while (current_item < static_cast<int> (num_obj)\n         && (retval2 = hdf5_h5g_iterate (loc_id, name, &current_item,\n                                         &dsub)) > 0)\n    {\n      octave_value t2 = dsub.tc;\n\n      Cell tcell = (t2.iscell () ? t2.xcell_value (\"load: internal error loading struct elements\") :\n                    Cell (t2));\n\n      m.setfield (dsub.name, tcell);\n\n    }\n\n  if (retval2 >= 0)\n    {\n      m_map = m;\n      retval = true;\n    }\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nmxArray *\noctave_struct::as_mxArray (bool interleaved) const\n{\n  int nf = nfields ();\n  string_vector kv = map_keys ();\n\n  OCTAVE_LOCAL_BUFFER (const char *, f, nf);\n\n  for (int i = 0; i < nf; i++)\n    f[i] = kv[i].c_str ();\n\n  mxArray *retval = new mxArray (interleaved, dims (), nf, f);\n\n  mxArray **elts = static_cast<mxArray **> (retval->get_data ());\n\n  mwSize nel = numel ();\n\n  mwSize ntot = nf * nel;\n\n  for (int i = 0; i < nf; i++)\n    {\n      Cell c = m_map.contents (kv[i]);\n\n      const octave_value *p = c.data ();\n\n      mwIndex k = 0;\n      for (mwIndex j = i; j < ntot; j += nf)\n        elts[j] = new mxArray (interleaved, p[k++]);\n    }\n\n  return retval;\n}\n\noctave_value\noctave_struct::fast_elem_extract (octave_idx_type n) const\n{\n  if (n < m_map.numel ())\n    return m_map.checkelem (n);\n  else\n    return octave_value ();\n}\n\nbool\noctave_struct::fast_elem_insert (octave_idx_type n,\n                                 const octave_value& x)\n{\n  bool retval = false;\n\n  if (n < m_map.numel ())\n    {\n      // To avoid copying the scalar struct, it just stores a pointer to\n      // itself.\n      const octave_scalar_map *sm_ptr;\n      void *here = reinterpret_cast<void *> (&sm_ptr);\n      return (x.get_rep ().fast_elem_insert_self (here, btyp_struct)\n              && m_map.fast_elem_insert (n, *sm_ptr));\n    }\n\n  return retval;\n}\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_scalar_struct, \"scalar struct\",\n                                    \"struct\");\n\nvoid\noctave_scalar_struct::break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame)\n{\n  for (octave_idx_type i = 0; i < m_map.nfields (); i++)\n    m_map.contents(i).break_closure_cycles (frame);\n}\n\noctave_value\noctave_scalar_struct::dotref (const octave_value_list& idx, bool auto_add)\n{\n  octave_value retval;\n\n  panic_if (idx.length () != 1);\n\n  std::string nm = idx(0).string_value ();\n\n  maybe_warn_invalid_field_name (nm, \"subsref\");\n\n  retval = m_map.getfield (nm);\n\n  if (! auto_add && retval.is_undefined ())\n    error_with_id (\"Octave:invalid-indexing\",\n                   \"structure has no member '%s'\", nm.c_str ());\n\n  return retval;\n}\n\noctave_value\noctave_scalar_struct::subsref (const std::string& type,\n                               const std::list<octave_value_list>& idx)\n{\n  octave_value retval;\n\n  if (type[0] == '.')\n    {\n      int skip = 1;\n\n      retval = dotref (idx.front ());\n\n      if (idx.size () > 1)\n        retval = retval.next_subsref (type, idx, skip);\n    }\n  else\n    retval = to_array ().subsref (type, idx);\n\n  return retval;\n}\n\noctave_value_list\noctave_scalar_struct::subsref (const std::string& type,\n                               const std::list<octave_value_list>& idx,\n                               int nargout)\n{\n  octave_value_list retval;\n\n  if (type[0] == '.')\n    {\n      int skip = 1;\n\n      retval(0) = dotref (idx.front ());\n\n      if (idx.size () > 1)\n        retval = retval(0).next_subsref (nargout, type, idx, skip);\n    }\n  else\n    retval = to_array ().subsref (type, idx, nargout);\n\n  return retval;\n}\n\noctave_value\noctave_scalar_struct::subsref (const std::string& type,\n                               const std::list<octave_value_list>& idx,\n                               bool auto_add)\n{\n  octave_value retval;\n\n  if (type[0] == '.')\n    {\n      int skip = 1;\n\n      retval = dotref (idx.front (), auto_add);\n\n      if (idx.size () > 1)\n        retval = retval.next_subsref (auto_add, type, idx, skip);\n    }\n  else\n    retval = to_array ().subsref (type, idx, auto_add);\n\n  return retval;\n}\n\n/*\n%!test\n%! x(1).a.a = 1;\n%! x(2).a.a = 2;\n%! assert (size (x), [1, 2]);\n%! assert (x(1).a.a, 1);\n%! assert (x(2).a.a, 2);\n*/\n\noctave_value\noctave_scalar_struct::numeric_conv (const octave_value& val,\n                                    const std::string& type)\n{\n  octave_value retval;\n\n  if (type.length () > 0 && type[0] == '.' && ! val.isstruct ())\n    retval = octave_map ();\n  else\n    retval = val;\n\n  return retval;\n}\n\noctave_value\noctave_scalar_struct::subsasgn (const std::string& type,\n                                const std::list<octave_value_list>& idx,\n                                const octave_value& rhs)\n{\n  octave_value retval;\n\n  if (idx.front ().empty ())\n    error (\"subsasgn: missing index in indexed assignment\");\n\n  if (type[0] == '.')\n    {\n      int n = type.length ();\n\n      octave_value t_rhs = rhs;\n\n      const octave_value_list& key_idx = idx.front ();\n\n      if (key_idx.length () != 1)\n        error (\"subsasgn: structure field names must be strings\");\n\n      std::string key\n        = key_idx(0).xstring_value (\"subsasgn: structure field names must be strings\");\n\n      maybe_warn_invalid_field_name (key, \"subsasgn\");\n\n      if (n > 1)\n        {\n          std::list<octave_value_list> next_idx (std::next (idx.begin ()),\n                                                 idx.end ());\n\n          std::string next_type = type.substr (1);\n\n          octave_value tmp;\n          auto pkey = m_map.seek (key);\n          if (pkey != m_map.end ())\n            {\n              m_map.contents (pkey).make_unique ();\n              tmp = m_map.contents (pkey);\n            }\n\n          bool orig_undefined = tmp.is_undefined ();\n\n          if (orig_undefined || tmp.is_zero_by_zero ())\n            {\n              tmp = octave_value::empty_conv (next_type, rhs);\n              tmp.make_unique (); // probably a no-op.\n            }\n          else\n            // optimization: ignore the copy still stored inside our m_map.\n            tmp.make_unique (1);\n\n          t_rhs = (orig_undefined\n                   ? tmp.undef_subsasgn (next_type, next_idx, rhs)\n                   : tmp.subsasgn (next_type, next_idx, rhs));\n        }\n\n      m_map.setfield (key, t_rhs.storable_value ());\n\n      m_count++;\n      retval = this;\n    }\n  else\n    {\n      // Forward this case to octave_struct.\n      octave_value tmp (new octave_struct (octave_map (m_map)));\n      retval = tmp.subsasgn (type, idx, rhs);\n    }\n\n  return retval;\n}\n\n/*\n%!test\n%! x = struct ();\n%! idx = struct (\"type\", \".\", \"subs\", {\"a\", \"b\"});\n%! x = subsasgn (x, idx, 42);\n%! assert (x.a.b, 42);\n\n%!test <*64213>\n%! x = struct ();\n%! idx = struct (\"type\", \".\", \"subs\", {{\"a\", \"b\"}});\n%! fail (\"x = subsasgn (x, idx, 42)\", ...\n%!       \"structure field names must be strings\");\n*/\n\noctave_value\noctave_scalar_struct::do_index_op (const octave_value_list& idx, bool resize_ok)\n{\n  // octave_map handles indexing itself.\n  return octave_map (m_map).index (idx, resize_ok);\n}\n\nstd::size_t\noctave_scalar_struct::byte_size () const\n{\n  // Neglect the size of the fieldnames.\n\n  std::size_t retval = 0;\n\n  for (auto p = m_map.cbegin (); p != m_map.cend (); p++)\n    {\n      std::string key = m_map.key (p);\n\n      octave_value val = octave_value (m_map.contents (p));\n\n      retval += val.byte_size ();\n    }\n\n  return retval;\n}\n\nvoid\noctave_scalar_struct::print (std::ostream& os, bool)\n{\n  print_raw (os);\n}\n\nvoid\noctave_scalar_struct::print_raw (std::ostream& os, bool) const\n{\n  octave::unwind_protect_var<int> restore_var (Vstruct_levels_to_print);\n\n  if (Vstruct_levels_to_print >= 0)\n    {\n      bool max_depth_reached = (Vstruct_levels_to_print-- == 0);\n\n      bool print_fieldnames_only = max_depth_reached;\n\n      increment_indent_level ();\n      increment_indent_level ();\n\n      string_vector key_list = m_map.fieldnames ();\n\n      for (octave_idx_type i = 0; i < key_list.numel (); i++)\n        {\n          std::string key = key_list[i];\n\n          octave_value val = m_map.contents (key);\n\n          if (print_fieldnames_only)\n            {\n              indent (os);\n              os << key;\n              const dim_vector& dv = val.dims ();\n              os << \": \" << dv.str () << ' ' << val.type_name ();\n              newline (os);\n            }\n          else\n            val.print_with_name (os, key);\n        }\n\n      decrement_indent_level ();\n      decrement_indent_level ();\n    }\n  else\n    {\n      indent (os);\n      os << \"<structure>\";\n      newline (os);\n    }\n}\n\nbool\noctave_scalar_struct::print_name_tag (std::ostream& os,\n                                      const std::string& name) const\n{\n  bool retval = false;\n\n  indent (os);\n\n  if (Vstruct_levels_to_print < 0)\n    os << name << \" = \";\n  else\n    {\n      os << name << \" =\";\n      newline (os);\n      if (! Vcompact_format)\n        newline (os);\n\n      increment_indent_level ();\n\n      indent (os);\n      os << \"scalar structure containing the fields:\";\n      newline (os);\n      if (! Vcompact_format)\n        newline (os);\n\n      decrement_indent_level ();\n\n      retval = true;\n    }\n\n  return retval;\n}\n\nstd::string\noctave_scalar_struct::edit_display (const float_display_format&,\n                                    octave_idx_type r, octave_idx_type) const\n{\n  // Scalar struct.  Rows are fields, single column for values.\n\n  octave_value val = m_map.contents (r);\n\n  std::string tname = val.type_name ();\n  const dim_vector& dv = val.dims ();\n  std::string dimstr = dv.str ();\n  return \"[\" + dimstr + \" \" + tname + \"]\";\n}\n\nbool\noctave_scalar_struct::save_ascii (std::ostream& os)\n{\n  octave_map m = map_value ();\n\n  octave_idx_type nf = m.nfields ();\n\n  const dim_vector dv = dims ();\n\n  os << \"# ndims: \" << dv.ndims () << \"\\n\";\n\n  for (int i = 0; i < dv.ndims (); i++)\n    os << ' ' << dv(i);\n  os << \"\\n\";\n\n  os << \"# length: \" << nf << \"\\n\";\n\n  // Iterating over the list of keys will preserve the order of the\n  // fields.\n  string_vector keys = m.fieldnames ();\n\n  for (octave_idx_type i = 0; i < nf; i++)\n    {\n      std::string key = keys(i);\n\n      octave_value val = m_map.contents (key);\n\n      bool b = save_text_data (os, val, key, false, 0);\n\n      if (! b)\n        return ! os.fail ();\n    }\n\n  return true;\n}\n\nbool\noctave_scalar_struct::load_ascii (std::istream& is)\n{\n  octave_idx_type len = 0;\n\n  if (! extract_keyword (is, \"length\", len) || len < 0)\n    error (\"load: failed to extract number of elements in structure\");\n\n  if (len > 0)\n    {\n      octave_scalar_map m;\n\n      for (octave_idx_type j = 0; j < len; j++)\n        {\n          octave_value t2;\n          bool dummy;\n\n          // recurse to read cell elements\n          std::string nm\n            = read_text_data (is, \"\", dummy, t2, j, false);\n\n          if (! is)\n            break;\n\n          m.setfield (nm, t2);\n        }\n\n      if (! is)\n        error (\"load: failed to load structure\");\n\n      m_map = m;\n    }\n  else if (len == 0)\n    m_map = octave_scalar_map ();\n  else\n    error (\"unexpected: len < 0 in octave_scalar_struct::load_ascii - please report this bug\");\n\n  return true;\n}\n\nbool\noctave_scalar_struct::save_binary (std::ostream& os, bool save_as_floats)\n{\n  octave_map m = map_value ();\n\n  octave_idx_type nf = m.nfields ();\n\n  int32_t len = nf;\n  os.write (reinterpret_cast<char *> (&len), 4);\n\n  // Iterating over the list of keys will preserve the order of the\n  // fields.\n  string_vector keys = m.fieldnames ();\n\n  for (octave_idx_type i = 0; i < nf; i++)\n    {\n      std::string key = keys(i);\n\n      octave_value val = m_map.contents (key);\n\n      bool b = save_binary_data (os, val, key, \"\", 0, save_as_floats);\n\n      if (! b)\n        return ! os.fail ();\n    }\n\n  return true;\n}\n\nbool\noctave_scalar_struct::load_binary (std::istream& is, bool swap,\n                                   octave::mach_info::float_format fmt)\n{\n  bool success = true;\n  int32_t len;\n  if (! is.read (reinterpret_cast<char *> (&len), 4))\n    return false;\n  if (swap)\n    swap_bytes<4> (&len);\n\n  if (len > 0)\n    {\n      octave_scalar_map m;\n\n      for (octave_idx_type j = 0; j < len; j++)\n        {\n          octave_value t2;\n          bool dummy;\n          std::string doc;\n\n          // recurse to read cell elements\n          std::string nm = read_binary_data (is, swap, fmt, \"\",\n                                             dummy, t2, doc);\n\n          if (! is)\n            break;\n\n          m.setfield (nm, t2);\n        }\n\n      if (! is)\n        error (\"load: failed to load structure\");\n\n      m_map = m;\n    }\n  else if (len == 0)\n    m_map = octave_scalar_map ();\n  else\n    success = false;\n\n  return success;\n}\n\nbool\noctave_scalar_struct::save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                                 bool save_as_floats)\n{\n#if defined (HAVE_HDF5)\n\n  hid_t data_hid = -1;\n\n#if defined (HAVE_HDF5_18)\n  data_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,\n                        octave_H5P_DEFAULT);\n#else\n  data_hid = H5Gcreate (loc_id, name, 0);\n#endif\n  if (data_hid < 0) return false;\n\n  // recursively add each element of the structure to this group\n  octave_scalar_map m = scalar_map_value ();\n\n  octave_idx_type nf = m.nfields ();\n\n  // Iterating over the list of keys will preserve the order of the\n  // fields.\n  string_vector keys = m.fieldnames ();\n\n  for (octave_idx_type i = 0; i < nf; i++)\n    {\n      std::string key = keys(i);\n\n      octave_value val = m_map.contents (key);\n\n      bool retval2 = add_hdf5_data (data_hid, val, key, \"\", false,\n                                    save_as_floats);\n\n      if (! retval2)\n        break;\n    }\n\n  H5Gclose (data_hid);\n\n  return true;\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n  octave_unused_parameter (save_as_floats);\n\n  warn_save (\"hdf5\");\n\n  return false;\n#endif\n}\n\nbool\noctave_scalar_struct::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool retval = false;\n\n#if defined (HAVE_HDF5)\n\n  hdf5_callback_data dsub;\n\n  herr_t retval2 = 0;\n  octave_scalar_map m;\n  int current_item = 0;\n  hsize_t num_obj = 0;\n#if defined (HAVE_HDF5_18)\n  hid_t group_id = H5Gopen (loc_id, name, octave_H5P_DEFAULT);\n#else\n  hid_t group_id = H5Gopen (loc_id, name);\n#endif\n  H5Gget_num_objs (group_id, &num_obj);\n  H5Gclose (group_id);\n\n  // FIXME: fields appear to be sorted alphabetically on loading.\n  // Why is that happening?\n\n  while (current_item < static_cast<int> (num_obj)\n         && (retval2 = hdf5_h5g_iterate (loc_id, name, &current_item,\n                                         &dsub)) > 0)\n    {\n      octave_value t2 = dsub.tc;\n\n      m.setfield (dsub.name, t2);\n\n    }\n\n  if (retval2 >= 0)\n    {\n      m_map = m;\n      retval = true;\n    }\n\n#else\n  octave_unused_parameter (loc_id);\n  octave_unused_parameter (name);\n\n  warn_load (\"hdf5\");\n#endif\n\n  return retval;\n}\n\nmxArray *\noctave_scalar_struct::as_mxArray (bool interleaved) const\n{\n  int nf = nfields ();\n  string_vector kv = map_keys ();\n\n  OCTAVE_LOCAL_BUFFER (const char *, f, nf);\n\n  for (int i = 0; i < nf; i++)\n    f[i] = kv[i].c_str ();\n\n  mxArray *retval = new mxArray (interleaved, dims (), nf, f);\n\n  mxArray **elts = static_cast<mxArray **> (retval->get_data ());\n\n  mwSize nel = numel ();\n\n  mwSize ntot = nf * nel;\n\n  for (int i = 0; i < nf; i++)\n    {\n      Cell c = m_map.contents (kv[i]);\n\n      const octave_value *p = c.data ();\n\n      mwIndex k = 0;\n      for (mwIndex j = i; j < ntot; j += nf)\n        elts[j] = new mxArray (interleaved, p[k++]);\n    }\n\n  return retval;\n}\n\noctave_value\noctave_scalar_struct::to_array ()\n{\n  return new octave_struct (octave_map (m_map));\n}\n\nbool\noctave_scalar_struct::fast_elem_insert_self (void *where,\n    builtin_type_t btyp) const\n{\n\n  if (btyp == btyp_struct)\n    {\n      *(reinterpret_cast<const octave_scalar_map **> (where)) = &m_map;\n      return true;\n    }\n  else\n    return false;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (struct, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{s} =} struct ()\n@deftypefnx {} {@var{s} =} struct (@var{field1}, @var{value1}, @var{field2}, @var{value2}, @dots{})\n@deftypefnx {} {@var{s} =} struct (@var{obj})\n\nCreate a scalar or array structure and initialize its values.\n\nThe @var{field1}, @var{field2}, @dots{} variables are strings specifying the\nnames of the fields and the @var{value1}, @var{value2}, @dots{} variables\ncan be of any type.\n\nIf the values are cell arrays, create a structure array and initialize its\nvalues.  The dimensions of each cell array of values must match.  Singleton\ncells and non-cell values are repeated so that they fill the entire array.\nIf the cells are empty, create an empty structure array with the specified\nfield names.\n\nIf the argument is an object, return the underlying struct.\n\nObserve that the syntax is optimized for struct @strong{arrays}.  Consider\nthe following examples:\n\n@example\n@group\nstruct (\"foo\", 1)\n  @xresult{} scalar structure containing the fields:\n    foo =  1\n\nstruct (\"foo\", @{@})\n  @xresult{} 0x0 struct array containing the fields:\n    foo\n\nstruct (\"foo\", @{ @{@} @})\n  @xresult{} scalar structure containing the fields:\n    foo = @{@}(0x0)\n\nstruct (\"foo\", @{1, 2, 3@})\n  @xresult{} 1x3 struct array containing the fields:\n    foo\n\n@end group\n@end example\n\n@noindent\nThe first case is an ordinary scalar struct---one field, one value.  The\nsecond produces an empty struct array with one field and no values, since\nbeing passed an empty cell array of struct array values.  When the value is\na cell array containing a single entry, this becomes a scalar struct with\nthat single entry as the value of the field.  That single entry happens\nto be an empty cell array.\n\nFinally, if the value is a nonscalar cell array, then @code{struct}\nproduces a struct @strong{array}.\n@seealso{cell2struct, fieldnames, getfield, setfield, rmfield, isfield,\norderfields, isstruct, structfun}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  // struct ([]) returns an empty struct.\n\n  // struct (empty_matrix) or struct (empty_matrix, cell_array_of field_names)\n  // return an empty struct with the same dimensions as the empty matrix.\n\n  // Note that struct () creates a 1x1 struct with no fields for\n  // compatibility with Matlab.\n\n  if (nargin == 1 && args(0).isstruct ())\n    return ovl (args(0));\n\n  if (nargin == 1 && args(0).isobject ())\n    return ovl (args(0).map_value ());\n\n  if ((nargin == 1 || nargin == 2)\n      && args(0).isempty () && args(0).is_real_matrix ()\n      && ! args(0).is_char_matrix ())\n    {\n      if (nargin == 2)\n        {\n          Array<std::string> cstr = args(1).xcellstr_value (\"struct: second argument should be a cell array of field names\");\n\n          return ovl (octave_map (args(0).dims (), cstr));\n        }\n      else\n        return ovl (octave_map (args(0).dims ()));\n    }\n\n  // Check for \"field\", VALUE pairs.\n\n  for (int i = 0; i < nargin; i += 2)\n    {\n      if (! args(i).is_string () || i + 1 >= nargin)\n        error (R\"(struct: additional arguments must occur as \"field\", VALUE pairs)\");\n    }\n\n  // Check that the dimensions of the values correspond.\n\n  dim_vector dims (1, 1);\n\n  int first_dimensioned_value = 0;\n\n  for (int i = 1; i < nargin; i += 2)\n    {\n      if (args(i).iscell ())\n        {\n          const dim_vector& argdims = args(i).dims ();\n\n          if (! scalar (argdims))\n            {\n              if (! first_dimensioned_value)\n                {\n                  dims = argdims;\n                  first_dimensioned_value = i + 1;\n                }\n              else if (dims != argdims)\n                {\n                  error (\"struct: dimensions of parameter %d \"\n                         \"do not match those of parameter %d\",\n                         first_dimensioned_value, i+1);\n                }\n            }\n        }\n    }\n\n  // Create the return value.\n\n  octave_map m_map (dims);\n\n  for (int i = 0; i < nargin; i+= 2)\n    {\n      // Get key.\n\n      std::string key (args(i).string_value ());\n\n      maybe_warn_invalid_field_name (key, \"struct\");\n\n      // Value may be v, { v }, or { v1, v2, ... }\n      // In the first two cases, we need to create a cell array of\n      // the appropriate dimensions filled with v.  In the last case,\n      // the cell array has already been determined to be of the\n      // correct dimensions.\n\n      if (args(i+1).iscell ())\n        {\n          const Cell c (args(i+1).cell_value ());\n\n          if (scalar (c.dims ()))\n            m_map.setfield (key, Cell (dims, c(0)));\n          else\n            m_map.setfield (key, c);\n        }\n      else\n        m_map.setfield (key, Cell (dims, args(i+1)));\n    }\n\n  return ovl (m_map);\n}\n\n/*\n%!shared x\n%! x(1).a=1;  x(2).a=2;  x(1).b=3;  x(2).b=3;\n%!assert (struct (\"a\",1, \"b\",3), x(1))\n%!assert (isempty (x([])))\n%!assert (isempty (struct (\"a\",{}, \"b\",{})))\n%!assert (struct (\"a\",{1,2}, \"b\",{3,3}), x)\n%!assert (struct (\"a\",{1,2}, \"b\",3), x)\n%!assert (struct (\"a\",{1,2}, \"b\",{3}), x)\n%!assert (struct (\"b\",3, \"a\",{1,2}), x)\n%!assert (struct (\"b\",{3}, \"a\",{1,2}), x)\n%!test x = struct ([]);\n%!assert (size (x), [0,0])\n%!assert (isstruct (x))\n%!assert (isempty (fieldnames (x)))\n%!fail ('struct (\"a\",{1,2},\"b\",{1,2,3})',\n%!      'dimensions of parameter 2 do not match those of parameter 4')\n%!error <arguments must occur as \"field\", VALUE pairs> struct (1,2,3,4)\n%!fail ('struct (\"1\",2,\"3\")',\n%!      'struct: additional arguments must occur as \"field\", VALUE pairs')\n\n%!test <*67255>  # Test empty string as field name\n% s.('') = 3;\n% assert (struct ('', 3), s)\n*/\n\nDEFUN (isstruct, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isstruct (@var{x})\nReturn true if @var{x} is a structure or a structure array.\n@seealso{ismatrix, iscell, isa}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).isstruct ());\n}\n\nDEFUN (__fieldnames__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{names} =} __fieldnames__ (@var{struct})\n@deftypefnx {} {@var{names} =} __fieldnames__ (@var{obj})\nInternal function.\n\nImplements @code{fieldnames()} for structures and Octave objects.\n@seealso{fieldnames}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  // Input validation has already been done in fieldnames.m.\n  octave_value arg = args(0);\n\n  octave_map m = arg.map_value ();\n\n  string_vector keys = m.fieldnames ();\n\n  if (keys.isempty ())\n    retval = Cell (0, 1);\n  else\n    retval = Cell (keys);\n\n  return retval;\n}\n\nDEFUN (isfield, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{tf} =} isfield (@var{x}, \"@var{name}\")\n@deftypefnx {} {@var{tf} =} isfield (@var{x}, @var{name})\nReturn true if the @var{x} is a structure and it includes an element named\n@var{name}.\n\nIf @var{name} is a cell array of strings then a logical array of equal\ndimension is returned.\n@seealso{fieldnames}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_value retval = false;\n\n  if (args(0).isstruct ())\n    {\n      octave_value m = args(0);\n\n      // FIXME: should this work for all types that can do\n      // structure reference operations?\n      if (args(1).is_string ())\n        {\n          std::string key = args(1).string_value ();\n\n          retval = m.isfield (key);\n        }\n      else if (args(1).iscell ())\n        {\n          Cell c = args(1).cell_value ();\n          boolNDArray bm (c.dims ());\n          octave_idx_type n = bm.numel ();\n\n          for (octave_idx_type i = 0; i < n; i++)\n            {\n              if (c(i).is_string ())\n                {\n                  std::string key = c(i).string_value ();\n\n                  bm(i) = m.isfield (key);\n                }\n              else\n                bm(i) = false;\n            }\n\n          retval = bm;\n        }\n    }\n\n  return retval;\n}\n\nDEFUN (numfields, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} numfields (@var{s})\nReturn the number of fields of the structure @var{s}.\n@seealso{fieldnames}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  if (! args(0).isstruct ())\n    error (\"numfields: argument must be a struct\");\n\n  return ovl (static_cast<double> (args(0).nfields ()));\n}\n\n/*\n## test isfield\n%!test\n%! x(3).d=1;  x(2).a=2;  x(1).b=3;  x(2).c=3;\n%! assert (isfield (x, \"b\"));\n%!assert (isfield (struct (\"a\", \"1\"), \"a\"))\n%!assert (isfield ({1}, \"c\"), false)\n%!assert (isfield (struct (\"a\", \"1\"), 10), false)\n%!assert (isfield (struct (\"a\", \"b\"), \"a \"), false)\n%!assert (isfield (struct (\"a\", 1, \"b\", 2), {\"a\", \"c\"}), [true, false])\n*/\n\nOCTAVE_NORETURN\nstatic void\ninvalid_cell2struct_fields_error ()\n{\n  error (\"cell2struct: FIELDS must be a cell array of strings or a scalar string\");\n}\n\nstatic Array<std::string>\nget_cell2struct_fields (const octave_value& arg)\n{\n  if (arg.is_string ())\n    {\n      if (arg.rows () > 1)\n        invalid_cell2struct_fields_error ();\n\n      return Array<std::string> (dim_vector (1, 1), arg.string_value ());\n    }\n\n  if (arg.iscell ())\n    {\n      const Cell c = arg.cell_value ();\n\n      Array<std::string> retval (c.dims ());\n\n      for (octave_idx_type i = 0; i < c.numel (); i++)\n        {\n          const octave_value val = c(i);\n\n          if (! val.is_string () || val.rows () > 1)\n            invalid_cell2struct_fields_error ();\n\n          retval(i) = c(i).string_value ();\n        }\n\n      return retval;\n    }\n\n  invalid_cell2struct_fields_error ();\n}\n\nDEFUN (cell2struct, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{S} =} cell2struct (@var{cell}, @var{fields})\n@deftypefnx {} {@var{S} =} cell2struct (@var{cell}, @var{fields}, @var{dim})\nConvert @var{cell} to a structure.\n\nThe number of fields in @var{fields} must match the number of elements in\n@var{cell} along dimension @var{dim}, that is\n@code{numel (@var{fields}) == size (@var{cell}, @var{dim})}.  If @var{dim}\nis omitted, a value of 1 is assumed.\n\n@example\n@group\nS = cell2struct (@{\"Peter\", \"Hannah\", \"Robert\";\n                   185, 170, 168@},\n                 @{\"Name\",\"Height\"@}, 1);\nS(1)\n   @xresult{}\n      @{\n        Name   = Peter\n        Height = 185\n      @}\n\n@end group\n@end example\n@seealso{struct2cell, cell2mat, struct}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  const Cell vals = args(0).xcell_value (\"cell2struct: argument CELL must be of type cell\");\n\n  const Array<std::string> fields = get_cell2struct_fields (args(1));\n\n  int dim = 0;\n\n  if (nargin == 3)\n    {\n      if (! args(2).is_real_scalar ())\n        error (\"cell2struct: DIM must be a real scalar\");\n\n      dim = args(2).int_value () - 1;\n    }\n\n  if (dim < 0)\n    error (\"cell2struct: DIM must be a valid dimension\");\n\n  octave_idx_type ext = (vals.ndims () > dim ? vals.dims ()(dim) : 1);\n\n  if (ext != fields.numel ())\n    error (\"cell2struct: number of FIELDS does not match dimension\");\n\n  int nd = std::max (dim+1, vals.ndims ());\n  // result dimensions.\n  dim_vector rdv = vals.dims ().redim (nd);\n\n  panic_unless (ext == rdv(dim));\n  if (nd == 2)\n    {\n      rdv(0) = rdv(1-dim);\n      rdv(1) = 1;\n    }\n  else\n    {\n      for (int i = dim + 1; i < nd; i++)\n        rdv(i-1) = rdv(i);\n\n      rdv.resize (nd-1);\n    }\n\n  octave_map m_map (rdv);\n  Array<idx_vector> ia (dim_vector (nd, 1), idx_vector::colon);\n\n  for (octave_idx_type i = 0; i < ext; i++)\n    {\n      ia(dim) = i;\n      m_map.setfield (fields(i), vals.index (ia).reshape (rdv));\n    }\n\n  return ovl (m_map);\n}\n\n/*\n## test cell2struct versus struct2cell\n%!test\n%! keys = cellstr (char (floor (rand (100,10)*24+65)))';\n%! vals = mat2cell (rand (100,1), ones (100,1), 1)';\n%! s = struct ([keys; vals]{:});\n%! t = cell2struct (vals, keys, 2);\n%! assert (s, t);\n%! assert (struct2cell (s), vals');\n%! assert (fieldnames (s), keys');\n\n%!assert (cell2struct ({1; 2}, {\"a\"; \"b\"}), struct (\"a\", 1, \"b\", 2))\n\n%!assert (cell2struct ({}, {\"f\"}, 3), struct (\"f\", {}))\n\n%!assert (cell2struct ({1; 2; 3; 4}, {'a', 'b'; 'c', 'd'}),\n%!        struct ('a', 1, 'c', 2, 'b', 3, 'd', 4));\n%!assert (cell2struct ({1, 2, 3, 4}, {'a', 'b'; 'c', 'd'}, 2),\n%!        struct ('a', 1, 'c', 2, 'b', 3, 'd', 4));\n%!error cell2struct ({1, 2, 3, 4}, {'a', 'b'; 'c', 'd'})\n\n%!test <*67255>  # Test empty string as field name\n% assert (cell2struct ({3}, {''}), struct ('', {3}))\n*/\n\nDEFUN (rmfield, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{sout} =} rmfield (@var{s}, \"@var{f}\")\n@deftypefnx {} {@var{sout} =} rmfield (@var{s}, @var{f})\nReturn a @emph{copy} of the structure (array) @var{s} with the field @var{f}\nremoved.\n\nIf @var{f} is a cell array of strings or a character array, remove each of\nthe named fields.\n@seealso{orderfields, fieldnames, isfield}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  octave_map m = args(0).xmap_value (\"rmfield: first argument must be a struct\");\n\n  octave_value_list fval = Fcellstr (ovl (args(1)), 1);\n\n  Cell fcell = fval(0).cell_value ();\n\n  for (int i = 0; i < fcell.numel (); i++)\n    {\n      std::string key = fcell(i).string_value ();\n\n      if (! m.isfield (key))\n        error (\"rmfield: structure does not contain field %s\", key.c_str ());\n\n      m.rmfield (key);\n    }\n\n  return ovl (m);\n}\n\n/*\n## test rmfield\n%!shared x\n%! x(3).d=1;  x(2).a=2;  x(1).b=3;  x(2).c=3;  x(6).f=\"abc123\";\n%!\n%!test\n%! y = rmfield (x, \"c\");\n%! assert (fieldnames (y), {\"d\"; \"a\"; \"b\"; \"f\"});\n%! assert (size (y), [1, 6]);\n%!test\n%! y = rmfield (x, {\"a\", \"f\"});\n%! assert (fieldnames (y), {\"d\"; \"b\"; \"c\"});\n%! assert (size (y), [1, 6]);\n*/\n\nDEFUN (struct_levels_to_print, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} struct_levels_to_print ()\n@deftypefnx {} {@var{old_val} =} struct_levels_to_print (@var{new_val})\n@deftypefnx {} {@var{old_val} =} struct_levels_to_print (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies the number of\nstructure levels to display.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{print_struct_array_contents}\n@end deftypefn */)\n{\n  return set_internal_variable (Vstruct_levels_to_print, args, nargout,\n                                \"struct_levels_to_print\", -1,\n                                std::numeric_limits<int>::max ());\n}\n\nDEFUN (print_struct_array_contents, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} print_struct_array_contents ()\n@deftypefnx {} {@var{old_val} =} print_struct_array_contents (@var{new_val})\n@deftypefnx {} {@var{old_val} =} print_struct_array_contents (@var{new_val}, \"local\")\nQuery or set the internal variable that specifies whether to print struct\narray contents.\n\nIf true, values of struct array elements are printed.  This variable does\nnot affect scalar structures whose elements are always printed.  In both\ncases, however, printing will be limited to the number of levels specified\nby @var{struct_levels_to_print}.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{struct_levels_to_print}\n@end deftypefn */)\n{\n  return set_internal_variable (Vprint_struct_array_contents, args, nargout,\n                                \"print_struct_array_contents\");\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-struct.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_struct_h)\n#define octave_ov_struct_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n\n#include \"mx-base.h\"\n#include \"str-vec.h\"\n\n#include \"error.h\"\n#include \"oct-map.h\"\n#include \"ov-base.h\"\n#include \"ov-typeinfo.h\"\n\nclass octave_value_list;\n\n// Data structures.\n\nclass octave_struct : public octave_base_value\n{\npublic:\n\n  octave_struct ()\n    : octave_base_value (), m_map () { }\n\n  octave_struct (const octave_map& m)\n    : octave_base_value (), m_map (m) { }\n\n  octave_struct (const octave_struct& s)\n    : octave_base_value (), m_map (s.m_map) { }\n\n  ~octave_struct () = default;\n\n  octave_base_value * clone () const { return new octave_struct (*this); }\n  octave_base_value * empty_clone () const { return new octave_struct (); }\n\n  void break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame);\n\n  octave_base_value * try_narrowing_conversion ();\n\n  Cell dotref (const octave_value_list& idx, bool auto_add = false);\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx)\n  {\n    octave_value_list tmp = subsref (type, idx, 1);\n    return tmp.length () > 0 ? tmp(0) : octave_value ();\n  }\n\n  octave_value_list subsref (const std::string&,\n                             const std::list<octave_value_list>&, int);\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx,\n                        bool auto_add);\n\n  static octave_value numeric_conv (const octave_value& val,\n                                    const std::string& type);\n\n  octave_value subsasgn (const std::string& type,\n                         const std::list<octave_value_list>& idx,\n                         const octave_value& rhs);\n\n  octave_value squeeze () const { return m_map.squeeze (); }\n\n  octave_value permute (const Array<int>& vec, bool inv = false) const\n  { return m_map.permute (vec, inv); }\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  dim_vector dims () const { return m_map.dims (); }\n\n  std::size_t byte_size () const;\n\n  // This is the number of elements in each field.  The total number\n  // of elements is numel () * nfields ().\n  octave_idx_type numel () const\n  {\n    return m_map.numel ();\n  }\n\n  octave_idx_type nfields () const { return m_map.nfields (); }\n\n  octave_value reshape (const dim_vector& new_dims) const\n  { return m_map.reshape (new_dims); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const\n  { octave_map tmap = m_map; tmap.resize (dv, fill); return tmap; }\n\n  bool is_defined () const { return true; }\n\n  bool is_constant () const { return true; }\n\n  bool isstruct () const { return true; }\n\n  builtin_type_t builtin_type () const { return btyp_struct; }\n\n  octave_map map_value () const { return m_map; }\n\n  string_vector map_keys () const { return m_map.fieldnames (); }\n\n  bool isfield (const std::string& field_name) const\n  { return m_map.isfield (field_name); }\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  bool print_name_tag (std::ostream& os, const std::string& name) const;\n\n  std::string edit_display (const float_display_format& fmt,\n                            octave_idx_type i, octave_idx_type j) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  octave_value\n  fast_elem_extract (octave_idx_type n) const;\n\n  bool\n  fast_elem_insert (octave_idx_type n, const octave_value& x);\n\nprotected:\n\n  // The associative array used to manage the structure data.\n  octave_map m_map;\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\nclass octave_scalar_struct : public octave_base_value\n{\npublic:\n\n  octave_scalar_struct ()\n    : octave_base_value (), m_map () { }\n\n  octave_scalar_struct (const octave_scalar_map& m)\n    : octave_base_value (), m_map (m) { }\n\n  octave_scalar_struct (const std::map<std::string, octave_value>& m)\n    : octave_base_value (), m_map (m) { }\n\n  octave_scalar_struct (const octave_scalar_struct& s)\n    : octave_base_value (), m_map (s.m_map) { }\n\n  ~octave_scalar_struct () = default;\n\n  octave_base_value * clone () const\n  { return new octave_scalar_struct (*this); }\n  octave_base_value * empty_clone () const\n  { return new octave_scalar_struct (); }\n\n  void break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame);\n\n  octave_value dotref (const octave_value_list& idx, bool auto_add = false);\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx);\n\n  octave_value_list subsref (const std::string& type,\n                             const std::list<octave_value_list>& idx, int);\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx,\n                        bool auto_add);\n\n  static octave_value numeric_conv (const octave_value& val,\n                                    const std::string& type);\n\n  octave_value subsasgn (const std::string& type,\n                         const std::list<octave_value_list>& idx,\n                         const octave_value& rhs);\n\n  octave_value squeeze () const { return m_map; }\n\n  octave_value permute (const Array<int>& vec, bool inv = false) const\n  { return octave_map (m_map).permute (vec, inv); }\n\n  octave_value do_index_op (const octave_value_list& idx,\n                            bool resize_ok = false);\n\n  dim_vector dims () const { static dim_vector dv (1, 1); return dv; }\n\n  std::size_t byte_size () const;\n\n  // This is the number of elements in each field.  The total number\n  // of elements is numel () * nfields ().\n  octave_idx_type numel () const\n  {\n    return 1;\n  }\n\n  octave_idx_type nfields () const { return m_map.nfields (); }\n\n  octave_value reshape (const dim_vector& new_dims) const\n  { return octave_map (m_map).reshape (new_dims); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const\n  { octave_map tmap = m_map; tmap.resize (dv, fill); return tmap; }\n\n  bool is_defined () const { return true; }\n\n  bool is_constant () const { return true; }\n\n  bool isstruct () const { return true; }\n\n  builtin_type_t builtin_type () const { return btyp_struct; }\n\n  octave_map map_value () const { return m_map; }\n\n  octave_scalar_map scalar_map_value () const { return m_map; }\n\n  string_vector map_keys () const { return m_map.fieldnames (); }\n\n  bool isfield (const std::string& field_name) const\n  { return m_map.isfield (field_name); }\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false);\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;\n\n  bool print_name_tag (std::ostream& os, const std::string& name) const;\n\n  std::string edit_display (const float_display_format& fmt,\n                            octave_idx_type i, octave_idx_type j) const;\n\n  bool save_ascii (std::ostream& os);\n\n  bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats);\n\n  bool load_binary (std::istream& is, bool swap,\n                    octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);\n\n  bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  mxArray * as_mxArray (bool interleaved) const;\n\n  bool fast_elem_insert_self (void *where, builtin_type_t btyp) const;\n\nprotected:\n\n  // The associative array used to manage the structure data.\n  octave_scalar_map m_map;\n\nprivate:\n\n  octave_value to_array ();\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-typeinfo.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n\n#include \"Array.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern void install_ops (type_info& ti);\n\n// FIXME: we should also store all class names and provide a\n// way to list them (calling class with nargin == 0?).\n\nstatic NDArray\nas_nd_array (const Array<int>& x)\n{\n  NDArray retval (x.dims ());\n\n  for (int i = 0; i < x.numel (); i++)\n    retval.xelem(i) = x(i);\n\n  return retval;\n}\n\nstatic boolNDArray\nas_bool_nd_array (const Array<void *>& x)\n{\n  boolNDArray retval (x.dims ());\n\n  for (octave_idx_type i = 0; i < x.numel (); i++)\n    retval.xelem (i) = x(i);\n\n  return retval;\n}\n\ntype_info::type_info (int init_tab_sz)\n  : m_num_types (0), m_types (dim_vector (init_tab_sz, 1), \"\"),\n    m_vals (dim_vector (init_tab_sz, 1)),\n    m_unary_class_ops (dim_vector (octave_value::num_unary_ops, 1), nullptr),\n    m_unary_ops (dim_vector (octave_value::num_unary_ops, init_tab_sz), nullptr),\n    m_non_const_unary_ops (dim_vector (octave_value::num_unary_ops, init_tab_sz), nullptr),\n    m_binary_class_ops (dim_vector (octave_value::num_binary_ops, 1), nullptr),\n    m_binary_ops (dim_vector (octave_value::num_binary_ops, init_tab_sz, init_tab_sz), nullptr),\n    m_compound_binary_class_ops (dim_vector (octave_value::num_compound_binary_ops, 1), nullptr),\n    m_compound_binary_ops (dim_vector (octave_value::num_compound_binary_ops, init_tab_sz, init_tab_sz),\n                           nullptr),\n    m_cat_ops (dim_vector (init_tab_sz, init_tab_sz), nullptr),\n    m_assign_ops (dim_vector (octave_value::num_assign_ops, init_tab_sz, init_tab_sz), nullptr),\n    m_assignany_ops (dim_vector (octave_value::num_assign_ops, init_tab_sz), nullptr),\n    m_pref_assign_conv (dim_vector (init_tab_sz, init_tab_sz), -1),\n    m_widening_ops (dim_vector (init_tab_sz, init_tab_sz), nullptr)\n{\n  install_types (*this);\n\n  install_ops (*this);\n}\n\nint\ntype_info::register_type (const std::string& t_name,\n                          const std::string& /* c_name */,\n                          const octave_value& val,\n                          bool abort_on_duplicate)\n{\n  int i = 0;\n\n  for (i = 0; i < m_num_types; i++)\n    {\n      if (t_name == m_types (i))\n        {\n          if (abort_on_duplicate)\n            {\n              std::cerr << \"duplicate type \" << t_name << std::endl;\n              abort ();\n            }\n\n          warning (\"duplicate type %s\\n\", t_name.c_str ());\n\n          return i;\n        }\n    }\n\n  int len = m_types.numel ();\n\n  if (i == len)\n    {\n      len *= 2;\n\n      m_types.resize (dim_vector (len, 1), \"\");\n\n      m_vals.resize (dim_vector (len, 1), nullptr);\n\n      m_unary_ops.resize\n      (dim_vector (octave_value::num_unary_ops, len), nullptr);\n\n      m_non_const_unary_ops.resize\n      (dim_vector (octave_value::num_unary_ops, len), nullptr);\n\n      m_binary_ops.resize\n      (dim_vector (octave_value::num_binary_ops, len, len), nullptr);\n\n      m_compound_binary_ops.resize\n      (dim_vector (octave_value::num_compound_binary_ops, len, len),\n       nullptr);\n\n      m_cat_ops.resize (dim_vector (len, len), nullptr);\n\n      m_assign_ops.resize\n      (dim_vector (octave_value::num_assign_ops, len, len), nullptr);\n\n      m_assignany_ops.resize\n      (dim_vector (octave_value::num_assign_ops, len), nullptr);\n\n      m_pref_assign_conv.resize (dim_vector (len, len), -1);\n\n      m_widening_ops.resize (dim_vector (len, len), nullptr);\n    }\n\n  m_types (i) = t_name;\n\n  // FIXME: This object is intentionally *not deleted* in the destructor\n  // so that we avoid a crash on exit for user-defined data types.\n  // See bug #53156.  However, this creates a memory leak (not a big one).\n  // If that problem is properly fixed, then this could be stored as an object\n  // instead of a pointer to an object allocated with new.\n\n  m_vals(i) = new octave_value (val);\n\n  m_num_types++;\n\n  return i;\n}\n\nbool\ntype_info::register_unary_class_op (octave_value::unary_op op,\n                                    type_info::unary_class_op_fcn f,\n                                    bool abort_on_duplicate)\n{\n  if (lookup_unary_class_op (op))\n    {\n      std::string op_name = octave_value::unary_op_as_string (op);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"duplicate unary operator '\" << op_name\n                    << \"' for class dispatch\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate unary operator '%s' for class dispatch\",\n               op_name.c_str ());\n    }\n\n  m_unary_class_ops.checkelem (static_cast<int> (op))\n    = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_unary_op (octave_value::unary_op op, int t,\n                              unary_op_fcn f, bool abort_on_duplicate)\n{\n  if (lookup_unary_op (op, t))\n    {\n      std::string op_name = octave_value::unary_op_as_string (op);\n      std::string type_name = m_types(t);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"duplicate unary operator '\" << op_name\n                    << \"' for type '\" << type_name << \"'\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate unary operator '%s' for type '%s'\",\n               op_name.c_str (), type_name.c_str ());\n    }\n\n  m_unary_ops.checkelem (static_cast<int> (op), t) = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_non_const_unary_op (octave_value::unary_op op, int t,\n                                        type_info::non_const_unary_op_fcn f,\n                                        bool abort_on_duplicate)\n{\n  if (lookup_non_const_unary_op (op, t))\n    {\n      std::string op_name = octave_value::unary_op_as_string (op);\n      std::string type_name = m_types(t);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"duplicate unary operator '\" << op_name\n                    << \"' for type '\" << type_name << \"'\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate unary operator '%s' for type '%s'\",\n               op_name.c_str (), type_name.c_str ());\n    }\n\n  m_non_const_unary_ops.checkelem (static_cast<int> (op), t)\n    = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_binary_class_op (octave_value::binary_op op,\n                                     type_info::binary_class_op_fcn f,\n                                     bool abort_on_duplicate)\n{\n  if (lookup_binary_class_op (op))\n    {\n      std::string op_name = octave_value::binary_op_as_string (op);\n\n      if (abort_on_duplicate)\n        {\n\n          std::cerr << \"duplicate binary operator '\" << op_name\n                    << \"' for class dispatch\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate binary operator '%s' for class dispatch\",\n               op_name.c_str ());\n    }\n\n  m_binary_class_ops.checkelem (static_cast<int> (op))\n    = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_binary_op (octave_value::binary_op op,\n                               int t1, int t2,\n                               type_info::binary_op_fcn f,\n                               bool abort_on_duplicate)\n{\n  if (lookup_binary_op (op, t1, t2))\n    {\n      std::string op_name = octave_value::binary_op_as_string (op);\n      std::string t1_name = m_types(t1);\n      std::string t2_name = m_types(t2);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"duplicate binary operator '\" << op_name\n                    << \"' for types '\" << t1_name << \"' and '\"\n                    << t2_name << \"'\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate binary operator '%s' for types '%s' and '%s'\",\n               op_name.c_str (), t1_name.c_str (), t1_name.c_str ());\n    }\n\n  m_binary_ops.checkelem (static_cast<int> (op), t1, t2)\n    = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_binary_class_op (octave_value::compound_binary_op op,\n                                     type_info::binary_class_op_fcn f,\n                                     bool abort_on_duplicate)\n{\n  if (lookup_binary_class_op (op))\n    {\n      std::string op_name = octave_value::binary_op_fcn_name (op);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"duplicate compound binary operator '\"\n                    << op_name << \"' for class dispatch\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate compound binary operator '%s' for class dispatch\",\n               op_name.c_str ());\n    }\n\n  m_compound_binary_class_ops.checkelem (static_cast<int> (op))\n    = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_binary_op (octave_value::compound_binary_op op,\n                               int t1, int t2,\n                               type_info::binary_op_fcn f,\n                               bool abort_on_duplicate)\n{\n  if (lookup_binary_op (op, t1, t2))\n    {\n      std::string op_name = octave_value::binary_op_fcn_name (op);\n      std::string t1_name = m_types(t1);\n      std::string t2_name = m_types(t2);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"duplicate compound binary operator '\"\n                    << op_name << \"' for types '\" << t1_name\n                    << \"' and '\" << t2_name << \"'\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate compound binary operator '%s' for types '%s' and '%s'\",\n               op_name.c_str (), t1_name.c_str (), t1_name.c_str ());\n    }\n\n  m_compound_binary_ops.checkelem (static_cast<int> (op), t1, t2)\n    = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_cat_op (int t1, int t2, type_info::cat_op_fcn f,\n                            bool abort_on_duplicate)\n{\n  if (lookup_cat_op (t1, t2))\n    {\n      std::string t1_name = m_types(t1);\n      std::string t2_name = m_types(t2);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"duplicate concatenation operator for types '\"\n                    << t1_name << \"' and '\" << t2_name << \"'\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate concatenation operator for types '%s' and '%s'\",\n               t1_name.c_str (), t1_name.c_str ());\n    }\n\n  m_cat_ops.checkelem (t1, t2) = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_assign_op (octave_value::assign_op op,\n                               int t_lhs, int t_rhs,\n                               type_info::assign_op_fcn f,\n                               bool abort_on_duplicate)\n{\n  if (lookup_assign_op (op, t_lhs, t_rhs))\n    {\n      std::string op_name = octave_value::assign_op_as_string (op);\n      std::string t_lhs_name = m_types(t_lhs);\n      std::string t_rhs_name = m_types(t_rhs);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"duplicate assignment operator '\"\n                    << op_name << \"' for types '\" << t_lhs_name\n                    << \"' and '\" << t_rhs_name << \"'\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate assignment operator '%s' for types '%s' and '%s'\",\n               op_name.c_str (), t_lhs_name.c_str (), t_rhs_name.c_str ());\n    }\n\n  m_assign_ops.checkelem (static_cast<int> (op), t_lhs, t_rhs)\n    = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_assignany_op (octave_value::assign_op op, int t_lhs,\n                                  type_info::assignany_op_fcn f,\n                                  bool abort_on_duplicate)\n{\n  if (lookup_assignany_op (op, t_lhs))\n    {\n      std::string op_name = octave_value::assign_op_as_string (op);\n      std::string t_lhs_name = m_types(t_lhs);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"duplicate assignment operator '\" << op_name\n                    << \"' for types '\" << t_lhs_name << \"'\" << std::endl;\n          abort ();\n        }\n\n      warning (\"duplicate assignment operator '%s' for types '%s'\",\n               op_name.c_str (), t_lhs_name.c_str ());\n    }\n\n  m_assignany_ops.checkelem (static_cast<int> (op), t_lhs)\n    = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\nbool\ntype_info::register_pref_assign_conv (int t_lhs, int t_rhs,\n                                      int t_result,\n                                      bool abort_on_duplicate)\n{\n  if (lookup_pref_assign_conv (t_lhs, t_rhs) >= 0)\n    {\n      std::string t_lhs_name = m_types(t_lhs);\n      std::string t_rhs_name = m_types(t_rhs);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"overriding assignment conversion for types '\"\n                    << t_lhs_name << \"' and '\" << t_rhs_name << \"'\"\n                    << std::endl;\n          abort ();\n        }\n\n      warning (\"overriding assignment conversion for types '%s' and '%s'\",\n               t_lhs_name.c_str (), t_rhs_name.c_str ());\n    }\n\n  m_pref_assign_conv.checkelem (t_lhs, t_rhs) = t_result;\n\n  return false;\n}\n\nbool\ntype_info::register_widening_op (int t, int t_result,\n                                 octave_base_value::type_conv_fcn f,\n                                 bool abort_on_duplicate)\n{\n  if (lookup_widening_op (t, t_result))\n    {\n      std::string t_name = m_types(t);\n      std::string t_result_name = m_types(t_result);\n\n      if (abort_on_duplicate)\n        {\n          std::cerr << \"overriding widening op for '\" << t_name\n                    << \"' to '\" << t_result_name << \"'\" << std::endl;\n          abort ();\n        }\n\n      warning (\"overriding widening op for '%s' to '%s'\",\n               t_name.c_str (), t_result_name.c_str ());\n    }\n\n  m_widening_ops.checkelem (t, t_result) = reinterpret_cast<void *> (f);\n\n  return false;\n}\n\noctave_value\ntype_info::lookup_type (const std::string& nm)\n{\n  octave_value retval;\n\n  for (int i = 0; i < m_num_types; i++)\n    {\n      if (nm == m_types(i))\n        {\n          retval = *m_vals(i);\n          retval.make_unique ();\n          break;\n        }\n    }\n\n  return retval;\n}\n\ntype_info::unary_class_op_fcn\ntype_info::lookup_unary_class_op (octave_value::unary_op op)\n{\n  void *f = m_unary_class_ops.checkelem (static_cast<int> (op));\n  return reinterpret_cast<type_info::unary_class_op_fcn> (f);\n}\n\ntype_info::unary_op_fcn\ntype_info::lookup_unary_op (octave_value::unary_op op, int t)\n{\n  void *f = m_unary_ops.checkelem (static_cast<int> (op), t);\n  return reinterpret_cast<type_info::unary_op_fcn> (f);\n}\n\ntype_info::non_const_unary_op_fcn\ntype_info::lookup_non_const_unary_op (octave_value::unary_op op, int t)\n{\n  void *f = m_non_const_unary_ops.checkelem (static_cast<int> (op), t);\n  return reinterpret_cast<type_info::non_const_unary_op_fcn> (f);\n}\n\ntype_info::binary_class_op_fcn\ntype_info::lookup_binary_class_op (octave_value::binary_op op)\n{\n  void *f = m_binary_class_ops.checkelem (static_cast<int> (op));\n  return reinterpret_cast<type_info::binary_class_op_fcn> (f);\n}\n\ntype_info::binary_op_fcn\ntype_info::lookup_binary_op (octave_value::binary_op op, int t1, int t2)\n{\n  void *f = m_binary_ops.checkelem (static_cast<int> (op), t1, t2);\n  return reinterpret_cast<type_info::binary_op_fcn> (f);\n}\n\ntype_info::binary_class_op_fcn\ntype_info::lookup_binary_class_op (octave_value::compound_binary_op op)\n{\n  void *f = m_compound_binary_class_ops.checkelem (static_cast<int> (op));\n  return reinterpret_cast<type_info::binary_class_op_fcn> (f);\n}\n\ntype_info::binary_op_fcn\ntype_info::lookup_binary_op (octave_value::compound_binary_op op,\n                             int t1, int t2)\n{\n  void *f = m_compound_binary_ops.checkelem (static_cast<int> (op), t1, t2);\n  return reinterpret_cast<type_info::binary_op_fcn> (f);\n}\n\ntype_info::cat_op_fcn\ntype_info::lookup_cat_op (int t1, int t2)\n{\n  void *f = m_cat_ops.checkelem (t1, t2);\n  return reinterpret_cast<type_info::cat_op_fcn> (f);\n}\n\ntype_info::assign_op_fcn\ntype_info::lookup_assign_op (octave_value::assign_op op,\n                             int t_lhs, int t_rhs)\n{\n  void *f = m_assign_ops.checkelem (static_cast<int> (op), t_lhs, t_rhs);\n  return reinterpret_cast<type_info::assign_op_fcn> (f);\n}\n\ntype_info::assignany_op_fcn\ntype_info::lookup_assignany_op (octave_value::assign_op op, int t_lhs)\n{\n  void *f = m_assignany_ops.checkelem (static_cast<int> (op), t_lhs);\n  return reinterpret_cast<type_info::assignany_op_fcn> (f);\n}\n\nint\ntype_info::lookup_pref_assign_conv (int t_lhs, int t_rhs)\n{\n  return m_pref_assign_conv.checkelem (t_lhs, t_rhs);\n}\n\noctave_base_value::type_conv_fcn\ntype_info::lookup_widening_op (int t, int t_result)\n{\n  void *f = m_widening_ops.checkelem (t, t_result);\n  return reinterpret_cast<octave_base_value::type_conv_fcn> (f);\n}\n\nstring_vector\ntype_info::installed_type_names () const\n{\n  string_vector retval (m_num_types);\n\n  for (int i = 0; i < m_num_types; i++)\n    retval(i) = m_types(i);\n\n  return retval;\n}\n\noctave_scalar_map\ntype_info::unary_ops_map () const\n{\n  octave_scalar_map retval;\n\n  int len = std::min (static_cast<int> (m_non_const_unary_ops.columns ()),\n                      m_num_types);\n\n  dim_vector tab_dims (1, len);\n\n  for (int j = 0; j < octave_value::num_unary_ops; j++)\n    {\n      boolNDArray tab (tab_dims);\n\n      for (int i = 0; i < len; i++)\n        tab.xelem (i) = (m_unary_ops(j, i) != nullptr);\n\n      octave_value::unary_op op_id = static_cast<octave_value::unary_op> (j);\n\n      retval.setfield (octave_value::unary_op_as_string (op_id), tab);\n    }\n\n  return retval;\n}\n\noctave_scalar_map\ntype_info::non_const_unary_ops_map () const\n{\n  octave_scalar_map retval;\n\n  int len = std::min (static_cast<int> (m_non_const_unary_ops.columns ()),\n                      m_num_types);\n\n  dim_vector tab_dims (1, len);\n\n  for (int j = 0; j < octave_value::num_unary_ops; j++)\n    {\n      boolNDArray tab (tab_dims);\n\n      for (int i = 0; i < len; i++)\n        tab.xelem (i) = (m_non_const_unary_ops(j, i) != nullptr);\n\n      octave_value::unary_op op_id = static_cast<octave_value::unary_op> (j);\n\n      retval.setfield (octave_value::unary_op_as_string (op_id), tab);\n    }\n\n  return retval;\n}\n\noctave_scalar_map\ntype_info::binary_ops_map () const\n{\n  octave_scalar_map retval;\n\n  int len = std::min (static_cast<int> (m_binary_ops.columns ()),\n                      m_num_types);\n\n  dim_vector tab_dims (len, len);\n\n  for (int k = 0; k < octave_value::num_binary_ops; k++)\n    {\n      boolNDArray tab (tab_dims);\n\n      for (int j = 0; j < len; j++)\n        for (int i = 0; i < len; i++)\n          tab.xelem (j, i) = (m_binary_ops(k, j, i) != nullptr);\n\n      octave_value::binary_op op_id = static_cast<octave_value::binary_op> (k);\n\n      retval.setfield (octave_value::binary_op_as_string (op_id), tab);\n    }\n\n  return retval;\n}\n\noctave_scalar_map\ntype_info::compound_binary_ops_map () const\n{\n  octave_scalar_map retval;\n\n  int len = std::min (static_cast<int> (m_compound_binary_ops.columns ()),\n                      m_num_types);\n\n  dim_vector tab_dims (len, len);\n\n  for (int k = 0; k < octave_value::num_compound_binary_ops; k++)\n    {\n      boolNDArray tab (tab_dims);\n\n      for (int j = 0; j < len; j++)\n        for (int i = 0; i < len; i++)\n          tab.xelem (j, i) = (m_compound_binary_ops(k, j, i) != nullptr);\n\n      octave_value::compound_binary_op op_id\n        = static_cast<octave_value::compound_binary_op> (k);\n\n      retval.setfield (octave_value::binary_op_fcn_name (op_id), tab);\n    }\n\n  return retval;\n}\n\noctave_scalar_map\ntype_info::assign_ops_map () const\n{\n  octave_scalar_map retval;\n\n  int len = std::min (static_cast<int> (m_assign_ops.columns ()),\n                      m_num_types);\n\n  dim_vector tab_dims (len, len);\n\n  for (int k = 0; k < octave_value::num_assign_ops; k++)\n    {\n      boolNDArray tab (tab_dims);\n\n      for (int j = 0; j < len; j++)\n        for (int i = 0; i < len; i++)\n          tab.xelem (j, i) = (m_assign_ops(k, j, i) != nullptr);\n\n      octave_value::assign_op op_id = static_cast<octave_value::assign_op> (k);\n\n      retval.setfield (octave_value::assign_op_as_string (op_id), tab);\n    }\n\n  return retval;\n}\n\noctave_scalar_map\ntype_info::assignany_ops_map () const\n{\n  octave_scalar_map retval;\n\n  int len = std::min (static_cast<int> (m_assignany_ops.columns ()),\n                      m_num_types);\n\n  dim_vector tab_dims (1, len);\n\n  for (int j = 0; j < octave_value::num_assign_ops; j++)\n    {\n      boolNDArray tab (tab_dims);\n\n      for (int i = 0; i < len; i++)\n        tab.xelem (i) = (m_assignany_ops(j, i) != nullptr);\n\n      octave_value::assign_op op_id = static_cast<octave_value::assign_op> (j);\n\n      retval.setfield (octave_value::assign_op_as_string (op_id), tab);\n    }\n\n  return retval;\n}\n\noctave_scalar_map\ntype_info::installed_type_info () const\n{\n  octave_scalar_map retval;\n\n  retval.setfield (\"types\", octave_value (Cell (installed_type_names ())));\n  retval.setfield (\"unary_ops\", unary_ops_map ());\n  retval.setfield (\"non_const_unary_ops\", non_const_unary_ops_map ());\n  retval.setfield (\"binary_ops\", binary_ops_map ());\n  retval.setfield (\"compound_binary_ops\", compound_binary_ops_map ());\n  retval.setfield (\"cat_ops\", as_bool_nd_array (m_cat_ops));\n  retval.setfield (\"assign_ops\", assign_ops_map ());\n  retval.setfield (\"assignany_ops\", assignany_ops_map ());\n  retval.setfield (\"pref_assign_conv\", as_nd_array (m_pref_assign_conv));\n  retval.setfield (\"widening_ops\", as_bool_nd_array (m_widening_ops));\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\nOCTAVE_BEGIN_NAMESPACE(octave_value_typeinfo)\n\nint register_type (const std::string& t_name, const std::string& c_name,\n                   const octave_value& val)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.register_type (t_name, c_name, val);\n}\n\noctave_value\nlookup_type (const std::string& nm)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_type (nm);\n}\n\nunary_class_op_fcn\nlookup_unary_class_op (octave_value::unary_op op)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_unary_class_op (op);\n}\n\nunary_op_fcn\nlookup_unary_op (octave_value::unary_op op, int t)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_unary_op (op, t);\n}\n\nnon_const_unary_op_fcn\nlookup_non_const_unary_op (octave_value::unary_op op, int t)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_non_const_unary_op (op, t);\n}\n\nbinary_class_op_fcn\nlookup_binary_class_op (octave_value::binary_op op)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_binary_class_op (op);\n}\n\nbinary_op_fcn\nlookup_binary_op (octave_value::binary_op op, int t1, int t2)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_binary_op (op, t1, t2);\n}\n\nbinary_class_op_fcn\nlookup_binary_class_op (octave_value::compound_binary_op op)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_binary_class_op (op);\n}\n\nbinary_op_fcn\nlookup_binary_op (octave_value::compound_binary_op op, int t1, int t2)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_binary_op (op, t1, t2);\n}\n\ncat_op_fcn\nlookup_cat_op (int t1, int t2)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_cat_op (t1, t2);\n}\n\nassign_op_fcn\nlookup_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_assign_op (op, t_lhs, t_rhs);\n}\n\nassignany_op_fcn\nlookup_assignany_op (octave_value::assign_op op, int t_lhs)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_assignany_op (op, t_lhs);\n}\n\nint\nlookup_pref_assign_conv (int t_lhs, int t_rhs)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_pref_assign_conv (t_lhs, t_rhs);\n}\n\noctave_base_value::type_conv_fcn\nlookup_widening_op (int t, int t_result)\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.lookup_widening_op (t, t_result);\n}\n\nstring_vector\ninstalled_type_names ()\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.installed_type_names ();\n}\n\noctave_scalar_map\ninstalled_type_info ()\n{\n  octave::type_info& type_info = octave::__get_type_info__ ();\n\n  return type_info.installed_type_info ();\n}\n\nOCTAVE_END_NAMESPACE(octave_value_typeinfo)\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFMETHOD (typeinfo, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{typestr} =} typeinfo (@var{expr})\n@deftypefnx {} {@var{cstr} =} typeinfo ()\n\nReturn the type of the expression @var{expr}, as a string.\n\nIf @var{expr} is omitted, return a cell array of strings containing all the\ncurrently installed data types.\n@seealso{class, isa}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 0)\n    {\n      type_info& type_info = interp.get_type_info ();\n\n      return ovl (Cell (type_info.installed_type_names ()));\n    }\n  else\n    return ovl (args(0).type_name ());\n}\n\n/*\n%!assert (iscellstr (typeinfo ()))\n\n%!assert (typeinfo ({\"cell\"}), \"cell\")\n\n%!assert (typeinfo (1), \"scalar\")\n%!assert (typeinfo (double (1)), \"scalar\")\n%!assert (typeinfo (i), \"complex scalar\")\n\n%!assert (typeinfo ([1, 2]), \"matrix\")\n%!assert (typeinfo (double ([1, 2])), \"matrix\")\n%!assert (typeinfo (diag ([1, 2])), \"diagonal matrix\")\n%!assert (typeinfo ([i, 2]), \"complex matrix\")\n%!assert (typeinfo (diag ([i, 2])), \"complex diagonal matrix\")\n\n%!test\n%! if (optimize_range ())\n%!   assert (typeinfo (1:2), \"double_range\");\n%! else\n%!   assert (typeinfo (1:2), \"matrix\");\n%! endif\n\n%!assert (typeinfo (false), \"bool\")\n%!assert (typeinfo ([true, false]), \"bool matrix\")\n\n%!assert (typeinfo (\"string\"), \"string\")\n%!assert (typeinfo ('string'), \"sq_string\")\n\n%!assert (typeinfo (int8 (1)), \"int8 scalar\")\n%!assert (typeinfo (int16 (1)), \"int16 scalar\")\n%!assert (typeinfo (int32 (1)), \"int32 scalar\")\n%!assert (typeinfo (int64 (1)), \"int64 scalar\")\n%!assert (typeinfo (uint8 (1)), \"uint8 scalar\")\n%!assert (typeinfo (uint16 (1)), \"uint16 scalar\")\n%!assert (typeinfo (uint32 (1)), \"uint32 scalar\")\n%!assert (typeinfo (uint64 (1)), \"uint64 scalar\")\n\n%!assert (typeinfo (int8 ([1,2])), \"int8 matrix\")\n%!assert (typeinfo (int16 ([1,2])), \"int16 matrix\")\n%!assert (typeinfo (int32 ([1,2])), \"int32 matrix\")\n%!assert (typeinfo (int64 ([1,2])), \"int64 matrix\")\n%!assert (typeinfo (uint8 ([1,2])), \"uint8 matrix\")\n%!assert (typeinfo (uint16 ([1,2])), \"uint16 matrix\")\n%!assert (typeinfo (uint32 ([1,2])), \"uint32 matrix\")\n%!assert (typeinfo (uint64 ([1,2])), \"uint64 matrix\")\n\n%!assert (typeinfo (sparse ([true, false])), \"sparse bool matrix\")\n%!assert (typeinfo (logical (sparse (i * eye (10)))), \"sparse bool matrix\")\n%!assert (typeinfo (sparse ([1,2])), \"sparse matrix\")\n%!assert (typeinfo (sparse (eye (10))), \"sparse matrix\")\n%!assert (typeinfo (sparse ([i,2])), \"sparse complex matrix\")\n%!assert (typeinfo (sparse (i * eye (10))), \"sparse complex matrix\")\n\n%!test\n%! s(2).a = 1;\n%! assert (typeinfo (s), \"struct\");\n\n%!test\n%! s.a = 1;\n%! assert (typeinfo (s), \"scalar struct\");\n\n## FIXME: This doesn't work as a test for comma-separated list\n%!#test\n%! clist = {1, 2, 3};\n%! assert (typeinfo (clist{:}), \"cs-list\");\n\n%!assert (typeinfo (@sin), \"function handle\")\n%!assert (typeinfo (@(x) x), \"function handle\")\n\n%!assert (typeinfo (single (1)), \"float scalar\")\n%!assert (typeinfo (single (i)), \"float complex scalar\")\n%!assert (typeinfo (single ([1, 2])), \"float matrix\")\n\n%!assert (typeinfo (single (diag ([1, 2]))), \"float diagonal matrix\")\n%!assert (typeinfo (diag (single ([1, 2]))), \"float diagonal matrix\")\n%!assert (typeinfo (single (diag ([i, 2]))), \"float complex diagonal matrix\")\n%!assert (typeinfo (diag (single ([i, 2]))), \"float complex diagonal matrix\")\n\n%!assert (typeinfo (eye(3)(:,[1 3 2])), \"permutation matrix\")\n%!test\n%! [l, u, p] = lu (rand (3));\n%! assert (typeinfo (p), \"permutation matrix\");\n\n%!assert (typeinfo ([]), \"null_matrix\")\n%!assert (typeinfo (\"\"), \"null_string\")\n%!assert (typeinfo (''), \"null_sq_string\")\n\n%!test\n%! cvar = onCleanup (@() \"\");\n%! assert (typeinfo (cvar), \"onCleanup\");\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! x = javaObject (\"java.lang.StringBuffer\");\n%! assert (typeinfo (x), \"octave_java\");\n\n## Test input validation\n%!error typeinfo (\"foo\", 1)\n*/\n\nDEFMETHOD (__dump_typeinfo__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __dump_typeinfo__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () > 0)\n    print_usage ();\n\n  type_info& type_info = interp.get_type_info ();\n\n  return ovl (type_info.installed_type_info ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-typeinfo.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_typeinfo_h)\n#define octave_ov_typeinfo_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"Array.h\"\n\n#include \"oct-map.h\"\n#include \"ov.h\"\n\nclass string_vector;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API type_info\n{\npublic:\n\n  typedef octave_value (*unary_class_op_fcn) (const octave_value&);\n\n  typedef octave_value (*unary_op_fcn) (const octave_base_value&);\n\n  typedef void (*non_const_unary_op_fcn) (octave_base_value&);\n\n  typedef octave_value (*binary_class_op_fcn)\n    (const octave_value&, const octave_value&);\n\n  typedef octave_value (*binary_op_fcn)\n    (const octave_base_value&, const octave_base_value&);\n\n  typedef octave_value (*cat_op_fcn)\n    (const octave_base_value&, const octave_base_value&,\n   const Array<octave_idx_type>& ra_idx);\n\n  typedef octave_value (*assign_op_fcn)\n    (octave_base_value&, const octave_value_list&, const octave_base_value&);\n\n  typedef octave_value (*assignany_op_fcn)\n    (octave_base_value&, const octave_value_list&, const octave_value&);\n\n  explicit type_info (int init_tab_sz = 16);\n\n  OCTAVE_DISABLE_COPY_MOVE (type_info)\n\n  ~type_info () = default;\n\n  // It is intentional that there is no install_type function.\n\n  bool install_unary_class_op (octave_value::unary_op op,\n                               unary_class_op_fcn f)\n  {\n    return register_unary_class_op (op, f, true);\n  }\n\n  bool install_unary_op (octave_value::unary_op op, int t, unary_op_fcn f)\n  {\n    return register_unary_op (op, t, f, true);\n  }\n\n  bool install_non_const_unary_op (octave_value::unary_op op, int t,\n                                   non_const_unary_op_fcn f)\n  {\n    return register_non_const_unary_op (op, t, f, true);\n  }\n\n  bool install_binary_class_op (octave_value::binary_op op,\n                                binary_class_op_fcn f)\n  {\n    return register_binary_class_op (op, f, true);\n  }\n\n  bool install_binary_op (octave_value::binary_op op, int t1, int t2,\n                          binary_op_fcn f)\n  {\n    return register_binary_op (op, t1, t2, f, true);\n  }\n\n  bool install_binary_class_op (octave_value::compound_binary_op op,\n                                binary_class_op_fcn f)\n  {\n    return register_binary_class_op (op, f, true);\n  }\n\n  bool install_binary_op (octave_value::compound_binary_op op,\n                          int t_lhs, int t_rhs, binary_op_fcn f)\n  {\n    return register_binary_op (op, t_lhs, t_rhs, f, true);\n  }\n\n  bool install_cat_op (int t1, int t2, cat_op_fcn f)\n  {\n    return register_cat_op (t1, t2, f, true);\n  }\n\n  bool install_assign_op (octave_value::assign_op op,\n                          int t_lhs, int t_rhs, assign_op_fcn f)\n  {\n    return register_assign_op (op, t_lhs, t_rhs, f, true);\n  }\n\n  bool install_assignany_op (octave_value::assign_op op, int t_lhs,\n                             assignany_op_fcn f)\n  {\n    return register_assignany_op (op, t_lhs, f, true);\n  }\n\n  bool install_pref_assign_conv (int t_lhs, int t_rhs, int t_result)\n  {\n    return register_pref_assign_conv (t_lhs, t_rhs, t_result, true);\n  }\n\n  bool install_widening_op (int t, int t_result,\n                            octave_base_value::type_conv_fcn f)\n  {\n    return register_widening_op (t, t_result, f, true);\n  }\n\n  int register_type (const std::string&, const std::string&,\n                     const octave_value&, bool abort_on_duplicate = false);\n\n  bool register_unary_class_op (octave_value::unary_op, unary_class_op_fcn,\n                                bool abort_on_duplicate = false);\n\n  bool register_unary_op (octave_value::unary_op, int, unary_op_fcn,\n                          bool abort_on_duplicate = false);\n\n  bool register_non_const_unary_op (octave_value::unary_op, int,\n                                    non_const_unary_op_fcn,\n                                    bool abort_on_duplicate = false);\n\n  bool register_binary_class_op (octave_value::binary_op,\n                                 binary_class_op_fcn,\n                                 bool abort_on_duplicate = false);\n\n  bool register_binary_op (octave_value::binary_op, int, int,\n                           binary_op_fcn, bool abort_on_duplicate = false);\n\n  bool register_binary_class_op (octave_value::compound_binary_op,\n                                 binary_class_op_fcn,\n                                 bool abort_on_duplicate = false);\n\n  bool register_binary_op (octave_value::compound_binary_op, int, int,\n                           binary_op_fcn, bool abort_on_duplicate = false);\n\n  bool register_cat_op (int, int, cat_op_fcn,\n                        bool abort_on_duplicate = false);\n\n  bool register_assign_op (octave_value::assign_op, int, int, assign_op_fcn,\n                           bool abort_on_duplicate = false);\n\n  bool register_assignany_op (octave_value::assign_op, int, assignany_op_fcn,\n                              bool abort_on_duplicate = false);\n\n  bool register_pref_assign_conv (int, int, int,\n                                  bool abort_on_duplicate = false);\n\n  bool register_widening_op (int, int, octave_base_value::type_conv_fcn,\n                             bool abort_on_duplicate = false);\n\n  octave_value lookup_type (const std::string& nm);\n\n  unary_class_op_fcn lookup_unary_class_op (octave_value::unary_op);\n\n  unary_op_fcn lookup_unary_op (octave_value::unary_op, int);\n\n  non_const_unary_op_fcn\n  lookup_non_const_unary_op (octave_value::unary_op, int);\n\n  binary_class_op_fcn lookup_binary_class_op (octave_value::binary_op);\n\n  binary_op_fcn lookup_binary_op (octave_value::binary_op, int, int);\n\n  binary_class_op_fcn\n  lookup_binary_class_op (octave_value::compound_binary_op);\n\n  binary_op_fcn\n  lookup_binary_op (octave_value::compound_binary_op, int, int);\n\n  cat_op_fcn lookup_cat_op (int, int);\n\n  assign_op_fcn lookup_assign_op (octave_value::assign_op, int, int);\n\n  assignany_op_fcn lookup_assignany_op (octave_value::assign_op, int);\n\n  int lookup_pref_assign_conv (int, int);\n\n  octave_base_value::type_conv_fcn lookup_widening_op (int, int);\n\n  string_vector installed_type_names () const;\n\n  octave_scalar_map installed_type_info () const;\n\n  octave_scalar_map unary_ops_map () const;\n\n  octave_scalar_map non_const_unary_ops_map () const;\n\n  octave_scalar_map binary_ops_map () const;\n\n  octave_scalar_map compound_binary_ops_map () const;\n\n  octave_scalar_map assign_ops_map () const;\n\n  octave_scalar_map assignany_ops_map () const;\n\nprivate:\n\n  int m_num_types;\n\n  Array<std::string> m_types;\n\n  Array<octave_value *> m_vals;\n\n  Array<void *> m_unary_class_ops;\n\n  Array<void *> m_unary_ops;\n\n  Array<void *> m_non_const_unary_ops;\n\n  Array<void *> m_binary_class_ops;\n\n  Array<void *> m_binary_ops;\n\n  Array<void *> m_compound_binary_class_ops;\n\n  Array<void *> m_compound_binary_ops;\n\n  Array<void *> m_cat_ops;\n\n  Array<void *> m_assign_ops;\n\n  Array<void *> m_assignany_ops;\n\n  Array<int> m_pref_assign_conv;\n\n  Array<void *> m_widening_ops;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\nOCTAVE_BEGIN_NAMESPACE(octave_value_typeinfo)\n\ntypedef octave::type_info::unary_class_op_fcn unary_class_op_fcn;\n\ntypedef octave::type_info::unary_op_fcn unary_op_fcn;\n\ntypedef octave::type_info::non_const_unary_op_fcn non_const_unary_op_fcn;\n\ntypedef octave::type_info::binary_class_op_fcn binary_class_op_fcn;\n\ntypedef octave::type_info::binary_op_fcn binary_op_fcn;\n\ntypedef octave::type_info::cat_op_fcn cat_op_fcn;\n\ntypedef octave::type_info::assign_op_fcn assign_op_fcn;\n\ntypedef octave::type_info::assignany_op_fcn assignany_op_fcn;\n\nextern OCTINTERP_API int register_type (const std::string& t_name,\n                                        const std::string& c_name,\n                                        const octave_value& val);\n\nextern OCTINTERP_API octave_value lookup_type (const std::string& nm);\n\nextern OCTINTERP_API unary_class_op_fcn\nlookup_unary_class_op (octave_value::unary_op op);\n\nextern OCTINTERP_API unary_op_fcn\nlookup_unary_op (octave_value::unary_op op, int t);\n\nextern OCTINTERP_API non_const_unary_op_fcn\nlookup_non_const_unary_op (octave_value::unary_op op, int t);\n\nextern OCTINTERP_API binary_class_op_fcn\nlookup_binary_class_op (octave_value::binary_op op);\n\nextern OCTINTERP_API binary_op_fcn\nlookup_binary_op (octave_value::binary_op op, int t1, int t2);\n\nextern OCTINTERP_API binary_class_op_fcn\nlookup_binary_class_op (octave_value::compound_binary_op op);\n\nextern OCTINTERP_API binary_op_fcn\nlookup_binary_op (octave_value::compound_binary_op op, int t1, int t2);\n\nextern OCTINTERP_API cat_op_fcn lookup_cat_op (int t1, int t2);\n\nextern OCTINTERP_API assign_op_fcn\nlookup_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs);\n\nextern OCTINTERP_API assignany_op_fcn\nlookup_assignany_op (octave_value::assign_op op, int t_lhs);\n\nextern OCTINTERP_API int lookup_pref_assign_conv (int t_lhs, int t_rhs);\n\nextern OCTINTERP_API octave_base_value::type_conv_fcn\nlookup_widening_op (int t, int t_result);\n\nextern OCTINTERP_API string_vector installed_type_names ();\n\nextern OCTINTERP_API octave_scalar_map installed_type_info ();\n\nOCTAVE_END_NAMESPACE(octave_value_typeinfo)\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-uint16.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"quit.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n\n#if defined (HAVE_HDF5)\n#  define HDF5_SAVE_TYPE H5T_NATIVE_UINT16\n#else\n// This value will not be used.\n#  define HDF5_SAVE_TYPE 0\n#endif\n\n#include \"ov-uint16.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\noctave_hdf5_id octave_uint16_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;\noctave_hdf5_id octave_uint16_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint16_matrix,\n                                     \"uint16 matrix\", \"uint16\");\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint16_scalar,\n                                     \"uint16 scalar\", \"uint16\");\n"
  },
  {
    "path": "libinterp/octave-value/ov-uint16.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_uint16_h)\n#define octave_ov_uint16_h 1\n\n#include \"octave-config.h\"\n\n#define OCTAVE_INT_T octave_uint16\n\n#define OCTAVE_VALUE_INT_MATRIX_T octave_uint16_matrix\n#define OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION uint16_array_value\n\n#define OCTAVE_VALUE_INT_SCALAR_T octave_uint16_scalar\n#define OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION uint16_scalar_value\n\n#define OCTAVE_TYPE_PREDICATE_FUNCTION is_uint16_type\n\n#define OCTAVE_INT_MX_CLASS mxUINT16_CLASS\n\n#define OCTAVE_INT_BTYP btyp_uint16\n\n#include \"ov-intx.h\"\n\n#undef OCTAVE_INT_T\n\n#undef OCTAVE_VALUE_INT_MATRIX_T\n#undef OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_VALUE_INT_SCALAR_T\n#undef OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_TYPE_PREDICATE_FUNCTION\n\n#undef OCTAVE_INT_MX_CLASS\n\n#undef OCTAVE_INT_BTYP\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-uint32.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"quit.h\"\n\n#include \"errwarn.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n\n#if defined (HAVE_HDF5)\n#  define HDF5_SAVE_TYPE H5T_NATIVE_UINT32\n#else\n// This value will not be used.\n#  define HDF5_SAVE_TYPE 0\n#endif\n\n#include \"ov-uint32.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\noctave_hdf5_id octave_uint32_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;\noctave_hdf5_id octave_uint32_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint32_matrix,\n                                     \"uint32 matrix\", \"uint32\");\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint32_scalar,\n                                     \"uint32 scalar\", \"uint32\");\n"
  },
  {
    "path": "libinterp/octave-value/ov-uint32.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_uint32_h)\n#define octave_ov_uint32_h 1\n\n#include \"octave-config.h\"\n\n#define OCTAVE_INT_T octave_uint32\n\n#define OCTAVE_VALUE_INT_MATRIX_T octave_uint32_matrix\n#define OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION uint32_array_value\n\n#define OCTAVE_VALUE_INT_SCALAR_T octave_uint32_scalar\n#define OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION uint32_scalar_value\n\n#define OCTAVE_TYPE_PREDICATE_FUNCTION is_uint32_type\n\n#define OCTAVE_INT_MX_CLASS mxUINT32_CLASS\n\n#define OCTAVE_INT_BTYP btyp_uint32\n\n#include \"ov-intx.h\"\n\n#undef OCTAVE_INT_T\n\n#undef OCTAVE_VALUE_INT_MATRIX_T\n#undef OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_VALUE_INT_SCALAR_T\n#undef OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_TYPE_PREDICATE_FUNCTION\n\n#undef OCTAVE_INT_MX_CLASS\n\n#undef OCTAVE_INT_BTYP\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-uint64.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"quit.h\"\n\n#include \"errwarn.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n\n#if defined (HAVE_HDF5)\n#  define HDF5_SAVE_TYPE H5T_NATIVE_UINT64\n#else\n// This value will not be used.\n#  define HDF5_SAVE_TYPE 0\n#endif\n\n#include \"ov-uint64.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\noctave_hdf5_id octave_uint64_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;\noctave_hdf5_id octave_uint64_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint64_matrix,\n                                     \"uint64 matrix\", \"uint64\");\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint64_scalar,\n                                     \"uint64 scalar\", \"uint64\");\n"
  },
  {
    "path": "libinterp/octave-value/ov-uint64.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_uint64_h)\n#define octave_ov_uint64_h 1\n\n#include \"octave-config.h\"\n\n#define OCTAVE_INT_T octave_uint64\n\n#define OCTAVE_VALUE_INT_MATRIX_T octave_uint64_matrix\n#define OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION uint64_array_value\n\n#define OCTAVE_VALUE_INT_SCALAR_T octave_uint64_scalar\n#define OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION uint64_scalar_value\n\n#define OCTAVE_TYPE_PREDICATE_FUNCTION is_uint64_type\n\n#define OCTAVE_INT_MX_CLASS mxUINT64_CLASS\n\n#define OCTAVE_INT_BTYP btyp_uint64\n\n#include \"ov-intx.h\"\n\n#undef OCTAVE_INT_T\n\n#undef OCTAVE_VALUE_INT_MATRIX_T\n#undef OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_VALUE_INT_SCALAR_T\n#undef OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_TYPE_PREDICATE_FUNCTION\n\n#undef OCTAVE_INT_MX_CLASS\n\n#undef OCTAVE_INT_BTYP\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-uint8.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mx-base.h\"\n#include \"quit.h\"\n\n#include \"errwarn.h\"\n#include \"oct-lvalue.h\"\n#include \"oct-hdf5.h\"\n#include \"ops.h\"\n#include \"ov-base.h\"\n\n#if defined (HAVE_HDF5)\n#  define HDF5_SAVE_TYPE H5T_NATIVE_UINT8\n#else\n// This value will not be used.\n#  define HDF5_SAVE_TYPE 0\n#endif\n\n#include \"ov-uint8.h\"\n#include \"pr-output.h\"\n#include \"variables.h\"\n\n#include \"byte-swap.h\"\n#include \"ls-oct-text.h\"\n#include \"ls-utils.h\"\n#include \"ls-hdf5.h\"\n\noctave_hdf5_id octave_uint8_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;\noctave_hdf5_id octave_uint8_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint8_matrix,\n                                     \"uint8 matrix\", \"uint8\");\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint8_scalar,\n                                     \"uint8 scalar\", \"uint8\");\n"
  },
  {
    "path": "libinterp/octave-value/ov-uint8.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_uint8_h)\n#define octave_ov_uint8_h 1\n\n#include \"octave-config.h\"\n\n#define OCTAVE_INT_T octave_uint8\n\n#define OCTAVE_VALUE_INT_MATRIX_T octave_uint8_matrix\n#define OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION uint8_array_value\n\n#define OCTAVE_VALUE_INT_SCALAR_T octave_uint8_scalar\n#define OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION uint8_scalar_value\n\n#define OCTAVE_TYPE_PREDICATE_FUNCTION is_uint8_type\n\n#define OCTAVE_INT_MX_CLASS mxUINT8_CLASS\n\n#define OCTAVE_INT_BTYP btyp_uint8\n\n#include \"ov-intx.h\"\n\n#undef OCTAVE_INT_T\n\n#undef OCTAVE_VALUE_INT_MATRIX_T\n#undef OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_VALUE_INT_SCALAR_T\n#undef OCTAVE_VALUE_INT_SCALAR_EXTRACTOR_FUNCTION\n\n#undef OCTAVE_TYPE_PREDICATE_FUNCTION\n\n#undef OCTAVE_INT_MX_CLASS\n\n#undef OCTAVE_INT_BTYP\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov-usr-fcn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n\n#include <sstream>\n\n#include \"file-info.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"str-vec.h\"\n\n#include \"builtin-defun-decls.h\"\n#include \"defaults.h\"\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"filepos.h\"\n#include \"input.h\"\n#include \"ovl.h\"\n#include \"ov-usr-fcn.h\"\n#include \"ov.h\"\n#include \"pager.h\"\n#include \"pt-cmd.h\"\n#include \"pt-eval.h\"\n#include \"pt-id.h\"\n#include \"pt-jump.h\"\n#include \"pt-misc.h\"\n#include \"pt-pr-code.h\"\n#include \"pt-stmt.h\"\n#include \"pt-walk.h\"\n#include \"symtab.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"parse.h\"\n#include \"profiler.h\"\n#include \"variables.h\"\n#include \"ov-fcn-handle.h\"\n\n// Whether to optimize subsasgn method calls.\nstatic bool Voptimize_subsasgn_calls = true;\n\noctave_user_code::~octave_user_code ()\n{\n  // This function is no longer valid, so remove the pointer to it from\n  // the corresponding scope.\n  // FIXME: would it be better to use shared/weak pointers for this job\n  // instead of storing a bare pointer in the scope object?\n  m_scope.set_user_code (nullptr);\n\n  // FIXME: shouldn't this happen automatically when deleting cmd_list?\n  if (m_cmd_list)\n    {\n      octave::event_manager& evmgr = octave::__get_event_manager__ ();\n\n      m_cmd_list->remove_all_breakpoints (evmgr, m_file_name);\n    }\n\n  delete m_cmd_list;\n  delete m_file_info;\n}\n\noctave::filepos octave_user_code::beg_pos () const\n{\n  return m_cmd_list->beg_pos ();\n}\n\noctave::filepos octave_user_code::end_pos () const\n{\n  return m_cmd_list->end_pos ();\n}\n\noctave::comment_list octave_user_code::leading_comments () const\n{\n  return m_cmd_list->leading_comments ();\n}\n\noctave::comment_list octave_user_code::trailing_comments () const\n{\n  if (m_cmd_list && ! m_cmd_list->empty ())\n    {\n      octave::tree_statement *last_stmt = m_cmd_list->back ();\n\n      octave::tree_command *cmd = last_stmt->command ();\n\n      octave::tree_no_op_command *no_op_cmd = dynamic_cast<octave::tree_no_op_command *> (cmd);\n\n      if (no_op_cmd && (no_op_cmd->is_end_of_fcn_or_script () || no_op_cmd->is_end_of_file ()))\n        return no_op_cmd->trailing_comments ();\n    }\n\n  return octave::comment_list ();\n}\n\nvoid\noctave_user_code::get_file_info ()\n{\n  m_file_info = new octave::file_info (m_file_name);\n\n  octave::sys::file_stat fs (m_file_name);\n\n  if (fs && (fs.mtime () > time_parsed ()))\n    warning (\"function file '%s' changed since it was parsed\",\n             m_file_name.c_str ());\n}\n\nstd::string\noctave_user_code::get_code_line (std::size_t line)\n{\n  if (! m_file_info)\n    get_file_info ();\n\n  return m_file_info->get_line (line);\n}\n\nstd::deque<std::string>\noctave_user_code::get_code_lines (std::size_t line, std::size_t num_lines)\n{\n  if (! m_file_info)\n    get_file_info ();\n\n  return m_file_info->get_lines (line, num_lines);\n}\n\nvoid\noctave_user_code::cache_function_text (const std::string& text,\n                                       const octave::sys::time& timestamp)\n{\n  delete m_file_info;\n\n  if (timestamp > time_parsed ())\n    warning (\"help text for function is newer than function\");\n\n  m_file_info = new octave::file_info (text, timestamp);\n}\n\nstd::map<std::string, octave_value>\noctave_user_code::subfunctions () const\n{\n  return std::map<std::string, octave_value> ();\n}\n\noctave_value\noctave_user_code::dump () const\n{\n  std::map<std::string, octave_value> m\n  = {{ \"scope_info\", m_scope ? m_scope.dump () : \"0x0\" },\n    { \"m_file_name\", m_file_name },\n    { \"time_parsed\", m_t_parsed },\n    { \"time_checked\", m_t_checked }\n  };\n\n  return octave_value (m);\n}\n\n\n// User defined scripts.\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_user_script,\n                                     \"user-defined script\",\n                                     \"user-defined script\");\n\noctave_user_script::octave_user_script ()\n  : octave_user_code ()\n{ }\n\noctave_user_script::octave_user_script\n(const std::string& fnm, const std::string& nm,\n const octave::symbol_scope& scope, octave::tree_statement_list *cmds,\n const std::string& ds)\n  : octave_user_code (fnm, nm, scope, cmds, ds)\n{\n  if (m_cmd_list)\n    m_cmd_list->mark_as_script_body ();\n}\n\noctave_user_script::octave_user_script\n(const std::string& fnm, const std::string& nm,\n const octave::symbol_scope& scope, const std::string& ds)\n  : octave_user_code (fnm, nm, scope, nullptr, ds)\n{ }\n\n// We must overload the call method so that we call the proper\n// push_stack_frame method, which is overloaded for pointers to\n// octave_function, octave_user_function, and octave_user_script\n// objects.\n\noctave_value_list\noctave_user_script::call (octave::tree_evaluator& tw, int nargout,\n                          const octave_value_list& args)\n{\n  tw.push_stack_frame (this);\n\n  octave::unwind_action act ([&tw] () { tw.pop_stack_frame (); });\n\n  return execute (tw, nargout, args);\n}\n\noctave_value_list\noctave_user_script::execute (octave::tree_evaluator& tw, int nargout,\n                             const octave_value_list& args)\n{\n  return tw.execute_user_script (*this, nargout, args);\n}\n\nvoid\noctave_user_script::accept (octave::tree_walker& tw)\n{\n  tw.visit_octave_user_script (*this);\n}\n\n// User defined functions.\n\nDEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_user_function,\n                                     \"user-defined function\",\n                                     \"user-defined function\");\n\n// Ugh.  This really needs to be simplified (code/data?\n// extrinsic/intrinsic state?).\n\noctave_user_function::octave_user_function (const octave::symbol_scope& scope, octave::tree_identifier *id, octave::tree_parameter_list *pl, octave::tree_parameter_list *rl, octave::tree_statement_list *cl)\n  : octave_user_code (\"\", \"\", scope, cl, \"\"), m_id (id), m_param_list (pl), m_ret_list (rl), m_num_named_args (m_param_list ? m_param_list->size () : 0)\n{\n  if (m_cmd_list)\n    m_cmd_list->mark_as_function_body ();\n}\n\noctave_user_function::~octave_user_function ()\n{\n  delete m_id;\n  delete m_param_list;\n  delete m_ret_list;\n}\n\nstd::string\noctave_user_function::signature () const\n{\n  std::ostringstream buf;\n\n  octave::tree_print_code tpc (buf);\n\n  if (m_ret_list)\n    {\n      m_ret_list->accept (tpc);\n      buf << \" = \";\n    }\n\n  buf << m_name << \" \";\n\n  if (m_param_list)\n    m_param_list->accept (tpc);\n  else\n    buf << \" ()\";\n\n  return buf.str ();\n}\n\noctave_user_function *\noctave_user_function::define_ret_list (octave::tree_parameter_list *t)\n{\n  m_ret_list = t;\n\n  return this;\n}\n\nvoid\noctave_user_function::attach_trailing_comments (const octave::comment_list& lst)\n{\n  if (m_cmd_list && ! m_cmd_list->empty ())\n    {\n      octave::tree_statement *last_stmt = m_cmd_list->back ();\n\n      octave::tree_command *cmd = last_stmt->command ();\n\n      octave::tree_no_op_command *no_op_cmd = dynamic_cast<octave::tree_no_op_command *> (cmd);\n\n      if (no_op_cmd && (no_op_cmd->is_end_of_fcn_or_script () || no_op_cmd->is_end_of_file ()))\n        no_op_cmd->attach_trailing_comments (lst);\n    }\n}\n\n// If there is no explicit end statement at the end of the function,\n// relocate the no_op that was generated for the end of file condition\n// to appear on the next line after the last statement in the file, or\n// the next line after the function keyword if there are no statements.\n\nvoid\noctave_user_function::maybe_relocate_end_internal ()\n{\n  // This shouldn't happen, but check and return early anyway.\n  if (m_anonymous_function)\n    return;\n\n  if (m_cmd_list && ! m_cmd_list->empty ())\n    {\n      octave::tree_statement *last_stmt = m_cmd_list->back ();\n\n      if (last_stmt && last_stmt->is_end_of_fcn_or_script ()\n          && last_stmt->is_end_of_file ())\n        {\n          octave::tree_statement_list::reverse_iterator next_to_last_elt = m_cmd_list->rbegin ();\n          next_to_last_elt++;\n\n          octave::filepos new_eof_pos;\n\n          if (next_to_last_elt == m_cmd_list->rend ())\n            {\n              // Empty function body, just the end statement.  Set the\n              // new beginning of that statement to the end of the\n              // argument list (if any) or the end of the function name.\n\n              // M_ID is only nullptr if this is an anonymous function\n              // and we shouldn't be updating the end position for that.\n              // So if there is no name and no parameter list, just\n              // return early.\n\n              if (m_param_list)\n                new_eof_pos = m_param_list->end_pos ();\n              else if (m_id)\n                new_eof_pos = m_id->end_pos ();\n              else\n                return;\n            }\n          else\n            {\n              octave::tree_statement *next_to_last_stmt = *next_to_last_elt;\n\n              new_eof_pos = next_to_last_stmt->end_pos ();\n            }\n\n          last_stmt->update_end_pos (new_eof_pos);\n        }\n    }\n}\n\nvoid\noctave_user_function::maybe_relocate_end ()\n{\n  std::map<std::string, octave_value> fcns = subfunctions ();\n\n  if (! fcns.empty ())\n    {\n      for (auto& nm_fnval : fcns)\n        {\n          octave_user_function *f = nm_fnval.second.user_function_value ();\n\n          if (f)\n            f->maybe_relocate_end_internal ();\n        }\n    }\n\n  maybe_relocate_end_internal ();\n}\n\nvoid\noctave_user_function::stash_parent_fcn_scope (const octave::symbol_scope& ps)\n{\n  m_scope.set_parent (ps);\n}\n\nstd::string\noctave_user_function::profiler_name () const\n{\n  std::ostringstream result;\n\n  octave::filepos bp = beg_pos ();\n\n  int bp_line = bp.line ();\n  int bp_column = bp.column ();\n\n  if (is_anonymous_function ())\n    result << \"anonymous@\" << fcn_file_name ()\n           << ':' << bp_line << ':' << bp_column;\n  else if (is_subfunction ())\n    result << parent_fcn_name () << '>' << name ();\n  else if (is_class_method ())\n    result << '@' << dispatch_class () << '/' << name ();\n  else if (is_class_constructor () || is_classdef_constructor ())\n    result << '@' << name ();\n  else if (is_inline_function ())\n    result << \"inline@\" << fcn_file_name ()\n           << ':' << bp_line << ':' << bp_column;\n  else\n    result << name ();\n\n  return result.str ();\n}\n\nvoid\noctave_user_function::mark_as_system_fcn_file ()\n{\n  if (! m_file_name.empty ())\n    {\n      // We really should stash the whole path to the file we found,\n      // when we looked it up, to avoid possible race conditions...\n      // FIXME\n      //\n      // We probably also don't need to get the library directory\n      // every time, but since this function is only called when the\n      // function file is parsed, it probably doesn't matter that\n      // much.\n\n      std::string ff_name = octave::fcn_file_in_path (m_file_name);\n\n      static const std::string canonical_fcn_file_dir\n        = octave::sys::canonicalize_file_name\n          (octave::config::fcn_file_dir ());\n      static const std::string fcn_file_dir\n        = canonical_fcn_file_dir.empty () ? octave::config::fcn_file_dir ()\n          : canonical_fcn_file_dir;\n\n      if (fcn_file_dir == ff_name.substr (0, fcn_file_dir.length ()))\n        m_system_fcn_file = true;\n    }\n  else\n    m_system_fcn_file = false;\n}\n\nvoid\noctave_user_function::erase_subfunctions ()\n{\n  m_scope.erase_subfunctions ();\n}\n\nbool\noctave_user_function::takes_varargs () const\n{\n  return (m_param_list && m_param_list->takes_varargs ());\n}\n\nbool\noctave_user_function::takes_var_return () const\n{\n  return (m_ret_list && m_ret_list->takes_varargs ());\n}\n\nvoid\noctave_user_function::mark_as_private_function (const std::string& cname)\n{\n  m_scope.mark_subfunctions_in_scope_as_private (cname);\n\n  octave_function::mark_as_private_function (cname);\n}\n\nvoid\noctave_user_function::lock_subfunctions ()\n{\n  m_scope.lock_subfunctions ();\n}\n\nvoid\noctave_user_function::unlock_subfunctions ()\n{\n  m_scope.unlock_subfunctions ();\n}\n\nstd::map<std::string, octave_value>\noctave_user_function::subfunctions () const\n{\n  return m_scope.subfunctions ();\n}\n\n// Find definition of final subfunction in list of subfcns:\n//\n//  sub1>sub2>...>subN\n\noctave_value\noctave_user_function::find_subfunction (const std::string& subfcns_arg) const\n{\n  std::string subfcns = subfcns_arg;\n\n  std::string first_fcn = subfcns;\n\n  std::size_t pos = subfcns.find ('>');\n\n  if (pos == std::string::npos)\n    subfcns = \"\";\n  else\n    {\n      first_fcn = subfcns.substr (0, pos-1);\n      subfcns = subfcns.substr (pos+1);\n    }\n\n  octave_value ov_fcn = m_scope.find_subfunction (first_fcn);\n\n  if (subfcns.empty ())\n    return ov_fcn;\n\n  octave_user_function *fcn = ov_fcn.user_function_value ();\n\n  return fcn->find_subfunction (subfcns);\n}\n\nbool\noctave_user_function::has_subfunctions () const\n{\n  return m_scope.has_subfunctions ();\n}\n\nvoid\noctave_user_function::stash_subfunction_names (const std::list<std::string>& names)\n{\n  m_scope.stash_subfunction_names (names);\n}\n\nstd::list<std::string>\noctave_user_function::subfunction_names () const\n{\n  return m_scope.subfunction_names ();\n}\n\noctave_value_list\noctave_user_function::all_va_args (const octave_value_list& args)\n{\n  octave_value_list retval;\n\n  octave_idx_type n = args.length () - m_num_named_args;\n\n  if (n > 0)\n    retval = args.slice (m_num_named_args, n);\n\n  return retval;\n}\n\n// We must overload the call method so that we call the proper\n// push_stack_frame method, which is overloaded for pointers to\n// octave_function, octave_user_function, and octave_user_script\n// objects.\n\noctave_value_list\noctave_user_function::call (octave::tree_evaluator& tw, int nargout,\n                            const octave_value_list& args)\n{\n  tw.push_stack_frame (this);\n\n  octave::unwind_action act ([&tw] () { tw.pop_stack_frame (); });\n\n  return execute (tw, nargout, args);\n}\n\noctave_value_list\noctave_user_function::execute (octave::tree_evaluator& tw, int nargout,\n                               const octave_value_list& args)\n{\n  return tw.execute_user_function (*this, nargout, args);\n}\n\nvoid\noctave_user_function::accept (octave::tree_walker& tw)\n{\n  tw.visit_octave_user_function (*this);\n}\n\noctave::tree_expression *\noctave_user_function::special_expr ()\n{\n  panic_unless (is_special_expr ());\n  panic_if (m_cmd_list->size () != 1);\n\n  octave::tree_statement *stmt = m_cmd_list->front ();\n  return stmt->expression ();\n}\n\nbool\noctave_user_function::subsasgn_optimization_ok ()\n{\n  bool retval = false;\n  if (Voptimize_subsasgn_calls\n      && m_param_list && m_ret_list\n      && m_param_list->size () > 0 && ! m_param_list->varargs_only ()\n      && m_ret_list->size () == 1 && ! m_ret_list->takes_varargs ())\n    {\n      octave::tree_identifier *par1 = m_param_list->front ()->ident ();\n      octave::tree_identifier *ret1 = m_ret_list->front ()->ident ();\n      retval = par1->name () == ret1->name ();\n    }\n\n  return retval;\n}\n\nstd::string\noctave_user_function::ctor_type_str () const\n{\n  std::string retval;\n\n  switch (m_class_constructor)\n    {\n    case none:\n      retval = \"none\";\n      break;\n\n    case legacy:\n      retval = \"legacy\";\n      break;\n\n    case classdef:\n      retval = \"classdef\";\n      break;\n\n    default:\n      retval = \"unrecognized enum value\";\n      break;\n    }\n\n  return retval;\n}\n\nstd::string\noctave_user_function::method_type_str () const\n{\n  std::string retval;\n\n  switch (m_class_method)\n    {\n    case none:\n      retval = \"none\";\n      break;\n\n    case legacy:\n      retval = \"legacy\";\n      break;\n\n    case classdef:\n      retval = \"classdef\";\n      break;\n\n    default:\n      retval = \"unrecognized enum value\";\n      break;\n    }\n\n  return retval;\n}\n\noctave_value\noctave_user_function::dump () const\n{\n  octave::filepos bp = beg_pos ();\n  octave::filepos ep = end_pos ();\n\n  std::map<std::string, octave_value> m\n    = {{ \"user_code\", octave_user_code::dump () },\n       { \"line\", bp.line () },\n       { \"col\", bp.column () },\n       { \"end_line\", ep.line () },\n       { \"end_col\", ep.column () },\n       { \"system_fcn_file\", m_system_fcn_file },\n       { \"num_named_args\", m_num_named_args },\n       { \"subfunction\", m_subfunction },\n       { \"inline_function\", m_inline_function },\n       { \"anonymous_function\", m_anonymous_function },\n       { \"nested_function\", m_nested_function },\n       { \"ctor_type\", ctor_type_str () },\n       { \"class_method\", m_class_method }\n  };\n\n  return octave_value (m);\n}\n\nvoid\noctave_user_function::print_code_function_header (const std::string& prefix)\n{\n  octave::tree_print_code tpc (octave_stdout, prefix);\n\n  tpc.visit_octave_user_function_header (*this);\n}\n\nvoid\noctave_user_function::print_code_function_trailer (const std::string& prefix)\n{\n  octave::tree_print_code tpc (octave_stdout, prefix);\n\n  tpc.visit_octave_user_function_trailer (*this);\n}\n\nvoid\noctave_user_function::restore_warning_states ()\n{\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::tree_evaluator& tw = interp.get_evaluator ();\n\n  octave_value val\n    = tw.get_auto_fcn_var (octave::stack_frame::SAVED_WARNING_STATES);\n\n  if (val.is_defined ())\n    {\n      // Fail if SAVED_WARNING_STATES is not an octave_map (or\n      // octave_scalar_map) object.\n\n      if (! val.isstruct ())\n        error (\"unexpected: SAVED_WARNING_STATES is not a struct in octave_user_function::restore_warning_states - please report this bug\");\n\n      octave_map m = val.map_value ();\n\n      Cell ids = m.contents (\"identifier\");\n      Cell states = m.contents (\"state\");\n\n      for (octave_idx_type i = 0; i < m.numel (); i++)\n        Fwarning (interp, ovl (states(i), ids(i)));\n    }\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFMETHOD (nargin, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{n} =} nargin ()\n@deftypefnx {} {@var{n} =} nargin (@var{fcn})\nReport the number of input arguments to a function.\n\nCalled from within a function, return the number of arguments passed to the\nfunction.  At the top level, return the number of command line arguments\npassed to Octave.\n\nIf called with the optional argument @var{fcn}---a function name or\nhandle---return the declared number of arguments that the function can\naccept.\n\nIf the last argument to @var{fcn} is @var{varargin} the returned value is\nnegative.  For example, the function @code{union} for sets is declared as\n\n@example\n@group\nfunction [y, ia, ib] = union (a, b, varargin)\n\nand\n\nnargin (\"union\")\n@xresult{} -3\n@end group\n@end example\n\nProgramming Note: @code{nargin} does not work on compiled functions\n(@file{.oct} files) such as built-in or dynamically loaded functions.\n@seealso{nargout, narginchk, varargin, inputname}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 1)\n    {\n      octave_value fcn = args(0);\n\n      if (fcn.is_string ())\n        {\n          symbol_table& symtab = interp.get_symbol_table ();\n\n          std::string name = fcn.string_value ();\n          fcn = symtab.find_function (name);\n          if (fcn.is_undefined ())\n            error (\"nargin: invalid function name: %s\", name.c_str ());\n        }\n\n      octave_function *fcn_val = fcn.function_value (true);\n      if (! fcn_val)\n        error (\"nargin: FCN must be a string or function handle\");\n\n      octave_user_function *ufcn = fcn_val->user_function_value (true);\n\n      if (! ufcn)\n        {\n          // Matlab gives up for histc, so maybe it's ok that we\n          // give up sometimes too?\n\n          std::string type = fcn_val->type_name ();\n          error (\"nargin: number of input arguments unavailable for %s objects\",\n                 type.c_str ());\n        }\n\n      tree_parameter_list *m_param_list = ufcn->parameter_list ();\n\n      retval = (m_param_list ? m_param_list->size () : 0);\n      if (ufcn->takes_varargs ())\n        retval = -1 - retval;\n    }\n  else\n    {\n      tree_evaluator& tw = interp.get_evaluator ();\n\n      retval = tw.get_auto_fcn_var (stack_frame::NARGIN);\n\n      if (retval.is_undefined ())\n        retval = 0;\n    }\n\n  return retval;\n}\n\nDEFMETHOD (nargout, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{n} =} nargout ()\n@deftypefnx {} {@var{n} =} nargout (@var{fcn})\nReport the number of output arguments from a function.\n\nCalled from within a function, return the number of values the caller\nexpects to receive.  At the top level, @code{nargout} with no argument is\nundefined and will produce an error.\n\nIf called with the optional argument @var{fcn}---a function name or\nhandle---return the number of declared output values that the function can\nproduce.\n\nIf the final output argument is @var{varargout} the returned value is\nnegative.\n\nFor example,\n\n@example\nf ()\n@end example\n\n@noindent\nwill cause @code{nargout} to return 0 inside the function @code{f} and\n\n@example\n[s, t] = f ()\n@end example\n\n@noindent\nwill cause @code{nargout} to return 2 inside the function @code{f}.\n\nIn the second usage,\n\n@example\nnargout (@@histc)   # or nargout (\"histc\") using a string input\n@end example\n\n@noindent\nwill return 2, because @code{histc} has two outputs, whereas\n\n@example\nnargout (@@imread)\n@end example\n\n@noindent\nwill return -2, because @code{imread} has two outputs and the second is\n@var{varargout}.\n\nProgramming Note.  @code{nargout} does not work for built-in functions and\nreturns -1 for all anonymous functions.\n@seealso{nargin, varargout, isargout, nthargout}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  octave_value retval;\n\n  if (nargin == 1)\n    {\n      octave_value fcn = args(0);\n\n      if (fcn.is_string ())\n        {\n          symbol_table& symtab = interp.get_symbol_table ();\n\n          std::string name = fcn.string_value ();\n          fcn = symtab.find_function (name);\n          if (fcn.is_undefined ())\n            error (\"nargout: invalid function name: %s\", name.c_str ());\n        }\n\n      if (fcn.is_inline_function ())\n        return ovl (1);\n\n      if (fcn.is_function_handle ())\n        {\n          octave_fcn_handle *fh = fcn.fcn_handle_value ();\n\n          if (fh->is_anonymous ())\n            return ovl (-1);\n        }\n\n      octave_function *fcn_val = fcn.function_value (true);\n      if (! fcn_val)\n        error (\"nargout: FCN must be a string or function handle\");\n\n      octave_user_function *ufcn = fcn_val->user_function_value (true);\n\n      if (! ufcn)\n        {\n          // Matlab gives up for histc, so maybe it's ok that we\n          // give up sometimes too?\n\n          std::string type = fcn_val->type_name ();\n          error (\"nargout: number of output arguments unavailable for %s objects\",\n                 type.c_str ());\n        }\n\n      tree_parameter_list *m_ret_list = ufcn->return_list ();\n\n      retval = (m_ret_list ? m_ret_list->size () : 0);\n\n      if (ufcn->takes_var_return ())\n        retval = -1 - retval;\n    }\n  else\n    {\n      if (interp.at_top_level ())\n        error (\"nargout: invalid call at top level\");\n\n      tree_evaluator& tw = interp.get_evaluator ();\n\n      retval = tw.get_auto_fcn_var (stack_frame::NARGOUT);\n\n      if (retval.is_undefined ())\n        retval = 0;\n    }\n\n  return retval;\n}\n\nDEFUN (optimize_subsasgn_calls, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} optimize_subsasgn_calls ()\n@deftypefnx {} {@var{old_val} =} optimize_subsasgn_calls (@var{new_val})\n@deftypefnx {} {@var{old_val} =} optimize_subsasgn_calls (@var{new_val}, \"local\")\nQuery or set the internal flag for @code{subsasgn} method call\noptimizations.\n\nIf true, Octave will attempt to eliminate the redundant copying when calling\nthe @code{subsasgn} method of a user-defined class.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{subsasgn}\n@end deftypefn */)\n{\n  return set_internal_variable (Voptimize_subsasgn_calls, args, nargout,\n                                \"optimize_subsasgn_calls\");\n}\n\nstatic bool\nval_in_table (const Matrix& table, double val)\n{\n  if (table.isempty ())\n    return false;\n\n  octave_idx_type i = table.lookup (val, ASCENDING);\n  return (i > 0 && table(i-1) == val);\n}\n\nstatic bool\nisargout1 (int nargout, const Matrix& ignored, double k)\n{\n  if (k != math::fix (k) || k <= 0)\n    error (\"isargout: K must be a positive integer\");\n\n  return (k == 1 || k <= nargout) && ! val_in_table (ignored, k);\n}\n\nDEFMETHOD (isargout, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isargout (@var{k})\nWithin a function, return a logical value indicating whether the argument\n@var{k} will be assigned to a variable on output.\n\nIf the result is false, the argument has been ignored during the function\ncall through the use of the tilde (~) special output argument.  Functions\ncan use @code{isargout} to avoid performing unnecessary calculations for\noutputs which are unwanted.\n\nIf @var{k} is outside the range @code{1:max (nargout)}, the function returns\nfalse.  @var{k} can also be an array, in which case the function works\nelement-by-element and a logical array is returned.  At the top level,\n@code{isargout} returns an error.\n@seealso{nargout, varargout, nthargout}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  if (interp.at_top_level ())\n    error (\"isargout: invalid call at top level\");\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  octave_value tmp;\n\n  int nargout1 = 0;\n  tmp = tw.get_auto_fcn_var (stack_frame::NARGOUT);\n  if (tmp.is_defined ())\n    nargout1 = tmp.int_value ();\n\n  Matrix ignored;\n  tmp = tw.get_auto_fcn_var (stack_frame::IGNORED);\n  if (tmp.is_defined ())\n    ignored = tmp.matrix_value ();\n\n  if (args(0).is_scalar_type ())\n    {\n      double k = args(0).double_value ();\n\n      return ovl (isargout1 (nargout1, ignored, k));\n    }\n  else if (args(0).isnumeric ())\n    {\n      const NDArray ka = args(0).array_value ();\n\n      boolNDArray r (ka.dims ());\n      for (octave_idx_type i = 0; i < ka.numel (); i++)\n        r(i) = isargout1 (nargout1, ignored, ka(i));\n\n      return ovl (r);\n    }\n  else\n    err_wrong_type_arg (\"isargout\", args(0));\n\n  return ovl ();\n}\n\n/*\n%!function [x, y] = try_isargout ()\n%!  if (isargout (1))\n%!    if (isargout (2))\n%!      x = 1; y = 2;\n%!    else\n%!      x = -1;\n%!    endif\n%!  else\n%!    if (isargout (2))\n%!      y = -2;\n%!    else\n%!      error (\"no outputs requested\");\n%!    endif\n%!  endif\n%!endfunction\n%!\n%!function [a, b] = try_isargout2 (x, y)\n%!  a = y;\n%!  b = {isargout(1), isargout(2), x};\n%!endfunction\n%!\n%!test\n%! [x, y] = try_isargout ();\n%! assert ([x, y], [1, 2]);\n%!\n%!test\n%! [x, ~] = try_isargout ();\n%! assert (x, -1);\n%!\n%!test\n%! [~, y] = try_isargout ();\n%! assert (y, -2);\n%!\n%!error [~, ~] = try_isargout ()\n%!\n## Check to see that isargout isn't sticky:\n%!test\n%! [x, y] = try_isargout ();\n%! assert ([x, y], [1, 2]);\n%!\n## It should work without ():\n%!test\n%! [~, y] = try_isargout;\n%! assert (y, -2);\n%!\n## It should work in function handles,\n%!test\n%! fh = @try_isargout;\n%! [~, y] = fh ();\n%! assert (y, -2);\n%!\n## anonymous functions,\n%!test\n%! af = @() try_isargout;\n%! [~, y] = af ();\n%! assert (y, -2);\n%!\n## and cell arrays of handles or anonymous functions.\n%!test\n%! fh = @try_isargout;\n%! af = @() try_isargout;\n%! c = {fh, af};\n%! [~, y] = c{1}();\n%! assert (y, -2);\n%!test\n%! fh = @try_isargout;\n%! af = @() try_isargout;\n%! c = {fh, af};\n%! [~, y] = c{2}();\n%! assert (y, -2);\n%!\n## Nesting, anyone?\n%!test\n%! [~, b] = try_isargout2 (try_isargout, rand);\n%! assert (b, {0, 1, -1});\n%!test\n%! [~, b] = try_isargout2 ({try_isargout, try_isargout}, rand);\n%! assert (b, {0, 1, {-1, -1}});\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov-usr-fcn.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_usr_fcn_h)\n#define octave_ov_usr_fcn_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"comment-list.h\"\n#include \"filepos.h\"\n#include \"ovl.h\"\n#include \"ov-fcn.h\"\n#include \"ov-typeinfo.h\"\n#include \"symscope.h\"\n#include \"token.h\"\n#include \"unwind-prot.h\"\n\nclass string_vector;\n\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass filepos;\nclass file_info;\nclass stack_frame;\nclass tree_identifier;\nclass tree_parameter_list;\nclass tree_statement_list;\nclass tree_evaluator;\nclass tree_expression;\nclass tree_walker;\n\nOCTAVE_END_NAMESPACE(octave)\n\nclass OCTINTERP_API octave_user_code : public octave_function\n{\nprotected:\n\n  octave_user_code (const std::string& fnm = \"\", const std::string& nm = \"\",\n                    const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),\n                    octave::tree_statement_list *cmds = nullptr,\n                    const std::string& ds = \"\")\n    : octave_function (nm, ds), m_scope (scope), m_file_name (fnm),\n      m_t_parsed (static_cast<OCTAVE_TIME_T> (0)),\n      m_t_checked (static_cast<OCTAVE_TIME_T> (0)),\n      m_file_info (nullptr), m_cmd_list (cmds)\n  {\n    if (m_scope)\n      m_scope.set_user_code (this);\n  }\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_user_code)\n\n  OCTINTERP_API ~octave_user_code ();\n\n  bool is_user_code () const { return true; }\n\n  OCTINTERP_API octave::filepos beg_pos () const;\n  OCTINTERP_API octave::filepos end_pos () const;\n\n  OCTINTERP_API octave::comment_list leading_comments () const;\n  OCTINTERP_API octave::comment_list trailing_comments () const;\n\n  OCTINTERP_API std::string get_code_line (std::size_t line);\n\n  OCTINTERP_API std::deque<std::string>\n  get_code_lines (std::size_t line, std::size_t num_lines);\n\n  OCTINTERP_API void\n  cache_function_text (const std::string& text,\n                       const octave::sys::time& timestamp);\n\n  octave::symbol_scope scope () { return m_scope; }\n\n  std::size_t scope_num_symbols () { return m_scope.num_symbols (); }\n\n  void stash_fcn_file_name (const std::string& nm) { m_file_name = nm; }\n\n  void mark_fcn_file_up_to_date (const octave::sys::time& t)\n  { m_t_checked = t; }\n\n  void stash_fcn_file_time (const octave::sys::time& t)\n  {\n    m_t_parsed = t;\n    mark_fcn_file_up_to_date (t);\n  }\n\n  std::string fcn_file_name () const { return m_file_name; }\n\n  octave::sys::time time_parsed () const { return m_t_parsed; }\n\n  octave::sys::time time_checked () const { return m_t_checked; }\n\n  virtual octave_value find_subfunction (const std::string&) const\n  {\n    return octave_value ();\n  }\n\n  virtual std::map<std::string, octave_value> subfunctions () const;\n\n  octave::tree_statement_list * body () { return m_cmd_list; }\n\n  OCTINTERP_API octave_value dump () const;\n\nprotected:\n\n  OCTINTERP_API void get_file_info ();\n\n  // Our symbol table scope.\n  octave::symbol_scope m_scope;\n\n  // The name of the file we parsed.\n  std::string m_file_name;\n\n  // The time the file was parsed.\n  octave::sys::time m_t_parsed;\n\n  // The time the file was last checked to see if it needs to be\n  // parsed again.\n  octave::sys::time m_t_checked;\n\n  // Cached text of function or script code with line offsets\n  // calculated.\n  octave::file_info *m_file_info;\n\n  // The list of commands that make up the body of this function.\n  octave::tree_statement_list *m_cmd_list;\n};\n\n// Scripts.\n\nclass OCTINTERP_API octave_user_script : public octave_user_code\n{\npublic:\n\n  OCTINTERP_API octave_user_script ();\n\n  OCTINTERP_API\n  octave_user_script (const std::string& fnm, const std::string& nm,\n                      const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),\n                      octave::tree_statement_list *cmds = nullptr,\n                      const std::string& ds = \"\");\n\n  OCTINTERP_API\n  octave_user_script (const std::string& fnm, const std::string& nm,\n                      const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),\n                      const std::string& ds = \"\");\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_user_script)\n\n  ~octave_user_script () = default;\n\n  octave_function * function_value (bool = false) { return this; }\n\n  octave_user_script * user_script_value (bool = false) { return this; }\n\n  octave_user_code * user_code_value (bool = false) { return this; }\n\n  // Scripts and user functions are both considered \"scripts\" because\n  // they are written in Octave's scripting language.\n\n  bool is_user_script () const { return true; }\n\n  // We must overload the call method so that we call the proper\n  // push_stack_frame method, which is overloaded for pointers to\n  // octave_function, octave_user_function, and octave_user_script\n  // objects.\n\n  OCTINTERP_API octave_value_list\n  call (octave::tree_evaluator& tw, int nargout = 0,\n        const octave_value_list& args = octave_value_list ());\n\n  OCTINTERP_API octave_value_list\n  execute (octave::tree_evaluator& tw, int nargout = 0,\n           const octave_value_list& args = octave_value_list ());\n\n  OCTINTERP_API void accept (octave::tree_walker& tw);\n\nprivate:\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n// User-defined functions.\n\nclass OCTINTERP_API octave_user_function : public octave_user_code\n{\npublic:\n\n  OCTINTERP_API\n  octave_user_function (const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),\n                        octave::tree_identifier *id = nullptr,\n                        octave::tree_parameter_list *pl = nullptr,\n                        octave::tree_parameter_list *rl = nullptr,\n                        octave::tree_statement_list *cl = nullptr);\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_user_function)\n\n  OCTINTERP_API ~octave_user_function ();\n\n  // Declared calling form, generated from the parse tree.\n  OCTINTERP_API std::string signature () const;\n\n  octave_function * function_value (bool = false) { return this; }\n\n  octave_user_function * user_function_value (bool = false) { return this; }\n\n  octave_user_code * user_code_value (bool = false) { return this; }\n\n  OCTINTERP_API octave_user_function *\n  define_param_list (octave::tree_parameter_list *t);\n\n  OCTINTERP_API octave_user_function *\n  define_ret_list (octave::tree_parameter_list *t);\n\n  void set_fcn_tok (const octave::token& fcn_tok) { m_fcn_tok = fcn_tok; }\n  void set_eq_tok (const octave::token& eq_tok) { m_eq_tok = eq_tok; }\n\n  OCTINTERP_API void\n  attach_trailing_comments (const octave::comment_list& lst);\n\n  octave::filepos beg_pos () const { return m_fcn_tok.beg_pos(); }\n  // The end_pos function is defined in the octave_user_code class.\n\n  octave::comment_list leading_comments () const\n  { return m_fcn_tok.leading_comments (); }\n  // The trailing_comments function is defined in the octave_user_code class.\n\n  OCTINTERP_API void maybe_relocate_end ();\n\n  OCTINTERP_API void stash_parent_fcn_scope (const octave::symbol_scope& ps);\n\n  OCTINTERP_API std::string profiler_name () const;\n\n  std::string parent_fcn_name () const\n  {\n    octave::symbol_scope pscope = parent_fcn_scope ();\n\n    return pscope.fcn_name ();\n  }\n\n  octave::symbol_scope parent_fcn_scope () const\n  {\n    return m_scope.parent_scope ();\n  }\n\n  std::list<std::string> parent_fcn_names () const\n  {\n    return m_scope.parent_fcn_names ();\n  }\n\n  OCTINTERP_API void mark_as_system_fcn_file ();\n\n  bool is_system_fcn_file () const { return m_system_fcn_file; }\n\n  bool is_user_function () const { return true; }\n\n  OCTINTERP_API void erase_subfunctions ();\n\n  OCTINTERP_API bool takes_varargs () const;\n\n  OCTINTERP_API bool takes_var_return () const;\n\n  OCTINTERP_API void mark_as_private_function (const std::string& cname = \"\");\n\n  OCTINTERP_API void lock_subfunctions ();\n\n  OCTINTERP_API void unlock_subfunctions ();\n\n  OCTINTERP_API std::map<std::string, octave_value> subfunctions () const;\n\n  OCTINTERP_API octave_value\n  find_subfunction (const std::string& subfuns) const;\n\n  OCTINTERP_API bool has_subfunctions () const;\n\n  OCTINTERP_API void\n  stash_subfunction_names (const std::list<std::string>& names);\n\n  OCTINTERP_API std::list<std::string> subfunction_names () const;\n\n  OCTINTERP_API octave_value_list all_va_args (const octave_value_list& args);\n\n  void stash_function_name (const std::string& s) { m_name = s; }\n\n  void mark_as_subfunction () { m_subfunction = true; }\n\n  bool is_subfunction () const { return m_subfunction; }\n\n  void mark_as_inline_function () { m_inline_function = true; }\n\n  bool is_inline_function () const { return m_inline_function; }\n\n  void mark_as_anonymous_function () { m_anonymous_function = true; }\n\n  bool is_anonymous_function () const { return m_anonymous_function; }\n\n  bool is_anonymous_function_of_class\n  (const std::string& cname = \"\") const\n  {\n    return m_anonymous_function\n           ? (cname.empty ()\n              ? (! dispatch_class ().empty ())\n              : cname == dispatch_class ())\n           : false;\n  }\n\n  // If we are a special expression, then the function body consists of exactly\n  // one expression.  The expression's result is the return value of the\n  // function.\n  bool is_special_expr () const\n  {\n    return is_inline_function () || is_anonymous_function ();\n  }\n\n  void mark_as_nested_function () { m_nested_function = true; }\n\n  bool is_nested_function () const { return m_nested_function; }\n\n  bool is_parent_function () const { return m_scope.is_parent (); }\n\n  void mark_as_legacy_constructor () { m_class_constructor = legacy; }\n\n  bool is_legacy_constructor (const std::string& cname = \"\") const\n  {\n    return (m_class_constructor == legacy\n            ? (cname.empty () ? true : cname == dispatch_class ()) : false);\n  }\n\n  void mark_as_classdef_constructor () { m_class_constructor = classdef; }\n\n  bool is_classdef_constructor (const std::string& cname = \"\") const\n  {\n    return (m_class_constructor == classdef\n            ? (cname.empty () ? true : cname == dispatch_class ()) : false);\n  }\n\n  void mark_as_legacy_method () { m_class_method = legacy; }\n\n  bool is_legacy_method (const std::string& cname = \"\") const\n  {\n    return (m_class_method == legacy\n            ? (cname.empty () ? true : cname == dispatch_class ()) : false);\n  }\n\n  void mark_as_classdef_method () { m_class_method = classdef; }\n\n  bool is_classdef_method (const std::string& cname = \"\") const\n  {\n    return (m_class_method == classdef\n            ? (cname.empty () ? true : cname == dispatch_class ()) : false);\n  }\n\n  // We must overload the call method so that we call the proper\n  // push_stack_frame method, which is overloaded for pointers to\n  // octave_function, octave_user_function, and octave_user_script\n  // objects.\n\n  OCTINTERP_API octave_value_list\n  call (octave::tree_evaluator& tw, int nargout = 0,\n        const octave_value_list& args = octave_value_list ());\n\n  OCTINTERP_API octave_value_list\n  execute (octave::tree_evaluator& tw, int nargout = 0,\n           const octave_value_list& args = octave_value_list ());\n\n  octave::tree_parameter_list * parameter_list () { return m_param_list; }\n\n  octave::tree_parameter_list * return_list () { return m_ret_list; }\n\n  // If is_special_expr is true, retrieve the sigular expression that forms the\n  // body.  May be null (even if is_special_expr is true).\n  OCTINTERP_API octave::tree_expression * special_expr ();\n\n  OCTINTERP_API bool subsasgn_optimization_ok ();\n\n  OCTINTERP_API void accept (octave::tree_walker& tw);\n\n  OCTINTERP_API octave_value dump () const;\n\nprivate:\n\n  enum class_method_type\n  {\n    none,\n    legacy,\n    classdef\n  };\n\n  OCTINTERP_API std::string ctor_type_str () const;\n  OCTINTERP_API std::string method_type_str () const;\n\n  // Name of this function.\n  octave::tree_identifier *m_id;\n\n  // List of arguments for this function.  These are local variables.\n  octave::tree_parameter_list *m_param_list;\n\n  // List of parameters we return.  These are also local variables in\n  // this function.\n  octave::tree_parameter_list *m_ret_list;\n\n  // We don't keep track of an end token separately because functions\n  // may still be defined without an explicit END.  If there is an\n  // explicit END, the final statement will contain it.\n\n  octave::token m_fcn_tok;\n  octave::token m_eq_tok;\n\n  // True if this function came from a file that is considered to be a\n  // system function.  This affects whether we check the time stamp\n  // on the file to see if it has changed.\n  bool m_system_fcn_file {false};\n\n  // The number of arguments that have names.\n  int m_num_named_args;\n\n  // TRUE means this is a m_subfunction of a primary function.\n  bool m_subfunction {false};\n\n  // TRUE means this is an inline function.\n  bool m_inline_function {false};\n\n  // TRUE means this is an anonymous function.\n  bool m_anonymous_function {false};\n\n  // TRUE means this is a nested function.\n  bool m_nested_function {false};\n\n  // Enum describing whether this function is the constructor for class object.\n  class_method_type m_class_constructor {none};\n\n  // Enum describing whether this function is a method for a class.\n  class_method_type m_class_method {none};\n\n  OCTINTERP_API void maybe_relocate_end_internal ();\n\n  OCTINTERP_API void print_code_function_header (const std::string& prefix);\n\n  OCTINTERP_API void print_code_function_trailer (const std::string& prefix);\n\n  // XXX FIXME (public)\npublic:\n\n  OCTINTERP_API void restore_warning_states ();\n\n  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ov.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <type_traits>\n\n#include \"data-conv.h\"\n#include \"quit.h\"\n#include \"str-vec.h\"\n\n#include \"ovl.h\"\n#include \"oct-stream.h\"\n#include \"ov.h\"\n#include \"ov-base.h\"\n#include \"ov-bool.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-cell.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-re-diag.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-legacy-range.h\"\n#include \"ov-perm.h\"\n#include \"ov-bool-sparse.h\"\n#include \"ov-cx-sparse.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-int8.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-cx-diag.h\"\n#include \"ov-flt-cx-diag.h\"\n#include \"ov-ch-mat.h\"\n#include \"ov-str-mat.h\"\n#include \"ov-range.h\"\n#include \"ov-struct.h\"\n#include \"ov-class.h\"\n#include \"ov-classdef.h\"\n#include \"ov-oncleanup.h\"\n#include \"ov-cs-list.h\"\n#include \"ov-colon.h\"\n#include \"ov-builtin.h\"\n#include \"ov-dld-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-magic-int.h\"\n#include \"ov-null-mat.h\"\n#include \"ov-lazy-idx.h\"\n#include \"ov-java.h\"\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"pr-flt-fmt.h\"\n#include \"pr-output.h\"\n#include \"symtab.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n// We are likely to have a lot of octave_value objects to allocate, so\n// make the grow_size large.\n\n// If TRUE, create special space-optimized diagonal matrix objects.\n\nstatic bool Voptimize_diagonal_matrix = true;\n\n// If TRUE, create special space-optimized permutation matrix objects.\n\nstatic bool Voptimize_permutation_matrix = true;\n\n// If TRUE, create special space-optimized range objects.\n\nstatic bool Voptimize_range = true;\n\n// FIXME\n\n// Octave's value type.\n\noctave_base_value *\noctave_value::nil_rep ()\n{\n  static octave_base_value nr;\n  return &nr;\n}\n\nstd::string\noctave_value::unary_op_as_string (unary_op op)\n{\n  switch (op)\n    {\n    case op_not:\n      return \"!\";\n\n    case op_uplus:\n      return \"+\";\n\n    case op_uminus:\n      return \"-\";\n\n    case op_transpose:\n      return \".'\";\n\n    case op_hermitian:\n      return \"'\";\n\n    case op_incr:\n      return \"++\";\n\n    case op_decr:\n      return \"--\";\n\n    default:\n      return \"<unknown>\";\n    }\n}\n\nstd::string\noctave_value::unary_op_fcn_name (unary_op op)\n{\n  switch (op)\n    {\n    case op_not:\n      return \"not\";\n\n    case op_uplus:\n      return \"uplus\";\n\n    case op_uminus:\n      return \"uminus\";\n\n    case op_transpose:\n      return \"transpose\";\n\n    case op_hermitian:\n      return \"ctranspose\";\n\n    default:\n      return \"<unknown>\";\n    }\n}\n\nstd::string\noctave_value::binary_op_as_string (binary_op op)\n{\n  switch (op)\n    {\n    case op_add:\n      return \"+\";\n\n    case op_sub:\n      return \"-\";\n\n    case op_mul:\n      return \"*\";\n\n    case op_div:\n      return \"/\";\n\n    case op_pow:\n      return \"^\";\n\n    case op_ldiv:\n      return R\"(\\)\";\n\n    case op_lt:\n      return \"<\";\n\n    case op_le:\n      return \"<=\";\n\n    case op_eq:\n      return \"==\";\n\n    case op_ge:\n      return \">=\";\n\n    case op_gt:\n      return \">\";\n\n    case op_ne:\n      return \"!=\";\n\n    case op_el_mul:\n      return \".*\";\n\n    case op_el_div:\n      return \"./\";\n\n    case op_el_pow:\n      return \".^\";\n\n    case op_el_ldiv:\n      return R\"(.\\)\";\n\n    case op_el_and:\n      return \"&\";\n\n    case op_el_or:\n      return \"|\";\n\n    case op_struct_ref:\n      return \".\";\n\n    default:\n      return \"<unknown>\";\n    }\n}\n\nstd::string\noctave_value::binary_op_fcn_name (binary_op op)\n{\n  switch (op)\n    {\n    case op_add:\n      return \"plus\";\n\n    case op_sub:\n      return \"minus\";\n\n    case op_mul:\n      return \"mtimes\";\n\n    case op_div:\n      return \"mrdivide\";\n\n    case op_pow:\n      return \"mpower\";\n\n    case op_ldiv:\n      return \"mldivide\";\n\n    case op_lt:\n      return \"lt\";\n\n    case op_le:\n      return \"le\";\n\n    case op_eq:\n      return \"eq\";\n\n    case op_ge:\n      return \"ge\";\n\n    case op_gt:\n      return \"gt\";\n\n    case op_ne:\n      return \"ne\";\n\n    case op_el_mul:\n      return \"times\";\n\n    case op_el_div:\n      return \"rdivide\";\n\n    case op_el_pow:\n      return \"power\";\n\n    case op_el_ldiv:\n      return \"ldivide\";\n\n    case op_el_and:\n      return \"and\";\n\n    case op_el_or:\n      return \"or\";\n\n    default:\n      return \"<unknown>\";\n    }\n}\n\nstd::string\noctave_value::binary_op_fcn_name (compound_binary_op op)\n{\n  switch (op)\n    {\n    case op_trans_mul:\n      return \"transtimes\";\n\n    case op_mul_trans:\n      return \"timestrans\";\n\n    case op_herm_mul:\n      return \"hermtimes\";\n\n    case op_mul_herm:\n      return \"timesherm\";\n\n    case op_trans_ldiv:\n      return \"transldiv\";\n\n    case op_herm_ldiv:\n      return \"hermldiv\";\n\n    case op_el_and_not:\n      return \"andnot\";\n\n    case op_el_or_not:\n      return \"ornot\";\n\n    case op_el_not_and:\n      return \"notand\";\n\n    case op_el_not_or:\n      return \"notor\";\n\n    default:\n      return \"<unknown>\";\n    }\n}\n\nstd::string\noctave_value::assign_op_as_string (assign_op op)\n{\n  switch (op)\n    {\n    case op_asn_eq:\n      return \"=\";\n\n    case op_add_eq:\n      return \"+=\";\n\n    case op_sub_eq:\n      return \"-=\";\n\n    case op_mul_eq:\n      return \"*=\";\n\n    case op_div_eq:\n      return \"/=\";\n\n    case op_ldiv_eq:\n      return R\"(\\=)\";\n\n    case op_pow_eq:\n      return \"^=\";\n\n    case op_el_mul_eq:\n      return \".*=\";\n\n    case op_el_div_eq:\n      return \"./=\";\n\n    case op_el_ldiv_eq:\n      return R\"(.\\=)\";\n\n    case op_el_pow_eq:\n      return \".^=\";\n\n    case op_el_and_eq:\n      return \"&=\";\n\n    case op_el_or_eq:\n      return \"|=\";\n\n    default:\n      return \"<unknown>\";\n    }\n}\n\noctave_value::binary_op\noctave_value::assign_op_to_binary_op (assign_op op)\n{\n  switch (op)\n    {\n    case op_add_eq:\n      return op_add;\n\n    case op_sub_eq:\n      return op_sub;\n\n    case op_mul_eq:\n      return op_mul;\n\n    case op_div_eq:\n      return op_div;\n\n    case op_ldiv_eq:\n      return op_ldiv;\n\n    case op_pow_eq:\n      return op_pow;\n\n    case op_el_mul_eq:\n      return op_el_mul;\n\n    case op_el_div_eq:\n      return op_el_div;\n\n    case op_el_ldiv_eq:\n      return op_el_ldiv;\n\n    case op_el_pow_eq:\n      return op_el_pow;\n\n    case op_el_and_eq:\n      return op_el_and;\n\n    case op_el_or_eq:\n      return op_el_or;\n\n    default:\n      return unknown_binary_op;\n    }\n}\n\noctave_value::assign_op\noctave_value::binary_op_to_assign_op (binary_op op)\n{\n  switch (op)\n    {\n    case op_add:\n      return op_add_eq;\n\n    case op_sub:\n      return op_sub_eq;\n\n    case op_mul:\n      return op_mul_eq;\n\n    case op_div:\n      return op_div_eq;\n\n    case op_el_mul:\n      return op_el_mul_eq;\n\n    case op_el_div:\n      return op_el_div_eq;\n\n    case op_el_and:\n      return op_el_and_eq;\n\n    case op_el_or:\n      return op_el_or_eq;\n\n    default:\n      return unknown_assign_op;\n    }\n}\n\noctave_value::octave_value (short int i)\n  : m_rep (new octave_scalar (i))\n{ }\n\noctave_value::octave_value (unsigned short int i)\n  : m_rep (new octave_scalar (i))\n{ }\n\noctave_value::octave_value (int i)\n  : m_rep (new octave_scalar (i))\n{ }\n\noctave_value::octave_value (unsigned int i)\n  : m_rep (new octave_scalar (i))\n{ }\n\noctave_value::octave_value (long int i)\n  : m_rep (new octave_scalar (i))\n{ }\n\noctave_value::octave_value (unsigned long int i)\n  : m_rep (new octave_scalar (i))\n{ }\n\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\noctave_value::octave_value (long long int i)\n  : m_rep (new octave_scalar (i))\n{ }\n#endif\n\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\noctave_value::octave_value (unsigned long long int i)\n  : m_rep (new octave_scalar (i))\n{ }\n#endif\n\noctave_value::octave_value (octave::sys::time t)\n  : m_rep (new octave_scalar (t.double_value ()))\n{ }\n\noctave_value::octave_value (double d)\n  : m_rep (new octave_scalar (d))\n{ }\n\noctave_value::octave_value (float d)\n  : m_rep (new octave_float_scalar (d))\n{ }\n\noctave_value::octave_value (const Cell& c, bool is_csl)\n  : m_rep (is_csl\n           ? dynamic_cast<octave_base_value *> (new octave_cs_list (c))\n           : dynamic_cast<octave_base_value *> (new octave_cell (c)))\n{ }\n\noctave_value::octave_value (const Matrix& m, const MatrixType& t)\n  : m_rep (new octave_matrix (m, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatMatrix& m, const MatrixType& t)\n  : m_rep (new octave_float_matrix (m, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const NDArray& a)\n  : m_rep (new octave_matrix (a))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatNDArray& a)\n  : m_rep (new octave_float_matrix (a))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<double>& a)\n  : m_rep (new octave_matrix (a))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<float>& a)\n  : m_rep (new octave_float_matrix (a))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const DiagArray2<double>& d)\n  : m_rep (Voptimize_diagonal_matrix\n           ? dynamic_cast<octave_base_value *> (new octave_diag_matrix (d))\n           : dynamic_cast<octave_base_value *> (new octave_matrix (Matrix (d))))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const DiagArray2<float>& d)\n  : m_rep (Voptimize_diagonal_matrix\n           ? dynamic_cast<octave_base_value *> (new octave_float_diag_matrix (d))\n           : dynamic_cast<octave_base_value *> (new octave_float_matrix (FloatMatrix (d))))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const DiagArray2<Complex>& d)\n  : m_rep (Voptimize_diagonal_matrix\n           ? dynamic_cast<octave_base_value *> (new octave_complex_diag_matrix (d))\n           : dynamic_cast<octave_base_value *> (new octave_complex_matrix (ComplexMatrix (d))))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const DiagArray2<FloatComplex>& d)\n  : m_rep (Voptimize_diagonal_matrix\n           ? dynamic_cast<octave_base_value *> (new octave_float_complex_diag_matrix (d))\n           : dynamic_cast<octave_base_value *> (new octave_float_complex_matrix (FloatComplexMatrix (d))))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const DiagMatrix& d)\n  : m_rep (Voptimize_diagonal_matrix\n           ? dynamic_cast<octave_base_value *> (new octave_diag_matrix (d))\n           : dynamic_cast<octave_base_value *> (new octave_matrix (Matrix (d))))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatDiagMatrix& d)\n  : m_rep (Voptimize_diagonal_matrix\n           ? dynamic_cast<octave_base_value *> (new octave_float_diag_matrix (d))\n           : dynamic_cast<octave_base_value *> (new octave_float_matrix (FloatMatrix (d))))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const RowVector& v)\n  : m_rep (new octave_matrix (v))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatRowVector& v)\n  : m_rep (new octave_float_matrix (v))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const ColumnVector& v)\n  : m_rep (new octave_matrix (v))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatColumnVector& v)\n  : m_rep (new octave_float_matrix (v))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Complex& C)\n  : m_rep (new octave_complex (C))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatComplex& C)\n  : m_rep (new octave_float_complex (C))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const ComplexMatrix& m, const MatrixType& t)\n  : m_rep (new octave_complex_matrix (m, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatComplexMatrix& m, const MatrixType& t)\n  : m_rep (new octave_float_complex_matrix (m, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const ComplexNDArray& a)\n  : m_rep (new octave_complex_matrix (a))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatComplexNDArray& a)\n  : m_rep (new octave_float_complex_matrix (a))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<Complex>& a)\n  : m_rep (new octave_complex_matrix (a))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<FloatComplex>& a)\n  : m_rep (new octave_float_complex_matrix (a))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const ComplexDiagMatrix& d)\n  : m_rep (Voptimize_diagonal_matrix\n           ? dynamic_cast<octave_base_value *> (new octave_complex_diag_matrix (d))\n           : dynamic_cast<octave_base_value *> (new octave_complex_matrix (ComplexMatrix (d))))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatComplexDiagMatrix& d)\n  : m_rep (Voptimize_diagonal_matrix\n           ? dynamic_cast<octave_base_value *> (new octave_float_complex_diag_matrix (d))\n           : dynamic_cast<octave_base_value *> (new octave_float_complex_matrix (FloatComplexMatrix (d))))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const ComplexRowVector& v)\n  : m_rep (new octave_complex_matrix (v))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatComplexRowVector& v)\n  : m_rep (new octave_float_complex_matrix (v))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const ComplexColumnVector& v)\n  : m_rep (new octave_complex_matrix (v))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const FloatComplexColumnVector& v)\n  : m_rep (new octave_float_complex_matrix (v))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const PermMatrix& p)\n  : m_rep (Voptimize_permutation_matrix\n           ? dynamic_cast<octave_base_value *> (new octave_perm_matrix (p))\n           : dynamic_cast<octave_base_value *> (new octave_matrix (Matrix (p))))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (bool b)\n  : m_rep (new octave_bool (b))\n{ }\n\noctave_value::octave_value (const boolMatrix& bm, const MatrixType& t)\n  : m_rep (new octave_bool_matrix (bm, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const boolNDArray& bnda)\n  : m_rep (new octave_bool_matrix (bnda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<bool>& bnda)\n  : m_rep (new octave_bool_matrix (bnda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (char c, char type)\n  : m_rep (type == '\"'\n           ? new octave_char_matrix_dq_str (c)\n           : new octave_char_matrix_sq_str (c))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const char *s, char type)\n  : m_rep (type == '\"'\n           ? new octave_char_matrix_dq_str (s)\n           : new octave_char_matrix_sq_str (s))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const std::string& s, char type)\n  : m_rep (type == '\"'\n           ? new octave_char_matrix_dq_str (s)\n           : new octave_char_matrix_sq_str (s))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const string_vector& s, char type)\n  : m_rep (type == '\"'\n           ? new octave_char_matrix_dq_str (s)\n           : new octave_char_matrix_sq_str (s))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const charMatrix& chm, char type)\n  : m_rep (type == '\"'\n           ? new octave_char_matrix_dq_str (chm)\n           : new octave_char_matrix_sq_str (chm))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const charNDArray& chm, char type)\n  : m_rep (type == '\"'\n           ? new octave_char_matrix_dq_str (chm)\n           : new octave_char_matrix_sq_str (chm))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<char>& chm, char type)\n  : m_rep (type == '\"'\n           ? new octave_char_matrix_dq_str (chm)\n           : new octave_char_matrix_sq_str (chm))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const SparseMatrix& m, const MatrixType& t)\n  : m_rep (new octave_sparse_matrix (m, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Sparse<double>& m, const MatrixType& t)\n  : m_rep (new octave_sparse_matrix (m, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const SparseComplexMatrix& m, const MatrixType& t)\n  : m_rep (new octave_sparse_complex_matrix (m, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Sparse<Complex>& m, const MatrixType& t)\n  : m_rep (new octave_sparse_complex_matrix (m, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const SparseBoolMatrix& bm, const MatrixType& t)\n  : m_rep (new octave_sparse_bool_matrix (bm, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Sparse<bool>& bm, const MatrixType& t)\n  : m_rep (new octave_sparse_bool_matrix (bm, t))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_int8& i)\n  : m_rep (new octave_int8_scalar (i))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_uint8& i)\n  : m_rep (new octave_uint8_scalar (i))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_int16& i)\n  : m_rep (new octave_int16_scalar (i))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_uint16& i)\n  : m_rep (new octave_uint16_scalar (i))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_int32& i)\n  : m_rep (new octave_int32_scalar (i))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_uint32& i)\n  : m_rep (new octave_uint32_scalar (i))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_int64& i)\n  : m_rep (new octave_int64_scalar (i))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_uint64& i)\n  : m_rep (new octave_uint64_scalar (i))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const int8NDArray& inda)\n  : m_rep (new octave_int8_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<octave_int8>& inda)\n  : m_rep (new octave_int8_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const uint8NDArray& inda)\n  : m_rep (new octave_uint8_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<octave_uint8>& inda)\n  : m_rep (new octave_uint8_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const int16NDArray& inda)\n  : m_rep (new octave_int16_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<octave_int16>& inda)\n  : m_rep (new octave_int16_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const uint16NDArray& inda)\n  : m_rep (new octave_uint16_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<octave_uint16>& inda)\n  : m_rep (new octave_uint16_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const int32NDArray& inda)\n  : m_rep (new octave_int32_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<octave_int32>& inda)\n  : m_rep (new octave_int32_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const uint32NDArray& inda)\n  : m_rep (new octave_uint32_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<octave_uint32>& inda)\n  : m_rep (new octave_uint32_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const int64NDArray& inda)\n  : m_rep (new octave_int64_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<octave_int64>& inda)\n  : m_rep (new octave_int64_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const uint64NDArray& inda)\n  : m_rep (new octave_uint64_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<octave_uint64>& inda)\n  : m_rep (new octave_uint64_matrix (inda))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<octave_idx_type>& inda, bool zero_based,\n                            bool cache_index)\n  : m_rep (new octave_matrix (inda, zero_based, cache_index))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave::idx_vector& idx, bool lazy)\n  : m_rep ()\n{\n  double scalar;\n  octave::range<double> range;\n  NDArray array;\n  boolNDArray mask;\n  octave::idx_vector::idx_class_type idx_class;\n\n  if (lazy)\n    {\n      // Only make lazy indices out of ranges and index vectors.\n      switch (idx.idx_class ())\n        {\n        case octave::idx_vector::class_range:\n        case octave::idx_vector::class_vector:\n          m_rep = new octave_lazy_index (idx);\n          maybe_mutate ();\n          return;\n\n        default:\n          break;\n        }\n    }\n\n  idx.unconvert (idx_class, scalar, range, array, mask);\n\n  switch (idx_class)\n    {\n    case octave::idx_vector::class_colon:\n      m_rep = new octave_magic_colon ();\n      break;\n\n    case octave::idx_vector::class_range:\n      m_rep = new octave_range (range, idx);\n      break;\n\n    case octave::idx_vector::class_scalar:\n      m_rep = new octave_scalar (scalar);\n      break;\n\n    case octave::idx_vector::class_vector:\n      m_rep = new octave_matrix (array, idx);\n      break;\n\n    case octave::idx_vector::class_mask:\n      m_rep = new octave_bool_matrix (mask, idx);\n      break;\n\n    case octave::idx_vector::class_invalid:\n      error (\"unexpected: invalid index in conversion to octave_value - please report this bug\");\n      break;\n\n      // We should have handled all possible enum values above.  Rely\n      // on compiler diagnostics to warn if we haven't.  For example,\n      // GCC's -Wswitch option, enabled by -Wall, will provide a\n      // warning.\n    }\n\n  // FIXME: needed?\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const Array<std::string>& cellstr)\n  : m_rep (new octave_cell (cellstr))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave::range<double>& r, bool force_range)\n  : m_rep (force_range || Voptimize_range\n           ? dynamic_cast<octave_base_value *> (new ov_range<double> (r))\n           : dynamic_cast<octave_base_value *> (new octave_matrix (r.array_value ())))\n{\n  maybe_mutate ();\n}\n\n// For now, enable only range<double>.\n\noctave_value::octave_value (const octave_map& m)\n  : m_rep (new octave_struct (m))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_scalar_map& m)\n  : m_rep (new octave_scalar_struct (m))\n{ }\n\noctave_value::octave_value (const std::map<std::string, octave_value>& m)\n  : m_rep (new octave_scalar_struct (m))\n{ }\n\noctave_value::octave_value (const octave_map& m, const std::string& id,\n                            const std::list<std::string>& plist)\n  : m_rep (new octave_class (m, id, plist))\n{\n  maybe_mutate ();\n}\n\noctave_value::octave_value (const octave_scalar_map& m, const std::string& id,\n                            const std::list<std::string>& plist)\n  : m_rep (new octave_class (m, id, plist))\n{ }\n\noctave_value::octave_value (const octave_value_list& l)\n  : m_rep (new octave_cs_list (l))\n{ }\n\noctave_value::octave_value (octave_value::magic_colon)\n  : m_rep (new octave_magic_colon ())\n{ }\n\noctave_base_value *\noctave_value::clone () const\n{\n  return m_rep->clone ();\n}\n\nvoid\noctave_value::break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame)\n{\n  if (is_function_handle ())\n    {\n      octave_fcn_handle *fhdl = m_rep->fcn_handle_value ();\n\n      if (fhdl->is_nested (frame) && ! fhdl->is_weak_nested ())\n        *this = fhdl->make_weak_nested_handle ();\n      else if (fhdl->is_anonymous () && ! fhdl->is_weak_anonymous ())\n        *this = fhdl->make_weak_anonymous_handle ();\n    }\n  else\n    {\n      // FIXME: Is there a efficient way to avoid calling make_unique\n      // if REP doesn't contain any nested function handles?\n      //\n      // Probably we should be asking REP to make a modified copy IFF it\n      // is needed, then replace our REP with that if a copy is made,\n      // otherwise we leave it alone.\n\n      make_unique ();\n\n      m_rep->break_closure_cycles (frame);\n    }\n}\n\nvoid\noctave_value::maybe_mutate ()\n{\n  octave_base_value *tmp = m_rep->try_narrowing_conversion ();\n\n  if (tmp && tmp != m_rep)\n    {\n      if (--m_rep->m_count == 0)\n        delete m_rep;\n\n      m_rep = tmp;\n    }\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (double, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} double (@var{x})\nConvert @var{x} to double precision type.\n@seealso{single}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).as_double ());\n}\n\n/*\n%!assert (class (double (single (1))), \"double\")\n%!assert (class (double (single (1 + i))), \"double\")\n%!assert (class (double (int8 (1))), \"double\")\n%!assert (class (double (uint8 (1))), \"double\")\n%!assert (class (double (int16 (1))), \"double\")\n%!assert (class (double (uint16 (1))), \"double\")\n%!assert (class (double (int32 (1))), \"double\")\n%!assert (class (double (uint32 (1))), \"double\")\n%!assert (class (double (int64 (1))), \"double\")\n%!assert (class (double (uint64 (1))), \"double\")\n%!assert (class (double (true)), \"double\")\n%!assert (class (double (\"A\")), \"double\")\n%!test\n%! x = sparse (logical ([1 0; 0 1]));\n%! y = double (x);\n%! assert (class (x), \"logical\");\n%! assert (class (y), \"double\");\n%! assert (issparse (y));\n%!test\n%! x = diag (single ([1 3 2]));\n%! y = double (x);\n%! assert (class (x), \"single\");\n%! assert (class (y), \"double\");\n%!test\n%! x = diag (single ([i 3 2]));\n%! y = double (x);\n%! assert (class (x), \"single\");\n%! assert (class (y), \"double\");\n*/\n\nDEFUN (single, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} single (@var{x})\nConvert @var{x} to single precision type.\n@seealso{double}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return args(0).as_single ();\n\n  return ovl ();\n}\n\n/*\n%!assert (class (single (1)), \"single\")\n%!assert (class (single (1 + i)), \"single\")\n%!assert (class (single (int8 (1))), \"single\")\n%!assert (class (single (uint8 (1))), \"single\")\n%!assert (class (single (int16 (1))), \"single\")\n%!assert (class (single (uint16 (1))), \"single\")\n%!assert (class (single (int32 (1))), \"single\")\n%!assert (class (single (uint32 (1))), \"single\")\n%!assert (class (single (int64 (1))), \"single\")\n%!assert (class (single (uint64 (1))), \"single\")\n%!assert (class (single (true)), \"single\")\n%!assert (class (single (\"A\")), \"single\")\n%!error single (sparse (1))\n%!test\n%! x = diag ([1 3 2]);\n%! y = single (x);\n%! assert (class (x), \"double\");\n%! assert (class (y), \"single\");\n%!test\n%! x = diag ([i 3 2]);\n%! y = single (x);\n%! assert (class (x), \"double\");\n%! assert (class (y), \"single\");\n*/\n\nDEFUN (int8, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} int8 (@var{x})\nConvert @var{x} to 8-bit integer type.\n@seealso{uint8, int16, uint16, int32, uint32, int64, uint64}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return args(0).as_int8 ();\n}\n\n/*\n%!assert (class (int8 (1)), \"int8\")\n%!assert (int8 (1.25), int8 (1))\n%!assert (int8 (1.5), int8 (2))\n%!assert (int8 (-1.5), int8 (-2))\n%!assert (int8 (2^9), int8 (2^8-1))\n%!assert (int8 (-2^9), int8 (-2^8))\n*/\n\nDEFUN (int16, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} int16 (@var{x})\nConvert @var{x} to 16-bit integer type.\n@seealso{int8, uint8, uint16, int32, uint32, int64, uint64}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return args(0).as_int16 ();\n}\n\n/*\n%!assert (class (int16 (1)), \"int16\")\n%!assert (int16 (1.25), int16 (1))\n%!assert (int16 (1.5), int16 (2))\n%!assert (int16 (-1.5), int16 (-2))\n%!assert (int16 (2^17), int16 (2^16-1))\n%!assert (int16 (-2^17), int16 (-2^16))\n*/\n\nDEFUN (int32, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} int32 (@var{x})\nConvert @var{x} to 32-bit integer type.\n@seealso{int8, uint8, int16, uint16, uint32, int64, uint64}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return args(0).as_int32 ();\n}\n\n/*\n%!assert (class (int32 (1)), \"int32\")\n%!assert (int32 (1.25), int32 (1))\n%!assert (int32 (1.5), int32 (2))\n%!assert (int32 (-1.5), int32 (-2))\n%!assert (int32 (2^33), int32 (2^32-1))\n%!assert (int32 (-2^33), int32 (-2^32))\n*/\n\nDEFUN (int64, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} int64 (@var{x})\nConvert @var{x} to 64-bit integer type.\n@seealso{int8, uint8, int16, uint16, int32, uint32, uint64}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return args(0).as_int64 ();\n}\n\n/*\n%!assert (class (int64 (1)), \"int64\")\n%!assert (int64 (1.25), int64 (1))\n%!assert (int64 (1.5), int64 (2))\n%!assert (int64 (-1.5), int64 (-2))\n%!assert (int64 (2^65), int64 (2^64-1))\n%!assert (int64 (-2^65), int64 (-2^64))\n*/\n\nDEFUN (uint8, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} uint8 (@var{x})\nConvert @var{x} to unsigned 8-bit integer type.\n@seealso{int8, int16, uint16, int32, uint32, int64, uint64}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return args(0).as_uint8 ();\n}\n\n/*\n%!assert (class (uint8 (1)), \"uint8\")\n%!assert (uint8 (1.25), uint8 (1))\n%!assert (uint8 (1.5), uint8 (2))\n%!assert (uint8 (-1.5), uint8 (0))\n%!assert (uint8 (2^9), uint8 (2^8-1))\n%!assert (uint8 (-2^9), uint8 (0))\n*/\n\nDEFUN (uint16, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} uint16 (@var{x})\nConvert @var{x} to unsigned 16-bit integer type.\n@seealso{int8, uint8, int16, int32, uint32, int64, uint64}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return args(0).as_uint16 ();\n}\n\n/*\n%!assert (class (uint16 (1)), \"uint16\")\n%!assert (uint16 (1.25), uint16 (1))\n%!assert (uint16 (1.5), uint16 (2))\n%!assert (uint16 (-1.5), uint16 (0))\n%!assert (uint16 (2^17), uint16 (2^16-1))\n%!assert (uint16 (-2^17), uint16 (0))\n*/\n\nDEFUN (uint32, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} uint32 (@var{x})\nConvert @var{x} to unsigned 32-bit integer type.\n@seealso{int8, uint8, int16, uint16, int32, int64, uint64}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return args(0).as_uint32 ();\n}\n\n/*\n%!assert (class (uint32 (1)), \"uint32\")\n%!assert (uint32 (1.25), uint32 (1))\n%!assert (uint32 (1.5), uint32 (2))\n%!assert (uint32 (-1.5), uint32 (0))\n%!assert (uint32 (2^33), uint32 (2^32-1))\n%!assert (uint32 (-2^33), uint32 (0))\n*/\n\nDEFUN (uint64, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{y} =} uint64 (@var{x})\nConvert @var{x} to unsigned 64-bit integer type.\n@seealso{int8, uint8, int16, uint16, int32, uint32, int64}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return args(0).as_uint64 ();\n}\n\n/*\n%!assert (class (uint64 (1)), \"uint64\")\n%!assert (uint64 (1.25), uint64 (1))\n%!assert (uint64 (1.5), uint64 (2))\n%!assert (uint64 (-1.5), uint64 (0))\n%!assert (uint64 (2^65), uint64 (2^64-1))\n%!assert (uint64 (-2^65), uint64 (0))\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n\noctave_value\noctave_value::single_subsref (const std::string& type,\n                              const octave_value_list& idx)\n{\n  std::list<octave_value_list> i;\n\n  i.push_back (idx);\n\n  return m_rep->subsref (type, i);\n}\n\noctave_value_list\noctave_value::\nsimple_subsref (char type, octave_value_list& idx, int nargout)\n{\n  return m_rep->simple_subsref (type, idx, nargout);\n}\n\noctave_value_list\noctave_value::subsref (const std::string& type,\n                       const std::list<octave_value_list>& idx, int nargout)\n{\n  return m_rep->subsref (type, idx, nargout);\n}\n\noctave_value\noctave_value::next_subsref (const std::string& type,\n                            const std::list<octave_value_list>& idx,\n                            std::size_t skip)\n{\n  if (idx.size () > skip)\n    {\n      std::list<octave_value_list> new_idx (std::next (idx.begin (), skip),\n                                            idx.end ());\n      return subsref (type.substr (skip), new_idx);\n    }\n  else\n    return *this;\n}\n\noctave_value_list\noctave_value::next_subsref (int nargout, const std::string& type,\n                            const std::list<octave_value_list>& idx,\n                            std::size_t skip)\n{\n  if (idx.size () > skip)\n    {\n      std::list<octave_value_list> new_idx (std::next (idx.begin (), skip),\n                                            idx.end ());\n      return subsref (type.substr (skip), new_idx, nargout);\n    }\n  else\n    return *this;\n}\n\noctave_value\noctave_value::next_subsref (bool auto_add, const std::string& type,\n                            const std::list<octave_value_list>& idx,\n                            std::size_t skip)\n{\n  if (idx.size () > skip)\n    {\n      std::list<octave_value_list> new_idx (std::next (idx.begin (), skip),\n                                            idx.end ());\n      return subsref (type.substr (skip), new_idx, auto_add);\n    }\n  else\n    return *this;\n}\n\noctave_idx_type\noctave_value::end_index (octave_idx_type index_position,\n                         octave_idx_type num_indices) const\n{\n  dim_vector dv = dims ();\n  int ndims = dv.ndims ();\n\n  if (num_indices < ndims)\n    {\n      for (int i = num_indices; i < ndims; i++)\n        dv(num_indices-1) *= dv(i);\n\n      if (num_indices == 1)\n        {\n          ndims = 2;\n          dv.resize (ndims);\n          dv(1) = 1;\n        }\n      else\n        {\n          ndims = num_indices;\n          dv.resize (ndims);\n        }\n    }\n\n  return (index_position < ndims ? dv(index_position) : 1);\n}\n\noctave_value\noctave_value::subsasgn (const std::string& type,\n                        const std::list<octave_value_list>& idx,\n                        const octave_value& rhs)\n{\n  return m_rep->subsasgn (type, idx, rhs);\n}\n\noctave_value\noctave_value::undef_subsasgn (const std::string& type,\n                              const std::list<octave_value_list>& idx,\n                              const octave_value& rhs)\n{\n  return m_rep->undef_subsasgn (type, idx, rhs);\n}\n\noctave_value&\noctave_value::assign (assign_op op, const std::string& type,\n                      const std::list<octave_value_list>& idx,\n                      const octave_value& rhs)\n{\n  make_unique ();\n\n  octave_value t_rhs = rhs;\n\n  if (op != op_asn_eq)\n    {\n      if (! is_defined ())\n        error (\"in computed assignment A(index) OP= X, A must be defined first\");\n\n      octave_value t = subsref (type, idx);\n\n      binary_op binop = op_eq_to_binary_op (op);\n\n      t_rhs = octave::binary_op (binop, t, rhs);\n    }\n\n  *this = subsasgn (type, idx, t_rhs);\n\n  return *this;\n}\n\noctave_value&\noctave_value::assign (assign_op op, const octave_value& rhs)\n{\n  if (op == op_asn_eq)\n    // Regularize a null matrix if stored into a variable.\n    operator = (rhs.storable_value ());\n  else if (is_defined ())\n    {\n      octave::type_info::assign_op_fcn f = nullptr;\n\n      // Only attempt to operate in-place if this variable is unshared.\n      if (m_rep->m_count == 1)\n        {\n          int tthis = this->type_id ();\n          int trhs = rhs.type_id ();\n\n          octave::type_info& ti = octave::__get_type_info__ ();\n\n          f = ti.lookup_assign_op (op, tthis, trhs);\n        }\n\n      if (f)\n        {\n          f (*m_rep, octave_value_list (), rhs.get_rep ());\n          // Usually unnecessary, but may be needed (complex arrays).\n          maybe_mutate ();\n        }\n      else\n        {\n\n          binary_op binop = op_eq_to_binary_op (op);\n\n          octave_value t = octave::binary_op (binop, *this, rhs);\n\n          operator = (t);\n        }\n    }\n  else\n    error (\"in computed assignment A OP= X, A must be defined first\");\n\n  return *this;\n}\n\n// FIXME: This is a bit of a kluge.  We'd like to just use val.dims()\n// and if val is an object, expect that dims will call size if it is\n// overloaded by a user-defined method.  But there are currently some\n// unresolved const issues that prevent that solution from working.\n\nstd::string\noctave_value::get_dims_str () const\n{\n  octave_value tmp = *this;\n\n  Matrix sz = tmp.size ();\n\n  dim_vector dv = dim_vector::alloc (sz.numel ());\n\n  for (octave_idx_type i = 0; i < dv.ndims (); i++)\n    dv(i) = sz(i);\n\n  return dv.str ();\n}\n\noctave_idx_type\noctave_value::length () const\n{\n  octave_idx_type retval = 0;\n\n  const dim_vector dv = dims ();\n\n  for (int i = 0; i < dv.ndims (); i++)\n    {\n      if (dv(i) == 0)\n        {\n          retval = 0;\n          break;\n        }\n\n      if (dv(i) > retval)\n        retval = dv(i);\n    }\n\n  return retval;\n}\n\nbool\noctave_value::is_equal (const octave_value& test) const\n{\n  bool retval = false;\n\n  // If there is no op_eq for these types, we can't compare values.\n\n  if (rows () == test.rows () && columns () == test.columns ())\n    {\n      octave_value tmp = octave::binary_op (octave_value::op_eq, *this, test);\n\n      // Empty array also means a match.\n      if (tmp.is_defined ())\n        {\n          if (tmp.isempty ())\n            retval = true;\n          else\n            {\n              // Reshape into a vector and call all() explicitly,\n              // to avoid Octave:array-as-logical warning.\n              tmp = tmp.reshape (dim_vector (tmp.numel (), 1));\n              retval = tmp.all ().is_true ();\n            }\n        }\n    }\n\n  return retval;\n}\n\n// Define the idx_type_value function here instead of in ov.h to avoid\n// needing definitions for the SIZEOF_X macros in ov.h.\n\noctave_idx_type\noctave_value::idx_type_value (bool req_int, bool frc_str_conv) const\n{\n#if defined (OCTAVE_ENABLE_64)\n  return int64_value (req_int, frc_str_conv);\n#else\n  return int_value (req_int, frc_str_conv);\n#endif\n}\n\noctave_idx_type\noctave_value::strict_idx_type_value (bool frc_str_conv) const\n{\n#if defined (OCTAVE_ENABLE_64)\n  return int64_value (true, frc_str_conv);\n#else\n  return int_value (true, frc_str_conv);\n#endif\n}\n\nCell\noctave_value::cell_value () const\n{\n  return m_rep->cell_value ();\n}\n\noctave_map\noctave_value::map_value () const\n{\n  return m_rep->map_value ();\n}\n\noctave_scalar_map\noctave_value::scalar_map_value () const\n{\n  return m_rep->scalar_map_value ();\n}\n\noctave_function *\noctave_value::function_value (bool silent) const\n{\n  return m_rep->function_value (silent);\n}\n\noctave_classdef *\noctave_value::classdef_object_value (bool silent) const\n{\n  return m_rep->classdef_object_value (silent);\n}\n\noctave_user_function *\noctave_value::user_function_value (bool silent) const\n{\n  return m_rep->user_function_value (silent);\n}\n\noctave_user_script *\noctave_value::user_script_value (bool silent) const\n{\n  return m_rep->user_script_value (silent);\n}\n\noctave_user_code *\noctave_value::user_code_value (bool silent) const\n{\n  return m_rep->user_code_value (silent);\n}\n\noctave_fcn_handle *\noctave_value::fcn_handle_value (bool silent) const\n{\n  return m_rep->fcn_handle_value (silent);\n}\n\noctave_value_list\noctave_value::list_value () const\n{\n  return m_rep->list_value ();\n}\n\nstatic dim_vector\nmake_vector_dims (const dim_vector& dv, bool force_vector_conversion,\n                  const std::string& my_type, const std::string& wanted_type)\n{\n  dim_vector retval (dv);\n  retval.chop_trailing_singletons ();\n  octave_idx_type nel = dv.numel ();\n\n  if (retval.ndims () > 2 || (retval(0) != 1 && retval(1) != 1))\n    {\n      if (! force_vector_conversion)\n        warn_implicit_conversion (\"Octave:array-to-vector\",\n                                  my_type.c_str (), wanted_type.c_str ());\n      retval = dim_vector (nel, 1);\n    }\n\n  return retval;\n}\n\nColumnVector\noctave_value::column_vector_value (bool force_string_conv,\n                                   bool frc_vec_conv) const\n{\n  return ColumnVector (vector_value (force_string_conv,\n                                     frc_vec_conv));\n}\n\nComplexColumnVector\noctave_value::complex_column_vector_value (bool force_string_conv,\n                                           bool frc_vec_conv) const\n{\n  return ComplexColumnVector (complex_vector_value (force_string_conv,\n                                                    frc_vec_conv));\n}\n\nRowVector\noctave_value::row_vector_value (bool force_string_conv,\n                                bool frc_vec_conv) const\n{\n  return RowVector (vector_value (force_string_conv,\n                                  frc_vec_conv));\n}\n\nComplexRowVector\noctave_value::complex_row_vector_value (bool force_string_conv,\n                                        bool frc_vec_conv) const\n{\n  return ComplexRowVector (complex_vector_value (force_string_conv,\n                                                 frc_vec_conv));\n}\n\nArray<double>\noctave_value::vector_value (bool force_string_conv,\n                            bool force_vector_conversion) const\n{\n  Array<double> retval = array_value (force_string_conv);\n\n  return retval.reshape (make_vector_dims (retval.dims (),\n                                           force_vector_conversion,\n                                           type_name (), \"real vector\"));\n}\n\ntemplate <typename T>\nstatic Array<int>\nconvert_to_int_array (const Array<octave_int<T>>& A)\n{\n  Array<int> retval (A.dims ());\n  octave_idx_type n = A.numel ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    retval.xelem (i) = octave_int<int> (A.xelem (i));\n\n  return retval;\n}\n\nArray<int>\noctave_value::int_vector_value (bool require_int, bool force_string_conv,\n                                bool force_vector_conversion) const\n{\n  Array<int> retval;\n\n  if (isinteger ())\n    {\n      if (is_int32_type ())\n        retval = convert_to_int_array (int32_array_value ());\n      else if (is_int64_type ())\n        retval = convert_to_int_array (int64_array_value ());\n      else if (is_int16_type ())\n        retval = convert_to_int_array (int16_array_value ());\n      else if (is_int8_type ())\n        retval = convert_to_int_array (int8_array_value ());\n      else if (is_uint32_type ())\n        retval = convert_to_int_array (uint32_array_value ());\n      else if (is_uint64_type ())\n        retval = convert_to_int_array (uint64_array_value ());\n      else if (is_uint16_type ())\n        retval = convert_to_int_array (uint16_array_value ());\n      else if (is_uint8_type ())\n        retval = convert_to_int_array (uint8_array_value ());\n      else\n        retval = array_value (force_string_conv);\n    }\n  else\n    {\n      const NDArray a = array_value (force_string_conv);\n\n      if (require_int)\n        {\n          retval.resize (a.dims ());\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              double ai = a.elem (i);\n              int v = static_cast<int> (ai);\n              if (ai == v)\n                retval.xelem (i) = v;\n              else\n                {\n                  error_with_cfn (\"conversion of %g to int value failed\", ai);\n                  break;\n                }\n            }\n        }\n      else\n        retval = Array<int> (a);\n    }\n\n  return retval.reshape (make_vector_dims (retval.dims (),\n                                           force_vector_conversion,\n                                           type_name (), \"integer vector\"));\n}\n\ntemplate <typename T>\nstatic Array<octave_idx_type>\nconvert_to_octave_idx_type_array (const Array<octave_int<T>>& A)\n{\n  Array<octave_idx_type> retval (A.dims ());\n  octave_idx_type n = A.numel ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    retval.xelem (i) = octave_int<octave_idx_type> (A.xelem (i));\n\n  return retval;\n}\n\nArray<octave_idx_type>\noctave_value::octave_idx_type_vector_value (bool require_int,\n                                            bool force_string_conv,\n                                            bool force_vector_conversion) const\n{\n  Array<octave_idx_type> retval;\n\n  if (isinteger ())\n    {\n      if (is_int32_type ())\n        retval = convert_to_octave_idx_type_array (int32_array_value ());\n      else if (is_int64_type ())\n        retval = convert_to_octave_idx_type_array (int64_array_value ());\n      else if (is_int16_type ())\n        retval = convert_to_octave_idx_type_array (int16_array_value ());\n      else if (is_int8_type ())\n        retval = convert_to_octave_idx_type_array (int8_array_value ());\n      else if (is_uint32_type ())\n        retval = convert_to_octave_idx_type_array (uint32_array_value ());\n      else if (is_uint64_type ())\n        retval = convert_to_octave_idx_type_array (uint64_array_value ());\n      else if (is_uint16_type ())\n        retval = convert_to_octave_idx_type_array (uint16_array_value ());\n      else if (is_uint8_type ())\n        retval = convert_to_octave_idx_type_array (uint8_array_value ());\n      else\n        retval = array_value (force_string_conv);\n    }\n  else\n    {\n      const NDArray a = array_value (force_string_conv);\n\n      if (require_int)\n        {\n          retval.resize (a.dims ());\n          for (octave_idx_type i = 0; i < a.numel (); i++)\n            {\n              double ai = a.elem (i);\n              octave_idx_type v = static_cast<octave_idx_type> (ai);\n              if (ai == v)\n                retval.xelem (i) = v;\n              else\n                {\n                  error_with_cfn (\"conversion of %g to octave_idx_type value failed\", ai);\n                  break;\n                }\n            }\n        }\n      else\n        retval = Array<octave_idx_type> (a);\n    }\n\n  return retval.reshape (make_vector_dims (retval.dims (),\n                                           force_vector_conversion,\n                                           type_name (), \"integer vector\"));\n}\n\nArray<Complex>\noctave_value::complex_vector_value (bool force_string_conv,\n                                    bool force_vector_conversion) const\n{\n  Array<Complex> retval = complex_array_value (force_string_conv);\n\n  return retval.reshape (make_vector_dims (retval.dims (),\n                                           force_vector_conversion,\n                                           type_name (), \"complex vector\"));\n}\n\nFloatColumnVector\noctave_value::float_column_vector_value (bool force_string_conv,\n                                         bool frc_vec_conv) const\n{\n  return FloatColumnVector (float_vector_value (force_string_conv,\n                                                frc_vec_conv));\n}\n\nFloatComplexColumnVector\noctave_value::float_complex_column_vector_value (bool force_string_conv,\n                                                 bool frc_vec_conv) const\n{\n  return\n    FloatComplexColumnVector (float_complex_vector_value (force_string_conv,\n                                                          frc_vec_conv));\n}\n\nFloatRowVector\noctave_value::float_row_vector_value (bool force_string_conv,\n                                      bool frc_vec_conv) const\n{\n  return FloatRowVector (float_vector_value (force_string_conv,\n                                             frc_vec_conv));\n}\n\nFloatComplexRowVector\noctave_value::float_complex_row_vector_value (bool force_string_conv,\n                                              bool frc_vec_conv) const\n{\n  return FloatComplexRowVector (float_complex_vector_value (force_string_conv,\n                                                           frc_vec_conv));\n}\n\nArray<float>\noctave_value::float_vector_value (bool force_string_conv,\n                                  bool force_vector_conversion) const\n{\n  Array<float> retval = float_array_value (force_string_conv);\n\n  return retval.reshape (make_vector_dims (retval.dims (),\n                                           force_vector_conversion,\n                                           type_name (), \"real vector\"));\n}\n\nArray<FloatComplex>\noctave_value::float_complex_vector_value (bool force_string_conv,\n                                          bool force_vector_conversion) const\n{\n  Array<FloatComplex> retval = float_complex_array_value (force_string_conv);\n\n  return retval.reshape (make_vector_dims (retval.dims (),\n                                           force_vector_conversion,\n                                           type_name (), \"complex vector\"));\n}\n\n// NAME can't always be \"x ## FCN\" because some of the original\n// value extraction functions perform implicit type conversions that we\n// wish to avoid for these functions.\n\n#define XVALUE_EXTRACTOR(TYPE, NAME, FCN)               \\\n  TYPE                                                  \\\n  octave_value::NAME (const char *fmt, ...) const       \\\n  {                                                     \\\n    TYPE retval;                                        \\\n                                                        \\\n    try                                                 \\\n      {                                                 \\\n        retval = FCN ();                                \\\n      }                                                 \\\n    catch (octave::execution_exception& ee)             \\\n      {                                                 \\\n        if (fmt)                                        \\\n          {                                             \\\n            va_list args;                               \\\n            va_start (args, fmt);                       \\\n            verror (ee, fmt, args);                     \\\n            va_end (args);                              \\\n          }                                             \\\n                                                        \\\n        throw ee;                                       \\\n      }                                                 \\\n                                                        \\\n    return retval;                                      \\\n  }\n\nXVALUE_EXTRACTOR (short int, xshort_value, short_value)\n\nXVALUE_EXTRACTOR (unsigned short int, xushort_value, ushort_value)\n\nXVALUE_EXTRACTOR (int, xint_value, int_value)\n\nXVALUE_EXTRACTOR (unsigned int, xuint_value, uint_value)\n\nXVALUE_EXTRACTOR (int, xnint_value, nint_value)\n\nXVALUE_EXTRACTOR (long int, xlong_value, long_value)\n\nXVALUE_EXTRACTOR (unsigned long int, xulong_value, ulong_value)\n\nXVALUE_EXTRACTOR (int64_t, xint64_value, int64_value)\n\nXVALUE_EXTRACTOR (uint64_t, xuint64_value, uint64_value)\n\nXVALUE_EXTRACTOR (octave_idx_type, xidx_type_value, idx_type_value)\n\nXVALUE_EXTRACTOR (double, xdouble_value, double_value)\nXVALUE_EXTRACTOR (float, xfloat_value, float_value)\n\nXVALUE_EXTRACTOR (double, xscalar_value, scalar_value)\nXVALUE_EXTRACTOR (float, xfloat_scalar_value, float_scalar_value)\n\nXVALUE_EXTRACTOR (Matrix, xmatrix_value, matrix_value)\nXVALUE_EXTRACTOR (FloatMatrix, xfloat_matrix_value, float_matrix_value)\n\nXVALUE_EXTRACTOR (NDArray, xarray_value, array_value)\nXVALUE_EXTRACTOR (FloatNDArray, xfloat_array_value, float_array_value)\n\nXVALUE_EXTRACTOR (Complex, xcomplex_value, complex_value)\nXVALUE_EXTRACTOR (FloatComplex, xfloat_complex_value, float_complex_value)\n\nXVALUE_EXTRACTOR (ComplexMatrix, xcomplex_matrix_value, complex_matrix_value)\nXVALUE_EXTRACTOR (FloatComplexMatrix, xfloat_complex_matrix_value, float_complex_matrix_value)\n\nXVALUE_EXTRACTOR (ComplexNDArray, xcomplex_array_value, complex_array_value)\nXVALUE_EXTRACTOR (FloatComplexNDArray, xfloat_complex_array_value, float_complex_array_value)\n\nXVALUE_EXTRACTOR (bool, xbool_value, bool_value)\nXVALUE_EXTRACTOR (boolMatrix, xbool_matrix_value, bool_matrix_value)\nXVALUE_EXTRACTOR (boolNDArray, xbool_array_value, bool_array_value)\n\nXVALUE_EXTRACTOR (charMatrix, xchar_matrix_value, char_matrix_value)\nXVALUE_EXTRACTOR (charNDArray, xchar_array_value, char_array_value)\n\nXVALUE_EXTRACTOR (SparseMatrix, xsparse_matrix_value, sparse_matrix_value)\nXVALUE_EXTRACTOR (SparseComplexMatrix, xsparse_complex_matrix_value, sparse_complex_matrix_value)\nXVALUE_EXTRACTOR (SparseBoolMatrix, xsparse_bool_matrix_value, sparse_bool_matrix_value)\n\nXVALUE_EXTRACTOR (DiagMatrix, xdiag_matrix_value, diag_matrix_value)\nXVALUE_EXTRACTOR (FloatDiagMatrix, xfloat_diag_matrix_value, float_diag_matrix_value)\nXVALUE_EXTRACTOR (ComplexDiagMatrix, xcomplex_diag_matrix_value, complex_diag_matrix_value)\nXVALUE_EXTRACTOR (FloatComplexDiagMatrix, xfloat_complex_diag_matrix_value, float_complex_diag_matrix_value)\n\nXVALUE_EXTRACTOR (PermMatrix, xperm_matrix_value, perm_matrix_value)\n\nXVALUE_EXTRACTOR (octave_int8, xint8_scalar_value, int8_scalar_value)\nXVALUE_EXTRACTOR (octave_int16, xint16_scalar_value, int16_scalar_value)\nXVALUE_EXTRACTOR (octave_int32, xint32_scalar_value, int32_scalar_value)\nXVALUE_EXTRACTOR (octave_int64, xint64_scalar_value, int64_scalar_value)\n\nXVALUE_EXTRACTOR (octave_uint8, xuint8_scalar_value, uint8_scalar_value)\nXVALUE_EXTRACTOR (octave_uint16, xuint16_scalar_value, uint16_scalar_value)\nXVALUE_EXTRACTOR (octave_uint32, xuint32_scalar_value, uint32_scalar_value)\nXVALUE_EXTRACTOR (octave_uint64, xuint64_scalar_value, uint64_scalar_value)\n\nXVALUE_EXTRACTOR (int8NDArray, xint8_array_value, int8_array_value)\nXVALUE_EXTRACTOR (int16NDArray, xint16_array_value, int16_array_value)\nXVALUE_EXTRACTOR (int32NDArray, xint32_array_value, int32_array_value)\nXVALUE_EXTRACTOR (int64NDArray, xint64_array_value, int64_array_value)\n\nXVALUE_EXTRACTOR (uint8NDArray, xuint8_array_value, uint8_array_value)\nXVALUE_EXTRACTOR (uint16NDArray, xuint16_array_value, uint16_array_value)\nXVALUE_EXTRACTOR (uint32NDArray, xuint32_array_value, uint32_array_value)\nXVALUE_EXTRACTOR (uint64NDArray, xuint64_array_value, uint64_array_value)\n\nXVALUE_EXTRACTOR (std::string, xstring_value, m_rep->xstring_value)\nXVALUE_EXTRACTOR (string_vector, xstring_vector_value, string_vector_value)\n\nXVALUE_EXTRACTOR (Cell, xcell_value, cell_value)\nXVALUE_EXTRACTOR (Array<std::string>, xcellstr_value, cellstr_value)\n\nXVALUE_EXTRACTOR (octave::range<double>, xrange_value, range_value)\n\n// For now, enable only ov_range<double>.\n\nXVALUE_EXTRACTOR (octave_map, xmap_value, map_value)\nXVALUE_EXTRACTOR (octave_scalar_map, xscalar_map_value, scalar_map_value)\n\nXVALUE_EXTRACTOR (ColumnVector, xcolumn_vector_value, column_vector_value)\nXVALUE_EXTRACTOR (ComplexColumnVector, xcomplex_column_vector_value, complex_column_vector_value)\n\nXVALUE_EXTRACTOR (RowVector, xrow_vector_value, row_vector_value)\nXVALUE_EXTRACTOR (ComplexRowVector, xcomplex_row_vector_value, complex_row_vector_value)\n\nXVALUE_EXTRACTOR (FloatColumnVector, xfloat_column_vector_value, float_column_vector_value)\nXVALUE_EXTRACTOR (FloatComplexColumnVector, xfloat_complex_column_vector_value, float_complex_column_vector_value)\n\nXVALUE_EXTRACTOR (FloatRowVector, xfloat_row_vector_value, float_row_vector_value)\nXVALUE_EXTRACTOR (FloatComplexRowVector, xfloat_complex_row_vector_value, float_complex_row_vector_value)\n\nXVALUE_EXTRACTOR (Array<int>, xint_vector_value, int_vector_value)\nXVALUE_EXTRACTOR (Array<octave_idx_type>, xoctave_idx_type_vector_value, octave_idx_type_vector_value)\n\nXVALUE_EXTRACTOR (Array<double>, xvector_value, vector_value)\nXVALUE_EXTRACTOR (Array<Complex>, xcomplex_vector_value, complex_vector_value)\n\nXVALUE_EXTRACTOR (Array<float>, xfloat_vector_value, float_vector_value)\nXVALUE_EXTRACTOR (Array<FloatComplex>, xfloat_complex_vector_value, float_complex_vector_value)\n\nXVALUE_EXTRACTOR (octave_function *, xfunction_value, function_value)\nXVALUE_EXTRACTOR (octave_user_function *, xuser_function_value, user_function_value)\nXVALUE_EXTRACTOR (octave_user_script *, xuser_script_value, user_script_value)\nXVALUE_EXTRACTOR (octave_user_code *, xuser_code_value, user_code_value)\nXVALUE_EXTRACTOR (octave_fcn_handle *, xfcn_handle_value, fcn_handle_value)\n\nXVALUE_EXTRACTOR (octave_value_list, xlist_value, list_value)\n\n// Make some stricter versions of XVALUE_EXTRACTOR,\n// especially for parsing integer arguments that cannot be floating point.\n// See bug #65538.\n\nXVALUE_EXTRACTOR (int, strict_int_value, strict_int_value)\n\nXVALUE_EXTRACTOR (bool, strict_bool_value, strict_bool_value)\n\nXVALUE_EXTRACTOR (octave_idx_type, strict_idx_type_value, strict_idx_type_value)\n\n#undef XVALUE_EXTRACTOR\n\n\noctave_value\noctave_value::storable_value () const\n{\n  octave_value retval = *this;\n  if (isnull ())\n    retval = octave_value (m_rep->empty_clone ());\n  else if (is_magic_int ())\n    retval = octave_value (m_rep->double_value ());\n  else if (is_range () && ! m_rep->is_storable ())\n    error (\"range with infinite number of elements cannot be stored\");\n  else\n    retval.maybe_economize ();\n\n  return retval;\n}\n\nvoid\noctave_value::make_storable_value ()\n{\n  if (isnull ())\n    {\n      octave_base_value *rc = m_rep->empty_clone ();\n      if (--m_rep->m_count == 0)\n        delete m_rep;\n      m_rep = rc;\n    }\n  else if (is_magic_int ())\n    {\n      octave_base_value *rc = new octave_scalar (m_rep->double_value ());\n      if (--m_rep->m_count == 0)\n        delete m_rep;\n      m_rep = rc;\n    }\n  else if (is_range () && ! m_rep->is_storable ())\n    error (\"range with infinite number of elements cannot be stored\");\n  else\n    maybe_economize ();\n}\n\nfloat_display_format\noctave_value::get_edit_display_format () const\n{\n  return m_rep->get_edit_display_format ();\n}\n\nint\noctave_value::write (octave::stream& os, int block_size,\n                     oct_data_conv::data_type output_type, int skip,\n                     octave::mach_info::float_format flt_fmt) const\n{\n  return m_rep->write (os, block_size, output_type, skip, flt_fmt);\n}\n\nvoid\noctave_value::print_info (std::ostream& os, const std::string& prefix) const\n{\n  os << prefix << \"type_name: \" << type_name () << \"\\n\"\n     << prefix << \"m_count:     \" << get_count () << \"\\n\"\n     << prefix << \"m_rep info:  \";\n\n  m_rep->print_info (os, prefix + ' ');\n}\n\nbool\noctave_value::load_ascii (std::istream& is)\n{\n  bool status = m_rep->load_ascii (is);\n\n  // Force conversion of legacy objects.\n  if (is_legacy_object ())\n    maybe_mutate ();\n\n  return status;\n}\nbool\noctave_value::load_binary (std::istream& is, bool swap,\n                           octave::mach_info::float_format fmt)\n{\n  bool status = m_rep->load_binary (is, swap, fmt);\n\n  // Force conversion of legacy objects.\n  if (is_legacy_object ())\n    maybe_mutate ();\n\n  return status;\n}\n\nbool\noctave_value::load_hdf5 (octave_hdf5_id loc_id, const char *name)\n{\n  bool status = m_rep->load_hdf5 (loc_id, name);\n\n  // Force conversion of legacy objects.\n  if (is_legacy_object ())\n    maybe_mutate ();\n\n  return status;\n}\n\nconst void *\noctave_value::mex_get_data (mxClassID class_id, mxComplexity complexity) const\n{\n  // If class_id is set to mxUNKNOWN_CLASS, return data for any type.\n  // Otherwise, require that REP matches the requested type and\n  // complexity.\n\n  if (class_id != mxUNKNOWN_CLASS)\n    {\n      bool type_ok = false;\n\n      switch (class_id)\n        {\n        case mxDOUBLE_CLASS:\n          type_ok = is_double_type ();\n          break;\n\n        case mxSINGLE_CLASS:\n          type_ok = is_single_type ();\n          break;\n\n        case mxINT8_CLASS:\n          type_ok = is_int8_type ();\n          break;\n\n        case mxINT16_CLASS:\n          type_ok = is_int16_type ();\n          break;\n\n        case mxINT32_CLASS:\n          type_ok = is_int32_type ();\n          break;\n\n        case mxINT64_CLASS:\n          type_ok = is_int64_type ();\n          break;\n\n        case mxUINT8_CLASS:\n          type_ok = is_uint8_type ();\n          break;\n\n        case mxUINT16_CLASS:\n          type_ok = is_uint16_type ();\n          break;\n\n        case mxUINT32_CLASS:\n          type_ok = is_uint32_type ();\n          break;\n\n        case mxUINT64_CLASS:\n          type_ok = is_uint64_type ();\n          break;\n\n        default:\n          // We only expect to see numeric types explicitly requested.\n          error (\"mex_get_data: unexpected type requested\");\n        }\n\n      if (! type_ok)\n        error (\"mex_get_data: type mismatch\");\n\n      if (complexity == mxCOMPLEX && ! iscomplex ())\n        error (\"mex_get_data: objectis not complex as requested\");\n    }\n\n  return m_rep->mex_get_data ();\n}\n\nOCTAVE_NORETURN static void\nerr_unary_op_conversion_failed (const std::string& op,\n                                const std::string& tn)\n{\n  error (\"operator %s: type conversion for '%s' failed\",\n         op.c_str (), tn.c_str ());\n}\n\nOCTAVE_NORETURN static void\nerr_unary_op (const std::string& on, const std::string& tn)\n{\n  error (\"unary operator '%s' not implemented for '%s' operands\",\n         on.c_str (), tn.c_str ());\n}\n\noctave_value&\noctave_value::non_const_unary_op (unary_op op)\n{\n  if (op == op_incr || op == op_decr)\n    {\n      // We want the error just here, because in the other branch this should\n      // not happen, and if it did anyway (internal error), the message would\n      // be confusing.\n      if (is_undefined ())\n        {\n          std::string op_str = unary_op_as_string (op);\n          error (\"in x%s or %sx, x must be defined first\",\n                 op_str.c_str (), op_str.c_str ());\n          return *this;\n        }\n\n      // Genuine.\n      int t = type_id ();\n\n      octave::type_info& ti = octave::__get_type_info__ ();\n\n      octave::type_info::non_const_unary_op_fcn f\n        = ti.lookup_non_const_unary_op (op, t);\n\n      if (f)\n        {\n          make_unique ();\n\n          f (*m_rep);\n        }\n      else\n        {\n          octave_base_value::type_conv_fcn cf = numeric_conversion_function ();\n\n          if (! cf)\n            err_unary_op (octave_value::unary_op_as_string (op), type_name ());\n\n          octave_base_value *tmp = cf (*m_rep);\n\n          if (! tmp)\n            err_unary_op_conversion_failed\n              (octave_value::unary_op_as_string (op), type_name ());\n\n          octave_base_value *old_rep = m_rep;\n          m_rep = tmp;\n\n          t = type_id ();\n\n          f = ti.lookup_non_const_unary_op (op, t);\n\n          if (f)\n            {\n              f (*m_rep);\n\n              if (old_rep && --old_rep->m_count == 0)\n                delete old_rep;\n            }\n          else\n            {\n              if (old_rep)\n                {\n                  if (--m_rep->m_count == 0)\n                    delete m_rep;\n\n                  m_rep = old_rep;\n                }\n\n              err_unary_op (octave_value::unary_op_as_string (op),\n                            type_name ());\n            }\n        }\n    }\n  else\n    {\n      // Non-genuine.\n      int t = type_id ();\n\n      octave::type_info::non_const_unary_op_fcn f = nullptr;\n\n      // Only attempt to operate in-place if this variable is unshared.\n      if (m_rep->m_count == 1)\n        {\n          octave::type_info& ti = octave::__get_type_info__ ();\n\n          f = ti.lookup_non_const_unary_op (op, t);\n        }\n\n      if (f)\n        f (*m_rep);\n      else\n        *this = octave::unary_op (op, *this);\n    }\n\n  return *this;\n}\n\noctave_value&\noctave_value::non_const_unary_op (unary_op op, const std::string& type,\n                                  const std::list<octave_value_list>& idx)\n{\n  if (idx.empty ())\n    non_const_unary_op (op);\n  else\n    {\n      // FIXME: only do the following stuff if we can't find a\n      // specific function to call to handle the op= operation for the\n      // types we have.\n\n      assign_op assop = unary_op_to_assign_op (op);\n\n      assign (assop, type, idx, 1.0);\n    }\n\n  return *this;\n}\n\noctave_value::assign_op\noctave_value::unary_op_to_assign_op (unary_op op)\n{\n  switch (op)\n    {\n    case op_incr:\n      return op_add_eq;\n\n    case op_decr:\n      return op_sub_eq;\n\n    default:\n      {\n        std::string on = unary_op_as_string (op);\n        error (\"operator %s: no assign operator found\", on.c_str ());\n      }\n    }\n}\n\noctave_value::binary_op\noctave_value::op_eq_to_binary_op (assign_op op)\n{\n  switch (op)\n    {\n    case op_add_eq:\n      return op_add;\n\n    case op_sub_eq:\n      return op_sub;\n\n    case op_mul_eq:\n      return op_mul;\n\n    case op_div_eq:\n      return op_div;\n\n    case op_ldiv_eq:\n      return op_ldiv;\n\n    case op_pow_eq:\n      return op_pow;\n\n    case op_el_mul_eq:\n      return op_el_mul;\n\n    case op_el_div_eq:\n      return op_el_div;\n\n    case op_el_ldiv_eq:\n      return op_el_ldiv;\n\n    case op_el_pow_eq:\n      return op_el_pow;\n\n    case op_el_and_eq:\n      return op_el_and;\n\n    case op_el_or_eq:\n      return op_el_or;\n\n    default:\n      {\n        std::string on = assign_op_as_string (op);\n        error (\"operator %s: no binary operator found\", on.c_str ());\n      }\n    }\n}\n\noctave_value\noctave_value::empty_conv (const std::string& type, const octave_value& rhs)\n{\n  if (type.length () > 0)\n    {\n      switch (type[0])\n        {\n        case '(':\n          if (type.length () > 1 && type[1] == '.')\n            return octave_map ();\n          else\n            return octave_value (rhs.empty_clone ());\n\n        case '{':\n          return Cell ();\n\n        case '.':\n          return octave_scalar_map ();\n\n        default:\n          error (\"unexpected: index not '(', '{', or '.' in octave_value::empty_conv - please report this bug\");\n        }\n    }\n  else\n    return octave_value (rhs.empty_clone ());\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_NORETURN static void\nerr_binary_op (const std::string& on, const std::string& tn1,\n               const std::string& tn2)\n{\n  error (\"binary operator '%s' not implemented for '%s' by '%s' operations\",\n         on.c_str (), tn1.c_str (), tn2.c_str ());\n}\n\nOCTAVE_NORETURN static void\nerr_binary_op_conv (const std::string& on)\n{\n  error (\"type conversion failed for binary operator '%s'\", on.c_str ());\n}\n\noctave_value\nbinary_op (type_info& ti, octave_value::binary_op op,\n           const octave_value& v1, const octave_value& v2)\n{\n  octave_value retval;\n\n  int t1 = v1.type_id ();\n  int t2 = v2.type_id ();\n\n  if (t1 == octave_class::static_type_id ()\n      || t2 == octave_class::static_type_id ()\n      || t1 == octave_classdef::static_type_id ()\n      || t2 == octave_classdef::static_type_id ())\n    {\n      type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op);\n\n      if (! f)\n        err_binary_op (octave_value::binary_op_as_string (op),\n                       v1.class_name (), v2.class_name ());\n\n      retval = f (v1, v2);\n    }\n  else\n    {\n      // FIXME: we need to handle overloading operators for built-in\n      // classes (double, char, int8, etc.)\n\n      type_info::binary_op_fcn f\n        = ti.lookup_binary_op (op, t1, t2);\n\n      if (f)\n        retval = f (v1.get_rep (), v2.get_rep ());\n      else\n        {\n          octave_value tv1;\n          octave_base_value::type_conv_info cf1\n            = v1.numeric_conversion_function ();\n\n          octave_value tv2;\n          octave_base_value::type_conv_info cf2\n            = v2.numeric_conversion_function ();\n\n          // Try biased (one-sided) conversions first.\n          if (cf2.type_id () >= 0\n              && ti.lookup_binary_op (op, t1, cf2.type_id ()))\n            cf1 = nullptr;\n          else if (cf1.type_id () >= 0\n                   && ti.lookup_binary_op (op, cf1.type_id (), t2))\n            cf2 = nullptr;\n\n          if (cf1)\n            {\n              octave_base_value *tmp = cf1 (v1.get_rep ());\n\n              if (! tmp)\n                err_binary_op_conv (octave_value::binary_op_as_string (op));\n\n              tv1 = octave_value (tmp);\n              t1 = tv1.type_id ();\n            }\n          else\n            tv1 = v1;\n\n          if (cf2)\n            {\n              octave_base_value *tmp = cf2 (v2.get_rep ());\n\n              if (! tmp)\n                err_binary_op_conv (octave_value::binary_op_as_string (op));\n\n              tv2 = octave_value (tmp);\n              t2 = tv2.type_id ();\n            }\n          else\n            tv2 = v2;\n\n          if (cf1 || cf2)\n            {\n              retval = binary_op (op, tv1, tv2);\n            }\n          else\n            {\n              //demote double -> single and try again\n              cf1 = tv1.numeric_demotion_function ();\n\n              cf2 = tv2.numeric_demotion_function ();\n\n              // Try biased (one-sided) conversions first.\n              if (cf2.type_id () >= 0\n                  && ti.lookup_binary_op (op, t1, cf2.type_id ()))\n                cf1 = nullptr;\n              else if (cf1.type_id () >= 0\n                       && ti.lookup_binary_op (op, cf1.type_id (), t2))\n                cf2 = nullptr;\n\n              if (cf1)\n                {\n                  octave_base_value *tmp = cf1 (tv1.get_rep ());\n\n                  if (! tmp)\n                    err_binary_op_conv (octave_value::binary_op_as_string (op));\n\n                  tv1 = octave_value (tmp);\n                  t1 = tv1.type_id ();\n                }\n\n              if (cf2)\n                {\n                  octave_base_value *tmp = cf2 (tv2.get_rep ());\n\n                  if (! tmp)\n                    err_binary_op_conv (octave_value::binary_op_as_string (op));\n\n                  tv2 = octave_value (tmp);\n                  t2 = tv2.type_id ();\n                }\n\n              if (! cf1 && ! cf2)\n                err_binary_op (octave_value::binary_op_as_string (op),\n                               v1.type_name (), v2.type_name ());\n\n              f = ti.lookup_binary_op (op, t1, t2);\n\n              if (! f)\n                err_binary_op (octave_value::binary_op_as_string (op),\n                               v1.type_name (), v2.type_name ());\n\n              retval = f (tv1.get_rep (), tv2.get_rep ());\n            }\n        }\n    }\n\n  return retval;\n}\n\noctave_value\nbinary_op (octave_value::binary_op op, const octave_value& v1,\n           const octave_value& v2)\n{\n  type_info& ti = __get_type_info__ ();\n\n  return binary_op (ti, op, v1, v2);\n}\n\nstatic octave_value\ndecompose_binary_op (type_info& ti, octave_value::compound_binary_op op,\n                     const octave_value& v1, const octave_value& v2)\n{\n  switch (op)\n    {\n    case octave_value::op_trans_mul:\n      return binary_op (octave_value::op_mul,\n                        unary_op (octave_value::op_transpose, v1), v2);\n\n    case octave_value::op_mul_trans:\n      return binary_op (ti, octave_value::op_mul,\n                        v1, unary_op (octave_value::op_transpose, v2));\n\n    case octave_value::op_herm_mul:\n      return binary_op (ti, octave_value::op_mul,\n                        unary_op (octave_value::op_hermitian, v1), v2);\n\n    case octave_value::op_mul_herm:\n      return binary_op (ti, octave_value::op_mul,\n                        v1, unary_op (octave_value::op_hermitian, v2));\n\n    case octave_value::op_trans_ldiv:\n      return binary_op (ti, octave_value::op_ldiv,\n                        unary_op (octave_value::op_transpose, v1), v2);\n\n    case octave_value::op_herm_ldiv:\n      return binary_op (ti, octave_value::op_ldiv,\n                        unary_op (octave_value::op_hermitian, v1), v2);\n\n    case octave_value::op_el_not_and:\n      return binary_op (ti, octave_value::op_el_and,\n                        unary_op (octave_value::op_not, v1), v2);\n\n    case octave_value::op_el_not_or:\n      return binary_op (ti, octave_value::op_el_or,\n                        unary_op (octave_value::op_not, v1), v2);\n\n    case octave_value::op_el_and_not:\n      return binary_op (ti, octave_value::op_el_and,\n                        v1, unary_op (octave_value::op_not, v2));\n\n    case octave_value::op_el_or_not:\n      return binary_op (ti, octave_value::op_el_or,\n                        v1, unary_op (octave_value::op_not, v2));\n\n    default:\n      error (\"invalid compound operator\");\n    }\n}\n\noctave_value\nbinary_op (type_info& ti, octave_value::compound_binary_op op,\n           const octave_value& v1, const octave_value& v2)\n{\n  octave_value retval;\n\n  int t1 = v1.type_id ();\n  int t2 = v2.type_id ();\n\n  if (t1 == octave_class::static_type_id ()\n      || t2 == octave_class::static_type_id ()\n      || t1 == octave_classdef::static_type_id ()\n      || t2 == octave_classdef::static_type_id ())\n    {\n      type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op);\n\n      if (f)\n        retval = f (v1, v2);\n      else\n        retval = decompose_binary_op (ti, op, v1, v2);\n    }\n  else\n    {\n      type_info::binary_op_fcn f = ti.lookup_binary_op (op, t1, t2);\n\n      if (f)\n        retval = f (v1.get_rep (), v2.get_rep ());\n      else\n        retval = decompose_binary_op (ti, op, v1, v2);\n    }\n\n  return retval;\n}\n\noctave_value\nbinary_op (octave_value::compound_binary_op op,\n           const octave_value& v1, const octave_value& v2)\n{\n  type_info& ti = __get_type_info__ ();\n\n  return binary_op (ti, op, v1, v2);\n}\n\nOCTAVE_NORETURN static void\nerr_cat_op (const std::string& tn1, const std::string& tn2)\n{\n  error (\"concatenation operator not implemented for '%s' by '%s' operations\",\n         tn1.c_str (), tn2.c_str ());\n}\n\nOCTAVE_NORETURN static void\nerr_cat_op_conv ()\n{\n  error (\"type conversion failed for concatenation operator\");\n}\n\noctave_value\ncat_op (type_info& ti, const octave_value& v1,\n        const octave_value& v2, const Array<octave_idx_type>& ra_idx)\n{\n  octave_value retval;\n\n  // Can't rapid return for concatenation with an empty object here as\n  // something like cat(1,[],single([]) must return the correct type.\n\n  int t1 = v1.type_id ();\n  int t2 = v2.type_id ();\n\n  type_info::cat_op_fcn f = ti.lookup_cat_op (t1, t2);\n\n  if (f)\n    retval = f (v1.get_rep (), v2.get_rep (), ra_idx);\n  else\n    {\n      octave_value tv1;\n      octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function ();\n\n      octave_value tv2;\n      octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function ();\n\n      // Try biased (one-sided) conversions first.\n      if (cf2.type_id () >= 0 && ti.lookup_cat_op (t1, cf2.type_id ()))\n        cf1 = nullptr;\n      else if (cf1.type_id () >= 0 && ti.lookup_cat_op (cf1.type_id (), t2))\n        cf2 = nullptr;\n\n      if (cf1)\n        {\n          octave_base_value *tmp = cf1 (v1.get_rep ());\n\n          if (! tmp)\n            err_cat_op_conv ();\n\n          tv1 = octave_value (tmp);\n          t1 = tv1.type_id ();\n        }\n      else\n        tv1 = v1;\n\n      if (cf2)\n        {\n          octave_base_value *tmp = cf2 (v2.get_rep ());\n\n          if (! tmp)\n            err_cat_op_conv ();\n\n          tv2 = octave_value (tmp);\n          t2 = tv2.type_id ();\n        }\n      else\n        tv2 = v2;\n\n      if (! cf1 && ! cf2)\n        err_cat_op (v1.type_name (), v2.type_name ());\n\n      retval = cat_op (ti, tv1, tv2, ra_idx);\n    }\n\n  return retval;\n}\n\noctave_value\ncat_op (const octave_value& v1, const octave_value& v2,\n        const Array<octave_idx_type>& ra_idx)\n{\n  type_info& ti = __get_type_info__ ();\n\n  return cat_op (ti, v1, v2, ra_idx);\n}\n\n// Unless the colon operator is used with a class or classdef object,\n// then all arguments must be the same type or mixed with double\n// values.\n\nstatic builtin_type_t\nget_colon_op_type (builtin_type_t op1_type, builtin_type_t op2_type)\n{\n  if (op1_type == op2_type)\n    return op1_type;\n\n  if (op1_type == btyp_double)\n    return op2_type;\n\n  if (op2_type == btyp_double)\n    return op1_type;\n\n  return btyp_unknown;\n}\n\nstatic builtin_type_t\nget_colon_op_type (const octave_value& base, const octave_value& increment,\n                   const octave_value& limit)\n{\n  builtin_type_t typ\n    = get_colon_op_type (base.builtin_type (), increment.builtin_type ());\n\n  if (typ == btyp_unknown)\n    return typ;\n\n  return get_colon_op_type (typ, limit.builtin_type ());\n}\n\n// This check depends on the type of VAL either being the expected\n// integer type or a double value.\n\ntemplate <typename T>\nstatic void\ncheck_colon_operand (const octave_value& val, const char *op_str)\n{\n  if (! val.is_double_type ())\n    return;\n\n  double dval = val.double_value ();\n  double intpart;\n  static constexpr double out_of_range_top\n    = static_cast<double> (std::numeric_limits<typename T::val_type>::max ()) + 1.0;\n\n  if (dval >= out_of_range_top\n      || dval < std::numeric_limits<typename T::val_type>::min ()\n      || std::modf (dval, &intpart) != 0.0)\n    error (\"colon operator %s invalid (not an integer or out of range for given integer type)\", op_str);\n}\n\n// Return the difference between two unsigned integers as an unsigned\n// integer of the same type.\n\ntemplate <typename UT,\n          typename std::enable_if<(std::is_integral<UT>::value\n                                   && std::is_unsigned<UT>::value),\n                                  bool>::type = true>\nUT\ninteger_difference (UT a, UT b)\n{\n  return a > b ? a - b : b - a;\n}\n\n// Return the difference between two signed integers as an unsigned\n// integer corresponding to the signed type.\n\ntemplate <typename ST,\n          typename UT = typename std::make_unsigned<ST>::type,\n          typename std::enable_if<(std::is_integral<ST>::value\n                                   && std::is_signed<ST>::value),\n                                  bool>::type = true>\nUT\ninteger_difference (ST a, ST b)\n{\n  // Map to unsigned.\n  // Idea from https://stackoverflow.com/questions/10589559\n\n  static const UT offset = UT (0) - static_cast<UT> (std::numeric_limits<ST>::min ());\n\n  UT au = static_cast<UT> (a) + offset;\n  UT bu = static_cast<UT> (b) + offset;\n\n  return integer_difference (au, bu);\n}\n\n// Number of elements in an integer range taking care to avoid\n// overflow.  Base and limit are of the same type.  If they are\n// unsigned, then increment is also of the same type.  If they are\n// signed, then the type of increment is the unsigned type\n// corresponding to T.  Assumes that the base and limit values are\n// consistent with the sign of the original increment (not an empty\n// range) so we can calculate numel with the absolute value of the\n// increment and the absolute difference between the base and limit\n// values.\n\ntemplate <typename T,\n          typename UT = typename std::make_unsigned<T>::type,\n          typename std::enable_if<std::is_integral<T>::value,\n                                  bool>::type = true>\noctave_idx_type\nrange_numel_aux (T base, UT unsigned_increment, T limit)\n{\n  // Adding one to DIFF/INCREMENT may overflow, so check whether it is\n  // out of range before adding.\n\n  UT nel_m1 = integer_difference (limit, base) / unsigned_increment;\n\n  // FIXME: fix error message.\n  if (nel_m1 > std::numeric_limits<octave_idx_type>::max () - 1)\n    error (\"too many elements for range!\");\n\n  return static_cast<octave_idx_type> (nel_m1) + 1;\n}\n\n// Convert signed range increment to unsigned.\n\ntemplate <typename ST,\n          typename UT = typename std::make_unsigned<ST>::type,\n          typename std::enable_if<(std::is_integral<ST>::value\n                                   && std::is_signed<ST>::value),\n                                  bool>::type = true>\nUT\nrange_increment (ST increment)\n{\n  return (increment < 0\n          ? UT (0) - static_cast<UT> (increment)\n          : static_cast<UT> (increment));\n}\n\n// \"Convert\" unsigned range increment to unsigned.  A no-op, but\n// needed to provide a consistent interface for other template\n// functions.\n\ntemplate <typename T,\n          typename UT = typename std::make_unsigned<T>::type,\n          typename std::enable_if<(std::is_integral<UT>::value\n                                   && std::is_unsigned<UT>::value),\n                                  bool>::type = true>\nUT\nrange_increment (UT increment)\n{\n  return increment;\n}\n\n// Convert double range increment to unsigned.  Enable by return type.\n\ntemplate <typename T,\n          typename UT = typename std::make_unsigned<T>::type>\ntypename std::enable_if<(std::is_integral<UT>::value\n                         && std::is_unsigned<UT>::value), UT>::type\nrange_increment (double increment)\n{\n  double abs_increment = std::abs (increment);\n\n  return static_cast<UT> (abs_increment);\n}\n\n// Number of elements in an integer range base:increment:limit.  Base,\n// increment, and limit are of the same signed type.\n\ntemplate <typename ST,\n          typename std::enable_if<(std::is_integral<ST>::value\n                                   && std::is_signed<ST>::value),\n                                  bool>::type = true>\noctave_idx_type\nrange_numel (ST base, ST increment, ST limit)\n{\n  typedef typename std::make_unsigned<ST>::type UT;\n\n  if (increment == 0\n      || (increment > 0 && base > limit)\n      || (increment < 0 && base < limit))\n    return 0;\n\n  UT unsigned_increment = range_increment<ST> (increment);\n\n  return range_numel_aux (base, unsigned_increment, limit);\n}\n\n// Number of elements in an integer range base:increment:limit.  Base,\n// increment, and limit are unsigned and of the same type.\n\ntemplate <typename UT,\n          typename std::enable_if<(std::is_integral<UT>::value\n                                   && std::is_unsigned<UT>::value),\n                                  bool>::type = true>\noctave_idx_type\nrange_numel (UT base, UT increment, UT limit)\n{\n  // Unsigned, INCREMENT is always >= 0.\n  if (increment == 0 || base > limit)\n    return 0;\n\n  return range_numel_aux (base, increment, limit);\n}\n\n// Number of elements in an integer range base:increment:limit.  Base\n// and limit are of the same type and increment is a double value.\n\ntemplate <typename T,\n          typename UT = typename std::make_unsigned<T>::type,\n          typename std::enable_if<std::is_integral<T>::value,\n                                  bool>::type = true>\noctave_idx_type\nrange_numel (T base, double increment, T limit)\n{\n  double intpart;\n  if (math::isnan (increment) || std::modf (increment, &intpart) != 0.0)\n    error (\"colon operator increment invalid (not an integer)\");\n\n  if (increment == 0\n      || (increment > 0 && base > limit)\n      || (increment < 0 && base < limit))\n    return 0;\n\n  static constexpr double out_of_range_top\n    = static_cast<double> (std::numeric_limits<UT>::max ()) + 1.0;\n\n  double abs_increment = std::abs (increment);\n\n  // Technically, this condition should be\n  // `abs_increment > std::numeric_limits<UT>::max ()`.\n  // But intmax('uint64') is not representable exactly as floating point\n  // number.  Instead, it \"rounds\" up by 1 to 2^64.  To account for\n  // this, use the following expression which works for all unsigned\n  // integer types.\n  if (abs_increment >= out_of_range_top)\n    return 1;\n\n  UT unsigned_increment = range_increment<T> (increment);\n\n  return range_numel_aux (base, unsigned_increment, limit);\n}\n\n// Make a range from integer values.  Increment may be integer or double.\n\ntemplate <typename T,\n          typename IT,\n          typename std::enable_if<(std::is_integral<T>::value\n                                   && std::is_arithmetic<IT>::value),\n                                  bool>::type = true>\noctave_value\nmake_int_range (T base, IT increment, T limit)\n{\n  octave_idx_type nel = range_numel (base, increment, limit);\n\n  // For now, we create arrays instead of range<T> for all types\n  // except double.\n\n  Array<octave_int<T>> result (dim_vector (1, nel));\n\n  if (nel > 0)\n    {\n      typedef typename std::make_unsigned<T>::type UT;\n\n      UT unsigned_increment = range_increment<T> (increment);\n\n      T val = base;\n      result.xelem (0) = val;\n\n      if (limit > base)\n        {\n          for (octave_idx_type i = 1; i < nel; i++)\n            {\n              val += unsigned_increment;\n              result.xelem (i) = val;\n            }\n        }\n      else\n        {\n          for (octave_idx_type i = 1; i < nel; i++)\n            {\n              val -= unsigned_increment;\n              result.xelem (i) = val;\n            }\n        }\n    }\n\n  return octave_value (result);\n}\n\n// Make a range from floating point values.\n\n// FIXME: Try again to define memory efficient range classes for\n// integer and floating point values?  Maybe with the templates\n// defined in this file we could do that in a reasonable way?\n// Regardless of that, it might be good to provide special treatment\n// of colon expressions in FOR loops so that we can eliminate the\n// \"is_for_cmd_expr / force_range\" flag from the parser and the\n// octave_value constructors for range objects.\n\n// NOTE: We define this function separately for float and double so\n// that we can avoid having to instantiate ov_range<float>.  We DO\n// instantiate range<float> but only so we can take advantage of the\n// range<T> class to generate the corresponding array of float values\n// and not have to duplicate that code here.\n\ntemplate <typename T,\n          typename std::enable_if<std::is_same<T, double>::value,\n                                  bool>::type = true>\noctave_value\nmake_float_range (T base, T increment, T limit, bool is_for_cmd_expr)\n{\n  if (math::isnan (base)\n      || math::isnan (increment)\n      || math::isnan (limit))\n    return octave_value (numeric_limits<T>::NaN ());\n\n  if (increment == 0\n      || (increment > 0 && base > limit)\n      || (increment < 0 && base < limit))\n    return octave_value (Array<T> (dim_vector (1, 0)));\n\n  // At this point, we know that the base and limit values are\n  // consistent with the sign of the increment (not an empty range).\n\n  range<T> r (base, increment, limit);\n\n  if (! is_for_cmd_expr && ! r.is_storable ())\n    error (\"range with infinite number of elements cannot be stored\");\n\n  return octave_value (r, is_for_cmd_expr);\n}\n\ntemplate <typename T,\n          typename std::enable_if<std::is_same<T, float>::value,\n                                  bool>::type = true>\noctave_value\nmake_float_range (T base, T increment, T limit, bool is_for_cmd_expr)\n{\n  if (math::isnan (base)\n      || math::isnan (increment)\n      || math::isnan (limit))\n    return octave_value (numeric_limits<T>::NaN ());\n\n  if (increment == 0\n      || (increment > 0 && base > limit)\n      || (increment < 0 && base < limit))\n    return octave_value (Array<T> (dim_vector (1, 0)));\n\n  // At this point, we know that the base and limit values are\n  // consistent with the sign of the increment (not an empty range).\n\n  range<T> r (base, increment, limit);\n\n  if (! is_for_cmd_expr && ! r.is_storable ())\n    error (\"range with infinite number of elements cannot be stored\");\n\n  return octave_value (r.array_value ());\n}\n\ntemplate <typename T,\n          typename std::enable_if<(std::is_same<T, octave_int8>::value\n                                   || std::is_same<T, octave_uint8>::value\n                                   || std::is_same<T, octave_int16>::value\n                                   || std::is_same<T, octave_uint16>::value\n                                   || std::is_same<T, octave_int32>::value\n                                   || std::is_same<T, octave_uint32>::value\n                                   || std::is_same<T, octave_int64>::value\n                                   || std::is_same<T, octave_uint64>::value),\n                                  bool>::type = true>\noctave_value\nmake_int_range (const octave_value& base, const octave_value& increment,\n                const octave_value& limit)\n{\n  if (base.isempty () || increment.isempty () || limit.isempty ())\n    return octave_value (Array<T> (dim_vector (1, 0)));\n\n  check_colon_operand<T> (base, \"lower bound\");\n  check_colon_operand<T> (limit, \"upper bound\");\n\n  typename T::val_type base_val = octave_value_extract<T> (base).value ();\n  typename T::val_type limit_val = octave_value_extract<T> (limit).value ();\n\n  if (increment.is_double_type ())\n    {\n      double increment_val = increment.double_value ();\n\n      return make_int_range (base_val, increment_val, limit_val);\n    }\n\n  check_colon_operand<T> (increment, \"increment\");\n\n  typename T::val_type increment_val\n    = octave_value_extract<T> (increment).value ();\n\n  return make_int_range (base_val, increment_val, limit_val);\n}\n\ntemplate <typename T,\n          typename std::enable_if<std::is_floating_point<T>::value,\n                                  bool>::type = true>\noctave_value\nmake_float_range (const octave_value& base, const octave_value& increment,\n                  const octave_value& limit, bool is_for_cmd_expr)\n{\n  if (base.isempty () || increment.isempty () || limit.isempty ())\n    return octave_value (Array<T> (dim_vector (1, 0)));\n\n  T base_val = octave_value_extract<T> (base);\n  T increment_val = octave_value_extract<T> (increment);\n  T limit_val = octave_value_extract<T> (limit);\n\n  return make_float_range (base_val, increment_val, limit_val,\n                           is_for_cmd_expr);\n}\n\n\noctave_value\nmake_char_range (const octave_value& base, const octave_value& increment,\n                 const octave_value& limit)\n{\n  octave_value retval;\n\n  bool dq_str = (base.is_dq_string () || increment.is_dq_string ()\n                 || limit.is_dq_string ());\n\n  char type = dq_str ? '\"' : '\\'';\n\n  if (base.isempty () || increment.isempty () || limit.isempty ())\n    retval = octave_value (\"\", type);\n  else\n    {\n      Matrix mtx_base = base.matrix_value (true);\n      Matrix mtx_increment = increment.matrix_value (true);\n      Matrix mtx_limit = limit.matrix_value (true);\n\n      range<double> tmp (mtx_base(0), mtx_increment(0), mtx_limit(0));\n\n      retval = octave_value (tmp);\n    }\n\n  return retval.convert_to_str (false, true, type);\n}\n\noctave_value\ncolon_op (const octave_value& base, const octave_value& increment_arg,\n          const octave_value& limit, bool is_for_cmd_expr)\n{\n  if (base.isobject () || increment_arg.isobject () || limit.isobject ())\n    {\n      octave_value_list tmp1;\n\n      if (increment_arg.is_defined ())\n        {\n          tmp1(2) = limit;\n          tmp1(1) = increment_arg;\n          tmp1(0) = base;\n        }\n      else\n        {\n          tmp1(1) = limit;\n          tmp1(0) = base;\n        }\n\n      interpreter& interp = __get_interpreter__ ();\n\n      symbol_table& symtab = interp.get_symbol_table ();\n\n      octave_value fcn = symtab.find_function (\"colon\", tmp1);\n\n      if (fcn.is_defined ())\n        {\n          octave_value_list tmp2 = interp.feval (fcn, tmp1, 1);\n\n          return tmp2(0);\n        }\n    }\n\n  octave_value increment\n    = increment_arg.is_defined () ? increment_arg : octave_value (1.0);\n\n  if (base.numel () > 1 || limit.numel () > 1 || increment.numel () > 1)\n    warning_with_id (\"Octave:colon-nonscalar-argument\",\n                     \"colon arguments should be scalars\");\n\n  if (base.iscomplex () || limit.iscomplex () || increment.iscomplex ())\n    warning_with_id (\"Octave:colon-complex-argument\",\n                     \"imaginary part of complex colon arguments is ignored\");\n\n  // FIXME: is there a better way to do this job, maybe using type traits?\n\n  builtin_type_t type_id = get_colon_op_type (base, increment, limit);\n\n  // For compatibility with Matlab, don't allow the range used in\n  // a FOR loop expression to be converted to a Matrix.\n\n  // For now, these functions create arrays instead of range<T> for\n  // all types except double.\n\n  switch (type_id)\n    {\n    case btyp_double:\n    case btyp_complex:\n      return make_float_range<double> (base, increment, limit, is_for_cmd_expr);\n\n    case btyp_float:\n    case btyp_float_complex:\n      return make_float_range<float> (base, increment, limit, is_for_cmd_expr);\n\n    case btyp_int8:\n      return make_int_range<octave_int8> (base, increment, limit);\n\n    case btyp_int16:\n      return make_int_range<octave_int16> (base, increment, limit);\n\n    case btyp_int32:\n      return make_int_range<octave_int32> (base, increment, limit);\n\n    case btyp_int64:\n      return make_int_range<octave_int64> (base, increment, limit);\n\n    case btyp_uint8:\n      return make_int_range<octave_uint8> (base, increment, limit);\n\n    case btyp_uint16:\n      return make_int_range<octave_uint16> (base, increment, limit);\n\n    case btyp_uint32:\n      return make_int_range<octave_uint32> (base, increment, limit);\n\n    case btyp_uint64:\n      return make_int_range<octave_uint64> (base, increment, limit);\n\n    case btyp_char:\n      return make_char_range (base, increment, limit);\n\n    case btyp_unknown:\n      error (\"incompatible types found in range expression\");\n\n    default:\n      error (\"invalid types found in range expression\");\n    }\n\n  return octave_value ();\n}\n\nOCTAVE_NORETURN static void\nerr_unary_op_conv (const std::string& on)\n{\n  error (\"type conversion failed for unary operator '%s'\", on.c_str ());\n}\n\noctave_value\nunary_op (type_info& ti, octave_value::unary_op op,\n          const octave_value& v)\n{\n  octave_value retval;\n\n  int t = v.type_id ();\n\n  if (t == octave_class::static_type_id ()\n      || t == octave_classdef::static_type_id ())\n    {\n      type_info::unary_class_op_fcn f = ti.lookup_unary_class_op (op);\n\n      if (! f)\n        err_unary_op (octave_value::unary_op_as_string (op), v.class_name ());\n\n      retval = f (v);\n    }\n  else\n    {\n      // FIXME: we need to handle overloading operators for built-in\n      // classes (double, char, int8, etc.)\n\n      type_info::unary_op_fcn f = ti.lookup_unary_op (op, t);\n\n      if (f)\n        retval = f (v.get_rep ());\n      else\n        {\n          octave_value tv;\n          octave_base_value::type_conv_fcn cf\n            = v.numeric_conversion_function ();\n\n          if (! cf)\n            err_unary_op (octave_value::unary_op_as_string (op),\n                          v.type_name ());\n\n          octave_base_value *tmp = cf (v.get_rep ());\n\n          if (! tmp)\n            err_unary_op_conv (octave_value::unary_op_as_string (op));\n\n          tv = octave_value (tmp);\n          retval = unary_op (op, tv);\n        }\n    }\n\n  return retval;\n}\n\noctave_value\nunary_op (octave_value::unary_op op, const octave_value& v)\n{\n  type_info& ti = __get_type_info__ ();\n\n  return unary_op (ti, op, v);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\nvoid\ninstall_types (octave::type_info& ti)\n{\n  octave_base_value::register_type (ti);\n  octave_cell::register_type (ti);\n  octave_scalar::register_type (ti);\n  octave_complex::register_type (ti);\n  octave_matrix::register_type (ti);\n  octave_diag_matrix::register_type (ti);\n  octave_complex_matrix::register_type (ti);\n  octave_complex_diag_matrix::register_type (ti);\n\n  // Legacy range type, preserved to allow loading \"constant\" ranges\n  // from data files.\n  octave_legacy_range::register_type (ti);\n\n  ov_range<double>::register_type (ti);\n\n  // For now, enable only ov_range<double>.\n\n  octave_bool::register_type (ti);\n  octave_bool_matrix::register_type (ti);\n  octave_char_matrix_str::register_type (ti);\n  octave_char_matrix_sq_str::register_type (ti);\n  octave_int8_scalar::register_type (ti);\n  octave_int16_scalar::register_type (ti);\n  octave_int32_scalar::register_type (ti);\n  octave_int64_scalar::register_type (ti);\n  octave_uint8_scalar::register_type (ti);\n  octave_uint16_scalar::register_type (ti);\n  octave_uint32_scalar::register_type (ti);\n  octave_uint64_scalar::register_type (ti);\n  octave_int8_matrix::register_type (ti);\n  octave_int16_matrix::register_type (ti);\n  octave_int32_matrix::register_type (ti);\n  octave_int64_matrix::register_type (ti);\n  octave_uint8_matrix::register_type (ti);\n  octave_uint16_matrix::register_type (ti);\n  octave_uint32_matrix::register_type (ti);\n  octave_uint64_matrix::register_type (ti);\n  octave_sparse_bool_matrix::register_type (ti);\n  octave_sparse_matrix::register_type (ti);\n  octave_sparse_complex_matrix::register_type (ti);\n  octave_struct::register_type (ti);\n  octave_scalar_struct::register_type (ti);\n  octave_class::register_type (ti);\n  octave_cs_list::register_type (ti);\n  octave_magic_colon::register_type (ti);\n  octave_builtin::register_type (ti);\n  octave_user_function::register_type (ti);\n  octave_dld_function::register_type (ti);\n  octave_fcn_handle::register_type (ti);\n  octave_float_scalar::register_type (ti);\n  octave_float_complex::register_type (ti);\n  octave_float_matrix::register_type (ti);\n  octave_float_diag_matrix::register_type (ti);\n  octave_float_complex_matrix::register_type (ti);\n  octave_float_complex_diag_matrix::register_type (ti);\n  octave_perm_matrix::register_type (ti);\n  octave_magic_int::register_type (ti);\n  octave_magic_uint::register_type (ti);\n  octave_null_matrix::register_type (ti);\n  octave_null_str::register_type (ti);\n  octave_null_sq_str::register_type (ti);\n  octave_lazy_index::register_type (ti);\n  octave_oncleanup::register_type (ti);\n  octave_java::register_type (ti);\n  octave_trivial_range::register_type (ti);\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUN (sizeof, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{sz} =} sizeof (@var{val})\nReturn the size of @var{val} in bytes.\n@seealso{whos}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).byte_size ());\n}\n\n/*\n%!assert (sizeof (uint64 (ones (3))), 72)\n%!assert (sizeof (double (zeros (2,4))), 64)\n%!assert (sizeof ({\"foo\", \"bar\", \"baaz\"}), 10)\n*/\n\nstatic void\ndecode_subscripts (const char *name, const octave_value& arg,\n                   std::string& type_string,\n                   std::list<octave_value_list>& idx)\n{\n  const octave_map m = arg.xmap_value (\"%s: second argument must be a structure with fields 'type' and 'subs'\", name);\n\n  if (m.nfields () != 2 || ! m.contains (\"type\") || ! m.contains (\"subs\"))\n    error (\"%s: second argument must be a structure with fields 'type' and 'subs'\",\n           name);\n\n  octave_idx_type nel = m.numel ();\n\n  type_string = std::string (nel, '\\0');\n  idx = std::list<octave_value_list> ();\n\n  if (nel == 0)\n    return;\n\n  const Cell type = m.contents (\"type\");\n  const Cell subs = m.contents (\"subs\");\n\n  for (int k = 0; k < nel; k++)\n    {\n      std::string item = type(k).xstring_value (\"%s: type(%d) must be a string\", name, k+1);\n\n      if (item == \"{}\")\n        type_string[k] = '{';\n      else if (item == \"()\")\n        type_string[k] = '(';\n      else if (item == \".\")\n        type_string[k] = '.';\n      else\n        error (\"%s: invalid indexing type '%s'\", name, item.c_str ());\n\n      octave_value_list idx_item;\n\n      if (subs(k).is_string ())\n        idx_item(0) = subs(k);\n      else if (subs(k).iscell ())\n        {\n          Cell subs_cell = subs(k).cell_value ();\n\n          for (int n = 0; n < subs_cell.numel (); n++)\n            {\n              if (subs_cell(n).is_string ()\n                  && subs_cell(n).string_value () == \":\")\n                idx_item(n) = octave_value(octave_value::magic_colon_t);\n              else\n                idx_item(n) = subs_cell(n);\n            }\n        }\n      else\n        error (\"%s: subs(%d) must be a string or cell array\", name, k+1);\n\n      idx.push_back (idx_item);\n    }\n}\n\nDEFUN (subsref, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{newval} =} subsref (@var{val}, @var{idx})\nPerform the subscripted element selection operation on @var{val} according\nto the subscript specified by @var{idx}.\n\nThe subscript @var{idx} must be a structure array with fields @samp{type}\nand @samp{subs}.  Valid values for @samp{type} are @qcode{\"()\"},\n@qcode{\"@{@}\"}, and @qcode{\".\"}.  The @samp{subs} field may be either\n@qcode{\":\"} or a cell array of index values.\n\nThe following example shows how to extract the first two columns of a matrix\n\n@example\n@group\nval = magic (3)\n    @xresult{} val = [ 8   1   6\n               3   5   7\n               4   9   2 ]\nidx.type = \"()\";\nidx.subs = @{\":\", 1:2@};\nsubsref (val, idx)\n     @xresult{} [ 8   1\n          3   5\n          4   9 ]\n@end group\n@end example\n\n@noindent\nNote that this is the same as writing @code{val(:, 1:2)}.\n\nIf @var{idx} is an empty structure array with fields @samp{type} and\n@samp{subs}, return @var{val}.\n\nThe keyword @code{end} cannot be used within @code{subsref} for indexing\nassignments.\n@seealso{subsasgn, substruct}\n@end deftypefn */)\n{\n  if (args.length () != 2)\n    print_usage ();\n\n  std::string type;\n  std::list<octave_value_list> idx;\n\n  decode_subscripts (\"subsref\", args(1), type, idx);\n\n  octave_value arg0 = args(0);\n\n  if (type.empty ())\n    return ovl (arg0);\n  else\n    return arg0.subsref (type, idx, nargout);\n}\n\nDEFUN (subsasgn, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{newval} =} subsasgn (@var{val}, @var{idx}, @var{rhs})\nPerform the subscripted assignment operation according to the subscript\nspecified by @var{idx}.\n\nThe subscript @var{idx} must be a structure array with fields @samp{type}\nand @samp{subs}.  Valid values for @samp{type} are @qcode{\"()\"},\n@qcode{\"@{@}\"}, and @qcode{\".\"}.  The @samp{subs} field may be either\n@qcode{\":\"} or a cell array of index values.\n\nThe following example shows how to set the two first columns of a 3-by-3\nmatrix to zero.\n\n@example\n@group\nval = magic (3);\nidx.type = \"()\";\nidx.subs = @{\":\", 1:2@};\nval = subsasgn (val, idx, 0)\n     @xresult{}  [ 0   0   6\n           0   0   7\n           0   0   2 ]\n@end group\n@end example\n\nNote that this is the same as writing @code{val(:, 1:2) = 0}.\n\nIf @var{idx} is an empty structure array with fields @samp{type} and\n@samp{subs}, return @var{rhs}.\n\nThe keyword @code{end} cannot be used within @code{subsasgn} for indexing\nassignments.\n@seealso{subsref, substruct, optimize_subsasgn_calls}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  std::string type;\n  std::list<octave_value_list> idx;\n\n  decode_subscripts (\"subsasgn\", args(1), type, idx);\n\n  if (type.empty ())\n    {\n      // Regularize a null matrix if stored into a variable.\n      return ovl (args(2).storable_value ());\n    }\n  else\n    {\n      octave_value arg0 = args(0);\n      octave_value arg2 = args(2);\n\n      arg0.make_unique ();\n\n      bool arg2_null = arg2.is_zero_by_zero () && arg2.is_double_type ();\n\n      return ovl (arg0.subsasgn (type, idx, (arg2_null\n                                             ? octave_null_matrix::instance\n                                             : arg2)));\n    }\n}\n\n/*\n%!test\n%! a = reshape ([1:25], 5,5);\n%! idx1 = substruct (\"()\", {3, 3});\n%! idx2 = substruct (\"()\", {2:2:5, 2:2:5});\n%! idx3 = substruct (\"()\", {\":\", [1,5]});\n%! idx4 = struct (\"type\", {}, \"subs\", {});\n%! assert (subsref (a, idx1), 13);\n%! assert (subsref (a, idx2), [7 17; 9 19]);\n%! assert (subsref (a, idx3), [1:5; 21:25]');\n%! assert (subsref (a, idx4), a);\n%! a = subsasgn (a, idx1, 0);\n%! a = subsasgn (a, idx2, 0);\n%! a = subsasgn (a, idx3, 0);\n%!# a = subsasgn (a, idx4, 0);\n%! b = [0    6   11   16    0\n%!      0    0   12    0    0\n%!      0    8    0   18    0\n%!      0    0   14    0    0\n%!      0   10   15   20    0];\n%! assert (a, b);\n\n%!test\n%! x = 1:10;\n%! assert (subsasgn (x, substruct (\"()\", {1}), zeros (0, 0)), 2:10);\n\n%!test\n%! c = num2cell (reshape ([1:25],5,5));\n%! idx1 = substruct  (\"{}\", {3, 3});\n%! idx2 = substruct  (\"()\", {2:2:5, 2:2:5});\n%! idx3 = substruct  (\"()\", {\":\", [1,5]});\n%! idx2p = substruct (\"{}\", {2:2:5, 2:2:5});\n%! idx3p = substruct (\"{}\", {\":\", [1,5]});\n%! idx4 = struct (\"type\", {}, \"subs\", {});\n%! assert ({ subsref(c, idx1) }, {13});\n%! assert ({ subsref(c, idx2p) }, {7 9 17 19});\n%! assert ({ subsref(c, idx3p) }, num2cell ([1:5, 21:25]));\n%! assert (subsref (c, idx4), c);\n%! c = subsasgn (c, idx1, 0);\n%! c = subsasgn (c, idx2, 0);\n%! c = subsasgn (c, idx3, 0);\n%!# c = subsasgn (c, idx4, 0);\n%! d = {0    6   11   16    0\n%!      0    0   12    0    0\n%!      0    8    0   18    0\n%!      0    0   14    0    0\n%!      0   10   15   20    0};\n%! assert (c, d);\n\n%!test\n%! s.a = \"ohai\";\n%! s.b = \"dere\";\n%! s.c = 42;\n%! idx1 = substruct (\".\", \"a\");\n%! idx2 = substruct (\".\", \"b\");\n%! idx3 = substruct (\".\", \"c\");\n%! idx4 = struct (\"type\", {}, \"subs\", {});\n%! assert (subsref (s, idx1), \"ohai\");\n%! assert (subsref (s, idx2), \"dere\");\n%! assert (subsref (s, idx3), 42);\n%! assert (subsref (s, idx4), s);\n%! s = subsasgn (s, idx1, \"Hello\");\n%! s = subsasgn (s, idx2, \"There\");\n%! s = subsasgn (s, idx3, 163);\n%!# s = subsasgn (s, idx4, 163);\n%! t.a = \"Hello\";\n%! t.b = \"There\";\n%! t.c = 163;\n%! assert (s, t);\n\n// Overloaded subsref in classdef class\n%!test\n%! data.x = 1;\n%! cm = containers.Map;\n%! cm('foo') = data;\n%! assert (cm('foo').x, 1);\n*/\n\nDEFUN (is_sq_string, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} is_sq_string (@var{x})\nReturn true if @var{x} is a single-quoted character string.\n@seealso{is_dq_string, ischar}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).is_sq_string ());\n}\n\n/*\n%!assert (is_sq_string ('foo'), true)\n%!assert (is_sq_string (\"foo\"), false)\n%!assert (is_sq_string (1.0), false)\n%!assert (is_sq_string ({2.0}), false)\n\n%!error is_sq_string ()\n%!error is_sq_string ('foo', 2)\n*/\n\nDEFUN (is_dq_string, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} is_dq_string (@var{x})\nReturn true if @var{x} is a double-quoted character string.\n@seealso{is_sq_string, ischar}\n@end deftypefn */)\n{\n  if (args.length () != 1)\n    print_usage ();\n\n  return ovl (args(0).is_dq_string ());\n}\n\n/*\n%!assert (is_dq_string (\"foo\"), true)\n%!assert (is_dq_string ('foo'), false)\n%!assert (is_dq_string (1.0), false)\n%!assert (is_dq_string ({2.0}), false)\n\n%!error is_dq_string ()\n%!error is_dq_string (\"foo\", 2)\n*/\n\nDEFUN (optimize_permutation_matrix, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} optimize_permutation_matrix ()\n@deftypefnx {} {@var{old_val} =} optimize_permutation_matrix (@var{new_val})\n@deftypefnx {} {@var{old_val} =} optimize_permutation_matrix (@var{new_val}, \"local\")\nQuery or set whether a special space-efficient format is used for storing\npermutation matrices.\n\nThe default value is true.  If this option is set to false, Octave will store\npermutation matrices as full matrices.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the setting\nis changed locally for the function and any subroutines it calls.  The original\nsetting is restored when exiting the function.\n@seealso{optimize_range, optimize_diagonal_matrix}\n@end deftypefn */)\n{\n  return set_internal_variable (Voptimize_permutation_matrix, args, nargout,\n                                \"optimize_permutation_matrix\");\n}\n\n/*\n%!function p = __test_dpm__ (dpm)\n%!  optimize_permutation_matrix (dpm, \"local\");\n%!  [~, ~, p] = lu ([1,2;3,4]);\n%!endfunction\n\n%!assert (typeinfo (__test_dpm__ (true)), \"permutation matrix\")\n%!assert (typeinfo (__test_dpm__ (false)), \"matrix\")\n*/\n\nDEFUN (optimize_diagonal_matrix, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} optimize_diagonal_matrix ()\n@deftypefnx {} {@var{old_val} =} optimize_diagonal_matrix (@var{new_val})\n@deftypefnx {} {@var{old_val} =} optimize_diagonal_matrix (@var{new_val}, \"local\")\nQuery or set whether a special space-efficient format is used for storing\ndiagonal matrices.\n\nThe default value is true.  If this option is set to false, Octave will store\ndiagonal matrices as full matrices.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the setting\nis changed locally for the function and any subroutines it calls.  The original\nsetting is restored when exiting the function.\n@seealso{optimize_range, optimize_permutation_matrix}\n@end deftypefn */)\n{\n  return set_internal_variable (Voptimize_diagonal_matrix, args, nargout,\n                                \"optimize_diagonal_matrix\");\n}\n\n/*\n%!function [x, xi, fx, fxi] = __test_ddm__ (ddm)\n%!  optimize_diagonal_matrix (ddm, \"local\");\n%!  x = eye (2);\n%!  xi = x*i;\n%!  fx = single (x);\n%!  fxi = single (xi);\n%!endfunction\n\n%!shared x, xi, fx, fxi\n%!  [x, xi, fx, fxi] = __test_ddm__ (true);\n%!assert (typeinfo (x), \"diagonal matrix\")\n%!assert (typeinfo (xi), \"complex diagonal matrix\")\n%!assert (typeinfo (fx), \"float diagonal matrix\")\n%!assert (typeinfo (fxi), \"float complex diagonal matrix\")\n\n%!shared x, xi, fx, fxi\n%!  [x, xi, fx, fxi] = __test_ddm__ (false);\n%!assert (typeinfo (x), \"matrix\")\n%!assert (typeinfo (xi), \"complex matrix\")\n%!assert (typeinfo (fx), \"float matrix\")\n%!assert (typeinfo (fxi), \"float complex matrix\")\n*/\n\nDEFUN (optimize_range, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} optimize_range ()\n@deftypefnx {} {@var{old_val} =} optimize_range (@var{new_val})\n@deftypefnx {} {@var{old_val} =} optimize_range (@var{new_val}, \"local\")\nQuery or set whether a special space-efficient format is used for storing\nranges.\n\nThe default value is true.  If this option is set to false, Octave will store\nranges as full matrices.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the setting\nis changed locally for the function and any subroutines it calls.  The original\nsetting is restored when exiting the function.\n@seealso{optimize_diagonal_matrix, optimize_permutation_matrix}\n@end deftypefn */)\n{\n  return set_internal_variable (Voptimize_range, args, nargout,\n                                \"optimize_range\");\n}\n\n/*\n%!function r = __test_dr__ (dr)\n%!  optimize_range (dr, \"local\");\n%!  ## Constant folding will produce range for 1:13.\n%!  base = 1;\n%!  limit = 13;\n%!  r = base:limit;\n%!endfunction\n\n%!assert (typeinfo (__test_dr__ (true)), \"double_range\")\n%!assert (typeinfo (__test_dr__ (false)), \"matrix\")\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave-value/ov.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ov_h)\n#define octave_ov_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n#include <string>\n#include <list>\n#include <memory>\n#include <map>\n\n#include \"panic.h\"\n\n#include \"data-conv.h\"\n#include \"idx-vector.h\"\n#include \"mach-info.h\"\n#include \"mx-base.h\"\n#include \"oct-sort.h\"\n#include \"oct-time.h\"\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass stack_frame;\nclass type_info;\nclass scope_stack_frame;\nclass base_value_stack_frame;\n\nOCTAVE_END_NAMESPACE(octave)\n\nclass Cell;\nclass float_format;\nclass mxArray;\nclass octave_map;\nclass octave_scalar_map;\nclass octave_function;\nclass octave_user_function;\nclass octave_fcn_handle;\nclass octave_value_list;\nclass octave_fcn_cache;\n\n#include \"mxtypes.h\"\n\n#include \"oct-stream.h\"\n#include \"ov-base.h\"\n\nclass OCTINTERP_API octave_value\n{\npublic:\n\n  enum unary_op\n  {\n    op_not,            // not\n    op_uplus,          // uplus\n    op_uminus,         // uminus\n    op_transpose,      // transpose\n    op_hermitian,      // ctranspose\n    op_incr,\n    op_decr,\n    num_unary_ops,\n    unknown_unary_op\n  };\n\n  enum binary_op\n  {\n    op_add,            // plus\n    op_sub,            // minus\n    op_mul,            // mtimes\n    op_div,            // mrdivide\n    op_pow,            // mpower\n    op_ldiv,           // mldivide\n    op_lt,             // lt\n    op_le,             // le\n    op_eq,             // eq\n    op_ge,             // ge\n    op_gt,             // gt\n    op_ne,             // ne\n    op_el_mul,         // times\n    op_el_div,         // rdivide\n    op_el_pow,         // power\n    op_el_ldiv,        // ldivide\n    op_el_and,         // and\n    op_el_or,          // or\n    op_struct_ref,\n    num_binary_ops,\n    unknown_binary_op\n  };\n\n  enum compound_binary_op\n  {\n    // ** compound operations **\n    op_trans_mul,\n    op_mul_trans,\n    op_herm_mul,\n    op_mul_herm,\n    op_trans_ldiv,\n    op_herm_ldiv,\n    op_el_not_and,\n    op_el_not_or,\n    op_el_and_not,\n    op_el_or_not,\n    num_compound_binary_ops,\n    unknown_compound_binary_op\n  };\n\n  enum assign_op\n  {\n    op_asn_eq,\n    op_add_eq,\n    op_sub_eq,\n    op_mul_eq,\n    op_div_eq,\n    op_ldiv_eq,\n    op_pow_eq,\n    op_el_mul_eq,\n    op_el_div_eq,\n    op_el_ldiv_eq,\n    op_el_pow_eq,\n    op_el_and_eq,\n    op_el_or_eq,\n    num_assign_ops,\n    unknown_assign_op\n  };\n\n  static OCTINTERP_API binary_op assign_op_to_binary_op (assign_op);\n\n  static OCTINTERP_API assign_op binary_op_to_assign_op (binary_op);\n\n  static OCTINTERP_API std::string unary_op_as_string (unary_op);\n  static OCTINTERP_API std::string unary_op_fcn_name (unary_op);\n\n  static OCTINTERP_API std::string binary_op_as_string (binary_op);\n  static OCTINTERP_API std::string binary_op_fcn_name (binary_op);\n\n  static OCTINTERP_API std::string binary_op_fcn_name (compound_binary_op);\n\n  static OCTINTERP_API std::string assign_op_as_string (assign_op);\n\n  static OCTINTERP_API octave_value\n  empty_conv (const std::string& type,\n              const octave_value& rhs = octave_value ());\n\n  enum magic_colon { magic_colon_t };\n\n  octave_value ()\n    : m_rep (nil_rep ())\n  {\n    m_rep->m_count++;\n  }\n\n  OCTINTERP_API octave_value (short int i);\n  OCTINTERP_API octave_value (unsigned short int i);\n  OCTINTERP_API octave_value (int i);\n  OCTINTERP_API octave_value (unsigned int i);\n  OCTINTERP_API octave_value (long int i);\n  OCTINTERP_API octave_value (unsigned long int i);\n\n  // FIXME: These are kluges.  They turn into doubles internally, which will\n  // break for very large values.  We just use them to store things like\n  // 64-bit ino_t, etc, and hope that those values are never actually larger\n  // than can be represented exactly in a double.\n\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\n  OCTINTERP_API octave_value (long long int i);\n#endif\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\n  OCTINTERP_API octave_value (unsigned long long int i);\n#endif\n\n  OCTINTERP_API octave_value (octave::sys::time t);\n  OCTINTERP_API octave_value (double d);\n  OCTINTERP_API octave_value (float d);\n  OCTINTERP_API octave_value (const Cell& c, bool is_cs_list = false);\n  OCTINTERP_API octave_value (const Matrix& m,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const FloatMatrix& m,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const NDArray& nda);\n  OCTINTERP_API octave_value (const FloatNDArray& nda);\n  OCTINTERP_API octave_value (const Array<double>& m);\n  OCTINTERP_API octave_value (const Array<float>& m);\n  OCTINTERP_API octave_value (const DiagMatrix& d);\n  OCTINTERP_API octave_value (const DiagArray2<double>& d);\n  OCTINTERP_API octave_value (const DiagArray2<float>& d);\n  OCTINTERP_API octave_value (const DiagArray2<Complex>& d);\n  OCTINTERP_API octave_value (const DiagArray2<FloatComplex>& d);\n  OCTINTERP_API octave_value (const FloatDiagMatrix& d);\n  OCTINTERP_API octave_value (const RowVector& v);\n  OCTINTERP_API octave_value (const FloatRowVector& v);\n  OCTINTERP_API octave_value (const ColumnVector& v);\n  OCTINTERP_API octave_value (const FloatColumnVector& v);\n  OCTINTERP_API octave_value (const Complex& C);\n  OCTINTERP_API octave_value (const FloatComplex& C);\n  OCTINTERP_API octave_value (const ComplexMatrix& m,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const FloatComplexMatrix& m,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const ComplexNDArray& cnda);\n  OCTINTERP_API octave_value (const FloatComplexNDArray& cnda);\n  OCTINTERP_API octave_value (const Array<Complex>& m);\n  OCTINTERP_API octave_value (const Array<FloatComplex>& m);\n  OCTINTERP_API octave_value (const ComplexDiagMatrix& d);\n  OCTINTERP_API octave_value (const FloatComplexDiagMatrix& d);\n  OCTINTERP_API octave_value (const ComplexRowVector& v);\n  OCTINTERP_API octave_value (const FloatComplexRowVector& v);\n  OCTINTERP_API octave_value (const ComplexColumnVector& v);\n  OCTINTERP_API octave_value (const FloatComplexColumnVector& v);\n  OCTINTERP_API octave_value (const PermMatrix& p);\n  OCTINTERP_API octave_value (bool b);\n  OCTINTERP_API octave_value (const boolMatrix& bm,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const boolNDArray& bnda);\n  OCTINTERP_API octave_value (const Array<bool>& bnda);\n  OCTINTERP_API octave_value (char c, char type = '\\'');\n  OCTINTERP_API octave_value (const char *s, char type = '\\'');\n  OCTINTERP_API octave_value (const std::string& s, char type = '\\'');\n  OCTINTERP_API octave_value (const string_vector& s, char type = '\\'');\n  OCTINTERP_API octave_value (const charMatrix& chm,  char type = '\\'');\n  OCTINTERP_API octave_value (const charNDArray& chnda, char type = '\\'');\n  OCTINTERP_API octave_value (const Array<char>& chnda, char type = '\\'');\n\n  OCTINTERP_API octave_value (const SparseMatrix& m,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const Sparse<double>& m,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const SparseComplexMatrix& m,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const Sparse<Complex>& m,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const SparseBoolMatrix& bm,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const Sparse<bool>& m,\n                              const MatrixType& t = MatrixType ());\n  OCTINTERP_API octave_value (const octave_int8& i);\n  OCTINTERP_API octave_value (const octave_int16& i);\n  OCTINTERP_API octave_value (const octave_int32& i);\n  OCTINTERP_API octave_value (const octave_int64& i);\n  OCTINTERP_API octave_value (const octave_uint8& i);\n  OCTINTERP_API octave_value (const octave_uint16& i);\n  OCTINTERP_API octave_value (const octave_uint32& i);\n  OCTINTERP_API octave_value (const octave_uint64& i);\n  OCTINTERP_API octave_value (const int8NDArray& inda);\n  OCTINTERP_API octave_value (const Array<octave_int8>& inda);\n  OCTINTERP_API octave_value (const int16NDArray& inda);\n  OCTINTERP_API octave_value (const Array<octave_int16>& inda);\n  OCTINTERP_API octave_value (const int32NDArray& inda);\n  OCTINTERP_API octave_value (const Array<octave_int32>& inda);\n  OCTINTERP_API octave_value (const int64NDArray& inda);\n  OCTINTERP_API octave_value (const Array<octave_int64>& inda);\n  OCTINTERP_API octave_value (const uint8NDArray& inda);\n  OCTINTERP_API octave_value (const Array<octave_uint8>& inda);\n  OCTINTERP_API octave_value (const uint16NDArray& inda);\n  OCTINTERP_API octave_value (const Array<octave_uint16>& inda);\n  OCTINTERP_API octave_value (const uint32NDArray& inda);\n  OCTINTERP_API octave_value (const Array<octave_uint32>& inda);\n  OCTINTERP_API octave_value (const uint64NDArray& inda);\n  OCTINTERP_API octave_value (const Array<octave_uint64>& inda);\n  OCTINTERP_API octave_value (const Array<octave_idx_type>& inda,\n                              bool zero_based = false,\n                              bool cache_index = false);\n  OCTINTERP_API octave_value (const Array<std::string>& cellstr);\n  OCTINTERP_API octave_value (const octave::idx_vector& idx, bool lazy = true);\n\n  OCTINTERP_API octave_value (const octave::range<double>& r,\n                              bool force_range = false);\n\n  // For now, enable only range<double>.\n\n  OCTINTERP_API octave_value (const octave_map& m);\n  OCTINTERP_API octave_value (const octave_scalar_map& m);\n  OCTINTERP_API octave_value (const std::map<std::string, octave_value>&);\n  OCTINTERP_API octave_value (const octave_map& m, const std::string& id,\n                              const std::list<std::string>& plist);\n  OCTINTERP_API octave_value (const octave_scalar_map& m, const std::string& id,\n                              const std::list<std::string>& plist);\n\n  // This one is explicit because it can cause some trouble to\n  // accidentally create a cs-list when one was not intended.\n  explicit OCTINTERP_API octave_value (const octave_value_list& m);\n\n  OCTINTERP_API octave_value (octave_value::magic_colon);\n\n  octave_value (octave_base_value *new_rep, bool borrow = false)\n    : m_rep (new_rep)\n  {\n    if (borrow)\n      m_rep->m_count++;\n  }\n\n  // Copy constructor.\n\n  octave_value (const octave_value& a)\n    : m_rep (a.m_rep)\n  {\n    m_rep->m_count++;\n  }\n\n  octave_value (octave_value&& a)\n    : m_rep (a.m_rep)\n  {\n    a.m_rep = nullptr;\n  }\n\n  // This should only be called for derived types.\n\n  OCTINTERP_API octave_base_value * clone () const;\n\n  octave_base_value * empty_clone () const\n  { return m_rep->empty_clone (); }\n\n  // Delete the representation of this constant if the count drops to zero.\n\n  ~octave_value ()\n  {\n    // Because we define a move constructor and a move assignment\n    // operator, rep may be a nullptr here.  We should only need to\n    // protect the move assignment operator in a similar way.\n\n    if (m_rep && --m_rep->m_count == 0 && m_rep != nil_rep ())\n      delete m_rep;\n  }\n\n  void make_unique ()\n  {\n    if (m_rep->m_count > 1)\n      {\n        octave_base_value *r = m_rep->unique_clone ();\n\n        if (--m_rep->m_count == 0 && m_rep != nil_rep ())\n          delete m_rep;\n\n        m_rep = r;\n      }\n  }\n\n  // This uniquifies the value if it is referenced by more than a certain\n  // number of shallow copies.  This is useful for optimizations where we\n  // know a certain copy, typically within a cell array, to be obsolete.\n  void make_unique (int obsolete_copies)\n  {\n    if (m_rep->m_count > obsolete_copies + 1)\n      {\n        octave_base_value *r = m_rep->unique_clone ();\n\n        if (--m_rep->m_count == 0 && m_rep != nil_rep ())\n          delete m_rep;\n\n        m_rep = r;\n      }\n  }\n\n  // Convert any nested function handles in this object to use weak\n  // references to their enclosing stack frame context.  Used to break\n  // shared_ptr reference cycles for handles to nested functions\n  // (closures).\n  void break_closure_cycles (const std::shared_ptr<octave::stack_frame>&);\n\n  // Simple assignment.\n\n  octave_value& operator = (const octave_value& a)\n  {\n    if (m_rep != a.m_rep)\n      {\n        if (--m_rep->m_count == 0 && m_rep != nil_rep ())\n          delete m_rep;\n\n        m_rep = a.m_rep;\n        m_rep->m_count++;\n      }\n\n    return *this;\n  }\n\n  octave_value& operator = (octave_value&& a)\n  {\n    // Because we define a move constructor and a move assignment\n    // operator, rep may be a nullptr here.  We should only need to\n    // protect the destructor in a similar way.\n\n    if (this != &a)\n      {\n        if (m_rep && --m_rep->m_count == 0 && m_rep != nil_rep ())\n          delete m_rep;\n\n        m_rep = a.m_rep;\n        a.m_rep = nullptr;\n      }\n\n    return *this;\n  }\n\n  octave_idx_type get_count () const { return m_rep->m_count; }\n\n  octave_base_value::type_conv_info numeric_conversion_function () const\n  { return m_rep->numeric_conversion_function (); }\n\n  octave_base_value::type_conv_info numeric_demotion_function () const\n  { return m_rep->numeric_demotion_function (); }\n\n  OCTINTERP_API void maybe_mutate ();\n\n  octave_value squeeze () const\n  { return m_rep->squeeze (); }\n\n  // The result of full().\n  octave_value full_value () const\n  { return m_rep->full_value (); }\n\n  // Type conversions.\n\n  // Returns a copy of a scalar (double), or makes a scalar\n  // for other types.\n  octave_value as_double_or_copy () const\n  { return m_rep->as_double_or_copy (); }\n\n  octave_value as_double () const { return m_rep->as_double (); }\n  octave_value as_single () const { return m_rep->as_single (); }\n\n  octave_value as_int8 () const { return m_rep->as_int8 (); }\n  octave_value as_int16 () const { return m_rep->as_int16 (); }\n  octave_value as_int32 () const { return m_rep->as_int32 (); }\n  octave_value as_int64 () const { return m_rep->as_int64 (); }\n\n  octave_value as_uint8 () const { return m_rep->as_uint8 (); }\n  octave_value as_uint16 () const { return m_rep->as_uint16 (); }\n  octave_value as_uint32 () const { return m_rep->as_uint32 (); }\n  octave_value as_uint64 () const { return m_rep->as_uint64 (); }\n\n  octave_base_value * try_narrowing_conversion ()\n  { return m_rep->try_narrowing_conversion (); }\n\n  // Close to dims (), but can be overloaded for classes.\n  Matrix size ()\n  { return m_rep->size (); }\n\n  // FIXME: should this function be deprecated and removed?  It supports\n  // an undocumented feature of Matlab.\n  octave_idx_type xnumel (const octave_value_list& idx)\n  { return m_rep->xnumel (idx); }\n\n  // FIXME: Do we really need all these different versions of subsref\n  // and related functions?\n\n  OCTINTERP_API octave_value\n  single_subsref (const std::string& type, const octave_value_list& idx);\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx)\n  { return m_rep->subsref (type, idx); }\n\n  octave_value subsref (const std::string& type,\n                        const std::list<octave_value_list>& idx,\n                        bool auto_add)\n  { return m_rep->subsref (type, idx, auto_add); }\n\n  OCTINTERP_API octave_value_list\n  subsref (const std::string& type, const std::list<octave_value_list>& idx,\n           int nargout);\n\n  octave_value_list\n  simple_subsref (char type, octave_value_list& idx, int nargout);\n\n  OCTINTERP_API octave_value\n  next_subsref (const std::string& type,\n                const std::list<octave_value_list>& idx, std::size_t skip = 1);\n\n  OCTINTERP_API octave_value_list\n  next_subsref (int nargout, const std::string& type,\n                const std::list<octave_value_list>& idx, std::size_t skip = 1);\n\n  OCTINTERP_API octave_value\n  next_subsref (bool auto_add, const std::string& type,\n                const std::list<octave_value_list>& idx, std::size_t skip = 1);\n\n  octave_value index_op (const octave_value_list& idx, bool resize_ok = false)\n  {\n    return m_rep->do_index_op (idx, resize_ok);\n  }\n\n  OCTINTERP_API octave_idx_type\n  end_index (octave_idx_type index_position,\n             octave_idx_type num_indices) const;\n\n  OCTINTERP_API octave_value\n  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,\n            const octave_value& rhs);\n\n  octave_value\n  simple_subsasgn (char type, octave_value_list& idx, const octave_value& rhs)\n  {\n    return m_rep->simple_subsasgn (type, idx, rhs);\n  }\n\n  OCTINTERP_API octave_value\n  undef_subsasgn (const std::string& type,\n                  const std::list<octave_value_list>& idx,\n                  const octave_value& rhs);\n\n  OCTINTERP_API octave_value&\n  assign (assign_op op, const std::string& type,\n          const std::list<octave_value_list>& idx, const octave_value& rhs);\n\n  OCTINTERP_API octave_value& assign (assign_op, const octave_value& rhs);\n\n  octave::idx_vector index_vector (bool require_integers = false) const\n  {\n    return m_rep->index_vector (require_integers);\n  }\n\n  // Size.\n\n  dim_vector dims () const { return m_rep->dims (); }\n\n  OCTINTERP_API std::string get_dims_str () const;\n\n  octave_idx_type rows () const { return m_rep->rows (); }\n\n  octave_idx_type columns () const { return m_rep->columns (); }\n\n  OCTINTERP_API octave_idx_type length () const;\n\n  int ndims () const { return m_rep->ndims (); }\n\n  bool all_zero_dims () const { return dims ().all_zero (); }\n\n  // Are the dimensions of this constant zero by zero?\n  bool is_zero_by_zero () const\n  { return (ndims () == 2 && rows () == 0 && columns () == 0); }\n\n  octave_idx_type numel () const\n  { return m_rep->numel (); }\n\n  std::size_t byte_size () const\n  { return m_rep->byte_size (); }\n\n  octave_idx_type nnz () const { return m_rep->nnz (); }\n\n  octave_idx_type nzmax () const { return m_rep->nzmax (); }\n\n  octave_idx_type nfields () const { return m_rep->nfields (); }\n\n  octave_value reshape (const dim_vector& dv) const\n  { return m_rep->reshape (dv); }\n\n  octave_value permute (const Array<int>& vec, bool inv = false) const\n  { return m_rep->permute (vec, inv); }\n\n  octave_value ipermute (const Array<int>& vec) const\n  { return m_rep->permute (vec, true); }\n\n  octave_value resize (const dim_vector& dv, bool fill = false) const\n  { return m_rep->resize (dv, fill);}\n\n  MatrixType matrix_type () const\n  { return m_rep->matrix_type (); }\n\n  MatrixType matrix_type (const MatrixType& typ) const\n  { return m_rep->matrix_type (typ); }\n\n  // Does this constant have a type?  Both of these are provided since it is\n  // sometimes more natural to write is_undefined() instead of ! is_defined().\n\n  bool is_defined () const\n  { return m_rep->is_defined (); }\n\n  bool is_undefined () const\n  { return ! is_defined (); }\n\n  bool is_legacy_object () const\n  { return m_rep->is_legacy_object (); }\n\n  bool isempty () const\n  { return m_rep->isempty (); }\n\n  bool iscell () const\n  { return m_rep->iscell (); }\n\n  bool iscellstr () const\n  { return m_rep->iscellstr (); }\n\n  bool is_real_scalar () const\n  { return m_rep->is_real_scalar (); }\n\n  bool is_real_matrix () const\n  { return m_rep->is_real_matrix (); }\n\n  bool is_complex_scalar () const\n  { return m_rep->is_complex_scalar (); }\n\n  bool is_complex_matrix () const\n  { return m_rep->is_complex_matrix (); }\n\n  bool is_bool_scalar () const\n  { return m_rep->is_bool_scalar (); }\n\n  bool is_bool_matrix () const\n  { return m_rep->is_bool_matrix (); }\n\n  bool is_char_matrix () const\n  { return m_rep->is_char_matrix (); }\n\n  bool is_diag_matrix () const\n  { return m_rep->is_diag_matrix (); }\n\n  bool is_perm_matrix () const\n  { return m_rep->is_perm_matrix (); }\n\n  bool is_string () const\n  { return m_rep->is_string (); }\n\n  bool is_sq_string () const\n  { return m_rep->is_sq_string (); }\n\n  bool is_dq_string () const\n  { return m_rep->is_string () && ! m_rep->is_sq_string (); }\n\n  bool is_range () const\n  { return m_rep->is_range (); }\n\n  bool isstruct () const\n  { return m_rep->isstruct (); }\n\n  bool is_classdef_meta () const\n  { return m_rep->is_classdef_meta (); }\n\n  bool is_classdef_object () const\n  { return m_rep->is_classdef_object (); }\n\n  bool is_classdef_superclass_ref () const\n  { return m_rep->is_classdef_superclass_ref (); }\n\n  bool is_package () const\n  { return m_rep->is_package (); }\n\n  bool isobject () const\n  { return m_rep->isobject (); }\n\n  bool isjava () const\n  { return m_rep->isjava (); }\n\n  bool is_cs_list () const\n  { return m_rep->is_cs_list (); }\n\n  bool is_magic_colon () const\n  { return m_rep->is_magic_colon (); }\n\n  bool is_magic_int () const\n  { return m_rep->is_magic_int (); }\n\n  bool isnull () const\n  { return m_rep->isnull (); }\n\n  // Are any or all of the elements in this constant nonzero?\n\n  octave_value all (int dim = 0) const\n  { return m_rep->all (dim); }\n\n  octave_value any (int dim = 0) const\n  { return m_rep->any (dim); }\n\n  builtin_type_t builtin_type () const\n  { return m_rep->builtin_type (); }\n\n  // Floating point types.\n\n  bool is_double_type () const\n  { return m_rep->is_double_type (); }\n\n  bool is_single_type () const\n  { return m_rep->is_single_type (); }\n\n  bool isfloat () const\n  { return m_rep->isfloat (); }\n\n  // Integer types.\n\n  bool is_int8_type () const\n  { return m_rep->is_int8_type (); }\n\n  bool is_int16_type () const\n  { return m_rep->is_int16_type (); }\n\n  bool is_int32_type () const\n  { return m_rep->is_int32_type (); }\n\n  bool is_int64_type () const\n  { return m_rep->is_int64_type (); }\n\n  bool is_uint8_type () const\n  { return m_rep->is_uint8_type (); }\n\n  bool is_uint16_type () const\n  { return m_rep->is_uint16_type (); }\n\n  bool is_uint32_type () const\n  { return m_rep->is_uint32_type (); }\n\n  bool is_uint64_type () const\n  { return m_rep->is_uint64_type (); }\n\n  bool isinteger () const\n  { return m_rep->isinteger (); }\n\n  // Other type stuff.\n\n  bool islogical () const\n  { return m_rep->islogical (); }\n\n  bool isreal () const\n  { return m_rep->isreal (); }\n\n  bool iscomplex () const\n  { return m_rep->iscomplex (); }\n\n  bool is_scalar_type () const\n  { return m_rep->is_scalar_type (); }\n\n  bool is_matrix_type () const\n  { return m_rep->is_matrix_type (); }\n\n  bool isnumeric () const\n  { return m_rep->isnumeric (); }\n\n  bool issparse () const\n  { return m_rep->issparse (); }\n\n  // Does this constant correspond to a truth value?\n\n  bool is_true () const\n  { return m_rep->is_true (); }\n\n  // Do two constants match (in a switch statement)?\n\n  bool is_equal (const octave_value&) const;\n\n  bool is_constant () const\n  { return m_rep->is_constant (); }\n\n  bool is_function_handle () const\n  { return m_rep->is_function_handle (); }\n\n  bool is_anonymous_function () const\n  { return m_rep->is_anonymous_function (); }\n\n  bool is_inline_function () const\n  { return m_rep->is_inline_function (); }\n\n  bool is_function () const\n  { return m_rep->is_function (); }\n\n  bool is_user_script () const\n  { return m_rep->is_user_script (); }\n\n  bool is_user_function () const\n  { return m_rep->is_user_function (); }\n\n  bool is_user_code () const\n  { return m_rep->is_user_code (); }\n\n  bool is_builtin_function () const\n  { return m_rep->is_builtin_function (); }\n\n  bool is_dld_function () const\n  { return m_rep->is_dld_function (); }\n\n  bool is_mex_function () const\n  { return m_rep->is_mex_function (); }\n\n  void erase_subfunctions () { m_rep->erase_subfunctions (); }\n\n  // Values.\n\n  octave_value eval () { return *this; }\n\n  short int\n  short_value (bool req_int = false, bool frc_str_conv = false) const\n  { return m_rep->short_value (req_int, frc_str_conv); }\n\n  unsigned short int\n  ushort_value (bool req_int = false, bool frc_str_conv = false) const\n  { return m_rep->ushort_value (req_int, frc_str_conv); }\n\n  int int_value (bool req_int = false, bool frc_str_conv = false) const\n  { return m_rep->int_value (req_int, frc_str_conv); }\n\n  int strict_int_value (bool frc_str_conv = false) const\n  { return m_rep->int_value (true, frc_str_conv); }\n\n  unsigned int\n  uint_value (bool req_int = false, bool frc_str_conv = false) const\n  { return m_rep->uint_value (req_int, frc_str_conv); }\n\n  int nint_value (bool frc_str_conv = false) const\n  { return m_rep->nint_value (frc_str_conv); }\n\n  long int\n  long_value (bool req_int = false, bool frc_str_conv = false) const\n  { return m_rep->long_value (req_int, frc_str_conv); }\n\n  unsigned long int\n  ulong_value (bool req_int = false, bool frc_str_conv = false) const\n  { return m_rep->ulong_value (req_int, frc_str_conv); }\n\n  int64_t\n  int64_value (bool req_int = false, bool frc_str_conv = false) const\n  { return m_rep->int64_value (req_int, frc_str_conv); }\n\n  uint64_t\n  uint64_value (bool req_int = false, bool frc_str_conv = false) const\n  { return m_rep->uint64_value (req_int, frc_str_conv); }\n\n  octave_idx_type\n  idx_type_value (bool req_int = false, bool frc_str_conv = false) const;\n\n  octave_idx_type\n  strict_idx_type_value (bool frc_str_conv = false) const;\n\n  double double_value (bool frc_str_conv = false) const\n  { return m_rep->double_value (frc_str_conv); }\n\n  float float_value (bool frc_str_conv = false) const\n  { return m_rep->float_value (frc_str_conv); }\n\n  double scalar_value (bool frc_str_conv = false) const\n  { return m_rep->scalar_value (frc_str_conv); }\n\n  float float_scalar_value (bool frc_str_conv = false) const\n  { return m_rep->float_scalar_value (frc_str_conv); }\n\n  Matrix matrix_value (bool frc_str_conv = false) const\n  { return m_rep->matrix_value (frc_str_conv); }\n\n  FloatMatrix float_matrix_value (bool frc_str_conv = false) const\n  { return m_rep->float_matrix_value (frc_str_conv); }\n\n  NDArray array_value (bool frc_str_conv = false) const\n  { return m_rep->array_value (frc_str_conv); }\n\n  FloatNDArray float_array_value (bool frc_str_conv = false) const\n  { return m_rep->float_array_value (frc_str_conv); }\n\n  Complex complex_value (bool frc_str_conv = false) const\n  { return m_rep->complex_value (frc_str_conv); }\n\n  FloatComplex float_complex_value (bool frc_str_conv = false) const\n  { return m_rep->float_complex_value (frc_str_conv); }\n\n  ComplexMatrix complex_matrix_value (bool frc_str_conv = false) const\n  { return m_rep->complex_matrix_value (frc_str_conv); }\n\n  FloatComplexMatrix\n  float_complex_matrix_value (bool frc_str_conv = false) const\n  { return m_rep->float_complex_matrix_value (frc_str_conv); }\n\n  ComplexNDArray complex_array_value (bool frc_str_conv = false) const\n  { return m_rep->complex_array_value (frc_str_conv); }\n\n  FloatComplexNDArray\n  float_complex_array_value (bool frc_str_conv = false) const\n  { return m_rep->float_complex_array_value (frc_str_conv); }\n\n  bool bool_value (bool warn = false) const\n  { return m_rep->bool_value (warn); }\n\n  bool strict_bool_value () const\n  { return m_rep->bool_value (true); }\n\n  boolMatrix bool_matrix_value (bool warn = false) const\n  { return m_rep->bool_matrix_value (warn); }\n\n  boolNDArray bool_array_value (bool warn = false) const\n  { return m_rep->bool_array_value (warn); }\n\n  charMatrix char_matrix_value (bool frc_str_conv = false) const\n  { return m_rep->char_matrix_value (frc_str_conv); }\n\n  charNDArray char_array_value (bool frc_str_conv = false) const\n  { return m_rep->char_array_value (frc_str_conv); }\n\n  SparseMatrix sparse_matrix_value (bool frc_str_conv = false) const\n  { return m_rep->sparse_matrix_value (frc_str_conv); }\n\n  SparseComplexMatrix\n  sparse_complex_matrix_value (bool frc_str_conv = false) const\n  { return m_rep->sparse_complex_matrix_value (frc_str_conv); }\n\n  SparseBoolMatrix sparse_bool_matrix_value (bool warn = false) const\n  { return m_rep->sparse_bool_matrix_value (warn); }\n\n  DiagMatrix diag_matrix_value (bool force = false) const\n  { return m_rep->diag_matrix_value (force); }\n\n  FloatDiagMatrix float_diag_matrix_value (bool force = false) const\n  { return m_rep->float_diag_matrix_value (force); }\n\n  ComplexDiagMatrix complex_diag_matrix_value (bool force = false) const\n  { return m_rep->complex_diag_matrix_value (force); }\n\n  FloatComplexDiagMatrix\n  float_complex_diag_matrix_value (bool force = false) const\n  { return m_rep->float_complex_diag_matrix_value (force); }\n\n  PermMatrix perm_matrix_value () const\n  { return m_rep->perm_matrix_value (); }\n\n  octave_int8 int8_scalar_value () const\n  { return m_rep->int8_scalar_value (); }\n\n  octave_int16 int16_scalar_value () const\n  { return m_rep->int16_scalar_value (); }\n\n  octave_int32 int32_scalar_value () const\n  { return m_rep->int32_scalar_value (); }\n\n  octave_int64 int64_scalar_value () const\n  { return m_rep->int64_scalar_value (); }\n\n  octave_uint8 uint8_scalar_value () const\n  { return m_rep->uint8_scalar_value (); }\n\n  octave_uint16 uint16_scalar_value () const\n  { return m_rep->uint16_scalar_value (); }\n\n  octave_uint32 uint32_scalar_value () const\n  { return m_rep->uint32_scalar_value (); }\n\n  octave_uint64 uint64_scalar_value () const\n  { return m_rep->uint64_scalar_value (); }\n\n  int8NDArray int8_array_value () const\n  { return m_rep->int8_array_value (); }\n\n  int16NDArray int16_array_value () const\n  { return m_rep->int16_array_value (); }\n\n  int32NDArray int32_array_value () const\n  { return m_rep->int32_array_value (); }\n\n  int64NDArray int64_array_value () const\n  { return m_rep->int64_array_value (); }\n\n  uint8NDArray uint8_array_value () const\n  { return m_rep->uint8_array_value (); }\n\n  uint16NDArray uint16_array_value () const\n  { return m_rep->uint16_array_value (); }\n\n  uint32NDArray uint32_array_value () const\n  { return m_rep->uint32_array_value (); }\n\n  uint64NDArray uint64_array_value () const\n  { return m_rep->uint64_array_value (); }\n\n  std::string string_value (bool force = false) const\n  { return m_rep->string_value (force); }\n\n  string_vector string_vector_value (bool pad = false) const\n  { return m_rep->string_vector_value (pad); }\n\n  Cell cell_value () const;\n\n  Array<std::string> cellstr_value () const\n  { return m_rep->cellstr_value (); }\n\n  octave::range<double> range_value () const\n  { return m_rep->range_value (); }\n\n  // For now, enable only range<double>.\n\n  OCTINTERP_API octave_map map_value () const;\n\n  OCTINTERP_API octave_scalar_map scalar_map_value () const;\n\n  string_vector map_keys () const\n  { return m_rep->map_keys (); }\n\n  bool isfield (const std::string& field_name) const\n  { return m_rep->isfield (field_name); }\n\n  std::size_t nparents () const\n  { return m_rep->nparents (); }\n\n  std::list<std::string> parent_class_name_list () const\n  { return m_rep->parent_class_name_list (); }\n\n  string_vector parent_class_names () const\n  { return m_rep->parent_class_names (); }\n\n  octave_base_value *\n  find_parent_class (const std::string& parent_class_name)\n  { return m_rep->find_parent_class (parent_class_name); }\n\n  bool is_instance_of (const std::string& cls_name) const\n  { return m_rep->is_instance_of (cls_name); }\n\n  OCTINTERP_API octave_classdef *\n  classdef_object_value (bool silent = false) const;\n\n  OCTINTERP_API octave_function *\n  function_value (bool silent = false) const;\n\n  OCTINTERP_API octave_user_function *\n  user_function_value (bool silent = false) const;\n\n  OCTINTERP_API octave_user_script *\n  user_script_value (bool silent = false) const;\n\n  OCTINTERP_API octave_user_code * user_code_value (bool silent = false) const;\n\n  OCTINTERP_API octave_fcn_handle *\n  fcn_handle_value (bool silent = false) const;\n\n  OCTINTERP_API octave_value_list list_value () const;\n\n  OCTINTERP_API ColumnVector\n  column_vector_value (bool frc_str_conv = false,\n                       bool frc_vec_conv = false) const;\n\n  OCTINTERP_API ComplexColumnVector\n  complex_column_vector_value (bool frc_str_conv = false,\n                               bool frc_vec_conv = false) const;\n\n  OCTINTERP_API RowVector\n  row_vector_value (bool frc_str_conv = false,\n                    bool frc_vec_conv = false) const;\n\n  OCTINTERP_API ComplexRowVector\n  complex_row_vector_value (bool frc_str_conv = false,\n                            bool frc_vec_conv = false) const;\n\n  OCTINTERP_API FloatColumnVector\n  float_column_vector_value (bool frc_str_conv = false,\n                             bool frc_vec_conv = false) const;\n\n  OCTINTERP_API FloatComplexColumnVector\n  float_complex_column_vector_value (bool frc_str_conv = false,\n                                     bool frc_vec_conv = false) const;\n\n  OCTINTERP_API FloatRowVector\n  float_row_vector_value (bool frc_str_conv = false,\n                          bool frc_vec_conv = false) const;\n\n  OCTINTERP_API FloatComplexRowVector\n  float_complex_row_vector_value (bool frc_str_conv = false,\n                                  bool frc_vec_conv = false) const;\n\n  OCTINTERP_API Array<int>\n  int_vector_value (bool req_int = false,\n                    bool frc_str_conv = false,\n                    bool frc_vec_conv = false) const;\n\n  OCTINTERP_API Array<octave_idx_type>\n  octave_idx_type_vector_value (bool req_int = false,\n                                bool frc_str_conv = false,\n                                bool frc_vec_conv = false) const;\n\n  OCTINTERP_API Array<double>\n  vector_value (bool frc_str_conv = false,\n                bool frc_vec_conv = false) const;\n\n  OCTINTERP_API Array<Complex>\n  complex_vector_value (bool frc_str_conv = false,\n                        bool frc_vec_conv = false) const;\n\n  OCTINTERP_API Array<float>\n  float_vector_value (bool frc_str_conv = false,\n                      bool frc_vec_conv = false) const;\n\n  OCTINTERP_API Array<FloatComplex>\n  float_complex_vector_value (bool frc_str_conv = false,\n                              bool frc_vec_conv = false) const;\n\n  // Extract values of specific types without any implicit type conversions.\n  // Throw an error if an object is the wrong type for the requested value\n  // extraction.\n  //\n  // These functions are intended to provide a simple way to extract values of\n  // specific types and display error messages that are more meaningful than\n  // the generic \"error: wrong type argument 'cell'\" message.\n\n  OCTINTERP_API short int xshort_value (const char *fmt, ...) const;\n\n  OCTINTERP_API unsigned short int xushort_value (const char *fmt, ...) const;\n\n  OCTINTERP_API int xint_value (const char *fmt, ...) const;\n\n  OCTINTERP_API int strict_int_value (const char *fmt, ...) const;\n\n  OCTINTERP_API unsigned int xuint_value (const char *fmt, ...) const;\n\n  OCTINTERP_API int xnint_value (const char *fmt, ...) const;\n\n  OCTINTERP_API long int xlong_value (const char *fmt, ...) const;\n\n  OCTINTERP_API unsigned long int xulong_value (const char *fmt, ...) const;\n\n  OCTINTERP_API int64_t xint64_value (const char *fmt, ...) const;\n\n  OCTINTERP_API uint64_t xuint64_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_idx_type xidx_type_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_idx_type strict_idx_type_value (const char *fmt, ...) const;\n\n  OCTINTERP_API double xdouble_value (const char *fmt, ...) const;\n\n  OCTINTERP_API float xfloat_value (const char *fmt, ...) const;\n\n  OCTINTERP_API double xscalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API float xfloat_scalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Matrix xmatrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatMatrix xfloat_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API NDArray xarray_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatNDArray xfloat_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Complex xcomplex_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatComplex xfloat_complex_value (const char *fmt, ...) const;\n\n  OCTINTERP_API ComplexMatrix\n  xcomplex_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatComplexMatrix\n  xfloat_complex_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API ComplexNDArray\n  xcomplex_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatComplexNDArray\n  xfloat_complex_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API bool xbool_value (const char *fmt, ...) const;\n\n  OCTINTERP_API bool strict_bool_value (const char *fmt, ...) const;\n\n  OCTINTERP_API boolMatrix xbool_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API boolNDArray xbool_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API charMatrix xchar_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API charNDArray xchar_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API SparseMatrix xsparse_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API SparseComplexMatrix\n  xsparse_complex_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API SparseBoolMatrix\n  xsparse_bool_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API DiagMatrix xdiag_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatDiagMatrix\n  xfloat_diag_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API ComplexDiagMatrix\n  xcomplex_diag_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatComplexDiagMatrix\n  xfloat_complex_diag_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API PermMatrix xperm_matrix_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_int8 xint8_scalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_int16 xint16_scalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_int32 xint32_scalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_int64 xint64_scalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_uint8 xuint8_scalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_uint16 xuint16_scalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_uint32 xuint32_scalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_uint64 xuint64_scalar_value (const char *fmt, ...) const;\n\n  OCTINTERP_API int8NDArray xint8_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API int16NDArray xint16_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API int32NDArray xint32_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API int64NDArray xint64_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API uint8NDArray xuint8_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API uint16NDArray xuint16_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API uint32NDArray xuint32_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API uint64NDArray xuint64_array_value (const char *fmt, ...) const;\n\n  OCTINTERP_API std::string xstring_value (const char *fmt, ...) const;\n\n  OCTINTERP_API string_vector xstring_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Cell xcell_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Array<std::string> xcellstr_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave::range<double>\n  xrange_value (const char *fmt, ...) const;\n\n  // For now, enable only range<double>.\n\n  OCTINTERP_API octave_map xmap_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_scalar_map\n  xscalar_map_value (const char *fmt, ...) const;\n\n  OCTINTERP_API ColumnVector xcolumn_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API ComplexColumnVector\n  xcomplex_column_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API RowVector xrow_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API ComplexRowVector\n  xcomplex_row_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatColumnVector\n  xfloat_column_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatComplexColumnVector\n  xfloat_complex_column_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatRowVector\n  xfloat_row_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API FloatComplexRowVector\n  xfloat_complex_row_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Array<int> xint_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Array<octave_idx_type>\n  xoctave_idx_type_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Array<double> xvector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Array<Complex>\n  xcomplex_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Array<float> xfloat_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API Array<FloatComplex>\n  xfloat_complex_vector_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_function * xfunction_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_user_function *\n  xuser_function_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_user_script *\n  xuser_script_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_user_code *\n  xuser_code_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_fcn_handle *\n  xfcn_handle_value (const char *fmt, ...) const;\n\n  OCTINTERP_API octave_value_list xlist_value (const char *fmt, ...) const;\n\n  // Possibly economize a lazy-indexed value.\n\n  void maybe_economize ()\n  { m_rep->maybe_economize (); }\n\n  // The following two hook conversions are called on any octave_value prior to\n  // storing it to a \"permanent\" location, like a named variable, a cell or a\n  // struct component, or a return value of a function.\n\n  OCTINTERP_API octave_value storable_value () const;\n\n  // Ditto, but in place, i.e., equivalent to *this = this->storable_value (),\n  // but possibly more efficient.\n\n  OCTINTERP_API void make_storable_value ();\n\n  // FIXME: These should probably be private.\n  // Conversions.  If a user of this class wants a certain kind of constant,\n  // he should simply ask for it, and we should convert it if possible.\n\n  octave_value convert_to_str (bool pad = false, bool force = false,\n                               char type = '\\'') const\n  { return m_rep->convert_to_str (pad, force, type); }\n\n  octave_value\n  convert_to_str_internal (bool pad, bool force, char type) const\n  { return m_rep->convert_to_str_internal (pad, force, type); }\n\n  void convert_to_row_or_column_vector ()\n  { m_rep->convert_to_row_or_column_vector (); }\n\n  bool print_as_scalar () const\n  { return m_rep->print_as_scalar (); }\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false)\n  { m_rep->print (os, pr_as_read_syntax); }\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const\n  { m_rep->print_raw (os, pr_as_read_syntax); }\n\n  bool print_name_tag (std::ostream& os, const std::string& name) const\n  { return m_rep->print_name_tag (os, name); }\n\n  void print_with_name (std::ostream& os, const std::string& name) const\n  { m_rep->print_with_name (os, name, true); }\n\n  void short_disp (std::ostream& os) const { m_rep->short_disp (os); }\n\n  OCTINTERP_API float_display_format get_edit_display_format () const;\n\n  std::string edit_display (const float_display_format& fmt,\n                            octave_idx_type i, octave_idx_type j) const\n  {\n    return m_rep->edit_display (fmt, i, j);\n  }\n\n  int type_id () const { return m_rep->type_id (); }\n\n  std::string type_name () const { return m_rep->type_name (); }\n\n  std::string class_name () const { return m_rep->class_name (); }\n\n  // Unary operations that are member functions.  There are also some\n  // non-member functions for unary and binary operations declared\n  // below, outside of the octave_value class declaration.\n\n  OCTINTERP_API octave_value& non_const_unary_op (unary_op op);\n\n  OCTINTERP_API octave_value&\n  non_const_unary_op (unary_op op, const std::string& type,\n                      const std::list<octave_value_list>& idx);\n\n  const octave_base_value& get_rep () const { return *m_rep; }\n\n  bool is_copy_of (const octave_value& val) const { return m_rep == val.m_rep; }\n\n  OCTINTERP_API void\n  print_info (std::ostream& os, const std::string& prefix = \"\") const;\n\n  bool save_ascii (std::ostream& os) { return m_rep->save_ascii (os); }\n\n  OCTINTERP_API bool load_ascii (std::istream& is);\n\n  bool save_binary (std::ostream& os, bool save_as_floats)\n  { return m_rep->save_binary (os, save_as_floats); }\n\n  OCTINTERP_API bool load_binary (std::istream& is, bool swap,\n                                  octave::mach_info::float_format fmt);\n\n  bool save_hdf5 (octave_hdf5_id loc_id, const char *name,\n                  bool save_as_floats)\n  { return m_rep->save_hdf5 (loc_id, name, save_as_floats); }\n\n  OCTINTERP_API bool load_hdf5 (octave_hdf5_id loc_id, const char *name);\n\n  OCTINTERP_API int\n  write (octave::stream& os, int block_size,\n         oct_data_conv::data_type output_type, int skip,\n         octave::mach_info::float_format flt_fmt) const;\n\n  octave_base_value * internal_rep () const { return m_rep; }\n\n  // These functions exist to support the MEX interface.\n  // You should not use them anywhere else.\n\n  OCTINTERP_API const void *\n  mex_get_data (mxClassID class_id = mxUNKNOWN_CLASS,\n                mxComplexity complexity = mxREAL) const;\n\n  const octave_idx_type * mex_get_ir () const\n  {\n    return m_rep->mex_get_ir ();\n  }\n\n  const octave_idx_type *\n  mex_get_jc () const\n  {\n    return m_rep->mex_get_jc ();\n  }\n\n  mxArray * as_mxArray (bool interleaved = false) const\n  { return m_rep->as_mxArray (interleaved); }\n\n  octave_value diag (octave_idx_type k = 0) const\n  { return m_rep->diag (k); }\n\n  octave_value diag (octave_idx_type m, octave_idx_type n) const\n  { return m_rep->diag (m, n); }\n\n  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const\n  { return m_rep->sort (dim, mode); }\n  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n                     sortmode mode = ASCENDING) const\n  { return m_rep->sort (sidx, dim, mode); }\n\n  sortmode issorted (sortmode mode = UNSORTED) const\n  { return m_rep->issorted (mode); }\n\n  Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const\n  { return m_rep->sort_rows_idx (mode); }\n\n  sortmode is_sorted_rows (sortmode mode = UNSORTED) const\n  { return m_rep->is_sorted_rows (mode); }\n\n  void lock () { m_rep->lock (); }\n\n  void unlock () { m_rep->unlock (); }\n\n  bool islocked () const { return m_rep->islocked (); }\n\n  void call_object_destructor () { return m_rep->call_object_destructor (); }\n\n  octave_value dump () const { return m_rep->dump (); }\n\n#define MAPPER_FORWARD(F) \\\n  octave_value F () const                           \\\n  {                                                     \\\n    return m_rep->map (octave_base_value::umap_ ## F);    \\\n  }\n\n  MAPPER_FORWARD (abs)\n  MAPPER_FORWARD (acos)\n  MAPPER_FORWARD (acosh)\n  MAPPER_FORWARD (angle)\n  MAPPER_FORWARD (arg)\n  MAPPER_FORWARD (asin)\n  MAPPER_FORWARD (asinh)\n  MAPPER_FORWARD (atan)\n  MAPPER_FORWARD (atanh)\n  MAPPER_FORWARD (cbrt)\n  MAPPER_FORWARD (ceil)\n  MAPPER_FORWARD (conj)\n  MAPPER_FORWARD (cos)\n  MAPPER_FORWARD (cosh)\n  MAPPER_FORWARD (erf)\n  MAPPER_FORWARD (erfinv)\n  MAPPER_FORWARD (erfcinv)\n  MAPPER_FORWARD (erfc)\n  MAPPER_FORWARD (erfcx)\n  MAPPER_FORWARD (erfi)\n  MAPPER_FORWARD (dawson)\n  MAPPER_FORWARD (exp)\n  MAPPER_FORWARD (expm1)\n  MAPPER_FORWARD (isfinite)\n  MAPPER_FORWARD (fix)\n  MAPPER_FORWARD (floor)\n  MAPPER_FORWARD (gamma)\n  MAPPER_FORWARD (imag)\n  MAPPER_FORWARD (isinf)\n  MAPPER_FORWARD (isna)\n  MAPPER_FORWARD (isnan)\n  MAPPER_FORWARD (lgamma)\n  MAPPER_FORWARD (log)\n  MAPPER_FORWARD (log2)\n  MAPPER_FORWARD (log10)\n  MAPPER_FORWARD (log1p)\n  MAPPER_FORWARD (real)\n  MAPPER_FORWARD (round)\n  MAPPER_FORWARD (roundb)\n  MAPPER_FORWARD (signum)\n  MAPPER_FORWARD (sin)\n  MAPPER_FORWARD (sinh)\n  MAPPER_FORWARD (sqrt)\n  MAPPER_FORWARD (tan)\n  MAPPER_FORWARD (tanh)\n\n  // These functions are prefixed with X to avoid potential macro conflicts.\n\n  MAPPER_FORWARD (xisalnum)\n  MAPPER_FORWARD (xisalpha)\n  MAPPER_FORWARD (xisascii)\n  MAPPER_FORWARD (xiscntrl)\n  MAPPER_FORWARD (xisdigit)\n  MAPPER_FORWARD (xisgraph)\n  MAPPER_FORWARD (xislower)\n  MAPPER_FORWARD (xisprint)\n  MAPPER_FORWARD (xispunct)\n  MAPPER_FORWARD (xisspace)\n  MAPPER_FORWARD (xisupper)\n  MAPPER_FORWARD (xisxdigit)\n  MAPPER_FORWARD (xsignbit)\n  MAPPER_FORWARD (xtolower)\n  MAPPER_FORWARD (xtoupper)\n\n#undef MAPPER_FORWARD\n\n  octave_value map (octave_base_value::unary_mapper_t umap) const\n  { return m_rep->map (umap); }\n\n  //! Extract the n-th element, aka 'val(n)'.\n  //!\n  //! @return Result is undefined if 'val' is not an array type\n  //!         or @p n is out of range.\n  //!\n  //! @warning Function calls should never error.\n\n  octave_value\n  fast_elem_extract (octave_idx_type n) const\n  { return m_rep->fast_elem_extract (n); }\n\n  //! Assign the n-th element, aka 'val(n) = x'.\n  //!\n  //! @returns false if 'val' is not an array type,\n  //!          @p x is not a matching scalar type,\n  //!          or @p n is out of range.\n  //!\n  //! @warning Function calls should never error.\n\n  bool\n  fast_elem_insert (octave_idx_type n, const octave_value& x)\n  {\n    make_unique ();\n    return m_rep->fast_elem_insert (n, x);\n  }\n\nprotected:\n\n  //! The real representation.\n  octave_base_value *m_rep;\n\n  static OCTINTERP_API octave_base_value * nil_rep ();\n\nprivate:\n\n  OCTINTERP_API assign_op unary_op_to_assign_op (unary_op op);\n\n  OCTINTERP_API binary_op op_eq_to_binary_op (assign_op op);\n\n  // This declaration protects against constructing octave_value from\n  // const octave_base_value* which actually silently calls octave_value (bool).\n  OCTINTERP_API octave_value (const octave_base_value *);\n\n};\n\n// Non-member unary and binary operations on octave_value objects.\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTINTERP_API octave_value\nunary_op (type_info& ti, octave_value::unary_op op,\n          const octave_value& a);\n\nextern OCTINTERP_API octave_value\nunary_op (octave_value::unary_op op, const octave_value& a);\n\nextern OCTINTERP_API octave_value\nbinary_op (type_info& ti, octave_value::binary_op op,\n           const octave_value& a, const octave_value& b);\n\nextern OCTINTERP_API octave_value\nbinary_op (type_info& ti, octave_value::compound_binary_op op,\n           const octave_value& a, const octave_value& b);\n\nextern OCTINTERP_API octave_value\nbinary_op (octave_value::binary_op op, const octave_value& a,\n           const octave_value& b);\n\nextern OCTINTERP_API octave_value\nbinary_op (octave_value::compound_binary_op op, const octave_value& a,\n           const octave_value& b);\n\nextern OCTINTERP_API octave_value\ncat_op (type_info& ti, const octave_value& a,\n        const octave_value& b, const Array<octave_idx_type>& ra_idx);\n\nextern OCTINTERP_API octave_value\ncat_op (const octave_value& a, const octave_value& b,\n        const Array<octave_idx_type>& ra_idx);\n\nextern OCTINTERP_API octave_value\ncolon_op (const octave_value& base, const octave_value& increment,\n          const octave_value& limit, bool is_for_cmd_expr = false);\n\ninline octave_value\ncolon_op (const octave_value& base, const octave_value& limit,\n          bool is_for_cmd_expr = false)\n{\n  // Note, we need to pass an undefined octave_value object instead of\n  // octave_value (1.0) so that we can properly detect the\n  // two-argument case and correctly pass just two arguments to any\n  // user-defined function that is provided if either base or limit is\n  // an object.\n\n  return colon_op (base, octave_value (), limit, is_for_cmd_expr);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#define OV_UNOP_FN(name)                                \\\n  inline octave_value                                   \\\n  name (const octave_value& a)                          \\\n  {                                                     \\\n    return octave::unary_op (octave_value::name, a);    \\\n  }\n\n#define OV_UNOP_OP(name, op)                    \\\n  inline octave_value                           \\\n  operator op (const octave_value& a)           \\\n  {                                             \\\n    return name (a);                            \\\n  }\n\n#define OV_UNOP_FN_OP(name, op)                 \\\n  OV_UNOP_FN (name)                             \\\n  OV_UNOP_OP (name, op)\n\nOV_UNOP_FN_OP (op_not, !)\nOV_UNOP_FN_OP (op_uplus, +)\nOV_UNOP_FN_OP (op_uminus, -)\n\nOV_UNOP_FN (op_transpose)\nOV_UNOP_FN (op_hermitian)\n\n// No simple way to define these for prefix and suffix ops?\n//\n//   incr\n//   decr\n\n#define OV_BINOP_FN(name)                                       \\\n  inline octave_value                                           \\\n  name (const octave_value& a1, const octave_value& a2)         \\\n  {                                                             \\\n    return octave::binary_op (octave_value::name, a1, a2);      \\\n  }\n\n#define OV_BINOP_OP(name, op)                                   \\\n  inline octave_value                                           \\\n  operator op (const octave_value& a1, const octave_value& a2)  \\\n  {                                                             \\\n    return name (a1, a2);                                       \\\n  }\n\n#define OV_BINOP_FN_OP(name, op)                \\\n  OV_BINOP_FN (name)                            \\\n  OV_BINOP_OP (name, op)\n\nOV_BINOP_FN_OP (op_add, +)\nOV_BINOP_FN_OP (op_sub, -)\nOV_BINOP_FN_OP (op_mul, *)\nOV_BINOP_FN_OP (op_div, /)\n\nOV_BINOP_FN (op_pow)\nOV_BINOP_FN (op_ldiv)\n\nOV_BINOP_FN_OP (op_lt, <)\nOV_BINOP_FN_OP (op_le, <=)\nOV_BINOP_FN_OP (op_eq, ==)\nOV_BINOP_FN_OP (op_ge, >=)\nOV_BINOP_FN_OP (op_gt, >)\nOV_BINOP_FN_OP (op_ne, !=)\n\nOV_BINOP_FN (op_el_mul)\nOV_BINOP_FN (op_el_div)\nOV_BINOP_FN (op_el_pow)\nOV_BINOP_FN (op_el_ldiv)\nOV_BINOP_FN (op_el_and)\nOV_BINOP_FN (op_el_or)\n\nOV_BINOP_FN (op_struct_ref)\n\n#define OV_COMP_BINOP_FN(name)                                  \\\n  inline octave_value                                           \\\n  name (const octave_value& a1, const octave_value& a2)         \\\n  {                                                             \\\n    return octave::binary_op (octave_value::name, a1, a2);      \\\n  }\n\nOV_COMP_BINOP_FN (op_trans_mul)\nOV_COMP_BINOP_FN (op_mul_trans)\nOV_COMP_BINOP_FN (op_herm_mul)\nOV_COMP_BINOP_FN (op_mul_herm)\n\nextern OCTINTERP_API void install_types (octave::type_info&);\n\n// Templated value extractors.\n\ntemplate <typename Value>\ninline Value octave_value_extract (const octave_value&)\n{\n  // We can't include error.h in ov.h.  Is there anything better than\n  // panic_impossible that we can do here?\n\n  panic_impossible ();\n}\n\n#define DEF_VALUE_EXTRACTOR(VALUE,MPREFIX)                              \\\n  template <>                                                           \\\n  inline VALUE octave_value_extract<VALUE> (const octave_value& v)      \\\n  {                                                                     \\\n    return v.MPREFIX ## _value ();                                      \\\n  }\n\nDEF_VALUE_EXTRACTOR (double, scalar)\nDEF_VALUE_EXTRACTOR (float, float_scalar)\nDEF_VALUE_EXTRACTOR (Complex, complex)\nDEF_VALUE_EXTRACTOR (FloatComplex, float_complex)\nDEF_VALUE_EXTRACTOR (bool, bool)\n\nDEF_VALUE_EXTRACTOR (octave_int8, int8_scalar)\nDEF_VALUE_EXTRACTOR (octave_int16, int16_scalar)\nDEF_VALUE_EXTRACTOR (octave_int32, int32_scalar)\nDEF_VALUE_EXTRACTOR (octave_int64, int64_scalar)\nDEF_VALUE_EXTRACTOR (octave_uint8, uint8_scalar)\nDEF_VALUE_EXTRACTOR (octave_uint16, uint16_scalar)\nDEF_VALUE_EXTRACTOR (octave_uint32, uint32_scalar)\nDEF_VALUE_EXTRACTOR (octave_uint64, uint64_scalar)\n\nDEF_VALUE_EXTRACTOR (NDArray, array)\nDEF_VALUE_EXTRACTOR (FloatNDArray, float_array)\nDEF_VALUE_EXTRACTOR (ComplexNDArray, complex_array)\nDEF_VALUE_EXTRACTOR (FloatComplexNDArray, float_complex_array)\nDEF_VALUE_EXTRACTOR (boolNDArray, bool_array)\n\nDEF_VALUE_EXTRACTOR (charNDArray, char_array)\nDEF_VALUE_EXTRACTOR (int8NDArray, int8_array)\nDEF_VALUE_EXTRACTOR (int16NDArray, int16_array)\nDEF_VALUE_EXTRACTOR (int32NDArray, int32_array)\nDEF_VALUE_EXTRACTOR (int64NDArray, int64_array)\nDEF_VALUE_EXTRACTOR (uint8NDArray, uint8_array)\nDEF_VALUE_EXTRACTOR (uint16NDArray, uint16_array)\nDEF_VALUE_EXTRACTOR (uint32NDArray, uint32_array)\nDEF_VALUE_EXTRACTOR (uint64NDArray, uint64_array)\n\nDEF_VALUE_EXTRACTOR (Matrix, matrix)\nDEF_VALUE_EXTRACTOR (FloatMatrix, float_matrix)\nDEF_VALUE_EXTRACTOR (ComplexMatrix, complex_matrix)\nDEF_VALUE_EXTRACTOR (FloatComplexMatrix, float_complex_matrix)\nDEF_VALUE_EXTRACTOR (boolMatrix, bool_matrix)\n\nDEF_VALUE_EXTRACTOR (ColumnVector, column_vector)\nDEF_VALUE_EXTRACTOR (FloatColumnVector, float_column_vector)\nDEF_VALUE_EXTRACTOR (ComplexColumnVector, complex_column_vector)\nDEF_VALUE_EXTRACTOR (FloatComplexColumnVector, float_complex_column_vector)\n\nDEF_VALUE_EXTRACTOR (RowVector, row_vector)\nDEF_VALUE_EXTRACTOR (FloatRowVector, float_row_vector)\nDEF_VALUE_EXTRACTOR (ComplexRowVector, complex_row_vector)\nDEF_VALUE_EXTRACTOR (FloatComplexRowVector, float_complex_row_vector)\n\nDEF_VALUE_EXTRACTOR (DiagMatrix, diag_matrix)\nDEF_VALUE_EXTRACTOR (FloatDiagMatrix, float_diag_matrix)\nDEF_VALUE_EXTRACTOR (ComplexDiagMatrix, complex_diag_matrix)\nDEF_VALUE_EXTRACTOR (FloatComplexDiagMatrix, float_complex_diag_matrix)\nDEF_VALUE_EXTRACTOR (PermMatrix, perm_matrix)\n\nDEF_VALUE_EXTRACTOR (SparseMatrix, sparse_matrix)\nDEF_VALUE_EXTRACTOR (SparseComplexMatrix, sparse_complex_matrix)\nDEF_VALUE_EXTRACTOR (SparseBoolMatrix, sparse_bool_matrix)\n#undef DEF_VALUE_EXTRACTOR\n\n// We can't include error.h in ov.h.  Is there anything better than\n// panic_impossible that we can do here?\n\n#define DEF_DUMMY_VALUE_EXTRACTOR(VALUE,DEFVAL)                         \\\n  template <>                                                           \\\n  inline VALUE octave_value_extract<VALUE> (const octave_value&)        \\\n  {                                                                     \\\n    panic_impossible ();                                                \\\n    return DEFVAL;                                                      \\\n  }\n\nDEF_DUMMY_VALUE_EXTRACTOR (char, 0)\nDEF_DUMMY_VALUE_EXTRACTOR (octave_value, octave_value ())\n#undef DEF_DUMMY_VALUE_EXTRACTOR\n\n#endif\n"
  },
  {
    "path": "libinterp/octave-value/ovl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"ovl.h\"\n\n// We are likely to have a lot of octave_value_list objects to allocate,\n// so make the grow_size large.\n\noctave_value_list::octave_value_list (const std::list<octave_value>& lst)\n{\n  std::size_t nel = lst.size ();\n\n  if (nel > 0)\n    {\n      m_data.resize (nel);\n      octave_idx_type k = 0;\n      for (const auto& ov : lst)\n        m_data[k++] = ov;\n    }\n}\n\noctave_value_list::octave_value_list (const std::list<octave_value_list>& lst)\n{\n  octave_idx_type n = 0;\n  octave_idx_type nel = 0;\n\n  // Determine number.\n  for (const auto& ovl : lst)\n    {\n      n++;\n      nel += ovl.length ();\n    }\n\n  // Optimize single-element case\n  if (n == 1)\n    m_data = lst.front ().m_data;\n  else if (nel > 0)\n    {\n      m_data.resize (nel);\n      octave_idx_type k = 0;\n      for (const auto& ovl : lst)\n        {\n          for (octave_idx_type i = 0; i < ovl.length (); i++)\n            m_data[k++] = ovl(i);\n        }\n\n      panic_unless (k == nel);\n    }\n\n}\n\noctave_value_list&\noctave_value_list::prepend (const octave_value& val)\n{\n  octave_idx_type n = length ();\n\n  resize (n + 1);\n\n  while (n > 0)\n    {\n      elem (n) = elem (n - 1);\n      n--;\n    }\n\n  elem (0) = val;\n\n  return *this;\n}\n\noctave_value_list&\noctave_value_list::append (const octave_value& val)\n{\n  octave_idx_type n = length ();\n\n  resize (n + 1);\n\n  elem (n) = val;\n\n  return *this;\n}\n\noctave_value_list&\noctave_value_list::append (const octave_value_list& lst)\n{\n  octave_idx_type len = length ();\n  octave_idx_type lst_len = lst.length ();\n\n  resize (len + lst_len);\n\n  for (octave_idx_type i = 0; i < lst_len; i++)\n    elem (len + i) = lst (i);\n\n  return *this;\n}\n\noctave_value_list&\noctave_value_list::reverse ()\n{\n  octave_idx_type n = length ();\n\n  for (octave_idx_type i = 0; i < n / 2; i++)\n    {\n      octave_value tmp = elem (i);\n      elem (i) = elem (n - i - 1);\n      elem (n - i - 1) = tmp;\n    }\n\n  return *this;\n}\n\noctave_value_list\noctave_value_list::splice (octave_idx_type offset, octave_idx_type rep_length,\n                           const octave_value_list& lst) const\n{\n  octave_value_list retval;\n\n  octave_idx_type len = length ();\n\n  if (offset < 0 || offset >= len)\n    {\n      if (! (rep_length == 0 && offset == len))\n        error (\"octave_value_list::splice: invalid OFFSET\");\n    }\n\n  if (rep_length < 0 || rep_length + offset > len)\n    error (\"octave_value_list::splice: invalid LENGTH\");\n\n  octave_idx_type lst_len = lst.length ();\n\n  octave_idx_type new_len = len - rep_length + lst_len;\n\n  retval.resize (new_len);\n\n  octave_idx_type k = 0;\n\n  for (octave_idx_type i = 0; i < offset; i++)\n    retval(k++) = elem (i);\n\n  for (octave_idx_type i = 0; i < lst_len; i++)\n    retval(k++) = lst (i);\n\n  for (octave_idx_type i = offset + rep_length; i < len; i++)\n    retval(k++) = elem (i);\n\n  return retval;\n}\n\nbool\noctave_value_list::all_strings_p () const\n{\n  octave_idx_type n = length ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    if (! elem(i).is_string ())\n      return false;\n\n  return true;\n}\n\nbool\noctave_value_list::all_scalars () const\n{\n  octave_idx_type n = length ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      const dim_vector& dv = elem(i).dims ();\n      if (! dv.all_ones ())\n        return false;\n    }\n\n  return true;\n}\n\nbool\noctave_value_list::any_cell () const\n{\n  octave_idx_type n = length ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    if (elem (i).iscell ())\n      return true;\n\n  return false;\n}\n\nbool\noctave_value_list::has_magic_colon () const\n{\n  octave_idx_type n = length ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    if (elem(i).is_magic_colon ())\n      return true;\n\n  return false;\n}\n\nstring_vector\noctave_value_list::make_argv (const std::string& fcn_name) const\n{\n  string_vector argv;\n\n  if (! all_strings_p ())\n    error (\"%s: all arguments must be strings\", fcn_name.c_str ());\n\n  octave_idx_type len = length ();\n\n  octave_idx_type total_nr = 0;\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      // An empty std::string (\"\") has zero columns and zero rows\n      // (a change that was made for Matlab contemptibility.\n\n      octave_idx_type n = elem (i).rows ();\n\n      total_nr += n ? n : 1;\n    }\n\n  octave_idx_type k = 0;\n  if (! fcn_name.empty ())\n    {\n      argv.resize (total_nr+1);\n      argv[0] = fcn_name;\n      k = 1;\n    }\n  else\n    argv.resize (total_nr);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      octave_idx_type nr = elem (i).rows ();\n\n      if (nr < 2)\n        argv[k++] = elem (i).string_value ();\n      else\n        {\n          string_vector tmp = elem (i).string_vector_value ();\n\n          for (octave_idx_type j = 0; j < nr; j++)\n            argv[k++] = tmp[j];\n        }\n    }\n\n  return argv;\n}\n\nvoid\noctave_value_list::make_storable_values ()\n{\n  octave_idx_type len = length ();\n  const std::vector<octave_value>& cdata = m_data;\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      // This is optimized so that we don't force a copy unless necessary.\n      octave_value tmp = cdata[i].storable_value ();\n      if (! tmp.is_copy_of (cdata[i]))\n        m_data[i] = tmp;\n    }\n}\n"
  },
  {
    "path": "libinterp/octave-value/ovl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ovl_h)\n#define octave_ovl_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n#include <vector>\n#include <initializer_list>\n\n#include \"str-vec.h\"\n#include \"Array.h\"\n\n#include \"ov.h\"\n#include \"Cell.h\"\n\nclass OCTINTERP_API octave_value_list\n{\npublic:\n\n  octave_value_list () = default;\n\n  explicit octave_value_list (octave_idx_type n)\n    : m_data (n), m_names () { }\n\n  octave_value_list (octave_idx_type n, const octave_value& val)\n    : m_data (n, val), m_names () { }\n\n  octave_value_list (const octave_value& tc)\n    : m_data (1, tc), m_names () { }\n\n  template<template <typename...> class OV_Container>\n  octave_value_list (const OV_Container<octave_value>& args)\n    : m_data (args.begin (), args.end ()), m_names () { }\n\n  octave_value_list (const Array<octave_value>& a)\n    : m_data (a.numel ()), m_names ()\n  {\n    for (octave_idx_type i = 0; i < a.numel (); i++)\n      m_data[i] = a(i);\n  }\n\n  octave_value_list (const Cell& c)\n    : m_data (c.numel ()), m_names ()\n  {\n    for (octave_idx_type i = 0; i < c.numel (); i++)\n      m_data[i] = c(i);\n  }\n\n  octave_value_list (const octave_value_list& obj) = default;\n\n  octave_value_list (octave_value_list&& obj) = default;\n\n  // Concatenation constructors.\n  octave_value_list (const std::list<octave_value>&);\n  octave_value_list (const std::list<octave_value_list>&);\n\n  ~octave_value_list () = default;\n\n  octave_value_list& operator = (const octave_value_list& obj) = default;\n\n  octave_value_list& operator = (octave_value_list&& obj) = default;\n\n  Array<octave_value> array_value () const\n  {\n    Array<octave_value> retval;\n\n    if (! m_data.empty ())\n      {\n        retval.resize (dim_vector (1, length ()));\n\n        for (octave_idx_type i = 0; i < retval.numel (); i++)\n          retval.xelem (i) = m_data[i];\n      }\n\n    return retval;\n  }\n\n  Cell cell_value () const { return array_value (); }\n\n  // Assignment will resize on range errors.\n\n  octave_value& operator () (octave_idx_type n) { return elem (n); }\n\n  const octave_value& operator () (octave_idx_type n) const { return elem (n); }\n\n  octave_idx_type length () const { return m_data.size (); }\n\n  bool empty () const { return length () == 0; }\n\n  void resize (octave_idx_type n, const octave_value& rfv = octave_value ())\n  {\n    m_data.resize (n, rfv);\n  }\n\n  octave_value_list& prepend (const octave_value& val);\n\n  octave_value_list& append (const octave_value& val);\n\n  octave_value_list& append (const octave_value_list& lst);\n\n  octave_value_list& reverse ();\n\n  octave_value_list\n  slice (octave_idx_type offset, octave_idx_type len, bool tags = false) const\n  {\n    // linear_slice uses begin/end indices instead of offset and length.\n    // Avoid calling with upper bound out of range.\n\n    octave_idx_type tlen = len > 0 ? len : 0;\n    std::vector<octave_value> slice_data (tlen);\n    auto beg = m_data.begin () + offset;\n    auto end = beg + len;\n    std::copy (beg, end, slice_data.begin ());\n\n    octave_value_list retval = slice_data;\n\n    if (tags && len > 0 && m_names.numel () > 0)\n      retval.m_names = m_names.linear_slice (offset, std::min (offset + len,\n                                             m_names.numel ()));\n\n    return retval;\n  }\n\n  octave_value_list\n  splice (octave_idx_type offset, octave_idx_type len,\n          const octave_value_list& lst = octave_value_list ()) const;\n\n  bool all_strings_p () const;\n\n  bool all_scalars () const;\n\n  bool any_cell () const;\n\n  bool has_magic_colon () const;\n\n  string_vector make_argv (const std::string& = \"\") const;\n\n  void stash_name_tags (const string_vector& nm) { m_names = nm; }\n\n  string_vector name_tags () const { return m_names; }\n\n  void make_storable_values ();\n\n  octave_value& xelem (octave_idx_type i) { return m_data[i]; }\n\n  void clear () { m_data.clear (); }\n\n  octave_value first_or_nil_ov () const\n  {\n    if (length ())\n      return m_data.front ();\n\n    return octave_value ();\n  }\n\nprivate:\n\n  std::vector<octave_value> m_data;\n\n  // The list of strings can be used to tag each element of m_data with a name.\n  // By default, it is empty.\n  string_vector m_names;\n\n  // elem will automatically resize array for out-of-bounds requests.\n  octave_value& elem (octave_idx_type n)\n  {\n    if (n >= length ())\n      resize (n + 1);\n\n    return m_data[n];\n  }\n\n  const octave_value& elem (octave_idx_type n) const { return m_data[n]; }\n\n};\n\n\n//! Construct an octave_value_list with less typing.\n//!\n//! Historically, this made it easier to create an octave_value_list\n//! from multiple octave_value arguments.  It is no longer useful since\n//! octave_value_list has now a constructor accepting an initializer_list\n//! so all it does is save some typing.  The following are equivalent:\n//!\n//! @code{.cc}\n//! return octave_value_list ({ov0, ov1, ov2});\n//! return ovl (ov0, ov1, ov2);\n//! @endcode\n\ntemplate<typename... OV_Args>\ninline octave_value_list\novl (const OV_Args& ... args)\n{\n  return octave_value_list (std::initializer_list<octave_value> ({args...}));\n}\n\n#endif\n"
  },
  {
    "path": "libinterp/octave.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Born February 20, 1992.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n\n#include <iostream>\n#include <string>\n\n#include \"file-ops.h\"\n#include \"getopt-wrapper.h\"\n#include \"oct-env.h\"\n#include \"oct-error.h\"\n#include \"str-vec.h\"\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"display.h\"\n#include \"error.h\"\n#include \"input.h\"\n#include \"interpreter.h\"\n#include \"octave.h\"\n#include \"oct-hist.h\"\n#include \"oct-map.h\"\n#include \"ovl.h\"\n#include \"options.h\"\n#include \"ov.h\"\n#include \"parse.h\"\n#include \"sysdep.h\"\n#include \"usage.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ncmdline_options::cmdline_options ()\n{\n  m_all_args.resize (1);\n  m_all_args[0] = \"\";\n}\n\ncmdline_options::cmdline_options (int argc, char **argv)\n{\n  // Save raw program arguments.\n  m_all_args = string_vector (argv, argc);\n\n  while (true)\n    {\n      int long_idx;\n\n      int optc = octave_getopt_long_wrapper (argc, argv, short_opts,\n                                             long_opts, &long_idx);\n\n      if (optc < 0)\n        break;\n\n      switch (optc)\n        {\n        case '?':\n          // Unrecognized option.  getopt_long already printed a message about\n          // it, so we will just print the usage string and exit.\n          octave_print_terse_usage_and_exit ();\n          break;\n\n        case 'G':\n          m_gui = false;\n          break;\n\n        case 'H':\n          m_read_history_file = false;\n          break;\n\n        case 'W':\n          m_no_window_system = true;\n          break;\n\n        case 'V':\n          m_init_trace = true;\n          break;\n\n        // FIXME: Disabled debug option for parser 2023-12-29.\n        // However, uncomment and restore option if Octave adds a debug option\n        // to immediately enter debug mode for a script.\n        // case 'd':\n        //   break;\n\n        case 'e':\n          if (octave_optarg_wrapper ())\n            {\n              if (m_code_to_eval.empty ())\n                m_code_to_eval = octave_optarg_wrapper ();\n              else\n                m_code_to_eval += (std::string (\" \")\n                                   + octave_optarg_wrapper ());\n            }\n          break;\n\n        case 'f':\n          m_read_user_files = false;\n          m_read_site_files = false;\n          break;\n\n        case 'g':\n          m_gui = true;\n          break;\n\n        case 'h':\n          octave_print_verbose_usage_and_exit ();\n          break;\n\n        case 'i':\n          m_forced_interactive = true;\n          break;\n\n        case 'p':\n          if (octave_optarg_wrapper ())\n            m_command_line_path.push_back (octave_optarg_wrapper ());\n          break;\n\n        case 'q':\n          m_inhibit_startup_message = true;\n          break;\n\n        case 'x':\n          m_echo_commands = true;\n          break;\n\n        case 'v':\n          octave_print_version_and_exit ();\n          break;\n\n        case BUILT_IN_DOCSTRINGS_FILE_OPTION:\n          if (octave_optarg_wrapper ())\n            m_docstrings_file = octave_optarg_wrapper ();\n          break;\n\n        case DOC_CACHE_FILE_OPTION:\n          if (octave_optarg_wrapper ())\n            m_doc_cache_file = octave_optarg_wrapper ();\n          break;\n\n        case EXEC_PATH_OPTION:\n          if (octave_optarg_wrapper ())\n            m_exec_path = octave_optarg_wrapper ();\n          break;\n\n        case EXPERIMENTAL_TERMINAL_WIDGET_OPTION:\n#if defined (HAVE_QSCINTILLA)\n          m_experimental_terminal_widget = true;\n#endif\n          break;\n\n        case IMAGE_PATH_OPTION:\n          if (octave_optarg_wrapper ())\n            m_image_path = octave_optarg_wrapper ();\n          break;\n\n        case INFO_FILE_OPTION:\n          if (octave_optarg_wrapper ())\n            m_info_file = octave_optarg_wrapper ();\n          break;\n\n        case INFO_PROG_OPTION:\n          if (octave_optarg_wrapper ())\n            m_info_program = octave_optarg_wrapper ();\n          break;\n\n        case LINE_EDITING_OPTION:\n          m_forced_line_editing = m_line_editing = true;\n          break;\n\n        case NO_INIT_USER_OPTION:\n          m_read_user_files = false;\n          break;\n\n        case NO_INIT_PATH_OPTION:\n          m_set_initial_path = false;\n          break;\n\n        case NO_LINE_EDITING_OPTION:\n          m_line_editing = false;\n          break;\n\n        case NO_INIT_SITE_OPTION:\n          m_read_site_files = false;\n          break;\n\n        case NO_STARTUP_TESTS_OPTION:\n          m_inhibit_startup_tests = true;\n          break;\n\n        case PERSIST_OPTION:\n          m_persist = true;\n          break;\n\n        case SERVER_OPTION:\n          m_server = true;\n          break;\n\n        case TEXI_MACROS_FILE_OPTION:\n          if (octave_optarg_wrapper ())\n            m_texi_macros_file = octave_optarg_wrapper ();\n          break;\n\n        case TRADITIONAL_OPTION:\n          m_traditional = true;\n          m_persist = true;\n          break;\n\n        default:\n          // getopt_long should print a message about unrecognized options and\n          // return '?', which is handled above.  If we end up here, it is\n          // because there was an option but we forgot to handle it.\n          // This is fatal.\n          std::cerr << \"unexpected option (= \" << optc << \") - please report this bug\\n\";\n          std::exit (EXIT_FAILURE);\n          break;\n        }\n    }\n\n  m_remaining_args = string_vector (argv+octave_optind_wrapper (),\n                                    argc-octave_optind_wrapper ());\n}\n\noctave_value\ncmdline_options::as_octave_value () const\n{\n  octave_scalar_map m;\n\n  m.assign (\"sys_argc\", sys_argc ());\n  m.assign (\"sys_argv\", Cell (all_args ()));\n  m.assign (\"echo_commands\", echo_commands ());\n  m.assign (\"forced_interactive\", forced_interactive ());\n  m.assign (\"forced_line_editing\", forced_line_editing ());\n  m.assign (\"gui\", gui ());\n  m.assign (\"inhibit_startup_message\", inhibit_startup_message ());\n  m.assign (\"inhibit_startup_tests\", inhibit_startup_tests ());\n  m.assign (\"line_editing\", line_editing ());\n  m.assign (\"no_window_system\", no_window_system ());\n  m.assign (\"persist\", persist ());\n  m.assign (\"read_history_file\", read_history_file ());\n  // FIXME: read_init_files deprecated in Octave 10 in favor of read_user_files\n  m.assign (\"read_init_files\", read_user_files ());\n  m.assign (\"read_user_files\", read_user_files ());\n  m.assign (\"read_site_files\", read_site_files ());\n  m.assign (\"server\", server ());\n  m.assign (\"set_initial_path\", set_initial_path ());\n  m.assign (\"traditional\", traditional ());\n  m.assign (\"init_trace\", init_trace ());\n  m.assign (\"code_to_eval\", code_to_eval ());\n  m.assign (\"command_line_path\", string_vector (command_line_path ()));\n  m.assign (\"docstrings_file\", docstrings_file ());\n  m.assign (\"doc_cache_file\", doc_cache_file ());\n  m.assign (\"exec_path\", exec_path ());\n  m.assign (\"image_path\", image_path ());\n  m.assign (\"info_file\", info_file ());\n  m.assign (\"info_program\", info_program ());\n  m.assign (\"texi_macros_file\", texi_macros_file ());\n  m.assign (\"all_args\", Cell (all_args ()));\n  m.assign (\"remaining_args\", Cell (remaining_args ()));\n\n  return m;\n}\n\napplication *application::s_instance = nullptr;\n\napplication::application (int argc, char **argv)\n  : m_options (argc, argv)\n{\n  init ();\n}\n\napplication::application (const cmdline_options& opts)\n  : m_options (opts)\n{\n  init ();\n}\n\n// Note: Although the application destructor doesn't explicitly\n// perform any actions, it can't be declared \"default\" in the header\n// file if the interpreter is an incomplete type.  Providing\n// an explicit definition of the destructor here is much simpler than\n// including the full declaration of interpreter in the\n// octave.h header file.\napplication::~application () { }\n\nvoid\napplication::set_program_names (const std::string& pname)\n{\n  m_program_invocation_name = pname;\n\n  std::size_t pos = pname.find_last_of (sys::file_ops::dir_sep_chars ());\n\n  m_program_name = (pos != std::string::npos) ? pname.substr (pos+1) : pname;\n}\n\nvoid\napplication::intern_argv (const string_vector& args)\n{\n  octave_idx_type nargs = args.numel ();\n\n  if (nargs > 0)\n    {\n      // Skip first argument (program name).\n      nargs--;\n\n      m_argv.resize (nargs);\n\n      for (octave_idx_type i = 0; i < nargs; i++)\n        m_argv[i] = args[i+1];\n    }\n}\n\nbool\napplication::forced_interactive ()\n{\n  return s_instance ? s_instance->m_options.forced_interactive () : false;\n}\n\n// Provided for convenience.  Will be removed once we eliminate the\n// old terminal widget.\nbool\napplication::experimental_terminal_widget () const\n{\n  return (s_instance\n          ? s_instance->m_options.experimental_terminal_widget () : false);\n}\n\nbool\napplication::interpreter_is_initialized () const\n{\n  return m_interpreter ? m_interpreter->is_initialized () : false;\n}\n\ninterpreter&\napplication::create_interpreter ()\n{\n  if (! m_interpreter)\n    m_interpreter = std::unique_ptr<interpreter> (new interpreter (this));\n\n  return *m_interpreter;\n}\n\nvoid\napplication::initialize_interpreter ()\n{\n  if (m_interpreter)\n    m_interpreter->initialize ();\n}\n\nint\napplication::execute_interpreter ()\n{\n  return m_interpreter ? m_interpreter->execute () : -1;\n}\n\nvoid\napplication::delete_interpreter ()\n{\n  m_interpreter.reset ();\n}\n\nvoid\napplication::init ()\n{\n  if (s_instance)\n    throw std::runtime_error\n    (\"only one Octave application object may be active\");\n\n  s_instance = this;\n\n  string_vector all_args = m_options.all_args ();\n\n  set_program_names (all_args[0]);\n\n  string_vector remaining_args = m_options.remaining_args ();\n\n  std::string code_to_eval = m_options.code_to_eval ();\n\n  m_have_script_file = ! remaining_args.empty ();\n\n  m_have_eval_option_code = ! code_to_eval.empty ();\n\n  if (m_have_eval_option_code && m_have_script_file)\n    {\n      std::cerr << R\"(error: --eval \"CODE\" and script file are mutually exclusive options)\" << std::endl;\n\n      octave_print_terse_usage_and_exit ();\n    }\n\n  if (m_options.gui ())\n    {\n      if (m_options.no_window_system ())\n        {\n          std::cerr << \"error: --gui and --no-window-system are mutually exclusive options\" << std::endl;\n          octave_print_terse_usage_and_exit ();\n        }\n      if (! m_options.line_editing ())\n        {\n          std::cerr << \"error: --gui and --no-line-editing are mutually exclusive options\" << std::endl;\n          octave_print_terse_usage_and_exit ();\n        }\n      if (m_options.server ())\n        {\n          std::cerr << \"error: --gui and --server are mutually exclusive options\" << std::endl;\n          octave_print_terse_usage_and_exit ();\n        }\n    }\n\n  m_is_octave_program = ((m_have_script_file || m_have_eval_option_code)\n                         && ! m_options.persist ()\n                         && ! m_options.traditional ());\n\n  // Perform system-dependent initialization here in case it is needed\n  // prior to constructing the interpreter object.\n  sysdep_init ();\n}\n\nint\ncli_application::execute ()\n{\n  interpreter& interp = create_interpreter ();\n\n  int status = interp.execute ();\n\n  return status;\n}\n\nDEFUN (isguirunning, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} isguirunning ()\nReturn true if Octave is running in GUI mode and false otherwise.\n@seealso{have_window_system}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  // FIXME: This isn't quite right, it just says that we intended to\n  // start the GUI, not that it is actually running.\n\n  return ovl (application::is_gui_running ());\n}\n\n/*\n%!assert (islogical (isguirunning ()))\n%!error <Invalid call> isguirunning (1)\n*/\n\nDEFUN (__is_multi_threaded__, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{tf} =} __is_multi_threaded__ ()\nReturn true if Octave is running with multiple threads.\n@seealso{isguirunning}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  // FIXME: This isn't quite right, it just says that we intended to\n  // start the GUI, not that it is actually running.\n\n  return ovl (application::is_multi_threaded ());\n}\n\n/*\n%!assert (islogical (__is_multi_threaded__ ()))\n%!error <Invalid call> __is_multi_threaded__ (1)\n*/\n\nDEFUN (argv, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{args} =} argv ()\nReturn the command line arguments passed to Octave.\n\nFor example, if you invoked Octave using the command\n\n@example\noctave --no-line-editing --quiet\n@end example\n\n@noindent\n@code{argv} would return a cell array of strings with the elements\n@option{--no-line-editing} and @option{--quiet}.\n\nIf you write an executable Octave script, @code{argv} will return the list\nof arguments passed to the script.  @xref{Executable Octave Programs}, for\nan example of how to create an executable Octave script.\n@seealso{program_name, cmdline_options}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (Cell (application::argv ()));\n}\n\n/*\n%!assert (iscellstr (argv ()))\n%!error <Invalid call> argv (1)\n*/\n\nDEFUN (cmdline_options, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{opt_struct} =} cmdline_options ()\nReturn a structure containing detailed information about the command line\narguments passed to Octave.\n\nProgramming Note: This function provides copious amounts of information about\nOctave's parsing of command line options and may be more useful for debugging\nOctave rather than for general use.\n@seealso{argv, program_name}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  application *app = application::app ();\n\n  if (! app)\n    error (\"invalid application context!\");\n\n  cmdline_options opts = app->options ();\n\n  return ovl (opts.as_octave_value ());\n}\n\n/*\n%!assert (isstruct (cmdline_options ()))\n%!error <Invalid call> cmdline_options (1)\n*/\n\nDEFUN (program_invocation_name, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{name} =} program_invocation_name ()\nReturn the string that was typed at the shell prompt to run Octave.\n\nThe string may include path components as well as the program filename.\n\nIf executing a script from the command line (e.g., @code{octave foo.m}) or\nusing an executable Octave script, the program name is set to the name of the\nscript.  @xref{Executable Octave Programs}, for an example of how to create an\nexecutable Octave script.\n@seealso{program_name, argv}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (application::program_invocation_name ());\n}\n\n/*\n%!assert (ischar (program_invocation_name ()))\n%!error <Invalid call> program_invocation_name (1)\n*/\n\nDEFUN (program_name, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{name} =} program_name ()\nReturn the filename component of the value returned by\n@code{program_invocation_name}.\n\n@seealso{program_invocation_name, argv}\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  return ovl (application::program_name ());\n}\n\n/*\n%!assert (ischar (program_name ()))\n%!error <Invalid call> program_name (1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/octave.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_octave_h)\n#define octave_octave_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <memory>\n#include <string>\n\n#include \"Array.h\"\n#include \"str-vec.h\"\n\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Command line arguments.  See also options.h.\n\nclass OCTINTERP_API cmdline_options\n{\npublic:\n\n  cmdline_options ();\n\n  cmdline_options (int argc, char **argv);\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (cmdline_options)\n\n  int sys_argc () const { return m_all_args.numel (); }\n  char ** sys_argv () const { return m_all_args.c_str_vec (); }\n\n  bool echo_commands () const { return m_echo_commands; }\n\n  bool experimental_terminal_widget () const\n  { return m_experimental_terminal_widget; }\n  bool forced_interactive () const { return m_forced_interactive; }\n  bool forced_line_editing () const { return m_forced_line_editing; }\n  bool gui () const { return m_gui; }\n  bool inhibit_startup_tests () const\n  { return m_inhibit_startup_tests; }\n  bool inhibit_startup_message () const\n  { return m_inhibit_startup_message; }\n  bool line_editing () const { return m_line_editing; }\n\n  bool no_window_system () const { return m_no_window_system; }\n  bool persist () const { return m_persist; }\n  bool read_history_file () const { return m_read_history_file; }\n  bool read_site_files () const { return m_read_site_files; }\n  bool read_user_files () const { return m_read_user_files; }\n  bool server () const { return m_server; }\n  bool set_initial_path () const { return m_set_initial_path; }\n  bool traditional () const { return m_traditional; }\n\n  bool init_trace () const { return m_init_trace; }\n  std::string code_to_eval () const { return m_code_to_eval; }\n  std::list<std::string> command_line_path () const\n  { return m_command_line_path; }\n  std::string docstrings_file () const { return m_docstrings_file; }\n  std::string doc_cache_file () const { return m_doc_cache_file; }\n  std::string exec_path () const { return m_exec_path; }\n  std::string image_path () const { return m_image_path; }\n  std::string info_file () const { return m_info_file; }\n  std::string info_program () const { return m_info_program; }\n  std::string texi_macros_file () const {return m_texi_macros_file; }\n  string_vector all_args () const { return m_all_args; }\n  string_vector remaining_args () const { return m_remaining_args; }\n\n  void echo_commands (bool arg) { m_echo_commands = arg; }\n\n  void experimental_terminal_widget (bool arg)\n  { m_experimental_terminal_widget = arg; }\n  void forced_line_editing (bool arg) { m_forced_line_editing = arg; }\n  void forced_interactive (bool arg) { m_forced_interactive = arg; }\n  void gui (bool arg) { m_gui = arg; }\n  void inhibit_startup_tests (bool arg) { m_inhibit_startup_tests = arg; }\n  void inhibit_startup_message (bool arg) { m_inhibit_startup_message = arg; }\n  void line_editing (bool arg) { m_line_editing = arg; }\n\n  void no_window_system (bool arg) { m_no_window_system = arg; }\n  void persist (bool arg) { m_persist = arg; }\n  void read_history_file (bool arg) { m_read_history_file = arg; }\n  // FIXME: Alias for read_user_files() introduced in Octave 10.\n  // Remove at some point in the future.\n  void read_site_files (bool arg) { m_read_site_files = arg; }\n  void read_user_files (bool arg) { m_read_user_files = arg; }\n  void server (bool arg) { m_server = arg; }\n  void set_initial_path (bool arg) { m_set_initial_path = arg; }\n  void traditional (bool arg) { m_traditional = arg; }\n  void init_trace (bool arg) { m_init_trace = arg; }\n  void code_to_eval (const std::string& arg) { m_code_to_eval = arg; }\n  void command_line_path (const std::list<std::string>& arg)\n  { m_command_line_path = arg; }\n  void docstrings_file (const std::string& arg) { m_docstrings_file = arg; }\n  void doc_cache_file (const std::string& arg) { m_doc_cache_file = arg; }\n  void exec_path (const std::string& arg) { m_exec_path = arg; }\n  void image_path (const std::string& arg) { m_image_path = arg; }\n  void info_file (const std::string& arg) { m_info_file = arg; }\n  void info_program (const std::string& arg) { m_info_program = arg; }\n  void texi_macros_file (const std::string& arg) { m_texi_macros_file = arg; }\n  void all_args (const string_vector& arg) { m_all_args = arg; }\n  void remaining_args (const string_vector& arg) { m_remaining_args = arg; }\n\n  octave_value as_octave_value () const;\n\nprivate:\n\n  // If TRUE, echo commands as they are read and executed.\n  // (--echo-commands, -x)\n  bool m_echo_commands = false;\n\n  // If TRUE, use new experimental terminal widget in the GUI.\n  // (--experimental-terminal-widget)\n  bool m_experimental_terminal_widget = false;\n\n  // If TRUE, start the GUI.\n  // (--gui) and (--force-gui) for backwards compatibility\n  bool m_gui = false;\n\n  // TRUE means the user forced this shell to be interactive.\n  // (--interactive, -i)\n  bool m_forced_interactive = false;\n\n  // If TRUE, force readline command line editing.\n  // (--line-editing)\n  bool m_forced_line_editing = false;\n\n  // TRUE means we don't check for incompatibilites on startup.\n  // (--no-startup-tests)\n  bool m_inhibit_startup_tests = false;\n\n  // TRUE means we don't print the usual startup message.\n  // (--quiet; --silent; -q)\n  bool m_inhibit_startup_message = false;\n\n  // TRUE means we are using readline.\n  // (--no-line-editing)\n  bool m_line_editing = true;\n\n  // If TRUE, ignore the window system even if it is available.\n  // (--no-window-system, -W)\n  bool m_no_window_system = false;\n\n  // If TRUE, don't exit after evaluating code given by --eval option.\n  // (--persist)\n  bool m_persist = false;\n\n  // If TRUE, initialize history list from saved history file.\n  // (--no-history; -H)\n  bool m_read_history_file = true;\n\n  // TRUE means we read ~/.octaverc and ./.octaverc.\n  // (--no-init-user; --no-init-file; --norc; -f)\n  bool m_read_user_files = true;\n\n  // TRUE means we read the site-wide octaverc files.\n  // (--no-init-site; --no-site-file; --norc; -f)\n  bool m_read_site_files = true;\n\n  // If TRUE, start the command server.\n  // (--server)\n  bool m_server = false;\n\n  // TRUE means we set the initial path to configured defaults.\n  // (--no-init-path)\n  bool m_set_initial_path = true;\n\n  // If TRUE use traditional (maximally MATLAB compatible) settings\n  // (--traditional)\n  bool m_traditional = false;\n\n  // If TRUE, print trace of files read during initialization\n  // (--init-trace, --verbose; -V)\n  // FIXME: --verbose and -V will eventually be deprecated and removed.\n  bool m_init_trace = false;\n\n  // The code to evaluate at startup\n  // (--eval CODE)\n  std::string m_code_to_eval;\n\n  // The value of \"path\" specified on the command line.\n  // (--path; -p)\n  std::list<std::string> m_command_line_path;\n\n  // The value for \"built_in_docstrings_file\" specified on the\n  // command line.\n  // (--built-in-docstrings-file)\n  std::string m_docstrings_file;\n\n  // The value for \"doc_cache_file\" specified on the command line.\n  // (--doc-cache-file)\n  std::string m_doc_cache_file;\n\n  // The value for \"EXEC_PATH\" specified on the command line.\n  // (--exec-path)\n  std::string m_exec_path;\n\n  // The value for \"IMAGE_PATH\" specified on the command line.\n  // (--image-path)\n  std::string m_image_path;\n\n  // The value for \"info_file\" specified on the command line.\n  // (--info-file)\n  std::string m_info_file;\n\n  // The value for \"info_program\" specified on the command line.\n  // (--info-program)\n  std::string m_info_program;\n\n  // The value for \"texi_macos_file\" specified on the command line.\n  // (--texi-macros-file)\n  std::string m_texi_macros_file;\n\n  // All arguments passed to the argc, argv constructor.\n  string_vector m_all_args;\n\n  // Arguments remaining after parsing.\n  string_vector m_remaining_args;\n};\n\n// The application object contains a pointer to the current\n// interpreter and the interpreter contains a pointer back to the\n// application context so we need a forward declaration for one (or\n// both) of them...\n\nclass interpreter;\n\n// Base class for an Octave application.\n\nclass OCTINTERP_API application\n{\npublic:\n\n  application (const cmdline_options& opts = cmdline_options ());\n\n  application (int argc, char **argv);\n\n  OCTAVE_DISABLE_COPY_MOVE (application)\n\n  virtual ~application ();\n\n  int sys_argc () const { return m_options.sys_argc (); }\n  char ** sys_argv () const { return m_options.sys_argv (); }\n\n  void set_program_names (const std::string& pname);\n\n  void intern_argv (const string_vector& args);\n\n  cmdline_options options () const { return m_options; }\n\n  bool have_eval_option_code () const { return m_have_eval_option_code; }\n\n  bool have_script_file () const { return m_have_script_file; }\n\n  bool is_octave_program () const { return m_is_octave_program; }\n\n  bool interpreter_is_initialized () const;\n\n  virtual interpreter& create_interpreter ();\n\n  virtual void initialize_interpreter ();\n\n  virtual int execute_interpreter ();\n\n  virtual void delete_interpreter ();\n\n  virtual int execute () = 0;\n\n  virtual bool gui_running () const { return false; }\n  virtual void gui_running (bool) { }\n\n  // TRUE if Octave uses multiple threads (e.g., for interpreter and GUI).\n  virtual bool multi_threaded () const { return false; }\n\n  void program_invocation_name (const std::string& nm)\n  { m_program_invocation_name = nm; }\n\n  void program_name (const std::string& nm) { m_program_name = nm; }\n\n  void forced_interactive (bool arg) { m_options.forced_interactive (arg); }\n\n  // Provided for convenience.  Will be removed once we eliminate the\n  // old terminal widget.\n  bool experimental_terminal_widget () const;\n\n  static application * app () { return s_instance; }\n\n  static std::string program_invocation_name ()\n  {\n    return s_instance ? s_instance->m_program_invocation_name : \"\";\n  }\n\n  static std::string program_name ()\n  {\n    return s_instance ? s_instance->m_program_name : \"\";\n  }\n\n  static string_vector argv ()\n  {\n    return s_instance ? s_instance->m_argv : string_vector ();\n  }\n\n  static bool is_gui_running ()\n  {\n    return s_instance ? s_instance->gui_running () : false;\n  }\n\n  static bool is_multi_threaded ()\n  {\n    return s_instance ? s_instance->multi_threaded () : false;\n  }\n\n  // Convenience functions.\n\n  static bool forced_interactive ();\n\nprivate:\n\n  // The application instance; There should be only one.\n  static application *s_instance;\n\n  void init ();\n\nprotected:\n\n  // The name used to invoke Octave.\n  std::string m_program_invocation_name;\n\n  // The last component of octave_program_invocation_name.\n  std::string m_program_name;\n\n  // The current argument vector (may change if we are running a\n  // script with --persist because after the script is done, the\n  // arguments revert to the full list given to the octave\n  // interpreter at startup.\n  string_vector m_argv;\n\n  cmdline_options m_options;\n\n  // TRUE means we have --eval CODE\n  bool m_have_eval_option_code = false;\n\n  // TRUE if there is a command line argument that looks like the\n  // name of a file to execute.\n  bool m_have_script_file = false;\n\n  // TRUE if this is a program and no interpreter and interaction is\n  // needed.  For example, an octave program with shebang line, or code\n  // from eval without persist.\n  bool m_is_octave_program = false;\n\n  std::unique_ptr<interpreter> m_interpreter;\n};\n\nclass OCTINTERP_API cli_application : public application\n{\npublic:\n\n  cli_application (const cmdline_options& opts = cmdline_options ())\n    : application (opts)\n  { }\n\n  cli_application (int argc, char **argv)\n    : application (argc, argv)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (cli_application)\n\n  ~cli_application () = default;\n\n  int execute ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/octinterp.in.pc",
    "content": "Name: @PACKAGE_NAME@\nDescription: C++ interface to GNU Octave interpreter.\nURL: https://www.octave.org\nVersion: @PACKAGE_VERSION@\nRequires: octave = @PACKAGE_VERSION@\nRequires.private:\nLibs: -L@octlibdir@ @LIBOCTINTERP@\nLibs.private:\nCflags: -I@octincludedir@/..\n"
  },
  {
    "path": "libinterp/op-kw-docs",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n\u001d!\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} !\nLogical 'not' operator.\n@seealso{~, not}\n@end deftypefn\n\u001d~\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ~\nLogical 'not' operator @emph{or} discard function outputs.\n\nThe symbol may be used to discard outputs of a function that are unwanted\nwithout using a temporary variable.\n\n@example\n[~, @var{idx_of_max}] = max (@var{x})\n@end example\n@seealso{!, not}\n@end deftypefn\n\u001d!=\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} !=\nLogical 'not equals' operator.\n@seealso{~=, ne}\n@end deftypefn\n\u001d~=\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ~=\nLogical 'not equals' operator.\n@seealso{!=, ne}\n@end deftypefn\n\u001d\"\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} \"\nString delimiter.\n\nEscape sequences within double-quoted strings are expanded.  I.e., \"\\n\" is a\n1-character string representing a newline.  See the single quote delimiter (')\nto create strings without escape sequence processing.\n@seealso{'}\n@end deftypefn\n\u001d#\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} #\nBegin comment character.\n@seealso{%, #@\\{}\n@end deftypefn\n\u001d%\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} %\nBegin comment character.\n@seealso{#, %@\\{}\n@end deftypefn\n\u001d#{\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} #@{\nBegin block comment.\n\nThe sequence @code{#@{} must appear alone on a line with no other characters,\nother than whitespace, before or after it.  It is possible to nest block\ncomments.\n@seealso{%@\\{, #@\\}, #}\n@end deftypefn\n\u001d%{\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} %@{\nBegin block comment.\n\nThe sequence @code{%@{} must appear alone on a line with no other characters,\nother than whitespace, before or after it.  It is possible to nest block\ncomments.\n@seealso{#@\\{, %@\\}, %}\n@end deftypefn\n\u001d#}\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} #@}\nTerminate block comment.\n\nThe sequence @code{#@}} must appear alone on a line with no other characters,\nother than whitespace, before or after it.  It is possible to nest block\ncomments.\n@seealso{%@\\}, #@\\{, #}\n@end deftypefn\n\u001d%}\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} %@}\nTerminate block comment.\n\nThe sequence @code{%@}} must appear alone on a line with no other characters,\nother than whitespace, before or after it.  It is possible to nest block\ncomments.\n@seealso{#@\\}, %@\\{, %}\n@end deftypefn\n\u001d...\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ...\nContinuation marker.\n\nJoin current line with following line before parsing.  This can be used to\nimprove the human-readability of Octave code, without affecting interpretation.\n@end deftypefn\n\u001d&\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} &\nElement-by-element logical 'and' operator.\n@seealso{and, &&}\n@end deftypefn\n\u001d&&\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} &&\nLogical 'and' operator (with short-circuit evaluation).\n@seealso{&}\n@end deftypefn\n\u001d'\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} '\nMatrix transpose operator @emph{or} string delimiter.\n\nFor complex matrices, computes the complex conjugate (Hermitian) transpose.\n\nThe single quote character may also be used to delimit strings.  Escape\nsequences within single-quoted strings are not expanded.  I.e., '\\n' is a\n2-character string '\\' and 'n' rather than \"\\n\" which is a single character\nrepresenting a newline.\n@seealso{ctranspose, .', \"}\n@end deftypefn\n\u001d(\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} (\nArray index @emph{or} function argument delimiter.\n@end deftypefn\n\u001d)\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {})\nArray index @emph{or} function argument delimiter.\n@end deftypefn\n\u001d*\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} *\nMultiplication operator.\n@seealso{mtimes, .*}\n@end deftypefn\n\u001d**\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} **\nPower operator.\n\nThis may return complex results for real inputs.  Use @code{realsqrt},\n@code{cbrt}, @code{nthroot}, or @code{realpow} to obtain real results when\npossible.\n@seealso{power, ^, .**, .^, realpow, realsqrt, cbrt, nthroot}\n@end deftypefn\n\u001d^\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ^\nPower operator.\n\nThis may return complex results for real inputs.  Use @code{realsqrt},\n@code{cbrt}, @code{nthroot}, or @code{realpow} to obtain real results when\npossible.\n@seealso{power, **, .^, .**, realpow, realsqrt, cbrt, nthroot}\n@end deftypefn\n\u001d+\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} +\nAddition operator.\n@seealso{plus}\n@end deftypefn\n\u001d++\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ++\nIncrement operator.\n\nAdd @code{1} to existing value of variable.  As in C, may be applied as a\nprefix (@code{++x}) or postfix (@code{x++}) operator.\n@seealso{--}\n@end deftypefn\n\u001d,\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ,\nArray index @emph{or} function argument @emph{or} command separator.\n@end deftypefn\n\u001d-\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} -\nSubtraction @emph{or} unary negation operator.\n@seealso{minus}\n@end deftypefn\n\u001d--\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} --\nDecrement operator.\n\nSubtract @code{1} from existing value of variable.  As in C, may be applied as\na prefix (@code{--x}) or postfix (@code{x--}) operator.\n@seealso{++}\n@end deftypefn\n\u001d.'\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} .'\nMatrix transpose operator.\n\nFor complex matrices, computes the transpose, @emph{not} the complex conjugate\n(Hermitian) transpose.\n@seealso{transpose, '}\n@end deftypefn\n\u001d.*\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} .*\nElement-by-element multiplication operator.\n@seealso{times, *}\n@end deftypefn\n\u001d.**\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} .**\nElement-by-element power operator.\n\nIf several complex results are possible, returns the one with smallest\nnon-negative argument (angle).  Use @code{realpow}, @code{realsqrt},\n@code{cbrt}, or @code{nthroot} if a real result is preferred.\n@seealso{power, .^, **, ^, realpow, realsqrt, cbrt, nthroot}\n@end deftypefn\n\u001d.^\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} .^\nElement-by-element power operator.\n\nIf several complex results are possible, returns the one with smallest\nnon-negative argument (angle).  Use @code{realpow}, @code{realsqrt},\n@code{cbrt}, or @code{nthroot} if a real result is preferred.\n@seealso{power, .**, ^, **, realpow, realsqrt, cbrt, nthroot}\n@end deftypefn\n\u001d./\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ./\nElement-by-element right division operator.\n@seealso{rdivide, /, mrdivide, .\\\\}\n@end deftypefn\n\u001d/\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} /\nRight division operator.\n@seealso{mrdivide, ./, rdivide, \\\\}\n@end deftypefn\n\u001d.\\\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} .\\\nElement-by-element left division operator.\n@seealso{ldivide, \\\\, mldivide, ./}\n@end deftypefn\n\u001d\\\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} \\\nLeft division operator.\n\nWithin double-quoted strings, @samp{\\} is the line continuation marker used\nto join the current line with the following line.\n@seealso{mldivide, .\\\\, ldivide, /}\n@end deftypefn\n\u001d:\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} :\nArray index @emph{or} range constructor separator.\n\nWhen indexing, select all elements in the specified dimension.\n\n@example\nx(2, :)   # selects 2nd row, all columns\n@end example\n\nWhen constructing ranges, @samp{:} is the separator between @var{base},\n@var{increment}, and @var{limit}.\n\n@example\n1:2:8\n@xresult{}  1  3  5  7\n@end example\n@end deftypefn\n\u001d;\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ;\nArray row @emph{or} command separator.\n@seealso{,}\n@end deftypefn\n\u001d<\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} <\n'Less than' operator.\n@seealso{lt}\n@end deftypefn\n\u001d<=\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} <=\n'Less than' or 'equals' operator.\n@seealso{le}\n@end deftypefn\n\u001d=\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} =\nAssignment operator.\n@end deftypefn\n\u001d==\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ==\nEquality test operator.\n@seealso{eq}\n@end deftypefn\n\u001d>\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} >\n'Greater than' operator.\n@seealso{gt}\n@end deftypefn\n\u001d>=\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} >=\n'Greater than' or 'equals' operator.\n@seealso{ge}\n@end deftypefn\n\u001d[\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} [\nReturn list delimiter.\n@seealso{]}\n@end deftypefn\n\u001d]\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ]\nReturn list delimiter.\n@seealso{[}\n@end deftypefn\n\u001d|\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} |\nElement-by-element logical 'or' operator.\n@seealso{or, ||}\n@end deftypefn\n\u001d||\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} ||\nLogical 'or' (with short-circuit evaluation) operator.\n@seealso{|}\n@end deftypefn\n\u001d@\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} @@\nReturn handle to a function.\n\nExample:\n\n@example\n@group\nf = @@plus;\nf (2, 2)\n@xresult{}  4\n@end group\n@end example\n\n(Note: @@ also finds use in creating classes.  See the manual chapter titled\nObject Oriented Programming for a detailed description.)\n@seealso{function, functions, func2str, str2func}\n@end deftypefn\n\u001d__FILE__\n@c libinterp/parse-tree/lex.ll\n-*- texinfo -*-\n@deftypefn {} {} __FILE__\nWhen the lexer recognizes the @qcode{\"__FILE__\"} keyword it returns a character\narray containing the full name and path of the file that is being executed.\n@qcode{\"__FILE__\"} will return @qcode{\"stdin\"} if called from the command line.\n@seealso{__LINE__}\n@end deftypefn\n\u001d__LINE__\n@c libinterp/parse-tree/lex.ll\n-*- texinfo -*-\n@deftypefn {} {} __LINE__\nWhen the lexer recognizes the @qcode{\"__LINE__\"} keyword it returns a numeric\nvalue containing the current input line number of the function or file being\nexecuted.  @qcode{\"__LINE__\"} will return @code{1} if called from the command\nline.\n@seealso{__FILE__}\n@end deftypefn\n\u001darguments\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} arguments\nBegin a function arguments block.\n\n@strong{Warning:} Function arguments validation blocks are not yet implemented\nin Octave.  Use of the keyword @code{arguments} will cause the parser to emit a\nwarning, and may throw an error depending on the contents of the code in the\nblock.\n@end deftypefn\n\u001dbreak\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} break\nExit the innermost enclosing @code{do}, @code{while}, or @code{for} loop.\n@seealso{continue, do, while, for, parfor}\n@end deftypefn\n\u001dcase\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn  {} {} case @var{value}\n@deftypefnx {} {} case @{@var{value1}, @dots{}@}\nA case statement in a switch block.\n\nThe code associated with a @code{case} statement is executed if one of the\ntests below succeeds given a @code{switch} argument @var{statement} and a\n@var{value} of type:\n\n@itemize\n\n@item number : @code{@var{statement} == @var{value}}\n\n@item character array or string : @code{strcmp (@var{statement}, @var{value})}\n\n@item object : @code{eq (@var{statement}, @var{value})}@*\n(programmer must write overloaded @code{eq} function which performs @samp{==}) \n\n@item cell array : One of the @var{values} in the cell array must match\n@var{statement} using the criteria above.\n\n@end itemize\n\nProgramming Notes: Octave cases are exclusive and do not fall-through as do\n@w{C-language} cases.  A @code{switch} statement must have at least one\n@code{case}.\n\nSee @code{switch} for an example.\n@seealso{switch}\n@end deftypefn\n\u001dcatch\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn  {} {} catch\n@deftypefnx {} {} catch @var{exception_var}\nBegin the cleanup part of a try-catch block.\n\nIf @var{exception_var} is specified then a variable of that name will defined\nin the scope of the @code{catch} block.  The variable is a scalar struct with\nfields @code{identifier}, @code{message}, and @code{stack} which describes\nthe error that was caught.\n@seealso{try}\n@end deftypefn\n\u001dclassdef\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} classdef\nBegin a classdef block.\n@c NOTE: Use Octave @xseealso macro in order to point at the keyword\n@c       documentation for \"properties\" and \"methods\" rather than the function\n@c       documentation.\n@xseealso{@ref{XREFkwpropertyproperties,,properties}, @ref{XREFkwpropertymethods,,methods}, @ref{XREFevents,,events}, @ref{XREFenumeration,,enumeration}}\n@end deftypefn\n\u001dcontinue\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} continue\nJump to the end of the innermost enclosing @code{do}, @code{while}, or\n@code{for} loop.\n@seealso{break, do, while, for, parfor}\n@end deftypefn\n\u001ddo\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} do\nBegin a do-until loop.\n\nThis differs from a @code{while} loop in that the body of the loop is executed\nat least once.\n\n@example\n@group\ni = 0;\ndo\n  i++\nuntil (i == 10)\n@end group\n@end example\n@seealso{for, until, while}\n@end deftypefn\n\u001delse\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} else\nAlternate action for an if block.\n\nSee @code{if} for an example.\n@seealso{if}\n@end deftypefn\n\u001delseif\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} elseif (@var{cond})\nAlternate conditional test for an if block.\n\nThe conditional @var{cond} is true if it is not empty and if @emph{all} values\nare nonzero.\n\nSee @code{if} for an example.\n@seealso{if}\n@end deftypefn\n\u001dend_try_catch\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} end_try_catch\nTerminate a try-catch block.\n@seealso{try, catch}\n@end deftypefn\n\u001dend_unwind_protect\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} end_unwind_protect\nTerminate an unwind_protect block.\n@seealso{unwind_protect}\n@end deftypefn\n\u001dendarguments\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endarguments\nTerminate a function arguments block.\n\n@strong{Warning:} Function arguments validation blocks are not yet implemented\nin Octave.  Use of the keyword @code{arguments} will cause the parser to emit a\nwarning, and may throw an error depending on the contents of the code in the\nblock.\n@seealso{arguments}\n@end deftypefn\n\u001dendclassdef\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endclassdef\nTerminate a classdef definition.\n@seealso{classdef}\n@end deftypefn\n\u001dendenumeration\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endenumeration\nTerminate an enumeration block in a classdef definition.\n@seealso{enumeration}\n@end deftypefn\n\u001dendevents\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endevents\nTerminate an events block in a classdef definition.\n@seealso{events}\n@end deftypefn\n\u001dendfor\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endfor\nTerminate a for loop.\n\nSee @code{for} for an example.\n@seealso{for}\n@end deftypefn\n\u001dendfunction\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endfunction\nTerminate a function definition.\n@seealso{function}\n@end deftypefn\n\u001dendif\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endif\nTerminate an if block.\n\nSee @code{if} for an example.\n@seealso{if}\n@end deftypefn\n\u001dendmethods\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endmethods\nTerminate a methods block in a classdef definition.\n@c NOTE: Use Octave @xseealso macro in order to point at property 'methods',\n@c       rather than function.\n@xseealso{@ref{XREFkwpropertymethods,,methods}}\n@end deftypefn\n\u001dendparfor\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endparfor\nTerminate a parfor loop.\n\nSee @code{parfor} for an example.\n@seealso{parfor}\n@end deftypefn\n\u001dendproperties\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endproperties\nTerminate a properties block in a classdef definition.\n@c NOTE: Use Octave @xseealso macro in order to point at property 'properties',\n@c       rather than function.\n@xseealso{@ref{XREFkwpropertyproperties,,properties}}\n@end deftypefn\n\u001dendspmd\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endparfor\nTerminate an spmd block.\n\nSee @code{spmd} for an example.\n@seealso{spmd, parfor}\n@end deftypefn\n\u001dendswitch\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endswitch\nTerminate a switch block.\n\nSee @code{switch} for an example.\n@seealso{switch}\n@end deftypefn\n\u001dendwhile\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} endwhile\nTerminate a while loop.\n\nSee @code{while} for an example.\n@seealso{do, while}\n@end deftypefn\n\u001denumeration\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} enumeration\nBegin an enumeration block in a classdef definition.\n@end deftypefn\n\u001devents\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} events\nBegin an events block in a classdef definition.\n@end deftypefn\n\u001dfor\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} for @var{i} = @var{range}\nBegin a for loop.\n\n@example\n@group\nfor i = 1:10\n  i\nendfor\n@end group\n@end example\n@seealso{parfor, do, while}\n@end deftypefn\n\u001dfunction\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn  {} {} function [@var{output1}, @dots{}] = function_name (@var{input1}, @dots{})\n@deftypefnx {} {} function {} function_name (@var{input1}, @dots{})\n@deftypefnx {} {} function @var{output} = function_name\nBegin a function body with name @code{function_name}, with @var{outputs} as\nresults, and with @var{inputs} as parameters.\n\nThe function can later be invoked in Octave using the syntax\n\n@example\n[@var{output1}, @var{output2}, @dots{}] = function_name (@var{input1}, @var{input2}, @dots{})\n@end example\n\n@seealso{return}\n@end deftypefn\n\u001dglobal\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} global @var{var}\nDeclare variables to have global scope.\n\n@example\n@group\nglobal @var{x};\nif (isempty (@var{x}))\n  x = 1;\nendif\n@end group\n@end example\n@seealso{persistent}\n@end deftypefn\n\u001dif\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn  {} {} if (@var{cond}) @dots{} endif\n@deftypefnx {} {} if (@var{cond}) @dots{} else @dots{} endif\n@deftypefnx {} {} if (@var{cond}) @dots{} elseif (@var{cond}) @dots{} endif\n@deftypefnx {} {} if (@var{cond}) @dots{} elseif (@var{cond}) @dots{} else @dots{} endif\nBegin an if block.\n\nThe conditional @var{cond} is true if it is not empty and if @emph{all} values\nare nonzero.\n\n@example\n@group\nx = 1;\nif (x == 1)\n  disp (\"one\");\nelseif (x == 2)\n  disp (\"two\");\nelse\n  disp (\"not one or two\");\nendif\n@end group\n@end example\n@seealso{switch}\n@end deftypefn\n@c ## FIXME: Can't have duplicate DOCSTRING entries.  The function methods()\n@c ##        already has a docstring which overrides this keyword definition.\n@c ##        If this is fixed, place \\x1d char before keyword \"methods\".\n@c ## methods\n@c ## @c libinterp/parse-tree/oct-parse.yy\n@c ## -*- texinfo -*-\n@c ## @deftypefn {} {} methods\n@c ## Begin a methods block in a classdef definition.\n@c ## @end deftypefn\n\u001dotherwise\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} otherwise\nThe default statement in a @code{switch} block which is executed when no other\n@code{case} statements match the input.\n@seealso{switch, case}\n@end deftypefn\n\u001dparfor\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn  {} {} parfor @var{i} = @var{range}\n@deftypefnx {} {} parfor (@var{i} = @var{range}, @var{maxproc})\nBegin a for loop that may execute in parallel.\n\nA @code{parfor} loop has the same syntax as a @code{for} loop.  If your Octave\nsession has a parallel processing pool enabled, the iterations of the\n@code{parfor} loop will be executed in parallel across the pool's workers.\nOtherwise, @code{parfor} will behave exactly as @code{for}.\n\nWhen operating in parallel mode, a @code{parfor} loop's iterations are not\nguaranteed to occur sequentially, and there are additional restrictions about\nthe data access operations you can do inside the loop body.\n\n@strong{Warning:} parallel processing pools are currently unimplemented in\nOctave; @code{parfor} currently behaves exactly as a normal @code{for} loop.\n\n@example\n@group\nparfor i = 1:10\n  i\nendparfor\n@end group\n@end example\n@seealso{for, do, while}\n@end deftypefn\n\u001dpersistent\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} persistent @var{var}\nDeclare variables as persistent.\n\nA variable that has been declared persistent within a function will retain its\ncontents in memory between subsequent calls to the same function.  The\ndifference between persistent variables and global variables is that persistent\nvariables are local in scope to a particular function and are not visible\nelsewhere.\n@seealso{global}\n@end deftypefn\n@c ## FIXME: Can't have duplicate DOCSTRING entries.  The function properties()\n@c ##        already has a docstring which overrides this keyword definition.\n@c ##        If this is fixed, place \\x1d char before keyword \"properties\".\n@c ## properties\n@c ## @c libinterp/parse-tree/oct-parse.yy\n@c ## -*- texinfo -*-\n@c ## @deftypefn {} {} properties\n@c ## Begin a properties block in a classdef definition.\n@c ## @end deftypefn\n\u001dreturn\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} return\nReturn execution control immediately from a function or script to the calling\ncode.\n\n@code{return} is used to stop executing code and exit an m-file immediately\nrather than continuing until the end of the function or script is reached.\n\nIf the function or script was invoked directly, rather than from calling code\nin an m-file, then Octave returns to the command line.\n@seealso{function}\n@end deftypefn\n\u001dspmd\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn  {} {} spmd\n@deftypefnx {} {} spmd (@var{n})\n@deftypefnx {} {} spmd (@var{m}, @var{n})\nBegin a block of statements which may execute in parallel across multiple\nworkers.\n\nIf Octave has a parallel processing pool enabled, the block of code will be\nexecuted in parallel across all of the pool's workers.  Otherwise, @code{spmd}\nhas no effect and the statements are processed as normal code by the main\nOctave interpreter.\n\nIf called with one additional argument @var{n} then use exactly @var{n} workers\nfrom the pool.  If called with two arguments @var{m}, @var{n} then use a\nminimum of @var{m} workers and a maximum of @var{n} workers from the parallel\npool.\n\n@strong{Warning:} parallel processing pools are currently unimplemented in\nOctave; @code{spmd} currently does nothing, but is included to avoid breaking\nexisting @sc{matlab} code.\n\n@seealso{parfor}\n@end deftypefn\n\u001dswitch\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} switch @var{statement}\nBegin a switch block.\n\n@example\n@group\nyesno = \"yes\";\n\nswitch (yesno)\n  case @{\"Yes\" \"yes\" \"YES\" \"y\" \"Y\"@}\n    value = 1;\n  case @{\"No\" \"no\" \"NO\" \"n\" \"N\"@}\n    value = 0;\n  otherwise\n    error (\"invalid value\");\nendswitch\n@end group\n@end example\n@seealso{if, case, otherwise}\n@end deftypefn\n\u001dtry\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} try\nBegin a try-catch block.\n\nIf an error occurs within a @code{try} block, then the code in the @code{catch}\nblock will be run.  Execution will proceed after the @code{catch} block (though\nit is often recommended to use the @code{lasterr} function to re-throw the\nerror after cleanup is completed).\n@seealso{catch, unwind_protect}\n@end deftypefn\n\u001duntil\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} until (@var{cond})\nEnd a do-until loop.\n\nThe conditional @var{cond} is true if it is not empty and if @emph{all} values\nare nonzero.\n\nSee @code{do} for an example.\n@seealso{do}\n@end deftypefn\n\u001dunwind_protect\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} unwind_protect\nBegin an unwind_protect block.\n\nIf an error occurs within the first part of an @code{unwind_protect} block the\ncommands within the @code{unwind_protect_cleanup} block are executed before the\nerror is thrown.  If an error is not thrown, then the\n@code{unwind_protect_cleanup} block is still executed.  In other words, the\n@code{unwind_protect_cleanup} code is guaranteed to execute regardless of\nsuccess or failure in the @code{unwind_protect} block.\n@seealso{unwind_protect_cleanup, try}\n@end deftypefn\n\u001dunwind_protect_cleanup\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} unwind_protect_cleanup\nBegin the cleanup section of an @code{unwind_protect} block.\n@seealso{unwind_protect}\n@end deftypefn\n\u001dvarargin\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} varargin\nPass an arbitrary number of arguments into a function.\n@seealso{varargout, nargin, isargout, nargout, nthargout}\n@end deftypefn\n\u001dvarargout\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} varargout\nPass an arbitrary number of arguments out of a function.\n@seealso{varargin, nargin, isargout, nargout, nthargout}\n@end deftypefn\n\u001dwhile\n@c libinterp/parse-tree/oct-parse.yy\n-*- texinfo -*-\n@deftypefn {} {} while (@var{cond})\nBegin a while loop.\n\nThe conditional @var{cond} is true if it is not empty and if @emph{all} values\nare nonzero.\n\n@example\n@group\ni = 0;\nwhile (i < 10)\n  i++\nendwhile\n@end group\n@end example\n@seealso{do, endwhile, for, until}\n@end deftypefn\n"
  },
  {
    "path": "libinterp/operators/mk-ops.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 1997-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nSED=${SED:-sed}\n\ncat << \\EOF\n// DO NOT EDIT!  Generated automatically by mk-ops.sh.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ov-typeinfo.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern void install_base_type_conversions (octave::type_info&);\n\nEOF\n\nfor file in \"$@\"; do\n  f=`echo $file | $SED 's,^\\./,,; s%^libinterp/operators/op-%%; s%\\.cc%%; s%-%_%g'`\n  echo \"extern void install_${f}_ops (octave::type_info&);\"\ndone\n\ncat << \\EOF\n\nvoid\ninstall_ops (octave::type_info& ti)\n{\n  install_base_type_conversions (ti);\n\nEOF\n\nfor file in \"$@\"; do\n  f=`echo $file | $SED 's,^\\./,,; s%^libinterp/operators/op-%%; s%\\.cc%%; s%-%_%g'`\n  echo \"  install_${f}_ops (ti);\"\ndone\n\ncat << \\EOF\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\nEOF\n\nexit 0\n"
  },
  {
    "path": "libinterp/operators/module.mk",
    "content": "LIBINTERP_OPERATORS_SRC = \\\n  %reldir%/op-b-b.cc \\\n  %reldir%/op-b-bm.cc \\\n  %reldir%/op-b-sbm.cc \\\n  %reldir%/op-bm-b.cc \\\n  %reldir%/op-bm-bm.cc \\\n  %reldir%/op-bm-sbm.cc \\\n  %reldir%/op-cdm-cdm.cc \\\n  %reldir%/op-cdm-cm.cc \\\n  %reldir%/op-cdm-cs.cc \\\n  %reldir%/op-cdm-dm.cc \\\n  %reldir%/op-cdm-m.cc \\\n  %reldir%/op-cdm-s.cc \\\n  %reldir%/op-cell.cc \\\n  %reldir%/op-chm.cc \\\n  %reldir%/op-class.cc \\\n  %reldir%/op-cm-cdm.cc \\\n  %reldir%/op-cm-cm.cc \\\n  %reldir%/op-cm-cs.cc \\\n  %reldir%/op-cm-dm.cc \\\n  %reldir%/op-cm-m.cc \\\n  %reldir%/op-cm-pm.cc \\\n  %reldir%/op-cm-s.cc \\\n  %reldir%/op-cm-scm.cc \\\n  %reldir%/op-cm-sm.cc \\\n  %reldir%/op-cs-cm.cc \\\n  %reldir%/op-cs-cs.cc \\\n  %reldir%/op-cs-m.cc \\\n  %reldir%/op-cs-s.cc \\\n  %reldir%/op-cs-scm.cc \\\n  %reldir%/op-cs-sm.cc \\\n  %reldir%/op-dm-cdm.cc \\\n  %reldir%/op-dm-cm.cc \\\n  %reldir%/op-dm-cs.cc \\\n  %reldir%/op-dm-dm.cc \\\n  %reldir%/op-dm-m.cc \\\n  %reldir%/op-dm-s.cc \\\n  %reldir%/op-dm-scm.cc \\\n  %reldir%/op-dm-sm.cc \\\n  %reldir%/op-fcdm-fcdm.cc \\\n  %reldir%/op-fcdm-fcm.cc \\\n  %reldir%/op-fcdm-fcs.cc \\\n  %reldir%/op-fcdm-fdm.cc \\\n  %reldir%/op-fcdm-fm.cc \\\n  %reldir%/op-fcdm-fs.cc \\\n  %reldir%/op-fcm-fcdm.cc \\\n  %reldir%/op-fcm-fcm.cc \\\n  %reldir%/op-fcm-fcs.cc \\\n  %reldir%/op-fcm-fdm.cc \\\n  %reldir%/op-fcm-fm.cc \\\n  %reldir%/op-fcm-fs.cc \\\n  %reldir%/op-fcm-pm.cc \\\n  %reldir%/op-fcn.cc \\\n  %reldir%/op-fcs-fcm.cc \\\n  %reldir%/op-fcs-fcs.cc \\\n  %reldir%/op-fcs-fm.cc \\\n  %reldir%/op-fcs-fs.cc \\\n  %reldir%/op-fdm-fcdm.cc \\\n  %reldir%/op-fdm-fcm.cc \\\n  %reldir%/op-fdm-fcs.cc \\\n  %reldir%/op-fdm-fdm.cc \\\n  %reldir%/op-fdm-fm.cc \\\n  %reldir%/op-fdm-fs.cc \\\n  %reldir%/op-fm-fcdm.cc \\\n  %reldir%/op-fm-fcm.cc \\\n  %reldir%/op-fm-fcs.cc \\\n  %reldir%/op-fm-fdm.cc \\\n  %reldir%/op-fm-fm.cc \\\n  %reldir%/op-fm-fs.cc \\\n  %reldir%/op-fm-pm.cc \\\n  %reldir%/op-fs-fcm.cc \\\n  %reldir%/op-fs-fcs.cc \\\n  %reldir%/op-fs-fm.cc \\\n  %reldir%/op-fs-fs.cc \\\n  %reldir%/op-i16-i16.cc \\\n  %reldir%/op-i32-i32.cc \\\n  %reldir%/op-i64-i64.cc \\\n  %reldir%/op-i8-i8.cc \\\n  %reldir%/op-int-concat.cc \\\n  %reldir%/op-m-cdm.cc \\\n  %reldir%/op-m-cm.cc \\\n  %reldir%/op-m-cs.cc \\\n  %reldir%/op-m-dm.cc \\\n  %reldir%/op-m-m.cc \\\n  %reldir%/op-m-pm.cc \\\n  %reldir%/op-m-s.cc \\\n  %reldir%/op-m-scm.cc \\\n  %reldir%/op-m-sm.cc \\\n  %reldir%/op-mi.cc \\\n  %reldir%/op-pm-cm.cc \\\n  %reldir%/op-pm-fcm.cc \\\n  %reldir%/op-pm-fm.cc \\\n  %reldir%/op-pm-m.cc \\\n  %reldir%/op-pm-pm.cc \\\n  %reldir%/op-pm-scm.cc \\\n  %reldir%/op-pm-sm.cc \\\n  %reldir%/op-range.cc \\\n  %reldir%/op-s-cm.cc \\\n  %reldir%/op-s-cs.cc \\\n  %reldir%/op-s-m.cc \\\n  %reldir%/op-s-s.cc \\\n  %reldir%/op-s-scm.cc \\\n  %reldir%/op-s-sm.cc \\\n  %reldir%/op-sbm-b.cc \\\n  %reldir%/op-sbm-bm.cc \\\n  %reldir%/op-sbm-sbm.cc \\\n  %reldir%/op-scm-cm.cc \\\n  %reldir%/op-scm-cs.cc \\\n  %reldir%/op-scm-m.cc \\\n  %reldir%/op-scm-s.cc \\\n  %reldir%/op-scm-scm.cc \\\n  %reldir%/op-scm-sm.cc \\\n  %reldir%/op-sm-cm.cc \\\n  %reldir%/op-sm-cs.cc \\\n  %reldir%/op-sm-m.cc \\\n  %reldir%/op-sm-s.cc \\\n  %reldir%/op-sm-scm.cc \\\n  %reldir%/op-sm-sm.cc \\\n  %reldir%/op-str-m.cc \\\n  %reldir%/op-str-s.cc \\\n  %reldir%/op-str-str.cc \\\n  %reldir%/op-struct.cc \\\n  %reldir%/op-ui16-ui16.cc \\\n  %reldir%/op-ui32-ui32.cc \\\n  %reldir%/op-ui64-ui64.cc \\\n  %reldir%/op-ui8-ui8.cc\n\nLIBINTERP_OPERATORS_INC = \\\n  %reldir%/ops.h\n\n## These look like included header files to Autotools build process\nNOINSTALL_LIBINTERP_OPERATORS_INC = \\\n  %reldir%/op-dm-template.cc \\\n  %reldir%/op-dms-template.cc \\\n  %reldir%/op-int.h \\\n  %reldir%/op-pm-template.cc\n\nlibinterp_EXTRA_DIST += \\\n  %reldir%/mk-ops.sh\n\n## Special rules for sources which must be built before rest of compilation.\n%reldir%/ops.cc: $(LIBINTERP_OPERATORS_SRC) %reldir%/mk-ops.sh\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(SHELL) $(srcdir)/%reldir%/mk-ops.sh $(LIBINTERP_OPERATORS_SRC) > $@-t && \\\n\tmv $@-t $@\n"
  },
  {
    "path": "libinterp/operators/op-b-b.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-bool.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-float.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-int8.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-null-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// bool unary ops.\n\n// scalar unary ops.\n\nDEFUNOP_OP (not, bool, !)\n\nstatic octave_value\noct_unop_uplus (const octave_base_value& a)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v, a);\n  return octave_value (v.double_value ());\n}\n\nstatic octave_value\noct_unop_uminus (const octave_base_value& a)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v, a);\n  return octave_value (- v.double_value ());\n}\n\nDEFUNOP_OP (transpose, bool, /* no-op */)\nDEFUNOP_OP (hermitian, bool, /* no-op */)\n\n// bool by bool ops.\n\nDEFBINOP_OP (eq, bool, bool, ==)\nDEFBINOP_OP (ne, bool, bool, !=)\nDEFBINOP_OP (el_and, bool, bool, &&)\nDEFBINOP_OP (el_or, bool, bool, ||)\n\nDEFNDCATOP_FN (b_b, bool, bool, bool_array, bool_array, concat)\nDEFNDCATOP_FN (b_s, bool, scalar, array, array, concat)\nDEFNDCATOP_FN (s_b, scalar, bool, array, array, concat)\nDEFNDCATOP_FN (b_f, bool, float_scalar, float_array, float_array, concat)\nDEFNDCATOP_FN (f_b, float_scalar, bool, float_array, float_array, concat)\n\n#define OCTAVE_INSTALL_BOOL_INT_ASSIGNCONV(TRHS)                    \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_ ## TRHS ## _scalar, octave_bool_matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_ ## TRHS ## _matrix, octave_bool_matrix)\n\nvoid\ninstall_b_b_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_bool, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_bool, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_bool, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_bool, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_bool, hermitian);\n\n  INSTALL_BINOP_TI (ti, op_eq, octave_bool, octave_bool, eq);\n  INSTALL_BINOP_TI (ti, op_ne, octave_bool, octave_bool, ne);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_bool, octave_bool, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_bool, octave_bool, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_bool, octave_bool, b_b);\n  INSTALL_CATOP_TI (ti, octave_bool, octave_scalar, b_s);\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_bool, s_b);\n  INSTALL_CATOP_TI (ti, octave_bool, octave_float_scalar, b_f);\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_bool, f_b);\n\n  OCTAVE_INSTALL_BOOL_INT_ASSIGNCONV(int8);\n  OCTAVE_INSTALL_BOOL_INT_ASSIGNCONV(int16);\n  OCTAVE_INSTALL_BOOL_INT_ASSIGNCONV(int32);\n  OCTAVE_INSTALL_BOOL_INT_ASSIGNCONV(int64);\n\n  OCTAVE_INSTALL_BOOL_INT_ASSIGNCONV(uint8);\n  OCTAVE_INSTALL_BOOL_INT_ASSIGNCONV(uint16);\n  OCTAVE_INSTALL_BOOL_INT_ASSIGNCONV(uint32);\n  OCTAVE_INSTALL_BOOL_INT_ASSIGNCONV(uint64);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_scalar, octave_bool_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_matrix, octave_bool_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_complex, octave_bool_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_complex_matrix, octave_bool_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_float_scalar, octave_bool_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_float_matrix, octave_bool_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_float_complex_scalar, octave_bool_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_float_complex_matrix, octave_bool_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_bool, octave_bool_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_null_matrix, octave_bool_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_null_str, octave_bool_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_null_sq_str, octave_bool_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-b-bm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-bool.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// bool matrix by bool ops.\n\nDEFNDBINOP_FN (el_and, bool, bool_matrix, bool, bool_array, mx_el_and)\nDEFNDBINOP_FN (el_or, bool, bool_matrix, bool, bool_array, mx_el_or)\n\nDEFNDBINOP_FN (el_and_not, bool, bool_matrix, bool, bool_array, mx_el_and_not)\nDEFNDBINOP_FN (el_or_not, bool, bool_matrix, bool, bool_array, mx_el_or_not)\n\nDEFNDCATOP_FN (b_bm, bool, bool_matrix, bool_array, bool_array, concat)\nDEFNDCATOP_FN (b_m, bool, matrix, array, array, concat)\nDEFNDCATOP_FN (s_bm, scalar, bool_matrix, array, array, concat)\n\nDEFNDCATOP_FN (b_fm, bool, float_matrix, float_array, float_array, concat)\nDEFNDCATOP_FN (f_bm, float_scalar, bool_matrix, float_array, float_array,\n               concat)\n\nDEFCONV (bool_matrix_conv, bool, bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v, a);\n\n  return new octave_bool_matrix (v.bool_matrix_value ());\n}\n\nvoid\ninstall_b_bm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_el_and, octave_bool, octave_bool_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_bool, octave_bool_matrix, el_or);\n  INSTALL_BINOP_TI (ti, op_el_and_not, octave_bool, octave_bool_matrix, el_and_not);\n  INSTALL_BINOP_TI (ti, op_el_or_not, octave_bool, octave_bool_matrix, el_or_not);\n\n  INSTALL_CATOP_TI (ti, octave_bool, octave_bool_matrix, b_bm);\n  INSTALL_CATOP_TI (ti, octave_bool, octave_matrix, b_m);\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_bool_matrix, s_bm);\n  INSTALL_CATOP_TI (ti, octave_bool, octave_float_matrix, b_fm);\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_bool_matrix, f_bm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_bool_matrix, octave_bool_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_bool, octave_bool_matrix, bool_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-b-sbm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-bool.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ops.h\"\n\n#include \"ov-re-sparse.h\"\n#include \"ov-bool-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// bool by sparse bool matrix ops.\n\nDEFBINOP_FN (ne, bool, sparse_bool_matrix, mx_el_ne)\nDEFBINOP_FN (eq, bool, sparse_bool_matrix, mx_el_eq)\n\nDEFBINOP_FN (el_and, bool, sparse_bool_matrix, mx_el_and)\nDEFBINOP_FN (el_or, bool, sparse_bool_matrix, mx_el_or)\n\nDEFCATOP (b_sbm, bool, sparse_bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v2, a2);\n  SparseBoolMatrix tmp (1, 1, v1.bool_value ());\n  return octave_value (tmp. concat (v2.sparse_bool_matrix_value (),\n                                    ra_idx));\n}\n\nDEFCATOP (b_sm, bool, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  SparseMatrix tmp (1, 1, v1.scalar_value ());\n  return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));\n}\n\nDEFCATOP (s_sbm, scalar, sparse_bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v2, a2);\n  SparseMatrix tmp (1, 1, v1.scalar_value ());\n  return octave_value(tmp. concat (v2.sparse_matrix_value (), ra_idx));\n}\n\nDEFCONV (sparse_bool_matrix_conv, bool, sparse_bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v, a);\n\n  return new octave_sparse_bool_matrix\n         (SparseBoolMatrix (1, 1, v.bool_value ()));\n}\n\nvoid\ninstall_b_sbm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_eq, octave_bool, octave_sparse_bool_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ne, octave_bool, octave_sparse_bool_matrix, ne);\n\n  INSTALL_BINOP_TI (ti, op_el_and, octave_bool, octave_sparse_bool_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_bool, octave_sparse_bool_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_bool, octave_sparse_bool_matrix, b_sbm);\n  INSTALL_CATOP_TI (ti, octave_bool, octave_sparse_matrix, b_sm);\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_sparse_bool_matrix, s_sbm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool, octave_sparse_bool_matrix,\n                         octave_bool_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_bool, octave_sparse_bool_matrix,\n                      sparse_bool_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-bm-b.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-bool.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-str-mat.h\"\n#include \"ov-int8.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// bool matrix by bool ops.\n\nDEFNDBINOP_FN (el_and, bool_matrix, bool, bool_array, bool, mx_el_and)\nDEFNDBINOP_FN (el_or, bool_matrix, bool, bool_array, bool, mx_el_or)\n\nDEFNDBINOP_FN (el_not_and, bool_matrix, bool, bool_array, bool, mx_el_not_and)\nDEFNDBINOP_FN (el_not_or, bool_matrix, bool, bool_array, bool, mx_el_not_or)\n\nDEFNDCATOP_FN (bm_b, bool_matrix, bool, bool_array, bool_array, concat)\nDEFNDCATOP_FN (bm_s, bool_matrix, scalar, array, array, concat)\nDEFNDCATOP_FN (m_b, matrix, bool, array, array, concat)\nDEFNDCATOP_FN (bm_f, bool_matrix, float_scalar, float_array, float_array,\n               concat)\nDEFNDCATOP_FN (fm_b, float_matrix, bool, float_array, float_array, concat)\n\nDEFNDASSIGNOP_FN (assign, bool_matrix, bool, bool_array, assign)\n\nstatic octave_value\noct_assignop_conv_and_assign (octave_base_value& a1,\n                              const octave_value_list& idx,\n                              const octave_base_value& a2)\n{\n  OCTAVE_CAST_BASE_VALUE (octave_bool_matrix&, v1, a1);\n\n  boolNDArray v2 = a2.bool_array_value ();\n\n  v1.assign (idx, v2);\n\n  return octave_value ();\n}\n\nvoid\ninstall_bm_b_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_el_and, octave_bool_matrix, octave_bool, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_bool_matrix, octave_bool, el_or);\n  INSTALL_BINOP_TI (ti, op_el_not_and, octave_bool_matrix, octave_bool, el_not_and);\n  INSTALL_BINOP_TI (ti, op_el_not_or, octave_bool_matrix, octave_bool, el_not_or);\n\n  INSTALL_CATOP_TI (ti, octave_bool_matrix, octave_bool, bm_b);\n  INSTALL_CATOP_TI (ti, octave_bool_matrix, octave_scalar, bm_s);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_bool, m_b);\n  INSTALL_CATOP_TI (ti, octave_bool_matrix, octave_float_scalar, bm_f);\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_bool, fm_b);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_bool, assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_scalar,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_int8_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_int16_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_int32_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_int64_scalar,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_uint8_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_uint16_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_uint32_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_uint64_scalar,\n                       conv_and_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-bm-bm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-range.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-str-mat.h\"\n#include \"ov-int8.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// unary bool matrix ops.\n\nDEFNDUNOP_OP (not, bool_matrix, bool_array, !)\nDEFNDUNOP_OP (uplus, bool_matrix, array, +)\nDEFNDUNOP_OP (uminus, bool_matrix, array, -)\n\nDEFNCUNOP_METHOD (invert, bool_matrix, invert)\n\nDEFUNOP (transpose, bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"transpose not defined for N-D objects\");\n\n  return octave_value (v.bool_matrix_value ().transpose ());\n}\n\n// bool matrix by bool matrix ops.\n\nDEFNDBINOP_FN (eq, bool_matrix, bool_matrix, bool_array, bool_array, mx_el_eq)\nDEFNDBINOP_FN (ne, bool_matrix, bool_matrix, bool_array, bool_array, mx_el_ne)\n\nDEFNDBINOP_FN (el_and, bool_matrix, bool_matrix, bool_array, bool_array,\n               mx_el_and)\n\nDEFNDBINOP_FN (el_or,  bool_matrix, bool_matrix, bool_array, bool_array,\n               mx_el_or)\n\nDEFNDBINOP_FN (el_not_and, bool_matrix, bool_matrix, bool_array, bool_array,\n               mx_el_not_and)\n\nDEFNDBINOP_FN (el_not_or,  bool_matrix, bool_matrix, bool_array, bool_array,\n               mx_el_not_or)\n\nDEFNDBINOP_FN (el_and_not, bool_matrix, bool_matrix, bool_array, bool_array,\n               mx_el_and_not)\n\nDEFNDBINOP_FN (el_or_not,  bool_matrix, bool_matrix, bool_array, bool_array,\n               mx_el_or_not)\n\nDEFNDCATOP_FN (bm_bm, bool_matrix, bool_matrix, bool_array, bool_array, concat)\nDEFNDCATOP_FN (bm_m, bool_matrix, matrix, array, array, concat)\nDEFNDCATOP_FN (m_bm, matrix, bool_matrix, array, array, concat)\nDEFNDCATOP_FN (bm_fm, bool_matrix, float_matrix, float_array, float_array,\n               concat)\nDEFNDCATOP_FN (fm_bm, float_matrix, bool_matrix, float_array, float_array,\n               concat)\n\nDEFNDASSIGNOP_FN (assign, bool_matrix, bool_matrix, bool_array, assign)\nDEFNDASSIGNOP_FNOP (assign_and, bool_matrix, bool_matrix, bool_array,\n                    mx_el_and_assign)\nDEFNDASSIGNOP_FNOP (assign_or, bool_matrix, bool_matrix, bool_array,\n                    mx_el_or_assign)\n\nDEFNULLASSIGNOP_FN (null_assign, bool_matrix, delete_elements)\n\nstatic octave_value\noct_assignop_conv_and_assign (octave_base_value& a1,\n                              const octave_value_list& idx,\n                              const octave_base_value& a2)\n{\n  OCTAVE_CAST_BASE_VALUE (octave_bool_matrix&, v1, a1);\n\n  boolNDArray v2 = a2.bool_array_value ();\n\n  v1.assign (idx, v2);\n\n  return octave_value ();\n}\n\nvoid\ninstall_bm_bm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_bool_matrix, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_bool_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_bool_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_bool_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_bool_matrix, transpose);\n\n  INSTALL_NCUNOP_TI (ti, op_not, octave_bool_matrix, invert);\n\n  INSTALL_BINOP_TI (ti, op_eq, octave_bool_matrix, octave_bool_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ne, octave_bool_matrix, octave_bool_matrix, ne);\n\n  INSTALL_BINOP_TI (ti, op_el_and, octave_bool_matrix, octave_bool_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_bool_matrix, octave_bool_matrix, el_or);\n  INSTALL_BINOP_TI (ti, op_el_not_and, octave_bool_matrix, octave_bool_matrix,\n                    el_not_and);\n  INSTALL_BINOP_TI (ti, op_el_not_or, octave_bool_matrix, octave_bool_matrix,\n                    el_not_or);\n  INSTALL_BINOP_TI (ti, op_el_and_not, octave_bool_matrix, octave_bool_matrix,\n                    el_and_not);\n  INSTALL_BINOP_TI (ti, op_el_or_not, octave_bool_matrix, octave_bool_matrix,\n                    el_or_not);\n\n  INSTALL_CATOP_TI (ti, octave_bool_matrix, octave_bool_matrix, bm_bm);\n  INSTALL_CATOP_TI (ti, octave_bool_matrix, octave_matrix, bm_m);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_bool_matrix, m_bm);\n  INSTALL_CATOP_TI (ti, octave_bool_matrix, octave_float_matrix, bm_fm);\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_bool_matrix, fm_bm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_bool_matrix,\n                       assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_char_matrix_str,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix,\n                       octave_char_matrix_sq_str,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_range,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_sparse_matrix,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_int8_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_int16_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_int32_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_int64_matrix,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_uint8_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_uint16_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_uint32_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_uint64_matrix,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_null_matrix,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_null_str,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix, octave_null_sq_str,\n                       null_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_el_and_eq, octave_bool_matrix, octave_bool_matrix,\n                       assign_and);\n  INSTALL_ASSIGNOP_TI (ti, op_el_or_eq, octave_bool_matrix, octave_bool_matrix,\n                       assign_or);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-bm-sbm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-bool-mat.h\"\n#include \"boolMatrix.h\"\n#include \"ov-scalar.h\"\n#include \"ops.h\"\n\n#include \"ov-re-sparse.h\"\n#include \"ov-bool-sparse.h\"\n#include \"smx-bm-sbm.h\"\n#include \"smx-sbm-bm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// bool matrix by sparse bool matrix ops.\n\nDEFBINOP_FN (eq, bool_matrix, sparse_bool_matrix, mx_el_eq)\nDEFBINOP_FN (ne, bool_matrix, sparse_bool_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_and, bool_matrix, sparse_bool_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  bool_matrix, sparse_bool_matrix, mx_el_or)\n\nDEFCATOP (bm_sbm, bool_matrix, sparse_bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v2, a2);\n  SparseBoolMatrix tmp (v1.bool_matrix_value ());\n  return octave_value (tmp. concat (v2.sparse_bool_matrix_value (),\n                                    ra_idx));\n}\n\nDEFCATOP (m_sbm, matrix, sparse_bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v2, a2);\n  SparseMatrix tmp (v1.matrix_value ());\n  return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));\n}\n\nDEFCATOP (bm_sm, bool_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  SparseMatrix tmp (v1.matrix_value ());\n  return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));\n}\n\nDEFCONV (sparse_bool_matrix_conv, bool_matrix, sparse_bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v, a);\n  return new octave_sparse_bool_matrix\n         (SparseBoolMatrix (v.bool_matrix_value ()));\n}\n\nDEFNDASSIGNOP_FN (assign, bool_matrix, sparse_bool_matrix, bool_array, assign)\n\nvoid\ninstall_bm_sbm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_eq, octave_bool_matrix, octave_sparse_bool_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ne, octave_bool_matrix, octave_sparse_bool_matrix, ne);\n\n  INSTALL_BINOP_TI (ti, op_el_and, octave_bool_matrix, octave_sparse_bool_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_bool_matrix, octave_sparse_bool_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_bool_matrix, octave_sparse_bool_matrix, bm_sbm);\n  INSTALL_CATOP_TI (ti, octave_bool_matrix, octave_sparse_matrix, bm_sm);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_sparse_bool_matrix, m_sbm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_bool_matrix,\n                       octave_sparse_bool_matrix,\n                       assign)\n  INSTALL_ASSIGNCONV_TI (ti, octave_bool_matrix, octave_sparse_bool_matrix,\n                         octave_bool_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_bool_matrix, octave_sparse_bool_matrix,\n                      sparse_bool_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cdm-cdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-cx-diag.h\"\n#include \"ov-flt-cx-diag.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix unary ops.\n\nDEFUNOP_OP (uplus, complex_diag_matrix, /* no-op */)\nDEFUNOP_OP (uminus, complex_diag_matrix, -)\n\nDEFUNOP (transpose, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v, a);\n  return octave_value (v.complex_diag_matrix_value ().transpose ());\n}\n\nDEFUNOP (hermitian, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v, a);\n  return octave_value (v.complex_diag_matrix_value ().hermitian ());\n}\n\n// matrix by matrix ops.\n\nDEFBINOP_OP (add, complex_diag_matrix, complex_diag_matrix, +)\nDEFBINOP_OP (sub, complex_diag_matrix, complex_diag_matrix, -)\nDEFBINOP_OP (mul, complex_diag_matrix, complex_diag_matrix, *)\n\nDEFBINOP (div, complex_diag_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  return xdiv (v1.complex_diag_matrix_value (),\n               v2.complex_diag_matrix_value ());\n}\n\nDEFBINOP (ldiv, complex_diag_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  return xleftdiv (v1.complex_diag_matrix_value (),\n                   v2.complex_diag_matrix_value ());\n}\n\nCONVDECL (complex_diag_matrix_to_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v, a);\n\n  return new octave_complex_matrix (v.complex_matrix_value ());\n}\n\nvoid\ninstall_cdm_cdm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_uplus, octave_complex_diag_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_complex_diag_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_complex_diag_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_complex_diag_matrix, hermitian);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_complex_diag_matrix,\n                    octave_complex_diag_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex_diag_matrix,\n                    octave_complex_diag_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex_diag_matrix,\n                    octave_complex_diag_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex_diag_matrix,\n                    octave_complex_diag_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex_diag_matrix,\n                    octave_complex_diag_matrix, ldiv);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex_diag_matrix, octave_complex_matrix,\n                         octave_complex_matrix);\n  INSTALL_WIDENOP_TI (ti, octave_complex_diag_matrix, octave_complex_matrix,\n                      complex_diag_matrix_to_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cdm-cm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-cx-diag.h\"\n#define RINCLUDE \"ov-cx-mat.h\"\n\n#define LMATRIX complex_diag_matrix\n#define RMATRIX complex_matrix\n\n#define LSHORT cdm\n#define RSHORT cm\n\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-cdm-cs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define SINCLUDE \"ov-complex.h\"\n#define MINCLUDE \"ov-cx-diag.h\"\n\n#define SCALAR complex\n#define DIAG_MATRIX complex_diag_matrix\n#define MATRIX complex_matrix\n\n#define SSHORT cs\n#define MSHORT cdm\n\n#include \"op-dms-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-cdm-dm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-cx-diag.h\"\n#define RINCLUDE \"ov-re-diag.h\"\n\n#define LMATRIX complex_diag_matrix\n#define RMATRIX diag_matrix\n#define RDMATRIX LMATRIX\n\n#define LSHORT cdm\n#define RSHORT dm\n\n#define DEFINEDIV\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-cdm-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-cx-diag.h\"\n#define RINCLUDE \"ov-re-mat.h\"\n\n#define LMATRIX complex_diag_matrix\n#define LDMATRIX complex_matrix\n#define RMATRIX matrix\n#define RDMATRIX complex_matrix\n\n#define LSHORT cdm\n#define RSHORT m\n\n#define DEFINELDIV\n#define DEFINENULLASSIGNCONV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-cdm-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define SINCLUDE \"ov-scalar.h\"\n#define MINCLUDE \"ov-cx-diag.h\"\n\n#define SCALAR scalar\n#define SCALARV complex\n#define DIAG_MATRIX complex_diag_matrix\n#define MATRIX complex_matrix\n\n#define SSHORT s\n#define MSHORT cdm\n\n#include \"op-dms-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-cell.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cell.h\"\n#include \"ov-scalar.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// cell ops.\n\nDEFUNOP (transpose, cell)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_cell&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"transpose not defined for N-D objects\");\n\n  return octave_value (Cell (v.cell_value ().transpose ()));\n}\n\nDEFCATOP_FN (c_c, cell, cell, concat)\n\nDEFASSIGNANYOP_FN (assign, cell, assign);\n\nDEFNULLASSIGNOP_FN (null_assign, cell, delete_elements)\n\nvoid\ninstall_cell_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_transpose, octave_cell, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_cell, transpose);\n\n  INSTALL_CATOP_TI (ti, octave_cell, octave_cell, c_c);\n\n  INSTALL_ASSIGNANYOP_TI (ti, op_asn_eq, octave_cell, assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_cell, octave_null_matrix,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_cell, octave_null_str, null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_cell, octave_null_sq_str,\n                       null_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-chm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-ch-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-bool.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// char matrix unary ops.\n\nDEFUNOP (transpose, char_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v, a);\n\n  return octave_value (v.matrix_value ().transpose ());\n}\n\nDEFNDCATOP_FN (chm_chm, char_matrix, char_matrix, char_array, char_array,\n               concat)\n\nDEFCATOP (chm_s, char_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  warn_implicit_conversion (\"Octave:num-to-str\",\n                            v2.type_name (), v1.type_name ());\n\n  return octave_value (v1.char_array_value (). concat (v2.array_value (),\n                       ra_idx));\n}\n\nDEFCATOP (chm_m, char_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  warn_implicit_conversion (\"Octave:num-to-str\",\n                            v2.type_name (), v1.type_name ());\n\n  return octave_value (v1.char_array_value (). concat (v2.array_value (),\n                       ra_idx));\n}\n\nDEFCATOP (s_chm, scalar, char_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v2, a2);\n\n  warn_implicit_conversion (\"Octave:num-to-str\",\n                            v1.type_name (), v2.type_name ());\n\n  return octave_value (v1.array_value (). concat (v2.char_array_value (),\n                       ra_idx));\n}\n\nDEFCATOP (m_chm, matrix, char_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v2, a2);\n\n  warn_implicit_conversion (\"Octave:num-to-str\",\n                            v1.type_name (), v2.type_name ());\n\n  return octave_value (v1.array_value (). concat (v2.char_array_value (),\n                       ra_idx));\n}\n\nvoid\ninstall_chm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_transpose, octave_char_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_char_matrix, transpose);\n\n  INSTALL_CATOP_TI (ti, octave_char_matrix, octave_char_matrix, chm_chm);\n  INSTALL_CATOP_TI (ti, octave_char_matrix, octave_scalar, chm_s);\n  INSTALL_CATOP_TI (ti, octave_char_matrix, octave_matrix, chm_m);\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_char_matrix, s_chm);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_char_matrix, m_chm);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-class.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n//! @file op-class.cc\n//! Unary and binary operators for classdef and old style classes.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-time.h\"\n\n#include \"cdef-utils.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"load-path.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-class.h\"\n#include \"ov-classdef.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"symtab.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n//! Default unary class operator.\n//!\n//! @param a operand\n//! @param opname operator name\n\nstatic octave_value\noct_unop_default (const octave_value& a, const std::string& opname)\n{\n  std::string class_name = a.class_name ();\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value meth = symtab.find_method (opname, class_name);\n\n  if (meth.is_defined ())\n    {\n      // Call overloaded unary class operator.\n      octave_value_list tmp\n        = interp.feval (meth.function_value (), ovl (a), 1);\n\n      // Return first element if present.\n      if (tmp.length () > 0)\n        return tmp(0);\n\n      return octave_value ();\n    }\n\n  // Matlab compatibility: If (conjugate) transpose is not overloaded and\n  // the number of dimensions is maximal two, just transpose the array of\n  // that class.\n\n  if ((opname == \"transpose\") || (opname == \"ctranspose\"))\n    {\n      if (a.ndims () > 2)\n        error (\"%s not defined for N-D objects of %s class\", opname.c_str (),\n               class_name.c_str ());\n\n      if (a.is_classdef_object ())\n        {\n          auto result_obj = a.classdef_object_value ()->get_object_ref ().transpose ();\n          return new octave_classdef (result_obj);\n        }\n      else\n        {\n          OCTAVE_CAST_BASE_VALUE (const octave_class&, v, a.get_rep ());\n\n          return octave_value (v.map_value ().transpose (),\n                               v.class_name (),\n                               v.parent_class_name_list ());\n        }\n    }\n  else\n    error (\"%s method not defined for %s class\", opname.c_str (),\n           class_name.c_str ());\n}\n\n//! Helper macro to define unary class operators.\n\n#define DEF_CLASS_UNOP(opname)                 \\\n  static octave_value                          \\\n  oct_unop_ ## opname (const octave_value& a)  \\\n  {                                            \\\n    return oct_unop_default (a, #opname);      \\\n  }\n\nDEF_CLASS_UNOP (not)         // !a or ~a\nDEF_CLASS_UNOP (uplus)       // +a\nDEF_CLASS_UNOP (uminus)      // -a\nDEF_CLASS_UNOP (transpose)   //  a.'\nDEF_CLASS_UNOP (ctranspose)  //  a'\n#undef DEF_CLASS_UNOP\n\n//! Default binary class operator.\n//!\n//! @param a1 first  operand\n//! @param a2 second operand\n//! @param opname operator name\n//!\n//! The operator precedence is as follows:\n//!\n//! 1.   If exactly one of the operands is a user defined class object, then\n//!      the class method of that operand is invoked.\n//!\n//! 2.   If both operands are user defined class objects, then\n//! 2.1  The superior class method is invoked.\n//! 2.2  The leftmost class method is invoked if both classes are the same\n//!      or their precedence is not defined by superiorto/inferiorto.\n\nstatic octave_value\noct_binop_default (const octave_value& a1, const octave_value& a2,\n                   const std::string& opname)\n{\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  octave::symbol_table& symtab = interp.get_symbol_table ();\n\n  // Dispatch to first (leftmost) operand by default.\n  std::string dispatch_type = a1.class_name ();\n\n  // Determine, if second operand takes precedence (see rules above).\n  if (! a1.isobject ()\n      || (a1.isobject () && a2.isobject ()\n          && symtab.is_superiorto (a2.class_name (), dispatch_type)))\n    dispatch_type = a2.class_name ();\n\n  octave_value meth = symtab.find_method (opname, dispatch_type);\n\n  if (meth.is_undefined ())\n    error (\"%s method not defined for %s class\", opname.c_str (),\n           dispatch_type.c_str ());\n\n  octave_value_list tmp\n    = interp.feval (meth.function_value (), ovl (a1, a2), 1);\n\n  if (tmp.length () > 0)\n    return tmp(0);\n\n  return octave_value ();\n}\n\n//! Helper macro to define binary class operators.\n\n#define DEF_CLASS_BINOP(opname)                                          \\\n  static octave_value                                                    \\\n  oct_binop_ ## opname (const octave_value& a1, const octave_value& a2)  \\\n  {                                                                      \\\n    return oct_binop_default (a1, a2, #opname);                          \\\n  }\n\nDEF_CLASS_BINOP (plus)     // a1 + a2\nDEF_CLASS_BINOP (minus)    // a1 - a2\nDEF_CLASS_BINOP (mtimes)   // a1 * a2\nDEF_CLASS_BINOP (mrdivide) // a1 / a2\nDEF_CLASS_BINOP (mpower)   // a1 ^ a2\nDEF_CLASS_BINOP (mldivide) // a1 \\ a2\nDEF_CLASS_BINOP (lt)       // a1 <  a2\nDEF_CLASS_BINOP (le)       // a1 <= a2\nDEF_CLASS_BINOP (eq)       // a1 <= a2\nDEF_CLASS_BINOP (ge)       // a1 >= a2\nDEF_CLASS_BINOP (gt)       // a1 >  a2\nDEF_CLASS_BINOP (ne)       // a1 ~= a2 or a1 != a2\nDEF_CLASS_BINOP (times)    // a1 .* a2\nDEF_CLASS_BINOP (rdivide)  // a1 ./ a2\nDEF_CLASS_BINOP (power)    // a1 .^ a2\nDEF_CLASS_BINOP (ldivide)  // a1 .\\ a2\nDEF_CLASS_BINOP (and)      // a1 & a2\nDEF_CLASS_BINOP (or)       // a1 | a2\n#undef DEF_CLASS_BINOP\n\nvoid\ninstall_class_ops (octave::type_info& ti)\n{\n  ti.install_unary_class_op (octave_value::op_not,       oct_unop_not);\n  ti.install_unary_class_op (octave_value::op_uplus,     oct_unop_uplus);\n  ti.install_unary_class_op (octave_value::op_uminus,    oct_unop_uminus);\n  ti.install_unary_class_op (octave_value::op_transpose, oct_unop_transpose);\n  ti.install_unary_class_op (octave_value::op_hermitian, oct_unop_ctranspose);\n\n  ti.install_binary_class_op (octave_value::op_add,     oct_binop_plus);\n  ti.install_binary_class_op (octave_value::op_sub,     oct_binop_minus);\n  ti.install_binary_class_op (octave_value::op_mul,     oct_binop_mtimes);\n  ti.install_binary_class_op (octave_value::op_div,     oct_binop_mrdivide);\n  ti.install_binary_class_op (octave_value::op_pow,     oct_binop_mpower);\n  ti.install_binary_class_op (octave_value::op_ldiv,    oct_binop_mldivide);\n  ti.install_binary_class_op (octave_value::op_lt,      oct_binop_lt);\n  ti.install_binary_class_op (octave_value::op_le,      oct_binop_le);\n  ti.install_binary_class_op (octave_value::op_eq,      oct_binop_eq);\n  ti.install_binary_class_op (octave_value::op_ge,      oct_binop_ge);\n  ti.install_binary_class_op (octave_value::op_gt,      oct_binop_gt);\n  ti.install_binary_class_op (octave_value::op_ne,      oct_binop_ne);\n  ti.install_binary_class_op (octave_value::op_el_mul,  oct_binop_times);\n  ti.install_binary_class_op (octave_value::op_el_div,  oct_binop_rdivide);\n  ti.install_binary_class_op (octave_value::op_el_pow,  oct_binop_power);\n  ti.install_binary_class_op (octave_value::op_el_ldiv, oct_binop_ldivide);\n  ti.install_binary_class_op (octave_value::op_el_and,  oct_binop_and);\n  ti.install_binary_class_op (octave_value::op_el_or,   oct_binop_or);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cm-cdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-cx-mat.h\"\n#define RINCLUDE \"ov-cx-diag.h\"\n\n#define LMATRIX complex_matrix\n#define RMATRIX complex_diag_matrix\n\n#define LSHORT cm\n#define RSHORT cdm\n\n#define DEFINEDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-cm-cm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// unary complex matrix ops.\n\nDEFNDUNOP_OP (not, complex_matrix, complex_array, !)\nDEFNDUNOP_OP (uplus, complex_matrix, complex_array, /* no-op */)\nDEFNDUNOP_OP (uminus, complex_matrix, complex_array, -)\n\nDEFUNOP (transpose, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"transpose not defined for N-D objects\");\n\n  return octave_value (v.complex_matrix_value ().transpose ());\n}\n\nDEFUNOP (hermitian, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"complex-conjugate transpose not defined for N-D objects\");\n\n  return octave_value (v.complex_matrix_value ().hermitian ());\n}\n\nDEFNCUNOP_METHOD (incr, complex_matrix, increment)\nDEFNCUNOP_METHOD (decr, complex_matrix, decrement)\nDEFNCUNOP_METHOD (changesign, complex_matrix, changesign)\n\n// complex matrix by complex matrix ops.\n\nDEFNDBINOP_OP (add, complex_matrix, complex_matrix, complex_array,\n               complex_array, +)\nDEFNDBINOP_OP (sub, complex_matrix, complex_matrix, complex_array,\n               complex_array, -)\n\nDEFBINOP_OP (mul, complex_matrix, complex_matrix, *)\n\nDEFBINOP (div, complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  ComplexMatrix ret = xdiv (v1.complex_matrix_value (),\n                            v2.complex_matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, complex_matrix, complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),\n                                v2.complex_matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP (trans_mul, complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  return octave_value(xgemm (v1.complex_matrix_value (),\n                             v2.complex_matrix_value (),\n                             blas_trans, blas_no_trans));\n}\n\nDEFBINOP (mul_trans, complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  return octave_value(xgemm (v1.complex_matrix_value (),\n                             v2.complex_matrix_value (),\n                             blas_no_trans, blas_trans));\n}\n\nDEFBINOP (herm_mul, complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  return octave_value(xgemm (v1.complex_matrix_value (),\n                             v2.complex_matrix_value (),\n                             blas_conj_trans, blas_no_trans));\n}\n\nDEFBINOP (mul_herm, complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  return octave_value(xgemm (v1.complex_matrix_value (),\n                             v2.complex_matrix_value (),\n                             blas_no_trans, blas_conj_trans));\n}\n\nDEFBINOP (trans_ldiv, complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),\n                                v2.complex_matrix_value (), typ, blas_trans);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP (herm_ldiv, complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),\n                                v2.complex_matrix_value (), typ,\n                                blas_conj_trans);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, complex_matrix, complex_matrix, complex_array,\n                    complex_array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, complex_matrix, complex_matrix, complex_array,\n                    complex_array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, complex_matrix, complex_matrix, complex_array,\n                    complex_array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, complex_matrix, complex_matrix, complex_array,\n                    complex_array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, complex_matrix, complex_matrix, complex_array,\n                    complex_array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, complex_matrix, complex_matrix, complex_array,\n                    complex_array, mx_el_ne)\n\nDEFNDBINOP_FN (el_mul, complex_matrix, complex_matrix, complex_array,\n               complex_array, product)\nDEFNDBINOP_FN (el_div, complex_matrix, complex_matrix, complex_array,\n               complex_array, quotient)\nDEFNDBINOP_FN (el_pow, complex_matrix, complex_matrix, complex_array,\n               complex_array, elem_xpow)\n\nDEFBINOP (el_ldiv, complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return octave_value (quotient (v2.complex_array_value (),\n                                 v1.complex_array_value ()));\n}\n\nDEFNDBINOP_FN (el_and, complex_matrix, complex_matrix, complex_array,\n               complex_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  complex_matrix, complex_matrix, complex_array,\n               complex_array, mx_el_or)\n\nDEFNDCATOP_FN (cm_cm, complex_matrix, complex_matrix, complex_array,\n               complex_array, concat)\n\nDEFNDASSIGNOP_FN (assign, complex_matrix, complex_matrix, complex_array, assign)\n\nDEFNULLASSIGNOP_FN (null_assign, complex_matrix, delete_elements)\n\nDEFNDASSIGNOP_OP (assign_add, complex_matrix, complex_matrix, complex_array, +=)\nDEFNDASSIGNOP_OP (assign_sub, complex_matrix, complex_matrix, complex_array, -=)\nDEFNDASSIGNOP_FNOP (assign_el_mul, complex_matrix, complex_matrix,\n                    complex_array, product_eq)\nDEFNDASSIGNOP_FNOP (assign_el_div, complex_matrix, complex_matrix,\n                    complex_array, quotient_eq)\n\nvoid\ninstall_cm_cm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_complex_matrix, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_complex_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_complex_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_complex_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_complex_matrix, hermitian);\n\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_complex_matrix, incr);\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_complex_matrix, decr);\n  INSTALL_NCUNOP_TI (ti, op_uminus, octave_complex_matrix, changesign);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_complex_matrix, octave_complex_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex_matrix, octave_complex_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex_matrix, octave_complex_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex_matrix, octave_complex_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex_matrix, octave_complex_matrix,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex_matrix, octave_complex_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_trans_mul, octave_complex_matrix,\n                    octave_complex_matrix,\n                    trans_mul);\n  INSTALL_BINOP_TI (ti, op_mul_trans, octave_complex_matrix,\n                    octave_complex_matrix,\n                    mul_trans);\n  INSTALL_BINOP_TI (ti, op_herm_mul, octave_complex_matrix, octave_complex_matrix,\n                    herm_mul);\n  INSTALL_BINOP_TI (ti, op_mul_herm, octave_complex_matrix, octave_complex_matrix,\n                    mul_herm);\n  INSTALL_BINOP_TI (ti, op_trans_ldiv, octave_complex_matrix,\n                    octave_complex_matrix,\n                    trans_ldiv);\n  INSTALL_BINOP_TI (ti, op_herm_ldiv, octave_complex_matrix,\n                    octave_complex_matrix,\n                    herm_ldiv);\n\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex_matrix, octave_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex_matrix, octave_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex_matrix, octave_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex_matrix, octave_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex_matrix, octave_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex_matrix, octave_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex_matrix, octave_complex_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex_matrix, octave_complex_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex_matrix, octave_complex_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex_matrix, octave_complex_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex_matrix, octave_complex_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex_matrix, octave_complex_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex_matrix, octave_complex_matrix, cm_cm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix,\n                       octave_complex_matrix,\n                       assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix, octave_null_matrix,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix, octave_null_str,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix, octave_null_sq_str,\n                       null_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_complex_matrix,\n                       octave_complex_matrix,\n                       assign_add);\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_complex_matrix,\n                       octave_complex_matrix,\n                       assign_sub);\n  INSTALL_ASSIGNOP_TI (ti, op_el_mul_eq, octave_complex_matrix,\n                       octave_complex_matrix,\n                       assign_el_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_el_div_eq, octave_complex_matrix,\n                       octave_complex_matrix,\n                       assign_el_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cm-cs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-complex.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex matrix by complex scalar ops.\n\nDEFNDBINOP_OP (add, complex_matrix, complex, complex_array, complex, +)\nDEFNDBINOP_OP (sub, complex_matrix, complex, complex_array, complex, -)\nDEFNDBINOP_OP (mul, complex_matrix, complex, complex_array, complex, *)\n\nDEFBINOP (div, complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.complex_array_value () / v2.complex_value ());\n}\n\nDEFBINOP_FN (pow, complex_matrix, complex, xpow)\n\nDEFBINOP (ldiv, complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  ComplexMatrix m1 = v1.complex_matrix_value ();\n  ComplexMatrix m2 = v2.complex_matrix_value ();\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (m1, m2, typ);\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, complex_matrix, complex, complex_array, complex,\n                    mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, complex_matrix, complex, complex_array, complex,\n                    mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, complex_matrix, complex, complex_array, complex,\n                    mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, complex_matrix, complex, complex_array, complex,\n                    mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, complex_matrix, complex, complex_array, complex,\n                    mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, complex_matrix, complex, complex_array, complex,\n                    mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, complex_matrix, complex, complex_array, complex, *)\n\nDEFBINOP (el_div, complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.complex_array_value () / v2.complex_value ());\n}\n\nDEFNDBINOP_FN (el_pow, complex_matrix, complex, complex_array, complex,\n               elem_xpow)\n\nDEFBINOP (el_ldiv, complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return elem_xdiv (v2.complex_value (), v1.complex_array_value ());\n}\n\nDEFNDBINOP_FN (el_and, complex_matrix, complex, complex_array, complex,\n               mx_el_and)\nDEFNDBINOP_FN (el_or,  complex_matrix, complex, complex_array, complex,\n               mx_el_or)\n\nDEFNDCATOP_FN (cm_cs, complex_matrix, complex, complex_array, complex_array,\n               concat)\n\nDEFNDASSIGNOP_FN (assign, complex_matrix, complex, complex, assign)\nDEFNDASSIGNOP_FN (sgl_assign, float_complex_matrix, complex, float_complex,\n                  assign)\n\nDEFNDASSIGNOP_OP (assign_add, complex_matrix, complex_scalar, complex, +=)\nDEFNDASSIGNOP_OP (assign_sub, complex_matrix, complex_scalar, complex, -=)\nDEFNDASSIGNOP_OP (assign_mul, complex_matrix, complex_scalar, complex, *=)\nDEFNDASSIGNOP_OP (assign_div, complex_matrix, complex_scalar, complex, /=)\n\nvoid\ninstall_cm_cs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex_matrix, octave_complex, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex_matrix, octave_complex, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex_matrix, octave_complex, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex_matrix, octave_complex, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex_matrix, octave_complex, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex_matrix, octave_complex, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex_matrix, octave_complex, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex_matrix, octave_complex, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex_matrix, octave_complex, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex_matrix, octave_complex, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex_matrix, octave_complex, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex_matrix, octave_complex, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex_matrix, octave_complex, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex_matrix, octave_complex, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex_matrix, octave_complex, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex_matrix, octave_complex,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex_matrix, octave_complex, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex_matrix, octave_complex, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex_matrix, octave_complex, cm_cs);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix, octave_complex,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix, octave_complex,\n                       sgl_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_complex_matrix,\n                       octave_complex_scalar,\n                       assign_add);\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_complex_matrix,\n                       octave_complex_scalar,\n                       assign_sub);\n  INSTALL_ASSIGNOP_TI (ti, op_mul_eq, octave_complex_matrix,\n                       octave_complex_scalar,\n                       assign_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_div_eq, octave_complex_matrix,\n                       octave_complex_scalar,\n                       assign_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cm-dm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-cx-mat.h\"\n#define RINCLUDE \"ov-re-diag.h\"\n\n#define LMATRIX complex_matrix\n#define RMATRIX diag_matrix\n\n#define LSHORT cm\n#define RSHORT dm\n\n#define DEFINEDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-cm-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-cm-m.h\"\n#include \"mx-m-cm.h\"\n#include \"mx-cnda-nda.h\"\n#include \"mx-nda-cnda.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex matrix by matrix ops.\n\nDEFNDBINOP_OP (add, complex_matrix, matrix, complex_array, array, +)\nDEFNDBINOP_OP (sub, complex_matrix, matrix, complex_array, array, -)\n\nDEFBINOP_OP (mul, complex_matrix, matrix, *)\n\nDEFBINOP (mul_trans, complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  ComplexMatrix m1 = v1.complex_matrix_value ();\n  Matrix m2 = v2.matrix_value ();\n\n  return ComplexMatrix (xgemm (real (m1), m2, blas_no_trans, blas_trans),\n                        xgemm (imag (m1), m2, blas_no_trans, blas_trans));\n}\n\nDEFBINOP (div, complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  ComplexMatrix ret = xdiv (v1.complex_matrix_value (),\n                            v2.matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, complex_matrix, matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),\n                                v2.matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, complex_matrix, matrix, complex_array, array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, complex_matrix, matrix, complex_array, array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, complex_matrix, matrix, complex_array, array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, complex_matrix, matrix, complex_array, array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, complex_matrix, matrix, complex_array, array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, complex_matrix, matrix, complex_array, array, mx_el_ne)\n\nDEFNDBINOP_FN (el_mul, complex_matrix, matrix, complex_array, array, product)\nDEFNDBINOP_FN (el_div, complex_matrix, matrix, complex_array, array, quotient)\nDEFNDBINOP_FN (el_pow, complex_matrix, matrix, complex_array, array, elem_xpow)\n\nDEFBINOP (el_ldiv, complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return quotient (v2.array_value (), v1.complex_array_value ());\n}\n\nDEFNDBINOP_FN (el_and, complex_matrix, matrix, complex_array, array, mx_el_and)\nDEFNDBINOP_FN (el_or,  complex_matrix, matrix, complex_array, array, mx_el_or)\n\nDEFNDCATOP_FN (cm_m, complex_matrix, matrix, complex_array, array, concat)\n\nDEFNDASSIGNOP_FN (assign, complex_matrix, matrix, complex_array, assign)\n\nvoid\ninstall_cm_m_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex_matrix, octave_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex_matrix, octave_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex_matrix, octave_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex_matrix, octave_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex_matrix, octave_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex_matrix, octave_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex_matrix, octave_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex_matrix, octave_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex_matrix, octave_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex_matrix, octave_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex_matrix, octave_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex_matrix, octave_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex_matrix, octave_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex_matrix, octave_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex_matrix, octave_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex_matrix, octave_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex_matrix, octave_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex_matrix, octave_matrix, el_or);\n  INSTALL_BINOP_TI (ti, op_mul_trans, octave_complex_matrix, octave_matrix,\n                    mul_trans);\n  INSTALL_BINOP_TI (ti, op_mul_herm, octave_complex_matrix, octave_matrix,\n                    mul_trans);\n\n  INSTALL_CATOP_TI (ti, octave_complex_matrix, octave_matrix, cm_m);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix, octave_matrix,\n                       assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cm-pm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define MINCLUDE \"ov-cx-mat.h\"\n\n#define LMATRIX complex_matrix\n#define RMATRIX perm_matrix\n\n#define LSHORT cm\n#define RSHORT pm\n\n#define RIGHT\n\n#include \"op-pm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-cm-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-cm-s.h\"\n#include \"mx-cnda-s.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex matrix by scalar ops.\n\nDEFNDBINOP_OP (add, complex_matrix, scalar, complex_array, scalar, +)\nDEFNDBINOP_OP (sub, complex_matrix, scalar, complex_array, scalar, -)\nDEFNDBINOP_OP (mul, complex_matrix, scalar, complex_array, scalar, *)\n\nDEFBINOP (div, complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.complex_array_value () / v2.double_value ());\n}\n\nDEFBINOP_FN (pow, complex_matrix, scalar, xpow)\n\nDEFBINOP (ldiv, complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  ComplexMatrix m1 = v1.complex_matrix_value ();\n  Matrix m2 = v2.matrix_value ();\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (m1, m2, typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, complex_matrix, scalar, complex_array, scalar, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, complex_matrix, scalar, complex_array, scalar, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, complex_matrix, scalar, complex_array, scalar, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, complex_matrix, scalar, complex_array, scalar, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, complex_matrix, scalar, complex_array, scalar, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, complex_matrix, scalar, complex_array, scalar, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, complex_matrix, scalar, complex_array, scalar, *)\n\nDEFBINOP (el_div, complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.complex_array_value () / v2.double_value ());\n}\n\nDEFNDBINOP_FN (el_pow, complex_matrix, scalar, complex_array, scalar, elem_xpow)\n\nDEFBINOP (el_ldiv, complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return elem_xdiv (v2.double_value (), v1.complex_array_value ());\n}\n\nDEFNDBINOP_FN (el_and, complex_matrix, scalar, complex_array, scalar, mx_el_and)\nDEFNDBINOP_FN (el_or,  complex_matrix, scalar, complex_array, scalar, mx_el_or)\n\nDEFNDCATOP_FN (cm_s, complex_matrix, scalar, complex_array, array, concat)\n\nDEFNDASSIGNOP_FN (assign, complex_matrix, scalar, complex_array, assign)\n\nDEFNDASSIGNOP_OP (assign_mul, complex_matrix, scalar, scalar, *=)\nDEFNDASSIGNOP_OP (assign_div, complex_matrix, scalar, scalar, /=)\n\nvoid\ninstall_cm_s_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex_matrix, octave_scalar, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex_matrix, octave_scalar, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex_matrix, octave_scalar, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex_matrix, octave_scalar, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex_matrix, octave_scalar, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex_matrix, octave_scalar, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex_matrix, octave_scalar, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex_matrix, octave_scalar, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex_matrix, octave_scalar, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex_matrix, octave_scalar, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex_matrix, octave_scalar, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex_matrix, octave_scalar, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex_matrix, octave_scalar, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex_matrix, octave_scalar, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex_matrix, octave_scalar, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex_matrix, octave_scalar,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex_matrix, octave_scalar, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex_matrix, octave_scalar, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex_matrix, octave_scalar, cm_s);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix, octave_scalar,\n                       assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_mul_eq, octave_complex_matrix, octave_scalar,\n                       assign_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_div_eq, octave_complex_matrix, octave_scalar,\n                       assign_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cm-scm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-cx-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-scm-cm.h\"\n#include \"smx-cm-scm.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex matrix by sparse complex matrix ops.\n\nDEFBINOP_OP (add, complex_matrix, sparse_complex_matrix, +)\nDEFBINOP_OP (sub, complex_matrix, sparse_complex_matrix, -)\n\nDEFBINOP_OP (mul, complex_matrix, sparse_complex_matrix, *)\n\nDEFBINOP (div, complex_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.complex_array_value () / v2.complex_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n\n      ComplexMatrix ret = xdiv (v1.complex_matrix_value (),\n                                v2.sparse_complex_matrix_value (), typ);\n\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOPX (pow, complex_matrix, sparse_complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, complex_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),\n                                v2.complex_matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (mul_trans, complex_matrix, sparse_complex_matrix, mul_trans);\nDEFBINOP_FN (mul_herm, complex_matrix, sparse_complex_matrix, mul_herm);\n\nDEFBINOP_FN (lt, complex_matrix, sparse_complex_matrix, mx_el_lt)\nDEFBINOP_FN (le, complex_matrix, sparse_complex_matrix, mx_el_le)\nDEFBINOP_FN (eq, complex_matrix, sparse_complex_matrix, mx_el_eq)\nDEFBINOP_FN (ge, complex_matrix, sparse_complex_matrix, mx_el_ge)\nDEFBINOP_FN (gt, complex_matrix, sparse_complex_matrix, mx_el_gt)\nDEFBINOP_FN (ne, complex_matrix, sparse_complex_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, complex_matrix, sparse_complex_matrix, product)\nDEFBINOP_FN (el_div, complex_matrix, sparse_complex_matrix, quotient)\n\nDEFBINOP (el_pow, complex_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return octave_value\n         (elem_xpow (SparseComplexMatrix (v1.complex_matrix_value ()),\n                     v2.sparse_complex_matrix_value ()));\n}\n\nDEFBINOP (el_ldiv, sparse_complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return octave_value (quotient (v2.sparse_complex_matrix_value (),\n                                 v1.complex_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, complex_matrix, sparse_complex_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  complex_matrix, sparse_complex_matrix, mx_el_or)\n\nDEFCATOP (cm_scm, complex_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n  SparseComplexMatrix tmp (v1.complex_matrix_value ());\n  return octave_value (tmp. concat (v2.sparse_complex_matrix_value (),\n                                    ra_idx));\n}\n\nDEFCONV (sparse_complex_matrix_conv, complex_matrix,\n         sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v, a);\n  return new octave_sparse_complex_matrix\n         (SparseComplexMatrix (v.complex_matrix_value ()));\n}\n\nDEFNDASSIGNOP_FN (assign, complex_matrix, sparse_complex_matrix,\n                  complex_array, assign)\n\nvoid\ninstall_cm_scm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex_matrix,\n                    octave_sparse_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex_matrix,\n                    octave_sparse_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex_matrix,\n                    octave_sparse_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex_matrix,\n                    octave_sparse_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex_matrix,\n                    octave_sparse_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex_matrix,\n                    octave_sparse_complex_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_mul_trans, octave_complex_matrix,\n                    octave_sparse_complex_matrix, mul_trans);\n  INSTALL_BINOP_TI (ti, op_mul_herm, octave_complex_matrix,\n                    octave_sparse_complex_matrix, mul_herm);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex_matrix,\n                    octave_sparse_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex_matrix,\n                    octave_sparse_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex_matrix,\n                    octave_sparse_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex_matrix,\n                    octave_sparse_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex_matrix,\n                    octave_sparse_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex_matrix,\n                    octave_sparse_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex_matrix,\n                    octave_sparse_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex_matrix,\n                    octave_sparse_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex_matrix,\n                    octave_sparse_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex_matrix,\n                    octave_sparse_complex_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex_matrix,\n                    octave_sparse_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex_matrix,\n                    octave_sparse_complex_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex_matrix,\n                    octave_sparse_complex_matrix, cm_scm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix,\n                       octave_sparse_complex_matrix, assign)\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex_matrix, octave_sparse_complex_matrix,\n                         octave_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_complex_matrix, octave_sparse_complex_matrix,\n                      sparse_complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cm-sm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-cx-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-sm-cm.h\"\n#include \"smx-cm-sm.h\"\n#include \"ov-re-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex matrix by sparse matrix ops.\n\nDEFBINOP_OP (add, complex_matrix, sparse_matrix, +)\nDEFBINOP_OP (sub, complex_matrix, sparse_matrix, -)\n\nDEFBINOP_OP (mul, complex_matrix, sparse_matrix, *)\n\nDEFBINOP (div, complex_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.complex_array_value () / v2.scalar_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n\n      ComplexMatrix ret = xdiv (v1.complex_matrix_value (),\n                                v2.sparse_matrix_value (), typ);\n\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOPX (pow, complex_matrix, sparse_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, complex_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),\n                                v2.matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (lt, complex_matrix, sparse_matrix, mx_el_lt)\nDEFBINOP_FN (le, complex_matrix, sparse_matrix, mx_el_le)\nDEFBINOP_FN (eq, complex_matrix, sparse_matrix, mx_el_eq)\nDEFBINOP_FN (ge, complex_matrix, sparse_matrix, mx_el_ge)\nDEFBINOP_FN (gt, complex_matrix, sparse_matrix, mx_el_gt)\nDEFBINOP_FN (ne, complex_matrix, sparse_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, complex_matrix, sparse_matrix, product)\nDEFBINOP_FN (el_div, complex_matrix, sparse_matrix, quotient)\n\nDEFBINOP (el_pow, complex_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  return octave_value\n         (elem_xpow (SparseComplexMatrix (v1.complex_matrix_value ()),\n                     v2.sparse_matrix_value ()));\n}\n\nDEFBINOP (el_ldiv, complex_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  return octave_value\n         (quotient (v2.sparse_matrix_value (), v1.complex_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, complex_matrix, sparse_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  complex_matrix, sparse_matrix, mx_el_or)\n\nDEFCATOP (cm_sm, complex_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  SparseComplexMatrix tmp (v1.complex_matrix_value ());\n  return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));\n}\n\nDEFNDASSIGNOP_FN (assign, complex_matrix, sparse_matrix, complex_array, assign)\n\nvoid\ninstall_cm_sm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex_matrix, octave_sparse_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex_matrix, octave_sparse_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex_matrix, octave_sparse_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex_matrix, octave_sparse_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex_matrix, octave_sparse_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex_matrix, octave_sparse_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex_matrix, octave_sparse_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex_matrix, octave_sparse_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex_matrix, octave_sparse_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex_matrix, octave_sparse_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex_matrix, octave_sparse_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex_matrix, octave_sparse_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex_matrix, octave_sparse_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex_matrix, octave_sparse_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex_matrix, octave_sparse_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex_matrix, octave_sparse_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex_matrix, octave_sparse_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex_matrix, octave_sparse_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex_matrix, octave_sparse_matrix, cm_sm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix, octave_sparse_matrix,\n                       assign);\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex_matrix, octave_sparse_matrix,\n                         octave_complex_matrix)\n\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cs-cm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex scalar by complex matrix ops.\n\nDEFNDBINOP_OP (add, complex, complex_matrix, complex, complex_array, +)\nDEFNDBINOP_OP (sub, complex, complex_matrix, complex, complex_array, -)\nDEFNDBINOP_OP (mul, complex, complex_matrix, complex, complex_array, *)\n\nDEFBINOP (div, complex, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  ComplexMatrix m1 = v1.complex_matrix_value ();\n  ComplexMatrix m2 = v2.complex_matrix_value ();\n  MatrixType typ = v2.matrix_type ();\n\n  ComplexMatrix ret = xdiv (m1, m2, typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (pow, complex, complex_matrix, xpow)\n\nDEFBINOP (ldiv, complex, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return octave_value (v2.complex_array_value () / v1.complex_value ());\n}\n\nDEFNDCMPLXCMPOP_FN (lt, complex, complex_matrix, complex, complex_array,\n                    mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, complex, complex_matrix, complex, complex_array,\n                    mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, complex, complex_matrix, complex, complex_array,\n                    mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, complex, complex_matrix, complex, complex_array,\n                    mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, complex, complex_matrix, complex, complex_array,\n                    mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, complex, complex_matrix, complex, complex_array,\n                    mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, complex, complex_matrix, complex, complex_array, *)\nDEFNDBINOP_FN (el_div, complex, complex_matrix, complex, complex_array,\n               elem_xdiv)\nDEFNDBINOP_FN (el_pow, complex, complex_matrix, complex, complex_array,\n               elem_xpow)\n\nDEFBINOP (el_ldiv, complex, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return octave_value (v2.complex_array_value () / v1.complex_value ());\n}\n\nDEFNDBINOP_FN (el_and, complex, complex_matrix, complex, complex_array,\n               mx_el_and)\nDEFNDBINOP_FN (el_or,  complex, complex_matrix, complex, complex_array,\n               mx_el_or)\n\nDEFNDCATOP_FN (cs_cm, complex, complex_matrix, complex_array, complex_array,\n               concat)\n\nDEFCONV (complex_matrix_conv, complex, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);\n\n  return new octave_complex_matrix (v.complex_matrix_value ());\n}\n\nvoid\ninstall_cs_cm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex, octave_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex, octave_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex, octave_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex, octave_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex, octave_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex, octave_complex_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex, octave_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex, octave_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex, octave_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex, octave_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex, octave_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex, octave_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex, octave_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex, octave_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex, octave_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex, octave_complex_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex, octave_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex, octave_complex_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex, octave_complex_matrix, cs_cm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_complex_matrix,\n                         octave_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_complex, octave_complex_matrix,\n                      complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cs-cs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-util.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// unary complex scalar ops.\n\nDEFUNOP (not, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);\n  Complex x = v.complex_value ();\n  if (octave::math::isnan (x))\n    octave::err_nan_to_logical_conversion ();\n\n  return octave_value (x == 0.0);\n}\n\nDEFUNOP_OP (uplus, complex, /* no-op */)\nDEFUNOP_OP (uminus, complex, -)\nDEFUNOP_OP (transpose, complex, /* no-op */)\n\nDEFUNOP (hermitian, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);\n\n  return octave_value (conj (v.complex_value ()));\n}\n\nDEFNCUNOP_METHOD (incr, complex, increment)\nDEFNCUNOP_METHOD (decr, complex, decrement)\n\n// complex scalar by complex scalar ops.\n\nDEFBINOP_OP (add, complex, complex, +)\nDEFBINOP_OP (sub, complex, complex, -)\nDEFBINOP_OP (mul, complex, complex, *)\n\nDEFBINOP (div, complex, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.complex_value () / v2.complex_value ());\n}\n\nDEFBINOP_FN (pow, complex, complex, xpow)\n\nDEFBINOP (ldiv, complex, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v2.complex_value () / v1.complex_value ());\n}\n\nDEFCMPLXCMPOP_OP (lt, complex, complex, <)\nDEFCMPLXCMPOP_OP (le, complex, complex, <=)\nDEFCMPLXCMPOP_OP (eq, complex, complex, ==)\nDEFCMPLXCMPOP_OP (ge, complex, complex, >=)\nDEFCMPLXCMPOP_OP (gt, complex, complex, >)\nDEFCMPLXCMPOP_OP (ne, complex, complex, !=)\n\nDEFBINOP_OP (el_mul, complex, complex, *)\n\nDEFBINOP (el_div, complex, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.complex_value () / v2.complex_value ());\n}\n\nDEFBINOP_FN (el_pow, complex, complex, xpow)\n\nDEFBINOP (el_ldiv, complex, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v2.complex_value () / v1.complex_value ());\n}\n\nDEFBINOP (el_and, complex, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return v1.complex_value () != 0.0 && v2.complex_value () != 0.0;\n}\n\nDEFBINOP (el_or, complex, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return v1.complex_value () != 0.0 || v2.complex_value () != 0.0;\n}\n\nDEFNDCATOP_FN (cs_cs, complex, complex, complex_array, complex_array, concat)\n\nvoid\ninstall_cs_cs_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_complex, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_complex, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_complex, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_complex, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_complex, hermitian);\n\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_complex, incr);\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_complex, decr);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_complex, octave_complex, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex, octave_complex, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex, octave_complex, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex, octave_complex, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex, octave_complex, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex, octave_complex, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex, octave_complex, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex, octave_complex, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex, octave_complex, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex, octave_complex, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex, octave_complex, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex, octave_complex, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex, octave_complex, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex, octave_complex, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex, octave_complex, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex, octave_complex, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex, octave_complex, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex, octave_complex, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex, octave_complex, cs_cs);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_complex,\n                         octave_complex_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_null_matrix,\n                         octave_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_null_str,\n                         octave_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_null_sq_str,\n                         octave_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cs-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-cs-nda.h\"\n#include \"mx-nda-cs.h\"\n#include \"mx-cs-nda.h\"\n#include \"mx-nda-cs.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex scalar by matrix ops.\n\nDEFNDBINOP_OP (add, complex, matrix, complex, array, +)\nDEFNDBINOP_OP (sub, complex, matrix, complex, array, -)\nDEFNDBINOP_OP (mul, complex, matrix, complex, array, *)\n\nDEFBINOP (div, complex, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  ComplexMatrix m1 = v1.complex_matrix_value ();\n  Matrix m2 = v2.matrix_value ();\n  MatrixType typ = v2.matrix_type ();\n\n  ComplexMatrix ret = xdiv (m1, m2, typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (pow, complex, matrix, xpow)\n\nDEFBINOP (ldiv, complex, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return octave_value (v2.array_value () / v1.complex_value ());\n}\n\nDEFNDCMPLXCMPOP_FN (lt, complex, matrix, complex, array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, complex, matrix, complex, array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, complex, matrix, complex, array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, complex, matrix, complex, array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, complex, matrix, complex, array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, complex, matrix, complex, array, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, complex, matrix, complex, array, *)\nDEFNDBINOP_FN (el_div, complex, matrix, complex, array, elem_xdiv)\nDEFNDBINOP_FN (el_pow, complex, matrix, complex, array, elem_xpow)\n\nDEFBINOP (el_ldiv, complex, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return octave_value (v2.array_value () / v1.complex_value ());\n}\n\nDEFNDBINOP_FN (el_and, complex, matrix, complex, array, mx_el_and)\nDEFNDBINOP_FN (el_or,  complex, matrix, complex, array, mx_el_or)\n\nDEFNDCATOP_FN (cs_m, complex, matrix, complex_array, array, concat)\n\nvoid\ninstall_cs_m_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex, octave_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex, octave_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex, octave_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex, octave_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex, octave_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex, octave_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex, octave_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex, octave_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex, octave_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex, octave_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex, octave_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex, octave_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex, octave_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex, octave_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex, octave_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex, octave_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex, octave_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex, octave_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex, octave_matrix, cs_m);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_matrix,\n                         octave_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cs-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex scalar by scalar ops.\n\nDEFBINOP_OP (add, complex, scalar, +)\nDEFBINOP_OP (sub, complex, scalar, -)\nDEFBINOP_OP (mul, complex, scalar, *)\n\nDEFBINOP (div, complex, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.complex_value () / v2.double_value ());\n}\n\nDEFBINOP_FN (pow, complex, scalar, xpow)\n\nDEFBINOP (ldiv, complex, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v2.double_value () / v1.complex_value ());\n}\n\nDEFCMPLXCMPOP_OP (lt, complex, scalar, <)\nDEFCMPLXCMPOP_OP (le, complex, scalar, <=)\nDEFCMPLXCMPOP_OP (eq, complex, scalar, ==)\nDEFCMPLXCMPOP_OP (ge, complex, scalar, >=)\nDEFCMPLXCMPOP_OP (gt, complex, scalar, >)\nDEFCMPLXCMPOP_OP (ne, complex, scalar, !=)\n\nDEFBINOP_OP (el_mul, complex, scalar, *)\n\nDEFBINOP (el_div, complex, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.complex_value () / v2.double_value ());\n}\n\nDEFBINOP_FN (el_pow, complex, scalar, xpow)\n\nDEFBINOP (el_ldiv, complex, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v2.double_value () / v1.complex_value ());\n}\n\nDEFBINOP (el_and, complex, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return v1.complex_value () != 0.0 && v2.double_value ();\n}\n\nDEFBINOP (el_or, complex, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return v1.complex_value () != 0.0 || v2.double_value ();\n}\n\nDEFNDCATOP_FN (cs_s, complex, scalar, complex_array, array, concat)\n\nvoid\ninstall_cs_s_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex, octave_scalar, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex, octave_scalar, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex, octave_scalar, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex, octave_scalar, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex, octave_scalar, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex, octave_scalar, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex, octave_scalar, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex, octave_scalar, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex, octave_scalar, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex, octave_scalar, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex, octave_scalar, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex, octave_scalar, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex, octave_scalar, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex, octave_scalar, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex, octave_scalar, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex, octave_scalar, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex, octave_scalar, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex, octave_scalar, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex, octave_scalar, cs_s);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_scalar,\n                         octave_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cs-scm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-complex.h\"\n#include \"ops.h\"\n#include \"xpow.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex scalar by sparse complex matrix ops.\n\nDEFBINOP_OP (add, complex, sparse_complex_matrix, +)\nDEFBINOP_OP (sub, complex, sparse_complex_matrix, -)\nDEFBINOP_OP (mul, complex, sparse_complex_matrix, *)\n\nDEFBINOP (div, complex, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (SparseComplexMatrix (1, 1, v1.complex_value ()\n                         / v2.complex_value ()));\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      ComplexMatrix m1 = ComplexMatrix (1, 1, v1.complex_value ());\n      SparseComplexMatrix m2 = v2.sparse_complex_matrix_value ();\n      ComplexMatrix ret = xdiv (m1, m2, typ);\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP (pow, complex, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n  return xpow (v1.complex_value (), v2.complex_matrix_value ());\n}\n\nDEFBINOP (ldiv, complex, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return octave_value (v2.sparse_complex_matrix_value () / v1.complex_value ());\n}\n\nDEFBINOP_FN (lt, complex, sparse_complex_matrix, mx_el_lt)\nDEFBINOP_FN (le, complex, sparse_complex_matrix, mx_el_le)\nDEFBINOP_FN (eq, complex, sparse_complex_matrix, mx_el_eq)\nDEFBINOP_FN (ge, complex, sparse_complex_matrix, mx_el_ge)\nDEFBINOP_FN (gt, complex, sparse_complex_matrix, mx_el_gt)\nDEFBINOP_FN (ne, complex, sparse_complex_matrix, mx_el_ne)\n\nDEFBINOP_OP (el_mul, complex, sparse_complex_matrix, *)\nDEFBINOP_FN (el_div, complex, sparse_complex_matrix, elem_xdiv)\n\nDEFBINOP_FN (el_pow, complex, sparse_complex_matrix, elem_xpow)\n\nDEFBINOP (el_ldiv, complex, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return octave_value (v2.sparse_complex_matrix_value () / v1.complex_value ());\n}\n\nDEFBINOP_FN (el_and, complex, sparse_complex_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  complex, sparse_complex_matrix, mx_el_or)\n\nDEFCATOP (cs_scm, complex, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n  SparseComplexMatrix tmp (1, 1, v1.complex_value ());\n  return octave_value (tmp. concat (v2.sparse_complex_matrix_value (),\n                                    ra_idx));\n}\n\nDEFCONV (sparse_complex_matrix_conv, complex, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);\n\n  return new octave_sparse_complex_matrix\n         (SparseComplexMatrix (v.complex_matrix_value ()));\n}\n\nvoid\ninstall_cs_scm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex, octave_sparse_complex_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex, octave_sparse_complex_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex, octave_sparse_complex_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex, octave_sparse_complex_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex, octave_sparse_complex_matrix,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex, octave_sparse_complex_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex, octave_sparse_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex, octave_sparse_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex, octave_sparse_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex, octave_sparse_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex, octave_sparse_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex, octave_sparse_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex, octave_sparse_complex_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex, octave_sparse_complex_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex, octave_sparse_complex_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex, octave_sparse_complex_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex, octave_sparse_complex_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex, octave_sparse_complex_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex, octave_sparse_complex_matrix, cs_scm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_sparse_complex_matrix,\n                         octave_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_complex, octave_sparse_complex_matrix,\n                      sparse_complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-cs-sm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-complex.h\"\n#include \"ops.h\"\n#include \"xpow.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n#include \"smx-cs-sm.h\"\n#include \"smx-sm-cs.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex by sparse matrix ops.\n\nDEFBINOP_OP (add, complex, sparse_matrix, +)\nDEFBINOP_OP (sub, complex, sparse_matrix, -)\nDEFBINOP_OP (mul, complex, sparse_matrix, *)\n\nDEFBINOP (div, complex, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (SparseComplexMatrix (1, 1, v1.complex_value () / v2.scalar_value ()));\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      ComplexMatrix m1 = ComplexMatrix (1, 1, v1.complex_value ());\n      SparseMatrix m2 = v2.sparse_matrix_value ();\n      ComplexMatrix ret = xdiv (m1, m2, typ);\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP (pow, complex, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  return xpow (v1.complex_value (), v2.matrix_value ());\n}\n\nDEFBINOP (ldiv, complex, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  return octave_value (v2.sparse_matrix_value () / v1.complex_value ());\n}\n\nDEFBINOP_FN (lt, complex, sparse_matrix, mx_el_lt)\nDEFBINOP_FN (le, complex, sparse_matrix, mx_el_le)\nDEFBINOP_FN (eq, complex, sparse_matrix, mx_el_eq)\nDEFBINOP_FN (ge, complex, sparse_matrix, mx_el_ge)\nDEFBINOP_FN (gt, complex, sparse_matrix, mx_el_gt)\nDEFBINOP_FN (ne, complex, sparse_matrix, mx_el_ne)\n\nDEFBINOP_OP (el_mul, complex, sparse_matrix, *)\nDEFBINOP_FN (el_div, complex, sparse_matrix, elem_xdiv)\nDEFBINOP_FN (el_pow, complex, sparse_matrix, elem_xpow)\n\nDEFBINOP (el_ldiv, complex, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  return octave_value (v2.sparse_matrix_value () / v1.complex_value ());\n}\n\nDEFBINOP_FN (el_and, complex, sparse_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  complex, sparse_matrix, mx_el_or)\n\nDEFCATOP (cs_sm, sparse_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  SparseComplexMatrix tmp (1, 1, v1.complex_value ());\n  return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));\n}\n\nDEFCONV (sparse_matrix_conv, complex, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);\n\n  return new octave_sparse_matrix (SparseMatrix (v.matrix_value ()));\n}\n\nvoid\ninstall_cs_sm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_complex, octave_sparse_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex, octave_sparse_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex, octave_sparse_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_complex, octave_sparse_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_complex, octave_sparse_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex, octave_sparse_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_complex, octave_sparse_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_complex, octave_sparse_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_complex, octave_sparse_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_complex, octave_sparse_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_complex, octave_sparse_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_complex, octave_sparse_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_complex, octave_sparse_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_complex, octave_sparse_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex, octave_sparse_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_complex, octave_sparse_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_complex, octave_sparse_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_complex, octave_sparse_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_complex, octave_sparse_matrix, cs_sm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_sparse_matrix,\n                         octave_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_complex, octave_sparse_matrix,\n                      sparse_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-dm-cdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-re-diag.h\"\n#define RINCLUDE \"ov-cx-diag.h\"\n\n#define LMATRIX diag_matrix\n#define RMATRIX complex_diag_matrix\n#define LDMATRIX RMATRIX\n\n#define LSHORT dm\n#define RSHORT cdm\n\n#define DEFINEDIV\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-dm-cm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-re-diag.h\"\n#define RINCLUDE \"ov-cx-mat.h\"\n\n#define LMATRIX diag_matrix\n#define RMATRIX complex_matrix\n\n#define LSHORT dm\n#define RSHORT cm\n\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-dm-cs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define SINCLUDE \"ov-complex.h\"\n#define MINCLUDE \"ov-re-diag.h\"\n\n#define SCALAR complex\n#define DIAG_MATRIX diag_matrix\n#define DIAG_MATRIXV complex_diag_matrix\n#define MATRIX matrix\n#define MATRIXV complex_matrix\n\n#define SSHORT cs\n#define MSHORT dm\n\n#include \"op-dms-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-dm-dm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-re-diag.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix unary ops.\n\nDEFUNOP_OP (uplus, diag_matrix, /* no-op */)\nDEFUNOP_OP (uminus, diag_matrix, -)\n\nDEFUNOP (transpose, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v, a);\n  return octave_value (v.diag_matrix_value ().transpose ());\n}\n\n// matrix by matrix ops.\n\nDEFBINOP_OP (add, diag_matrix, diag_matrix, +)\nDEFBINOP_OP (sub, diag_matrix, diag_matrix, -)\nDEFBINOP_OP (mul, diag_matrix, diag_matrix, *)\n\nDEFBINOP (div, diag_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  return xdiv (v1.diag_matrix_value (),\n               v2.diag_matrix_value ());\n}\n\nDEFBINOP (ldiv, diag_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  return xleftdiv (v1.diag_matrix_value (),\n                   v2.diag_matrix_value ());\n}\n\nCONVDECL (diag_matrix_to_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v, a);\n\n  return new octave_matrix (v.matrix_value ());\n}\n\nvoid\ninstall_dm_dm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_uplus, octave_diag_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_diag_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_diag_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_diag_matrix, transpose);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_diag_matrix, octave_diag_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_diag_matrix, octave_diag_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_diag_matrix, octave_diag_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_diag_matrix, octave_diag_matrix, div);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_diag_matrix, octave_diag_matrix, ldiv);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_diag_matrix, octave_matrix, octave_matrix);\n  INSTALL_WIDENOP_TI (ti, octave_diag_matrix, octave_matrix,\n                      diag_matrix_to_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-dm-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-re-diag.h\"\n#define RINCLUDE \"ov-re-mat.h\"\n\n#define LMATRIX diag_matrix\n#define LDMATRIX matrix\n#define RMATRIX matrix\n\n#define LSHORT dm\n#define RSHORT m\n\n#define DEFINELDIV\n#define DEFINENULLASSIGNCONV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-dm-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define SINCLUDE \"ov-scalar.h\"\n#define MINCLUDE \"ov-re-diag.h\"\n\n#define SCALAR scalar\n#define DIAG_MATRIX diag_matrix\n#define MATRIX matrix\n\n#define SSHORT s\n#define MSHORT dm\n\n#include \"op-dms-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-dm-scm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-cm-s.h\"\n#include \"mx-s-cm.h\"\n\n#include \"mx-dm-cs.h\"\n#include \"mx-cs-dm.h\"\n\n#include \"mx-m-cs.h\"\n#include \"mx-cs-m.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\n#include \"ov-re-diag.h\"\n#include \"ov-cx-diag.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\n#include \"sparse-xdiv.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// diagonal matrix by sparse matrix ops\n\nDEFBINOP (mul_dm_scm, diag_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.diag_matrix_value () * d);\n    }\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      SparseComplexMatrix ret = v1.diag_matrix_value () *\n                                v2.sparse_complex_matrix_value ();\n      octave_value out = octave_value (ret);\n      typ.mark_as_unsymmetric ();\n      out.matrix_type (typ);\n      return out;\n    }\n}\n\nDEFBINOP (mul_cdm_sm, complex_diag_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.scalar_value ();\n\n      return octave_value (v1.complex_diag_matrix_value () * d);\n    }\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      SparseComplexMatrix ret = v1.complex_diag_matrix_value () *\n                                v2.sparse_matrix_value ();\n      octave_value out = octave_value (ret);\n      typ.mark_as_unsymmetric ();\n      out.matrix_type (typ);\n      return out;\n    }\n}\n\nDEFBINOP (mul_cdm_scm, complex_diag_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.complex_diag_matrix_value () * d);\n    }\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      SparseComplexMatrix ret = v1.complex_diag_matrix_value () *\n                                v2.sparse_complex_matrix_value ();\n      octave_value out = octave_value (ret);\n      typ.mark_as_unsymmetric ();\n      out.matrix_type (typ);\n      return out;\n    }\n}\n\nDEFBINOP (ldiv_dm_scm, diag_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  MatrixType typ = v2.matrix_type ();\n  return xleftdiv (v1.diag_matrix_value (), v2.sparse_complex_matrix_value (),\n                   typ);\n}\n\nDEFBINOP (ldiv_cdm_sm, complex_diag_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  MatrixType typ = v2.matrix_type ();\n  return xleftdiv (v1.complex_diag_matrix_value (), v2.sparse_matrix_value (),\n                   typ);\n}\n\nDEFBINOP (ldiv_cdm_scm, complex_diag_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  MatrixType typ = v2.matrix_type ();\n  return xleftdiv (v1.complex_diag_matrix_value (),\n                   v2.sparse_complex_matrix_value (),\n                   typ);\n}\n\nDEFBINOP (add_dm_scm, diag_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.matrix_value () + d);\n    }\n  else\n    return v1.diag_matrix_value () + v2.sparse_complex_matrix_value ();\n}\n\nDEFBINOP (add_cdm_sm, complex_diag_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v2.scalar_value ();\n\n      return octave_value (v1.complex_matrix_value () + d);\n    }\n  else\n    return v1.complex_diag_matrix_value () + v2.sparse_matrix_value ();\n}\n\nDEFBINOP (add_cdm_scm, complex_diag_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.complex_matrix_value () + d);\n    }\n  else\n    return v1.complex_diag_matrix_value () + v2.sparse_complex_matrix_value ();\n}\n\nDEFBINOP (sub_dm_scm, diag_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.matrix_value () + (-d));\n    }\n  else\n    return v1.diag_matrix_value () - v2.sparse_complex_matrix_value ();\n}\n\nDEFBINOP (sub_cdm_sm, complex_diag_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v2.scalar_value ();\n\n      return octave_value (v1.complex_matrix_value () + (-d));\n    }\n  else\n    return v1.complex_diag_matrix_value () - v2.sparse_matrix_value ();\n}\n\nDEFBINOP (sub_cdm_scm, complex_diag_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.complex_matrix_value () + (-d));\n    }\n  else\n    return v1.complex_diag_matrix_value () - v2.sparse_complex_matrix_value ();\n}\n\n// sparse matrix by diagonal matrix ops\n\nDEFBINOP (mul_scm_dm, sparse_complex_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    // If v1 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v1.complex_value ();\n\n      return octave_value (d * v2.diag_matrix_value ());\n    }\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n      SparseComplexMatrix ret = v1.sparse_complex_matrix_value () *\n                                v2.diag_matrix_value ();\n      octave_value out = octave_value (ret);\n      typ.mark_as_unsymmetric ();\n      out.matrix_type (typ);\n      return out;\n    }\n}\n\nDEFBINOP (mul_sm_cdm, sparse_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    // If v1 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v1.complex_value ();\n\n      return octave_value (d * v2.complex_diag_matrix_value ());\n    }\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n      SparseComplexMatrix ret = v1.sparse_matrix_value () *\n                                v2.complex_diag_matrix_value ();\n      octave_value out = octave_value (ret);\n      typ.mark_as_unsymmetric ();\n      out.matrix_type (typ);\n      return out;\n    }\n}\n\nDEFBINOP (mul_scm_cdm, sparse_complex_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    // If v1 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v1.complex_value ();\n\n      return octave_value (d * v2.complex_diag_matrix_value ());\n    }\n  else if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, don't bother with further dispatching.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.sparse_complex_matrix_value () * d);\n    }\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n      SparseComplexMatrix ret = v1.sparse_complex_matrix_value () *\n                                v2.complex_diag_matrix_value ();\n      octave_value out = octave_value (ret);\n      typ.mark_as_unsymmetric ();\n      out.matrix_type (typ);\n      return out;\n    }\n}\n\nDEFBINOP (div_scm_dm, sparse_complex_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_complex_matrix_value () / v2.scalar_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      return xdiv (v1.sparse_complex_matrix_value (),\n                   v2.diag_matrix_value (), typ);\n    }\n}\n\nDEFBINOP (div_sm_cdm, sparse_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_matrix_value () / v2.complex_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      return xdiv (v1.sparse_matrix_value (),\n                   v2.complex_diag_matrix_value (), typ);\n    }\n}\n\nDEFBINOP (div_scm_cdm, sparse_complex_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      return xdiv (v1.sparse_complex_matrix_value (),\n                   v2.complex_diag_matrix_value (), typ);\n    }\n}\n\nDEFBINOP (add_sm_cdm, sparse_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.sparse_matrix_value () + d);\n    }\n  else\n    return v1.sparse_matrix_value () + v2.complex_diag_matrix_value ();\n}\n\nDEFBINOP (add_scm_dm, sparse_complex_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v2.scalar_value ();\n\n      return octave_value (v1.sparse_complex_matrix_value () + d);\n    }\n  else\n    return v1.sparse_complex_matrix_value () + v2.diag_matrix_value ();\n}\n\nDEFBINOP (add_scm_cdm, sparse_complex_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.sparse_complex_matrix_value () + d);\n    }\n  else\n    return v1.sparse_complex_matrix_value () + v2.complex_diag_matrix_value ();\n}\n\nDEFBINOP (sub_sm_cdm, sparse_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.sparse_matrix_value () + (-d));\n    }\n  else\n    return v1.sparse_matrix_value () - v2.complex_diag_matrix_value ();\n}\n\nDEFBINOP (sub_scm_dm, sparse_complex_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v2.scalar_value ();\n\n      return octave_value (v1.sparse_complex_matrix_value () + (-d));\n    }\n  else\n    return v1.sparse_complex_matrix_value () - v2.diag_matrix_value ();\n}\n\nDEFBINOP (sub_scm_cdm, sparse_complex_matrix, complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.sparse_complex_matrix_value () + (-d));\n    }\n  else\n    return v1.sparse_complex_matrix_value () - v2.complex_diag_matrix_value ();\n}\n\nvoid\ninstall_dm_scm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_mul, octave_diag_matrix, octave_sparse_complex_matrix,\n                    mul_dm_scm);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex_diag_matrix, octave_sparse_matrix,\n                    mul_cdm_sm);\n  INSTALL_BINOP_TI (ti, op_mul, octave_complex_diag_matrix,\n                    octave_sparse_complex_matrix, mul_cdm_scm);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_diag_matrix, octave_sparse_complex_matrix,\n                    ldiv_dm_scm);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex_diag_matrix, octave_sparse_matrix,\n                    ldiv_cdm_sm);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_complex_diag_matrix,\n                    octave_sparse_complex_matrix, ldiv_cdm_scm);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_diag_matrix, octave_sparse_complex_matrix,\n                    add_dm_scm);\n  INSTALL_BINOP_TI (ti, op_add, octave_complex_diag_matrix, octave_sparse_matrix,\n                    add_cdm_sm);\n  INSTALL_BINOP_TI (ti, op_add, octave_complex_diag_matrix,\n                    octave_sparse_complex_matrix, add_cdm_scm);\n  INSTALL_BINOP_TI (ti, op_sub, octave_diag_matrix, octave_sparse_complex_matrix,\n                    sub_dm_scm);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex_diag_matrix, octave_sparse_matrix,\n                    sub_cdm_sm);\n  INSTALL_BINOP_TI (ti, op_sub, octave_complex_diag_matrix,\n                    octave_sparse_complex_matrix, sub_cdm_scm);\n\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_complex_matrix, octave_diag_matrix,\n                    mul_scm_dm);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_matrix, octave_complex_diag_matrix,\n                    mul_sm_cdm);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_complex_matrix,\n                    octave_complex_diag_matrix, mul_scm_cdm);\n\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_complex_matrix, octave_diag_matrix,\n                    div_scm_dm);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_matrix, octave_complex_diag_matrix,\n                    div_sm_cdm);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_complex_matrix,\n                    octave_complex_diag_matrix, div_scm_cdm);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_complex_matrix, octave_diag_matrix,\n                    add_scm_dm);\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_matrix, octave_complex_diag_matrix,\n                    add_sm_cdm);\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_complex_matrix,\n                    octave_complex_diag_matrix, add_scm_cdm);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_complex_matrix, octave_diag_matrix,\n                    sub_scm_dm);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_matrix, octave_complex_diag_matrix,\n                    sub_sm_cdm);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_complex_matrix,\n                    octave_complex_diag_matrix, sub_scm_cdm);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-dm-sm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\n#include \"ov-re-diag.h\"\n#include \"ov-re-sparse.h\"\n\n#include \"sparse-xdiv.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// diagonal matrix by sparse matrix ops\n\nDEFBINOP (mul_dm_sm, diag_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v2.scalar_value ();\n\n      return octave_value (v1.diag_matrix_value () * d);\n    }\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      SparseMatrix ret = v1.diag_matrix_value () * v2.sparse_matrix_value ();\n      octave_value out = octave_value (ret);\n      typ.mark_as_unsymmetric ();\n      out.matrix_type (typ);\n      return out;\n    }\n}\n\nDEFBINOP (ldiv_dm_sm, diag_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  MatrixType typ = v2.matrix_type ();\n  return xleftdiv (v1.diag_matrix_value (), v2.sparse_matrix_value (), typ);\n}\n\nDEFBINOP (add_dm_sm, diag_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v2.scalar_value ();\n\n      return octave_value (v1.matrix_value () + d);\n    }\n  else\n    return v1.diag_matrix_value () + v2.sparse_matrix_value ();\n}\n\nDEFBINOP (sub_dm_sm, diag_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    // If v2 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v2.scalar_value ();\n\n      return octave_value (v1.matrix_value () - d);\n    }\n  else\n    return v1.diag_matrix_value () - v2.sparse_matrix_value ();\n}\n\n// sparse matrix by diagonal matrix ops\n\nDEFBINOP (mul_sm_dm, sparse_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    // If v1 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v1.scalar_value ();\n\n      return octave_value (d * v2.diag_matrix_value ());\n    }\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n      SparseMatrix ret = v1.sparse_matrix_value () * v2.diag_matrix_value ();\n      octave_value out = octave_value (ret);\n      typ.mark_as_unsymmetric ();\n      out.matrix_type (typ);\n      return out;\n    }\n}\n\nDEFBINOP (div_sm_dm, sparse_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_matrix_value () / v2.scalar_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      return xdiv (v1.sparse_matrix_value (), v2.diag_matrix_value (), typ);\n    }\n}\n\nDEFBINOP (add_sm_dm, sparse_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    // If v1 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v1.scalar_value ();\n\n      return octave_value (d + v2.matrix_value ());\n    }\n  else\n    return v1.sparse_matrix_value () + v2.diag_matrix_value ();\n}\n\nDEFBINOP (sub_sm_dm, sparse_matrix, diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    // If v1 is a scalar in disguise, return a diagonal matrix rather than\n    // a sparse matrix.\n    {\n      double d = v1.scalar_value ();\n\n      return octave_value (d - v2.matrix_value ());\n    }\n  else\n    return v1.sparse_matrix_value () - v2.diag_matrix_value ();\n}\n\nvoid\ninstall_dm_sm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_mul, octave_diag_matrix, octave_sparse_matrix,\n                    mul_dm_sm);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_diag_matrix, octave_sparse_matrix,\n                    add_dm_sm);\n  INSTALL_BINOP_TI (ti, op_sub, octave_diag_matrix, octave_sparse_matrix,\n                    sub_dm_sm);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_diag_matrix, octave_sparse_matrix,\n                    ldiv_dm_sm);\n\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_matrix, octave_diag_matrix,\n                    mul_sm_dm);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_matrix, octave_diag_matrix,\n                    add_sm_dm);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_matrix, octave_diag_matrix,\n                    sub_sm_dm);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_matrix, octave_diag_matrix,\n                    div_sm_dm);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-dm-template.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n// FIXME: it might be nice to only include the declarations of the\n// operators that are actually needed instead of including all of them.\n#include \"mx-ops.h\"\n\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include LINCLUDE\n#include RINCLUDE\n#if defined (DEFINENULLASSIGNCONV)\n#  include \"ov-null-mat.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix by diag matrix ops.\n\nDEFBINOP_OP (add, LMATRIX, RMATRIX, +)\nDEFBINOP_OP (sub, LMATRIX, RMATRIX, -)\nDEFBINOP_OP (mul, LMATRIX, RMATRIX, *)\n\n#if ! defined (LDMATRIX)\n#  define LDMATRIX LMATRIX\n#endif\n\n#if ! defined (RDMATRIX)\n#  define RDMATRIX RMATRIX\n#endif\n\n#define OCTAVE_LMATRIX CONCAT2(octave_, LMATRIX)\n#define OCTAVE_LDMATRIX CONCAT2(octave_, LDMATRIX)\n#define OCTAVE_RMATRIX CONCAT2(octave_, RMATRIX)\n#define LMATRIX_VALUE CONCAT2(LMATRIX, _value)\n#define RMATRIX_VALUE CONCAT2(RMATRIX, _value)\n#define LDMATRIX_VALUE CONCAT2(LDMATRIX, _value)\n#define RDMATRIX_VALUE CONCAT2(RDMATRIX, _value)\n\n#if defined (DEFINEDIV)\nDEFBINOP (div, LMATRIX, RMATRIX)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);\n\n  return xdiv (v1.LDMATRIX_VALUE (), v2.RMATRIX_VALUE ());\n}\n#endif\n\n#if defined (DEFINELDIV)\nDEFBINOP (ldiv, LMATRIX, RMATRIX)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);\n\n  return xleftdiv (v1.LMATRIX_VALUE (), v2.RDMATRIX_VALUE ());\n}\n#endif\n\n#define SHORT_NAME CONCAT3(LSHORT, _, RSHORT)\n#define INST_NAME CONCAT3(install_, SHORT_NAME, _ops)\n\nvoid\nINST_NAME (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, OCTAVE_LMATRIX, OCTAVE_RMATRIX, add);\n  INSTALL_BINOP_TI (ti, op_sub, OCTAVE_LMATRIX, OCTAVE_RMATRIX, sub);\n  INSTALL_BINOP_TI (ti, op_mul, OCTAVE_LMATRIX, OCTAVE_RMATRIX, mul);\n#if defined (DEFINEDIV)\n  INSTALL_BINOP_TI (ti, op_div, OCTAVE_LMATRIX, OCTAVE_RMATRIX, div);\n#endif\n#if defined (DEFINELDIV)\n  INSTALL_BINOP_TI (ti, op_ldiv, OCTAVE_LMATRIX, OCTAVE_RMATRIX, ldiv);\n#endif\n#if defined (DEFINENULLASSIGNCONV)\n  INSTALL_ASSIGNCONV_TI (ti, OCTAVE_LMATRIX, octave_null_matrix, OCTAVE_LDMATRIX);\n  INSTALL_ASSIGNCONV_TI (ti, OCTAVE_LMATRIX, octave_null_str, OCTAVE_LDMATRIX);\n  INSTALL_ASSIGNCONV_TI (ti, OCTAVE_LMATRIX, octave_null_sq_str, OCTAVE_LDMATRIX);\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-dms-template.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ops.h\"\n#include \"xpow.h\"\n#include SINCLUDE\n#include MINCLUDE\n\n// matrix by diag matrix ops.\n\n#if ! defined (SCALARV)\n#  define SCALARV SCALAR\n#endif\n\n#if ! defined (DIAG_MATRIXV)\n#  define DIAG_MATRIXV DIAG_MATRIX\n#endif\n\n#if ! defined (MATRIXV)\n#  define MATRIXV MATRIX\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#define OCTAVE_DIAG_MATRIX CONCAT2(octave_, DIAG_MATRIX)\n#define OCTAVE_MATRIX CONCAT2(octave_, MATRIX)\n#define OCTAVE_SCALAR CONCAT2(octave_, SCALAR)\n#define DIAG_MATRIX_VALUE CONCAT2(DIAG_MATRIXV, _value)\n#define MATRIX_VALUE CONCAT2(MATRIXV, _value)\n#define SCALAR_VALUE CONCAT2(SCALARV, _value)\n\ntemplate <typename DM, typename S>\noctave_value\ndm_s_mul (const DM& dm, const S& d)\n{\n  if constexpr (is_instance<std::complex, S>::value)\n    {\n      if (math::isfinite (std::norm (d)))\n        return octave_value (dm.DIAG_MATRIX_VALUE () * d);\n      else\n        return octave_value (dm.MATRIX_VALUE () * d);\n    }\n  else\n    {\n      if (math::isfinite (d))\n        return octave_value (dm.DIAG_MATRIX_VALUE () * d);\n      else\n        return octave_value (dm.MATRIX_VALUE () * d);\n    }\n}\n\nDEFBINOP (dmsmul, DIAG_MATRIX, SCALAR)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_DIAG_MATRIX&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_SCALAR&, v2, a2);\n\n  return dm_s_mul<> (v1, v2.SCALAR_VALUE ());\n}\n\ntemplate <typename DM, typename S>\noctave_value\ndm_s_div (const DM& dm, const S& d)\n{\n  if constexpr (is_instance<std::complex, S>::value)\n    {\n      auto nd = std::norm (d);\n      if (nd == 0.0 || math::isnan (nd))\n        return octave_value (dm.MATRIX_VALUE () / d);\n      else\n        return octave_value (dm.DIAG_MATRIX_VALUE () / d);\n    }\n  else\n    {\n      if (d == 0.0 || math::isnan (d))\n        return octave_value (dm.MATRIX_VALUE () / d);\n      else\n        return octave_value (dm.DIAG_MATRIX_VALUE () / d);\n    }\n}\n\nDEFBINOP (dmsdiv, MATRIX, SCALAR)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_DIAG_MATRIX&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_SCALAR&, v2, a2);\n\n  return dm_s_div<> (v1, v2.SCALAR_VALUE ());\n}\n\ntemplate <typename S, typename DM>\noctave_value\ns_dm_mul (const S& d, const DM& dm)\n{\n  if constexpr (is_instance<std::complex, S>::value)\n    {\n      if (math::isfinite (std::norm (d)))\n        return octave_value (d * dm.DIAG_MATRIX_VALUE ());\n      else\n        return octave_value (d * dm.MATRIX_VALUE ());\n    }\n  else\n    {\n      if (math::isfinite (d))\n        return octave_value (d * dm.DIAG_MATRIX_VALUE ());\n      else\n        return octave_value (d * dm.MATRIX_VALUE ());\n    }\n}\n\nDEFBINOP (sdmmul, SCALAR, DIAG_MATRIX)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_SCALAR&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_DIAG_MATRIX&, v2, a2);\n\n  return s_dm_mul<> (v1.SCALAR_VALUE (), v2);\n}\n\ntemplate <typename S, typename DM>\noctave_value\ns_dm_ldiv (const S& d, const DM& dm)\n{\n  if constexpr (is_instance<std::complex, S>::value)\n    {\n      auto nd = std::norm (d);\n      if (nd == 0.0 || math::isnan (nd))\n        return octave_value (dm.MATRIX_VALUE () / d);\n      else\n        return octave_value (dm.DIAG_MATRIX_VALUE () / d);\n    }\n  else\n    {\n      if (d == 0.0 || math::isnan (d))\n        return octave_value (dm.MATRIX_VALUE () / d);\n      else\n        return octave_value (dm.DIAG_MATRIX_VALUE () / d);\n    }\n}\n\nDEFBINOP (sdmldiv, SCALAR, MATRIX)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_SCALAR&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_DIAG_MATRIX&, v2, a2);\n\n  return s_dm_ldiv<> (v1.SCALAR_VALUE (), v2);\n}\n\nDEFBINOP (dmspow, MATRIX, SCALAR)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_DIAG_MATRIX&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_SCALAR&, v2, a2);\n\n  return xpow (v1.DIAG_MATRIX_VALUE (), v2.SCALAR_VALUE ());\n}\n\n#define SHORT_NAME CONCAT3(MSHORT, _, SSHORT)\n#define INST_NAME CONCAT3(install_, SHORT_NAME, _ops)\n\nvoid\nINST_NAME (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_mul, OCTAVE_DIAG_MATRIX, OCTAVE_SCALAR, dmsmul);\n  INSTALL_BINOP_TI (ti, op_div, OCTAVE_DIAG_MATRIX, OCTAVE_SCALAR, dmsdiv);\n  INSTALL_BINOP_TI (ti, op_mul, OCTAVE_SCALAR, OCTAVE_DIAG_MATRIX, sdmmul);\n  INSTALL_BINOP_TI (ti, op_ldiv, OCTAVE_SCALAR, OCTAVE_DIAG_MATRIX, sdmldiv);\n  INSTALL_BINOP_TI (ti, op_pow, OCTAVE_DIAG_MATRIX, OCTAVE_SCALAR, dmspow);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcdm-fcdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-flt-cx-diag.h\"\n#include \"ov-cx-diag.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix unary ops.\n\nDEFUNOP_OP (uplus, float_complex_diag_matrix, /* no-op */)\nDEFUNOP_OP (uminus, float_complex_diag_matrix, -)\n\nDEFUNOP (transpose, float_complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v, a);\n  return octave_value (v.float_complex_diag_matrix_value ().transpose ());\n}\n\nDEFUNOP (hermitian, float_complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v, a);\n  return octave_value (v.float_complex_diag_matrix_value ().hermitian ());\n}\n\n// matrix by matrix ops.\n\nDEFBINOP_OP (add, float_complex_diag_matrix, float_complex_diag_matrix, +)\nDEFBINOP_OP (sub, float_complex_diag_matrix, float_complex_diag_matrix, -)\nDEFBINOP_OP (mul, float_complex_diag_matrix, float_complex_diag_matrix, *)\n\nDEFBINOP (div, float_complex_diag_matrix, float_complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v2, a2);\n\n  return xdiv (v1.float_complex_diag_matrix_value (),\n               v2.float_complex_diag_matrix_value ());\n}\n\nDEFBINOP (ldiv, float_complex_diag_matrix, float_complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v2, a2);\n\n  return xleftdiv (v1.float_complex_diag_matrix_value (),\n                   v2.float_complex_diag_matrix_value ());\n}\n\nCONVDECL (float_complex_diag_matrix_to_complex_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v, a);\n\n  return new octave_complex_diag_matrix (v.complex_diag_matrix_value ());\n}\n\nvoid\ninstall_fcdm_fcdm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_uplus, octave_float_complex_diag_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_float_complex_diag_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_float_complex_diag_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_float_complex_diag_matrix, hermitian);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_float_complex_diag_matrix,\n                    octave_float_complex_diag_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_complex_diag_matrix,\n                    octave_float_complex_diag_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_complex_diag_matrix,\n                    octave_float_complex_diag_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_complex_diag_matrix,\n                    octave_float_complex_diag_matrix, div);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_complex_diag_matrix,\n                    octave_float_complex_diag_matrix, ldiv);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex_diag_matrix,\n                         octave_float_complex_matrix, octave_float_complex_matrix);\n  INSTALL_WIDENOP_TI (ti, octave_float_complex_diag_matrix,\n                      octave_complex_diag_matrix,\n                      float_complex_diag_matrix_to_complex_diag_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcdm-fcm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-flt-cx-diag.h\"\n#define RINCLUDE \"ov-flt-cx-mat.h\"\n\n#define LMATRIX float_complex_diag_matrix\n#define RMATRIX float_complex_matrix\n\n#define LSHORT fcdm\n#define RSHORT fcm\n\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fcdm-fcs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define SINCLUDE \"ov-flt-complex.h\"\n#define MINCLUDE \"ov-flt-cx-diag.h\"\n\n#define SCALAR float_complex\n#define DIAG_MATRIX float_complex_diag_matrix\n#define MATRIX float_complex_matrix\n\n#define SSHORT fcs\n#define MSHORT fcdm\n\n#include \"op-dms-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fcdm-fdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-flt-cx-diag.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\n#define LINCLUDE \"ov-flt-cx-diag.h\"\n#define RINCLUDE \"ov-flt-re-diag.h\"\n\n#define LMATRIX float_complex_diag_matrix\n#define RMATRIX float_diag_matrix\n#define RDMATRIX LMATRIX\n\n#define LSHORT fcdm\n#define RSHORT fdm\n\n#define DEFINEDIV\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fcdm-fm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-flt-cx-diag.h\"\n#define RINCLUDE \"ov-flt-re-mat.h\"\n\n#define LMATRIX float_complex_diag_matrix\n#define RMATRIX float_matrix\n#define RDMATRIX float_complex_matrix\n\n#define LSHORT fcdm\n#define RSHORT fm\n\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fcdm-fs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define SINCLUDE \"ov-float.h\"\n#define MINCLUDE \"ov-flt-cx-diag.h\"\n\n#define SCALAR float_scalar\n#define SCALARV float_complex\n#define DIAG_MATRIX float_complex_diag_matrix\n#define MATRIX float_complex_matrix\n\n#define SSHORT fs\n#define MSHORT fcdm\n\n#include \"op-dms-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fcm-fcdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-flt-cx-mat.h\"\n#define RINCLUDE \"ov-flt-cx-diag.h\"\n\n#define LMATRIX float_complex_matrix\n#define RMATRIX float_complex_diag_matrix\n\n#define LSHORT fcm\n#define RSHORT fcdm\n\n#define DEFINEDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fcm-fcm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// unary complex matrix ops.\n\nDEFNDUNOP_OP (not, float_complex_matrix, float_complex_array, !)\nDEFNDUNOP_OP (uplus, float_complex_matrix, float_complex_array, /* no-op */)\nDEFNDUNOP_OP (uminus, float_complex_matrix, float_complex_array, -)\n\nDEFUNOP (transpose, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"transpose not defined for N-D objects\");\n\n  return octave_value (v.float_complex_matrix_value ().transpose ());\n}\n\nDEFUNOP (hermitian, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"complex-conjugate transpose not defined for N-D objects\");\n\n  return octave_value (v.float_complex_matrix_value ().hermitian ());\n}\n\nDEFNCUNOP_METHOD (incr, float_complex_matrix, increment)\nDEFNCUNOP_METHOD (decr, float_complex_matrix, decrement)\nDEFNCUNOP_METHOD (changesign, float_complex_matrix, changesign)\n\n// complex matrix by complex matrix ops.\n\nDEFNDBINOP_OP (add, float_complex_matrix, float_complex_matrix,\n               float_complex_array, float_complex_array, +)\nDEFNDBINOP_OP (sub, float_complex_matrix, float_complex_matrix,\n               float_complex_array, float_complex_array, -)\n\nDEFBINOP_OP (mul, float_complex_matrix, float_complex_matrix, *)\n\nDEFBINOP (div, float_complex_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  FloatComplexMatrix ret = xdiv (v1.float_complex_matrix_value (),\n                                 v2.float_complex_matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, float_complex_matrix, float_complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, float_complex_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  FloatComplexMatrix ret = xleftdiv (v1.float_complex_matrix_value (),\n                                     v2.float_complex_matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP (trans_mul, float_complex_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  return octave_value(xgemm (v1.float_complex_matrix_value (),\n                             v2.float_complex_matrix_value (),\n                             blas_trans, blas_no_trans));\n}\n\nDEFBINOP (mul_trans, float_complex_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  return octave_value(xgemm (v1.float_complex_matrix_value (),\n                             v2.float_complex_matrix_value (),\n                             blas_no_trans, blas_trans));\n}\n\nDEFBINOP (herm_mul, float_complex_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  return octave_value(xgemm (v1.float_complex_matrix_value (),\n                             v2.float_complex_matrix_value (),\n                             blas_conj_trans, blas_no_trans));\n}\n\nDEFBINOP (mul_herm, float_complex_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  return octave_value(xgemm (v1.float_complex_matrix_value (),\n                             v2.float_complex_matrix_value (),\n                             blas_no_trans, blas_conj_trans));\n}\n\nDEFBINOP (trans_ldiv, float_complex_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  FloatComplexMatrix ret = xleftdiv (v1.float_complex_matrix_value (),\n                                     v2.float_complex_matrix_value (),\n                                     typ, blas_trans);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP (herm_ldiv, float_complex_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  FloatComplexMatrix ret = xleftdiv (v1.float_complex_matrix_value (),\n                                     v2.float_complex_matrix_value (),\n                                     typ, blas_conj_trans);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, float_complex_matrix, float_complex_matrix,\n                    float_complex_array, float_complex_array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, float_complex_matrix, float_complex_matrix,\n                    float_complex_array, float_complex_array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, float_complex_matrix, float_complex_matrix,\n                    float_complex_array, float_complex_array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, float_complex_matrix, float_complex_matrix,\n                    float_complex_array, float_complex_array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, float_complex_matrix, float_complex_matrix,\n                    float_complex_array, float_complex_array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, float_complex_matrix, float_complex_matrix,\n                    float_complex_array, float_complex_array, mx_el_ne)\n\nDEFNDBINOP_FN (el_mul, float_complex_matrix, float_complex_matrix,\n               float_complex_array, float_complex_array, product)\nDEFNDBINOP_FN (el_div, float_complex_matrix, float_complex_matrix,\n               float_complex_array, float_complex_array, quotient)\nDEFNDBINOP_FN (el_pow, float_complex_matrix, float_complex_matrix,\n               float_complex_array, float_complex_array, elem_xpow)\n\nDEFBINOP (el_ldiv, float_complex_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n\n  return octave_value (quotient (v2.float_complex_array_value (),\n                                 v1.float_complex_array_value ()));\n}\n\nDEFNDBINOP_FN (el_and, float_complex_matrix, float_complex_matrix,\n               float_complex_array, float_complex_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_complex_matrix, float_complex_matrix,\n               float_complex_array, float_complex_array, mx_el_or)\n\nDEFNDCATOP_FN (fcm_fcm, float_complex_matrix, float_complex_matrix,\n               float_complex_array, float_complex_array, concat)\n\nDEFNDCATOP_FN (cm_fcm, complex_matrix, float_complex_matrix,\n               float_complex_array, float_complex_array, concat)\n\nDEFNDCATOP_FN (fcm_cm, float_complex_matrix, complex_matrix,\n               float_complex_array, float_complex_array, concat)\n\nDEFNDASSIGNOP_FN (assign, float_complex_matrix, float_complex_matrix,\n                  float_complex_array, assign)\nDEFNDASSIGNOP_FN (sgl_clx_assign, float_complex_matrix, complex_matrix,\n                  float_complex_array, assign)\nDEFNDASSIGNOP_FN (sgl_assign, float_complex_matrix, matrix,\n                  float_complex_array, assign)\nDEFNDASSIGNOP_FN (dbl_assign, complex_matrix, float_complex_matrix,\n                  complex_array, assign)\n\nDEFNULLASSIGNOP_FN (null_assign, float_complex_matrix, delete_elements)\n\nDEFNDASSIGNOP_OP (assign_add, float_complex_matrix,\n                  float_complex_matrix, float_complex_array, +=)\nDEFNDASSIGNOP_OP (assign_sub, float_complex_matrix,\n                  float_complex_matrix, float_complex_array, -=)\nDEFNDASSIGNOP_FNOP (assign_el_mul, float_complex_matrix, float_complex_matrix,\n                    float_complex_array, product_eq)\nDEFNDASSIGNOP_FNOP (assign_el_div, float_complex_matrix, float_complex_matrix,\n                    float_complex_array, quotient_eq)\n\nvoid\ninstall_fcm_fcm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_float_complex_matrix, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_float_complex_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_float_complex_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_float_complex_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_float_complex_matrix, hermitian);\n\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_float_complex_matrix, incr);\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_float_complex_matrix, decr);\n  INSTALL_NCUNOP_TI (ti, op_uminus, octave_float_complex_matrix, changesign);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_float_complex_matrix,\n                    octave_float_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_complex_matrix,\n                    octave_float_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_complex_matrix,\n                    octave_float_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_complex_matrix,\n                    octave_float_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_complex_matrix,\n                    octave_float_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_complex_matrix,\n                    octave_float_complex_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_trans_mul, octave_float_complex_matrix,\n                    octave_float_complex_matrix, trans_mul);\n  INSTALL_BINOP_TI (ti, op_mul_trans, octave_float_complex_matrix,\n                    octave_float_complex_matrix, mul_trans);\n  INSTALL_BINOP_TI (ti, op_herm_mul, octave_float_complex_matrix,\n                    octave_float_complex_matrix, herm_mul);\n  INSTALL_BINOP_TI (ti, op_mul_herm, octave_float_complex_matrix,\n                    octave_float_complex_matrix, mul_herm);\n  INSTALL_BINOP_TI (ti, op_trans_ldiv, octave_float_complex_matrix,\n                    octave_float_complex_matrix, trans_ldiv);\n  INSTALL_BINOP_TI (ti, op_herm_ldiv, octave_float_complex_matrix,\n                    octave_float_complex_matrix, herm_ldiv);\n\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_complex_matrix,\n                    octave_float_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_complex_matrix,\n                    octave_float_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_complex_matrix,\n                    octave_float_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_complex_matrix,\n                    octave_float_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_complex_matrix,\n                    octave_float_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_complex_matrix,\n                    octave_float_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_complex_matrix,\n                    octave_float_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_complex_matrix,\n                    octave_float_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_complex_matrix,\n                    octave_float_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_complex_matrix,\n                    octave_float_complex_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_complex_matrix,\n                    octave_float_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_complex_matrix,\n                    octave_float_complex_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_complex_matrix,\n                    octave_float_complex_matrix, fcm_fcm);\n  INSTALL_CATOP_TI (ti, octave_complex_matrix,\n                    octave_float_complex_matrix, cm_fcm);\n  INSTALL_CATOP_TI (ti, octave_float_complex_matrix,\n                    octave_complex_matrix, fcm_cm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix,\n                       octave_float_complex_matrix, assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix,\n                       octave_complex_matrix, sgl_clx_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix,\n                       octave_matrix, sgl_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix,\n                       octave_float_complex_matrix, dbl_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix,\n                       octave_null_matrix, null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix,\n                       octave_null_str, null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix,\n                       octave_null_sq_str, null_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_float_complex_matrix,\n                       octave_float_complex_matrix, assign_add);\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_float_complex_matrix,\n                       octave_float_complex_matrix, assign_sub);\n  INSTALL_ASSIGNOP_TI (ti, op_el_mul_eq, octave_float_complex_matrix,\n                       octave_float_complex_matrix, assign_el_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_el_div_eq, octave_float_complex_matrix,\n                       octave_float_complex_matrix, assign_el_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcm-fcs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-complex.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex matrix by complex scalar ops.\n\nDEFNDBINOP_OP (add, float_complex_matrix, float_complex,\n               float_complex_array, float_complex, +)\nDEFNDBINOP_OP (sub, float_complex_matrix, float_complex,\n               float_complex_array, float_complex, -)\nDEFNDBINOP_OP (mul, float_complex_matrix, float_complex,\n               float_complex_array, float_complex, *)\n\nDEFBINOP (div, float_complex_matrix, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_complex_array_value () / v2.float_complex_value ());\n}\n\nDEFBINOP_FN (pow, float_complex_matrix, float_complex, xpow)\n\nDEFBINOP (ldiv, float_complex_matrix, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  FloatComplexMatrix m1 = v1.float_complex_matrix_value ();\n  FloatComplexMatrix m2 = v2.float_complex_matrix_value ();\n  MatrixType typ = v1.matrix_type ();\n\n  FloatComplexMatrix ret = xleftdiv (m1, m2, typ);\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, float_complex_matrix, float_complex,\n                    float_complex_array, float_complex, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, float_complex_matrix, float_complex,\n                    float_complex_array, float_complex, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, float_complex_matrix, float_complex,\n                    float_complex_array, float_complex, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, float_complex_matrix, float_complex,\n                    float_complex_array, float_complex, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, float_complex_matrix, float_complex,\n                    float_complex_array, float_complex, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, float_complex_matrix, float_complex,\n                    float_complex_array, float_complex, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, float_complex_matrix, float_complex,\n               float_complex_array, float_complex, *)\n\nDEFBINOP (el_div, float_complex_matrix, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_complex_array_value () / v2.float_complex_value ());\n}\n\nDEFNDBINOP_FN (el_pow, float_complex_matrix, float_complex,\n               float_complex_array, float_complex, elem_xpow)\n\nDEFBINOP (el_ldiv, float_complex_matrix, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return elem_xdiv (v2.float_complex_value (), v1.float_complex_array_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_complex_matrix, float_complex,\n               float_complex_array, float_complex, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_complex_matrix, float_complex,\n               float_complex_array, float_complex, mx_el_or)\n\nDEFNDCATOP_FN (fcm_fcs, float_complex_matrix, float_complex,\n               float_complex_array, float_complex_array, concat)\n\nDEFNDCATOP_FN (cm_fcs, complex_matrix, float_complex,\n               float_complex_array, float_complex_array, concat)\n\nDEFNDCATOP_FN (fcm_cs, float_complex_matrix, complex,\n               float_complex_array, float_complex_array, concat)\n\nDEFNDASSIGNOP_FN (assign, float_complex_matrix, float_complex,\n                  float_complex, assign)\nDEFNDASSIGNOP_FN (dbl_assign, complex_matrix, float_complex,\n                  complex, assign)\n\nDEFNDASSIGNOP_OP (assign_add, float_complex_matrix, float_complex_scalar,\n                  float_complex, +=)\nDEFNDASSIGNOP_OP (assign_sub, float_complex_matrix, float_complex_scalar,\n                  float_complex, -=)\nDEFNDASSIGNOP_OP (assign_mul, float_complex_matrix, float_complex_scalar,\n                  float_complex, *=)\nDEFNDASSIGNOP_OP (assign_div, float_complex_matrix, float_complex_scalar,\n                  float_complex, /=)\n\nvoid\ninstall_fcm_fcs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_complex_matrix,\n                    octave_float_complex, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_complex_matrix,\n                    octave_float_complex, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_complex_matrix,\n                    octave_float_complex, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_complex_matrix,\n                    octave_float_complex, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_complex_matrix,\n                    octave_float_complex, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_complex_matrix,\n                    octave_float_complex, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_complex_matrix, octave_float_complex,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_complex_matrix, octave_float_complex,\n                    le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_complex_matrix, octave_float_complex,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_complex_matrix, octave_float_complex,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_complex_matrix, octave_float_complex,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_complex_matrix, octave_float_complex,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_complex_matrix,\n                    octave_float_complex, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_complex_matrix,\n                    octave_float_complex, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_complex_matrix,\n                    octave_float_complex, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_complex_matrix,\n                    octave_float_complex, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_complex_matrix,\n                    octave_float_complex, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_complex_matrix,\n                    octave_float_complex, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_complex_matrix, octave_float_complex,\n                    fcm_fcs);\n  INSTALL_CATOP_TI (ti, octave_complex_matrix, octave_float_complex, cm_fcs);\n  INSTALL_CATOP_TI (ti, octave_float_complex_matrix, octave_complex, fcm_cs);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix,\n                       octave_float_complex, assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix,\n                       octave_float_complex, dbl_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_float_complex_matrix,\n                       octave_float_complex_scalar, assign_add);\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_float_complex_matrix,\n                       octave_float_complex_scalar, assign_sub);\n  INSTALL_ASSIGNOP_TI (ti, op_mul_eq, octave_float_complex_matrix,\n                       octave_float_complex_scalar, assign_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_div_eq, octave_float_complex_matrix,\n                       octave_float_complex_scalar, assign_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcm-fdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-flt-cx-mat.h\"\n#define RINCLUDE \"ov-flt-re-diag.h\"\n\n#define LMATRIX float_complex_matrix\n#define RMATRIX float_diag_matrix\n\n#define LSHORT fcm\n#define RSHORT fdm\n\n#define DEFINEDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fcm-fm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-fcm-fm.h\"\n#include \"mx-fm-fcm.h\"\n#include \"mx-fcnda-fnda.h\"\n#include \"mx-fnda-fcnda.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex matrix by matrix ops.\n\nDEFNDBINOP_OP (add, float_complex_matrix, float_matrix, float_complex_array,\n               float_array, +)\nDEFNDBINOP_OP (sub, float_complex_matrix, float_matrix, float_complex_array,\n               float_array, -)\n\nDEFBINOP_OP (mul, float_complex_matrix, float_matrix, *)\n\nDEFBINOP (mul_trans, float_complex_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n\n  FloatComplexMatrix m1 = v1.float_complex_matrix_value ();\n  FloatMatrix m2 = v2.float_matrix_value ();\n\n  return FloatComplexMatrix (xgemm (real (m1), m2, blas_no_trans, blas_trans),\n                             xgemm (imag (m1), m2, blas_no_trans, blas_trans));\n}\n\nDEFBINOP (div, float_complex_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  FloatComplexMatrix ret = xdiv (v1.float_complex_matrix_value (),\n                                 v2.float_matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, float_complex_matrix, float_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, float_complex_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  FloatComplexMatrix ret = xleftdiv (v1.float_complex_matrix_value (),\n                                     v2.float_matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, float_complex_matrix, float_matrix,\n                    float_complex_array, float_array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, float_complex_matrix, float_matrix,\n                    float_complex_array, float_array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, float_complex_matrix, float_matrix,\n                    float_complex_array, float_array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, float_complex_matrix, float_matrix,\n                    float_complex_array, float_array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, float_complex_matrix, float_matrix,\n                    float_complex_array, float_array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, float_complex_matrix, float_matrix,\n                    float_complex_array, float_array, mx_el_ne)\n\nDEFNDBINOP_FN (el_mul, float_complex_matrix, float_matrix,\n               float_complex_array, float_array, product)\nDEFNDBINOP_FN (el_div, float_complex_matrix, float_matrix,\n               float_complex_array, float_array, quotient)\nDEFNDBINOP_FN (el_pow, float_complex_matrix, float_matrix,\n               float_complex_array, float_array, elem_xpow)\n\nDEFBINOP (el_ldiv, float_complex_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n\n  return quotient (v2.float_array_value (), v1.float_complex_array_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_complex_matrix, float_matrix,\n               float_complex_array, float_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_complex_matrix, float_matrix,\n               float_complex_array, float_array, mx_el_or)\n\nDEFNDCATOP_FN (fcm_fm, float_complex_matrix, float_matrix,\n               float_complex_array, float_array, concat)\n\nDEFNDCATOP_FN (cm_fm, complex_matrix, float_matrix,\n               float_complex_array, float_array, concat)\n\nDEFNDCATOP_FN (fcm_m, float_complex_matrix, matrix,\n               float_complex_array, float_array, concat)\n\nDEFNDASSIGNOP_FN (assign, float_complex_matrix, float_matrix,\n                  float_complex_array, assign)\nDEFNDASSIGNOP_FN (dbl_assign, complex_matrix, float_matrix,\n                  complex_array, assign)\n\nvoid\ninstall_fcm_fm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_complex_matrix, octave_float_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_complex_matrix, octave_float_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_complex_matrix, octave_float_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_complex_matrix, octave_float_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_complex_matrix, octave_float_matrix,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_complex_matrix,\n                    octave_float_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_complex_matrix, octave_float_matrix,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_complex_matrix, octave_float_matrix,\n                    le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_complex_matrix, octave_float_matrix,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_complex_matrix, octave_float_matrix,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_complex_matrix, octave_float_matrix,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_complex_matrix, octave_float_matrix,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_complex_matrix,\n                    octave_float_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_complex_matrix,\n                    octave_float_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_complex_matrix,\n                    octave_float_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_complex_matrix,\n                    octave_float_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_complex_matrix,\n                    octave_float_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_complex_matrix,\n                    octave_float_matrix, el_or);\n  INSTALL_BINOP_TI (ti, op_mul_trans, octave_float_complex_matrix,\n                    octave_float_matrix, mul_trans);\n  INSTALL_BINOP_TI (ti, op_mul_herm, octave_float_complex_matrix,\n                    octave_float_matrix, mul_trans);\n\n  INSTALL_CATOP_TI (ti, octave_float_complex_matrix, octave_float_matrix, fcm_fm);\n  INSTALL_CATOP_TI (ti, octave_complex_matrix, octave_float_matrix, cm_fm);\n  INSTALL_CATOP_TI (ti, octave_float_complex_matrix, octave_matrix, fcm_m);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix,\n                       octave_float_matrix, assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix,\n                       octave_float_matrix, dbl_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcm-fs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-fcnda-fs.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-float.h\"\n#include \"ov-scalar.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex matrix by scalar ops.\n\nDEFNDBINOP_OP (add, float_complex_matrix, float_scalar, float_complex_array,\n               float_scalar, +)\nDEFNDBINOP_OP (sub, float_complex_matrix, float_scalar, float_complex_array,\n               float_scalar, -)\nDEFNDBINOP_OP (mul, float_complex_matrix, float_scalar, float_complex_array,\n               float_scalar, *)\n\nDEFBINOP (div, float_complex_matrix, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v1.float_complex_array_value () / v2.float_value ());\n}\n\nDEFBINOP_FN (pow, float_complex_matrix, float_scalar, xpow)\n\nDEFBINOP (ldiv, float_complex_matrix, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  FloatComplexMatrix m1 = v1.float_complex_matrix_value ();\n  FloatMatrix m2 = v2.float_matrix_value ();\n  MatrixType typ = v1.matrix_type ();\n\n  FloatComplexMatrix ret = xleftdiv (m1, m2, typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, float_complex_matrix, float_scalar, float_complex_array,\n                    float_scalar, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, float_complex_matrix, float_scalar, float_complex_array,\n                    float_scalar, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, float_complex_matrix, float_scalar, float_complex_array,\n                    float_scalar, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, float_complex_matrix, float_scalar, float_complex_array,\n                    float_scalar, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, float_complex_matrix, float_scalar, float_complex_array,\n                    float_scalar, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, float_complex_matrix, float_scalar, float_complex_array,\n                    float_scalar, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, float_complex_matrix, float_scalar, float_complex_array,\n               float_scalar, *)\n\nDEFBINOP (el_div, float_complex_matrix, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v1.float_complex_array_value () / v2.float_value ());\n}\n\nDEFNDBINOP_FN (el_pow, float_complex_matrix, float_scalar, float_complex_array,\n               float_scalar, elem_xpow)\n\nDEFBINOP (el_ldiv, float_complex_matrix, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return elem_xdiv (v2.float_value (), v1.float_complex_array_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_complex_matrix, float_scalar, float_complex_array,\n               float_scalar, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_complex_matrix, float_scalar, float_complex_array,\n               float_scalar, mx_el_or)\n\nDEFNDCATOP_FN (fcm_fs, float_complex_matrix, float_scalar, float_complex_array,\n               float_array, concat)\n\nDEFNDCATOP_FN (cm_fs, complex_matrix, float_scalar, float_complex_array,\n               float_array, concat)\n\nDEFNDCATOP_FN (fcm_s, float_complex_matrix, scalar, float_complex_array,\n               float_array, concat)\n\nDEFNDASSIGNOP_FN (assign, float_complex_matrix, float_scalar,\n                  float_complex_array, assign)\nDEFNDASSIGNOP_FN (dbl_assign, complex_matrix, float_scalar, complex_array,\n                  assign)\n\nDEFNDASSIGNOP_OP (assign_mul, float_complex_matrix, float_scalar,\n                  float_scalar, *=)\nDEFNDASSIGNOP_OP (assign_div, float_complex_matrix, float_scalar,\n                  float_scalar, /=)\n\nvoid\ninstall_fcm_fs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_complex_matrix, octave_float_scalar,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_complex_matrix, octave_float_scalar,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_complex_matrix, octave_float_scalar,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_complex_matrix, octave_float_scalar,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_complex_matrix, octave_float_scalar,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_complex_matrix, octave_float_scalar,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_complex_matrix, octave_float_scalar,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_complex_matrix, octave_float_scalar,\n                    le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_complex_matrix, octave_float_scalar,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_complex_matrix, octave_float_scalar,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_complex_matrix, octave_float_scalar,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_complex_matrix, octave_float_scalar,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_complex_matrix,\n                    octave_float_scalar,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_complex_matrix,\n                    octave_float_scalar,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_complex_matrix,\n                    octave_float_scalar,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_complex_matrix,\n                    octave_float_scalar,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_complex_matrix,\n                    octave_float_scalar,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_complex_matrix,\n                    octave_float_scalar,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_complex_matrix, octave_float_scalar, fcm_fs);\n  INSTALL_CATOP_TI (ti, octave_complex_matrix, octave_float_scalar, cm_fs);\n  INSTALL_CATOP_TI (ti, octave_float_complex_matrix, octave_scalar, fcm_s);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix,\n                       octave_float_scalar, assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix,\n                       octave_float_scalar, dbl_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_mul_eq, octave_float_complex_matrix,\n                       octave_float_scalar, assign_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_div_eq, octave_float_complex_matrix,\n                       octave_float_scalar, assign_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcm-pm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define MINCLUDE \"ov-flt-cx-mat.h\"\n\n#define LMATRIX float_complex_matrix\n#define RMATRIX perm_matrix\n\n#define LSHORT fcm\n#define RSHORT pm\n\n#define RIGHT\n\n#include \"op-pm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fcn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-scalar.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFBINOP (eq, fcn_handle, fcn_handle)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_fcn_handle&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_fcn_handle&, v2, a2);\n\n  return is_equal_to (v1, v2);\n}\n\nDEFBINOP (ne, fcn_handle, fcn_handle)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_fcn_handle&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_fcn_handle&, v2, a2);\n\n  return ! is_equal_to (v1, v2);\n}\n\nvoid\ninstall_fcn_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_eq, octave_fcn_handle, octave_fcn_handle, eq);\n  INSTALL_BINOP_TI (ti, op_ne, octave_fcn_handle, octave_fcn_handle, ne);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcs-fcm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex scalar by complex matrix ops.\n\nDEFNDBINOP_OP (add, float_complex, float_complex_matrix, float_complex,\n               float_complex_array, +)\nDEFNDBINOP_OP (sub, float_complex, float_complex_matrix, float_complex,\n               float_complex_array, -)\nDEFNDBINOP_OP (mul, float_complex, float_complex_matrix, float_complex,\n               float_complex_array, *)\n\nDEFBINOP (div, float_complex, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n\n  FloatComplexMatrix m1 = v1.float_complex_matrix_value ();\n  FloatComplexMatrix m2 = v2.float_complex_matrix_value ();\n  MatrixType typ = v2.matrix_type ();\n\n  FloatComplexMatrix ret = xdiv (m1, m2, typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (pow, float_complex, float_complex_matrix, xpow)\n\nDEFBINOP (ldiv, float_complex, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n\n  return octave_value (v2.float_complex_array_value () / v1.float_complex_value ());\n}\n\nDEFNDCMPLXCMPOP_FN (lt, float_complex, float_complex_matrix, float_complex,\n                    float_complex_array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, float_complex, float_complex_matrix, float_complex,\n                    float_complex_array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, float_complex, float_complex_matrix, float_complex,\n                    float_complex_array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, float_complex, float_complex_matrix, float_complex,\n                    float_complex_array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, float_complex, float_complex_matrix, float_complex,\n                    float_complex_array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, float_complex, float_complex_matrix, float_complex,\n                    float_complex_array, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, float_complex, float_complex_matrix, float_complex,\n               float_complex_array, *)\nDEFNDBINOP_FN (el_div, float_complex, float_complex_matrix, float_complex,\n               float_complex_array, elem_xdiv)\nDEFNDBINOP_FN (el_pow, float_complex, float_complex_matrix, float_complex,\n               float_complex_array, elem_xpow)\n\nDEFBINOP (el_ldiv, float_complex, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n\n  return octave_value (v2.float_complex_array_value () / v1.float_complex_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_complex, float_complex_matrix, float_complex,\n               float_complex_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_complex, float_complex_matrix, float_complex,\n               float_complex_array, mx_el_or)\n\nDEFNDCATOP_FN (fcs_fcm, float_complex, float_complex_matrix,\n               float_complex_array, float_complex_array, concat)\n\nDEFNDCATOP_FN (cs_fcm, complex, float_complex_matrix, float_complex_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (fcs_cm, float_complex, complex_matrix, float_complex_array,\n               float_complex_array, concat)\n\nDEFCONV (float_complex_matrix_conv, float_complex, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v, a);\n\n  return new octave_float_complex_matrix (v.float_complex_matrix_value ());\n}\n\nvoid\ninstall_fcs_fcm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_complex, octave_float_complex_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_complex, octave_float_complex_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_complex, octave_float_complex_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_complex, octave_float_complex_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_complex, octave_float_complex_matrix,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_complex,\n                    octave_float_complex_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_complex, octave_float_complex_matrix,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_complex, octave_float_complex_matrix,\n                    le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_complex, octave_float_complex_matrix,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_complex, octave_float_complex_matrix,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_complex, octave_float_complex_matrix,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_complex, octave_float_complex_matrix,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_complex,\n                    octave_float_complex_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_complex,\n                    octave_float_complex_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_complex,\n                    octave_float_complex_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_complex,\n                    octave_float_complex_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_complex,\n                    octave_float_complex_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_complex,\n                    octave_float_complex_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_complex, octave_float_complex_matrix,\n                    fcs_fcm);\n  INSTALL_CATOP_TI (ti, octave_complex, octave_float_complex_matrix, cs_fcm);\n  INSTALL_CATOP_TI (ti, octave_float_complex, octave_complex_matrix, fcs_cm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex, octave_float_complex_matrix,\n                         octave_float_complex_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_float_complex_matrix,\n                         octave_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_float_complex, octave_float_complex_matrix,\n                      float_complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcs-fcs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// unary complex scalar ops.\n\nDEFUNOP (not, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v, a);\n  FloatComplex x = v.float_complex_value ();\n  if (octave::math::isnan (x))\n    octave::err_nan_to_logical_conversion ();\n\n  return octave_value (x == 0.0f);\n}\n\nDEFUNOP_OP (uplus, float_complex, /* no-op */)\nDEFUNOP_OP (uminus, float_complex, -)\nDEFUNOP_OP (transpose, float_complex, /* no-op */)\n\nDEFUNOP (hermitian, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v, a);\n\n  return octave_value (conj (v.float_complex_value ()));\n}\n\nDEFNCUNOP_METHOD (incr, float_complex, increment)\nDEFNCUNOP_METHOD (decr, float_complex, decrement)\n\n// complex scalar by complex scalar ops.\n\nDEFBINOP_OP (add, float_complex, float_complex, +)\nDEFBINOP_OP (sub, float_complex, float_complex, -)\nDEFBINOP_OP (mul, float_complex, float_complex, *)\n\nDEFBINOP (div, float_complex, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_complex_value () / v2.float_complex_value ());\n}\n\nDEFBINOP_FN (pow, float_complex, float_complex, xpow)\n\nDEFBINOP (ldiv, float_complex, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v2.float_complex_value () / v1.float_complex_value ());\n}\n\nDEFCMPLXCMPOP_OP (lt, float_complex, float_complex, <)\nDEFCMPLXCMPOP_OP (le, float_complex, float_complex, <=)\nDEFCMPLXCMPOP_OP (eq, float_complex, float_complex, ==)\nDEFCMPLXCMPOP_OP (ge, float_complex, float_complex, >=)\nDEFCMPLXCMPOP_OP (gt, float_complex, float_complex, >)\nDEFCMPLXCMPOP_OP (ne, float_complex, float_complex, !=)\n\nDEFBINOP_OP (el_mul, float_complex, float_complex, *)\n\nDEFBINOP (el_div, float_complex, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_complex_value () / v2.float_complex_value ());\n}\n\nDEFBINOP_FN (el_pow, float_complex, float_complex, xpow)\n\nDEFBINOP (el_ldiv, float_complex, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v2.float_complex_value () / v1.float_complex_value ());\n}\n\nDEFBINOP (el_and, float_complex, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return (v1.float_complex_value () != 0.0f\n          && v2.float_complex_value () != 0.0f);\n}\n\nDEFBINOP (el_or, float_complex, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return (v1.float_complex_value () != 0.0f\n          || v2.float_complex_value () != 0.0f);\n}\n\nDEFNDCATOP_FN (fcs_fcs, float_complex, float_complex, float_complex_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (cs_fcs, complex, float_complex, float_complex_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (fcs_cs, float_complex, complex, float_complex_array,\n               float_complex_array, concat)\n\nvoid\ninstall_fcs_fcs_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_float_complex, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_float_complex, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_float_complex, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_float_complex, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_float_complex, hermitian);\n\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_float_complex, incr);\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_float_complex, decr);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_float_complex, octave_float_complex, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_complex, octave_float_complex, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_complex, octave_float_complex, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_complex, octave_float_complex, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_complex, octave_float_complex, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_complex, octave_float_complex,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_complex, octave_float_complex, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_complex, octave_float_complex, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_complex, octave_float_complex, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_complex, octave_float_complex, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_complex, octave_float_complex, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_complex, octave_float_complex, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_complex, octave_float_complex,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_complex, octave_float_complex,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_complex, octave_float_complex,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_complex, octave_float_complex,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_complex, octave_float_complex,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_complex, octave_float_complex,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_complex, octave_float_complex, fcs_fcs);\n  INSTALL_CATOP_TI (ti, octave_complex, octave_float_complex, cs_fcs);\n  INSTALL_CATOP_TI (ti, octave_float_complex, octave_complex, fcs_cs);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex, octave_float_complex,\n                         octave_float_complex_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_float_complex,\n                         octave_complex_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex, octave_null_matrix,\n                         octave_float_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex, octave_null_str,\n                         octave_float_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex, octave_null_sq_str,\n                         octave_float_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcs-fm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-fcs-fnda.h\"\n#include \"mx-fnda-fcs.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex scalar by matrix ops.\n\nDEFNDBINOP_OP (add, float_complex, float_matrix, float_complex, float_array, +)\nDEFNDBINOP_OP (sub, float_complex, float_matrix, float_complex, float_array, -)\nDEFNDBINOP_OP (mul, float_complex, float_matrix, float_complex, float_array, *)\n\nDEFBINOP (div, float_complex, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n\n  FloatComplexMatrix m1 = v1.float_complex_matrix_value ();\n  FloatMatrix m2 = v2.float_matrix_value ();\n  MatrixType typ = v2.matrix_type ();\n\n  FloatComplexMatrix ret = xdiv (m1, m2, typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (pow, float_complex, float_matrix, xpow)\n\nDEFBINOP (ldiv, float_complex, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n\n  return octave_value (v2.float_array_value () / v1.float_complex_value ());\n}\n\nDEFNDCMPLXCMPOP_FN (lt, float_complex, float_matrix, float_complex,\n                    float_array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, float_complex, float_matrix, float_complex,\n                    float_array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, float_complex, float_matrix, float_complex,\n                    float_array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, float_complex, float_matrix, float_complex,\n                    float_array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, float_complex, float_matrix, float_complex,\n                    float_array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, float_complex, float_matrix, float_complex,\n                    float_array, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, float_complex, float_matrix, float_complex,\n               float_array, *)\nDEFNDBINOP_FN (el_div, float_complex, float_matrix, float_complex,\n               float_array, elem_xdiv)\nDEFNDBINOP_FN (el_pow, float_complex, float_matrix, float_complex,\n               float_array, elem_xpow)\n\nDEFBINOP (el_ldiv, float_complex, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n\n  return octave_value (v2.float_array_value () / v1.float_complex_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_complex, float_matrix, float_complex,\n               float_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_complex, float_matrix, float_complex,\n               float_array, mx_el_or)\n\nDEFNDCATOP_FN (fcs_fm, float_complex, float_matrix, float_complex_array,\n               float_array, concat)\n\nDEFNDCATOP_FN (cs_fm, complex, float_matrix, float_complex_array,\n               float_array, concat)\n\nDEFNDCATOP_FN (fcs_m, float_complex, matrix, float_complex_array,\n               float_array, concat)\n\nvoid\ninstall_fcs_fm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_complex, octave_float_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_complex, octave_float_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_complex, octave_float_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_complex, octave_float_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_complex, octave_float_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_complex, octave_float_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_complex, octave_float_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_complex, octave_float_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_complex, octave_float_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_complex, octave_float_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_complex, octave_float_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_complex, octave_float_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_complex, octave_float_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_complex, octave_float_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_complex, octave_float_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_complex, octave_float_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_complex, octave_float_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_complex, octave_float_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_complex, octave_float_matrix, fcs_fm);\n  INSTALL_CATOP_TI (ti, octave_complex, octave_float_matrix, cs_fm);\n  INSTALL_CATOP_TI (ti, octave_float_complex, octave_matrix, fcs_m);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex, octave_float_matrix,\n                         octave_float_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_float_matrix,\n                         octave_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fcs-fs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-float.h\"\n#include \"ov-scalar.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// complex scalar by scalar ops.\n\nDEFBINOP_OP (add, float_complex, float_scalar, +)\nDEFBINOP_OP (sub, float_complex, float_scalar, -)\nDEFBINOP_OP (mul, float_complex, float_scalar, *)\n\nDEFBINOP (div, float_complex, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v1.float_complex_value () / v2.float_value ());\n}\n\nDEFBINOP_FN (pow, float_complex, float_scalar, xpow)\n\nDEFBINOP (ldiv, float_complex, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v2.float_value () / v1.float_complex_value ());\n}\n\nDEFCMPLXCMPOP_OP (lt, float_complex, float_scalar, <)\nDEFCMPLXCMPOP_OP (le, float_complex, float_scalar, <=)\nDEFCMPLXCMPOP_OP (eq, float_complex, float_scalar, ==)\nDEFCMPLXCMPOP_OP (ge, float_complex, float_scalar, >=)\nDEFCMPLXCMPOP_OP (gt, float_complex, float_scalar, >)\nDEFCMPLXCMPOP_OP (ne, float_complex, float_scalar, !=)\n\nDEFBINOP_OP (el_mul, float_complex, float_scalar, *)\n\nDEFBINOP (el_div, float_complex, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v1.float_complex_value () / v2.float_value ());\n}\n\nDEFBINOP_FN (el_pow, float_complex, float_scalar, xpow)\n\nDEFBINOP (el_ldiv, float_complex, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v2.float_value () / v1.float_complex_value ());\n}\n\nDEFBINOP (el_and, float_complex, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return (v1.float_complex_value () != 0.0f && v2.float_value ());\n}\n\nDEFBINOP (el_or, float_complex, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return (v1.float_complex_value () != 0.0f || v2.float_value ());\n}\n\nDEFNDCATOP_FN (fcs_fs, float_complex, float_scalar, float_complex_array,\n               float_array, concat)\n\nDEFNDCATOP_FN (cs_fs, complex, float_scalar, float_complex_array,\n               float_array, concat)\n\nDEFNDCATOP_FN (fcs_s, float_complex, scalar, float_complex_array,\n               float_array, concat)\n\nvoid\ninstall_fcs_fs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_complex, octave_float_scalar, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_complex, octave_float_scalar, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_complex, octave_float_scalar, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_complex, octave_float_scalar, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_complex, octave_float_scalar, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_complex, octave_float_scalar, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_complex, octave_float_scalar, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_complex, octave_float_scalar, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_complex, octave_float_scalar, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_complex, octave_float_scalar, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_complex, octave_float_scalar, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_complex, octave_float_scalar, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_complex, octave_float_scalar,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_complex, octave_float_scalar,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_complex, octave_float_scalar,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_complex, octave_float_scalar,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_complex, octave_float_scalar,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_complex, octave_float_scalar,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_complex, octave_float_scalar, fcs_fs);\n  INSTALL_CATOP_TI (ti, octave_complex, octave_float_scalar, cs_fs);\n  INSTALL_CATOP_TI (ti, octave_float_complex, octave_scalar, fcs_s);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex, octave_float_scalar,\n                         octave_float_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex, octave_float_scalar,\n                         octave_complex_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex, octave_scalar,\n                         octave_float_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fdm-fcdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-flt-re-diag.h\"\n#define RINCLUDE \"ov-flt-cx-diag.h\"\n\n#define LMATRIX float_diag_matrix\n#define RMATRIX float_complex_diag_matrix\n#define LDMATRIX RMATRIX\n\n#define LSHORT fdm\n#define RSHORT fcdm\n\n#define DEFINEDIV\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fdm-fcm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-flt-re-diag.h\"\n#define RINCLUDE \"ov-flt-cx-mat.h\"\n\n#define LMATRIX float_diag_matrix\n#define RMATRIX float_complex_matrix\n\n#define LSHORT fdm\n#define RSHORT fcm\n\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fdm-fcs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define SINCLUDE \"ov-flt-complex.h\"\n#define MINCLUDE \"ov-flt-re-diag.h\"\n\n#define SCALAR float_complex\n#define DIAG_MATRIX float_diag_matrix\n#define DIAG_MATRIXV float_complex_diag_matrix\n#define MATRIX float_matrix\n#define MATRIXV float_complex_matrix\n\n#define SSHORT fcs\n#define MSHORT fdm\n\n#include \"op-dms-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fdm-fdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-flt-re-diag.h\"\n#include \"ov-re-diag.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix unary ops.\n\nDEFUNOP_OP (uplus, float_diag_matrix, /* no-op */)\nDEFUNOP_OP (uminus, float_diag_matrix, -)\n\nDEFUNOP (transpose, float_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v, a);\n  return octave_value (v.float_diag_matrix_value ().transpose ());\n}\n\n// matrix by matrix ops.\n\nDEFBINOP_OP (add, float_diag_matrix, float_diag_matrix, +)\nDEFBINOP_OP (sub, float_diag_matrix, float_diag_matrix, -)\nDEFBINOP_OP (mul, float_diag_matrix, float_diag_matrix, *)\n\nDEFBINOP (div, float_diag_matrix, float_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v2, a2);\n\n  return xdiv (v1.float_diag_matrix_value (),\n               v2.float_diag_matrix_value ());\n}\n\nDEFBINOP (ldiv, float_diag_matrix, float_diag_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v2, a2);\n\n  return xleftdiv (v1.float_diag_matrix_value (),\n                   v2.float_diag_matrix_value ());\n}\n\nCONVDECL (float_diag_matrix_to_float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v, a);\n\n  return new octave_float_matrix (v.float_matrix_value ());\n}\n\nvoid\ninstall_fdm_fdm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_uplus, octave_float_diag_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_float_diag_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_float_diag_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_float_diag_matrix, transpose);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_float_diag_matrix,\n                    octave_float_diag_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_diag_matrix,\n                    octave_float_diag_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_diag_matrix,\n                    octave_float_diag_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_diag_matrix,\n                    octave_float_diag_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_diag_matrix,\n                    octave_float_diag_matrix,\n                    ldiv);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_diag_matrix, octave_float_matrix,\n                         octave_float_matrix);\n  INSTALL_WIDENOP_TI (ti, octave_float_diag_matrix, octave_float_matrix,\n                      float_diag_matrix_to_float_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fdm-fm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-flt-re-diag.h\"\n#define RINCLUDE \"ov-flt-re-mat.h\"\n\n#define LMATRIX float_diag_matrix\n#define RMATRIX float_matrix\n\n#define LSHORT fdm\n#define RSHORT fm\n\n#define DEFINELDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fdm-fs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define SINCLUDE \"ov-float.h\"\n#define MINCLUDE \"ov-flt-re-diag.h\"\n\n#define SCALAR float_scalar\n#define DIAG_MATRIX float_diag_matrix\n#define MATRIX float_matrix\n\n#define SSHORT fs\n#define MSHORT fdm\n\n#include \"op-dms-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fm-fcdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-flt-re-mat.h\"\n#define RINCLUDE \"ov-flt-cx-diag.h\"\n\n#define LMATRIX float_matrix\n#define RMATRIX float_complex_diag_matrix\n#define LDMATRIX float_complex_matrix\n\n#define LSHORT fm\n#define RSHORT fcdm\n\n#define DEFINEDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fm-fcm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-fm-fcm.h\"\n#include \"mx-fcm-fm.h\"\n#include \"mx-fnda-fcnda.h\"\n#include \"mx-fcnda-fnda.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix by complex matrix ops.\n\nDEFNDBINOP_OP (add, float_matrix, float_complex_matrix, float_array,\n               float_complex_array, +)\nDEFNDBINOP_OP (sub, float_matrix, float_complex_matrix, float_array,\n               float_complex_array, -)\n\nDEFBINOP_OP (mul, float_matrix, float_complex_matrix, *)\n\nDEFBINOP (trans_mul, float_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n\n  FloatMatrix m1 = v1.float_matrix_value ();\n  FloatComplexMatrix m2 = v2.float_complex_matrix_value ();\n\n  return FloatComplexMatrix (xgemm (m1, real (m2), blas_trans, blas_no_trans),\n                             xgemm (m1, imag (m2), blas_trans, blas_no_trans));\n}\n\nDEFBINOP (div, float_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  FloatComplexMatrix ret = xdiv (v1.float_matrix_value (),\n                                 v2.float_complex_matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, float_matrix, float_complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, float_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  FloatComplexMatrix ret = xleftdiv (v1.float_matrix_value (),\n                                     v2.float_complex_matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP (trans_ldiv, float_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  FloatComplexMatrix ret = xleftdiv (v1.float_matrix_value (),\n                                     v2.float_complex_matrix_value (),\n                                     typ, blas_trans);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, float_matrix, float_complex_matrix, float_array,\n                    float_complex_array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, float_matrix, float_complex_matrix, float_array,\n                    float_complex_array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, float_matrix, float_complex_matrix, float_array,\n                    float_complex_array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, float_matrix, float_complex_matrix, float_array,\n                    float_complex_array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, float_matrix, float_complex_matrix, float_array,\n                    float_complex_array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, float_matrix, float_complex_matrix, float_array,\n                    float_complex_array, mx_el_ne)\n\nDEFNDBINOP_FN (el_mul, float_matrix, float_complex_matrix, float_array,\n               float_complex_array, product)\nDEFNDBINOP_FN (el_div, float_matrix, float_complex_matrix, float_array,\n               float_complex_array, quotient)\nDEFNDBINOP_FN (el_pow, float_matrix, float_complex_matrix, float_array,\n               float_complex_array, elem_xpow)\n\nDEFBINOP (el_ldiv, float_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n\n  return quotient (v2.float_complex_array_value (), v1.float_array_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_matrix, float_complex_matrix, float_array,\n               float_complex_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_matrix, float_complex_matrix, float_array,\n               float_complex_array, mx_el_or)\n\nDEFNDCATOP_FN (fm_fcm, float_matrix, float_complex_matrix, float_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (m_fcm, matrix, float_complex_matrix, float_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (fm_cm, float_matrix, complex_matrix, float_array,\n               float_complex_array, concat)\n\nDEFCONV (float_complex_matrix_conv, float_matrix, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v, a);\n\n  return new octave_float_complex_matrix (FloatComplexNDArray\n                                          (v.float_array_value ()));\n}\n\nvoid\ninstall_fm_fcm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_matrix, octave_float_complex_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_matrix, octave_float_complex_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_matrix, octave_float_complex_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_matrix, octave_float_complex_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_matrix, octave_float_complex_matrix,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_matrix,\n                    octave_float_complex_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_matrix, octave_float_complex_matrix,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_matrix, octave_float_complex_matrix,\n                    le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_matrix, octave_float_complex_matrix,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_matrix, octave_float_complex_matrix,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_matrix, octave_float_complex_matrix,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_matrix, octave_float_complex_matrix,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_matrix,\n                    octave_float_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_matrix,\n                    octave_float_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_matrix,\n                    octave_float_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_matrix,\n                    octave_float_complex_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_matrix,\n                    octave_float_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_matrix,\n                    octave_float_complex_matrix, el_or);\n  INSTALL_BINOP_TI (ti, op_trans_mul, octave_float_matrix,\n                    octave_float_complex_matrix, trans_mul);\n  INSTALL_BINOP_TI (ti, op_herm_mul, octave_float_matrix,\n                    octave_float_complex_matrix, trans_mul);\n  INSTALL_BINOP_TI (ti, op_trans_ldiv, octave_float_matrix,\n                    octave_float_complex_matrix, trans_ldiv);\n  INSTALL_BINOP_TI (ti, op_herm_ldiv, octave_float_matrix,\n                    octave_float_complex_matrix, trans_ldiv);\n\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_float_complex_matrix, fm_fcm);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_float_complex_matrix, m_fcm);\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_complex_matrix, fm_cm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_matrix, octave_float_complex_matrix,\n                         octave_float_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_matrix, octave_float_complex_matrix,\n                         octave_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_float_matrix, octave_float_complex_matrix,\n                      float_complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fm-fcs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-fm-fcs.h\"\n#include \"mx-fcs-fm.h\"\n#include \"mx-fnda-fcs.h\"\n#include \"mx-fcs-fnda.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-complex.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix by complex scalar ops.\n\nDEFNDBINOP_OP (add, float_matrix, float_complex, float_array, float_complex, +)\nDEFNDBINOP_OP (sub, float_matrix, float_complex, float_array, float_complex, -)\nDEFNDBINOP_OP (mul, float_matrix, float_complex, float_array, float_complex, *)\n\nDEFBINOP (div, float_matrix, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_array_value () / v2.float_complex_value ());\n}\n\nDEFBINOP_FN (pow, float_matrix, float_complex, xpow)\n\nDEFBINOP (ldiv, float_matrix, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  FloatMatrix m1 = v1.float_matrix_value ();\n  FloatComplexMatrix m2 = v2.float_complex_matrix_value ();\n  MatrixType typ = v1.matrix_type ();\n\n  FloatComplexMatrix ret = xleftdiv (m1, m2, typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, float_matrix, float_complex, float_array,\n                    float_complex, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, float_matrix, float_complex, float_array,\n                    float_complex, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, float_matrix, float_complex, float_array,\n                    float_complex, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, float_matrix, float_complex, float_array,\n                    float_complex, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, float_matrix, float_complex, float_array,\n                    float_complex, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, float_matrix, float_complex, float_array,\n                    float_complex, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, float_matrix, float_complex, float_array,\n               float_complex, *)\n\nDEFBINOP (el_div, float_matrix, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_array_value () / v2.float_complex_value ());\n}\n\nDEFNDBINOP_FN (el_pow, float_matrix, float_complex, float_array,\n               float_complex, elem_xpow)\n\nDEFBINOP (el_ldiv, float_matrix, flaot_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return elem_xdiv (v2.float_complex_value (), v1.float_array_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_matrix, float_complex, float_array,\n               float_complex, mx_el_and)\nDEFNDBINOP_FN (el_or, float_matrix, float_complex, float_array,\n               float_complex, mx_el_or)\n\nDEFNDCATOP_FN (fm_fcs, float_matrix, float_complex, float_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (m_fcs, matrix, float_complex, float_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (fm_cs, float_matrix, complex, float_array,\n               float_complex_array, concat)\n\nvoid\ninstall_fm_fcs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_matrix, octave_float_complex, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_matrix, octave_float_complex, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_matrix, octave_float_complex, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_matrix, octave_float_complex, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_matrix, octave_float_complex, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_matrix, octave_float_complex, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_matrix, octave_float_complex, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_matrix, octave_float_complex, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_matrix, octave_float_complex, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_matrix, octave_float_complex, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_matrix, octave_float_complex, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_matrix, octave_float_complex, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_matrix, octave_float_complex,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_matrix, octave_float_complex,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_matrix, octave_float_complex,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_matrix, octave_float_complex,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_matrix, octave_float_complex,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_matrix, octave_float_complex,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_float_complex, fm_fcs);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_float_complex, m_fcs);\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_complex, fm_cs);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_matrix, octave_float_complex,\n                         octave_float_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_matrix, octave_float_complex,\n                         octave_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fm-fdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-flt-re-mat.h\"\n#define RINCLUDE \"ov-flt-re-diag.h\"\n\n#define LMATRIX float_matrix\n#define RMATRIX float_diag_matrix\n\n#define LSHORT fm\n#define RSHORT fdm\n\n#define DEFINEDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fm-fm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix unary ops.\n\nDEFNDUNOP_OP (not, float_matrix, float_array, !)\nDEFNDUNOP_OP (uplus, float_matrix, float_array, /* no-op */)\nDEFNDUNOP_OP (uminus, float_matrix, float_array, -)\n\nDEFUNOP (transpose, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"transpose not defined for N-D objects\");\n\n  return octave_value (v.float_matrix_value ().transpose ());\n}\n\nDEFNCUNOP_METHOD (incr, float_matrix, increment)\nDEFNCUNOP_METHOD (decr, float_matrix, decrement)\nDEFNCUNOP_METHOD (changesign, float_matrix, changesign)\n\n// matrix by matrix ops.\n\nDEFNDBINOP_OP (add, float_matrix, float_matrix, float_array, float_array, +)\nDEFNDBINOP_OP (sub, float_matrix, float_matrix, float_array, float_array, -)\n\nDEFBINOP_OP (mul, float_matrix, float_matrix, *)\n\nDEFBINOP (div, float_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  FloatMatrix ret = xdiv (v1.float_matrix_value (),\n                          v2.float_matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, float_matrix, float_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, float_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  FloatMatrix ret = xleftdiv (v1.float_matrix_value (),\n                              v2.float_matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP (trans_mul, float_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n  return octave_value(xgemm (v1.float_matrix_value (),\n                             v2.float_matrix_value (),\n                             blas_trans, blas_no_trans));\n}\n\nDEFBINOP (mul_trans, float_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n  return octave_value(xgemm (v1.float_matrix_value (),\n                             v2.float_matrix_value (),\n                             blas_no_trans, blas_trans));\n}\n\nDEFBINOP (trans_ldiv, float_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  FloatMatrix ret = xleftdiv (v1.float_matrix_value (),\n                              v2.float_matrix_value (), typ, blas_trans);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDBINOP_FN (lt, float_matrix, float_matrix, float_array,\n               float_array, mx_el_lt)\nDEFNDBINOP_FN (le, float_matrix, float_matrix, float_array,\n               float_array, mx_el_le)\nDEFNDBINOP_FN (eq, float_matrix, float_matrix, float_array,\n               float_array, mx_el_eq)\nDEFNDBINOP_FN (ge, float_matrix, float_matrix, float_array,\n               float_array, mx_el_ge)\nDEFNDBINOP_FN (gt, float_matrix, float_matrix, float_array,\n               float_array, mx_el_gt)\nDEFNDBINOP_FN (ne, float_matrix, float_matrix, float_array,\n               float_array, mx_el_ne)\n\nDEFNDBINOP_FN (el_mul, float_matrix, float_matrix, float_array,\n               float_array, product)\nDEFNDBINOP_FN (el_div, float_matrix, float_matrix, float_array,\n               float_array, quotient)\nDEFNDBINOP_FN (el_pow, float_matrix, float_matrix, float_array,\n               float_array, elem_xpow)\n\nDEFBINOP (el_ldiv, float_matrix, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n\n  return octave_value (quotient (v2.float_array_value (),\n                                 v1.float_array_value ()));\n}\n\nDEFNDBINOP_FN (el_and, float_matrix, float_matrix, float_array,\n               float_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_matrix, float_matrix, float_array,\n               float_array, mx_el_or)\nDEFNDBINOP_FN (el_not_and, float_matrix, float_matrix, float_array,\n               float_array, mx_el_not_and)\nDEFNDBINOP_FN (el_not_or,  float_matrix, float_matrix, float_array,\n               float_array, mx_el_not_or)\nDEFNDBINOP_FN (el_and_not, float_matrix, float_matrix, float_array,\n               float_array, mx_el_and_not)\nDEFNDBINOP_FN (el_or_not,  float_matrix, float_matrix, float_array,\n               float_array, mx_el_or_not)\n\nDEFNDCATOP_FN (fm_fm, float_matrix, float_matrix, float_array,\n               float_array, concat)\n\nDEFNDCATOP_FN (m_fm, matrix, float_matrix, float_array, float_array, concat)\n\nDEFNDCATOP_FN (fm_m, float_matrix, matrix, float_array, float_array, concat)\n\nDEFNDASSIGNOP_FN (assign, float_matrix, float_matrix, float_array, assign)\n\nDEFNDASSIGNOP_FN (dbl_assign, matrix, float_matrix, array, assign)\n\nDEFNULLASSIGNOP_FN (null_assign, float_matrix, delete_elements)\n\nDEFNDASSIGNOP_OP (assign_add, float_matrix, float_matrix, float_array, +=)\nDEFNDASSIGNOP_OP (assign_sub, float_matrix, float_matrix, float_array, -=)\nDEFNDASSIGNOP_FNOP (assign_el_mul, float_matrix, float_matrix, float_array,\n                    product_eq)\nDEFNDASSIGNOP_FNOP (assign_el_div, float_matrix, float_matrix, float_array,\n                    quotient_eq)\n\nvoid\ninstall_fm_fm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_float_matrix, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_float_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_float_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_float_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_float_matrix, transpose);\n\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_float_matrix, incr);\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_float_matrix, decr);\n  INSTALL_NCUNOP_TI (ti, op_uminus, octave_float_matrix, changesign);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_float_matrix, octave_float_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_matrix, octave_float_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_matrix, octave_float_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_matrix, octave_float_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_matrix, octave_float_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_matrix, octave_float_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_matrix, octave_float_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_matrix, octave_float_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_matrix, octave_float_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_matrix, octave_float_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_matrix, octave_float_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_matrix, octave_float_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_matrix, octave_float_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_matrix, octave_float_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_matrix, octave_float_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_matrix, octave_float_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_matrix, octave_float_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_matrix, octave_float_matrix,\n                    el_or);\n  INSTALL_BINOP_TI (ti, op_el_and_not, octave_float_matrix, octave_float_matrix,\n                    el_and_not);\n  INSTALL_BINOP_TI (ti, op_el_or_not, octave_float_matrix, octave_float_matrix,\n                    el_or_not);\n  INSTALL_BINOP_TI (ti, op_el_not_and, octave_float_matrix, octave_float_matrix,\n                    el_not_and);\n  INSTALL_BINOP_TI (ti, op_el_not_or, octave_float_matrix, octave_float_matrix,\n                    el_not_or);\n  INSTALL_BINOP_TI (ti, op_trans_mul, octave_float_matrix, octave_float_matrix,\n                    trans_mul);\n  INSTALL_BINOP_TI (ti, op_mul_trans, octave_float_matrix, octave_float_matrix,\n                    mul_trans);\n  INSTALL_BINOP_TI (ti, op_herm_mul, octave_float_matrix, octave_float_matrix,\n                    trans_mul);\n  INSTALL_BINOP_TI (ti, op_mul_herm, octave_float_matrix, octave_float_matrix,\n                    mul_trans);\n  INSTALL_BINOP_TI (ti, op_trans_ldiv, octave_float_matrix, octave_float_matrix,\n                    trans_ldiv);\n  INSTALL_BINOP_TI (ti, op_herm_ldiv, octave_float_matrix, octave_float_matrix,\n                    trans_ldiv);\n\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_float_matrix, fm_fm);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_float_matrix, m_fm);\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_matrix, fm_m);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_matrix,\n                       octave_float_matrix, assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix,\n                       octave_float_matrix, dbl_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_matrix, octave_null_matrix,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_matrix, octave_null_str,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_matrix, octave_null_sq_str,\n                       null_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_float_matrix, octave_float_matrix,\n                       assign_add);\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_float_matrix, octave_float_matrix,\n                       assign_sub);\n  INSTALL_ASSIGNOP_TI (ti, op_el_mul_eq, octave_float_matrix, octave_float_matrix,\n                       assign_el_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_el_div_eq, octave_float_matrix, octave_float_matrix,\n                       assign_el_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fm-fs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-float.h\"\n#include \"ov-scalar.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix by scalar ops.\n\nDEFNDBINOP_OP (add, float_matrix, float_scalar, float_array, float_scalar, +)\nDEFNDBINOP_OP (sub, float_matrix, float_scalar, float_array, float_scalar, -)\nDEFNDBINOP_OP (mul, float_matrix, float_scalar, float_array, float_scalar, *)\n\nDEFBINOP (div, float_matrix, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v1.float_array_value () / v2.float_value ());\n}\n\nDEFBINOP_FN (pow, float_matrix, float_scalar, xpow)\n\nDEFBINOP (ldiv, float_matrix, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  FloatMatrix m1 = v1.float_matrix_value ();\n  FloatMatrix m2 = v2.float_matrix_value ();\n  MatrixType typ = v1.matrix_type ();\n\n  FloatMatrix ret = xleftdiv (m1, m2, typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDBINOP_FN (lt, float_matrix, float_scalar, float_array,\n               float_scalar, mx_el_lt)\nDEFNDBINOP_FN (le, float_matrix, float_scalar, float_array,\n               float_scalar, mx_el_le)\nDEFNDBINOP_FN (eq, float_matrix, float_scalar, float_array,\n               float_scalar, mx_el_eq)\nDEFNDBINOP_FN (ge, float_matrix, float_scalar, float_array,\n               float_scalar, mx_el_ge)\nDEFNDBINOP_FN (gt, float_matrix, float_scalar, float_array,\n               float_scalar, mx_el_gt)\nDEFNDBINOP_FN (ne, float_matrix, float_scalar, float_array,\n               float_scalar, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, float_matrix, float_scalar, float_array, float_scalar, *)\n\nDEFBINOP (el_div, float_matrix, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v1.float_array_value () / v2.float_value ());\n}\n\nDEFNDBINOP_FN (el_pow, float_matrix, float_scalar, float_array,\n               float_scalar, elem_xpow)\n\nDEFBINOP (el_ldiv, float_matrix, float)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return elem_xdiv (v2.float_value (), v1.float_array_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_matrix, float_scalar, float_array,\n               float_scalar, mx_el_and)\nDEFNDBINOP_FN (el_or, float_matrix, float_scalar, float_array,\n               float_scalar, mx_el_or)\n\nDEFNDCATOP_FN (fm_fs, float_matrix, float_scalar, float_array,\n               float_array, concat)\n\nDEFNDCATOP_FN (m_fs, matrix, float_scalar, float_array, float_array, concat)\n\nDEFNDCATOP_FN (fm_s, float_matrix, scalar, float_array, float_array, concat)\n\nDEFNDASSIGNOP_FN (assign, float_matrix, float_scalar, float_scalar, assign)\nDEFNDASSIGNOP_FN (dbl_assign, matrix, float_scalar, scalar, assign)\n\nDEFNDASSIGNOP_OP (assign_add, float_matrix, float_scalar, float_scalar, +=)\nDEFNDASSIGNOP_OP (assign_sub, float_matrix, float_scalar, float_scalar, -=)\nDEFNDASSIGNOP_OP (assign_mul, float_matrix, float_scalar, float_scalar, *=)\nDEFNDASSIGNOP_OP (assign_div, float_matrix, float_scalar, float_scalar, /=)\n\nvoid\ninstall_fm_fs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_matrix, octave_float_scalar, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_matrix, octave_float_scalar, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_matrix, octave_float_scalar, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_matrix, octave_float_scalar, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_matrix, octave_float_scalar, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_matrix, octave_float_scalar, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_matrix, octave_float_scalar, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_matrix, octave_float_scalar, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_matrix, octave_float_scalar, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_matrix, octave_float_scalar, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_matrix, octave_float_scalar, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_matrix, octave_float_scalar, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_matrix, octave_float_scalar,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_matrix, octave_float_scalar,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_matrix, octave_float_scalar,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_matrix, octave_float_scalar,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_matrix, octave_float_scalar,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_matrix, octave_float_scalar,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_float_scalar, fm_fs);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_float_scalar, m_fs);\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_scalar, fm_s);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_matrix, octave_float_scalar,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_float_scalar,\n                       dbl_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_float_matrix, octave_float_scalar,\n                       assign_add);\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_float_matrix, octave_float_scalar,\n                       assign_sub);\n  INSTALL_ASSIGNOP_TI (ti, op_mul_eq, octave_float_matrix, octave_float_scalar,\n                       assign_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_div_eq, octave_float_matrix, octave_float_scalar,\n                       assign_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fm-pm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define MINCLUDE \"ov-flt-re-mat.h\"\n\n#define LMATRIX float_matrix\n#define RMATRIX perm_matrix\n\n#define LSHORT fm\n#define RSHORT pm\n\n#define RIGHT\n\n#include \"op-pm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-fs-fcm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-fs-fcm.h\"\n#include \"mx-fcm-fs.h\"\n#include \"mx-fs-fcnda.h\"\n#include \"mx-fcnda-fs.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar by complex matrix ops.\n\nDEFNDBINOP_OP (add, float_scalar, float_complex_matrix, float_scalar,\n               float_complex_array, +)\nDEFNDBINOP_OP (sub, float_scalar, float_complex_matrix, float_scalar,\n               float_complex_array, -)\nDEFNDBINOP_OP (mul, float_scalar, float_complex_matrix, float_scalar,\n               float_complex_array, *)\n\nDEFBINOP (div, float_scalar, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n\n  FloatMatrix m1 = v1.float_matrix_value ();\n  FloatComplexMatrix m2 = v2.float_complex_matrix_value ();\n  MatrixType typ = v2.matrix_type ();\n\n  FloatComplexMatrix ret = xdiv (m1, m2, typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (pow, float_scalar, float_complex_matrix, xpow)\n\nDEFBINOP (ldiv, float_scalar, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n\n  return octave_value (v2.float_complex_array_value () / v1.float_value ());\n}\n\nDEFNDCMPLXCMPOP_FN (lt, float_scalar, float_complex_matrix, float_scalar,\n                    float_complex_array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, float_scalar, float_complex_matrix, float_scalar,\n                    float_complex_array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, float_scalar, float_complex_matrix, float_scalar,\n                    float_complex_array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, float_scalar, float_complex_matrix, float_scalar,\n                    float_complex_array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, float_scalar, float_complex_matrix, float_scalar,\n                    float_complex_array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, float_scalar, float_complex_matrix, float_scalar,\n                    float_complex_array, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, float_scalar, float_complex_matrix, float_scalar,\n               float_complex_array, *)\nDEFNDBINOP_FN (el_div, float_scalar, float_complex_matrix, float_scalar,\n               float_complex_array, elem_xdiv)\nDEFNDBINOP_FN (el_pow, float_scalar, float_complex_matrix, float_scalar,\n               float_complex_array, elem_xpow)\n\nDEFBINOP (el_ldiv, float_scalar, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);\n\n  return octave_value (v2.float_complex_array_value () / v1.float_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_scalar, float_complex_matrix, float_scalar,\n               float_complex_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_scalar, float_complex_matrix, float_scalar,\n               float_complex_array, mx_el_or)\n\nDEFNDCATOP_FN (fs_fcm, float_scalar, float_complex_matrix, float_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (s_fcm, scalar, float_complex_matrix, float_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (fs_cm, float_scalar, complex_matrix, float_array,\n               float_complex_array, concat)\n\nDEFCONV (float_complex_matrix_conv, float_scalar, float_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v, a);\n\n  return new octave_float_complex_matrix (FloatComplexMatrix\n                                          (v.float_matrix_value ()));\n}\n\nvoid\ninstall_fs_fcm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_scalar, octave_float_complex_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_scalar, octave_float_complex_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_scalar, octave_float_complex_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_scalar, octave_float_complex_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_scalar, octave_float_complex_matrix,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_scalar,\n                    octave_float_complex_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_scalar, octave_float_complex_matrix,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_scalar, octave_float_complex_matrix,\n                    le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_scalar, octave_float_complex_matrix,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_scalar, octave_float_complex_matrix,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_scalar, octave_float_complex_matrix,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_scalar, octave_float_complex_matrix,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_scalar,\n                    octave_float_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_scalar,\n                    octave_float_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_scalar,\n                    octave_float_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_scalar,\n                    octave_float_complex_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_scalar,\n                    octave_float_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_scalar,\n                    octave_float_complex_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_float_complex_matrix, fs_fcm);\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_float_complex_matrix, s_fcm);\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_complex_matrix, fs_cm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_float_complex_matrix,\n                         octave_float_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_float_complex_matrix,\n                         octave_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_float_scalar, octave_float_complex_matrix,\n                      float_complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fs-fcs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar by complex scalar ops.\n\nDEFBINOP_OP (add, float_scalar, float_complex, +)\nDEFBINOP_OP (sub, float_scalar, float_complex, -)\nDEFBINOP_OP (mul, float_scalar, float_complex, *)\n\nDEFBINOP (div, float_scalar, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_value () / v2.float_complex_value ());\n}\n\nDEFBINOP_FN (pow, float_scalar, float_complex, xpow)\n\nDEFBINOP (ldiv, float_scalar, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v2.float_complex_value () / v1.float_value ());\n}\n\nDEFCMPLXCMPOP_OP (lt, float_scalar, float_complex, <)\nDEFCMPLXCMPOP_OP (le, float_scalar, float_complex, <=)\nDEFCMPLXCMPOP_OP (eq, float_scalar, float_complex, ==)\nDEFCMPLXCMPOP_OP (ge, float_scalar, float_complex, >=)\nDEFCMPLXCMPOP_OP (gt, float_scalar, float_complex, >)\nDEFCMPLXCMPOP_OP (ne, float_scalar, float_complex, !=)\n\nDEFBINOP_OP (el_mul, float_scalar, float_complex, *)\n\nDEFBINOP (el_div, float_scalar, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_value () / v2.float_complex_value ());\n}\n\nDEFBINOP_FN (el_pow, float_scalar, float_complex, xpow)\n\nDEFBINOP (el_ldiv, float_scalar, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v2.float_complex_value () / v1.float_value ());\n}\n\nDEFBINOP (el_and, float_scalar, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_scalar_value ()\n                       && (v2.float_complex_value () != 0.0f));\n}\n\nDEFBINOP (el_or, float_scalar, float_complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);\n\n  return octave_value (v1.float_scalar_value ()\n                       || (v2.float_complex_value () != 0.0f));\n}\n\nDEFNDCATOP_FN (fs_fcs, float_scalar, float_complex, float_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (s_fcs, scalar, float_complex, float_array,\n               float_complex_array, concat)\n\nDEFNDCATOP_FN (fs_cs, float_scalar, complex, float_array,\n               float_complex_array, concat)\n\nvoid\ninstall_fs_fcs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_scalar, octave_float_complex, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_scalar, octave_float_complex, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_scalar, octave_float_complex, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_scalar, octave_float_complex, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_scalar, octave_float_complex, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_scalar, octave_float_complex, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_scalar, octave_float_complex, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_scalar, octave_float_complex, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_scalar, octave_float_complex, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_scalar, octave_float_complex, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_scalar, octave_float_complex, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_scalar, octave_float_complex, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_scalar, octave_float_complex,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_scalar, octave_float_complex,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_scalar, octave_float_complex,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_scalar, octave_float_complex,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_scalar, octave_float_complex,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_scalar, octave_float_complex,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_float_complex, fs_fcs);\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_float_complex, s_fcs);\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_complex, fs_cs);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_float_complex,\n                         octave_float_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_float_complex,\n                         octave_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fs-fm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar by matrix ops.\n\nDEFNDBINOP_OP (add, float_scalar, float_matrix, float_scalar, float_array, +)\nDEFNDBINOP_OP (sub, float_scalar, float_matrix, float_scalar, float_array, -)\nDEFNDBINOP_OP (mul, float_scalar, float_matrix, float_scalar, float_array, *)\n\nDEFBINOP (div, float_scalar, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n\n  FloatMatrix m1 = v1.float_matrix_value ();\n  FloatMatrix m2 = v2.float_matrix_value ();\n  MatrixType typ = v2.matrix_type ();\n\n  FloatMatrix ret = xdiv (m1, m2, typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (pow, float_scalar, float_matrix, xpow)\n\nDEFBINOP (ldiv, float_scalar, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n\n  return octave_value (v2.float_array_value () / v1.float_value ());\n}\n\nDEFNDBINOP_FN (lt, float_scalar, float_matrix, float_scalar,\n               float_array, mx_el_lt)\nDEFNDBINOP_FN (le, float_scalar, float_matrix, float_scalar,\n               float_array, mx_el_le)\nDEFNDBINOP_FN (eq, float_scalar, float_matrix, float_scalar,\n               float_array, mx_el_eq)\nDEFNDBINOP_FN (ge, float_scalar, float_matrix, float_scalar,\n               float_array, mx_el_ge)\nDEFNDBINOP_FN (gt, float_scalar, float_matrix, float_scalar,\n               float_array, mx_el_gt)\nDEFNDBINOP_FN (ne, float_scalar, float_matrix, float_scalar,\n               float_array, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, float_scalar, float_matrix, float_scalar,\n               float_array, *)\nDEFNDBINOP_FN (el_div, float_scalar, float_matrix, float_scalar,\n               float_array, elem_xdiv)\nDEFNDBINOP_FN (el_pow, float_scalar, float_matrix, float_scalar,\n               float_array, elem_xpow)\n\nDEFBINOP (el_ldiv, float_scalar, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);\n\n  return octave_value (v2.float_array_value () / v1.float_value ());\n}\n\nDEFNDBINOP_FN (el_and, float_scalar, float_matrix, float_scalar,\n               float_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  float_scalar, float_matrix, float_scalar,\n               float_array, mx_el_or)\n\nDEFNDCATOP_FN (fs_fm, float_scalar, float_matrix, float_array,\n               float_array, concat)\n\nDEFNDCATOP_FN (s_fm, scalar, float_matrix, float_array, float_array, concat)\n\nDEFNDCATOP_FN (fs_m, float_scalar, matrix, float_array, float_array, concat)\n\nDEFCONV (matrix_conv, float_scalar, float_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v, a);\n\n  return new octave_float_matrix (v.float_matrix_value ());\n}\n\nvoid\ninstall_fs_fm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_float_scalar, octave_float_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_scalar, octave_float_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_scalar, octave_float_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_scalar, octave_float_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_scalar, octave_float_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_scalar, octave_float_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_scalar, octave_float_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_scalar, octave_float_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_scalar, octave_float_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_scalar, octave_float_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_scalar, octave_float_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_scalar, octave_float_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_scalar, octave_float_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_scalar, octave_float_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_scalar, octave_float_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_scalar, octave_float_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_scalar, octave_float_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_scalar, octave_float_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_float_matrix, fs_fm);\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_float_matrix, s_fm);\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_matrix, fs_m);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_float_matrix,\n                         octave_float_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_float_matrix, octave_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_float_scalar, octave_float_matrix, matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-fs-fs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-util.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar unary ops.\n\nDEFUNOP (not, float_scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v, a);\n  float x = v.float_value ();\n  if (octave::math::isnan (x))\n    octave::err_nan_to_logical_conversion ();\n\n  return octave_value (x == 0.0f);\n}\n\nDEFUNOP_OP (uplus, float_scalar, /* no-op */)\nDEFUNOP_OP (uminus, float_scalar, -)\nDEFUNOP_OP (transpose, float_scalar, /* no-op */)\nDEFUNOP_OP (hermitian, float_scalar, /* no-op */)\n\nDEFNCUNOP_METHOD (incr, float_scalar, increment)\nDEFNCUNOP_METHOD (decr, float_scalar, decrement)\n\n// float by float ops.\n\nDEFBINOP_OP (add, float_scalar, float_scalar, +)\nDEFBINOP_OP (sub, float_scalar, float_scalar, -)\nDEFBINOP_OP (mul, float_scalar, float_scalar, *)\n\nDEFBINOP (div, float_scalar, float_scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v1.float_value () / v2.float_value ());\n}\n\nDEFBINOP_FN (pow, float_scalar, float_scalar, xpow)\n\nDEFBINOP (ldiv, float_scalar, float_scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v2.float_value () / v1.float_value ());\n}\n\nDEFBINOP_OP (lt, float_scalar, float_scalar, <)\nDEFBINOP_OP (le, float_scalar, float_scalar, <=)\nDEFBINOP_OP (eq, float_scalar, float_scalar, ==)\nDEFBINOP_OP (ge, float_scalar, float_scalar, >=)\nDEFBINOP_OP (gt, float_scalar, float_scalar, >)\nDEFBINOP_OP (ne, float_scalar, float_scalar, !=)\n\nDEFBINOP_OP (el_mul, float_scalar, float_scalar, *)\n\nDEFBINOP (el_div, float_scalar, float_scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v1.float_value () / v2.float_value ());\n}\n\nDEFBINOP_FN (el_pow, float_scalar, float_scalar, xpow)\n\nDEFBINOP (el_ldiv, float_scalar, float_scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);\n\n  return octave_value (v2.float_value () / v1.float_value ());\n}\n\nDEFSCALARBOOLOP_OP (el_and, float_scalar, float_scalar, &&)\nDEFSCALARBOOLOP_OP (el_or, float_scalar, float_scalar, ||)\n\nDEFNDCATOP_FN (fs_fs, float_scalar, float_scalar, float_array, float_array,\n               concat)\nDEFNDCATOP_FN (s_fs, scalar, float_scalar, float_array, float_array, concat)\nDEFNDCATOP_FN (fs_s, float_scalar, scalar, float_array, float_array, concat)\n\nvoid\ninstall_fs_fs_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_float_scalar, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_float_scalar, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_float_scalar, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_float_scalar, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_float_scalar, hermitian);\n\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_float_scalar, incr);\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_float_scalar, decr);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_float_scalar, octave_float_scalar, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_float_scalar, octave_float_scalar, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_float_scalar, octave_float_scalar, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_float_scalar, octave_float_scalar, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_float_scalar, octave_float_scalar, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_float_scalar, octave_float_scalar, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_float_scalar, octave_float_scalar, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_float_scalar, octave_float_scalar, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_float_scalar, octave_float_scalar, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_float_scalar, octave_float_scalar, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_float_scalar, octave_float_scalar, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_float_scalar, octave_float_scalar, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_float_scalar, octave_float_scalar,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_float_scalar, octave_float_scalar,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_float_scalar, octave_float_scalar,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_float_scalar, octave_float_scalar,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_float_scalar, octave_float_scalar,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_float_scalar, octave_float_scalar,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_float_scalar, fs_fs);\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_float_scalar, s_fs);\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_scalar, fs_s);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_float_scalar,\n                         octave_float_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_float_scalar, octave_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_null_matrix,\n                         octave_float_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_null_str,\n                         octave_float_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_null_sq_str,\n                         octave_float_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-i16-i16.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-i16nda-i8.h\"\n#include \"mx-i16nda-ui8.h\"\n#include \"mx-i16nda-ui16.h\"\n#include \"mx-i16nda-i32.h\"\n#include \"mx-i16nda-ui32.h\"\n#include \"mx-i16nda-i64.h\"\n#include \"mx-i16nda-ui64.h\"\n\n#include \"mx-i16nda-i8nda.h\"\n#include \"mx-i16nda-ui8nda.h\"\n#include \"mx-i16nda-ui16nda.h\"\n#include \"mx-i16nda-i32nda.h\"\n#include \"mx-i16nda-ui32nda.h\"\n#include \"mx-i16nda-i64nda.h\"\n#include \"mx-i16nda-ui64nda.h\"\n\n#include \"mx-i16-i8nda.h\"\n#include \"mx-i16-ui8nda.h\"\n#include \"mx-i16-ui16nda.h\"\n#include \"mx-i16-i32nda.h\"\n#include \"mx-i16-ui32nda.h\"\n#include \"mx-i16-i64nda.h\"\n#include \"mx-i16-ui64nda.h\"\n\n#include \"mx-i16nda-s.h\"\n#include \"mx-s-i16nda.h\"\n\n#include \"mx-i16nda-nda.h\"\n#include \"mx-nda-i16nda.h\"\n\n#include \"mx-i16-nda.h\"\n#include \"mx-nda-i16.h\"\n\n#include \"mx-i16nda-fs.h\"\n#include \"mx-fs-i16nda.h\"\n\n#include \"mx-i16nda-fnda.h\"\n#include \"mx-fnda-i16nda.h\"\n\n#include \"mx-i16-fnda.h\"\n#include \"mx-fnda-i16.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\n#include \"op-int.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_INT_OPS (int16)\n\nOCTAVE_MS_INT_ASSIGN_OPS (mi8, int16_, int8_, int8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui8, int16_, uint8_, uint8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui16, int16_, uint16_, uint16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi32, int16_, int32_, int32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui32, int16_, uint32_, uint32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi64, int16_, int64_, int64_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui64, int16_, uint64_, uint64_)\n\nOCTAVE_MM_INT_ASSIGN_OPS (mmi8, int16_, int8_, int8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui8, int16_, uint8_, uint8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui16, int16_, uint16_, uint16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi32, int16_, int32_, int32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui32, int16_, uint32_, uint32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi64, int16_, int64_, int64_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui64, int16_, uint64_, uint64_)\n\nOCTAVE_MIXED_INT_CMP_OPS (int16, int8)\nOCTAVE_MIXED_INT_CMP_OPS (int16, uint8)\nOCTAVE_MIXED_INT_CMP_OPS (int16, uint16)\nOCTAVE_MIXED_INT_CMP_OPS (int16, int32)\nOCTAVE_MIXED_INT_CMP_OPS (int16, uint32)\nOCTAVE_MIXED_INT_CMP_OPS (int16, int64)\nOCTAVE_MIXED_INT_CMP_OPS (int16, uint64)\n\nvoid\ninstall_i16_i16_ops (octave::type_info& ti)\n{\n  OCTAVE_INSTALL_INT_OPS (int16);\n\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi8, int16_, int8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui8, int16_, uint8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui16, int16_, uint16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi32, int16_, int32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui32, int16_, uint32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi64, int16_, int64_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui64, int16_, uint64_);\n\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi8, int16_, int8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui8, int16_, uint8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui16, int16_, uint16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi32, int16_, int32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui32, int16_, uint32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi64, int16_, int64_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui64, int16_, uint64_);\n\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int16, int8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int16, uint8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int16, uint16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int16, int32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int16, uint32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int16, int64);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int16, uint64);\n\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int16, int8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int16, uint8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int16, uint16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int16, int32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int16, uint32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int16, int64);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int16, uint64);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-i32-i32.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-i32nda-i8.h\"\n#include \"mx-i32nda-ui8.h\"\n#include \"mx-i32nda-i16.h\"\n#include \"mx-i32nda-ui16.h\"\n#include \"mx-i32nda-ui32.h\"\n#include \"mx-i32nda-i64.h\"\n#include \"mx-i32nda-ui64.h\"\n\n#include \"mx-i32nda-i8nda.h\"\n#include \"mx-i32nda-ui8nda.h\"\n#include \"mx-i32nda-i16nda.h\"\n#include \"mx-i32nda-ui16nda.h\"\n#include \"mx-i32nda-ui32nda.h\"\n#include \"mx-i32nda-i64nda.h\"\n#include \"mx-i32nda-ui64nda.h\"\n\n#include \"mx-i32-i8nda.h\"\n#include \"mx-i32-ui8nda.h\"\n#include \"mx-i32-i16nda.h\"\n#include \"mx-i32-ui16nda.h\"\n#include \"mx-i32-ui32nda.h\"\n#include \"mx-i32-i64nda.h\"\n#include \"mx-i32-ui64nda.h\"\n\n#include \"mx-i32nda-s.h\"\n#include \"mx-s-i32nda.h\"\n\n#include \"mx-i32nda-nda.h\"\n#include \"mx-nda-i32nda.h\"\n\n#include \"mx-i32-nda.h\"\n#include \"mx-nda-i32.h\"\n\n#include \"mx-i32nda-fs.h\"\n#include \"mx-fs-i32nda.h\"\n\n#include \"mx-i32nda-fnda.h\"\n#include \"mx-fnda-i32nda.h\"\n\n#include \"mx-i32-fnda.h\"\n#include \"mx-fnda-i32.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\n#include \"op-int.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_INT_OPS (int32)\n\nOCTAVE_MS_INT_ASSIGN_OPS (mi8, int32_, int8_, int8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui8, int32_, uint8_, uint8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi16, int32_, int16_, int16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui16, int32_, uint16_, uint16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui32, int32_, uint32_, uint32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi64, int32_, int64_, int64_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui64, int32_, uint64_, uint64_)\n\nOCTAVE_MM_INT_ASSIGN_OPS (mmi8, int32_, int8_, int8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui8, int32_, uint8_, uint8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi16, int32_, int16_, int16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui16, int32_, uint16_, uint16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui32, int32_, uint32_, uint32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi64, int32_, int64_, int64_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui64, int32_, uint64_, uint64_)\n\nOCTAVE_MIXED_INT_CMP_OPS (int32, int8)\nOCTAVE_MIXED_INT_CMP_OPS (int32, uint8)\nOCTAVE_MIXED_INT_CMP_OPS (int32, int16)\nOCTAVE_MIXED_INT_CMP_OPS (int32, uint16)\nOCTAVE_MIXED_INT_CMP_OPS (int32, uint32)\nOCTAVE_MIXED_INT_CMP_OPS (int32, int64)\nOCTAVE_MIXED_INT_CMP_OPS (int32, uint64)\n\nvoid\ninstall_i32_i32_ops (octave::type_info& ti)\n{\n  OCTAVE_INSTALL_INT_OPS (int32);\n\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi8, int32_, int8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui8, int32_, uint8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi16, int32_, int16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui16, int32_, uint16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui32, int32_, uint32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi64, int32_, int64_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui64, int32_, uint64_);\n\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi8, int32_, int8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui8, int32_, uint8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi16, int32_, int16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui16, int32_, uint16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui32, int32_, uint32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi64, int32_, int64_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui64, int32_, uint64_);\n\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int32, int8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int32, uint8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int32, int16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int32, uint16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int32, uint32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int32, int64);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int32, uint64);\n\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int32, int8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int32, uint8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int32, int16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int32, uint16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int32, uint32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int32, int64);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int32, uint64);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-i64-i64.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-i64nda-i8.h\"\n#include \"mx-i64nda-ui8.h\"\n#include \"mx-i64nda-i16.h\"\n#include \"mx-i64nda-ui16.h\"\n#include \"mx-i64nda-i32.h\"\n#include \"mx-i64nda-ui32.h\"\n#include \"mx-i64nda-ui64.h\"\n\n#include \"mx-i64nda-i8nda.h\"\n#include \"mx-i64nda-ui8nda.h\"\n#include \"mx-i64nda-i16nda.h\"\n#include \"mx-i64nda-ui16nda.h\"\n#include \"mx-i64nda-i32nda.h\"\n#include \"mx-i64nda-ui32nda.h\"\n#include \"mx-i64nda-ui64nda.h\"\n\n#include \"mx-i64-i8nda.h\"\n#include \"mx-i64-ui8nda.h\"\n#include \"mx-i64-i16nda.h\"\n#include \"mx-i64-ui16nda.h\"\n#include \"mx-i64-i32nda.h\"\n#include \"mx-i64-ui32nda.h\"\n#include \"mx-i64-ui64nda.h\"\n\n#include \"mx-i64nda-s.h\"\n#include \"mx-s-i64nda.h\"\n\n#include \"mx-i64nda-nda.h\"\n#include \"mx-nda-i64nda.h\"\n\n#include \"mx-i64-nda.h\"\n#include \"mx-nda-i64.h\"\n\n#include \"mx-i64nda-fs.h\"\n#include \"mx-fs-i64nda.h\"\n\n#include \"mx-i64nda-fnda.h\"\n#include \"mx-fnda-i64nda.h\"\n\n#include \"mx-i64-fnda.h\"\n#include \"mx-fnda-i64.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\n#include \"op-int.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_INT_OPS (int64)\n\nOCTAVE_MS_INT_ASSIGN_OPS (mi8, int64_, int8_, int8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui8, int64_, uint8_, uint8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi16, int64_, int16_, int16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui16, int64_, uint16_, uint16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi32, int64_, int32_, int32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui32, int64_, uint32_, uint32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui64, int64_, uint64_, uint64_)\n\nOCTAVE_MM_INT_ASSIGN_OPS (mmi8, int64_, int8_, int8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui8, int64_, uint8_, uint8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi16, int64_, int16_, int16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui16, int64_, uint16_, uint16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi32, int64_, int32_, int32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui32, int64_, uint32_, uint32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui64, int64_, uint64_, uint64_)\n\nOCTAVE_MIXED_INT_CMP_OPS (int64, int8)\nOCTAVE_MIXED_INT_CMP_OPS (int64, uint8)\nOCTAVE_MIXED_INT_CMP_OPS (int64, int16)\nOCTAVE_MIXED_INT_CMP_OPS (int64, uint16)\nOCTAVE_MIXED_INT_CMP_OPS (int64, int32)\nOCTAVE_MIXED_INT_CMP_OPS (int64, uint32)\nOCTAVE_MIXED_INT_CMP_OPS (int64, uint64)\n\nvoid\ninstall_i64_i64_ops (octave::type_info& ti)\n{\n  OCTAVE_INSTALL_INT_OPS (int64);\n\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi8, int64_, int8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui8, int64_, uint8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi16, int64_, int16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui16, int64_, uint16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi32, int64_, int32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui32, int64_, uint32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui64, int64_, uint64_);\n\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi8, int64_, int8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui8, int64_, uint8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi16, int64_, int16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui16, int64_, uint16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi32, int64_, int32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui32, int64_, uint32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui64, int64_, uint64_);\n\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, int8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, uint8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, int16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, uint16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, int32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, uint32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, uint64);\n\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, int8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, uint8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, int16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, uint16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, int32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, uint32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, uint64);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-i8-i8.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-i8nda-ui8.h\"\n#include \"mx-i8nda-i16.h\"\n#include \"mx-i8nda-ui16.h\"\n#include \"mx-i8nda-i32.h\"\n#include \"mx-i8nda-ui32.h\"\n#include \"mx-i8nda-i64.h\"\n#include \"mx-i8nda-ui64.h\"\n\n#include \"mx-i8nda-ui8nda.h\"\n#include \"mx-i8nda-i16nda.h\"\n#include \"mx-i8nda-ui16nda.h\"\n#include \"mx-i8nda-i32nda.h\"\n#include \"mx-i8nda-ui32nda.h\"\n#include \"mx-i8nda-i64nda.h\"\n#include \"mx-i8nda-ui64nda.h\"\n\n#include \"mx-i8-ui8nda.h\"\n#include \"mx-i8-i16nda.h\"\n#include \"mx-i8-ui16nda.h\"\n#include \"mx-i8-i32nda.h\"\n#include \"mx-i8-ui32nda.h\"\n#include \"mx-i8-i64nda.h\"\n#include \"mx-i8-ui64nda.h\"\n\n#include \"mx-i8nda-s.h\"\n#include \"mx-s-i8nda.h\"\n\n#include \"mx-i8nda-nda.h\"\n#include \"mx-nda-i8nda.h\"\n\n#include \"mx-i8-nda.h\"\n#include \"mx-nda-i8.h\"\n\n#include \"mx-i8nda-fs.h\"\n#include \"mx-fs-i8nda.h\"\n\n#include \"mx-i8nda-fnda.h\"\n#include \"mx-fnda-i8nda.h\"\n\n#include \"mx-i8-fnda.h\"\n#include \"mx-fnda-i8.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\n#include \"op-int.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_INT_OPS (int8)\n\nOCTAVE_MS_INT_ASSIGN_OPS (mui8, int8_, uint8_, uint8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi16, int8_, int16_, int16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui16, int8_, uint16_, uint16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi32, int8_, int32_, int32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui32, int8_, uint32_, uint32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi64, int8_, int64_, int64_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui64, int8_, uint64_, uint64_)\n\nOCTAVE_MM_INT_ASSIGN_OPS (mmui8, int8_, uint8_, uint8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi16, int8_, int16_, int16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui16, int8_, uint16_, uint16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi32, int8_, int32_, int32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui32, int8_, uint32_, uint32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi64, int8_, int64_, int64_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui64, int8_, uint64_, uint64_)\n\nOCTAVE_MIXED_INT_CMP_OPS (int8, uint8)\nOCTAVE_MIXED_INT_CMP_OPS (int8, int16)\nOCTAVE_MIXED_INT_CMP_OPS (int8, uint16)\nOCTAVE_MIXED_INT_CMP_OPS (int8, int32)\nOCTAVE_MIXED_INT_CMP_OPS (int8, uint32)\nOCTAVE_MIXED_INT_CMP_OPS (int8, int64)\nOCTAVE_MIXED_INT_CMP_OPS (int8, uint64)\n\nvoid\ninstall_i8_i8_ops (octave::type_info& ti)\n{\n  OCTAVE_INSTALL_INT_OPS (int8);\n\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui8, int8_, uint8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi16, int8_, int16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui16, int8_, uint16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi32, int8_, int32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui32, int8_, uint32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi64, int8_, int64_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui64, int8_, uint64_);\n\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui8, int8_, uint8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi16, int8_, int16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui16, int8_, uint16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi32, int8_, int32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui32, int8_, uint32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi64, int8_, int64_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui64, int8_, uint64_);\n\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int8, uint8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int8, int16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int8, uint16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int8, int32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int8, uint32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int8, int64);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int8, uint64);\n\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int8, uint8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int8, int16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int8, uint16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int8, int32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int8, uint32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int8, int64);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int8, uint64);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-int-concat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-int8.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-range.h\"\n#include \"ov-bool.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-str-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"op-int.h\"\n#include \"ops.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Concatenation of mixed integer types:\n\nOCTAVE_CONCAT_FN2 (int8, int16)\nOCTAVE_CONCAT_FN2 (int8, int32)\nOCTAVE_CONCAT_FN2 (int8, int64)\n\nOCTAVE_CONCAT_FN2 (int8, uint8)\nOCTAVE_CONCAT_FN2 (int8, uint16)\nOCTAVE_CONCAT_FN2 (int8, uint32)\nOCTAVE_CONCAT_FN2 (int8, uint64)\n\nOCTAVE_CONCAT_FN2 (int16, int8)\nOCTAVE_CONCAT_FN2 (int16, int32)\nOCTAVE_CONCAT_FN2 (int16, int64)\n\nOCTAVE_CONCAT_FN2 (int16, uint8)\nOCTAVE_CONCAT_FN2 (int16, uint16)\nOCTAVE_CONCAT_FN2 (int16, uint32)\nOCTAVE_CONCAT_FN2 (int16, uint64)\n\nOCTAVE_CONCAT_FN2 (int32, int8)\nOCTAVE_CONCAT_FN2 (int32, int16)\nOCTAVE_CONCAT_FN2 (int32, int64)\n\nOCTAVE_CONCAT_FN2 (int32, uint8)\nOCTAVE_CONCAT_FN2 (int32, uint16)\nOCTAVE_CONCAT_FN2 (int32, uint32)\nOCTAVE_CONCAT_FN2 (int32, uint64)\n\nOCTAVE_CONCAT_FN2 (int64, int8)\nOCTAVE_CONCAT_FN2 (int64, int16)\nOCTAVE_CONCAT_FN2 (int64, int32)\n\nOCTAVE_CONCAT_FN2 (int64, uint8)\nOCTAVE_CONCAT_FN2 (int64, uint16)\nOCTAVE_CONCAT_FN2 (int64, uint32)\nOCTAVE_CONCAT_FN2 (int64, uint64)\n\nOCTAVE_CONCAT_FN2 (uint8, int8)\nOCTAVE_CONCAT_FN2 (uint8, int16)\nOCTAVE_CONCAT_FN2 (uint8, int32)\nOCTAVE_CONCAT_FN2 (uint8, int64)\n\nOCTAVE_CONCAT_FN2 (uint8, uint16)\nOCTAVE_CONCAT_FN2 (uint8, uint32)\nOCTAVE_CONCAT_FN2 (uint8, uint64)\n\nOCTAVE_CONCAT_FN2 (uint16, int8)\nOCTAVE_CONCAT_FN2 (uint16, int16)\nOCTAVE_CONCAT_FN2 (uint16, int32)\nOCTAVE_CONCAT_FN2 (uint16, int64)\n\nOCTAVE_CONCAT_FN2 (uint16, uint8)\nOCTAVE_CONCAT_FN2 (uint16, uint32)\nOCTAVE_CONCAT_FN2 (uint16, uint64)\n\nOCTAVE_CONCAT_FN2 (uint32, int8)\nOCTAVE_CONCAT_FN2 (uint32, int16)\nOCTAVE_CONCAT_FN2 (uint32, int32)\nOCTAVE_CONCAT_FN2 (uint32, int64)\n\nOCTAVE_CONCAT_FN2 (uint32, uint8)\nOCTAVE_CONCAT_FN2 (uint32, uint16)\nOCTAVE_CONCAT_FN2 (uint32, uint64)\n\nOCTAVE_CONCAT_FN2 (uint64, int8)\nOCTAVE_CONCAT_FN2 (uint64, int16)\nOCTAVE_CONCAT_FN2 (uint64, int32)\nOCTAVE_CONCAT_FN2 (uint64, int64)\n\nOCTAVE_CONCAT_FN2 (uint64, uint8)\nOCTAVE_CONCAT_FN2 (uint64, uint16)\nOCTAVE_CONCAT_FN2 (uint64, uint32)\n\nOCTAVE_INT_DOUBLE_CONCAT_FN (int8)\nOCTAVE_INT_DOUBLE_CONCAT_FN (int16)\nOCTAVE_INT_DOUBLE_CONCAT_FN (int32)\nOCTAVE_INT_DOUBLE_CONCAT_FN (int64)\n\nOCTAVE_INT_DOUBLE_CONCAT_FN (uint8)\nOCTAVE_INT_DOUBLE_CONCAT_FN (uint16)\nOCTAVE_INT_DOUBLE_CONCAT_FN (uint32)\nOCTAVE_INT_DOUBLE_CONCAT_FN (uint64)\n\nOCTAVE_DOUBLE_INT_CONCAT_FN (int8)\nOCTAVE_DOUBLE_INT_CONCAT_FN (int16)\nOCTAVE_DOUBLE_INT_CONCAT_FN (int32)\nOCTAVE_DOUBLE_INT_CONCAT_FN (int64)\n\nOCTAVE_DOUBLE_INT_CONCAT_FN (uint8)\nOCTAVE_DOUBLE_INT_CONCAT_FN (uint16)\nOCTAVE_DOUBLE_INT_CONCAT_FN (uint32)\nOCTAVE_DOUBLE_INT_CONCAT_FN (uint64)\n\nOCTAVE_INT_FLOAT_CONCAT_FN (int8)\nOCTAVE_INT_FLOAT_CONCAT_FN (int16)\nOCTAVE_INT_FLOAT_CONCAT_FN (int32)\nOCTAVE_INT_FLOAT_CONCAT_FN (int64)\n\nOCTAVE_INT_FLOAT_CONCAT_FN (uint8)\nOCTAVE_INT_FLOAT_CONCAT_FN (uint16)\nOCTAVE_INT_FLOAT_CONCAT_FN (uint32)\nOCTAVE_INT_FLOAT_CONCAT_FN (uint64)\n\nOCTAVE_FLOAT_INT_CONCAT_FN (int8)\nOCTAVE_FLOAT_INT_CONCAT_FN (int16)\nOCTAVE_FLOAT_INT_CONCAT_FN (int32)\nOCTAVE_FLOAT_INT_CONCAT_FN (int64)\n\nOCTAVE_FLOAT_INT_CONCAT_FN (uint8)\nOCTAVE_FLOAT_INT_CONCAT_FN (uint16)\nOCTAVE_FLOAT_INT_CONCAT_FN (uint32)\nOCTAVE_FLOAT_INT_CONCAT_FN (uint64)\n\nOCTAVE_INT_CHAR_CONCAT_FN (int8)\nOCTAVE_INT_CHAR_CONCAT_FN (int16)\nOCTAVE_INT_CHAR_CONCAT_FN (int32)\nOCTAVE_INT_CHAR_CONCAT_FN (int64)\n\nOCTAVE_INT_CHAR_CONCAT_FN (uint8)\nOCTAVE_INT_CHAR_CONCAT_FN (uint16)\nOCTAVE_INT_CHAR_CONCAT_FN (uint32)\nOCTAVE_INT_CHAR_CONCAT_FN (uint64)\n\nOCTAVE_CHAR_INT_CONCAT_FN (int8)\nOCTAVE_CHAR_INT_CONCAT_FN (int16)\nOCTAVE_CHAR_INT_CONCAT_FN (int32)\nOCTAVE_CHAR_INT_CONCAT_FN (int64)\n\nOCTAVE_CHAR_INT_CONCAT_FN (uint8)\nOCTAVE_CHAR_INT_CONCAT_FN (uint16)\nOCTAVE_CHAR_INT_CONCAT_FN (uint32)\nOCTAVE_CHAR_INT_CONCAT_FN (uint64)\n\nvoid\ninstall_int_concat_ops (octave::type_info& ti)\n{\n  OCTAVE_INSTALL_CONCAT_FN2 (int8, int16);\n  OCTAVE_INSTALL_CONCAT_FN2 (int8, int32);\n  OCTAVE_INSTALL_CONCAT_FN2 (int8, int64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (int8, uint8);\n  OCTAVE_INSTALL_CONCAT_FN2 (int8, uint16);\n  OCTAVE_INSTALL_CONCAT_FN2 (int8, uint32);\n  OCTAVE_INSTALL_CONCAT_FN2 (int8, uint64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (int16, int8);\n  OCTAVE_INSTALL_CONCAT_FN2 (int16, int32);\n  OCTAVE_INSTALL_CONCAT_FN2 (int16, int64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (int16, uint8);\n  OCTAVE_INSTALL_CONCAT_FN2 (int16, uint16);\n  OCTAVE_INSTALL_CONCAT_FN2 (int16, uint32);\n  OCTAVE_INSTALL_CONCAT_FN2 (int16, uint64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (int32, int8);\n  OCTAVE_INSTALL_CONCAT_FN2 (int32, int16);\n  OCTAVE_INSTALL_CONCAT_FN2 (int32, int64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (int32, uint8);\n  OCTAVE_INSTALL_CONCAT_FN2 (int32, uint16);\n  OCTAVE_INSTALL_CONCAT_FN2 (int32, uint32);\n  OCTAVE_INSTALL_CONCAT_FN2 (int32, uint64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (int64, int8);\n  OCTAVE_INSTALL_CONCAT_FN2 (int64, int16);\n  OCTAVE_INSTALL_CONCAT_FN2 (int64, int32);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (int64, uint8);\n  OCTAVE_INSTALL_CONCAT_FN2 (int64, uint16);\n  OCTAVE_INSTALL_CONCAT_FN2 (int64, uint32);\n  OCTAVE_INSTALL_CONCAT_FN2 (int64, uint64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (uint8, int8);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint8, int16);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint8, int32);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint8, int64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (uint8, uint16);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint8, uint32);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint8, uint64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (uint16, int8);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint16, int16);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint16, int32);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint16, int64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (uint16, uint8);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint16, uint32);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint16, uint64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (uint32, int8);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint32, int16);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint32, int32);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint32, int64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (uint32, uint8);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint32, uint16);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint32, uint64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (uint64, int8);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint64, int16);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint64, int32);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint64, int64);\n\n  OCTAVE_INSTALL_CONCAT_FN2 (uint64, uint8);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint64, uint16);\n  OCTAVE_INSTALL_CONCAT_FN2 (uint64, uint32);\n\n  OCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN (int8);\n  OCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN (int16);\n  OCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN (int32);\n  OCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN (int64);\n\n  OCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN (uint8);\n  OCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN (uint16);\n  OCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN (uint32);\n  OCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN (uint64);\n\n  OCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN (int8);\n  OCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN (int16);\n  OCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN (int32);\n  OCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN (int64);\n\n  OCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN (uint8);\n  OCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN (uint16);\n  OCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN (uint32);\n  OCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN (uint64);\n\n  OCTAVE_INSTALL_INT_FLOAT_CONCAT_FN (int8);\n  OCTAVE_INSTALL_INT_FLOAT_CONCAT_FN (int16);\n  OCTAVE_INSTALL_INT_FLOAT_CONCAT_FN (int32);\n  OCTAVE_INSTALL_INT_FLOAT_CONCAT_FN (int64);\n\n  OCTAVE_INSTALL_INT_FLOAT_CONCAT_FN (uint8);\n  OCTAVE_INSTALL_INT_FLOAT_CONCAT_FN (uint16);\n  OCTAVE_INSTALL_INT_FLOAT_CONCAT_FN (uint32);\n  OCTAVE_INSTALL_INT_FLOAT_CONCAT_FN (uint64);\n\n  OCTAVE_INSTALL_FLOAT_INT_CONCAT_FN (int8);\n  OCTAVE_INSTALL_FLOAT_INT_CONCAT_FN (int16);\n  OCTAVE_INSTALL_FLOAT_INT_CONCAT_FN (int32);\n  OCTAVE_INSTALL_FLOAT_INT_CONCAT_FN (int64);\n\n  OCTAVE_INSTALL_FLOAT_INT_CONCAT_FN (uint8);\n  OCTAVE_INSTALL_FLOAT_INT_CONCAT_FN (uint16);\n  OCTAVE_INSTALL_FLOAT_INT_CONCAT_FN (uint32);\n  OCTAVE_INSTALL_FLOAT_INT_CONCAT_FN (uint64);\n\n  OCTAVE_INSTALL_INT_CHAR_CONCAT_FN (int8);\n  OCTAVE_INSTALL_INT_CHAR_CONCAT_FN (int16);\n  OCTAVE_INSTALL_INT_CHAR_CONCAT_FN (int32);\n  OCTAVE_INSTALL_INT_CHAR_CONCAT_FN (int64);\n\n  OCTAVE_INSTALL_INT_CHAR_CONCAT_FN (uint8);\n  OCTAVE_INSTALL_INT_CHAR_CONCAT_FN (uint16);\n  OCTAVE_INSTALL_INT_CHAR_CONCAT_FN (uint32);\n  OCTAVE_INSTALL_INT_CHAR_CONCAT_FN (uint64);\n\n  OCTAVE_INSTALL_CHAR_INT_CONCAT_FN (int8);\n  OCTAVE_INSTALL_CHAR_INT_CONCAT_FN (int16);\n  OCTAVE_INSTALL_CHAR_INT_CONCAT_FN (int32);\n  OCTAVE_INSTALL_CHAR_INT_CONCAT_FN (int64);\n\n  OCTAVE_INSTALL_CHAR_INT_CONCAT_FN (uint8);\n  OCTAVE_INSTALL_CHAR_INT_CONCAT_FN (uint16);\n  OCTAVE_INSTALL_CHAR_INT_CONCAT_FN (uint32);\n  OCTAVE_INSTALL_CHAR_INT_CONCAT_FN (uint64);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-int.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_op_int_h)\n#define octave_op_int_h 1\n\n#include \"octave-config.h\"\n\n#include \"quit.h\"\n#include \"bsxfun.h\"\n\n#define DEFINTBINOP_OP(name, t1, t2, op, t3)                            \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \\\n    octave_value retval = octave_value                                  \\\n      (v1.t1 ## _value () op v2.t2 ## _value ());                       \\\n    return retval;                                                      \\\n  }\n\n#define DEFINTNDBINOP_OP(name, t1, t2, e1, e2, op, t3)                  \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \\\n    octave_value retval = octave_value                                  \\\n      (v1.e1 ## _value () op v2.e2 ## _value ());                       \\\n    return retval;                                                      \\\n  }\n\n#define DEFINTBINOP_FN(name, t1, t2, f, t3, op)                         \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \\\n    octave_value retval = octave_value (f (v1.t1 ## _value (), v2.t2 ## _value ())); \\\n    return retval;                                                      \\\n  }\n\n#define DEFINTNDBINOP_FN(name, t1, t2, e1, e2, f, t3, op)               \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \\\n    octave_value retval = octave_value (f (v1.e1 ## _value (), v2.e2 ## _value ())); \\\n    return retval;                                                      \\\n  }\n\n#define OCTAVE_CONCAT_FN2(T1, T2)                                       \\\n  DEFNDCATOP_FN2 (T1 ## _ ## T2 ## _s_s, T1 ## _scalar, T2 ## _scalar, , T1 ## NDArray, T1 ## _array, T2 ## _array, concat) \\\n  DEFNDCATOP_FN2 (T1 ## _ ## T2 ## _s_m, T1 ## _scalar, T2 ## _matrix, , T1 ## NDArray, T1 ## _array, T2 ## _array, concat) \\\n  DEFNDCATOP_FN2 (T1 ## _ ## T2 ## _m_s, T1 ## _matrix, T2 ## _scalar, , T1 ## NDArray, T1 ## _array, T2 ## _array, concat) \\\n  DEFNDCATOP_FN2 (T1 ## _ ## T2 ## _m_m, T1 ## _matrix, T2 ## _matrix, , T1 ## NDArray, T1 ## _array, T2 ## _array, concat)\n\n#define OCTAVE_INSTALL_CONCAT_FN2(T1, T2)                               \\\n  INSTALL_CATOP_TI (ti, octave_ ## T1 ## _scalar, octave_ ## T2 ## _scalar, T1 ## _ ## T2 ## _s_s) \\\n  INSTALL_CATOP_TI (ti, octave_ ## T1 ## _scalar, octave_ ## T2 ## _matrix, T1 ## _ ## T2 ## _s_m) \\\n  INSTALL_CATOP_TI (ti, octave_ ## T1 ## _matrix, octave_ ## T2 ## _scalar, T1 ## _ ## T2 ## _m_s) \\\n  INSTALL_CATOP_TI (ti, octave_ ## T1 ## _matrix, octave_ ## T2 ## _matrix, T1 ## _ ## T2 ## _m_m)\n\n#define OCTAVE_DOUBLE_INT_CONCAT_FN(TYPE)                               \\\n  DEFNDCATOP_FN2 (double ## _ ## TYPE ## _s_s, scalar, TYPE ## _scalar, TYPE ## NDArray, , array, TYPE ## _array, concat) \\\n  DEFNDCATOP_FN2 (double ## _ ## TYPE ## _s_m, scalar, TYPE ## _matrix, TYPE ## NDArray, , array, TYPE ## _array, concat) \\\n  DEFNDCATOP_FN2 (double ## _ ## TYPE ## _m_s, matrix, TYPE ## _scalar, TYPE ## NDArray, , array, TYPE ## _array, concat) \\\n  DEFNDCATOP_FN2 (double ## _ ## TYPE ## _m_m, matrix, TYPE ## _matrix, TYPE ## NDArray, , array, TYPE ## _array, concat)\n\n#define OCTAVE_INSTALL_DOUBLE_INT_CONCAT_FN(TYPE)                       \\\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_ ## TYPE ## _scalar, double ## _ ## TYPE ## _s_s) \\\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_ ## TYPE ## _matrix, double ## _ ## TYPE ## _s_m) \\\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_ ## TYPE ## _scalar, double ## _ ## TYPE ## _m_s) \\\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_ ## TYPE ## _matrix, double ## _ ## TYPE ## _m_m)\n\n#define OCTAVE_INT_DOUBLE_CONCAT_FN(TYPE)                               \\\n  DEFNDCATOP_FN2 (TYPE ## _ ## double ## _s_s, TYPE ## _scalar, scalar, , TYPE ## NDArray, TYPE ## _array, array, concat) \\\n  DEFNDCATOP_FN2 (TYPE ## _ ## double ## _s_m, TYPE ## _scalar, matrix, , TYPE ## NDArray, TYPE ## _array, array, concat) \\\n  DEFNDCATOP_FN2 (TYPE ## _ ## double ## _m_s, TYPE ## _matrix, scalar, , TYPE ## NDArray, TYPE ## _array, array, concat) \\\n  DEFNDCATOP_FN2 (TYPE ## _ ## double ## _m_m, TYPE ## _matrix, matrix, , TYPE ## NDArray, TYPE ## _array, array, concat)\n\n#define OCTAVE_INSTALL_INT_DOUBLE_CONCAT_FN(TYPE)                       \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _scalar, octave_scalar, TYPE ## _ ## double ## _s_s) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _scalar, octave_matrix, TYPE ## _ ## double ## _s_m) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _matrix, octave_scalar, TYPE ## _ ## double ## _m_s) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _matrix, octave_matrix, TYPE ## _ ## double ## _m_m)\n\n#define OCTAVE_FLOAT_INT_CONCAT_FN(TYPE)                                \\\n  DEFNDCATOP_FN2 (float ## _ ## TYPE ## _s_s, float_scalar, TYPE ## _scalar, TYPE ## NDArray, , float_array, TYPE ## _array, concat) \\\n  DEFNDCATOP_FN2 (float ## _ ## TYPE ## _s_m, float_scalar, TYPE ## _matrix, TYPE ## NDArray, , float_array, TYPE ## _array, concat) \\\n  DEFNDCATOP_FN2 (float ## _ ## TYPE ## _m_s, float_matrix, TYPE ## _scalar, TYPE ## NDArray, , float_array, TYPE ## _array, concat) \\\n  DEFNDCATOP_FN2 (float ## _ ## TYPE ## _m_m, float_matrix, TYPE ## _matrix, TYPE ## NDArray, , float_array, TYPE ## _array, concat)\n\n#define OCTAVE_INSTALL_FLOAT_INT_CONCAT_FN(TYPE)                        \\\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_ ## TYPE ## _scalar, float ## _ ## TYPE ## _s_s) \\\n  INSTALL_CATOP_TI (ti, octave_float_scalar, octave_ ## TYPE ## _matrix, float ## _ ## TYPE ## _s_m) \\\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_ ## TYPE ## _scalar, float ## _ ## TYPE ## _m_s) \\\n  INSTALL_CATOP_TI (ti, octave_float_matrix, octave_ ## TYPE ## _matrix, float ## _ ## TYPE ## _m_m)\n\n#define OCTAVE_INT_FLOAT_CONCAT_FN(TYPE)                                \\\n  DEFNDCATOP_FN2 (TYPE ## _ ## float ## _s_s, TYPE ## _scalar, float_scalar, , TYPE ## NDArray, TYPE ## _array, float_array, concat) \\\n  DEFNDCATOP_FN2 (TYPE ## _ ## float ## _s_m, TYPE ## _scalar, float_matrix, , TYPE ## NDArray, TYPE ## _array, float_array, concat) \\\n  DEFNDCATOP_FN2 (TYPE ## _ ## float ## _m_s, TYPE ## _matrix, float_scalar, , TYPE ## NDArray, TYPE ## _array, float_array, concat) \\\n  DEFNDCATOP_FN2 (TYPE ## _ ## float ## _m_m, TYPE ## _matrix, float_matrix, , TYPE ## NDArray, TYPE ## _array, float_array, concat)\n\n#define OCTAVE_INSTALL_INT_FLOAT_CONCAT_FN(TYPE)                        \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _scalar, octave_float_scalar, TYPE ## _ ## float ## _s_s) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _scalar, octave_float_matrix, TYPE ## _ ## float ## _s_m) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _matrix, octave_float_scalar, TYPE ## _ ## float ## _m_s) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _matrix, octave_float_matrix, TYPE ## _ ## float ## _m_m)\n\n// For compatibility, concatenation with a character always returns a\n// character.\n\n#define OCTAVE_CHAR_INT_CONCAT_FN(TYPE)                                 \\\n  DEFNDCHARCATOP_FN (char ## _ ## TYPE ## _m_s, char_matrix, TYPE ## _scalar, concat) \\\n  DEFNDCHARCATOP_FN (char ## _ ## TYPE ## _m_m, char_matrix, TYPE ## _matrix, concat)\n\n#define OCTAVE_INSTALL_CHAR_INT_CONCAT_FN(TYPE)                         \\\n  INSTALL_CATOP_TI (ti, octave_char_matrix_str, octave_ ## TYPE ## _scalar, char ## _ ## TYPE ## _m_s) \\\n  INSTALL_CATOP_TI (ti, octave_char_matrix_str, octave_ ## TYPE ## _matrix, char ## _ ## TYPE ## _m_m) \\\n  INSTALL_CATOP_TI (ti, octave_char_matrix_sq_str, octave_ ## TYPE ## _scalar, char ## _ ## TYPE ## _m_s) \\\n  INSTALL_CATOP_TI (ti, octave_char_matrix_sq_str, octave_ ## TYPE ## _matrix, char ## _ ## TYPE ## _m_m)\n\n#define OCTAVE_INT_CHAR_CONCAT_FN(TYPE)                                 \\\n  DEFNDCHARCATOP_FN (TYPE ## _ ## char ## _s_m, TYPE ## _scalar, char_matrix, concat) \\\n  DEFNDCHARCATOP_FN (TYPE ## _ ## char ## _m_m, TYPE ## _matrix, char_matrix, concat)\n\n#define OCTAVE_INSTALL_INT_CHAR_CONCAT_FN(TYPE)                         \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _scalar, octave_char_matrix_str, TYPE ## _ ## char ## _s_m) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _matrix, octave_char_matrix_str, TYPE ## _ ## char ## _m_m) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _scalar, octave_char_matrix_sq_str, TYPE ## _ ## char ## _s_m) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _matrix, octave_char_matrix_sq_str, TYPE ## _ ## char ## _m_m)\n\n#define OCTAVE_CONCAT_FN(TYPE)                                          \\\n  DEFNDCATOP_FN (TYPE ## _s_s, TYPE ## _scalar, TYPE ## _scalar, TYPE ## _array, TYPE ## _array, concat) \\\n  DEFNDCATOP_FN (TYPE ## _s_m, TYPE ## _scalar, TYPE ## _matrix, TYPE ## _array, TYPE ## _array, concat) \\\n  DEFNDCATOP_FN (TYPE ## _m_s, TYPE ## _matrix, TYPE ## _scalar, TYPE ## _array, TYPE ## _array, concat) \\\n  DEFNDCATOP_FN (TYPE ## _m_m, TYPE ## _matrix, TYPE ## _matrix, TYPE ## _array, TYPE ## _array, concat)\n\n#define OCTAVE_INSTALL_CONCAT_FN(TYPE)                                  \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _scalar, octave_ ## TYPE ## _scalar, TYPE ## _s_s) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _scalar, octave_ ## TYPE ## _matrix, TYPE ## _s_m) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _matrix, octave_ ## TYPE ## _scalar, TYPE ## _m_s) \\\n  INSTALL_CATOP_TI (ti, octave_ ## TYPE ## _matrix, octave_ ## TYPE ## _matrix, TYPE ## _m_m)\n\n// scalar unary ops.\n#define OCTAVE_S_INT_UNOPS(TYPE)                                        \\\n                                                                        \\\n  DEFUNOP_OP (s_not, TYPE ## _scalar, !)                                \\\n  DEFUNOP_OP (s_uplus, TYPE ## _scalar, /* no-op */)                    \\\n  DEFUNOP (s_uminus, TYPE ## _scalar)                                   \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TYPE ## _scalar&, v, a);   \\\n    octave_value retval = octave_value (- v. TYPE ## _scalar_value ()); \\\n    return retval;                                                      \\\n  }                                                                     \\\n  DEFUNOP_OP (s_transpose, TYPE ## _scalar, /* no-op */)                \\\n  DEFUNOP_OP (s_hermitian, TYPE ## _scalar, /* no-op */)                \\\n                                                                        \\\n  DEFNCUNOP_METHOD (s_incr, TYPE ## _scalar, increment)                 \\\n  DEFNCUNOP_METHOD (s_decr, TYPE ## _scalar, decrement)\n\n// scalar by scalar ops.\n#define OCTAVE_SS_INT_ARITH_OPS(PFX, T1, T2, T3)                        \\\n                                                                        \\\n  DEFINTBINOP_OP (PFX ## _add, T1 ## scalar, T2 ## scalar, +, T3)       \\\n  DEFINTBINOP_OP (PFX ## _sub, T1 ## scalar, T2 ## scalar, -, T3)       \\\n  DEFINTBINOP_OP (PFX ## _mul, T1 ## scalar, T2 ## scalar, *, T3)       \\\n                                                                        \\\n  DEFBINOP (PFX ## _div, T1 ## scalar, T2 ## scalar)                    \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \\\n                                                                        \\\n    return octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \\\n  }                                                                     \\\n                                                                        \\\n  DEFINTBINOP_FN (PFX ## _pow, T1 ## scalar, T2 ## scalar, xpow, T3, ^) \\\n                                                                        \\\n  DEFBINOP (PFX ## _ldiv, T1 ## scalar, T2 ## scalar)                   \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \\\n                                                                        \\\n    return octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \\\n  }                                                                     \\\n                                                                        \\\n  DEFINTBINOP_OP (PFX ## _el_mul, T1 ## scalar, T2 ## scalar, *, T3)    \\\n                                                                        \\\n  DEFBINOP (PFX ## _el_div, T1 ## scalar, T2 ## scalar)                 \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \\\n                                                                        \\\n    return octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \\\n  }                                                                     \\\n                                                                        \\\n  DEFINTBINOP_FN (PFX ## _el_pow, T1 ## scalar, T2 ## scalar, xpow, T3, .^) \\\n                                                                        \\\n  DEFBINOP (PFX ## _el_ldiv, T1 ## scalar, T2 ## scalar)                \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \\\n                                                                        \\\n    return octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \\\n  }\n\n#define OCTAVE_SS_INT_BOOL_OPS(PFX, T1, T2, Z1, Z2)                     \\\n  DEFBINOP (PFX ## _el_and, T2, T2)                                     \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \\\n                                                                        \\\n    return v1.T1 ## scalar_value () != Z1 && v2.T2 ## scalar_value () != Z2; \\\n  }                                                                     \\\n                                                                        \\\n  DEFBINOP (PFX ## _el_or, T1, T2)                                      \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \\\n                                                                        \\\n    return v1.T1 ## scalar_value () != Z1 || v2.T2 ## scalar_value () != Z2; \\\n  }\n\n#define OCTAVE_SS_INT_CMP_OPS(PFX, T1, T2)                      \\\n  DEFBINOP_OP (PFX ## _lt, T1 ## scalar, T2 ## scalar, <)       \\\n  DEFBINOP_OP (PFX ## _le, T1 ## scalar, T2 ## scalar, <=)      \\\n  DEFBINOP_OP (PFX ## _eq, T1 ## scalar, T2 ## scalar, ==)      \\\n  DEFBINOP_OP (PFX ## _ge, T1 ## scalar, T2 ## scalar, >=)      \\\n  DEFBINOP_OP (PFX ## _gt, T1 ## scalar, T2 ## scalar, >)       \\\n  DEFBINOP_OP (PFX ## _ne, T1 ## scalar, T2 ## scalar, !=)\n\n#define OCTAVE_SS_POW_OPS(T1, T2)                       \\\n  static octave_value                                   \\\n  xpow (const octave_ ## T1& a, const octave_ ## T2& b) \\\n  {                                                     \\\n    return pow (a, b);                                  \\\n  }                                                     \\\n                                                        \\\n  static octave_value                                   \\\n  xpow (const octave_ ## T1& a, double b)               \\\n  {                                                     \\\n    return pow (a, b);                                  \\\n  }                                                     \\\n                                                        \\\n  static octave_value                                   \\\n  xpow (double a, const octave_ ## T1& b)               \\\n  {                                                     \\\n    return pow (a, b);                                  \\\n  }                                                     \\\n                                                        \\\n  static octave_value                                   \\\n  xpow (const octave_ ## T1& a, float b)                \\\n  {                                                     \\\n    return powf (a, b);                                 \\\n  }                                                     \\\n                                                        \\\n  static octave_value                                   \\\n  xpow (float a, const octave_ ## T1& b)                \\\n  {                                                     \\\n    return powf (a, b);                                 \\\n  }\n\n#define OCTAVE_SS_INT_OPS(TYPE)                                         \\\n  OCTAVE_S_INT_UNOPS (TYPE)                                             \\\n  OCTAVE_SS_POW_OPS (TYPE, TYPE)                                        \\\n  OCTAVE_SS_INT_ARITH_OPS (ss, TYPE ## _, TYPE ## _, TYPE)              \\\n  OCTAVE_SS_INT_ARITH_OPS (ssx, TYPE ## _, , TYPE)                      \\\n  OCTAVE_SS_INT_ARITH_OPS (sxs, , TYPE ## _, TYPE)                      \\\n  OCTAVE_SS_INT_ARITH_OPS (ssfx, TYPE ## _, float_, TYPE)               \\\n  OCTAVE_SS_INT_ARITH_OPS (sfxs, float_, TYPE ## _, TYPE)               \\\n  OCTAVE_SS_INT_CMP_OPS (ss, TYPE ## _, TYPE ## _)                      \\\n  OCTAVE_SS_INT_CMP_OPS (sx, TYPE ## _, )                               \\\n  OCTAVE_SS_INT_CMP_OPS (xs, , TYPE ## _)                               \\\n  OCTAVE_SS_INT_CMP_OPS (sfx, TYPE ## _, float_)                        \\\n  OCTAVE_SS_INT_CMP_OPS (fxs, float_, TYPE ## _)                        \\\n  OCTAVE_SS_INT_BOOL_OPS (ss, TYPE ## _, TYPE ## _, octave_ ## TYPE (0), octave_ ## TYPE (0)) \\\n  OCTAVE_SS_INT_BOOL_OPS (sx, TYPE ## _, , octave_ ## TYPE (0), 0)      \\\n  OCTAVE_SS_INT_BOOL_OPS (xs, , TYPE ## _, 0, octave_ ## TYPE (0))      \\\n  OCTAVE_SS_INT_BOOL_OPS (sfx, TYPE ## _, float_, octave_ ## TYPE (0), 0) \\\n  OCTAVE_SS_INT_BOOL_OPS (fxs, float_, TYPE ## _, 0, octave_ ## TYPE (0))\n\n// scalar by matrix ops.\n#define OCTAVE_SM_INT_ARITH_OPS(PFX, TS, TM, TI)                        \\\n                                                                        \\\n  DEFINTNDBINOP_OP (PFX ## _add, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, +, TI) \\\n  DEFINTNDBINOP_OP (PFX ## _sub, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, -, TI) \\\n  DEFINTNDBINOP_OP (PFX ## _mul, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, *, TI) \\\n                                                                        \\\n  /* DEFBINOP (PFX ## _div, TS ## scalar, TM ## matrix) */              \\\n  /* { */                                                               \\\n  /* OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v1, a1); */ \\\n  /* OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v2, a2); */ \\\n  /* */                                                                 \\\n  /* Matrix m1 = v1.TM ## matrix_value (); */                           \\\n  /* Matrix m2 = v2.TM ## matrix_value (); */                           \\\n  /* */                                                                 \\\n  /* return octave_value (xdiv (m1, m2)); */                            \\\n  /* } */                                                               \\\n                                                                        \\\n  /* DEFBINOP_FN (PFX ## _pow, TS ## scalar, TM ## matrix, xpow) */     \\\n                                                                        \\\n  DEFBINOP (PFX ## _ldiv, TS ## scalar, TM ## matrix)                   \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v2, a2);    \\\n                                                                        \\\n   return octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \\\n   }                                                                    \\\n                                                                        \\\n  DEFINTNDBINOP_OP (PFX ## _el_mul, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, *, TI) \\\n  DEFBINOP (PFX ## _el_div, TS ## scalar, TM ## matrix)                 \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v2, a2);    \\\n                                                                        \\\n   octave_value retval = octave_value (v1.TS ## scalar_value () / v2.TM ## array_value ()); \\\n   return retval;                                                       \\\n   }                                                                    \\\n                                                                        \\\n  DEFINTNDBINOP_FN (PFX ## _el_pow, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, elem_xpow, TI, .^) \\\n                                                                        \\\n  DEFBINOP (PFX ## _el_ldiv, TS ## scalar, TM ## matrix)                \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v2, a2);    \\\n                                                                        \\\n   return octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \\\n   }\n\n#define OCTAVE_SM_INT_CMP_OPS(PFX, TS, TM)                              \\\n  DEFNDBINOP_FN (PFX ## _lt, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_lt) \\\n  DEFNDBINOP_FN (PFX ## _le, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_le) \\\n  DEFNDBINOP_FN (PFX ## _eq, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_eq) \\\n  DEFNDBINOP_FN (PFX ## _ge, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_ge) \\\n  DEFNDBINOP_FN (PFX ## _gt, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_gt) \\\n  DEFNDBINOP_FN (PFX ## _ne, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_ne)\n\n#define OCTAVE_SM_INT_BOOL_OPS(PFX, TS, TM)                             \\\n  DEFNDBINOP_FN (PFX ## _el_and, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_and) \\\n  DEFNDBINOP_FN (PFX ## _el_or,  TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_or) \\\n  DEFNDBINOP_FN (PFX ## _el_and_not, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_and_not) \\\n  DEFNDBINOP_FN (PFX ## _el_or_not,  TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, mx_el_or_not)\n\n#define OCTAVE_SM_POW_OPS(T1, T2)                               \\\n  static octave_value                                           \\\n  elem_xpow (const octave_ ## T1& a, const T2 ## NDArray& b)    \\\n  {                                                             \\\n    T2 ## NDArray result (b.dims ());                           \\\n    for (int i = 0; i < b.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = pow (a, b(i));                             \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (const octave_ ## T1& a, const NDArray& b)          \\\n  {                                                             \\\n    T1 ## NDArray result (b.dims ());                           \\\n    for (int i = 0; i < b.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = pow (a, b(i));                             \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (double a, const T2 ## NDArray& b)                  \\\n  {                                                             \\\n    T2 ## NDArray result (b.dims ());                           \\\n    for (int i = 0; i < b.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = pow (a, b(i));                             \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (const octave_ ## T1& a, const FloatNDArray& b)     \\\n  {                                                             \\\n    T1 ## NDArray result (b.dims ());                           \\\n    for (int i = 0; i < b.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = powf (a, b(i));                            \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (float a, const T2 ## NDArray& b)                   \\\n  {                                                             \\\n    T2 ## NDArray result (b.dims ());                           \\\n    for (int i = 0; i < b.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = powf (a, b(i));                            \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }\n\n#define OCTAVE_SM_CONV(TS, TM)                                          \\\n  DEFCONV (TS ## s_ ## TM ## m_conv, TM ## scalar, TM ## matrix)        \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v, a);      \\\n                                                                        \\\n    return new octave_ ## TM ## matrix (v.TM ## array_value ());        \\\n  }\n\n#define OCTAVE_SM_INT_OPS(TYPE)                                 \\\n  OCTAVE_SM_POW_OPS (TYPE, TYPE)                                \\\n  OCTAVE_SM_INT_ARITH_OPS (sm, TYPE ## _, TYPE ## _, TYPE)      \\\n  OCTAVE_SM_INT_ARITH_OPS (smx, TYPE ## _, , TYPE)              \\\n  OCTAVE_SM_INT_ARITH_OPS (sxm, , TYPE ## _, TYPE)              \\\n  OCTAVE_SM_INT_ARITH_OPS (smfx, TYPE ## _, float_, TYPE)       \\\n  OCTAVE_SM_INT_ARITH_OPS (sfxm, float_, TYPE ## _, TYPE)       \\\n  OCTAVE_SM_INT_CMP_OPS (sm, TYPE ## _, TYPE ## _)              \\\n  OCTAVE_SM_INT_CMP_OPS (xm, , TYPE ## _)                       \\\n  OCTAVE_SM_INT_CMP_OPS (smx, TYPE ## _, )                      \\\n  OCTAVE_SM_INT_CMP_OPS (fxm, float_, TYPE ## _)                \\\n  OCTAVE_SM_INT_CMP_OPS (smfx, TYPE ## _, float_)               \\\n  OCTAVE_SM_INT_BOOL_OPS (sm, TYPE ## _, TYPE ## _)             \\\n  OCTAVE_SM_INT_BOOL_OPS (xm, , TYPE ## _)                      \\\n  OCTAVE_SM_INT_BOOL_OPS (smx, TYPE ## _, )                     \\\n  OCTAVE_SM_INT_BOOL_OPS (fxm, float_, TYPE ## _)               \\\n  OCTAVE_SM_INT_BOOL_OPS (smfx, TYPE ## _, float_)              \\\n  OCTAVE_SM_CONV (TYPE ## _, TYPE ## _)                         \\\n  OCTAVE_SM_CONV (TYPE ## _, complex_)                          \\\n  OCTAVE_SM_CONV (TYPE ## _, float_complex_)\n\n// matrix by scalar ops.\n#define OCTAVE_MS_INT_ARITH_OPS(PFX, TM, TS, TI)                        \\\n                                                                        \\\n  DEFINTNDBINOP_OP (PFX ## _add, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, +, TI) \\\n  DEFINTNDBINOP_OP (PFX ## _sub, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, -, TI) \\\n  DEFINTNDBINOP_OP (PFX ## _mul, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, *, TI) \\\n                                                                        \\\n  DEFBINOP (PFX ## _div, TM ## matrix, TS ## scalar)                    \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v2, a2);    \\\n                                                                        \\\n    return octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \\\n  }                                                                     \\\n                                                                        \\\n  /* DEFBINOP_FN (PFX ## _pow, TM ## matrix, TS ## scalar, xpow) */     \\\n                                                                        \\\n  /* DEFBINOP (PFX ## _ldiv, TM ## matrix, TS ## scalar) */             \\\n  /* { */                                                               \\\n  /* OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v1, a1); */ \\\n  /* OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v2, a2); */ \\\n  /* */                                                                 \\\n  /* Matrix m1 = v1.TM ## matrix_value (); */                           \\\n  /* Matrix m2 = v2.TM ## matrix_value (); */                           \\\n  /* */                                                                 \\\n  /* return octave_value (xleftdiv (m1, m2)); */                        \\\n  /* } */                                                               \\\n                                                                        \\\n  DEFINTNDBINOP_OP (PFX ## _el_mul, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, *, TI) \\\n                                                                        \\\n  DEFBINOP (PFX ## _el_div, TM ## matrix, TS ## scalar)                 \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v2, a2);    \\\n                                                                        \\\n    return octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \\\n  }                                                                     \\\n                                                                        \\\n  DEFINTNDBINOP_FN (PFX ## _el_pow, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, elem_xpow, TI, .^) \\\n                                                                        \\\n  DEFBINOP (PFX ## _el_ldiv, TM ## matrix, TS ## scalar)                \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v2, a2);    \\\n                                                                        \\\n    octave_value retval = v2.TS ## scalar_value () / v1.TM ## array_value (); \\\n    return retval;                                                      \\\n  }\n\n#define OCTAVE_MS_INT_CMP_OPS(PFX, TM, TS)                              \\\n  DEFNDBINOP_FN (PFX ## _lt, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_lt) \\\n  DEFNDBINOP_FN (PFX ## _le, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_le) \\\n  DEFNDBINOP_FN (PFX ## _eq, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_eq) \\\n  DEFNDBINOP_FN (PFX ## _ge, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_ge) \\\n  DEFNDBINOP_FN (PFX ## _gt, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_gt) \\\n  DEFNDBINOP_FN (PFX ## _ne, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_ne)\n\n#define OCTAVE_MS_INT_BOOL_OPS(PFX, TM, TS)                             \\\n  DEFNDBINOP_FN (PFX ## _el_and, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_and) \\\n  DEFNDBINOP_FN (PFX ## _el_or, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_or) \\\n  DEFNDBINOP_FN (PFX ## _el_not_and, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_not_and) \\\n  DEFNDBINOP_FN (PFX ## _el_not_or,  TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_not_or)\n\n#define OCTAVE_MS_INT_ASSIGN_OPS(PFX, TM, TS, TE)                       \\\n  DEFNDASSIGNOP_FN (PFX ## _assign, TM ## matrix, TS ## scalar, TM ## scalar, assign)\n\n#define OCTAVE_MS_INT_ASSIGNEQ_OPS(PFX, TM)                             \\\n  DEFNDASSIGNOP_OP (PFX ## _assign_add, TM ## matrix, TM ## scalar, TM ## scalar, +=) \\\n  DEFNDASSIGNOP_OP (PFX ## _assign_sub, TM ## matrix, TM ## scalar, TM ## scalar, -=) \\\n  DEFNDASSIGNOP_OP (PFX ## _assign_mul, TM ## matrix, TM ## scalar, TM ## scalar, *=) \\\n  DEFNDASSIGNOP_OP (PFX ## _assign_div, TM ## matrix, TM ## scalar, TM ## scalar, /=)\n\n#define OCTAVE_MS_POW_OPS(T1, T2)                               \\\n  static octave_value                                           \\\n  elem_xpow (T1 ## NDArray a, octave_ ## T2 b)                  \\\n  {                                                             \\\n   T1 ## NDArray result (a.dims ());                            \\\n   for (int i = 0; i < a.numel (); i++)                         \\\n     {                                                          \\\n       octave_quit ();                                          \\\n       result (i) = pow (a(i), b);                              \\\n     }                                                          \\\n   return octave_value (result);                                \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (T1 ## NDArray a, double b)                         \\\n  {                                                             \\\n    T1 ## NDArray result (a.dims ());                           \\\n    for (int i = 0; i < a.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = pow (a(i), b);                             \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (NDArray a, octave_ ## T2 b)                        \\\n  {                                                             \\\n    T2 ## NDArray result (a.dims ());                           \\\n    for (int i = 0; i < a.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = pow (a(i), b);                             \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (T1 ## NDArray a, float b)                          \\\n  {                                                             \\\n    T1 ## NDArray result (a.dims ());                           \\\n    for (int i = 0; i < a.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = powf (a(i), b);                            \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (FloatNDArray a, octave_ ## T2 b)                   \\\n  {                                                             \\\n    T2 ## NDArray result (a.dims ());                           \\\n    for (int i = 0; i < a.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = powf (a(i), b);                            \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }\n\n#define OCTAVE_MS_INT_OPS(TYPE)                                         \\\n  OCTAVE_MS_POW_OPS (TYPE, TYPE)                                        \\\n  OCTAVE_MS_INT_ARITH_OPS (ms, TYPE ## _, TYPE ## _, TYPE)              \\\n  OCTAVE_MS_INT_ARITH_OPS (msx, TYPE ## _, , TYPE)                      \\\n  OCTAVE_MS_INT_ARITH_OPS (mxs, , TYPE ## _, TYPE)                      \\\n  OCTAVE_MS_INT_ARITH_OPS (msfx, TYPE ## _, float_, TYPE)               \\\n  OCTAVE_MS_INT_ARITH_OPS (mfxs, float_, TYPE ## _, TYPE)               \\\n  OCTAVE_MS_INT_CMP_OPS (ms, TYPE ## _, TYPE ## _)                      \\\n  OCTAVE_MS_INT_CMP_OPS (mx, TYPE ## _, )                               \\\n  OCTAVE_MS_INT_CMP_OPS (mxs, , TYPE ## _)                              \\\n  OCTAVE_MS_INT_CMP_OPS (mfx, TYPE ## _, float_)                        \\\n  OCTAVE_MS_INT_CMP_OPS (mfxs, float_, TYPE ## _)                       \\\n  OCTAVE_MS_INT_BOOL_OPS (ms, TYPE ## _, TYPE ## _)                     \\\n  OCTAVE_MS_INT_BOOL_OPS (mx, TYPE ## _, )                              \\\n  OCTAVE_MS_INT_BOOL_OPS (mxs, , TYPE ## _)                             \\\n  OCTAVE_MS_INT_BOOL_OPS (mfx, TYPE ## _, float_)                       \\\n  OCTAVE_MS_INT_BOOL_OPS (mfxs, float_, TYPE ## _)                      \\\n  OCTAVE_MS_INT_ASSIGN_OPS (ms, TYPE ## _, TYPE ## _, TYPE ## _)        \\\n  OCTAVE_MS_INT_ASSIGNEQ_OPS (mse, TYPE ## _)                           \\\n  OCTAVE_MS_INT_ASSIGN_OPS (mx, TYPE ## _, , )                          \\\n  OCTAVE_MS_INT_ASSIGN_OPS (mfx, TYPE ## _, float_, float_)\n\n// matrix unary ops.\n#define OCTAVE_M_INT_UNOPS(TYPE)                                        \\\n                                                                        \\\n  DEFNDUNOP_OP (m_not, TYPE ## _matrix, TYPE ## _array, !)              \\\n  DEFNDUNOP_OP (m_uplus, TYPE ## _matrix, TYPE ## _array, /* no-op */)  \\\n  DEFUNOP (m_uminus, TYPE ## _matrix)                                   \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TYPE ## _matrix&, v, a);   \\\n    octave_value retval = octave_value (- v. TYPE ## _array_value ());  \\\n    return retval;                                                      \\\n  }                                                                     \\\n                                                                        \\\n  DEFUNOP (m_transpose, TYPE ## _matrix)                                \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## TYPE ## _matrix&, v, a);   \\\n                                                                        \\\n    if (v.ndims () > 2)                                                 \\\n      error (\"transpose not defined for N-D objects\");                  \\\n                                                                        \\\n    return octave_value (v.TYPE ## _array_value ().transpose ());       \\\n  }                                                                     \\\n                                                                        \\\n  DEFNCUNOP_METHOD (m_incr, TYPE ## _matrix, increment)                 \\\n  DEFNCUNOP_METHOD (m_decr, TYPE ## _matrix, decrement)                 \\\n  DEFNCUNOP_METHOD (m_changesign, TYPE ## _matrix, changesign)\n\n// matrix by matrix ops.\n#define OCTAVE_MM_INT_ARITH_OPS(PFX, T1, T2, T3)                        \\\n                                                                        \\\n  DEFINTNDBINOP_OP (PFX ## _add, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, +, T3) \\\n  DEFINTNDBINOP_OP (PFX ## _sub, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, -, T3) \\\n                                                                        \\\n  /* DEFBINOP_OP (PFX ## _mul, T1 ## matrix, T2 ## matrix, *) */        \\\n  /* DEFBINOP_FN (PFX ## _div, T1 ## matrix, T2 ## matrix, xdiv) */     \\\n                                                                        \\\n  DEFBINOPX (PFX ## _pow, T1 ## matrix, T2 ## matrix)                   \\\n  {                                                                     \\\n    error (\"can't do A ^ B for A and B both matrices\");                 \\\n  }                                                                     \\\n                                                                        \\\n  /* DEFBINOP_FN (PFX ## _ldiv, T1 ## matrix, T2 ## matrix, xleftdiv) */ \\\n                                                                        \\\n  DEFINTNDBINOP_FN (PFX ## _el_mul, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, product, T3, .*) \\\n                                                                        \\\n  DEFINTNDBINOP_FN (PFX ## _el_div, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, quotient, T3, ./) \\\n                                                                        \\\n  DEFINTNDBINOP_FN (PFX ## _el_pow, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, elem_xpow, T3, .^) \\\n                                                                        \\\n  DEFBINOP (PFX ## _el_ldiv, T1 ## matrix, T2 ## matrix)                \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## matrix&, v1, a1);    \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## matrix&, v2, a2);    \\\n                                                                        \\\n    octave_value retval = octave_value (quotient (v2.T2 ## array_value (), v1.T1 ## array_value ())); \\\n    return retval;                                                      \\\n  }\n\n#define OCTAVE_MM_INT_CMP_OPS(PFX, T1, T2)                              \\\n  DEFNDBINOP_FN (PFX ## _lt, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_lt) \\\n  DEFNDBINOP_FN (PFX ## _le, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_le) \\\n  DEFNDBINOP_FN (PFX ## _eq, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_eq) \\\n  DEFNDBINOP_FN (PFX ## _ge, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_ge) \\\n  DEFNDBINOP_FN (PFX ## _gt, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_gt) \\\n  DEFNDBINOP_FN (PFX ## _ne, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_ne)\n\n#define OCTAVE_MM_INT_BOOL_OPS(PFX, T1, T2)                             \\\n  DEFNDBINOP_FN (PFX ## _el_and, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_and) \\\n  DEFNDBINOP_FN (PFX ## _el_or,  T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_or) \\\n  DEFNDBINOP_FN (PFX ## _el_not_and, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_not_and) \\\n  DEFNDBINOP_FN (PFX ## _el_not_or,  T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_not_or) \\\n  DEFNDBINOP_FN (PFX ## _el_and_not, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_and_not) \\\n  DEFNDBINOP_FN (PFX ## _el_or_not,  T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_or_not)\n\n#define OCTAVE_MM_INT_ASSIGN_OPS(PFX, TLHS, TRHS, TE)                   \\\n  DEFNDASSIGNOP_FN (PFX ## _assign, TLHS ## matrix, TRHS ## matrix, TLHS ## array, assign)\n\n#define OCTAVE_MM_INT_ASSIGNEQ_OPS(PFX, TM)                             \\\n  DEFNDASSIGNOP_OP (PFX ## _assign_add, TM ## matrix, TM ## matrix, TM ## array, +=) \\\n  DEFNDASSIGNOP_OP (PFX ## _assign_sub, TM ## matrix, TM ## matrix, TM ## array, -=) \\\n  DEFNDASSIGNOP_FNOP (PFX ## _assign_el_mul, TM ## matrix, TM ## matrix, TM ## array, product_eq) \\\n  DEFNDASSIGNOP_FNOP (PFX ## _assign_el_div, TM ## matrix, TM ## matrix, TM ## array, quotient_eq)\n\n#define OCTAVE_MM_POW_OPS(T1, T2)                               \\\n  static octave_value                                           \\\n  elem_xpow (const T1 ## NDArray& a, const T2 ## NDArray& b)    \\\n  {                                                             \\\n    const dim_vector& a_dims = a.dims ();                       \\\n    const dim_vector& b_dims = b.dims ();                       \\\n    if (a_dims != b_dims)                                       \\\n      {                                                         \\\n        if (! is_valid_bsxfun (a_dims, b_dims))                 \\\n          octave::err_nonconformant (\"operator .^\", a_dims, b_dims);    \\\n                                                                \\\n        return bsxfun_pow (a, b);                               \\\n      }                                                         \\\n    T1 ## NDArray result (a_dims);                              \\\n    for (int i = 0; i < a.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = pow (a(i), b(i));                          \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (const T1 ## NDArray& a, const NDArray& b)          \\\n  {                                                             \\\n    const dim_vector& a_dims = a.dims ();                       \\\n    const dim_vector& b_dims = b.dims ();                       \\\n    if (a_dims != b_dims)                                       \\\n      {                                                         \\\n        if (! is_valid_bsxfun (a_dims, b_dims))                 \\\n          octave::err_nonconformant (\"operator .^\", a_dims, b_dims);    \\\n                                                                \\\n        return bsxfun_pow (a, b);                               \\\n      }                                                         \\\n    T1 ## NDArray result (a_dims);                              \\\n    for (int i = 0; i < a.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = pow (a(i), b(i));                          \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (const NDArray& a, const T2 ## NDArray& b)          \\\n  {                                                             \\\n    const dim_vector& a_dims = a.dims ();                       \\\n    const dim_vector& b_dims = b.dims ();                       \\\n    if (a_dims != b_dims)                                       \\\n      {                                                         \\\n        if (! is_valid_bsxfun (a_dims, b_dims))                 \\\n          octave::err_nonconformant (\"operator .^\", a_dims, b_dims);    \\\n                                                                \\\n        return bsxfun_pow (a, b);                               \\\n      }                                                         \\\n    T2 ## NDArray result (a_dims);                              \\\n    for (int i = 0; i < a.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = pow (a(i), b(i));                          \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (const T1 ## NDArray& a, const FloatNDArray& b)     \\\n  {                                                             \\\n    const dim_vector& a_dims = a.dims ();                       \\\n    const dim_vector& b_dims = b.dims ();                       \\\n    if (a_dims != b_dims)                                       \\\n      {                                                         \\\n        if (! is_valid_bsxfun (a_dims, b_dims))                 \\\n          octave::err_nonconformant (\"operator .^\", a_dims, b_dims);    \\\n                                                                \\\n        return bsxfun_pow (a, b);                               \\\n      }                                                         \\\n    T1 ## NDArray result (a_dims);                              \\\n    for (int i = 0; i < a.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = powf (a(i), b(i));                         \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }                                                             \\\n                                                                \\\n  static octave_value                                           \\\n  elem_xpow (const FloatNDArray& a, const T2 ## NDArray& b)     \\\n  {                                                             \\\n    const dim_vector& a_dims = a.dims ();                       \\\n    const dim_vector& b_dims = b.dims ();                       \\\n    if (a_dims != b_dims)                                       \\\n      {                                                         \\\n        if (! is_valid_bsxfun (a_dims, b_dims))                 \\\n          octave::err_nonconformant (\"operator .^\", a_dims, b_dims);    \\\n                                                                \\\n        return bsxfun_pow (a, b);                               \\\n      }                                                         \\\n    T2 ## NDArray result (a_dims);                              \\\n    for (int i = 0; i < a.numel (); i++)                        \\\n      {                                                         \\\n        octave_quit ();                                         \\\n        result (i) = powf (a(i), b(i));                         \\\n      }                                                         \\\n    return octave_value (result);                               \\\n  }\n\n#define OCTAVE_MM_CONV(T1, T2)                                          \\\n  DEFCONV (T1 ## m_ ## T2 ## m_conv, T1 ## matrix, T2 ## matrix)        \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## matrix&, v, a);      \\\n                                                                        \\\n    return new octave_ ## T2 ## matrix (v.T2 ## array_value ());        \\\n  }\n\n#define OCTAVE_MM_INT_OPS(TYPE)                                         \\\n  OCTAVE_M_INT_UNOPS (TYPE)                                             \\\n  OCTAVE_MM_POW_OPS (TYPE, TYPE)                                        \\\n  OCTAVE_MM_INT_ARITH_OPS (mm, TYPE ## _, TYPE ## _, TYPE)              \\\n  OCTAVE_MM_INT_ARITH_OPS (mmx, TYPE ## _, , TYPE)                      \\\n  OCTAVE_MM_INT_ARITH_OPS (mxm, , TYPE ## _, TYPE)                      \\\n  OCTAVE_MM_INT_ARITH_OPS (mmfx, TYPE ## _, float_, TYPE)               \\\n  OCTAVE_MM_INT_ARITH_OPS (mfxm, float_, TYPE ## _, TYPE)               \\\n  OCTAVE_MM_INT_CMP_OPS (mm, TYPE ## _, TYPE ## _)                      \\\n  OCTAVE_MM_INT_CMP_OPS (mmx, TYPE ## _, )                              \\\n  OCTAVE_MM_INT_CMP_OPS (mfxm, float_, TYPE ## _)                       \\\n  OCTAVE_MM_INT_CMP_OPS (mmfx, TYPE ## _, float_)                       \\\n  OCTAVE_MM_INT_CMP_OPS (mxm, , TYPE ## _)                              \\\n  OCTAVE_MM_INT_BOOL_OPS (mm, TYPE ## _, TYPE ## _)                     \\\n  OCTAVE_MM_INT_BOOL_OPS (mmx, TYPE ## _, )                             \\\n  OCTAVE_MM_INT_BOOL_OPS (mxm, , TYPE ## _)                             \\\n  OCTAVE_MM_INT_BOOL_OPS (mmfx, TYPE ## _, float_)                      \\\n  OCTAVE_MM_INT_BOOL_OPS (mfxm, float_, TYPE ## _)                      \\\n  OCTAVE_MM_INT_ASSIGN_OPS (mm, TYPE ## _, TYPE ## _, TYPE ## _)        \\\n  OCTAVE_MM_INT_ASSIGNEQ_OPS (mme, TYPE ## _)                           \\\n  OCTAVE_MM_INT_ASSIGN_OPS (mmx, TYPE ## _, , )                         \\\n  OCTAVE_MM_INT_ASSIGN_OPS (mmfx, TYPE ## _, float_, float_)            \\\n  OCTAVE_MM_CONV(TYPE ## _, complex_)                                   \\\n  OCTAVE_MM_CONV(TYPE ## _, float_complex_)\n\n#define OCTAVE_RE_INT_ASSIGN_OPS(TYPE)                                  \\\n  DEFNDASSIGNOP_FN (TYPE ## ms_assign, matrix, TYPE ## _scalar, array, assign) \\\n  DEFNDASSIGNOP_FN (TYPE ## mm_assign, matrix, TYPE ## _matrix, array, assign)\n\n#define OCTAVE_FLT_RE_INT_ASSIGN_OPS(TYPE)                              \\\n  DEFNDASSIGNOP_FN (TYPE ## fms_assign, float_matrix, TYPE ## _scalar, float_array, assign) \\\n  DEFNDASSIGNOP_FN (TYPE ## fmm_assign, float_matrix, TYPE ## _matrix, float_array, assign)\n\n#define OCTAVE_CX_INT_ASSIGN_OPS(TYPE)                                  \\\n  DEFNDASSIGNOP_FN (TYPE ## cms_assign, complex_matrix, TYPE ## _scalar, complex_array, assign) \\\n  DEFNDASSIGNOP_FN (TYPE ## cmm_assign, complex_matrix, TYPE ## _matrix, complex_array, assign)\n\n#define OCTAVE_FLT_CX_INT_ASSIGN_OPS(TYPE)                              \\\n  DEFNDASSIGNOP_FN (TYPE ## fcms_assign, float_complex_matrix, TYPE ## _scalar, float_complex_array, assign) \\\n  DEFNDASSIGNOP_FN (TYPE ## fcmm_assign, float_complex_matrix, TYPE ## _matrix, float_complex_array, assign)\n\n#define OCTAVE_INT_NULL_ASSIGN_OPS(TYPE)                                \\\n  DEFNULLASSIGNOP_FN (TYPE ## null_assign, TYPE ## _matrix, delete_elements)\n\n#define OCTAVE_INT_OPS(TYPE)                    \\\n  OCTAVE_SS_INT_OPS (TYPE)                      \\\n  OCTAVE_SM_INT_OPS (TYPE)                      \\\n  OCTAVE_MS_INT_OPS (TYPE)                      \\\n  OCTAVE_MM_INT_OPS (TYPE)                      \\\n  OCTAVE_CONCAT_FN (TYPE)                       \\\n  OCTAVE_RE_INT_ASSIGN_OPS (TYPE)               \\\n  OCTAVE_FLT_RE_INT_ASSIGN_OPS (TYPE)           \\\n  OCTAVE_CX_INT_ASSIGN_OPS (TYPE)               \\\n  OCTAVE_FLT_CX_INT_ASSIGN_OPS (TYPE)           \\\n  OCTAVE_INT_NULL_ASSIGN_OPS(TYPE)\n\n#define OCTAVE_INSTALL_S_INT_UNOPS(TYPE)                                \\\n  INSTALL_UNOP_TI (ti, op_not, octave_ ## TYPE ## _scalar, s_not);             \\\n  INSTALL_UNOP_TI (ti, op_uplus, octave_ ## TYPE ## _scalar, s_uplus);         \\\n  INSTALL_UNOP_TI (ti, op_uminus, octave_ ## TYPE ## _scalar, s_uminus);       \\\n  INSTALL_UNOP_TI (ti, op_transpose, octave_ ## TYPE ## _scalar, s_transpose); \\\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_ ## TYPE ## _scalar, s_hermitian); \\\n                                                                        \\\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_ ## TYPE ## _scalar, s_incr);         \\\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_ ## TYPE ## _scalar, s_decr);\n\n#define OCTAVE_INSTALL_SS_INT_ARITH_OPS(PFX, T1, T2)                    \\\n  INSTALL_BINOP_TI (ti, op_add, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _add); \\\n  INSTALL_BINOP_TI (ti, op_sub, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _sub); \\\n  INSTALL_BINOP_TI (ti, op_mul, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _mul); \\\n  INSTALL_BINOP_TI (ti, op_div, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _div); \\\n  INSTALL_BINOP_TI (ti, op_pow, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _pow); \\\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _ldiv); \\\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _el_mul); \\\n  INSTALL_BINOP_TI (ti, op_el_div, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _el_div); \\\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _el_pow); \\\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _el_ldiv);\n\n#define OCTAVE_INSTALL_SS_INT_CMP_OPS(PFX, T1, T2)                      \\\n  INSTALL_BINOP_TI (ti, op_lt, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _lt); \\\n  INSTALL_BINOP_TI (ti, op_le, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _le); \\\n  INSTALL_BINOP_TI (ti, op_eq, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _eq); \\\n  INSTALL_BINOP_TI (ti, op_ge, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _ge); \\\n  INSTALL_BINOP_TI (ti, op_gt, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _gt); \\\n  INSTALL_BINOP_TI (ti, op_ne, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _ne);\n\n#define OCTAVE_INSTALL_SS_INT_BOOL_OPS(PFX, T1, T2)                     \\\n  INSTALL_BINOP_TI (ti, op_el_and, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _el_and); \\\n  INSTALL_BINOP_TI (ti, op_el_or, octave_ ## T1 ## scalar, octave_ ## T2 ## scalar, PFX ## _el_or);\n\n#define OCTAVE_INSTALL_SS_INT_OPS(TYPE)                                 \\\n  OCTAVE_INSTALL_S_INT_UNOPS (TYPE)                                     \\\n  OCTAVE_INSTALL_SS_INT_ARITH_OPS (ss, TYPE ## _, TYPE ## _)            \\\n  OCTAVE_INSTALL_SS_INT_ARITH_OPS (ssx, TYPE ## _, )                    \\\n  OCTAVE_INSTALL_SS_INT_ARITH_OPS (sxs,  , TYPE ## _)                   \\\n  OCTAVE_INSTALL_SS_INT_ARITH_OPS (ssfx, TYPE ## _, float_)             \\\n  OCTAVE_INSTALL_SS_INT_ARITH_OPS (sfxs,  float_, TYPE ## _)            \\\n  OCTAVE_INSTALL_SS_INT_CMP_OPS (ss, TYPE ## _, TYPE ## _)              \\\n  OCTAVE_INSTALL_SS_INT_CMP_OPS (sx, TYPE ## _, )                       \\\n  OCTAVE_INSTALL_SS_INT_CMP_OPS (xs, , TYPE ## _)                       \\\n  OCTAVE_INSTALL_SS_INT_CMP_OPS (sfx, TYPE ## _, float_)                \\\n  OCTAVE_INSTALL_SS_INT_CMP_OPS (fxs, float_, TYPE ## _)                \\\n  OCTAVE_INSTALL_SS_INT_BOOL_OPS (ss, TYPE ## _, TYPE ## _)             \\\n  OCTAVE_INSTALL_SS_INT_BOOL_OPS (sx, TYPE ## _, )                      \\\n  OCTAVE_INSTALL_SS_INT_BOOL_OPS (xs, , TYPE ## _)                      \\\n  OCTAVE_INSTALL_SS_INT_BOOL_OPS (sfx, TYPE ## _, float_)               \\\n  OCTAVE_INSTALL_SS_INT_BOOL_OPS (fxs, float_, TYPE ## _)               \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_ ## TYPE ## _scalar, octave_ ## TYPE ## _matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_scalar, octave_ ## TYPE ## _matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_float_scalar, octave_ ## TYPE ## _matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_complex_scalar, octave_complex_matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_float_complex_scalar, octave_float_complex_matrix)\n\n#define OCTAVE_INSTALL_SM_INT_ARITH_OPS(PFX, T1, T2)                    \\\n  INSTALL_BINOP_TI (ti, op_add, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _add); \\\n  INSTALL_BINOP_TI (ti, op_sub, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _sub); \\\n  INSTALL_BINOP_TI (ti, op_mul, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _mul); \\\n  /* INSTALL_BINOP_TI (ti, op_div, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _div); */ \\\n  /* INSTALL_BINOP_TI (ti, op_pow, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _pow); */ \\\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _ldiv); \\\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _el_mul); \\\n  INSTALL_BINOP_TI (ti, op_el_div, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _el_div); \\\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _el_pow); \\\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _el_ldiv);\n\n#define OCTAVE_INSTALL_SM_INT_CMP_OPS(PFX, T1, T2)                      \\\n  INSTALL_BINOP_TI (ti, op_lt, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _lt); \\\n  INSTALL_BINOP_TI (ti, op_le, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _le); \\\n  INSTALL_BINOP_TI (ti, op_eq, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _eq); \\\n  INSTALL_BINOP_TI (ti, op_ge, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _ge); \\\n  INSTALL_BINOP_TI (ti, op_gt, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _gt); \\\n  INSTALL_BINOP_TI (ti, op_ne, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _ne);\n\n#define OCTAVE_INSTALL_SM_INT_BOOL_OPS(PFX, T1, T2)                     \\\n  INSTALL_BINOP_TI (ti, op_el_and, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _el_and); \\\n  INSTALL_BINOP_TI (ti, op_el_or, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _el_or); \\\n  INSTALL_BINOP_TI (ti, op_el_and_not, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _el_and_not); \\\n  INSTALL_BINOP_TI (ti, op_el_or_not, octave_ ## T1 ## scalar, octave_ ## T2 ## matrix, PFX ## _el_or_not);\n\n#define OCTAVE_INSTALL_SM_INT_OPS(TYPE)                                 \\\n  OCTAVE_INSTALL_SM_INT_ARITH_OPS (sm, TYPE ## _, TYPE ## _)            \\\n  OCTAVE_INSTALL_SM_INT_ARITH_OPS (smx, TYPE ## _, )                    \\\n  OCTAVE_INSTALL_SM_INT_ARITH_OPS (sxm, , TYPE ## _)                    \\\n  OCTAVE_INSTALL_SM_INT_ARITH_OPS (smfx, TYPE ## _, float_)             \\\n  OCTAVE_INSTALL_SM_INT_ARITH_OPS (sfxm, float_, TYPE ## _)             \\\n  OCTAVE_INSTALL_SM_INT_CMP_OPS (sm, TYPE ## _, TYPE ## _)              \\\n  OCTAVE_INSTALL_SM_INT_CMP_OPS (xm, , TYPE ## _)                       \\\n  OCTAVE_INSTALL_SM_INT_CMP_OPS (smx, TYPE ## _, )                      \\\n  OCTAVE_INSTALL_SM_INT_CMP_OPS (fxm, float_, TYPE ## _)                \\\n  OCTAVE_INSTALL_SM_INT_CMP_OPS (smfx, TYPE ## _, float_)               \\\n  OCTAVE_INSTALL_SM_INT_BOOL_OPS (sm, TYPE ## _, TYPE ## _)             \\\n  OCTAVE_INSTALL_SM_INT_BOOL_OPS (xm, , TYPE ## _)                      \\\n  OCTAVE_INSTALL_SM_INT_BOOL_OPS (smx, TYPE ## _, )                     \\\n  OCTAVE_INSTALL_SM_INT_BOOL_OPS (fxm, float_, TYPE ## _)               \\\n  OCTAVE_INSTALL_SM_INT_BOOL_OPS (smfx, TYPE ## _, float_)              \\\n  INSTALL_WIDENOP_TI (ti, octave_ ## TYPE ## _scalar, octave_ ## TYPE ## _matrix, TYPE ## _s_ ## TYPE ## _m_conv) \\\n  INSTALL_WIDENOP_TI (ti, octave_ ## TYPE ## _scalar, octave_complex_matrix, TYPE ## _s_complex_m_conv) \\\n  INSTALL_WIDENOP_TI (ti, octave_ ## TYPE ## _scalar, octave_float_complex_matrix, TYPE ## _s_float_complex_m_conv) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_ ## TYPE ## _matrix, octave_ ## TYPE ## _matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_matrix, octave_ ## TYPE ## _matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_float_matrix, octave_ ## TYPE ## _matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_complex_matrix, octave_complex_matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_float_complex_matrix, octave_float_complex_matrix)\n\n#define OCTAVE_INSTALL_MS_INT_ARITH_OPS(PFX, T1, T2)                    \\\n  INSTALL_BINOP_TI (ti, op_add, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _add); \\\n  INSTALL_BINOP_TI (ti, op_sub, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _sub); \\\n  INSTALL_BINOP_TI (ti, op_mul, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _mul); \\\n  INSTALL_BINOP_TI (ti, op_div, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _div); \\\n  /* INSTALL_BINOP_TI (ti, op_pow, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _pow); */ \\\n  /* INSTALL_BINOP_TI (ti, op_ldiv, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _ldiv); */ \\\n                                                                        \\\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _el_mul); \\\n  INSTALL_BINOP_TI (ti, op_el_div, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _el_div); \\\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _el_pow); \\\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _el_ldiv);\n\n#define OCTAVE_INSTALL_MS_INT_CMP_OPS(PFX, T1, T2)                      \\\n  INSTALL_BINOP_TI (ti, op_lt, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _lt); \\\n  INSTALL_BINOP_TI (ti, op_le, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _le); \\\n  INSTALL_BINOP_TI (ti, op_eq, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _eq); \\\n  INSTALL_BINOP_TI (ti, op_ge, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _ge); \\\n  INSTALL_BINOP_TI (ti, op_gt, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _gt); \\\n  INSTALL_BINOP_TI (ti, op_ne, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _ne);\n\n#define OCTAVE_INSTALL_MS_INT_BOOL_OPS(PFX, T1, T2)                     \\\n  INSTALL_BINOP_TI (ti, op_el_and, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _el_and); \\\n  INSTALL_BINOP_TI (ti, op_el_or, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _el_or); \\\n  INSTALL_BINOP_TI (ti, op_el_not_and, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _el_not_and); \\\n  INSTALL_BINOP_TI (ti, op_el_not_or, octave_ ## T1 ## matrix, octave_ ## T2 ## scalar, PFX ## _el_not_or);\n\n#define OCTAVE_INSTALL_MS_INT_ASSIGN_OPS(PFX, TLHS, TRHS)               \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign)\n\n#define OCTAVE_INSTALL_MS_INT_ASSIGNEQ_OPS(PFX, TLHS, TRHS)             \\\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign_add) \\\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign_sub) \\\n  INSTALL_ASSIGNOP_TI (ti, op_mul_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign_mul) \\\n  INSTALL_ASSIGNOP_TI (ti, op_div_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign_div)\n\n#define OCTAVE_INSTALL_MS_INT_OPS(TYPE)                                 \\\n  OCTAVE_INSTALL_MS_INT_ARITH_OPS (ms, TYPE ## _, TYPE ## _)            \\\n  OCTAVE_INSTALL_MS_INT_ARITH_OPS (msx, TYPE ## _, )                    \\\n  OCTAVE_INSTALL_MS_INT_ARITH_OPS (mxs, , TYPE ## _)                    \\\n  OCTAVE_INSTALL_MS_INT_ARITH_OPS (msfx, TYPE ## _, float_)             \\\n  OCTAVE_INSTALL_MS_INT_ARITH_OPS (mfxs, float_, TYPE ## _)             \\\n  OCTAVE_INSTALL_MS_INT_CMP_OPS (ms, TYPE ## _, TYPE ## _)              \\\n  OCTAVE_INSTALL_MS_INT_CMP_OPS (mx, TYPE ## _, )                       \\\n  OCTAVE_INSTALL_MS_INT_CMP_OPS (mxs, , TYPE ## _)                      \\\n  OCTAVE_INSTALL_MS_INT_CMP_OPS (mfx, TYPE ## _, float_)                \\\n  OCTAVE_INSTALL_MS_INT_CMP_OPS (mfxs, float_, TYPE ## _)               \\\n  OCTAVE_INSTALL_MS_INT_BOOL_OPS (ms, TYPE ## _, TYPE ## _)             \\\n  OCTAVE_INSTALL_MS_INT_BOOL_OPS (mx, TYPE ## _, )                      \\\n  OCTAVE_INSTALL_MS_INT_BOOL_OPS (mxs, , TYPE ## _)                     \\\n  OCTAVE_INSTALL_MS_INT_BOOL_OPS (mfx, TYPE ## _, float_)               \\\n  OCTAVE_INSTALL_MS_INT_BOOL_OPS (mfxs, float_, TYPE ## _)              \\\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (ms, TYPE ## _, TYPE ## _)           \\\n  OCTAVE_INSTALL_MS_INT_ASSIGNEQ_OPS (mse, TYPE ## _, TYPE ## _)        \\\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mx, TYPE ## _, )                    \\\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mfx, TYPE ## _, float_)             \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _matrix, octave_complex_scalar, octave_complex_matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _matrix, octave_float_complex_scalar, octave_float_complex_matrix)\n\n#define OCTAVE_INSTALL_M_INT_UNOPS(TYPE)                                \\\n  INSTALL_UNOP_TI (ti, op_not, octave_ ## TYPE ## _matrix, m_not);             \\\n  INSTALL_UNOP_TI (ti, op_uplus, octave_ ## TYPE ## _matrix, m_uplus);         \\\n  INSTALL_UNOP_TI (ti, op_uminus, octave_ ## TYPE ## _matrix, m_uminus);       \\\n  INSTALL_UNOP_TI (ti, op_transpose, octave_ ## TYPE ## _matrix, m_transpose); \\\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_ ## TYPE ## _matrix, m_transpose); \\\n                                                                        \\\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_ ## TYPE ## _matrix, m_incr);         \\\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_ ## TYPE ## _matrix, m_decr);         \\\n  INSTALL_NCUNOP_TI (ti, op_uminus, octave_ ## TYPE ## _matrix, m_changesign);\n\n#define OCTAVE_INSTALL_MM_INT_ARITH_OPS(PFX, T1, T2)                    \\\n  INSTALL_BINOP_TI (ti, op_add, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _add); \\\n  INSTALL_BINOP_TI (ti, op_sub, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _sub); \\\n  /* INSTALL_BINOP_TI (ti, op_mul, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _mul); */ \\\n  /* INSTALL_BINOP_TI (ti, op_div, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _div); */ \\\n  INSTALL_BINOP_TI (ti, op_pow, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _pow); \\\n  /* INSTALL_BINOP_TI (ti, op_ldiv, octave_ ## T1 ## _matrix, octave_ ## T2 ## _matrix, mm_ldiv); */ \\\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_mul); \\\n  INSTALL_BINOP_TI (ti, op_el_div, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_div); \\\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_pow); \\\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_ldiv);\n\n#define OCTAVE_INSTALL_MM_INT_CMP_OPS(PFX, T1, T2)                      \\\n  INSTALL_BINOP_TI (ti, op_lt, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _lt); \\\n  INSTALL_BINOP_TI (ti, op_le, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _le); \\\n  INSTALL_BINOP_TI (ti, op_eq, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _eq); \\\n  INSTALL_BINOP_TI (ti, op_ge, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _ge); \\\n  INSTALL_BINOP_TI (ti, op_gt, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _gt); \\\n  INSTALL_BINOP_TI (ti, op_ne, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _ne);\n\n#define OCTAVE_INSTALL_MM_INT_BOOL_OPS(PFX, T1, T2)                     \\\n  INSTALL_BINOP_TI (ti, op_el_and, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_and); \\\n  INSTALL_BINOP_TI (ti, op_el_or, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_or); \\\n  INSTALL_BINOP_TI (ti, op_el_not_and, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_not_and); \\\n  INSTALL_BINOP_TI (ti, op_el_not_or, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_not_or); \\\n  INSTALL_BINOP_TI (ti, op_el_and_not, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_and_not); \\\n  INSTALL_BINOP_TI (ti, op_el_or_not, octave_ ## T1 ## matrix, octave_ ## T2 ## matrix, PFX ## _el_or_not);\n\n#define OCTAVE_INSTALL_MM_INT_ASSIGN_OPS(PFX, TLHS, TRHS)               \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## matrix, PFX ## _assign)\n\n#define OCTAVE_INSTALL_MM_INT_ASSIGNEQ_OPS(PFX, TLHS, TRHS)             \\\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## matrix, PFX ## _assign_add) \\\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## matrix, PFX ## _assign_sub) \\\n  INSTALL_ASSIGNOP_TI (ti, op_el_mul_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## matrix, PFX ## _assign_el_mul) \\\n  INSTALL_ASSIGNOP_TI (ti, op_el_div_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## matrix, PFX ## _assign_el_div)\n\n#define OCTAVE_INSTALL_MM_INT_OPS(TYPE)                                 \\\n  OCTAVE_INSTALL_M_INT_UNOPS (TYPE)                                     \\\n  OCTAVE_INSTALL_MM_INT_ARITH_OPS (mm, TYPE ##_, TYPE ## _)             \\\n  OCTAVE_INSTALL_MM_INT_ARITH_OPS (mmx, TYPE ##_, )                     \\\n  OCTAVE_INSTALL_MM_INT_ARITH_OPS (mxm, , TYPE ##_)                     \\\n  OCTAVE_INSTALL_MM_INT_ARITH_OPS (mmfx, TYPE ##_, float_)              \\\n  OCTAVE_INSTALL_MM_INT_ARITH_OPS (mfxm, float_, TYPE ##_)              \\\n  OCTAVE_INSTALL_MM_INT_CMP_OPS (mm, TYPE ## _, TYPE ## _)              \\\n  OCTAVE_INSTALL_MM_INT_CMP_OPS (mmx, TYPE ## _, )                      \\\n  OCTAVE_INSTALL_MM_INT_CMP_OPS (mxm, , TYPE ## _)                      \\\n  OCTAVE_INSTALL_MM_INT_CMP_OPS (mmfx, TYPE ## _, float_)               \\\n  OCTAVE_INSTALL_MM_INT_CMP_OPS (mfxm, float_, TYPE ## _)               \\\n  OCTAVE_INSTALL_MM_INT_BOOL_OPS (mm, TYPE ## _, TYPE ## _)             \\\n  OCTAVE_INSTALL_MM_INT_BOOL_OPS (mmx, TYPE ## _, )                     \\\n  OCTAVE_INSTALL_MM_INT_BOOL_OPS (mxm, , TYPE ## _)                     \\\n  OCTAVE_INSTALL_MM_INT_BOOL_OPS (mmfx, TYPE ## _, float_)              \\\n  OCTAVE_INSTALL_MM_INT_BOOL_OPS (mfxm, float_, TYPE ## _)              \\\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mm, TYPE ## _, TYPE ## _)           \\\n  OCTAVE_INSTALL_MM_INT_ASSIGNEQ_OPS (mme, TYPE ## _, TYPE ## _)        \\\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmx, TYPE ## _, )                   \\\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmfx, TYPE ## _, float_)            \\\n  INSTALL_WIDENOP_TI (ti, octave_ ## TYPE ## _matrix, octave_complex_matrix, TYPE ## _m_complex_m_conv) \\\n  INSTALL_WIDENOP_TI (ti, octave_ ## TYPE ## _matrix, octave_float_complex_matrix, TYPE ## _m_float_complex_m_conv) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _matrix, octave_complex_matrix, octave_complex_matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _matrix, octave_float_complex_matrix, octave_float_complex_matrix)\n\n#define OCTAVE_INSTALL_RE_INT_ASSIGN_OPS(TYPE)                          \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_ ## TYPE ## _scalar, TYPE ## ms_assign) \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_ ## TYPE ## _matrix, TYPE ## mm_assign) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_ ## TYPE ## _scalar, octave_matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_matrix, octave_ ## TYPE ## _matrix, octave_matrix)\n\n#define OCTAVE_INSTALL_FLT_RE_INT_ASSIGN_OPS(TYPE)                      \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_matrix, octave_ ## TYPE ## _scalar, TYPE ## fms_assign) \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_matrix, octave_ ## TYPE ## _matrix, TYPE ## fmm_assign) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_ ## TYPE ## _scalar, octave_float_matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_matrix, octave_ ## TYPE ## _matrix, octave_float_matrix)\n\n#define OCTAVE_INSTALL_CX_INT_ASSIGN_OPS(TYPE)                          \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix, octave_ ## TYPE ## _scalar, TYPE ## cms_assign) \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_complex_matrix, octave_ ## TYPE ## _matrix, TYPE ## cmm_assign) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex_scalar, octave_ ## TYPE ## _scalar, octave_complex_matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_complex_matrix, octave_ ## TYPE ## _matrix, octave_complex_matrix)\n\n#define OCTAVE_INSTALL_FLT_CX_INT_ASSIGN_OPS(TYPE)                      \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix, octave_ ## TYPE ## _scalar, TYPE ## fcms_assign) \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix, octave_ ## TYPE ## _matrix, TYPE ## fcmm_assign) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex_scalar, octave_ ## TYPE ## _scalar, octave_complex_matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_complex_matrix, octave_ ## TYPE ## _matrix, octave_complex_matrix)\n\n#define OCTAVE_INSTALL_INT_NULL_ASSIGN_OPS(TYPE)                        \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_matrix, TYPE ## null_assign) \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_str, TYPE ## null_assign) \\\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_sq_str, TYPE ## null_assign) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TYPE ## _scalar, octave_null_matrix, octave_ ## TYPE ## _matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_## TYPE ## _scalar, octave_null_str, octave_ ## TYPE ## _matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_## TYPE ## _scalar, octave_null_sq_str, octave_ ## TYPE ## _matrix)\n\n#define OCTAVE_INSTALL_INT_OPS(TYPE)            \\\n  OCTAVE_INSTALL_SS_INT_OPS (TYPE)              \\\n  OCTAVE_INSTALL_SM_INT_OPS (TYPE)              \\\n  OCTAVE_INSTALL_MS_INT_OPS (TYPE)              \\\n  OCTAVE_INSTALL_MM_INT_OPS (TYPE)              \\\n  OCTAVE_INSTALL_CONCAT_FN (TYPE)               \\\n  OCTAVE_INSTALL_RE_INT_ASSIGN_OPS (TYPE)       \\\n  OCTAVE_INSTALL_FLT_RE_INT_ASSIGN_OPS (TYPE)   \\\n  OCTAVE_INSTALL_CX_INT_ASSIGN_OPS (TYPE)       \\\n  OCTAVE_INSTALL_FLT_CX_INT_ASSIGN_OPS (TYPE)   \\\n  OCTAVE_INSTALL_INT_NULL_ASSIGN_OPS(TYPE)\n\n#define OCTAVE_INSTALL_SM_INT_ASSIGNCONV(TLHS, TRHS)                    \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TLHS ## _scalar, octave_ ## TRHS ## _scalar, octave_ ## TLHS ## _matrix) \\\n  INSTALL_ASSIGNCONV_TI (ti, octave_ ## TLHS ## _scalar, octave_ ## TRHS ## _matrix, octave_ ## TLHS ## _matrix)\n\n#define OCTAVE_MIXED_INT_CMP_OPS(T1, T2)                                \\\n  OCTAVE_SS_INT_CMP_OPS (T1 ## _ ## T2 ## _ss, T1 ## _, T2 ## _)        \\\n  OCTAVE_SM_INT_CMP_OPS (T1 ## _ ## T2 ## _sm, T1 ## _, T2 ## _)        \\\n  OCTAVE_MS_INT_CMP_OPS (T1 ## _ ## T2 ## _ms, T1 ## _, T2 ## _)        \\\n  OCTAVE_MM_INT_CMP_OPS (T1 ## _ ## T2 ## _mm, T1 ## _, T2 ## _)\n\n#define OCTAVE_INSTALL_MIXED_INT_CMP_OPS(T1, T2)                        \\\n  OCTAVE_INSTALL_SS_INT_CMP_OPS (T1 ## _ ## T2 ## _ss, T1 ## _, T2 ## _) \\\n  OCTAVE_INSTALL_SM_INT_CMP_OPS (T1 ## _ ## T2 ## _sm, T1 ## _, T2 ## _) \\\n  OCTAVE_INSTALL_MS_INT_CMP_OPS (T1 ## _ ## T2 ## _ms, T1 ## _, T2 ## _) \\\n  OCTAVE_INSTALL_MM_INT_CMP_OPS (T1 ## _ ## T2 ## _mm, T1 ## _, T2 ## _)\n\n#endif\n"
  },
  {
    "path": "libinterp/operators/op-m-cdm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-re-mat.h\"\n#define RINCLUDE \"ov-cx-diag.h\"\n\n#define LMATRIX matrix\n#define RMATRIX complex_diag_matrix\n#define LDMATRIX complex_matrix\n\n#define LSHORT m\n#define RSHORT cdm\n\n#define DEFINEDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-m-cm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-m-cm.h\"\n#include \"mx-cm-m.h\"\n#include \"mx-nda-cnda.h\"\n#include \"mx-cnda-nda.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix by complex matrix ops.\n\nDEFNDBINOP_OP (add, matrix, complex_matrix, array, complex_array, +)\nDEFNDBINOP_OP (sub, matrix, complex_matrix, array, complex_array, -)\n\nDEFBINOP_OP (mul, matrix, complex_matrix, *)\n\nDEFBINOP (trans_mul, matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  Matrix m1 = v1.matrix_value ();\n  ComplexMatrix m2 = v2.complex_matrix_value ();\n\n  return ComplexMatrix (xgemm (m1, real (m2), blas_trans, blas_no_trans),\n                        xgemm (m1, imag (m2), blas_trans, blas_no_trans));\n}\n\nDEFBINOP (div, matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  ComplexMatrix ret = xdiv (v1.matrix_value (),\n                            v2.complex_matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, matrix, complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (v1.matrix_value (),\n                                v2.complex_matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP (trans_ldiv, matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (v1.matrix_value (),\n                                v2.complex_matrix_value (), typ, blas_trans);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, matrix, complex_matrix, array, complex_array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, matrix, complex_matrix, array, complex_array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, matrix, complex_matrix, array, complex_array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, matrix, complex_matrix, array, complex_array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, matrix, complex_matrix, array, complex_array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, matrix, complex_matrix, array, complex_array, mx_el_ne)\n\nDEFNDBINOP_FN (el_mul, matrix, complex_matrix, array, complex_array, product)\nDEFNDBINOP_FN (el_div, matrix, complex_matrix, array, complex_array, quotient)\nDEFNDBINOP_FN (el_pow, matrix, complex_matrix, array, complex_array, elem_xpow)\n\nDEFBINOP (el_ldiv, matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return quotient (v2.complex_array_value (), v1.array_value ());\n}\n\nDEFNDBINOP_FN (el_and, matrix, complex_matrix, array, complex_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  matrix, complex_matrix, array, complex_array, mx_el_or)\n\nDEFNDCATOP_FN (m_cm, matrix, complex_matrix, array, complex_array, concat)\n\nDEFCONV (complex_matrix_conv, matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v, a);\n\n  return new octave_complex_matrix (ComplexNDArray (v.array_value ()));\n}\n\nvoid\ninstall_m_cm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_matrix, octave_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_matrix, octave_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_matrix, octave_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_matrix, octave_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_matrix, octave_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_matrix, octave_complex_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_matrix, octave_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_matrix, octave_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_matrix, octave_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_matrix, octave_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_matrix, octave_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_matrix, octave_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_matrix, octave_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_matrix, octave_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_matrix, octave_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_matrix, octave_complex_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_matrix, octave_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_matrix, octave_complex_matrix, el_or);\n  INSTALL_BINOP_TI (ti, op_trans_mul, octave_matrix, octave_complex_matrix,\n                    trans_mul);\n  INSTALL_BINOP_TI (ti, op_herm_mul, octave_matrix, octave_complex_matrix,\n                    trans_mul);\n  INSTALL_BINOP_TI (ti, op_trans_ldiv, octave_matrix, octave_complex_matrix,\n                    trans_ldiv);\n  INSTALL_BINOP_TI (ti, op_herm_ldiv, octave_matrix, octave_complex_matrix,\n                    trans_ldiv);\n\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_complex_matrix, m_cm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_matrix, octave_complex_matrix,\n                         octave_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_matrix, octave_complex_matrix,\n                         octave_float_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_matrix, octave_complex_matrix,\n                      complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-m-cs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-m-cs.h\"\n#include \"mx-cs-m.h\"\n#include \"mx-nda-cs.h\"\n#include \"mx-cs-nda.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-complex.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix by complex scalar ops.\n\nDEFNDBINOP_OP (add, matrix, complex, array, complex, +)\nDEFNDBINOP_OP (sub, matrix, complex, array, complex, -)\nDEFNDBINOP_OP (mul, matrix, complex, array, complex, *)\n\nDEFBINOP (div, matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.array_value () / v2.complex_value ());\n}\n\nDEFBINOP_FN (pow, matrix, complex, xpow)\n\nDEFBINOP (ldiv, matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  Matrix m1 = v1.matrix_value ();\n  ComplexMatrix m2 = v2.complex_matrix_value ();\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (m1, m2, typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDCMPLXCMPOP_FN (lt, matrix, complex, array, complex, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, matrix, complex, array, complex, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, matrix, complex, array, complex, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, matrix, complex, array, complex, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, matrix, complex, array, complex, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, matrix, complex, array, complex, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, matrix, complex, array, complex, *)\n\nDEFBINOP (el_div, matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.array_value () / v2.complex_value ());\n}\n\nDEFNDBINOP_FN (el_pow, matrix, complex, array, complex, elem_xpow)\n\nDEFBINOP (el_ldiv, matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return elem_xdiv (v2.complex_value (), v1.array_value ());\n}\n\nDEFNDBINOP_FN (el_and, matrix, complex, array, complex, mx_el_and)\nDEFNDBINOP_FN (el_or, matrix, complex, array, complex, mx_el_or)\n\nDEFNDCATOP_FN (m_cs, matrix, complex, array, complex_array, concat)\n\nvoid\ninstall_m_cs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_matrix, octave_complex, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_matrix, octave_complex, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_matrix, octave_complex, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_matrix, octave_complex, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_matrix, octave_complex, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_matrix, octave_complex, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_matrix, octave_complex, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_matrix, octave_complex, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_matrix, octave_complex, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_matrix, octave_complex, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_matrix, octave_complex, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_matrix, octave_complex, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_matrix, octave_complex, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_matrix, octave_complex, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_matrix, octave_complex, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_matrix, octave_complex, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_matrix, octave_complex, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_matrix, octave_complex, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_complex, m_cs);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_matrix, octave_complex,\n                         octave_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_matrix, octave_complex,\n                         octave_float_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-m-dm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define LINCLUDE \"ov-re-mat.h\"\n#define RINCLUDE \"ov-re-diag.h\"\n\n#define LMATRIX matrix\n#define RMATRIX diag_matrix\n\n#define LSHORT m\n#define RSHORT dm\n\n#define DEFINEDIV\n\n#include \"op-dm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-m-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix unary ops.\n\nDEFNDUNOP_OP (not, matrix, array, !)\nDEFNDUNOP_OP (uplus, matrix, array, /* no-op */)\nDEFNDUNOP_OP (uminus, matrix, array, -)\n\nDEFUNOP (transpose, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"transpose not defined for N-D objects\");\n\n  return octave_value (v.matrix_value ().transpose ());\n}\n\nDEFNCUNOP_METHOD (incr, matrix, increment)\nDEFNCUNOP_METHOD (decr, matrix, decrement)\nDEFNCUNOP_METHOD (changesign, matrix, changesign)\n\n// matrix by matrix ops.\n\nDEFNDBINOP_OP (add, matrix, matrix, array, array, +)\nDEFNDBINOP_OP (sub, matrix, matrix, array, array, -)\n\nDEFBINOP_OP (mul, matrix, matrix, *)\n\nDEFBINOP (div, matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  Matrix ret = xdiv (v1.matrix_value (), v2.matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, matrix, matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  Matrix ret = xleftdiv (v1.matrix_value (), v2.matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP (trans_mul, matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  return octave_value(xgemm (v1.matrix_value (), v2.matrix_value (),\n                             blas_trans, blas_no_trans));\n}\n\nDEFBINOP (mul_trans, matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  return octave_value(xgemm (v1.matrix_value (), v2.matrix_value (),\n                             blas_no_trans, blas_trans));\n}\n\nDEFBINOP (trans_ldiv, matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  Matrix ret = xleftdiv (v1.matrix_value (), v2.matrix_value (),\n                         typ, blas_trans);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDBINOP_FN (lt, matrix, matrix, array, array, mx_el_lt)\nDEFNDBINOP_FN (le, matrix, matrix, array, array, mx_el_le)\nDEFNDBINOP_FN (eq, matrix, matrix, array, array, mx_el_eq)\nDEFNDBINOP_FN (ge, matrix, matrix, array, array, mx_el_ge)\nDEFNDBINOP_FN (gt, matrix, matrix, array, array, mx_el_gt)\nDEFNDBINOP_FN (ne, matrix, matrix, array, array, mx_el_ne)\n\nDEFNDBINOP_FN (el_mul, matrix, matrix, array, array, product)\nDEFNDBINOP_FN (el_div, matrix, matrix, array, array, quotient)\nDEFNDBINOP_FN (el_pow, matrix, matrix, array, array, elem_xpow)\n\nDEFBINOP (el_ldiv, matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return octave_value (quotient (v2.array_value (), v1.array_value ()));\n}\n\nDEFNDBINOP_FN (el_and, matrix, matrix, array, array, mx_el_and)\nDEFNDBINOP_FN (el_or,  matrix, matrix, array, array, mx_el_or)\nDEFNDBINOP_FN (el_not_and, matrix, matrix, array, array, mx_el_not_and)\nDEFNDBINOP_FN (el_not_or,  matrix, matrix, array, array, mx_el_not_or)\nDEFNDBINOP_FN (el_and_not, matrix, matrix, array, array, mx_el_and_not)\nDEFNDBINOP_FN (el_or_not,  matrix, matrix, array, array, mx_el_or_not)\n\nDEFNDCATOP_FN (m_m, matrix, matrix, array, array, concat)\n\nDEFNDASSIGNOP_FN (assign, matrix, matrix, array, assign)\nDEFNDASSIGNOP_FN (sgl_assign, float_matrix, matrix, float_array, assign)\n\nDEFNULLASSIGNOP_FN (null_assign, matrix, delete_elements)\n\nDEFNDASSIGNOP_OP (assign_add, matrix, matrix, array, +=)\nDEFNDASSIGNOP_OP (assign_sub, matrix, matrix, array, -=)\nDEFNDASSIGNOP_FNOP (assign_el_mul, matrix, matrix, array, product_eq)\nDEFNDASSIGNOP_FNOP (assign_el_div, matrix, matrix, array, quotient_eq)\n\nvoid\ninstall_m_m_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_matrix, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_matrix, transpose);\n\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_matrix, incr);\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_matrix, decr);\n  INSTALL_NCUNOP_TI (ti, op_uminus, octave_matrix, changesign);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_matrix, octave_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_matrix, octave_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_matrix, octave_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_matrix, octave_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_matrix, octave_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_matrix, octave_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_matrix, octave_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_matrix, octave_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_matrix, octave_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_matrix, octave_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_matrix, octave_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_matrix, octave_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_matrix, octave_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_matrix, octave_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_matrix, octave_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_matrix, octave_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_matrix, octave_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_matrix, octave_matrix, el_or);\n  INSTALL_BINOP_TI (ti, op_el_and_not, octave_matrix, octave_matrix, el_and_not);\n  INSTALL_BINOP_TI (ti, op_el_or_not, octave_matrix, octave_matrix, el_or_not);\n  INSTALL_BINOP_TI (ti, op_el_not_and, octave_matrix, octave_matrix, el_not_and);\n  INSTALL_BINOP_TI (ti, op_el_not_or, octave_matrix, octave_matrix, el_not_or);\n  INSTALL_BINOP_TI (ti, op_trans_mul, octave_matrix, octave_matrix, trans_mul);\n  INSTALL_BINOP_TI (ti, op_mul_trans, octave_matrix, octave_matrix, mul_trans);\n  INSTALL_BINOP_TI (ti, op_herm_mul, octave_matrix, octave_matrix, trans_mul);\n  INSTALL_BINOP_TI (ti, op_mul_herm, octave_matrix, octave_matrix, mul_trans);\n  INSTALL_BINOP_TI (ti, op_trans_ldiv, octave_matrix, octave_matrix, trans_ldiv);\n  INSTALL_BINOP_TI (ti, op_herm_ldiv, octave_matrix, octave_matrix, trans_ldiv);\n\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_matrix, m_m);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_matrix, assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_matrix, octave_matrix,\n                       sgl_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_null_matrix,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_null_str,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_null_sq_str,\n                       null_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_matrix, octave_matrix, assign_add);\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_matrix, octave_matrix, assign_sub);\n  INSTALL_ASSIGNOP_TI (ti, op_el_mul_eq, octave_matrix, octave_matrix,\n                       assign_el_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_el_div_eq, octave_matrix, octave_matrix,\n                       assign_el_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-m-pm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define MINCLUDE \"ov-re-mat.h\"\n\n#define LMATRIX matrix\n#define RMATRIX perm_matrix\n\n#define LSHORT m\n#define RSHORT pm\n\n#define RIGHT\n\n#include \"op-pm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-m-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix by scalar ops.\n\nDEFNDBINOP_OP (add, matrix, scalar, array, scalar, +)\nDEFNDBINOP_OP (sub, matrix, scalar, array, scalar, -)\nDEFNDBINOP_OP (mul, matrix, scalar, array, scalar, *)\n\nDEFBINOP (div, matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.array_value () / v2.double_value ());\n}\n\nDEFBINOP_FN (pow, matrix, scalar, xpow)\n\nDEFBINOP (ldiv, matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  Matrix m1 = v1.matrix_value ();\n  Matrix m2 = v2.matrix_value ();\n  MatrixType typ = v1.matrix_type ();\n\n  Matrix ret = xleftdiv (m1, m2, typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFNDBINOP_FN (lt, matrix, scalar, array, scalar, mx_el_lt)\nDEFNDBINOP_FN (le, matrix, scalar, array, scalar, mx_el_le)\nDEFNDBINOP_FN (eq, matrix, scalar, array, scalar, mx_el_eq)\nDEFNDBINOP_FN (ge, matrix, scalar, array, scalar, mx_el_ge)\nDEFNDBINOP_FN (gt, matrix, scalar, array, scalar, mx_el_gt)\nDEFNDBINOP_FN (ne, matrix, scalar, array, scalar, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, matrix, scalar, array, scalar, *)\n\nDEFBINOP (el_div, matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.array_value () / v2.double_value ());\n}\n\nDEFNDBINOP_FN (el_pow, matrix, scalar, array, scalar, elem_xpow)\n\nDEFBINOP (el_ldiv, matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return elem_xdiv (v2.double_value (), v1.array_value ());\n}\n\nDEFNDBINOP_FN (el_and, matrix, scalar, array, scalar, mx_el_and)\nDEFNDBINOP_FN (el_or, matrix, scalar, array, scalar, mx_el_or)\n\nDEFNDCATOP_FN (m_s, matrix, scalar, array, array, concat)\n\nDEFNDASSIGNOP_FN (assign, matrix, scalar, scalar, assign)\nDEFNDASSIGNOP_FN (sgl_assign, float_matrix, scalar, float_scalar, assign)\nDEFNDASSIGNOP_FN (clx_sgl_assign, float_complex_matrix, scalar, float_complex,\n                  assign)\n\nDEFNDASSIGNOP_OP (assign_add, matrix, scalar, scalar, +=)\nDEFNDASSIGNOP_OP (assign_sub, matrix, scalar, scalar, -=)\nDEFNDASSIGNOP_OP (assign_mul, matrix, scalar, scalar, *=)\nDEFNDASSIGNOP_OP (assign_div, matrix, scalar, scalar, /=)\n\nvoid\ninstall_m_s_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_matrix, octave_scalar, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_matrix, octave_scalar, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_matrix, octave_scalar, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_matrix, octave_scalar, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_matrix, octave_scalar, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_matrix, octave_scalar, ldiv);\n\n  INSTALL_BINOP_TI (ti, op_lt, octave_matrix, octave_scalar, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_matrix, octave_scalar, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_matrix, octave_scalar, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_matrix, octave_scalar, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_matrix, octave_scalar, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_matrix, octave_scalar, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_matrix, octave_scalar, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_matrix, octave_scalar, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_matrix, octave_scalar, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_matrix, octave_scalar, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_matrix, octave_scalar, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_matrix, octave_scalar, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_scalar, m_s);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_scalar, assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_matrix, octave_scalar,\n                       sgl_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_float_complex_matrix, octave_scalar,\n                       clx_sgl_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_add_eq, octave_matrix, octave_scalar, assign_add);\n  INSTALL_ASSIGNOP_TI (ti, op_sub_eq, octave_matrix, octave_scalar, assign_sub);\n  INSTALL_ASSIGNOP_TI (ti, op_mul_eq, octave_matrix, octave_scalar, assign_mul);\n  INSTALL_ASSIGNOP_TI (ti, op_div_eq, octave_matrix, octave_scalar, assign_div);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-m-scm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-scm-m.h\"\n#include \"smx-m-scm.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix by sparse complex matrix ops.\n\nDEFBINOP_OP (add, matrix, sparse_complex_matrix, +)\nDEFBINOP_OP (sub, matrix, sparse_complex_matrix, -)\n\nDEFBINOP_OP (mul, matrix, sparse_complex_matrix, *)\n\nDEFBINOP (div, matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.array_value () / v2.complex_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n\n      ComplexMatrix ret = xdiv (v1.matrix_value (),\n                                v2.sparse_complex_matrix_value (), typ);\n\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOPX (pow, matrix, sparse_complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  ComplexMatrix ret = xleftdiv (v1.matrix_value (),\n                                v2.complex_matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (lt, matrix, sparse_complex_matrix, mx_el_lt)\nDEFBINOP_FN (le, matrix, sparse_complex_matrix, mx_el_le)\nDEFBINOP_FN (eq, matrix, sparse_complex_matrix, mx_el_eq)\nDEFBINOP_FN (ge, matrix, sparse_complex_matrix, mx_el_ge)\nDEFBINOP_FN (gt, matrix, sparse_complex_matrix, mx_el_gt)\nDEFBINOP_FN (ne, matrix, sparse_complex_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, matrix, sparse_complex_matrix, product)\nDEFBINOP_FN (el_div, matrix, sparse_complex_matrix, quotient)\n\nDEFBINOP (el_pow, matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return octave_value\n         (elem_xpow (SparseMatrix (v1.matrix_value ()),\n                     v2.sparse_complex_matrix_value ()));\n}\n\nDEFBINOP (el_ldiv, matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n  return octave_value\n         (quotient (v2.sparse_complex_matrix_value (), v1.matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, matrix, sparse_complex_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  matrix, sparse_complex_matrix, mx_el_or)\n\nDEFCATOP (m_scm, matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n  SparseMatrix tmp (v1.matrix_value ());\n  return octave_value (tmp. concat (v2.sparse_complex_matrix_value (),\n                                    ra_idx));\n}\n\nDEFCONV (sparse_complex_matrix_conv, matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v, a);\n  return new octave_sparse_complex_matrix\n         (SparseComplexMatrix (v.complex_matrix_value ()));\n}\n\nvoid\ninstall_m_scm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_matrix, octave_sparse_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_matrix, octave_sparse_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_matrix, octave_sparse_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_matrix, octave_sparse_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_matrix, octave_sparse_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_matrix, octave_sparse_complex_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_matrix, octave_sparse_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_matrix, octave_sparse_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_matrix, octave_sparse_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_matrix, octave_sparse_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_matrix, octave_sparse_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_matrix, octave_sparse_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_matrix, octave_sparse_complex_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_matrix, octave_sparse_complex_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_matrix, octave_sparse_complex_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_matrix, octave_sparse_complex_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_matrix, octave_sparse_complex_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_matrix, octave_sparse_complex_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_sparse_complex_matrix, m_scm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_matrix, octave_sparse_complex_matrix,\n                         octave_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_matrix, octave_sparse_complex_matrix,\n                      sparse_complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-m-sm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-re-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-sm-m.h\"\n#include \"smx-m-sm.h\"\n#include \"ov-re-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// matrix by sparse matrix ops.\n\nDEFBINOP_OP (add, matrix, sparse_matrix, +)\nDEFBINOP_OP (sub, matrix, sparse_matrix, -)\n\nDEFBINOP_OP (mul, matrix, sparse_matrix, *)\n\nDEFBINOP (div, matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.array_value () / v2.scalar_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n\n      Matrix ret = xdiv (v1.matrix_value (), v2.sparse_matrix_value (), typ);\n\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOPX (pow, matrix, sparse_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  MatrixType typ = v1.matrix_type ();\n\n  Matrix ret = xleftdiv (v1.matrix_value (), v2.matrix_value (), typ);\n\n  v1.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (mul_trans, matrix, sparse_matrix, mul_trans);\n\nDEFBINOP_FN (lt, matrix, sparse_matrix, mx_el_lt)\nDEFBINOP_FN (le, matrix, sparse_matrix, mx_el_le)\nDEFBINOP_FN (eq, matrix, sparse_matrix, mx_el_eq)\nDEFBINOP_FN (ge, matrix, sparse_matrix, mx_el_ge)\nDEFBINOP_FN (gt, matrix, sparse_matrix, mx_el_gt)\nDEFBINOP_FN (ne, matrix, sparse_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, matrix, sparse_matrix, product)\nDEFBINOP_FN (el_div, matrix, sparse_matrix, quotient)\n\nDEFBINOP (el_pow, matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  return octave_value (elem_xpow (SparseMatrix (v1.matrix_value ()),\n                                  v2.sparse_matrix_value ()));\n}\n\nDEFBINOP (el_ldiv, matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  return octave_value\n         (quotient (v2.sparse_matrix_value (), v1.matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, matrix, sparse_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  matrix, sparse_matrix, mx_el_or)\n\nDEFCATOP (m_sm, matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  SparseMatrix tmp (v1.matrix_value ());\n  return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));\n}\n\nDEFCONV (sparse_matrix_conv, matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v, a);\n  return new octave_sparse_matrix (SparseMatrix (v.matrix_value ()));\n}\n\nDEFNDASSIGNOP_FN (assign, matrix, sparse_matrix, array, assign)\n\nvoid\ninstall_m_sm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_matrix, octave_sparse_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_matrix, octave_sparse_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_matrix, octave_sparse_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_matrix, octave_sparse_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_matrix, octave_sparse_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_matrix, octave_sparse_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_mul_trans, octave_matrix, octave_sparse_matrix,\n                    mul_trans);\n  INSTALL_BINOP_TI (ti, op_mul_herm, octave_matrix, octave_sparse_matrix,\n                    mul_trans);\n  INSTALL_BINOP_TI (ti, op_lt, octave_matrix, octave_sparse_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_matrix, octave_sparse_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_matrix, octave_sparse_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_matrix, octave_sparse_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_matrix, octave_sparse_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_matrix, octave_sparse_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_matrix, octave_sparse_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_matrix, octave_sparse_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_matrix, octave_sparse_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_matrix, octave_sparse_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_matrix, octave_sparse_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_matrix, octave_sparse_matrix,  el_or);\n\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_sparse_matrix, m_sm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_sparse_matrix, assign)\n  INSTALL_ASSIGNCONV_TI (ti, octave_matrix, octave_sparse_matrix, octave_matrix)\n\n  INSTALL_WIDENOP_TI (ti, octave_matrix, octave_sparse_matrix,\n                      sparse_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-mi.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ops.h\"\n#include \"ov-magic-int.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Magic integer unary ops.  Only + and - are allowed so that\n// expressions like\n//\n//   int64 (-9007199254740994)\n//\n// produce proper int64 constants.\n\nstatic octave_value\noct_unop_unsigned_uplus (const octave_base_value& a)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_magic_uint&, v, a);\n  // no-op.\n  // FIXME: but can we do this just by incrementing the reference count?\n  return octave_value (v.clone ());\n}\n\nstatic octave_value\noct_unop_unsigned_uminus (const octave_base_value& a)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_magic_uint&, v, a);\n\n  // We are storing a uint64 value, so some fakery is needed here.\n  // Is there a better way?\n\n  // FIXME: Maybe there should also be octave_magic_int::as_TYPE_value\n  // functions?\n  octave_uint64 val (v.scalar_ref ());\n\n  uint64_t ival = val.value ();\n\n  static constexpr uint64_t max_val\n    = static_cast<uint64_t> (std::numeric_limits<int64_t>::max ());\n\n  static constexpr uint64_t max_val_p1 = max_val + 1;\n\n  if (ival <= max_val)\n    {\n      int64_t signed_ival = ival;\n      return octave_value (new octave_magic_int (-signed_ival));\n    }\n\n  if (ival == max_val_p1)\n    {\n      // Correctly capture intmin.  For example, negating uint8(128)\n      // should return int8(-128) but converting directly to int8 and\n      // negating will not return the correct result.\n\n      static constexpr int64_t min_signed_ival\n        = std::numeric_limits<int64_t>::min ();\n\n      return octave_value (new octave_magic_int (min_signed_ival));\n    }\n\n  return octave_value (-static_cast<double> (ival));\n}\n\nstatic octave_value\noct_unop_signed_uplus (const octave_base_value& a)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_magic_int&, v, a);\n  // no-op.\n  // FIXME: but can we do this just by incrementing the reference count?\n  return octave_value (v.clone ());\n}\n\nstatic octave_value\noct_unop_signed_uminus (const octave_base_value& a)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_magic_int&, v, a);\n\n  // FIXME: Maybe there should also be octave_magic_int::as_TYPE_value\n  // functions?\n  octave_int64 val (v.scalar_ref ());\n\n  return octave_value (new octave_magic_int (-val));\n}\n\nvoid\ninstall_mi_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_uplus, octave_magic_uint, unsigned_uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_magic_uint, unsigned_uminus);\n\n  INSTALL_UNOP_TI (ti, op_uplus, octave_magic_int, signed_uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_magic_int, signed_uminus);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-pm-cm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define MINCLUDE \"ov-cx-mat.h\"\n\n#define LMATRIX perm_matrix\n#define RMATRIX complex_matrix\n\n#define LSHORT pm\n#define RSHORT cm\n\n#define LEFT\n\n#include \"op-pm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-pm-fcm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define MINCLUDE \"ov-flt-cx-mat.h\"\n\n#define LMATRIX perm_matrix\n#define RMATRIX float_complex_matrix\n\n#define LSHORT pm\n#define RSHORT fcm\n\n#define LEFT\n\n#include \"op-pm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-pm-fm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define MINCLUDE \"ov-flt-re-mat.h\"\n\n#define LMATRIX perm_matrix\n#define RMATRIX float_matrix\n\n#define LSHORT pm\n#define RSHORT fm\n\n#define LEFT\n\n#include \"op-pm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-pm-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#define MINCLUDE \"ov-re-mat.h\"\n\n#define LMATRIX perm_matrix\n#define LDMATRIX matrix\n#define RMATRIX matrix\n\n#define LSHORT pm\n#define RSHORT m\n\n#define LEFT\n#define DEFINENULLASSIGNCONV\n\n#include \"op-pm-template.cc\"\n"
  },
  {
    "path": "libinterp/operators/op-pm-pm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-perm.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFUNOP (transpose, perm_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v, a);\n  return octave_value (v.perm_matrix_value ().transpose ());\n}\n\nDEFBINOP_OP (mul, perm_matrix, perm_matrix, *)\n\nDEFBINOP (div, perm_matrix, perm_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);\n\n  return (v1.perm_matrix_value () * v2.perm_matrix_value ().inverse ());\n}\n\nDEFBINOP (ldiv, perm_matrix, perm_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);\n\n  return (v1.perm_matrix_value ().inverse () * v2.perm_matrix_value ());\n}\n\nDEFBINOP (pow, perm_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return xpow (v1.perm_matrix_value (), v2.scalar_value ());\n}\n\nCONVDECL (perm_matrix_to_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v, a);\n\n  return new octave_matrix (v.matrix_value ());\n}\n\nvoid\ninstall_pm_pm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_transpose, octave_perm_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_perm_matrix, transpose);\n\n  INSTALL_BINOP_TI (ti, op_mul, octave_perm_matrix, octave_perm_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_perm_matrix, octave_perm_matrix, div);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_perm_matrix, octave_perm_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_pow, octave_perm_matrix, octave_scalar, pow);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_perm_matrix, octave_matrix, octave_matrix);\n  INSTALL_WIDENOP_TI (ti, octave_perm_matrix, octave_matrix,\n                      perm_matrix_to_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-pm-scm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\n#include \"ov-perm.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// permutation matrix by sparse matrix ops\n\nDEFBINOP (mul_pm_scm, perm_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    {\n      std::complex<double> d = v2.complex_value ();\n\n      return octave_value (v1.sparse_matrix_value () * d);\n    }\n  else if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.sparse_complex_matrix_value ());\n  else\n    return v1.perm_matrix_value  () * v2.sparse_complex_matrix_value ();\n}\n\nDEFBINOP (ldiv_pm_scm, perm_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return v1.perm_matrix_value ().inverse () * v2.sparse_complex_matrix_value ();\n}\n\n// sparse matrix by diagonal matrix ops\n\nDEFBINOP (mul_scm_pm, sparse_complex_matrix, perm_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    {\n      std::complex<double> d = v1.scalar_value ();\n\n      return octave_value (d * v2.sparse_matrix_value ());\n    }\n  else if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_complex_matrix_value ());\n  else\n    return v1.sparse_complex_matrix_value  () * v2.perm_matrix_value ();\n}\n\nDEFBINOP (div_scm_pm, sparse_complex_matrix, perm_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);\n\n  return v1.sparse_complex_matrix_value () * v2.perm_matrix_value ().inverse ();\n}\n\nvoid\ninstall_pm_scm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_mul, octave_perm_matrix, octave_sparse_complex_matrix,\n                    mul_pm_scm);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_perm_matrix, octave_sparse_complex_matrix,\n                    ldiv_pm_scm);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_complex_matrix, octave_perm_matrix,\n                    mul_scm_pm);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_complex_matrix, octave_perm_matrix,\n                    div_scm_pm);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-pm-sm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\n#include \"ov-perm.h\"\n#include \"ov-re-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// permutation matrix by sparse matrix ops\n\nDEFBINOP (mul_pm_sm, perm_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    {\n      double d = v2.scalar_value ();\n\n      return octave_value (v1.sparse_matrix_value () * d);\n    }\n  else if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.sparse_matrix_value ());\n  else\n    return v1.perm_matrix_value  () * v2.sparse_matrix_value ();\n}\n\nDEFBINOP (ldiv_pm_sm, perm_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  return v1.perm_matrix_value ().inverse () * v2.sparse_matrix_value ();\n}\n\n// sparse matrix by diagonal matrix ops\n\nDEFBINOP (mul_sm_pm, sparse_matrix, perm_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    {\n      double d = v1.scalar_value ();\n\n      return octave_value (d * v2.sparse_matrix_value ());\n    }\n  else if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_matrix_value ());\n  else\n    return v1.sparse_matrix_value  () * v2.perm_matrix_value ();\n}\n\nDEFBINOP (div_sm_pm, sparse_matrix, perm_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);\n\n  return v1.sparse_matrix_value () * v2.perm_matrix_value ().inverse ();\n}\n\nvoid\ninstall_pm_sm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_mul, octave_perm_matrix, octave_sparse_matrix,\n                    mul_pm_sm);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_perm_matrix, octave_sparse_matrix,\n                    ldiv_pm_sm);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_matrix, octave_perm_matrix,\n                    mul_sm_pm);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_matrix, octave_perm_matrix,\n                    div_sm_pm);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-pm-template.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// FIXME: it might be nice to only include the declarations of the\n// operators that are actually needed instead of including all of them.\n#include \"mx-ops.h\"\n\n#include \"ov-perm.h\"\n#include MINCLUDE\n#include \"ops.h\"\n#if defined (DEFINENULLASSIGNCONV)\n#  include \"ov-null-mat.h\"\n#endif\n\n#if ! defined (LDMATRIX)\n#  define LDMATRIX LMATRIX\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#define OCTAVE_LMATRIX CONCAT2(octave_, LMATRIX)\n#define OCTAVE_LDMATRIX CONCAT2(octave_, LDMATRIX)\n#define OCTAVE_RMATRIX CONCAT2(octave_, RMATRIX)\n#if defined (LEFT)\n#  define LMATRIX_VALUE perm_matrix_value\n#  define RMATRIX_VALUE CONCAT2(RMATRIX, _value)\n#else\n#  define LMATRIX_VALUE CONCAT2(LMATRIX, _value)\n#  define RMATRIX_VALUE perm_matrix_value\n#endif\n\nDEFBINOP (mul, LMATRIX, RMATRIX)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);\n\n  return v1.LMATRIX_VALUE () * v2.RMATRIX_VALUE ();\n}\n\n#if defined (LEFT)\nDEFBINOP (ldiv, LMATRIX, RMATRIX)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);\n\n  return v1.perm_matrix_value ().inverse () * v2.RMATRIX_VALUE ();\n}\n#else\nDEFBINOP (div, LMATRIX, RMATRIX)\n{\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);\n\n  return v1.LMATRIX_VALUE () * v2.perm_matrix_value ().inverse ();\n}\n#endif\n\n#define SHORT_NAME CONCAT3(LSHORT, _, RSHORT)\n#define INST_NAME CONCAT3(install_, SHORT_NAME, _ops)\n\nvoid\nINST_NAME (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_mul, OCTAVE_LMATRIX, OCTAVE_RMATRIX, mul);\n#if defined (LEFT)\n  INSTALL_BINOP_TI (ti, op_ldiv, OCTAVE_LMATRIX, OCTAVE_RMATRIX, ldiv);\n#else\n  INSTALL_BINOP_TI (ti, op_div, OCTAVE_LMATRIX, OCTAVE_RMATRIX, div);\n#endif\n#if defined (DEFINENULLASSIGNCONV)\n  INSTALL_ASSIGNCONV_TI (ti, OCTAVE_LMATRIX, octave_null_matrix, OCTAVE_LDMATRIX);\n  INSTALL_ASSIGNCONV_TI (ti, OCTAVE_LMATRIX, octave_null_str, OCTAVE_LDMATRIX);\n  INSTALL_ASSIGNCONV_TI (ti, OCTAVE_LMATRIX, octave_null_sq_str, OCTAVE_LDMATRIX);\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-range.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-range.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Allow +RNG_VAL to avoid conversion to array.\nDEFUNOP_OP (uplus, range, /* no-op */)\n\nCONVDECL (range_to_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_range&, v, a);\n\n  return new octave_matrix (v.array_value ());\n}\n\nvoid\ninstall_range_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_uplus, octave_range, uplus);\n\n  // FIXME: this would be unnecessary if\n  // octave_base_value::numeric_assign always tried converting lhs\n  // before rhs.\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_range, octave_null_matrix, octave_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_range, octave_null_str, octave_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_range, octave_null_sq_str, octave_matrix);\n\n  // Hmm, this one also seems to be needed.\n\n  INSTALL_WIDENOP_TI (ti, octave_range, octave_matrix, range_to_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-s-cm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-s-cm.h\"\n#include \"mx-cm-s.h\"\n#include \"mx-s-cnda.h\"\n#include \"mx-cnda-s.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar by complex matrix ops.\n\nDEFNDBINOP_OP (add, scalar, complex_matrix, scalar, complex_array, +)\nDEFNDBINOP_OP (sub, scalar, complex_matrix, scalar, complex_array, -)\nDEFNDBINOP_OP (mul, scalar, complex_matrix, scalar, complex_array, *)\n\nDEFBINOP (div, scalar, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  Matrix m1 = v1.matrix_value ();\n  ComplexMatrix m2 = v2.complex_matrix_value ();\n  MatrixType typ = v2.matrix_type ();\n\n  ComplexMatrix ret = xdiv (m1, m2, typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (pow, scalar, complex_matrix, xpow)\n\nDEFBINOP (ldiv, scalar, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return octave_value (v2.complex_array_value () / v1.double_value ());\n}\n\nDEFNDCMPLXCMPOP_FN (lt, scalar, complex_matrix, scalar, complex_array, mx_el_lt)\nDEFNDCMPLXCMPOP_FN (le, scalar, complex_matrix, scalar, complex_array, mx_el_le)\nDEFNDCMPLXCMPOP_FN (eq, scalar, complex_matrix, scalar, complex_array, mx_el_eq)\nDEFNDCMPLXCMPOP_FN (ge, scalar, complex_matrix, scalar, complex_array, mx_el_ge)\nDEFNDCMPLXCMPOP_FN (gt, scalar, complex_matrix, scalar, complex_array, mx_el_gt)\nDEFNDCMPLXCMPOP_FN (ne, scalar, complex_matrix, scalar, complex_array, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, scalar, complex_matrix, scalar, complex_array, *)\nDEFNDBINOP_FN (el_div, scalar, complex_matrix, scalar, complex_array, elem_xdiv)\nDEFNDBINOP_FN (el_pow, scalar, complex_matrix, scalar, complex_array, elem_xpow)\n\nDEFBINOP (el_ldiv, scalar, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return octave_value (v2.complex_array_value () / v1.double_value ());\n}\n\nDEFNDBINOP_FN (el_and, scalar, complex_matrix, scalar, complex_array, mx_el_and)\nDEFNDBINOP_FN (el_or,  scalar, complex_matrix, scalar, complex_array, mx_el_or)\n\nDEFNDCATOP_FN (s_cm, scalar, complex_matrix, array, complex_array, concat)\n\nDEFCONV (complex_matrix_conv, scalar, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);\n\n  return new octave_complex_matrix (ComplexMatrix (v.matrix_value ()));\n}\n\nvoid\ninstall_s_cm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_scalar, octave_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_scalar, octave_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_scalar, octave_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_scalar, octave_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_scalar, octave_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_scalar, octave_complex_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_scalar, octave_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_scalar, octave_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_scalar, octave_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_scalar, octave_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_scalar, octave_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_scalar, octave_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_scalar, octave_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_scalar, octave_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_scalar, octave_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_scalar, octave_complex_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_scalar, octave_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_scalar, octave_complex_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_complex_matrix, s_cm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_complex_matrix,\n                         octave_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_complex_matrix,\n                         octave_float_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_scalar, octave_complex_matrix,\n                      complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-s-cs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar by complex scalar ops.\n\nDEFBINOP_OP (add, scalar, complex, +)\nDEFBINOP_OP (sub, scalar, complex, -)\nDEFBINOP_OP (mul, scalar, complex, *)\n\nDEFBINOP (div, scalar, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.double_value () / v2.complex_value ());\n}\n\nDEFBINOP_FN (pow, scalar, complex, xpow)\n\nDEFBINOP (ldiv, scalar, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v2.complex_value () / v1.double_value ());\n}\n\nDEFCMPLXCMPOP_OP (lt, scalar, complex, <)\nDEFCMPLXCMPOP_OP (le, scalar, complex, <=)\nDEFCMPLXCMPOP_OP (eq, scalar, complex, ==)\nDEFCMPLXCMPOP_OP (ge, scalar, complex, >=)\nDEFCMPLXCMPOP_OP (gt, scalar, complex, >)\nDEFCMPLXCMPOP_OP (ne, scalar, complex, !=)\n\nDEFBINOP_OP (el_mul, scalar, complex, *)\n\nDEFBINOP (el_div, scalar, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.double_value () / v2.complex_value ());\n}\n\nDEFBINOP_FN (el_pow, scalar, complex, xpow)\n\nDEFBINOP (el_ldiv, scalar, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v2.complex_value () / v1.double_value ());\n}\n\nDEFBINOP (el_and, scalar, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.double_value () && (v2.complex_value () != 0.0));\n}\n\nDEFBINOP (el_or, scalar, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.double_value () || (v2.complex_value () != 0.0));\n}\n\nDEFNDCATOP_FN (s_cs, scalar, complex, array, complex_array, concat)\n\nvoid\ninstall_s_cs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_scalar, octave_complex, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_scalar, octave_complex, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_scalar, octave_complex, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_scalar, octave_complex, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_scalar, octave_complex, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_scalar, octave_complex, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_scalar, octave_complex, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_scalar, octave_complex, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_scalar, octave_complex, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_scalar, octave_complex, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_scalar, octave_complex, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_scalar, octave_complex, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_scalar, octave_complex, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_scalar, octave_complex, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_scalar, octave_complex, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_scalar, octave_complex, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_scalar, octave_complex, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_scalar, octave_complex, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_complex, s_cs);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_complex,\n                         octave_complex_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_complex,\n                         octave_float_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-s-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar by matrix ops.\n\nDEFNDBINOP_OP (add, scalar, matrix, scalar, array, +)\nDEFNDBINOP_OP (sub, scalar, matrix, scalar, array, -)\nDEFNDBINOP_OP (mul, scalar, matrix, scalar, array, *)\n\nDEFBINOP (div, scalar, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  Matrix m1 = v1.matrix_value ();\n  Matrix m2 = v2.matrix_value ();\n  MatrixType typ = v2.matrix_type ();\n\n  Matrix ret = xdiv (m1, m2, typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOP_FN (pow, scalar, matrix, xpow)\n\nDEFBINOP (ldiv, scalar, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return octave_value (v2.array_value () / v1.double_value ());\n}\n\nDEFNDBINOP_FN (lt, scalar, matrix, scalar, array, mx_el_lt)\nDEFNDBINOP_FN (le, scalar, matrix, scalar, array, mx_el_le)\nDEFNDBINOP_FN (eq, scalar, matrix, scalar, array, mx_el_eq)\nDEFNDBINOP_FN (ge, scalar, matrix, scalar, array, mx_el_ge)\nDEFNDBINOP_FN (gt, scalar, matrix, scalar, array, mx_el_gt)\nDEFNDBINOP_FN (ne, scalar, matrix, scalar, array, mx_el_ne)\n\nDEFNDBINOP_OP (el_mul, scalar, matrix, scalar, array, *)\nDEFNDBINOP_FN (el_div, scalar, matrix, scalar, array, elem_xdiv)\nDEFNDBINOP_FN (el_pow, scalar, matrix, scalar, array, elem_xpow)\n\nDEFBINOP (el_ldiv, scalar, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return octave_value (v2.array_value () / v1.double_value ());\n}\n\nDEFNDBINOP_FN (el_and, scalar, matrix, scalar, array, mx_el_and)\nDEFNDBINOP_FN (el_or,  scalar, matrix, scalar, array, mx_el_or)\n\nDEFNDCATOP_FN (s_m, scalar, matrix, array, array, concat)\n\nDEFCONV (matrix_conv, scalar, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);\n\n  return new octave_matrix (v.matrix_value ());\n}\n\nvoid\ninstall_s_m_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_scalar, octave_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_scalar, octave_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_scalar, octave_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_scalar, octave_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_scalar, octave_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_scalar, octave_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_scalar, octave_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_scalar, octave_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_scalar, octave_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_scalar, octave_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_scalar, octave_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_scalar, octave_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_scalar, octave_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_scalar, octave_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_scalar, octave_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_scalar, octave_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_scalar, octave_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_scalar, octave_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_matrix, s_m);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_matrix, octave_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_matrix,\n                         octave_float_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_scalar, octave_matrix, matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-s-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-util.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar unary ops.\n\nDEFUNOP (not, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);\n  double x = v.scalar_value ();\n  if (octave::math::isnan (x))\n    octave::err_nan_to_logical_conversion ();\n\n  return octave_value (x == 0.0);\n}\n\nDEFUNOP_OP (uplus, scalar, /* no-op */)\nDEFUNOP_OP (uminus, scalar, -)\nDEFUNOP_OP (transpose, scalar, /* no-op */)\nDEFUNOP_OP (hermitian, scalar, /* no-op */)\n\nDEFNCUNOP_METHOD (incr, scalar, increment)\nDEFNCUNOP_METHOD (decr, scalar, decrement)\n\n// scalar by scalar ops.\n\nDEFBINOP_OP (add, scalar, scalar, +)\nDEFBINOP_OP (sub, scalar, scalar, -)\nDEFBINOP_OP (mul, scalar, scalar, *)\n\nDEFBINOP (div, scalar, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.double_value () / v2.double_value ());\n}\n\nDEFBINOP_FN (pow, scalar, scalar, xpow)\n\nDEFBINOP (ldiv, scalar, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v2.double_value () / v1.double_value ());\n}\n\nDEFBINOP_OP (lt, scalar, scalar, <)\nDEFBINOP_OP (le, scalar, scalar, <=)\nDEFBINOP_OP (eq, scalar, scalar, ==)\nDEFBINOP_OP (ge, scalar, scalar, >=)\nDEFBINOP_OP (gt, scalar, scalar, >)\nDEFBINOP_OP (ne, scalar, scalar, !=)\n\nDEFBINOP_OP (el_mul, scalar, scalar, *)\n\nDEFBINOP (el_div, scalar, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.double_value () / v2.double_value ());\n}\n\nDEFBINOP_FN (el_pow, scalar, scalar, xpow)\n\nDEFBINOP (el_ldiv, scalar, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v2.double_value () / v1.double_value ());\n}\n\nDEFSCALARBOOLOP_OP (el_and, scalar, scalar, &&)\nDEFSCALARBOOLOP_OP (el_or, scalar, scalar, ||)\n\nDEFNDCATOP_FN (s_s, scalar, scalar, array, array, concat)\n\nvoid\ninstall_s_s_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_scalar, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_scalar, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_scalar, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_scalar, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_scalar, hermitian);\n\n  INSTALL_NCUNOP_TI (ti, op_incr, octave_scalar, incr);\n  INSTALL_NCUNOP_TI (ti, op_decr, octave_scalar, decr);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_scalar, octave_scalar, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_scalar, octave_scalar, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_scalar, octave_scalar, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_scalar, octave_scalar, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_scalar, octave_scalar, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_scalar, octave_scalar, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_scalar, octave_scalar, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_scalar, octave_scalar, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_scalar, octave_scalar, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_scalar, octave_scalar, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_scalar, octave_scalar, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_scalar, octave_scalar, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_scalar, octave_scalar, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_scalar, octave_scalar, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_scalar, octave_scalar, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_scalar, octave_scalar, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_scalar, octave_scalar, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_scalar, octave_scalar, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_scalar, s_s);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_scalar, octave_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_float_scalar, octave_scalar,\n                         octave_float_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_null_matrix, octave_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_null_str, octave_matrix);\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_null_sq_str, octave_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-s-scm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ops.h\"\n#include \"xpow.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-s-scm.h\"\n#include \"smx-scm-s.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar by sparse complex matrix ops.\n\nDEFBINOP_OP (add, scalar, sparse_complex_matrix, +)\nDEFBINOP_OP (sub, scalar, sparse_complex_matrix, -)\nDEFBINOP_OP (mul, scalar, sparse_complex_matrix, *)\n\nDEFBINOP (div, scalar, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (SparseComplexMatrix (1, 1, v1.scalar_value ()\n                         / v2.complex_value ()));\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      Matrix m1 = Matrix (1, 1, v1.scalar_value ());\n      SparseComplexMatrix m2 = v2.sparse_complex_matrix_value ();\n      ComplexMatrix ret = xdiv (m1, m2, typ);\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP (pow, scalar, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n  return xpow (v1.scalar_value (), v2.complex_matrix_value ());\n}\n\nDEFBINOP (ldiv, scalar, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return octave_value (v2.sparse_complex_matrix_value () / v1.double_value ());\n}\n\nDEFBINOP_FN (lt, scalar, sparse_complex_matrix, mx_el_lt)\nDEFBINOP_FN (le, scalar, sparse_complex_matrix, mx_el_le)\nDEFBINOP_FN (eq, scalar, sparse_complex_matrix, mx_el_eq)\nDEFBINOP_FN (ge, scalar, sparse_complex_matrix, mx_el_ge)\nDEFBINOP_FN (gt, scalar, sparse_complex_matrix, mx_el_gt)\nDEFBINOP_FN (ne, scalar, sparse_complex_matrix, mx_el_ne)\n\nDEFBINOP_OP (el_mul, scalar, sparse_complex_matrix, *)\nDEFBINOP_FN (el_div, scalar, sparse_complex_matrix, elem_xdiv)\nDEFBINOP_FN (el_pow, scalar, sparse_complex_matrix, elem_xpow)\n\nDEFBINOP (el_ldiv, scalar, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return octave_value (v2.sparse_complex_matrix_value () / v1.double_value ());\n}\n\nDEFBINOP_FN (el_and, scalar, sparse_complex_matrix, mx_el_and)\nDEFBINOP_FN (el_or, scalar, sparse_complex_matrix, mx_el_or)\n\nDEFCATOP (s_scm, scalar, sparse_compelx_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n  SparseMatrix tmp (1, 1, v1.scalar_value ());\n  return octave_value\n         (tmp.concat (v2.sparse_complex_matrix_value (), ra_idx));\n}\n\nDEFCONV (sparse_complex_matrix_conv, scalar, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);\n\n  return new octave_sparse_complex_matrix\n         (SparseComplexMatrix (v.complex_matrix_value ()));\n}\n\nvoid\ninstall_s_scm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_scalar, octave_sparse_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_scalar, octave_sparse_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_scalar, octave_sparse_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_scalar, octave_sparse_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_scalar, octave_sparse_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_scalar, octave_sparse_complex_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_scalar, octave_sparse_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_scalar, octave_sparse_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_scalar, octave_sparse_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_scalar, octave_sparse_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_scalar, octave_sparse_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_scalar, octave_sparse_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_scalar, octave_sparse_complex_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_scalar, octave_sparse_complex_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_scalar, octave_sparse_complex_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_scalar, octave_sparse_complex_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_scalar, octave_sparse_complex_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_scalar, octave_sparse_complex_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_sparse_complex_matrix, s_scm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_sparse_complex_matrix,\n                         octave_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_scalar, octave_sparse_complex_matrix,\n                      sparse_complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-s-sm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-scalar.h\"\n#include \"ops.h\"\n#include \"xpow.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"ov-re-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// scalar by sparse matrix ops.\n\nDEFBINOP_OP (add, scalar, sparse_matrix, +)\nDEFBINOP_OP (sub, scalar, sparse_matrix, -)\nDEFBINOP_OP (mul, scalar, sparse_matrix, *)\n\nDEFBINOP (div, scalar, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (SparseMatrix (1, 1, v1.scalar_value () / v2.scalar_value ()));\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      Matrix m1 = Matrix (1, 1, v1.double_value ());\n      SparseMatrix m2 = v2.sparse_matrix_value ();\n      Matrix ret = xdiv (m1, m2, typ);\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP (pow, scalar, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  return xpow (v1.scalar_value (), v2.matrix_value ());\n}\n\nDEFBINOP (ldiv, scalar, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  return octave_value (v2.sparse_matrix_value () / v1.double_value ());\n}\n\nDEFBINOP_FN (lt, scalar, sparse_matrix, mx_el_lt)\nDEFBINOP_FN (le, scalar, sparse_matrix, mx_el_le)\nDEFBINOP_FN (eq, scalar, sparse_matrix, mx_el_eq)\nDEFBINOP_FN (ge, scalar, sparse_matrix, mx_el_ge)\nDEFBINOP_FN (gt, scalar, sparse_matrix, mx_el_gt)\nDEFBINOP_FN (ne, scalar, sparse_matrix, mx_el_ne)\n\nDEFBINOP_OP (el_mul, scalar, sparse_matrix, *)\nDEFBINOP_FN (el_div, scalar, sparse_matrix, elem_xdiv)\nDEFBINOP_FN (el_pow, scalar, sparse_matrix, elem_xpow)\n\nDEFBINOP (el_ldiv, scalar, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  return octave_value (v2.sparse_matrix_value () / v1.double_value ());\n}\n\nDEFBINOP_FN (el_and, scalar, sparse_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  scalar, sparse_matrix, mx_el_or)\n\nDEFCATOP (s_sm, scalar, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  SparseMatrix tmp (1, 1, v1.scalar_value ());\n  return octave_value (tmp.concat (v2.sparse_matrix_value (), ra_idx));\n}\n\nDEFCONV (sparse_matrix_conv, scalar, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);\n\n  return new octave_sparse_matrix (SparseMatrix (v.matrix_value ()));\n}\n\nvoid\ninstall_s_sm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_scalar, octave_sparse_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_scalar, octave_sparse_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_scalar, octave_sparse_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_scalar, octave_sparse_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_scalar, octave_sparse_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_scalar, octave_sparse_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_scalar, octave_sparse_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_scalar, octave_sparse_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_scalar, octave_sparse_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_scalar, octave_sparse_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_scalar, octave_sparse_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_scalar, octave_sparse_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_scalar, octave_sparse_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_scalar, octave_sparse_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_scalar, octave_sparse_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_scalar, octave_sparse_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_scalar, octave_sparse_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_scalar, octave_sparse_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_sparse_matrix, s_sm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_sparse_matrix, octave_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_scalar, octave_sparse_matrix,\n                      sparse_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-sbm-b.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-bool.h\"\n#include \"ov-int8.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-scalar.h\"\n#include \"ops.h\"\n\n#include \"ov-re-sparse.h\"\n#include \"ov-bool-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse bool matrix by bool ops.\n\nDEFBINOP_FN (ne, sparse_bool_matrix, bool, mx_el_ne)\nDEFBINOP_FN (eq, sparse_bool_matrix, bool, mx_el_eq)\n\nDEFBINOP_FN (el_and, sparse_bool_matrix, bool, mx_el_and)\nDEFBINOP_FN (el_or, sparse_bool_matrix, bool, mx_el_or)\n\nDEFCATOP (sbm_b, sparse_bool_matrix, bool)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v2, a2);\n\n  SparseBoolMatrix tmp (1, 1, v2.bool_value ());\n  return octave_value (v1.sparse_bool_matrix_value (). concat (tmp, ra_idx));\n}\n\nDEFCATOP (sm_b, sparse_matrix, bool)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v2, a2);\n\n  SparseMatrix tmp (1, 1, v2.scalar_value ());\n  return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));\n}\n\nDEFCATOP (sbm_s, sparse_bool_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  SparseMatrix tmp (1, 1, v2.scalar_value ());\n  return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));\n}\n\nDEFASSIGNOP (assign, sparse_bool_matrix, bool)\n{\n  OCTAVE_CAST_BASE_VALUE (octave_sparse_bool_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v2, a2);\n\n  SparseBoolMatrix tmp (1, 1, v2.bool_value ());\n  v1.assign (idx, tmp);\n  return octave_value ();\n}\n\nstatic octave_value\noct_assignop_conv_and_assign (octave_base_value& a1,\n                              const octave_value_list& idx,\n                              const octave_base_value& a2)\n{\n  OCTAVE_CAST_BASE_VALUE (octave_sparse_bool_matrix&, v1, a1);\n\n  // FIXME: perhaps add a warning for this conversion if the values\n  // are not all 0 or 1?\n\n  SparseBoolMatrix v2 (1, 1, a2.bool_value ());\n\n  v1.assign (idx, v2);\n\n  return octave_value ();\n}\n\nvoid\ninstall_sbm_b_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_bool_matrix, octave_bool, eq);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_bool_matrix, octave_bool, ne);\n\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_bool_matrix, octave_bool,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_bool_matrix, octave_bool, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_bool_matrix, octave_bool, sbm_b);\n  INSTALL_CATOP_TI (ti, octave_sparse_bool_matrix, octave_scalar, sbm_s);\n  INSTALL_CATOP_TI (ti, octave_sparse_matrix, octave_bool, sm_b);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix, octave_bool,\n                       assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix, octave_scalar,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_int8_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_int16_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_int32_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_int64_scalar,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_uint8_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_uint16_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_uint32_scalar,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_uint64_scalar,\n                       conv_and_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-sbm-bm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-bool-mat.h\"\n#include \"boolMatrix.h\"\n#include \"ov-int8.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-range.h\"\n#include \"ov-scalar.h\"\n#include \"ov-str-mat.h\"\n#include \"ops.h\"\n#include \"ov-null-mat.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-bool-sparse.h\"\n#include \"smx-bm-sbm.h\"\n#include \"smx-sbm-bm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse bool matrix by bool matrix ops.\n\nDEFBINOP_FN (eq, sparse_bool_matrix, bool_matrix, mx_el_eq)\nDEFBINOP_FN (ne, sparse_bool_matrix, bool_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_and, sparse_bool_matrix, bool_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_bool_matrix, bool_matrix, mx_el_or)\n\nDEFCATOP (sbm_bm, sparse_bool_matrix, bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v2, a2);\n\n  SparseBoolMatrix tmp (v2.bool_matrix_value ());\n  return octave_value (v1.sparse_bool_matrix_value (). concat (tmp, ra_idx));\n}\n\nDEFCATOP (sbm_m, sparse_bool_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  SparseMatrix tmp (v2.matrix_value ());\n  return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));\n}\n\nDEFCATOP (sm_bm, sparse_matrix, bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v2, a2);\n\n  SparseMatrix tmp (v2.matrix_value ());\n  return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));\n}\n\nDEFASSIGNOP (assign, sparse_bool_matrix, bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (octave_sparse_bool_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v2, a2);\n\n  v1.assign (idx, SparseBoolMatrix (v2.bool_matrix_value ()));\n  return octave_value ();\n}\n\nDEFNULLASSIGNOP_FN (null_assign, sparse_bool_matrix, delete_elements)\n\nstatic octave_value\noct_assignop_conv_and_assign (octave_base_value& a1,\n                              const octave_value_list& idx,\n                              const octave_base_value& a2)\n{\n  OCTAVE_CAST_BASE_VALUE (octave_sparse_bool_matrix&, v1, a1);\n\n  // FIXME: perhaps add a warning for this conversion if the values\n  // are not all 0 or 1?\n\n  SparseBoolMatrix v2 (a2.bool_array_value ());\n\n  v1.assign (idx, v2);\n\n  return octave_value ();\n}\n\nvoid\ninstall_sbm_bm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_bool_matrix, octave_bool_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_bool_matrix, octave_bool_matrix, ne);\n\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_bool_matrix, octave_bool_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_bool_matrix, octave_bool_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_bool_matrix, octave_bool_matrix, sbm_bm);\n  INSTALL_CATOP_TI (ti, octave_sparse_matrix, octave_bool_matrix, sm_bm);\n  INSTALL_CATOP_TI (ti, octave_sparse_bool_matrix, octave_matrix, sbm_m);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_bool_matrix, assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix, octave_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_char_matrix_str, conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_char_matrix_sq_str, conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix, octave_range,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_sparse_matrix,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_int8_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_int16_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_int32_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_int64_matrix,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_uint8_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_uint16_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_uint32_matrix,\n                       conv_and_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_uint64_matrix,\n                       conv_and_assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_null_matrix,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix, octave_null_str,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_null_sq_str,\n                       null_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-sbm-sbm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-bool-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ops.h\"\n\n#include \"ov-re-sparse.h\"\n#include \"ov-bool-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// unary sparse bool matrix ops.\n\nDEFUNOP_OP (not, sparse_bool_matrix, !)\n\nDEFUNOP (uplus, sparse_bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v, a);\n  return octave_value (v.sparse_matrix_value ());\n}\n\nDEFUNOP (uminus, sparse_bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v, a);\n  return octave_value (- v.sparse_matrix_value ());\n}\n\nDEFUNOP (transpose, sparse_bool_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v, a);\n  return octave_value (v.sparse_bool_matrix_value ().transpose ());\n}\n\n// sparse bool matrix by sparse bool matrix ops.\n\nDEFBINOP_FN (eq, sparse_bool_matrix, sparse_bool_matrix, mx_el_eq)\nDEFBINOP_FN (ne, sparse_bool_matrix, sparse_bool_matrix, mx_el_ne)\nDEFBINOP_FN (el_and, sparse_bool_matrix, sparse_bool_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_bool_matrix, sparse_bool_matrix, mx_el_or)\n\nDEFNDCATOP_FN (sbm_sbm, sparse_bool_matrix, sparse_bool_matrix,\n               sparse_bool_matrix, sparse_bool_matrix, concat)\nDEFNDCATOP_FN (sbm_sm, sparse_bool_matrix, sparse_matrix, sparse_matrix,\n               sparse_matrix, concat)\nDEFNDCATOP_FN (sm_sbm, sparse_matrix, sparse_bool_matrix, sparse_matrix,\n               sparse_matrix, concat)\n\nDEFASSIGNOP_FN (assign, sparse_bool_matrix, sparse_bool_matrix,\n                assign)\n\nvoid\ninstall_sbm_sbm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_sparse_bool_matrix, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_sparse_bool_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_sparse_bool_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_sparse_bool_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_sparse_bool_matrix, transpose);\n\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_bool_matrix,\n                    octave_sparse_bool_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_bool_matrix,\n                    octave_sparse_bool_matrix, ne);\n\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_bool_matrix,\n                    octave_sparse_bool_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_bool_matrix,\n                    octave_sparse_bool_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_bool_matrix, octave_sparse_bool_matrix,\n                    sbm_sbm);\n  INSTALL_CATOP_TI (ti, octave_sparse_bool_matrix, octave_sparse_matrix, sbm_sm);\n  INSTALL_CATOP_TI (ti, octave_sparse_matrix, octave_sparse_bool_matrix, sm_sbm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_bool_matrix,\n                       octave_sparse_bool_matrix, assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-scm-cm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-scm-cm.h\"\n#include \"smx-cm-scm.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse complex matrix by complex matrix ops.\n\nDEFBINOP_OP (add, sparse_complex_matrix, complex_matrix, +)\nDEFBINOP_OP (sub, sparse_complex_matrix, complex_matrix, -)\n\nDEFBINOP_OP (mul, sparse_complex_matrix, complex_matrix, *)\n\nDEFBINOP (div, sparse_complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  ComplexMatrix ret = xdiv (v1.complex_matrix_value (),\n                            v2.complex_matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, sparse_complex_matrix, complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, sparse_complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.complex_array_value () / v1.complex_value ());\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n\n      ComplexMatrix ret = xleftdiv (v1.sparse_complex_matrix_value (),\n                                    v2.complex_matrix_value (), typ);\n\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (trans_mul, sparse_complex_matrix, complex_matrix, trans_mul);\nDEFBINOP_FN (herm_mul, sparse_complex_matrix, complex_matrix, herm_mul);\n\nDEFBINOP_FN (lt, sparse_complex_matrix, complex_matrix, mx_el_lt)\nDEFBINOP_FN (le, sparse_complex_matrix, complex_matrix, mx_el_le)\nDEFBINOP_FN (eq, sparse_complex_matrix, complex_matrix, mx_el_eq)\nDEFBINOP_FN (ge, sparse_complex_matrix, complex_matrix, mx_el_ge)\nDEFBINOP_FN (gt, sparse_complex_matrix, complex_matrix, mx_el_gt)\nDEFBINOP_FN (ne, sparse_complex_matrix, complex_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, sparse_complex_matrix, complex_matrix, product)\nDEFBINOP_FN (el_div, sparse_complex_matrix, complex_matrix, quotient)\n\nDEFBINOP (el_pow, sparse_complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return octave_value\n         (elem_xpow (v1.sparse_complex_matrix_value (), SparseComplexMatrix\n                     (v2.complex_matrix_value ())));\n}\n\nDEFBINOP (el_ldiv, sparse_complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return octave_value (quotient (v2.complex_matrix_value (),\n                                 v1.sparse_complex_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_complex_matrix, complex_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_complex_matrix, complex_matrix, mx_el_or)\n\nDEFCATOP (scm_cm, sparse_complex_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  SparseComplexMatrix tmp (v2.complex_matrix_value ());\n  return octave_value\n         (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx));\n}\n\nDEFNDASSIGNOP_FN (assign, sparse_complex_matrix, complex_matrix, complex_matrix, assign);\nDEFNDASSIGNOP_FN (sgl_assign, sparse_complex_matrix, float_complex_matrix, complex_matrix, assign);\n\nvoid\ninstall_scm_cm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_complex_matrix,\n                    octave_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_complex_matrix,\n                    octave_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_complex_matrix,\n                    octave_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_complex_matrix,\n                    octave_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_complex_matrix,\n                    octave_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_complex_matrix,\n                    octave_complex_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_trans_mul, octave_sparse_complex_matrix,\n                    octave_complex_matrix, trans_mul);\n  INSTALL_BINOP_TI (ti, op_herm_mul, octave_sparse_complex_matrix,\n                    octave_complex_matrix, herm_mul);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_complex_matrix,\n                    octave_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_complex_matrix,\n                    octave_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_complex_matrix,\n                    octave_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_complex_matrix,\n                    octave_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_complex_matrix,\n                    octave_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_complex_matrix,\n                    octave_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_complex_matrix,\n                    octave_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_complex_matrix,\n                    octave_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_complex_matrix,\n                    octave_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_complex_matrix,\n                    octave_complex_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_complex_matrix,\n                    octave_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_complex_matrix,\n                    octave_complex_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_complex_matrix,\n                    octave_complex_matrix, scm_cm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix,\n                       octave_complex_matrix, assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix,\n                       octave_float_complex_matrix, sgl_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-scm-cs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ops.h\"\n#include \"xpow.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse complex matrix by complex scalar ops.\n\nDEFBINOP_OP (add, sparse_complex_matrix, complex, +)\nDEFBINOP_OP (sub, sparse_complex_matrix, complex, -)\nDEFBINOP_OP (mul, sparse_complex_matrix, complex, *)\n\nDEFBINOP (div, sparse_complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());\n}\n\nDEFBINOP (pow, sparse_complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n  return xpow (v1.complex_matrix_value (), v2.complex_value ());\n}\n\nDEFBINOP (ldiv, sparse_complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (SparseComplexMatrix (1, 1, v2.complex_value ()\n                         / v1.complex_value ()));\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n      SparseComplexMatrix m1 = v1.sparse_complex_matrix_value ();\n      ComplexMatrix m2 = ComplexMatrix (1, 1, v2.complex_value ());\n      ComplexMatrix ret = xleftdiv (m1, m2, typ);\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_complex_matrix, complex, mx_el_lt)\nDEFBINOP_FN (le, sparse_complex_matrix, complex, mx_el_le)\nDEFBINOP_FN (eq, sparse_complex_matrix, complex, mx_el_eq)\nDEFBINOP_FN (ge, sparse_complex_matrix, complex, mx_el_ge)\nDEFBINOP_FN (gt, sparse_complex_matrix, complex, mx_el_gt)\nDEFBINOP_FN (ne, sparse_complex_matrix, complex, mx_el_ne)\n\nDEFBINOP_OP (el_mul, sparse_complex_matrix, complex, *)\n\nDEFBINOP (el_div, sparse_complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());\n}\n\nDEFBINOP_FN (el_pow, sparse_complex_matrix, complex, elem_xpow)\n\nDEFBINOP (el_ldiv, sparse_complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value\n         (elem_xdiv (v2.complex_value (), v1.sparse_complex_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_complex_matrix, complex, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_complex_matrix, complex, mx_el_or)\n\nDEFCATOP (scm_cs, sparse_complex_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n  SparseComplexMatrix tmp (1, 1, v2.complex_value ());\n  return octave_value\n         (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx));\n}\n\nDEFNDASSIGNOP_FN (assign, sparse_complex_matrix, complex, complex, assign);\nDEFNDASSIGNOP_FN (sgl_assign, sparse_complex_matrix, float_complex, complex, assign);\n\nvoid\ninstall_scm_cs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_complex_matrix, octave_complex,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_complex_matrix, octave_complex,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_complex_matrix, octave_complex,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_complex_matrix, octave_complex,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_complex_matrix, octave_complex,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_complex_matrix, octave_complex,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_complex_matrix, octave_complex, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_complex_matrix, octave_complex, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_complex_matrix, octave_complex, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_complex_matrix, octave_complex, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_complex_matrix, octave_complex, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_complex_matrix, octave_complex, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_complex_matrix, octave_complex,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_complex_matrix, octave_complex,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_complex_matrix, octave_complex,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_complex_matrix, octave_complex,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_complex_matrix, octave_complex,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_complex_matrix, octave_complex,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_complex_matrix, octave_complex, scm_cs);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix,\n                       octave_complex, assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix,\n                       octave_float_complex, sgl_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-scm-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-scm-m.h\"\n#include \"smx-m-scm.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse complex matrix by matrix ops.\n\nDEFBINOP_OP (add, sparse_complex_matrix, matrix, +)\nDEFBINOP_OP (sub, sparse_complex_matrix, matrix, -)\n\nDEFBINOP_OP (mul, sparse_complex_matrix, matrix, *)\n\nDEFBINOP (div, sparse_complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  ComplexMatrix ret = xdiv (v1.complex_matrix_value (),\n                            v2.matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, sparse_complex_matrix, matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, sparse_complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.array_value () / v1.complex_value ());\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n\n      ComplexMatrix ret = xleftdiv (v1.sparse_complex_matrix_value (),\n                                    v2.matrix_value (), typ);\n\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_complex_matrix, matrix, mx_el_lt)\nDEFBINOP_FN (le, sparse_complex_matrix, matrix, mx_el_le)\nDEFBINOP_FN (eq, sparse_complex_matrix, matrix, mx_el_eq)\nDEFBINOP_FN (ge, sparse_complex_matrix, matrix, mx_el_ge)\nDEFBINOP_FN (gt, sparse_complex_matrix, matrix, mx_el_gt)\nDEFBINOP_FN (ne, sparse_complex_matrix, matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, sparse_complex_matrix, matrix, product)\nDEFBINOP_FN (el_div, sparse_complex_matrix, matrix, quotient)\n\nDEFBINOP (el_pow, sparse_complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return octave_value\n         (elem_xpow (v1.sparse_complex_matrix_value (), SparseMatrix\n                     (v2.matrix_value ())));\n}\n\nDEFBINOP (el_ldiv, sparse_complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return octave_value\n         (quotient (v2.matrix_value (), v1.sparse_complex_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_complex_matrix, matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_complex_matrix, matrix, mx_el_or)\n\nDEFCATOP (scm_m, sparse_complex_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  SparseMatrix tmp (v2.matrix_value ());\n  return octave_value\n         (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx));\n}\n\nDEFNDASSIGNOP_FN (assign, sparse_complex_matrix, matrix, complex_matrix, assign);\nDEFNDASSIGNOP_FN (sgl_assign, sparse_complex_matrix, float_matrix, complex_matrix, assign);\n\nvoid\ninstall_scm_m_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_complex_matrix, octave_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_complex_matrix, octave_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_complex_matrix, octave_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_complex_matrix, octave_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_complex_matrix, octave_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_complex_matrix, octave_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_complex_matrix, octave_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_complex_matrix, octave_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_complex_matrix, octave_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_complex_matrix, octave_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_complex_matrix, octave_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_complex_matrix, octave_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_complex_matrix, octave_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_complex_matrix, octave_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_complex_matrix, octave_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_complex_matrix, octave_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_complex_matrix, octave_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_complex_matrix, octave_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_complex_matrix, octave_matrix, scm_m);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, octave_matrix,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, octave_float_matrix,\n                       sgl_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-scm-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ops.h\"\n#include \"xpow.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-scm-s.h\"\n#include \"smx-s-scm.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse complex matrix by scalar ops.\n\nDEFBINOP_OP (add, sparse_complex_matrix, scalar, +)\nDEFBINOP_OP (sub, sparse_complex_matrix, scalar, -)\nDEFBINOP_OP (mul, sparse_complex_matrix, scalar, *)\n\nDEFBINOP (div, sparse_complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.sparse_complex_matrix_value () / v2.double_value ());\n}\n\nDEFBINOP (pow, sparse_complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  double tmp = v2.scalar_value ();\n  if (static_cast<int> (tmp) == tmp)\n    return xpow (v1.sparse_complex_matrix_value (), tmp);\n  else\n    return xpow (v1.complex_matrix_value (), tmp);\n}\n\nDEFBINOP (ldiv, sparse_complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (SparseComplexMatrix (1, 1, v2.scalar_value ()\n                         / v1.complex_value ()));\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n      SparseComplexMatrix m1 = v1.sparse_complex_matrix_value ();\n      Matrix m2 = Matrix (1, 1, v2.scalar_value ());\n      ComplexMatrix ret = xleftdiv (m1, m2, typ);\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_complex_matrix, scalar, mx_el_lt)\nDEFBINOP_FN (le, sparse_complex_matrix, scalar, mx_el_le)\nDEFBINOP_FN (eq, sparse_complex_matrix, scalar, mx_el_eq)\nDEFBINOP_FN (ge, sparse_complex_matrix, scalar, mx_el_ge)\nDEFBINOP_FN (gt, sparse_complex_matrix, scalar, mx_el_gt)\nDEFBINOP_FN (ne, sparse_complex_matrix, scalar, mx_el_ne)\n\nDEFBINOP_OP (el_mul, sparse_complex_matrix, scalar, *)\n\nDEFBINOP (el_div, sparse_complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.sparse_complex_matrix_value () / v2.double_value ());\n}\n\nDEFBINOP_FN (el_pow, sparse_complex_matrix, scalar, elem_xpow)\n\nDEFBINOP (el_ldiv, sparse_complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value\n         (elem_xdiv (v2.double_value (), v1.sparse_complex_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_complex_matrix, scalar, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_complex_matrix, scalar, mx_el_or)\n\nDEFCATOP (scm_s, sparse_complex_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n  SparseComplexMatrix tmp (1, 1, v2.complex_value ());\n  return octave_value\n         (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx));\n}\n\nDEFNDASSIGNOP_FN (assign, sparse_complex_matrix, scalar, scalar, assign);\nDEFNDASSIGNOP_FN (sgl_assign, sparse_complex_matrix, float_scalar, scalar, assign);\n\nvoid\ninstall_scm_s_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_complex_matrix, octave_scalar, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_complex_matrix, octave_scalar, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_complex_matrix, octave_scalar, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_complex_matrix, octave_scalar, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_complex_matrix, octave_scalar, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_complex_matrix, octave_scalar,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_complex_matrix, octave_scalar, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_complex_matrix, octave_scalar, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_complex_matrix, octave_scalar, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_complex_matrix, octave_scalar, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_complex_matrix, octave_scalar, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_complex_matrix, octave_scalar, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_complex_matrix, octave_scalar,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_complex_matrix, octave_scalar,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_complex_matrix, octave_scalar,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_complex_matrix, octave_scalar,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_complex_matrix, octave_scalar,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_complex_matrix, octave_scalar,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_complex_matrix, octave_scalar, scm_s);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, octave_scalar,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, octave_float_scalar,\n                       sgl_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-scm-scm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n\n#include \"sparse-xdiv.h\"\n#include \"sparse-xpow.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-cx-sparse.h\"\n#include \"ov-re-sparse.h\"\n\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// unary sparse complex matrix ops.\n\nDEFUNOP_OP (not, sparse_complex_matrix, !)\nDEFUNOP_OP (uplus, sparse_complex_matrix, /* no-op */)\nDEFUNOP_OP (uminus, sparse_complex_matrix, -)\n\nDEFUNOP (transpose, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v, a);\n  return octave_value\n         (v.sparse_complex_matrix_value ().transpose (),\n          v.matrix_type ().transpose ());\n}\n\nDEFUNOP (hermitian, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v, a);\n  return octave_value\n         (v.sparse_complex_matrix_value ().hermitian (),\n          v.matrix_type ().transpose ());\n}\n\n// complex matrix by complex matrix ops.\n\nDEFBINOP_OP (add, sparse_complex_matrix, sparse_complex_matrix, +)\nDEFBINOP_OP (sub, sparse_complex_matrix, sparse_complex_matrix, -)\n\nDEFBINOP_OP (mul, sparse_complex_matrix, sparse_complex_matrix, *)\n\nDEFBINOP (div, sparse_complex_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      SparseComplexMatrix ret = xdiv (v1.sparse_complex_matrix_value (),\n                                      v2.sparse_complex_matrix_value (), typ);\n\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOPX (pow, sparse_complex_matrix, sparse_complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, sparse_complex_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.sparse_complex_matrix_value () / v1.complex_value ());\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n\n      SparseComplexMatrix ret\n        = xleftdiv (v1.sparse_complex_matrix_value (),\n                    v2.sparse_complex_matrix_value (), typ);\n\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_complex_matrix, sparse_complex_matrix, mx_el_lt)\nDEFBINOP_FN (le, sparse_complex_matrix, sparse_complex_matrix, mx_el_le)\nDEFBINOP_FN (eq, sparse_complex_matrix, sparse_complex_matrix, mx_el_eq)\nDEFBINOP_FN (ge, sparse_complex_matrix, sparse_complex_matrix, mx_el_ge)\nDEFBINOP_FN (gt, sparse_complex_matrix, sparse_complex_matrix, mx_el_gt)\nDEFBINOP_FN (ne, sparse_complex_matrix, sparse_complex_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, sparse_complex_matrix, sparse_complex_matrix, product)\nDEFBINOP_FN (el_div, sparse_complex_matrix, sparse_complex_matrix, quotient)\nDEFBINOP_FN (el_pow, sparse_complex_matrix, sparse_complex_matrix, elem_xpow)\n\nDEFBINOP (el_ldiv, sparse_complex_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return octave_value (quotient (v2.sparse_complex_matrix_value (),\n                                 v1.sparse_complex_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_complex_matrix, sparse_complex_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_complex_matrix, sparse_complex_matrix, mx_el_or)\n\nDEFCATOP_FN (scm_scm, sparse_complex_matrix, sparse_complex_matrix, concat)\n\nDEFASSIGNOP_FN (assign, sparse_complex_matrix, sparse_complex_matrix, assign)\n\nDEFNULLASSIGNOP_FN (null_assign, sparse_complex_matrix, delete_elements)\n\nvoid\ninstall_scm_scm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_sparse_complex_matrix, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_sparse_complex_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_sparse_complex_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_sparse_complex_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_sparse_complex_matrix, hermitian);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_complex_matrix,\n                    octave_sparse_complex_matrix, scm_scm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix,\n                       octave_sparse_complex_matrix, assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix,\n                       octave_null_matrix, null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix,\n                       octave_null_str, null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix,\n                       octave_null_sq_str, null_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-scm-sm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\n#include \"sparse-xdiv.h\"\n#include \"sparse-xpow.h\"\n#include \"smx-sm-scm.h\"\n#include \"smx-scm-sm.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse complex matrix by sparse matrix ops.\n\nDEFBINOP_OP (add, sparse_complex_matrix, sparse_matrix, +)\nDEFBINOP_OP (sub, sparse_complex_matrix, sparse_matrix, -)\n\nDEFBINOP_OP (mul, sparse_complex_matrix, sparse_matrix, *)\n\nDEFBINOP (div, sparse_complex_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_complex_matrix_value () / v2.scalar_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      SparseComplexMatrix ret = xdiv (v1.sparse_complex_matrix_value (),\n                                      v2.sparse_matrix_value (), typ);\n\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOPX (pow, sparse_complex_matrix, sparse_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, sparse_complex_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.sparse_matrix_value () / v1.complex_value ());\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n\n      SparseComplexMatrix ret = xleftdiv (v1.sparse_complex_matrix_value (),\n                                          v2.sparse_matrix_value (), typ);\n\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_complex_matrix, sparse_matrix, mx_el_lt)\nDEFBINOP_FN (le, sparse_complex_matrix, sparse_matrix, mx_el_le)\nDEFBINOP_FN (eq, sparse_complex_matrix, sparse_matrix, mx_el_eq)\nDEFBINOP_FN (ge, sparse_complex_matrix, sparse_matrix, mx_el_ge)\nDEFBINOP_FN (gt, sparse_complex_matrix, sparse_matrix, mx_el_gt)\nDEFBINOP_FN (ne, sparse_complex_matrix, sparse_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, sparse_complex_matrix, sparse_matrix, product)\nDEFBINOP_FN (el_div, sparse_complex_matrix, sparse_matrix, quotient)\nDEFBINOP_FN (el_pow, sparse_complex_matrix, sparse_matrix, elem_xpow)\n\nDEFBINOP (el_ldiv, sparse_complex_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  return octave_value (quotient (v2.sparse_matrix_value (),\n                                 v1.sparse_complex_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_complex_matrix, sparse_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_complex_matrix, sparse_matrix, mx_el_or)\n\nDEFCATOP_FN (scm_sm, sparse_complex_matrix, sparse_matrix, concat)\n\nDEFASSIGNOP_FN (assign, sparse_complex_matrix, sparse_matrix, assign)\n\nvoid\ninstall_scm_sm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_complex_matrix,\n                    octave_sparse_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_complex_matrix,\n                    octave_sparse_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_complex_matrix,\n                    octave_sparse_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_complex_matrix,\n                    octave_sparse_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_complex_matrix,\n                    octave_sparse_matrix,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_complex_matrix,\n                    octave_sparse_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_complex_matrix, octave_sparse_matrix,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_complex_matrix, octave_sparse_matrix,\n                    le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_complex_matrix, octave_sparse_matrix,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_complex_matrix, octave_sparse_matrix,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_complex_matrix, octave_sparse_matrix,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_complex_matrix, octave_sparse_matrix,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_complex_matrix,\n                    octave_sparse_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_complex_matrix,\n                    octave_sparse_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_complex_matrix,\n                    octave_sparse_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_complex_matrix,\n                    octave_sparse_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_complex_matrix,\n                    octave_sparse_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_complex_matrix,\n                    octave_sparse_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_complex_matrix, octave_sparse_matrix,\n                    scm_sm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix,\n                       octave_sparse_matrix, assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-sm-cm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-sm-cm.h\"\n#include \"smx-cm-sm.h\"\n#include \"ov-re-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse matrix by complex matrix ops.\n\nDEFBINOP_OP (add, sparse_matrix, complex_matrix, +)\nDEFBINOP_OP (sub, sparse_matrix, complex_matrix, -)\n\nDEFBINOP_OP (mul, sparse_matrix, complex_matrix, *)\n\nDEFBINOP (div, sparse_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  ComplexMatrix ret = xdiv (v1.matrix_value (),\n                            v2.complex_matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, sparse_matrix, complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, sparse_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.complex_array_value () / v1.scalar_value ());\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n\n      ComplexMatrix ret = xleftdiv (v1.sparse_matrix_value (),\n                                    v2.complex_matrix_value (), typ);\n\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_matrix, complex_matrix, mx_el_lt)\nDEFBINOP_FN (le, sparse_matrix, complex_matrix, mx_el_le)\nDEFBINOP_FN (eq, sparse_matrix, complex_matrix, mx_el_eq)\nDEFBINOP_FN (ge, sparse_matrix, complex_matrix, mx_el_ge)\nDEFBINOP_FN (gt, sparse_matrix, complex_matrix, mx_el_gt)\nDEFBINOP_FN (ne, sparse_matrix, complex_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, sparse_matrix, complex_matrix, product)\nDEFBINOP_FN (el_div, sparse_matrix, complex_matrix, quotient)\n\nDEFBINOP (el_pow, sparse_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return octave_value\n         (elem_xpow (v1.sparse_matrix_value (), SparseComplexMatrix\n                     (v2.complex_matrix_value ())));\n}\n\nDEFBINOP (el_ldiv, sparse_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n\n  return octave_value\n         (quotient (v2.complex_matrix_value (), v1.sparse_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_matrix, complex_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_matrix, complex_matrix, mx_el_or)\n\nDEFCATOP (sm_cm, sparse_matrix, complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);\n  SparseComplexMatrix tmp (v2.complex_matrix_value ());\n  return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));\n}\n\nDEFCONV (sparse_complex_matrix_conv, sparse_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v, a);\n  return new octave_complex_matrix (v.complex_matrix_value ());\n}\n\nvoid\ninstall_sm_cm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_matrix, octave_complex_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_matrix, octave_complex_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_matrix, octave_complex_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_matrix, octave_complex_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_matrix, octave_complex_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_matrix, octave_complex_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_matrix, octave_complex_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_matrix, octave_complex_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_matrix, octave_complex_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_matrix, octave_complex_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_matrix, octave_complex_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_matrix, octave_complex_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_matrix, octave_complex_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_matrix, octave_complex_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_matrix, octave_complex_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_matrix, octave_complex_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_matrix, octave_complex_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_matrix, octave_complex_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_matrix, octave_complex_matrix, sm_cm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_sparse_matrix, octave_complex_matrix,\n                         octave_sparse_complex_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_sparse_matrix, octave_float_complex_matrix,\n                         octave_sparse_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_sparse_matrix, octave_complex_matrix,\n                      sparse_complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-sm-cs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ops.h\"\n#include \"xpow.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n#include \"smx-sm-cs.h\"\n#include \"smx-cs-sm.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse matrix by scalar ops.\n\nDEFBINOP_OP (add, sparse_matrix, complex, +)\nDEFBINOP_OP (sub, sparse_matrix, complex, -)\nDEFBINOP_OP (mul, sparse_matrix, complex, *)\n\nDEFBINOP (div, sparse_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.sparse_matrix_value () / v2.complex_value ());\n}\n\nDEFBINOP (pow, sparse_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n  return xpow (v1.matrix_value (), v2.complex_value ());\n}\n\nDEFBINOP (ldiv, sparse_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (SparseComplexMatrix (1, 1, v2.complex_value ()\n                         / v1.scalar_value ()));\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n      SparseMatrix m1 = v1.sparse_matrix_value ();\n      ComplexMatrix m2 = ComplexMatrix (1, 1, v2.complex_value ());\n      ComplexMatrix ret = xleftdiv (m1, m2, typ);\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_matrix, complex, mx_el_lt)\nDEFBINOP_FN (le, sparse_matrix, complex, mx_el_le)\nDEFBINOP_FN (eq, sparse_matrix, complex, mx_el_eq)\nDEFBINOP_FN (ge, sparse_matrix, complex, mx_el_ge)\nDEFBINOP_FN (gt, sparse_matrix, complex, mx_el_gt)\nDEFBINOP_FN (ne, sparse_matrix, complex, mx_el_ne)\n\nDEFBINOP_OP (el_mul, sparse_matrix, complex, *)\n\nDEFBINOP (el_div, sparse_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (v1.sparse_matrix_value () / v2.complex_value ());\n}\n\nDEFBINOP_FN (el_pow, sparse_matrix, complex, elem_xpow)\n\nDEFBINOP (el_ldiv, sparse_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n\n  return octave_value (elem_xdiv (v2.complex_value (),\n                                  v1.sparse_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_matrix, complex, mx_el_and)\nDEFBINOP_FN (el_or, sparse_matrix, complex, mx_el_or)\n\nDEFCATOP (sm_cs, sparse_matrix, complex)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);\n  SparseComplexMatrix tmp (1, 1, v2.complex_value ());\n  return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));\n}\n\nvoid\ninstall_sm_cs_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_matrix, octave_complex, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_matrix, octave_complex, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_matrix, octave_complex, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_matrix, octave_complex, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_matrix, octave_complex, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_matrix, octave_complex, ldiv);\n\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_matrix, octave_complex, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_matrix, octave_complex, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_matrix, octave_complex, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_matrix, octave_complex, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_matrix, octave_complex, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_matrix, octave_complex, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_matrix, octave_complex, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_matrix, octave_complex, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_matrix, octave_complex, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_matrix, octave_complex,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_matrix, octave_complex, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_matrix, octave_complex, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_matrix, octave_complex, sm_cs);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_sparse_matrix, octave_complex,\n                         octave_sparse_complex_matrix);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_sparse_matrix, octave_float_complex,\n                         octave_sparse_complex_matrix);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-sm-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"smx-sm-m.h\"\n#include \"smx-m-sm.h\"\n#include \"ov-re-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse matrix by matrix ops.\n\nDEFBINOP_OP (add, sparse_matrix, matrix, +)\nDEFBINOP_OP (sub, sparse_matrix, matrix, -)\n\nDEFBINOP_OP (mul, sparse_matrix, matrix, *)\n\nDEFBINOP (div, sparse_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  MatrixType typ = v2.matrix_type ();\n\n  Matrix ret = xdiv (v1.matrix_value (), v2.matrix_value (), typ);\n\n  v2.matrix_type (typ);\n  return ret;\n}\n\nDEFBINOPX (pow, sparse_matrix, matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, sparse_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.array_value () / v1.scalar_value ());\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n\n      Matrix ret = xleftdiv (v1.sparse_matrix_value (),\n                             v2.matrix_value (), typ);\n\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (trans_mul, sparse_matrix, matrix, trans_mul);\n\nDEFBINOP_FN (lt, sparse_matrix, matrix, mx_el_lt)\nDEFBINOP_FN (le, sparse_matrix, matrix, mx_el_le)\nDEFBINOP_FN (eq, sparse_matrix, matrix, mx_el_eq)\nDEFBINOP_FN (ge, sparse_matrix, matrix, mx_el_ge)\nDEFBINOP_FN (gt, sparse_matrix, matrix, mx_el_gt)\nDEFBINOP_FN (ne, sparse_matrix, matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, sparse_matrix, matrix, product)\nDEFBINOP_FN (el_div, sparse_matrix, matrix, quotient)\n\nDEFBINOP (el_pow, sparse_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return octave_value (elem_xpow (v1.sparse_matrix_value (),\n                                  SparseMatrix (v2.matrix_value ())));\n}\n\nDEFBINOP (el_ldiv, sparse_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  return octave_value\n         (quotient (v2.matrix_value (), v1.sparse_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_matrix, matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_matrix, matrix, mx_el_or)\n\nDEFCATOP (sm_m, sparse_matrix, matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n  SparseMatrix tmp (v2.matrix_value ());\n  return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));\n}\n\nDEFNDASSIGNOP_FN (assign, sparse_matrix, matrix, matrix, assign);\nDEFNDASSIGNOP_FN (sgl_assign, sparse_matrix, float_matrix, matrix, assign);\n\nvoid\ninstall_sm_m_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_matrix, octave_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_matrix, octave_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_matrix, octave_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_matrix, octave_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_matrix, octave_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_matrix, octave_matrix, ldiv);\n  INSTALL_BINOP_TI (ti, op_trans_mul, octave_sparse_matrix, octave_matrix,\n                    trans_mul);\n  INSTALL_BINOP_TI (ti, op_herm_mul, octave_sparse_matrix, octave_matrix,\n                    trans_mul);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_matrix, octave_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_matrix, octave_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_matrix, octave_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_matrix, octave_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_matrix, octave_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_matrix, octave_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_matrix, octave_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_matrix, octave_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_matrix, octave_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_matrix, octave_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_matrix, octave_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_matrix, octave_matrix,  el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_matrix, octave_matrix, sm_m);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_matrix,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_float_matrix,\n                       sgl_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-sm-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ops.h\"\n#include \"xpow.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"ov-re-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse matrix by scalar ops.\n\nDEFBINOP_OP (add, sparse_matrix, scalar, +)\nDEFBINOP_OP (sub, sparse_matrix, scalar, -)\nDEFBINOP_OP (mul, sparse_matrix, scalar, *)\n\nDEFBINOP (div, sparse_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.sparse_matrix_value () / v2.double_value ());\n}\n\nDEFBINOP (pow, sparse_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  double tmp = v2.scalar_value ();\n  if (static_cast<int> (tmp) == tmp)\n    return xpow (v1.sparse_matrix_value (), tmp);\n  else\n    return xpow (v1.matrix_value (), tmp);\n}\n\nDEFBINOP (ldiv, sparse_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (SparseMatrix(1, 1, v2.scalar_value () / v1.scalar_value ()));\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n      SparseMatrix m1 = v1.sparse_matrix_value ();\n      Matrix m2 = Matrix (1, 1, v2.scalar_value ());\n      Matrix ret = xleftdiv (m1, m2, typ);\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_matrix, scalar, mx_el_lt)\nDEFBINOP_FN (le, sparse_matrix, scalar, mx_el_le)\nDEFBINOP_FN (eq, sparse_matrix, scalar, mx_el_eq)\nDEFBINOP_FN (ge, sparse_matrix, scalar, mx_el_ge)\nDEFBINOP_FN (gt, sparse_matrix, scalar, mx_el_gt)\nDEFBINOP_FN (ne, sparse_matrix, scalar, mx_el_ne)\n\nDEFBINOP_OP (el_mul, sparse_matrix, scalar, *)\n\nDEFBINOP (el_div, sparse_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value (v1.sparse_matrix_value () / v2.double_value ());\n}\n\nDEFBINOP_FN (el_pow, sparse_matrix, scalar, elem_xpow)\n\nDEFBINOP (el_ldiv, sparse_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  return octave_value\n         (elem_xdiv (v2.complex_value (), v1.sparse_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_matrix, scalar, mx_el_and)\nDEFBINOP_FN (el_or, sparse_matrix, scalar, mx_el_or)\n\nDEFCATOP (sm_s, sparse_matrix, scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n  SparseMatrix tmp (1, 1, v2.scalar_value ());\n  return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));\n}\n\nDEFNDASSIGNOP_FN (assign, sparse_matrix, scalar, scalar, assign);\nDEFNDASSIGNOP_FN (sgl_assign, sparse_matrix, float_scalar, scalar, assign);\n\nvoid\ninstall_sm_s_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_matrix, octave_scalar, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_matrix, octave_scalar, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_matrix, octave_scalar, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_matrix, octave_scalar, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_matrix, octave_scalar, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_matrix, octave_scalar, ldiv);\n\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_matrix, octave_scalar, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_matrix, octave_scalar, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_matrix, octave_scalar, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_matrix, octave_scalar, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_matrix, octave_scalar, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_matrix, octave_scalar, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_matrix, octave_scalar, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_matrix, octave_scalar, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_matrix, octave_scalar, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_matrix, octave_scalar, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_matrix, octave_scalar, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_matrix, octave_scalar, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_matrix, octave_scalar, sm_s);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_scalar,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_float_scalar,\n                       sgl_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-sm-scm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\n#include \"sparse-xdiv.h\"\n#include \"sparse-xpow.h\"\n#include \"smx-sm-scm.h\"\n#include \"smx-scm-sm.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse matrix by sparse complex matrix ops.\n\nDEFBINOP_OP (add, sparse_matrix, sparse_complex_matrix, +)\nDEFBINOP_OP (sub, sparse_matrix, sparse_complex_matrix, -)\n\nDEFBINOP_OP (mul, sparse_matrix, sparse_complex_matrix, *)\n\nDEFBINOP (div, sparse_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_matrix_value () / v2.complex_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      SparseComplexMatrix ret = xdiv (v1.sparse_matrix_value (),\n                                      v2.sparse_complex_matrix_value (), typ);\n\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOPX (pow, sparse_matrix, sparse_complex_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, sparse_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.sparse_complex_matrix_value () / v1.scalar_value ());\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n\n      SparseComplexMatrix ret\n        = xleftdiv (v1.sparse_matrix_value (),\n                    v2.sparse_complex_matrix_value (), typ);\n\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_matrix, sparse_complex_matrix, mx_el_lt)\nDEFBINOP_FN (le, sparse_matrix, sparse_complex_matrix, mx_el_le)\nDEFBINOP_FN (eq, sparse_matrix, sparse_complex_matrix, mx_el_eq)\nDEFBINOP_FN (ge, sparse_matrix, sparse_complex_matrix, mx_el_ge)\nDEFBINOP_FN (gt, sparse_matrix, sparse_complex_matrix, mx_el_gt)\nDEFBINOP_FN (ne, sparse_matrix, sparse_complex_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, sparse_matrix, sparse_complex_matrix, product)\nDEFBINOP_FN (el_div, sparse_matrix, sparse_complex_matrix, quotient)\nDEFBINOP_FN (el_pow, sparse_matrix, sparse_complex_matrix, elem_xpow)\n\nDEFBINOP (el_ldiv, sparse_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);\n\n  return octave_value (quotient (v2.sparse_complex_matrix_value (),\n                                 v1.sparse_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_matrix, sparse_complex_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_matrix, sparse_complex_matrix, mx_el_or)\n\nDEFCATOP_FN (sm_scm, sparse_matrix, sparse_complex_matrix, concat)\n\nDEFCONV (sparse_complex_matrix_conv, sparse_matrix, sparse_complex_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v, a);\n  return new octave_sparse_complex_matrix (v.sparse_complex_matrix_value ());\n}\n\nvoid\ninstall_sm_scm_ops (octave::type_info& ti)\n{\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_matrix,\n                    octave_sparse_complex_matrix,\n                    add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_matrix,\n                    octave_sparse_complex_matrix,\n                    sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_matrix,\n                    octave_sparse_complex_matrix,\n                    mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_matrix,\n                    octave_sparse_complex_matrix,\n                    div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_matrix,\n                    octave_sparse_complex_matrix,\n                    pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_matrix,\n                    octave_sparse_complex_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_matrix, octave_sparse_complex_matrix,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_matrix, octave_sparse_complex_matrix,\n                    le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_matrix, octave_sparse_complex_matrix,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_matrix, octave_sparse_complex_matrix,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_matrix, octave_sparse_complex_matrix,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_matrix, octave_sparse_complex_matrix,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_matrix,\n                    octave_sparse_complex_matrix, el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_matrix,\n                    octave_sparse_complex_matrix, el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_matrix,\n                    octave_sparse_complex_matrix, el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_matrix,\n                    octave_sparse_complex_matrix, el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_matrix,\n                    octave_sparse_complex_matrix, el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_matrix,\n                    octave_sparse_complex_matrix, el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_matrix, octave_sparse_complex_matrix,\n                    sm_scm);\n\n  INSTALL_ASSIGNCONV_TI (ti, octave_sparse_matrix, octave_sparse_complex_matrix,\n                         octave_sparse_complex_matrix);\n\n  INSTALL_WIDENOP_TI (ti, octave_sparse_matrix, octave_sparse_complex_matrix,\n                      sparse_complex_matrix_conv);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-sm-sm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n\n#include \"sparse-xpow.h\"\n#include \"sparse-xdiv.h\"\n#include \"ov-re-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// sparse matrix unary ops.\n\nDEFUNOP_OP (not, sparse_matrix, !)\nDEFUNOP_OP (uplus, sparse_matrix, /* no-op */)\nDEFUNOP_OP (uminus, sparse_matrix, -)\n\nDEFUNOP (transpose, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v, a);\n  return octave_value (v.sparse_matrix_value ().transpose (),\n                       v.matrix_type ().transpose ());\n}\n\n// sparse matrix by sparse matrix ops.\n\nDEFBINOP_OP (add, sparse_matrix, sparse_matrix, +)\n\n// DEFBINOP_OP (sub, sparse_matrix, sparse_matrix, -)\n\nstatic octave_value\noct_binop_sub (const octave_base_value& a1, const octave_base_value& a2)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  SparseMatrix m = v1.sparse_matrix_value () - v2.sparse_matrix_value ();\n\n  return octave_value (m);\n}\n\nDEFBINOP_OP (mul, sparse_matrix, sparse_matrix, *)\n\nDEFBINOP (div, sparse_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v2.rows () == 1 && v2.columns () == 1)\n    return octave_value (v1.sparse_matrix_value () / v2.scalar_value ());\n  else\n    {\n      MatrixType typ = v2.matrix_type ();\n      SparseMatrix ret = xdiv (v1.sparse_matrix_value (),\n                               v2.sparse_matrix_value (), typ);\n\n      v2.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOPX (pow, sparse_matrix, sparse_matrix)\n{\n  error (\"can't do A ^ B for A and B both matrices\");\n}\n\nDEFBINOP (ldiv, sparse_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n\n  if (v1.rows () == 1 && v1.columns () == 1)\n    return octave_value (v2.sparse_matrix_value () / v1.double_value ());\n  else\n    {\n      MatrixType typ = v1.matrix_type ();\n\n      SparseMatrix ret = xleftdiv (v1.sparse_matrix_value (),\n                                   v2.sparse_matrix_value (), typ);\n\n      v1.matrix_type (typ);\n      return ret;\n    }\n}\n\nDEFBINOP_FN (lt, sparse_matrix, sparse_matrix, mx_el_lt)\nDEFBINOP_FN (le, sparse_matrix, sparse_matrix, mx_el_le)\nDEFBINOP_FN (eq, sparse_matrix, sparse_matrix, mx_el_eq)\nDEFBINOP_FN (ge, sparse_matrix, sparse_matrix, mx_el_ge)\nDEFBINOP_FN (gt, sparse_matrix, sparse_matrix, mx_el_gt)\nDEFBINOP_FN (ne, sparse_matrix, sparse_matrix, mx_el_ne)\n\nDEFBINOP_FN (el_mul, sparse_matrix, sparse_matrix, product)\nDEFBINOP_FN (el_div, sparse_matrix, sparse_matrix, quotient)\n\nDEFBINOP_FN (el_pow, sparse_matrix, sparse_matrix, elem_xpow)\n\nDEFBINOP (el_ldiv, sparse_matrix, sparse_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);\n  return octave_value\n         (quotient (v2.sparse_matrix_value (), v1.sparse_matrix_value ()));\n}\n\nDEFBINOP_FN (el_and, sparse_matrix, sparse_matrix, mx_el_and)\nDEFBINOP_FN (el_or,  sparse_matrix, sparse_matrix, mx_el_or)\n\nDEFCATOP_FN (sm_sm, sparse_matrix, sparse_matrix, concat)\n\nDEFASSIGNOP_FN (assign, sparse_matrix, sparse_matrix, assign)\n\nDEFNULLASSIGNOP_FN (null_assign, sparse_matrix, delete_elements)\n\nvoid\ninstall_sm_sm_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_not, octave_sparse_matrix, not);\n  INSTALL_UNOP_TI (ti, op_uplus, octave_sparse_matrix, uplus);\n  INSTALL_UNOP_TI (ti, op_uminus, octave_sparse_matrix, uminus);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_sparse_matrix, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_sparse_matrix, transpose);\n\n  INSTALL_BINOP_TI (ti, op_add, octave_sparse_matrix, octave_sparse_matrix, add);\n  INSTALL_BINOP_TI (ti, op_sub, octave_sparse_matrix, octave_sparse_matrix, sub);\n  INSTALL_BINOP_TI (ti, op_mul, octave_sparse_matrix, octave_sparse_matrix, mul);\n  INSTALL_BINOP_TI (ti, op_div, octave_sparse_matrix, octave_sparse_matrix, div);\n  INSTALL_BINOP_TI (ti, op_pow, octave_sparse_matrix, octave_sparse_matrix, pow);\n  INSTALL_BINOP_TI (ti, op_ldiv, octave_sparse_matrix, octave_sparse_matrix,\n                    ldiv);\n  INSTALL_BINOP_TI (ti, op_lt, octave_sparse_matrix, octave_sparse_matrix, lt);\n  INSTALL_BINOP_TI (ti, op_le, octave_sparse_matrix, octave_sparse_matrix, le);\n  INSTALL_BINOP_TI (ti, op_eq, octave_sparse_matrix, octave_sparse_matrix, eq);\n  INSTALL_BINOP_TI (ti, op_ge, octave_sparse_matrix, octave_sparse_matrix, ge);\n  INSTALL_BINOP_TI (ti, op_gt, octave_sparse_matrix, octave_sparse_matrix, gt);\n  INSTALL_BINOP_TI (ti, op_ne, octave_sparse_matrix, octave_sparse_matrix, ne);\n  INSTALL_BINOP_TI (ti, op_el_mul, octave_sparse_matrix, octave_sparse_matrix,\n                    el_mul);\n  INSTALL_BINOP_TI (ti, op_el_div, octave_sparse_matrix, octave_sparse_matrix,\n                    el_div);\n  INSTALL_BINOP_TI (ti, op_el_pow, octave_sparse_matrix, octave_sparse_matrix,\n                    el_pow);\n  INSTALL_BINOP_TI (ti, op_el_ldiv, octave_sparse_matrix, octave_sparse_matrix,\n                    el_ldiv);\n  INSTALL_BINOP_TI (ti, op_el_and, octave_sparse_matrix, octave_sparse_matrix,\n                    el_and);\n  INSTALL_BINOP_TI (ti, op_el_or, octave_sparse_matrix, octave_sparse_matrix,\n                    el_or);\n\n  INSTALL_CATOP_TI (ti, octave_sparse_matrix, octave_sparse_matrix, sm_sm);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_sparse_matrix,\n                       assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_null_matrix,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_null_str,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_null_sq_str,\n                       null_assign);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-str-m.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-str-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFASSIGNOP (assign, char_matrix_str, octave_matrix)\n{\n  OCTAVE_CAST_BASE_VALUE (octave_char_matrix_str&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  octave_value tmp\n    = v2.convert_to_str_internal (false, false,\n                                  a1.is_sq_string () ? '\\'' : '\"');\n\n  v1.assign (idx, tmp.char_array_value ());\n\n  return octave_value ();\n}\n\nDEFNDCHARCATOP_FN (str_m, char_matrix_str, matrix, concat)\n\nDEFNDCHARCATOP_FN (m_str, matrix, char_matrix_str, concat)\n\nvoid\ninstall_str_m_ops (octave::type_info& ti)\n{\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_str, octave_matrix,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_sq_str, octave_matrix,\n                       assign);\n\n  INSTALL_CATOP_TI (ti, octave_char_matrix_str, octave_matrix, str_m);\n  INSTALL_CATOP_TI (ti, octave_char_matrix_sq_str, octave_matrix, str_m);\n\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_char_matrix_str, m_str);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_char_matrix_sq_str, m_str);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-str-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-scalar.h\"\n#include \"ov-str-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nDEFASSIGNOP (assign, char_matrix_str, octave_scalar)\n{\n  OCTAVE_CAST_BASE_VALUE (octave_char_matrix_str&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);\n\n  octave_value tmp\n    = v2.convert_to_str_internal (false, false,\n                                  a1.is_sq_string () ? '\\'' : '\"');\n\n  v1.assign (idx, tmp.char_array_value ());\n\n  return octave_value ();\n}\n\nDEFNDCHARCATOP_FN (str_s, char_matrix_str, scalar, concat)\n\nDEFNDCHARCATOP_FN (s_str, scalar, char_matrix_str, concat)\n\nvoid\ninstall_str_s_ops (octave::type_info& ti)\n{\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_str, octave_scalar,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_sq_str, octave_scalar,\n                       assign);\n\n  INSTALL_CATOP_TI (ti, octave_char_matrix_str, octave_scalar, str_s);\n  INSTALL_CATOP_TI (ti, octave_char_matrix_sq_str, octave_scalar, str_s);\n\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_char_matrix_str, s_str);\n  INSTALL_CATOP_TI (ti, octave_scalar, octave_char_matrix_sq_str, s_str);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-str-str.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-str-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// string unary ops.\n\nDEFUNOP (transpose, char_matrix_str)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix_str&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"transpose not defined for N-D objects\");\n\n  return octave_value (v.char_matrix_value ().transpose (),\n                       a.is_sq_string () ? '\\'' : '\"');\n}\n\n// string by string ops.\n\n#define DEFCHARNDBINOP_FN(name, op, t1, t2, e1, e2, f)                  \\\n  static octave_value                                                   \\\n  CONCAT2(oct_binop_, name) (const octave_base_value& a1,               \\\n                             const octave_base_value& a2)               \\\n  {                                                                     \\\n    const dim_vector& a1_dims = a1.dims ();                             \\\n    const dim_vector& a2_dims = a2.dims ();                             \\\n                                                                        \\\n    bool a1_is_scalar = a1_dims.all_ones ();                            \\\n    bool a2_is_scalar = a2_dims.all_ones ();                            \\\n                                                                        \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \\\n    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \\\n                                                                        \\\n    if (a1_is_scalar)                                                   \\\n      {                                                                 \\\n        if (a2_is_scalar)                                               \\\n          return octave_value ((v1.e1 ## _value ())(0)                  \\\n                               op (v2.e2 ## _value ())(0));             \\\n        else                                                            \\\n          return octave_value (f ((v1.e1 ## _value ())(0),              \\\n                                  v2.e2 ## _value ()));                 \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        if (a2_is_scalar)                                               \\\n          return octave_value (f (v1.e1 ## _value (),                   \\\n                                  (v2.e2 ## _value ())(0)));            \\\n        else                                                            \\\n          return octave_value (f (v1.e1 ## _value (),                   \\\n                                  v2.e2 ## _value ()));                 \\\n      }                                                                 \\\n  }\n\nDEFCHARNDBINOP_FN (lt, <, char_matrix_str, char_matrix_str, char_array,\n                   char_array, mx_el_lt)\nDEFCHARNDBINOP_FN (le, <=, char_matrix_str, char_matrix_str, char_array,\n                   char_array, mx_el_le)\nDEFCHARNDBINOP_FN (eq, ==, char_matrix_str, char_matrix_str, char_array,\n                   char_array, mx_el_eq)\nDEFCHARNDBINOP_FN (ge, >=, char_matrix_str, char_matrix_str, char_array,\n                   char_array, mx_el_ge)\nDEFCHARNDBINOP_FN (gt, >, char_matrix_str, char_matrix_str, char_array,\n                   char_array, mx_el_gt)\nDEFCHARNDBINOP_FN (ne, !=, char_matrix_str, char_matrix_str, char_array,\n                   char_array, mx_el_ne)\n\nDEFASSIGNOP (assign, char_matrix_str, char_matrix_str)\n{\n  OCTAVE_CAST_BASE_VALUE (octave_char_matrix_str&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix_str&, v2, a2);\n\n  v1.assign (idx, v2.char_array_value ());\n  return octave_value ();\n}\n\nDEFNULLASSIGNOP_FN (null_assign, char_matrix_str, delete_elements)\n\nDEFNDCHARCATOP_FN (str_str, char_matrix_str, char_matrix_str, concat)\n\nvoid\ninstall_str_str_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_transpose, octave_char_matrix_str, transpose);\n  INSTALL_UNOP_TI (ti, op_transpose, octave_char_matrix_sq_str, transpose);\n\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_char_matrix_str, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_char_matrix_sq_str, transpose);\n\n  INSTALL_BINOP_TI (ti, op_lt, octave_char_matrix_str, octave_char_matrix_str,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_lt, octave_char_matrix_str, octave_char_matrix_sq_str,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_lt, octave_char_matrix_sq_str, octave_char_matrix_str,\n                    lt);\n  INSTALL_BINOP_TI (ti, op_lt, octave_char_matrix_sq_str,\n                    octave_char_matrix_sq_str,\n                    lt);\n\n  INSTALL_BINOP_TI (ti, op_le, octave_char_matrix_str, octave_char_matrix_str,\n                    le);\n  INSTALL_BINOP_TI (ti, op_le, octave_char_matrix_str, octave_char_matrix_sq_str,\n                    le);\n  INSTALL_BINOP_TI (ti, op_le, octave_char_matrix_sq_str, octave_char_matrix_str,\n                    le);\n  INSTALL_BINOP_TI (ti, op_le, octave_char_matrix_sq_str,\n                    octave_char_matrix_sq_str,\n                    le);\n\n  INSTALL_BINOP_TI (ti, op_eq, octave_char_matrix_str, octave_char_matrix_str,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_eq, octave_char_matrix_str, octave_char_matrix_sq_str,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_eq, octave_char_matrix_sq_str, octave_char_matrix_str,\n                    eq);\n  INSTALL_BINOP_TI (ti, op_eq, octave_char_matrix_sq_str,\n                    octave_char_matrix_sq_str,\n                    eq);\n\n  INSTALL_BINOP_TI (ti, op_ge, octave_char_matrix_str, octave_char_matrix_str,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_ge, octave_char_matrix_str, octave_char_matrix_sq_str,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_ge, octave_char_matrix_sq_str, octave_char_matrix_str,\n                    ge);\n  INSTALL_BINOP_TI (ti, op_ge, octave_char_matrix_sq_str,\n                    octave_char_matrix_sq_str,\n                    ge);\n\n  INSTALL_BINOP_TI (ti, op_gt, octave_char_matrix_str, octave_char_matrix_str,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_gt, octave_char_matrix_str, octave_char_matrix_sq_str,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_gt, octave_char_matrix_sq_str, octave_char_matrix_str,\n                    gt);\n  INSTALL_BINOP_TI (ti, op_gt, octave_char_matrix_sq_str,\n                    octave_char_matrix_sq_str,\n                    gt);\n\n  INSTALL_BINOP_TI (ti, op_ne, octave_char_matrix_str, octave_char_matrix_str,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_ne, octave_char_matrix_str, octave_char_matrix_sq_str,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_ne, octave_char_matrix_sq_str, octave_char_matrix_str,\n                    ne);\n  INSTALL_BINOP_TI (ti, op_ne, octave_char_matrix_sq_str,\n                    octave_char_matrix_sq_str,\n                    ne);\n\n  INSTALL_CATOP_TI (ti, octave_char_matrix_str, octave_char_matrix_str, str_str);\n  INSTALL_CATOP_TI (ti, octave_char_matrix_str, octave_char_matrix_sq_str,\n                    str_str);\n  INSTALL_CATOP_TI (ti, octave_char_matrix_sq_str, octave_char_matrix_str,\n                    str_str);\n  INSTALL_CATOP_TI (ti, octave_char_matrix_sq_str, octave_char_matrix_sq_str,\n                    str_str);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_str,\n                       octave_char_matrix_str,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_str,\n                       octave_char_matrix_sq_str,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_sq_str,\n                       octave_char_matrix_str,\n                       assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_sq_str,\n                       octave_char_matrix_sq_str, assign);\n\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_str, octave_null_matrix,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_str, octave_null_str,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_str, octave_null_sq_str,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_sq_str,\n                       octave_null_matrix,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_sq_str, octave_null_str,\n                       null_assign);\n  INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_char_matrix_sq_str,\n                       octave_null_sq_str,\n                       null_assign);\n\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-struct.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-struct.h\"\n#include \"ov-typeinfo.h\"\n#include \"ops.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// struct ops.\n\nDEFUNOP (transpose, struct)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_struct&, v, a);\n\n  if (v.ndims () > 2)\n    error (\"transpose not defined for N-D objects\");\n\n  return octave_value (v.map_value ().transpose ());\n}\n\nDEFUNOP (scalar_transpose, scalar_struct)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_scalar_struct&, v, a);\n\n  return octave_value (v.scalar_map_value ());\n}\n\nDEFNDCATOP_FN (s_s_concat, struct, struct, map, map, concat)\nDEFNDCATOP_FN (s_ss_concat, struct, scalar_struct, map, map, concat)\nDEFNDCATOP_FN (ss_s_concat, scalar_struct, struct, map, map, concat)\nDEFNDCATOP_FN (ss_ss_concat, scalar_struct, scalar_struct, map, map, concat)\n\nstatic octave_value\noct_catop_struct_matrix (const octave_base_value& a1,\n                         const octave_base_value& a2,\n                         const Array<octave_idx_type>&)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_struct&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);\n\n  NDArray tmp = v2.array_value ();\n  const dim_vector& dv = tmp.dims ();\n\n  if (! dv.all_zero ())\n    error (\"invalid concatenation of structure with matrix\");\n\n  return octave_value (v1.map_value ());\n}\n\nstatic octave_value\noct_catop_matrix_struct (const octave_base_value& a1,\n                         const octave_base_value& a2,\n                         const Array<octave_idx_type>&)\n{\n  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);\n  OCTAVE_CAST_BASE_VALUE (const octave_struct&, v2, a2);\n\n  NDArray tmp = v1.array_value ();\n  const dim_vector& dv = tmp.dims ();\n\n  if (! dv.all_zero ())\n    error (\"invalid concatenation of structure with matrix\");\n\n  return octave_value (v2.map_value ());\n}\n\nvoid\ninstall_struct_ops (octave::type_info& ti)\n{\n  INSTALL_UNOP_TI (ti, op_transpose, octave_struct, transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_struct, transpose);\n\n  INSTALL_UNOP_TI (ti, op_transpose, octave_scalar_struct, scalar_transpose);\n  INSTALL_UNOP_TI (ti, op_hermitian, octave_scalar_struct, scalar_transpose);\n\n  INSTALL_CATOP_TI (ti, octave_struct, octave_struct, s_s_concat);\n  INSTALL_CATOP_TI (ti, octave_struct, octave_scalar_struct, s_ss_concat)\n  INSTALL_CATOP_TI (ti, octave_scalar_struct, octave_struct, ss_s_concat)\n  INSTALL_CATOP_TI (ti, octave_scalar_struct, octave_scalar_struct, ss_ss_concat)\n\n  INSTALL_CATOP_TI (ti, octave_struct, octave_matrix, struct_matrix);\n  INSTALL_CATOP_TI (ti, octave_matrix, octave_struct, matrix_struct);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-ui16-ui16.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-ui16nda-i8.h\"\n#include \"mx-ui16nda-ui8.h\"\n#include \"mx-ui16nda-i16.h\"\n#include \"mx-ui16nda-i32.h\"\n#include \"mx-ui16nda-ui32.h\"\n#include \"mx-ui16nda-i64.h\"\n#include \"mx-ui16nda-ui64.h\"\n\n#include \"mx-ui16nda-i8nda.h\"\n#include \"mx-ui16nda-ui8nda.h\"\n#include \"mx-ui16nda-i16nda.h\"\n#include \"mx-ui16nda-i32nda.h\"\n#include \"mx-ui16nda-ui32nda.h\"\n#include \"mx-ui16nda-i64nda.h\"\n#include \"mx-ui16nda-ui64nda.h\"\n\n#include \"mx-ui16-i8nda.h\"\n#include \"mx-ui16-ui8nda.h\"\n#include \"mx-ui16-i16nda.h\"\n#include \"mx-ui16-i32nda.h\"\n#include \"mx-ui16-ui32nda.h\"\n#include \"mx-ui16-i64nda.h\"\n#include \"mx-ui16-ui64nda.h\"\n\n#include \"mx-ui16nda-s.h\"\n#include \"mx-s-ui16nda.h\"\n\n#include \"mx-ui16nda-nda.h\"\n#include \"mx-nda-ui16nda.h\"\n\n#include \"mx-ui16-nda.h\"\n#include \"mx-nda-ui16.h\"\n\n#include \"mx-ui16nda-fs.h\"\n#include \"mx-fs-ui16nda.h\"\n\n#include \"mx-ui16nda-fnda.h\"\n#include \"mx-fnda-ui16nda.h\"\n\n#include \"mx-ui16-fnda.h\"\n#include \"mx-fnda-ui16.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\n#include \"op-int.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_INT_OPS (uint16)\n\nOCTAVE_MS_INT_ASSIGN_OPS (mi8, uint16_, int8_, int8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui8, uint16_, uint8_, uint8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi16, uint16_, int16_, int16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi32, uint16_, int32_, int32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui32, uint16_, uint32_, uint32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi64, uint16_, int64_, int64_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui64, uint16_, uint64_, uint64_)\n\nOCTAVE_MM_INT_ASSIGN_OPS (mmi8, uint16_, int8_, int8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui8, uint16_, uint8_, uint8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi16, uint16_, int16_, int16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi32, uint16_, int32_, int32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui32, uint16_, uint32_, uint32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi64, uint16_, int64_, int64_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui64, uint16_, uint64_, uint64_)\n\nOCTAVE_MIXED_INT_CMP_OPS (uint16, int8)\nOCTAVE_MIXED_INT_CMP_OPS (uint16, uint8)\nOCTAVE_MIXED_INT_CMP_OPS (uint16, int16)\nOCTAVE_MIXED_INT_CMP_OPS (uint16, int32)\nOCTAVE_MIXED_INT_CMP_OPS (uint16, uint32)\nOCTAVE_MIXED_INT_CMP_OPS (uint16, int64)\nOCTAVE_MIXED_INT_CMP_OPS (uint16, uint64)\n\nvoid\ninstall_ui16_ui16_ops (octave::type_info& ti)\n{\n  OCTAVE_INSTALL_INT_OPS (uint16);\n\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi8, uint16_, int8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui8, uint16_, uint8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi16, uint16_, int16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi32, uint16_, int32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui32, uint16_, uint32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi64, uint16_, int64_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui64, uint16_, uint64_);\n\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi8, uint16_, int8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui8, uint16_, uint8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi16, uint16_, int16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi32, uint16_, int32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui32, uint16_, uint32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi64, uint16_, int64_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui64, uint16_, uint64_);\n\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint16, int8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint16, uint8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint16, int16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint16, int32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint16, uint32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint16, int64);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint16, uint64);\n\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint16, int8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint16, uint8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint16, int16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint16, int32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint16, uint32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint16, int64);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint16, uint64);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-ui32-ui32.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-ui32nda-i8.h\"\n#include \"mx-ui32nda-ui8.h\"\n#include \"mx-ui32nda-i16.h\"\n#include \"mx-ui32nda-ui16.h\"\n#include \"mx-ui32nda-i32.h\"\n#include \"mx-ui32nda-i64.h\"\n#include \"mx-ui32nda-ui64.h\"\n\n#include \"mx-ui32nda-i8nda.h\"\n#include \"mx-ui32nda-ui8nda.h\"\n#include \"mx-ui32nda-i16nda.h\"\n#include \"mx-ui32nda-ui16nda.h\"\n#include \"mx-ui32nda-i32nda.h\"\n#include \"mx-ui32nda-i64nda.h\"\n#include \"mx-ui32nda-ui64nda.h\"\n\n#include \"mx-ui32-i8nda.h\"\n#include \"mx-ui32-ui8nda.h\"\n#include \"mx-ui32-i16nda.h\"\n#include \"mx-ui32-ui16nda.h\"\n#include \"mx-ui32-i32nda.h\"\n#include \"mx-ui32-i64nda.h\"\n#include \"mx-ui32-ui64nda.h\"\n\n#include \"mx-ui32nda-s.h\"\n#include \"mx-s-ui32nda.h\"\n\n#include \"mx-ui32nda-nda.h\"\n#include \"mx-nda-ui32nda.h\"\n\n#include \"mx-ui32-nda.h\"\n#include \"mx-nda-ui32.h\"\n\n#include \"mx-ui32nda-fs.h\"\n#include \"mx-fs-ui32nda.h\"\n\n#include \"mx-ui32nda-fnda.h\"\n#include \"mx-fnda-ui32nda.h\"\n\n#include \"mx-ui32-fnda.h\"\n#include \"mx-fnda-ui32.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\n#include \"op-int.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_INT_OPS (uint32)\n\nOCTAVE_MS_INT_ASSIGN_OPS (mi8, uint32_, int8_, int8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui8, uint32_, uint8_, uint8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi16, uint32_, int16_, int16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui16, uint32_, uint16_, uint16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi32, uint32_, int32_, int32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi64, uint32_, int64_, int64_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui64, uint32_, uint64_, uint64_)\n\nOCTAVE_MM_INT_ASSIGN_OPS (mmi8, uint32_, int8_, int8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui8, uint32_, uint8_, uint8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi16, uint32_, int16_, int16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui16, uint32_, uint16_, uint16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi32, uint32_, int32_, int32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi64, uint32_, int64_, int64_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui64, uint32_, uint64_, uint64_)\n\nOCTAVE_MIXED_INT_CMP_OPS (uint32, int8)\nOCTAVE_MIXED_INT_CMP_OPS (uint32, uint8)\nOCTAVE_MIXED_INT_CMP_OPS (uint32, int16)\nOCTAVE_MIXED_INT_CMP_OPS (uint32, uint16)\nOCTAVE_MIXED_INT_CMP_OPS (uint32, int32)\nOCTAVE_MIXED_INT_CMP_OPS (uint32, int64)\nOCTAVE_MIXED_INT_CMP_OPS (uint32, uint64)\nvoid\ninstall_ui32_ui32_ops (octave::type_info& ti)\n{\n  OCTAVE_INSTALL_INT_OPS (uint32);\n\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi8, uint32_, int8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui8, uint32_, uint8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi16, uint32_, int16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui16, uint32_, uint16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi32, uint32_, int32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi64, uint32_, int64_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui64, uint32_, uint64_);\n\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi8, uint32_, int8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui8, uint32_, uint8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi16, uint32_, int16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui16, uint32_, uint16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi32, uint32_, int32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi64, uint32_, int64_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui64, uint32_, uint64_);\n\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint32, int8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint32, uint8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint32, int16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint32, uint16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint32, int32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint32, int64);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint32, uint64);\n\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint32, int8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint32, uint8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint32, int16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint32, uint16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint32, int32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint32, int64);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint32, uint64);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-ui64-ui64.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-ui64nda-i8.h\"\n#include \"mx-ui64nda-ui8.h\"\n#include \"mx-ui64nda-i16.h\"\n#include \"mx-ui64nda-ui16.h\"\n#include \"mx-ui64nda-i32.h\"\n#include \"mx-ui64nda-ui32.h\"\n#include \"mx-ui64nda-i64.h\"\n\n#include \"mx-ui64nda-i8nda.h\"\n#include \"mx-ui64nda-ui8nda.h\"\n#include \"mx-ui64nda-i16nda.h\"\n#include \"mx-ui64nda-ui16nda.h\"\n#include \"mx-ui64nda-i32nda.h\"\n#include \"mx-ui64nda-ui32nda.h\"\n#include \"mx-ui64nda-i64nda.h\"\n\n#include \"mx-ui64-i8nda.h\"\n#include \"mx-ui64-ui8nda.h\"\n#include \"mx-ui64-i16nda.h\"\n#include \"mx-ui64-ui16nda.h\"\n#include \"mx-ui64-i32nda.h\"\n#include \"mx-ui64-ui32nda.h\"\n#include \"mx-ui64-i64nda.h\"\n\n#include \"mx-ui64nda-s.h\"\n#include \"mx-s-ui64nda.h\"\n\n#include \"mx-ui64nda-nda.h\"\n#include \"mx-nda-ui64nda.h\"\n\n#include \"mx-ui64-nda.h\"\n#include \"mx-nda-ui64.h\"\n\n#include \"mx-ui64nda-fs.h\"\n#include \"mx-fs-ui64nda.h\"\n\n#include \"mx-ui64nda-fnda.h\"\n#include \"mx-fnda-ui64nda.h\"\n\n#include \"mx-ui64-fnda.h\"\n#include \"mx-fnda-ui64.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\n#include \"op-int.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_INT_OPS (uint64)\n\nOCTAVE_MS_INT_ASSIGN_OPS (mi8, uint64_, int8_, int8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui8, uint64_, uint8_, uint8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi16, uint64_, int16_, int16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui16, uint64_, uint16_, uint16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi32, uint64_, int32_, int32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui32, uint64_, uint32_, uint32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi64, uint64_, int64_, int64_)\n\nOCTAVE_MM_INT_ASSIGN_OPS (mmi8, uint64_, int8_, int8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui8, uint64_, uint8_, uint8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi16, uint64_, int16_, int16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui16, uint64_, uint16_, uint16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi32, uint64_, int32_, int32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui32, uint64_, uint32_, uint32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi64, uint64_, int64_, int64_)\n\nOCTAVE_MIXED_INT_CMP_OPS (uint64, int8)\nOCTAVE_MIXED_INT_CMP_OPS (uint64, uint8)\nOCTAVE_MIXED_INT_CMP_OPS (uint64, int16)\nOCTAVE_MIXED_INT_CMP_OPS (uint64, uint16)\nOCTAVE_MIXED_INT_CMP_OPS (uint64, int32)\nOCTAVE_MIXED_INT_CMP_OPS (uint64, uint32)\nOCTAVE_MIXED_INT_CMP_OPS (uint64, int64)\n\nvoid\ninstall_ui64_ui64_ops (octave::type_info& ti)\n{\n  OCTAVE_INSTALL_INT_OPS (uint64);\n\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi8, uint64_, int8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui8, uint64_, uint8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi16, uint64_, int16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui16, uint64_, uint16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi32, uint64_, int32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui32, uint64_, uint32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi64, uint64_, int64_);\n\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi8, uint64_, int8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui8, uint64_, uint8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi16, uint64_, int16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui16, uint64_, uint16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi32, uint64_, int32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui32, uint64_, uint32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi64, uint64_, int64_);\n\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, int8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, uint8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, int16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, uint16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, int32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, uint32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, int64);\n\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, int8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, uint8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, int16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, uint16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, int32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, uint32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, int64);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/op-ui8-ui8.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mx-ui8nda-i8.h\"\n#include \"mx-ui8nda-i16.h\"\n#include \"mx-ui8nda-ui16.h\"\n#include \"mx-ui8nda-i32.h\"\n#include \"mx-ui8nda-ui32.h\"\n#include \"mx-ui8nda-i64.h\"\n#include \"mx-ui8nda-ui64.h\"\n\n#include \"mx-ui8nda-i8nda.h\"\n#include \"mx-ui8nda-i16nda.h\"\n#include \"mx-ui8nda-ui16nda.h\"\n#include \"mx-ui8nda-i32nda.h\"\n#include \"mx-ui8nda-ui32nda.h\"\n#include \"mx-ui8nda-i64nda.h\"\n#include \"mx-ui8nda-ui64nda.h\"\n\n#include \"mx-ui8-i8nda.h\"\n#include \"mx-ui8-i16nda.h\"\n#include \"mx-ui8-ui16nda.h\"\n#include \"mx-ui8-i32nda.h\"\n#include \"mx-ui8-ui32nda.h\"\n#include \"mx-ui8-i64nda.h\"\n#include \"mx-ui8-ui64nda.h\"\n\n#include \"mx-ui8nda-s.h\"\n#include \"mx-s-ui8nda.h\"\n\n#include \"mx-ui8nda-nda.h\"\n#include \"mx-nda-ui8nda.h\"\n\n#include \"mx-ui8-nda.h\"\n#include \"mx-nda-ui8.h\"\n\n#include \"mx-ui8nda-fs.h\"\n#include \"mx-fs-ui8nda.h\"\n\n#include \"mx-ui8nda-fnda.h\"\n#include \"mx-fnda-ui8nda.h\"\n\n#include \"mx-ui8-fnda.h\"\n#include \"mx-fnda-ui8.h\"\n\n#include \"errwarn.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-int16.h\"\n#include \"ov-int32.h\"\n#include \"ov-int64.h\"\n#include \"ov-int8.h\"\n#include \"ov-uint16.h\"\n#include \"ov-uint32.h\"\n#include \"ov-uint64.h\"\n#include \"ov-uint8.h\"\n#include \"ov-scalar.h\"\n#include \"ov-float.h\"\n#include \"ov-complex.h\"\n#include \"ov-flt-complex.h\"\n#include \"ov-re-mat.h\"\n#include \"ov-flt-re-mat.h\"\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-typeinfo.h\"\n#include \"ov-null-mat.h\"\n#include \"ops.h\"\n#include \"xdiv.h\"\n#include \"xpow.h\"\n\n#include \"op-int.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_INT_OPS (uint8)\n\nOCTAVE_MS_INT_ASSIGN_OPS (mi8, uint8_, int8_, int8_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi16, uint8_, int16_, int16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui16, uint8_, uint16_, uint16_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi32, uint8_, int32_, int32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui32, uint8_, uint32_, uint32_)\nOCTAVE_MS_INT_ASSIGN_OPS (mi64, uint8_, int64_, int64_)\nOCTAVE_MS_INT_ASSIGN_OPS (mui64, uint8_, uint64_, uint64_)\n\nOCTAVE_MM_INT_ASSIGN_OPS (mmi8, uint8_, int8_, int8_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi16, uint8_, int16_, int16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui16, uint8_, uint16_, uint16_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi32, uint8_, int32_, int32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui32, uint8_, uint32_, uint32_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmi64, uint8_, int64_, int64_)\nOCTAVE_MM_INT_ASSIGN_OPS (mmui64, uint8_, uint64_, uint64_)\n\nOCTAVE_MIXED_INT_CMP_OPS (uint8, int8)\nOCTAVE_MIXED_INT_CMP_OPS (uint8, int16)\nOCTAVE_MIXED_INT_CMP_OPS (uint8, uint16)\nOCTAVE_MIXED_INT_CMP_OPS (uint8, int32)\nOCTAVE_MIXED_INT_CMP_OPS (uint8, uint32)\nOCTAVE_MIXED_INT_CMP_OPS (uint8, int64)\nOCTAVE_MIXED_INT_CMP_OPS (uint8, uint64)\n\nvoid\ninstall_ui8_ui8_ops (octave::type_info& ti)\n{\n  OCTAVE_INSTALL_INT_OPS (uint8)\n\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi8, uint8_, int8_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi16, uint8_, int16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui16, uint8_, uint16_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi32, uint8_, int32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui32, uint8_, uint32_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi64, uint8_, int64_);\n  OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui64, uint8_, uint64_);\n\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi8, uint8_, int8_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi16, uint8_, int16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui16, uint8_, uint16_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi32, uint8_, int32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui32, uint8_, uint32_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi64, uint8_, int64_);\n  OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui64, uint8_, uint64_);\n\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint8, int8);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint8, int16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint8, uint16);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint8, int32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint8, uint32);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint8, int64);\n  OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint8, uint64);\n\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint8, int8);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint8, int16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint8, uint16);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint8, int32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint8, uint32);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint8, int64);\n  OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint8, uint64);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/operators/ops.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ops_h)\n#define octave_ops_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-util.h\"\n#include \"error.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass type_info;\n\nOCTAVE_END_NAMESPACE(octave)\n\n// NOTE: If OCTAVE_ENABLE_INTERNAL_CHECKS is defined, then\n// OCTAVE_DYNAMIC_CAST is only safe if you can ensure that the cast will\n// succeed.  Using static_cast disables the RTTI checks used by\n// dynamic_cast that ensure an unsuccesful cast will either throw an\n// error for reference types or return nullptr for pointer types.\n\n#if defined (OCTAVE_ENABLE_INTERNAL_CHECKS)\n#  define OCTAVE_DYNAMIC_CAST dynamic_cast\n#else\n#  define OCTAVE_DYNAMIC_CAST static_cast\n#endif\n\n#define OCTAVE_CAST_BASE_VALUE(T, T_VAL, BASE_VAL)      \\\n  T T_VAL = OCTAVE_DYNAMIC_CAST<T> (BASE_VAL)\n\n// Concatenation macros that enforce argument prescan\n#define CONCAT2X(x, y) x ## y\n#define CONCAT2(x, y) CONCAT2X (x, y)\n\n#define CONCAT3X(x, y, z) x ## y ## z\n#define CONCAT3(x, y, z) CONCAT3X (x, y, z)\n\n#define INSTALL_UNOP_TI(ti, op, t, f)                                   \\\n  ti.install_unary_op                                                   \\\n  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));\n\n#define INSTALL_NCUNOP_TI(ti, op, t, f)                                 \\\n  ti.install_non_const_unary_op                                         \\\n  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));\n\n#define INSTALL_BINOP_TI(ti, op, t1, t2, f)                             \\\n  ti.install_binary_op                                                  \\\n  (octave_value::op, t1::static_type_id (), t2::static_type_id (),      \\\n   CONCAT2 (oct_binop_, f));\n\n#define INSTALL_CATOP_TI(ti, t1, t2, f)                                 \\\n  ti.install_cat_op                                                     \\\n  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_catop_, f));\n\n#define INSTALL_ASSIGNOP_TI(ti, op, t1, t2, f)                          \\\n  ti.install_assign_op                                                  \\\n  (octave_value::op, t1::static_type_id (), t2::static_type_id (),      \\\n   CONCAT2 (oct_assignop_, f));\n\n#define INSTALL_ASSIGNANYOP_TI(ti, op, t1, f)                           \\\n  ti.install_assignany_op                                               \\\n  (octave_value::op, t1::static_type_id (), CONCAT2 (oct_assignop_, f));\n\n#define INSTALL_ASSIGNCONV_TI(ti, t1, t2, tr)                           \\\n  ti.install_pref_assign_conv                                           \\\n  (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ());\n\n#define INSTALL_WIDENOP_TI(ti, t1, t2, f)                               \\\n  ti.install_widening_op                                                \\\n  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_conv_, f));\n\n#define DEFASSIGNOP(name, t1, t2)                               \\\n  static octave_value                                           \\\n  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,         \\\n                                 const octave_value_list& idx,  \\\n                                 const octave_base_value& a2)\n\n#define DEFASSIGNOP_FN(name, t1, t2, f)                                 \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,                 \\\n                                 const octave_value_list& idx,          \\\n                                 const octave_base_value& a2)           \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);            \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    v1.f (idx, v2.CONCAT2 (t1, _value) ());                             \\\n    return octave_value ();                                             \\\n  }\n\n#define DEFNULLASSIGNOP_FN(name, t, f)                          \\\n  static octave_value                                           \\\n  CONCAT2 (oct_assignop_, name) (octave_base_value& a,          \\\n                                 const octave_value_list& idx,  \\\n                                 const octave_base_value&)      \\\n  {                                                             \\\n    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t)&, v, a);       \\\n                                                                \\\n    v.f (idx);                                                  \\\n    return octave_value ();                                     \\\n  }\n\n#define DEFNDASSIGNOP_FN(name, t1, t2, e, f)                            \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,                 \\\n                                 const octave_value_list& idx,          \\\n                                 const octave_base_value& a2)           \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);            \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    v1.f (idx, v2.CONCAT2 (e, _value) ());                              \\\n    return octave_value ();                                             \\\n  }\n\n// FIXME: the following currently don't handle index.\n\n#define DEFNDASSIGNOP_OP(name, t1, t2, f, op)                                                           \\\n  static octave_value                                                                                   \\\n  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,                                                 \\\n                                 const octave_value_list& idx,                                          \\\n                                 const octave_base_value& a2)                                           \\\n  {                                                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);                                            \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);                                      \\\n                                                                                                        \\\n    if (! idx.empty ())                                                                                 \\\n      error (\"unexpected: index is not empty in oct_assignop_ \" #name \" - please report this bug\");     \\\n    v1.matrix_ref () op v2.CONCAT2 (f, _value) ();                                                      \\\n                                                                                                        \\\n    return octave_value ();                                                                             \\\n  }\n\n#define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop)                                                       \\\n  static octave_value                                                                                   \\\n  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,                                                 \\\n                                 const octave_value_list& idx,                                          \\\n                                 const octave_base_value& a2)                                           \\\n  {                                                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);                                            \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);                                      \\\n                                                                                                        \\\n    if (! idx.empty ())                                                                                 \\\n      error (\"unexpected: index is not empty in oct_assignop_ \" #name \" - please report this bug\");     \\\n    fnop (v1.matrix_ref (), v2.CONCAT2 (f, _value) ());                                                 \\\n                                                                                                        \\\n    return octave_value ();                                                                             \\\n  }\n\n#define DEFASSIGNANYOP_FN(name, t1, f)                          \\\n  static octave_value                                           \\\n  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,         \\\n                                 const octave_value_list& idx,  \\\n                                 const octave_value& a2)        \\\n  {                                                             \\\n    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);    \\\n                                                                \\\n    v1.f (idx, a2);                                             \\\n    return octave_value ();                                     \\\n  }\n\n#define CONVDECL(name)                                          \\\n  static octave_base_value *                                    \\\n  CONCAT2 (oct_conv_, name) (const octave_base_value& a)\n\n#define DEFCONV(name, a_dummy, b_dummy)         \\\n  CONVDECL (name)\n\n#define DEFUNOPX(name, t)                               \\\n  static octave_value                                   \\\n  CONCAT2 (oct_unop_, name) (const octave_base_value&)\n\n#define DEFUNOP(name, t)                                        \\\n  static octave_value                                           \\\n  CONCAT2 (oct_unop_, name) (const octave_base_value& a)\n\n#define DEFUNOP_OP(name, t, op)                                 \\\n  static octave_value                                           \\\n  CONCAT2 (oct_unop_, name) (const octave_base_value& a)        \\\n  {                                                             \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \\\n    return octave_value (op v.CONCAT2 (t, _value) ());          \\\n  }\n\n#define DEFNDUNOP_OP(name, t, e, op)                            \\\n  static octave_value                                           \\\n  CONCAT2 (oct_unop_, name) (const octave_base_value& a)        \\\n  {                                                             \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \\\n    return octave_value (op v.CONCAT2 (e, _value) ());          \\\n  }\n\n// FIXME: in some cases, the constructor isn't necessary.\n\n#define DEFUNOP_FN(name, t, f)                                  \\\n  static octave_value                                           \\\n  CONCAT2 (oct_unop_, name) (const octave_base_value& a)        \\\n  {                                                             \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \\\n    return octave_value (f (v.CONCAT2 (t, _value) ()));         \\\n  }\n\n#define DEFNDUNOP_FN(name, t, e, f)                             \\\n  static octave_value                                           \\\n  CONCAT2 (oct_unop_, name) (const octave_base_value& a)        \\\n  {                                                             \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \\\n    return octave_value (f (v.CONCAT2 (e, _value) ()));         \\\n  }\n\n#define DEFNCUNOP_METHOD(name, t, method)                       \\\n  static void                                                   \\\n  CONCAT2 (oct_unop_, name) (octave_base_value& a)              \\\n  {                                                             \\\n    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t)&, v, a);       \\\n    v.method ();                                                \\\n  }\n\n#define DEFBINOPX(name, t1, t2)                         \\\n  static octave_value                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value&, \\\n                              const octave_base_value&)\n\n#define DEFBINOP(name, t1, t2)                                  \\\n  static octave_value                                           \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,      \\\n                              const octave_base_value& a2)\n\n#define DEFBINOP_OP(name, t1, t2, op)                                   \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    return octave_value                                                 \\\n      (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ());       \\\n  }\n\n#define DEFCMPLXCMPOP_OP(name, t1, t2, op)                              \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    warn_complex_cmp ();                                                \\\n                                                                        \\\n    return octave_value                                                 \\\n      (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ());       \\\n  }\n\n#define DEFSCALARBOOLOP_OP(name, t1, t2, op)                            \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    if (octave::math::isnan (v1.CONCAT2 (t1, _value) ()) || octave::math::isnan (v2.CONCAT2 (t2, _value) ())) \\\n      octave::err_nan_to_logical_conversion ();                         \\\n                                                                        \\\n    return octave_value                                                 \\\n      (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ());       \\\n  }\n\n#define DEFNDBINOP_OP(name, t1, t2, e1, e2, op)                         \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    return octave_value                                                 \\\n      (v1.CONCAT2 (e1, _value) () op v2.CONCAT2 (e2, _value) ());       \\\n  }\n\n// FIXME: in some cases, the constructor isn't necessary.\n\n#define DEFBINOP_FN(name, t1, t2, f)                                    \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    return octave_value (f (v1.CONCAT2 (t1, _value) (), v2.CONCAT2 (t2, _value) ())); \\\n  }\n\n#define DEFNDBINOP_FN(name, t1, t2, e1, e2, f)                          \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \\\n  }\n\n#define DEFNDCMPLXCMPOP_FN(name, t1, t2, e1, e2, f)                     \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2)              \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \\\n  }\n\n#define DEFCATOPX(name, t1, t2)                                         \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_catop_, name) (const octave_base_value&,                 \\\n                              const octave_base_value&,                 \\\n                              const Array<octave_idx_type>& ra_idx)\n\n#define DEFCATOP(name, t1, t2)                                          \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_catop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2,              \\\n                              const Array<octave_idx_type>& ra_idx)\n\n// FIXME: in some cases, the constructor isn't necessary.\n\n#define DEFCATOP_FN(name, t1, t2, f)                                    \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_catop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2,              \\\n                              const Array<octave_idx_type>& ra_idx)     \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    return octave_value (v1.CONCAT2 (t1, _value) () . f (v2.CONCAT2 (t2, _value) (), ra_idx)); \\\n  }\n\n#define DEFNDCATOP_FN(name, t1, t2, e1, e2, f)                          \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_catop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2,              \\\n                              const Array<octave_idx_type>& ra_idx)     \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    return octave_value (v1.CONCAT2 (e1, _value) () . f (v2.CONCAT2 (e2, _value) (), ra_idx)); \\\n  }\n\n#define DEFNDCHARCATOP_FN(name, t1, t2, f)                              \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_catop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2,              \\\n                              const Array<octave_idx_type>& ra_idx)     \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \\\n                         ((a1.is_sq_string () || a2.is_sq_string ())    \\\n                          ? '\\'' : '\"'));                               \\\n  }\n\n// For compatibility, the second arg is always converted to the type\n// of the first.  Hmm.\n\n#define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f)               \\\n  static octave_value                                                   \\\n  CONCAT2 (oct_catop_, name) (const octave_base_value& a1,              \\\n                              const octave_base_value& a2,              \\\n                              const Array<octave_idx_type>& ra_idx)     \\\n  {                                                                     \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \\\n    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \\\n                                                                        \\\n    return octave_value (tc1 (v1.CONCAT2 (e1, _value) ()) . f (tc2 (v2.CONCAT2 (e2, _value) ()), ra_idx)); \\\n  }\n\n#endif\n"
  },
  {
    "path": "libinterp/options.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_options_h)\n#define octave_options_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n// This is here so that it's more likely that the usage message and\n// the real set of options will agree.  Note: the '+' must come first\n// to prevent getopt from permuting arguments!\nstatic const char *short_opts = \"+GHWVe:fghip:qvx\";\n\n// Long options.  See the comments in getopt.h for the meanings of the\n// fields in this structure.\n#define BUILT_IN_DOCSTRINGS_FILE_OPTION 1\n#define DOC_CACHE_FILE_OPTION 2\n#define EXEC_PATH_OPTION 3\n#define EXPERIMENTAL_TERMINAL_WIDGET_OPTION 4\n#define IMAGE_PATH_OPTION 5\n#define INFO_FILE_OPTION 6\n#define INFO_PROG_OPTION 7\n#define LINE_EDITING_OPTION 8\n#define NO_GUI_LIBS_OPTION 9\n#define NO_INIT_USER_OPTION 10\n#define NO_INIT_PATH_OPTION 11\n#define NO_INIT_SITE_OPTION 12\n#define NO_LINE_EDITING_OPTION 13\n#define NO_STARTUP_TESTS_OPTION 14\n#define PERSIST_OPTION 15\n#define SERVER_OPTION 16\n#define TEXI_MACROS_FILE_OPTION 17\n#define TRADITIONAL_OPTION 18\nstruct octave_getopt_options long_opts[] =\n{\n  // Alias for --traditional, not displayed in help\n  { \"braindead\",                octave_no_arg,       nullptr, TRADITIONAL_OPTION },\n  // Option for developers, not displayed in help\n  { \"built-in-docstrings-file\", octave_required_arg, nullptr, BUILT_IN_DOCSTRINGS_FILE_OPTION },\n  // FIXME: Disabled debug option for parser 2023-12-29.\n  // Uncomment and restore code if Octave adds capability to\n  // immediately enter debug mode for a script.\n  // { \"debug\",                    octave_no_arg,       nullptr, 'd' },\n  // Option for developers, not displayed in help\n  { \"doc-cache-file\",           octave_required_arg, nullptr, DOC_CACHE_FILE_OPTION },\n  { \"echo-commands\",            octave_no_arg,       nullptr, 'x' },\n  { \"eval\",                     octave_required_arg, nullptr, 'e' },\n  // Option for developers, not displayed in help\n  { \"exec-path\",                octave_required_arg, nullptr, EXEC_PATH_OPTION },\n  { \"experimental-terminal-widget\", octave_no_arg,   nullptr, EXPERIMENTAL_TERMINAL_WIDGET_OPTION },\n  // Alias for --gui, not displayed in help, eventually will be deprecated\n  { \"force-gui\",                octave_no_arg,       nullptr, 'g' },\n  { \"gui\",                      octave_no_arg,       nullptr, 'g' },\n  { \"help\",                     octave_no_arg,       nullptr, 'h' },\n  // Option for developers, not displayed in help\n  { \"image-path\",               octave_required_arg, nullptr, IMAGE_PATH_OPTION },\n  // Option for developers, not displayed in help\n  { \"info-file\",                octave_required_arg, nullptr, INFO_FILE_OPTION },\n  // Option for developers, not displayed in help\n  { \"info-program\",             octave_required_arg, nullptr, INFO_PROG_OPTION },\n  // Option for developers, not displayed in help\n  { \"init-trace\",               octave_no_arg,       nullptr, 'V' },\n  { \"interactive\",              octave_no_arg,       nullptr, 'i' },\n  { \"line-editing\",             octave_no_arg,       nullptr, LINE_EDITING_OPTION },\n  { \"no-gui\",                   octave_no_arg,       nullptr, 'G' },\n  // Option for developers, not displayed in help\n  { \"no-gui-libs\",              octave_no_arg,       nullptr, NO_GUI_LIBS_OPTION },\n  { \"no-history\",               octave_no_arg,       nullptr, 'H' },\n  { \"no-init-all\",              octave_no_arg,       nullptr, 'f' },\n  // Alias for --no-init-user, not displayed in help\n  { \"no-init-file\",             octave_no_arg,       nullptr, NO_INIT_USER_OPTION },\n  { \"no-init-path\",             octave_no_arg,       nullptr, NO_INIT_PATH_OPTION },\n  { \"no-init-user\",             octave_no_arg,       nullptr, NO_INIT_USER_OPTION },\n  { \"no-line-editing\",          octave_no_arg,       nullptr, NO_LINE_EDITING_OPTION },\n  { \"no-init-site\",             octave_no_arg,       nullptr, NO_INIT_SITE_OPTION },\n  // Alias for --no-init-site, not displayed in help\n  { \"no-site-file\",             octave_no_arg,       nullptr, NO_INIT_SITE_OPTION },\n  { \"no-startup-tests\",         octave_no_arg,       nullptr, NO_STARTUP_TESTS_OPTION },\n  { \"no-window-system\",         octave_no_arg,       nullptr, 'W' },\n  { \"norc\",                     octave_no_arg,       nullptr, 'f' },\n  { \"path\",                     octave_required_arg, nullptr, 'p' },\n  { \"persist\",                  octave_no_arg,       nullptr, PERSIST_OPTION },\n  { \"quiet\",                    octave_no_arg,       nullptr, 'q' },\n  { \"server\",                   octave_no_arg,       nullptr, SERVER_OPTION },\n  { \"silent\",                   octave_no_arg,       nullptr, 'q' },\n  // Option for developers, not displayed in help\n  { \"texi-macros-file\",         octave_required_arg, nullptr, TEXI_MACROS_FILE_OPTION },\n  { \"traditional\",              octave_no_arg,       nullptr, TRADITIONAL_OPTION },\n  // Alias for --init-trace, not displayed in help, eventually will be deprecated\n  { \"verbose\",                  octave_no_arg,       nullptr, 'V' },\n  { \"version\",                  octave_no_arg,       nullptr, 'v' },\n  { nullptr,                    0,                   nullptr, 0 }\n};\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/anon-fcn-validator.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"anon-fcn-validator.h\"\n#include \"ov.h\"\n#include \"pt-all.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nanon_fcn_validator::anon_fcn_validator (tree_parameter_list *, tree_expression *expr)\n{\n  expr->accept (*this);\n}\n\nvoid\nanon_fcn_validator::visit_postfix_expression (tree_postfix_expression& expr)\n{\n  octave_value::unary_op op = expr.op_type ();\n\n  if (op == octave_value::op_incr || op == octave_value::op_decr)\n    error (expr);\n  else\n    tree_walker::visit_postfix_expression (expr);\n}\n\nvoid\nanon_fcn_validator::visit_prefix_expression (tree_prefix_expression& expr)\n{\n  octave_value::unary_op op = expr.op_type ();\n\n  if (op == octave_value::op_incr || op == octave_value::op_decr)\n    error (expr);\n  else\n    tree_walker::visit_prefix_expression (expr);\n}\n\nvoid\nanon_fcn_validator::visit_multi_assignment (tree_multi_assignment& expr)\n{\n  error (expr);\n}\n\nvoid\nanon_fcn_validator::visit_simple_assignment (tree_simple_assignment& expr)\n{\n  error (expr);\n}\n\nvoid\nanon_fcn_validator::error (tree_expression& expr)\n{\n  m_ok = false;\n  m_beg_pos = expr.beg_pos ();\n  m_end_pos = expr.end_pos ();\n  m_message = \"invalid use of operator \" + expr.op_str () + \" in anonymous function\";\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/anon-fcn-validator.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_anon_fcn_validator_h)\n#define octave_anon_fcn_validator_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"filepos.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_expression;\nclass tree_parameter_list;\n\n// How to check the semantics of the code that the parse trees represent.\n\nclass anon_fcn_validator : public tree_walker\n{\npublic:\n\n  anon_fcn_validator (tree_parameter_list *, tree_expression *expr);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (anon_fcn_validator)\n\n  ~anon_fcn_validator () = default;\n\n  void visit_postfix_expression (tree_postfix_expression&);\n\n  void visit_prefix_expression (tree_prefix_expression&);\n\n  void visit_multi_assignment (tree_multi_assignment&);\n\n  void visit_simple_assignment (tree_simple_assignment&);\n\n  bool ok () const { return m_ok; }\n\n  filepos beg_pos () const { return m_beg_pos; }\n  filepos end_pos () const { return m_end_pos; }\n\n  std::string message () const { return m_message; }\n\nprivate:\n\n  void error (tree_expression& expr);\n\n  //--------\n\n  bool m_ok {true};\n  filepos m_beg_pos;\n  filepos m_end_pos;\n  std::string m_message;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/bp-table.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <limits>\n#include <list>\n#include <map>\n#include <set>\n#include <string>\n#include <vector>\n\n#include \"file-ops.h\"\n#include \"oct-env.h\"\n\n#include \"bp-table.h\"\n#include \"cdef-utils.h\"\n#include \"defun-int.h\"\n#include \"error.h\"\n#include \"event-manager.h\"\n#include \"interpreter.h\"\n#include \"interpreter-private.h\"\n#include \"oct-map.h\"\n#include \"ov-usr-fcn.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"pt-eval.h\"\n#include \"pt-exp.h\"\n#include \"pt-stmt.h\"\n#include \"sighandlers.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass bp_file_info\n{\npublic:\n\n  bp_file_info (tree_evaluator& tw, const std::string& file)\n    : m_ok (false), m_file (file), m_dir (), m_fcn (), m_class_name ()\n  {\n    std::string abs_file = sys::env::make_absolute (file);\n\n    std::string dir = sys::file_ops::dirname (abs_file);\n    std::string fcn = sys::file_ops::tail (abs_file);\n    std::size_t len = fcn.length ();\n    if (len >= 2 && fcn[len-2] == '.' && fcn[len-1] == 'm')\n      fcn = fcn.substr (0, len-2);\n\n    std::size_t pos = dir.rfind (sys::file_ops::dir_sep_chars ());\n\n    if (pos != std::string::npos && pos < dir.length () - 1)\n      {\n        if (dir[pos+1] == '@')\n          {\n            m_class_name = dir.substr (pos+1);\n\n            fcn = sys::file_ops::concat (m_class_name, fcn);\n\n            dir = dir.substr (0, pos);\n          }\n      }\n\n    m_dir = dir;\n    m_fcn = fcn;\n\n    interpreter& interp = tw.get_interpreter ();\n\n    load_path& lp = interp.get_load_path ();\n\n    if (lp.contains_file_in_dir (m_file, m_dir))\n      m_ok = true;\n  }\n\n  std::string file () const { return m_file; }\n  std::string dir () const { return m_fcn; }\n  std::string fcn () const { return m_fcn; }\n  std::string class_name () const { return m_class_name; }\n\n  bool ok () const { return m_ok; }\n\nprivate:\n\n  bool m_ok;\n  std::string m_file;\n  std::string m_dir;\n  std::string m_fcn;\n  std::string m_class_name;\n};\n\n// Clear all reasons to stop, other than breakpoints.\n\nvoid\nbp_table::dbclear_all_signals ()\n{\n  interpreter& interp = m_evaluator.get_interpreter ();\n  error_system& es = interp.get_error_system ();\n\n  es.debug_on_error (false);\n  bp_table::m_errors_that_stop.clear ();\n\n  es.debug_on_caught (false);\n  bp_table::m_caught_that_stop.clear ();\n\n  es.debug_on_warning (false);\n  bp_table::m_warnings_that_stop.clear ();\n\n  Vdebug_on_interrupt = false;\n}\n\n// Process the \"warn\", \"errs\", \"caught\" and \"intr\" fields for a call of\n// \"dbstop (p)\".\n\nvoid\nbp_table::dbstop_process_map_args (const octave_map& mv)\n{\n  interpreter& interp = m_evaluator.get_interpreter ();\n  error_system& es = interp.get_error_system ();\n\n  // process errs\n  // why so many levels of indirection needed?\n  bool fail = false;\n  Cell U = mv.contents (\"errs\");\n  if (U.numel () != 1)\n    fail = (U.numel () > 1);\n  else\n    {\n      Array<octave_value> W = U.index (0);\n      if (W.isempty () || W(0).isempty ())\n        es.debug_on_error (true);    // like \"dbstop if error\" with no identifier\n      else if (! W(0).iscell ())\n        fail = true;\n      else\n        {\n          Cell V = W(0).cell_value ();\n          for (int i = 0; i < V.numel (); i++)\n            {\n              m_errors_that_stop.insert (V(i).string_value ());\n              es.debug_on_error (true);\n            }\n        }\n    }\n\n  if (fail)\n    error (\"dbstop: invalid 'errs' field\");\n\n  // process caught\n  // why so many levels of indirection needed?\n  fail = false;\n  U = mv.contents (\"caught\");\n  if (U.numel () != 1)\n    fail = (U.numel () > 1);\n  else\n    {\n      Array<octave_value> W = U.index (0);\n      if (W.isempty () || W(0).isempty ())\n        es.debug_on_caught (true);  // like \"dbstop if caught error\" with no ID\n      else if (! W(0).iscell ())\n        fail = true;\n      else\n        {\n          Cell V = W(0).cell_value ();\n          for (int i = 0; i < V.numel (); i++)\n            {\n              m_caught_that_stop.insert (V(i).string_value ());\n              es.debug_on_caught (true);\n            }\n        }\n    }\n\n  if (fail)\n    error (\"dbstop: invalid 'caught' field\");\n\n  // process warn\n  // why so many levels of indirection needed?\n  fail = false;\n  U = mv.contents (\"warn\");\n  if (U.numel () != 1)\n    fail = (U.numel () > 1);\n  else\n    {\n      Array<octave_value> W = U.index (0);\n      if (W.isempty () || W(0).isempty ())\n        es.debug_on_warning (true);    // like \"dbstop if warning\" with no identifier\n      else if (! W(0).iscell ())\n        fail = true;\n      else\n        {\n          Cell V = W(0).cell_value ();\n          for (int i = 0; i < V.numel (); i++)\n            {\n              m_warnings_that_stop.insert (V(i).string_value ());\n              es.debug_on_warning (true);\n            }\n        }\n    }\n\n  if (fail)\n    error (\"dbstop: invalid 'warn' field\");\n\n  // process interrupt\n  if (mv.isfield (\"intr\"))\n    Vdebug_on_interrupt = true;\n}\n\n// Insert a breakpoint in function fcn at line within file fname,\n// to stop only when condition is true.\n// Record in m_bp_set that fname contains a breakpoint.\n\nbool\nbp_table::add_breakpoint_1 (octave_user_code *fcn,\n                            const std::string& fcn_ident,\n                            const bp_table::bp_lines& line,\n                            const std::string& condition,\n                            bp_table::bp_lines& retval)\n{\n  bool found = false;\n\n  tree_statement_list *cmds = fcn->body ();\n\n  std::string file = fcn->fcn_file_name ();\n\n  if (cmds)\n    {\n      interpreter& interp = m_evaluator.get_interpreter ();\n\n      event_manager& evmgr = interp.get_event_manager ();\n\n      retval = cmds->add_breakpoint (evmgr, file, line, condition);\n\n      for (auto& lineno : retval)\n        {\n          if (lineno != 0)\n            {\n              // Normalize to store only the file name.\n              // Otherwise, there can be an entry for both\n              // file>subfunction and file, which causes a crash on\n              // dbclear all\n              const char *s = strchr (fcn_ident.c_str (), '>');\n              if (s)\n                m_bp_set.insert (fcn_ident.substr (0, s - fcn_ident.c_str ()));\n              else\n                m_bp_set.insert (fcn_ident);\n\n              found = true;\n              break;\n            }\n        }\n    }\n\n  return found;\n}\n\n// Cursory check that cond is a valid condition to use for a breakpoint.\n// Currently allows conditions with side-effects, like 'y+=10' and 'y++';\n// it is odd that the former is not flagged by \"is_assignment_expression\".\n// Throws an exception if not valid.\n\nbool\nbp_table::condition_valid (const std::string& cond)\n{\n  if (cond.length () > 0)\n    {\n      // ; to reject partial expr like \"y==\"\n      parser parser (cond + \" ;\", m_evaluator.get_interpreter ());\n      parser.reset ();\n      int parse_status = parser.run ();\n      if (parse_status)\n        error (\"dbstop: Cannot parse condition '%s'\", cond.c_str ());\n      else\n        {\n          tree_statement *stmt = nullptr;\n\n          std::shared_ptr<tree_statement_list> stmt_list\n            = parser.statement_list ();\n\n          if (! stmt_list)\n            error (\"dbstop: \"\n                   \"condition is not empty, but has nothing to evaluate\");\n          else\n            {\n              if (stmt_list->size () == 1\n                  && (stmt = stmt_list->front ())\n                  && stmt->is_expression ())\n                {\n                  tree_expression *expr = stmt->expression ();\n                  if (expr->is_assignment_expression ())\n                    error (\"dbstop: condition cannot be an assignment.  \"\n                           \"Did you mean '=='?\");\n                }\n              else\n                error (\"dbstop: condition must be an expression\");\n            }\n        }\n    }\n\n  return true;\n}\n\nenum dbstop_args\n{\n  dbstop_in,\n  dbstop_at,\n  dbstop_if,\n  dbstop_none\n};\n\n// FIXME: This function probably needs to be completely overhauled to\n// correctly parse the full syntax of the dbstop command and properly\n// reject incorrect forms.\n\n// Parse parameters (args) of dbstop and dbclear commands.\n// For dbstop, who==\"dbstop\"; for dbclear, who==\"dbclear\".\n// The syntax is: dbstop [[in] symbol] [[at] [method | line [line [...]]]] [if condition]\n// where the form of condition depends on whether or not a file or line has\n// been seen.  IF symbol and method are specified, then symbol should\n// be a class name.  Otherwise it should be a function name.\n// Also execute \"if [error|warning|interrupt|naninf]\" clauses.\n\nvoid\nbp_table::parse_dbfunction_params (const char *who,\n                                   const octave_value_list& args,\n                                   std::string& fcn_name,\n                                   std::string& class_name,\n                                   bp_table::bp_lines& lines,\n                                   std::string& cond)\n{\n  int nargin = args.length ();\n  fcn_name = \"\";\n  class_name = \"\";\n  lines = bp_table::bp_lines ();\n\n  if (nargin == 0 || ! args(0).is_string ())\n    print_usage (who);\n\n  // elements already processed\n  bool seen_in = false;\n  bool seen_at = false;\n  bool seen_if = false;\n  int pos = 0;\n  dbstop_args tok = dbstop_none;\n  while (pos < nargin)\n    {\n      // allow \"in\" and \"at\" to be implicit\n      if (args(pos).is_string ())\n        {\n          // Default value.\n          tok = dbstop_in;\n\n          std::string arg = args(pos).string_value ();\n          if (arg == \"in\")\n            {\n              tok = dbstop_in;\n              pos++;\n            }\n          else if (arg == \"at\")\n            {\n              tok = dbstop_at;\n              pos++;\n            }\n          else if (arg == \"if\")\n            {\n              tok = dbstop_if;\n              pos++;\n            }\n          else\n            {\n              try\n                {\n                  if (std::stoi (args(pos).string_value ()) > 0)\n                    tok = dbstop_at;\n                }\n              catch (const std::invalid_argument&) { }\n              catch (const std::out_of_range&) { }\n            }\n        }\n      else\n        tok = dbstop_at;\n\n      if (pos >= nargin)\n        error (\"%s: '%s' missing argument\", who,\n               (tok == dbstop_in\n                ? \"in\" : (tok == dbstop_at ? \"at\" : \"if\")));\n\n      // process the actual arguments\n      switch (tok)\n        {\n        case dbstop_in:\n          fcn_name = args(pos).string_value ();\n          if (seen_in)\n            error (\"%s: Too many function names specified -- %s\",\n                   who, fcn_name.c_str ());\n          else if (seen_at || seen_if)\n            error (\"%s: function name must come before line number and 'if'\",\n                   who);\n          seen_in = true;\n          pos++;\n          break;\n\n        case dbstop_at:\n          if (seen_at)\n            error (\"%s: Only one 'at' clause is allowed -- %s\",\n                   who, args(pos).string_value ().c_str ());\n          else if (seen_if)\n            error (\"%s: line number must come before 'if' clause\\n\", who);\n          seen_at = true;\n\n          if (seen_if)\n            error (\"%s: line number must come before 'if' clause\\n\", who);\n          else if (seen_in)\n            {\n              std::string arg = args(pos).string_value ();\n\n              // FIXME: we really want to distinguish number\n              // vs. method name here.\n\n              // FIXME: I'm not sure what the\n\n              bool int_conv_ok = true;\n\n              try\n                {\n                  if (std::stoi (arg) == 0)\n                    int_conv_ok = false;\n                }\n              catch (const std::invalid_argument&)\n                {\n                  int_conv_ok = false;\n                }\n              catch (const std::out_of_range&)\n                {\n                  int_conv_ok = false;\n                }\n\n              if (! int_conv_ok)\n                {\n                  // Assume we are looking at a function name.\n                  // We have class and function names but already\n                  // stored the class name in fcn_name.\n                  class_name = fcn_name;\n                  fcn_name = arg;\n                  pos++;\n                  break;\n                }\n\n            }\n          else\n            {\n              // It was a line number.  Get function name from debugger.\n              if (m_evaluator.in_debug_repl ())\n                fcn_name = m_evaluator.get_user_code ()->profiler_name ();\n              else\n                error (\"%s: function name must come before line number \"\n                       \"and 'if'\", who);\n              seen_in = true;\n            }\n\n          // Read a list of line numbers (or arrays thereof)\n          for ( ; pos < nargin; pos++)\n            {\n              if (args(pos).is_string ())\n                {\n                  std::string str = args(pos).string_value ();\n\n                  try\n                    {\n                      int line = std::stoi (str);\n\n                      if (line > 0)\n                        lines.insert (line);\n                      else\n                        break; // may be \"if\" or a method name\n                    }\n                  catch (const std::invalid_argument&)\n                    {\n                      break; // may be \"if\" or a method name\n                    }\n                  catch (const std::out_of_range&)\n                    {\n                      error (\"dbstop: location value out of range '%s'\", str.c_str ());\n                    }\n                }\n              else if (args(pos).isnumeric ())\n                {\n                  const NDArray arg = args(pos).array_value ();\n\n                  for (octave_idx_type j = 0; j < arg.numel (); j++)\n                    lines.insert (static_cast<int> (arg.elem (j)));\n                }\n              else\n                error (\"%s: Invalid argument type %s\",\n                       who, args(pos).type_name ().c_str ());\n            }\n          break;\n\n        case dbstop_if:\n          if (seen_in)    // conditional breakpoint\n            {\n              cond = \"\";  // remaining arguments form condition\n              for (; pos < nargin; pos++)\n                {\n                  if (args(pos).is_string ())\n                    cond += ' ' + args(pos).string_value ();\n                  else\n                    error (\"%s: arguments to 'if' must all be strings\", who);\n                }\n\n              cond = cond.substr (1);   // omit initial space\n            }\n          else    // stop on event (error, warning, interrupt, NaN/inf)\n            {\n              std::string condition = args(pos).string_value ();\n              bool on_off = ! strcmp (who, \"dbstop\");\n\n              // FIXME: the following seems a bit messy in the way it\n              // duplicates checks on CONDITION.\n\n              if (condition == \"error\")\n                process_id_list (who, condition, args, nargin, pos, on_off,\n                                 m_errors_that_stop);\n              else if (condition == \"warning\")\n                process_id_list (who, condition, args, nargin, pos, on_off,\n                                 m_warnings_that_stop);\n              else if (condition == \"caught\" && nargin > pos+1\n                       && args(pos+1).string_value () == \"error\")\n                {\n                  pos++;\n                  process_id_list (who, condition, args, nargin, pos, on_off,\n                                   m_caught_that_stop);\n                }\n              else if (condition == \"interrupt\")\n                {\n                  Vdebug_on_interrupt = on_off;\n                }\n              else if (condition == \"naninf\")\n                {\n#if defined (DBSTOP_NANINF)\n                  Vdebug_on_naninf = on_off;\n                  enable_fpe (on_off);\n#else\n                  warning (\"%s: condition '%s' not yet supported\",\n                           who, condition.c_str ());\n#endif\n                }\n              else\n                error (\"%s: invalid condition %s\",\n                       who, condition.c_str ());\n\n              pos = nargin;\n            }\n          break;\n\n        default:      // dbstop_none should never occur\n          break;\n        }\n    }\n}\n\n/*\n%!test\n%! if (isguirunning ())\n%!   orig_show_dbg = __event_manager_gui_preference__ (\"editor/show_dbg_file\",\n%!                                                     \"false\");\n%! endif\n%! unwind_protect\n%!   dbclear all;   # Clear out breakpoints before test\n%!   dbstop help;\n%!   dbstop in ls;\n%!   dbstop help at 105;  # 105 is a comment; code line is at 106\n%!   dbstop in ls 124;    # 124 is a comment; code line is at 127\n%!   dbstop help 204 if a==5;\n%!   dbstop if error Octave:undefined-function;\n%!   s = dbstatus;\n%!   dbclear all;\n%!   assert ({s.bkpt(:).name}, {\"help\", \"help\", \"help>do_contents\", \"ls\", \"ls\"});\n%!   assert ([s.bkpt(:).line], [56, 106, 208, 63, 127]);\n%!   assert (s.errs, {\"Octave:undefined-function\"});\n%! unwind_protect_cleanup\n%!   if (isguirunning ())\n%!     __event_manager_gui_preference__ (\"editor/show_dbg_file\", orig_show_dbg);\n%!   endif\n%! end_unwind_protect\n*/\n\nvoid\nbp_table::set_stop_flag (const char *who, const std::string& condition,\n                         bool on_off)\n{\n  interpreter& interp = m_evaluator.get_interpreter ();\n  error_system& es = interp.get_error_system ();\n\n  if (condition == \"error\")\n    es.debug_on_error (on_off);\n  else if (condition == \"warning\")\n    es.debug_on_warning (on_off);\n  else if (condition == \"caught\")\n    es.debug_on_caught (on_off);\n  else\n    error (\"%s: internal error in set_stop_flag\", who);\n}\n\nvoid\nbp_table::process_id_list (const char *who,\n                           const std::string& condition,\n                           const octave_value_list& args,\n                           int nargin, int& pos, bool on_off,\n                           std::set<std::string>& id_list)\n{\n  pos++;\n\n  if (nargin > pos)       // only affect a single error ID\n    {\n      if (! args(pos).is_string () || nargin > pos+1)\n        error (\"%s: ID must be a single string\", who);\n      else if (on_off)\n        {\n          id_list.insert (args(pos).string_value ());\n          set_stop_flag (who, condition, true);\n        }\n      else\n        {\n          id_list.erase (args(pos).string_value ());\n          if (id_list.empty ())\n            set_stop_flag (who, condition, false);\n        }\n    }\n  else   // unqualified.  Turn all on or off\n    {\n      id_list.clear ();\n      set_stop_flag (who, condition, on_off);\n\n      if (condition == \"error\")\n        {\n          // Matlab stops on both.\n          Vdebug_on_interrupt = on_off;\n        }\n    }\n}\n\n// Return the sub/nested/main function of MAIN_FCN that contains\n// line number LINENO of the source file.\n// If FOUND_ENDING_LINE != 0, *FOUND_ENDING_LINE is set to last line of the returned function.\n\nstatic octave_user_code *\nfind_fcn_by_line (octave_user_code *main_fcn, int lineno, int *found_end_line = nullptr)\n{\n  octave_user_code *retval = nullptr;\n  octave_user_code *next_fcn = nullptr;  // 1st function starting after lineno\n\n  // Find innermost nested (or parent) function containing lineno.\n  int earliest_end = std::numeric_limits<int>::max ();\n\n  std::map<std::string, octave_value> subfcns = main_fcn->subfunctions ();\n  for (const auto& str_val_p : subfcns)\n    {\n      if (str_val_p.second.is_user_function ())\n        {\n          auto *dbg_subfcn = str_val_p.second.user_function_value ();\n\n          // Check if lineno is within dbg_subfcn.\n          // FIXME: we could break when the beginning line > lineno,\n          // but that makes the code \"fragile\"\n          // if the order of walking subfcns changes,\n          // for a minor speed improvement in non-critical code.\n\n          filepos beg_pos = dbg_subfcn->beg_pos ();\n          filepos end_pos = dbg_subfcn->end_pos ();\n\n          int beginning_line = beg_pos.line ();\n          int ending_line = end_pos.line ();\n\n          if (ending_line < earliest_end && ending_line >= lineno && beginning_line <= lineno)\n            {\n              earliest_end = ending_line;\n              retval = find_fcn_by_line (dbg_subfcn, lineno, &earliest_end);\n            }\n\n          // Find the first fcn starting after lineno.\n          // This is used if line is not inside any function.\n          if (beginning_line >= lineno && ! next_fcn)\n            next_fcn = dbg_subfcn;\n        }\n    }\n\n  // The breakpoint is either in the subfunction found above,\n  // or in the main function, which we check now.\n  if (main_fcn->is_user_function ())\n    {\n      filepos end_pos = dynamic_cast<octave_user_function *> (main_fcn)->end_pos ();\n\n      int ending_line = end_pos.line ();\n\n      if (ending_line >= lineno && ending_line < earliest_end)\n        retval = main_fcn;\n\n      if (! retval)\n        retval = next_fcn;\n    }\n  else  // main_fcn is a script.\n    {\n      if (! retval)\n        retval = main_fcn;\n    }\n\n  if (found_end_line && earliest_end < *found_end_line)\n    *found_end_line = earliest_end;\n\n  return retval;\n}\n\n// Given function identifier fcn_ident, find the subfunction at line and create\n// a breakpoint there.  Put the system into debug_mode.\nint\nbp_table::add_breakpoint_in_function (const std::string& fcn_ident,\n                                      int line,\n                                      const std::string& condition)\n{\n  bp_lines line_info;\n  line_info.insert (line);\n\n  bp_lines result\n    = add_breakpoints_in_function (fcn_ident, line_info, condition);\n\n  return result.empty () ? 0 : *(result.begin ());\n}\n\n// A class that encapsulates the \"get_user_code\" operation.\n// This operation changes depending on the symbol being a function or classdef.\n// Octave used to assume everything was a function, one per file.\n// Classdefs can have several functions in a single file.\nclass user_code_provider\n{\npublic:\n  user_code_provider (const std::string& who, const std::string& fcn_ident,\n                      octave_user_code *pfcn, bool silent = false)\n    : m_fcn (nullptr), m_is_valid (false)\n  {\n    m_fcn = pfcn;\n    if (m_fcn && ! (m_fcn->is_classdef_method ()\n                    || m_fcn->is_classdef_constructor ()))\n      {\n        // Already have the usercode, no need to do anything.\n        m_is_valid = true;\n        return;\n      }\n\n    // If we get here, try to get a classdef to support getting method by\n    // line number.\n\n    // Extract class name from function identifier\n    std::string class_name = fcn_ident;\n    const char *s = strchr (fcn_ident.c_str (), '/');\n    if (s && fcn_ident[0] == '@')\n      class_name = fcn_ident.substr (1, s - fcn_ident.c_str () - 1);\n\n    m_cls = lookup_class (class_name, false);\n    m_is_valid = m_cls.ok () && (m_cls.get_name () == class_name);\n    if (m_is_valid)\n      populate_function_cache ();\n    else if (! silent)\n      error (\"%s: unable to find function '%s'\\n\", who.c_str (),\n             fcn_ident.c_str ());\n\n  }\n\n  octave_user_code * operator () (int line = 1)\n  {\n    if (! is_valid ())\n      return nullptr;\n\n    if (is_function ())\n      return find_fcn_by_line (m_fcn, line);\n\n    if (line < 0)\n      return nullptr;\n\n    octave_value method = m_cls.get_method (line);\n    if (method.is_function_handle ())\n      return method.user_function_value ()->user_code_value (true);\n    else\n      return method.user_code_value (true);\n  }\n\n  bool is_function () const { return m_fcn; }\n\n  bool is_valid () const { return m_is_valid; }\n\n  size_t number_of_functions () const\n  {\n    if (! is_valid ())\n      return 0;\n\n    if (is_function ())\n      return 1;\n\n    return m_methods_cache.size ();\n  }\n\n  octave_user_code * get_function (const size_t i) const\n  {\n    if (! is_valid ())\n      return nullptr;\n\n    if (is_function ())\n      return m_fcn;\n\n    if (i < m_methods_cache.size ())\n      return m_methods_cache[i];\n\n    return nullptr;\n  }\n\nprivate:\n  void populate_function_cache ()\n  {\n    if (m_methods_cache.empty ())\n      {\n        // Not the most efficient, but reuses code:\n        const std::map<std::string, cdef_method>& map\n          = m_cls.get_method_map (false, true);\n        for (const auto& meth : map)\n          {\n            octave_user_code *fcn\n              = m_cls.get_method (meth.first).user_code_value (true);\n            if (fcn != nullptr)\n              m_methods_cache.push_back (fcn);\n          }\n\n        // Check get and set methods of properties\n        const std::map<property_key, cdef_property>& prop_map\n          = m_cls.get_property_map (cdef_class::property_all);\n        for (const auto& prop : prop_map)\n          {\n            octave_value get_meth = prop.second.get (\"GetMethod\");\n            if (get_meth.is_function_handle ())\n              {\n                octave_user_code *fcn\n                  = get_meth.user_function_value ()->user_code_value (true);\n                if (fcn != nullptr)\n                  m_methods_cache.push_back (fcn);\n              }\n\n            octave_value set_meth = prop.second.get (\"SetMethod\");\n            if (set_meth.is_function_handle ())\n              {\n                octave_user_code *fcn\n                  = set_meth.user_function_value ()->user_code_value (true);\n                if (fcn != nullptr)\n                  m_methods_cache.push_back (fcn);\n              }\n          }\n      }\n  }\n\nprivate:\n  std::vector<octave_user_code *> m_methods_cache;\n  cdef_class m_cls;\n  octave_user_code *m_fcn;\n  bool m_is_valid;\n};\n\n// Given file name fname, find the subfunction at line and create\n// a breakpoint there.  Put the system into debug_mode.\nbp_table::bp_lines\nbp_table::add_breakpoints_in_function (const std::string& fcn_ident,\n                                       const bp_table::bp_lines& lines,\n                                       const std::string& condition)\n{\n  user_code_provider user_code (\"add_breakpoints_in_function\", fcn_ident,\n                                m_evaluator.get_user_code (fcn_ident));\n\n  condition_valid (condition);  // Throw error if condition not valid.\n\n  bp_lines retval;\n\n  for (const auto& lineno : lines)\n    {\n      octave_user_code *dbg_fcn = user_code (lineno);\n\n      if (! dbg_fcn)\n        error (\"add_breakpoints_in_function: unable to find function '%s'\\n\",\n               fcn_ident.c_str ());\n\n      // We've found the right (sub)function.  Now insert the breakpoint.\n      bp_lines line_info;\n      line_info.insert (lineno);\n\n      bp_lines ret_one;\n\n      std::string ident = fcn_ident;\n      if (! user_code.is_function () && fcn_ident[0] != '@')\n        {\n          // identifier of the form @class_name/method_name\n          ident = \"@\" + fcn_ident + \"/\" + dbg_fcn->name ();\n        }\n\n      if (add_breakpoint_1 (dbg_fcn, ident, line_info, condition, ret_one))\n        {\n          if (! ret_one.empty ())\n            {\n              int line = *(ret_one.begin ());\n\n              if (line)\n                retval.insert (line);\n            }\n        }\n    }\n\n  m_evaluator.reset_debug_state ();\n\n  return retval;\n}\n\nint\nbp_table::add_breakpoint_in_file (const std::string& file,\n                                  int line,\n                                  const std::string& condition)\n{\n  // Duplicates what the GUI was doing previously, but this action\n  // should not be specific to the GUI.\n\n  bp_file_info info (m_evaluator, file);\n\n  if (! info.ok ())\n    return 0;\n\n  std::string fcn_ident;\n  if (info.class_name ().empty () || info.fcn ()[0] == '@')\n    fcn_ident = info.fcn ();\n  else\n    fcn_ident = \"@\" + info.class_name () + \"/\" + info.fcn ();\n\n  return add_breakpoint_in_function (fcn_ident, line, condition);\n}\n\nbp_table::bp_lines\nbp_table::add_breakpoints_in_file (const std::string& file,\n                                   const bp_lines& lines,\n                                   const std::string& condition)\n{\n  // Duplicates what the GUI was doing previously, but this action\n  // should not be specific to the GUI.\n\n  bp_file_info info (m_evaluator, file);\n\n  if (! info.ok ())\n    return bp_lines ();\n\n  std::string fcn_ident;\n  if (info.class_name ().empty () || info.fcn ()[0] == '@')\n    fcn_ident = info.fcn ();\n  else\n    fcn_ident = \"@\" + info.class_name () + \"/\" + info.fcn ();\n\n  return add_breakpoints_in_function (fcn_ident, lines, condition);\n}\n\nint\nbp_table::remove_breakpoint_1 (octave_user_code *fcn,\n                               const std::string& fcn_ident,\n                               const bp_table::bp_lines& lines)\n{\n  int retval = 0;\n\n  std::string file = fcn->fcn_file_name ();\n\n  tree_statement_list *cmds = fcn->body ();\n\n  // FIXME: move the operation on cmds to the tree_statement_list class?\n\n  if (cmds)\n    {\n      octave_value_list results = cmds->list_breakpoints ();\n\n      if (results.length () > 0)\n        {\n          interpreter& interp = m_evaluator.get_interpreter ();\n\n          event_manager& evmgr = interp.get_event_manager ();\n\n          for (const auto& lineno : lines)\n            {\n              cmds->delete_breakpoint (lineno);\n\n              if (! file.empty ())\n                evmgr.update_breakpoint (false, file, lineno);\n            }\n\n          results = cmds->list_breakpoints ();\n\n          auto it = m_bp_set.find (fcn_ident);\n          if (results.empty () && it != m_bp_set.end ())\n            m_bp_set.erase (it);\n        }\n\n      retval = results.length ();\n    }\n\n  return retval;\n}\n\nint\nbp_table::remove_breakpoint_from_function (const std::string& fcn_ident,\n                                           int line)\n{\n  bp_lines line_info;\n  line_info.insert (line);\n\n  return remove_breakpoints_from_function (fcn_ident, line_info);\n}\n\nint\nbp_table::remove_breakpoints_from_function (const std::string& fcn_ident,\n                                            const bp_table::bp_lines& lines)\n{\n  int retval = 0;\n\n  if (lines.empty ())\n    {\n      bp_lines results = remove_all_breakpoints_from_function (fcn_ident);\n      retval = results.size ();\n    }\n  else\n    {\n      octave_user_code *dbg_fcn = m_evaluator.get_user_code (fcn_ident);\n      user_code_provider user_code (\"remove_breakpoints_from_function\",\n                                    fcn_ident, dbg_fcn);\n\n      // Remove all breakpoints from all functions\n      for (const auto line : lines)\n        {\n          octave_user_code *fcn = user_code (line);\n          std::string file = fcn->fcn_file_name ();\n\n          tree_statement_list *cmds = fcn->body ();\n          if (cmds)\n            {\n              octave_value_list results = cmds->list_breakpoints ();\n\n              if (results.length () > 0)\n                {\n                  interpreter& interp = m_evaluator.get_interpreter ();\n                  event_manager& evmgr = interp.get_event_manager ();\n\n                  cmds->delete_breakpoint (line);\n\n                  if (! file.empty ())\n                    evmgr.update_breakpoint (false, file, line);\n                }\n            }\n        }\n\n      // Remove all breakpoints from all subfunctions\n      if (dbg_fcn != nullptr)\n        {\n          // Search subfunctions in the order they appear in the file.\n          const std::list<std::string> subfcn_names\n            = dbg_fcn->subfunction_names ();\n\n          std::map<std::string, octave_value> subfcns\n            = dbg_fcn->subfunctions ();\n\n          for (const auto& subf_nm : subfcn_names)\n            {\n              const auto q = subfcns.find (subf_nm);\n\n              if (q != subfcns.end ())\n                {\n                  octave_user_code *dbg_subfcn\n                    = q->second.user_code_value ();\n\n                  retval += remove_breakpoint_1 (dbg_subfcn, fcn_ident, lines);\n                }\n            }\n        }\n      // Remove file from breakpoint set if no breakpoints remain\n      octave_value_list fname_list = {fcn_ident};\n      const bool no_breakpoints\n        = get_breakpoint_list (fname_list).empty ();\n      auto iter = m_bp_set.find (fcn_ident);\n      if (no_breakpoints && iter != m_bp_set.end ())\n        m_bp_set.erase (iter);\n    }\n\n  m_evaluator.reset_debug_state ();\n\n  return retval;\n}\n\n// Remove all breakpoints from a file, including those in subfunctions.\n\nbp_table::bp_lines\nbp_table::remove_all_breakpoints_from_function (const std::string& fcn_ident,\n                                                bool silent)\n{\n  bp_lines retval;\n\n  octave_user_code *fcn = m_evaluator.get_user_code (fcn_ident);\n  user_code_provider user_code (\"remove_all_breakpoints_from_function\",\n                                fcn_ident, fcn, silent);\n\n  if (user_code.is_valid ())\n    {\n      for (size_t i = 0; i != user_code.number_of_functions (); ++i)\n        {\n          octave_user_code *dbg_fcn = user_code.get_function (i);\n          std::string file = dbg_fcn->fcn_file_name ();\n\n          tree_statement_list *cmds = dbg_fcn->body ();\n\n          if (cmds)\n            {\n              interpreter& interp = m_evaluator.get_interpreter ();\n\n              event_manager& evmgr = interp.get_event_manager ();\n\n              retval = cmds->remove_all_breakpoints (evmgr, file);\n            }\n        }\n\n      auto it = m_bp_set.find (fcn_ident);\n      if (it != m_bp_set.end ())\n        m_bp_set.erase (it);\n    }\n\n  m_evaluator.reset_debug_state ();\n\n  return retval;\n}\n\nint\nbp_table::remove_breakpoint_from_file (const std::string& file, int line)\n{\n  // Duplicates what the GUI was doing previously, but this action\n  // should not be specific to the GUI.\n\n  bp_file_info info (m_evaluator, file);\n\n  if (! info.ok ())\n    return 0;\n\n  return remove_breakpoint_from_function (info.fcn (), line);\n}\n\nint\nbp_table::remove_breakpoints_from_file (const std::string& file,\n                                        const bp_lines& lines)\n{\n  // Duplicates what the GUI was doing previously, but this action\n  // should not be specific to the GUI.\n\n  bp_file_info info (m_evaluator, file);\n\n  if (! info.ok ())\n    return 0;\n\n  return remove_breakpoints_from_function (info.fcn (), lines);\n}\n\nbp_table::bp_lines\nbp_table::remove_all_breakpoints_from_file (const std::string& file,\n                                            bool silent)\n{\n  // Duplicates what the GUI was doing previously, but this action\n  // should not be specific to the GUI.\n\n  bp_file_info info (m_evaluator, file);\n\n  if (! info.ok ())\n    return bp_lines ();\n\n  return remove_all_breakpoints_from_function (info.fcn (), silent);\n}\n\nvoid\nbp_table::remove_all_breakpoints ()\n{\n  // Odd loop structure required because delete will invalidate\n  // m_bp_set iterators.\n  for (auto it = m_bp_set.cbegin (), it_next = it;\n       it != m_bp_set.cend ();\n       it = it_next)\n    {\n      ++it_next;\n      remove_all_breakpoints_from_function (*it);\n    }\n\n  m_evaluator.reset_debug_state ();\n}\n\nstd::string\nfind_bkpt_list (octave_value_list slist, std::string match)\n{\n  std::string retval;\n\n  for (int i = 0; i < slist.length (); i++)\n    {\n      if (slist(i).string_value () == match)\n        {\n          retval = slist(i).string_value ();\n          break;\n        }\n    }\n\n  return retval;\n}\n\nbp_table::fname_bp_map\nbp_table::get_breakpoint_list (const octave_value_list& fname_list)\n{\n  fname_bp_map retval;\n\n  // make copy since changes may invalidate iters of m_bp_set.\n  std::set<std::string> tmp_bp_set = m_bp_set;\n\n  for (auto& bp_fname : tmp_bp_set)\n    {\n      if (fname_list.empty ()\n          || find_bkpt_list (fname_list, bp_fname) != \"\")\n        {\n          octave_user_code *dbg_fcn = m_evaluator.get_user_code (bp_fname);\n          user_code_provider user_code (\"get_breakpoint_list\", bp_fname,\n                                        dbg_fcn);\n          // Gather breakpoints from all functions in the file\n          std::list<bp_type> all_bkpts;\n          std::list<bp_type>::iterator it (all_bkpts.begin ());\n          for (size_t i = 0; i != user_code.number_of_functions (); ++i)\n            {\n              octave_user_code *fcn = user_code.get_function (i);\n              if (fcn)\n                {\n                  tree_statement_list *cmds = fcn->body ();\n                  // FIXME: move the operation on cmds to the\n                  //        tree_statement_list class?\n                  if (cmds)\n                    {\n                      const std::list<bp_type>& bp\n                        = cmds->breakpoints_and_conds ();\n                      if (!bp.empty())\n                        it = all_bkpts.insert (it, bp.cbegin (),\n                                               bp.cend ());\n                    }\n                }\n            }\n\n          if (! all_bkpts.empty ())\n            retval[bp_fname] = all_bkpts;\n\n          // look for breakpoints in subfunctions\n          // Assuming classdefs can't have subfunctions\n          if (dbg_fcn != nullptr)\n            {\n              const std::list<std::string> subf_nm\n                = dbg_fcn->subfunction_names ();\n\n              std::map<std::string, octave_value> subfcns\n                = dbg_fcn->subfunctions ();\n\n              for (const auto& subfcn_nm : subf_nm)\n                {\n                  const auto q = subfcns.find (subfcn_nm);\n\n                  if (q != subfcns.end ())\n                    {\n                      octave_user_code *dbg_subfcn\n                        = q->second.user_code_value ();\n\n                      tree_statement_list *cmds = dbg_subfcn->body ();\n                      if (cmds)\n                        {\n                          std::list<bp_type> bkpts\n                            = cmds->breakpoints_and_conds ();\n\n                          if (! bkpts.empty ())\n                            {\n                              std::string key\n                                = bp_fname + '>' + dbg_subfcn->name ();\n\n                              retval[key] = bkpts;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\n// Report the status of \"dbstop if error ...\" and \"dbstop if warning ...\"\n// If to_screen is true, the output goes to octave_stdout; otherwise it is\n// returned.\n// If dbstop if error is true but no explicit IDs are specified, the return\n// value will have an empty field called \"errs\".  If IDs are specified, the\n// \"errs\" field will have a row per ID.  If dbstop if error is false, there\n// is no \"errs\" field.  The \"warn\" field is set similarly by dbstop if warning\n\noctave_map\nbp_table::stop_on_err_warn_status (bool to_screen)\n{\n  octave_map retval;\n\n  interpreter& interp = m_evaluator.get_interpreter ();\n  error_system& es = interp.get_error_system ();\n\n  // print dbstop if error information\n  if (es.debug_on_error ())\n    {\n      if (m_errors_that_stop.empty ())\n        {\n          if (to_screen)\n            octave_stdout << \"stop if error\\n\";\n          else\n            retval.assign (\"errs\", octave_value (\"\"));\n        }\n      else\n        {\n          Cell errs (dim_vector (bp_table::m_errors_that_stop.size (), 1));\n          int i = 0;\n\n          for (const auto& e : m_errors_that_stop)\n            {\n              if (to_screen)\n                octave_stdout << \"stop if error \" << e << \"\\n\";\n              else\n                errs(i++) = e;\n            }\n          if (! to_screen)\n            retval.assign (\"errs\", octave_value (errs));\n        }\n    }\n\n  // print dbstop if caught error information\n  if (es.debug_on_caught ())\n    {\n      if (m_caught_that_stop.empty ())\n        {\n          if (to_screen)\n            octave_stdout << \"stop if caught error\\n\";\n          else\n            retval.assign (\"caught\", octave_value (\"\"));\n        }\n      else\n        {\n          Cell errs (dim_vector (m_caught_that_stop.size (), 1));\n          int i = 0;\n\n          for (const auto& e : m_caught_that_stop)\n            {\n              if (to_screen)\n                octave_stdout << \"stop if caught error \" << e << \"\\n\";\n              else\n                errs(i++) = e;\n            }\n          if (! to_screen)\n            retval.assign (\"caught\", octave_value (errs));\n        }\n    }\n\n  // print dbstop if warning information\n  if (es.debug_on_warning ())\n    {\n      if (m_warnings_that_stop.empty ())\n        {\n          if (to_screen)\n            octave_stdout << \"stop if warning\\n\";\n          else\n            retval.assign (\"warn\", octave_value (\"\"));\n        }\n      else\n        {\n          Cell warn (dim_vector (m_warnings_that_stop.size (), 1));\n          int i = 0;\n\n          for (const auto& w : m_warnings_that_stop)\n            {\n              if (to_screen)\n                octave_stdout << \"stop if warning \" << w << \"\\n\";\n              else\n                warn(i++) = w;\n            }\n          if (! to_screen)\n            retval.assign (\"warn\", octave_value (warn));\n        }\n    }\n\n  // print dbstop if interrupt information\n  if (Vdebug_on_interrupt)\n    {\n      if (to_screen)\n        octave_stdout << \"stop if interrupt\\n\";\n      else\n        retval.assign (\"intr\", octave_value (\"\"));\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/bp-table.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_bp_table_h)\n#define octave_bp_table_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <map>\n#include <set>\n#include <string>\n\nclass octave_map;\nclass octave_user_code;\nclass octave_value_list;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_evaluator;\n\nstruct bp_type\n{\npublic:\n\n  bp_type (int l, const std::string& c) : line (l), cond (c) { }\n\n  //--------\n\n  int line;\n  std::string cond;\n};\n\n// Interface to breakpoints.\nclass OCTINTERP_API bp_table\n{\npublic:\n\n  bp_table (tree_evaluator& tw)\n    : m_evaluator (tw), m_bp_set (), m_errors_that_stop (),\n      m_caught_that_stop (), m_warnings_that_stop ()\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (bp_table)\n\n  ~bp_table () = default;\n\n  // Set of breakpoint lines.\n  typedef std::set<int> bp_lines;\n\n  typedef bp_lines::const_iterator const_bp_lines_iterator;\n  typedef bp_lines::iterator bp_lines_iterator;\n\n  typedef std::map<std::string, bp_lines> fname_line_map;\n\n  typedef fname_line_map::const_iterator const_fname_line_map_iterator;\n  typedef fname_line_map::iterator fname_line_map_iterator;\n\n  typedef std::map<std::string, std::list<bp_type>> fname_bp_map;\n  typedef fname_bp_map::const_iterator const_fname_bp_map_iterator;\n  typedef fname_bp_map::iterator fname_bp_map_iterator;\n\n  // Add a breakpoint at the nearest executable line in a function.\n  int add_breakpoint_in_function (const std::string& fcn_ident = \"\",\n                                  int line = 1,\n                                  const std::string& condition = \"\");\n\n  // Add a set of breakpoints at the nearest executable lines in a\n  // function.\n  bp_lines add_breakpoints_in_function (const std::string& fcn_ident = \"\",\n                                        const bp_lines& lines = bp_lines (),\n                                        const std::string& condition = \"\");\n\n  // Add a breakpoint at the nearest executable line in a file.\n  int add_breakpoint_in_file (const std::string& file = \"\",\n                              int line = 1,\n                              const std::string& condition = \"\");\n\n  // Add a set of breakpoints at the nearest executable lines in a\n  // file.\n  bp_lines add_breakpoints_in_file (const std::string& file = \"\",\n                                    const bp_lines& lines = bp_lines (),\n                                    const std::string& condition = \"\");\n\n  // Remove a breakpoint from the given line in file.\n  int remove_breakpoint_from_function (const std::string& fcn_ident = \"\",\n                                       int line = 1);\n\n  // Remove a set of breakpoints from the given lines in file.\n  int remove_breakpoints_from_function (const std::string& fcn_ident = \"\",\n                                        const bp_lines& lines = bp_lines ());\n\n  // Remove all the breakpoints in a specified function.\n  bp_lines remove_all_breakpoints_from_function (const std::string& fcn_ident,\n                                                 bool silent = false);\n\n  // Remove a breakpoint from the given line in file.\n  int remove_breakpoint_from_file (const std::string& file = \"\",\n                                   int line = 1);\n\n  // Remove a set of breakpoints from the given lines in file.\n  int remove_breakpoints_from_file (const std::string& file = \"\",\n                                    const bp_lines& lines = bp_lines ());\n\n\n  // Remove all the breakpoints from a file.\n  bp_lines remove_all_breakpoints_from_file (const std::string& file,\n                                             bool silent = false);\n\n  // Remove all the breakpoints registered with octave.\n  void remove_all_breakpoints ();\n\n  // Return all breakpoints.  Each element of the map is a vector\n  // containing the breakpoints corresponding to a given function name.\n  fname_bp_map get_breakpoint_list (const octave_value_list& fname_list);\n\n  bool have_breakpoints () { return (! m_bp_set.empty ()); }\n\n  // Should we enter debugging for this particular error identifier?\n  bool debug_on_err (const std::string& id)\n  {\n    return (m_errors_that_stop.empty () || m_errors_that_stop.count (id));\n  }\n\n  // Should we enter debugging for this particular identifier in a try/catch?\n  bool debug_on_caught (const std::string& id)\n  {\n    return (m_caught_that_stop.empty () || m_caught_that_stop.count (id));\n  }\n\n  // Should we enter debugging for this particular warning identifier?\n  bool debug_on_warn (const std::string& id)\n  {\n    return (m_warnings_that_stop.empty () || m_warnings_that_stop.count (id));\n  }\n\n  octave_map stop_on_err_warn_status (bool to_screen);\n\n  void dbstop_process_map_args (const octave_map& mv);\n\n  void dbclear_all_signals ();\n\n  bool condition_valid (const std::string& cond);\n\n  void parse_dbfunction_params (const char *who,\n                                const octave_value_list& args,\n                                std::string& fcn_name,\n                                std::string& class_name,\n                                bp_table::bp_lines& lines,\n                                std::string& cond);\n\nprivate:\n\n  void set_stop_flag (const char *who, const std::string& condition,\n                      bool on_off);\n\n  void process_id_list (const char *who, const std::string& condition,\n                        const octave_value_list& args,\n                        int nargin, int& pos, bool on_off,\n                        std::set<std::string>& id_list);\n\n  bool add_breakpoint_1 (octave_user_code *fcn, const std::string& fname,\n                         const bp_lines& line, const std::string& condition,\n                         bp_lines& retval);\n\n  int remove_breakpoint_1 (octave_user_code *fcn, const std::string&,\n                           const bp_lines& lines);\n\n  bp_lines remove_all_breakpoints_in_file_1 (octave_user_code *fcn,\n                                             const std::string& fname);\n\n  //--------\n\n  typedef std::set<std::string>::const_iterator const_bp_set_iterator;\n  typedef std::set<std::string>::iterator bp_set_iterator;\n\n  tree_evaluator& m_evaluator;\n\n  // Set of function (.m file) names containing at least one breakpoint.\n  std::set<std::string> m_bp_set;\n\n  // Set of error and warning message IDs that cause us to stop\n  // *if* Vdebug_on_error / Vdebug_on_caught / Vdebug_on_warning is set.\n  // Empty means stop on any error / caught error / warning.\n  std::set<std::string> m_errors_that_stop;\n  std::set<std::string> m_caught_that_stop;\n  std::set<std::string> m_warnings_that_stop;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/comment-list.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"lo-utils.h\"\n\n#include \"comment-list.h\"\n#include \"error.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ncomment_list *\ncomment_list::dup () const\n{\n  return new comment_list (*this);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/comment-list.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_comment_list_h)\n#define octave_comment_list_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <memory>\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern std::string get_comment_text ();\n\nextern char * get_comment_text_c_str ();\n\nextern void save_comment_text (const std::string& text);\n\nclass OCTINTERP_API comment_elt\n{\npublic:\n\n  enum comment_type\n  {\n    unknown,\n    block,\n    full_line,\n    end_of_line,\n    copyright\n  };\n\n  comment_elt (const std::string& s = \"\", comment_type t = unknown, bool uses_hash_char = false)\n    : m_text (s), m_type (t), m_uses_hash_char (uses_hash_char) { }\n\n  comment_elt (const comment_elt& oc)\n    : m_text (oc.m_text), m_type (oc.m_type), m_uses_hash_char (oc.m_uses_hash_char)\n  { }\n\n  comment_elt& operator = (const comment_elt& oc)\n  {\n    if (this != &oc)\n      {\n        m_text = oc.m_text;\n        m_type = oc.m_type;\n        m_uses_hash_char = oc.m_uses_hash_char;\n      }\n\n    return *this;\n  }\n\n  bool empty () const { return m_text.empty (); }\n\n  std::string text () const { return m_text; }\n\n  comment_type type () const { return m_type; }\n\n  bool is_block () const { return m_type == block; }\n  bool is_full_line () const { return m_type == full_line; }\n  bool is_end_of_line () const { return m_type == end_of_line; }\n  bool is_copyright () const { return m_type == copyright; }\n  bool uses_hash_char () const { return m_uses_hash_char; }\n\n  void reset ()\n  {\n    m_text = \"\";\n    m_type = unknown;\n    m_uses_hash_char = false;\n  }\n\n  ~comment_elt () = default;\n\nprivate:\n\n  // The text of the comment.\n  std::string m_text;\n\n  // The type of comment.\n  comment_type m_type;\n\n  // TRUE means a line comment uses '#' or a block comment used at least\n  // one '#' delimiter.\n  bool m_uses_hash_char;\n};\n\nclass OCTINTERP_API comment_list\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (comment_list)\n\n  typedef std::list<comment_elt>::reference reference;\n  typedef std::list<comment_elt>::const_reference const_reference;\n\n  typedef std::list<comment_elt>::iterator iterator;\n  typedef std::list<comment_elt>::const_iterator const_iterator;\n\n  void append (const comment_elt& elt)\n  {\n    m_list.push_back (elt);\n  }\n\n  void append (const std::string& s,\n               comment_elt::comment_type t = comment_elt::unknown,\n               bool uses_hash_char = false)\n  {\n    m_list.push_back (comment_elt (s, t, uses_hash_char));\n  }\n\n  void clear () { m_list.clear (); }\n\n  bool empty () const { return m_list.empty (); }\n\n  reference front () { return m_list.front (); }\n  reference back () { return m_list.back (); }\n\n  const_reference front () const { return m_list.front (); }\n  const_reference back () const { return m_list.back (); }\n\n  iterator begin () { return m_list.begin (); }\n  iterator end () { return m_list.end (); }\n\n  const_iterator begin () const { return m_list.begin (); }\n  const_iterator end () const { return m_list.end (); }\n\n  comment_list * dup () const;\n\n  // Documentation for functions is typically the first block of\n  // comments that doesn't look like a copyright statement.\n  comment_elt find_doc_comment () const\n  {\n    for (const auto& elt : m_list)\n      {\n        // FIXME: should we also omit end-of-line comments?\n        if (! elt.is_copyright ())\n          return elt;\n      }\n\n    return comment_elt ();\n  }\n\n  std::string find_doc_string () const\n  {\n    return find_doc_comment().text ();\n  }\n\nprivate:\n\n  std::list<comment_elt> m_list;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/filepos.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2019-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_filepos_h)\n#define octave_filepos_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API filepos\n{\npublic:\n\n  filepos () : m_line (0), m_column (0) { }\n\n  filepos (int l, int c) : m_line (l), m_column (c) { }\n\n  filepos (const filepos&) = default;\n\n  filepos& operator = (const filepos&) = default;\n\n  ~filepos () = default;\n\n  operator bool () { return m_line > 0 && m_column > 0; }\n\n  void line (int l) { m_line = l; }\n  void column (int c) { m_column = c; }\n\n  int line () const { return m_line; }\n  int column () const { return m_column; }\n\n  void increment_line (int val = 1) { m_line += val; }\n  void increment_column (int val = 1) { m_column += val; }\n\n  void decrement_line (int val = 1) { m_line -= val; }\n  void decrement_column (int val = 1) { m_column -= val; }\n\n  void next_line ()\n  {\n    m_line++;\n    m_column = 1;\n  }\n\nprivate:\n\n  int m_line;\n  int m_column;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/lex.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lex_h)\n#define octave_lex_h 1\n\n#include \"octave-config.h\"\n\n#include <deque>\n#include <list>\n#include <set>\n#include <stack>\n\n#include \"comment-list.h\"\n#include \"filepos.h\"\n#include \"input.h\"\n#include \"symscope.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass interpreter;\n\n// Is the given string a keyword?\nextern bool iskeyword (const std::string& s);\n\n// For communication between the lexer and parser.\n\nclass OCTINTERP_API lexical_feedback\n{\npublic:\n\n  // Track symbol table information when parsing functions.\n\n  class symbol_table_context\n  {\n  public:\n\n    symbol_table_context (interpreter& interp)\n      : m_interpreter (interp), m_frame_stack () { }\n\n    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (symbol_table_context)\n\n    ~symbol_table_context () { clear (); }\n\n    void clear ();\n\n    bool empty () const { return m_frame_stack.empty (); }\n\n    std::size_t size () const { return m_frame_stack.size (); }\n\n    void pop ();\n\n    void push (const symbol_scope& scope)\n    {\n      m_frame_stack.push_front (scope);\n    }\n\n    symbol_scope curr_scope () const;\n    symbol_scope parent_scope () const;\n\n  private:\n\n    interpreter& m_interpreter;\n\n    std::deque<symbol_scope> m_frame_stack;\n  };\n\n  // Track nesting of square brackets, curly braces, and parentheses.\n\n  class bbp_nesting_level\n  {\n  private:\n\n    enum bracket_type\n    {\n      BRACKET = 1,\n      BRACE = 2,\n      PAREN = 3,\n      ANON_FCN_BODY = 4\n    };\n\n  public:\n\n    bbp_nesting_level () : m_context () { }\n\n    bbp_nesting_level (const bbp_nesting_level& nl)\n      : m_context (nl.m_context)\n    { }\n\n    bbp_nesting_level& operator = (const bbp_nesting_level& nl)\n    {\n      if (&nl != this)\n        m_context = nl.m_context;\n\n      return *this;\n    }\n\n    ~bbp_nesting_level () = default;\n\n    // Alias for clear function.\n    void reset () { clear (); }\n\n    void bracket () { m_context.push (BRACKET); }\n\n    bool is_bracket ()\n    {\n      return ! m_context.empty () && m_context.top () == BRACKET;\n    }\n\n    void brace () { m_context.push (BRACE); }\n\n    bool is_brace ()\n    {\n      return ! m_context.empty () && m_context.top () == BRACE;\n    }\n\n    void paren () { m_context.push (PAREN); }\n\n    bool is_paren ()\n    {\n      return ! m_context.empty () && m_context.top () == PAREN;\n    }\n\n    void anon_fcn_body () { m_context.push (ANON_FCN_BODY); }\n\n    bool is_anon_fcn_body ()\n    {\n      return ! m_context.empty () && m_context.top () == ANON_FCN_BODY;\n    }\n\n    bool is_bracket_or_brace ()\n    {\n      return (! m_context.empty ()\n              && (m_context.top () == BRACKET || m_context.top () == BRACE));\n    }\n\n    bool none () { return m_context.empty (); }\n\n    void remove ()\n    {\n      if (! m_context.empty ())\n        m_context.pop ();\n    }\n\n    void clear ()\n    {\n      while (! m_context.empty ())\n        m_context.pop ();\n    }\n\n  private:\n\n    std::stack<int> m_context;\n  };\n\n  class token_cache\n  {\n  public:\n\n    // Store an \"unlimited\" number of tokens.\n\n    // Tokens are allocated with new.  Delete them when they are\n    // removed from the cache.\n    //\n    // One of the reasons for using this class instead of std::deque\n    // directly is that we can ensure that memory is cleaned up\n    // properly.  It's more tedious to do that with deque since the\n    // deque destructor and clear method don't call delete on the\n    // elements that it stores.  Another reason is that it makes it\n    // easier to change the implementation later if needed.\n\n    token_cache () : m_buffer () { }\n\n    OCTAVE_DISABLE_COPY_MOVE (token_cache)\n\n    ~token_cache () { clear (); }\n\n    void push (token *tok)\n    {\n      m_buffer.push_front (tok);\n    }\n\n    void pop ()\n    {\n      if (! empty ())\n        {\n          delete m_buffer.back ();\n          m_buffer.pop_back ();\n        }\n    }\n\n    // Direct access.\n    token * at (std::size_t n)\n    {\n      return empty () ? nullptr : m_buffer.at (n);\n    }\n\n    const token * at (std::size_t n) const\n    {\n      return empty () ? nullptr : m_buffer.at (n);\n    }\n\n    // Most recently pushed.\n    token * front ()\n    {\n      return empty () ? nullptr : m_buffer.front ();\n    }\n\n    const token * front () const\n    {\n      return empty () ? nullptr : m_buffer.front ();\n    }\n\n    token * back ()\n    {\n      return empty () ? nullptr : m_buffer.back ();\n    }\n\n    const token * back () const\n    {\n      return empty () ? nullptr : m_buffer.back ();\n    }\n\n    // Number of elements currently in the buffer.\n    std::size_t size () const { return m_buffer.size (); }\n\n    bool empty () const { return m_buffer.empty (); }\n\n    void clear ()\n    {\n      while (! empty ())\n        pop ();\n    }\n\n  private:\n\n    std::deque<token *> m_buffer;\n  };\n\n  lexical_feedback (interpreter& interp)\n    : m_interpreter (interp),\n      m_end_of_input (false),\n      m_allow_command_syntax (true),\n      m_at_beginning_of_statement (true),\n      m_looking_at_anon_fcn_args (false),\n      m_looking_at_return_list (false),\n      m_looking_at_parameter_list (false),\n      m_looking_at_decl_list (false),\n      m_looking_at_matrix_or_assign_lhs (false),\n      m_looking_for_object_index (false),\n      m_looking_at_indirect_ref (false),\n      m_arguments_is_keyword (false),\n      m_classdef_element_names_are_keywords (false),\n      m_parsing_anon_fcn_body (false),\n      m_parsing_class_method (false),\n      m_parsing_classdef (false),\n      m_parsing_classdef_decl (false),\n      m_parsing_classdef_superclass (false),\n      m_maybe_classdef_get_set_method (false),\n      m_parsing_classdef_get_method (false),\n      m_parsing_classdef_set_method (false),\n      m_quote_is_transpose (false),\n      m_force_script (false),\n      m_reading_fcn_file (false),\n      m_reading_script_file (false),\n      m_reading_classdef_file (false),\n      m_buffer_function_text (false),\n      m_comment_uses_hash_char (false),\n      m_bracketflag (0),\n      m_braceflag (0),\n      m_looping (0),\n      m_defining_fcn (0),\n      m_looking_at_function_handle (0),\n      m_block_comment_nesting_level (0),\n      m_command_arg_paren_count (0),\n      m_token_count (0),\n      m_filepos (1, 1),\n      m_tok_beg (),\n      m_tok_end (),\n      m_string_text (),\n      m_current_input_line (),\n      m_comment_text (),\n      m_function_text (),\n      m_fcn_file_name (),\n      m_fcn_file_full_name (),\n      m_dir_name (),\n      m_package_name (),\n      m_looking_at_object_index (),\n      m_parsed_function_name (),\n      m_symtab_context (interp),\n      m_nesting_level (),\n      m_tokens ()\n  {\n    init ();\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (lexical_feedback)\n\n  ~lexical_feedback ();\n\n  void init ();\n\n  void reset ();\n\n  int previous_token_id () const;\n  token * previous_token ();\n  const token * previous_token () const;\n\n  bool previous_token_is (int tok_id) const;\n  bool previous_token_is (const token *tok) const;\n\n  void mark_previous_token_trailing_space ();\n\n  bool space_follows_previous_token () const;\n\n  bool previous_token_is_binop () const;\n\n  bool previous_token_is_keyword () const;\n\n  bool previous_token_may_be_command () const;\n\n  void mark_as_variable (const std::string& nm);\n  void mark_as_variables (const std::list<std::string>& lst);\n\n  //--------\n\n  interpreter& m_interpreter;\n\n  // true means that we have encountered eof on the input stream.\n  bool m_end_of_input;\n\n  // true means command syntax is allowed.\n  bool m_allow_command_syntax;\n\n  // true means we are at the beginning of a statement, where a\n  // command name is possible.\n  bool m_at_beginning_of_statement;\n\n  // true means we are parsing an anonymous function argument list.\n  bool m_looking_at_anon_fcn_args;\n\n  // true means we're parsing the return list for a function.\n  bool m_looking_at_return_list;\n\n  // true means we're parsing the parameter list for a function.\n  bool m_looking_at_parameter_list;\n\n  // true means we're parsing a declaration list (global or\n  // persistent).\n  bool m_looking_at_decl_list;\n\n  // true means we're parsing a matrix or the left hand side of\n  // multi-value assignment statement.\n  bool m_looking_at_matrix_or_assign_lhs;\n\n  // object index not possible until we've seen something.\n  bool m_looking_for_object_index;\n\n  // true means we're looking at an indirect reference to a\n  // structure element.\n  bool m_looking_at_indirect_ref;\n\n  // true means arguments is handled as keyword.\n  bool m_arguments_is_keyword;\n\n  // true means \"properties\", \"methods\", \"events\", and \"enumeration\"\n  // are treated like keywords.\n  bool m_classdef_element_names_are_keywords;\n\n  // true means we are parsing the body of an anonymous function.\n  bool m_parsing_anon_fcn_body;\n\n  // true means we are parsing a class method in function or classdef file.\n  bool m_parsing_class_method;\n\n  // true means we are parsing a classdef file\n  bool m_parsing_classdef;\n\n  // true means we are parsing the initial classdef declaration\n  // portion of classdef file, from the \"classdef\" token through the\n  // optional list of superclasses.\n  bool m_parsing_classdef_decl;\n\n  // true means we are parsing the superclass part of a classdef\n  // declaration.\n  bool m_parsing_classdef_superclass;\n\n  // true means we are parsing a class method declaration line in a\n  // classdef file and can accept a property get or set method name.\n  // for example, \"get.propertyname\" is recognized as a function name.\n  bool m_maybe_classdef_get_set_method;\n\n  // TRUE means we are parsing a classdef get.method.\n  bool m_parsing_classdef_get_method;\n\n  // TRUE means we are parsing a classdef set.method.\n  bool m_parsing_classdef_set_method;\n\n  // return transpose or start a string?\n  bool m_quote_is_transpose;\n\n  // TRUE means treat the current file as a script even if the first\n  // token is \"function\" or \"classdef\".\n  bool m_force_script;\n\n  // TRUE means we're parsing a function file.\n  bool m_reading_fcn_file;\n\n  // TRUE means we're parsing a script file.\n  bool m_reading_script_file;\n\n  // TRUE means we're parsing a classdef file.\n  bool m_reading_classdef_file;\n\n  // TRUE means we should store the text of the function we are\n  // parsing.\n  bool m_buffer_function_text;\n\n  // TRUE means a line comment uses '#' or a block comment used at least\n  // one '#' delimiter.\n  bool m_comment_uses_hash_char;\n\n  // square bracket level count.\n  int m_bracketflag;\n\n  // curly brace level count.\n  int m_braceflag;\n\n  // true means we're in the middle of defining a loop.\n  int m_looping;\n\n  // nonzero means we're in the middle of defining a function.\n  int m_defining_fcn;\n\n  // nonzero means we are parsing a function handle.\n  int m_looking_at_function_handle;\n\n  // nestng level for block comments.\n  int m_block_comment_nesting_level;\n\n  // Parenthesis count for command argument parsing.\n  int m_command_arg_paren_count;\n\n  // Count of tokens recognized by this lexer since initialized or\n  // since the last reset.\n  std::size_t m_token_count;\n\n  // The current position in the file (line and column).\n  filepos m_filepos;\n\n  // The positions of the beginning and end of the current token after\n  // calling update_token_positions.  Also used apart from\n  // update_token_positions to handle the beginning and end of\n  // character strings.\n  filepos m_tok_beg;\n  filepos m_tok_end;\n\n  // The current character string text.\n  std::string m_string_text;\n\n  // The current line of input.\n  std::string m_current_input_line;\n\n  // The text of the current comment, used to gather comment lines\n  // before storing in m_comment_list.\n  std::string m_comment_text;\n\n  // The text of functions entered on the command line.\n  std::string m_function_text;\n\n  // Simple name of function file we are reading.\n  std::string m_fcn_file_name;\n\n  // Full name of file we are reading.\n  std::string m_fcn_file_full_name;\n\n  // Directory name where this file was found.  May be relative.\n  std::string m_dir_name;\n\n  // Name of +package containing this file, if any.\n  std::string m_package_name;\n\n  // if the front of the list is true, the closest paren, brace, or\n  // bracket nesting is an index for an object.\n  std::list<bool> m_looking_at_object_index;\n\n  // if the top of the stack is true, then we've already seen the name\n  // of the current function.  should only matter if\n  // current_function_level > 0\n  std::stack<bool> m_parsed_function_name;\n\n  // Track current symbol table scope and context.\n  symbol_table_context m_symtab_context;\n\n  // is the closest nesting level a square bracket, squiggly brace,\n  // a paren, or an anonymous function body?\n  bbp_nesting_level m_nesting_level;\n\n  // Tokens generated by the lexer.\n  token_cache m_tokens;\n};\n\n// base_lexer inherits from lexical_feedback because we will\n// eventually have several different constructors and it is easier to\n// initialize if everything is grouped in a parent class rather than\n// listing all the members in the base_lexer class.\n\nclass OCTINTERP_API base_lexer : public lexical_feedback\n{\npublic:\n\n  // Handle buffering of input for lexer.\n\n  class input_buffer\n  {\n  public:\n\n    input_buffer ()\n      : m_buffer (), m_offset (0), m_chars_left (0), m_eof (false)\n    { }\n\n    OCTAVE_DEFAULT_COPY_MOVE_DELETE (input_buffer)\n\n    void fill (const std::string& input, bool eof_arg);\n\n    // Copy at most max_size characters to buf.\n    int copy_chunk (char *buf, std::size_t max_size, bool by_lines = false);\n\n    bool empty () const { return m_chars_left == 0; }\n\n    bool at_eof () const { return m_eof; }\n\n  private:\n\n    std::string m_buffer;\n    std::size_t m_offset;\n    std::size_t m_chars_left;\n    bool m_eof;\n  };\n\n  base_lexer (interpreter& interp)\n    : lexical_feedback (interp), m_scanner (nullptr), m_input_buf ()\n  {\n    init ();\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (base_lexer)\n\n  virtual ~base_lexer ();\n\n  void init ();\n\n  virtual bool is_push_lexer () const { return false; }\n\n  virtual void reset ();\n\n  void prep_for_file ();\n\n  void begin_string (int state);\n\n  virtual int fill_flex_buffer (char *buf, unsigned int max_size) = 0;\n\n  bool at_end_of_buffer () const { return m_input_buf.empty (); }\n\n  bool at_end_of_file () const { return m_input_buf.at_eof (); }\n\n  int handle_end_of_input ();\n\n  char * flex_yytext ();\n\n  int flex_yyleng ();\n\n  int text_yyinput ();\n\n  void xunput (char c, char *buf);\n\n  void xunput (char c);\n\n  void update_token_positions (int tok_len);\n\n  bool looking_at_space ();\n\n  bool inside_any_object_index ();\n\n  token * make_keyword_token (const std::string& s);\n\n  bool fq_identifier_contains_keyword (const std::string& s);\n\n  bool whitespace_is_significant ();\n\n  // We only provide specializations with base equal to 2, 10, or 16.\n  template <int base>\n  int handle_number ();\n\n  void handle_continuation ();\n\n  void finish_comment (comment_elt::comment_type typ);\n\n  comment_list get_comment_list ()\n  {\n    comment_list retval = m_comment_list;\n    m_comment_list.clear ();\n    return retval;\n  }\n\n  int handle_close_bracket (int bracket_type);\n\n  bool looks_like_command_arg ();\n\n  int handle_superclass_identifier ();\n\n  token * make_meta_identifier_token (const std::string& cls);\n\n  token * make_fq_identifier_token (const std::string& ident);\n\n  int handle_identifier ();\n\n  void check_comment_for_hash_char (const char *txt, std::size_t len);\n\n  void maybe_warn_separator_insert (char sep);\n\n  void warn_language_extension (const std::string& msg);\n\n  void maybe_warn_language_extension_comment (char c);\n\n  void warn_language_extension_continuation ();\n\n  void warn_language_extension_operator (const std::string& op);\n\n  void warn_deprecated_syntax (const std::string& msg);\n\n  int syntax_error (const std::string& msg);\n  int syntax_error (const std::string& msg, const filepos& pos);\n  int syntax_error (const std::string& msg, const filepos& beg_pos, const filepos& end_pos);\n\n  void push_token (token *);\n\n  token * current_token ();\n\n  std::size_t pending_token_count () const;\n\n  void display_token (int tok_id);\n\n  void fatal_error (const char *msg);\n\n  bool debug_flag () const;\n\n  bool display_tokens () const;\n\n  void increment_token_count ();\n\n  void lexer_debug (const char *pattern);\n\n  // Internal state of the flex-generated lexer.\n  void *m_scanner;\n\n  // Object that reads and buffers input.\n  input_buffer m_input_buf;\n\n  // List of collected comments.\n  comment_list m_comment_list;\n\n  virtual std::string input_source () const { return \"unknown\"; }\n\n  virtual bool input_from_terminal () const { return false; }\n\n  virtual bool input_from_file () const { return false; }\n\n  virtual bool input_from_eval_string () const { return false; }\n\n  bool input_from_tmp_history_file ();\n\n  void push_start_state (int state);\n\n  void pop_start_state ();\n\n  void clear_start_state ();\n\n  int start_state () const { return start_state_stack.top (); }\n\n  void display_start_state () const;\n\n  bool maybe_unput_comma_before_unary_op (int tok_id);\n\n  int handle_op (int tok_id, const std::string& tok_txt, int tok_len, bool bos = false, bool compat = true);\n\n  int finish_command_arg ();\n\n  int handle_token (int tok_id);\n  int handle_token (token *tok);\n\n  int count_token_internal (int tok_id);\n\n  int show_token (int tok_id);\n\nprotected:\n\n  std::stack<int> start_state_stack;\n};\n\nclass OCTINTERP_API lexer : public base_lexer\n{\npublic:\n\n  lexer (interpreter& interp)\n    : base_lexer (interp), m_reader (interp), m_initial_input (true)\n  { }\n\n  lexer (FILE *file, interpreter& interp)\n    : base_lexer (interp), m_reader (interp, file), m_initial_input (true)\n  { }\n\n  lexer (FILE *file, interpreter& interp, const std::string& encoding)\n    : base_lexer (interp), m_reader (interp, file, encoding),\n      m_initial_input (true)\n  { }\n\n  lexer (const std::string& eval_string, interpreter& interp)\n    : base_lexer (interp), m_reader (interp, eval_string),\n      m_initial_input (true)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (lexer)\n\n  ~lexer () = default;\n\n  void reset ()\n  {\n    m_initial_input = true;\n\n    base_lexer::reset ();\n  }\n\n  std::string input_source () const\n  {\n    return m_reader.input_source ();\n  }\n\n  bool input_from_terminal () const\n  {\n    return m_reader.input_from_terminal ();\n  }\n\n  bool input_from_file () const\n  {\n    return m_reader.input_from_file ();\n  }\n\n  bool input_from_eval_string () const\n  {\n    return m_reader.input_from_eval_string ();\n  }\n\n  int fill_flex_buffer (char *buf, unsigned int max_size);\n\n  //--------\n\n  input_reader m_reader;\n\n  // TRUE means we are filling the input buffer for the first time.\n  // Otherwise, we are requesting more input to complete the parse\n  // and, if printing a prompt, should use the secondary prompt\n  // string.\n\n  bool m_initial_input;\n};\n\ntemplate <> OCTINTERP_API int base_lexer::handle_number<2> ();\ntemplate <> OCTINTERP_API int base_lexer::handle_number<10> ();\ntemplate <> OCTINTERP_API int base_lexer::handle_number<16> ();\n\nclass OCTINTERP_API push_lexer : public base_lexer\n{\npublic:\n\n  push_lexer (interpreter& interp)\n    : base_lexer (interp)\n  {\n    append_input (\"\", false);\n  }\n\n  push_lexer (const std::string& input, interpreter& interp)\n    : base_lexer (interp)\n  {\n    append_input (input, false);\n  }\n\n  push_lexer (bool eof, interpreter& interp)\n    : base_lexer (interp)\n  {\n    append_input (\"\", eof);\n  }\n\n  push_lexer (const std::string& input, bool eof, interpreter& interp)\n    : base_lexer (interp)\n  {\n    append_input (input, eof);\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (push_lexer)\n\n  ~push_lexer () = default;\n\n  bool is_push_lexer () const { return true; }\n\n  void append_input (const std::string& input, bool eof);\n\n  std::string input_source () const { return \"push buffer\"; }\n\n  int fill_flex_buffer (char *buf, unsigned int max_size);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/lex.ll",
    "content": "/*\n\nWe are using the pure parser interface and the reentrant lexer interface\nbut the Octave parser and lexer are NOT properly reentrant because both\nstill use many global variables.  It should be safe to create a parser\nobject and call it while another parser object is active (to parse a\ncallback function while the main interactive parser is waiting for\ninput, for example) if you take care to properly save and restore\n(typically with an unwind_protect object) relevant global values before\nand after the nested call.\n\n*/\n\n%top {\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Uncomment to enable parser debugging\n// #define OCTAVE_PARSER_DEBUG 1\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // This one needs to be global.\n#  pragma GCC diagnostic ignored \"-Wunused-function\"\n   // Disable these warnings for code that is generated by flex,\n   // including pattern rules.  Push the current state so we can\n   // restore the warning state prior to functions we define at\n   // the bottom of the file.\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#  pragma GCC diagnostic ignored \"-Wsign-compare\"\n#  pragma GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"\n#  if defined (HAVE_WARN_IMPLICIT_FALLTHROUGH)\n#    pragma GCC diagnostic ignored \"-Wimplicit-fallthrough\"\n#  endif\n#endif\n\n// Define away the deprecated register storage class specifier to avoid\n// potential warnings about it.\n#if ! defined (register)\n#  define register\n#endif\n\n}\n\n%option prefix = \"octave_\"\n%option noyywrap\n%option reentrant\n%option bison-bridge\n\n%option noyyalloc\n%option noyyrealloc\n%option noyyfree\n\n%x COMMAND_START\n%s MATRIX_START\n\n%x INPUT_FILE_START\n\n%x BLOCK_COMMENT_START\n%x LINE_COMMENT_START\n\n%x DQ_STRING_START\n%x SQ_STRING_START\n\n%x FQ_IDENT_START\n\n%{\n\n#include <cctype>\n#include <cstring>\n\n#include <algorithm>\n#include <charconv>\n#include <iostream>\n#include <set>\n#include <sstream>\n#include <string>\n#include <stack>\n\n#if defined (OCTAVE_HAVE_FAST_FLOAT)\n#  include <fast_float/fast_float.h>\n#endif\n\n#include \"cmd-edit.h\"\n#include \"mappers.h\"\n#include \"quit.h\"\n#include \"unistd-wrappers.h\"\n\n// These would be alphabetical, but oct-parse.h must be included before\n// oct-gperf.h and oct-parse.h must be included after token.h and the tree\n// class declarations.  We can't include oct-parse.h in oct-gperf.h\n// because it may not be protected to allow it to be included multiple\n// times.\n\n#include \"Cell.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"input.h\"\n#include \"interpreter.h\"\n#include \"lex.h\"\n#include \"octave.h\"\n#include \"ov-magic-int.h\"\n#include \"ov.h\"\n#include \"parse.h\"\n#include \"pt-all.h\"\n#include \"symtab.h\"\n#include \"token.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"oct-parse.h\"\n#include \"oct-gperf.h\"\n\n// FIXME: with bison 3.x, OCTAVE_STYPE appears in the generated\n// oct-parse.h file, but there is no definition for YYSTYPE, which is\n// needed by the code that is generated by flex.  I can't seem to find a\n// way to tell flex to use OCTAVE_STYPE instead of YYSTYPE in the code\n// it generates, or to tell bison to provide the definition of YYSTYPE\n// in the generated oct-parse.h file.\n\n#if defined (OCTAVE_STYPE_IS_DECLARED) && ! defined YYSTYPE\n#  define YYSTYPE OCTAVE_STYPE\n#endif\n\n#define YY_NO_UNISTD_H 1\n#define isatty octave_isatty_wrapper\n\n#if ! (defined (FLEX_SCANNER)                                           \\\n       && defined (YY_FLEX_MAJOR_VERSION) && YY_FLEX_MAJOR_VERSION >= 2 \\\n       && defined (YY_FLEX_MINOR_VERSION) && YY_FLEX_MINOR_VERSION >= 5)\n#error lex.l requires flex version 2.5.4 or later\n#endif\n\n#define YY_EXTRA_TYPE octave::base_lexer *\n#define curr_lexer yyextra\n\n// Arrange to get input via readline.\n\n#if defined (YY_INPUT)\n#  undef YY_INPUT\n#endif\n#define YY_INPUT(buf, result, max_size)                 \\\n  result = curr_lexer->fill_flex_buffer (buf, max_size)\n\n// Try to avoid crashing out completely on fatal scanner errors.\n\n#if defined (YY_FATAL_ERROR)\n#  undef YY_FATAL_ERROR\n#endif\n#define YY_FATAL_ERROR(msg)                     \\\n   (yyget_extra (yyscanner))->fatal_error (msg)\n\n#define CMD_OR_OP(PATTERN, TOK_ID, COMPAT)                      \\\n   do                                                           \\\n     {                                                          \\\n       curr_lexer->lexer_debug (PATTERN);                       \\\n                                                                \\\n       /* Preserve values before they may be invalidated by     \\\n          a call to unput.  */                                  \\\n       std::string tok_txt (yytext);                            \\\n       int tok_len = yyleng;                                    \\\n                                                                \\\n       if (curr_lexer->looks_like_command_arg ())               \\\n         {                                                      \\\n           yyless (0);                                          \\\n           curr_lexer->push_start_state (COMMAND_START);        \\\n         }                                                      \\\n       else                                                     \\\n         return curr_lexer->handle_op (TOK_ID, tok_txt, tok_len, false, COMPAT); \\\n     }                                                          \\\n   while (0)\n\n#define CMD_OR_UNARY_OP(PATTERN, TOK_ID, COMPAT)                        \\\n   do                                                                   \\\n     {                                                                  \\\n       curr_lexer->lexer_debug (PATTERN);                               \\\n                                                                        \\\n       /* Preserve values before they may be invalidated by             \\\n          a call to unput.  */                                          \\\n       std::string tok_txt (yytext);                                    \\\n       int tok_len = yyleng;                                            \\\n                                                                        \\\n       if (curr_lexer->previous_token_may_be_command ())                \\\n         {                                                              \\\n           if (curr_lexer->looks_like_command_arg ())                   \\\n             {                                                          \\\n               yyless (0);                                              \\\n               curr_lexer->push_start_state (COMMAND_START);            \\\n             }                                                          \\\n           else                                                         \\\n             return curr_lexer->handle_op (TOK_ID, tok_txt, tok_len, false, COMPAT); \\\n         }                                                              \\\n       else                                                             \\\n         {                                                              \\\n           if (curr_lexer->maybe_unput_comma_before_unary_op (TOK_ID))  \\\n             {                                                          \\\n               yyless (0);                                              \\\n               curr_lexer->xunput (',');                                \\\n             }                                                          \\\n           else                                                         \\\n             return curr_lexer->handle_op (TOK_ID, tok_txt, tok_len, false, COMPAT); \\\n         }                                                              \\\n     }                                                                  \\\n   while (0)\n\n#define HANDLE_EOB_OR_EOF(STATUS)                       \\\n   do                                                   \\\n     {                                                  \\\n       if (curr_lexer->is_push_lexer ())                \\\n         {                                              \\\n           if (curr_lexer->at_end_of_buffer ())         \\\n             return STATUS;                             \\\n                                                        \\\n           if (curr_lexer->at_end_of_file ())           \\\n             return curr_lexer->handle_end_of_input (); \\\n         }                                              \\\n     }                                                  \\\n   while (0)\n\n   // If we are at the end of the buffer, ask for more input.\n   // If we are at the end of the file, deal with it.\n   // Otherwise, just keep going with the text from the current buffer.\n#define HANDLE_STRING_CONTINUATION              \\\n   do                                           \\\n     {                                          \\\n       curr_lexer->m_filepos.next_line ();      \\\n                                                \\\n       HANDLE_EOB_OR_EOF (-1);                  \\\n     }                                          \\\n   while (0)\n\n#define HANDLE_NUMBER(PATTERN, BASE)                                    \\\n   do                                                                   \\\n     {                                                                  \\\n       curr_lexer->lexer_debug (PATTERN);                               \\\n                                                                        \\\n       if (curr_lexer->previous_token_may_be_command ()                 \\\n           &&  curr_lexer->space_follows_previous_token ())             \\\n         {                                                              \\\n           yyless (0);                                                  \\\n           curr_lexer->push_start_state (COMMAND_START);                \\\n         }                                                              \\\n       else                                                             \\\n         {                                                              \\\n           int tok_id = curr_lexer->previous_token_id ();               \\\n                                                                        \\\n           if (curr_lexer->whitespace_is_significant ()                 \\\n               && curr_lexer->space_follows_previous_token ()           \\\n               && ! (tok_id == '[' || tok_id == '{'                     \\\n                     || curr_lexer->previous_token_is_binop ()))        \\\n             {                                                          \\\n               yyless (0);                                              \\\n               curr_lexer->xunput (',');                                \\\n             }                                                          \\\n           else                                                         \\\n             return curr_lexer->handle_number<BASE> ();                 \\\n         }                                                              \\\n     }                                                                  \\\n   while (0)\n\n#define HANDLE_IDENTIFIER(pattern, get_set)                             \\\n   do                                                                   \\\n     {                                                                  \\\n       curr_lexer->lexer_debug (pattern);                               \\\n                                                                        \\\n       int tok_id = curr_lexer->previous_token_id ();                   \\\n                                                                        \\\n       if (curr_lexer->whitespace_is_significant ()                     \\\n           && curr_lexer->space_follows_previous_token ()               \\\n           && ! (tok_id == '[' || tok_id == '{'                         \\\n                 || curr_lexer->previous_token_is_binop ()))            \\\n         {                                                              \\\n           yyless (0);                                                  \\\n           curr_lexer->xunput (',');                                    \\\n         }                                                              \\\n       else                                                             \\\n         {                                                              \\\n           if (! curr_lexer->m_looking_at_decl_list                     \\\n               && curr_lexer->previous_token_may_be_command ())         \\\n             {                                                          \\\n               yyless (0);                                              \\\n               curr_lexer->push_start_state (COMMAND_START);            \\\n             }                                                          \\\n           else                                                         \\\n             {                                                          \\\n               if (get_set)                                             \\\n                 {                                                      \\\n                   yyless (3);                                          \\\n                   curr_lexer->m_filepos.increment_column (3);          \\\n                   curr_lexer->m_maybe_classdef_get_set_method = false; \\\n                 }                                                      \\\n                                                                        \\\n               return curr_lexer->handle_identifier ();                 \\\n             }                                                          \\\n         }                                                              \\\n     }                                                                  \\\n   while (0)\n\nstatic inline bool\nis_space_or_tab (char c)\n{\n  return c == ' ' || c == '\\t';\n}\n\nstatic inline bool\nis_space_or_tab_or_eol (char c)\n{\n  return c == ' ' || c == '\\t' || c == '\\n' || c == '\\r';\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n  bool iskeyword (const std::string& s)\n  {\n    // Parsing function names like \"set.property_name\" inside\n    // classdef-style class definitions is simplified by handling the\n    // \"set\" and \"get\" portions of the names using the same mechanism\n    // as is used for keywords.  However, they are not really keywords\n    // in the language, so omit them from the list of possible\n    // keywords.  Likewise for \"arguments\", \"enumeration\", \"events\",\n    // \"methods\", and \"properties\".\n\n    // FIXME: The following check is duplicated in Fiskeyword.\n    return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != nullptr\n            && ! (s == \"set\" || s == \"get\" || s == \"arguments\"\n                  || s == \"enumeration\" || s == \"events\"\n                  || s == \"methods\" || s == \"properties\"));\n  }\n\nOCTAVE_END_NAMESPACE(octave)\n\n%}\n\nD       [0-9]\nD_      [0-9_]\nS       [ \\t]\nNL      ((\\n)|(\\r)|(\\r\\n))\nCCHAR   [#%]\nIDENT   ([_a-zA-Z][_a-zA-Z0-9]*)\nFQIDENT ({IDENT}({S}*\\.{S}*{IDENT})*)\n\n%{\n// Decimal numbers may be real or imaginary but always create\n// double precision constants initially.  Any conversion to single\n// precision happens as part of an expression evaluation in the\n// interpreter, not the lexer and parser.\n%}\n\nDECIMAL_DIGITS ({D}{D_}*)\nEXPONENT       ([DdEe][+-]?{DECIMAL_DIGITS})\nREAL_DECIMAL   ((({DECIMAL_DIGITS}\\.?)|({DECIMAL_DIGITS}?\\.{DECIMAL_DIGITS})){EXPONENT}?)\nIMAG_DECIMAL   ({REAL_DECIMAL}[IiJj])\nDECIMAL_NUMBER ({REAL_DECIMAL}|{IMAG_DECIMAL})\n\n%{\n// It is possible to specify signedness and size for binary and\n// hexadecimal numbers but there is no special syntax for imaginary\n// constants.  Binary and hexadecimal constants always create integer\n// valued constants ({u,}int{8,16,32,64}).  If a size is not specified,\n// the smallest integer type that will hold the value is used.  Negative\n// values may be created with a signed size specification by applying\n// twos-complement conversion (for example, 0xffs8 produces an 8-bit\n// signed integer equal to -1 and 0b10000000s8 produces an 8-bit signed\n// integer equal to -128).\n%}\n\nSIZE_SUFFIX        ([su](8|16|32|64))\nBINARY_BITS        (0[bB][01][01_]*)\nBINARY_NUMBER      ({BINARY_BITS}|{BINARY_BITS}{SIZE_SUFFIX})\nHEXADECIMAL_BITS   (0[xX][0-9a-fA-F][0-9a-fA-F_]*)\nHEXADECIMAL_NUMBER ({HEXADECIMAL_BITS}|{HEXADECIMAL_BITS}{SIZE_SUFFIX})\n\nANY_EXCEPT_NL [^\\r\\n]\nANY_INCLUDING_NL (.|{NL})\n\n%%\n\n%{\n// Make script and function files start with an invalid token.  This makes\n// the parser go down a special path.\n%}\n\n<INPUT_FILE_START>{ANY_INCLUDING_NL} {\n    curr_lexer->lexer_debug (\"<INPUT_FILE_START>{ANY_INCLUDING_NL}\");\n\n    curr_lexer->xunput (yytext[0]);\n\n    // May be reset later if we see \"function\" or \"classdef\" appears\n    // as the first token.\n    curr_lexer->m_reading_script_file = true;\n\n    curr_lexer->pop_start_state ();\n\n    return curr_lexer->show_token (INPUT_FILE);\n  }\n\n<INPUT_FILE_START><<EOF>> {\n    curr_lexer->lexer_debug (\"<INPUT_FILE_START><<EOF>>\");\n\n    // May be reset later if we see \"function\" or \"classdef\" appears\n    // as the first token.\n    curr_lexer->m_reading_script_file = true;\n\n    curr_lexer->pop_start_state ();\n\n    return curr_lexer->show_token (INPUT_FILE);\n  }\n\n%{\n// Help and other command-style functions.\n%}\n\n%{\n// Commands can be continued on a second line using the ellipsis.\n// If an argument is in construction, it is completed.\n%}\n\n<COMMAND_START>(\\.\\.\\.){ANY_EXCEPT_NL}*{NL} {\n    curr_lexer->lexer_debug (\"<COMMAND_START>(\\\\.\\\\.\\\\.){ANY_EXCEPT_NL}*{NL}\");\n\n    if (! curr_lexer->m_string_text.empty ())\n      {\n        yyless (0);\n        curr_lexer->m_tok_end = curr_lexer->m_filepos;\n        return curr_lexer->finish_command_arg ();\n      }\n\n    HANDLE_STRING_CONTINUATION;\n  }\n\n%{\n// Commands normally end at the end of a line or a semicolon.\n%}\n\n<COMMAND_START>({CCHAR}{ANY_EXCEPT_NL}*)?{NL} {\n    curr_lexer->lexer_debug (\"<COMMAND_START>({CCHAR}{ANY_EXCEPT_NL}*)?{NL}\");\n\n    if (! curr_lexer->m_string_text.empty ())\n      {\n        yyless (0);\n        curr_lexer->m_tok_end = curr_lexer->m_filepos;\n        return curr_lexer->finish_command_arg ();\n      }\n\n    curr_lexer->update_token_positions (yyleng);\n\n    curr_lexer->m_filepos.next_line ();\n    curr_lexer->m_looking_for_object_index = false;\n    curr_lexer->pop_start_state ();\n    curr_lexer->m_comment_uses_hash_char = yytext[0] == '#';\n    curr_lexer->finish_comment (octave::comment_elt::end_of_line);\n\n    return curr_lexer->handle_token ('\\n');\n  }\n\n<COMMAND_START>[\\,\\;] {\n    curr_lexer->lexer_debug (\"<COMMAND_START>[\\\\,\\\\;]\");\n\n    if (yytext[0] != ',' || curr_lexer->m_command_arg_paren_count == 0)\n      {\n        if (! curr_lexer->m_string_text.empty ())\n          {\n            yyless (0);\n            curr_lexer->m_tok_end = curr_lexer->m_filepos;\n            return curr_lexer->finish_command_arg ();\n          }\n\n        curr_lexer->update_token_positions (yyleng);\n\n        curr_lexer->m_looking_for_object_index = false;\n        curr_lexer->m_at_beginning_of_statement = true;\n        curr_lexer->pop_start_state ();\n\n        return curr_lexer->handle_token (yytext[0]);\n      }\n    else\n      {\n        curr_lexer->m_string_text += yytext;\n        curr_lexer->m_filepos.increment_column (yyleng);\n      }\n  }\n\n%{\n// Unbalanced parentheses serve as pseudo-quotes: they are included in\n// the final argument string, but they cause parentheses and quotes to\n// be slurped into that argument as well.\n%}\n\n<COMMAND_START>[\\(\\[\\{]* {\n    curr_lexer->lexer_debug (\"<COMMAND_START>[\\\\(\\\\[\\\\{]+\");\n\n    curr_lexer->m_command_arg_paren_count += yyleng;\n    curr_lexer->m_string_text += yytext;\n    curr_lexer->m_filepos.increment_column (yyleng);\n  }\n\n<COMMAND_START>[\\)\\]\\}]* {\n   curr_lexer->lexer_debug (\"<COMMAND_START>[\\\\)\\\\]\\\\}]+\");\n\n   curr_lexer->m_command_arg_paren_count -= yyleng;\n   curr_lexer->m_string_text += yytext;\n   curr_lexer->m_filepos.increment_column (yyleng);\n}\n\n%{\n// Handle quoted strings.  Quoted strings that are not separated by\n// whitespace from other argument text are combined with that previous\n// text.  For instance,\n//\n//   command 'text1'\"text2\"\n//\n// has a single argument text1text2, not two separate arguments.\n// That's why we must test to see if we are in command argument mode\n// when processing the end of a string.\n%}\n\n<COMMAND_START>[\\\"\\'] {\n    curr_lexer->lexer_debug (\"<COMMAND_START>[\\\\\\\"\\\\']\");\n\n    if (curr_lexer->m_command_arg_paren_count == 0)\n      curr_lexer->begin_string (yytext[0] == '\"'\n                                ? DQ_STRING_START : SQ_STRING_START);\n    else\n      curr_lexer->m_string_text += yytext;\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n  }\n\n%{\n// In standard command argument processing, whitespace separates\n// arguments.  In the presence of unbalanced parentheses, it is\n// incorporated into the argument.\n%}\n\n<COMMAND_START>{S}* {\n    curr_lexer->lexer_debug (\"<COMMAND_START>{S}*\");\n\n    if (curr_lexer->m_command_arg_paren_count == 0)\n      {\n        if (! curr_lexer->m_string_text.empty ())\n          {\n            yyless (0);\n            curr_lexer->m_tok_end = curr_lexer->m_filepos;\n            return curr_lexer->finish_command_arg ();\n          }\n      }\n    else\n      curr_lexer->m_string_text += yytext;\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n  }\n\n%{\n// Everything else is slurped into the command arguments.\n%}\n\n<COMMAND_START>([\\.]|[^#% \\t\\r\\n\\.\\,\\;\\\"\\'\\(\\[\\{\\}\\]\\)]*) {\n    curr_lexer->lexer_debug (\"<COMMAND_START>([\\\\.]|[^#% \\\\t\\\\r\\\\n\\\\.\\\\,\\\\;\\\\\\\"\\\\'\\\\(\\\\[\\\\{\\\\}\\\\]\\\\)]*\");\n\n    curr_lexer->m_string_text += yytext;\n    curr_lexer->m_filepos.increment_column (yyleng);\n  }\n\n%{\n// Whitespace inside matrix lists.\n%}\n\n<MATRIX_START>{S}* {\n    curr_lexer->lexer_debug (\"<MATRIX_START>{S}*\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n\n    curr_lexer->mark_previous_token_trailing_space ();\n  }\n\n<MATRIX_START>{NL} {\n    curr_lexer->lexer_debug (\"<MATRIX_START>{NL}\");\n\n    curr_lexer->m_filepos.next_line ();\n\n    if (curr_lexer->m_nesting_level.is_paren ())\n      curr_lexer->warn_language_extension (\"bare newline inside parentheses\");\n    else\n      {\n        int tok_id = curr_lexer->previous_token_id ();\n\n        if (! (tok_id == ';' || tok_id == '[' || tok_id == '{'))\n          curr_lexer->xunput (';');\n      }\n  }\n\n%{\n// Continuation lines in matrix constants are handled as whitespace.\n// Allow arbitrary text after the continuation marker.\n%}\n\n<MATRIX_START>\\.\\.\\.{ANY_EXCEPT_NL}*{NL} {\n    curr_lexer->lexer_debug (\"<MATRIX_START>\\\\.\\\\.\\\\.{ANY_EXCEPT_NL}*{NL}\");\n\n    curr_lexer->handle_continuation ();\n\n    // Even if there wasn't a space before or after the continuation\n    // marker, treat the continuation as if it were.  But since it will\n    // be transformed to a separator later anyway, there's no need to\n    // actually unput a space on the input stream.\n\n    curr_lexer->mark_previous_token_trailing_space ();\n  }\n\n%{\n// For this and the next two rules, we're looking at ']', and we\n// need to know if the next token is '=' or '=='.\n//\n// It would have been so much easier if the delimiters were simply\n// different for the expression on the left hand side of the equals\n// operator.\n//\n// It's also a pain in the ass to decide whether to insert a comma\n// after seeing a ']' character...\n\n// FIXME: we need to handle block comments here.\n%}\n\n<MATRIX_START>\\] {\n    curr_lexer->lexer_debug (\"<MATRIX_START>\\\\]\");\n\n    curr_lexer->update_token_positions (yyleng);\n    return curr_lexer->handle_close_bracket (']');\n  }\n\n%{\n// FIXME: we need to handle block comments here.\n%}\n\n<MATRIX_START>\\} {\n    curr_lexer->lexer_debug (\"<MATRIX_START>\\\\}*\");\n\n    curr_lexer->update_token_positions (yyleng);\n    return curr_lexer->handle_close_bracket ('}');\n  }\n\n\\[ {\n    curr_lexer->lexer_debug (\"\\\\[\");\n\n        bool unput_comma = false;\n\n    if (curr_lexer->whitespace_is_significant ()\n        && curr_lexer->space_follows_previous_token ())\n      {\n        int tok_id = curr_lexer->previous_token_id ();\n\n        if (! (tok_id == '[' || tok_id == '{'\n               || curr_lexer->previous_token_is_binop ()))\n          unput_comma = true;\n      }\n\n    if (unput_comma)\n      {\n        yyless (0);\n        curr_lexer->xunput (',');\n      }\n    else\n      {\n        curr_lexer->update_token_positions (yyleng);\n\n        curr_lexer->m_nesting_level.bracket ();\n\n        curr_lexer->m_looking_at_object_index.push_front (false);\n\n        curr_lexer->m_looking_for_object_index = false;\n        curr_lexer->m_at_beginning_of_statement = false;\n\n        if (curr_lexer->m_defining_fcn\n            && ! curr_lexer->m_parsed_function_name.top ())\n          curr_lexer->m_looking_at_return_list = true;\n        else\n          curr_lexer->m_looking_at_matrix_or_assign_lhs = true;\n\n        curr_lexer->m_bracketflag++;\n\n        curr_lexer->push_start_state (MATRIX_START);\n\n        return curr_lexer->handle_token ('[');\n      }\n  }\n\n\\] {\n    curr_lexer->lexer_debug (\"\\\\]\");\n\n    curr_lexer->update_token_positions (yyleng);\n\n    curr_lexer->m_nesting_level.remove ();\n\n    curr_lexer->m_looking_at_object_index.pop_front ();\n\n    curr_lexer->m_looking_for_object_index = true;\n    curr_lexer->m_at_beginning_of_statement = false;\n\n    return curr_lexer->handle_token (']');\n  }\n\n%{\n// Gobble comments.  Both BLOCK_COMMENT_START and LINE_COMMENT_START\n// are exclusive start states.  We try to grab a continuous series of\n// line-oriented comments as a single collection of comments.\n%}\n\n%{\n// Start of a block comment.  Since comment start states are exclusive,\n// this pattern will not match a block comment that immediately follows\n// a line-oriented comment.  All we need to do is push the matched text\n// back on the input stream and push the new start state.\n%}\n\n^{S}*{CCHAR}\\{{S}*{NL} {\n    curr_lexer->lexer_debug (\"^{S}*{CCHAR}\\\\{{S}*{NL}\");\n\n    yyless (0);\n\n    curr_lexer->push_start_state (BLOCK_COMMENT_START);\n  }\n\n<BLOCK_COMMENT_START>^{S}*{CCHAR}\\{{S}*{NL} {\n    curr_lexer->lexer_debug (\"<BLOCK_COMMENT_START>^{S}*{CCHAR}\\\\{{S}*{NL}\");\n\n    curr_lexer->m_filepos.next_line ();\n\n    if (curr_lexer->m_block_comment_nesting_level)\n      curr_lexer->m_comment_text = \"\\n\";\n    else\n      curr_lexer->check_comment_for_hash_char (yytext, yyleng);\n\n    curr_lexer->m_block_comment_nesting_level++;\n\n    HANDLE_EOB_OR_EOF (-1);\n  }\n\n%{\n// End of a block comment.  If this block comment is nested inside\n// another, wait for the outermost block comment to be closed before\n// storing the comment.\n\n// NOTE: This pattern must appear before the one below.  Both may match\n// the same text and this one should take precedence over the one that\n// follows.\n%}\n\n<BLOCK_COMMENT_START>^{S}*{CCHAR}\\}{S}*{NL} {\n    curr_lexer->lexer_debug (\"<BLOCK_COMMENT_START>^{S}*{CCHAR}\\\\}{S}*{NL}\");\n\n    curr_lexer->m_filepos.next_line ();\n\n    if (curr_lexer->m_block_comment_nesting_level > 1)\n      curr_lexer->m_comment_text = \"\\n\";\n    else\n      {\n        curr_lexer->check_comment_for_hash_char (yytext, yyleng);\n        curr_lexer->finish_comment (octave::comment_elt::block);\n      }\n\n    curr_lexer->m_block_comment_nesting_level--;\n\n    if (curr_lexer->m_block_comment_nesting_level == 0)\n      {\n        curr_lexer->pop_start_state ();\n\n        if (curr_lexer->pending_token_count () > 0)\n          HANDLE_EOB_OR_EOF (-1);\n        else\n          HANDLE_EOB_OR_EOF (-2);\n      }\n    else\n      HANDLE_EOB_OR_EOF (-1);\n  }\n\n%{\n// Body of a block comment.\n%}\n\n<BLOCK_COMMENT_START>{ANY_EXCEPT_NL}*{NL} {\n    curr_lexer->lexer_debug (\"<BLOCK_COMMENT_START>{ANY_EXCEPT_NL}*{NL}\");\n\n    curr_lexer->m_filepos.next_line ();\n    curr_lexer->m_comment_text += yytext;\n\n    HANDLE_EOB_OR_EOF (-1);\n  }\n\n%{\n// Full-line or end-of-line comment.\n%}\n\n{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL} {\n    curr_lexer->lexer_debug (\"{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL}\");\n\n    curr_lexer->push_start_state (LINE_COMMENT_START);\n    yyless (0);\n  }\n\n%{\n// Beginning of a block comment while we are looking at a series of\n// line-oriented comments.  Finish previous comment, push current\n// text back on input stream, and switch start states.\n\n// NOTE: This pattern must appear before the one below.  Both may match\n// the same text and this one should take precedence over the one that\n// follows.\n%}\n\n<LINE_COMMENT_START>^{S}*{CCHAR}\\{{S}*{NL} {\n    curr_lexer->lexer_debug (\"<LINE_COMMENT_START>^{S}*{CCHAR}\\\\{{S}*{NL}\");\n\n    if (! curr_lexer->m_comment_text.empty ())\n      curr_lexer->finish_comment (octave::comment_elt::full_line);\n\n    curr_lexer->pop_start_state ();\n    curr_lexer->push_start_state (BLOCK_COMMENT_START);\n    yyless (0);\n  }\n\n%{\n// Line-oriented comment.  If we are at the beginning of a line, this is\n// part of a series of full-line comments.  Otherwise, this is an end of\n// line comment.  We don't need to parse the matched text to determine\n// whether we are looking at the start of a block comment as that\n// pattern is handled above.\n\n// NOTE: This pattern must appear before the one below.  Both may match\n// the same text and this one should take precedence over the one that\n// follows.\n%}\n\n<LINE_COMMENT_START>{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL} {\n    curr_lexer->lexer_debug (\"<LINE_COMMENT_START>{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL}\");\n\n    // Grab text of comment without leading space or comment\n    // characters.\n\n    std::size_t i = 0;\n    while (i < yyleng && is_space_or_tab (yytext[i]))\n      i++;\n\n    bool have_space = (i > 0);\n\n    bool first = true;\n\n    while (i < yyleng)\n      {\n        char c = yytext[i];\n\n        if (c == '#' || c == '%')\n          {\n            if (first && c == '#')\n              {\n                curr_lexer->m_comment_uses_hash_char = true;\n                first = false;\n              }\n\n            i++;\n          }\n        else\n          break;\n      }\n\n    curr_lexer->m_comment_text += &yytext[i];\n\n    if (curr_lexer->m_filepos.column () == 1)\n      {\n        curr_lexer->m_filepos.next_line ();\n      }\n    else\n      {\n        // End of line comment.\n\n        if (have_space)\n          curr_lexer->mark_previous_token_trailing_space ();\n\n        curr_lexer->finish_comment (octave::comment_elt::end_of_line);\n\n        curr_lexer->pop_start_state ();\n\n        // Push the newline character back on the input and skip\n        // incrementing the line count so we don't have to duplicate\n        // all the possible actions that happen with newlines here.\n\n        curr_lexer->xunput ('\\n');\n\n        // The next action should recognize a newline character and set\n        // the input column back to 1, but we should try to keep the\n        // input column location accurate anyway, so update here.\n        curr_lexer->m_filepos.increment_column (yyleng);\n      }\n  }\n\n%{\n// End of a series of full-line because some other character was\n// found on the input stream.\n%}\n\n<LINE_COMMENT_START>{ANY_INCLUDING_NL} {\n    curr_lexer->lexer_debug (\"<LINE_COMMENT_START>{ANY_INCLUDING_NL}\");\n\n    if (yytext[0] == '\\001')\n      {\n        // We are here because we are using the push parser/lexer\n        // interface and we hit the end of the input buffer or file.\n        // The special ASCII 1 marker is added to the input by\n        // push_lexer::fill_flex_buffer.\n\n        if (curr_lexer->pending_token_count () > 0)\n          {\n            // We are in the middle of parsing a command, expresison,\n            // etc., so set the return status so that if we are at the\n            // end of the buffer we'll continue looking for more input,\n            // possibly buffering a series of line oriented comments as\n            // a single block.\n\n            HANDLE_EOB_OR_EOF (-1);\n          }\n        else\n          {\n            // We are not in the process of parsing a command,\n            // expression, etc., so end any current sequence of comments\n            // with this full line comment, pop the start state and\n            // return as if we have just finished parsing a complete\n            // statement.\n\n            curr_lexer->finish_comment (octave::comment_elt::full_line);\n\n            curr_lexer->pop_start_state ();\n\n            HANDLE_EOB_OR_EOF (-2);\n          }\n      }\n    else\n      {\n        // End any current sequence of comments, pop the start state,\n        // and unput the pending input character that ended the series\n        // of comments.\n\n        curr_lexer->finish_comment (octave::comment_elt::full_line);\n\n        curr_lexer->pop_start_state ();\n\n        curr_lexer->xunput (yytext[0]);\n      }\n  }\n\n%{\n// End of file will also end a series of full-line comments.\n%}\n\n<LINE_COMMENT_START><<EOF>> {\n    curr_lexer->lexer_debug (\"<LINE_COMMENT_START><<EOF>>\");\n\n    curr_lexer->finish_comment (octave::comment_elt::full_line);\n\n    curr_lexer->pop_start_state ();\n  }\n\n%{\n// Double-quoted character strings.\n%}\n\n<DQ_STRING_START>\\\"\\\" {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\\\\\"\\\\\\\"\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += '\"';\n  }\n\n<DQ_STRING_START>\\\" {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\\\\\"\");\n\n    // m_tok_beg was set when we started parsing the string.\n    curr_lexer->m_tok_end = curr_lexer->m_filepos;\n    curr_lexer->m_filepos.increment_column ();\n\n    curr_lexer->pop_start_state ();\n\n    if (curr_lexer->start_state() != COMMAND_START)\n      {\n        curr_lexer->m_looking_for_object_index = true;\n        curr_lexer->m_at_beginning_of_statement = false;\n\n        octave::token *tok = new octave::token (DQ_STRING, curr_lexer->m_string_text, curr_lexer->m_tok_beg, curr_lexer->m_tok_end, curr_lexer->get_comment_list ());\n\n        curr_lexer->m_string_text = \"\";\n\n        return curr_lexer->handle_token (tok);\n      }\n  }\n\n<DQ_STRING_START>\\\\[0-7]{1,3} {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\\\\\\[0-7]{1,3}\");\n\n    curr_lexer->update_token_positions (yyleng);\n\n    unsigned int result = 0;\n    const char *chars_start = yytext + 1;\n    const char *chars_end = yytext + yyleng;\n    auto [ptr, ec] = std::from_chars (chars_start, chars_end, result, 8);\n    if (ec != std::errc{})\n      {\n        switch (ec)\n          {\n          case std::errc::invalid_argument:\n            curr_lexer->fatal_error (\"invalid octal digits in lexer rule <DQ_STRING_START>\\\\\\\\[0-7]{1,3} - please report this bug\");\n            break;\n          case std::errc::result_out_of_range:\n            curr_lexer->fatal_error (\"octal value out of range in lexer rule <DQ_STRING_START>\\\\\\\\[0-7]{1,3} - please report this bug\");\n            break;\n          default:\n            curr_lexer->fatal_error (\"from_chars failed in lexer rule <DQ_STRING_START>\\\\\\\\[0-7]{1,3} - please report this bug\");\n            break;\n          }\n      }\n\n\n    if (result > 0xff)\n      {\n        // Use location of octal digits for error token.\n        std::string msg {\"invalid octal escape sequence in character string\"};\n        return curr_lexer->syntax_error (msg);\n      }\n    else\n      curr_lexer->m_string_text += static_cast<unsigned char> (result);\n  }\n\n<DQ_STRING_START>\\\\x[0-9a-fA-F]+ {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\\\\\\x[0-9a-fA-F]+\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n\n    unsigned int result = 0;\n    const char *chars_start = yytext + 2;\n    const char *chars_end = yytext + yyleng;\n    auto [ptr, ec] = std::from_chars (chars_start, chars_end, result, 16);\n    if (ec != std::errc{})\n      {\n        switch (ec)\n          {\n          case std::errc::invalid_argument:\n            curr_lexer->fatal_error (\"invalid hexadecimal digits in lexer rule <DQ_STRING_START>\\\\\\\\x[0-9a-fA-F]+ - please report this bug\");\n            break;\n          case std::errc::result_out_of_range:\n            curr_lexer->fatal_error (\"hexadecimal value out of range in lexer rule <DQ_STRING_START>\\\\\\\\x[0-9a-fA-F]+ - please report this bug\");\n            break;\n          default:\n            curr_lexer->fatal_error (\"from_chars failed in lexer rule <DQ_STRING_START>\\\\\\\\x[0-9a-fA-F]+ - please report this bug\");\n            break;\n          }\n      }\n\n\n    // Truncate the value silently instead of checking the range like\n    // we do for octal above.  This is to match C/C++ where any number\n    // of digits is allowed but the value is implementation-defined if\n    // it exceeds the range of the character type.\n    curr_lexer->m_string_text += static_cast<unsigned char> (result);\n  }\n\n<DQ_STRING_START>\"\\\\a\" {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\"\\\\\\\\a\\\"\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += '\\a';\n  }\n\n<DQ_STRING_START>\"\\\\b\" {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\"\\\\\\\\b\\\"\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += '\\b';\n  }\n\n<DQ_STRING_START>\"\\\\f\" {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\"\\\\\\\\f\\\"\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += '\\f';\n  }\n\n<DQ_STRING_START>\"\\\\n\" {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\"\\\\\\\\n\\\"\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += '\\n';\n  }\n\n<DQ_STRING_START>\"\\\\r\" {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\"\\\\\\\\r\\\"\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += '\\r';\n  }\n\n<DQ_STRING_START>\"\\\\t\" {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\"\\\\\\\\t\\\"\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += '\\t';\n  }\n\n<DQ_STRING_START>\"\\\\v\" {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\"\\\\\\\\v\\\"\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += '\\v';\n  }\n\n<DQ_STRING_START>\\\\{NL} {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\\\\\\{NL}\");\n\n    HANDLE_STRING_CONTINUATION;\n  }\n\n<DQ_STRING_START>\\\\. {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\\\\\\.\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += yytext[1];\n  }\n\n<DQ_STRING_START>\\. {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>\\\\.\");\n\n    curr_lexer->m_filepos.increment_column ();\n    curr_lexer->m_string_text += yytext[0];\n  }\n\n<DQ_STRING_START>[^\\.\\\\\\r\\n\\\"]+ {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>[^\\\\.\\\\\\\\\\\\r\\\\n\\\\\\\"]+\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += yytext;\n  }\n\n<DQ_STRING_START>{NL} {\n    curr_lexer->lexer_debug (\"<DQ_STRING_START>{NL}\");\n\n    // Use current file position for error token.\n    std::string msg {\"unterminated character string constant\"};\n    return curr_lexer->syntax_error (msg, curr_lexer->m_filepos);\n  }\n\n%{\n// Single-quoted character strings.\n%}\n\n<SQ_STRING_START>\\'\\' {\n    curr_lexer->lexer_debug (\"<SQ_STRING_START>\\\\'\\\\'\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += '\\'';\n  }\n\n<SQ_STRING_START>\\' {\n    curr_lexer->lexer_debug (\"<SQ_STRING_START>\\\\'\");\n\n    // m_tok_beg was set when we started parsing the string.\n    curr_lexer->m_tok_end = curr_lexer->m_filepos;\n    curr_lexer->m_filepos.increment_column ();\n\n    curr_lexer->pop_start_state ();\n\n    if (curr_lexer->start_state() != COMMAND_START)\n      {\n        curr_lexer->m_looking_for_object_index = true;\n        curr_lexer->m_at_beginning_of_statement = false;\n\n        octave::token *tok = new octave::token (SQ_STRING, curr_lexer->m_string_text, curr_lexer->m_tok_beg, curr_lexer->m_tok_end, curr_lexer->get_comment_list ());\n\n        curr_lexer->m_string_text = \"\";\n\n        return curr_lexer->handle_token (tok);\n      }\n  }\n\n<SQ_STRING_START>[^\\'\\n\\r]+ {\n    curr_lexer->lexer_debug (\"<SQ_STRING_START>[^\\\\'\\\\n\\\\r]+\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n    curr_lexer->m_string_text += yytext;\n  }\n\n<SQ_STRING_START>{NL} {\n    curr_lexer->lexer_debug (\"<SQ_STRING_START>{NL}\");\n\n    // Use current file position for error token.\n    std::string msg {\"unterminated character string constant\"};\n    return curr_lexer->syntax_error (msg, curr_lexer->m_filepos);\n  }\n\n%{\n// Fully-qualified identifiers (used for classdef).\n%}\n\n<FQ_IDENT_START>{FQIDENT} {\n    curr_lexer->lexer_debug (\"<FQ_IDENT_START>{FQIDENT}{S}*\");\n\n    curr_lexer->pop_start_state ();\n\n    curr_lexer->update_token_positions (yyleng);\n\n    std::string ident = yytext;\n\n    ident.erase (std::remove_if (ident.begin (), ident.end (), is_space_or_tab), ident.end ());\n\n    if (curr_lexer->fq_identifier_contains_keyword (ident))\n      return curr_lexer->syntax_error (\"function, method, class, and package names may not be keywords\");\n\n    octave::token *tok = curr_lexer->make_fq_identifier_token (ident);\n\n    return curr_lexer->handle_token (tok);\n  }\n\n<FQ_IDENT_START>{S}+ {\n    curr_lexer->lexer_debug (\"<FQ_IDENT_START>{S}+\");\n\n    curr_lexer->m_filepos.increment_column (yyleng);\n\n    curr_lexer->mark_previous_token_trailing_space ();\n  }\n\n<FQ_IDENT_START>(\\.\\.\\.){ANY_EXCEPT_NL}*{NL} {\n    curr_lexer->lexer_debug (\"<FQ_IDENT_START>(\\\\.\\\\.\\\\.){ANY_EXCEPT_NL}*{NL}\");\n\n    curr_lexer->m_filepos.next_line ();\n  }\n\n<FQ_IDENT_START>{ANY_INCLUDING_NL} {\n    curr_lexer->lexer_debug (\"<FQ_IDENT_START>{ANY_INCLUDING_NL}\");\n\n    // If input doesn't match FQIDENT, return char and go to previous\n    // start state.\n\n    yyless (0);\n    curr_lexer->pop_start_state ();\n  }\n\n{BINARY_NUMBER} {\n    HANDLE_NUMBER (\"{BINARY_NUMBER}\", 2);\n  }\n\n%{\n// Decimal numbers.  For expressions that are just digits followed\n// directly by an element-by-element operator, don't grab the '.'\n// part of the operator as part of the constant (for example, in an\n// expression like \"13./x\").\n%}\n\n{DECIMAL_DIGITS}/\\.[\\*/\\\\^\\'] |\n{DECIMAL_NUMBER} {\n    HANDLE_NUMBER (\"{DECIMAL_DIGITS}/\\\\.[\\\\*/\\\\\\\\^\\\\']|{DECIMAL_NUMBER}\", 10);\n  }\n\n{HEXADECIMAL_NUMBER} {\n    HANDLE_NUMBER (\"{HEXADECIMAL_NUMBER}\", 16);\n  }\n\n%{\n// Eat whitespace.  Whitespace inside matrix constants is handled by\n// the <MATRIX_START> start state code above.\n%}\n\n{S}+ {\n    curr_lexer->m_filepos.increment_column (yyleng);\n\n    curr_lexer->mark_previous_token_trailing_space ();\n  }\n\n%{\n// Continuation lines.  Allow arbitrary text after continuations.\n%}\n\n\\.\\.\\.{ANY_EXCEPT_NL}*{NL} {\n    curr_lexer->lexer_debug (\"\\\\.\\\\.\\\\.{ANY_EXCEPT_NL}*{NL}\");\n\n    curr_lexer->handle_continuation ();\n  }\n\n%{\n// Deprecated C preprocessor style continuation markers.\n%}\n\n\n%{\n// End of file.\n%}\n\n<<EOF>> {\n   return curr_lexer->handle_end_of_input ();\n  }\n\n%{\n// Identifiers.\n\n// Don't allow get and set to be recognized as keywords if they are\n// followed by \"(\".\n%}\n\n(set|get){S}*\\( {\n    HANDLE_IDENTIFIER (\"(set|get){S}*\\\\(\", true);\n  }\n\n{IDENT} {\n    HANDLE_IDENTIFIER (\"{IDENT}\", false);\n  }\n\n%{\n// Superclass method identifiers.\n%}\n\n{FQIDENT}{S}*@{S}*{FQIDENT} {\n    curr_lexer->lexer_debug (\"{FQIDENT}{S}*@{S}*{FQIDENT}\");\n\n    if (curr_lexer->previous_token_may_be_command ())\n      {\n        yyless (0);\n        curr_lexer->push_start_state (COMMAND_START);\n      }\n    else\n      {\n        if (curr_lexer->m_at_beginning_of_statement)\n          {\n            std::string txt = yytext;\n\n            std::size_t at_or_dot_pos = txt.find_first_of (\"@.\");\n\n            if (at_or_dot_pos != std::string::npos)\n              {\n                std::size_t spc_pos = txt.find_first_of (\" \\t\");\n\n                if (spc_pos != std::string::npos && spc_pos < at_or_dot_pos)\n                  {\n                    yyless (spc_pos);\n                    curr_lexer->m_filepos.increment_column (spc_pos);\n\n                    return curr_lexer->handle_identifier ();\n                  }\n              }\n          }\n\n        curr_lexer->m_looking_for_object_index = true;\n        curr_lexer->m_at_beginning_of_statement = false;\n\n        return curr_lexer->handle_superclass_identifier ();\n      }\n  }\n\n%{\n// Metaclass query\n%}\n\n\\?{S}*{FQIDENT} {\n    curr_lexer->lexer_debug (\"\\\\?{S}*{FQIDENT}\");\n\n    if (curr_lexer->previous_token_may_be_command ()\n        &&  curr_lexer->space_follows_previous_token ())\n      {\n        yyless (0);\n        curr_lexer->push_start_state (COMMAND_START);\n      }\n    else\n      {\n        curr_lexer->update_token_positions (yyleng);\n\n        std::string txt = yytext;\n\n        txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab), txt.end ());\n\n        // Eliminate leading '?'\n        std::string cls = txt.substr (1);\n\n        if (curr_lexer->fq_identifier_contains_keyword (cls))\n          return curr_lexer->syntax_error (\"class and package names may not be keywords\");\n\n        octave::token *tok = curr_lexer->make_meta_identifier_token (cls);\n\n        return curr_lexer->handle_token (tok);\n      }\n  }\n\n\\@ |\n\\@{S}*{FQIDENT} {\n    curr_lexer->lexer_debug (\"\\\\@|\\\\@{S}*{FQIDENT}\");\n\n    if (curr_lexer->previous_token_may_be_command ()\n        &&  curr_lexer->space_follows_previous_token ())\n      {\n        yyless (0);\n        curr_lexer->push_start_state (COMMAND_START);\n      }\n    else\n      {\n        int tok_id = curr_lexer->previous_token_id ();\n\n        if (curr_lexer->whitespace_is_significant ()\n            && curr_lexer->space_follows_previous_token ()\n            && ! (tok_id == '[' || tok_id == '{'\n                  || curr_lexer->previous_token_is_binop ()))\n          {\n            yyless (0);\n            curr_lexer->xunput (',');\n          }\n        else\n          {\n            curr_lexer->update_token_positions (yyleng);\n\n            curr_lexer->m_at_beginning_of_statement = false;\n\n            std::string ident = yytext;\n\n            if (ident == \"@\")\n              {\n                curr_lexer->m_looking_at_function_handle++;\n                curr_lexer->m_looking_for_object_index = false;\n\n                return curr_lexer->handle_token ('@');\n              }\n            else\n              {\n                ident = ident.substr (1);\n                ident.erase (std::remove_if (ident.begin (), ident.end (),\n                                             is_space_or_tab), ident.end ());\n\n                octave::token *tok;\n\n                if (octave::iskeyword (ident))\n                  {\n                    std::string msg {\"function handles may not refer to keywords\"};\n                    return curr_lexer->syntax_error (msg);\n                  }\n\n                curr_lexer->m_looking_for_object_index = true;\n\n                tok = new octave::token (FCN_HANDLE, ident, curr_lexer->m_tok_beg, curr_lexer->m_tok_end, curr_lexer->get_comment_list ());\n\n                return curr_lexer->handle_token (tok);\n              }\n          }\n      }\n  }\n\n%{\n// A new line character.  New line characters inside matrix constants\n// are handled by the <MATRIX_START> start state code above.  If closest\n// nesting is inside parentheses, don't return a row separator.\n%}\n\n{NL} {\n    curr_lexer->lexer_debug (\"{NL}\");\n\n    if (curr_lexer->m_nesting_level.is_paren ())\n      {\n        curr_lexer->m_filepos.next_line ();\n\n        curr_lexer->m_at_beginning_of_statement = false;\n        curr_lexer->warn_language_extension\n          (\"bare newline inside parentheses\");\n      }\n    else if (curr_lexer->m_nesting_level.none ()\n        || curr_lexer->m_nesting_level.is_anon_fcn_body ())\n      {\n        curr_lexer->update_token_positions (yyleng);\n        curr_lexer->m_filepos.next_line ();\n\n        curr_lexer->m_at_beginning_of_statement = true;\n\n        return curr_lexer->handle_token ('\\n');\n      }\n    else if (curr_lexer->m_nesting_level.is_bracket_or_brace ())\n      {\n        curr_lexer->update_token_positions (yyleng);\n        curr_lexer->m_filepos.next_line ();\n\n        // Use current file position for error token.\n        std::string msg {\"unexpected internal lexer error\"};\n        return curr_lexer->syntax_error (msg, curr_lexer->m_filepos);\n      }\n  }\n\n%{\n// Single quote can either be the beginning of a string or a transpose\n// operator.\n%}\n\n\"'\" {\n    curr_lexer->lexer_debug (\"'\");\n\n    if (curr_lexer->previous_token_may_be_command ()\n        &&  curr_lexer->space_follows_previous_token ())\n      {\n        curr_lexer->m_filepos.increment_column ();\n        curr_lexer->push_start_state (COMMAND_START);\n        curr_lexer->begin_string (SQ_STRING_START);\n      }\n    else if (curr_lexer->m_at_beginning_of_statement)\n      {\n        curr_lexer->m_filepos.increment_column ();\n        curr_lexer->begin_string (SQ_STRING_START);\n      }\n    else\n      {\n        int tok_id = curr_lexer->previous_token_id ();\n\n        if (curr_lexer->whitespace_is_significant ())\n          {\n            if (curr_lexer->space_follows_previous_token ())\n              {\n                if (tok_id == '[' || tok_id == '{'\n                    || curr_lexer->previous_token_is_binop ())\n                  {\n                    curr_lexer->m_filepos.increment_column ();\n                    curr_lexer->begin_string (SQ_STRING_START);\n                  }\n                else\n                  {\n                    yyless (0);\n                    curr_lexer->xunput (',');\n                  }\n              }\n            else\n              {\n                if (tok_id == '[' || tok_id == '{'\n                    || curr_lexer->previous_token_is_binop ()\n                    || curr_lexer->previous_token_is_keyword ())\n                  {\n                    curr_lexer->m_filepos.increment_column ();\n                    curr_lexer->begin_string (SQ_STRING_START);\n                  }\n                else\n                  {\n                    curr_lexer->m_filepos.increment_column ();\n                    return curr_lexer->handle_token (HERMITIAN);\n                  }\n              }\n          }\n        else\n          {\n            if (! tok_id || tok_id == '[' || tok_id == '{' || tok_id == '('\n                || curr_lexer->previous_token_is_binop ()\n                || curr_lexer->previous_token_is_keyword ())\n              {\n                curr_lexer->m_filepos.increment_column ();\n                curr_lexer->begin_string (SQ_STRING_START);\n              }\n            else\n              {\n                curr_lexer->m_filepos.increment_column ();\n                return curr_lexer->handle_token (HERMITIAN);\n              }\n          }\n      }\n  }\n\n%{\n// Double quotes always begin strings.\n%}\n\n\\\" {\n    curr_lexer->lexer_debug (\"\\\\\\\"\");\n\n    if (curr_lexer->previous_token_may_be_command ()\n        &&  curr_lexer->space_follows_previous_token ())\n      {\n        curr_lexer->m_filepos.increment_column ();\n        curr_lexer->push_start_state (COMMAND_START);\n        curr_lexer->begin_string (DQ_STRING_START);\n      }\n    else\n      {\n        int tok_id = curr_lexer->previous_token_id ();\n\n        if (curr_lexer->whitespace_is_significant ())\n          {\n            if (curr_lexer->space_follows_previous_token ())\n              {\n                if (tok_id == '[' || tok_id == '{'\n                    || curr_lexer->previous_token_is_binop ())\n                  {\n                    curr_lexer->m_filepos.increment_column ();\n                    curr_lexer->begin_string (DQ_STRING_START);\n                  }\n                else\n                  {\n                    yyless (0);\n                    curr_lexer->xunput (',');\n                  }\n              }\n            else\n              {\n                curr_lexer->m_filepos.increment_column ();\n                curr_lexer->begin_string (DQ_STRING_START);\n              }\n          }\n        else\n          {\n            curr_lexer->m_filepos.increment_column ();\n            curr_lexer->begin_string (DQ_STRING_START);\n          }\n      }\n  }\n\n%{\n// Other operators.\n%}\n\n\":\"   { CMD_OR_OP (\":\", ':', true); }\n\".*\"  { CMD_OR_OP (\".*\", EMUL, true); }\n\"./\"  { CMD_OR_OP (\"./\", EDIV, true); }\n\".\\\\\" { CMD_OR_OP (\".\\\\\", ELEFTDIV, true); }\n\".^\"  { CMD_OR_OP (\".^\", EPOW, true); }\n\"<=\"  { CMD_OR_OP (\"<=\", EXPR_LE, true); }\n\"==\"  { CMD_OR_OP (\"==\", EXPR_EQ, true); }\n\"!=\"  { CMD_OR_OP (\"!=\", EXPR_NE, false); }\n\"~=\"  { CMD_OR_OP (\"~=\", EXPR_NE, true); }\n\">=\"  { CMD_OR_OP (\">=\", EXPR_GE, true); }\n\"&\"   { CMD_OR_OP (\"&\", EXPR_AND, true); }\n\"|\"   { CMD_OR_OP (\"|\", EXPR_OR, true); }\n\"<\"   { CMD_OR_OP (\"<\", EXPR_LT, true); }\n\">\"   { CMD_OR_OP (\">\", EXPR_GT, true); }\n\"*\"   { CMD_OR_OP (\"*\", '*', true); }\n\"/\"   { CMD_OR_OP (\"/\", '/', true); }\n\n%{\n// In Matlab, '\\' may also trigger command syntax.\n%}\n\n\"\\\\\" {\n    // FIXME: After backslash is no longer handled as a line\n    // continuation marker outside of character strings, this\n    // action may be replaced with\n    //\n    //   CMD_OR_OP (\"\\\\\", LEFTDIV, true);\n\n    curr_lexer->lexer_debug (\"\\\\\");\n\n    return curr_lexer->handle_op (LEFTDIV, yytext, yyleng);\n  }\n\n\"^\"   { CMD_OR_OP (\"^\", POW, true); }\n\"&&\"  { CMD_OR_OP (\"&&\", EXPR_AND_AND, true); }\n\"||\"  { CMD_OR_OP (\"||\", EXPR_OR_OR, true); }\n\n\";\" {\n    curr_lexer->lexer_debug (\";\");\n\n    bool at_beginning_of_statement\n      = (! (curr_lexer->whitespace_is_significant ()\n            || curr_lexer->m_looking_at_object_index.front ()));\n\n    return curr_lexer->handle_op (';', yytext, yyleng, at_beginning_of_statement);\n  }\n\n\"+\" { CMD_OR_UNARY_OP (\"+\", '+', true); }\n\"-\" { CMD_OR_UNARY_OP (\"-\", '-', true); }\n\n\"~\" { CMD_OR_UNARY_OP (\"~\", '~', true); }\n\"!\" { CMD_OR_UNARY_OP (\"!\", '!', false); }\n\n\",\" {\n    curr_lexer->lexer_debug (\",\");\n\n    bool at_beginning_of_statement\n      = (! (curr_lexer->whitespace_is_significant ()\n            || curr_lexer->m_looking_at_object_index.front ()));\n\n    return curr_lexer->handle_op (',', yytext, yyleng, at_beginning_of_statement);\n  }\n\n\".'\" {\n    curr_lexer->lexer_debug (\".'\");\n\n    return curr_lexer->handle_op (TRANSPOSE, yytext, yyleng);\n  }\n\n\"++\" { CMD_OR_UNARY_OP (\"++\", PLUS_PLUS, false); }\n\"--\" { CMD_OR_UNARY_OP (\"--\", MINUS_MINUS, false); }\n\n\"(\" {\n    curr_lexer->lexer_debug (\"(\");\n\n    bool unput_comma = false;\n\n    if (curr_lexer->whitespace_is_significant ()\n        && curr_lexer->space_follows_previous_token ())\n      {\n        int tok_id = curr_lexer->previous_token_id ();\n\n        if (! (tok_id == '[' || tok_id == '{'\n               || curr_lexer->previous_token_is_binop ()))\n          unput_comma = true;\n      }\n\n    if (unput_comma)\n      {\n        yyless (0);\n        curr_lexer->xunput (',');\n      }\n    else\n      {\n        curr_lexer->update_token_positions (yyleng);\n\n        // If we are looking for an object index, then push TRUE for\n        // m_looking_at_object_index.  Otherwise, just push whatever state\n        // is current (so that we can pop it off the stack when we find\n        // the matching close paren).\n\n        curr_lexer->m_looking_at_object_index.push_front\n          (curr_lexer->m_looking_for_object_index);\n\n        curr_lexer->m_looking_at_indirect_ref = false;\n        curr_lexer->m_looking_for_object_index = false;\n        curr_lexer->m_at_beginning_of_statement = false;\n\n        curr_lexer->m_nesting_level.paren ();\n\n        return curr_lexer->handle_token ('(');\n      }\n  }\n\n\")\" {\n    curr_lexer->lexer_debug (\")\");\n\n    curr_lexer->update_token_positions (yyleng);\n\n    curr_lexer->m_nesting_level.remove ();\n\n    curr_lexer->m_looking_at_object_index.pop_front ();\n\n    curr_lexer->m_looking_for_object_index = true;\n    curr_lexer->m_at_beginning_of_statement = false;\n\n    if (curr_lexer->m_looking_at_anon_fcn_args)\n      {\n        curr_lexer->m_looking_at_anon_fcn_args = false;\n        curr_lexer->m_nesting_level.anon_fcn_body ();\n      }\n\n    return curr_lexer->handle_token (')');\n  }\n\n\".\" {\n    curr_lexer->lexer_debug (\".\");\n\n    if (curr_lexer->previous_token_may_be_command ()\n        && curr_lexer->space_follows_previous_token ())\n      {\n        yyless (0);\n        curr_lexer->push_start_state (COMMAND_START);\n      }\n    else\n      {\n        curr_lexer->update_token_positions (yyleng);\n\n        curr_lexer->m_looking_for_object_index = false;\n        curr_lexer->m_at_beginning_of_statement = false;\n\n        return curr_lexer->handle_token ('.');\n      }\n  }\n\n%{\n// = and op= operators.\n%}\n\n\"=\" {\n    curr_lexer->lexer_debug (\"=\");\n\n    return curr_lexer->handle_op ('=', yytext, yyleng);\n  }\n\n\"+=\"   { CMD_OR_OP (\"+=\", ADD_EQ, false); }\n\"-=\"   { CMD_OR_OP (\"-=\", SUB_EQ, false); }\n\"*=\"   { CMD_OR_OP (\"*=\", MUL_EQ, false); }\n\"/=\"   { CMD_OR_OP (\"/=\", DIV_EQ, false); }\n\"\\\\=\"  { CMD_OR_OP (\"\\\\=\", LEFTDIV_EQ, false); }\n\".*=\"  { CMD_OR_OP (\".*=\", EMUL_EQ, false); }\n\"./=\"  { CMD_OR_OP (\"./=\", EDIV_EQ, false); }\n\".\\\\=\" { CMD_OR_OP (\".\\\\=\", ELEFTDIV_EQ, false); }\n\"^=\"   { CMD_OR_OP (\"^=\", POW_EQ, false); }\n\".^=\"  { CMD_OR_OP (\".^=\", EPOW_EQ, false); }\n\"&=\"   { CMD_OR_OP (\"&=\", AND_EQ, false); }\n\"|=\"   { CMD_OR_OP (\"|=\", OR_EQ, false); }\n\n%{\n// In Matlab, '{' may also trigger command syntax.\n%}\n\n\"{\" {\n    curr_lexer->lexer_debug (\"{\");\n\n    bool unput_comma = false;\n\n    if (curr_lexer->whitespace_is_significant ()\n        && curr_lexer->space_follows_previous_token ())\n      {\n        int tok_id = curr_lexer->previous_token_id ();\n\n        if (! (tok_id == '[' || tok_id == '{'\n               || curr_lexer->previous_token_is_binop ()))\n          unput_comma = true;\n      }\n\n    if (unput_comma)\n      {\n        yyless (0);\n        curr_lexer->xunput (',');\n      }\n    else\n      {\n        curr_lexer->m_nesting_level.brace ();\n\n        curr_lexer->m_looking_at_object_index.push_front\n          (curr_lexer->m_looking_for_object_index);\n\n        curr_lexer->m_filepos.increment_column (yyleng);\n        curr_lexer->m_looking_for_object_index = false;\n        curr_lexer->m_at_beginning_of_statement = false;\n\n        curr_lexer->m_braceflag++;\n\n        curr_lexer->push_start_state (MATRIX_START);\n\n        return curr_lexer->handle_token ('{');\n      }\n  }\n\n\"}\" {\n    curr_lexer->lexer_debug (\"}\");\n\n    curr_lexer->update_token_positions (yyleng);\n\n    curr_lexer->m_looking_at_object_index.pop_front ();\n\n    curr_lexer->m_looking_for_object_index = true;\n    curr_lexer->m_at_beginning_of_statement = false;\n\n    curr_lexer->m_nesting_level.remove ();\n\n    return curr_lexer->handle_token ('}');\n  }\n\n%{\n// Unrecognized input.  If the previous token may be a command and is\n// followed by a space, parse the remainder of this statement as a\n// command-style function call.  Otherwise, unrecognized input is a\n// lexical error.\n%}\n\n. {\n    curr_lexer->lexer_debug (\".\");\n\n    // Check for possible command syntax before doing any other operations\n    // that may modify the input buffer.\n\n    if (curr_lexer->previous_token_may_be_command ()\n        && curr_lexer->space_follows_previous_token ())\n      {\n        yyless (0);\n        curr_lexer->push_start_state (COMMAND_START);\n      }\n    else\n      {\n        curr_lexer->xunput (yytext[0]);\n\n        int c = curr_lexer->text_yyinput ();\n\n        if (c == 1)\n          return -1;\n        else if (c == EOF)\n          return curr_lexer->handle_end_of_input ();\n        else\n          {\n            std::ostringstream buf;\n\n            buf << \"invalid character '\"\n                << octave::undo_string_escape (static_cast<char> (c))\n                << \"' (ASCII \" << c << \")\";\n\n            curr_lexer->update_token_positions (yyleng);\n\n            return curr_lexer->syntax_error (buf.str ());\n          }\n      }\n  }\n\n%{\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // Disable these warnings for flex code.\n#  pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#  pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#endif\n%}\n\n%%\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // Restore prevailing warning state for remainder of the file.\n#  pragma GCC diagnostic pop\n#endif\n\nvoid *\noctave_alloc (yy_size_t size, yyscan_t)\n{\n  return std::malloc (size);\n}\n\nvoid *\noctave_realloc (void *ptr, yy_size_t size, yyscan_t)\n{\n  return std::realloc (ptr, size);\n}\n\nvoid\noctave_free (void *ptr, yyscan_t)\n{\n  std::free (ptr);\n}\n\n#if defined (OCTAVE_PARSER_DEBUG)\nstatic void\ndisplay_character (char c)\n{\n  if (isgraph (c))\n    std::cerr << c;\n  else\n    switch (c)\n      {\n      case 0:\n        std::cerr << \"NUL\";\n        break;\n\n      case 1:\n        std::cerr << \"SOH\";\n        break;\n\n      case 2:\n        std::cerr << \"STX\";\n        break;\n\n      case 3:\n        std::cerr << \"ETX\";\n        break;\n\n      case 4:\n        std::cerr << \"EOT\";\n        break;\n\n      case 5:\n        std::cerr << \"ENQ\";\n        break;\n\n      case 6:\n        std::cerr << \"ACK\";\n        break;\n\n      case 7:\n        std::cerr << \"\\\\a\";\n        break;\n\n      case 8:\n        std::cerr << \"\\\\b\";\n        break;\n\n      case 9:\n        std::cerr << \"\\\\t\";\n        break;\n\n      case 10:\n        std::cerr << \"\\\\n\";\n        break;\n\n      case 11:\n        std::cerr << \"\\\\v\";\n        break;\n\n      case 12:\n        std::cerr << \"\\\\f\";\n        break;\n\n      case 13:\n        std::cerr << \"\\\\r\";\n        break;\n\n      case 14:\n        std::cerr << \"SO\";\n        break;\n\n      case 15:\n        std::cerr << \"SI\";\n        break;\n\n      case 16:\n        std::cerr << \"DLE\";\n        break;\n\n      case 17:\n        std::cerr << \"DC1\";\n        break;\n\n      case 18:\n        std::cerr << \"DC2\";\n        break;\n\n      case 19:\n        std::cerr << \"DC3\";\n        break;\n\n      case 20:\n        std::cerr << \"DC4\";\n        break;\n\n      case 21:\n        std::cerr << \"NAK\";\n        break;\n\n      case 22:\n        std::cerr << \"SYN\";\n        break;\n\n      case 23:\n        std::cerr << \"ETB\";\n        break;\n\n      case 24:\n        std::cerr << \"CAN\";\n        break;\n\n      case 25:\n        std::cerr << \"EM\";\n        break;\n\n      case 26:\n        std::cerr << \"SUB\";\n        break;\n\n      case 27:\n        std::cerr << \"ESC\";\n        break;\n\n      case 28:\n        std::cerr << \"FS\";\n        break;\n\n      case 29:\n        std::cerr << \"GS\";\n        break;\n\n      case 30:\n        std::cerr << \"RS\";\n        break;\n\n      case 31:\n        std::cerr << \"US\";\n        break;\n\n      case 32:\n        std::cerr << \"SPACE\";\n        break;\n\n      case 127:\n        std::cerr << \"DEL\";\n        break;\n      }\n}\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (OCTAVE_PARSER_DEBUG)\nstatic bool V__lexer_debug_flag__ = false;\nstatic bool V__display_tokens__ = false;\nstatic std::size_t V__token_count__ = 0;\n#endif\n\nDEFUN (iskeyword, args, ,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{tf} =} iskeyword (@var{name})\n@deftypefnx {} {@var{keyword_list} =} iskeyword ()\nReturn true if @var{name} is an Octave keyword.\n\nIf @var{name} is omitted, return a list of keywords.\n@seealso{isvarname, exist}\n@end deftypefn */)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  if (nargin == 0)\n    {\n      // Neither set nor get are keywords.  See the note in the\n      // iskeyword function for additional details.\n\n      string_vector lst (TOTAL_KEYWORDS);\n\n      int j = 0;\n\n      for (int i = 0; i < TOTAL_KEYWORDS; i++)\n        {\n          std::string kword = wordlist[i].name;\n\n          // FIXME: The following check is duplicated in iskeyword.\n          if (! (kword == \"set\" || kword == \"get\" || kword == \"arguments\"\n                 || kword == \"enumeration\" || kword == \"events\"\n                 || kword == \"methods\" || kword == \"properties\"))\n            lst[j++] = kword;\n        }\n\n      lst.resize (j);\n\n      retval = Cell (lst.sort ());\n    }\n  else\n    {\n      std::string name = args(0).xstring_value (\"iskeyword: NAME must be a string\");\n      retval = iskeyword (name);\n    }\n\n  return retval;\n}\n\n/*\n\n%!assert (iskeyword (\"for\"))\n%!assert (iskeyword (\"fort\"), false)\n%!assert (iskeyword (\"fft\"), false)\n%!assert (iskeyword (\"get\"), false)\n%!assert (iskeyword (\"set\"), false)\n\n%!error <Invalid call> iskeyword (\"A\", \"B\")\n%!error <NAME must be a string> iskeyword (1)\n\n*/\n\nDEFUN (__lexer_debug_flag__, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} __lexer_debug_flag__ ()\n@deftypefnx {} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val})\n@deftypefnx {} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val}, \"local\")\nQuery or set the internal flag that determines whether Octave's lexer prints\ndebug information as it processes an expression.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{__display_tokens__, __token_count__, __parser_debug_flag__}\n@end deftypefn */)\n{\n#if defined (OCTAVE_PARSER_DEBUG)\n  return set_internal_variable (V__lexer_debug_flag__, args, nargout,\n                                \"__lexer_debug_flag__\");\n#else\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  error (\"__lexer_debug_flag__: support for debugging the lexer was disabled when Octave was built\");\n#endif\n}\n\nDEFUN (__display_tokens__, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} __display_tokens__ ()\n@deftypefnx {} {@var{old_val} =} __display_tokens__ (@var{new_val})\n@deftypefnx {} {@var{old_val} =} __display_tokens__ (@var{new_val}, \"local\")\nQuery or set the internal variable that determines whether Octave's\nlexer displays tokens as they are read.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{__token_count__, __lexer_debug_flag__, __parser_debug_flag__}\n@end deftypefn */)\n{\n#if defined (OCTAVE_PARSER_DEBUG)\n  return set_internal_variable (V__display_tokens__, args, nargout,\n                                \"__display_tokens__\");\n#else\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  error (\"__display_tokens__: support for debugging the lexer was disabled when Octave was built\");\n#endif\n}\n\nDEFUN (__token_count__, , ,\n       doc: /* -*- texinfo -*-\n@deftypefn {} {@var{n} =} __token_count__ ()\nReturn the number of language tokens processed since Octave startup.\n@seealso{__display_tokens__, __lexer_debug_flag__, __parser_debug_flag__}\n@end deftypefn */)\n{\n#if defined (OCTAVE_PARSER_DEBUG)\n  return octave_value (V__token_count__);\n#else\n  error (\"__token_count__: support for debugging the lexer was disabled when Octave was built\");\n#endif\n}\n\nvoid\nlexical_feedback::symbol_table_context::clear ()\n{\n  while (! m_frame_stack.empty ())\n    m_frame_stack.pop_front ();\n}\n\nvoid\nlexical_feedback::symbol_table_context::pop ()\n{\n  if (empty ())\n    error (\"unexpected: empty stack in lexical_feedback::symbol_table_context::pop - please report this bug\");\n\n  m_frame_stack.pop_front ();\n}\n\nsymbol_scope\nlexical_feedback::symbol_table_context::curr_scope () const\n{\n  if (empty ())\n    return m_interpreter.get_current_scope ();\n  else\n    return m_frame_stack.front ();\n}\n\nsymbol_scope\nlexical_feedback::symbol_table_context::parent_scope () const\n{\n  std::size_t sz = size ();\n\n  return (sz > 1\n          ? m_frame_stack[1]\n          : (sz == 1 ? m_frame_stack[0] : symbol_scope::invalid ()));\n}\n\nlexical_feedback::~lexical_feedback ()\n{\n  m_tokens.clear ();\n}\n\nvoid\nlexical_feedback::init ()\n{\n  // The closest paren, brace, or bracket nesting is not an object index.\n  m_looking_at_object_index.push_front (false);\n}\n\nvoid\nlexical_feedback::reset ()\n{\n  m_end_of_input = false;\n  m_allow_command_syntax = true;\n  m_at_beginning_of_statement = true;\n  m_looking_at_anon_fcn_args = false;\n  m_looking_at_return_list = false;\n  m_looking_at_parameter_list = false;\n  m_looking_at_decl_list = false;\n  m_looking_at_matrix_or_assign_lhs = false;\n  m_looking_for_object_index = false;\n  m_looking_at_indirect_ref = false;\n  m_arguments_is_keyword = false;\n  m_classdef_element_names_are_keywords = false;\n  m_parsing_anon_fcn_body = false;\n  m_parsing_class_method = false;\n  m_parsing_classdef = false;\n  m_parsing_classdef_decl = false;\n  m_parsing_classdef_superclass = false;\n  m_maybe_classdef_get_set_method = false;\n  m_parsing_classdef_get_method = false;\n  m_parsing_classdef_set_method = false;\n  m_quote_is_transpose = false;\n  m_force_script = false;\n  m_reading_fcn_file = false;\n  m_reading_script_file = false;\n  m_reading_classdef_file = false;\n  m_buffer_function_text = false;\n  m_comment_uses_hash_char = false;\n  m_bracketflag = 0;\n  m_braceflag = 0;\n  m_looping = 0;\n  m_defining_fcn = 0;\n  m_looking_at_function_handle = 0;\n  m_block_comment_nesting_level = 0;\n  m_command_arg_paren_count = 0;\n  m_token_count = 0;\n  m_filepos = filepos (1, 1);\n  m_tok_beg = filepos ();\n  m_tok_end = filepos ();\n  m_string_text = \"\";\n  m_current_input_line = \"\";\n  m_comment_text = \"\";\n  m_function_text = \"\";\n  m_fcn_file_name = \"\";\n  m_fcn_file_full_name = \"\";\n  m_dir_name = \"\";\n  m_package_name = \"\";\n  m_looking_at_object_index.clear ();\n  m_looking_at_object_index.push_front (false);\n\n  while (! m_parsed_function_name.empty ())\n    m_parsed_function_name.pop ();\n\n  m_symtab_context.clear ();\n  m_nesting_level.reset ();\n  m_tokens.clear ();\n}\n\ntoken *\nlexical_feedback::previous_token ()\n{\n  return m_tokens.front ();\n}\n\nconst token *\nlexical_feedback::previous_token () const\n{\n  return m_tokens.front ();\n}\n\nint\nlexical_feedback::previous_token_id () const\n{\n  const token *prev_tok = previous_token ();\n  return prev_tok ? prev_tok->token_id () : 0;\n}\n\nbool\nlexical_feedback::previous_token_is (int tok_id) const\n{\n  const token *prev_tok = previous_token ();\n  return prev_tok ? prev_tok->token_is (tok_id) : false;\n}\n\nbool\nlexical_feedback::previous_token_is (const token *tok) const\n{\n  const token *prev_tok = previous_token ();\n  return prev_tok ? prev_tok->token_is (tok) : false;\n}\n\nvoid\nlexical_feedback::mark_previous_token_trailing_space ()\n{\n  token *prev_tok = previous_token ();\n  if (prev_tok && ! previous_token_is ('\\n'))\n    prev_tok->mark_trailing_space ();\n}\n\nbool\nlexical_feedback::space_follows_previous_token () const\n{\n  const token *prev_tok = previous_token ();\n  return prev_tok ? prev_tok->space_follows_token () : false;\n}\n\nbool\nlexical_feedback::previous_token_is_binop () const\n{\n  int tok_id = previous_token_id ();\n\n  return (tok_id == '+' || tok_id == '-' || tok_id == '@' || tok_id == '~' || tok_id == '!'\n          || tok_id == ',' || tok_id == ';' || tok_id == '*' || tok_id == '/'\n          || tok_id == ':' || tok_id == '=' || tok_id == ADD_EQ\n          || tok_id == AND_EQ || tok_id == DIV_EQ || tok_id == EDIV\n          || tok_id == EDIV_EQ || tok_id == ELEFTDIV || tok_id == ELEFTDIV_EQ\n          || tok_id == EMUL || tok_id == EMUL_EQ\n          || tok_id == EPOW || tok_id == EPOW_EQ || tok_id == EXPR_AND\n          || tok_id == EXPR_AND_AND || tok_id == EXPR_EQ || tok_id == EXPR_GE\n          || tok_id == EXPR_GT || tok_id == EXPR_LE || tok_id == EXPR_LT\n          || tok_id == EXPR_NE || tok_id == EXPR_OR\n          || tok_id == EXPR_OR_OR || tok_id == LEFTDIV || tok_id == LEFTDIV_EQ\n          || tok_id == MUL_EQ || tok_id == OR_EQ || tok_id == POW\n          || tok_id == POW_EQ || tok_id == SUB_EQ);\n}\n\nbool\nlexical_feedback::previous_token_is_keyword () const\n{\n  const token *prev_tok = previous_token ();\n  return prev_tok ? prev_tok->iskeyword () : false;\n}\n\nvoid\nlexical_feedback::mark_as_variable (const std::string& nm)\n{\n  symbol_scope scope = m_symtab_context.curr_scope ();\n\n  if (scope)\n    scope.mark_as_variable (nm);\n}\n\nvoid\nlexical_feedback::mark_as_variables (const std::list<std::string>& lst)\n{\n  symbol_scope scope = m_symtab_context.curr_scope ();\n\n  if (scope)\n    scope.mark_as_variables (lst);\n}\n\nbool\nlexical_feedback::previous_token_may_be_command () const\n{\n  if (! m_allow_command_syntax)\n    return false;\n\n  const token *prev_tok = previous_token ();\n  return prev_tok ? prev_tok->may_be_command () : false;\n  }\n\nstatic bool\nlooks_like_copyright (const std::string& s)\n{\n  if (s.empty ())\n    return false;\n\n  // Comment characters have been stripped but whitespace\n  // (including newlines) remains.\n\n  std::size_t offset = s.find_first_not_of (\" \\t\\n\\r\");\n\n  return (offset != std::string::npos\n          && (s.substr (offset, 9) == \"Copyright\"\n              || s.substr (offset, 6) == \"Author\"\n              || s.substr (offset, 23) == \"SPDX-License-Identifier\"));\n}\n\n// FIXME: This function does not appear to be used anywhere in Octave code.\nstatic bool\nlooks_like_shebang (const std::string& s)\n{\n  return ((! s.empty ()) && (s[0] == '!'));\n}\n\nvoid\nbase_lexer::input_buffer::fill (const std::string& input, bool eof_arg)\n{\n  m_buffer = input;\n  m_chars_left = m_buffer.length ();\n  m_offset = 0;\n  m_eof = eof_arg;\n}\n\n// If BY_LINES is true, return chunks to the lexer line by line.\nint\nbase_lexer::input_buffer::copy_chunk (char *buf, std::size_t max_size,\n                                      bool by_lines)\n{\n  static const char * const eol = \"\\n\";\n\n  std::size_t len = 0;\n  if (by_lines)\n    {\n      std::size_t newline_pos = m_buffer.find ('\\n', m_offset);\n      len = (newline_pos != std::string::npos\n             ? newline_pos - m_offset + 1\n             : (max_size > m_chars_left ? m_chars_left : max_size));\n    }\n  else\n    len = max_size > m_chars_left ? m_chars_left : max_size;\n\n  if (len <= 0)\n    error (\"unexpected: buffer underflow in base_lexer::input_buffer::copy_chunk - please report this bug\");\n\n  memcpy (buf, m_buffer.c_str () + m_offset, len);\n\n  m_chars_left -= len;\n  m_offset += len;\n\n  // Make sure the final input returned to the lexer ends with a new\n  // line character.\n\n  if (m_chars_left == 0 && buf[len-1] != '\\n')\n    {\n      if (len < max_size)\n        {\n          // There is enough room to plug the newline character in\n          // the buffer.\n          buf[len++] = '\\n';\n        }\n      else\n        {\n          // There isn't enough room to plug the newline character\n          // in BUF so arrange to have it returned on the next call\n          // to base_lexer::read.\n\n          // At this point we've exhausted the original input\n          // (m_chars_left is zero) so we can overwrite the initial\n          // buffer with a single newline character to be returned on\n          // the next call.\n\n          m_buffer = eol;\n          m_chars_left = 1;\n          m_offset = 0;\n        }\n    }\n\n  return len;\n}\n\nbase_lexer::~base_lexer ()\n{\n  yylex_destroy (m_scanner);\n}\n\nvoid\nbase_lexer::init ()\n{\n  yylex_init (&m_scanner);\n\n  // Make base_lexer object available through yyextra in\n  // flex-generated lexer.\n  yyset_extra (this, m_scanner);\n\n  clear_start_state ();\n}\n\n// Inside Flex-generated functions, yyg is the scanner cast to its real\n// type.  Some flex macros that we use in base_lexer member functions\n// (for example, BEGIN) use yyg.  If we could perform the actions of\n// these macros with functions instead, we could eliminate the\n  // OCTAVE_YYG macro.\n\n#define OCTAVE_YYG                                                      \\\n  struct yyguts_t *yyg = static_cast<struct yyguts_t*> (m_scanner)\n\nvoid\nbase_lexer::reset ()\n{\n  // Start off on the right foot.\n  clear_start_state ();\n\n  m_symtab_context.clear ();\n\n  // Only ask for input from stdin if we are expecting interactive\n  // input.\n\n  if (m_interpreter.interactive ()\n      && ! (m_reading_fcn_file\n            || m_reading_classdef_file\n            || m_reading_script_file\n            || input_from_eval_string ()))\n    yyrestart (stdin, m_scanner);\n\n  lexical_feedback::reset ();\n\n  m_comment_list.clear ();\n}\n\nvoid\nbase_lexer::prep_for_file ()\n{\n  m_reading_script_file = true;\n\n  push_start_state (INPUT_FILE_START);\n}\n\nvoid\nbase_lexer::begin_string (int state)\n{\n  m_tok_beg = m_filepos;\n\n  push_start_state (state);\n}\n\nint\nbase_lexer::handle_end_of_input ()\n{\n  lexer_debug (\"<<EOF>>\");\n\n  m_tok_beg = m_filepos;\n  m_tok_end = m_filepos;\n\n  if (m_block_comment_nesting_level != 0)\n    {\n      std::string msg {\"block comment unterminated at end of input\"};\n\n      if ((m_reading_fcn_file || m_reading_script_file || m_reading_classdef_file)\n          && ! m_fcn_file_name.empty ())\n        msg += \" near line \" + std::to_string (m_filepos.line () - 1) + \" of file '\" + m_fcn_file_name + \".m'\";\n\n      syntax_error (msg);\n    }\n\n  token *tok = new token (END_OF_INPUT, m_tok_beg, m_tok_end, get_comment_list ());\n\n  return handle_token (tok);\n}\n\nchar *\nbase_lexer::flex_yytext ()\n{\n  return yyget_text (m_scanner);\n}\n\nint\nbase_lexer::flex_yyleng ()\n{\n  return yyget_leng (m_scanner);\n}\n\nint\nbase_lexer::text_yyinput ()\n{\n  int c = yyinput (m_scanner);\n\n#if defined (OCTAVE_PARSER_DEBUG)\n  if (V__lexer_debug_flag__)\n    {\n      std::cerr << \"I: \";\n      display_character (c);\n      std::cerr << std::endl;\n    }\n#endif\n\n  // Convert CRLF into just LF and single CR into LF.\n  if (c == '\\r')\n    {\n      c = yyinput (m_scanner);\n\n#if defined (OCTAVE_PARSER_DEBUG)\n      if (V__lexer_debug_flag__)\n        {\n          std::cerr << \"I: \";\n          display_character (c);\n          std::cerr << std::endl;\n        }\n#endif\n\n      if (c != '\\n')\n        {\n          xunput (c);\n          c = '\\n';\n        }\n    }\n\n  return c;\n}\n\nvoid\nbase_lexer::xunput (char c, char *buf)\n{\n  if (c != EOF)\n    {\n#if defined (OCTAVE_PARSER_DEBUG)\n      if (V__lexer_debug_flag__)\n        {\n          std::cerr << \"U: \";\n          display_character (c);\n          std::cerr << std::endl;\n        }\n#endif\n      yyunput (c, buf, m_scanner);\n    }\n}\n\nvoid\nbase_lexer::xunput (char c)\n{\n  char *yytxt = flex_yytext ();\n\n  xunput (c, yytxt);\n}\n\nvoid\nbase_lexer::update_token_positions (int tok_len)\n{\n  m_tok_beg = m_filepos;\n  m_tok_end = m_filepos;\n\n  if (tok_len > 1)\n    m_tok_end.increment_column (tok_len - 1);\n\n  m_filepos.increment_column (tok_len);\n}\n\nbool\nbase_lexer::looking_at_space ()\n{\n  int c = text_yyinput ();\n  xunput (c);\n  return is_space_or_tab (c);\n}\n\nbool\nbase_lexer::inside_any_object_index ()\n{\n  bool retval = false;\n\n  for (const bool is_obj_idx : m_looking_at_object_index)\n    {\n      if (is_obj_idx)\n        {\n          retval = true;\n          break;\n        }\n    }\n\n  return retval;\n}\n\ntoken *\nbase_lexer::make_keyword_token (const std::string& s)\n{\n  // Token positions should have already been updated before this\n  // function is called.\n\n  int slen = s.length ();\n\n  const octave_kw *kw = octave_kw_hash::in_word_set (s.c_str (), slen);\n\n  if (! kw)\n    return nullptr;\n\n  bool previous_at_bos = m_at_beginning_of_statement;\n\n  // May be reset to true for some token types.\n  m_at_beginning_of_statement = false;\n\n  token *tok = nullptr;\n\n  switch (kw->kw_id)\n    {\n    case break_kw:\n    case catch_kw:\n    case continue_kw:\n    case else_kw:\n    case otherwise_kw:\n    case return_kw:\n    case unwind_protect_cleanup_kw:\n      m_at_beginning_of_statement = true;\n      break;\n\n    case persistent_kw:\n    case global_kw:\n      m_looking_at_decl_list = true;\n      break;\n\n    case case_kw:\n    case elseif_kw:\n    case until_kw:\n      break;\n\n    case end_kw:\n      if (inside_any_object_index ()\n          || (m_defining_fcn\n              && ! (m_looking_at_return_list\n                    || m_parsed_function_name.top ())))\n        {\n          m_at_beginning_of_statement = previous_at_bos;\n          return nullptr;\n        }\n\n      tok = new token (kw->tok_id, token::simple_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case end_try_catch_kw:\n      tok = new token (kw->tok_id, token::try_catch_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case end_unwind_protect_kw:\n      tok = new token (kw->tok_id, token::unwind_protect_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endfor_kw:\n      tok = new token (kw->tok_id, token::for_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endfunction_kw:\n      tok = new token (kw->tok_id, token::function_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endif_kw:\n      tok = new token (kw->tok_id, token::if_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endparfor_kw:\n      tok = new token (kw->tok_id, token::parfor_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endswitch_kw:\n      tok = new token (kw->tok_id, token::switch_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endwhile_kw:\n      tok = new token (kw->tok_id, token::while_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endarguments_kw:\n#if defined (DISABLE_ARGUMENTS_VALIDATION_BLOCK)\n      return nullptr;\n#else\n      tok = new token (kw->tok_id, token::arguments_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n#endif\n\n    case endclassdef_kw:\n      tok = new token (kw->tok_id, token::classdef_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endenumeration_kw:\n      tok = new token (kw->tok_id, token::enumeration_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endevents_kw:\n      tok = new token (kw->tok_id, token::events_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endmethods_kw:\n      tok = new token (kw->tok_id, token::methods_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endproperties_kw:\n      tok = new token (kw->tok_id, token::properties_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case for_kw:\n    case parfor_kw:\n    case while_kw:\n      m_looping++;\n      break;\n\n    case do_kw:\n      m_at_beginning_of_statement = true;\n      m_looping++;\n      break;\n\n    case try_kw:\n    case unwind_protect_kw:\n      m_at_beginning_of_statement = true;\n      break;\n\n    case if_kw:\n    case switch_kw:\n      break;\n\n    case get_kw:\n    case set_kw:\n      // 'get' and 'set' are keywords in classdef method declarations.\n      if (! m_maybe_classdef_get_set_method)\n        {\n          m_at_beginning_of_statement = previous_at_bos;\n          return nullptr;\n        }\n      break;\n\n    case enumeration_kw:\n    case events_kw:\n    case methods_kw:\n    case properties_kw:\n      // 'properties', 'methods' and 'events' are keywords for\n      // classdef blocks.\n      if (! m_classdef_element_names_are_keywords)\n        {\n          m_at_beginning_of_statement = previous_at_bos;\n          return nullptr;\n        }\n      // fall through ...\n\n    case classdef_kw:\n      // 'classdef' is always a keyword.\n      if (! m_force_script && m_token_count == 0 && input_from_file ())\n        {\n          m_reading_classdef_file = true;\n          m_reading_script_file = false;\n        }\n      break;\n\n    case function_kw:\n      m_defining_fcn++;\n      m_parsed_function_name.push (false);\n\n      if (! m_force_script && m_token_count == 0 && input_from_file ())\n        {\n          m_reading_fcn_file = true;\n          m_reading_script_file = false;\n        }\n\n      // FIXME: should we be asking directly whether input is coming from an\n      // eval string instead of that it is not coming from a file?\n      if (! (m_reading_fcn_file || m_reading_script_file\n             || m_reading_classdef_file))\n        {\n          // Input must be coming from the terminal or stdin?\n          m_buffer_function_text = true;\n          m_function_text += (m_current_input_line + \"\\n\");\n\n          // FIXME: do we need to save and restore the file position\n          // or just reset the line number here?  The goal is to\n          // track line info for command-line functions relative\n          // to the function keyword.  Should we really be setting\n          // the line and column info to (1, 1) here?\n\n          m_filepos = filepos (1, 1);\n          update_token_positions (slen);\n        }\n      break;\n\n    case arguments_kw:\n#if defined (DISABLE_ARGUMENTS_VALIDATION_BLOCK)\n      return nullptr;\n#else\n      if (! m_arguments_is_keyword)\n        return nullptr;\n      break;\n#endif\n\n    case spmd_kw:\n      m_at_beginning_of_statement = true;\n      break;\n\n    case endspmd_kw:\n      tok = new token (kw->tok_id, token::spmd_end, m_tok_beg, m_tok_end, get_comment_list ());\n      m_at_beginning_of_statement = true;\n      break;\n\n    case magic_file_kw:\n      {\n        if ((m_reading_fcn_file || m_reading_script_file\n             || m_reading_classdef_file)\n            && ! m_fcn_file_full_name.empty ())\n          tok = new token (kw->tok_id, m_fcn_file_full_name, m_tok_beg, m_tok_end, get_comment_list ());\n        else\n          tok = new token (kw->tok_id, \"stdin\", m_tok_beg, m_tok_end, get_comment_list ());\n      }\n      break;\n\n    case magic_line_kw:\n      {\n        int l = m_tok_beg.line ();\n        octave_value ov (static_cast<double> (l));\n        tok = new token (kw->tok_id, ov, \"\", m_tok_beg, m_tok_end, get_comment_list ());\n      }\n      break;\n\n      // We should have handled all possible enum values above.  Rely on\n      // compiler diagnostics to warn if we haven't.  For example, GCC's\n      // -Wswitch option, enabled by -Wall, will provide a warning.\n    }\n\n  if (! tok)\n    tok = new token (kw->tok_id, true, m_tok_beg, m_tok_end, get_comment_list ());\n\n  return tok;\n}\n\n/*\n\n## check if magic file and line keywords are working\n%!assert <*62587> (ischar (__FILE__))\n%!assert <*62587> (isnumeric (__LINE__))\n\n*/\n\nbool\nbase_lexer::fq_identifier_contains_keyword (const std::string& s)\n{\n  std::size_t p1 = 0;\n  std::size_t p2;\n\n  std::string s_part;\n\n  do\n    {\n      p2 = s.find ('.', p1);\n\n      if (p2 != std::string::npos)\n        {\n          s_part = s.substr (p1, p2 - p1);\n          p1 = p2 + 1;\n        }\n      else\n        s_part = s.substr (p1);\n\n      if (iskeyword (s_part))\n        return true;\n    }\n  while (p2 != std::string::npos);\n\n  return false;\n}\n\nbool\nbase_lexer::whitespace_is_significant ()\n{\n  return (m_nesting_level.is_bracket ()\n          || (m_nesting_level.is_brace ()\n              && ! m_looking_at_object_index.front ()));\n}\n\nstatic inline bool\nlooks_like_bin (const char *s, int len)\n{\n  return (len > 2 && s[0] == '0' && (s[1] == 'b' || s[1] == 'B'));\n}\n\nstatic inline bool\nlooks_like_hex (const char *s, int len)\n{\n  return (len > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'));\n}\n\nOCTAVE_NORETURN static void\nerror_unexpected_bytes (int bytes)\n{\n  error (\"unexpected: bytes (= %d) not 1, 2, 4, or 8 in make_integer_value - please report this bug\", bytes);\n}\n\nstatic inline octave_value\nmake_integer_value (uintmax_t long_int_val, bool unsigned_val, int bytes)\n{\n  if (unsigned_val)\n    {\n     switch (bytes)\n       {\n       case 1:\n         return octave_value (octave_uint8 (long_int_val));\n\n       case 2:\n         return octave_value (octave_uint16 (long_int_val));\n\n       case 4:\n         return octave_value (octave_uint32 (long_int_val));\n\n       case 8:\n         return octave_value (octave_uint64 (long_int_val));\n\n       default:\n         error_unexpected_bytes (bytes);\n       };\n    }\n  else\n    {\n      // FIXME: Conversion to signed values is supposed to follow\n      // twos-complement rules.  Do we need to be more carefule here?\n\n      switch (bytes)\n        {\n        case 1:\n          return octave_value (octave_int8 (int8_t (long_int_val)));\n\n        case 2:\n          return octave_value (octave_int16 (int16_t (long_int_val)));\n\n        case 4:\n          return octave_value (octave_int32 (int32_t (long_int_val)));\n\n        case 8:\n        return octave_value (octave_int64 (int64_t (long_int_val)));\n\n        default:\n          error_unexpected_bytes (bytes);\n        };\n    }\n\n  return octave_value ();\n}\n\ntemplate <>\nint\nbase_lexer::handle_number<2> ()\n{\n  // Skip 0[bB] prefix.\n  std::string yytxt (flex_yytext () + 2);\n\n  yytxt.erase (std::remove (yytxt.begin (), yytxt.end (), '_'), yytxt.end ());\n\n  std::size_t pos = yytxt.find_first_of (\"su\");\n\n  bool unsigned_val = true;\n  int bytes = -1;\n\n  if (pos == std::string::npos)\n    {\n      std::size_t num_digits = yytxt.length ();\n\n      if (num_digits <= 8)\n        bytes = 1;\n      else if (num_digits <= 16)\n        bytes = 2;\n      else if (num_digits <= 32)\n        bytes = 4;\n      else if (num_digits <= 64)\n        bytes = 8;\n    }\n  else\n    {\n      unsigned_val = (yytxt[pos] == 'u');\n      std::string size_str = yytxt.substr (pos+1);\n      yytxt = yytxt.substr (0, pos);\n      std::size_t num_digits = yytxt.length ();\n\n      if (size_str == \"8\" && num_digits <= 8)\n        bytes = 1;\n      else if (size_str == \"16\" && num_digits <= 16)\n        bytes = 2;\n      else if (size_str == \"32\" && num_digits <= 32)\n        bytes = 4;\n      else if (size_str == \"64\" && num_digits <= 64)\n        bytes = 8;\n    }\n\n  if (bytes < 0)\n    {\n      std::string msg {\"too many digits for binary constant\"};\n      return syntax_error (msg);\n    }\n\n  // FIXME: is there a better way?  Can uintmax_t be anything other than long\n  // or long long?  Should we just be using uint64_t instead of uintmax_t?\n\n  errno = 0;\n  char *end;\n  uintmax_t long_int_val;\n  if (sizeof (uintmax_t) == sizeof (unsigned long long))\n    long_int_val = strtoull (yytxt.c_str (), &end, 2);\n  else if (sizeof (uintmax_t) == sizeof (unsigned long))\n    long_int_val = strtoul (yytxt.c_str (), &end, 2);\n  else\n    error (\"unexpected: size mismatch: uintmax_t vs unsigned long or unsigned long long in base_lexer::handle_number<2> - please report this bug\");\n\n  if (errno == ERANGE)\n    error (\"unexpected: ERANGE error in base_lexer::handle_number<2> - please report this bug\");\n\n  octave_value ov = make_integer_value (long_int_val, unsigned_val, bytes);\n\n  m_looking_for_object_index = false;\n  m_at_beginning_of_statement = false;\n\n  update_token_positions (flex_yyleng ());\n\n  token *tok = new token (NUMBER, ov, yytxt, m_tok_beg, m_tok_end, get_comment_list ());\n\n  return handle_token (tok);\n}\n\nstatic uint64_t\nflintmax ()\n{\n  return (static_cast<uint64_t> (1) << std::numeric_limits<double>::digits);\n}\n\ntemplate <>\nint\nbase_lexer::handle_number<10> ()\n{\n  bool imag = false;\n  bool digits_only = true;\n\n  char *yytxt = flex_yytext ();\n  std::size_t yylng = flex_yyleng ();\n\n  OCTAVE_LOCAL_BUFFER (char, tmptxt, yylng + 1);\n  char *rp = yytxt;\n  char *p = &tmptxt[0];\n\n  char ch;\n  while ((ch = *rp++))\n    {\n      switch (ch)\n        {\n        case '_':\n          break;\n\n        case 'D':\n        case 'd':\n          *p++ = 'e';\n          digits_only = false;\n          break;\n\n        case 'I':\n        case 'J':\n        case 'i':\n        case 'j':\n          // Octave does not provide imaginary integers.\n          digits_only = false;\n          imag = true;\n          break;\n\n        case '+':\n        case '-':\n        case '.':\n        case 'E':\n        case 'e':\n          digits_only = false;\n          *p++ = ch;\n          break;\n\n        default:\n          *p++ = ch;\n          break;\n        }\n    }\n\n  *p = '\\0';\n\n  double value = 0.0;\n  const char *chars_start = tmptxt;\n  const char *chars_end = tmptxt + std::strlen (tmptxt);\n\n#if defined (OCTAVE_HAVE_STD_FROM_CHARS_DOUBLE)\n  auto [ptr, ec] = std::from_chars (chars_start, chars_end, value);\n#elif defined (OCTAVE_HAVE_FAST_FLOAT)\n  auto [ptr, ec] = fast_float::from_chars (chars_start, chars_end, value);\n#else\n#  error \"Cannot convert string to floating-point number.  This should be unreachable.\"\n#endif\n\n  if (ec != std::errc{})\n    {\n      switch (ec)\n        {\n        case std::errc::invalid_argument:\n          fatal_error (\"invalid floating point format in base_lexer::handle_number<10> - please report this bug\");\n          break;\n        case std::errc::result_out_of_range:\n            // For floating point, convert overflow to infinity (like sscanf did)\n            // Check if the input represents a negative number\n            if (tmptxt[0] == '-')\n              value = -std::numeric_limits<double>::infinity ();\n            else\n              value = std::numeric_limits<double>::infinity ();\n          break;\n        default:\n          fatal_error (\"from_chars failed in base_lexer::handle_number<10> - please report this bug\");\n          break;\n        }\n      }\n\n  octave_value ov;\n\n  // Use >= because > will not return true until value is greater than\n  // flintmax + 2!\n\n  if (digits_only && value >= flintmax ())\n    {\n      // Try reading as an unsigned 64-bit integer.  If there is a range error,\n      // then create a double value.  Otherwise, create a special uint64 object\n      // that will be automatically converted to double unless it appears as\n      // the argument to one of the int64 or uint64 functions.\n\n      errno = 0;\n      char *end;\n      uintmax_t long_int_val;\n      if (sizeof (uintmax_t) == sizeof (unsigned long long))\n        long_int_val = strtoull (tmptxt, &end, 10);\n      else if (sizeof (uintmax_t) == sizeof (unsigned long))\n        long_int_val = strtoul (tmptxt, &end, 10);\n      else\n        error (\"unexpected: size mismatch: uintmax_t vs unsigned long or unsigned long long in base_lexer::handle_number<10> - please report this bug\");\n\n      if (errno != ERANGE)\n        {\n          // If possible, store the value as a signed integer.\n\n          octave_base_value *magic_int;\n          if (long_int_val > std::numeric_limits<int64_t>::max ())\n            magic_int = new octave_magic_uint (octave_uint64 (long_int_val));\n          else\n            magic_int = new octave_magic_int (octave_int64 (long_int_val));\n\n          ov = octave_value (magic_int);\n        }\n    }\n\n  m_looking_for_object_index = false;\n  m_at_beginning_of_statement = false;\n\n  update_token_positions (yylng);\n\n  if (ov.is_undefined ())\n    ov = (imag ? octave_value (Complex (0.0, value))\n               : octave_value (value));\n\n  token *tok = new token (NUMBER, ov, yytxt, m_tok_beg, m_tok_end, get_comment_list ());\n\n  return handle_token (tok);\n}\n\n/*\n%!assert (1e999, Inf)\n%!assert (-1e999, -Inf)\n*/\n\ntemplate <>\nint\nbase_lexer::handle_number<16> ()\n{\n  // Skip 0[xX] prefix.\n  std::string yytxt (flex_yytext () + 2);\n\n  yytxt.erase (std::remove (yytxt.begin (), yytxt.end (), '_'), yytxt.end ());\n\n  std::size_t pos = yytxt.find_first_of (\"su\");\n\n  bool unsigned_val = true;\n  int bytes = -1;\n\n  if (pos == std::string::npos)\n    {\n      std::size_t num_digits = yytxt.length ();\n\n      if (num_digits <= 2)\n        bytes = 1;\n      else if (num_digits <= 4)\n        bytes = 2;\n      else if (num_digits <= 8)\n        bytes = 4;\n      else if (num_digits <= 16)\n        bytes = 8;\n    }\n  else\n    {\n      unsigned_val = (yytxt[pos] == 'u');\n      std::string size_str = yytxt.substr (pos+1);\n      yytxt = yytxt.substr (0, pos);\n      std::size_t num_digits = yytxt.length ();\n\n      if (size_str == \"8\" && num_digits <= 2)\n        bytes = 1;\n      else if (size_str == \"16\" && num_digits <= 4)\n        bytes = 2;\n      else if (size_str == \"32\" && num_digits <= 8)\n        bytes = 4;\n      else if (size_str == \"64\" && num_digits <= 16)\n        bytes = 8;\n    }\n\n  if (bytes < 0)\n    {\n      std::string msg {\"too many digits for hexadecimal constant\"};\n      return syntax_error (msg);\n    }\n\n  uintmax_t long_int_val = 0;\n  const char *chars_start = yytxt.c_str ();\n  const char *chars_end = chars_start + yytxt.length ();\n  auto [ptr, ec] = std::from_chars (chars_start, chars_end, long_int_val, 16);\n  if (ec != std::errc{})\n    {\n      switch (ec)\n        {\n        case std::errc::invalid_argument:\n          fatal_error (\"invalid hexadecimal format in base_lexer::handle_number<16> - please report this bug\");\n          break;\n        case std::errc::result_out_of_range:\n          fatal_error (\"hexadecimal value out of range in base_lexer::handle_number<16> - please report this bug\");\n          break;\n        default:\n          fatal_error (\"from_chars failed in base_lexer::handle_number<16> - please report this bug\");\n          break;\n        }\n      }\n\n\n  octave_value ov = make_integer_value (long_int_val, unsigned_val, bytes);\n\n  m_looking_for_object_index = false;\n  m_at_beginning_of_statement = false;\n\n  update_token_positions (flex_yyleng ());\n\n  token *tok = new token (NUMBER, ov, yytxt, m_tok_beg, m_tok_end, get_comment_list ());\n\n  return handle_token (tok);\n}\n\nvoid\nbase_lexer::handle_continuation ()\n{\n  char *yytxt = flex_yytext ();\n  int yylng = flex_yyleng ();\n\n  int offset = 1;\n  if (yytxt[0] == '\\\\')\n    warn_language_extension_continuation ();\n  else\n    offset = 3;\n\n  bool have_space = false;\n  while (offset < yylng)\n    {\n      char c = yytxt[offset];\n      if (is_space_or_tab (c))\n        {\n          have_space = true;\n          offset++;\n        }\n      else\n        break;\n    }\n\n  if (have_space)\n    mark_previous_token_trailing_space ();\n\n  bool have_comment = false;\n  bool first = true;\n  while (offset < yylng)\n    {\n      char c = yytxt[offset];\n\n      if (c == '#' || c == '%')\n        {\n          if (first && c == '#')\n            {\n              m_comment_uses_hash_char = true;\n              first = false;\n            }\n\n          have_comment = true;\n          offset++;\n        }\n      else\n        break;\n    }\n\n  if (have_comment)\n    {\n      m_comment_text = &yytxt[offset];\n\n      // finish_comment sets m_at_beginning_of_statement to true but that's not\n      // be correct if we are handling a continued statement.  Preserve the\n      // current state.\n\n      bool saved_bos = m_at_beginning_of_statement;\n\n      finish_comment (comment_elt::end_of_line);\n\n      m_at_beginning_of_statement = saved_bos;\n    }\n\n  m_filepos.next_line ();\n}\n\nvoid\nbase_lexer::finish_comment (comment_elt::comment_type typ)\n{\n  if (looks_like_copyright (m_comment_text))\n    typ = comment_elt::copyright;\n\n  m_comment_list.append (m_comment_text, typ, m_comment_uses_hash_char);\n\n  m_comment_text = \"\";\n  m_comment_uses_hash_char = false;\n  m_at_beginning_of_statement = true;\n}\n\nint\nbase_lexer::handle_close_bracket (int bracket_type)\n{\n  m_looking_at_object_index.pop_front ();\n\n  m_looking_for_object_index = true;\n  m_at_beginning_of_statement = false;\n\n  if (! m_nesting_level.none ())\n    {\n      m_nesting_level.remove ();\n\n      if (bracket_type == ']')\n        m_bracketflag--;\n      else if (bracket_type == '}')\n        m_braceflag--;\n      else\n        error (\"unexpected: bracket_type not ']' or '}' in base_lexer::handle_close_bracket - please report this bug\");\n    }\n\n  pop_start_state ();\n\n  return handle_token (bracket_type);\n}\n\nbool\nbase_lexer::looks_like_command_arg ()\n{\n  if (! m_allow_command_syntax)\n    return false;\n\n  bool space_before = space_follows_previous_token ();\n  bool space_after = looking_at_space ();\n\n  return (space_before && ! space_after && previous_token_may_be_command ());\n}\n\nint\nbase_lexer::handle_superclass_identifier ()\n{\n  update_token_positions (flex_yyleng ());\n\n  std::string txt = flex_yytext ();\n\n  txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab),\n             txt.end ());\n\n  std::size_t pos = txt.find (\"@\");\n\n  std::string meth = txt.substr (0, pos);\n  std::string cls = txt.substr (pos + 1);\n\n  if (iskeyword (meth) || fq_identifier_contains_keyword (cls))\n    {\n      std::string msg {\"method, class, and package names may not be keywords\"};\n      return syntax_error (msg);\n    }\n\n  token *tok = new token (SUPERCLASSREF, meth, cls, m_tok_beg, m_tok_end, get_comment_list ());\n\n  m_filepos.increment_column (flex_yyleng ());\n\n  return handle_token (tok);\n}\n\ntoken *\nbase_lexer::make_meta_identifier_token (const std::string& cls)\n{\n  // Token positions should have already been updated before this\n  // function is called.\n\n  m_looking_for_object_index = true;\n\n  token *tok = new token (METAQUERY, cls, m_tok_beg, m_tok_end, get_comment_list ());\n\n  m_filepos.increment_column (flex_yyleng ());\n\n  return tok;\n}\n\ntoken *\nbase_lexer::make_fq_identifier_token (const std::string& ident)\n{\n  // Token positions should have already been updated before this\n  // function is called.\n\n  m_looking_for_object_index = true;\n\n  token *tok = new token (FQ_IDENT, ident, m_tok_beg, m_tok_end, get_comment_list ());\n\n  m_filepos.increment_column (flex_yyleng ());\n\n  return tok;\n}\n\n// Figure out exactly what kind of token to return when we have seen an\n// identifier.  Handles keywords.  Return -1 if the identifier should be\n// ignored.\n\nint\nbase_lexer::handle_identifier ()\n{\n  update_token_positions (flex_yyleng ());\n\n  std::string ident = flex_yytext ();\n\n  // If we are expecting a structure element, avoid recognizing keywords and\n  // other special names and return STRUCT_ELT, which is a string that is also\n  // a valid identifier.\n\n  if (m_looking_at_indirect_ref)\n    {\n      token *tok = new token (STRUCT_ELT, ident, m_tok_beg, m_tok_end, get_comment_list ());\n\n      m_looking_for_object_index = true;\n\n      return handle_token (tok);\n    }\n\n  // If ident is a keyword token, then make_keyword_token will set\n  // m_at_beginning_of_statement.  For example, if tok is an IF token, then\n  // m_at_beginning_of_statement will be false.\n\n  token *tok = make_keyword_token (ident);\n\n  // If we have a regular keyword, return it.\n  // Keywords can be followed by identifiers.\n\n  if (tok)\n    {\n      m_looking_for_object_index = false;\n\n      // The call to make_keyword_token set m_at_beginning_of_statement.\n      return handle_token (tok);\n    }\n\n  tok = new token (NAME, ident, m_tok_beg, m_tok_end, get_comment_list ());\n\n  // For compatibility with Matlab, the following symbols are handled specially\n  // so that things like\n  //\n  //   pi +1\n  //\n  // are parsed as an addition expression instead of as a command-style\n  // function call with the argument \"+1\".\n\n  if (m_at_beginning_of_statement\n      && ! (m_parsing_anon_fcn_body\n            || ident == \"e\" || ident == \"pi\"\n            || ident == \"I\" || ident == \"i\"\n            || ident == \"J\" || ident == \"j\"\n            || ident == \"Inf\" || ident == \"inf\"\n            || ident == \"NaN\" || ident == \"nan\"))\n    tok->mark_may_be_command ();\n\n  // The magic end index can't be indexed.\n  if (ident != \"end\")\n    m_looking_for_object_index = true;\n\n  m_at_beginning_of_statement = false;\n\n  return handle_token (tok);\n}\n\nvoid\nbase_lexer::check_comment_for_hash_char (const char *txt, std::size_t len)\n{\n  if (m_comment_uses_hash_char)\n    return;\n\n  std::size_t i = 0;\n  while (i < len && is_space_or_tab (txt[i]))\n    i++;\n\n  m_comment_uses_hash_char = txt[i] == '#';\n}\n\nvoid\nbase_lexer::maybe_warn_separator_insert (char sep)\n{\n  std::string nm = m_fcn_file_full_name;\n\n  if (nm.empty ())\n    warning_with_id (\"Octave:separator-insert\",\n                     \"potential auto-insertion of '%c' near line %d\",\n                     sep, m_filepos.line ());\n  else\n    warning_with_id (\"Octave:separator-insert\",\n                     \"potential auto-insertion of '%c' near line %d of file %s\",\n                     sep, m_filepos.line (), nm.c_str ());\n}\n\nvoid\nbase_lexer::warn_language_extension (const std::string& msg)\n{\n  std::string nm = m_fcn_file_full_name;\n\n  if (nm.empty ())\n    warning_with_id (\"Octave:language-extension\",\n                     \"Octave language extension used: %s\",\n                     msg.c_str ());\n  else\n    warning_with_id (\"Octave:language-extension\",\n                     \"Octave language extension used: %s near line %d of file %s\",\n                     msg.c_str (), m_filepos.line (), nm.c_str ());\n}\n\nvoid\nbase_lexer::maybe_warn_language_extension_comment (char c)\n{\n  if (c == '#')\n    warn_language_extension (\"# used as comment character\");\n}\n\nvoid\nbase_lexer::warn_language_extension_continuation ()\n{\n  warn_language_extension (\"\\\\ used as line continuation marker\");\n}\n\nvoid\nbase_lexer::warn_language_extension_operator (const std::string& op)\n{\n  std::string t = op;\n  int n = t.length ();\n  if (t[n-1] == '\\n')\n    t.resize (n-1);\n  warn_language_extension (t + \" used as operator\");\n}\n\nvoid\nbase_lexer::warn_deprecated_syntax (const std::string& msg)\n{\n  if (m_fcn_file_full_name.empty ())\n    warning_with_id (\"Octave:deprecated-syntax\", \"%s\", msg.c_str ());\n  else\n    warning_with_id (\"Octave:deprecated-syntax\",\n                     \"%s; near line %d of file '%s'\", msg.c_str (),\n                     m_filepos.line (), m_fcn_file_full_name.c_str ());\n}\n\nint\nbase_lexer::syntax_error (const std::string& msg)\n{\n  return syntax_error (msg, m_tok_beg, m_tok_end);\n}\n\nint\nbase_lexer::syntax_error (const std::string& msg, const filepos& pos)\n{\n  return syntax_error (msg, pos, pos);\n}\n\nint\nbase_lexer::syntax_error (const std::string& msg, const filepos& beg_pos,\n                          const filepos& end_pos)\n{\n  token *tok = new token (LEXICAL_ERROR, msg, beg_pos, end_pos);\n\n  push_token (tok);\n\n  return count_token_internal (tok->token_id ());\n}\n\nvoid\nbase_lexer::push_token (token *tok)\n{\n  YYSTYPE *lval = yyget_lval (m_scanner);\n  lval->tok = tok;\n  m_tokens.push (tok);\n}\n\ntoken *\nbase_lexer::current_token ()\n{\n  YYSTYPE *lval = yyget_lval (m_scanner);\n  return lval->tok;\n}\n\nstd::size_t\nbase_lexer::pending_token_count () const\n{\n  return m_tokens.size ();\n}\n\n#if defined (OCTAVE_PARSER_DEBUG)\nvoid\nbase_lexer::display_token (int tok_id)\n{\n  switch (tok_id)\n    {\n    case '=': std::cerr << \"'='\\n\"; break;\n    case ':': std::cerr << \"':'\\n\"; break;\n    case '-': std::cerr << \"'-'\\n\"; break;\n    case '+': std::cerr << \"'+'\\n\"; break;\n    case '*': std::cerr << \"'*'\\n\"; break;\n    case '/': std::cerr << \"'/'\\n\"; break;\n    case '~': std::cerr << \"'~'\\n\"; break;\n    case '!': std::cerr << \"'!'\\n\"; break;\n    case ADD_EQ: std::cerr << \"ADD_EQ\\n\"; break;\n    case SUB_EQ: std::cerr << \"SUB_EQ\\n\"; break;\n    case MUL_EQ: std::cerr << \"MUL_EQ\\n\"; break;\n    case DIV_EQ: std::cerr << \"DIV_EQ\\n\"; break;\n    case LEFTDIV_EQ: std::cerr << \"LEFTDIV_EQ\\n\"; break;\n    case POW_EQ: std::cerr << \"POW_EQ\\n\"; break;\n    case EMUL_EQ: std::cerr << \"EMUL_EQ\\n\"; break;\n    case EDIV_EQ: std::cerr << \"EDIV_EQ\\n\"; break;\n    case ELEFTDIV_EQ: std::cerr << \"ELEFTDIV_EQ\\n\"; break;\n    case EPOW_EQ: std::cerr << \"EPOW_EQ\\n\"; break;\n    case AND_EQ: std::cerr << \"AND_EQ\\n\"; break;\n    case OR_EQ: std::cerr << \"OR_EQ\\n\"; break;\n    case EXPR_AND_AND: std::cerr << \"EXPR_AND_AND\\n\"; break;\n    case EXPR_OR_OR: std::cerr << \"EXPR_OR_OR\\n\"; break;\n    case EXPR_AND: std::cerr << \"EXPR_AND\\n\"; break;\n    case EXPR_OR: std::cerr << \"EXPR_OR\\n\"; break;\n    case EXPR_LT: std::cerr << \"EXPR_LT\\n\"; break;\n    case EXPR_LE: std::cerr << \"EXPR_LE\\n\"; break;\n    case EXPR_EQ: std::cerr << \"EXPR_EQ\\n\"; break;\n    case EXPR_NE: std::cerr << \"EXPR_NE\\n\"; break;\n    case EXPR_GE: std::cerr << \"EXPR_GE\\n\"; break;\n    case EXPR_GT: std::cerr << \"EXPR_GT\\n\"; break;\n    case LEFTDIV: std::cerr << \"LEFTDIV\\n\"; break;\n    case EMUL: std::cerr << \"EMUL\\n\"; break;\n    case EDIV: std::cerr << \"EDIV\\n\"; break;\n    case ELEFTDIV: std::cerr << \"ELEFTDIV\\n\"; break;\n    case HERMITIAN: std::cerr << \"HERMITIAN\\n\"; break;\n    case TRANSPOSE: std::cerr << \"TRANSPOSE\\n\"; break;\n    case PLUS_PLUS: std::cerr << \"PLUS_PLUS\\n\"; break;\n    case MINUS_MINUS: std::cerr << \"MINUS_MINUS\\n\"; break;\n    case POW: std::cerr << \"POW\\n\"; break;\n    case EPOW: std::cerr << \"EPOW\\n\"; break;\n\n    case NUMBER:\n      {\n        token *tok = current_token ();\n        std::cerr << \"NUMBER [\";\n        octave_value num = tok->number ();\n        num.print_raw (std::cerr);\n        std::cerr << \"]\\n\";\n      }\n      break;\n\n    case STRUCT_ELT:\n      {\n        token *tok = current_token ();\n        std::cerr << \"STRUCT_ELT [\" << tok->text () << \"]\\n\";\n      }\n      break;\n\n    case NAME:\n      {\n        token *tok = current_token ();\n        std::cerr << \"NAME [\" << tok->text () << \"]\\n\";\n      }\n      break;\n\n    case END: std::cerr << \"END\\n\"; break;\n\n    case DQ_STRING:\n    case SQ_STRING:\n      {\n        token *tok = current_token ();\n\n        std::cerr << (tok_id == DQ_STRING ? \"DQ_STRING\" : \"SQ_STRING\")\n                  << \" [\" << tok->text () << \"]\\n\";\n      }\n      break;\n\n    case FOR: std::cerr << \"FOR\\n\"; break;\n    case WHILE: std::cerr << \"WHILE\\n\"; break;\n    case DO: std::cerr << \"DO\\n\"; break;\n    case UNTIL: std::cerr << \"UNTIL\\n\"; break;\n    case IF: std::cerr << \"IF\\n\"; break;\n    case ELSEIF: std::cerr << \"ELSEIF\\n\"; break;\n    case ELSE: std::cerr << \"ELSE\\n\"; break;\n    case SWITCH: std::cerr << \"SWITCH\\n\"; break;\n    case CASE: std::cerr << \"CASE\\n\"; break;\n    case OTHERWISE: std::cerr << \"OTHERWISE\\n\"; break;\n    case BREAK: std::cerr << \"BREAK\\n\"; break;\n    case CONTINUE: std::cerr << \"CONTINUE\\n\"; break;\n    case RETURN: std::cerr << \"RETURN\\n\"; break;\n    case UNWIND: std::cerr << \"UNWIND\\n\"; break;\n    case CLEANUP: std::cerr << \"CLEANUP\\n\"; break;\n    case TRY: std::cerr << \"TRY\\n\"; break;\n    case CATCH: std::cerr << \"CATCH\\n\"; break;\n    case GLOBAL: std::cerr << \"GLOBAL\\n\"; break;\n    case PERSISTENT: std::cerr << \"PERSISTENT\\n\"; break;\n    case FCN_HANDLE: std::cerr << \"FCN_HANDLE\\n\"; break;\n    case END_OF_INPUT: std::cerr << \"END_OF_INPUT\\n\\n\"; break;\n    case LEXICAL_ERROR: std::cerr << \"LEXICAL_ERROR\\n\\n\"; break;\n    case FUNCTION: std::cerr << \"FUNCTION\\n\"; break;\n    case INPUT_FILE: std::cerr << \"INPUT_FILE\\n\"; break;\n    case SUPERCLASSREF: std::cerr << \"SUPERCLASSREF\\n\"; break;\n    case METAQUERY: std::cerr << \"METAQUERY\\n\"; break;\n    case GET: std::cerr << \"GET\\n\"; break;\n    case SET: std::cerr << \"SET\\n\"; break;\n    case PROPERTIES: std::cerr << \"PROPERTIES\\n\"; break;\n    case METHODS: std::cerr << \"METHODS\\n\"; break;\n    case EVENTS: std::cerr << \"EVENTS\\n\"; break;\n    case CLASSDEF: std::cerr << \"CLASSDEF\\n\"; break;\n    case '\\n': std::cerr << \"\\\\n\\n\"; break;\n    case '\\r': std::cerr << \"\\\\r\\n\"; break;\n    case '\\t': std::cerr << \"TAB\\n\"; break;\n    default:\n      {\n        if (tok_id < 256 && tok_id > 31)\n          std::cerr << static_cast<char> (tok_id) << \"\\n\";\n        else\n          std::cerr << \"UNKNOWN(\" << tok_id << \")\\n\";\n      }\n      break;\n    }\n}\n#endif\n\nvoid\nbase_lexer::fatal_error (const char *msg)\n{\n  ::error (\"fatal lexer error: %s\", msg);\n}\n\nvoid\nbase_lexer::increment_token_count ()\n{\n  m_token_count++;\n\n#if defined (OCTAVE_PARSER_DEBUG)\n  ++V__token_count__;\n#endif\n}\n\nvoid\nbase_lexer::lexer_debug (const char *pattern)\n{\n#if defined (OCTAVE_PARSER_DEBUG)\n  if (V__lexer_debug_flag__)\n    {\n      std::cerr << std::endl;\n\n      display_start_state ();\n\n      std::cerr << \"P: \" << pattern << std::endl;\n      std::cerr << \"T: \" << flex_yytext () << std::endl;\n    }\n#else\n  // No code.  Compiler should optimize this away.\n  octave_unused_parameter (pattern);\n#endif\n}\n\nbool\nbase_lexer::input_from_tmp_history_file ()\n{\n  history_system& history_sys = m_interpreter.get_history_system ();\n\n  return history_sys.input_from_tmp_file ();\n}\n\nvoid\nbase_lexer::push_start_state (int state)\n{\n  OCTAVE_YYG;\n\n  start_state_stack.push (state);\n\n  BEGIN (start_state ());\n}\n\nvoid\nbase_lexer::pop_start_state ()\n{\n  OCTAVE_YYG;\n\n  start_state_stack.pop ();\n\n  BEGIN (start_state ());\n}\n\nvoid\nbase_lexer::clear_start_state ()\n{\n  while (! start_state_stack.empty ())\n    start_state_stack.pop ();\n\n  push_start_state (INITIAL);\n}\n\n\n#if defined (OCTAVE_PARSER_DEBUG)\nvoid\nbase_lexer::display_start_state () const\n{\n  std::cerr << \"S: \";\n\n  switch (start_state ())\n    {\n    case INITIAL:\n      std::cerr << \"INITIAL\" << std::endl;\n      break;\n\n    case COMMAND_START:\n      std::cerr << \"COMMAND_START\" << std::endl;\n      break;\n\n    case MATRIX_START:\n      std::cerr << \"MATRIX_START\" << std::endl;\n      break;\n\n    case INPUT_FILE_START:\n      std::cerr << \"INPUT_FILE_START\" << std::endl;\n      break;\n\n    case BLOCK_COMMENT_START:\n      std::cerr << \"BLOCK_COMMENT_START\" << std::endl;\n      break;\n\n    case LINE_COMMENT_START:\n      std::cerr << \"LINE_COMMENT_START\" << std::endl;\n      break;\n\n    case DQ_STRING_START:\n      std::cerr << \"DQ_STRING_START\" << std::endl;\n      break;\n\n    case SQ_STRING_START:\n      std::cerr << \"SQ_STRING_START\" << std::endl;\n      break;\n\n    case FQ_IDENT_START:\n      std::cerr << \"FQ_IDENT_START\" << std::endl;\n      break;\n\n    default:\n      std::cerr << \"UNKNOWN START STATE!\" << std::endl;\n      break;\n    }\n}\n#endif\n\nbool\nbase_lexer::maybe_unput_comma_before_unary_op (int tok_id)\n{\n  int prev_tok_id = previous_token_id ();\n\n  bool unput_comma = false;\n\n  if (whitespace_is_significant () && space_follows_previous_token ())\n    {\n      int c = text_yyinput ();\n      xunput (c);\n\n      bool space_after = is_space_or_tab (c);\n\n      if (! (prev_tok_id == '[' || prev_tok_id == '{'\n             || previous_token_is_binop ()\n             || ((tok_id == '+' || tok_id == '-') && space_after)))\n        unput_comma = true;\n    }\n\n  return unput_comma;\n}\n\nint\nbase_lexer::handle_op (int tok_id, const std::string& tok_txt, int tok_len,\n                       bool bos, bool compat)\n{\n  if (! compat)\n    warn_language_extension_operator (tok_txt);\n\n  update_token_positions (tok_len);\n\n  token *tok = new token (tok_id, m_tok_beg, m_tok_end, get_comment_list ());\n\n  m_looking_for_object_index = false;\n  m_at_beginning_of_statement = bos;\n\n  switch (tok_id)\n    {\n    case EXPR_LT:\n      if (m_parsing_classdef_decl)\n        {\n          m_parsing_classdef_superclass = true;\n          push_start_state (FQ_IDENT_START);\n        }\n      break;\n\n    case EXPR_AND:\n      if (m_parsing_classdef_superclass)\n        push_start_state (FQ_IDENT_START);\n      break;\n\n    default:\n      break;\n    }\n\n  return handle_token (tok);\n}\n\n// When a command argument boundary is detected, push out the current argument\n// being built.  This one seems like a good candidate for a function call.\n\nint\nbase_lexer::finish_command_arg ()\n{\n  token *tok = new token (SQ_STRING, m_string_text, m_tok_beg, m_tok_end, get_comment_list ());\n\n  m_string_text = \"\";\n  m_command_arg_paren_count = 0;\n\n  return handle_token (tok);\n}\n\nint\nbase_lexer::handle_token (int tok_id)\n{\n  return handle_token (new token (tok_id, m_tok_beg, m_tok_end));\n}\n\nint\nbase_lexer::handle_token (token *tok)\n{\n  push_token (tok);\n\n  int tok_id = tok->token_id ();\n\n  if (m_arguments_is_keyword\n      && ! (tok_id == ';' || tok_id == ',' || tok_id == '\\n'))\n    m_arguments_is_keyword = false;\n\n  return count_token_internal (tok_id);\n}\n\nint\nbase_lexer::count_token_internal (int tok_id)\n{\n  if (tok_id != '\\n')\n    increment_token_count ();\n\n  return show_token (tok_id);\n}\n\nint\nbase_lexer::show_token (int tok_id)\n{\n#if defined (OCTAVE_PARSER_DEBUG)\n  if (V__display_tokens__)\n    display_token (tok_id);\n\n  if (V__lexer_debug_flag__)\n    {\n      std::cerr << \"R: \";\n      display_token (tok_id);\n      std::cerr << std::endl;\n    }\n#endif\n\n  return tok_id;\n}\n\nint\nlexer::fill_flex_buffer (char *buf, unsigned max_size)\n{\n  int status = 0;\n\n  if (m_input_buf.empty ())\n    {\n      std::string ps\n        = m_initial_input ? m_interpreter.PS1 () : m_interpreter.PS2 ();\n\n      std::string prompt = command_editor::decode_prompt_string (ps);\n\n      bool eof = false;\n      m_current_input_line = m_reader.get_input (prompt, eof);\n\n      m_input_buf.fill (m_current_input_line, eof);\n\n      // Attempt to capture text for functions defined on the command line.\n      //\n      // FIXME: the handling of newline here seems a bit clumsy.\n      //\n      // See also comments in push_lexer::append_input.\n\n      if (m_buffer_function_text)\n        {\n          if (! m_current_input_line.empty ())\n          {\n            m_function_text += m_current_input_line;\n            if (m_current_input_line.back () != '\\n')\n              m_function_text += '\\n';\n          }\n        }\n    }\n\n  if (! m_input_buf.empty ())\n    status = m_input_buf.copy_chunk (buf, max_size);\n  else\n    status = YY_NULL;\n\n  m_initial_input = false;\n\n  return status;\n}\n\nvoid\npush_lexer::append_input (const std::string& input, bool eof)\n{\n  // FIXME: input may contain more than one line, so how can we properly start\n  // buffering input for command-line functions?\n  //\n  // Currently, base_lexer::make_keyword_token starts buffering text for\n  // command-line functions by setting the initial value of m_function_text to\n  // m_current_input_line when function_kw is recognized.  To make that work,\n  // we need to do something like maintain a queue of input strings and pass\n  // them to the flex buffer one line at a time, while also setting\n  // m_current_input_line.  Some care will be needed if a single line of input\n  // arrives in multiple calls to append_input.\n  //\n  // OR, should we require that the input string to append_input IS a single\n  // line of input?  That seems to be what we are doing here by setting\n  // m_current_input_line to input.\n\n  m_input_buf.fill (input, eof);\n  m_current_input_line = input;\n}\n\nint\npush_lexer::fill_flex_buffer (char *buf, unsigned max_size)\n{\n  int status = 0;\n\n  if (m_input_buf.empty () && ! m_input_buf.at_eof ())\n    {\n      // If the input buffer is empty or we are at the end of the buffer,\n      // insert ASCII 1 as a marker for subsequent rules.  Don't insert a\n      // newline character in this case.  Instead of calling input_buffer::fill\n      // followed immediately by input_buffer::copy_chunk, simply insert the\n      // marker directly in BUF.\n\n      if (max_size <= 0)\n        error (\"unexpected: max_size <= 0 in push_lexer::fill_flex_buffer - please report this bug\");\n\n      buf[0] = static_cast<char> (1);\n      status = 1;\n    }\n  else\n    {\n      // Note that the copy_chunk function may append a newline character to\n      // the input.\n\n      if (! m_input_buf.empty ())\n        status = m_input_buf.copy_chunk (buf, max_size, true);\n      else\n        status = YY_NULL;\n    }\n\n  return status;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/module.mk",
    "content": "PARSE_TREE_INC = \\\n  %reldir%/anon-fcn-validator.h \\\n  %reldir%/bp-table.h \\\n  %reldir%/comment-list.h \\\n  %reldir%/filepos.h \\\n  %reldir%/lex.h \\\n  %reldir%/oct-lvalue.h \\\n  %reldir%/parse.h \\\n  %reldir%/profiler.h \\\n  %reldir%/pt-all.h \\\n  %reldir%/pt-anon-scopes.h \\\n  %reldir%/pt-arg-list.h \\\n  %reldir%/pt-args-block.h \\\n  %reldir%/pt-array-list.h \\\n  %reldir%/pt-assign.h \\\n  %reldir%/pt-binop.h \\\n  %reldir%/pt-bp.h \\\n  %reldir%/pt-cbinop.h \\\n  %reldir%/pt-cell.h \\\n  %reldir%/pt-check.h \\\n  %reldir%/pt-classdef.h \\\n  %reldir%/pt-cmd.h \\\n  %reldir%/pt-colon.h \\\n  %reldir%/pt-const.h \\\n  %reldir%/pt-decl.h \\\n  %reldir%/pt-delimiter-list.h \\\n  %reldir%/pt-eval.h \\\n  %reldir%/pt-except.h \\\n  %reldir%/pt-exp.h \\\n  %reldir%/pt-fcn-handle.h \\\n  %reldir%/pt-id.h \\\n  %reldir%/pt-idx.h \\\n  %reldir%/pt-jump.h \\\n  %reldir%/pt-loop.h \\\n  %reldir%/pt-mat.h \\\n  %reldir%/pt-misc.h \\\n  %reldir%/pt-pr-code.h \\\n  %reldir%/pt-select.h \\\n  %reldir%/pt-spmd.h \\\n  %reldir%/pt-stmt.h \\\n  %reldir%/pt-tm-const.h \\\n  %reldir%/pt-unop.h \\\n  %reldir%/pt-walk.h \\\n  %reldir%/pt.h \\\n  %reldir%/separator-list.h \\\n  %reldir%/token.h\n\n\n## oct-gperf.h and oct-parse.h are in the SRC list so that they will\n## be distributed but not installed.\n\nPARSE_TREE_SRC = \\\n  %reldir%/anon-fcn-validator.cc \\\n  %reldir%/bp-table.cc \\\n  %reldir%/comment-list.cc \\\n  %reldir%/lex.ll \\\n  %reldir%/oct-gperf.h \\\n  %reldir%/oct-lvalue.cc \\\n  %reldir%/oct-parse.h \\\n  %reldir%/oct-parse.yy \\\n  %reldir%/profiler.cc \\\n  %reldir%/pt-anon-scopes.cc \\\n  %reldir%/pt-arg-list.cc \\\n  %reldir%/pt-args-block.cc \\\n  %reldir%/pt-array-list.cc \\\n  %reldir%/pt-assign.cc \\\n  %reldir%/pt-binop.cc \\\n  %reldir%/pt-bp.cc \\\n  %reldir%/pt-cbinop.cc \\\n  %reldir%/pt-cell.cc \\\n  %reldir%/pt-check.cc \\\n  %reldir%/pt-classdef.cc \\\n  %reldir%/pt-colon.cc \\\n  %reldir%/pt-const.cc \\\n  %reldir%/pt-decl.cc \\\n  %reldir%/pt-eval.cc \\\n  %reldir%/pt-except.cc \\\n  %reldir%/pt-exp.cc \\\n  %reldir%/pt-fcn-handle.cc \\\n  %reldir%/pt-id.cc \\\n  %reldir%/pt-idx.cc \\\n  %reldir%/pt-loop.cc \\\n  %reldir%/pt-mat.cc \\\n  %reldir%/pt-misc.cc \\\n  %reldir%/pt-pr-code.cc \\\n  %reldir%/pt-select.cc \\\n  %reldir%/pt-spmd.cc \\\n  %reldir%/pt-stmt.cc \\\n  %reldir%/pt-tm-const.cc \\\n  %reldir%/pt-unop.cc \\\n  %reldir%/pt-walk.cc \\\n  %reldir%/pt.cc\n\n## Special rules for sources which must be built before rest of compilation.\n\n## Don't use a pipeline to process gperf output since if gperf\n## is missing but sed is not, the exit status of the pipeline\n## will still be success and we will end up creating an empty\n## oct-gperf.h file.\n%reldir%/oct-gperf.h: %reldir%/octave.gperf\n\t$(AM_V_GEN)rm -f $@-t $@t1 $@ && \\\n\t$(GPERF) -t -C -D -G -L C++ -Z octave_kw_hash $< > $@-t1 && \\\n\t$(SED) -e 's,lookup\\[,gperf_lookup[,' -e 's,register ,,g' < $@-t1 > $@-t && \\\n\tmv $@-t $@ && \\\n\trm -f $@-t1\n\nnoinst_LTLIBRARIES += \\\n  %reldir%/libparse-tree.la\n\n%canon_reldir%_libparse_tree_la_SOURCES = $(PARSE_TREE_SRC)\n\n%canon_reldir%_libparse_tree_la_CPPFLAGS = \\\n  $(libinterp_liboctinterp_la_CPPFLAGS) \\\n  $(OCTAVE_PARSER_CPPFLAGS)\n\nlibinterp_EXTRA_DIST += \\\n  %reldir%/octave.gperf\n\nlibinterp_liboctinterp_la_LIBADD += %reldir%/libparse-tree.la\n"
  },
  {
    "path": "libinterp/parse-tree/oct-lvalue.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"ovl.h\"\n#include \"oct-lvalue.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nbool octave_lvalue::is_defined () const\n{\n  return ! is_black_hole () && m_frame->is_defined (m_sym);\n}\n\nbool\noctave_lvalue::is_undefined () const\n{\n  return ! is_defined ();\n}\n\nvoid\noctave_lvalue::define (const octave_value& v)\n{\n  m_frame->assign (m_sym, v);\n}\n\nvoid\noctave_lvalue::assign (octave_value::assign_op op,\n                       const octave_value& rhs)\n{\n  if (! is_black_hole ())\n    m_frame->assign (op, m_sym, m_type, m_idx, rhs);\n}\n\noctave_idx_type\noctave_lvalue::numel () const\n{\n  // Return 1 if there is no index because without an index there\n  // should be no way to have a cs-list here.  Cs-lists may be passed\n  // around internally but they are not supposed to be stored as\n  // single symbols in a stack frame.\n\n  std::size_t num_indices = m_idx.size ();\n\n  if (num_indices == 0)\n    return 1;\n\n  switch (m_type[num_indices-1])\n    {\n    case '(':\n      return 1;\n\n    case '{':\n      {\n        // FIXME: Duplicate code in '.' case below...\n\n        // Evaluate, skipping the last index.\n\n        std::string tmp_type = m_type;\n        std::list<octave_value_list> tmp_idx = m_idx;\n\n        tmp_type.pop_back ();\n        tmp_idx.pop_back ();\n\n        octave_value tmp = eval_for_numel (tmp_type, tmp_idx);\n\n        octave_value_list tidx = m_idx.back ();\n\n        if (tmp.is_undefined ())\n          {\n            if (tidx.has_magic_colon ())\n              err_invalid_inquiry_subscript ();\n\n            tmp = Cell ();\n          }\n        else if (tmp.is_zero_by_zero ()\n                 && (tmp.is_matrix_type () || tmp.is_string ()))\n          {\n            tmp = Cell ();\n          }\n\n        return tmp.xnumel (tidx);\n      }\n      break;\n\n    case '.':\n      {\n        // Evaluate, skipping either the last index or the last two\n        // indices if we are looking at \"(idx).field\".\n\n        std::string tmp_type = m_type;\n        std::list<octave_value_list> tmp_idx = m_idx;\n\n        tmp_type.pop_back ();\n        tmp_idx.pop_back ();\n\n        bool paren_dot = num_indices > 1 && m_type[num_indices-2] == '(';\n\n        // Index for paren operator, if any.\n        octave_value_list pidx;\n\n        if (paren_dot)\n          {\n            pidx = tmp_idx.back ();\n\n            tmp_type.pop_back ();\n            tmp_idx.pop_back ();\n          }\n\n        octave_value tmp = eval_for_numel (tmp_type, tmp_idx);\n\n        bool autoconv = (tmp.is_zero_by_zero ()\n                         && (tmp.is_matrix_type () || tmp.is_string ()\n                             || tmp.iscell ()));\n\n        if (paren_dot)\n          {\n            // Use octave_map, not octave_scalar_map so that the\n            // dimensions are 0x0, not 1x1.\n\n            if (tmp.is_undefined ())\n              {\n                if (pidx.has_magic_colon ())\n                  err_invalid_inquiry_subscript ();\n\n                tmp = octave_map ();\n              }\n            else if (autoconv)\n              tmp = octave_map ();\n\n            return tmp.xnumel (pidx);\n          }\n        else if (tmp.is_undefined () || autoconv)\n          return 1;\n        else\n          return tmp.xnumel (octave_value_list ());\n      }\n      break;\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in octave_lvalue::numel - please report this bug\");\n    }\n}\n\nvoid\noctave_lvalue::set_index (const std::string& t,\n                          const std::list<octave_value_list>& i)\n{\n  if (! m_idx.empty ())\n    error (\"invalid index expression in assignment\");\n\n  m_type = t;\n  m_idx = i;\n}\n\nbool\noctave_lvalue::index_is_empty () const\n{\n  bool retval = false;\n\n  if (m_idx.size () == 1)\n    {\n      octave_value_list tmp = m_idx.front ();\n\n      retval = (tmp.length () == 1 && tmp(0).isempty ());\n    }\n\n  return retval;\n}\n\nbool\noctave_lvalue::index_is_colon () const\n{\n  bool retval = false;\n\n  if (m_idx.size () == 1)\n    {\n      octave_value_list tmp = m_idx.front ();\n\n      retval = (tmp.length () == 1 && tmp(0).is_magic_colon ());\n    }\n\n  return retval;\n}\n\nvoid\noctave_lvalue::unary_op (octave_value::unary_op op)\n{\n  if (! is_black_hole ())\n    m_frame->non_const_unary_op (op, m_sym, m_type, m_idx);\n}\n\noctave_value\noctave_lvalue::value () const\n{\n  return (is_black_hole ()\n          ? octave_value () : m_frame->value (m_sym, m_type, m_idx));\n}\n\noctave_value\noctave_lvalue::eval_for_numel (const std::string& type,\n                               const std::list<octave_value_list>& idx) const\n{\n  octave_value retval;\n\n  try\n    {\n      retval = m_frame->varval (m_sym);\n\n      if (retval.is_constant () && ! idx.empty ())\n        retval = retval.subsref (type, idx);\n    }\n  catch (const execution_exception&)\n    {\n      // Ignore an error and treat it as undefined.  The error\n      // could happen because there is an index is out of range\n      // and we will be resizing a cell array.\n\n      interpreter& interp = __get_interpreter__ ();\n\n      interp.recover_from_exception ();\n\n      retval = octave_value ();\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/oct-lvalue.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_lvalue_h)\n#define octave_oct_lvalue_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"ovl.h\"\n#include \"stack-frame.h\"\n#include \"symrec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass octave_lvalue\n{\npublic:\n\n  octave_lvalue (const symbol_record& sr,\n                 const std::shared_ptr<stack_frame>& frame)\n    : m_sym (sr), m_frame (frame), m_black_hole (false),\n      m_type (), m_idx ()\n  { }\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (octave_lvalue)\n\n  bool is_black_hole () const { return m_black_hole; }\n\n  void mark_black_hole () { m_black_hole = true; }\n\n  bool is_defined () const;\n\n  bool is_undefined () const;\n\n  bool isstruct () const { return value().isstruct (); }\n\n  void define (const octave_value& v);\n\n  void assign (octave_value::assign_op, const octave_value&);\n\n  octave_idx_type numel () const;\n\n  void set_index (const std::string& t,\n                  const std::list<octave_value_list>& i);\n\n  void clear_index () { m_type = \"\"; m_idx.clear (); }\n\n  std::string index_type () const { return m_type; }\n\n  bool index_is_empty () const;\n\n  bool index_is_colon () const;\n\n  void unary_op (octave_value::unary_op op);\n\n  octave_value value () const;\n\nprivate:\n\n  octave_value eval_for_numel (const std::string& type, const std::list<octave_value_list>& idx) const;\n\n  //--------\n\n  symbol_record m_sym;\n\n  std::shared_ptr<stack_frame> m_frame;\n\n  bool m_black_hole;\n\n  std::string m_type;\n\n  std::list<octave_value_list> m_idx;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/oct-parse.yy",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Parser for Octave.\n\n// C decarations.\n\n%{\n\n// Uncomment to enable parser debugging\n// #define OCTAVE_PARSER_DEBUG 1\n#if defined (OCTAVE_PARSER_DEBUG)\n  // Magic variable used by Bison\n  #define OCTAVE_DEBUG 1\n#endif\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdio>\n#include <cstdlib>\n\n#include <iostream>\n#include <map>\n#include <sstream>\n\n#include \"Matrix.h\"\n#include \"cmd-edit.h\"\n#include \"cmd-hist.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"oct-env.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n\n#include \"Cell.h\"\n#include \"anon-fcn-validator.h\"\n#include \"builtin-defun-decls.h\"\n#include \"defun.h\"\n#include \"dynamic-ld.h\"\n#include \"error.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"lex.h\"\n#include \"load-path.h\"\n#include \"oct-sysdep.h\"\n#include \"oct-hist.h\"\n#include \"oct-map.h\"\n#include \"ov-classdef.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-usr-fcn.h\"\n#include \"ov-null-mat.h\"\n#include \"pager.h\"\n#include \"parse.h\"\n#include \"pt-all.h\"\n#include \"pt-eval.h\"\n#include \"separator-list.h\"\n#include \"symtab.h\"\n#include \"token.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\n// oct-parse.h must be included after pt-all.h\n#include \"oct-parse.h\"\n\nextern int octave_lex (YYSTYPE *, void *);\n\n// Forward declarations for some functions defined at the bottom of\n// the file.\n\nstatic void yyerror (octave::base_parser& parser, const char *s);\n\n// TRUE means that syntax errors will be shown with a caret symbol,\n// including when reading from a file.\nstatic bool Vdiagnostics_show_caret = true;\n\n#define lexer (parser.get_lexer ())\n#define scanner lexer.m_scanner\n\n// Previous versions of Octave used Bison's YYUSE macro to avoid\n// warnings about unused values in rules.  But that Bison macro was\n// apparently never intended to be public.  So define our own.  All we\n// need to do is mention the symantic value somewhere in the rule.  It\n// doesn't actually need to be used to avoid the Bison warning, so just\n// define this macro to discard its parameter.\n#define OCTAVE_YYUSE(...)\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // Disable this warning for code that is generated by Bison,\n   // including grammar rules.  Push the current state so we can\n   // restore the warning state prior to functions we define at\n   // the bottom of the file.\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n%}\n\n// Bison declarations.\n\n// The grammar currently has 9 shift/reduce conflicts.  Ensure that\n// we notice if that number changes.\n\n%expect 9\n\n// We are using the pure parser interface and the reentrant lexer\n// interface but the Octave parser and lexer are NOT properly\n// reentrant because both still use many global variables.  It should be\n// safe to create a parser object and call it while another parser\n// object is active (to parse a callback function while the main\n// interactive parser is waiting for input, for example) if you take\n// care to properly save and restore (typically with an unwind_protect\n// object) relevant global values before and after the nested call.\n\n%define api.pure\n// No spaces inside the braces for the prefix and push-pull definitions!\n%define api.prefix {octave_}\n%define api.push-pull both\n%parse-param { octave::base_parser& parser }\n%lex-param { void *lexer.scanner }\n\n%union\n{\n  int dummy_type;\n\n  // The type of the basic tokens returned by the lexer.\n  octave::token *tok;\n\n  // Lists of separators with optional comment lists attached.\n  octave::separator_list *sep_list_type;\n\n  // Types for the nonterminals we generate.\n  octave::tree *tree_type;\n  octave::tree_matrix *tree_matrix_type;\n  octave::tree_cell *tree_cell_type;\n  octave::tree_expression *tree_expression_type;\n  octave::tree_constant *tree_constant_type;\n  octave::tree_fcn_handle *tree_fcn_handle_type;\n  octave::tree_superclass_ref *tree_superclass_ref_type;\n  octave::tree_metaclass_query *tree_metaclass_query_type;\n  octave::tree_function_def *tree_function_def_type;\n  octave::tree_anon_fcn_handle *tree_anon_fcn_handle_type;\n  octave::tree_identifier *tree_identifier_type;\n  octave::tree_index_expression *tree_index_expression_type;\n  octave::tree_colon_expression *tree_colon_expression_type;\n  octave::tree_argument_list *tree_argument_list_type;\n  octave::tree_parameter_list *tree_parameter_list_type;\n  octave::tree_command *tree_command_type;\n  octave::tree_if_command *tree_if_command_type;\n  octave::tree_if_clause *tree_if_clause_type;\n  octave::tree_if_command_list *tree_if_command_list_type;\n  octave::tree_switch_command *tree_switch_command_type;\n  octave::tree_switch_case *tree_switch_case_type;\n  octave::tree_switch_case_list *tree_switch_case_list_type;\n  octave::tree_decl_elt *tree_decl_elt_type;\n  octave::tree_decl_init_list *tree_decl_init_list_type;\n  octave::tree_decl_command *tree_decl_command_type;\n  octave::tree_statement *tree_statement_type;\n  octave::tree_statement_list *tree_statement_list_type;\n  octave::tree_arguments_block *tree_arguments_block_type;\n  octave::tree_args_block_attribute_list *tree_args_block_attribute_list_type;\n  octave::tree_args_block_validation_list *tree_args_block_validation_list_type;\n  octave::tree_arg_size_spec *tree_arg_size_spec_type;\n  octave::tree_arg_validation *tree_arg_validation_type;\n  octave::tree_arg_validation_fcns *tree_arg_validation_fcns_type;\n  octave_user_function *octave_user_function_type;\n\n  octave::tree_classdef *tree_classdef_type;\n  octave::tree_classdef_attribute* tree_classdef_attribute_type;\n  octave::tree_classdef_attribute_list* tree_classdef_attribute_list_type;\n  octave::tree_classdef_superclass* tree_classdef_superclass_type;\n  octave::tree_classdef_superclass_list* tree_classdef_superclass_list_type;\n  octave::tree_classdef_body* tree_classdef_body_type;\n  octave::tree_classdef_property* tree_classdef_property_type;\n  octave::tree_classdef_property_list* tree_classdef_property_list_type;\n  octave::tree_classdef_properties_block* tree_classdef_properties_block_type;\n  octave::tree_classdef_method_list* tree_classdef_method_list_type;\n  octave::tree_classdef_methods_block* tree_classdef_methods_block_type;\n  octave::tree_classdef_event* tree_classdef_event_type;\n  octave::tree_classdef_event_list* tree_classdef_event_list_type;\n  octave::tree_classdef_events_block* tree_classdef_events_block_type;\n  octave::tree_classdef_enum* tree_classdef_enum_type;\n  octave::tree_classdef_enum_list* tree_classdef_enum_list_type;\n  octave::tree_classdef_enum_block* tree_classdef_enum_block_type;\n}\n\n// Tokens with position information.\n%token <tok> '=' ':' '-' '+' '*' '/' '~' '!'\n%token <tok> '(' ')' '[' ']' '{' '}' '.' '@'\n%token <tok> ',' ';' '\\n'\n%token <tok> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ\n%token <tok> EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ AND_EQ OR_EQ\n%token <tok> EXPR_AND_AND EXPR_OR_OR\n%token <tok> EXPR_AND EXPR_OR\n%token <tok> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT\n%token <tok> LEFTDIV EMUL EDIV ELEFTDIV\n%token <tok> HERMITIAN TRANSPOSE\n%token <tok> PLUS_PLUS MINUS_MINUS POW EPOW\n%token <tok> NUMBER\n// The result of a constant folding operation.\n%token <tok> CONSTANT\n%token <tok> STRUCT_ELT\n%token <tok> NAME\n%token <tok> END\n%token <tok> DQ_STRING SQ_STRING\n%token <tok> FOR PARFOR WHILE DO UNTIL\n%token <tok> SPMD\n%token <tok> IF ELSEIF ELSE\n%token <tok> SWITCH CASE OTHERWISE\n%token <tok> BREAK CONTINUE RETURN\n%token <tok> UNWIND CLEANUP\n%token <tok> TRY CATCH\n%token <tok> GLOBAL PERSISTENT\n%token <tok> FCN_HANDLE\n%token <tok> CLASSDEF\n%token <tok> PROPERTIES METHODS EVENTS ENUMERATION\n%token <tok> METAQUERY\n%token <tok> SUPERCLASSREF\n%token <tok> FQ_IDENT\n%token <tok> GET SET\n%token <tok> FUNCTION\n%token <tok> ARGUMENTS\n%token <tok> LEXICAL_ERROR\n%token <tok> END_OF_INPUT\n\n// Other tokens.\n%token <dummy_type> INPUT_FILE\n// %token VARARGIN VARARGOUT\n\n// Nonterminals we construct.\n%type <dummy_type> push_fcn_symtab push_script_symtab begin_file\n%type <dummy_type> stmt_begin anon_fcn_begin\n%type <dummy_type> parsing_local_fcns parse_error\n%type <tok> param_list_beg param_list_end\n%type <tok> function_beg classdef_beg arguments_beg indirect_ref_op\n%type <tok> properties_beg methods_beg events_beg enumeration_beg\n%type <sep_list_type> sep_no_nl opt_sep_no_nl sep opt_sep\n%type <tree_type> input\n%type <tree_constant_type> string constant magic_colon\n%type <tree_anon_fcn_handle_type> anon_fcn_handle\n%type <tree_fcn_handle_type> fcn_handle\n%type <tree_matrix_type> matrix_rows\n%type <tree_cell_type> cell_rows\n%type <tree_expression_type> matrix cell\n%type <tree_expression_type> primary_expr oper_expr power_expr\n%type <tree_expression_type> simple_expr colon_expr assign_expr expression\n%type <tree_expression_type> arg_name\n%type <tree_identifier_type> identifier fcn_name magic_tilde\n%type <tree_superclass_ref_type> superclass_identifier\n%type <tree_metaclass_query_type> meta_identifier\n%type <tree_index_expression_type> word_list_cmd\n%type <tree_argument_list_type> arg_list word_list assign_lhs\n%type <tree_argument_list_type> cell_or_matrix_row\n%type <tree_parameter_list_type> opt_param_list param_list\n%type <tree_parameter_list_type> param_list1 param_list2\n%type <tree_parameter_list_type> return_list return_list1\n%type <tree_command_type> command select_command loop_command\n%type <tree_command_type> jump_command spmd_command except_command\n%type <tree_function_def_type> function\n%type <tree_classdef_type> classdef\n%type <tree_command_type> file\n%type <tree_if_command_type> if_command\n%type <tree_if_command_list_type> if_clause_list\n%type <tree_if_clause_type> if_clause elseif_clause else_clause\n%type <tree_switch_command_type> switch_command\n%type <tree_switch_case_type> switch_case default_case\n%type <tree_switch_case_list_type> case_list1 case_list\n%type <tree_decl_elt_type> decl_elt param_list_elt\n%type <tree_decl_init_list_type> decl_init_list\n%type <tree_decl_command_type> declaration\n%type <tree_statement_type> statement function_end\n%type <tree_statement_list_type> simple_list simple_list1 list list1\n%type <tree_statement_list_type> statement_list opt_list\n%type <tree_statement_list_type> arguments_block_list function_body\n%type <tree_statement_list_type> opt_fcn_list fcn_list fcn_list1\n%type <tree_classdef_attribute_type> attr\n%type <tree_classdef_attribute_list_type> attr_list attr_list1\n%type <tree_classdef_superclass_type> superclass\n%type <tree_classdef_superclass_list_type> superclass_list superclass_list1\n%type <tree_classdef_body_type> class_body class_body1\n%type <tree_classdef_property_type> class_property\n%type <tree_classdef_property_list_type> property_list property_list1\n%type <tree_classdef_properties_block_type> properties_block\n%type <tree_classdef_method_list_type> method_list method_list1\n%type <tree_classdef_methods_block_type> methods_block\n%type <tree_classdef_event_type> class_event\n%type <tree_classdef_event_list_type> event_list event_list1\n%type <tree_classdef_events_block_type> events_block\n%type <tree_classdef_enum_type> class_enum\n%type <tree_classdef_enum_list_type> enum_list enum_list1\n%type <tree_classdef_enum_block_type> enum_block\n%type <tree_function_def_type> method_decl method\n%type <tree_arguments_block_type> arguments_block\n%type <tree_args_block_attribute_list_type> args_attr_list\n%type <tree_args_block_validation_list_type> args_validation_list\n%type <tree_arg_validation_type> arg_validation\n%type <tree_arg_size_spec_type> size_spec\n%type <tree_identifier_type> class_name\n%type <tree_arg_validation_fcns_type> validation_fcns\n%type <octave_user_function_type> method_decl1\n\n// Precedence and associativity.\n%right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ\n%left EXPR_OR_OR\n%left EXPR_AND_AND\n%left EXPR_OR\n%left EXPR_AND\n%left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT\n%left ':'\n%left '-' '+'\n%left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV\n%right UNARY '~' '!'\n%left POW EPOW HERMITIAN TRANSPOSE\n%right PLUS_PLUS MINUS_MINUS\n%left '(' '.' '{'\n\n// How to clean up if there is a parse error.  We handle deleting\n// individual tokens and comments separately.  The remaining items are\n// dynamically allocated parse tree objects that must be deleted.  Use\n// the wildcard case (<*>) to detect unhandled cases (for example, to\n// guard against a new semantic type that has been added but not\n// explicitly handled here).\n\n%destructor { } <tok>\n%destructor { } <>\n\n%destructor { delete $$; } <sep_list_type>\n\n%destructor { delete $$; } <tree_type>\n%destructor { delete $$; } <tree_matrix_type>\n%destructor { delete $$; } <tree_cell_type>\n%destructor { delete $$; } <tree_expression_type>\n%destructor { delete $$; } <tree_constant_type>\n%destructor { delete $$; } <tree_fcn_handle_type>\n%destructor { delete $$; } <tree_superclass_ref_type>\n%destructor { delete $$; } <tree_metaclass_query_type>\n%destructor { delete $$; } <tree_function_def_type>\n%destructor { delete $$; } <tree_anon_fcn_handle_type>\n%destructor { delete $$; } <tree_identifier_type>\n%destructor { delete $$; } <tree_index_expression_type>\n%destructor { delete $$; } <tree_argument_list_type>\n%destructor { delete $$; } <tree_parameter_list_type>\n%destructor { delete $$; } <tree_command_type>\n%destructor { delete $$; } <tree_if_command_type>\n%destructor { delete $$; } <tree_if_clause_type>\n%destructor { delete $$; } <tree_if_command_list_type>\n%destructor { delete $$; } <tree_switch_command_type>\n%destructor { delete $$; } <tree_switch_case_type>\n%destructor { delete $$; } <tree_switch_case_list_type>\n%destructor { delete $$; } <tree_decl_elt_type>\n%destructor { delete $$; } <tree_decl_init_list_type>\n%destructor { delete $$; } <tree_decl_command_type>\n%destructor { delete $$; } <tree_statement_type>\n%destructor { delete $$; } <tree_statement_list_type>\n%destructor { delete $$; } <tree_arguments_block_type>\n%destructor { delete $$; } <tree_args_block_attribute_list_type>\n%destructor { delete $$; } <tree_args_block_validation_list_type>\n%destructor { delete $$; } <tree_arg_validation_type>\n%destructor { delete $$; } <tree_arg_size_spec_type>\n%destructor { delete $$; } <tree_arg_validation_fcns_type>\n%destructor { delete $$; } <octave_user_function_type>\n\n%destructor { delete $$; } <tree_classdef_type>\n%destructor { delete $$; } <tree_classdef_attribute_type>\n%destructor { delete $$; } <tree_classdef_attribute_list_type>\n%destructor { delete $$; } <tree_classdef_superclass_type>\n%destructor { delete $$; } <tree_classdef_superclass_list_type>\n%destructor { delete $$; } <tree_classdef_body_type>\n%destructor { delete $$; } <tree_classdef_property_type>\n%destructor { delete $$; } <tree_classdef_property_list_type>\n%destructor { delete $$; } <tree_classdef_properties_block_type>\n%destructor { delete $$; } <tree_classdef_method_list_type>\n%destructor { delete $$; } <tree_classdef_methods_block_type>\n%destructor { delete $$; } <tree_classdef_event_type>\n%destructor { delete $$; } <tree_classdef_event_list_type>\n%destructor { delete $$; } <tree_classdef_events_block_type>\n%destructor { delete $$; } <tree_classdef_enum_type>\n%destructor { delete $$; } <tree_classdef_enum_list_type>\n%destructor { delete $$; } <tree_classdef_enum_block_type>\n\n// Defining a generic destructor generates a warning if destructors are\n// already explicitly declared for all types.\n//\n// %destructor {\n//    warning_with_id (\"Octave:parser-destructor\", \"possible memory leak in cleanup following parse error\");\n// } <*>\n\n// Where to start.\n%start input\n\n%%\n\n// ==============================\n// Statements and statement lists\n// ==============================\n\ninput           : simple_list '\\n'\n                  {\n                    OCTAVE_YYUSE ($2);\n\n                    $$ = nullptr;\n\n                    if (! parser.finish_input ($1))\n                      YYABORT;\n                    else\n                      YYACCEPT;\n                  }\n                | simple_list END_OF_INPUT\n                  {\n                    OCTAVE_YYUSE ($2);\n\n                    $$ = nullptr;\n\n                    if (! parser.finish_input ($1, true))\n                      YYABORT;\n                    else\n                      YYACCEPT;\n                  }\n                | file\n                  {\n                    lexer.m_end_of_input = true;\n\n                    $$ = $1;\n                    YYACCEPT;\n                  }\n                | parse_error\n                  {\n                    $$ = nullptr;\n                    YYABORT;\n                  }\n                ;\n\nsimple_list     : opt_sep_no_nl\n                  {\n                    // FIXME: should we return an empty statement list\n                    // with the separators attached?  For now, delete\n                    // the unused list.\n                    delete $1;\n\n                    $$ = nullptr;\n                  }\n                | simple_list1 opt_sep_no_nl\n                  {\n                    $$ = parser.set_stmt_print_flag ($1, $2, false);\n\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n                  }\n                ;\n\nsimple_list1    : statement\n                  { $$ = parser.make_statement_list ($1); }\n                | simple_list1 sep_no_nl statement\n                  { $$ = parser.append_statement_list ($1, $2, $3, false); }\n                ;\n\nstatement_list  : opt_sep opt_list\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $1;\n\n                    $$ = $2;\n                  }\n                ;\n\nopt_list        : // empty\n                  { $$ = nullptr; }\n                | list\n                  { $$ = $1; }\n                ;\n\nlist            : list1 opt_sep\n                  {\n                    $$ = parser.set_stmt_print_flag ($1, $2, true);\n\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n                  }\n                ;\n\nlist1           : statement\n                  { $$ = parser.make_statement_list ($1); }\n                | list1 sep statement\n                  { $$ = parser.append_statement_list ($1, $2, $3, true); }\n                ;\n\nopt_fcn_list    : // empty\n                  { $$ = nullptr; }\n                | fcn_list\n                  { $$ = $1; }\n                ;\n\nfcn_list        : fcn_list1 opt_sep\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    $$ = $1;\n                  }\n                ;\n\nfcn_list1       : function\n                  { $$ = parser.make_function_def_list ($1); }\n                | fcn_list1 opt_sep function\n                  { $$ = parser.append_function_def_list ($1, $2, $3); }\n                ;\n\nstatement       : expression\n                  { $$ = parser.make_statement ($1); }\n                | command\n                  { $$ = parser.make_statement ($1); }\n                | word_list_cmd\n                  { $$ = parser.make_statement ($1); }\n                ;\n\n// =================\n// Word-list command\n// =================\n\n// These are not really like expressions since they can't appear on\n// the RHS of an assignment.  But they are also not like commands (IF,\n// WHILE, etc.\n\nword_list_cmd   : identifier word_list\n                  {\n                    if (! ($$ = parser.make_word_list_command ($1, $2)))\n                      {\n                        // make_index_expression deleted $1 and $2.\n                        YYABORT;\n                      }\n                  }\n                ;\n\nword_list       : string\n                  { $$ = parser.make_argument_list ($1); }\n                | word_list string\n                  { $$ = parser.append_argument_list ($1, $2); }\n                ;\n\n// ===========\n// Expressions\n// ===========\n\nidentifier      : NAME\n                  { $$ = parser.make_identifier ($1); }\n                ;\n\nsuperclass_identifier\n                : SUPERCLASSREF\n                  { $$ = parser.make_superclass_ref ($1); }\n                ;\n\nmeta_identifier : METAQUERY\n                  { $$ = parser.make_metaclass_query ($1); }\n                ;\n\nstring          : DQ_STRING\n                  { $$ = parser.make_constant ($1); }\n                | SQ_STRING\n                  { $$ = parser.make_constant ($1); }\n                ;\n\nconstant        : NUMBER\n                  { $$ = parser.make_constant ($1); }\n                | string\n                  { $$ = $1; }\n                ;\n\nmatrix          : '[' matrix_rows ']'\n                  { $$ = parser.finish_matrix ($1, $2, $3); }\n                ;\n\nmatrix_rows     : cell_or_matrix_row\n                  { $$ = parser.make_matrix ($1); }\n                | matrix_rows ';' cell_or_matrix_row\n                  { $$ = parser.append_matrix_row ($1, $2, $3); }\n                ;\n\ncell            : '{' cell_rows '}'\n                  { $$ = parser.finish_cell ($1, $2, $3); }\n                ;\n\ncell_rows       : cell_or_matrix_row\n                  { $$ = parser.make_cell ($1); }\n                | cell_rows ';' cell_or_matrix_row\n                  { $$ = parser.append_cell_row ($1, $2, $3); }\n                ;\n\n// tree_argument_list objects can't be empty or have leading or trailing\n// commas, but those are all allowed in matrix and cell array rows.\n\n// FIXME: is tree_argument_list the best object for this purpose, or\n// should we have a separate one intended specifically to represent the\n// list of objects that make up elements in cell and matrix expressions?\n\ncell_or_matrix_row\n                : // empty\n                  { $$ = nullptr; }\n                | ','\n                  {\n                    // FIXME: Need to capture separator token info here.\n                    OCTAVE_YYUSE ($1);\n\n                    $$ = nullptr;\n                  }\n                | arg_list\n                  { $$ = $1; }\n                | arg_list ','\n                  {\n                    // FIXME: Need to capture separator token info here.\n                    OCTAVE_YYUSE ($2);\n\n                    $$ = $1;\n                  }\n                | ',' arg_list\n                  {\n                    // FIXME: Need to capture separator token info here.\n                    OCTAVE_YYUSE ($1);\n\n                    $$ = $2;\n                  }\n                | ',' arg_list ','\n                  {\n                    // FIXME: Need to capture separator token info here.\n                    OCTAVE_YYUSE ($1, $3);\n\n                    $$ = $2;\n                  }\n                ;\n\nfcn_handle      : FCN_HANDLE\n                  { $$ = parser.make_fcn_handle ($1); }\n                ;\n\n// Note that we are deliberately not setting the beginning of statement\n// flag after recognizing the parameter list because we don't want to\n// accept word list commands in anonymous function bodies.\n\nanon_fcn_handle : '@' param_list anon_fcn_begin expression\n                  {\n                    if (! ($$ = parser.make_anon_fcn_handle ($1, $2, $4)))\n                      {\n                        // make_anon_fcn_handle deleted $2 and $4.\n                        YYABORT;\n                      }\n\n                    lexer.m_parsing_anon_fcn_body = false;\n                    lexer.m_nesting_level.remove ();\n                  }\n                | '@' param_list anon_fcn_begin error\n                  {\n                    OCTAVE_YYUSE ($1, $2);\n\n                    lexer.m_parsing_anon_fcn_body = false;\n\n                    $$ = nullptr;\n\n                    parser.bison_error (\"anonymous function bodies must be single expressions\");\n                    YYABORT;\n                  }\n                ;\n\nprimary_expr    : identifier\n                  { $$ = $1; }\n                | constant\n                  { $$ = $1; }\n                | fcn_handle\n                  { $$ = $1; }\n                | matrix\n                  {\n                    lexer.m_looking_at_matrix_or_assign_lhs = false;\n                    $$ = $1;\n                  }\n                | cell\n                  { $$ = $1; }\n                | meta_identifier\n                  { $$ = $1; }\n                | superclass_identifier\n                  { $$ = $1; }\n                | '(' expression ')'\n                  { $$ = $2->mark_in_delims (*($1), *($3)); }\n                ;\n\nmagic_colon     : ':'\n                  { $$ = parser.make_constant ($1); }\n                ;\n\nmagic_tilde     : '~'\n                  { $$ = parser.make_black_hole ($1); }\n                ;\n\narg_list        : expression\n                  { $$ = parser.make_argument_list ($1); }\n                | magic_colon\n                  { $$ = parser.make_argument_list ($1); }\n                | magic_tilde\n                  { $$ = parser.make_argument_list ($1); }\n                | arg_list ',' magic_colon\n                  { $$ = parser.append_argument_list ($1, $2, $3); }\n                | arg_list ',' magic_tilde\n                  { $$ = parser.append_argument_list ($1, $2, $3); }\n                | arg_list ',' expression\n                  { $$ = parser.append_argument_list ($1, $2, $3); }\n                ;\n\nindirect_ref_op : '.'\n                  {\n                    lexer.m_looking_at_indirect_ref = true;\n                    $$ = $1;\n                  }\n                ;\n\noper_expr       : primary_expr\n                  { $$ = $1; }\n                | oper_expr PLUS_PLUS\n                  { $$ = parser.make_postfix_op ($1, $2); }\n                | oper_expr MINUS_MINUS\n                  { $$ = parser.make_postfix_op ($1, $2); }\n                | oper_expr '(' ')'\n                  {\n                    if (! ($$ = parser.make_index_expression ($1, $2, nullptr, $3, '(')))\n                      {\n                        // make_index_expression deleted $1.\n                        YYABORT;\n                      }\n                  }\n                | oper_expr '(' arg_list ')'\n                  {\n                    if (! ($$ = parser.make_index_expression ($1, $2, $3, $4, '(')))\n                      {\n                        // make_index_expression deleted $1 and $3.\n                        YYABORT;\n                      }\n                  }\n                | oper_expr '{' '}'\n                  {\n                    if (! ($$ = parser.make_index_expression ($1, $2, nullptr, $3, '{')))\n                      {\n                        // make_index_expression deleted $1.\n                        YYABORT;\n                      }\n                  }\n                | oper_expr '{' arg_list '}'\n                  {\n                    if (! ($$ = parser.make_index_expression ($1, $2, $3, $4, '{')))\n                      {\n                        // make_index_expression deleted $1 and $3.\n                        YYABORT;\n                      }\n                  }\n                | oper_expr HERMITIAN\n                  { $$ = parser.make_postfix_op ($1, $2); }\n                | oper_expr TRANSPOSE\n                  { $$ = parser.make_postfix_op ($1, $2); }\n                | oper_expr indirect_ref_op STRUCT_ELT\n                  { $$ = parser.make_indirect_ref ($1, $2, $3); }\n                | oper_expr indirect_ref_op '(' expression ')'\n                  { $$ = parser.make_indirect_ref ($1, $2, $3, $4, $5); }\n                | PLUS_PLUS oper_expr %prec UNARY\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | MINUS_MINUS oper_expr %prec UNARY\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | '~' oper_expr %prec UNARY\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | '!' oper_expr %prec UNARY\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | '+' oper_expr %prec UNARY\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | '-' oper_expr %prec UNARY\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | oper_expr POW power_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | oper_expr EPOW power_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | oper_expr '+' oper_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | oper_expr '-' oper_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | oper_expr '*' oper_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | oper_expr '/' oper_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | oper_expr EMUL oper_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | oper_expr EDIV oper_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | oper_expr LEFTDIV oper_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | oper_expr ELEFTDIV oper_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                ;\n\npower_expr      : primary_expr\n                  { $$ = $1; }\n                | power_expr PLUS_PLUS\n                  { $$ = parser.make_postfix_op ($1, $2); }\n                | power_expr MINUS_MINUS\n                  { $$ = parser.make_postfix_op ($1, $2); }\n                | power_expr '(' ')'\n                  {\n                    if (! ($$ = parser.make_index_expression ($1, $2, nullptr, $3, '(')))\n                      {\n                        // make_index_expression deleted $1.\n                        YYABORT;\n                      }\n                  }\n                | power_expr '(' arg_list ')'\n                  {\n                    if (! ($$ = parser.make_index_expression ($1, $2, $3, $4, '(')))\n                      {\n                        // make_index_expression deleted $1 and $3.\n                        YYABORT;\n                      }\n                  }\n                | power_expr '{' '}'\n                  {\n                    if (! ($$ = parser.make_index_expression ($1, $2, nullptr, $3, '{')))\n                      {\n                        // make_index_expression deleted $1.\n                        YYABORT;\n                      }\n                  }\n                | power_expr '{' arg_list '}'\n                  {\n                    if (! ($$ = parser.make_index_expression ($1, $2, $3, $4, '{')))\n                      {\n                        // make_index_expression deleted $1 and $3.\n                        YYABORT;\n                      }\n                  }\n                | power_expr indirect_ref_op STRUCT_ELT\n                  { $$ = parser.make_indirect_ref ($1, $2, $3); }\n                | power_expr indirect_ref_op '(' expression ')'\n                  { $$ = parser.make_indirect_ref ($1, $2, $3, $4, $5); }\n                | PLUS_PLUS power_expr %prec POW\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | MINUS_MINUS power_expr %prec POW\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | '~' power_expr %prec POW\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | '!' power_expr %prec POW\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | '+' power_expr %prec POW\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                | '-' power_expr %prec POW\n                  { $$ = parser.make_prefix_op ($1, $2); }\n                ;\n\ncolon_expr      : oper_expr ':' oper_expr\n                  {\n                    if (! ($$ = parser.make_colon_expression ($1, $2, $3)))\n                      {\n                        // make_colon_expression deleted $1 and $3.\n                        YYABORT;\n                      }\n                  }\n                | oper_expr ':' oper_expr ':' oper_expr\n                  {\n                    if (! ($$ = parser.make_colon_expression ($1, $2, $3, $4, $5)))\n                      {\n                        // make_colon_expression deleted $1, $3, and $5.\n                        YYABORT;\n                      }\n                  }\n                ;\n\nsimple_expr     : oper_expr\n                  { $$ = $1; }\n                | colon_expr\n                  { $$ = $1; }\n                | simple_expr EXPR_LT simple_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | simple_expr EXPR_LE simple_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | simple_expr EXPR_EQ simple_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | simple_expr EXPR_GE simple_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | simple_expr EXPR_GT simple_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | simple_expr EXPR_NE simple_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | simple_expr EXPR_AND simple_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | simple_expr EXPR_OR simple_expr\n                  { $$ = parser.make_binary_op ($1, $2, $3); }\n                | simple_expr EXPR_AND_AND simple_expr\n                  { $$ = parser.make_boolean_op ($1, $2, $3); }\n                | simple_expr EXPR_OR_OR simple_expr\n                  { $$ = parser.make_boolean_op ($1, $2, $3); }\n                ;\n\nassign_lhs      : simple_expr\n                  {\n                    if (! ($$ = parser.validate_matrix_for_assignment ($1)))\n                      {\n                        // validate_matrix_for_assignment deleted $1.\n                        YYABORT;\n                      }\n\n                    lexer.m_looking_at_matrix_or_assign_lhs = false;\n                  }\n                ;\n\nassign_expr     : assign_lhs '=' expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs ADD_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs SUB_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs MUL_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs DIV_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs LEFTDIV_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs POW_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs EMUL_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs EDIV_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs ELEFTDIV_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs EPOW_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs AND_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                | assign_lhs OR_EQ expression\n                  { $$ = parser.make_assign_op ($1, $2, $3); }\n                ;\n\nexpression      : simple_expr\n                  {\n                    if ($1 && ($1->is_matrix () || $1->iscell ()))\n                      {\n                        if (parser.validate_array_list ($1))\n                          $$ = $1;\n                        else\n                          {\n                            delete $1;\n                            YYABORT;\n                          }\n                      }\n                    else\n                      $$ = $1;\n                  }\n                | assign_expr\n                  {\n                    if (! $1)\n                      YYABORT;\n\n                    $$ = $1;\n                  }\n                | anon_fcn_handle\n                  { $$ = $1; }\n                ;\n\n// ================================================\n// Commands, declarations, and function definitions\n// ================================================\n\ncommand         : declaration\n                  { $$ = $1; }\n                | select_command\n                  { $$ = $1; }\n                | loop_command\n                  { $$ = $1; }\n                | jump_command\n                  { $$ = $1; }\n                | spmd_command\n                  { $$ = $1; }\n                | except_command\n                  { $$ = $1; }\n                | function\n                  { $$ = $1; }\n                ;\n\n// ======================\n// Declaration statements\n// ======================\n\ndeclaration     : GLOBAL decl_init_list\n                  {\n                    $$ = parser.make_decl_command ($1, $2);\n                    lexer.m_looking_at_decl_list = false;\n                  }\n                | PERSISTENT decl_init_list\n                  {\n                    $$ = parser.make_decl_command ($1, $2);\n                    lexer.m_looking_at_decl_list = false;\n                  }\n                ;\n\ndecl_init_list   : decl_elt\n                  { $$ = parser.make_decl_init_list ($1); }\n                | decl_init_list decl_elt\n                  { $$ = parser.append_decl_init_list ($1, $2); }\n                ;\n\ndecl_elt        : identifier\n                  { $$ = parser.make_decl_elt ($1); }\n                | identifier '=' expression\n                  { $$ = parser.make_decl_elt ($1, $2, $3); }\n                ;\n\n// ====================\n// Selection statements\n// ====================\n\nselect_command  : if_command\n                  { $$ = $1; }\n                | switch_command\n                  { $$ = $1; }\n                ;\n\n// ============\n// If statement\n// ============\n\nif_command      : if_clause_list else_clause END\n                  {\n                    if (! ($$ = parser.finish_if_command ($1, $2, $3)))\n                      {\n                        // finish_if_command deleted $1 and $2.\n                        YYABORT;\n                      }\n                  }\n                ;\n\nif_clause_list  : if_clause\n                  { $$ = parser.start_if_command ($1); }\n                | if_clause_list elseif_clause\n                  { $$ = parser.append_if_clause ($1, $2); }\n                ;\n\nif_clause       : IF opt_sep expression stmt_begin statement_list\n                  { $$ = parser.make_if_clause ($1, $2, $3, $5); }\n                ;\n\nelseif_clause   : ELSEIF opt_sep expression stmt_begin statement_list\n                  { $$ = parser.make_if_clause ($1, $2, $3, $5); }\n                ;\n\nelse_clause     : // empty\n                  { $$ = nullptr; }\n                | ELSE statement_list\n                  { $$ = parser.make_if_clause ($1, nullptr, nullptr, $2); }\n                ;\n\n// ================\n// Switch statement\n// ================\n\nswitch_command  : SWITCH expression opt_sep case_list END\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $3;\n\n                    if (! ($$ = parser.finish_switch_command ($1, $2, $4, $5)))\n                      {\n                        // finish_switch_command deleted $2 and $4.\n                        YYABORT;\n                      }\n                  }\n                ;\n\ncase_list       : // empty\n                  { $$ = nullptr; }\n                | default_case\n                  { $$ = parser.make_switch_case_list ($1); }\n                | case_list1\n                  { $$ = $1; }\n                | case_list1 default_case\n                  { $$ = parser.append_switch_case ($1, $2); }\n                ;\n\ncase_list1      : switch_case\n                  { $$ = parser.make_switch_case_list ($1); }\n                | case_list1 switch_case\n                  { $$ = parser.append_switch_case ($1, $2); }\n                ;\n\nswitch_case     : CASE opt_sep expression stmt_begin statement_list\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    $$ = parser.make_switch_case ($1, $3, $5);\n                  }\n                ;\n\ndefault_case    : OTHERWISE statement_list\n                  { $$ = parser.make_default_switch_case ($1, $2); }\n                ;\n\n// =======\n// Looping\n// =======\n\nloop_command    : WHILE expression stmt_begin statement_list END\n                  {\n                    parser.maybe_convert_to_braindead_shortcircuit ($2);\n\n                    if (! ($$ = parser.make_while_command ($1, $2, $4, $5)))\n                      {\n                        // make_while_command deleted $2 and $4.\n                        YYABORT;\n                      }\n                  }\n                | DO statement_list UNTIL expression\n                  {\n                    $$ = parser.make_do_until_command ($1, $2, $3, $4);\n                  }\n                | FOR assign_lhs '=' expression stmt_begin statement_list END\n                  {\n                    if (! ($$ = parser.make_for_command ($1, nullptr, $2, $3, $4, nullptr, nullptr, nullptr, $6, $7)))\n                      {\n                        // make_for_command deleted $2, $4, and $6.\n                        YYABORT;\n                      }\n                  }\n                | FOR '(' assign_lhs '=' expression ')' statement_list END\n                  {\n                    // FIXME: Need to capture token info here.\n                    OCTAVE_YYUSE ($2, $4, $6);\n\n                    if (! ($$ = parser.make_for_command ($1, $2, $3, $4, $5, nullptr, nullptr, $6, $7, $8)))\n                      {\n                        // make_for_command deleted $3, $5, and $7.\n                        YYABORT;\n                      }\n                  }\n                | PARFOR assign_lhs '=' expression stmt_begin statement_list END\n                  {\n                    // FIXME: Need to capture token info here.\n                    OCTAVE_YYUSE ($3);\n\n                    if (! ($$ = parser.make_for_command ($1, nullptr, $2, $3, $4, nullptr, nullptr, nullptr, $6, $7)))\n                      {\n                        // make_for_command deleted $2, $4, and $6.\n                        YYABORT;\n                      }\n                  }\n                | PARFOR '(' assign_lhs '=' expression ',' expression ')' statement_list END\n                  {\n                    // FIXME: Need to capture token info here.\n                    OCTAVE_YYUSE ($2, $4, $6, $8);\n\n                    if (! ($$ = parser.make_for_command ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)))\n                      {\n                        // make_for_command deleted $3, $5, $7, and $9.\n                        YYABORT;\n                      }\n                  }\n                ;\n\n// =======\n// Jumping\n// =======\n\njump_command    : BREAK\n                  {\n                    if (! ($$ = parser.make_break_command ($1)))\n                      YYABORT;\n                  }\n                | CONTINUE\n                  {\n                    if (! ($$ = parser.make_continue_command ($1)))\n                      YYABORT;\n                  }\n                | RETURN\n                  { $$ = parser.make_return_command ($1); }\n                ;\n\n// =======================\n// Parallel execution pool\n// =======================\n\nspmd_command    : SPMD statement_list END\n                  {\n                    if (! ($$ = parser.make_spmd_command ($1, $2, $3)))\n                      {\n                        // make_spmd_command deleted $2.\n                        YYABORT;\n                      }\n                  }\n                ;\n\n// ==========\n// Exceptions\n// ==========\n\nexcept_command  : UNWIND statement_list CLEANUP statement_list END\n                  {\n                    if (! ($$ = parser.make_unwind_command ($1, $2, $3, $4, $5)))\n                      {\n                        // make_unwind_command deleted $2 and $4.\n                        YYABORT;\n                      }\n                  }\n                | TRY statement_list CATCH opt_sep opt_list END\n                  {\n                    if (! ($$ = parser.make_try_command ($1, $2, $3, $4, $5, $6)))\n                      {\n                        // make_try_command deleted $2, $4, and $5.\n                        YYABORT;\n                      }\n                  }\n                | TRY statement_list END\n                  {\n                    if (! ($$ = parser.make_try_command ($1, $2, nullptr, nullptr, nullptr, $3)))\n                      {\n                        // make_try_command deleted $2.\n                        YYABORT;\n                      }\n                  }\n                ;\n\n// ===========================================\n// Some 'subroutines' for function definitions\n// ===========================================\n\npush_fcn_symtab : // empty\n                  {\n                    if (! parser.push_fcn_symtab ())\n                      YYABORT;\n\n                    $$ = 0;\n                  }\n                ;\n\n// ===========================\n// List of function parameters\n// ===========================\n\nparam_list_beg  : '('\n                  {\n                    lexer.m_looking_at_parameter_list = true;\n                    lexer.m_arguments_is_keyword = false;\n\n                    if (lexer.m_looking_at_function_handle)\n                      {\n                        // Will get a real name later.\n                        lexer.m_symtab_context.push (octave::symbol_scope (\"parser:param_list_beg\"));\n                        lexer.m_looking_at_function_handle--;\n                        lexer.m_looking_at_anon_fcn_args = true;\n                      }\n\n                    $$ = $1;\n                  }\n                ;\n\nparam_list_end  : ')'\n                  {\n                    lexer.m_looking_at_parameter_list = false;\n                    lexer.m_arguments_is_keyword = true;\n                    lexer.m_looking_for_object_index = false;\n                    $$ = $1;\n                  }\n                ;\n\nopt_param_list  : // empty\n                  { $$ = nullptr; }\n                | param_list\n                  { $$ = $1; }\n                ;\n\nparam_list      : param_list_beg param_list1 param_list_end\n                  {\n                    if ($2)\n                      lexer.mark_as_variables ($2->variable_names ());\n\n                    $$ = $2->mark_in_delims (*($1), *($3));\n                  }\n                | param_list_beg error\n                  {\n                    OCTAVE_YYUSE ($1);\n\n                    $$ = nullptr;\n\n                    parser.bison_error (\"invalid parameter list\");\n                    YYABORT;\n                  }\n                ;\n\nparam_list1     : // empty\n                  { $$ = parser.make_parameter_list (octave::tree_parameter_list::in); }\n                | param_list2\n                  {\n                    $1->mark_as_formal_parameters ();\n\n                    if (parser.validate_param_list ($1, octave::tree_parameter_list::in))\n                      {\n                        lexer.mark_as_variables ($1->variable_names ());\n                        $$ = $1;\n                      }\n                    else\n                      {\n                        delete $1;\n                        YYABORT;\n                      }\n                  }\n                ;\n\nparam_list2     : param_list_elt\n                  { $$ = parser.make_parameter_list (octave::tree_parameter_list::in, $1); }\n                | param_list2 ',' param_list_elt\n                  { $$ = parser.append_parameter_list ($1, $2, $3); }\n                ;\n\nparam_list_elt  : decl_elt\n                  { $$ = $1; }\n                | magic_tilde\n                  { $$ = parser.make_decl_elt ($1); }\n                ;\n\n// ===================================\n// List of function return value names\n// ===================================\n\nreturn_list     : '[' ']'\n                  {\n                    lexer.m_looking_at_return_list = false;\n\n                    octave::tree_parameter_list *tmp = parser.make_parameter_list (octave::tree_parameter_list::out);\n\n                    $$ = tmp->mark_in_delims (*($1), *($2));\n                  }\n                | identifier\n                  {\n                    lexer.m_looking_at_return_list = false;\n\n                    octave::tree_parameter_list *tmp = parser.make_parameter_list (octave::tree_parameter_list::out, $1);\n\n                    // Even though this parameter list can contain only\n                    // a single identifier, we still need to validate it\n                    // to check for varargin or varargout.\n\n                    if (parser.validate_param_list (tmp, octave::tree_parameter_list::out))\n                      $$ = tmp;\n                    else\n                      {\n                        delete tmp;\n                        YYABORT;\n                      }\n                  }\n                | '[' return_list1 ']'\n                  {\n                    lexer.m_looking_at_return_list = false;\n\n                    // Check for duplicate parameter names, varargin,\n                    // or varargout.\n\n                    if (parser.validate_param_list ($2, octave::tree_parameter_list::out))\n                      $$ = $2->mark_in_delims (*($1), *($3));\n                    else\n                      {\n                        delete $2;\n                        YYABORT;\n                      }\n                  }\n                ;\n\nreturn_list1    : identifier\n                  { $$ = parser.make_parameter_list (octave::tree_parameter_list::out, $1); }\n                | return_list1 ',' identifier\n                  { $$ = parser.append_parameter_list ($1, $2, $3); }\n                ;\n\n// =======================\n// Script or function file\n// =======================\n\nparsing_local_fcns\n                : // empty\n                  { parser.parsing_local_functions (true); }\n                ;\n\npush_script_symtab : // empty\n                  {\n                    $$ = 0;\n\n                    // This scope may serve as the parent scope for local\n                    // functions in classdef files..\n                    lexer.m_symtab_context.push (octave::symbol_scope (\"parser:push_script_symtab\"));\n                  }\n                ;\n\nbegin_file      : push_script_symtab INPUT_FILE\n                  { $$ = 0; }\n                ;\n\nfile            : begin_file statement_list END_OF_INPUT\n                  {\n                    if (lexer.m_reading_fcn_file)\n                      {\n                        // Delete the dummy statement_list we created\n                        // after parsing the function.  Any function\n                        // definitions found in the file have already\n                        // been stored in the symbol table or in\n                        // base_parser::m_primary_fcn.\n\n                        // Unused symbol table context.\n                        lexer.m_symtab_context.pop ();\n\n                        delete $2;\n                      }\n                    else\n                      {\n                        octave::tree_statement *end_of_script = parser.make_end (\"endscript\", true, $3);\n\n                        parser.make_script ($2, end_of_script);\n                      }\n\n                    if (! parser.validate_primary_fcn ())\n                      YYABORT;\n\n                    $$ = nullptr;\n                  }\n                | begin_file opt_sep classdef parsing_local_fcns opt_sep opt_fcn_list END_OF_INPUT\n                  {\n                    // We need to skip whitespace before the classdef\n                    // keyword.  The opt_sep rule is more liberal than\n                    // we need to be because it accepts ';' and ',' in\n                    // addition to '\\n', but we need to use it to avoid\n                    // creating a reduce/reduce conflict with the rule\n                    // above.  Matching the extra ';' and ',' characters\n                    // doesn't cause trouble because the lexer ensures\n                    // that classdef is the first token in the file.\n\n                    // FIXME: Need to capture separator lists here.\n                    // For now, delete the unused lists.\n                    delete $2;\n                    delete $5;\n\n                    // Unused symbol table context.\n                    lexer.m_symtab_context.pop ();\n\n                    if (! parser.finish_classdef_file ($3, $6, $7))\n                      YYABORT;\n\n                    $$ = nullptr;\n                  }\n                ;\n\n// ===================\n// Function definition\n// ===================\n\nfunction_beg    : push_fcn_symtab FUNCTION\n                  {\n                    if (lexer.m_reading_classdef_file || lexer.m_parsing_classdef)\n                      lexer.m_maybe_classdef_get_set_method = true;\n\n                    $$ = $2;\n                  }\n                ;\n\nfcn_name        : identifier\n                  {\n                    if (! ($$ = parser.make_fcn_name ($1)))\n                      {\n                        // make_fcn_name deleted $1.\n                        YYABORT;\n                      }\n\n                    lexer.m_arguments_is_keyword = true;\n                  }\n                | GET '.' identifier\n                  {\n                    $$ = $3->mark_get_set (*($1), *($2));\n\n                    lexer.m_parsed_function_name.top () = true;\n                    lexer.m_maybe_classdef_get_set_method = false;\n                    lexer.m_parsing_classdef_get_method = true;\n                    lexer.m_arguments_is_keyword = true;\n                  }\n                | SET '.' identifier\n                  {\n                    $$ = $3->mark_get_set (*($1), *($2));\n\n                    lexer.m_parsed_function_name.top () = true;\n                    lexer.m_maybe_classdef_get_set_method = false;\n                    lexer.m_parsing_classdef_set_method = true;\n                    lexer.m_arguments_is_keyword = true;\n                  }\n                ;\n\nfunction_end    : END\n                  {\n                    parser.endfunction_found (true);\n\n                    if (parser.end_token_ok ($1, octave::token::function_end))\n                      $$ = parser.make_end (\"endfunction\", false, $1);\n                    else\n                      {\n                        parser.end_token_error ($1, octave::token::function_end);\n                        YYABORT;\n                      }\n                  }\n                | END_OF_INPUT\n                  {\n// A lot of tests are based on the assumption that this is OK\n//                  if (lexer.m_reading_script_file)\n//                    {\n//                      parser.bison_error (\"function body open at end of script\");\n//                      YYABORT;\n//                    }\n\n                    if (parser.endfunction_found ())\n                      {\n                        parser.bison_error (\"inconsistent function endings -- \"\n                                 \"if one function is explicitly ended, \"\n                                 \"so must all the others\");\n                        YYABORT;\n                      }\n\n                    if (! (lexer.m_reading_fcn_file || lexer.m_reading_script_file\n                           || lexer.input_from_eval_string ()))\n                      {\n                        parser.bison_error (\"function body open at end of input\");\n                        YYABORT;\n                      }\n\n                    if (lexer.m_reading_classdef_file)\n                      {\n                        parser.bison_error (\"classdef body open at end of input\");\n                        YYABORT;\n                      }\n\n                    $$ = parser.make_end (\"endfunction\", true, $1);\n                  }\n                ;\n\nfunction        : function_beg fcn_name opt_param_list function_body function_end\n                  {\n                    $$ = parser.make_function ($1, nullptr, nullptr, $2, $3, $4, $5);\n                  }\n                | function_beg return_list '=' fcn_name opt_param_list function_body function_end\n                  {\n                    $$ = parser.make_function ($1, $2, $3, $4, $5, $6, $7);\n                  }\n                ;\n\nfunction_body   : statement_list\n                  {\n                    $$ = $1;\n                  }\n                | opt_sep arguments_block_list statement_list\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $1;\n\n                    $$ = parser.append_function_body ($2, $3);\n                  }\n                ;\n\narguments_block_list\n                : arguments_block\n                  {\n                    octave::tree_statement *stmt = parser.make_statement ($1);\n\n                    $$ = parser.make_statement_list (stmt);\n                  }\n                | arguments_block_list opt_sep arguments_block\n                  {\n                    octave::tree_statement *stmt = parser.make_statement ($3);\n\n                    $$ = parser.append_statement_list ($1, $2, stmt, false);\n                  }\n                ;\n\narguments_block : arguments_beg opt_sep args_attr_list args_validation_list opt_sep END\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused lists.\n                    delete $2;\n                    delete $5;\n\n                    if (! ($$ = parser.make_arguments_block ($1, $3, $4, $6)))\n                      {\n                        // make_arguments_block deleted $3, and $4.\n                        YYABORT;\n                      }\n\n                    lexer.m_arguments_is_keyword = true;\n                  }\n                ;\n\narguments_beg   : ARGUMENTS\n                  {\n                    $$ = $1;\n\n                    lexer.m_arguments_is_keyword = false;\n                  }\n                ;\n\nargs_attr_list  : // empty\n                  { $$ = nullptr; }\n                | '(' identifier ')'\n                  {\n                    $2->mark_in_delims (*($1), *($3));\n\n                    // Error if $$ is nullptr.\n                    if  (! ($$ = parser.make_args_attribute_list ($2)))\n                      {\n                        // make_args_attribute_list deleted $2.\n                        YYABORT;\n                      }\n                  }\n                ;\n\nargs_validation_list\n                  : arg_name arg_validation\n                    {\n                      $2->arg_name ($1);\n                      $$ = parser.make_args_validation_list ($2);\n                    }\n                  | args_validation_list sep arg_name arg_validation\n                    {\n                      // FIXME: Need to capture SEP here.\n                      // For now, delete the unused list.\n                      delete $2;\n\n                      $4->arg_name ($3);\n                      $$ = parser.append_args_validation_list ($1, $4);\n                    }\n                  ;\n\n// FIXME: Change grammar to allow IDENTIFIER to be either\n// \"NAME\" or \"NAME '.' NAME\", possibly not entered in the symbol\n// table for the current scope.  Also stash comments before identifier.\n\narg_name          : identifier\n                    { $$ = $1; }\n                  ;\n\narg_validation    : size_spec class_name validation_fcns\n                    {\n                      if (! ($$ = parser.make_arg_validation ($1, $2, $3)))\n                        {\n                          // make_arg_validation deleted ...\n                          YYABORT;\n                        }\n                    }\n                  | size_spec class_name validation_fcns '=' expression\n                    {\n                      if (! ($$ = parser.make_arg_validation ($1, $2, $3, $4, $5)))\n                        {\n                          // make_arg_validation deleted ...\n                          YYABORT;\n                        }\n                    }\n                ;\n\nsize_spec       : // empty\n                  { $$ = nullptr; }\n                | '(' arg_list ')'\n                  {\n                    $2->mark_in_delims (*($1), *($3));\n\n                    if (! ($$ = parser.make_arg_size_spec ($2)))\n                      {\n                        // make_arg_size_spec deleted $2.\n                        YYABORT;\n                      }\n                  }\n                ;\n\nclass_name      : // empty\n                  { $$ = nullptr; }\n                | identifier\n                  { $$ = $1; }\n                ;\n\n// Use argument list so we can accept anonymous functions.\nvalidation_fcns : // empty\n                  { $$ = nullptr; }\n                | '{' arg_list '}'\n                  {\n                    $2->mark_in_delims (*($1), *($3));\n\n                    if (! ($$ = parser.make_arg_validation_fcns ($2)))\n                      {\n                        // make_arg_validation_fcns deleted $2.\n                        YYABORT;\n                      }\n                  }\n                ;\n\n// ========\n// Classdef\n// ========\n\nclassdef_beg    : CLASSDEF\n                  {\n                    if (! lexer.m_reading_classdef_file)\n                      {\n                        parser.bison_error (\"classdef must appear inside a file containing only a class definition\");\n                        YYABORT;\n                      }\n\n                    // Create invalid parent scope.\n                    lexer.m_symtab_context.push (octave::symbol_scope::anonymous ());\n                    lexer.m_parsing_classdef = true;\n                    lexer.m_parsing_classdef_decl = true;\n                    lexer.m_classdef_element_names_are_keywords = true;\n\n                    $$ = $1;\n                  }\n                ;\n\nclassdef        : classdef_beg attr_list identifier opt_sep superclass_list class_body END\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $4;\n\n                    lexer.m_parsing_classdef = false;\n\n                    if (! ($$ = parser.make_classdef ($1, $2, $3, $5, $6, $7)))\n                      {\n                        // make_classdef deleted $2, $3, $5, $6\n                        YYABORT;\n                      }\n                  }\n                ;\n\nattr_list       : // empty\n                  { $$ = nullptr; }\n                | '(' attr_list1 ')' opt_sep\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $4;\n\n                    $$ = $2->mark_in_delims (*($1), *($3));\n                  }\n                ;\n\nattr_list1      : attr\n                  { $$ = parser.make_classdef_attribute_list ($1); }\n                | attr_list1 ',' attr\n                  { $$ = parser.append_classdef_attribute ($1, $2, $3); }\n                ;\n\nattr            : identifier\n                  { $$ = parser.make_classdef_attribute ($1); }\n                | identifier '=' expression\n                  { $$ = parser.make_classdef_attribute ($1, $2, $3); }\n                | '~' identifier\n                  { $$ = parser.make_not_classdef_attribute ($1, $2); }\n                | '!' identifier\n                  { $$ = parser.make_not_classdef_attribute ($1, $2); }\n                ;\n\nsuperclass_list : // empty\n                  {\n                    lexer.m_parsing_classdef_decl = false;\n                    lexer.m_parsing_classdef_superclass = false;\n                    $$ = nullptr;\n                  }\n                | superclass_list1 opt_sep\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    lexer.m_parsing_classdef_decl = false;\n                    lexer.m_parsing_classdef_superclass = false;\n                    $$ = $1;\n                  }\n                ;\n\nsuperclass_list1\n                : EXPR_LT superclass\n                  { $$ = parser.make_classdef_superclass_list ($1, $2); }\n                | superclass_list1 EXPR_AND superclass\n                  { $$ = parser.append_classdef_superclass ($1, $2, $3); }\n                ;\n\nsuperclass      : FQ_IDENT\n                  { $$ = parser.make_classdef_superclass ($1); }\n                ;\n\nclass_body      : // empty\n                  {\n                    lexer.m_classdef_element_names_are_keywords = false;\n                    $$ = nullptr;\n                  }\n                | class_body1 opt_sep\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    lexer.m_classdef_element_names_are_keywords = false;\n                    $$ = $1;\n                  }\n                ;\n\nclass_body1     : properties_block\n                  { $$ = parser.make_classdef_body ($1); }\n                | methods_block\n                  { $$ = parser.make_classdef_body ($1); }\n                | events_block\n                  { $$ = parser.make_classdef_body ($1); }\n                | enum_block\n                  { $$ = parser.make_classdef_body ($1); }\n                | class_body1 opt_sep properties_block\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    $$ = parser.append_classdef_properties_block ($1, $3);\n                  }\n                | class_body1 opt_sep methods_block\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    $$ = parser.append_classdef_methods_block ($1, $3);\n                  }\n                | class_body1 opt_sep events_block\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    $$ = parser.append_classdef_events_block ($1, $3);\n                  }\n                | class_body1 opt_sep enum_block\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    $$ = parser.append_classdef_enum_block ($1, $3);\n                  }\n                ;\n\nproperties_block\n                : properties_beg opt_sep attr_list property_list END\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    if (! ($$ = parser.make_classdef_properties_block ($1, $3, $4, $5)))\n                      {\n                        // make_classdef_properties_block deleted $3 and $4.\n                        YYABORT;\n                      }\n                  }\n                ;\n\nproperties_beg  : PROPERTIES\n                  {\n                    lexer.m_classdef_element_names_are_keywords = false;\n                    $$ = $1;\n                  }\n                ;\n\nproperty_list   : // empty\n                  {\n                    lexer.m_classdef_element_names_are_keywords = true;\n                    $$ = nullptr;\n                  }\n                | property_list1 opt_sep\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    lexer.m_classdef_element_names_are_keywords = true;\n                    $$ = $1;\n                  }\n                ;\n\nproperty_list1\n                : class_property\n                  { $$ = parser.make_classdef_property_list ($1); }\n                | property_list1 sep class_property\n                  {\n                    // FIXME: Need to capture SEP here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    // We don't look ahead to grab end-of-line comments.\n                    // Instead, they are grabbed when we see the\n                    // identifier that becomes the next element in the\n                    // list.  If the element at the end of the list\n                    // doesn't have a doc string, see whether the\n                    // element we are adding is storing an end-of-line\n                    // comment for us to use.\n\n                    octave::tree_classdef_property *last_elt = $1->back ();\n\n                    if (! last_elt->have_doc_string ())\n                      {\n                        octave::comment_list comments = $3->leading_comments ();\n\n                        if (! comments.empty ())\n                          {\n                            octave::comment_elt elt = comments.front ();\n\n                            if (elt.is_end_of_line ())\n                              last_elt->doc_string (elt.text ());\n                          }\n                      }\n\n                    $$ = parser.append_classdef_property ($1, $3);\n                  }\n                ;\n\nclass_property  : identifier arg_validation\n                  { $$ = parser.make_classdef_property ($1, $2); }\n                ;\n\nmethods_block   : methods_beg opt_sep attr_list method_list END\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    if (! ($$ = parser.make_classdef_methods_block ($1, $3, $4, $5)))\n                      {\n                        // make_classdef_methods_block deleted $3 and $4.\n                        YYABORT;\n                      }\n                  }\n                ;\n\nmethods_beg     : METHODS\n                  {\n                    lexer.m_classdef_element_names_are_keywords = false;\n                    $$ = $1;\n                  }\n                ;\n\nmethod_decl1    : identifier\n                  {\n                    if (! ($$ = parser.start_classdef_external_method ($1)))\n                      YYABORT;\n                  }\n                | identifier param_list\n                  {\n                    if (! ($$ = parser.start_classdef_external_method ($1, $2)))\n                      YYABORT;\n                  }\n                ;\n\nmethod_decl     : method_decl1\n                  { $$ = parser.finish_classdef_external_method ($1); }\n                | return_list '='\n                  {\n                    lexer.m_defining_fcn++;\n                    lexer.m_parsed_function_name.push (false);\n                  }\n                  method_decl1\n                  {\n                    lexer.m_defining_fcn--;\n                    lexer.m_parsed_function_name.pop ();\n\n                    $$ = parser.finish_classdef_external_method ($4, $1, $2);\n                  }\n                ;\n\nmethod          : method_decl\n                  { $$ = $1; }\n                | function\n                  { $$ = $1; }\n                ;\n\nmethod_list     : // empty\n                  {\n                    lexer.m_classdef_element_names_are_keywords = true;\n                    $$ = nullptr;\n                  }\n                | method_list1 opt_sep\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    lexer.m_classdef_element_names_are_keywords = true;\n                    $$ = $1;\n                  }\n                ;\n\nmethod_list1    : method\n                  { $$ = parser.make_classdef_method_list ($1); }\n                | method_list1 opt_sep method\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    $$ = parser.append_classdef_method ($1, $3);\n                  }\n                ;\n\nevents_block    : events_beg opt_sep attr_list event_list END\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    if (! ($$ = parser.make_classdef_events_block ($1, $3, $4, $5)))\n                      {\n                        // make_classdef_events_block deleted $4 and $5.\n                        YYABORT;\n                      }\n                  }\n                ;\n\nevents_beg      : EVENTS\n                  {\n                    lexer.m_classdef_element_names_are_keywords = false;\n                    $$ = $1;\n                  }\n                ;\n\nevent_list      : // empty\n                  {\n                    lexer.m_classdef_element_names_are_keywords = true;\n                    $$ = nullptr;\n                  }\n                | event_list1 opt_sep\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    lexer.m_classdef_element_names_are_keywords = true;\n                    $$ = $1;\n                  }\n                ;\n\nevent_list1     : class_event\n                  { $$ = parser.make_classdef_event_list ($1); }\n                | event_list1 opt_sep class_event\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    $$ = parser.append_classdef_event ($1, $3);\n                  }\n                ;\n\nclass_event     : identifier\n                  { $$ = parser.make_classdef_event ($1); }\n                ;\n\nenum_block      : enumeration_beg opt_sep attr_list enum_list END\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    if (! ($$ = parser.make_classdef_enum_block ($1, $3, $4, $5)))\n                      {\n                        // make_classdef_enum_block deleted $3 and $4.\n                        YYABORT;\n                      }\n                  }\n                ;\n\nenumeration_beg : ENUMERATION\n                  {\n                    lexer.m_classdef_element_names_are_keywords = false;\n                    $$ = $1;\n                  }\n                ;\n\nenum_list       : // empty\n                  {\n                    lexer.m_classdef_element_names_are_keywords = true;\n                    $$ = nullptr;\n                  }\n                | enum_list1 opt_sep\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    lexer.m_classdef_element_names_are_keywords = true;\n                    $$ = $1;\n                  }\n                ;\n\nenum_list1      : class_enum\n                  { $$ = parser.make_classdef_enum_list ($1); }\n                | enum_list1 opt_sep class_enum\n                  {\n                    // FIXME: Need to capture separator list here.\n                    // For now, delete the unused list.\n                    delete $2;\n\n                    $$ = parser.append_classdef_enum ($1, $3);\n                  }\n                ;\n\nclass_enum      : identifier '(' expression ')'\n                  { $$ = parser.make_classdef_enum ($1, $2, $3, $4); }\n                ;\n\n// =============\n// Miscellaneous\n// =============\n\nstmt_begin      : // empty\n                  {\n                    $$ = 0;\n                    lexer.m_at_beginning_of_statement = true;\n                  }\n                ;\n\nanon_fcn_begin  : // empty\n                  {\n                    $$ = 0;\n                    lexer.m_at_beginning_of_statement = true;\n                    lexer.m_parsing_anon_fcn_body = true;\n                  }\n                ;\n\nparse_error     : LEXICAL_ERROR\n                  {\n                    $$ = 0;\n                    std::string msg = $1->text ();\n                    parser.bison_error (msg.c_str ());\n                  }\n                | error\n                  { $$ = 0; }\n                ;\n\nsep_no_nl       : ','\n                  { $$ = new octave::separator_list (*($1)); }\n                | ';'\n                  { $$ = new octave::separator_list (*($1)); }\n                | sep_no_nl ','\n                  { $$ = $1->append (*($2)); }\n                | sep_no_nl ';'\n                  { $$ = $1->append (*($2)); }\n                ;\n\nopt_sep_no_nl   : // empty\n                  { $$ = nullptr; }\n                | sep_no_nl\n                  { $$ = $1; }\n                ;\n\nsep             : ','\n                  { $$ = new octave::separator_list (*($1)); }\n                | ';'\n                  { $$ = new octave::separator_list (*($1)); }\n                | '\\n'\n                  { $$ = new octave::separator_list (*($1)); }\n                | sep ','\n                  { $$ = $1->append (*($2)); }\n                | sep ';'\n                  { $$ = $1->append (*($2)); }\n                | sep '\\n'\n                  { $$ = $1->append (*($2)); }\n                ;\n\nopt_sep         : // empty\n                  { $$ = nullptr; }\n                | sep\n                  { $$ = $1; }\n                ;\n\n%%\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n   // Restore prevailing warning state for remainder of the file.\n#  pragma GCC diagnostic pop\n#endif\n\n// Generic error messages.\n\n#undef lexer\n#undef scanner\n\nstatic void\nyyerror (octave::base_parser& parser, const char *s)\n{\n  parser.bison_error (s);\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_EXCEPTION_API parse_exception : public std::runtime_error\n{\npublic:\n\n  parse_exception () = delete;\n\n  parse_exception (const std::string& message, const std::string& fcn_name = \"\", const std::string& file_name = \"\", const filepos& pos = filepos ())\n    : runtime_error (message), m_message (message), m_fcn_name (fcn_name), m_file_name (file_name), m_pos (pos)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (parse_exception)\n\n  std::string message () const { return m_message; }\n\n  // Provided for std::exception interface.\n  const char * what () const noexcept { return m_message.c_str (); }\n\n  std::string fcn_name () const { return m_fcn_name; }\n  std::string file_name () const { return m_file_name; }\n\n  filepos pos () const { return m_pos; }\n\n  // virtual void display (std::ostream& os) const;\n\nprivate:\n\n  std::string m_message;\n\n  std::string m_fcn_name;\n  std::string m_file_name;\n  filepos m_pos;\n};\n\nclass parse_tree_validator : public tree_walker\n{\npublic:\n\n  parse_tree_validator ()\n    : m_scope (symbol_scope::anonymous ()), m_error_list ()\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (parse_tree_validator)\n\n  ~parse_tree_validator () = default;\n\n  symbol_scope get_scope () const { return m_scope; }\n\n  bool ok () const { return m_error_list.empty (); }\n\n  std::list<parse_exception> error_list () const\n  {\n    return m_error_list;\n  }\n\n  void visit_octave_user_script (octave_user_script& script)\n  {\n    unwind_protect_var<symbol_scope> restore_var (m_scope, script.scope ());\n\n    tree_statement_list *stmt_list = script.body ();\n\n    if (stmt_list)\n      stmt_list->accept (*this);\n  }\n\n  void visit_octave_user_function (octave_user_function& fcn)\n  {\n    unwind_protect_var<symbol_scope> restore_var (m_scope, fcn.scope ());\n\n    tree_statement_list *stmt_list = fcn.body ();\n\n    if (stmt_list)\n      stmt_list->accept (*this);\n\n    std::map<std::string, octave_value> subfcns = fcn.subfunctions ();\n\n    if (! subfcns.empty ())\n      {\n        for (auto& nm_val : subfcns)\n          {\n            octave_user_function *subfcn = nm_val.second.user_function_value ();\n\n            if (subfcn)\n              subfcn->accept (*this);\n          }\n      }\n  }\n\n  void visit_index_expression (tree_index_expression& idx_expr)\n  {\n    if (idx_expr.is_word_list_cmd ())\n      {\n        std::string sym_nm = idx_expr.name ();\n\n        if (m_scope.is_variable (sym_nm))\n          {\n            std::string message = sym_nm + \": invalid use of symbol as both variable and command\";\n            parse_exception pe (message, m_scope.fcn_name (), m_scope.fcn_file_name (), idx_expr.beg_pos ());\n\n            m_error_list.push_back (pe);\n          }\n      }\n  }\n\nprivate:\n\n  symbol_scope m_scope;\n\n  std::list<parse_exception> m_error_list;\n};\n\ntemplate <typename LIST_T, typename ELT_T>\nstatic LIST_T *\nlist_append (LIST_T *list, ELT_T elt)\n{\n  list->push_back (elt);\n  return list;\n}\n\ntemplate <typename LIST_T, typename ELT_T>\nstatic LIST_T *\nlist_append (LIST_T *list, const token& /*sep_tok*/, ELT_T elt)\n{\n  // FIXME: Need to capture SEP_TOK here\n  list->push_back (elt);\n  return list;\n}\n\nstd::size_t\nbase_parser::parent_scope_info::size () const\n{\n  return m_info.size ();\n}\n\nvoid\nbase_parser::parent_scope_info::push (const value_type& elt)\n{\n  m_info.push_back (elt);\n}\n\nvoid\nbase_parser::parent_scope_info::push (const symbol_scope& scope)\n{\n  push (value_type (scope, \"\"));\n}\n\nvoid\nbase_parser::parent_scope_info::pop ()\n{\n  m_info.pop_back ();\n}\n\nbool\nbase_parser::parent_scope_info::name_ok (const std::string& name)\n{\n  // Name can't be the same as any parent function or any other\n  // function we've already seen.  We could maintain a complex\n  // tree structure of names, or we can just store the set of\n  // full names of all the functions, which must be unique.\n\n  std::string full_name;\n\n  for (std::size_t i = 0; i < size()-1; i++)\n    {\n      const value_type& elt = m_info[i];\n\n      if (name == elt.second)\n        return false;\n\n      full_name += elt.second + \">\";\n    }\n\n  full_name += name;\n\n  if (m_all_names.find (full_name) != m_all_names.end ())\n    {\n      // Return false (failure) if we are parsing a subfunction, local\n      // function, or nested function.  Otherwise, it is OK to have a\n      // duplicate name.\n\n      return ! (m_parser.parsing_subfunctions () || m_parser.parsing_local_functions () || m_parser.curr_fcn_depth () > 0);\n    }\n\n  m_all_names.insert (full_name);\n\n  return true;\n}\n\nbool\nbase_parser::parent_scope_info::name_current_scope (const std::string& name)\n{\n  if (! name_ok (name))\n    return false;\n\n  if (size () > 0)\n    m_info.back().second = name;\n\n  return true;\n}\n\nsymbol_scope\nbase_parser::parent_scope_info::parent_scope () const\n{\n  return size () > 1 ? m_info[size()-2].first : symbol_scope::invalid ();\n}\n\nstd::string\nbase_parser::parent_scope_info::parent_name () const\n{\n  return m_info[size()-2].second;\n}\n\nvoid base_parser::parent_scope_info::clear ()\n{\n  m_info.clear ();\n  m_all_names.clear ();\n}\n\nbase_parser::base_parser (base_lexer& lxr)\n  : m_endfunction_found (false), m_autoloading (false),\n    m_fcn_file_from_relative_lookup (false),\n    m_parsing_subfunctions (false), m_parsing_local_functions (false),\n    m_max_fcn_depth (-1), m_curr_fcn_depth (-1),\n    m_primary_fcn_scope (symbol_scope::invalid ()),\n    m_curr_class_name (), m_curr_package_name (), m_function_scopes (*this),\n    m_primary_fcn (), m_subfunction_names (), m_classdef_object (),\n    m_stmt_list (), m_lexer (lxr), m_parser_state (yypstate_new ())\n{ }\n\nbase_parser::~base_parser ()\n{\n  delete &m_lexer;\n\n  // FIXME: Deleting the internal Bison parser state structure does\n  // not clean up any partial parse trees in the event of an interrupt or\n  // error.  It's not clear how to safely do that with the C language\n  // parser that Bison generates.  The C++ language parser that Bison\n  // generates would do it for us automatically whenever an exception\n  // is thrown while parsing input, but there is currently no C++\n  // interface for a push parser.\n\n  yypstate_delete (static_cast<yypstate *> (m_parser_state));\n}\n\nvoid\nbase_parser::reset ()\n{\n  m_endfunction_found = false;\n  m_autoloading = false;\n  m_fcn_file_from_relative_lookup = false;\n  m_parsing_subfunctions = false;\n  m_parsing_local_functions = false;\n  m_max_fcn_depth = -1;\n  m_curr_fcn_depth = -1;\n  m_primary_fcn_scope = symbol_scope::invalid ();\n  m_curr_class_name = \"\";\n  m_curr_package_name = \"\";\n  m_function_scopes.clear ();\n  m_primary_fcn = octave_value ();\n  m_subfunction_names.clear ();\n  m_classdef_object.reset ();\n  m_stmt_list.reset ();\n\n  m_lexer.reset ();\n\n  yypstate_delete (static_cast<yypstate *> (m_parser_state));\n  m_parser_state = yypstate_new ();\n}\n\nOCTAVE_NORETURN static void\nunexpected_token (int tok_id, const char *where)\n{\n  error (\"unexpected token (= %d) in %s - please report this bug\", tok_id, where);\n}\n\n// Error messages for mismatched end tokens.\n\nstatic std::string\nend_token_as_string (token::end_tok_type ettype)\n{\n  std::string retval = \"<unknown>\";\n\n  switch (ettype)\n    {\n    case token::simple_end:\n      retval = \"end\";\n      break;\n\n    case token::arguments_end:\n      retval = \"endarguments\";\n      break;\n\n    case token::classdef_end:\n      retval = \"endclassdef\";\n      break;\n\n    case token::enumeration_end:\n      retval = \"endenumeration\";\n      break;\n\n    case token::events_end:\n      retval = \"endevents\";\n      break;\n\n    case token::for_end:\n      retval = \"endfor\";\n      break;\n\n    case token::function_end:\n      retval = \"endfunction\";\n      break;\n\n    case token::if_end:\n      retval = \"endif\";\n      break;\n\n    case token::methods_end:\n      retval = \"endmethods\";\n      break;\n\n    case token::parfor_end:\n      retval = \"endparfor\";\n      break;\n\n    case token::properties_end:\n      retval = \"endproperties\";\n      break;\n\n    case token::spmd_end:\n      retval = \"endspmd\";\n      break;\n\n    case token::switch_end:\n      retval = \"endswitch\";\n      break;\n\n    case token::try_catch_end:\n      retval = \"end_try_catch\";\n      break;\n\n    case token::unwind_protect_end:\n      retval = \"end_unwind_protect\";\n      break;\n\n    case token::while_end:\n      retval = \"endwhile\";\n      break;\n\n      // We should have handled all possible enum values above.  Rely on\n      // compiler diagnostics to warn if we haven't.  For example, GCC's\n      // -Wswitch option, enabled by -Wall, will provide a warning.\n    }\n\n  return retval;\n}\n\nvoid\nbase_parser::statement_list (std::shared_ptr<tree_statement_list>& lst)\n{\n  if (! lst)\n    return;\n\n  if (m_stmt_list)\n    {\n      // Append additional code to existing statement list.\n\n      while (! lst->empty ())\n        {\n          m_stmt_list->push_back (lst->front ());\n          lst->pop_front ();\n        }\n    }\n  else\n    m_stmt_list = lst;\n}\n\nvoid\nbase_parser::end_token_error (token *tok, token::end_tok_type expected)\n{\n  std::string msg = (\"'\" + end_token_as_string (expected) + \"' command matched by '\" + end_token_as_string (tok->ettype ()) + \"'\");\n\n  bison_error (msg, tok->beg_pos ());\n}\n\n// Check to see that end tokens are properly matched.\n\nbool\nbase_parser::end_token_ok (token *tok, token::end_tok_type expected)\n{\n  token::end_tok_type ettype = tok->ettype ();\n\n  return ettype == expected || ettype == token::simple_end;\n}\n\nbool\nbase_parser::push_fcn_symtab ()\n{\n  m_curr_fcn_depth++;\n\n  if (m_max_fcn_depth < m_curr_fcn_depth)\n    m_max_fcn_depth = m_curr_fcn_depth;\n\n  // Will get a real name later.\n  m_lexer.m_symtab_context.push (symbol_scope (\"parser:push_fcn_symtab\"));\n  m_function_scopes.push (m_lexer.m_symtab_context.curr_scope ());\n\n  if (! m_lexer.m_reading_script_file && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)\n    {\n      m_primary_fcn_scope = m_lexer.m_symtab_context.curr_scope ();\n      m_primary_fcn_scope.mark_primary_fcn_scope ();\n    }\n\n  if (m_lexer.m_reading_script_file && m_curr_fcn_depth > 0)\n    {\n      bison_error (\"nested functions not implemented in this context\");\n\n      return false;\n    }\n\n  return true;\n}\n\n// Make a constant.\n\ntree_constant *\nbase_parser::make_constant (token *tok)\n{\n  int tok_id = tok->token_id ();\n\n  tree_constant *retval = nullptr;\n\n  switch (tok_id)\n    {\n    case ':':\n      retval = new tree_constant (octave_value (octave_value::magic_colon_t), *tok);\n      break;\n\n    case NUMBER:\n      retval = new tree_constant (tok->number (), tok->text_rep (), *tok);\n      break;\n\n    case DQ_STRING:\n    case SQ_STRING:\n      {\n        std::string txt = tok->text ();\n\n        char delim = tok_id == DQ_STRING ? '\"' : '\\'';\n        octave_value tmp (txt, delim);\n\n        if (txt.empty ())\n          {\n            if (tok_id == DQ_STRING)\n              tmp = octave_null_str::instance;\n            else\n              tmp = octave_null_sq_str::instance;\n          }\n\n        if (tok_id == DQ_STRING)\n          txt = undo_string_escapes (txt);\n\n        // FIXME: maybe the addition of delims should be handled by\n        // tok->text_rep () for character strings?\n\n        retval = new tree_constant (tmp, delim + txt + delim, *tok);\n      }\n      break;\n\n    default:\n      unexpected_token (tok_id, \"base_parser::make_constant\");\n      break;\n    }\n\n  return retval;\n}\n\ntree_black_hole *\nbase_parser::make_black_hole (token *tilde)\n{\n  return new tree_black_hole (*tilde);\n}\n\n// Make a function handle.\n\ntree_fcn_handle *\nbase_parser::make_fcn_handle (token *tok)\n{\n  tree_fcn_handle *retval = new tree_fcn_handle (*tok);\n\n  return retval;\n}\n\n// Make an anonymous function handle.\n\ntree_anon_fcn_handle *\nbase_parser::make_anon_fcn_handle (token *at_tok, tree_parameter_list *param_list, tree_expression *expr)\n{\n  // FIXME: We need to examine EXPR and issue an error if any\n  // sub-expression contains an assignment, compound assignment,\n  // increment, or decrement operator.\n\n  anon_fcn_validator validator (param_list, expr);\n\n  if (! validator.ok ())\n    {\n      delete param_list;\n      delete expr;\n\n      bison_error (validator.message (), validator.beg_pos ());\n\n      return nullptr;\n    }\n\n  symbol_scope fcn_scope = m_lexer.m_symtab_context.curr_scope ();\n  symbol_scope parent_scope = m_lexer.m_symtab_context.parent_scope ();\n\n  m_lexer.m_symtab_context.pop ();\n\n  expr->set_print_flag (false);\n\n  fcn_scope.mark_static ();\n\n  tree_anon_fcn_handle *retval = new tree_anon_fcn_handle (*at_tok, param_list, expr, fcn_scope, parent_scope);\n\n  std::ostringstream buf;\n\n  tree_print_code tpc (buf);\n\n  retval->accept (tpc);\n\n  std::string file = m_lexer.m_fcn_file_full_name;\n  if (! file.empty ())\n    buf << \": file: \" << file;\n  else if (m_lexer.input_from_terminal ())\n    buf << \": *terminal input*\";\n  else if (m_lexer.input_from_eval_string ())\n    buf << \": *eval string*\";\n\n  filepos at_pos = at_tok->beg_pos ();\n  buf << \": line: \" << at_pos.line () << \" column: \" << at_pos.column ();\n\n  std::string scope_name = buf.str ();\n\n  fcn_scope.cache_name (scope_name);\n\n  // FIXME: Stash the filename.  This does not work and produces\n  // errors when executed.\n  //retval->stash_file_name (m_lexer.m_fcn_file_name);\n\n  return retval;\n}\n\n// Build a colon expression.\n\ntree_expression *\nbase_parser::make_colon_expression (tree_expression *base, token *colon_tok, tree_expression *limit)\n{\n  return make_colon_expression (base, colon_tok, nullptr, nullptr, limit);\n}\n\ntree_expression *\nbase_parser::make_colon_expression (tree_expression *base, token *colon_1_tok, tree_expression *incr, token *colon_2_tok, tree_expression *limit)\n{\n  tree_expression *retval = nullptr;\n\n  if (! base || ! limit)\n    {\n      delete base;\n      delete limit;\n      delete incr;\n\n      return retval;\n    }\n\n  token tmp_colon_2_tok = colon_2_tok ? *colon_2_tok : token ();\n\n  tree_colon_expression *expr = new tree_colon_expression (base, *colon_1_tok, incr, tmp_colon_2_tok, limit);\n\n  retval = expr;\n\n  if (base->is_constant () && limit->is_constant () && (! incr || incr->is_constant ()))\n    {\n      interpreter& interp = m_lexer.m_interpreter;\n\n      try\n        {\n          // If the evaluation generates a warning message, restore\n          // the previous value of last_warning_message and skip the\n          // conversion to a constant value.\n\n          error_system& es = interp.get_error_system ();\n\n          unwind_action restore_last_warning_message (&error_system::set_last_warning_message, &es, es.last_warning_message (\"\"));\n\n          unwind_action restore_discard_warning_messages (&error_system::set_discard_warning_messages, &es, es.discard_warning_messages (true));\n\n          tree_evaluator& tw = interp.get_evaluator ();\n\n          octave_value tmp = expr->evaluate (tw);\n\n          std::string msg = es.last_warning_message ();\n\n          if (msg.empty ())\n            {\n              std::ostringstream buf;\n\n              tree_print_code tpc (buf);\n\n              expr->accept (tpc);\n\n              std::string orig_text = buf.str ();\n\n              token tok (CONSTANT, tmp, orig_text, expr->beg_pos (), expr->end_pos ());\n\n              tree_constant *tc_retval = new tree_constant (tmp, orig_text, tok);\n\n              delete expr;\n\n              retval = tc_retval;\n            }\n        }\n      catch (const execution_exception&)\n        {\n          interp.recover_from_exception ();\n        }\n    }\n\n  return retval;\n}\n\n// Build a binary expression.\n\ntree_expression *\nbase_parser::make_binary_op (tree_expression *op1, token *op_tok, tree_expression *op2)\n{\n  octave_value::binary_op t = octave_value::unknown_binary_op;\n\n  int tok_id = op_tok->token_id ();\n\n  switch (tok_id)\n    {\n    case POW:\n      t = octave_value::op_pow;\n      break;\n\n    case EPOW:\n      t = octave_value::op_el_pow;\n      break;\n\n    case '+':\n      t = octave_value::op_add;\n      break;\n\n    case '-':\n      t = octave_value::op_sub;\n      break;\n\n    case '*':\n      t = octave_value::op_mul;\n      break;\n\n    case '/':\n      t = octave_value::op_div;\n      break;\n\n    case EMUL:\n      t = octave_value::op_el_mul;\n      break;\n\n    case EDIV:\n      t = octave_value::op_el_div;\n      break;\n\n    case LEFTDIV:\n      t = octave_value::op_ldiv;\n      break;\n\n    case ELEFTDIV:\n      t = octave_value::op_el_ldiv;\n      break;\n\n    case EXPR_LT:\n      t = octave_value::op_lt;\n      break;\n\n    case EXPR_LE:\n      t = octave_value::op_le;\n      break;\n\n    case EXPR_EQ:\n      t = octave_value::op_eq;\n      break;\n\n    case EXPR_GE:\n      t = octave_value::op_ge;\n      break;\n\n    case EXPR_GT:\n      t = octave_value::op_gt;\n      break;\n\n    case EXPR_NE:\n      t = octave_value::op_ne;\n      break;\n\n    case EXPR_AND:\n      t = octave_value::op_el_and;\n      break;\n\n    case EXPR_OR:\n      t = octave_value::op_el_or;\n      break;\n\n    default:\n      unexpected_token (tok_id, \"base_parser::make_binary_op\");\n      break;\n    }\n\n  return maybe_compound_binary_expression (op1, *op_tok, op2, t);\n}\n\nvoid\nbase_parser::maybe_convert_to_braindead_shortcircuit (tree_expression*& expr)\n{\n  if (expr->is_binary_expression ())\n    {\n      tree_binary_expression *binexp = dynamic_cast<tree_binary_expression *> (expr);\n\n      token op_tok = binexp->op_token ();\n\n      tree_expression *lhs = binexp->lhs ();\n      tree_expression *rhs = binexp->rhs ();\n\n      maybe_convert_to_braindead_shortcircuit (lhs);\n      maybe_convert_to_braindead_shortcircuit (rhs);\n\n      // Operands may have changed.\n      binexp->lhs (lhs);\n      binexp->rhs (rhs);\n\n      octave_value::binary_op op_type = binexp->op_type ();\n      if (op_type == octave_value::op_el_and || op_type == octave_value::op_el_or)\n        {\n          binexp->preserve_operands ();\n\n          delete expr;\n\n          expr = new tree_braindead_shortcircuit_binary_expression (lhs, op_tok, rhs, op_type);\n        }\n    }\n}\n\n// Build a boolean expression.\n\ntree_expression *\nbase_parser::make_boolean_op (tree_expression *op1, token *op_tok, tree_expression *op2)\n{\n  tree_boolean_expression::type t;\n\n  int tok_id = op_tok->token_id ();\n\n  switch (tok_id)\n    {\n    case EXPR_AND_AND:\n      t = tree_boolean_expression::bool_and;\n      break;\n\n    case EXPR_OR_OR:\n      t = tree_boolean_expression::bool_or;\n      break;\n\n    default:\n      unexpected_token (tok_id, \"base_parser::make_boolean_op\");\n      break;\n    }\n\n  return new tree_boolean_expression (op1, *op_tok, op2, t);\n}\n\n// Build a prefix expression.\n\ntree_expression *\nbase_parser::make_prefix_op (token *op_tok, tree_expression *op1)\n{\n  octave_value::unary_op t = octave_value::unknown_unary_op;\n\n  int tok_id = op_tok->token_id ();\n\n  switch (tok_id)\n    {\n    case '~':\n    case '!':\n      t = octave_value::op_not;\n      break;\n\n    case '+':\n      t = octave_value::op_uplus;\n      break;\n\n    case '-':\n      t = octave_value::op_uminus;\n      break;\n\n    case PLUS_PLUS:\n      t = octave_value::op_incr;\n      break;\n\n    case MINUS_MINUS:\n      t = octave_value::op_decr;\n      break;\n\n    default:\n      unexpected_token (tok_id, \"base_parser::make_prefix_op\");\n      break;\n    }\n\n  return new tree_prefix_expression (*op_tok, op1, t);\n}\n\n// Build a postfix expression.\n\ntree_expression *\nbase_parser::make_postfix_op (tree_expression *op1, token *op_tok)\n{\n  octave_value::unary_op t = octave_value::unknown_unary_op;\n\n  int tok_id = op_tok->token_id ();\n\n  switch (tok_id)\n    {\n    case HERMITIAN:\n      t = octave_value::op_hermitian;\n      break;\n\n    case TRANSPOSE:\n      t = octave_value::op_transpose;\n      break;\n\n    case PLUS_PLUS:\n      t = octave_value::op_incr;\n      break;\n\n    case MINUS_MINUS:\n      t = octave_value::op_decr;\n      break;\n\n    default:\n      unexpected_token (tok_id, \"base_parser::make_postfix_op\");\n      break;\n    }\n\n  return new tree_postfix_expression (op1, *op_tok, t);\n}\n\n// Build an unwind-protect command.\n\ntree_command *\nbase_parser::make_unwind_command (token *unwind_tok, tree_statement_list *body, token *cleanup_tok, tree_statement_list *cleanup_stmts, token *end_tok)\n{\n  tree_command *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::unwind_protect_end))\n    {\n      retval = new tree_unwind_protect_command (*unwind_tok, body, *cleanup_tok, cleanup_stmts, *end_tok);\n    }\n  else\n    {\n      delete body;\n      delete cleanup_stmts;\n\n      end_token_error (end_tok, token::unwind_protect_end);\n    }\n\n  return retval;\n}\n\n// Build a try-catch command.\n\ntree_command *\nbase_parser::make_try_command (token *try_tok, tree_statement_list *body, token *catch_tok, separator_list *catch_sep_list, tree_statement_list *cleanup_stmts, token *end_tok)\n{\n  tree_command *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::try_catch_end))\n    {\n      tree_identifier *id = nullptr;\n\n      // Look for exception ID.  Note that adding a separate rule to\n      // match\n      //\n      //   try\n      //     try-body\n      //   catch IDENTIFIER\n      //     catch-body\n      //   end\n      //\n      // in the grammar leads to yet another shift-reduce conflict, so\n      // instead we only match\n      //\n      //   try\n      //     try-body\n      //   catch\n      //     catch-body\n      //   end\n      //\n      // and then recognize the first form above by checking that the\n      // first element of CATCH-BODY is an identifier and that there is\n      // is no separator (comma, semicolon, or newline) between the\n      // CATCH token and the identifier.\n\n      if (! catch_sep_list && cleanup_stmts && ! cleanup_stmts->empty ())\n        {\n          tree_statement *stmt = cleanup_stmts->front ();\n\n          if (stmt)\n            {\n              tree_expression *expr = stmt->expression ();\n\n              if (expr && expr->is_identifier ())\n                {\n                  id = dynamic_cast<tree_identifier *> (expr);\n\n                  cleanup_stmts->pop_front ();\n\n                  stmt->set_expression (nullptr);\n                  delete stmt;\n                }\n            }\n        }\n\n      token tmp_catch_tok = catch_tok ? *catch_tok : token ();\n\n      // FIXME: Need to capture separator list here.\n      // For now, delete the unused list.\n      delete catch_sep_list;\n\n      retval = new tree_try_catch_command (*try_tok, body, tmp_catch_tok, id, cleanup_stmts, *end_tok);\n    }\n  else\n    {\n      delete body;\n      delete catch_sep_list;\n      delete cleanup_stmts;\n\n      end_token_error (end_tok, token::try_catch_end);\n    }\n\n  return retval;\n}\n\n// Build a while command.\n\ntree_command *\nbase_parser::make_while_command (token *while_tok, tree_expression *expr, tree_statement_list *body, token *end_tok)\n{\n  tree_command *retval = nullptr;\n\n  maybe_warn_assign_as_truth_value (expr);\n\n  if (end_token_ok (end_tok, token::while_end))\n    {\n      m_lexer.m_looping--;\n\n      retval = new tree_while_command (*while_tok, expr, body, *end_tok);\n    }\n  else\n    {\n      delete expr;\n      delete body;\n\n      end_token_error (end_tok, token::while_end);\n    }\n\n  return retval;\n}\n\n// Build a do-until command.\n\ntree_command *\nbase_parser::make_do_until_command (token *do_tok, tree_statement_list *body, token *until_tok, tree_expression *expr)\n{\n  maybe_warn_assign_as_truth_value (expr);\n\n  m_lexer.m_looping--;\n\n  return new tree_do_until_command (*do_tok, body, *until_tok, expr);\n}\n\n// Build a for command.\n\ntree_command *\nbase_parser::make_for_command (token *for_tok, token *open_paren, tree_argument_list *lhs, token *eq_tok, tree_expression *expr, token *sep_tok, tree_expression *maxproc, token *close_paren, tree_statement_list *body, token *end_tok)\n{\n  tree_command *retval = nullptr;\n\n  bool parfor = for_tok->token_id () == PARFOR;\n\n  token tmp_open_paren = open_paren ? *open_paren : token ();\n  token tmp_close_paren = close_paren ? *close_paren : token ();\n  token tmp_sep_tok = sep_tok ? *sep_tok : token ();\n\n  if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))\n    {\n      expr->mark_as_for_cmd_expr ();\n\n      m_lexer.m_looping--;\n\n      if (lhs->size () == 1)\n        {\n          tree_expression *tmp = lhs->remove_front ();\n\n          m_lexer.mark_as_variable (tmp->name ());\n\n          retval = new tree_simple_for_command (parfor, *for_tok, tmp_open_paren, tmp, *eq_tok, expr, tmp_sep_tok, maxproc, tmp_close_paren, body, *end_tok);\n\n          delete lhs;\n        }\n      else if (parfor)\n        {\n          delete lhs;\n          delete expr;\n          delete maxproc;\n          delete body;\n\n          bison_error (\"invalid syntax for parfor statement\");\n        }\n      else\n        {\n          m_lexer.mark_as_variables (lhs->variable_names ());\n\n          retval = new tree_complex_for_command (*for_tok, lhs, *eq_tok, expr, body, *end_tok);\n        }\n    }\n  else\n    {\n      delete lhs;\n      delete expr;\n      delete maxproc;\n      delete body;\n\n      end_token_error (end_tok, parfor ? token::parfor_end : token::for_end);\n    }\n\n  return retval;\n}\n\n// Build a break command.\n\ntree_command *\nbase_parser::make_break_command (token *break_tok)\n{\n  if (! m_lexer.m_looping)\n    {\n      bison_error (\"break must appear within a loop\");\n      return nullptr;\n    }\n  else\n    return new tree_break_command (*break_tok);\n}\n\n// Build a continue command.\n\ntree_command *\nbase_parser::make_continue_command (token *continue_tok)\n{\n  if (! m_lexer.m_looping)\n    {\n      bison_error (\"continue must appear within a loop\");\n      return nullptr;\n    }\n  else\n    return new tree_continue_command (*continue_tok);\n}\n\n// Build a return command.\n\ntree_command *\nbase_parser::make_return_command (token *return_tok)\n{\n  return new tree_return_command (*return_tok);\n}\n\n// Build an spmd command.\n\ntree_spmd_command *\nbase_parser::make_spmd_command (token *spmd_tok, tree_statement_list *body, token *end_tok)\n{\n  tree_spmd_command *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::spmd_end))\n    retval = new tree_spmd_command (*spmd_tok, body, *end_tok);\n  else\n    {\n      delete body;\n\n      end_token_error (end_tok, token::spmd_end);\n    }\n\n  return retval;\n}\n\n// Start an if command.\n\ntree_if_command_list *\nbase_parser::start_if_command (tree_if_clause *clause)\n{\n  return new tree_if_command_list (clause);\n}\n\n// Finish an if command.\n\ntree_if_command *\nbase_parser::finish_if_command (tree_if_command_list *list, tree_if_clause *else_clause, token *end_tok)\n{\n  tree_if_command *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::if_end))\n    {\n      if (else_clause)\n        list_append (list, else_clause);\n\n      token if_tok = list->if_token ();\n\n      retval = new tree_if_command (if_tok, list, *end_tok);\n    }\n  else\n    {\n      delete list;\n      delete else_clause;\n\n      end_token_error (end_tok, token::if_end);\n    }\n\n  return retval;\n}\n\n// Build an if, elseif, or else clause.\n\ntree_if_clause *\nbase_parser::make_if_clause (token *if_tok, separator_list *if_sep_list, tree_expression *expr, tree_statement_list *list)\n{\n  if (expr)\n    {\n      maybe_warn_assign_as_truth_value (expr);\n\n      maybe_convert_to_braindead_shortcircuit (expr);\n    }\n\n  // FIXME: Need to capture separator list here.\n  // For now, delete the unused list.\n  delete if_sep_list;\n\n  return new tree_if_clause (*if_tok, expr, list);\n}\n\ntree_if_command_list *\nbase_parser::append_if_clause (tree_if_command_list *list, tree_if_clause *clause)\n{\n  return list_append (list, clause);\n}\n\n// Finish a switch command.\n\ntree_switch_command *\nbase_parser::finish_switch_command (token *switch_tok, tree_expression *expr, tree_switch_case_list *list, token *end_tok)\n{\n  tree_switch_command *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::switch_end))\n    retval = new tree_switch_command (*switch_tok, expr, list, *end_tok);\n  else\n    {\n      delete expr;\n      delete list;\n\n      end_token_error (end_tok, token::switch_end);\n    }\n\n  return retval;\n}\n\ntree_switch_case_list *\nbase_parser::make_switch_case_list (tree_switch_case *switch_case)\n{\n  return new tree_switch_case_list (switch_case);\n}\n\n// Build a switch case.\n\ntree_switch_case *\nbase_parser::make_switch_case (token *case_tok, tree_expression *expr, tree_statement_list *list)\n{\n  maybe_warn_variable_switch_label (expr);\n\n  return new tree_switch_case (*case_tok, expr, list);\n}\n\ntree_switch_case *\nbase_parser::make_default_switch_case (token *default_tok, tree_statement_list *list)\n{\n  return new tree_switch_case (*default_tok, list);\n}\n\ntree_switch_case_list *\nbase_parser::append_switch_case (tree_switch_case_list *list, tree_switch_case *elt)\n{\n  return list_append (list, elt);\n}\n\n// Build an assignment to a variable.\n\ntree_expression *\nbase_parser::make_assign_op (tree_argument_list *lhs, token *eq_tok, tree_expression *rhs)\n{\n  octave_value::assign_op t = octave_value::unknown_assign_op;\n\n  int tok_id = eq_tok->token_id ();\n\n  switch (tok_id)\n    {\n    case '=':\n      t = octave_value::op_asn_eq;\n      break;\n\n    case ADD_EQ:\n      t = octave_value::op_add_eq;\n      break;\n\n    case SUB_EQ:\n      t = octave_value::op_sub_eq;\n      break;\n\n    case MUL_EQ:\n      t = octave_value::op_mul_eq;\n      break;\n\n    case DIV_EQ:\n      t = octave_value::op_div_eq;\n      break;\n\n    case LEFTDIV_EQ:\n      t = octave_value::op_ldiv_eq;\n      break;\n\n    case POW_EQ:\n      t = octave_value::op_pow_eq;\n      break;\n\n    case EMUL_EQ:\n      t = octave_value::op_el_mul_eq;\n      break;\n\n    case EDIV_EQ:\n      t = octave_value::op_el_div_eq;\n      break;\n\n    case ELEFTDIV_EQ:\n      t = octave_value::op_el_ldiv_eq;\n      break;\n\n    case EPOW_EQ:\n      t = octave_value::op_el_pow_eq;\n      break;\n\n    case AND_EQ:\n      t = octave_value::op_el_and_eq;\n      break;\n\n    case OR_EQ:\n      t = octave_value::op_el_or_eq;\n      break;\n\n    default:\n      unexpected_token (tok_id, \"base_parser::make_assign_op\");\n      break;\n    }\n\n  if (! lhs->is_simple_assign_lhs () && t != octave_value::op_asn_eq)\n    {\n      // Multiple assignments like [x,y] OP= rhs are only valid for\n      // '=', not '+=', etc.\n\n      delete lhs;\n      delete rhs;\n\n      bison_error (\"computed multiple assignment not allowed\", eq_tok->beg_pos ());\n\n      return nullptr;\n    }\n\n  if (lhs->is_simple_assign_lhs ())\n    {\n      // We are looking at a simple assignment statement like x = rhs;\n\n      tree_expression *tmp = lhs->remove_front ();\n\n      if ((tmp->is_identifier () || tmp->is_index_expression ()) && iskeyword (tmp->name ()))\n        {\n          std::string kw = tmp->name ();\n\n          delete tmp;\n          delete lhs;\n          delete rhs;\n\n          bison_error (\"invalid assignment to keyword \\\"\" + kw + \"\\\"\", eq_tok->beg_pos ());\n\n          return nullptr;\n        }\n\n      delete lhs;\n\n      m_lexer.mark_as_variable (tmp->name ());\n\n      return new tree_simple_assignment (tmp, rhs, false, t);\n    }\n  else\n    {\n      std::list<std::string> names = lhs->variable_names ();\n\n      for (const auto& kw : names)\n        {\n          if (iskeyword (kw))\n            {\n              delete lhs;\n              delete rhs;\n\n              bison_error (\"invalid assignment to keyword \\\"\" + kw + \"\\\"\", eq_tok->beg_pos ());\n\n              return nullptr;\n            }\n        }\n\n      m_lexer.mark_as_variables (names);\n\n      return new tree_multi_assignment (lhs, rhs, false);\n    }\n}\n\nvoid\nbase_parser::make_script (tree_statement_list *cmds, tree_statement *end_script)\n{\n  // Any comments at the beginning of a script file should be\n  // attached to the first statement in the file or the END_SCRIPT\n  // statement created by the parser.\n\n  if (! cmds)\n    cmds = new tree_statement_list ();\n\n  cmds->push_back (end_script);\n\n  symbol_scope script_scope = m_lexer.m_symtab_context.curr_scope ();\n\n  script_scope.cache_name (m_lexer.m_fcn_file_full_name);\n  script_scope.cache_fcn_file_name (m_lexer.m_fcn_file_full_name);\n  script_scope.cache_dir_name (m_lexer.m_dir_name);\n\n  // First non-copyright comment in classdef body, before first\n  // properties, methods, etc. block.\n\n  comment_list leading_comments = cmds->leading_comments ();\n\n  std::string doc_string = leading_comments.find_doc_string ();\n\n  octave_user_script *script = new octave_user_script (m_lexer.m_fcn_file_full_name, m_lexer.m_fcn_file_name, script_scope, cmds, doc_string);\n\n  m_lexer.m_symtab_context.pop ();\n\n  sys::time now;\n\n  script->stash_fcn_file_time (now);\n  script->stash_dir_name (m_lexer.m_dir_name);\n\n  m_primary_fcn = octave_value (script);\n}\n\ntree_identifier *\nbase_parser::make_fcn_name (tree_identifier *id)\n{\n  std::string id_name = id->name ();\n\n  // Make classdef local functions unique from classdef methods.\n\n  if (m_parsing_local_functions && m_curr_fcn_depth == 0)\n    id_name = m_lexer.m_fcn_file_name + \">\" + id_name;\n\n  if (! m_function_scopes.name_current_scope (id_name))\n    {\n      // FIXME: is this correct?  Before using position, the column\n      // was incremented.  Hmm.\n\n      filepos id_pos = id->beg_pos ();\n      id_pos.increment_column ();\n\n      bison_error (\"duplicate subfunction or nested function name\", id_pos);\n\n      delete id;\n      return nullptr;\n    }\n\n  symbol_scope curr_scope = m_lexer.m_symtab_context.curr_scope ();\n  curr_scope.cache_name (id_name);\n\n  m_lexer.m_parsed_function_name.top () = true;\n  m_lexer.m_maybe_classdef_get_set_method = false;\n\n  return id;\n}\n\n// Define a function.\n\n// FIXME: combining start_function, finish_function, and\n// recover_from_parsing_function should be possible, but it makes\n// for a large mess.  Maybe this could be a bit better organized?\n\ntree_function_def *\nbase_parser::make_function (token *fcn_tok, tree_parameter_list *ret_list, token *eq_tok, tree_identifier *id, tree_parameter_list *param_list, tree_statement_list *body, tree_statement *end_fcn_stmt)\n{\n  // First non-copyright comments found above and below function keyword.\n  comment_elt leading_doc_comment;\n  comment_elt body_doc_comment;\n\n  comment_list lc = fcn_tok->leading_comments ();\n\n  if (! lc.empty ())\n    leading_doc_comment = lc.find_doc_comment ();\n\n  if (body)\n    {\n      comment_list bc = body->leading_comments ();\n\n      if (! bc.empty ())\n        body_doc_comment = bc.find_doc_comment ();\n    }\n  else if (end_fcn_stmt)\n    {\n      comment_list ec = end_fcn_stmt->leading_comments ();\n\n      if (! ec.empty ())\n        body_doc_comment = ec.find_doc_comment ();\n    }\n\n  // Choose which comment to use for doc string.\n\n  // For ordinary functions, use the first comment that isn't empty.\n\n  // If we are looking at a classdef method and there is a comment\n  // prior to the function keyword and another after, then\n  //\n  //   * Choose the one outside the function definition if either of\n  //     the comments use hash '#' characters.  This is the preferred\n  //     Octave style.\n  //\n  //   * Choose the one inside the function definition if both\n  //     comments use percent '%' characters.  This is\n  //     Matlab-compatible behavior.\n\n  // FIXME: maybe choose which comment to used by checking whether\n  // any language extensions are noticed in the entire source file,\n  // not just in the comments that are candidates to become the\n  // function doc string.\n\n  std::string doc_string;\n\n  if (leading_doc_comment.empty ()\n      || (m_lexer.m_parsing_classdef && ! body_doc_comment.empty ()\n          && (! (leading_doc_comment.uses_hash_char () || body_doc_comment.uses_hash_char ()))))\n    doc_string = body_doc_comment.text ();\n  else\n    doc_string = leading_doc_comment.text ();\n\n  octave_user_function *tmp_fcn = start_function (id, param_list, body, end_fcn_stmt, doc_string);\n\n  tree_function_def *retval = finish_function (fcn_tok, ret_list, eq_tok, tmp_fcn);\n\n  recover_from_parsing_function ();\n\n  return retval;\n}\n\n// Begin defining a function.\n\noctave_user_function *\nbase_parser::start_function (tree_identifier *id, tree_parameter_list *param_list, tree_statement_list *body, tree_statement *end_fcn_stmt, const std::string& doc_string)\n{\n  // We'll fill in the return list later.\n\n  std::string id_name = id->name ();\n\n  if (m_lexer.m_parsing_classdef_get_method)\n    id_name.insert (0, \"get.\");\n  else if (m_lexer.m_parsing_classdef_set_method)\n    id_name.insert (0, \"set.\");\n\n  m_lexer.m_parsing_classdef_get_method = false;\n  m_lexer.m_parsing_classdef_set_method = false;\n\n  if (! body)\n    body = new tree_statement_list ();\n\n  body->push_back (end_fcn_stmt);\n\n  octave_user_function *fcn = new octave_user_function (m_lexer.m_symtab_context.curr_scope (), id, param_list, nullptr, body);\n\n  // If input is coming from a file, issue a warning if the name of\n  // the file does not match the name of the function stated in the\n  // file.  Matlab doesn't provide a diagnostic (it ignores the stated\n  // name).\n  if (! m_autoloading && m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)\n    {\n      // FIXME: should m_lexer.m_fcn_file_name already be\n      // preprocessed when we get here?  It seems to only be a\n      // problem with relative filenames.\n\n      std::string nm = m_lexer.m_fcn_file_name;\n\n      std::size_t pos = nm.find_last_of (sys::file_ops::dir_sep_chars ());\n\n      if (pos != std::string::npos)\n        nm = m_lexer.m_fcn_file_name.substr (pos+1);\n\n      if (nm != id_name)\n        {\n          warning_with_id (\"Octave:function-name-clash\", \"function name '%s' does not agree with function filename '%s'\", id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());\n\n          id_name = nm;\n        }\n    }\n\n  sys::time now;\n\n  fcn->stash_fcn_file_name (m_lexer.m_fcn_file_full_name);\n  fcn->stash_fcn_file_time (now);\n  fcn->stash_dir_name (m_lexer.m_dir_name);\n  fcn->stash_package_name (m_lexer.m_package_name);\n  fcn->mark_as_system_fcn_file ();\n  fcn->stash_function_name (id_name);\n\n  if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_classdef_file || m_autoloading)\n    {\n      if (m_fcn_file_from_relative_lookup)\n        fcn->mark_relative ();\n\n      if (m_lexer.m_parsing_class_method)\n        {\n          if (m_lexer.m_parsing_classdef)\n            {\n              if (m_curr_class_name == id_name)\n                fcn->mark_as_classdef_constructor ();\n              else\n                fcn->mark_as_classdef_method ();\n            }\n          else\n            {\n              if (m_curr_class_name == id_name)\n                fcn->mark_as_legacy_constructor ();\n              else\n                fcn->mark_as_legacy_method ();\n            }\n\n          fcn->stash_dispatch_class (m_curr_class_name);\n        }\n\n      std::string nm = fcn->fcn_file_name ();\n\n      sys::file_stat fs (nm);\n\n      if (fs && fs.is_newer (now))\n        warning_with_id (\"Octave:future-time-stamp\", \"time stamp for '%s' is in the future\", nm.c_str ());\n    }\n  else if (! m_lexer.input_from_tmp_history_file () && ! m_lexer.m_force_script && m_lexer.m_reading_script_file && m_lexer.m_fcn_file_name == id_name)\n    warning (\"function '%s' defined within script file '%s'\", id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());\n\n  // Record doc string for functions other than nested functions.\n  // We cannot currently record help for nested functions (bug #46008)\n  // because the doc_string of the outermost function is read first,\n  // whereas this function is called for the innermost function first.\n  // We could have a stack of doc_string objects in lexer.\n  if (! doc_string.empty () && m_curr_fcn_depth == 0)\n    fcn->document (doc_string);\n\n\n  if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)\n    m_primary_fcn = octave_value (fcn);\n\n  return fcn;\n}\n\ntree_statement *\nbase_parser::make_end (const std::string& type, bool eof, token *end_tok)\n{\n  return make_statement (new tree_no_op_command (type, eof, *end_tok));\n}\n\ntree_function_def *\nbase_parser::finish_function (token *fcn_tok, tree_parameter_list *ret_list, token *eq_tok, octave_user_function *fcn)\n{\n  tree_function_def *retval = nullptr;\n\n  if (! ret_list)\n    ret_list = new tree_parameter_list (tree_parameter_list::out);\n\n  ret_list->mark_as_formal_parameters ();\n\n  if (fcn)\n    {\n      fcn->set_fcn_tok (*fcn_tok);\n\n      if (eq_tok)\n        fcn->set_eq_tok (*eq_tok);\n\n      std::string fcn_nm = fcn->name ();\n      std::string file = fcn->fcn_file_name ();\n\n      std::string tmp = fcn_nm;\n      if (! file.empty ())\n        tmp += \": \" + file;\n\n      symbol_scope fcn_scope = fcn->scope ();\n      fcn_scope.cache_name (tmp);\n      fcn_scope.cache_fcn_name (fcn_nm);\n      fcn_scope.cache_fcn_file_name (file);\n      fcn_scope.cache_dir_name (m_lexer.m_dir_name);\n\n      fcn->define_ret_list (ret_list);\n\n      if (m_curr_fcn_depth > 0 || m_parsing_subfunctions)\n        {\n          octave_value ov_fcn (fcn);\n\n          if (m_endfunction_found && m_function_scopes.size () > 1)\n            {\n              fcn->mark_as_nested_function ();\n              fcn_scope.set_nesting_depth (m_curr_fcn_depth);\n\n              symbol_scope pscope = m_function_scopes.parent_scope ();\n              fcn_scope.set_parent (pscope);\n              fcn_scope.set_primary_parent (m_primary_fcn_scope);\n\n              pscope.install_nestfunction (fcn_nm, ov_fcn, fcn_scope);\n\n              // For nested functions, the list of parent functions is\n              // set in symbol_scope::update_nest.\n            }\n          else\n            {\n              fcn->mark_as_subfunction ();\n              m_subfunction_names.push_back (fcn_nm);\n\n              fcn_scope.set_parent (m_primary_fcn_scope);\n              if (m_parsing_subfunctions)\n                fcn_scope.set_primary_parent (m_primary_fcn_scope);\n\n              m_primary_fcn_scope.install_subfunction (fcn_nm, ov_fcn);\n            }\n        }\n\n      if (m_curr_fcn_depth == 0)\n        fcn_scope.update_nest ();\n\n      if (! m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0)\n        {\n          // We are either reading a script file or defining a function\n          // at the command line, so this definition creates a\n          // tree_function object that is placed in the parse tree.\n          // Otherwise, it is just inserted in the symbol table,\n          // either as a subfunction or nested function (see above),\n          // or as the primary function for the file, via\n          // m_primary_fcn (see also load_fcn_from_file,,\n          // parse_fcn_file, and\n          // fcn_info::fcn_info_rep::find_user_function).\n\n          if (m_lexer.m_buffer_function_text)\n            {\n              fcn->cache_function_text (m_lexer.m_function_text, fcn->time_parsed ());\n              m_lexer.m_buffer_function_text = false;\n            }\n\n          retval = new tree_function_def (fcn);\n        }\n    }\n\n  return retval;\n}\n\ntree_statement_list *\nbase_parser::append_function_body (tree_statement_list *body, tree_statement_list *list)\n{\n  if (list)\n    {\n      for (const auto& elt : *list)\n        list_append (body, elt);\n\n      list->clear ();\n      delete (list);\n    }\n\n  return body;\n}\n\ntree_arguments_block *\nbase_parser::make_arguments_block (token *arguments_tok, tree_args_block_attribute_list *attr_list, tree_args_block_validation_list *validation_list, token *end_tok)\n{\n  tree_arguments_block *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::arguments_end))\n    retval = new tree_arguments_block (*arguments_tok, attr_list, validation_list, *end_tok);\n  else\n    {\n      delete attr_list;\n      delete validation_list;\n    }\n\n  return retval;\n}\n\ntree_arg_validation *\nbase_parser::make_arg_validation (tree_arg_size_spec *size_spec, tree_identifier *class_name, tree_arg_validation_fcns *validation_fcns, token *eq_tok, tree_expression *default_value)\n{\n  // FIXME: Validate arguments and convert to more specific types\n  // (std::string for arg_name and class_name, etc).\n\n  token tmp_eq_tok = eq_tok ? *eq_tok : token ();\n\n  return new tree_arg_validation (size_spec, class_name, validation_fcns, tmp_eq_tok, default_value);\n}\n\ntree_args_block_attribute_list *\nbase_parser::make_args_attribute_list (tree_identifier *attribute_name)\n{\n  // FIXME: Validate argument and convert to more specific type\n  // (std::string for attribute_name).\n\n  return new tree_args_block_attribute_list (attribute_name);\n}\n\ntree_args_block_validation_list *\nbase_parser::make_args_validation_list (tree_arg_validation *arg_validation)\n{\n  return new tree_args_block_validation_list (arg_validation);\n}\n\ntree_args_block_validation_list *\nbase_parser::append_args_validation_list (tree_args_block_validation_list *list, tree_arg_validation *arg_validation)\n{\n  return list_append (list, arg_validation);\n}\n\ntree_arg_size_spec *\nbase_parser::make_arg_size_spec (tree_argument_list *size_args)\n{\n  // FIXME: Validate argument.\n\n  return new tree_arg_size_spec (size_args);\n}\n\ntree_arg_validation_fcns *\nbase_parser::make_arg_validation_fcns (tree_argument_list *fcn_args)\n{\n  // FIXME: Validate argument.\n\n  return new tree_arg_validation_fcns (fcn_args);\n}\n\nvoid\nbase_parser::recover_from_parsing_function ()\n{\n  m_lexer.m_symtab_context.pop ();\n\n  if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)\n    m_parsing_subfunctions = true;\n\n  m_curr_fcn_depth--;\n  m_function_scopes.pop ();\n\n  m_lexer.m_defining_fcn--;\n  m_lexer.m_parsed_function_name.pop ();\n  m_lexer.m_looking_at_return_list = false;\n  m_lexer.m_looking_at_parameter_list = false;\n}\n\n// A CLASSDEF block defines a class that has a constructor and other\n// methods, but it is not an executable command.  Parsing the block\n// makes some changes in the symbol table (inserting the constructor\n// and methods, and adding to the list of known objects) and creates\n// a parse tree containing meta information about the class.\n\ntree_classdef *\nbase_parser::make_classdef (token *cdef_tok, tree_classdef_attribute_list *a, tree_identifier *id, tree_classdef_superclass_list *sc, tree_classdef_body *body, token *end_tok)\n{\n  tree_classdef *retval = nullptr;\n\n  m_lexer.m_symtab_context.pop ();\n\n  std::string cls_name = id->name ();\n\n  std::string full_name = m_lexer.m_fcn_file_full_name;\n  std::string short_name = m_lexer.m_fcn_file_name;\n\n  std::size_t pos = short_name.find_last_of (sys::file_ops::dir_sep_chars ());\n\n  if (pos != std::string::npos)\n    short_name = short_name.substr (pos+1);\n\n  if (short_name != cls_name)\n    {\n      filepos f_pos = id->beg_pos ();\n\n      delete a;\n      delete id;\n      delete sc;\n      delete body;\n\n      bison_error (\"invalid classdef definition, the class name must match the filename\", f_pos);\n\n    }\n  else\n    {\n      if (end_token_ok (end_tok, token::classdef_end))\n        {\n          if (! body)\n            body = new tree_classdef_body ();\n\n          retval = new tree_classdef (m_lexer.m_symtab_context.curr_scope (), *cdef_tok, a, id, sc, body, *end_tok, m_curr_package_name, full_name);\n        }\n      else\n        {\n          delete a;\n          delete id;\n          delete sc;\n          delete body;\n\n          end_token_error (end_tok, token::switch_end);\n        }\n    }\n\n  return retval;\n}\n\ntree_classdef_properties_block *\nbase_parser::make_classdef_properties_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_property_list *plist, token *end_tok)\n{\n  tree_classdef_properties_block *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::properties_end))\n    {\n      if (plist)\n        {\n          // If the element at the end of the list doesn't have a doc\n          // string, see whether the first element of the comments\n          // attached to the end token is an end-of-line comment for\n          // us to use.\n\n          tree_classdef_property *last_elt = plist->back ();\n\n          if (last_elt && ! last_elt->have_doc_string ())\n            {\n              comment_list comments = end_tok->leading_comments ();\n\n              if (! comments.empty ())\n                {\n                  comment_elt elt = comments.front ();\n\n                  if (elt.is_end_of_line ())\n                    last_elt->doc_string (elt.text ());\n                }\n            }\n        }\n      else\n        plist = new tree_classdef_property_list ();\n\n      retval = new tree_classdef_properties_block (*tok, a, plist, *end_tok);\n    }\n  else\n    {\n      delete a;\n      delete plist;\n\n      end_token_error (end_tok, token::properties_end);\n    }\n\n  return retval;\n}\n\ntree_classdef_property_list *\nbase_parser::make_classdef_property_list (tree_classdef_property *prop)\n{\n  return new tree_classdef_property_list (prop);\n}\n\ntree_classdef_property *\nbase_parser::make_classdef_property (tree_identifier *id, tree_arg_validation *av)\n{\n  av->arg_name (id);\n\n  if (av->size_spec () || av->class_name () || av->validation_fcns ())\n    warning (\"size, class, and validation function specifications are not yet supported for classdef properties; INCORRECT RESULTS ARE POSSIBLE!\");\n\n  return new tree_classdef_property (av);\n}\n\ntree_classdef_methods_block *\nbase_parser::make_classdef_methods_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_method_list *mlist, token *end_tok)\n{\n  tree_classdef_methods_block *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::methods_end))\n    {\n      if (! mlist)\n        mlist = new tree_classdef_method_list ();\n\n      retval = new tree_classdef_methods_block (*tok, a, mlist, *end_tok);\n    }\n  else\n    {\n      delete a;\n      delete mlist;\n\n      end_token_error (end_tok, token::methods_end);\n    }\n\n  return retval;\n}\n\ntree_classdef_events_block *\nbase_parser::make_classdef_events_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_event_list *elist, token *end_tok)\n{\n  tree_classdef_events_block *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::events_end))\n    {\n      if (! elist)\n        elist = new tree_classdef_event_list ();\n\n      retval = new tree_classdef_events_block (*tok, a, elist, *end_tok);\n    }\n  else\n    {\n      delete a;\n      delete elist;\n\n      end_token_error (end_tok, token::events_end);\n    }\n\n  return retval;\n}\n\ntree_classdef_event_list *\nbase_parser::make_classdef_event_list (tree_classdef_event *e)\n{\n  return new tree_classdef_event_list (e);\n}\n\ntree_classdef_event *\nbase_parser::make_classdef_event (tree_identifier *id)\n{\n  return new tree_classdef_event (id);\n}\n\ntree_classdef_enum_block *\nbase_parser::make_classdef_enum_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_enum_list *elist, token *end_tok)\n{\n  tree_classdef_enum_block *retval = nullptr;\n\n  if (end_token_ok (end_tok, token::enumeration_end))\n    {\n      if (! elist)\n        elist = new tree_classdef_enum_list ();\n\n      retval = new tree_classdef_enum_block (*tok, a, elist, *end_tok);\n    }\n  else\n    {\n      delete a;\n      delete elist;\n\n      end_token_error (end_tok, token::enumeration_end);\n    }\n\n  return retval;\n}\n\ntree_classdef_enum_list *\nbase_parser::make_classdef_enum_list (tree_classdef_enum *e)\n{\n  return new tree_classdef_enum_list (e);\n}\n\ntree_classdef_enum *\nbase_parser::make_classdef_enum (tree_identifier *id, token *open_paren, tree_expression *expr, token *close_paren)\n{\n  return new tree_classdef_enum (id, *open_paren, expr, *close_paren);\n}\n\ntree_classdef_property_list *\nbase_parser::append_classdef_property (tree_classdef_property_list *list, tree_classdef_property *elt)\n{\n  return list_append (list, elt);\n}\n\ntree_classdef_event_list *\nbase_parser::append_classdef_event (tree_classdef_event_list *list, tree_classdef_event *elt)\n{\n  return list_append (list, elt);\n}\n\ntree_classdef_enum_list *\nbase_parser::append_classdef_enum (tree_classdef_enum_list *list, tree_classdef_enum *elt)\n{\n  return list_append (list, elt);\n}\n\ntree_classdef_superclass_list *\nbase_parser::make_classdef_superclass_list (token *lt_tok, tree_classdef_superclass *sc)\n{\n  sc->set_separator (*lt_tok);\n\n  return new tree_classdef_superclass_list (sc);\n}\n\ntree_classdef_superclass *\nbase_parser::make_classdef_superclass (token *fqident)\n{\n  return new tree_classdef_superclass (*fqident);\n}\n\ntree_classdef_superclass_list *\nbase_parser::append_classdef_superclass (tree_classdef_superclass_list *list, token *and_tok, tree_classdef_superclass *elt)\n{\n  elt->set_separator (*and_tok);\n\n  return list_append (list, elt);\n}\n\ntree_classdef_attribute_list *\nbase_parser::make_classdef_attribute_list (tree_classdef_attribute *attr)\n{\n  return new tree_classdef_attribute_list (attr);\n}\n\ntree_classdef_attribute *\nbase_parser::make_classdef_attribute (tree_identifier *id)\n{\n  return make_classdef_attribute (id, nullptr, nullptr);\n}\n\ntree_classdef_attribute *\nbase_parser::make_classdef_attribute (tree_identifier *id, token *eq_tok, tree_expression *expr)\n{\n  return (expr ? new tree_classdef_attribute (id, *eq_tok, expr) : new tree_classdef_attribute (id));\n}\n\ntree_classdef_attribute *\nbase_parser::make_not_classdef_attribute (token *not_tok, tree_identifier *id)\n{\n  return new tree_classdef_attribute (*not_tok, id, false);\n}\n\ntree_classdef_attribute_list *\nbase_parser::append_classdef_attribute (tree_classdef_attribute_list *list, token *sep_tok, tree_classdef_attribute *elt)\n{\n  return list_append (list, *sep_tok, elt);\n}\n\ntree_classdef_body *\nbase_parser::make_classdef_body (tree_classdef_properties_block *pb)\n{\n  return new tree_classdef_body (pb);\n}\n\ntree_classdef_body *\nbase_parser::make_classdef_body (tree_classdef_methods_block *mb)\n{\n  return new tree_classdef_body (mb);\n}\n\ntree_classdef_body *\nbase_parser::make_classdef_body (tree_classdef_events_block *evb)\n{\n  return new tree_classdef_body (evb);\n}\n\ntree_classdef_body *\nbase_parser::make_classdef_body  (tree_classdef_enum_block *enb)\n{\n  return new tree_classdef_body (enb);\n}\n\ntree_classdef_body *\nbase_parser::append_classdef_properties_block (tree_classdef_body *body, tree_classdef_properties_block *block)\n{\n  return body->append (block);\n}\n\ntree_classdef_body *\nbase_parser::append_classdef_methods_block (tree_classdef_body *body, tree_classdef_methods_block *block)\n{\n  return body->append (block);\n}\n\ntree_classdef_body *\nbase_parser::append_classdef_events_block (tree_classdef_body *body, tree_classdef_events_block *block)\n{\n  return body->append (block);\n}\n\ntree_classdef_body *\nbase_parser::append_classdef_enum_block (tree_classdef_body *body, tree_classdef_enum_block *block)\n{\n  return body->append (block);\n}\n\noctave_user_function*\nbase_parser::start_classdef_external_method (tree_identifier *id, tree_parameter_list *pl)\n{\n  octave_user_function* retval = nullptr;\n\n  // External methods are only allowed within @-folders.  In this case,\n  // m_curr_class_name will be non-empty.\n\n  if (! m_curr_class_name.empty ())\n    {\n      std::string mname = id->name ();\n\n      // Methods that cannot be declared outside the classdef file:\n      // - methods with '.' character (e.g., property accessors)\n      // - class constructor\n      // - 'delete'\n\n      if (mname.find_first_of (\".\") == std::string::npos && mname != \"delete\" && mname != m_curr_class_name)\n        {\n          // Create a dummy function that is used until the real method\n          // is loaded.\n\n          retval = new octave_user_function (symbol_scope::anonymous (), id, pl);\n\n          retval->stash_function_name (mname);\n        }\n      else\n        bison_error (\"invalid external method declaration, an external method cannot be the class constructor, 'delete' or have a dot (.) character in its name\");\n    }\n  else\n    bison_error (\"external methods are only allowed in @-folders\");\n\n  return retval;\n}\n\ntree_function_def *\nbase_parser::finish_classdef_external_method (octave_user_function *fcn, tree_parameter_list *ret_list, token *eq_tok)\n{\n  if (! ret_list)\n    ret_list = new tree_parameter_list (tree_parameter_list::out);\n\n  fcn->define_ret_list (ret_list);\n\n  if (eq_tok)\n    fcn->set_eq_tok (*eq_tok);\n\n  return new tree_function_def (fcn);\n}\n\ntree_classdef_method_list *\nbase_parser::make_classdef_method_list (tree_function_def *fcn_def)\n{\n  octave_value fcn;\n\n  if (fcn_def)\n    fcn = fcn_def->function ();\n\n  delete fcn_def;\n\n  return new tree_classdef_method_list (fcn);\n}\n\ntree_classdef_method_list *\nbase_parser::append_classdef_method (tree_classdef_method_list *list, tree_function_def *fcn_def)\n{\n  octave_value fcn;\n\n  if (fcn_def)\n    {\n      fcn = fcn_def->function ();\n\n      delete fcn_def;\n    }\n\n  return list_append (list, fcn);\n}\n\nbool\nbase_parser::finish_classdef_file (tree_classdef *cls, tree_statement_list *local_fcns, token *eof_tok)\n{\n  parse_tree_validator validator;\n\n  cls->accept (validator);\n\n  if (local_fcns)\n    {\n      for (tree_statement *elt : *local_fcns)\n        {\n          tree_command *cmd = elt->command ();\n\n          tree_function_def *fcn_def = dynamic_cast<tree_function_def *> (cmd);\n\n          fcn_def->accept (validator);\n        }\n    }\n\n  if (! validator.ok ())\n    {\n      delete cls;\n      delete local_fcns;\n\n      bison_error (validator.error_list ());\n\n      return false;\n    }\n\n  // Require all validations to succeed before installing any local\n  // functions or defining the classdef object for later use.\n\n  if (local_fcns)\n    {\n      interpreter& interp = m_lexer.m_interpreter;\n\n      symbol_table& symtab = interp.get_symbol_table ();\n\n      for (tree_statement *elt : *local_fcns)\n        {\n          tree_command *cmd = elt->command ();\n\n          tree_function_def *fcn_def = dynamic_cast<tree_function_def *> (cmd);\n\n          octave_value ov_fcn = fcn_def->function ();\n          octave_user_function *fcn = ov_fcn.user_function_value ();\n\n          std::string nm = fcn->name ();\n          std::string file = fcn->fcn_file_name ();\n\n          fcn->attach_trailing_comments (eof_tok->leading_comments ());\n\n          symtab.install_local_function (nm, ov_fcn, file);\n        }\n\n      delete local_fcns;\n    }\n\n  // FIXME: Is it possible for the following condition to be false?\n  if (m_lexer.m_reading_classdef_file)\n    m_classdef_object = std::shared_ptr<tree_classdef> (cls);\n\n  return true;\n}\n\n// Make a word list command.\ntree_index_expression *\nbase_parser::make_word_list_command (tree_expression *expr, tree_argument_list *args)\n{\n  tree_index_expression *retval = make_index_expression (expr, nullptr, args, nullptr, '(');\n\n  if (retval)\n    retval->mark_word_list_cmd ();\n\n  return retval;\n}\n\n// Make an index expression.\n\ntree_index_expression *\nbase_parser::make_index_expression (tree_expression *expr, token *open_delim, tree_argument_list *args, token *close_delim, char type)\n{\n  tree_index_expression *retval = nullptr;\n\n  if (! args)\n    args = new tree_argument_list ();\n\n  if (args->has_magic_tilde ())\n    {\n      delete expr;\n      delete args;\n\n      bison_error (\"invalid use of empty argument (~) in index expression\");\n    }\n  else\n    {\n      if (! expr->is_postfix_indexed ())\n        expr->set_postfix_index (type);\n\n      token tmp_open_delim = open_delim ? *open_delim : token ();\n      token tmp_close_delim = close_delim ? *close_delim : token ();\n\n      if (expr->is_index_expression ())\n        {\n          retval = dynamic_cast<tree_index_expression *> (expr);\n\n          retval->append (tmp_open_delim, args, tmp_close_delim, type);\n        }\n      else\n        retval = new tree_index_expression (expr, tmp_open_delim, args, tmp_close_delim, type);\n    }\n\n  return retval;\n}\n\n// Make an indirect reference expression.\n\ntree_index_expression *\nbase_parser::make_indirect_ref (tree_expression *expr, token *dot_tok, token *struct_elt_tok)\n{\n  tree_index_expression *retval = nullptr;\n\n  if (! expr->is_postfix_indexed ())\n    expr->set_postfix_index ('.');\n\n  if (expr->is_index_expression ())\n    {\n      retval = dynamic_cast<tree_index_expression *> (expr);\n\n      retval->append (*dot_tok, *struct_elt_tok);\n    }\n  else\n    retval = new tree_index_expression (expr, *dot_tok, *struct_elt_tok);\n\n  m_lexer.m_looking_at_indirect_ref = false;\n\n  return retval;\n}\n\n// Make an indirect reference expression with dynamic field name.\n\ntree_index_expression *\nbase_parser::make_indirect_ref (tree_expression *expr, token *dot_tok, token *open_paren, tree_expression *elt, token *close_paren)\n{\n  tree_index_expression *retval = nullptr;\n\n  if (! expr->is_postfix_indexed ())\n    expr->set_postfix_index ('.');\n\n  if (expr->is_index_expression ())\n    {\n      retval = dynamic_cast<tree_index_expression *> (expr);\n\n      retval->append (*dot_tok, *open_paren, elt, *close_paren);\n    }\n  else\n    retval = new tree_index_expression (expr, *dot_tok, *open_paren, elt, *close_paren);\n\n  m_lexer.m_looking_at_indirect_ref = false;\n\n  return retval;\n}\n\n// Make a declaration command.\n\ntree_decl_command *\nbase_parser::make_decl_command (token *tok, tree_decl_init_list *lst)\n{\n  tree_decl_command *retval = nullptr;\n\n  if (lst)\n    m_lexer.mark_as_variables (lst->variable_names ());\n\n  int tok_id = tok->token_id ();\n\n  switch (tok->token_id ())\n    {\n    case GLOBAL:\n      {\n        retval = new tree_decl_command (\"global\", *tok, lst);\n        retval->mark_global ();\n      }\n      break;\n\n    case PERSISTENT:\n      if (m_curr_fcn_depth >= 0)\n        {\n          retval = new tree_decl_command (\"persistent\", *tok, lst);\n          retval->mark_persistent ();\n        }\n      else\n        {\n          filepos pos = tok->beg_pos ();\n          int line = pos.line ();\n\n          if (m_lexer.m_reading_script_file)\n            warning (\"ignoring persistent declaration near line %d of file '%s'\", line, m_lexer.m_fcn_file_full_name.c_str ());\n          else\n            warning (\"ignoring persistent declaration near line %d\", line);\n        }\n      break;\n\n    default:\n      unexpected_token (tok_id, \"base_parser::make_decl_command\");\n      break;\n    }\n\n  return retval;\n}\n\ntree_decl_init_list *\nbase_parser::make_decl_init_list (tree_decl_elt *elt)\n{\n  return new tree_decl_init_list (elt);\n}\n\ntree_decl_init_list *\nbase_parser::append_decl_init_list (tree_decl_init_list *list, tree_decl_elt *elt)\n{\n  return list_append (list, elt);\n}\n\ntree_decl_elt *\nbase_parser::make_decl_elt (tree_identifier *id, token */*eq_op*/, tree_expression *expr)\n{\n  // FIXME: Need to capture EQ_OP here.\n  return expr ? new tree_decl_elt (id, expr) : new tree_decl_elt (id);\n}\n\nbool\nbase_parser::validate_param_list (tree_parameter_list *lst, tree_parameter_list::in_or_out type)\n{\n  std::set<std::string> dict;\n\n  for (tree_decl_elt *elt : *lst)\n    {\n      tree_identifier *id = elt->ident ();\n\n      if (id)\n        {\n          std::string name = id->name ();\n\n          if (id->is_black_hole ())\n            {\n              if (type != tree_parameter_list::in)\n                {\n                  bison_error (\"invalid use of ~ in output list\");\n                  return false;\n                }\n            }\n          else if (iskeyword (name))\n            {\n              bison_error (\"invalid use of keyword '\" + name + \"' in parameter list\");\n              return false;\n            }\n          else if (dict.find (name) != dict.end ())\n            {\n              bison_error (\"'\" + name + \"' appears more than once in parameter list\");\n              return false;\n            }\n          else\n            dict.insert (name);\n        }\n    }\n\n  std::string va_type = (type == tree_parameter_list::in ? \"varargin\" : \"varargout\");\n\n  std::size_t len = lst->size ();\n\n  if (len > 0)\n    {\n      tree_decl_elt *elt = lst->back ();\n\n      tree_identifier *id = elt->ident ();\n\n      if (id && id->name () == va_type)\n        {\n          if (len == 1)\n            lst->mark_varargs_only ();\n          else\n            lst->mark_varargs ();\n\n          tree_parameter_list::iterator p = lst->end ();\n          --p;\n          delete *p;\n          lst->erase (p);\n        }\n    }\n\n  return true;\n}\n\nbool\nbase_parser::validate_array_list (tree_expression *e)\n{\n  bool retval = true;\n\n  tree_array_list *al = dynamic_cast<tree_array_list *> (e);\n\n  for (tree_argument_list* row : *al)\n    {\n      if (row && row->has_magic_tilde ())\n        {\n          retval = false;\n\n          if (e->is_matrix ())\n            bison_error (\"invalid use of tilde (~) in matrix expression\");\n          else\n            bison_error (\"invalid use of tilde (~) in cell expression\");\n\n          break;\n        }\n    }\n\n  return retval;\n}\n\ntree_argument_list *\nbase_parser::validate_matrix_for_assignment (tree_expression *e)\n{\n  tree_argument_list *retval = nullptr;\n\n  if (e->is_constant ())\n    {\n      interpreter& interp = m_lexer.m_interpreter;\n\n      tree_evaluator& tw = interp.get_evaluator ();\n\n      octave_value ov = e->evaluate (tw);\n\n      delete e;\n\n      if (ov.isempty ())\n        bison_error (\"invalid empty left hand side of assignment\");\n      else\n        bison_error (\"invalid constant left hand side of assignment\");\n    }\n  else\n    {\n      bool is_simple_assign = true;\n\n      tree_argument_list *tmp = nullptr;\n\n      if (e->is_matrix ())\n        {\n          tree_matrix *mat = dynamic_cast<tree_matrix *> (e);\n\n          if (mat && mat->size () == 1)\n            {\n              tmp = mat->front ();\n              mat->pop_front ();\n              delete e;\n              is_simple_assign = false;\n            }\n        }\n      else\n        tmp = new tree_argument_list (e);\n\n      if (tmp && tmp->is_valid_lvalue_list ())\n        {\n          m_lexer.mark_as_variables (tmp->variable_names ());\n          retval = tmp;\n        }\n      else\n        {\n          delete tmp;\n\n          bison_error (\"invalid left hand side of assignment\");\n        }\n\n      if (retval && is_simple_assign)\n        retval->mark_as_simple_assign_lhs ();\n    }\n\n  return retval;\n}\n\n// Finish building an array_list.\n\ntree_expression *\nbase_parser::finish_array_list (token *open_delim, tree_array_list *array_list, token *close_delim)\n{\n  tree_expression *retval = array_list;\n\n  array_list->mark_in_delims (*open_delim, *close_delim);\n\n  if (array_list->all_elements_are_constant ())\n    {\n      interpreter& interp = m_lexer.m_interpreter;\n\n      try\n        {\n          // If the evaluation generates a warning message, restore\n          // the previous value of last_warning_message and skip the\n          // conversion to a constant value.\n\n          error_system& es = interp.get_error_system ();\n\n          unwind_action restore_last_warning_message (&error_system::set_last_warning_message, &es, es.last_warning_message (\"\"));\n\n          unwind_action restore_discard_warning_messages (&error_system::set_discard_warning_messages, &es, es.discard_warning_messages (true));\n\n          tree_evaluator& tw = interp.get_evaluator ();\n\n          octave_value tmp = array_list->evaluate (tw);\n\n          std::string msg = es.last_warning_message ();\n\n          if (msg.empty ())\n            {\n              std::ostringstream buf;\n\n              tree_print_code tpc (buf);\n\n              array_list->accept (tpc);\n\n              std::string orig_text = buf.str ();\n\n              token tok (CONSTANT, tmp, orig_text, open_delim->beg_pos (), close_delim->end_pos ());\n\n              tree_constant *tc_retval = new tree_constant (tmp, orig_text, tok);\n\n              delete array_list;\n\n              retval = tc_retval;\n            }\n        }\n      catch (const execution_exception&)\n        {\n          interp.recover_from_exception ();\n        }\n    }\n\n  return retval;\n}\n\n// Finish building a matrix list.\n\ntree_expression *\nbase_parser::finish_matrix (token *open_delim, tree_matrix *m, token *close_delim)\n{\n  if (m)\n    return finish_array_list (open_delim, m, close_delim);\n\n  octave_value tmp {octave_null_matrix::instance};\n  std::string orig_text {\"{}\"};\n\n  token tok (CONSTANT, tmp, orig_text, open_delim->beg_pos (), close_delim->end_pos ());\n\n  return new tree_constant (tmp, orig_text, tok);\n}\n\ntree_matrix *\nbase_parser::make_matrix (tree_argument_list *row)\n{\n  return row ? new tree_matrix (row) : nullptr;\n}\n\ntree_matrix *\nbase_parser::append_matrix_row (tree_matrix *matrix, token *sep_tok, tree_argument_list *row)\n{\n  if (! matrix)\n    return make_matrix (row);\n\n  return row ? list_append (matrix, *sep_tok, row) : matrix;\n}\n\n// Finish building a cell list.\n\ntree_expression *\nbase_parser::finish_cell (token *open_delim, tree_cell *c, token *close_delim)\n{\n  if (c)\n    return finish_array_list (open_delim, c, close_delim);\n\n  octave_value tmp {Cell ()};\n  std::string orig_text {\"{}\"};\n\n  token tok (CONSTANT, tmp, orig_text, open_delim->beg_pos (), close_delim->end_pos ());\n\n  return new tree_constant (tmp, orig_text, tok);\n}\n\ntree_cell *\nbase_parser::make_cell (tree_argument_list *row)\n{\n  return row ? new tree_cell (row) : nullptr;\n}\n\ntree_cell *\nbase_parser::append_cell_row (tree_cell *cell, token *sep_tok, tree_argument_list *row)\n{\n  if (! cell)\n    return make_cell (row);\n\n  return row ? list_append (cell, *sep_tok, row) : cell;\n}\n\ntree_identifier *\nbase_parser::make_identifier (token *ident)\n{\n  symbol_scope scope = m_lexer.m_symtab_context.curr_scope ();\n\n  return new tree_identifier (scope, *ident);\n}\n\ntree_superclass_ref *\nbase_parser::make_superclass_ref (token *superclassref)\n{\n  std::string meth = superclassref->superclass_method_name ();\n  std::string cls = superclassref->superclass_class_name ();\n\n  return new tree_superclass_ref (meth, cls, *superclassref);\n}\n\ntree_metaclass_query *\nbase_parser::make_metaclass_query (token *metaquery)\n{\n  std::string cls = metaquery->text ();\n\n  return new tree_metaclass_query (cls, *metaquery);\n}\n\ntree_statement_list *\nbase_parser::set_stmt_print_flag (tree_statement_list *list, int sep_char, bool warn_missing_semi)\n{\n  tree_statement *tmp = list->back ();\n\n  switch (sep_char)\n    {\n    case ';':\n      tmp->set_print_flag (false);\n      break;\n\n    case '\\0':\n    case ',':\n    case '\\n':\n      tmp->set_print_flag (true);\n      if (warn_missing_semi)\n        maybe_warn_missing_semi (list);\n      break;\n\n    default:\n      warning (\"unrecognized separator type!\");\n      break;\n    }\n\n  // Even if a statement is null, we add it to the list then remove it\n  // here so that the print flag is applied to the correct statement.\n\n  if (tmp->is_null_statement ())\n    {\n      list->pop_back ();\n      delete tmp;\n    }\n\n  return list;\n}\n\ntree_statement_list *\nbase_parser::set_stmt_print_flag (tree_statement_list *list, const token& sep_tok, bool warn_missing_semi)\n{\n  return set_stmt_print_flag (list, sep_tok.token_id (), warn_missing_semi);\n}\n\ntree_statement_list *\nbase_parser::set_stmt_print_flag (tree_statement_list *list, separator_list *sep_list, bool warn_missing_semi)\n{\n  return (sep_list\n          ? set_stmt_print_flag (list, sep_list->front (), warn_missing_semi)\n          : set_stmt_print_flag (list, '\\0', warn_missing_semi));\n}\n\n// Finish building a statement.\ntemplate <typename T>\ntree_statement *\nbase_parser::make_statement (T *arg)\n{\n  return new tree_statement (arg);\n}\n\ntree_statement_list *\nbase_parser::make_statement_list (tree_statement *stmt)\n{\n  return new tree_statement_list (stmt);\n}\n\ntree_statement_list *\nbase_parser::append_statement_list (tree_statement_list *list, int sep_char, tree_statement *stmt, bool warn_missing_semi)\n{\n  set_stmt_print_flag (list, sep_char, warn_missing_semi);\n\n  // FIXME: need to capture SEP_CHAR here.\n  return list_append (list, stmt);\n}\n\ntree_statement_list *\nbase_parser::append_statement_list (tree_statement_list *list, token *sep_tok, tree_statement *stmt, bool warn_missing_semi)\n{\n  if (sep_tok)\n    set_stmt_print_flag (list, *sep_tok, warn_missing_semi);\n  else\n    set_stmt_print_flag (list, '\\0', warn_missing_semi);\n\n  // FIXME: need to capture SEP_TOK here.\n  return list_append (list, stmt);\n}\n\ntree_statement_list *\nbase_parser::append_statement_list (tree_statement_list *list, separator_list *sep_list, tree_statement *stmt, bool warn_missing_semi)\n{\n  set_stmt_print_flag (list, sep_list, warn_missing_semi);\n\n  // FIXME: need to capture separator list here.\n  // For now, delete the unused list.\n  delete sep_list;\n\n  return list_append (list, stmt);\n}\n\ntree_statement_list *\nbase_parser::make_function_def_list (tree_function_def *fcn_def)\n{\n  tree_statement *stmt = make_statement (fcn_def);\n\n  return new tree_statement_list (stmt);\n}\n\ntree_statement_list *\nbase_parser::append_function_def_list (tree_statement_list *list, separator_list *sep_list, tree_function_def *fcn_def)\n{\n  tree_statement *stmt = make_statement (fcn_def);\n\n  // FIXME: Need to capture separator list here.\n  // For now, delete the unused list.\n  delete sep_list;\n\n  return list_append (list, stmt);\n}\n\ntree_argument_list *\nbase_parser::make_argument_list (tree_expression *expr)\n{\n  return new tree_argument_list (expr);\n}\n\ntree_argument_list *\nbase_parser::append_argument_list (tree_argument_list *list, tree_expression *expr)\n{\n  return list_append (list, expr);\n}\n\ntree_argument_list *\nbase_parser::append_argument_list (tree_argument_list *list, token *sep_tok, tree_expression *expr)\n{\n  return list_append (list, *sep_tok, expr);\n}\n\ntree_parameter_list *\nbase_parser::make_parameter_list (tree_parameter_list::in_or_out io)\n{\n  return new tree_parameter_list (io);\n}\n\ntree_parameter_list *\nbase_parser::make_parameter_list (tree_parameter_list::in_or_out io, tree_decl_elt *t)\n{\n  return new tree_parameter_list (io, t);\n}\n\ntree_parameter_list *\nbase_parser::make_parameter_list (tree_parameter_list::in_or_out io, tree_identifier *id)\n{\n  return new tree_parameter_list (io, id);\n}\n\ntree_parameter_list *\nbase_parser::append_parameter_list (tree_parameter_list *list, token *sep_tok, tree_decl_elt *t)\n{\n  return list_append (list, *sep_tok, t);\n}\n\ntree_parameter_list *\nbase_parser::append_parameter_list (tree_parameter_list *list, token *sep_tok, tree_identifier *id)\n{\n  return list_append (list, *sep_tok, new tree_decl_elt (id));\n}\n\nvoid\nbase_parser::disallow_command_syntax ()\n{\n  m_lexer.m_allow_command_syntax = false;\n}\n\nvoid\nbase_parser::bison_error (const std::string& str)\n{\n  bison_error (str, m_lexer.m_filepos);\n}\n\nvoid\nbase_parser::bison_error (const std::string& str, const filepos& pos)\n{\n  std::ostringstream output_buf;\n\n  int err_line = pos.line ();\n  int err_col = pos.column ();\n\n  bool in_file = (   m_lexer.m_reading_fcn_file\n                  || m_lexer.m_reading_script_file\n                  || m_lexer.m_reading_classdef_file);\n\n  // Adjust the error column for display because it is 1-based in the\n  // lexer for easier reporting.\n  err_col--;\n\n  if (in_file)\n    output_buf << str << \" near line \" << err_line << \", column \" << err_col\n               << \" in file \" << m_lexer.m_fcn_file_full_name << \"\\n\";\n  else\n    output_buf << str << \"\\n\";\n\n  if (! in_file || Vdiagnostics_show_caret)\n    {\n      output_buf << \"\\n\";\n\n      // Point directly to error in code using caret ('^').\n      std::string curr_line = m_lexer.m_current_input_line;\n\n      if (! curr_line.empty ())\n        {\n          // FIXME: we could do better if we just cached lines from the\n          // input file in a list.  See also functions for managing input\n          // buffers in lex.ll.\n          std::size_t len = curr_line.length ();\n\n          if (curr_line[len-1] == '\\n')\n            curr_line.resize (len-1);\n\n          // Print the line, maybe with a pointer near the error token.\n          output_buf << \">>> \" << curr_line << \"\\n\";\n\n          if (err_col == 0)\n            err_col = len;\n\n          for (int i = 0; i < err_col + 3; i++)\n            output_buf << \" \";\n\n          output_buf << \"^\" << \"\\n\";\n        }\n\n    }\n\n  m_parse_error_msg = output_buf.str ();\n}\n\nvoid\nbase_parser::bison_error (const parse_exception& pe)\n{\n  bison_error (pe.message (), pe.pos ());\n}\n\nvoid\nbase_parser::bison_error (const std::list<parse_exception>& pe_list)\n{\n  // For now, we just report the first error found.  Reporting all\n  // errors will require a bit more refactoring.\n\n  parse_exception pe = pe_list.front ();\n\n  bison_error (pe.message (), pe.pos ());\n}\n\nint\nparser::run ()\n{\n  int status = -1;\n\n  yypstate *pstate = static_cast<yypstate *> (m_parser_state);\n\n  try\n    {\n      status = octave_pull_parse (pstate, *this);\n    }\n  catch (const execution_exception&)\n    {\n      // FIXME: In previous versions, we emitted a parse error here\n      // but that is not always correct because the error could have\n      // happened inside a GUI callback functions executing in the\n      // readline event_hook loop.  Maybe we need a separate exception\n      // class for parse errors?\n\n      throw;\n    }\n  catch (const exit_exception&)\n    {\n      throw;\n    }\n  catch (const interrupt_exception&)\n    {\n      throw;\n    }\n  catch (...)\n    {\n      std::string file = m_lexer.m_fcn_file_full_name;\n\n      if (file.empty ())\n        error (\"unexpected exception while parsing input\");\n      else\n        error (\"unexpected exception while parsing %s\", file.c_str ());\n    }\n\n  if (status != 0)\n    parse_error_with_id (\"Octave:parse-error\", \"%s\", m_parse_error_msg.c_str ());\n\n  return status;\n}\n\n// Parse input from INPUT.  Pass TRUE for EOF if the end of INPUT should\n// finish the parse.\n\nint\npush_parser::run (const std::string& input, bool eof)\n{\n  int status = -1;\n\n  dynamic_cast<push_lexer&> (m_lexer).append_input (input, eof);\n\n  do\n    {\n      YYSTYPE lval;\n\n      int tok_id = octave_lex (&lval, m_lexer.m_scanner);\n\n      if (tok_id < 0)\n        {\n          // TOKEN == -2 means that the lexer recognized a comment\n          // and we should be at the end of the buffer but not the\n          // end of the file so we should return 0 to indicate\n          // \"complete input\" instead of -1 to request more input.\n\n          status = (tok_id == -2 ? 0 : -1);\n\n          if (! eof && m_lexer.at_end_of_buffer ())\n            return status;\n\n          break;\n        }\n\n      yypstate *pstate = static_cast<yypstate *> (m_parser_state);\n\n      try\n        {\n          status = octave_push_parse (pstate, tok_id, &lval, *this);\n        }\n      catch (execution_exception& e)\n        {\n          std::string file = m_lexer.m_fcn_file_full_name;\n\n          if (file.empty ())\n            error (e, \"parse error\");\n          else\n            error (e, \"parse error in %s\", file.c_str ());\n        }\n      catch (const exit_exception&)\n        {\n          throw;\n        }\n      catch (interrupt_exception &)\n        {\n          throw;\n        }\n      catch (...)\n        {\n          std::string file = m_lexer.m_fcn_file_full_name;\n\n          if (file.empty ())\n            error (\"unexpected exception while parsing input\");\n          else\n            error (\"unexpected exception while parsing %s\", file.c_str ());\n        }\n    }\n  while (status == YYPUSH_MORE || ! m_lexer.at_end_of_buffer ());\n\n  if (status != 0)\n    parse_error_with_id (\"Octave:parse-error\", \"%s\", m_parse_error_msg.c_str ());\n\n  return status;\n}\n\nint\npush_parser::run ()\n{\n  if (! m_reader)\n    error (\"push_parser::run requires valid input_reader\");\n\n  int exit_status = 0;\n\n  std::string prompt = command_editor::decode_prompt_string (m_interpreter.PS1 ());\n\n  do\n    {\n      // Reset status each time through the read loop so that\n      // it won't be set to -1 and cause us to exit the outer\n      // loop early if there is an exception while reading\n      // input or parsing.\n\n      exit_status = 0;\n\n      bool eof = false;\n      std::string input_line = m_reader->get_input (prompt, eof);\n\n      if (eof)\n        {\n          exit_status = EOF;\n          break;\n        }\n\n      exit_status = run (input_line, false);\n\n      prompt = command_editor::decode_prompt_string (m_interpreter.PS2 ());\n    }\n  while (exit_status < 0);\n\n  return exit_status;\n}\n\noctave_value\nparse_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)\n{\n  octave_value retval;\n\n  FILE *ffile = nullptr;\n\n  if (! full_file.empty ())\n    {\n      // Check that m-file is not overly large which can segfault interpreter.\n      const int max_file_size = 512 * 1024 * 1024;  // 512 MB\n      sys::file_stat fs (full_file);\n\n      if (fs && fs.size () > max_file_size)\n        {\n          error (\"file '%s' is too large, > 512 MB\", full_file.c_str ());\n\n          return octave_value ();\n        }\n\n      ffile = sys::fopen (full_file, \"rb\");\n    }\n\n  if (! ffile)\n    {\n      if (require_file)\n        error (\"no such file, '%s'\", full_file.c_str ());\n\n      return octave_value ();\n    }\n\n  unwind_action act ([ffile] () { ::fclose (ffile); });\n\n  // get the encoding for this folder\n  input_system& input_sys = interp.get_input_system ();\n  parser parser (ffile, interp, input_sys.dir_encoding (dir_name));\n\n  parser.m_curr_class_name = dispatch_type;\n  parser.m_curr_package_name = package_name;\n  parser.m_autoloading = autoload;\n  parser.m_fcn_file_from_relative_lookup = relative_lookup;\n\n  parser.m_lexer.m_force_script = force_script;\n  parser.m_lexer.prep_for_file ();\n  parser.m_lexer.m_parsing_class_method = ! dispatch_type.empty ();\n\n  parser.m_lexer.m_fcn_file_name = file;\n  parser.m_lexer.m_fcn_file_full_name = full_file;\n  parser.m_lexer.m_dir_name = dir_name;\n  parser.m_lexer.m_package_name = package_name;\n\n  int err = parser.run ();\n\n  if (err)\n    error (\"parse error while reading file %s\", full_file.c_str ());\n\n  octave_value ov_fcn = parser.m_primary_fcn;\n\n  if (parser.m_lexer.m_reading_classdef_file && parser.classdef_object ())\n    {\n      // Convert parse tree for classdef object to\n      // meta.class info (and stash it in the symbol\n      // table?).  Return pointer to constructor?\n\n      if (ov_fcn.is_defined ())\n        error (\"unexpected: defining classdef object but primary_fcn is already defined - please report this bug\");\n\n      bool is_at_folder = ! dispatch_type.empty ();\n\n      std::shared_ptr<tree_classdef> cdef_obj = parser.classdef_object();\n\n      return cdef_obj->make_meta_class (interp, is_at_folder);\n    }\n  else if (ov_fcn.is_defined ())\n    {\n      octave_function *fcn = ov_fcn.function_value ();\n\n      fcn->maybe_relocate_end ();\n\n      if (parser.m_parsing_subfunctions)\n        {\n          if (! parser.m_endfunction_found)\n            parser.m_subfunction_names.reverse ();\n\n          fcn->stash_subfunction_names (parser.m_subfunction_names);\n        }\n\n      return ov_fcn;\n    }\n\n  return octave_value ();\n}\n\nbool\nbase_parser::finish_input (tree_statement_list *lst, bool at_eof)\n{\n  m_lexer.m_end_of_input = at_eof;\n\n  if (lst)\n    {\n      parse_tree_validator validator;\n\n      lst->accept (validator);\n\n      if (! validator.ok ())\n        {\n          delete lst;\n\n          bison_error (validator.error_list ());\n\n          return false;\n        }\n    }\n\n  std::shared_ptr<tree_statement_list> tmp_lst (lst);\n\n  statement_list (tmp_lst);\n\n  return true;\n}\n\n// Check script or function for semantic errors.\nbool\nbase_parser::validate_primary_fcn ()\n{\n  octave_user_code *code = m_primary_fcn.user_code_value ();\n\n  if (code)\n    {\n      parse_tree_validator validator;\n\n      code->accept (validator);\n\n      if (! validator.ok ())\n        {\n          bison_error (validator.error_list ());\n\n          return false;\n        }\n    }\n\n  return true;\n}\n\n// Maybe print a warning if an assignment expression is used as the\n// test in a logical expression.\n\nvoid\nbase_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)\n{\n  if (expr->is_assignment_expression () && expr->delim_count () < 2)\n    {\n      if (m_lexer.m_fcn_file_full_name.empty ())\n        warning_with_id (\"Octave:assign-as-truth-value\", \"suggest parenthesis around assignment used as truth value\");\n      else\n        warning_with_id (\"Octave:assign-as-truth-value\", \"suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'\", expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());\n    }\n}\n\n// Maybe print a warning about switch labels that aren't constants.\n\nvoid\nbase_parser::maybe_warn_variable_switch_label (tree_expression *expr)\n{\n  if (! expr->is_constant ())\n    {\n      if (m_lexer.m_fcn_file_full_name.empty ())\n        warning_with_id (\"Octave:variable-switch-label\", \"variable switch label\");\n      else\n        warning_with_id (\"Octave:variable-switch-label\", \"variable switch label near line %d, column %d in file '%s'\", expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());\n    }\n}\n\nvoid\nbase_parser::maybe_warn_missing_semi (tree_statement_list *t)\n{\n  if (m_curr_fcn_depth >= 0)\n    {\n      tree_statement *tmp = t->back ();\n\n      if (tmp->is_expression ())\n        warning_with_id (\"Octave:missing-semicolon\", \"missing semicolon near line %d, column %d in file '%s'\", tmp->line (), tmp->column (), m_lexer.m_fcn_file_full_name.c_str ());\n    }\n}\n\nstd::string\nget_help_from_file (const std::string& nm, bool& symbol_found, std::string& full_file)\n{\n  std::string retval;\n\n  full_file = fcn_file_in_path (nm);\n\n  std::string file = full_file;\n\n  std::size_t file_len = file.length ();\n\n  if ((file_len > 4 && file.substr (file_len-4) == \".oct\")\n      || (file_len > 4 && file.substr (file_len-4) == \".mex\")\n      || (file_len > 2 && file.substr (file_len-2) == \".m\"))\n    {\n      file = sys::env::base_pathname (file);\n      file = file.substr (0, file.find_last_of ('.'));\n\n      std::size_t pos = file.find_last_of (sys::file_ops::dir_sep_str ());\n      if (pos != std::string::npos)\n        file = file.substr (pos+1);\n    }\n\n  if (! file.empty ())\n    {\n      interpreter& interp = __get_interpreter__ ();\n\n      symbol_found = true;\n\n      octave_value ov_fcn = parse_fcn_file (interp, full_file, file, \"\", \"\", \"\", true, false, false, false);\n\n      if (ov_fcn.is_defined ())\n        {\n          octave_function *fcn = ov_fcn.function_value ();\n\n          if (fcn)\n            retval = fcn->doc_string ();\n        }\n    }\n\n  return retval;\n}\n\nstd::string\nget_help_from_file (const std::string& nm, bool& symbol_found)\n{\n  std::string file;\n  return get_help_from_file (nm, symbol_found, file);\n}\n\noctave_value\nload_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)\n{\n  octave_value retval;\n\n  unwind_protect frame;\n\n  std::string nm = file_name;\n\n  std::size_t nm_len = nm.length ();\n\n  std::string file;\n\n  bool relative_lookup = false;\n\n  file = nm;\n\n  if ((nm_len > 4 && nm.substr (nm_len-4) == \".oct\")\n      || (nm_len > 4 && nm.substr (nm_len-4) == \".mex\")\n      || (nm_len > 2 && nm.substr (nm_len-2) == \".m\"))\n    {\n      nm = sys::env::base_pathname (file);\n      nm = nm.substr (0, nm.find_last_of ('.'));\n\n      std::size_t pos = nm.find_last_of (sys::file_ops::dir_sep_str ());\n      if (pos != std::string::npos)\n        nm = nm.substr (pos+1);\n    }\n\n  relative_lookup = ! sys::env::absolute_pathname (file);\n\n  file = sys::env::make_absolute (file);\n\n  int len = file.length ();\n\n  interpreter& interp = __get_interpreter__ ();\n\n  dynamic_loader& dyn_loader = interp.get_dynamic_loader ();\n\n  if (len > 4 && file.substr (len-4, len-1) == \".oct\")\n    {\n      if (autoload && ! fcn_name.empty ())\n        nm = fcn_name;\n\n      octave_function *tmpfcn = dyn_loader.load_oct (nm, file, relative_lookup);\n\n      if (tmpfcn)\n        {\n          tmpfcn->stash_package_name (package_name);\n          retval = octave_value (tmpfcn);\n        }\n    }\n  else if (len > 4 && file.substr (len-4, len-1) == \".mex\")\n    {\n      // Temporarily load m-file version of mex-file, if it exists,\n      // to get the help-string to use.\n\n      std::string doc_string;\n\n      octave_value ov_fcn = parse_fcn_file (interp, file.substr (0, len - 2), nm, dir_name, dispatch_type, package_name, false, autoload, autoload, relative_lookup);\n\n      if (ov_fcn.is_defined ())\n        {\n          octave_function *tmpfcn = ov_fcn.function_value ();\n\n          if (tmpfcn)\n            doc_string = tmpfcn->doc_string ();\n        }\n\n      octave_function *tmpfcn = dyn_loader.load_mex (nm, file, relative_lookup);\n\n      if (tmpfcn)\n        {\n          tmpfcn->document (doc_string);\n          tmpfcn->stash_package_name (package_name);\n\n          retval = octave_value (tmpfcn);\n        }\n    }\n  else if (len > 2)\n    retval = parse_fcn_file (interp, file, nm, dir_name, dispatch_type, package_name, true, autoload, autoload, relative_lookup);\n\n  return retval;\n}\n\nDEFMETHOD (autoload, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{autoload_map} =} autoload ()\n@deftypefnx {} {} autoload (@var{function}, @var{file})\n@deftypefnx {} {} autoload (@dots{}, \"remove\")\nDefine @var{function} to autoload from @var{file}.\n\nThe second argument, @var{file}, should be an absolute filename or a file\nname in the same directory as the function or script from which the autoload\ncommand was run.  @var{file} @emph{should not} depend on the Octave load\npath.\n\nNormally, calls to @code{autoload} appear in PKG_ADD script files that are\nevaluated when a directory is added to Octave's load path.  To avoid having\nto hardcode directory names in @var{file}, if @var{file} is in the same\ndirectory as the PKG_ADD script then\n\n@example\nautoload (\"foo\", \"bar.oct\");\n@end example\n\n@noindent\nwill load the function @code{foo} from the file @code{bar.oct}.  The above\nusage when @code{bar.oct} is not in the same directory, or usages such as\n\n@example\nautoload (\"foo\", file_in_loadpath (\"bar.oct\"))\n@end example\n\n@noindent\nare strongly discouraged, as their behavior may be unpredictable.\n\nWith no arguments, return a structure containing the current autoload map.\n\nIf a third argument @qcode{\"remove\"} is given, the function is cleared and\nnot loaded anymore during the current Octave session.\n\n@seealso{PKG_ADD}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 1 || nargin > 3)\n    print_usage ();\n\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  if (nargin == 0)\n    return octave_value (tw.get_autoload_map ());\n  else\n    {\n      string_vector argv = args.make_argv (\"autoload\");\n\n      if (nargin == 2)\n        tw.add_autoload (argv[1], argv[2]);\n      else if (nargin == 3)\n        {\n          if (argv[3] != \"remove\")\n            error_with_id (\"Octave:invalid-input-arg\", \"autoload: third argument can only be 'remove'\");\n\n          tw.remove_autoload (argv[1], argv[2]);\n        }\n    }\n\n  return octave_value_list ();\n}\n\nDEFMETHOD (mfilename, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} mfilename ()\n@deftypefnx {} {} mfilename (\"fullpath\")\n@deftypefnx {} {} mfilename (\"fullpathext\")\nReturn the name of the currently executing file.\n\nThe base name of the currently executing script or function is returned without\nany extension.  If called from outside an m-file, such as the command line,\nreturn the empty string.\n\nGiven the argument @qcode{\"fullpath\"}, include the directory part of the\nfilename, but not the extension.\n\nGiven the argument @qcode{\"fullpathext\"}, include the directory part of\nthe filename and the extension.\n@seealso{inputname, dbstack}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  std::string opt;\n\n  if (nargin == 1)\n    opt = args(0).xstring_value (\"mfilename: option argument must be a string\");\n\n  return octave_value (interp.mfilename (opt));\n}\n\n  // Execute the contents of a script file.  For compatibility with\n  // Matlab, also execute a function file by calling the function it\n  // defines with no arguments and nargout = 0.\n\n  void\n  source_file (const std::string& file_name, const std::string& context,\n               bool verbose, bool require_file)\n  {\n    interpreter& interp = __get_interpreter__ ();\n\n    interp.source_file (file_name, context, verbose, require_file);\n  }\n\nDEFMETHOD (source, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} source (@var{file})\n@deftypefnx {} {} source (@var{file}, @var{context})\nParse and execute the contents of @var{file}.\n\nWithout specifying @var{context}, this is equivalent to executing commands\nfrom a script file, but without requiring the file to be named\n@file{@var{file}.m} or to be on the execution path.\n\nInstead of the current context, the script may be executed in either the\ncontext of the function that called the present function\n(@qcode{\"caller\"}), or the top-level context (@qcode{\"base\"}).\n@seealso{run}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string file_name = args(0).xstring_value (\"source: FILE must be a string\");\n\n  std::string context;\n  if (nargin == 2)\n    context = args(1).xstring_value (\"source: CONTEXT must be a string\");\n\n  interp.source_file (file_name, context);\n\n  return octave_value_list ();\n}\n\n  //! Evaluate an Octave function (built-in or interpreted) and return\n  //! the list of result values.\n  //!\n  //! @param name The name of the function to call.\n  //! @param args The arguments to the function.\n  //! @param nargout The number of output arguments expected.\n  //! @return A list of output values.  The length of the list is not\n  //!         necessarily the same as @c nargout.\n\n  octave_value_list\n  feval (const char *name, const octave_value_list& args, int nargout)\n  {\n    interpreter& interp = __get_interpreter__ ();\n\n    return interp.feval (name, args, nargout);\n  }\n\n  octave_value_list\n  feval (const std::string& name, const octave_value_list& args, int nargout)\n  {\n    interpreter& interp = __get_interpreter__ ();\n\n    return interp.feval (name, args, nargout);\n  }\n\n  octave_value_list\n  feval (octave_function *fcn, const octave_value_list& args, int nargout)\n  {\n    interpreter& interp = __get_interpreter__ ();\n\n    return interp.feval (fcn, args, nargout);\n  }\n\n  octave_value_list\n  feval (const octave_value& val, const octave_value_list& args, int nargout)\n  {\n    interpreter& interp = __get_interpreter__ ();\n\n    return interp.feval (val, args, nargout);\n  }\n\n  octave_value_list\n  feval (const octave_value_list& args, int nargout)\n  {\n    interpreter& interp = __get_interpreter__ ();\n\n    return interp.feval (args, nargout);\n  }\n\nDEFMETHOD (feval, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {[@var{y1}, @var{y2}, @dots{}] =} feval ('@var{fcn}', @var{x1}, @var{x2}, @dots{})\n@deftypefnx {} {[@var{y1}, @var{y2}, @dots{}] =} feval (@@@var{fcn}, @var{x1}, @var{x2}, @dots{})\nEvaluate the function @var{fcn} with inputs @var{x1}, @var{x2}, @enddots{}\n\nThe function @var{fcn} may be specified by name in a string or given as a\nfunction handle.  Any arguments after the first are passed as inputs to the\nnamed function.  For example,\n\n@example\n@group\nfeval (\"acos\", -1)\n     @xresult{} 3.1416\n@end group\n@end example\n\n@noindent\ncalls the function @code{acos} with the argument @samp{-1}.\n\nThe function @code{feval} can also be used with function handles of any sort\n(@pxref{Function Handles}).  Historically, @code{feval} was the only way to\ncall user-supplied functions in strings, but function handles are now preferred\ndue to the cleaner syntax they offer.  For example,\n\n@example\n@group\n@var{f} = @@exp;\nfeval (@var{f}, 1)\n    @xresult{} 2.7183\n@var{f} (1)\n    @xresult{} 2.7183\n@end group\n@end example\n\n@noindent\nare equivalent ways to call the function referred to by @var{f}.  If it cannot\nbe predicted beforehand whether @var{f} is a function handle, function name in\na string, or inline function then @code{feval} can be used instead.\n@seealso{builtin, eval, evalin}\n@end deftypefn */)\n{\n  if (args.length () == 0)\n    print_usage ();\n\n  return interp.feval (args, nargout);\n}\n\nDEFMETHOD (builtin, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {[@dots{}] =} builtin (@var{f}, @dots{})\nCall the base function @var{f} even if @var{f} is overloaded to another\nfunction for the given type signature.\n\nThis is normally useful when doing object-oriented programming and there is\na requirement to call one of Octave's base functions rather than the\noverloaded one of a new class.\n\nA trivial example which redefines the @code{sin} function to be the\n@code{cos} function shows how @code{builtin} works.\n\n@example\n@group\nsin (0)\n  @xresult{} 0\nfunction y = sin (x), y = cos (x); endfunction\nsin (0)\n  @xresult{} 1\nbuiltin (\"sin\", 0)\n  @xresult{} 0\n@end group\n@end example\n@end deftypefn */)\n{\n  octave_value_list retval;\n\n  if (args.length () == 0)\n    print_usage ();\n\n  const std::string name (args(0).xstring_value (\"builtin: function name (F) must be a string\"));\n\n  symbol_table& symtab = interp.get_symbol_table ();\n\n  octave_value fcn = symtab.builtin_find (name);\n\n  if (fcn.is_defined ())\n    retval = interp.feval (fcn.function_value (), args.splice (0, 1), nargout);\n  else\n    error (\"builtin: lookup for symbol '%s' failed\", name.c_str ());\n\n  return retval;\n}\n\nDEFMETHOD (eval, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} eval (@var{try})\n@deftypefnx {} {} eval (@var{try}, @var{catch})\n@deftypefnx {} {[@var{var1}, @dots{}] =} eval (@dots{})\nParse the string @var{try} and evaluate it as if it were an Octave program.\n\nIf execution fails, evaluate the optional string @var{catch}.\n\nThe string @var{try} is evaluated in the current context, so any results remain\navailable after @code{eval} returns.\n\nThe following example creates the variable @var{A} with the approximate value\nof pi (3.1416) in the current workspace.\n\n@example\neval ('A = acos (-1);');\n@end example\n\nIf an error occurs during the evaluation of @var{try} then the @var{catch}\nstring is evaluated, as the following example shows:\n\n@example\n@group\neval ('error (\"This is a bad example\");',\n      'printf (\"This error occurred:\\n%s\\n\", lasterr ());');\n     @print{} This error occurred:\n        This is a bad example\n@end group\n@end example\n\nRather than create variables as part of the code string @var{try}, it is\nclearer and slightly faster to assign the results of evaluation to an output\nvariable(s).  The first example can be re-written as\n\n@example\nA = eval ('acos (-1);');\n@end example\n\nProgramming Note: if you are only using @code{eval} as an error-capturing\nmechanism, rather than for the execution of arbitrary code strings, consider\nusing @code{try}/@code{catch} blocks or\n@code{unwind_protect}/@code{unwind_protect_cleanup} blocks instead.  These\ntechniques have higher performance and don't introduce the security\nconsiderations that the evaluation of arbitrary code does.\n@seealso{evalin, evalc, assignin, feval, try, unwind_protect}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  if (! args(0).is_string () || args(0).rows () > 1 || args(0).ndims () != 2)\n    error (\"eval: TRY must be a string\");\n\n  std::string try_code = args(0).string_value ();\n\n  if (nargin == 1)\n    return interp.eval (try_code, nargout);\n  else\n    {\n      if (! args(1).is_string () || args(1).rows () > 1 || args(1).ndims () != 2)\n        error (\"eval: CATCH must be a string\");\n\n      std::string catch_code = args(1).string_value ();\n\n      return interp.eval (try_code, catch_code, nargout);\n    }\n}\n\n/*\n\n%!shared x\n%! x = 1;\n\n%!assert (eval (\"x\"), 1)\n%!assert (eval (\"x;\"))\n%!assert (eval (\"x;\"), 1)\n\n%!test\n%! y = eval (\"x\");\n%! assert (y, 1);\n\n%!test\n%! y = eval (\"x;\");\n%! assert (y, 1);\n\n%!test\n%! eval (\"x = 1;\");\n%! assert (x,1);\n\n%!test\n%! eval (\"flipud = 2;\");\n%! assert (flipud, 2);\n\n%!function y = __f ()\n%!  eval (\"flipud = 2;\");\n%!  y = flipud;\n%!endfunction\n%!assert (__f(), 2)\n\n%!test <*35645>\n%! [a,] = gcd (1,2);\n%! [a,b,] = gcd (1, 2);\n\n## Can't assign to a keyword\n%!error eval (\"switch = 13;\")\n\n%!shared str\n%! str = \"disp ('hello');\";\n%! str(:,:,2) = str(:,:,1);\n\n%!error <TRY must be a string> eval (1)\n%!error <TRY must be a string> eval (['a';'b'])\n%!error <TRY must be a string> eval (str)\n\n%!error <CATCH must be a string> eval (str(:,:,1), 1)\n%!error <CATCH must be a string> eval (str(:,:,1), ['a';'b'])\n%!error <CATCH must be a string> eval (str(:,:,1), str)\n\n*/\n\nDEFMETHOD (assignin, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} assignin (@var{context}, @var{varname}, @var{value})\nAssign @var{value} to @var{varname} in context @var{context}, which\nmay be either @qcode{\"base\"} or @qcode{\"caller\"}.\n@seealso{evalin}\n@end deftypefn */)\n{\n  if (args.length () != 3)\n    print_usage ();\n\n  std::string context = args(0).xstring_value (\"assignin: CONTEXT must be a string\");\n\n  std::string varname = args(1).xstring_value (\"assignin: VARNAME must be a string\");\n\n  interp.assignin (context, varname, args(2));\n\n  return octave_value_list ();\n}\n\n/*\n\n%!error assignin (\"base\", \"switch\", \"13\")\n\n*/\n\nDEFMETHOD (evalin, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} evalin (@var{context}, @var{try})\n@deftypefnx {} {} evalin (@var{context}, @var{try}, @var{catch})\n@deftypefnx {} {[@var{var1}, @dots{}] =} evalin (@dots{})\nLike @code{eval}, except that the expressions are evaluated in the context\n@var{context}, which may be either @qcode{\"caller\"} or @qcode{\"base\"}.\n@seealso{eval, assignin}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n\n  std::string context = args(0).xstring_value (\"evalin: CONTEXT must be a string\");\n\n  std::string try_code = args(1).xstring_value (\"evalin: TRY must be a string\");\n\n  if (nargin == 3)\n    {\n      std::string catch_code = args(2).xstring_value (\"evalin: CATCH must be a string\");\n\n      return interp.evalin (context, try_code, catch_code, nargout);\n    }\n\n  return interp.evalin (context, try_code, nargout);\n}\n\nDEFMETHOD (evalc, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{s} =} evalc (@var{try})\n@deftypefnx {} {@var{s} =} evalc (@var{try}, @var{catch})\n@deftypefnx {} {[~, @var{var1}, @dots{}] =} evalc (@dots{})\nParse and evaluate the string @var{try} as if it were an Octave program,\nwhile capturing the output into the return variable @var{s}.\n\nIf execution fails, evaluate the optional string @var{catch}.\n\nThis function behaves like @code{eval}, but any output or warning messages\nwhich would normally be written to the console are captured and returned in\nthe string @var{s}.\n\nIf the first output @var{s} is ignored with @code{~} then the actual results\nof the code evaluation (not the string capture) will be assigned to output\nvariables @var{var1}, @var{var2}, etc.\n\nExample 1:\n\n@example\n@group\ns = evalc (\"t = 42\"), t\n  @xresult{} s = t =  42\n\n  @xresult{} t =  42\n@end group\n@end example\n\nExample 2:\n\n@example\n@group\n[~, p] = evalc (\"pi\")\n  @xresult{} p = 3.1416\n@end group\n@end example\n\nProgramming Note: The @code{diary} is disabled during the execution of this\nfunction.  When @code{system} is used, any output produced by external programs\nis @emph{not} captured, unless their output is captured by the @code{system}\nfunction itself.\n\n@seealso{eval, diary}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin == 0 || nargin > 2)\n    print_usage ();\n\n  // Flush pending output and redirect stdout/stderr to capturing\n  // buffer.\n\n  octave_stdout.flush ();\n  std::cerr.flush ();\n\n  std::stringbuf buffer;\n\n  std::streambuf *old_out_buf = octave_stdout.rdbuf (&buffer);\n  std::streambuf *old_err_buf = std::cerr.rdbuf (&buffer);\n\n  // Restore previous output buffers no matter how control exits this\n  // function.  There's no need to flush here.  That has already\n  // happened for the normal execution path.  If an error happens during\n  // the eval, then the message is stored in the exception object and we\n  // will display it later, after the buffers have been restored.\n\n  unwind_action act ([old_out_buf, old_err_buf] ()\n                             {\n                               octave_stdout.rdbuf (old_out_buf);\n                               std::cerr.rdbuf (old_err_buf);\n                             });\n\n  // Call standard eval function.\n\n  int eval_nargout = std::max (0, nargout - 1);\n\n  octave_value_list retval = Feval (interp, args, eval_nargout);\n\n  // Make sure we capture all pending output.\n\n  octave_stdout.flush ();\n  std::cerr.flush ();\n\n  retval.prepend (buffer.str ());\n\n  return retval;\n}\n\n/*\n\n%!test\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format short;\n%!   str = evalc (\"1\");\n%!   assert (str, \"ans = 1\\n\");\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n\n%!assert (evalc (\"1;\"), \"\")\n\n%!test\n%! [s, y] = evalc (\"1\");\n%! assert (s, \"\");\n%! assert (y, 1);\n\n%!test\n%! [s, y] = evalc (\"1;\");\n%! assert (s, \"\");\n%! assert (y, 1);\n\n%!test\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format short;\n%!   str = evalc (\"y = 2\");\n%!   assert (str, \"y = 2\\n\");\n%!   assert (y, 2);\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n\n%!test\n%! assert (evalc (\"y = 3;\"), \"\");\n%! assert (y, 3);\n\n%!test\n%! [s, a, b] = evalc (\"deal (1, 2)\");\n%! assert (s, \"\");\n%! assert (a, 1);\n%! assert (b, 2);\n\n%!function [a, b] = __f_evalc ()\n%!  printf (\"foo\");\n%!  fprintf (stdout, \"bar \");\n%!  disp (pi);\n%!  a = 1;\n%!  b = 2;\n%!endfunction\n%!test\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format short;\n%!   [s, a, b] = evalc (\"__f_evalc ()\");\n%!   assert (s, \"foobar 3.1416\\n\");\n%!   assert (a, 1);\n%!   assert (b, 2);\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n\n%!error <foo> (evalc (\"error ('foo')\"))\n%!error <bar> (evalc (\"error ('foo')\", \"error ('bar')\"))\n\n%!test\n%! warning (\"off\", \"quiet\", \"local\");\n%! str = evalc (\"warning ('foo')\");\n%! assert (str(1:13), \"warning: foo\\n\");\n\n%!test\n%! warning (\"off\", \"quiet\", \"local\");\n%! str = evalc (\"error ('foo')\", \"warning ('bar')\");\n%! assert (str(1:13), \"warning: bar\\n\");\n\n%!error evalc (\"switch = 13;\")\n\n*/\n\nDEFUN (__parser_debug_flag__, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} __parser_debug_flag__ ()\n@deftypefnx {} {@var{old_val} =} __parser_debug_flag__ (@var{new_val})\nQuery or set the internal flag that determines whether Octave's parser\nprints debug information as it processes an expression.\n@seealso{__lexer_debug_flag__}\n@end deftypefn */)\n{\n#if defined (OCTAVE_PARSER_DEBUG)\n  octave_value retval;\n\n  bool debug_flag = octave_debug;\n\n  retval = set_internal_variable (debug_flag, args, nargout,\n                                  \"__parser_debug_flag__\");\n\n  octave_debug = debug_flag;\n\n  return retval;\n#else\n\n  octave_unused_parameter (args);\n  octave_unused_parameter (nargout);\n\n  error (\"__parser_debug_flag__: support for debugging the parser was disabled when Octave was built\");\n\n#endif\n}\n\nDEFUN (diagnostics_show_caret, args, nargout,\n       doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} diagnostics_show_caret ()\n@deftypefnx {} {@var{old_val} =} diagnostics_show_caret (@var{new_val})\n@deftypefnx {} {@var{old_val} =} diagnostics_show_caret (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether syntax errors are\nprinted with a caret when reading from a file.\n\nBy default, when a parse error occurs the source line is printed with a caret\n@samp{^} that points to the token that caused the error.  This is the case in\nthe interactive interpreter and also when reading from a script or function\nfile.  If this variable is set to false, when reading from a file, the source\nline and the caret will not be printed.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  return set_internal_variable (Vdiagnostics_show_caret, args, nargout,\n                                \"diagnostics_show_caret\");\n}\n\nDEFMETHOD (__parse_file__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __parse_file__ (@var{file}, @var{verbose})\nUndocumented internal function.\n@end deftypefn */)\n{\n  octave_value retval;\n\n  int nargin = args.length ();\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n\n  std::string file = args(0).xstring_value (\"__parse_file__: expecting filename as argument\");\n\n  std::string full_file = sys::file_ops::tilde_expand (file);\n\n  full_file = sys::env::make_absolute (full_file);\n\n  std::string dir_name;\n\n  std::size_t file_len = file.length ();\n\n  if ((file_len > 4 && file.substr (file_len-4) == \".oct\")\n      || (file_len > 4 && file.substr (file_len-4) == \".mex\")\n      || (file_len > 2 && file.substr (file_len-2) == \".m\"))\n    {\n      file = sys::env::base_pathname (file);\n      file = file.substr (0, file.find_last_of ('.'));\n\n      std::size_t pos = file.find_last_of (sys::file_ops::dir_sep_str ());\n      if (pos != std::string::npos)\n        {\n          dir_name = file.substr (0, pos);\n          file = file.substr (pos+1);\n        }\n    }\n\n  if (nargin == 2)\n    octave_stdout << \"parsing \" << full_file << std::endl;\n\n  octave_value ov_fcn = parse_fcn_file (interp, full_file, file, dir_name, \"\", \"\", true, false, false, false);\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/octave.gperf",
    "content": "%{\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n// NOTE: gperf 2.7.2 will silently generate bad code if there are blank\n// lines following the \"%{\" marker above.  This comment block seems to be\n// handled correctly.\n//\n////////////////////////////////////////////////////////////////////////\n\nenum octave_kw_id\n{\n  arguments_kw,\n  break_kw,\n  case_kw,\n  catch_kw,\n  classdef_kw,\n  continue_kw,\n  do_kw,\n  else_kw,\n  elseif_kw,\n  end_kw,\n  end_try_catch_kw,\n  end_unwind_protect_kw,\n  endarguments_kw,\n  endclassdef_kw,\n  endenumeration_kw,\n  endevents_kw,\n  endfor_kw,\n  endfunction_kw,\n  endif_kw,\n  endmethods_kw,\n  endparfor_kw,\n  endproperties_kw,\n  endspmd_kw,\n  endswitch_kw,\n  endwhile_kw,\n  enumeration_kw,\n  events_kw,\n  for_kw,\n  function_kw,\n  get_kw,\n  global_kw,\n  if_kw,\n  magic_file_kw,\n  magic_line_kw,\n  methods_kw,\n  otherwise_kw,\n  parfor_kw,\n  persistent_kw,\n  properties_kw,\n  return_kw,\n  set_kw,\n  spmd_kw,\n  switch_kw,\n  try_kw,\n  until_kw,\n  unwind_protect_kw,\n  unwind_protect_cleanup_kw,\n  while_kw\n};\n\n%}\n\nstruct octave_kw { const char *name; int tok_id; octave_kw_id kw_id; };\n\n%%\narguments, ARGUMENTS, arguments_kw\nbreak, BREAK, break_kw\ncase, CASE, case_kw\ncatch, CATCH, catch_kw\nclassdef, CLASSDEF, classdef_kw\ncontinue, CONTINUE, continue_kw\ndo, DO, do_kw\nelse, ELSE, else_kw\nelseif, ELSEIF, elseif_kw\nend, END, end_kw\nend_try_catch, END, end_try_catch_kw\nend_unwind_protect, END, end_unwind_protect_kw\nendarguments, END, endarguments_kw\nendclassdef, END, endclassdef_kw\nendenumeration, END, endenumeration_kw\nendevents, END, endevents_kw\nendfor, END, endfor_kw\nendfunction, END, endfunction_kw\nendif, END, endif_kw\nendmethods, END, endmethods_kw\nendparfor, END, endparfor_kw\nendproperties, END, endproperties_kw\nendspmd, END, endspmd_kw\nendswitch, END, endswitch_kw\nendwhile, END, endwhile_kw\nenumeration, ENUMERATION, enumeration_kw\nevents, EVENTS, events_kw\nfor, FOR, for_kw\nfunction, FUNCTION, function_kw\nget, GET, get_kw\nglobal, GLOBAL, global_kw\nif, IF, if_kw\nmethods, METHODS, methods_kw\notherwise, OTHERWISE, otherwise_kw\nparfor, PARFOR, parfor_kw\npersistent, PERSISTENT, persistent_kw\nproperties, PROPERTIES, properties_kw\nreturn, RETURN, return_kw\nset, SET, set_kw\nspmd, SPMD, spmd_kw\nswitch, SWITCH, switch_kw\ntry, TRY, try_kw\nuntil, UNTIL, until_kw\nunwind_protect, UNWIND, unwind_protect_kw\nunwind_protect_cleanup, CLEANUP, unwind_protect_cleanup_kw\nwhile, WHILE, while_kw\n__FILE__, DQ_STRING, magic_file_kw\n__LINE__, NUMBER, magic_line_kw\n"
  },
  {
    "path": "libinterp/parse-tree/parse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_parse_h)\n#define octave_parse_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdio>\n\n#include <deque>\n#include <map>\n#include <memory>\n#include <set>\n#include <string>\n\n#include \"input.h\"\n#include \"lex.h\"\n#include \"pt-misc.h\"\n#include \"symscope.h\"\n#include \"token.h\"\n\nclass octave_function;\nclass octave_user_code;\nclass octave_user_function;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass parse_exception;\nclass separator_list;\nclass tree;\nclass tree_anon_fcn_handle;\nclass tree_arg_size_spec;\nclass tree_arg_validation;\nclass tree_arg_validation_fcns;\nclass tree_args_block_attribute_list;\nclass tree_args_block_validation_list;\nclass tree_argument_list;\nclass tree_arguments_block;\nclass tree_array_list;\nclass tree_cell;\nclass tree_classdef;\nclass tree_classdef_attribute_list;\nclass tree_classdef_body;\nclass tree_classdef_enum_block;\nclass tree_classdef_enum_list;\nclass tree_classdef_events_block;\nclass tree_classdef_event_list;\nclass tree_classdef_methods_block;\nclass tree_classdef_method_list;\nclass tree_classdef_properties_block;\nclass tree_classdef_property_list;\nclass tree_classdef_superclass_list;\nclass tree_colon_expression;\nclass tree_command;\nclass tree_constant;\nclass tree_decl_command;\nclass tree_decl_init_list;\nclass tree_expression;\nclass tree_fcn_handle;\nclass tree_function_def;\nclass tree_identifier;\nclass tree_if_clause;\nclass tree_if_command;\nclass tree_if_command_list;\nclass tree_index_expression;\nclass tree_matrix;\nclass tree_matrix;\nclass tree_parameter_list;\nclass tree_spmd_command;\nclass tree_statement;\nclass tree_statement_list;\nclass tree_statement_listtree_statement;\nclass tree_switch_case;\nclass tree_switch_case_list;\nclass tree_switch_command;\n\nOCTAVE_END_NAMESPACE(octave)\n\n#include \"ovl.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass base_parser\n{\nprivate:\n\n  class parent_scope_info\n  {\n  public:\n\n    typedef std::pair<symbol_scope, std::string> value_type;\n\n    typedef std::deque<value_type>::iterator iterator;\n    typedef std::deque<value_type>::const_iterator const_iterator;\n\n    typedef std::deque<value_type>::reverse_iterator reverse_iterator;\n    typedef std::deque<value_type>::const_reverse_iterator const_reverse_iterator;\n\n    parent_scope_info () = delete;\n\n    parent_scope_info (base_parser& parser)\n      : m_parser (parser), m_info (), m_all_names ()\n    { }\n\n    OCTAVE_DISABLE_COPY_MOVE (parent_scope_info)\n\n    ~parent_scope_info () = default;\n\n    OCTINTERP_API std::size_t size () const;\n\n    OCTINTERP_API void push (const value_type& elt);\n\n    OCTINTERP_API void push (const symbol_scope& id);\n\n    OCTINTERP_API void pop ();\n\n    OCTINTERP_API bool name_ok (const std::string& name);\n\n    OCTINTERP_API bool name_current_scope (const std::string& name);\n\n    OCTINTERP_API symbol_scope parent_scope () const;\n\n    OCTINTERP_API std::string parent_name () const;\n\n    OCTINTERP_API void clear ();\n\n  private:\n\n    base_parser& m_parser;\n    std::deque<value_type> m_info;\n    std::set<std::string> m_all_names;\n  };\n\npublic:\n\n  OCTINTERP_API base_parser (base_lexer& lxr);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (base_parser)\n\n  virtual ~base_parser ();\n\n  base_lexer& get_lexer () const { return m_lexer; }\n\n  bool at_end_of_input () const { return m_lexer.m_end_of_input; }\n\n  OCTINTERP_API void reset ();\n\n  void classdef_object (const std::shared_ptr<tree_classdef>& obj)\n  {\n    m_classdef_object = obj;\n  }\n\n  std::shared_ptr<tree_classdef> classdef_object () const\n  {\n    return m_classdef_object;\n  }\n\n  OCTINTERP_API void statement_list (std::shared_ptr<tree_statement_list>& lst);\n\n  std::shared_ptr<tree_statement_list> statement_list () const\n  {\n    return m_stmt_list;\n  }\n\n  void parsing_subfunctions (bool flag)\n  {\n    m_parsing_subfunctions = flag;\n  }\n\n  bool parsing_subfunctions () const\n  {\n    return m_parsing_subfunctions;\n  }\n\n  void parsing_local_functions (bool flag)\n  {\n    m_parsing_local_functions = flag;\n  }\n\n  bool parsing_local_functions () const\n  {\n    return m_parsing_local_functions;\n  }\n\n  int curr_fcn_depth () const\n  {\n    return m_curr_fcn_depth;\n  }\n\n  void endfunction_found (bool flag)\n  {\n    m_endfunction_found = flag;\n  }\n\n  bool endfunction_found () const\n  {\n    return m_endfunction_found;\n  }\n\n  // Error messages for mismatched end tokens.\n  OCTINTERP_API void\n  end_token_error (token *tok, token::end_tok_type expected);\n\n  // Check to see that end tokens are properly matched.\n  OCTINTERP_API bool end_token_ok (token *tok, token::end_tok_type expected);\n\n  // Handle pushing symbol table for new function scope.\n  OCTINTERP_API bool push_fcn_symtab ();\n\n  // Build a constant.\n  OCTINTERP_API tree_constant * make_constant (token *tok);\n\n  OCTINTERP_API tree_black_hole * make_black_hole (token *tilde);\n\n  OCTINTERP_API tree_matrix * make_matrix (tree_argument_list *row);\n\n  OCTINTERP_API tree_matrix *\n  append_matrix_row (tree_matrix *matrix, token *sep_tok, tree_argument_list *row);\n\n  OCTINTERP_API tree_cell * make_cell (tree_argument_list *row);\n\n  OCTINTERP_API tree_cell *\n  append_cell_row (tree_cell *cell, token *sep_tok, tree_argument_list *row);\n\n  // Build a function handle.\n  OCTINTERP_API tree_fcn_handle * make_fcn_handle (token *tok);\n\n  // Build an anonymous function handle.\n  OCTINTERP_API tree_anon_fcn_handle *\n  make_anon_fcn_handle (token *at_tok, tree_parameter_list *param_list, tree_expression *expr);\n\n  // Build a colon expression.\n  OCTINTERP_API tree_expression *\n  make_colon_expression (tree_expression *base, token *colon_tok, tree_expression *limit);\n\n  // Build a colon expression.\n  OCTINTERP_API tree_expression *\n  make_colon_expression (tree_expression *base, token *colon_1_tok, tree_expression *incr, token *colon_2_tok, tree_expression *limit);\n\n  // Build a binary expression.\n  OCTINTERP_API tree_expression *\n  make_binary_op (tree_expression *op1, token *op_tok, tree_expression *op2);\n\n  // Maybe convert EXPR to a braindead_shortcircuit expression.\n  OCTINTERP_API void\n  maybe_convert_to_braindead_shortcircuit (tree_expression *&expr);\n\n  // Build a boolean expression.\n  OCTINTERP_API tree_expression *\n  make_boolean_op (tree_expression *op1, token *op_tok, tree_expression *op2);\n\n  // Build a prefix expression.\n  OCTINTERP_API tree_expression *\n  make_prefix_op (token *op_tok, tree_expression *op1);\n\n  // Build a postfix expression.\n  OCTINTERP_API tree_expression *\n  make_postfix_op (tree_expression *op1, token *op_tok);\n\n  // Build an unwind-protect command.\n  OCTINTERP_API tree_command *\n  make_unwind_command (token *unwind_tok, tree_statement_list *body, token *cleanup_tok, tree_statement_list *cleanup, token *end_tok);\n\n  // Build a try-catch command.\n  OCTINTERP_API tree_command *\n  make_try_command (token *try_tok, tree_statement_list *body, token *catch_tok, separator_list *catch_sep_list, tree_statement_list *cleanup, token *end_tok);\n\n  // Build a while command.\n  OCTINTERP_API tree_command *\n  make_while_command (token *while_tok, tree_expression *expr, tree_statement_list *body, token *end_tok);\n\n  // Build a do-until command.\n  OCTINTERP_API tree_command *\n  make_do_until_command (token *do_tok, tree_statement_list *body, token *until_tok, tree_expression *expr);\n\n  // Build a for command.\n  OCTINTERP_API tree_command *\n  make_for_command (token *for_tok, token *open_paren, tree_argument_list *lhs, token *eq_tok, tree_expression *expr, token *sep_tok, tree_expression *maxproc, token *close_paren, tree_statement_list *body, token *end_tok);\n\n  // Build a break command.\n  OCTINTERP_API tree_command * make_break_command (token *break_tok);\n\n  // Build a continue command.\n  OCTINTERP_API tree_command * make_continue_command (token *continue_tok);\n\n  // Build a return command.\n  OCTINTERP_API tree_command * make_return_command (token *return_tok);\n\n  // Build an spmd command.\n\n  OCTINTERP_API tree_spmd_command *\n  make_spmd_command (token *spmd_tok, tree_statement_list *body, token *end_tok);\n\n  // Start an if command.\n  OCTINTERP_API tree_if_command_list *\n  start_if_command (tree_if_clause *clause);\n\n  // Finish an if command.\n  OCTINTERP_API tree_if_command *\n  finish_if_command (tree_if_command_list *list, tree_if_clause *else_clause, token *end_tok);\n\n  // Build an elseif clause.\n  OCTINTERP_API tree_if_clause *\n  make_if_clause (token *if_tok, separator_list *if_sep_list, tree_expression *expr, tree_statement_list *list);\n\n  OCTINTERP_API tree_if_command_list *\n  append_if_clause (tree_if_command_list *list, tree_if_clause *clause);\n\n  // Finish a switch command.\n  OCTINTERP_API tree_switch_command *\n  finish_switch_command (token *switch_tok, tree_expression *expr, tree_switch_case_list *list, token *end_tok);\n\n  OCTINTERP_API tree_switch_case_list *\n  make_switch_case_list (tree_switch_case *switch_case);\n\n  // Build a switch case.\n  OCTINTERP_API tree_switch_case *\n  make_switch_case (token *case_tok, tree_expression *expr, tree_statement_list *list);\n\n  OCTINTERP_API tree_switch_case *\n  make_default_switch_case (token *default_tok, tree_statement_list *list);\n\n  OCTINTERP_API tree_switch_case_list *\n  append_switch_case (tree_switch_case_list *list, tree_switch_case *elt);\n\n  // Build an assignment to a variable.\n  OCTINTERP_API tree_expression *\n  make_assign_op (tree_argument_list *lhs, token *eq_tok, tree_expression *rhs);\n\n  // Define a script.\n  OCTINTERP_API void\n  make_script (tree_statement_list *cmds, tree_statement *end_script);\n\n  // Handle identifier that is recognized as a function name.\n  OCTINTERP_API tree_identifier *\n  make_fcn_name (tree_identifier *id);\n\n  // Define a function.\n  OCTINTERP_API tree_function_def *\n  make_function (token *fcn_tok, tree_parameter_list *ret_list, token *eq_tok, tree_identifier *id, tree_parameter_list *param_list, tree_statement_list *body, tree_statement *end_fcn_stmt);\n\n  // Begin defining a function.\n  OCTINTERP_API octave_user_function *\n  start_function (tree_identifier *id, tree_parameter_list *param_list, tree_statement_list *body, tree_statement *end_function, const std::string& doc_string);\n\n  // Create a no-op statement for end_function.\n  OCTINTERP_API tree_statement *\n  make_end (const std::string& type, bool eof, token *tok);\n\n  // Do most of the work for defining a function.\n  OCTINTERP_API octave_user_function *\n  frob_function (tree_identifier *id, octave_user_function *fcn);\n\n  // Finish defining a function.\n  OCTINTERP_API tree_function_def *\n  finish_function (token *fcn_tok, tree_parameter_list *ret_list, token *eq_tok, octave_user_function *fcn);\n\n  OCTINTERP_API tree_statement_list *\n  append_function_body (tree_statement_list *body, tree_statement_list *list);\n\n  // Make an arguments validation block.\n  OCTINTERP_API tree_arguments_block *\n  make_arguments_block (token *arguments_tok, tree_args_block_attribute_list *attr_list, tree_args_block_validation_list *validation_list, token *end_tok);\n\n  OCTINTERP_API tree_args_block_attribute_list *\n  make_args_attribute_list (tree_identifier *attribute_name);\n\n  // Make an argument validation.\n  OCTINTERP_API tree_arg_validation *\n  make_arg_validation (tree_arg_size_spec *size_spec, tree_identifier *class_name, tree_arg_validation_fcns *validation_fcns, token *eq_tok = nullptr, tree_expression *default_value = nullptr);\n\n  // Make an argument validation list.\n  OCTINTERP_API tree_args_block_validation_list *\n  make_args_validation_list (tree_arg_validation *arg_validation);\n\n  // Append an argument validation to an existing list.\n  OCTINTERP_API tree_args_block_validation_list *\n  append_args_validation_list (tree_args_block_validation_list *list, tree_arg_validation *arg_validation);\n\n  // Make an argument size specification object.\n  OCTINTERP_API tree_arg_size_spec *\n  make_arg_size_spec (tree_argument_list *size_args);\n\n  // Make a list of argument validation functions.\n  OCTINTERP_API tree_arg_validation_fcns *\n  make_arg_validation_fcns (tree_argument_list *fcn_args);\n\n  // Reset state after parsing function.\n  OCTINTERP_API void\n  recover_from_parsing_function ();\n\n  OCTINTERP_API tree_classdef *\n  make_classdef (token *tok, tree_classdef_attribute_list *a, tree_identifier *id, tree_classdef_superclass_list *sc, tree_classdef_body *body, token *end_tok);\n\n  OCTINTERP_API tree_classdef_properties_block *\n  make_classdef_properties_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_property_list *plist, token *end_tok);\n\n  OCTINTERP_API tree_classdef_property_list *\n  make_classdef_property_list (tree_classdef_property *prop);\n\n  OCTINTERP_API tree_classdef_property *\n  make_classdef_property (tree_identifier *id, tree_arg_validation *av);\n\n  OCTINTERP_API tree_classdef_property_list *\n  append_classdef_property (tree_classdef_property_list *list, tree_classdef_property *elt);\n\n  OCTINTERP_API tree_classdef_methods_block *\n  make_classdef_methods_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_method_list *mlist, token *end_tok);\n\n  OCTINTERP_API tree_classdef_events_block *\n  make_classdef_events_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_event_list *elist, token *end_tok);\n\n  OCTINTERP_API tree_classdef_event_list *\n  make_classdef_event_list (tree_classdef_event *e);\n\n  OCTINTERP_API tree_classdef_event *\n  make_classdef_event (tree_identifier *id);\n\n  OCTINTERP_API tree_classdef_event_list *\n  append_classdef_event (tree_classdef_event_list *list, tree_classdef_event *elt);\n\n  OCTINTERP_API tree_classdef_enum_block *\n  make_classdef_enum_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_enum_list *elist, token *end_tok);\n\n  OCTINTERP_API tree_classdef_enum_list *\n  make_classdef_enum_list (tree_classdef_enum *e);\n\n  OCTINTERP_API tree_classdef_enum *\n  make_classdef_enum (tree_identifier *id, token *open_paren, tree_expression *expr, token *close_paren);\n\n  OCTINTERP_API tree_classdef_enum_list *\n  append_classdef_enum (tree_classdef_enum_list *list, tree_classdef_enum *elt);\n\n  OCTINTERP_API tree_classdef_superclass_list *\n  make_classdef_superclass_list (token *lt_tok, tree_classdef_superclass *sc);\n\n  OCTINTERP_API tree_classdef_superclass *\n  make_classdef_superclass (token *fqident);\n\n  OCTINTERP_API tree_classdef_superclass_list *\n  append_classdef_superclass (tree_classdef_superclass_list *list, token *and_tok, tree_classdef_superclass *elt);\n\n  OCTINTERP_API tree_classdef_attribute_list *\n  make_classdef_attribute_list (tree_classdef_attribute *attr);\n\n  OCTINTERP_API tree_classdef_attribute *\n  make_classdef_attribute (tree_identifier *id);\n\n  OCTINTERP_API tree_classdef_attribute *\n  make_classdef_attribute (tree_identifier *id, token *eq_tok, tree_expression *expr);\n\n  OCTINTERP_API tree_classdef_attribute *\n  make_not_classdef_attribute (token *not_tok, tree_identifier *id);\n\n  OCTINTERP_API tree_classdef_attribute_list *\n  append_classdef_attribute (tree_classdef_attribute_list *list, token *sep_tok, tree_classdef_attribute *elt);\n\n  OCTINTERP_API tree_classdef_body *\n  make_classdef_body (tree_classdef_properties_block *pb);\n\n  OCTINTERP_API tree_classdef_body *\n  make_classdef_body (tree_classdef_methods_block *mb);\n\n  OCTINTERP_API tree_classdef_body *\n  make_classdef_body (tree_classdef_events_block *evb);\n\n  OCTINTERP_API tree_classdef_body *\n  make_classdef_body  (tree_classdef_enum_block *enb);\n\n  OCTINTERP_API tree_classdef_body *\n  append_classdef_properties_block (tree_classdef_body *body, tree_classdef_properties_block *block);\n\n  OCTINTERP_API tree_classdef_body *\n  append_classdef_methods_block (tree_classdef_body *body, tree_classdef_methods_block *block);\n\n  OCTINTERP_API tree_classdef_body *\n  append_classdef_events_block (tree_classdef_body *body, tree_classdef_events_block *block);\n\n  OCTINTERP_API tree_classdef_body *\n  append_classdef_enum_block (tree_classdef_body *body, tree_classdef_enum_block *block);\n\n  OCTINTERP_API octave_user_function *\n  start_classdef_external_method (tree_identifier *id, tree_parameter_list *pl = nullptr);\n\n  OCTINTERP_API tree_function_def *\n  finish_classdef_external_method (octave_user_function *fcn, tree_parameter_list *ret_list = nullptr, token *eq_tok = nullptr);\n\n  OCTINTERP_API tree_classdef_method_list *\n  make_classdef_method_list (tree_function_def *fcn_def);\n\n  OCTINTERP_API tree_classdef_method_list *\n  append_classdef_method (tree_classdef_method_list *list, tree_function_def *fcn_def);\n\n  OCTINTERP_API bool\n  finish_classdef_file (tree_classdef *cls, tree_statement_list *local_fcns, token *eof_tok);\n\n  // Make a word list command.\n  OCTINTERP_API tree_index_expression *\n  make_word_list_command (tree_expression *expr, tree_argument_list *args);\n\n  // Make an index expression.\n  OCTINTERP_API tree_index_expression *\n  make_index_expression (tree_expression *expr, token *open_paren, tree_argument_list *args, token *close_paren, char type);\n\n  // Make an indirect reference expression.\n  OCTINTERP_API tree_index_expression *\n  make_indirect_ref (tree_expression *expr, token *dot_tok, token *struct_elt_tok);\n\n  // Make an indirect reference expression with dynamic field name.\n  OCTINTERP_API tree_index_expression *\n  make_indirect_ref (tree_expression *expr, token *dot_tok, token *open_paren, tree_expression *field, token *close_paren);\n\n  // Make a declaration command.\n  OCTINTERP_API tree_decl_command *\n  make_decl_command (token *tok, tree_decl_init_list *lst);\n\n  OCTINTERP_API tree_decl_init_list *\n  make_decl_init_list (tree_decl_elt *elt);\n\n  OCTINTERP_API tree_decl_elt *\n  make_decl_elt (tree_identifier *id, token *eq_op = nullptr, tree_expression *expr = nullptr);\n\n  OCTINTERP_API tree_decl_init_list *\n  append_decl_init_list (tree_decl_init_list *list, tree_decl_elt *elt);\n\n  // Validate an function parameter list.\n  OCTINTERP_API bool\n  validate_param_list (tree_parameter_list *lst, tree_parameter_list::in_or_out type);\n  // Validate matrix or cell\n  OCTINTERP_API bool validate_array_list (tree_expression *e);\n\n  // Validate matrix object used in \"[lhs] = ...\" assignments.\n  OCTINTERP_API tree_argument_list *\n  validate_matrix_for_assignment (tree_expression *e);\n\n  // Finish building an array_list (common action for finish_matrix\n  // and finish_cell).\n  OCTINTERP_API tree_expression *\n  finish_array_list (token *open_delim, tree_array_list *a, token *close_delim);\n\n  // Finish building a matrix list.\n  OCTINTERP_API tree_expression *\n  finish_matrix (token *open_delim, tree_matrix *m, token *close_delim);\n\n  // Finish building a cell list.\n  OCTINTERP_API tree_expression *\n  finish_cell (token *open_delim, tree_cell *c, token *close_delim);\n\n  OCTINTERP_API tree_identifier *\n  make_identifier (token *ident);\n\n  OCTINTERP_API tree_superclass_ref *\n  make_superclass_ref (token *superclassref);\n\n  OCTINTERP_API tree_metaclass_query *\n  make_metaclass_query (token *metaquery);\n\n  // Set the print flag for a statement based on the separator type.\n  OCTINTERP_API tree_statement_list *\n  set_stmt_print_flag (tree_statement_list *list, int sep_char, bool warn_missing_semi);\n\n  // Set the print flag for a statement based on the separator type.\n  OCTINTERP_API tree_statement_list *\n  set_stmt_print_flag (tree_statement_list *list, const token& sep_tok, bool warn_missing_semi);\n\n  // Set the print flag for a statement based on the separator type.\n  OCTINTERP_API tree_statement_list *\n  set_stmt_print_flag (tree_statement_list *list, separator_list *sep_list, bool warn_missing_semi);\n\n  // Finish building a statement.\n  template <typename T>\n  OCTINTERP_API tree_statement * make_statement (T *arg);\n\n  // Create a statement list.\n  OCTINTERP_API tree_statement_list *\n  make_statement_list (tree_statement *stmt);\n\n  // Append a statement to an existing statement list.\n  OCTINTERP_API tree_statement_list *\n  append_statement_list (tree_statement_list *list, int sep_char, tree_statement *stmt, bool warn_missing_semi);\n\n  // Append a statement to an existing statement list.\n  OCTINTERP_API tree_statement_list *\n  append_statement_list (tree_statement_list *list, token *sep_tok, tree_statement *stmt, bool warn_missing_semi);\n\n  // Append a statement to an existing statement list.\n  OCTINTERP_API tree_statement_list *\n  append_statement_list (tree_statement_list *list, separator_list *sep_list, tree_statement *stmt, bool warn_missing_semi);\n\n  // Create a statement list containing only function_def commands.\n  OCTINTERP_API tree_statement_list *\n  make_function_def_list (tree_function_def *fcn_def);\n\n  // Append a function_def command to an existing statement list (that\n  // should contain only other function_def commands).\n  OCTINTERP_API tree_statement_list *\n  append_function_def_list (tree_statement_list *list, separator_list *sep_list, tree_function_def *fcn_def);\n\n  OCTINTERP_API tree_argument_list *\n  make_argument_list (tree_expression *expr);\n\n  OCTINTERP_API tree_argument_list *\n  append_argument_list (tree_argument_list *list, tree_expression *expr);\n\n  OCTINTERP_API tree_argument_list *\n  append_argument_list (tree_argument_list *list, token *sep_tok, tree_expression *expr);\n\n  OCTINTERP_API tree_parameter_list *\n  make_parameter_list (tree_parameter_list::in_or_out io);\n\n  OCTINTERP_API tree_parameter_list *\n  make_parameter_list (tree_parameter_list::in_or_out io, tree_decl_elt *t);\n\n  OCTINTERP_API tree_parameter_list *\n  make_parameter_list (tree_parameter_list::in_or_out io, tree_identifier *id);\n\n  OCTINTERP_API tree_parameter_list *\n  append_parameter_list (tree_parameter_list *list, token *sep_tok, tree_decl_elt *t);\n\n  OCTINTERP_API tree_parameter_list *\n  append_parameter_list (tree_parameter_list *list, token *sep_tok, tree_identifier *id);\n\n  // Don't allow parsing command syntax.  If the parser/lexer is\n  // reset, this setting is also reset to the default (allow command\n  // syntax).\n  OCTINTERP_API void disallow_command_syntax ();\n\n  // Generic error messages.\n  OCTINTERP_API void bison_error (const std::string& s);\n  OCTINTERP_API void bison_error (const std::string& s, const filepos& pos);\n  OCTINTERP_API void bison_error (const std::list<parse_exception>& pe);\n  OCTINTERP_API void bison_error (const parse_exception& pe);\n\n  friend OCTINTERP_API octave_value\n  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);\n\n  // Thih interface allows push or pull parsers to be used\n  // equivalently, provided that the push parser also owns its input\n  // method (see below).  Alternatively, the push parser interface may\n  // use a separate run method and completely separate input from\n  // lexical analysis and parsing.\n\n  virtual int run () = 0;\n\n  // Check primary script or function generated by the parser for\n  // semantic errors.\n  OCTINTERP_API bool validate_primary_fcn ();\n\n  OCTINTERP_API bool finish_input (tree_statement_list *lst, bool at_eof = false);\n\nprotected:\n\n  // Contains error message if Bison-generated parser returns nonzero\n  // status.\n  std::string m_parse_error_msg;\n\n  // Have we found an explicit end to a function?\n  bool m_endfunction_found;\n\n  // TRUE means we are in the process of autoloading a function.\n  bool m_autoloading;\n\n  // TRUE means the current function file was found in a relative path\n  // element.\n  bool m_fcn_file_from_relative_lookup;\n\n  // FALSE if we are still at the primary function.  Subfunctions can\n  // only be declared inside function files.\n  bool m_parsing_subfunctions;\n\n  // TRUE if we are parsing local functions defined at after a\n  // classdef block.  Local functions can only be declared inside\n  // classdef files.\n  bool m_parsing_local_functions;\n\n  // Maximum function depth detected.  Used to determine whether\n  // we have nested functions or just implicitly ended subfunctions.\n  int m_max_fcn_depth;\n\n  // = 0 currently outside any function.\n  // = 1 inside the primary function or a subfunction.\n  // > 1 means we are looking at a function definition that seems to be\n  //     inside a function.  Note that the function still might not be a\n  //     nested function.\n  int m_curr_fcn_depth;\n\n  // Scope where we install all subfunctions and nested functions.  Only\n  // used while reading function files.\n  symbol_scope m_primary_fcn_scope;\n\n  // Name of the current class when we are parsing class methods or\n  // constructors.\n  std::string m_curr_class_name;\n\n  // Name of the current package when we are parsing an element contained\n  // in a package directory (+-directory).\n  std::string m_curr_package_name;\n\n  // Nested function scopes and names currently being parsed.\n  parent_scope_info m_function_scopes;\n\n  // Pointer to the primary user function or user script function.\n  octave_value m_primary_fcn;\n\n  // List of subfunction names, initially in the order they are\n  // installed in the symbol table, then ordered as they appear in the\n  // file.  Eventually stashed in the primary function object.\n  std::list<std::string> m_subfunction_names;\n\n  // Pointer to the classdef object we just parsed, if any.\n  std::shared_ptr<tree_classdef> m_classdef_object;\n\n  // Result of parsing input.\n  std::shared_ptr<tree_statement_list> m_stmt_list;\n\n  // State of the lexer.\n  base_lexer& m_lexer;\n\n  // Internal state of the Bison parser.\n  void *m_parser_state;\n\nprivate:\n\n  // Maybe print a warning if an assignment expression is used as the\n  // test in a logical expression.\n  OCTINTERP_API void maybe_warn_assign_as_truth_value (tree_expression *expr);\n\n  // Maybe print a warning about switch labels that aren't constants.\n  OCTINTERP_API void maybe_warn_variable_switch_label (tree_expression *expr);\n\n  // Maybe print a warning.\n  OCTINTERP_API void maybe_warn_missing_semi (tree_statement_list *);\n};\n\n// Publish externally used friend functions.\n\nextern OCTINTERP_API octave_value\nparse_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);\n\nclass parser : public base_parser\n{\npublic:\n\n  parser (interpreter& interp)\n    : base_parser (*(new lexer (interp)))\n  { }\n\n  parser (FILE *file, interpreter& interp)\n    : base_parser (*(new lexer (file, interp)))\n  { }\n\n  parser (FILE *file, interpreter& interp, std::string encoding)\n    : base_parser (*(new lexer (file, interp, encoding)))\n  { }\n\n  parser (const std::string& eval_string, interpreter& interp)\n    : base_parser (*(new lexer (eval_string, interp)))\n  { }\n\n  // The lexer must be allocated with new.  The parser object\n  // takes ownership of and deletes the lexer object in its\n  // destructor.\n\n  parser (lexer *lxr)\n    : base_parser (*lxr)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (parser)\n\n  ~parser () = default;\n\n  OCTINTERP_API int run ();\n};\n\nclass push_parser : public base_parser\n{\npublic:\n\n  push_parser (interpreter& interp)\n    : base_parser (*(new push_lexer (interp))), m_interpreter (interp), m_reader ()\n  { }\n\n  // The parser assumes ownership of READER, which must be created\n  // with new.\n\n  push_parser (interpreter& interp, input_reader *reader)\n    : base_parser (*(new push_lexer (interp))), m_interpreter (interp), m_reader (reader)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (push_parser)\n\n  ~push_parser () = default;\n\n  // Use the push parser in the same way as the pull parser.  The\n  // parser arranges for input through the M_READER object.  See, for\n  // example, interpreter::main_loop.\n\n  OCTINTERP_API int run ();\n\n  // Parse INPUT.  M_READER is not used.  The user is responsible for\n  // collecting input.\n\n  OCTINTERP_API int run (const std::string& input, bool eof);\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  std::shared_ptr<input_reader> m_reader;\n};\n\nextern OCTINTERP_API std::string\nget_help_from_file (const std::string& nm, bool& symbol_found, std::string& file);\n\nextern OCTINTERP_API std::string\nget_help_from_file (const std::string& nm, bool& symbol_found);\n\nextern OCTINTERP_API octave_value\nload_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);\n\nextern OCTINTERP_API void\nsource_file (const std::string& file_name, const std::string& context = \"\", bool verbose = false, bool require_file = true);\n\nextern OCTINTERP_API octave_value_list\nfeval (const char *name, const octave_value_list& args = octave_value_list (), int nargout = 0);\n\nextern OCTINTERP_API octave_value_list\nfeval (const std::string& name, const octave_value_list& args = octave_value_list (), int nargout = 0);\n\nextern OCTINTERP_API octave_value_list\nfeval (octave_function *fcn, const octave_value_list& args = octave_value_list (), int nargout = 0);\n\nextern OCTINTERP_API octave_value_list\nfeval (const octave_value& val, const octave_value_list& args = octave_value_list (), int nargout = 0);\n\nextern OCTINTERP_API octave_value_list\nfeval (const octave_value_list& args, int nargout = 0);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/profiler.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"event-manager.h\"\n#include \"interpreter.h\"\n#include \"oct-time.h\"\n#include \"ov-struct.h\"\n#include \"pager.h\"\n#include \"profiler.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nprofiler::stats::stats ()\n  : m_time (0.0), m_calls (0), m_recursive (false),\n    m_parents (), m_children ()\n{ }\n\noctave_value\nprofiler::stats::function_set_value (const function_set& list)\n{\n  const octave_idx_type n = list.size ();\n\n  RowVector retval (n);\n  octave_idx_type i = 0;\n  for (const auto& nm : list)\n    retval(i++) = nm;\n\n  return retval;\n}\n\nprofiler::tree_node::tree_node (tree_node *p, octave_idx_type f)\n  : m_parent (p), m_fcn_id (f), m_children (), m_time (0.0), m_calls (0)\n{ }\n\nprofiler::tree_node::~tree_node ()\n{\n  for (auto& idx_tnode : m_children)\n    delete idx_tnode.second;\n}\n\nprofiler::tree_node *\nprofiler::tree_node::enter (octave_idx_type fcn)\n{\n  tree_node *retval;\n\n  child_map::iterator pos = m_children.find (fcn);\n  if (pos == m_children.end ())\n    {\n      retval = new tree_node (this, fcn);\n      m_children[fcn] = retval;\n    }\n  else\n    retval = pos->second;\n\n  ++retval->m_calls;\n  return retval;\n}\n\nprofiler::tree_node *\nprofiler::tree_node::exit (octave_idx_type /* fcn */)\n{\n  return m_parent;\n}\n\nvoid\nprofiler::tree_node::build_flat (flat_profile& data) const\n{\n  // If this is not the top-level node,\n  // update profile entry for this function.\n  if (m_fcn_id != 0)\n    {\n      stats& entry = data[m_fcn_id - 1];\n\n      entry.m_time += m_time;\n      entry.m_calls += m_calls;\n\n      if (! m_parent)\n        error (\"unexpected: m_parent is nullptr in profiler::tree_node::build_flat - please report this bug\");\n\n      if (m_parent->m_fcn_id != 0)\n        {\n          entry.m_parents.insert (m_parent->m_fcn_id);\n          data[m_parent->m_fcn_id - 1].m_children.insert (m_fcn_id);\n        }\n\n      if (! entry.m_recursive)\n        for (const tree_node *i = m_parent; i; i = i->m_parent)\n          if (i->m_fcn_id == m_fcn_id)\n            {\n              entry.m_recursive = true;\n              break;\n            }\n    }\n\n  // Recurse on children.\n  for (const auto& idx_tnode : m_children)\n    idx_tnode.second->build_flat (data);\n}\n\noctave_value\nprofiler::tree_node::get_hierarchical (double *total) const\n{\n  // Note that we don't generate the entry just for this node, but\n  // rather a struct-array with entries for all children.  This way, the\n  // top-node (for which we don't want a real entry) generates already\n  // the final hierarchical profile data.\n\n  const octave_idx_type n = m_children.size ();\n\n  Cell rv_indices (n, 1);\n  Cell rv_times (n, 1);\n  Cell rv_totals (n, 1);\n  Cell rv_calls (n, 1);\n  Cell rv_children (n, 1);\n\n  octave_idx_type i = 0;\n  for (const auto& idx_tnode : m_children)\n    {\n      const tree_node& entry = *idx_tnode.second;\n      double child_total = entry.m_time;\n\n      rv_indices(i) = octave_value (idx_tnode.first);\n      rv_times(i) = octave_value (entry.m_time);\n      rv_calls(i) = octave_value (entry.m_calls);\n      rv_children(i) = entry.get_hierarchical (&child_total);\n      rv_totals(i) = octave_value (child_total);\n\n      if (total)\n        *total += child_total;\n\n      ++i;\n    }\n\n  octave_map retval;\n\n  retval.assign (\"Index\", rv_indices);\n  retval.assign (\"SelfTime\", rv_times);\n  retval.assign (\"TotalTime\", rv_totals);\n  retval.assign (\"NumCalls\", rv_calls);\n  retval.assign (\"Children\", rv_children);\n\n  return retval;\n}\n\nprofiler::profiler ()\n  : m_known_functions (), m_fcn_index (),\n    m_enabled (false), m_call_tree (new tree_node (nullptr, 0)),\n    m_active_fcn (nullptr), m_last_time (-1.0)\n{ }\n\nprofiler::~profiler ()\n{\n  delete m_call_tree;\n}\n\nvoid\nprofiler::set_active (bool value)\n{\n  m_enabled = value;\n}\n\nvoid\nprofiler::enter_function (const std::string& fcn)\n{\n  // The enter class will check and only call us if the profiler is active.\n  if (! enabled ())\n    error (\"unexpected: profiler not enabled in profiler::enter_function - please report this bug\");\n\n  if (! m_call_tree)\n    error (\"unexpected: m_call_tree is nullptr in profiler::enter_function - please report this bug\");\n\n  // If there is already an active function, add to its time before\n  // pushing the new one.\n  if (m_active_fcn && m_active_fcn != m_call_tree)\n    add_current_time ();\n\n  // Map the function's name to its index.\n  octave_idx_type fcn_idx;\n  fcn_index_map::iterator pos = m_fcn_index.find (fcn);\n  if (pos == m_fcn_index.end ())\n    {\n      m_known_functions.push_back (fcn);\n      fcn_idx = m_known_functions.size ();\n      m_fcn_index[fcn] = fcn_idx;\n    }\n  else\n    fcn_idx = pos->second;\n\n  if (! m_active_fcn)\n    m_active_fcn = m_call_tree;\n\n  m_active_fcn = m_active_fcn->enter (fcn_idx);\n\n  m_last_time = query_time ();\n\n}\n\nvoid\nprofiler::exit_function (const std::string& fcn)\n{\n  if (m_active_fcn)\n    {\n      if (! m_call_tree)\n        error (\"unexpected: m_call_tree is nullptr in profiler::enter_function - please report this bug\");\n\n      // Usually, if we are disabled this function is not even called.  But\n      // the call disabling the profiler is an exception.  So also check here\n      // and only record the time if enabled.\n      if (enabled ())\n        add_current_time ();\n\n      fcn_index_map::iterator pos = m_fcn_index.find (fcn);\n\n      m_active_fcn = m_active_fcn->exit (pos->second);\n\n      // If this was an \"inner call\", we resume executing the parent function\n      // up the stack.  So note the start-time for this!\n      m_last_time = query_time ();\n    }\n}\n\nvoid\nprofiler::reset ()\n{\n  if (enabled ())\n    error (\"profile: can't reset active profiler\");\n\n  m_known_functions.clear ();\n  m_fcn_index.clear ();\n\n  if (m_call_tree)\n    {\n      delete m_call_tree;\n      m_call_tree = new tree_node (nullptr, 0);\n      m_active_fcn = nullptr;\n    }\n\n  m_last_time = -1.0;\n}\n\noctave_value\nprofiler::get_flat () const\n{\n  octave_value retval;\n\n  const octave_idx_type n = m_known_functions.size ();\n\n  flat_profile flat (n);\n\n  if (m_call_tree)\n    {\n      m_call_tree->build_flat (flat);\n\n      Cell rv_names (n, 1);\n      Cell rv_times (n, 1);\n      Cell rv_calls (n, 1);\n      Cell rv_recursive (n, 1);\n      Cell rv_parents (n, 1);\n      Cell rv_children (n, 1);\n\n      for (octave_idx_type i = 0; i != n; ++i)\n        {\n          rv_names(i) = octave_value (m_known_functions[i]);\n          rv_times(i) = octave_value (flat[i].m_time);\n          rv_calls(i) = octave_value (flat[i].m_calls);\n          rv_recursive(i) = octave_value (flat[i].m_recursive);\n          rv_parents(i) = stats::function_set_value (flat[i].m_parents);\n          rv_children(i) = stats::function_set_value (flat[i].m_children);\n        }\n\n      octave_map m;\n\n      m.assign (\"FunctionName\", rv_names);\n      m.assign (\"TotalTime\", rv_times);\n      m.assign (\"NumCalls\", rv_calls);\n      m.assign (\"IsRecursive\", rv_recursive);\n      m.assign (\"Parents\", rv_parents);\n      m.assign (\"Children\", rv_children);\n\n      retval = m;\n    }\n  else\n    {\n      static const char *fn[] =\n      {\n        \"FunctionName\",\n        \"TotalTime\",\n        \"NumCalls\",\n        \"IsRecursive\",\n        \"Parents\",\n        \"Children\",\n        nullptr\n      };\n\n      static octave_map m (dim_vector (0, 1), string_vector (fn));\n\n      retval = m;\n    }\n\n  return retval;\n}\n\noctave_value\nprofiler::get_hierarchical () const\n{\n  octave_value retval;\n\n  if (m_call_tree)\n    retval = m_call_tree->get_hierarchical ();\n  else\n    {\n      static const char *fn[] =\n      {\n        \"Index\",\n        \"SelfTime\",\n        \"NumCalls\",\n        \"Children\",\n        nullptr\n      };\n\n      static octave_map m (dim_vector (0, 1), string_vector (fn));\n\n      retval = m;\n    }\n\n  return retval;\n}\n\ndouble\nprofiler::query_time () const\n{\n  sys::time now;\n\n  return now.double_value ();\n}\n\nvoid\nprofiler::add_current_time ()\n{\n  if (m_active_fcn)\n    {\n      const double t = query_time ();\n\n      m_active_fcn->add_time (t - m_last_time);\n    }\n}\n\n// Enable or disable the profiler data collection.\nDEFMETHOD (__profiler_enable__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{state} =} __profiler_enable__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin > 1)\n    print_usage ();\n\n  profiler& profiler = interp.get_profiler ();\n\n  if (nargin == 1)\n    {\n      profiler.set_active (args(0).bool_value ());\n\n      std::string status = \"off\";\n      if (args(0).bool_value ())\n        status = \"on\";\n\n      event_manager& evmgr = interp.get_event_manager ();\n      evmgr.gui_status_update (\"profiler\", status);  // tell GUI\n    }\n\n  return ovl (profiler.enabled ());\n}\n\n// Clear all collected profiling data.\nDEFMETHOD (__profiler_reset__, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} __profiler_reset__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  profiler& profiler = interp.get_profiler ();\n\n  profiler.reset ();\n\n  return ovl ();\n}\n\n// Query the timings collected by the profiler.\nDEFMETHOD (__profiler_data__, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {@var{data} =} __profiler_data__ ()\nUndocumented internal function.\n@end deftypefn */)\n{\n  if (args.length () != 0)\n    print_usage ();\n\n  profiler& profiler = interp.get_profiler ();\n\n  if (nargout > 1)\n    return ovl (profiler.get_flat (), profiler.get_hierarchical ());\n  else\n    return ovl (profiler.get_flat ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/profiler.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_profiler_h)\n#define octave_profiler_h 1\n\n#include \"octave-config.h\"\n\n#include <cstddef>\n#include <map>\n#include <set>\n#include <string>\n#include <vector>\n\nclass octave_value;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API profiler\n{\npublic:\n\n  // This is a utility class that can be used to call the enter/exit\n  // functions in a manner protected from stack unwinding.\n  template <typename T> class enter\n  {\n  public:\n\n    enter (profiler& p, const T& t) : m_profiler (p)\n    {\n      // A profiling block cannot be active if the profiler is not\n      m_enabled = m_profiler.enabled ();\n\n      if (m_enabled)\n        {\n          m_fcn = t.profiler_name ();\n\n          // NOTE: The test f != \"\" must be kept to prevent a blank\n          // line showing up in profiler statistics.  See bug\n          // #39524.  The root cause is that the function name is\n          // not set for the recurring readline hook function.\n          if (m_fcn == \"\")\n            m_enabled = false;  // Inactive profiling block\n          else\n            m_profiler.enter_function (m_fcn);\n        }\n    }\n\n    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (enter)\n\n    ~enter ()\n    {\n      if (m_enabled)\n        m_profiler.exit_function (m_fcn);\n    }\n\n  private:\n\n    profiler& m_profiler;\n    std::string m_fcn;\n    bool m_enabled;\n  };\n\n  profiler ();\n\n  OCTAVE_DISABLE_COPY_MOVE (profiler)\n\n  virtual ~profiler ();\n\n  bool enabled () const { return m_enabled; }\n  void set_active (bool);\n\n  void reset ();\n\n  octave_value get_flat () const;\n  octave_value get_hierarchical () const;\n\nprivate:\n\n  // One entry in the flat profile (i.e., a collection of data for a single\n  // function).  This is filled in when building the flat profile from the\n  // hierarchical call tree.\n  struct stats\n  {\n  public:\n\n    stats ();\n\n    OCTAVE_DEFAULT_COPY_MOVE_DELETE (stats)\n\n    typedef std::set<octave_idx_type> function_set;\n\n    // Convert a function_set list to an Octave array of indices.\n    static octave_value function_set_value (const function_set&);\n\n    //--------\n\n    double m_time;\n    std::size_t m_calls;\n\n    bool m_recursive;\n\n    function_set m_parents;\n    function_set m_children;\n  };\n\n  typedef std::vector<stats> flat_profile;\n\n  // Store data for one node in the call-tree of the hierarchical profiler\n  // data we collect.\n  class tree_node\n  {\n  public:\n\n    tree_node (tree_node *, octave_idx_type);\n\n    virtual ~tree_node ();\n\n    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_node)\n\n    void add_time (double dt) { m_time += dt; }\n\n    // Enter a child function.  It is created in the list of children if it\n    // wasn't already there.  The now-active child node is returned.\n    tree_node * enter (octave_idx_type);\n\n    // Exit function.  As a sanity-check, it is verified that the currently\n    // active function actually is the one handed in here.  Returned is the\n    // then-active node, which is our parent.\n    tree_node * exit (octave_idx_type);\n\n    void build_flat (flat_profile&) const;\n\n    // Get the hierarchical profile for this node and its children.  If total\n    // is set, accumulate total time of the subtree in that variable as\n    // additional return value.\n    octave_value get_hierarchical (double *total = nullptr) const;\n\n  private:\n\n    tree_node *m_parent;\n    octave_idx_type m_fcn_id;\n\n    typedef std::map<octave_idx_type, tree_node *> child_map;\n    child_map m_children;\n\n    // This is only time spent *directly* on this level, excluding children!\n    double m_time;\n\n    std::size_t m_calls;\n  };\n\n  // These are private as only the unwind-protecting inner class enter\n  // should be allowed to call them.\n  void enter_function (const std::string&);\n  void exit_function (const std::string&);\n\n  // Query a timestamp, used for timing calls (obviously).\n  // This is not static because in the future, maybe we want a flag\n  // in the profiler or something to choose between cputime, wall-time,\n  // user-time, system-time, ...\n  double query_time () const;\n\n  // Add the time elapsed since last_time to the function we're currently in.\n  // This is called from two different positions, thus it is useful to have\n  // it as a separate function.\n  void add_current_time ();\n\n  //--------\n\n  // Each function we see in the profiler is given a unique index (which\n  // simply counts starting from 1).  We thus have to map profiler-names to\n  // those indices.  For all other stuff, we identify functions by their\n  // index.\n\n  typedef std::vector<std::string> function_set;\n  typedef std::map<std::string, octave_idx_type> fcn_index_map;\n\n  function_set m_known_functions;\n  fcn_index_map m_fcn_index;\n\n  bool m_enabled;\n\n  tree_node *m_call_tree;\n  tree_node *m_active_fcn;\n\n  // Store last timestamp we had, when the currently active function was\n  // called.\n  double m_last_time;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-all.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_all_h)\n#define octave_pt_all_h 1\n\n#include \"octave-config.h\"\n\n#include \"pt.h\"\n#include \"pt-args-block.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-assign.h\"\n#include \"pt-bp.h\"\n#include \"pt-binop.h\"\n#include \"pt-cbinop.h\"\n#include \"pt-check.h\"\n#include \"pt-classdef.h\"\n#include \"pt-cmd.h\"\n#include \"pt-colon.h\"\n#include \"pt-const.h\"\n#include \"pt-decl.h\"\n#include \"pt-except.h\"\n#include \"pt-exp.h\"\n#include \"pt-fcn-handle.h\"\n#include \"pt-id.h\"\n#include \"pt-idx.h\"\n#include \"pt-jump.h\"\n#include \"pt-loop.h\"\n#include \"pt-mat.h\"\n#include \"pt-cell.h\"\n#include \"pt-misc.h\"\n#include \"pt-pr-code.h\"\n#include \"pt-select.h\"\n#include \"pt-spmd.h\"\n#include \"pt-stmt.h\"\n#include \"pt-unop.h\"\n#include \"pt-pr-code.h\"\n#include \"pt-walk.h\"\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-anon-scopes.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"pt-all.h\"\n#include \"pt-anon-scopes.h\"\n\n// TODO: make sure that if(f->scope()) is checked if necessary\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntree_anon_scopes::tree_anon_scopes (tree_anon_fcn_handle& anon_fh)\n  : tree_walker (), m_params (), m_vars ()\n{\n  visit_anon_fcn_handle (anon_fh);\n}\n\nvoid\ntree_anon_scopes::visit_anon_fcn_handle (tree_anon_fcn_handle& afh)\n{\n  tree_parameter_list *param_list = afh.parameter_list ();\n  tree_expression *expr = afh.expression ();\n\n  // Collect names of parameters.\n\n  if (param_list)\n    {\n      std::list<std::string> pnames = param_list->variable_names ();\n\n      for (const auto& nm : pnames)\n        m_params.insert (nm);\n\n      // Hmm, should this be included in the list returned from\n      // tree_parameter_list::variable_names?\n      if (param_list->takes_varargs ())\n        m_params.insert (\"varargin\");\n    }\n\n  // Further walk the tree to find free variables in this expression\n  // and any nested definitions of additional anonymous functions.\n\n  if (expr)\n    expr->accept (*this);\n}\n\n// The rest of visit_... methods is only for walking the tree.  Many of\n// them, in particular all methods for commands, are not applicable to\n// anonymous functions.  Only parts of the tree are walked which could\n// contain further (nested) anonymous function definitions (so, e.g.,\n// identifiers and left hand sides of assignments are ignored).\n\nvoid\ntree_anon_scopes::visit_identifier (tree_identifier& id)\n{\n  std::string nm = id.name ();\n\n  if (m_params.find (nm) == m_params.end ())\n    m_vars.insert (nm);\n}\n\nvoid\ntree_anon_scopes::visit_parameter_list (tree_parameter_list&)\n{\n  // In visit_anon_fcn_handle we only accept/visit the body of\n  // anonymous function definitions, not the parameter list.\n\n  error (\"unexpected call to tree_anon_scopes::visit_parameter_list - please report this bug\");\n}\n\nvoid\ntree_anon_scopes::visit_statement (tree_statement& stmt)\n{\n  tree_command *cmd = stmt.command ();\n\n  if (cmd)\n    error (\"unexpected call to tree_anon_scopes::visit_statement - please report this bug\");\n  else\n    {\n      tree_expression *expr = stmt.expression ();\n\n      if (expr)\n        expr->accept (*this);\n    }\n}\n\nvoid\ntree_anon_scopes::visit_statement_list (tree_statement_list& lst)\n{\n  for (auto& p : lst)\n    {\n      tree_statement *elt = p;\n\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-anon-scopes.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_anon_scopes_h)\n#define octave_pt_anon_scopes_h 1\n\n#include <set>\n#include <string>\n\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// In possibly nested definitions of anonymous functions, collect\n// their scopes and the symbol records therein.\n\nclass OCTINTERP_API tree_anon_scopes : public tree_walker\n{\npublic:\n\n  tree_anon_scopes () = delete;\n\n  tree_anon_scopes (tree_anon_fcn_handle& anon_fh);\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_anon_scopes)\n\n  ~tree_anon_scopes () = default;\n\n  std::set<std::string> fcn_parameters () const { return m_params; }\n\n  std::set<std::string> free_variables () const { return m_vars; }\n\n  // The following methods, though public, don't belong to the\n  // intended user interface of this class.\n\n  void visit_anon_fcn_handle (tree_anon_fcn_handle&);\n\n  void visit_identifier (tree_identifier&);\n\n  void visit_parameter_list (tree_parameter_list&);\n\n  void visit_statement (tree_statement&);\n\n  void visit_statement_list (tree_statement_list&);\n\nprivate:\n\n  // Variable names that are function parameters.\n  std::set<std::string> m_params;\n\n  // Other variable names.\n  std::set<std::string> m_vars;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-arg-list.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"str-vec.h\"\n\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-exp.h\"\n#include \"pt-id.h\"\n#include \"pt-idx.h\"\n#include \"pt-pr-code.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Argument lists.\n\ntree_argument_list::~tree_argument_list ()\n{\n  while (! empty ())\n    {\n      auto p = begin ();\n      delete *p;\n      erase (p);\n    }\n}\n\nvoid\ntree_argument_list::push_back (const element_type& s)\n{\n  std::list<tree_expression *>::push_back (s);\n\n  if (! m_list_includes_magic_tilde && s && s->is_identifier ())\n    {\n      tree_identifier *id = dynamic_cast<tree_identifier *> (s);\n      m_list_includes_magic_tilde = id && id->is_black_hole ();\n    }\n}\n\nbool\ntree_argument_list::all_elements_are_constant () const\n{\n  for (const tree_expression *elt : *this)\n    {\n      if (! elt->is_constant ())\n        return false;\n    }\n\n  return true;\n}\n\nbool\ntree_argument_list::is_valid_lvalue_list () const\n{\n  bool retval = true;\n\n  for (const tree_expression *elt : *this)\n    {\n      // There is no need for a separate check for the magic \"~\" because it\n      // is represented by tree_black_hole, and that is derived from\n      // tree_identifier.\n      if (! (elt->is_identifier () || elt->is_index_expression ()))\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nstring_vector\ntree_argument_list::get_arg_names () const\n{\n  int len = size ();\n\n  string_vector retval (len);\n\n  int k = 0;\n\n  for (tree_expression *elt : *this)\n    retval(k++) = elt->str_print_code ();\n\n  return retval;\n}\n\nstd::list<std::string>\ntree_argument_list::variable_names () const\n{\n  std::list<std::string> retval;\n\n  for (tree_expression *elt : *this)\n    {\n      if (elt->is_identifier ())\n        {\n          tree_identifier *id = dynamic_cast<tree_identifier *> (elt);\n\n          retval.push_back (id->name ());\n        }\n      else if (elt->is_index_expression ())\n        {\n          tree_index_expression *idx_expr\n            = dynamic_cast<tree_index_expression *> (elt);\n\n          retval.push_back (idx_expr->name ());\n        }\n    }\n\n  return retval;\n}\n\ntree_argument_list *\ntree_argument_list::dup (symbol_scope& scope) const\n{\n  tree_argument_list *new_list = new tree_argument_list ();\n\n  new_list->m_simple_assign_lhs = m_simple_assign_lhs;\n  new_list->m_list_includes_magic_tilde = m_list_includes_magic_tilde;\n  new_list->m_delims = m_delims;\n\n  for (const tree_expression *elt : *this)\n    new_list->push_back (elt ? elt->dup (scope) : nullptr);\n\n  return new_list;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-arg-list.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_arg_list_h)\n#define octave_pt_arg_list_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n\nclass octave_value;\nclass octave_value_list;\n\n#include \"str-vec.h\"\n\n#include \"pt-delimiter-list.h\"\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\nclass tree_evaluator;\nclass tree_expression;\n\n// Argument lists.  Used to hold the list of expressions that are the\n// arguments in a function call or index expression.\n\nclass OCTINTERP_API tree_argument_list : public std::list<tree_expression *>\n{\npublic:\n\n  typedef tree_expression *element_type;\n\n  tree_argument_list () { }\n\n  tree_argument_list (tree_expression *t) { push_back (t); }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_argument_list)\n\n  ~tree_argument_list ();\n\n  tree_argument_list * mark_in_delims (const token& open_delim, const token& close_delim)\n  {\n    m_delims.push (open_delim, close_delim);\n    return this;\n  }\n\n  filepos beg_pos () const\n  {\n    if (m_delims.empty ())\n      {\n        if (empty ())\n          return filepos ();\n\n        tree_expression *elt = front ();\n        return elt->beg_pos ();\n      }\n\n    return m_delims.beg_pos ();\n  }\n\n  filepos end_pos () const\n  {\n    if (m_delims.empty ())\n      {\n        if (empty ())\n          return filepos ();\n\n        tree_expression *elt = back ();\n        return elt->end_pos ();\n      }\n\n    return m_delims.end_pos ();\n  }\n\n  comment_list leading_comments () const\n  {\n    if (m_delims.empty ())\n      {\n        if (empty ())\n          return comment_list ();\n\n        tree_expression *elt = front ();\n        return elt->leading_comments ();\n      }\n\n    return m_delims.leading_comments ();\n  }\n\n  comment_list trailing_comments () const\n  {\n    if (m_delims.empty ())\n      {\n        if (empty ())\n          return comment_list ();\n\n        tree_expression *elt = back ();\n        return elt->trailing_comments ();\n      }\n\n    return m_delims.trailing_comments ();\n  }\n\n  bool has_magic_tilde () const\n  {\n    return m_list_includes_magic_tilde;\n  }\n\n  bool includes_magic_tilde () const\n  {\n    return m_list_includes_magic_tilde;\n  }\n\n  tree_expression * remove_front ()\n  {\n    auto p = begin ();\n    tree_expression *retval = *p;\n    erase (p);\n    return retval;\n  }\n\n  void push_back (const element_type& s);\n\n  void mark_as_simple_assign_lhs () { m_simple_assign_lhs = true; }\n\n  bool is_simple_assign_lhs () { return m_simple_assign_lhs; }\n\n  tree_delimiter_list delims () const { return m_delims; }\n\n  bool all_elements_are_constant () const;\n\n  bool is_valid_lvalue_list () const;\n\n  string_vector get_arg_names () const;\n\n  std::list<std::string> variable_names () const;\n\n  tree_argument_list * dup (symbol_scope& scope) const;\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_argument_list (*this);\n  }\n\nprivate:\n\n  bool m_list_includes_magic_tilde {false};\n\n  bool m_simple_assign_lhs {false};\n\n  tree_delimiter_list m_delims;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-args-block.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"pt-args-block.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntree_args_block_validation_list::~tree_args_block_validation_list ()\n{\n  while (! empty ())\n    {\n      auto p = begin ();\n      delete *p;\n      erase (p);\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-args-block.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_args_block_h)\n#define octave_pt_args_block_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n\n#include \"pt-arg-list.h\"\n#include \"pt-cmd.h\"\n#include \"pt-exp.h\"\n#include \"pt-id.h\"\n#include \"pt-walk.h\"\n\n// FIXME: We could maybe re-think the naming of some of these objects\n// before releasing a version that contains these new classes...\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass comment_list;\n\nclass OCTINTERP_API tree_arg_size_spec\n{\npublic:\n\n  tree_arg_size_spec (tree_argument_list *size_args)\n    : m_size_args (size_args)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arg_size_spec)\n\n  ~tree_arg_size_spec ()\n  {\n    delete m_size_args;\n  }\n\n  tree_argument_list * size_args () { return m_size_args; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_arg_size_spec (*this);\n  }\n\nprivate:\n\n  tree_argument_list *m_size_args;\n};\n\nclass OCTINTERP_API tree_arg_validation_fcns\n{\npublic:\n\n  tree_arg_validation_fcns (tree_argument_list *fcn_args)\n    : m_fcn_args (fcn_args)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arg_validation_fcns)\n\n  ~tree_arg_validation_fcns ()\n  {\n    delete m_fcn_args;\n  }\n\n  tree_argument_list * fcn_args () { return m_fcn_args; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_arg_validation_fcns (*this);\n  }\n\nprivate:\n\n  tree_argument_list *m_fcn_args;\n};\n\nclass OCTINTERP_API tree_arg_validation\n{\npublic:\n\n  tree_arg_validation (tree_arg_size_spec *size_spec,\n                       tree_identifier *class_name,\n                       tree_arg_validation_fcns *validation_fcns,\n                       const token& eq_tok,\n                       tree_expression *default_value)\n    : m_arg_name (nullptr), m_size_spec (size_spec),\n      m_class_name (class_name), m_validation_fcns (validation_fcns),\n      m_eq_tok (eq_tok), m_default_value (default_value)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arg_validation)\n\n  ~tree_arg_validation ()\n  {\n    delete m_arg_name;\n    delete m_size_spec;\n    delete m_class_name;\n    delete m_validation_fcns;\n    delete m_default_value;\n  }\n\n  void arg_name (tree_expression *name)\n  {\n    m_arg_name = name;\n  }\n\n  tree_expression * identifier_expression () { return m_arg_name; }\n\n  tree_arg_size_spec * size_spec () { return m_size_spec; }\n\n  tree_identifier * class_name () { return m_class_name; }\n\n  tree_arg_validation_fcns *\n  validation_fcns () { return m_validation_fcns; }\n\n  token eq_token () const { return m_eq_tok; }\n\n  tree_expression *\n  initializer_expression () { return m_default_value; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_arg_validation (*this);\n  }\n\nprivate:\n\n  // May be a simple identifier or an identifier followed by a single\n  // field name.\n  tree_expression *m_arg_name;\n  tree_arg_size_spec *m_size_spec;\n  tree_identifier *m_class_name;\n  tree_arg_validation_fcns *m_validation_fcns;\n  token m_eq_tok;\n  tree_expression *m_default_value;\n};\n\nclass OCTINTERP_API tree_args_block_validation_list\n  : public std::list<tree_arg_validation *>\n{\npublic:\n\n  tree_args_block_validation_list () { }\n\n  tree_args_block_validation_list (tree_arg_validation *a) { push_back (a); }\n\n  tree_args_block_validation_list (const std::list<tree_arg_validation *>& a)\n    : std::list<tree_arg_validation *> (a)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_args_block_validation_list)\n\n  ~tree_args_block_validation_list ();\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_args_block_validation_list (*this);\n  }\n};\n\n// FIXME: Maybe make this object an actual list even though we don't\n// currently need it?\n\nclass OCTINTERP_API tree_args_block_attribute_list\n{\npublic:\n\n  tree_args_block_attribute_list (tree_identifier *attr = nullptr)\n    : m_attr (attr)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_args_block_attribute_list)\n\n  ~tree_args_block_attribute_list ()\n  {\n    delete m_attr;\n  }\n\n  tree_identifier * attribute () { return m_attr; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_args_block_attribute_list (*this);\n  }\n\nprivate:\n\n  tree_identifier *m_attr;\n};\n\n// Arguments block.\n\nclass OCTINTERP_API tree_arguments_block : public tree_command\n{\npublic:\n\n  tree_arguments_block (const token& args_tok, tree_args_block_attribute_list *attr_list, tree_args_block_validation_list *validation_list, const token& end_tok)\n    : m_args_tok (args_tok), m_attr_list (attr_list), m_validation_list (validation_list), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arguments_block)\n\n  ~tree_arguments_block ()\n  {\n    delete m_attr_list;\n    delete m_validation_list;\n  }\n\n  filepos beg_pos () const { return m_args_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_args_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  token args_token () const { return m_args_tok; }\n\n  tree_args_block_attribute_list * attribute_list ()\n  {\n    return m_attr_list;\n  }\n\n  tree_args_block_validation_list * validation_list ()\n  {\n    return m_validation_list;\n  }\n\n  token end_token () const { return m_end_tok; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_arguments_block (*this);\n  }\n\nprivate:\n\n  token m_args_tok;\n\n  tree_args_block_attribute_list *m_attr_list;\n\n  tree_args_block_validation_list *m_validation_list;\n\n  token m_end_tok;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-array-list.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"quit.h\"\n\n#include \"error.h\"\n#include \"pt-array-list.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntree_array_list::~tree_array_list ()\n{\n  while (! empty ())\n    {\n      auto p = begin ();\n      delete *p;\n      erase (p);\n    }\n}\n\nbool\ntree_array_list::all_elements_are_constant () const\n{\n  for (const tree_argument_list *elt : *this)\n    {\n      octave_quit ();\n\n      if (! elt->all_elements_are_constant ())\n        return false;\n    }\n\n  return true;\n}\n\nvoid\ntree_array_list::copy_base (const tree_array_list& array_list)\n{\n  tree_expression::copy_base (array_list);\n}\n\nvoid\ntree_array_list::copy_base (const tree_array_list& array_list,\n                            symbol_scope& scope)\n{\n  for (const tree_argument_list *elt : array_list)\n    push_back (elt ? elt->dup (scope) : nullptr);\n\n  copy_base (*this);\n}\n\ntree_expression *\ntree_array_list::dup (symbol_scope&) const\n{\n  error (\"unexpected call to tree_array_list::dup - please report this bug\");\n\n  return nullptr;\n}\n\nvoid\ntree_array_list::accept (tree_walker&)\n{\n  error (\"unexpected call to tree_array_list::accept - please report this bug\");\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-array-list.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_array_list_h)\n#define octave_pt_array_list_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n\n#include \"pt-arg-list.h\"\n#include \"pt-exp.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\nclass tree_walker;\n\n// Base class for cell arrays and matrices.\n\nclass OCTINTERP_API tree_array_list : public tree_expression,\n  public std::list<tree_argument_list *>\n{\npublic:\n\n  typedef std::list<tree_argument_list *>::iterator iterator;\n  typedef std::list<tree_argument_list *>::const_iterator const_iterator;\n\nprotected:\n\n  tree_array_list (tree_argument_list *row = nullptr)\n  {\n    if (row)\n      push_back (row);\n  }\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_array_list)\n\n  ~tree_array_list ();\n\n  // The delimiter list for a cell array should never be empty.  But\n  // better safe than sorry, I guess.\n\n  filepos beg_pos () const { return m_delims.empty () ? filepos () : m_delims.beg_pos (); }\n  filepos end_pos () const { return m_delims.empty () ? filepos () : m_delims.end_pos (); }\n\n  comment_list leading_comments () const { return m_delims.empty () ? comment_list () : m_delims.leading_comments (); }\n  comment_list trailing_comments () const { return m_delims.empty () ? comment_list () : m_delims.trailing_comments (); }\n\n  bool all_elements_are_constant () const;\n\n  // FIXME: should we import the functions from the base class and\n  // overload them here, or should we use a different name so we don't\n  // have to do this?  Without the using declaration or a name change,\n  // the base class functions will be hidden.  That may be OK, but it\n  // can also cause some confusion.\n  using tree_expression::copy_base;\n\n  void copy_base (const tree_array_list& array_list);\n\n  void copy_base (const tree_array_list& array_list,\n                  symbol_scope& scope);\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  void accept (tree_walker& tw);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-assign.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"error.h\"\n#include \"interpreter.h\"\n#include \"oct-lvalue.h\"\n#include \"ov.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-assign.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Simple assignment expressions.\n\ntree_simple_assignment::tree_simple_assignment (tree_expression *le, tree_expression *re, bool plhs, octave_value::assign_op t)\n  : m_lhs (le), m_rhs (re), m_preserve (plhs), m_ans_assign (), m_etype (t)\n{ }\n\ntree_simple_assignment::~tree_simple_assignment ()\n{\n  if (! m_preserve)\n    delete m_lhs;\n\n  delete m_rhs;\n}\n\nstd::string\ntree_simple_assignment::op_str () const\n{\n  return octave_value::assign_op_as_string (m_etype);\n}\n\ntree_expression *\ntree_simple_assignment::dup (symbol_scope& scope) const\n{\n  tree_simple_assignment *new_sa\n    = new tree_simple_assignment (m_lhs ? m_lhs->dup (scope) : nullptr,\n                                  m_rhs ? m_rhs->dup (scope) : nullptr,\n                                  m_preserve, m_etype);\n\n  new_sa->copy_base (*this);\n\n  return new_sa;\n}\n\noctave_value\ntree_simple_assignment::evaluate (tree_evaluator& tw, int)\n{\n  octave_value val;\n\n  if (m_rhs)\n    {\n      try\n        {\n          octave_lvalue ult = m_lhs->lvalue (tw);\n\n          std::list<octave_lvalue> lvalue_list;\n          lvalue_list.push_back (ult);\n\n          unwind_action act ([&tw] (const std::list<octave_lvalue> *lvl)\n          {\n            tw.set_lvalue_list (lvl);\n          }, tw.lvalue_list ());\n          tw.set_lvalue_list (&lvalue_list);\n\n          octave_value rhs_val = m_rhs->evaluate (tw);\n\n          if (rhs_val.is_undefined ())\n            error (\"value on right hand side of assignment is undefined\");\n\n          if (rhs_val.is_cs_list ())\n            {\n              const octave_value_list lst = rhs_val.list_value ();\n\n              if (lst.empty ())\n                error (\"invalid number of elements on RHS of assignment\");\n\n              rhs_val = lst(0);\n            }\n\n          ult.assign (m_etype, rhs_val);\n\n          if (m_etype == octave_value::op_asn_eq)\n            val = rhs_val;\n          else\n            val = ult.value ();\n\n          if (print_result () && tw.statement_printing_enabled ())\n            {\n              // We clear any index here so that we can\n              // get the new value of the referenced\n              // object below, instead of the indexed\n              // value (which should be the same as the\n              // right hand side value).\n\n              ult.clear_index ();\n\n              octave_value lhs_val = ult.value ();\n\n              octave_value_list args = ovl (lhs_val);\n              args.stash_name_tags (string_vector (m_lhs->name ()));\n\n              interpreter& interp = tw.get_interpreter ();\n\n              interp.feval (\"display\", args);\n            }\n        }\n      catch (index_exception& ie)\n        {\n          ie.set_var (m_lhs->name ());\n          std::string msg = ie.message ();\n          error_with_id (ie.err_id (), \"%s\", msg.c_str ());\n        }\n    }\n\n  return val;\n}\n\n// Multi-valued assignment expressions.\n\ntree_multi_assignment::tree_multi_assignment (tree_argument_list *lst, tree_expression *r, bool plhs)\n  : m_lhs (lst), m_rhs (r), m_preserve (plhs)\n{ }\n\ntree_multi_assignment::~tree_multi_assignment ()\n{\n  if (! m_preserve)\n    delete m_lhs;\n\n  delete m_rhs;\n}\n\nstd::string\ntree_multi_assignment::op_str () const\n{\n  return octave_value::assign_op_as_string (op_type ());\n}\n\ntree_expression *\ntree_multi_assignment::dup (symbol_scope&) const\n{\n  error (\"unexpected call to tree_multi_assignment::dup - please report this bug\");\n\n  return nullptr;\n}\n\noctave_value_list\ntree_multi_assignment::evaluate_n (tree_evaluator& tw, int)\n{\n  octave_value_list val;\n\n  if (m_rhs)\n    {\n      std::list<octave_lvalue> lvalue_list = tw.make_lvalue_list (m_lhs);\n\n      unwind_action act ([&tw] (const std::list<octave_lvalue> *lvl)\n      {\n        tw.set_lvalue_list (lvl);\n      }, tw.lvalue_list ());\n      tw.set_lvalue_list (&lvalue_list);\n\n      octave_idx_type n_out = 0;\n\n      for (const auto& lval : lvalue_list)\n        n_out += lval.numel ();\n\n      // The following trick is used to keep rhs_val constant.\n      const octave_value_list rhs_val1 = m_rhs->evaluate_n (tw, n_out);\n      const octave_value_list rhs_val = (rhs_val1.length () == 1\n                                         && rhs_val1(0).is_cs_list ()\n                                         ? rhs_val1(0).list_value ()\n                                         : rhs_val1);\n\n      octave_idx_type k = 0;\n\n      octave_idx_type n = rhs_val.length ();\n\n      // To avoid copying per elements and possible optimizations, we\n      // postpone joining the final values.\n      std::list<octave_value_list> retval_list;\n\n      auto q = m_lhs->begin ();\n\n      for (octave_lvalue ult : lvalue_list)\n        {\n          tree_expression *lhs_elt = *q++;\n\n          octave_idx_type nel = ult.numel ();\n\n          if (nel != 1)\n            {\n              // Huge kluge so that wrapper scripts with lines like\n              //\n              //   [varargout{1:nargout}] = fcn (args);\n              //\n              // or\n              //\n              //   varargout = cell (1, nargout);\n              //   [varargout{1:nargout}] = fcn (args);\n              //\n              // or\n              //\n              //   varargout = cell (1, nargout);\n              //   [varargout{:}] = fcn (args);\n              //\n              // Will work the same as calling fcn directly when nargout\n              // is 0 and fcn produces more than one output even when\n              // nargout is 0.  See also bug #43813.\n\n              if (lvalue_list.size () == 1 && nel == 0 && n > 0\n                  && ! ult.is_black_hole () && ult.index_type () == \"{\"\n                  && (ult.index_is_empty ()\n                      || (ult.is_defined () && ult.index_is_colon ())))\n                {\n                  // Convert undefined lvalue with empty index to a cell\n                  // array with a single value and indexed by 1 to\n                  // handle a single output.\n\n                  nel = 1;\n\n                  ult.define (Cell (1, 1));\n\n                  ult.clear_index ();\n                  std::list<octave_value_list> idx;\n                  idx.push_back (octave_value_list (octave_value (1)));\n                  ult.set_index (\"{\", idx);\n                }\n\n              if (k + nel > n)\n                error (\"some elements undefined in return list\");\n\n              // This element of the return list expects a\n              // comma-separated list of values.  Slicing avoids\n              // copying.\n\n              octave_value_list ovl = rhs_val.slice (k, nel);\n\n              ult.assign (octave_value::op_asn_eq, octave_value (ovl));\n\n              retval_list.push_back (ovl);\n\n              k += nel;\n            }\n          else\n            {\n              if (k < n)\n                {\n                  if (ult.is_black_hole ())\n                    {\n                      k++;\n                      continue;\n                    }\n                  else\n                    {\n                      octave_value tmp = rhs_val(k);\n\n                      if (tmp.is_undefined ())\n                        error (\"element number %\" OCTAVE_IDX_TYPE_FORMAT\n                               \" undefined in return list\", k+1);\n\n                      ult.assign (octave_value::op_asn_eq, tmp);\n\n                      retval_list.push_back (tmp);\n\n                      k++;\n                    }\n                }\n              else\n                {\n                  // This can happen for a function like\n                  //\n                  //   function varargout = f ()\n                  //     varargout{1} = nargout;\n                  //   endfunction\n                  //\n                  // called with\n                  //\n                  //    [a, ~] = f ();\n                  //\n                  // Then the list of RHS values will contain one\n                  // element but we are iterating over the list of all\n                  // RHS values.  We shouldn't complain that a value we\n                  // don't need is missing from the list.\n\n                  if (! ult.is_black_hole ())\n                    error (\"element number %\" OCTAVE_IDX_TYPE_FORMAT\n                           \" undefined in return list\", k+1);\n\n                  k++;\n                  continue;\n                }\n            }\n\n          if (print_result () && tw.statement_printing_enabled ())\n            {\n              // We clear any index here so that we can get\n              // the new value of the referenced object below,\n              // instead of the indexed value (which should be\n              // the same as the right hand side value).\n\n              ult.clear_index ();\n\n              octave_value lhs_val = ult.value ();\n\n              octave_value_list args = ovl (lhs_val);\n              args.stash_name_tags (string_vector (lhs_elt->name ()));\n\n              interpreter& interp = tw.get_interpreter ();\n\n              interp.feval (\"display\", args);\n            }\n        }\n\n      // Concatenate return values.\n      val = retval_list;\n    }\n\n  return val;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n/*\n%!function varargout = f1 ()\n%!  varargout{1} = nargout;\n%!endfunction\n%!\n%!test\n%! [a, ~] = f1 ();\n%! assert (a, 2);\n%!test\n%! [a, ~, ~, ~, ~] = f1 ();\n%! assert (a, 5);\n\n%!function [x, y] = f2 ()\n%!  y = 1;\n%!endfunction\n%!\n%!test\n%! [~, y] = f2 ();\n%! assert (y, 1);\n\n%!function [x, y, varargout] = f3 ()\n%!  y = 1;\n%!  varargout = {2, 3};\n%!endfunction\n%!\n%!test\n%! [~, y, a, b] = f3 ();\n%! assert ([y, a, b], [1, 2, 3]);\n%!test\n%! [~, y, ~, b] = f3 ();\n%! assert ([y, b], [1, 3]);\n*/\n"
  },
  {
    "path": "libinterp/parse-tree/pt-assign.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_assign_h)\n#define octave_pt_assign_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\n\n#include \"comment-list.h\"\n#include \"ov.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\nclass octave_lvalue;\nclass tree_argument_list;\n\n// Simple assignment expressions.\n\nclass OCTINTERP_API tree_simple_assignment : public tree_expression\n{\npublic:\n\n  tree_simple_assignment (tree_expression *le, tree_expression *re, bool plhs = false, octave_value::assign_op t = octave_value::op_asn_eq);\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_simple_assignment)\n\n  ~tree_simple_assignment ();\n\n  filepos beg_pos () const { return m_lhs->beg_pos (); }\n  filepos end_pos () const { return m_rhs->end_pos (); }\n\n  comment_list leading_comments () const { return m_lhs->leading_comments (); }\n  comment_list trailing_comments () const { return m_rhs->trailing_comments (); }\n\n  bool rvalue_ok () const { return true; }\n\n  bool is_assignment_expression () const { return true; }\n\n  OCTAVE_DEPRECATED (11, \"use tree_simple_assignment::op_str instead\")\n  std::string oper () const { return op_str (); }\n\n  std::string op_str () const;\n\n  tree_expression * left_hand_side () { return m_lhs; }\n\n  tree_expression * right_hand_side () { return m_rhs; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator& tw, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_simple_assignment (*this);\n  }\n\n  octave_value::assign_op op_type () const { return m_etype; }\n\nprivate:\n\n  void do_assign (octave_lvalue& ult, const octave_value_list& args,\n                  const octave_value& rhs_val);\n\n  void do_assign (octave_lvalue& ult, const octave_value& rhs_val);\n\n  // The left hand side of the assignment.\n  tree_expression *m_lhs;\n\n  // The right hand side of the assignment.\n  tree_expression *m_rhs;\n\n  // True if we should not delete the lhs.\n  bool m_preserve;\n\n  // True if this is an assignment to the automatic variable ans.\n  bool m_ans_assign;\n\n  // The type of the expression.\n  octave_value::assign_op m_etype;\n};\n\n// Multi-valued assignment expressions.\n\nclass OCTINTERP_API tree_multi_assignment : public tree_expression\n{\npublic:\n\n  tree_multi_assignment (bool plhs = false)\n    : m_lhs (nullptr), m_rhs (nullptr), m_preserve (plhs)\n  { }\n\n  tree_multi_assignment (tree_argument_list *lst, tree_expression *r, bool plhs = false);\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_multi_assignment)\n\n  ~tree_multi_assignment ();\n\n  bool is_assignment_expression () const { return true; }\n\n  filepos beg_pos () const { return m_lhs->beg_pos (); }\n  filepos end_pos () const { return m_rhs->end_pos (); }\n\n  comment_list leading_comments () const { return m_lhs->leading_comments (); }\n  comment_list trailing_comments () const { return m_rhs->trailing_comments (); }\n\n  bool rvalue_ok () const { return true; }\n\n  OCTAVE_DEPRECATED (11, \"use tree_multi_assignment::op_str instead\")\n  std::string oper () const { return op_str (); }\n\n  std::string op_str () const;\n\n  tree_argument_list * left_hand_side () { return m_lhs; }\n\n  tree_expression * right_hand_side () { return m_rhs; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator& tw, int nargout = 1)\n  {\n    octave_value_list retval = evaluate_n (tw, nargout);\n\n    return retval.length () > 0 ? retval(0) : octave_value ();\n  }\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1);\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_multi_assignment (*this);\n  }\n\n  octave_value::assign_op op_type () const\n  {\n    return octave_value::op_asn_eq;\n  }\n\nprivate:\n\n  // The left hand side of the assignment.\n  tree_argument_list *m_lhs;\n\n  // The right hand side of the assignment.\n  tree_expression *m_rhs;\n\n  // True if we should not delete the lhs.\n  bool m_preserve;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-binop.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"interpreter.h\"\n#include \"ov.h\"\n#include \"profiler.h\"\n#include \"pt-binop.h\"\n#include \"pt-eval.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Binary expressions.\n\nvoid\ntree_binary_expression::matlab_style_short_circuit_warning (const char *op)\n{\n  warning_with_id (\"Octave:possible-matlab-short-circuit-operator\",\n                   \"Matlab-style short-circuit operation performed for operator %s\",\n                   op);\n}\n\nstd::string\ntree_binary_expression::op_str () const\n{\n  return octave_value::binary_op_as_string (m_etype);\n}\n\ntree_expression *\ntree_binary_expression::dup (symbol_scope& scope) const\n{\n  tree_binary_expression *new_be\n    = new tree_binary_expression (m_lhs ? m_lhs->dup (scope) : nullptr,\n                                  m_op_tok,\n                                  m_rhs ? m_rhs->dup (scope) : nullptr,\n                                  m_etype);\n\n  new_be->copy_base (*this);\n\n  return new_be;\n}\n\noctave_value\ntree_binary_expression::evaluate (tree_evaluator& tw, int)\n{\n  if (m_lhs)\n    {\n      // Evaluate with unknown number of output arguments\n      octave_value a = m_lhs->evaluate (tw, -1);\n\n      if (a.is_defined () && m_rhs)\n        {\n          // Evaluate with unknown number of output arguments\n          octave_value b = m_rhs->evaluate (tw, -1);\n\n          if (b.is_defined ())\n            {\n              profiler::enter<tree_binary_expression>\n              block (tw.get_profiler (), *this);\n\n              // Note: The profiler does not catch the braindead\n              // short-circuit evaluation code above, but that should be\n              // ok.  The evaluation of operands and the operator itself\n              // is entangled and it's not clear where to start/stop\n              // timing the operator to make it reasonable.\n\n              interpreter& interp = tw.get_interpreter ();\n\n              type_info& ti = interp.get_type_info ();\n\n              return binary_op (ti, m_etype, a, b);\n            }\n        }\n    }\n\n  return octave_value ();\n}\n\ntree_expression *\ntree_braindead_shortcircuit_binary_expression::dup (symbol_scope& scope) const\n{\n  tree_braindead_shortcircuit_binary_expression *new_be\n    = new tree_braindead_shortcircuit_binary_expression\n  (m_lhs ? m_lhs->dup (scope) : nullptr,\n   m_op_tok,\n   m_rhs ? m_rhs->dup (scope) : nullptr,\n   op_type ());\n\n  new_be->copy_base (*this);\n\n  return new_be;\n}\n\noctave_value\ntree_braindead_shortcircuit_binary_expression::evaluate (tree_evaluator& tw, int)\n{\n  if (m_lhs)\n    {\n      octave_value a = m_lhs->evaluate (tw);\n\n      if (a.ndims () == 2 && a.rows () == 1 && a.columns () == 1)\n        {\n          bool result = false;\n\n          bool a_true = a.is_true ();\n\n          octave_value::binary_op oper_type = op_type ();\n\n          if (a_true)\n            {\n              if (oper_type == octave_value::op_el_or)\n                {\n                  matlab_style_short_circuit_warning (\"|\");\n                  return octave_value (true);\n                }\n            }\n          else\n            {\n              if (oper_type == octave_value::op_el_and)\n                {\n                  matlab_style_short_circuit_warning (\"&\");\n                  return octave_value (false);\n                }\n            }\n\n          if (m_rhs)\n            {\n              octave_value b = m_rhs->evaluate (tw);\n\n              result = b.is_true ();\n            }\n\n          return octave_value (result);\n        }\n      else\n        return tree_binary_expression::evaluate (tw);\n    }\n\n  return octave_value ();\n}\n\n// Boolean expressions.\n\nstd::string\ntree_boolean_expression::op_str () const\n{\n  std::string retval = \"<unknown>\";\n\n  switch (m_etype)\n    {\n    case bool_and:\n      retval = \"&&\";\n      break;\n\n    case bool_or:\n      retval = \"||\";\n      break;\n\n    default:\n      break;\n    }\n\n  return retval;\n}\n\ntree_expression *\ntree_boolean_expression::dup (symbol_scope& scope) const\n{\n  tree_boolean_expression *new_be\n    = new tree_boolean_expression (m_lhs ? m_lhs->dup (scope) : nullptr,\n                                   m_op_tok,\n                                   m_rhs ? m_rhs->dup (scope) : nullptr,\n                                   m_etype);\n\n  new_be->copy_base (*this);\n\n  return new_be;\n}\n\noctave_value\ntree_boolean_expression::evaluate (tree_evaluator& tw, int)\n{\n  octave_value val;\n\n  bool result = false;\n\n  // This evaluation is not caught by the profiler, since we can't find\n  // a reasonable place where to time.  Note that we don't want to\n  // include evaluation of LHS or RHS into the timing, but this is\n  // entangled together with short-circuit evaluation here.\n\n  if (m_lhs)\n    {\n      octave_value a = m_lhs->evaluate (tw);\n\n      bool a_true = a.is_true ();\n\n      if (a_true)\n        {\n          if (m_etype == tree_boolean_expression::bool_or)\n            return octave_value (true);\n        }\n      else\n        {\n          if (m_etype == tree_boolean_expression::bool_and)\n            return octave_value (false);\n        }\n\n      if (m_rhs)\n        {\n          octave_value b = m_rhs->evaluate (tw);\n\n          result = b.is_true ();\n        }\n\n      val = octave_value (result);\n    }\n\n  return val;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-binop.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_binop_h)\n#define octave_pt_binop_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\n\n#include \"ov.h\"\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\n\n// Binary expressions.\n\nclass OCTINTERP_API tree_binary_expression : public tree_expression\n{\npublic:\n\n  tree_binary_expression (octave_value::binary_op t = octave_value::unknown_binary_op)\n    : m_lhs (nullptr), m_rhs (nullptr), m_etype (t), m_preserve_operands (false)\n  { }\n\n  tree_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t = octave_value::unknown_binary_op)\n    : m_lhs (a), m_op_tok (op_tok), m_rhs (b), m_etype (t), m_preserve_operands (false)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_binary_expression)\n\n  ~tree_binary_expression ()\n  {\n    if (! m_preserve_operands)\n      {\n        delete m_lhs;\n        delete m_rhs;\n      }\n  }\n\n  void preserve_operands () { m_preserve_operands = true; }\n\n  bool is_binary_expression () const { return true; }\n\n  filepos beg_pos () const { return m_lhs->beg_pos (); }\n  filepos end_pos () const { return m_rhs->end_pos (); }\n\n  comment_list leading_comments () const { return m_lhs->leading_comments (); }\n  comment_list trailing_comments () const { return m_rhs->trailing_comments (); }\n\n  bool rvalue_ok () const { return true; }\n\n  OCTAVE_DEPRECATED (11, \"use tree_binary_expression::op_str instead\")\n  std::string oper () const { return op_str (); }\n\n  std::string op_str () const;\n\n  octave_value::binary_op op_type () const { return m_etype; }\n\n  tree_expression * lhs () { return m_lhs; }\n\n  token op_token () const { return m_op_tok; }\n\n  tree_expression * rhs () { return m_rhs; }\n\n  void lhs (tree_expression *expr) { m_lhs = expr; }\n  void rhs (tree_expression *expr) { m_rhs = expr; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_binary_expression (*this);\n  }\n\n  std::string profiler_name () const { return \"binary \" + op_str (); }\n\n  void matlab_style_short_circuit_warning (const char *op);\n\n  virtual bool is_braindead () const { return false; }\n\nprotected:\n\n  // The operands and operator for the expression.\n  tree_expression *m_lhs;\n\n  token m_op_tok;\n\n  tree_expression *m_rhs;\n\nprivate:\n\n  // The type of the expression.\n  octave_value::binary_op m_etype;\n\n  // If TRUE, don't delete m_lhs and m_rhs in destructor;\n  bool m_preserve_operands;\n};\n\nclass OCTINTERP_API tree_braindead_shortcircuit_binary_expression\n  : public tree_binary_expression\n{\npublic:\n\n  tree_braindead_shortcircuit_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t)\n    : tree_binary_expression (a, op_tok, b, t)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_braindead_shortcircuit_binary_expression)\n\n  ~tree_braindead_shortcircuit_binary_expression () = default;\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  using tree_binary_expression::evaluate_n;\n\n  bool is_braindead () const { return true; }\n};\n\n// Boolean expressions.\n\nclass OCTINTERP_API tree_boolean_expression : public tree_binary_expression\n{\npublic:\n\n  enum type\n  {\n    unknown,\n    bool_and,\n    bool_or\n  };\n\n  tree_boolean_expression (type t = unknown) : m_etype (t) { }\n\n  tree_boolean_expression (tree_expression *a, const token& op_tok, tree_expression *b, type t = unknown)\n    : tree_binary_expression (a, op_tok, b), m_etype (t)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_boolean_expression)\n\n  ~tree_boolean_expression () = default;\n\n  bool is_boolean_expression () const { return true; }\n\n  bool rvalue_ok () const { return true; }\n\n  OCTAVE_DEPRECATED (11, \"use tree_binary_expression::op_str instead\")\n  std::string oper () const { return op_str (); }\n\n  std::string op_str () const;\n\n  type op_type () const { return m_etype; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_boolean_expression (*this);\n  }\n\nprivate:\n\n  // The type of the expression.\n  type m_etype;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-bp.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"pt-all.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_NORETURN static void\nerror_unexpected (const char *name)\n{\n  error (\"unexpected call to %s - please report this bug\", name);\n}\n\nvoid\ntree_breakpoint::visit_while_command (tree_while_command& cmd)\n{\n  if (cmd.line () >= m_line)\n    take_action (cmd);\n\n  if (! m_found)\n    {\n      tree_statement_list *lst = cmd.body ();\n\n      if (lst)\n        lst->accept (*this);\n    }\n}\n\nvoid\ntree_breakpoint::visit_do_until_command (tree_do_until_command& cmd)\n{\n  if (! m_found)\n    {\n      tree_statement_list *lst = cmd.body ();\n\n      if (lst)\n        lst->accept (*this);\n\n      if (! m_found)\n        {\n          if (cmd.line () >= m_line)\n            take_action (cmd);\n        }\n    }\n}\n\nvoid\ntree_breakpoint::visit_argument_list (tree_argument_list&)\n{\n  error_unexpected (\"tree_breakpoint::visit_argument_list\");\n}\n\nvoid\ntree_breakpoint::visit_arguments_block (tree_arguments_block&)\n{\n  // FIXME\n}\n\nvoid\ntree_breakpoint::visit_args_block_attribute_list (tree_args_block_attribute_list&)\n{\n  error_unexpected (\"tree_breakpoint::visit_args_block_attribute_list\");\n}\n\nvoid\ntree_breakpoint::visit_args_block_validation_list (tree_args_block_validation_list&)\n{\n  error_unexpected (\"tree_breakpoint::visit_args_block_validation_list\");\n}\n\nvoid\ntree_breakpoint::visit_arg_validation (tree_arg_validation&)\n{\n  error_unexpected (\"tree_breakpoint::visit_arg_validation\");\n}\n\nvoid\ntree_breakpoint::visit_arg_size_spec (tree_arg_size_spec&)\n{\n  error_unexpected (\"tree_breakpoint::visit_arg_size_spec\");\n}\n\nvoid\ntree_breakpoint::visit_arg_validation_fcns (tree_arg_validation_fcns&)\n{\n  error_unexpected (\"tree_breakpoint::visit_arg_validation_fcns\");\n}\n\nvoid\ntree_breakpoint::visit_binary_expression (tree_binary_expression&)\n{\n  error_unexpected (\"tree_breakpoint::visit_binary_expression\");\n}\n\nvoid\ntree_breakpoint::visit_break_command (tree_break_command& cmd)\n{\n  if (cmd.line () >= m_line)\n    take_action (cmd);\n}\n\nvoid\ntree_breakpoint::visit_colon_expression (tree_colon_expression&)\n{\n  error_unexpected (\"tree_breakpoint::visit_colon_expression\");\n}\n\nvoid\ntree_breakpoint::visit_continue_command (tree_continue_command& cmd)\n{\n  if (cmd.line () >= m_line)\n    take_action (cmd);\n}\n\nvoid\ntree_breakpoint::visit_decl_command (tree_decl_command& cmd)\n{\n  if (cmd.line () >= m_line)\n    take_action (cmd);\n}\n\nvoid\ntree_breakpoint::visit_decl_init_list (tree_decl_init_list&)\n{\n  error_unexpected (\"tree_breakpoint::visit_decl_init_list\");\n}\n\nvoid\ntree_breakpoint::visit_decl_elt (tree_decl_elt&)\n{\n  error_unexpected (\"tree_breakpoint::visit_decl_elt\");\n}\n\nvoid\ntree_breakpoint::visit_simple_for_command (tree_simple_for_command& cmd)\n{\n  if (cmd.line () >= m_line)\n    take_action (cmd);\n\n  if (! m_found)\n    {\n      tree_statement_list *lst = cmd.body ();\n\n      if (lst)\n        lst->accept (*this);\n    }\n}\n\nvoid\ntree_breakpoint::visit_complex_for_command (tree_complex_for_command& cmd)\n{\n  if (cmd.line () >= m_line)\n    take_action (cmd);\n\n  if (! m_found)\n    {\n      tree_statement_list *lst = cmd.body ();\n\n      if (lst)\n        lst->accept (*this);\n    }\n}\n\nvoid\ntree_breakpoint::visit_octave_user_function_header (octave_user_function&)\n{\n  error_unexpected (\"tree_breakpoint::visit_octave_user_function_header\");\n}\n\nvoid\ntree_breakpoint::visit_octave_user_function_trailer (octave_user_function&)\n{\n  error_unexpected (\"tree_breakpoint::visit_octave_user_function_trailer\");\n}\n\nvoid\ntree_breakpoint::visit_identifier (tree_identifier&)\n{\n  error_unexpected (\"tree_breakpoint::visit_identifier\");\n}\n\nvoid\ntree_breakpoint::visit_if_clause (tree_if_clause&)\n{\n  error_unexpected (\"tree_breakpoint::visit_if_clause\");\n}\n\nvoid\ntree_breakpoint::visit_if_command_list (tree_if_command_list& lst)\n{\n  for (tree_if_clause *t : lst)\n    {\n      if (t->line () >= m_line)\n        take_action (*t);\n\n      if (! m_found)\n        {\n          tree_statement_list *stmt_lst = t->commands ();\n\n          if (stmt_lst)\n            stmt_lst->accept (*this);\n        }\n\n      if (m_found)\n        break;\n    }\n}\n\nvoid\ntree_breakpoint::visit_index_expression (tree_index_expression&)\n{\n  error_unexpected (\"tree_breakpoint::visit_index_expression\");\n}\n\nvoid\ntree_breakpoint::visit_matrix (tree_matrix&)\n{\n  error_unexpected (\"tree_breakpoint::visit_matrix\");\n}\n\nvoid\ntree_breakpoint::visit_cell (tree_cell&)\n{\n  error_unexpected (\"tree_breakpoint::visit_cell\");\n}\n\nvoid\ntree_breakpoint::visit_multi_assignment (tree_multi_assignment&)\n{\n  error_unexpected (\"tree_breakpoint::visit_multi_assignment\");\n}\n\nvoid\ntree_breakpoint::visit_no_op_command (tree_no_op_command& cmd)\n{\n  if (cmd.is_end_of_fcn_or_script () && cmd.line () >= m_line)\n    take_action (cmd);\n}\n\nvoid\ntree_breakpoint::visit_anon_fcn_handle (tree_anon_fcn_handle&)\n{\n  error_unexpected (\"tree_breakpoint::visit_anon_fcn_handle\");\n}\n\nvoid\ntree_breakpoint::visit_constant (tree_constant&)\n{\n  error_unexpected (\"tree_breakpoint::visit_constant\");\n}\n\nvoid\ntree_breakpoint::visit_fcn_handle (tree_fcn_handle&)\n{\n  error_unexpected (\"tree_breakpoint::visit_fcn_handle\");\n}\n\nvoid\ntree_breakpoint::visit_parameter_list (tree_parameter_list&)\n{\n  error_unexpected (\"tree_breakpoint::visit_parameter_list\");\n}\n\nvoid\ntree_breakpoint::visit_postfix_expression (tree_postfix_expression&)\n{\n  error_unexpected (\"tree_breakpoint::visit_postfix_expression\");\n}\n\nvoid\ntree_breakpoint::visit_prefix_expression (tree_prefix_expression&)\n{\n  error_unexpected (\"tree_breakpoint::visit_prefix_expression\");\n}\n\nvoid\ntree_breakpoint::visit_return_command (tree_return_command& cmd)\n{\n  if (cmd.line () >= m_line)\n    take_action (cmd);\n}\n\nvoid\ntree_breakpoint::visit_simple_assignment (tree_simple_assignment&)\n{\n  error_unexpected (\"tree_breakpoint::visit_simple_assignment\");\n}\n\nvoid\ntree_breakpoint::visit_statement (tree_statement& stmt)\n{\n  if (stmt.is_command ())\n    {\n      tree_command *cmd = stmt.command ();\n\n      cmd->accept (*this);\n    }\n  else\n    {\n      if (stmt.line () >= m_line)\n        take_action (stmt);\n    }\n}\n\n// Called by\n//   tree_statement_list::set_breakpoint (int line, std::string& condition)\n// with <lst> consisting of a user function in which to set a breakpoint.\nvoid\ntree_breakpoint::visit_statement_list (tree_statement_list& lst)\n{\n  for (tree_statement *elt : lst)\n    {\n      if (elt)\n        {\n          elt->accept (*this);\n\n          if (m_found)\n            break;\n        }\n    }\n}\n\nvoid\ntree_breakpoint::visit_switch_case (tree_switch_case&)\n{\n  error_unexpected (\"tree_breakpoint::visit_switch_case\");\n}\n\nvoid\ntree_breakpoint::visit_switch_case_list (tree_switch_case_list& lst)\n{\n  for (tree_switch_case *t : lst)\n    {\n      if (t->line () >= m_line)\n        take_action (*t);\n\n      if (! m_found)\n        {\n          tree_statement_list *stmt_lst = t->commands ();\n\n          if (stmt_lst)\n            stmt_lst->accept (*this);\n        }\n\n      if (m_found)\n        break;\n    }\n}\n\nvoid\ntree_breakpoint::visit_switch_command (tree_switch_command& cmd)\n{\n  if (cmd.line () >= m_line)\n    take_action (cmd);\n\n  if (! m_found)\n    {\n      tree_switch_case_list *lst = cmd.case_list ();\n\n      if (lst)\n        lst->accept (*this);\n    }\n}\n\nvoid\ntree_breakpoint::visit_try_catch_command (tree_try_catch_command& cmd)\n{\n  tree_statement_list *try_code = cmd.body ();\n\n  if (try_code)\n    try_code->accept (*this);\n\n  if (! m_found)\n    {\n      tree_statement_list *catch_code = cmd.cleanup ();\n\n      if (catch_code)\n        catch_code->accept (*this);\n    }\n}\n\nvoid\ntree_breakpoint::visit_unwind_protect_command (tree_unwind_protect_command& cmd)\n{\n  tree_statement_list *body = cmd.body ();\n\n  if (body)\n    body->accept (*this);\n\n  if (! m_found)\n    {\n      tree_statement_list *cleanup = cmd.cleanup ();\n\n      if (cleanup)\n        cleanup->accept (*this);\n    }\n}\n\nvoid\ntree_breakpoint::take_action (tree& tr)\n{\n  switch (m_action)\n    {\n    case set:\n      tr.set_breakpoint (m_condition);\n      m_line = tr.line ();\n      m_found = true;\n      break;\n\n    case clear:\n      if (tr.is_breakpoint ())\n        {\n          tr.delete_breakpoint ();\n          m_found = true;\n        }\n      break;\n\n    case list:\n      if (tr.is_breakpoint ())\n        {\n          m_bp_list.append (octave_value (tr.line ()));\n          m_bp_cond_list.append (octave_value (tr.bp_cond ()));\n        }\n      break;\n\n      // We should have handled all possible enum values above.  Rely on\n      // compiler diagnostics to warn if we haven't.  For example, GCC's\n      // -Wswitch option, enabled by -Wall, will provide a warning.\n    }\n}\n\nvoid\ntree_breakpoint::take_action (tree_statement& stmt)\n{\n  int lineno = stmt.line ();\n\n  switch (m_action)\n    {\n    case set:\n      stmt.set_breakpoint (m_condition);\n      m_line = lineno;\n      m_found = true;\n      break;\n\n    case clear:\n      if (stmt.is_breakpoint ())\n        {\n          stmt.delete_breakpoint ();\n          m_found = true;\n        }\n      break;\n\n    case list:\n      if (stmt.is_breakpoint ())\n        {\n          m_bp_list.append (octave_value (lineno));\n          m_bp_cond_list.append (octave_value (stmt.bp_cond ()));\n        }\n      break;\n\n      // We should have handled all possible enum values above.  Rely on\n      // compiler diagnostics to warn if we haven't.  For example, GCC's\n      // -Wswitch option, enabled by -Wall, will provide a warning.\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-bp.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_bp_h)\n#define octave_pt_bp_h 1\n\n#include \"octave-config.h\"\n\n#include \"input.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pt-walk.h\"\n#include \"pt-pr-code.h\"\n#include \"interpreter.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree;\nclass tree_decl_command;\n\nclass OCTINTERP_API tree_breakpoint : public tree_walker\n{\npublic:\n\n  enum action { set = 1, clear = 2, list = 3 };\n\n  tree_breakpoint (int l, action a, const std::string& c = \"\")\n    : m_line (l), m_action (a), m_condition (c), m_found (false),\n      m_bp_list (), m_bp_cond_list ()\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_breakpoint)\n\n  ~tree_breakpoint () = default;\n\n  bool success () const { return m_found; }\n\n  void visit_argument_list (tree_argument_list&);\n\n  void visit_arguments_block (tree_arguments_block&);\n\n  void visit_args_block_attribute_list (tree_args_block_attribute_list&);\n\n  void visit_args_block_validation_list (tree_args_block_validation_list&);\n\n  void visit_arg_validation (tree_arg_validation&);\n\n  void visit_arg_size_spec (tree_arg_size_spec&);\n\n  void visit_arg_validation_fcns (tree_arg_validation_fcns&);\n\n  void visit_binary_expression (tree_binary_expression&);\n\n  void visit_break_command (tree_break_command&);\n\n  void visit_colon_expression (tree_colon_expression&);\n\n  void visit_continue_command (tree_continue_command&);\n\n  void visit_decl_command (tree_decl_command&);\n\n  void visit_decl_init_list (tree_decl_init_list&);\n\n  void visit_decl_elt (tree_decl_elt&);\n\n  void visit_while_command (tree_while_command&);\n\n  void visit_do_until_command (tree_do_until_command&);\n\n  void visit_simple_for_command (tree_simple_for_command&);\n\n  void visit_complex_for_command (tree_complex_for_command&);\n\n  void visit_octave_user_function_header (octave_user_function&);\n\n  void visit_octave_user_function_trailer (octave_user_function&);\n\n\n  void visit_identifier (tree_identifier&);\n\n  void visit_if_clause (tree_if_clause&);\n\n  void visit_if_command_list (tree_if_command_list&);\n\n  void visit_index_expression (tree_index_expression&);\n\n  void visit_matrix (tree_matrix&);\n\n  void visit_cell (tree_cell&);\n\n  void visit_multi_assignment (tree_multi_assignment&);\n\n  void visit_no_op_command (tree_no_op_command&);\n\n  void visit_anon_fcn_handle (tree_anon_fcn_handle&);\n\n  void visit_constant (tree_constant&);\n\n  void visit_fcn_handle (tree_fcn_handle&);\n\n  void visit_parameter_list (tree_parameter_list&);\n\n  void visit_postfix_expression (tree_postfix_expression&);\n\n  void visit_prefix_expression (tree_prefix_expression&);\n\n  void visit_return_command (tree_return_command&);\n\n  void visit_simple_assignment (tree_simple_assignment&);\n\n  void visit_statement (tree_statement&);\n\n  void visit_statement_list (tree_statement_list&);\n\n  void visit_switch_case (tree_switch_case&);\n\n  void visit_switch_case_list (tree_switch_case_list&);\n\n  void visit_switch_command (tree_switch_command&);\n\n  void visit_try_catch_command (tree_try_catch_command&);\n\n  void visit_unwind_protect_command (tree_unwind_protect_command&);\n\n  octave_value_list get_list () { return m_bp_list; }\n\n  octave_value_list get_cond_list () { return m_bp_cond_list; }\n\n  int get_line () { return m_found ? m_line : 0; }\n\nprivate:\n\n  void take_action (tree& tr);\n\n  void take_action (tree_statement& stmt);\n\n  //--------\n\n  // Statement line number we are looking for.\n  int m_line;\n\n  // What to do.\n  action m_action;\n\n  // Expression which must be true to break\n  std::string m_condition;\n\n  // Have we already found the line?\n  bool m_found;\n\n  // List of breakpoint line numbers.\n  octave_value_list m_bp_list;\n\n  // List of breakpoint conditions.\n  octave_value_list m_bp_cond_list;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-cbinop.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"interpreter.h\"\n#include \"ov.h\"\n#include \"pt-cbinop.h\"\n#include \"pt-eval.h\"\n#include \"pt-unop.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\noctave_value\ntree_compound_binary_expression::evaluate (tree_evaluator& tw, int)\n{\n  octave_value val;\n\n  if (m_lhs)\n    {\n      // Evaluate with unknown number of output arguments\n      octave_value a = m_lhs->evaluate (tw, -1);\n\n      if (a.is_defined () && m_rhs)\n        {\n          // Evaluate with unknown number of output arguments\n          octave_value b = m_rhs->evaluate (tw, -1);\n\n          if (b.is_defined ())\n            {\n              interpreter& interp = tw.get_interpreter ();\n\n              type_info& ti = interp.get_type_info ();\n\n              val = binary_op (ti, m_etype, a, b);\n            }\n        }\n    }\n\n  return val;\n}\n\ntypedef tree_expression *tree_expression_ptr_t;\n\n// If a tree expression is a transpose or hermitian transpose, return\n// the argument and corresponding operator.\n\nstatic octave_value::unary_op\nstrip_trans_herm (tree_expression_ptr_t& exp)\n{\n  if (exp->is_unary_expression ())\n    {\n      tree_unary_expression *uexp\n        = dynamic_cast<tree_unary_expression *> (exp);\n\n      octave_value::unary_op op = uexp->op_type ();\n\n      if (op == octave_value::op_transpose\n          || op == octave_value::op_hermitian)\n        exp = uexp->operand ();\n      else\n        op = octave_value::unknown_unary_op;\n\n      return op;\n    }\n  else\n    return octave_value::unknown_unary_op;\n}\n\n// Possibly convert multiplication to trans_mul, mul_trans, herm_mul,\n// or mul_herm.\n\nstatic octave_value::compound_binary_op\nsimplify_mul_op (tree_expression_ptr_t& a, tree_expression_ptr_t& b)\n{\n  octave_value::compound_binary_op retop\n    = octave_value::unknown_compound_binary_op;\n\n  octave_value::unary_op opa = strip_trans_herm (a);\n\n  if (opa == octave_value::op_hermitian)\n    retop = octave_value::op_herm_mul;\n  else if (opa == octave_value::op_transpose)\n    retop = octave_value::op_trans_mul;\n  else\n    {\n      octave_value::unary_op opb = strip_trans_herm (b);\n\n      if (opb == octave_value::op_hermitian)\n        retop = octave_value::op_mul_herm;\n      else if (opb == octave_value::op_transpose)\n        retop = octave_value::op_mul_trans;\n    }\n\n  return retop;\n}\n\n// Possibly convert left division to trans_ldiv or herm_ldiv.\n\nstatic octave_value::compound_binary_op\nsimplify_ldiv_op (tree_expression_ptr_t& a, tree_expression_ptr_t&)\n{\n  octave_value::compound_binary_op retop\n    = octave_value::unknown_compound_binary_op;\n\n  octave_value::unary_op opa = strip_trans_herm (a);\n\n  if (opa == octave_value::op_hermitian)\n    retop = octave_value::op_herm_ldiv;\n  else if (opa == octave_value::op_transpose)\n    retop = octave_value::op_trans_ldiv;\n\n  return retop;\n}\n\n// Possibly contract and/or with negation.\n\ntree_binary_expression *\nmaybe_compound_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t)\n{\n  tree_expression *ca = a;\n  tree_expression *cb = b;\n  octave_value::compound_binary_op ct;\n\n  switch (t)\n    {\n    case octave_value::op_mul:\n      ct = simplify_mul_op (ca, cb);\n      break;\n\n    case octave_value::op_ldiv:\n      ct = simplify_ldiv_op (ca, cb);\n      break;\n\n    default:\n      ct = octave_value::unknown_compound_binary_op;\n      break;\n    }\n\n  tree_binary_expression *ret\n    = (ct == octave_value::unknown_compound_binary_op\n       ? new tree_binary_expression (a, op_tok, b, t)\n       : new tree_compound_binary_expression (a, op_tok, b, t, ca, cb, ct));\n\n  return ret;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-cbinop.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_cbinop_h)\n#define octave_pt_cbinop_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\n\n#include \"ov.h\"\n#include \"pt-binop.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Binary expressions that can be reduced to compound operations\n\nclass OCTINTERP_API tree_compound_binary_expression : public tree_binary_expression\n{\npublic:\n\n  tree_compound_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t,\n                                   tree_expression *ca, tree_expression *cb, octave_value::compound_binary_op ct)\n    : tree_binary_expression (a, op_tok, b, t), m_lhs (ca), m_rhs (cb), m_etype (ct)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_compound_binary_expression)\n\n  // FIXME: who is responsibile for deleting M_LHS and M_RHS?\n  ~tree_compound_binary_expression () = default;\n\n  octave_value::compound_binary_op cop_type () const { return m_etype; }\n\n  bool rvalue_ok () const { return true; }\n\n  tree_expression * clhs () { return m_lhs; }\n  tree_expression * crhs () { return m_rhs; }\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_compound_binary_expression (*this);\n  }\n\nprivate:\n\n  tree_expression *m_lhs;\n  tree_expression *m_rhs;\n\n  octave_value::compound_binary_op m_etype;\n};\n\n// a \"virtual constructor\"\n\nextern OCTINTERP_API tree_binary_expression *\nmaybe_compound_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t = octave_value::unknown_binary_op);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-cell.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Cell.h\"\n#include \"ovl.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-eval.h\"\n#include \"pt-exp.h\"\n#include \"pt-cell.h\"\n#include \"pt-walk.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntree_expression *\ntree_cell::dup (symbol_scope& scope) const\n{\n  tree_cell *new_cell = new tree_cell (nullptr);\n\n  new_cell->copy_base (*this, scope);\n\n  return new_cell;\n}\n\noctave_value\ntree_cell::evaluate (tree_evaluator& tw, int)\n{\n  unwind_action act ([&tw] (const std::list<octave_lvalue> *lvl)\n  {\n    tw.set_lvalue_list (lvl);\n  }, tw.lvalue_list ());\n  tw.set_lvalue_list (nullptr);\n\n  octave_idx_type nr = size ();\n  octave_idx_type nc = -1;\n\n  Cell val;\n\n  octave_idx_type i = 0;\n\n  for (tree_argument_list *elt : *this)\n    {\n      octave_value_list row = tw.convert_to_const_vector (elt);\n\n      if (nr == 1)\n        // Optimize the single row case.\n        val = row.cell_value ();\n      else if (nc < 0)\n        {\n          nc = row.length ();\n\n          val = Cell (nr, nc);\n        }\n      else\n        {\n          octave_idx_type this_nc = row.length ();\n\n          if (this_nc != nc)\n            {\n              if (this_nc == 0)\n                continue;  // blank line\n              else\n                error (\"number of columns must match\");\n            }\n        }\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        val(i, j) = row(j);\n\n      i++;\n    }\n\n  if (i < nr)\n    val.resize (dim_vector (i, nc));  // there were blank rows\n\n  return octave_value (val);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-cell.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_cell_h)\n#define octave_pt_cell_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\nclass octave_value;\nclass octave_value_list;\n\n#include \"pt-mat.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\nclass tree_argument_list;\n\n// General cells.\n\nclass OCTINTERP_API tree_cell : public tree_array_list\n{\npublic:\n\n  tree_cell (tree_argument_list *row = nullptr)\n    : tree_array_list (row)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_cell)\n\n  ~tree_cell () = default;\n\n  bool iscell () const { return true; }\n\n  bool rvalue_ok () const { return true; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_cell (*this);\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-check.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"input.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pt-all.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\ntree_checker::visit_argument_list (tree_argument_list& lst)\n{\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_expression *elt = *p++;\n\n      if (elt)\n        {\n          if (m_do_lvalue_check && ! elt->lvalue_ok ())\n            errmsg (\"invalid lvalue in multiple assignment\", elt->line ());\n        }\n    }\n}\n\nvoid\ntree_checker::visit_simple_for_command (tree_simple_for_command& cmd)\n{\n  tree_expression *lhs = cmd.left_hand_side ();\n\n  if (lhs)\n    {\n      if (! lhs->lvalue_ok ())\n        errmsg (\"invalid lvalue in for command\", cmd.line ());\n    }\n\n  tree_expression *expr = cmd.control_expr ();\n\n  if (expr)\n    expr->accept (*this);\n\n  tree_expression *maxproc = cmd.maxproc_expr ();\n\n  if (maxproc)\n    maxproc->accept (*this);\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    list->accept (*this);\n}\n\nvoid\ntree_checker::visit_complex_for_command (tree_complex_for_command& cmd)\n{\n  tree_argument_list *lhs = cmd.left_hand_side ();\n\n  if (lhs)\n    {\n      int len = lhs->size ();\n\n      if (len == 0 || len > 2)\n        errmsg (\"invalid number of output arguments in for command\",\n                cmd.line ());\n\n      m_do_lvalue_check = true;\n\n      lhs->accept (*this);\n\n      m_do_lvalue_check = false;\n    }\n\n  tree_expression *expr = cmd.control_expr ();\n\n  if (expr)\n    expr->accept (*this);\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    list->accept (*this);\n}\n\nvoid\ntree_checker::visit_multi_assignment (tree_multi_assignment& expr)\n{\n  tree_argument_list *lhs = expr.left_hand_side ();\n\n  if (lhs)\n    {\n      m_do_lvalue_check = true;\n\n      lhs->accept (*this);\n\n      m_do_lvalue_check = false;\n    }\n\n  tree_expression *rhs = expr.right_hand_side ();\n\n  if (rhs)\n    rhs->accept (*this);\n}\n\nvoid\ntree_checker::visit_simple_assignment (tree_simple_assignment& expr)\n{\n  tree_expression *lhs = expr.left_hand_side ();\n\n  if (lhs)\n    {\n      if (! lhs->lvalue_ok ())\n        errmsg (\"invalid lvalue in assignment\", expr.line ());\n    }\n\n  tree_expression *rhs = expr.right_hand_side ();\n\n  if (rhs)\n    rhs->accept (*this);\n}\n\nvoid\ntree_checker::visit_try_catch_command (tree_try_catch_command& cmd)\n{\n  tree_statement_list *try_code = cmd.body ();\n\n  tree_identifier *expr_id = cmd.identifier ();\n\n  if (expr_id)\n    {\n      if (! expr_id->lvalue_ok ())\n        errmsg (\"invalid lvalue used for identifier in try-catch command\",\n                cmd.line ());\n    }\n\n  if (try_code)\n    try_code->accept (*this);\n\n  tree_statement_list *catch_code = cmd.cleanup ();\n\n  if (catch_code)\n    catch_code->accept (*this);\n}\n\nvoid\ntree_checker::errmsg (const std::string& msg, int line)\n{\n  if (m_file_name.empty ())\n    error (\"%s\", msg.c_str ());\n  else\n    error (\"%s: %d: %s\", m_file_name.c_str (), line, msg.c_str ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-check.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_check_h)\n#define octave_pt_check_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_decl_command;\n\n// How to check the semantics of the code that the parse trees represent.\n\nclass OCTINTERP_API tree_checker : public tree_walker\n{\npublic:\n\n  tree_checker ()\n    : m_do_lvalue_check (false), m_file_name () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_checker)\n\n  ~tree_checker () = default;\n\n  void visit_argument_list (tree_argument_list&);\n\n  void visit_simple_for_command (tree_simple_for_command&);\n\n  void visit_complex_for_command (tree_complex_for_command&);\n\n  void visit_multi_assignment (tree_multi_assignment&);\n\n  void visit_simple_assignment (tree_simple_assignment&);\n\n  void visit_try_catch_command (tree_try_catch_command&);\n\nprivate:\n\n  OCTAVE_NORETURN void errmsg (const std::string& msg, int line);\n\n  //--------\n\n  bool m_do_lvalue_check;\n\n  std::string m_file_name;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-classdef.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"comment-list.h\"\n#include \"ov.h\"\n#include \"ov-classdef.h\"\n#include \"pt-args-block.h\"\n#include \"pt-classdef.h\"\n#include \"pt-eval.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntree_superclass_ref *\ntree_superclass_ref::dup (symbol_scope&) const\n{\n  tree_superclass_ref *new_scr = new tree_superclass_ref (m_method_name, m_class_name, m_token);\n\n  new_scr->copy_base (*this);\n\n  return new_scr;\n}\n\noctave_value_list\ntree_superclass_ref::evaluate_n (tree_evaluator& tw, int nargout)\n{\n  octave_value tmp = octave_classdef::superclass_ref (m_method_name, m_class_name);\n\n  if (! is_postfix_indexed ())\n    {\n      // There was no index, so this superclass_ref object is not\n      // part of an index expression.  It is also not an identifier in\n      // the syntax tree but we need to handle it as if it were.  So\n      // call the function here.\n      octave_function *f = tmp.function_value (true);\n\n      panic_unless (f);\n\n      return f->call (tw, nargout);\n    }\n\n  // The superclass_ref function object will be indexed as part of the\n  // enclosing index expression.\n\n  return ovl (tmp);\n}\n\ntree_metaclass_query *\ntree_metaclass_query::dup (symbol_scope&) const\n{\n  tree_metaclass_query *new_mcq = new tree_metaclass_query (m_class_name, m_token);\n\n  new_mcq->copy_base (*this);\n\n  return new_mcq;\n}\n\noctave_value\ntree_metaclass_query::evaluate (tree_evaluator&, int)\n{\n  return octave_classdef::metaclass_query (m_class_name);\n}\n\n// Classdef attribute\n\n// Classdef attribute_list\n\ntree_classdef_attribute_list::~tree_classdef_attribute_list ()\n{\n  while (! empty ())\n    {\n      auto p = begin ();\n      delete *p;\n      erase (p);\n    }\n}\n\n// Classdef superclass\n\n// Classdef superclass_list\n\ntree_classdef_superclass_list::~tree_classdef_superclass_list ()\n{\n  while (! empty ())\n    {\n      auto p = begin ();\n      delete *p;\n      erase (p);\n    }\n}\n\n// Classdef property\n\nstatic std::string\ncheck_for_doc_string (const comment_list& comments)\n{\n  if (! comments.empty ())\n    {\n      // If the comment list ends in a block comment or full-line\n      // comment, then it is the doc string for this property.\n\n      comment_elt last_elt = comments.back ();\n\n      if (! last_elt.is_copyright ()\n          && (last_elt.is_block () || last_elt.is_full_line ()))\n        return last_elt.text ();\n    }\n\n  return \"\";\n}\n\ntree_classdef_property::tree_classdef_property (tree_arg_validation *av)\n  : m_av (av), m_doc_string (check_for_doc_string (leading_comments ()))\n{ }\n\ntree_classdef_property::~tree_classdef_property ()\n{\n  delete m_av;\n}\n\ncomment_list\ntree_classdef_property::leading_comments ()\n{\n  tree_identifier *id = ident ();\n\n  return id->leading_comments ();\n}\n\ntree_identifier *\ntree_classdef_property::ident ()\n{\n  tree_expression *id_expr = m_av->identifier_expression ();\n\n  return dynamic_cast<tree_identifier *> (id_expr);\n}\n\ntree_expression *\ntree_classdef_property::expression ()\n{\n  return m_av->initializer_expression ();\n}\n\n// Classdef property_list\n\ntree_classdef_property_list::~tree_classdef_property_list ()\n{\n  while (! empty ())\n    {\n      auto p = begin ();\n      delete *p;\n      erase (p);\n    }\n}\n\n// Classdef properties_block\n\n// Classdef method_list\n\n// Classdef methods_block\n\n// Classdef event\n\ntree_classdef_event::tree_classdef_event (tree_identifier *i)\n  : m_id (i)\n{ }\n\n// Classdef event_list\n\ntree_classdef_event_list::~tree_classdef_event_list ()\n{\n  while (! empty ())\n    {\n      auto p = begin ();\n      delete *p;\n      erase (p);\n    }\n}\n\n// Classdef events_block\n\n// Classdef enum\n\ntree_classdef_enum::tree_classdef_enum (tree_identifier *i, const token& open_paren, tree_expression *e, const token& close_paren)\n  : m_id (i), m_open_paren (open_paren), m_expr (e), m_close_paren (close_paren)\n{ }\n\n// Classdef enum_list\n\ntree_classdef_enum_list::~tree_classdef_enum_list ()\n{\n  while (! empty ())\n    {\n      auto p = begin ();\n      delete *p;\n      erase (p);\n    }\n}\n\n// Classdef enum_block\n\n// Classdef body\n\ntree_classdef_body::tree_classdef_body ()\n  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()\n{ }\n\ntree_classdef_body::tree_classdef_body (tree_classdef_properties_block *pb)\n  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()\n{\n  append (pb);\n}\n\ntree_classdef_body::tree_classdef_body (tree_classdef_methods_block *mb)\n  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()\n{\n  append (mb);\n}\n\ntree_classdef_body::tree_classdef_body (tree_classdef_events_block *evb)\n  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()\n{\n  append (evb);\n}\n\ntree_classdef_body::tree_classdef_body (tree_classdef_enum_block *enb)\n  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()\n{\n  append (enb);\n}\n\ncomment_list\ntree_classdef_body::leading_comments () const\n{\n  if (! m_all_elements.empty ())\n    {\n      tree_base_classdef_block *element = m_all_elements.front ();\n\n      if (element)\n        return element->leading_comments ();\n    }\n\n  return comment_list ();\n}\n\ntree_classdef_body::~tree_classdef_body ()\n{\n  while (! m_all_elements.empty ())\n    {\n      auto p = m_all_elements.begin ();\n      delete *p;\n      m_all_elements.erase (p);\n    }\n}\n\n// Classdef\n\noctave_value\ntree_classdef::make_meta_class (interpreter& interp, bool is_at_folder)\n{\n  cdef_class cls = cdef_class::make_meta_class (interp, this, is_at_folder);\n\n  if (cls.ok ())\n    return cls.get_constructor_function ();\n\n  return octave_value ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-classdef.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_tree_classdef_h)\n#define octave_tree_classdef_h 1\n\n#include \"octave-config.h\"\n\nclass octave_value;\n\n#include \"pt-cmd.h\"\n#include \"pt-delimiter-list.h\"\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n#include \"pt-id.h\"\n#include \"token.h\"\n\n#include <list>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass coment_list;\nclass interpreter;\nclass tree_arg_validation;\n\nclass OCTINTERP_API tree_superclass_ref : public tree_expression\n{\npublic:\n\n  tree_superclass_ref (const std::string& meth, const std::string& cls, const token& tok)\n    : m_method_name (meth), m_class_name (cls), m_token (tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_superclass_ref)\n\n  ~tree_superclass_ref () = default;\n\n  filepos beg_pos () const { return m_token.beg_pos (); }\n  filepos end_pos () const { return m_token.end_pos (); }\n\n  comment_list leading_comments () const { return m_token.leading_comments (); }\n  comment_list trailing_comments () const { return m_token.trailing_comments (); }\n\n  std::string method_name () const\n  {\n    return m_method_name;\n  }\n\n  std::string class_name () const { return m_class_name; }\n\n  token op_token () const { return m_token; }\n\n  tree_superclass_ref * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator& tw, int nargout = 1)\n  {\n    octave_value_list retval = evaluate_n (tw, nargout);\n\n    return retval.length () > 0 ? retval(0) : octave_value ();\n  }\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1);\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_superclass_ref (*this);\n  }\n\nprivate:\n\n  // The name of the method to call.  This is the text before the\n  // \"@\" and may be of the form \"object.method\".\n  std::string m_method_name;\n\n  // The name of the superclass.  This is the text after the \"@\"\n  // and may be of the form \"object.method\".\n  std::string m_class_name;\n\n  token m_token;\n};\n\nclass OCTINTERP_API tree_metaclass_query : public tree_expression\n{\npublic:\n\n  tree_metaclass_query (const std::string& cls, const token& tok)\n    : m_class_name (cls), m_token (tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_metaclass_query)\n\n  ~tree_metaclass_query () = default;\n\n  filepos beg_pos () const { return m_token.beg_pos (); }\n  filepos end_pos () const { return m_token.end_pos (); }\n\n  comment_list leading_comments () const { return m_token.leading_comments (); }\n  comment_list trailing_comments () const { return m_token.trailing_comments (); }\n\n  std::string class_name () const { return m_class_name; }\n\n  token op_token () const { return m_token; }\n\n  tree_metaclass_query * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_metaclass_query (*this);\n  }\n\nprivate:\n\n  std::string m_class_name;\n\n  token m_token;\n};\n\nclass OCTINTERP_API tree_classdef_attribute\n{\npublic:\n\n  tree_classdef_attribute (tree_identifier *i)\n    : m_id (i)\n  { }\n\n  tree_classdef_attribute (tree_identifier *i, const token eq_tok, tree_expression *e)\n    : m_id (i), m_eq_tok (eq_tok), m_expr (e)\n  { }\n\n  tree_classdef_attribute (const token& not_tok, tree_identifier *i, bool b)\n    : m_not_tok (not_tok), m_id (i), m_neg (b)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_attribute)\n\n  ~tree_classdef_attribute ()\n  {\n    delete m_id;\n    delete m_expr;\n  }\n\n  filepos beg_pos () const { return m_not_tok ? m_not_tok.beg_pos () : m_id->beg_pos (); }\n  filepos end_pos () const { return m_expr ? m_expr->end_pos () : m_id->end_pos (); }\n\n  comment_list leading_comments () const { return m_not_tok ? m_not_tok.leading_comments () : m_id->leading_comments (); }\n  comment_list trailing_comments () const { return m_expr ? m_expr->trailing_comments () : m_id->trailing_comments (); }\n\n  token not_token () { return m_not_tok; }\n\n  tree_identifier * ident () { return m_id; }\n\n  token eq_token () { return m_eq_tok; }\n\n  tree_expression * expression () { return m_expr; }\n\n  bool negate () { return m_neg; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_attribute (*this);\n  }\n\nprivate:\n\n  token m_not_tok;\n\n  tree_identifier *m_id;\n\n  token m_eq_tok;\n\n  tree_expression *m_expr {nullptr};\n\n  bool m_neg {false};\n};\n\nclass OCTINTERP_API tree_classdef_attribute_list : public std::list<tree_classdef_attribute *>\n{\npublic:\n\n  tree_classdef_attribute_list () { }\n\n  tree_classdef_attribute_list (tree_classdef_attribute *a) { push_back (a); }\n\n  tree_classdef_attribute_list (const std::list<tree_classdef_attribute *>& a)\n    : std::list<tree_classdef_attribute *> (a)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_attribute_list)\n\n  ~tree_classdef_attribute_list ();\n\n  tree_classdef_attribute_list * mark_in_delims (const token& open_delim, token& close_delim)\n  {\n    m_delims.push (open_delim, close_delim);\n    return this;\n  }\n\n  tree_delimiter_list delims () const { return m_delims; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_attribute_list (*this);\n  }\n\nprivate:\n\n  tree_delimiter_list m_delims;\n};\n\nclass OCTINTERP_API tree_classdef_superclass\n{\npublic:\n\n  tree_classdef_superclass (const token& fqident)\n    : m_fqident (fqident)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_superclass)\n\n  ~tree_classdef_superclass () = default;\n\n  void set_separator (const token& sep_tok) { m_sep_tok = sep_tok; }\n\n  std::string class_name () { return m_fqident.text (); }\n\n  token separator_token () const { return m_sep_tok; }\n\n  token fqident_token () const { return m_fqident; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_superclass (*this);\n  }\n\nprivate:\n\n  // The '<' or '&&' token introducing an element of a superclass list\n  // element.  Is there a better name for it?\n\n  token m_sep_tok;\n\n  // The fully-qualified identifier token for this superclass element.\n  token m_fqident;\n};\n\nclass OCTINTERP_API tree_classdef_superclass_list\n  : public std::list<tree_classdef_superclass *>\n{\npublic:\n\n  tree_classdef_superclass_list () { }\n\n  tree_classdef_superclass_list (tree_classdef_superclass *sc)\n  {\n    push_back (sc);\n  }\n\n  tree_classdef_superclass_list (const std::list<tree_classdef_superclass *>& a)\n    : std::list<tree_classdef_superclass *> (a)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_superclass_list)\n\n  ~tree_classdef_superclass_list ();\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_superclass_list (*this);\n  }\n};\n\nclass OCTINTERP_API tree_base_classdef_block : public tree\n{\npublic:\n\n  tree_base_classdef_block (const token& block_tok, tree_classdef_attribute_list *a, const token& end_tok)\n    : m_block_tok (block_tok), m_attr_list (a), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_base_classdef_block)\n\n  ~tree_base_classdef_block ()\n  {\n    delete m_attr_list;\n  }\n\n  comment_list leading_comments () const { return m_block_tok.leading_comments (); }\n\n  token block_token () const { return m_block_tok; }\n\n  tree_classdef_attribute_list * attribute_list () { return m_attr_list; }\n\n  token end_token () const { return m_end_tok; }\n\n  void accept (tree_walker&) { }\n\nprotected:\n\n  token m_block_tok;\n\n  // List of attributes that apply to this class.\n  tree_classdef_attribute_list *m_attr_list;\n\n  token m_end_tok;\n};\n\ntemplate <typename T>\nclass tree_classdef_block : public tree_base_classdef_block\n{\npublic:\n\n  tree_classdef_block (const token& block_tok, tree_classdef_attribute_list *a, T *elt_list, const token& end_tok)\n    : tree_base_classdef_block (block_tok, a, end_tok), m_elt_list (elt_list)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_block)\n\n  ~tree_classdef_block ()\n  {\n    delete m_elt_list;\n  }\n\n  filepos beg_pos () const { return m_block_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_block_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  T * element_list () { return m_elt_list; }\n\nprivate:\n\n  T *m_elt_list;\n};\n\n// FIXME: should this class be derived from tree?\n\nclass OCTINTERP_API tree_classdef_property\n{\npublic:\n\n  tree_classdef_property (tree_arg_validation *av);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_property)\n\n  ~tree_classdef_property ();\n\n  comment_list leading_comments ();\n\n  tree_arg_validation * arg_validation () { return m_av; }\n\n  void doc_string (const std::string& s) { m_doc_string = s; }\n\n  std::string doc_string () const { return m_doc_string; }\n\n  bool have_doc_string () const { return ! m_doc_string.empty (); }\n\n  tree_identifier * ident ();\n\n  tree_expression * expression ();\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_property (*this);\n  }\n\nprivate:\n\n  tree_arg_validation *m_av;\n\n  std::string m_doc_string;\n};\n\nclass OCTINTERP_API tree_classdef_property_list : public std::list<tree_classdef_property *>\n{\npublic:\n\n  tree_classdef_property_list () { }\n\n  tree_classdef_property_list (tree_classdef_property *p) { push_back (p); }\n\n  tree_classdef_property_list (const std::list<tree_classdef_property *>& a)\n    : std::list<tree_classdef_property *> (a) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_property_list)\n\n  ~tree_classdef_property_list ();\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_property_list (*this);\n  }\n};\n\nclass OCTINTERP_API tree_classdef_properties_block : public tree_classdef_block<tree_classdef_property_list>\n{\npublic:\n\n  tree_classdef_properties_block (const token& block_tok, tree_classdef_attribute_list *a, tree_classdef_property_list *plist, const token& end_tok)\n    : tree_classdef_block<tree_classdef_property_list> (block_tok, a, plist, end_tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_properties_block)\n\n  ~tree_classdef_properties_block () = default;\n\n  tree_classdef_property_list * property_list () { return element_list (); }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_properties_block (*this);\n  }\n};\n\nclass OCTINTERP_API tree_classdef_method_list : public std::list<octave_value>\n{\npublic:\n\n  tree_classdef_method_list () { }\n\n  tree_classdef_method_list (const octave_value& f) { push_back (f); }\n\n  tree_classdef_method_list (const std::list<octave_value>& a)\n    : std::list<octave_value> (a) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_method_list)\n\n  ~tree_classdef_method_list () = default;\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_method_list (*this);\n  }\n};\n\nclass OCTINTERP_API tree_classdef_methods_block : public tree_classdef_block<tree_classdef_method_list>\n{\npublic:\n\n  tree_classdef_methods_block (const token& block_tok, tree_classdef_attribute_list *a, tree_classdef_method_list *mlist, const token& end_tok)\n    : tree_classdef_block<tree_classdef_method_list> (block_tok, a, mlist, end_tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_methods_block)\n\n  ~tree_classdef_methods_block () = default;\n\n  tree_classdef_method_list * method_list () { return element_list (); }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_methods_block (*this);\n  }\n};\n\nclass OCTINTERP_API tree_classdef_event\n{\npublic:\n\n  tree_classdef_event (tree_identifier *i = nullptr);\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_event)\n\n  ~tree_classdef_event ()\n  {\n    delete m_id;\n  }\n\n  tree_identifier * ident () { return m_id; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_event (*this);\n  }\n\nprivate:\n\n  tree_identifier *m_id;\n};\n\nclass OCTINTERP_API tree_classdef_event_list : public std::list<tree_classdef_event *>\n{\npublic:\n\n  tree_classdef_event_list () { }\n\n  tree_classdef_event_list (tree_classdef_event *e) { push_back (e); }\n\n  tree_classdef_event_list (const std::list<tree_classdef_event *>& a)\n    : std::list<tree_classdef_event *> (a)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_event_list)\n\n  ~tree_classdef_event_list ();\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_event_list (*this);\n  }\n};\n\nclass OCTINTERP_API tree_classdef_events_block : public tree_classdef_block<tree_classdef_event_list>\n{\npublic:\n\n  tree_classdef_events_block (const token& block_tok, tree_classdef_attribute_list *a, tree_classdef_event_list *elist, const token& end_tok)\n    : tree_classdef_block<tree_classdef_event_list> (block_tok, a, elist, end_tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_events_block)\n\n  ~tree_classdef_events_block () = default;\n\n  tree_classdef_event_list * event_list () { return element_list (); }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_events_block (*this);\n  }\n};\n\nclass OCTINTERP_API tree_classdef_enum\n{\npublic:\n\n  tree_classdef_enum (tree_identifier *i, const token& open_paren, tree_expression *e, const token& close_paren);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_enum)\n\n  ~tree_classdef_enum ()\n  {\n    delete m_id;\n    delete m_expr;\n  }\n\n  tree_identifier * ident () { return m_id; }\n\n  token open_paren () const { return m_open_paren; }\n\n  tree_expression * expression () { return m_expr; }\n\n  token close_paren () const { return m_close_paren; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_enum (*this);\n  }\n\nprivate:\n\n  tree_identifier *m_id;\n\n  token m_open_paren;\n\n  tree_expression *m_expr;\n\n  token m_close_paren;\n};\n\nclass OCTINTERP_API tree_classdef_enum_list : public std::list<tree_classdef_enum *>\n{\npublic:\n\n  tree_classdef_enum_list () { }\n\n  tree_classdef_enum_list (tree_classdef_enum *e) { push_back (e); }\n\n  tree_classdef_enum_list (const std::list<tree_classdef_enum *>& a)\n    : std::list<tree_classdef_enum *> (a)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_enum_list)\n\n  ~tree_classdef_enum_list ();\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_enum_list (*this);\n  }\n};\n\nclass OCTINTERP_API tree_classdef_enum_block : public tree_classdef_block<tree_classdef_enum_list>\n{\npublic:\n\n  tree_classdef_enum_block (const token& block_tok, tree_classdef_attribute_list *a, tree_classdef_enum_list *elist, const token& end_tok)\n    : tree_classdef_block<tree_classdef_enum_list> (block_tok, a, elist, end_tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_enum_block)\n\n  ~tree_classdef_enum_block () = default;\n\n  tree_classdef_enum_list * enum_list () { return element_list (); }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_enum_block (*this);\n  }\n};\n\n// FIXME: should this class be derived from tree?\n\nclass OCTINTERP_API tree_classdef_body\n{\npublic:\n\n  typedef std::list<tree_classdef_properties_block *>::iterator property_list_iterator;\n  typedef std::list<tree_classdef_properties_block *>::const_iterator property_list_const_iterator;\n\n  typedef std::list<tree_classdef_methods_block *>::iterator method_list_iterator;\n  typedef std::list<tree_classdef_methods_block *>::const_iterator method_list_const_iterator;\n\n  typedef std::list<tree_classdef_events_block *>::iterator event_list_iterator;\n  typedef std::list<tree_classdef_events_block *>::const_iterator event_list_const_iterator;\n\n  typedef std::list<tree_classdef_enum_block *>::iterator enum_list_iterator;\n  typedef std::list<tree_classdef_enum_block *>::const_iterator enum_list_const_iterator;\n\n  tree_classdef_body ();\n\n  tree_classdef_body (tree_classdef_properties_block *pb);\n\n  tree_classdef_body (tree_classdef_methods_block *mb);\n\n  tree_classdef_body (tree_classdef_events_block *evb);\n\n  tree_classdef_body (tree_classdef_enum_block *enb);\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_body)\n\n  ~tree_classdef_body ();\n\n  comment_list leading_comments () const;\n\n  tree_classdef_body * append (tree_classdef_properties_block *pb)\n  {\n    m_property_lst.push_back (pb);\n    m_all_elements.push_back (pb);\n    return this;\n  }\n\n  tree_classdef_body * append (tree_classdef_methods_block *mb)\n  {\n    m_method_lst.push_back (mb);\n    m_all_elements.push_back (mb);\n    return this;\n  }\n\n  tree_classdef_body * append (tree_classdef_events_block *evb)\n  {\n    m_event_lst.push_back (evb);\n    m_all_elements.push_back (evb);\n    return this;\n  }\n\n  tree_classdef_body * append (tree_classdef_enum_block *enb)\n  {\n    m_enum_lst.push_back (enb);\n    m_all_elements.push_back (enb);\n    return this;\n  }\n\n  std::list<tree_classdef_properties_block *> property_list ()\n  {\n    return m_property_lst;\n  }\n\n  std::list<tree_classdef_methods_block *> method_list ()\n  {\n    return m_method_lst;\n  }\n\n  std::list<tree_classdef_events_block *> event_list ()\n  {\n    return m_event_lst;\n  }\n\n  std::list<tree_classdef_enum_block *> enum_list ()\n  {\n    return m_enum_lst;\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef_body (*this);\n  }\n\nprivate:\n\n  std::list<tree_classdef_properties_block *> m_property_lst;\n\n  std::list<tree_classdef_methods_block *> m_method_lst;\n\n  std::list<tree_classdef_events_block *> m_event_lst;\n\n  std::list<tree_classdef_enum_block *> m_enum_lst;\n\n  std::list<tree_base_classdef_block *> m_all_elements;\n};\n\n// Classdef definition.\n\nclass OCTINTERP_API tree_classdef : public tree_command\n{\npublic:\n\n  tree_classdef (const symbol_scope& scope, const token& cdef_tok, tree_classdef_attribute_list *a, tree_identifier *i, tree_classdef_superclass_list *sc, tree_classdef_body *b, const token& end_tok, const std::string& pn = \"\", const std::string& fn = \"\")\n    : m_scope (scope), m_cdef_tok (cdef_tok), m_attr_list (a), m_id (i), m_supclass_list (sc), m_body (b), m_end_tok (end_tok), m_pack_name (pn), m_file_name (fn)\n  {\n    cache_doc_string ();\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef)\n\n  ~tree_classdef ()\n  {\n    delete m_attr_list;\n    delete m_id;\n    delete m_supclass_list;\n    delete m_body;\n  }\n\n  filepos beg_pos () const { return m_cdef_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_cdef_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  symbol_scope scope () { return m_scope; }\n\n  token classdef_token () const { return m_cdef_tok; }\n\n  tree_classdef_attribute_list *\n  attribute_list () { return m_attr_list; }\n\n  tree_identifier * ident () { return m_id; }\n\n  tree_classdef_superclass_list *\n  superclass_list () { return m_supclass_list; }\n\n  tree_classdef_body * body () { return m_body; }\n\n  token end_token () const { return m_end_tok; }\n\n  std::string package_name () const { return m_pack_name; }\n\n  std::string file_name () const { return m_file_name; }\n\n  octave_value make_meta_class (interpreter& interp,\n                                bool is_at_folder = false);\n\n  std::string doc_string () const { return m_doc_string; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_classdef (*this);\n  }\n\nprivate:\n\n  void cache_doc_string ()\n  {\n    // First non-copyright comments found above and below classdef\n    // keyword are candidates for the documentation string.  Use the\n    // first one that is not empty.\n\n    comment_list comments = m_cdef_tok.leading_comments ();\n\n    m_doc_string = comments.find_doc_string ();\n\n    if (m_doc_string.empty ())\n      {\n        comments = m_body->leading_comments ();\n\n        m_doc_string = comments.find_doc_string ();\n      }\n  }\n\n  // The scope that was used when parsing the classdef object and that\n  // corresponds to any identifiers that were found in attribute lists\n  // (for example).  Used again when computing the meta class object.\n\n  symbol_scope m_scope;\n\n  token m_cdef_tok;\n\n  tree_classdef_attribute_list *m_attr_list;\n\n  tree_identifier *m_id;\n\n  tree_classdef_superclass_list *m_supclass_list;\n\n  tree_classdef_body *m_body;\n\n  token m_end_tok;\n\n  std::string m_pack_name;\n  std::string m_file_name;\n\n  std::string m_doc_string;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-cmd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_cmd_h)\n#define octave_pt_cmd_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"comment-list.h\"\n#include \"ov-fcn.h\"\n#include \"pt.h\"\n#include \"pt-bp.h\"\n#include \"pt-walk.h\"\n#include \"panic.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// A base class for commands.\n\nclass OCTINTERP_API tree_command : public tree\n{\npublic:\n\n  tree_command () = default;\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_command)\n\n  virtual ~tree_command () = default;\n\n  virtual void update_end_pos (const filepos&)\n  {\n    error (\"unexpected call to tree_command::update_end_pos - please report this bug\");\n  }\n};\n\n// No-op.\n\nclass OCTINTERP_API tree_no_op_command : public tree_command\n{\npublic:\n\n  tree_no_op_command (const std::string& cmd, bool eof, const token& tok)\n    : m_eof (eof), m_tok (tok), m_orig_cmd (cmd)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_no_op_command)\n\n  ~tree_no_op_command () = default;\n\n  filepos beg_pos () const { return m_tok.beg_pos (); }\n  filepos end_pos () const { return m_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_tok.trailing_comments (); }\n\n  void update_end_pos (const filepos& pos)\n  {\n    if (is_end_of_fcn_or_script () || is_end_of_file ())\n      m_tok.end_pos (pos);\n    else\n      error (\"unexpected call to tree_no_op_command::update_end_pos - please report this bug\");\n  }\n\n  void attach_trailing_comments (const comment_list& lst)\n  {\n    m_tok.trailing_comments (lst);\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_no_op_command (*this);\n  }\n\n  bool is_end_of_fcn_or_script () const\n  {\n    return (m_orig_cmd == \"endfunction\" || m_orig_cmd == \"endscript\");\n  }\n\n  bool is_end_of_file () const { return m_eof; }\n\n  std::string original_command () { return m_orig_cmd; }\n\nprivate:\n\n  bool m_eof;\n\n  // If defined, may be END token or EOF.\n  token m_tok;\n\n  std::string m_orig_cmd;\n};\n\n// Function definition.\n\nclass OCTINTERP_API tree_function_def : public tree_command\n{\npublic:\n\n  tree_function_def (octave_function *f) : m_fcn (f) { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_function_def)\n\n  ~tree_function_def () = default;\n\n  filepos beg_pos () const\n  {\n    octave_function *f = m_fcn.function_value ();\n    return f->beg_pos ();\n  }\n\n  filepos end_pos () const\n  {\n    octave_function *f = m_fcn.function_value ();\n    return f->end_pos ();\n  }\n\n  comment_list leading_comments () const\n  {\n    octave_function *f = m_fcn.function_value ();\n    return f->leading_comments ();\n  }\n\n  comment_list trailing_comments () const\n  {\n    octave_function *f = m_fcn.function_value ();\n    return f->trailing_comments ();\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_function_def (*this);\n  }\n\n  octave_value function () { return m_fcn; }\n\nprivate:\n\n  tree_function_def (const octave_value& v) : m_fcn (v) { }\n\n  //--------\n\n  octave_value m_fcn;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-colon.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"interpreter.h\"\n#include \"parse.h\"\n#include \"pt-colon.h\"\n#include \"pt-eval.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Colon expressions.\n\ntree_expression *\ntree_colon_expression::dup (symbol_scope& scope) const\n{\n  tree_colon_expression *new_ce\n    = new tree_colon_expression (m_base ? m_base->dup (scope) : nullptr,\n                                 m_colon_1_tok,\n                                 m_increment ? m_increment->dup (scope) : nullptr,\n                                 m_colon_2_tok,\n                                 m_limit ? m_limit->dup (scope) : nullptr);\n\n  new_ce->copy_base (*this);\n\n  return new_ce;\n}\n\noctave_value\ntree_colon_expression::evaluate (tree_evaluator& tw, int)\n{\n  octave_value val;\n\n  if (! m_base || ! m_limit)\n    return val;\n\n  octave_value ov_base;\n  octave_value ov_increment;\n  octave_value ov_limit;\n\n  if (m_increment)\n    {\n      ov_base = m_base->evaluate (tw);\n      ov_increment = m_increment->evaluate (tw);\n      ov_limit = m_limit->evaluate (tw);\n    }\n  else\n    {\n      ov_base = m_base->evaluate (tw);\n      ov_limit = m_limit->evaluate (tw);\n    }\n\n  return colon_op (ov_base, ov_increment, ov_limit, is_for_cmd_expr ());\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-colon.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_colon_h)\n#define octave_pt_colon_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\n\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\n\n// Colon expressions.\n\nclass OCTINTERP_API tree_colon_expression : public tree_expression\n{\npublic:\n\n  tree_colon_expression (tree_expression *base, const token& colon_1_tok, tree_expression *limit)\n    : m_base (base), m_colon_1_tok (colon_1_tok), m_limit (limit)\n  { }\n\n  tree_colon_expression (tree_expression *base, const token& colon_1_tok, tree_expression *increment, const token& colon_2_tok, tree_expression *limit)\n    : m_base (base), m_colon_1_tok (colon_1_tok), m_increment (increment), m_colon_2_tok (colon_2_tok), m_limit (limit)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_colon_expression)\n\n  ~tree_colon_expression ()\n  {\n    if (! m_save_base)\n      delete m_base;\n\n    delete m_limit;\n    delete m_increment;\n  }\n\n  filepos beg_pos () const { return m_base->beg_pos (); }\n  filepos end_pos () const { return m_limit->end_pos (); }\n\n  comment_list leading_comments () const { return m_base->leading_comments (); }\n  comment_list trailing_comments () const { return m_limit->trailing_comments (); }\n\n  void preserve_base () { m_save_base = true; }\n\n  bool rvalue_ok () const { return true; }\n\n  void eval_error (const std::string& s) const;\n\n  tree_expression * base () { return m_base; }\n\n  token first_colon_token () const { return m_colon_1_tok; }\n\n  tree_expression * limit () { return m_limit; }\n\n  token second_colon_token () const { return m_colon_2_tok; }\n\n  tree_expression * increment () { return m_increment; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  bool is_colon_expression () const { return true; }\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_colon_expression (*this);\n  }\n\nprivate:\n\n  // The components of the expression.\n  tree_expression *m_base;\n\n  token m_colon_1_tok;\n\n  tree_expression *m_increment {nullptr};\n\n  token m_colon_2_tok;\n\n  tree_expression *m_limit;\n\n  bool m_save_base {false};\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-const.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ostream>\n\n#include \"error.h\"\n#include \"ovl.h\"\n#include \"pager.h\"\n#include \"pt-const.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// We are likely to have a lot of tree_constant objects to allocate,\n// so make the grow_size large.\n\nvoid\ntree_constant::print (std::ostream& os, bool pr_as_read_syntax,\n                      bool pr_orig_text)\n{\n  if (pr_orig_text && ! m_orig_text.empty ())\n    os << m_orig_text;\n  else\n    m_value.print (os, pr_as_read_syntax);\n}\n\nvoid\ntree_constant::print_raw (std::ostream& os, bool pr_as_read_syntax,\n                          bool pr_orig_text)\n{\n  if (pr_orig_text && ! m_orig_text.empty ())\n    os << m_orig_text;\n  else\n    m_value.print_raw (os, pr_as_read_syntax);\n}\n\ntree_expression *\ntree_constant::dup (symbol_scope&) const\n{\n  tree_constant *new_tc = new tree_constant (m_value, m_orig_text, m_token);\n\n  new_tc->copy_base (*this);\n\n  return new_tc;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-const.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_const_h)\n#define octave_pt_const_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\nclass octave_value_list;\n\n#include \"error.h\"\n#include \"ov.h\"\n#include \"pt-bp.h\"\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\nclass tree_evaluator;\n\nclass OCTINTERP_API tree_constant : public tree_expression\n{\npublic:\n\n  tree_constant (const octave_value& v, const token& tok)\n    : m_value (v), m_token (tok)\n  { }\n\n  tree_constant (const octave_value& v, const std::string& ot, const token& tok)\n    : m_value (v), m_orig_text (ot), m_token (tok)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_constant)\n\n  ~tree_constant () = default;\n\n  // Type.  It would be nice to eliminate the need for this.\n\n  bool is_constant () const { return true; }\n\n  filepos beg_pos () const { return m_token.beg_pos (); }\n  filepos end_pos () const { return m_token.end_pos (); }\n\n  comment_list leading_comments () const { return m_token.leading_comments (); }\n  comment_list trailing_comments () const { return m_token.trailing_comments (); }\n\n  void maybe_mutate () { m_value.maybe_mutate (); }\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false,\n              bool pr_orig_txt = true);\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false,\n                  bool pr_orig_txt = true);\n\n  bool rvalue_ok () const { return true; }\n\n  octave_value value () { return m_value; }\n\n  token const_token () const { return m_token; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_constant (*this);\n  }\n\n  // Store the original text corresponding to this constant for later\n  // pretty printing.\n\n  void stash_original_text (const std::string& s) { m_orig_text = s; }\n\n  std::string original_text () const { return m_orig_text; }\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1)\n  {\n    if (nargout > 1)\n      error (\"invalid number of output arguments for constant expression\");\n\n    return value ();\n  }\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\nprivate:\n\n  // The actual value that this constant refers to.\n  octave_value m_value;\n\n  // The original text form of this constant.\n  std::string m_orig_text;\n\n  token m_token;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-decl.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"error.h\"\n#include \"pt-cmd.h\"\n#include \"ov.h\"\n#include \"oct-lvalue.h\"\n#include \"pt-bp.h\"\n#include \"pt-decl.h\"\n#include \"pt-exp.h\"\n#include \"pt-id.h\"\n#include \"pt-walk.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Declarations (global, static, etc.).\n\ntree_decl_elt::tree_decl_elt (tree_identifier *i, tree_expression *e)\n  : m_type (unknown), m_id (i), m_expr (e)\n{\n  if (! m_id)\n    error (\"tree_decl_elt: invalid ID\");\n}\n\ntree_decl_elt::~tree_decl_elt ()\n{\n  delete m_id;\n  delete m_expr;\n}\n\ntree_decl_elt *\ntree_decl_elt::dup (symbol_scope& scope) const\n{\n  return new tree_decl_elt (m_id->dup (scope),\n                            m_expr ? m_expr->dup (scope) : nullptr);\n}\n\n// Initializer lists for declaration statements.\n\n// Declaration commands (global, static).\n\ntree_decl_command::tree_decl_command (const std::string& n, const token& tok, tree_decl_init_list *t)\n  : m_cmd_name (n), m_token (tok), m_init_list (t)\n{\n  if (t)\n    {\n      if (m_cmd_name == \"global\")\n        mark_global ();\n      else if (m_cmd_name == \"persistent\")\n        mark_persistent ();\n      else\n        error (\"tree_decl_command: unknown decl type: %s\",\n               m_cmd_name.c_str ());\n    }\n}\n\ntree_decl_command::~tree_decl_command ()\n{\n  delete m_init_list;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-decl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_decl_h)\n#define octave_pt_decl_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n\n#include \"oct-lvalue.h\"\n#include \"pt-cmd.h\"\n#include \"pt-id.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\nclass tree_evaluator;\nclass tree_expression;\nclass tree_identifier;\n\n// List of expressions that make up a declaration statement.\n\nclass OCTINTERP_API tree_decl_elt\n{\npublic:\n\n  enum decl_type\n  {\n    unknown,\n    global,\n    persistent\n  };\n\n  tree_decl_elt (tree_identifier *i, tree_expression *e = nullptr);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_decl_elt)\n\n  ~tree_decl_elt ();\n\n  filepos beg_pos () const { return m_id->beg_pos (); }\n  filepos end_pos () const { return m_expr ? m_expr->end_pos () : m_id->end_pos (); }\n\n  comment_list leading_comments () const { return m_id->leading_comments (); }\n  comment_list trailing_comments () const { return m_expr ? m_expr->trailing_comments () : m_id->trailing_comments (); }\n\n  void mark_as_formal_parameter ()\n  {\n    m_id->mark_as_formal_parameter ();\n  }\n\n  bool lvalue_ok () { return m_id->lvalue_ok (); }\n\n  octave_lvalue lvalue (tree_evaluator& tw)\n  {\n    return m_id->lvalue (tw);\n  }\n\n  void mark_global () { m_type = global; }\n  bool is_global () const { return m_type == global; }\n\n  void mark_persistent () { m_type = persistent; }\n  bool is_persistent () const { return m_type == persistent; }\n\n  tree_identifier * ident () { return m_id; }\n\n  std::string name () const { return m_id->name (); }\n\n  tree_expression * expression () { return m_expr; }\n\n  tree_decl_elt * dup (symbol_scope& scope) const;\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_decl_elt (*this);\n  }\n\nprivate:\n\n  decl_type m_type;\n\n  // An identifier to tag with the declared property.\n  tree_identifier *m_id;\n\n  // An initializer expression (may be zero);\n  tree_expression *m_expr;\n};\n\nclass OCTINTERP_API tree_decl_init_list : public std::list<tree_decl_elt *>\n{\npublic:\n\n  tree_decl_init_list () { }\n\n  tree_decl_init_list (tree_decl_elt *t) { push_back (t); }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_decl_init_list)\n\n  ~tree_decl_init_list ()\n  {\n    while (! empty ())\n      {\n        auto p = begin ();\n        delete *p;\n        erase (p);\n      }\n  }\n\n  filepos beg_pos () const\n  {\n    if (empty ())\n      return filepos ();\n\n    tree_decl_elt *elt = front ();\n    return elt->beg_pos ();\n  }\n\n  filepos end_pos () const\n  {\n    if (empty ())\n      return filepos ();\n\n    tree_decl_elt *elt = back ();\n    return elt->end_pos ();\n  }\n\n  comment_list leading_comments () const\n  {\n    if (empty ())\n      return comment_list ();\n\n    tree_decl_elt *elt = front ();\n    return elt->leading_comments ();\n  }\n\n  comment_list trailing_comments () const\n  {\n    if (empty ())\n      return comment_list ();\n\n    tree_decl_elt *elt = back ();\n    return elt->trailing_comments ();\n  }\n\n  void mark_global ()\n  {\n    for (tree_decl_elt *elt : *this)\n      elt->mark_global ();\n  }\n\n  void mark_persistent ()\n  {\n    for (tree_decl_elt *elt : *this)\n      elt->mark_persistent ();\n  }\n\n  std::list<std::string> variable_names () const\n  {\n    std::list<std::string> retval;\n\n    for (const tree_decl_elt *elt : *this)\n      {\n        std::string nm = elt->name ();\n\n        if (! nm.empty ())\n          retval.push_back (nm);\n      }\n\n    return retval;\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_decl_init_list (*this);\n  }\n};\n\n// Base class for declaration commands -- global, static, etc.\n\nclass OCTINTERP_API tree_decl_command : public tree_command\n{\npublic:\n\n  tree_decl_command (const std::string& n, const token& tok, tree_decl_init_list *t);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_decl_command)\n\n  ~tree_decl_command ();\n\n  filepos beg_pos () const { return m_token.beg_pos (); }\n  filepos end_pos () const { return m_init_list->end_pos (); }\n\n  comment_list leading_comments () const { return m_token.leading_comments (); }\n  comment_list trailing_comments () const { return m_init_list->trailing_comments (); }\n\n  void mark_global ()\n  {\n    if (m_init_list)\n      m_init_list->mark_global ();\n  }\n\n  void mark_persistent ()\n  {\n    if (m_init_list)\n      m_init_list->mark_persistent ();\n  }\n\n  token decl_token () const { return m_token; }\n\n  std::string name () const { return m_cmd_name; }\n\n  tree_decl_init_list * initializer_list () { return m_init_list; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_decl_command (*this);\n  }\n\nprivate:\n\n  // The name of this command -- global, static, etc.\n  std::string m_cmd_name;\n\n  token m_token;\n\n  // The list of variables or initializers in this declaration command.\n  tree_decl_init_list *m_init_list;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-delimiter-list.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_tree_delimiter_list_h)\n#define octave_tree_delimiter_list_h 1\n\n#include \"octave-config.h\"\n\n#include <stack>\n\n#include \"filepos.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API tree_delimiter_list\n{\npublic:\n\n  typedef std::pair<token, token> element_type;\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (tree_delimiter_list)\n\n  size_t count () const { return m_delimiters.size (); }\n\n  bool empty () const { return m_delimiters.empty (); }\n\n  void push (const token& open_delim, const token& close_delim)\n  {\n    m_delimiters.push (element_type (open_delim, close_delim));\n  }\n\n  filepos beg_pos () const\n  {\n    if (m_delimiters.empty ())\n      return filepos ();\n\n    const element_type& elt = m_delimiters.top ();\n    return elt.first.beg_pos ();\n  }\n\n  filepos end_pos () const\n  {\n    if (m_delimiters.empty ())\n      return filepos ();\n\n    const element_type& elt = m_delimiters.top ();\n    return elt.second.end_pos ();\n  }\n\n  comment_list leading_comments () const\n  {\n    if (m_delimiters.empty ())\n      return comment_list ();\n\n    const element_type& elt = m_delimiters.top ();\n    return elt.first.leading_comments ();\n  }\n\n  comment_list trailing_comments () const\n  {\n    if (m_delimiters.empty ())\n      return comment_list ();\n\n    const element_type& elt = m_delimiters.top ();\n    return elt.second.trailing_comments ();\n  }\n\n  std::stack<element_type> delims () const { return m_delimiters; }\n\nprivate:\n\n  std::stack<element_type> m_delimiters;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-eval.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <condition_variable>\n#include <iostream>\n#include <list>\n#include <mutex>\n#include <string>\n\n#include \"cmd-edit.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"lo-array-errwarn.h\"\n#include \"lo-ieee.h\"\n#include \"oct-env.h\"\n\n#include \"bp-table.h\"\n#include \"call-stack.h\"\n#include \"cdef-manager.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"event-manager.h\"\n#include \"input.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n#include \"mex-private.h\"\n#include \"octave.h\"\n#include \"ov-classdef.h\"\n#include \"ov-fcn-handle.h\"\n#include \"ov-mex-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n#include \"parse.h\"\n#include \"profiler.h\"\n#include \"pt-all.h\"\n#include \"pt-anon-scopes.h\"\n#include \"pt-eval.h\"\n#include \"pt-tm-const.h\"\n#include \"stack-frame.h\"\n#include \"symtab.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_NORETURN static void\nerror_unexpected (const char *name)\n{\n  error (\"unexpected call to %s - please report this bug\", name);\n}\n\n// Normal evaluator.\n\nclass quit_debug_exception\n{\npublic:\n\n  quit_debug_exception (bool all = false) : m_all (all) { }\n\n  quit_debug_exception (const quit_debug_exception&) = default;\n\n  quit_debug_exception& operator = (const quit_debug_exception&) = default;\n\n  ~quit_debug_exception () = default;\n\n  bool all () const { return m_all; }\n\nprivate:\n\n  bool m_all;\n};\n\nclass debugger\n{\npublic:\n\n  enum execution_mode\n  {\n    EX_NORMAL = 0,\n    EX_CONTINUE = 1,\n    EX_QUIT = 2,\n    EX_QUIT_ALL = 3\n  };\n\n  debugger (interpreter& interp, std::size_t level)\n    : m_interpreter (interp), m_level (level),\n      m_execution_mode (EX_NORMAL), m_in_debug_repl (false)\n  { }\n\n  int server_loop ();\n\n  void repl (const std::string& prompt = \"debug> \");\n\n  bool in_debug_repl () const { return m_in_debug_repl; }\n\n  void dbcont () { m_execution_mode = EX_CONTINUE; }\n\n  void dbquit (bool all = false)\n  {\n    if (all)\n      m_execution_mode = EX_QUIT_ALL;\n    else\n      m_execution_mode = EX_QUIT;\n  }\n\n  bool quitting_debugger () const;\n\nprivate:\n\n  interpreter& m_interpreter;\n\n  std::size_t m_level;\n  execution_mode m_execution_mode;\n  bool m_in_debug_repl;\n};\n\n// FIXME: Could the debugger server_loop and repl functions be merged\n// with the corresponding tree_evaluator functions or do they need to\n// remain separate?  They perform nearly the same functions.\n\nint\ndebugger::server_loop ()\n{\n  // Process events from the event queue.\n\n  tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n  void (tree_evaluator::*server_mode_fptr) (bool)\n    = &tree_evaluator::server_mode;\n  unwind_action act (server_mode_fptr, &tw, true);\n\n  int exit_status = 0;\n\n  do\n    {\n      if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ())\n        break;\n\n      if (quitting_debugger ())\n        break;\n\n      try\n        {\n          // FIXME: Should we call octave_quit in the octave::sleep\n          // and/or command_editor::run_event_hooks functions?\n\n          octave_quit ();\n\n          // FIXME: Running the event queue should be decoupled from\n          // the command_editor.\n\n          // FIXME: Is it OK to use command_editor::run_event_hooks\n          // here?  It may run more than one queued function per call,\n          // and it seems that the checks at the top of the loop\n          // probably need to be done after each individual event\n          // function is executed.  For now, maybe the simplest thing\n          // would be to pass a predicate function (lambda expression)\n          // to the command_editor::run_event_hooks and have it check\n          // that and break out of the eval loop(s) if the condition\n          // is met?\n\n          // FIXME: We should also use a condition variable to manage\n          // the execution of entries in the queue and eliminate the\n          // need for the busy-wait loop.\n\n          command_editor::run_event_hooks ();\n\n          release_unreferenced_dynamic_libraries ();\n\n          sleep (0.1);\n        }\n      catch (const interrupt_exception&)\n        {\n          octave_interrupt_state = 1;\n          m_interpreter.recover_from_exception ();\n\n          // Required newline when the user does Ctrl+C at the prompt.\n          if (m_interpreter.interactive ())\n            octave_stdout << \"\\n\";\n        }\n      catch (const index_exception& e)\n        {\n          m_interpreter.recover_from_exception ();\n\n          std::cerr << \"error: unhandled index exception: \"\n                    << e.message () << \" -- trying to return to prompt\"\n                    << std::endl;\n        }\n      catch (const execution_exception& ee)\n        {\n          error_system& es = m_interpreter.get_error_system ();\n\n          es.save_exception (ee);\n          es.display_exception (ee);\n\n          if (m_interpreter.interactive ())\n            {\n              m_interpreter.recover_from_exception ();\n            }\n          else\n            {\n              // We should exit with a nonzero status.\n              exit_status = 1;\n              break;\n            }\n        }\n      catch (const quit_debug_exception& qde)\n        {\n          if (qde.all ())\n            throw;\n\n          // Continue in this debug level.\n        }\n      catch (const std::bad_alloc&)\n        {\n          m_interpreter.recover_from_exception ();\n\n          std::cerr << \"error: out of memory -- trying to return to prompt\"\n                    << std::endl;\n        }\n    }\n  while (exit_status == 0);\n\n  if (exit_status == EOF)\n    {\n      if (m_interpreter.interactive ())\n        octave_stdout << \"\\n\";\n\n      exit_status = 0;\n    }\n\n  return exit_status;\n}\n\nvoid\ndebugger::repl (const std::string& prompt_arg)\n{\n  unwind_protect frame;\n\n  frame.protect_var (m_in_debug_repl);\n  frame.protect_var (m_execution_mode);\n\n  m_in_debug_repl = true;\n\n  tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n  bool silent = tw.quiet_breakpoint_flag (false);\n\n  frame.add (&tree_evaluator::restore_frame, &tw,\n             tw.current_call_stack_frame_number ());\n\n  tw.goto_frame (tw.debug_frame ());\n\n  octave_user_code *caller = tw.current_user_code ();\n  std::string fcn_file_nm, fcn_nm;\n\n  if (caller)\n    {\n      fcn_file_nm = caller->fcn_file_name ();\n      fcn_nm = fcn_file_nm.empty () ? caller->name () : fcn_file_nm;\n    }\n\n  int curr_debug_line = tw.current_line ();\n\n  std::ostringstream buf;\n\n  input_system& input_sys = m_interpreter.get_input_system ();\n\n  event_manager& evmgr = m_interpreter.get_event_manager ();\n\n  if (! fcn_nm.empty ())\n    {\n      if (input_sys.gud_mode ())\n        {\n          static char ctrl_z = 'Z' & 0x1f;\n\n          buf << ctrl_z << ctrl_z << fcn_nm << ':' << curr_debug_line;\n        }\n      else\n        {\n          // FIXME: we should come up with a clean way to detect\n          // that we are stopped on the no-op command that marks the\n          // end of a function or script.\n\n          if (! silent)\n            {\n              std::shared_ptr<stack_frame> frm = tw.current_user_frame ();\n\n              frm->display_stopped_in_message (buf);\n            }\n\n          evmgr.enter_debugger_event (fcn_nm, fcn_file_nm, curr_debug_line);\n\n          evmgr.set_workspace ();\n\n          frame.add (&event_manager::execute_in_debugger_event, &evmgr,\n                     fcn_nm, curr_debug_line);\n\n          if (! silent)\n            {\n              std::string line_buf;\n\n              if (caller)\n                line_buf = caller->get_code_line (curr_debug_line);\n\n              if (! line_buf.empty ())\n                buf << curr_debug_line << \": \" << line_buf;\n              else\n                buf << \"[End of function]\";\n            }\n        }\n    }\n\n  if (silent)\n    command_editor::erase_empty_line (true);\n\n  std::string stopped_in_msg = buf.str ();\n\n  if (m_interpreter.server_mode ())\n    {\n      if (! stopped_in_msg.empty ())\n        octave_stdout << stopped_in_msg << std::endl;\n\n      evmgr.push_event_queue ();\n\n      frame.add (&event_manager::pop_event_queue, &evmgr);\n\n      frame.add (&tree_evaluator::set_parser, &tw, tw.get_parser ());\n\n      std::shared_ptr<push_parser>\n        debug_parser (new push_parser (m_interpreter));\n\n      tw.set_parser (debug_parser);\n\n      server_loop ();\n    }\n  else\n    {\n      if (! stopped_in_msg.empty ())\n        std::cerr << stopped_in_msg << std::endl;\n\n      std::string tmp_prompt = prompt_arg;\n      if (m_level > 0)\n        tmp_prompt = \"[\" + std::to_string (m_level) + \"]\" + prompt_arg;\n\n      frame.add (&interpreter::set_PS1, &m_interpreter, m_interpreter.PS1 ());\n      m_interpreter.PS1 (tmp_prompt);\n\n      if (! m_interpreter.interactive ())\n        {\n          void (interpreter::*interactive_fptr) (bool)\n            = &interpreter::interactive;\n          frame.add (interactive_fptr, &m_interpreter,\n                     m_interpreter.interactive ());\n\n          m_interpreter.interactive (true);\n\n          // FIXME: should debugging be possible in an embedded\n          // interpreter?\n\n          application *app = application::app ();\n\n          if (app)\n            {\n              void (application::*forced_interactive_fptr) (bool)\n                = &application::forced_interactive;\n              frame.add (forced_interactive_fptr, app,\n                         app->forced_interactive ());\n\n              app->forced_interactive (true);\n            }\n        }\n\n#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)\n\n      input_reader reader (m_interpreter);\n\n      push_parser debug_parser (m_interpreter);\n\n#else\n\n      parser debug_parser (m_interpreter);\n\n#endif\n\n      error_system& es = m_interpreter.get_error_system ();\n\n      while (m_in_debug_repl)\n        {\n          if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ())\n            break;\n\n          if (quitting_debugger ())\n            break;\n\n          try\n            {\n              debug_parser.reset ();\n\n#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)\n\n              int retval = 0;\n\n              std::string prompt\n                = command_editor::decode_prompt_string (tmp_prompt);\n\n              bool auto_repeat_state = input_sys.auto_repeat_debug_command ();\n\n              unwind_action restore_auto_repeat_debugging_command ([&input_sys, auto_repeat_state] () { input_sys.auto_repeat_debug_command (auto_repeat_state); });\n              do\n                {\n                  bool eof = false;\n                  std::string input_line = reader.get_input (prompt, eof);\n\n                  if (eof)\n                    {\n                      retval = EOF;\n                      break;\n                    }\n\n                  retval = debug_parser.run (input_line, false);\n\n                  input_sys.auto_repeat_debug_command (false);\n                  prompt = command_editor::decode_prompt_string (m_interpreter.PS2 ());\n                }\n              while (retval < 0);\n\n#else\n\n              int retval = debug_parser.run ();\n\n#endif\n              if (command_editor::interrupt (false))\n                {\n                  // Break regardless of m_execution_mode value.\n\n                  quitting_debugger ();\n\n                  break;\n                }\n              else\n                {\n                  if (retval == 0)\n                    {\n                      std::shared_ptr<tree_statement_list> stmt_list\n                        = debug_parser.statement_list ();\n\n                      if (stmt_list)\n                        stmt_list->accept (tw);\n\n                      if (octave_completion_matches_called)\n                        octave_completion_matches_called = false;\n\n                      // FIXME: the following statement is here because\n                      // the last command may have been a dbup, dbdown, or\n                      // dbstep command that changed the current debug\n                      // frame.  If so, we need to reset the current frame\n                      // for the call stack.  But is this right way to do\n                      // this job?  What if the statement list was\n                      // something like \"dbup; dbstack\"?  Will the call to\n                      // dbstack use the right frame?  If not, how can we\n                      // fix this problem?\n                      tw.goto_frame (tw.debug_frame ());\n                    }\n\n                  octave_quit ();\n                }\n            }\n          catch (const execution_exception& ee)\n            {\n              es.save_exception (ee);\n              es.display_exception (ee);\n\n              // Ignore errors when in debugging mode;\n              m_interpreter.recover_from_exception ();\n            }\n          catch (const quit_debug_exception& qde)\n            {\n              if (qde.all ())\n                throw;\n\n              // Continue in this debug level.\n            }\n        }\n    }\n}\n\nbool\ndebugger::quitting_debugger () const\n{\n  if (m_execution_mode == EX_QUIT)\n    {\n      // If there is no enclosing debug level or the top-level\n      // repl is not active, handle dbquit the same as dbcont.\n\n      if (m_level > 0 || m_interpreter.server_mode ()\n          || m_interpreter.in_top_level_repl ())\n        throw quit_debug_exception ();\n      else\n        return true;\n    }\n\n  if (m_execution_mode == EX_QUIT_ALL)\n    {\n      // If the top-level repl is not active, handle \"dbquit all\"\n      // the same as dbcont.\n\n      if (m_interpreter.server_mode () || m_interpreter.in_top_level_repl ())\n        throw quit_debug_exception (true);\n      else\n        return true;\n    }\n\n  return false;\n}\n\nbool\ntree_evaluator::at_top_level () const\n{\n  return m_call_stack.at_top_level ();\n}\n\nstd::string\ntree_evaluator::mfilename (const std::string& opt) const\n{\n  std::string fname;\n\n  octave_user_code *fcn = m_call_stack.current_user_code ();\n\n  if (fcn)\n    {\n      fname = fcn->fcn_file_name ();\n\n      if (fname.empty ())\n        fname = fcn->name ();\n    }\n\n  if (opt == \"fullpathext\")\n    return fname;\n\n  std::size_t dpos = fname.rfind (sys::file_ops::dir_sep_char ());\n  std::size_t epos = fname.rfind ('.');\n\n  if (epos <= dpos+1)\n    epos = std::string::npos;\n\n  if (epos != std::string::npos)\n    fname = fname.substr (0, epos);\n\n  if (opt == \"fullpath\")\n    return fname;\n\n  if (dpos != std::string::npos)\n    fname = fname.substr (dpos+1);\n\n  return fname;\n}\n\nvoid\ntree_evaluator::parse_and_execute (const std::string& input,\n                                   bool& incomplete_parse)\n{\n  incomplete_parse = false;\n\n  unwind_protect_var<bool> upv (m_in_top_level_repl, true);\n\n  if (at_top_level ())\n    {\n      dbstep_flag (0);\n      reset_debug_state ();\n    }\n\n  // FIXME: OK to do this job here, or should it be in the functions\n  // that do the actual prompting?\n\n  // Update the time stamp for the \"prompt\" so that automatically\n  // finding modified files based on file modification times will\n  // work.  In the future, we may do something completely different to\n  // check for changes to files but for now, we rely on the prompt\n  // time stamp to limit the checks for file modification times.\n\n  Vlast_prompt_time.stamp ();\n\n  bool eof = false;\n\n  event_manager& evmgr = m_interpreter.get_event_manager ();\n\n  if (command_history::add (input))\n    evmgr.append_history (input);\n\n  m_exit_status = m_parser->run (input, eof);\n\n  if (m_exit_status == 0)\n    {\n      std::shared_ptr<tree_statement_list>\n        stmt_list = m_parser->statement_list ();\n\n      if (stmt_list)\n        {\n          command_editor::increment_current_command_number ();\n\n          eval (stmt_list, m_interpreter.interactive ());\n\n          evmgr.set_workspace ();\n        }\n      else if (m_parser->at_end_of_input ())\n        m_exit_status = EOF;\n    }\n  else\n    incomplete_parse = true;\n\n  // FIXME: Should we be checking m_exit_status or incomplete_parse or\n  // both here?  Could EOF have a value other than -1, and is there\n  // possible confusion between that state and the parser returning -1?\n\n  if (m_exit_status == -1)\n    m_exit_status = 0;\n  else\n    m_parser->reset ();\n\n  evmgr.pre_input_event ();\n}\n\nvoid\ntree_evaluator::get_line_and_eval ()\n{\n  std::mutex mtx;\n  std::unique_lock<std::mutex> lock (mtx);\n  std::condition_variable cv;\n  bool incomplete_parse = false;\n  bool evaluation_pending = false;\n  bool exiting = false;\n\n  event_manager& evmgr = m_interpreter.get_event_manager ();\n\n  while (true)\n    {\n      // FIXME: Detect EOF?  Use readline?  If\n      // so, then we need to disable idle event loop hook function\n      // execution.\n\n      std::string ps\n        = incomplete_parse ? m_interpreter.PS2 () : m_interpreter.PS1 ();\n\n      std::cout << command_editor::decode_prompt_string (ps);\n\n      std::string input;\n      std::getline (std::cin, input);\n\n      if (input.empty ())\n        continue;\n\n      incomplete_parse = false;\n      evaluation_pending = true;\n      exiting = false;\n\n      evmgr.post_event\n        ([this, input, &mtx, &incomplete_parse, &evaluation_pending, &cv, &exiting] (interpreter& interp)\n         {\n           // INTERPRETER THREAD\n\n           std::lock_guard<std::mutex> local_lock (mtx);\n\n           try\n             {\n               interp.parse_and_execute (input, incomplete_parse);\n             }\n           catch (const exit_exception&)\n             {\n               evaluation_pending = false;\n               exiting = true;\n               cv.notify_all ();\n               throw;\n             }\n           catch (const execution_exception& ee)\n             {\n               error_system& es = interp.get_error_system ();\n\n               es.save_exception (ee);\n               es.display_exception (ee);\n\n               if (interp.interactive ())\n                 {\n                   interp.recover_from_exception ();\n                   m_parser->reset ();\n                   evaluation_pending = false;\n                   cv.notify_all ();\n                 }\n               else\n                 {\n                   evaluation_pending = false;\n                   cv.notify_all ();\n                   throw exit_exception (1);\n                 }\n             }\n           catch (...)\n             {\n               evaluation_pending = false;\n               cv.notify_all ();\n               throw;\n             }\n\n           evaluation_pending = false;\n           cv.notify_all ();\n         });\n\n      // Wait until evaluation is finished before prompting for input\n      // again.\n\n      cv.wait (lock, [&evaluation_pending] { return ! evaluation_pending; });\n\n      if (exiting)\n        break;\n    }\n}\n\nint\ntree_evaluator::repl ()\n{\n  // The big loop.  Read, Eval, Print, Loop.  Normally user\n  // interaction at the command line in a terminal session, but we may\n  // also end up here when reading from a pipe or when stdin is\n  // connected to a file by the magic of input redirection.\n\n  int exit_status = 0;\n\n  // FIXME: should this choice be a command-line option?  Note that we\n  // intend that the push parser interface only be used for\n  // interactive sessions.\n\n#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)\n  static bool use_command_line_push_parser = true;\n#else\n  static bool use_command_line_push_parser = false;\n#endif\n\n  // The following logic is written as it is to allow easy transition\n  // to setting USE_COMMAND_LINE_PUSH_PARSER at run time and to\n  // simplify the logic of the main loop below by using the same\n  // base_parser::run interface for both push and pull parsers.\n\n  std::shared_ptr<base_parser> repl_parser;\n\n  if (m_interpreter.interactive ())\n    {\n      if (use_command_line_push_parser)\n        {\n          push_parser *pp\n            = new push_parser (m_interpreter,\n                               new input_reader (m_interpreter));\n\n          repl_parser = std::shared_ptr<base_parser> (pp);\n        }\n      else\n        {\n          parser *pp = new parser (new lexer (m_interpreter));\n          repl_parser = std::shared_ptr<base_parser> (pp);\n        }\n    }\n  else\n    {\n      parser *pp = new parser (new lexer (stdin, m_interpreter));\n      repl_parser = std::shared_ptr<base_parser> (pp);\n    }\n\n  do\n    {\n      try\n        {\n          unwind_protect_var<bool> upv (m_in_top_level_repl, true);\n\n          repl_parser->reset ();\n\n          if (at_top_level ())\n            {\n              dbstep_flag (0);\n              reset_debug_state ();\n            }\n\n          exit_status = repl_parser->run ();\n\n          if (exit_status == 0)\n            {\n              std::shared_ptr<tree_statement_list>\n                stmt_list = repl_parser->statement_list ();\n\n              if (stmt_list)\n                {\n                  command_editor::increment_current_command_number ();\n\n                  eval (stmt_list, m_interpreter.interactive ());\n                }\n              else if (repl_parser->at_end_of_input ())\n                {\n                  exit_status = EOF;\n                  break;\n                }\n            }\n        }\n      catch (const interrupt_exception&)\n        {\n          m_interpreter.recover_from_exception ();\n\n          // Required newline when the user does Ctrl+C at the prompt.\n          if (m_interpreter.interactive ())\n            octave_stdout << \"\\n\";\n        }\n      catch (const index_exception& ie)\n        {\n          m_interpreter.recover_from_exception ();\n\n          std::cerr << \"error: unhandled index exception: \"\n                    << ie.message () << \" -- trying to return to prompt\"\n                    << std::endl;\n        }\n      catch (const execution_exception& ee)\n        {\n          error_system& es = m_interpreter.get_error_system ();\n\n          es.save_exception (ee);\n          es.display_exception (ee);\n\n          if (m_interpreter.interactive ())\n            m_interpreter.recover_from_exception ();\n          else\n            {\n              // We should exit with a nonzero status.\n              exit_status = 1;\n              break;\n            }\n        }\n      catch (const quit_debug_exception&)\n        {\n          m_interpreter.recover_from_exception ();\n\n          // FIXME: Does anything else need to happen here?\n        }\n      catch (const std::bad_alloc&)\n        {\n          m_interpreter.recover_from_exception ();\n\n          std::cerr << \"error: out of memory -- trying to return to prompt\"\n                    << std::endl;\n        }\n    }\n  while (exit_status == 0);\n\n  if (exit_status == EOF)\n    {\n      if (m_interpreter.interactive ())\n        octave_stdout << \"\\n\";\n\n      exit_status = 0;\n    }\n\n  return exit_status;\n}\n\nint\ntree_evaluator::server_loop ()\n{\n  // Process events from the event queue.\n\n  unwind_protect_var<bool> upv1 (m_server_mode, true);\n\n  m_exit_status = 0;\n\n  std::shared_ptr<push_parser> parser (new push_parser (m_interpreter));\n  unwind_protect_var<std::shared_ptr<push_parser>> upv2 (m_parser, parser);\n\n  // FIXME: We are currently resetting the parser after every call to\n  // recover_from_exception.  This action should probably be handled\n  // in a more consistent way, but resetting the parser in every call\n  // to interpreter::recover_from_exception appears to cause\n  // segfaults in the test suite.\n\n  do\n    {\n      try\n        {\n          // FIXME: Should we call octave_quit in the octave::sleep\n          // and/or command_editor::run_event_hooks functions?\n\n          octave_quit ();\n\n          // FIXME: Running the event queue should be decoupled from\n          // the command_editor.  We should also use a condition\n          // variable to manage the execution of entries in the queue\n          // and eliminate the need for the busy-wait loop.\n\n          command_editor::run_event_hooks ();\n\n          release_unreferenced_dynamic_libraries ();\n\n          sleep (0.1);\n        }\n      catch (const interrupt_exception&)\n        {\n          octave_interrupt_state = 1;\n          m_interpreter.recover_from_exception ();\n          m_parser->reset ();\n\n          // Required newline when the user does Ctrl+C at the prompt.\n          if (m_interpreter.interactive ())\n            octave_stdout << \"\\n\";\n        }\n      catch (const index_exception& e)\n        {\n          m_interpreter.recover_from_exception ();\n          m_parser->reset ();\n\n          std::cerr << \"error: unhandled index exception: \"\n                    << e.message () << \" -- trying to return to prompt\"\n                    << std::endl;\n        }\n      catch (const execution_exception& ee)\n        {\n          error_system& es = m_interpreter.get_error_system ();\n\n          es.save_exception (ee);\n          es.display_exception (ee);\n\n          if (m_interpreter.interactive ())\n            {\n              m_interpreter.recover_from_exception ();\n              m_parser->reset ();\n            }\n          else\n            {\n              // We should exit with a nonzero status.\n              m_exit_status = 1;\n              break;\n            }\n        }\n      catch (const quit_debug_exception&)\n        {\n          octave_interrupt_state = 1;\n          m_interpreter.recover_from_exception ();\n          m_parser->reset ();\n        }\n      catch (const exit_exception& xe)\n        {\n          m_exit_status = xe.exit_status ();\n          break;\n        }\n      catch (const std::bad_alloc&)\n        {\n          m_interpreter.recover_from_exception ();\n          m_parser->reset ();\n\n          std::cerr << \"error: out of memory -- trying to return to prompt\"\n                    << std::endl;\n        }\n    }\n  while (m_exit_status == 0);\n\n  if (m_exit_status == EOF)\n    {\n      if (m_interpreter.interactive ())\n        octave_stdout << \"\\n\";\n\n      m_exit_status = 0;\n    }\n\n  return m_exit_status;\n}\n\nvoid\ntree_evaluator::eval (std::shared_ptr<tree_statement_list>& stmt_list,\n                      bool interactive)\n{\n  try\n    {\n      stmt_list->accept (*this);\n\n      octave_quit ();\n\n      if (! interactive)\n        {\n          bool quit = (m_returning || m_breaking);\n\n          if (m_returning)\n            m_returning = 0;\n\n          if (m_breaking)\n            m_breaking--;\n\n          if (quit)\n            return;\n        }\n\n      if (octave_completion_matches_called)\n        octave_completion_matches_called = false;\n    }\n  catch (const quit_debug_exception&)\n    {\n      m_interpreter.recover_from_exception ();\n    }\n}\n\noctave_value_list\ntree_evaluator::eval_string (const std::string& eval_str, bool silent,\n                             int& parse_status, int nargout)\n{\n  octave_value_list retval;\n\n  parser eval_parser (eval_str, m_interpreter);\n\n  do\n    {\n      eval_parser.reset ();\n\n      // If we are looking at\n      //\n      //   val = eval (\"code\");\n      //\n      // then don't allow code to be parsed as a command.\n\n      if (nargout > 0)\n        eval_parser.disallow_command_syntax ();\n\n      parse_status = eval_parser.run ();\n\n      if (parse_status == 0)\n        {\n          std::shared_ptr<tree_statement_list> stmt_list\n            = eval_parser.statement_list ();\n\n          if (stmt_list)\n            {\n              tree_statement *stmt = nullptr;\n\n              if (stmt_list->size () == 1\n                  && (stmt = stmt_list->front ())\n                  && stmt->is_expression ())\n                {\n                  tree_expression *expr = stmt->expression ();\n\n                  if (silent)\n                    expr->set_print_flag (false);\n\n                  retval = expr->evaluate_n (*this, nargout);\n\n                  bool do_bind_ans = false;\n\n                  if (expr->is_identifier ())\n                    do_bind_ans = ! is_variable (expr);\n                  else\n                    do_bind_ans = ! expr->is_assignment_expression ();\n\n                  if (nargout == 0 && do_bind_ans && ! retval.empty ())\n                    bind_ans (retval(0), expr->print_result ());\n\n                  if (nargout == 0)\n                    retval = octave_value_list ();\n                }\n              else if (nargout == 0)\n                stmt_list->accept (*this);\n              else\n                error (\"eval: invalid use of statement list\");\n\n              if (returning () || breaking () || continuing ())\n                break;\n            }\n          else if (eval_parser.at_end_of_input ())\n            break;\n        }\n    }\n  while (parse_status == 0);\n\n  return retval;\n}\n\noctave_value\ntree_evaluator::eval_string (const std::string& eval_str,\n                             bool silent, int& parse_status)\n{\n  octave_value retval;\n\n  octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1);\n\n  if (! tmp.empty ())\n    retval = tmp(0);\n\n  return retval;\n}\n\noctave_value_list\ntree_evaluator::eval_string (const octave_value& arg,\n                             bool silent, int& parse_status,\n                             int nargout)\n{\n  std::string s = arg.xstring_value (\"eval: expecting string argument\");\n\n  return eval_string (s, silent, parse_status, nargout);\n}\n\noctave_value_list\ntree_evaluator::eval (const std::string& try_code,\n                      int nargout)\n{\n  int parse_status = 0;\n\n  return eval_string (try_code, nargout > 0, parse_status, nargout);\n}\n\noctave_value_list\ntree_evaluator::eval (const std::string& try_code,\n                      const std::string& catch_code,\n                      int nargout)\n{\n  octave_value_list retval;\n\n  error_system& es = m_interpreter.get_error_system ();\n\n  int parse_status = 0;\n\n  bool execution_error = false;\n\n  octave_value_list tmp;\n\n  try\n    {\n      tmp = eval_string (try_code, nargout > 0, parse_status, nargout);\n    }\n  catch (const execution_exception& ee)\n    {\n      es.save_exception (ee);\n      m_interpreter.recover_from_exception ();\n\n      execution_error = true;\n    }\n\n  if (parse_status != 0 || execution_error)\n    {\n      tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);\n\n      retval = (nargout > 0) ? tmp : octave_value_list ();\n    }\n  else\n    {\n      if (nargout > 0)\n        retval = tmp;\n\n      // FIXME: we should really be rethrowing whatever\n      // exception occurred, not just throwing an\n      // execution exception.\n      if (execution_error)\n        throw execution_exception ();\n    }\n\n  return retval;\n}\n\noctave_value_list\ntree_evaluator::evalin (const std::string& context,\n                        const std::string& try_code,\n                        int nargout)\n{\n  unwind_action act ([this] (std::size_t frm)\n                     {\n                       m_call_stack.restore_frame (frm);\n                     }, m_call_stack.current_frame ());\n\n  if (context == \"caller\")\n    m_call_stack.goto_caller_frame ();\n  else if (context == \"base\")\n    m_call_stack.goto_base_frame ();\n  else\n    error (R\"(evalin: CONTEXT must be \"caller\" or \"base\")\");\n\n  int parse_status = 0;\n\n  return eval_string (try_code, nargout > 0, parse_status, nargout);\n}\n\noctave_value_list\ntree_evaluator::evalin (const std::string& context,\n                        const std::string& try_code,\n                        const std::string& catch_code,\n                        int nargout)\n{\n  octave_value_list retval;\n\n  unwind_action act1 ([this] (std::size_t frm)\n                      {\n                        m_call_stack.restore_frame (frm);\n                      }, m_call_stack.current_frame ());\n\n  if (context == \"caller\")\n    m_call_stack.goto_caller_frame ();\n  else if (context == \"base\")\n    m_call_stack.goto_base_frame ();\n  else\n    error (R\"(evalin: CONTEXT must be \"caller\" or \"base\")\");\n\n  error_system& es = m_interpreter.get_error_system ();\n\n  int parse_status = 0;\n\n  bool execution_error = false;\n\n  octave_value_list tmp;\n\n  try\n    {\n      tmp = eval_string (try_code, nargout > 0, parse_status, nargout);\n    }\n  catch (const execution_exception& ee)\n    {\n      es.save_exception (ee);\n      m_interpreter.recover_from_exception ();\n\n      execution_error = true;\n    }\n\n  if (parse_status != 0 || execution_error)\n    {\n      tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);\n\n      retval = (nargout > 0) ? tmp : octave_value_list ();\n    }\n  else\n    {\n      if (nargout > 0)\n        retval = tmp;\n\n      // FIXME: we should really be rethrowing whatever\n      // exception occurred, not just throwing an\n      // execution exception.\n      if (execution_error)\n        throw execution_exception ();\n    }\n\n  return retval;\n}\n\nvoid\ntree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&)\n{\n  error_unexpected (\"tree_evaluator::visit_anon_fcn_handle\");\n}\n\nvoid\ntree_evaluator::visit_argument_list (tree_argument_list&)\n{\n  error_unexpected (\"tree_evaluator::visit_argument_list\");\n}\n\nvoid\ntree_evaluator::visit_arguments_block (tree_arguments_block&)\n{\n  warning (\"function arguments validation blocks are not yet implemented; INCORRECT RESULTS ARE POSSIBLE\");\n}\n\nvoid\ntree_evaluator::visit_args_block_attribute_list (tree_args_block_attribute_list&)\n{\n  error_unexpected (\"tree_evaluator::visit_args_block_attribute_list\");\n}\n\nvoid\ntree_evaluator::visit_args_block_validation_list (tree_args_block_validation_list&)\n{\n  error_unexpected (\"tree_evaluator::visit_args_block_validation_list\");\n}\n\nvoid\ntree_evaluator::visit_arg_validation (tree_arg_validation&)\n{\n  error_unexpected (\"tree_evaluator::visit_arg_validation\");\n}\n\nvoid\ntree_evaluator::visit_arg_size_spec (tree_arg_size_spec&)\n{\n  error_unexpected (\"tree_evaluator::visit_arg_size_spec\");\n}\n\nvoid\ntree_evaluator::visit_arg_validation_fcns (tree_arg_validation_fcns&)\n{\n  error_unexpected (\"tree_evaluator::visit_arg_validation_fcns\");\n}\n\nvoid\ntree_evaluator::visit_binary_expression (tree_binary_expression&)\n{\n  error_unexpected (\"tree_evaluator::visit_binary_expression\");\n}\n\nvoid\ntree_evaluator::visit_boolean_expression (tree_boolean_expression&)\n{\n  error_unexpected (\"tree_evaluator::visit_boolean_expression\");\n}\n\nvoid\ntree_evaluator::visit_compound_binary_expression (tree_compound_binary_expression&)\n{\n  error_unexpected (\"tree_evaluator::visit_compound_binary_expression\");\n}\n\nvoid\ntree_evaluator::visit_break_command (tree_break_command& cmd)\n{\n  if (m_echo_state)\n    {\n      int line = cmd.line ();\n      if (line < 0)\n        line = 1;\n      echo_code (line);\n      m_echo_file_pos = line + 1;\n    }\n\n  if (m_debug_mode)\n    do_breakpoint (cmd.is_active_breakpoint (*this));\n\n  if (m_in_loop_command)\n    m_breaking = 1;\n  else\n    error (\"break must appear in a loop in the same file as loop command\");\n}\n\nvoid\ntree_evaluator::visit_colon_expression (tree_colon_expression&)\n{\n  error_unexpected (\"tree_evaluator::visit_colon_expression\");\n}\n\nvoid\ntree_evaluator::visit_continue_command (tree_continue_command& cmd)\n{\n  if (m_echo_state)\n    {\n      int line = cmd.line ();\n      if (line < 0)\n        line = 1;\n      echo_code (line);\n      m_echo_file_pos = line + 1;\n    }\n\n  if (m_debug_mode)\n    do_breakpoint (cmd.is_active_breakpoint (*this));\n\n  if (m_in_loop_command)\n    m_continuing = 1;\n}\n\nbool\ntree_evaluator::statement_printing_enabled ()\n{\n  return ! (m_silent_functions && (m_statement_context == SC_FUNCTION\n                                   || m_statement_context == SC_SCRIPT));\n}\n\nvoid\ntree_evaluator::reset_debug_state ()\n{\n  m_debug_mode = (m_bp_table.have_breakpoints ()\n                  || m_dbstep_flag != 0\n                  || m_break_on_next_stmt\n                  || in_debug_repl ());\n}\n\nvoid\ntree_evaluator::reset_debug_state (bool mode)\n{\n  m_debug_mode = mode;\n}\n\nvoid\ntree_evaluator::enter_debugger (const std::string& prompt)\n{\n  unwind_protect frame;\n\n  frame.add (command_history::ignore_entries,\n             command_history::ignoring_entries ());\n\n  command_history::ignore_entries (false);\n\n  frame.add (&call_stack::restore_frame, &m_call_stack,\n             m_call_stack.current_frame ());\n\n  // Don't allow errors or warnings at the debug prompt to push us\n  // into deeper levels of debugging.\n\n  error_system& es = m_interpreter.get_error_system ();\n\n  frame.add (&error_system::set_debug_on_error, &es, es.debug_on_error ());\n\n  frame.add (&error_system::set_debug_on_warning, &es,\n             es.debug_on_warning ());\n\n  es.debug_on_error (false);\n  es.debug_on_warning (false);\n\n  // Go up to the nearest user code frame.\n\n  tree_evaluator& tw = m_interpreter.get_evaluator ();\n\n  frame.add ([&tw, saved_frame = m_debug_frame] ()\n  {\n    if (! tw.dbstep_flag ())\n      tw.debug_frame (saved_frame);\n  });\n\n  m_debug_frame = m_call_stack.dbupdown (0);\n\n  // FIXME: probably we just want to print one line, not the\n  // entire statement, which might span many lines...\n  //\n  // tree_print_code tpc (octave_stdout);\n  // stmt.accept (tpc);\n\n  debugger *dbgr = new debugger (m_interpreter, m_debugger_stack.size ());\n\n  m_debugger_stack.push (dbgr);\n\n  frame.add ([this] ()\n             {\n               delete m_debugger_stack.top ();\n               m_debugger_stack.pop ();\n               reset_debug_state ();\n             });\n\n  dbgr->repl (prompt);\n}\n\nvoid\ntree_evaluator::keyboard (const std::string& prompt)\n{\n  enter_debugger (prompt);\n}\n\nvoid\ntree_evaluator::dbupdown (int n, bool verbose)\n{\n  m_debug_frame = m_call_stack.dbupdown (n, verbose);\n}\n\nstd::string tree_evaluator::inputname (int n, bool ids_only) const\n{\n  std::shared_ptr<stack_frame> frame = m_call_stack.current_user_frame ();\n\n  return frame->inputname (n, ids_only);\n}\n\nMatrix\ntree_evaluator::ignored_fcn_outputs () const\n{\n  Matrix retval;\n\n  const std::list<octave_lvalue> *lvalues = m_lvalue_list;\n\n  if (! lvalues)\n    return retval;\n\n  octave_idx_type nbh = 0;\n\n  for (const auto& lval : *lvalues)\n    nbh += lval.is_black_hole ();\n\n  if (nbh > 0)\n    {\n      retval.resize (1, nbh);\n\n      octave_idx_type k = 0;\n      octave_idx_type l = 0;\n\n      for (const auto& lval : *lvalues)\n        {\n          if (lval.is_black_hole ())\n            retval(l++) = k+1;\n\n          k += lval.numel ();\n        }\n    }\n\n  return retval;\n}\n\n// If NAME is an operator (like \"+\", \"-\", ...), convert it to the\n// corresponding function name (\"plus\", \"minus\", ...).\n\nstatic std::string\nget_operator_function_name (const std::string& name)\n{\n  // Bow to the god of compatibility.\n\n  // FIXME: it seems ugly to put this here, but there is no single\n  // function in the parser that converts from the operator name to\n  // the corresponding function name.  At least try to do it without N\n  // string compares.\n\n  std::size_t len = name.length ();\n\n  if (len == 2)\n    {\n      if (name[0] == '.')\n        {\n          switch (name[1])\n            {\n            case '\\'':\n              return \"transpose\";\n\n            case '*':\n              return \"times\";\n\n            case '/':\n              return \"rdivide\";\n\n            case '^':\n              return \"power\";\n\n            case '\\\\':\n              return \"ldivide\";\n\n            default:\n              break;\n            }\n        }\n      else if (name[1] == '=')\n        {\n          switch (name[0])\n            {\n            case '<':\n              return \"le\";\n\n            case '=':\n              return \"eq\";\n\n            case '>':\n              return \"ge\";\n\n            case '~':\n            case '!':\n              return \"ne\";\n\n            default:\n              break;\n            }\n        }\n    }\n  else if (len == 1)\n    {\n      switch (name[0])\n        {\n        case '~':\n        case '!':\n          return \"not\";\n\n        case '\\'':\n          return \"ctranspose\";\n\n        case '+':\n          return \"plus\";\n\n        case '-':\n          return \"minus\";\n\n        case '*':\n          return \"mtimes\";\n\n        case '/':\n          return \"mrdivide\";\n\n        case '^':\n          return \"mpower\";\n\n        case '\\\\':\n          return \"mldivide\";\n\n        case '<':\n          return \"lt\";\n\n        case '>':\n          return \"gt\";\n\n        case '&':\n          return \"and\";\n\n        case '|':\n          return \"or\";\n\n        default:\n          break;\n        }\n    }\n\n  return name;\n}\n\n// Creates a function handle that takes into account the context,\n// finding local, nested, private, or sub functions.\n\noctave_value\ntree_evaluator::make_fcn_handle (const std::string& name)\n{\n  octave_value retval;\n\n  // The str2func function can create a function handle with the name\n  // of an operator (for example, \"+\").  If so, it is converted to the\n  // name of the corresponding function (\"+\" -> \"plus\") and we create\n  // a simple function handle using that name.\n\n  std::string fcn_name = get_operator_function_name (name);\n\n  // If FCN_NAME is different from NAME, then NAME is an operator.  As\n  // of version 2020a, Matlab apparently uses the function name\n  // corresponding to the operator to search for private and local\n  // functions in the current scope but not(!) nested functions.\n\n  bool name_is_operator = fcn_name != name;\n\n  std::size_t pos = fcn_name.find ('.');\n\n  if (pos != std::string::npos)\n    {\n      // Recognize (some of?  which ones?) the following cases\n      // and create something other than a simple function handle?\n      // Should we just be checking for the last two when the first\n      // element of the dot-separated list is an object?  If so, then\n      // should this syntax be limited to a dot-separated list with\n      // exactly two elements?\n      //\n      //   object . method\n      //   object . static-method\n      //\n      // Code to do that duplicates some of simple_fcn_handle::call.\n\n      // Only accept expressions that contain one '.' separator.\n\n      // FIXME: The logic here is a bit complicated.  Is there a good\n      // way to simplify it?\n\n      std::string meth_nm = fcn_name.substr (pos+1);\n\n      if (meth_nm.find ('.') == std::string::npos)\n        {\n          std::string obj_nm = fcn_name.substr (0, pos);\n\n          // If obj_nm is an object in the current scope with a\n          // method named meth_nm, create a classsimple handle.\n\n          octave_value object = varval (obj_nm);\n\n          if (object.is_defined () && object.is_classdef_object ())\n            {\n              octave_classdef *cdef = object.classdef_object_value ();\n\n              if (cdef)\n                {\n                  std::string class_nm = cdef->class_name ();\n\n                  cdef_object cdef_obj = cdef->get_object ();\n\n                  cdef_class cls = cdef_obj.get_class ();\n\n                  cdef_method meth = cls.find_method (meth_nm);\n\n                  if (meth.ok ())\n                    {\n                      // If the method we found is static, create a\n                      // new function name from the class name and\n                      // method name and create a simple function\n                      // handle below.  Otherwise, create a class\n                      // simple function handle.\n\n                      if (meth.is_static ())\n                        fcn_name = class_nm + '.' + meth_nm;\n                      else\n                        {\n                          octave_value meth_fcn = meth.get_function ();\n\n                          octave_fcn_handle *fh\n                            = new octave_fcn_handle (object, meth_fcn,\n                                                     class_nm, meth_nm);\n\n                          return octave_value (fh);\n                        }\n                    }\n                }\n            }\n        }\n\n      // We didn't match anything above, so create handle to SIMPLE\n      // package function or static class method.  Function resolution\n      // is performed when the handle is used.\n\n      return octave_value (new octave_fcn_handle (fcn_name));\n    }\n\n  // If the function name refers to a sub/local/private function or a\n  // class method/constructor, create scoped function handle that is\n  // bound to that function.  Use the same precedence list as\n  // fcn_info::find but limit search to the following types of\n  // functions:\n  //\n  //   nested functions (and subfunctions)\n  //   local functions in the current file\n  //   private function\n  //   class method\n  //\n  // For anything else we create a simple function handle that will be\n  // resolved dynamically in the scope where it is evaluated.\n\n  symbol_scope curr_scope = get_current_scope ();\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  if (curr_scope)\n    {\n      octave_value ov_fcn\n        = symtab.find_scoped_function (fcn_name, curr_scope);\n\n      // If name is operator, we are in Fstr2func, so skip the stack\n      // frame for that function.\n\n      bool skip_first = name_is_operator;\n      octave_function *curr_fcn = current_function (skip_first);\n\n      if (ov_fcn.is_defined ())\n        {\n          octave_function *fcn = ov_fcn.function_value ();\n\n          if (fcn->is_nested_function ())\n            {\n              if (! name_is_operator)\n                {\n                  // Get current stack frame and return handle to nested\n                  // function.\n\n                  std::shared_ptr<stack_frame> frame\n                    = m_call_stack.get_current_stack_frame ();\n\n                  // If we are creating a handle to the current\n                  // function or a handle to a sibling function (i.e.,\n                  // not a child of the current function), then use\n                  // the calling stack frame as the context instead of\n                  // the current stack frame.\n\n                  // FIXME: Do we need both checks here or is it\n                  // sufficient to check that the parent of curr_fcn\n                  // is the same as the parent of fcn?  Is there any\n                  // case where curr_fcn could be nullptr, or does\n                  // that indicate an internal error of some kind?\n\n                  if (curr_fcn\n                      && (fcn_name == curr_fcn->name ()\n                          || fcn->parent_fcn_name () == curr_fcn->parent_fcn_name ()))\n                    frame = frame->access_link ();\n\n                  octave_fcn_handle *fh\n                    = new octave_fcn_handle (ov_fcn, fcn_name, frame);\n\n                  return octave_value (fh);\n                }\n            }\n          else if (fcn->is_subfunction ()\n                   /* || fcn->is_localfunction () */\n                   || fcn->is_private_function ())\n            {\n              // Create handle to SCOPED function (sub/local function\n              // or private function).\n\n              std::list<std::string> parentage = fcn->parent_fcn_names ();\n\n              octave_fcn_handle *fh\n                = new octave_fcn_handle (ov_fcn, fcn_name, parentage);\n\n              return octave_value (fh);\n            }\n        }\n\n      if (curr_fcn && (curr_fcn->is_class_method ()\n                       || curr_fcn->is_class_constructor ()))\n        {\n          std::string dispatch_class = curr_fcn->dispatch_class ();\n\n          octave_value ov_meth\n            = symtab.find_method (fcn_name, dispatch_class);\n\n          if (ov_meth.is_defined ())\n            {\n              octave_function *fcn = ov_meth.function_value ();\n\n              // FIXME: do we need to check that it is a method of\n              // dispatch_class, or is it sufficient to just check\n              // that it is a method?\n\n              if (fcn->is_class_method ())\n                {\n                  // Create CLASSSIMPLE handle to method but don't\n                  // bind to the method.  Lookup will be done later.\n\n                  octave_fcn_handle *fh\n                    = new octave_fcn_handle (dispatch_class, fcn_name);\n\n                  return octave_value (fh);\n                }\n            }\n        }\n    }\n\n  octave_value ov_fcn = symtab.find_user_function (fcn_name);\n\n  // Create handle to SIMPLE function.  If the function is not found\n  // now, then we will look for it again when the handle is used.\n\n  return octave_value (new octave_fcn_handle (ov_fcn, fcn_name));\n}\n\n/*\n%!test\n%! x = {\".'\", \"transpose\";\n%!      \".*\", \"times\";\n%!      \"./\", \"rdivide\";\n%!      \".^\", \"power\";\n%!      \".\\\\\", \"ldivide\";\n%!      \"<=\", \"le\";\n%!      \"==\", \"eq\";\n%!      \">=\", \"ge\";\n%!      \"!=\", \"ne\";\n%!      \"~=\", \"ne\";\n%!      \"~\", \"not\";\n%!      \"!\", \"not\";\n%!      \"\\'\", \"ctranspose\";\n%!      \"+\", \"plus\";\n%!      \"-\", \"minus\";\n%!      \"*\", \"mtimes\";\n%!      \"/\", \"mrdivide\";\n%!      \"^\", \"mpower\";\n%!      \"\\\\\", \"mldivide\";\n%!      \"<\", \"lt\";\n%!      \">\", \"gt\";\n%!      \"&\", \"and\";\n%!      \"|\", \"or\"};\n%! for i = 1:rows (x)\n%!   assert (functions (str2func (x{i,1})).function, x{i,2});\n%! endfor\n*/\n\noctave_value\ntree_evaluator::evaluate (tree_decl_elt *elt)\n{\n  // Do not allow functions to return null values.\n\n  tree_identifier *id = elt->ident ();\n\n  return id ? id->evaluate (*this).storable_value () : octave_value ();\n}\n\nbool\ntree_evaluator::is_variable (const std::string& name) const\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  return frame->is_variable (name);\n}\n\nbool\ntree_evaluator::is_local_variable (const std::string& name) const\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  return frame->is_local_variable (name);\n}\n\nbool\ntree_evaluator::is_variable (const tree_expression *expr) const\n{\n  if (expr->is_identifier ())\n    {\n      const tree_identifier *id\n        = dynamic_cast<const tree_identifier *> (expr);\n\n      if (id->is_black_hole ())\n        return false;\n\n      return is_variable (id->symbol ());\n    }\n\n  return false;\n}\n\nbool\ntree_evaluator::is_defined (const tree_expression *expr) const\n{\n  if (expr->is_identifier ())\n    {\n      const tree_identifier *id\n        = dynamic_cast<const tree_identifier *> (expr);\n\n      return is_defined (id->symbol ());\n    }\n\n  return false;\n}\n\nbool\ntree_evaluator::is_variable (const symbol_record& sym) const\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  return frame->is_variable (sym);\n}\n\nbool\ntree_evaluator::is_defined (const symbol_record& sym) const\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  return frame->is_defined (sym);\n}\n\nbool\ntree_evaluator::is_global (const std::string& name) const\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  return frame->is_global (name);\n}\n\noctave_value\ntree_evaluator::varval (const symbol_record& sym) const\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  return frame->varval (sym);\n}\n\noctave_value\ntree_evaluator::varval (const std::string& name) const\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  return frame->varval (name);\n}\n\nvoid\ntree_evaluator::install_variable (const std::string& name,\n                                  const octave_value& value,\n                                  bool global)\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  return frame->install_variable (name, value, global);\n}\n\noctave_value\ntree_evaluator::global_varval (const std::string& name) const\n{\n  return m_call_stack.global_varval (name);\n}\n\noctave_value&\ntree_evaluator::global_varref (const std::string& name)\n{\n  return m_call_stack.global_varref (name);\n}\n\nvoid\ntree_evaluator::global_assign (const std::string& name,\n                               const octave_value& val)\n{\n  m_call_stack.global_varref (name) = val;\n}\n\noctave_value\ntree_evaluator::top_level_varval (const std::string& name) const\n{\n  return m_call_stack.get_top_level_value (name);\n}\n\nvoid\ntree_evaluator::top_level_assign (const std::string& name,\n                                  const octave_value& val)\n{\n  m_call_stack.set_top_level_value (name, val);\n}\n\nvoid\ntree_evaluator::assign (const std::string& name, const octave_value& val)\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  frame->assign (name, val);\n}\n\nvoid\ntree_evaluator::assignin (const std::string& context,\n                          const std::string& name, const octave_value& val)\n{\n  // FIXME: Can this be done without an unwind-protect frame, simply\n  // by getting a reference to the caller or base stack frame and\n  // calling assign on that?\n\n  unwind_action act ([this] (std::size_t frm)\n                     {\n                       m_call_stack.restore_frame (frm);\n                     }, m_call_stack.current_frame ());\n\n  if (context == \"caller\")\n    m_call_stack.goto_caller_frame ();\n  else if (context == \"base\")\n    m_call_stack.goto_base_frame ();\n  else\n    error (R\"(assignin: CONTEXT must be \"caller\" or \"base\")\");\n\n  if (valid_identifier (name))\n    {\n      // Put the check here so that we don't slow down assignments\n      // generally.  Any that go through Octave's parser should have\n      // already been checked.\n\n      if (iskeyword (name))\n        error (\"assignin: invalid assignment to keyword '%s'\",\n               name.c_str ());\n\n      assign (name, val);\n    }\n  else\n    error (\"assignin: invalid variable name '%s'\", name.c_str ());\n}\n\nvoid\ntree_evaluator::source_file (const std::string& file_name,\n                             const std::string& context,\n                             bool verbose, bool require_file)\n{\n  // Map from absolute name of script file to recursion level.  We\n  // use a map instead of simply placing a limit on recursion in the\n  // source_file function so that two mutually recursive scripts\n  // written as\n  //\n  //   foo1.m:\n  //   ------\n  //   foo2\n  //\n  //   foo2.m:\n  //   ------\n  //   foo1\n  //\n  // and called with\n  //\n  //   foo1\n  //\n  // (for example) will behave the same if they are written as\n  //\n  //   foo1.m:\n  //   ------\n  //   source (\"foo2.m\")\n  //\n  //   foo2.m:\n  //   ------\n  //   source (\"foo1.m\")\n  //\n  // and called with\n  //\n  //   source (\"foo1.m\")\n  //\n  // (for example).\n\n  static std::map<std::string, int> source_call_depth;\n\n  std::string file_full_name\n    = sys::file_ops::tilde_expand (file_name);\n\n  std::size_t pos\n    = file_full_name.find_last_of (sys::file_ops::dir_sep_str ());\n\n  std::string dir_name = file_full_name.substr (0, pos);\n\n  file_full_name = sys::env::make_absolute (file_full_name);\n\n  unwind_protect frame;\n\n  if (source_call_depth.find (file_full_name) == source_call_depth.end ())\n    source_call_depth[file_full_name] = -1;\n\n  frame.protect_var (source_call_depth[file_full_name]);\n\n  source_call_depth[file_full_name]++;\n\n  if (source_call_depth[file_full_name] >= max_recursion_depth ())\n    error (\"max_recursion_depth exceeded\");\n\n  if (! context.empty ())\n    {\n      frame.add (&call_stack::restore_frame, &m_call_stack,\n                 m_call_stack.current_frame ());\n\n      if (context == \"caller\")\n        m_call_stack.goto_caller_frame ();\n      else if (context == \"base\")\n        m_call_stack.goto_base_frame ();\n      else\n        error (R\"(source: CONTEXT must be \"caller\" or \"base\")\");\n    }\n\n  // Find symbol name that would be in symbol_table, if it were loaded.\n  std::size_t dir_end\n    = file_name.find_last_of (sys::file_ops::dir_sep_chars ());\n  dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1;\n\n  std::size_t extension = file_name.find_last_of ('.');\n  if (extension == std::string::npos)\n    extension = file_name.length ();\n\n  std::string symbol = file_name.substr (dir_end, extension - dir_end);\n  std::string full_name = sys::canonicalize_file_name (file_name);\n\n  // Check if this file is already loaded (or in the path)\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n  octave_value ov_code = symtab.fcn_table_find (symbol);\n\n  // For compatibility with Matlab, accept both scripts and\n  // functions.\n\n  if (ov_code.is_user_code ())\n    {\n      octave_user_code *code = ov_code.user_code_value ();\n\n      if (! code\n          || (sys::canonicalize_file_name (code->fcn_file_name ())\n              != full_name))\n        {\n          // Wrong file, so load it below.\n          ov_code = octave_value ();\n        }\n    }\n  else\n    {\n      // Not a script, so load it below.\n      ov_code = octave_value ();\n    }\n\n  // If no symbol of this name, or the symbol is for a different\n  // file, load.\n\n  if (ov_code.is_undefined ())\n    {\n      try\n        {\n          ov_code = parse_fcn_file (m_interpreter, file_full_name,\n                                    file_name, dir_name, \"\", \"\",\n                                    require_file, true, false, false);\n        }\n      catch (execution_exception& ee)\n        {\n          std::string error_message = ee.message ();\n          if (error_message.empty ())\n            error (ee, \"source: error sourcing file '%s'\",\n                   file_full_name.c_str ());\n          else\n            error (ee, \"%s\", error_message.c_str ());\n        }\n    }\n\n  // Return or error if we don't have a valid script or function.\n\n  if (ov_code.is_undefined ())\n    return;\n\n  if (! ov_code.is_user_code ())\n    error (\"source: %s is not a script\", full_name.c_str ());\n\n  if (verbose)\n    {\n      octave_stdout << \"executing commands from \" << full_name << \" ... \";\n      octave_stdout.flush ();\n    }\n\n  octave_user_code *code = ov_code.user_code_value ();\n\n  code->call (*this, 0, octave_value_list ());\n\n  if (verbose)\n    {\n      octave_stdout << \"done.\" << std::endl;\n      octave_stdout.flush ();\n    }\n}\n\nvoid\ntree_evaluator::set_auto_fcn_var (stack_frame::auto_var_type avt,\n                                  const octave_value& val)\n{\n  m_call_stack.set_auto_fcn_var (avt, val);\n}\n\nvoid\ntree_evaluator::set_nargin (int nargin)\n{\n  m_call_stack.set_nargin (nargin);\n}\n\nvoid\ntree_evaluator::set_nargout (int nargout)\n{\n  m_call_stack.set_nargout (nargout);\n}\n\noctave_value\ntree_evaluator::get_auto_fcn_var (stack_frame::auto_var_type avt) const\n{\n  return m_call_stack.get_auto_fcn_var (avt);\n}\n\nvoid\ntree_evaluator::define_parameter_list_from_arg_vector\n  (tree_parameter_list *param_list, const octave_value_list& args)\n{\n  if (! param_list || param_list->varargs_only ())\n    return;\n\n  int i = -1;\n\n  for (tree_decl_elt *elt : *param_list)\n    {\n      i++;\n\n      octave_lvalue ref = elt->lvalue (*this);\n\n      if (i < args.length ())\n        {\n          if (args(i).is_defined () && args(i).is_magic_colon ())\n            {\n              if (! eval_decl_elt (elt))\n                error (\"no default value for argument %d\", i+1);\n            }\n          else\n            ref.define (args(i));\n        }\n      else\n        eval_decl_elt (elt);\n    }\n}\n\nvoid\ntree_evaluator::undefine_parameter_list (tree_parameter_list *param_list)\n{\n  for (tree_decl_elt *elt : *param_list)\n    {\n      octave_lvalue ref = elt->lvalue (*this);\n\n      ref.assign (octave_value::op_asn_eq, octave_value ());\n    }\n}\n\nDEFMETHOD (end, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn {} {} end\nThe termination of a code block @emph{or} the last element of an array.\n\nThe keyword @code{end} is used to terminate blocks of code begun with\n@code{for}, @code{parfor}, @code{if}, @code{do}, @code{while}, @code{function},\n@code{switch}, @code{try}, or @code{unwind_protect}.\n\nWhen using classdef (object-oriented) programming, the keyword terminates blocks\nof code begun with @code{classdef}, @code{properties}, @code{methods},\n@code{events}, or @code{enumeration}.\n\nAs an index of an array, the magic index @qcode{\"end\"} refers to the last valid\nentry in an indexing operation.\n\nExamples:\n\n@example\n@group\n@var{x} = [ 1 2 3; 4 5 6 ];\n@var{x}(1,end)\n @xresult{} 3\n@var{x}(end,1)\n @xresult{} 4\n@var{x}(end,end)\n @xresult{} 6\n@end group\n@end example\n\nProgramming Notes:\n@enumerate\n@item\nThe @code{end} keyword cannot be used within @code{subsref}, @code{subsasgn}, or\n@code{substruct} for manual indexing operations.\n\n@item\nFor custom classes, enabling use of @code{end} in indexing expressions requires\nwriting an overloaded function such as:\n\n@example\n@group\nfunction last_index = end (obj, end_dim, ndim_obj)\n  if (end_dim == ndim_obj)\n    last_index = prod (size (obj)(end_dim:ndim_obj));\n  else\n    last_index = size (obj, end_dim);\n  endif\nendfunction\n@end group\n@end example\n\nFor more information, @pxref{Object Oriented Programming}.\n@end enumerate\n\n@seealso{for, parfor, if, do, while, function, switch, try, unwind_protect}\n@end deftypefn */)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.evaluate_end_expression (args);\n}\n\n/*\n%!test <*58830>\n%! fail (\"__undef_sym__ (end)\",\n%!       \"invalid use of 'end': may only be used to index existing value\");\n\n%!test <*58953>\n%! x = 1:10;\n%! assert (x(end), 10);\n%! assert (x(minus (end, 1)), 9);\n%! assert (x(minus (minus (end, 1), 1)), 8);\n*/\n\noctave_value_list\ntree_evaluator::convert_to_const_vector (tree_argument_list *args)\n{\n  std::list<octave_value> arg_vals;\n\n  for (auto elt : *args)\n    {\n      // FIXME: is it possible for elt to be invalid?\n\n      if (! elt)\n        break;\n\n      // Evaluate with unknown number of output arguments\n      octave_value tmp = elt->evaluate (*this, -1);\n\n      if (tmp.is_cs_list ())\n        {\n          octave_value_list tmp_ovl = tmp.list_value ();\n\n          for (octave_idx_type i = 0; i < tmp_ovl.length (); i++)\n            arg_vals.push_back (tmp_ovl(i));\n        }\n      else if (tmp.is_defined ())\n        arg_vals.push_back (tmp);\n    }\n\n  return octave_value_list (arg_vals);\n}\n\noctave_value_list\ntree_evaluator::convert_return_list_to_const_vector\n(tree_parameter_list *ret_list, int nargout, const Cell& varargout)\n{\n  octave_idx_type vlen = varargout.numel ();\n  int len = ret_list->size ();\n\n  // Special case.  Will do a shallow copy.\n  if (len == 0)\n    return varargout;\n  else\n    {\n      int i = 0;\n\n      if (nargout <= len)\n        {\n          int nout = nargout > 0 ? nargout : 1;\n          octave_value_list retval (nout);\n\n          for (tree_decl_elt *elt : *ret_list)\n            {\n              if (nargout == 0 && ! is_defined (elt->ident ()))\n                break;\n\n              if (is_defined (elt->ident ()))\n                retval(i) = evaluate (elt);\n\n              i++;\n\n              if (i == nout)\n                break;\n            }\n\n          return retval;\n        }\n      else\n        {\n          octave_value_list retval (len + vlen);\n\n          for (tree_decl_elt *elt : *ret_list)\n            {\n              if (is_defined (elt->ident ()))\n                retval(i) = evaluate (elt);\n\n              i++;\n            }\n\n          for (octave_idx_type j = 0; j < vlen; j++)\n            retval(i++) = varargout(j);\n\n          return retval;\n        }\n    }\n}\n\nbool\ntree_evaluator::eval_decl_elt (tree_decl_elt *elt)\n{\n  bool retval = false;\n\n  tree_identifier *id = elt->ident ();\n  tree_expression *expr = elt->expression ();\n\n  if (id && expr)\n    {\n      octave_lvalue ult = id->lvalue (*this);\n\n      octave_value init_val = expr->evaluate (*this);\n\n      ult.assign (octave_value::op_asn_eq, init_val);\n\n      retval = true;\n    }\n\n  return retval;\n}\n\nbool\ntree_evaluator::switch_case_label_matches (tree_switch_case *expr,\n                                           const octave_value& val)\n{\n  tree_expression *label = expr->case_label ();\n\n  octave_value label_value = label->evaluate (*this);\n\n  if (label_value.is_defined ())\n    {\n      if (label_value.iscell ())\n        {\n          Cell cell (label_value.cell_value ());\n\n          for (octave_idx_type i = 0; i < cell.rows (); i++)\n            {\n              for (octave_idx_type j = 0; j < cell.columns (); j++)\n                {\n                  bool match = val.is_equal (cell(i,j));\n\n                  if (match)\n                    return true;\n                }\n            }\n        }\n      else\n        return val.is_equal (label_value);\n    }\n\n  return false;\n}\n\nvoid\ntree_evaluator::push_stack_frame (const symbol_scope& scope)\n{\n  m_call_stack.push (scope);\n}\n\nvoid\ntree_evaluator::push_stack_frame (octave_user_function *fcn,\n                                  const std::shared_ptr<stack_frame>& closure_frames)\n{\n  m_call_stack.push (fcn, closure_frames);\n}\n\nvoid\ntree_evaluator::push_stack_frame (octave_user_function *fcn,\n                                  const stack_frame::local_vars_map& local_vars,\n                                  const std::shared_ptr<stack_frame>& closure_frames)\n{\n  m_call_stack.push (fcn, local_vars, closure_frames);\n}\n\nvoid\ntree_evaluator::push_stack_frame (octave_user_script *script)\n{\n  m_call_stack.push (script);\n}\n\nvoid\ntree_evaluator::push_stack_frame (octave_function *fcn)\n{\n  m_call_stack.push (fcn);\n}\n\nvoid\ntree_evaluator::pop_stack_frame ()\n{\n  m_call_stack.pop ();\n}\n\nstd::shared_ptr<stack_frame>\ntree_evaluator::pop_return_stack_frame ()\n{\n  return m_call_stack.pop_return ();\n}\n\nint\ntree_evaluator::current_line () const\n{\n  return m_call_stack.current_line ();\n}\n\nint\ntree_evaluator::current_column () const\n{\n  return m_call_stack.current_column ();\n}\n\nint\ntree_evaluator::debug_user_code_line () const\n{\n  return m_call_stack.debug_user_code_line ();\n}\n\nint\ntree_evaluator::debug_user_code_column () const\n{\n  return m_call_stack.debug_user_code_column ();\n}\n\nvoid\ntree_evaluator::debug_where (std::ostream& os) const\n{\n  std::shared_ptr<stack_frame> frm = m_call_stack.current_user_frame ();\n\n  frm->display_stopped_in_message (os);\n}\n\nvoid\ntree_evaluator::debug_list (std::ostream& os, int num_lines) const\n{\n  std::shared_ptr<stack_frame> frm = m_call_stack.current_user_frame ();\n\n  if (! (frm->is_user_script_frame () || frm->is_user_fcn_frame ()))\n    error (\"dblist: must be inside a user function or script to use dblist\\n\");\n\n  frm->debug_list (os, num_lines);\n}\n\nvoid\ntree_evaluator::debug_type (std::ostream& os, int start_line, int end_line) const\n{\n  std::shared_ptr<stack_frame> frm = m_call_stack.current_user_frame ();\n\n  if (! (frm->is_user_script_frame () || frm->is_user_fcn_frame ()))\n    error (\"dbtype: must be inside a user function or script to use dbtype\\n\");\n\n  frm->debug_type (os, start_line, end_line);\n}\n\noctave_user_code *\ntree_evaluator::current_user_code () const\n{\n  return m_call_stack.current_user_code ();\n}\n\nunwind_protect *\ntree_evaluator::curr_fcn_unwind_protect_frame ()\n{\n  return m_call_stack.curr_fcn_unwind_protect_frame ();\n}\n\noctave_user_code *\ntree_evaluator::debug_user_code () const\n{\n  return m_call_stack.debug_user_code ();\n}\n\noctave_function *\ntree_evaluator::current_function (bool skip_first) const\n{\n  return m_call_stack.current_function (skip_first);\n}\n\noctave_function *\ntree_evaluator::caller_function () const\n{\n  return m_call_stack.current_function (true);\n}\n\nbool\ntree_evaluator::goto_frame (std::size_t n, bool verbose)\n{\n  return m_call_stack.goto_frame (n, verbose);\n}\n\nvoid\ntree_evaluator::goto_caller_frame ()\n{\n  m_call_stack.goto_caller_frame ();\n}\n\nvoid\ntree_evaluator::goto_base_frame ()\n{\n  m_call_stack.goto_base_frame ();\n}\n\nvoid\ntree_evaluator::restore_frame (std::size_t n)\n{\n  return m_call_stack.restore_frame (n);\n}\n\nstd::string\ntree_evaluator::get_dispatch_class () const\n{\n  return m_call_stack.get_dispatch_class ();\n}\n\nvoid\ntree_evaluator::set_dispatch_class (const std::string& class_name)\n{\n  m_call_stack.set_dispatch_class (class_name);\n}\n\nbool\ntree_evaluator::is_class_method_executing (std::string& dclass) const\n{\n  return m_call_stack.is_class_method_executing (dclass);\n}\n\nbool\ntree_evaluator::is_class_constructor_executing (std::string& dclass) const\n{\n  return m_call_stack.is_class_constructor_executing (dclass);\n}\n\nstd::list<std::shared_ptr<stack_frame>>\ntree_evaluator::backtrace_frames (octave_idx_type& curr_user_frame) const\n{\n  return m_call_stack.backtrace_frames (curr_user_frame);\n}\n\nstd::list<std::shared_ptr<stack_frame>>\ntree_evaluator::backtrace_frames () const\n{\n  return m_call_stack.backtrace_frames ();\n}\n\nstd::list<frame_info>\ntree_evaluator::backtrace_info (octave_idx_type& curr_user_frame,\n                                bool print_subfn) const\n{\n  return m_call_stack.backtrace_info (curr_user_frame, print_subfn);\n}\n\nstd::list<frame_info>\ntree_evaluator::backtrace_info () const\n{\n  return m_call_stack.backtrace_info ();\n}\n\noctave_map\ntree_evaluator::backtrace (octave_idx_type& curr_user_frame,\n                           bool print_subfn) const\n{\n  return m_call_stack.backtrace (curr_user_frame, print_subfn);\n}\n\noctave_map\ntree_evaluator::backtrace () const\n{\n  return m_call_stack.backtrace ();\n}\n\noctave_map\ntree_evaluator::empty_backtrace () const\n{\n  return m_call_stack.empty_backtrace ();\n}\n\nstd::string\ntree_evaluator::backtrace_message () const\n{\n  std::list<frame_info> frames = backtrace_info ();\n\n  std::ostringstream buf;\n\n  for (const auto& frm : frames)\n    {\n      buf << \"    \" << frm.fcn_name ();\n\n      int line = frm.line ();\n\n      if (line > 0)\n        {\n          buf << \" at line \" << line;\n\n          int column = frm.column ();\n\n          if (column > 0)\n            buf << \" column \" << column;\n\n          buf << \"\\n\";\n        }\n    }\n\n  return buf.str ();\n}\n\nvoid\ntree_evaluator::push_dummy_scope (const std::string& name)\n{\n  symbol_scope dummy_scope (name + \"$dummy\");\n\n  m_call_stack.push (dummy_scope);\n}\n\nvoid\ntree_evaluator::pop_scope ()\n{\n  m_call_stack.pop ();\n}\n\nsymbol_scope\ntree_evaluator::get_top_scope () const\n{\n  return m_call_stack.top_scope ();\n}\n\nsymbol_scope\ntree_evaluator::get_current_scope () const\n{\n  return m_call_stack.current_scope ();\n}\n\nvoid\ntree_evaluator::mlock (bool skip_first) const\n{\n  octave_function *fcn = m_call_stack.current_function (skip_first);\n\n  if (! fcn)\n    error (\"mlock: invalid use outside a function\");\n\n  if (fcn->is_builtin_function ())\n    {\n      warning (\"mlock: locking built-in function has no effect\");\n      return;\n    }\n\n  fcn->lock ();\n}\n\nvoid\ntree_evaluator::munlock (bool skip_first) const\n{\n  octave_function *fcn = m_call_stack.current_function (skip_first);\n\n  if (! fcn)\n    error (\"munlock: invalid use outside a function\");\n\n  if (fcn->is_builtin_function ())\n    {\n      warning (\"munlock: unlocking built-in function has no effect\");\n      return;\n    }\n\n  fcn->unlock ();\n}\n\nbool\ntree_evaluator::mislocked (bool skip_first) const\n{\n  octave_function *fcn = m_call_stack.current_function (skip_first);\n\n  if (! fcn)\n    error (\"mislocked: invalid use outside a function\");\n\n  return fcn->islocked ();\n}\n\noctave_value\ntree_evaluator::max_stack_depth (const octave_value_list& args, int nargout)\n{\n  return m_call_stack.max_stack_depth (args, nargout);\n}\n\nvoid\ntree_evaluator::display_call_stack () const\n{\n  m_call_stack.display ();\n}\n\noctave_value\ntree_evaluator::find (const std::string& name)\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  octave_value val = frame->varval (name);\n\n  if (val.is_defined ())\n    return val;\n\n  // Subfunction.  I think it only makes sense to check for\n  // subfunctions if we are currently executing a function defined\n  // from a .m file.\n\n  octave_value fcn = frame->find_subfunction (name);\n\n  if (fcn.is_defined ())\n    return fcn;\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  return symtab.fcn_table_find (name, ovl ());\n}\n\nvoid\ntree_evaluator::clear_objects ()\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  frame->clear_objects ();\n}\n\nvoid\ntree_evaluator::clear_variable (const std::string& name)\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  frame->clear_variable (name);\n}\n\nvoid\ntree_evaluator::clear_variable_pattern (const std::string& pattern)\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  frame->clear_variable_pattern (pattern);\n}\n\nvoid\ntree_evaluator::clear_variable_regexp (const std::string& pattern)\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  frame->clear_variable_regexp (pattern);\n}\n\nvoid\ntree_evaluator::clear_variables ()\n{\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  frame->clear_variables ();\n}\n\nvoid\ntree_evaluator::clear_global_variable (const std::string& name)\n{\n  m_call_stack.clear_global_variable (name);\n}\n\nvoid\ntree_evaluator::clear_global_variable_pattern (const std::string& pattern)\n{\n  m_call_stack.clear_global_variable_pattern (pattern);\n}\n\nvoid\ntree_evaluator::clear_global_variable_regexp(const std::string& pattern)\n{\n  m_call_stack.clear_global_variable_regexp (pattern);\n}\n\nvoid\ntree_evaluator::clear_global_variables ()\n{\n  m_call_stack.clear_global_variables ();\n}\n\nvoid\ntree_evaluator::clear_all (bool force)\n{\n  // FIXME: should this also clear objects?\n\n  clear_variables ();\n  clear_global_variables ();\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  symtab.clear_functions (force);\n}\n\nvoid\ntree_evaluator::clear_symbol (const std::string& name)\n{\n  // FIXME: are we supposed to do both here?\n\n  clear_variable (name);\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  symtab.clear_function (name);\n}\n\nvoid\ntree_evaluator::clear_symbol_pattern (const std::string& pattern)\n{\n  // FIXME: are we supposed to do both here?\n\n  clear_variable_pattern (pattern);\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  symtab.clear_function_pattern (pattern);\n}\n\nvoid\ntree_evaluator::clear_symbol_regexp (const std::string& pattern)\n{\n  // FIXME: are we supposed to do both here?\n\n  clear_variable_regexp (pattern);\n\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  symtab.clear_function_regexp (pattern);\n}\n\nstd::list<std::string>\ntree_evaluator::global_variable_names () const\n{\n  return m_call_stack.global_variable_names ();\n}\n\nstd::list<std::string>\ntree_evaluator::top_level_variable_names () const\n{\n  return m_call_stack.top_level_variable_names ();\n}\n\nstd::list<std::string>\ntree_evaluator::variable_names () const\n{\n  return m_call_stack.variable_names ();\n}\n\n// Return a pointer to the user-defined function FNAME.  If FNAME is empty,\n// search backward for the first user-defined function in the\n// current call stack.\n\noctave_user_code *\ntree_evaluator::get_user_code (const std::string& fname)\n{\n  octave_user_code *user_code = nullptr;\n\n  if (fname.empty ())\n    user_code = m_call_stack.debug_user_code ();\n  else\n    {\n      std::string name = fname;\n\n      if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@')\n        {\n          auto beg = name.begin () + 2;  // never have @/method\n          auto end = name.end () - 1;    // never have trailing '/'\n          std::replace (beg, end, '/', sys::file_ops::dir_sep_char ());\n        }\n\n      std::size_t name_len = name.length ();\n\n      if (name_len > 2 && name.substr (name_len-2) == \".m\")\n        name = name.substr (0, name_len-2);\n\n      if (name.empty ())\n        return nullptr;\n\n      symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n      octave_value fcn;\n      std::size_t p2 = std::string::npos;\n\n      if (name[0] == '@')\n        {\n          std::size_t p1 = name.find (sys::file_ops::dir_sep_char (), 1);\n\n          if (p1 == std::string::npos)\n            return nullptr;\n\n          std::string dispatch_type = name.substr (1, p1-1);\n\n          p2 = name.find ('>', p1);\n\n          std::string method = name.substr (p1+1, p2-1);\n\n          // first check for classdef method\n          cdef_manager& cdm = m_interpreter.get_cdef_manager ();\n\n//          fcn = cdm.find_method_symbol (method, dispatch_type);\n\n          cdef_class cls = cdm.find_class (dispatch_type, false);\n          if (cls.ok () && cls.get_name () == dispatch_type)\n            {\n              if (! method.compare (0, 4, \"get.\"))\n                {\n                  // find get method of classdef property\n                  std::string prop_name = method.substr (4);\n                  cdef_property prop = cls.find_property (prop_name);\n                  if (prop.ok () && prop.get_name () == prop_name)\n                    {\n                      const octave_value& get_meth = prop.get (\"GetMethod\");\n                      if (get_meth.is_function_handle ())\n                        return get_meth.user_function_value ()->user_code_value ();\n                      else\n                        return nullptr;\n                    }\n                }\n              else if (! method.compare (0, 4, \"set.\"))\n                {\n                  // find set method of classdef property\n                  std::string prop_name = method.substr (4);\n                  cdef_property prop = cls.find_property (prop_name);\n                  if (prop.ok () && prop.get_name () == prop_name)\n                    {\n                      const octave_value& set_meth = prop.get (\"SetMethod\");\n                      if (set_meth.is_function_handle ())\n                        return set_meth.user_function_value ()->user_code_value ();\n                      else\n                        return nullptr;\n                    }\n                }\n              else\n                {\n                  cdef_method meth = cls.find_method (method);\n                  if (meth.ok () && meth.get_name () == method)\n                    fcn = meth.get_function ();\n                  else\n                    return nullptr;\n                }\n            }\n\n          // If there is no classdef method, then try legacy classes.\n          if (fcn.is_undefined ())\n            fcn = symtab.find_method (method, dispatch_type);\n        }\n      else\n        {\n          p2 = name.find ('>');\n\n          std::string main_fcn = name.substr (0, p2);\n\n          fcn = symtab.find_function (main_fcn);\n        }\n\n      // List of function names sub1>sub2>...\n      std::string subfuns;\n\n      if (p2 != std::string::npos)\n        subfuns = name.substr (p2+1);\n\n      if (fcn.is_defined () && fcn.is_user_code ())\n        user_code = fcn.user_code_value ();\n\n      if (! user_code || subfuns.empty ())\n        return user_code;\n\n      fcn = user_code->find_subfunction (subfuns);\n\n      if (fcn.is_undefined ())\n        return nullptr;\n\n      user_code = fcn.user_code_value ();\n    }\n\n  return user_code;\n}\n\nstd::string\ntree_evaluator::current_function_name (bool skip_first) const\n{\n  octave_function *curfcn = m_call_stack.current_function (skip_first);\n\n  if (curfcn)\n    return curfcn->name ();\n\n  return \"\";\n}\n\nbool\ntree_evaluator::in_user_code () const\n{\n  return m_call_stack.current_user_code () != nullptr;\n}\n\nvoid\ntree_evaluator::visit_decl_command (tree_decl_command& cmd)\n{\n  if (m_echo_state)\n    {\n      int line = cmd.line ();\n      if (line < 0)\n        line = 1;\n      echo_code (line);\n      m_echo_file_pos = line + 1;\n    }\n\n  if (m_debug_mode)\n    do_breakpoint (cmd.is_active_breakpoint (*this));\n\n  // FIXME: tree_decl_init_list is not derived from tree, so should it\n  // really have an accept method?\n\n  tree_decl_init_list *init_list = cmd.initializer_list ();\n\n  if (init_list)\n    init_list->accept (*this);\n}\n\nvoid\ntree_evaluator::visit_decl_elt (tree_decl_elt& elt)\n{\n  tree_identifier *id = elt.ident ();\n\n  if (id)\n    {\n      if (elt.is_global ())\n        m_call_stack.make_global (id->symbol ());\n      else if (elt.is_persistent ())\n        m_call_stack.make_persistent (id->symbol ());\n      else\n        error (\"declaration list element not global or persistent\");\n\n      octave_lvalue ult = id->lvalue (*this);\n\n      if (ult.is_undefined ())\n        {\n          tree_expression *expr = elt.expression ();\n\n          octave_value init_val;\n\n          if (expr)\n            init_val = expr->evaluate (*this);\n          else\n            init_val = Matrix ();\n\n          ult.assign (octave_value::op_asn_eq, init_val);\n        }\n    }\n}\n\ntemplate <typename T>\nvoid\ntree_evaluator::execute_range_loop (const range<T>& rng, int line,\n                                    octave_lvalue& ult,\n                                    tree_statement_list *loop_body)\n{\n  octave_idx_type steps = rng.numel ();\n\n  if (math::isinf (rng.limit ()) || math::isinf (rng.base ()))\n    warning_with_id (\"Octave:infinite-loop\",\n                     \"FOR loop limit is infinite, will stop after %\"\n                     OCTAVE_IDX_TYPE_FORMAT \" steps\", steps);\n\n  for (octave_idx_type i = 0; i < steps; i++)\n    {\n      if (m_echo_state)\n        m_echo_file_pos = line;\n\n      octave_value val (rng.elem (i));\n\n      ult.assign (octave_value::op_asn_eq, val);\n\n      if (loop_body)\n        loop_body->accept (*this);\n\n      if (quit_loop_now ())\n        break;\n    }\n}\n\nvoid\ntree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd)\n{\n  int line = cmd.line ();\n  if (line < 0)\n    line = 1;\n\n  if (m_echo_state)\n    {\n      echo_code (line);\n      line++;\n    }\n\n  if (m_debug_mode)\n    do_breakpoint (cmd.is_active_breakpoint (*this));\n\n  // FIXME: need to handle PARFOR loops here using cmd.in_parallel ()\n  // and cmd.maxproc_expr ();\n\n  unwind_protect_var<bool> upv (m_in_loop_command, true);\n\n  tree_expression *expr = cmd.control_expr ();\n\n  octave_value rhs = expr->evaluate (*this);\n\n  if (rhs.is_undefined ())\n    return;\n\n  tree_expression *lhs = cmd.left_hand_side ();\n\n  octave_lvalue ult = lhs->lvalue (*this);\n\n  tree_statement_list *loop_body = cmd.body ();\n\n  if (rhs.is_range ())\n    {\n      // FIXME: is there a better way to dispatch here?\n\n      if (rhs.is_double_type ())\n        {\n          execute_range_loop (rhs.range_value (), line, ult, loop_body);\n          return;\n        }\n\n      // For now, enable only range<double>.\n    }\n\n  if (rhs.is_scalar_type ())\n    {\n      if (m_echo_state)\n        m_echo_file_pos = line;\n\n      ult.assign (octave_value::op_asn_eq, rhs);\n\n      if (loop_body)\n        loop_body->accept (*this);\n\n      // Maybe decrement break and continue states.\n      quit_loop_now ();\n\n      return;\n    }\n\n  // Also handle any range types not explicitly handled above, though\n  // not as efficiently as the specialized code above.\n\n  if (rhs.is_range () || rhs.is_matrix_type () || rhs.iscell ()\n      || rhs.is_string () || rhs.isstruct ())\n    {\n      // A matrix or cell is reshaped to 2 dimensions and iterated by\n      // columns.\n\n      const dim_vector& dv = rhs.dims ().redim (2);\n\n      octave_idx_type nrows = dv(0);\n      octave_idx_type steps = dv(1);\n\n      octave_value arg = rhs;\n      if (rhs.ndims () > 2)\n        arg = arg.reshape (dv);\n\n      if (steps > 0)\n        {\n          octave_value_list idx;\n          octave_idx_type iidx;\n\n          // for row vectors, use single index to speed things up.\n          if (nrows == 1)\n            {\n              idx.resize (1);\n              iidx = 0;\n            }\n          else\n            {\n              idx.resize (2);\n              idx(0) = octave_value::magic_colon_t;\n              iidx = 1;\n            }\n\n          for (octave_idx_type i = 1; i <= steps; i++)\n            {\n              if (m_echo_state)\n                m_echo_file_pos = line;\n\n              // index_op expects one-based indices.\n              idx(iidx) = i;\n              octave_value val = arg.index_op (idx);\n\n              ult.assign (octave_value::op_asn_eq, val);\n\n              if (loop_body)\n                loop_body->accept (*this);\n\n              if (quit_loop_now ())\n                break;\n            }\n        }\n      else\n        {\n          // Handle empty cases, while still assigning to loop var.\n          ult.assign (octave_value::op_asn_eq, arg);\n        }\n\n      return;\n    }\n\n  error (\"invalid type in for loop expression near line %d, column %d\",\n         cmd.line (), cmd.column ());\n}\n\nvoid\ntree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd)\n{\n  int line = cmd.line ();\n  if (line < 0)\n    line = 1;\n\n  if (m_echo_state)\n    {\n      echo_code (line);\n      line++;\n    }\n\n  if (m_debug_mode)\n    do_breakpoint (cmd.is_active_breakpoint (*this));\n\n  unwind_protect_var<bool> upv (m_in_loop_command, true);\n\n  tree_expression *expr = cmd.control_expr ();\n\n  octave_value rhs = expr->evaluate (*this);\n\n  if (rhs.is_undefined ())\n    return;\n\n  if (! rhs.isstruct ())\n    error (\"in statement 'for [X, Y] = VAL', VAL must be a structure\");\n\n  // Cycle through structure elements.  First element of id_list\n  // is set to value and the second is set to the name of the\n  // structure element.\n\n  tree_argument_list *lhs = cmd.left_hand_side ();\n\n  auto p = lhs->begin ();\n\n  tree_expression *elt = *p++;\n\n  octave_lvalue val_ref = elt->lvalue (*this);\n\n  elt = *p;\n\n  octave_lvalue key_ref = elt->lvalue (*this);\n\n  const octave_map tmp_val = rhs.map_value ();\n\n  tree_statement_list *loop_body = cmd.body ();\n\n  string_vector keys = tmp_val.keys ();\n\n  octave_idx_type nel = keys.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      if (m_echo_state)\n        m_echo_file_pos = line;\n\n      std::string key = keys[i];\n\n      const Cell val_lst = tmp_val.contents (key);\n\n      octave_idx_type n = val_lst.numel ();\n\n      octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst);\n\n      val_ref.assign (octave_value::op_asn_eq, val);\n      key_ref.assign (octave_value::op_asn_eq, key);\n\n      if (loop_body)\n        loop_body->accept (*this);\n\n      if (quit_loop_now ())\n        break;\n    }\n}\n\nvoid\ntree_evaluator::visit_spmd_command (tree_spmd_command& cmd)\n{\n  // For now, we just execute the commands serially.\n\n  tree_statement_list *body = cmd.body ();\n\n  if (body)\n    body->accept (*this);\n}\n\noctave_value\ntree_evaluator::evaluate_anon_fcn_handle (tree_anon_fcn_handle& afh)\n{\n  // FIXME: should CMD_LIST be limited to a single expression?\n  // I think that is what Matlab does.\n\n  symbol_scope scope = afh.scope ();\n  symbol_scope new_scope = scope ? scope.dup () : symbol_scope::invalid ();\n\n  tree_parameter_list *param_list = afh.parameter_list ();\n  tree_parameter_list *param_list_dup\n    = param_list ? param_list->dup (new_scope) : nullptr;\n\n  tree_parameter_list *ret_list = nullptr;\n\n  tree_statement_list *stmt_list = nullptr;\n\n  symbol_scope parent_scope = get_current_scope ();\n\n  new_scope.set_parent (parent_scope);\n  new_scope.set_primary_parent (parent_scope);\n\n  tree_expression *expr = afh.expression ();\n  if (expr)\n    {\n      tree_expression *expr_dup = expr->dup (new_scope);\n      tree_statement *stmt = new tree_statement (expr_dup);\n      stmt_list = new tree_statement_list (stmt);\n    }\n\n  tree_anon_scopes anon_fcn_ctx (afh);\n\n  std::set<std::string> free_vars = anon_fcn_ctx.free_variables ();\n\n  stack_frame::local_vars_map local_vars;\n\n  std::shared_ptr<stack_frame> frame\n    = m_call_stack.get_current_stack_frame ();\n\n  for (auto& name : free_vars)\n    {\n      octave_value val = frame->varval (name);\n\n      if (val.is_defined ())\n        local_vars[name] = val;\n    }\n\n  octave_user_function *af = new octave_user_function (new_scope, nullptr, param_list_dup, ret_list, stmt_list);\n\n  octave_function *curr_fcn = m_call_stack.current_function ();\n\n  bool is_nested = false;\n\n  if (curr_fcn)\n    {\n      // FIXME: maybe it would be better to just stash curr_fcn\n      // instead of individual bits of info about it?\n\n      // An anonymous function defined inside another nested function\n      // or parent of a nested function also behaves like a nested\n      // function.\n\n      if (curr_fcn->is_parent_function () || curr_fcn->is_nested_function ())\n        {\n          is_nested = true;\n          af->mark_as_nested_function ();\n          new_scope.set_nesting_depth (parent_scope.nesting_depth () + 1);\n        }\n\n      af->stash_dir_name (curr_fcn->dir_name ());\n\n      new_scope.cache_fcn_file_name (curr_fcn->fcn_file_name ());\n      new_scope.cache_dir_name (curr_fcn->dir_name ());\n\n      // The following is needed so that class method dispatch works\n      // properly for anonymous functions that wrap class methods.\n\n      if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ())\n        af->stash_dispatch_class (curr_fcn->dispatch_class ());\n\n      af->stash_fcn_file_name (curr_fcn->fcn_file_name ());\n    }\n\n  af->mark_as_anonymous_function ();\n\n  octave_value ov_fcn (af);\n\n  return (is_nested\n          ? octave_value (new octave_fcn_handle (ov_fcn, local_vars, frame))\n          : octave_value (new octave_fcn_handle (ov_fcn, local_vars)));\n}\n\noctave_value_list\ntree_evaluator::execute_builtin_function (octave_builtin& builtin_function,\n                                          int nargout,\n                                          const octave_value_list& args)\n{\n  octave_value_list retval;\n\n  if (args.has_magic_colon ())\n    error (\"invalid use of colon in function argument list\");\n\n  profiler::enter<octave_builtin> block (m_profiler, builtin_function);\n\n  octave_builtin::fcn fcn = builtin_function.function ();\n\n  // If number of outputs unknown (and this is not a complete statement),\n  // pass nargout=1 to the function being called\n  if (nargout < 0)\n    nargout = 1;\n\n  if (fcn)\n    retval = (*fcn) (args, nargout);\n  else\n    {\n      octave_builtin::meth meth = builtin_function.method ();\n\n      retval = (*meth) (m_interpreter, args, nargout);\n    }\n\n  // Do not allow null values to be returned from functions.\n  // FIXME: perhaps true builtins should be allowed?\n\n  retval.make_storable_values ();\n\n  // Fix the case of a single undefined value.\n  // This happens when a compiled function uses\n  //\n  //   octave_value retval;\n  //\n  // instead of\n  //\n  //   octave_value_list retval;\n  //\n  // the idiom is very common, so we solve that here.\n\n  if (retval.length () == 1 && retval.xelem (0).is_undefined ())\n    retval.clear ();\n\n  return retval;\n}\n\noctave_value_list\ntree_evaluator::execute_mex_function (octave_mex_function& mex_function,\n                                      int nargout,\n                                      const octave_value_list& args)\n{\n  octave_value_list retval;\n\n  if (args.has_magic_colon ())\n    error (\"invalid use of colon in function argument list\");\n\n  profiler::enter<octave_mex_function> block (m_profiler, mex_function);\n\n  // If number of outputs unknown (and this is not a complete statement),\n  // pass nargout=1 to the function being called\n  if (nargout < 0)\n    nargout = 1;\n\n  retval = call_mex (mex_function, args, nargout);\n\n  return retval;\n}\n\noctave_value_list\ntree_evaluator::execute_user_script (octave_user_script& user_script,\n                                     int nargout,\n                                     const octave_value_list& args)\n{\n  octave_value_list retval;\n\n  std::string file_name = user_script.fcn_file_name ();\n\n  if (args.length () != 0 || nargout != 0)\n    error (\"invalid call to script %s\", file_name.c_str ());\n\n  tree_statement_list *cmd_list = user_script.body ();\n\n  if (! cmd_list)\n    return retval;\n\n  // FIXME: Maybe this check belongs in the places where we push a new\n  // stack frame?  Or in the call_stack push method itself?\n\n  if (m_call_stack.size () >= static_cast<std::size_t> (m_max_recursion_depth))\n    error (\"max_recursion_depth exceeded\");\n\n  unwind_protect_var<stmt_list_type> upv (m_statement_context, SC_SCRIPT);\n\n  profiler::enter<octave_user_script> block (m_profiler, user_script);\n\n  if (echo ())\n    push_echo_state (tree_evaluator::ECHO_SCRIPTS, file_name);\n\n  // FIXME: Should we be using tree_evaluator::eval here?\n\n  cmd_list->accept (*this);\n\n  if (m_returning)\n    m_returning = 0;\n\n  if (m_breaking)\n    m_breaking--;\n\n  return retval;\n}\n\nvoid\ntree_evaluator::visit_octave_user_script (octave_user_script&)\n{\n  // ??\n  error_unexpected (\"tree_evaluator::visit_octave_user_script\");\n}\n\noctave_value_list\ntree_evaluator::execute_user_function (octave_user_function& user_function,\n                                       int nargout,\n                                       const octave_value_list& xargs)\n{\n  octave_value_list retval;\n\n  // If this function is a classdef constructor, extract the first input\n  // argument, which must be the partially constructed object instance.\n\n  octave_value_list args (xargs);\n\n  // FIXME: this probably shouldn't be a double-precision matrix.\n  Matrix ignored_outputs = ignored_fcn_outputs ();\n\n  unwind_protect frame;\n\n  if (! user_function.is_anonymous_function ())\n    {\n      frame.protect_var (m_lvalue_list);\n      m_lvalue_list = nullptr;\n    }\n\n  octave_value_list ret_args;\n\n  int nargin = args.length ();\n\n  // If number of outputs unknown (and this is not a complete statement),\n  // pass nargout=1 to the function being called\n  if (nargout < 0)\n    nargout = 1;\n\n  if (user_function.is_classdef_constructor ())\n    {\n      if (nargin > 0)\n        {\n          ret_args = args.slice (0, 1, true);\n          --nargin;\n          args = args.slice (1, nargin, true);\n        }\n      else\n        error (\"invalid call to classdef constructor in tree_evaluator::execute_user_function - please report this bug\");\n    }\n\n  tree_parameter_list *param_list = user_function.parameter_list ();\n\n  bool takes_varargs = false;\n  int max_inputs = 0;\n\n  if (param_list)\n    {\n      takes_varargs = param_list->takes_varargs ();\n      max_inputs = param_list->size ();\n    }\n\n  if (! takes_varargs && nargin > max_inputs)\n    {\n      std::string name = user_function.name ();\n\n      if (name.empty ())\n        name = \"@<anonymous>\";\n\n      error_with_id (\"Octave:invalid-fun-call\",\n                     \"%s: function called with too many inputs\",\n                     name.c_str ());\n    }\n\n  define_parameter_list_from_arg_vector (param_list, args);\n\n  tree_parameter_list *ret_list = user_function.return_list ();\n\n  if (ret_list && ! ret_list->takes_varargs ())\n    {\n      int max_outputs = ret_list->size ();\n\n      if (nargout > max_outputs)\n        {\n          std::string name = user_function.name ();\n\n          error_with_id (\"Octave:invalid-fun-call\",\n                         \"%s: function called with too many outputs\",\n                         name.c_str ());\n        }\n    }\n\n  bind_auto_fcn_vars (xargs.name_tags (), ignored_outputs, nargin,\n                      nargout, user_function.takes_varargs (),\n                      user_function.all_va_args (args));\n\n  // For classdef constructor, pre-populate the output arguments\n  // with the pre-initialized object instance, extracted above.\n\n  if (user_function.is_classdef_constructor ())\n    {\n      if (! ret_list)\n        error (\"%s: invalid classdef constructor, no output argument defined\",\n               user_function.dispatch_class ().c_str ());\n\n      define_parameter_list_from_arg_vector (ret_list, ret_args);\n    }\n\n  // FIXME: Maybe this check belongs in the places where we push a\n  // new stack frame?  Or in the call_stack push method itself?\n\n  if (m_call_stack.size () >= static_cast<std::size_t> (m_max_recursion_depth))\n    error (\"max_recursion_depth exceeded\");\n\n  unwind_action act2 ([&user_function] () {\n                        user_function.restore_warning_states ();\n                      });\n\n  // Evaluate the commands that make up the function.\n\n  unwind_protect_var<stmt_list_type> upv (m_statement_context, SC_FUNCTION);\n\n  tree_statement_list *cmd_list = user_function.body ();\n\n  if (cmd_list)\n    {\n      profiler::enter<octave_user_function>\n        block (m_profiler, user_function);\n\n      if (echo ())\n        push_echo_state (tree_evaluator::ECHO_FUNCTIONS,\n                         user_function.fcn_file_name ());\n\n      if (user_function.is_special_expr ())\n        {\n          panic_if (cmd_list->size () != 1);\n\n          tree_statement *stmt = cmd_list->front ();\n\n          tree_expression *expr = stmt->expression ();\n\n          if (expr)\n            {\n              m_call_stack.set_location (stmt->line (), stmt->column ());\n\n              retval = expr->evaluate_n (*this, nargout);\n\n              // Don't allow a comma-separated list to escape (see bug #64783).\n\n              if (nargout <= 1 && retval.length () == 1 && retval(0).is_cs_list ())\n                retval = retval(0).list_value ();\n            }\n        }\n      else\n        cmd_list->accept (*this);\n\n      if (m_returning)\n        m_returning = 0;\n\n      if (m_breaking)\n        m_breaking--;\n    }\n\n  // Copy return values out.\n\n  if (ret_list && ! user_function.is_special_expr ())\n    {\n      Cell varargout;\n\n      if (ret_list->takes_varargs ())\n        {\n          octave_value varargout_varval = varval (\"varargout\");\n\n          if (varargout_varval.is_defined ())\n            varargout = varargout_varval.xcell_value (\"varargout must be a cell array object\");\n        }\n\n      retval = convert_return_list_to_const_vector (ret_list, nargout, varargout);\n    }\n\n  return retval;\n}\n\nvoid\ntree_evaluator::visit_octave_user_function (octave_user_function&)\n{\n  // ??\n  error_unexpected (\"tree_evaluator::visit_octave_user_function\");\n}\n\nvoid\ntree_evaluator::visit_octave_user_function_header (octave_user_function&)\n{\n  error_unexpected (\"tree_evaluator::visit_octave_user_function_header\");\n}\n\nvoid\ntree_evaluator::visit_octave_user_function_trailer (octave_user_function&)\n{\n  error_unexpected (\"tree_evaluator::visit_octave_user_function_trailer\");\n}\n\nvoid\ntree_evaluator::visit_function_def (tree_function_def& cmd)\n{\n  octave_value fcn = cmd.function ();\n\n  octave_function *f = fcn.function_value ();\n\n  if (f)\n    {\n      std::string nm = f->name ();\n\n      symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n      symtab.install_cmdline_function (nm, fcn);\n\n      // Make sure that any variable with the same name as the new\n      // function is cleared.\n\n      assign (nm);\n    }\n}\n\nvoid\ntree_evaluator::visit_identifier (tree_identifier&)\n{\n  error_unexpected (\"tree_evaluator::visit_identifier\");\n}\n\nvoid\ntree_evaluator::visit_if_clause (tree_if_clause&)\n{\n  error_unexpected (\"tree_evaluator::visit_if_clause\");\n}\n\nvoid\ntree_evaluator::visit_if_command (tree_if_command& cmd)\n{\n  if (m_echo_state)\n    {\n      int line = cmd.line ();\n      if (line < 0)\n        line = 1;\n      echo_code (line);\n      m_echo_file_pos = line + 1;\n    }\n\n  // FIXME: tree_if_command_list is not derived from tree, so should it\n  // really have an accept method?\n\n  tree_if_command_list *lst = cmd.cmd_list ();\n\n  if (lst)\n    lst->accept (*this);\n}\n\nvoid\ntree_evaluator::visit_if_command_list (tree_if_command_list& lst)\n{\n  for (tree_if_clause *tic : lst)\n    {\n      tree_expression *expr = tic->condition ();\n\n      if (! (in_debug_repl ()\n             && m_call_stack.current_frame () == m_debug_frame))\n        m_call_stack.set_location (tic->line (), tic->column ());\n\n      if (m_debug_mode && ! tic->is_else_clause ())\n        do_breakpoint (tic->is_active_breakpoint (*this));\n\n      if (tic->is_else_clause () || is_logically_true (expr, \"if\"))\n        {\n          tree_statement_list *stmt_lst = tic->commands ();\n\n          if (stmt_lst)\n            stmt_lst->accept (*this);\n\n          break;\n        }\n    }\n}\n\nvoid\ntree_evaluator::visit_index_expression (tree_index_expression&)\n{\n  error_unexpected (\"tree_evaluator::visit_index_expression\");\n}\n\nvoid\ntree_evaluator::visit_matrix (tree_matrix&)\n{\n  error_unexpected (\"tree_evaluator::visit_matrix\");\n}\n\nvoid\ntree_evaluator::visit_cell (tree_cell&)\n{\n  error_unexpected (\"tree_evaluator::visit_cell\");\n}\n\nvoid\ntree_evaluator::visit_multi_assignment (tree_multi_assignment&)\n{\n  error_unexpected (\"tree_evaluator::visit_multi_assignment\");\n}\n\nvoid\ntree_evaluator::visit_no_op_command (tree_no_op_command& cmd)\n{\n  if (m_echo_state)\n    {\n      int line = cmd.line ();\n      if (line < 0)\n        line = 1;\n      echo_code (line);\n      m_echo_file_pos = line + 1;\n    }\n\n  if (m_debug_mode && cmd.is_end_of_fcn_or_script ())\n    do_breakpoint (cmd.is_active_breakpoint (*this), true);\n}\n\nvoid\ntree_evaluator::visit_constant (tree_constant&)\n{\n  error_unexpected (\"tree_evaluator::visit_constant\");\n}\n\nvoid\ntree_evaluator::visit_fcn_handle (tree_fcn_handle&)\n{\n  error_unexpected (\"tree_evaluator::visit_fcn_handle\");\n}\n\nvoid\ntree_evaluator::visit_parameter_list (tree_parameter_list&)\n{\n  error_unexpected (\"tree_evaluator::visit_parameter_list\");\n}\n\nvoid\ntree_evaluator::visit_postfix_expression (tree_postfix_expression&)\n{\n  error_unexpected (\"tree_evaluator::visit_postfix_expression\");\n}\n\nvoid\ntree_evaluator::visit_prefix_expression (tree_prefix_expression&)\n{\n  error_unexpected (\"tree_evaluator::visit_prefix_expression\");\n}\n\nvoid\ntree_evaluator::visit_return_command (tree_return_command& cmd)\n{\n  if (m_echo_state)\n    {\n      int line = cmd.line ();\n      if (line < 0)\n        line = 1;\n      echo_code (line);\n      m_echo_file_pos = line + 1;\n    }\n\n  if (m_debug_mode)\n    do_breakpoint (cmd.is_active_breakpoint (*this));\n\n  // Act like dbcont.\n\n  if (in_debug_repl () && m_call_stack.current_frame () == m_debug_frame)\n    dbcont ();\n  else if (m_statement_context == SC_FUNCTION\n           || m_statement_context == SC_SCRIPT\n           || m_in_loop_command)\n    m_returning = 1;\n}\n\nvoid\ntree_evaluator::visit_simple_assignment (tree_simple_assignment&)\n{\n  error_unexpected (\"tree_evaluator::visit_simple_assignment\");\n}\n\nvoid\ntree_evaluator::visit_statement (tree_statement& stmt)\n{\n  tree_command *cmd = stmt.command ();\n  tree_expression *expr = stmt.expression ();\n\n  if (cmd || expr)\n    {\n      if (! (in_debug_repl ()\n             && m_call_stack.current_frame () == m_debug_frame))\n        m_call_stack.set_location (stmt.line (), stmt.column ());\n\n      try\n        {\n          if (cmd)\n            {\n              unwind_protect_var<const std::list<octave_lvalue> *>\n                upv (m_lvalue_list, nullptr);\n\n              cmd->accept (*this);\n            }\n          else\n            {\n              if (m_echo_state)\n                {\n                  int line = stmt.line ();\n                  if (line < 0)\n                    line = 1;\n                  echo_code (line);\n                  m_echo_file_pos = line + 1;\n                }\n\n              if (m_debug_mode)\n                do_breakpoint (expr->is_active_breakpoint (*this));\n\n              // FIXME: maybe all of this should be packaged in\n              // one virtual function that returns a flag saying whether\n              // or not the expression will take care of binding ans and\n              // printing the result.\n\n              // FIXME: it seems that we should just have to\n              // evaluate the expression and that should take care of\n              // everything, binding ans as necessary?\n\n              octave_value tmp_result = expr->evaluate (*this, 0);\n\n              if (tmp_result.is_defined ())\n                {\n                  bool do_bind_ans = false;\n\n                  if (expr->is_identifier ())\n                    do_bind_ans = ! is_variable (expr);\n                  else\n                    do_bind_ans = ! expr->is_assignment_expression ();\n\n                  if (do_bind_ans)\n                    bind_ans (tmp_result, expr->print_result ()\n                              && statement_printing_enabled ());\n                }\n            }\n        }\n      catch (const std::bad_alloc&)\n        {\n          // FIXME: We want to use error_with_id here so that give users\n          // control over this error message but error_with_id will\n          // require some memory allocations.  Is there anything we can\n          // do to make those more likely to succeed?\n\n          error_with_id (\"Octave:bad-alloc\",\n                         \"out of memory or dimension too large for Octave's index type\");\n        }\n      catch (const interrupt_exception&)\n        {\n          // If we are debugging, then continue with next statement.\n          // Otherwise, jump out of here.\n\n          if (m_debug_mode)\n            m_interpreter.recover_from_exception ();\n          else\n            throw;\n        }\n      catch (const execution_exception& ee)\n        {\n          error_system& es = m_interpreter.get_error_system ();\n\n          if ((m_interpreter.interactive ()\n               || application::forced_interactive ())\n              && ((es.debug_on_error ()\n                   && m_bp_table.debug_on_err (es.last_error_id ()))\n                  || (es.debug_on_caught ()\n                      && m_bp_table.debug_on_caught (es.last_error_id ())))\n              && in_user_code ())\n            {\n              es.save_exception (ee);\n              es.display_exception (ee);\n\n              enter_debugger ();\n\n              // It doesn't make sense to continue execution after an\n              // error occurs so force the debugger to quit all debug\n              // levels and return the top prompt.\n\n              throw quit_debug_exception (true);\n            }\n          else\n            throw;\n        }\n    }\n}\n\nvoid\ntree_evaluator::visit_statement_list (tree_statement_list& lst)\n{\n  // FIXME: commented out along with else clause below.\n  // static octave_value_list empty_list;\n\n  auto p = lst.begin ();\n\n  if (p != lst.end ())\n    {\n      while (true)\n        {\n          tree_statement *elt = *p++;\n\n          if (! elt)\n            error (\"invalid statement found in statement list!\");\n\n          octave_quit ();\n\n          elt->accept (*this);\n\n          if (m_breaking || m_continuing)\n            break;\n\n          if (m_returning)\n            break;\n\n          if (p == lst.end ())\n            break;\n          else\n            {\n              // Clear previous values before next statement is\n              // evaluated so that we aren't holding an extra\n              // reference to a value that may be used next.  For\n              // example, in code like this:\n              //\n              //   X = rand (N);  # refcount for X should be 1\n              //                  # after this statement\n              //\n              //   X(idx) = val;  # no extra copy of X should be\n              //                  # needed, but we will be faked\n              //                  # out if retval is not cleared\n              //                  # between statements here\n\n              //              result_values = empty_list;\n            }\n        }\n    }\n}\n\nvoid\ntree_evaluator::visit_switch_case (tree_switch_case&)\n{\n  error_unexpected (\"tree_evaluator::visit_switch_case\");\n}\n\nvoid\ntree_evaluator::visit_switch_case_list (tree_switch_case_list&)\n{\n  error_unexpected (\"tree_evaluator::visit_switch_case_list\");\n}\n\nvoid\ntree_evaluator::visit_switch_command (tree_switch_command& cmd)\n{\n  if (m_echo_state)\n    {\n      int line = cmd.line ();\n      if (line < 0)\n        line = 1;\n      echo_code (line);\n      m_echo_file_pos = line + 1;\n    }\n\n  if (m_debug_mode)\n    do_breakpoint (cmd.is_active_breakpoint (*this));\n\n  tree_expression *expr = cmd.switch_value ();\n\n  if (! expr)\n    error (\"missing value in switch command near line %d, column %d\",\n           cmd.line (), cmd.column ());\n\n  octave_value val = expr->evaluate (*this);\n\n  tree_switch_case_list *lst = cmd.case_list ();\n\n  if (lst)\n    {\n      for (tree_switch_case *t : *lst)\n        {\n          if (t->is_default_case () || switch_case_label_matches (t, val))\n            {\n              tree_statement_list *stmt_lst = t->commands ();\n\n              if (stmt_lst)\n                stmt_lst->accept (*this);\n\n              break;\n            }\n        }\n    }\n}\n\nvoid\ntree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd)\n{\n  if (m_echo_state)\n    {\n      int line = cmd.line ();\n      if (line < 0)\n        line = 1;\n      echo_code (line);\n      m_echo_file_pos = line + 1;\n    }\n\n  bool execution_error = false;\n  octave_scalar_map err_map;\n\n  tree_statement_list *try_code = cmd.body ();\n\n  if (try_code)\n    {\n      // unwind frame before catch block\n\n      unwind_protect frame;\n\n      interpreter_try (frame);\n\n      // The catch code is *not* added to unwind_protect stack; it\n      // doesn't need to be run on interrupts.\n\n      try\n        {\n          try_code->accept (*this);\n        }\n      catch (const execution_exception& ee)\n        {\n          execution_error = true;\n\n          error_system& es = m_interpreter.get_error_system ();\n\n          es.save_exception (ee);\n\n          err_map.assign (\"message\", es.last_error_message ());\n          err_map.assign (\"identifier\", es.last_error_id ());\n          err_map.assign (\"stack\", es.last_error_stack ());\n\n          m_interpreter.recover_from_exception ();\n        }\n\n      // Actions attached to unwind_protect frame will run here, prior\n      // to executing the catch block.\n    }\n\n  if (execution_error)\n    {\n      tree_statement_list *catch_code = cmd.cleanup ();\n\n      if (catch_code)\n        {\n          tree_identifier *expr_id = cmd.identifier ();\n\n          if (expr_id)\n            {\n              octave_lvalue ult = expr_id->lvalue (*this);\n\n              ult.assign (octave_value::op_asn_eq, err_map);\n            }\n\n          // perform actual \"catch\" block\n          catch_code->accept (*this);\n        }\n    }\n}\n\nvoid\ntree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list)\n{\n  unwind_protect frame;\n\n  frame.protect_var (octave_interrupt_state);\n  octave_interrupt_state = 0;\n\n  // We want to preserve the last location info for possible\n  // backtracking.\n\n  frame.add (&call_stack::set_line, &m_call_stack,\n             m_call_stack.current_line ());\n\n  frame.add (&call_stack::set_column, &m_call_stack,\n             m_call_stack.current_column ());\n\n  // Similarly, if we have seen a return or break statement, allow all\n  // the cleanup code to run before returning or handling the break.\n  // We don't have to worry about continue statements because they can\n  // only occur in loops.\n\n  frame.protect_var (m_returning);\n  m_returning = 0;\n\n  frame.protect_var (m_breaking);\n  m_breaking = 0;\n\n  try\n    {\n      if (list)\n        list->accept (*this);\n    }\n  catch (const execution_exception& ee)\n    {\n      error_system& es = m_interpreter.get_error_system ();\n\n      es.save_exception (ee);\n      m_interpreter.recover_from_exception ();\n\n      if (m_breaking || m_returning)\n        frame.discard (2);\n      else\n        frame.run (2);\n\n      frame.discard (2);\n\n      throw;\n    }\n\n  // The unwind_protects are popped off the stack in the reverse of\n  // the order they are pushed on.\n\n  // FIXME: these statements say that if we see a break or\n  // return statement in the cleanup block, that we want to use the\n  // new value of the breaking or returning flag instead of restoring\n  // the previous value.  Is that the right thing to do?  I think so.\n  // Consider the case of\n  //\n  //   function foo ()\n  //     unwind_protect\n  //       fprintf (stderr, \"1: this should always be executed\\n\");\n  //       break;\n  //       fprintf (stderr, \"1: this should never be executed\\n\");\n  //     unwind_protect_cleanup\n  //       fprintf (stderr, \"2: this should always be executed\\n\");\n  //       return;\n  //       fprintf (stderr, \"2: this should never be executed\\n\");\n  //     end_unwind_protect\n  //   endfunction\n  //\n  // If we reset the value of the breaking flag, both the returning\n  // flag and the breaking flag will be set, and we shouldn't have\n  // both.  So, use the most recent one.  If there is no return or\n  // break in the cleanup block, the values should be reset to\n  // whatever they were when the cleanup block was entered.\n\n  if (m_breaking || m_returning)\n    frame.discard (2);\n  else\n    frame.run (2);\n}\n\nvoid\ntree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd)\n{\n  if (m_echo_state)\n    {\n      int line = cmd.line ();\n      if (line < 0)\n        line = 1;\n      echo_code (line);\n      m_echo_file_pos = line + 1;\n    }\n\n  tree_statement_list *cleanup_code = cmd.cleanup ();\n\n  tree_statement_list *unwind_protect_code = cmd.body ();\n\n  if (unwind_protect_code)\n    {\n      try\n        {\n          unwind_protect_code->accept (*this);\n        }\n      catch (const execution_exception& ee)\n        {\n          error_system& es = m_interpreter.get_error_system ();\n\n          // FIXME: Maybe we should be able to temporarily set the\n          // interpreter's exception handling state to something \"safe\"\n          // while the cleanup block runs instead of just resetting it\n          // here?\n          es.save_exception (ee);\n          m_interpreter.recover_from_exception ();\n\n          // Run the cleanup code on exceptions, so that it is run even\n          // in case of interrupt or out-of-memory.\n          do_unwind_protect_cleanup_code (cleanup_code);\n\n          // If an error occurs inside the cleanup code, a new\n          // exception will be thrown instead of the original.\n          throw;\n        }\n      catch (const interrupt_exception&)\n        {\n          // The comments above apply here as well.\n          m_interpreter.recover_from_exception ();\n          do_unwind_protect_cleanup_code (cleanup_code);\n          throw;\n        }\n\n      // Also execute the unwind_protect_cleanump code if the\n      // unwind_protect block runs without error.\n      do_unwind_protect_cleanup_code (cleanup_code);\n    }\n}\n\nvoid\ntree_evaluator::visit_while_command (tree_while_command& cmd)\n{\n  int line = cmd.line ();\n  if (line < 0)\n    line = 1;\n\n  if (m_echo_state)\n    {\n      echo_code (line);\n      line++;\n    }\n\n  unwind_protect_var<bool> upv (m_in_loop_command, true);\n\n  tree_expression *expr = cmd.condition ();\n\n  if (! expr)\n    error (\"unexpected: while condition is nullptr - please report this bug\");\n\n  for (;;)\n    {\n      if (m_echo_state)\n        m_echo_file_pos = line;\n\n      if (m_debug_mode)\n        do_breakpoint (cmd.is_active_breakpoint (*this));\n\n      if (is_logically_true (expr, \"while\"))\n        {\n          tree_statement_list *loop_body = cmd.body ();\n\n          if (loop_body)\n            loop_body->accept (*this);\n\n          if (quit_loop_now ())\n            break;\n        }\n      else\n        break;\n    }\n}\n\nvoid\ntree_evaluator::visit_do_until_command (tree_do_until_command& cmd)\n{\n  int line = cmd.line ();\n  if (line < 0)\n    line = 1;\n\n  if (m_echo_state)\n    {\n      echo_code (line);\n      line++;\n    }\n\n  unwind_protect_var<bool> upv (m_in_loop_command, true);\n\n  tree_expression *expr = cmd.condition ();\n\n  if (! expr)\n    error (\"unexpected: do-until condition is nullptr - please report this bug\");\n\n  for (;;)\n    {\n      if (m_echo_state)\n        m_echo_file_pos = line;\n\n      tree_statement_list *loop_body = cmd.body ();\n\n      if (loop_body)\n        loop_body->accept (*this);\n\n      if (quit_loop_now ())\n        break;\n\n      if (m_debug_mode)\n        do_breakpoint (cmd.is_active_breakpoint (*this));\n\n      if (is_logically_true (expr, \"do-until\"))\n        break;\n    }\n}\n\nvoid\ntree_evaluator::visit_superclass_ref (tree_superclass_ref&)\n{\n  error_unexpected (\"tree_evaluator::visit_superclass_ref\");\n}\n\nvoid\ntree_evaluator::visit_metaclass_query (tree_metaclass_query&)\n{\n  error_unexpected (\"tree_evaluator::visit_metaclass_query\");\n}\n\nvoid\ntree_evaluator::bind_ans (const octave_value& val, bool print)\n{\n  static std::string ans = \"ans\";\n\n  if (val.is_defined ())\n    {\n      if (val.is_cs_list ())\n        {\n          octave_value_list lst = val.list_value ();\n\n          for (octave_idx_type i = 0; i < lst.length (); i++)\n            bind_ans (lst(i), print);\n        }\n      else\n        {\n          // FIXME: Maybe assign could also return the assigned value,\n          // just for convenience?\n\n          assign (ans, val);\n\n          if (print)\n            {\n              // Use varval instead of displaying VAL directly so that\n              // we get the right type and value for things like\n              // magic_int values that may mutate when stored.\n\n              octave_value_list args = ovl (varval (ans));\n              args.stash_name_tags (string_vector (ans));\n              m_interpreter.feval (\"display\", args);\n            }\n        }\n    }\n}\n\nvoid\ntree_evaluator::do_breakpoint (tree_statement& stmt)\n{\n  do_breakpoint (stmt.is_active_breakpoint (*this),\n                 stmt.is_end_of_fcn_or_script ());\n}\n\nvoid\ntree_evaluator::do_breakpoint (bool is_breakpoint,\n                               bool is_end_of_fcn_or_script)\n{\n  bool break_on_this_statement = false;\n\n  if (is_breakpoint)\n    break_on_this_statement = true;\n  else if (m_dbstep_flag > 0)\n    {\n      if (m_call_stack.current_frame () == m_debug_frame)\n        {\n          if (m_dbstep_flag == 1 || is_end_of_fcn_or_script)\n            {\n              // We get here if we are doing a \"dbstep\" or a \"dbstep N\" and\n              // the count has reached 1 so that we must stop and return to\n              // debug prompt.  Alternatively, \"dbstep N\" has been used but\n              // the end of the frame has been reached so we stop at the last\n              // line and return to prompt.\n\n              break_on_this_statement = true;\n            }\n          else\n            {\n              // Executing \"dbstep N\".  Decrease N by one and continue.\n\n              m_dbstep_flag--;\n            }\n\n        }\n      else if (m_dbstep_flag == 1\n               && m_call_stack.current_frame () < m_debug_frame)\n        {\n          // We stepped out from the end of a function.\n\n          m_debug_frame = m_call_stack.current_frame ();\n\n          break_on_this_statement = true;\n        }\n    }\n  else if (m_dbstep_flag == -1)\n    {\n      // We get here if we are doing a \"dbstep in\".\n\n      break_on_this_statement = true;\n\n      m_debug_frame = m_call_stack.current_frame ();\n    }\n  else if (m_dbstep_flag == -2)\n    {\n      // We get here if we are doing a \"dbstep out\".  Check for end of\n      // function and whether the current frame is the same as the\n      // cached value because we want to step out from the frame where\n      // \"dbstep out\" was evaluated, not from any functions called from\n      // that frame.\n\n      if (is_end_of_fcn_or_script\n          && m_call_stack.current_frame () == m_debug_frame)\n        m_dbstep_flag = -1;\n    }\n\n  if (! break_on_this_statement)\n    break_on_this_statement = m_break_on_next_stmt;\n\n  m_break_on_next_stmt = false;\n\n  if (break_on_this_statement)\n    {\n      m_dbstep_flag = 0;\n\n      enter_debugger ();\n    }\n}\n\nbool\ntree_evaluator::is_logically_true (tree_expression *expr,\n                                   const char *warn_for)\n{\n  bool expr_value = false;\n\n  m_call_stack.set_location (expr->line (), expr->column ());\n\n  octave_value t1 = expr->evaluate (*this);\n\n  if (t1.is_defined ())\n    return t1.is_true ();\n  else\n    error (\"%s: undefined value used in conditional expression\", warn_for);\n\n  return expr_value;\n}\n\noctave_value\ntree_evaluator::max_recursion_depth (const octave_value_list& args,\n                                     int nargout)\n{\n  return set_internal_variable (m_max_recursion_depth, args, nargout,\n                                \"max_recursion_depth\", 0);\n}\n\nsymbol_info_list\ntree_evaluator::glob_symbol_info (const std::string& pattern) const\n{\n  return m_call_stack.glob_symbol_info (pattern);\n}\n\nsymbol_info_list\ntree_evaluator::regexp_symbol_info (const std::string& pattern) const\n{\n  return m_call_stack.regexp_symbol_info (pattern);\n}\n\nsymbol_info_list\ntree_evaluator::get_symbol_info ()\n{\n  return m_call_stack.get_symbol_info ();\n}\n\nsymbol_info_list\ntree_evaluator::top_scope_symbol_info () const\n{\n  return m_call_stack.top_scope_symbol_info ();\n}\n\noctave_map\ntree_evaluator::get_autoload_map () const\n{\n  Cell fcn_names (dim_vector (m_autoload_map.size (), 1));\n  Cell file_names (dim_vector (m_autoload_map.size (), 1));\n\n  octave_idx_type i = 0;\n  for (const auto& fcn_fname : m_autoload_map)\n    {\n      fcn_names(i) = fcn_fname.first;\n      file_names(i) = fcn_fname.second;\n\n      i++;\n    }\n\n  octave_map m;\n\n  m.assign (\"function\", fcn_names);\n  m.assign (\"file\", file_names);\n\n  return m;\n}\n\nstd::string\ntree_evaluator::lookup_autoload (const std::string& nm) const\n{\n  std::string retval;\n\n  auto p = m_autoload_map.find (nm);\n\n  if (p != m_autoload_map.end ())\n    {\n      load_path& lp = m_interpreter.get_load_path ();\n\n      retval = lp.find_file (p->second);\n    }\n\n  return retval;\n}\n\nstd::list<std::string>\ntree_evaluator::autoloaded_functions () const\n{\n  std::list<std::string> names;\n\n  for (const auto& fcn_fname : m_autoload_map)\n    names.push_back (fcn_fname.first);\n\n  return names;\n}\n\nstd::list<std::string>\ntree_evaluator::reverse_lookup_autoload (const std::string& nm) const\n{\n  std::list<std::string> names;\n\n  for (const auto& fcn_fname : m_autoload_map)\n    if (nm == fcn_fname.second)\n      names.push_back (fcn_fname.first);\n\n  return names;\n}\n\nvoid\ntree_evaluator::add_autoload (const std::string& fcn,\n                              const std::string& nm)\n{\n  m_autoload_map[fcn] = check_autoload_file (nm);\n}\n\nvoid\ntree_evaluator::remove_autoload (const std::string& fcn,\n                                 const std::string& nm)\n{\n  check_autoload_file (nm);\n\n  // Remove function from symbol table and autoload map.\n  symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n  symtab.clear_dld_function (fcn);\n\n  m_autoload_map.erase (fcn);\n}\n\noctave_value\ntree_evaluator::whos_line_format (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_whos_line_format, args, nargout,\n                                \"whos_line_format\");\n}\n\noctave_value\ntree_evaluator::silent_functions (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_silent_functions, args, nargout,\n                                \"silent_functions\");\n}\n\noctave_value\ntree_evaluator::string_fill_char (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_string_fill_char, args, nargout,\n                                \"string_fill_char\");\n}\n\n// Final step of processing an indexing error.  Add the name of the\n// variable being indexed, if any, then issue an error.  (Will this also\n// be needed by pt-lvalue, which calls subsref?)\n\nvoid\ntree_evaluator::final_index_error (index_exception& ie,\n                                   const tree_expression *expr)\n{\n  std::string extra_message;\n\n  if (is_variable (expr))\n    {\n      std::string var = expr->name ();\n\n      ie.set_var (var);\n\n      symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n      octave_value fcn = symtab.find_function (var);\n\n      if (fcn.is_function ())\n        {\n          octave_function *fp = fcn.function_value ();\n\n          if (fp && fp->name () == var)\n            extra_message\n              = \" (note: variable '\" + var + \"' shadows function)\";\n        }\n    }\n\n  std::string msg = ie.message () + extra_message;\n\n  error_with_id (ie.err_id (), \"%s\", msg.c_str ());\n}\n\noctave_value\ntree_evaluator::do_who (int argc, const string_vector& argv,\n                        bool return_list, bool verbose)\n{\n  return m_call_stack.do_who (argc, argv, return_list, verbose);\n}\n\noctave_value_list\ntree_evaluator::make_value_list (tree_argument_list *args,\n                                 const string_vector& arg_nm)\n{\n  octave_value_list retval;\n\n  if (args)\n    {\n      unwind_protect_var<const std::list<octave_lvalue> *>\n        upv (m_lvalue_list, nullptr);\n\n      int len = args->size ();\n\n      unwind_protect_var<int> upv2 (m_index_position);\n      unwind_protect_var<int> upv3 (m_num_indices);\n\n      m_num_indices = len;\n\n      std::list<octave_value> arg_vals;\n\n      int k = 0;\n\n      for (auto elt : *args)\n        {\n          // FIXME: is it possible for elt to be invalid?\n\n          if (! elt)\n            break;\n\n          m_index_position = k++;\n\n          octave_value tmp = elt->evaluate (*this);\n\n          if (tmp.is_cs_list ())\n            {\n              octave_value_list tmp_ovl = tmp.list_value ();\n\n              for (octave_idx_type i = 0; i < tmp_ovl.length (); i++)\n                arg_vals.push_back (tmp_ovl(i));\n            }\n          else if (tmp.is_defined ())\n            arg_vals.push_back (tmp);\n        }\n\n      retval = octave_value_list (arg_vals);\n    }\n\n  octave_idx_type n = retval.length ();\n\n  if (n > 0)\n    retval.stash_name_tags (arg_nm);\n\n  return retval;\n}\n\nstd::list<octave_lvalue>\ntree_evaluator::make_lvalue_list (tree_argument_list *lhs)\n{\n  std::list<octave_lvalue> retval;\n\n  for (tree_expression *elt : *lhs)\n    retval.push_back (elt->lvalue (*this));\n\n  return retval;\n}\n\nvoid\ntree_evaluator::push_echo_state (int type, const std::string& file_name,\n                                 int pos)\n{\n  unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame ();\n\n  if (frame)\n    {\n      push_echo_state_cleanup (*frame);\n\n      set_echo_state (type, file_name, pos);\n    }\n}\n\nvoid\ntree_evaluator::set_echo_state (int type, const std::string& file_name,\n                                int pos)\n{\n  m_echo_state = echo_this_file (file_name, type);\n\n  m_echo_file_name = file_name;\n  m_echo_file_pos = pos;\n}\n\nvoid\ntree_evaluator::uwp_set_echo_state (bool state, const std::string& file_name,\n                                    int pos)\n{\n  m_echo_state = state;\n\n  m_echo_file_name = file_name;\n  m_echo_file_pos = pos;\n}\n\nvoid\ntree_evaluator::maybe_set_echo_state ()\n{\n  octave_function *caller = caller_function ();\n\n  if (caller && caller->is_user_code ())\n    {\n      octave_user_code *fcn = dynamic_cast<octave_user_code *> (caller);\n\n      int type = fcn->is_user_function () ? ECHO_FUNCTIONS : ECHO_SCRIPTS;\n\n      std::string file_name = fcn->fcn_file_name ();\n\n      // We want the line where \"echo\" was called, not the line number\n      // stored in the stack frame that was created for the echo\n      // function (that will always be -1).\n\n      int pos = m_call_stack.current_user_code_line ();\n\n      if (pos < 0)\n        pos = 1;\n\n      set_echo_state (type, file_name, pos);\n    }\n}\n\nvoid\ntree_evaluator::push_echo_state_cleanup (unwind_protect& frame)\n{\n  frame.add (&tree_evaluator::uwp_set_echo_state, this,\n             m_echo_state, m_echo_file_name, m_echo_file_pos);\n}\n\nbool\ntree_evaluator::maybe_push_echo_state_cleanup ()\n{\n  // This function is expected to be called from ECHO, which would be\n  // the top of the call stack.  If the caller of ECHO is a\n  // user-defined function or script, then set up unwind-protect\n  // elements to restore echo state.\n\n  unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame ();\n\n  if (frame)\n    {\n      push_echo_state_cleanup (*frame);\n      return true;\n    }\n\n  return false;\n}\n\n\noctave_value\ntree_evaluator::echo (const octave_value_list& args, int)\n{\n  bool cleanup_pushed = maybe_push_echo_state_cleanup ();\n\n  string_vector argv = args.make_argv ();\n\n  switch (args.length ())\n    {\n    case 0:\n      if ((m_echo & ECHO_SCRIPTS) || (m_echo & ECHO_FUNCTIONS))\n        {\n          m_echo = ECHO_OFF;\n          m_echo_files.clear ();\n        }\n      else\n        m_echo = ECHO_SCRIPTS;\n      break;\n\n    case 1:\n      {\n        std::string arg0 = argv[0];\n\n        if (arg0 == \"on\")\n          m_echo = ECHO_SCRIPTS;\n        else if (arg0 == \"off\")\n          m_echo = ECHO_OFF;\n        else\n          {\n            std::string file = fcn_file_in_path (arg0);\n            file = sys::env::make_absolute (file);\n\n            if (file.empty ())\n              error (\"echo: no such file %s\", arg0.c_str ());\n\n            if (m_echo & ECHO_ALL)\n              {\n                // Echo is enabled for all functions, so turn it off\n                // for this one.\n\n                m_echo_files[file] = false;\n              }\n            else\n              {\n                // Echo may be enabled for specific functions.\n\n                auto p = m_echo_files.find (file);\n\n                if (p == m_echo_files.end ())\n                  {\n                    // Not this one, so enable it.\n\n                    m_echo |= ECHO_FUNCTIONS;\n                    m_echo_files[file] = true;\n                  }\n                else\n                  {\n                    // This one is already in the list.  Flip the\n                    // status for it.\n\n                    p->second = ! p->second;\n                  }\n              }\n          }\n      }\n      break;\n\n    case 2:\n      {\n        std::string arg0 = argv[0];\n        std::string arg1 = argv[1];\n\n        if (arg1 == \"on\" || arg1 == \"off\")\n          std::swap (arg0, arg1);\n\n        if (arg0 == \"on\")\n          {\n            if (arg1 == \"all\")\n              {\n                m_echo = (ECHO_SCRIPTS | ECHO_FUNCTIONS | ECHO_ALL);\n                m_echo_files.clear ();\n              }\n            else\n              {\n                std::string file = fcn_file_in_path (arg1);\n                file = sys::env::make_absolute (file);\n\n                if (file.empty ())\n                  error (\"echo: no such file %s\", arg1.c_str ());\n\n                m_echo |= ECHO_FUNCTIONS;\n                m_echo_files[file] = true;\n              }\n          }\n        else if (arg0 == \"off\")\n          {\n            if (arg1 == \"all\")\n              {\n                m_echo = ECHO_OFF;\n                m_echo_files.clear ();\n              }\n            else\n              {\n                std::string file = fcn_file_in_path (arg1);\n                file = sys::env::make_absolute (file);\n\n                if (file.empty ())\n                  error (\"echo: no such file %s\", arg1.c_str ());\n\n                m_echo_files[file] = false;\n              }\n          }\n        else\n          print_usage ();\n      }\n      break;\n\n    default:\n      print_usage ();\n      break;\n    }\n\n  if (cleanup_pushed)\n    maybe_set_echo_state ();\n\n  return octave_value ();\n}\n\nbool\ntree_evaluator::in_debug_repl () const\n{\n  return (m_debugger_stack.empty ()\n          ? false : m_debugger_stack.top()->in_debug_repl ());\n}\n\nvoid\ntree_evaluator::dbcont ()\n{\n  if (! m_debugger_stack.empty ())\n    m_debugger_stack.top()->dbcont ();\n}\n\nvoid\ntree_evaluator::dbquit (bool all)\n{\n  if (! m_debugger_stack.empty ())\n    m_debugger_stack.top()->dbquit (all);\n}\n\noctave_value_list\ntree_evaluator::evaluate_end_expression (const octave_value_list& args)\n{\n  int nargin = args.length ();\n\n  if (nargin != 0 && nargin != 3)\n    print_usage ();\n\n  if (nargin == 3)\n    {\n      octave_idx_type index_position\n        = args(1).strict_idx_type_value (\"end: K must be integer value\");\n\n      if (index_position < 1)\n        error (\"end: K must be greater than zero\");\n\n      octave_idx_type num_indices\n        = args(2).strict_idx_type_value (\"end: N must be integer value\");\n\n      if (num_indices < 1)\n        error (\"end: N must be greater than zero\");\n\n      return octave_value (args(0).end_index (index_position-1, num_indices));\n    }\n\n  // If m_indexed_object is undefined, then this use of 'end' is\n  // either appearing in a function call argument list or in an\n  // attempt to index an undefined symbol.  There seems to be no\n  // reasonable way to provide a better error message.  So just fail\n  // with an invalid use message.  See bug #58830.\n\n  if (m_indexed_object.is_undefined ())\n    error (\"invalid use of 'end': may only be used to index existing value\");\n\n  octave_value expr_result;\n\n  if (m_index_list.empty ())\n    expr_result = m_indexed_object;\n  else\n    {\n      try\n        {\n          // When evaluating \"end\" with no arguments, we should have\n          // been called from the built-in Fend function that appears\n          // in the context of an argument list.  Fend will be\n          // evaluated in its own stack frame.  But we need to\n          // evaluate the partial expression that the special \"end\"\n          // token applies to in the calling stack frame.\n\n          unwind_action act ([this] (std::size_t frm)\n                             {\n                               m_call_stack.restore_frame (frm);\n                             }, m_call_stack.current_frame ());\n\n          std::size_t n = m_call_stack.find_current_user_frame ();\n          m_call_stack.goto_frame (n);\n\n          // End is only valid inside argument lists used for\n          // indexing.  The dispatch class is set by the function that\n          // evaluates the argument list.\n\n          // Silently ignore extra output values.\n\n          octave_value_list tmp\n            = m_indexed_object.subsref (m_index_type, m_index_list, 1);\n\n          expr_result = tmp.length () ? tmp(0) : octave_value ();\n\n          if (expr_result.is_cs_list ())\n            err_indexed_cs_list ();\n        }\n      catch (const index_exception&)\n        {\n          error (\"error evaluating partial expression for END\");\n        }\n    }\n\n  if (expr_result.isobject ())\n    {\n      // FIXME: is there a better way to lookup and execute a method\n      // that handles all the details like setting the dispatch class\n      // appropriately?\n\n      std::string dispatch_class = expr_result.class_name ();\n\n      symbol_table& symtab = m_interpreter.get_symbol_table ();\n\n      octave_value meth = symtab.find_method (\"end\", dispatch_class);\n\n      if (meth.is_defined ())\n        return m_interpreter.feval\n          (meth, ovl (expr_result, m_index_position+1, m_num_indices), 1);\n    }\n\n  return octave_value (expr_result.end_index (m_index_position, m_num_indices));\n}\n\noctave_value\ntree_evaluator::PS4 (const octave_value_list& args, int nargout)\n{\n  return set_internal_variable (m_PS4, args, nargout, \"PS4\");\n}\n\nbool\ntree_evaluator::echo_this_file (const std::string& file, int type) const\n{\n  if ((type & m_echo) == ECHO_SCRIPTS)\n    {\n      // Asking about scripts and echo is enabled for them.\n      return true;\n    }\n\n  if ((type & m_echo) == ECHO_FUNCTIONS)\n    {\n      // Asking about functions and echo is enabled for functions.\n      // Now, which ones?\n\n      auto p = m_echo_files.find (file);\n\n      if (m_echo & ECHO_ALL)\n        {\n          // Return true ulness echo was turned off for a specific\n          // file.\n\n          return (p == m_echo_files.end () || p->second);\n        }\n      else\n        {\n          // Return true if echo is specifically enabled for this file.\n\n          return p != m_echo_files.end () && p->second;\n        }\n    }\n\n  return false;\n}\n\nvoid\ntree_evaluator::echo_code (int line)\n{\n  std::string prefix = command_editor::decode_prompt_string (m_PS4);\n\n  octave_function *curr_fcn = m_call_stack.current_function ();\n\n  if (curr_fcn && curr_fcn->is_user_code ())\n    {\n      octave_user_code *code = dynamic_cast<octave_user_code *> (curr_fcn);\n\n      int num_lines = line - m_echo_file_pos + 1;\n\n      std::deque<std::string> lines\n        = code->get_code_lines (m_echo_file_pos, num_lines);\n\n      for (auto& elt : lines)\n        octave_stdout << prefix << elt << std::endl;\n    }\n}\n\n// Decide if it's time to quit a for or while loop.\nbool\ntree_evaluator::quit_loop_now ()\n{\n  octave_quit ();\n\n  // Maybe handle 'continue N' someday...\n\n  if (m_continuing)\n    m_continuing--;\n\n  bool quit = (m_returning || m_breaking || m_continuing);\n\n  if (m_breaking)\n    m_breaking--;\n\n  return quit;\n}\n\nvoid\ntree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names,\n                                    const Matrix& ignored_outputs,\n                                    int nargin, int nargout,\n                                    bool takes_varargs,\n                                    const octave_value_list& va_args)\n{\n  set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (arg_names));\n  set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs);\n  set_auto_fcn_var (stack_frame::NARGIN, nargin);\n  set_auto_fcn_var (stack_frame::NARGOUT, nargout);\n  set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, octave_value ());\n\n  if (takes_varargs)\n    assign (\"varargin\", va_args.cell_value ());\n}\n\nstd::string\ntree_evaluator::check_autoload_file (const std::string& nm) const\n{\n  if (sys::env::absolute_pathname (nm))\n    return nm;\n\n  std::string full_name = nm;\n\n  octave_user_code *fcn = m_call_stack.current_user_code ();\n\n  bool found = false;\n\n  if (fcn)\n    {\n      std::string fname = fcn->fcn_file_name ();\n\n      if (! fname.empty ())\n        {\n          fname = sys::env::make_absolute (fname);\n          fname = fname.substr (0, fname.find_last_of (sys::file_ops::dir_sep_str ()) + 1);\n\n          sys::file_stat fs (fname + nm);\n\n          if (fs.exists ())\n            {\n              full_name = fname + nm;\n              found = true;\n            }\n        }\n    }\n\n  if (! found)\n    warning_with_id (\"Octave:autoload-relative-file-name\",\n                     \"autoload: '%s' is not an absolute filename\",\n                     nm.c_str ());\n\n  return full_name;\n}\n\nDEFMETHOD (max_recursion_depth, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} max_recursion_depth ()\n@deftypefnx {} {@var{old_val} =} max_recursion_depth (@var{new_val})\n@deftypefnx {} {@var{old_val} =} max_recursion_depth (@var{new_val}, \"local\")\nQuery or set the internal limit on the number of times a function may\nbe called recursively.\n\nIf the limit is exceeded, an error message is printed and control returns to\nthe top level.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n\n@seealso{max_stack_depth}\n@end deftypefn */)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.max_recursion_depth (args, nargout);\n}\n\n/*\n%!test\n%! orig_val = max_recursion_depth ();\n%! old_val = max_recursion_depth (2*orig_val);\n%! assert (orig_val, old_val);\n%! assert (max_recursion_depth (), 2*orig_val);\n%! max_recursion_depth (orig_val);\n%! assert (max_recursion_depth (), orig_val);\n\n%!error max_recursion_depth (1, 2)\n*/\n\nDEFMETHOD (whos_line_format, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} whos_line_format ()\n@deftypefnx {} {@var{old_val} =} whos_line_format (@var{new_val})\n@deftypefnx {} {@var{old_val} =} whos_line_format (@var{new_val}, \"local\")\nQuery or set the format string used by the command @code{whos}.\n\nA full format string is:\n@c Set example in small font to prevent overfull line\n\n@smallexample\n%[modifier]<command>[:width[:left-min[:balance]]];\n@end smallexample\n\nThe following command sequences are available:\n\n@table @code\n@item %a\nPrints attributes of variables (c=complex, s=sparse, f=formal parameter,\ng=global, p=persistent).\n\n@item %b\nPrints number of bytes occupied by variables.\n\n@item %c\nPrints class names of variables.\n\n@item %e\nPrints elements held by variables.\n\n@item %n\nPrints variable names.\n\n@item %s\nPrints dimensions of variables.\n\n@item %t\nPrints type names of variables.\n@end table\n\nEvery command may also have an alignment modifier:\n\n@table @code\n@item l\nLeft alignment.\n\n@item r\nRight alignment (default).\n\n@item c\nColumn-aligned (only applicable to command %s).\n@end table\n\nThe @code{width} parameter is a positive integer specifying the minimum\nnumber of columns used for printing.  No maximum is needed as the field will\nauto-expand as required.\n\nThe parameters @code{left-min} and @code{balance} are only available when\nthe column-aligned modifier is used with the command @samp{%s}.\n@code{balance} specifies the column number within the field width which\nwill be aligned between entries.  Numbering starts from 0 which indicates\nthe leftmost column.  @code{left-min} specifies the minimum field width to\nthe left of the specified balance column.\n\nThe default format is:\n\n@example\n\"  %la:5; %ln:6; %cs:16:6:1;  %rb:12;  %lc:-1;@backslashchar{}n\"\n@end example\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{whos}\n@end deftypefn */)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.whos_line_format (args, nargout);\n}\n\nDEFMETHOD (silent_functions, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} silent_functions ()\n@deftypefnx {} {@var{old_val} =} silent_functions (@var{new_val})\n@deftypefnx {} {@var{old_val} =} silent_functions (@var{new_val}, \"local\")\nQuery or set the internal variable that controls whether internal\noutput from a function is suppressed.\n\nIf this option is disabled, Octave will display the results produced by\nevaluating expressions within a function body that are not terminated with\na semicolon.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.silent_functions (args, nargout);\n}\n\n/*\n%!test\n%! orig_val = silent_functions ();\n%! old_val = silent_functions (! orig_val);\n%! assert (orig_val, old_val);\n%! assert (silent_functions (), ! orig_val);\n%! silent_functions (orig_val);\n%! assert (silent_functions (), orig_val);\n\n%!error silent_functions (1, 2)\n*/\n\nDEFMETHOD (string_fill_char, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} string_fill_char ()\n@deftypefnx {} {@var{old_val} =} string_fill_char (@var{new_val})\n@deftypefnx {} {@var{old_val} =} string_fill_char (@var{new_val}, \"local\")\nQuery or set the internal variable used to pad all rows of a character\nmatrix to the same length.\n\nThe value must be a single character and the default is @qcode{\" \"} (a\nsingle space).  For example:\n\n@example\n@group\nstring_fill_char (\"X\");\n[ \"these\"; \"are\"; \"strings\" ]\n    @xresult{}  \"theseXX\"\n        \"areXXXX\"\n        \"strings\"\n@end group\n@end example\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@end deftypefn */)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.string_fill_char (args, nargout);\n}\n\n/*\n## string_fill_char() function call must be outside of %!test block\n## due to the way a %!test block is wrapped inside a function\n%!shared orig_val, old_val\n%! orig_val = string_fill_char ();\n%! old_val  = string_fill_char (\"X\");\n%!test\n%! assert (orig_val, old_val);\n%! assert (string_fill_char (), \"X\");\n%! assert ([\"these\"; \"are\"; \"strings\"], [\"theseXX\"; \"areXXXX\"; \"strings\"]);\n%! string_fill_char (orig_val);\n%! assert (string_fill_char (), orig_val);\n\n%!assert ( [ [], {1} ], {1} )\n\n%!error string_fill_char (1, 2)\n*/\n\nDEFMETHOD (PS4, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{val} =} PS4 ()\n@deftypefnx {} {@var{old_val} =} PS4 (@var{new_val})\n@deftypefnx {} {@var{old_val} =} PS4 (@var{new_val}, \"local\")\nQuery or set the character string used to prefix output produced\nwhen echoing commands is enabled.\n\nThe default value is @qcode{\"+ \"}.\n@xref{Diary and Echo Commands}, for a description of echoing commands.\n\nWhen called from inside a function with the @qcode{\"local\"} option, the\nvariable is changed locally for the function and any subroutines it calls.\nThe original variable value is restored when exiting the function.\n@seealso{echo, PS1, PS2}\n@end deftypefn */)\n{\n  return interp.PS4 (args, nargout);\n}\n\nDEFMETHOD (echo, interp, args, nargout,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {} echo\n@deftypefnx {} {} echo on\n@deftypefnx {} {} echo off\n@deftypefnx {} {} echo on all\n@deftypefnx {} {} echo off all\n@deftypefnx {} {} echo @var{function} on\n@deftypefnx {} {} echo @var{function} off\nControl whether commands are displayed as they are executed.\n\nValid options are:\n\n@table @code\n@item on\nEnable echoing of commands as they are executed in script files.\n\n@item off\nDisable echoing of commands as they are executed in script and function files.\n\n@item on all\nEnable echoing of commands as they are executed in script files and functions.\n\n@item off all\nDisable echoing of commands as they are executed in script files and functions.\n\n@item @var{function} on\nEnable echoing of commands as they are executed in the named function.\n\n@item @var{function} off\nDisable echoing of commands as they are executed in the named function.\n@end table\n\n@noindent\nWith no arguments, @code{echo} toggles the current echo state.\n\nProgramming Note: Echoing all commands can be a simple way to debug an easy\ncoding problem.  However, the amount of output can grow quite quickly.  For\nmore difficult problems the built-in debugger (@code{help debug}) is more\nuseful.\n@seealso{PS4}\n@end deftypefn */)\n{\n  tree_evaluator& tw = interp.get_evaluator ();\n\n  return tw.echo (args, nargout);\n}\n\n/*\n%!error echo ([])\n%!error echo (0)\n%!error echo (\"\")\n%!error echo (\"Octave\")\n%!error echo (\"off\", \"invalid\")\n%!error echo (\"on\", \"invalid\")\n%!error echo (\"on\", \"all\", \"all\")\n*/\n\n/*\nFIXME: Actually, it probably *isn't* worth fixing, but there is one small\ndifference between Octave and Matlab.\n\nIf inputname is not called from a function, Matlab walks up the stack until it\nfinds some valid code and then works from there.  This could be relevant for\nmex files or anonymous functions.\n\nfcn = @(x) inputname (x);\na = 1:4;\narrayfun (fcn, a, 'uniformoutput', false)\n% output is {'fcn', 'a', '', ''}\n*/\nDEFMETHOD (inputname, interp, args, ,\n           doc: /* -*- texinfo -*-\n@deftypefn  {} {@var{namestr} =} inputname (@var{n})\n@deftypefnx {} {@var{namestr} =} inputname (@var{n}, @var{ids_only})\nReturn the name of the @var{n}-th argument to the calling function.\n\nIf the argument is not a simple variable name, return an empty string.\nExamples which will return @qcode{\"\"} are numbers (@code{5.1}), expressions\n(@code{@var{y}/2}), and cell or structure indexing (@code{@var{c}@{1@}} or\n@code{@var{s}.@var{field}}).\n\n@code{inputname} is only useful within a function.  When used at the command\nline or within a script it always returns an empty string.\n\nBy default, return an empty string if the @var{n}-th argument is not a valid\nvariable name.  If the optional argument @var{ids_only} is false, return the\ntext of the argument even if it is not a valid variable name.  This is an\nOctave extension that allows the programmer to view exactly how the function\nwas invoked even when the inputs are complex expressions.\n@seealso{nargin, narginchk}\n@end deftypefn */)\n{\n  int nargin = args.length ();\n\n  if (nargin < 1)\n    print_usage ();\n\n  dim_vector dims = args(0).dims ();\n  if (! dims.all_ones ())\n    error (\"inputname: N must be a scalar index\");\n\n  int n = args(0).strict_int_value (\"inputname: N must be a scalar index\");\n\n  if (n < 1)\n    error (\"inputname: N must be a scalar index\");\n\n  bool ids_only = true;\n\n  if (nargin == 2)\n    ids_only = args(1).strict_bool_value (\"inputname: IDS_ONLY must be a logical value\");\n\n  // Use zero-based indexing internally.\n  return ovl (interp.inputname (n-1, ids_only));\n}\n\n/*\n%!function name = __iname1__ (arg1, arg2, arg3)\n%!  name = inputname (1);\n%!endfunction\n\n%!function name = __iname1_ID__ (arg1, arg2, arg3)\n%!  name = inputname (1, false);\n%!endfunction\n\n%!function name = __iname2__ (arg1, arg2, arg3)\n%!  name = inputname (2);\n%!endfunction\n\n%!function names = __iname3__ (arg1, arg2, arg3)\n%!  names = cell (1, 3);\n%!  for i = 1:3\n%!    names{i} = inputname (i);\n%!  endfor\n%!endfunction\n\n%!test\n%! assert (__iname1__ ('xvar'), \"\");\n%! xvar = 1;\n%! assert (__iname1__ (xvar), \"xvar\");\n\n%!test\n%! xvar = 1;  yvar = 2;\n%! assert (__iname2__ (xvar), \"\");\n%! assert (__iname2__ (xvar, yvar), \"yvar\");\n\n%!test\n%! xvar = 1;  yvar = 2;\n%! assert (__iname3__ (xvar), {\"xvar\", \"\", \"\"});\n%! assert (__iname3__ (xvar, yvar), {\"xvar\", \"yvar\", \"\"});\n%! assert (__iname3__ (xvar, 3, yvar), {\"xvar\", \"\", \"yvar\"});\n\n## Test numbers, expressions, indexing operations\n%!test\n%! assert (__iname1__ (1.0), \"\");\n%! x = 1;\n%! assert (__iname1__ (x / 2), \"\");\n%! assert (__iname1__ (Inf), \"\");\n\n%!test\n%! assert (__iname1_ID__ (1.0), \"1.0\");\n%! x = 1;\n%! assert (__iname1_ID__ (x / 2), \"x / 2\");\n%! assert (__iname1_ID__ (Inf), \"Inf\");\n\n%!error <Invalid call> inputname ()\n%!error <N must be a scalar> inputname (ones (2,2))\n%!error <N must be a scalar index> inputname (-1)\n*/\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-eval.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_eval_h)\n#define octave_pt_eval_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <list>\n#include <memory>\n#include <set>\n#include <stack>\n#include <string>\n\n#include \"bp-table.h\"\n#include \"call-stack.h\"\n#include \"oct-lvalue.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"profiler.h\"\n#include \"pt-walk.h\"\n#include \"stack-frame.h\"\n\nclass octave_builtin;\nclass octave_mex_function;\nclass octave_user_code;\nclass octave_user_function;\nclass octave_user_script;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_info_list;\nclass symbol_scope;\nclass tree_decl_elt;\nclass tree_expression;\n\nclass debugger;\nclass interpreter;\nclass push_parser;\nclass unwind_protect;\n\n// How to evaluate the code that the parse trees represent.\n\nclass OCTINTERP_API tree_evaluator : public tree_walker\n{\npublic:\n\n  enum echo_state\n  {\n    ECHO_OFF = 0,\n    ECHO_SCRIPTS = 1,\n    ECHO_FUNCTIONS = 2,\n    ECHO_ALL = 4\n  };\n\n  // Possible types of evaluation contexts.\n  enum stmt_list_type\n  {\n    SC_FUNCTION,  // function body\n    SC_SCRIPT,    // script file\n    SC_OTHER      // command-line input or eval string\n  };\n\n  typedef void (*decl_elt_init_fcn) (tree_decl_elt&);\n\n  template <typename T>\n  class value_stack\n  {\n  public:\n\n    OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (value_stack)\n\n    void push (const T& val) { m_stack.push (val); }\n\n    void pop ()\n    {\n      m_stack.pop ();\n    }\n\n    T val_pop ()\n    {\n      T retval = m_stack.top ();\n      m_stack.pop ();\n      return retval;\n    }\n\n    T top () const\n    {\n      return m_stack.top ();\n    }\n\n    std::size_t size () const\n    {\n      return m_stack.size ();\n    }\n\n    bool empty () const\n    {\n      return m_stack.empty ();\n    }\n\n    void clear ()\n    {\n      while (! m_stack.empty ())\n        m_stack.pop ();\n    }\n\n  private:\n\n    std::stack<T> m_stack;\n  };\n\n  tree_evaluator (interpreter& interp)\n    : m_interpreter (interp), m_parser (), m_error_system (interp),\n      m_statement_context (SC_OTHER), m_lvalue_list (nullptr),\n      m_autoload_map (), m_bp_table (*this), m_call_stack (*this),\n      m_profiler (), m_debug_frame (0), m_debug_mode (false),\n      m_quiet_breakpoint_flag (false), m_debugger_stack (), m_exit_status (0),\n      m_max_recursion_depth (256),\n      m_whos_line_format (\"  %la:5; %ln:6; %cs:16:6:1;  %rb:12;  %lc:-1;\\n\"),\n      m_silent_functions (false), m_string_fill_char (' '), m_PS4 (\"+ \"),\n      m_dbstep_flag (0), m_break_on_next_stmt (false), m_echo (ECHO_OFF),\n      m_echo_state (false), m_echo_file_name (),\n      m_echo_file_pos (1),\n      m_echo_files (), m_in_top_level_repl (false),\n      m_server_mode (false), m_in_loop_command (false),\n      m_breaking (0), m_continuing (0), m_returning (0),\n      m_indexed_object (), m_index_list (), m_index_type (),\n      m_index_position (0), m_num_indices (0)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_evaluator)\n\n  ~tree_evaluator () = default;\n\n  std::shared_ptr<push_parser> get_parser ()\n  {\n    return m_parser;\n  }\n\n  void set_parser (const std::shared_ptr<push_parser>& parser)\n  {\n    m_parser = parser;\n  }\n\n  error_system& get_error_system ()\n  {\n    return m_error_system;\n  }\n\n  bool at_top_level () const;\n\n  std::string mfilename (const std::string& opt = \"\") const;\n\n  // Parse a line of input.  If input ends at a complete statement\n  // boundary, execute the resulting parse tree.  Useful to handle\n  // parsing user input when running in server mode.\n\n  void parse_and_execute (const std::string& input, bool& incomplete_parse);\n\n  void get_line_and_eval ();\n\n  int repl ();\n\n  bool in_top_level_repl () const { return m_in_top_level_repl; }\n\n  int server_loop ();\n\n  bool server_mode () const { return m_server_mode; }\n\n  void server_mode (bool arg) { m_server_mode = arg; }\n\n  void eval (std::shared_ptr<tree_statement_list>& stmt_list,\n             bool interactive);\n\n  octave_value_list eval_string (const std::string& eval_str, bool silent,\n                                 int& parse_status, int nargout);\n\n  octave_value eval_string (const std::string& eval_str, bool silent,\n                            int& parse_status);\n\n  octave_value_list eval_string (const octave_value& arg, bool silent,\n                                 int& parse_status, int nargout);\n\n  octave_value_list eval (const std::string& try_code, int nargout);\n\n  octave_value_list eval (const std::string& try_code,\n                          const std::string& catch_code, int nargout);\n\n  octave_value_list evalin (const std::string& context,\n                            const std::string& try_code, int nargout);\n\n  octave_value_list evalin (const std::string& context,\n                            const std::string& try_code,\n                            const std::string& catch_code, int nargout);\n\n  void visit_anon_fcn_handle (tree_anon_fcn_handle&);\n\n  void visit_argument_list (tree_argument_list&);\n\n  void visit_arguments_block (tree_arguments_block&);\n\n  void visit_args_block_attribute_list (tree_args_block_attribute_list&);\n\n  void visit_args_block_validation_list (tree_args_block_validation_list&);\n\n  void visit_arg_validation (tree_arg_validation&);\n\n  void visit_arg_size_spec (tree_arg_size_spec&);\n\n  void visit_arg_validation_fcns (tree_arg_validation_fcns&);\n\n  void visit_binary_expression (tree_binary_expression&);\n\n  void visit_boolean_expression (tree_boolean_expression&);\n\n  void visit_compound_binary_expression (tree_compound_binary_expression&);\n\n  void visit_break_command (tree_break_command&);\n\n  void visit_colon_expression (tree_colon_expression&);\n\n  void visit_continue_command (tree_continue_command&);\n\n  void visit_decl_command (tree_decl_command&);\n\n  void visit_decl_elt (tree_decl_elt&);\n\n  void visit_simple_for_command (tree_simple_for_command&);\n\n  void visit_complex_for_command (tree_complex_for_command&);\n\n  void visit_spmd_command (tree_spmd_command&);\n\n  octave_value evaluate_anon_fcn_handle (tree_anon_fcn_handle& afh);\n\n  octave_value_list\n  execute_builtin_function (octave_builtin& builtin_function, int nargout,\n                            const octave_value_list& args);\n  octave_value_list\n  execute_mex_function (octave_mex_function& mex_function, int nargout,\n                        const octave_value_list& args);\n\n  void visit_octave_user_script (octave_user_script&);\n\n  octave_value_list\n  execute_user_script (octave_user_script& user_script, int nargout,\n                       const octave_value_list& args);\n\n  void visit_octave_user_function (octave_user_function&);\n\n  octave_value_list\n  execute_user_function (octave_user_function& user_function,\n                         int nargout, const octave_value_list& args);\n\n  void visit_octave_user_function_header (octave_user_function&);\n\n  void visit_octave_user_function_trailer (octave_user_function&);\n\n  void visit_function_def (tree_function_def&);\n\n  void visit_identifier (tree_identifier&);\n\n  void visit_if_clause (tree_if_clause&);\n\n  void visit_if_command (tree_if_command&);\n\n  void visit_if_command_list (tree_if_command_list&);\n\n  void visit_index_expression (tree_index_expression&);\n\n  void visit_matrix (tree_matrix&);\n\n  void visit_cell (tree_cell&);\n\n  void visit_multi_assignment (tree_multi_assignment&);\n\n  void visit_no_op_command (tree_no_op_command&);\n\n  void visit_constant (tree_constant&);\n\n  void visit_fcn_handle (tree_fcn_handle&);\n\n  void visit_parameter_list (tree_parameter_list&);\n\n  void visit_postfix_expression (tree_postfix_expression&);\n\n  void visit_prefix_expression (tree_prefix_expression&);\n\n  void visit_return_command (tree_return_command&);\n\n  void visit_simple_assignment (tree_simple_assignment&);\n\n  void visit_statement (tree_statement&);\n\n  void visit_statement_list (tree_statement_list&);\n\n  void visit_switch_case (tree_switch_case&);\n\n  void visit_switch_case_list (tree_switch_case_list&);\n\n  void visit_switch_command (tree_switch_command&);\n\n  void visit_try_catch_command (tree_try_catch_command&);\n\n  void do_unwind_protect_cleanup_code (tree_statement_list *list);\n\n  void visit_unwind_protect_command (tree_unwind_protect_command&);\n\n  void visit_while_command (tree_while_command&);\n  void visit_do_until_command (tree_do_until_command&);\n\n  void visit_superclass_ref (tree_superclass_ref&);\n  void visit_metaclass_query (tree_metaclass_query&);\n\n  void bind_ans (const octave_value& val, bool print);\n\n  bool statement_printing_enabled ();\n\n  void reset_debug_state ();\n\n  void reset_debug_state (bool mode);\n\n  void enter_debugger (const std::string& prompt = \"debug> \");\n\n  void keyboard (const std::string& prompt = \"debug> \");\n\n  void dbupdown (int n, bool verbose = false);\n\n  Matrix ignored_fcn_outputs () const;\n\n  std::string inputname (int n, bool ids_only = true) const;\n\n  octave_value make_fcn_handle (const std::string& nm);\n\n  octave_value evaluate (tree_decl_elt *);\n\n  void install_variable (const std::string& name,\n                         const octave_value& value, bool global);\n\n  octave_value global_varval (const std::string& name) const;\n\n  octave_value& global_varref (const std::string& name);\n\n  void global_assign (const std::string& name,\n                      const octave_value& val = octave_value ());\n\n  octave_value top_level_varval (const std::string& name) const;\n\n  void top_level_assign (const std::string& name,\n                         const octave_value& val = octave_value ());\n\n  bool is_variable (const std::string& name) const;\n\n  bool is_local_variable (const std::string& name) const;\n\n  bool is_variable (const tree_expression *expr) const;\n\n  bool is_defined (const tree_expression *expr) const;\n\n  bool is_variable (const symbol_record& sym) const;\n\n  bool is_defined (const symbol_record& sym) const;\n\n  bool is_global (const std::string& name) const;\n\n  octave_value varval (const symbol_record& sym) const;\n\n  octave_value varval (const std::string& name) const;\n\n  void assign (const std::string& name,\n               const octave_value& val = octave_value ());\n\n  void assignin (const std::string& context, const std::string& name,\n                 const octave_value& val = octave_value ());\n\n  void source_file (const std::string& file_name,\n                    const std::string& context = \"\",\n                    bool verbose = false, bool require_file = true);\n\n  void set_auto_fcn_var (stack_frame::auto_var_type avt,\n                         const octave_value& val = octave_value ());\n\n  void set_nargin (int nargin);\n  void set_nargout (int nargout);\n\n  octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const;\n\n  void define_parameter_list_from_arg_vector\n  (tree_parameter_list *param_list, const octave_value_list& args);\n\n  void undefine_parameter_list (tree_parameter_list *param_list);\n\n  octave_value_list convert_to_const_vector (tree_argument_list *arg_list);\n\n  octave_value_list\n  convert_return_list_to_const_vector\n  (tree_parameter_list *ret_list, int nargout, const Cell& varargout);\n\n  bool eval_decl_elt (tree_decl_elt *elt);\n\n  bool switch_case_label_matches (tree_switch_case *expr,\n                                  const octave_value& val);\n\n  interpreter& get_interpreter () { return m_interpreter; }\n\n  bp_table& get_bp_table () { return m_bp_table; }\n\n  profiler& get_profiler () { return m_profiler; }\n\n  void push_stack_frame (const symbol_scope& scope);\n\n  void push_stack_frame (octave_user_function *fcn,\n                         const std::shared_ptr<stack_frame>& closure_frames = std::shared_ptr<stack_frame> ());\n\n  void push_stack_frame (octave_user_function *fcn,\n                         const stack_frame::local_vars_map& local_vars,\n                         const std::shared_ptr<stack_frame>& closure_frames = std::shared_ptr<stack_frame> ());\n\n  void push_stack_frame (octave_user_script *script);\n\n  void push_stack_frame (octave_function *fcn);\n\n  void pop_stack_frame ();\n\n  std::shared_ptr<stack_frame> pop_return_stack_frame ();\n\n  std::shared_ptr<stack_frame> get_current_stack_frame () const\n  {\n    return m_call_stack.get_current_stack_frame ();\n  }\n\n  std::shared_ptr<stack_frame> current_user_frame () const\n  {\n    return m_call_stack.current_user_frame ();\n  }\n\n  // Current line in current function.\n  int current_line () const;\n\n  // Current column in current function.\n  int current_column () const;\n\n  // Line number in current function that we are debugging.\n  int debug_user_code_line () const;\n\n  // Column number in current function that we are debugging.\n  int debug_user_code_column () const;\n\n  void debug_where (std::ostream& os) const;\n\n  void debug_list (std::ostream& os, int num_lines) const;\n\n  void debug_type (std::ostream& os, int start_line, int end_line) const;\n\n  octave_user_code * current_user_code () const;\n\n  unwind_protect * curr_fcn_unwind_protect_frame ();\n\n  // Current function that we are debugging.\n  octave_user_code * debug_user_code () const;\n\n  octave_function * current_function (bool skip_first = false) const;\n\n  octave_function * caller_function () const;\n\n  bool goto_frame (std::size_t n = 0, bool verbose = false);\n\n  void goto_caller_frame ();\n\n  void goto_base_frame ();\n\n  void restore_frame (std::size_t n);\n\n  std::string get_dispatch_class () const;\n\n  void set_dispatch_class (const std::string& class_name);\n\n  bool is_class_method_executing (std::string& dispatch_class) const;\n\n  bool is_class_constructor_executing (std::string& dispatch_class) const;\n\n  std::list<std::shared_ptr<stack_frame>>\n                                       backtrace_frames (octave_idx_type& curr_user_frame) const;\n\n  std::list<std::shared_ptr<stack_frame>> backtrace_frames () const;\n\n  std::list<frame_info> backtrace_info (octave_idx_type& curr_user_frame,\n                                        bool print_subfn = true) const;\n\n  std::list<frame_info> backtrace_info () const;\n\n  octave_map backtrace (octave_idx_type& curr_user_frame,\n                        bool print_subfn = true) const;\n\n  octave_map backtrace () const;\n\n  octave_map empty_backtrace () const;\n\n  std::string backtrace_message () const;\n\n  void push_dummy_scope (const std::string& name);\n  void pop_scope ();\n\n  symbol_scope get_top_scope () const;\n  symbol_scope get_current_scope () const;\n\n  void mlock (bool skip_first = false) const;\n\n  void munlock (bool skip_first = false) const;\n\n  bool mislocked (bool skip_first = false) const;\n\n  octave_value max_stack_depth (const octave_value_list& args, int nargout);\n\n  // Useful for debugging\n  void display_call_stack () const;\n\n  octave_value find (const std::string& name);\n\n  void clear_objects ();\n\n  void clear_variable (const std::string& name);\n\n  void clear_variable_pattern (const std::string& pattern);\n\n  void clear_variable_regexp (const std::string& pattern);\n\n  void clear_variables ();\n\n  void clear_global_variable (const std::string& name);\n\n  void clear_global_variable_pattern (const std::string& pattern);\n\n  void clear_global_variable_regexp (const std::string& pattern);\n\n  void clear_global_variables ();\n\n  void clear_all (bool force = false);\n\n  void clear_symbol (const std::string& name);\n\n  void clear_symbol_pattern (const std::string& pattern);\n\n  void clear_symbol_regexp (const std::string& pattern);\n\n  std::list<std::string> global_variable_names () const;\n\n  std::list<std::string> top_level_variable_names () const;\n\n  std::list<std::string> variable_names () const;\n\n  octave_user_code * get_user_code (const std::string& fname = \"\");\n\n  std::string current_function_name (bool skip_first = false) const;\n\n  bool in_user_code () const;\n\n  symbol_info_list glob_symbol_info (const std::string& pattern) const;\n\n  symbol_info_list regexp_symbol_info (const std::string& pattern) const;\n\n  symbol_info_list get_symbol_info ();\n\n  symbol_info_list top_scope_symbol_info () const;\n\n  octave_map get_autoload_map () const;\n\n  std::string lookup_autoload (const std::string& nm) const;\n\n  std::list<std::string> autoloaded_functions () const;\n\n  std::list<std::string> reverse_lookup_autoload (const std::string& nm) const;\n\n  void add_autoload (const std::string& fcn, const std::string& nm);\n\n  void remove_autoload (const std::string& fcn, const std::string& nm);\n\n  int max_recursion_depth () const { return m_max_recursion_depth; }\n\n  int max_recursion_depth (int n)\n  {\n    int val = m_max_recursion_depth;\n    m_max_recursion_depth = n;\n    return val;\n  }\n\n  octave_value\n  max_recursion_depth (const octave_value_list& args, int nargout);\n\n  bool silent_functions () const { return m_silent_functions; }\n\n  bool silent_functions (bool b)\n  {\n    int val = m_silent_functions;\n    m_silent_functions = b;\n    return val;\n  }\n\n  octave_value whos_line_format (const octave_value_list& args, int nargout);\n\n  std::string whos_line_format () const { return m_whos_line_format; }\n\n  std::string whos_line_format (const std::string& s)\n  {\n    std::string val = m_whos_line_format;\n    m_whos_line_format = s;\n    return val;\n  }\n\n  octave_value\n  silent_functions (const octave_value_list& args, int nargout);\n\n  std::size_t debug_frame () const { return m_debug_frame; }\n\n  std::size_t debug_frame (std::size_t n)\n  {\n    std::size_t val = m_debug_frame;\n    m_debug_frame = n;\n    return val;\n  }\n\n  std::size_t current_call_stack_frame_number () const\n  {\n    return m_call_stack.current_frame ();\n  }\n\n  bool quiet_breakpoint_flag () const { return m_quiet_breakpoint_flag; }\n\n  bool quiet_breakpoint_flag (bool flag)\n  {\n    bool val = m_quiet_breakpoint_flag;\n    m_quiet_breakpoint_flag = flag;\n    return val;\n  }\n\n  char string_fill_char () const { return m_string_fill_char; }\n\n  char string_fill_char (char c)\n  {\n    int val = m_string_fill_char;\n    m_string_fill_char = c;\n    return val;\n  }\n\n  // The following functions are provided for convenience.  They\n  // call the corresponding functions in the debugger class for the\n  // current debugger (if any).\n\n  bool in_debug_repl () const;\n\n  void dbcont ();\n\n  // Return true if we are in the debug repl and m_execution_mode is\n  // set to exit the debugger.  Otherwise, do nothing.\n\n  void dbquit (bool all = false);\n\n  // Add EXPR to the set of expressions that may be evaluated when the\n  // debugger stops at a breakpoint.\n  void add_debug_watch_expression (const std::string& expr)\n  {\n    m_debug_watch_expressions.insert (expr);\n  }\n\n  // Remove EXPR from the set of expressions that may be evaluated\n  // when the debugger stops at a breakpoint.\n  void remove_debug_watch_expression (const std::string& expr)\n  {\n    m_debug_watch_expressions.erase (expr);\n  }\n\n  // Clear the set of expressions that may be evaluated when the\n  // debugger stops at a breakpoint.\n  void clear_debug_watch_expressions ()\n  {\n    m_debug_watch_expressions.clear ();\n  }\n\n  // Return the set of expressions that may be evaluated when the\n  // debugger stops at a breakpoint.\n  std::set<std::string> debug_watch_expressions () const\n  {\n    return m_debug_watch_expressions;\n  }\n\n  octave_value PS4 (const octave_value_list& args, int nargout);\n\n  std::string PS4 () const { return m_PS4; }\n\n  std::string PS4 (const std::string& s)\n  {\n    std::string val = m_PS4;\n    m_PS4 = s;\n    return val;\n  }\n\n  void set_PS4 (const std::string& s) { m_PS4 = s; }\n\n  octave_value indexed_object () const\n  {\n    return m_indexed_object;\n  }\n\n  void set_indexed_object (const octave_value& obj = octave_value ())\n  {\n    m_indexed_object = obj;\n  }\n\n  const std::list<octave_value_list>& index_list () const\n  {\n    return m_index_list;\n  }\n\n  void set_index_list (const std::string& index_type,\n                       const std::list<octave_value_list>& index_list)\n  {\n    m_index_type = index_type;\n    m_index_list = index_list;\n  }\n\n  void clear_index_list ()\n  {\n    m_index_type = \"\";\n    m_index_list.clear ();\n  }\n\n  void append_index_list (char type, const octave_value_list& idx)\n  {\n    m_index_type += type;\n    m_index_list.push_back (idx);\n  }\n\n  const std::string& index_type () const\n  {\n    return m_index_type;\n  }\n\n  int index_position () const { return m_index_position; }\n\n  int num_indices () const { return m_num_indices; }\n\n  octave_value_list evaluate_end_expression (const octave_value_list& args);\n\n  const std::list<octave_lvalue> * lvalue_list () const\n  {\n    return m_lvalue_list;\n  }\n\n  void set_lvalue_list (const std::list<octave_lvalue> *lst)\n  {\n    m_lvalue_list = lst;\n  }\n\n  int breaking () const { return m_breaking; }\n\n  int breaking (int n)\n  {\n    int val = m_breaking;\n    m_breaking = n;\n    return val;\n  }\n\n  int continuing () const { return m_continuing; }\n\n  int continuing (int n)\n  {\n    int val = m_continuing;\n    m_continuing = n;\n    return val;\n  }\n\n  int returning () const { return m_returning; }\n\n  int returning (int n)\n  {\n    int val = m_returning;\n    m_returning = n;\n    return val;\n  }\n\n  int dbstep_flag () const { return m_dbstep_flag; }\n\n  int dbstep_flag (int val)\n  {\n    int old_val = m_dbstep_flag;\n    m_dbstep_flag = val;\n    return old_val;\n  }\n\n  void set_dbstep_flag (int step) { m_dbstep_flag = step; }\n\n  bool break_on_next_statement () const\n  {\n    return m_break_on_next_stmt;\n  }\n\n  bool break_on_next_statement (bool val)\n  {\n    bool old_val = m_break_on_next_stmt;\n    m_break_on_next_stmt = val;\n    return old_val;\n  }\n\n  void set_break_on_next_statement (bool val)\n  {\n    m_break_on_next_stmt = val;\n  }\n\n  octave_value echo (const octave_value_list& args, int nargout);\n\n  int echo () const { return m_echo; }\n\n  int echo (int val)\n  {\n    int old_val = m_echo;\n    m_echo = val;\n\n    return old_val;\n  }\n\n  octave_value\n  string_fill_char (const octave_value_list& args, int nargout);\n\n  void final_index_error (index_exception& ie, const tree_expression *expr);\n\n  octave_value do_who (int argc, const string_vector& argv,\n                       bool return_list, bool verbose = false);\n\n  octave_value_list\n  make_value_list (tree_argument_list *args, const string_vector& arg_nm);\n\n  std::list<octave_lvalue> make_lvalue_list (tree_argument_list *);\n\n  void push_echo_state (int type, const std::string& file_name, int pos = 1);\n\n  bool debug_mode () const { return m_debug_mode; }\n\n  int echo_state () { return m_echo_state; }\n\n  void set_echo_file_pos (int pos)\n  {\n    m_echo_file_pos = pos;\n  }\n\nprivate:\n\n  template <typename T>\n  void execute_range_loop (const range<T>& rng, int line,\n                           octave_lvalue& ult,\n                           tree_statement_list *loop_body);\n\n  void set_echo_state (int type, const std::string& file_name, int pos);\n\n  void maybe_set_echo_state ();\n\n  void push_echo_state_cleanup (unwind_protect& frame);\n\n  bool maybe_push_echo_state_cleanup ();\n\n  void do_breakpoint (tree_statement& stmt);\n\n  void do_breakpoint (bool is_breakpoint,\n                      bool is_end_of_fcn_or_script = false);\n\n  bool is_logically_true (tree_expression *expr, const char *warn_for);\n\n  // For unwind-protect.\n  void uwp_set_echo_state (bool state, const std::string& file_name, int pos);\n\n  bool echo_this_file (const std::string& file, int type) const;\n\n  void echo_code (int line);\n\n  bool quit_loop_now ();\n\n  void bind_auto_fcn_vars (const string_vector& arg_names,\n                           const Matrix& ignored_outputs, int nargin,\n                           int nargout, bool takes_varargs,\n                           const octave_value_list& va_args);\n\n  std::string check_autoload_file (const std::string& nm) const;\n\n  //--------\n\n  interpreter& m_interpreter;\n\n  std::shared_ptr<push_parser> m_parser;\n\n  error_system m_error_system;\n\n  // The context for the current evaluation.\n  stmt_list_type m_statement_context;\n\n  const std::list<octave_lvalue> *m_lvalue_list;\n\n  // List of autoloads (function -> file mapping).\n  std::map<std::string, std::string> m_autoload_map;\n\n  bp_table m_bp_table;\n\n  call_stack m_call_stack;\n\n  profiler m_profiler;\n\n  // The number of the stack frame we are currently debugging.\n  std::size_t m_debug_frame;\n\n  bool m_debug_mode;\n\n  bool m_quiet_breakpoint_flag;\n\n  // When entering the debugger we push it on this stack.  Managing\n  // debugger invocations this way allows us to handle recursive\n  // debugger calls.  When we exit a debugger the object is popped\n  // from the stack and deleted and we resume working with the\n  // previous debugger (if any) that is now at the top of the stack.\n  std::stack<debugger *> m_debugger_stack;\n\n  std::set<std::string> m_debug_watch_expressions;\n\n  int m_exit_status;\n\n  // Maximum nesting level for functions, scripts, or sourced files\n  // called recursively.\n  int m_max_recursion_depth;\n\n  // Defines layout for the whos/who -long command\n  std::string m_whos_line_format;\n\n  // If TRUE, turn off printing of results in functions (as if a\n  // semicolon has been appended to each statement).\n  bool m_silent_functions;\n\n  // The character to fill with when creating string arrays.\n  char m_string_fill_char;\n\n  // String printed before echoed commands (enabled by --echo-commands).\n  std::string m_PS4;\n\n  // If > 0, stop executing at the (N-1)th stopping point, counting\n  //         from the current execution point in the current frame.\n  //\n  // If < 0, stop executing at the next possible stopping point.\n  int m_dbstep_flag;\n\n  // If TRUE, and we are not stopping for another reason (dbstep or a\n  // breakpoint) then stop at next statement and enter the debugger.\n  bool m_break_on_next_stmt;\n\n  // Echo commands as they are executed?\n  //\n  //   1 => echo commands read from script files\n  //   2 => echo commands from functions\n  //\n  // more than one state can be active at once.\n  int m_echo;\n\n  // Are we currently echoing commands?  This state is set by the\n  // functions that execute functions and scripts.\n  bool m_echo_state;\n\n  std::string m_echo_file_name;\n\n  // Next line to echo, counting from 1.  We use int here because the\n  // parser does.  It also initializes line and column numbers to the\n  // invalid value -1 and that can cause trouble if cast to an\n  // unsigned value.  When updating this value and echoing ranges of\n  // code, we also check to ensure that the line numbers stored in the\n  // parse tree are valid.  It would be better to ensure that the\n  // parser always stores valid position info, but that's more\n  // difficult to always do correctly.\n  int m_echo_file_pos;\n\n  std::map<std::string, bool> m_echo_files;\n\n  // TRUE if we are in the top level interactive read eval print loop.\n  bool m_in_top_level_repl;\n\n  // TRUE means we are executing in the server_loop function.\n  bool m_server_mode;\n\n  // TRUE means we are evaluating some kind of looping construct.\n  bool m_in_loop_command;\n\n  // Nonzero means we're breaking out of a loop or function body.\n  int m_breaking;\n\n  // Nonzero means we're jumping to the end of a loop.\n  int m_continuing;\n\n  // Nonzero means we're returning from a function.\n  int m_returning;\n\n  // The following are all used by the END function.  Maybe they\n  // should be kept together in a separate object?\n  octave_value m_indexed_object;\n  std::list<octave_value_list> m_index_list;\n  std::string m_index_type;\n  int m_index_position;\n  int m_num_indices;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-except.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"quit.h\"\n\n#include \"error.h\"\n#include \"oct-lvalue.h\"\n#include \"ov.h\"\n#include \"pt-bp.h\"\n#include \"pt-cmd.h\"\n#include \"pt-except.h\"\n#include \"pt-exp.h\"\n#include \"pt-id.h\"\n#include \"pt-jump.h\"\n#include \"pt-stmt.h\"\n#include \"pt-walk.h\"\n#include \"unwind-prot.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Simple exception handling.\n\ntree_try_catch_command::~tree_try_catch_command ()\n{\n  delete m_expr_id;\n  delete m_try_code;\n  delete m_catch_code;\n}\n\n// Simple exception handling.\n\ntree_unwind_protect_command::~tree_unwind_protect_command ()\n{\n  delete m_unwind_protect_code;\n  delete m_cleanup_code;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-except.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_except_h)\n#define octave_pt_except_h 1\n\n#include \"octave-config.h\"\n\n#include \"pt-cmd.h\"\n#include \"pt-id.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass comment_list;\nclass tree_statement_list;\n\n// Simple exception handling.\n\nclass OCTINTERP_API tree_try_catch_command : public tree_command\n{\npublic:\n\n  tree_try_catch_command (const token try_tok, tree_statement_list *tc, const token catch_tok, tree_identifier *id, tree_statement_list *cc, const token& end_tok)\n    : m_try_tok (try_tok), m_try_code (tc), m_catch_tok (catch_tok), m_expr_id (id), m_catch_code (cc), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_try_catch_command)\n\n  ~tree_try_catch_command ();\n\n  filepos beg_pos () const { return m_try_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_try_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  token try_token () const { return m_try_tok; }\n\n  tree_statement_list * body () { return m_try_code; }\n\n  token catch_token () const { return m_catch_tok; }\n\n  tree_identifier * identifier () { return m_expr_id; }\n\n  tree_statement_list * cleanup () { return m_catch_code; }\n\n  token end_token () const { return m_end_tok; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_try_catch_command (*this);\n  }\n\nprivate:\n\n  token m_try_tok;\n\n  // The first block of code to attempt to execute.\n  tree_statement_list *m_try_code;\n\n  token m_catch_tok;\n\n  // Identifier to modify.\n  tree_identifier *m_expr_id;\n\n  // The code to execute if an error occurs in the first block.\n  tree_statement_list *m_catch_code;\n\n  token m_end_tok;\n};\n\n// Simple exception handling.\n\nclass OCTINTERP_API tree_unwind_protect_command : public tree_command\n{\npublic:\n\n  tree_unwind_protect_command (const token& unwind_tok, tree_statement_list *tc, const token& cleanup_tok, tree_statement_list *cc, const token& end_tok)\n    : m_unwind_tok (unwind_tok), m_unwind_protect_code (tc), m_cleanup_tok (cleanup_tok), m_cleanup_code (cc), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_unwind_protect_command)\n\n  ~tree_unwind_protect_command ();\n\n  filepos beg_pos () const { return m_unwind_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_unwind_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  token unwind_token () const { return m_unwind_tok; }\n\n  tree_statement_list * body () { return m_unwind_protect_code; }\n\n  token cleanup_token () { return m_cleanup_tok; }\n\n  tree_statement_list * cleanup () { return m_cleanup_code; }\n\n  token end_token () { return m_end_tok; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_unwind_protect_command (*this);\n  }\n\nprivate:\n\n  token m_unwind_tok;\n\n  // The first body of code to attempt to execute.\n  tree_statement_list *m_unwind_protect_code;\n\n  token m_cleanup_tok;\n\n  // The body of code to execute no matter what happens in the first\n  // body of code.\n  tree_statement_list *m_cleanup_code;\n\n  token m_end_tok;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-exp.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"error.h\"\n#include \"pager.h\"\n#include \"oct-lvalue.h\"\n#include \"ov.h\"\n#include \"pt-exp.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Expressions.\n\noctave_lvalue\ntree_expression::lvalue (tree_evaluator&)\n{\n  error (\"invalid lvalue function called in expression\");\n}\n\nstd::string\ntree_expression::original_text () const\n{\n  return \"\";\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-exp.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_exp_h)\n#define octave_pt_exp_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n#include <list>\n\nclass octave_value;\n\n#include \"pt.h\"\n#include \"pt-delimiter-list.h\"\n#include \"pt-eval.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\nclass octave_lvalue;\n\n// A base class for expressions.\n\nclass OCTINTERP_API tree_expression : public tree\n{\npublic:\n\n  tree_expression ()\n    : m_postfix_index_type ('\\0'), m_for_cmd_expr (false), m_print_flag (false)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_expression)\n\n  virtual ~tree_expression () = default;\n\n  virtual tree_expression * dup (symbol_scope& scope) const = 0;\n\n  virtual bool is_constant () const { return false; }\n\n  virtual bool is_matrix () const { return false; }\n\n  virtual bool iscell () const { return false; }\n\n  virtual bool is_identifier () const { return false; }\n\n  virtual bool is_index_expression () const { return false; }\n\n  virtual bool is_assignment_expression () const { return false; }\n\n  virtual bool is_prefix_expression () const { return false; }\n\n  virtual bool is_unary_expression () const { return false; }\n\n  virtual bool is_binary_expression () const { return false; }\n\n  virtual bool is_boolean_expression () const { return false; }\n\n  virtual bool is_colon_expression () const { return false; }\n\n  virtual bool lvalue_ok () const { return false; }\n\n  virtual bool rvalue_ok () const { return false; }\n\n  virtual octave_lvalue lvalue (tree_evaluator&);\n\n  // The number of times this expression appears directly inside a set\n  // of delimiters.\n  //\n  //   (([e1]) + e2)  ==> 2 for expression e1\n  //                  ==> 1 for expression ([e1]) + e2\n  //                  ==> 0 for expression e2\n\n  size_t delim_count () const { return m_delims.count (); }\n\n  bool is_postfix_indexed () const\n  { return (m_postfix_index_type != '\\0'); }\n\n  char postfix_index () const { return m_postfix_index_type; }\n\n  // Check if the result of the expression should be printed.\n  // Should normally be used in conjunction with\n  // tree_evaluator::statement_printing_enabled.\n  bool print_result () const { return m_print_flag; }\n\n  OCTAVE_DEPRECATED (11, \"use tree_expression::op_str instead\")\n  virtual std::string oper () const { return \"<unknown>\"; }\n\n  virtual std::string op_str () const { return \"<unknown>\"; }\n\n  virtual std::string name () const { return \"<unknown>\"; }\n\n  virtual std::string original_text () const;\n\n  tree_delimiter_list delims () const { return m_delims; }\n\n  void mark_as_for_cmd_expr () { m_for_cmd_expr = true; }\n\n  bool is_for_cmd_expr () const { return m_for_cmd_expr; }\n\n  tree_expression * mark_in_delims (const token& open_delim, const token& close_delim)\n  {\n    m_delims.push (open_delim, close_delim);\n    return this;\n  }\n\n  tree_expression * set_postfix_index (char type)\n  {\n    m_postfix_index_type = type;\n    return this;\n  }\n\n  tree_expression * set_print_flag (bool print)\n  {\n    m_print_flag = print;\n    return this;\n  }\n\n  virtual void copy_base (const tree_expression& e)\n  {\n    m_postfix_index_type = e.m_postfix_index_type;\n    m_print_flag = e.m_print_flag;\n    m_delims = e.m_delims;\n  }\n\n  virtual octave_value evaluate (tree_evaluator& tw, int nargout = 1) = 0;\n\n  virtual octave_value_list\n  evaluate_n (tree_evaluator& tw, int nargout = 1) = 0;\n\nprotected:\n\n  // The first index type associated with this expression.  This field\n  // is 0 (character '\\0') if the expression has no associated index.\n  // See the code in tree_identifier::rvalue for the rationale.\n  char m_postfix_index_type;\n\n  // TRUE if this expression is the EXPR in for loop:\n  // FOR i = EXPR ... END\n  bool m_for_cmd_expr;\n\n  // Print result of rvalue for this expression?\n  bool m_print_flag;\n\n  // Tokens for any delimiters surrounding this expression.\n  tree_delimiter_list m_delims;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-fcn-handle.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ostream>\n\n#include \"interpreter-private.h\"\n#include \"pt-anon-scopes.h\"\n#include \"pt-fcn-handle.h\"\n#include \"stack-frame.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\ntree_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax,\n                        bool pr_orig_text)\n{\n  print_raw (os, pr_as_read_syntax, pr_orig_text);\n}\n\nvoid\ntree_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax,\n                            bool pr_orig_text)\n{\n  os << ((pr_as_read_syntax || pr_orig_text) ? \"@\" : \"\") << m_name;\n}\n\ntree_expression *\ntree_fcn_handle::dup (symbol_scope&) const\n{\n  tree_fcn_handle *new_fh = new tree_fcn_handle (m_token);\n\n  new_fh->copy_base (*this);\n\n  return new_fh;\n}\n\noctave_value\ntree_fcn_handle::evaluate (tree_evaluator& tw, int)\n{\n  return tw.make_fcn_handle (m_name);\n}\n\ntree_anon_fcn_handle::~tree_anon_fcn_handle ()\n{\n  delete m_parameter_list;\n  delete m_expression;\n}\n\ntree_expression *\ntree_anon_fcn_handle::dup (symbol_scope&) const\n{\n  tree_parameter_list *param_list = parameter_list ();\n  tree_expression *expr = expression ();\n\n  symbol_scope af_scope = m_scope;\n  symbol_scope af_parent_scope = m_parent_scope;\n\n  symbol_scope new_scope = af_scope ? af_scope.dup () : symbol_scope::invalid ();\n\n  // FIXME: if new scope is nullptr, then we are in big trouble here...\n\n  tree_anon_fcn_handle *new_afh\n    = new tree_anon_fcn_handle (m_at_tok, param_list ? param_list->dup (new_scope) : nullptr,\n                                expr ? expr->dup (new_scope) : nullptr,\n                                new_scope, af_parent_scope);\n\n  new_afh->copy_base (*this);\n\n  return new_afh;\n}\n\noctave_value\ntree_anon_fcn_handle::evaluate (tree_evaluator& tw, int)\n{\n  return tw.evaluate_anon_fcn_handle (*this);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n/*\n%!function r = __f2 (f, x)\n%!  r = f (x);\n%!endfunction\n%!function f = __f1 (k)\n%!  f = @(x) __f2 (@(y) y-k, x);\n%!endfunction\n\n%!assert ((__f1 (3)) (10) == 7)\n\n%!test\n%! g = @(t) feval (@(x) t*x, 2);\n%! assert (g(0.5) == 1);\n\n%!test\n%! h = @(x) sin (x);\n%! g = @(f, x) h (x);\n%! f = @() g (@(x) h, pi);\n%! assert (f () == sin (pi));\n\nThe next two tests are intended to test parsing of a character string\nvs. hermitian operator at the beginning of an anonymous function\nexpression.  The use of ' for the character string and the spacing is\nintentional, so don't change it.\n\n%!test\n%! f = @() 'foo';\n%! assert (f (), 'foo');\n\n%!test\n%! f = @()'foo';\n%! assert (f (), 'foo');\n*/\n"
  },
  {
    "path": "libinterp/parse-tree/pt-fcn-handle.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_fcn_handle_h)\n#define octave_pt_fcn_handle_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\n#include \"pt-bp.h\"\n#include \"pt-exp.h\"\n#include \"pt-misc.h\"\n#include \"pt-stmt.h\"\n#include \"pt-walk.h\"\n#include \"symscope.h\"\n\nclass octave_value_list;\n\n#include \"ov.h\"\n#include \"ov-usr-fcn.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API tree_fcn_handle : public tree_expression\n{\npublic:\n\n  tree_fcn_handle (const token& tok) : m_token (tok), m_name (m_token.text ()) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_fcn_handle)\n\n  ~tree_fcn_handle () = default;\n\n  filepos beg_pos () const { return m_token.beg_pos (); }\n  filepos end_pos () const { return m_token.end_pos (); }\n\n  comment_list leading_comments () const { return m_token.leading_comments (); }\n  comment_list trailing_comments () const { return m_token.trailing_comments (); }\n\n  void print (std::ostream& os, bool pr_as_read_syntax = false,\n              bool pr_orig_txt = true);\n\n  void print_raw (std::ostream& os, bool pr_as_read_syntax = false,\n                  bool pr_orig_txt = true);\n\n  token at_token () const { return m_token; }\n\n  std::string name () const { return m_name; }\n\n  bool rvalue_ok () const { return true; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator& tw, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_fcn_handle (*this);\n  }\n\nprivate:\n\n  token m_token;\n\n  // The name of this function handle.\n  std::string m_name;\n};\n\nclass OCTINTERP_API tree_anon_fcn_handle : public tree_expression\n{\npublic:\n\n  tree_anon_fcn_handle (const token& at_tok, tree_parameter_list *pl, tree_expression *ex, const symbol_scope& scope, const symbol_scope& parent_scope)\n    : m_at_tok (at_tok), m_parameter_list (pl), m_expression (ex), m_scope (scope), m_parent_scope (parent_scope)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_anon_fcn_handle)\n\n  ~tree_anon_fcn_handle ();\n\n  filepos beg_pos () const { return m_at_tok.beg_pos (); }\n  filepos end_pos () const { return m_expression->end_pos (); }\n\n  comment_list leading_comments () const { return m_at_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_expression->trailing_comments (); }\n\n  bool rvalue_ok () const { return true; }\n\n  token at_token () const { return m_at_tok; }\n\n  tree_parameter_list * parameter_list () const\n  {\n    return m_parameter_list;\n  }\n\n  tree_expression * expression () const { return m_expression; }\n\n  symbol_scope scope () const { return m_scope; }\n\n  symbol_scope parent_scope () const { return m_parent_scope; }\n\n  bool has_parent_scope () const { return m_parent_scope.is_valid (); }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator& tw, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw) { tw.visit_anon_fcn_handle (*this); }\n\n  void stash_file_name (const std::string& file) { m_file_name = file; }\n\n  std::string file_name () const { return m_file_name; }\n\nprivate:\n\n  token m_at_tok;\n\n  // Inputs parameters.\n  tree_parameter_list *m_parameter_list;\n\n  // Function body, limited to a single expression.\n  tree_expression *m_expression;\n\n  // Function scope.\n  symbol_scope m_scope;\n\n  // Parent scope, or an invalid scope if none.\n  symbol_scope m_parent_scope;\n\n  // Filename where the handle was defined.\n  std::string m_file_name;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-id.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"oct-lvalue.h\"\n#include \"pt-const.h\"\n#include \"pt-id.h\"\n#include \"symscope.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Symbols from the symbol table.\n\nvoid\ntree_identifier::eval_undefined_error ()\n{\n  int l = line ();\n  int c = column ();\n\n  std::string msg = \"'\" + name () + \"' undefined\";\n\n  if (l > 0)\n    {\n      msg += \" near line \" + std::to_string (l);\n\n      if (c > 0)\n        msg += \", column \" + std::to_string (c);\n    }\n\n  std::string missing_msg = maybe_missing_function_hook (name ());\n\n  if (! missing_msg.empty ())\n    msg += \"\\n\\n\" + missing_msg;\n\n  error_with_id (\"Octave:undefined-function\", \"%s\", msg.c_str ());\n}\n\noctave_lvalue\ntree_identifier::lvalue (tree_evaluator& tw)\n{\n  if (m_sym.is_added_static ())\n    static_workspace_error ();\n\n  return octave_lvalue (m_sym, tw.get_current_stack_frame ());\n}\n\ntree_identifier *\ntree_identifier::dup (symbol_scope& scope) const\n{\n  // The new tree_identifier object contains a symbol_record\n  // entry from the duplicated scope.\n\n  symbol_record new_sym = scope.find_symbol (name ());\n\n  tree_identifier *new_id = new tree_identifier (new_sym, m_token);\n\n  new_id->copy_base (*this);\n\n  return new_id;\n}\n\noctave_value_list\ntree_identifier::evaluate_n (tree_evaluator& tw, int nargout)\n{\n  octave_value_list retval;\n\n  octave_value val = tw.varval (m_sym);\n\n  if (val.is_undefined ())\n    {\n      interpreter& interp = tw.get_interpreter ();\n\n      symbol_table& symtab = interp.get_symbol_table ();\n\n      val = symtab.find_function (m_sym.name ());\n    }\n\n  if (val.is_defined ())\n    {\n      // GAGME -- this would be cleaner if we required\n      // parens to indicate function calls.\n      //\n      // If this identifier refers to a function, we need to know\n      // whether it is indexed so that we can do the same thing\n      // for 'f' and 'f()'.  If the index is present and the function\n      // object declares it can handle it, return the function object\n      // and let tree_index_expression::rvalue handle indexing.\n      // Otherwise, arrange to call the function here, so that we don't\n      // return the function definition as a value.\n\n      octave_function *fcn = nullptr;\n\n      if (val.is_function ())\n        fcn = val.function_value (true);\n\n      if (fcn && ! (is_postfix_indexed ()\n                    && fcn->accepts_postfix_index (postfix_index ())))\n        {\n          retval = fcn->call (tw, nargout);\n        }\n      else\n        {\n          if (print_result () && nargout == 0\n              && tw.statement_printing_enabled ())\n            {\n              octave_value_list args = ovl (val);\n              args.stash_name_tags (string_vector (name ()));\n\n              interpreter& interp = tw.get_interpreter ();\n\n              interp.feval (\"display\", args);\n            }\n\n          retval = ovl (val);\n        }\n    }\n  else if (m_sym.is_added_static ())\n    static_workspace_error ();\n  else\n    eval_undefined_error ();\n\n  return retval;\n}\n\noctave_lvalue\ntree_black_hole::lvalue (tree_evaluator& tw)\n{\n  octave_lvalue retval (m_sym, tw.get_current_stack_frame ());\n\n  retval.mark_black_hole ();\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-id.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_id_h)\n#define octave_pt_id_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\nclass octave_function;\n\n#include \"comment-list.h\"\n#include \"oct-lvalue.h\"\n#include \"pt-bp.h\"\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n#include \"symscope.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_evaluator;\n\n// Symbols from the symbol table.\n\nclass OCTINTERP_API tree_identifier : public tree_expression\n{\n  friend class tree_index_expression;\n\npublic:\n\n  tree_identifier (const token& tok) : m_token (tok) { }\n\n  tree_identifier (symbol_scope& scope, const token& tok)\n    : m_sym (scope ? scope.insert (tok.text ()) : symbol_record (tok.text ())),\n      m_token (tok)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_identifier)\n\n  ~tree_identifier () = default;\n\n  bool is_identifier () const { return true; }\n\n  std::string name () const { return m_sym.name (); }\n\n  filepos beg_pos () const { return m_token.beg_pos (); }\n  filepos end_pos () const { return m_token.end_pos (); }\n\n  comment_list leading_comments () const { return m_token.leading_comments (); }\n  comment_list trailing_comments () const { return m_token.trailing_comments (); }\n\n  virtual bool is_black_hole () const { return false; }\n\n  void mark_as_formal_parameter () { m_sym.mark_formal (); }\n\n  // We really need to know whether this symbol refers to a variable\n  // or a function, but we may not know that yet.\n\n  bool lvalue_ok () const { return true; }\n\n  octave_lvalue lvalue (tree_evaluator& tw);\n\n  void eval_undefined_error ();\n\n  void static_workspace_error ()\n  {\n    error (R\"(can not add variable \"%s\" to a static workspace)\",\n           name ().c_str ());\n  }\n\n  tree_identifier * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator& tw, int nargout = 1)\n  {\n    octave_value_list retval = evaluate_n (tw, nargout);\n\n    return retval.length () > 0 ? retval(0) : octave_value ();\n  }\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1);\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_identifier (*this);\n  }\n\n  symbol_record symbol () const { return m_sym; }\n\n  token get_set_token () const { return m_get_set_tok; }\n\n  token dot_token () const { return m_dot_tok; }\n\n  token identifier_token () const { return m_get_set_tok; }\n\n  tree_identifier * mark_get_set (const token& get_set_tok, const token& dot_tok)\n  {\n    m_get_set_tok = get_set_tok;\n    m_dot_tok = dot_tok;\n\n    return this;\n  }\n\nprotected:\n\n  tree_identifier (symbol_record& sym, const token& tok)\n    : m_sym (sym), m_token (tok)\n  { }\n\n  //--------\n\n  // The symbol record that this identifier references.\n  symbol_record m_sym;\n\n  // These will be defined for get.ID or set.ID function names.\n  token m_get_set_tok;\n  token m_dot_tok;\n\n  // The IDENT token from the lexer.\n  token m_token;\n};\n\nclass OCTINTERP_API tree_black_hole : public tree_identifier\n{\npublic:\n\n  tree_black_hole (const token& token)\n    : tree_identifier (token)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_black_hole)\n\n  ~tree_black_hole () = default;\n\n  std::string name () const { return \"~\"; }\n\n  bool is_black_hole () const { return true; }\n\n  token tilde_token () const { return identifier_token (); }\n\n  tree_black_hole * dup (symbol_scope&) const\n  {\n    return new tree_black_hole (m_token);\n  }\n\n  octave_lvalue lvalue (tree_evaluator& tw);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-idx.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Cell.h\"\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"oct-map.h\"\n#include \"ovl.h\"\n#include \"oct-lvalue.h\"\n#include \"ov.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-eval.h\"\n#include \"pt-id.h\"\n#include \"pt-idx.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"errwarn.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Index expressions.\n\ntree_index_expression::tree_index_expression (tree_expression *e, const token& open_delim, tree_argument_list *lst, const token& close_delim, char t)\n  : m_expr (e), m_args (0), m_type (), m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)\n{\n  append (open_delim, lst, close_delim, t);\n}\n\ntree_index_expression::tree_index_expression (tree_expression *e, const token& dot_tok, const token& struct_elt_tok)\n  : m_expr (e), m_args (0), m_type (), m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)\n{\n  append (dot_tok, struct_elt_tok);\n}\n\ntree_index_expression::tree_index_expression (tree_expression *e, const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren)\n  : m_expr (e), m_args (0), m_type (), m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)\n{\n  append (dot_tok, open_paren, df, close_paren);\n}\n\ntree_index_expression *\ntree_index_expression::append (const token& open_delim, tree_argument_list *lst, const token& close_delim, char t)\n{\n  lst->mark_in_delims (open_delim, close_delim);\n  m_args.push_back (lst);\n  m_type.append (1, t);\n  m_dot_tok.push_back (token ());\n  m_arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ());\n  m_dyn_field.push_back (static_cast<tree_expression *> (nullptr));\n\n  if (lst && lst->has_magic_tilde ())\n    error (\"invalid use of empty argument (~) in index expression\");\n\n  return this;\n}\n\ntree_index_expression *\ntree_index_expression::append (const token& dot_tok, const token& struct_elt_tok)\n{\n  m_args.push_back (static_cast<tree_argument_list *> (nullptr));\n  m_type += '.';\n  m_dot_tok.push_back (dot_tok);\n  m_arg_nm.push_back (struct_elt_tok.text ());\n  m_dyn_field.push_back (static_cast<tree_expression *> (nullptr));\n\n  return this;\n}\n\ntree_index_expression *\ntree_index_expression::append (const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren)\n{\n  m_args.push_back (static_cast<tree_argument_list *> (nullptr));\n  m_type += '.';\n  m_dot_tok.push_back (dot_tok);\n  m_arg_nm.push_back (\"\");\n  df->mark_in_delims (open_paren, close_paren);\n  m_dyn_field.push_back (df);\n\n  return this;\n}\n\ntree_index_expression::~tree_index_expression ()\n{\n  delete m_expr;\n\n  while (! m_args.empty ())\n    {\n      auto p = m_args.begin ();\n      delete *p;\n      m_args.erase (p);\n    }\n\n  while (! m_dyn_field.empty ())\n    {\n      auto p = m_dyn_field.begin ();\n      delete *p;\n      m_dyn_field.erase (p);\n    }\n}\n\n// This is useful for printing the name of the variable in an indexed\n// assignment.\n\nstd::string\ntree_index_expression::name () const\n{\n  return m_expr->name ();\n}\n\nfilepos\ntree_index_expression::end_pos () const\n{\n  int n = m_args.size ();\n\n  if (n == 0)\n    return m_expr->end_pos ();\n\n  switch (m_type[n-1])\n    {\n    case '(':\n    case '{':\n      {\n        tree_argument_list *args = m_args.back ();\n        return args->end_pos ();\n      }\n      break;\n\n    case '.':\n      {\n        string_vector arg_names = m_arg_nm.back ();\n\n        if (arg_names.empty ())\n          {\n            tree_expression *dyn_field = m_dyn_field.back ();\n\n            if (dyn_field)\n              return dyn_field->end_pos ();\n            else\n              error (\"unexpected: dynamic field is nullptr in call to tree_index_expression::end_pos - please report this bug\");\n\n          }\n\n        token dot_tok = m_dot_tok.back ();\n        std::string arg_nm = arg_names(0);\n\n        // FIXME: this might not be correct because we have no way\n        // to account for space between the '.' operator and the\n        // field name.  Maybe we should really be storing an\n        // identifier that contains position information?\n\n        filepos pos = dot_tok.end_pos ();\n        pos.increment_column (arg_nm.size ());\n\n        return pos;\n      }\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in tree_index_expression::end_pos - please report this bug\");\n    }\n}\n\ncomment_list\ntree_index_expression::trailing_comments () const\n{\n  int n = m_args.size ();\n\n  if (n == 0)\n    return m_expr->trailing_comments ();\n\n  switch (m_type[n-1])\n    {\n    case '(':\n    case '{':\n      {\n        tree_argument_list *args = m_args.back ();\n        return args->trailing_comments ();\n      }\n      break;\n\n    case '.':\n      {\n        string_vector arg_names = m_arg_nm.back ();\n\n        if (arg_names.empty ())\n          {\n            tree_expression *dyn_field = m_dyn_field.back ();\n\n            if (dyn_field)\n              return dyn_field->trailing_comments ();\n            else\n              error (\"unexpected: dynamic field is nullptr in call to tree_index_expression::trailing_comments - please report this bug\");\n\n          }\n\n        token dot_tok = m_dot_tok.back ();\n        std::string arg_nm = arg_names(0);\n\n        // FIXME: is this correct?  Are trailing comments in this case\n        // stored correctly by the parser?  To which token are they\n        // attached?\n\n        return dot_tok.trailing_comments ();\n      }\n\n    default:\n      error (\"unexpected: index not '(', '{', or '.' in tree_index_expression::trailing_comments - please report this bug\");\n    }\n}\n\nstd::string\ntree_index_expression::get_struct_index\n(tree_evaluator& tw,\n std::list<string_vector>::const_iterator p_arg_nm,\n std::list<tree_expression *>::const_iterator p_dyn_field) const\n{\n  std::string fn = (*p_arg_nm)(0);\n\n  if (fn.empty ())\n    {\n      tree_expression *df = *p_dyn_field;\n\n      if (df)\n        {\n          octave_value t = df->evaluate (tw);\n\n          fn = t.xstring_value (\"dynamic structure field names must be strings\");\n        }\n      else\n        error (\"unexpected: DF is nullptr in call to tree_index_expression::get_struct_index - please report this bug\");\n    }\n\n  return fn;\n}\n\noctave_lvalue\ntree_index_expression::lvalue (tree_evaluator& tw)\n{\n  std::list<octave_value_list> idx;\n\n  int n = m_args.size ();\n\n  auto p_args = m_args.begin ();\n  auto p_arg_nm = m_arg_nm.begin ();\n  auto p_dyn_field = m_dyn_field.begin ();\n\n  octave_lvalue retval = m_expr->lvalue (tw);\n\n  unwind_action\n  act ([&tw] (const octave_value& val,\n              const std::string& index_type,\n              const std::list<octave_value_list>& index_list)\n  {\n    tw.set_indexed_object (val);\n    tw.set_index_list (index_type, index_list);\n  }, tw.indexed_object (), tw.index_type (), tw.index_list ());\n\n  tw.set_indexed_object (retval.value ());\n  tw.clear_index_list ();\n\n  for (int i = 0; i < n; i++)\n    {\n      switch (m_type[i])\n        {\n        case '(':\n          {\n            octave_value_list tidx = tw.make_value_list (*p_args, *p_arg_nm);\n\n            tw.append_index_list ('(', tidx);\n            idx.push_back (tidx);\n          }\n          break;\n\n        case '{':\n          {\n            octave_value_list tidx = tw.make_value_list (*p_args, *p_arg_nm);\n\n            tw.append_index_list ('{', tidx);\n            idx.push_back (tidx);\n          }\n          break;\n\n        case '.':\n          {\n            octave_value tidx = get_struct_index (tw, p_arg_nm, p_dyn_field);\n\n            tw.append_index_list ('.', tidx);\n            idx.push_back (tidx);\n          }\n          break;\n\n        default:\n          error (\"unexpected: index not '(', '{', or '.' in tree_index_expression::lvalue - please report this bug\");\n        }\n\n      if (idx.back ().empty ())\n        error (\"invalid empty index list\");\n\n      p_args++;\n      p_arg_nm++;\n      p_dyn_field++;\n    }\n\n  retval.set_index (m_type, idx);\n\n  return retval;\n}\n\ntree_index_expression *\ntree_index_expression::dup (symbol_scope& scope) const\n{\n  tree_index_expression *new_idx_expr = new tree_index_expression ();\n\n  new_idx_expr->m_expr = (m_expr ? m_expr->dup (scope) : nullptr);\n\n  std::list<tree_argument_list *> new_args;\n\n  for (const tree_argument_list *elt : m_args)\n    new_args.push_back (elt ? elt->dup (scope) : nullptr);\n\n  new_idx_expr->m_args = new_args;\n\n  new_idx_expr->m_type = m_type;\n\n  new_idx_expr->m_arg_nm = m_arg_nm;\n\n  std::list<tree_expression *> new_dyn_field;\n\n  for (const tree_expression *elt : m_dyn_field)\n    new_dyn_field.push_back (elt ? elt->dup (scope) : nullptr);\n\n  new_idx_expr->m_dyn_field = new_dyn_field;\n\n  new_idx_expr->copy_base (*this);\n\n  return new_idx_expr;\n}\n\n// Unlike Matlab, which does not allow the result of a function call\n// or array indexing expression to be further indexed, Octave attempts\n// to handle arbitrary index expressions.  For example, Octave allows\n// expressions like\n//\n//   svd (rand (10))(1:5)\n//\n// Although octave_value objects may contain function objects, no\n// indexing operation or function call is supposed to return them\n// directly.  Instead, the language is supposed to only allow function\n// objects to be stored as function handles (named or anonymous) or as\n// inline functions.  The only place a function object should appear\n// directly is if the symbol stored in a tree_identifier object\n// resolves to a function.  This means that the only place we need to\n// look for functions is in the first element of the index\n// expression.\n//\n// Steps:\n//\n//  * Obtain the initial value from the expression component of the\n//    tree_index_expression object.  If it is a tree_identifier object\n//    indexed by '(args)' and the identifier is not a variable, then\n//    perform a function call.  Use the (optional) arguments to perform\n//    the function lookup so we choose the correct function or class\n//    method to call.  Otherwise, evaluate the first expression\n//    without any additional arguments.\n//\n//  * Iterate over the remaining elements of the index expression and\n//    call the octave_value::subsref method.  If indexing a class or\n//    classdef object, build up a list of indices for a call to the\n//    subsref method for the object.  Otherwise, use the result of\n//    each temporary evaluation for the next index element.\n//\n//  * If not indexing a class or classdef object and any partial\n//    expression evaluation produces a class or classdef object, then\n//    build up a complete argument list from that point on for a final\n//    subsref call for that object.\n//\n//    Multiple partial evaluations may be required.  For example,\n//    given a class or classdef object X, then for the expression\n//\n//      x.a{end}(2:end).b\n//\n//    we must evaluate x.a to obtain the size for the first {end}\n//    expression, then we must evaluate x.a{end} to obtain the size\n//    for the second (2:end) expression.  Finally, the complete\n//    expression may be evaluated.\n//\n//    If X is a cell array in the above expression, and none of the\n//    intermediate evaluations produces a class or classdef object,\n//    then the evaluation is performed as the following series of\n//    steps\n//\n//      tmp = x.a\n//      tmp = tmp{end}\n//      tmp = tmp(2:end)\n//      result = tmp.b\n//\n//    If any of the partial evaluations produces a class or classdef\n//    object, then the subsref method for that object is called as\n//    described above.  For example, suppose x.a produces a classdef\n//    object.  Then the evaluation is performed as the following\n//    series of steps\n//\n//      base_expr = tmp = x.a\n//      tmp = base_expr{end}\n//      base_expr{end}(2:end).b\n//\n//    In the last two steps, the partial value computed in the\n//    previous step is used to determine the value of END.\n\noctave_value_list\ntree_index_expression::evaluate_n (tree_evaluator& tw, int nargout)\n{\n  octave_value_list retval;\n\n  panic_if (m_args.empty ());\n\n  auto p_args = m_args.begin ();\n  auto p_arg_nm = m_arg_nm.begin ();\n  auto p_dyn_field = m_dyn_field.begin ();\n\n  int n = m_args.size ();\n  int beg = 0;\n\n  // Set nargout to 1 for all subsref operations except the last one.\n  int nargout_saved = nargout;\n  if (n > 1)\n    nargout = 1;\n\n  octave_value base_expr_val;\n\n  if (m_expr->is_identifier () && m_type[beg] == '(')\n    {\n      tree_identifier *id = dynamic_cast<tree_identifier *> (m_expr);\n\n      bool is_var = tw.is_variable (m_expr);\n\n      std::string nm =  id->name ();\n\n      if (is_var && is_word_list_cmd ())\n        {\n          bool maybe_binary_op = false;\n          if ((*p_args) && (*p_args)->size () > 0)\n            {\n              // check if first character of first argument might be (the\n              // start of) a binary operator\n              std::string ops = \"+-*/\\\\.^|&\";\n              string_vector arg_list = (*p_args)->get_arg_names ();\n              if (! arg_list.isempty ()\n                  && (ops.find (arg_list(0)[1]) != std::string::npos))\n                maybe_binary_op = true;\n            }\n\n          std::string advice;\n          if (maybe_binary_op)\n            advice = \"\\nCheck whitespace around potential binary operator.\";\n\n          error (\"variable \\\"%s\\\" used as function in command style expression%s\",\n                 nm.c_str (), advice.c_str ());\n        }\n\n      if (! is_var)\n        {\n          octave_value_list first_args;\n\n          tree_argument_list *al = *p_args;\n\n          if (al && al->size () > 0)\n            {\n              unwind_action act ([&tw] (const std::list<octave_lvalue> *lvl)\n              {\n                tw.set_lvalue_list (lvl);\n              }, tw.lvalue_list ());\n\n              tw.set_lvalue_list (nullptr);\n\n              string_vector anm = *p_arg_nm;\n\n              first_args = tw.convert_to_const_vector (al);\n\n              first_args.stash_name_tags (anm);\n            }\n\n          interpreter& interp = tw.get_interpreter ();\n\n          symbol_table& symtab = interp.get_symbol_table ();\n\n          octave_value val = symtab.find_function (nm, first_args);\n\n          octave_function *fcn = nullptr;\n\n          if (val.is_function ())\n            fcn = val.function_value (true);\n\n          if (fcn)\n            {\n              try\n                {\n                  retval = fcn->call (tw, nargout, first_args);\n                }\n              catch (index_exception& ie)\n                {\n                  tw.final_index_error (ie, m_expr);\n                }\n\n              beg++;\n              p_args++;\n              p_arg_nm++;\n              p_dyn_field++;\n\n              if (n > beg)\n                {\n                  // More indices to follow.  Silently ignore\n                  // extra output values.\n\n                  if (retval.length () == 0 || retval(0).is_undefined ())\n                    error (\"indexing undefined value\");\n                  else\n                    base_expr_val = retval(0);\n                }\n              else\n                {\n                  // No more indices, so we are done.\n\n                  // See note at end of function about deleting\n                  // temporaries prior to pushing result.\n\n                  base_expr_val = octave_value ();\n                  first_args = octave_value_list ();\n\n                  return retval;\n                }\n            }\n        }\n    }\n\n  if (base_expr_val.is_undefined ())\n    base_expr_val = m_expr->evaluate (tw);\n\n  // If we are indexing an object or looking at something like\n  //\n  //   classname.static_function (args, ...);\n  //\n  // then we'll just build a complete index list for one big subsref\n  // call.  If the expression we are indexing is a classname then\n  // base_expr_val will be an octave_classdef_meta object.  If we have\n  // files in a +packagename folder, they will also be an\n  // octave_classdef_meta object, but we don't want to index them.\n\n  std::list<octave_value_list> idx_list;\n\n  {\n    // Note: need new scope so that the following unwind action will\n    // happen before we perform the final indexing for objects (for\n    // example).\n\n    unwind_action\n    act ([&tw] (const octave_value& val,\n                const std::string& index_type,\n                const std::list<octave_value_list>& index_list)\n    {\n      tw.set_indexed_object (val);\n      tw.set_index_list (index_type, index_list);\n    },\n    tw.indexed_object (),\n    tw.index_type (), tw.index_list ());\n\n    tw.set_indexed_object ();\n    tw.clear_index_list ();\n\n    bool indexing_object = (base_expr_val.isobject ()\n                            || base_expr_val.isjava ()\n                            || (base_expr_val.is_classdef_meta ()\n                                && ! base_expr_val.is_package ()));\n\n    octave_value partial_expr_val = base_expr_val;\n\n    for (int i = beg; i < n; i++)\n      {\n        if (i > beg)\n          {\n            if (! indexing_object)\n              {\n                // Evaluate what we have so far.\n\n                try\n                  {\n                    // Silently ignore extra output values.\n\n                    octave_value_list tmp_list\n                      = base_expr_val.subsref (m_type.substr (beg, i-beg),\n                                               idx_list, nargout);\n\n                    partial_expr_val\n                      = tmp_list.length () ? tmp_list(0) : octave_value ();\n\n                    base_expr_val = partial_expr_val;\n\n                    if (partial_expr_val.is_cs_list ())\n                      err_indexed_cs_list ();\n\n                    retval = partial_expr_val;\n\n                    beg = i;\n                    idx_list.clear ();\n                    tw.clear_index_list ();\n\n                    if (partial_expr_val.isobject ()\n                        || partial_expr_val.isjava ()\n                        || (partial_expr_val.is_classdef_meta ()\n                            && ! partial_expr_val.is_package ()))\n                      {\n                        // Found an object, so now we'll build up\n                        // complete index list for one big subsref\n                        // call from this point on.\n\n                        // FIXME: is it also possible to have a\n                        // static method call buried somewhere in\n                        // the depths of a complex indexing\n                        // expression so that we would also need to\n                        // check for an octave_classdef_meta object\n                        // here?\n\n                        indexing_object = true;\n                      }\n                  }\n                catch (index_exception& ie)\n                  {\n                    tw.final_index_error (ie, m_expr);\n                  }\n              }\n          }\n\n        tw.set_indexed_object (partial_expr_val);\n\n        switch (m_type[i])\n          {\n          case '(':\n            {\n              octave_value_list tmp = tw.make_value_list (*p_args, *p_arg_nm);\n              tw.append_index_list ('(', tmp);\n              idx_list.push_back (tmp);\n            }\n            break;\n\n          case '{':\n            {\n              octave_value_list tmp = tw.make_value_list (*p_args, *p_arg_nm);\n              tw.append_index_list ('{', tmp);\n              idx_list.push_back (tmp);\n            }\n            break;\n\n          case '.':\n            {\n              octave_value tmp = get_struct_index (tw, p_arg_nm, p_dyn_field);\n              tw.append_index_list ('.', tmp);\n              idx_list.push_back (tmp);\n            }\n            break;\n\n          default:\n            error (\"unexpected: index not '(', '{', or '.' in tree_index_expression::evaluate_n - please report this bug\");\n          }\n\n        p_args++;\n        p_arg_nm++;\n        p_dyn_field++;\n      }\n  }\n\n  // Restore original nargout for last subsref operation\n  nargout = nargout_saved;\n\n  // If ! idx_list.empty () that means we still have stuff to index\n  // otherwise they would have been dealt with and idx_list would have\n  // been emptied.\n  if (! idx_list.empty ())\n    {\n      // This is for +package and other classdef_meta objects\n      if (! base_expr_val.is_function ()\n          || base_expr_val.is_classdef_meta ())\n        {\n          try\n            {\n              retval = base_expr_val.subsref (m_type.substr (beg, n-beg),\n                                              idx_list, nargout);\n              beg = n;\n              idx_list.clear ();\n            }\n          catch (index_exception& ie)\n            {\n              tw.final_index_error (ie, m_expr);\n            }\n        }\n      else\n        {\n          // FIXME: we want this to only be a superclass constructor\n          // call Should we actually make a check for this or are all\n          // other types of calls already dealt with?\n\n          octave_function *fcn = base_expr_val.function_value ();\n\n          if (fcn)\n            {\n              try\n                {\n                  // FIXME: is it possible for the IDX_LIST to have\n                  // more than one element here?  Do we need to check?\n\n                  octave_value_list final_args;\n\n                  if (idx_list.size () != 1)\n                    error (\"unexpected extra index at end of expression\");\n\n                  if (m_type[beg] != '(')\n                    error (\"invalid index type '%c' for function call\",\n                           m_type[beg]);\n\n                  final_args = idx_list.front ();\n\n                  // FIXME: Do we ever need the names of the arguments\n                  // passed to FCN here?\n\n                  retval = fcn->call (tw, nargout, final_args);\n                }\n              catch (index_exception& ie)\n                {\n                  tw.final_index_error (ie, m_expr);\n                }\n            }\n        }\n    }\n\n  // FIXME: when can the following happen?  In what case does indexing\n  // result in a value that is a function?  Classdef method calls?\n  // Something else?\n\n  octave_value val = (retval.length () ? retval(0) : octave_value ());\n\n  if (val.is_function ())\n    {\n      octave_function *fcn = val.function_value (true);\n\n      if (fcn)\n        {\n          octave_value_list final_args;\n\n          if (! idx_list.empty ())\n            {\n              if (n - beg != 1)\n                error (\"unexpected extra index at end of expression\");\n\n              if (m_type[beg] != '(')\n                error (\"invalid index type '%c' for function call\",\n                       m_type[beg]);\n\n              final_args = idx_list.front ();\n            }\n\n          retval = fcn->call (tw, nargout, final_args);\n        }\n    }\n\n  // Delete any temporary values prior to returning so that\n  // destructors for any temporary classdef handle objects will be\n  // called before we return.\n\n  idx_list.clear ();\n  base_expr_val = octave_value ();\n  val = octave_value ();\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n/*\n%!test\n%! clear x;\n%! clear y;\n%! y = 3;\n%! x(y(end)) = 1;\n%! assert (x, [0, 0, 1]);\n%! clear x;\n%! clear y;\n%! y = {3};\n%! x(y{end}) = 1;\n%! assert (x, [0, 0, 1]);\n\n%!test\n%! x = {1, 2, 3};\n%! [x{:}] = deal (4, 5, 6);\n%! assert (x, {4, 5, 6});\n\n%!test\n%! [x.a, x.b.c] = deal (1, 2);\n%! assert (x.a == 1 && x.b.c == 2);\n\n%!test\n%! [x.a, x(2).b] = deal (1, 2);\n%! assert (x(1).a == 1 && isempty (x(2).a) && isempty (x(1).b) && x(2).b == 2);\n\n%!test\n%! x = struct (zeros (0, 1), {\"a\", \"b\"});\n%! x(2).b = 1;\n%! assert (x(2).b == 1);\n\n%!test\n%! x = struct (zeros (0, 1), {\"a\", \"b\"});\n%! x(2).b = 1;\n%! assert (x(2).b == 1);\n\n## Test nargout when indexing function calls\n%!\n%!function [a] = __fcell ()\n%!  a = num2cell (1:5);\n%!endfunction\n%!\n%!function [a] = __fstruct ()\n%!  a = struct ('a', {1, 2}, 'b', {3, 4});\n%!endfunction\n%!\n%!test  # Function call at the start of the index expression\n%! [a, b] = __fcell () {1:2};\n%! assert ([a, b], [1, 2]);\n%! [a, b] = __fstruct ().b;\n%! assert ([a, b], [3, 4]);\n#!\n%!test  # Function handle call at the start of the index expression\n%! f = @__fcell;\n%! [a, b] = f () {1:2};\n%! assert ([a, b], [1, 2]);\n%! f = @__fstruct;\n%! [a, b] = f ().b;\n%! assert ([a, b], [3, 4]);\n#!\n%!test  # Intermediate function handle call followed by {} indexing\n%! x = {@__fcell};\n%! [a, b] = x {1} () {1:2};\n%! assert ([a, b], [1, 2]);\n%! s.f = @__fcell;\n%! [a, b] = s.f () {3:4};\n%! assert ([a, b], [3, 4]);\n%!\n%!test  # Intermediate function handle call followed by . indexing\n%! x = {@__fstruct};\n%! [a, b] = x {1} ().a;\n%! assert ([a, b], [1, 2]);\n%! s.f = @__fstruct;\n%! [a, b] = s.f ().b;\n%! assert ([a, b], [3, 4]);\n%!\n%!test  # Anonymous function call at the start of the index expression\n%! f = @() num2cell (1:5);\n%! [a, b] = f () {1:2};\n%! assert ([a, b], [1, 2]);\n%! f = @() struct ('a', {1, 2}, 'b', {3, 4});\n%! [a, b] = f ().b;\n%! assert ([a, b], [3, 4]);\n#!\n%!test  # Intermediate anon func call followed by {} indexing\n%! x = {@() num2cell (1:5)};\n%! [a, b] = x {1} () {1:2};\n%! assert ([a, b], [1, 2]);\n%! s.f = @() num2cell (1:5);\n%! [a, b] = s.f () {3:4};\n%! assert ([a, b], [3, 4]);\n%!\n%!test  # Intermediate anon func call followed by . indexing\n%! x = {@() struct ('a', {1, 2}, 'b', {3, 4})};\n%! [a, b] = x {1} ().a;\n%! assert ([a, b], [1, 2]);\n%! s.f = @() struct ('a', {1, 2}, 'b', {3, 4});\n%! [a, b] = s.f ().b;\n%! assert ([a, b], [3, 4]);\n\n%!test <*67111>\n%! function [a] = fcelln (n)\n%!   if (n >= 0)\n%!     a = num2cell (1:n);\n%!   endif\n%! endfunction\n%!\n%! fail (\"fcelln (-5) {1:3}\", \"indexing undefined value\");\n%! fail (\"fcelln (-5) (1:3)\", \"indexing undefined value\");\n%! fail (\"fcelln (-5).prop\", \"indexing undefined value\");\n\n%!test <*67111>\n%! function [a] = fnothing ()\n%! endfunction\n%!\n%! fail (\"fnothing () {1:3}\", \"indexing undefined value\");\n%! fail (\"fnothing () (1:3)\", \"indexing undefined value\");\n%! fail (\"fnothing ().prop\", \"indexing undefined value\");\n%! fail (\"fnothing () ()\", \"indexing undefined value\");\n*/\n"
  },
  {
    "path": "libinterp/parse-tree/pt-idx.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_idx_h)\n#define octave_pt_idx_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n\nclass octave_map;\nclass octave_value;\nclass octave_value_list;\n\n#include \"str-vec.h\"\n\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass octave_lvalue;\nclass symbol_scope;\nclass tree_argument_list;\nclass tree_evaluator;\n\n// Index expressions.\n\nclass OCTINTERP_API tree_index_expression : public tree_expression\n{\npublic:\n\n  tree_index_expression (tree_expression *e, const token& open_delim, tree_argument_list *lst, const token& close_delim, char t);\n\n  tree_index_expression (tree_expression *e, const token& dot_tok, const token& struct_elt_tok);\n\n  tree_index_expression (tree_expression *e, const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren);\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_index_expression)\n\n  ~tree_index_expression ();\n\n  tree_index_expression *\n  append (const token& open_delim, tree_argument_list *lst, const token& close_delim, char t = '(');\n\n  tree_index_expression * append (const token& dot_tok, const token& struct_elt_tok);\n\n  tree_index_expression * append (const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren);\n\n  bool is_index_expression () const { return true; }\n\n  std::string name () const;\n\n  filepos beg_pos () const { return m_expr->beg_pos (); }\n  filepos end_pos () const;\n\n  comment_list leading_comments () const { return m_expr->leading_comments (); }\n  comment_list trailing_comments () const;\n\n  tree_expression * expression () { return m_expr; }\n\n  std::list<tree_argument_list *> arg_lists () { return m_args; }\n\n  std::string type_tags () { return m_type; }\n\n  std::list<token> dot_tokens () const { return m_dot_tok; }\n\n  std::list<string_vector> arg_names () { return m_arg_nm; }\n\n  std::list<tree_expression *> dyn_fields () { return m_dyn_field; }\n\n  void mark_word_list_cmd () { m_word_list_cmd = true; }\n\n  bool is_word_list_cmd () const { return m_word_list_cmd; }\n\n  bool lvalue_ok () const { return m_expr->lvalue_ok (); }\n\n  bool rvalue_ok () const { return true; }\n\n  octave_lvalue lvalue (tree_evaluator& tw);\n\n  tree_index_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator& tw, int nargout = 1)\n  {\n    octave_value_list retval = evaluate_n (tw, nargout);\n\n    return retval.length () > 0 ? retval(0) : octave_value ();\n  }\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1);\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_index_expression (*this);\n  }\n\n  std::string\n  get_struct_index\n  (tree_evaluator& tw, std::list<string_vector>::const_iterator p_arg_nm,\n   std::list<tree_expression *>::const_iterator p_dyn_field) const;\n\nprivate:\n\n  tree_index_expression () = default;\n\n  octave_map make_arg_struct () const;\n\n  //--------\n\n  // The LHS of this index expression.\n  tree_expression *m_expr {nullptr};\n\n  // FIXME: maybe all the things in the list should be in a struct or\n  // class so we can more easily ensure that they remain synchronized.\n\n  // The indices (only valid if type == paren || type == brace).\n  std::list<tree_argument_list *> m_args;\n\n  // The type of this index expression.\n  std::string m_type;\n\n  // Record dot tokens for position and possible comment info.\n  std::list<token> m_dot_tok;\n\n  // The names of the arguments.  Used for constant struct element\n  // references.\n  std::list<string_vector> m_arg_nm;\n\n  // The list of dynamic field names, if any.\n  std::list<tree_expression *> m_dyn_field;\n\n  // TRUE if this expression was parsed as a word list command.\n  bool m_word_list_cmd {false};\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-jump.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_jump_h)\n#define octave_pt_jump_h 1\n\n#include \"octave-config.h\"\n\n#include \"pt-cmd.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Base class for jump commands\n\nclass OCTINTERP_API tree_jump_command : public tree_command\n{\npublic:\n\n  tree_jump_command (const token& tok) : m_token (tok) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_jump_command)\n\n  ~tree_jump_command () = default;\n\n  filepos beg_pos () const { return m_token.beg_pos (); }\n  filepos end_pos () const { return m_token.end_pos (); }\n\n  comment_list leading_comments () const { return m_token.leading_comments (); }\n  comment_list trailing_comments () const { return m_token.trailing_comments (); }\n\n  token jump_token () const { return m_token; }\n\nprotected:\n\n  token m_token;\n};\n\n// Break.\n\nclass OCTINTERP_API tree_break_command : public tree_jump_command\n{\npublic:\n\n  tree_break_command (const token& tok) : tree_jump_command (tok) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_break_command)\n\n  ~tree_break_command () = default;\n\n  token break_token () const { return jump_token (); }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_break_command (*this);\n  }\n};\n\n// Continue.\n\nclass OCTINTERP_API tree_continue_command : public tree_jump_command\n{\npublic:\n\n  tree_continue_command (const token& tok) : tree_jump_command (tok) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_continue_command)\n\n  ~tree_continue_command () = default;\n\n  token continue_token () const { return jump_token (); }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_continue_command (*this);\n  }\n};\n\n// Return.\n\nclass OCTINTERP_API tree_return_command : public tree_jump_command\n{\npublic:\n\n  tree_return_command (const token& tok) : tree_jump_command (tok) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_return_command)\n\n  ~tree_return_command () = default;\n\n  token return_token () const { return jump_token (); }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_return_command (*this);\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-loop.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"pt-arg-list.h\"\n#include \"pt-exp.h\"\n#include \"pt-loop.h\"\n#include \"pt-stmt.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// While.\n\ntree_while_command::~tree_while_command ()\n{\n  delete m_expr;\n  delete m_body;\n}\n\n// Do-until.\n\ntree_do_until_command::~tree_do_until_command ()\n{\n  delete m_body;\n  delete m_expr;\n}\n\n// For.\n\ntree_simple_for_command::~tree_simple_for_command ()\n{\n  delete m_lhs;\n  delete m_expr;\n  delete m_maxproc;\n  delete m_body;\n}\n\ntree_complex_for_command::~tree_complex_for_command ()\n{\n  delete m_lhs;\n  delete m_expr;\n  delete m_body;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-loop.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_loop_h)\n#define octave_pt_loop_h 1\n\n#include \"octave-config.h\"\n\nclass octave_value;\n\n#include \"pt-cmd.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass comment_list;\nclass tree_argument_list;\nclass tree_expression;\nclass tree_statement_list;\n\n// While.\n\nclass OCTINTERP_API tree_while_command : public tree_command\n{\npublic:\n\n  tree_while_command (const token& while_tok, tree_expression *expr, tree_statement_list *body, const token& end_tok)\n    : m_while_tok (while_tok), m_expr (expr), m_body (body), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_while_command)\n\n  ~tree_while_command ();\n\n  filepos beg_pos () const { return m_while_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_while_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  token while_token () const { return m_while_tok; }\n\n  tree_expression * condition () { return m_expr; }\n\n  tree_statement_list * body () { return m_body; }\n\n  token end_token () const { return m_end_tok; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_while_command (*this);\n  }\n\nprivate:\n\n  token m_while_tok;\n\n  // Expression to test.\n  tree_expression *m_expr;\n\n  // List of commands to execute.\n  tree_statement_list *m_body {nullptr};\n\n  token m_end_tok;\n};\n\n// Do-Until.\n\nclass OCTINTERP_API tree_do_until_command : public tree_command\n{\npublic:\n\n  tree_do_until_command (const token& do_tok, tree_statement_list *body, const token& until_tok, tree_expression *expr)\n    : m_do_tok (do_tok), m_body (body), m_until_tok (until_tok), m_expr (expr)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_do_until_command)\n\n  ~tree_do_until_command ();\n\n  filepos beg_pos () const { return m_do_tok.beg_pos (); }\n  filepos end_pos () const { return m_expr->end_pos (); }\n\n  comment_list leading_comments () const { return m_do_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_expr->trailing_comments (); }\n\n  token do_token () const { return m_do_tok; }\n\n  tree_statement_list * body () { return m_body; }\n\n  token until_token () const { return m_until_tok; }\n\n  tree_expression * condition () { return m_expr; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_do_until_command (*this);\n  }\n\nprivate:\n\n  token m_do_tok;\n\n  // List of commands to execute.\n  tree_statement_list *m_body {nullptr};\n\n  token m_until_tok;\n\n  // Expression to test.\n  tree_expression *m_expr;\n};\n\n// For.\n\nclass OCTINTERP_API tree_simple_for_command : public tree_command\n{\npublic:\n\n  tree_simple_for_command (bool parfor, const token& for_tok, const token& open_paren, tree_expression *le, const token& eq_tok,\n                           tree_expression *re, const token& sep_tok, tree_expression *maxproc_arg, const token& close_paren,\n                           tree_statement_list *body, const token& end_tok)\n    : m_parfor (parfor), m_for_tok (for_tok), m_open_paren (open_paren), m_lhs (le), m_eq_tok (eq_tok),\n      m_expr (re), m_sep_tok (sep_tok), m_maxproc (maxproc_arg), m_close_paren (close_paren),\n      m_body (body), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_simple_for_command)\n\n  ~tree_simple_for_command ();\n\n  bool in_parallel () { return m_parfor; }\n\n  filepos beg_pos () const { return m_for_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_for_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  token for_token () const { return m_for_tok; }\n\n  token open_paren () const { return m_open_paren; }\n\n  tree_expression * left_hand_side () { return m_lhs; }\n\n  tree_expression * control_expr () { return m_expr; }\n\n  tree_expression * maxproc_expr () { return m_maxproc; }\n\n  token close_paren () const { return m_close_paren; }\n\n  tree_statement_list * body () { return m_body; }\n\n  token end_token () const { return m_end_tok; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_simple_for_command (*this);\n  }\n\nprivate:\n\n  // FIXME: it would be better to get this info from FOR_TOK.\n  bool m_parfor {false};\n\n  token m_for_tok;\n\n  token m_open_paren;\n\n  // Expression to modify.\n  tree_expression *m_lhs;\n\n  token m_eq_tok;\n\n  // Expression to evaluate.\n  tree_expression *m_expr;\n\n  token m_sep_tok;\n\n  // Expression to tell how many processors should be used (only valid\n  // if parallel is TRUE).\n  tree_expression *m_maxproc {nullptr};\n\n  token m_close_paren;\n\n  // List of commands to execute.\n  tree_statement_list *m_body;\n\n  token m_end_tok;\n};\n\nclass OCTINTERP_API tree_complex_for_command : public tree_command\n{\npublic:\n\n  tree_complex_for_command (const token& for_tok, tree_argument_list *le, const token& eq_tok, tree_expression *re,\n                            tree_statement_list *body, const token& end_tok)\n    : m_for_tok (for_tok), m_lhs (le), m_eq_tok (eq_tok), m_expr (re), m_body (body), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_complex_for_command)\n\n  ~tree_complex_for_command ();\n\n  filepos beg_pos () const { return m_for_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_for_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  token for_token () const { return m_for_tok; }\n\n  tree_argument_list * left_hand_side () { return m_lhs; }\n\n  tree_expression * control_expr () { return m_expr; }\n\n  tree_statement_list * body () { return m_body; }\n\n  token end_token () { return m_end_tok; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_complex_for_command (*this);\n  }\n\nprivate:\n\n  token m_for_tok;\n\n  // Expression to modify.\n  tree_argument_list *m_lhs;\n\n  token m_eq_tok;\n\n  // Expression to evaluate.\n  tree_expression *m_expr;\n\n  // List of commands to execute.\n  tree_statement_list *m_body;\n\n  token m_end_tok;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-mat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"defun.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-eval.h\"\n#include \"pt-exp.h\"\n#include \"pt-mat.h\"\n#include \"pt-tm-const.h\"\n#include \"variables.h\"\n\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\noctave_value\ntree_matrix::evaluate (tree_evaluator& tw, int)\n{\n  unwind_action act ([&tw] (const std::list<octave_lvalue> *lvl)\n  {\n    tw.set_lvalue_list (lvl);\n  }, tw.lvalue_list ());\n\n  tw.set_lvalue_list (nullptr);\n\n  tm_const tmp (*this, tw);\n\n  return tmp.concat (tw.string_fill_char ());\n}\n\nstd::string\nget_concat_class (const std::string& c1, const std::string& c2)\n{\n  std::string retval = octave_base_value::static_class_name ();\n\n  if (c1 == c2)\n    retval = c1;\n  else if (c1.empty ())\n    retval = c2;\n  else if (c2.empty ())\n    retval = c1;\n  else if (c1 == \"class\" || c2 == \"class\")\n    retval = \"class\";\n  else\n    {\n      bool c1_is_int = (c1 == \"int8\" || c1 == \"uint8\"\n                        || c1 == \"int16\" || c1 == \"uint16\"\n                        || c1 == \"int32\" || c1 == \"uint32\"\n                        || c1 == \"int64\" || c1 == \"uint64\");\n      bool c2_is_int = (c2 == \"int8\" || c2 == \"uint8\"\n                        || c2 == \"int16\" || c2 == \"uint16\"\n                        || c2 == \"int32\" || c2 == \"uint32\"\n                        || c2 == \"int64\" || c2 == \"uint64\");\n\n      bool c1_is_char = (c1 == \"char\");\n      bool c2_is_char = (c2 == \"char\");\n\n      bool c1_is_double = (c1 == \"double\");\n      bool c2_is_double = (c2 == \"double\");\n\n      bool c1_is_single = (c1 == \"single\");\n      bool c2_is_single = (c2 == \"single\");\n\n      bool c1_is_logical = (c1 == \"logical\");\n      bool c2_is_logical = (c2 == \"logical\");\n\n      bool c1_is_built_in_type\n        = (c1_is_int || c1_is_char || c1_is_double || c1_is_single\n           || c1_is_logical);\n\n      bool c2_is_built_in_type\n        = (c2_is_int || c2_is_char ||  c2_is_double || c2_is_single\n           || c2_is_logical);\n\n      // Order is important here...\n\n      if (c1 == \"cell\" || c2 == \"cell\")\n        retval = \"cell\";\n      else if (c1_is_char && c2_is_built_in_type)\n        retval = c1;\n      else if (c2_is_char && c1_is_built_in_type)\n        retval = c2;\n      else if (c1_is_int && c2_is_built_in_type)\n        retval = c1;\n      else if (c2_is_int && c1_is_built_in_type)\n        retval = c2;\n      else if (c1_is_single && c2_is_built_in_type)\n        retval = c1;\n      else if (c2_is_single && c1_is_built_in_type)\n        retval = c2;\n      else if (c1_is_double && c2_is_built_in_type)\n        retval = c1;\n      else if (c2_is_double && c1_is_built_in_type)\n        retval = c2;\n      else if (c1_is_logical && c2_is_logical)\n        retval = c1;\n    }\n\n  return retval;\n}\n\nvoid\nmaybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p)\n{\n  if (! (all_dq_strings_p || all_sq_strings_p))\n    warning_with_id (\"Octave:mixed-string-concat\",\n                     \"concatenation of single and double quoted string objects creates a single quoted string object\");\n}\n\ntree_expression *\ntree_matrix::dup (symbol_scope& scope) const\n{\n  tree_matrix *new_matrix = new tree_matrix (nullptr);\n\n  new_matrix->copy_base (*this, scope);\n\n  return new_matrix;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-mat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_mat_h)\n#define octave_pt_mat_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\nclass octave_value;\nclass octave_value_list;\n\n#include \"pt-array-list.h\"\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\nclass tree_argument_list;\n\n// General matrices.  This allows us to construct matrices from\n// other matrices, variables, and functions.\n\nclass OCTINTERP_API tree_matrix : public tree_array_list\n{\npublic:\n\n  tree_matrix (tree_argument_list *row = nullptr)\n    : tree_array_list (row)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_matrix)\n\n  ~tree_matrix () = default;\n\n  bool is_matrix () const { return true; }\n\n  bool rvalue_ok () const { return true; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_matrix (*this);\n  }\n};\n\nextern OCTINTERP_API std::string\nget_concat_class (const std::string& c1, const std::string& c2);\n\nextern OCTINTERP_API void\nmaybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-misc.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"pt-idx.h\"\n#include \"pt-misc.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Parameter lists.\n\ntree_parameter_list::~tree_parameter_list ()\n{\n  while (! empty ())\n    {\n      auto p = begin ();\n      delete *p;\n      erase (p);\n    }\n}\n\nvoid\ntree_parameter_list::mark_as_formal_parameters ()\n{\n  for (tree_decl_elt *elt : *this)\n    elt->mark_as_formal_parameter ();\n}\n\nstd::list<std::string>\ntree_parameter_list::variable_names () const\n{\n  std::list<std::string> retval;\n\n  for (tree_decl_elt *elt : *this)\n    retval.push_back (elt->name ());\n\n  if (m_marked_for_varargs)\n    retval.push_back (varargs_symbol_name ());\n\n  return retval;\n}\n\ntree_parameter_list *\ntree_parameter_list::dup (symbol_scope& scope) const\n{\n  tree_parameter_list *new_list = new tree_parameter_list (m_in_or_out);\n\n  new_list->m_marked_for_varargs = m_marked_for_varargs;\n\n  for (const tree_decl_elt *elt : *this)\n    new_list->push_back (elt->dup (scope));\n\n  return new_list;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-misc.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_misc_h)\n#define octave_pt_misc_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n\n#include \"pt-decl.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\nclass tree_identifier;\nclass tree_index_expression;\n\n// Parameter lists.  Used to hold the list of input and output\n// parameters in a function definition.  Elements are identifiers\n// only.\n\nclass OCTINTERP_API tree_parameter_list : public std::list<tree_decl_elt *>\n{\npublic:\n\n  enum in_or_out\n  {\n    in = 1,\n    out = 2\n  };\n\n  tree_parameter_list (in_or_out io)\n    : m_in_or_out (io), m_marked_for_varargs (0)\n  { }\n\n  tree_parameter_list (in_or_out io, tree_decl_elt *t)\n    : m_in_or_out (io), m_marked_for_varargs (0)\n  {\n    push_back (t);\n  }\n\n  tree_parameter_list (in_or_out io, tree_identifier *id)\n    : m_in_or_out (io), m_marked_for_varargs (0)\n  {\n    push_back (new tree_decl_elt (id));\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_parameter_list)\n\n  ~tree_parameter_list ();\n\n  tree_parameter_list * mark_in_delims (const token& open_delim, const token& close_delim)\n  {\n    m_open_delim = open_delim;\n    m_close_delim = close_delim;\n\n    return this;\n  }\n\n  filepos beg_pos () const { return m_open_delim.beg_pos (); }\n  filepos end_pos () const { return m_close_delim.end_pos (); }\n\n  comment_list leading_comments () const { return m_open_delim.leading_comments (); }\n  comment_list trailing_comments () const { return m_close_delim.trailing_comments (); }\n\n  void mark_as_formal_parameters ();\n\n  void mark_varargs () { m_marked_for_varargs = 1; }\n\n  void mark_varargs_only () { m_marked_for_varargs = -1; }\n\n  bool takes_varargs () const { return m_marked_for_varargs != 0; }\n\n  bool varargs_only () { return (m_marked_for_varargs < 0); }\n\n  bool is_input_list () const { return m_in_or_out == in; }\n\n  bool is_output_list () const { return m_in_or_out == out; }\n\n  std::list<std::string> variable_names () const;\n\n  std::string varargs_symbol_name () const\n  {\n    return m_in_or_out == in ? \"varargin\" : \"varargout\";\n  }\n\n  token open_delim () const { return m_open_delim; }\n  token close_delim () const { return m_close_delim; }\n\n  tree_parameter_list * dup (symbol_scope& scope) const;\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_parameter_list (*this);\n  }\n\nprivate:\n\n  in_or_out m_in_or_out;\n\n  // 1: takes varargs\n  // -1: takes varargs only\n  // 0: does not take varargs.\n  int m_marked_for_varargs;\n\n  token m_open_delim;\n  token m_close_delim;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-pr-code.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cctype>\n\n#include \"comment-list.h\"\n#include \"error.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pr-output.h\"\n#include \"pt-all.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_NORETURN static void\nerror_unexpected (const char *name)\n{\n  error (\"unexpected call to %s - please report this bug\", name);\n}\n\nvoid\ntree_print_code::visit_anon_fcn_handle (tree_anon_fcn_handle& afh)\n{\n  indent ();\n\n  print_parens (afh, \"(\");\n\n  m_os << \"@\";\n\n  tree_parameter_list *param_list = afh.parameter_list ();\n\n  if (param_list)\n    param_list->accept (*this);\n\n  print_fcn_handle_body (afh.expression ());\n\n  print_parens (afh, \")\");\n}\n\nvoid\ntree_print_code::visit_argument_list (tree_argument_list& lst)\n{\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_expression *elt = *p++;\n\n      if (elt)\n        {\n          elt->accept (*this);\n\n          if (p != lst.end ())\n            m_os << \", \";\n        }\n    }\n}\n\nvoid\ntree_print_code::visit_arguments_block (tree_arguments_block&)\n{\n  indent ();\n\n  // FIXME\n  m_os << \"arguments ... endarguments\";\n}\n\nvoid\ntree_print_code::visit_args_block_attribute_list (tree_args_block_attribute_list&)\n{\n  error_unexpected (\"tree_print_code::visit_args_block_attribute_list\");\n}\n\nvoid\ntree_print_code::visit_args_block_validation_list (tree_args_block_validation_list&)\n{\n  error_unexpected (\"tree_print_code::visit_args_block_validation_list\");\n}\n\nvoid\ntree_print_code::visit_arg_validation (tree_arg_validation&)\n{\n  error_unexpected (\"tree_print_code::visit_arg_validation\");\n}\n\nvoid\ntree_print_code::visit_arg_size_spec (tree_arg_size_spec&)\n{\n  error_unexpected (\"tree_print_code::visit_arg_size_spec\");\n}\n\nvoid\ntree_print_code::visit_arg_validation_fcns (tree_arg_validation_fcns&)\n{\n  error_unexpected (\"tree_print_code::visit_arg_validation_fcns\");\n}\n\nvoid\ntree_print_code::visit_binary_expression (tree_binary_expression& expr)\n{\n  indent ();\n\n  print_parens (expr, \"(\");\n\n  tree_expression *op1 = expr.lhs ();\n\n  if (op1)\n    op1->accept (*this);\n\n  m_os << ' ' << expr.op_str () << ' ';\n\n  tree_expression *op2 = expr.rhs ();\n\n  if (op2)\n    op2->accept (*this);\n\n  print_parens (expr, \")\");\n}\n\nvoid\ntree_print_code::visit_break_command (tree_break_command&)\n{\n  indent ();\n\n  m_os << \"break\";\n}\n\nvoid\ntree_print_code::visit_colon_expression (tree_colon_expression& expr)\n{\n  indent ();\n\n  print_parens (expr, \"(\");\n\n  tree_expression *op1 = expr.base ();\n\n  if (op1)\n    op1->accept (*this);\n\n  // Stupid syntax.\n\n  tree_expression *op3 = expr.increment ();\n\n  if (op3)\n    {\n      m_os << ':';\n      op3->accept (*this);\n    }\n\n  tree_expression *op2 = expr.limit ();\n\n  if (op2)\n    {\n      m_os << ':';\n      op2->accept (*this);\n    }\n\n  print_parens (expr, \")\");\n}\n\nvoid\ntree_print_code::visit_continue_command (tree_continue_command&)\n{\n  indent ();\n\n  m_os << \"continue\";\n}\n\nvoid\ntree_print_code::visit_decl_command (tree_decl_command& cmd)\n{\n  indent ();\n\n  m_os << cmd.name () << ' ';\n\n  tree_decl_init_list *init_list = cmd.initializer_list ();\n\n  if (init_list)\n    init_list->accept (*this);\n}\n\nvoid\ntree_print_code::visit_decl_init_list (tree_decl_init_list& lst)\n{\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_decl_elt *elt = *p++;\n\n      if (elt)\n        {\n          elt->accept (*this);\n\n          if (p != lst.end ())\n            m_os << \", \";\n        }\n    }\n}\n\nvoid\ntree_print_code::visit_decl_elt (tree_decl_elt& cmd)\n{\n  tree_identifier *id = cmd.ident ();\n\n  if (id)\n    id->accept (*this);\n\n  tree_expression *expr = cmd.expression ();\n\n  if (expr)\n    {\n      m_os << \" = \";\n\n      expr->accept (*this);\n    }\n}\n\nvoid\ntree_print_code::visit_simple_for_command (tree_simple_for_command& cmd)\n{\n  print_comment_list (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << (cmd.in_parallel () ? \"parfor \" : \"for \");\n\n  tree_expression *lhs = cmd.left_hand_side ();\n\n  tree_expression *maxproc = cmd.maxproc_expr ();\n\n  if (maxproc)\n    m_os << '(';\n\n  if (lhs)\n    lhs->accept (*this);\n\n  m_os << \" = \";\n\n  tree_expression *expr = cmd.control_expr ();\n\n  if (expr)\n    expr->accept (*this);\n\n  if (maxproc)\n    {\n      m_os << \", \";\n      maxproc->accept (*this);\n      m_os << ')';\n    }\n\n  newline ();\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    {\n      increment_indent_level ();\n\n      list->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  indent ();\n\n  m_os << (cmd.in_parallel () ? \"endparfor\" : \"endfor\");\n}\n\nvoid\ntree_print_code::visit_complex_for_command (tree_complex_for_command& cmd)\n{\n  print_comment_list (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << \"for [\";\n  m_nesting.push ('[');\n\n  tree_argument_list *lhs = cmd.left_hand_side ();\n\n  if (lhs)\n    lhs->accept (*this);\n\n  m_nesting.pop ();\n  m_os << \"] = \";\n\n  tree_expression *expr = cmd.control_expr ();\n\n  if (expr)\n    expr->accept (*this);\n\n  newline ();\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    {\n      increment_indent_level ();\n\n      list->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  indent ();\n\n  m_os << \"endfor\";\n}\n\nvoid\ntree_print_code::visit_spmd_command (tree_spmd_command& cmd)\n{\n  print_comment_list (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << \"spmd\";\n\n  newline ();\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    {\n      increment_indent_level ();\n\n      list->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  indent ();\n\n  m_os << \"endspmd\";\n}\n\nvoid\ntree_print_code::visit_octave_user_script (octave_user_script& fcn)\n{\n  reset ();\n\n  tree_statement_list *cmd_list = fcn.body ();\n\n  if (cmd_list)\n    cmd_list->accept (*this);\n}\n\nvoid\ntree_print_code::visit_octave_user_function (octave_user_function& fcn)\n{\n  reset ();\n\n  visit_octave_user_function_header (fcn);\n\n  tree_statement_list *cmd_list = fcn.body ();\n\n  if (cmd_list)\n    {\n      increment_indent_level ();\n\n      cmd_list->accept (*this);\n\n      // endfunction will decrement the indent level.\n    }\n\n  visit_octave_user_function_trailer (fcn);\n}\n\nvoid\ntree_print_code::visit_octave_user_function_header (octave_user_function& fcn)\n{\n  comment_list leading_comments = fcn.leading_comments ();\n\n  if (! leading_comments.empty ())\n    {\n      print_comment_list (leading_comments);\n      newline ();\n    }\n\n  indent ();\n\n  m_os << \"function \";\n\n  tree_parameter_list *ret_list = fcn.return_list ();\n\n  if (ret_list)\n    {\n      ret_list->accept (*this);\n\n      m_os << \" = \";\n    }\n  std::string fcn_name = fcn.name ();\n\n  m_os << (fcn_name.empty () ? \"(empty)\" : fcn_name) << ' ';\n\n  tree_parameter_list *param_list = fcn.parameter_list ();\n\n  if (param_list)\n    param_list->accept (*this);\n\n  newline ();\n}\n\nvoid\ntree_print_code::visit_octave_user_function_trailer (octave_user_function& fcn)\n{\n  print_indented_comment (fcn.trailing_comments ());\n\n  newline ();\n}\n\nvoid\ntree_print_code::visit_function_def (tree_function_def& fdef)\n{\n  indent ();\n\n  octave_value fcn = fdef.function ();\n\n  octave_function *f = fcn.function_value ();\n\n  if (f)\n    f->accept (*this);\n}\n\nvoid\ntree_print_code::visit_identifier (tree_identifier& id)\n{\n  indent ();\n\n  print_parens (id, \"(\");\n\n  std::string nm = id.name ();\n  m_os << (nm.empty () ? \"(empty)\" : nm);\n\n  print_parens (id, \")\");\n}\n\nvoid\ntree_print_code::visit_if_clause (tree_if_clause& cmd)\n{\n  tree_expression *expr = cmd.condition ();\n\n  if (expr)\n    expr->accept (*this);\n\n  newline ();\n\n  tree_statement_list *list = cmd.commands ();\n\n  if (list)\n    {\n      increment_indent_level ();\n\n      list->accept (*this);\n\n      decrement_indent_level ();\n    }\n}\n\nvoid\ntree_print_code::visit_if_command (tree_if_command& cmd)\n{\n  print_comment_list (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << \"if \";\n\n  tree_if_command_list *list = cmd.cmd_list ();\n\n  if (list)\n    list->accept (*this);\n\n  indent ();\n\n  m_os << \"endif\";\n}\n\nvoid\ntree_print_code::visit_if_command_list (tree_if_command_list& lst)\n{\n  auto p = lst.begin ();\n\n  bool first_elt = true;\n\n  while (p != lst.end ())\n    {\n      tree_if_clause *elt = *p++;\n\n      if (elt)\n        {\n          if (! first_elt)\n            {\n              print_indented_comment (elt->leading_comments ());\n\n              indent ();\n\n              if (elt->is_else_clause ())\n                m_os << \"else\";\n              else\n                m_os << \"elseif \";\n            }\n\n          elt->accept (*this);\n        }\n\n      first_elt = false;\n    }\n}\n\nvoid\ntree_print_code::visit_index_expression (tree_index_expression& expr)\n{\n  indent ();\n\n  print_parens (expr, \"(\");\n\n  tree_expression *e = expr.expression ();\n\n  if (e)\n    e->accept (*this);\n\n  std::list<tree_argument_list *> arg_lists = expr.arg_lists ();\n  std::string type_tags = expr.type_tags ();\n  std::list<string_vector> arg_names = expr.arg_names ();\n  std::list<tree_expression *> dyn_fields = expr.dyn_fields ();\n\n  int n = type_tags.length ();\n\n  auto p_arg_lists = arg_lists.begin ();\n  auto p_arg_names = arg_names.begin ();\n  auto p_dyn_fields = dyn_fields.begin ();\n\n  for (int i = 0; i < n; i++)\n    {\n      switch (type_tags[i])\n        {\n        case '(':\n          {\n            char nc = m_nesting.top ();\n            if ((nc == '[' || nc == '{') && expr.delim_count () == 0)\n              m_os << '(';\n            else\n              m_os << \" (\";\n            m_nesting.push ('(');\n\n            tree_argument_list *l = *p_arg_lists;\n            if (l)\n              l->accept (*this);\n\n            m_nesting.pop ();\n            m_os << ')';\n          }\n          break;\n\n        case '{':\n          {\n            char nc = m_nesting.top ();\n            if ((nc == '[' || nc == '{') && expr.delim_count () == 0)\n              m_os << '{';\n            else\n              m_os << \" {\";\n            // We only care about whitespace inside [] and {} when we\n            // are defining matrix and cell objects, not when indexing.\n            m_nesting.push ('(');\n\n            tree_argument_list *l = *p_arg_lists;\n            if (l)\n              l->accept (*this);\n\n            m_nesting.pop ();\n            m_os << '}';\n          }\n          break;\n\n        case '.':\n          {\n            std::string fn = (*p_arg_names)(0);\n            if (fn.empty ())\n              {\n                tree_expression *df = *p_dyn_fields;\n\n                if (df)\n                  {\n                    m_nesting.push ('(');\n                    m_os << \".(\";\n                    df->accept (*this);\n                    m_os << \")\";\n                    m_nesting.pop ();\n                  }\n              }\n            else\n              m_os << '.' << fn;\n          }\n          break;\n\n        default:\n          error (\"unexpected: index not '(', '{', or '.' in tree_print_code::visit_index_expression - please report this bug\");\n        }\n\n      p_arg_lists++;\n      p_arg_names++;\n      p_dyn_fields++;\n    }\n\n  print_parens (expr, \")\");\n}\n\nvoid\ntree_print_code::visit_matrix (tree_matrix& lst)\n{\n  indent ();\n\n  print_parens (lst, \"(\");\n\n  m_os << '[';\n  m_nesting.push ('[');\n\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_argument_list *elt = *p++;\n\n      if (elt)\n        {\n          elt->accept (*this);\n\n          if (p != lst.end ())\n            m_os << \"; \";\n        }\n    }\n\n  m_nesting.pop ();\n  m_os << ']';\n\n  print_parens (lst, \")\");\n}\n\nvoid\ntree_print_code::visit_cell (tree_cell& lst)\n{\n  indent ();\n\n  print_parens (lst, \"(\");\n\n  m_os << '{';\n  m_nesting.push ('{');\n\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_argument_list *elt = *p++;\n\n      if (elt)\n        {\n          elt->accept (*this);\n\n          if (p != lst.end ())\n            m_os << \"; \";\n        }\n    }\n\n  m_nesting.pop ();\n  m_os << '}';\n\n  print_parens (lst, \")\");\n}\n\nvoid\ntree_print_code::visit_multi_assignment (tree_multi_assignment& expr)\n{\n  indent ();\n\n  print_parens (expr, \"(\");\n\n  tree_argument_list *lhs = expr.left_hand_side ();\n\n  if (lhs)\n    {\n      int len = lhs->size ();\n\n      if (len > 1)\n        {\n          m_os << '[';\n          m_nesting.push ('[');\n        }\n\n      lhs->accept (*this);\n\n      if (len > 1)\n        {\n          m_nesting.pop ();\n          m_os << ']';\n        }\n    }\n\n  m_os << ' ' << expr.op_str () << ' ';\n\n  tree_expression *rhs = expr.right_hand_side ();\n\n  if (rhs)\n    rhs->accept (*this);\n\n  print_parens (expr, \")\");\n}\n\nvoid\ntree_print_code::visit_no_op_command (tree_no_op_command& cmd)\n{\n  if (cmd.is_end_of_fcn_or_script () && m_curr_print_indent_level > 1)\n    decrement_indent_level ();\n\n  indent ();\n\n  m_os << cmd.original_command ();\n}\n\nvoid\ntree_print_code::visit_constant (tree_constant& val)\n{\n  indent ();\n\n  print_parens (val, \"(\");\n\n  val.print_raw (m_os, true, m_print_original_text);\n\n  print_parens (val, \")\");\n}\n\nvoid\ntree_print_code::visit_fcn_handle (tree_fcn_handle& fh)\n{\n  indent ();\n\n  print_parens (fh, \"(\");\n\n  fh.print_raw (m_os, true, m_print_original_text);\n\n  print_parens (fh, \")\");\n}\n\nvoid\ntree_print_code::visit_parameter_list (tree_parameter_list& lst)\n{\n  bool is_input_list = lst.is_input_list ();\n\n  if (is_input_list)\n    {\n      m_os << '(';\n      m_nesting.push ('(');\n    }\n  else\n    {\n      int len = lst.size ();\n      if (lst.takes_varargs ())\n        len++;\n\n      if (len != 1)\n        {\n          m_os << '[';\n          m_nesting.push ('[');\n        }\n    }\n\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_decl_elt *elt = *p++;\n\n      if (elt)\n        {\n          elt->accept (*this);\n\n          if (p != lst.end () || lst.takes_varargs ())\n            m_os << \", \";\n        }\n    }\n\n  if (lst.takes_varargs ())\n    m_os << lst.varargs_symbol_name ();\n\n  if (is_input_list)\n    {\n      m_nesting.pop ();\n      m_os << ')';\n    }\n  else\n    {\n      int len = lst.size ();\n      if (lst.takes_varargs ())\n        len++;\n\n      if (len != 1)\n        {\n          m_nesting.pop ();\n          m_os << ']';\n        }\n    }\n}\n\nvoid\ntree_print_code::visit_postfix_expression (tree_postfix_expression& expr)\n{\n  indent ();\n\n  print_parens (expr, \"(\");\n\n  tree_expression *e = expr.operand ();\n\n  if (e)\n    e->accept (*this);\n\n  m_os << expr.op_str ();\n\n  print_parens (expr, \")\");\n}\n\nvoid\ntree_print_code::visit_prefix_expression (tree_prefix_expression& expr)\n{\n  indent ();\n\n  print_parens (expr, \"(\");\n\n  m_os << expr.op_str ();\n\n  tree_expression *e = expr.operand ();\n\n  if (e)\n    e->accept (*this);\n\n  print_parens (expr, \")\");\n}\n\nvoid\ntree_print_code::visit_return_command (tree_return_command&)\n{\n  indent ();\n\n  m_os << \"return\";\n}\n\nvoid\ntree_print_code::visit_simple_assignment (tree_simple_assignment& expr)\n{\n  indent ();\n\n  print_parens (expr, \"(\");\n\n  tree_expression *lhs = expr.left_hand_side ();\n\n  if (lhs)\n    lhs->accept (*this);\n\n  m_os << ' ' << expr.op_str () << ' ';\n\n  tree_expression *rhs = expr.right_hand_side ();\n\n  if (rhs)\n    rhs->accept (*this);\n\n  print_parens (expr, \")\");\n}\n\nvoid\ntree_print_code::visit_statement (tree_statement& stmt)\n{\n  print_comment_list (stmt.leading_comments ());\n\n  tree_command *cmd = stmt.command ();\n\n  if (cmd)\n    {\n      cmd->accept (*this);\n\n      newline ();\n    }\n  else\n    {\n      tree_expression *expr = stmt.expression ();\n\n      if (expr)\n        {\n          expr->accept (*this);\n\n          if (! stmt.print_result ())\n            {\n              m_os << ';';\n              newline (\" \");\n            }\n          else\n            newline ();\n        }\n    }\n}\n\nvoid\ntree_print_code::visit_statement_list (tree_statement_list& lst)\n{\n  for (tree_statement *elt : lst)\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_print_code::visit_switch_case (tree_switch_case& cs)\n{\n  print_comment_list (cs.leading_comments ());\n\n  indent ();\n\n  if (cs.is_default_case ())\n    m_os << \"otherwise\";\n  else\n    m_os << \"case \";\n\n  tree_expression *label = cs.case_label ();\n\n  if (label)\n    label->accept (*this);\n\n  newline ();\n\n  tree_statement_list *list = cs.commands ();\n\n  if (list)\n    {\n      increment_indent_level ();\n\n      list->accept (*this);\n\n      newline ();\n\n      decrement_indent_level ();\n    }\n}\n\nvoid\ntree_print_code::visit_switch_command (tree_switch_command& cmd)\n{\n  print_comment_list (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << \"switch \";\n\n  tree_expression *expr = cmd.switch_value ();\n\n  if (expr)\n    expr->accept (*this);\n\n  newline ();\n\n  tree_switch_case_list *list = cmd.case_list ();\n\n  if (list)\n    {\n      increment_indent_level ();\n\n      list->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  print_indented_comment (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << \"endswitch\";\n}\n\nvoid\ntree_print_code::visit_try_catch_command (tree_try_catch_command& cmd)\n{\n  print_comment_list (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << \"try\";\n\n  newline ();\n\n  tree_statement_list *try_code = cmd.body ();\n  tree_identifier *expr_id = cmd.identifier ();\n\n  if (try_code)\n    {\n      increment_indent_level ();\n\n      try_code->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  indent ();\n\n  m_os << \"catch\";\n\n  if (expr_id)\n    {\n      m_os << ' ';\n      expr_id->accept (*this);\n    }\n\n  newline ();\n\n  tree_statement_list *catch_code = cmd.cleanup ();\n\n  if (catch_code)\n    {\n      increment_indent_level ();\n\n      catch_code->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  indent ();\n\n  m_os << \"end_try_catch\";\n}\n\nvoid\ntree_print_code::visit_unwind_protect_command (tree_unwind_protect_command& cmd)\n{\n  print_comment_list (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << \"unwind_protect\";\n\n  newline ();\n\n  tree_statement_list *unwind_protect_code = cmd.body ();\n\n  if (unwind_protect_code)\n    {\n      increment_indent_level ();\n\n      unwind_protect_code->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  indent ();\n\n  m_os << \"unwind_protect_cleanup\";\n\n  newline ();\n\n  tree_statement_list *cleanup_code = cmd.cleanup ();\n\n  if (cleanup_code)\n    {\n      increment_indent_level ();\n\n      cleanup_code->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  indent ();\n\n  m_os << \"end_unwind_protect\";\n}\n\nvoid\ntree_print_code::visit_while_command (tree_while_command& cmd)\n{\n  print_comment_list (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << \"while \";\n\n  tree_expression *expr = cmd.condition ();\n\n  if (expr)\n    expr->accept (*this);\n\n  newline ();\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    {\n      increment_indent_level ();\n\n      list->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  indent ();\n\n  m_os << \"endwhile\";\n}\n\nvoid\ntree_print_code::visit_do_until_command (tree_do_until_command& cmd)\n{\n  print_comment_list (cmd.leading_comments ());\n\n  indent ();\n\n  m_os << \"do\";\n\n  newline ();\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    {\n      increment_indent_level ();\n\n      list->accept (*this);\n\n      decrement_indent_level ();\n    }\n\n  indent ();\n\n  m_os << \"until \";\n\n  tree_expression *expr = cmd.condition ();\n\n  if (expr)\n    expr->accept (*this);\n\n  newline ();\n}\n\nvoid\ntree_print_code::visit_superclass_ref (tree_superclass_ref& scr)\n{\n  m_os << scr.method_name () << \"@\" << scr.class_name ();\n}\n\nvoid\ntree_print_code::visit_metaclass_query (tree_metaclass_query& mcq)\n{\n  m_os << \"?\" << mcq.class_name ();\n}\n\nvoid\ntree_print_code::print_fcn_handle_body (tree_expression *e)\n{\n  if (e)\n    {\n      m_suppress_newlines++;\n      e->accept (*this);\n      m_suppress_newlines--;\n    }\n}\n\n// Each print_code() function should call this before printing anything.\n\nvoid\ntree_print_code::indent ()\n{\n  panic_unless (m_curr_print_indent_level >= 0);\n\n  if (m_beginning_of_line)\n    {\n      m_os << m_prefix;\n\n      m_os << std::string (m_curr_print_indent_level, ' ');\n\n      m_beginning_of_line = false;\n    }\n}\n\n// All print_code() functions should use this to print new lines.\n\nvoid\ntree_print_code::newline (const char *alt_txt)\n{\n  if (m_suppress_newlines)\n    m_os << alt_txt;\n  else\n    {\n      // Print prefix for blank lines.\n      indent ();\n\n      m_os << \"\\n\";\n\n      m_beginning_of_line = true;\n    }\n}\n\n// For resetting print_code state.\n\nvoid\ntree_print_code::reset ()\n{\n  m_beginning_of_line = true;\n  m_curr_print_indent_level = 0;\n  while (m_nesting.top () != 'n')\n    m_nesting.pop ();\n}\n\nvoid\ntree_print_code::print_parens (const tree_expression& expr, const char *txt)\n{\n  int n = expr.delim_count ();\n\n  for (int i = 0; i < n; i++)\n    m_os << txt;\n}\n\nvoid\ntree_print_code::print_comment_elt (const comment_elt& elt)\n{\n  bool printed_something = false;\n\n  bool prev_char_was_newline = false;\n\n  std::string comment = elt.text ();\n\n  std::size_t len = comment.length ();\n\n  std::size_t i = 0;\n\n  while (i < len && comment[i++] == '\\n')\n    ; // Skip leading new lines.\n  i--;\n\n  while (i < len)\n    {\n      char c = comment[i++];\n\n      if (c == '\\n')\n        {\n          if (prev_char_was_newline)\n            {\n              printed_something = true;\n\n              indent ();\n\n              m_os << \"##\";\n            }\n\n          newline ();\n\n          prev_char_was_newline = true;\n        }\n      else\n        {\n          if (m_beginning_of_line)\n            {\n              printed_something = true;\n\n              indent ();\n\n              m_os << \"##\";\n\n              if (! (isspace (c) || c == '!'))\n                m_os << ' ';\n            }\n\n          m_os << static_cast<char> (c);\n\n          prev_char_was_newline = false;\n        }\n    }\n\n  if (printed_something && ! m_beginning_of_line)\n    newline ();\n}\n\nvoid\ntree_print_code::print_comment_list (const comment_list& comment_list)\n{\n  auto p = comment_list.begin ();\n\n  while (p != comment_list.end ())\n    {\n      comment_elt elt = *p++;\n\n      print_comment_elt (elt);\n\n      if (p != comment_list.end ())\n        newline ();\n    }\n}\n\nvoid\ntree_print_code::print_indented_comment (const comment_list& comment_list)\n{\n  increment_indent_level ();\n\n  print_comment_list (comment_list);\n\n  decrement_indent_level ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-pr-code.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_pr_code_h)\n#define octave_pt_pr_code_h 1\n\n#include \"octave-config.h\"\n\n#include <stack>\n#include <string>\n\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass comment_elt;\nclass comment_list;\nclass tree_decl_command;\nclass tree_expression;\n\n// How to print the code that the parse trees represent.\n\nclass OCTINTERP_API tree_print_code : public tree_walker\n{\npublic:\n\n  tree_print_code (std::ostream& os_arg,\n                   const std::string& pfx = \"\",\n                   bool pr_orig_txt = true)\n    : m_os (os_arg), m_prefix (pfx), m_nesting (),\n      m_print_original_text (pr_orig_txt),\n      m_curr_print_indent_level (0), m_beginning_of_line (true),\n      m_suppress_newlines (0)\n  {\n    // For \"none\".\n    m_nesting.push ('n');\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_print_code)\n\n  ~tree_print_code () = default;\n\n  void visit_anon_fcn_handle (tree_anon_fcn_handle&);\n\n  void visit_argument_list (tree_argument_list&);\n\n  void visit_arguments_block (tree_arguments_block&);\n\n  void visit_args_block_attribute_list (tree_args_block_attribute_list&);\n\n  void visit_args_block_validation_list (tree_args_block_validation_list&);\n\n  void visit_arg_validation (tree_arg_validation&);\n\n  void visit_arg_size_spec (tree_arg_size_spec&);\n\n  void visit_arg_validation_fcns (tree_arg_validation_fcns&);\n\n  void visit_binary_expression (tree_binary_expression&);\n\n  void visit_break_command (tree_break_command&);\n\n  void visit_colon_expression (tree_colon_expression&);\n\n  void visit_continue_command (tree_continue_command&);\n\n  void visit_decl_command (tree_decl_command&);\n\n  void visit_decl_init_list (tree_decl_init_list&);\n\n  void visit_decl_elt (tree_decl_elt&);\n\n  void visit_simple_for_command (tree_simple_for_command&);\n\n  void visit_complex_for_command (tree_complex_for_command&);\n\n  void visit_spmd_command (tree_spmd_command&);\n\n  void visit_octave_user_script (octave_user_script&);\n\n  void visit_octave_user_function (octave_user_function&);\n\n  void visit_octave_user_function_header (octave_user_function&);\n\n  void visit_octave_user_function_trailer (octave_user_function&);\n\n  void visit_function_def (tree_function_def&);\n\n  void visit_identifier (tree_identifier&);\n\n  void visit_if_clause (tree_if_clause&);\n\n  void visit_if_command (tree_if_command&);\n\n  void visit_if_command_list (tree_if_command_list&);\n\n  void visit_index_expression (tree_index_expression&);\n\n  void visit_matrix (tree_matrix&);\n\n  void visit_cell (tree_cell&);\n\n  void visit_multi_assignment (tree_multi_assignment&);\n\n  void visit_no_op_command (tree_no_op_command&);\n\n  void visit_constant (tree_constant&);\n\n  void visit_fcn_handle (tree_fcn_handle&);\n\n  void visit_parameter_list (tree_parameter_list&);\n\n  void visit_postfix_expression (tree_postfix_expression&);\n\n  void visit_prefix_expression (tree_prefix_expression&);\n\n  void visit_return_command (tree_return_command&);\n\n  void visit_simple_assignment (tree_simple_assignment&);\n\n  void visit_statement (tree_statement&);\n\n  void visit_statement_list (tree_statement_list&);\n\n  void visit_switch_case (tree_switch_case&);\n\n  void visit_switch_command (tree_switch_command&);\n\n  void visit_try_catch_command (tree_try_catch_command&);\n\n  void visit_unwind_protect_command (tree_unwind_protect_command&);\n\n  void visit_while_command (tree_while_command&);\n\n  void visit_do_until_command (tree_do_until_command&);\n\n  void visit_superclass_ref (tree_superclass_ref&);\n\n  void visit_metaclass_query (tree_metaclass_query&);\n\n  void print_fcn_handle_body (tree_expression *);\n\nprivate:\n\n  void reset_indent_level () { m_curr_print_indent_level = 0; }\n\n  void increment_indent_level () { m_curr_print_indent_level += 2; }\n\n  void decrement_indent_level () { m_curr_print_indent_level -= 2; }\n\n  void newline (const char *alt_txt = \", \");\n\n  void indent ();\n\n  void reset ();\n\n  void print_parens (const tree_expression& expr, const char *txt);\n\n  void print_comment_list (const comment_list& comment_list);\n\n  void print_comment_elt (const comment_elt& comment_elt);\n\n  void print_indented_comment (const comment_list& comment_list);\n\n  // Must create with an output stream!\n\n  tree_print_code ();\n\n  //--------\n\n  std::ostream& m_os;\n\n  std::string m_prefix;\n\n  std::stack<char> m_nesting;\n\n  bool m_print_original_text;\n\n  // Current indentation.\n  int m_curr_print_indent_level;\n\n  // TRUE means we are at the beginning of a line.\n  bool m_beginning_of_line;\n\n  // Nonzero means we are not printing newlines and indenting.\n  int m_suppress_newlines;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-select.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"pt-exp.h\"\n#include \"pt-select.h\"\n#include \"pt-stmt.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// If clauses.\n\ntree_if_clause::~tree_if_clause ()\n{\n  delete m_expr;\n  delete m_list;\n}\n\n// If.\n\ntree_if_command::~tree_if_command ()\n{\n  delete m_list;\n}\n\n// Switch cases.\n\ntree_switch_case::~tree_switch_case ()\n{\n  delete m_label;\n  delete m_list;\n}\n\n// Switch.\n\ntree_switch_command::~tree_switch_command ()\n{\n  delete m_expr;\n  delete m_list;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-select.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_select_h)\n#define octave_pt_select_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n\n#include \"comment-list.h\"\n#include \"pt-cmd.h\"\n#include \"pt-stmt.h\"\n#include \"pt-walk.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass comment_list;\nclass tree_expression;\nclass tree_statement_list;\n\n// If.\n\nclass OCTINTERP_API tree_if_clause : public tree\n{\npublic:\n\n  tree_if_clause (const token& tok, tree_expression *e, tree_statement_list *sl)\n    : m_tok (tok), m_expr (e), m_list (sl)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_if_clause)\n\n  ~tree_if_clause ();\n\n  bool is_else_clause () { return ! m_expr; }\n\n  filepos beg_pos () const { return m_tok.beg_pos (); }\n  filepos end_pos () const { return m_list->end_pos (); }\n\n  comment_list leading_comments () const { return m_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_list->trailing_comments (); }\n\n  token if_token () const { return m_tok; }\n\n  tree_expression * condition () { return m_expr; }\n\n  tree_statement_list * commands () { return m_list; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_if_clause (*this);\n  }\n\nprivate:\n\n  token m_tok;\n\n  // The condition to test.\n  tree_expression *m_expr = nullptr;\n\n  // The list of statements to evaluate if expr is true.\n  tree_statement_list *m_list;\n};\n\nclass OCTINTERP_API tree_if_command_list : public std::list<tree_if_clause *>\n{\npublic:\n\n  tree_if_command_list () { }\n\n  tree_if_command_list (tree_if_clause *t) { push_back (t); }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_if_command_list)\n\n  ~tree_if_command_list ()\n  {\n    while (! empty ())\n      {\n        auto p = begin ();\n        delete *p;\n        erase (p);\n      }\n  }\n\n  filepos beg_pos () const\n  {\n    if (empty ())\n      return filepos ();\n\n    tree_if_clause *elt = front ();\n    return elt->beg_pos ();\n  }\n\n  filepos end_pos () const\n  {\n    if (empty ())\n      return filepos ();\n\n    tree_if_clause *elt = back ();\n    return elt->end_pos ();\n  }\n\n  comment_list leading_comments () const\n  {\n    if (empty ())\n      return comment_list ();\n\n    tree_if_clause *elt = front ();\n    return elt->leading_comments ();\n  }\n\n  comment_list trailing_comments () const\n  {\n    if (empty ())\n      return comment_list ();\n\n    tree_if_clause *elt = back ();\n    return elt->trailing_comments ();\n  }\n\n  token if_token () const\n  {\n    if (! empty ())\n      {\n        tree_if_clause *p = front ();\n        return p->if_token ();\n      }\n\n    return token ();\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_if_command_list (*this);\n  }\n};\n\nclass OCTINTERP_API tree_if_command : public tree_command\n{\npublic:\n\n  tree_if_command (const token& if_tok, const token& end_tok)\n    : m_if_tok (if_tok), m_end_tok (end_tok)\n  { }\n\n  tree_if_command (const token& if_tok, tree_if_command_list *lst, const token& end_tok)\n    : m_if_tok (if_tok), m_list (lst), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_if_command)\n\n  ~tree_if_command ();\n\n  filepos beg_pos () const { return m_if_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_if_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  token if_token () const { return m_if_tok; }\n\n  tree_if_command_list * cmd_list () { return m_list; }\n\n  token end_token () const { return m_end_tok; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_if_command (*this);\n  }\n\nprivate:\n\n  token m_if_tok;\n\n  // List of if commands (if, elseif, elseif, ... else, endif)\n  tree_if_command_list *m_list = nullptr;\n\n  token m_end_tok;\n};\n\n// Switch.\n\nclass OCTINTERP_API tree_switch_case : public tree\n{\npublic:\n\n  tree_switch_case (const token& tok, tree_statement_list *sl)\n    : m_tok (tok), m_list (sl)\n  { }\n\n  tree_switch_case (const token& tok, tree_expression *e, tree_statement_list *sl)\n    : m_tok (tok), m_label (e), m_list (sl)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_switch_case)\n\n  ~tree_switch_case ();\n\n  bool is_default_case () { return ! m_label; }\n\n  filepos beg_pos () const { return m_tok.beg_pos (); }\n  filepos end_pos () const { return m_list->end_pos (); }\n\n  comment_list leading_comments () const { return m_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_list->trailing_comments (); }\n\n  token case_token () const { return m_tok; }\n\n  tree_expression * case_label () { return m_label; }\n\n  tree_statement_list * commands () { return m_list; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_switch_case (*this);\n  }\n\nprivate:\n\n  token m_tok;\n\n  // The case label.\n  tree_expression *m_label = nullptr;\n\n  // The list of statements to evaluate if the label matches.\n  tree_statement_list *m_list;\n};\n\nclass OCTINTERP_API tree_switch_case_list : public std::list<tree_switch_case *>\n{\npublic:\n\n  tree_switch_case_list () { }\n\n  tree_switch_case_list (tree_switch_case *t) { push_back (t); }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_switch_case_list)\n\n  ~tree_switch_case_list ()\n  {\n    while (! empty ())\n      {\n        auto p = begin ();\n        delete *p;\n        erase (p);\n      }\n  }\n\n  filepos beg_pos () const\n  {\n    if (empty ())\n      return filepos ();\n\n    tree_switch_case *elt = front ();\n    return elt->beg_pos ();\n  }\n\n  filepos end_pos () const\n  {\n    if (empty ())\n      return filepos ();\n\n    tree_switch_case *elt = back ();\n    return elt->end_pos ();\n  }\n\n  comment_list leading_comments () const\n  {\n    if (empty ())\n      return comment_list ();\n\n    tree_switch_case *elt = front ();\n    return elt->leading_comments ();\n  }\n\n  comment_list trailing_comments () const\n  {\n    if (empty ())\n      return comment_list ();\n\n    tree_switch_case *elt = back ();\n    return elt->trailing_comments ();\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_switch_case_list (*this);\n  }\n};\n\nclass OCTINTERP_API tree_switch_command : public tree_command\n{\npublic:\n\n  tree_switch_command (const token& switch_tok, tree_expression *e, tree_switch_case_list *lst, const token& end_tok)\n    : m_switch_tok (switch_tok), m_expr (e), m_list (lst), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_switch_command)\n\n  ~tree_switch_command ();\n\n  filepos beg_pos () const { return m_switch_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_switch_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  token switch_token () const { return m_switch_tok; }\n\n  tree_expression * switch_value () { return m_expr; }\n\n  tree_switch_case_list * case_list () { return m_list; }\n\n  token end_token () const { return m_end_tok; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_switch_command (*this);\n  }\n\nprivate:\n\n  token m_switch_tok;\n\n  // Value on which to switch.\n  tree_expression *m_expr;\n\n  // List of cases (case 1, case 2, ..., default)\n  tree_switch_case_list *m_list;\n\n  token m_end_tok;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-spmd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"comment-list.h\"\n#include \"pt-spmd.h\"\n#include \"pt-stmt.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntree_spmd_command::~tree_spmd_command ()\n{\n  delete m_body;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-spmd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_spmd_command_h)\n#define octave_pt_spmd_command_h 1\n\n#include \"octave-config.h\"\n\n#include \"pt-cmd.h\"\n#include \"pt-walk.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass comment_list;\nclass tree_statement_list;\n\n// Spmd.\n\nclass OCTINTERP_API tree_spmd_command : public tree_command\n{\npublic:\n\n  tree_spmd_command (const token& spmd_tok, tree_statement_list *body, const token& end_tok)\n    : m_spmd_tok (spmd_tok), m_body (body), m_end_tok (end_tok)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_spmd_command)\n\n  ~tree_spmd_command ();\n\n  filepos beg_pos () const { return m_spmd_tok.beg_pos (); }\n  filepos end_pos () const { return m_end_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_spmd_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_end_tok.trailing_comments (); }\n\n  token spmd_token () { return m_spmd_tok; }\n\n  tree_statement_list * body () { return m_body; }\n\n  token end_token () { return m_end_tok; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_spmd_command (*this);\n  }\n\nprivate:\n\n  token m_spmd_tok;\n\n  // List of commands.\n  tree_statement_list *m_body;\n\n  token m_end_tok;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-stmt.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <typeinfo>\n\n#include \"quit.h\"\n\n#include \"bp-table.h\"\n#include \"comment-list.h\"\n#include \"event-manager.h\"\n#include \"input.h\"\n#include \"oct-lvalue.h\"\n#include \"ov.h\"\n#include \"pager.h\"\n#include \"pt-bp.h\"\n#include \"pt-cmd.h\"\n#include \"pt-eval.h\"\n#include \"pt-id.h\"\n#include \"pt-idx.h\"\n#include \"pt-jump.h\"\n#include \"pt-pr-code.h\"\n#include \"pt-stmt.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// A list of commands to be executed.\n\ntree_statement::~tree_statement ()\n{\n  delete m_command;\n  delete m_expression;\n}\n\nvoid\ntree_statement::set_print_flag (bool print_flag)\n{\n  if (m_expression)\n    m_expression->set_print_flag (print_flag);\n}\n\nbool\ntree_statement::print_result ()\n{\n  return m_expression && m_expression->print_result ();\n}\n\nvoid\ntree_statement::set_breakpoint (const std::string& condition)\n{\n  if (m_command)\n    m_command->set_breakpoint (condition);\n  else if (m_expression)\n    m_expression->set_breakpoint (condition);\n}\n\nvoid\ntree_statement::delete_breakpoint ()\n{\n  if (m_command)\n    m_command->delete_breakpoint ();\n  else if (m_expression)\n    m_expression->delete_breakpoint ();\n}\n\nbool\ntree_statement::is_breakpoint () const\n{\n  return m_command ? m_command->is_breakpoint ()\n         : (m_expression ? m_expression->is_breakpoint ()\n            : false);\n}\n\nbool\ntree_statement::is_active_breakpoint (tree_evaluator& tw) const\n{\n  return m_command ? m_command->is_active_breakpoint (tw)\n         : (m_expression ? m_expression->is_active_breakpoint (tw)\n            : false);\n}\n\nfilepos\ntree_statement::beg_pos () const\n{\n  return (m_command ? m_command->beg_pos () : m_expression->beg_pos ());\n}\n\nfilepos\ntree_statement::end_pos () const\n{\n  return (m_command ? m_command->end_pos () : m_expression->end_pos ());\n}\n\ncomment_list\ntree_statement::leading_comments () const\n{\n  return m_command ? m_command->leading_comments () : m_expression->leading_comments ();\n}\n\ncomment_list\ntree_statement::trailing_comments () const\n{\n  return m_command ? m_command->trailing_comments () : m_expression->trailing_comments ();\n}\n\nvoid\ntree_statement::update_end_pos (const filepos& pos)\n{\n  if (m_command)\n    m_command->update_end_pos (pos);\n  else\n    error (\"unexpected call to tree_statement::update_end_pos - please report this bug\");\n}\n\nstd::string\ntree_statement::bp_cond () const\n{\n  return (m_command\n          ? m_command->bp_cond ()\n          : (m_expression ? m_expression->bp_cond () : \"0\"));\n}\n\nint\ntree_statement::line () const\n{\n  return (m_command\n          ? m_command->line ()\n          : (m_expression ? m_expression->line () : -1));\n}\n\nint\ntree_statement::column () const\n{\n  return (m_command\n          ? m_command->column ()\n          : (m_expression ? m_expression->column () : -1));\n}\n\nvoid\ntree_statement::echo_code (const std::string& prefix)\n{\n  tree_print_code tpc (octave_stdout, prefix);\n\n  accept (tpc);\n}\n\nbool\ntree_statement::is_end_of_fcn_or_script () const\n{\n  bool retval = false;\n\n  if (m_command)\n    {\n      tree_no_op_command *no_op_cmd\n        = dynamic_cast<tree_no_op_command *> (m_command);\n\n      if (no_op_cmd)\n        retval = no_op_cmd->is_end_of_fcn_or_script ();\n    }\n\n  return retval;\n}\n\nbool\ntree_statement::is_end_of_file () const\n{\n  bool retval = false;\n\n  if (m_command)\n    {\n      tree_no_op_command *no_op_cmd\n        = dynamic_cast<tree_no_op_command *> (m_command);\n\n      if (no_op_cmd)\n        retval = no_op_cmd->is_end_of_file ();\n    }\n\n  return retval;\n}\n\n// Create a \"breakpoint\" tree-walker, and get it to \"walk\" this\n// statement list\n// (FIXME: What does that do???)\n\nint\ntree_statement_list::set_breakpoint (int line, const std::string& condition)\n{\n  tree_breakpoint tbp (line, tree_breakpoint::set, condition);\n  accept (tbp);\n\n  return tbp.get_line ();\n}\n\nvoid\ntree_statement_list::delete_breakpoint (int line)\n{\n  if (line < 0)\n    {\n      octave_value_list bp_lst = list_breakpoints ();\n\n      int len = bp_lst.length ();\n\n      for (int i = 0; i < len; i++)\n        {\n          tree_breakpoint tbp (i, tree_breakpoint::clear);\n          accept (tbp);\n        }\n    }\n  else\n    {\n      tree_breakpoint tbp (line, tree_breakpoint::clear);\n      accept (tbp);\n    }\n}\n\noctave_value_list\ntree_statement_list::list_breakpoints ()\n{\n  tree_breakpoint tbp (0, tree_breakpoint::list);\n  accept (tbp);\n\n  return tbp.get_list ();\n}\n\n// Get list of pairs (breakpoint line, breakpoint condition)\nstd::list<bp_type>\ntree_statement_list::breakpoints_and_conds ()\n{\n  tree_breakpoint tbp (0, tree_breakpoint::list);\n  accept (tbp);\n\n  std::list<bp_type> retval;\n  octave_value_list lines = tbp.get_list ();\n  octave_value_list conds = tbp.get_cond_list ();\n\n  for (int i = 0; i < lines.length (); i++)\n    {\n      retval.push_back (bp_type (lines(i).double_value (),\n                                 conds(i).string_value ()));\n    }\n\n  return retval;\n}\n\n// Add breakpoints to file at multiple lines (the second arguments\n// of line), to stop only if condition is true.\n// Updates GUI via event_manager::update_breakpoint.\n// FIXME: COME BACK TO ME.\n\nbp_table::bp_lines\ntree_statement_list::add_breakpoint (event_manager& evmgr,\n                                     const std::string& file,\n                                     const bp_table::bp_lines& lines,\n                                     const std::string& condition)\n{\n  bp_table::bp_lines retval;\n\n  for (const auto& lineno : lines)\n    {\n      int line = set_breakpoint (lineno, condition);\n\n      if (line)\n        {\n          if (! file.empty ())\n            evmgr.update_breakpoint (true, file, line, condition);\n\n          retval.insert (line);\n        }\n    }\n\n  return retval;\n}\n\nbp_table::bp_lines\ntree_statement_list::remove_all_breakpoints (event_manager& evmgr,\n    const std::string& file)\n{\n  bp_table::bp_lines retval;\n\n  octave_value_list bkpts = list_breakpoints ();\n\n  for (int i = 0; i < bkpts.length (); i++)\n    {\n      int lineno = bkpts(i).int_value ();\n\n      delete_breakpoint (lineno);\n\n      retval.insert (lineno);\n\n      if (! file.empty ())\n        evmgr.update_breakpoint (false, file, lineno);\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-stmt.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_stmt_h)\n#define octave_pt_stmt_h 1\n\n#include \"octave-config.h\"\n\nclass octave_value_list;\n\n#include <deque>\n#include <list>\n\n#include \"bp-table.h\"\n#include \"pt.h\"\n#include \"pt-walk.h\"\n\nclass event_manager;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass comment_list;\nclass tree_command;\nclass tree_evaluator;\nclass tree_expression;\n\n// A statement is either a command to execute or an expression to\n// evaluate.\n\nclass OCTINTERP_API tree_statement : public tree\n{\npublic:\n\n  tree_statement ()\n    : m_command (nullptr), m_expression (nullptr)\n  { }\n\n  tree_statement (tree_command *c)\n    : m_command (c), m_expression (nullptr)\n  { }\n\n  tree_statement (tree_expression *e)\n    : m_command (nullptr), m_expression (e)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_statement)\n\n  ~tree_statement ();\n\n  void set_print_flag (bool print_flag);\n\n  bool print_result ();\n\n  bool is_command () const { return m_command != nullptr; }\n\n  bool is_expression () const { return m_expression != nullptr; }\n\n  void set_breakpoint (const std::string& condition);\n\n  void delete_breakpoint ();\n\n  bool is_breakpoint () const;\n\n  bool is_active_breakpoint (tree_evaluator& tw) const;\n\n  filepos beg_pos () const;\n  filepos end_pos () const;\n\n  comment_list leading_comments () const;\n  comment_list trailing_comments () const;\n\n  virtual void update_end_pos (const filepos& pos);\n\n  std::string bp_cond () const;\n\n  int line () const;\n  int column () const;\n\n  void echo_code (const std::string& prefix);\n\n  tree_command * command () { return m_command; }\n\n  tree_expression * expression () { return m_expression; }\n\n  bool is_null_statement () const\n  {\n    return ! (m_command || m_expression);\n  }\n\n  bool is_end_of_fcn_or_script () const;\n\n  bool is_end_of_file () const;\n\n  // Allow modification of this statement.  Note that there is no\n  // checking.  If you use these, are you sure you know what you are\n  // doing?\n\n  void set_command (tree_command *c) { m_command = c; }\n\n  void set_expression (tree_expression *e) { m_expression = e; }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_statement (*this);\n  }\n\nprivate:\n\n  // Only one of cmd or expr can be valid at once.\n\n  // Command to execute.\n  tree_command *m_command;\n\n  // Expression to evaluate.\n  tree_expression *m_expression;\n};\n\n// A list of statements to evaluate.\n\nclass OCTINTERP_API tree_statement_list : public std::list<tree_statement *>\n{\npublic:\n\n  tree_statement_list ()\n    : m_function_body (false), m_anon_function_body (false),\n      m_script_body (false) { }\n\n  tree_statement_list (tree_statement *s)\n    : m_function_body (false), m_anon_function_body (false),\n      m_script_body (false) { push_back (s); }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_statement_list)\n\n  ~tree_statement_list ()\n  {\n    while (! empty ())\n      {\n        auto p = begin ();\n        delete *p;\n        erase (p);\n      }\n  }\n\n  filepos beg_pos () const\n  {\n    if (empty ())\n      return filepos ();\n\n    tree_statement *elt = front ();\n    return elt->beg_pos ();\n  }\n\n  filepos end_pos () const\n  {\n    if (empty ())\n      return filepos ();\n\n    tree_statement *elt = back ();\n    return elt->end_pos ();\n  }\n\n  comment_list leading_comments () const\n  {\n    if (empty ())\n      return comment_list ();\n\n    tree_statement *elt = front ();\n    return elt->leading_comments ();\n  }\n\n  comment_list trailing_comments () const\n  {\n    if (empty ())\n      return comment_list ();\n\n    tree_statement *elt = back ();\n    return elt->trailing_comments ();\n  }\n\n  void mark_as_function_body () { m_function_body = true; }\n\n  void mark_as_anon_function_body () { m_anon_function_body = true; }\n\n  void mark_as_script_body () { m_script_body = true; }\n\n  bool is_function_body () const { return m_function_body; }\n\n  bool is_anon_function_body () const { return m_anon_function_body; }\n\n  bool is_script_body () const { return m_script_body; }\n\n  int set_breakpoint (int line, const std::string& condition);\n\n  void delete_breakpoint (int line);\n\n  octave_value_list list_breakpoints ();\n\n  std::list<bp_type> breakpoints_and_conds ();\n\n  bp_table::bp_lines add_breakpoint (event_manager& evmgr,\n                                     const std::string& file,\n                                     const bp_table::bp_lines& lines,\n                                     const std::string& condition);\n\n  bp_table::bp_lines remove_all_breakpoints (event_manager& evmgr,\n      const std::string& file);\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_statement_list (*this);\n  }\n\nprivate:\n\n  // Does this list of statements make up the body of a function?\n  bool m_function_body;\n\n  // Does this list of statements make up the body of a function?\n  bool m_anon_function_body;\n\n  // Does this list of statements make up the body of a script?\n  bool m_script_body;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-tm-const.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-locbuf.h\"\n#include \"quit.h\"\n\n#include \"data.h\"\n#include \"defun.h\"\n#include \"error.h\"\n#include \"errwarn.h\"\n#include \"oct-map.h\"\n#include \"ovl.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-bp.h\"\n#include \"pt-eval.h\"\n#include \"pt-exp.h\"\n#include \"pt-mat.h\"\n#include \"pt-tm-const.h\"\n#include \"utils.h\"\n#include \"ov.h\"\n#include \"variables.h\"\n\n#include \"ov-cx-mat.h\"\n#include \"ov-flt-cx-mat.h\"\n#include \"ov-re-sparse.h\"\n#include \"ov-cx-sparse.h\"\n\nOCTAVE_NORETURN static\nvoid\neval_error (const char *msg, const dim_vector& x, const dim_vector& y)\n{\n  error (\"%s (%s vs %s)\", msg, x.str ().c_str (), y.str ().c_str ());\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid tm_row_const::cellify ()\n{\n  bool elt_changed = false;\n\n  for (auto& elt : m_values)\n    {\n      octave_quit ();\n\n      if (! elt.iscell ())\n        {\n          elt_changed = true;\n\n          if (elt.isempty ())\n            elt = Cell ();\n          else\n            elt = Cell (elt);\n        }\n    }\n\n  if (! elt_changed)\n    return;\n\n  bool first_elem = true;\n\n  for (const auto& val : m_values)\n    {\n      octave_quit ();\n\n      const dim_vector& this_elt_dv = val.dims ();\n\n      if (! this_elt_dv.zero_by_zero ())\n        {\n          if (first_elem)\n            {\n              first_elem = false;\n              m_dv = this_elt_dv;\n            }\n          else if (! m_dv.hvcat (this_elt_dv, 1))\n            eval_error (\"horizontal dimensions mismatch\", m_dv, this_elt_dv);\n        }\n    }\n}\n\nvoid\ntm_row_const::init_element (const octave_value& val, bool& first_elem)\n{\n  std::string this_elt_class_name\n    = val.isobject () ? \"class\" : val.class_name ();\n\n  m_class_name = get_concat_class (m_class_name, this_elt_class_name);\n\n  const dim_vector& this_elt_dv = val.dims ();\n\n  if (! this_elt_dv.zero_by_zero ())\n    {\n      m_all_empty = false;\n\n      if (first_elem)\n        {\n          if (val.isstruct ())\n            m_first_elem_is_struct = true;\n\n          first_elem = false;\n        }\n    }\n  else if (val.iscell ())\n    first_elem = false;\n\n  m_values.push_back (val);\n\n  if (m_all_strings && ! val.is_string ())\n    m_all_strings = false;\n\n  if (m_all_sq_strings && ! val.is_sq_string ())\n    m_all_sq_strings = false;\n\n  if (m_all_dq_strings && ! val.is_dq_string ())\n    m_all_dq_strings = false;\n\n  if (! m_some_strings && val.is_string ())\n    m_some_strings = true;\n\n  if (m_all_real && ! val.isreal ())\n    m_all_real = false;\n\n  if (m_all_complex && ! (val.iscomplex () || val.isreal ()))\n    m_all_complex = false;\n\n  if (! m_any_cell && val.iscell ())\n    m_any_cell = true;\n\n  if (! m_any_sparse && val.issparse ())\n    m_any_sparse = true;\n\n  if (! m_any_class && val.isobject ())\n    m_any_class = true;\n\n  // Special treatment of sparse matrices to avoid out-of-memory error\n  m_all_1x1 = m_all_1x1 && ! val.issparse () && val.numel () == 1;\n}\n\n// FIXME: This function is mostly a duplicate of\n//\n//   void tm_row_const::init (const octave_value *, const octave_value *)\n//\n// The common parts should be factored out into a single function that\n// is used by the others.\n\nvoid\ntm_row_const::init (const tree_argument_list& row, tree_evaluator& tw)\n{\n  bool first_elem = true;\n\n  for (auto *elt : row)\n    {\n      octave_quit ();\n\n      // Evaluate with unknown number of output arguments\n      octave_value tmp = elt->evaluate (tw, -1);\n\n      if (tmp.is_undefined ())\n        error (\"undefined element in matrix list\");\n\n      if (tmp.is_cs_list ())\n        {\n          octave_value_list tlst = tmp.list_value ();\n\n          for (octave_idx_type i = 0; i < tlst.length (); i++)\n            {\n              octave_quit ();\n\n              init_element (tlst(i), first_elem);\n            }\n        }\n      else\n        init_element (tmp, first_elem);\n    }\n\n  if (m_any_cell && ! m_any_class && ! m_first_elem_is_struct)\n    cellify ();\n\n  first_elem = true;\n\n  for (const auto& val : m_values)\n    {\n      octave_quit ();\n\n      const dim_vector& this_elt_dv = val.dims ();\n\n      if (! this_elt_dv.zero_by_zero ())\n        {\n          m_all_empty = false;\n\n          if (first_elem)\n            {\n              first_elem = false;\n              m_dv = this_elt_dv;\n            }\n          else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 1)))\n            eval_error (\"horizontal dimensions mismatch\", m_dv, this_elt_dv);\n        }\n    }\n}\n\noctave_value\ntm_const::concat (char string_fill_char) const\n{\n  if (m_tm_rows.empty ())\n    return Matrix ();\n\n  // Try to speed up the common cases.\n\n  std::string result_type = m_class_name;\n\n  if (m_any_class)\n    return class_concat ();\n  else if (result_type == \"double\")\n    {\n      if (m_any_sparse)\n        {\n          if (m_all_real)\n            return sparse_array_concat<SparseMatrix> ();\n          else\n            return sparse_array_concat<SparseComplexMatrix> ();\n        }\n      else\n        {\n          if (m_all_real)\n            return array_concat<NDArray> ();\n          else\n            return array_concat<ComplexNDArray> ();\n        }\n    }\n  else if (result_type == \"single\")\n    {\n      if (m_all_real)\n        return array_concat<FloatNDArray> ();\n      else\n        return array_concat<FloatComplexNDArray> ();\n    }\n  else if (result_type == \"char\")\n    {\n      if (! m_all_strings)\n        warn_implicit_conversion (\"Octave:num-to-str\",\n                                  \"numeric\", result_type);\n      else\n        maybe_warn_string_concat (m_all_dq_strings, m_all_sq_strings);\n\n      return char_array_concat (string_fill_char);\n    }\n  else if (result_type == \"logical\")\n    {\n      if (m_any_sparse)\n        return sparse_array_concat<SparseBoolMatrix> ();\n      else\n        return array_concat<boolNDArray> ();\n    }\n  else if (result_type == \"int8\")\n    return array_concat<int8NDArray> ();\n  else if (result_type == \"int16\")\n    return array_concat<int16NDArray> ();\n  else if (result_type == \"int32\")\n    return array_concat<int32NDArray> ();\n  else if (result_type == \"int64\")\n    return array_concat<int64NDArray> ();\n  else if (result_type == \"uint8\")\n    return array_concat<uint8NDArray> ();\n  else if (result_type == \"uint16\")\n    return array_concat<uint16NDArray> ();\n  else if (result_type == \"uint32\")\n    return array_concat<uint32NDArray> ();\n  else if (result_type == \"uint64\")\n    return array_concat<uint64NDArray> ();\n  else if (result_type == \"cell\")\n    return array_concat<Cell> ();\n  else if (result_type == \"struct\")\n    {\n      if (m_all_1x1)\n        return map_concat<octave_scalar_map> ();\n      else\n        return map_concat<octave_map> ();\n    }\n  else\n    return generic_concat ();\n}\n\n// FIXME: This function is mostly a duplicate of both of the functions\n//\n//   void tm_const::init (const octave_value *, const octave_value *,\n//                        const std::vector<int>&)\n//   void tm_const::init (const octave_value *, const octave_value *,\n//                        octave_idx_type)\n//\n// The common parts should be factored out into a single function that\n// is used by the others.\n\nvoid\ntm_const::init (const tree_matrix& tm)\n{\n  bool first_elem = true;\n  bool first_elem_is_struct = false;\n\n  // Just eval and figure out if what we have is complex or all strings.\n  // We can't check columns until we know that this is a numeric matrix --\n  // collections of strings can have elements of different lengths.\n\n  for (const auto *elt : tm)\n    {\n      octave_quit ();\n\n      tm_row_const row (*elt, m_evaluator);\n\n      if (first_elem)\n        {\n          first_elem_is_struct = row.first_elem_struct_p ();\n\n          first_elem = false;\n        }\n\n      if (row.empty ())\n        continue;\n\n      if (m_all_strings && ! row.all_strings_p ())\n        m_all_strings = false;\n\n      if (m_all_sq_strings && ! row.all_sq_strings_p ())\n        m_all_sq_strings = false;\n\n      if (m_all_dq_strings && ! row.all_dq_strings_p ())\n        m_all_dq_strings = false;\n\n      if (! m_some_strings && row.some_strings_p ())\n        m_some_strings = true;\n\n      if (m_all_real && ! row.all_real_p ())\n        m_all_real = false;\n\n      if (m_all_complex && ! row.all_complex_p ())\n        m_all_complex = false;\n\n      if (m_all_empty && ! row.all_empty_p ())\n        m_all_empty = false;\n\n      if (! m_any_cell && row.any_cell_p ())\n        m_any_cell = true;\n\n      if (! m_any_sparse && row.any_sparse_p ())\n        m_any_sparse = true;\n\n      if (! m_any_class && row.any_class_p ())\n        m_any_class = true;\n\n      m_all_1x1 = m_all_1x1 && row.all_1x1_p ();\n\n      m_tm_rows.push_back (row);\n    }\n\n  if (m_any_cell && ! m_any_class && ! first_elem_is_struct)\n    {\n      for (auto& elt : m_tm_rows)\n        {\n          octave_quit ();\n\n          elt.cellify ();\n        }\n    }\n\n  first_elem = true;\n\n  for (const auto& elt : m_tm_rows)\n    {\n      octave_quit ();\n\n      octave_idx_type this_elt_nr = elt.rows ();\n      octave_idx_type this_elt_nc = elt.cols ();\n\n      std::string this_elt_class_name = elt.class_name ();\n      m_class_name = get_concat_class (m_class_name, this_elt_class_name);\n\n      const dim_vector& this_elt_dv = elt.dims ();\n\n      m_all_empty = false;\n\n      if (first_elem)\n        {\n          first_elem = false;\n\n          m_dv = this_elt_dv;\n        }\n      else if (m_all_strings && m_dv.ndims () == 2\n               && this_elt_dv.ndims () == 2)\n        {\n          // This is Octave's specialty.\n          // Character matrices support rows of unequal length.\n          if (m_dv.any_zero ())\n            {\n              // Empty existing element (bug #52542).\n              // Replace empty element with non-empty one.\n              m_dv = this_elt_dv;\n            }\n          else\n            {\n              if (this_elt_nc > cols ())\n                m_dv(1) = this_elt_nc;\n              m_dv(0) += this_elt_nr;\n            }\n        }\n      else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0)))\n        eval_error (\"vertical dimensions mismatch\", m_dv, this_elt_dv);\n    }\n}\n\noctave_value\ntm_const::char_array_concat (char string_fill_char) const\n{\n  char type = (m_all_dq_strings ? '\"' : '\\'');\n\n  charNDArray result (m_dv, string_fill_char);\n\n  array_concat_internal<charNDArray> (result);\n\n  return octave_value (result, type);\n}\n\noctave_value\ntm_const::class_concat () const\n{\n  octave_value retval;\n\n  octave_value_list rows (m_tm_rows.size (), octave_value ());\n\n  octave_idx_type j = 0;\n  for (const auto& tmrc : m_tm_rows)\n    {\n      octave_quit ();\n\n      if (tmrc.length () == 1)\n        rows(j++) = *(tmrc.begin ());\n      else\n        {\n          octave_value_list row (tmrc.length (), octave_value ());\n\n          octave_idx_type i = 0;\n          for (const auto& elt : tmrc)\n            row(i++) = elt;\n\n          rows(j++) = do_class_concat (row, \"horzcat\", 1);\n        }\n    }\n\n  if (rows.length () == 1)\n    retval = rows(0);\n  else\n    retval = do_class_concat (rows, \"vertcat\", 0);\n\n  return retval;\n}\n\noctave_value\ntm_const::generic_concat () const\n{\n  // The line below might seem crazy, since we take a copy of the\n  // first argument, resize it to be empty and then resize it to be\n  // full.  This is done since it means that there is no recopying of\n  // data, as would happen if we used a single resize.  It should be\n  // noted that resize operation is also significantly slower than the\n  // cat_op function, so it makes sense to have an empty matrix and\n  // copy all data.\n  //\n  // We might also start with a empty octave_value using\n  //\n  //   ctmp = type_info::lookup_type (tmp.begin() -> begin() -> type_name());\n  //\n  // and then directly resize.  However, for some types there might be\n  // some additional setup needed, and so this should be avoided.\n\n  octave_value ctmp;\n\n  // Find the first non-empty object\n\n  if (m_any_sparse)\n    {\n      // Start with sparse matrix to avoid issues memory issues with\n      // things like [ones(1,4),sprandn(1e8,4,1e-4)]\n\n      if (m_all_real)\n        ctmp = octave_sparse_matrix ().resize (m_dv);\n      else\n        ctmp = octave_sparse_complex_matrix ().resize (m_dv);\n    }\n  else\n    {\n      for (const auto& row : m_tm_rows)\n        {\n          octave_quit ();\n\n          for (const auto& elt : row)\n            {\n              octave_quit ();\n\n              ctmp = elt;\n\n              if (! ctmp.all_zero_dims ())\n                goto found_non_empty;\n            }\n        }\n\n      ctmp = (*(m_tm_rows.begin () -> begin ()));\n\n    found_non_empty:\n\n      if (! m_all_empty)\n        ctmp = ctmp.resize (dim_vector (0, 0)).resize (m_dv);\n    }\n\n  // Now, extract the values from the individual elements and insert\n  // them in the result matrix.\n\n  interpreter& interp = m_evaluator.get_interpreter ();\n\n  type_info& ti = interp.get_type_info ();\n\n  int dv_len = m_dv.ndims ();\n  octave_idx_type ntmp = (dv_len > 1 ? dv_len : 2);\n  Array<octave_idx_type> ra_idx (dim_vector (ntmp, 1), 0);\n\n  for (const auto& row : m_tm_rows)\n    {\n      octave_quit ();\n\n      for (const auto& elt : row)\n        {\n          octave_quit ();\n\n          if (elt.isempty ())\n            continue;\n\n          ctmp = cat_op (ti, ctmp, elt, ra_idx);\n\n          ra_idx (1) += elt.columns ();\n        }\n\n      ra_idx (0) += row.rows ();\n      ra_idx (1) = 0;\n    }\n\n  octave_value retval = ctmp;\n\n  // If some elements are strings, force the result to be a string.\n\n  if (m_some_strings && ! retval.is_string ())\n    retval = retval.convert_to_str ();\n\n  return retval;\n}\n\n// The result is passed as a parameter to this function so that the\n// char_array_concat function can create the array externally.\n// Otherwise, we would need a specialization of this function for\n// character arrays just to handle string_fill_char.\n\ntemplate <typename TYPE>\nvoid\ntm_const::array_concat_internal (TYPE& result) const\n{\n  octave_idx_type r = 0;\n  octave_idx_type c = 0;\n\n  for (const auto& row : m_tm_rows)\n    {\n      // Skip empty arrays to allow looser rules.\n      if (row.dims ().any_zero ())\n        continue;\n\n      for (const auto& elt : row)\n        {\n          octave_quit ();\n\n          TYPE ra = octave_value_extract<TYPE> (elt);\n\n          // Skip empty arrays to allow looser rules.\n\n          if (! ra.isempty ())\n            {\n              result.insert (ra, r, c);\n\n              c += ra.columns ();\n            }\n        }\n\n      r += row.rows ();\n      c = 0;\n    }\n}\n\ntemplate <typename TYPE>\nTYPE\ntm_const::array_concat () const\n{\n  typedef typename TYPE::element_type ELT_T;\n\n  if (m_dv.any_zero ())\n    return TYPE (m_dv);\n\n  if (m_tm_rows.size () == 1)\n    {\n      // If possible, forward the operation to liboctave.\n      // Single row.\n      const tm_row_const& row = m_tm_rows.front ();\n      if (! (equal_types<ELT_T, char>::value\n             || equal_types<ELT_T, octave_value>::value)\n          && row.all_1x1_p ())\n        {\n          // Optimize all scalars case.\n          TYPE result (m_dv);\n          panic_unless (static_cast<std::size_t> (result.numel ())\n                        == row.length ());\n          octave_idx_type i = 0;\n          for (const auto& elt : row)\n            result(i++) = octave_value_extract<ELT_T> (elt);\n\n          return result;\n        }\n\n      octave_idx_type ncols = row.length ();\n      octave_idx_type i = 0;\n      OCTAVE_LOCAL_BUFFER (TYPE, array_list, ncols);\n\n      for (const auto& elt : row)\n        {\n          octave_quit ();\n\n          array_list[i++] = octave_value_extract<TYPE> (elt);\n        }\n\n      return TYPE::cat (-2, ncols, array_list);\n    }\n  else\n    {\n      TYPE result (m_dv);\n      array_concat_internal<TYPE> (result);\n      return result;\n    }\n}\n\ntemplate <typename TYPE>\nTYPE\ntm_const::sparse_array_concat () const\n{\n  if (m_dv.any_zero ())\n    return TYPE (m_dv);\n\n  // Sparse matrices require preallocation for efficient indexing; besides,\n  // only horizontal concatenation can be efficiently handled by indexing.\n  // So we just cat all rows through liboctave, then cat the final column.\n  octave_idx_type nrows = m_tm_rows.size ();\n  octave_idx_type j = 0;\n  OCTAVE_LOCAL_BUFFER (TYPE, sparse_row_list, nrows);\n  for (const auto& row : m_tm_rows)\n    {\n      octave_idx_type ncols = row.length ();\n      octave_idx_type i = 0;\n      OCTAVE_LOCAL_BUFFER (TYPE, sparse_list, ncols);\n\n      for (auto& elt : row)\n        {\n          octave_quit ();\n\n          sparse_list[i] = octave_value_extract<TYPE> (elt);\n          i++;\n        }\n\n      TYPE stmp = TYPE::cat (-2, ncols, sparse_list);\n      sparse_row_list[j] = stmp;\n      j++;\n    }\n\n  return TYPE::cat (-1, nrows, sparse_row_list);\n}\n\ntemplate <typename MAP>\noctave_map\ntm_const::map_concat () const\n{\n  if (m_dv.any_zero ())\n    return octave_map (m_dv);\n\n  octave_idx_type nrows = m_tm_rows.size ();\n  octave_idx_type j = 0;\n  OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows);\n  for (const auto& row : m_tm_rows)\n    {\n      octave_idx_type ncols = row.length ();\n      octave_idx_type i = 0;\n      OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols);\n\n      for (auto& elt : row)\n        {\n          octave_quit ();\n\n          map_list[i] = octave_value_extract<MAP> (elt);\n          i++;\n        }\n\n      octave_map mtmp = octave_map::cat (-2, ncols, map_list);\n      map_row_list[j] = mtmp;\n      j++;\n    }\n\n  return octave_map::cat (-1, nrows, map_row_list);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n/*\n## test concatenation with all zero matrices\n%!assert ([ \"\" 65*ones(1,10) ], \"AAAAAAAAAA\")\n%!assert ([ 65*ones(1,10) \"\" ], \"AAAAAAAAAA\")\n\n%!test\n%! c = {\"foo\"; \"bar\"; \"bazoloa\"};\n%! assert ([c; \"a\"; \"bc\"; \"def\"], {\"foo\"; \"bar\"; \"bazoloa\"; \"a\"; \"bc\"; \"def\"});\n\n%!assert (class ([int64(1), int64(1)]), \"int64\")\n%!assert (class ([int64(1), int32(1)]), \"int64\")\n%!assert (class ([int64(1), int16(1)]), \"int64\")\n%!assert (class ([int64(1), int8(1)]), \"int64\")\n%!assert (class ([int64(1), uint64(1)]), \"int64\")\n%!assert (class ([int64(1), uint32(1)]), \"int64\")\n%!assert (class ([int64(1), uint16(1)]), \"int64\")\n%!assert (class ([int64(1), uint8(1)]), \"int64\")\n%!assert (class ([int64(1), single(1)]), \"int64\")\n%!assert (class ([int64(1), double(1)]), \"int64\")\n%!assert (class ([int64(1), cell(1)]), \"cell\")\n%!assert (class ([int64(1), true]), \"int64\")\n%!assert (class ([int64(1), \"a\"]), \"char\")\n\n%!assert (class ([int32(1), int64(1)]), \"int32\")\n%!assert (class ([int32(1), int32(1)]), \"int32\")\n%!assert (class ([int32(1), int16(1)]), \"int32\")\n%!assert (class ([int32(1), int8(1)]), \"int32\")\n%!assert (class ([int32(1), uint64(1)]), \"int32\")\n%!assert (class ([int32(1), uint32(1)]), \"int32\")\n%!assert (class ([int32(1), uint16(1)]), \"int32\")\n%!assert (class ([int32(1), uint8(1)]), \"int32\")\n%!assert (class ([int32(1), single(1)]), \"int32\")\n%!assert (class ([int32(1), double(1)]), \"int32\")\n%!assert (class ([int32(1), cell(1)]), \"cell\")\n%!assert (class ([int32(1), true]), \"int32\")\n%!assert (class ([int32(1), \"a\"]), \"char\")\n\n%!assert (class ([int16(1), int64(1)]), \"int16\")\n%!assert (class ([int16(1), int32(1)]), \"int16\")\n%!assert (class ([int16(1), int16(1)]), \"int16\")\n%!assert (class ([int16(1), int8(1)]), \"int16\")\n%!assert (class ([int16(1), uint64(1)]), \"int16\")\n%!assert (class ([int16(1), uint32(1)]), \"int16\")\n%!assert (class ([int16(1), uint16(1)]), \"int16\")\n%!assert (class ([int16(1), uint8(1)]), \"int16\")\n%!assert (class ([int16(1), single(1)]), \"int16\")\n%!assert (class ([int16(1), double(1)]), \"int16\")\n%!assert (class ([int16(1), cell(1)]), \"cell\")\n%!assert (class ([int16(1), true]), \"int16\")\n%!assert (class ([int16(1), \"a\"]), \"char\")\n\n%!assert (class ([int8(1), int64(1)]), \"int8\")\n%!assert (class ([int8(1), int32(1)]), \"int8\")\n%!assert (class ([int8(1), int16(1)]), \"int8\")\n%!assert (class ([int8(1), int8(1)]), \"int8\")\n%!assert (class ([int8(1), uint64(1)]), \"int8\")\n%!assert (class ([int8(1), uint32(1)]), \"int8\")\n%!assert (class ([int8(1), uint16(1)]), \"int8\")\n%!assert (class ([int8(1), uint8(1)]), \"int8\")\n%!assert (class ([int8(1), single(1)]), \"int8\")\n%!assert (class ([int8(1), double(1)]), \"int8\")\n%!assert (class ([int8(1), cell(1)]), \"cell\")\n%!assert (class ([int8(1), true]), \"int8\")\n%!assert (class ([int8(1), \"a\"]), \"char\")\n\n%!assert (class ([uint64(1), int64(1)]), \"uint64\")\n%!assert (class ([uint64(1), int32(1)]), \"uint64\")\n%!assert (class ([uint64(1), int16(1)]), \"uint64\")\n%!assert (class ([uint64(1), int8(1)]), \"uint64\")\n%!assert (class ([uint64(1), uint64(1)]), \"uint64\")\n%!assert (class ([uint64(1), uint32(1)]), \"uint64\")\n%!assert (class ([uint64(1), uint16(1)]), \"uint64\")\n%!assert (class ([uint64(1), uint8(1)]), \"uint64\")\n%!assert (class ([uint64(1), single(1)]), \"uint64\")\n%!assert (class ([uint64(1), double(1)]), \"uint64\")\n%!assert (class ([uint64(1), cell(1)]), \"cell\")\n%!assert (class ([uint64(1), true]), \"uint64\")\n%!assert (class ([uint64(1), \"a\"]), \"char\")\n\n%!assert (class ([uint32(1), int64(1)]), \"uint32\")\n%!assert (class ([uint32(1), int32(1)]), \"uint32\")\n%!assert (class ([uint32(1), int16(1)]), \"uint32\")\n%!assert (class ([uint32(1), int8(1)]), \"uint32\")\n%!assert (class ([uint32(1), uint64(1)]), \"uint32\")\n%!assert (class ([uint32(1), uint32(1)]), \"uint32\")\n%!assert (class ([uint32(1), uint16(1)]), \"uint32\")\n%!assert (class ([uint32(1), uint8(1)]), \"uint32\")\n%!assert (class ([uint32(1), single(1)]), \"uint32\")\n%!assert (class ([uint32(1), double(1)]), \"uint32\")\n%!assert (class ([uint32(1), cell(1)]), \"cell\")\n%!assert (class ([uint32(1), true]), \"uint32\")\n%!assert (class ([uint32(1), \"a\"]), \"char\")\n\n%!assert (class ([uint16(1), int64(1)]), \"uint16\")\n%!assert (class ([uint16(1), int32(1)]), \"uint16\")\n%!assert (class ([uint16(1), int16(1)]), \"uint16\")\n%!assert (class ([uint16(1), int8(1)]), \"uint16\")\n%!assert (class ([uint16(1), uint64(1)]), \"uint16\")\n%!assert (class ([uint16(1), uint32(1)]), \"uint16\")\n%!assert (class ([uint16(1), uint16(1)]), \"uint16\")\n%!assert (class ([uint16(1), uint8(1)]), \"uint16\")\n%!assert (class ([uint16(1), single(1)]), \"uint16\")\n%!assert (class ([uint16(1), double(1)]), \"uint16\")\n%!assert (class ([uint16(1), cell(1)]), \"cell\")\n%!assert (class ([uint16(1), true]), \"uint16\")\n%!assert (class ([uint16(1), \"a\"]), \"char\")\n\n%!assert (class ([uint8(1), int64(1)]), \"uint8\")\n%!assert (class ([uint8(1), int32(1)]), \"uint8\")\n%!assert (class ([uint8(1), int16(1)]), \"uint8\")\n%!assert (class ([uint8(1), int8(1)]), \"uint8\")\n%!assert (class ([uint8(1), uint64(1)]), \"uint8\")\n%!assert (class ([uint8(1), uint32(1)]), \"uint8\")\n%!assert (class ([uint8(1), uint16(1)]), \"uint8\")\n%!assert (class ([uint8(1), uint8(1)]), \"uint8\")\n%!assert (class ([uint8(1), single(1)]), \"uint8\")\n%!assert (class ([uint8(1), double(1)]), \"uint8\")\n%!assert (class ([uint8(1), cell(1)]), \"cell\")\n%!assert (class ([uint8(1), true]), \"uint8\")\n%!assert (class ([uint8(1), \"a\"]), \"char\")\n\n%!assert (class ([single(1), int64(1)]), \"int64\")\n%!assert (class ([single(1), int32(1)]), \"int32\")\n%!assert (class ([single(1), int16(1)]), \"int16\")\n%!assert (class ([single(1), int8(1)]), \"int8\")\n%!assert (class ([single(1), uint64(1)]), \"uint64\")\n%!assert (class ([single(1), uint32(1)]), \"uint32\")\n%!assert (class ([single(1), uint16(1)]), \"uint16\")\n%!assert (class ([single(1), uint8(1)]), \"uint8\")\n%!assert (class ([single(1), single(1)]), \"single\")\n%!assert (class ([single(1), double(1)]), \"single\")\n%!assert (class ([single(1), cell(1)]), \"cell\")\n%!assert (class ([single(1), true]), \"single\")\n%!assert (class ([single(1), \"a\"]), \"char\")\n\n%!assert (class ([double(1), int64(1)]), \"int64\")\n%!assert (class ([double(1), int32(1)]), \"int32\")\n%!assert (class ([double(1), int16(1)]), \"int16\")\n%!assert (class ([double(1), int8(1)]), \"int8\")\n%!assert (class ([double(1), uint64(1)]), \"uint64\")\n%!assert (class ([double(1), uint32(1)]), \"uint32\")\n%!assert (class ([double(1), uint16(1)]), \"uint16\")\n%!assert (class ([double(1), uint8(1)]), \"uint8\")\n%!assert (class ([double(1), single(1)]), \"single\")\n%!assert (class ([double(1), double(1)]), \"double\")\n%!assert (class ([double(1), cell(1)]), \"cell\")\n%!assert (class ([double(1), true]), \"double\")\n%!assert (class ([double(1), \"a\"]), \"char\")\n\n%!assert (class ([cell(1), int64(1)]), \"cell\")\n%!assert (class ([cell(1), int32(1)]), \"cell\")\n%!assert (class ([cell(1), int16(1)]), \"cell\")\n%!assert (class ([cell(1), int8(1)]), \"cell\")\n%!assert (class ([cell(1), uint64(1)]), \"cell\")\n%!assert (class ([cell(1), uint32(1)]), \"cell\")\n%!assert (class ([cell(1), uint16(1)]), \"cell\")\n%!assert (class ([cell(1), uint8(1)]), \"cell\")\n%!assert (class ([cell(1), single(1)]), \"cell\")\n%!assert (class ([cell(1), double(1)]), \"cell\")\n%!assert (class ([cell(1), cell(1)]), \"cell\")\n%!assert (class ([cell(1), true]), \"cell\")\n%!assert (class ([cell(1), \"a\"]), \"cell\")\n\n%!assert (class ([true, int64(1)]), \"int64\")\n%!assert (class ([true, int32(1)]), \"int32\")\n%!assert (class ([true, int16(1)]), \"int16\")\n%!assert (class ([true, int8(1)]), \"int8\")\n%!assert (class ([true, uint64(1)]), \"uint64\")\n%!assert (class ([true, uint32(1)]), \"uint32\")\n%!assert (class ([true, uint16(1)]), \"uint16\")\n%!assert (class ([true, uint8(1)]), \"uint8\")\n%!assert (class ([true, single(1)]), \"single\")\n%!assert (class ([true, double(1)]), \"double\")\n%!assert (class ([true, cell(1)]), \"cell\")\n%!assert (class ([true, true]), \"logical\")\n%!assert (class ([true, \"a\"]), \"char\")\n\n%!assert (class ([\"a\", int64(1)]), \"char\")\n%!assert (class ([\"a\", int32(1)]), \"char\")\n%!assert (class ([\"a\", int16(1)]), \"char\")\n%!assert (class ([\"a\", int8(1)]), \"char\")\n%!assert (class ([\"a\", int64(1)]), \"char\")\n%!assert (class ([\"a\", int32(1)]), \"char\")\n%!assert (class ([\"a\", int16(1)]), \"char\")\n%!assert (class ([\"a\", int8(1)]), \"char\")\n%!assert (class ([\"a\", single(1)]), \"char\")\n%!assert (class ([\"a\", double(1)]), \"char\")\n%!assert (class ([\"a\", cell(1)]), \"cell\")\n%!assert (class ([\"a\", true]), \"char\")\n%!assert (class ([\"a\", \"a\"]), \"char\")\n\n%!assert (class ([cell(1), struct(\"foo\", \"bar\")]), \"cell\")\n%!error [struct(\"foo\", \"bar\"), cell(1)]\n\n%!test <*39041> assert (class ([cell(0), struct()]), \"cell\")\n%!test <51086> assert (class ([struct(), cell(0)]), \"struct\")\n\n%!assert ([,1], 1)\n%!assert ([1,], 1)\n%!assert ([,1,], 1)\n%!assert ([,1,;;], 1)\n%!assert ([,1,;,;], 1)\n\n%!assert ([1,1], ones (1, 2))\n%!assert ([,1,1], ones (1, 2))\n%!assert ([1,1,], ones (1, 2))\n%!assert ([,1,1,], ones (1, 2))\n%!assert ([,1,1,;;], ones (1, 2))\n%!assert ([,1,1,;,;], ones (1, 2))\n%!assert ([,;,1,1], ones (1, 2))\n\n%!assert ([1;1], ones (2, 1))\n%!assert ([1,;1], ones (2, 1))\n%!assert ([1,;,;1], ones (2, 1))\n\n%!error eval (\"[,,]\")\n%!error eval (\"[,,;,]\")\n%!error eval (\"[,;,,;,]\")\n\n%!assert (isnull ([,]))\n%!assert (isnull ([;]))\n%!assert (isnull ([;;]))\n%!assert (isnull ([;,;]))\n%!assert (isnull ([,;,;,]))\n\n## Undefined elements.\n%!function my_undef ()\n%!endfunction\n%!\n%!shared es\n%! es = struct (\"a\", {});\n%!\n%!assert <*58695> ([1; es.a; 3], [1; 3])\n%!test <*58695>\n%! fail (\"undefined element in matrix list\", \"[1; my_undef(), 3]\");\n%!\n%!assert <*58695> ([es.a; es.a; 3], 3)\n%!test <*58695>\n%! fail (\"undefined element in matrix list\", \"[my_undef(); my_undef(); 3]\")\n*/\n"
  },
  {
    "path": "libinterp/parse-tree/pt-tm-const.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_tm_const_h)\n#define octave_pt_tm_const_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <memory>\n#include <string>\n\n#include \"Array.h\"\n#include \"Sparse.h\"\n\n#include \"data.h\"\n#include \"dim-vector.h\"\n#include \"oct-map.h\"\n#include \"ov.h\"\n#include \"ovl.h\"\n#include \"pt-arg-list.h\"\n#include \"pt-mat.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass tree_evaluator;\n\n// Evaluate tree_matrix objects and convert them to octave_value\n// arrays (full and sparse numeric, char, cell, struct, class and\n// anything else that works like an array).  Use a separate class\n// (tm_const) and pass the evaluator object to it instead of doing\n// all this work in tree_evaluator::visit_matrix because the job is\n// fairly large and requires extra data (stored in the tm_info\n// class) for each row and for the overall array.\n\n// Evaluate all elements of the array, recording info about each\n// row, then create summary info for the full array.  Compute the\n// result type and dimension first before copying values.\n\n// FIXME: Handle overloading of horzcat and vertcat for built-in\n// types.\n\n// Summary info about the current row or matrix.\n\nclass OCTINTERP_API tm_info\n{\npublic:\n\n  tm_info (bool obj_is_empty)\n    : m_dv (0, 0), m_all_strings (true), m_all_sq_strings (true),\n      m_all_dq_strings (true), m_some_strings (false),\n      m_all_real (true), m_all_complex (true), m_all_empty (true),\n      m_any_cell (false), m_any_sparse (false),\n      m_any_class (false), m_all_1x1 (! obj_is_empty),\n      m_first_elem_is_struct (false), m_class_name ()\n  { }\n\n  dim_vector dims () const { return m_dv; }\n\n  octave_idx_type rows () const { return m_dv(0); }\n  octave_idx_type cols () const { return m_dv(1); }\n\n  bool all_strings_p () const { return m_all_strings; }\n  bool all_sq_strings_p () const { return m_all_sq_strings; }\n  bool all_dq_strings_p () const { return m_all_dq_strings; }\n  bool some_strings_p () const { return m_some_strings; }\n  bool all_real_p () const { return m_all_real; }\n  bool all_complex_p () const { return m_all_complex; }\n  bool all_empty_p () const { return m_all_empty; }\n  bool any_cell_p () const { return m_any_cell; }\n  bool any_sparse_p () const { return m_any_sparse; }\n  bool any_class_p () const { return m_any_class; }\n  bool all_1x1_p () const { return m_all_1x1; }\n  bool first_elem_struct_p () const { return m_first_elem_is_struct; }\n\n  std::string class_name () const { return m_class_name; }\n\nprotected:\n\n  // Size of this row or matrix after evaluation.\n  dim_vector m_dv;\n\n  // Are all elements character strings?\n  bool m_all_strings;\n\n  // Are all elements double-quoted character strings?\n  bool m_all_sq_strings;\n\n  // Are all elements single-quoted character strings?\n  bool m_all_dq_strings;\n\n  // Are any elements character strings?\n  bool m_some_strings;\n\n  // Are all elements real valued?\n  bool m_all_real;\n\n  // Are all elements complex valued?\n  bool m_all_complex;\n\n  // Are all elements empty?\n  bool m_all_empty;\n\n  // Are any elements cells?\n  bool m_any_cell;\n\n  // Are any elements sparse arrays?\n  bool m_any_sparse;\n\n  // Are any elements sparse class objects?\n  bool m_any_class;\n\n  // Do all elements have dimensions 1x1?\n  bool m_all_1x1;\n\n  // Is the first element a struct?\n  bool m_first_elem_is_struct;\n\n  // Class name of result.\n  std::string m_class_name;\n};\n\nclass OCTINTERP_API tm_row_const : public tm_info\n{\npublic:\n\n  typedef std::list<octave_value>::iterator iterator;\n  typedef std::list<octave_value>::const_iterator const_iterator;\n\n  tm_row_const () = delete;\n\n  tm_row_const (const tree_argument_list& row, tree_evaluator& tw)\n    : tm_info (row.empty ()), m_values ()\n  {\n    init (row, tw);\n  }\n\n  tm_row_const (const tm_row_const&) = default;\n\n  tm_row_const& operator = (const tm_row_const&) = delete;\n\n  ~tm_row_const () = default;\n\n  iterator begin () { return m_values.begin (); }\n  const_iterator begin () const { return m_values.begin (); }\n\n  iterator end () { return m_values.end (); }\n  const_iterator end () const { return m_values.end (); }\n\n  bool empty () const { return m_values.empty (); }\n\n  std::size_t length () const { return m_values.size (); }\n\n  void cellify ();\n\n  std::list<octave_value> values () const { return m_values; }\n\nprivate:\n\n  void init_element (const octave_value&, bool&);\n\n  void init (const tree_argument_list&, tree_evaluator& tw);\n\n  //--------\n\n  std::list<octave_value> m_values;\n};\n\nclass OCTINTERP_API tm_const : public tm_info\n{\npublic:\n\n  typedef std::list<tm_row_const>::iterator iterator;\n  typedef std::list<tm_row_const>::const_iterator const_iterator;\n\n  tm_const () = delete;\n\n  tm_const (const tree_matrix& tm, tree_evaluator& tw)\n    : tm_info (tm.empty ()), m_evaluator (tw), m_tm_rows ()\n  {\n    init (tm);\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (tm_const)\n\n  ~tm_const () = default;\n\n  octave_value concat (char string_fill_char) const;\n\n  std::list<tm_row_const> tm_rows () const { return m_tm_rows; }\n\nprivate:\n\n  void init (const tree_matrix& tm);\n\n  octave_value char_array_concat (char string_fill_char) const;\n\n  octave_value class_concat () const;\n\n  octave_value generic_concat () const;\n\n  template <typename TYPE>\n  void array_concat_internal (TYPE& result) const;\n\n  template <typename TYPE>\n  TYPE array_concat () const;\n\n  template <typename TYPE>\n  TYPE sparse_array_concat () const;\n\n  template <typename MAP>\n  octave_map map_concat () const;\n\n  //--------\n\n  tree_evaluator& m_evaluator;\n\n  // The list of lists of octave_value objects that contain the\n  // values of elements in each row of the tree_matrix object we are\n  // evaluating.\n\n  std::list<tm_row_const> m_tm_rows;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-unop.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"interpreter.h\"\n#include \"ov.h\"\n#include \"profiler.h\"\n#include \"pt-unop.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Unary expressions.\n\nstd::string\ntree_unary_expression::op_str () const\n{\n  return octave_value::unary_op_as_string (m_etype);\n}\n\n// Prefix expressions.\n\ntree_expression *\ntree_prefix_expression::dup (symbol_scope& scope) const\n{\n  tree_prefix_expression *new_pe\n    = new tree_prefix_expression (m_op_tok, m_op ? m_op->dup (scope) : nullptr, m_etype);\n\n  new_pe->copy_base (*this);\n\n  return new_pe;\n}\n\noctave_value\ntree_prefix_expression::evaluate (tree_evaluator& tw, int)\n{\n  octave_value val;\n\n  if (m_op)\n    {\n      if (m_etype == octave_value::op_incr\n          || m_etype == octave_value::op_decr)\n        {\n          octave_lvalue op_ref = m_op->lvalue (tw);\n\n          profiler::enter<tree_prefix_expression>\n          block (tw.get_profiler (), *this);\n\n          op_ref.unary_op (m_etype);\n\n          val = op_ref.value ();\n        }\n      else\n        {\n          // Evaluate with unknown number of output arguments\n          octave_value op_val = m_op->evaluate (tw, -1);\n\n          if (op_val.is_defined ())\n            {\n              profiler::enter<tree_prefix_expression>\n              block (tw.get_profiler (), *this);\n\n              // Attempt to do the operation in-place if it is unshared\n              // (a temporary expression).\n              if (op_val.get_count () == 1)\n                val = op_val.non_const_unary_op (m_etype);\n              else\n                {\n                  interpreter& interp = tw.get_interpreter ();\n\n                  type_info& ti = interp.get_type_info ();\n\n                  val = unary_op (ti, m_etype, op_val);\n                }\n            }\n        }\n    }\n\n  return val;\n}\n\n// Postfix expressions.\n\ntree_expression *\ntree_postfix_expression::dup (symbol_scope& scope) const\n{\n  tree_postfix_expression *new_pe\n    = new tree_postfix_expression (m_op ? m_op->dup (scope) : nullptr, m_op_tok, m_etype);\n\n  new_pe->copy_base (*this);\n\n  return new_pe;\n}\n\noctave_value\ntree_postfix_expression::evaluate (tree_evaluator& tw, int)\n{\n  octave_value val;\n\n  if (m_op)\n    {\n      if (m_etype == octave_value::op_incr\n          || m_etype == octave_value::op_decr)\n        {\n          octave_lvalue ref = m_op->lvalue (tw);\n\n          val = ref.value ();\n\n          profiler::enter<tree_postfix_expression>\n          block (tw.get_profiler (), *this);\n\n          ref.unary_op (m_etype);\n        }\n      else\n        {\n          // Evaluate with unknown number of output arguments\n          octave_value op_val = m_op->evaluate (tw, -1);\n\n          if (op_val.is_defined ())\n            {\n              profiler::enter<tree_postfix_expression>\n              block (tw.get_profiler (), *this);\n\n              interpreter& interp = tw.get_interpreter ();\n\n              type_info& ti = interp.get_type_info ();\n\n              val = unary_op (ti, m_etype, op_val);\n            }\n        }\n    }\n\n  return val;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-unop.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_unop_h)\n#define octave_pt_unop_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nclass octave_value;\nclass octave_value_list;\n\n#include \"ov.h\"\n#include \"pt-exp.h\"\n#include \"pt-walk.h\"\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass symbol_scope;\n\n// Unary expressions.\n\nclass OCTINTERP_API tree_unary_expression : public tree_expression\n{\nprotected:\n\n  tree_unary_expression (octave_value::unary_op t = octave_value::unknown_unary_op)\n    : m_op (nullptr), m_etype (t)  { }\n\n  tree_unary_expression (const token& op_tok, tree_expression *e, octave_value::unary_op t = octave_value::unknown_unary_op)\n    : m_op_tok (op_tok), m_op (e), m_etype (t)\n  { }\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_unary_expression)\n\n  ~tree_unary_expression () { delete m_op; }\n\n  bool is_unary_expression () const { return true; }\n\n  tree_expression * operand () { return m_op; }\n\n  token op_token () const { return m_op_tok; }\n\n  OCTAVE_DEPRECATED (11, \"use tree_unary_op::op_str instead\")\n  std::string oper () const { return op_str (); }\n\n  std::string op_str () const;\n\n  octave_value::unary_op op_type () const { return m_etype; }\n\nprotected:\n\n  // The operator token.\n  token m_op_tok;\n\n  // The operand for the expression.\n  tree_expression *m_op;\n\n  // The type of the expression.\n  octave_value::unary_op m_etype;\n};\n\n// Prefix expressions.\n\nclass OCTINTERP_API tree_prefix_expression : public tree_unary_expression\n{\npublic:\n\n  tree_prefix_expression (const token& op_tok, tree_expression *e, octave_value::unary_op t = octave_value::unknown_unary_op)\n    : tree_unary_expression (op_tok, e, t)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_prefix_expression)\n\n  ~tree_prefix_expression () = default;\n\n  filepos beg_pos () const { return m_op_tok.beg_pos (); }\n  filepos end_pos () const { return m_op->end_pos (); }\n\n  comment_list leading_comments () const { return m_op_tok.leading_comments (); }\n  comment_list trailing_comments () const { return m_op->trailing_comments (); }\n\n  bool rvalue_ok () const { return true; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_prefix_expression (*this);\n  }\n\n  std::string profiler_name () const { return \"prefix \" + op_str (); }\n};\n\n// Postfix expressions.\n\nclass OCTINTERP_API tree_postfix_expression : public tree_unary_expression\n{\npublic:\n\n  tree_postfix_expression (tree_expression *e, const token& op_tok, octave_value::unary_op t = octave_value::unknown_unary_op)\n    : tree_unary_expression (op_tok, e, t)\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_postfix_expression)\n\n  ~tree_postfix_expression () = default;\n\n  filepos beg_pos () const { return m_op->beg_pos (); }\n  filepos end_pos () const { return m_op_tok.end_pos (); }\n\n  comment_list leading_comments () const { return m_op->leading_comments (); }\n  comment_list trailing_comments () const { return m_op_tok.trailing_comments (); }\n\n  bool rvalue_ok () const { return true; }\n\n  tree_expression * dup (symbol_scope& scope) const;\n\n  octave_value evaluate (tree_evaluator&, int nargout = 1);\n\n  octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1)\n  {\n    return ovl (evaluate (tw, nargout));\n  }\n\n  void accept (tree_walker& tw)\n  {\n    tw.visit_postfix_expression (*this);\n  }\n\n  std::string profiler_name () const { return \"postfix \" + op_str (); }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt-walk.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"pt-all.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid tree_walker::visit_anon_fcn_handle (tree_anon_fcn_handle& afh)\n{\n  tree_parameter_list *parameter_list = afh.parameter_list ();\n\n  if (parameter_list)\n    parameter_list->accept (*this);\n\n  tree_expression *expression = afh.expression ();\n\n  if (expression)\n    expression->accept (*this);\n}\n\nvoid\ntree_walker::visit_argument_list (tree_argument_list& lst)\n{\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_expression *elt = *p++;\n\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_arguments_block (tree_arguments_block& blk)\n{\n  tree_args_block_attribute_list *attribute_list = blk.attribute_list ();\n\n  if (attribute_list)\n    attribute_list->accept (*this);\n\n  tree_args_block_validation_list *validation_list = blk.validation_list ();\n\n  if (validation_list)\n    validation_list->accept (*this);\n}\n\nvoid\ntree_walker::visit_args_block_attribute_list (tree_args_block_attribute_list& lst)\n{\n  tree_identifier *attribute = lst.attribute ();\n\n  if (attribute)\n    attribute->accept (*this);\n}\n\nvoid\ntree_walker::visit_args_block_validation_list (tree_args_block_validation_list& lst)\n{\n  for (auto *elt : lst)\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_arg_validation (tree_arg_validation& val)\n{\n  tree_expression *arg_name = val.identifier_expression ();\n\n  if (arg_name)\n    arg_name->accept (*this);\n\n  tree_arg_size_spec *size_spec = val.size_spec ();\n\n  if (size_spec)\n    size_spec->accept (*this);\n\n  tree_identifier *class_name = val.class_name ();\n\n  if (class_name)\n    class_name->accept (*this);\n\n  tree_arg_validation_fcns *validation_fcns = val.validation_fcns ();\n\n  if (validation_fcns)\n    validation_fcns->accept (*this);\n\n  tree_expression *default_value = val.initializer_expression ();\n\n  if (default_value)\n    default_value->accept (*this);\n}\n\nvoid\ntree_walker::visit_arg_size_spec (tree_arg_size_spec& spec)\n{\n  tree_argument_list *size_args = spec.size_args ();\n\n  if (size_args)\n    size_args->accept (*this);\n}\n\nvoid\ntree_walker::visit_arg_validation_fcns (tree_arg_validation_fcns& spec)\n{\n  tree_argument_list *fcn_args = spec.fcn_args ();\n\n  if (fcn_args)\n    fcn_args->accept (*this);\n}\n\nvoid\ntree_walker::visit_binary_expression (tree_binary_expression& expr)\n{\n  tree_expression *op1 = expr.lhs ();\n\n  if (op1)\n    op1->accept (*this);\n\n  tree_expression *op2 = expr.rhs ();\n\n  if (op2)\n    op2->accept (*this);\n}\n\nvoid\ntree_walker::visit_boolean_expression (tree_boolean_expression& expr)\n{\n  visit_binary_expression (expr);\n}\n\nvoid\ntree_walker::visit_compound_binary_expression (tree_compound_binary_expression& expr)\n{\n  visit_binary_expression (expr);\n}\n\nvoid\ntree_walker::visit_break_command (tree_break_command&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_colon_expression (tree_colon_expression& expr)\n{\n  tree_expression *op1 = expr.base ();\n\n  if (op1)\n    op1->accept (*this);\n\n  tree_expression *op3 = expr.increment ();\n\n  if (op3)\n    op3->accept (*this);\n\n  tree_expression *op2 = expr.limit ();\n\n  if (op2)\n    op2->accept (*this);\n}\n\nvoid\ntree_walker::visit_continue_command (tree_continue_command&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_decl_command (tree_decl_command& cmd)\n{\n  tree_decl_init_list *init_list = cmd.initializer_list ();\n\n  if (init_list)\n    init_list->accept (*this);\n}\n\nvoid\ntree_walker::visit_decl_elt (tree_decl_elt& cmd)\n{\n  tree_identifier *id = cmd.ident ();\n\n  if (id)\n    id->accept (*this);\n\n  tree_expression *expr = cmd.expression ();\n\n  if (expr)\n    expr->accept (*this);\n}\n\nvoid\ntree_walker::visit_decl_init_list (tree_decl_init_list& lst)\n{\n  // FIXME: tree_decl_elt is not derived from tree, so should it\n  // really have an accept method?\n\n  for (tree_decl_elt *elt : lst)\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_simple_for_command (tree_simple_for_command& cmd)\n{\n  tree_expression *lhs = cmd.left_hand_side ();\n\n  if (lhs)\n    lhs->accept (*this);\n\n  tree_expression *expr = cmd.control_expr ();\n\n  if (expr)\n    expr->accept (*this);\n\n  tree_expression *maxproc = cmd.maxproc_expr ();\n\n  if (maxproc)\n    maxproc->accept (*this);\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    list->accept (*this);\n}\n\nvoid\ntree_walker::visit_complex_for_command (tree_complex_for_command& cmd)\n{\n  tree_argument_list *lhs = cmd.left_hand_side ();\n\n  if (lhs)\n    lhs->accept (*this);\n\n  tree_expression *expr = cmd.control_expr ();\n\n  if (expr)\n    expr->accept (*this);\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    list->accept (*this);\n}\n\nvoid\ntree_walker::visit_spmd_command (tree_spmd_command& cmd)\n{\n  tree_statement_list *body = cmd.body ();\n\n  if (body)\n    body->accept (*this);\n}\n\nvoid\ntree_walker::visit_octave_user_script (octave_user_script& fcn)\n{\n  tree_statement_list *cmd_list = fcn.body ();\n\n  if (cmd_list)\n    cmd_list->accept (*this);\n}\n\nvoid\ntree_walker::visit_octave_user_function (octave_user_function& fcn)\n{\n  tree_statement_list *cmd_list = fcn.body ();\n\n  if (cmd_list)\n    cmd_list->accept (*this);\n}\n\nvoid\ntree_walker::visit_function_def (tree_function_def& fdef)\n{\n  octave_value fcn = fdef.function ();\n\n  octave_function *f = fcn.function_value ();\n\n  if (f)\n    f->accept (*this);\n}\n\nvoid\ntree_walker::visit_identifier (tree_identifier&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_if_clause (tree_if_clause& cmd)\n{\n  tree_expression *expr = cmd.condition ();\n\n  if (expr)\n    expr->accept (*this);\n\n  tree_statement_list *list = cmd.commands ();\n\n  if (list)\n    list->accept (*this);\n}\n\nvoid\ntree_walker::visit_if_command (tree_if_command& cmd)\n{\n  tree_if_command_list *list = cmd.cmd_list ();\n\n  if (list)\n    list->accept (*this);\n}\n\nvoid\ntree_walker::visit_if_command_list (tree_if_command_list& lst)\n{\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_if_clause *elt = *p++;\n\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_switch_case (tree_switch_case& cs)\n{\n  tree_expression *label = cs.case_label ();\n\n  if (label)\n    label->accept (*this);\n\n  tree_statement_list *list = cs.commands ();\n\n  if (list)\n    list->accept (*this);\n}\n\nvoid\ntree_walker::visit_switch_case_list (tree_switch_case_list& lst)\n{\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_switch_case *elt = *p++;\n\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_switch_command (tree_switch_command& cmd)\n{\n  tree_expression *expr = cmd.switch_value ();\n\n  if (expr)\n    expr->accept (*this);\n\n  tree_switch_case_list *list = cmd.case_list ();\n\n  if (list)\n    list->accept (*this);\n}\n\nvoid\ntree_walker::visit_index_expression (tree_index_expression& expr)\n{\n  tree_expression *e = expr.expression ();\n\n  if (e)\n    e->accept (*this);\n\n  std::list<tree_argument_list *> arg_lists = expr.arg_lists ();\n  std::list<string_vector> arg_names = expr.arg_names ();\n  std::list<tree_expression *> dyn_fields = expr.dyn_fields ();\n\n  auto p_arg_lists = arg_lists.begin ();\n  auto p_arg_names = arg_names.begin ();\n  auto p_dyn_fields = dyn_fields.begin ();\n\n  std::string type_tags = expr.type_tags ();\n  int n = type_tags.length ();\n\n  for (int i = 0; i < n; i++)\n    {\n      switch (type_tags[i])\n        {\n        case '(':\n        case '{':\n          {\n            tree_argument_list *l = *p_arg_lists;\n            if (l)\n              l->accept (*this);\n          }\n          break;\n\n        case '.':\n          {\n            std::string fn = (*p_arg_names)(0);\n            if (fn.empty ())\n              {\n                tree_expression *df = *p_dyn_fields;\n                if (df)\n                  df->accept (*this);\n              }\n          }\n          break;\n\n        default:\n          error (\"unexpected: index not '(', '{', or '.' in tree_walker::visit_index_expression - please report this bug\");\n        }\n\n      p_arg_lists++;\n      p_arg_names++;\n      p_dyn_fields++;\n    }\n}\n\nvoid\ntree_walker::visit_matrix (tree_matrix& lst)\n{\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_argument_list *elt = *p++;\n\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_cell (tree_cell& lst)\n{\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_argument_list *elt = *p++;\n\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_multi_assignment (tree_multi_assignment& expr)\n{\n  tree_argument_list *lhs = expr.left_hand_side ();\n\n  if (lhs)\n    lhs->accept (*this);\n\n  tree_expression *rhs = expr.right_hand_side ();\n\n  if (rhs)\n    rhs->accept (*this);\n}\n\nvoid\ntree_walker::visit_no_op_command (tree_no_op_command&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_constant (tree_constant&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_fcn_handle (tree_fcn_handle&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_parameter_list (tree_parameter_list& lst)\n{\n  auto p = lst.begin ();\n\n  while (p != lst.end ())\n    {\n      tree_decl_elt *elt = *p++;\n\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_postfix_expression (tree_postfix_expression& expr)\n{\n  tree_expression *e = expr.operand ();\n\n  if (e)\n    e->accept (*this);\n}\n\nvoid\ntree_walker::visit_prefix_expression (tree_prefix_expression& expr)\n{\n  tree_expression *e = expr.operand ();\n\n  if (e)\n    e->accept (*this);\n}\n\nvoid\ntree_walker::visit_return_command (tree_return_command&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_simple_assignment (tree_simple_assignment& expr)\n{\n  tree_expression *lhs = expr.left_hand_side ();\n\n  if (lhs)\n    lhs->accept (*this);\n\n  tree_expression *rhs = expr.right_hand_side ();\n\n  if (rhs)\n    rhs->accept (*this);\n}\n\nvoid\ntree_walker::visit_statement (tree_statement& stmt)\n{\n  tree_command *cmd = stmt.command ();\n\n  if (cmd)\n    cmd->accept (*this);\n  else\n    {\n      tree_expression *expr = stmt.expression ();\n\n      if (expr)\n        expr->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_statement_list (tree_statement_list& lst)\n{\n  for (tree_statement *elt : lst)\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_try_catch_command (tree_try_catch_command& cmd)\n{\n  tree_statement_list *try_code = cmd.body ();\n\n  if (try_code)\n    try_code->accept (*this);\n\n  tree_identifier *expr_id = cmd.identifier ();\n\n  if (expr_id)\n    expr_id->accept (*this);\n\n  tree_statement_list *catch_code = cmd.cleanup ();\n\n  if (catch_code)\n    catch_code->accept (*this);\n}\n\nvoid\ntree_walker::visit_unwind_protect_command (tree_unwind_protect_command& cmd)\n{\n  tree_statement_list *unwind_protect_code = cmd.body ();\n\n  if (unwind_protect_code)\n    unwind_protect_code->accept (*this);\n\n  tree_statement_list *cleanup_code = cmd.cleanup ();\n\n  if (cleanup_code)\n    cleanup_code->accept (*this);\n}\n\nvoid\ntree_walker::visit_while_command (tree_while_command& cmd)\n{\n  tree_expression *expr = cmd.condition ();\n\n  if (expr)\n    expr->accept (*this);\n\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    list->accept (*this);\n}\n\nvoid\ntree_walker::visit_do_until_command (tree_do_until_command& cmd)\n{\n  tree_statement_list *list = cmd.body ();\n\n  if (list)\n    list->accept (*this);\n\n  tree_expression *expr = cmd.condition ();\n\n  if (expr)\n    expr->accept (*this);\n}\n\nvoid\ntree_walker::visit_superclass_ref (tree_superclass_ref&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_metaclass_query (tree_metaclass_query&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_classdef_attribute (tree_classdef_attribute& attr)\n{\n  tree_identifier *id = attr.ident ();\n\n  if (id)\n    id->accept (*this);\n\n  tree_expression *expr = attr.expression ();\n\n  if (expr)\n    expr->accept (*this);\n}\n\nvoid\ntree_walker::visit_classdef_attribute_list (tree_classdef_attribute_list& lst)\n{\n  for (auto *elt : lst)\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_classdef_superclass (tree_classdef_superclass&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_classdef_superclass_list (tree_classdef_superclass_list& lst)\n{\n  for (auto *elt : lst)\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_classdef_property (tree_classdef_property&)\n{\n  // FIXME: Should we operate on the tree_arg_validation object or the\n  // identifier and expression parts separately?\n}\n\nvoid\ntree_walker::visit_classdef_property_list (tree_classdef_property_list& lst)\n{\n  for (auto *elt : lst)\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_classdef_properties_block (tree_classdef_properties_block& blk)\n{\n  tree_classdef_property_list *property_list = blk.property_list ();\n\n  if (property_list)\n    property_list->accept (*this);\n}\n\nvoid\ntree_walker::visit_classdef_method_list (tree_classdef_method_list& lst)\n{\n  for (auto ov_meth : lst)\n    {\n      octave_user_function *meth = ov_meth.user_function_value ();\n\n      if (meth)\n        meth->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_classdef_methods_block (tree_classdef_methods_block& blk)\n{\n  tree_classdef_method_list *method_list = blk.method_list ();\n\n  if (method_list)\n    method_list->accept (*this);\n}\n\nvoid\ntree_walker::visit_classdef_event (tree_classdef_event&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_classdef_event_list (tree_classdef_event_list& lst)\n{\n  for (auto *elt : lst)\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_classdef_events_block (tree_classdef_events_block& blk)\n{\n  tree_classdef_event_list *event_list = blk.event_list ();\n\n  if (event_list)\n    event_list->accept (*this);\n}\n\nvoid\ntree_walker::visit_classdef_enum (tree_classdef_enum&)\n{\n  // Nothing to do.\n}\n\nvoid\ntree_walker::visit_classdef_enum_list (tree_classdef_enum_list& lst)\n{\n  for (auto *elt : lst)\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_classdef_enum_block (tree_classdef_enum_block& blk)\n{\n  tree_classdef_enum_list *enum_list = blk.enum_list ();\n\n  if (enum_list)\n    enum_list->accept (*this);\n}\n\nvoid\ntree_walker::visit_classdef_body (tree_classdef_body& body)\n{\n  for (auto *elt : body.property_list ())\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n\n  for (auto *elt : body.method_list ())\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n\n\n  for (auto *elt : body.event_list ())\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n\n  for (auto *elt : body.enum_list ())\n    {\n      if (elt)\n        elt->accept (*this);\n    }\n}\n\nvoid\ntree_walker::visit_classdef (tree_classdef& cdef)\n{\n  tree_classdef_attribute_list *attribute_list = cdef.attribute_list ();\n\n  if (attribute_list)\n    attribute_list->accept (*this);\n\n  tree_identifier *ident = cdef.ident ();\n\n  if (ident)\n    ident->accept (*this);\n\n  tree_classdef_superclass_list *superclass_list = cdef.superclass_list ();\n\n  if (superclass_list)\n    superclass_list->accept (*this);\n\n  tree_classdef_body *body = cdef.body ();\n\n  if (body)\n    body->accept (*this);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt-walk.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_walk_h)\n#define octave_pt_walk_h 1\n\n#include \"octave-config.h\"\n\nclass octave_user_script;\nclass octave_user_function;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// No separate visitor needed\n// Base classes only, so no need to include them.\n//\n//  class tree_array_list\n//  class tree_unary_expression\n//  class tree_black_hole\n\nclass tree_anon_fcn_handle;\nclass tree_arg_size_spec;\nclass tree_arg_validation;\nclass tree_arg_validation_fcns;\nclass tree_args_block_attribute_list;\nclass tree_args_block_validation_list;\nclass tree_argument_list;\nclass tree_arguments_block;\nclass tree_binary_expression;\nclass tree_boolean_expression;\nclass tree_compound_binary_expression;\nclass tree_break_command;\nclass tree_colon_expression;\nclass tree_continue_command;\nclass tree_decl_command;\nclass tree_decl_init_list;\nclass tree_decl_elt;\nclass tree_simple_for_command;\nclass tree_complex_for_command;\nclass tree_spmd_command;\nclass tree_function_def;\nclass tree_identifier;\nclass tree_if_clause;\nclass tree_if_command;\nclass tree_if_command_list;\nclass tree_switch_case;\nclass tree_switch_case_list;\nclass tree_switch_command;\nclass tree_index_expression;\nclass tree_matrix;\nclass tree_cell;\nclass tree_multi_assignment;\nclass tree_no_op_command;\nclass tree_constant;\nclass tree_fcn_handle;\nclass tree_parameter_list;\nclass tree_postfix_expression;\nclass tree_prefix_expression;\nclass tree_return_command;\nclass tree_simple_assignment;\nclass tree_statement;\nclass tree_statement_list;\nclass tree_try_catch_command;\nclass tree_unwind_protect_command;\nclass tree_while_command;\nclass tree_do_until_command;\n\nclass tree_superclass_ref;\nclass tree_metaclass_query;\nclass tree_classdef_attribute;\nclass tree_classdef_attribute_list;\nclass tree_classdef_superclass;\nclass tree_classdef_superclass_list;\nclass tree_classdef_property;\nclass tree_classdef_property_list;\nclass tree_classdef_properties_block;\nclass tree_classdef_method_list;\nclass tree_classdef_methods_block;\nclass tree_classdef_event;\nclass tree_classdef_event_list;\nclass tree_classdef_events_block;\nclass tree_classdef_enum;\nclass tree_classdef_enum_list;\nclass tree_classdef_enum_block;\nclass tree_classdef_body;\nclass tree_classdef;\n\nclass OCTINTERP_API tree_walker\n{\nprotected:\n\n  tree_walker () { }\n\n  virtual ~tree_walker () = default;\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (tree_walker)\n\n  virtual void visit_anon_fcn_handle (tree_anon_fcn_handle&);\n\n  virtual void visit_argument_list (tree_argument_list&);\n\n  virtual void visit_arguments_block (tree_arguments_block&);\n\n  virtual void visit_args_block_attribute_list (tree_args_block_attribute_list&);\n\n  virtual void visit_args_block_validation_list (tree_args_block_validation_list&);\n\n  virtual void visit_arg_validation (tree_arg_validation&);\n\n  virtual void visit_arg_size_spec (tree_arg_size_spec&);\n\n  virtual void visit_arg_validation_fcns (tree_arg_validation_fcns&);\n\n  virtual void visit_binary_expression (tree_binary_expression&);\n\n  virtual void visit_boolean_expression (tree_boolean_expression&);\n\n  virtual void visit_compound_binary_expression (tree_compound_binary_expression&);\n\n  virtual void visit_break_command (tree_break_command&);\n\n  virtual void visit_colon_expression (tree_colon_expression&);\n\n  virtual void visit_continue_command (tree_continue_command&);\n\n  virtual void visit_decl_command (tree_decl_command&);\n\n  virtual void visit_decl_elt (tree_decl_elt&);\n\n  virtual void visit_decl_init_list (tree_decl_init_list&);\n\n  virtual void visit_simple_for_command (tree_simple_for_command&);\n\n  virtual void visit_complex_for_command (tree_complex_for_command&);\n\n  virtual void visit_spmd_command (tree_spmd_command&);\n\n  virtual void visit_octave_user_script (octave_user_script&);\n\n  virtual void visit_octave_user_function (octave_user_function&);\n\n  virtual void visit_function_def (tree_function_def&);\n\n  virtual void visit_identifier (tree_identifier&);\n\n  virtual void visit_if_clause (tree_if_clause&);\n\n  virtual void visit_if_command (tree_if_command&);\n\n  virtual void visit_if_command_list (tree_if_command_list&);\n\n  virtual void visit_switch_case (tree_switch_case&);\n\n  virtual void visit_switch_case_list (tree_switch_case_list&);\n\n  virtual void visit_switch_command (tree_switch_command&);\n\n  virtual void visit_index_expression (tree_index_expression&);\n\n  virtual void visit_matrix (tree_matrix&);\n\n  virtual void visit_cell (tree_cell&);\n\n  virtual void visit_multi_assignment (tree_multi_assignment&);\n\n  virtual void visit_no_op_command (tree_no_op_command&);\n\n  virtual void visit_constant (tree_constant&);\n\n  virtual void visit_fcn_handle (tree_fcn_handle&);\n\n  virtual void visit_parameter_list (tree_parameter_list&);\n\n  virtual void visit_postfix_expression (tree_postfix_expression&);\n\n  virtual void visit_prefix_expression (tree_prefix_expression&);\n\n  virtual void visit_return_command (tree_return_command&);\n\n  virtual void visit_simple_assignment (tree_simple_assignment&);\n\n  virtual void visit_statement (tree_statement&);\n\n  virtual void visit_statement_list (tree_statement_list&);\n\n  virtual void visit_try_catch_command (tree_try_catch_command&);\n\n  virtual void visit_unwind_protect_command (tree_unwind_protect_command&);\n\n  virtual void visit_while_command (tree_while_command&);\n\n  virtual void visit_do_until_command (tree_do_until_command&);\n\n  virtual void visit_superclass_ref (tree_superclass_ref&);\n\n  virtual void visit_metaclass_query (tree_metaclass_query&);\n\n  virtual void visit_classdef_attribute (tree_classdef_attribute&);\n\n  virtual void visit_classdef_attribute_list (tree_classdef_attribute_list&);\n\n  virtual void visit_classdef_superclass (tree_classdef_superclass&);\n\n  virtual void visit_classdef_superclass_list (tree_classdef_superclass_list&);\n\n  virtual void visit_classdef_property (tree_classdef_property&);\n\n  virtual void visit_classdef_property_list (tree_classdef_property_list&);\n\n  virtual void visit_classdef_properties_block (tree_classdef_properties_block&);\n\n  virtual void visit_classdef_method_list (tree_classdef_method_list&);\n\n  virtual void visit_classdef_methods_block (tree_classdef_methods_block&);\n\n  virtual void visit_classdef_event (tree_classdef_event&);\n\n  virtual void visit_classdef_event_list (tree_classdef_event_list&);\n\n  virtual void visit_classdef_events_block (tree_classdef_events_block&);\n\n  virtual void visit_classdef_enum (tree_classdef_enum&);\n\n  virtual void visit_classdef_enum_list (tree_classdef_enum_list&);\n\n  virtual void visit_classdef_enum_block (tree_classdef_enum_block&);\n\n  virtual void visit_classdef_body (tree_classdef_body&);\n\n  virtual void visit_classdef (tree_classdef&);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/pt.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n#include <string>\n\n#include \"comment-list.h\"\n#include \"filepos.h\"\n#include \"interpreter.h\"\n#include \"ov-fcn.h\"\n#include \"pt.h\"\n#include \"pt-eval.h\"\n#include \"pt-pr-code.h\"\n#include \"unwind-prot.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nint\ntree::line () const\n{\n  return beg_pos().line ();\n}\n\nint\ntree::column () const\n{\n  return beg_pos().column ();\n}\n\n// Hide the details of the string buffer so that we are less likely to\n// create a memory leak.\n\nstd::string\ntree::str_print_code ()\n{\n  std::ostringstream buf;\n\n  tree_print_code tpc (buf);\n\n  accept (tpc);\n\n  std::string retval = buf.str ();\n\n  return retval;\n}\n\n// Is the current breakpoint condition met?\n\nbool\ntree::meets_bp_condition (tree_evaluator& tw) const\n{\n  bool retval;\n  if (m_bp_cond == nullptr)\n    retval = false;\n  else if (m_bp_cond->empty ())     // empty condition always met\n    retval = true;\n  else\n    {\n      int parse_status = 0;\n\n      unwind_protect frame;\n\n      octave::interpreter_try (frame);\n\n      retval = true;                // default to stopping if any error\n      try\n        {\n          octave_value_list val\n            = tw.eval_string (*m_bp_cond, 1, parse_status, 1);\n\n          if (parse_status == 0)\n            {\n              if (! val(0).is_scalar_type ())\n                warning (\"Breakpoint condition must be a scalar, not size %s\",\n                         val(0).dims ().str ('x').c_str ());\n              else\n                retval = val(0).bool_value ();\n            }\n          else\n            warning (\"Error parsing breakpoint condition\");\n        }\n      catch (const execution_exception& ee)\n        {\n          interpreter& interp = tw.get_interpreter ();\n\n          interp.recover_from_exception ();\n\n          std::string tmp = ee.message ();\n\n          warning (\"Error evaluating breakpoint condition:\\n    %s\",\n                   tmp.c_str ());\n        }\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "libinterp/parse-tree/pt.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pt_h)\n#define octave_pt_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include <iosfwd>\n\nclass octave_function;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass comment_list;\nclass filepos;\nclass tree_evaluator;\nclass tree_walker;\n\n// Base class for the parse tree.\n\nclass OCTINTERP_API tree\n{\npublic:\n\n  tree () : m_bp_cond (nullptr) { }\n\n  OCTAVE_DISABLE_COPY_MOVE (tree)\n\n  virtual ~tree () = default;\n\n  virtual int line () const;\n  virtual int column () const;\n\n  virtual filepos beg_pos () const = 0;\n  virtual filepos end_pos () const = 0;\n\n  virtual comment_list leading_comments () const = 0;\n  virtual comment_list trailing_comments () const = 0;\n\n  virtual void set_breakpoint (const std::string& condition)\n  {\n    if (m_bp_cond)\n      *m_bp_cond = condition;\n    else\n      m_bp_cond = new std::string (condition);\n  }\n\n  virtual void delete_breakpoint ()\n  {\n    delete m_bp_cond;\n\n    m_bp_cond = nullptr;\n  }\n\n  bool meets_bp_condition (tree_evaluator& tw) const;\n\n  bool is_breakpoint () const\n  {\n    return m_bp_cond;\n  }\n\n  bool is_active_breakpoint (tree_evaluator& tw) const\n  {\n    return m_bp_cond && meets_bp_condition (tw);\n  }\n\n  // breakpoint condition, or \"0\" (i.e., \"false\") if no breakpoint.\n  // To distinguish \"0\" from a disabled breakpoint, test \"is_breakpoint\" too.\n  const std::string bp_cond () const\n  {\n    return m_bp_cond ? *m_bp_cond : \"0\";\n  }\n\n  std::string str_print_code ();\n\n  virtual void accept (tree_walker& tw) = 0;\n\nprivate:\n\n  // NULL if no breakpoint, or a breakpoint condition if there is one.\n  std::string *m_bp_cond;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/separator-list.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_separator_list_h)\n#define octave_separator_list_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n\n#include \"token.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API separator_list : public std::list<token>\n{\npublic:\n\n  separator_list (const token& tok)\n  {\n    append (tok);\n  }\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (separator_list)\n\n  separator_list *append (const token& tok)\n  {\n    push_back (tok);\n\n    return this;\n  }\n\n  int first_sep_char () const\n  {\n    token tok = front ();\n\n    return tok.token_id ();\n  }\n\n  separator_list * dup () const\n  {\n    return new separator_list (*this);\n  }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/parse-tree/token.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_token_h)\n#define octave_token_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n#include <variant>\n\n#include \"comment-list.h\"\n#include \"error.h\"\n#include \"filepos.h\"\n#include \"ov.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTINTERP_API token\n{\npublic:\n\n  enum token_type\n  {\n    invalid_token,\n    generic_token,\n    keyword_token,\n    string_token,\n    numeric_token,\n    ettype_token,\n    scls_name_token,\n  };\n\n  enum end_tok_type\n  {\n    simple_end,\n    arguments_end,\n    classdef_end,\n    enumeration_end,\n    events_end,\n    for_end,\n    function_end,\n    if_end,\n    methods_end,\n    parfor_end,\n    properties_end,\n    switch_end,\n    try_catch_end,\n    unwind_protect_end,\n    spmd_end,\n    while_end,\n  };\n\n  token ()\n    : m_type_tag (invalid_token)\n  { }\n\n  token (int id, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())\n    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_leading_comments (lst)\n  { }\n\n  token (int id, bool is_kw, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())\n    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (is_kw ? keyword_token : generic_token), m_leading_comments (lst)\n  { }\n\n  token (int id, const char *s, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())\n    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (string_token), m_tok_info (s), m_leading_comments (lst)\n  { }\n\n  token (int id, const std::string& s, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())\n    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (string_token), m_tok_info (s), m_leading_comments (lst)\n  { }\n\n  token (int id, const octave_value& val, const std::string& s, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())\n    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (numeric_token), m_tok_info (val), m_orig_text (s), m_leading_comments (lst)\n  { }\n\n  token (int id, end_tok_type t, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())\n    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (ettype_token), m_tok_info (t), m_leading_comments (lst)\n  { }\n\n  token (int id, const std::string& meth, const std::string& cls, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())\n    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (scls_name_token), m_tok_info (meth, cls), m_leading_comments (lst)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (token)\n\n  void mark_may_be_command () { m_maybe_cmd = true; }\n  bool may_be_command () const { return m_maybe_cmd; }\n\n  void mark_trailing_space () { m_tspc = true; }\n  bool space_follows_token () const { return m_tspc; }\n\n  operator bool () const { return m_type_tag != invalid_token; }\n\n  int token_id () const { return m_tok_id; }\n\n  bool token_is (int id) const { return m_tok_id == id; }\n  bool token_is (const token *tok) const\n  {\n    return tok ? token_is (tok->token_id ()) : false;\n  }\n\n  filepos beg_pos () const { return m_beg_pos; }\n  filepos end_pos () const { return m_end_pos; }\n\n  void beg_pos (const filepos& pos) { m_beg_pos = pos; }\n  void end_pos (const filepos& pos) { m_end_pos = pos; }\n\n  comment_list leading_comments () const { return m_leading_comments; }\n  comment_list trailing_comments () const { return m_trailing_comments; }\n\n  void leading_comments (const comment_list& lst) { m_leading_comments = lst; }\n  void trailing_comments (const comment_list& lst) { m_trailing_comments = lst; }\n\n  // These will probably be removed.\n  int line () const { return m_beg_pos.line (); }\n  int column () const { return m_beg_pos.column (); }\n\n  bool iskeyword () const\n  {\n    return m_type_tag == keyword_token || m_type_tag == ettype_token;\n  }\n\n  bool isstring () const { return m_type_tag == string_token; }\n\n  std::string text () const { return m_tok_info.text (); }\n  octave_value number () const { return m_tok_info.number (); }\n  token_type ttype () const { return m_type_tag; }\n  end_tok_type ettype () const { return m_tok_info.ettype (); }\n\n  std::string superclass_method_name () const { return m_tok_info.superclass_method_name (); }\n  std::string superclass_class_name () const { return m_tok_info.superclass_class_name (); }\n\n  std::string text_rep () const { return m_orig_text; }\n\nprivate:\n\n  class superclass_info\n  {\n  public:\n\n    superclass_info (const std::string& meth, const std::string& cls)\n      : m_method_name (meth), m_class_name (cls)\n    { }\n\n    OCTAVE_DEFAULT_COPY_MOVE_DELETE (superclass_info)\n\n    std::string method_name () const { return m_method_name; }\n\n    std::string class_name () const { return m_class_name; }\n\n  private:\n\n    //--------\n\n    // The name of the method to call.  This is the text before the\n    // \"@\" and may be of the form \"object.method\".\n    std::string m_method_name;\n\n    // The name of the superclass.  This is the text after the \"@\"\n    // and may be of the form \"object.method\".\n    std::string m_class_name;\n  };\n\n  class tok_info\n  {\n  public:\n\n    tok_info (const char *s) : m_value (std::string (s)) { }\n\n    tok_info (const std::string& str) : m_value (str) { }\n\n    tok_info (const octave_value& num) : m_value (octave_value (num)) { }\n\n    tok_info (end_tok_type et) : m_value (et) { }\n\n    tok_info (const std::string& meth, const std::string& cls) : m_value (superclass_info (meth, cls)) { }\n\n    OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (tok_info)\n\n    std::string text () const\n    {\n      panic_unless (std::holds_alternative<std::string> (m_value));\n      return std::get<std::string> (m_value);\n    }\n\n    octave_value number () const\n    {\n      panic_unless (std::holds_alternative<octave_value> (m_value));\n      return std::get<octave_value> (m_value);\n    }\n\n    token::end_tok_type ettype () const\n    {\n      panic_unless (std::holds_alternative<end_tok_type> (m_value));\n      return std::get<end_tok_type> (m_value);\n    }\n\n    std::string\n    superclass_method_name () const\n    {\n      panic_unless (std::holds_alternative<superclass_info> (m_value));\n      return std::get<superclass_info> (m_value).method_name ();\n    }\n\n    std::string\n    superclass_class_name () const\n    {\n      panic_unless (std::holds_alternative<superclass_info> (m_value));\n      return std::get<superclass_info> (m_value).class_name ();\n    }\n\n  private:\n\n    std::variant<std::string, octave_value, end_tok_type, superclass_info> m_value;\n  };\n\n  //--------\n\n  bool m_maybe_cmd {false};\n\n  bool m_tspc {false};\n\n  filepos m_beg_pos;\n  filepos m_end_pos;\n\n  int m_tok_id {-1};\n\n  token_type m_type_tag {generic_token};\n\n  tok_info m_tok_info;\n\n  std::string m_orig_text;\n\n  // Comments that appear prior to the token.\n  comment_list m_leading_comments;\n\n  // Comments that appear after the token.  This list is only used to\n  // hold comments that appear after the last token in a file.\n  comment_list m_trailing_comments;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "libinterp/template-inst/Array-tc.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Instantiate Arrays of octave_values.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#define OCTINTERP_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.cc\"\n\n#include \"ov.h\"\n#include \"cdef-class.h\"\n#include \"cdef-object.h\"\n\n#include \"oct-sort.cc\"\n\nNO_INSTANTIATE_ARRAY_SORT_API (octave_value, OCTINTERP_API);\nINSTANTIATE_ARRAY (octave_value, );\n\nNO_INSTANTIATE_ARRAY_SORT_API (octave_value *, OCTINTERP_API);\nINSTANTIATE_ARRAY (octave_value *, );\n\nNO_INSTANTIATE_ARRAY_SORT_API (octave::cdef_object, OCTINTERP_API);\nINSTANTIATE_ARRAY (octave::cdef_object, );\n"
  },
  {
    "path": "libinterp/template-inst/Array.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2022-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n\n// Include this file when instantiating the Array class with new types in\n// projects linking to \"liboctinterp\".\n\n#include \"Array-oct.cc\"\n\n#include \"ov.h\"\n#include \"cdef-fwd.h\"\n\n#if ! defined (OCTINTERP_EXTERN_TEMPLATE_ARRAY)\n// guard against double extern template declarations\n#define OCTINTERP_EXTERN_TEMPLATE_ARRAY\n\n// \"Protect\" Array<T> instantiations that are exported by liboctinterp from\n// being implicitly instantiated in compilation units including this file.\n\n// instantiated in Array-tc.cc\nextern template class OCTINTERP_API Array<octave_value>;\nextern template class OCTINTERP_API Array<octave_value *>;\nextern template class OCTINTERP_API Array<octave::cdef_object>;\n\n#endif  // OCTINTERP_EXTERN_TEMPLATE_ARRAY\n"
  },
  {
    "path": "libinterp/template-inst/Array.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n\n// Include this file when instantiating the Array<T> template class with new\n// types in new types while linking to \"liboctinterp\".\n\n#if ! defined (octave_Array_h)\n#define octave_Array_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-oct.h\"\n\n// FIXME: Including \"Array-oct.h\" includes \"Array-base.h\" which will have\n// implicitly instantiated Array<octave_idx_type>.  Could that be an issue?\n\n#if ! defined (OCTINTERP_EXTERN_TEMPLATE_ARRAY)\n// guard against double extern template declarations\n#define OCTINTERP_EXTERN_TEMPLATE_ARRAY\n\n\nclass OCTINTERP_API octave_value;\n#include \"cdef-fwd.h\"\n\n// \"Protect\" Array<T> instantiations that are exported by liboctinterp from\n// being implicitly instantiated in compilation units including this file.\n\n// instantiated in Array-tc.cc\nextern template class OCTINTERP_API Array<octave_value>;\nextern template class OCTINTERP_API Array<octave_value *>;\nextern template class OCTINTERP_API Array<octave::cdef_object>;\n\n#endif  // OCTINTERP_EXTERN_TEMPLATE_ARRAY\n\n#endif\n"
  },
  {
    "path": "libinterp/template-inst/module.mk",
    "content": "TEMPLATE_INST_SRC = \\\n  %reldir%/Array-tc.cc\n\nTEMPLATE_INST_INC = \\\n  %reldir%/Array.cc \\\n  %reldir%/Array.h\n"
  },
  {
    "path": "libinterp/usage.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_usage_h)\n#define octave_usage_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include <iosfwd>\n\n#include \"version.h\"\n\n// Usage message for terse output.\nstatic const char *usage_string =\n  \"octave [-GHVWefghiqvx] [--echo-commands] [--eval CODE]\\n\\\n       [--experimental-terminal-widget] [--gui] [--help] [--interactive]\\n\\\n       [--line-editing] [--no-gui] [--no-history] [--no-init-all]\\n\\\n       [--no-init-path] [--no-init-site] [--no-init-user]\\n\\\n       [--no-line-editing] [--no-startup-tests] [--no-window-system]\\n\\\n       [--path path] [--persist] [--quiet] [--server] [--traditional]\\n\\\n       [--version] [file]\";\n\n// Usage message for --help argument.\nstatic void\noctave_print_verbose_usage_and_exit ()\n{\n  std::cout << octave_name_version_copyright_license_copying_warranty () << \"\\n\\\n\\n\\\nUsage: octave [options] [FILE]\\n\\\n\\n\\\nOptions:\\n\\\n\\n\"\n// FIXME: Disabled debug option for parser 2023-12-29.\n// Uncomment and restore code if Octave adds capability to\n// immediately enter debug mode for a script.\n//--debug, -d             Enter debugging mode.\\n\\ //\n\"\\\n  --echo-commands, -x     Echo commands as they are executed.\\n\\\n  --eval, -e CODE         Evaluate CODE.  Exit when done unless --persist.\\n\\\n  --experimental-terminal-widget\\n\\\n                          Use new experimental terminal widget in the GUI.\\n\\\n  --gui, -g               Start the graphical user interface.\\n\\\n  --help, -h,             Print short help message and exit.\\n\\\n  --interactive, -i       Force interactive behavior.\\n\\\n  --line-editing          Force readline use for command-line editing.\\n\\\n  --no-gui, -G            Disable the graphical user interface.\\n\\\n  --no-history, -H        Don't save commands to the history list\\n\\\n  --no-init-all, --norc, -f\\n\\\n                          Don't read any initialization files.\\n\\\n  --no-init-path          Don't initialize function search path.\\n\\\n  --no-init-site          Don't read the site-wide octaverc files.\\n\\\n  --no-init-user          Don't read the ~/.octaverc or .octaverc files.\\n\\\n  --no-line-editing       Don't use readline for command-line editing.\\n\\\n  --no-startup-tests      Don't run compatibility tests on startup.\\n\\\n  --no-window-system, -W  Disable window system, including graphics.\\n\\\n  --path PATH, -p PATH    Add PATH to head of function search path.\\n\\\n  --persist               Go interactive after --eval or reading from FILE.\\n\\\n  --server                Enter server mode at startup.\\n\\\n  --quiet, --silent, -q   Don't print message at startup.\\n\\\n  --traditional           Set variables for closer MATLAB compatibility.\\n\\\n  --version, -v           Print version information and exit.\\n\\\n\\n\\\n  FILE                    Execute commands from FILE.  Exit when done\\n\\\n                          unless --persist is also specified.\\n\\\n\\n\"\n            << octave_www_statement () << \"\\n\"\n            << octave_bugs_statement () << \"\\n\"\n            << octave_contrib_statement () << \"\\n\";\n\n  std::exit (EXIT_SUCCESS);\n}\n\n// Terse usage message when argument is not recognized.\nstatic void\noctave_print_terse_usage_and_exit ()\n{\n  std::cerr << \"\\nusage: \" << usage_string << \"\\n\\n\";\n\n  std::exit (EXIT_FAILURE);\n}\n\n// Version message for --version argument.\nstatic void\noctave_print_version_and_exit ()\n{\n  std::cout << octave_name_version_copyright_license_copying_warranty_bugs ()\n            << \"\\n\";\n  std::exit (EXIT_SUCCESS);\n}\n\n#endif\n"
  },
  {
    "path": "libmex/liboctmex-build-info.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_liboctmex_build_info_h)\n#define octave_liboctmex_build_info_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nextern OCTMEX_API std::string liboctmex_hg_id ();\n\n#endif\n"
  },
  {
    "path": "libmex/liboctmex-build-info.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"liboctmex-build-info.h\"\n\nstd::string\nliboctmex_hg_id ()\n{\n  return \"%OCTAVE_HG_ID%\";\n}\n"
  },
  {
    "path": "libmex/mex.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// #define OCTAVE_MEX_DEBUG 1\n\n#if defined (OCTAVE_MEX_DEBUG)\n#  include <iostream>\n#endif\n\n#include <cstdarg>\n#include <cstdlib>\n#include <cstring>\n// #include <cctype>\n\n#include <limits>\n#include <map>\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n#  include <memory_resource>\n#endif\n#include <set>\n#include <string>\n\n#include \"f77-fcn.h\"\n#include \"oct-locbuf.h\"\n#include \"quit.h\"\n\n#include \"Cell.h\"\n#include \"error.h\"\n#include \"interpreter-private.h\"\n#include \"interpreter.h\"\n// mxArray must be declared as a class before including mexproto.h.\n#include \"mxarray.h\"\n#include \"mexproto.h\"\n#include \"oct-map.h\"\n#include \"ovl.h\"\n#include \"ov.h\"\n#include \"ov-classdef.h\"\n#include \"ov-mex-fcn.h\"\n#include \"ov-usr-fcn.h\"\n#include \"pager.h\"\n#include \"unwind-prot.h\"\n#include \"utils.h\"\n#include \"variables.h\"\n#include \"graphics.h\"\n\n// These must be declared extern \"C\" but may be omitted from the set of\n// symbols declared in mexproto.h, so we declare them here as well.\n\nextern \"C\"\n{\n  extern OCTMEX_API const mxArray *\n  mexGet_interleaved (double handle, const char *property);\n\n  extern OCTMEX_API mxArray *\n  mxCreateCellArray (mwSize ndims, const mwSize *dims);\n\n  extern OCTMEX_API mxArray *\n  mxCreateCellMatrix (mwSize m, mwSize n);\n\n  extern OCTMEX_API mxArray *\n  mxCreateCharArray (mwSize ndims, const mwSize *dims);\n\n  extern OCTMEX_API mxArray *\n  mxCreateCharMatrixFromStrings (mwSize m, const char **str);\n\n  extern OCTMEX_API mxArray *\n  mxCreateDoubleMatrix (mwSize nr, mwSize nc, mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateDoubleScalar (double val);\n\n  extern OCTMEX_API mxArray *\n  mxCreateLogicalArray (mwSize ndims, const mwSize *dims);\n\n  extern OCTMEX_API mxArray *\n  mxCreateLogicalMatrix (mwSize m, mwSize n);\n\n  extern OCTMEX_API mxArray *\n  mxCreateLogicalScalar (mxLogical val);\n\n  extern OCTMEX_API mxArray *\n  mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id,\n                        mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id,\n                         mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateUninitNumericArray (mwSize ndims, const mwSize *dims,\n                              mxClassID class_id, mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateUninitNumericMatrix (mwSize m, mwSize n, mxClassID class_id,\n                               mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax);\n\n  extern OCTMEX_API mxArray *\n  mxCreateString (const char *str);\n\n  extern OCTMEX_API mxArray *\n  mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys,\n                       const char **keys);\n\n  extern OCTMEX_API mxArray *\n  mxCreateStructMatrix (mwSize rows, mwSize cols, int num_keys,\n                        const char **keys);\n\n  extern OCTMEX_API mxArray *\n  mxCreateCellArray_interleaved (mwSize ndims, const mwSize *dims);\n\n  extern OCTMEX_API mxArray *\n  mxCreateCellMatrix_interleaved (mwSize m, mwSize n);\n\n  extern OCTMEX_API mxArray *\n  mxCreateCharArray_interleaved (mwSize ndims, const mwSize *dims);\n\n  extern OCTMEX_API mxArray *\n  mxCreateCharMatrixFromStrings_interleaved (mwSize m, const char **str);\n\n  extern OCTMEX_API mxArray *\n  mxCreateDoubleMatrix_interleaved (mwSize nr, mwSize nc, mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateDoubleScalar_interleaved (double val);\n\n  extern OCTMEX_API mxArray *\n  mxCreateLogicalArray_interleaved (mwSize ndims, const mwSize *dims);\n\n  extern OCTMEX_API mxArray *\n  mxCreateLogicalMatrix_interleaved (mwSize m, mwSize n);\n\n  extern OCTMEX_API mxArray *\n  mxCreateLogicalScalar_interleaved (mxLogical val);\n\n  extern OCTMEX_API mxArray *\n  mxCreateNumericArray_interleaved (mwSize ndims, const mwSize *dims,\n                                    mxClassID class_id, mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateNumericMatrix_interleaved (mwSize m, mwSize n, mxClassID class_id,\n                                     mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateUninitNumericArray_interleaved (mwSize ndims, const mwSize *dims,\n                                          mxClassID class_id,\n                                          mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateUninitNumericMatrix_interleaved (mwSize m, mwSize n,\n                                           mxClassID class_id,\n                                           mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateSparse_interleaved (mwSize m, mwSize n, mwSize nzmax,\n                              mxComplexity flag);\n\n  extern OCTMEX_API mxArray *\n  mxCreateSparseLogicalMatrix_interleaved (mwSize m, mwSize n, mwSize nzmax);\n\n  extern OCTMEX_API mxArray *\n  mxCreateString_interleaved (const char *str);\n\n  extern OCTMEX_API mxArray *\n  mxCreateStructArray_interleaved (mwSize ndims, const mwSize *dims,\n                                   int num_keys, const char **keys);\n\n  extern OCTMEX_API mxArray *\n  mxCreateStructMatrix_interleaved (mwSize rows, mwSize cols, int num_keys,\n                                    const char **keys);\n\n  extern OCTMEX_API int mxMakeArrayReal (mxArray *ptr);\n  extern OCTMEX_API int mxMakeArrayComplex (mxArray *ptr);\n\n  extern OCTMEX_API mxDouble * mxGetDoubles (const mxArray *p);\n  extern OCTMEX_API mxSingle * mxGetSingles (const mxArray *p);\n  extern OCTMEX_API mxInt8 * mxGetInt8s (const mxArray *p);\n  extern OCTMEX_API mxInt16 * mxGetInt16s (const mxArray *p);\n  extern OCTMEX_API mxInt32 * mxGetInt32s (const mxArray *p);\n  extern OCTMEX_API mxInt64 * mxGetInt64s (const mxArray *p);\n  extern OCTMEX_API mxUint8 * mxGetUint8s (const mxArray *p);\n  extern OCTMEX_API mxUint16 * mxGetUint16s (const mxArray *p);\n  extern OCTMEX_API mxUint32 * mxGetUint32s (const mxArray *p);\n  extern OCTMEX_API mxUint64 * mxGetUint64s (const mxArray *p);\n\n  extern OCTMEX_API mxComplexDouble * mxGetComplexDoubles (const mxArray *p);\n  extern OCTMEX_API mxComplexSingle * mxGetComplexSingles (const mxArray *p);\n\n  extern OCTMEX_API double * mxGetPi (const mxArray *ptr);\n  extern OCTMEX_API void * mxGetImagData (const mxArray *ptr);\n\n  extern OCTMEX_API int mxSetDoubles (mxArray *p, mxDouble *d);\n  extern OCTMEX_API int mxSetSingles (mxArray *p, mxSingle *d);\n  extern OCTMEX_API int mxSetInt8s (mxArray *p, mxInt8 *d);\n  extern OCTMEX_API int mxSetInt16s (mxArray *p, mxInt16 *d);\n  extern OCTMEX_API int mxSetInt32s (mxArray *p, mxInt32 *d);\n  extern OCTMEX_API int mxSetInt64s (mxArray *p, mxInt64 *d);\n  extern OCTMEX_API int mxSetUint8s (mxArray *p, mxUint8 *d);\n  extern OCTMEX_API int mxSetUint16s (mxArray *p, mxUint16 *d);\n  extern OCTMEX_API int mxSetUint32s (mxArray *p, mxUint32 *d);\n  extern OCTMEX_API int mxSetUint64s (mxArray *p, mxUint64 *d);\n\n  extern OCTMEX_API int mxSetComplexDoubles (mxArray *p, mxComplexDouble *d);\n  extern OCTMEX_API int mxSetComplexSingles (mxArray *p, mxComplexSingle *d);\n\n  extern OCTMEX_API void mxSetPi (mxArray *ptr, double *pi);\n  extern OCTMEX_API void mxSetImagData (mxArray *ptr, void *pi);\n}\n\nstatic void *\nxmalloc (size_t n)\n{\n  void *ptr = std::malloc (n);\n\n#if defined (OCTAVE_MEX_DEBUG)\n  std::cerr << \"xmalloc (\" << n << \") = \" << ptr << std::endl;\n#endif\n\n  return ptr;\n}\n\nstatic void *\nxrealloc (void *ptr, size_t n)\n{\n  void *newptr = std::realloc (ptr, n);\n\n#if defined (OCTAVE_MEX_DEBUG)\n  std::cerr << \"xrealloc (\" << ptr << \", \" << n << \") = \" << newptr << std::endl;\n#endif\n\n  return newptr;\n}\n\nstatic void\nxfree (void *ptr)\n{\n#if defined (OCTAVE_MEX_DEBUG)\n  std::cerr << \"xfree (\" << ptr << \")\" << std::endl;\n#endif\n\n  std::free (ptr);\n}\n\n// FIXME: Is there a better/standard way to do this job?\n\ntemplate <typename T>\nclass fp_type_traits\n{\npublic:\n  static const bool is_complex = false;\n};\n\ntemplate <>\nclass fp_type_traits<Complex>\n{\npublic:\n  static const bool is_complex = true;\n};\n\ntemplate <>\nclass fp_type_traits<FloatComplex>\n{\npublic:\n  static const bool is_complex = true;\n};\n\nextern OCTINTERP_API mex *mex_context;\n\ntemplate <typename T>\nstatic inline T *\nmaybe_unmark (T *ptr)\n{\n  if (mex_context)\n    mex_context->unmark (ptr);\n\n  return ptr;\n}\n\nstatic inline mxArray *\nmaybe_unmark_array (mxArray *ptr)\n{\n  if (mex_context)\n    mex_context->unmark_array (ptr);\n\n  return ptr;\n}\n\n// ------------------------------------------------------------------\n\n// C interface to mxArray objects:\n\n// Floating point predicates.\n\nbool\nmxIsFinite (const double v)\n{\n  return octave::math::isfinite (v) != 0;\n}\n\nbool\nmxIsInf (const double v)\n{\n  return octave::math::isinf (v) != 0;\n}\n\nbool\nmxIsNaN (const double v)\n{\n  return octave::math::isnan (v) != 0;\n}\n\ndouble\nmxGetEps ()\n{\n  return std::numeric_limits<double>::epsilon ();\n}\n\ndouble\nmxGetInf ()\n{\n  return lo_ieee_inf_value ();\n}\n\ndouble\nmxGetNaN ()\n{\n  return lo_ieee_nan_value ();\n}\n\n// Memory management.\nvoid *\nmxCalloc (std::size_t n, std::size_t size)\n{\n  return mex_context ? mex_context->calloc (n, size) : ::calloc (n, size);\n}\n\nvoid *\nmxMalloc (std::size_t n)\n{\n  return mex_context ? mex_context->malloc (n) : xmalloc (n);\n}\n\nvoid *\nmxRealloc (void *ptr, std::size_t size)\n{\n  return (mex_context\n          ? mex_context->realloc (ptr, size) : xrealloc (ptr, size));\n}\n\nvoid\nmxFree (void *ptr)\n{\n  if (mex_context)\n    mex_context->free (ptr);\n  else\n    xfree (ptr);\n}\n\nstatic inline mxArray *\nmaybe_mark_array (mxArray *ptr)\n{\n  return mex_context ? mex_context->mark_array (ptr) : ptr;\n}\n\n// Constructors.\nmxArray *\nmxCreateCellArray_interleaved (mwSize ndims, const mwSize *dims)\n{\n  return maybe_mark_array (new mxArray (true, ndims, dims));\n}\n\nmxArray *\nmxCreateCellArray (mwSize ndims, const mwSize *dims)\n{\n  return maybe_mark_array (new mxArray (false, ndims, dims));\n}\n\nmxArray *\nmxCreateCellMatrix_interleaved (mwSize m, mwSize n)\n{\n  return maybe_mark_array (new mxArray (true, m, n));\n}\n\nmxArray *\nmxCreateCellMatrix (mwSize m, mwSize n)\n{\n  return maybe_mark_array (new mxArray (false, m, n));\n}\n\nmxArray *\nmxCreateCharArray_interleaved (mwSize ndims, const mwSize *dims)\n{\n  return maybe_mark_array (new mxArray (true, mxCHAR_CLASS, ndims, dims));\n}\n\nmxArray *\nmxCreateCharArray (mwSize ndims, const mwSize *dims)\n{\n  return maybe_mark_array (new mxArray (false, mxCHAR_CLASS, ndims, dims));\n}\n\nmxArray *\nmxCreateCharMatrixFromStrings_interleaved (mwSize m, const char **str)\n{\n  return maybe_mark_array (new mxArray (true, m, str));\n}\n\nmxArray *\nmxCreateCharMatrixFromStrings (mwSize m, const char **str)\n{\n  return maybe_mark_array (new mxArray (false, m, str));\n}\n\nmxArray *\nmxCreateDoubleMatrix_interleaved (mwSize m, mwSize n, mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (true, mxDOUBLE_CLASS, m, n, flag));\n}\n\nmxArray *\nmxCreateDoubleMatrix (mwSize m, mwSize n, mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (false, mxDOUBLE_CLASS, m, n, flag));\n}\n\nmxArray *\nmxCreateDoubleScalar_interleaved (double val)\n{\n  return maybe_mark_array (new mxArray (true, mxDOUBLE_CLASS, val));\n}\n\nmxArray *\nmxCreateDoubleScalar (double val)\n{\n  return maybe_mark_array (new mxArray (false, mxDOUBLE_CLASS, val));\n}\n\nmxArray *\nmxCreateLogicalArray_interleaved (mwSize ndims, const mwSize *dims)\n{\n  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, ndims, dims));\n}\n\nmxArray *\nmxCreateLogicalArray (mwSize ndims, const mwSize *dims)\n{\n  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, ndims, dims));\n}\n\nmxArray *\nmxCreateLogicalMatrix_interleaved (mwSize m, mwSize n)\n{\n  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, m, n));\n}\n\nmxArray *\nmxCreateLogicalMatrix (mwSize m, mwSize n)\n{\n  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, m, n));\n}\n\nmxArray *\nmxCreateLogicalScalar_interleaved (mxLogical val)\n{\n  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, val));\n}\n\nmxArray *\nmxCreateLogicalScalar (mxLogical val)\n{\n  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, val));\n}\n\nmxArray *\nmxCreateNumericArray_interleaved (mwSize ndims, const mwSize *dims,\n                                  mxClassID class_id, mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (true, class_id, ndims, dims, flag));\n}\n\nmxArray *\nmxCreateNumericArray (mwSize ndims, const mwSize *dims,\n                      mxClassID class_id, mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (false, class_id, ndims, dims, flag));\n}\n\nmxArray *\nmxCreateNumericMatrix_interleaved (mwSize m, mwSize n, mxClassID class_id,\n                                   mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (true, class_id, m, n, flag));\n}\n\nmxArray *\nmxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id,\n                       mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (false, class_id, m, n, flag));\n}\n\nmxArray *\nmxCreateUninitNumericArray_interleaved (mwSize ndims, const mwSize *dims,\n                                        mxClassID class_id, mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (true, class_id, ndims, dims, flag,\n                                        false));\n}\n\nmxArray *\nmxCreateUninitNumericArray (mwSize ndims, const mwSize *dims,\n                            mxClassID class_id, mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (false, class_id, ndims, dims, flag,\n                                        false));\n}\n\nmxArray *\nmxCreateUninitNumericMatrix_interleaved (mwSize m, mwSize n,\n    mxClassID class_id, mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (true, class_id, m, n, flag, false));\n}\n\nmxArray *\nmxCreateUninitNumericMatrix (mwSize m, mwSize n, mxClassID class_id,\n                             mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (false, class_id, m, n, flag, false));\n}\n\nmxArray *\nmxCreateSparse_interleaved (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (true, mxDOUBLE_CLASS, m, n, nzmax,\n                                        flag));\n}\n\nmxArray *\nmxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)\n{\n  return maybe_mark_array (new mxArray (false, mxDOUBLE_CLASS, m, n, nzmax,\n                                        flag));\n}\n\nmxArray *\nmxCreateSparseLogicalMatrix_interleaved (mwSize m, mwSize n, mwSize nzmax)\n{\n  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, m, n, nzmax));\n}\n\nmxArray *\nmxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax)\n{\n  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, m, n, nzmax));\n}\n\nmxArray *\nmxCreateString_interleaved (const char *str)\n{\n  return maybe_mark_array (new mxArray (true, str));\n}\n\nmxArray *\nmxCreateString (const char *str)\n{\n  return maybe_mark_array (new mxArray (false, str));\n}\n\nmxArray *\nmxCreateStructArray_interleaved (mwSize ndims, const mwSize *dims,\n                                 int num_keys, const char **keys)\n{\n  return maybe_mark_array (new mxArray (true, ndims, dims, num_keys, keys));\n}\n\nmxArray *\nmxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys,\n                     const char **keys)\n{\n  return maybe_mark_array (new mxArray (false, ndims, dims, num_keys, keys));\n}\n\nmxArray *\nmxCreateStructMatrix_interleaved (mwSize m, mwSize n, int num_keys,\n                                  const char **keys)\n{\n  return maybe_mark_array (new mxArray (true, m, n, num_keys, keys));\n}\n\nmxArray *\nmxCreateStructMatrix (mwSize m, mwSize n, int num_keys,\n                      const char **keys)\n{\n  return maybe_mark_array (new mxArray (false, m, n, num_keys, keys));\n}\n\n// Copy constructor.\nmxArray *\nmxDuplicateArray (const mxArray *ptr)\n{\n  return maybe_mark_array (ptr->dup ());\n}\n\n// Destructor.\nvoid\nmxDestroyArray (mxArray *ptr)\n{\n  if (! (mex_context && mex_context->free_value (ptr)))\n    delete ptr;\n}\n\n// Type Predicates.\nbool\nmxIsCell (const mxArray *ptr)\n{\n  return ptr->iscell ();\n}\n\nbool\nmxIsChar (const mxArray *ptr)\n{\n  return ptr->is_char ();\n}\n\nbool\nmxIsClass (const mxArray *ptr, const char *name)\n{\n  return ptr->is_class (name);\n}\n\nbool\nmxIsComplex (const mxArray *ptr)\n{\n  return ptr->is_complex ();\n}\n\nbool\nmxIsDouble (const mxArray *ptr)\n{\n  return ptr->is_double ();\n}\n\nbool\nmxIsFunctionHandle (const mxArray *ptr)\n{\n  return ptr->is_function_handle ();\n}\n\nbool\nmxIsInt16 (const mxArray *ptr)\n{\n  return ptr->is_int16 ();\n}\n\nbool\nmxIsInt32 (const mxArray *ptr)\n{\n  return ptr->is_int32 ();\n}\n\nbool\nmxIsInt64 (const mxArray *ptr)\n{\n  return ptr->is_int64 ();\n}\n\nbool\nmxIsInt8 (const mxArray *ptr)\n{\n  return ptr->is_int8 ();\n}\n\nbool\nmxIsLogical (const mxArray *ptr)\n{\n  return ptr->is_logical ();\n}\n\nbool\nmxIsNumeric (const mxArray *ptr)\n{\n  return ptr->is_numeric ();\n}\n\nbool\nmxIsSingle (const mxArray *ptr)\n{\n  return ptr->is_single ();\n}\n\nbool\nmxIsSparse (const mxArray *ptr)\n{\n  return ptr->is_sparse ();\n}\n\nbool\nmxIsStruct (const mxArray *ptr)\n{\n  return ptr->is_struct ();\n}\n\nbool\nmxIsUint16 (const mxArray *ptr)\n{\n  return ptr->is_uint16 ();\n}\n\nbool\nmxIsUint32 (const mxArray *ptr)\n{\n  return ptr->is_uint32 ();\n}\n\nbool\nmxIsUint64 (const mxArray *ptr)\n{\n  return ptr->is_uint64 ();\n}\n\nbool\nmxIsUint8 (const mxArray *ptr)\n{\n  return ptr->is_uint8 ();\n}\n\n// Odd type+size predicate.\nbool\nmxIsLogicalScalar (const mxArray *ptr)\n{\n  return ptr->is_logical_scalar ();\n}\n\n// Odd type+size+value predicate.\nbool\nmxIsLogicalScalarTrue (const mxArray *ptr)\n{\n  return ptr->is_logical_scalar_true ();\n}\n\n// Size predicate.\nbool\nmxIsEmpty (const mxArray *ptr)\n{\n  return ptr->isempty ();\n}\n\nbool\nmxIsScalar (const mxArray *ptr)\n{\n  return ptr->is_scalar ();\n}\n\n// FIXME: Just plain odd thing to ask of a value.\n// Still, Octave is incompatible because it does not implement this.\nbool\nmxIsFromGlobalWS (const mxArray * /*ptr*/)\n{\n  mexErrMsgTxt (\"mxIsFromGlobalWS() is unimplemented\");\n\n  return 0;\n}\n\n// Dimension extractors.\nstd::size_t\nmxGetM (const mxArray *ptr)\n{\n  return ptr->get_m ();\n}\n\nstd::size_t\nmxGetN (const mxArray *ptr)\n{\n  return ptr->get_n ();\n}\n\nconst mwSize *\nmxGetDimensions (const mxArray *ptr)\n{\n  return ptr->get_dimensions ();\n}\n\nmwSize\nmxGetNumberOfDimensions (const mxArray *ptr)\n{\n  return ptr->get_number_of_dimensions ();\n}\n\nstd::size_t\nmxGetNumberOfElements (const mxArray *ptr)\n{\n  return ptr->get_number_of_elements ();\n}\n\n// Dimension setters.\nvoid\nmxSetM (mxArray *ptr, mwSize m)\n{\n  ptr->set_m (m);\n}\n\nvoid\nmxSetN (mxArray *ptr, mwSize n)\n{\n  ptr->set_n (n);\n}\n\nint\nmxSetDimensions (mxArray *ptr, const mwSize *dims, mwSize ndims)\n{\n  return (ptr->set_dimensions (static_cast<mwSize *>\n                               (maybe_unmark (const_cast<mwSize *> (dims))),\n                               ndims));\n}\n\n// Data extractors.\ndouble *\nmxGetPr (const mxArray *ptr)\n{\n  return static_cast<double *> (ptr->get_data ());\n}\n\ndouble\nmxGetScalar (const mxArray *ptr)\n{\n  return ptr->get_scalar ();\n}\n\nmxChar *\nmxGetChars (const mxArray *ptr)\n{\n  if (mxIsChar (ptr))\n    return static_cast<mxChar *> (ptr->get_data ());\n  else\n    return nullptr;\n}\n\nmxLogical *\nmxGetLogicals (const mxArray *ptr)\n{\n  return static_cast<mxLogical *> (ptr->get_data ());\n}\n\nvoid *\nmxGetData (const mxArray *ptr)\n{\n  return ptr->get_data ();\n}\n\ndouble *\nmxGetPi (const mxArray *ptr)\n{\n  return static_cast<double *> (ptr->get_imag_data ());\n}\n\nvoid *\nmxGetImagData (const mxArray *ptr)\n{\n  return ptr->get_imag_data ();\n}\n\nmxDouble *\nmxGetDoubles (const mxArray *ptr)\n{\n  return ptr->get_doubles ();\n}\n\nmxSingle *\nmxGetSingles (const mxArray *ptr)\n{\n  return ptr->get_singles ();\n}\n\nmxInt8 *\nmxGetInt8s (const mxArray *ptr)\n{\n  return ptr->get_int8s ();\n}\n\nmxInt16 *\nmxGetInt16s (const mxArray *ptr)\n{\n  return ptr->get_int16s ();\n}\n\nmxInt32 *\nmxGetInt32s (const mxArray *ptr)\n{\n  return ptr->get_int32s ();\n}\n\nmxInt64 *\nmxGetInt64s (const mxArray *ptr)\n{\n  return ptr->get_int64s ();\n}\n\nmxUint8 *\nmxGetUint8s (const mxArray *ptr)\n{\n  return ptr->get_uint8s ();\n}\n\nmxUint16 *\nmxGetUint16s (const mxArray *ptr)\n{\n  return ptr->get_uint16s ();\n}\n\nmxUint32 *\nmxGetUint32s (const mxArray *ptr)\n{\n  return ptr->get_uint32s ();\n}\n\nmxUint64 *\nmxGetUint64s (const mxArray *ptr)\n{\n  return ptr->get_uint64s ();\n}\n\nmxComplexDouble *\nmxGetComplexDoubles (const mxArray *ptr)\n{\n  return ptr->get_complex_doubles ();\n}\n\nmxComplexSingle *\nmxGetComplexSingles (const mxArray *ptr)\n{\n  return ptr->get_complex_singles ();\n}\n\n// Data setters.\nvoid\nmxSetPr (mxArray *ptr, double *pr)\n{\n  ptr->set_data (maybe_unmark (pr));\n}\n\nvoid\nmxSetData (mxArray *ptr, void *pr)\n{\n  ptr->set_data (maybe_unmark (pr));\n}\n\nint\nmxSetDoubles (mxArray *ptr, mxDouble *data)\n{\n  return ptr->set_doubles (maybe_unmark (data));\n}\n\nint\nmxSetSingles (mxArray *ptr, mxSingle *data)\n{\n  return ptr->set_singles (maybe_unmark (data));\n}\n\nint\nmxSetInt8s (mxArray *ptr, mxInt8 *data)\n{\n  return ptr->set_int8s (maybe_unmark (data));\n}\n\nint\nmxSetInt16s (mxArray *ptr, mxInt16 *data)\n{\n  return ptr->set_int16s (maybe_unmark (data));\n}\n\nint\nmxSetInt32s (mxArray *ptr, mxInt32 *data)\n{\n  return ptr->set_int32s (maybe_unmark (data));\n}\n\nint\nmxSetInt64s (mxArray *ptr, mxInt64 *data)\n{\n  return ptr->set_int64s (maybe_unmark (data));\n}\n\nint\nmxSetUint8s (mxArray *ptr, mxUint8 *data)\n{\n  return ptr->set_uint8s (maybe_unmark (data));\n}\n\nint\nmxSetUint16s (mxArray *ptr, mxUint16 *data)\n{\n  return ptr->set_uint16s (maybe_unmark (data));\n}\n\nint\nmxSetUint32s (mxArray *ptr, mxUint32 *data)\n{\n  return ptr->set_uint32s (maybe_unmark (data));\n}\n\nint\nmxSetUint64s (mxArray *ptr, mxUint64 *data)\n{\n  return ptr->set_uint64s (maybe_unmark (data));\n}\n\nint\nmxSetComplexDoubles (mxArray *ptr, mxComplexDouble *data)\n{\n  return ptr->set_complex_doubles (maybe_unmark (data));\n}\n\nint\nmxSetComplexSingles (mxArray *ptr, mxComplexSingle *data)\n{\n  return ptr->set_complex_singles (maybe_unmark (data));\n}\n\nvoid\nmxSetPi (mxArray *ptr, double *pi)\n{\n  ptr->set_imag_data (maybe_unmark (pi));\n}\n\nvoid\nmxSetImagData (mxArray *ptr, void *pi)\n{\n  ptr->set_imag_data (maybe_unmark (pi));\n}\n\n// Classes.\nmxClassID\nmxGetClassID (const mxArray *ptr)\n{\n  return ptr->get_class_id ();\n}\n\nconst char *\nmxGetClassName (const mxArray *ptr)\n{\n  return ptr->get_class_name ();\n}\n\nvoid\nmxSetClassName (mxArray *ptr, const char *name)\n{\n  ptr->set_class_name (name);\n}\n\nvoid\nmxSetProperty (mxArray *ptr, mwIndex idx, const char *property_name,\n               const mxArray *property_value)\n{\n  ptr->set_property (idx, property_name, property_value);\n}\n\nmxArray *\nmxGetProperty (const mxArray *ptr, mwIndex idx, const char *property_name)\n{\n  return ptr->get_property (idx, property_name);\n}\n\n// Cell support.\nmxArray *\nmxGetCell (const mxArray *ptr, mwIndex idx)\n{\n  return ptr->get_cell (idx);\n}\n\nvoid\nmxSetCell (mxArray *ptr, mwIndex idx, mxArray *val)\n{\n  ptr->set_cell (idx, val);\n}\n\n// Sparse support.\nmwIndex *\nmxGetIr (const mxArray *ptr)\n{\n  return ptr->get_ir ();\n}\n\nmwIndex *\nmxGetJc (const mxArray *ptr)\n{\n  return ptr->get_jc ();\n}\n\nmwSize\nmxGetNzmax (const mxArray *ptr)\n{\n  return ptr->get_nzmax ();\n}\n\nvoid\nmxSetIr (mxArray *ptr, mwIndex *ir)\n{\n  ptr->set_ir (static_cast<mwIndex *> (maybe_unmark (ir)));\n}\n\nvoid\nmxSetJc (mxArray *ptr, mwIndex *jc)\n{\n  ptr->set_jc (static_cast<mwIndex *> (maybe_unmark (jc)));\n}\n\nvoid\nmxSetNzmax (mxArray *ptr, mwSize nzmax)\n{\n  ptr->set_nzmax (nzmax);\n}\n\n// Structure support.\nint\nmxAddField (mxArray *ptr, const char *key)\n{\n  return ptr->add_field (key);\n}\n\nvoid\nmxRemoveField (mxArray *ptr, int key_num)\n{\n  ptr->remove_field (key_num);\n}\n\nmxArray *\nmxGetField (const mxArray *ptr, mwIndex index, const char *key)\n{\n  int key_num = mxGetFieldNumber (ptr, key);\n  return mxGetFieldByNumber (ptr, index, key_num);\n}\n\nmxArray *\nmxGetFieldByNumber (const mxArray *ptr, mwIndex index, int key_num)\n{\n  return ptr->get_field_by_number (index, key_num);\n}\n\nvoid\nmxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val)\n{\n  int key_num = mxGetFieldNumber (ptr, key);\n  mxSetFieldByNumber (ptr, index, key_num, val);\n}\n\nvoid\nmxSetFieldByNumber (mxArray *ptr, mwIndex index, int key_num, mxArray *val)\n{\n  ptr->set_field_by_number (index, key_num, val);\n}\n\nint\nmxGetNumberOfFields (const mxArray *ptr)\n{\n  return ptr->get_number_of_fields ();\n}\n\nconst char *\nmxGetFieldNameByNumber (const mxArray *ptr, int key_num)\n{\n  return ptr->get_field_name_by_number (key_num);\n}\n\nint\nmxGetFieldNumber (const mxArray *ptr, const char *key)\n{\n  return ptr->get_field_number (key);\n}\n\nint\nmxGetString (const mxArray *ptr, char *buf, mwSize buflen)\n{\n  return ptr->get_string (buf, buflen);\n}\n\nchar *\nmxArrayToString (const mxArray *ptr)\n{\n  return ptr->array_to_string ();\n}\n\nmwIndex\nmxCalcSingleSubscript (const mxArray *ptr, mwSize nsubs, mwIndex *subs)\n{\n  return ptr->calc_single_subscript (nsubs, subs);\n}\n\nstd::size_t\nmxGetElementSize (const mxArray *ptr)\n{\n  return ptr->get_element_size ();\n}\n\n// ------------------------------------------------------------------\n\n// C interface to mex functions:\n\nconst char *\nmexFunctionName ()\n{\n  return mex_context ? mex_context->function_name () : \"unknown\";\n}\n\nint\nmexCallMATLAB (int nargout, mxArray *argout[], int nargin,\n               mxArray *argin[], const char *fname)\n{\n  octave_value_list args = mx_to_ov_args (nargin, argin);\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  bool execution_error = false;\n\n  octave_value_list retval;\n\n  try\n    {\n      octave::tree_evaluator& tw = interp.get_evaluator ();\n\n      octave::unwind_action act\n      ([&tw] (const std::list<octave::octave_lvalue> *lvl)\n      {\n        tw.set_lvalue_list (lvl);\n      }, tw.lvalue_list ());\n\n      tw.set_lvalue_list (nullptr);\n\n      retval = interp.feval (fname, args, nargout);\n    }\n  catch (const octave::execution_exception&)\n    {\n      if (mex_context->trap_feval_error)\n        {\n          // FIXME: is there a way to indicate what error occurred?\n          // Should the error message be displayed here?  Do we need to\n          // save the exception info for lasterror?\n\n          interp.recover_from_exception ();\n\n          execution_error = true;\n        }\n      else\n        {\n          args.resize (0);\n          retval.resize (0);\n\n          throw;\n        }\n    }\n\n  int num_to_copy = retval.length ();\n\n  if (nargout < retval.length ())\n    num_to_copy = nargout;\n\n  for (int i = 0; i < num_to_copy; i++)\n    {\n      // FIXME: it would be nice to avoid copying the value here,\n      // but there is no way to steal memory from a matrix, never mind\n      // that matrix memory is allocated by new[] and mxArray memory\n      // is allocated by malloc().\n      argout[i] = mex_context->make_value (retval(i));\n    }\n\n  while (num_to_copy < nargout)\n    argout[num_to_copy++] = nullptr;\n\n  return execution_error ? 1 : 0;\n}\n\nmxArray *\nmexCallMATLABWithTrap (int nargout, mxArray *argout[], int nargin,\n                       mxArray *argin[], const char *fname)\n{\n  mxArray *mx = nullptr;\n\n  int old_flag = (mex_context ? mex_context->trap_feval_error : 0);\n  mexSetTrapFlag (1);\n  if (mexCallMATLAB (nargout, argout, nargin, argin, fname))\n    {\n      const char *field_names[] = {\"identifier\", \"message\", \"case\", \"stack\"};\n      mx = mxCreateStructMatrix (1, 1, 4, field_names);\n      mxSetFieldByNumber (mx, 0, 0, mxCreateString (\"Octave:MEX\"));\n      std::string msg = \"mexCallMATLABWithTrap: function call <\"\n                        + std::string (fname) + \"> failed\";\n      mxSetFieldByNumber (mx, 0, 1, mxCreateString (msg.c_str ()));\n      mxSetFieldByNumber (mx, 0, 2, mxCreateCellMatrix (0, 0));\n      mxSetFieldByNumber (mx, 0, 3, mxCreateStructMatrix (0, 1, 0, nullptr));\n    }\n  mexSetTrapFlag (old_flag);\n\n  return mx;\n}\n\nvoid\nmexSetTrapFlag (int flag)\n{\n  if (mex_context)\n    mex_context->trap_feval_error = flag;\n}\n\nint\nmexEvalString (const char *s)\n{\n  int retval = 0;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  int parse_status;\n  bool execution_error = false;\n\n  octave_value_list ret;\n\n  try\n    {\n      ret = interp.eval_string (std::string (s), false, parse_status, 0);\n    }\n  catch (const octave::execution_exception&)\n    {\n      interp.recover_from_exception ();\n\n      execution_error = true;\n    }\n\n  if (parse_status || execution_error)\n    retval = 1;\n\n  return retval;\n}\n\nmxArray *\nmexEvalStringWithTrap (const char *s)\n{\n  mxArray *mx = nullptr;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  int parse_status;\n  bool execution_error = false;\n\n  octave_value_list ret;\n\n  try\n    {\n      ret = interp.eval_string (std::string (s), false, parse_status, 0);\n    }\n  catch (const octave::execution_exception&)\n    {\n      interp.recover_from_exception ();\n\n      execution_error = true;\n    }\n\n  if (parse_status || execution_error)\n    {\n      const char *field_names[] = {\"identifier\", \"message\", \"case\", \"stack\"};\n      mx = mxCreateStructMatrix (1, 1, 4, field_names);\n      mxSetFieldByNumber (mx, 0, 0, mxCreateString (\"Octave:MEX\"));\n      std::string msg = \"mexEvalStringWithTrap: eval of <\"\n                        + std::string (s) + \"> failed\";\n      mxSetFieldByNumber (mx, 0, 1, mxCreateString (msg.c_str ()));\n      mxSetFieldByNumber (mx, 0, 2, mxCreateCellMatrix (0, 0));\n      mxSetFieldByNumber (mx, 0, 3, mxCreateStructMatrix (0, 1, 0, nullptr));\n    }\n\n  return mx;\n}\n\nvoid\nmexErrMsgTxt (const char *s)\n{\n  mexErrMsgTxt_impl (mexFunctionName (), s);\n}\n\nvoid\nmexErrMsgIdAndTxt (const char *id, const char *fmt, ...)\n{\n  if (fmt && strlen (fmt) > 0)\n    {\n      const char *fname = mexFunctionName ();\n      std::size_t len = strlen (fname) + 2 + strlen (fmt) + 1;\n      OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);\n      snprintf (tmpfmt, len, \"%s: %s\", fname, fmt);\n      va_list args;\n      va_start (args, fmt);\n      verror_with_id (id, tmpfmt, args);\n      va_end (args);\n    }\n  else\n    {\n      // For compatibility with Matlab, print an empty message.\n      // Octave's error routine requires a non-null input so use a SPACE.\n      error (\" \");\n    }\n}\n\nvoid\nmexWarnMsgTxt (const char *s)\n{\n  std::size_t len;\n\n  if (s && (len = strlen (s)) > 0)\n    {\n      if (s[len - 1] == '\\n')\n        {\n          std::string s_tmp (s, len - 1);\n          warning (\"%s\\n\", s_tmp.c_str ());\n        }\n      else\n        warning (\"%s\", s);\n    }\n  else\n    {\n      // For compatibility with Matlab, print an empty message.\n      // Octave's warning routine requires a non-null input so use a SPACE.\n      warning (\" \");\n    }\n}\n\nvoid\nmexWarnMsgIdAndTxt (const char *id, const char *fmt, ...)\n{\n  // FIXME: is this right?  What does Matlab do if fmt is NULL or\n  //        an empty string?\n\n  if (fmt && strlen (fmt) > 0)\n    {\n      const char *fname = mexFunctionName ();\n      std::size_t len = strlen (fname) + 2 + strlen (fmt) + 1;\n      OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);\n      snprintf (tmpfmt, len, \"%s: %s\", fname, fmt);\n      va_list args;\n      va_start (args, fmt);\n      vwarning_with_id (id, tmpfmt, args);\n      va_end (args);\n    }\n}\n\nint\nmexPrintf (const char *fmt, ...)\n{\n  int retval;\n  va_list args;\n  va_start (args, fmt);\n  retval = octave::vformat (octave_stdout, fmt, args);\n  va_end (args);\n  return retval;\n}\n\nmxArray *\nmexGetVariable (const char *space, const char *name)\n{\n  mxArray *retval = nullptr;\n\n  octave_value val;\n\n  octave::interpreter& interp = octave::__get_interpreter__ ();\n\n  if (! strcmp (space, \"global\"))\n    val = interp.global_varval (name);\n  else\n    {\n      // FIXME: should this be in variables.cc?\n\n      octave::unwind_protect frame;\n\n      bool caller = ! strcmp (space, \"caller\");\n      bool base = ! strcmp (space, \"base\");\n\n      if (caller || base)\n        {\n          // MEX files don't create a separate frame in the call stack,\n          // so we are already in the \"caller\" frame.\n\n          if (base)\n            {\n              octave::tree_evaluator& tw = interp.get_evaluator ();\n\n              frame.add (&octave::tree_evaluator::restore_frame, &tw,\n                         tw.current_call_stack_frame_number ());\n\n              tw.goto_base_frame ();\n            }\n\n          val = interp.varval (name);\n        }\n      else\n        mexErrMsgTxt (\"mexGetVariable: symbol table does not exist\");\n    }\n\n  if (val.is_defined ())\n    {\n      retval = mex_context->make_value (val);\n\n      retval->set_name (name);\n    }\n\n  return retval;\n}\n\nconst mxArray *\nmexGetVariablePtr (const char *space, const char *name)\n{\n  return mexGetVariable (space, name);\n}\n\nint\nmexPutVariable (const char *space, const char *name, const mxArray *ptr)\n{\n  return mexPutVariable_impl (space, name, ptr);\n}\n\nvoid\nmexMakeArrayPersistent (mxArray *ptr)\n{\n  maybe_unmark_array (ptr);\n}\n\nvoid\nmexMakeMemoryPersistent (void *ptr)\n{\n  maybe_unmark (ptr);\n}\n\nint\nmexAtExit (void (*f) ())\n{\n  if (mex_context)\n    {\n      octave_mex_function& curr_mex_fcn = mex_context->current_mex_function ();\n\n      curr_mex_fcn.atexit (f);\n    }\n\n  return 0;\n}\n\nconst mxArray *\nmexGet_interleaved (double handle, const char *property)\n{\n  mxArray *m = nullptr;\n\n  octave_value ret\n    = octave::get_property_from_handle (handle, property, \"mexGet\");\n\n  if (ret.is_defined ())\n    m = ret.as_mxArray (true);\n\n  return m;\n}\n\nconst mxArray *\nmexGet (double handle, const char *property)\n{\n  mxArray *m = nullptr;\n\n  octave_value ret\n    = octave::get_property_from_handle (handle, property, \"mexGet\");\n\n  if (ret.is_defined ())\n    m = ret.as_mxArray (false);\n\n  return m;\n}\n\nint\nmexIsGlobal (const mxArray *ptr)\n{\n  return mxIsFromGlobalWS (ptr);\n}\n\nint\nmexIsLocked ()\n{\n  int retval = 0;\n\n  if (mex_context)\n    {\n      const char *fname = mexFunctionName ();\n\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      retval = interp.mislocked (fname);\n    }\n\n  return retval;\n}\n\nstd::map<std::string, int> mex_lock_count;\n\nvoid\nmexLock ()\n{\n  if (mex_context)\n    {\n      const char *fname = mexFunctionName ();\n\n      if (mex_lock_count.find (fname) == mex_lock_count.end ())\n        mex_lock_count[fname] = 1;\n      else\n        mex_lock_count[fname]++;\n\n      octave::interpreter& interp = octave::__get_interpreter__ ();\n\n      interp.mlock ();\n    }\n}\n\nint\nmexSet (double handle, const char *property, mxArray *val)\n{\n  return mexSet_impl (handle, property, val);\n}\n\nvoid\nmexUnlock ()\n{\n  if (mex_context)\n    {\n      const char *fname = mexFunctionName ();\n\n      auto p = mex_lock_count.find (fname);\n\n      if (p != mex_lock_count.end ())\n        {\n          int count = --mex_lock_count[fname];\n\n          if (count == 0)\n            {\n              octave::interpreter& interp = octave::__get_interpreter__ ();\n\n              interp.munlock (fname);\n\n              mex_lock_count.erase (p);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "libmex/mex.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nThis code was originally distributed as part of Octave Forge under\nthe following terms:\n\nAuthor: Paul Kienzle\nI grant this code to the public domain.\n2001-03-22\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\nOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n\n*/\n\n/* mex.h is for use in C-programs only; do NOT include it in mex.cc */\n\n#if ! defined (octave_mex_h)\n#define octave_mex_h 1\n\n#include \"octave-config.h\"\n\n#define HAVE_OCTAVE\n\nstruct mxArray;\n#define mxArray struct mxArray\n\n/* -V4 stuff */\n#if defined (V4)\n#  define Matrix mxArray\n#  define REAL mxREAL\n#endif\n\n#define mxMAXNAME 64\n\n#include \"mexproto.h\"\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#if defined (V4)\nvoid mexFunction (int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);\n#else\nvoid mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);\n#endif\n\n/* V4 floating point routines renamed in V5.  */\n#define mexIsNaN mxIsNaN\n#define mexIsFinite mxIsFinite\n#define mexIsInf mxIsInf\n#define mexGetEps mxGetEps\n#define mexGetInf mxGetInf\n#define mexGetNaN mxGetNaN\n\n#define mexGetGlobal(nm) mexGetArray (nm, \"global\")\n#define mexGetMatrix(nm) mexGetArray (nm, \"caller\")\n#define mexGetMatrixPtr(nm) mexGetArrayPtr (nm, \"caller\")\n\n#define mexGetArray(nm, space) mexGetVariable (space, nm)\n#define mexGetArrayPtr(nm, space) mexGetVariablePtr (space, nm)\n\n#define mexPutMatrix(ptr) mexPutVariable (\"caller\", \"\", ptr)\n#define mexPutArray(ptr, space) mexPutVariable (space, \"\", ptr)\n\n#define mxCreateFull mxCreateDoubleMatrix\n\n#define mxCreateScalarDouble mxCreateDoubleScalar\n\n#define mxFreeMatrix mxDestroyArray\n\n#define mxIsString mxIsChar\n\n/* Apparently these are also defined.  */\n\n#if ! defined (UINT64_T)\n#  define UINT64_T uint64_t\n#endif\n\n#if ! defined (uint64_T)\n#  define uint64_T uint64_t\n#endif\n\n#if ! defined (INT64_T)\n#  define INT64_T int64_t\n#endif\n\n#if ! defined (int64_T)\n#  define int64_T int64_t\n#endif\n\n#if ! defined (UINT32_T)\n#  define UINT32_T uint32_t\n#endif\n\n#if ! defined (uint32_T)\n#  define uint32_T uint32_t\n#endif\n\n#if ! defined (INT32_T)\n#  define INT32_T int32_t\n#endif\n\n#if ! defined (int32_T)\n#  define int32_T int32_t\n#endif\n\n#if ! defined (UINT16_T)\n#  define UINT16_T uint16_t\n#endif\n\n#if ! defined (uint16_T)\n#  define uint16_T uint16_t\n#endif\n\n#if ! defined (INT16_T)\n#  define INT16_T int16_t\n#endif\n\n#if ! defined (int16_T)\n#  define int16_T int16_t\n#endif\n\n#if ! defined (UINT8_T)\n#  define UINT8_T uint8_t\n#endif\n\n#if ! defined (uint8_T)\n#  define uint8_T uint8_t\n#endif\n\n#if ! defined (INT8_T)\n#  define INT8_T int8_t\n#endif\n\n#if ! defined (int8_T)\n#  define int8_T int8_t\n#endif\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "libmex/mexproto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nThis code was originally distributed as part of Octave Forge under\nthe following terms:\n\nAuthor: Paul Kienzle\nI grant this code to the public domain.\n2001-03-22\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\nOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n\n*/\n\n/* mex.h is for use in C-programs only; do NOT include it in mex.cc */\n\n#if ! defined (octave_mexproto_h)\n#define octave_mexproto_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\n#  include <cstdlib>\nusing std::size_t;\nextern \"C\" {\n#else\n#  include <stdlib.h>\n#  include <stdbool.h>\n#endif\n\n#if ! defined (MX_HAS_INTERLEAVED_COMPLEX)\n#  define MX_HAS_INTERLEAVED_COMPLEX 0\n#endif\n\n#include \"mxtypes.h\"\n\n/* Prototype for the gateway function.  */\n\nextern void mexFunction (int nlhs, mxArray *plhs[],\n                         int nrhs, const mxArray *prhs[]);\n\n/* Interface to the interpreter.  */\nextern OCTMEX_API const char * mexFunctionName (void);\n\nextern OCTMEX_API int\nmexCallMATLAB (int nargout, mxArray *argout[],\n               int nargin, mxArray *argin[],\n               const char *fname);\n\nextern OCTMEX_API mxArray *\nmexCallMATLABWithTrap (int nargout, mxArray *argout[],\n                       int nargin, mxArray *argin[],\n                       const char *fname);\n\nextern OCTMEX_API int mexEvalString (const char *s);\nextern OCTMEX_API mxArray * mexEvalStringWithTrap (const char *s);\n\nextern OCTMEX_API void mexSetTrapFlag (int flag);\n\nextern OCTMEX_API void mexErrMsgTxt (const char *s);\nextern OCTMEX_API void mexErrMsgIdAndTxt (const char *id, const char *s, ...);\nextern OCTMEX_API void mexWarnMsgTxt (const char *s);\nextern OCTMEX_API void mexWarnMsgIdAndTxt (const char *id, const char *s, ...);\nextern OCTMEX_API int mexPrintf (const char *fmt, ...);\n\nextern OCTMEX_API mxArray *\nmexGetVariable (const char *space, const char *name);\nextern OCTMEX_API const mxArray *\nmexGetVariablePtr (const char *space, const char *name);\n\nextern OCTMEX_API int\nmexPutVariable (const char *space, const char *name, const mxArray *ptr);\n\n#if MX_HAS_INTERLEAVED_COMPLEX\n#  define mexGet mexGet_interleaved\n#endif\nextern OCTMEX_API const mxArray *\nmexGet (double handle, const char *property);\n\nextern OCTMEX_API int\nmexSet (double handle, const char *property, mxArray *val);\n\nextern OCTMEX_API void mexMakeArrayPersistent (mxArray *ptr);\nextern OCTMEX_API void mexMakeMemoryPersistent (void *ptr);\n\nextern OCTMEX_API void mexLock (void);\nextern OCTMEX_API void mexUnlock (void);\n\nextern OCTMEX_API int mexIsGlobal (const mxArray *ptr);\nextern OCTMEX_API int mexIsLocked (void);\n\nextern OCTMEX_API int mexAtExit (void (*f) (void));\n\n/* Floating point predicates.  */\nextern OCTMEX_API bool mxIsFinite (double v);\nextern OCTMEX_API bool mxIsInf (double v);\nextern OCTMEX_API bool mxIsNaN (double v);\n\n/* Floating point values.  */\nextern OCTMEX_API double mxGetEps (void);\nextern OCTMEX_API double mxGetInf (void);\nextern OCTMEX_API double mxGetNaN (void);\n\n/* Memory management.  */\nextern OCTMEX_API void * mxCalloc (size_t n, size_t size);\nextern OCTMEX_API void * mxMalloc (size_t n);\nextern OCTMEX_API void * mxRealloc (void *ptr, size_t size);\nextern OCTMEX_API void mxFree (void *ptr);\n\n/* Constructors.  */\n#if MX_HAS_INTERLEAVED_COMPLEX\n#  define mxCreateCellArray mxCreateCellArray_interleaved\n#  define mxCreateCellMatrix mxCreateCellMatrix_interleaved\n#  define mxCreateCharArray mxCreateCharArray_interleaved\n#  define mxCreateCharMatrixFromStrings mxCreateCharMatrixFromStrings_interleaved\n#  define mxCreateDoubleMatrix mxCreateDoubleMatrix_interleaved\n#  define mxCreateDoubleScalar mxCreateDoubleScalar_interleaved\n#  define mxCreateLogicalArray mxCreateLogicalArray_interleaved\n#  define mxCreateLogicalMatrix mxCreateLogicalMatrix_interleaved\n#  define mxCreateLogicalScalar mxCreateLogicalScalar_interleaved\n#  define mxCreateNumericArray mxCreateNumericArray_interleaved\n#  define mxCreateNumericMatrix mxCreateNumericMatrix_interleaved\n#  define mxCreateUninitNumericArray mxCreateUninitNumericArray_interleaved\n#  define mxCreateUninitNumericMatrix mxCreateUninitNumericMatrix_interleaved\n#  define mxCreateSparse mxCreateSparse_interleaved\n#  define mxCreateSparseLogicalMatrix mxCreateSparseLogicalMatrix_interleaved\n#  define mxCreateString mxCreateString_interleaved\n#  define mxCreateStructArray mxCreateStructArray_interleaved\n#  define mxCreateStructMatrix mxCreateStructMatrix_interleaved\n#endif\n\nextern OCTMEX_API mxArray *\nmxCreateCellArray (mwSize ndims, const mwSize *dims);\nextern OCTMEX_API mxArray *\nmxCreateCellMatrix (mwSize m, mwSize n);\nextern OCTMEX_API mxArray *\nmxCreateCharArray (mwSize ndims, const mwSize *dims);\nextern OCTMEX_API mxArray *\nmxCreateCharMatrixFromStrings (mwSize m, const char **str);\nextern OCTMEX_API mxArray *\nmxCreateDoubleMatrix (mwSize nr, mwSize nc, mxComplexity flag);\nextern OCTMEX_API mxArray *\nmxCreateDoubleScalar (double val);\nextern OCTMEX_API mxArray *\nmxCreateLogicalArray (mwSize ndims, const mwSize *dims);\nextern OCTMEX_API mxArray *\nmxCreateLogicalMatrix (mwSize m, mwSize n);\nextern OCTMEX_API mxArray *\nmxCreateLogicalScalar (mxLogical val);\nextern OCTMEX_API mxArray *\nmxCreateNumericArray (mwSize ndims, const mwSize *dims,\n                      mxClassID class_id, mxComplexity flag);\nextern OCTMEX_API mxArray *\nmxCreateNumericMatrix (mwSize m, mwSize n,\n                       mxClassID class_id, mxComplexity flag);\nextern OCTMEX_API mxArray *\nmxCreateUninitNumericArray (mwSize ndims, const mwSize *dims,\n                            mxClassID class_id, mxComplexity flag);\nextern OCTMEX_API mxArray *\nmxCreateUninitNumericMatrix (mwSize m, mwSize n,\n                             mxClassID class_id, mxComplexity flag);\n\nextern OCTMEX_API mxArray *\nmxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag);\nextern OCTMEX_API mxArray *\nmxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax);\nextern OCTMEX_API mxArray *\nmxCreateString (const char *str);\nextern OCTMEX_API mxArray *\nmxCreateStructArray (mwSize ndims, const mwSize *dims,\n                     int num_keys, const char **keys);\nextern OCTMEX_API mxArray *\nmxCreateStructMatrix (mwSize rows, mwSize cols,\n                      int num_keys, const char **keys);\n\n/* Copy constructor.  */\nextern OCTMEX_API mxArray *mxDuplicateArray (const mxArray *v);\n\n/* Destructor.  */\nextern OCTMEX_API void mxDestroyArray (mxArray *v);\n\n/* Type Predicates.  */\nextern OCTMEX_API bool mxIsCell (const mxArray *ptr);\nextern OCTMEX_API bool mxIsChar (const mxArray *ptr);\nextern OCTMEX_API bool mxIsClass (const mxArray *ptr, const char *name);\nextern OCTMEX_API bool mxIsComplex (const mxArray *ptr);\nextern OCTMEX_API bool mxIsDouble (const mxArray *ptr);\n/* Matlab seems to have deprecated IsFunctionHandle, but it seems useful */\nextern OCTMEX_API bool mxIsFunctionHandle (const mxArray *ptr);\nextern OCTMEX_API bool mxIsInt16 (const mxArray *ptr);\nextern OCTMEX_API bool mxIsInt32 (const mxArray *ptr);\nextern OCTMEX_API bool mxIsInt64 (const mxArray *ptr);\nextern OCTMEX_API bool mxIsInt8 (const mxArray *ptr);\nextern OCTMEX_API bool mxIsLogical (const mxArray *ptr);\nextern OCTMEX_API bool mxIsNumeric (const mxArray *ptr);\nextern OCTMEX_API bool mxIsSingle (const mxArray *ptr);\nextern OCTMEX_API bool mxIsSparse (const mxArray *ptr);\nextern OCTMEX_API bool mxIsStruct (const mxArray *ptr);\nextern OCTMEX_API bool mxIsUint16 (const mxArray *ptr);\nextern OCTMEX_API bool mxIsUint32 (const mxArray *ptr);\nextern OCTMEX_API bool mxIsUint64 (const mxArray *ptr);\nextern OCTMEX_API bool mxIsUint8 (const mxArray *ptr);\n\n/* Odd type+size predicate.  */\nextern OCTMEX_API bool mxIsLogicalScalar (const mxArray *ptr);\n\n/* Odd type+size+value predicate.  */\nextern OCTMEX_API bool mxIsLogicalScalarTrue (const mxArray *ptr);\n\n/* Size predicates.  */\nextern OCTMEX_API bool mxIsEmpty (const mxArray *ptr);\nextern OCTMEX_API bool mxIsScalar (const mxArray *ptr);\n\n/* Just plain odd thing to ask of a value.  */\nextern OCTMEX_API bool mxIsFromGlobalWS (const mxArray *ptr);\n\n/* Dimension extractors.  */\nextern OCTMEX_API size_t mxGetM (const mxArray *ptr);\nextern OCTMEX_API size_t mxGetN (const mxArray *ptr);\nextern OCTMEX_API const mwSize * mxGetDimensions (const mxArray *ptr);\nextern OCTMEX_API mwSize mxGetNumberOfDimensions (const mxArray *ptr);\nextern OCTMEX_API size_t mxGetNumberOfElements (const mxArray *ptr);\n\n/* Dimension setters.  */\nextern OCTMEX_API void mxSetM (mxArray *ptr, mwSize M);\nextern OCTMEX_API void mxSetN (mxArray *ptr, mwSize N);\nextern OCTMEX_API int mxSetDimensions (mxArray *ptr, const mwSize *dims,\n                                       mwSize ndims);\n\n#if MX_HAS_INTERLEAVED_COMPLEX\nextern OCTMEX_API int mxMakeArrayReal (mxArray *ptr);\nextern OCTMEX_API int mxMakeArrayComplex (mxArray *ptr);\n#endif\n\n/* Data extractors.  */\nextern OCTMEX_API double * mxGetPr (const mxArray *ptr);\nextern OCTMEX_API double mxGetScalar (const mxArray *ptr);\nextern OCTMEX_API mxChar * mxGetChars (const mxArray *ptr);\nextern OCTMEX_API mxLogical *mxGetLogicals (const mxArray *ptr);\nextern OCTMEX_API void * mxGetData (const mxArray *ptr);\n#if MX_HAS_INTERLEAVED_COMPLEX\nextern OCTMEX_API mxDouble * mxGetDoubles (const mxArray *p);\nextern OCTMEX_API mxSingle * mxGetSingles (const mxArray *p);\nextern OCTMEX_API mxInt8 * mxGetInt8s (const mxArray *p);\nextern OCTMEX_API mxInt16 * mxGetInt16s (const mxArray *p);\nextern OCTMEX_API mxInt32 * mxGetInt32s (const mxArray *p);\nextern OCTMEX_API mxInt64 * mxGetInt64s (const mxArray *p);\nextern OCTMEX_API mxUint8 * mxGetUint8s (const mxArray *p);\nextern OCTMEX_API mxUint16 * mxGetUint16s (const mxArray *p);\nextern OCTMEX_API mxUint32 * mxGetUint32s (const mxArray *p);\nextern OCTMEX_API mxUint64 * mxGetUint64s (const mxArray *p);\n\nextern OCTMEX_API mxComplexDouble * mxGetComplexDoubles (const mxArray *p);\nextern OCTMEX_API mxComplexSingle * mxGetComplexSingles (const mxArray *p);\n#else\nextern OCTMEX_API double * mxGetPi (const mxArray *ptr);\nextern OCTMEX_API void * mxGetImagData (const mxArray *ptr);\n#endif\n\n/* Data setters.  */\nextern OCTMEX_API void mxSetPr (mxArray *ptr, double *pr);\nextern OCTMEX_API void mxSetData (mxArray *ptr, void *data);\n#if MX_HAS_INTERLEAVED_COMPLEX\nextern OCTMEX_API int mxSetDoubles (mxArray *p, mxDouble *d);\nextern OCTMEX_API int mxSetSingles (mxArray *p, mxSingle *d);\nextern OCTMEX_API int mxSetInt8s (mxArray *p, mxInt8 *d);\nextern OCTMEX_API int mxSetInt16s (mxArray *p, mxInt16 *d);\nextern OCTMEX_API int mxSetInt32s (mxArray *p, mxInt32 *d);\nextern OCTMEX_API int mxSetInt64s (mxArray *p, mxInt64 *d);\nextern OCTMEX_API int mxSetUint8s (mxArray *p, mxUint8 *d);\nextern OCTMEX_API int mxSetUint16s (mxArray *p, mxUint16 *d);\nextern OCTMEX_API int mxSetUint32s (mxArray *p, mxUint32 *d);\nextern OCTMEX_API int mxSetUint64s (mxArray *p, mxUint64 *d);\n\nextern OCTMEX_API int mxSetComplexDoubles (mxArray *p, mxComplexDouble *d);\nextern OCTMEX_API int mxSetComplexSingles (mxArray *p, mxComplexSingle *d);\n#else\nextern OCTMEX_API void mxSetPi (mxArray *ptr, double *pi);\nextern OCTMEX_API void mxSetImagData (mxArray *ptr, void *pi);\n#endif\n\n/* Classes.  */\nextern OCTMEX_API mxClassID mxGetClassID (const mxArray *ptr);\nextern OCTMEX_API const char * mxGetClassName (const mxArray *ptr);\nextern OCTMEX_API void mxSetClassName (mxArray *ptr, const char *name);\nextern OCTMEX_API mxArray *\nmxGetProperty (const mxArray *ptr, mwIndex idx, const char *property_name);\nextern OCTMEX_API void\nmxSetProperty (mxArray *ptr, mwIndex idx,\n               const char *property_name, const mxArray *property_value);\n\n/* Cell support.  */\nextern OCTMEX_API mxArray * mxGetCell (const mxArray *ptr, mwIndex idx);\n\nextern OCTMEX_API void mxSetCell (mxArray *ptr, mwIndex idx, mxArray *val);\n\n/* Sparse support.  */\nextern OCTMEX_API mwIndex * mxGetIr (const mxArray *ptr);\nextern OCTMEX_API mwIndex * mxGetJc (const mxArray *ptr);\nextern OCTMEX_API mwSize mxGetNzmax (const mxArray *ptr);\n\nextern OCTMEX_API void mxSetIr (mxArray *ptr, mwIndex *ir);\nextern OCTMEX_API void mxSetJc (mxArray *ptr, mwIndex *jc);\nextern OCTMEX_API void mxSetNzmax (mxArray *ptr, mwSize nzmax);\n\n/* Structure support.  */\nextern OCTMEX_API int mxAddField (mxArray *ptr, const char *key);\n\nextern OCTMEX_API void mxRemoveField (mxArray *ptr, int key_num);\n\nextern OCTMEX_API mxArray *\nmxGetField (const mxArray *ptr, mwIndex index, const char *key);\nextern OCTMEX_API mxArray *\nmxGetFieldByNumber (const mxArray *ptr, mwIndex index, int key_num);\n\nextern OCTMEX_API void\nmxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val);\nextern OCTMEX_API void\nmxSetFieldByNumber (mxArray *ptr, mwIndex index, int key_num, mxArray *val);\n\nextern OCTMEX_API int mxGetNumberOfFields (const mxArray *ptr);\n\nextern OCTMEX_API const char *\nmxGetFieldNameByNumber (const mxArray *ptr, int key_num);\nextern OCTMEX_API int mxGetFieldNumber (const mxArray *ptr, const char *key);\n\nextern OCTMEX_API int\nmxGetString (const mxArray *ptr, char *buf, mwSize buflen);\nextern OCTMEX_API char *mxArrayToString (const mxArray *ptr);\n\n/* Miscellaneous.  */\nextern OCTMEX_API mwIndex\nmxCalcSingleSubscript (const mxArray *ptr, mwSize nsubs, mwIndex *subs);\n\nextern OCTMEX_API size_t mxGetElementSize (const mxArray *ptr);\n\n#if defined (MEX_DEBUG)\n\n#  define mxAssert(expr, msg)                                           \\\n  do                                                                    \\\n    {                                                                   \\\n      if (! (expr))                                                     \\\n        {                                                               \\\n          if (msg && msg[0])                                            \\\n            mexErrMsgIdAndTxt                                           \\\n              (\"Octave:MEX\",                                            \\\n               \"Assertion failed: %s, at line %d of file \\\"%s\\\".\\n%s\\n\", \\\n               #expr, __LINE__, __FILE__, msg);                         \\\n          else                                                          \\\n            mexErrMsgIdAndTxt                                           \\\n              (\"Octave:MEX\",                                            \\\n               \"Assertion failed: %s, at line %d of file \\\"%s\\\".\\n\",    \\\n               #expr, __LINE__, __FILE__);                              \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\n#  define mxAssertS(expr, msg)                                          \\\n  do                                                                    \\\n    {                                                                   \\\n      if (! (expr))                                                     \\\n        {                                                               \\\n          if (msg && msg[0])                                            \\\n            mexErrMsgIdAndTxt                                           \\\n              (\"Octave:MEX\",                                            \\\n               \"Assertion failed at line %d of file \\\"%s\\\".\\n%s\\n\",     \\\n               __LINE__, __FILE__, msg);                                \\\n          else                                                          \\\n            mexErrMsgIdAndTxt                                           \\\n              (\"Octave:MEX\",                                            \\\n               \"Assertion failed at line %d of file \\\"%s\\\".\\n\",         \\\n               __LINE__, __FILE__);                                     \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\n#else\n#  define mxAssert(expr, msg)\n#  define mxAssertS(expr, msg)\n#endif\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "libmex/module.mk",
    "content": "DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\n%canon_reldir%_CLEANFILES =\n%canon_reldir%_DISTCLEANFILES =\n%canon_reldir%_MAINTAINERCLEANFILES =\n\n## Search local directories before those specified by the user.\n%canon_reldir%_liboctmex_la_CPPFLAGS = \\\n  @OCTMEX_DLL_DEFS@ \\\n  -I$(srcdir)/libmex \\\n  -Ilibinterp -I$(srcdir)/libinterp \\\n  -Ilibinterp/corefcn -I$(srcdir)/libinterp/corefcn \\\n  -I$(srcdir)/libinterp/octave-value \\\n  -I$(srcdir)/libinterp/parse-tree \\\n  -I$(srcdir)/libinterp/template-inst \\\n  -I$(srcdir)/liboctave/array \\\n  -I$(srcdir)/liboctave/numeric \\\n  -Iliboctave/operators -I$(srcdir)/liboctave/operators \\\n  -I$(srcdir)/liboctave/system \\\n  -I$(srcdir)/liboctave/util\n\noctlib_LTLIBRARIES += %reldir%/liboctmex.la\n\n%canon_reldir%_pkgconfig_DATA = %reldir%/octmex.pc\n\nLIBOCTMEX_BUILT_NODISTFILES = \\\n  %reldir%/liboctmex-build-info.cc\n\n%canon_reldir%_EXTRA_DIST = \\\n  %reldir%/liboctmex-build-info.in.cc\n\nLIBMEX_INC = \\\n  %reldir%/mex.h \\\n  %reldir%/mexproto.h\n\noctinclude_HEADERS += \\\n  %reldir%/liboctmex-build-info.h \\\n  $(LIBMEX_INC)\n\n%canon_reldir%_liboctmex_la_SOURCES = \\\n  %reldir%/mex.cc\n\nnodist_%canon_reldir%_liboctmex_la_SOURCES = \\\n  %reldir%/liboctmex-build-info.cc\n\n%canon_reldir%_liboctmex_la_LIBADD = \\\n  libinterp/liboctinterp.la \\\n  liboctave/liboctave.la\n\n## Increment the following version numbers as needed and according\n## to the rules in the etc/HACKING.md file.\n\n%canon_reldir%_liboctmex_current = 1\n%canon_reldir%_liboctmex_revision = 1\n%canon_reldir%_liboctmex_age = 0\n\n## Initialize variable used to verify that this version of Octave can run\n## a dynamically loaded MEX file (checked against SOVERSION embedded in file).\nOCTAVE_LIBOCTMEX_SOVERSION_MAJOR = $(%canon_reldir%_liboctmex_current)-$(%canon_reldir%_liboctmex_age)\n\n%canon_reldir%_liboctmex_version_info = $(%canon_reldir%_liboctmex_current):$(%canon_reldir%_liboctmex_revision):$(%canon_reldir%_liboctmex_age)\n\n%canon_reldir%_liboctmex_la_LDFLAGS = \\\n  $(AM_LDFLAGS) \\\n  -version-info $(%canon_reldir%_liboctmex_version_info) \\\n  $(NO_UNDEFINED_LDFLAG) \\\n  -bindir $(bindir) \\\n  $(WARN_LDFLAGS)\n\n%reldir%/liboctmex-build-info.cc: %reldir%/liboctmex-build-info.in.cc HG-ID | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(build-info-commands)\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n\n%canon_reldir%_CLEANFILES += \\\n  $(LIBOCTMEX_BUILT_NODISTFILES)\n\n%canon_reldir%_DISTCLEANFILES += \\\n  $(%canon_reldir%_pkgconfig_DATA)\n\nCLEANFILES += $(%canon_reldir%_CLEANFILES)\nDISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)\nMAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)\n\nlibmex-clean:\n\trm -f $(%canon_reldir%_CLEANFILES)\n\nlibmex-distclean: libmex-clean\n\trm -f $(%canon_reldir%_DISTCLEANFILES)\n\nlibmex-maintainer-clean: libmex-distclean\n\trm -f $(%canon_reldir%_MAINTAINERCLEANFILES)\n\n"
  },
  {
    "path": "libmex/octmex.in.pc",
    "content": "Name: @PACKAGE_NAME@\nDescription: C interface (MEX) to GNU Octave interpreter.\nURL: https://www.octave.org\nVersion: @PACKAGE_VERSION@\nRequires:\nRequires.private: octinterp octave\nLibs: -L@octlibdir@ @LIBOCTMEX@\nLibs.private:\nCflags: -I@octincludedir@/..\n"
  },
  {
    "path": "liboctave/array/Array-C.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Arrays of Complex values.\n\n#include \"mappers.h\"\n#include \"oct-cmplx.h\"\n\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n#include \"oct-sort.cc\"\n\ntemplate <>\ninline bool\nsort_isnan<Complex> (const Complex& x)\n{\n  return octave::math::isnan (x);\n}\n\n// Sort Criteria: 1) isnan, 2) magnitude of z, 3) phase of z in range (-pi, pi]\n\nstatic bool\nnan_ascending_compare (const Complex& x, const Complex& y)\n{\n  return octave::math::isnan (y) ? ! octave::math::isnan (x) : x < y;\n}\n\nstatic bool\nnan_descending_compare (const Complex& x, const Complex& y)\n{\n  return octave::math::isnan (x) ? ! octave::math::isnan (y) : x > y;\n}\n\nArray<Complex>::compare_fcn_type\nsafe_comparator (sortmode mode, const Array<Complex>& a, bool allow_chk)\n{\n  Array<Complex>::compare_fcn_type result = nullptr;\n\n  if (allow_chk)\n    {\n      octave_idx_type k = 0;\n      for (; k < a.numel () && ! octave::math::isnan (a(k)); k++) ;\n      if (k == a.numel ())\n        {\n          if (mode == ASCENDING)\n            result = octave_sort<Complex>::ascending_compare;\n          else if (mode == DESCENDING)\n            result = octave_sort<Complex>::descending_compare;\n        }\n    }\n\n  if (! result)\n    {\n      if (mode == ASCENDING)\n        result = nan_ascending_compare;\n      else if (mode == DESCENDING)\n        result = nan_descending_compare;\n    }\n\n  return result;\n}\n\ntemplate class octave_sort<Complex>;\n\nINSTANTIATE_ARRAY (Complex, );\n\ntemplate OCTAVE_API std::ostream& operator << (std::ostream&,\n                                               const Array<Complex>&);\n\n#include \"DiagArray2.h\"\n#include \"DiagArray2.cc\"\n\ntemplate class DiagArray2<Complex>;\n"
  },
  {
    "path": "liboctave/array/Array-b.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Arrays of bool values.\n\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n\n#define INLINE_ASCENDING_SORT 1\n#define INLINE_DESCENDING_SORT 1\n#include \"oct-sort.cc\"\n\n// Specialize bool sorting (aka stable partitioning).\n\ntemplate <bool desc>\nstatic void\ndo_bool_partition (bool *data, octave_idx_type nel)\n{\n  octave_idx_type k = 0;\n  for (octave_idx_type i = 0; i < nel; i++)\n    if (data[i] == desc)\n      data[k++] = desc;\n  for (octave_idx_type i = k; i < nel; i++)\n    data[i] = ! desc;\n}\n\ntemplate <bool desc>\nstatic void\ndo_bool_partition (bool *data, octave_idx_type *idx,\n                   octave_idx_type nel)\n{\n  // FIXME: This is essentially a simple bucket sort.\n  // Can it be efficiently done by std::partition?\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, jdx, nel);\n  octave_idx_type k = 0;\n  octave_idx_type l = 0;\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      if (data[i] == desc)\n        {\n          data[k] = desc;\n          idx[k++] = idx[i];\n        }\n      else\n        jdx[l++] = idx[i];\n    }\n\n  for (octave_idx_type i = k; i < nel; i++)\n    {\n      data[i] = ! desc;\n      idx[i] = jdx[i-k];\n    }\n}\n\ntemplate <>\ntemplate <>\nvoid\noctave_sort<bool>::sort (bool *data, octave_idx_type nel,\n                         std::less<bool>)\n{\n  do_bool_partition<false> (data, nel);\n}\n\ntemplate <>\ntemplate <>\nvoid\noctave_sort<bool>::sort (bool *data, octave_idx_type nel,\n                         std::greater<bool>)\n{\n  do_bool_partition<true> (data, nel);\n}\n\ntemplate <>\ntemplate <>\nvoid\noctave_sort<bool>::sort (bool *data, octave_idx_type *idx, octave_idx_type nel,\n                         std::less<bool>)\n{\n  do_bool_partition<false> (data, idx, nel);\n}\n\ntemplate <>\ntemplate <>\nvoid\noctave_sort<bool>::sort (bool *data, octave_idx_type *idx, octave_idx_type nel,\n                         std::greater<bool>)\n{\n  do_bool_partition<true> (data, idx, nel);\n}\n\ntemplate class octave_sort<bool>;\n\nINSTANTIATE_ARRAY (bool, );\n\ntemplate OCTAVE_API std::ostream& operator << (std::ostream&,\n                                               const Array<bool>&);\n\n#include \"DiagArray2.h\"\n#include \"DiagArray2.cc\"\n\ntemplate class DiagArray2<bool>;\n"
  },
  {
    "path": "liboctave/array/Array-base.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Do not include this file directly to instantiate the Array<T> template\n// class in code outside liboctave.  Include \"Array-oct.cc\" or \"Array.cc\"\n// instead.\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <ostream>\n\n#include \"Array-oct.h\"\n#include \"Array-util.h\"\n#include \"mappers.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n\n// One-dimensional array class.  Handles the reference counting for\n// all the derived classes.\n\ntemplate <typename T, typename Alloc>\ntypename Array<T, Alloc>::ArrayRep *\nArray<T, Alloc>::nil_rep ()\n{\n  static ArrayRep nr;\n  return &nr;\n}\n\n// This is similar to the template for containers but specialized for Array.\n// Note we can't specialize a member without also specializing the class.\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>::Array (const Array<T, Alloc>& a, const dim_vector& dv)\n  : m_dimensions (dv), m_rep (a.m_rep),\n    m_slice_data (a.m_slice_data), m_slice_len (a.m_slice_len)\n{\n  bool invalid_size = false;\n\n  octave_idx_type new_numel = 0;\n\n  try\n    {\n      // Safe numel may throw a bad_alloc error because the new\n      // dimensions are too large to allocate.  Trap that here so\n      // we can issue a more helpful diagnostic that is consistent\n      // with other size mismatch failures.\n\n      new_numel = m_dimensions.safe_numel ();\n    }\n  catch (const std::bad_alloc&)\n    {\n      invalid_size = true;\n    }\n\n  if (invalid_size || new_numel != a.numel ())\n    {\n      std::string dimensions_str = a.m_dimensions.str ();\n      std::string new_dims_str = m_dimensions.str ();\n\n      (*current_liboctave_error_handler)\n        (\"reshape: can't reshape %s array to %s array\",\n         dimensions_str.c_str (), new_dims_str.c_str ());\n    }\n\n  // This goes here because if an exception is thrown by the above,\n  // destructor will be never called.\n  m_rep->m_count++;\n  m_dimensions.chop_trailing_singletons ();\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::fill (const T& val)\n{\n  if (m_rep->m_count > 1)\n    {\n      --m_rep->m_count;\n      m_rep = new ArrayRep (numel (), val);\n      m_slice_data = m_rep->m_data;\n    }\n  else\n    std::fill_n (m_slice_data, m_slice_len, val);\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::clear ()\n{\n  if (--m_rep->m_count == 0)\n    delete m_rep;\n\n  m_rep = nil_rep ();\n  m_rep->m_count++;\n  m_slice_data = m_rep->m_data;\n  m_slice_len = m_rep->m_len;\n\n  m_dimensions = dim_vector ();\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::clear (const dim_vector& dv)\n{\n  if (--m_rep->m_count == 0)\n    delete m_rep;\n\n  m_rep = new ArrayRep (dv.safe_numel ());\n  m_slice_data = m_rep->m_data;\n  m_slice_len = m_rep->m_len;\n\n  m_dimensions = dv;\n  m_dimensions.chop_trailing_singletons ();\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::squeeze () const\n{\n  Array<T, Alloc> retval = *this;\n\n  if (ndims () > 2)\n    {\n      bool dims_changed = false;\n\n      dim_vector new_dimensions = m_dimensions;\n\n      int k = 0;\n\n      for (int i = 0; i < ndims (); i++)\n        {\n          if (m_dimensions(i) == 1)\n            dims_changed = true;\n          else\n            new_dimensions(k++) = m_dimensions(i);\n        }\n\n      if (dims_changed)\n        {\n          switch (k)\n            {\n            case 0:\n              new_dimensions = dim_vector (1, 1);\n              break;\n\n            case 1:\n              {\n                octave_idx_type tmp = new_dimensions(0);\n\n                new_dimensions.resize (2);\n\n                new_dimensions(0) = tmp;\n                new_dimensions(1) = 1;\n              }\n              break;\n\n            default:\n              new_dimensions.resize (k);\n              break;\n            }\n        }\n\n      retval = Array<T, Alloc> (*this, new_dimensions);\n    }\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\noctave_idx_type\nArray<T, Alloc>::compute_index (octave_idx_type i, octave_idx_type j) const\n{\n  return ::compute_index (i, j, m_dimensions);\n}\n\ntemplate <typename T, typename Alloc>\noctave_idx_type\nArray<T, Alloc>::compute_index (octave_idx_type i, octave_idx_type j,\n                                octave_idx_type k) const\n{\n  return ::compute_index (i, j, k, m_dimensions);\n}\n\ntemplate <typename T, typename Alloc>\noctave_idx_type\nArray<T, Alloc>::compute_index (const Array<octave_idx_type>& ra_idx) const\n{\n  return ::compute_index (ra_idx, m_dimensions);\n}\n\ntemplate <typename T, typename Alloc>\noctave_idx_type\nArray<T, Alloc>::compute_index_unchecked (const Array<octave_idx_type>& ra_idx) const\n{\n  return m_dimensions.compute_index (ra_idx.data (), ra_idx.numel ());\n}\n\ntemplate <typename T, typename Alloc>\nT&\nArray<T, Alloc>::checkelem (octave_idx_type n)\n{\n  // Do checks directly to avoid recomputing m_slice_len.\n  if (n < 0)\n    octave::err_invalid_index (n);\n  if (n >= m_slice_len)\n    octave::err_index_out_of_range (1, 1, n+1, m_slice_len, m_dimensions);\n\n  return elem (n);\n}\n\ntemplate <typename T, typename Alloc>\nT&\nArray<T, Alloc>::checkelem (octave_idx_type i, octave_idx_type j)\n{\n  return elem (compute_index (i, j));\n}\n\ntemplate <typename T, typename Alloc>\nT&\nArray<T, Alloc>::checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k)\n{\n  return elem (compute_index (i, j, k));\n}\n\ntemplate <typename T, typename Alloc>\nT&\nArray<T, Alloc>::checkelem (const Array<octave_idx_type>& ra_idx)\n{\n  return elem (compute_index (ra_idx));\n}\n\ntemplate <typename T, typename Alloc>\ntypename Array<T, Alloc>::crefT\nArray<T, Alloc>::checkelem (octave_idx_type n) const\n{\n  // Do checks directly to avoid recomputing m_slice_len.\n  if (n < 0)\n    octave::err_invalid_index (n);\n  if (n >= m_slice_len)\n    octave::err_index_out_of_range (1, 1, n+1, m_slice_len, m_dimensions);\n\n  return elem (n);\n}\n\ntemplate <typename T, typename Alloc>\ntypename Array<T, Alloc>::crefT\nArray<T, Alloc>::checkelem (octave_idx_type i, octave_idx_type j) const\n{\n  return elem (compute_index (i, j));\n}\n\ntemplate <typename T, typename Alloc>\ntypename Array<T, Alloc>::crefT\nArray<T, Alloc>::checkelem (octave_idx_type i, octave_idx_type j,\n                            octave_idx_type k) const\n{\n  return elem (compute_index (i, j, k));\n}\n\ntemplate <typename T, typename Alloc>\ntypename Array<T, Alloc>::crefT\nArray<T, Alloc>::checkelem (const Array<octave_idx_type>& ra_idx) const\n{\n  return elem (compute_index (ra_idx));\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::column (octave_idx_type k) const\n{\n  octave_idx_type r = m_dimensions(0);\n\n  return Array<T, Alloc> (*this, dim_vector (r, 1), k*r, k*r + r);\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::page (octave_idx_type k) const\n{\n  octave_idx_type r = m_dimensions(0);\n  octave_idx_type c = m_dimensions(1);\n  octave_idx_type p = r*c;\n\n  return Array<T, Alloc> (*this, dim_vector (r, c), k*p, k*p + p);\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::linear_slice (octave_idx_type lo, octave_idx_type up) const\n{\n  if (up < lo)\n    up = lo;\n\n  return Array<T, Alloc> (*this, dim_vector (up - lo, 1), lo, up);\n}\n\n// Helper class for multi-d dimension permuting (generalized transpose).\nclass rec_permute_helper\n{\npublic:\n\n  rec_permute_helper (const dim_vector& dv, const Array<octave_idx_type>& perm)\n\n    : m_n (dv.ndims ()), m_top (0), m_dim (new octave_idx_type [2*m_n]),\n      m_stride (m_dim + m_n), m_use_blk (false)\n  {\n    liboctave_panic_unless (m_n == perm.numel ());\n\n    // Get cumulative dimensions.\n    OCTAVE_LOCAL_BUFFER (octave_idx_type, cdim, m_n+1);\n    cdim[0] = 1;\n    for (int i = 1; i < m_n+1; i++) cdim[i] = cdim[i-1] * dv(i-1);\n\n    // Setup the permuted strides.\n    for (int k = 0; k < m_n; k++)\n      {\n        int kk = perm(k);\n        m_dim[k] = dv(kk);\n        m_stride[k] = cdim[kk];\n      }\n\n    // Reduce contiguous runs.\n    for (int k = 1; k < m_n; k++)\n      {\n        if (m_stride[k] == m_stride[m_top]*m_dim[m_top])\n          m_dim[m_top] *= m_dim[k];\n        else\n          {\n            m_top++;\n            m_dim[m_top] = m_dim[k];\n            m_stride[m_top] = m_stride[k];\n          }\n      }\n\n    // Determine whether we can use block transposes.\n    m_use_blk = m_top >= 1 && m_stride[1] == 1 && m_stride[0] == m_dim[1];\n\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (rec_permute_helper)\n\n  ~rec_permute_helper () { delete [] m_dim; }\n\n  template <typename T>\n  void permute (const T *src, T *dest) const { do_permute (src, dest, m_top); }\n\n  // Helper method for fast blocked transpose.\n  template <typename T>\n  static T *\n  blk_trans (const T *src, T *dest, octave_idx_type nr, octave_idx_type nc)\n  {\n    static const octave_idx_type m = 8;\n    OCTAVE_LOCAL_BUFFER (T, blk, m*m);\n    for (octave_idx_type kr = 0; kr < nr; kr += m)\n      for (octave_idx_type kc = 0; kc < nc; kc += m)\n        {\n          octave_idx_type lr = std::min (m, nr - kr);\n          octave_idx_type lc = std::min (m, nc - kc);\n          if (lr == m && lc == m)\n            {\n              const T *ss = src + kc * nr + kr;\n              for (octave_idx_type j = 0; j < m; j++)\n                for (octave_idx_type i = 0; i < m; i++)\n                  blk[j*m+i] = ss[j*nr + i];\n              T *dd = dest + kr * nc + kc;\n              for (octave_idx_type j = 0; j < m; j++)\n                for (octave_idx_type i = 0; i < m; i++)\n                  dd[j*nc+i] = blk[i*m+j];\n            }\n          else\n            {\n              const T *ss = src + kc * nr + kr;\n              for (octave_idx_type j = 0; j < lc; j++)\n                for (octave_idx_type i = 0; i < lr; i++)\n                  blk[j*m+i] = ss[j*nr + i];\n              T *dd = dest + kr * nc + kc;\n              for (octave_idx_type j = 0; j < lr; j++)\n                for (octave_idx_type i = 0; i < lc; i++)\n                  dd[j*nc+i] = blk[i*m+j];\n            }\n        }\n\n    return dest + nr*nc;\n  }\n\nprivate:\n\n  // Recursive N-D generalized transpose\n  template <typename T>\n  T * do_permute (const T *src, T *dest, int lev) const\n  {\n    if (lev == 0)\n      {\n        octave_idx_type step = m_stride[0];\n        octave_idx_type len = m_dim[0];\n        if (step == 1)\n          {\n            std::copy_n (src, len, dest);\n            dest += len;\n          }\n        else\n          {\n            for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)\n              dest[i] = src[j];\n\n            dest += len;\n          }\n      }\n    else if (m_use_blk && lev == 1)\n      dest = blk_trans (src, dest, m_dim[1], m_dim[0]);\n    else\n      {\n        octave_idx_type step = m_stride[lev];\n        octave_idx_type len = m_dim[lev];\n        for (octave_idx_type i = 0, j = 0; i < len; i++, j+= step)\n          dest = do_permute (src + j, dest, lev-1);\n      }\n\n    return dest;\n  }\n\n  //--------\n\n  // STRIDE occupies the last half of the space allocated for dim to\n  // avoid a double allocation.\n\n  int m_n;\n  int m_top;\n  octave_idx_type *m_dim;\n  octave_idx_type *m_stride;\n  bool m_use_blk;\n};\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::permute (const Array<octave_idx_type>& perm_vec_arg, bool inv) const\n{\n  Array<T, Alloc> retval;\n\n  Array<octave_idx_type> perm_vec = perm_vec_arg;\n\n  dim_vector dv = dims ();\n\n  int perm_vec_len = perm_vec_arg.numel ();\n\n  if (perm_vec_len < dv.ndims ())\n    (*current_liboctave_error_handler)\n      (\"%s: invalid permutation vector\", inv ? \"ipermute\" : \"permute\");\n\n  dim_vector dv_new = dim_vector::alloc (perm_vec_len);\n\n  // Append singleton dimensions as needed.\n  dv.resize (perm_vec_len, 1);\n\n  // Need this array to check for identical elements in permutation array.\n  OCTAVE_LOCAL_BUFFER_INIT (bool, checked, perm_vec_len, false);\n\n  bool identity = true;\n\n  // Find dimension vector of permuted array.\n  for (int i = 0; i < perm_vec_len; i++)\n    {\n      octave_idx_type perm_elt = perm_vec.elem (i);\n      if (perm_elt >= perm_vec_len || perm_elt < 0)\n        (*current_liboctave_error_handler)\n          (\"%s: permutation vector contains an invalid element\",\n           inv ? \"ipermute\" : \"permute\");\n\n      if (checked[perm_elt])\n        (*current_liboctave_error_handler)\n          (\"%s: permutation vector cannot contain identical elements\",\n           inv ? \"ipermute\" : \"permute\");\n      else\n        {\n          checked[perm_elt] = true;\n          identity = identity && perm_elt == i;\n        }\n    }\n\n  if (identity)\n    return *this;\n\n  if (inv)\n    {\n      for (int i = 0; i < perm_vec_len; i++)\n        perm_vec(perm_vec_arg(i)) = i;\n    }\n\n  for (int i = 0; i < perm_vec_len; i++)\n    dv_new(i) = dv(perm_vec(i));\n\n  retval = Array<T, Alloc> (dv_new);\n\n  if (numel () > 0)\n    {\n      rec_permute_helper rh (dv, perm_vec);\n      rh.permute (data (), retval.rwdata ());\n    }\n\n  return retval;\n}\n\n// Helper class for multi-d index reduction and recursive\n// indexing/indexed assignment.  Rationale: we could avoid recursion\n// using a state machine instead.  However, using recursion is much\n// more amenable to possible parallelization in the future.\n// Also, the recursion solution is cleaner and more understandable.\n\nclass rec_index_helper\n{\npublic:\n\n  rec_index_helper (const dim_vector& dv, const Array<octave::idx_vector>& ia)\n    : m_n (ia.numel ()), m_top (0), m_dim (new octave_idx_type [2*m_n]),\n      m_cdim (m_dim + m_n), m_idx (new octave::idx_vector [m_n])\n  {\n    liboctave_panic_unless (m_n > 0 && dv.ndims () == std::max (m_n, static_cast<octave_idx_type> (2)));\n\n    m_dim[0] = dv(0);\n    m_cdim[0] = 1;\n    m_idx[0] = ia(0);\n\n    for (octave_idx_type i = 1; i < m_n; i++)\n      {\n        // Try reduction...\n        if (m_idx[m_top].maybe_reduce (m_dim[m_top], ia(i), dv(i)))\n          {\n            // Reduction successful, fold dimensions.\n            m_dim[m_top] *= dv(i);\n          }\n        else\n          {\n            // Unsuccessful, store index & cumulative m_dim.\n            m_top++;\n            m_idx[m_top] = ia(i);\n            m_dim[m_top] = dv(i);\n            m_cdim[m_top] = m_cdim[m_top-1] * m_dim[m_top-1];\n          }\n      }\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (rec_index_helper)\n\n  ~rec_index_helper () { delete [] m_idx; delete [] m_dim; }\n\n  template <typename T>\n  void index (const T *src, T *dest) const { do_index (src, dest, m_top); }\n\n  template <typename T>\n  void assign (const T *src, T *dest) const { do_assign (src, dest, m_top); }\n\n  template <typename T>\n  void fill (const T& val, T *dest) const { do_fill (val, dest, m_top); }\n\n  bool is_cont_range (octave_idx_type& l, octave_idx_type& u) const\n  {\n    return m_top == 0 && m_idx[0].is_cont_range (m_dim[0], l, u);\n  }\n\nprivate:\n\n  // Recursive N-D indexing\n  template <typename T>\n  T * do_index (const T *src, T *dest, octave_idx_type lev) const\n  {\n    if (lev == 0)\n      dest += m_idx[0].index (src, m_dim[0], dest);\n    else\n      {\n        octave_idx_type nn = m_idx[lev].length (m_dim[lev]);\n        octave_idx_type d = m_cdim[lev];\n        for (octave_idx_type i = 0; i < nn; i++)\n          dest = do_index (src + d*m_idx[lev].xelem (i), dest, lev-1);\n      }\n\n    return dest;\n  }\n\n  // Recursive N-D indexed assignment\n  template <typename T>\n  const T * do_assign (const T *src, T *dest, octave_idx_type lev) const\n  {\n    if (lev == 0)\n      src += m_idx[0].assign (src, m_dim[0], dest);\n    else\n      {\n        octave_idx_type nn = m_idx[lev].length (m_dim[lev]);\n        octave_idx_type d = m_cdim[lev];\n        for (octave_idx_type i = 0; i < nn; i++)\n          src = do_assign (src, dest + d*m_idx[lev].xelem (i), lev-1);\n      }\n\n    return src;\n  }\n\n  // Recursive N-D indexed assignment\n  template <typename T>\n  void do_fill (const T& val, T *dest, octave_idx_type lev) const\n  {\n    if (lev == 0)\n      m_idx[0].fill (val, m_dim[0], dest);\n    else\n      {\n        octave_idx_type nn = m_idx[lev].length (m_dim[lev]);\n        octave_idx_type d = m_cdim[lev];\n        for (octave_idx_type i = 0; i < nn; i++)\n          do_fill (val, dest + d*m_idx[lev].xelem (i), lev-1);\n      }\n  }\n\n  //--------\n\n  // CDIM occupies the last half of the space allocated for dim to\n  // avoid a double allocation.\n\n  octave_idx_type m_n;\n  octave_idx_type m_top;\n  octave_idx_type *m_dim;\n  octave_idx_type *m_cdim;\n  octave::idx_vector *m_idx;\n};\n\n// Helper class for multi-d recursive resizing\n// This handles resize () in an efficient manner, touching memory only\n// once (apart from reinitialization)\nclass rec_resize_helper\n{\npublic:\n\n  rec_resize_helper (const dim_vector& ndv, const dim_vector& odv)\n    : m_cext (nullptr), m_sext (nullptr), m_dext (nullptr), m_n (0)\n  {\n    int l = ndv.ndims ();\n    liboctave_panic_unless (odv.ndims () == l);\n    octave_idx_type ld = 1;\n    int i = 0;\n    for (; i < l-1 && ndv(i) == odv(i); i++) ld *= ndv(i);\n    m_n = l - i;\n    m_cext = new octave_idx_type [3*m_n];\n    // Trick to avoid three allocations\n    m_sext = m_cext + m_n;\n    m_dext = m_sext + m_n;\n\n    octave_idx_type sld = ld;\n    octave_idx_type dld = ld;\n    for (int j = 0; j < m_n; j++)\n      {\n        m_cext[j] = std::min (ndv(i+j), odv(i+j));\n        m_sext[j] = sld *= odv(i+j);\n        m_dext[j] = dld *= ndv(i+j);\n      }\n    m_cext[0] *= ld;\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (rec_resize_helper)\n\n  ~rec_resize_helper () { delete [] m_cext; }\n\n  template <typename T>\n  void resize_fill (const T *src, T *dest, const T& rfv) const\n  { do_resize_fill (src, dest, rfv, m_n-1); }\n\nprivate:\n\n  // recursive resizing\n  template <typename T>\n  void do_resize_fill (const T *src, T *dest, const T& rfv, int lev) const\n  {\n    if (lev == 0)\n      {\n        std::copy_n (src, m_cext[0], dest);\n        std::fill_n (dest + m_cext[0], m_dext[0] - m_cext[0], rfv);\n      }\n    else\n      {\n        octave_idx_type sd, dd, k;\n        sd = m_sext[lev-1];\n        dd = m_dext[lev-1];\n        for (k = 0; k < m_cext[lev]; k++)\n          do_resize_fill (src + k * sd, dest + k * dd, rfv, lev - 1);\n\n        std::fill_n (dest + k * dd, m_dext[lev] - k * dd, rfv);\n      }\n  }\n\n  //--------\n\n  octave_idx_type *m_cext;\n  octave_idx_type *m_sext;\n  octave_idx_type *m_dext;\n  int m_n;\n};\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::index (const octave::idx_vector& i) const\n{\n  // Colon:\n  //\n  //   object   | index    | result orientation\n  //   ---------+----------+-------------------\n  //   anything | colon    | column vector\n  //\n  // Numeric array or logical mask:\n  //\n  //   Note that logical mask indices are always transformed to vectors\n  //   before we see them.\n  //\n  //   object   | index    | result orientation\n  //   ---------+----------+-------------------\n  //   vector   | vector   | indexed object\n  //            | other    | same size as index\n  //   ---------+----------+-------------------\n  //   array    | anything | same size as index\n\n  octave_idx_type n = numel ();\n  Array<T, Alloc> retval;\n\n  if (i.is_colon ())\n    {\n      // A(:) produces a shallow copy as a column vector.\n      retval = Array<T, Alloc> (*this, dim_vector (n, 1));\n    }\n  else\n    {\n      if (i.extent (n) != n)\n        octave::err_index_out_of_range (1, 1, i.extent (n), n, m_dimensions);\n\n      dim_vector result_dims = i.orig_dimensions ();\n      octave_idx_type idx_len = i.length ();\n\n      if (n != 1 && is_nd_vector () && idx_len != 1\n          && result_dims.is_nd_vector ())\n        {\n          // Indexed object and index are both vectors.  Set result size\n          // and orientation as above.\n\n          const dim_vector& dv = dims ();\n\n          result_dims = dv.make_nd_vector (idx_len);\n        }\n\n      octave_idx_type l, u;\n      if (idx_len != 0 && i.is_cont_range (n, l, u))\n        // If suitable, produce a shallow slice.\n        retval = Array<T, Alloc> (*this, result_dims, l, u);\n      else\n        {\n          // Don't use resize here to avoid useless initialization for POD\n          // types.\n          retval = Array<T, Alloc> (result_dims);\n\n          if (idx_len != 0)\n            i.index (data (), n, retval.rwdata ());\n        }\n    }\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::index (const octave::idx_vector& i, const octave::idx_vector& j) const\n{\n  // Get dimensions, allowing Fortran indexing in the 2nd dim.\n  const dim_vector& dv = m_dimensions.redim (2);\n  octave_idx_type r = dv(0);\n  octave_idx_type c = dv(1);\n  Array<T, Alloc> retval;\n\n  if (i.is_colon () && j.is_colon ())\n    {\n      // A(:,:) produces a shallow copy.\n      retval = Array<T, Alloc> (*this, dv);\n    }\n  else\n    {\n      if (i.extent (r) != r)\n        octave::err_index_out_of_range (2, 1, i.extent (r), r, m_dimensions); // throws\n      if (j.extent (c) != c)\n        octave::err_index_out_of_range (2, 2, j.extent (c), c, m_dimensions); // throws\n\n      octave_idx_type n = numel ();\n      octave_idx_type il = i.length (r);\n      octave_idx_type jl = j.length (c);\n\n      octave::idx_vector ii (i);\n\n      if (ii.maybe_reduce (r, j, c))\n        {\n          octave_idx_type l, u;\n          if (ii.length () > 0 && ii.is_cont_range (n, l, u))\n            // If suitable, produce a shallow slice.\n            retval = Array<T, Alloc> (*this, dim_vector (il, jl), l, u);\n          else\n            {\n              // Don't use resize to avoid useless initialization for POD types.\n              retval = Array<T, Alloc> (dim_vector (il, jl));\n\n              ii.index (data (), n, retval.rwdata ());\n            }\n        }\n      else\n        {\n          // Don't use resize to avoid useless initialization for POD types.\n          retval = Array<T, Alloc> (dim_vector (il, jl));\n\n          const T *src = data ();\n          T *dest = retval.rwdata ();\n\n          for (octave_idx_type k = 0; k < jl; k++)\n            dest += i.index (src + r * j.xelem (k), r, dest);\n        }\n    }\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::index (const Array<octave::idx_vector>& ia) const\n{\n  int ial = ia.numel ();\n  Array<T, Alloc> retval;\n\n  // FIXME: is this dispatching necessary?\n  if (ial == 1)\n    retval = index (ia(0));\n  else if (ial == 2)\n    retval = index (ia(0), ia(1));\n  else if (ial > 0)\n    {\n      // Get dimensions, allowing Fortran indexing in the last dim.\n      dim_vector dv = m_dimensions.redim (ial);\n\n      // Check for out of bounds conditions.\n      bool all_colons = true;\n      for (int i = 0; i < ial; i++)\n        {\n          if (ia(i).extent (dv(i)) != dv(i))\n            octave::err_index_out_of_range (ial, i+1, ia(i).extent (dv(i)), dv(i),\n                                            m_dimensions); // throws\n\n          all_colons = all_colons && ia(i).is_colon ();\n        }\n\n      if (all_colons)\n        {\n          // A(:,:,...,:) produces a shallow copy.\n          dv.chop_trailing_singletons ();\n          retval = Array<T, Alloc> (*this, dv);\n        }\n      else\n        {\n          // Form result dimensions.\n          dim_vector rdv = dim_vector::alloc (ial);\n          for (int i = 0; i < ial; i++) rdv(i) = ia(i).length (dv(i));\n          rdv.chop_trailing_singletons ();\n\n          // Prepare for recursive indexing\n          rec_index_helper rh (dv, ia);\n\n          octave_idx_type l, u;\n          if (rh.is_cont_range (l, u))\n            // If suitable, produce a shallow slice.\n            retval = Array<T, Alloc> (*this, rdv, l, u);\n          else\n            {\n              // Don't use resize to avoid useless initialization for POD types.\n              retval = Array<T, Alloc> (rdv);\n\n              // Do it.\n              rh.index (data (), retval.rwdata ());\n            }\n        }\n    }\n\n  return retval;\n}\n\n// The default fill value.  Override if you want a different one.\n\ntemplate <typename T, typename Alloc>\nT\nArray<T, Alloc>::resize_fill_value () const\n{\n  static T zero = T ();\n  return zero;\n}\n\n// Yes, we could do resize using index & assign.  However, that would\n// possibly involve a lot more memory traffic than we actually need.\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::resize1 (octave_idx_type n, const T& rfv)\n{\n  if (n < 0 || ndims () != 2)\n    octave::err_invalid_resize ();\n\n  dim_vector dv;\n  // This is driven by Matlab's behavior of giving a *row* vector\n  // on some out-of-bounds assignments.  Specifically, Matlab\n  // allows a(i) with out-of-bouds i when a is either of 0x0, 1x0,\n  // 1x1, 0xN, and gives a row vector in all cases (yes, even the\n  // last one, search me why).  Giving a column vector would make\n  // much more sense (given the way trailing singleton dims are\n  // treated).\n  bool invalid = false;\n  if (rows () == 0 || rows () == 1)\n    dv = dim_vector (1, n);\n  else if (columns () == 1)\n    dv = dim_vector (n, 1);\n  else\n    invalid = true;\n\n  if (invalid)\n    octave::err_invalid_resize ();\n\n  octave_idx_type nx = numel ();\n  if (n == nx - 1 && n > 0)\n    {\n      // Stack \"pop\" operation.\n      if (m_rep->m_count == 1)\n        m_slice_data[m_slice_len-1] = T ();\n      m_slice_len--;\n      m_dimensions = dv;\n    }\n  else if (n == nx + 1 && nx > 0)\n    {\n      // Stack \"push\" operation.\n      if (m_rep->m_count == 1\n          && m_slice_data + m_slice_len < m_rep->m_data + m_rep->m_len)\n        {\n          m_slice_data[m_slice_len++] = rfv;\n          m_dimensions = dv;\n        }\n      else\n        {\n          static const octave_idx_type MAX_STACK_CHUNK = 1024;\n          octave_idx_type nn = n + std::min (nx, MAX_STACK_CHUNK);\n          Array<T, Alloc> tmp (Array<T, Alloc> (dim_vector (nn, 1)), dv, 0, n);\n          T *dest = tmp.rwdata ();\n\n          std::copy_n (data (), nx, dest);\n          dest[nx] = rfv;\n\n          *this = tmp;\n        }\n    }\n  else if (n != nx)\n    {\n      Array<T, Alloc> tmp = Array<T, Alloc> (dv);\n      T *dest = tmp.rwdata ();\n\n      octave_idx_type n0 = std::min (n, nx);\n      octave_idx_type n1 = n - n0;\n      std::copy_n (data (), n0, dest);\n      std::fill_n (dest + n0, n1, rfv);\n\n      *this = tmp;\n    }\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::resize2 (octave_idx_type r, octave_idx_type c, const T& rfv)\n{\n  if (r < 0 || c < 0 || ndims () != 2)\n    octave::err_invalid_resize ();\n\n  octave_idx_type rx = rows ();\n  octave_idx_type cx = columns ();\n  if (r != rx || c != cx)\n    {\n      Array<T, Alloc> tmp = Array<T, Alloc> (dim_vector (r, c));\n      T *dest = tmp.rwdata ();\n\n      octave_idx_type r0 = std::min (r, rx);\n      octave_idx_type r1 = r - r0;\n      octave_idx_type c0 = std::min (c, cx);\n      octave_idx_type c1 = c - c0;\n      const T *src = data ();\n      if (r == rx)\n        {\n          std::copy_n (src, r * c0, dest);\n          dest += r * c0;\n        }\n      else\n        {\n          for (octave_idx_type k = 0; k < c0; k++)\n            {\n              std::copy_n (src, r0, dest);\n              src += rx;\n              dest += r0;\n              std::fill_n (dest, r1, rfv);\n              dest += r1;\n            }\n        }\n\n      std::fill_n (dest, r * c1, rfv);\n\n      *this = tmp;\n    }\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::resize (const dim_vector& dv, const T& rfv)\n{\n  int dvl = dv.ndims ();\n  if (dvl == 2)\n    resize2 (dv(0), dv(1), rfv);\n  else if (m_dimensions != dv)\n    {\n      if (m_dimensions.ndims () > dvl || dv.any_neg ())\n        octave::err_invalid_resize ();\n\n      Array<T, Alloc> tmp (dv);\n      // Prepare for recursive resizing.\n      rec_resize_helper rh (dv, m_dimensions.redim (dvl));\n\n      // Do it.\n      rh.resize_fill (data (), tmp.rwdata (), rfv);\n      *this = tmp;\n    }\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::index (const octave::idx_vector& i, bool resize_ok, const T& rfv) const\n{\n  Array<T, Alloc> tmp = *this;\n  if (resize_ok)\n    {\n      octave_idx_type n = numel ();\n      octave_idx_type nx = i.extent (n);\n      if (n != nx)\n        {\n          if (i.is_scalar ())\n            return Array<T, Alloc> (dim_vector (1, 1), rfv);\n          else\n            tmp.resize1 (nx, rfv);\n        }\n\n      if (tmp.numel () != nx)\n        return Array<T, Alloc> ();\n    }\n\n  return tmp.index (i);\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::index (const octave::idx_vector& i, const octave::idx_vector& j,\n                        bool resize_ok, const T& rfv) const\n{\n  Array<T, Alloc> tmp = *this;\n  if (resize_ok)\n    {\n      const dim_vector& dv = m_dimensions.redim (2);\n      octave_idx_type r = dv(0);\n      octave_idx_type c = dv(1);\n      octave_idx_type rx = i.extent (r);\n      octave_idx_type cx = j.extent (c);\n      if (r != rx || c != cx)\n        {\n          if (i.is_scalar () && j.is_scalar ())\n            return Array<T, Alloc> (dim_vector (1, 1), rfv);\n          else\n            tmp.resize2 (rx, cx, rfv);\n        }\n\n      if (tmp.rows () != rx || tmp.columns () != cx)\n        return Array<T, Alloc> ();\n    }\n\n  return tmp.index (i, j);\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::index (const Array<octave::idx_vector>& ia,\n                        bool resize_ok, const T& rfv) const\n{\n  Array<T, Alloc> tmp = *this;\n  if (resize_ok)\n    {\n      int ial = ia.numel ();\n      const dim_vector& dv = m_dimensions.redim (ial);\n      dim_vector dvx = dim_vector::alloc (ial);\n      // Set initial number of columns to 1.  Necessary if ial is 1 because all\n      // Octave arrays (including column vectors) have at least two dimensions.\n      dvx(1) = 1;\n      for (int i = 0; i < ial; i++)\n        dvx(i) = ia(i).extent (dv(i));\n      if (! (dvx == dv))\n        {\n          bool all_scalars = true;\n          for (int i = 0; i < ial; i++)\n            all_scalars = all_scalars && ia(i).is_scalar ();\n          if (all_scalars)\n            return Array<T, Alloc> (dim_vector (1, 1), rfv);\n          else\n            tmp.resize (dvx, rfv);\n\n          if (tmp.m_dimensions != dvx)\n            return Array<T, Alloc> ();\n        }\n    }\n\n  return tmp.index (ia);\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::index (const Array<octave::idx_vector>& ia, bool resize_ok) const\n{\n  return index (ia, resize_ok, resize_fill_value ());\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::assign (const octave::idx_vector& i, const Array<T, Alloc>& rhs, const T& rfv)\n{\n  octave_idx_type n = numel ();\n  octave_idx_type rhl = rhs.numel ();\n\n  if (rhl != 1 && i.length (n) != rhl)\n    octave::err_nonconformant (\"=\", dim_vector(i.length(n), 1), rhs.dims());\n\n  octave_idx_type nx = i.extent (n);\n  bool colon = i.is_colon_equiv (nx);\n  // Try to resize first if necessary.\n  if (nx != n)\n    {\n      // Optimize case A = []; A(1:n) = X with A empty.\n      if (m_dimensions.zero_by_zero () && colon)\n        {\n          if (rhl == 1)\n            *this = Array<T, Alloc> (dim_vector (1, nx), rhs(0));\n          else\n            *this = Array<T, Alloc> (rhs, dim_vector (1, nx));\n          return;\n        }\n\n      resize1 (nx, rfv);\n      n = numel ();\n    }\n\n  if (colon)\n    {\n      // A(:) = X makes a full fill or a shallow copy.\n      if (rhl == 1)\n        fill (rhs(0));\n      else\n        *this = rhs.reshape (m_dimensions);\n    }\n  else\n    {\n      if (rhl == 1)\n        i.fill (rhs(0), n, rwdata ());\n      else\n        i.assign (rhs.data (), n, rwdata ());\n    }\n}\n\n// Assignment to a 2-dimensional array\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::assign (const octave::idx_vector& i, const octave::idx_vector& j,\n                         const Array<T, Alloc>& rhs, const T& rfv)\n{\n  bool initial_dims_all_zero = m_dimensions.all_zero ();\n\n  // Get RHS extents, discarding singletons.\n  dim_vector rhdv = rhs.dims ();\n\n  // Get LHS extents, allowing Fortran indexing in the second dim.\n  dim_vector dv = m_dimensions.redim (2);\n\n  // Check for out-of-bounds and form resizing m_dimensions.\n  dim_vector rdv;\n\n  // In the special when all dimensions are zero, colons are allowed\n  // to inquire the shape of RHS.  The rules are more obscure, so we\n  // solve that elsewhere.\n  if (initial_dims_all_zero)\n    rdv = zero_dims_inquire (i, j, rhdv);\n  else\n    {\n      rdv(0) = i.extent (dv(0));\n      rdv(1) = j.extent (dv(1));\n    }\n\n  bool isfill = rhs.numel () == 1;\n  octave_idx_type il = i.length (rdv(0));\n  octave_idx_type jl = j.length (rdv(1));\n  rhdv.chop_all_singletons ();\n  bool match = (isfill\n                || (rhdv.ndims () == 2 && il == rhdv(0) && jl == rhdv(1)));\n  match = match || (il == 1 && jl == rhdv(0) && rhdv(1) == 1);\n\n  if (match)\n    {\n      bool all_colons = (i.is_colon_equiv (rdv(0))\n                         && j.is_colon_equiv (rdv(1)));\n      // Resize if requested.\n      if (rdv != dv)\n        {\n          // Optimize case A = []; A(1:m, 1:n) = X\n          if (dv.zero_by_zero () && all_colons)\n            {\n              if (isfill)\n                *this = Array<T, Alloc> (rdv, rhs(0));\n              else\n                *this = Array<T, Alloc> (rhs, rdv);\n              return;\n            }\n\n          resize (rdv, rfv);\n          dv = m_dimensions;\n        }\n\n      if (all_colons)\n        {\n          // A(:,:) = X makes a full fill or a shallow copy\n          if (isfill)\n            fill (rhs(0));\n          else\n            *this = rhs.reshape (m_dimensions);\n        }\n      else\n        {\n          // The actual work.\n          octave_idx_type n = numel ();\n          octave_idx_type r = dv(0);\n          octave_idx_type c = dv(1);\n          octave::idx_vector ii (i);\n\n          const T *src = rhs.data ();\n          T *dest = rwdata ();\n\n          // Try reduction first.\n          if (ii.maybe_reduce (r, j, c))\n            {\n              if (isfill)\n                ii.fill (*src, n, dest);\n              else\n                ii.assign (src, n, dest);\n            }\n          else\n            {\n              if (isfill)\n                {\n                  for (octave_idx_type k = 0; k < jl; k++)\n                    i.fill (*src, r, dest + r * j.xelem (k));\n                }\n              else\n                {\n                  for (octave_idx_type k = 0; k < jl; k++)\n                    src += i.assign (src, r, dest + r * j.xelem (k));\n                }\n            }\n        }\n    }\n  // any empty RHS can be assigned to an empty LHS\n  else if ((il != 0 && jl != 0) || (rhdv(0) != 0 && rhdv(1) != 0))\n    octave::err_nonconformant (\"=\", il, jl, rhs.dim1 (), rhs.dim2 ());\n}\n\n// Assignment to a multi-dimensional array\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::assign (const Array<octave::idx_vector>& ia,\n                         const Array<T, Alloc>& rhs, const T& rfv)\n{\n  int ial = ia.numel ();\n\n  // FIXME: is this dispatching necessary / desirable?\n  if (ial == 1)\n    assign (ia(0), rhs, rfv);\n  else if (ial == 2)\n    assign (ia(0), ia(1), rhs, rfv);\n  else if (ial > 0)\n    {\n      bool initial_dims_all_zero = m_dimensions.all_zero ();\n\n      // Get RHS extents, discarding trailing singletons.\n      dim_vector rhdv = rhs.dims ();\n\n      // Get LHS extents, allowing Fortran indexing in the second dim.\n      dim_vector dv = m_dimensions.redim (ial);\n\n      // Get the extents forced by indexing.\n      dim_vector rdv;\n\n      // In the special when all dimensions are zero, colons are\n      // allowed to inquire the shape of RHS.  The rules are more\n      // obscure, so we solve that elsewhere.\n      if (initial_dims_all_zero)\n        rdv = zero_dims_inquire (ia, rhdv);\n      else\n        {\n          rdv = dim_vector::alloc (ial);\n          for (int i = 0; i < ial; i++)\n            rdv(i) = ia(i).extent (dv(i));\n        }\n\n      // Check whether LHS and RHS match, up to singleton dims.\n      bool match = true;\n      bool all_colons = true;\n      bool isfill = rhs.numel () == 1;\n\n      rhdv.chop_all_singletons ();\n      int j = 0;\n      int rhdvl = rhdv.ndims ();\n      for (int i = 0; i < ial; i++)\n        {\n          all_colons = all_colons && ia(i).is_colon_equiv (rdv(i));\n          octave_idx_type l = ia(i).length (rdv(i));\n          if (l == 1) continue;\n          match = match && j < rhdvl && l == rhdv(j++);\n        }\n\n      match = match && (j == rhdvl || rhdv(j) == 1);\n      match = match || isfill;\n\n      if (match)\n        {\n          // Resize first if necessary.\n          if (rdv != dv)\n            {\n              // Optimize case A = []; A(1:m, 1:n) = X\n              if (dv.zero_by_zero () && all_colons)\n                {\n                  rdv.chop_trailing_singletons ();\n                  if (isfill)\n                    *this = Array<T, Alloc> (rdv, rhs(0));\n                  else\n                    *this = Array<T, Alloc> (rhs, rdv);\n                  return;\n                }\n\n              resize (rdv, rfv);\n              dv = rdv;\n            }\n\n          if (all_colons)\n            {\n              // A(:,:,...,:) = X makes a full fill or a shallow copy.\n              if (isfill)\n                fill (rhs(0));\n              else\n                *this = rhs.reshape (m_dimensions);\n            }\n          else\n            {\n              // Do the actual work.\n\n              // Prepare for recursive indexing\n              rec_index_helper rh (dv, ia);\n\n              // Do it.\n              if (isfill)\n                rh.fill (rhs(0), rwdata ());\n              else\n                rh.assign (rhs.data (), rwdata ());\n            }\n        }\n      else\n        {\n          // dimension mismatch, unless LHS and RHS both empty\n          bool lhsempty, rhsempty;\n          lhsempty = false;\n          dim_vector lhs_dv = dim_vector::alloc (ial);\n          for (int i = 0; i < ial; i++)\n            {\n              octave_idx_type l = ia(i).length (rdv(i));\n              lhs_dv(i) = l;\n              lhsempty = lhsempty || (l == 0);\n            }\n          rhsempty = rhdv.any_zero ();\n          if (! lhsempty || ! rhsempty)\n            {\n              lhs_dv.chop_trailing_singletons ();\n              rhdv = rhs.dims ();\n              rhdv.chop_trailing_singletons ();\n              octave::err_nonconformant (\"=\", lhs_dv, rhdv);\n            }\n        }\n    }\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::assign (const Array<octave::idx_vector>& ia,\n                         const Array<T, Alloc>& rhs)\n{\n  assign (ia, rhs, resize_fill_value ());\n}\n\n/*\n%!shared a\n%! a = [1 2; 3 4];\n%!error <op1 is 1x2, op2 is 1x3> a(1,:) = [1 2 3]\n%!error <op1 is 2x1, op2 is 1x3> a(:,1) = [1 2 3]\n%!error <op1 is 2x2, op2 is 2x1> a(1:2,2:3) = [1;2]\n*/\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::delete_elements (const octave::idx_vector& i)\n{\n  octave_idx_type n = numel ();\n  if (i.is_colon ())\n    {\n      *this = Array<T, Alloc> ();\n    }\n  else if (i.length (n) != 0)\n    {\n      if (i.extent (n) != n)\n        octave::err_del_index_out_of_range (true, i.extent (n), n);\n\n      octave_idx_type l, u;\n      bool col_vec = ndims () == 2 && columns () == 1 && rows () != 1;\n      if (i.is_scalar () && i(0) == n-1 && m_dimensions.isvector ())\n        {\n          // Stack \"pop\" operation.\n          resize1 (n-1);\n        }\n      else if (i.is_cont_range (n, l, u))\n        {\n          // Special case deleting a contiguous range.\n          octave_idx_type m = n + l - u;\n          Array<T, Alloc> tmp (dim_vector (col_vec ? m : 1, ! col_vec ? m : 1));\n          const T *src = data ();\n          T *dest = tmp.rwdata ();\n          std::copy_n (src, l, dest);\n          std::copy (src + u, src + n, dest + l);\n          *this = tmp;\n        }\n      else\n        {\n          // Use index.\n          *this = index (i.complement (n));\n        }\n    }\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::delete_elements (int dim, const octave::idx_vector& i)\n{\n  if (dim < 0)\n    (*current_liboctave_error_handler) (\"invalid dimension in delete_elements\");\n\n  dim_vector dimensions = m_dimensions;\n\n  if (dim >= ndims ())\n    dimensions.resize (dim + 1, 1);\n\n  octave_idx_type ndim = dimensions.ndims ();\n  octave_idx_type n = dimensions(dim);\n\n  if (i.is_colon ())\n    {\n      *this = Array<T, Alloc> ();\n    }\n  else if (i.length (n) != 0)\n    {\n      if (i.extent (n) != n)\n        octave::err_del_index_out_of_range (false, i.extent (n), n);\n\n      octave_idx_type l, u;\n\n      if (i.is_cont_range (n, l, u))\n        {\n          // Special case deleting a contiguous range.\n          octave_idx_type nd = n + l - u;\n          octave_idx_type dl = 1;\n          octave_idx_type du = 1;\n          dim_vector rdv = dimensions;\n          rdv(dim) = nd;\n          for (int k = 0; k < dim; k++) dl *= dimensions(k);\n          for (int k = dim + 1; k < ndim; k++) du *= dimensions(k);\n\n          // Special case deleting a contiguous range.\n          Array<T, Alloc> tmp = Array<T, Alloc> (rdv);\n          const T *src = data ();\n          T *dest = tmp.rwdata ();\n          l *= dl; u *= dl; n *= dl;\n          for (octave_idx_type k = 0; k < du; k++)\n            {\n              std::copy_n (src, l, dest);\n              dest += l;\n              std::copy (src + u, src + n, dest);\n              dest += n - u;\n              src += n;\n            }\n\n          *this = tmp;\n        }\n      else\n        {\n          // Use index.\n          Array<octave::idx_vector> ia (dim_vector (ndim, 1), octave::idx_vector::colon);\n          ia (dim) = i.complement (n);\n          *this = index (ia);\n        }\n    }\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::delete_elements (const Array<octave::idx_vector>& ia)\n{\n  int ial = ia.numel ();\n\n  if (ial == 1)\n    delete_elements (ia(0));\n  else\n    {\n      int k, dim = -1;\n      for (k = 0; k < ial; k++)\n        {\n          if (! ia(k).is_colon ())\n            {\n              if (dim < 0)\n                dim = k;\n              else\n                break;\n            }\n        }\n      if (dim < 0)\n        {\n          dim_vector dv = m_dimensions;\n          dv(0) = 0;\n          *this = Array<T, Alloc> (dv);\n        }\n      else if (k == ial)\n        {\n          delete_elements (dim, ia(dim));\n        }\n      else\n        {\n          // Allow the null assignment to succeed if it won't change\n          // anything because the indices reference an empty slice,\n          // provided that there is at most one non-colon (or\n          // equivalent) index.  So, we still have the requirement of\n          // deleting a slice, but it is OK if the slice is empty.\n\n          // For compatibility with Matlab, stop checking once we see\n          // more than one non-colon index or an empty index.  Matlab\n          // considers \"[]\" to be an empty index but not \"false\".  We\n          // accept both.\n\n          bool empty_assignment = false;\n\n          int num_non_colon_indices = 0;\n\n          int nd = ndims ();\n\n          for (int i = 0; i < ial; i++)\n            {\n              octave_idx_type dim_len = (i >= nd ? 1 : m_dimensions(i));\n\n              if (ia(i).length (dim_len) == 0)\n                {\n                  empty_assignment = true;\n                  break;\n                }\n\n              if (! ia(i).is_colon_equiv (dim_len))\n                {\n                  num_non_colon_indices++;\n\n                  if (num_non_colon_indices == 2)\n                    break;\n                }\n            }\n\n          if (! empty_assignment)\n            (*current_liboctave_error_handler)\n              (\"a null assignment can only have one non-colon index\");\n        }\n    }\n\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>&\nArray<T, Alloc>::insert (const Array<T, Alloc>& a, octave_idx_type r, octave_idx_type c)\n{\n  octave::idx_vector i (r, r + a.rows ());\n  octave::idx_vector j (c, c + a.columns ());\n  if (ndims () == 2 && a.ndims () == 2)\n    assign (i, j, a);\n  else\n    {\n      Array<octave::idx_vector> idx (dim_vector (a.ndims (), 1));\n      idx(0) = i;\n      idx(1) = j;\n      for (int k = 2; k < a.ndims (); k++)\n        idx(k) = octave::idx_vector (0, a.m_dimensions(k));\n      assign (idx, a);\n    }\n\n  return *this;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>&\nArray<T, Alloc>::insert (const Array<T, Alloc>& a, const Array<octave_idx_type>& ra_idx)\n{\n  octave_idx_type n = ra_idx.numel ();\n  Array<octave::idx_vector> idx (dim_vector (n, 1));\n  const dim_vector dva = a.dims ().redim (n);\n  for (octave_idx_type k = 0; k < n; k++)\n    idx(k) = octave::idx_vector (ra_idx(k), ra_idx(k) + dva(k));\n\n  assign (idx, a);\n\n  return *this;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::transpose () const\n{\n  liboctave_panic_unless (ndims () == 2);\n\n  octave_idx_type nr = dim1 ();\n  octave_idx_type nc = dim2 ();\n\n  if (nr >= 8 && nc >= 8)\n    {\n      Array<T, Alloc> result (dim_vector (nc, nr));\n\n      // Reuse the implementation used for permuting.\n\n      rec_permute_helper::blk_trans (data (), result.rwdata (), nr, nc);\n\n      return result;\n    }\n  else if (nr > 1 && nc > 1)\n    {\n      Array<T, Alloc> result (dim_vector (nc, nr));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          result.xelem (j, i) = xelem (i, j);\n\n      return result;\n    }\n  else\n    {\n      // Fast transpose for vectors and empty matrices.\n      return Array<T, Alloc> (*this, dim_vector (nc, nr));\n    }\n}\n\ntemplate <typename T>\nstatic T\nno_op_fcn (const T& x)\n{\n  return x;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::hermitian (T (*fcn) (const T&)) const\n{\n  liboctave_panic_unless (ndims () == 2);\n\n  if (! fcn)\n    fcn = no_op_fcn<T>;\n\n  octave_idx_type nr = dim1 ();\n  octave_idx_type nc = dim2 ();\n\n  if (nr >= 8 && nc >= 8)\n    {\n      Array<T, Alloc> result (dim_vector (nc, nr));\n\n      // Blocked transpose to attempt to avoid cache misses.\n\n      T buf[64];\n\n      octave_idx_type jj;\n      for (jj = 0; jj < (nc - 8 + 1); jj += 8)\n        {\n          octave_idx_type ii;\n          for (ii = 0; ii < (nr - 8 + 1); ii += 8)\n            {\n              // Copy to buffer\n              for (octave_idx_type j = jj, k = 0, idxj = jj * nr;\n                   j < jj + 8; j++, idxj += nr)\n                for (octave_idx_type i = ii; i < ii + 8; i++)\n                  buf[k++] = xelem (i + idxj);\n\n              // Copy from buffer\n              for (octave_idx_type i = ii, idxi = ii * nc; i < ii + 8;\n                   i++, idxi += nc)\n                for (octave_idx_type j = jj, k = i - ii; j < jj + 8;\n                     j++, k+=8)\n                  result.xelem (j + idxi) = fcn (buf[k]);\n            }\n\n          if (ii < nr)\n            for (octave_idx_type j = jj; j < jj + 8; j++)\n              for (octave_idx_type i = ii; i < nr; i++)\n                result.xelem (j, i) = fcn (xelem (i, j));\n        }\n\n      for (octave_idx_type j = jj; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          result.xelem (j, i) = fcn (xelem (i, j));\n\n      return result;\n    }\n  else\n    {\n      Array<T, Alloc> result (dim_vector (nc, nr));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          result.xelem (j, i) = fcn (xelem (i, j));\n\n      return result;\n    }\n}\n\n/*\n\n## Transpose tests for matrices of the tile size and plus or minus a row\n## and with four tiles.\n\n%!shared m7, mt7, m8, mt8, m9, mt9\n%! m7 = reshape (1 : 7*8, 8, 7);\n%! mt7 = [1:8; 9:16; 17:24; 25:32; 33:40; 41:48; 49:56];\n%! m8 = reshape (1 : 8*8, 8, 8);\n%! mt8 = mt8 = [mt7; 57:64];\n%! m9 = reshape (1 : 9*8, 8, 9);\n%! mt9 = [mt8; 65:72];\n\n%!assert (m7', mt7)\n%!assert ((1i*m7).', 1i * mt7)\n%!assert ((1i*m7)', conj (1i * mt7))\n%!assert (m8', mt8)\n%!assert ((1i*m8).', 1i * mt8)\n%!assert ((1i*m8)', conj (1i * mt8))\n%!assert (m9', mt9)\n%!assert ((1i*m9).', 1i * mt9)\n%!assert ((1i*m9)', conj (1i * mt9))\n%!assert ([m7, m8; m7, m8]', [mt7, mt7; mt8, mt8])\n%!assert ((1i*[m7, m8; m7, m8]).', 1i * [mt7, mt7; mt8, mt8])\n%!assert ((1i*[m7, m8; m7, m8])', conj (1i * [mt7, mt7; mt8, mt8]))\n%!assert ([m8, m8; m8, m8]', [mt8, mt8; mt8, mt8])\n%!assert ((1i*[m8, m8; m8, m8]).', 1i * [mt8, mt8; mt8, mt8])\n%!assert ((1i*[m8, m8; m8, m8])', conj (1i * [mt8, mt8; mt8, mt8]))\n%!assert ([m9, m8; m9, m8]', [mt9, mt9; mt8, mt8])\n%!assert ((1i*[m9, m8; m9, m8]).', 1i * [mt9, mt9; mt8, mt8])\n%!assert ((1i*[m9, m8; m9, m8])', conj (1i * [mt9, mt9; mt8, mt8]))\n\n*/\n\ntemplate <typename T, typename Alloc>\nT *\nArray<T, Alloc>::rwdata ()\n{\n  make_unique ();\n\n  return m_slice_data;\n}\n\n// Non-real types don't have NaNs.\ntemplate <typename T>\ninline bool\nsort_isnan (typename ref_param<T>::type)\n{\n  return false;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::sort (int dim, sortmode mode) const\n{\n  if (dim < 0)\n    (*current_liboctave_error_handler) (\"sort: invalid dimension\");\n\n  if (numel () < 1)  // input array is empty,\n    return *this;\n\n  if (dim >= ndims ())\n    {\n      // The dimension to sort along exceeds the array's dimensions,\n      // ==> array is already trivially sorted in such higher dimensions,\n      // ==> return early.\n\n      return *this;\n    }\n\n  Array<T, Alloc> m (dims ());\n\n  dim_vector dv = m.dims ();\n\n  octave_idx_type ns = dv(dim);\n  octave_idx_type iter = dv.numel () / ns;\n  octave_idx_type stride = 1;\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  T *v = m.rwdata ();\n  const T *ov = data ();\n\n  octave_sort<T> lsort;\n\n  if (mode != UNSORTED)\n    lsort.set_compare (mode);\n  else\n    return m;\n\n  if (stride == 1)\n    {\n      // Special case along first dimension avoids gather/scatter AND directly\n      // sorts into destination buffer for an 11% performance boost.\n      for (octave_idx_type j = 0; j < iter; j++)\n        {\n          // Copy and partition out NaNs.\n          // No need to special case integer types <T> from floating point\n          // types <T> to avoid sort_isnan() test as it makes no discernible\n          // performance impact.\n          octave_idx_type kl = 0;\n          octave_idx_type ku = ns;\n          for (octave_idx_type i = 0; i < ns; i++)\n            {\n              T tmp = ov[i];\n              if (sort_isnan<T> (tmp))\n                v[--ku] = tmp;\n              else\n                v[kl++] = tmp;\n            }\n\n          // sort.\n          lsort.sort (v, kl);\n\n          if (ku < ns)\n            {\n              // NaNs are in reverse order\n              std::reverse (v + ku, v + ns);\n              if (mode == DESCENDING)\n                std::rotate (v, v + ku, v + ns);\n            }\n\n          v += ns;\n          ov += ns;\n        }\n    }\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (T, buf, ns);\n\n      for (octave_idx_type j = 0; j < iter; j++)\n        {\n          octave_idx_type offset = j;\n          octave_idx_type n_strides = j / stride;\n          offset += n_strides * stride * (ns - 1);\n\n          // gather and partition out NaNs.\n          octave_idx_type kl = 0;\n          octave_idx_type ku = ns;\n          for (octave_idx_type i = 0; i < ns; i++)\n            {\n              T tmp = ov[i*stride + offset];\n              if (sort_isnan<T> (tmp))\n                buf[--ku] = tmp;\n              else\n                buf[kl++] = tmp;\n            }\n\n          // sort.\n          lsort.sort (buf, kl);\n\n          if (ku < ns)\n            {\n              // NaNs are in reverse order\n              std::reverse (buf + ku, buf + ns);\n              if (mode == DESCENDING)\n                std::rotate (buf, buf + ku, buf + ns);\n            }\n\n          // scatter.\n          for (octave_idx_type i = 0; i < ns; i++)\n            v[i*stride + offset] = buf[i];\n        }\n    }\n\n  return m;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::sort (Array<octave_idx_type>& sidx, int dim,\n                       sortmode mode) const\n{\n  if (dim < 0)\n    (*current_liboctave_error_handler) (\"sort: invalid dimension\");\n\n  const dim_vector& dv = dims ();\n\n  sidx = Array<octave_idx_type> (dv);\n\n  if (numel () < 1 || dim >= ndims ())\n    return *this;\n\n  Array<T, Alloc> m (dims ());\n\n  octave_idx_type ns = dv(dim);\n  octave_idx_type iter = dv.numel () / ns;\n  octave_idx_type stride = 1;\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  T *v = m.rwdata ();\n  const T *ov = data ();\n\n  octave_sort<T> lsort;\n\n  octave_idx_type *vi = sidx.rwdata ();\n\n  if (mode != UNSORTED)\n    lsort.set_compare (mode);\n  else\n    return m;\n\n  if (stride == 1)\n    {\n      // Special case for dim 1 avoids gather/scatter for performance boost.\n      // See comments in Array::sort (dim, mode).\n      for (octave_idx_type j = 0; j < iter; j++)\n        {\n          // copy and partition out NaNs.\n          octave_idx_type kl = 0;\n          octave_idx_type ku = ns;\n          for (octave_idx_type i = 0; i < ns; i++)\n            {\n              T tmp = ov[i];\n              if (sort_isnan<T> (tmp))\n                {\n                  --ku;\n                  v[ku] = tmp;\n                  vi[ku] = i;\n                }\n              else\n                {\n                  v[kl] = tmp;\n                  vi[kl] = i;\n                  kl++;\n                }\n            }\n\n          // sort.\n          lsort.sort (v, vi, kl);\n\n          if (ku < ns)\n            {\n              // NaNs are in reverse order\n              std::reverse (v + ku, v + ns);\n              std::reverse (vi + ku, vi + ns);\n              if (mode == DESCENDING)\n                {\n                  std::rotate (v, v + ku, v + ns);\n                  std::rotate (vi, vi + ku, vi + ns);\n                }\n            }\n\n          v += ns;\n          vi += ns;\n          ov += ns;\n        }\n    }\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (T, buf, ns);\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, bufi, ns);\n\n      for (octave_idx_type j = 0; j < iter; j++)\n        {\n          octave_idx_type offset = j;\n          octave_idx_type n_strides = j / stride;\n          offset += n_strides * stride * (ns - 1);\n\n          // gather and partition out NaNs.\n          octave_idx_type kl = 0;\n          octave_idx_type ku = ns;\n          for (octave_idx_type i = 0; i < ns; i++)\n            {\n              T tmp = ov[i*stride + offset];\n              if (sort_isnan<T> (tmp))\n                {\n                  --ku;\n                  buf[ku] = tmp;\n                  bufi[ku] = i;\n                }\n              else\n                {\n                  buf[kl] = tmp;\n                  bufi[kl] = i;\n                  kl++;\n                }\n            }\n\n          // sort.\n          lsort.sort (buf, bufi, kl);\n\n          if (ku < ns)\n            {\n              // NaNs are in reverse order\n              std::reverse (buf + ku, buf + ns);\n              std::reverse (bufi + ku, bufi + ns);\n              if (mode == DESCENDING)\n                {\n                  std::rotate (buf, buf + ku, buf + ns);\n                  std::rotate (bufi, bufi + ku, bufi + ns);\n                }\n            }\n\n          // scatter.\n          for (octave_idx_type i = 0; i < ns; i++)\n            v[i*stride + offset] = buf[i];\n          for (octave_idx_type i = 0; i < ns; i++)\n            vi[i*stride + offset] = bufi[i];\n        }\n    }\n\n  return m;\n}\n\ntemplate <typename T, typename Alloc>\ntypename Array<T, Alloc>::compare_fcn_type\nsafe_comparator (sortmode mode, const Array<T, Alloc>& /* a */,\n                 bool /* allow_chk */)\n{\n  if (mode == ASCENDING)\n    return octave_sort<T>::ascending_compare;\n  else if (mode == DESCENDING)\n    return octave_sort<T>::descending_compare;\n  else\n    return nullptr;\n}\n\ntemplate <typename T, typename Alloc>\nsortmode\nArray<T, Alloc>::issorted (sortmode mode) const\n{\n  octave_sort<T> lsort;\n\n  octave_idx_type n = numel ();\n\n  if (n <= 1)\n    return (mode == UNSORTED) ? ASCENDING : mode;\n\n  if (mode == UNSORTED)\n    {\n      // Auto-detect mode.\n      compare_fcn_type compare\n        = safe_comparator (ASCENDING, *this, false);\n\n      if (compare (elem (n-1), elem (0)))\n        mode = DESCENDING;\n      else\n        mode = ASCENDING;\n    }\n\n  lsort.set_compare (safe_comparator (mode, *this, false));\n\n  if (! lsort.issorted (data (), n))\n    mode = UNSORTED;\n\n  return mode;\n\n}\n\ntemplate <typename T, typename Alloc>\nArray<octave_idx_type>\nArray<T, Alloc>::sort_rows_idx (sortmode mode) const\n{\n  Array<octave_idx_type> idx;\n\n  octave_sort<T> lsort (safe_comparator (mode, *this, true));\n\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n\n  idx = Array<octave_idx_type> (dim_vector (r, 1));\n\n  lsort.sort_rows (data (), idx.rwdata (), r, c);\n\n  return idx;\n}\n\ntemplate <typename T, typename Alloc>\nsortmode\nArray<T, Alloc>::is_sorted_rows (sortmode mode) const\n{\n  octave_sort<T> lsort;\n\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n\n  if (r <= 1 || c == 0)\n    return (mode == UNSORTED) ? ASCENDING : mode;\n\n  if (mode == UNSORTED)\n    {\n      // Auto-detect mode.\n      compare_fcn_type compare\n        = safe_comparator (ASCENDING, *this, false);\n\n      octave_idx_type i;\n      for (i = 0; i < cols (); i++)\n        {\n          T l = elem (0, i);\n          T u = elem (rows () - 1, i);\n          if (compare (l, u))\n            {\n              if (mode == DESCENDING)\n                {\n                  mode = UNSORTED;\n                  break;\n                }\n              else\n                mode = ASCENDING;\n            }\n          else if (compare (u, l))\n            {\n              if (mode == ASCENDING)\n                {\n                  mode = UNSORTED;\n                  break;\n                }\n              else\n                mode = DESCENDING;\n            }\n        }\n      if (mode == UNSORTED && i == cols ())\n        mode = ASCENDING;\n    }\n\n  if (mode != UNSORTED)\n    {\n      lsort.set_compare (safe_comparator (mode, *this, false));\n\n      if (! lsort.is_sorted_rows (data (), r, c))\n        mode = UNSORTED;\n    }\n\n  return mode;\n\n}\n\n// Do a binary lookup in a sorted array.\ntemplate <typename T, typename Alloc>\noctave_idx_type\nArray<T, Alloc>::lookup (const T& value, sortmode mode) const\n{\n  octave_idx_type n = numel ();\n  octave_sort<T> lsort;\n\n  if (mode == UNSORTED)\n    {\n      // auto-detect mode\n      if (n > 1 && lsort.descending_compare (elem (0), elem (n-1)))\n        mode = DESCENDING;\n      else\n        mode = ASCENDING;\n    }\n\n  lsort.set_compare (mode);\n\n  return lsort.lookup (data (), n, value);\n}\n\ntemplate <typename T, typename Alloc>\nArray<octave_idx_type>\nArray<T, Alloc>::lookup (const Array<T, Alloc>& values, sortmode mode) const\n{\n  octave_idx_type n = numel ();\n  octave_idx_type nval = values.numel ();\n  octave_sort<T> lsort;\n  Array<octave_idx_type> idx (values.dims ());\n\n  if (mode == UNSORTED)\n    {\n      // auto-detect mode\n      if (n > 1 && lsort.descending_compare (elem (0), elem (n-1)))\n        mode = DESCENDING;\n      else\n        mode = ASCENDING;\n    }\n\n  lsort.set_compare (mode);\n\n  // This determines the split ratio between the O(M*log2(N)) and O(M+N)\n  // algorithms.\n  static const double RATIO = 1.0;\n  sortmode vmode = UNSORTED;\n\n  // Attempt the O(M+N) algorithm if M is large enough.\n  if (nval > RATIO * n / octave::math::log2 (n + 1.0))\n    {\n      vmode = values.issorted ();\n      // The table must not contain a NaN.\n      if ((vmode == ASCENDING && sort_isnan<T> (values(nval-1)))\n          || (vmode == DESCENDING && sort_isnan<T> (values(0))))\n        vmode = UNSORTED;\n    }\n\n  if (vmode != UNSORTED)\n    lsort.lookup_sorted (data (), n, values.data (), nval,\n                         idx.rwdata (), vmode != mode);\n  else\n    lsort.lookup (data (), n, values.data (), nval, idx.rwdata ());\n\n  return idx;\n}\n\ntemplate <typename T, typename Alloc>\noctave_idx_type\nArray<T, Alloc>::nnz () const\n{\n  const T *src = data ();\n  octave_idx_type nel = numel ();\n  octave_idx_type retval = 0;\n  const T zero = T ();\n  for (octave_idx_type i = 0; i < nel; i++)\n    if (src[i] != zero)\n      retval++;\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nArray<octave_idx_type>\nArray<T, Alloc>::find (octave_idx_type n, bool backward) const\n{\n  Array<octave_idx_type> retval;\n  const T *src = data ();\n  octave_idx_type nel = numel ();\n  const T zero = T ();\n  if (n < 0 || n >= nel)\n    {\n      // We want all elements, which means we'll almost surely need\n      // to resize.  So count first, then allocate array of exact size.\n      octave_idx_type cnt = 0;\n      for (octave_idx_type i = 0; i < nel; i++)\n        cnt += src[i] != zero;\n\n      retval.clear (cnt, 1);\n      octave_idx_type *dest = retval.rwdata ();\n      for (octave_idx_type i = 0; i < nel; i++)\n        if (src[i] != zero) *dest++ = i;\n    }\n  else\n    {\n      // We want a fixed max number of elements, usually small.  So be\n      // optimistic, alloc the array in advance, and then resize if\n      // needed.\n      retval.clear (n, 1);\n      if (backward)\n        {\n          // Do the search as a series of successive single-element searches.\n          octave_idx_type k = 0;\n          octave_idx_type l = nel - 1;\n          for (; k < n; k++)\n            {\n              for (; l >= 0 && src[l] == zero; l--) ;\n              if (l >= 0)\n                retval(k) = l--;\n              else\n                break;\n            }\n          if (k < n)\n            retval.resize2 (k, 1);\n          octave_idx_type *rdata = retval.rwdata ();\n          std::reverse (rdata, rdata + k);\n        }\n      else\n        {\n          // Do the search as a series of successive single-element searches.\n          octave_idx_type k = 0;\n          octave_idx_type l = 0;\n          for (; k < n; k++)\n            {\n              for (; l != nel && src[l] == zero; l++) ;\n              if (l != nel)\n                retval(k) = l++;\n              else\n                break;\n            }\n          if (k < n)\n            retval.resize2 (k, 1);\n        }\n    }\n\n  // Fixup return dimensions, for Matlab compatibility.\n  // find (zeros (0,0)) -> zeros (0,0)\n  // find (zeros (1,0)) -> zeros (1,0)\n  // find (zeros (0,1)) -> zeros (0,1)\n  // find (zeros (0,X)) -> zeros (0,1)\n  // find (zeros (1,1)) -> zeros (0,0) !!!! WHY?\n  // find (zeros (0,1,0)) -> zeros (0,0)\n  // find (zeros (0,1,0,1)) -> zeros (0,0) etc\n\n  if ((numel () == 1 && retval.isempty ())\n      || (rows () == 0 && dims ().numel (1) == 0))\n    retval.m_dimensions = dim_vector ();\n  else if (rows () == 1 && ndims () == 2)\n    retval.m_dimensions = dim_vector (1, retval.numel ());\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::nth_element (const octave::idx_vector& n, int dim) const\n{\n  if (dim < 0)\n    (*current_liboctave_error_handler) (\"nth_element: invalid dimension\");\n\n  dim_vector dv = dims ();\n  if (dim >= dv.ndims ())\n    dv.resize (dim+1, 1);\n\n  octave_idx_type ns = dv(dim);\n\n  octave_idx_type nn = n.length (ns);\n\n  dv(dim) = std::min (nn, ns);\n  dv.chop_trailing_singletons ();\n  dim = std::min (dv.ndims (), static_cast<octave_idx_type> (dim));\n\n  Array<T, Alloc> m (dv);\n\n  if (m.isempty ())\n    return m;\n\n  sortmode mode = UNSORTED;\n  octave_idx_type lo = 0;\n\n  switch (n.idx_class ())\n    {\n    case octave::idx_vector::class_scalar:\n      mode = ASCENDING;\n      lo = n(0);\n      break;\n    case octave::idx_vector::class_range:\n      {\n        octave_idx_type inc = n.increment ();\n        if (inc == 1)\n          {\n            mode = ASCENDING;\n            lo = n(0);\n          }\n        else if (inc == -1)\n          {\n            mode = DESCENDING;\n            lo = ns - 1 - n(0);\n          }\n      }\n      break;\n    case octave::idx_vector::class_vector:\n      // This case resolves bug #51329, a fallback to allow the given index\n      // to be a sequential vector instead of the typical scalar or range\n      if (n(1) - n(0) == 1)\n        {\n          mode = ASCENDING;\n          lo = n(0);\n        }\n      else if (n(1) - n(0) == -1)\n        {\n          mode = DESCENDING;\n          lo = ns - 1 - n(0);\n        }\n      // Ensure that the vector is actually an arithmetic contiguous sequence\n      for (octave_idx_type i = 2; i < n.length () && mode != UNSORTED; i++)\n        if ((mode == ASCENDING && n(i) - n(i-1) != 1)\n            || (mode == DESCENDING && n(i) - n(i-1) != -1))\n          mode = UNSORTED;\n      break;\n    default:\n      break;\n    }\n\n  if (mode == UNSORTED)\n    (*current_liboctave_error_handler)\n      (\"nth_element: n must be a scalar or a contiguous range\");\n\n  octave_idx_type up = lo + nn;\n\n  if (lo < 0 || up > ns)\n    (*current_liboctave_error_handler) (\"nth_element: invalid element index\");\n\n  octave_idx_type iter = numel () / ns;\n  octave_idx_type stride = 1;\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  T *v = m.rwdata ();\n  const T *ov = data ();\n\n  OCTAVE_LOCAL_BUFFER (T, buf, ns);\n\n  octave_sort<T> lsort;\n  lsort.set_compare (mode);\n\n  for (octave_idx_type j = 0; j < iter; j++)\n    {\n      octave_idx_type kl = 0;\n      octave_idx_type ku = ns;\n\n      if (stride == 1)\n        {\n          // copy without NaNs.\n          for (octave_idx_type i = 0; i < ns; i++)\n            {\n              T tmp = ov[i];\n              if (sort_isnan<T> (tmp))\n                buf[--ku] = tmp;\n              else\n                buf[kl++] = tmp;\n            }\n\n          ov += ns;\n        }\n      else\n        {\n          octave_idx_type offset = j % stride;\n          // copy without NaNs.\n          for (octave_idx_type i = 0; i < ns; i++)\n            {\n              T tmp = ov[offset + i*stride];\n              if (sort_isnan<T> (tmp))\n                buf[--ku] = tmp;\n              else\n                buf[kl++] = tmp;\n            }\n\n          if (offset == stride-1)\n            ov += ns*stride;\n        }\n\n      if (ku == ns)\n        lsort.nth_element (buf, ns, lo, up);\n      else if (mode == ASCENDING)\n        lsort.nth_element (buf, ku, lo, std::min (ku, up));\n      else\n        {\n          octave_idx_type nnan = ns - ku;\n          octave_idx_type zero = 0;\n          lsort.nth_element (buf, ku, std::max (lo - nnan, zero),\n                             std::max (up - nnan, zero));\n          std::rotate (buf, buf + ku, buf + ns);\n        }\n\n      if (stride == 1)\n        {\n          for (octave_idx_type i = 0; i < nn; i++)\n            v[i] = buf[lo + i];\n\n          v += nn;\n        }\n      else\n        {\n          octave_idx_type offset = j % stride;\n          for (octave_idx_type i = 0; i < nn; i++)\n            v[offset + stride * i] = buf[lo + i];\n          if (offset == stride-1)\n            v += nn*stride;\n        }\n    }\n\n  return m;\n}\n\n#define NO_INSTANTIATE_ARRAY_SORT_API(T, API)                           \\\n  template <> API Array<T>                                              \\\n  Array<T>::sort (int, sortmode) const                                  \\\n  {                                                                     \\\n    return *this;                                                       \\\n  }                                                                     \\\n  template <> API Array<T>                                              \\\n  Array<T>::sort (Array<octave_idx_type> &sidx, int, sortmode) const  \\\n  {                                                                     \\\n    sidx = Array<octave_idx_type> ();                                   \\\n    return *this;                                                       \\\n  }                                                                     \\\n  template <> API sortmode                                              \\\n  Array<T>::issorted (sortmode) const                                   \\\n  {                                                                     \\\n    return UNSORTED;                                                    \\\n  }                                                                     \\\n  API Array<T>::compare_fcn_type                                        \\\n  safe_comparator (sortmode, const Array<T>&, bool)                     \\\n  {                                                                     \\\n    return nullptr;                                                     \\\n  }                                                                     \\\n  template <> API Array<octave_idx_type>                                \\\n  Array<T>::sort_rows_idx (sortmode) const                              \\\n  {                                                                     \\\n    return Array<octave_idx_type> ();                                   \\\n  }                                                                     \\\n  template <> API sortmode                                              \\\n  Array<T>::is_sorted_rows (sortmode) const                             \\\n  {                                                                     \\\n    return UNSORTED;                                                    \\\n  }                                                                     \\\n  template <> API octave_idx_type                                       \\\n  Array<T>::lookup (T const &, sortmode) const                          \\\n  {                                                                     \\\n    return 0;                                                           \\\n  }                                                                     \\\n  template <> API Array<octave_idx_type>                                \\\n  Array<T>::lookup (const Array<T>&, sortmode) const                    \\\n  {                                                                     \\\n    return Array<octave_idx_type> ();                                   \\\n  }                                                                     \\\n  template <> API octave_idx_type                                       \\\n  Array<T>::nnz () const                                            \\\n  {                                                                     \\\n    return 0;                                                           \\\n  }                                                                     \\\n  template <> API Array<octave_idx_type>                                \\\n  Array<T>::find (octave_idx_type, bool) const                          \\\n  {                                                                     \\\n    return Array<octave_idx_type> ();                                   \\\n  }                                                                     \\\n  template <> API Array<T>                                              \\\n  Array<T>::nth_element (const octave::idx_vector&, int) const {        \\\n    return Array<T> ();                                                 \\\n  }\n\n#define NO_INSTANTIATE_ARRAY_SORT(T) NO_INSTANTIATE_ARRAY_SORT_API (T,)\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::diag (octave_idx_type k) const\n{\n  const dim_vector& dv = dims ();\n  octave_idx_type nd = dv.ndims ();\n  Array<T, Alloc> d;\n\n  if (nd > 2)\n    (*current_liboctave_error_handler) (\"Matrix must be 2-dimensional\");\n\n  octave_idx_type nnr = dv(0);\n  octave_idx_type nnc = dv(1);\n\n  if (nnr == 0 && nnc == 0)\n    ; // do nothing for empty matrix\n  else if (nnr != 1 && nnc != 1)\n    {\n      // Extract diag from matrix\n      if (k > 0)\n        nnc -= k;\n      else if (k < 0)\n        nnr += k;\n\n      if (nnr > 0 && nnc > 0)\n        {\n          octave_idx_type ndiag = (nnr < nnc) ? nnr : nnc;\n\n          d.resize (dim_vector (ndiag, 1));\n\n          if (k > 0)\n            {\n              for (octave_idx_type i = 0; i < ndiag; i++)\n                d.xelem (i) = elem (i, i+k);\n            }\n          else if (k < 0)\n            {\n              for (octave_idx_type i = 0; i < ndiag; i++)\n                d.xelem (i) = elem (i-k, i);\n            }\n          else\n            {\n              for (octave_idx_type i = 0; i < ndiag; i++)\n                d.xelem (i) = elem (i, i);\n            }\n        }\n      else  // Matlab returns [] 0x1 for out-of-range diagonal\n        d.resize (dim_vector (0, 1));\n    }\n  else\n    {\n      // Create diag matrix from vector\n      octave_idx_type roff = 0;\n      octave_idx_type coff = 0;\n      if (k > 0)\n        {\n          roff = 0;\n          coff = k;\n        }\n      else if (k < 0)\n        {\n          roff = -k;\n          coff = 0;\n        }\n\n      if (nnr == 1)\n        {\n          octave_idx_type n = nnc + std::abs (k);\n          d = Array<T, Alloc> (dim_vector (n, n), resize_fill_value ());\n\n          for (octave_idx_type i = 0; i < nnc; i++)\n            d.xelem (i+roff, i+coff) = elem (0, i);\n        }\n      else\n        {\n          octave_idx_type n = nnr + std::abs (k);\n          d = Array<T, Alloc> (dim_vector (n, n), resize_fill_value ());\n\n          for (octave_idx_type i = 0; i < nnr; i++)\n            d.xelem (i+roff, i+coff) = elem (i, 0);\n        }\n    }\n\n  return d;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::diag (octave_idx_type m, octave_idx_type n) const\n{\n  if (ndims () != 2 || (rows () != 1 && cols () != 1))\n    (*current_liboctave_error_handler) (\"cat: invalid dimension\");\n\n  Array<T, Alloc> retval (dim_vector (m, n), resize_fill_value ());\n\n  octave_idx_type nel = std::min (numel (), std::min (m, n));\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval.xelem (i, i) = xelem (i);\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nArray<T, Alloc>\nArray<T, Alloc>::cat (int dim, octave_idx_type n, const Array<T, Alloc> *array_list)\n{\n  // Default concatenation.\n  bool (dim_vector::*concat_rule) (const dim_vector&, int) = &dim_vector::concat;\n\n  if (dim == -1 || dim == -2)\n    {\n      concat_rule = &dim_vector::hvcat;\n      dim = -dim - 1;\n    }\n  else if (dim < 0)\n    (*current_liboctave_error_handler) (\"cat: invalid dimension\");\n\n  if (n == 1)\n    return array_list[0];\n  else if (n == 0)\n    return Array<T, Alloc> ();\n\n  // Special case:\n  //\n  //   cat (dim, [], ..., [], A, ...)\n  //\n  // with dim > 2, A not 0x0, and at least three arguments to\n  // concatenate is equivalent to\n  //\n  //   cat (dim, A, ...)\n  //\n  // Note that this check must be performed here because for full-on\n  // braindead Matlab compatibility, we need to have things like\n  //\n  //   cat (3, [], [], A)\n  //\n  // succeed, but to have things like\n  //\n  //   cat (3, cat (3, [], []), A)\n  //   cat (3, zeros (0, 0, 2), A)\n  //\n  // fail.  See also bug report #31615.\n\n  octave_idx_type istart = 0;\n\n  if (n > 2 && dim > 1)\n    {\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          const dim_vector& dv = array_list[i].dims ();\n\n          if (dv.zero_by_zero ())\n            istart++;\n          else\n            break;\n        }\n\n      // Don't skip any initial arguments if they are all empty.\n      if (istart >= n)\n        istart = 0;\n    }\n\n  dim_vector dv = array_list[istart++].dims ();\n\n  for (octave_idx_type i = istart; i < n; i++)\n    if (! (dv.*concat_rule) (array_list[i].dims (), dim))\n      (*current_liboctave_error_handler) (\"cat: dimension mismatch\");\n\n  Array<T, Alloc> retval (dv);\n\n  if (retval.isempty ())\n    return retval;\n\n  int nidx = std::max (dv.ndims (), static_cast<octave_idx_type> (dim + 1));\n  Array<octave::idx_vector> idxa (dim_vector (nidx, 1), octave::idx_vector::colon);\n  octave_idx_type l = 0;\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      // NOTE: This takes some thinking, but no matter what the above rules\n      // are, an empty array can always be skipped at this point, because\n      // the result dimensions are already determined, and there is no way\n      // an empty array may contribute a nonzero piece along the dimension\n      // at this point, unless an empty array can be promoted to a non-empty\n      // one (which makes no sense).  I repeat, *no way*, think about it.\n      if (array_list[i].isempty ())\n        continue;\n\n      octave_quit ();\n\n      octave_idx_type u;\n      if (dim < array_list[i].ndims ())\n        u = l + array_list[i].dims ()(dim);\n      else\n        u = l + 1;\n\n      idxa(dim) = octave::idx_vector (l, u);\n\n      retval.assign (idxa, array_list[i]);\n\n      l = u;\n    }\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::print_info (std::ostream& os, const std::string& prefix) const\n{\n  os << prefix << \"m_rep address:   \" << m_rep << '\\n'\n     << prefix << \"m_rep->m_len:    \" << m_rep->m_len << '\\n'\n     << prefix << \"m_rep->m_data:   \" << static_cast<void *> (m_rep->m_data) << '\\n'\n     << prefix << \"m_rep->m_count:  \" << m_rep->m_count << '\\n'\n     << prefix << \"m_slice_data:    \" << static_cast<void *> (m_slice_data) << '\\n'\n     << prefix << \"m_slice_len:     \" << m_slice_len << '\\n';\n\n  // 2-D info:\n  //\n  //     << pefix << \"rows: \" << rows () << \"\\n\"\n  //     << prefix << \"cols: \" << cols () << \"\\n\";\n}\n\ntemplate <typename T, typename Alloc>\nbool\nArray<T, Alloc>::optimize_dimensions (const dim_vector& dv)\n{\n  bool retval = m_dimensions == dv;\n  if (retval)\n    m_dimensions = dv;\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nvoid\nArray<T, Alloc>::instantiation_guard ()\n{\n  // This guards against accidental implicit instantiations.\n  // Array<T, Alloc> instances should always be explicit and use INSTANTIATE_ARRAY.\n  T::__xXxXx__ ();\n}\n\n#define INSTANTIATE_ARRAY(T, API)               \\\n  template <> API void                          \\\n  Array<T>::instantiation_guard () { }          \\\n                                                \\\n  template class API Array<T>\n\n// FIXME: is this used?\n\ntemplate <typename T, typename Alloc>\nstd::ostream&\noperator << (std::ostream& os, const Array<T, Alloc>& a)\n{\n  const dim_vector& a_dims = a.dims ();\n\n  int n_dims = a_dims.ndims ();\n\n  os << n_dims << \"-dimensional array\";\n\n  if (n_dims)\n    os << \" (\" << a_dims.str () << ')';\n\n  os <<\"\\n\\n\";\n\n  if (n_dims)\n    {\n      os << \"data:\";\n\n      Array<octave_idx_type> ra_idx (dim_vector (n_dims, 1), 0);\n\n      // Number of times the first 2-D array is to be displayed.\n\n      octave_idx_type m = 1;\n      for (int i = 2; i < n_dims; i++)\n        m *= a_dims(i);\n\n      if (m == 1)\n        {\n          octave_idx_type rows = 0;\n          octave_idx_type cols = 0;\n\n          switch (n_dims)\n            {\n            case 2:\n              rows = a_dims(0);\n              cols = a_dims(1);\n\n              for (octave_idx_type j = 0; j < rows; j++)\n                {\n                  ra_idx(0) = j;\n                  for (octave_idx_type k = 0; k < cols; k++)\n                    {\n                      ra_idx(1) = k;\n                      os << ' ' << a.elem (ra_idx);\n                    }\n                  os << \"\\n\";\n                }\n              break;\n\n            default:\n              rows = a_dims(0);\n\n              for (octave_idx_type k = 0; k < rows; k++)\n                {\n                  ra_idx(0) = k;\n                  os << ' ' << a.elem (ra_idx);\n                }\n              break;\n            }\n\n          os << \"\\n\";\n        }\n      else\n        {\n          octave_idx_type rows = a_dims(0);\n          octave_idx_type cols = a_dims(1);\n\n          for (int i = 0; i < m; i++)\n            {\n              os << \"\\n(:,:,\";\n\n              for (int j = 2; j < n_dims - 1; j++)\n                os << ra_idx(j) + 1 << ',';\n\n              os << ra_idx(n_dims - 1) + 1 << \") = \\n\";\n\n              for (octave_idx_type j = 0; j < rows; j++)\n                {\n                  ra_idx(0) = j;\n\n                  for (octave_idx_type k = 0; k < cols; k++)\n                    {\n                      ra_idx(1) = k;\n                      os << ' ' << a.elem (ra_idx);\n                    }\n\n                  os << \"\\n\";\n                }\n\n              os << \"\\n\";\n\n              if (i != m - 1)\n                increment_index (ra_idx, a_dims, 2);\n            }\n        }\n    }\n\n  return os;\n}\n"
  },
  {
    "path": "liboctave/array/Array-base.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Array_base_h)\n#define octave_Array_base_h 1\n\n#include \"octave-config.h\"\n\n#include <cstddef>\n\n#include <algorithm>\n#include <iosfwd>\n#include <string>\n\n#include \"Array-fwd.h\"\n#include \"dim-vector.h\"\n#include \"idx-vector.h\"\n#include \"oct-error.h\"\n#include \"oct-traits.h\"\n#include \"lo-utils.h\"\n#include \"oct-refcount.h\"\n#include \"oct-sort.h\"\n#include \"quit.h\"\n\n//! N Dimensional Array with copy-on-write semantics.\n//!\n//! The Array class is at the root of Octave.  It provides a container\n//! with an arbitrary number of dimensions.  The operator () provides\n//! access to individual elements via subscript and linear indexing.\n//! Indexing starts at 0.  Arrays are column-major order as in Fortran.\n//!\n//! @code{.cc}\n//! // 3 D Array with 10 rows, 20 columns, and 5 pages, filled with 7.0\n//! Array<double> A (dim_vector (10, 20, 5), 7.0);\n//!\n//! // set value for row 0, column 10, and page 3\n//! A(0, 10, 3) = 2.5;\n//!\n//! // get value for row 1, column 2, and page 0\n//! double v = A(1, 2, 0);\n//!\n//! // get value for 25th element (row 4, column 3, page 1)\n//! double v = A(24);\n//! @endcode\n//!\n//! ## Notes on STL compatibility\n//!\n//! ### size() and length()\n//!\n//! To access the total number of elements in an Array, use numel()\n//! which is short for number of elements and is equivalent to the\n//! Octave function with same name.\n//!\n//! @code{.cc}\n//! Array<int> A (dim_vector (10, 20, 4), 1);\n//!\n//! octave_idx_type n = A.numel (); // returns 800 (10x20x4)\n//!\n//! octave_idx_type nr = A.size (0); // returns 10 (number of rows/dimension 0)\n//! octave_idx_type nc = A.size (1); // returns 20 (number of columns)\n//! octave_idx_type nc = A.size (2); // returns 4 (size of dimension 3)\n//! octave_idx_type l6 = A.size (6); // returns 1 (implicit singleton dimension)\n//!\n//! // Alternatively, get a dim_vector which represents the dimensions.\n//! dim_vector dims = A.dims ();\n//! @endcode\n//!\n//! The methods size() and length() as they exist in the STL cause\n//! confusion in the context of a N dimensional array.\n//!\n//! The size() of an array is the length of all dimensions.  In Octave,\n//! the size() function returns a row vector with the length of each\n//! dimension, or the size of a specific dimension.  Only the latter is\n//! present in liboctave.\n//!\n//! Since there is more than 1 dimension, length() would not make sense\n//! without expliciting which dimension.  If the function existed, which\n//! length should it return?  Octave length() function returns the length\n//! of the longest dimension which is an odd definition, only useful for\n//! vectors and square matrices.  The alternatives numel(), rows(),\n//! columns(), and size(d) are more explicit and recommended.\n//!\n//! ### size_type\n//!\n//! Array::size_type is 'octave_idx_type' which is a typedef for 'int'\n//! or 'long int', depending whether Octave was configured for 64-bit\n//! indexing.\n//!\n//! This is a signed integer which may cause problems when mixed with\n//! STL containers.  The reason is that Octave interacts with Fortran\n//! routines, providing an interface many Fortran numeric libraries.\n//!\n//! ## Subclasses\n//!\n//! The following subclasses specializations, will be of most use:\n//!   - Matrix: Array<double> with only 2 dimensions\n//!   - ComplexMatrix: Array<std::complex<double>> with only 2 dimensions\n//!   - boolNDArray: N dimensional Array<bool>\n//!   - ColumnVector: Array<double> with 1 column\n//!   - string_vector: Array<std::string> with 1 column\n//!   - Cell: Array<octave_value>, equivalent to an Octave cell.\n\n// forward declare template with visibility attributes\ntemplate <typename T, typename Alloc> class OCTARRAY_API Array;\n\ntemplate <typename T, typename Alloc>\nclass OCTARRAY_TEMPLATE_API Array\n{\nprotected:\n\n  //! The real representation of all arrays.\n  class OCTARRAY_TEMPLATE_API ArrayRep : public Alloc\n  {\n  public:\n\n    typedef std::allocator_traits<Alloc> Alloc_traits;\n\n    typedef typename Alloc_traits::template rebind_traits<T> T_Alloc_traits;\n    typedef typename T_Alloc_traits::pointer pointer;\n\n    pointer m_data;\n    octave_idx_type m_len;\n    octave::refcount<octave_idx_type> m_count;\n\n    OCTARRAY_OVERRIDABLE_FUNC_API\n    ArrayRep (pointer d, octave_idx_type len)\n      : Alloc (), m_data (allocate (len)), m_len (len), m_count (1)\n    {\n      std::copy_n (d, len, m_data);\n    }\n\n    template <typename U>\n    OCTARRAY_OVERRIDABLE_FUNC_API\n    ArrayRep (U *d, octave_idx_type len)\n      : Alloc (), m_data (allocate (len)), m_len (len), m_count (1)\n    {\n      if constexpr (std::is_same_v<T, bool>)\n        {\n          // Required specialization because std::copy_n can sometimes choose\n          // to copy bool as bit, rather than as 8-bit byte.  See bug #63515.\n          for (octave_idx_type i = 0; i < len; i++)\n            m_data[i] = static_cast<bool> (d[i]);\n        }\n      else\n        std::copy_n (d, len, m_data);\n    }\n\n    // Use new instead of setting data to 0 so that rwdata() and data()\n    // always return valid addresses, even for zero-size arrays.\n\n    OCTARRAY_OVERRIDABLE_FUNC_API ArrayRep ()\n      : Alloc (), m_data (allocate (0)), m_len (0), m_count (1) { }\n\n    explicit OCTARRAY_OVERRIDABLE_FUNC_API ArrayRep (octave_idx_type len)\n      : Alloc (), m_data (allocate (len)), m_len (len), m_count (1) { }\n\n    explicit OCTARRAY_OVERRIDABLE_FUNC_API\n    ArrayRep (octave_idx_type len, const T& val)\n      : Alloc (), m_data (allocate (len)), m_len (len), m_count (1)\n    {\n      std::fill_n (m_data, len, val);\n    }\n\n    explicit OCTARRAY_OVERRIDABLE_FUNC_API\n    ArrayRep (pointer ptr, const dim_vector& dv,\n              const Alloc& xallocator = Alloc ())\n      : Alloc (xallocator), m_data (ptr), m_len (dv.safe_numel ()), m_count (1)\n    { }\n\n    // FIXME: Should the allocator be copied or created with the default?\n    OCTARRAY_OVERRIDABLE_FUNC_API ArrayRep (const ArrayRep& a)\n      : Alloc (), m_data (allocate (a.m_len)), m_len (a.m_len),\n        m_count (1)\n    {\n      std::copy_n (a.m_data, a.m_len, m_data);\n    }\n\n    OCTARRAY_OVERRIDABLE_FUNC_API ~ArrayRep () { deallocate (m_data, m_len); }\n\n    OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type numel () const\n    {\n      return m_len;\n    }\n\n    // No assignment!\n\n    OCTARRAY_OVERRIDABLE_FUNC_API ArrayRep&\n    operator = (const ArrayRep&) = delete;\n\n    OCTARRAY_OVERRIDABLE_FUNC_API pointer allocate (size_t len)\n    {\n      pointer data = Alloc_traits::allocate (*this, len);\n      for (size_t i = 0; i < len; i++)\n        T_Alloc_traits::construct (*this, data+i);\n      return data;\n    }\n\n    OCTARRAY_OVERRIDABLE_FUNC_API void deallocate (pointer data, size_t len)\n    {\n      for (size_t i = 0; i < len; i++)\n        T_Alloc_traits::destroy (*this, data+i);\n      Alloc_traits::deallocate (*this, data, len);\n    }\n  };\n\n  //--------------------------------------------------------------------\n\npublic:\n\n  OCTARRAY_OVERRIDABLE_FUNC_API void make_unique ()\n  {\n    if (m_rep->m_count > 1)\n      {\n        ArrayRep *r = new ArrayRep (m_slice_data, m_slice_len);\n\n        if (--m_rep->m_count == 0)\n          delete m_rep;\n\n        m_rep = r;\n        m_slice_data = m_rep->m_data;\n      }\n  }\n\n  typedef T element_type;\n\n  typedef T value_type;\n\n  //! Used for operator(), and returned by numel() and size()\n  //! (beware: signed integer)\n  typedef octave_idx_type size_type;\n\n  typedef typename ref_param<T>::type crefT;\n\n  typedef bool (*compare_fcn_type) (typename ref_param<T>::type,\n                                    typename ref_param<T>::type);\n\nprotected:\n\n  dim_vector m_dimensions;\n\n  typename Array<T, Alloc>::ArrayRep *m_rep;\n\n  // Rationale:\n  // m_slice_data is a pointer to m_rep->m_data, denoting together with m_slice_len the\n  // actual portion of the data referenced by this Array<T> object.  This\n  // allows to make shallow copies not only of a whole array, but also of\n  // contiguous subranges.  Every time m_rep is directly manipulated, m_slice_data\n  // and m_slice_len need to be properly updated.\n\n  T *m_slice_data;\n  octave_idx_type m_slice_len;\n\n  //! slice constructor\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  Array (const Array<T, Alloc>& a, const dim_vector& dv,\n         octave_idx_type l, octave_idx_type u)\n    : m_dimensions (dv), m_rep(a.m_rep), m_slice_data (a.m_slice_data+l), m_slice_len (u-l)\n  {\n    m_rep->m_count++;\n    m_dimensions.chop_trailing_singletons ();\n  }\n\nprivate:\n\n  static OCTARRAY_API typename Array<T, Alloc>::ArrayRep * nil_rep ();\n\npublic:\n\n  //! Empty ctor (0 by 0).\n  OCTARRAY_OVERRIDABLE_FUNC_API Array ()\n    : m_dimensions (), m_rep (nil_rep ()), m_slice_data (m_rep->m_data),\n      m_slice_len (m_rep->m_len)\n  {\n    m_rep->m_count++;\n  }\n\n  //! N-D uninitialized ctor.\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  explicit Array (const dim_vector& dv)\n    : m_dimensions (dv),\n      m_rep (new typename Array<T, Alloc>::ArrayRep (dv.safe_numel ())),\n      m_slice_data (m_rep->m_data), m_slice_len (m_rep->m_len)\n  {\n    m_dimensions.chop_trailing_singletons ();\n  }\n\n  //! N-D initialized ctor.\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  explicit Array (const dim_vector& dv, const T& val)\n    : m_dimensions (dv),\n      m_rep (new typename Array<T, Alloc>::ArrayRep (dv.safe_numel ())),\n      m_slice_data (m_rep->m_data), m_slice_len (m_rep->m_len)\n  {\n    fill (val);\n    m_dimensions.chop_trailing_singletons ();\n  }\n\n  // Construct an Array from a pointer to an externally allocated array\n  // of values.  PTR must be allocated with operator new.  The Array\n  // object takes ownership of PTR and will delete it when the Array\n  // object is deleted.  The dimension vector DV must be consistent with\n  // the size of the allocated PTR array.\n\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  explicit Array (T *ptr, const dim_vector& dv,\n                  const Alloc& xallocator = Alloc ())\n    : m_dimensions (dv),\n      m_rep (new typename Array<T, Alloc>::ArrayRep (ptr, dv, xallocator)),\n      m_slice_data (m_rep->m_data), m_slice_len (m_rep->m_len)\n  {\n    m_dimensions.chop_trailing_singletons ();\n  }\n\n  //! Reshape constructor.\n  OCTARRAY_API Array (const Array<T, Alloc>& a, const dim_vector& dv);\n\n  //! Constructor from standard library sequence containers.\n  template<template <typename...> class Container>\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  Array (const Container<T>& a, const dim_vector& dv);\n\n  //! Type conversion case.\n  template <typename U, typename A = Alloc>\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  Array (const Array<U, A>& a)\n    : m_dimensions (a.dims ()),\n      m_rep (new typename Array<T, Alloc>::ArrayRep (a.data (), a.numel ())),\n      m_slice_data (m_rep->m_data), m_slice_len (m_rep->m_len)\n  { }\n\n  //! No type conversion case.\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  Array (const Array<T, Alloc>& a)\n    : m_dimensions (a.m_dimensions), m_rep (a.m_rep), m_slice_data (a.m_slice_data),\n      m_slice_len (a.m_slice_len)\n  {\n    m_rep->m_count++;\n  }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  Array (Array<T, Alloc>&& a)\n    : m_dimensions (std::move (a.m_dimensions)), m_rep (a.m_rep),\n      m_slice_data (a.m_slice_data), m_slice_len (a.m_slice_len)\n  {\n    a.m_rep = nullptr;\n    a.m_slice_data = nullptr;\n    a.m_slice_len = 0;\n  }\n\npublic:\n\n  virtual OCTARRAY_OVERRIDABLE_FUNC_API ~Array ()\n  {\n    // Because we define a move constructor and a move assignment\n    // operator, m_rep may be a nullptr here.  We should only need to\n    // protect the move assignment operator in a similar way.\n\n    if (m_rep && --m_rep->m_count == 0)\n      delete m_rep;\n  }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>&\n  operator = (const Array<T, Alloc>& a)\n  {\n    if (this != &a)\n      {\n        if (--m_rep->m_count == 0)\n          delete m_rep;\n\n        m_rep = a.m_rep;\n        m_rep->m_count++;\n\n        m_dimensions = a.m_dimensions;\n        m_slice_data = a.m_slice_data;\n        m_slice_len = a.m_slice_len;\n      }\n\n    return *this;\n  }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>&\n  operator = (Array<T, Alloc>&& a)\n  {\n    if (this != &a)\n      {\n        m_dimensions = std::move (a.m_dimensions);\n\n        // Because we define a move constructor and a move assignment\n        // operator, m_rep may be a nullptr here.  We should only need to\n        // protect the destructor in a similar way.\n\n        if (m_rep && --m_rep->m_count == 0)\n          delete m_rep;\n\n        m_rep = a.m_rep;\n        m_slice_data = a.m_slice_data;\n        m_slice_len = a.m_slice_len;\n\n        a.m_rep = nullptr;\n        a.m_slice_data = nullptr;\n        a.m_slice_len = 0;\n      }\n\n    return *this;\n  }\n\n  OCTARRAY_API void fill (const T& val);\n\n  OCTARRAY_API void clear ();\n  OCTARRAY_API void clear (const dim_vector& dv);\n\n  OCTARRAY_OVERRIDABLE_FUNC_API void\n  clear (octave_idx_type r, octave_idx_type c)\n  { clear (dim_vector (r, c)); }\n\n  //! Number of elements in the array.\n  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type\n  numel () const\n  { return m_slice_len; }\n  //@}\n\n  //! Return the array as a column vector.\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>\n  as_column () const\n  {\n    Array<T, Alloc> retval (*this);\n    if (m_dimensions.ndims () != 2 || m_dimensions(1) != 1)\n      retval.m_dimensions = dim_vector (numel (), 1);\n\n    return retval;\n  }\n\n  //! Return the array as a row vector.\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>\n  as_row () const\n  {\n    Array<T, Alloc> retval (*this);\n    if (m_dimensions.ndims () != 2 || m_dimensions(0) != 1)\n      retval.m_dimensions = dim_vector (1, numel ());\n\n    return retval;\n  }\n\n  //! Return the array as a matrix.\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>\n  as_matrix () const\n  {\n    Array<T, Alloc> retval (*this);\n    if (m_dimensions.ndims () != 2)\n      retval.m_dimensions = m_dimensions.redim (2);\n\n    return retval;\n  }\n\n  //! @name First dimension\n  //!\n  //! Get the first dimension of the array (number of rows)\n  //@{\n  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type\n  dim1 () const\n  { return m_dimensions(0); }\n  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type\n  rows () const\n  { return dim1 (); }\n  //@}\n\n  //! @name Second dimension\n  //!\n  //! Get the second dimension of the array (number of columns)\n  //@{\n  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type dim2 () const\n  { return m_dimensions(1); }\n  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type cols () const\n  { return dim2 (); }\n  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type columns () const\n  { return dim2 (); }\n  //@}\n\n  //! @name Third dimension\n  //!\n  //! Get the third dimension of the array (number of pages)\n  //@{\n  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type dim3 () const\n  { return m_dimensions.ndims () >= 3 ? m_dimensions(2) : 1; }\n  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type pages () const\n  { return dim3 (); }\n  //@}\n\n  //! Size of the specified dimension.\n  //!\n  //! Dimensions beyond the Array number of dimensions return 1 as\n  //! those are implicit singleton dimensions.\n  //!\n  //! Equivalent to Octave's 'size (A, DIM)'\n\n  OCTARRAY_OVERRIDABLE_FUNC_API size_type size (const size_type d) const\n  {\n    // Should we throw for negative values?\n    // Should >= ndims () be handled by dim_vector operator() instead ?\n    return d >= ndims () ? 1 : m_dimensions(d);\n  }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API std::size_t byte_size () const\n  { return static_cast<std::size_t> (numel ()) * sizeof (T); }\n\n  //! Return a const-reference so that dims ()(i) works efficiently.\n  OCTARRAY_OVERRIDABLE_FUNC_API const dim_vector& dims () const\n  { return m_dimensions; }\n\n  //! Chop off leading singleton dimensions\n  OCTARRAY_API Array<T, Alloc> squeeze () const;\n\n  OCTARRAY_API octave_idx_type\n  compute_index (octave_idx_type i, octave_idx_type j) const;\n  OCTARRAY_API octave_idx_type\n  compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k) const;\n  OCTARRAY_API octave_idx_type\n  compute_index (const Array<octave_idx_type>& ra_idx) const;\n\n  OCTARRAY_API octave_idx_type\n  compute_index_unchecked (const Array<octave_idx_type>& ra_idx) const;\n\n  // No checking, even for multiple references, ever.\n\n  OCTARRAY_OVERRIDABLE_FUNC_API T& xelem (octave_idx_type n)\n  { return m_slice_data[n]; }\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT xelem (octave_idx_type n) const\n  { return m_slice_data[n]; }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API T&\n  xelem (octave_idx_type i, octave_idx_type j)\n  { return xelem (dim1 ()*j+i); }\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  xelem (octave_idx_type i, octave_idx_type j) const\n  { return xelem (dim1 ()*j+i); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API T&\n  xelem (octave_idx_type i, octave_idx_type j, octave_idx_type k)\n  { return xelem (i, dim2 ()*k+j); }\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  xelem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const\n  { return xelem (i, dim2 ()*k+j); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API T&\n  xelem (const Array<octave_idx_type>& ra_idx)\n  { return xelem (compute_index_unchecked (ra_idx)); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  xelem (const Array<octave_idx_type>& ra_idx) const\n  { return xelem (compute_index_unchecked (ra_idx)); }\n\n  // FIXME: would be nice to fix this so that we don't unnecessarily force\n  //        a copy, but that is not so easy, and I see no clean way to do it.\n\n  OCTARRAY_API T& checkelem (octave_idx_type n);\n\n  OCTARRAY_API T& checkelem (octave_idx_type i, octave_idx_type j);\n\n  OCTARRAY_API T& checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k);\n\n  OCTARRAY_API T& checkelem (const Array<octave_idx_type>& ra_idx);\n\n  OCTARRAY_OVERRIDABLE_FUNC_API T& elem (octave_idx_type n)\n  {\n    make_unique ();\n    return xelem (n);\n  }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API T& elem (octave_idx_type i, octave_idx_type j)\n  { return elem (dim1 ()*j+i); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API T& elem (octave_idx_type i, octave_idx_type j, octave_idx_type k)\n  { return elem (i, dim2 ()*k+j); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API T& elem (const Array<octave_idx_type>& ra_idx)\n  { return Array<T, Alloc>::elem (compute_index_unchecked (ra_idx)); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API T& operator () (octave_idx_type n)\n  { return elem (n); }\n  OCTARRAY_OVERRIDABLE_FUNC_API T& operator () (octave_idx_type i, octave_idx_type j)\n  { return elem (i, j); }\n  OCTARRAY_OVERRIDABLE_FUNC_API T& operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k)\n  { return elem (i, j, k); }\n  OCTARRAY_OVERRIDABLE_FUNC_API T& operator () (const Array<octave_idx_type>& ra_idx)\n  { return elem (ra_idx); }\n\n  OCTARRAY_API crefT checkelem (octave_idx_type n) const;\n\n  OCTARRAY_API crefT checkelem (octave_idx_type i, octave_idx_type j) const;\n\n  OCTARRAY_API crefT checkelem (octave_idx_type i, octave_idx_type j,\n                                octave_idx_type k) const;\n\n  OCTARRAY_API crefT checkelem (const Array<octave_idx_type>& ra_idx) const;\n\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT elem (octave_idx_type n) const\n  { return xelem (n); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  elem (octave_idx_type i, octave_idx_type j) const\n  { return xelem (i, j); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  elem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const\n  { return xelem (i, j, k); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  elem (const Array<octave_idx_type>& ra_idx) const\n  { return Array<T, Alloc>::xelem (compute_index_unchecked (ra_idx)); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  operator () (octave_idx_type n) const { return elem (n); }\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  operator () (octave_idx_type i, octave_idx_type j) const\n  { return elem (i, j); }\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k) const\n  { return elem (i, j, k); }\n  OCTARRAY_OVERRIDABLE_FUNC_API crefT\n  operator () (const Array<octave_idx_type>& ra_idx) const\n  { return elem (ra_idx); }\n\n  // Fast extractors.  All of these produce shallow copies.\n\n  //! Extract column: A(:,k+1).\n  OCTARRAY_API Array<T, Alloc> column (octave_idx_type k) const;\n  //! Extract page: A(:,:,k+1).\n  OCTARRAY_API Array<T, Alloc> page (octave_idx_type k) const;\n\n  //! Extract a slice from this array as a column vector: A(:)(lo+1:up).\n  //! Must be 0 <= lo && up <= numel.  May be up < lo.\n  OCTARRAY_API Array<T, Alloc>\n  linear_slice (octave_idx_type lo, octave_idx_type up) const;\n\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>\n  reshape (octave_idx_type nr, octave_idx_type nc) const\n  { return Array<T, Alloc> (*this, dim_vector (nr, nc)); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>\n  reshape (const dim_vector& new_dims) const\n  { return Array<T, Alloc> (*this, new_dims); }\n\n  OCTARRAY_API Array<T, Alloc>\n  permute (const Array<octave_idx_type>& vec, bool inv = false) const;\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>\n  ipermute (const Array<octave_idx_type>& vec) const\n  { return permute (vec, true); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API bool issquare () const\n  { return (dim1 () == dim2 ()); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API bool isempty () const\n  { return numel () == 0; }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API bool isvector () const\n  { return m_dimensions.isvector (); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API bool is_nd_vector () const\n  { return m_dimensions.is_nd_vector (); }\n\n  OCTARRAY_API Array<T, Alloc> transpose () const;\n  OCTARRAY_API Array<T, Alloc> hermitian (T (*fcn) (const T&) = nullptr) const;\n\n  // Use for direct read-only access to Array data.\n  OCTARRAY_OVERRIDABLE_FUNC_API const T * data () const\n  { return m_slice_data; }\n\n  // Use for direct read-write access to Array data.\n  OCTARRAY_API T * rwdata ();\n\n  // Alias for direct read-write access to Array data.\n  // FIXME: It is recommended to use rwdata() in future code for clarity.\n  inline OCTARRAY_OVERRIDABLE_FUNC_API T * fortran_vec ()\n  { return rwdata (); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API bool is_shared () const\n  { return m_rep->m_count > 1; }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API int ndims () const\n  { return m_dimensions.ndims (); }\n\n  //@{\n  //! Indexing without resizing.\n  OCTARRAY_API Array<T, Alloc> index (const octave::idx_vector& i) const;\n\n  OCTARRAY_API Array<T, Alloc> index (const octave::idx_vector& i, const octave::idx_vector& j) const;\n\n  OCTARRAY_API Array<T, Alloc> index (const Array<octave::idx_vector>& ia) const;\n  //@}\n\n  virtual OCTARRAY_API T resize_fill_value () const;\n\n  //@{\n  //! Resizing (with fill).\n  OCTARRAY_API void resize2 (octave_idx_type nr, octave_idx_type nc, const T& rfv);\n  OCTARRAY_OVERRIDABLE_FUNC_API void resize2 (octave_idx_type nr, octave_idx_type nc)\n  {\n    resize2 (nr, nc, resize_fill_value ());\n  }\n\n  OCTARRAY_API void resize1 (octave_idx_type n, const T& rfv);\n  OCTARRAY_OVERRIDABLE_FUNC_API void resize1 (octave_idx_type n)\n  { resize1 (n, resize_fill_value ()); }\n\n  OCTARRAY_API void resize (const dim_vector& dv, const T& rfv);\n  OCTARRAY_OVERRIDABLE_FUNC_API void resize (const dim_vector& dv)\n  { resize (dv, resize_fill_value ()); }\n  //@}\n\n  //@{\n  //! Indexing with possible resizing and fill\n\n  // FIXME: this is really a corner case, that should better be\n  // handled directly in liboctinterp.\n\n  OCTARRAY_API Array<T, Alloc>\n  index (const octave::idx_vector& i, bool resize_ok, const T& rfv) const;\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>\n  index (const octave::idx_vector& i, bool resize_ok) const\n  {\n    return index (i, resize_ok, resize_fill_value ());\n  }\n\n  OCTARRAY_API Array<T, Alloc>\n  index (const octave::idx_vector& i, const octave::idx_vector& j,\n         bool resize_ok, const T& rfv) const;\n  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>\n  index (const octave::idx_vector& i, const octave::idx_vector& j,\n         bool resize_ok) const\n  {\n    return index (i, j, resize_ok, resize_fill_value ());\n  }\n\n  OCTARRAY_API Array<T, Alloc>\n  index (const Array<octave::idx_vector>& ia, bool resize_ok,\n         const T& rfv) const;\n  OCTARRAY_API Array<T, Alloc>\n  index (const Array<octave::idx_vector>& ia, bool resize_ok) const;\n  //@}\n\n  //@{\n  //! Indexed assignment (always with resize & fill).\n  OCTARRAY_API void\n  assign (const octave::idx_vector& i, const Array<T, Alloc>& rhs, const T& rfv);\n  OCTARRAY_OVERRIDABLE_FUNC_API void\n  assign (const octave::idx_vector& i, const Array<T, Alloc>& rhs)\n  {\n    assign (i, rhs, resize_fill_value ());\n  }\n\n  OCTARRAY_API void\n  assign (const octave::idx_vector& i, const octave::idx_vector& j,\n          const Array<T, Alloc>& rhs, const T& rfv);\n  OCTARRAY_OVERRIDABLE_FUNC_API void\n  assign (const octave::idx_vector& i, const octave::idx_vector& j,\n          const Array<T, Alloc>& rhs)\n  {\n    assign (i, j, rhs, resize_fill_value ());\n  }\n\n  OCTARRAY_API void\n  assign (const Array<octave::idx_vector>& ia, const Array<T, Alloc>& rhs, const T& rfv);\n  OCTARRAY_API void\n  assign (const Array<octave::idx_vector>& ia, const Array<T, Alloc>& rhs);\n  //@}\n\n  //@{\n  //! Deleting elements.\n\n  //! A(I) = [] (with a single subscript)\n  OCTARRAY_API void delete_elements (const octave::idx_vector& i);\n\n  //! A(:,...,I,...,:) = [] (>= 2 subscripts, one of them is non-colon)\n  OCTARRAY_API void delete_elements (int dim, const octave::idx_vector& i);\n\n  //! Dispatcher to the above two.\n  OCTARRAY_API void delete_elements (const Array<octave::idx_vector>& ia);\n  //@}\n\n  //! Insert an array into another at a specified position.  If\n  //! size (a) is [d1 d2 ... dN] and idx is [i1 i2 ... iN], this\n  //! method is equivalent to x(i1:i1+d1-1, i2:i2+d2-1, ... ,\n  //! iN:iN+dN-1) = a.\n  OCTARRAY_API Array<T, Alloc>&\n  insert (const Array<T, Alloc>& a, const Array<octave_idx_type>& idx);\n\n  //! This is just a special case for idx = [r c 0 ...]\n  OCTARRAY_API Array<T, Alloc>&\n  insert (const Array<T, Alloc>& a, octave_idx_type r, octave_idx_type c);\n\n  OCTARRAY_OVERRIDABLE_FUNC_API void maybe_economize ()\n  {\n    if (m_rep->m_count == 1 && m_slice_len != m_rep->m_len)\n      {\n        ArrayRep *new_rep = new ArrayRep (m_slice_data, m_slice_len);\n        delete m_rep;\n        m_rep = new_rep;\n        m_slice_data = m_rep->m_data;\n      }\n  }\n\n  OCTARRAY_API void print_info (std::ostream& os, const std::string& prefix) const;\n\n  OCTARRAY_API Array<T, Alloc> sort (int dim = 0, sortmode mode = ASCENDING) const;\n  OCTARRAY_API Array<T, Alloc> sort (Array<octave_idx_type>& sidx, int dim = 0,\n                                     sortmode mode = ASCENDING) const;\n\n  //! Ordering is auto-detected or can be specified.\n  OCTARRAY_API sortmode issorted (sortmode mode = UNSORTED) const;\n\n  //! Sort by rows returns only indices.\n  OCTARRAY_API Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const;\n\n  //! Ordering is auto-detected or can be specified.\n  OCTARRAY_API sortmode is_sorted_rows (sortmode mode = UNSORTED) const;\n\n  //! Do a binary lookup in a sorted array.  Must not contain NaNs.\n  //! Mode can be specified or is auto-detected by comparing 1st and last element.\n  OCTARRAY_API octave_idx_type lookup (const T& value, sortmode mode = UNSORTED) const;\n\n  //! Ditto, but for an array of values, specializing on the case when values\n  //! are sorted.  NaNs get the value N.\n  OCTARRAY_API Array<octave_idx_type> lookup (const Array<T, Alloc>& values,\n                                              sortmode mode = UNSORTED) const;\n\n  //! Count nonzero elements.\n  OCTARRAY_API octave_idx_type nnz () const;\n\n  //! Find indices of (at most n) nonzero elements.  If n is specified,\n  //! backward specifies search from backward.\n  OCTARRAY_API Array<octave_idx_type> find (octave_idx_type n = -1,\n                                            bool backward = false) const;\n\n  //! Returns the n-th element in increasing order, using the same\n  //! ordering as used for sort.  n can either be a scalar index or a\n  //! contiguous range.\n  OCTARRAY_API Array<T, Alloc> nth_element (const octave::idx_vector& n, int dim = 0) const;\n\n  //! Get the kth super or subdiagonal.  The zeroth diagonal is the\n  //! ordinary diagonal.\n  OCTARRAY_API Array<T, Alloc> diag (octave_idx_type k = 0) const;\n\n  OCTARRAY_API Array<T, Alloc> diag (octave_idx_type m, octave_idx_type n) const;\n\n  //! Concatenation along a specified (0-based) dimension, equivalent\n  //! to cat().  dim = -1 corresponds to dim = 0 and dim = -2\n  //! corresponds to dim = 1, but apply the looser matching rules of\n  //! vertcat/horzcat.\n  static OCTARRAY_API Array<T, Alloc>\n  cat (int dim, octave_idx_type n, const Array<T, Alloc> *array_list);\n\n  //! Apply function fcn to each element of the Array<T, Alloc>.  This function\n  //! is optimized with a manually unrolled loop.\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n  template <typename U, typename F,\n            typename A = std::pmr::polymorphic_allocator<U>>\n#else\n  template <typename U, typename F, typename A = std::allocator<U>>\n#endif\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  Array<U, A>\n  map (F fcn) const\n  {\n    octave_idx_type len = numel ();\n\n    const T *m = data ();\n\n    Array<U, A> result (dims ());\n    U *p = result.rwdata ();\n\n    octave_idx_type i;\n    for (i = 0; i < len - 3; i += 4)\n      {\n        octave_quit ();\n\n        p[i] = fcn (m[i]);\n        p[i+1] = fcn (m[i+1]);\n        p[i+2] = fcn (m[i+2]);\n        p[i+3] = fcn (m[i+3]);\n      }\n\n    octave_quit ();\n\n    for (; i < len; i++)\n      p[i] = fcn (m[i]);\n\n    return result;\n  }\n\n  //@{\n  //! Overloads for function references.\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n  template <typename U, typename A = std::pmr::polymorphic_allocator<U>>\n#else\n  template <typename U, typename A = std::allocator<U>>\n#endif\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  Array<U, A>\n  map (U (&fcn) (T)) const\n  { return map<U, U (&) (T), A> (fcn); }\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n  template <typename U, typename A = std::pmr::polymorphic_allocator<U>>\n#else\n  template <typename U, typename A = std::allocator<U>>\n#endif\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  Array<U, A>\n  map (U (&fcn) (const T&)) const\n  { return map<U, U (&) (const T&), A> (fcn); }\n  //@}\n\n  //! Generic any/all test functionality with arbitrary predicate.\n  template <typename F, bool zero>\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  bool test (F fcn) const\n  {\n    return octave::any_all_test<F, T, zero> (fcn, data (), numel ());\n  }\n\n  //@{\n  //! Simpler calls.\n  template <typename F>\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  bool test_any (F fcn) const\n  { return test<F, false> (fcn); }\n\n  template <typename F>\n  OCTARRAY_OVERRIDABLE_FUNC_API\n  bool test_all (F fcn) const\n  { return test<F, true> (fcn); }\n  //@}\n\n  //@{\n  //! Overloads for function references.\n  OCTARRAY_OVERRIDABLE_FUNC_API bool test_any (bool (&fcn) (T)) const\n  { return test<bool (&) (T), false> (fcn); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API bool test_any (bool (&fcn) (const T&)) const\n  { return test<bool (&) (const T&), false> (fcn); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API bool test_all (bool (&fcn) (T)) const\n  { return test<bool (&) (T), true> (fcn); }\n\n  OCTARRAY_OVERRIDABLE_FUNC_API bool test_all (bool (&fcn) (const T&)) const\n  { return test<bool (&) (const T&), true> (fcn); }\n  //@}\n\n  template <typename U, typename A> friend class Array;\n\n  //! Returns true if this->dims () == dv, and if so, replaces this->m_dimensions\n  //! by a shallow copy of dv.  This is useful for maintaining several arrays\n  //! with supposedly equal dimensions (e.g., structs in the interpreter).\n  OCTARRAY_API bool optimize_dimensions (const dim_vector& dv);\n\nprivate:\n  OCTARRAY_API static void instantiation_guard ();\n};\n\n// We use a variadic template for template parameter so that\n// we don't have to specify all the template parameters and limit this\n// to Container<T>. http://stackoverflow.com/a/20499809/1609556\ntemplate<typename T, typename Alloc>\ntemplate<template <typename...> class Container>\nOCTARRAY_OVERRIDABLE_FUNC_API\nArray<T, Alloc>::Array (const Container<T>& a, const dim_vector& dv)\n  : m_dimensions (dv), m_rep (new typename Array<T, Alloc>::ArrayRep (dv.safe_numel ())),\n    m_slice_data (m_rep->m_data), m_slice_len (m_rep->m_len)\n{\n  if (m_dimensions.safe_numel () != octave_idx_type (a.size ()))\n    {\n      std::string new_dims_str = m_dimensions.str ();\n\n      (*current_liboctave_error_handler)\n        (\"reshape: can't reshape %zi elements into %s array\",\n         a.size (), new_dims_str.c_str ());\n    }\n\n  octave_idx_type i = 0;\n  for (const T& x : a)\n    m_slice_data[i++] = x;\n\n  m_dimensions.chop_trailing_singletons ();\n}\n\ntemplate <typename T, typename Alloc>\nOCTARRAY_API std::ostream&\noperator << (std::ostream& os, const Array<T, Alloc>& a);\n\n#endif\n"
  },
  {
    "path": "liboctave/array/Array-ch.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Arrays of char values.\n\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n\n#define INLINE_ASCENDING_SORT 1\n#define INLINE_DESCENDING_SORT 1\n#include \"oct-sort.cc\"\n\ntemplate class octave_sort<char>;\n\nINSTANTIATE_ARRAY (char, );\n\ntemplate OCTAVE_API std::ostream& operator << (std::ostream&,\n                                               const Array<char>&);\n\n#include \"DiagArray2.h\"\n#include \"DiagArray2.cc\"\n\ntemplate class DiagArray2<char>;\n"
  },
  {
    "path": "liboctave/array/Array-d.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Arrays of double values.\n\n#include \"mappers.h\"\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n#include \"oct-locbuf.h\"\n\n#define INLINE_ASCENDING_SORT 1\n#define INLINE_DESCENDING_SORT 1\n#include \"oct-sort.cc\"\n\ntemplate <>\ninline bool\nsort_isnan<double> (double x)\n{\n  return octave::math::isnan (x);\n}\n\nstatic bool\nnan_ascending_compare (double x, double y)\n{\n  return octave::math::isnan (y) ? ! octave::math::isnan (x) : x < y;\n}\n\nstatic bool\nnan_descending_compare (double x, double y)\n{\n  return octave::math::isnan (x) ? ! octave::math::isnan (y) : x > y;\n}\n\nArray<double>::compare_fcn_type\nsafe_comparator (sortmode mode, const Array<double>& a, bool allow_chk)\n{\n  Array<double>::compare_fcn_type result = nullptr;\n\n  if (allow_chk)\n    {\n      octave_idx_type k = 0;\n      for (; k < a.numel () && ! octave::math::isnan (a(k)); k++) ;\n      if (k == a.numel ())\n        {\n          if (mode == ASCENDING)\n            result = octave_sort<double>::ascending_compare;\n          else if (mode == DESCENDING)\n            result = octave_sort<double>::descending_compare;\n        }\n    }\n\n  if (! result)\n    {\n      if (mode == ASCENDING)\n        result = nan_ascending_compare;\n      else if (mode == DESCENDING)\n        result = nan_descending_compare;\n    }\n\n  return result;\n}\n\n// The default solution using NaN-safe comparator is OK, but almost twice as\n// slow than this code.\ntemplate <>\nOCTAVE_API\nsortmode\nArray<double>::issorted (sortmode mode) const\n{\n  octave_idx_type n = numel ();\n\n  const double *el = data ();\n\n  if (n <= 1)\n    return (mode == UNSORTED) ? ASCENDING : mode;\n\n  if (mode == UNSORTED)\n    {\n      // Auto-detect mode.\n      if (el[n-1] < el[0] || octave::math::isnan (el[0]))\n        mode = DESCENDING;\n      else\n        mode = ASCENDING;\n    }\n\n  if (mode == DESCENDING)\n    {\n      octave_idx_type j = 0;\n      double r;\n      // Sort out NaNs.\n      do\n        r = el[j++];\n      while (octave::math::isnan (r) && j < n);\n\n      // Orient the test so that NaN will not pass through.\n      for (; j < n; j++)\n        {\n          if (r >= el[j])\n            r = el[j];\n          else\n            {\n              mode = UNSORTED;\n              break;\n            }\n        }\n\n    }\n  else  // mode == ASCENDING\n    {\n      // Sort out NaNs.\n      while (n > 0 && octave::math::isnan (el[n-1]))\n        n--;\n\n      if (n > 0)\n        {\n          // Orient the test so that NaN will not pass through.\n          double r = el[0];\n          for (octave_idx_type j = 1; j < n; j++)\n            {\n              if (r <= el[j])\n                r = el[j];\n              else\n                {\n                  mode = UNSORTED;\n                  break;\n                }\n            }\n        }\n    }\n\n  return mode;\n}\n\ntemplate class octave_sort<double>;\n\nINSTANTIATE_ARRAY (double, );\n\ntemplate OCTAVE_API std::ostream& operator << (std::ostream&,\n                                               const Array<double>&);\n\n#include \"DiagArray2.h\"\n#include \"DiagArray2.cc\"\n\ntemplate class DiagArray2<double>;\n"
  },
  {
    "path": "liboctave/array/Array-f.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Arrays of float values.\n\n#include \"mappers.h\"\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n#include \"oct-locbuf.h\"\n\n#define INLINE_ASCENDING_SORT 1\n#define INLINE_DESCENDING_SORT 1\n#include \"oct-sort.cc\"\n\ntemplate <>\ninline bool\nsort_isnan<float> (float x)\n{\n  return octave::math::isnan (x);\n}\n\nstatic bool\nnan_ascending_compare (float x, float y)\n{\n  return octave::math::isnan (y) ? ! octave::math::isnan (x) : x < y;\n}\n\nstatic bool\nnan_descending_compare (float x, float y)\n{\n  return octave::math::isnan (x) ? ! octave::math::isnan (y) : x > y;\n}\n\nArray<float>::compare_fcn_type\nsafe_comparator (sortmode mode, const Array<float>& a, bool allow_chk)\n{\n  Array<float>::compare_fcn_type result = nullptr;\n\n  if (allow_chk)\n    {\n      octave_idx_type k = 0;\n      for (; k < a.numel () && ! octave::math::isnan (a(k)); k++) ;\n      if (k == a.numel ())\n        {\n          if (mode == ASCENDING)\n            result = octave_sort<float>::ascending_compare;\n          else if (mode == DESCENDING)\n            result = octave_sort<float>::descending_compare;\n        }\n    }\n\n  if (! result)\n    {\n      if (mode == ASCENDING)\n        result = nan_ascending_compare;\n      else if (mode == DESCENDING)\n        result = nan_descending_compare;\n    }\n\n  return result;\n}\n\n// The default solution using NaN-safe comparator is OK, but almost twice as\n// slow than this code.\ntemplate <>\nOCTAVE_API\nsortmode\nArray<float>::issorted (sortmode mode) const\n{\n  octave_idx_type n = numel ();\n\n  const float *el = data ();\n\n  if (n <= 1)\n    return (mode == UNSORTED) ? ASCENDING : mode;\n\n  if (mode == UNSORTED)\n    {\n      // Auto-detect mode.\n      if (el[n-1] < el[0] || octave::math::isnan (el[0]))\n        mode = DESCENDING;\n      else\n        mode = ASCENDING;\n    }\n\n  if (mode == DESCENDING)\n    {\n      octave_idx_type j = 0;\n      float r;\n      // Sort out NaNs.\n      do\n        r = el[j++];\n      while (octave::math::isnan (r) && j < n);\n\n      // Orient the test so that NaN will not pass through.\n      for (; j < n; j++)\n        {\n          if (r >= el[j])\n            r = el[j];\n          else\n            {\n              mode = UNSORTED;\n              break;\n            }\n        }\n\n    }\n  else  // mode == ASCENDING\n    {\n      // Sort out NaNs.\n      while (n > 0 && octave::math::isnan (el[n-1]))\n        n--;\n\n      if (n > 0)\n        {\n          // Orient the test so that NaN will not pass through.\n          float r = el[0];\n          for (octave_idx_type j = 1; j < n; j++)\n            {\n              if (r <= el[j])\n                r = el[j];\n              else\n                {\n                  mode = UNSORTED;\n                  break;\n                }\n            }\n        }\n    }\n\n  return mode;\n}\n\ntemplate class octave_sort<float>;\n\nINSTANTIATE_ARRAY (float, );\n\ntemplate OCTAVE_API std::ostream& operator << (std::ostream&,\n                                               const Array<float>&);\n\n#include \"DiagArray2.h\"\n#include \"DiagArray2.cc\"\n\ntemplate class DiagArray2<float>;\n"
  },
  {
    "path": "liboctave/array/Array-fC.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Arrays of FloatComplex values.\n\n#include \"mappers.h\"\n#include \"oct-cmplx.h\"\n\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n#include \"oct-sort.cc\"\n\ntemplate <>\ninline bool\nsort_isnan<FloatComplex> (const FloatComplex& x)\n{\n  return octave::math::isnan (x);\n}\n\n// Sort Criteria: 1) isnan, 2) magnitude of z, 3) phase of z in range (-pi, pi]\n\nstatic bool\nnan_ascending_compare (const FloatComplex& x, const FloatComplex& y)\n{\n  return octave::math::isnan (y) ? ! octave::math::isnan (x) : x < y;\n}\n\nstatic bool\nnan_descending_compare (const FloatComplex& x, const FloatComplex& y)\n{\n  return octave::math::isnan (x) ? ! octave::math::isnan (y) : x > y;\n}\n\nArray<FloatComplex>::compare_fcn_type\nsafe_comparator (sortmode mode, const Array<FloatComplex>& a, bool allow_chk)\n{\n  Array<FloatComplex>::compare_fcn_type result = nullptr;\n\n  if (allow_chk)\n    {\n      octave_idx_type k = 0;\n      for (; k < a.numel () && ! octave::math::isnan (a(k)); k++) ;\n      if (k == a.numel ())\n        {\n          if (mode == ASCENDING)\n            result = octave_sort<FloatComplex>::ascending_compare;\n          else if (mode == DESCENDING)\n            result = octave_sort<FloatComplex>::descending_compare;\n        }\n    }\n\n  if (! result)\n    {\n      if (mode == ASCENDING)\n        result = nan_ascending_compare;\n      else if (mode == DESCENDING)\n        result = nan_descending_compare;\n    }\n\n  return result;\n}\n\ntemplate class octave_sort<FloatComplex>;\n\nINSTANTIATE_ARRAY (FloatComplex, );\n\ntemplate OCTAVE_API std::ostream& operator << (std::ostream&,\n                                               const Array<FloatComplex>&);\n\n#include \"DiagArray2.h\"\n#include \"DiagArray2.cc\"\n\ntemplate class DiagArray2<FloatComplex>;\n"
  },
  {
    "path": "liboctave/array/Array-fwd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Array_fwd_h)\n#define octave_Array_fwd_h 1\n\n#include \"octave-config.h\"\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n#  include <memory_resource>\n\ntemplate <typename T, typename Alloc = std::pmr::polymorphic_allocator<T>>\nclass OCTAVE_TEMPLATE_API Array;\n\n#else\n#  include <memory>\n\ntemplate <typename T, typename Alloc = std::allocator<T>>\nclass OCTAVE_TEMPLATE_API Array;\n\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/array/Array-i.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-inttypes-fwd.h\"\n\n// Instantiate Arrays of integer values.\n\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\n\n#include \"Array-base.cc\"\n\n#define INLINE_ASCENDING_SORT 1\n#define INLINE_DESCENDING_SORT 1\n#include \"oct-sort.cc\"\n\ntemplate class octave_sort<signed char>;\n//template class octave_sort<short>;\ntemplate class octave_sort<int>;\ntemplate class octave_sort<long>;\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\ntemplate class octave_sort<long long>;\n#endif\n\nINSTANTIATE_ARRAY (signed char, );\n//INSTANTIATE_ARRAY (short, );\nINSTANTIATE_ARRAY (int, );\nINSTANTIATE_ARRAY (long, );\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\nINSTANTIATE_ARRAY (long long, );\n#endif\n\ntemplate class octave_sort<unsigned char>;\ntemplate class octave_sort<unsigned short>;\ntemplate class octave_sort<unsigned int>;\ntemplate class octave_sort<unsigned long>;\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\ntemplate class octave_sort<unsigned long long>;\n#endif\n\nINSTANTIATE_ARRAY (unsigned char, );\nINSTANTIATE_ARRAY (unsigned short, );\nINSTANTIATE_ARRAY (unsigned int, );\nINSTANTIATE_ARRAY (unsigned long, );\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\nINSTANTIATE_ARRAY (unsigned long long, );\n#endif\n\ntemplate class octave_sort<octave_int8>;\ntemplate class octave_sort<octave_int16>;\ntemplate class octave_sort<octave_int32>;\ntemplate class octave_sort<octave_int64>;\n\nINSTANTIATE_ARRAY (octave_int8, );\nINSTANTIATE_ARRAY (octave_int16, );\nINSTANTIATE_ARRAY (octave_int32, );\nINSTANTIATE_ARRAY (octave_int64, );\n\ntemplate class octave_sort<octave_uint8>;\ntemplate class octave_sort<octave_uint16>;\ntemplate class octave_sort<octave_uint32>;\ntemplate class octave_sort<octave_uint64>;\n\nINSTANTIATE_ARRAY (octave_uint8, );\nINSTANTIATE_ARRAY (octave_uint16, );\nINSTANTIATE_ARRAY (octave_uint32, );\nINSTANTIATE_ARRAY (octave_uint64, );\n\n#include \"DiagArray2.h\"\n#include \"DiagArray2.cc\"\n\ntemplate class DiagArray2<int>;\n"
  },
  {
    "path": "liboctave/array/Array-idx-vec.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Arrays of integer values.\n\n#include \"idx-vector.h\"\n\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n\nNO_INSTANTIATE_ARRAY_SORT_API (octave::idx_vector, OCTAVE_API);\n\nINSTANTIATE_ARRAY (octave::idx_vector, );\n"
  },
  {
    "path": "liboctave/array/Array-oct.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2022-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n\n// Include this file when instantiating the Array class with new types in\n// projects linking to \"liboctave\" but not to \"liboctinterp\".\n\n#include \"Array-base.h\"\n\n// FIXME: Including \"Array-base.h\" will have implicitly instantiated\n// Array<octave_idx_type>.  Could that be an issue?\n\n#if ! defined (OCTAVE_EXTERN_TEMPLATE_ARRAY)\n// guard against double extern template declarations\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n\n#include <string>\n#include \"idx-vector.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-inttypes-fwd.h\"\n\n// \"Protect\" Array<T> instantiations that are exported by liboctave from\n// being implicitly instantiated in compilation units including this file.\n\n// Declare extern templates before including \"Array-base.cc\" to avoid\n// implicitly instantiating Array<octave::idx_vector>.\n\n// instantiated in Array-C.cc\nextern template class OCTAVE_API Array<Complex>;\n// instantiated in Array-b.cc\nextern template class OCTAVE_API Array<bool>;\n// instantiated in Array-ch.cc\nextern template class OCTAVE_API Array<char>;\n// instantiated in Array-d.cc\nextern template class OCTAVE_API Array<double>;\n// instantiated in Array-f.cc\nextern template class OCTAVE_API Array<float>;\n// instantiated in Array-fC.cc\nextern template class OCTAVE_API Array<FloatComplex>;\n// instantiated in Array-i.cc\nextern template class OCTAVE_API Array<signed char>;\n// extern template class Array<short>;\nextern template class OCTAVE_API Array<int>;\nextern template class OCTAVE_API Array<long>;\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\nextern template class OCTAVE_API Array<long long>;\n#endif\nextern template class OCTAVE_API Array<unsigned char>;\nextern template class OCTAVE_API Array<unsigned short>;\nextern template class OCTAVE_API Array<unsigned int>;\nextern template class OCTAVE_API Array<unsigned long>;\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\nextern template class OCTAVE_API Array<unsigned long long>;\n#endif\nextern template class OCTAVE_API Array<octave_int8>;\nextern template class OCTAVE_API Array<octave_int16>;\nextern template class OCTAVE_API Array<octave_int32>;\nextern template class OCTAVE_API Array<octave_int64>;\nextern template class OCTAVE_API Array<octave_uint8>;\nextern template class OCTAVE_API Array<octave_uint16>;\nextern template class OCTAVE_API Array<octave_uint32>;\nextern template class OCTAVE_API Array<octave_uint64>;\n// instantiated in Array-idx-vec.cc\nextern template class OCTAVE_API Array<octave::idx_vector>;\n// instantiated in Array-s.cc\nextern template class OCTAVE_API Array<short>;\n// instantiated in Array-str.cc\nextern template class OCTAVE_API Array<std::string>;\n// instantiated in Array-voidp.cc\nextern template class OCTAVE_API Array<void *>;\n\n#endif  // OCTAVE_EXTERN_TEMPLATE_ARRAY\n\n#include \"Array-base.cc\"\n"
  },
  {
    "path": "liboctave/array/Array-oct.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n\n// Include this file when instantiating the Array<T> template class with new\n// types in projects linking to \"liboctave\" but not to \"liboctinterp\".\n\n#if ! defined (octave_Array_oct_h)\n#define octave_Array_oct_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-base.h\"\n\n// FIXME: Including \"Array-base.h\" will have implicitly instantiated\n// Array<octave_idx_type>.  Could that be an issue?\n\n#if ! defined (OCTAVE_EXTERN_TEMPLATE_ARRAY)\n// guard against double extern template declarations\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n\n#include <string>\n#include \"idx-vector.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-inttypes-fwd.h\"\n\n// \"Protect\" Array<T> instantiations that are exported by liboctave from\n// being implicitly instantiated in compilation units including this file.\n\n// instantiated in Array-C.cc\nextern template class OCTAVE_API Array<Complex>;\n// instantiated in Array-b.cc\nextern template class OCTAVE_API Array<bool>;\n// instantiated in Array-ch.cc\nextern template class OCTAVE_API Array<char>;\n// instantiated in Array-d.cc\nextern template class OCTAVE_API Array<double>;\n// instantiated in Array-f.cc\nextern template class OCTAVE_API Array<float>;\n// instantiated in Array-fC.cc\nextern template class OCTAVE_API Array<FloatComplex>;\n// instantiated in Array-i.cc\nextern template class OCTAVE_API Array<signed char>;\n// extern template class Array<short>;\nextern template class OCTAVE_API Array<int>;\nextern template class OCTAVE_API Array<long>;\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\nextern template class OCTAVE_API Array<long long>;\n#endif\nextern template class OCTAVE_API Array<unsigned char>;\nextern template class OCTAVE_API Array<unsigned short>;\nextern template class OCTAVE_API Array<unsigned int>;\nextern template class OCTAVE_API Array<unsigned long>;\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\nextern template class OCTAVE_API Array<unsigned long long>;\n#endif\nextern template class OCTAVE_API Array<octave_int8>;\nextern template class OCTAVE_API Array<octave_int16>;\nextern template class OCTAVE_API Array<octave_int32>;\nextern template class OCTAVE_API Array<octave_int64>;\nextern template class OCTAVE_API Array<octave_uint8>;\nextern template class OCTAVE_API Array<octave_uint16>;\nextern template class OCTAVE_API Array<octave_uint32>;\nextern template class OCTAVE_API Array<octave_uint64>;\n// instantiated in Array-idx-vec.cc\nextern template class OCTAVE_API Array<octave::idx_vector>;\n// instantiated in Array-s.cc\nextern template class OCTAVE_API Array<short>;\n// instantiated in Array-str.cc\nextern template class OCTAVE_API Array<std::string>;\n// instantiated in Array-voidp.cc\nextern template class OCTAVE_API Array<void *>;\n\n#endif  // OCTAVE_EXTERN_TEMPLATE_ARRAY\n\n#endif\n"
  },
  {
    "path": "liboctave/array/Array-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Arrays of short int values.\n\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n\n#define INLINE_ASCENDING_SORT 1\n#define INLINE_DESCENDING_SORT 1\n#include \"oct-sort.cc\"\n\ntemplate class octave_sort<short>;\n\nINSTANTIATE_ARRAY (short, );\n\n#include \"DiagArray2.h\"\n#include \"DiagArray2.cc\"\n\ntemplate class DiagArray2<short>;\n"
  },
  {
    "path": "liboctave/array/Array-str.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n// Instantiate Arrays of strings.\n\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n\n#include \"oct-sort.cc\"\n\ntemplate class octave_sort<std::string>;\n\nINSTANTIATE_ARRAY (std::string, );\n"
  },
  {
    "path": "liboctave/array/Array-util.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-util.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n\nbool\nindex_in_bounds (const Array<octave_idx_type>& ra_idx,\n                 const dim_vector& dimensions)\n{\n  bool retval = true;\n\n  int n = ra_idx.numel ();\n\n  if (n == dimensions.ndims ())\n    {\n      for (int i = 0; i < n; i++)\n        {\n          if (ra_idx(i) < 0 || ra_idx(i) >= dimensions(i))\n            {\n              retval = false;\n              break;\n            }\n        }\n    }\n  else\n    retval = false;\n\n  return retval;\n}\n\nvoid\nincrement_index (Array<octave_idx_type>& ra_idx, const dim_vector& dimensions,\n                 int start_dimension)\n{\n  ra_idx(start_dimension)++;\n\n  int n = ra_idx.numel () - 1;\n  int nda = dimensions.ndims ();\n\n  for (int i = start_dimension; i < n; i++)\n    {\n      if (ra_idx(i) < (i < nda ? dimensions(i) : 1))\n        break;\n      else\n        {\n          ra_idx(i) = 0;\n          ra_idx(i+1)++;\n        }\n    }\n}\n\noctave_idx_type\nget_scalar_idx (Array<octave_idx_type>& idx, dim_vector& dims)\n{\n  octave_idx_type retval (-1);\n\n  int n = idx.numel ();\n\n  if (n > 0)\n    {\n      retval = idx(--n);\n\n      while (--n >= 0)\n        {\n          retval *= dims(n);\n\n          retval += idx(n);\n        }\n    }\n  return retval;\n}\n\noctave_idx_type\nnum_ones (const Array<octave_idx_type>& ra_idx)\n{\n  octave_idx_type retval = 0;\n\n  for (octave_idx_type i = 0; i < ra_idx.numel (); i++)\n    {\n      if (ra_idx(i) == 1)\n        retval++;\n    }\n\n  return retval;\n}\n\nbool\nis_scalar (const dim_vector& dim)\n{\n  bool retval = true;\n\n  int n = dim.ndims ();\n\n  if (n == 0)\n    retval = false;\n  else\n    {\n      for (int i = 0; i < n; i++)\n        {\n          if (dim(i) != 1)\n            {\n              retval = false;\n\n              break;\n            }\n        }\n    }\n  return retval;\n}\n\nbool\nisvector (const dim_vector& dim)\n{\n  int m = 0;\n  int n = dim.ndims ();\n\n  if (n == 0)\n    m = 2;\n  else\n    {\n      for (int i = 0; i < n; i++)\n        if (dim(i) > 1)\n          m++;\n        else if (dim(i) < 1)\n          m += 2;\n    }\n\n  return (m < 2);\n}\n\nbool\nany_ones (const Array<octave_idx_type>& arr)\n{\n  bool retval = false;\n\n  for (octave_idx_type i = 0; i < arr.numel (); i++)\n    {\n      if (arr (i) == 1)\n        {\n          retval = true;\n\n          break;\n        }\n    }\n  return retval;\n}\n\noctave_idx_type\ncompute_index (octave_idx_type n, const dim_vector& dims)\n{\n  if (n < 0)\n    octave::err_invalid_index (n, 1, 1);\n  if (n >= dims.numel ())\n    octave::err_index_out_of_range (1, 1, n+1, dims.numel (), dims);\n\n  return n;\n}\n\noctave_idx_type\ncompute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims)\n{\n  if (i < 0)\n    octave::err_invalid_index (i, 2, 1);\n  if (j < 0)\n    octave::err_invalid_index (j, 2, 2);\n  if (i >= dims(0))\n    octave::err_index_out_of_range (2, 1, i+1, dims(0), dims);\n  if (j >= dims.numel (1))\n    octave::err_index_out_of_range (2, 2, j+1, dims.numel (1), dims);\n\n  return j*dims(0) + i;\n}\n\noctave_idx_type\ncompute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k,\n               const dim_vector& dims)\n{\n  if (i < 0)\n    octave::err_invalid_index (i, 3, 1);\n  if (j < 0)\n    octave::err_invalid_index (j, 3, 2);\n  if (k < 0)\n    octave::err_invalid_index (k, 3, 3);\n  if (i >= dims(0))\n    octave::err_index_out_of_range (3, 1, i+1, dims(0), dims);\n  if (j >= dims(1))\n    octave::err_index_out_of_range (3, 2, j+1, dims(1), dims);\n  if (k >= dims.numel (2))\n    octave::err_index_out_of_range (3, 3, k+1, dims.numel (2), dims);\n\n  return (k*dims(1) + j)*dims(0) + i;\n}\n\noctave_idx_type\ncompute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims)\n{\n  int nd = ra_idx.numel ();\n  const dim_vector dv = dims.redim (nd);\n  for (int d = 0; d < nd; d++)\n    {\n      if (ra_idx(d) < 0)\n        octave::err_invalid_index (ra_idx(d), nd, d+1);\n      if (ra_idx(d) >= dv(d))\n        octave::err_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d), dims);\n    }\n\n  return dv.compute_index (ra_idx.data ());\n}\n\nArray<octave_idx_type>\nconv_to_int_array (const Array<octave::idx_vector>& a)\n{\n  Array<octave_idx_type> retval (a.dims ());\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    retval(i) = a(i).elem (0);\n\n  return retval;\n}\n\nArray<octave::idx_vector>\nconv_to_array (const octave::idx_vector *tmp, const octave_idx_type len)\n{\n  Array<octave::idx_vector> retval (dim_vector (len, 1));\n\n  for (octave_idx_type i = 0; i < len; i++)\n    retval(i) = tmp[i];\n\n  return retval;\n}\n\ndim_vector\nfreeze (Array<octave::idx_vector>& ra_idx, const dim_vector& dimensions, int resize_ok)\n{\n  dim_vector retval;\n\n  int n = ra_idx.numel ();\n\n  liboctave_panic_unless (n == dimensions.ndims ());\n\n  retval.resize (n);\n\n  static const char *tag[3] = { \"row\", \"column\", nullptr };\n\n  for (int i = 0; i < n; i++)\n    retval(i) = ra_idx(i).freeze (dimensions(i), tag[i < 2 ? i : 2],\n                                  resize_ok);\n\n  return retval;\n}\n\nbool\nvector_equivalent (const dim_vector& dv)\n{\n  int n = dv.ndims ();\n\n  bool found_first = false;\n\n  for (int i = 0; i < n; i++)\n    {\n      if (dv(i) != 1)\n        {\n          if (! found_first)\n            found_first = true;\n          else\n            return false;\n        }\n    }\n\n  return true;\n}\n\n// FIXME: Deprecated in Octave 9.\nbool\nall_ok (const Array<octave::idx_vector>& ra_idx)\n{\n  octave_unused_parameter (ra_idx);\n\n  // idx_vector objects are always valid once constructed\n  return true;\n}\n\nbool\nany_orig_empty (const Array<octave::idx_vector>& ra_idx)\n{\n  bool retval = false;\n\n  octave_idx_type n = ra_idx.numel ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      if (ra_idx(i).orig_empty ())\n        {\n          retval = true;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nbool\nall_colon_equiv (const Array<octave::idx_vector>& ra_idx,\n                 const dim_vector& frozen_lengths)\n{\n  bool retval = true;\n\n  octave_idx_type idx_n = ra_idx.numel ();\n\n  int n = frozen_lengths.ndims ();\n\n  if (idx_n != n)\n    (*current_liboctave_error_handler)\n      (\"unexpected: idx_n != n in all_colon_equiv - please report this bug\");\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      if (! ra_idx(i).is_colon_equiv (frozen_lengths(i)))\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nbool\nall_ones (const Array<octave_idx_type>& arr)\n{\n  bool retval = true;\n\n  for (octave_idx_type i = 0; i < arr.numel (); i++)\n    {\n      if (arr(i) != 1)\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nArray<octave_idx_type>\nget_elt_idx (const Array<octave::idx_vector>& ra_idx,\n             const Array<octave_idx_type>& result_idx)\n{\n  octave_idx_type n = ra_idx.numel ();\n\n  Array<octave_idx_type> retval (dim_vector (n, 1));\n\n  for (octave_idx_type i = 0; i < n; i++)\n    retval(i) = ra_idx(i).elem (result_idx(i));\n\n  return retval;\n}\n\nArray<octave_idx_type>\nget_ra_idx (octave_idx_type idx, const dim_vector& dims)\n{\n  Array<octave_idx_type> retval;\n\n  int n_dims = dims.ndims ();\n\n  retval.resize (dim_vector (n_dims, 1));\n\n  for (int i = 0; i < n_dims; i++)\n    retval(i) = 0;\n\n  liboctave_panic_unless (idx > 0 || idx < dims.numel ());\n\n  for (octave_idx_type i = 0; i < idx; i++)\n    increment_index (retval, dims);\n\n  // FIXME: the solution using increment_index is not efficient.\n\n  return retval;\n}\n\ndim_vector\nzero_dims_inquire (const Array<octave::idx_vector>& ia, const dim_vector& rhdv)\n{\n  int ial = ia.numel ();\n  int rhdvl = rhdv.ndims ();\n  dim_vector rdv = dim_vector::alloc (ial);\n  bool *scalar = new bool [ial];\n  bool *colon = new bool [ial];\n  // Mark scalars and colons, count nonscalar indices.\n  int nonsc = 0;\n  bool all_colons = true;\n  for (int i = 0; i < ial; i++)\n    {\n      // FIXME: should we check for length() instead?\n      scalar[i] = ia(i).is_scalar ();\n      colon[i] = ia(i).is_colon ();\n      if (! scalar[i]) nonsc++;\n      if (! colon[i]) rdv(i) = ia(i).extent (0);\n      all_colons = all_colons && colon[i];\n    }\n\n  // If the number of nonscalar indices matches the dimensionality of\n  // RHS, we try an exact match, inquiring even singleton dimensions.\n  if (all_colons)\n    {\n      rdv = rhdv;\n      rdv.resize (ial, 1);\n    }\n  else if (nonsc == rhdvl)\n    {\n      for (int i = 0, j = 0; i < ial; i++)\n        {\n          if (scalar[i]) continue;\n          if (colon[i])\n            rdv(i) = rhdv(j);\n          j++;\n        }\n    }\n  else\n    {\n      dim_vector rhdv0 = rhdv;\n      rhdv0.chop_all_singletons ();\n      int rhdv0l = rhdv0.ndims ();\n      for (int i = 0, j = 0; i < ial; i++)\n        {\n          if (scalar[i]) continue;\n          if (colon[i])\n            rdv(i) = (j < rhdv0l) ? rhdv0(j++) : 1;\n        }\n    }\n\n  delete [] scalar;\n  delete [] colon;\n\n  return rdv;\n}\n\ndim_vector\nzero_dims_inquire (const octave::idx_vector& i, const octave::idx_vector& j,\n                   const dim_vector& rhdv)\n{\n  bool icol = i.is_colon ();\n  bool jcol = j.is_colon ();\n  dim_vector rdv;\n  if (icol && jcol && rhdv.ndims () == 2)\n    {\n      rdv(0) = rhdv(0);\n      rdv(1) = rhdv(1);\n    }\n  else if (rhdv.ndims () == 2\n           && ! i.is_scalar () && ! j.is_scalar ())\n    {\n      rdv(0) = (icol ? rhdv(0) : i.extent (0));\n      rdv(1) = (jcol ? rhdv(1) : j.extent (0));\n    }\n  else\n    {\n      dim_vector rhdv0 = rhdv;\n      rhdv0.chop_all_singletons ();\n      int k = 0;\n      rdv(0) = i.extent (0);\n      if (icol)\n        rdv(0) = rhdv0(k++);\n      else if (! i.is_scalar ())\n        k++;\n      rdv(1) = j.extent (0);\n      if (jcol)\n        rdv(1) = rhdv0(k++);\n      else if (! j.is_scalar ())\n        k++;\n    }\n\n  return rdv;\n}\n\noctave::idx_vector\nsub2ind (const dim_vector& dv, const Array<octave::idx_vector>& idxa)\n{\n  octave::idx_vector retval;\n  octave_idx_type len = idxa.numel ();\n\n  if (len == 0)\n    (*current_liboctave_error_handler) (\"sub2ind: needs at least 2 indices\");\n\n  const dim_vector dvx = dv.redim (len);\n  bool all_ranges = true;\n  octave_idx_type clen = -1;\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      try\n        {\n          octave::idx_vector idx = idxa(i);\n          octave_idx_type n = dvx(i);\n\n          all_ranges = all_ranges && idx.is_range ();\n          if (clen < 0)\n            clen = idx.length (n);\n          else if (clen != idx.length (n))\n            (*current_liboctave_error_handler)\n              (\"sub2ind: lengths of indices must match\");\n\n          if (idx.extent (n) > n)\n            octave::err_index_out_of_range (len, i+1, idx.extent (n), n, dv);\n        }\n      catch (octave::index_exception& ie)\n        {\n          ie.set_pos_if_unset (len, i+1);\n          ie.set_var ();\n          std::string msg = ie.message ();\n          (*current_liboctave_error_with_id_handler)\n            (ie.err_id (), \"%s\", msg.c_str ());\n        }\n    }\n  // idxa known to be valid.\n  // Shouldn't need to catch index_exception below here.\n\n  if (len == 1)\n    retval = idxa(0);\n  else if (clen == 1)\n    {\n      // All scalars case - the result is a scalar.\n      octave_idx_type idx = idxa(len-1)(0);\n      for (octave_idx_type i = len - 2; i >= 0; i--)\n        idx = dvx(i) * idx + idxa(i)(0);\n      retval = octave::idx_vector (idx);\n    }\n  else if (all_ranges && clen != 0)\n    {\n      // All ranges case - the result is a range.\n      octave_idx_type start = 0;\n      octave_idx_type step = 0;\n      for (octave_idx_type i = len - 1; i >= 0; i--)\n        {\n          octave_idx_type xstart = idxa(i)(0);\n          octave_idx_type xstep = idxa(i)(1) - xstart;\n          start = dvx(i) * start + xstart;\n          step = dvx(i) * step + xstep;\n        }\n      retval = octave::idx_vector::make_range (start, step, clen);\n    }\n  else\n    {\n      Array<octave_idx_type> idx (idxa(0).orig_dimensions ());\n\n      for (octave_idx_type i = len - 1; i >= 0; i--)\n        {\n          // Initialized inside the loop so that each call to\n          // idx_vector::loop operates from the beginning of IDX_VEC.\n\n          octave_idx_type *idx_vec = idx.rwdata ();\n\n          if (i < len - 1)\n            idxa(i).loop (clen, [n = dvx(i), &idx_vec] (octave_idx_type k) { (*idx_vec++ *= n) += k; });\n          else\n            idxa(i).copy_data (idx_vec);\n        }\n\n      retval = octave::idx_vector (idx);\n    }\n\n  return retval;\n}\n\nArray<octave::idx_vector>\nind2sub (const dim_vector& dv, const octave::idx_vector& idx)\n{\n  octave_idx_type len = idx.length (0);\n  octave_idx_type n = dv.ndims ();\n  Array<octave::idx_vector> retval (dim_vector (n, 1));\n  octave_idx_type numel = dv.numel ();\n\n  if (idx.is_scalar ())\n    {\n      octave_idx_type k = idx(0);\n      for (octave_idx_type j = 0; j < n-1; j++)\n        {\n          retval(j) = k % dv(j);\n          k /= dv(j);\n        }\n\n      retval(n-1) = idx(0) < numel ? k % dv(n-1) : k;\n    }\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (Array<octave_idx_type>, rdata, n);\n\n      const dim_vector& odv = idx.orig_dimensions ();\n      for (octave_idx_type j = 0; j < n; j++)\n        rdata[j] = Array<octave_idx_type> (odv);\n\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          octave_idx_type k = idx(i);\n          for (octave_idx_type j = 0; j < n-1; j++)\n            {\n              rdata[j](i) = k % dv(j);\n              k /= dv(j);\n            }\n\n          rdata[n-1](i) = idx(i) < numel ? k % dv(n-1) : k;\n        }\n\n      for (octave_idx_type j = 0; j < n; j++)\n        retval(j) = rdata[j];\n    }\n\n  return retval;\n}\n\nint\npermute_vector_compare (const void *a, const void *b)\n{\n  const permute_vector *pva = static_cast<const permute_vector *> (a);\n  const permute_vector *pvb = static_cast<const permute_vector *> (b);\n\n  return pva->pidx > pvb->pidx;\n}\n"
  },
  {
    "path": "liboctave/array/Array-util.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2000-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Array_util_h)\n#define octave_Array_util_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-oct.h\"\n#include \"lo-array-errwarn.h\"\n\nextern OCTAVE_API bool index_in_bounds (const Array<octave_idx_type>& ra_idx,\n                                        const dim_vector& dimensions);\n\nextern OCTAVE_API void increment_index (Array<octave_idx_type>& ra_idx,\n                                        const dim_vector& dimensions,\n                                        int start_dimension = 0);\n\nextern OCTAVE_API octave_idx_type get_scalar_idx (Array<octave_idx_type>& idx,\n                                                  dim_vector& dims);\n\nextern OCTAVE_API octave_idx_type num_ones (const Array<octave_idx_type>&\n                                            ra_idx);\n\nextern OCTAVE_API bool is_scalar (const dim_vector& dim);\n\nextern OCTAVE_API bool isvector (const dim_vector& dim);\n\nextern OCTAVE_API bool any_ones (const Array<octave_idx_type>& arr);\n\n// These four compute a linear index for given dimensions, throwing\n// exceptions on invalid indices.\nextern OCTAVE_API octave_idx_type\ncompute_index (octave_idx_type n, const dim_vector& dims);\n\nextern OCTAVE_API octave_idx_type\ncompute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims);\n\nextern OCTAVE_API octave_idx_type\ncompute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k,\n               const dim_vector& dims);\n\nextern OCTAVE_API octave_idx_type\ncompute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims);\n\nextern OCTAVE_API Array<octave_idx_type>\nconv_to_int_array (const Array<octave::idx_vector>& a);\n\nextern OCTAVE_API Array<octave::idx_vector>\nconv_to_array (const octave::idx_vector *tmp, const octave_idx_type len);\n\nextern OCTAVE_API dim_vector\nfreeze (Array<octave::idx_vector>& ra_idx, const dim_vector& dimensions,\n        int resize_ok);\n\nextern OCTAVE_API bool vector_equivalent (const dim_vector& dv);\n\nextern OCTAVE_API bool\nany_orig_empty (const Array<octave::idx_vector>& ra_idx);\n\nextern OCTAVE_API bool\nall_colon_equiv (const Array<octave::idx_vector>& ra_idx,\n                 const dim_vector& frozen_lengths);\n\nextern OCTAVE_API bool all_ones (const Array<octave_idx_type>& arr);\n\nextern OCTAVE_API Array<octave_idx_type>\nget_elt_idx (const Array<octave::idx_vector>& ra_idx,\n             const Array<octave_idx_type>& result_idx);\n\nextern OCTAVE_API Array<octave_idx_type> get_ra_idx (octave_idx_type idx,\n                                                     const dim_vector& dims);\n\nextern OCTAVE_API dim_vector\nzero_dims_inquire (const Array<octave::idx_vector>& ia, const dim_vector& rhdv);\n\nextern OCTAVE_API dim_vector\nzero_dims_inquire (const octave::idx_vector& i, const octave::idx_vector& j,\n                   const dim_vector& rhdv);\n\nextern OCTAVE_API octave::idx_vector\nsub2ind (const dim_vector& dv, const Array<octave::idx_vector>& idxa);\n\nextern OCTAVE_API Array<octave::idx_vector>\nind2sub (const dim_vector& dv, const octave::idx_vector& idx);\n\nstruct\npermute_vector\n{\n  octave_idx_type pidx;\n  octave_idx_type iidx;\n};\n\nextern int OCTAVE_API permute_vector_compare (const void *a, const void *b);\n\n#endif\n"
  },
  {
    "path": "liboctave/array/Array-voidp.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Arrays of void *.\n\n#define OCTAVE_EXTERN_TEMPLATE_ARRAY\n#include \"Array-oct.h\"\n\n// Prevent implicit instantiations on some systems (Windows, others?)\n// that can lead to duplicate definitions of static data members.\n\nextern template class OCTAVE_API Array<octave::idx_vector>;\nextern template class Array<octave_idx_type>;\n\n#include \"Array-base.cc\"\n\nNO_INSTANTIATE_ARRAY_SORT_API (void *, OCTAVE_API);\n\nINSTANTIATE_ARRAY (void *, );\n"
  },
  {
    "path": "liboctave/array/CColVector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"blas-proto.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// Complex Column Vector class\n\nComplexColumnVector::ComplexColumnVector (const ColumnVector& a)\n  : MArray<Complex> (a)\n{ }\n\nbool\nComplexColumnVector::operator == (const ComplexColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  if (len != a.numel ())\n    return 0;\n  return mx_inline_equal (len, data (), a.data ());\n}\n\nbool\nComplexColumnVector::operator != (const ComplexColumnVector& a) const\n{\n  return !(*this == a);\n}\n\n// destructive insert/delete/reorder operations\n\nComplexColumnVector&\nComplexColumnVector::insert (const ColumnVector& a, octave_idx_type r)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nComplexColumnVector&\nComplexColumnVector::insert (const ComplexColumnVector& a, octave_idx_type r)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nComplexColumnVector&\nComplexColumnVector::fill (double val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nComplexColumnVector&\nComplexColumnVector::fill (const Complex& val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nComplexColumnVector&\nComplexColumnVector::fill (double val, octave_idx_type r1, octave_idx_type r2)\n{\n  octave_idx_type len = numel ();\n\n  if (r1 < 0 || r2 < 0 || r1 >= len || r2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  if (r2 >= r1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = r1; i <= r2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nComplexColumnVector&\nComplexColumnVector::fill (const Complex& val,\n                           octave_idx_type r1, octave_idx_type r2)\n{\n  octave_idx_type len = numel ();\n\n  if (r1 < 0 || r2 < 0 || r1 >= len || r2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  if (r2 >= r1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = r1; i <= r2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nComplexColumnVector\nComplexColumnVector::stack (const ColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nr_insert = len;\n  ComplexColumnVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nr_insert);\n  return retval;\n}\n\nComplexColumnVector\nComplexColumnVector::stack (const ComplexColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nr_insert = len;\n  ComplexColumnVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nr_insert);\n  return retval;\n}\n\nComplexRowVector\nComplexColumnVector::hermitian () const\n{\n  return MArray<Complex>::hermitian (std::conj);\n}\n\nComplexRowVector\nComplexColumnVector::transpose () const\n{\n  return MArray<Complex>::transpose ();\n}\n\nColumnVector\nComplexColumnVector::abs () const\n{\n  return do_mx_unary_map<double, Complex, std::abs> (*this);\n}\n\nComplexColumnVector\nconj (const ComplexColumnVector& a)\n{\n  return do_mx_unary_map<Complex, Complex, std::conj<double>> (a);\n}\n\n// resize is the destructive equivalent for this one\n\nComplexColumnVector\nComplexColumnVector::extract (octave_idx_type r1, octave_idx_type r2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  octave_idx_type new_r = r2 - r1 + 1;\n\n  ComplexColumnVector result (new_r);\n\n  for (octave_idx_type i = 0; i < new_r; i++)\n    result.elem (i) = elem (r1+i);\n\n  return result;\n}\n\nComplexColumnVector\nComplexColumnVector::extract_n (octave_idx_type r1, octave_idx_type n) const\n{\n  ComplexColumnVector result (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    result.elem (i) = elem (r1+i);\n\n  return result;\n}\n\n// column vector by column vector -> column vector operations\n\nComplexColumnVector&\nComplexColumnVector::operator += (const ColumnVector& a)\n{\n  octave_idx_type len = numel ();\n\n  octave_idx_type a_len = a.numel ();\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator +=\", len, a_len);\n\n  if (len == 0)\n    return *this;\n\n  Complex *d = rwdata (); // Ensures only one reference to my privates!\n\n  mx_inline_add2 (len, d, a.data ());\n  return *this;\n}\n\nComplexColumnVector&\nComplexColumnVector::operator -= (const ColumnVector& a)\n{\n  octave_idx_type len = numel ();\n\n  octave_idx_type a_len = a.numel ();\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator -=\", len, a_len);\n\n  if (len == 0)\n    return *this;\n\n  Complex *d = rwdata (); // Ensures only one reference to my privates!\n\n  mx_inline_sub2 (len, d, a.data ());\n  return *this;\n}\n\n// matrix by column vector -> column vector operations\n\nComplexColumnVector\noperator * (const ComplexMatrix& m, const ColumnVector& a)\n{\n  ComplexColumnVector tmp (a);\n  return m * tmp;\n}\n\nComplexColumnVector\noperator * (const ComplexMatrix& m, const ComplexColumnVector& a)\n{\n  ComplexColumnVector retval;\n\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  retval.clear (nr);\n\n  if (nr != 0)\n    {\n      if (nc == 0)\n        retval.fill (0.0);\n      else\n        {\n          Complex *y = retval.rwdata ();\n\n          F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                                   nr, nc, 1.0,\n                                   F77_CONST_DBLE_CMPLX_ARG (m.data ()), nr,\n                                   F77_CONST_DBLE_CMPLX_ARG (a.data ()), 1, 0.0,\n                                   F77_DBLE_CMPLX_ARG (y), 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n    }\n\n  return retval;\n}\n\n// matrix by column vector -> column vector operations\n\nComplexColumnVector\noperator * (const Matrix& m, const ComplexColumnVector& a)\n{\n  ComplexMatrix tmp (m);\n  return tmp * a;\n}\n\n// diagonal matrix by column vector -> column vector operations\n\nComplexColumnVector\noperator * (const DiagMatrix& m, const ComplexColumnVector& a)\n{\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  if (nc == 0 || nr == 0)\n    return ComplexColumnVector (0);\n\n  ComplexColumnVector result (nr);\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    result.elem (i) = a.elem (i) * m.elem (i, i);\n\n  for (octave_idx_type i = a_len; i < nr; i++)\n    result.elem (i) = 0.0;\n\n  return result;\n}\n\nComplexColumnVector\noperator * (const ComplexDiagMatrix& m, const ColumnVector& a)\n{\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  if (nc == 0 || nr == 0)\n    return ComplexColumnVector (0);\n\n  ComplexColumnVector result (nr);\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    result.elem (i) = a.elem (i) * m.elem (i, i);\n\n  for (octave_idx_type i = a_len; i < nr; i++)\n    result.elem (i) = 0.0;\n\n  return result;\n}\n\nComplexColumnVector\noperator * (const ComplexDiagMatrix& m, const ComplexColumnVector& a)\n{\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  if (nc == 0 || nr == 0)\n    return ComplexColumnVector (0);\n\n  ComplexColumnVector result (nr);\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    result.elem (i) = a.elem (i) * m.elem (i, i);\n\n  for (octave_idx_type i = a_len; i < nr; i++)\n    result.elem (i) = 0.0;\n\n  return result;\n}\n\n// other operations\n\nComplex\nComplexColumnVector::min () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0.0;\n\n  Complex res = elem (0);\n  double absres = std::abs (res);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (std::abs (elem (i)) < absres)\n      {\n        res = elem (i);\n        absres = std::abs (res);\n      }\n\n  return res;\n}\n\nComplex\nComplexColumnVector::max () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0.0;\n\n  Complex res = elem (0);\n  double absres = std::abs (res);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (std::abs (elem (i)) > absres)\n      {\n        res = elem (i);\n        absres = std::abs (res);\n      }\n\n  return res;\n}\n\n// i/o\n\nstd::ostream&\noperator << (std::ostream& os, const ComplexColumnVector& a)\n{\n//  int field_width = os.precision () + 7;\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    os << /* setw (field_width) << */ a.elem (i) << \"\\n\";\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, ComplexColumnVector& a)\n{\n  octave_idx_type len = a.numel ();\n\n  if (len > 0)\n    {\n      double tmp;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          is >> tmp;\n          if (is)\n            a.elem (i) = tmp;\n          else\n            break;\n        }\n    }\n  return is;\n}\n"
  },
  {
    "path": "liboctave/array/CColVector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_CColVector_h)\n#define octave_CColVector_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API ComplexColumnVector : public MArray<Complex>\n{\n  friend class ComplexMatrix;\n  friend class ComplexRowVector;\n\npublic:\n\n  ComplexColumnVector () : MArray<Complex> (dim_vector (0, 1)) { }\n\n  explicit ComplexColumnVector (octave_idx_type n)\n    : MArray<Complex> (dim_vector (n, 1)) { }\n\n  explicit ComplexColumnVector (const dim_vector& dv)\n    : MArray<Complex> (dv.as_column ()) { }\n\n  ComplexColumnVector (octave_idx_type n, const Complex& val)\n    : MArray<Complex> (dim_vector (n, 1), val) { }\n\n  ComplexColumnVector (const ComplexColumnVector& a) : MArray<Complex> (a) { }\n\n  ComplexColumnVector (const MArray<Complex>& a)\n    : MArray<Complex> (a.as_column ()) { }\n\n  ComplexColumnVector (const Array<Complex>& a)\n    : MArray<Complex> (a.as_column ()) { }\n\n  explicit OCTAVE_API ComplexColumnVector (const ColumnVector& a);\n\n  ComplexColumnVector& operator = (const ComplexColumnVector& a)\n  {\n    MArray<Complex>::operator = (a);\n    return *this;\n  }\n\n  ~ComplexColumnVector () = default;\n\n  OCTAVE_API bool operator == (const ComplexColumnVector& a) const;\n  OCTAVE_API bool operator != (const ComplexColumnVector& a) const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API ComplexColumnVector&\n  insert (const ColumnVector& a, octave_idx_type r);\n  OCTAVE_API ComplexColumnVector&\n  insert (const ComplexColumnVector& a, octave_idx_type r);\n\n  OCTAVE_API ComplexColumnVector& fill (double val);\n  OCTAVE_API ComplexColumnVector& fill (const Complex& val);\n  OCTAVE_API ComplexColumnVector&\n  fill (double val, octave_idx_type r1, octave_idx_type r2);\n  OCTAVE_API ComplexColumnVector&\n  fill (const Complex& val, octave_idx_type r1, octave_idx_type r2);\n\n  OCTAVE_API ComplexColumnVector stack (const ColumnVector& a) const;\n  OCTAVE_API ComplexColumnVector stack (const ComplexColumnVector& a) const;\n\n  OCTAVE_API ComplexRowVector hermitian () const;\n  OCTAVE_API ComplexRowVector transpose () const;\n\n  friend OCTAVE_API ComplexColumnVector conj (const ComplexColumnVector& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API ComplexColumnVector\n  extract (octave_idx_type r1, octave_idx_type r2) const;\n\n  OCTAVE_API ComplexColumnVector\n  extract_n (octave_idx_type r1, octave_idx_type n) const;\n\n  // column vector by column vector -> column vector operations\n\n  OCTAVE_API ComplexColumnVector& operator += (const ColumnVector& a);\n  OCTAVE_API ComplexColumnVector& operator -= (const ColumnVector& a);\n\n  // matrix by column vector -> column vector operations\n\n  friend OCTAVE_API ComplexColumnVector operator * (const ComplexMatrix& a,\n                                                    const ColumnVector& b);\n\n  friend OCTAVE_API ComplexColumnVector operator * (const ComplexMatrix& a,\n                                                    const ComplexColumnVector& b);\n\n  // matrix by column vector -> column vector operations\n\n  friend OCTAVE_API ComplexColumnVector operator * (const Matrix& a,\n                                                    const ComplexColumnVector& b);\n\n  // diagonal matrix by column vector -> column vector operations\n\n  friend OCTAVE_API ComplexColumnVector operator * (const DiagMatrix& a,\n                                                    const ComplexColumnVector& b);\n\n  friend OCTAVE_API ComplexColumnVector operator * (const ComplexDiagMatrix& a,\n                                                    const ColumnVector& b);\n\n  friend OCTAVE_API ComplexColumnVector operator * (const ComplexDiagMatrix& a,\n                                                    const ComplexColumnVector& b);\n\n  // other operations\n\n  OCTAVE_API Complex min () const;\n  OCTAVE_API Complex max () const;\n\n  OCTAVE_API ColumnVector abs () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream& operator << (std::ostream& os,\n                                               const ComplexColumnVector& a);\n  friend OCTAVE_API std::istream& operator >> (std::istream& is,\n                                               ComplexColumnVector& a);\n\n  void resize (octave_idx_type n, const Complex& rfv = Complex (0))\n  {\n    Array<Complex>::resize (dim_vector (n, 1), rfv);\n  }\n\n  void clear (octave_idx_type n)\n  { Array<Complex>::clear (n, 1); }\n\n};\n\nMARRAY_FORWARD_DEFS (MArray, ComplexColumnVector, Complex)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/CDiagMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"lo-ieee.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// Complex Diagonal Matrix class\n\nComplexDiagMatrix::ComplexDiagMatrix (const DiagMatrix& a)\n  : MDiagArray2<Complex> (a.rows (), a.cols ())\n{\n  for (octave_idx_type i = 0; i < length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nbool\nComplexDiagMatrix::operator == (const ComplexDiagMatrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return 0;\n\n  return mx_inline_equal (length (), data (), a.data ());\n}\n\nbool\nComplexDiagMatrix::operator != (const ComplexDiagMatrix& a) const\n{\n  return !(*this == a);\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (double val)\n{\n  for (octave_idx_type i = 0; i < length (); i++)\n    elem (i, i) = val;\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const Complex& val)\n{\n  for (octave_idx_type i = 0; i < length (); i++)\n    elem (i, i) = val;\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (double val, octave_idx_type beg, octave_idx_type end)\n{\n  if (beg < 0 || end >= length () || end < beg)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = beg; i <= end; i++)\n    elem (i, i) = val;\n\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const Complex& val,\n                         octave_idx_type beg, octave_idx_type end)\n{\n  if (beg < 0 || end >= length () || end < beg)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = beg; i <= end; i++)\n    elem (i, i) = val;\n\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const ColumnVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const ComplexColumnVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const RowVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const ComplexRowVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const ColumnVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const ComplexColumnVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const RowVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nComplexDiagMatrix&\nComplexDiagMatrix::fill (const ComplexRowVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nDiagMatrix\nComplexDiagMatrix::abs () const\n{\n  return DiagMatrix (extract_diag ().abs (), rows (), columns ());\n}\n\nComplexDiagMatrix\nconj (const ComplexDiagMatrix& a)\n{\n  return ComplexDiagMatrix (conj (a.extract_diag ()), a.rows (), a.columns ());\n}\n\n// resize is the destructive analog for this one\n\nComplexMatrix\nComplexDiagMatrix::extract (octave_idx_type r1, octave_idx_type c1,\n                            octave_idx_type r2, octave_idx_type c2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  octave_idx_type new_r = r2 - r1 + 1;\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  ComplexMatrix result (new_r, new_c);\n\n  for (octave_idx_type j = 0; j < new_c; j++)\n    for (octave_idx_type i = 0; i < new_r; i++)\n      result.elem (i, j) = elem (r1+i, c1+j);\n\n  return result;\n}\n\n// extract row or column i.\n\nComplexRowVector\nComplexDiagMatrix::row (octave_idx_type i) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (i < 0 || i >= r)\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n\n  ComplexRowVector retval (c, 0.0);\n  if (r <= c || i < c)\n    retval.elem (i) = elem (i, i);\n\n  return retval;\n}\n\nComplexRowVector\nComplexDiagMatrix::row (char *s) const\n{\n  if (! s)\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n\n  char c = s[0];\n  if (c == 'f' || c == 'F')\n    return row (static_cast<octave_idx_type> (0));\n  else if (c == 'l' || c == 'L')\n    return row (rows () - 1);\n  else\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n}\n\nComplexColumnVector\nComplexDiagMatrix::column (octave_idx_type i) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (i < 0 || i >= c)\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n\n  ComplexColumnVector retval (r, 0.0);\n  if (r >= c || i < r)\n    retval.elem (i) = elem (i, i);\n\n  return retval;\n}\n\nComplexColumnVector\nComplexDiagMatrix::column (char *s) const\n{\n  if (! s)\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n\n  char c = s[0];\n  if (c == 'f' || c == 'F')\n    return column (static_cast<octave_idx_type> (0));\n  else if (c == 'l' || c == 'L')\n    return column (cols () - 1);\n  else\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n}\n\nComplexDiagMatrix\nComplexDiagMatrix::inverse () const\n{\n  octave_idx_type info;\n  return inverse (info);\n}\n\nComplexDiagMatrix\nComplexDiagMatrix::inverse (octave_idx_type& info) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (r != c)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  ComplexDiagMatrix retval (r, c);\n\n  info = 0;\n  octave_idx_type len = r;        // alias for readability\n  octave_idx_type z_count  = 0;   // zeros\n  octave_idx_type nz_count = 0;   // nonzeros\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      if (xelem (i, i) == 0.0)\n        {\n          z_count++;\n          if (nz_count > 0)\n            break;\n        }\n      else\n        {\n          nz_count++;\n          if (z_count > 0)\n            break;\n          retval.elem (i, i) = 1.0 / xelem (i, i);\n        }\n    }\n  if (nz_count == 0)\n    {\n      (*current_liboctave_error_handler)\n        (\"inverse of the null matrix not defined\");\n    }\n  else if (z_count > 0)\n    {\n      info = -1;\n      element_type *data = retval.rwdata ();\n      std::fill (data, data + len, octave::numeric_limits<double>::Inf ());\n    }\n\n  return retval;\n}\n\nComplexDiagMatrix\nComplexDiagMatrix::pseudo_inverse (double tol) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  octave_idx_type len = length ();\n\n  ComplexDiagMatrix retval (c, r);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      double val = std::abs (elem (i, i));\n      if (val < tol || val == 0.0)\n        retval.elem (i, i) = 0.0;\n      else\n        retval.elem (i, i) = 1.0 / elem (i, i);\n    }\n\n  return retval;\n}\n\nbool\nComplexDiagMatrix::all_elements_are_real () const\n{\n  return mx_inline_all_real (length (), data ());\n}\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\nComplexDiagMatrix&\nComplexDiagMatrix::operator += (const DiagMatrix& a)\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r != a_nr || c != a_nc)\n    octave::err_nonconformant (\"operator +=\", r, c, a_nr, a_nc);\n\n  if (r == 0 || c == 0)\n    return *this;\n\n  Complex *d = rwdata (); // Ensures only one reference to my privates!\n\n  mx_inline_add2 (length (), d, a.data ());\n  return *this;\n}\n\nComplexDiagMatrix\noperator * (const ComplexDiagMatrix& a, const DiagMatrix& b)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  ComplexDiagMatrix c (a_nr, b_nc);\n\n  octave_idx_type len = c.length ();\n  octave_idx_type lenm = std::min (len, a_nc);\n\n  for (octave_idx_type i = 0; i < lenm; i++)\n    c.dgxelem (i) = a.dgelem (i) * b.dgelem (i);\n  for (octave_idx_type i = lenm; i < len; i++)\n    c.dgxelem (i) = 0.0;\n\n  return c;\n}\n\nComplexDiagMatrix\noperator * (const DiagMatrix& a, const ComplexDiagMatrix& b)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  if (a_nr == 0 || a_nc == 0 || b_nc == 0)\n    return ComplexDiagMatrix (a_nr, a_nc, 0.0);\n\n  ComplexDiagMatrix c (a_nr, b_nc);\n\n  octave_idx_type len = std::min (a_nr, b_nc);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      double a_element = a.elem (i, i);\n      Complex b_element = b.elem (i, i);\n\n      c.elem (i, i) = a_element * b_element;\n    }\n\n  return c;\n}\n\nComplexDiagMatrix\noperator * (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  if (a_nr == 0 || a_nc == 0 || b_nc == 0)\n    return ComplexDiagMatrix (a_nr, a_nc, 0.0);\n\n  ComplexDiagMatrix c (a_nr, b_nc);\n\n  octave_idx_type len = std::min (a_nr, b_nc);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      Complex a_element = a.elem (i, i);\n      Complex b_element = b.elem (i, i);\n\n      c.elem (i, i) = a_element * b_element;\n    }\n\n  return c;\n}\n\n// other operations\n\nComplexDET\nComplexDiagMatrix::determinant () const\n{\n  ComplexDET det (1.0);\n  if (rows () != cols ())\n    (*current_liboctave_error_handler) (\"determinant requires square matrix\");\n\n  octave_idx_type len = length ();\n  for (octave_idx_type i = 0; i < len; i++)\n    det *= elem (i, i);\n\n  return det;\n}\n\ndouble\nComplexDiagMatrix::rcond () const\n{\n  ColumnVector av = extract_diag (0).map<double> (std::abs);\n  double amx = av.max ();\n  double amn = av.min ();\n  return amx == 0 ? 0.0 : amn / amx;\n}\n\n// i/o\n\nstd::ostream&\noperator << (std::ostream& os, const ComplexDiagMatrix& a)\n{\n  Complex ZERO (0.0);\n//  int field_width = os.precision () + 7;\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    {\n      for (octave_idx_type j = 0; j < a.cols (); j++)\n        {\n          if (i == j)\n            os << ' ' /* setw (field_width) */ << a.elem (i, i);\n          else\n            os << ' ' /* setw (field_width) */ << ZERO;\n        }\n      os << \"\\n\";\n    }\n  return os;\n}\n"
  },
  {
    "path": "liboctave/array/CDiagMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_CDiagMatrix_h)\n#define octave_CDiagMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"CColVector.h\"\n#include \"CRowVector.h\"\n#include \"DET.h\"\n#include \"MDiagArray2.h\"\n#include \"dColVector.h\"\n#include \"dRowVector.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API ComplexDiagMatrix : public MDiagArray2<Complex>\n{\npublic:\n\n  typedef ComplexMatrix full_matrix_type;\n\n  typedef double real_elt_type;\n  typedef Complex complex_elt_type;\n  typedef Complex element_type;\n\n  ComplexDiagMatrix () = default;\n\n  ComplexDiagMatrix (const ComplexDiagMatrix& a) = default;\n\n  ComplexDiagMatrix& operator = (const ComplexDiagMatrix& a) = default;\n\n  ~ComplexDiagMatrix () = default;\n\n  ComplexDiagMatrix (octave_idx_type r, octave_idx_type c)\n    : MDiagArray2<Complex> (r, c) { }\n\n  ComplexDiagMatrix (octave_idx_type r, octave_idx_type c, const Complex& val)\n    : MDiagArray2<Complex> (r, c, val) { }\n\n  explicit ComplexDiagMatrix (const Array<Complex>& a)\n    : MDiagArray2<Complex> (a) { }\n\n  explicit ComplexDiagMatrix (const Array<double>& a)\n    : MDiagArray2<Complex> (Array<Complex> (a)) { }\n\n  ComplexDiagMatrix (const Array<Complex>& a, octave_idx_type r,\n                     octave_idx_type c)\n    : MDiagArray2<Complex> (a, r, c) { }\n\n  explicit OCTAVE_API ComplexDiagMatrix (const DiagMatrix& a);\n\n  ComplexDiagMatrix (const MDiagArray2<Complex>& a)\n    : MDiagArray2<Complex> (a) { }\n\n  template <typename U>\n  ComplexDiagMatrix (const DiagArray2<U>& a)\n    : MDiagArray2<Complex> (a) { }\n\n  OCTAVE_API bool operator == (const ComplexDiagMatrix& a) const;\n  OCTAVE_API bool operator != (const ComplexDiagMatrix& a) const;\n\n  OCTAVE_API ComplexDiagMatrix& fill (double val);\n  OCTAVE_API ComplexDiagMatrix& fill (const Complex& val);\n  OCTAVE_API ComplexDiagMatrix&\n  fill (double val, octave_idx_type beg, octave_idx_type end);\n  OCTAVE_API ComplexDiagMatrix&\n  fill (const Complex& val, octave_idx_type beg, octave_idx_type end);\n  OCTAVE_API ComplexDiagMatrix& fill (const ColumnVector& a);\n  OCTAVE_API ComplexDiagMatrix& fill (const ComplexColumnVector& a);\n  OCTAVE_API ComplexDiagMatrix& fill (const RowVector& a);\n  OCTAVE_API ComplexDiagMatrix& fill (const ComplexRowVector& a);\n  OCTAVE_API ComplexDiagMatrix&\n  fill (const ColumnVector& a, octave_idx_type beg);\n  OCTAVE_API ComplexDiagMatrix&\n  fill (const ComplexColumnVector& a, octave_idx_type beg);\n  OCTAVE_API ComplexDiagMatrix& fill (const RowVector& a, octave_idx_type beg);\n  OCTAVE_API ComplexDiagMatrix&\n  fill (const ComplexRowVector& a, octave_idx_type beg);\n\n  ComplexDiagMatrix hermitian () const\n  { return MDiagArray2<Complex>::hermitian (std::conj); }\n  ComplexDiagMatrix transpose () const\n  { return MDiagArray2<Complex>::transpose (); }\n  DiagMatrix abs () const;\n\n  friend OCTAVE_API ComplexDiagMatrix conj (const ComplexDiagMatrix& a);\n\n  // resize is the destructive analog for this one\n\n  OCTAVE_API ComplexMatrix\n  extract (octave_idx_type r1, octave_idx_type c1,\n           octave_idx_type r2, octave_idx_type c2) const;\n\n  // extract row or column i\n\n  OCTAVE_API ComplexRowVector row (octave_idx_type i) const;\n  OCTAVE_API ComplexRowVector row (char *s) const;\n\n  OCTAVE_API ComplexColumnVector column (octave_idx_type i) const;\n  OCTAVE_API ComplexColumnVector column (char *s) const;\n\n  OCTAVE_API ComplexDiagMatrix inverse (octave_idx_type& info) const;\n  OCTAVE_API ComplexDiagMatrix inverse () const;\n  OCTAVE_API ComplexDiagMatrix pseudo_inverse (double tol = 0.0) const;\n\n  OCTAVE_API bool all_elements_are_real () const;\n\n  // diagonal matrix by diagonal matrix -> diagonal matrix operations\n\n  OCTAVE_API ComplexDiagMatrix& operator += (const DiagMatrix& a);\n  OCTAVE_API ComplexDiagMatrix& operator -= (const DiagMatrix& a);\n\n  // other operations\n\n  ComplexColumnVector extract_diag (octave_idx_type k = 0) const\n  { return MDiagArray2<Complex>::extract_diag (k); }\n\n  OCTAVE_API ComplexDET determinant () const;\n  OCTAVE_API double rcond () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const ComplexDiagMatrix& a);\n\n};\n\nOCTAVE_API ComplexDiagMatrix conj (const ComplexDiagMatrix& a);\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\nOCTAVE_API ComplexDiagMatrix\noperator * (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b);\n\nOCTAVE_API ComplexDiagMatrix\noperator * (const ComplexDiagMatrix& a, const DiagMatrix& b);\n\nOCTAVE_API ComplexDiagMatrix\noperator * (const DiagMatrix& a, const ComplexDiagMatrix& b);\n\nMDIAGARRAY2_FORWARD_DEFS (MDiagArray2, ComplexDiagMatrix, Complex)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/CMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <cmath>\n#include <complex>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"CDiagMatrix.h\"\n#include \"CMatrix.h\"\n#include \"CNDArray.h\"\n#include \"CRowVector.h\"\n#include \"DET.h\"\n#include \"blas-proto.h\"\n#include \"boolMatrix.h\"\n#include \"chMatrix.h\"\n#include \"chol.h\"\n#include \"dDiagMatrix.h\"\n#include \"dMatrix.h\"\n#include \"dRowVector.h\"\n#include \"lapack-proto.h\"\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"mx-cm-dm.h\"\n#include \"mx-cm-s.h\"\n#include \"mx-dm-cm.h\"\n#include \"mx-inlines.cc\"\n#include \"mx-op-defs.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-norm.h\"\n#include \"schur.h\"\n#include \"svd.h\"\n\nstatic const Complex Complex_NaN_result (octave::numeric_limits<double>::NaN (),\n                                         octave::numeric_limits<double>::NaN ());\n\n// Complex Matrix class\n\nComplexMatrix::ComplexMatrix (const Matrix& a)\n  : ComplexNDArray (a)\n{ }\n\nComplexMatrix::ComplexMatrix (const RowVector& rv)\n  : ComplexNDArray (rv)\n{ }\n\nComplexMatrix::ComplexMatrix (const ColumnVector& cv)\n  : ComplexNDArray (cv)\n{ }\n\nComplexMatrix::ComplexMatrix (const DiagMatrix& a)\n  : ComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nComplexMatrix::ComplexMatrix (const MDiagArray2<double>& a)\n  : ComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nComplexMatrix::ComplexMatrix (const DiagArray2<double>& a)\n  : ComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nComplexMatrix::ComplexMatrix (const ComplexRowVector& rv)\n  : ComplexNDArray (rv)\n{ }\n\nComplexMatrix::ComplexMatrix (const ComplexColumnVector& cv)\n  : ComplexNDArray (cv)\n{ }\n\nComplexMatrix::ComplexMatrix (const ComplexDiagMatrix& a)\n  : ComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nComplexMatrix::ComplexMatrix (const MDiagArray2<Complex>& a)\n  : ComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nComplexMatrix::ComplexMatrix (const DiagArray2<Complex>& a)\n  : ComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\n// FIXME: could we use a templated mixed-type copy function here?\n\nComplexMatrix::ComplexMatrix (const boolMatrix& a)\n  : ComplexNDArray (a)\n{ }\n\nComplexMatrix::ComplexMatrix (const charMatrix& a)\n  : ComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    for (octave_idx_type j = 0; j < a.cols (); j++)\n      elem (i, j) = static_cast<unsigned char> (a.elem (i, j));\n}\n\nComplexMatrix::ComplexMatrix (const Matrix& re, const Matrix& im)\n  : ComplexNDArray (re.dims ())\n{\n  if (im.rows () != rows () || im.cols () != cols ())\n    (*current_liboctave_error_handler) (\"complex: internal error\");\n\n  octave_idx_type nel = numel ();\n  for (octave_idx_type i = 0; i < nel; i++)\n    xelem (i) = Complex (re(i), im(i));\n}\n\nbool\nComplexMatrix::operator == (const ComplexMatrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return false;\n\n  return mx_inline_equal (numel (), data (), a.data ());\n}\n\nbool\nComplexMatrix::operator != (const ComplexMatrix& a) const\n{\n  return !(*this == a);\n}\n\nbool\nComplexMatrix::ishermitian () const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (issquare () && nr > 0)\n    {\n      for (octave_idx_type i = 0; i < nr; i++)\n        for (octave_idx_type j = i; j < nc; j++)\n          if (elem (i, j) != conj (elem (j, i)))\n            return false;\n\n      return true;\n    }\n\n  return false;\n}\n\n// destructive insert/delete/reorder operations\n\nComplexMatrix&\nComplexMatrix::insert (const Matrix& a, octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_nr >0 && a_nc > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = 0; j < a_nc; j++)\n        for (octave_idx_type i = 0; i < a_nr; i++)\n          xelem (r+i, c+j) = a.elem (i, j);\n    }\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::insert (const RowVector& a, octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r, c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::insert (const ColumnVector& a,\n                       octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c) = a.elem (i);\n    }\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::insert (const DiagMatrix& a,\n                       octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);\n\n  octave_idx_type a_len = a.length ();\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c+i) = a.elem (i, i);\n    }\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::insert (const ComplexMatrix& a,\n                       octave_idx_type r, octave_idx_type c)\n{\n  ComplexNDArray::insert (a, r, c);\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::insert (const ComplexRowVector& a,\n                       octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n  if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (r, c+i) = a.elem (i);\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::insert (const ComplexColumnVector& a,\n                       octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c) = a.elem (i);\n    }\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::insert (const ComplexDiagMatrix& a,\n                       octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);\n\n  octave_idx_type a_len = a.length ();\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c+i) = a.elem (i, i);\n    }\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::fill (double val)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::fill (const Complex& val)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::fill (double val, octave_idx_type r1, octave_idx_type c1,\n                     octave_idx_type r2, octave_idx_type c2)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0\n      || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (r2 >= r1 && c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = c1; j <= c2; j++)\n        for (octave_idx_type i = r1; i <= r2; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::fill (const Complex& val, octave_idx_type r1, octave_idx_type c1,\n                     octave_idx_type r2, octave_idx_type c2)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0\n      || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (r2 >= r1 && c2 >=c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = c1; j <= c2; j++)\n        for (octave_idx_type i = r1; i <= r2; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nComplexMatrix\nComplexMatrix::append (const Matrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  ComplexMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::append (const RowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != 1)\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  ComplexMatrix retval (nr, nc + a.numel ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::append (const ColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.numel ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  ComplexMatrix retval (nr, nc + 1);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::append (const DiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  ComplexMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::append (const ComplexMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  ComplexMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::append (const ComplexRowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != 1)\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  ComplexMatrix retval (nr, nc + a.numel ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::append (const ComplexColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.numel ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  ComplexMatrix retval (nr, nc + 1);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::append (const ComplexDiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  ComplexMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::stack (const Matrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  ComplexMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::stack (const RowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.numel ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  ComplexMatrix retval (nr + 1, nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::stack (const ColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != 1)\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  ComplexMatrix retval (nr + a.numel (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::stack (const DiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  ComplexMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::stack (const ComplexMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  ComplexMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::stack (const ComplexRowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.numel ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  ComplexMatrix retval (nr + 1, nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::stack (const ComplexColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != 1)\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  ComplexMatrix retval (nr + a.numel (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::stack (const ComplexDiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  ComplexMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nComplexMatrix\nconj (const ComplexMatrix& a)\n{\n  return do_mx_unary_map<Complex, Complex, std::conj<double>> (a);\n}\n\n// resize is the destructive equivalent for this one\n\nComplexMatrix\nComplexMatrix::extract (octave_idx_type r1, octave_idx_type c1,\n                        octave_idx_type r2, octave_idx_type c2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  return index (octave::idx_vector (r1, r2+1), octave::idx_vector (c1, c2+1));\n}\n\nComplexMatrix\nComplexMatrix::extract_n (octave_idx_type r1, octave_idx_type c1,\n                          octave_idx_type nr, octave_idx_type nc) const\n{\n  return index (octave::idx_vector (r1, r1 + nr), octave::idx_vector (c1, c1 + nc));\n}\n\n// extract row or column i.\n\nComplexRowVector\nComplexMatrix::row (octave_idx_type i) const\n{\n  return index (octave::idx_vector (i), octave::idx_vector::colon);\n}\n\nComplexColumnVector\nComplexMatrix::column (octave_idx_type i) const\n{\n  return index (octave::idx_vector::colon, octave::idx_vector (i));\n}\n\n// Local function to calculate the 1-norm.\nstatic\ndouble\nnorm1 (const ComplexMatrix& a)\n{\n  double anorm = 0.0;\n  RowVector colsum = a.abs ().sum ().row (0);\n\n  for (octave_idx_type i = 0; i < colsum.numel (); i++)\n    {\n      double sum = colsum.xelem (i);\n      if (octave::math::isinf (sum) || octave::math::isnan (sum))\n        {\n          anorm = sum;  // Pass Inf or NaN to output\n          break;\n        }\n      else\n        anorm = std::max (anorm, sum);\n    }\n\n  return anorm;\n}\n\n// Local function to check if matrix is singular based on rcond.\nstatic inline\nbool\nis_singular (const double rcond)\n{\n  return (std::abs (rcond) <= std::numeric_limits<double>::epsilon ());\n}\n\nComplexMatrix\nComplexMatrix::inverse () const\n{\n  octave_idx_type info;\n  double rcon;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, false, false);\n}\n\nComplexMatrix\nComplexMatrix::inverse (octave_idx_type& info) const\n{\n  double rcon;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, false, false);\n}\n\nComplexMatrix\nComplexMatrix::inverse (octave_idx_type& info, double& rcon, bool force,\n                        bool calc_cond) const\n{\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, force, calc_cond);\n}\n\nComplexMatrix\nComplexMatrix::inverse (MatrixType& mattype) const\n{\n  octave_idx_type info;\n  double rcon;\n  return inverse (mattype, info, rcon, false, false);\n}\n\nComplexMatrix\nComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const\n{\n  double rcon;\n  return inverse (mattype, info, rcon, false, false);\n}\n\nComplexMatrix\nComplexMatrix::tinverse (MatrixType& mattype, octave_idx_type& info,\n                         double& rcon, bool force, bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc || nr == 0 || nc == 0)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  int typ = mattype.type ();\n  char uplo = (typ == MatrixType::Lower ? 'L' : 'U');\n  char udiag = 'N';\n  retval = *this;\n  Complex *tmp_data = retval.rwdata ();\n\n  F77_INT tmp_info = 0;\n\n  F77_XFCN (ztrtri, ZTRTRI, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                             F77_CONST_CHAR_ARG2 (&udiag, 1),\n                             nr, F77_DBLE_CMPLX_ARG (tmp_data), nr, tmp_info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  info = tmp_info;\n\n  // Throw away extra info LAPACK gives so as to not change output.\n  rcon = 0.0;\n  if (info != 0)\n    info = -1;\n  else if (calc_cond)\n    {\n      F77_INT ztrcon_info = 0;\n      char job = '1';\n\n      OCTAVE_LOCAL_BUFFER (Complex, cwork, 2*nr);\n      OCTAVE_LOCAL_BUFFER (double, rwork, nr);\n\n      F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                 F77_CONST_CHAR_ARG2 (&udiag, 1),\n                                 nr, F77_DBLE_CMPLX_ARG (tmp_data), nr, rcon,\n                                 F77_DBLE_CMPLX_ARG (cwork), rwork, ztrcon_info\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (ztrcon_info != 0)\n        info = -1;\n    }\n\n  if (info == -1 && ! force)\n    retval = *this; // Restore matrix contents.\n\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::finverse (MatrixType& mattype, octave_idx_type& info,\n                         double& rcon, bool force, bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  Array<F77_INT> ipvt (dim_vector (nr, 1));\n  F77_INT *pipvt = ipvt.rwdata ();\n\n  retval = *this;\n  Complex *tmp_data = retval.rwdata ();\n\n  Array<Complex> z (dim_vector (1, 1));\n  F77_INT lwork = -1;\n\n  // Query the optimum work array size.\n\n  F77_INT tmp_info = 0;\n\n  F77_XFCN (zgetri, ZGETRI, (nc, F77_DBLE_CMPLX_ARG (tmp_data), nr, pipvt,\n                             F77_DBLE_CMPLX_ARG (z.rwdata ()), lwork,\n                             tmp_info));\n\n  lwork = static_cast<F77_INT> (std::real (z(0)));\n  lwork = std::max (lwork, 2 * nc);\n  z.resize (dim_vector (lwork, 1));\n  Complex *pz = z.rwdata ();\n\n  info = 0;\n  tmp_info = 0;\n\n  // Calculate norm of the matrix (always, see bug #45577) for later use.\n  double anorm = norm1 (retval);\n\n  // Work around bug #45577, LAPACK crashes Octave if norm is NaN\n  // and bug #46330, segfault with matrices containing Inf & NaN\n  if (octave::math::isnan (anorm) || octave::math::isinf (anorm))\n    info = -1;\n  else\n    {\n      F77_XFCN (zgetrf, ZGETRF, (nc, nc, F77_DBLE_CMPLX_ARG (tmp_data), nr,\n                                 pipvt, tmp_info));\n\n      info = tmp_info;\n    }\n\n  // Throw away extra info LAPACK gives so as to not change output.\n  rcon = 0.0;\n  if (info != 0)\n    info = -1;\n  else if (calc_cond)\n    {\n      if (octave::math::isnan (anorm))\n        rcon = octave::numeric_limits<double>::NaN ();\n      else\n        {\n          F77_INT zgecon_info = 0;\n\n          // Now calculate the condition number for non-singular matrix.\n          char job = '1';\n          Array<double> rz (dim_vector (2 * nc, 1));\n          double *prz = rz.rwdata ();\n          F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     nc, F77_DBLE_CMPLX_ARG (tmp_data), nr,\n                                     anorm, rcon, F77_DBLE_CMPLX_ARG (pz), prz,\n                                     zgecon_info F77_CHAR_ARG_LEN (1)));\n\n          if (zgecon_info != 0)\n            info = -1;\n        }\n    }\n\n  if ((info == -1 && ! force)\n      || octave::math::isnan (anorm) || octave::math::isinf (anorm))\n    retval = *this;  // Restore contents.\n  else\n    {\n      F77_INT zgetri_info = 0;\n\n      F77_XFCN (zgetri, ZGETRI, (nc, F77_DBLE_CMPLX_ARG (tmp_data), nr, pipvt,\n                                 F77_DBLE_CMPLX_ARG (pz), lwork, zgetri_info));\n\n      if (zgetri_info != 0)\n        info = -1;\n    }\n\n  if (info != 0)\n    mattype.mark_as_rectangular ();\n\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info,\n                        double& rcon, bool force, bool calc_cond) const\n{\n  int typ = mattype.type (false);\n  ComplexMatrix ret;\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal)  // a scalar is classified as Diagonal.\n    {\n      Complex scalar = this->elem (0);\n      double real = std::real (scalar);\n      double imag = std::imag (scalar);\n\n      if (real == 0 && imag == 0)\n        ret = ComplexMatrix (1, 1,\n                             Complex (octave::numeric_limits<double>::Inf (), 0.0));\n      else\n        ret = Complex (1, 0) / (*this);\n\n      if (calc_cond)\n        {\n          if (octave::math::isfinite (real) && octave::math::isfinite (imag)\n              && (real != 0 || imag != 0))\n            rcon = 1.0;\n          else if (octave::math::isinf (real) || octave::math::isinf (imag)\n                   || (real == 0 && imag == 0))\n            rcon = 0.0;\n          else\n            rcon = octave::numeric_limits<double>::NaN ();\n        }\n    }\n  else if (typ == MatrixType::Upper || typ == MatrixType::Lower)\n    ret = tinverse (mattype, info, rcon, force, calc_cond);\n  else\n    {\n      if (mattype.ishermitian ())\n        {\n          octave::math::chol<ComplexMatrix> chol (*this, info, true, calc_cond);\n          if (info == 0)\n            {\n              if (calc_cond)\n                rcon = chol.rcond ();\n              else\n                rcon = 1.0;\n              ret = chol.inverse ();\n            }\n          else\n            mattype.mark_as_unsymmetric ();\n        }\n\n      if (! mattype.ishermitian ())\n        ret = finverse (mattype, info, rcon, force, calc_cond);\n\n      if ((calc_cond || mattype.ishermitian ()) && rcon == 0.0)\n        {\n          ret = ComplexMatrix (rows (), columns (),\n                               Complex (octave::numeric_limits<double>::Inf (), 0.0));\n        }\n    }\n\n  return ret;\n}\n\nComplexMatrix\nComplexMatrix::pseudo_inverse (double tol) const\n{\n  ComplexMatrix retval;\n\n  octave::math::svd<ComplexMatrix> result (*this,\n      octave::math::svd<ComplexMatrix>::Type::economy);\n\n  DiagMatrix S = result.singular_values ();\n  ComplexMatrix U = result.left_singular_matrix ();\n  ComplexMatrix V = result.right_singular_matrix ();\n\n  ColumnVector sigma = S.extract_diag ();\n\n  octave_idx_type r = sigma.numel () - 1;\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (tol <= 0.0)\n    {\n      tol = std::max (nr, nc) * sigma.elem (0)\n            * std::numeric_limits<double>::epsilon ();\n\n      if (tol == 0)\n        tol = std::numeric_limits<double>::min ();\n    }\n\n  while (r >= 0 && sigma.elem (r) < tol)\n    r--;\n\n  if (r < 0)\n    retval = ComplexMatrix (nc, nr, 0.0);\n  else\n    {\n      ComplexMatrix Ur = U.extract (0, 0, nr-1, r);\n      DiagMatrix D = DiagMatrix (sigma.extract (0, r)).inverse ();\n      ComplexMatrix Vr = V.extract (0, 0, nc-1, r);\n      retval = Vr * D * Ur.hermitian ();\n    }\n\n  return retval;\n}\n\n#if defined (HAVE_FFTW)\n\nComplexMatrix\nComplexMatrix::fourier () const\n{\n  std::size_t nr = rows ();\n  std::size_t nc = cols ();\n\n  ComplexMatrix retval (nr, nc);\n\n  std::size_t npts, nsamples;\n\n  if (nr == 1 || nc == 1)\n    {\n      npts = std::max (nr, nc);\n      nsamples = 1;\n    }\n  else\n    {\n      npts = nr;\n      nsamples = nc;\n    }\n\n  const Complex *in (data ());\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::fft (in, out, npts, nsamples);\n\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::ifourier () const\n{\n  std::size_t nr = rows ();\n  std::size_t nc = cols ();\n\n  ComplexMatrix retval (nr, nc);\n\n  std::size_t npts, nsamples;\n\n  if (nr == 1 || nc == 1)\n    {\n      npts = std::max (nr, nc);\n      nsamples = 1;\n    }\n  else\n    {\n      npts = nr;\n      nsamples = nc;\n    }\n\n  const Complex *in (data ());\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::ifft (in, out, npts, nsamples);\n\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::fourier2d () const\n{\n  dim_vector dv (rows (), cols ());\n\n  ComplexMatrix retval (rows (), cols ());\n  const Complex *in (data ());\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::fftNd (in, out, 2, dv);\n\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::ifourier2d () const\n{\n  dim_vector dv (rows (), cols ());\n\n  ComplexMatrix retval (rows (), cols ());\n  const Complex *in (data ());\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::ifftNd (in, out, 2, dv);\n\n  return retval;\n}\n\n#else\n\nComplexMatrix\nComplexMatrix::fourier () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexMatrix ();\n}\n\nComplexMatrix\nComplexMatrix::ifourier () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexMatrix ();\n}\n\nComplexMatrix\nComplexMatrix::fourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexMatrix ();\n}\n\nComplexMatrix\nComplexMatrix::ifourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexMatrix ();\n}\n\n#endif\n\nComplexDET\nComplexMatrix::determinant () const\n{\n  octave_idx_type info;\n  double rcon;\n  return determinant (info, rcon, 0);\n}\n\nComplexDET\nComplexMatrix::determinant (octave_idx_type& info) const\n{\n  double rcon;\n  return determinant (info, rcon, 0);\n}\n\nComplexDET\nComplexMatrix::determinant (octave_idx_type& info, double& rcon,\n                            bool calc_cond) const\n{\n  MatrixType mattype (*this);\n  return determinant (mattype, info, rcon, calc_cond);\n}\n\nComplexDET\nComplexMatrix::determinant (MatrixType& mattype,\n                            octave_idx_type& info, double& rcon,\n                            bool calc_cond) const\n{\n  ComplexDET retval (1.0);\n\n  info = 0;\n  rcon = 0.0;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"matrix must be square\");\n\n  int typ = mattype.type ();\n\n  // Even though the matrix is marked as singular (Rectangular), we may\n  // still get a useful number from the LU factorization, because it always\n  // completes.\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n  else if (typ == MatrixType::Rectangular)\n    typ = MatrixType::Full;\n\n  if (typ == MatrixType::Lower || typ == MatrixType::Upper)\n    {\n      for (F77_INT i = 0; i < nc; i++)\n        retval *= elem (i, i);\n    }\n  else if (typ == MatrixType::Hermitian)\n    {\n      ComplexMatrix atmp = *this;\n      Complex *tmp_data = atmp.rwdata ();\n\n      double anorm;\n      if (calc_cond)\n        anorm = norm1 (*this);\n\n      F77_INT tmp_info = 0;\n\n      char job = 'L';\n      F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                 F77_DBLE_CMPLX_ARG (tmp_data), nr, tmp_info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      info = tmp_info;\n\n      if (info != 0)\n        {\n          rcon = 0.0;\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n        }\n      else\n        {\n          if (calc_cond)\n            {\n              Array<Complex> z (dim_vector (2 * nc, 1));\n              Complex *pz = z.rwdata ();\n              Array<double> rz (dim_vector (nc, 1));\n              double *prz = rz.rwdata ();\n\n              F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                         nr, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,\n                                         rcon, F77_DBLE_CMPLX_ARG (pz), prz, tmp_info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n\n              if (info != 0)\n                rcon = 0.0;\n            }\n\n          for (F77_INT i = 0; i < nc; i++)\n            retval *= atmp(i, i);\n\n          retval = retval.square ();\n        }\n    }\n  else if (typ != MatrixType::Full)\n    (*current_liboctave_error_handler) (\"det: invalid dense matrix type\");\n\n  if (typ == MatrixType::Full)\n    {\n      Array<F77_INT> ipvt (dim_vector (nr, 1));\n      F77_INT *pipvt = ipvt.rwdata ();\n\n      ComplexMatrix atmp = *this;\n      Complex *tmp_data = atmp.rwdata ();\n\n      info = 0;\n\n      // Calculate norm of the matrix (always, see bug #45577) for later use.\n      double anorm = norm1 (*this);\n\n      F77_INT tmp_info = 0;\n\n      // Work around bug #45577, LAPACK crashes Octave if norm is NaN\n      if (octave::math::isnan (anorm))\n        info = -1;\n      else\n        {\n          F77_XFCN (zgetrf, ZGETRF, (nr, nr, F77_DBLE_CMPLX_ARG (tmp_data), nr, pipvt,\n                                     tmp_info));\n\n          info = tmp_info;\n        }\n\n      // Throw away extra info LAPACK gives so as to not change output.\n      rcon = 0.0;\n      if (info != 0)\n        {\n          info = -1;\n          retval = ComplexDET ();\n        }\n      else\n        {\n          if (calc_cond)\n            {\n              // Now calc the condition number for non-singular matrix.\n              char job = '1';\n              Array<Complex> z (dim_vector (2 * nc, 1));\n              Complex *pz = z.rwdata ();\n              Array<double> rz (dim_vector (2 * nc, 1));\n              double *prz = rz.rwdata ();\n\n              F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                         nc, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,\n                                         rcon, F77_DBLE_CMPLX_ARG (pz), prz, tmp_info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n            }\n\n          if (info != 0)\n            {\n              info = -1;\n              retval = ComplexDET ();\n            }\n          else\n            {\n              for (F77_INT i = 0; i < nc; i++)\n                {\n                  Complex c = atmp(i, i);\n                  retval *= (ipvt(i) != (i+1)) ? -c : c;\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\ndouble\nComplexMatrix::rcond () const\n{\n  MatrixType mattype (*this);\n  return rcond (mattype);\n}\n\ndouble\nComplexMatrix::rcond (MatrixType& mattype) const\n{\n  double rcon = octave::numeric_limits<double>::NaN ();\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"matrix must be square\");\n\n  if (nr == 0 || nc == 0)\n    rcon = octave::numeric_limits<double>::Inf ();\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ == MatrixType::Unknown)\n        typ = mattype.type (*this);\n\n      // Only calculate the condition number for LU/Cholesky\n      if (typ == MatrixType::Upper)\n        {\n          const Complex *tmp_data = data ();\n          F77_INT info = 0;\n          char norm = '1';\n          char uplo = 'U';\n          char dia = 'N';\n\n          Array<Complex> z (dim_vector (2 * nc, 1));\n          Complex *pz = z.rwdata ();\n          Array<double> rz (dim_vector (nc, 1));\n          double *prz = rz.rwdata ();\n\n          F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, F77_CONST_DBLE_CMPLX_ARG (tmp_data), nr, rcon,\n                                     F77_DBLE_CMPLX_ARG (pz), prz, info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (info != 0)\n            rcon = 0;\n        }\n      else if (typ == MatrixType::Permuted_Upper)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n      else if (typ == MatrixType::Lower)\n        {\n          const Complex *tmp_data = data ();\n          F77_INT info = 0;\n          char norm = '1';\n          char uplo = 'L';\n          char dia = 'N';\n\n          Array<Complex> z (dim_vector (2 * nc, 1));\n          Complex *pz = z.rwdata ();\n          Array<double> rz (dim_vector (nc, 1));\n          double *prz = rz.rwdata ();\n\n          F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, F77_CONST_DBLE_CMPLX_ARG (tmp_data), nr, rcon,\n                                     F77_DBLE_CMPLX_ARG (pz), prz, info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (info != 0)\n            rcon = 0.0;\n        }\n      else if (typ == MatrixType::Permuted_Lower)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n      else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n        {\n          double anorm = -1.0;\n\n          if (typ == MatrixType::Hermitian)\n            {\n              F77_INT info = 0;\n              char job = 'L';\n\n              ComplexMatrix atmp = *this;\n              Complex *tmp_data = atmp.rwdata ();\n\n              anorm = norm1 (atmp);\n\n              F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                         F77_DBLE_CMPLX_ARG (tmp_data), nr, info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              if (info != 0)\n                {\n                  rcon = 0.0;\n\n                  mattype.mark_as_unsymmetric ();\n                  typ = MatrixType::Full;\n                }\n              else\n                {\n                  Array<Complex> z (dim_vector (2 * nc, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> rz (dim_vector (nc, 1));\n                  double *prz = rz.rwdata ();\n\n                  F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,\n                                             rcon, F77_DBLE_CMPLX_ARG (pz), prz, info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  if (info != 0)\n                    rcon = 0.0;\n                }\n            }\n\n          if (typ == MatrixType::Full)\n            {\n              F77_INT info = 0;\n\n              ComplexMatrix atmp = *this;\n              Complex *tmp_data = atmp.rwdata ();\n\n              Array<F77_INT> ipvt (dim_vector (nr, 1));\n              F77_INT *pipvt = ipvt.rwdata ();\n\n              if (anorm < 0.0)\n                anorm = norm1 (atmp);\n\n              Array<Complex> z (dim_vector (2 * nc, 1));\n              Complex *pz = z.rwdata ();\n              Array<double> rz (dim_vector (2 * nc, 1));\n              double *prz = rz.rwdata ();\n\n              // Work around bug #45577, LAPACK crashes Octave if norm is NaN\n              if (octave::math::isnan (anorm))\n                info = -1;\n              else\n                F77_XFCN (zgetrf, ZGETRF, (nr, nr,\n                                           F77_DBLE_CMPLX_ARG (tmp_data),\n                                           nr, pipvt, info));\n\n              if (info != 0)\n                {\n                  rcon = 0.0;\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                {\n                  char job = '1';\n                  F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nc, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,\n                                             rcon, F77_DBLE_CMPLX_ARG (pz), prz, info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  if (info != 0)\n                    rcon = 0.0;\n                }\n            }\n        }\n      else\n        rcon = 0.0;\n    }\n\n  return rcon;\n}\n\nComplexMatrix\nComplexMatrix::utsolve (MatrixType& mattype, const ComplexMatrix& b,\n                        octave_idx_type& info, double& rcon,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond, blas_trans_type transt) const\n{\n  ComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    retval = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0));\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      rcon = 1.0;\n      info = 0;\n\n      if (typ == MatrixType::Permuted_Upper)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n\n      const Complex *tmp_data = data ();\n\n      retval = b;\n      Complex *result = retval.rwdata ();\n\n      char uplo = 'U';\n      char trans = get_blas_char (transt);\n      char dia = 'N';\n\n      F77_INT tmp_info = 0;\n\n      F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                 F77_CONST_CHAR_ARG2 (&trans, 1),\n                                 F77_CONST_CHAR_ARG2 (&dia, 1),\n                                 nr, b_nc, F77_CONST_DBLE_CMPLX_ARG (tmp_data), nr,\n                                 F77_DBLE_CMPLX_ARG (result), nr, tmp_info\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)));\n\n      info = tmp_info;\n\n      if (calc_cond)\n        {\n          char norm = '1';\n          uplo = 'U';\n          dia = 'N';\n\n          Array<Complex> z (dim_vector (2 * nc, 1));\n          Complex *pz = z.rwdata ();\n          Array<double> rz (dim_vector (nc, 1));\n          double *prz = rz.rwdata ();\n\n          F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, F77_CONST_DBLE_CMPLX_ARG (tmp_data), nr, rcon,\n                                     F77_DBLE_CMPLX_ARG (pz), prz, tmp_info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          info = tmp_info;\n\n          if (info != 0)\n            info = -2;\n\n          if (is_singular (rcon) || octave::math::isnan (rcon))\n            {\n              info = -2;\n\n              if (sing_handler)\n                sing_handler (rcon);\n              else\n                octave::warn_singular_matrix (rcon);\n            }\n        }\n    }\n\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::ltsolve (MatrixType& mattype, const ComplexMatrix& b,\n                        octave_idx_type& info, double& rcon,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond, blas_trans_type transt) const\n{\n  ComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    retval = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0));\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      rcon = 1.0;\n      info = 0;\n\n      if (typ == MatrixType::Permuted_Lower)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n\n      const Complex *tmp_data = data ();\n\n      retval = b;\n      Complex *result = retval.rwdata ();\n\n      char uplo = 'L';\n      char trans = get_blas_char (transt);\n      char dia = 'N';\n\n      F77_INT tmp_info = 0;\n\n      F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                 F77_CONST_CHAR_ARG2 (&trans, 1),\n                                 F77_CONST_CHAR_ARG2 (&dia, 1),\n                                 nr, b_nc, F77_CONST_DBLE_CMPLX_ARG (tmp_data), nr,\n                                 F77_DBLE_CMPLX_ARG (result), nr, tmp_info\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)));\n\n      info = tmp_info;\n\n      if (calc_cond)\n        {\n          char norm = '1';\n          uplo = 'L';\n          dia = 'N';\n\n          Array<Complex> z (dim_vector (2 * nc, 1));\n          Complex *pz = z.rwdata ();\n          Array<double> rz (dim_vector (nc, 1));\n          double *prz = rz.rwdata ();\n\n          F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, F77_CONST_DBLE_CMPLX_ARG (tmp_data), nr, rcon,\n                                     F77_DBLE_CMPLX_ARG (pz), prz, tmp_info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          info = tmp_info;\n\n          if (info != 0)\n            info = -2;\n\n          if (is_singular (rcon) || octave::math::isnan (rcon))\n            {\n              info = -2;\n\n              if (sing_handler)\n                sing_handler (rcon);\n              else\n                octave::warn_singular_matrix (rcon);\n            }\n        }\n    }\n\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::fsolve (MatrixType& mattype, const ComplexMatrix& b,\n                       octave_idx_type& info, double& rcon,\n                       solve_singularity_handler sing_handler,\n                       bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != nc || nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b_nc == 0)\n    retval = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0));\n  else\n    {\n      int typ = mattype.type ();\n\n      // Calculate the norm of the matrix for later use when determining rcon.\n      double anorm = -1.0;\n\n      if (typ == MatrixType::Hermitian)\n        {\n          info = 0;\n          char job = 'L';\n\n          ComplexMatrix atmp = *this;\n          Complex *tmp_data = atmp.rwdata ();\n\n          // The norm of the matrix for later use when determining rcon.\n          if (calc_cond)\n            anorm = norm1 (atmp);\n\n          F77_INT tmp_info = 0;\n\n          F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                     F77_DBLE_CMPLX_ARG (tmp_data), nr, tmp_info\n                                     F77_CHAR_ARG_LEN (1)));\n\n          info = tmp_info;\n\n          // Throw away extra info LAPACK gives so as to not change output.\n          rcon = 0.0;\n          if (info != 0)\n            {\n              info = -2;\n\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<Complex> z (dim_vector (2 * nc, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> rz (dim_vector (nc, 1));\n                  double *prz = rz.rwdata ();\n\n                  F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,\n                                             rcon, F77_DBLE_CMPLX_ARG (pz), prz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      info = -2;\n\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n\n              if (info == 0)\n                {\n                  retval = b;\n                  Complex *result = retval.rwdata ();\n\n                  F77_XFCN (zpotrs, ZPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, b_nc, F77_DBLE_CMPLX_ARG (tmp_data), nr,\n                                             F77_DBLE_CMPLX_ARG (result), b_nr, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n                }\n              else\n                {\n                  mattype.mark_as_unsymmetric ();\n                  typ = MatrixType::Full;\n                }\n            }\n        }\n\n      if (typ == MatrixType::Full)\n        {\n          info = 0;\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          ComplexMatrix atmp = *this;\n          Complex *tmp_data = atmp.rwdata ();\n\n          Array<Complex> z (dim_vector (2 * nc, 1));\n          Complex *pz = z.rwdata ();\n          Array<double> rz (dim_vector (2 * nc, 1));\n          double *prz = rz.rwdata ();\n\n          // Calculate the norm of the matrix, for later use.\n          if (calc_cond && anorm < 0.0)\n            anorm = norm1 (atmp);\n\n          F77_INT tmp_info = 0;\n\n          // Work around bug #45577, LAPACK crashes Octave if norm is NaN\n          // and bug #46330, segfault with matrices containing Inf & NaN\n          if (octave::math::isnan (anorm) || octave::math::isinf (anorm))\n            info = -2;\n          else\n            {\n              F77_XFCN (zgetrf, ZGETRF, (nr, nr, F77_DBLE_CMPLX_ARG (tmp_data),\n                                         nr, pipvt, tmp_info));\n\n              info = tmp_info;\n            }\n\n          // Throw away extra info LAPACK gives so as to not change output.\n          rcon = 0.0;\n          if (info != 0)\n            {\n              info = -2;\n\n              if (sing_handler)\n                sing_handler (rcon);\n              else\n                octave::warn_singular_matrix ();\n\n              mattype.mark_as_rectangular ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  // Calculate the condition number for non-singular matrix.\n                  char job = '1';\n                  F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nc, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,\n                                             rcon, F77_DBLE_CMPLX_ARG (pz), prz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n\n              if (info == 0)\n                {\n                  retval = b;\n                  Complex *result = retval.rwdata ();\n\n                  char job = 'N';\n                  F77_XFCN (zgetrs, ZGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, b_nc, F77_DBLE_CMPLX_ARG (tmp_data), nr,\n                                             pipvt, F77_DBLE_CMPLX_ARG (result), b_nr, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n                }\n              else\n                mattype.mark_as_rectangular ();\n            }\n        }\n\n      if (octave::math::isinf (anorm))\n        {\n          retval = ComplexMatrix (b_nr, b_nc, Complex (0, 0));\n          mattype.mark_as_full ();\n        }\n    }\n\n  return retval;\n}\n\nComplexMatrix\nComplexMatrix::solve (MatrixType& mattype, const Matrix& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (MatrixType& mattype, const Matrix& b,\n                      octave_idx_type& info) const\n{\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (MatrixType& mattype, const Matrix& b,\n                      octave_idx_type& info, double& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (MatrixType& mattype, const Matrix& b,\n                      octave_idx_type& info, double& rcon,\n                      solve_singularity_handler sing_handler,\n                      bool singular_fallback, blas_trans_type transt) const\n{\n  ComplexMatrix tmp (b);\n  return solve (mattype, tmp, info, rcon, sing_handler, singular_fallback,\n                transt);\n}\n\nComplexMatrix\nComplexMatrix::solve (MatrixType& mattype, const ComplexMatrix& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n                      octave_idx_type& info) const\n{\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n                      octave_idx_type& info, double& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n                      octave_idx_type& info, double& rcon,\n                      solve_singularity_handler sing_handler,\n                      bool singular_fallback, blas_trans_type transt) const\n{\n  ComplexMatrix retval;\n  int typ = mattype.type ();\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  // Only calculate the condition number for LU/Cholesky\n  if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, info, rcon, sing_handler, true, transt);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, info, rcon, sing_handler, true, transt);\n  else if (transt == blas_trans)\n    return transpose ().solve (mattype, b, info, rcon, sing_handler,\n                               singular_fallback);\n  else if (transt == blas_conj_trans)\n    retval = hermitian ().solve (mattype, b, info, rcon, sing_handler,\n                                 singular_fallback);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, info, rcon, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  // Rectangular or one of the above solvers flags a singular matrix\n  if (singular_fallback && mattype.type () == MatrixType::Rectangular)\n    {\n      octave_idx_type rank;\n      retval = lssolve (b, info, rank, rcon);\n    }\n\n  return retval;\n}\n\nComplexColumnVector\nComplexMatrix::solve (MatrixType& mattype, const ColumnVector& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (mattype, ComplexColumnVector (b), info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n                      octave_idx_type& info) const\n{\n  double rcon;\n  return solve (mattype, ComplexColumnVector (b), info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n                      octave_idx_type& info, double& rcon) const\n{\n  return solve (mattype, ComplexColumnVector (b), info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n                      octave_idx_type& info, double& rcon,\n                      solve_singularity_handler sing_handler,\n                      blas_trans_type transt) const\n{\n  return solve (mattype, ComplexColumnVector (b), info, rcon, sing_handler,\n                transt);\n}\n\nComplexColumnVector\nComplexMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n                      octave_idx_type& info) const\n{\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n                      octave_idx_type& info, double& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n                      octave_idx_type& info, double& rcon,\n                      solve_singularity_handler sing_handler,\n                      blas_trans_type transt) const\n{\n\n  ComplexMatrix tmp (b);\n  tmp = solve (mattype, tmp, info, rcon, sing_handler, true, transt);\n  return tmp.column (static_cast<octave_idx_type> (0));\n}\n\nComplexMatrix\nComplexMatrix::solve (const Matrix& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (const Matrix& b, octave_idx_type& info) const\n{\n  double rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (const Matrix& b, octave_idx_type& info,\n                      double& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (const Matrix& b, octave_idx_type& info, double& rcon,\n                      solve_singularity_handler sing_handler,\n                      blas_trans_type transt) const\n{\n  ComplexMatrix tmp (b);\n  return solve (tmp, info, rcon, sing_handler, transt);\n}\n\nComplexMatrix\nComplexMatrix::solve (const ComplexMatrix& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info) const\n{\n  double rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info,\n                      double& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nComplexMatrix\nComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info,\n                      double& rcon,\n                      solve_singularity_handler sing_handler,\n                      blas_trans_type transt) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, info, rcon, sing_handler, true, transt);\n}\n\nComplexColumnVector\nComplexMatrix::solve (const ColumnVector& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (ComplexColumnVector (b), info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info) const\n{\n  double rcon;\n  return solve (ComplexColumnVector (b), info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info,\n                      double& rcon) const\n{\n  return solve (ComplexColumnVector (b), info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info,\n                      double& rcon,\n                      solve_singularity_handler sing_handler,\n                      blas_trans_type transt) const\n{\n  return solve (ComplexColumnVector (b), info, rcon, sing_handler, transt);\n}\n\nComplexColumnVector\nComplexMatrix::solve (const ComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const\n{\n  double rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,\n                      double& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nComplexColumnVector\nComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,\n                      double& rcon,\n                      solve_singularity_handler sing_handler,\n                      blas_trans_type transt) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, info, rcon, sing_handler, transt);\n}\n\nComplexMatrix\nComplexMatrix::lssolve (const Matrix& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (ComplexMatrix (b), info, rank, rcon);\n}\n\nComplexMatrix\nComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (ComplexMatrix (b), info, rank, rcon);\n}\n\nComplexMatrix\nComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info,\n                        octave_idx_type& rank) const\n{\n  double rcon;\n  return lssolve (ComplexMatrix (b), info, rank, rcon);\n}\n\nComplexMatrix\nComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info,\n                        octave_idx_type& rank, double& rcon) const\n{\n  return lssolve (ComplexMatrix (b), info, rank, rcon);\n}\n\nComplexMatrix\nComplexMatrix::lssolve (const ComplexMatrix& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nComplexMatrix\nComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nComplexMatrix\nComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info,\n                        octave_idx_type& rank) const\n{\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nComplexMatrix\nComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info,\n                        octave_idx_type& rank, double& rcon) const\n{\n  ComplexMatrix retval;\n\n  F77_INT m = octave::to_f77_int (rows ());\n  F77_INT n = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n  F77_INT nrhs = b_nc;  // alias for code readability\n\n  if (m != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (m == 0 || n == 0 || b_nc == 0)\n    retval = ComplexMatrix (n, b_nc, Complex (0.0, 0.0));\n  else\n    {\n      F77_INT minmn = std::min (m, n);\n      F77_INT maxmn = std::max (m, n);\n      rcon = -1.0;\n\n      if (m != n)\n        {\n          retval = ComplexMatrix (maxmn, nrhs);\n\n          for (F77_INT j = 0; j < nrhs; j++)\n            for (F77_INT i = 0; i < m; i++)\n              retval.elem (i, j) = b.elem (i, j);\n        }\n      else\n        retval = b;\n\n      ComplexMatrix atmp = *this;\n      Complex *tmp_data = atmp.rwdata ();\n\n      Complex *pretval = retval.rwdata ();\n      Array<double> s (dim_vector (minmn, 1));\n      double *ps = s.rwdata ();\n\n      // Ask ZGELSD what the dimension of WORK should be.\n      F77_INT lwork = -1;\n\n      Array<Complex> work (dim_vector (1, 1));\n\n      F77_INT smlsiz;\n      F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 (\"ZGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   0, 0, 0, 0, smlsiz\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      F77_INT mnthr;\n      F77_FUNC (xilaenv, XILAENV) (6, F77_CONST_CHAR_ARG2 (\"ZGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   m, n, nrhs, -1, mnthr\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      // We compute the size of rwork and iwork because ZGELSD in\n      // older versions of LAPACK does not return them on a query\n      // call.\n      double dminmn = static_cast<double> (minmn);\n      double dsmlsizp1 = static_cast<double> (smlsiz+1);\n      double tmp = octave::math::log2 (dminmn / dsmlsizp1);\n\n      F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;\n      if (nlvl < 0)\n        nlvl = 0;\n\n      F77_INT lrwork = minmn*(10 + 2*smlsiz + 8*nlvl)\n                       + 3*smlsiz*nrhs\n                       + std::max ((smlsiz+1)*(smlsiz+1),\n                                   n*(1+nrhs) + 2*nrhs);\n      if (lrwork < 1)\n        lrwork = 1;\n      Array<double> rwork (dim_vector (lrwork, 1));\n      double *prwork = rwork.rwdata ();\n\n      F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;\n      if (liwork < 1)\n        liwork = 1;\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n      F77_INT *piwork = iwork.rwdata ();\n\n      F77_INT tmp_info = 0;\n      F77_INT tmp_rank = 0;\n\n      F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data), m,\n                                 F77_DBLE_CMPLX_ARG (pretval), maxmn,\n                                 ps, rcon, tmp_rank, F77_DBLE_CMPLX_ARG (work.rwdata ()),\n                                 lwork, prwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      // The workspace query is broken in at least LAPACK 3.0.0\n      // through 3.1.1 when n >= mnthr.  The obtuse formula below\n      // should provide sufficient workspace for ZGELSD to operate\n      // efficiently.\n      if (n > m && n >= mnthr)\n        {\n          F77_INT addend = m;\n\n          if (2*m-4 > addend)\n            addend = 2*m-4;\n\n          if (nrhs > addend)\n            addend = nrhs;\n\n          if (n-3*m > addend)\n            addend = n-3*m;\n\n          const F77_INT lworkaround = 4*m + m*m + addend;\n\n          if (std::real (work(0)) < lworkaround)\n            work(0) = lworkaround;\n        }\n      else if (m >= n)\n        {\n          F77_INT lworkaround = 2*m + m*nrhs;\n\n          if (std::real (work(0)) < lworkaround)\n            work(0) = lworkaround;\n        }\n\n      lwork = static_cast<F77_INT> (std::real (work(0)));\n      work.resize (dim_vector (lwork, 1));\n\n      double anorm = norm1 (*this);\n\n      if (octave::math::isinf (anorm))\n        {\n          rcon = 0.0;\n          retval = ComplexMatrix (n, b_nc, 0.0);\n        }\n      else if (octave::math::isnan (anorm))\n        {\n          rcon = octave::numeric_limits<double>::NaN ();\n          retval = ComplexMatrix (n, b_nc,\n                                  octave::numeric_limits<double>::NaN ());\n        }\n      else\n        {\n          F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data),\n                                     m, F77_DBLE_CMPLX_ARG (pretval),\n                                     maxmn, ps, rcon, tmp_rank,\n                                     F77_DBLE_CMPLX_ARG (work.rwdata ()),\n                                     lwork, prwork, piwork, tmp_info));\n\n          info = tmp_info;\n          rank = tmp_rank;\n\n          if (s.elem (0) == 0.0)\n            rcon = 0.0;\n          else\n            rcon = s.elem (minmn - 1) / s.elem (0);\n\n          retval.resize (n, nrhs);\n        }\n    }\n\n  return retval;\n}\n\nComplexColumnVector\nComplexMatrix::lssolve (const ColumnVector& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (ComplexColumnVector (b), info, rank, rcon);\n}\n\nComplexColumnVector\nComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (ComplexColumnVector (b), info, rank, rcon);\n}\n\nComplexColumnVector\nComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info,\n                        octave_idx_type& rank) const\n{\n  double rcon;\n  return lssolve (ComplexColumnVector (b), info, rank, rcon);\n}\n\nComplexColumnVector\nComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info,\n                        octave_idx_type& rank, double& rcon) const\n{\n  return lssolve (ComplexColumnVector (b), info, rank, rcon);\n}\n\nComplexColumnVector\nComplexMatrix::lssolve (const ComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nComplexColumnVector\nComplexMatrix::lssolve (const ComplexColumnVector& b,\n                        octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nComplexColumnVector\nComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info,\n                        octave_idx_type& rank) const\n{\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n\n}\n\nComplexColumnVector\nComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info,\n                        octave_idx_type& rank, double& rcon) const\n{\n  ComplexColumnVector retval;\n\n  F77_INT nrhs = 1;\n\n  F77_INT m = octave::to_f77_int (rows ());\n  F77_INT n = octave::to_f77_int (cols ());\n\n  F77_INT b_nel = octave::to_f77_int (b.numel ());\n\n  if (m != b_nel)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (m == 0 || n == 0)\n    retval = ComplexColumnVector (n, Complex (0.0, 0.0));\n  else\n    {\n      F77_INT minmn = std::min (m, n);\n      F77_INT maxmn = std::max (m, n);\n      rcon = -1.0;\n\n      if (m != n)\n        {\n          retval = ComplexColumnVector (maxmn);\n\n          for (F77_INT i = 0; i < m; i++)\n            retval.elem (i) = b.elem (i);\n        }\n      else\n        retval = b;\n\n      ComplexMatrix atmp = *this;\n      Complex *tmp_data = atmp.rwdata ();\n\n      Complex *pretval = retval.rwdata ();\n      Array<double> s (dim_vector (minmn, 1));\n      double *ps = s.rwdata ();\n\n      // Ask ZGELSD what the dimension of WORK should be.\n      F77_INT lwork = -1;\n\n      Array<Complex> work (dim_vector (1, 1));\n\n      F77_INT smlsiz;\n      F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 (\"ZGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   0, 0, 0, 0, smlsiz\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      // We compute the size of rwork and iwork because ZGELSD in\n      // older versions of LAPACK does not return them on a query\n      // call.\n      double dminmn = static_cast<double> (minmn);\n      double dsmlsizp1 = static_cast<double> (smlsiz+1);\n      double tmp = octave::math::log2 (dminmn / dsmlsizp1);\n\n      F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;\n      if (nlvl < 0)\n        nlvl = 0;\n\n      F77_INT lrwork = minmn*(10 + 2*smlsiz + 8*nlvl)\n                       + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1);\n      if (lrwork < 1)\n        lrwork = 1;\n      Array<double> rwork (dim_vector (lrwork, 1));\n      double *prwork = rwork.rwdata ();\n\n      F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;\n      if (liwork < 1)\n        liwork = 1;\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n      F77_INT *piwork = iwork.rwdata ();\n\n      F77_INT tmp_info = 0;\n      F77_INT tmp_rank = 0;\n\n      F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data), m,\n                                 F77_DBLE_CMPLX_ARG (pretval), maxmn,\n                                 ps, rcon, tmp_rank, F77_DBLE_CMPLX_ARG (work.rwdata ()),\n                                 lwork, prwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      lwork = static_cast<F77_INT> (std::real (work(0)));\n      work.resize (dim_vector (lwork, 1));\n      rwork.resize (dim_vector (static_cast<F77_INT> (rwork(0)), 1));\n      iwork.resize (dim_vector (iwork(0), 1));\n\n      F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data), m,\n                                 F77_DBLE_CMPLX_ARG (pretval),\n                                 maxmn, ps, rcon, tmp_rank,\n                                 F77_DBLE_CMPLX_ARG (work.rwdata ()), lwork,\n                                 prwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      if (rank < minmn)\n        {\n          if (s.elem (0) == 0.0)\n            rcon = 0.0;\n          else\n            rcon = s.elem (minmn - 1) / s.elem (0);\n\n          retval.resize (n);\n        }\n    }\n\n  return retval;\n}\n\n// column vector by row vector -> matrix operations\n\nComplexMatrix\noperator * (const ColumnVector& v, const ComplexRowVector& a)\n{\n  ComplexColumnVector tmp (v);\n  return tmp * a;\n}\n\nComplexMatrix\noperator * (const ComplexColumnVector& a, const RowVector& b)\n{\n  ComplexRowVector tmp (b);\n  return a * tmp;\n}\n\nComplexMatrix\noperator * (const ComplexColumnVector& v, const ComplexRowVector& a)\n{\n  ComplexMatrix retval;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  if (len != 0)\n    {\n      F77_INT a_len = octave::to_f77_int (a.numel ());\n\n      retval = ComplexMatrix (len, a_len);\n      Complex *c = retval.rwdata ();\n\n      F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                               F77_CONST_CHAR_ARG2 (\"N\", 1),\n                               len, a_len, 1, 1.0, F77_CONST_DBLE_CMPLX_ARG (v.data ()), len,\n                               F77_CONST_DBLE_CMPLX_ARG (a.data ()), 1, 0.0, F77_DBLE_CMPLX_ARG (c), len\n                               F77_CHAR_ARG_LEN (1)\n                               F77_CHAR_ARG_LEN (1)));\n    }\n\n  return retval;\n}\n\n// matrix by diagonal matrix -> matrix operations\n\nComplexMatrix&\nComplexMatrix::operator += (const DiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator +=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) += a.elem (i, i);\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::operator -= (const DiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator -=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) -= a.elem (i, i);\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::operator += (const ComplexDiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator +=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) += a.elem (i, i);\n\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::operator -= (const ComplexDiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator -=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) -= a.elem (i, i);\n\n  return *this;\n}\n\n// matrix by matrix -> matrix operations\n\nComplexMatrix&\nComplexMatrix::operator += (const Matrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator +=\", nr, nc, a_nr, a_nc);\n\n  if (nr == 0 || nc == 0)\n    return *this;\n\n  Complex *d = rwdata (); // Ensures only one reference to my privates!\n\n  mx_inline_add2 (numel (), d, a.data ());\n  return *this;\n}\n\nComplexMatrix&\nComplexMatrix::operator -= (const Matrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator -=\", nr, nc, a_nr, a_nc);\n\n  if (nr == 0 || nc == 0)\n    return *this;\n\n  Complex *d = rwdata (); // Ensures only one reference to my privates!\n\n  mx_inline_sub2 (numel (), d, a.data ());\n  return *this;\n}\n\n// other operations\n\nboolMatrix\nComplexMatrix::all (int dim) const\n{\n  return ComplexNDArray::all (dim);\n}\n\nboolMatrix\nComplexMatrix::any (int dim) const\n{\n  return ComplexNDArray::any (dim);\n}\n\nComplexMatrix\nComplexMatrix::flip (int dim) const\n{\n  return ComplexNDArray::flip (dim);\n}\n\nComplexMatrix\nComplexMatrix::cumprod (int dim, bool nanflag) const\n{\n  return ComplexNDArray::cumprod (dim, nanflag);\n}\n\nComplexMatrix\nComplexMatrix::cumsum (int dim, bool nanflag) const\n{\n  return ComplexNDArray::cumsum (dim, nanflag);\n}\n\nComplexMatrix\nComplexMatrix::prod (int dim, bool nanflag) const\n{\n  return ComplexNDArray::prod (dim, nanflag);\n}\n\nComplexMatrix\nComplexMatrix::sum (int dim, bool nanflag) const\n{\n  return ComplexNDArray::sum (dim, nanflag);\n}\n\nComplexMatrix\nComplexMatrix::sumsq (int dim, bool nanflag) const\n{\n  return ComplexNDArray::sumsq (dim, nanflag);\n}\n\nMatrix\nComplexMatrix::abs () const\n{\n  return ComplexNDArray::abs ();\n}\n\nComplexMatrix\nComplexMatrix::diag (octave_idx_type k) const\n{\n  return ComplexNDArray::diag (k);\n}\n\nComplexDiagMatrix\nComplexMatrix::diag (octave_idx_type m, octave_idx_type n) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr != 1 && nc != 1)\n    (*current_liboctave_error_handler) (\"diag: expecting vector argument\");\n\n  return ComplexDiagMatrix (*this, m, n);\n}\n\nbool\nComplexMatrix::row_is_real_only (octave_idx_type i) const\n{\n  bool retval = true;\n\n  octave_idx_type nc = columns ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      if (std::imag (elem (i, j)) != 0.0)\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nbool\nComplexMatrix::column_is_real_only (octave_idx_type j) const\n{\n  bool retval = true;\n\n  octave_idx_type nr = rows ();\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    {\n      if (std::imag (elem (i, j)) != 0.0)\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nComplexColumnVector\nComplexMatrix::row_min () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return row_min (dummy_idx);\n}\n\nComplexColumnVector\nComplexMatrix::row_min (Array<octave_idx_type>& idx_arg) const\n{\n  ComplexColumnVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nr);\n      idx_arg.resize (dim_vector (nr, 1));\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          bool real_only = row_is_real_only (i);\n\n          octave_idx_type idx_j;\n\n          Complex tmp_min;\n\n          double abs_min = octave::numeric_limits<double>::NaN ();\n\n          for (idx_j = 0; idx_j < nc; idx_j++)\n            {\n              tmp_min = elem (i, idx_j);\n\n              if (! octave::math::isnan (tmp_min))\n                {\n                  abs_min = (real_only ? tmp_min.real ()\n                                       : std::abs (tmp_min));\n                  break;\n                }\n            }\n\n          for (octave_idx_type j = idx_j+1; j < nc; j++)\n            {\n              Complex tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n\n              double abs_tmp = (real_only ? tmp.real () : std::abs (tmp));\n\n              if (abs_tmp < abs_min)\n                {\n                  idx_j = j;\n                  tmp_min = tmp;\n                  abs_min = abs_tmp;\n                }\n            }\n\n          if (octave::math::isnan (tmp_min))\n            {\n              result.elem (i) = Complex_NaN_result;\n              idx_arg.elem (i) = 0;\n            }\n          else\n            {\n              result.elem (i) = tmp_min;\n              idx_arg.elem (i) = idx_j;\n            }\n        }\n    }\n\n  return result;\n}\n\nComplexColumnVector\nComplexMatrix::row_max () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return row_max (dummy_idx);\n}\n\nComplexColumnVector\nComplexMatrix::row_max (Array<octave_idx_type>& idx_arg) const\n{\n  ComplexColumnVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nr);\n      idx_arg.resize (dim_vector (nr, 1));\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          bool real_only = row_is_real_only (i);\n\n          octave_idx_type idx_j;\n\n          Complex tmp_max;\n\n          double abs_max = octave::numeric_limits<double>::NaN ();\n\n          for (idx_j = 0; idx_j < nc; idx_j++)\n            {\n              tmp_max = elem (i, idx_j);\n\n              if (! octave::math::isnan (tmp_max))\n                {\n                  abs_max = (real_only ? tmp_max.real ()\n                                       : std::abs (tmp_max));\n                  break;\n                }\n            }\n\n          for (octave_idx_type j = idx_j+1; j < nc; j++)\n            {\n              Complex tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n\n              double abs_tmp = (real_only ? tmp.real () : std::abs (tmp));\n\n              if (abs_tmp > abs_max)\n                {\n                  idx_j = j;\n                  tmp_max = tmp;\n                  abs_max = abs_tmp;\n                }\n            }\n\n          if (octave::math::isnan (tmp_max))\n            {\n              result.elem (i) = Complex_NaN_result;\n              idx_arg.elem (i) = 0;\n            }\n          else\n            {\n              result.elem (i) = tmp_max;\n              idx_arg.elem (i) = idx_j;\n            }\n        }\n    }\n\n  return result;\n}\n\nComplexRowVector\nComplexMatrix::column_min () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return column_min (dummy_idx);\n}\n\nComplexRowVector\nComplexMatrix::column_min (Array<octave_idx_type>& idx_arg) const\n{\n  ComplexRowVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nc);\n      idx_arg.resize (dim_vector (1, nc));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          bool real_only = column_is_real_only (j);\n\n          octave_idx_type idx_i;\n\n          Complex tmp_min;\n\n          double abs_min = octave::numeric_limits<double>::NaN ();\n\n          for (idx_i = 0; idx_i < nr; idx_i++)\n            {\n              tmp_min = elem (idx_i, j);\n\n              if (! octave::math::isnan (tmp_min))\n                {\n                  abs_min = (real_only ? tmp_min.real ()\n                                       : std::abs (tmp_min));\n                  break;\n                }\n            }\n\n          for (octave_idx_type i = idx_i+1; i < nr; i++)\n            {\n              Complex tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n\n              double abs_tmp = (real_only ? tmp.real () : std::abs (tmp));\n\n              if (abs_tmp < abs_min)\n                {\n                  idx_i = i;\n                  tmp_min = tmp;\n                  abs_min = abs_tmp;\n                }\n            }\n\n          if (octave::math::isnan (tmp_min))\n            {\n              result.elem (j) = Complex_NaN_result;\n              idx_arg.elem (j) = 0;\n            }\n          else\n            {\n              result.elem (j) = tmp_min;\n              idx_arg.elem (j) = idx_i;\n            }\n        }\n    }\n\n  return result;\n}\n\nComplexRowVector\nComplexMatrix::column_max () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return column_max (dummy_idx);\n}\n\nComplexRowVector\nComplexMatrix::column_max (Array<octave_idx_type>& idx_arg) const\n{\n  ComplexRowVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nc);\n      idx_arg.resize (dim_vector (1, nc));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          bool real_only = column_is_real_only (j);\n\n          octave_idx_type idx_i;\n\n          Complex tmp_max;\n\n          double abs_max = octave::numeric_limits<double>::NaN ();\n\n          for (idx_i = 0; idx_i < nr; idx_i++)\n            {\n              tmp_max = elem (idx_i, j);\n\n              if (! octave::math::isnan (tmp_max))\n                {\n                  abs_max = (real_only ? tmp_max.real ()\n                                       : std::abs (tmp_max));\n                  break;\n                }\n            }\n\n          for (octave_idx_type i = idx_i+1; i < nr; i++)\n            {\n              Complex tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n\n              double abs_tmp = (real_only ? tmp.real () : std::abs (tmp));\n\n              if (abs_tmp > abs_max)\n                {\n                  idx_i = i;\n                  tmp_max = tmp;\n                  abs_max = abs_tmp;\n                }\n            }\n\n          if (octave::math::isnan (tmp_max))\n            {\n              result.elem (j) = Complex_NaN_result;\n              idx_arg.elem (j) = 0;\n            }\n          else\n            {\n              result.elem (j) = tmp_max;\n              idx_arg.elem (j) = idx_i;\n            }\n        }\n    }\n\n  return result;\n}\n\n// i/o\n\nstd::ostream&\noperator << (std::ostream& os, const ComplexMatrix& a)\n{\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    {\n      for (octave_idx_type j = 0; j < a.cols (); j++)\n        {\n          os << ' ';\n          octave::write_value<Complex> (os, a.elem (i, j));\n        }\n      os << \"\\n\";\n    }\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, ComplexMatrix& a)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      Complex tmp;\n      for (octave_idx_type i = 0; i < nr; i++)\n        for (octave_idx_type j = 0; j < nc; j++)\n          {\n            tmp = octave::read_value<Complex> (is);\n            if (is)\n              a.elem (i, j) = tmp;\n            else\n              return is;\n          }\n    }\n\n  return is;\n}\n\nComplexMatrix\nGivens (const Complex& x, const Complex& y)\n{\n  double cc;\n  Complex cs, temp_r;\n\n  F77_FUNC (zlartg, ZLARTG) (F77_CONST_DBLE_CMPLX_ARG (&x),\n                             F77_CONST_DBLE_CMPLX_ARG (&y),\n                             cc,\n                             F77_DBLE_CMPLX_ARG (&cs),\n                             F77_DBLE_CMPLX_ARG (&temp_r));\n\n  ComplexMatrix g (2, 2);\n\n  g.elem (0, 0) = cc;\n  g.elem (1, 1) = cc;\n  g.elem (0, 1) = cs;\n  g.elem (1, 0) = -conj (cs);\n\n  return g;\n}\n\nComplexMatrix\nSylvester (const ComplexMatrix& a, const ComplexMatrix& b,\n           const ComplexMatrix& c)\n{\n  ComplexMatrix retval;\n\n  // FIXME: need to check that a, b, and c are all the same size.\n\n  // Compute Schur decompositions\n\n  octave::math::schur<ComplexMatrix> as (a, \"U\");\n  octave::math::schur<ComplexMatrix> bs (b, \"U\");\n\n  // Transform c to new coordinates.\n\n  ComplexMatrix ua = as.unitary_schur_matrix ();\n  ComplexMatrix sch_a = as.schur_matrix ();\n\n  ComplexMatrix ub = bs.unitary_schur_matrix ();\n  ComplexMatrix sch_b = bs.schur_matrix ();\n\n  ComplexMatrix cx = ua.hermitian () * c * ub;\n\n  // Solve the sylvester equation, back-transform, and return the solution.\n\n  F77_INT a_nr = octave::to_f77_int (a.rows ());\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n\n  double scale;\n  F77_INT info;\n\n  Complex *pa = sch_a.rwdata ();\n  Complex *pb = sch_b.rwdata ();\n  Complex *px = cx.rwdata ();\n\n  F77_XFCN (ztrsyl, ZTRSYL, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             1, a_nr, b_nr, F77_DBLE_CMPLX_ARG (pa), a_nr, F77_DBLE_CMPLX_ARG (pb),\n                             b_nr, F77_DBLE_CMPLX_ARG (px), a_nr, scale, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // FIXME: check info?\n\n  retval = ua * cx * ub.hermitian ();\n\n  return retval;\n}\n\nComplexMatrix\noperator * (const ComplexMatrix& m, const Matrix& a)\n{\n  if (m.columns () > std::min (m.rows (), a.columns ()) / 10)\n    return ComplexMatrix (real (m) * a, imag (m) * a);\n  else\n    return m * ComplexMatrix (a);\n}\n\nComplexMatrix\noperator * (const Matrix& m, const ComplexMatrix& a)\n{\n  if (a.rows () > std::min (m.rows (), a.columns ()) / 10)\n    return ComplexMatrix (m * real (a), m * imag (a));\n  else\n    return ComplexMatrix (m) * a;\n}\n\n/*\n\n## Simple Dot Product, Matrix-Vector, and Matrix-Matrix Unit tests\n%!assert ([1+i 2+i 3+i] * [ 4+i ; 5+i ; 6+i], 29+21i, 1e-14)\n%!assert ([1+i 2+i ; 3+i 4+i ] * [5+i ; 6+i], [15 + 14i ; 37 + 18i], 1e-14)\n%!assert ([1+i 2+i ; 3+i 4+i ] * [5+i 6+i ; 7+i 8+i], [17 + 15i 20 + 17i; 41 + 19i 48 + 21i], 1e-14)\n%!assert ([1 i]*[i 0]', -i)\n\n## Test some simple identities\n%!shared M, cv, rv\n%! M = randn (10,10) + i*rand (10,10);\n%! cv = randn (10,1) + i*rand (10,1);\n%! rv = randn (1,10) + i*rand (1,10);\n%!assert ([M*cv,M*cv], M*[cv,cv], 1e-14)\n%!assert ([M.'*cv,M.'*cv], M.'*[cv,cv], 1e-14)\n%!assert ([M'*cv,M'*cv], M'*[cv,cv], 1e-14)\n%!assert ([rv*M;rv*M], [rv;rv]*M, 1e-14)\n%!assert ([rv*M.';rv*M.'], [rv;rv]*M.', 1e-14)\n%!assert ([rv*M';rv*M'], [rv;rv]*M', 1e-14)\n%!assert (2*rv*cv, [rv,rv]*[cv;cv], 2e-14)\n\n*/\n\nstatic inline char\nget_blas_trans_arg (bool trans, bool conj)\n{\n  return trans ? (conj ? 'C' : 'T') : 'N';\n}\n\n// the general GEMM operation\n\nComplexMatrix\nxgemm (const ComplexMatrix& a, const ComplexMatrix& b,\n       blas_trans_type transa, blas_trans_type transb)\n{\n  ComplexMatrix retval;\n\n  bool tra = transa != blas_no_trans;\n  bool trb = transb != blas_no_trans;\n  bool cja = transa == blas_conj_trans;\n  bool cjb = transb == blas_conj_trans;\n\n  F77_INT a_nr = octave::to_f77_int (tra ? a.cols () : a.rows ());\n  F77_INT a_nc = octave::to_f77_int (tra ? a.rows () : a.cols ());\n\n  F77_INT b_nr = octave::to_f77_int (trb ? b.cols () : b.rows ());\n  F77_INT b_nc = octave::to_f77_int (trb ? b.rows () : b.cols ());\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  if (a_nr == 0 || a_nc == 0 || b_nc == 0)\n    retval = ComplexMatrix (a_nr, b_nc, 0.0);\n  else if (a.data () == b.data () && a_nr == b_nc && tra != trb)\n    {\n      F77_INT lda = octave::to_f77_int (a.rows ());\n\n      // FIXME: looking at the reference BLAS, it appears that it\n      // should not be necessary to initialize the output matrix if\n      // BETA is 0 in the call to ZHERK, but ATLAS appears to\n      // use the result matrix before zeroing the elements.\n\n      retval = ComplexMatrix (a_nr, b_nc, 0.0);\n      Complex *c = retval.rwdata ();\n\n      const char ctra = get_blas_trans_arg (tra, cja);\n      if (cja || cjb)\n        {\n          F77_XFCN (zherk, ZHERK, (F77_CONST_CHAR_ARG2 (\"U\", 1),\n                                   F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   a_nr, a_nc, 1.0,\n                                   F77_CONST_DBLE_CMPLX_ARG (a.data ()), lda, 0.0, F77_DBLE_CMPLX_ARG (c), a_nr\n                                   F77_CHAR_ARG_LEN (1)\n                                   F77_CHAR_ARG_LEN (1)));\n          for (F77_INT j = 0; j < a_nr; j++)\n            for (F77_INT i = 0; i < j; i++)\n              retval.xelem (j, i) = octave::math::conj (retval.xelem (i, j));\n        }\n      else\n        {\n          F77_XFCN (zsyrk, ZSYRK, (F77_CONST_CHAR_ARG2 (\"U\", 1),\n                                   F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   a_nr, a_nc, 1.0,\n                                   F77_CONST_DBLE_CMPLX_ARG (a.data ()), lda, 0.0, F77_DBLE_CMPLX_ARG (c), a_nr\n                                   F77_CHAR_ARG_LEN (1)\n                                   F77_CHAR_ARG_LEN (1)));\n          for (F77_INT j = 0; j < a_nr; j++)\n            for (F77_INT i = 0; i < j; i++)\n              retval.xelem (j, i) = retval.xelem (i, j);\n\n        }\n\n    }\n  else\n    {\n      F77_INT lda = octave::to_f77_int (a.rows ());\n      F77_INT tda = octave::to_f77_int (a.cols ());\n      F77_INT ldb = octave::to_f77_int (b.rows ());\n      F77_INT tdb = octave::to_f77_int (b.cols ());\n\n      retval = ComplexMatrix (a_nr, b_nc, 0.0);\n      Complex *c = retval.rwdata ();\n\n      if (b_nc == 1 && a_nr == 1)\n        {\n          if (cja == cjb)\n            {\n              F77_FUNC (xzdotu, XZDOTU) (a_nc, F77_CONST_DBLE_CMPLX_ARG (a.data ()), 1,\n                                         F77_CONST_DBLE_CMPLX_ARG (b.data ()), 1,\n                                         F77_DBLE_CMPLX_ARG (c));\n              if (cja) *c = octave::math::conj (*c);\n            }\n          else if (cja)\n            F77_FUNC (xzdotc, XZDOTC) (a_nc, F77_CONST_DBLE_CMPLX_ARG (a.data ()), 1,\n                                       F77_CONST_DBLE_CMPLX_ARG (b.data ()), 1,\n                                       F77_DBLE_CMPLX_ARG (c));\n          else\n            F77_FUNC (xzdotc, XZDOTC) (a_nc, F77_CONST_DBLE_CMPLX_ARG (b.data ()), 1,\n                                       F77_CONST_DBLE_CMPLX_ARG (a.data ()), 1,\n                                       F77_DBLE_CMPLX_ARG (c));\n        }\n      else if (b_nc == 1 && ! cjb)\n        {\n          const char ctra = get_blas_trans_arg (tra, cja);\n          F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   lda, tda, 1.0, F77_CONST_DBLE_CMPLX_ARG (a.data ()), lda,\n                                   F77_CONST_DBLE_CMPLX_ARG (b.data ()), 1, 0.0, F77_DBLE_CMPLX_ARG (c), 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n      else if (a_nr == 1 && ! cja && ! cjb)\n        {\n          const char crevtrb = get_blas_trans_arg (! trb, cjb);\n          F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 (&crevtrb, 1),\n                                   ldb, tdb, 1.0, F77_CONST_DBLE_CMPLX_ARG (b.data ()), ldb,\n                                   F77_CONST_DBLE_CMPLX_ARG (a.data ()), 1, 0.0, F77_DBLE_CMPLX_ARG (c), 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n      else\n        {\n          const char ctra = get_blas_trans_arg (tra, cja);\n          const char ctrb = get_blas_trans_arg (trb, cjb);\n          F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   F77_CONST_CHAR_ARG2 (&ctrb, 1),\n                                   a_nr, b_nc, a_nc, 1.0, F77_CONST_DBLE_CMPLX_ARG (a.data ()),\n                                   lda, F77_CONST_DBLE_CMPLX_ARG (b.data ()), ldb, 0.0, F77_DBLE_CMPLX_ARG (c),\n                                   a_nr\n                                   F77_CHAR_ARG_LEN (1)\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n    }\n\n  return retval;\n}\n\nComplexMatrix\noperator * (const ComplexMatrix& a, const ComplexMatrix& b)\n{\n  return xgemm (a, b);\n}\n\n// FIXME: it would be nice to share code among the min/max functions below.\n\n#define EMPTY_RETURN_CHECK(T)                   \\\n  if (nr == 0 || nc == 0)                       \\\n    return T (nr, nc);\n\nComplexMatrix\nmin (const Complex& c, const ComplexMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmin (const Complex& c, const ComplexMatrix& m, const bool nanflag)\n{\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmin (const Complex& c, const ComplexMatrix& m,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (ComplexMatrix);\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::min (c, m(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nComplexMatrix\nmin (const ComplexMatrix& m, const Complex& c)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmin (const ComplexMatrix& m, const Complex& c, const bool nanflag)\n{\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmin (const ComplexMatrix& m, const Complex& c,\n     const bool nanflag, const bool realabs)\n{\n  return min (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmin (const ComplexMatrix& a, const ComplexMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return min (a, b, nanflag, realabs);\n}\n\nComplexMatrix\nmin (const ComplexMatrix& a, const ComplexMatrix& b, const bool nanflag)\n{\n  const bool realabs = false;\n  return min (a, b, nanflag, realabs);\n}\n\nComplexMatrix\nmin (const ComplexMatrix& a, const ComplexMatrix& b,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n\n  if (nr != b.rows () || nc != b.columns ())\n    (*current_liboctave_error_handler)\n      (\"two-arg min requires same size arguments\");\n\n  EMPTY_RETURN_CHECK (ComplexMatrix);\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::min (a(i, j), b(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nComplexMatrix\nmax (const Complex& c, const ComplexMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmax (const Complex& c, const ComplexMatrix& m, const bool nanflag)\n{\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmax (const Complex& c, const ComplexMatrix& m,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (ComplexMatrix);\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::max (c, m(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nComplexMatrix\nmax (const ComplexMatrix& m, const Complex& c)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmax (const ComplexMatrix& m, const Complex& c, const bool nanflag)\n{\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmax (const ComplexMatrix& m, const Complex& c,\n     const bool nanflag, const bool realabs)\n{\n  return max (c, m, nanflag, realabs);\n}\n\nComplexMatrix\nmax (const ComplexMatrix& a, const ComplexMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return max (a, b, nanflag, realabs);\n}\n\nComplexMatrix\nmax (const ComplexMatrix& a, const ComplexMatrix& b, const bool nanflag)\n{\n  const bool realabs = false;\n  return max (a, b, nanflag, realabs);\n}\n\nComplexMatrix\nmax (const ComplexMatrix& a, const ComplexMatrix& b,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n\n  if (nr != b.rows () || nc != b.columns ())\n    (*current_liboctave_error_handler)\n      (\"two-arg max requires same size arguments\");\n\n  EMPTY_RETURN_CHECK (ComplexMatrix);\n\n  ComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::max (a(i, j), b(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nComplexMatrix\nlinspace (const ComplexColumnVector& x1,\n          const ComplexColumnVector& x2,\n          octave_idx_type n)\n{\n  octave_idx_type m = x1.numel ();\n\n  if (x2.numel () != m)\n    (*current_liboctave_error_handler)\n      (\"linspace: vectors must be of equal length\");\n\n  ComplexMatrix retval;\n\n  if (n < 1)\n    {\n      retval.clear (m, 0);\n      return retval;\n    }\n\n  retval.clear (m, n);\n  for (octave_idx_type i = 0; i < m; i++)\n    retval.insert (linspace (x1(i), x2(i), n), i, 0);\n\n  return retval;\n}\n\nMS_CMP_OPS (ComplexMatrix, Complex)\nMS_BOOL_OPS (ComplexMatrix, Complex)\n\nSM_CMP_OPS (Complex, ComplexMatrix)\nSM_BOOL_OPS (Complex, ComplexMatrix)\n\nMM_CMP_OPS (ComplexMatrix, ComplexMatrix)\nMM_BOOL_OPS (ComplexMatrix, ComplexMatrix)\n"
  },
  {
    "path": "liboctave/array/CMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_CMatrix_h)\n#define octave_CMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"CNDArray.h\"\n#include \"DET.h\"\n#include \"MArray.h\"\n#include \"MDiagArray2.h\"\n#include \"MatrixType.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-cmplx.h\"\n\nclass OCTAVE_API ComplexMatrix : public ComplexNDArray\n{\npublic:\n\n  typedef ComplexColumnVector column_vector_type;\n  typedef ComplexRowVector row_vector_type;\n\n  typedef ColumnVector real_column_vector_type;\n  typedef RowVector real_row_vector_type;\n\n  typedef Matrix real_matrix_type;\n  typedef ComplexMatrix complex_matrix_type;\n\n  typedef DiagMatrix real_diag_matrix_type;\n  typedef ComplexDiagMatrix complex_diag_matrix_type;\n\n  typedef double real_elt_type;\n  typedef Complex complex_elt_type;\n\n  typedef void (*solve_singularity_handler) (double rcon);\n\n  ComplexMatrix () = default;\n\n  ComplexMatrix (const ComplexMatrix& a) = default;\n\n  ComplexMatrix& operator = (const ComplexMatrix& a) = default;\n\n  ~ComplexMatrix () = default;\n\n  ComplexMatrix (octave_idx_type r, octave_idx_type c)\n    : ComplexNDArray (dim_vector (r, c)) { }\n\n  ComplexMatrix (octave_idx_type r, octave_idx_type c, const Complex& val)\n    : ComplexNDArray (dim_vector (r, c), val) { }\n\n  ComplexMatrix (const dim_vector& dv) : ComplexNDArray (dv.redim (2)) { }\n\n  ComplexMatrix (const dim_vector& dv, const Complex& val)\n    : ComplexNDArray (dv.redim (2), val) { }\n\n  template <typename U>\n  ComplexMatrix (const MArray<U>& a) : ComplexNDArray (a.as_matrix ()) { }\n\n  template <typename U>\n  ComplexMatrix (const Array<U>& a) : ComplexNDArray (a.as_matrix ()) { }\n\n  OCTAVE_API ComplexMatrix (const Matrix& re, const Matrix& im);\n\n  explicit OCTAVE_API ComplexMatrix (const Matrix& a);\n\n  explicit OCTAVE_API ComplexMatrix (const RowVector& rv);\n\n  explicit OCTAVE_API ComplexMatrix (const ColumnVector& cv);\n\n  explicit OCTAVE_API ComplexMatrix (const DiagMatrix& a);\n\n  explicit OCTAVE_API ComplexMatrix (const MDiagArray2<double>& a);\n\n  explicit OCTAVE_API ComplexMatrix (const DiagArray2<double>& a);\n\n  explicit OCTAVE_API ComplexMatrix (const ComplexRowVector& rv);\n\n  explicit OCTAVE_API ComplexMatrix (const ComplexColumnVector& cv);\n\n  explicit OCTAVE_API ComplexMatrix (const ComplexDiagMatrix& a);\n\n  explicit OCTAVE_API ComplexMatrix (const MDiagArray2<Complex>& a);\n\n  explicit OCTAVE_API ComplexMatrix (const DiagArray2<Complex>& a);\n\n  explicit OCTAVE_API ComplexMatrix (const boolMatrix& a);\n\n  explicit OCTAVE_API ComplexMatrix (const charMatrix& a);\n\n  OCTAVE_API bool operator == (const ComplexMatrix& a) const;\n  OCTAVE_API bool operator != (const ComplexMatrix& a) const;\n\n  OCTAVE_API bool ishermitian () const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API ComplexMatrix&\n  insert (const Matrix& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API ComplexMatrix&\n  insert (const RowVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API ComplexMatrix&\n  insert (const ColumnVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API ComplexMatrix&\n  insert (const DiagMatrix& a, octave_idx_type r, octave_idx_type c);\n\n  OCTAVE_API ComplexMatrix&\n  insert (const ComplexMatrix& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API ComplexMatrix&\n  insert (const ComplexRowVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API ComplexMatrix&\n  insert (const ComplexColumnVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API ComplexMatrix&\n  insert (const ComplexDiagMatrix& a, octave_idx_type r, octave_idx_type c);\n\n  OCTAVE_API ComplexMatrix& fill (double val);\n  OCTAVE_API ComplexMatrix& fill (const Complex& val);\n  OCTAVE_API ComplexMatrix&\n  fill (double val, octave_idx_type r1, octave_idx_type c1,\n        octave_idx_type r2, octave_idx_type c2);\n  OCTAVE_API ComplexMatrix&\n  fill (const Complex& val, octave_idx_type r1, octave_idx_type c1,\n        octave_idx_type r2, octave_idx_type c2);\n\n  OCTAVE_API ComplexMatrix append (const Matrix& a) const;\n  OCTAVE_API ComplexMatrix append (const RowVector& a) const;\n  OCTAVE_API ComplexMatrix append (const ColumnVector& a) const;\n  OCTAVE_API ComplexMatrix append (const DiagMatrix& a) const;\n\n  OCTAVE_API ComplexMatrix append (const ComplexMatrix& a) const;\n  OCTAVE_API ComplexMatrix append (const ComplexRowVector& a) const;\n  OCTAVE_API ComplexMatrix append (const ComplexColumnVector& a) const;\n  OCTAVE_API ComplexMatrix append (const ComplexDiagMatrix& a) const;\n\n  OCTAVE_API ComplexMatrix stack (const Matrix& a) const;\n  OCTAVE_API ComplexMatrix stack (const RowVector& a) const;\n  OCTAVE_API ComplexMatrix stack (const ColumnVector& a) const;\n  OCTAVE_API ComplexMatrix stack (const DiagMatrix& a) const;\n\n  OCTAVE_API ComplexMatrix stack (const ComplexMatrix& a) const;\n  OCTAVE_API ComplexMatrix stack (const ComplexRowVector& a) const;\n  OCTAVE_API ComplexMatrix stack (const ComplexColumnVector& a) const;\n  OCTAVE_API ComplexMatrix stack (const ComplexDiagMatrix& a) const;\n\n  ComplexMatrix hermitian () const\n  { return MArray<Complex>::hermitian (std::conj); }\n  ComplexMatrix transpose () const\n  { return MArray<Complex>::transpose (); }\n\n  friend OCTAVE_API ComplexMatrix conj (const ComplexMatrix& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API ComplexMatrix\n  extract (octave_idx_type r1, octave_idx_type c1,\n           octave_idx_type r2, octave_idx_type c2) const;\n\n  OCTAVE_API ComplexMatrix\n  extract_n (octave_idx_type r1, octave_idx_type c1,\n             octave_idx_type nr, octave_idx_type nc) const;\n\n  // extract row or column i.\n\n  OCTAVE_API ComplexRowVector row (octave_idx_type i) const;\n\n  OCTAVE_API ComplexColumnVector column (octave_idx_type i) const;\n\n  void resize (octave_idx_type nr, octave_idx_type nc,\n               const Complex& rfv = Complex (0))\n  {\n    MArray<Complex>::resize (dim_vector (nr, nc), rfv);\n  }\n\nprivate:\n  ComplexMatrix tinverse (MatrixType& mattype, octave_idx_type& info,\n                          double& rcon, bool force, bool calc_cond) const;\n\n  ComplexMatrix finverse (MatrixType& mattype, octave_idx_type& info,\n                          double& rcon, bool force, bool calc_cond) const;\n\npublic:\n  OCTAVE_API ComplexMatrix inverse () const;\n  OCTAVE_API ComplexMatrix inverse (octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  inverse (octave_idx_type& info, double& rcon,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API ComplexMatrix inverse (MatrixType& mattype) const;\n  OCTAVE_API ComplexMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info, double& rcon,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API ComplexMatrix pseudo_inverse (double tol = 0.0) const;\n\n  OCTAVE_API ComplexMatrix fourier () const;\n  OCTAVE_API ComplexMatrix ifourier () const;\n\n  OCTAVE_API ComplexMatrix fourier2d () const;\n  OCTAVE_API ComplexMatrix ifourier2d () const;\n\n  OCTAVE_API ComplexDET determinant () const;\n  OCTAVE_API ComplexDET determinant (octave_idx_type& info) const;\n  OCTAVE_API ComplexDET\n  determinant (octave_idx_type& info, double& rcon,\n               bool calc_cond = true) const;\n  OCTAVE_API ComplexDET\n  determinant (MatrixType& mattype, octave_idx_type& info, double& rcon,\n               bool calc_cond = true) const;\n\n  OCTAVE_API double rcond () const;\n  OCTAVE_API double rcond (MatrixType& mattype) const;\n\nprivate:\n  // Upper triangular matrix solvers\n  ComplexMatrix utsolve (MatrixType& mattype, const ComplexMatrix& b,\n                         octave_idx_type& info, double& rcon,\n                         solve_singularity_handler sing_handler,\n                         bool calc_cond = false,\n                         blas_trans_type transt = blas_no_trans) const;\n\n  // Lower triangular matrix solvers\n  ComplexMatrix ltsolve (MatrixType& mattype, const ComplexMatrix& b,\n                         octave_idx_type& info, double& rcon,\n                         solve_singularity_handler sing_handler,\n                         bool calc_cond = false,\n                         blas_trans_type transt = blas_no_trans) const;\n\n  // Full matrix solvers (umfpack/cholesky)\n  ComplexMatrix fsolve (MatrixType& mattype, const ComplexMatrix& b,\n                        octave_idx_type& info, double& rcon,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond = false) const;\n\npublic:\n  // Generic interface to solver with no probing of type\n  OCTAVE_API ComplexMatrix solve (MatrixType& mattype, const Matrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n         double& rcon) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n         double& rcon, solve_singularity_handler sing_handler,\n         bool singular_fallback = true,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b, octave_idx_type& info,\n         double& rcon) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b, octave_idx_type& info,\n         double& rcon, solve_singularity_handler sing_handler,\n         bool singular_fallback = true,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b,\n         octave_idx_type& info, double& rcon) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b, octave_idx_type& info,\n         double& rcon, solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b,\n         octave_idx_type& info, double& rcon) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b,\n         octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  // Generic interface to solver with probing of type\n  OCTAVE_API ComplexMatrix solve (const Matrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (const Matrix& b, octave_idx_type& info, double& rcon) const;\n  OCTAVE_API ComplexMatrix\n  solve (const Matrix& b, octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexMatrix solve (const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexColumnVector solve (const ColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info, double& rcon) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexColumnVector solve (const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info,\n         double& rcon) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexMatrix lssolve (const Matrix& b) const;\n  OCTAVE_API ComplexMatrix\n  lssolve (const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  lssolve (const Matrix& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API ComplexMatrix\n  lssolve (const Matrix& b, octave_idx_type& info,\n           octave_idx_type& rank, double& rcon) const;\n\n  OCTAVE_API ComplexMatrix lssolve (const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  lssolve (const ComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  lssolve (const ComplexMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API ComplexMatrix\n  lssolve (const ComplexMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank, double& rcon) const;\n\n  OCTAVE_API ComplexColumnVector lssolve (const ColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  lssolve (const ColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  lssolve (const ColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API ComplexColumnVector\n  lssolve (const ColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank, double& rcon) const;\n\n  OCTAVE_API ComplexColumnVector lssolve (const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  lssolve (const ComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  lssolve (const ComplexColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API ComplexColumnVector\n  lssolve (const ComplexColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank, double& rcon) const;\n\n  // matrix by diagonal matrix -> matrix operations\n\n  OCTAVE_API ComplexMatrix& operator += (const DiagMatrix& a);\n  OCTAVE_API ComplexMatrix& operator -= (const DiagMatrix& a);\n\n  OCTAVE_API ComplexMatrix& operator += (const ComplexDiagMatrix& a);\n  OCTAVE_API ComplexMatrix& operator -= (const ComplexDiagMatrix& a);\n\n  // matrix by matrix -> matrix operations\n\n  OCTAVE_API ComplexMatrix& operator += (const Matrix& a);\n  OCTAVE_API ComplexMatrix& operator -= (const Matrix& a);\n\n  // other operations\n\n  OCTAVE_API boolMatrix all (int dim = -1) const;\n  OCTAVE_API boolMatrix any (int dim = -1) const;\n\n  OCTAVE_API ComplexMatrix flip (int dim = -1) const;\n  OCTAVE_API ComplexMatrix cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexMatrix cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexMatrix prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexMatrix sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexMatrix sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API Matrix abs () const;\n\n  OCTAVE_API ComplexMatrix diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API ComplexDiagMatrix\n  diag (octave_idx_type m, octave_idx_type n) const;\n\n  OCTAVE_API bool row_is_real_only (octave_idx_type) const;\n  OCTAVE_API bool column_is_real_only (octave_idx_type) const;\n\n  OCTAVE_API ComplexColumnVector row_min () const;\n  OCTAVE_API ComplexColumnVector row_max () const;\n\n  OCTAVE_API ComplexColumnVector row_min (Array<octave_idx_type>& index) const;\n  OCTAVE_API ComplexColumnVector row_max (Array<octave_idx_type>& index) const;\n\n  OCTAVE_API ComplexRowVector column_min () const;\n  OCTAVE_API ComplexRowVector column_max () const;\n\n  OCTAVE_API ComplexRowVector column_min (Array<octave_idx_type>& index) const;\n  OCTAVE_API ComplexRowVector column_max (Array<octave_idx_type>& index) const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const ComplexMatrix& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, ComplexMatrix& a);\n};\n\nextern OCTAVE_API ComplexMatrix conj (const ComplexMatrix& a);\n\n// column vector by row vector -> matrix operations\n\nextern OCTAVE_API ComplexMatrix\noperator * (const ColumnVector& a, const ComplexRowVector& b);\n\nextern OCTAVE_API ComplexMatrix\noperator * (const ComplexColumnVector& a, const RowVector& b);\n\nextern OCTAVE_API ComplexMatrix\noperator * (const ComplexColumnVector& a, const ComplexRowVector& b);\n\nextern OCTAVE_API ComplexMatrix\nGivens (const Complex&, const Complex&);\n\nextern OCTAVE_API ComplexMatrix\nSylvester (const ComplexMatrix&, const ComplexMatrix&, const ComplexMatrix&);\n\nextern OCTAVE_API ComplexMatrix\nxgemm (const ComplexMatrix& a, const ComplexMatrix& b,\n       blas_trans_type transa = blas_no_trans,\n       blas_trans_type transb = blas_no_trans);\n\nextern OCTAVE_API ComplexMatrix operator * (const Matrix&,\n                                            const ComplexMatrix&);\nextern OCTAVE_API ComplexMatrix operator * (const ComplexMatrix&,\n                                            const Matrix&);\nextern OCTAVE_API ComplexMatrix operator * (const ComplexMatrix&,\n                                            const ComplexMatrix&);\n\nextern OCTAVE_API ComplexMatrix min (const Complex& c, const ComplexMatrix& m);\nextern OCTAVE_API ComplexMatrix min (const Complex& c, const ComplexMatrix& m,\n                                     const bool nanflag);\nextern OCTAVE_API ComplexMatrix min (const Complex& c, const ComplexMatrix& m,\n                                     const bool nanflag, const bool realabs);\nextern OCTAVE_API ComplexMatrix min (const ComplexMatrix& m, const Complex& c);\nextern OCTAVE_API ComplexMatrix min (const ComplexMatrix& m, const Complex& c,\n                                     const bool nanflag);\nextern OCTAVE_API ComplexMatrix min (const ComplexMatrix& m, const Complex& c,\n                                     const bool nanflag, const bool realabs);\nextern OCTAVE_API ComplexMatrix min (const ComplexMatrix& a,\n                                     const ComplexMatrix& b);\nextern OCTAVE_API ComplexMatrix min (const ComplexMatrix& a,\n                                     const ComplexMatrix& b, const bool nanflag);\nextern OCTAVE_API ComplexMatrix min (const ComplexMatrix& a,\n                                     const ComplexMatrix& b,\n                                     const bool nanflag, const bool realabs);\n\nextern OCTAVE_API ComplexMatrix max (const Complex& c, const ComplexMatrix& m);\nextern OCTAVE_API ComplexMatrix max (const Complex& c, const ComplexMatrix& m,\n                                     const bool nanflag);\nextern OCTAVE_API ComplexMatrix max (const Complex& c, const ComplexMatrix& m,\n                                     const bool nanflag, const bool realabs);\nextern OCTAVE_API ComplexMatrix max (const ComplexMatrix& m, const Complex& c);\nextern OCTAVE_API ComplexMatrix max (const ComplexMatrix& m, const Complex& c,\n                                     const bool nanflag);\nextern OCTAVE_API ComplexMatrix max (const ComplexMatrix& m, const Complex& c,\n                                     const bool nanflag, const bool realabs);\nextern OCTAVE_API ComplexMatrix max (const ComplexMatrix& a,\n                                     const ComplexMatrix& b);\nextern OCTAVE_API ComplexMatrix max (const ComplexMatrix& a,\n                                     const ComplexMatrix& b, const bool nanflag);\nextern OCTAVE_API ComplexMatrix max (const ComplexMatrix& a,\n                                     const ComplexMatrix& b,\n                                     const bool nanflag, const bool realabs);\n\nextern OCTAVE_API ComplexMatrix linspace (const ComplexColumnVector& x1,\n                                          const ComplexColumnVector& x2,\n                                          octave_idx_type n);\n\nMS_CMP_OP_DECLS (ComplexMatrix, Complex, OCTAVE_API)\nMS_BOOL_OP_DECLS (ComplexMatrix, Complex, OCTAVE_API)\n\nSM_CMP_OP_DECLS (Complex, ComplexMatrix, OCTAVE_API)\nSM_BOOL_OP_DECLS (Complex, ComplexMatrix, OCTAVE_API)\n\nMM_CMP_OP_DECLS (ComplexMatrix, ComplexMatrix, OCTAVE_API)\nMM_BOOL_OP_DECLS (ComplexMatrix, ComplexMatrix, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, ComplexMatrix, Complex)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/CNDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <complex>\n#include <istream>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"CNDArray.h\"\n#include \"f77-fcn.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"mx-base.h\"\n#include \"mx-cnda-s.h\"\n#include \"mx-op-defs.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n\n#include \"bsxfun-defs.cc\"\n\nComplexNDArray::ComplexNDArray (const charNDArray& a)\n  : MArray<Complex> (a.dims ())\n{\n  octave_idx_type n = a.numel ();\n  for (octave_idx_type i = 0; i < n; i++)\n    xelem (i) = static_cast<unsigned char> (a(i));\n}\n\n#if defined (HAVE_FFTW)\n\nComplexNDArray\nComplexNDArray::fourier (int dim) const\n{\n  const dim_vector& dv = dims ();\n\n  if (dim > dv.ndims () || dim < 0)\n    return ComplexNDArray ();\n\n  octave_idx_type stride = 1;\n  octave_idx_type n = dv(dim);\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  octave_idx_type howmany = numel () / dv(dim);\n  howmany = (stride == 1) ? howmany : std::min (howmany, stride);\n  octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);\n  octave_idx_type dist = (stride == 1 ? n : 1);\n\n  const Complex *in (data ());\n  ComplexNDArray retval (dv);\n  Complex *out (retval.rwdata ());\n\n  // Need to be careful here about the distance between fft's\n  for (octave_idx_type k = 0; k < nloop; k++)\n    octave::fftw::fft (in + k * stride * n, out + k * stride * n,\n                       n, howmany, stride, dist);\n\n  return retval;\n}\n\nComplexNDArray\nComplexNDArray::ifourier (int dim) const\n{\n  const dim_vector& dv = dims ();\n\n  if (dim > dv.ndims () || dim < 0)\n    return ComplexNDArray ();\n\n  octave_idx_type stride = 1;\n  octave_idx_type n = dv(dim);\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  octave_idx_type howmany = numel () / dv(dim);\n  howmany = (stride == 1) ? howmany : std::min (howmany, stride);\n  octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);\n  octave_idx_type dist = (stride == 1 ? n : 1);\n\n  const Complex *in (data ());\n  ComplexNDArray retval (dv);\n  Complex *out (retval.rwdata ());\n\n  // Need to be careful here about the distance between fft's\n  for (octave_idx_type k = 0; k < nloop; k++)\n    octave::fftw::ifft (in + k * stride * n, out + k * stride * n,\n                        n, howmany, stride, dist);\n\n  return retval;\n}\n\nComplexNDArray\nComplexNDArray::fourier2d () const\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 2)\n    return ComplexNDArray ();\n\n  dim_vector dv2 (dv(0), dv(1));\n  const Complex *in = data ();\n  ComplexNDArray retval (dv);\n  Complex *out = retval.rwdata ();\n  octave_idx_type howmany = numel () / dv(0) / dv(1);\n  octave_idx_type dist = dv(0) * dv(1);\n\n  for (octave_idx_type i=0; i < howmany; i++)\n    octave::fftw::fftNd (in + i*dist, out + i*dist, 2, dv2);\n\n  return retval;\n}\n\nComplexNDArray\nComplexNDArray::ifourier2d () const\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 2)\n    return ComplexNDArray ();\n\n  dim_vector dv2 (dv(0), dv(1));\n  const Complex *in = data ();\n  ComplexNDArray retval (dv);\n  Complex *out = retval.rwdata ();\n  octave_idx_type howmany = numel () / dv(0) / dv(1);\n  octave_idx_type dist = dv(0) * dv(1);\n\n  for (octave_idx_type i=0; i < howmany; i++)\n    octave::fftw::ifftNd (in + i*dist, out + i*dist, 2, dv2);\n\n  return retval;\n}\n\nComplexNDArray\nComplexNDArray::fourierNd () const\n{\n  const dim_vector& dv = dims ();\n  int rank = dv.ndims ();\n\n  const Complex *in (data ());\n  ComplexNDArray retval (dv);\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::fftNd (in, out, rank, dv);\n\n  return retval;\n}\n\nComplexNDArray\nComplexNDArray::ifourierNd () const\n{\n  const dim_vector& dv = dims ();\n  int rank = dv.ndims ();\n\n  const Complex *in (data ());\n  ComplexNDArray retval (dv);\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::ifftNd (in, out, rank, dv);\n\n  return retval;\n}\n\n#else\n\nComplexNDArray\nComplexNDArray::fourier (int dim) const\n{\n  octave_unused_parameter (dim);\n\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nComplexNDArray::ifourier (int dim) const\n{\n  octave_unused_parameter (dim);\n\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nComplexNDArray::fourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nComplexNDArray::ifourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nComplexNDArray::fourierNd () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nComplexNDArray::ifourierNd () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\n#endif\n\n// unary operations\n\nboolNDArray\nComplexNDArray::operator ! () const\n{\n  if (any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n\n  return do_mx_unary_op<bool, Complex> (*this, mx_inline_not);\n}\n\n// FIXME: this is not quite the right thing.\n\nbool\nComplexNDArray::any_element_is_nan () const\n{\n  return do_mx_check<Complex> (*this, mx_inline_any_nan);\n}\n\nbool\nComplexNDArray::any_element_is_inf_or_nan () const\n{\n  return ! do_mx_check<Complex> (*this, mx_inline_all_finite);\n}\n\n// Return true if no elements have imaginary components.\n\nbool\nComplexNDArray::all_elements_are_real () const\n{\n  return do_mx_check<Complex> (*this, mx_inline_all_real);\n}\n\n// Return nonzero if any element of CM has a non-integer real or\n// imaginary part.  Also extract the largest and smallest (real or\n// imaginary) values and return them in MAX_VAL and MIN_VAL.\n\nbool\nComplexNDArray::all_integers (double& max_val, double& min_val) const\n{\n  octave_idx_type nel = numel ();\n\n  if (nel > 0)\n    {\n      Complex val = elem (0);\n\n      double r_val = val.real ();\n      double i_val = val.imag ();\n\n      max_val = r_val;\n      min_val = r_val;\n\n      if (i_val > max_val)\n        max_val = i_val;\n\n      if (i_val < max_val)\n        min_val = i_val;\n    }\n  else\n    return false;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      Complex val = elem (i);\n\n      double r_val = val.real ();\n      double i_val = val.imag ();\n\n      if (r_val > max_val)\n        max_val = r_val;\n\n      if (i_val > max_val)\n        max_val = i_val;\n\n      if (r_val < min_val)\n        min_val = r_val;\n\n      if (i_val < min_val)\n        min_val = i_val;\n\n      if (octave::math::round (r_val) != r_val\n          || octave::math::round (i_val) != i_val)\n        return false;\n    }\n\n  return true;\n}\n\nbool\nComplexNDArray::too_large_for_float () const\n{\n  return test_any (octave::too_large_for_float);\n}\n\nboolNDArray\nComplexNDArray::all (int dim) const\n{\n  return do_mx_red_op<bool, Complex> (*this, dim, mx_inline_all);\n}\n\nboolNDArray\nComplexNDArray::any (int dim) const\n{\n  return do_mx_red_op<bool, Complex> (*this, dim, mx_inline_any);\n}\n\nComplexNDArray\nComplexNDArray::flip (int dim) const\n{\n  return do_mx_flip_op<Complex, Complex> (*this, dim, mx_inline_flip);\n}\n\nComplexNDArray\nComplexNDArray::cumprod (int dim, bool nanflag) const\n{\n  return do_mx_cum_op<Complex, Complex> (*this, dim, nanflag, mx_inline_cumprod);\n}\n\nComplexNDArray\nComplexNDArray::cumsum (int dim, bool nanflag) const\n{\n  return do_mx_cum_op<Complex, Complex> (*this, dim, nanflag, mx_inline_cumsum);\n}\n\nComplexNDArray\nComplexNDArray::prod (int dim, bool nanflag) const\n{\n  return do_mx_red_op<Complex, Complex> (*this, dim, nanflag, mx_inline_prod);\n}\n\nComplexNDArray\nComplexNDArray::sum (int dim, bool nanflag) const\n{\n  return do_mx_red_op<Complex, Complex> (*this, dim, nanflag, mx_inline_sum);\n}\n\nComplexNDArray\nComplexNDArray::xsum (int dim, bool nanflag) const\n{\n  return do_mx_red_op<Complex, Complex> (*this, dim, nanflag, mx_inline_xsum);\n}\n\nComplexNDArray\nComplexNDArray::sumsq (int dim, bool nanflag) const\n{\n  return do_mx_red_op<double, Complex> (*this, dim, nanflag, mx_inline_sumsq);\n}\n\nComplexNDArray\nComplexNDArray::diff (octave_idx_type order, int dim) const\n{\n  return do_mx_diff_op<Complex> (*this, dim, order, mx_inline_diff);\n}\n\nComplexNDArray\nComplexNDArray::concat (const ComplexNDArray& rb,\n                        const Array<octave_idx_type>& ra_idx)\n{\n  if (rb.numel () > 0)\n    insert (rb, ra_idx);\n  return *this;\n}\n\nComplexNDArray\nComplexNDArray::concat (const NDArray& rb, const Array<octave_idx_type>& ra_idx)\n{\n  ComplexNDArray tmp (rb);\n  if (rb.numel () > 0)\n    insert (tmp, ra_idx);\n  return *this;\n}\n\nComplexNDArray\nconcat (NDArray& ra, ComplexNDArray& rb, const Array<octave_idx_type>& ra_idx)\n{\n  ComplexNDArray retval (ra);\n  if (rb.numel () > 0)\n    retval.insert (rb, ra_idx);\n  return retval;\n}\n\nstatic const Complex Complex_NaN_result (octave::numeric_limits<double>::NaN (),\n                                         octave::numeric_limits<double>::NaN ());\n\nComplexNDArray\nComplexNDArray::max (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<Complex> (*this, dim, nanflag, realabs, mx_inline_cmax);\n}\n\nComplexNDArray\nComplexNDArray::max (Array<octave_idx_type>& idx_arg,\n                     int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<Complex> (*this, idx_arg, dim, nanflag,\n                                   realabs, mx_inline_cmax);\n}\n\nComplexNDArray\nComplexNDArray::min (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<Complex> (*this, dim, nanflag, realabs, mx_inline_cmin);\n}\n\nComplexNDArray\nComplexNDArray::min (Array<octave_idx_type>& idx_arg,\n                     int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<Complex> (*this, idx_arg, dim, nanflag,\n                                   realabs, mx_inline_cmin);\n}\n\nComplexNDArray\nComplexNDArray::cummax (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<Complex> (*this, dim, nanflag,\n                                      realabs, mx_inline_ccummax);\n}\n\nComplexNDArray\nComplexNDArray::cummax (Array<octave_idx_type>& idx_arg,\n                        int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<Complex> (*this, idx_arg, dim, nanflag,\n                                      realabs, mx_inline_ccummax);\n}\n\nComplexNDArray\nComplexNDArray::cummin (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<Complex> (*this, dim, nanflag,\n                                      realabs, mx_inline_ccummin);\n}\n\nComplexNDArray\nComplexNDArray::cummin (Array<octave_idx_type>& idx_arg,\n                        int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<Complex> (*this, idx_arg, dim, nanflag,\n                                      realabs, mx_inline_ccummin);\n}\n\nNDArray\nComplexNDArray::abs () const\n{\n  return do_mx_unary_map<double, Complex, std::abs> (*this);\n}\n\nboolNDArray\nComplexNDArray::isnan () const\n{\n  return do_mx_unary_map<bool, Complex, octave::math::isnan> (*this);\n}\n\nboolNDArray\nComplexNDArray::isinf () const\n{\n  return do_mx_unary_map<bool, Complex, octave::math::isinf> (*this);\n}\n\nboolNDArray\nComplexNDArray::isfinite () const\n{\n  return do_mx_unary_map<bool, Complex, octave::math::isfinite> (*this);\n}\n\nComplexNDArray\nconj (const ComplexNDArray& a)\n{\n  return do_mx_unary_map<Complex, Complex, std::conj<double>> (a);\n}\n\nComplexNDArray&\nComplexNDArray::insert (const NDArray& a, octave_idx_type r, octave_idx_type c)\n{\n  const dim_vector& a_dv = a.dims ();\n  const dim_vector& dv = dims ();\n\n  int n = a_dv.ndims ();\n\n  if (n != dv.ndims ())\n    (*current_liboctave_error_handler)\n      (\"Array<T>::insert: invalid indexing operation\");\n\n  Array<octave_idx_type> a_ra_idx (dim_vector (a_dv.ndims (), 1), 0);\n\n  a_ra_idx.elem (0) = r;\n  a_ra_idx.elem (1) = c;\n\n  for (int i = 0; i < n; i++)\n    {\n      if (a_ra_idx(i) < 0 || (a_ra_idx(i) + a_dv(i)) > dv(i))\n        (*current_liboctave_error_handler)\n          (\"Array<T>::insert: range error for insert\");\n    }\n\n  a_ra_idx.elem (0) = 0;\n  a_ra_idx.elem (1) = 0;\n\n  octave_idx_type n_elt = a.numel ();\n\n  // IS make_unique () NECESSARY HERE?\n\n  for (octave_idx_type i = 0; i < n_elt; i++)\n    {\n      Array<octave_idx_type> ra_idx = a_ra_idx;\n\n      ra_idx.elem (0) = a_ra_idx(0) + r;\n      ra_idx.elem (1) = a_ra_idx(1) + c;\n\n      elem (ra_idx) = a.elem (a_ra_idx);\n\n      increment_index (a_ra_idx, a_dv);\n    }\n\n  return *this;\n}\n\nComplexNDArray&\nComplexNDArray::insert (const ComplexNDArray& a,\n                        octave_idx_type r, octave_idx_type c)\n{\n  Array<Complex>::insert (a, r, c);\n  return *this;\n}\n\nComplexNDArray&\nComplexNDArray::insert (const ComplexNDArray& a,\n                        const Array<octave_idx_type>& ra_idx)\n{\n  Array<Complex>::insert (a, ra_idx);\n  return *this;\n}\n\nvoid\nComplexNDArray::increment_index (Array<octave_idx_type>& ra_idx,\n                                 const dim_vector& dimensions,\n                                 int start_dimension)\n{\n  ::increment_index (ra_idx, dimensions, start_dimension);\n}\n\noctave_idx_type\nComplexNDArray::compute_index (Array<octave_idx_type>& ra_idx,\n                               const dim_vector& dimensions)\n{\n  return ::compute_index (ra_idx, dimensions);\n}\n\nComplexNDArray\nComplexNDArray::diag (octave_idx_type k) const\n{\n  return MArray<Complex>::diag (k);\n}\n\nComplexNDArray\nComplexNDArray::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return MArray<Complex>::diag (m, n);\n}\n\n// This contains no information on the array structure !!!\nstd::ostream&\noperator << (std::ostream& os, const ComplexNDArray& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      os << ' ';\n      octave::write_value<Complex> (os, a.elem (i));\n      os << \"\\n\";\n    }\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, ComplexNDArray& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  if (nel > 0)\n    {\n      Complex tmp;\n      for (octave_idx_type i = 0; i < nel; i++)\n        {\n          tmp = octave::read_value<Complex> (is);\n          if (is)\n            a.elem (i) = tmp;\n          else\n            return is;\n        }\n    }\n\n  return is;\n}\n\nMINMAX_FCNS (ComplexNDArray, Complex)\n\nNDS_CMP_OPS (ComplexNDArray, Complex)\nNDS_BOOL_OPS (ComplexNDArray, Complex)\n\nSND_CMP_OPS (Complex, ComplexNDArray)\nSND_BOOL_OPS (Complex, ComplexNDArray)\n\nNDND_CMP_OPS (ComplexNDArray, ComplexNDArray)\nNDND_BOOL_OPS (ComplexNDArray, ComplexNDArray)\n\nComplexNDArray& operator *= (ComplexNDArray& a, double s)\n{\n  if (a.is_shared ())\n    a = a * s;\n  else\n    do_ms_inplace_op<Complex, double> (a, s, mx_inline_mul2);\n  return a;\n}\n\nComplexNDArray&\noperator /= (ComplexNDArray& a, double s)\n{\n  if (a.is_shared ())\n    return a = a / s;\n  else\n    do_ms_inplace_op<Complex, double> (a, s, mx_inline_div2);\n  return a;\n}\n\nBSXFUN_STDOP_DEFS_MXLOOP (ComplexNDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (ComplexNDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, ComplexNDArray, mx_inline_pow)\n"
  },
  {
    "path": "liboctave/array/CNDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_CNDArray_h)\n#define octave_CNDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"bsxfun-decl.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n\nclass OCTAVE_API ComplexNDArray : public MArray<Complex>\n{\npublic:\n\n  ComplexNDArray () : MArray<Complex> () { }\n\n  ComplexNDArray (const dim_vector& dv) : MArray<Complex> (dv) { }\n\n  ComplexNDArray (const dim_vector& dv, const Complex& val)\n    : MArray<Complex> (dv, val) { }\n\n  ComplexNDArray (const ComplexNDArray& a) : MArray<Complex> (a) { }\n\n  template <typename U>\n  ComplexNDArray (const MArray<U>& a) : MArray<Complex> (a) { }\n\n  template <typename U>\n  ComplexNDArray (const Array<U>& a) : MArray<Complex> (a) { }\n\n  ComplexNDArray (const charNDArray&);\n\n  ComplexNDArray& operator = (const ComplexNDArray& a)\n  {\n    MArray<Complex>::operator = (a);\n    return *this;\n  }\n\n  ~ComplexNDArray () = default;\n\n  // unary operations\n\n  OCTAVE_API boolNDArray operator ! () const;\n\n  // other operations\n\n  OCTAVE_API bool any_element_is_nan () const;\n  OCTAVE_API bool any_element_is_inf_or_nan () const;\n  OCTAVE_API bool all_elements_are_real () const;\n  OCTAVE_API bool all_integers (double& max_val, double& min_val) const;\n  OCTAVE_API bool too_large_for_float () const;\n\n  OCTAVE_API boolNDArray all (int dim = -1) const;\n  OCTAVE_API boolNDArray any (int dim = -1) const;\n\n  OCTAVE_API ComplexNDArray flip (int dim = -1) const;\n  OCTAVE_API ComplexNDArray cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexNDArray cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexNDArray prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexNDArray sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexNDArray xsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexNDArray sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexNDArray\n  concat (const ComplexNDArray& rb, const Array<octave_idx_type>& ra_idx);\n  OCTAVE_API ComplexNDArray\n  concat (const NDArray& rb, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API ComplexNDArray\n  max (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API ComplexNDArray max (Array<octave_idx_type>& index, int dim = -1,\n                                 bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API ComplexNDArray\n  min (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API ComplexNDArray min (Array<octave_idx_type>& index, int dim = -1,\n                                 bool nanflag = true, bool realabs = false) const;\n\n  OCTAVE_API ComplexNDArray\n  cummax (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API ComplexNDArray\n  cummax (Array<octave_idx_type>& index, int dim = -1,\n          bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API ComplexNDArray\n  cummin (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API ComplexNDArray\n  cummin (Array<octave_idx_type>& index, int dim = -1,\n          bool nanflag = true, bool realabs = false) const;\n\n  OCTAVE_API ComplexNDArray\n  diff (octave_idx_type order = 1, int dim = -1) const;\n\n  OCTAVE_API ComplexNDArray&\n  insert (const NDArray& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API ComplexNDArray&\n  insert (const ComplexNDArray& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API ComplexNDArray&\n  insert (const ComplexNDArray& a, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API NDArray abs () const;\n  OCTAVE_API boolNDArray isnan () const;\n  OCTAVE_API boolNDArray isinf () const;\n  OCTAVE_API boolNDArray isfinite () const;\n\n  friend OCTAVE_API ComplexNDArray conj (const ComplexNDArray& a);\n\n  OCTAVE_API ComplexNDArray fourier (int dim = 1) const;\n  OCTAVE_API ComplexNDArray ifourier (int dim = 1) const;\n\n  OCTAVE_API ComplexNDArray fourier2d () const;\n  OCTAVE_API ComplexNDArray ifourier2d () const;\n\n  OCTAVE_API ComplexNDArray fourierNd () const;\n  OCTAVE_API ComplexNDArray ifourierNd () const;\n\n  ComplexNDArray squeeze () const { return MArray<Complex>::squeeze (); }\n\n  static OCTAVE_API void\n  increment_index (Array<octave_idx_type>& ra_idx,\n                   const dim_vector& dimensions,\n                   int start_dimension = 0);\n\n  static OCTAVE_API octave_idx_type\n  compute_index (Array<octave_idx_type>& ra_idx,\n                 const dim_vector& dimensions);\n\n  // i/o\n\n  friend OCTAVE_API std::ostream& operator << (std::ostream& os,\n                                               const ComplexNDArray& a);\n  friend OCTAVE_API std::istream& operator >> (std::istream& is,\n                                               ComplexNDArray& a);\n\n  //  bool all_elements_are_real () const;\n  //  bool all_integers (double& max_val, double& min_val) const;\n\n  OCTAVE_API ComplexNDArray diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API ComplexNDArray diag (octave_idx_type m, octave_idx_type n) const;\n\n  ComplexNDArray& changesign ()\n  {\n    MArray<Complex>::changesign ();\n    return *this;\n  }\n\n};\n\nextern OCTAVE_API ComplexNDArray conj (const ComplexNDArray& a);\n\nMINMAX_DECLS (ComplexNDArray, Complex, OCTAVE_API)\n\nNDS_CMP_OP_DECLS (ComplexNDArray, Complex, OCTAVE_API)\nNDS_BOOL_OP_DECLS (ComplexNDArray, Complex, OCTAVE_API)\n\nSND_CMP_OP_DECLS (Complex, ComplexNDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (Complex, ComplexNDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (ComplexNDArray, ComplexNDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (ComplexNDArray, ComplexNDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, ComplexNDArray, Complex)\n\nextern OCTAVE_API ComplexNDArray& operator *= (ComplexNDArray& a, double s);\nextern OCTAVE_API ComplexNDArray& operator /= (ComplexNDArray& a, double s);\n\nBSXFUN_STDOP_DECLS (ComplexNDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (ComplexNDArray, OCTAVE_API)\n\nBSXFUN_OP_DECL (pow, ComplexNDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/CRowVector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n#include <type_traits>\n\n#include \"Array-util.h\"\n#include \"blas-proto.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// Complex Row Vector class\n\nbool\nComplexRowVector::operator == (const ComplexRowVector& a) const\n{\n  octave_idx_type len = numel ();\n  if (len != a.numel ())\n    return 0;\n  return mx_inline_equal (len, data (), a.data ());\n}\n\nbool\nComplexRowVector::operator != (const ComplexRowVector& a) const\n{\n  return !(*this == a);\n}\n\n// destructive insert/delete/reorder operations\n\nComplexRowVector&\nComplexRowVector::insert (const RowVector& a, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (c < 0 || c + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nComplexRowVector&\nComplexRowVector::insert (const ComplexRowVector& a, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (c < 0 || c + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nComplexRowVector&\nComplexRowVector::fill (double val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nComplexRowVector&\nComplexRowVector::fill (const Complex& val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nComplexRowVector&\nComplexRowVector::fill (double val, octave_idx_type c1, octave_idx_type c2)\n{\n  octave_idx_type len = numel ();\n\n  if (c1 < 0 || c2 < 0 || c1 >= len || c2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = c1; i <= c2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nComplexRowVector&\nComplexRowVector::fill (const Complex& val,\n                        octave_idx_type c1, octave_idx_type c2)\n{\n  octave_idx_type len = numel ();\n\n  if (c1 < 0 || c2 < 0 || c1 >= len || c2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = c1; i <= c2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nComplexRowVector\nComplexRowVector::append (const RowVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nc_insert = len;\n  ComplexRowVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nc_insert);\n  return retval;\n}\n\nComplexRowVector\nComplexRowVector::append (const ComplexRowVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nc_insert = len;\n  ComplexRowVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nc_insert);\n  return retval;\n}\n\nComplexColumnVector\nComplexRowVector::hermitian () const\n{\n  return MArray<Complex>::hermitian (std::conj);\n}\n\nComplexColumnVector\nComplexRowVector::transpose () const\n{\n  return MArray<Complex>::transpose ();\n}\n\nComplexRowVector\nconj (const ComplexRowVector& a)\n{\n  return do_mx_unary_map<Complex, Complex, std::conj<double>> (a);\n}\n\n// resize is the destructive equivalent for this one\n\nComplexRowVector\nComplexRowVector::extract (octave_idx_type c1, octave_idx_type c2) const\n{\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  ComplexRowVector result (new_c);\n\n  for (octave_idx_type i = 0; i < new_c; i++)\n    result.elem (i) = elem (c1+i);\n\n  return result;\n}\n\nComplexRowVector\nComplexRowVector::extract_n (octave_idx_type r1, octave_idx_type n) const\n{\n  ComplexRowVector result (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    result.elem (i) = elem (r1+i);\n\n  return result;\n}\n\n// row vector by row vector -> row vector operations\n\nComplexRowVector&\nComplexRowVector::operator += (const RowVector& a)\n{\n  octave_idx_type len = numel ();\n\n  octave_idx_type a_len = a.numel ();\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator +=\", len, a_len);\n\n  if (len == 0)\n    return *this;\n\n  Complex *d = rwdata (); // Ensures only one reference to my privates!\n\n  mx_inline_add2 (len, d, a.data ());\n  return *this;\n}\n\nComplexRowVector&\nComplexRowVector::operator -= (const RowVector& a)\n{\n  octave_idx_type len = numel ();\n\n  octave_idx_type a_len = a.numel ();\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator -=\", len, a_len);\n\n  if (len == 0)\n    return *this;\n\n  Complex *d = rwdata (); // Ensures only one reference to my privates!\n\n  mx_inline_sub2 (len, d, a.data ());\n  return *this;\n}\n\n// row vector by matrix -> row vector\n\nComplexRowVector\noperator * (const ComplexRowVector& v, const ComplexMatrix& a)\n{\n  ComplexRowVector retval;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  F77_INT a_nr = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (a_nr != len)\n    octave::err_nonconformant (\"operator *\", 1, len, a_nr, a_nc);\n\n  if (len == 0)\n    retval.resize (a_nc, 0.0);\n  else\n    {\n      // Transpose A to form A'*x == (x'*A)'\n\n      F77_INT ld = a_nr;\n\n      retval.resize (a_nc);\n      Complex *y = retval.rwdata ();\n\n      F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 (\"T\", 1),\n                               a_nr, a_nc, 1.0, F77_CONST_DBLE_CMPLX_ARG (a.data ()),\n                               ld, F77_CONST_DBLE_CMPLX_ARG (v.data ()), 1, 0.0, F77_DBLE_CMPLX_ARG (y), 1\n                               F77_CHAR_ARG_LEN (1)));\n    }\n\n  return retval;\n}\n\nComplexRowVector\noperator * (const RowVector& v, const ComplexMatrix& a)\n{\n  ComplexRowVector tmp (v);\n  return tmp * a;\n}\n\n// other operations\n\nComplex\nComplexRowVector::min () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return Complex (0.0);\n\n  Complex res = elem (0);\n  double absres = std::abs (res);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (std::abs (elem (i)) < absres)\n      {\n        res = elem (i);\n        absres = std::abs (res);\n      }\n\n  return res;\n}\n\nComplex\nComplexRowVector::max () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return Complex (0.0);\n\n  Complex res = elem (0);\n  double absres = std::abs (res);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (std::abs (elem (i)) > absres)\n      {\n        res = elem (i);\n        absres = std::abs (res);\n      }\n\n  return res;\n}\n\n// i/o\n\nstd::ostream&\noperator << (std::ostream& os, const ComplexRowVector& a)\n{\n//  int field_width = os.precision () + 7;\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    os << ' ' /* setw (field_width) */ << a.elem (i);\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, ComplexRowVector& a)\n{\n  octave_idx_type len = a.numel ();\n\n  if (len > 0)\n    {\n      Complex tmp;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          is >> tmp;\n          if (is)\n            a.elem (i) = tmp;\n          else\n            break;\n        }\n    }\n  return is;\n}\n\n// row vector by column vector -> scalar\n\n// row vector by column vector -> scalar\n\nComplex\noperator * (const ComplexRowVector& v, const ColumnVector& a)\n{\n  ComplexColumnVector tmp (a);\n  return v * tmp;\n}\n\nComplex\noperator * (const ComplexRowVector& v, const ComplexColumnVector& a)\n{\n  Complex retval (0.0, 0.0);\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator *\", len, a_len);\n  if (len != 0)\n    F77_FUNC (xzdotu, XZDOTU) (len, F77_CONST_DBLE_CMPLX_ARG (v.data ()), 1,\n                               F77_CONST_DBLE_CMPLX_ARG (a.data ()), 1, F77_DBLE_CMPLX_ARG (&retval));\n\n  return retval;\n}\n\n// other operations\n\nComplexRowVector\nlinspace (const Complex& x1, const Complex& x2, octave_idx_type n_in)\n{\n  ComplexRowVector retval;\n\n  if (n_in < 1)\n    return retval;\n  else if (n_in == 1)\n    {\n      retval.resize (1, x2);\n      return retval;\n    }\n  else if (x1 == x2)\n    {\n      retval.resize (n_in, x2);\n      return retval;\n    }\n\n  // Use unsigned type (guaranteed n_in > 1 at this point) so that divisions\n  // by 2 can be replaced by compiler with shift right instructions.\n  typedef std::make_unsigned<octave_idx_type>::type unsigned_octave_idx_type;\n\n  unsigned_octave_idx_type n = n_in;\n\n  // Set endpoints, rather than calculate, for maximum accuracy.\n  retval.clear (n);\n  retval.xelem (0) = x1;\n  retval.xelem (n-1) = x2;\n\n  // Construct linspace symmetrically from both ends.\n  bool isnan_delta = false;\n  Complex delta = (x2 - x1) / (n - 1.0);\n  if (octave::math::isinf (delta))\n    {\n      if (octave::math::isinf (delta.real ()))\n        delta.real (octave::numeric_limits<double>::NaN ());\n      if (octave::math::isinf (delta.imag ()))\n        delta.imag (octave::numeric_limits<double>::NaN ());\n      isnan_delta = true;\n    }\n\n  unsigned_octave_idx_type n2 = n/2;\n  for (unsigned_octave_idx_type i = 1; i < n2; i++)\n    {\n      retval.xelem (i) = x1 + static_cast<double> (i)*delta;\n      retval.xelem (n-1-i) = x2 - static_cast<double> (i)*delta;\n    }\n  if (n % 2 == 1)  // Middle element if number of elements is odd.\n    {\n      if (x1 == -x2)\n        retval.xelem (n2) = 0;\n      else\n        {\n          Complex c = (x1 + x2) / 2.0;\n          if (isnan_delta)\n            {\n              if (octave::math::isnan (delta.real ()))\n                c.real (octave::numeric_limits<double>::NaN ());\n              if (octave::math::isnan (delta.imag ()))\n                c.imag (octave::numeric_limits<double>::NaN ());\n            }\n          retval.xelem (n2) = c;\n        }\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/array/CRowVector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_CRowVector_h)\n#define octave_CRowVector_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"dRowVector.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API ComplexRowVector : public MArray<Complex>\n{\n  friend class ComplexColumnVector;\n\npublic:\n\n  ComplexRowVector () : MArray<Complex> (dim_vector (1, 0)) { }\n\n  explicit ComplexRowVector (octave_idx_type n)\n    : MArray<Complex> (dim_vector (1, n)) { }\n\n  explicit ComplexRowVector (const dim_vector& dv) : MArray<Complex> (dv) { }\n\n  ComplexRowVector (octave_idx_type n, const Complex& val)\n    : MArray<Complex> (dim_vector (1, n), val) { }\n\n  ComplexRowVector (const ComplexRowVector& a) : MArray<Complex> (a) { }\n\n  ComplexRowVector (const MArray<Complex>& a)\n    : MArray<Complex> (a.as_row ()) { }\n\n  ComplexRowVector (const Array<Complex>& a)\n    : MArray<Complex> (a.as_row ()) { }\n\n  explicit ComplexRowVector (const RowVector& a) : MArray<Complex> (a) { }\n\n  ComplexRowVector& operator = (const ComplexRowVector& a)\n  {\n    MArray<Complex>::operator = (a);\n    return *this;\n  }\n\n  ~ComplexRowVector () = default;\n\n  OCTAVE_API bool operator == (const ComplexRowVector& a) const;\n  OCTAVE_API bool operator != (const ComplexRowVector& a) const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API ComplexRowVector&\n  insert (const RowVector& a, octave_idx_type c);\n  OCTAVE_API ComplexRowVector&\n  insert (const ComplexRowVector& a, octave_idx_type c);\n\n  OCTAVE_API ComplexRowVector& fill (double val);\n  OCTAVE_API ComplexRowVector& fill (const Complex& val);\n  OCTAVE_API ComplexRowVector&\n  fill (double val, octave_idx_type c1, octave_idx_type c2);\n  OCTAVE_API ComplexRowVector&\n  fill (const Complex& val, octave_idx_type c1, octave_idx_type c2);\n\n  OCTAVE_API ComplexRowVector append (const RowVector& a) const;\n  OCTAVE_API ComplexRowVector append (const ComplexRowVector& a) const;\n\n  OCTAVE_API ComplexColumnVector hermitian () const;\n  OCTAVE_API ComplexColumnVector transpose () const;\n\n  friend OCTAVE_API ComplexRowVector conj (const ComplexRowVector& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API ComplexRowVector\n  extract (octave_idx_type c1, octave_idx_type c2) const;\n\n  OCTAVE_API ComplexRowVector\n  extract_n (octave_idx_type c1, octave_idx_type n) const;\n\n  // row vector by row vector -> row vector operations\n\n  OCTAVE_API ComplexRowVector& operator += (const RowVector& a);\n  OCTAVE_API ComplexRowVector& operator -= (const RowVector& a);\n\n  // row vector by matrix -> row vector\n\n  friend OCTAVE_API ComplexRowVector\n  operator * (const ComplexRowVector& a, const ComplexMatrix& b);\n\n  friend OCTAVE_API ComplexRowVector\n  operator * (const RowVector& a, const ComplexMatrix& b);\n\n  // other operations\n\n  OCTAVE_API Complex min () const;\n  OCTAVE_API Complex max () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const ComplexRowVector& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, ComplexRowVector& a);\n\n  void resize (octave_idx_type n, const Complex& rfv = Complex (0))\n  {\n    Array<Complex>::resize (dim_vector (1, n), rfv);\n  }\n\n  void clear (octave_idx_type n)\n  { Array<Complex>::clear (1, n); }\n\n};\n\n// row vector by column vector -> scalar\n\nOCTAVE_API Complex operator * (const ComplexRowVector& a,\n                               const ColumnVector& b);\n\nOCTAVE_API Complex operator * (const ComplexRowVector& a,\n                               const ComplexColumnVector& b);\n\n// other operations\n\nOCTAVE_API ComplexRowVector linspace (const Complex& x1, const Complex& x2,\n                                      octave_idx_type n);\n\nMARRAY_FORWARD_DEFS (MArray, ComplexRowVector, Complex)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/CSparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <complex>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"dRowVector.h\"\n#include \"f77-fcn.h\"\n#include \"lapack-proto.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"mx-cm-s.h\"\n#include \"mx-cs-m.h\"\n#include \"mx-fcm-fs.h\"\n#include \"mx-fs-fcm.h\"\n#include \"mx-m-cs.h\"\n#include \"mx-s-cm.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"quit.h\"\n\n#include \"dDiagMatrix.h\"\n#include \"CDiagMatrix.h\"\n#include \"CSparse.h\"\n#include \"boolSparse.h\"\n#include \"dSparse.h\"\n#include \"oct-spparms.h\"\n#include \"sparse-lu.h\"\n#include \"oct-sparse.h\"\n#include \"sparse-util.h\"\n#include \"sparse-chol.h\"\n#include \"sparse-qr.h\"\n\n#include \"Sparse-op-defs.h\"\n\n#include \"Sparse-diag-op-defs.h\"\n\n#include \"Sparse-perm-op-defs.h\"\n\n#include \"sparse-dmsolve.h\"\n\nSparseComplexMatrix::SparseComplexMatrix (const SparseMatrix& a)\n  : MSparse<Complex> (a)\n{ }\n\nSparseComplexMatrix::SparseComplexMatrix (const SparseBoolMatrix& a)\n  : MSparse<Complex> (a.rows (), a.cols (), a.nnz ())\n{\n  octave_idx_type nc = cols ();\n  octave_idx_type nz = a.nnz ();\n\n  for (octave_idx_type i = 0; i < nc + 1; i++)\n    cidx (i) = a.cidx (i);\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    {\n      data (i) = Complex (a.data (i));\n      ridx (i) = a.ridx (i);\n    }\n}\n\nSparseComplexMatrix::SparseComplexMatrix (const ComplexDiagMatrix& a)\n  : MSparse<Complex> (a.rows (), a.cols (), a.length ())\n{\n  octave_idx_type j = 0;\n  octave_idx_type l = a.length ();\n  for (octave_idx_type i = 0; i < l; i++)\n    {\n      cidx (i) = j;\n      if (a(i, i) != 0.0)\n        {\n          data (j) = a(i, i);\n          ridx (j) = i;\n          j++;\n        }\n    }\n  for (octave_idx_type i = l; i <= a.cols (); i++)\n    cidx (i) = j;\n}\nbool\nSparseComplexMatrix::operator == (const SparseComplexMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz = nnz ();\n  octave_idx_type nr_a = a.rows ();\n  octave_idx_type nc_a = a.cols ();\n  octave_idx_type nz_a = a.nnz ();\n\n  if (nr != nr_a || nc != nc_a || nz != nz_a)\n    return false;\n\n  for (octave_idx_type i = 0; i < nc + 1; i++)\n    if (cidx (i) != a.cidx (i))\n      return false;\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    if (data (i) != a.data (i) || ridx (i) != a.ridx (i))\n      return false;\n\n  return true;\n}\n\nbool\nSparseComplexMatrix::operator != (const SparseComplexMatrix& a) const\n{\n  return !(*this == a);\n}\n\nbool\nSparseComplexMatrix::ishermitian () const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr == nc && nr > 0)\n    {\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n            {\n              octave_idx_type ri = ridx (i);\n\n              if (ri != j)\n                {\n                  bool found = false;\n\n                  for (octave_idx_type k = cidx (ri); k < cidx (ri+1); k++)\n                    {\n                      if (ridx (k) == j)\n                        {\n                          if (data (i) == conj (data (k)))\n                            found = true;\n                          break;\n                        }\n                    }\n\n                  if (! found)\n                    return false;\n                }\n            }\n        }\n\n      return true;\n    }\n\n  return false;\n}\n\nstatic const Complex\nComplex_NaN_result (octave::numeric_limits<double>::NaN (),\n                    octave::numeric_limits<double>::NaN ());\n\nSparseComplexMatrix\nSparseComplexMatrix::max (int dim, bool nanflag, bool realabs) const\n{\n  Array<octave_idx_type> dummy_idx;\n  return max (dummy_idx, dim, nanflag, realabs);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::max (Array<octave_idx_type>& idx_arg, int dim,\n                          bool nanflag, bool realabs) const\n{\n  SparseComplexMatrix result;\n  const dim_vector& dv = dims ();\n  octave_idx_type nr = dv(0);\n  octave_idx_type nc = dv(1);\n\n  if (dim >= dv.ndims ())\n    {\n      idx_arg.resize (dim_vector (nr, nc), 0);\n      return *this;\n    }\n\n  if (dim < 0)\n    dim = dv.first_non_singleton ();\n\n  if (dim == 0)\n    {\n      idx_arg.resize (dim_vector (nr == 0 ? 0 : 1, nc), 0);\n\n      if (nr == 0 || nc == 0 || dim >= dv.ndims ())\n        return SparseComplexMatrix (nr == 0 ? 0 : 1, nc);\n\n      octave_idx_type nel = 0;\n      if (realabs)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              Complex tmp_max;\n              double real_max = octave::numeric_limits<double>::NaN ();\n              double imag_max = octave::numeric_limits<double>::NaN ();\n              //double neg_inf = std::numeric_limits<double>::infinity () * -1;\n              octave_idx_type idx_j = 0;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  if (ridx (i) != idx_j)\n                    break;\n                  else\n                    idx_j++;\n                }\n\n              if (idx_j != nr)\n                {\n                  real_max = 0.;\n                  imag_max = 0.;\n                }\n\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  Complex tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n\n                  double real_tmp = tmp.real ();\n                  double imag_tmp = tmp.imag ();\n\n                  if (octave::math::isnan (real_max) || real_tmp > real_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      real_max = real_tmp;\n                      imag_max = imag_tmp;\n                    }\n                  else if (real_tmp == real_max && imag_tmp > imag_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      real_max = real_tmp;\n                      imag_max = imag_tmp;\n                    }\n                }\n\n              if (octave::math::isnan (tmp_max) && ! nanflag)\n                idx_arg.elem (j) = idx_j;\n              else\n                idx_arg.elem (j) = (octave::math::isnan (tmp_max) ? 0 : idx_j);\n              if (real_max != 0. || imag_max != 0.)\n                nel++;\n            }\n        }\n      else\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              Complex tmp_max;\n              double abs_max = octave::numeric_limits<double>::NaN ();\n              double arg_max = octave::numeric_limits<double>::NaN ();\n              octave_idx_type idx_j = 0;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  if (ridx (i) != idx_j)\n                    break;\n                  else\n                    idx_j++;\n                }\n\n              if (idx_j != nr)\n                {\n                  abs_max = 0.;\n                  arg_max = 0.; //-3.141592653589793238463;\n                }\n\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  Complex tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n\n                  double abs_tmp = std::abs (tmp);\n                  double arg_tmp = std::arg (tmp);\n\n                  if (octave::math::isnan (abs_max) || abs_tmp > abs_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      abs_max = abs_tmp;\n                      arg_max = arg_tmp;\n                    }\n                  else if (abs_tmp == abs_max && arg_tmp > arg_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      abs_max = abs_tmp;\n                      arg_max = arg_tmp;\n                    }\n                }\n\n              if (octave::math::isnan (tmp_max) && ! nanflag)\n                idx_arg.elem (j) = idx_j;\n              else\n                idx_arg.elem (j) = (octave::math::isnan (tmp_max) ? 0 : idx_j);\n              if (abs_max != 0. || arg_max != 0.)\n                nel++;\n            }\n        }\n\n      result = SparseComplexMatrix (1, nc, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          Complex tmp = elem (idx_arg(j), j);\n          if (tmp != 0.)\n            {\n              result.xdata (ii) = tmp;\n              result.xridx (ii++) = 0;\n            }\n          result.xcidx (j+1) = ii;\n        }\n    }\n  else\n    {\n      idx_arg.resize (dim_vector (nr, nc == 0 ? 0 : 1), 0);\n\n      if (nr == 0 || nc == 0 || dim >= dv.ndims ())\n        return SparseComplexMatrix (nr, nc == 0 ? 0 : 1);\n\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, found, nr);\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        found[i] = 0;\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n          if (found[ridx (i)] == -j)\n            found[ridx (i)] = -j - 1;\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        if (found[i] > -nc && found[i] < 0)\n          idx_arg.elem (i) = -found[i];\n\n      if (realabs)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  octave_idx_type ir = ridx (i);\n                  octave_idx_type ix = idx_arg.elem (ir);\n                  Complex tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_arg.elem (ir) = j;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (ix == -1 || octave::math::isnan (elem (ir, ix)) ||\n                           tmp.real () > elem (ir, ix).real ())\n                    idx_arg.elem (ir) = j;\n                  else if (tmp.real () == elem (ir, ix).real () &&\n                           tmp.imag () > elem (ir, ix).imag ())\n                    idx_arg.elem (ir) = j;\n                }\n            }\n        }\n      else\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  octave_idx_type ir = ridx (i);\n                  octave_idx_type ix = idx_arg.elem (ir);\n                  Complex tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_arg.elem (ir) = j;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (ix == -1 || octave::math::isnan (elem (ir, ix)) ||\n                           std::abs (tmp) > std::abs (elem (ir, ix)))\n                    idx_arg.elem (ir) = j;\n                  else if (std::abs (tmp) == std::abs (elem (ir, ix)) &&\n                           std::arg (tmp) > std::arg (elem (ir, ix)))\n                    idx_arg.elem (ir) = j;\n                }\n            }\n        }\n\n      octave_idx_type nel = 0;\n      for (octave_idx_type j = 0; j < nr; j++)\n        if (idx_arg.elem (j) == -1 || elem (j, idx_arg.elem (j)) != 0.)\n          nel++;\n\n      result = SparseComplexMatrix (nr, 1, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      result.xcidx (1) = nel;\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          if (idx_arg(j) == -1)\n            {\n              idx_arg(j) = 0;\n              result.xdata (ii) = Complex_NaN_result;\n              result.xridx (ii++) = j;\n            }\n          else\n            {\n              Complex tmp = elem (j, idx_arg(j));\n              if (tmp != 0.)\n                {\n                  result.xdata (ii) = tmp;\n                  result.xridx (ii++) = j;\n                }\n            }\n        }\n    }\n\n  return result;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::min (int dim, bool nanflag, bool realabs) const\n{\n  Array<octave_idx_type> dummy_idx;\n  return min (dummy_idx, dim, nanflag, realabs);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::min (Array<octave_idx_type>& idx_arg, int dim,\n                          bool nanflag, bool realabs) const\n{\n  SparseComplexMatrix result;\n  const dim_vector& dv = dims ();\n  octave_idx_type nr = dv(0);\n  octave_idx_type nc = dv(1);\n\n  if (dim >= dv.ndims ())\n    {\n      idx_arg.resize (dim_vector (nr, nc), 0);\n      return *this;\n    }\n\n  if (dim < 0)\n    dim = dv.first_non_singleton ();\n\n  if (dim == 0)\n    {\n      idx_arg.resize (dim_vector (nr == 0 ? 0 : 1, nc), 0);\n\n      if (nr == 0 || nc == 0 || dim >= dv.ndims ())\n        return SparseComplexMatrix (nr == 0 ? 0 : 1, nc);\n\n      octave_idx_type nel = 0;\n      if (realabs)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              Complex tmp_min;\n              double real_min = octave::numeric_limits<double>::NaN ();\n              double imag_min = octave::numeric_limits<double>::NaN ();\n              //double pos_inf = std::numeric_limits<double>::infinity ();\n              octave_idx_type idx_j = 0;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  if (ridx (i) != idx_j)\n                    break;\n                  else\n                    idx_j++;\n                }\n\n              if (idx_j != nr)\n                {\n                  real_min = 0.;\n                  imag_min = 0.;\n                }\n\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  Complex tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_j = ridx (i);\n                      tmp_min = tmp;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n\n                  double real_tmp = tmp.real ();\n                  double imag_tmp = tmp.imag ();\n\n                  if (octave::math::isnan (real_min) || real_tmp < real_min)\n                    {\n                      idx_j = ridx (i);\n                      tmp_min = tmp;\n                      real_min = real_tmp;\n                      imag_min = imag_tmp;\n                    }\n                  else if (real_tmp == real_min && imag_tmp < imag_min)\n                    {\n                      idx_j = ridx (i);\n                      tmp_min = tmp;\n                      real_min = real_tmp;\n                      imag_min = imag_tmp;\n                    }\n                }\n\n              if (octave::math::isnan (tmp_min) && ! nanflag)\n                idx_arg.elem (j) = idx_j;\n              else\n                idx_arg.elem (j) = (octave::math::isnan (tmp_min) ? 0 : idx_j);\n              if (real_min != 0. || imag_min != 0.)\n                nel++;\n            }\n        }\n      else\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              Complex tmp_min;\n              double abs_min = octave::numeric_limits<double>::NaN ();\n              double arg_min = octave::numeric_limits<double>::NaN ();\n              //double pos_inf = std::numeric_limits<double>::infinity ();\n              octave_idx_type idx_j = 0;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  if (ridx (i) != idx_j)\n                    break;\n                  else\n                    idx_j++;\n                }\n\n              if (idx_j != nr)\n                {\n                  abs_min = 0.;\n                  arg_min = 0.; //3.141592653589793238463;\n                }\n\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  Complex tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_j = ridx (i);\n                      tmp_min = tmp;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n\n                  double abs_tmp = std::abs (tmp);\n                  double arg_tmp = std::arg (tmp);\n\n                  if (octave::math::isnan (abs_min) || abs_tmp < abs_min)\n                    {\n                      idx_j = ridx (i);\n                      tmp_min = tmp;\n                      abs_min = abs_tmp;\n                      arg_min = arg_tmp;\n                    }\n                  else if (abs_tmp == abs_min && arg_tmp < arg_min)\n                    {\n                      idx_j = ridx (i);\n                      tmp_min = tmp;\n                      abs_min = abs_tmp;\n                      arg_min = arg_tmp;\n                    }\n                }\n\n              if (octave::math::isnan (tmp_min) && ! nanflag)\n                idx_arg.elem (j) = idx_j;\n              else\n                idx_arg.elem (j) = (octave::math::isnan (tmp_min) ? 0 : idx_j);\n              if (abs_min != 0. || arg_min != 0.)\n                nel++;\n            }\n        }\n\n      result = SparseComplexMatrix (1, nc, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          Complex tmp = elem (idx_arg(j), j);\n          if (tmp != 0.)\n            {\n              result.xdata (ii) = tmp;\n              result.xridx (ii++) = 0;\n            }\n          result.xcidx (j+1) = ii;\n        }\n    }\n  else\n    {\n      idx_arg.resize (dim_vector (nr, nc == 0 ? 0 : 1), 0);\n\n      if (nr == 0 || nc == 0 || dim >= dv.ndims ())\n        return SparseComplexMatrix (nr, nc == 0 ? 0 : 1);\n\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, found, nr);\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        found[i] = 0;\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n          if (found[ridx (i)] == -j)\n            found[ridx (i)] = -j - 1;\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        if (found[i] > -nc && found[i] < 0)\n          idx_arg.elem (i) = -found[i];\n\n      if (realabs)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  octave_idx_type ir = ridx (i);\n                  octave_idx_type ix = idx_arg.elem (ir);\n                  Complex tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_arg.elem (ir) = j;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (ix == -1 || octave::math::isnan (elem (ir, ix)) ||\n                           tmp.real () < elem (ir, ix).real ())\n                    idx_arg.elem (ir) = j;\n                  else if (tmp.real () == elem (ir, ix).real () &&\n                           tmp.imag () < elem (ir, ix).imag ())\n                    idx_arg.elem (ir) = j;\n                }\n            }\n        }\n      else\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  octave_idx_type ir = ridx (i);\n                  octave_idx_type ix = idx_arg.elem (ir);\n                  Complex tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_arg.elem (ir) = j;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (ix == -1 || octave::math::isnan (elem (ir, ix)) ||\n                           std::abs (tmp) < std::abs (elem (ir, ix)))\n                    idx_arg.elem (ir) = j;\n                  else if (std::abs (tmp) == std::abs (elem (ir, ix)) &&\n                           std::arg (tmp) < std::arg (elem (ir, ix)))\n                    idx_arg.elem (ir) = j;\n                }\n            }\n        }\n\n      octave_idx_type nel = 0;\n      for (octave_idx_type j = 0; j < nr; j++)\n        if (idx_arg.elem (j) == -1 || elem (j, idx_arg.elem (j)) != 0.)\n          nel++;\n\n      result = SparseComplexMatrix (nr, 1, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      result.xcidx (1) = nel;\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          if (idx_arg(j) == -1)\n            {\n              idx_arg(j) = 0;\n              result.xdata (ii) = Complex_NaN_result;\n              result.xridx (ii++) = j;\n            }\n          else\n            {\n              Complex tmp = elem (j, idx_arg(j));\n              if (tmp != 0.)\n                {\n                  result.xdata (ii) = tmp;\n                  result.xridx (ii++) = j;\n                }\n            }\n        }\n    }\n\n  return result;\n}\n\n/*\n\n%!assert (max (max (speye (65536) * 1i)), sparse (1i))\n%!assert (min (min (speye (65536) * 1i)), sparse (0))\n%!assert (size (max (sparse (8, 0), [], 1)), [1, 0])\n%!assert (size (max (sparse (8, 0), [], 2)), [8, 0])\n%!assert (size (max (sparse (0, 8), [], 1)), [0, 8])\n%!assert (size (max (sparse (0, 8), [], 2)), [0, 1])\n%!assert (size (min (sparse (8, 0), [], 1)), [1, 0])\n%!assert (size (min (sparse (8, 0), [], 2)), [8, 0])\n%!assert (size (min (sparse (0, 8), [], 1)), [0, 8])\n%!assert (size (min (sparse (0, 8), [], 2)), [0, 1])\n\n*/\n\nComplexRowVector\nSparseComplexMatrix::row (octave_idx_type i) const\n{\n  octave_idx_type nc = columns ();\n  ComplexRowVector retval (nc, 0);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type k = cidx (j); k < cidx (j+1); k++)\n      {\n        if (ridx (k) == i)\n          {\n            retval(j) = data (k);\n            break;\n          }\n      }\n\n  return retval;\n}\n\nComplexColumnVector\nSparseComplexMatrix::column (octave_idx_type i) const\n{\n  octave_idx_type nr = rows ();\n  ComplexColumnVector retval (nr, 0);\n\n  for (octave_idx_type k = cidx (i); k < cidx (i+1); k++)\n    retval(ridx (k)) = data (k);\n\n  return retval;\n}\n\n// destructive insert/delete/reorder operations\n\nSparseComplexMatrix&\nSparseComplexMatrix::insert (const SparseMatrix& a,\n                             octave_idx_type r, octave_idx_type c)\n{\n  SparseComplexMatrix tmp (a);\n  return insert (tmp /*a*/, r, c);\n}\n\nSparseComplexMatrix&\nSparseComplexMatrix::insert (const SparseComplexMatrix& a,\n                             octave_idx_type r, octave_idx_type c)\n{\n  MSparse<Complex>::insert (a, r, c);\n  return *this;\n}\n\nSparseComplexMatrix&\nSparseComplexMatrix::insert (const SparseMatrix& a,\n                             const Array<octave_idx_type>& indx)\n{\n  SparseComplexMatrix tmp (a);\n  return insert (tmp /*a*/, indx);\n}\n\nSparseComplexMatrix&\nSparseComplexMatrix::insert (const SparseComplexMatrix& a,\n                             const Array<octave_idx_type>& indx)\n{\n  MSparse<Complex>::insert (a, indx);\n  return *this;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::concat (const SparseComplexMatrix& rb,\n                             const Array<octave_idx_type>& ra_idx)\n{\n  // Don't use numel to avoid all possibility of an overflow\n  if (rb.rows () > 0 && rb.cols () > 0)\n    insert (rb, ra_idx(0), ra_idx(1));\n  return *this;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::concat (const SparseMatrix& rb,\n                             const Array<octave_idx_type>& ra_idx)\n{\n  SparseComplexMatrix tmp (rb);\n  if (rb.rows () > 0 && rb.cols () > 0)\n    insert (tmp, ra_idx(0), ra_idx(1));\n  return *this;\n}\n\nComplexMatrix\nSparseComplexMatrix::matrix_value () const\n{\n  return Sparse<Complex>::array_value ();\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::hermitian () const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz = nnz ();\n  SparseComplexMatrix retval (nc, nr, nz);\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    retval.xcidx (ridx (i) + 1)++;\n  // retval.xcidx[1:nr] holds the row degrees for rows 0:(nr-1)\n  nz = 0;\n  for (octave_idx_type i = 1; i <= nr; i++)\n    {\n      const octave_idx_type tmp = retval.xcidx (i);\n      retval.xcidx (i) = nz;\n      nz += tmp;\n    }\n  // retval.xcidx[1:nr] holds row entry *start* offsets for rows 0:(nr-1)\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type k = cidx (j); k < cidx (j+1); k++)\n      {\n        octave_idx_type q = retval.xcidx (ridx (k) + 1)++;\n        retval.xridx (q) = j;\n        retval.xdata (q) = conj (data (k));\n      }\n  liboctave_panic_unless (nnz () == retval.xcidx (nr));\n  // retval.xcidx[1:nr] holds row entry *end* offsets for rows 0:(nr-1)\n  // and retval.xcidx[0:(nr-1)] holds their row entry *start* offsets\n\n  return retval;\n}\n\nSparseComplexMatrix\nconj (const SparseComplexMatrix& a)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n  octave_idx_type nz = a.nnz ();\n  SparseComplexMatrix retval (nc, nr, nz);\n\n  for (octave_idx_type i = 0; i < nc + 1; i++)\n    retval.cidx (i) = a.cidx (i);\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    {\n      retval.data (i) = conj (a.data (i));\n      retval.ridx (i) = a.ridx (i);\n    }\n\n  return retval;\n}\n\n// Local function to check if matrix is singular based on rcond.\nstatic inline\nbool\nis_singular (const double rcond)\n{\n  return (std::abs (rcond) <= std::numeric_limits<double>::epsilon ());\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::inverse () const\n{\n  octave_idx_type info;\n  double rcond;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcond, 0, 0);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::inverse (MatrixType& mattype) const\n{\n  octave_idx_type info;\n  double rcond;\n  return inverse (mattype, info, rcond, 0, 0);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const\n{\n  double rcond;\n  return inverse (mattype, info, rcond, 0, 0);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::dinverse (MatrixType& mattype, octave_idx_type& info,\n                               double& rcond, const bool,\n                               const bool calccond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  info = 0;\n\n  if (nr == 0 || nc == 0 || nr != nc)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  // Print spparms(\"spumoni\") info if requested\n  int typ = mattype.type ();\n  mattype.info ();\n\n  if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n    (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n  if (typ == MatrixType::Permuted_Diagonal)\n    retval = transpose ();\n  else\n    retval = *this;\n\n  // Force make_unique to be called\n  Complex *v = retval.data ();\n\n  if (calccond)\n    {\n      double dmax = 0.;\n      double dmin = octave::numeric_limits<double>::Inf ();\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          double tmp = std::abs (v[i]);\n          if (tmp > dmax)\n            dmax = tmp;\n          if (tmp < dmin)\n            dmin = tmp;\n        }\n      rcond = dmin / dmax;\n    }\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    v[i] = 1.0 / v[i];\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::tinverse (MatrixType& mattype, octave_idx_type& info,\n                               double& rcond, const bool,\n                               const bool calccond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  info = 0;\n\n  if (nr == 0 || nc == 0 || nr != nc)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  // Print spparms(\"spumoni\") info if requested\n  int typ = mattype.type ();\n  mattype.info ();\n\n  if (typ != MatrixType::Upper && typ != MatrixType::Permuted_Upper\n      && typ != MatrixType::Lower && typ != MatrixType::Permuted_Lower)\n    (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n  double anorm = 0.;\n  double ainvnorm = 0.;\n\n  if (calccond)\n    {\n      // Calculate the 1-norm of matrix for rcond calculation\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          double atmp = 0.;\n          for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n            atmp += std::abs (data (i));\n          if (atmp > anorm)\n            anorm = atmp;\n        }\n    }\n\n  if (typ == MatrixType::Upper || typ == MatrixType::Lower)\n    {\n      octave_idx_type nz = nnz ();\n      octave_idx_type cx = 0;\n      octave_idx_type nz2 = nz;\n      retval = SparseComplexMatrix (nr, nc, nz2);\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_quit ();\n          // place the 1 in the identity position\n          octave_idx_type cx_colstart = cx;\n\n          if (cx == nz2)\n            {\n              nz2 *= 2;\n              retval.change_capacity (nz2);\n            }\n\n          retval.xcidx (i) = cx;\n          retval.xridx (cx) = i;\n          retval.xdata (cx) = 1.0;\n          cx++;\n\n          // iterate across columns of input matrix\n          for (octave_idx_type j = i+1; j < nr; j++)\n            {\n              Complex v = 0.;\n              // iterate to calculate sum\n              octave_idx_type colXp = retval.xcidx (i);\n              octave_idx_type colUp = cidx (j);\n              octave_idx_type rpX, rpU;\n\n              if (cidx (j) == cidx (j+1))\n                (*current_liboctave_error_handler) (\"division by zero\");\n\n              do\n                {\n                  octave_quit ();\n                  rpX = retval.xridx (colXp);\n                  rpU = ridx (colUp);\n\n                  if (rpX < rpU)\n                    colXp++;\n                  else if (rpX > rpU)\n                    colUp++;\n                  else\n                    {\n                      v -= retval.xdata (colXp) * data (colUp);\n                      colXp++;\n                      colUp++;\n                    }\n                }\n              while (rpX < j && rpU < j && colXp < cx && colUp < nz);\n\n              // get A(m,m)\n              if (typ == MatrixType::Upper)\n                colUp = cidx (j+1) - 1;\n              else\n                colUp = cidx (j);\n              Complex pivot = data (colUp);\n              if (pivot == 0. || ridx (colUp) != j)\n                (*current_liboctave_error_handler) (\"division by zero\");\n\n              if (v != 0.)\n                {\n                  if (cx == nz2)\n                    {\n                      nz2 *= 2;\n                      retval.change_capacity (nz2);\n                    }\n\n                  retval.xridx (cx) = j;\n                  retval.xdata (cx) = v / pivot;\n                  cx++;\n                }\n            }\n\n          // get A(m,m)\n          octave_idx_type colUp;\n          if (typ == MatrixType::Upper)\n            colUp = cidx (i+1) - 1;\n          else\n            colUp = cidx (i);\n          Complex pivot = data (colUp);\n          if (pivot == 0. || ridx (colUp) != i)\n            (*current_liboctave_error_handler) (\"division by zero\");\n\n          if (pivot != 1.0)\n            for (octave_idx_type j = cx_colstart; j < cx; j++)\n              retval.xdata (j) /= pivot;\n        }\n      retval.xcidx (nr) = cx;\n      retval.maybe_compress ();\n    }\n  else\n    {\n      octave_idx_type nz = nnz ();\n      octave_idx_type cx = 0;\n      octave_idx_type nz2 = nz;\n      retval = SparseComplexMatrix (nr, nc, nz2);\n\n      OCTAVE_LOCAL_BUFFER (Complex, work, nr);\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nr);\n\n      octave_idx_type *perm = mattype.triangular_perm ();\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          for (octave_idx_type i = 0; i < nr; i++)\n            rperm[perm[i]] = i;\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < nr; i++)\n            rperm[i] = perm[i];\n          for (octave_idx_type i = 0; i < nr; i++)\n            perm[rperm[i]] = i;\n        }\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_quit ();\n          octave_idx_type iidx = rperm[i];\n\n          for (octave_idx_type j = 0; j < nr; j++)\n            work[j] = 0.;\n\n          // place the 1 in the identity position\n          work[iidx] = 1.0;\n\n          // iterate across columns of input matrix\n          for (octave_idx_type j = iidx+1; j < nr; j++)\n            {\n              Complex v = 0.;\n              octave_idx_type jidx = perm[j];\n              // iterate to calculate sum\n              for (octave_idx_type k = cidx (jidx);\n                   k < cidx (jidx+1); k++)\n                {\n                  octave_quit ();\n                  v -= work[ridx (k)] * data (k);\n                }\n\n              // get A(m,m)\n              Complex pivot;\n              if (typ == MatrixType::Permuted_Upper)\n                pivot = data (cidx (jidx+1) - 1);\n              else\n                pivot = data (cidx (jidx));\n              if (pivot == 0.)\n                (*current_liboctave_error_handler) (\"division by zero\");\n\n              work[j] = v / pivot;\n            }\n\n          // get A(m,m)\n          octave_idx_type colUp;\n          if (typ == MatrixType::Permuted_Upper)\n            colUp = cidx (perm[iidx]+1) - 1;\n          else\n            colUp = cidx (perm[iidx]);\n\n          Complex pivot = data (colUp);\n          if (pivot == 0.)\n            (*current_liboctave_error_handler) (\"division by zero\");\n\n          octave_idx_type new_cx = cx;\n          for (octave_idx_type j = iidx; j < nr; j++)\n            if (work[j] != 0.0)\n              {\n                new_cx++;\n                if (pivot != 1.0)\n                  work[j] /= pivot;\n              }\n\n          if (cx < new_cx)\n            {\n              nz2 = (2*nz2 < new_cx ? new_cx : 2*nz2);\n              retval.change_capacity (nz2);\n            }\n\n          retval.xcidx (i) = cx;\n          for (octave_idx_type j = iidx; j < nr; j++)\n            if (work[j] != 0.)\n              {\n                retval.xridx (cx) = j;\n                retval.xdata (cx++) = work[j];\n              }\n        }\n\n      retval.xcidx (nr) = cx;\n      retval.maybe_compress ();\n    }\n\n  if (calccond)\n    {\n      // Calculate the 1-norm of inverse matrix for rcond calculation\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          double atmp = 0.;\n          for (octave_idx_type i = retval.cidx (j);\n               i < retval.cidx (j+1); i++)\n            atmp += std::abs (retval.data (i));\n          if (atmp > ainvnorm)\n            ainvnorm = atmp;\n        }\n\n      rcond = 1. / ainvnorm / anorm;\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info,\n                              double& rcond, bool, bool calc_cond) const\n{\n  if (nnz () == 0)\n    {\n      (*current_liboctave_error_handler)\n        (\"inverse of the null matrix not defined\");\n    }\n\n  int typ = mattype.type (false);\n  SparseComplexMatrix ret;\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    ret = dinverse (mattype, info, rcond, true, calc_cond);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    ret = tinverse (mattype, info, rcond, true, calc_cond).transpose ();\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    {\n      MatrixType newtype = mattype.transpose ();\n      ret = transpose ().tinverse (newtype, info, rcond, true, calc_cond);\n    }\n  else\n    {\n      if (mattype.ishermitian ())\n        {\n          MatrixType tmp_typ (MatrixType::Upper);\n          octave::math::sparse_chol<SparseComplexMatrix> fact (*this, info, false);\n          rcond = fact.rcond ();\n          if (info == 0)\n            {\n              double rcond2;\n              SparseMatrix Q = fact.Q ();\n              SparseComplexMatrix InvL = fact.L ().transpose ().\n                                         tinverse (tmp_typ, info, rcond2,\n                                                   true, false);\n              ret = Q * InvL.hermitian () * InvL * Q.transpose ();\n            }\n          else\n            {\n              // Matrix is either singular or not positive definite\n              mattype.mark_as_unsymmetric ();\n            }\n        }\n\n      if (! mattype.ishermitian ())\n        {\n          octave_idx_type n = rows ();\n          ColumnVector Qinit(n);\n          for (octave_idx_type i = 0; i < n; i++)\n            Qinit(i) = i;\n\n          MatrixType tmp_typ (MatrixType::Upper);\n          octave::math::sparse_lu<SparseComplexMatrix> fact (*this,\n                                                             Qinit, Matrix (),\n                                                             false, false);\n          rcond = fact.rcond ();\n          if (rcond == 0.0)\n            {\n              // Return all Inf matrix with sparsity pattern of input.\n              octave_idx_type nz = nnz ();\n              ret = SparseComplexMatrix (rows (), cols (), nz);\n              std::fill (ret.xdata (), ret.xdata () + nz,\n                         octave::numeric_limits<double>::Inf ());\n              std::copy_n (ridx (), nz, ret.xridx ());\n              std::copy_n (cidx (), cols () + 1, ret.xcidx ());\n\n              return ret;\n            }\n          double rcond2;\n          SparseComplexMatrix InvL = fact.L ().transpose ().\n                                     tinverse (tmp_typ, info, rcond2,\n                                               true, false);\n          SparseComplexMatrix InvU = fact.U ().\n                                     tinverse (tmp_typ, info, rcond2,\n                                               true, false).transpose ();\n          ret = fact.Pc ().transpose () * InvU * InvL * fact.Pr ();\n        }\n    }\n\n  return ret;\n}\n\nComplexDET\nSparseComplexMatrix::determinant () const\n{\n  octave_idx_type info;\n  double rcond;\n  return determinant (info, rcond, 0);\n}\n\nComplexDET\nSparseComplexMatrix::determinant (octave_idx_type& info) const\n{\n  double rcond;\n  return determinant (info, rcond, 0);\n}\n\nComplexDET\nSparseComplexMatrix::determinant (octave_idx_type& err, double& rcond,\n                                  bool) const\n{\n  ComplexDET retval;\n\n#if defined (HAVE_UMFPACK)\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr == 0 || nc == 0 || nr != nc)\n    {\n      retval = ComplexDET (1.0);\n    }\n  else\n    {\n      err = 0;\n\n      // Setup the control parameters\n      Matrix Control (UMFPACK_CONTROL, 1);\n      double *control = Control.rwdata ();\n      UMFPACK_ZNAME (defaults) (control);\n\n      double tmp = octave::sparse_params::get_key (\"spumoni\");\n      if (! octave::math::isnan (tmp))\n        Control (UMFPACK_PRL) = tmp;\n\n      tmp = octave::sparse_params::get_key (\"piv_tol\");\n      if (! octave::math::isnan (tmp))\n        {\n          Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;\n          Control (UMFPACK_PIVOT_TOLERANCE) = tmp;\n        }\n\n      // Set whether we are allowed to modify Q or not\n      tmp = octave::sparse_params::get_key (\"autoamd\");\n      if (! octave::math::isnan (tmp))\n        Control (UMFPACK_FIXQ) = tmp;\n\n      // Turn-off UMFPACK scaling for LU\n      Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;\n\n      UMFPACK_ZNAME (report_control) (control);\n\n      const octave_idx_type *Ap = cidx ();\n      const octave_idx_type *Ai = ridx ();\n      const Complex *Ax = data ();\n\n      UMFPACK_ZNAME (report_matrix) (nr, nc,\n                                     octave::to_suitesparse_intptr (Ap),\n                                     octave::to_suitesparse_intptr (Ai),\n                                     reinterpret_cast<const double *> (Ax),\n                                     nullptr, 1, control);\n\n      void *Symbolic;\n      Matrix Info (1, UMFPACK_INFO);\n      double *info = Info.rwdata ();\n      int status = UMFPACK_ZNAME (qsymbolic) (nr, nc,\n                                              octave::to_suitesparse_intptr (Ap),\n                                              octave::to_suitesparse_intptr (Ai),\n                                              reinterpret_cast<const double *> (Ax),\n                                              nullptr, nullptr, &Symbolic, control, info);\n\n      if (status < 0)\n        {\n          UMFPACK_ZNAME (report_status) (control, status);\n          UMFPACK_ZNAME (report_info) (control, info);\n\n          UMFPACK_ZNAME (free_symbolic) (&Symbolic);\n\n          (*current_liboctave_error_handler)\n            (\"SparseComplexMatrix::determinant symbolic factorization failed\");\n        }\n      else\n        {\n          UMFPACK_ZNAME (report_symbolic) (Symbolic, control);\n\n          void *Numeric;\n          status\n            = UMFPACK_ZNAME (numeric) (octave::to_suitesparse_intptr (Ap),\n                                       octave::to_suitesparse_intptr (Ai),\n                                       reinterpret_cast<const double *> (Ax),\n                                       nullptr, Symbolic, &Numeric, control, info);\n          UMFPACK_ZNAME (free_symbolic) (&Symbolic);\n\n          rcond = Info (UMFPACK_RCOND);\n\n          if (status < 0)\n            {\n              UMFPACK_ZNAME (report_status) (control, status);\n              UMFPACK_ZNAME (report_info) (control, info);\n\n              UMFPACK_ZNAME (free_numeric) (&Numeric);\n\n              (*current_liboctave_error_handler)\n                (\"SparseComplexMatrix::determinant numeric factorization failed\");\n            }\n          else\n            {\n              UMFPACK_ZNAME (report_numeric) (Numeric, control);\n\n              double c10[2], e10;\n\n              status = UMFPACK_ZNAME (get_determinant) (c10, nullptr, &e10,\n                                                        Numeric, info);\n\n              if (status < 0)\n                {\n                  UMFPACK_ZNAME (report_status) (control, status);\n                  UMFPACK_ZNAME (report_info) (control, info);\n\n                  (*current_liboctave_error_handler)\n                    (\"SparseComplexMatrix::determinant error calculating determinant\");\n                }\n              else\n                retval = ComplexDET (Complex (c10[0], c10[1]), e10, 10);\n\n              UMFPACK_ZNAME (free_numeric) (&Numeric);\n            }\n        }\n    }\n\n#else\n\n  octave_unused_parameter (err);\n  octave_unused_parameter (rcond);\n\n  (*current_liboctave_error_handler)\n    (\"support for UMFPACK was unavailable or disabled when liboctave was built\");\n\n#endif\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::dsolve (MatrixType& mattype, const Matrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler, bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = (nc < nr ? nc : nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      retval.resize (nc, b.cols (), Complex (0., 0.));\n      if (typ == MatrixType::Diagonal)\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          for (octave_idx_type i = 0; i < nm; i++)\n            retval(i, j) = b(i, j) / data (i);\n      else\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          for (octave_idx_type k = 0; k < nc; k++)\n            for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n              retval(k, j) = b(ridx (i), j) / data (i);\n\n      if (calc_cond)\n        {\n          double dmax = 0.;\n          double dmin = octave::numeric_limits<double>::Inf ();\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              double tmp = std::abs (data (i));\n              if (tmp > dmax)\n                dmax = tmp;\n              if (tmp < dmin)\n                dmin = tmp;\n            }\n          rcond = dmin / dmax;\n        }\n      else\n        rcond = 1.0;\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::dsolve (MatrixType& mattype, const SparseMatrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler,\n                             bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = (nc < nr ? nc : nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseComplexMatrix (nc, b_nc, b_nz);\n\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      if (typ == MatrixType::Diagonal)\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          {\n            for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n              {\n                if (b.ridx (i) >= nm)\n                  break;\n                retval.xridx (ii) = b.ridx (i);\n                retval.xdata (ii++) = b.data (i) / data (b.ridx (i));\n              }\n            retval.xcidx (j+1) = ii;\n          }\n      else\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          {\n            for (octave_idx_type l = 0; l < nc; l++)\n              for (octave_idx_type i = cidx (l); i < cidx (l+1); i++)\n                {\n                  bool found = false;\n                  octave_idx_type k;\n                  for (k = b.cidx (j); k < b.cidx (j+1); k++)\n                    if (ridx (i) == b.ridx (k))\n                      {\n                        found = true;\n                        break;\n                      }\n                  if (found)\n                    {\n                      retval.xridx (ii) = l;\n                      retval.xdata (ii++) = b.data (k) / data (i);\n                    }\n                }\n            retval.xcidx (j+1) = ii;\n          }\n\n      if (calc_cond)\n        {\n          double dmax = 0.;\n          double dmin = octave::numeric_limits<double>::Inf ();\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              double tmp = std::abs (data (i));\n              if (tmp > dmax)\n                dmax = tmp;\n              if (tmp < dmin)\n                dmin = tmp;\n            }\n          rcond = dmin / dmax;\n        }\n      else\n        rcond = 1.0;\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::dsolve (MatrixType& mattype, const ComplexMatrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler,\n                             bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = (nc < nr ? nc : nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      retval.resize (nc, b.cols (), Complex (0., 0.));\n      if (typ == MatrixType::Diagonal)\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          for (octave_idx_type i = 0; i < nm; i++)\n            retval(i, j) = b(i, j) / data (i);\n      else\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          for (octave_idx_type k = 0; k < nc; k++)\n            for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n              retval(k, j) = b(ridx (i), j) / data (i);\n\n      if (calc_cond)\n        {\n          double dmax = 0.;\n          double dmin = octave::numeric_limits<double>::Inf ();\n          for (octave_idx_type i = 0; i < nr; i++)\n            {\n              double tmp = std::abs (data (i));\n              if (tmp > dmax)\n                dmax = tmp;\n              if (tmp < dmin)\n                dmin = tmp;\n            }\n          rcond = dmin / dmax;\n        }\n      else\n        rcond = 1.0;\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::dsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler,\n                             bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = (nc < nr ? nc : nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseComplexMatrix (nc, b_nc, b_nz);\n\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      if (typ == MatrixType::Diagonal)\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          {\n            for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n              {\n                if (b.ridx (i) >= nm)\n                  break;\n                retval.xridx (ii) = b.ridx (i);\n                retval.xdata (ii++) = b.data (i) / data (b.ridx (i));\n              }\n            retval.xcidx (j+1) = ii;\n          }\n      else\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          {\n            for (octave_idx_type l = 0; l < nc; l++)\n              for (octave_idx_type i = cidx (l); i < cidx (l+1); i++)\n                {\n                  bool found = false;\n                  octave_idx_type k;\n                  for (k = b.cidx (j); k < b.cidx (j+1); k++)\n                    if (ridx (i) == b.ridx (k))\n                      {\n                        found = true;\n                        break;\n                      }\n                  if (found)\n                    {\n                      retval.xridx (ii) = l;\n                      retval.xdata (ii++) = b.data (k) / data (i);\n                    }\n                }\n            retval.xcidx (j+1) = ii;\n          }\n\n      if (calc_cond)\n        {\n          double dmax = 0.;\n          double dmin = octave::numeric_limits<double>::Inf ();\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              double tmp = std::abs (data (i));\n              if (tmp > dmax)\n                dmax = tmp;\n              if (tmp < dmin)\n                dmin = tmp;\n            }\n          rcond = dmin / dmax;\n        }\n      else\n        rcond = 1.0;\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::utsolve (MatrixType& mattype, const Matrix& b,\n                              octave_idx_type& err, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      octave_idx_type b_nc = b.cols ();\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += std::abs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          retval.resize (nc, b_nc);\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  octave_idx_type kidx = perm[k];\n\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (kidx+1)-1) != k\n                          || data (cidx (kidx+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (kidx+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (kidx);\n                           i < cidx (kidx+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval(perm[i], j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      octave_idx_type iidx = perm[k];\n\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (iidx+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (iidx);\n                               i < cidx (iidx+1)-1; i++)\n                            {\n                              octave_idx_type idx2 = ridx (i);\n                              work[idx2] = work[idx2] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n          retval.resize (nc, b_nc);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k+1)-1) != k\n                          || data (cidx (k+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (k+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (i, j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (k+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1)-1; i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::utsolve (MatrixType& mattype, const SparseMatrix& b,\n                              octave_idx_type& err, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += std::abs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseComplexMatrix (nc, b_nc, b_nz);\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      octave_idx_type x_nz = b_nz;\n\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc);\n          for (octave_idx_type i = 0; i < nc; i++)\n            rperm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  octave_idx_type kidx = perm[k];\n\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (kidx+1)-1) != k\n                          || data (cidx (kidx+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (kidx+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (kidx);\n                           i < cidx (kidx+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[rperm[i]] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[rperm[i]];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      octave_idx_type iidx = perm[k];\n\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (iidx+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (iidx);\n                               i < cidx (iidx+1)-1; i++)\n                            {\n                              octave_idx_type idx2 = ridx (i);\n                              work[idx2] = work[idx2] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k+1)-1) != k\n                          || data (cidx (k+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (k+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (k+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1)-1; i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::utsolve (MatrixType& mattype, const ComplexMatrix& b,\n                              octave_idx_type& err, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      octave_idx_type b_nc = b.cols ();\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += std::abs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          retval.resize (nc, b_nc);\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  octave_idx_type kidx = perm[k];\n\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (kidx+1)-1) != k\n                          || data (cidx (kidx+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (kidx+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (kidx);\n                           i < cidx (kidx+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval(perm[i], j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      octave_idx_type iidx = perm[k];\n\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (iidx+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (iidx);\n                               i < cidx (iidx+1)-1; i++)\n                            {\n                              octave_idx_type idx2 = ridx (i);\n                              work[idx2] = work[idx2] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n          retval.resize (nc, b_nc);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k+1)-1) != k\n                          || data (cidx (k+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (k+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (i, j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (k+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1)-1; i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::utsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                              octave_idx_type& err, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += std::abs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseComplexMatrix (nc, b_nc, b_nz);\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      octave_idx_type x_nz = b_nz;\n\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc);\n          for (octave_idx_type i = 0; i < nc; i++)\n            rperm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  octave_idx_type kidx = perm[k];\n\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (kidx+1)-1) != k\n                          || data (cidx (kidx+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (kidx+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (kidx);\n                           i < cidx (kidx+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[rperm[i]] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[rperm[i]];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      octave_idx_type iidx = perm[k];\n\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (iidx+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (iidx);\n                               i < cidx (iidx+1)-1; i++)\n                            {\n                              octave_idx_type idx2 = ridx (i);\n                              work[idx2] = work[idx2] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = nr-1; k >= 0; k--)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k+1)-1) != k\n                          || data (cidx (k+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (k+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (k+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1)-1; i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::ltsolve (MatrixType& mattype, const Matrix& b,\n                              octave_idx_type& err, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      octave_idx_type b_nc = b.cols ();\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += std::abs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      if (typ == MatrixType::Permuted_Lower)\n        {\n          retval.resize (nc, b_nc);\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, inv_perm, nr);\n          for (octave_idx_type i = 0; i < nr; i++)\n            inv_perm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[inv_perm[i]] = b(i, j);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      octave_idx_type minr = nr;\n                      octave_idx_type mini = 0;\n\n                      // Check that permutation leads to lower triangular form\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        if (inv_perm[ridx (i)] < minr)\n                          {\n                            minr = inv_perm[ridx (i)];\n                            mini = i;\n                          }\n\n                      if (minr != k || data (mini) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (mini);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        {\n                          if (i == mini)\n                            continue;\n\n                          octave_idx_type iidx = inv_perm[ridx (i)];\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval(i, j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = 0; k < nc; k++)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          octave_idx_type minr = nr;\n                          octave_idx_type mini = 0;\n\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            if (inv_perm[ridx (i)] < minr)\n                              {\n                                minr = inv_perm[ridx (i)];\n                                mini = i;\n                              }\n\n                          Complex tmp = work[k] / data (mini);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            {\n                              if (i == mini)\n                                continue;\n\n                              octave_idx_type iidx = inv_perm[ridx (i)];\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n          retval.resize (nc, b_nc, 0.);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                work[i] = 0.;\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k)) != k || data (cidx (k)) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (k));\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (i, j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k < nc; k++)\n                    {\n\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (k));\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k)+1;\n                               i < cidx (k+1); i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::ltsolve (MatrixType& mattype, const SparseMatrix& b,\n                              octave_idx_type& err, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += std::abs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseComplexMatrix (nc, b_nc, b_nz);\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      octave_idx_type x_nz = b_nz;\n\n      if (typ == MatrixType::Permuted_Lower)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, inv_perm, nr);\n          for (octave_idx_type i = 0; i < nr; i++)\n            inv_perm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[inv_perm[b.ridx (i)]] = b.data (i);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      octave_idx_type minr = nr;\n                      octave_idx_type mini = 0;\n\n                      // Check that permutation leads to lower triangular form\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        if (inv_perm[ridx (i)] < minr)\n                          {\n                            minr = inv_perm[ridx (i)];\n                            mini = i;\n                          }\n\n                      if (minr != k || data (mini) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (mini);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        {\n                          if (i == mini)\n                            continue;\n\n                          octave_idx_type iidx = inv_perm[ridx (i)];\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = 0; k < nc; k++)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          octave_idx_type minr = nr;\n                          octave_idx_type mini = 0;\n\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            if (inv_perm[ridx (i)] < minr)\n                              {\n                                minr = inv_perm[ridx (i)];\n                                mini = i;\n                              }\n\n                          Complex tmp = work[k] / data (mini);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            {\n                              if (i == mini)\n                                continue;\n\n                              octave_idx_type iidx = inv_perm[ridx (i)];\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k)) != k || data (cidx (k)) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (k));\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k < nc; k++)\n                    {\n\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (k));\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k)+1;\n                               i < cidx (k+1); i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::ltsolve (MatrixType& mattype, const ComplexMatrix& b,\n                              octave_idx_type& err, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      octave_idx_type b_nc = b.cols ();\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += std::abs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      if (typ == MatrixType::Permuted_Lower)\n        {\n          retval.resize (nc, b_nc);\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, inv_perm, nr);\n          for (octave_idx_type i = 0; i < nr; i++)\n            inv_perm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[inv_perm[i]] = b(i, j);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      octave_idx_type minr = nr;\n                      octave_idx_type mini = 0;\n\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        if (inv_perm[ridx (i)] < minr)\n                          {\n                            minr = inv_perm[ridx (i)];\n                            mini = i;\n                          }\n\n                      if (minr != k || data (mini) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (mini);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        {\n                          if (i == mini)\n                            continue;\n\n                          octave_idx_type iidx = inv_perm[ridx (i)];\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval(i, j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = 0; k < nc; k++)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          octave_idx_type minr = nr;\n                          octave_idx_type mini = 0;\n\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            if (inv_perm[ridx (i)] < minr)\n                              {\n                                minr = inv_perm[ridx (i)];\n                                mini = i;\n                              }\n\n                          Complex tmp = work[k] / data (mini);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            {\n                              if (i == mini)\n                                continue;\n\n                              octave_idx_type iidx = inv_perm[ridx (i)];\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n          retval.resize (nc, b_nc, 0.);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k)) != k || data (cidx (k)) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (k));\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (i, j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k < nc; k++)\n                    {\n\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (k));\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k)+1;\n                               i < cidx (k+1); i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::ltsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                              octave_idx_type& err, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += std::abs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseComplexMatrix (nc, b_nc, b_nz);\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      octave_idx_type x_nz = b_nz;\n\n      if (typ == MatrixType::Permuted_Lower)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, inv_perm, nr);\n          for (octave_idx_type i = 0; i < nr; i++)\n            inv_perm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[inv_perm[b.ridx (i)]] = b.data (i);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      octave_idx_type minr = nr;\n                      octave_idx_type mini = 0;\n\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        if (inv_perm[ridx (i)] < minr)\n                          {\n                            minr = inv_perm[ridx (i)];\n                            mini = i;\n                          }\n\n                      if (minr != k || data (mini) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (mini);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        {\n                          if (i == mini)\n                            continue;\n\n                          octave_idx_type iidx = inv_perm[ridx (i)];\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = 0; k < nc; k++)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          octave_idx_type minr = nr;\n                          octave_idx_type mini = 0;\n\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            if (inv_perm[ridx (i)] < minr)\n                              {\n                                minr = inv_perm[ridx (i)];\n                                mini = i;\n                              }\n\n                          Complex tmp = work[k] / data (mini);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            {\n                              if (i == mini)\n                                continue;\n\n                              octave_idx_type iidx = inv_perm[ridx (i)];\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, work, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k)) != k || data (cidx (k)) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = work[k] / data (cidx (k));\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k < nc; k++)\n                    {\n\n                      if (work[k] != 0.)\n                        {\n                          Complex tmp = work[k] / data (cidx (k));\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k)+1;\n                               i < cidx (k+1); i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += std::abs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::trisolve (MatrixType& mattype, const Matrix& b,\n                               octave_idx_type& err, double& rcond,\n                               solve_singularity_handler sing_handler,\n                               bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else if (calc_cond)\n    (*current_liboctave_error_handler)\n      (\"calculation of condition number not implemented\");\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Tridiagonal_Hermitian)\n        {\n          OCTAVE_LOCAL_BUFFER (double, D, nr);\n          OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = std::real (data (ii++));\n                  DL[j] = data (ii);\n                  ii += 2;\n                }\n              D[nc-1] = std::real (data (ii));\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = std::real (data (i));\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                  }\n            }\n\n          F77_INT b_nr = octave::to_f77_int (b.rows ());\n          F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n          retval = ComplexMatrix (b);\n          Complex *result = retval.rwdata ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zptsv, ZPTSV, (tmp_nr, b_nc, D, F77_DBLE_CMPLX_ARG (DL),\n                                   F77_DBLE_CMPLX_ARG (result),\n                                   b_nr, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = 0;\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Tridiagonal;\n            }\n          else\n            rcond = 1.;\n        }\n\n      if (typ == MatrixType::Tridiagonal)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1);\n          OCTAVE_LOCAL_BUFFER (Complex, D, nr);\n          OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii++);\n                  DU[j] = data (ii++);\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                  DU[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                    else if (ridx (i) == j - 1)\n                      DU[j-1] = data (i);\n                  }\n            }\n\n          F77_INT b_nr = octave::to_f77_int (b.rows ());\n          F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n          retval = ComplexMatrix (b);\n          Complex *result = retval.rwdata ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zgtsv, ZGTSV, (tmp_nr, b_nc, F77_DBLE_CMPLX_ARG (DL),\n                                   F77_DBLE_CMPLX_ARG (D), F77_DBLE_CMPLX_ARG (DU), F77_DBLE_CMPLX_ARG (result),\n                                   b_nr, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              rcond = 0.;\n              err = -2;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n\n            }\n          else\n            rcond = 1.;\n        }\n      else if (typ != MatrixType::Tridiagonal_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::trisolve (MatrixType& mattype, const SparseMatrix& b,\n                               octave_idx_type& err, double& rcond,\n                               solve_singularity_handler sing_handler,\n                               bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else if (calc_cond)\n    (*current_liboctave_error_handler)\n      (\"calculation of condition number not implemented\");\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      // Note can't treat symmetric case as there is no dpttrf function\n      if (typ == MatrixType::Tridiagonal\n          || typ == MatrixType::Tridiagonal_Hermitian)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2);\n          OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1);\n          OCTAVE_LOCAL_BUFFER (Complex, D, nr);\n          OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii++);\n                  DU[j] = data (ii++);\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                  DU[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                    else if (ridx (i) == j - 1)\n                      DU[j-1] = data (i);\n                  }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zgttrf, ZGTTRF, (tmp_nr, F77_DBLE_CMPLX_ARG (DL),\n                                     F77_DBLE_CMPLX_ARG (D),\n                                     F77_DBLE_CMPLX_ARG (DU),\n                                     F77_DBLE_CMPLX_ARG (DU2),\n                                     pipvt, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = -2;\n              rcond = 0.0;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              char job = 'N';\n              octave_idx_type x_nz = b.nnz ();\n              F77_INT b_nr = octave::to_f77_int (b.rows ());\n              octave_idx_type b_nc = b.cols ();\n              retval = SparseComplexMatrix (nr, b_nc, x_nz);\n              retval.xcidx (0) = 0;\n              octave_idx_type ii = 0;\n              rcond = 1.0;\n\n              OCTAVE_LOCAL_BUFFER (Complex, work, nr);\n\n              for (octave_idx_type j = 0; j < b_nc; j++)\n                {\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    work[i] = 0.;\n                  for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                    work[b.ridx (i)] = b.data (i);\n\n                  F77_XFCN (zgttrs, ZGTTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, 1, F77_DBLE_CMPLX_ARG (DL),\n                             F77_DBLE_CMPLX_ARG (D),\n                             F77_DBLE_CMPLX_ARG (DU),\n                             F77_DBLE_CMPLX_ARG (DU2), pipvt,\n                             F77_DBLE_CMPLX_ARG (work), b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  // Count nonzeros in work vector and adjust\n                  // space in retval if needed\n                  octave_idx_type new_nnz = 0;\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    if (work[i] != 0.)\n                      new_nnz++;\n\n                  if (ii + new_nnz > x_nz)\n                    {\n                      // Resize the sparse matrix\n                      octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                      retval.change_capacity (sz);\n                      x_nz = sz;\n                    }\n\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    if (work[i] != 0.)\n                      {\n                        retval.xridx (ii) = i;\n                        retval.xdata (ii++) = work[i];\n                      }\n                  retval.xcidx (j+1) = ii;\n                }\n\n              retval.maybe_compress ();\n            }\n        }\n      else if (typ != MatrixType::Tridiagonal_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::trisolve (MatrixType& mattype, const ComplexMatrix& b,\n                               octave_idx_type& err, double& rcond,\n                               solve_singularity_handler sing_handler,\n                               bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else if (calc_cond)\n    (*current_liboctave_error_handler)\n      (\"calculation of condition number not implemented\");\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Tridiagonal_Hermitian)\n        {\n          OCTAVE_LOCAL_BUFFER (double, D, nr);\n          OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = std::real (data (ii++));\n                  DL[j] = data (ii);\n                  ii += 2;\n                }\n              D[nc-1] = std::real (data (ii));\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = std::real (data (i));\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                  }\n            }\n\n          F77_INT b_nr = octave::to_f77_int (b.rows ());\n          F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n          rcond = 1.;\n\n          retval = ComplexMatrix (b);\n          Complex *result = retval.rwdata ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zptsv, ZPTSV, (tmp_nr, b_nc, D, F77_DBLE_CMPLX_ARG (DL),\n                                   F77_DBLE_CMPLX_ARG (result),\n                                   b_nr, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = 0;\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Tridiagonal;\n            }\n        }\n\n      if (typ == MatrixType::Tridiagonal)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1);\n          OCTAVE_LOCAL_BUFFER (Complex, D, nr);\n          OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii++);\n                  DU[j] = data (ii++);\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                  DU[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                    else if (ridx (i) == j - 1)\n                      DU[j-1] = data (i);\n                  }\n            }\n\n          F77_INT b_nr = octave::to_f77_int (b.rows ());\n          F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n          rcond = 1.;\n\n          retval = ComplexMatrix (b);\n          Complex *result = retval.rwdata ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zgtsv, ZGTSV, (tmp_nr, b_nc, F77_DBLE_CMPLX_ARG (DL),\n                                   F77_DBLE_CMPLX_ARG (D), F77_DBLE_CMPLX_ARG (DU), F77_DBLE_CMPLX_ARG (result),\n                                   b_nr, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              rcond = 0.;\n              err = -2;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n        }\n      else if (typ != MatrixType::Tridiagonal_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::trisolve (MatrixType& mattype,\n                               const SparseComplexMatrix& b,\n                               octave_idx_type& err, double& rcond,\n                               solve_singularity_handler sing_handler,\n                               bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else if (calc_cond)\n    (*current_liboctave_error_handler)\n      (\"calculation of condition number not implemented\");\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      // Note can't treat symmetric case as there is no dpttrf function\n      if (typ == MatrixType::Tridiagonal\n          || typ == MatrixType::Tridiagonal_Hermitian)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2);\n          OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1);\n          OCTAVE_LOCAL_BUFFER (Complex, D, nr);\n          OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii++);\n                  DU[j] = data (ii++);\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                  DU[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                    else if (ridx (i) == j - 1)\n                      DU[j-1] = data (i);\n                  }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zgttrf, ZGTTRF, (tmp_nr, F77_DBLE_CMPLX_ARG (DL),\n                                     F77_DBLE_CMPLX_ARG (D),\n                                     F77_DBLE_CMPLX_ARG (DU),\n                                     F77_DBLE_CMPLX_ARG (DU2),\n                                     pipvt, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              rcond = 0.0;\n              err = -2;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              rcond = 1.;\n              char job = 'N';\n              F77_INT b_nr = octave::to_f77_int (b.rows ());\n              octave_idx_type b_nc = b.cols ();\n              OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);\n\n              // Take a first guess that the number of nonzero terms\n              // will be as many as in b\n              octave_idx_type x_nz = b.nnz ();\n              octave_idx_type ii = 0;\n              retval = SparseComplexMatrix (b_nr, b_nc, x_nz);\n\n              retval.xcidx (0) = 0;\n              for (octave_idx_type j = 0; j < b_nc; j++)\n                {\n\n                  for (F77_INT i = 0; i < b_nr; i++)\n                    Bx[i] = b(i, j);\n\n                  F77_XFCN (zgttrs, ZGTTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, 1, F77_DBLE_CMPLX_ARG (DL),\n                             F77_DBLE_CMPLX_ARG (D),\n                             F77_DBLE_CMPLX_ARG (DU),\n                             F77_DBLE_CMPLX_ARG (DU2), pipvt,\n                             F77_DBLE_CMPLX_ARG (Bx), b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    {\n                      // FIXME: This should probably be a warning so that\n                      //        error value can be passed back.\n                      (*current_liboctave_error_handler)\n                        (\"SparseComplexMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n\n                  // Count nonzeros in work vector and adjust\n                  // space in retval if needed\n                  octave_idx_type new_nnz = 0;\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    if (Bx[i] != 0.)\n                      new_nnz++;\n\n                  if (ii + new_nnz > x_nz)\n                    {\n                      // Resize the sparse matrix\n                      octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                      retval.change_capacity (sz);\n                      x_nz = sz;\n                    }\n\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    if (Bx[i] != 0.)\n                      {\n                        retval.xridx (ii) = i;\n                        retval.xdata (ii++) = Bx[i];\n                      }\n\n                  retval.xcidx (j+1) = ii;\n                }\n\n              retval.maybe_compress ();\n            }\n        }\n      else if (typ != MatrixType::Tridiagonal_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::bsolve (MatrixType& mattype, const Matrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Banded_Hermitian)\n        {\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_lower + 1;\n          ComplexMatrix m_band (ldm, nc);\n          Complex *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              {\n                octave_idx_type ri = ridx (i);\n                if (ri >= j)\n                  m_band(ri - j, j) = data (i);\n              }\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            anorm = m_band.abs ().sum ().row (0).max ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          char job = 'L';\n          F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     tmp_nr, n_lower, F77_DBLE_CMPLX_ARG (tmp_data), ldm, tmp_err\n                                     F77_CHAR_ARG_LEN (1)));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              rcond = 0.0;\n              // Matrix is not positive definite!! Fall through to\n              // unsymmetric banded solver.\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Banded;\n              err = 0;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<Complex> z (dim_vector (2 * nr, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> iz (dim_vector (nr, 1));\n                  double *piz = iz.rwdata ();\n\n                  F77_XFCN (zpbcon, ZPBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, F77_DBLE_CMPLX_ARG (tmp_data), ldm,\n                             anorm, rcond, F77_DBLE_CMPLX_ARG (pz), piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.0;\n\n              if (err == 0)\n                {\n                  retval = ComplexMatrix (b);\n                  Complex *result = retval.rwdata ();\n\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n                  F77_XFCN (zpbtrs, ZPBTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, b_nc, F77_DBLE_CMPLX_ARG (tmp_data),\n                             ldm, F77_DBLE_CMPLX_ARG (result), b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    {\n                      // FIXME: Probably should be a warning.\n                      (*current_liboctave_error_handler)\n                        (\"SparseMatrix::solve solve failed\");\n                      err = -1;\n                    }\n                }\n            }\n        }\n\n      if (typ == MatrixType::Banded)\n        {\n          // Create the storage for the banded form of the sparse matrix\n          F77_INT n_upper = octave::to_f77_int (mattype.nupper ());\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_upper + 2 * n_lower + 1;\n\n          ComplexMatrix m_band (ldm, nc);\n          Complex *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm = 0.0;\n          if (calc_cond)\n            {\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  double atmp = 0.;\n                  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                    atmp += std::abs (data (i));\n                  if (atmp > anorm)\n                    anorm = atmp;\n                }\n            }\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zgbtrf, ZGBTRF, (tmp_nr, tmp_nr, n_lower, n_upper,\n                                     F77_DBLE_CMPLX_ARG (tmp_data),\n                                     ldm, pipvt, tmp_err));\n\n          err = tmp_err;\n\n          // Throw away extra info LAPACK gives so as to not\n          // change output.\n          if (err != 0)\n            {\n              rcond = 0.0;\n              err = -2;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  char job = '1';\n                  Array<Complex> z (dim_vector (2 * nr, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> iz (dim_vector (nr, 1));\n                  double *piz = iz.rwdata ();\n\n                  F77_INT tmp_nc = octave::to_f77_int (nc);\n\n                  F77_XFCN (zgbcon, ZGBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nc, n_lower, n_upper, F77_DBLE_CMPLX_ARG (tmp_data), ldm, pipvt,\n                             anorm, rcond, F77_DBLE_CMPLX_ARG (pz), piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  retval = ComplexMatrix (b);\n                  Complex *result = retval.rwdata ();\n\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n                  char job = 'N';\n                  F77_XFCN (zgbtrs, ZGBTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, n_upper, b_nc, F77_DBLE_CMPLX_ARG (tmp_data),\n                             ldm, pipvt, F77_DBLE_CMPLX_ARG (result), b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n                }\n            }\n        }\n      else if (typ != MatrixType::Banded_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::bsolve (MatrixType& mattype, const SparseMatrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Banded_Hermitian)\n        {\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_lower + 1;\n\n          ComplexMatrix m_band (ldm, nc);\n          Complex *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              {\n                octave_idx_type ri = ridx (i);\n                if (ri >= j)\n                  m_band(ri - j, j) = data (i);\n              }\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            anorm = m_band.abs ().sum ().row (0).max ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          char job = 'L';\n          F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     tmp_nr, n_lower, F77_DBLE_CMPLX_ARG (tmp_data), ldm, tmp_err\n                                     F77_CHAR_ARG_LEN (1)));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              rcond = 0.0;\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Banded;\n              err = 0;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<Complex> z (dim_vector (2 * nr, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> iz (dim_vector (nr, 1));\n                  double *piz = iz.rwdata ();\n\n                  F77_XFCN (zpbcon, ZPBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, F77_DBLE_CMPLX_ARG (tmp_data), ldm,\n                             anorm, rcond, F77_DBLE_CMPLX_ARG (pz), piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.0;\n\n              if (err == 0)\n                {\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  octave_idx_type b_nc = b.cols ();\n                  OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);\n\n                  // Take a first guess that the number of nonzero terms\n                  // will be as many as in b\n                  octave_idx_type x_nz = b.nnz ();\n                  octave_idx_type ii = 0;\n                  retval = SparseComplexMatrix (b_nr, b_nc, x_nz);\n\n                  retval.xcidx (0) = 0;\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n                      for (F77_INT i = 0; i < b_nr; i++)\n                        Bx[i] = b.elem (i, j);\n\n                      F77_XFCN (zpbtrs, ZPBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, 1, F77_DBLE_CMPLX_ARG (tmp_data),\n                                 ldm, F77_DBLE_CMPLX_ARG (Bx), b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      if (err != 0)\n                        {\n                          // FIXME: Probably should be a warning.\n                          (*current_liboctave_error_handler)\n                            (\"SparseComplexMatrix::solve solve failed\");\n                          err = -1;\n                          break;\n                        }\n\n                      for (octave_idx_type i = 0; i < b_nr; i++)\n                        {\n                          Complex tmp = Bx[i];\n                          if (tmp != 0.0)\n                            {\n                              if (ii == x_nz)\n                                {\n                                  // Resize the sparse matrix\n                                  octave_idx_type sz;\n                                  sz = (static_cast<double> (b_nc) - j) / b_nc\n                                       * x_nz;\n                                  sz = x_nz + (sz > 100 ? sz : 100);\n                                  retval.change_capacity (sz);\n                                  x_nz = sz;\n                                }\n                              retval.xdata (ii) = tmp;\n                              retval.xridx (ii++) = i;\n                            }\n                        }\n                      retval.xcidx (j+1) = ii;\n                    }\n\n                  retval.maybe_compress ();\n                }\n            }\n        }\n\n      if (typ == MatrixType::Banded)\n        {\n          // Create the storage for the banded form of the sparse matrix\n          F77_INT n_upper = octave::to_f77_int (mattype.nupper ());\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_upper + 2 * n_lower + 1;\n\n          ComplexMatrix m_band (ldm, nc);\n          Complex *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm = 0.0;\n          if (calc_cond)\n            {\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  double atmp = 0.;\n                  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                    atmp += std::abs (data (i));\n                  if (atmp > anorm)\n                    anorm = atmp;\n                }\n            }\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zgbtrf, ZGBTRF, (tmp_nr, tmp_nr, n_lower, n_upper,\n                                     F77_DBLE_CMPLX_ARG (tmp_data),\n                                     ldm, pipvt, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              rcond = 0.0;\n              err = -2;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  char job = '1';\n                  Array<Complex> z (dim_vector (2 * nr, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> iz (dim_vector (nr, 1));\n                  double *piz = iz.rwdata ();\n\n                  F77_INT tmp_nc = octave::to_f77_int (nc);\n\n                  F77_XFCN (zgbcon, ZGBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nc, n_lower, n_upper, F77_DBLE_CMPLX_ARG (tmp_data), ldm, pipvt,\n                             anorm, rcond, F77_DBLE_CMPLX_ARG (pz), piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  char job = 'N';\n                  octave_idx_type x_nz = b.nnz ();\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  octave_idx_type b_nc = b.cols ();\n                  retval = SparseComplexMatrix (nr, b_nc, x_nz);\n                  retval.xcidx (0) = 0;\n                  octave_idx_type ii = 0;\n\n                  OCTAVE_LOCAL_BUFFER (Complex, work, nr);\n\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        work[i] = 0.;\n                      for (octave_idx_type i = b.cidx (j);\n                           i < b.cidx (j+1); i++)\n                        work[b.ridx (i)] = b.data (i);\n\n                      F77_XFCN (zgbtrs, ZGBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, n_upper, 1, F77_DBLE_CMPLX_ARG (tmp_data),\n                                 ldm, pipvt, F77_DBLE_CMPLX_ARG (work), b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      // Count nonzeros in work vector and adjust\n                      // space in retval if needed\n                      octave_idx_type new_nnz = 0;\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (work[i] != 0.)\n                          new_nnz++;\n\n                      if (ii + new_nnz > x_nz)\n                        {\n                          // Resize the sparse matrix\n                          octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                          retval.change_capacity (sz);\n                          x_nz = sz;\n                        }\n\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (work[i] != 0.)\n                          {\n                            retval.xridx (ii) = i;\n                            retval.xdata (ii++) = work[i];\n                          }\n                      retval.xcidx (j+1) = ii;\n                    }\n\n                  retval.maybe_compress ();\n                }\n            }\n        }\n      else if (typ != MatrixType::Banded_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::bsolve (MatrixType& mattype, const ComplexMatrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Banded_Hermitian)\n        {\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_lower + 1;\n\n          ComplexMatrix m_band (ldm, nc);\n          Complex *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              {\n                octave_idx_type ri = ridx (i);\n                if (ri >= j)\n                  m_band(ri - j, j) = data (i);\n              }\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            anorm = m_band.abs ().sum ().row (0).max ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          char job = 'L';\n          F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     tmp_nr, n_lower, F77_DBLE_CMPLX_ARG (tmp_data), ldm, tmp_err\n                                     F77_CHAR_ARG_LEN (1)));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              // Matrix is not positive definite!! Fall through to\n              // unsymmetric banded solver.\n              rcond = 0.0;\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Banded;\n              err = 0;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<Complex> z (dim_vector (2 * nr, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> iz (dim_vector (nr, 1));\n                  double *piz = iz.rwdata ();\n\n                  F77_XFCN (zpbcon, ZPBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, F77_DBLE_CMPLX_ARG (tmp_data), ldm,\n                             anorm, rcond, F77_DBLE_CMPLX_ARG (pz), piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.0;\n\n              if (err == 0)\n                {\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  F77_INT b_nc = octave::to_f77_int (b.cols ());\n                  retval = ComplexMatrix (b);\n                  Complex *result = retval.rwdata ();\n\n                  F77_XFCN (zpbtrs, ZPBTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, b_nc, F77_DBLE_CMPLX_ARG (tmp_data),\n                             ldm, F77_DBLE_CMPLX_ARG (result), b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    {\n                      // FIXME: Probably should be a warning.\n                      (*current_liboctave_error_handler)\n                        (\"SparseComplexMatrix::solve solve failed\");\n                      err = -1;\n                    }\n                }\n            }\n        }\n\n      if (typ == MatrixType::Banded)\n        {\n          // Create the storage for the banded form of the sparse matrix\n          F77_INT n_upper = octave::to_f77_int (mattype.nupper ());\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_upper + 2 * n_lower + 1;\n\n          ComplexMatrix m_band (ldm, nc);\n          Complex *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm = 0.0;\n          if (calc_cond)\n            {\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  double atmp = 0.;\n                  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                    atmp += std::abs (data (i));\n                  if (atmp > anorm)\n                    anorm = atmp;\n                }\n            }\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zgbtrf, ZGBTRF, (tmp_nr, tmp_nr, n_lower, n_upper,\n                                     F77_DBLE_CMPLX_ARG (tmp_data),\n                                     ldm, pipvt, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = -2;\n              rcond = 0.0;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  char job = '1';\n                  Array<Complex> z (dim_vector (2 * nr, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> iz (dim_vector (nr, 1));\n                  double *piz = iz.rwdata ();\n\n                  F77_INT tmp_nc = octave::to_f77_int (nc);\n\n                  F77_XFCN (zgbcon, ZGBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nc, n_lower, n_upper, F77_DBLE_CMPLX_ARG (tmp_data), ldm, pipvt,\n                             anorm, rcond, F77_DBLE_CMPLX_ARG (pz), piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  char job = 'N';\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  F77_INT b_nc = octave::to_f77_int (b.cols ());\n                  retval = ComplexMatrix (b);\n                  Complex *result = retval.rwdata ();\n\n                  F77_XFCN (zgbtrs, ZGBTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, n_upper, b_nc, F77_DBLE_CMPLX_ARG (tmp_data),\n                             ldm, pipvt, F77_DBLE_CMPLX_ARG (result), b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n                }\n            }\n        }\n      else if (typ != MatrixType::Banded_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::bsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Banded_Hermitian)\n        {\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_lower + 1;\n\n          ComplexMatrix m_band (ldm, nc);\n          Complex *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              {\n                octave_idx_type ri = ridx (i);\n                if (ri >= j)\n                  m_band(ri - j, j) = data (i);\n              }\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            anorm = m_band.abs ().sum ().row (0).max ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          char job = 'L';\n          F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     tmp_nr, n_lower, F77_DBLE_CMPLX_ARG (tmp_data), ldm, tmp_err\n                                     F77_CHAR_ARG_LEN (1)));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              // Matrix is not positive definite!! Fall through to\n              // unsymmetric banded solver.\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Banded;\n\n              rcond = 0.0;\n              err = 0;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<Complex> z (dim_vector (2 * nr, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> iz (dim_vector (nr, 1));\n                  double *piz = iz.rwdata ();\n\n                  F77_XFCN (zpbcon, ZPBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, F77_DBLE_CMPLX_ARG (tmp_data), ldm,\n                             anorm, rcond, F77_DBLE_CMPLX_ARG (pz), piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.0;\n\n              if (err == 0)\n                {\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  octave_idx_type b_nc = b.cols ();\n                  OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);\n\n                  // Take a first guess that the number of nonzero terms\n                  // will be as many as in b\n                  octave_idx_type x_nz = b.nnz ();\n                  octave_idx_type ii = 0;\n                  retval = SparseComplexMatrix (b_nr, b_nc, x_nz);\n\n                  retval.xcidx (0) = 0;\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n\n                      for (F77_INT i = 0; i < b_nr; i++)\n                        Bx[i] = b(i, j);\n\n                      F77_XFCN (zpbtrs, ZPBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, 1, F77_DBLE_CMPLX_ARG (tmp_data),\n                                 ldm, F77_DBLE_CMPLX_ARG (Bx), b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      if (err != 0)\n                        {\n                          // FIXME: Probably should be a warning.\n                          (*current_liboctave_error_handler)\n                            (\"SparseMatrix::solve solve failed\");\n                          err = -1;\n                          break;\n                        }\n\n                      // Count nonzeros in work vector and adjust\n                      // space in retval if needed\n                      octave_idx_type new_nnz = 0;\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (Bx[i] != 0.)\n                          new_nnz++;\n\n                      if (ii + new_nnz > x_nz)\n                        {\n                          // Resize the sparse matrix\n                          octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                          retval.change_capacity (sz);\n                          x_nz = sz;\n                        }\n\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (Bx[i] != 0.)\n                          {\n                            retval.xridx (ii) = i;\n                            retval.xdata (ii++) = Bx[i];\n                          }\n\n                      retval.xcidx (j+1) = ii;\n                    }\n\n                  retval.maybe_compress ();\n                }\n            }\n        }\n\n      if (typ == MatrixType::Banded)\n        {\n          // Create the storage for the banded form of the sparse matrix\n          F77_INT n_upper = octave::to_f77_int (mattype.nupper ());\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_upper + 2 * n_lower + 1;\n\n          ComplexMatrix m_band (ldm, nc);\n          Complex *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm = 0.0;\n          if (calc_cond)\n            {\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  double atmp = 0.;\n                  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                    atmp += std::abs (data (i));\n                  if (atmp > anorm)\n                    anorm = atmp;\n                }\n            }\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zgbtrf, ZGBTRF, (tmp_nr, tmp_nr, n_lower, n_upper,\n                                     F77_DBLE_CMPLX_ARG (tmp_data),\n                                     ldm, pipvt, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = -2;\n              rcond = 0.0;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  char job = '1';\n                  Array<Complex> z (dim_vector (2 * nr, 1));\n                  Complex *pz = z.rwdata ();\n                  Array<double> iz (dim_vector (nr, 1));\n                  double *piz = iz.rwdata ();\n\n                  F77_INT tmp_nc = octave::to_f77_int (nc);\n\n                  F77_XFCN (zgbcon, ZGBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nc, n_lower, n_upper, F77_DBLE_CMPLX_ARG (tmp_data), ldm, pipvt,\n                             anorm, rcond, F77_DBLE_CMPLX_ARG (pz), piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  char job = 'N';\n                  octave_idx_type x_nz = b.nnz ();\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  octave_idx_type b_nc = b.cols ();\n                  retval = SparseComplexMatrix (nr, b_nc, x_nz);\n                  retval.xcidx (0) = 0;\n                  octave_idx_type ii = 0;\n\n                  OCTAVE_LOCAL_BUFFER (Complex, Bx, nr);\n\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        Bx[i] = 0.;\n\n                      for (octave_idx_type i = b.cidx (j);\n                           i < b.cidx (j+1); i++)\n                        Bx[b.ridx (i)] = b.data (i);\n\n                      F77_XFCN (zgbtrs, ZGBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, n_upper, 1, F77_DBLE_CMPLX_ARG (tmp_data),\n                                 ldm, pipvt, F77_DBLE_CMPLX_ARG (Bx), b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      // Count nonzeros in work vector and adjust\n                      // space in retval if needed\n                      octave_idx_type new_nnz = 0;\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (Bx[i] != 0.)\n                          new_nnz++;\n\n                      if (ii + new_nnz > x_nz)\n                        {\n                          // Resize the sparse matrix\n                          octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                          retval.change_capacity (sz);\n                          x_nz = sz;\n                        }\n\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (Bx[i] != 0.)\n                          {\n                            retval.xridx (ii) = i;\n                            retval.xdata (ii++) = Bx[i];\n                          }\n                      retval.xcidx (j+1) = ii;\n                    }\n\n                  retval.maybe_compress ();\n                }\n            }\n        }\n      else if (typ != MatrixType::Banded_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nvoid *\nSparseComplexMatrix::factorize (octave_idx_type& err, double& rcond,\n                                Matrix& Control, Matrix& Info,\n                                solve_singularity_handler sing_handler,\n                                bool calc_cond) const\n{\n  // The return values\n  void *Numeric = nullptr;\n  err = 0;\n\n#if defined (HAVE_UMFPACK)\n\n  // Setup the control parameters\n  Control = Matrix (UMFPACK_CONTROL, 1);\n  double *control = Control.rwdata ();\n  UMFPACK_ZNAME (defaults) (control);\n\n  double tmp = octave::sparse_params::get_key (\"spumoni\");\n  if (! octave::math::isnan (tmp))\n    Control (UMFPACK_PRL) = tmp;\n  tmp = octave::sparse_params::get_key (\"piv_tol\");\n  if (! octave::math::isnan (tmp))\n    {\n      Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;\n      Control (UMFPACK_PIVOT_TOLERANCE) = tmp;\n    }\n\n  // Set whether we are allowed to modify Q or not\n  tmp = octave::sparse_params::get_key (\"autoamd\");\n  if (! octave::math::isnan (tmp))\n    Control (UMFPACK_FIXQ) = tmp;\n\n  UMFPACK_ZNAME (report_control) (control);\n\n  const octave_idx_type *Ap = cidx ();\n  const octave_idx_type *Ai = ridx ();\n  const Complex *Ax = data ();\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  UMFPACK_ZNAME (report_matrix) (nr, nc,\n                                 octave::to_suitesparse_intptr (Ap),\n                                 octave::to_suitesparse_intptr (Ai),\n                                 reinterpret_cast<const double *> (Ax),\n                                 nullptr, 1, control);\n\n  void *Symbolic;\n  Info = Matrix (1, UMFPACK_INFO);\n  double *info = Info.rwdata ();\n  int status = UMFPACK_ZNAME (qsymbolic) (nr, nc,\n                                          octave::to_suitesparse_intptr (Ap),\n                                          octave::to_suitesparse_intptr (Ai),\n                                          reinterpret_cast<const double *> (Ax),\n                                          nullptr, nullptr, &Symbolic, control, info);\n\n  if (status < 0)\n    {\n      UMFPACK_ZNAME (report_status) (control, status);\n      UMFPACK_ZNAME (report_info) (control, info);\n\n      UMFPACK_ZNAME (free_symbolic) (&Symbolic);\n\n      // FIXME: Should this be a warning?\n      (*current_liboctave_error_handler)\n        (\"SparseComplexMatrix::solve symbolic factorization failed\");\n      err = -1;\n    }\n  else\n    {\n      UMFPACK_ZNAME (report_symbolic) (Symbolic, control);\n\n      status = UMFPACK_ZNAME (numeric) (octave::to_suitesparse_intptr (Ap),\n                                        octave::to_suitesparse_intptr (Ai),\n                                        reinterpret_cast<const double *> (Ax),\n                                        nullptr, Symbolic, &Numeric, control, info);\n      UMFPACK_ZNAME (free_symbolic) (&Symbolic);\n\n      if (calc_cond)\n        rcond = Info (UMFPACK_RCOND);\n      else\n        rcond = 1.;\n\n      if (status == UMFPACK_WARNING_singular_matrix\n          || is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          UMFPACK_ZNAME (report_numeric) (Numeric, control);\n\n          err = -2;\n\n          if (sing_handler)\n            sing_handler (rcond);\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n      else if (status < 0)\n        {\n          UMFPACK_ZNAME (report_status) (control, status);\n          UMFPACK_ZNAME (report_info) (control, info);\n\n          // FIXME: Should this be a warning?\n          (*current_liboctave_error_handler)\n            (\"SparseComplexMatrix::solve numeric factorization failed\");\n\n          err = -1;\n        }\n      else\n        {\n          UMFPACK_ZNAME (report_numeric) (Numeric, control);\n        }\n    }\n\n  if (err != 0)\n    UMFPACK_ZNAME (free_numeric) (&Numeric);\n\n#else\n\n  octave_unused_parameter (rcond);\n  octave_unused_parameter (Control);\n  octave_unused_parameter (Info);\n  octave_unused_parameter (sing_handler);\n  octave_unused_parameter (calc_cond);\n\n  (*current_liboctave_error_handler)\n    (\"support for UMFPACK was unavailable or disabled when liboctave was built\");\n\n#endif\n\n  return Numeric;\n}\n\nComplexMatrix\nSparseComplexMatrix::fsolve (MatrixType& mattype, const Matrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Hermitian)\n        {\n#if defined (HAVE_CHOLMOD)\n          cholmod_common Common;\n          cholmod_common *cm = &Common;\n\n          // Setup initial parameters\n          CHOLMOD_NAME(start) (cm);\n          cm->prefer_zomplex = false;\n\n          double spu = octave::sparse_params::get_key (\"spumoni\");\n          if (spu == 0.)\n            {\n              cm->print = -1;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n            }\n          else\n            {\n              cm->print = static_cast<int> (spu) + 2;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);\n            }\n\n          cm->error_handler = &SparseCholError;\n          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);\n          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n          cm->final_ll = true;\n\n          cholmod_sparse Astore;\n          cholmod_sparse *A = &Astore;\n          A->nrow = nr;\n          A->ncol = nc;\n\n          A->p = const_cast<octave_idx_type *> (cidx ());\n          A->i = const_cast<octave_idx_type *> (ridx ());\n          A->nzmax = nnz ();\n          A->packed = true;\n          A->sorted = true;\n          A->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          A->itype = CHOLMOD_LONG;\n#else\n          A->itype = CHOLMOD_INT;\n#endif\n          A->dtype = CHOLMOD_DOUBLE;\n          A->stype = 1;\n          A->xtype = CHOLMOD_COMPLEX;\n\n          A->x = const_cast<Complex *> (data ());\n\n          cholmod_dense Bstore;\n          cholmod_dense *B = &Bstore;\n          B->nrow = b.rows ();\n          B->ncol = b.cols ();\n          B->d = B->nrow;\n          B->nzmax = B->nrow * B->ncol;\n          B->dtype = CHOLMOD_DOUBLE;\n          B->xtype = CHOLMOD_REAL;\n\n          B->x = const_cast<double *> (b.data ());\n\n          cholmod_factor *L = CHOLMOD_NAME(analyze) (A, cm);\n          CHOLMOD_NAME(factorize) (A, L, cm);\n          if (calc_cond)\n            rcond = CHOLMOD_NAME(rcond)(L, cm);\n          else\n            rcond = 1.;\n\n          if (rcond == 0.0)\n            {\n              // Either its indefinite or singular.  Try UMFPACK\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (is_singular (rcond) || octave::math::isnan (rcond))\n                {\n                  err = -2;\n\n                  if (sing_handler)\n                    {\n                      sing_handler (rcond);\n                      mattype.mark_as_rectangular ();\n                    }\n                  else\n                    octave::warn_singular_matrix (rcond);\n\n                  return retval;\n                }\n\n              cholmod_dense *X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm);\n\n              retval.resize (b.rows (), b.cols ());\n              for (octave_idx_type j = 0; j < b.cols (); j++)\n                {\n                  octave_idx_type jr = j * b.rows ();\n                  for (octave_idx_type i = 0; i < b.rows (); i++)\n                    retval.xelem (i, j) = static_cast<Complex *> (X->x)[jr + i];\n                }\n\n              CHOLMOD_NAME(free_dense) (&X, cm);\n              CHOLMOD_NAME(free_factor) (&L, cm);\n              CHOLMOD_NAME(finish) (cm);\n              static char blank_name[] = \" \";\n              CHOLMOD_NAME(print_common) (blank_name, cm);\n            }\n#else\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:missing-dependency\",\n             \"support for CHOLMOD was unavailable or disabled \"\n             \"when liboctave was built\");\n\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n#endif\n        }\n\n      if (typ == MatrixType::Full)\n        {\n#if defined (HAVE_UMFPACK)\n          Matrix Control, Info;\n          void *Numeric = factorize (err, rcond, Control, Info,\n                                     sing_handler, calc_cond);\n\n          if (err == 0)\n            {\n              // one iterative refinement instead of the default two in UMFPACK\n              Control (UMFPACK_IRSTEP) = 1;\n              octave_idx_type b_nr = b.rows ();\n              octave_idx_type b_nc = b.cols ();\n              int status = 0;\n              double *control = Control.rwdata ();\n              double *info = Info.rwdata ();\n              const octave_idx_type *Ap = cidx ();\n              const octave_idx_type *Ai = ridx ();\n              const Complex *Ax = data ();\n#if defined (UMFPACK_SEPARATE_SPLIT)\n              const double *Bx = b.data ();\n              OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);\n              for (octave_idx_type i = 0; i < b_nr; i++)\n                Bz[i] = 0.;\n#else\n              OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr);\n#endif\n              retval.resize (b_nr, b_nc);\n              Complex *Xx = retval.rwdata ();\n\n              for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr)\n                {\n#if defined (UMFPACK_SEPARATE_SPLIT)\n                  status = UMFPACK_ZNAME (solve) (UMFPACK_A,\n                                                  octave::to_suitesparse_intptr (Ap),\n                                                  octave::to_suitesparse_intptr (Ai),\n                                                  reinterpret_cast<const double *> (Ax),\n                                                  nullptr,\n                                                  reinterpret_cast<double *> (&Xx[iidx]),\n                                                  nullptr,\n                                                  &Bx[iidx], Bz, Numeric,\n                                                  control, info);\n#else\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    Bz[i] = b.elem (i, j);\n\n                  status = UMFPACK_ZNAME (solve) (UMFPACK_A,\n                                                  octave::to_suitesparse_intptr (Ap),\n                                                  octave::to_suitesparse_intptr (Ai),\n                                                  reinterpret_cast<const double *> (Ax),\n                                                  0,\n                                                  reinterpret_cast<double *> (&Xx[iidx]),\n                                                  0,\n                                                  reinterpret_cast<const double *> (Bz),\n                                                  0, Numeric,\n                                                  control, info);\n#endif\n\n                  if (status < 0)\n                    {\n                      UMFPACK_ZNAME (report_status) (control, status);\n\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseComplexMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n                }\n\n              UMFPACK_ZNAME (report_info) (control, info);\n\n              UMFPACK_ZNAME (free_numeric) (&Numeric);\n            }\n          else\n            mattype.mark_as_rectangular ();\n\n#else\n          octave_unused_parameter (rcond);\n          octave_unused_parameter (sing_handler);\n          octave_unused_parameter (calc_cond);\n\n          (*current_liboctave_error_handler)\n            (\"support for UMFPACK was unavailable or disabled \"\n             \"when liboctave was built\");\n#endif\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::fsolve (MatrixType& mattype, const SparseMatrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Hermitian)\n        {\n#if defined (HAVE_CHOLMOD)\n          cholmod_common Common;\n          cholmod_common *cm = &Common;\n\n          // Setup initial parameters\n          CHOLMOD_NAME(start) (cm);\n          cm->prefer_zomplex = false;\n\n          double spu = octave::sparse_params::get_key (\"spumoni\");\n          if (spu == 0.)\n            {\n              cm->print = -1;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n            }\n          else\n            {\n              cm->print = static_cast<int> (spu) + 2;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);\n            }\n\n          cm->error_handler = &SparseCholError;\n          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);\n          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n          cm->final_ll = true;\n\n          cholmod_sparse Astore;\n          cholmod_sparse *A = &Astore;\n          A->nrow = nr;\n          A->ncol = nc;\n\n          A->p = const_cast<octave_idx_type *> (cidx ());\n          A->i = const_cast<octave_idx_type *> (ridx ());\n          A->nzmax = nnz ();\n          A->packed = true;\n          A->sorted = true;\n          A->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          A->itype = CHOLMOD_LONG;\n#else\n          A->itype = CHOLMOD_INT;\n#endif\n          A->dtype = CHOLMOD_DOUBLE;\n          A->stype = 1;\n          A->xtype = CHOLMOD_COMPLEX;\n\n          A->x = const_cast<Complex *> (data ());\n\n          cholmod_sparse Bstore;\n          cholmod_sparse *B = &Bstore;\n          B->nrow = b.rows ();\n          B->ncol = b.cols ();\n          B->p = const_cast<octave_idx_type *> (b.cidx ());\n          B->i = const_cast<octave_idx_type *> (b.ridx ());\n          B->nzmax = b.nnz ();\n          B->packed = true;\n          B->sorted = true;\n          B->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          B->itype = CHOLMOD_LONG;\n#else\n          B->itype = CHOLMOD_INT;\n#endif\n          B->dtype = CHOLMOD_DOUBLE;\n          B->stype = 0;\n          B->xtype = CHOLMOD_REAL;\n\n          B->x = const_cast<double *> (b.data ());\n\n          cholmod_factor *L = CHOLMOD_NAME(analyze) (A, cm);\n          CHOLMOD_NAME(factorize) (A, L, cm);\n          if (calc_cond)\n            rcond = CHOLMOD_NAME(rcond)(L, cm);\n          else\n            rcond = 1.;\n\n          if (rcond == 0.0)\n            {\n              // Either its indefinite or singular.  Try UMFPACK\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (is_singular (rcond) || octave::math::isnan (rcond))\n                {\n                  err = -2;\n\n                  if (sing_handler)\n                    {\n                      sing_handler (rcond);\n                      mattype.mark_as_rectangular ();\n                    }\n                  else\n                    octave::warn_singular_matrix (rcond);\n\n                  return retval;\n                }\n\n              cholmod_sparse *X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm);\n\n              retval = SparseComplexMatrix\n                       (octave::from_size_t (X->nrow),\n                        octave::from_size_t (X->ncol),\n                        octave::from_suitesparse_long (CHOLMOD_NAME(nnz)\n                                                       (X, cm)));\n              for (octave_idx_type j = 0;\n                   j <= static_cast<octave_idx_type> (X->ncol); j++)\n                retval.xcidx (j) = static_cast<octave_idx_type *> (X->p)[j];\n              for (octave_idx_type j = 0;\n                   j < octave::from_suitesparse_long (CHOLMOD_NAME(nnz) (X, cm));\n                   j++)\n                {\n                  retval.xridx (j) = static_cast<octave_idx_type *> (X->i)[j];\n                  retval.xdata (j) = static_cast<Complex *> (X->x)[j];\n                }\n\n              CHOLMOD_NAME(free_sparse) (&X, cm);\n              CHOLMOD_NAME(free_factor) (&L, cm);\n              CHOLMOD_NAME(finish) (cm);\n              static char blank_name[] = \" \";\n              CHOLMOD_NAME(print_common) (blank_name, cm);\n            }\n#else\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:missing-dependency\",\n             \"support for CHOLMOD was unavailable or disabled \"\n             \"when liboctave was built\");\n\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n#endif\n        }\n\n      if (typ == MatrixType::Full)\n        {\n#if defined (HAVE_UMFPACK)\n          Matrix Control, Info;\n          void *Numeric = factorize (err, rcond, Control, Info,\n                                     sing_handler, calc_cond);\n\n          if (err == 0)\n            {\n              // one iterative refinement instead of the default two in UMFPACK\n              Control (UMFPACK_IRSTEP) = 1;\n              octave_idx_type b_nr = b.rows ();\n              octave_idx_type b_nc = b.cols ();\n              int status = 0;\n              double *control = Control.rwdata ();\n              double *info = Info.rwdata ();\n              const octave_idx_type *Ap = cidx ();\n              const octave_idx_type *Ai = ridx ();\n              const Complex *Ax = data ();\n\n#if defined (UMFPACK_SEPARATE_SPLIT)\n              OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);\n              OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);\n              for (octave_idx_type i = 0; i < b_nr; i++)\n                Bz[i] = 0.;\n#else\n              OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr);\n#endif\n\n              // Take a first guess that the number of nonzero terms\n              // will be as many as in b\n              octave_idx_type x_nz = b.nnz ();\n              octave_idx_type ii = 0;\n              retval = SparseComplexMatrix (b_nr, b_nc, x_nz);\n\n              OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);\n\n              retval.xcidx (0) = 0;\n              for (octave_idx_type j = 0; j < b_nc; j++)\n                {\n\n#if defined (UMFPACK_SEPARATE_SPLIT)\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    Bx[i] = b.elem (i, j);\n\n                  status = UMFPACK_ZNAME (solve) (UMFPACK_A,\n                                                  octave::to_suitesparse_intptr (Ap),\n                                                  octave::to_suitesparse_intptr (Ai),\n                                                  reinterpret_cast<const double *> (Ax),\n                                                  nullptr,\n                                                  reinterpret_cast<double *> (Xx),\n                                                  nullptr,\n                                                  Bx, Bz, Numeric, control,\n                                                  info);\n#else\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    Bz[i] = b.elem (i, j);\n\n                  status = UMFPACK_ZNAME (solve) (UMFPACK_A,\n                                                  octave::to_suitesparse_intptr (Ap),\n                                                  octave::to_suitesparse_intptr (Ai),\n                                                  reinterpret_cast<const double *> (Ax),\n                                                  0,\n                                                  reinterpret_cast<double *> (Xx),\n                                                  0,\n                                                  reinterpret_cast<double *> (Bz),\n                                                  0,\n                                                  Numeric, control,\n                                                  info);\n#endif\n                  if (status < 0)\n                    {\n                      UMFPACK_ZNAME (report_status) (control, status);\n\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseComplexMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    {\n                      Complex tmp = Xx[i];\n                      if (tmp != 0.0)\n                        {\n                          if (ii == x_nz)\n                            {\n                              // Resize the sparse matrix\n                              octave_idx_type sz;\n                              sz = (static_cast<double> (b_nc) - j) / b_nc\n                                   * x_nz;\n                              sz = x_nz + (sz > 100 ? sz : 100);\n                              retval.change_capacity (sz);\n                              x_nz = sz;\n                            }\n                          retval.xdata (ii) = tmp;\n                          retval.xridx (ii++) = i;\n                        }\n                    }\n                  retval.xcidx (j+1) = ii;\n                }\n\n              retval.maybe_compress ();\n\n              UMFPACK_ZNAME (report_info) (control, info);\n\n              UMFPACK_ZNAME (free_numeric) (&Numeric);\n            }\n          else\n            mattype.mark_as_rectangular ();\n\n#else\n          octave_unused_parameter (rcond);\n          octave_unused_parameter (sing_handler);\n          octave_unused_parameter (calc_cond);\n\n          (*current_liboctave_error_handler)\n            (\"support for UMFPACK was unavailable or disabled \"\n             \"when liboctave was built\");\n#endif\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::fsolve (MatrixType& mattype, const ComplexMatrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Hermitian)\n        {\n#if defined (HAVE_CHOLMOD)\n          cholmod_common Common;\n          cholmod_common *cm = &Common;\n\n          // Setup initial parameters\n          CHOLMOD_NAME(start) (cm);\n          cm->prefer_zomplex = false;\n\n          double spu = octave::sparse_params::get_key (\"spumoni\");\n          if (spu == 0.)\n            {\n              cm->print = -1;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n            }\n          else\n            {\n              cm->print = static_cast<int> (spu) + 2;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);\n            }\n\n          cm->error_handler = &SparseCholError;\n          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);\n          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n          cm->final_ll = true;\n\n          cholmod_sparse Astore;\n          cholmod_sparse *A = &Astore;\n          A->nrow = nr;\n          A->ncol = nc;\n\n          A->p = const_cast<octave_idx_type *> (cidx ());\n          A->i = const_cast<octave_idx_type *> (ridx ());\n          A->nzmax = nnz ();\n          A->packed = true;\n          A->sorted = true;\n          A->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          A->itype = CHOLMOD_LONG;\n#else\n          A->itype = CHOLMOD_INT;\n#endif\n          A->dtype = CHOLMOD_DOUBLE;\n          A->stype = 1;\n          A->xtype = CHOLMOD_COMPLEX;\n\n          A->x = const_cast<Complex *> (data ());\n\n          cholmod_dense Bstore;\n          cholmod_dense *B = &Bstore;\n          B->nrow = b.rows ();\n          B->ncol = b.cols ();\n          B->d = B->nrow;\n          B->nzmax = B->nrow * B->ncol;\n          B->dtype = CHOLMOD_DOUBLE;\n          B->xtype = CHOLMOD_COMPLEX;\n\n          B->x = const_cast<Complex *> (b.data ());\n\n          cholmod_factor *L = CHOLMOD_NAME(analyze) (A, cm);\n          CHOLMOD_NAME(factorize) (A, L, cm);\n          if (calc_cond)\n            rcond = CHOLMOD_NAME(rcond)(L, cm);\n          else\n            rcond = 1.;\n\n          if (rcond == 0.0)\n            {\n              // Either its indefinite or singular.  Try UMFPACK\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (is_singular (rcond) || octave::math::isnan (rcond))\n                {\n                  err = -2;\n\n                  if (sing_handler)\n                    {\n                      sing_handler (rcond);\n                      mattype.mark_as_rectangular ();\n                    }\n                  else\n                    octave::warn_singular_matrix (rcond);\n\n                  return retval;\n                }\n\n              cholmod_dense *X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm);\n\n              retval.resize (b.rows (), b.cols ());\n              for (octave_idx_type j = 0; j < b.cols (); j++)\n                {\n                  octave_idx_type jr = j * b.rows ();\n                  for (octave_idx_type i = 0; i < b.rows (); i++)\n                    retval.xelem (i, j) = static_cast<Complex *> (X->x)[jr + i];\n                }\n\n              CHOLMOD_NAME(free_dense) (&X, cm);\n              CHOLMOD_NAME(free_factor) (&L, cm);\n              CHOLMOD_NAME(finish) (cm);\n              static char blank_name[] = \" \";\n              CHOLMOD_NAME(print_common) (blank_name, cm);\n            }\n#else\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:missing-dependency\",\n             \"support for CHOLMOD was unavailable or disabled \"\n             \"when liboctave was built\");\n\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n#endif\n        }\n\n      if (typ == MatrixType::Full)\n        {\n#if defined (HAVE_UMFPACK)\n          Matrix Control, Info;\n          void *Numeric = factorize (err, rcond, Control, Info,\n                                     sing_handler, calc_cond);\n\n          if (err == 0)\n            {\n              // one iterative refinement instead of the default two in UMFPACK\n              Control (UMFPACK_IRSTEP) = 1;\n              octave_idx_type b_nr = b.rows ();\n              octave_idx_type b_nc = b.cols ();\n              int status = 0;\n              double *control = Control.rwdata ();\n              double *info = Info.rwdata ();\n              const octave_idx_type *Ap = cidx ();\n              const octave_idx_type *Ai = ridx ();\n              const Complex *Ax = data ();\n              const Complex *Bx = b.data ();\n\n              retval.resize (b_nr, b_nc);\n              Complex *Xx = retval.rwdata ();\n\n              for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr)\n                {\n                  status\n                    = UMFPACK_ZNAME (solve) (UMFPACK_A,\n                                             octave::to_suitesparse_intptr (Ap),\n                                             octave::to_suitesparse_intptr (Ai),\n                                             reinterpret_cast<const double *> (Ax),\n                                             nullptr,\n                                             reinterpret_cast<double *> (&Xx[iidx]),\n                                             nullptr,\n                                             reinterpret_cast<const double *> (&Bx[iidx]),\n                                             nullptr, Numeric, control, info);\n\n                  if (status < 0)\n                    {\n                      UMFPACK_ZNAME (report_status) (control, status);\n\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseComplexMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n                }\n\n              UMFPACK_ZNAME (report_info) (control, info);\n\n              UMFPACK_ZNAME (free_numeric) (&Numeric);\n            }\n          else\n            mattype.mark_as_rectangular ();\n\n#else\n          octave_unused_parameter (rcond);\n          octave_unused_parameter (sing_handler);\n          octave_unused_parameter (calc_cond);\n\n          (*current_liboctave_error_handler)\n            (\"support for UMFPACK was unavailable or disabled \"\n             \"when liboctave was built\");\n#endif\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::fsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                             octave_idx_type& err, double& rcond,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Hermitian)\n        {\n#if defined (HAVE_CHOLMOD)\n          cholmod_common Common;\n          cholmod_common *cm = &Common;\n\n          // Setup initial parameters\n          CHOLMOD_NAME(start) (cm);\n          cm->prefer_zomplex = false;\n\n          double spu = octave::sparse_params::get_key (\"spumoni\");\n          if (spu == 0.)\n            {\n              cm->print = -1;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n            }\n          else\n            {\n              cm->print = static_cast<int> (spu) + 2;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);\n            }\n\n          cm->error_handler = &SparseCholError;\n          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);\n          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n          cm->final_ll = true;\n\n          cholmod_sparse Astore;\n          cholmod_sparse *A = &Astore;\n          A->nrow = nr;\n          A->ncol = nc;\n\n          A->p = const_cast<octave_idx_type *> (cidx ());\n          A->i = const_cast<octave_idx_type *> (ridx ());\n          A->nzmax = nnz ();\n          A->packed = true;\n          A->sorted = true;\n          A->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          A->itype = CHOLMOD_LONG;\n#else\n          A->itype = CHOLMOD_INT;\n#endif\n          A->dtype = CHOLMOD_DOUBLE;\n          A->stype = 1;\n          A->xtype = CHOLMOD_COMPLEX;\n\n          A->x = const_cast<Complex *> (data ());\n\n          cholmod_sparse Bstore;\n          cholmod_sparse *B = &Bstore;\n          B->nrow = b.rows ();\n          B->ncol = b.cols ();\n          B->p = const_cast<octave_idx_type *> (b.cidx ());\n          B->i = const_cast<octave_idx_type *> (b.ridx ());\n          B->nzmax = b.nnz ();\n          B->packed = true;\n          B->sorted = true;\n          B->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          B->itype = CHOLMOD_LONG;\n#else\n          B->itype = CHOLMOD_INT;\n#endif\n          B->dtype = CHOLMOD_DOUBLE;\n          B->stype = 0;\n          B->xtype = CHOLMOD_COMPLEX;\n\n          B->x = const_cast<Complex *> (b.data ());\n\n          cholmod_factor *L = CHOLMOD_NAME(analyze) (A, cm);\n          CHOLMOD_NAME(factorize) (A, L, cm);\n          if (calc_cond)\n            rcond = CHOLMOD_NAME(rcond)(L, cm);\n          else\n            rcond = 1.;\n\n          if (rcond == 0.0)\n            {\n              // Either its indefinite or singular.  Try UMFPACK\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (is_singular (rcond) || octave::math::isnan (rcond))\n                {\n                  err = -2;\n\n                  if (sing_handler)\n                    {\n                      sing_handler (rcond);\n                      mattype.mark_as_rectangular ();\n                    }\n                  else\n                    octave::warn_singular_matrix (rcond);\n\n                  return retval;\n                }\n\n              cholmod_sparse *X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm);\n\n              retval = SparseComplexMatrix\n                       (octave::from_size_t (X->nrow),\n                        octave::from_size_t (X->ncol),\n                        octave::from_suitesparse_long (CHOLMOD_NAME(nnz)\n                                                       (X, cm)));\n              for (octave_idx_type j = 0;\n                   j <= static_cast<octave_idx_type> (X->ncol); j++)\n                retval.xcidx (j) = static_cast<octave_idx_type *> (X->p)[j];\n              for (octave_idx_type j = 0;\n                   j < octave::from_suitesparse_long (CHOLMOD_NAME(nnz) (X, cm));\n                   j++)\n                {\n                  retval.xridx (j) = static_cast<octave_idx_type *> (X->i)[j];\n                  retval.xdata (j) = static_cast<Complex *> (X->x)[j];\n                }\n\n              CHOLMOD_NAME(free_sparse) (&X, cm);\n              CHOLMOD_NAME(free_factor) (&L, cm);\n              CHOLMOD_NAME(finish) (cm);\n              static char blank_name[] = \" \";\n              CHOLMOD_NAME(print_common) (blank_name, cm);\n            }\n#else\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:missing-dependency\",\n             \"support for CHOLMOD was unavailable or disabled \"\n             \"when liboctave was built\");\n\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n#endif\n        }\n\n      if (typ == MatrixType::Full)\n        {\n#if defined (HAVE_UMFPACK)\n          Matrix Control, Info;\n          void *Numeric = factorize (err, rcond, Control, Info,\n                                     sing_handler, calc_cond);\n\n          if (err == 0)\n            {\n              // one iterative refinement instead of the default two in UMFPACK\n              Control (UMFPACK_IRSTEP) = 1;\n              octave_idx_type b_nr = b.rows ();\n              octave_idx_type b_nc = b.cols ();\n              int status = 0;\n              double *control = Control.rwdata ();\n              double *info = Info.rwdata ();\n              const octave_idx_type *Ap = cidx ();\n              const octave_idx_type *Ai = ridx ();\n              const Complex *Ax = data ();\n\n              OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);\n\n              // Take a first guess that the number of nonzero terms\n              // will be as many as in b\n              octave_idx_type x_nz = b.nnz ();\n              octave_idx_type ii = 0;\n              retval = SparseComplexMatrix (b_nr, b_nc, x_nz);\n\n              OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);\n\n              retval.xcidx (0) = 0;\n              for (octave_idx_type j = 0; j < b_nc; j++)\n                {\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    Bx[i] = b(i, j);\n\n                  status = UMFPACK_ZNAME (solve) (UMFPACK_A,\n                                                  octave::to_suitesparse_intptr (Ap),\n                                                  octave::to_suitesparse_intptr (Ai),\n                                                  reinterpret_cast<const double *> (Ax),\n                                                  nullptr,\n                                                  reinterpret_cast<double *> (Xx),\n                                                  nullptr,\n                                                  reinterpret_cast<double *> (Bx),\n                                                  nullptr, Numeric, control, info);\n\n                  if (status < 0)\n                    {\n                      UMFPACK_ZNAME (report_status) (control, status);\n\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseComplexMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    {\n                      Complex tmp = Xx[i];\n                      if (tmp != 0.0)\n                        {\n                          if (ii == x_nz)\n                            {\n                              // Resize the sparse matrix\n                              octave_idx_type sz;\n                              sz = (static_cast<double> (b_nc) - j) / b_nc\n                                   * x_nz;\n                              sz = x_nz + (sz > 100 ? sz : 100);\n                              retval.change_capacity (sz);\n                              x_nz = sz;\n                            }\n                          retval.xdata (ii) = tmp;\n                          retval.xridx (ii++) = i;\n                        }\n                    }\n                  retval.xcidx (j+1) = ii;\n                }\n\n              retval.maybe_compress ();\n\n              rcond = Info (UMFPACK_RCOND);\n              if (status == UMFPACK_WARNING_singular_matrix\n                  || is_singular (rcond) || octave::math::isnan (rcond))\n                {\n                  err = -2;\n\n                  if (sing_handler)\n                    sing_handler (rcond);\n                  else\n                    octave::warn_singular_matrix (rcond);\n                }\n\n              UMFPACK_ZNAME (report_info) (control, info);\n\n              UMFPACK_ZNAME (free_numeric) (&Numeric);\n            }\n          else\n            mattype.mark_as_rectangular ();\n\n#else\n          octave_unused_parameter (rcond);\n          octave_unused_parameter (sing_handler);\n          octave_unused_parameter (calc_cond);\n\n          (*current_liboctave_error_handler)\n            (\"support for UMFPACK was unavailable or disabled \"\n             \"when liboctave was built\");\n#endif\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const Matrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const Matrix& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const Matrix& b,\n                            octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const Matrix& b,\n                            octave_idx_type& err, double& rcond,\n                            solve_singularity_handler sing_handler,\n                            bool singular_fallback) const\n{\n  ComplexMatrix retval;\n  int typ = mattype.type (false);\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    retval = dsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)\n    retval = bsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Tridiagonal\n           || typ == MatrixType::Tridiagonal_Hermitian)\n    retval = trisolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, err, rcond, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)\n    {\n      rcond = 1.;\n      retval = dmsolve<ComplexMatrix, SparseComplexMatrix, Matrix>\n               (*this, b, err);\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const SparseMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const SparseMatrix& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const SparseMatrix& b,\n                            octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const SparseMatrix& b,\n                            octave_idx_type& err, double& rcond,\n                            solve_singularity_handler sing_handler,\n                            bool singular_fallback) const\n{\n  SparseComplexMatrix retval;\n  int typ = mattype.type (false);\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    retval = dsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)\n    retval = bsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Tridiagonal\n           || typ == MatrixType::Tridiagonal_Hermitian)\n    retval = trisolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, err, rcond, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)\n    {\n      rcond = 1.;\n      retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix, SparseMatrix>\n               (*this, b, err);\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const ComplexMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n                            octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n                            octave_idx_type& err, double& rcond,\n                            solve_singularity_handler sing_handler,\n                            bool singular_fallback) const\n{\n  ComplexMatrix retval;\n  int typ = mattype.type (false);\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    retval = dsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)\n    retval = bsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Tridiagonal\n           || typ == MatrixType::Tridiagonal_Hermitian)\n    retval = trisolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, err, rcond, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)\n    {\n      rcond = 1.;\n      retval = dmsolve<ComplexMatrix, SparseComplexMatrix, ComplexMatrix>\n               (*this, b, err);\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype,\n                            const SparseComplexMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const SparseComplexMatrix& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const SparseComplexMatrix& b,\n                            octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (MatrixType& mattype, const SparseComplexMatrix& b,\n                            octave_idx_type& err, double& rcond,\n                            solve_singularity_handler sing_handler,\n                            bool singular_fallback) const\n{\n  SparseComplexMatrix retval;\n  int typ = mattype.type (false);\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    retval = dsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)\n    retval = bsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Tridiagonal\n           || typ == MatrixType::Tridiagonal_Hermitian)\n    retval = trisolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, err, rcond, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)\n    {\n      rcond = 1.;\n      retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix,\n      SparseComplexMatrix> (*this, b, err);\n    }\n\n  return retval;\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (MatrixType& mattype, const ColumnVector& b) const\n{\n  octave_idx_type info; double rcond;\n  return solve (mattype, b, info, rcond);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n                            octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n                            octave_idx_type& info, double& rcond,\n                            solve_singularity_handler sing_handler) const\n{\n  Matrix tmp (b);\n  return solve (mattype, tmp, info, rcond,\n                sing_handler).column (static_cast<octave_idx_type> (0));\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (MatrixType& mattype,\n                            const ComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n                            octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n                            octave_idx_type& info, double& rcond,\n                            solve_singularity_handler sing_handler) const\n{\n  ComplexMatrix tmp (b);\n  return solve (mattype, tmp, info, rcond,\n                sing_handler).column (static_cast<octave_idx_type> (0));\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (const Matrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (const Matrix& b, octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (const Matrix& b, octave_idx_type& info,\n                            double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (const Matrix& b, octave_idx_type& err,\n                            double& rcond,\n                            solve_singularity_handler sing_handler) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, err, rcond, sing_handler);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (const SparseMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (const SparseMatrix& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (const SparseMatrix& b,\n                            octave_idx_type& info, double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (const SparseMatrix& b,\n                            octave_idx_type& err, double& rcond,\n                            solve_singularity_handler sing_handler) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, err, rcond, sing_handler);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (const ComplexMatrix& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (const ComplexMatrix& b,\n                            octave_idx_type& info, double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseComplexMatrix::solve (const ComplexMatrix& b,\n                            octave_idx_type& err, double& rcond,\n                            solve_singularity_handler sing_handler) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, err, rcond, sing_handler);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (const SparseComplexMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (const SparseComplexMatrix& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (const SparseComplexMatrix& b,\n                            octave_idx_type& info, double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::solve (const SparseComplexMatrix& b,\n                            octave_idx_type& err, double& rcond,\n                            solve_singularity_handler sing_handler) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, err, rcond, sing_handler);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (const ColumnVector& b) const\n{\n  octave_idx_type info; double rcond;\n  return solve (b, info, rcond);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info,\n                            double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info,\n                            double& rcond,\n                            solve_singularity_handler sing_handler) const\n{\n  Matrix tmp (b);\n  return solve (tmp, info, rcond,\n                sing_handler).column (static_cast<octave_idx_type> (0));\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (const ComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (const ComplexColumnVector& b,\n                            octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,\n                            double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,\n                            double& rcond,\n                            solve_singularity_handler sing_handler) const\n{\n  ComplexMatrix tmp (b);\n  return solve (tmp, info, rcond,\n                sing_handler).column (static_cast<octave_idx_type> (0));\n}\n\n// unary operations\nSparseBoolMatrix\nSparseComplexMatrix::operator ! () const\n{\n  if (any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz1 = nnz ();\n  octave_idx_type nz2 = nr*nc - nz1;\n\n  SparseBoolMatrix r (nr, nc, nz2);\n\n  octave_idx_type ii = 0;\n  octave_idx_type jj = 0;\n  r.cidx (0) = 0;\n  for (octave_idx_type i = 0; i < nc; i++)\n    {\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          if (jj < cidx (i+1) && ridx (jj) == j)\n            jj++;\n          else\n            {\n              r.data (ii) = true;\n              r.ridx (ii++) = j;\n            }\n        }\n      r.cidx (i+1) = ii;\n    }\n\n  return r;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::squeeze () const\n{\n  return MSparse<Complex>::squeeze ();\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::reshape (const dim_vector& new_dims) const\n{\n  return MSparse<Complex>::reshape (new_dims);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::permute (const Array<octave_idx_type>& vec, bool inv) const\n{\n  return MSparse<Complex>::permute (vec, inv);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::ipermute (const Array<octave_idx_type>& vec) const\n{\n  return MSparse<Complex>::ipermute (vec);\n}\n\n// other operations\n\nbool\nSparseComplexMatrix::any_element_is_nan () const\n{\n  octave_idx_type nel = nnz ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      Complex val = data (i);\n      if (octave::math::isnan (val))\n        return true;\n    }\n\n  return false;\n}\n\nbool\nSparseComplexMatrix::any_element_is_inf_or_nan () const\n{\n  octave_idx_type nel = nnz ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      Complex val = data (i);\n      if (octave::math::isinf (val) || octave::math::isnan (val))\n        return true;\n    }\n\n  return false;\n}\n\n// Return true if no elements have imaginary components.\n\nbool\nSparseComplexMatrix::all_elements_are_real () const\n{\n  return mx_inline_all_real (nnz (), data ());\n}\n\n// Return nonzero if any element of CM has a non-integer real or\n// imaginary part.  Also extract the largest and smallest (real or\n// imaginary) values and return them in MAX_VAL and MIN_VAL.\n\nbool\nSparseComplexMatrix::all_integers (double& max_val, double& min_val) const\n{\n  octave_idx_type nel = nnz ();\n\n  if (nel == 0)\n    return false;\n\n  max_val = std::real (data (0));\n  min_val = std::real (data (0));\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      Complex val = data (i);\n\n      double r_val = val.real ();\n      double i_val = val.imag ();\n\n      if (r_val > max_val)\n        max_val = r_val;\n\n      if (i_val > max_val)\n        max_val = i_val;\n\n      if (r_val < min_val)\n        min_val = r_val;\n\n      if (i_val < min_val)\n        min_val = i_val;\n\n      if (octave::math::round (r_val) != r_val\n          || octave::math::round (i_val) != i_val)\n        return false;\n    }\n\n  return true;\n}\n\nbool\nSparseComplexMatrix::too_large_for_float () const\n{\n  return test_any (octave::too_large_for_float);\n}\n\n// FIXME: Do these really belong here?  Maybe they should be in a base class?\n\nSparseBoolMatrix\nSparseComplexMatrix::all (int dim) const\n{\n  SPARSE_ANY_ALL_HEADER\n  SPARSE_ALL_OP (dim);\n}\n\nSparseBoolMatrix\nSparseComplexMatrix::any (int dim) const\n{\n  SPARSE_ANY_ALL_HEADER\n  SPARSE_ANY_OP (dim);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::cumprod (int dim, bool nanflag) const\n{\n  if (dim > 1)\n    return *this;\n  SPARSE_CUMPROD (SparseComplexMatrix, Complex, cumprod);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::cumsum (int dim, bool nanflag) const\n{\n#define NAN_EXPR                           \\\n  if (! octave::math::isnan (data (j)))    \\\n    t += data (j);                         \\\n  else                                     \\\n    t += 0.0\n\n#define EXPR                               \\\n  t += data (j)\n\n  if (dim > 1)\n    return *this;\n  SPARSE_CUMSUM (SparseComplexMatrix, Complex, cumsum, NAN_EXPR, EXPR);\n\n#undef NAN_EXPR\n#undef EXPR\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::prod (int dim, bool nanflag) const\n{\n  if (dim > 1)\n    return *this;\n  else if ((rows () == 1 && dim == -1) || dim == 1)\n    return transpose ().prod (0, nanflag).transpose ();\n  else\n    {\n    #define ROW_EXPR                           \\\n      Complex d = data (i);                    \\\n      if (nanflag && octave::math::isnan (d))  \\\n        tmp[ridx (i)] *= 1.0;                  \\\n      else                                     \\\n        tmp[ridx (i)] *= d\n\n    #define COL_EXPR                           \\\n      Complex d = data (i);                    \\\n      if (nanflag && octave::math::isnan (d))  \\\n        tmp[j] *= 1.0;                         \\\n      else                                     \\\n        tmp[j] *= d\n\n      SPARSE_BASE_REDUCTION_OP (SparseComplexMatrix, Complex, ROW_EXPR,\n                                COL_EXPR,\n                                (cidx (j+1) - cidx (j) < nr ? 0.0 : 1.0), 1.0);\n\n    #undef ROW_EXPR\n    #undef COL_EXPR\n    }\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::sum (int dim, bool nanflag) const\n{\n#define ROW_EXPR                           \\\n  Complex d = data (i);                    \\\n  if (nanflag && octave::math::isnan (d))  \\\n    tmp[ridx (i)] += 0.0;                  \\\n  else                                     \\\n    tmp[ridx (i)] += d\n\n#define COL_EXPR                           \\\n  Complex d = data (i);                    \\\n  if (nanflag && octave::math::isnan (d))  \\\n    tmp[j] += 0.0;                         \\\n  else                                     \\\n    tmp[j] += d\n\n  if (dim > 1)\n    return *this;\n  SPARSE_BASE_REDUCTION_OP (SparseComplexMatrix, Complex, ROW_EXPR,\n                            COL_EXPR, 0.0, 0.0);\n\n#undef ROW_EXPR\n#undef COL_EXPR\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::xsum (int dim, bool nanflag) const\n{\n  if (dim > 1)\n    return *this;\n  SPARSE_XSUM_REDUCTION_OP (SparseComplexMatrix, Complex);\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::sumsq (int dim, bool nanflag) const\n{\n#define EXPR r.data (nel++) = data (i) * conj (data (i));\n\n#define ROW_EXPR                           \\\n  Complex d = data (i);                    \\\n  if (nanflag && octave::math::isnan (d))  \\\n    tmp[ridx (i)] += 0.0;                  \\\n  else                                     \\\n    tmp[ridx (i)] += d * conj (d)\n\n#define COL_EXPR                           \\\n  Complex d = data (i);                    \\\n  if (nanflag && octave::math::isnan (d))  \\\n    tmp[j] += 0.0;                         \\\n  else                                     \\\n    tmp[j] += d * conj (d)\n\n  SPARSE_SUMSQ_HEADER (SparseComplexMatrix, EXPR)\n  SPARSE_BASE_REDUCTION_OP (SparseComplexMatrix, Complex, ROW_EXPR,\n                            COL_EXPR, 0.0, 0.0);\n\n#undef EXPR\n#undef ROW_EXPR\n#undef COL_EXPR\n}\n\nSparseMatrix\nSparseComplexMatrix::abs () const\n{\n  octave_idx_type nz = nnz ();\n  octave_idx_type nc = cols ();\n\n  SparseMatrix retval (rows (), nc, nz);\n\n  for (octave_idx_type i = 0; i < nc + 1; i++)\n    retval.cidx (i) = cidx (i);\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    {\n      retval.data (i) = std::abs (data (i));\n      retval.ridx (i) = ridx (i);\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseComplexMatrix::diag (octave_idx_type k) const\n{\n  return MSparse<Complex>::diag (k);\n}\n\nstd::ostream&\noperator << (std::ostream& os, const SparseComplexMatrix& a)\n{\n  octave_idx_type nc = a.cols ();\n\n  // add one to the printed indices to go from\n  //  zero-based to one-based arrays\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      octave_quit ();\n      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n        {\n          os << a.ridx (i) + 1 << ' '  << j + 1 << ' ';\n          octave::write_value<Complex> (os, a.data (i));\n          os << \"\\n\";\n        }\n    }\n\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, SparseComplexMatrix& a)\n{\n  typedef SparseComplexMatrix::element_type elt_type;\n\n  return read_sparse_matrix<elt_type> (is, a, octave::read_value<Complex>);\n}\n\nSparseComplexMatrix\noperator * (const SparseComplexMatrix& m, const SparseMatrix& a)\n{\n  SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, double);\n}\n\nSparseComplexMatrix\noperator * (const SparseMatrix& m, const SparseComplexMatrix& a)\n{\n  SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, Complex);\n}\n\nSparseComplexMatrix\noperator * (const SparseComplexMatrix& m, const SparseComplexMatrix& a)\n{\n  SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, Complex);\n}\n\nComplexMatrix\noperator * (const ComplexMatrix& m, const SparseMatrix& a)\n{\n  FULL_SPARSE_MUL (ComplexMatrix, double);\n}\n\nComplexMatrix\noperator * (const Matrix& m, const SparseComplexMatrix& a)\n{\n  FULL_SPARSE_MUL (ComplexMatrix, Complex);\n}\n\nComplexMatrix\noperator * (const ComplexMatrix& m, const SparseComplexMatrix& a)\n{\n  FULL_SPARSE_MUL (ComplexMatrix, Complex);\n}\n\nComplexMatrix\nmul_trans (const ComplexMatrix& m, const SparseComplexMatrix& a)\n{\n  FULL_SPARSE_MUL_TRANS (ComplexMatrix, Complex, );\n}\n\nComplexMatrix\nmul_herm (const ComplexMatrix& m, const SparseComplexMatrix& a)\n{\n  FULL_SPARSE_MUL_TRANS (ComplexMatrix, Complex, conj);\n}\n\nComplexMatrix\noperator * (const SparseComplexMatrix& m, const Matrix& a)\n{\n  SPARSE_FULL_MUL (ComplexMatrix, double);\n}\n\nComplexMatrix\noperator * (const SparseMatrix& m, const ComplexMatrix& a)\n{\n  SPARSE_FULL_MUL (ComplexMatrix, Complex);\n}\n\nComplexMatrix\noperator * (const SparseComplexMatrix& m, const ComplexMatrix& a)\n{\n  SPARSE_FULL_MUL (ComplexMatrix, Complex);\n}\n\nComplexMatrix\ntrans_mul (const SparseComplexMatrix& m, const ComplexMatrix& a)\n{\n  SPARSE_FULL_TRANS_MUL (ComplexMatrix, Complex, );\n}\n\nComplexMatrix\nherm_mul (const SparseComplexMatrix& m, const ComplexMatrix& a)\n{\n  SPARSE_FULL_TRANS_MUL (ComplexMatrix, Complex, conj);\n}\n\n// diag * sparse and sparse * diag\nSparseComplexMatrix\noperator * (const DiagMatrix& d, const SparseComplexMatrix& a)\n{\n  return do_mul_dm_sm<SparseComplexMatrix> (d, a);\n}\nSparseComplexMatrix\noperator * (const SparseComplexMatrix& a, const DiagMatrix& d)\n{\n  return do_mul_sm_dm<SparseComplexMatrix> (a, d);\n}\n\nSparseComplexMatrix\noperator * (const ComplexDiagMatrix& d, const SparseMatrix& a)\n{\n  return do_mul_dm_sm<SparseComplexMatrix> (d, a);\n}\nSparseComplexMatrix\noperator * (const SparseMatrix& a, const ComplexDiagMatrix& d)\n{\n  return do_mul_sm_dm<SparseComplexMatrix> (a, d);\n}\n\nSparseComplexMatrix\noperator * (const ComplexDiagMatrix& d, const SparseComplexMatrix& a)\n{\n  return do_mul_dm_sm<SparseComplexMatrix> (d, a);\n}\nSparseComplexMatrix\noperator * (const SparseComplexMatrix& a, const ComplexDiagMatrix& d)\n{\n  return do_mul_sm_dm<SparseComplexMatrix> (a, d);\n}\n\nSparseComplexMatrix\noperator + (const ComplexDiagMatrix& d, const SparseMatrix& a)\n{\n  return do_add_dm_sm<SparseComplexMatrix> (d, a);\n}\nSparseComplexMatrix\noperator + (const DiagMatrix& d, const SparseComplexMatrix& a)\n{\n  return do_add_dm_sm<SparseComplexMatrix> (d, a);\n}\nSparseComplexMatrix\noperator + (const ComplexDiagMatrix& d, const SparseComplexMatrix& a)\n{\n  return do_add_dm_sm<SparseComplexMatrix> (d, a);\n}\nSparseComplexMatrix\noperator + (const SparseMatrix& a, const ComplexDiagMatrix& d)\n{\n  return do_add_sm_dm<SparseComplexMatrix> (a, d);\n}\nSparseComplexMatrix\noperator + (const SparseComplexMatrix& a, const DiagMatrix& d)\n{\n  return do_add_sm_dm<SparseComplexMatrix> (a, d);\n}\nSparseComplexMatrix\noperator + (const SparseComplexMatrix& a, const ComplexDiagMatrix& d)\n{\n  return do_add_sm_dm<SparseComplexMatrix> (a, d);\n}\n\nSparseComplexMatrix\noperator - (const ComplexDiagMatrix& d, const SparseMatrix& a)\n{\n  return do_sub_dm_sm<SparseComplexMatrix> (d, a);\n}\nSparseComplexMatrix\noperator - (const DiagMatrix& d, const SparseComplexMatrix& a)\n{\n  return do_sub_dm_sm<SparseComplexMatrix> (d, a);\n}\nSparseComplexMatrix\noperator - (const ComplexDiagMatrix& d, const SparseComplexMatrix& a)\n{\n  return do_sub_dm_sm<SparseComplexMatrix> (d, a);\n}\nSparseComplexMatrix\noperator - (const SparseMatrix& a, const ComplexDiagMatrix& d)\n{\n  return do_sub_sm_dm<SparseComplexMatrix> (a, d);\n}\nSparseComplexMatrix\noperator - (const SparseComplexMatrix& a, const DiagMatrix& d)\n{\n  return do_sub_sm_dm<SparseComplexMatrix> (a, d);\n}\nSparseComplexMatrix\noperator - (const SparseComplexMatrix& a, const ComplexDiagMatrix& d)\n{\n  return do_sub_sm_dm<SparseComplexMatrix> (a, d);\n}\n\n// perm * sparse and sparse * perm\n\nSparseComplexMatrix\noperator * (const PermMatrix& p, const SparseComplexMatrix& a)\n{\n  return octinternal_do_mul_pm_sm (p, a);\n}\n\nSparseComplexMatrix\noperator * (const SparseComplexMatrix& a, const PermMatrix& p)\n{\n  return octinternal_do_mul_sm_pm (a, p);\n}\n\n// FIXME: it would be nice to share code among the min/max functions below.\n\n#define EMPTY_RETURN_CHECK(T)                   \\\n  if (nr == 0 || nc == 0)                       \\\n    return T (nr, nc);\n\nSparseComplexMatrix\nmin (const Complex& c, const SparseComplexMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmin (const Complex& c, const SparseComplexMatrix& m, const bool nanflag)\n{\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmin (const Complex& c, const SparseComplexMatrix& m,\n     const bool nanflag, const bool realabs)\n{\n  SparseComplexMatrix result;\n\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (SparseComplexMatrix);\n\n  if (abs (c) == 0.)\n    return SparseComplexMatrix (nr, nc);\n  else\n    {\n      result = SparseComplexMatrix (m);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n          result.data (i) = octave::math::min (c, m.data (i), nanflag, realabs);\n    }\n\n  return result;\n}\n\nSparseComplexMatrix\nmin (const SparseComplexMatrix& m, const Complex& c)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmin (const SparseComplexMatrix& m, const Complex& c, const bool nanflag)\n{\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmin (const SparseComplexMatrix& m, const Complex& c,\n     const bool nanflag, const bool realabs)\n{\n  return min (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmin (const SparseComplexMatrix& a, const SparseComplexMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return min (a, b, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmin (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n     const bool nanflag)\n{\n  const bool realabs = false;\n  return min (a, b, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmin (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n     const bool nanflag, const bool realabs)\n{\n  SparseComplexMatrix r;\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nr == b_nr && a_nc == b_nc)\n    {\n      r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));\n\n      octave_idx_type jx = 0;\n      r.cidx (0) = 0;\n      for (octave_idx_type i = 0 ; i < a_nc ; i++)\n        {\n          octave_idx_type ja = a.cidx (i);\n          octave_idx_type ja_max = a.cidx (i+1);\n          bool ja_lt_max = ja < ja_max;\n\n          octave_idx_type jb = b.cidx (i);\n          octave_idx_type jb_max = b.cidx (i+1);\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  Complex tmp = octave::math::min (a.data (ja), 0.,\n                                                   nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.ridx (jx) = a.ridx (ja);\n                      r.data (jx) = tmp;\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                }\n              else if ((! ja_lt_max)\n                       || (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))\n                {\n                  Complex tmp = octave::math::min (0., b.data (jb),\n                                                   nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.ridx (jx) = b.ridx (jb);\n                      r.data (jx) = tmp;\n                      jx++;\n                    }\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n              else\n                {\n                  Complex tmp = octave::math::min (a.data (ja), b.data (jb),\n                                                   nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.data (jx) = tmp;\n                      r.ridx (jx) = a.ridx (ja);\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n\n      r.maybe_compress ();\n    }\n  else\n    {\n      if (a_nr == 0 && (b_nr == 0 || b_nr == 1))\n        {\n          if (a_nc == 1 || b_nc == 1 || a_nc == b_nc)\n            r.resize (a_nr, std::max (a_nc, b_nc));\n          else\n            octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (a_nc == 0 && (b_nc == 0 || b_nc == 1))\n        {\n          if (a_nr == 1 || b_nr == 1 || a_nr == b_nr)\n            r.resize (std::max (a_nr, b_nr), a_nc);\n          else\n            octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (b_nr == 0 && (a_nr == 0 || a_nr == 1))\n        {\n          if (b_nc == 1 || a_nc == 1 || b_nc == a_nc)\n            r.resize (b_nr, std::max (a_nc, b_nc));\n          else\n            octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (b_nc == 0 && (a_nc == 0 || a_nc == 1))\n        {\n          if (b_nr == 1 || a_nr == 1 || b_nr == a_nr)\n            r.resize (std::max (a_nr, b_nr), b_nc);\n          else\n            octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else\n        octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n    }\n\n  return r;\n}\n\nSparseComplexMatrix\nmax (const Complex& c, const SparseComplexMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmax (const Complex& c, const SparseComplexMatrix& m, const bool nanflag)\n{\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmax (const Complex& c, const SparseComplexMatrix& m, const bool nanflag,\n     const bool realabs)\n{\n  SparseComplexMatrix result;\n\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (SparseComplexMatrix);\n\n  // Count the number of nonzero elements\n  if (octave::math::max (c, 0., nanflag, realabs) != 0.)\n    {\n      result = SparseComplexMatrix (nr, nc, c);\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n          result.xdata (m.ridx (i) + j * nr) = octave::math::max\n                                               (c, m.data (i), nanflag, realabs);\n    }\n  else\n    result = SparseComplexMatrix (m);\n\n  return result;\n}\n\nSparseComplexMatrix\nmax (const SparseComplexMatrix& m, const Complex& c)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmax (const SparseComplexMatrix& m, const Complex& c, const bool nanflag)\n{\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmax (const SparseComplexMatrix& m, const Complex& c, const bool nanflag,\n     const bool realabs)\n{\n  return max (c, m, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmax (const SparseComplexMatrix& a, const SparseComplexMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return max (a, b, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmax (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n     const bool nanflag)\n{\n  const bool realabs = false;\n  return max (a, b, nanflag, realabs);\n}\n\nSparseComplexMatrix\nmax (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n     const bool nanflag, const bool realabs)\n{\n  SparseComplexMatrix r;\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nr == b_nr && a_nc == b_nc)\n    {\n      r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));\n\n      octave_idx_type jx = 0;\n      r.cidx (0) = 0;\n      for (octave_idx_type i = 0 ; i < a_nc ; i++)\n        {\n          octave_idx_type ja = a.cidx (i);\n          octave_idx_type ja_max = a.cidx (i+1);\n          bool ja_lt_max = ja < ja_max;\n\n          octave_idx_type jb = b.cidx (i);\n          octave_idx_type jb_max = b.cidx (i+1);\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  Complex tmp = octave::math::max (a.data (ja), 0.,\n                                                   nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.ridx (jx) = a.ridx (ja);\n                      r.data (jx) = tmp;\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                }\n              else if ((! ja_lt_max)\n                       || (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))\n                {\n                  Complex tmp = octave::math::max (0., b.data (jb),\n                                                   nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.ridx (jx) = b.ridx (jb);\n                      r.data (jx) = tmp;\n                      jx++;\n                    }\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n              else\n                {\n                  Complex tmp = octave::math::max (a.data (ja), b.data (jb),\n                                                   nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.data (jx) = tmp;\n                      r.ridx (jx) = a.ridx (ja);\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n\n      r.maybe_compress ();\n    }\n  else\n    {\n      if (a_nr == 0 && (b_nr == 0 || b_nr == 1))\n        {\n          if (a_nc == 1 || b_nc == 1 || a_nc == b_nc)\n            r.resize (a_nr, std::max (a_nc, b_nc));\n          else\n            octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (a_nc == 0 && (b_nc == 0 || b_nc == 1))\n        {\n          if (a_nr == 1 || b_nr == 1 || a_nr == b_nr)\n            r.resize (std::max (a_nr, b_nr), a_nc);\n          else\n            octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (b_nr == 0 && (a_nr == 0 || a_nr == 1))\n        {\n          if (b_nc == 1 || a_nc == 1 || b_nc == a_nc)\n            r.resize (b_nr, std::max (a_nc, b_nc));\n          else\n            octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (b_nc == 0 && (a_nc == 0 || a_nc == 1))\n        {\n          if (b_nr == 1 || a_nr == 1 || b_nr == a_nr)\n            r.resize (std::max (a_nr, b_nr), b_nc);\n          else\n            octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else\n        octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n    }\n\n  return r;\n}\n\nSPARSE_SMS_CMP_OPS (SparseComplexMatrix, Complex)\nSPARSE_SMS_BOOL_OPS (SparseComplexMatrix, Complex)\n\nSPARSE_SSM_CMP_OPS (Complex, SparseComplexMatrix)\nSPARSE_SSM_BOOL_OPS (Complex, SparseComplexMatrix)\n\nSPARSE_SMSM_CMP_OPS (SparseComplexMatrix, SparseComplexMatrix)\nSPARSE_SMSM_BOOL_OPS (SparseComplexMatrix, SparseComplexMatrix)\n"
  },
  {
    "path": "liboctave/array/CSparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_CSparse_h)\n#define octave_CSparse_h 1\n\n#include \"octave-config.h\"\n\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n#include \"CNDArray.h\"\n#include \"DET.h\"\n#include \"MSparse.h\"\n#include \"MatrixType.h\"\n#include \"Sparse-op-decls.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"dNDArray.h\"\n#include \"oct-cmplx.h\"\n#include \"mx-fwd.h\"\n\nclass OCTAVE_API SparseComplexMatrix : public MSparse<Complex>\n{\npublic:\n\n  // Corresponding dense matrix type for this sparse matrix type.\n  typedef ComplexMatrix dense_matrix_type;\n\n  typedef void (*solve_singularity_handler) (double rcond);\n\n  SparseComplexMatrix () : MSparse<Complex> () { }\n\n  SparseComplexMatrix (octave_idx_type r,\n                       octave_idx_type c) : MSparse<Complex> (r, c) { }\n\n  SparseComplexMatrix (const dim_vector& dv, octave_idx_type nz = 0)\n    : MSparse<Complex> (dv, nz) { }\n\n  explicit SparseComplexMatrix (octave_idx_type r, octave_idx_type c,\n                                Complex val)\n    : MSparse<Complex> (r, c, val) { }\n\n  SparseComplexMatrix (octave_idx_type r, octave_idx_type c, double val)\n    : MSparse<Complex> (r, c, Complex (val)) { }\n\n  SparseComplexMatrix (const SparseComplexMatrix& a)\n    : MSparse<Complex> (a) { }\n\n  SparseComplexMatrix (const SparseComplexMatrix& a, const dim_vector& dv)\n    : MSparse<Complex> (a, dv) { }\n\n  SparseComplexMatrix (const MSparse<Complex>& a) : MSparse<Complex> (a) { }\n\n  SparseComplexMatrix (const Sparse<Complex>& a) : MSparse<Complex> (a) { }\n\n  explicit SparseComplexMatrix (const ComplexMatrix& a)\n    : MSparse<Complex> (a) { }\n\n  explicit SparseComplexMatrix (const ComplexNDArray& a)\n    : MSparse<Complex> (a) { }\n\n  SparseComplexMatrix (const Array<Complex>& a, const octave::idx_vector& r,\n                       const octave::idx_vector& c, octave_idx_type nr = -1,\n                       octave_idx_type nc = -1, bool sum_terms = true,\n                       octave_idx_type nzm = -1)\n    : MSparse<Complex> (a, r, c, nr, nc, sum_terms, nzm) { }\n\n  explicit OCTAVE_API SparseComplexMatrix (const SparseMatrix& a);\n\n  explicit OCTAVE_API SparseComplexMatrix (const SparseBoolMatrix& a);\n\n  explicit OCTAVE_API SparseComplexMatrix (const ComplexDiagMatrix& a);\n\n  SparseComplexMatrix (octave_idx_type r, octave_idx_type c,\n                       octave_idx_type num_nz)\n    : MSparse<Complex> (r, c, num_nz) { }\n\n  SparseComplexMatrix& operator = (const SparseComplexMatrix& a)\n  {\n    MSparse<Complex>::operator = (a);\n    return *this;\n  }\n\n  ~SparseComplexMatrix () = default;\n\n  OCTAVE_API bool operator == (const SparseComplexMatrix& a) const;\n  OCTAVE_API bool operator != (const SparseComplexMatrix& a) const;\n\n  OCTAVE_API bool ishermitian () const;\n\n  OCTAVE_API SparseComplexMatrix\n  max (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API SparseComplexMatrix\n  max (Array<octave_idx_type>& index, int dim = -1,\n       bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API SparseComplexMatrix\n  min (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API SparseComplexMatrix\n  min (Array<octave_idx_type>& index, int dim = -1,\n       bool nanflag = true, bool realabs = false) const;\n\n  OCTAVE_API SparseComplexMatrix&\n  insert (const SparseComplexMatrix& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API SparseComplexMatrix&\n  insert (const SparseMatrix& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API SparseComplexMatrix&\n  insert (const SparseComplexMatrix& a, const Array<octave_idx_type>& indx);\n  OCTAVE_API SparseComplexMatrix&\n  insert (const SparseMatrix& a, const Array<octave_idx_type>& indx);\n\n  OCTAVE_API SparseComplexMatrix\n  concat (const SparseComplexMatrix& rb, const Array<octave_idx_type>& ra_idx);\n  OCTAVE_API SparseComplexMatrix\n  concat (const SparseMatrix& rb, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API ComplexMatrix matrix_value () const;\n\n  OCTAVE_API SparseComplexMatrix hermitian () const;  // complex conjugate transpose\n  SparseComplexMatrix transpose () const\n  { return MSparse<Complex>::transpose (); }\n\n  friend OCTAVE_API SparseComplexMatrix conj (const SparseComplexMatrix& a);\n\n  // extract row or column i.\n\n  OCTAVE_API ComplexRowVector row (octave_idx_type i) const;\n\n  OCTAVE_API ComplexColumnVector column (octave_idx_type i) const;\n\nprivate:\n  SparseComplexMatrix dinverse (MatrixType& mattype, octave_idx_type& info,\n                                double& rcond, const bool force = false,\n                                const bool calccond = true) const;\n\n  SparseComplexMatrix tinverse (MatrixType& mattype, octave_idx_type& info,\n                                double& rcond, const bool force = false,\n                                const bool calccond = true) const;\n\npublic:\n  OCTAVE_API SparseComplexMatrix inverse () const;\n  OCTAVE_API SparseComplexMatrix inverse (MatrixType& mattype) const;\n  OCTAVE_API SparseComplexMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info) const;\n  OCTAVE_API SparseComplexMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info, double& rcond,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API ComplexDET determinant () const;\n  OCTAVE_API ComplexDET determinant (octave_idx_type& info) const;\n  OCTAVE_API ComplexDET\n  determinant (octave_idx_type& info, double& rcond,\n               bool calc_cond = true) const;\n\nprivate:\n  // Diagonal matrix solvers\n  ComplexMatrix dsolve (MatrixType& mattype, const Matrix& b,\n                        octave_idx_type& info, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond = false) const;\n\n  ComplexMatrix dsolve (MatrixType& mattype, const ComplexMatrix& b,\n                        octave_idx_type& info, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond = false) const;\n\n  SparseComplexMatrix dsolve (MatrixType& mattype, const SparseMatrix& b,\n                              octave_idx_type& info, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond = false) const;\n\n  SparseComplexMatrix dsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                              octave_idx_type& info, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond = false) const;\n\n  // Upper triangular matrix solvers\n  ComplexMatrix utsolve (MatrixType& mattype, const Matrix& b,\n                         octave_idx_type& info, double& rcond,\n                         solve_singularity_handler sing_handler,\n                         bool calc_cond = false) const;\n\n  ComplexMatrix utsolve (MatrixType& mattype, const ComplexMatrix& b,\n                         octave_idx_type& info, double& rcond,\n                         solve_singularity_handler sing_handler,\n                         bool calc_cond = false) const;\n\n  SparseComplexMatrix utsolve (MatrixType& mattype, const SparseMatrix& b,\n                               octave_idx_type& info, double& rcond,\n                               solve_singularity_handler sing_handler,\n                               bool calc_cond = false) const;\n\n  SparseComplexMatrix utsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                               octave_idx_type& info, double& rcond,\n                               solve_singularity_handler sing_handler,\n                               bool calc_cond = false) const;\n\n  // Lower triangular matrix solvers\n  ComplexMatrix ltsolve (MatrixType& mattype, const Matrix& b,\n                         octave_idx_type& info, double& rcond,\n                         solve_singularity_handler sing_handler,\n                         bool calc_cond = false) const;\n\n  ComplexMatrix ltsolve (MatrixType& mattype, const ComplexMatrix& b,\n                         octave_idx_type& info, double& rcond,\n                         solve_singularity_handler sing_handler,\n                         bool calc_cond = false) const;\n\n  SparseComplexMatrix ltsolve (MatrixType& mattype, const SparseMatrix& b,\n                               octave_idx_type& info, double& rcond,\n                               solve_singularity_handler sing_handler,\n                               bool calc_cond = false) const;\n\n  SparseComplexMatrix ltsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                               octave_idx_type& info, double& rcond,\n                               solve_singularity_handler sing_handler,\n                               bool calc_cond = false) const;\n\n  // Tridiagonal matrix solvers\n  ComplexMatrix trisolve (MatrixType& mattype, const Matrix& b,\n                          octave_idx_type& info, double& rcond,\n                          solve_singularity_handler sing_handler,\n                          bool calc_cond = false) const;\n\n  ComplexMatrix trisolve (MatrixType& mattype, const ComplexMatrix& b,\n                          octave_idx_type& info, double& rcond,\n                          solve_singularity_handler sing_handler,\n                          bool calc_cond = false) const;\n\n  SparseComplexMatrix trisolve (MatrixType& mattype, const SparseMatrix& b,\n                                octave_idx_type& info, double& rcond,\n                                solve_singularity_handler sing_handler,\n                                bool calc_cond = false) const;\n\n  SparseComplexMatrix trisolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                                octave_idx_type& info, double& rcond,\n                                solve_singularity_handler sing_handler,\n                                bool calc_cond = false) const;\n\n  // Banded matrix solvers (umfpack/cholesky)\n  ComplexMatrix bsolve (MatrixType& mattype, const Matrix& b,\n                        octave_idx_type& info, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond = false) const;\n\n  ComplexMatrix bsolve (MatrixType& mattype, const ComplexMatrix& b,\n                        octave_idx_type& info, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond = false) const;\n\n  SparseComplexMatrix bsolve (MatrixType& mattype, const SparseMatrix& b,\n                              octave_idx_type& info, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond = false) const;\n\n  SparseComplexMatrix bsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                              octave_idx_type& info, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond = false) const;\n\n  // Full matrix solvers (umfpack/cholesky)\n  void * factorize (octave_idx_type& err, double& rcond, Matrix& Control,\n                    Matrix& Info, solve_singularity_handler sing_handler,\n                    bool calc_cond) const;\n\n  ComplexMatrix fsolve (MatrixType& mattype, const Matrix& b,\n                        octave_idx_type& info, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond = false) const;\n\n  ComplexMatrix fsolve (MatrixType& mattype, const ComplexMatrix& b,\n                        octave_idx_type& info, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond = false) const;\n\n  SparseComplexMatrix fsolve (MatrixType& mattype, const SparseMatrix& b,\n                              octave_idx_type& info, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond = false) const;\n\n  SparseComplexMatrix fsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                              octave_idx_type& info, double& rcond,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond = false) const;\n\npublic:\n  // Generic interface to solver with no probing of type\n  OCTAVE_API ComplexMatrix solve (MatrixType& mattype, const Matrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n         double& rcond, solve_singularity_handler sing_handler,\n         bool singular_fallback = true) const;\n\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b,\n         octave_idx_type& info, double& rcond) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b,\n         octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler,\n         bool singular_fallback = true) const;\n\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& mattype, const SparseMatrix& b) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& mattype, const SparseMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& mattype, const SparseMatrix& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& mattype, const SparseMatrix& b, octave_idx_type& info,\n         double& rcond, solve_singularity_handler sing_handler,\n         bool singular_fallback = true) const;\n\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& mattype, const SparseComplexMatrix& b) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& mattype, const SparseComplexMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& mattype, const SparseComplexMatrix& b,\n         octave_idx_type& info, double& rcond) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& mattype, const SparseComplexMatrix& b,\n         octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler,\n         bool singular_fallback = true) const;\n\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b,\n         octave_idx_type& info, double& rcond) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b,\n         octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b,\n         octave_idx_type& info, double& rcond) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b,\n         octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  // Generic interface to solver with probing of type\n  OCTAVE_API ComplexMatrix solve (const Matrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (const Matrix& b, octave_idx_type& info, double& rcond) const;\n  OCTAVE_API ComplexMatrix\n  solve (const Matrix& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API ComplexMatrix solve (const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info, double& rcond) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API SparseComplexMatrix solve (const SparseMatrix& b) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (const SparseMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (const SparseMatrix& b, octave_idx_type& info, double& rcond) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (const SparseMatrix& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API SparseComplexMatrix solve (const SparseComplexMatrix& b) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (const SparseComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (const SparseComplexMatrix& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (const SparseComplexMatrix& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API ComplexColumnVector solve (const ColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info, double& rcond) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API ComplexColumnVector solve (const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API SparseComplexMatrix squeeze () const;\n\n  OCTAVE_API SparseComplexMatrix reshape (const dim_vector& new_dims) const;\n\n  OCTAVE_API SparseComplexMatrix\n  permute (const Array<octave_idx_type>& vec, bool inv = false) const;\n\n  OCTAVE_API SparseComplexMatrix\n  ipermute (const Array<octave_idx_type>& vec) const;\n\n  OCTAVE_API bool any_element_is_nan () const;\n  OCTAVE_API bool any_element_is_inf_or_nan () const;\n  OCTAVE_API bool all_elements_are_real () const;\n  OCTAVE_API bool all_integers (double& max_val, double& min_val) const;\n  OCTAVE_API bool too_large_for_float () const;\n\n  OCTAVE_API SparseBoolMatrix operator ! () const;\n\n  OCTAVE_API SparseBoolMatrix all (int dim = -1) const;\n  OCTAVE_API SparseBoolMatrix any (int dim = -1) const;\n\n  OCTAVE_API SparseComplexMatrix cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseComplexMatrix cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseComplexMatrix prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseComplexMatrix sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseComplexMatrix xsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseComplexMatrix sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseMatrix abs () const;\n\n  OCTAVE_API SparseComplexMatrix diag (octave_idx_type k = 0) const;\n\n  // i/o\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const SparseComplexMatrix& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, SparseComplexMatrix& a);\n};\n\nextern OCTAVE_API SparseComplexMatrix\noperator * (const SparseMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator * (const SparseComplexMatrix&, const SparseMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator * (const SparseComplexMatrix&, const SparseComplexMatrix&);\n\nextern OCTAVE_API ComplexMatrix\noperator * (const Matrix&, const SparseComplexMatrix&);\nextern OCTAVE_API ComplexMatrix\noperator * (const ComplexMatrix&, const SparseMatrix&);\nextern OCTAVE_API ComplexMatrix\noperator * (const ComplexMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API ComplexMatrix\nmul_trans (const ComplexMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API ComplexMatrix\nmul_herm (const ComplexMatrix&, const SparseComplexMatrix&);\n\nextern OCTAVE_API ComplexMatrix\noperator * (const SparseMatrix&, const ComplexMatrix&);\nextern OCTAVE_API ComplexMatrix\noperator * (const SparseComplexMatrix&, const Matrix&);\nextern OCTAVE_API ComplexMatrix\noperator * (const SparseComplexMatrix&, const ComplexMatrix&);\nextern OCTAVE_API ComplexMatrix\ntrans_mul (const SparseComplexMatrix&, const ComplexMatrix&);\nextern OCTAVE_API ComplexMatrix\nherm_mul (const SparseComplexMatrix&, const ComplexMatrix&);\n\nextern OCTAVE_API SparseComplexMatrix\noperator * (const DiagMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator * (const SparseComplexMatrix&, const DiagMatrix&);\n\nextern OCTAVE_API SparseComplexMatrix\noperator * (const ComplexDiagMatrix&, const SparseMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator * (const SparseMatrix&, const ComplexDiagMatrix&);\n\nextern OCTAVE_API SparseComplexMatrix\noperator * (const ComplexDiagMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator * (const SparseComplexMatrix&, const ComplexDiagMatrix&);\n\nextern OCTAVE_API SparseComplexMatrix\noperator + (const ComplexDiagMatrix&, const SparseMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator + (const DiagMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator + (const ComplexDiagMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator + (const SparseMatrix&, const ComplexDiagMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator + (const SparseComplexMatrix&, const DiagMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator + (const SparseComplexMatrix&, const ComplexDiagMatrix&);\n\nextern OCTAVE_API SparseComplexMatrix\noperator - (const ComplexDiagMatrix&, const SparseMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator - (const DiagMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator - (const ComplexDiagMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator - (const SparseMatrix&, const ComplexDiagMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator - (const SparseComplexMatrix&, const DiagMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator - (const SparseComplexMatrix&, const ComplexDiagMatrix&);\n\nextern OCTAVE_API SparseComplexMatrix\noperator * (const PermMatrix&, const SparseComplexMatrix&);\nextern OCTAVE_API SparseComplexMatrix\noperator * (const SparseComplexMatrix&, const PermMatrix&);\n\nextern OCTAVE_API SparseComplexMatrix\nmin (const Complex& c, const SparseComplexMatrix& m);\nextern OCTAVE_API SparseComplexMatrix\nmin (const Complex& c, const SparseComplexMatrix& m, const bool nanflag);\nextern OCTAVE_API SparseComplexMatrix\nmin (const Complex& c, const SparseComplexMatrix& m, const bool nanflag,\n     const bool realabs);\nextern OCTAVE_API SparseComplexMatrix\nmin (const SparseComplexMatrix& m, const Complex& c);\nextern OCTAVE_API SparseComplexMatrix\nmin (const SparseComplexMatrix& m, const Complex& c, const bool nanflag);\nextern OCTAVE_API SparseComplexMatrix\nmin (const SparseComplexMatrix& m, const Complex& c, const bool nanflag,\n     const bool realabs);\nextern OCTAVE_API SparseComplexMatrix\nmin (const SparseComplexMatrix& a, const SparseComplexMatrix& b);\nextern OCTAVE_API SparseComplexMatrix\nmin (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n     const bool nanflag);\nextern OCTAVE_API SparseComplexMatrix\nmin (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n     const bool nanflag, const bool realabs);\n\nextern OCTAVE_API SparseComplexMatrix\nmax (const Complex& c, const SparseComplexMatrix& m);\nextern OCTAVE_API SparseComplexMatrix\nmax (const Complex& c, const SparseComplexMatrix& m, const bool nanflag);\nextern OCTAVE_API SparseComplexMatrix\nmax (const Complex& c, const SparseComplexMatrix& m, const bool nanflag,\n     const bool realabs);\nextern OCTAVE_API SparseComplexMatrix\nmax (const SparseComplexMatrix& m, const Complex& c);\nextern OCTAVE_API SparseComplexMatrix\nmax (const SparseComplexMatrix& m, const Complex& c, const bool nanflag);\nextern OCTAVE_API SparseComplexMatrix\nmax (const SparseComplexMatrix& m, const Complex& c, const bool nanflag,\n     const bool realabs);\nextern OCTAVE_API SparseComplexMatrix\nmax (const SparseComplexMatrix& a, const SparseComplexMatrix& b);\nextern OCTAVE_API SparseComplexMatrix\nmax (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n     const bool nanflag);\nextern OCTAVE_API SparseComplexMatrix\nmax (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n     const bool nanflag, const bool realabs);\n\nSPARSE_SMS_CMP_OP_DECLS (SparseComplexMatrix, Complex, OCTAVE_API)\nSPARSE_SMS_BOOL_OP_DECLS (SparseComplexMatrix, Complex, OCTAVE_API)\n\nSPARSE_SSM_CMP_OP_DECLS (Complex, SparseComplexMatrix, OCTAVE_API)\nSPARSE_SSM_BOOL_OP_DECLS (Complex, SparseComplexMatrix, OCTAVE_API)\n\nSPARSE_SMSM_CMP_OP_DECLS (SparseComplexMatrix, SparseComplexMatrix, OCTAVE_API)\nSPARSE_SMSM_BOOL_OP_DECLS (SparseComplexMatrix, SparseComplexMatrix, OCTAVE_API)\n\nSPARSE_FORWARD_DEFS (MSparse, SparseComplexMatrix, ComplexMatrix, Complex)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/DiagArray2.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <algorithm>\n\n#include \"DiagArray2.h\"\n\n#include \"oct-error.h\"\n\ntemplate <typename T>\nDiagArray2<T>::DiagArray2 (const Array<T>& a, octave_idx_type r,\n                           octave_idx_type c)\n  : Array<T> (a.as_column ()), m_d1 (r), m_d2 (c)\n{\n  octave_idx_type rcmin = std::min (r, c);\n  if (rcmin != a.numel ())\n    Array<T>::resize (dim_vector (rcmin, 1));\n}\n\ntemplate <typename T>\nArray<T>\nDiagArray2<T>::extract_diag (octave_idx_type k) const\n{\n  Array<T> d;\n\n  if (k == 0)\n    // The main diagonal is shallow-copied.\n    d = *this;\n  else if (k > 0 && k < cols ())\n    d = Array<T> (dim_vector (std::min (cols () - k, rows ()), 1), T ());\n  else if (k < 0 && -k < rows ())\n    d = Array<T> (dim_vector (std::min (rows () + k, cols ()), 1), T ());\n  else  // Matlab returns [] 0x1 for out-of-range diagonal\n    d.resize (dim_vector (0, 1));\n\n  return d;\n}\n\ntemplate <typename T>\nDiagArray2<T>\nDiagArray2<T>::transpose () const\n{\n  return DiagArray2<T> (*this, m_d2, m_d1);\n}\n\ntemplate <typename T>\nDiagArray2<T>\nDiagArray2<T>::hermitian (T (* fcn) (const T&)) const\n{\n  return DiagArray2<T> (Array<T>::template map<T> (fcn), m_d2, m_d1);\n}\n\n// A two-dimensional array with diagonal elements only.\n\ntemplate <typename T>\nT&\nDiagArray2<T>::elem (octave_idx_type r, octave_idx_type c)\n{\n  static T zero (0);\n  return (r == c) ? Array<T>::elem (r) : zero;\n}\n\ntemplate <typename T>\nT&\nDiagArray2<T>::checkelem (octave_idx_type r, octave_idx_type c)\n{\n  static T zero (0);\n  return check_idx (r, c) ? elem (r, c) : zero;\n}\n\ntemplate <typename T>\nvoid\nDiagArray2<T>::resize (octave_idx_type r, octave_idx_type c,\n                       const T& rfv)\n{\n  if (r < 0 || c < 0)\n    (*current_liboctave_error_handler) (\"can't resize to negative dimensions\");\n\n  if (r != dim1 () || c != dim2 ())\n    {\n      Array<T>::resize (dim_vector (std::min (r, c), 1), rfv);\n      m_d1 = r; m_d2 = c;\n    }\n}\n\ntemplate <typename T>\nArray<T>\nDiagArray2<T>::array_value () const\n{\n  Array<T> result (dims (), T (0));\n\n  for (octave_idx_type i = 0, len = length (); i < len; i++)\n    result.xelem (i, i) = dgelem (i);\n\n  return result;\n}\n\ntemplate <typename T>\nbool\nDiagArray2<T>::check_idx (octave_idx_type r, octave_idx_type c) const\n{\n  bool ok = true;\n\n  if (r < 0 || r >= dim1 ())\n    octave::err_index_out_of_range (2, 1, r+1, dim1 (), dims ());\n\n  if (c < 0 || c >= dim2 ())\n    octave::err_index_out_of_range (2, 2, c+1, dim2 (), dims ());\n\n  return ok;\n}\n"
  },
  {
    "path": "liboctave/array/DiagArray2.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_DiagArray2_h)\n#define octave_DiagArray2_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdlib>\n\n#include \"Array-oct.h\"\n\n// Array<T> is inherited privately so that some methods, like index, don't\n// produce unexpected results.\n\ntemplate <typename T>\nclass OCTAVE_API DiagArray2 : protected Array<T>\n{\nprotected:\n  octave_idx_type m_d1, m_d2;\n\npublic:\n\n  using typename Array<T>::element_type;\n\n  DiagArray2 ()\n    : Array<T> (), m_d1 (0), m_d2 (0) { }\n\n  DiagArray2 (octave_idx_type r, octave_idx_type c)\n    : Array<T> (dim_vector (std::min (r, c), 1)), m_d1 (r), m_d2 (c) { }\n\n  DiagArray2 (octave_idx_type r, octave_idx_type c, const T& val)\n    : Array<T> (dim_vector (std::min (r, c), 1), val), m_d1 (r), m_d2 (c) { }\n\n  explicit DiagArray2 (const Array<T>& a)\n    : Array<T> (a.as_column ()), m_d1 (a.numel ()), m_d2 (a.numel ()) { }\n\n  DiagArray2 (const Array<T>& a, octave_idx_type r, octave_idx_type c);\n\n  DiagArray2 (const DiagArray2<T>& a)\n    : Array<T> (a), m_d1 (a.m_d1), m_d2 (a.m_d2) { }\n\n  template <typename U>\n  DiagArray2 (const DiagArray2<U>& a)\n    : Array<T> (a.extract_diag ()), m_d1 (a.dim1 ()), m_d2 (a.dim2 ()) { }\n\n  ~DiagArray2 () = default;\n\n  DiagArray2<T>& operator = (const DiagArray2<T>& a)\n  {\n    if (this != &a)\n      {\n        Array<T>::operator = (a);\n        m_d1 = a.m_d1;\n        m_d2 = a.m_d2;\n      }\n\n    return *this;\n  }\n\n  octave_idx_type dim1 () const { return m_d1; }\n  octave_idx_type dim2 () const { return m_d2; }\n\n  octave_idx_type rows () const { return dim1 (); }\n  octave_idx_type cols () const { return dim2 (); }\n  octave_idx_type columns () const { return dim2 (); }\n\n  octave_idx_type diag_length () const { return Array<T>::numel (); }\n  // FIXME: a dangerous ambiguity?\n  octave_idx_type length () const { return Array<T>::numel (); }\n  octave_idx_type nelem () const { return dim1 () * dim2 (); }\n  octave_idx_type numel () const { return nelem (); }\n\n  std::size_t byte_size () const { return Array<T>::byte_size (); }\n\n  dim_vector dims () const { return dim_vector (m_d1, m_d2); }\n\n  bool isempty () const { return numel () == 0; }\n\n  int ndims () const { return 2; }\n\n  OCTAVE_API Array<T> extract_diag (octave_idx_type k = 0) const;\n\n  DiagArray2<T> build_diag_matrix () const\n  {\n    return DiagArray2<T> (array_value ());\n  }\n\n  // Warning: the non-const two-index versions will silently ignore assignments\n  // to off-diagonal elements.\n\n  T elem (octave_idx_type r, octave_idx_type c) const\n  {\n    return (r == c) ? Array<T>::elem (r) : T (0);\n  }\n\n  OCTAVE_API T& elem (octave_idx_type r, octave_idx_type c);\n\n  T dgelem (octave_idx_type i) const\n  { return Array<T>::elem (i); }\n\n  T& dgelem (octave_idx_type i)\n  { return Array<T>::elem (i); }\n\n  T checkelem (octave_idx_type r, octave_idx_type c) const\n  { return check_idx (r, c) ? elem (r, c) : T (0); }\n\n  T operator () (octave_idx_type r, octave_idx_type c) const\n  {\n    return elem (r, c);\n  }\n\n  T& checkelem (octave_idx_type r, octave_idx_type c);\n\n  T& operator () (octave_idx_type r, octave_idx_type c)\n  {\n    return elem (r, c);\n  }\n\n  // No checking.\n\n  T xelem (octave_idx_type r, octave_idx_type c) const\n  {\n    return (r == c) ? Array<T>::xelem (r) : T (0);\n  }\n\n  T& dgxelem (octave_idx_type i)\n  { return Array<T>::xelem (i); }\n\n  T dgxelem (octave_idx_type i) const\n  { return Array<T>::xelem (i); }\n\n  OCTAVE_API void resize (octave_idx_type n, octave_idx_type m, const T& rfv);\n  void resize (octave_idx_type n, octave_idx_type m)\n  {\n    resize (n, m, Array<T>::resize_fill_value ());\n  }\n\n  OCTAVE_API DiagArray2<T> transpose () const;\n  OCTAVE_API DiagArray2<T> hermitian (T (*fcn) (const T&) = nullptr) const;\n\n  OCTAVE_API Array<T> array_value () const;\n\n  const T * data () const { return Array<T>::data (); }\n\n  T * rwdata () { return Array<T>::rwdata (); }\n  inline T * fortran_vec () { return rwdata (); }\n\n  void print_info (std::ostream& os, const std::string& prefix) const\n  { Array<T>::print_info (os, prefix); }\n\nprivate:\n\n  bool check_idx (octave_idx_type r, octave_idx_type c) const;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/array/MArray-C.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate MArrays of Complex values.\n\n#include \"oct-cmplx.h\"\n\n#define OCTAVE_EXTERN_TEMPLATE_MARRAY\n#include \"MArray.h\"\n#include \"MArray.cc\"\n\nINSTANTIATE_MARRAY (Complex, );\n\nINSTANTIATE_MARRAY_FRIENDS (Complex, OCTAVE_API)\n\n#include \"MDiagArray2.h\"\n#include \"MDiagArray2.cc\"\n\ntemplate class MDiagArray2<Complex>;\n\nINSTANTIATE_MDIAGARRAY2_FRIENDS (Complex, OCTAVE_API)\n"
  },
  {
    "path": "liboctave/array/MArray-d.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate MArrays of double values.\n\n#define OCTAVE_EXTERN_TEMPLATE_MARRAY\n#include \"MArray.h\"\n#include \"MArray.cc\"\n\nINSTANTIATE_MARRAY (double, );\n\nINSTANTIATE_MARRAY_FRIENDS (double, OCTAVE_API)\n\n#include \"MDiagArray2.h\"\n#include \"MDiagArray2.cc\"\n\ntemplate class MDiagArray2<double>;\n\nINSTANTIATE_MDIAGARRAY2_FRIENDS (double, OCTAVE_API)\n"
  },
  {
    "path": "liboctave/array/MArray-f.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate MArrays of float values.\n\n#define OCTAVE_EXTERN_TEMPLATE_MARRAY\n#include \"MArray.h\"\n#include \"MArray.cc\"\n\nINSTANTIATE_MARRAY (float, );\n\nINSTANTIATE_MARRAY_FRIENDS (float, OCTAVE_API)\n\n#include \"MDiagArray2.h\"\n#include \"MDiagArray2.cc\"\n\ntemplate class MDiagArray2<float>;\n\nINSTANTIATE_MDIAGARRAY2_FRIENDS (float, OCTAVE_API)\n"
  },
  {
    "path": "liboctave/array/MArray-fC.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate MArrays of FloatComplex values.\n\n#include \"oct-cmplx.h\"\n\n#define OCTAVE_EXTERN_TEMPLATE_MARRAY\n#include \"MArray.h\"\n#include \"MArray.cc\"\n\nINSTANTIATE_MARRAY (FloatComplex, );\n\nINSTANTIATE_MARRAY_FRIENDS (FloatComplex, OCTAVE_API)\n\n#include \"MDiagArray2.h\"\n#include \"MDiagArray2.cc\"\n\ntemplate class MDiagArray2<FloatComplex>;\n\nINSTANTIATE_MDIAGARRAY2_FRIENDS (FloatComplex, OCTAVE_API)\n"
  },
  {
    "path": "liboctave/array/MArray-fwd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_MArray_fwd_h)\n#define octave_MArray_fwd_h 1\n\n#include \"octave-config.h\"\n\ntemplate <typename T> class OCTAVE_TEMPLATE_API MArray;\n\n#endif\n"
  },
  {
    "path": "liboctave/array/MArray-i.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-inttypes-fwd.h\"\n\n// Instantiate MArrays of int values.\n\n#define OCTAVE_EXTERN_TEMPLATE_MARRAY\n#include \"MArray.h\"\n#include \"MArray.cc\"\n\nINSTANTIATE_MARRAY (int, );\n#if defined (OCTAVE_ENABLE_64)\nINSTANTIATE_MARRAY (int64_t, );\n#endif\n\nINSTANTIATE_MARRAY_FRIENDS (int, OCTAVE_API)\n#if defined (OCTAVE_ENABLE_64)\nINSTANTIATE_MARRAY_FRIENDS (int64_t, OCTAVE_API)\n#endif\n\nINSTANTIATE_MARRAY (octave_int8, );\nINSTANTIATE_MARRAY (octave_int16, );\nINSTANTIATE_MARRAY (octave_int32, );\nINSTANTIATE_MARRAY (octave_int64, );\n\nINSTANTIATE_MARRAY_FRIENDS (octave_int8, OCTAVE_API)\nINSTANTIATE_MARRAY_FRIENDS (octave_int16, OCTAVE_API)\nINSTANTIATE_MARRAY_FRIENDS (octave_int32, OCTAVE_API)\nINSTANTIATE_MARRAY_FRIENDS (octave_int64, OCTAVE_API)\n\nINSTANTIATE_MARRAY (octave_uint8, );\nINSTANTIATE_MARRAY (octave_uint16, );\nINSTANTIATE_MARRAY (octave_uint32, );\nINSTANTIATE_MARRAY (octave_uint64, );\n\nINSTANTIATE_MARRAY_FRIENDS (octave_uint8, OCTAVE_API)\nINSTANTIATE_MARRAY_FRIENDS (octave_uint16, OCTAVE_API)\nINSTANTIATE_MARRAY_FRIENDS (octave_uint32, OCTAVE_API)\nINSTANTIATE_MARRAY_FRIENDS (octave_uint64, OCTAVE_API)\n\n#include \"MDiagArray2.h\"\n#include \"MDiagArray2.cc\"\n\ntemplate class MDiagArray2<int>;\n\nINSTANTIATE_MDIAGARRAY2_FRIENDS (int, OCTAVE_API)\n"
  },
  {
    "path": "liboctave/array/MArray-s.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate MArrays of short int values.\n\n#define OCTAVE_EXTERN_TEMPLATE_MARRAY\n#include \"MArray.h\"\n#include \"MArray.cc\"\n\nINSTANTIATE_MARRAY (short, );\n\nINSTANTIATE_MARRAY_FRIENDS (short, OCTAVE_API)\n\n#include \"MDiagArray2.h\"\n#include \"MDiagArray2.cc\"\n\ntemplate class MDiagArray2<short>;\n\nINSTANTIATE_MDIAGARRAY2_FRIENDS (short, OCTAVE_API)\n"
  },
  {
    "path": "liboctave/array/MArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include \"MArray.h\"\n#include \"Array-util.h\"\n#include \"oct-error.h\"\n\ntemplate <typename T>\nclass _idxadds_helper\n{\npublic:\n  _idxadds_helper (T *a, T v) : m_array (a), m_val (v) { }\n\n  void operator () (octave_idx_type i)\n  { m_array[i] += m_val; }\n\nprivate:\n  T *m_array;\n  T m_val;\n};\n\ntemplate <typename T>\nclass _idxadda_helper\n{\npublic:\n  _idxadda_helper (T *a, const T *v) : m_array (a), m_vals (v) { }\n\n  void operator () (octave_idx_type i)\n  { m_array[i] += *m_vals++; }\n\nprivate:\n  T *m_array;\n  const T *m_vals;\n};\n\ntemplate <typename T>\nvoid\nMArray<T>::idx_add (const octave::idx_vector& idx, T val)\n{\n  octave_idx_type n = this->numel ();\n  octave_idx_type ext = idx.extent (n);\n  if (ext > n)\n    {\n      this->resize1 (ext);\n      n = ext;\n    }\n\n  octave_quit ();\n\n  octave_idx_type len = idx.length (n);\n  idx.loop (len, _idxadds_helper<T> (this->rwdata (), val));\n}\n\ntemplate <typename T>\nvoid\nMArray<T>::idx_add (const octave::idx_vector& idx, const MArray<T>& vals)\n{\n  octave_idx_type n = this->numel ();\n  octave_idx_type ext = idx.extent (n);\n  if (ext > n)\n    {\n      this->resize1 (ext);\n      n = ext;\n    }\n\n  octave_quit ();\n\n  octave_idx_type len = std::min (idx.length (n), vals.numel ());\n  idx.loop (len, _idxadda_helper<T> (this->rwdata (), vals.data ()));\n}\n\ntemplate <typename T, T op (typename ref_param<T>::type,\n                            typename ref_param<T>::type)>\nstruct _idxbinop_helper\n{\npublic:\n  _idxbinop_helper (T *a, const T *v) : m_array (a), m_vals (v) { }\n\n  void operator () (octave_idx_type i)\n  { m_array[i] = op (m_array[i], *m_vals++); }\n\nprivate:\n  T *m_array;\n  const T *m_vals;\n};\n\ntemplate <typename T>\nvoid\nMArray<T>::idx_min (const octave::idx_vector& idx, const MArray<T>& vals)\n{\n  octave_idx_type n = this->numel ();\n  octave_idx_type ext = idx.extent (n);\n  if (ext > n)\n    {\n      this->resize1 (ext);\n      n = ext;\n    }\n\n  octave_quit ();\n\n  octave_idx_type len = std::min (idx.length (n), vals.numel ());\n  idx.loop (len, _idxbinop_helper<T, octave::math::min> (this->rwdata (),\n                                                         vals.data ()));\n}\n\ntemplate <typename T>\nvoid\nMArray<T>::idx_max (const octave::idx_vector& idx, const MArray<T>& vals)\n{\n  octave_idx_type n = this->numel ();\n  octave_idx_type ext = idx.extent (n);\n  if (ext > n)\n    {\n      this->resize1 (ext);\n      n = ext;\n    }\n\n  octave_quit ();\n\n  octave_idx_type len = std::min (idx.length (n), vals.numel ());\n  idx.loop (len, _idxbinop_helper<T, octave::math::max> (this->rwdata (),\n                                                         vals.data ()));\n}\n\ntemplate <typename T>\nvoid\nMArray<T>::idx_add_nd (const octave::idx_vector& idx,\n                       const MArray<T>& vals, int dim)\n{\n  int nd = std::max (this->ndims (), vals.ndims ());\n  if (dim < 0)\n    dim = vals.dims ().first_non_singleton ();\n  else if (dim > nd)\n    nd = dim;\n\n  // Check dimensions.\n  dim_vector ddv = Array<T>::dims ().redim (nd);\n  dim_vector sdv = vals.dims ().redim (nd);\n\n  octave_idx_type ext = idx.extent (ddv(dim));\n\n  if (ext > ddv(dim))\n    {\n      ddv(dim) = ext;\n      Array<T>::resize (ddv);\n      ext = ddv(dim);\n    }\n\n  octave_idx_type l, n, u, ns;\n  get_extent_triplet (ddv, dim, l, n, u);\n  ns = sdv(dim);\n\n  sdv(dim) = ddv(dim) = 0;\n  if (ddv != sdv)\n    (*current_liboctave_error_handler) (\"accumdim: dimension mismatch\");\n\n  T *dst = Array<T>::rwdata ();\n  const T *src = vals.data ();\n  octave_idx_type len = idx.length (ns);\n\n  if (l == 1)\n    {\n      for (octave_idx_type j = 0; j < u; j++)\n        {\n          octave_quit ();\n\n          idx.loop (len, _idxadda_helper<T> (dst + j*n, src + j*ns));\n        }\n    }\n  else\n    {\n      for (octave_idx_type j = 0; j < u; j++)\n        {\n          octave_quit ();\n          for (octave_idx_type i = 0; i < len; i++)\n            {\n              octave_idx_type k = idx(i);\n\n              mx_inline_add2 (l, dst + l*k, src + l*i);\n            }\n\n          dst += l*n;\n          src += l*ns;\n        }\n    }\n}\n\n// N-dimensional array with math ops.\ntemplate <typename T>\nvoid\nMArray<T>::changesign ()\n{\n  if (Array<T>::is_shared ())\n    *this = - *this;\n  else\n    do_mx_inplace_op<T> (*this, mx_inline_uminus2);\n}\n\n// Element by element MArray by scalar ops.\n\ntemplate <typename T>\nMArray<T>&\noperator += (MArray<T>& a, const T& s)\n{\n  if (a.is_shared ())\n    a = a + s;\n  else\n    do_ms_inplace_op<T, T> (a, s, mx_inline_add2);\n  return a;\n}\n\ntemplate <typename T>\nMArray<T>&\noperator -= (MArray<T>& a, const T& s)\n{\n  if (a.is_shared ())\n    a = a - s;\n  else\n    do_ms_inplace_op<T, T> (a, s, mx_inline_sub2);\n  return a;\n}\n\ntemplate <typename T>\nMArray<T>&\noperator *= (MArray<T>& a, const T& s)\n{\n  if (a.is_shared ())\n    a = a * s;\n  else\n    do_ms_inplace_op<T, T> (a, s, mx_inline_mul2);\n  return a;\n}\n\ntemplate <typename T>\nMArray<T>&\noperator /= (MArray<T>& a, const T& s)\n{\n  if (a.is_shared ())\n    a = a / s;\n  else\n    do_ms_inplace_op<T, T> (a, s, mx_inline_div2);\n  return a;\n}\n\n// Element by element MArray by MArray ops.\n\ntemplate <typename T>\nMArray<T>&\noperator += (MArray<T>& a, const MArray<T>& b)\n{\n  if (a.is_shared ())\n    a = a + b;\n  else\n    do_mm_inplace_op<T, T> (a, b, mx_inline_add2, mx_inline_add2, \"+=\");\n  return a;\n}\n\ntemplate <typename T>\nMArray<T>&\noperator -= (MArray<T>& a, const MArray<T>& b)\n{\n  if (a.is_shared ())\n    a = a - b;\n  else\n    do_mm_inplace_op<T, T> (a, b, mx_inline_sub2, mx_inline_sub2, \"-=\");\n  return a;\n}\n\ntemplate <typename T>\nMArray<T>&\nproduct_eq (MArray<T>& a, const MArray<T>& b)\n{\n  if (a.is_shared ())\n    return a = product (a, b);\n  else\n    do_mm_inplace_op<T, T> (a, b, mx_inline_mul2, mx_inline_mul2, \".*=\");\n  return a;\n}\n\ntemplate <typename T>\nMArray<T>&\nquotient_eq (MArray<T>& a, const MArray<T>& b)\n{\n  if (a.is_shared ())\n    return a = quotient (a, b);\n  else\n    do_mm_inplace_op<T, T> (a, b, mx_inline_div2, mx_inline_div2, \"./=\");\n  return a;\n}\n\n// Element by element MArray by scalar ops.\n\n#define MARRAY_NDS_OP(OP, FN)                   \\\n  template <typename T>                         \\\n  MArray<T>                                     \\\n  operator OP (const MArray<T>& a, const T& s)  \\\n  {                                             \\\n    return do_ms_binary_op<T, T, T> (a, s, FN); \\\n  }\n\nMARRAY_NDS_OP (+, mx_inline_add)\nMARRAY_NDS_OP (-, mx_inline_sub)\nMARRAY_NDS_OP (*, mx_inline_mul)\nMARRAY_NDS_OP (/, mx_inline_div)\n\n// Element by element scalar by MArray ops.\n\n#define MARRAY_SND_OP(OP, FN)                   \\\n  template <typename T>                         \\\n  MArray<T>                                     \\\n  operator OP (const T& s, const MArray<T>& a)  \\\n  {                                             \\\n    return do_sm_binary_op<T, T, T> (s, a, FN); \\\n  }\n\nMARRAY_SND_OP (+, mx_inline_add)\nMARRAY_SND_OP (-, mx_inline_sub)\nMARRAY_SND_OP (*, mx_inline_mul)\nMARRAY_SND_OP (/, mx_inline_div)\n\n// Element by element MArray by MArray ops.\n\n#define MARRAY_NDND_OP(FCN, OP, FN) \\\n  template <typename T> \\\n  MArray<T> \\\n  FCN (const MArray<T>& a, const MArray<T>& b) \\\n  { \\\n    return do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN); \\\n  }\n\nMARRAY_NDND_OP (operator +, +, mx_inline_add)\nMARRAY_NDND_OP (operator -, -, mx_inline_sub)\nMARRAY_NDND_OP (product,    *, mx_inline_mul)\nMARRAY_NDND_OP (quotient,   /, mx_inline_div)\n\ntemplate <typename T>\nMArray<T>\noperator + (const MArray<T>& a)\n{\n  return a;\n}\n\ntemplate <typename T>\nMArray<T>\noperator - (const MArray<T>& a)\n{\n  return do_mx_unary_op<T, T> (a, mx_inline_uminus);\n}\n\ntemplate <typename T>\nvoid\nMArray<T>::instantiation_guard ()\n{\n  // This guards against accidental implicit instantiations.\n  // Array<T, Alloc> instances should always be explicit and use INSTANTIATE_ARRAY.\n  T::__xXxXx__ ();\n}\n\n#define INSTANTIATE_MARRAY(T, API)            \\\n  template <> API void                          \\\n  MArray<T>::instantiation_guard () { }         \\\n                                                \\\n  template class API MArray<T>\n"
  },
  {
    "path": "liboctave/array/MArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_MArray_h)\n#define octave_MArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-oct.h\"\n#include \"MArray-fwd.h\"\n#include \"mx-inlines.cc\"\n\ntemplate <typename T> OCTAVE_API MArray<T>& operator += (MArray<T>&, const T&);\ntemplate <typename T> OCTAVE_API MArray<T>& operator -= (MArray<T>&, const T&);\ntemplate <typename T> OCTAVE_API MArray<T>& operator *= (MArray<T>&, const T&);\ntemplate <typename T> OCTAVE_API MArray<T>& operator /= (MArray<T>&, const T&);\ntemplate <typename T> OCTAVE_API MArray<T>& operator += (MArray<T>&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T>& operator -= (MArray<T>&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T>& product_eq (MArray<T>&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T>& quotient_eq (MArray<T>&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> operator + (const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> operator - (const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> operator + (const MArray<T>&, const T&);\ntemplate <typename T> OCTAVE_API MArray<T> operator - (const MArray<T>&, const T&);\ntemplate <typename T> OCTAVE_API MArray<T> operator * (const MArray<T>&, const T&);\ntemplate <typename T> OCTAVE_API MArray<T> operator / (const MArray<T>&, const T&);\ntemplate <typename T> OCTAVE_API MArray<T> operator + (const T&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> operator - (const T&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> operator * (const T&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> operator / (const T&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> operator + (const MArray<T>&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> operator - (const MArray<T>&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> quotient (const MArray<T>&, const MArray<T>&);\ntemplate <typename T> OCTAVE_API MArray<T> product (const MArray<T>&, const MArray<T>&);\n\n//! Template for N-dimensional array classes with like-type math operators.\ntemplate <typename T>\nclass OCTAVE_API MArray : public Array<T>\n{\npublic:\n\n  OCTAVE_OVERRIDABLE_FUNC_API\n  MArray () : Array<T> () { }\n\n  explicit OCTAVE_OVERRIDABLE_FUNC_API\n  MArray (const dim_vector& dv)\n    : Array<T> (dv) { }\n\n  explicit OCTAVE_OVERRIDABLE_FUNC_API\n  MArray (const dim_vector& dv, const T& val)\n    : Array<T> (dv, val) { }\n\n  OCTAVE_OVERRIDABLE_FUNC_API\n  MArray (const MArray<T>& a) : Array<T> (a) { }\n\n  template <typename U>\n  OCTAVE_OVERRIDABLE_FUNC_API\n  MArray (const Array<U>& a) : Array<T> (a) { }\n\n  OCTAVE_OVERRIDABLE_FUNC_API ~MArray () = default;\n\n  OCTAVE_OVERRIDABLE_FUNC_API MArray<T>& operator = (const MArray<T>& a)\n  {\n    Array<T>::operator = (a);\n    return *this;\n  }\n\n  OCTAVE_OVERRIDABLE_FUNC_API MArray<T>\n  reshape (const dim_vector& new_dims) const\n  { return Array<T>::reshape (new_dims); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API MArray<T>\n  permute (const Array<octave_idx_type>& vec, bool inv = false) const\n  { return Array<T>::permute (vec, inv); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API MArray<T>\n  ipermute (const Array<octave_idx_type>& vec) const\n  { return Array<T>::ipermute (vec); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API MArray squeeze () const\n  { return Array<T>::squeeze (); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API MArray<T> transpose () const\n  { return Array<T>::transpose (); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API MArray<T>\n  hermitian (T (*fcn) (const T&) = nullptr) const\n  { return Array<T>::hermitian (fcn); }\n\n  //! Performs indexed accumulative addition.\n  //@{\n  OCTAVE_API void idx_add (const octave::idx_vector& idx, T val);\n  OCTAVE_API void\n  idx_add (const octave::idx_vector& idx, const MArray<T>& vals);\n  //@}\n\n  OCTAVE_API void\n  idx_min (const octave::idx_vector& idx, const MArray<T>& vals);\n\n  OCTAVE_API void\n  idx_max (const octave::idx_vector& idx, const MArray<T>& vals);\n\n  OCTAVE_API void\n  idx_add_nd (const octave::idx_vector& idx, const MArray<T>& vals,\n              int dim = -1);\n\n  OCTAVE_API void changesign ();\n\nprivate:\n  OCTAVE_API static void instantiation_guard ();\n};\n\n// Define all the MArray forwarding functions for return type R and\n// MArray element type T\n#define MARRAY_FORWARD_DEFS(B, R, T)                                    \\\n  inline R operator += (R& x, const T& y)                               \\\n  {                                                                     \\\n    return R (operator += (dynamic_cast<B<T>&> (x), (y)));              \\\n  }                                                                     \\\n  inline R operator -= (R& x, const T& y)                               \\\n  {                                                                     \\\n    return R (operator -= (dynamic_cast<B<T>&> (x), (y)));              \\\n  }                                                                     \\\n  inline R operator *= (R& x, const T& y)                               \\\n  {                                                                     \\\n    return R (operator *= (dynamic_cast<B<T>&> (x), (y)));              \\\n  }                                                                     \\\n  inline R operator /= (R& x, const T& y)                               \\\n  {                                                                     \\\n    return R (operator /= (dynamic_cast<B<T>&> (x), (y)));              \\\n  }                                                                     \\\n  inline R operator += (R& x, const R& y)                               \\\n  {                                                                     \\\n    return R (operator += (dynamic_cast<B<T>&> (x),                     \\\n                           dynamic_cast<const B<T>&> (y)));             \\\n  }                                                                     \\\n  inline R operator -= (R& x, const R& y)                               \\\n  {                                                                     \\\n    return R (operator -= (dynamic_cast<B<T>&> (x),                     \\\n                           dynamic_cast<const B<T>&> (y)));             \\\n  }                                                                     \\\n  inline R product_eq (R& x, const R& y)                                \\\n  {                                                                     \\\n    return R (product_eq (dynamic_cast<B<T>&> (x),                      \\\n                          dynamic_cast<const B<T>&> (y)));              \\\n  }                                                                     \\\n  inline R quotient_eq (R& x, const R& y)                               \\\n  {                                                                     \\\n    return R (quotient_eq (dynamic_cast<B<T>&> (x),                     \\\n                           dynamic_cast<const B<T>&> (y)));             \\\n  }                                                                     \\\n  inline R operator + (const R& x)                                      \\\n  {                                                                     \\\n    return R (operator + (dynamic_cast<const B<T>&> (x)));              \\\n  }                                                                     \\\n  inline R operator - (const R& x)                                      \\\n  {                                                                     \\\n    return R (operator - (dynamic_cast<const B<T>&> (x)));              \\\n  }                                                                     \\\n  inline R operator + (const R& x, const T& y)                          \\\n  {                                                                     \\\n    return R (operator + (dynamic_cast<const B<T>&> (x), (y)));         \\\n  }                                                                     \\\n  inline R operator - (const R& x, const T& y)                          \\\n  {                                                                     \\\n    return R (operator - (dynamic_cast<const B<T>&> (x), (y)));         \\\n  }                                                                     \\\n  inline R operator * (const R& x, const T& y)                          \\\n  {                                                                     \\\n    return R (operator * (dynamic_cast<const B<T>&> (x), (y)));         \\\n  }                                                                     \\\n  inline R operator / (const R& x, const T& y)                          \\\n  {                                                                     \\\n    return R (operator / (dynamic_cast<const B<T>&> (x), (y)));         \\\n  }                                                                     \\\n  inline R operator + (const T& x, const R& y)                          \\\n  {                                                                     \\\n    return R (operator + ( (x), dynamic_cast<const B<T>&> (y)));        \\\n  }                                                                     \\\n  inline R operator - (const T& x, const R& y)                          \\\n  {                                                                     \\\n    return R (operator - ( (x), dynamic_cast<const B<T>&> (y)));        \\\n  }                                                                     \\\n  inline R operator * (const T& x, const R& y)                          \\\n  {                                                                     \\\n    return R (operator * ( (x), dynamic_cast<const B<T>&> (y)));        \\\n  }                                                                     \\\n  inline R operator / (const T& x, const R& y)                          \\\n  {                                                                     \\\n    return R (operator / ( (x), dynamic_cast<const B<T>&> (y)));        \\\n  }                                                                     \\\n  inline R operator + (const R& x, const R& y)                          \\\n  {                                                                     \\\n    return R (operator + (dynamic_cast<const B<T>&> (x),                \\\n                          dynamic_cast<const B<T>&> (y)));              \\\n  }                                                                     \\\n  inline R operator - (const R& x, const R& y)                          \\\n  {                                                                     \\\n    return R (operator - (dynamic_cast<const B<T>&> (x),                \\\n                          dynamic_cast<const B<T>&> (y)));              \\\n  }                                                                     \\\n  inline R product (const R& x, const R& y)                             \\\n  {                                                                     \\\n    return R (product (dynamic_cast<const B<T>&> (x),                   \\\n                       dynamic_cast<const B<T>&> (y)));                 \\\n  }                                                                     \\\n  inline R quotient (const R& x, const R& y)                            \\\n  {                                                                     \\\n    return R (quotient (dynamic_cast<const B<T>&> (x),                  \\\n                        dynamic_cast<const B<T>&> (y)));                \\\n  }\n\n// Instantiate all the MArray friends for MArray element type T.\n#define INSTANTIATE_MARRAY_FRIENDS(T, API)                              \\\n  template API MArray<T>& operator += (MArray<T>&, const T&);           \\\n  template API MArray<T>& operator -= (MArray<T>&, const T&);           \\\n  template API MArray<T>& operator *= (MArray<T>&, const T&);           \\\n  template API MArray<T>& operator /= (MArray<T>&, const T&);           \\\n  template API MArray<T>& operator += (MArray<T>&, const MArray<T>&);   \\\n  template API MArray<T>& operator -= (MArray<T>&, const MArray<T>&);   \\\n  template API MArray<T>& product_eq (MArray<T>&, const MArray<T>&);    \\\n  template API MArray<T>& quotient_eq (MArray<T>&, const MArray<T>&);   \\\n  template API MArray<T> operator + (const MArray<T>&);                 \\\n  template API MArray<T> operator - (const MArray<T>&);                 \\\n  template API MArray<T> operator + (const MArray<T>&, const T&);       \\\n  template API MArray<T> operator - (const MArray<T>&, const T&);       \\\n  template API MArray<T> operator * (const MArray<T>&, const T&);       \\\n  template API MArray<T> operator / (const MArray<T>&, const T&);       \\\n  template API MArray<T> operator + (const T&, const MArray<T>&);       \\\n  template API MArray<T> operator - (const T&, const MArray<T>&);       \\\n  template API MArray<T> operator * (const T&, const MArray<T>&);       \\\n  template API MArray<T> operator / (const T&, const MArray<T>&);       \\\n  template API MArray<T> operator + (const MArray<T>&, const MArray<T>&); \\\n  template API MArray<T> operator - (const MArray<T>&, const MArray<T>&); \\\n  template API MArray<T> quotient (const MArray<T>&, const MArray<T>&); \\\n  template API MArray<T> product (const MArray<T>&, const MArray<T>&);\n\n// Instantiate all the MDiagArray2 friends for MDiagArray2 element type T.\n#define INSTANTIATE_MDIAGARRAY2_FRIENDS(T, API)                         \\\n  template API MDiagArray2<T> operator + (const MDiagArray2<T>&);       \\\n  template API MDiagArray2<T> operator - (const MDiagArray2<T>&);       \\\n  template API MDiagArray2<T> operator * (const MDiagArray2<T>&, const T&); \\\n  template API MDiagArray2<T> operator / (const MDiagArray2<T>&, const T&); \\\n  template API MDiagArray2<T> operator * (const T&, const MDiagArray2<T>&); \\\n  template API MDiagArray2<T> operator + (const MDiagArray2<T>&,        \\\n                                          const MDiagArray2<T>&);       \\\n  template API MDiagArray2<T> operator - (const MDiagArray2<T>&,        \\\n                                          const MDiagArray2<T>&);       \\\n  template API MDiagArray2<T> product (const MDiagArray2<T>&,           \\\n                                       const MDiagArray2<T>&);\n\n#if ! defined (OCTAVE_EXTERN_TEMPLATE_MARRAY)\n// guard against double extern template declarations\n#define OCTAVE_EXTERN_TEMPLATE_MARRAY\n\n#include \"oct-cmplx.h\"\n#include \"oct-inttypes-fwd.h\"\n\n// \"Protect\" MArray<T> instantiations that are exported by liboctave from\n// being implicitly instantiated in compilation units including this file.\n\n// instantiated in MArray-C.cc\nextern template class OCTAVE_API MArray<Complex>;\n// instantiated in MArray-d.cc\nextern template class OCTAVE_API MArray<double>;\n// instantiated in MArray-f.cc\nextern template class OCTAVE_API MArray<float>;\n// instantiated in MArray-fC.cc\nextern template class OCTAVE_API MArray<FloatComplex>;\n// instantiated in MArray-i.cc\nextern template class OCTAVE_API MArray<int>;\n#if defined (OCTAVE_ENABLE_64)\nextern template class OCTAVE_API MArray<int64_t>;\n#endif\nextern template class OCTAVE_API MArray<octave_int8>;\nextern template class OCTAVE_API MArray<octave_int16>;\nextern template class OCTAVE_API MArray<octave_int32>;\nextern template class OCTAVE_API MArray<octave_int64>;\nextern template class OCTAVE_API MArray<octave_uint8>;\nextern template class OCTAVE_API MArray<octave_uint16>;\nextern template class OCTAVE_API MArray<octave_uint32>;\nextern template class OCTAVE_API MArray<octave_uint64>;\n// instantiated in MArray-s.cc\nextern template class OCTAVE_API MArray<short>;\n\n#endif  // OCTAVE_EXTERN_TEMPLATE_MARRAY\n\n#endif\n"
  },
  {
    "path": "liboctave/array/MDiagArray2.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include \"MDiagArray2.h\"\n#include \"Array-util.h\"\n#include \"oct-error.h\"\n\ntemplate <typename T>\nbool\nMDiagArray2<T>::is_multiple_of_identity (T val) const\n{\n  bool retval = this->rows () == this->cols ();\n  if (retval)\n    {\n      octave_idx_type len = this->length ();\n      octave_idx_type i = 0;\n      for (; i < len; i++)\n        if (DiagArray2<T>::elem (i, i) != val) break;\n      retval = i == len;\n    }\n\n  return retval;\n}\n\n// Two-dimensional diagonal array with math ops.\n\n// Element by element MDiagArray2 by scalar ops.\n\n#define MARRAY_DAS_OP(OP, FN)                                   \\\n  template <typename T>                                         \\\n  MDiagArray2<T>                                                \\\n  operator OP (const MDiagArray2<T>& a, const T& s)             \\\n  {                                                             \\\n    return MDiagArray2<T> (do_ms_binary_op<T, T, T> (a, s, FN), \\\n                           a.m_d1, a.m_d2);                     \\\n  }\n\nMARRAY_DAS_OP (*, mx_inline_mul)\nMARRAY_DAS_OP (/, mx_inline_div)\n\n// Element by element scalar by MDiagArray2 ops.\n\ntemplate <typename T>\nMDiagArray2<T>\noperator * (const T& s, const MDiagArray2<T>& a)\n{\n  return MDiagArray2<T> (do_sm_binary_op<T, T, T> (s, a, mx_inline_mul),\n                         a.m_d1, a.m_d2);\n}\n\n// Element by element MDiagArray2 by MDiagArray2 ops.\n\n#define MARRAY_DADA_OP(FCN, OP, FN)                                     \\\n  template <typename T>                                                 \\\n  MDiagArray2<T>                                                        \\\n  FCN (const MDiagArray2<T>& a, const MDiagArray2<T>& b)                \\\n  {                                                                     \\\n    if (a.m_d1 != b.m_d1 || a.m_d2 != b.m_d2)                           \\\n      octave::err_nonconformant (#FCN, a.m_d1, a.m_d2, b.m_d1, b.m_d2); \\\n                                                                        \\\n    return MDiagArray2<T> (do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN), \\\n                           a.m_d1, a.m_d2);                             \\\n  }\n\nMARRAY_DADA_OP (operator +, +, mx_inline_add)\nMARRAY_DADA_OP (operator -, -, mx_inline_sub)\nMARRAY_DADA_OP (product,    *, mx_inline_mul)\n\n// Unary MDiagArray2 ops.\n\ntemplate <typename T>\nMDiagArray2<T>\noperator + (const MDiagArray2<T>& a)\n{\n  return a;\n}\n\ntemplate <typename T>\nMDiagArray2<T>\noperator - (const MDiagArray2<T>& a)\n{\n  return MDiagArray2<T> (do_mx_unary_op<T, T> (a, mx_inline_uminus),\n                         a.m_d1, a.m_d2);\n}\n"
  },
  {
    "path": "liboctave/array/MDiagArray2.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_MDiagArray2_h)\n#define octave_MDiagArray2_h 1\n\n#include \"octave-config.h\"\n\n#include \"DiagArray2.h\"\n#include \"MArray.h\"\n\ntemplate <typename T> class MDiagArray2;\n\ntemplate <typename T> MDiagArray2<T> operator + (const MDiagArray2<T>&);\ntemplate <typename T> MDiagArray2<T> operator - (const MDiagArray2<T>&);\ntemplate <typename T> MDiagArray2<T> operator * (const MDiagArray2<T>&,\n                                                 const T&);\ntemplate <typename T> MDiagArray2<T> operator / (const MDiagArray2<T>&,\n                                                 const T&);\ntemplate <typename T> MDiagArray2<T> operator * (const T&,\n                                                 const MDiagArray2<T>&);\ntemplate <typename T> MDiagArray2<T> operator + (const MDiagArray2<T>&,\n                                                 const MDiagArray2<T>&);\ntemplate <typename T> MDiagArray2<T> operator - (const MDiagArray2<T>&,\n                                                 const MDiagArray2<T>&);\ntemplate <typename T> MDiagArray2<T> product (const MDiagArray2<T>&,\n                                              const MDiagArray2<T>&);\n\n//! Template for two-dimensional diagonal array with math operators.\ntemplate <typename T>\nclass OCTAVE_API MDiagArray2 : public DiagArray2<T>\n{\npublic:\n\n  MDiagArray2 () : DiagArray2<T> () { }\n\n  MDiagArray2 (octave_idx_type r, octave_idx_type c) : DiagArray2<T> (r, c) { }\n\n  MDiagArray2 (octave_idx_type r, octave_idx_type c, const T& val)\n    : DiagArray2<T> (r, c, val) { }\n\n  MDiagArray2 (const MDiagArray2<T>& a) : DiagArray2<T> (a) { }\n\n  MDiagArray2 (const DiagArray2<T>& a) : DiagArray2<T> (a) { }\n\n  template <typename U>\n  MDiagArray2 (const DiagArray2<U>& a) : DiagArray2<T> (a) { }\n\n  explicit MDiagArray2 (const Array<T>& a) : DiagArray2<T> (a) { }\n\n  MDiagArray2 (const Array<T>& a, octave_idx_type r, octave_idx_type c)\n    : DiagArray2<T> (a, r, c) { }\n\n  ~MDiagArray2 () = default;\n\n  MDiagArray2<T>& operator = (const MDiagArray2<T>& a)\n  {\n    DiagArray2<T>::operator = (a);\n    return *this;\n  }\n\n  MArray<T> array_value () const\n  {\n    return DiagArray2<T>::array_value ();\n  }\n\n  octave_idx_type nnz () const\n  {\n    const T *d = this->data ();\n\n    octave_idx_type nel = this->length ();\n\n    static constexpr T zero = T ();\n\n    return std::count_if (d, d + nel,\n                          [] (T elem) { return elem != zero; });\n  }\n\n  MArray<T> diag (octave_idx_type k = 0) const\n  { return DiagArray2<T>::extract_diag (k); }\n\n  MDiagArray2<T> transpose () const { return DiagArray2<T>::transpose (); }\n  MDiagArray2<T> hermitian (T (*fcn) (const T&) = nullptr) const\n  { return DiagArray2<T>::hermitian (fcn); }\n\n  OCTAVE_API bool is_multiple_of_identity (T val) const;\n\n  // Currently, the OPS functions don't need to be friends, but that\n  // may change.\n\n  friend OCTAVE_API MDiagArray2<T> operator + <> (const MDiagArray2<T>&);\n  friend OCTAVE_API MDiagArray2<T> operator - <> (const MDiagArray2<T>&);\n  friend OCTAVE_API MDiagArray2<T>\n  operator * <> (const MDiagArray2<T>&, const T&);\n  friend OCTAVE_API MDiagArray2<T>\n  operator / <> (const MDiagArray2<T>&, const T&);\n  friend OCTAVE_API MDiagArray2<T>\n  operator * <> (const T&, const MDiagArray2<T>&);\n  friend OCTAVE_API MDiagArray2<T>\n  operator + <> (const MDiagArray2<T>&, const MDiagArray2<T>&);\n  friend OCTAVE_API MDiagArray2<T>\n  operator - <> (const MDiagArray2<T>&, const MDiagArray2<T>&);\n  friend OCTAVE_API MDiagArray2<T>\n  product <> (const MDiagArray2<T>&, const MDiagArray2<T>&);\n\n};\n\n#define MDIAGARRAY2_FORWARD_DEFS(B, R, T)                               \\\n  inline R                                                              \\\n  operator + (const R& x)                                               \\\n  {                                                                     \\\n    return R (operator + (dynamic_cast<const B<T>&> (x)));              \\\n  }                                                                     \\\n  inline R                                                              \\\n  operator - (const R& x)                                               \\\n  {                                                                     \\\n    return R (operator - (dynamic_cast<const B<T>&> (x)));              \\\n  }                                                                     \\\n  inline R                                                              \\\n  operator * (const R& x, const T& y)                                   \\\n  {                                                                     \\\n    return R (operator * (dynamic_cast<const B<T>&> (x), (y)));         \\\n  }                                                                     \\\n  inline R                                                              \\\n  operator / (const R& x, const T& y)                                   \\\n  {                                                                     \\\n    return R (operator / (dynamic_cast<const B<T>&> (x), (y)));         \\\n  }                                                                     \\\n  inline R                                                              \\\n  operator * (const T& x, const R& y)                                   \\\n  {                                                                     \\\n    return R (operator * ( (x), dynamic_cast<const B<T>&> (y)));        \\\n  }                                                                     \\\n  inline R                                                              \\\n  operator + (const R& x, const R& y)                                   \\\n  {                                                                     \\\n    return R (operator + (dynamic_cast<const B<T>&> (x),                \\\n                          dynamic_cast<const B<T>&> (y)));              \\\n  }                                                                     \\\n  inline R                                                              \\\n  operator - (const R& x, const R& y)                                   \\\n  {                                                                     \\\n    return R (operator - (dynamic_cast<const B<T>&> (x),                \\\n                          dynamic_cast<const B<T>&> (y)));              \\\n  }                                                                     \\\n  inline R                                                              \\\n  product (const R& x, const R& y)                                      \\\n  {                                                                     \\\n    return R (product (dynamic_cast<const B<T>&> (x),                   \\\n                       dynamic_cast<const B<T>&> (y)));                 \\\n  }\n\n#endif\n"
  },
  {
    "path": "liboctave/array/MSparse-C.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-cmplx.h\"\n\n#include \"MSparse.h\"\n\ntemplate class MSparse<Complex>;\n\nINSTANTIATE_SPARSE_FRIENDS (Complex, OCTAVE_API);\n"
  },
  {
    "path": "liboctave/array/MSparse-d.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"MSparse.h\"\n\ntemplate class MSparse<double>;\n\nINSTANTIATE_SPARSE_FRIENDS (double, OCTAVE_API);\n"
  },
  {
    "path": "liboctave/array/MSparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// sparse array with math ops.\n// Element by element MSparse by MSparse ops.\n\ntemplate <typename T, typename OP>\nMSparse<T>&\nplus_or_minus (MSparse<T>& a, const MSparse<T>& b, OP op, const char *op_name)\n{\n  MSparse<T> r;\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nr == 0 && (b_nr == 0 || b_nr == 1))\n    {\n      if (a_nc == 1 || b_nc == 1 || a_nc == b_nc)\n        r.resize (a_nr, std::max (a_nc, b_nc));\n      else\n        octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (a_nc == 0 && (b_nc == 0 || b_nc == 1))\n    {\n      if (a_nr == 1 || b_nr == 1 || a_nr == b_nr)\n        r.resize (std::max (a_nr, b_nr), a_nc);\n      else\n        octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (b_nr == 0 && (a_nr == 0 || a_nr == 1))\n    {\n      if (b_nc == 1 || a_nc == 1 || b_nc == a_nc)\n        r.resize (b_nr, std::max (a_nc, b_nc));\n      else\n        octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (b_nc == 0 && (a_nc == 0 || a_nc == 1))\n    {\n      if (b_nr == 1 || a_nr == 1 || b_nr == a_nr)\n        r.resize (std::max (a_nr, b_nr), b_nc);\n      else\n        octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (a_nr != b_nr || a_nc != b_nc)\n    octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n  else\n    {\n      r = MSparse<T> (a_nr, a_nc, (a.nnz () + b.nnz ()));\n\n      octave_idx_type jx = 0;\n      for (octave_idx_type i = 0 ; i < a_nc ; i++)\n        {\n          octave_idx_type ja = a.cidx (i);\n          octave_idx_type ja_max = a.cidx (i+1);\n          bool ja_lt_max = ja < ja_max;\n\n          octave_idx_type jb = b.cidx (i);\n          octave_idx_type jb_max = b.cidx (i+1);\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  r.ridx (jx) = a.ridx (ja);\n                  r.data (jx) = op (a.data (ja), 0.);\n                  jx++;\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                }\n              else if ((! ja_lt_max)\n                       || (b.ridx (jb) < a.ridx (ja)))\n                {\n                  r.ridx (jx) = b.ridx (jb);\n                  r.data (jx) = op (0., b.data (jb));\n                  jx++;\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n              else\n                {\n                  if (op (a.data (ja), b.data (jb)) != 0.)\n                    {\n                      r.data (jx) = op (a.data (ja), b.data (jb));\n                      r.ridx (jx) = a.ridx (ja);\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n    }\n  a = r.maybe_compress ();\n  return a;\n}\n\ntemplate <typename T>\nMSparse<T>&\noperator += (MSparse<T>& a, const MSparse<T>& b)\n{\n  return plus_or_minus (a, b, std::plus<T> (), \"operator +=\");\n}\n\ntemplate <typename T>\nMSparse<T>&\noperator -= (MSparse<T>& a, const MSparse<T>& b)\n{\n  return plus_or_minus (a, b, std::minus<T> (), \"operator -=\");\n}\n\n// Element by element MSparse by scalar ops.\n\ntemplate <typename T, typename OP>\nMArray<T>\nplus_or_minus (const MSparse<T>& a, const T& s, OP op)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  MArray<T> r;\n\n  if (octave::math::isnan (s))\n    r = MArray<T> (dim_vector (nr, nc), octave::numeric_limits<T>::NaN ());\n  else\n    {\n      r = MArray<T> (dim_vector (nr, nc), op (0.0, s));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n          r.elem (a.ridx (i), j) = op (a.data (i), s);\n    }\n  return r;\n}\n\ntemplate <typename T>\nMArray<T>\noperator + (const MSparse<T>& a, const T& s)\n{\n  return plus_or_minus (a, s, std::plus<T> ());\n}\n\ntemplate <typename T>\nMArray<T>\noperator - (const MSparse<T>& a, const T& s)\n{\n  return plus_or_minus (a, s, std::minus<T> ());\n}\n\ntemplate <typename T, typename OP>\nMSparse<T>\ntimes_or_divide (const MSparse<T>& a, const T& s, OP op)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n  octave_idx_type nz = a.nnz ();\n\n  MSparse<T> r;\n\n  // Handle scalars that affect zero elements in sparse array\n  bool non_zero = op (0.0, s) != 0.0;\n\n  if (non_zero)\n    {\n      r = MSparse<T> (nr, nc, nr * nc);\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          r.elem (i, j) = op (0.0, s);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = a.cidx(j); i < a.cidx (j+1); i++)\n          r.elem (a.ridx (i), j) = op (a.data (i), s);\n      r.maybe_compress (true);\n    }\n  else\n    {\n      r = MSparse<T> (nr, nc, nz);\n\n      for (octave_idx_type i = 0; i < nz; i++)\n        {\n          r.data (i) = op (a.data (i), s);\n          r.ridx (i) = a.ridx (i);\n        }\n      for (octave_idx_type i = 0; i < nc + 1; i++)\n        r.cidx (i) = a.cidx (i);\n      r.maybe_compress (true);\n    }\n  return r;\n}\n\ntemplate <typename T>\nMSparse<T>\noperator * (const MSparse<T>& a, const T& s)\n{\n  return times_or_divide (a, s, std::multiplies<T> ());\n}\n\ntemplate <typename T>\nMSparse<T>\noperator / (const MSparse<T>& a, const T& s)\n{\n  return times_or_divide (a, s, std::divides<T> ());\n}\n\n// Element by element scalar by MSparse ops.\n\ntemplate <typename T, typename OP>\nMArray<T>\nplus_or_minus (const T& s, const MSparse<T>& a, OP op)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  MArray<T> r;\n\n  if (octave::math::isnan (s))\n    r = MArray<T> (dim_vector (nr, nc), octave::numeric_limits<T>::NaN ());\n  else\n    {\n      r = MArray<T> (dim_vector (nr, nc), op (s, 0.0));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n          r.elem (a.ridx (i), j) = op (s, a.data (i));\n    }\n  return r;\n}\n\ntemplate <typename T>\nMArray<T>\noperator + (const T& s, const MSparse<T>& a)\n{\n  return plus_or_minus (s, a, std::plus<T> ());\n}\n\ntemplate <typename T>\nMArray<T>\noperator - (const T& s, const MSparse<T>& a)\n{\n  return plus_or_minus (s, a, std::minus<T> ());\n}\n\ntemplate <typename T, typename OP>\nMSparse<T>\ntimes_or_divide (const T& s, const MSparse<T>& a, OP op)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n  octave_idx_type nz = a.nnz ();\n\n  MSparse<T> r;\n\n  // Handle scalars that affect zero elements in sparse array\n  bool non_zero = op (s, 0.0) != 0.0;\n\n  if (non_zero)\n    {\n      r = MSparse<T> (nr, nc, nr * nc);\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          r.elem (i, j) = op (s, 0.0);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = a.cidx(j); i < a.cidx (j+1); i++)\n          r.elem (a.ridx (i), j) = op (s, a.data (i));\n      r.maybe_compress (true);\n    }\n  else\n    {\n      r = MSparse<T> (nr, nc, nz);\n\n      for (octave_idx_type i = 0; i < nz; i++)\n        {\n          r.data (i) = op (s, a.data (i));\n          r.ridx (i) = a.ridx (i);\n        }\n      for (octave_idx_type i = 0; i < nc + 1; i++)\n        r.cidx (i) = a.cidx (i);\n      r.maybe_compress (true);\n    }\n  return r;\n}\n\ntemplate <typename T>\nMSparse<T>\noperator * (const T& s, const MSparse<T>& a)\n{\n  return times_or_divide (s, a, std::multiplies<T> ());\n}\n\ntemplate <typename T>\nMSparse<T>\noperator / (const T& s, const MSparse<T>& a)\n{\n  return times_or_divide (s, a, std::divides<T> ());\n}\n\n// Element by element MSparse by MSparse ops.\n\ntemplate <typename T, typename OP>\nMSparse<T>\nplus_or_minus (const MSparse<T>& a, const MSparse<T>& b, OP op,\n               const char *op_name, bool negate)\n{\n  MSparse<T> r;\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nr == 1 && a_nc == 1)\n    {\n      if (a.elem (0, 0) == 0.)\n        if (negate)\n          r = -MSparse<T> (b);\n        else\n          r = MSparse<T> (b);\n      else\n        {\n          r = MSparse<T> (b_nr, b_nc, op (a.data (0), 0.));\n\n          for (octave_idx_type j = 0 ; j < b_nc ; j++)\n            {\n              octave_quit ();\n              octave_idx_type idxj = j * b_nr;\n              for (octave_idx_type i = b.cidx (j) ; i < b.cidx (j+1) ; i++)\n                {\n                  octave_quit ();\n                  r.data (idxj + b.ridx (i)) = op (a.data (0), b.data (i));\n                }\n            }\n          r.maybe_compress ();\n        }\n    }\n  else if (b_nr == 1 && b_nc == 1)\n    {\n      if (b.elem (0, 0) == 0.)\n        r = MSparse<T> (a);\n      else\n        {\n          r = MSparse<T> (a_nr, a_nc, op (0.0, b.data (0)));\n\n          for (octave_idx_type j = 0 ; j < a_nc ; j++)\n            {\n              octave_quit ();\n              octave_idx_type idxj = j * a_nr;\n              for (octave_idx_type i = a.cidx (j) ; i < a.cidx (j+1) ; i++)\n                {\n                  octave_quit ();\n                  r.data (idxj + a.ridx (i)) = op (a.data (i), b.data (0));\n                }\n            }\n          r.maybe_compress ();\n        }\n    }\n  else if (a_nr == 0 && (b_nr == 0 || b_nr == 1))\n    {\n      if (a_nc == 1 || b_nc == 1 || a_nc == b_nc)\n        r.resize (a_nr, std::max (a_nc, b_nc));\n      else\n        octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (a_nc == 0 && (b_nc == 0 || b_nc == 1))\n    {\n      if (a_nr == 1 || b_nr == 1 || a_nr == b_nr)\n        r.resize (std::max (a_nr, b_nr), a_nc);\n      else\n        octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (b_nr == 0 && (a_nr == 0 || a_nr == 1))\n    {\n      if (b_nc == 1 || a_nc == 1 || b_nc == a_nc)\n        r.resize (b_nr, std::max (a_nc, b_nc));\n      else\n        octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (b_nc == 0 && (a_nc == 0 || a_nc == 1))\n    {\n      if (b_nr == 1 || a_nr == 1 || b_nr == a_nr)\n        r.resize (std::max (a_nr, b_nr), b_nc);\n      else\n        octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (a_nr == b_nr && a_nc == b_nc)\n    {\n      r = MSparse<T> (a_nr, a_nc, (a.nnz () + b.nnz ()));\n\n      octave_idx_type jx = 0;\n      r.cidx (0) = 0;\n      for (octave_idx_type i = 0 ; i < a_nc ; i++)\n        {\n          octave_idx_type ja = a.cidx (i);\n          octave_idx_type ja_max = a.cidx (i+1);\n          bool ja_lt_max = ja < ja_max;\n\n          octave_idx_type jb = b.cidx (i);\n          octave_idx_type jb_max = b.cidx (i+1);\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  r.ridx (jx) = a.ridx (ja);\n                  r.data (jx) = op (a.data (ja), 0.);\n                  jx++;\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                }\n              else if ((! ja_lt_max) || (b.ridx (jb) < a.ridx (ja)))\n                {\n                  r.ridx (jx) = b.ridx (jb);\n                  r.data (jx) = op (0., b.data (jb));\n                  jx++;\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n              else\n                {\n                  if (op (a.data (ja), b.data (jb)) != 0.)\n                    {\n                      r.data (jx) = op (a.data (ja), b.data (jb));\n                      r.ridx (jx) = a.ridx (ja);\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n      r.maybe_compress ();\n    }\n  else if (a_nr == b_nr && (a_nc == 1 || b_nc == 1))\n    // (a_nc == b_nc && (a_nr == 1 || b_nr == 1)) is handled\n    // by double transpose in the caller functions\n    {\n      octave_idx_type r_nc = (a_nc < b_nc ? b_nc : a_nc);\n      octave_idx_type rnnz = (a_nc < b_nc ? a.nnz () * b_nc + b.nnz () :\n                                            a.nnz () + a_nc * b.nnz ());\n      r = MSparse<T> (a_nr, r_nc, rnnz);\n\n      octave_idx_type jx = 0;\n      r.cidx (0) = 0;\n      for (octave_idx_type i = 0 ; i < r_nc ; i++)\n        {\n          octave_idx_type ja;\n          octave_idx_type ja_max;\n          octave_idx_type jb;\n          octave_idx_type jb_max;\n          if (a_nc == 1)\n            {\n              ja = a.cidx(0);\n              ja_max = a.cidx(1);\n              jb = b.cidx (i);\n              jb_max = b.cidx (i+1);\n            }\n          else\n            {\n              ja = a.cidx(i);\n              ja_max = a.cidx(i+1);\n              jb = b.cidx (0);\n              jb_max = b.cidx (1);\n            }\n          bool ja_lt_max = ja < ja_max;\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  r.ridx (jx) = a.ridx (ja);\n                  r.data (jx) = op (a.data (ja), 0.);\n                  jx++;\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                }\n              else if ((! ja_lt_max) || (b.ridx (jb) < a.ridx (ja)))\n                {\n                  r.ridx (jx) = b.ridx (jb);\n                  r.data (jx) = op (0., b.data (jb));\n                  jx++;\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n              else\n                {\n                  if (op (a.data (ja), b.data (jb)) != 0.)\n                    {\n                      r.data (jx) = op (a.data (ja), b.data (jb));\n                      r.ridx (jx) = a.ridx (ja);\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n      r.maybe_compress ();\n    }\n  else if (a_nr == 1 && b_nc == 1)\n    // (a_nc == 1 && b_nr == 1) is handled\n    // by double transpose in the caller functions\n    {\n      // a: 1 x a_nc (row vector)\n      // b: b_nr x 1 (column vector)\n      //\n      // Result: outer broadcast\n      //   r(i,j) = op(a(0,j), b(i,0))\n\n      r = MSparse<T> (b_nr, a_nc, (a.nnz () * b_nr + b.nnz () * a_nc));\n\n      for (octave_idx_type j = 0; j < a_nc; j++)\n        {\n          const T a_val = a.elem (0, j);\n\n          for (octave_idx_type i = 0; i < b_nr; i++)\n            {\n              octave_quit ();\n\n              const T b_val = b.elem (i, 0);\n              const T val = op (a_val, b_val);\n\n              if (val != T ())\n                r.elem (i, j) = val;\n            }\n        }\n      r.maybe_compress ();\n    }\n  else\n    octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, b_nc);\n\n  return r;\n}\n\ntemplate <typename T>\nMSparse<T>\noperator + (const MSparse<T>& a, const MSparse<T>& b)\n{\n  if ((a.cols () != 1 && a.cols () == b.cols () &&\n       (a.rows () == 1 || b.rows () == 1)) ||\n      (a.cols () == 1 && b.rows () == 1 && a.rows () > 1 && b.cols () > 1))\n    return plus_or_minus (a.transpose (), b.transpose (), std::plus<T> (),\n                          \"operator +\", false).transpose ();\n  else\n    return plus_or_minus (a, b, std::plus<T> (), \"operator +\", false);\n}\n\ntemplate <typename T>\nMSparse<T>\noperator - (const MSparse<T>& a, const MSparse<T>& b)\n{\n  if ((a.cols () != 1 && a.cols () == b.cols () &&\n       (a.rows () == 1 || b.rows () == 1)) ||\n      (a.cols () == 1 && b.rows () == 1 && a.rows () > 1 && b.cols () > 1))\n    return plus_or_minus (a.transpose (), b.transpose (), std::minus<T> (),\n                          \"operator -\", true).transpose ();\n  else\n    return plus_or_minus (a, b, std::minus<T> (), \"operator -\", true);\n}\n\ntemplate <typename T>\nMSparse<T>\nproduct (const MSparse<T>& a, const MSparse<T>& b)\n{\n  MSparse<T> r;\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nr == 1 && a_nc == 1)\n    {\n      if (a.elem (0, 0) == 0.)\n        r = MSparse<T> (b_nr, b_nc);\n      else if (octave::math::isnan (a.elem (0, 0)))\n        {\n          r = MSparse<T> (b_nr, b_nc, b_nr * b_nc);\n          for (octave_idx_type i = 0 ; i < r.numel () ; i++)\n            r.elem(i) = octave::numeric_limits<T>::NaN ();\n        }\n      else if (octave::math::isinf (a.elem (0, 0)))\n        {\n          r = MSparse<T> (b_nr, b_nc, b_nr * b_nc);\n\n          for (octave_idx_type j = 0 ; j < b_nc ; j++)\n            {\n              octave_quit ();\n              for (octave_idx_type i = 0 ; i < b_nr ; i++)\n                {\n                  if (b.elem (i, j) == 0.0)\n                    r.elem (i, j) = octave::numeric_limits<T>::NaN ();\n                  else\n                    r.elem (i, j) = a.elem (0, 0) * b.elem (i, j);\n                }\n            }\n          r.maybe_compress (true);\n        }\n      else\n        {\n          r = MSparse<T> (b);\n          octave_idx_type b_nnz = b.nnz ();\n\n          for (octave_idx_type i = 0 ; i < b_nnz ; i++)\n            {\n              octave_quit ();\n              r.data (i) = a.data (0) * r.data (i);\n            }\n          r.maybe_compress ();\n        }\n    }\n  else if (b_nr == 1 && b_nc == 1)\n    {\n      if (b.elem (0, 0) == 0.)\n        r = MSparse<T> (a_nr, a_nc);\n      else if (octave::math::isnan (b.elem (0, 0)))\n        {\n          r = MSparse<T> (a_nr, a_nc, a_nr * a_nc);\n          for (octave_idx_type i = 0 ; i < r.numel () ; i++)\n            r.elem(i) = octave::numeric_limits<T>::NaN ();\n        }\n      else if (octave::math::isinf (b.elem (0, 0)))\n        {\n          r = MSparse<T> (a_nr, a_nc, a_nr * a_nc);\n\n          for (octave_idx_type j = 0 ; j < a_nc ; j++)\n            {\n              octave_quit ();\n              for (octave_idx_type i = 0 ; i < a_nr ; i++)\n                {\n                  if (a.elem (i, j) == 0.0)\n                    r.elem (i, j) = octave::numeric_limits<T>::NaN ();\n                  else\n                    r.elem (i, j) = a.elem (i, j) * b.elem (0, 0);\n                }\n            }\n          r.maybe_compress (true);\n        }\n      else\n        {\n          r = MSparse<T> (a);\n          octave_idx_type a_nnz = a.nnz ();\n\n          for (octave_idx_type i = 0 ; i < a_nnz ; i++)\n            {\n              octave_quit ();\n              r.data (i) = r.data (i) * b.data (0);\n            }\n          r.maybe_compress ();\n        }\n    }\n  else if (a_nr == 0 && (b_nr == 0 || b_nr == 1))\n    {\n      if (a_nc == 1 || b_nc == 1 || a_nc == b_nc)\n        r.resize (a_nr, std::max (a_nc, b_nc));\n      else\n        octave::err_nonconformant (\"product\", a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (a_nc == 0 && (b_nc == 0 || b_nc == 1))\n    {\n      if (a_nr == 1 || b_nr == 1 || a_nr == b_nr)\n        r.resize (std::max (a_nr, b_nr), a_nc);\n      else\n        octave::err_nonconformant (\"product\", a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (b_nr == 0 && (a_nr == 0 || a_nr == 1))\n    {\n      if (b_nc == 1 || a_nc == 1 || b_nc == a_nc)\n        r.resize (b_nr, std::max (a_nc, b_nc));\n      else\n        octave::err_nonconformant (\"product\", a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (b_nc == 0 && (a_nc == 0 || a_nc == 1))\n    {\n      if (b_nr == 1 || a_nr == 1 || b_nr == a_nr)\n        r.resize (std::max (a_nr, b_nr), b_nc);\n      else\n        octave::err_nonconformant (\"product\", a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (a_nr == b_nr && a_nc == b_nc &&\n           (a.any_element_is_inf_or_nan () || b.any_element_is_inf_or_nan ()))\n    {\n      r = MSparse<T> (a_nr, a_nc, a_nr * a_nc);\n\n      for (octave_idx_type j = 0 ; j < a_nc ; j++)\n        {\n          octave_quit ();\n          for (octave_idx_type i = 0 ; i < a_nr ; i++)\n            r.elem (i, j) = a.elem (i, j) * b.elem (i, j);\n        }\n      r.maybe_compress (true);\n    }\n  else if (a_nr == b_nr && a_nc == b_nc)\n    {\n      r = MSparse<T> (a_nr, a_nc, (a.nnz () > b.nnz () ? a.nnz () : b.nnz ()));\n\n      octave_idx_type jx = 0;\n      r.cidx (0) = 0;\n      for (octave_idx_type i = 0 ; i < a_nc ; i++)\n        {\n          octave_idx_type ja = a.cidx (i);\n          octave_idx_type ja_max = a.cidx (i+1);\n          bool ja_lt_max = ja < ja_max;\n\n          octave_idx_type jb = b.cidx (i);\n          octave_idx_type jb_max = b.cidx (i+1);\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                }\n              else if ((! ja_lt_max) || (b.ridx (jb) < a.ridx (ja)))\n                {\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n              else\n                {\n                  if ((a.data (ja) * b.data (jb)) != 0.)\n                    {\n                      r.data (jx) = a.data (ja) * b.data (jb);\n                      r.ridx (jx) = a.ridx (ja);\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n      r.maybe_compress ();\n    }\n  else if (a_nr == b_nr && (a_nc == 1 || b_nc == 1) &&\n           (a.any_element_is_inf_or_nan () || b.any_element_is_inf_or_nan ()))\n    {\n      octave_idx_type r_nc = (a_nc < b_nc ? b_nc : a_nc);\n      r = MSparse<T> (a_nr, r_nc, a_nr * r_nc);\n\n      if (a_nc == 1)\n        {\n          for (octave_idx_type j = 0 ; j < r_nc ; j++)\n            {\n              octave_quit ();\n              for (octave_idx_type i = 0 ; i < a_nr ; i++)\n                r.elem (i, j) = a.elem (i, 0) * b.elem (i, j);\n            }\n        }\n      else\n        {\n          for (octave_idx_type j = 0 ; j < r_nc ; j++)\n            {\n              octave_quit ();\n              for (octave_idx_type i = 0 ; i < a_nr ; i++)\n                r.elem (i, j) = a.elem (i, j) * b.elem (i, 0);\n            }\n        }\n      r.maybe_compress (true);\n    }\n  else if (a_nr == b_nr && (a_nc == 1 || b_nc == 1))\n    {\n      octave_idx_type r_nc = (a_nc < b_nc ? b_nc : a_nc);\n      octave_idx_type rnnz = (a_nc < b_nc ? a.nnz () * b_nc + b.nnz () :\n                                            a.nnz () + a_nc * b.nnz ());\n      r = MSparse<T> (a_nr, r_nc, rnnz);\n\n      octave_idx_type jx = 0;\n      r.cidx (0) = 0;\n      for (octave_idx_type i = 0 ; i < r_nc ; i++)\n        {\n          octave_idx_type ja;\n          octave_idx_type ja_max;\n          octave_idx_type jb;\n          octave_idx_type jb_max;\n          if (a_nc == 1)\n            {\n              ja = a.cidx(0);\n              ja_max = a.cidx(1);\n              jb = b.cidx (i);\n              jb_max = b.cidx (i+1);\n            }\n          else\n            {\n              ja = a.cidx(i);\n              ja_max = a.cidx(i+1);\n              jb = b.cidx (0);\n              jb_max = b.cidx (1);\n            }\n          bool ja_lt_max = ja < ja_max;\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                }\n              else if ((! ja_lt_max) || (b.ridx (jb) < a.ridx (ja)))\n                {\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n              else\n                {\n                  if ((a.data (ja) * b.data (jb)) != 0.)\n                    {\n                      r.data (jx) = a.data (ja) * b.data (jb);\n                      r.ridx (jx) = a.ridx (ja);\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n      r.maybe_compress ();\n    }\n  else if (a_nc == b_nc && (a_nr == 1 || b_nr == 1))\n    r = product (a.transpose (), b.transpose ()).transpose ();\n  else if (a_nr == 1 && b_nc == 1 &&\n           (a.any_element_is_inf_or_nan () || b.any_element_is_inf_or_nan ()))\n    {\n      r = MSparse<T> (b_nr, a_nc, b_nr * a_nc);\n\n      for (octave_idx_type j = 0 ; j < a_nc ; j++)\n        {\n          octave_quit ();\n          for (octave_idx_type i = 0 ; i < b_nr ; i++)\n            r.elem (i, j) = a.elem (0, j) * b.elem (i, 0);\n        }\n      r.maybe_compress (true);\n    }\n  else if (a_nr == 1 && b_nc == 1)\n    {\n      r = MSparse<T> (b_nr, a_nc, (a.nnz () * b_nr + b.nnz () * a_nc));\n\n      octave_idx_type jx = 0;\n      r.cidx (0) = 0;\n      for (octave_idx_type i = 0 ; i < a_nc ; i++)\n        {\n          octave_idx_type ja = a.cidx (i);\n          octave_idx_type ja_max = a.cidx (i+1);\n          bool ja_lt_max = ja < ja_max;\n\n          octave_idx_type jb = b.cidx (0);\n          octave_idx_type jb_max = b.cidx (1);\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if (! ja_lt_max && jb_lt_max)\n                {\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n              else if (ja_lt_max && ! jb_lt_max)\n                {\n                  ja_lt_max = false;\n                }\n              else // (ja_lt_max && jb_lt_max)\n                {\n                  if ((a.data (ja) * b.data (jb)) != 0.)\n                    {\n                      r.data (jx) = a.data (ja) * b.data (jb);\n                      r.ridx (jx) = b.ridx (jb);\n                      jx++;\n                    }\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                  ja_lt_max = jb_lt_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n      r.maybe_compress ();\n    }\n  else if (a_nc == 1 && b_nr == 1)\n    r = product (a.transpose (), b.transpose ()).transpose ();\n  else\n    octave::err_nonconformant (\"product\", a_nr, a_nc, b_nr, b_nc);\n\n  return r;\n}\n\ntemplate <typename T>\nMSparse<T>\nquotient (const MSparse<T>& a, const MSparse<T>& b)\n{\n  MSparse<T> r;\n  T Zero = T ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nr == 1 && a_nc == 1)\n    {\n      T val = a.elem (0, 0);\n      T fill = val / T ();\n      if (fill == T ())\n        {\n          octave_idx_type b_nnz = b.nnz ();\n          r = MSparse<T> (b);\n          for (octave_idx_type i = 0 ; i < b_nnz ; i++)\n            r.data (i) = val / r.data (i);\n          r.maybe_compress (true);\n        }\n      else\n        {\n          r = MSparse<T> (b_nr, b_nc, fill);\n          for (octave_idx_type j = 0 ; j < b_nc ; j++)\n            {\n              octave_quit ();\n              octave_idx_type idxj = j * b_nr;\n              for (octave_idx_type i = b.cidx (j) ; i < b.cidx (j+1) ; i++)\n                {\n                  octave_quit ();\n                  r.data (idxj + b.ridx (i)) = val / b.data (i);\n                }\n            }\n          r.maybe_compress (true);\n        }\n    }\n  else if (b_nr == 1 && b_nc == 1)\n    {\n      T val = b.elem (0, 0);\n      T fill = T () / val;\n      if (fill == T ())\n        {\n          octave_idx_type a_nnz = a.nnz ();\n          r = MSparse<T> (a);\n          for (octave_idx_type i = 0 ; i < a_nnz ; i++)\n            r.data (i) = r.data (i) / val;\n          r.maybe_compress (true);\n        }\n      else\n        {\n          r = MSparse<T> (a_nr, a_nc, fill);\n          for (octave_idx_type j = 0 ; j < a_nc ; j++)\n            {\n              octave_quit ();\n              octave_idx_type idxj = j * a_nr;\n              for (octave_idx_type i = a.cidx (j) ; i < a.cidx (j+1) ; i++)\n                {\n                  octave_quit ();\n                  r.data (idxj + a.ridx (i)) = a.data (i) / val;\n                }\n            }\n          r.maybe_compress (true);\n        }\n    }\n  else if (a_nr == 0 && (b_nr == 0 || b_nr == 1))\n    {\n      if (a_nc == 1 || b_nc == 1 || a_nc == b_nc)\n        r.resize (a_nr, std::max (a_nc, b_nc));\n      else\n        octave::err_nonconformant (\"quotient\", a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (a_nc == 0 && (b_nc == 0 || b_nc == 1))\n    {\n      if (a_nr == 1 || b_nr == 1 || a_nr == b_nr)\n        r.resize (std::max (a_nr, b_nr), a_nc);\n      else\n        octave::err_nonconformant (\"quotient\", a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (b_nr == 0 && (a_nr == 0 || a_nr == 1))\n    {\n      if (b_nc == 1 || a_nc == 1 || b_nc == a_nc)\n        r.resize (b_nr, std::max (a_nc, b_nc));\n      else\n        octave::err_nonconformant (\"quotient\", a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (b_nc == 0 && (a_nc == 0 || a_nc == 1))\n    {\n      if (b_nr == 1 || a_nr == 1 || b_nr == a_nr)\n        r.resize (std::max (a_nr, b_nr), b_nc);\n      else\n        octave::err_nonconformant (\"quotient\", a_nr, a_nc, b_nr, b_nc);\n    }\n  else if (a_nr == b_nr && a_nc == b_nc)\n    {\n      r = MSparse<T> (a_nr, a_nc, (Zero / Zero));\n\n      for (octave_idx_type i = 0 ; i < a_nc ; i++)\n        {\n          octave_idx_type ja = a.cidx (i);\n          octave_idx_type ja_max = a.cidx (i+1);\n          bool ja_lt_max = ja < ja_max;\n\n          octave_idx_type jb = b.cidx (i);\n          octave_idx_type jb_max = b.cidx (i+1);\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  r.elem (a.ridx (ja), i) = a.data (ja) / Zero;\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                }\n              else if ((! ja_lt_max) || (b.ridx (jb) < a.ridx (ja)))\n                {\n                  r.elem (b.ridx (jb), i) = Zero / b.data (jb);\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n              else\n                {\n                  r.elem (a.ridx (ja), i) = a.data (ja) / b.data (jb);\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n            }\n        }\n      r.maybe_compress (true);\n    }\n  else if (a_nr == b_nr && (a_nc == 1 || b_nc == 1))\n    {\n      octave_idx_type r_nc = (a_nc < b_nc ? b_nc : a_nc);\n      r = MSparse<T> (a_nr, r_nc, (Zero / Zero));\n\n      for (octave_idx_type i = 0 ; i < r_nc ; i++)\n        {\n          octave_idx_type ja;\n          octave_idx_type ja_max;\n          octave_idx_type jb;\n          octave_idx_type jb_max;\n          if (a_nc == 1)\n            {\n              ja = a.cidx(0);\n              ja_max = a.cidx(1);\n              jb = b.cidx (i);\n              jb_max = b.cidx (i+1);\n            }\n          else\n            {\n              ja = a.cidx(i);\n              ja_max = a.cidx(i+1);\n              jb = b.cidx (0);\n              jb_max = b.cidx (1);\n            }\n          bool ja_lt_max = ja < ja_max;\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  r.elem (a.ridx (ja), i) = a.data (ja) / Zero;\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                }\n              else if ((! ja_lt_max) || (b.ridx (jb) < a.ridx (ja)))\n                {\n                  r.elem (b.ridx (jb), i) = Zero / b.data (jb);\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n              else\n                {\n                  r.elem (a.ridx (ja), i) = a.data (ja) / b.data (jb);\n                  ja++;\n                  ja_lt_max = ja < ja_max;\n                  jb++;\n                  jb_lt_max = jb < jb_max;\n                }\n            }\n        }\n      r.maybe_compress (true);\n    }\n  else if (a_nc == b_nc && (a_nr == 1 || b_nr == 1))\n    r = quotient (a.transpose (), b.transpose ()).transpose ();\n  else if (a_nr == 1 && b_nc == 1)\n    {\n      r = MSparse<T> (b_nr, a_nc, (a_nc * b_nr));\n\n      for (octave_idx_type j = 0; j < a_nc; j++)\n        {\n          const T a_val = a.elem (0, j);\n\n          for (octave_idx_type i = 0; i < b_nr; i++)\n            {\n              octave_quit ();\n\n              const T b_val = b.elem (i, 0);\n              const T val = a_val / b_val;\n\n              if (val != Zero || val != val)\n                r.elem (i, j) = val;\n            }\n        }\n      r.maybe_compress (true);\n    }\n  else if (a_nc == 1 && b_nr == 1)\n    r = quotient (a.transpose (), b.transpose ()).transpose ();\n  else\n    octave::err_nonconformant (\"quotient\", a_nr, a_nc, b_nr, b_nc);\n\n  return r;\n}\n\n// Unary MSparse ops.\n\ntemplate <typename T>\nMSparse<T>\noperator + (const MSparse<T>& a)\n{\n  return a;\n}\n\ntemplate <typename T>\nMSparse<T>\noperator - (const MSparse<T>& a)\n{\n  MSparse<T> retval (a);\n  octave_idx_type nz = a.nnz ();\n  for (octave_idx_type i = 0; i < nz; i++)\n    retval.data (i) = - retval.data (i);\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/array/MSparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_MSparse_h)\n#define octave_MSparse_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-util.h\"\n#include \"MArray.h\"\n#include \"Sparse.h\"\n#include \"oct-error.h\"\n#include \"quit.h\"\n\n\n// forward declare template with visibility attributes\ntemplate <typename T> class OCTAVE_API MSparse;\n\n// Two-dimensional sparse array with math ops.\ntemplate <typename T>\nclass OCTAVE_API MSparse : public Sparse<T>\n{\npublic:\n\n  MSparse () : Sparse<T> () { }\n\n  MSparse (octave_idx_type n, octave_idx_type m) : Sparse<T> (n, m) { }\n\n  MSparse (const dim_vector& dv, octave_idx_type nz = 0)\n    : Sparse<T> (dv, nz) { }\n\n  MSparse (const MSparse<T>& a) : Sparse<T> (a) { }\n\n  MSparse (const MSparse<T>& a, const dim_vector& dv) : Sparse<T> (a, dv) { }\n\n  MSparse (const Sparse<T>& a) : Sparse<T> (a) { }\n\n  template <typename U>\n  MSparse (const Sparse<U>& a) : Sparse<T> (a) { }\n\n  MSparse (const Array<T>& a, const octave::idx_vector& r, const octave::idx_vector& c,\n           octave_idx_type nr = -1, octave_idx_type nc = -1,\n           bool sum_terms = true, octave_idx_type nzm = -1)\n    : Sparse<T> (a, r, c, nr, nc, sum_terms, nzm) { }\n\n  explicit MSparse (octave_idx_type r, octave_idx_type c, T val)\n    : Sparse<T> (r, c, val) { }\n\n  explicit MSparse (const PermMatrix& a) : Sparse<T> (a) { }\n\n  MSparse (octave_idx_type r, octave_idx_type c, octave_idx_type num_nz)\n    : Sparse<T> (r, c, num_nz) { }\n\n  ~MSparse () = default;\n\n  MSparse<T>& operator = (const MSparse<T>& a)\n  {\n    Sparse<T>::operator = (a);\n    return *this;\n  }\n\n  MSparse<T>& insert (const Sparse<T>& a, octave_idx_type r, octave_idx_type c)\n  {\n    Sparse<T>::insert (a, r, c);\n    return *this;\n  }\n\n  MSparse<T>& insert (const Sparse<T>& a, const Array<octave_idx_type>& indx)\n  {\n    Sparse<T>::insert (a, indx);\n    return *this;\n  }\n\n  MSparse<T> transpose () const { return Sparse<T>::transpose (); }\n\n  MSparse<T> squeeze () const { return Sparse<T>::squeeze (); }\n\n  MSparse<T> reshape (const dim_vector& new_dims) const\n  { return Sparse<T>::reshape (new_dims); }\n\n  MSparse<T> permute (const Array<octave_idx_type>& vec, bool inv = false) const\n  { return Sparse<T>::permute (vec, inv); }\n\n  MSparse<T> ipermute (const Array<octave_idx_type>& vec) const\n  { return Sparse<T>::ipermute (vec); }\n\n  MSparse<T> diag (octave_idx_type k = 0) const\n  {\n    return Sparse<T>::diag (k);\n  }\n\n  // FIXME: should go away.\n  template <typename U>\n  Sparse<U>\n  map (U (&fcn) (T)) const\n  { return Sparse<T>::template map<U> (fcn); }\n\n  template <typename U>\n  Sparse<U>\n  map (U (&fcn) (const T&)) const\n  { return Sparse<T>::template map<U> (fcn); }\n};\n\n// Include operator templates for MSparse\n#include \"MSparse.cc\"\n\n// A macro that can be used to declare and instantiate OP= operators.\n#define SPARSE_OP_ASSIGN_DECL(T, OP, API)       \\\n  template API MSparse<T>&                      \\\n  operator OP (MSparse<T>&, const MSparse<T>&)\n\n// A macro that can be used to declare and instantiate unary operators.\n#define SPARSE_UNOP_DECL(T, OP, API)            \\\n  template API MSparse<T>                       \\\n  operator OP (const MSparse<T>&)\n\n// A macro that can be used to declare and instantiate binary operators.\n#define SPARSE_BINOP_DECL(A_T, T, F, API, X_T, Y_T)     \\\n  template API A_T<T>                                   \\\n  F (const X_T&, const Y_T&)\n\n// A function that can be used to forward OP= operations from derived\n// classes back to us.\n#define SPARSE_OP_ASSIGN_FWD_FCN(R, F, T, C_X, X_T, C_Y, Y_T)   \\\n  inline R                                                      \\\n  F (X_T& x, const Y_T& y)                                      \\\n  {                                                             \\\n    return R (F (C_X (x), C_Y (y)));                            \\\n  }\n\n// A function that can be used to forward unary operations from derived\n// classes back to us.\n#define SPARSE_UNOP_FWD_FCN(R, F, T, C_X, X_T)  \\\n  inline R                                      \\\n  F (const X_T& x)                              \\\n  {                                             \\\n    return R (F (C_X (x)));                     \\\n  }\n\n// A function that can be used to forward binary operations from derived\n// classes back to us.\n#define SPARSE_BINOP_FWD_FCN(R, F, T, C_X, X_T, C_Y, Y_T)       \\\n  inline R                                                      \\\n  F (const X_T& x, const Y_T& y)                                \\\n  {                                                             \\\n    return R (F (C_X (x), C_Y (y)));                            \\\n  }\n\n// Instantiate all the MSparse friends for MSparse element type T.\n#define INSTANTIATE_SPARSE_FRIENDS(T, API)                              \\\n  SPARSE_OP_ASSIGN_DECL (T, +=, API);                                   \\\n  SPARSE_OP_ASSIGN_DECL (T, -=, API);                                   \\\n  SPARSE_UNOP_DECL (T, +, API);                                         \\\n  SPARSE_UNOP_DECL (T, -, API);                                         \\\n  SPARSE_BINOP_DECL (MArray,  T, operator +, API, MSparse<T>, T);       \\\n  SPARSE_BINOP_DECL (MArray,  T, operator -, API, MSparse<T>, T);       \\\n  SPARSE_BINOP_DECL (MSparse, T, operator *, API, MSparse<T>, T);       \\\n  SPARSE_BINOP_DECL (MSparse, T, operator /, API, MSparse<T>, T);       \\\n  SPARSE_BINOP_DECL (MArray,  T, operator +, API, T, MSparse<T>);       \\\n  SPARSE_BINOP_DECL (MArray,  T, operator -, API, T, MSparse<T>);       \\\n  SPARSE_BINOP_DECL (MSparse, T, operator *, API, T, MSparse<T>);       \\\n  SPARSE_BINOP_DECL (MSparse, T, operator /, API, T, MSparse<T>);       \\\n  SPARSE_BINOP_DECL (MSparse, T, operator +, API, MSparse<T>, MSparse<T>); \\\n  SPARSE_BINOP_DECL (MSparse, T, operator -, API, MSparse<T>, MSparse<T>); \\\n  SPARSE_BINOP_DECL (MSparse, T, quotient,   API, MSparse<T>, MSparse<T>); \\\n  SPARSE_BINOP_DECL (MSparse, T, product,    API, MSparse<T>, MSparse<T>);\n\n// Define all the MSparse forwarding functions for return type R and\n// MSparse element type T\n#define SPARSE_FORWARD_DEFS(B, R, F, T)                                 \\\n  SPARSE_OP_ASSIGN_FWD_FCN (R, operator +=, T, dynamic_cast<B<T>&>,     \\\n                            R, dynamic_cast<const B<T>&>, R)            \\\n  SPARSE_OP_ASSIGN_FWD_FCN (R, operator -=, T, dynamic_cast<B<T>&>,     \\\n                            R, dynamic_cast<const B<T>&>, R)            \\\n  SPARSE_UNOP_FWD_FCN (R, operator +, T, dynamic_cast<const B<T>&>, R)  \\\n  SPARSE_UNOP_FWD_FCN (R, operator -, T, dynamic_cast<const B<T>&>, R)  \\\n  SPARSE_BINOP_FWD_FCN (F, operator +, T, dynamic_cast<const B<T>&>, R, , T) \\\n  SPARSE_BINOP_FWD_FCN (F, operator -, T, dynamic_cast<const B<T>&>, R, , T) \\\n  SPARSE_BINOP_FWD_FCN (R, operator *, T, dynamic_cast<const B<T>&>, R, , T) \\\n  SPARSE_BINOP_FWD_FCN (R, operator /, T, dynamic_cast<const B<T>&>, R, , T) \\\n  SPARSE_BINOP_FWD_FCN (F, operator +, T, , T, dynamic_cast<const B<T>&>, R) \\\n  SPARSE_BINOP_FWD_FCN (F, operator -, T, , T, dynamic_cast<const B<T>&>, R) \\\n  SPARSE_BINOP_FWD_FCN (R, operator *, T, , T, dynamic_cast<const B<T>&>, R) \\\n  SPARSE_BINOP_FWD_FCN (R, operator /, T, , T, dynamic_cast<const B<T>&>, R) \\\n  SPARSE_BINOP_FWD_FCN (R, operator +, T, dynamic_cast<const B<T>&>,    \\\n                        R, dynamic_cast<const B<T>&>, R)                \\\n  SPARSE_BINOP_FWD_FCN (R, operator -, T, dynamic_cast<const B<T>&>,    \\\n                        R, dynamic_cast<const B<T>&>, R)                \\\n  SPARSE_BINOP_FWD_FCN (R, product,    T, dynamic_cast<const B<T>&>,    \\\n                        R, dynamic_cast<const B<T>&>, R)                \\\n  SPARSE_BINOP_FWD_FCN (R, quotient, T, dynamic_cast<const B<T>&>,      \\\n                        R, dynamic_cast<const B<T>&>, R)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/Matrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// Should probably say something here about why these classes are not\n// represented by some sort of inheritance tree...\n\n#if ! defined (octave_Matrix_h)\n#define octave_Matrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-base.h\"\n#include \"mx-ext.h\"\n#include \"mx-ops.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/array/MatrixType.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <vector>\n\n#include \"MatrixType.h\"\n#include \"dMatrix.h\"\n#include \"fMatrix.h\"\n#include \"CMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"dSparse.h\"\n#include \"CSparse.h\"\n#include \"oct-spparms.h\"\n#include \"oct-locbuf.h\"\n\nstatic void\nwarn_cached ()\n{\n  (*current_liboctave_warning_with_id_handler)\n    (\"Octave:matrix-type-info\", \"using cached matrix type\");\n}\n\nstatic void\nwarn_invalid ()\n{\n  (*current_liboctave_warning_with_id_handler)\n    (\"Octave:matrix-type-info\", \"invalid matrix type\");\n}\n\nstatic void\nwarn_calculating_sparse_type ()\n{\n  (*current_liboctave_warning_with_id_handler)\n    (\"Octave:matrix-type-info\", \"calculating sparse matrix type\");\n}\n\n// FIXME: There is a large code duplication here\n\nMatrixType::MatrixType ()\n  : m_type (MatrixType::Unknown),\n    m_sp_bandden (octave::sparse_params::get_bandden ()),\n    m_bandden (0), m_upper_band (0), m_lower_band (0),\n    m_dense (false), m_full (false), m_nperm (0), m_perm (nullptr) { }\n\nMatrixType::MatrixType (const MatrixType& a)\n  : m_type (a.m_type), m_sp_bandden (a.m_sp_bandden), m_bandden (a.m_bandden),\n    m_upper_band (a.m_upper_band), m_lower_band (a.m_lower_band),\n    m_dense (a.m_dense), m_full (a.m_full),\n    m_nperm (a.m_nperm), m_perm (nullptr)\n{\n  if (m_nperm != 0)\n    {\n      m_perm = new octave_idx_type [m_nperm];\n      for (octave_idx_type i = 0; i < m_nperm; i++)\n        m_perm[i] = a.m_perm[i];\n    }\n}\n\ntemplate <typename T>\nMatrixType::matrix_type\nmatrix_real_probe (const MArray<T>& a)\n{\n  MatrixType::matrix_type m_type;\n  octave_idx_type nrows = a.rows ();\n  octave_idx_type ncols = a.cols ();\n\n  const T zero = 0;\n\n  if (ncols == nrows)\n    {\n      bool upper = true;\n      bool lower = true;\n      bool hermitian = true;\n\n      // do the checks for lower/upper/hermitian all in one pass.\n      OCTAVE_LOCAL_BUFFER (T, diag, ncols);\n\n      for (octave_idx_type j = 0;\n           j < ncols && upper; j++)\n        {\n          T d = a.elem (j, j);\n          upper = upper && (d != zero);\n          lower = lower && (d != zero);\n          hermitian = hermitian && (d > zero);\n          diag[j] = d;\n        }\n\n      for (octave_idx_type j = 0;\n           j < ncols && (upper || lower || hermitian); j++)\n        {\n          for (octave_idx_type i = 0; i < j; i++)\n            {\n              T aij = a.elem (i, j);\n              T aji = a.elem (j, i);\n              lower = lower && (aij == zero);\n              upper = upper && (aji == zero);\n              hermitian = hermitian && (aij == aji\n                                        && aij*aij < diag[i]*diag[j]);\n            }\n        }\n\n      if (upper)\n        m_type = MatrixType::Upper;\n      else if (lower)\n        m_type = MatrixType::Lower;\n      else if (hermitian)\n        m_type = MatrixType::Hermitian;\n      else\n        m_type = MatrixType::Full;\n    }\n  else\n    m_type = MatrixType::Rectangular;\n\n  return m_type;\n}\n\ntemplate <typename T>\nMatrixType::matrix_type\nmatrix_complex_probe (const MArray<std::complex<T>>& a)\n{\n  MatrixType::matrix_type m_type = MatrixType::Unknown;\n  octave_idx_type nrows = a.rows ();\n  octave_idx_type ncols = a.cols ();\n\n  const T zero = 0;\n  // get the real type\n\n  if (ncols == nrows)\n    {\n      bool upper = true;\n      bool lower = true;\n      bool hermitian = true;\n\n      // do the checks for lower/upper/hermitian all in one pass.\n      OCTAVE_LOCAL_BUFFER (T, diag, ncols);\n\n      for (octave_idx_type j = 0;\n           j < ncols && upper; j++)\n        {\n          std::complex<T> d = a.elem (j, j);\n          upper = upper && (d != zero);\n          lower = lower && (d != zero);\n          hermitian = hermitian && (d.real () > zero && d.imag () == zero);\n          diag[j] = d.real ();\n        }\n\n      for (octave_idx_type j = 0;\n           j < ncols && (upper || lower || hermitian); j++)\n        {\n          for (octave_idx_type i = 0; i < j; i++)\n            {\n              std::complex<T> aij = a.elem (i, j);\n              std::complex<T> aji = a.elem (j, i);\n              lower = lower && (aij == zero);\n              upper = upper && (aji == zero);\n              hermitian = hermitian && (aij == octave::math::conj (aji)\n                                        && std::norm (aij) < diag[i]*diag[j]);\n            }\n        }\n\n      if (upper)\n        m_type = MatrixType::Upper;\n      else if (lower)\n        m_type = MatrixType::Lower;\n      else if (hermitian)\n        m_type = MatrixType::Hermitian;\n      else\n        m_type = MatrixType::Full;\n    }\n  else\n    m_type = MatrixType::Rectangular;\n\n  return m_type;\n}\n\nMatrixType::MatrixType (const Matrix& a)\n  : m_type (MatrixType::Unknown),\n    m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),\n    m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr)\n{\n  m_type = matrix_real_probe (a);\n}\n\nMatrixType::MatrixType (const ComplexMatrix& a)\n  : m_type (MatrixType::Unknown),\n    m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),\n    m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr)\n{\n  m_type = matrix_complex_probe (a);\n}\n\nMatrixType::MatrixType (const FloatMatrix& a)\n  : m_type (MatrixType::Unknown),\n    m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),\n    m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr)\n{\n  m_type = matrix_real_probe (a);\n}\n\nMatrixType::MatrixType (const FloatComplexMatrix& a)\n  : m_type (MatrixType::Unknown),\n    m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),\n    m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr)\n{\n  m_type = matrix_complex_probe (a);\n}\n\n\ntemplate <typename T>\nMatrixType::MatrixType (const MSparse<T>& a)\n  : m_type (MatrixType::Unknown),\n    m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),\n    m_dense (false), m_full (false), m_nperm (0), m_perm (nullptr)\n{\n  octave_idx_type nrows = a.rows ();\n  octave_idx_type ncols = a.cols ();\n  octave_idx_type nm = (ncols < nrows ? ncols : nrows);\n  octave_idx_type nnz = a.nnz ();\n\n  if (octave::sparse_params::get_key (\"spumoni\") != 0.)\n    warn_calculating_sparse_type ();\n\n  m_sp_bandden = octave::sparse_params::get_bandden ();\n  bool maybe_hermitian = false;\n  m_type = MatrixType::Full;\n\n  if (nnz == nm)\n    {\n      matrix_type tmp_typ = MatrixType::Diagonal;\n      octave_idx_type i;\n      // Maybe the matrix is diagonal\n      for (i = 0; i < nm; i++)\n        {\n          if (a.cidx (i+1) != a.cidx (i) + 1)\n            {\n              tmp_typ = MatrixType::Full;\n              break;\n            }\n          if (a.ridx (i) != i)\n            {\n              tmp_typ = MatrixType::Permuted_Diagonal;\n              break;\n            }\n        }\n\n      if (tmp_typ == MatrixType::Permuted_Diagonal)\n        {\n          std::vector<bool> found (nrows);\n\n          for (octave_idx_type j = 0; j < i; j++)\n            found[j] = true;\n          for (octave_idx_type j = i; j < nrows; j++)\n            found[j] = false;\n\n          for (octave_idx_type j = i; j < nm; j++)\n            {\n              if ((a.cidx (j+1) > a.cidx (j) + 1)\n                  || ((a.cidx (j+1) == a.cidx (j) + 1) && found[a.ridx (j)]))\n                {\n                  tmp_typ = MatrixType::Full;\n                  break;\n                }\n              found[a.ridx (j)] = true;\n            }\n        }\n      m_type = tmp_typ;\n    }\n\n  if (m_type == MatrixType::Full)\n    {\n      // Search for banded, upper and lower triangular matrices\n      bool singular = false;\n      m_upper_band = 0;\n      m_lower_band = 0;\n      for (octave_idx_type j = 0; j < ncols; j++)\n        {\n          bool zero_on_diagonal = false;\n          if (j < nrows)\n            {\n              zero_on_diagonal = true;\n              for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n                if (a.ridx (i) == j)\n                  {\n                    zero_on_diagonal = false;\n                    break;\n                  }\n            }\n\n          if (zero_on_diagonal)\n            {\n              singular = true;\n              break;\n            }\n\n          if (a.cidx (j+1) != a.cidx (j))\n            {\n              octave_idx_type ru = a.ridx (a.cidx (j));\n              octave_idx_type rl = a.ridx (a.cidx (j+1)-1);\n\n              if (j - ru > m_upper_band)\n                m_upper_band = j - ru;\n\n              if (rl - j > m_lower_band)\n                m_lower_band = rl - j;\n            }\n        }\n\n      if (! singular)\n        {\n          m_bandden = double (nnz) /\n                      (double (ncols) * (double (m_lower_band) +\n                                         double (m_upper_band)) -\n                       0.5 * double (m_upper_band + 1) * double (m_upper_band) -\n                       0.5 * double (m_lower_band + 1) * double (m_lower_band));\n\n          if (nrows == ncols && m_sp_bandden != 1. && m_bandden > m_sp_bandden)\n            {\n              if (m_upper_band == 1 && m_lower_band == 1)\n                m_type = MatrixType::Tridiagonal;\n              else\n                m_type = MatrixType::Banded;\n\n              octave_idx_type nnz_in_band\n                = ((m_upper_band + m_lower_band + 1) * nrows\n                   - (1 + m_upper_band) * m_upper_band / 2\n                   - (1 + m_lower_band) * m_lower_band / 2);\n\n              if (nnz_in_band == nnz)\n                m_dense = true;\n              else\n                m_dense = false;\n            }\n\n          // If a matrix is Banded but also Upper/Lower, set to the latter.\n          if (m_upper_band == 0)\n            m_type = MatrixType::Lower;\n          else if (m_lower_band == 0)\n            m_type = MatrixType::Upper;\n\n          if (m_upper_band == m_lower_band && nrows == ncols)\n            maybe_hermitian = true;\n        }\n\n      if (m_type == MatrixType::Full)\n        {\n          // Search for a permuted triangular matrix, and test if\n          // permutation is singular\n\n          // FIXME: Perhaps this should be based on a dmperm algorithm?\n          bool found = false;\n\n          m_nperm = ncols;\n          m_perm = new octave_idx_type [ncols];\n\n          for (octave_idx_type i = 0; i < ncols; i++)\n            m_perm[i] = -1;\n\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              found = false;\n\n              for (octave_idx_type j = 0; j < ncols; j++)\n                {\n                  if ((a.cidx (j+1) - a.cidx (j)) > 0\n                      && (a.ridx (a.cidx (j+1)-1) == i))\n                    {\n                      m_perm[i] = j;\n                      found = true;\n                      break;\n                    }\n                }\n\n              if (! found)\n                break;\n            }\n\n          if (found)\n            {\n              m_type = MatrixType::Permuted_Upper;\n              if (ncols > nrows)\n                {\n                  octave_idx_type k = nrows;\n                  for (octave_idx_type i = 0; i < ncols; i++)\n                    if (m_perm[i] == -1)\n                      m_perm[i] = k++;\n                }\n            }\n          else if (a.cidx (nm) == a.cidx (ncols))\n            {\n              m_nperm = nrows;\n              delete [] m_perm;\n              m_perm = new octave_idx_type [nrows];\n              OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nrows);\n\n              for (octave_idx_type i = 0; i < nrows; i++)\n                {\n                  m_perm[i] = -1;\n                  tmp[i] = -1;\n                }\n\n              for (octave_idx_type j = 0; j < ncols; j++)\n                for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n                  m_perm[a.ridx (i)] = j;\n\n              found = true;\n              for (octave_idx_type i = 0; i < nm; i++)\n                if (m_perm[i] == -1)\n                  {\n                    found = false;\n                    break;\n                  }\n                else\n                  {\n                    tmp[m_perm[i]] = 1;\n                  }\n\n              if (found)\n                {\n                  octave_idx_type k = ncols;\n                  for (octave_idx_type i = 0; i < nrows; i++)\n                    {\n                      if (tmp[i] == -1)\n                        {\n                          if (k < nrows)\n                            {\n                              m_perm[k++] = i;\n                            }\n                          else\n                            {\n                              found = false;\n                              break;\n                            }\n                        }\n                    }\n                }\n\n              if (found)\n                m_type = MatrixType::Permuted_Lower;\n              else\n                {\n                  delete [] m_perm;\n                  m_nperm = 0;\n                }\n            }\n          else\n            {\n              delete [] m_perm;\n              m_nperm = 0;\n            }\n        }\n\n      // FIXME: Disable lower under-determined and upper over-determined\n      //        problems as being detected, and force to treat as singular\n      //        as this seems to cause issues.\n      if (((m_type == MatrixType::Lower\n            || m_type == MatrixType::Permuted_Lower)\n           && nrows > ncols)\n          || ((m_type == MatrixType::Upper\n               || m_type == MatrixType::Permuted_Upper)\n              && nrows < ncols))\n        {\n          if (m_type == MatrixType::Permuted_Upper\n              || m_type == MatrixType::Permuted_Lower)\n            delete [] m_perm;\n          m_nperm = 0;\n          m_type = MatrixType::Rectangular;\n        }\n\n      if (m_type == MatrixType::Full && ncols != nrows)\n        m_type = MatrixType::Rectangular;\n\n      if (maybe_hermitian && (m_type == MatrixType::Full\n                              || m_type == MatrixType::Tridiagonal\n                              || m_type == MatrixType::Banded))\n        {\n          bool is_herm = true;\n\n          // first, check whether the diagonal is positive & extract it\n          ColumnVector diag (ncols);\n\n          for (octave_idx_type j = 0; is_herm && j < ncols; j++)\n            {\n              is_herm = false;\n              for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n                {\n                  if (a.ridx (i) == j)\n                    {\n                      T d = a.data (i);\n                      is_herm = (std::real (d) > 0.0\n                                 && std::imag (d) == 0.0);\n                      diag(j) = std::real (d);\n                      break;\n                    }\n                }\n            }\n\n          // next, check symmetry and 2x2 positiveness\n\n          for (octave_idx_type j = 0; is_herm && j < ncols; j++)\n            for (octave_idx_type i = a.cidx (j); is_herm && i < a.cidx (j+1); i++)\n              {\n                octave_idx_type k = a.ridx (i);\n                is_herm = k == j;\n                if (is_herm)\n                  continue;\n\n                T d = a.data (i);\n                if (std::norm (d) < diag(j)*diag(k))\n                  {\n                    d = octave::math::conj (d);\n                    for (octave_idx_type l = a.cidx (k); l < a.cidx (k+1); l++)\n                      {\n                        if (a.ridx (l) == j)\n                          {\n                            is_herm = a.data (l) == d;\n                            break;\n                          }\n                      }\n                  }\n              }\n\n          if (is_herm)\n            {\n              if (m_type == MatrixType::Full)\n                m_type = MatrixType::Hermitian;\n              else if (m_type == MatrixType::Banded)\n                m_type = MatrixType::Banded_Hermitian;\n              else\n                m_type = MatrixType::Tridiagonal_Hermitian;\n            }\n        }\n    }\n}\n\n\nMatrixType::MatrixType (const matrix_type t, bool _full)\n  : m_type (MatrixType::Unknown),\n    m_sp_bandden (octave::sparse_params::get_bandden ()),\n    m_bandden (0), m_upper_band (0), m_lower_band (0),\n    m_dense (false), m_full (_full), m_nperm (0), m_perm (nullptr)\n{\n  if (t == MatrixType::Unknown || t == MatrixType::Full\n      || t == MatrixType::Diagonal || t == MatrixType::Permuted_Diagonal\n      || t == MatrixType::Upper || t == MatrixType::Lower\n      || t == MatrixType::Tridiagonal || t == MatrixType::Tridiagonal_Hermitian\n      || t == MatrixType::Rectangular)\n    m_type = t;\n  else\n    warn_invalid ();\n}\n\nMatrixType::MatrixType (const matrix_type t, const octave_idx_type np,\n                        const octave_idx_type *p, bool _full)\n  : m_type (MatrixType::Unknown),\n    m_sp_bandden (octave::sparse_params::get_bandden ()),\n    m_bandden (0), m_upper_band (0), m_lower_band (0),\n    m_dense (false), m_full (_full), m_nperm (0), m_perm (nullptr)\n{\n  if ((t == MatrixType::Permuted_Upper || t == MatrixType::Permuted_Lower)\n      && np > 0 && p != nullptr)\n    {\n      m_type = t;\n      m_nperm = np;\n      m_perm = new octave_idx_type [m_nperm];\n      for (octave_idx_type i = 0; i < m_nperm; i++)\n        m_perm[i] = p[i];\n    }\n  else\n    warn_invalid ();\n}\n\nMatrixType::MatrixType (const matrix_type t, const octave_idx_type ku,\n                        const octave_idx_type kl, bool _full)\n  : m_type (MatrixType::Unknown),\n    m_sp_bandden (octave::sparse_params::get_bandden ()),\n    m_bandden (0), m_upper_band (0), m_lower_band (0),\n    m_dense (false), m_full (_full), m_nperm (0), m_perm (nullptr)\n{\n  if (t == MatrixType::Banded || t == MatrixType::Banded_Hermitian)\n    {\n      m_type = t;\n      m_upper_band = ku;\n      m_lower_band = kl;\n    }\n  else\n    warn_invalid ();\n}\n\nMatrixType::~MatrixType ()\n{\n  if (m_nperm != 0)\n    {\n      delete [] m_perm;\n    }\n}\n\nMatrixType&\nMatrixType::operator = (const MatrixType& a)\n{\n  if (this != &a)\n    {\n      m_type = a.m_type;\n      m_sp_bandden = a.m_sp_bandden;\n      m_bandden = a.m_bandden;\n      m_upper_band = a.m_upper_band;\n      m_lower_band = a.m_lower_band;\n      m_dense = a.m_dense;\n      m_full = a.m_full;\n\n      if (m_nperm)\n        {\n          delete[] m_perm;\n        }\n\n      if (a.m_nperm != 0)\n        {\n          m_perm = new octave_idx_type [a.m_nperm];\n          for (octave_idx_type i = 0; i < a.m_nperm; i++)\n            m_perm[i] = a.m_perm[i];\n        }\n\n      m_nperm = a.m_nperm;\n    }\n\n  return *this;\n}\n\nint\nMatrixType::type (bool quiet)\n{\n  if (m_type != MatrixType::Unknown\n      && (m_full || m_sp_bandden == octave::sparse_params::get_bandden ()))\n    {\n      if (! quiet && octave::sparse_params::get_key (\"spumoni\") != 0.)\n        warn_cached ();\n\n      return m_type;\n    }\n\n  if (m_type != MatrixType::Unknown\n      && octave::sparse_params::get_key (\"spumoni\") != 0.)\n    (*current_liboctave_warning_with_id_handler)\n      (\"Octave:matrix-type-info\", \"invalidating matrix type\");\n\n  m_type = MatrixType::Unknown;\n\n  return m_type;\n}\n\nint\nMatrixType::type (const SparseMatrix& a)\n{\n  if (m_type != MatrixType::Unknown\n      && (m_full || m_sp_bandden == octave::sparse_params::get_bandden ()))\n    {\n      if (octave::sparse_params::get_key (\"spumoni\") != 0.)\n        warn_cached ();\n\n      return m_type;\n    }\n\n  MatrixType tmp_typ (a);\n  m_type = tmp_typ.m_type;\n  m_sp_bandden = tmp_typ.m_sp_bandden;\n  m_bandden = tmp_typ.m_bandden;\n  m_upper_band = tmp_typ.m_upper_band;\n  m_lower_band = tmp_typ.m_lower_band;\n  m_dense = tmp_typ.m_dense;\n  m_full = tmp_typ.m_full;\n  m_nperm = tmp_typ.m_nperm;\n\n  if (m_nperm != 0)\n    {\n      m_perm = new octave_idx_type [m_nperm];\n      for (octave_idx_type i = 0; i < m_nperm; i++)\n        m_perm[i] = tmp_typ.m_perm[i];\n    }\n\n  return m_type;\n}\n\nint\nMatrixType::type (const SparseComplexMatrix& a)\n{\n  if (m_type != MatrixType::Unknown\n      && (m_full || m_sp_bandden == octave::sparse_params::get_bandden ()))\n    {\n      if (octave::sparse_params::get_key (\"spumoni\") != 0.)\n        warn_cached ();\n\n      return m_type;\n    }\n\n  MatrixType tmp_typ (a);\n  m_type = tmp_typ.m_type;\n  m_sp_bandden = tmp_typ.m_sp_bandden;\n  m_bandden = tmp_typ.m_bandden;\n  m_upper_band = tmp_typ.m_upper_band;\n  m_lower_band = tmp_typ.m_lower_band;\n  m_dense = tmp_typ.m_dense;\n  m_full = tmp_typ.m_full;\n  m_nperm = tmp_typ.m_nperm;\n\n  if (m_nperm != 0)\n    {\n      m_perm = new octave_idx_type [m_nperm];\n      for (octave_idx_type i = 0; i < m_nperm; i++)\n        m_perm[i] = tmp_typ.m_perm[i];\n    }\n\n  return m_type;\n}\n\nint\nMatrixType::type (const Matrix& a)\n{\n  if (m_type != MatrixType::Unknown)\n    {\n      if (octave::sparse_params::get_key (\"spumoni\") != 0.)\n        warn_cached ();\n\n      return m_type;\n    }\n\n  MatrixType tmp_typ (a);\n  m_type = tmp_typ.m_type;\n  m_full = tmp_typ.m_full;\n  m_nperm = tmp_typ.m_nperm;\n\n  if (m_nperm != 0)\n    {\n      m_perm = new octave_idx_type [m_nperm];\n      for (octave_idx_type i = 0; i < m_nperm; i++)\n        m_perm[i] = tmp_typ.m_perm[i];\n    }\n\n  return m_type;\n}\n\nint\nMatrixType::type (const ComplexMatrix& a)\n{\n  if (m_type != MatrixType::Unknown)\n    {\n      if (octave::sparse_params::get_key (\"spumoni\") != 0.)\n        warn_cached ();\n\n      return m_type;\n    }\n\n  MatrixType tmp_typ (a);\n  m_type = tmp_typ.m_type;\n  m_full = tmp_typ.m_full;\n  m_nperm = tmp_typ.m_nperm;\n\n  if (m_nperm != 0)\n    {\n      m_perm = new octave_idx_type [m_nperm];\n      for (octave_idx_type i = 0; i < m_nperm; i++)\n        m_perm[i] = tmp_typ.m_perm[i];\n    }\n\n  return m_type;\n}\n\nint\nMatrixType::type (const FloatMatrix& a)\n{\n  if (m_type != MatrixType::Unknown)\n    {\n      if (octave::sparse_params::get_key (\"spumoni\") != 0.)\n        warn_cached ();\n\n      return m_type;\n    }\n\n  MatrixType tmp_typ (a);\n  m_type = tmp_typ.m_type;\n  m_full = tmp_typ.m_full;\n  m_nperm = tmp_typ.m_nperm;\n\n  if (m_nperm != 0)\n    {\n      m_perm = new octave_idx_type [m_nperm];\n      for (octave_idx_type i = 0; i < m_nperm; i++)\n        m_perm[i] = tmp_typ.m_perm[i];\n    }\n\n  return m_type;\n}\n\nint\nMatrixType::type (const FloatComplexMatrix& a)\n{\n  if (m_type != MatrixType::Unknown)\n    {\n      if (octave::sparse_params::get_key (\"spumoni\") != 0.)\n        warn_cached ();\n\n      return m_type;\n    }\n\n  MatrixType tmp_typ (a);\n  m_type = tmp_typ.m_type;\n  m_full = tmp_typ.m_full;\n  m_nperm = tmp_typ.m_nperm;\n\n  if (m_nperm != 0)\n    {\n      m_perm = new octave_idx_type [m_nperm];\n      for (octave_idx_type i = 0; i < m_nperm; i++)\n        m_perm[i] = tmp_typ.m_perm[i];\n    }\n\n  return m_type;\n}\n\nvoid\nMatrixType::info () const\n{\n  if (octave::sparse_params::get_key (\"spumoni\") != 0.)\n    {\n      if (m_type == MatrixType::Unknown)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"unknown matrix type\");\n      else if (m_type == MatrixType::Diagonal)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"diagonal sparse matrix\");\n      else if (m_type == MatrixType::Permuted_Diagonal)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"permuted diagonal sparse matrix\");\n      else if (m_type == MatrixType::Upper)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"upper triangular matrix\");\n      else if (m_type == MatrixType::Lower)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"lower triangular matrix\");\n      else if (m_type == MatrixType::Permuted_Upper)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"permuted upper triangular matrix\");\n      else if (m_type == MatrixType::Permuted_Lower)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"permuted lower triangular Matrix\");\n      else if (m_type == MatrixType::Banded)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\",\n           \"banded sparse matrix %\" OCTAVE_IDX_TYPE_FORMAT \"-1-\"\n           \"%\" OCTAVE_IDX_TYPE_FORMAT \" (density %f)\",\n           m_lower_band, m_upper_band, m_bandden);\n      else if (m_type == MatrixType::Banded_Hermitian)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\",\n           \"banded hermitian/symmetric sparse matrix %\" OCTAVE_IDX_TYPE_FORMAT\n           \"-1-%\" OCTAVE_IDX_TYPE_FORMAT \" (density %f)\",\n           m_lower_band, m_upper_band, m_bandden);\n      else if (m_type == MatrixType::Hermitian)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"hermitian/symmetric matrix\");\n      else if (m_type == MatrixType::Tridiagonal)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"tridiagonal sparse matrix\");\n      else if (m_type == MatrixType::Tridiagonal_Hermitian)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\",\n           \"hermitian/symmetric tridiagonal sparse matrix\");\n      else if (m_type == MatrixType::Rectangular)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"rectangular/singular matrix\");\n      else if (m_type == MatrixType::Full)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:matrix-type-info\", \"m_full matrix\");\n    }\n}\n\nvoid\nMatrixType::mark_as_symmetric ()\n{\n  if (m_type == MatrixType::Tridiagonal\n      || m_type == MatrixType::Tridiagonal_Hermitian)\n    m_type = MatrixType::Tridiagonal_Hermitian;\n  else if (m_type == MatrixType::Banded\n           || m_type == MatrixType::Banded_Hermitian)\n    m_type = MatrixType::Banded_Hermitian;\n  else if (m_type == MatrixType::Full || m_type == MatrixType::Hermitian\n           || m_type == MatrixType::Unknown)\n    m_type = MatrixType::Hermitian;\n  else\n    (*current_liboctave_error_handler)\n      (\"Can not mark current matrix type as symmetric\");\n}\n\nvoid\nMatrixType::mark_as_unsymmetric ()\n{\n  if (m_type == MatrixType::Tridiagonal\n      || m_type == MatrixType::Tridiagonal_Hermitian)\n    m_type = MatrixType::Tridiagonal;\n  else if (m_type == MatrixType::Banded\n           || m_type == MatrixType::Banded_Hermitian)\n    m_type = MatrixType::Banded;\n  else if (m_type == MatrixType::Full || m_type == MatrixType::Hermitian\n           || m_type == MatrixType::Unknown)\n    m_type = MatrixType::Full;\n}\n\nvoid\nMatrixType::mark_as_permuted (const octave_idx_type np,\n                              const octave_idx_type *p)\n{\n  m_nperm = np;\n  m_perm = new octave_idx_type [m_nperm];\n  for (octave_idx_type i = 0; i < m_nperm; i++)\n    m_perm[i] = p[i];\n\n  if (m_type == MatrixType::Diagonal\n      || m_type == MatrixType::Permuted_Diagonal)\n    m_type = MatrixType::Permuted_Diagonal;\n  else if (m_type == MatrixType::Upper || m_type == MatrixType::Permuted_Upper)\n    m_type = MatrixType::Permuted_Upper;\n  else if (m_type == MatrixType::Lower || m_type == MatrixType::Permuted_Lower)\n    m_type = MatrixType::Permuted_Lower;\n  else\n    (*current_liboctave_error_handler)\n      (\"Can not mark current matrix type as symmetric\");\n}\n\nvoid\nMatrixType::mark_as_unpermuted ()\n{\n  if (m_nperm)\n    {\n      m_nperm = 0;\n      delete [] m_perm;\n    }\n\n  if (m_type == MatrixType::Diagonal\n      || m_type == MatrixType::Permuted_Diagonal)\n    m_type = MatrixType::Diagonal;\n  else if (m_type == MatrixType::Upper || m_type == MatrixType::Permuted_Upper)\n    m_type = MatrixType::Upper;\n  else if (m_type == MatrixType::Lower || m_type == MatrixType::Permuted_Lower)\n    m_type = MatrixType::Lower;\n}\n\nMatrixType\nMatrixType::transpose () const\n{\n  MatrixType retval (*this);\n  if (m_type == MatrixType::Upper)\n    retval.m_type = MatrixType::Lower;\n  else if (m_type == MatrixType::Permuted_Upper)\n    retval.m_type = MatrixType::Permuted_Lower;\n  else if (m_type == MatrixType::Lower)\n    retval.m_type = MatrixType::Upper;\n  else if (m_type == MatrixType::Permuted_Lower)\n    retval.m_type = MatrixType::Permuted_Upper;\n  else if (m_type == MatrixType::Banded)\n    {\n      retval.m_upper_band = m_lower_band;\n      retval.m_lower_band = m_upper_band;\n    }\n\n  return retval;\n}\n\n// Instantiate MatrixType template constructors that we need.\n\ntemplate MatrixType::MatrixType (const MSparse<double>&);\ntemplate MatrixType::MatrixType (const MSparse<Complex>&);\n"
  },
  {
    "path": "liboctave/array/MatrixType.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_MatrixType_h)\n#define octave_MatrixType_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\n#include \"MSparse.h\"\n\nclass MatrixType\n{\npublic:\n  enum matrix_type\n  {\n    Unknown = 0,\n    Full,\n    Diagonal,\n    Permuted_Diagonal,\n    Upper,\n    Lower,\n    Permuted_Upper,\n    Permuted_Lower,\n    Banded,\n    Hermitian,\n    Banded_Hermitian,\n    Tridiagonal,\n    Tridiagonal_Hermitian,\n    Rectangular\n  };\n\n  OCTAVE_API MatrixType ();\n\n  OCTAVE_API MatrixType (const MatrixType& a);\n\n  OCTAVE_API MatrixType (const Matrix& a);\n\n  OCTAVE_API MatrixType (const ComplexMatrix& a);\n\n  OCTAVE_API MatrixType (const FloatMatrix& a);\n\n  OCTAVE_API MatrixType (const FloatComplexMatrix& a);\n\n  template <typename T>\n  OCTAVE_API\n  MatrixType (const MSparse<T>& a);\n\n  OCTAVE_API MatrixType (const matrix_type t, bool _full = false);\n\n  OCTAVE_API MatrixType (const matrix_type t, const octave_idx_type np,\n                         const octave_idx_type *p, bool _full = false);\n\n  OCTAVE_API MatrixType (const matrix_type t, const octave_idx_type ku,\n                         const octave_idx_type kl, bool _full = false);\n\n  OCTAVE_API ~MatrixType ();\n\n  OCTAVE_API MatrixType& operator = (const MatrixType& a);\n\n  OCTAVE_API int type (bool quiet = true);\n\n  OCTAVE_API int type (const Matrix& a);\n\n  OCTAVE_API int type (const ComplexMatrix& a);\n\n  OCTAVE_API int type (const FloatMatrix& a);\n\n  OCTAVE_API int type (const FloatComplexMatrix& a);\n\n  OCTAVE_API int type (const SparseMatrix& a);\n\n  OCTAVE_API int type (const SparseComplexMatrix& a);\n\n  double band_density () const { return m_bandden; }\n\n  int nupper () const { return m_upper_band; }\n\n  int nlower () const { return m_lower_band; }\n\n  bool is_dense () const { return m_dense; }\n\n  bool isdiag () const\n  { return (m_type == Diagonal || m_type == Permuted_Diagonal); }\n\n  bool istriu () const\n  { return (m_type == Upper || m_type == Permuted_Upper); }\n\n  bool istril () const\n  { return (m_type == Lower || m_type == Permuted_Lower); }\n\n  bool isbanded () const\n  { return (m_type == Banded || m_type == Banded_Hermitian); }\n\n  bool is_tridiagonal () const\n  { return (m_type == Tridiagonal || m_type == Tridiagonal_Hermitian); }\n\n  bool ishermitian () const\n  {\n    return (m_type == Banded_Hermitian || m_type == Tridiagonal_Hermitian\n            || m_type == Hermitian);\n  }\n\n  bool is_rectangular () const { return (m_type == Rectangular); }\n\n  bool is_known () const { return (m_type != Unknown); }\n\n  bool is_unknown () const { return (m_type == Unknown); }\n\n  OCTAVE_API void info () const;\n\n  octave_idx_type * triangular_perm () const { return m_perm; }\n\n  void invalidate_type () { m_type = Unknown; }\n\n  void mark_as_diagonal () { m_type = Diagonal; }\n\n  void mark_as_permuted_diagonal () { m_type = Permuted_Diagonal; }\n\n  void mark_as_upper_triangular () { m_type = Upper; }\n\n  void mark_as_lower_triangular () { m_type = Lower; }\n\n  void mark_as_tridiagonal () {m_type = Tridiagonal; }\n\n  void mark_as_banded (const octave_idx_type ku, const octave_idx_type kl)\n  { m_type = Banded; m_upper_band = ku; m_lower_band = kl; }\n\n  void mark_as_full () { m_type = Full; }\n\n  void mark_as_rectangular () { m_type = Rectangular; }\n\n  void mark_as_dense () { m_dense = true; }\n\n  void mark_as_not_dense () { m_dense = false; }\n\n  OCTAVE_API void mark_as_symmetric ();\n\n  OCTAVE_API void mark_as_unsymmetric ();\n\n  OCTAVE_API void mark_as_permuted (const octave_idx_type np, const octave_idx_type *p);\n\n  OCTAVE_API void mark_as_unpermuted ();\n\n  OCTAVE_API MatrixType transpose () const;\n\nprivate:\n  void type (int new_typ) { m_type = static_cast<matrix_type> (new_typ); }\n\n  matrix_type m_type;\n  double m_sp_bandden;\n  double m_bandden;\n  octave_idx_type m_upper_band;\n  octave_idx_type m_lower_band;\n  bool m_dense;\n  bool m_full;\n  octave_idx_type m_nperm;\n  octave_idx_type *m_perm;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/array/PermMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"PermMatrix.h\"\n#include \"idx-vector.h\"\n#include \"Array-util.h\"\n#include \"oct-locbuf.h\"\n\nOCTAVE_NORETURN static\nvoid\nerr_invalid_permutation ()\n{\n  (*current_liboctave_error_handler) (\"PermMatrix: invalid permutation vector\");\n}\n\nvoid\nPermMatrix::setup (const Array<octave_idx_type>& p, bool colp, bool check)\n{\n  if (check)\n    {\n      if (! octave::idx_vector (p).is_permutation (p.numel ()))\n        err_invalid_permutation ();\n    }\n\n  if (! colp)\n    *this = this->transpose ();\n}\n\nPermMatrix::PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check)\n  : Array<octave_idx_type> (p)\n{\n  setup (p, colp, check);\n}\n\nvoid\nPermMatrix::setup (const octave::idx_vector& idx, bool colp, octave_idx_type n)\n{\n  octave_idx_type len = idx.length (n);\n\n  if (! idx.is_permutation (len))\n    err_invalid_permutation ();\n\n  Array<octave_idx_type> idxa (dim_vector (len, 1));\n  for (octave_idx_type i = 0; i < len; i++) idxa(i) = idx(i);\n  Array<octave_idx_type>::operator = (idxa);\n\n  if (! colp)\n    *this = this->transpose ();\n}\n\nPermMatrix::PermMatrix (const octave::idx_vector& idx, bool colp, octave_idx_type n)\n  : Array<octave_idx_type> ()\n{\n  setup (idx, colp, n);\n}\n\nPermMatrix::PermMatrix (octave_idx_type n)\n  : Array<octave_idx_type> (dim_vector (n, 1))\n{\n  for (octave_idx_type i = 0; i < n; i++)\n    xelem (i) = i;\n}\n\noctave_idx_type\nPermMatrix::checkelem (octave_idx_type i, octave_idx_type j) const\n{\n  octave_idx_type len = Array<octave_idx_type>::numel ();\n  if (i < 0 || j < 0 || i > len || j > len)\n    (*current_liboctave_error_handler) (\"index out of range\");\n\n  return elem (i, j);\n}\n\nPermMatrix\nPermMatrix::transpose () const\n{\n  octave_idx_type len = Array<octave_idx_type>::numel ();\n\n  PermMatrix retval (len);\n\n  for (octave_idx_type i = 0; i < len; ++i)\n    retval.xelem (xelem (i)) = i;\n\n  return retval;\n}\n\nPermMatrix\nPermMatrix::inverse () const\n{\n  return transpose ();\n}\n\noctave_idx_type\nPermMatrix::determinant () const\n{\n  // Determine the sign of a permutation in linear time.\n  // Is this widely known?\n\n  octave_idx_type len = perm_length ();\n  const octave_idx_type *pa = data ();\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, p, len);\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, q, len);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      p[i] = pa[i];\n      q[p[i]] = i;\n    }\n\n  bool neg = false;\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      octave_idx_type j = p[i];\n      octave_idx_type k = q[i];\n      if (j != i)\n        {\n          p[k] = p[i];\n          q[j] = q[i];\n          neg = ! neg;\n        }\n    }\n\n  return neg ? -1 : 1;\n}\n\nPermMatrix\nPermMatrix::power(octave_idx_type m) const\n{\n  if (m < 0)\n    return inverse ().pos_power (-m);\n  else if (m > 0)\n    return pos_power (m);\n  else\n    return PermMatrix (rows ());\n}\n\nPermMatrix\nPermMatrix::pos_power (octave_idx_type m) const\n{\n  octave_idx_type n = rows ();\n\n  const octave_idx_type *p = data ();\n  Array<octave_idx_type> res_pvec (dim_vector (n, 1), -1);\n  octave_idx_type *q = res_pvec.rwdata ();\n\n  for (octave_idx_type ics = 0; ics < n; ics++)\n    {\n      if (q[ics] > 0)\n        continue;\n\n      // go forward m steps or until a cycle is found.\n      octave_idx_type ic, j;\n      for (j = 1, ic = p[ics]; j != m && ic != ics; j++, ic = p[ic]) ;\n      if (ic == ics)\n        {\n          // reduce power.\n          octave_idx_type mm = m % j;\n          // go forward mm steps.\n          for (j = 0, ic = ics; j != mm; j++, ic = p[ic]) ;\n        }\n\n      // now ic = p^m[ics].  Loop through the whole cycle.\n      octave_idx_type jcs = ics;\n      do\n        {\n          q[jcs] = ic;\n          jcs = p[jcs]; ic = p[ic];\n        }\n      while (jcs != ics);\n\n    }\n\n  return PermMatrix (res_pvec, true, false);\n}\n\nPermMatrix\nPermMatrix::eye (octave_idx_type n)\n{\n  return PermMatrix (n);\n}\n\nPermMatrix\noperator *(const PermMatrix& a, const PermMatrix& b)\n{\n  PermMatrix r;\n\n  const Array<octave_idx_type> ia = a.col_perm_vec ();\n  const Array<octave_idx_type> ib = b.col_perm_vec ();\n\n  octave_idx_type n = a.columns ();\n\n  if (n != b.rows ())\n    octave::err_nonconformant (\"operator *\", n, n, b.rows (), b.rows ());\n\n  r = PermMatrix (ia.index (octave::idx_vector (ib)), true, false);\n\n  return r;\n}\n"
  },
  {
    "path": "liboctave/array/PermMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_PermMatrix_h)\n#define octave_PermMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-oct.h\"\n#include \"mx-defs.h\"\n\n// Array<T> is inherited privately so that some methods, like index, don't\n// produce unexpected results.\n\nclass OCTAVE_API PermMatrix : protected Array<octave_idx_type>\n{\npublic:\n\n  PermMatrix () = default;\n\n  PermMatrix (const PermMatrix& m) = default;\n\n  PermMatrix& operator = (const PermMatrix& m) = default;\n\n  ~PermMatrix () = default;\n\n  OCTAVE_API PermMatrix (octave_idx_type n);\n\n  OCTAVE_API PermMatrix (const Array<octave_idx_type>& p, bool colp,\n                         bool check = true);\n\n  OCTAVE_API PermMatrix (const octave::idx_vector& idx, bool colp,\n                         octave_idx_type n = 0);\n\n  octave_idx_type dim1 () const\n  { return Array<octave_idx_type>::numel (); }\n  octave_idx_type dim2 () const\n  { return Array<octave_idx_type>::numel (); }\n\n  octave_idx_type rows () const { return dim1 (); }\n  octave_idx_type cols () const { return dim2 (); }\n  octave_idx_type columns () const { return dim2 (); }\n\n  octave_idx_type perm_length () const\n  { return Array<octave_idx_type>::numel (); }\n  // FIXME: a dangerous ambiguity?\n  octave_idx_type length () const\n  { return perm_length (); }\n\n  octave_idx_type numel () const { return dim1 () * dim2 (); }\n\n  std::size_t byte_size () const\n  { return Array<octave_idx_type>::byte_size (); }\n\n  dim_vector dims () const { return dim_vector (dim1 (), dim2 ()); }\n\n  bool isempty () const { return numel () == 0; }\n\n  int ndims () const { return 2; }\n\n  const Array<octave_idx_type>& col_perm_vec () const\n  { return *this; }\n\n  octave_idx_type\n  elem (octave_idx_type i, octave_idx_type j) const\n  {\n    return (Array<octave_idx_type>::elem (j) == i) ? 1 : 0;\n  }\n\n  octave_idx_type\n  checkelem (octave_idx_type i, octave_idx_type j) const;\n\n  octave_idx_type\n  operator () (octave_idx_type i, octave_idx_type j) const\n  {\n    return elem (i, j);\n  }\n\n  // These are, in fact, super-fast.\n  OCTAVE_API PermMatrix transpose () const;\n  OCTAVE_API PermMatrix inverse () const;\n\n  // Determinant, i.e., the sign of permutation.\n  OCTAVE_API octave_idx_type determinant () const;\n\n  // Efficient integer power of a permutation.\n  OCTAVE_API PermMatrix power (octave_idx_type n) const;\n\n  bool is_col_perm () const { return true; }\n  bool is_row_perm () const { return false; }\n\n  void print_info (std::ostream& os, const std::string& prefix) const\n  { Array<octave_idx_type>::print_info (os, prefix); }\n\n  static OCTAVE_API PermMatrix eye (octave_idx_type n);\n\nprivate:\n\n  PermMatrix pos_power (octave_idx_type m) const;\n\n  void setup (const Array<octave_idx_type>& p, bool colp, bool check);\n\n  void setup (const octave::idx_vector& idx, bool colp, octave_idx_type n);\n};\n\n// Multiplying permutations together.\nOCTAVE_API PermMatrix\noperator * (const PermMatrix& a, const PermMatrix& b);\n\n#endif\n"
  },
  {
    "path": "liboctave/array/Range.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <limits>\n\n#include \"Array-util.h\"\n#include \"Range.h\"\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"oct-error.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T>\nT xtfloor (T x, T ct)\n{\n  // C---------FLOOR(X) is the largest integer algebraically less than\n  // C         or equal to X; that is, the unfuzzy FLOOR function.\n\n  //  DINT (X) = X - DMOD (X, 1.0);\n  //  FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0);\n\n  // C---------Hagerty's FL5 function follows...\n\n  T q = 1;\n\n  if (x < 0)\n    q = 1 - ct;\n\n  T rmax = q / (2 - ct);\n\n  T t1 = 1 + std::floor (x);\n  t1 = (ct / q) * (t1 < 0 ? -t1 : t1);\n  t1 = (rmax < t1 ? rmax : t1);\n  t1 = (ct > t1 ? ct : t1);\n  t1 = std::floor (x + t1);\n\n  if (x <= 0 || (t1 - x) < rmax)\n    return t1;\n  else\n    return t1 - 1;\n}\n\ntemplate <typename T>\nbool\nxteq (T u, T v, T ct = 3 * std::numeric_limits<T>::epsilon ())\n{\n  T tu = std::abs (u);\n  T tv = std::abs (v);\n\n  return std::abs (u - v) < ((tu > tv ? tu : tv) * ct);\n}\n\ntemplate <typename T>\noctave_idx_type\nxnumel_internal (T base, T limit, T inc)\n{\n  octave_idx_type retval = -1;\n  if (! math::isfinite (base) || ! math::isfinite (inc)\n      || math::isnan (limit))\n    retval = -2;\n  else if (math::isinf (limit)\n           && ((inc > 0 && limit > 0)\n               || (inc < 0 && limit < 0)))\n    retval = std::numeric_limits<octave_idx_type>::max () - 1;\n  else if (inc == 0\n           || (limit > base && inc < 0)\n           || (limit < base && inc > 0))\n    {\n      retval = 0;\n    }\n  else\n    {\n      T ct = 3 * std::numeric_limits<T>::epsilon ();\n\n      T tmp = xtfloor ((limit - base + inc) / inc, ct);\n\n      octave_idx_type n_elt\n        = (tmp > 0 ? static_cast<octave_idx_type> (tmp) : 0);\n\n      // If the final element that we would compute for the range is\n      // equal to the limit of the range, or is an adjacent floating\n      // point number, accept it.  Otherwise, try a range with one\n      // fewer element.  If that fails, try again with one more\n      // element.\n      //\n      // I'm not sure this is very good, but it seems to work better\n      // than just using tfloor as above.  For example, without it,\n      // the expression 1.8:0.05:1.9 fails to produce the expected\n      // result of [1.8, 1.85, 1.9].\n\n      if (! xteq (base + (n_elt - 1) * inc, limit))\n        {\n          if (xteq (base + (n_elt - 2) * inc, limit))\n            n_elt--;\n          else if (xteq (base + n_elt * inc, limit))\n            n_elt++;\n        }\n\n      retval = (n_elt < std::numeric_limits<octave_idx_type>::max () - 1\n                ? n_elt : -1);\n    }\n\n  return retval;\n}\n\ntemplate <typename T>\nbool\nxall_elements_are_ints (T base, T inc, T final_val, octave_idx_type nel)\n{\n  // If the range is empty or NaN then there are no elements so there\n  // can be no int elements.\n  if (nel == 0 || math::isnan (final_val))\n    return false;\n\n  // If the base and increment are ints, all elements will be\n  // integers.\n  if (math::nint_big (base) == base && math::nint_big (inc) == inc)\n    return true;\n\n  // If the range has only one element, then the base needs to be an\n  // integer.\n  if (nel == 1 && math::nint_big (base))\n    return true;\n\n  return false;\n}\n\ntemplate <typename T>\nT\nxfinal_value (T base, T limit, T inc, octave_idx_type nel)\n{\n  T retval = T (0);\n\n  if (nel <= 1)\n    return base;\n\n  // If increment is 0, then numel should also be zero.\n\n  retval = base + (nel - 1) * inc;\n\n  // On some machines (x86 with extended precision floating point\n  // arithmetic, for example) it is possible that we can overshoot\n  // the limit by approximately the machine precision even though\n  // we were very careful in our calculation of the number of\n  // elements.  Therefore, we clip the result to the limit if it\n  // overshoots.\n\n  // NOTE: The test also includes equality (>= limit) to have\n  // expressions such as -5:1:-0 result in a -0 endpoint.\n\n  if ((inc > T (0) && retval >= limit) || (inc < T (0) && retval <= limit))\n    retval = limit;\n\n  // If all elements are integers, then ensure the final value is.\n  // Note that we pass the preliminary computed final value to\n  // xall_elements_are_ints, but it only checks whether that value is\n  // NaN.\n\n  if (xall_elements_are_ints (base, inc, retval, nel))\n    retval = std::round (retval);\n\n  return retval;\n}\n\ntemplate <typename T>\nvoid\nxinit (T base, T limit, T inc, bool reverse, T& final_val,\n       octave_idx_type& nel)\n{\n  // Catch obvious NaN ranges.\n  if (math::isnan (base) || math::isnan (limit) || math::isnan (inc))\n    {\n      final_val = numeric_limits<T>::NaN ();\n      nel = 1;\n      return;\n    }\n\n  // Floating point numbers are always signed\n  if (reverse)\n    inc = -inc;\n\n  // Catch empty ranges.\n  if (inc == 0\n      || (limit < base && inc > 0)\n      || (limit > base && inc < 0))\n    {\n      nel = 0;\n      return;\n    }\n\n  // The following case also catches Inf values for increment when\n  // there will be only one element.\n\n  if ((limit <= base && base + inc < limit)\n      || (limit >= base && base + inc > limit))\n    {\n      final_val = base;\n      nel = 1;\n      return;\n    }\n\n  // Any other calculations with Inf will give us either a NaN range\n  // or an infinite nember of elements.\n\n  T dnel = (limit - base) / inc;\n  if (math::isnan (dnel))\n    {\n      nel = 1;\n      final_val = numeric_limits<T>::NaN ();\n      return;\n    }\n\n  if (dnel > 0 && math::isinf (dnel))\n    {\n      // FIXME: Should this be an immediate error?\n      nel = std::numeric_limits<octave_idx_type>::max ();\n\n      // FIXME: Will this do the right thing in all cases?\n      final_val = xfinal_value (base, limit, inc, nel);\n\n      return;\n    }\n\n  // Now that we have handled all the special cases, we can compute\n  // the number of elements and the final value in a way that attempts\n  // to avoid rounding errors as much as possible.\n\n  nel = xnumel_internal (base, limit, inc);\n  final_val = xfinal_value (base, limit, inc, nel);\n}\n\ntemplate <typename T>\nvoid\nxinit (const octave_int<T>& base, const octave_int<T>& limit,\n       const octave_int<T>& inc, bool reverse,\n       octave_int<T>& final_val, octave_idx_type& nel)\n{\n  // We need an integer division that is truncating decimals instead\n  // of rounding.  So, use underlying C++ types instead of\n  // octave_int<T>.\n\n  // FIXME: The numerator might underflow or overflow.  Add checks for\n  // that.\n  if (reverse)\n    {\n      nel = ((inc == octave_int<T> (0)\n              || (limit > base && inc > octave_int<T> (0))\n              || (limit < base && inc < octave_int<T> (0)))\n             ? 0\n             : (base.value () - limit.value () + inc.value ())\n             / inc.value ());\n\n      final_val = base - (nel - 1) * inc;\n    }\n  else\n    {\n      nel = ((inc == octave_int<T> (0)\n              || (limit > base && inc < octave_int<T> (0))\n              || (limit < base && inc > octave_int<T> (0)))\n             ? 0\n             : (limit.value () - base.value () + inc.value ())\n             / inc.value ());\n\n      final_val = base + (nel - 1) * inc;\n    }\n}\n\ntemplate <typename T>\nbool\nxis_storable (T base, T limit, octave_idx_type nel)\n{\n  return ! (nel > 1 && (math::isinf (base) || math::isinf (limit)));\n}\n\ntemplate <>\nbool\nrange<double>::all_elements_are_ints () const\n{\n  return xall_elements_are_ints (m_base, m_increment, m_final, m_numel);\n}\n\ntemplate <>\nbool\nrange<float>::all_elements_are_ints () const\n{\n  return xall_elements_are_ints (m_base, m_increment, m_final, m_numel);\n}\n\ntemplate <>\nvoid\nrange<double>::init ()\n{\n  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);\n}\n\ntemplate <>\nvoid\nrange<float>::init ()\n{\n  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);\n}\n\n// For now, only define for float and double.\n\ntemplate <>\nbool\nrange<double>::is_storable () const\n{\n  return xis_storable (m_base, m_limit, m_numel);\n}\n\ntemplate <>\nbool\nrange<float>::is_storable () const\n{\n  return xis_storable (m_base, m_limit, m_numel);\n}\n\ntemplate <typename T>\noctave_idx_type\nxnnz (T base, T limit, T inc, T final_val, octave_idx_type nel)\n{\n  // Note that the order of the following checks matters.\n\n  // If there are no elements, there can be no nonzero elements.\n  if (nel == 0)\n    return 0;\n\n  // All elements have the same sign, hence there are no zeros.\n  if ((base > 0 && limit > 0) || (base < 0 && limit < 0))\n    return nel;\n\n  // All elements are equal (inc = 0) but we know from the previous\n  // condition that they are not positive or negative, therefore all\n  // elements are zero.\n  if (inc == 0)\n    return 0;\n\n  // Exactly one zero at beginning or end of range.\n  if (base == 0 || final_val == 0)\n    return nel - 1;\n\n  // Range crosses negative/positive without hitting zero.\n  // FIXME: Is this test sufficiently tolerant or do we need to be\n  // more careful?\n  if (math::mod (-base, inc) != 0)\n    return nel;\n\n  // Range crosses negative/positive and hits zero.\n  return nel - 1;\n}\n\ntemplate <>\noctave_idx_type\nrange<double>::nnz () const\n{\n  return xnnz (m_base, m_limit, m_increment, m_final, m_numel);\n}\n\ntemplate <>\noctave_idx_type\nrange<float>::nnz () const\n{\n  return xnnz (m_base, m_limit, m_increment, m_final, m_numel);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/array/Range.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Range_h)\n#define octave_Range_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <type_traits>\n\n#include \"Array-fwd.h\"\n#include \"dMatrix.h\"\n#include \"dim-vector.h\"\n#include \"oct-error.h\"\n#include \"oct-sort.h\"\n#include \"range-fwd.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// For now, only define for floating point types.  However, we only\n// need range<float> as a temporary local variable in make_float_range\n// in ov.cc.\n\ntemplate <typename T>\nclass range<T, typename std::enable_if<std::is_floating_point<T>::value>::type>\n{\npublic:\n\n  range ()\n    : m_base (0), m_increment (0), m_limit (0), m_final (0), m_numel (0),\n      m_reverse (false)\n  { }\n\n  // LIMIT is an upper limit and may be outside the range of actual\n  // values.  For floating point ranges, we perform a tolerant check\n  // to attempt to capture limit in the set of values if it is \"close\"\n  // to the value of base + a multiple of the increment.\n\n  range (const T& base, const T& increment, const T& limit,\n         bool reverse = false)\n    : m_base (base), m_increment (increment), m_limit (limit),\n      m_final (), m_numel (), m_reverse (reverse)\n  {\n    init ();\n  }\n\n  range (const T& base, const T& limit)\n    : m_base (base), m_increment (1), m_limit (limit), m_final (), m_numel (),\n      m_reverse (false)\n  {\n    init ();\n  }\n\n  // Allow conversion from (presumably) properly constructed Range\n  // objects.  The values of base, limit, increment, and numel must be\n  // consistent.\n\n  // FIXME: Actually check that base, limit, increment, and numel are\n  // consistent?\n\n  range (const T& base, const T& increment, const T& limit,\n         octave_idx_type numel, bool reverse = false)\n    : m_base (base), m_increment (increment), m_limit (limit),\n      m_final (limit), m_numel (numel), m_reverse (reverse)\n  { }\n\n  // We don't use a constructor for this because it will conflict with\n  // range<T> (base, limit, increment) when T is octave_idx_type.\n\n  static range<T> make_n_element_range (const T& base, const T& increment,\n                                        octave_idx_type numel,\n                                        bool reverse = false)\n  {\n    // We could just make this constructor public, but it allows\n    // inconsistent ranges to be constructed.  And it is probably much\n    // clearer to see \"make_n_element_range\" instead of puzzling over the\n    // purpose of this strange constructor form.\n\n    T final_val = (reverse ? base - (numel - 1) * increment\n                           : base + (numel - 1) * increment);\n\n    return range<T> (base, increment, final_val, numel, reverse);\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (range)\n\n  T base () const { return m_base; }\n  T increment () const { return m_increment; }\n  T limit () const { return m_limit; }\n  bool reverse () const { return m_reverse; }\n\n  T final_value () const { return m_final; }\n\n  T min () const\n  {\n    return (m_numel > 0\n            ? ((m_reverse ? m_increment > T (0)\n                          : m_increment > T (0)) ? base () : final_value ())\n            : T (0));\n  }\n\n  T max () const\n  {\n    return (m_numel > 0\n            ? ((m_reverse ? m_increment < T (0)\n                          : m_increment > T (0)) ? final_value () : base ())\n            : T (0));\n  }\n\n  octave_idx_type numel () const { return m_numel; }\n\n  // To support things like \"for i = 1:Inf; ...; end\" that are\n  // required for Matlab compatibility, creation of a range object\n  // like 1:Inf is allowed with m_numel set to\n  // numeric_limits<octave_idx_type>::max().  However, it is not\n  // possible to store these ranges.  The following function allows\n  // us to easily distinguish ranges with an infinite number of\n  // elements.  There are specializations for double and float.\n\n  bool is_storable () const { return true; }\n\n  dim_vector dims () const { return dim_vector (1, m_numel); }\n\n  octave_idx_type rows () const { return 1; }\n\n  octave_idx_type cols () const { return numel (); }\n  octave_idx_type columns () const { return numel (); }\n\n  bool isempty () const { return numel () == 0; }\n\n  bool all_elements_are_ints () const { return true; }\n\n  sortmode issorted (sortmode mode = ASCENDING) const\n  {\n    if (m_numel > 1 && (m_reverse ? m_increment < T (0)\n                                  : m_increment > T (0)))\n      mode = ((mode == DESCENDING) ? UNSORTED : ASCENDING);\n    else if (m_numel > 1 && (m_reverse ? m_increment > T (0)\n                                       : m_increment < T (0)))\n      mode = ((mode == ASCENDING) ? UNSORTED : DESCENDING);\n    else\n      mode = ((mode == UNSORTED) ? ASCENDING : mode);\n\n    return mode;\n  }\n\n  OCTAVE_API octave_idx_type nnz () const;\n\n  // Support for single-index subscripting, without generating matrix cache.\n\n  T checkelem (octave_idx_type i) const\n  {\n    if (i < 0 || i >= m_numel)\n      err_index_out_of_range (2, 2, i+1, m_numel, dims ());\n\n    if (i == 0)\n      // Required for proper NaN handling.\n      return (m_numel == 1 ? final_value () : m_base);\n    else if (i < m_numel - 1)\n      return (m_reverse ? m_base + T (i) * m_increment\n                        : m_base + T (i) * m_increment);\n    else\n      return final_value ();\n  }\n\n  T checkelem (octave_idx_type i, octave_idx_type j) const\n  {\n    // Ranges are *always* row vectors.\n    if (i != 0)\n      err_index_out_of_range (1, 1, i+1, m_numel, dims ());\n\n    return checkelem (j);\n  }\n\n  T elem (octave_idx_type i) const\n  {\n    if (i == 0)\n      // Required for proper NaN handling.\n      return (m_numel == 1 ? final_value () : m_base);\n    else if (i < m_numel - 1)\n      return (m_reverse ? m_base - T (i) * m_increment\n                        : m_base + T (i) * m_increment);\n    else\n      return final_value ();\n  }\n\n  T elem (octave_idx_type /* i */, octave_idx_type j) const\n  {\n    return elem (j);\n  }\n\n  T operator () (octave_idx_type i) const\n  {\n    return elem (i);\n  }\n\n  T operator () (octave_idx_type i, octave_idx_type j) const\n  {\n    return elem (i, j);\n  }\n\n  Array<T> index (const idx_vector& idx) const\n  {\n    Array<T> retval;\n\n    octave_idx_type n = m_numel;\n\n    if (idx.is_colon ())\n      {\n        retval = array_value ().reshape (dim_vector (m_numel, 1));\n      }\n    else\n      {\n        if (idx.extent (n) != n)\n          err_index_out_of_range (1, 1, idx.extent (n), n, dims ());\n\n        dim_vector idx_dims = idx.orig_dimensions ();\n        octave_idx_type idx_len = idx.length (n);\n\n        // taken from Array.cc.\n        if (n != 1 && idx_dims.isvector ())\n          idx_dims = dim_vector (1, idx_len);\n\n        retval.clear (idx_dims);\n\n        // Loop over all values in IDX, executing the lambda\n        // expression for each index value.\n\n        T *array = retval.rwdata ();\n\n        idx.loop (n, [this, &array] (octave_idx_type i)\n        {\n          if (i == 0)\n            // Required for proper NaN handling.\n            *array++ = (m_numel == 0 ? m_final : m_base);\n          else if (i < m_numel - 1)\n            *array++ = (m_reverse ? m_base - T (i) * m_increment\n                                  : m_base + T (i) * m_increment);\n          else\n            *array++ = m_final;\n        });\n      }\n\n    return retval;\n  }\n\n  Array<T> diag (octave_idx_type k) const\n  {\n    return array_value ().diag (k);\n  }\n\n  Array<T> array_value () const\n  {\n    octave_idx_type nel = numel ();\n\n    Array<T> retval (dim_vector (1, nel));\n\n    if (nel == 1)\n      // Required for proper NaN handling.\n      retval(0) = final_value ();\n    else if (nel > 1)\n      {\n        // The first element must always be *exactly* the base.\n        // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment).\n        retval(0) = m_base;\n\n        if (m_reverse)\n          for (octave_idx_type i = 1; i < nel - 1; i++)\n            retval.xelem (i) = m_base - i * m_increment;\n        else\n          for (octave_idx_type i = 1; i < nel - 1; i++)\n            retval.xelem (i) = m_base + i * m_increment;\n\n        retval.xelem (nel - 1) = final_value ();\n      }\n\n    return retval;\n  }\n\nprivate:\n\n  T m_base;\n  T m_increment;\n  T m_limit;\n  T m_final;\n  octave_idx_type m_numel;\n  bool m_reverse;\n\n  // Setting the number of elements to zero when the increment is zero\n  // is intentional and matches the behavior of Matlab's colon\n  // operator.\n\n  // These calculations are appropriate for integer ranges.  There are\n  // specializations for double and float.\n\n  void init ()\n  {\n    if (m_reverse)\n      {\n        m_numel = ((m_increment == T (0)\n                    || (m_limit > m_base && m_increment > T (0))\n                    || (m_limit < m_base && m_increment < T (0)))\n                   ? T (0)\n                   : (m_base - m_limit - m_increment) / m_increment);\n\n        m_final = m_base - (m_numel - 1) * m_increment;\n      }\n    else\n      {\n        m_numel = ((m_increment == T (0)\n                    || (m_limit > m_base && m_increment < T (0))\n                    || (m_limit < m_base && m_increment > T (0)))\n                   ? T (0)\n                   : (m_limit - m_base + m_increment) / m_increment);\n\n        m_final = m_base + (m_numel - 1) * m_increment;\n      }\n  }\n};\n\n// Specializations defined externally.\n\ntemplate <> OCTAVE_API bool range<double>::all_elements_are_ints () const;\ntemplate <> OCTAVE_API bool range<float>::all_elements_are_ints () const;\n\ntemplate <> OCTAVE_API void range<double>::init ();\ntemplate <> OCTAVE_API void range<float>::init ();\n\n// For now, only define for floating point types.  However, we only\n// need range<float> as a temporary local variable in make_float_range\n// in ov.cc.\n\ntemplate <> OCTAVE_API bool range<double>::is_storable () const;\ntemplate <> OCTAVE_API bool range<float>::is_storable () const;\n\ntemplate <> OCTAVE_API octave_idx_type range<double>::nnz () const;\ntemplate <> OCTAVE_API octave_idx_type range<float>::nnz () const;\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/Sparse-C.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Sparse matrix of complex values.\n\n#include \"Array-oct.h\"\n#include \"Sparse.cc\"\n#include \"Sparse.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"oct-cmplx.h\"\n\n\nstatic double\nxabs (const Complex& x)\n{\n  return ((octave::math::isinf (x.real ()) || octave::math::isinf (x.imag ()))\n          ? octave::numeric_limits<double>::Inf () : abs (x));\n}\n\ntemplate <>\nOCTAVE_API\nbool\nsparse_ascending_compare<Complex> (const Complex& a, const Complex& b)\n{\n  return (octave::math::isnan (b) || (xabs (a) < xabs (b))\n          || ((xabs (a) == xabs (b)) && (arg (a) < arg (b))));\n}\n\ntemplate <>\nOCTAVE_API\nbool\nsparse_descending_compare<Complex> (const Complex& a, const Complex& b)\n{\n  return (octave::math::isnan (a) || (xabs (a) > xabs (b))\n          || ((xabs (a) == xabs (b)) && (arg (a) > arg (b))));\n}\n\nINSTANTIATE_SPARSE (Complex);\n"
  },
  {
    "path": "liboctave/array/Sparse-b.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Sparse matrix of double values.\n\n#include \"Array-oct.h\"\n#include \"Sparse.h\"\n#include \"Sparse.cc\"\n\ntemplate <>\nOCTAVE_API\nbool\nSparse<bool>::SparseRep::any_element_is_nan () const\n{\n  return false;\n}\n\ntemplate <>\nOCTAVE_API\nbool\nSparse<bool>::SparseRep::any_element_is_inf_or_nan () const\n{\n  return false;\n}\n\nINSTANTIATE_SPARSE (bool);\n"
  },
  {
    "path": "liboctave/array/Sparse-d.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n// Instantiate Sparse matrix of double values.\n\n#include \"Array-oct.h\"\n#include \"Sparse.cc\"\n#include \"Sparse.h\"\n#include \"mappers.h\"\n\ntemplate <>\nOCTAVE_API\nbool\nsparse_ascending_compare<double> (double a, double b)\n{\n  return (octave::math::isnan (b) || (a < b));\n}\n\ntemplate <>\nOCTAVE_API\nbool\nsparse_descending_compare<double> (double a, double b)\n{\n  return (octave::math::isnan (a) || (a > b));\n}\n\nINSTANTIATE_SPARSE (double);\n"
  },
  {
    "path": "liboctave/array/Sparse-fwd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Sparse_fwd_h)\n#define octave_Sparse_fwd_h 1\n\n#include \"octave-config.h\"\n\n#if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)\n#  include <memory_resource>\n\ntemplate <typename T, typename Alloc = std::pmr::polymorphic_allocator<T>>\nclass OCTAVE_TEMPLATE_API Sparse;\n\n#else\n\ntemplate <typename T, typename Alloc = std::allocator<T>>\nclass OCTAVE_TEMPLATE_API Sparse;\n\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/array/Sparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <cinttypes>\n\n#include <algorithm>\n#include <istream>\n#include <ostream>\n#include <sstream>\n#include <vector>\n\n#include \"Array-oct.h\"\n#include \"Array-util.h\"\n#include \"MArray.h\"\n#include \"Range.h\"\n#include \"idx-vector.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"quit.h\"\n\n#include \"Sparse.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-spparms.h\"\n#include \"sparse-util.h\"\n\n#include \"PermMatrix.h\"\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API typename Sparse<T, Alloc>::SparseRep *\nSparse<T, Alloc>::nil_rep ()\n{\n  static typename Sparse<T, Alloc>::SparseRep nr;\n  return &nr;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nT&\nSparse<T, Alloc>::SparseRep::elem (octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type i;\n\n  if (m_nzmax <= 0)\n    (*current_liboctave_error_handler)\n      (\"Sparse::SparseRep::elem (octave_idx_type, octave_idx_type): sparse matrix filled\");\n\n  for (i = m_cidx[c]; i < m_cidx[c + 1]; i++)\n    if (m_ridx[i] == r)\n      return m_data[i];\n    else if (m_ridx[i] > r)\n      break;\n\n  // Ok, If we've gotten here, we're in trouble.  Have to create a\n  // new element in the sparse array.  This' gonna be slow!!!\n  if (m_cidx[m_ncols] == m_nzmax)\n    (*current_liboctave_error_handler)\n      (\"Sparse::SparseRep::elem (octave_idx_type, octave_idx_type): sparse matrix filled\");\n\n  octave_idx_type to_move = m_cidx[m_ncols] - i;\n  if (to_move != 0)\n    {\n      for (octave_idx_type j = m_cidx[m_ncols]; j > i; j--)\n        {\n          m_data[j] = m_data[j-1];\n          m_ridx[j] = m_ridx[j-1];\n        }\n    }\n\n  for (octave_idx_type j = c + 1; j < m_ncols + 1; j++)\n    m_cidx[j] = m_cidx[j] + 1;\n\n  m_data[i] = 0.;\n  m_ridx[i] = r;\n\n  return m_data[i];\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nT\nSparse<T, Alloc>::SparseRep::celem (octave_idx_type r, octave_idx_type c) const\n{\n  if (m_nzmax > 0)\n    for (octave_idx_type i = m_cidx[c]; i < m_cidx[c + 1]; i++)\n      if (m_ridx[i] == r)\n        return m_data[i];\n  return T ();\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::SparseRep::maybe_compress (bool remove_zeros)\n{\n  if (remove_zeros)\n    {\n      octave_idx_type i = 0;\n      octave_idx_type k = 0;\n      for (octave_idx_type j = 1; j <= m_ncols; j++)\n        {\n          octave_idx_type u = m_cidx[j];\n          for (; i < u; i++)\n            if (m_data[i] != T ())\n              {\n                m_data[k] = m_data[i];\n                m_ridx[k++] = m_ridx[i];\n              }\n          m_cidx[j] = k;\n        }\n    }\n\n  change_length (m_cidx[m_ncols]);\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::SparseRep::change_length (octave_idx_type nz)\n{\n  for (octave_idx_type j = m_ncols; j > 0 && m_cidx[j] > nz; j--)\n    m_cidx[j] = nz;\n\n  // Always preserve space for 1 element.\n  nz = (nz > 0 ? nz : 1);\n\n  // Skip reallocation if we have less than 1/FRAC extra elements to discard.\n  static const int FRAC = 5;\n  if (nz > m_nzmax || nz < m_nzmax - m_nzmax/FRAC)\n    {\n      // Reallocate.\n      octave_idx_type min_nzmax = std::min (nz, m_nzmax);\n\n      octave_idx_type *new_ridx = idx_type_allocate (nz);\n      std::copy_n (m_ridx, min_nzmax, new_ridx);\n\n      idx_type_deallocate (m_ridx, m_nzmax);\n      m_ridx = new_ridx;\n\n      T *new_data = T_allocate (nz);\n      std::copy_n (m_data, min_nzmax, new_data);\n\n      T_deallocate (m_data, m_nzmax);\n      m_data = new_data;\n\n      m_nzmax = nz;\n    }\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nbool\nSparse<T, Alloc>::SparseRep::indices_ok () const\n{\n  return sparse_indices_ok (m_ridx, m_cidx, m_nrows, m_ncols, nnz ());\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nbool\nSparse<T, Alloc>::SparseRep::any_element_is_nan () const\n{\n  octave_idx_type nz = nnz ();\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    if (octave::math::isnan (m_data[i]))\n      return true;\n\n  return false;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nbool\nSparse<T, Alloc>::SparseRep::any_element_is_inf_or_nan () const\n{\n  octave_idx_type nz = nnz ();\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    if (octave::math::isinf (m_data[i]) || octave::math::isnan (m_data[i]))\n      return true;\n\n  return false;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>::Sparse (octave_idx_type nr, octave_idx_type nc, T val)\n  : m_rep (nullptr), m_dimensions (dim_vector (nr, nc))\n{\n  if (val != T ())\n    {\n      m_rep = new typename Sparse<T, Alloc>::SparseRep (nr, nc, m_dimensions.safe_numel ());\n\n      octave_idx_type ii = 0;\n      xcidx (0) = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          for (octave_idx_type i = 0; i < nr; i++)\n            {\n              xdata (ii) = val;\n              xridx (ii++) = i;\n            }\n          xcidx (j+1) = ii;\n        }\n    }\n  else\n    {\n      m_rep = new typename Sparse<T, Alloc>::SparseRep (nr, nc, 0);\n      for (octave_idx_type j = 0; j < nc+1; j++)\n        xcidx (j) = 0;\n    }\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>::Sparse (const PermMatrix& a)\n  : m_rep (new typename Sparse<T, Alloc>::SparseRep (a.rows (), a.cols (), a.rows ())),\n    m_dimensions (dim_vector (a.rows (), a.cols ()))\n{\n  octave_idx_type n = a.rows ();\n  for (octave_idx_type i = 0; i <= n; i++)\n    cidx (i) = i;\n\n  const Array<octave_idx_type> pv = a.col_perm_vec ();\n\n  for (octave_idx_type i = 0; i < n; i++)\n    ridx (i) = pv(i);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    data (i) = 1.0;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>::Sparse (const dim_vector& dv)\n  : m_rep (nullptr), m_dimensions (dv)\n{\n  if (dv.ndims () != 2)\n    (*current_liboctave_error_handler)\n      (\"Sparse::Sparse (const dim_vector&): dimension mismatch\");\n\n  m_rep = new typename Sparse<T, Alloc>::SparseRep (dv(0), dv(1), 0);\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>::Sparse (const Sparse<T, Alloc>& a, const dim_vector& dv)\n  : m_rep (nullptr), m_dimensions (dv)\n{\n\n  // Work in unsigned long long to avoid overflow issues with numel\n  unsigned long long a_nel = static_cast<unsigned long long> (a.rows ()) *\n                             static_cast<unsigned long long> (a.cols ());\n  unsigned long long dv_nel = static_cast<unsigned long long> (dv(0)) *\n                              static_cast<unsigned long long> (dv(1));\n\n  if (a_nel != dv_nel)\n    (*current_liboctave_error_handler)\n      (\"Sparse::Sparse (const Sparse&, const dim_vector&): dimension mismatch\");\n\n  const dim_vector& old_dims = a.dims ();\n  octave_idx_type new_nzmax = a.nnz ();\n  octave_idx_type new_nr = dv(0);\n  octave_idx_type new_nc = dv(1);\n  octave_idx_type old_nr = old_dims(0);\n  octave_idx_type old_nc = old_dims(1);\n\n  m_rep = new typename Sparse<T, Alloc>::SparseRep (new_nr, new_nc, new_nzmax);\n\n  octave_idx_type kk = 0;\n  xcidx (0) = 0;\n  for (octave_idx_type i = 0; i < old_nc; i++)\n    for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++)\n      {\n        octave_idx_type tmp = i * old_nr + a.ridx (j);\n        octave_idx_type ii = tmp % new_nr;\n        octave_idx_type jj = (tmp - ii) / new_nr;\n        for (octave_idx_type k = kk; k < jj; k++)\n          xcidx (k+1) = j;\n        kk = jj;\n        xdata (j) = a.data (j);\n        xridx (j) = ii;\n      }\n  for (octave_idx_type k = kk; k < new_nc; k++)\n    xcidx (k+1) = new_nzmax;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>::Sparse (const Array<T>& a,\n                          const octave::idx_vector& r,\n                          const octave::idx_vector& c,\n                          octave_idx_type nr, octave_idx_type nc,\n                          bool sum_terms, octave_idx_type nzm)\n  : m_rep (nullptr), m_dimensions ()\n{\n  if (nr < 0)\n    nr = r.extent (0);\n  else if (r.extent (nr) > nr)\n    (*current_liboctave_error_handler)\n      (\"sparse: row index %\" OCTAVE_IDX_TYPE_FORMAT \"out of bound \"\n       \"%\" OCTAVE_IDX_TYPE_FORMAT, r.extent (nr), nr);\n\n  if (nc < 0)\n    nc = c.extent (0);\n  else if (c.extent (nc) > nc)\n    (*current_liboctave_error_handler)\n      (\"sparse: column index %\" OCTAVE_IDX_TYPE_FORMAT \" out of bound \"\n       \"%\" OCTAVE_IDX_TYPE_FORMAT, c.extent (nc), nc);\n\n  m_dimensions = dim_vector (nr, nc);\n\n  octave_idx_type n = a.numel ();\n  octave_idx_type rl = r.length (nr);\n  octave_idx_type cl = c.length (nc);\n  bool a_scalar = n == 1;\n  if (a_scalar)\n    {\n      if (rl != 1)\n        n = rl;\n      else if (cl != 1)\n        n = cl;\n    }\n\n  if ((rl != 1 && rl != n) || (cl != 1 && cl != n))\n    (*current_liboctave_error_handler) (\"sparse: dimension mismatch\");\n\n  // Only create m_rep after input validation to avoid memory leak.\n  m_rep = new typename Sparse<T, Alloc>::SparseRep (nr, nc, std::max<octave_idx_type> (nzm, 0));\n\n  if (rl <= 1 && cl <= 1)\n    {\n      if (n == 1 && a(0) != T ())\n        {\n          change_capacity (std::max<octave_idx_type> (nzm, 1));\n          xridx (0) = r(0);\n          xdata (0) = a(0);\n          std::fill_n (xcidx () + c(0) + 1, nc - c(0), 1);\n        }\n    }\n  else if (a_scalar)\n    {\n      // This is completely specialized, because the sorts can be simplified.\n      T a0 = a(0);\n      if (a0 == T ())\n        {\n          // Do nothing, it's an empty matrix.\n        }\n      else if (cl == 1)\n        {\n          // Sparse column vector.  Sort row indices.\n          octave::idx_vector rs = r.sorted ();\n\n          octave_quit ();\n\n          const octave_idx_type *rd = rs.raw ();\n          // Count unique indices.\n          octave_idx_type new_nz = 1;\n          for (octave_idx_type i = 1; i < n; i++)\n            new_nz += rd[i-1] != rd[i];\n\n          // Allocate result.\n          change_capacity (std::max (nzm, new_nz));\n          std::fill_n (xcidx () + c(0) + 1, nc - c(0), new_nz);\n\n          octave_idx_type *rri = ridx ();\n          T *rrd = data ();\n\n          octave_quit ();\n\n          octave_idx_type k = -1;\n          octave_idx_type l = -1;\n\n          if (sum_terms)\n            {\n              // Sum repeated indices.\n              for (octave_idx_type i = 0; i < n; i++)\n                {\n                  if (rd[i] != l)\n                    {\n                      l = rd[i];\n                      rri[++k] = rd[i];\n                      rrd[k] = a0;\n                    }\n                  else\n                    rrd[k] += a0;\n                }\n            }\n          else\n            {\n              // Pick the last one.\n              for (octave_idx_type i = 0; i < n; i++)\n                {\n                  if (rd[i] != l)\n                    {\n                      l = rd[i];\n                      rri[++k] = rd[i];\n                      rrd[k] = a0;\n                    }\n                }\n            }\n\n        }\n      else\n        {\n          octave::idx_vector rr = r;\n          octave::idx_vector cc = c;\n          const octave_idx_type *rd = rr.raw ();\n          const octave_idx_type *cd = cc.raw ();\n          OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ci, nc+1, 0);\n          ci[0] = 0;\n          // Bin counts of column indices.\n          for (octave_idx_type i = 0; i < n; i++)\n            ci[cd[i]+1]++;\n          // Make them cumulative, shifted one to right.\n          for (octave_idx_type i = 1, s = 0; i <= nc; i++)\n            {\n              octave_idx_type s1 = s + ci[i];\n              ci[i] = s;\n              s = s1;\n            }\n\n          octave_quit ();\n\n          // Bucket sort.\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, sidx, n);\n          for (octave_idx_type i = 0; i < n; i++)\n            if (rl == 1)\n              sidx[ci[cd[i]+1]++] = rd[0];\n            else\n              sidx[ci[cd[i]+1]++] = rd[i];\n\n          // Subsorts.  We don't need a stable sort, all values are equal.\n          xcidx (0) = 0;\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              std::sort (sidx + ci[j], sidx + ci[j+1]);\n              octave_idx_type l = -1;\n              octave_idx_type nzj = 0;\n              // Count.\n              for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)\n                {\n                  octave_idx_type k = sidx[i];\n                  if (k != l)\n                    {\n                      l = k;\n                      nzj++;\n                    }\n                }\n              // Set column pointer.\n              xcidx (j+1) = xcidx (j) + nzj;\n            }\n\n          change_capacity (std::max (nzm, xcidx (nc)));\n          octave_idx_type *rri = ridx ();\n          T *rrd = data ();\n\n          // Fill-in data.\n          for (octave_idx_type j = 0, jj = -1; j < nc; j++)\n            {\n              octave_quit ();\n              octave_idx_type l = -1;\n              if (sum_terms)\n                {\n                  // Sum adjacent terms.\n                  for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)\n                    {\n                      octave_idx_type k = sidx[i];\n                      if (k != l)\n                        {\n                          l = k;\n                          rrd[++jj] = a0;\n                          rri[jj] = k;\n                        }\n                      else\n                        rrd[jj] += a0;\n                    }\n                }\n              else\n                {\n                  // Use the last one.\n                  for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)\n                    {\n                      octave_idx_type k = sidx[i];\n                      if (k != l)\n                        {\n                          l = k;\n                          rrd[++jj] = a0;\n                          rri[jj] = k;\n                        }\n                    }\n                }\n            }\n        }\n    }\n  else if (cl == 1)\n    {\n      // Sparse column vector.  Sort row indices.\n      Array<octave_idx_type> rsi;\n      octave::idx_vector rs = r.sorted (rsi);\n\n      octave_quit ();\n\n      const octave_idx_type *rd = rs.raw ();\n      const octave_idx_type *rdi = rsi.data ();\n      // Count unique indices.\n      octave_idx_type new_nz = 1;\n      for (octave_idx_type i = 1; i < n; i++)\n        new_nz += rd[i-1] != rd[i];\n\n      // Allocate result.\n      change_capacity (std::max (nzm, new_nz));\n      std::fill_n (xcidx () + c(0) + 1, nc - c(0), new_nz);\n\n      octave_idx_type *rri = ridx ();\n      T *rrd = data ();\n\n      octave_quit ();\n\n      octave_idx_type k = 0;\n      rri[k] = rd[0];\n      rrd[k] = a(rdi[0]);\n\n      if (sum_terms)\n        {\n          // Sum repeated indices.\n          for (octave_idx_type i = 1; i < n; i++)\n            {\n              if (rd[i] != rd[i-1])\n                {\n                  rri[++k] = rd[i];\n                  rrd[k] = a(rdi[i]);\n                }\n              else\n                rrd[k] += a(rdi[i]);\n            }\n        }\n      else\n        {\n          // Pick the last one.\n          for (octave_idx_type i = 1; i < n; i++)\n            {\n              if (rd[i] != rd[i-1])\n                rri[++k] = rd[i];\n              rrd[k] = a(rdi[i]);\n            }\n        }\n\n      maybe_compress (true);\n    }\n  else\n    {\n      octave::idx_vector rr = r;\n      octave::idx_vector cc = c;\n      const octave_idx_type *rd = rr.raw ();\n      const octave_idx_type *cd = cc.raw ();\n      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ci, nc+1, 0);\n      ci[0] = 0;\n      // Bin counts of column indices.\n      for (octave_idx_type i = 0; i < n; i++)\n        ci[cd[i]+1]++;\n      // Make them cumulative, shifted one to right.\n      for (octave_idx_type i = 1, s = 0; i <= nc; i++)\n        {\n          octave_idx_type s1 = s + ci[i];\n          ci[i] = s;\n          s = s1;\n        }\n\n      octave_quit ();\n\n      typedef std::pair<octave_idx_type, octave_idx_type> idx_pair;\n      // Bucket sort.\n      OCTAVE_LOCAL_BUFFER (idx_pair, spairs, n);\n      for (octave_idx_type i = 0; i < n; i++)\n        {\n          idx_pair& p = spairs[ci[cd[i]+1]++];\n          if (rl == 1)\n            p.first = rd[0];\n          else\n            p.first = rd[i];\n          p.second = i;\n        }\n\n      // Subsorts.  We don't need a stable sort, the second index stabilizes it.\n      xcidx (0) = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          std::sort (spairs + ci[j], spairs + ci[j+1]);\n          octave_idx_type l = -1;\n          octave_idx_type nzj = 0;\n          // Count.\n          for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)\n            {\n              octave_idx_type k = spairs[i].first;\n              if (k != l)\n                {\n                  l = k;\n                  nzj++;\n                }\n            }\n          // Set column pointer.\n          xcidx (j+1) = xcidx (j) + nzj;\n        }\n\n      change_capacity (std::max (nzm, xcidx (nc)));\n      octave_idx_type *rri = ridx ();\n      T *rrd = data ();\n\n      // Fill-in data.\n      for (octave_idx_type j = 0, jj = -1; j < nc; j++)\n        {\n          octave_quit ();\n          octave_idx_type l = -1;\n          if (sum_terms)\n            {\n              // Sum adjacent terms.\n              for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)\n                {\n                  octave_idx_type k = spairs[i].first;\n                  if (k != l)\n                    {\n                      l = k;\n                      rrd[++jj] = a(spairs[i].second);\n                      rri[jj] = k;\n                    }\n                  else\n                    rrd[jj] += a(spairs[i].second);\n                }\n            }\n          else\n            {\n              // Use the last one.\n              for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)\n                {\n                  octave_idx_type k = spairs[i].first;\n                  if (k != l)\n                    {\n                      l = k;\n                      rri[++jj] = k;\n                    }\n                  rrd[jj] = a(spairs[i].second);\n                }\n            }\n        }\n\n      maybe_compress (true);\n    }\n}\n\n/*\n%!assert <*51880> (sparse (1:2, 2, 1:2, 2, 2), sparse ([0, 1; 0, 2]))\n%!assert <*51880> (sparse (1:2, 1, 1:2, 2, 2), sparse ([1, 0; 2, 0]))\n%!assert <*51880> (sparse (1:2, 2, 1:2, 2, 3), sparse ([0, 1, 0; 0, 2, 0]))\n*/\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>::Sparse (const Array<T>& a)\n  : m_rep (nullptr), m_dimensions (a.dims ())\n{\n  if (m_dimensions.ndims () > 2)\n    (*current_liboctave_error_handler)\n      (\"Sparse::Sparse (const Array<T>&): dimension mismatch\");\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type len = a.numel ();\n  octave_idx_type new_nzmax = 0;\n\n  // First count the number of nonzero terms\n  for (octave_idx_type i = 0; i < len; i++)\n    if (a(i) != T ())\n      new_nzmax++;\n\n  m_rep = new typename Sparse<T, Alloc>::SparseRep (nr, nc, new_nzmax);\n\n  octave_idx_type ii = 0;\n  xcidx (0) = 0;\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      for (octave_idx_type i = 0; i < nr; i++)\n        if (a.elem (i, j) != T ())\n          {\n            xdata (ii) = a.elem (i, j);\n            xridx (ii++) = i;\n          }\n      xcidx (j+1) = ii;\n    }\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>::~Sparse ()\n{\n  if (--m_rep->m_count == 0)\n    delete m_rep;\n}\n\ntemplate <typename T, typename Alloc>\nSparse<T, Alloc>&\nSparse<T, Alloc>::operator = (const Sparse<T, Alloc>& a)\n{\n  if (this != &a)\n    {\n      if (--m_rep->m_count == 0)\n        delete m_rep;\n\n      m_rep = a.m_rep;\n      m_rep->m_count++;\n\n      m_dimensions = a.m_dimensions;\n    }\n\n  return *this;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\noctave_idx_type\nSparse<T, Alloc>::compute_index (const Array<octave_idx_type>& ra_idx) const\n{\n  octave_idx_type n = m_dimensions.ndims ();\n\n  if (n <= 0 || n != ra_idx.numel ())\n    (*current_liboctave_error_handler)\n      (\"Sparse<T, Alloc>::compute_index: invalid ra_idxing operation\");\n\n  octave_idx_type retval = -1;\n\n  retval = ra_idx(--n);\n\n  while (--n >= 0)\n    {\n      retval *= m_dimensions(n);\n      retval += ra_idx(n);\n    }\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nT\nSparse<T, Alloc>::range_error (const char *fcn, octave_idx_type n) const\n{\n  (*current_liboctave_error_handler) (\"%s (%\" OCTAVE_IDX_TYPE_FORMAT \"): \"\n                                      \"range error\", fcn, n);\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nT&\nSparse<T, Alloc>::range_error (const char *fcn, octave_idx_type n)\n{\n  (*current_liboctave_error_handler) (\"%s (%\" OCTAVE_IDX_TYPE_FORMAT \"): \"\n                                      \"range error\", fcn, n);\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nT\nSparse<T, Alloc>::range_error (const char *fcn,\n                               octave_idx_type i, octave_idx_type j) const\n{\n  (*current_liboctave_error_handler)\n    (\"%s (%\" OCTAVE_IDX_TYPE_FORMAT \", %\" OCTAVE_IDX_TYPE_FORMAT \"): \"\n     \"range error\", fcn, i, j);\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nT&\nSparse<T, Alloc>::range_error (const char *fcn,\n                               octave_idx_type i, octave_idx_type j)\n{\n  (*current_liboctave_error_handler)\n    (\"%s (%\" OCTAVE_IDX_TYPE_FORMAT \", %\" OCTAVE_IDX_TYPE_FORMAT \"): \"\n     \"range error\", fcn, i, j);\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nT\nSparse<T, Alloc>::range_error (const char *fcn,\n                               const Array<octave_idx_type>& ra_idx) const\n{\n  std::ostringstream buf;\n\n  buf << fcn << \" (\";\n\n  octave_idx_type n = ra_idx.numel ();\n\n  if (n > 0)\n    buf << ra_idx(0);\n\n  for (octave_idx_type i = 1; i < n; i++)\n    buf << \", \" << ra_idx(i);\n\n  buf << \"): range error\";\n\n  std::string buf_str = buf.str ();\n\n  (*current_liboctave_error_handler) (\"%s\", buf_str.c_str ());\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nT&\nSparse<T, Alloc>::range_error (const char *fcn,\n                               const Array<octave_idx_type>& ra_idx)\n{\n  std::ostringstream buf;\n\n  buf << fcn << \" (\";\n\n  octave_idx_type n = ra_idx.numel ();\n\n  if (n > 0)\n    buf << ra_idx(0);\n\n  for (octave_idx_type i = 1; i < n; i++)\n    buf << \", \" << ra_idx(i);\n\n  buf << \"): range error\";\n\n  std::string buf_str = buf.str ();\n\n  (*current_liboctave_error_handler) (\"%s\", buf_str.c_str ());\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>\nSparse<T, Alloc>::reshape (const dim_vector& new_dims) const\n{\n  Sparse<T, Alloc> retval;\n  dim_vector dims2 = new_dims;\n\n  if (dims2.ndims () > 2)\n    {\n      (*current_liboctave_warning_with_id_handler)\n        (\"Octave:reshape-smashes-dims\",\n         \"reshape: sparse reshape to N-D array smashes dims\");\n\n      for (octave_idx_type i = 2; i < dims2.ndims (); i++)\n        dims2(1) *= dims2(i);\n\n      dims2.resize (2);\n    }\n\n  if (m_dimensions != dims2)\n    {\n      if (m_dimensions.numel () == dims2.numel ())\n        {\n          octave_idx_type new_nnz = nnz ();\n          octave_idx_type new_nr = dims2 (0);\n          octave_idx_type new_nc = dims2 (1);\n          octave_idx_type old_nr = rows ();\n          octave_idx_type old_nc = cols ();\n          retval = Sparse<T, Alloc> (new_nr, new_nc, new_nnz);\n          // Special case for empty matrices (bug #64080)\n          if (new_nr == 0 || new_nc == 0)\n            return retval;\n\n          octave_idx_type kk = 0;\n          retval.xcidx (0) = 0;\n          // Quotient and remainder of i * old_nr divided by new_nr.\n          // Track them individually to avoid overflow (bug #42850).\n          octave_idx_type i_old_qu = 0;\n          octave_idx_type i_old_rm = static_cast<octave_idx_type> (-old_nr);\n          for (octave_idx_type i = 0; i < old_nc; i++)\n            {\n              i_old_rm += old_nr;\n              if (i_old_rm >= new_nr)\n                {\n                  i_old_qu += i_old_rm / new_nr;\n                  i_old_rm = i_old_rm % new_nr;\n                }\n              for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)\n                {\n                  octave_idx_type ii, jj;\n                  ii = (i_old_rm + ridx (j)) % new_nr;\n                  jj = i_old_qu + (i_old_rm + ridx (j)) / new_nr;\n\n                  // Original calculation subject to overflow\n                  // ii = (i*old_nr + ridx (j)) % new_nr\n                  // jj = (i*old_nr + ridx (j)) / new_nr\n                  for (octave_idx_type k = kk; k < jj; k++)\n                    retval.xcidx (k+1) = j;\n                  kk = jj;\n                  retval.xdata (j) = data (j);\n                  retval.xridx (j) = ii;\n                }\n            }\n          for (octave_idx_type k = kk; k < new_nc; k++)\n            retval.xcidx (k+1) = new_nnz;\n        }\n      else\n        {\n          std::string dimensions_str = m_dimensions.str ();\n          std::string new_dims_str = new_dims.str ();\n\n          (*current_liboctave_error_handler)\n            (\"reshape: can't reshape %s array to %s array\",\n             dimensions_str.c_str (), new_dims_str.c_str ());\n        }\n    }\n  else\n    retval = *this;\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>\nSparse<T, Alloc>::permute (const Array<octave_idx_type>& perm_vec, bool) const\n{\n  // The only valid permutations of a sparse array are [1, 2] and [2, 1].\n\n  bool fail = false;\n  bool trans = false;\n\n  if (perm_vec.numel () == 2)\n    {\n      if (perm_vec(0) == 0 && perm_vec(1) == 1)\n        /* do nothing */;\n      else if (perm_vec(0) == 1 && perm_vec(1) == 0)\n        trans = true;\n      else\n        fail = true;\n    }\n  else\n    fail = true;\n\n  if (fail)\n    (*current_liboctave_error_handler)\n      (\"permutation vector contains an invalid element\");\n\n  return trans ? this->transpose () : *this;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::resize1 (octave_idx_type n)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr == 0)\n    resize (1, std::max (nc, n));\n  else if (nc == 0)\n    resize (nr, (n + nr - 1) / nr); // Ain't it wicked?\n  else if (nr == 1)\n    resize (1, n);\n  else if (nc == 1)\n    resize (n, 1);\n  else\n    octave::err_invalid_resize ();\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::resize (const dim_vector& dv)\n{\n  octave_idx_type n = dv.ndims ();\n\n  if (n != 2)\n    (*current_liboctave_error_handler) (\"sparse array must be 2-D\");\n\n  resize (dv(0), dv(1));\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::resize (octave_idx_type r, octave_idx_type c)\n{\n  if (r < 0 || c < 0)\n    (*current_liboctave_error_handler) (\"can't resize to negative dimension\");\n\n  if (r == dim1 () && c == dim2 ())\n    return;\n\n  // This wouldn't be necessary for r >= rows () if m_nrows wasn't part of the\n  // Sparse rep.  It is not good for anything in there.\n  make_unique ();\n\n  if (r < rows ())\n    {\n      octave_idx_type i = 0;\n      octave_idx_type k = 0;\n      for (octave_idx_type j = 1; j <= m_rep->m_ncols; j++)\n        {\n          octave_idx_type u = xcidx (j);\n          for (; i < u; i++)\n            if (xridx (i) < r)\n              {\n                xdata (k) = xdata (i);\n                xridx (k++) = xridx (i);\n              }\n          xcidx (j) = k;\n        }\n    }\n\n  m_rep->m_nrows = m_dimensions(0) = r;\n\n  if (c != m_rep->m_ncols)\n    {\n      octave_idx_type *new_cidx = m_rep->idx_type_allocate (c+1);\n      std::copy_n (m_rep->m_cidx, std::min (c, m_rep->m_ncols) + 1, new_cidx);\n      m_rep->idx_type_deallocate (m_rep->m_cidx, m_rep->m_ncols + 1);\n      m_rep->m_cidx = new_cidx;\n\n      if (c > m_rep->m_ncols)\n        std::fill_n (m_rep->m_cidx + m_rep->m_ncols + 1, c - m_rep->m_ncols,\n                     m_rep->m_cidx[m_rep->m_ncols]);\n    }\n\n  m_rep->m_ncols = m_dimensions(1) = c;\n\n  m_rep->change_length (m_rep->nnz ());\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>&\nSparse<T, Alloc>::insert (const Sparse<T, Alloc>& a,\n                          octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_rows = a.rows ();\n  octave_idx_type a_cols = a.cols ();\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  // First count the number of elements in the final array\n  octave_idx_type nel = cidx (c) + a.nnz ();\n\n  if (c + a_cols < nc)\n    nel += cidx (nc) - cidx (c + a_cols);\n\n  for (octave_idx_type i = c; i < c + a_cols; i++)\n    for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)\n      if (ridx (j) < r || ridx (j) >= r + a_rows)\n        nel++;\n\n  Sparse<T, Alloc> tmp (*this);\n  --m_rep->m_count;\n  m_rep = new typename Sparse<T, Alloc>::SparseRep (nr, nc, nel);\n\n  for (octave_idx_type i = 0; i < tmp.cidx (c); i++)\n    {\n      data (i) = tmp.data (i);\n      ridx (i) = tmp.ridx (i);\n    }\n  for (octave_idx_type i = 0; i < c + 1; i++)\n    cidx (i) = tmp.cidx (i);\n\n  octave_idx_type ii = cidx (c);\n\n  for (octave_idx_type i = c; i < c + a_cols; i++)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = tmp.cidx (i); j < tmp.cidx (i+1); j++)\n        if (tmp.ridx (j) < r)\n          {\n            data (ii) = tmp.data (j);\n            ridx (ii++) = tmp.ridx (j);\n          }\n\n      octave_quit ();\n\n      for (octave_idx_type j = a.cidx (i-c); j < a.cidx (i-c+1); j++)\n        {\n          data (ii) = a.data (j);\n          ridx (ii++) = r + a.ridx (j);\n        }\n\n      octave_quit ();\n\n      for (octave_idx_type j = tmp.cidx (i); j < tmp.cidx (i+1); j++)\n        if (tmp.ridx (j) >= r + a_rows)\n          {\n            data (ii) = tmp.data (j);\n            ridx (ii++) = tmp.ridx (j);\n          }\n\n      cidx (i+1) = ii;\n    }\n\n  for (octave_idx_type i = c + a_cols; i < nc; i++)\n    {\n      for (octave_idx_type j = tmp.cidx (i); j < tmp.cidx (i+1); j++)\n        {\n          data (ii) = tmp.data (j);\n          ridx (ii++) = tmp.ridx (j);\n        }\n      cidx (i+1) = ii;\n    }\n\n  return *this;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>&\nSparse<T, Alloc>::insert (const Sparse<T, Alloc>& a,\n                          const Array<octave_idx_type>& ra_idx)\n{\n\n  if (ra_idx.numel () != 2)\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  return insert (a, ra_idx(0), ra_idx(1));\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>\nSparse<T, Alloc>::transpose () const\n{\n  liboctave_panic_unless (ndims () == 2);\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz = nnz ();\n  Sparse<T, Alloc> retval (nc, nr, nz);\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    retval.xcidx (ridx (i) + 1)++;\n  // retval.xcidx[1:nr] holds the row degrees for rows 0:(nr-1)\n  nz = 0;\n  for (octave_idx_type i = 1; i <= nr; i++)\n    {\n      const octave_idx_type tmp = retval.xcidx (i);\n      retval.xcidx (i) = nz;\n      nz += tmp;\n    }\n  // retval.xcidx[1:nr] holds row entry *start* offsets for rows 0:(nr-1)\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type k = cidx (j); k < cidx (j+1); k++)\n      {\n        octave_idx_type q = retval.xcidx (ridx (k) + 1)++;\n        retval.xridx (q) = j;\n        retval.xdata (q) = data (k);\n      }\n  liboctave_panic_unless (nnz () == retval.xcidx (nr));\n  // retval.xcidx[1:nr] holds row entry *end* offsets for rows 0:(nr-1)\n  // and retval.xcidx[0:(nr-1)] holds their row entry *start* offsets\n\n  return retval;\n}\n\n// Lower bound lookup.  Could also use octave_sort, but that has upper bound\n// semantics, so requires some manipulation to set right.  Uses a plain loop\n// for small columns.\nstatic\noctave_idx_type\nlblookup (const octave_idx_type *ridx, octave_idx_type nr,\n          octave_idx_type ri)\n{\n  if (nr <= 8)\n    {\n      octave_idx_type l;\n      for (l = 0; l < nr; l++)\n        if (ridx[l] >= ri)\n          break;\n      return l;\n    }\n  else\n    return std::lower_bound (ridx, ridx + nr, ri) - ridx;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::delete_elements (const octave::idx_vector& idx)\n{\n  Sparse<T, Alloc> retval;\n\n  liboctave_panic_unless (ndims () == 2);\n\n  octave_idx_type nr = dim1 ();\n  octave_idx_type nc = dim2 ();\n  octave_idx_type nz = nnz ();\n\n  octave_idx_type nel = numel (); // Can throw.\n\n  const dim_vector idx_dims = idx.orig_dimensions ();\n\n  if (idx.extent (nel) > nel)\n    octave::err_del_index_out_of_range (true, idx.extent (nel), nel);\n\n  if (nc == 1)\n    {\n      // Sparse column vector.\n      const Sparse<T, Alloc> tmp = *this; // constant copy to prevent COW.\n\n      octave_idx_type lb, ub;\n\n      if (idx.is_cont_range (nel, lb, ub))\n        {\n          // Special-case a contiguous range.\n          // Look-up indices first.\n          octave_idx_type li = lblookup (tmp.ridx (), nz, lb);\n          octave_idx_type ui = lblookup (tmp.ridx (), nz, ub);\n          // Copy data and adjust indices.\n          octave_idx_type nz_new = nz - (ui - li);\n          *this = Sparse<T, Alloc> (nr - (ub - lb), 1, nz_new);\n          std::copy_n (tmp.data (), li, data ());\n          std::copy_n (tmp.ridx (), li, xridx ());\n          std::copy (tmp.data () + ui, tmp.data () + nz, xdata () + li);\n          mx_inline_sub (nz - ui, xridx () + li, tmp.ridx () + ui, ub - lb);\n          xcidx (1) = nz_new;\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, ridx_new, nz);\n          OCTAVE_LOCAL_BUFFER (T, data_new, nz);\n          octave::idx_vector sidx = idx.sorted (true);\n          const octave_idx_type *sj = sidx.raw ();\n          octave_idx_type sl = sidx.length (nel);\n          octave_idx_type nz_new = 0;\n          octave_idx_type j = 0;\n          for (octave_idx_type i = 0; i < nz; i++)\n            {\n              octave_idx_type r = tmp.ridx (i);\n              for (; j < sl && sj[j] < r; j++) ;\n              if (j == sl || sj[j] > r)\n                {\n                  data_new[nz_new] = tmp.data (i);\n                  ridx_new[nz_new++] = r - j;\n                }\n            }\n\n          *this = Sparse<T, Alloc> (nr - sl, 1, nz_new);\n          std::copy_n (ridx_new, nz_new, ridx ());\n          std::copy_n (data_new, nz_new, xdata ());\n          xcidx (1) = nz_new;\n        }\n    }\n  else if (nr == 1)\n    {\n      // Sparse row vector.\n      octave_idx_type lb, ub;\n      if (idx.is_cont_range (nc, lb, ub))\n        {\n          const Sparse<T, Alloc> tmp = *this;\n          octave_idx_type lbi = tmp.cidx (lb);\n          octave_idx_type ubi = tmp.cidx (ub);\n          octave_idx_type new_nz = nz - (ubi - lbi);\n          *this = Sparse<T, Alloc> (1, nc - (ub - lb), new_nz);\n          std::copy_n (tmp.data (), lbi, data ());\n          std::copy (tmp.data () + ubi, tmp.data () + nz, xdata () + lbi);\n          std::fill_n (ridx (), new_nz, static_cast<octave_idx_type> (0));\n          std::copy_n (tmp.cidx () + 1, lb, cidx () + 1);\n          mx_inline_sub (nc - ub, xcidx () + 1, tmp.cidx () + ub + 1,\n                         ubi - lbi);\n        }\n      else\n        *this = index (idx.complement (nc));\n    }\n  else if (idx.length (nel) != 0)\n    {\n      if (idx.is_colon_equiv (nel))\n        *this = Sparse<T, Alloc> ();\n      else\n        {\n          *this = index (octave::idx_vector::colon);\n          delete_elements (idx);\n          *this = transpose (); // We want a row vector.\n        }\n    }\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::delete_elements (const octave::idx_vector& idx_i,\n                                   const octave::idx_vector& idx_j)\n{\n  liboctave_panic_unless (ndims () == 2);\n\n  octave_idx_type nr = dim1 ();\n  octave_idx_type nc = dim2 ();\n  octave_idx_type nz = nnz ();\n\n  if (idx_i.is_colon ())\n    {\n      // Deleting columns.\n      octave_idx_type lb, ub;\n      if (idx_j.extent (nc) > nc)\n        octave::err_del_index_out_of_range (false, idx_j.extent (nc), nc);\n      else if (idx_j.is_cont_range (nc, lb, ub))\n        {\n          if (lb == 0 && ub == nc)\n            {\n              // Delete all rows and columns.\n              *this = Sparse<T, Alloc> (nr, 0);\n            }\n          else if (nz == 0)\n            {\n              // No elements to preserve; adjust dimensions.\n              *this = Sparse<T, Alloc> (nr, nc - (ub - lb));\n            }\n          else\n            {\n              const Sparse<T, Alloc> tmp = *this;\n              octave_idx_type lbi = tmp.cidx (lb);\n              octave_idx_type ubi = tmp.cidx (ub);\n              octave_idx_type new_nz = nz - (ubi - lbi);\n\n              *this = Sparse<T, Alloc> (nr, nc - (ub - lb), new_nz);\n              std::copy_n (tmp.data (), lbi, data ());\n              std::copy_n (tmp.ridx (), lbi, ridx ());\n              std::copy (tmp.data () + ubi, tmp.data () + nz, xdata () + lbi);\n              std::copy (tmp.ridx () + ubi, tmp.ridx () + nz, xridx () + lbi);\n              std::copy_n (tmp.cidx () + 1, lb, cidx () + 1);\n              mx_inline_sub (nc - ub, xcidx () + lb + 1,\n                             tmp.cidx () + ub + 1, ubi - lbi);\n            }\n        }\n      else\n        *this = index (idx_i, idx_j.complement (nc));\n    }\n  else if (idx_j.is_colon ())\n    {\n      // Deleting rows.\n      octave_idx_type lb, ub;\n      if (idx_i.extent (nr) > nr)\n        octave::err_del_index_out_of_range (false, idx_i.extent (nr), nr);\n      else if (idx_i.is_cont_range (nr, lb, ub))\n        {\n          if (lb == 0 && ub == nr)\n            {\n              // Delete all rows and columns.\n              *this = Sparse<T, Alloc> (0, nc);\n            }\n          else if (nz == 0)\n            {\n              // No elements to preserve; adjust dimensions.\n              *this = Sparse<T, Alloc> (nr - (ub - lb), nc);\n            }\n          else\n            {\n              // This is more memory-efficient than the approach below.\n              const Sparse<T, Alloc> tmpl = index (octave::idx_vector (0, lb), idx_j);\n              const Sparse<T, Alloc> tmpu = index (octave::idx_vector (ub, nr), idx_j);\n              *this = Sparse<T, Alloc> (nr - (ub - lb), nc,\n                                        tmpl.nnz () + tmpu.nnz ());\n              for (octave_idx_type j = 0, k = 0; j < nc; j++)\n                {\n                  for (octave_idx_type i = tmpl.cidx (j); i < tmpl.cidx (j+1);\n                       i++)\n                    {\n                      xdata (k) = tmpl.data (i);\n                      xridx (k++) = tmpl.ridx (i);\n                    }\n                  for (octave_idx_type i = tmpu.cidx (j); i < tmpu.cidx (j+1);\n                       i++)\n                    {\n                      xdata (k) = tmpu.data (i);\n                      xridx (k++) = tmpu.ridx (i) + lb;\n                    }\n\n                  xcidx (j+1) = k;\n                }\n            }\n        }\n      else\n        {\n          // This is done by transposing, deleting columns, then transposing\n          // again.\n          Sparse<T, Alloc> tmp = transpose ();\n          tmp.delete_elements (idx_j, idx_i);\n          *this = tmp.transpose ();\n        }\n    }\n  else\n    {\n      // Empty assignment (no elements to delete) is OK if there is at\n      // least one zero-length index and at most one other index that is\n      // non-colon (or equivalent) index.  Since we only have two\n      // indices, we just need to check that we have at least one zero\n      // length index.  Matlab considers \"[]\" to be an empty index but\n      // not \"false\".  We accept both.\n\n      bool empty_assignment\n        = (idx_i.length (nr) == 0 || idx_j.length (nc) == 0);\n\n      if (! empty_assignment)\n        (*current_liboctave_error_handler)\n          (\"a null assignment can only have one non-colon index\");\n    }\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::delete_elements (int dim, const octave::idx_vector& idx)\n{\n  if (dim == 0)\n    delete_elements (idx, octave::idx_vector::colon);\n  else if (dim == 1)\n    delete_elements (octave::idx_vector::colon, idx);\n  else\n    (*current_liboctave_error_handler) (\"invalid dimension in delete_elements\");\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>\nSparse<T, Alloc>::index (const octave::idx_vector& idx, bool resize_ok) const\n{\n  Sparse<T, Alloc> retval;\n\n  liboctave_panic_unless (ndims () == 2);\n\n  octave_idx_type nr = dim1 ();\n  octave_idx_type nc = dim2 ();\n  octave_idx_type nz = nnz ();\n\n  octave_idx_type nel = numel (); // Can throw.\n\n  const dim_vector idx_dims = idx.orig_dimensions ();\n  if (idx_dims.ndims () != 2)\n    (*current_liboctave_error_handler) (\"only 2-D indexing is allowed for sparse arrays\");\n\n  if (idx.is_colon ())\n    {\n      if (nc == 1)\n        retval = *this;\n      else\n        {\n          // Fast magic colon processing.\n          retval = Sparse<T, Alloc> (nel, 1, nz);\n\n          for (octave_idx_type i = 0; i < nc; i++)\n            {\n              for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)\n                {\n                  retval.xdata (j) = data (j);\n                  retval.xridx (j) = ridx (j) + i * nr;\n                }\n            }\n\n          retval.xcidx (0) = 0;\n          retval.xcidx (1) = nz;\n        }\n    }\n  else if (idx.extent (nel) > nel)\n    {\n      if (! resize_ok)\n        octave::err_index_out_of_range (1, 1, idx.extent (nel), nel, dims ());\n\n      // resize_ok is completely handled here.\n      octave_idx_type ext = idx.extent (nel);\n      Sparse<T, Alloc> tmp = *this;\n      tmp.resize1 (ext);\n      retval = tmp.index (idx);\n    }\n  else if (nr == 1 && nc == 1)\n    {\n      // You have to be pretty sick to get to this bit of code,\n      // since you have a scalar stored as a sparse matrix, and\n      // then want to make a dense matrix with sparse representation.\n      // Ok, we'll do it, but you deserve what you get!!\n      retval = (Sparse<T, Alloc> (idx_dims(0), idx_dims(1), nz ? data (0) : T ()));\n    }\n  else if (nc == 1)\n    {\n      // Sparse column vector.\n      octave_idx_type lb, ub;\n\n      if (idx.is_scalar ())\n        {\n          // Scalar index - just a binary lookup.\n          octave_idx_type i = lblookup (ridx (), nz, idx(0));\n          if (i < nz && ridx (i) == idx(0))\n            retval = Sparse (1, 1, data (i));\n          else\n            retval = Sparse (1, 1);\n        }\n      else if (idx.is_cont_range (nel, lb, ub))\n        {\n          // Special-case a contiguous range.\n          // Look-up indices first.\n          octave_idx_type li = lblookup (ridx (), nz, lb);\n          octave_idx_type ui = lblookup (ridx (), nz, ub);\n          // Copy data and adjust indices.\n          octave_idx_type nz_new = ui - li;\n          retval = Sparse<T, Alloc> (ub - lb, 1, nz_new);\n          std::copy_n (data () + li, nz_new, retval.data ());\n          mx_inline_sub (nz_new, retval.xridx (), ridx () + li, lb);\n          retval.xcidx (1) = nz_new;\n        }\n      else if (idx.is_permutation (nel) && idx.isvector ())\n        {\n          if (idx.is_range () && idx.increment () == -1)\n            {\n              retval = Sparse<T, Alloc> (nr, 1, nz);\n\n              for (octave_idx_type j = 0; j < nz; j++)\n                retval.ridx (j) = nr - ridx (nz - j - 1) - 1;\n\n              std::copy_n (cidx (), 2, retval.cidx ());\n              std::reverse_copy (data (), data () + nz, retval.data ());\n            }\n          else\n            {\n              Array<T> tmp = array_value ();\n              tmp = tmp.index (idx);\n              retval = Sparse<T, Alloc> (tmp);\n            }\n        }\n      else\n        {\n          // If indexing a sparse column vector by a vector, the result is a\n          // sparse column vector, otherwise it inherits the shape of index.\n          // Vector transpose is cheap, so do it right here.\n\n          Array<octave_idx_type> tmp_idx = idx.as_array ().as_matrix ();\n\n          const Array<octave_idx_type> idxa = (idx_dims(0) == 1\n                                               ? tmp_idx.transpose ()\n                                               : tmp_idx);\n\n          octave_idx_type new_nr = idxa.rows ();\n          octave_idx_type new_nc = idxa.cols ();\n\n          // Lookup.\n          // FIXME: Could specialize for sorted idx?\n          Array<octave_idx_type> lidx (dim_vector (new_nr, new_nc));\n          for (octave_idx_type i = 0; i < new_nr*new_nc; i++)\n            lidx.xelem (i) = lblookup (ridx (), nz, idxa(i));\n\n          // Count matches.\n          retval = Sparse<T, Alloc> (idxa.rows (), idxa.cols ());\n          for (octave_idx_type j = 0; j < new_nc; j++)\n            {\n              octave_idx_type nzj = 0;\n              for (octave_idx_type i = 0; i < new_nr; i++)\n                {\n                  octave_idx_type l = lidx.xelem (i, j);\n                  if (l < nz && ridx (l) == idxa(i, j))\n                    nzj++;\n                  else\n                    lidx.xelem (i, j) = nz;\n                }\n              retval.xcidx (j+1) = retval.xcidx (j) + nzj;\n            }\n\n          retval.change_capacity (retval.xcidx (new_nc));\n\n          // Copy data and set row indices.\n          octave_idx_type k = 0;\n          for (octave_idx_type j = 0; j < new_nc; j++)\n            for (octave_idx_type i = 0; i < new_nr; i++)\n              {\n                octave_idx_type l = lidx.xelem (i, j);\n                if (l < nz)\n                  {\n                    retval.data (k) = data (l);\n                    retval.xridx (k++) = i;\n                  }\n              }\n        }\n    }\n  else if (nr == 1)\n    {\n      octave_idx_type lb, ub;\n      if (idx.is_scalar ())\n        retval = Sparse<T, Alloc> (1, 1, elem (0, idx(0)));\n      else if (idx.is_cont_range (nel, lb, ub))\n        {\n          // Special-case a contiguous range.\n          octave_idx_type lbi = cidx (lb);\n          octave_idx_type ubi = cidx (ub);\n          octave_idx_type new_nz = ubi - lbi;\n          retval = Sparse<T, Alloc> (1, ub - lb, new_nz);\n          std::copy_n (data () + lbi, new_nz, retval.data ());\n          std::fill_n (retval.ridx (), new_nz, static_cast<octave_idx_type> (0));\n          mx_inline_sub (ub - lb + 1, retval.cidx (), cidx () + lb, lbi);\n        }\n      else\n        {\n          // Sparse row vectors occupy O(nr) storage anyway, so let's just\n          // convert the matrix to full, index, and sparsify the result.\n          retval = Sparse<T, Alloc> (array_value ().index (idx));\n        }\n    }\n  else\n    {\n      if (nr != 0 && idx.is_scalar ())\n        retval = Sparse<T, Alloc> (1, 1, elem (idx(0) % nr, idx(0) / nr));\n      else\n        {\n          // Indexing a non-vector sparse matrix by linear indexing.\n          // I suppose this is rare (and it may easily overflow), so let's take\n          // the easy way, and reshape first to column vector, which is already\n          // handled above.\n          retval = index (octave::idx_vector::colon).index (idx);\n          // In this case we're supposed to always inherit the shape, but\n          // column(row) doesn't do it, so we'll do it instead.\n          if (idx_dims(0) == 1 && idx_dims(1) != 1)\n            retval = retval.transpose ();\n        }\n    }\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>\nSparse<T, Alloc>::index (const octave::idx_vector& idx_i,\n                         const octave::idx_vector& idx_j,\n                         bool resize_ok) const\n{\n  Sparse<T, Alloc> retval;\n\n  liboctave_panic_unless (ndims () == 2);\n\n  octave_idx_type nr = dim1 ();\n  octave_idx_type nc = dim2 ();\n\n  octave_idx_type n = idx_i.length (nr);\n  octave_idx_type m = idx_j.length (nc);\n\n  octave_idx_type lb, ub;\n\n  if (idx_i.extent (nr) > nr || idx_j.extent (nc) > nc)\n    {\n      // resize_ok is completely handled here.\n      if (resize_ok)\n        {\n          octave_idx_type ext_i = idx_i.extent (nr);\n          octave_idx_type ext_j = idx_j.extent (nc);\n          Sparse<T, Alloc> tmp = *this;\n          tmp.resize (ext_i, ext_j);\n          retval = tmp.index (idx_i, idx_j);\n        }\n      else if (idx_i.extent (nr) > nr)\n        octave::err_index_out_of_range (2, 1, idx_i.extent (nr), nr, dims ());\n      else\n        octave::err_index_out_of_range (2, 2, idx_j.extent (nc), nc, dims ());\n    }\n  else if (nr == 1 && nc == 1)\n    {\n      // Scalars stored as sparse matrices occupy more memory than\n      // a scalar, so let's just convert the matrix to full, index,\n      // and sparsify the result.\n\n      retval = Sparse<T, Alloc> (array_value ().index (idx_i, idx_j));\n    }\n  else if (idx_i.is_colon ())\n    {\n      // Great, we're just manipulating columns.  This is going to be quite\n      // efficient, because the columns can stay compressed as they are.\n      if (idx_j.is_colon ())\n        retval = *this; // Shallow copy.\n      else if (idx_j.is_cont_range (nc, lb, ub))\n        {\n          // Special-case a contiguous range.\n          octave_idx_type lbi = cidx (lb);\n          octave_idx_type ubi = cidx (ub);\n          octave_idx_type new_nz = ubi - lbi;\n          retval = Sparse<T, Alloc> (nr, ub - lb, new_nz);\n          std::copy_n (data () + lbi, new_nz, retval.data ());\n          std::copy_n (ridx () + lbi, new_nz, retval.ridx ());\n          mx_inline_sub (ub - lb + 1, retval.cidx (), cidx () + lb, lbi);\n        }\n      else\n        {\n          // Count new nonzero elements.\n          retval = Sparse<T, Alloc> (nr, m);\n          for (octave_idx_type j = 0; j < m; j++)\n            {\n              octave_idx_type jj = idx_j(j);\n              retval.xcidx (j+1) = retval.xcidx (j) + (cidx (jj+1) - cidx (jj));\n            }\n\n          retval.change_capacity (retval.xcidx (m));\n\n          // Copy data & indices.\n          for (octave_idx_type j = 0; j < m; j++)\n            {\n              octave_idx_type ljj = cidx (idx_j(j));\n              octave_idx_type lj = retval.xcidx (j);\n              octave_idx_type nzj = retval.xcidx (j+1) - lj;\n\n              std::copy_n (data () + ljj, nzj, retval.data () + lj);\n              std::copy_n (ridx () + ljj, nzj, retval.ridx () + lj);\n            }\n        }\n    }\n  else if (nc == 1 && idx_j.is_colon_equiv (nc) && idx_i.isvector ())\n    {\n      // It's actually vector indexing.  The 1-D index is specialized for that.\n      retval = index (idx_i);\n\n      // If nr == 1 then the vector indexing will return a column vector!!\n      if (nr == 1)\n        retval.transpose ();\n    }\n  else if (idx_i.is_scalar ())\n    {\n      octave_idx_type ii = idx_i(0);\n      retval = Sparse<T, Alloc> (1, m);\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, ij, m);\n      for (octave_idx_type j = 0; j < m; j++)\n        {\n          octave_quit ();\n          octave_idx_type jj = idx_j(j);\n          octave_idx_type lj = cidx (jj);\n          octave_idx_type nzj = cidx (jj+1) - cidx (jj);\n\n          // Scalar index - just a binary lookup.\n          octave_idx_type i = lblookup (ridx () + lj, nzj, ii);\n          if (i < nzj && ridx (i+lj) == ii)\n            {\n              ij[j] = i + lj;\n              retval.xcidx (j+1) = retval.xcidx (j) + 1;\n            }\n          else\n            retval.xcidx (j+1) = retval.xcidx (j);\n        }\n\n      retval.change_capacity (retval.xcidx (m));\n\n      // Copy data, adjust row indices.\n      for (octave_idx_type j = 0; j < m; j++)\n        {\n          octave_idx_type i = retval.xcidx (j);\n          if (retval.xcidx (j+1) > i)\n            {\n              retval.xridx (i) = 0;\n              retval.xdata (i) = data (ij[j]);\n            }\n        }\n    }\n  else if (idx_i.is_cont_range (nr, lb, ub))\n    {\n      retval = Sparse<T, Alloc> (n, m);\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, li, m);\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, ui, m);\n      for (octave_idx_type j = 0; j < m; j++)\n        {\n          octave_quit ();\n          octave_idx_type jj = idx_j(j);\n          octave_idx_type lj = cidx (jj);\n          octave_idx_type nzj = cidx (jj+1) - cidx (jj);\n          octave_idx_type lij, uij;\n\n          // Lookup indices.\n          li[j] = lij = lblookup (ridx () + lj, nzj, lb) + lj;\n          ui[j] = uij = lblookup (ridx () + lj, nzj, ub) + lj;\n          retval.xcidx (j+1) = retval.xcidx (j) + ui[j] - li[j];\n        }\n\n      retval.change_capacity (retval.xcidx (m));\n\n      // Copy data, adjust row indices.\n      for (octave_idx_type j = 0, k = 0; j < m; j++)\n        {\n          octave_quit ();\n          for (octave_idx_type i = li[j]; i < ui[j]; i++)\n            {\n              retval.xdata (k) = data (i);\n              retval.xridx (k++) = ridx (i) - lb;\n            }\n        }\n    }\n  else if (idx_i.is_permutation (nr))\n    {\n      // The columns preserve their length, just need to renumber and sort them.\n      // Count new nonzero elements.\n      retval = Sparse<T, Alloc> (nr, m);\n      for (octave_idx_type j = 0; j < m; j++)\n        {\n          octave_idx_type jj = idx_j(j);\n          retval.xcidx (j+1) = retval.xcidx (j) + (cidx (jj+1) - cidx (jj));\n        }\n\n      retval.change_capacity (retval.xcidx (m));\n\n      octave_quit ();\n\n      if (idx_i.is_range () && idx_i.increment () == -1)\n        {\n          // It's nr:-1:1.  Just flip all columns.\n          for (octave_idx_type j = 0; j < m; j++)\n            {\n              octave_quit ();\n              octave_idx_type jj = idx_j(j);\n              octave_idx_type lj = cidx (jj);\n              octave_idx_type nzj = cidx (jj+1) - cidx (jj);\n              octave_idx_type li = retval.xcidx (j);\n              octave_idx_type uj = lj + nzj - 1;\n              for (octave_idx_type i = 0; i < nzj; i++)\n                {\n                  retval.xdata (li + i) = data (uj - i); // Copy in reverse order.\n                  retval.xridx (li + i) = nr - 1 - ridx (uj - i); // Ditto with transform.\n                }\n            }\n        }\n      else\n        {\n          // Get inverse permutation.\n          octave::idx_vector idx_iinv = idx_i.inverse_permutation (nr);\n          const octave_idx_type *iinv = idx_iinv.raw ();\n\n          // Scatter buffer.\n          OCTAVE_LOCAL_BUFFER (T, scb, nr);\n          octave_idx_type *rri = retval.ridx ();\n\n          for (octave_idx_type j = 0; j < m; j++)\n            {\n              octave_quit ();\n              octave_idx_type jj = idx_j(j);\n              octave_idx_type lj = cidx (jj);\n              octave_idx_type nzj = cidx (jj+1) - cidx (jj);\n              octave_idx_type li = retval.xcidx (j);\n              // Scatter the column, transform indices.\n              for (octave_idx_type i = 0; i < nzj; i++)\n                scb[rri[li + i] = iinv[ridx (lj + i)]] = data (lj + i);\n\n              octave_quit ();\n\n              // Sort them.\n              std::sort (rri + li, rri + li + nzj);\n\n              // Gather.\n              for (octave_idx_type i = 0; i < nzj; i++)\n                retval.xdata (li + i) = scb[rri[li + i]];\n            }\n        }\n\n    }\n  else if (idx_j.is_colon ())\n    {\n      // This requires uncompressing columns, which is generally costly,\n      // so we rely on the efficient transpose to handle this.\n      // It may still make sense to optimize some cases here.\n      retval = transpose ();\n      retval = retval.index (octave::idx_vector::colon, idx_i);\n      retval = retval.transpose ();\n    }\n  else\n    {\n      // A(I, J) is decomposed into A(:, J)(I, :).\n      retval = index (octave::idx_vector::colon, idx_j);\n      retval = retval.index (idx_i, octave::idx_vector::colon);\n    }\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::assign (const octave::idx_vector& idx,\n                          const Sparse<T, Alloc>& rhs)\n{\n  Sparse<T, Alloc> retval;\n\n  liboctave_panic_unless (ndims () == 2);\n\n  octave_idx_type nr = dim1 ();\n  octave_idx_type nc = dim2 ();\n  octave_idx_type nz = nnz ();\n\n  octave_idx_type n = numel (); // Can throw.\n\n  octave_idx_type rhl = rhs.numel ();\n\n  if (idx.length (n) == rhl)\n    {\n      if (rhl == 0)\n        return;\n\n      octave_idx_type nx = idx.extent (n);\n      // Try to resize first if necessary.\n      if (nx != n)\n        {\n          resize1 (nx);\n          n = numel ();\n          nr = rows ();\n          nc = cols ();\n          // nz is preserved.\n        }\n\n      if (idx.is_colon ())\n        {\n          *this = rhs.reshape (m_dimensions);\n        }\n      else if (nc == 1 && rhs.cols () == 1)\n        {\n          // Sparse column vector to sparse column vector assignment.\n\n          octave_idx_type lb, ub;\n          if (idx.is_cont_range (nr, lb, ub))\n            {\n              // Special-case a contiguous range.\n              // Look-up indices first.\n              octave_idx_type li = lblookup (ridx (), nz, lb);\n              octave_idx_type ui = lblookup (ridx (), nz, ub);\n              octave_idx_type rnz = rhs.nnz ();\n              octave_idx_type new_nz = nz - (ui - li) + rnz;\n\n              if (new_nz >= nz && new_nz <= nzmax ())\n                {\n                  // Adding/overwriting elements, enough capacity allocated.\n\n                  if (new_nz > nz)\n                    {\n                      // Make room first.\n                      std::copy_backward (data () + ui, data () + nz,\n                                          data () + nz + rnz);\n                      std::copy_backward (ridx () + ui, ridx () + nz,\n                                          ridx () + nz + rnz);\n                    }\n\n                  // Copy data and adjust indices from rhs.\n                  std::copy_n (rhs.data (), rnz, data () + li);\n                  mx_inline_add (rnz, ridx () + li, rhs.ridx (), lb);\n                }\n              else\n                {\n                  // Clearing elements or exceeding capacity, allocate afresh\n                  // and paste pieces.\n                  const Sparse<T, Alloc> tmp = *this;\n                  *this = Sparse<T, Alloc> (nr, 1, new_nz);\n\n                  // Head ...\n                  std::copy_n (tmp.data (), li, data ());\n                  std::copy_n (tmp.ridx (), li, ridx ());\n\n                  // new stuff ...\n                  std::copy_n (rhs.data (), rnz, data () + li);\n                  mx_inline_add (rnz, ridx () + li, rhs.ridx (), lb);\n\n                  // ...tail\n                  std::copy (tmp.data () + ui, tmp.data () + nz,\n                             data () + li + rnz);\n                  std::copy (tmp.ridx () + ui, tmp.ridx () + nz,\n                             ridx () + li + rnz);\n                }\n\n              cidx (1) = new_nz;\n            }\n          else if (idx.is_range () && idx.increment () == -1)\n            {\n              // It's s(u:-1:l) = r.  Reverse the assignment.\n              assign (idx.sorted (), rhs.index (octave::idx_vector (rhl - 1, -1, -1)));\n            }\n          else if (idx.is_permutation (n))\n            {\n              *this = rhs.index (idx.inverse_permutation (n));\n            }\n          else if (rhs.nnz () == 0)\n            {\n              // Elements are being zeroed.\n              octave_idx_type *ri = ridx ();\n              for (octave_idx_type i = 0; i < rhl; i++)\n                {\n                  octave_idx_type iidx = idx(i);\n                  octave_idx_type li = lblookup (ri, nz, iidx);\n                  if (li != nz && ri[li] == iidx)\n                    xdata (li) = T ();\n                }\n\n              maybe_compress (true);\n            }\n          else\n            {\n              const Sparse<T, Alloc> tmp = *this;\n              octave_idx_type new_nz = nz + rhl;\n              // Disassembly our matrix...\n              Array<octave_idx_type> new_ri (dim_vector (new_nz, 1));\n              Array<T> new_data (dim_vector (new_nz, 1));\n              std::copy_n (tmp.ridx (), nz, new_ri.rwdata ());\n              std::copy_n (tmp.data (), nz, new_data.rwdata ());\n              // ... insert new data (densified) ...\n              idx.copy_data (new_ri.rwdata () + nz);\n              new_data.assign (octave::idx_vector (nz, new_nz), rhs.array_value ());\n              // ... reassembly.\n              *this = Sparse<T, Alloc> (new_data, new_ri, 0, nr, nc, false);\n            }\n        }\n      else\n        {\n          dim_vector save_dims = m_dimensions;\n          *this = index (octave::idx_vector::colon);\n          assign (idx, rhs.index (octave::idx_vector::colon));\n          *this = reshape (save_dims);\n        }\n    }\n  else if (rhl == 1)\n    {\n      rhl = idx.length (n);\n      if (rhs.nnz () != 0)\n        assign (idx, Sparse<T, Alloc> (rhl, 1, rhs.data (0)));\n      else\n        assign (idx, Sparse<T, Alloc> (rhl, 1));\n    }\n  else\n    octave::err_nonconformant (\"=\", dim_vector(idx.length (n), 1), rhs.dims());\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::assign (const octave::idx_vector& idx, const T& rhs)\n{\n  // FIXME: Converting the RHS and forwarding to the sparse matrix\n  // assignment function is simpler, but it might be good to have a\n  // specialization...\n\n  assign (idx, Sparse<T, Alloc> (1, 1, rhs));\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::assign (const octave::idx_vector& idx_i,\n                          const octave::idx_vector& idx_j,\n                          const Sparse<T, Alloc>& rhs)\n{\n  Sparse<T, Alloc> retval;\n\n  liboctave_panic_unless (ndims () == 2);\n\n  octave_idx_type nr = dim1 ();\n  octave_idx_type nc = dim2 ();\n  octave_idx_type nz = nnz ();\n\n  octave_idx_type n = rhs.rows ();\n  octave_idx_type m = rhs.columns ();\n\n  // FIXME: this should probably be written more like the\n  // Array<T>::assign function...\n\n  bool orig_zero_by_zero = (nr == 0 && nc == 0);\n\n  if (orig_zero_by_zero || (idx_i.length (nr) == n && idx_j.length (nc) == m))\n    {\n      octave_idx_type nrx;\n      octave_idx_type ncx;\n\n      if (orig_zero_by_zero)\n        {\n          if (idx_i.is_colon ())\n            {\n              nrx = n;\n\n              if (idx_j.is_colon ())\n                ncx = m;\n              else\n                ncx = idx_j.extent (nc);\n            }\n          else if (idx_j.is_colon ())\n            {\n              nrx = idx_i.extent (nr);\n              ncx = m;\n            }\n          else\n            {\n              nrx = idx_i.extent (nr);\n              ncx = idx_j.extent (nc);\n            }\n        }\n      else\n        {\n          nrx = idx_i.extent (nr);\n          ncx = idx_j.extent (nc);\n        }\n\n      // Try to resize first if necessary.\n      if (nrx != nr || ncx != nc)\n        {\n          resize (nrx, ncx);\n          nr = rows ();\n          nc = cols ();\n          // nz is preserved.\n        }\n\n      if (n == 0 || m == 0)\n        return;\n\n      if (idx_i.is_colon ())\n        {\n          octave_idx_type lb, ub;\n          // Great, we're just manipulating columns.  This is going to be quite\n          // efficient, because the columns can stay compressed as they are.\n          if (idx_j.is_colon ())\n            *this = rhs; // Shallow copy.\n          else if (idx_j.is_cont_range (nc, lb, ub))\n            {\n              // Special-case a contiguous range.\n              octave_idx_type li = cidx (lb);\n              octave_idx_type ui = cidx (ub);\n              octave_idx_type rnz = rhs.nnz ();\n              octave_idx_type new_nz = nz - (ui - li) + rnz;\n\n              if (new_nz >= nz && new_nz <= nzmax ())\n                {\n                  // Adding/overwriting elements, enough capacity allocated.\n\n                  if (new_nz > nz)\n                    {\n                      // Make room first.\n                      std::copy_backward (data () + ui, data () + nz,\n                                          data () + new_nz);\n                      std::copy_backward (ridx () + ui, ridx () + nz,\n                                          ridx () + new_nz);\n                      mx_inline_add2 (nc - ub, cidx () + ub + 1, new_nz - nz);\n                    }\n\n                  // Copy data and indices from rhs.\n                  std::copy_n (rhs.data (), rnz, data () + li);\n                  std::copy_n (rhs.ridx (), rnz, ridx () + li);\n                  mx_inline_add (ub - lb, cidx () + lb + 1, rhs.cidx () + 1,\n                                 li);\n\n                  liboctave_panic_unless (nnz () == new_nz);\n                }\n              else\n                {\n                  // Clearing elements or exceeding capacity, allocate afresh\n                  // and paste pieces.\n                  const Sparse<T, Alloc> tmp = *this;\n                  *this = Sparse<T, Alloc> (nr, nc, new_nz);\n\n                  // Head...\n                  std::copy_n (tmp.data (), li, data ());\n                  std::copy_n (tmp.ridx (), li, ridx ());\n                  std::copy_n (tmp.cidx () + 1, lb, cidx () + 1);\n\n                  // new stuff...\n                  std::copy_n (rhs.data (), rnz, data () + li);\n                  std::copy_n (rhs.ridx (), rnz, ridx () + li);\n                  mx_inline_add (ub - lb, cidx () + lb + 1, rhs.cidx () + 1,\n                                 li);\n\n                  // ...tail.\n                  std::copy (tmp.data () + ui, tmp.data () + nz,\n                             data () + li + rnz);\n                  std::copy (tmp.ridx () + ui, tmp.ridx () + nz,\n                             ridx () + li + rnz);\n                  mx_inline_add (nc - ub, cidx () + ub + 1,\n                                 tmp.cidx () + ub + 1, new_nz - nz);\n\n                  liboctave_panic_unless (nnz () == new_nz);\n                }\n            }\n          else if (idx_j.is_range () && idx_j.increment () == -1)\n            {\n              // It's s(:,u:-1:l) = r.  Reverse the assignment.\n              assign (idx_i, idx_j.sorted (),\n                      rhs.index (idx_i, octave::idx_vector (m - 1, -1, -1)));\n            }\n          else if (idx_j.is_permutation (nc))\n            {\n              *this = rhs.index (idx_i, idx_j.inverse_permutation (nc));\n            }\n          else\n            {\n              const Sparse<T, Alloc> tmp = *this;\n              *this = Sparse<T, Alloc> (nr, nc);\n              OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, jsav, nc, -1);\n\n              // Assemble column lengths.\n              for (octave_idx_type i = 0; i < nc; i++)\n                xcidx (i+1) = tmp.cidx (i+1) - tmp.cidx (i);\n\n              for (octave_idx_type i = 0; i < m; i++)\n                {\n                  octave_idx_type j =idx_j(i);\n                  jsav[j] = i;\n                  xcidx (j+1) = rhs.cidx (i+1) - rhs.cidx (i);\n                }\n\n              // Make cumulative.\n              for (octave_idx_type i = 0; i < nc; i++)\n                xcidx (i+1) += xcidx (i);\n\n              change_capacity (nnz ());\n\n              // Merge columns.\n              for (octave_idx_type i = 0; i < nc; i++)\n                {\n                  octave_idx_type l = xcidx (i);\n                  octave_idx_type u = xcidx (i+1);\n                  octave_idx_type j = jsav[i];\n                  if (j >= 0)\n                    {\n                      // from rhs\n                      octave_idx_type k = rhs.cidx (j);\n                      std::copy_n (rhs.data () + k, u - l, xdata () + l);\n                      std::copy_n (rhs.ridx () + k, u - l, xridx () + l);\n                    }\n                  else\n                    {\n                      // original\n                      octave_idx_type k = tmp.cidx (i);\n                      std::copy_n (tmp.data () + k, u - l, xdata () + l);\n                      std::copy_n (tmp.ridx () + k, u - l, xridx () + l);\n                    }\n                }\n\n            }\n        }\n      else if (nc == 1 && idx_j.is_colon_equiv (nc) && idx_i.isvector ())\n        {\n          // It's just vector indexing.  The 1-D assign is specialized for that.\n          assign (idx_i, rhs);\n        }\n      else if (idx_j.is_colon ())\n        {\n          if (idx_i.is_permutation (nr))\n            {\n              *this = rhs.index (idx_i.inverse_permutation (nr), idx_j);\n            }\n          else\n            {\n              // FIXME: optimize more special cases?\n              // In general this requires unpacking the columns, which is slow,\n              // especially for many small columns.  OTOH, transpose is an\n              // efficient O(nr+nc+nnz) operation.\n              *this = transpose ();\n              assign (octave::idx_vector::colon, idx_i, rhs.transpose ());\n              *this = transpose ();\n            }\n        }\n      else\n        {\n          // Split it into 2 assignments and one indexing.\n          Sparse<T, Alloc> tmp = index (octave::idx_vector::colon, idx_j);\n          tmp.assign (idx_i, octave::idx_vector::colon, rhs);\n          assign (octave::idx_vector::colon, idx_j, tmp);\n        }\n    }\n  else if (m == 1 && n == 1)\n    {\n      n = idx_i.length (nr);\n      m = idx_j.length (nc);\n      if (rhs.nnz () != 0)\n        assign (idx_i, idx_j, Sparse<T, Alloc> (n, m, rhs.data (0)));\n      else\n        assign (idx_i, idx_j, Sparse<T, Alloc> (n, m));\n    }\n  else if (idx_i.length (nr) == m && idx_j.length (nc) == n\n           && (n == 1 || m == 1))\n    {\n      assign (idx_i, idx_j, rhs.transpose ());\n    }\n  else\n    octave::err_nonconformant  (\"=\", idx_i.length (nr), idx_j.length (nc), n, m);\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::assign (const octave::idx_vector& idx_i,\n                          const octave::idx_vector& idx_j,\n                          const T& rhs)\n{\n  // FIXME: Converting the RHS and forwarding to the sparse matrix\n  // assignment function is simpler, but it might be good to have a\n  // specialization...\n\n  assign (idx_i, idx_j, Sparse<T, Alloc> (1, 1, rhs));\n}\n\n// Can't use versions of these in Array.cc due to duplication of the\n// instantiations for Array<double and Sparse<double>, etc.\ntemplate <typename T>\nOCTAVE_API\nbool\nsparse_ascending_compare (typename ref_param<T>::type a,\n                          typename ref_param<T>::type b)\n{\n  return (a < b);\n}\n\ntemplate <typename T>\nOCTAVE_API\nbool\nsparse_descending_compare (typename ref_param<T>::type a,\n                           typename ref_param<T>::type b)\n{\n  return (a > b);\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>\nSparse<T, Alloc>::sort (octave_idx_type dim, sortmode mode) const\n{\n  Sparse<T, Alloc> m = *this;\n\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  if (m.numel () < 1 || dim > 1)\n    return m;\n\n  bool sort_by_column = (dim > 0);\n  if (sort_by_column)\n    {\n      m = m.transpose ();\n      std::swap (nr, nc);\n    }\n\n  octave_sort<T> lsort;\n\n  if (mode == ASCENDING)\n    lsort.set_compare (sparse_ascending_compare<T>);\n  else if (mode == DESCENDING)\n    lsort.set_compare (sparse_descending_compare<T>);\n  else\n    (*current_liboctave_error_handler)\n      (\"Sparse<T, Alloc>::sort: invalid MODE\");\n\n  T *v = m.data ();\n  octave_idx_type *mcidx = m.cidx ();\n  octave_idx_type *mridx = m.ridx ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      octave_idx_type ns = mcidx[j + 1] - mcidx[j];\n      lsort.sort (v, ns);\n\n      octave_idx_type i;\n      if (mode == ASCENDING)\n        {\n          for (i = 0; i < ns; i++)\n            if (sparse_ascending_compare<T> (static_cast<T> (0), v[i]))\n              break;\n        }\n      else\n        {\n          for (i = 0; i < ns; i++)\n            if (sparse_descending_compare<T> (static_cast<T> (0), v[i]))\n              break;\n        }\n      for (octave_idx_type k = 0; k < i; k++)\n        mridx[k] = k;\n      for (octave_idx_type k = i; k < ns; k++)\n        mridx[k] = k - ns + nr;\n\n      v += ns;\n      mridx += ns;\n    }\n\n  if (sort_by_column)\n    m = m.transpose ();\n\n  return m;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>\nSparse<T, Alloc>::sort (Array<octave_idx_type>& sidx,\n                        octave_idx_type dim, sortmode mode) const\n{\n  Sparse<T, Alloc> m = *this;\n\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  if (m.numel () < 1 || dim > 1)\n    {\n      sidx = Array<octave_idx_type> (dim_vector (nr, nc), 1);\n      return m;\n    }\n\n  bool sort_by_column = (dim > 0);\n  if (sort_by_column)\n    {\n      m = m.transpose ();\n      std::swap (nr, nc);\n    }\n\n  octave_sort<T> indexed_sort;\n\n  if (mode == ASCENDING)\n    indexed_sort.set_compare (sparse_ascending_compare<T>);\n  else if (mode == DESCENDING)\n    indexed_sort.set_compare (sparse_descending_compare<T>);\n  else\n    (*current_liboctave_error_handler)\n      (\"Sparse<T, Alloc>::sort: invalid MODE\");\n\n  T *v = m.data ();\n  octave_idx_type *mcidx = m.cidx ();\n  octave_idx_type *mridx = m.ridx ();\n\n  sidx = Array<octave_idx_type> (dim_vector (nr, nc));\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, vi, nr);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      octave_idx_type ns = mcidx[j + 1] - mcidx[j];\n      octave_idx_type offset = j * nr;\n\n      if (ns == 0)\n        {\n          for (octave_idx_type k = 0; k < nr; k++)\n            sidx(offset + k) = k;\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < ns; i++)\n            vi[i] = mridx[i];\n\n          indexed_sort.sort (v, vi, ns);\n\n          octave_idx_type i;\n          if (mode == ASCENDING)\n            {\n              for (i = 0; i < ns; i++)\n                if (sparse_ascending_compare<T> (static_cast<T> (0), v[i]))\n                  break;\n            }\n          else\n            {\n              for (i = 0; i < ns; i++)\n                if (sparse_descending_compare<T> (static_cast<T> (0), v[i]))\n                  break;\n            }\n\n          octave_idx_type ii = 0;\n          octave_idx_type jj = i;\n          for (octave_idx_type k = 0; k < nr; k++)\n            {\n              if (ii < ns && mridx[ii] == k)\n                ii++;\n              else\n                sidx(offset + jj++) = k;\n            }\n\n          for (octave_idx_type k = 0; k < i; k++)\n            {\n              sidx(k + offset) = vi[k];\n              mridx[k] = k;\n            }\n\n          for (octave_idx_type k = i; k < ns; k++)\n            {\n              sidx(k - ns + nr + offset) = vi[k];\n              mridx[k] = k - ns + nr;\n            }\n\n          v += ns;\n          mridx += ns;\n        }\n    }\n\n  if (sort_by_column)\n    {\n      m = m.transpose ();\n      sidx = sidx.transpose ();\n    }\n\n  return m;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>\nSparse<T, Alloc>::diag (octave_idx_type k) const\n{\n  octave_idx_type nnr = rows ();\n  octave_idx_type nnc = cols ();\n  Sparse<T, Alloc> d;\n\n  if (nnr == 0 || nnc == 0)\n    ; // do nothing\n  else if (nnr != 1 && nnc != 1)\n    {\n      if (k > 0)\n        nnc -= k;\n      else if (k < 0)\n        nnr += k;\n\n      if (nnr > 0 && nnc > 0)\n        {\n          octave_idx_type ndiag = std::min (nnr, nnc);\n\n          // Count the number of nonzero elements\n          octave_idx_type nel = 0;\n          if (k > 0)\n            {\n              for (octave_idx_type i = 0; i < ndiag; i++)\n                if (elem (i, i+k) != 0.)\n                  nel++;\n            }\n          else if (k < 0)\n            {\n              for (octave_idx_type i = 0; i < ndiag; i++)\n                if (elem (i-k, i) != 0.)\n                  nel++;\n            }\n          else\n            {\n              for (octave_idx_type i = 0; i < ndiag; i++)\n                if (elem (i, i) != 0.)\n                  nel++;\n            }\n\n          d = Sparse<T, Alloc> (ndiag, 1, nel);\n          d.xcidx (0) = 0;\n          d.xcidx (1) = nel;\n\n          octave_idx_type ii = 0;\n          if (k > 0)\n            {\n              for (octave_idx_type i = 0; i < ndiag; i++)\n                {\n                  T tmp = elem (i, i+k);\n                  if (tmp != 0.)\n                    {\n                      d.xdata (ii) = tmp;\n                      d.xridx (ii++) = i;\n                    }\n                }\n            }\n          else if (k < 0)\n            {\n              for (octave_idx_type i = 0; i < ndiag; i++)\n                {\n                  T tmp = elem (i-k, i);\n                  if (tmp != 0.)\n                    {\n                      d.xdata (ii) = tmp;\n                      d.xridx (ii++) = i;\n                    }\n                }\n            }\n          else\n            {\n              for (octave_idx_type i = 0; i < ndiag; i++)\n                {\n                  T tmp = elem (i, i);\n                  if (tmp != 0.)\n                    {\n                      d.xdata (ii) = tmp;\n                      d.xridx (ii++) = i;\n                    }\n                }\n            }\n        }\n      else\n        {\n          // Matlab returns [] 0x1 for out-of-range diagonal\n\n          octave_idx_type nr = 0;\n          octave_idx_type nc = 1;\n          octave_idx_type nz = 0;\n\n          d = Sparse<T, Alloc> (nr, nc, nz);\n        }\n    }\n  else  // one of dimensions == 1 (vector)\n    {\n      octave_idx_type roff = 0;\n      octave_idx_type coff = 0;\n      if (k > 0)\n        {\n          roff = 0;\n          coff = k;\n        }\n      else if (k < 0)\n        {\n          roff = -k;\n          coff = 0;\n        }\n\n      if (nnr == 1)\n        {\n          octave_idx_type n = nnc + std::abs (k);\n          octave_idx_type nz = nnz ();\n\n          d = Sparse<T, Alloc> (n, n, nz);\n\n          if (nnz () > 0)\n            {\n              for (octave_idx_type i = 0; i < coff+1; i++)\n                d.xcidx (i) = 0;\n\n              for (octave_idx_type j = 0; j < nnc; j++)\n                {\n                  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                    {\n                      d.xdata (i) = data (i);\n                      d.xridx (i) = j + roff;\n                    }\n                  d.xcidx (j + coff + 1) = cidx (j+1);\n                }\n\n              for (octave_idx_type i = nnc + coff + 1; i < n + 1; i++)\n                d.xcidx (i) = nz;\n            }\n        }\n      else\n        {\n          octave_idx_type n = nnr + std::abs (k);\n          octave_idx_type nz = nnz ();\n\n          d = Sparse<T, Alloc> (n, n, nz);\n\n          if (nnz () > 0)\n            {\n              octave_idx_type ii = 0;\n              octave_idx_type ir = ridx (0);\n\n              for (octave_idx_type i = 0; i < coff+1; i++)\n                d.xcidx (i) = 0;\n\n              for (octave_idx_type i = 0; i < nnr; i++)\n                {\n                  if (ir == i)\n                    {\n                      d.xdata (ii) = data (ii);\n                      d.xridx (ii++) = ir + roff;\n\n                      if (ii != nz)\n                        ir = ridx (ii);\n                    }\n                  d.xcidx (i + coff + 1) = ii;\n                }\n\n              for (octave_idx_type i = nnr + coff + 1; i < n+1; i++)\n                d.xcidx (i) = nz;\n            }\n        }\n    }\n\n  return d;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nSparse<T, Alloc>\nSparse<T, Alloc>::cat (int dim, octave_idx_type n,\n                       const Sparse<T, Alloc> *sparse_list)\n{\n  // Default concatenation.\n  bool (dim_vector::*concat_rule) (const dim_vector&, int) = &dim_vector::concat;\n\n  if (dim == -1 || dim == -2)\n    {\n      concat_rule = &dim_vector::hvcat;\n      dim = -dim - 1;\n    }\n  else if (dim < 0)\n    (*current_liboctave_error_handler) (\"cat: invalid dimension\");\n\n  dim_vector dv;\n  octave_idx_type total_nz = 0;\n  if (dim != 0 && dim != 1)\n    (*current_liboctave_error_handler)\n      (\"cat: invalid dimension for sparse concatenation\");\n\n  if (n == 1)\n    return sparse_list[0];\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      if (! (dv.*concat_rule) (sparse_list[i].dims (), dim))\n        (*current_liboctave_error_handler) (\"cat: dimension mismatch\");\n\n      total_nz += sparse_list[i].nnz ();\n    }\n\n  Sparse<T, Alloc> retval (dv, total_nz);\n\n  if (retval.isempty ())\n    return retval;\n\n  switch (dim)\n    {\n    case 0:\n      {\n        // sparse vertcat.  This is not efficiently handled by assignment,\n        // so we'll do it directly.\n        octave_idx_type l = 0;\n        for (octave_idx_type j = 0; j < dv(1); j++)\n          {\n            octave_quit ();\n\n            octave_idx_type rcum = 0;\n            for (octave_idx_type i = 0; i < n; i++)\n              {\n                const Sparse<T, Alloc>& spi = sparse_list[i];\n                // Skipping empty matrices.  See the comment in Array.cc.\n                if (spi.isempty ())\n                  continue;\n\n                octave_idx_type kl = spi.cidx (j);\n                octave_idx_type ku = spi.cidx (j+1);\n                for (octave_idx_type k = kl; k < ku; k++, l++)\n                  {\n                    retval.xridx (l) = spi.ridx (k) + rcum;\n                    retval.xdata (l) = spi.data (k);\n                  }\n\n                rcum += spi.rows ();\n              }\n\n            retval.xcidx (j+1) = l;\n          }\n\n        break;\n      }\n    case 1:\n      {\n        octave_idx_type l = 0;\n        for (octave_idx_type i = 0; i < n; i++)\n          {\n            octave_quit ();\n\n            // Skipping empty matrices.  See the comment in Array.cc.\n            if (sparse_list[i].isempty ())\n              continue;\n\n            octave_idx_type u = l + sparse_list[i].columns ();\n            retval.assign (octave::idx_vector::colon, octave::idx_vector (l, u),\n                           sparse_list[i]);\n            l = u;\n          }\n\n        break;\n      }\n    default:\n      (*current_liboctave_error_handler) (\"Sparse<T, Alloc>::cat: invalid dimension = %d - please report this bug\", dim);\n    }\n\n  return retval;\n}\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nArray<T>\nSparse<T, Alloc>::array_value () const\n{\n  Array<T> retval (dims (), T ());\n  if (rows () == 1)\n    {\n      octave_idx_type i = 0;\n      for (octave_idx_type j = 0, nc = cols (); j < nc; j++)\n        {\n          if (cidx (j+1) > i)\n            retval.xelem (j) = data (i++);\n        }\n    }\n  else\n    {\n      for (octave_idx_type j = 0, nc = cols (); j < nc; j++)\n        for (octave_idx_type i = cidx (j), iu = cidx (j+1); i < iu; i++)\n          retval.xelem (ridx (i), j) = data (i);\n    }\n\n  return retval;\n}\n\ntemplate <typename T>\nOCTAVE_API\nstd::istream&\nread_sparse_matrix (std::istream& is, Sparse<T>& a,\n                    T (*read_fcn) (std::istream&))\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n  octave_idx_type nz = a.nzmax ();\n\n  if (nr > 0 && nc > 0)\n    {\n      octave_idx_type itmp;\n      octave_idx_type jtmp;\n      octave_idx_type iold = 0;\n      octave_idx_type jold = 0;\n      octave_idx_type ii = 0;\n      T tmp;\n\n      a.cidx (0) = 0;\n      for (octave_idx_type i = 0; i < nz; i++)\n        {\n          itmp = 0; jtmp = 0;\n          is >> itmp;\n          itmp--;\n\n          is >> jtmp;\n          jtmp--;\n\n          if (is.fail ())\n            {\n              is.clear();\n              std::string err_field;\n              is >> err_field;\n              (*current_liboctave_error_handler)\n                (\"invalid sparse matrix: element %\" OCTAVE_IDX_TYPE_FORMAT \": \"\n                 \"Symbols '%s' is not an integer format\",\n                 i+1, err_field.c_str ());\n            }\n\n          if (itmp < 0 || itmp >= nr)\n            {\n              is.setstate (std::ios::failbit);\n\n              (*current_liboctave_error_handler)\n                (\"invalid sparse matrix: element %\" OCTAVE_IDX_TYPE_FORMAT \": \"\n                 \"row index = %\" OCTAVE_IDX_TYPE_FORMAT \" out of range\",\n                 i+1, itmp + 1);\n            }\n\n          if (jtmp < 0 || jtmp >= nc)\n            {\n              is.setstate (std::ios::failbit);\n\n              (*current_liboctave_error_handler)\n                (\"invalid sparse matrix: element %\" OCTAVE_IDX_TYPE_FORMAT \": \"\n                 \"column index = %\" OCTAVE_IDX_TYPE_FORMAT \" out of range\",\n                 i+1, jtmp + 1);\n            }\n\n          if (jtmp < jold)\n            {\n              is.setstate (std::ios::failbit);\n\n              (*current_liboctave_error_handler)\n                (\"invalid sparse matrix: element %\" OCTAVE_IDX_TYPE_FORMAT \":\"\n                 \"column indices must appear in ascending order \"\n                 \"(%\" OCTAVE_IDX_TYPE_FORMAT \" < %\" OCTAVE_IDX_TYPE_FORMAT \")\",\n                 i+1, jtmp, jold);\n            }\n          else if (jtmp > jold)\n            {\n              for (octave_idx_type j = jold; j < jtmp; j++)\n                a.cidx (j+1) = ii;\n            }\n          else if (itmp < iold)\n            {\n              is.setstate (std::ios::failbit);\n\n              (*current_liboctave_error_handler)\n                (\"invalid sparse matrix: element %\" OCTAVE_IDX_TYPE_FORMAT \": \"\n                 \"row indices must appear in ascending order in each column \"\n                 \"(%\" OCTAVE_IDX_TYPE_FORMAT \" < %\" OCTAVE_IDX_TYPE_FORMAT \")\",\n                 i+1, iold, itmp);\n            }\n\n          iold = itmp;\n          jold = jtmp;\n\n          tmp = read_fcn (is);\n\n          if (! is)\n            return is;  // Problem, return is in error state\n\n          a.data (ii) = tmp;\n          a.ridx (ii++) = itmp;\n        }\n\n      for (octave_idx_type j = jold; j < nc; j++)\n        a.cidx (j+1) = ii;\n    }\n\n  return is;\n}\n\n/*\n * Tests\n *\n\n%!function x = set_slice (x, dim, slice, arg)\n%!  switch (dim)\n%!    case 11\n%!      x(slice) = 2;\n%!    case 21\n%!      x(slice, :) = 2;\n%!    case 22\n%!      x(:, slice) = 2;\n%!    otherwise\n%!      error (\"invalid dim, '%d'\", dim);\n%!  endswitch\n%!endfunction\n\n%!function x = set_slice2 (x, dim, slice)\n%!  switch (dim)\n%!    case 11\n%!      x(slice) = 2 * ones (size (slice));\n%!    case 21\n%!      x(slice, :) = 2 * ones (length (slice), columns (x));\n%!    case 22\n%!      x(:, slice) = 2 * ones (rows (x), length (slice));\n%!    otherwise\n%!      error (\"invalid dim, '%d'\", dim);\n%!  endswitch\n%!endfunction\n\n%!function test_sparse_slice (size, dim, slice)\n%!  x = ones (size);\n%!  s = set_slice (sparse (x), dim, slice);\n%!  f = set_slice (x, dim, slice);\n%!  assert (nnz (s), nnz (f));\n%!  assert (full (s), f);\n%!  s = set_slice2 (sparse (x), dim, slice);\n%!  f = set_slice2 (x, dim, slice);\n%!  assert (nnz (s), nnz (f));\n%!  assert (full (s), f);\n%!endfunction\n\n#### 1-D indexing\n\n## size = [2 0]\n%!test test_sparse_slice ([2 0], 11, []);\n%!assert (set_slice (sparse (ones ([2 0])), 11, 1), sparse ([2 0]'))  # sparse different from full\n%!assert (set_slice (sparse (ones ([2 0])), 11, 2), sparse ([0 2]'))  # sparse different from full\n%!assert (set_slice (sparse (ones ([2 0])), 11, 3), sparse ([0 0; 2 0]'))  # sparse different from full\n%!assert (set_slice (sparse (ones ([2 0])), 11, 4), sparse ([0 0; 0 2]'))  # sparse different from full\n\n## size = [0 2]\n%!test test_sparse_slice ([0 2], 11, []);\n%!assert (set_slice (sparse (ones ([0 2])), 11, 1), sparse ([2 0]))  # sparse different from full\n%!test test_sparse_slice ([0 2], 11, 2);\n%!test test_sparse_slice ([0 2], 11, 3);\n%!test test_sparse_slice ([0 2], 11, 4);\n%!test test_sparse_slice ([0 2], 11, [4, 4]);\n\n## size = [2 1]\n%!test test_sparse_slice ([2 1], 11, []);\n%!test test_sparse_slice ([2 1], 11, 1);\n%!test test_sparse_slice ([2 1], 11, 2);\n%!test test_sparse_slice ([2 1], 11, 3);\n%!test test_sparse_slice ([2 1], 11, 4);\n%!test test_sparse_slice ([2 1], 11, [4, 4]);\n\n## size = [1 2]\n%!test test_sparse_slice ([1 2], 11, []);\n%!test test_sparse_slice ([1 2], 11, 1);\n%!test test_sparse_slice ([1 2], 11, 2);\n%!test test_sparse_slice ([1 2], 11, 3);\n%!test test_sparse_slice ([1 2], 11, 4);\n%!test test_sparse_slice ([1 2], 11, [4, 4]);\n\n## size = [2 2]\n%!test test_sparse_slice ([2 2], 11, []);\n%!test test_sparse_slice ([2 2], 11, 1);\n%!test test_sparse_slice ([2 2], 11, 2);\n%!test test_sparse_slice ([2 2], 11, 3);\n%!test test_sparse_slice ([2 2], 11, 4);\n%!test test_sparse_slice ([2 2], 11, [4, 4]);\n# These 2 errors are the same as in the full case\n%!error id=Octave:invalid-resize set_slice (sparse (ones ([2 2])), 11, 5)\n%!error id=Octave:invalid-resize set_slice (sparse (ones ([2 2])), 11, 6)\n\n#### 2-D indexing\n\n## size = [2 0]\n%!test test_sparse_slice ([2 0], 21, []);\n%!test test_sparse_slice ([2 0], 21, 1);\n%!test test_sparse_slice ([2 0], 21, 2);\n%!test test_sparse_slice ([2 0], 21, [2,2]);\n%!assert (set_slice (sparse (ones ([2 0])), 21, 3), sparse (3,0))\n%!assert (set_slice (sparse (ones ([2 0])), 21, 4), sparse (4,0))\n%!test test_sparse_slice ([2 0], 22, []);\n%!test test_sparse_slice ([2 0], 22, 1);\n%!test test_sparse_slice ([2 0], 22, 2);\n%!test test_sparse_slice ([2 0], 22, [2,2]);\n%!assert (set_slice (sparse (ones ([2 0])), 22, 3), sparse ([0 0 2;0 0 2]))  # sparse different from full\n%!assert (set_slice (sparse (ones ([2 0])), 22, 4), sparse ([0 0 0 2;0 0 0 2]))  # sparse different from full\n\n## size = [0 2]\n%!test test_sparse_slice ([0 2], 21, []);\n%!test test_sparse_slice ([0 2], 21, 1);\n%!test test_sparse_slice ([0 2], 21, 2);\n%!test test_sparse_slice ([0 2], 21, [2,2]);\n%!assert (set_slice (sparse (ones ([0 2])), 21, 3), sparse ([0 0;0 0;2 2]))  # sparse different from full\n%!assert (set_slice (sparse (ones ([0 2])), 21, 4), sparse ([0 0;0 0;0 0;2 2]))  # sparse different from full\n%!test test_sparse_slice ([0 2], 22, []);\n%!test test_sparse_slice ([0 2], 22, 1);\n%!test test_sparse_slice ([0 2], 22, 2);\n%!test test_sparse_slice ([0 2], 22, [2,2]);\n%!assert (set_slice (sparse (ones ([0 2])), 22, 3), sparse (0,3))\n%!assert (set_slice (sparse (ones ([0 2])), 22, 4), sparse (0,4))\n\n## size = [2 1]\n%!test test_sparse_slice ([2 1], 21, []);\n%!test test_sparse_slice ([2 1], 21, 1);\n%!test test_sparse_slice ([2 1], 21, 2);\n%!test test_sparse_slice ([2 1], 21, [2,2]);\n%!test test_sparse_slice ([2 1], 21, 3);\n%!test test_sparse_slice ([2 1], 21, 4);\n%!test test_sparse_slice ([2 1], 22, []);\n%!test test_sparse_slice ([2 1], 22, 1);\n%!test test_sparse_slice ([2 1], 22, 2);\n%!test test_sparse_slice ([2 1], 22, [2,2]);\n%!test test_sparse_slice ([2 1], 22, 3);\n%!test test_sparse_slice ([2 1], 22, 4);\n\n## size = [1 2]\n%!test test_sparse_slice ([1 2], 21, []);\n%!test test_sparse_slice ([1 2], 21, 1);\n%!test test_sparse_slice ([1 2], 21, 2);\n%!test test_sparse_slice ([1 2], 21, [2,2]);\n%!test test_sparse_slice ([1 2], 21, 3);\n%!test test_sparse_slice ([1 2], 21, 4);\n%!test test_sparse_slice ([1 2], 22, []);\n%!test test_sparse_slice ([1 2], 22, 1);\n%!test test_sparse_slice ([1 2], 22, 2);\n%!test test_sparse_slice ([1 2], 22, [2,2]);\n%!test test_sparse_slice ([1 2], 22, 3);\n%!test test_sparse_slice ([1 2], 22, 4);\n\n## size = [2 2]\n%!test test_sparse_slice ([2 2], 21, []);\n%!test test_sparse_slice ([2 2], 21, 1);\n%!test test_sparse_slice ([2 2], 21, 2);\n%!test test_sparse_slice ([2 2], 21, [2,2]);\n%!test test_sparse_slice ([2 2], 21, 3);\n%!test test_sparse_slice ([2 2], 21, 4);\n%!test test_sparse_slice ([2 2], 22, []);\n%!test test_sparse_slice ([2 2], 22, 1);\n%!test test_sparse_slice ([2 2], 22, 2);\n%!test test_sparse_slice ([2 2], 22, [2,2]);\n%!test test_sparse_slice ([2 2], 22, 3);\n%!test test_sparse_slice ([2 2], 22, 4);\n\n%!assert <*35570> (speye (3,1)(3:-1:1), sparse ([0; 0; 1]))\n\n## Test removing columns\n%!test <*36656>\n%! s = sparse (magic (5));\n%! s(:,2:4) = [];\n%! assert (s, sparse (magic (5)(:, [1,5])));\n\n%!test\n%! s = sparse ([], [], [], 1, 1);\n%! s(1,:) = [];\n%! assert (s, sparse ([], [], [], 0, 1));\n\n## Test (bug #37321)\n%!test <*37321> a=sparse (0,0); assert (all (a) == sparse ([1]));\n%!test <*37321> a=sparse (0,1); assert (all (a) == sparse ([1]));\n%!test <*37321> a=sparse (1,0); assert (all (a) == sparse ([1]));\n%!test <*37321> a=sparse (1,0); assert (all (a,2) == sparse ([1]));\n%!test <*37321> a=sparse (1,0); assert (size (all (a,1)), [1 0]);\n%!test <*37321> a=sparse (1,1);\n%! assert (all (a) == sparse ([0]));\n%! assert (size (all (a)), [1 1]);\n%!test <*37321> a=sparse (2,1);\n%! assert (all (a) == sparse ([0]));\n%! assert (size (all (a)), [1 1]);\n%!test <*37321> a=sparse (1,2);\n%! assert (all (a) == sparse ([0]));\n%! assert (size (all (a)), [1 1]);\n%!test <*37321> a=sparse (2,2); assert (isequal (all (a), sparse ([0 0])));\n\n## Test assigning row to a column slice\n%!test <45589>\n%! a = sparse (magic (3));\n%! b = a;\n%! a(1,:) = 1:3;\n%! b(1,:) = (1:3)';\n%! assert (a, b);\n\n*/\n\ntemplate <typename T, typename Alloc>\nOCTAVE_API\nvoid\nSparse<T, Alloc>::print_info (std::ostream& os, const std::string& prefix) const\n{\n  os << prefix << \"m_rep address:  \" << m_rep << \"\\n\"\n     << prefix << \"m_rep->m_nzmax: \" << m_rep->m_nzmax  << \"\\n\"\n     << prefix << \"m_rep->m_nrows: \" << m_rep->m_nrows << \"\\n\"\n     << prefix << \"m_rep->m_ncols: \" << m_rep->m_ncols << \"\\n\"\n     << prefix << \"m_rep->m_data:  \" << m_rep->m_data << \"\\n\"\n     << prefix << \"m_rep->m_ridx:  \" << m_rep->m_ridx << \"\\n\"\n     << prefix << \"m_rep->m_cidx:  \" << m_rep->m_cidx << \"\\n\"\n     << prefix << \"m_rep->m_count: \" << m_rep->m_count << \"\\n\";\n}\n\n#if defined (__clang__)\n#  define INSTANTIATE_SPARSE(T)                                 \\\n  template class OCTAVE_API Sparse<T>;                          \\\n  template OCTAVE_API std::istream&                             \\\n  read_sparse_matrix<T> (std::istream& is, Sparse<T>& a,        \\\n                         T (*read_fcn) (std::istream&));\n#else\n#  define INSTANTIATE_SPARSE(T)                                 \\\n  template class Sparse<T>;                                     \\\n  template OCTAVE_API std::istream&                             \\\n  read_sparse_matrix<T> (std::istream& is, Sparse<T>& a,        \\\n                         T (*read_fcn) (std::istream&));\n#endif\n"
  },
  {
    "path": "liboctave/array/Sparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Sparse_h)\n#define octave_Sparse_h 1\n\n#include \"octave-config.h\"\n\n#include <cstddef>\n\n#include <algorithm>\n#include <iosfwd>\n#include <string>\n\n#include \"Array-fwd.h\"\n#include \"Sparse-fwd.h\"\n#include \"mx-fwd.h\"\n\n// Two-dimensional sparse class.  Handles the reference counting for\n// all the derived classes.\n\ntemplate <typename T, typename Alloc>\nclass OCTAVE_API Sparse\n{\npublic:\n\n  typedef T element_type;\n\nprotected:\n  //--------------------------------------------------------------------\n  // The real representation of all Sparse arrays.\n  //--------------------------------------------------------------------\n\n  class SparseRep : public Alloc\n  {\n  public:\n\n    typedef std::allocator_traits<Alloc> Alloc_traits;\n\n    typedef typename Alloc_traits::template rebind_traits<T> T_Alloc_traits;\n    typedef typename T_Alloc_traits::pointer T_pointer;\n\n    typedef typename Alloc_traits::template rebind_traits<octave_idx_type> idx_type_Alloc_traits;\n    typedef typename idx_type_Alloc_traits::pointer idx_type_pointer;\n\n    T_pointer m_data;\n    idx_type_pointer m_ridx;\n    idx_type_pointer m_cidx;\n    octave_idx_type m_nzmax;\n    octave_idx_type m_nrows;\n    octave_idx_type m_ncols;\n    octave::refcount<octave_idx_type> m_count;\n\n    SparseRep ()\n      : Alloc (), m_data (T_allocate (1)), m_ridx (idx_type_allocate (1)),\n        m_cidx (idx_type_allocate (1)),\n        m_nzmax (1), m_nrows (0), m_ncols (0), m_count (1)\n    { }\n\n    SparseRep (octave_idx_type n)\n      : Alloc (), m_data (T_allocate (1)), m_ridx (idx_type_allocate (1)),\n        m_cidx (idx_type_allocate (n+1)),\n        m_nzmax (1), m_nrows (n), m_ncols (n), m_count (1)\n    { }\n\n    SparseRep (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz = 1)\n      : Alloc (), m_data (T_allocate (nz > 0 ? nz : 1)),\n        m_ridx (idx_type_allocate (nz > 0 ? nz : 1)),\n        m_cidx (idx_type_allocate (nc+1)),\n        m_nzmax (nz > 0 ? nz : 1), m_nrows (nr), m_ncols (nc), m_count (1)\n    { }\n\n    SparseRep (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz,\n               const T *d, const octave_idx_type *r, const octave_idx_type *c)\n      : Alloc (), m_data (T_allocate (nz)),\n        m_ridx (idx_type_allocate (nz)),\n        m_cidx (idx_type_allocate (nc+1)),\n        m_nzmax (nz), m_nrows (nr), m_ncols (nc), m_count (1)\n    {\n      std::copy_n (d, nz, m_data);\n      std::copy_n (r, nz, m_ridx);\n      std::copy_n (c, m_ncols + 1, m_cidx);\n    }\n\n    template <typename U>\n    SparseRep (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz,\n               const U *d, const octave_idx_type *r, const octave_idx_type *c)\n      : Alloc (), m_data (T_allocate (nz)),\n        m_ridx (idx_type_allocate (nz)),\n        m_cidx (idx_type_allocate (nc+1)),\n        m_nzmax (nz), m_nrows (nr), m_ncols (nc), m_count (1)\n    {\n      std::copy_n (d, nz, m_data);\n      std::copy_n (r, nz, m_ridx);\n      std::copy_n (c, nc + 1, m_cidx);\n    }\n\n    template <typename U>\n    SparseRep (const dim_vector& dv, octave_idx_type nz,\n               U *d, octave_idx_type *r, octave_idx_type *c,\n               const Alloc& xallocator = Alloc ())\n      : Alloc (xallocator), m_data (d), m_ridx (r), m_cidx (c),\n        m_nzmax (nz), m_nrows (dv(0)), m_ncols (dv(1)), m_count (1)\n    { }\n\n    SparseRep (const SparseRep& a)\n      : Alloc (), m_data (T_allocate (a.m_nzmax)),\n        m_ridx (idx_type_allocate (a.m_nzmax)),\n        m_cidx (idx_type_allocate (a.m_ncols + 1)),\n        m_nzmax (a.m_nzmax), m_nrows (a.m_nrows), m_ncols (a.m_ncols),\n        m_count (1)\n    {\n      octave_idx_type nz = a.nnz ();\n      std::copy_n (a.m_data, nz, m_data);\n      std::copy_n (a.m_ridx, nz, m_ridx);\n      std::copy_n (a.m_cidx, m_ncols + 1, m_cidx);\n    }\n\n    ~SparseRep ()\n    {\n      T_deallocate (m_data, m_nzmax);\n      idx_type_deallocate (m_ridx, m_nzmax);\n      idx_type_deallocate (m_cidx, m_ncols + 1);\n    }\n\n    octave_idx_type nzmax () const { return m_nzmax; }\n    octave_idx_type nnz () const { return m_cidx[m_ncols]; }\n\n    octave_idx_type rows () const { return m_nrows; }\n    octave_idx_type cols () const { return m_ncols; }\n    octave_idx_type columns () const { return m_ncols; }\n\n    OCTAVE_API T& elem (octave_idx_type r, octave_idx_type c);\n\n    OCTAVE_API T celem (octave_idx_type r, octave_idx_type c) const;\n\n    T& data (octave_idx_type i) { return m_data[i]; }\n\n    T cdata (octave_idx_type i) const { return m_data[i]; }\n\n    octave_idx_type& ridx (octave_idx_type i) { return m_ridx[i]; }\n\n    octave_idx_type cridx (octave_idx_type i) const { return m_ridx[i]; }\n\n    octave_idx_type& cidx (octave_idx_type i) { return m_cidx[i]; }\n\n    octave_idx_type ccidx (octave_idx_type i) const { return m_cidx[i]; }\n\n    OCTAVE_API void maybe_compress (bool remove_zeros);\n\n    OCTAVE_API void change_length (octave_idx_type nz);\n\n    OCTAVE_API bool indices_ok () const;\n\n    OCTAVE_API bool any_element_is_nan () const;\n\n    OCTAVE_API bool any_element_is_inf_or_nan () const;\n\n    // Prefer nzmax.\n    octave_idx_type length () const { return m_nzmax; }\n\n    template <typename U, typename A> friend class Sparse;\n\n    // No assignment!\n\n    SparseRep& operator = (const SparseRep&) = delete;\n\n    T_pointer T_allocate (size_t len)\n    {\n      typename T_Alloc_traits::allocator_type& alloc = *this;\n\n      T_pointer data = T_Alloc_traits::allocate (alloc, len);\n      for (size_t i = 0; i < len; i++)\n        T_Alloc_traits::construct (alloc, data+i);\n\n      return data;\n    }\n\n    void T_deallocate (T_pointer data, size_t len)\n    {\n      typename T_Alloc_traits::allocator_type& alloc = *this;\n\n      for (size_t i = 0; i < len; i++)\n        T_Alloc_traits::destroy (alloc, data+i);\n      T_Alloc_traits::deallocate (alloc, data, len);\n    }\n\n    idx_type_pointer idx_type_allocate (size_t len)\n    {\n      typename idx_type_Alloc_traits::allocator_type alloc = *this;\n\n      idx_type_pointer idx = idx_type_Alloc_traits::allocate (alloc, len);\n      for (size_t i = 0; i < len; i++)\n        idx_type_Alloc_traits::construct (alloc, idx+i);\n\n      return idx;\n    }\n\n    void idx_type_deallocate (idx_type_pointer idx, size_t len)\n    {\n      typename idx_type_Alloc_traits::allocator_type alloc = *this;\n\n      for (size_t i = 0; i < len; i++)\n        idx_type_Alloc_traits::destroy (alloc, idx+i);\n      idx_type_Alloc_traits::deallocate (alloc, idx, len);\n    }\n  };\n\n  //--------------------------------------------------------------------\n\n  void make_unique ()\n  {\n    if (m_rep->m_count > 1)\n      {\n        SparseRep *r = new SparseRep (*m_rep);\n\n        if (--m_rep->m_count == 0)\n          delete m_rep;\n\n        m_rep = r;\n      }\n  }\n\nprotected:\n\n  typename Sparse<T, Alloc>::SparseRep *m_rep;\n\n  dim_vector m_dimensions;\n\nprivate:\n\n  static OCTAVE_API typename Sparse<T, Alloc>::SparseRep * nil_rep ();\n\npublic:\n\n  Sparse ()\n    : m_rep (nil_rep ()), m_dimensions (dim_vector (0, 0))\n  {\n    m_rep->m_count++;\n  }\n\n  explicit Sparse (octave_idx_type n)\n    : m_rep (new typename Sparse<T, Alloc>::SparseRep (n)),\n      m_dimensions (dim_vector (n, n)) { }\n\n  explicit Sparse (octave_idx_type nr, octave_idx_type nc)\n    : m_rep (new typename Sparse<T, Alloc>::SparseRep (nr, nc)),\n      m_dimensions (dim_vector (nr, nc)) { }\n\n  explicit OCTAVE_API Sparse (octave_idx_type nr, octave_idx_type nc, T val);\n\n  Sparse (const dim_vector& dv, octave_idx_type nz)\n    : m_rep (new typename Sparse<T, Alloc>::SparseRep (dv(0), dv(1), nz)),\n      m_dimensions (dv) { }\n\n  Sparse (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz)\n    : m_rep (new typename Sparse<T, Alloc>::SparseRep (nr, nc, nz)),\n      m_dimensions (dim_vector (nr, nc)) { }\n\n  // Construct a Sparse array from pointers to externally allocated\n  // arrays of values and indices.  PTR, RIDX, and CIDX must be\n  // allocated with operator new.  The Sparse object takes ownership of\n  // these arrays and will delete them when the Sparse object is\n  // deleted.  The dimension vector DV must be consistent with the sizes\n  // of the allocated PTR, CIDX, and RIDX arrays.\n\n  Sparse (const dim_vector& dv, octave_idx_type nz,\n          T *ptr, octave_idx_type *ridx, octave_idx_type *cidx,\n          const Alloc& xallocator = Alloc ())\n    : m_rep (new typename Sparse<T, Alloc>::SparseRep (dv, nz, ptr, ridx, cidx, xallocator)),\n      m_dimensions (dv)\n  { }\n\n  // Both SparseMatrix and SparseBoolMatrix need this ctor, and this\n  // is their only common ancestor.\n  explicit OCTAVE_API Sparse (const PermMatrix& a);\n\n  // Type conversion case.  Preserves nzmax.\n  template <typename U>\n  Sparse (const Sparse<U>& a)\n    : m_rep (new typename Sparse<T, Alloc>::SparseRep (a.rows (), a.cols (),\n                                                       a.nzmax (), a.data (),\n                                                       a.ridx (), a.cidx ())),\n      m_dimensions (a.dims ()) { }\n\n  // No type conversion case.\n  Sparse (const Sparse<T, Alloc>& a)\n    : m_rep (a.m_rep), m_dimensions (a.m_dimensions)\n  {\n    m_rep->m_count++;\n  }\n\npublic:\n\n  OCTAVE_API Sparse (const dim_vector& dv);\n\n  OCTAVE_API Sparse (const Sparse<T, Alloc>& a, const dim_vector& dv);\n\n  OCTAVE_API\n  Sparse (const Array<T>& a, const octave::idx_vector& r, const octave::idx_vector& c,\n          octave_idx_type nr = -1, octave_idx_type nc = -1,\n          bool sum_terms = true, octave_idx_type nzm = -1);\n\n  // Sparsify a normal matrix\n  OCTAVE_API Sparse (const Array<T>& a);\n\n  virtual ~Sparse ();\n\n  OCTAVE_API Sparse<T, Alloc>& operator = (const Sparse<T, Alloc>& a);\n\n  //! Amount of storage for nonzero elements.\n  //! This may differ from the actual number of elements, see nnz().\n  octave_idx_type nzmax () const { return m_rep->nzmax (); }\n\n  //! Actual number of nonzero terms.\n  octave_idx_type nnz () const { return m_rep->nnz (); }\n\n  // Querying the number of elements (incl. zeros) may overflow the index type,\n  // so don't do it unless you really need it.\n  octave_idx_type numel () const\n  {\n    return m_dimensions.safe_numel ();\n  }\n\n  octave_idx_type dim1 () const { return m_dimensions(0); }\n  octave_idx_type dim2 () const { return m_dimensions(1); }\n\n  octave_idx_type rows () const { return dim1 (); }\n  octave_idx_type cols () const { return dim2 (); }\n  octave_idx_type columns () const { return dim2 (); }\n\n  octave_idx_type get_row_index (octave_idx_type k) { return ridx (k); }\n  octave_idx_type get_col_index (octave_idx_type k)\n  {\n    octave_idx_type ret = 0;\n    while (cidx (ret+1) < k)\n      ret++;\n    return ret;\n  }\n\n  std::size_t byte_size () const\n  {\n    return (static_cast<std::size_t> (cols () + 1) * sizeof (octave_idx_type)\n            + static_cast<std::size_t> (nzmax ())\n            * (sizeof (T) + sizeof (octave_idx_type)));\n  }\n\n  dim_vector dims () const { return m_dimensions; }\n\n  Sparse<T, Alloc> squeeze () const { return *this; }\n\n  OCTAVE_API octave_idx_type\n  compute_index (const Array<octave_idx_type>& ra_idx) const;\n\n  OCTAVE_NORETURN OCTAVE_API T\n  range_error (const char *fcn, octave_idx_type n) const;\n  OCTAVE_NORETURN OCTAVE_API T&\n  range_error (const char *fcn, octave_idx_type n);\n\n  OCTAVE_NORETURN OCTAVE_API T\n  range_error (const char *fcn, octave_idx_type i, octave_idx_type j) const;\n  OCTAVE_NORETURN OCTAVE_API T&\n  range_error (const char *fcn, octave_idx_type i, octave_idx_type j);\n\n  OCTAVE_NORETURN OCTAVE_API T\n  range_error (const char *fcn, const Array<octave_idx_type>& ra_idx) const;\n  OCTAVE_NORETURN OCTAVE_API T&\n  range_error (const char *fcn, const Array<octave_idx_type>& ra_idx);\n\n  // No checking, even for multiple references, ever.\n\n  T& xelem (octave_idx_type n)\n  {\n    octave_idx_type i = n % rows ();\n    octave_idx_type j = n / rows ();\n    return xelem (i, j);\n  }\n\n  T xelem (octave_idx_type n) const\n  {\n    octave_idx_type i = n % rows ();\n    octave_idx_type j = n / rows ();\n    return xelem (i, j);\n  }\n\n  T& xelem (octave_idx_type i, octave_idx_type j) { return m_rep->elem (i, j); }\n  T xelem (octave_idx_type i, octave_idx_type j) const\n  {\n    return m_rep->celem (i, j);\n  }\n\n  T& xelem (const Array<octave_idx_type>& ra_idx)\n  { return xelem (compute_index (ra_idx)); }\n\n  T xelem (const Array<octave_idx_type>& ra_idx) const\n  { return xelem (compute_index (ra_idx)); }\n\n  // FIXME: would be nice to fix this so that we don't unnecessarily force a\n  // copy, but that is not so easy, and I see no clean way to do it.\n\n  T& checkelem (octave_idx_type n)\n  {\n    if (n < 0 || n >= numel ())\n      range_error (\"T& Sparse<T>::checkelem\", n);\n    else\n      {\n        make_unique ();\n        return xelem (n);\n      }\n  }\n\n  T& checkelem (octave_idx_type i, octave_idx_type j)\n  {\n    if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ())\n      range_error (\"T& Sparse<T>::checkelem\", i, j);\n    else\n      {\n        make_unique ();\n        return xelem (i, j);\n      }\n  }\n\n  T& checkelem (const Array<octave_idx_type>& ra_idx)\n  {\n    octave_idx_type i = compute_index (ra_idx);\n\n    if (i < 0)\n      range_error (\"T& Sparse<T>::checkelem\", ra_idx);\n    else\n      return elem (i);\n  }\n\n  T& elem (octave_idx_type n)\n  {\n    make_unique ();\n    return xelem (n);\n  }\n\n  T& elem (octave_idx_type i, octave_idx_type j)\n  {\n    make_unique ();\n    return xelem (i, j);\n  }\n\n  T& elem (const Array<octave_idx_type>& ra_idx)\n  { return Sparse<T, Alloc>::elem (compute_index (ra_idx)); }\n\n  T& operator () (octave_idx_type n)\n  {\n    return elem (n);\n  }\n\n  T& operator () (octave_idx_type i, octave_idx_type j)\n  {\n    return elem (i, j);\n  }\n\n  T& operator () (const Array<octave_idx_type>& ra_idx)\n  {\n    return elem (ra_idx);\n  }\n\n  T checkelem (octave_idx_type n) const\n  {\n    if (n < 0 || n >= numel ())\n      range_error (\"T Sparse<T>::checkelem\", n);\n    else\n      return xelem (n);\n  }\n\n  T checkelem (octave_idx_type i, octave_idx_type j) const\n  {\n    if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ())\n      range_error (\"T Sparse<T>::checkelem\", i, j);\n    else\n      return xelem (i, j);\n  }\n\n  T checkelem (const Array<octave_idx_type>& ra_idx) const\n  {\n    octave_idx_type i = compute_index (ra_idx);\n\n    if (i < 0)\n      range_error (\"T Sparse<T>::checkelem\", ra_idx);\n    else\n      return Sparse<T, Alloc>::elem (i);\n  }\n\n  T elem (octave_idx_type n) const { return xelem (n); }\n\n  T elem (octave_idx_type i, octave_idx_type j) const { return xelem (i, j); }\n\n  T elem (const Array<octave_idx_type>& ra_idx) const\n  { return Sparse<T, Alloc>::elem (compute_index (ra_idx)); }\n\n  T operator () (octave_idx_type n) const { return elem (n); }\n\n  T operator () (octave_idx_type i, octave_idx_type j) const\n  {\n    return elem (i, j);\n  }\n\n  T operator () (const Array<octave_idx_type>& ra_idx) const\n  {\n    return elem (ra_idx);\n  }\n\n  Sparse<T, Alloc> maybe_compress (bool remove_zeros = false)\n  {\n    if (remove_zeros)\n      make_unique ();  // Need to unshare because elements are removed.\n\n    m_rep->maybe_compress (remove_zeros);\n    return (*this);\n  }\n\n  OCTAVE_API Sparse<T, Alloc> reshape (const dim_vector& new_dims) const;\n\n  OCTAVE_API Sparse<T, Alloc>\n  permute (const Array<octave_idx_type>& vec, bool inv = false) const;\n\n  Sparse<T, Alloc> ipermute (const Array<octave_idx_type>& vec) const\n  {\n    return permute (vec, true);\n  }\n\n  OCTAVE_API void resize1 (octave_idx_type n);\n\n  OCTAVE_API void resize (octave_idx_type r, octave_idx_type c);\n\n  OCTAVE_API void resize (const dim_vector& dv);\n\n  void change_capacity (octave_idx_type nz)\n  {\n    if (nz < nnz ())\n      make_unique ();  // Unshare now because elements will be truncated.\n    m_rep->change_length (nz);\n  }\n\n  OCTAVE_API Sparse<T, Alloc>&\n  insert (const Sparse<T, Alloc>& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API Sparse<T, Alloc>&\n  insert (const Sparse<T, Alloc>& a, const Array<octave_idx_type>& idx);\n\n  bool issquare () const { return (dim1 () == dim2 ()); }\n\n  bool isempty () const { return (rows () < 1 || cols () < 1); }\n\n  OCTAVE_API Sparse<T, Alloc> transpose () const;\n\n  T * data () { make_unique (); return m_rep->m_data; }\n  T& data (octave_idx_type i) { make_unique (); return m_rep->data (i); }\n  T * xdata () { return m_rep->m_data; }\n  T& xdata (octave_idx_type i) { return m_rep->data (i); }\n\n  // Explicit mutable-access name, consistent with Array::rwdata.\n  T * rwdata () { make_unique (); return m_rep->m_data; }\n\n  T data (octave_idx_type i) const { return m_rep->data (i); }\n  const T * data () const { return m_rep->m_data; }\n\n  octave_idx_type * ridx () { make_unique (); return m_rep->m_ridx; }\n  octave_idx_type& ridx (octave_idx_type i)\n  {\n    make_unique (); return m_rep->ridx (i);\n  }\n\n  octave_idx_type * xridx () { return m_rep->m_ridx; }\n  octave_idx_type& xridx (octave_idx_type i) { return m_rep->ridx (i); }\n\n  // Explicit mutable-access name, consistent with Array::rwdata.\n  octave_idx_type * rwridx () { make_unique (); return m_rep->m_ridx; }\n\n  octave_idx_type ridx (octave_idx_type i) const { return m_rep->cridx (i); }\n  const octave_idx_type * ridx () const { return m_rep->m_ridx; }\n\n  octave_idx_type * cidx () { make_unique (); return m_rep->m_cidx; }\n  octave_idx_type& cidx (octave_idx_type i)\n  {\n    make_unique (); return m_rep->cidx (i);\n  }\n\n  octave_idx_type * xcidx () { return m_rep->m_cidx; }\n  octave_idx_type& xcidx (octave_idx_type i) { return m_rep->cidx (i); }\n\n  // Explicit mutable-access name, consistent with Array::rwdata.\n  octave_idx_type * rwcidx () { make_unique (); return m_rep->m_cidx; }\n\n  octave_idx_type cidx (octave_idx_type i) const { return m_rep->ccidx (i); }\n  const octave_idx_type * cidx () const { return m_rep->m_cidx; }\n\n  octave_idx_type ndims () const { return m_dimensions.ndims (); }\n\n  OCTAVE_API void delete_elements (const octave::idx_vector& i);\n\n  OCTAVE_API void delete_elements (int dim, const octave::idx_vector& i);\n\n  OCTAVE_API void delete_elements (const octave::idx_vector& i, const octave::idx_vector& j);\n\n  OCTAVE_API Sparse<T, Alloc>\n  index (const octave::idx_vector& i, bool resize_ok = false) const;\n\n  OCTAVE_API Sparse<T, Alloc>\n  index (const octave::idx_vector& i, const octave::idx_vector& j,\n         bool resize_ok = false) const;\n\n  OCTAVE_API void assign (const octave::idx_vector& i,\n                          const Sparse<T, Alloc>& rhs);\n\n  OCTAVE_API void assign (const octave::idx_vector& i, const T& rhs);\n\n  OCTAVE_API void\n  assign (const octave::idx_vector& i, const octave::idx_vector& j,\n          const Sparse<T, Alloc>& rhs);\n\n  OCTAVE_API void\n  assign (const octave::idx_vector& i, const octave::idx_vector& j,\n          const T& rhs);\n\n  OCTAVE_API void\n  print_info (std::ostream& os, const std::string& prefix) const;\n\n  OCTAVE_API Sparse<T, Alloc>\n  sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;\n  OCTAVE_API Sparse<T, Alloc>\n  sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,\n        sortmode mode = ASCENDING) const;\n\n  OCTAVE_API Sparse<T, Alloc> diag (octave_idx_type k = 0) const;\n\n  // dim = -1 and dim = -2 are special; see Array<T>::cat description.\n  static OCTAVE_API Sparse<T, Alloc>\n  cat (int dim, octave_idx_type n, const Sparse<T, Alloc> *sparse_list);\n\n  OCTAVE_API Array<T> array_value () const;\n\n  // Generic any/all test functionality with arbitrary predicate.\n  template <typename F, bool zero>\n  bool test (F fcn) const\n  {\n    return octave::any_all_test<F, T, zero> (fcn, data (), nnz ());\n  }\n\n  // Simpler calls.\n  template <typename F>\n  bool test_any (F fcn) const\n  { return test<F, false> (fcn); }\n\n  template <typename F>\n  bool test_all (F fcn) const\n  { return test<F, true> (fcn); }\n\n  // Overloads for function references.\n  bool test_any (bool (&fcn) (T)) const\n  { return test<bool (&) (T), false> (fcn); }\n\n  bool test_any (bool (&fcn) (const T&)) const\n  { return test<bool (&) (const T&), false> (fcn); }\n\n  bool test_all (bool (&fcn) (T)) const\n  { return test<bool (&) (T), true> (fcn); }\n\n  bool test_all (bool (&fcn) (const T&)) const\n  { return test<bool (&) (const T&), true> (fcn); }\n\n  template <typename U, typename F>\n  Sparse<U>\n  map (F fcn) const\n  {\n    Sparse<U> result;\n    U f_zero = fcn (0.0);\n\n    if (f_zero != 0.0)\n      {\n        octave_idx_type nr = rows ();\n        octave_idx_type nc = cols ();\n\n        result = Sparse<U> (nr, nc, f_zero);\n\n        for (octave_idx_type j = 0; j < nc; j++)\n          for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n            {\n              octave_quit ();\n              /* Use data instead of elem for better performance. */\n              result.data (ridx (i) + j * nr) = fcn (data (i));\n            }\n\n        result.maybe_compress (true);\n      }\n    else\n      {\n        octave_idx_type nz = nnz ();\n        octave_idx_type nr = rows ();\n        octave_idx_type nc = cols ();\n\n        result = Sparse<U> (nr, nc, nz);\n        octave_idx_type ii = 0;\n        result.cidx (ii) = 0;\n\n        for (octave_idx_type j = 0; j < nc; j++)\n          {\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              {\n                U val = fcn (data (i));\n                if (val != 0.0)\n                  {\n                    result.data (ii) = val;\n                    result.ridx (ii++) = ridx (i);\n                  }\n                octave_quit ();\n              }\n            result.cidx (j+1) = ii;\n          }\n\n        result.maybe_compress (false);\n      }\n\n    return result;\n  }\n\n  // Overloads for function references.\n  template <typename U>\n  Sparse<U>\n  map (U (&fcn) (T)) const\n  { return map<U, U (&) (T)> (fcn); }\n\n  template <typename U>\n  Sparse<U>\n  map (U (&fcn) (const T&)) const\n  { return map<U, U (&) (const T&)> (fcn); }\n\n  bool indices_ok () const { return m_rep->indices_ok (); }\n\n  bool any_element_is_nan () const\n  { return m_rep->any_element_is_nan (); }\n\n  bool any_element_is_inf_or_nan () const\n  { return m_rep->any_element_is_inf_or_nan (); }\n};\n\ntemplate <typename T>\nOCTAVE_API\nstd::istream&\nread_sparse_matrix (std::istream& is, Sparse<T>& a,\n                    T (*read_fcn) (std::istream&));\n\n#endif\n"
  },
  {
    "path": "liboctave/array/boolMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-util.h\"\n#include \"boolMatrix.h\"\n#include \"mx-inlines.cc\"\n#include \"mx-op-defs.h\"\n#include \"oct-error.h\"\n#include \"str-vec.h\"\n\n// boolMatrix class.\n\nbool\nboolMatrix::operator == (const boolMatrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return 0;\n\n  return mx_inline_equal (numel (), data (), a.data ());\n}\n\nbool\nboolMatrix::operator != (const boolMatrix& a) const\n{\n  return !(*this == a);\n}\n\nboolMatrix&\nboolMatrix::insert (const boolMatrix& a, octave_idx_type r, octave_idx_type c)\n{\n  Array<bool>::insert (a, r, c);\n  return *this;\n}\n\n// unary operations\n\nboolMatrix\nboolMatrix::operator ! () const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  boolMatrix b (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      b.elem (i, j) = ! elem (i, j);\n\n  return b;\n}\n\n// other operations\n\nboolMatrix\nboolMatrix::diag (octave_idx_type k) const\n{\n  return Array<bool>::diag (k);\n}\n\nMM_BOOL_OPS (boolMatrix, boolMatrix)\nMS_BOOL_OPS (boolMatrix, bool)\nSM_BOOL_OPS (bool, boolMatrix)\nMM_CMP_OPS (boolMatrix, boolMatrix)\n"
  },
  {
    "path": "liboctave/array/boolMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_boolMatrix_h)\n#define octave_boolMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-oct.h\"\n#include \"boolNDArray.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n\nclass OCTAVE_API boolMatrix : public boolNDArray\n{\npublic:\n\n  boolMatrix () = default;\n\n  boolMatrix (const boolMatrix& a) = default;\n\n  boolMatrix& operator = (const boolMatrix& a) = default;\n\n  ~boolMatrix () = default;\n\n  boolMatrix (octave_idx_type r, octave_idx_type c)\n    : boolNDArray (dim_vector (r, c)) { }\n\n  boolMatrix (octave_idx_type r, octave_idx_type c, bool val)\n    : boolNDArray (dim_vector (r, c), val) { }\n\n  boolMatrix (const dim_vector& dv) : boolNDArray (dv.redim (2)) { }\n\n  boolMatrix (const dim_vector& dv, bool val)\n    : boolNDArray (dv.redim (2), val) { }\n\n  boolMatrix (const Array<bool>& a) : boolNDArray (a.as_matrix ()) { }\n\n  OCTAVE_API bool operator == (const boolMatrix& a) const;\n  OCTAVE_API bool operator != (const boolMatrix& a) const;\n\n  boolMatrix transpose () const { return Array<bool>::transpose (); }\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API boolMatrix&\n  insert (const boolMatrix& a, octave_idx_type r, octave_idx_type c);\n\n  // unary operations\n\n  OCTAVE_API boolMatrix operator ! () const;\n\n  // other operations\n\n  OCTAVE_API boolMatrix diag (octave_idx_type k = 0) const;\n\n  void resize (octave_idx_type nr, octave_idx_type nc, bool rfv = false)\n  {\n    Array<bool>::resize (dim_vector (nr, nc), rfv);\n  }\n};\n\nMM_BOOL_OP_DECLS (boolMatrix, boolMatrix, OCTAVE_API)\nMS_BOOL_OP_DECLS (boolMatrix, bool, OCTAVE_API)\nSM_BOOL_OP_DECLS (bool, boolMatrix, OCTAVE_API)\nMM_CMP_OP_DECLS (boolMatrix, boolMatrix, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/boolNDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-util.h\"\n#include \"boolNDArray.h\"\n#include \"CNDArray.h\"\n#include \"mx-base.h\"\n#include \"lo-ieee.h\"\n#include \"mx-op-defs.h\"\n\n#include \"bsxfun-defs.cc\"\n\n// unary operations\n\nboolNDArray\nboolNDArray::operator ! () const\n{\n  return do_mx_unary_op<bool, bool> (*this, mx_inline_not);\n}\n\nboolNDArray&\nboolNDArray::invert ()\n{\n  if (is_shared ())\n    *this = ! *this;\n  else\n    do_mx_inplace_op<bool> (*this, mx_inline_not2);\n\n  return *this;\n}\n\n// FIXME: this is not quite the right thing.\n\nboolNDArray\nboolNDArray::all (int dim) const\n{\n  return do_mx_red_op<bool, bool> (*this, dim, mx_inline_all);\n}\n\nboolNDArray\nboolNDArray::any (int dim) const\n{\n  return do_mx_red_op<bool, bool> (*this, dim, mx_inline_any);\n}\n\nboolNDArray\nboolNDArray::concat (const boolNDArray& rb,\n                     const Array<octave_idx_type>& ra_idx)\n{\n  if (rb.numel () > 0)\n    insert (rb, ra_idx);\n  return *this;\n}\n\nboolNDArray&\nboolNDArray::insert (const boolNDArray& a, octave_idx_type r, octave_idx_type c)\n{\n  Array<bool>::insert (a, r, c);\n  return *this;\n}\n\nboolNDArray&\nboolNDArray::insert (const boolNDArray& a, const Array<octave_idx_type>& ra_idx)\n{\n  Array<bool>::insert (a, ra_idx);\n  return *this;\n}\n\nvoid\nboolNDArray::increment_index (Array<octave_idx_type>& ra_idx,\n                              const dim_vector& dimensions,\n                              int start_dimension)\n{\n  ::increment_index (ra_idx, dimensions, start_dimension);\n}\n\noctave_idx_type\nboolNDArray::compute_index (Array<octave_idx_type>& ra_idx,\n                            const dim_vector& dimensions)\n{\n  return ::compute_index (ra_idx, dimensions);\n}\n\nboolNDArray\nboolNDArray::diag (octave_idx_type k) const\n{\n  return Array<bool>::diag (k);\n}\n\nboolNDArray\nboolNDArray::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return Array<bool>::diag (m, n);\n}\n\nNDND_BOOL_OPS (boolNDArray, boolNDArray)\nNDND_CMP_OPS (boolNDArray, boolNDArray)\n\nNDS_BOOL_OPS (boolNDArray, bool)\nNDS_CMP_OPS (boolNDArray, bool)\n\nSND_BOOL_OPS (bool, boolNDArray)\nSND_CMP_OPS (bool, boolNDArray)\n\nboolNDArray&\nmx_el_and_assign (boolNDArray& a, const boolNDArray& b)\n{\n  if (a.is_shared ())\n    a = mx_el_and (a, b);\n  else\n    do_mm_inplace_op<bool, bool> (a, b, mx_inline_and2, mx_inline_and2,\n                                  \"operator &=\");\n\n  return a;\n}\n\nboolNDArray&\nmx_el_or_assign (boolNDArray& a, const boolNDArray& b)\n{\n  if (a.is_shared ())\n    a = mx_el_or (a, b);\n  else\n    do_mm_inplace_op<bool, bool> (a, b, mx_inline_or2, mx_inline_or2,\n                                  \"operator |=\");\n\n  return a;\n}\n\nBSXFUN_OP_DEF_MXLOOP (and, boolNDArray, mx_inline_and)\nBSXFUN_OP_DEF_MXLOOP (or, boolNDArray, mx_inline_or)\n"
  },
  {
    "path": "liboctave/array/boolNDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_boolNDArray_h)\n#define octave_boolNDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-oct.h\"\n#include \"bsxfun-decl.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n\nclass OCTAVE_API boolNDArray : public Array<bool>\n{\npublic:\n\n  typedef boolMatrix matrix_type;\n\n  boolNDArray () : Array<bool> () { }\n\n  boolNDArray (const dim_vector& dv) : Array<bool> (dv) { }\n\n  boolNDArray (const dim_vector& dv, const bool& val)\n    : Array<bool> (dv, val) { }\n\n  boolNDArray (const boolNDArray& a) : Array<bool> (a) { }\n\n  boolNDArray (const Array<bool>& a) : Array<bool> (a) { }\n\n  boolNDArray& operator = (const boolNDArray& a)\n  {\n    Array<bool>::operator = (a);\n    return *this;\n  }\n\n  ~boolNDArray () = default;\n\n  // unary operations\n\n  OCTAVE_API boolNDArray operator ! () const;\n\n  OCTAVE_API boolNDArray& invert ();\n\n  bool any_element_is_nan () const { return false; }\n\n  // FIXME: this is not quite the right thing.\n\n  OCTAVE_API boolNDArray all (int dim = -1) const;\n  OCTAVE_API boolNDArray any (int dim = -1) const;\n\n  OCTAVE_API boolNDArray\n  concat (const boolNDArray& rb, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API boolNDArray&\n  insert (const boolNDArray& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API boolNDArray&\n  insert (const boolNDArray& a, const Array<octave_idx_type>& ra_idx);\n\n  boolNDArray squeeze () const { return Array<bool>::squeeze (); }\n\n  static OCTAVE_API void\n  increment_index (Array<octave_idx_type>& ra_idx,\n                   const dim_vector& dimensions, int start_dimension = 0);\n\n  static OCTAVE_API octave_idx_type\n  compute_index (Array<octave_idx_type>& ra_idx,\n                 const dim_vector& dimensions);\n\n  // i/o\n\n  // friend std::ostream& operator << (std::ostream& os, const NDArray& a);\n  // friend std::istream& operator >> (std::istream& is, NDArray& a);\n\n  //  bool all_elements_are_real () const;\n  //  bool all_integers (double& max_val, double& min_val) const;\n\n  OCTAVE_API boolNDArray diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API boolNDArray diag (octave_idx_type m, octave_idx_type n) const;\n};\n\nNDND_BOOL_OP_DECLS (boolNDArray, boolNDArray, OCTAVE_API)\nNDND_CMP_OP_DECLS (boolNDArray, boolNDArray, OCTAVE_API)\n\nNDS_BOOL_OP_DECLS (boolNDArray, bool, OCTAVE_API)\nNDS_CMP_OP_DECLS (boolNDArray, bool, OCTAVE_API)\n\nSND_BOOL_OP_DECLS (bool, boolNDArray, OCTAVE_API)\nSND_CMP_OP_DECLS (bool, boolNDArray, OCTAVE_API)\n\nextern OCTAVE_API boolNDArray&\nmx_el_and_assign (boolNDArray& m, const boolNDArray& a);\nextern OCTAVE_API boolNDArray&\nmx_el_or_assign (boolNDArray& m, const boolNDArray& a);\n\nBSXFUN_OP_DECL (and, boolNDArray, OCTAVE_API)\nBSXFUN_OP_DECL (or, boolNDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/boolSparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"quit.h\"\n\n#include \"boolSparse.h\"\n#include \"dSparse.h\"\n#include \"oct-locbuf.h\"\n\n#include \"Sparse-op-defs.h\"\n\n// SparseBoolMatrix class.\n\nbool\nSparseBoolMatrix::operator == (const SparseBoolMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz = nnz ();\n  octave_idx_type nr_a = a.rows ();\n  octave_idx_type nc_a = a.cols ();\n  octave_idx_type nz_a = a.nnz ();\n\n  if (nr != nr_a || nc != nc_a || nz != nz_a)\n    return false;\n\n  for (octave_idx_type i = 0; i < nc + 1; i++)\n    if (cidx (i) != a.cidx (i))\n      return false;\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    if (data (i) != a.data (i) || ridx (i) != a.ridx (i))\n      return false;\n\n  return true;\n}\n\nbool\nSparseBoolMatrix::operator != (const SparseBoolMatrix& a) const\n{\n  return !(*this == a);\n}\n\nSparseBoolMatrix&\nSparseBoolMatrix::insert (const SparseBoolMatrix& a,\n                          octave_idx_type r, octave_idx_type c)\n{\n  Sparse<bool>::insert (a, r, c);\n  return *this;\n}\n\nSparseBoolMatrix&\nSparseBoolMatrix::insert (const SparseBoolMatrix& a,\n                          const Array<octave_idx_type>& indx)\n{\n  Sparse<bool>::insert (a, indx);\n  return *this;\n}\n\nSparseBoolMatrix\nSparseBoolMatrix::concat (const SparseBoolMatrix& rb,\n                          const Array<octave_idx_type>& ra_idx)\n{\n  // Don't use numel to avoid all possibility of an overflow\n  if (rb.rows () > 0 && rb.cols () > 0)\n    insert (rb, ra_idx(0), ra_idx(1));\n  return *this;\n}\n\n// unary operations\n\nSparseBoolMatrix\nSparseBoolMatrix::operator ! () const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz1 = nnz ();\n  octave_idx_type nz2 = nr*nc - nz1;\n\n  SparseBoolMatrix r (nr, nc, nz2);\n\n  octave_idx_type ii = 0;\n  octave_idx_type jj = 0;\n  r.cidx (0) = 0;\n  for (octave_idx_type i = 0; i < nc; i++)\n    {\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          if (jj < cidx (i+1) && ridx (jj) == j)\n            jj++;\n          else\n            {\n              r.data (ii) = true;\n              r.ridx (ii++) = j;\n            }\n        }\n      r.cidx (i+1) = ii;\n    }\n\n  return r;\n}\n\n// other operations\n\n// FIXME: Do these really belong here?  Maybe they should be in a base class?\n\nSparseBoolMatrix\nSparseBoolMatrix::all (int dim) const\n{\n  SPARSE_ALL_OP (dim);\n}\n\nSparseBoolMatrix\nSparseBoolMatrix::any (int dim) const\n{\n  Sparse<bool> retval;\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz = nnz ();\n  if (dim == -1)\n    dim = (nr == 1 && nc != 1) ? 1 : 0;\n\n  if (dim == 0)\n    {\n      // Result is a row vector.\n      retval = Sparse<bool> (1, nc);\n      retval.xcidx (0) = 0;\n      for (octave_idx_type i = 0; i < nc; i++)\n        retval.xcidx (i+1) = retval.xcidx (i) + (cidx (i+1) > cidx (i));\n      octave_idx_type new_nz = retval.xcidx (nc);\n      retval.change_capacity (new_nz);\n      std::fill_n (retval.ridx (), new_nz, static_cast<octave_idx_type> (0));\n      std::fill_n (retval.data (), new_nz, true);\n    }\n  else if (dim == 1)\n    {\n      // Result is a column vector.\n      if (nz > nr/4)\n        {\n          // We can use O(nr) memory.\n          Array<bool> tmp (dim_vector (nr, 1), false);\n          for (octave_idx_type i = 0; i < nz; i++)\n            tmp.xelem (ridx (i)) = true;\n          retval = tmp;\n        }\n      else\n        {\n          Array<octave_idx_type> tmp (dim_vector (nz, 1));\n          std::copy_n (ridx (), nz, tmp.rwdata ());\n          retval = Sparse<bool> (Array<bool> (dim_vector (1, 1), true),\n                                 octave::idx_vector (tmp),\n                                 octave::idx_vector (0), nr, 1, false);\n        }\n    }\n\n  return retval;\n}\n\nSparseMatrix\nSparseBoolMatrix::sum (int dim) const\n{\n  Sparse<double> retval;\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz = nnz ();\n  if (dim == -1)\n    dim = (nr == 1 && nc != 1) ? 1 : 0;\n\n  if (dim == 0)\n    {\n      // Result is a row vector.\n      retval = Sparse<double> (1, nc);\n      for (octave_idx_type i = 0; i < nc; i++)\n        retval.xcidx (i+1) = retval.xcidx (i) + (cidx (i+1) > cidx (i));\n      octave_idx_type new_nz = retval.xcidx (nc);\n      retval.change_capacity (new_nz);\n      std::fill_n (retval.ridx (), new_nz, static_cast<octave_idx_type> (0));\n      for (octave_idx_type i = 0, k = 0; i < nc; i++)\n        {\n          octave_idx_type c = cidx (i+1) - cidx (i);\n          if (c > 0)\n            retval.xdata (k++) = c;\n        }\n    }\n  else if (dim == 1)\n    {\n      // Result is a column vector.\n      if (nz > nr)\n        {\n          // We can use O(nr) memory.\n          Array<double> tmp (dim_vector (nr, 1), 0);\n          for (octave_idx_type i = 0; i < nz; i++)\n            tmp.xelem (ridx (i)) += 1.0;\n          retval = tmp;\n        }\n      else\n        {\n          Array<octave_idx_type> tmp (dim_vector (nz, 1));\n          std::copy_n (ridx (), nz, tmp.rwdata ());\n          retval = Sparse<double> (Array<double> (dim_vector (1, 1), 1.0),\n                                   octave::idx_vector (tmp),\n                                   octave::idx_vector (0), nr, 1);\n        }\n    }\n\n  return retval;\n}\n\nSparseBoolMatrix\nSparseBoolMatrix::diag (octave_idx_type k) const\n{\n  return Sparse<bool>::diag (k);\n}\n\nboolMatrix\nSparseBoolMatrix::matrix_value () const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  boolMatrix retval (nr, nc, false);\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n      retval.elem (ridx (i), j) = data (i);\n\n  return retval;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const SparseBoolMatrix& a)\n{\n  octave_idx_type nc = a.cols ();\n\n  // add one to the printed indices to go from\n  //  zero-based to one-based arrays\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      octave_quit ();\n      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n        os << a.ridx (i) + 1 << ' '  << j + 1 << ' ' << a.data (i) << \"\\n\";\n    }\n\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, SparseBoolMatrix& a)\n{\n  typedef SparseBoolMatrix::element_type elt_type;\n\n  return read_sparse_matrix<elt_type> (is, a, octave::read_value<bool>);\n}\n\nSparseBoolMatrix\nSparseBoolMatrix::squeeze () const\n{\n  return Sparse<bool>::squeeze ();\n}\n\nSparseBoolMatrix\nSparseBoolMatrix::index (const octave::idx_vector& i, bool resize_ok) const\n{\n  return Sparse<bool>::index (i, resize_ok);\n}\n\nSparseBoolMatrix\nSparseBoolMatrix::index (const octave::idx_vector& i, const octave::idx_vector& j,\n                         bool resize_ok) const\n{\n  return Sparse<bool>::index (i, j, resize_ok);\n}\n\nSparseBoolMatrix\nSparseBoolMatrix::reshape (const dim_vector& new_dims) const\n{\n  return Sparse<bool>::reshape (new_dims);\n}\n\nSparseBoolMatrix\nSparseBoolMatrix::permute (const Array<octave_idx_type>& vec, bool inv) const\n{\n  return Sparse<bool>::permute (vec, inv);\n}\n\nSparseBoolMatrix\nSparseBoolMatrix::ipermute (const Array<octave_idx_type>& vec) const\n{\n  return Sparse<bool>::ipermute (vec);\n}\n\nSPARSE_SMS_EQNE_OPS (SparseBoolMatrix, bool)\nSPARSE_SMS_BOOL_OPS (SparseBoolMatrix, bool)\n\nSPARSE_SSM_EQNE_OPS (bool, SparseBoolMatrix)\nSPARSE_SSM_BOOL_OPS (bool, SparseBoolMatrix)\n\nSPARSE_SMSM_EQNE_OPS (SparseBoolMatrix, SparseBoolMatrix)\nSPARSE_SMSM_BOOL_OPS (SparseBoolMatrix, SparseBoolMatrix)\n"
  },
  {
    "path": "liboctave/array/boolSparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_boolSparse_h)\n#define octave_boolSparse_h 1\n\n#include \"octave-config.h\"\n\n#include \"PermMatrix.h\"\n#include \"Sparse-op-decls.h\"\n#include \"Sparse.h\"\n#include \"boolMatrix.h\"\n#include \"boolNDArray.h\"\n#include \"mx-fwd.h\"\n\nclass OCTAVE_API SparseBoolMatrix : public Sparse<bool>\n{\npublic:\n\n  // Corresponding dense matrix type for this sparse matrix type.\n  typedef boolMatrix dense_matrix_type;\n\n  SparseBoolMatrix () : Sparse<bool> () { }\n\n  SparseBoolMatrix (octave_idx_type r, octave_idx_type c)\n    : Sparse<bool> (r, c) { }\n\n  explicit SparseBoolMatrix (octave_idx_type r, octave_idx_type c, bool val)\n    : Sparse<bool> (r, c, val) { }\n\n  SparseBoolMatrix (const dim_vector& dv, octave_idx_type nz = 0)\n    : Sparse<bool> (dv, nz) { }\n\n  SparseBoolMatrix (const Sparse<bool>& a) : Sparse<bool> (a) { }\n\n  SparseBoolMatrix (const SparseBoolMatrix& a) : Sparse<bool> (a) { }\n\n  SparseBoolMatrix (const SparseBoolMatrix& a, const dim_vector& dv)\n    : Sparse<bool> (a, dv) { }\n\n  explicit SparseBoolMatrix (const boolMatrix& a) : Sparse<bool> (a) { }\n\n  explicit SparseBoolMatrix (const boolNDArray& a) : Sparse<bool> (a) { }\n\n  explicit SparseBoolMatrix (const PermMatrix& a) : Sparse<bool> (a) { }\n\n  SparseBoolMatrix (const Array<bool>& a, const octave::idx_vector& r,\n                    const octave::idx_vector& c, octave_idx_type nr = -1,\n                    octave_idx_type nc = -1, bool sum_terms = true,\n                    octave_idx_type nzm = -1)\n    : Sparse<bool> (a, r, c, nr, nc, sum_terms, nzm) { }\n\n  SparseBoolMatrix (octave_idx_type r, octave_idx_type c,\n                    octave_idx_type num_nz) : Sparse<bool> (r, c, num_nz) { }\n\n  SparseBoolMatrix& operator = (const SparseBoolMatrix& a)\n  {\n    Sparse<bool>::operator = (a);\n    return *this;\n  }\n\n  ~SparseBoolMatrix () = default;\n\n  OCTAVE_API bool operator == (const SparseBoolMatrix& a) const;\n  OCTAVE_API bool operator != (const SparseBoolMatrix& a) const;\n\n  SparseBoolMatrix transpose () const\n  { return Sparse<bool>::transpose (); }\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API SparseBoolMatrix&\n  insert (const SparseBoolMatrix& a, octave_idx_type r, octave_idx_type c);\n\n  OCTAVE_API SparseBoolMatrix&\n  insert (const SparseBoolMatrix& a, const Array<octave_idx_type>& indx);\n\n  OCTAVE_API SparseBoolMatrix\n  concat (const SparseBoolMatrix& rb, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API SparseBoolMatrix diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API boolMatrix matrix_value () const;\n\n  OCTAVE_API SparseBoolMatrix squeeze () const;\n\n  OCTAVE_API SparseBoolMatrix\n  index (const octave::idx_vector& i, bool resize_ok) const;\n\n  OCTAVE_API SparseBoolMatrix\n  index (const octave::idx_vector& i, const octave::idx_vector& j,\n         bool resize_ok) const;\n\n  OCTAVE_API SparseBoolMatrix reshape (const dim_vector& new_dims) const;\n\n  OCTAVE_API SparseBoolMatrix\n  permute (const Array<octave_idx_type>& vec, bool inv = false) const;\n\n  OCTAVE_API SparseBoolMatrix\n  ipermute (const Array<octave_idx_type>& vec) const;\n\n  // unary operations\n\n  OCTAVE_API SparseBoolMatrix operator ! () const;\n\n  // other operations\n\n  OCTAVE_API SparseBoolMatrix all (int dim = -1) const;\n  OCTAVE_API SparseBoolMatrix any (int dim = -1) const;\n  OCTAVE_API SparseMatrix sum (int dim = -1) const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream& operator << (std::ostream& os,\n                                               const SparseBoolMatrix& a);\n  friend OCTAVE_API std::istream& operator >> (std::istream& is,\n                                               SparseBoolMatrix& a);\n};\n\nSPARSE_SMS_EQNE_OP_DECLS (SparseBoolMatrix, bool, OCTAVE_API)\nSPARSE_SMS_BOOL_OP_DECLS (SparseBoolMatrix, bool, OCTAVE_API)\n\nSPARSE_SSM_EQNE_OP_DECLS (bool, SparseBoolMatrix, OCTAVE_API)\nSPARSE_SSM_BOOL_OP_DECLS (bool, SparseBoolMatrix, OCTAVE_API)\n\nSPARSE_SMSM_EQNE_OP_DECLS (SparseBoolMatrix, SparseBoolMatrix, OCTAVE_API)\nSPARSE_SMSM_BOOL_OP_DECLS (SparseBoolMatrix, SparseBoolMatrix, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/chMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstring>\n\n#include <string>\n\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"mx-op-defs.h\"\n#include \"oct-error.h\"\n#include \"str-vec.h\"\n\n// charMatrix class.\n\nbool\ncharMatrix::operator == (const charMatrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return 0;\n\n  return mx_inline_equal (numel (), data (), a.data ());\n}\n\nbool\ncharMatrix::operator != (const charMatrix& a) const\n{\n  return !(*this == a);\n}\n\ncharMatrix&\ncharMatrix::insert (const char *s, octave_idx_type r, octave_idx_type c)\n{\n  if (s)\n    {\n      octave_idx_type s_len = strlen (s);\n\n      if (r < 0 || r >= rows () || c < 0 || c + s_len - 1 > cols ())\n        (*current_liboctave_error_handler) (\"range error for insert\");\n\n      for (octave_idx_type i = 0; i < s_len; i++)\n        elem (r, c+i) = s[i];\n    }\n  return *this;\n}\n\ncharMatrix&\ncharMatrix::insert (const charMatrix& a, octave_idx_type r, octave_idx_type c)\n{\n  Array<char>::insert (a, r, c);\n  return *this;\n}\n\nstd::string\ncharMatrix::row_as_string (octave_idx_type r, bool strip_ws) const\n{\n  std::string retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (r == 0 && (nr == 0 || nc == 0))\n    return retval;\n\n  if (r < 0 || r >= nr)\n    (*current_liboctave_error_handler) (\"range error for row_as_string\");\n\n  retval.resize (nc, '\\0');\n\n  for (octave_idx_type i = 0; i < nc; i++)\n    retval[i] = elem (r, i);\n\n  if (strip_ws)\n    {\n      while (--nc >= 0)\n        {\n          char c = retval[nc];\n          if (c && c != ' ')\n            break;\n        }\n\n      retval.resize (nc+1);\n    }\n\n  return retval;\n}\n\ncharMatrix\ncharMatrix::extract (octave_idx_type r1, octave_idx_type c1,\n                     octave_idx_type r2, octave_idx_type c2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  octave_idx_type new_r = r2 - r1 + 1;\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  charMatrix result (new_r, new_c);\n\n  for (octave_idx_type j = 0; j < new_c; j++)\n    for (octave_idx_type i = 0; i < new_r; i++)\n      result.elem (i, j) = elem (r1+i, c1+j);\n\n  return result;\n}\n\nMS_CMP_OPS (charMatrix, char)\nMS_BOOL_OPS (charMatrix, char)\n\nSM_CMP_OPS (char, charMatrix)\nSM_BOOL_OPS (char, charMatrix)\n\nMM_CMP_OPS (charMatrix, charMatrix)\nMM_BOOL_OPS (charMatrix, charMatrix)\n"
  },
  {
    "path": "liboctave/array/chMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_chMatrix_h)\n#define octave_chMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"Array-oct.h\"\n#include \"chNDArray.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n#include \"str-vec.h\"\n\nclass OCTAVE_API charMatrix : public charNDArray\n{\n  friend class ComplexMatrix;\n\npublic:\n\n  charMatrix () = default;\n\n  charMatrix (const charMatrix& a) = default;\n\n  charMatrix& operator = (const charMatrix& a) = default;\n\n  ~charMatrix () = default;\n\n  charMatrix (octave_idx_type r, octave_idx_type c)\n    : charNDArray (dim_vector (r, c)) { }\n\n  charMatrix (octave_idx_type r, octave_idx_type c, char val)\n    : charNDArray (dim_vector (r, c), val) { }\n\n  charMatrix (const dim_vector& dv) : charNDArray (dv.redim (2)) { }\n\n  charMatrix (const dim_vector& dv, char val)\n    : charNDArray (dv.redim (2), val) { }\n\n  charMatrix (const Array<char>& a) : charNDArray (a.as_matrix ()) { }\n\n  charMatrix (char c) : charNDArray (c) { }\n\n  charMatrix (const char *s) : charNDArray (s) { }\n\n  charMatrix (const std::string& s) : charNDArray (s) { }\n\n  charMatrix (const string_vector& s, char fill_value = '\\0')\n    : charNDArray (s, fill_value) { }\n\n  OCTAVE_API bool operator == (const charMatrix& a) const;\n  OCTAVE_API bool operator != (const charMatrix& a) const;\n\n  charMatrix transpose () const { return Array<char>::transpose (); }\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API charMatrix&\n  insert (const char *s, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API charMatrix&\n  insert (const charMatrix& a, octave_idx_type r, octave_idx_type c);\n\n  OCTAVE_API std::string\n  row_as_string (octave_idx_type, bool strip_ws = false) const;\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API charMatrix\n  extract (octave_idx_type r1, octave_idx_type c1,\n           octave_idx_type r2, octave_idx_type c2) const;\n\n  void resize (octave_idx_type nr, octave_idx_type nc, char rfv = 0)\n  {\n    Array<char>::resize (dim_vector (nr, nc), rfv);\n  }\n\n};\n\nMS_CMP_OP_DECLS (charMatrix, char, OCTAVE_API)\nMS_BOOL_OP_DECLS (charMatrix, char, OCTAVE_API)\n\nSM_CMP_OP_DECLS (char, charMatrix, OCTAVE_API)\nSM_BOOL_OP_DECLS (char, charMatrix, OCTAVE_API)\n\nMM_CMP_OP_DECLS (charMatrix, charMatrix, OCTAVE_API)\nMM_BOOL_OP_DECLS (charMatrix, charMatrix, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/chNDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"Array-util.h\"\n#include \"chNDArray.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"mx-base.h\"\n#include \"mx-op-defs.h\"\n#include \"str-vec.h\"\n\n#include \"bsxfun-defs.cc\"\n\ncharNDArray::charNDArray (char c)\n  : Array<char> ()\n{\n  octave_idx_type n = 1;\n\n  resize1 (n);\n\n  elem (0) = c;\n}\n\ncharNDArray::charNDArray (const char *s)\n  : Array<char> ()\n{\n  octave_idx_type n = (s ? strlen (s) : 0);\n\n  resize1 (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    elem (i) = s[i];\n}\n\ncharNDArray::charNDArray (const std::string& s)\n  : Array<char> ()\n{\n  octave_idx_type n = s.length ();\n\n  resize1 (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    elem (i) = s[i];\n}\n\ncharNDArray::charNDArray (const string_vector& s, char fill_value)\n  : Array<char> (dim_vector (s.numel (), s.max_length ()), fill_value)\n{\n  octave_idx_type nr = rows ();\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    {\n      const std::string si = s(i);\n      octave_idx_type nc = si.length ();\n      for (octave_idx_type j = 0; j < nc; j++)\n        elem (i, j) = si[j];\n    }\n}\n\n// FIXME: this is not quite the right thing.\n\nboolNDArray\ncharNDArray::all (int dim) const\n{\n  return do_mx_red_op<bool, char> (*this, dim, mx_inline_all);\n}\n\nboolNDArray\ncharNDArray::any (int dim) const\n{\n  return do_mx_red_op<bool, char> (*this, dim, mx_inline_any);\n}\n\ncharNDArray\ncharNDArray::concat (const charNDArray& rb,\n                     const Array<octave_idx_type>& ra_idx)\n{\n  if (rb.numel () > 0)\n    insert (rb, ra_idx);\n  return *this;\n}\n\ncharNDArray\ncharNDArray::concat (const NDArray& rb, const Array<octave_idx_type>& ra_idx)\n{\n  charNDArray tmp (rb.dims ());\n  octave_idx_type nel = rb.numel ();\n\n  if (rb.isempty ())\n    return *this;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      double d = rb.elem (i);\n\n      if (octave::math::isnan (d))\n        (*current_liboctave_error_handler)\n          (\"invalid conversion from NaN to character\");\n\n      octave_idx_type ival = octave::math::nint_big (d);\n\n      if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())\n        // FIXME: is there something better to do? Should we warn the user?\n        ival = 0;\n\n      tmp.elem (i) = static_cast<char> (ival);\n    }\n\n  insert (tmp, ra_idx);\n  return *this;\n}\n\ncharNDArray\ncharNDArray::max (int dim) const\n{\n  return do_mx_minmax_op<char> (*this, dim, mx_inline_chmax);\n}\n\ncharNDArray\ncharNDArray::max (Array<octave_idx_type>& idx_arg, int dim) const\n{\n  return do_mx_minmax_op<char> (*this, idx_arg, dim, mx_inline_chmax);\n}\n\ncharNDArray\ncharNDArray::min (int dim) const\n{\n  return do_mx_minmax_op<char> (*this, dim, mx_inline_chmin);\n}\n\ncharNDArray\ncharNDArray::min (Array<octave_idx_type>& idx_arg, int dim) const\n{\n  return do_mx_minmax_op<char> (*this, idx_arg, dim, mx_inline_chmin);\n}\n\ncharNDArray&\ncharNDArray::insert (const charNDArray& a, octave_idx_type r, octave_idx_type c)\n{\n  Array<char>::insert (a, r, c);\n  return *this;\n}\n\ncharNDArray&\ncharNDArray::insert (const charNDArray& a, const Array<octave_idx_type>& ra_idx)\n{\n  Array<char>::insert (a, ra_idx);\n  return *this;\n}\n\nvoid\ncharNDArray::increment_index (Array<octave_idx_type>& ra_idx,\n                              const dim_vector& dimensions,\n                              int start_dimension)\n{\n  ::increment_index (ra_idx, dimensions, start_dimension);\n}\n\noctave_idx_type\ncharNDArray::compute_index (Array<octave_idx_type>& ra_idx,\n                            const dim_vector& dimensions)\n{\n  return ::compute_index (ra_idx, dimensions);\n}\n\ncharNDArray\ncharNDArray::diag (octave_idx_type k) const\n{\n  return Array<char>::diag (k);\n}\n\ncharNDArray\ncharNDArray::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return Array<char>::diag (m, n);\n}\n\ncharNDArray\nmin (char d, const charNDArray& m)\n{\n  return do_sm_binary_op<charNDArray::element_type, char,\n                         charNDArray::element_type> (d, m, mx_inline_xmin);\n}\n\ncharNDArray\nmin (const charNDArray& m, char d)\n{\n  return do_ms_binary_op<charNDArray::element_type, charNDArray::element_type,\n                         char> (m, d, mx_inline_xmin);\n}\n\ncharNDArray\nmin (const charNDArray& a, const charNDArray& b)\n{\n  return do_mm_binary_op<charNDArray::element_type, charNDArray::element_type,\n                         charNDArray::element_type> (a, b, mx_inline_xmin,\n                                                     mx_inline_xmin,\n                                                     mx_inline_xmin, \"min\");\n}\n\ncharNDArray\nmax (char d, const charNDArray& m)\n{\n  return do_sm_binary_op<charNDArray::element_type, char,\n                         charNDArray::element_type> (d, m, mx_inline_xmax);\n}\n\ncharNDArray\nmax (const charNDArray& m, char d)\n{\n  return do_ms_binary_op<charNDArray::element_type, charNDArray::element_type,\n                         char> (m, d, mx_inline_xmax);\n}\n\ncharNDArray\nmax (const charNDArray& a, const charNDArray& b)\n{\n  return do_mm_binary_op<charNDArray::element_type, charNDArray::element_type,\n                         charNDArray::element_type> (a, b, mx_inline_xmax,\n                                                     mx_inline_xmax,\n                                                     mx_inline_xmax, \"max\");\n}\n\nNDS_CMP_OPS (charNDArray, char)\nNDS_BOOL_OPS (charNDArray, char)\n\nSND_CMP_OPS (char, charNDArray)\nSND_BOOL_OPS (char, charNDArray)\n\nNDND_CMP_OPS (charNDArray, charNDArray)\nNDND_BOOL_OPS (charNDArray, charNDArray)\n\nBSXFUN_STDREL_DEFS_MXLOOP (charNDArray)\n"
  },
  {
    "path": "liboctave/array/chNDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_chNDArray_h)\n#define octave_chNDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-oct.h\"\n#include \"bsxfun-decl.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n#include \"str-vec.h\"\n\nclass OCTAVE_API charNDArray : public Array<char>\n{\npublic:\n\n  typedef charMatrix matrix_type;\n\n  charNDArray () : Array<char> () { }\n\n  charNDArray (const dim_vector& dv) : Array<char> (dv) { }\n\n  charNDArray (const dim_vector& dv, char val) : Array<char> (dv, val) { }\n\n  charNDArray (const charNDArray& a) : Array<char> (a) { }\n\n  charNDArray (const Array<char>& a) : Array<char> (a) { }\n\n  OCTAVE_API charNDArray (char c);\n\n  OCTAVE_API charNDArray (const char *s);\n\n  OCTAVE_API charNDArray (const std::string& s);\n\n  OCTAVE_API charNDArray (const string_vector& s, char fill_value = '\\0');\n\n  charNDArray& operator = (const charNDArray& a)\n  {\n    Array<char>::operator = (a);\n    return *this;\n  }\n\n  ~charNDArray () = default;\n\n  bool any_element_is_nan () const { return false; }\n\n  // FIXME: this is not quite the right thing.\n\n  OCTAVE_API boolNDArray all (int dim = -1) const;\n  OCTAVE_API boolNDArray any (int dim = -1) const;\n  OCTAVE_API charNDArray\n  concat (const charNDArray& rb, const Array<octave_idx_type>& ra_idx);\n  OCTAVE_API charNDArray\n  concat (const NDArray& rb, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API charNDArray max (int dim = -1) const;\n  OCTAVE_API charNDArray max (Array<octave_idx_type>& index, int dim = -1) const;\n  OCTAVE_API charNDArray min (int dim = -1) const;\n  OCTAVE_API charNDArray min (Array<octave_idx_type>& index, int dim = -1) const;\n\n  OCTAVE_API charNDArray&\n  insert (const charNDArray& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API charNDArray&\n  insert (const charNDArray& a, const Array<octave_idx_type>& ra_idx);\n\n  charNDArray squeeze () const { return Array<char>::squeeze (); }\n\n  static OCTAVE_API void\n  increment_index (Array<octave_idx_type>& ra_idx,\n                   const dim_vector& dimensions, int start_dimension = 0);\n\n  static OCTAVE_API octave_idx_type\n  compute_index (Array<octave_idx_type>& ra_idx, const dim_vector& dimensions);\n\n  // i/o\n\n  // friend OCTAVE_API std::ostream&\n  // operator << (std::ostream& os, const charNDArray& a);\n  // friend OCTAVE_API std::istream&\n  // operator >> (std::istream& is, charNDArray& a);\n\n  OCTAVE_API charNDArray diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API charNDArray diag (octave_idx_type m, octave_idx_type n) const;\n};\n\nextern OCTAVE_API charNDArray min (char d, const charNDArray& m);\nextern OCTAVE_API charNDArray min (const charNDArray& m, char d);\nextern OCTAVE_API charNDArray min (const charNDArray& a, const charNDArray& b);\nextern OCTAVE_API charNDArray max (char d, const charNDArray& m);\nextern OCTAVE_API charNDArray max (const charNDArray& m, char d);\nextern OCTAVE_API charNDArray max (const charNDArray& a, const charNDArray& b);\n\nNDS_CMP_OP_DECLS (charNDArray, char, OCTAVE_API)\nNDS_BOOL_OP_DECLS (charNDArray, char, OCTAVE_API)\n\nSND_CMP_OP_DECLS (char, charNDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (char, charNDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (charNDArray, charNDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (charNDArray, charNDArray, OCTAVE_API)\n\nBSXFUN_STDREL_DECLS (charNDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/dColVector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"blas-proto.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// Column Vector class.\n\nbool\nColumnVector::operator == (const ColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  if (len != a.numel ())\n    return 0;\n  return mx_inline_equal (len, data (), a.data ());\n}\n\nbool\nColumnVector::operator != (const ColumnVector& a) const\n{\n  return !(*this == a);\n}\n\nColumnVector&\nColumnVector::insert (const ColumnVector& a, octave_idx_type r)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nColumnVector&\nColumnVector::fill (double val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nColumnVector&\nColumnVector::fill (double val, octave_idx_type r1, octave_idx_type r2)\n{\n  octave_idx_type len = numel ();\n\n  if (r1 < 0 || r2 < 0 || r1 >= len || r2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  if (r2 >= r1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = r1; i <= r2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nColumnVector\nColumnVector::stack (const ColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nr_insert = len;\n  ColumnVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nr_insert);\n  return retval;\n}\n\nRowVector\nColumnVector::transpose () const\n{\n  return MArray<double>::transpose ();\n}\n\nColumnVector\nColumnVector::abs () const\n{\n  return do_mx_unary_map<double, double, std::abs> (*this);\n}\n\nColumnVector\nreal (const ComplexColumnVector& a)\n{\n  return do_mx_unary_op<double, Complex> (a, mx_inline_real);\n}\n\nColumnVector\nimag (const ComplexColumnVector& a)\n{\n  return do_mx_unary_op<double, Complex> (a, mx_inline_imag);\n}\n\n// resize is the destructive equivalent for this one\n\nColumnVector\nColumnVector::extract (octave_idx_type r1, octave_idx_type r2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  octave_idx_type new_r = r2 - r1 + 1;\n\n  ColumnVector result (new_r);\n\n  for (octave_idx_type i = 0; i < new_r; i++)\n    result.xelem (i) = elem (r1+i);\n\n  return result;\n}\n\nColumnVector\nColumnVector::extract_n (octave_idx_type r1, octave_idx_type n) const\n{\n  ColumnVector result (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    result.xelem (i) = elem (r1+i);\n\n  return result;\n}\n\n// matrix by column vector -> column vector operations\n\nColumnVector\noperator * (const Matrix& m, const ColumnVector& a)\n{\n  ColumnVector retval;\n\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  retval.clear (nr);\n\n  if (nr != 0)\n    {\n      if (nc == 0)\n        retval.fill (0.0);\n      else\n        {\n          double *y = retval.rwdata ();\n\n          F77_XFCN (dgemv, DGEMV, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                                   nr, nc, 1.0, m.data (), nr,\n                                   a.data (), 1, 0.0, y, 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n    }\n\n  return retval;\n}\n\n// diagonal matrix by column vector -> column vector operations\n\nColumnVector\noperator * (const DiagMatrix& m, const ColumnVector& a)\n{\n  ColumnVector retval;\n\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  if (nr == 0 || nc == 0)\n    retval.resize (nr, 0.0);\n  else\n    {\n      retval.resize (nr);\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        retval.elem (i) = a.elem (i) * m.elem (i, i);\n\n      for (octave_idx_type i = a_len; i < nr; i++)\n        retval.elem (i) = 0.0;\n    }\n\n  return retval;\n}\n\n// other operations\n\ndouble\nColumnVector::min () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0.0;\n\n  double res = elem (0);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (elem (i) < res)\n      res = elem (i);\n\n  return res;\n}\n\ndouble\nColumnVector::max () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0.0;\n\n  double res = elem (0);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (elem (i) > res)\n      res = elem (i);\n\n  return res;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const ColumnVector& a)\n{\n//  int field_width = os.precision () + 7;\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    os << /* setw (field_width) << */ a.elem (i) << \"\\n\";\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, ColumnVector& a)\n{\n  octave_idx_type len = a.numel ();\n\n  if (len > 0)\n    {\n      double tmp;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          is >> tmp;\n          if (is)\n            a.elem (i) = tmp;\n          else\n            break;\n        }\n    }\n  return is;\n}\n"
  },
  {
    "path": "liboctave/array/dColVector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dColVector_h)\n#define octave_dColVector_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API ColumnVector : public MArray<double>\n{\npublic:\n\n  ColumnVector () : MArray<double> (dim_vector (0, 1)) { }\n\n  explicit ColumnVector (octave_idx_type n)\n    : MArray<double> (dim_vector (n, 1)) { }\n\n  explicit ColumnVector (const dim_vector& dv)\n    : MArray<double> (dv.as_column ()) { }\n\n  ColumnVector (octave_idx_type n, double val)\n    : MArray<double> (dim_vector (n, 1), val) { }\n\n  ColumnVector (const ColumnVector& a) : MArray<double> (a) { }\n\n  ColumnVector (const MArray<double>& a) : MArray<double> (a.as_column ()) { }\n  ColumnVector (const Array<double>& a) : MArray<double> (a.as_column ()) { }\n\n  ColumnVector& operator = (const ColumnVector& a)\n  {\n    MArray<double>::operator = (a);\n    return *this;\n  }\n\n  ~ColumnVector () = default;\n\n  OCTAVE_API bool operator == (const ColumnVector& a) const;\n  OCTAVE_API bool operator != (const ColumnVector& a) const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API ColumnVector& insert (const ColumnVector& a, octave_idx_type r);\n\n  OCTAVE_API ColumnVector& fill (double val);\n  OCTAVE_API ColumnVector&\n  fill (double val, octave_idx_type r1, octave_idx_type r2);\n\n  OCTAVE_API ColumnVector stack (const ColumnVector& a) const;\n\n  OCTAVE_API RowVector transpose () const;\n\n  friend OCTAVE_API ColumnVector real (const ComplexColumnVector& a);\n  friend OCTAVE_API ColumnVector imag (const ComplexColumnVector& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API ColumnVector\n  extract (octave_idx_type r1, octave_idx_type r2) const;\n\n  OCTAVE_API ColumnVector\n  extract_n (octave_idx_type r1, octave_idx_type n) const;\n\n  // matrix by column vector -> column vector operations\n\n  friend OCTAVE_API ColumnVector operator * (const Matrix& a,\n                                             const ColumnVector& b);\n\n  // diagonal matrix by column vector -> column vector operations\n\n  friend OCTAVE_API ColumnVector operator * (const DiagMatrix& a,\n                                             const ColumnVector& b);\n\n  // other operations\n\n  OCTAVE_API double min () const;\n  OCTAVE_API double max () const;\n\n  OCTAVE_API ColumnVector abs () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream& operator << (std::ostream& os,\n                                               const ColumnVector& a);\n  friend OCTAVE_API std::istream& operator >> (std::istream& is,\n                                               ColumnVector& a);\n\n  void resize (octave_idx_type n, const double& rfv = 0)\n  {\n    Array<double>::resize (dim_vector (n, 1), rfv);\n  }\n\n  void clear (octave_idx_type n)\n  { Array<double>::clear (n, 1); }\n\n};\n\n// Publish externally used friend functions.\n\nextern OCTAVE_API ColumnVector real (const ComplexColumnVector& a);\nextern OCTAVE_API ColumnVector imag (const ComplexColumnVector& a);\n\nMARRAY_FORWARD_DEFS (MArray, ColumnVector, double)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/dDiagMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// Diagonal Matrix class.\n\nbool\nDiagMatrix::operator == (const DiagMatrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return 0;\n\n  return mx_inline_equal (length (), data (), a.data ());\n}\n\nbool\nDiagMatrix::operator != (const DiagMatrix& a) const\n{\n  return !(*this == a);\n}\n\nDiagMatrix&\nDiagMatrix::fill (double val)\n{\n  for (octave_idx_type i = 0; i < length (); i++)\n    elem (i, i) = val;\n  return *this;\n}\n\nDiagMatrix&\nDiagMatrix::fill (double val, octave_idx_type beg, octave_idx_type end)\n{\n  if (beg < 0 || end >= length () || end < beg)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = beg; i <= end; i++)\n    elem (i, i) = val;\n\n  return *this;\n}\n\nDiagMatrix&\nDiagMatrix::fill (const ColumnVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nDiagMatrix&\nDiagMatrix::fill (const RowVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nDiagMatrix&\nDiagMatrix::fill (const ColumnVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nDiagMatrix&\nDiagMatrix::fill (const RowVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nDiagMatrix\nDiagMatrix::abs () const\n{\n  return DiagMatrix (extract_diag ().abs (), rows (), columns ());\n}\n\nDiagMatrix\nreal (const ComplexDiagMatrix& a)\n{\n  return DiagMatrix (real (a.extract_diag ()), a.rows (), a.cols ());\n}\n\nDiagMatrix\nimag (const ComplexDiagMatrix& a)\n{\n  return DiagMatrix (imag (a.extract_diag ()), a.rows (), a.cols ());\n}\n\nMatrix\nDiagMatrix::extract (octave_idx_type r1, octave_idx_type c1,\n                     octave_idx_type r2, octave_idx_type c2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  octave_idx_type new_r = r2 - r1 + 1;\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  Matrix result (new_r, new_c);\n\n  for (octave_idx_type j = 0; j < new_c; j++)\n    for (octave_idx_type i = 0; i < new_r; i++)\n      result.elem (i, j) = elem (r1+i, c1+j);\n\n  return result;\n}\n\n// extract row or column i.\n\nRowVector\nDiagMatrix::row (octave_idx_type i) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (i < 0 || i >= r)\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n\n  RowVector retval (c, 0.0);\n  if (r <= c || i < c)\n    retval.elem (i) = elem (i, i);\n\n  return retval;\n}\n\nRowVector\nDiagMatrix::row (char *s) const\n{\n  if (! s)\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n\n  char c = s[0];\n  if (c == 'f' || c == 'F')\n    return row (static_cast<octave_idx_type> (0));\n  else if (c == 'l' || c == 'L')\n    return row (rows () - 1);\n  else\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n}\n\nColumnVector\nDiagMatrix::column (octave_idx_type i) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (i < 0 || i >= c)\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n\n  ColumnVector retval (r, 0.0);\n  if (r >= c || i < r)\n    retval.elem (i) = elem (i, i);\n\n  return retval;\n}\n\nColumnVector\nDiagMatrix::column (char *s) const\n{\n  if (! s)\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n\n  char c = s[0];\n  if (c == 'f' || c == 'F')\n    return column (static_cast<octave_idx_type> (0));\n  else if (c == 'l' || c == 'L')\n    return column (cols () - 1);\n  else\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n}\n\nDiagMatrix\nDiagMatrix::inverse () const\n{\n  octave_idx_type info;\n  return inverse (info);\n}\n\nDiagMatrix\nDiagMatrix::inverse (octave_idx_type& info) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (r != c)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  DiagMatrix retval (r, c);\n\n  info = 0;\n  octave_idx_type len = r;        // alias for readability\n  octave_idx_type z_count  = 0;   // zeros\n  octave_idx_type nz_count = 0;   // nonzeros\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      if (xelem (i, i) == 0.0)\n        {\n          z_count++;\n          if (nz_count > 0)\n            break;\n        }\n      else\n        {\n          nz_count++;\n          if (z_count > 0)\n            break;\n          retval.elem (i, i) = 1.0 / xelem (i, i);\n        }\n    }\n  if (nz_count == 0)\n    {\n      (*current_liboctave_error_handler)\n        (\"inverse of the null matrix not defined\");\n    }\n  else if (z_count > 0)\n    {\n      info = -1;\n      element_type *data = retval.rwdata ();\n      std::fill (data, data + len, octave::numeric_limits<double>::Inf ());\n    }\n\n  return retval;\n}\n\nDiagMatrix\nDiagMatrix::pseudo_inverse (double tol) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  octave_idx_type len = length ();\n\n  DiagMatrix retval (c, r);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      double val = std::abs (elem (i, i));\n      if (val < tol || val == 0.0)\n        retval.elem (i, i) = 0.0;\n      else\n        retval.elem (i, i) = 1.0 / elem (i, i);\n    }\n\n  return retval;\n}\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\nDiagMatrix\noperator * (const DiagMatrix& a, const DiagMatrix& b)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  DiagMatrix c (a_nr, b_nc);\n\n  octave_idx_type len = c.length ();\n  octave_idx_type lenm = (len < a_nc ? len : a_nc);\n\n  for (octave_idx_type i = 0; i < lenm; i++)\n    c.dgxelem (i) = a.dgelem (i) * b.dgelem (i);\n  for (octave_idx_type i = lenm; i < len; i++)\n    c.dgxelem (i) = 0.0;\n\n  return c;\n}\n\n// other operations\n\nDET\nDiagMatrix::determinant () const\n{\n  DET det (1.0);\n  if (rows () != cols ())\n    (*current_liboctave_error_handler) (\"determinant requires square matrix\");\n\n  octave_idx_type len = length ();\n  for (octave_idx_type i = 0; i < len; i++)\n    det *= elem (i, i);\n\n  return det;\n}\n\ndouble\nDiagMatrix::rcond () const\n{\n  ColumnVector av = extract_diag (0).map<double> (fabs);\n  double amx = av.max ();\n  double amn = av.min ();\n  return amx == 0 ? 0.0 : amn / amx;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const DiagMatrix& a)\n{\n//  int field_width = os.precision () + 7;\n\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    {\n      for (octave_idx_type j = 0; j < a.cols (); j++)\n        {\n          if (i == j)\n            os << ' ' /* setw (field_width) */ << a.elem (i, i);\n          else\n            os << ' ' /* setw (field_width) */ << 0.0;\n        }\n      os << \"\\n\";\n    }\n  return os;\n}\n"
  },
  {
    "path": "liboctave/array/dDiagMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dDiagMatrix_h)\n#define octave_dDiagMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"DET.h\"\n#include \"MDiagArray2.h\"\n#include \"dColVector.h\"\n#include \"dRowVector.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API DiagMatrix : public MDiagArray2<double>\n{\npublic:\n\n  typedef Matrix full_matrix_type;\n\n  DiagMatrix () = default;\n\n  DiagMatrix (const DiagMatrix& a) = default;\n\n  DiagMatrix& operator = (const DiagMatrix& a) = default;\n\n  ~DiagMatrix () = default;\n\n  DiagMatrix (octave_idx_type r, octave_idx_type c)\n    : MDiagArray2<double> (r, c) { }\n\n  DiagMatrix (octave_idx_type r, octave_idx_type c, double val)\n    : MDiagArray2<double> (r, c, val) { }\n\n  DiagMatrix (const MDiagArray2<double>& a) : MDiagArray2<double> (a) { }\n\n  template <typename U>\n  DiagMatrix (const DiagArray2<U>& a) : MDiagArray2<double> (a) { }\n\n  explicit DiagMatrix (const Array<double>& a) : MDiagArray2<double> (a) { }\n\n  DiagMatrix (const Array<double>& a, octave_idx_type r, octave_idx_type c)\n    : MDiagArray2<double> (a, r, c) { }\n\n  OCTAVE_API bool operator == (const DiagMatrix& a) const;\n  OCTAVE_API bool operator != (const DiagMatrix& a) const;\n\n  OCTAVE_API DiagMatrix& fill (double val);\n  OCTAVE_API DiagMatrix&\n  fill (double val, octave_idx_type beg, octave_idx_type end);\n  OCTAVE_API DiagMatrix& fill (const ColumnVector& a);\n  OCTAVE_API DiagMatrix& fill (const RowVector& a);\n  OCTAVE_API DiagMatrix& fill (const ColumnVector& a, octave_idx_type beg);\n  OCTAVE_API DiagMatrix& fill (const RowVector& a, octave_idx_type beg);\n\n  DiagMatrix transpose () const\n  { return MDiagArray2<double>::transpose (); }\n  DiagMatrix abs () const;\n\n  friend OCTAVE_API DiagMatrix real (const ComplexDiagMatrix& a);\n  friend OCTAVE_API DiagMatrix imag (const ComplexDiagMatrix& a);\n\n  // resize is the destructive analog for this one\n\n  OCTAVE_API Matrix\n  extract (octave_idx_type r1, octave_idx_type c1,\n           octave_idx_type r2, octave_idx_type c2) const;\n\n  // extract row or column i.\n\n  OCTAVE_API RowVector row (octave_idx_type i) const;\n  OCTAVE_API RowVector row (char *s) const;\n\n  OCTAVE_API ColumnVector column (octave_idx_type i) const;\n  OCTAVE_API ColumnVector column (char *s) const;\n\n  OCTAVE_API DiagMatrix inverse () const;\n  OCTAVE_API DiagMatrix inverse (octave_idx_type& info) const;\n  OCTAVE_API DiagMatrix pseudo_inverse (double tol = 0.0) const;\n\n  // other operations\n\n  ColumnVector extract_diag (octave_idx_type k = 0) const\n  { return MDiagArray2<double>::extract_diag (k); }\n\n  OCTAVE_API DET determinant () const;\n  OCTAVE_API double rcond () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const DiagMatrix& a);\n\n};\n\nOCTAVE_API DiagMatrix real (const ComplexDiagMatrix& a);\nOCTAVE_API DiagMatrix imag (const ComplexDiagMatrix& a);\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\nOCTAVE_API DiagMatrix\noperator * (const DiagMatrix& a, const DiagMatrix& b);\n\nMDIAGARRAY2_FORWARD_DEFS (MDiagArray2, DiagMatrix, double)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/dMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <cmath>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n#include \"DET.h\"\n#include \"PermMatrix.h\"\n#include \"blas-proto.h\"\n#include \"boolMatrix.h\"\n#include \"byte-swap.h\"\n#include \"chMatrix.h\"\n#include \"chol.h\"\n#include \"dColVector.h\"\n#include \"dDiagMatrix.h\"\n#include \"dMatrix.h\"\n#include \"dRowVector.h\"\n#include \"lapack-proto.h\"\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"mx-dm-m.h\"\n#include \"mx-inlines.cc\"\n#include \"mx-m-dm.h\"\n#include \"mx-op-defs.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-norm.h\"\n#include \"quit.h\"\n#include \"schur.h\"\n#include \"svd.h\"\n\n// Matrix class.\n\nMatrix::Matrix (const RowVector& rv)\n  : NDArray (rv)\n{ }\n\nMatrix::Matrix (const ColumnVector& cv)\n  : NDArray (cv)\n{ }\n\nMatrix::Matrix (const DiagMatrix& a)\n  : NDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nMatrix::Matrix (const MDiagArray2<double>& a)\n  : NDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nMatrix::Matrix (const DiagArray2<double>& a)\n  : NDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nMatrix::Matrix (const PermMatrix& a)\n  : NDArray (a.dims (), 0.0)\n{\n  const Array<octave_idx_type> ia (a.col_perm_vec ());\n  octave_idx_type len = a.rows ();\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (ia(i), i) = 1.0;\n}\n\n// FIXME: could we use a templated mixed-type copy function here?\n\nMatrix::Matrix (const boolMatrix& a)\n  : NDArray (a)\n{ }\n\nMatrix::Matrix (const charMatrix& a)\n  : NDArray (a.dims ())\n{\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    for (octave_idx_type j = 0; j < a.cols (); j++)\n      elem (i, j) = static_cast<unsigned char> (a.elem (i, j));\n}\n\nbool\nMatrix::operator == (const Matrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return false;\n\n  return mx_inline_equal (numel (), data (), a.data ());\n}\n\nbool\nMatrix::operator != (const Matrix& a) const\n{\n  return !(*this == a);\n}\n\nbool\nMatrix::issymmetric () const\n{\n  if (issquare () && rows () > 0)\n    {\n      for (octave_idx_type i = 0; i < rows (); i++)\n        for (octave_idx_type j = i+1; j < cols (); j++)\n          if (elem (i, j) != elem (j, i))\n            return false;\n\n      return true;\n    }\n\n  return false;\n}\n\nMatrix&\nMatrix::insert (const Matrix& a, octave_idx_type r, octave_idx_type c)\n{\n  Array<double>::insert (a, r, c);\n  return *this;\n}\n\nMatrix&\nMatrix::insert (const RowVector& a, octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r, c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nMatrix&\nMatrix::insert (const ColumnVector& a, octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c) = a.elem (i);\n    }\n\n  return *this;\n}\n\nMatrix&\nMatrix::insert (const DiagMatrix& a, octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);\n\n  octave_idx_type a_len = a.length ();\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c+i) = a.elem (i, i);\n    }\n\n  return *this;\n}\n\nMatrix&\nMatrix::fill (double val)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nMatrix&\nMatrix::fill (double val, octave_idx_type r1, octave_idx_type c1,\n              octave_idx_type r2, octave_idx_type c2)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0\n      || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (r2 >= r1 && c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = c1; j <= c2; j++)\n        for (octave_idx_type i = r1; i <= r2; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nMatrix\nMatrix::append (const Matrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  Matrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nMatrix\nMatrix::append (const RowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != 1)\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  Matrix retval (nr, nc + a.numel ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nMatrix\nMatrix::append (const ColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.numel ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  Matrix retval (nr, nc + 1);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nMatrix\nMatrix::append (const DiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  Matrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nMatrix\nMatrix::stack (const Matrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  Matrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nMatrix\nMatrix::stack (const RowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.numel ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  Matrix retval (nr + 1, nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nMatrix\nMatrix::stack (const ColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != 1)\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  Matrix retval (nr + a.numel (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nMatrix\nMatrix::stack (const DiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  Matrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nMatrix\nreal (const ComplexMatrix& a)\n{\n  return do_mx_unary_op<double, Complex> (a, mx_inline_real);\n}\n\nMatrix\nimag (const ComplexMatrix& a)\n{\n  return do_mx_unary_op<double, Complex> (a, mx_inline_imag);\n}\n\nMatrix\nMatrix::extract (octave_idx_type r1, octave_idx_type c1,\n                 octave_idx_type r2, octave_idx_type c2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  return index (octave::idx_vector (r1, r2+1), octave::idx_vector (c1, c2+1));\n}\n\nMatrix\nMatrix::extract_n (octave_idx_type r1, octave_idx_type c1, octave_idx_type nr,\n                   octave_idx_type nc) const\n{\n  return index (octave::idx_vector (r1, r1 + nr), octave::idx_vector (c1, c1 + nc));\n}\n\n// extract row or column i.\n\nRowVector\nMatrix::row (octave_idx_type i) const\n{\n  return index (octave::idx_vector (i), octave::idx_vector::colon);\n}\n\nColumnVector\nMatrix::column (octave_idx_type i) const\n{\n  return index (octave::idx_vector::colon, octave::idx_vector (i));\n}\n\n// Local function to calculate the 1-norm.\nstatic\ndouble\nnorm1 (const Matrix& a)\n{\n  double anorm = 0.0;\n  RowVector colsum = a.abs ().sum ().row (0);\n\n  for (octave_idx_type i = 0; i < colsum.numel (); i++)\n    {\n      double sum = colsum.xelem (i);\n      if (octave::math::isinf (sum) || octave::math::isnan (sum))\n        {\n          anorm = sum;  // Pass Inf or NaN to output\n          break;\n        }\n      else\n        anorm = std::max (anorm, sum);\n    }\n\n  return anorm;\n}\n\n// Local function to check if matrix is singular based on rcond.\nstatic inline\nbool\nis_singular (const double rcond)\n{\n  return (std::abs (rcond) <= std::numeric_limits<double>::epsilon ());\n}\n\nMatrix\nMatrix::inverse () const\n{\n  octave_idx_type info;\n  double rcon;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, false, false);\n}\n\nMatrix\nMatrix::inverse (octave_idx_type& info) const\n{\n  double rcon;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, false, false);\n}\n\nMatrix\nMatrix::inverse (octave_idx_type& info, double& rcon,\n                 bool force, bool calc_cond) const\n{\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, force, calc_cond);\n}\n\nMatrix\nMatrix::inverse (MatrixType& mattype) const\n{\n  octave_idx_type info;\n  double rcon;\n  return inverse (mattype, info, rcon, false, false);\n}\n\nMatrix\nMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const\n{\n  double rcon;\n  return inverse (mattype, info, rcon, false, false);\n}\n\nMatrix\nMatrix::tinverse (MatrixType& mattype, octave_idx_type& info, double& rcon,\n                  bool force, bool calc_cond) const\n{\n  Matrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc || nr == 0 || nc == 0)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  int typ = mattype.type ();\n  char uplo = (typ == MatrixType::Lower ? 'L' : 'U');\n  char udiag = 'N';\n  retval = *this;\n  double *tmp_data = retval.rwdata ();\n\n  F77_INT tmp_info = 0;\n\n  F77_XFCN (dtrtri, DTRTRI, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                             F77_CONST_CHAR_ARG2 (&udiag, 1),\n                             nr, tmp_data, nr, tmp_info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  info = tmp_info;\n\n  // Throw away extra info LAPACK gives so as to not change output.\n  rcon = 0.0;\n  if (info != 0)\n    info = -1;\n  else if (calc_cond)\n    {\n      F77_INT dtrcon_info = 0;\n      char job = '1';\n\n      OCTAVE_LOCAL_BUFFER (double, work, 3 * nr);\n      OCTAVE_LOCAL_BUFFER (F77_INT, iwork, nr);\n\n      F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                 F77_CONST_CHAR_ARG2 (&udiag, 1),\n                                 nr, tmp_data, nr, rcon,\n                                 work, iwork, dtrcon_info\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (dtrcon_info != 0)\n        info = -1;\n    }\n\n  if (info == -1 && ! force)\n    retval = *this; // Restore matrix contents.\n\n  return retval;\n}\n\nMatrix\nMatrix::finverse (MatrixType& mattype, octave_idx_type& info, double& rcon,\n                  bool force, bool calc_cond) const\n{\n  Matrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc || nr == 0 || nc == 0)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  Array<F77_INT> ipvt (dim_vector (nr, 1));\n  F77_INT *pipvt = ipvt.rwdata ();\n\n  retval = *this;\n  double *tmp_data = retval.rwdata ();\n\n  Array<double> z (dim_vector (1, 1));\n  F77_INT lwork = -1;\n\n  F77_INT tmp_info = 0;\n\n  // Query the optimum work array size.\n  F77_XFCN (dgetri, DGETRI, (nc, tmp_data, nr, pipvt,\n                             z.rwdata (), lwork, tmp_info));\n\n  lwork = static_cast<F77_INT> (z(0));\n  lwork = (lwork < 4 * nc ? 4 * nc : lwork);\n  z.resize (dim_vector (lwork, 1));\n  double *pz = z.rwdata ();\n\n  info = 0;\n  tmp_info = 0;\n\n  // Calculate the norm of the matrix for later use when determining rcon.\n  double anorm;\n  if (calc_cond)\n    anorm = norm1 (retval);\n\n  F77_XFCN (dgetrf, DGETRF, (nc, nc, tmp_data, nr, pipvt, tmp_info));\n\n  info = tmp_info;\n\n  // Throw away extra info LAPACK gives so as to not change output.\n  rcon = 0.0;\n  if (info != 0)\n    info = -1;\n  else if (calc_cond)\n    {\n      if (octave::math::isnan (anorm))\n        rcon = octave::numeric_limits<double>::NaN ();\n      else\n        {\n          F77_INT dgecon_info = 0;\n\n          // Now calculate the condition number for non-singular matrix.\n          char job = '1';\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n          F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     nc, tmp_data, nr, anorm,\n                                     rcon, pz, piz, dgecon_info\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (dgecon_info != 0)\n            info = -1;\n        }\n    }\n\n  if (info == -1 && ! force)\n    retval = *this; // Restore matrix contents.\n  else\n    {\n      F77_INT dgetri_info = 0;\n\n      F77_XFCN (dgetri, DGETRI, (nc, tmp_data, nr, pipvt,\n                                 pz, lwork, dgetri_info));\n\n      if (dgetri_info != 0)\n        info = -1;\n    }\n\n  if (info != 0)\n    mattype.mark_as_rectangular ();\n\n  return retval;\n}\n\nMatrix\nMatrix::inverse (MatrixType& mattype, octave_idx_type& info, double& rcon,\n                 bool force, bool calc_cond) const\n{\n  int typ = mattype.type (false);\n  Matrix ret;\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal)  // a scalar is classified as Diagonal.\n    {\n      ret = 1 / (*this);\n      if (calc_cond)\n        {\n          double scalar = this->elem (0);\n          if (octave::math::isfinite (scalar) && scalar != 0)\n            rcon = 1.0;\n          else if (octave::math::isinf (scalar) || scalar == 0)\n            rcon = 0.0;\n          else\n            rcon = octave::numeric_limits<double>::NaN ();\n        }\n    }\n  else if (typ == MatrixType::Upper || typ == MatrixType::Lower)\n    ret = tinverse (mattype, info, rcon, force, calc_cond);\n  else\n    {\n      if (mattype.ishermitian ())\n        {\n          octave::math::chol<Matrix> chol (*this, info, true, calc_cond);\n          if (info == 0)\n            {\n              if (calc_cond)\n                rcon = chol.rcond ();\n              else\n                rcon = 1.0;\n              ret = chol.inverse ();\n            }\n          else\n            mattype.mark_as_unsymmetric ();\n        }\n\n      if (! mattype.ishermitian ())\n        ret = finverse (mattype, info, rcon, force, calc_cond);\n\n      if ((calc_cond || mattype.ishermitian ()) && rcon == 0.0)\n        ret = Matrix (rows (), columns (),\n                      octave::numeric_limits<double>::Inf ());\n    }\n\n  return ret;\n}\n\nMatrix\nMatrix::pseudo_inverse (double tol) const\n{\n  octave::math::svd<Matrix> result (*this,\n                                    octave::math::svd<Matrix>::Type::economy);\n\n  DiagMatrix S = result.singular_values ();\n  Matrix U = result.left_singular_matrix ();\n  Matrix V = result.right_singular_matrix ();\n\n  ColumnVector sigma = S.extract_diag ();\n\n  octave_idx_type r = sigma.numel () - 1;\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (tol <= 0.0)\n    {\n      tol = std::max (nr, nc) * sigma.elem (0)\n            * std::numeric_limits<double>::epsilon ();\n\n      if (tol == 0)\n        tol = std::numeric_limits<double>::min ();\n    }\n\n  while (r >= 0 && sigma.elem (r) < tol)\n    r--;\n\n  if (r < 0)\n    return Matrix (nc, nr, 0.0);\n  else\n    {\n      Matrix Ur = U.extract (0, 0, nr-1, r);\n      DiagMatrix D = DiagMatrix (sigma.extract (0, r)).inverse ();\n      Matrix Vr = V.extract (0, 0, nc-1, r);\n      return Vr * D * Ur.transpose ();\n    }\n}\n\n#if defined (HAVE_FFTW)\n\nComplexMatrix\nMatrix::fourier () const\n{\n  std::size_t nr = rows ();\n  std::size_t nc = cols ();\n\n  ComplexMatrix retval (nr, nc);\n\n  std::size_t npts, nsamples;\n\n  if (nr == 1 || nc == 1)\n    {\n      npts = (nr > nc ? nr : nc);\n      nsamples = 1;\n    }\n  else\n    {\n      npts = nr;\n      nsamples = nc;\n    }\n\n  const double *in (data ());\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::fft (in, out, npts, nsamples);\n\n  return retval;\n}\n\nComplexMatrix\nMatrix::ifourier () const\n{\n  std::size_t nr = rows ();\n  std::size_t nc = cols ();\n\n  ComplexMatrix retval (nr, nc);\n\n  std::size_t npts, nsamples;\n\n  if (nr == 1 || nc == 1)\n    {\n      npts = (nr > nc ? nr : nc);\n      nsamples = 1;\n    }\n  else\n    {\n      npts = nr;\n      nsamples = nc;\n    }\n\n  ComplexMatrix tmp (*this);\n  const Complex *in (tmp.data ());\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::ifft (in, out, npts, nsamples);\n\n  return retval;\n}\n\nComplexMatrix\nMatrix::fourier2d () const\n{\n  dim_vector dv (rows (), cols ());\n\n  const double *in = data ();\n  ComplexMatrix retval (rows (), cols ());\n  octave::fftw::fftNd (in, retval.rwdata (), 2, dv);\n\n  return retval;\n}\n\nComplexMatrix\nMatrix::ifourier2d () const\n{\n  dim_vector dv (rows (), cols ());\n\n  ComplexMatrix retval (*this);\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::ifftNd (out, out, 2, dv);\n\n  return retval;\n}\n\n#else\n\nComplexMatrix\nMatrix::fourier () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexMatrix ();\n}\n\nComplexMatrix\nMatrix::ifourier () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexMatrix ();\n}\n\nComplexMatrix\nMatrix::fourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexMatrix ();\n}\n\nComplexMatrix\nMatrix::ifourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexMatrix ();\n}\n\n#endif\n\nDET\nMatrix::determinant () const\n{\n  octave_idx_type info;\n  double rcon;\n  return determinant (info, rcon, 0);\n}\n\nDET\nMatrix::determinant (octave_idx_type& info) const\n{\n  double rcon;\n  return determinant (info, rcon, 0);\n}\n\nDET\nMatrix::determinant (octave_idx_type& info, double& rcon, bool calc_cond) const\n{\n  MatrixType mattype (*this);\n  return determinant (mattype, info, rcon, calc_cond);\n}\n\nDET\nMatrix::determinant (MatrixType& mattype,\n                     octave_idx_type& info, double& rcon, bool calc_cond) const\n{\n  DET retval (1.0);\n\n  info = 0;\n  rcon = 0.0;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"matrix must be square\");\n\n  int typ = mattype.type ();\n\n  // Even though the matrix is marked as singular (Rectangular), we may still\n  // get a useful number from the LU factorization, because it always completes.\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n  else if (typ == MatrixType::Rectangular)\n    typ = MatrixType::Full;\n\n  if (typ == MatrixType::Lower || typ == MatrixType::Upper)\n    {\n      for (F77_INT i = 0; i < nc; i++)\n        retval *= elem (i, i);\n    }\n  else if (typ == MatrixType::Hermitian)\n    {\n      Matrix atmp = *this;\n      double *tmp_data = atmp.rwdata ();\n\n      // Calculate the norm of the matrix for later use when determining rcon.\n      double anorm;\n      if (calc_cond)\n        anorm = norm1 (*this);\n\n      F77_INT tmp_info = 0;\n\n      char job = 'L';\n      F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                 tmp_data, nr, tmp_info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      info = tmp_info;\n\n      if (info != 0)\n        {\n          rcon = 0.0;\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n        }\n      else\n        {\n          if (calc_cond)\n            {\n              Array<double> z (dim_vector (3 * nc, 1));\n              double *pz = z.rwdata ();\n              Array<F77_INT> iz (dim_vector (nc, 1));\n              F77_INT *piz = iz.rwdata ();\n\n              F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                         nr, tmp_data, nr, anorm,\n                                         rcon, pz, piz, tmp_info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n\n              if (info != 0)\n                rcon = 0.0;\n            }\n\n          for (F77_INT i = 0; i < nc; i++)\n            retval *= atmp(i, i);\n\n          retval = retval.square ();\n        }\n    }\n  else if (typ != MatrixType::Full)\n    (*current_liboctave_error_handler) (\"det: invalid dense matrix type\");\n\n  if (typ == MatrixType::Full)\n    {\n      Array<F77_INT> ipvt (dim_vector (nr, 1));\n      F77_INT *pipvt = ipvt.rwdata ();\n\n      Matrix atmp = *this;\n      double *tmp_data = atmp.rwdata ();\n\n      info = 0;\n      F77_INT tmp_info = 0;\n\n      // Calculate the norm of the matrix for later use when determining rcon.\n      double anorm;\n      if (calc_cond)\n        anorm = norm1 (*this);\n\n      F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, tmp_info));\n\n      info = tmp_info;\n\n      // Throw away extra info LAPACK gives so as to not change output.\n      rcon = 0.0;\n      if (info != 0)\n        {\n          info = -1;\n          retval = DET ();\n        }\n      else\n        {\n          if (calc_cond)\n            {\n              // Now calc the condition number for non-singular matrix.\n              char job = '1';\n              Array<double> z (dim_vector (4 * nc, 1));\n              double *pz = z.rwdata ();\n              Array<F77_INT> iz (dim_vector (nc, 1));\n              F77_INT *piz = iz.rwdata ();\n\n              F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                         nc, tmp_data, nr, anorm,\n                                         rcon, pz, piz, tmp_info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n            }\n\n          if (info != 0)\n            {\n              info = -1;\n              retval = DET ();\n            }\n          else\n            {\n              for (F77_INT i = 0; i < nc; i++)\n                {\n                  double c = atmp(i, i);\n                  retval *= (ipvt(i) != (i+1)) ? -c : c;\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\ndouble\nMatrix::rcond () const\n{\n  MatrixType mattype (*this);\n  return rcond (mattype);\n}\n\ndouble\nMatrix::rcond (MatrixType& mattype) const\n{\n  double rcon = octave::numeric_limits<double>::NaN ();\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"matrix must be square\");\n\n  if (nr == 0 || nc == 0)\n    rcon = octave::numeric_limits<double>::Inf ();\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ == MatrixType::Unknown)\n        typ = mattype.type (*this);\n\n      // Only calculate the condition number for LU/Cholesky\n      if (typ == MatrixType::Upper)\n        {\n          const double *tmp_data = data ();\n          F77_INT info = 0;\n          char norm = '1';\n          char uplo = 'U';\n          char dia = 'N';\n\n          Array<double> z (dim_vector (3 * nc, 1));\n          double *pz = z.rwdata ();\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n\n          F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, tmp_data, nr, rcon,\n                                     pz, piz, info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (info != 0)\n            rcon = 0.0;\n        }\n      else if (typ == MatrixType::Permuted_Upper)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n      else if (typ == MatrixType::Lower)\n        {\n          const double *tmp_data = data ();\n          F77_INT info = 0;\n          char norm = '1';\n          char uplo = 'L';\n          char dia = 'N';\n\n          Array<double> z (dim_vector (3 * nc, 1));\n          double *pz = z.rwdata ();\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n\n          F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, tmp_data, nr, rcon,\n                                     pz, piz, info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (info != 0)\n            rcon = 0.0;\n        }\n      else if (typ == MatrixType::Permuted_Lower)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n      else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n        {\n          double anorm = -1.0;\n\n          if (typ == MatrixType::Hermitian)\n            {\n              F77_INT info = 0;\n              char job = 'L';\n\n              Matrix atmp = *this;\n              double *tmp_data = atmp.rwdata ();\n\n              anorm = norm1 (atmp);\n\n              F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                         tmp_data, nr, info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              if (info != 0)\n                {\n                  rcon = 0.0;\n                  mattype.mark_as_unsymmetric ();\n                  typ = MatrixType::Full;\n                }\n              else\n                {\n                  Array<double> z (dim_vector (3 * nc, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nc, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, tmp_data, nr, anorm,\n                                             rcon, pz, piz, info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  if (info != 0)\n                    rcon = 0.0;\n                }\n            }\n\n          if (typ == MatrixType::Full)\n            {\n              F77_INT info = 0;\n\n              Matrix atmp = *this;\n              double *tmp_data = atmp.rwdata ();\n\n              Array<F77_INT> ipvt (dim_vector (nr, 1));\n              F77_INT *pipvt = ipvt.rwdata ();\n\n              if (anorm < 0.0)\n                anorm = norm1 (atmp);\n\n              Array<double> z (dim_vector (4 * nc, 1));\n              double *pz = z.rwdata ();\n              Array<F77_INT> iz (dim_vector (nc, 1));\n              F77_INT *piz = iz.rwdata ();\n\n              F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, info));\n\n              if (info != 0)\n                {\n                  rcon = 0.0;\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                {\n                  char job = '1';\n                  F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nc, tmp_data, nr, anorm,\n                                             rcon, pz, piz, info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  if (info != 0)\n                    rcon = 0.0;\n                }\n            }\n        }\n      else\n        rcon = 0.0;\n    }\n\n  return rcon;\n}\n\nMatrix\nMatrix::utsolve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n                 double& rcon, solve_singularity_handler sing_handler,\n                 bool calc_cond, blas_trans_type transt) const\n{\n  Matrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    retval = Matrix (nc, b_nc, 0.0);\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      rcon = 1.0;\n      info = 0;\n\n      if (typ == MatrixType::Permuted_Upper)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n\n      const double *tmp_data = data ();\n\n      retval = b;\n      double *result = retval.rwdata ();\n\n      char uplo = 'U';\n      char trans = get_blas_char (transt);\n      char dia = 'N';\n\n      F77_INT tmp_info = 0;\n\n      F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                 F77_CONST_CHAR_ARG2 (&trans, 1),\n                                 F77_CONST_CHAR_ARG2 (&dia, 1),\n                                 nr, b_nc, tmp_data, nr,\n                                 result, nr, tmp_info\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)));\n\n      info = tmp_info;\n\n      if (calc_cond)\n        {\n          char norm = '1';\n          uplo = 'U';\n          dia = 'N';\n\n          Array<double> z (dim_vector (3 * nc, 1));\n          double *pz = z.rwdata ();\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n\n          F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, tmp_data, nr, rcon,\n                                     pz, piz, tmp_info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          info = tmp_info;\n\n          if (info != 0)\n            info = -2;\n\n          if (is_singular (rcon) || octave::math::isnan (rcon))\n            {\n              info = -2;\n\n              if (sing_handler)\n                sing_handler (rcon);\n              else\n                octave::warn_singular_matrix (rcon);\n            }\n        }\n    }\n\n  return retval;\n}\n\nMatrix\nMatrix::ltsolve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n                 double& rcon, solve_singularity_handler sing_handler,\n                 bool calc_cond, blas_trans_type transt) const\n{\n  Matrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    retval = Matrix (nc, b_nc, 0.0);\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      rcon = 1.0;\n      info = 0;\n\n      if (typ == MatrixType::Permuted_Lower)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n\n      const double *tmp_data = data ();\n\n      retval = b;\n      double *result = retval.rwdata ();\n\n      char uplo = 'L';\n      char trans = get_blas_char (transt);\n      char dia = 'N';\n\n      F77_INT tmp_info = 0;\n\n      F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                 F77_CONST_CHAR_ARG2 (&trans, 1),\n                                 F77_CONST_CHAR_ARG2 (&dia, 1),\n                                 nr, b_nc, tmp_data, nr,\n                                 result, nr, tmp_info\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)));\n\n      info = tmp_info;\n\n      if (calc_cond)\n        {\n          char norm = '1';\n          uplo = 'L';\n          dia = 'N';\n\n          Array<double> z (dim_vector (3 * nc, 1));\n          double *pz = z.rwdata ();\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n\n          F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, tmp_data, nr, rcon,\n                                     pz, piz, tmp_info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          info = tmp_info;\n\n          if (info != 0)\n            info = -2;\n\n          if (is_singular (rcon) || octave::math::isnan (rcon))\n            {\n              info = -2;\n\n              if (sing_handler)\n                sing_handler (rcon);\n              else\n                octave::warn_singular_matrix (rcon);\n            }\n        }\n    }\n\n  return retval;\n}\n\nMatrix\nMatrix::fsolve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n                double& rcon, solve_singularity_handler sing_handler,\n                bool calc_cond) const\n{\n  Matrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = Matrix (nc, b.cols (), 0.0);\n  else\n    {\n      int typ = mattype.type ();\n\n      // Calculate the norm of the matrix for later use when determining rcon.\n      double anorm = -1.0;\n\n      if (typ == MatrixType::Hermitian)\n        {\n          info = 0;\n          char job = 'L';\n\n          Matrix atmp = *this;\n          double *tmp_data = atmp.rwdata ();\n\n          // The norm of the matrix for later use when determining rcon.\n          if (calc_cond)\n            anorm = norm1 (atmp);\n\n          F77_INT tmp_info = 0;\n\n          F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                     tmp_data, nr, tmp_info\n                                     F77_CHAR_ARG_LEN (1)));\n\n          info = tmp_info;\n\n          // Throw away extra info LAPACK gives so as to not change output.\n          rcon = 0.0;\n          if (info != 0)\n            {\n              info = -2;\n\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<double> z (dim_vector (3 * nc, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nc, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, tmp_data, nr, anorm,\n                                             rcon, pz, piz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      info = -2;\n\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n\n              if (info == 0)\n                {\n                  retval = b;\n                  double *result = retval.rwdata ();\n\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n                  F77_XFCN (dpotrs, DPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, b_nc, tmp_data, nr,\n                                             result, b_nr, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n                }\n              else\n                {\n                  mattype.mark_as_unsymmetric ();\n                  typ = MatrixType::Full;\n                }\n            }\n        }\n\n      if (typ == MatrixType::Full)\n        {\n          info = 0;\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          Matrix atmp = *this;\n          double *tmp_data = atmp.rwdata ();\n\n          if (calc_cond && anorm < 0.0)\n            anorm = norm1 (atmp);\n\n          Array<double> z (dim_vector (4 * nc, 1));\n          double *pz = z.rwdata ();\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n\n          F77_INT tmp_info = 0;\n\n          F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, tmp_info));\n\n          info = tmp_info;\n\n          // Throw away extra info LAPACK gives so as to not change output.\n          rcon = 0.0;\n          if (info != 0)\n            {\n              info = -2;\n\n              if (sing_handler)\n                sing_handler (rcon);\n              else\n                octave::warn_singular_matrix ();\n\n              mattype.mark_as_rectangular ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  // Calculate the condition number for non-singular matrix.\n                  char job = '1';\n                  F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nc, tmp_data, nr, anorm,\n                                             rcon, pz, piz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n\n              if (info == 0)\n                {\n                  retval = b;\n                  double *result = retval.rwdata ();\n\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n                  char job = 'N';\n                  F77_XFCN (dgetrs, DGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, b_nc, tmp_data, nr,\n                                             pipvt, result, b_nr, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n                }\n              else\n                mattype.mark_as_rectangular ();\n            }\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nMatrix\nMatrix::solve (MatrixType& mattype, const Matrix& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nMatrix\nMatrix::solve (MatrixType& mattype, const Matrix& b,\n               octave_idx_type& info) const\n{\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nMatrix\nMatrix::solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n               double& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nMatrix\nMatrix::solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n               double& rcon, solve_singularity_handler sing_handler,\n               bool singular_fallback, blas_trans_type transt) const\n{\n  Matrix retval;\n  int typ = mattype.type ();\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  // Only calculate the condition number for LU/Cholesky\n  if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, info, rcon, sing_handler, true, transt);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, info, rcon, sing_handler, true, transt);\n  else if (transt == blas_trans || transt == blas_conj_trans)\n    return transpose ().solve (mattype, b, info, rcon, sing_handler,\n                               singular_fallback);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, info, rcon, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  // Rectangular or one of the above solvers flags a singular matrix\n  if (singular_fallback && mattype.type () == MatrixType::Rectangular)\n    {\n      octave_idx_type rank;\n      retval = lssolve (b, info, rank, rcon);\n    }\n\n  return retval;\n}\n\nComplexMatrix\nMatrix::solve (MatrixType& mattype, const ComplexMatrix& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexMatrix\nMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n               octave_idx_type& info) const\n{\n  double rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nComplexMatrix\nMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n               octave_idx_type& info, double& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nstatic Matrix\nstack_complex_matrix (const ComplexMatrix& cm)\n{\n  octave_idx_type m = cm.rows ();\n  octave_idx_type n = cm.cols ();\n  octave_idx_type nel = m*n;\n  Matrix retval (m, 2*n);\n  const Complex *cmd = cm.data ();\n  double *rd = retval.rwdata ();\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      rd[i] = std::real (cmd[i]);\n      rd[nel+i] = std::imag (cmd[i]);\n    }\n  return retval;\n}\n\nstatic ComplexMatrix\nunstack_complex_matrix (const Matrix& sm)\n{\n  octave_idx_type m = sm.rows ();\n  octave_idx_type n = sm.cols () / 2;\n  octave_idx_type nel = m*n;\n  ComplexMatrix retval (m, n);\n  const double *smd = sm.data ();\n  Complex *rd = retval.rwdata ();\n  for (octave_idx_type i = 0; i < nel; i++)\n    rd[i] = Complex (smd[i], smd[nel+i]);\n  return retval;\n}\n\nComplexMatrix\nMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n               octave_idx_type& info, double& rcon,\n               solve_singularity_handler sing_handler,\n               bool singular_fallback, blas_trans_type transt) const\n{\n  Matrix tmp = stack_complex_matrix (b);\n  tmp = solve (mattype, tmp, info, rcon, sing_handler, singular_fallback,\n               transt);\n  return unstack_complex_matrix (tmp);\n}\n\nColumnVector\nMatrix::solve (MatrixType& mattype, const ColumnVector& b) const\n{\n  octave_idx_type info; double rcon;\n  return solve (mattype, b, info, rcon);\n}\n\nColumnVector\nMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n               octave_idx_type& info) const\n{\n  double rcon;\n  return solve (mattype, b, info, rcon);\n}\n\nColumnVector\nMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n               octave_idx_type& info, double& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nColumnVector\nMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n               octave_idx_type& info, double& rcon,\n               solve_singularity_handler sing_handler,\n               blas_trans_type transt) const\n{\n  Matrix tmp (b);\n  tmp = solve (mattype, tmp, info, rcon, sing_handler, true, transt);\n  return tmp.column (static_cast<octave_idx_type> (0));\n}\n\nComplexColumnVector\nMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (mattype, b);\n}\n\nComplexColumnVector\nMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n               octave_idx_type& info) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (mattype, b, info);\n}\n\nComplexColumnVector\nMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n               octave_idx_type& info, double& rcon) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (mattype, b, info, rcon);\n}\n\nComplexColumnVector\nMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n               octave_idx_type& info, double& rcon,\n               solve_singularity_handler sing_handler,\n               blas_trans_type transt) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (mattype, b, info, rcon, sing_handler, transt);\n}\n\nMatrix\nMatrix::solve (const Matrix& b) const\n{\n  octave_idx_type info;\n  double rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nMatrix\nMatrix::solve (const Matrix& b, octave_idx_type& info) const\n{\n  double rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nMatrix\nMatrix::solve (const Matrix& b, octave_idx_type& info, double& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nMatrix\nMatrix::solve (const Matrix& b, octave_idx_type& info,\n               double& rcon, solve_singularity_handler sing_handler,\n               blas_trans_type transt) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, info, rcon, sing_handler, true, transt);\n}\n\nComplexMatrix\nMatrix::solve (const ComplexMatrix& b) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (b);\n}\n\nComplexMatrix\nMatrix::solve (const ComplexMatrix& b, octave_idx_type& info) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (b, info);\n}\n\nComplexMatrix\nMatrix::solve (const ComplexMatrix& b, octave_idx_type& info,\n               double& rcon) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (b, info, rcon);\n}\n\nComplexMatrix\nMatrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon,\n               solve_singularity_handler sing_handler,\n               blas_trans_type transt) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (b, info, rcon, sing_handler, transt);\n}\n\nColumnVector\nMatrix::solve (const ColumnVector& b) const\n{\n  octave_idx_type info; double rcon;\n  return solve (b, info, rcon);\n}\n\nColumnVector\nMatrix::solve (const ColumnVector& b, octave_idx_type& info) const\n{\n  double rcon;\n  return solve (b, info, rcon);\n}\n\nColumnVector\nMatrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nColumnVector\nMatrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcon,\n               solve_singularity_handler sing_handler,\n               blas_trans_type transt) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, info, rcon, sing_handler, transt);\n}\n\nComplexColumnVector\nMatrix::solve (const ComplexColumnVector& b) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (b);\n}\n\nComplexColumnVector\nMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (b, info);\n}\n\nComplexColumnVector\nMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,\n               double& rcon) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (b, info, rcon);\n}\n\nComplexColumnVector\nMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,\n               double& rcon,\n               solve_singularity_handler sing_handler,\n               blas_trans_type transt) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.solve (b, info, rcon, sing_handler, transt);\n}\n\nMatrix\nMatrix::lssolve (const Matrix& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nMatrix\nMatrix::lssolve (const Matrix& b, octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nMatrix\nMatrix::lssolve (const Matrix& b, octave_idx_type& info,\n                 octave_idx_type& rank) const\n{\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nMatrix\nMatrix::lssolve (const Matrix& b, octave_idx_type& info,\n                 octave_idx_type& rank, double& rcon) const\n{\n  Matrix retval;\n\n  F77_INT m = octave::to_f77_int (rows ());\n  F77_INT n = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n  F77_INT nrhs = b_nc;  // alias for code readability\n\n  if (m != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (m == 0 || n == 0 || b_nc == 0)\n    retval = Matrix (n, b_nc, 0.0);\n  else\n    {\n      F77_INT minmn = (m < n ? m : n);\n      F77_INT maxmn = (m > n ? m : n);\n      rcon = -1.0;\n      if (m != n)\n        {\n          retval = Matrix (maxmn, nrhs, 0.0);\n\n          for (F77_INT j = 0; j < nrhs; j++)\n            for (F77_INT i = 0; i < m; i++)\n              retval.elem (i, j) = b.elem (i, j);\n        }\n      else\n        retval = b;\n\n      Matrix atmp = *this;\n      double *tmp_data = atmp.rwdata ();\n\n      double *pretval = retval.rwdata ();\n      Array<double> s (dim_vector (minmn, 1));\n      double *ps = s.rwdata ();\n\n      // Ask DGELSD what the dimension of WORK should be.\n      F77_INT lwork = -1;\n\n      Array<double> work (dim_vector (1, 1));\n\n      F77_INT smlsiz;\n      F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 (\"DGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   0, 0, 0, 0, smlsiz\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      F77_INT mnthr;\n      F77_FUNC (xilaenv, XILAENV) (6, F77_CONST_CHAR_ARG2 (\"DGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   m, n, nrhs, -1, mnthr\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      // We compute the size of iwork because DGELSD in older versions\n      // of LAPACK does not return it on a query call.\n      double dminmn = static_cast<double> (minmn);\n      double dsmlsizp1 = static_cast<double> (smlsiz+1);\n      double tmp = octave::math::log2 (dminmn / dsmlsizp1);\n\n      F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;\n      if (nlvl < 0)\n        nlvl = 0;\n\n      F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;\n      if (liwork < 1)\n        liwork = 1;\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n      F77_INT *piwork = iwork.rwdata ();\n\n      F77_INT tmp_info = 0;\n      F77_INT tmp_rank = 0;\n\n      F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,\n                                 ps, rcon, tmp_rank, work.rwdata (),\n                                 lwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      // The workspace query is broken in at least LAPACK 3.0.0\n      // through 3.1.1 when n >= mnthr.  The obtuse formula below\n      // should provide sufficient workspace for DGELSD to operate\n      // efficiently.\n      if (n > m && n >= mnthr)\n        {\n          const F77_INT wlalsd\n            = 9*m + 2*m*smlsiz + 8*m*nlvl + m*nrhs + (smlsiz+1)*(smlsiz+1);\n\n          F77_INT addend = m;\n\n          if (2*m-4 > addend)\n            addend = 2*m-4;\n\n          if (nrhs > addend)\n            addend = nrhs;\n\n          if (n-3*m > addend)\n            addend = n-3*m;\n\n          if (wlalsd > addend)\n            addend = wlalsd;\n\n          const F77_INT lworkaround = 4*m + m*m + addend;\n\n          if (work(0) < lworkaround)\n            work(0) = lworkaround;\n        }\n      else if (m >= n)\n        {\n          F77_INT lworkaround\n            = 12*n + 2*n*smlsiz + 8*n*nlvl + n*nrhs + (smlsiz+1)*(smlsiz+1);\n\n          if (work(0) < lworkaround)\n            work(0) = lworkaround;\n        }\n\n      lwork = static_cast<F77_INT> (work(0));\n      work.resize (dim_vector (lwork, 1));\n\n      double anorm = norm1 (*this);\n\n      if (octave::math::isinf (anorm))\n        {\n          rcon = 0.0;\n          retval = Matrix (n, b_nc, 0.0);\n        }\n      else if (octave::math::isnan (anorm))\n        {\n          rcon = octave::numeric_limits<double>::NaN ();\n          retval = Matrix (n, b_nc, octave::numeric_limits<double>::NaN ());\n        }\n      else\n        {\n          F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval,\n                                     maxmn, ps, rcon, tmp_rank,\n                                     work.rwdata (), lwork,\n                                     piwork, tmp_info));\n\n          info = tmp_info;\n          rank = tmp_rank;\n\n          if (s.elem (0) == 0.0)\n            rcon = 0.0;\n          else\n            rcon = s.elem (minmn - 1) / s.elem (0);\n\n          retval.resize (n, nrhs);\n        }\n    }\n\n  return retval;\n}\n\nComplexMatrix\nMatrix::lssolve (const ComplexMatrix& b) const\n{\n  ComplexMatrix tmp (*this);\n  octave_idx_type info;\n  octave_idx_type rank;\n  double rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nComplexMatrix\nMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const\n{\n  ComplexMatrix tmp (*this);\n  octave_idx_type rank;\n  double rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nComplexMatrix\nMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info,\n                 octave_idx_type& rank) const\n{\n  ComplexMatrix tmp (*this);\n  double rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nComplexMatrix\nMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info,\n                 octave_idx_type& rank, double& rcon) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nColumnVector\nMatrix::lssolve (const ColumnVector& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nColumnVector\nMatrix::lssolve (const ColumnVector& b, octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nColumnVector\nMatrix::lssolve (const ColumnVector& b, octave_idx_type& info,\n                 octave_idx_type& rank) const\n{\n  double rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nColumnVector\nMatrix::lssolve (const ColumnVector& b, octave_idx_type& info,\n                 octave_idx_type& rank, double& rcon) const\n{\n  ColumnVector retval;\n\n  F77_INT nrhs = 1;\n\n  F77_INT m = octave::to_f77_int (rows ());\n  F77_INT n = octave::to_f77_int (cols ());\n\n  F77_INT b_nel = octave::to_f77_int (b.numel ());\n\n  if (m != b_nel)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (m == 0 || n == 0)\n    retval = ColumnVector (n, 0.0);\n  else\n    {\n      F77_INT minmn = (m < n ? m : n);\n      F77_INT maxmn = (m > n ? m : n);\n      rcon = -1.0;\n\n      if (m != n)\n        {\n          retval = ColumnVector (maxmn, 0.0);\n\n          for (F77_INT i = 0; i < m; i++)\n            retval.elem (i) = b.elem (i);\n        }\n      else\n        retval = b;\n\n      Matrix atmp = *this;\n      double *tmp_data = atmp.rwdata ();\n\n      double *pretval = retval.rwdata ();\n      Array<double> s (dim_vector (minmn, 1));\n      double *ps = s.rwdata ();\n\n      // Ask DGELSD what the dimension of WORK should be.\n      F77_INT lwork = -1;\n\n      Array<double> work (dim_vector (1, 1));\n\n      F77_INT smlsiz;\n      F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 (\"DGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   0, 0, 0, 0, smlsiz\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      // We compute the size of iwork because DGELSD in older versions\n      // of LAPACK does not return it on a query call.\n      double dminmn = static_cast<double> (minmn);\n      double dsmlsizp1 = static_cast<double> (smlsiz+1);\n      double tmp = octave::math::log2 (dminmn / dsmlsizp1);\n\n      F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;\n      if (nlvl < 0)\n        nlvl = 0;\n\n      F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;\n      if (liwork < 1)\n        liwork = 1;\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n      F77_INT *piwork = iwork.rwdata ();\n\n      F77_INT tmp_info = 0;\n      F77_INT tmp_rank = 0;\n\n      F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,\n                                 ps, rcon, tmp_rank, work.rwdata (),\n                                 lwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      lwork = static_cast<F77_INT> (work(0));\n      work.resize (dim_vector (lwork, 1));\n\n      F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval,\n                                 maxmn, ps, rcon, tmp_rank,\n                                 work.rwdata (), lwork,\n                                 piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      if (rank < minmn)\n        {\n          if (s.elem (0) == 0.0)\n            rcon = 0.0;\n          else\n            rcon = s.elem (minmn - 1) / s.elem (0);\n        }\n\n      retval.resize (n);\n    }\n\n  return retval;\n}\n\nComplexColumnVector\nMatrix::lssolve (const ComplexColumnVector& b) const\n{\n  ComplexMatrix tmp (*this);\n  octave_idx_type info;\n  octave_idx_type rank;\n  double rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nComplexColumnVector\nMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const\n{\n  ComplexMatrix tmp (*this);\n  octave_idx_type rank;\n  double rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nComplexColumnVector\nMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info,\n                 octave_idx_type& rank) const\n{\n  ComplexMatrix tmp (*this);\n  double rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nComplexColumnVector\nMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info,\n                 octave_idx_type& rank, double& rcon) const\n{\n  ComplexMatrix tmp (*this);\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nMatrix&\nMatrix::operator += (const DiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator +=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) += a.elem (i, i);\n\n  return *this;\n}\n\nMatrix&\nMatrix::operator -= (const DiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator -=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) -= a.elem (i, i);\n\n  return *this;\n}\n\n// unary operations\n\n// column vector by row vector -> matrix operations\n\nMatrix\noperator * (const ColumnVector& v, const RowVector& a)\n{\n  Matrix retval;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  if (len != 0)\n    {\n      F77_INT a_len = octave::to_f77_int (a.numel ());\n\n      retval = Matrix (len, a_len);\n      double *c = retval.rwdata ();\n\n      F77_XFCN (dgemm, DGEMM, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                               F77_CONST_CHAR_ARG2 (\"N\", 1),\n                               len, a_len, 1, 1.0, v.data (), len,\n                               a.data (), 1, 0.0, c, len\n                               F77_CHAR_ARG_LEN (1)\n                               F77_CHAR_ARG_LEN (1)));\n    }\n\n  return retval;\n}\n\n// other operations.\n\n// FIXME: Do these really belong here?  Maybe they should be in a base class?\n\nboolMatrix\nMatrix::all (int dim) const\n{\n  return NDArray::all (dim);\n}\n\nboolMatrix\nMatrix::any (int dim) const\n{\n  return NDArray::any (dim);\n}\n\nMatrix\nMatrix::flip (int dim) const\n{\n  return NDArray::flip (dim);\n}\n\nMatrix\nMatrix::cumprod (int dim, bool nanflag) const\n{\n  return NDArray::cumprod (dim, nanflag);\n}\n\nMatrix\nMatrix::cumsum (int dim, bool nanflag) const\n{\n  return NDArray::cumsum (dim, nanflag);\n}\n\nMatrix\nMatrix::prod (int dim, bool nanflag) const\n{\n  return NDArray::prod (dim, nanflag);\n}\n\nMatrix\nMatrix::sum (int dim, bool nanflag) const\n{\n  return NDArray::sum (dim, nanflag);\n}\n\nMatrix\nMatrix::sumsq (int dim, bool nanflag) const\n{\n  return NDArray::sumsq (dim, nanflag);\n}\n\nMatrix\nMatrix::abs () const\n{\n  return NDArray::abs ();\n}\n\nMatrix\nMatrix::diag (octave_idx_type k) const\n{\n  return NDArray::diag (k);\n}\n\nDiagMatrix\nMatrix::diag (octave_idx_type m, octave_idx_type n) const\n{\n  DiagMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr == 1 || nc == 1)\n    retval = DiagMatrix (*this, m, n);\n  else\n    (*current_liboctave_error_handler) (\"diag: expecting vector argument\");\n\n  return retval;\n}\n\nColumnVector\nMatrix::row_min () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return row_min (dummy_idx);\n}\n\nColumnVector\nMatrix::row_min (Array<octave_idx_type>& idx_arg) const\n{\n  ColumnVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nr);\n      idx_arg.resize (dim_vector (nr, 1));\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_idx_type idx_j;\n\n          double tmp_min = octave::numeric_limits<double>::NaN ();\n\n          for (idx_j = 0; idx_j < nc; idx_j++)\n            {\n              tmp_min = elem (i, idx_j);\n\n              if (! octave::math::isnan (tmp_min))\n                break;\n            }\n\n          for (octave_idx_type j = idx_j+1; j < nc; j++)\n            {\n              double tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n              else if (tmp < tmp_min)\n                {\n                  idx_j = j;\n                  tmp_min = tmp;\n                }\n            }\n\n          result.elem (i) = tmp_min;\n          idx_arg.elem (i) = (octave::math::isnan (tmp_min) ? 0 : idx_j);\n        }\n    }\n\n  return result;\n}\n\nColumnVector\nMatrix::row_max () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return row_max (dummy_idx);\n}\n\nColumnVector\nMatrix::row_max (Array<octave_idx_type>& idx_arg) const\n{\n  ColumnVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nr);\n      idx_arg.resize (dim_vector (nr, 1));\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_idx_type idx_j;\n\n          double tmp_max = octave::numeric_limits<double>::NaN ();\n\n          for (idx_j = 0; idx_j < nc; idx_j++)\n            {\n              tmp_max = elem (i, idx_j);\n\n              if (! octave::math::isnan (tmp_max))\n                break;\n            }\n\n          for (octave_idx_type j = idx_j+1; j < nc; j++)\n            {\n              double tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n              else if (tmp > tmp_max)\n                {\n                  idx_j = j;\n                  tmp_max = tmp;\n                }\n            }\n\n          result.elem (i) = tmp_max;\n          idx_arg.elem (i) = (octave::math::isnan (tmp_max) ? 0 : idx_j);\n        }\n    }\n\n  return result;\n}\n\nRowVector\nMatrix::column_min () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return column_min (dummy_idx);\n}\n\nRowVector\nMatrix::column_min (Array<octave_idx_type>& idx_arg) const\n{\n  RowVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nc);\n      idx_arg.resize (dim_vector (1, nc));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_idx_type idx_i;\n\n          double tmp_min = octave::numeric_limits<double>::NaN ();\n\n          for (idx_i = 0; idx_i < nr; idx_i++)\n            {\n              tmp_min = elem (idx_i, j);\n\n              if (! octave::math::isnan (tmp_min))\n                break;\n            }\n\n          for (octave_idx_type i = idx_i+1; i < nr; i++)\n            {\n              double tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n              else if (tmp < tmp_min)\n                {\n                  idx_i = i;\n                  tmp_min = tmp;\n                }\n            }\n\n          result.elem (j) = tmp_min;\n          idx_arg.elem (j) = (octave::math::isnan (tmp_min) ? 0 : idx_i);\n        }\n    }\n\n  return result;\n}\n\nRowVector\nMatrix::column_max () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return column_max (dummy_idx);\n}\n\nRowVector\nMatrix::column_max (Array<octave_idx_type>& idx_arg) const\n{\n  RowVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nc);\n      idx_arg.resize (dim_vector (1, nc));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_idx_type idx_i;\n\n          double tmp_max = octave::numeric_limits<double>::NaN ();\n\n          for (idx_i = 0; idx_i < nr; idx_i++)\n            {\n              tmp_max = elem (idx_i, j);\n\n              if (! octave::math::isnan (tmp_max))\n                break;\n            }\n\n          for (octave_idx_type i = idx_i+1; i < nr; i++)\n            {\n              double tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n              else if (tmp > tmp_max)\n                {\n                  idx_i = i;\n                  tmp_max = tmp;\n                }\n            }\n\n          result.elem (j) = tmp_max;\n          idx_arg.elem (j) = (octave::math::isnan (tmp_max) ? 0 : idx_i);\n        }\n    }\n\n  return result;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const Matrix& a)\n{\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    {\n      for (octave_idx_type j = 0; j < a.cols (); j++)\n        {\n          os << ' ';\n          octave::write_value<double> (os, a.elem (i, j));\n        }\n      os << \"\\n\";\n    }\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, Matrix& a)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      double tmp;\n      for (octave_idx_type i = 0; i < nr; i++)\n        for (octave_idx_type j = 0; j < nc; j++)\n          {\n            tmp = octave::read_value<double> (is);\n            if (is)\n              a.elem (i, j) = tmp;\n            else\n              return is;\n          }\n    }\n\n  return is;\n}\n\nMatrix\nGivens (double x, double y)\n{\n  double cc, s, temp_r;\n\n  F77_FUNC (dlartg, DLARTG) (x, y, cc, s, temp_r);\n\n  Matrix g (2, 2);\n\n  g.elem (0, 0) = cc;\n  g.elem (1, 1) = cc;\n  g.elem (0, 1) = s;\n  g.elem (1, 0) = -s;\n\n  return g;\n}\n\nMatrix\nSylvester (const Matrix& a, const Matrix& b, const Matrix& c)\n{\n  Matrix retval;\n\n  // FIXME: need to check that a, b, and c are all the same size.\n\n  // Compute Schur decompositions.\n\n  octave::math::schur<Matrix> as (a, \"U\");\n  octave::math::schur<Matrix> bs (b, \"U\");\n\n  // Transform c to new coordinates.\n\n  Matrix ua = as.unitary_schur_matrix ();\n  Matrix sch_a = as.schur_matrix ();\n\n  Matrix ub = bs.unitary_schur_matrix ();\n  Matrix sch_b = bs.schur_matrix ();\n\n  Matrix cx = ua.transpose () * c * ub;\n\n  // Solve the sylvester equation, back-transform, and return the solution.\n\n  F77_INT a_nr = octave::to_f77_int (a.rows ());\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n\n  double scale;\n  F77_INT info;\n\n  double *pa = sch_a.rwdata ();\n  double *pb = sch_b.rwdata ();\n  double *px = cx.rwdata ();\n\n  F77_XFCN (dtrsyl, DTRSYL, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             1, a_nr, b_nr, pa, a_nr, pb,\n                             b_nr, px, a_nr, scale, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // FIXME: check info?\n\n  retval = ua*cx*ub.transpose ();\n\n  return retval;\n}\n\n// matrix by matrix -> matrix operations\n\n/*\n\n## Simple Dot Product, Matrix-Vector and Matrix-Matrix Unit tests\n%!assert ([1 2 3] * [ 4 ; 5 ; 6], 32, 1e-14)\n%!assert ([1 2 ; 3 4 ] * [5 ; 6], [17 ; 39 ], 1e-14)\n%!assert ([1 2 ; 3 4 ] * [5 6 ; 7 8], [19 22; 43 50], 1e-14)\n\n## Test some simple identities\n%!shared M, cv, rv, Mt, rvt\n%! M = randn (10,10) + 100*eye (10,10);\n%! Mt = M';\n%! cv = randn (10,1);\n%! rv = randn (1,10);\n%! rvt = rv';\n%!assert ([M*cv,M*cv], M*[cv,cv], 2e-13)\n%!assert ([M'*cv,M'*cv], M'*[cv,cv], 2e-13)\n%!assert ([rv*M;rv*M], [rv;rv]*M, 2e-13)\n%!assert ([rv*M';rv*M'], [rv;rv]*M', 2e-13)\n%!assert (2*rv*cv, [rv,rv]*[cv;cv], 2e-13)\n%!assert (M'\\cv, Mt\\cv, 1e-14)\n%!assert (M'\\rv', Mt\\rvt, 1e-14)\n\n*/\n\nstatic inline char\nget_blas_trans_arg (bool trans)\n{\n  return trans ? 'T' : 'N';\n}\n\n// the general GEMM operation\n\nMatrix\nxgemm (const Matrix& a, const Matrix& b,\n       blas_trans_type transa, blas_trans_type transb)\n{\n  Matrix retval;\n\n  bool tra = transa != blas_no_trans;\n  bool trb = transb != blas_no_trans;\n\n  F77_INT a_nr = octave::to_f77_int (tra ? a.cols () : a.rows ());\n  F77_INT a_nc = octave::to_f77_int (tra ? a.rows () : a.cols ());\n\n  F77_INT b_nr = octave::to_f77_int (trb ? b.cols () : b.rows ());\n  F77_INT b_nc = octave::to_f77_int (trb ? b.rows () : b.cols ());\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  if (a_nr == 0 || a_nc == 0 || b_nc == 0)\n    retval = Matrix (a_nr, b_nc, 0.0);\n  else if (a.data () == b.data () && a_nr == b_nc && tra != trb)\n    {\n      F77_INT lda = octave::to_f77_int (a.rows ());\n\n      retval = Matrix (a_nr, b_nc);\n      double *c = retval.rwdata ();\n\n      const char ctra = get_blas_trans_arg (tra);\n      F77_XFCN (dsyrk, DSYRK, (F77_CONST_CHAR_ARG2 (\"U\", 1),\n                               F77_CONST_CHAR_ARG2 (&ctra, 1),\n                               a_nr, a_nc, 1.0,\n                               a.data (), lda, 0.0, c, a_nr\n                               F77_CHAR_ARG_LEN (1)\n                               F77_CHAR_ARG_LEN (1)));\n      for (int j = 0; j < a_nr; j++)\n        for (int i = 0; i < j; i++)\n          retval.xelem (j, i) = retval.xelem (i, j);\n\n    }\n  else\n    {\n      F77_INT lda = octave::to_f77_int (a.rows ());\n      F77_INT tda = octave::to_f77_int (a.cols ());\n      F77_INT ldb = octave::to_f77_int (b.rows ());\n      F77_INT tdb = octave::to_f77_int (b.cols ());\n\n      retval = Matrix (a_nr, b_nc);\n      double *c = retval.rwdata ();\n\n      if (b_nc == 1)\n        {\n          if (a_nr == 1)\n            F77_FUNC (xddot, XDDOT) (a_nc, a.data (), 1, b.data (), 1, *c);\n          else\n            {\n              const char ctra = get_blas_trans_arg (tra);\n              F77_XFCN (dgemv, DGEMV, (F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                       lda, tda, 1.0, a.data (), lda,\n                                       b.data (), 1, 0.0, c, 1\n                                       F77_CHAR_ARG_LEN (1)));\n            }\n        }\n      else if (a_nr == 1)\n        {\n          const char crevtrb = get_blas_trans_arg (! trb);\n          F77_XFCN (dgemv, DGEMV, (F77_CONST_CHAR_ARG2 (&crevtrb, 1),\n                                   ldb, tdb, 1.0, b.data (), ldb,\n                                   a.data (), 1, 0.0, c, 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n      else\n        {\n          const char ctra = get_blas_trans_arg (tra);\n          const char ctrb = get_blas_trans_arg (trb);\n          F77_XFCN (dgemm, DGEMM, (F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   F77_CONST_CHAR_ARG2 (&ctrb, 1),\n                                   a_nr, b_nc, a_nc, 1.0, a.data (),\n                                   lda, b.data (), ldb, 0.0, c, a_nr\n                                   F77_CHAR_ARG_LEN (1)\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n    }\n\n  return retval;\n}\n\nMatrix\noperator * (const Matrix& a, const Matrix& b)\n{\n  return xgemm (a, b);\n}\n\n// FIXME: it would be nice to share code among the min/max functions below.\n\n#define EMPTY_RETURN_CHECK(T)                   \\\n  if (nr == 0 || nc == 0)                       \\\n    return T (nr, nc);\n\nMatrix\nmin (double d, const Matrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return min (d, m, nanflag, realabs);\n}\n\nMatrix\nmin (double d, const Matrix& m, const bool nanflag)\n{\n  const bool realabs = true;\n  return min (d, m, nanflag, realabs);\n}\n\nMatrix\nmin (double d, const Matrix& m, const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (Matrix);\n\n  Matrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::min (d, m(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nMatrix\nmin (const Matrix& m, double d)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return min (d, m, nanflag, realabs);\n}\n\nMatrix\nmin (const Matrix& m, double d, const bool nanflag)\n{\n  const bool realabs = true;\n  return min (d, m, nanflag, realabs);\n}\n\nMatrix\nmin (const Matrix& m, double d, const bool nanflag, const bool realabs)\n{\n  return min (d, m, nanflag, realabs);\n}\n\nMatrix\nmin (const Matrix& a, const Matrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return min (a, b, nanflag, realabs);\n}\n\nMatrix\nmin (const Matrix& a, const Matrix& b, const bool nanflag)\n{\n  const bool realabs = true;\n  return min (a, b, nanflag, realabs);\n}\n\nMatrix\nmin (const Matrix& a, const Matrix& b, const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n\n  if (nr != b.rows () || nc != b.columns ())\n    (*current_liboctave_error_handler)\n      (\"two-arg min requires same size arguments\");\n\n  EMPTY_RETURN_CHECK (Matrix);\n\n  Matrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::min (a(i, j), b(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nMatrix\nmax (double d, const Matrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return max (d, m, nanflag, realabs);\n}\n\nMatrix\nmax (double d, const Matrix& m, const bool nanflag)\n{\n  const bool realabs = true;\n  return max (d, m, nanflag, realabs);\n}\n\nMatrix\nmax (double d, const Matrix& m, const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (Matrix);\n\n  Matrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::max (d, m(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nMatrix\nmax (const Matrix& m, double d)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return max (d, m, nanflag, realabs);\n}\n\nMatrix\nmax (const Matrix& m, double d, const bool nanflag)\n{\n  const bool realabs = true;\n  return max (d, m, nanflag, realabs);\n}\n\nMatrix\nmax (const Matrix& m, double d, const bool nanflag, const bool realabs)\n{\n  return max (d, m, nanflag, realabs);\n}\n\nMatrix\nmax (const Matrix& a, const Matrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return max (a, b, nanflag, realabs);\n}\n\nMatrix\nmax (const Matrix& a, const Matrix& b, const bool nanflag)\n{\n  const bool realabs = true;\n  return max (a, b, nanflag, realabs);\n}\n\nMatrix\nmax (const Matrix& a, const Matrix& b, const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n\n  if (nr != b.rows () || nc != b.columns ())\n    (*current_liboctave_error_handler)\n      (\"two-arg max requires same size arguments\");\n\n  EMPTY_RETURN_CHECK (Matrix);\n\n  Matrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::max (a(i, j), b(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nMatrix\nlinspace (const ColumnVector& x1,\n          const ColumnVector& x2,\n          octave_idx_type n)\n\n{\n  octave_idx_type m = x1.numel ();\n\n  if (x2.numel () != m)\n    (*current_liboctave_error_handler)\n      (\"linspace: vectors must be of equal length\");\n\n  Matrix retval;\n\n  if (n < 1)\n    {\n      retval.clear (m, 0);\n      return retval;\n    }\n\n  retval.clear (m, n);\n  for (octave_idx_type i = 0; i < m; i++)\n    retval.insert (linspace (x1(i), x2(i), n), i, 0);\n\n  return retval;\n}\n\nMS_CMP_OPS (Matrix, double)\nMS_BOOL_OPS (Matrix, double)\n\nSM_CMP_OPS (double, Matrix)\nSM_BOOL_OPS (double, Matrix)\n\nMM_CMP_OPS (Matrix, Matrix)\nMM_BOOL_OPS (Matrix, Matrix)\n"
  },
  {
    "path": "liboctave/array/dMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dMatrix_h)\n#define octave_dMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"DET.h\"\n#include \"MArray.h\"\n#include \"MDiagArray2.h\"\n#include \"MatrixType.h\"\n#include \"dNDArray.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n\nclass OCTAVE_API Matrix : public NDArray\n{\npublic:\n\n  typedef ColumnVector column_vector_type;\n  typedef RowVector row_vector_type;\n\n  typedef ColumnVector real_column_vector_type;\n  typedef RowVector real_row_vector_type;\n\n  typedef Matrix real_matrix_type;\n  typedef ComplexMatrix complex_matrix_type;\n\n  typedef DiagMatrix real_diag_matrix_type;\n  typedef ComplexDiagMatrix complex_diag_matrix_type;\n\n  typedef double real_elt_type;\n  typedef Complex complex_elt_type;\n\n  typedef void (*solve_singularity_handler) (double rcon);\n\n  Matrix () = default;\n\n  Matrix (const Matrix& a) = default;\n\n  Matrix& operator = (const Matrix& a) = default;\n\n  ~Matrix () = default;\n\n  Matrix (octave_idx_type r, octave_idx_type c)\n    : NDArray (dim_vector (r, c)) { }\n\n  Matrix (octave_idx_type r, octave_idx_type c, double val)\n    : NDArray (dim_vector (r, c), val) { }\n\n  Matrix (const dim_vector& dv) : NDArray (dv.redim (2)) { }\n\n  Matrix (const dim_vector& dv, double val)\n    : NDArray (dv.redim (2), val) { }\n\n  template <typename U>\n  Matrix (const MArray<U>& a) : NDArray (a.as_matrix ()) { }\n\n  template <typename U>\n  Matrix (const Array<U>& a) : NDArray (a.as_matrix ()) { }\n\n  explicit OCTAVE_API Matrix (const RowVector& rv);\n\n  explicit OCTAVE_API Matrix (const ColumnVector& cv);\n\n  explicit OCTAVE_API Matrix (const DiagMatrix& a);\n\n  explicit OCTAVE_API Matrix (const MDiagArray2<double>& a);\n\n  explicit OCTAVE_API Matrix (const DiagArray2<double>& a);\n\n  explicit OCTAVE_API Matrix (const PermMatrix& a);\n\n  explicit OCTAVE_API Matrix (const boolMatrix& a);\n\n  explicit Matrix (const charMatrix& a);\n\n  OCTAVE_API bool operator == (const Matrix& a) const;\n  OCTAVE_API bool operator != (const Matrix& a) const;\n\n  OCTAVE_API bool issymmetric () const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API Matrix&\n  insert (const Matrix& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API Matrix&\n  insert (const RowVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API Matrix&\n  insert (const ColumnVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API Matrix&\n  insert (const DiagMatrix& a, octave_idx_type r, octave_idx_type c);\n\n  OCTAVE_API Matrix& fill (double val);\n  OCTAVE_API Matrix&\n  fill (double val, octave_idx_type r1, octave_idx_type c1,\n        octave_idx_type r2, octave_idx_type c2);\n\n  OCTAVE_API Matrix append (const Matrix& a) const;\n  OCTAVE_API Matrix append (const RowVector& a) const;\n  OCTAVE_API Matrix append (const ColumnVector& a) const;\n  OCTAVE_API Matrix append (const DiagMatrix& a) const;\n\n  OCTAVE_API Matrix stack (const Matrix& a) const;\n  OCTAVE_API Matrix stack (const RowVector& a) const;\n  OCTAVE_API Matrix stack (const ColumnVector& a) const;\n  OCTAVE_API Matrix stack (const DiagMatrix& a) const;\n\n  friend OCTAVE_API Matrix real (const ComplexMatrix& a);\n  friend OCTAVE_API Matrix imag (const ComplexMatrix& a);\n\n  friend class ComplexMatrix;\n\n  Matrix hermitian () const { return MArray<double>::transpose (); }\n  Matrix transpose () const { return MArray<double>::transpose (); }\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API Matrix\n  extract (octave_idx_type r1, octave_idx_type c1,\n           octave_idx_type r2, octave_idx_type c2) const;\n\n  OCTAVE_API Matrix\n  extract_n (octave_idx_type r1, octave_idx_type c1,\n             octave_idx_type nr, octave_idx_type nc) const;\n\n  // extract row or column i.\n\n  OCTAVE_API RowVector row (octave_idx_type i) const;\n\n  OCTAVE_API ColumnVector column (octave_idx_type i) const;\n\n  void resize (octave_idx_type nr, octave_idx_type nc, double rfv = 0)\n  {\n    MArray<double>::resize (dim_vector (nr, nc), rfv);\n  }\n\nprivate:\n  Matrix tinverse (MatrixType& mattype, octave_idx_type& info, double& rcon,\n                   bool force, bool calc_cond) const;\n\n  Matrix finverse (MatrixType& mattype, octave_idx_type& info, double& rcon,\n                   bool force, bool calc_cond) const;\n\npublic:\n  OCTAVE_API Matrix inverse () const;\n  OCTAVE_API Matrix inverse (octave_idx_type& info) const;\n  OCTAVE_API Matrix\n  inverse (octave_idx_type& info, double& rcon,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API Matrix inverse (MatrixType& mattype) const;\n  OCTAVE_API Matrix inverse (MatrixType& mattype, octave_idx_type& info) const;\n  OCTAVE_API Matrix\n  inverse (MatrixType& mattype, octave_idx_type& info, double& rcon,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API Matrix pseudo_inverse (double tol = 0.0) const;\n\n  OCTAVE_API ComplexMatrix fourier () const;\n  OCTAVE_API ComplexMatrix ifourier () const;\n\n  OCTAVE_API ComplexMatrix fourier2d () const;\n  OCTAVE_API ComplexMatrix ifourier2d () const;\n\n  OCTAVE_API DET determinant () const;\n  OCTAVE_API DET determinant (octave_idx_type& info) const;\n  OCTAVE_API DET\n  determinant (octave_idx_type& info, double& rcon,\n               bool calc_cond = true) const;\n  OCTAVE_API DET\n  determinant (MatrixType& mattype, octave_idx_type& info,\n               double& rcon, bool calc_cond = true) const;\n\n  OCTAVE_API double rcond () const;\n  OCTAVE_API double rcond (MatrixType& mattype) const;\n\nprivate:\n  // Upper triangular matrix solvers\n  Matrix utsolve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n                  double& rcon, solve_singularity_handler sing_handler,\n                  bool calc_cond = false,\n                  blas_trans_type transt = blas_no_trans) const;\n\n  // Lower triangular matrix solvers\n  Matrix ltsolve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n                  double& rcon, solve_singularity_handler sing_handler,\n                  bool calc_cond = false,\n                  blas_trans_type transt = blas_no_trans) const;\n\n  // Full matrix solvers (lu/cholesky)\n  Matrix fsolve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n                 double& rcon, solve_singularity_handler sing_handler,\n                 bool calc_cond = false) const;\n\npublic:\n  // Generic interface to solver with no probing of type\n  OCTAVE_API Matrix solve (MatrixType& mattype, const Matrix& b) const;\n  OCTAVE_API Matrix\n  solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API Matrix\n  solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n         double& rcon) const;\n  OCTAVE_API Matrix\n  solve (MatrixType& mattype, const Matrix& b, octave_idx_type& info,\n         double& rcon, solve_singularity_handler sing_handler,\n         bool singular_fallback = true,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b,\n         octave_idx_type& info, double& rcon) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& mattype, const ComplexMatrix& b,\n         octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         bool singular_fallback = true,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b) const;\n  OCTAVE_API ColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b,\n         octave_idx_type& info, double& rcon) const;\n  OCTAVE_API ColumnVector\n  solve (MatrixType& mattype, const ColumnVector& b, octave_idx_type& info,\n         double& rcon, solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b,\n         octave_idx_type& info, double& rcon) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& mattype, const ComplexColumnVector& b,\n         octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  // Generic interface to solver with probing of type\n  OCTAVE_API Matrix solve (const Matrix& b) const;\n  OCTAVE_API Matrix solve (const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API Matrix\n  solve (const Matrix& b, octave_idx_type& info, double& rcon) const;\n  OCTAVE_API Matrix\n  solve (const Matrix& b, octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexMatrix solve (const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info,\n         double& rcon) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ColumnVector solve (const ColumnVector& b) const;\n  OCTAVE_API ColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info, double& rcon) const;\n  OCTAVE_API ColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API ComplexColumnVector solve (const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info,\n         double& rcon) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info, double& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  // Singular solvers\n  OCTAVE_API Matrix lssolve (const Matrix& b) const;\n  OCTAVE_API Matrix lssolve (const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API Matrix\n  lssolve (const Matrix& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API Matrix\n  lssolve (const Matrix& b, octave_idx_type& info, octave_idx_type& rank,\n           double& rcon) const;\n\n  OCTAVE_API ComplexMatrix lssolve (const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  lssolve (const ComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  lssolve (const ComplexMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API ComplexMatrix\n  lssolve (const ComplexMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank, double& rcon) const;\n\n  OCTAVE_API ColumnVector lssolve (const ColumnVector& b) const;\n  OCTAVE_API ColumnVector\n  lssolve (const ColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ColumnVector\n  lssolve (const ColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API ColumnVector\n  lssolve (const ColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank, double& rcon) const;\n\n  OCTAVE_API ComplexColumnVector lssolve (const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  lssolve (const ComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  lssolve (const ComplexColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API ComplexColumnVector\n  lssolve (const ComplexColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank, double& rcon) const;\n\n  OCTAVE_API Matrix& operator += (const DiagMatrix& a);\n  OCTAVE_API Matrix& operator -= (const DiagMatrix& a);\n\n  // unary operations\n\n  // other operations\n\n  OCTAVE_API boolMatrix all (int dim = -1) const;\n  OCTAVE_API boolMatrix any (int dim = -1) const;\n\n  OCTAVE_API Matrix flip (int dim = -1) const;\n  OCTAVE_API Matrix cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API Matrix cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API Matrix prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API Matrix sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API Matrix sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API Matrix abs () const;\n\n  OCTAVE_API Matrix diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API DiagMatrix diag (octave_idx_type m, octave_idx_type n) const;\n\n  OCTAVE_API ColumnVector row_min () const;\n  OCTAVE_API ColumnVector row_max () const;\n\n  OCTAVE_API ColumnVector row_min (Array<octave_idx_type>& index) const;\n  OCTAVE_API ColumnVector row_max (Array<octave_idx_type>& index) const;\n\n  OCTAVE_API RowVector column_min () const;\n  OCTAVE_API RowVector column_max () const;\n\n  OCTAVE_API RowVector column_min (Array<octave_idx_type>& index) const;\n  OCTAVE_API RowVector column_max (Array<octave_idx_type>& index) const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const Matrix& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, Matrix& a);\n};\n\n// Publish externally used friend functions.\n\nextern OCTAVE_API Matrix real (const ComplexMatrix& a);\nextern OCTAVE_API Matrix imag (const ComplexMatrix& a);\n\n// column vector by row vector -> matrix operations\n\nextern OCTAVE_API Matrix operator * (const ColumnVector& a,\n                                     const RowVector& b);\n\n// Other functions.\n\nextern OCTAVE_API Matrix Givens (double, double);\n\nextern OCTAVE_API Matrix Sylvester (const Matrix&, const Matrix&,\n                                    const Matrix&);\n\nextern OCTAVE_API Matrix xgemm (const Matrix& a, const Matrix& b,\n                                blas_trans_type transa = blas_no_trans,\n                                blas_trans_type transb = blas_no_trans);\n\nextern OCTAVE_API Matrix operator * (const Matrix& a, const Matrix& b);\n\nextern OCTAVE_API Matrix min (double d, const Matrix& m);\nextern OCTAVE_API Matrix min (double d, const Matrix& m, const bool nanflag);\nextern OCTAVE_API Matrix\nmin (double d, const Matrix& m, const bool nanflag, const bool realabs);\nextern OCTAVE_API Matrix min (const Matrix& m, double d);\nextern OCTAVE_API Matrix min (const Matrix& m, double d, const bool nanflag);\nextern OCTAVE_API Matrix\nmin (const Matrix& m, double d, const bool nanflag, const bool realabs);\nextern OCTAVE_API Matrix min (const Matrix& a, const Matrix& b);\nextern OCTAVE_API Matrix\nmin (const Matrix& a, const Matrix& b, const bool nanflag);\nextern OCTAVE_API Matrix\nmin (const Matrix& a, const Matrix& b, const bool nanflag, const bool realabs);\n\nextern OCTAVE_API Matrix max (double d, const Matrix& m);\nextern OCTAVE_API Matrix max (double d, const Matrix& m, const bool nanflag);\nextern OCTAVE_API Matrix\nmax (double d, const Matrix& m, const bool nanflag, const bool realabs);\nextern OCTAVE_API Matrix max (const Matrix& m, double d);\nextern OCTAVE_API Matrix max (const Matrix& m, double d, const bool nanflag);\nextern OCTAVE_API Matrix\nmax (const Matrix& m, double d, const bool nanflag, const bool realabs);\nextern OCTAVE_API Matrix max (const Matrix& a, const Matrix& b);\nextern OCTAVE_API Matrix\nmax (const Matrix& a, const Matrix& b, const bool nanflag);\nextern OCTAVE_API Matrix\nmax (const Matrix& a, const Matrix& b, const bool nanflag, const bool realabs);\n\nextern OCTAVE_API Matrix linspace (const ColumnVector& x1,\n                                   const ColumnVector& x2,\n                                   octave_idx_type n);\n\nMS_CMP_OP_DECLS (Matrix, double, OCTAVE_API)\nMS_BOOL_OP_DECLS (Matrix, double, OCTAVE_API)\n\nSM_CMP_OP_DECLS (double, Matrix, OCTAVE_API)\nSM_BOOL_OP_DECLS (double, Matrix, OCTAVE_API)\n\nMM_CMP_OP_DECLS (Matrix, Matrix, OCTAVE_API)\nMM_BOOL_OP_DECLS (Matrix, Matrix, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, Matrix, double)\n\ntemplate <typename T>\nvoid read_int (std::istream& is, bool swap_bytes, T& val);\n\n#endif\n"
  },
  {
    "path": "liboctave/array/dNDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"dNDArray.h\"\n#include \"f77-fcn.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"mx-base.h\"\n#include \"mx-op-defs.h\"\n#include \"oct-error.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n\n#include \"bsxfun-defs.cc\"\n\nNDArray::NDArray (const Array<octave_idx_type>& a, bool zero_based,\n                  bool negative_to_nan)\n{\n  const octave_idx_type *pa = a.data ();\n  resize (a.dims ());\n  double *ptmp = rwdata ();\n  if (negative_to_nan)\n    {\n      double nan_val = lo_ieee_nan_value ();\n\n      if (zero_based)\n        for (octave_idx_type i = 0; i < a.numel (); i++)\n          {\n            double val = static_cast<double>\n                         (pa[i] + static_cast<octave_idx_type> (1));\n            if (val <= 0)\n              ptmp[i] = nan_val;\n            else\n              ptmp[i] = val;\n          }\n      else\n        for (octave_idx_type i = 0; i < a.numel (); i++)\n          {\n            double val = static_cast<double> (pa[i]);\n            if (val <= 0)\n              ptmp[i] = nan_val;\n            else\n              ptmp[i] = val;\n          }\n    }\n  else\n    {\n      if (zero_based)\n        for (octave_idx_type i = 0; i < a.numel (); i++)\n          ptmp[i] = static_cast<double>\n                    (pa[i] + static_cast<octave_idx_type> (1));\n      else\n        for (octave_idx_type i = 0; i < a.numel (); i++)\n          ptmp[i] = static_cast<double> (pa[i]);\n    }\n}\n\nNDArray::NDArray (const charNDArray& a)\n  : MArray<double> (a.dims ())\n{\n  octave_idx_type n = a.numel ();\n  for (octave_idx_type i = 0; i < n; i++)\n    xelem (i) = static_cast<unsigned char> (a(i));\n}\n\n#if defined (HAVE_FFTW)\n\nComplexNDArray\nNDArray::fourier (int dim) const\n{\n  const dim_vector& dv = dims ();\n\n  if (dim > dv.ndims () || dim < 0)\n    return ComplexNDArray ();\n\n  octave_idx_type stride = 1;\n  octave_idx_type n = dv(dim);\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  octave_idx_type howmany = numel () / dv(dim);\n  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));\n  octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);\n  octave_idx_type dist = (stride == 1 ? n : 1);\n\n  const double *in (data ());\n  ComplexNDArray retval (dv);\n  Complex *out (retval.rwdata ());\n\n  // Need to be careful here about the distance between fft's\n  for (octave_idx_type k = 0; k < nloop; k++)\n    octave::fftw::fft (in + k * stride * n, out + k * stride * n,\n                       n, howmany, stride, dist);\n\n  return retval;\n}\n\nComplexNDArray\nNDArray::ifourier (int dim) const\n{\n  const dim_vector& dv = dims ();\n\n  if (dim > dv.ndims () || dim < 0)\n    return ComplexNDArray ();\n\n  octave_idx_type stride = 1;\n  octave_idx_type n = dv(dim);\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  octave_idx_type howmany = numel () / dv(dim);\n  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));\n  octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);\n  octave_idx_type dist = (stride == 1 ? n : 1);\n\n  ComplexNDArray retval (*this);\n  Complex *out (retval.rwdata ());\n\n  // Need to be careful here about the distance between fft's\n  for (octave_idx_type k = 0; k < nloop; k++)\n    octave::fftw::ifft (out + k * stride * n, out + k * stride * n,\n                        n, howmany, stride, dist);\n\n  return retval;\n}\n\nComplexNDArray\nNDArray::fourier2d () const\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 2)\n    return ComplexNDArray ();\n\n  dim_vector dv2 (dv(0), dv(1));\n  const double *in = data ();\n  ComplexNDArray retval (dv);\n  Complex *out = retval.rwdata ();\n  octave_idx_type howmany = numel () / dv(0) / dv(1);\n  octave_idx_type dist = dv(0) * dv(1);\n\n  for (octave_idx_type i=0; i < howmany; i++)\n    octave::fftw::fftNd (in + i*dist, out + i*dist, 2, dv2);\n\n  return retval;\n}\n\nComplexNDArray\nNDArray::ifourier2d () const\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 2)\n    return ComplexNDArray ();\n\n  dim_vector dv2 (dv(0), dv(1));\n  ComplexNDArray retval (*this);\n  Complex *out = retval.rwdata ();\n  octave_idx_type howmany = numel () / dv(0) / dv(1);\n  octave_idx_type dist = dv(0) * dv(1);\n\n  for (octave_idx_type i=0; i < howmany; i++)\n    octave::fftw::ifftNd (out + i*dist, out + i*dist, 2, dv2);\n\n  return retval;\n}\n\nComplexNDArray\nNDArray::fourierNd () const\n{\n  const dim_vector& dv = dims ();\n  int rank = dv.ndims ();\n\n  const double *in (data ());\n  ComplexNDArray retval (dv);\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::fftNd (in, out, rank, dv);\n\n  return retval;\n}\n\nComplexNDArray\nNDArray::ifourierNd () const\n{\n  const dim_vector& dv = dims ();\n  int rank = dv.ndims ();\n\n  ComplexNDArray tmp (*this);\n  Complex *in (tmp.rwdata ());\n  ComplexNDArray retval (dv);\n  Complex *out (retval.rwdata ());\n\n  octave::fftw::ifftNd (in, out, rank, dv);\n\n  return retval;\n}\n\n#else\n\nComplexNDArray\nNDArray::fourier (int dim) const\n{\n  octave_unused_parameter (dim);\n\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nNDArray::ifourier (int dim) const\n{\n  octave_unused_parameter (dim);\n\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nNDArray::fourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nNDArray::ifourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nNDArray::fourierNd () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\nComplexNDArray\nNDArray::ifourierNd () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return ComplexNDArray ();\n}\n\n#endif\n\n// unary operations\n\nboolNDArray\nNDArray::operator ! () const\n{\n  if (any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n\n  return do_mx_unary_op<bool, double> (*this, mx_inline_not);\n}\n\nbool\nNDArray::any_element_is_negative (bool neg_zero) const\n{\n  return (neg_zero ? test_all (octave::math::negative_sign)\n          : do_mx_check<double> (*this, mx_inline_any_negative));\n}\n\nbool\nNDArray::any_element_is_positive (bool neg_zero) const\n{\n  return (neg_zero ? test_all (octave::math::positive_sign)\n          : do_mx_check<double> (*this, mx_inline_any_positive));\n}\n\nbool\nNDArray::any_element_is_nan () const\n{\n  return do_mx_check<double> (*this, mx_inline_any_nan);\n}\n\nbool\nNDArray::any_element_is_inf_or_nan () const\n{\n  return ! do_mx_check<double> (*this, mx_inline_all_finite);\n}\n\nbool\nNDArray::any_element_not_one_or_zero () const\n{\n  return ! test_all (octave::is_one_or_zero);\n}\n\nbool\nNDArray::all_elements_are_zero () const\n{\n  return test_all (octave::is_zero);\n}\n\nbool\nNDArray::all_elements_are_int_or_inf_or_nan () const\n{\n  return test_all (octave::is_int_or_inf_or_nan);\n}\n\n// Return nonzero if any element of M is not an integer.  Also extract\n// the largest and smallest values and return them in MAX_VAL and MIN_VAL.\n\nbool\nNDArray::all_integers (double& max_val, double& min_val) const\n{\n  octave_idx_type nel = numel ();\n\n  if (nel > 0)\n    {\n      max_val = elem (0);\n      min_val = elem (0);\n    }\n  else\n    return false;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      double val = elem (i);\n\n      if (val > max_val)\n        max_val = val;\n\n      if (val < min_val)\n        min_val = val;\n\n      if (! octave::math::is_integer (val))\n        return false;\n    }\n\n  return true;\n}\n\nbool\nNDArray::all_integers () const\n{\n  return test_all (octave::math::is_integer);\n}\n\nbool\nNDArray::too_large_for_float () const\n{\n  return test_any (octave::too_large_for_float);\n}\n\nboolNDArray\nNDArray::all (int dim) const\n{\n  return do_mx_red_op<bool, double> (*this, dim, mx_inline_all);\n}\n\nboolNDArray\nNDArray::any (int dim) const\n{\n  return do_mx_red_op<bool, double> (*this, dim, mx_inline_any);\n}\n\nNDArray\nNDArray::flip (int dim) const\n{\n  return do_mx_flip_op<double, double> (*this, dim, mx_inline_flip);\n}\n\nNDArray\nNDArray::cumprod (int dim, bool nanflag) const\n{\n  return do_mx_cum_op<double, double> (*this, dim, nanflag, mx_inline_cumprod);\n}\n\nNDArray\nNDArray::cumsum (int dim, bool nanflag) const\n{\n  return do_mx_cum_op<double, double> (*this, dim, nanflag, mx_inline_cumsum);\n}\nNDArray\nNDArray::prod (int dim, bool nanflag) const\n{\n  return do_mx_red_op<double, double> (*this, dim, nanflag, mx_inline_prod);\n}\n\nNDArray\nNDArray::sum (int dim, bool nanflag) const\n{\n  return do_mx_red_op<double, double> (*this, dim, nanflag, mx_inline_sum);\n}\n\nNDArray\nNDArray::xsum (int dim, bool nanflag) const\n{\n  return do_mx_red_op<double, double> (*this, dim, nanflag, mx_inline_xsum);\n}\n\nNDArray\nNDArray::sumsq (int dim, bool nanflag) const\n{\n  return do_mx_red_op<double, double> (*this, dim, nanflag, mx_inline_sumsq);\n}\n\nNDArray\nNDArray::max (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<double> (*this, dim, nanflag, realabs, mx_inline_max);\n}\n\nNDArray\nNDArray::max (Array<octave_idx_type>& idx_arg, int dim,\n              bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<double> (*this, idx_arg, dim, nanflag,\n                                  realabs, mx_inline_max);\n}\n\nNDArray\nNDArray::min (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<double> (*this, dim, nanflag, realabs, mx_inline_min);\n}\n\nNDArray\nNDArray::min (Array<octave_idx_type>& idx_arg, int dim,\n              bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<double> (*this, idx_arg, dim, nanflag,\n                                  realabs, mx_inline_min);\n}\n\nNDArray\nNDArray::cummax (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<double> (*this, dim, nanflag,\n                                     realabs, mx_inline_cummax);\n}\n\nNDArray\nNDArray::cummax (Array<octave_idx_type>& idx_arg,\n                 int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<double> (*this, idx_arg, dim, nanflag,\n                                     realabs, mx_inline_cummax);\n}\n\nNDArray\nNDArray::cummin (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<double> (*this, dim, nanflag,\n                                     realabs, mx_inline_cummin);\n}\n\nNDArray\nNDArray::cummin (Array<octave_idx_type>& idx_arg,\n                 int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<double> (*this, idx_arg, dim, nanflag,\n                                     realabs, mx_inline_cummin);\n}\n\nNDArray\nNDArray::diff (octave_idx_type order, int dim) const\n{\n  return do_mx_diff_op<double> (*this, dim, order, mx_inline_diff);\n}\n\nNDArray\nNDArray::concat (const NDArray& rb, const Array<octave_idx_type>& ra_idx)\n{\n  if (rb.numel () > 0)\n    insert (rb, ra_idx);\n  return *this;\n}\n\nComplexNDArray\nNDArray::concat (const ComplexNDArray& rb, const Array<octave_idx_type>& ra_idx)\n{\n  ComplexNDArray retval (*this);\n  if (rb.numel () > 0)\n    retval.insert (rb, ra_idx);\n  return retval;\n}\n\ncharNDArray\nNDArray::concat (const charNDArray& rb, const Array<octave_idx_type>& ra_idx)\n{\n  charNDArray retval (dims ());\n  octave_idx_type nel = numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      double d = elem (i);\n\n      if (octave::math::isnan (d))\n        (*current_liboctave_error_handler)\n          (\"invalid conversion from NaN to character\");\n\n      octave_idx_type ival = octave::math::nint_big (d);\n\n      if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())\n        // FIXME: is there something better to do? Should we warn the user?\n        ival = 0;\n\n      retval.elem (i) = static_cast<char> (ival);\n    }\n\n  if (rb.isempty ())\n    return retval;\n\n  retval.insert (rb, ra_idx);\n  return retval;\n}\n\nNDArray\nreal (const ComplexNDArray& a)\n{\n  return do_mx_unary_op<double, Complex> (a, mx_inline_real);\n}\n\nNDArray\nimag (const ComplexNDArray& a)\n{\n  return do_mx_unary_op<double, Complex> (a, mx_inline_imag);\n}\n\nNDArray&\nNDArray::insert (const NDArray& a, octave_idx_type r, octave_idx_type c)\n{\n  Array<double>::insert (a, r, c);\n  return *this;\n}\n\nNDArray&\nNDArray::insert (const NDArray& a, const Array<octave_idx_type>& ra_idx)\n{\n  Array<double>::insert (a, ra_idx);\n  return *this;\n}\n\nNDArray\nNDArray::abs () const\n{\n  return do_mx_unary_map<double, double, std::abs> (*this);\n}\n\nboolNDArray\nNDArray::isnan () const\n{\n  return do_mx_unary_map<bool, double, octave::math::isnan> (*this);\n}\n\nboolNDArray\nNDArray::isinf () const\n{\n  return do_mx_unary_map<bool, double, octave::math::isinf> (*this);\n}\n\nboolNDArray\nNDArray::isfinite () const\n{\n  return do_mx_unary_map<bool, double, octave::math::isfinite> (*this);\n}\n\nvoid\nNDArray::increment_index (Array<octave_idx_type>& ra_idx,\n                          const dim_vector& dimensions,\n                          int start_dimension)\n{\n  ::increment_index (ra_idx, dimensions, start_dimension);\n}\n\noctave_idx_type\nNDArray::compute_index (Array<octave_idx_type>& ra_idx,\n                        const dim_vector& dimensions)\n{\n  return ::compute_index (ra_idx, dimensions);\n}\n\nNDArray\nNDArray::diag (octave_idx_type k) const\n{\n  return MArray<double>::diag (k);\n}\n\nNDArray\nNDArray::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return MArray<double>::diag (m, n);\n}\n\n// This contains no information on the array structure !!!\nstd::ostream&\noperator << (std::ostream& os, const NDArray& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      os << ' ';\n      octave::write_value<double> (os, a.elem (i));\n      os << \"\\n\";\n    }\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, NDArray& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  if (nel > 0)\n    {\n      double tmp;\n      for (octave_idx_type i = 0; i < nel; i++)\n        {\n          tmp = octave::read_value<double> (is);\n          if (is)\n            a.elem (i) = tmp;\n          else\n            return is;\n        }\n    }\n\n  return is;\n}\n\nMINMAX_FCNS (NDArray, double)\n\nNDS_CMP_OPS (NDArray, double)\nNDS_BOOL_OPS (NDArray, double)\n\nSND_CMP_OPS (double, NDArray)\nSND_BOOL_OPS (double, NDArray)\n\nNDND_CMP_OPS (NDArray, NDArray)\nNDND_BOOL_OPS (NDArray, NDArray)\n\nBSXFUN_STDOP_DEFS_MXLOOP (NDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (NDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, NDArray, mx_inline_pow)\nBSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, ComplexNDArray,\n                       NDArray, mx_inline_pow)\nBSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, NDArray,\n                       ComplexNDArray, mx_inline_pow)\n"
  },
  {
    "path": "liboctave/array/dNDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dNDArray_h)\n#define octave_dNDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"intNDArray-fwd.h\"\n#include \"MArray.h\"\n#include \"bsxfun-decl.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n\nclass OCTAVE_API NDArray : public MArray<double>\n{\npublic:\n\n  NDArray () : MArray<double> () { }\n\n  NDArray (const dim_vector& dv) : MArray<double> (dv) { }\n\n  NDArray (const dim_vector& dv, double val)\n    : MArray<double> (dv, val) { }\n\n  NDArray (const NDArray& a) : MArray<double> (a) { }\n\n  NDArray (const Array<octave_idx_type>& a, bool zero_based = false,\n           bool negative_to_nan = false);\n\n  template <typename U>\n  NDArray (const MArray<U>& a) : MArray<double> (a) { }\n\n  template <typename U>\n  NDArray (const Array<U>& a) : MArray<double> (a) { }\n\n  template <typename U>\n  explicit NDArray (const intNDArray<U>& a) : MArray<double> (a) { }\n\n  NDArray (const charNDArray&);\n\n  NDArray& operator = (const NDArray& a)\n  {\n    MArray<double>::operator = (a);\n    return *this;\n  }\n\n  ~NDArray () = default;\n\n  // unary operations\n\n  OCTAVE_API boolNDArray operator ! () const;\n\n  OCTAVE_API bool any_element_is_negative (bool = false) const;\n  OCTAVE_API bool any_element_is_positive (bool = false) const;\n  OCTAVE_API bool any_element_is_nan () const;\n  OCTAVE_API bool any_element_is_inf_or_nan () const;\n  OCTAVE_API bool any_element_not_one_or_zero () const;\n  OCTAVE_API bool all_elements_are_zero () const;\n  OCTAVE_API bool all_elements_are_int_or_inf_or_nan () const;\n  OCTAVE_API bool all_integers (double& max_val, double& min_val) const;\n  OCTAVE_API bool all_integers () const;\n  OCTAVE_API bool too_large_for_float () const;\n\n  // other operations\n\n  OCTAVE_API boolNDArray all (int dim = -1) const;\n  OCTAVE_API boolNDArray any (int dim = -1) const;\n\n  OCTAVE_API NDArray flip (int dim = -1) const;\n  OCTAVE_API NDArray cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API NDArray cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API NDArray prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API NDArray sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API NDArray xsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API NDArray sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API NDArray\n  concat (const NDArray& rb, const Array<octave_idx_type>& ra_idx);\n  OCTAVE_API ComplexNDArray\n  concat (const ComplexNDArray& rb, const Array<octave_idx_type>& ra_idx);\n  OCTAVE_API charNDArray\n  concat (const charNDArray& rb, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API NDArray\n  max (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API NDArray max (Array<octave_idx_type>& index, int dim = -1,\n                          bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API NDArray\n  min (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API NDArray min (Array<octave_idx_type>& index, int dim = -1,\n                          bool nanflag = true, bool realabs = true) const;\n\n  OCTAVE_API NDArray\n  cummax (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API NDArray cummax (Array<octave_idx_type>& index, int dim = -1,\n                             bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API NDArray\n  cummin (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API NDArray cummin (Array<octave_idx_type>& index, int dim = -1,\n                             bool nanflag = true, bool realabs = true) const;\n\n  OCTAVE_API NDArray diff (octave_idx_type order = 1, int dim = -1) const;\n\n  OCTAVE_API NDArray&\n  insert (const NDArray& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API NDArray&\n  insert (const NDArray& a, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API NDArray abs () const;\n  OCTAVE_API boolNDArray isnan () const;\n  OCTAVE_API boolNDArray isinf () const;\n  OCTAVE_API boolNDArray isfinite () const;\n\n  OCTAVE_API ComplexNDArray fourier (int dim = 1) const;\n  OCTAVE_API ComplexNDArray ifourier (int dim = 1) const;\n\n  OCTAVE_API ComplexNDArray fourier2d () const;\n  OCTAVE_API ComplexNDArray ifourier2d () const;\n\n  OCTAVE_API ComplexNDArray fourierNd () const;\n  OCTAVE_API ComplexNDArray ifourierNd () const;\n\n  friend OCTAVE_API NDArray real (const ComplexNDArray& a);\n  friend OCTAVE_API NDArray imag (const ComplexNDArray& a);\n\n  friend class ComplexNDArray;\n\n  NDArray squeeze () const { return MArray<double>::squeeze (); }\n\n  static OCTAVE_API void\n  increment_index (Array<octave_idx_type>& ra_idx,\n                   const dim_vector& dimensions, int start_dimension = 0);\n\n  static OCTAVE_API octave_idx_type\n  compute_index (Array<octave_idx_type>& ra_idx, const dim_vector& dimensions);\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const NDArray& a);\n  friend OCTAVE_API std::istream& operator >> (std::istream& is, NDArray& a);\n\n  OCTAVE_API NDArray diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API NDArray diag (octave_idx_type m, octave_idx_type n) const;\n\n  NDArray& changesign ()\n  {\n    MArray<double>::changesign ();\n    return *this;\n  }\n\n};\n\n// Publish externally used friend functions.\n\nextern OCTAVE_API NDArray real (const ComplexNDArray& a);\nextern OCTAVE_API NDArray imag (const ComplexNDArray& a);\n\nMINMAX_DECLS (NDArray, double, OCTAVE_API)\n\nNDS_CMP_OP_DECLS (NDArray, double, OCTAVE_API)\nNDS_BOOL_OP_DECLS (NDArray, double, OCTAVE_API)\n\nSND_CMP_OP_DECLS (double, NDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (double, NDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (NDArray, NDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (NDArray, NDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, NDArray, double)\n\nBSXFUN_STDOP_DECLS (NDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (NDArray, OCTAVE_API)\n\nBSXFUN_OP_DECL (pow, NDArray, OCTAVE_API)\nBSXFUN_OP2_DECL (pow, ComplexNDArray, ComplexNDArray,\n                 NDArray, OCTAVE_API)\nBSXFUN_OP2_DECL (pow, ComplexNDArray, NDArray,\n                 ComplexNDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/dRowVector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n#include <type_traits>\n\n#include \"Array-util.h\"\n#include \"blas-proto.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// Row Vector class.\n\nbool\nRowVector::operator == (const RowVector& a) const\n{\n  octave_idx_type len = numel ();\n  if (len != a.numel ())\n    return 0;\n  return mx_inline_equal (len, data (), a.data ());\n}\n\nbool\nRowVector::operator != (const RowVector& a) const\n{\n  return !(*this == a);\n}\n\nRowVector&\nRowVector::insert (const RowVector& a, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (c < 0 || c + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nRowVector&\nRowVector::fill (double val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nRowVector&\nRowVector::fill (double val, octave_idx_type c1, octave_idx_type c2)\n{\n  octave_idx_type len = numel ();\n\n  if (c1 < 0 || c2 < 0 || c1 >= len || c2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = c1; i <= c2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nRowVector\nRowVector::append (const RowVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nc_insert = len;\n  RowVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nc_insert);\n  return retval;\n}\n\nColumnVector\nRowVector::transpose () const\n{\n  return MArray<double>::transpose ();\n}\n\nRowVector\nreal (const ComplexRowVector& a)\n{\n  return do_mx_unary_op<double, Complex> (a, mx_inline_real);\n}\n\nRowVector\nimag (const ComplexRowVector& a)\n{\n  return do_mx_unary_op<double, Complex> (a, mx_inline_imag);\n}\n\nRowVector\nRowVector::extract (octave_idx_type c1, octave_idx_type c2) const\n{\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  RowVector result (new_c);\n\n  for (octave_idx_type i = 0; i < new_c; i++)\n    result.xelem (i) = elem (c1+i);\n\n  return result;\n}\n\nRowVector\nRowVector::extract_n (octave_idx_type r1, octave_idx_type n) const\n{\n  RowVector result (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    result.xelem (i) = elem (r1+i);\n\n  return result;\n}\n\n// row vector by matrix -> row vector\n\nRowVector\noperator * (const RowVector& v, const Matrix& a)\n{\n  RowVector retval;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  F77_INT a_nr = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (a_nr != len)\n    octave::err_nonconformant (\"operator *\", 1, len, a_nr, a_nc);\n\n  if (len == 0)\n    retval.resize (a_nc, 0.0);\n  else\n    {\n      // Transpose A to form A'*x == (x'*A)'\n\n      F77_INT ld = a_nr;\n\n      retval.resize (a_nc);\n      double *y = retval.rwdata ();\n\n      F77_XFCN (dgemv, DGEMV, (F77_CONST_CHAR_ARG2 (\"T\", 1),\n                               a_nr, a_nc, 1.0, a.data (),\n                               ld, v.data (), 1, 0.0, y, 1\n                               F77_CHAR_ARG_LEN (1)));\n    }\n\n  return retval;\n}\n\n// other operations\n\ndouble\nRowVector::min () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0;\n\n  double res = elem (0);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (elem (i) < res)\n      res = elem (i);\n\n  return res;\n}\n\ndouble\nRowVector::max () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0;\n\n  double res = elem (0);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (elem (i) > res)\n      res = elem (i);\n\n  return res;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const RowVector& a)\n{\n//  int field_width = os.precision () + 7;\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    os << ' ' /* setw (field_width) */ << a.elem (i);\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, RowVector& a)\n{\n  octave_idx_type len = a.numel ();\n\n  if (len > 0)\n    {\n      double tmp;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          is >> tmp;\n          if (is)\n            a.elem (i) = tmp;\n          else\n            break;\n        }\n    }\n  return is;\n}\n\n// other operations\n\nRowVector\nlinspace (double x1, double x2, octave_idx_type n_in)\n{\n  RowVector retval;\n\n  if (n_in < 1)\n    return retval;\n  else if (n_in == 1)\n    {\n      retval.resize (1, x2);\n      return retval;\n    }\n  else if (x1 == x2)\n    {\n      retval.resize (n_in, x2);\n      return retval;\n    }\n\n  // Use unsigned type (guaranteed n_in > 1 at this point) so that divisions\n  // by 2 can be replaced by compiler with shift right instructions.\n  typedef std::make_unsigned<octave_idx_type>::type unsigned_octave_idx_type;\n\n  unsigned_octave_idx_type n = n_in;\n\n  // Set endpoints, rather than calculate, for maximum accuracy.\n  retval.clear (n);\n  retval.xelem (0) = x1;\n  retval.xelem (n-1) = x2;\n\n  // Construct linspace symmetrically from both ends.\n  bool isnan_delta = false;\n  double delta = (x2 - x1) / (n - 1);\n  if (octave::math::isinf (delta))\n    {\n      delta = octave::numeric_limits<double>::NaN ();\n      isnan_delta = true;\n    }\n\n  unsigned_octave_idx_type n2 = n/2;\n  for (unsigned_octave_idx_type i = 1; i < n2; i++)\n    {\n      retval.xelem (i) = x1 + i*delta;\n      retval.xelem (n-1-i) = x2 - i*delta;\n    }\n  if (n % 2 == 1)  // Middle element if number of elements is odd.\n    {\n      if (x1 == -x2)\n        retval.xelem (n2) = 0;\n      else if (isnan_delta)\n        retval.xelem (n2) = octave::numeric_limits<double>::NaN ();\n      else\n        retval.xelem (n2) = (x1 + x2) / 2;\n    }\n\n  return retval;\n}\n\n// row vector by column vector -> scalar\n\ndouble\noperator * (const RowVector& v, const ColumnVector& a)\n{\n  double retval = 0.0;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator *\", len, a_len);\n\n  if (len != 0)\n    F77_FUNC (xddot, XDDOT) (len, v.data (), 1, a.data (), 1, retval);\n\n  return retval;\n}\n\nComplex\noperator * (const RowVector& v, const ComplexColumnVector& a)\n{\n  ComplexRowVector tmp (v);\n  return tmp * a;\n}\n"
  },
  {
    "path": "liboctave/array/dRowVector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dRowVector_h)\n#define octave_dRowVector_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API RowVector : public MArray<double>\n{\npublic:\n\n  RowVector () : MArray<double> (dim_vector (1, 0)) { }\n\n  explicit RowVector (octave_idx_type n)\n    : MArray<double> (dim_vector (1, n)) { }\n\n  explicit RowVector (const dim_vector& dv) : MArray<double> (dv.as_row ()) { }\n\n  RowVector (octave_idx_type n, double val)\n    : MArray<double> (dim_vector (1, n), val) { }\n\n  RowVector (const RowVector& a) : MArray<double> (a) { }\n\n  RowVector (const MArray<double>& a) : MArray<double> (a.as_row ()) { }\n\n  RowVector (const Array<double>& a) : MArray<double> (a.as_row ()) { }\n\n  RowVector& operator = (const RowVector& a)\n  {\n    MArray<double>::operator = (a);\n    return *this;\n  }\n\n  ~RowVector () = default;\n\n  OCTAVE_API bool operator == (const RowVector& a) const;\n  OCTAVE_API bool operator != (const RowVector& a) const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API RowVector& insert (const RowVector& a, octave_idx_type c);\n\n  OCTAVE_API RowVector& fill (double val);\n  OCTAVE_API RowVector& fill (double val, octave_idx_type c1, octave_idx_type c2);\n\n  OCTAVE_API RowVector append (const RowVector& a) const;\n\n  OCTAVE_API ColumnVector transpose () const;\n\n  friend OCTAVE_API RowVector real (const ComplexRowVector& a);\n  friend OCTAVE_API RowVector imag (const ComplexRowVector& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API RowVector extract (octave_idx_type c1, octave_idx_type c2) const;\n\n  OCTAVE_API RowVector extract_n (octave_idx_type c1, octave_idx_type n) const;\n\n  // row vector by matrix -> row vector\n\n  friend OCTAVE_API RowVector operator * (const RowVector& a, const Matrix& b);\n\n  // other operations\n\n  OCTAVE_API double min () const;\n  OCTAVE_API double max () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream& operator << (std::ostream& os,\n                                               const RowVector& a);\n  friend OCTAVE_API std::istream& operator >> (std::istream& is, RowVector& a);\n\n  void resize (octave_idx_type n, const double& rfv = 0)\n  {\n    Array<double>::resize (dim_vector (1, n), rfv);\n  }\n\n  void clear (octave_idx_type n)\n  { Array<double>::clear (1, n); }\n\n};\n\n// row vector by column vector -> scalar\n\nOCTAVE_API double operator * (const RowVector& a, const ColumnVector& b);\n\nOCTAVE_API Complex operator * (const RowVector& a,\n                               const ComplexColumnVector& b);\n\n// other operations\n\nOCTAVE_API RowVector linspace (double x1, double x2, octave_idx_type n);\n\nMARRAY_FORWARD_DEFS (MArray, RowVector, double)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/dSparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"dRowVector.h\"\n#include \"lapack-proto.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"oct-locbuf.h\"\n#include \"quit.h\"\n\n#include \"dDiagMatrix.h\"\n#include \"CSparse.h\"\n#include \"boolSparse.h\"\n#include \"dSparse.h\"\n#include \"oct-spparms.h\"\n#include \"sparse-lu.h\"\n#include \"MatrixType.h\"\n#include \"oct-sparse.h\"\n#include \"sparse-util.h\"\n#include \"sparse-chol.h\"\n#include \"sparse-qr.h\"\n\n#include \"Sparse-op-defs.h\"\n\n#include \"Sparse-diag-op-defs.h\"\n\n#include \"Sparse-perm-op-defs.h\"\n\n#include \"sparse-dmsolve.h\"\n\nSparseMatrix::SparseMatrix (const SparseBoolMatrix& a)\n  : MSparse<double> (a.rows (), a.cols (), a.nnz ())\n{\n  octave_idx_type nc = cols ();\n  octave_idx_type nz = a.nnz ();\n\n  for (octave_idx_type i = 0; i < nc + 1; i++)\n    cidx (i) = a.cidx (i);\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    {\n      data (i) = a.data (i);\n      ridx (i) = a.ridx (i);\n    }\n}\n\nSparseMatrix::SparseMatrix (const DiagMatrix& a)\n  : MSparse<double> (a.rows (), a.cols (), a.length ())\n{\n  octave_idx_type j = 0;\n  octave_idx_type l = a.length ();\n  for (octave_idx_type i = 0; i < l; i++)\n    {\n      cidx (i) = j;\n      if (a(i, i) != 0.0)\n        {\n          data (j) = a(i, i);\n          ridx (j) = i;\n          j++;\n        }\n    }\n  for (octave_idx_type i = l; i <= a.cols (); i++)\n    cidx (i) = j;\n}\n\nbool\nSparseMatrix::operator == (const SparseMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz = nnz ();\n  octave_idx_type nr_a = a.rows ();\n  octave_idx_type nc_a = a.cols ();\n  octave_idx_type nz_a = a.nnz ();\n\n  if (nr != nr_a || nc != nc_a || nz != nz_a)\n    return false;\n\n  for (octave_idx_type i = 0; i < nc + 1; i++)\n    if (cidx (i) != a.cidx (i))\n      return false;\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    if (data (i) != a.data (i) || ridx (i) != a.ridx (i))\n      return false;\n\n  return true;\n}\n\nbool\nSparseMatrix::operator != (const SparseMatrix& a) const\n{\n  return !(*this == a);\n}\n\nbool\nSparseMatrix::issymmetric () const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr == nc && nr > 0)\n    {\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n            {\n              octave_idx_type ri = ridx (i);\n\n              if (ri != j)\n                {\n                  bool found = false;\n\n                  for (octave_idx_type k = cidx (ri); k < cidx (ri+1); k++)\n                    {\n                      if (ridx (k) == j)\n                        {\n                          if (data (i) == data (k))\n                            found = true;\n                          break;\n                        }\n                    }\n\n                  if (! found)\n                    return false;\n                }\n            }\n        }\n\n      return true;\n    }\n\n  return false;\n}\n\nSparseMatrix&\nSparseMatrix::insert (const SparseMatrix& a,\n                      octave_idx_type r, octave_idx_type c)\n{\n  MSparse<double>::insert (a, r, c);\n  return *this;\n}\n\nSparseMatrix&\nSparseMatrix::insert (const SparseMatrix& a, const Array<octave_idx_type>& indx)\n{\n  MSparse<double>::insert (a, indx);\n  return *this;\n}\n\nSparseMatrix\nSparseMatrix::max (int dim, bool nanflag, bool realabs) const\n{\n  Array<octave_idx_type> dummy_idx;\n  return max (dummy_idx, dim, nanflag, realabs);\n}\n\nSparseMatrix\nSparseMatrix::max (Array<octave_idx_type>& idx_arg, int dim,\n                   bool nanflag, bool realabs) const\n{\n  SparseMatrix result;\n  const dim_vector& dv = dims ();\n  octave_idx_type nr = dv(0);\n  octave_idx_type nc = dv(1);\n\n  if (dim >= dv.ndims ())\n    {\n      idx_arg.resize (dim_vector (nr, nc), 0);\n      return *this;\n    }\n\n  if (dim < 0)\n    dim = dv.first_non_singleton ();\n\n  if (dim == 0)\n    {\n      idx_arg.resize (dim_vector (nr == 0 ? 0 : 1, nc), 0);\n\n      if (nr == 0 || nc == 0 || dim >= dv.ndims ())\n        return SparseMatrix (nr == 0 ? 0 : 1, nc);\n\n      octave_idx_type nel = 0;\n      if (realabs)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double tmp_max = octave::numeric_limits<double>::NaN ();\n              octave_idx_type idx_j = 0;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  if (ridx (i) != idx_j)\n                    break;\n                  else\n                    idx_j++;\n                }\n\n              if (idx_j != nr)\n                tmp_max = 0.;\n\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  double tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (octave::math::isnan (tmp_max) || tmp > tmp_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                    }\n\n                }\n\n              if (octave::math::isnan (tmp_max) && ! nanflag)\n                idx_arg.elem (j) = idx_j;\n              else\n                idx_arg.elem (j) = (octave::math::isnan (tmp_max) ? 0 : idx_j);\n              if (tmp_max != 0.)\n                nel++;\n            }\n        }\n      else\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double tmp_max = octave::numeric_limits<double>::NaN ();\n              double abs_max = octave::numeric_limits<double>::NaN ();\n              octave_idx_type idx_j = 0;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  if (ridx (i) != idx_j)\n                    break;\n                  else\n                    idx_j++;\n                }\n\n              if (idx_j != nr)\n                {\n                  tmp_max = 0.;\n                  abs_max = 0.;\n                }\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  double tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n\n                  double abs_tmp = std::abs (tmp);\n                  if (octave::math::isnan (abs_max) || abs_tmp > abs_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      abs_max = abs_tmp;\n                    }\n                  else if (abs_tmp == abs_max && tmp > tmp_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      abs_max = abs_tmp;\n                    }\n\n                }\n\n              if (octave::math::isnan (tmp_max) && ! nanflag)\n                idx_arg.elem (j) = idx_j;\n              else\n                idx_arg.elem (j) = (octave::math::isnan (tmp_max) ? 0 : idx_j);\n              if (tmp_max != 0.)\n                nel++;\n            }\n        }\n\n      result = SparseMatrix (1, nc, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          double tmp = elem (idx_arg(j), j);\n          if (tmp != 0.)\n            {\n              result.xdata (ii) = tmp;\n              result.xridx (ii++) = 0;\n            }\n          result.xcidx (j+1) = ii;\n\n        }\n    }\n  else\n    {\n      idx_arg.resize (dim_vector (nr, nc == 0 ? 0 : 1), 0);\n\n      if (nr == 0 || nc == 0 || dim >= dv.ndims ())\n        return SparseMatrix (nr, nc == 0 ? 0 : 1);\n\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, found, nr);\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        found[i] = 0;\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n          if (found[ridx (i)] == -j)\n            found[ridx (i)] = -j - 1;\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        if (found[i] > -nc && found[i] < 0)\n          idx_arg.elem (i) = -found[i];\n\n      if (realabs)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  octave_idx_type ir = ridx (i);\n                  octave_idx_type ix = idx_arg.elem (ir);\n                  double tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_arg.elem (ir) = j;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (ix == -1 || octave::math::isnan (elem (ir, ix)) ||\n                           tmp > elem (ir, ix))\n                    idx_arg.elem (ir) = j;\n                }\n            }\n        }\n      else\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  octave_idx_type ir = ridx (i);\n                  octave_idx_type ix = idx_arg.elem (ir);\n                  double tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_arg.elem (ir) = j;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (ix == -1 || octave::math::isnan (elem (ir, ix)) ||\n                           std::abs (tmp) > std::abs (elem (ir, ix)))\n                    idx_arg.elem (ir) = j;\n                  else if (std::abs (tmp) == std::abs (elem (ir, ix)) &&\n                           tmp > elem (ir, ix))\n                    idx_arg.elem (ir) = j;\n                }\n            }\n        }\n\n      octave_idx_type nel = 0;\n      for (octave_idx_type j = 0; j < nr; j++)\n        if (idx_arg.elem (j) == -1 || elem (j, idx_arg.elem (j)) != 0.)\n          nel++;\n\n      result = SparseMatrix (nr, 1, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      result.xcidx (1) = nel;\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          if (idx_arg(j) == -1)\n            {\n              idx_arg(j) = 0;\n              result.xdata (ii) = octave::numeric_limits<double>::NaN ();\n              result.xridx (ii++) = j;\n            }\n          else\n            {\n              double tmp = elem (j, idx_arg(j));\n              if (tmp != 0.)\n                {\n                  result.xdata (ii) = tmp;\n                  result.xridx (ii++) = j;\n                }\n            }\n        }\n    }\n\n  return result;\n}\n\nSparseMatrix\nSparseMatrix::min (int dim, bool nanflag, bool realabs) const\n{\n  Array<octave_idx_type> dummy_idx;\n  return min (dummy_idx, dim, nanflag, realabs);\n}\n\nSparseMatrix\nSparseMatrix::min (Array<octave_idx_type>& idx_arg, int dim,\n                   bool nanflag, bool realabs) const\n{\n  SparseMatrix result;\n  const dim_vector& dv = dims ();\n  octave_idx_type nr = dv(0);\n  octave_idx_type nc = dv(1);\n\n  if (dim >= dv.ndims ())\n    {\n      idx_arg.resize (dim_vector (nr, nc), 0);\n      return *this;\n    }\n\n  if (dim < 0)\n    dim = dv.first_non_singleton ();\n\n  if (dim == 0)\n    {\n      idx_arg.resize (dim_vector (nr == 0 ? 0 : 1, nc), 0);\n\n      if (nr == 0 || nc == 0 || dim >= dv.ndims ())\n        return SparseMatrix (nr == 0 ? 0 : 1, nc);\n\n      octave_idx_type nel = 0;\n      if (realabs)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double tmp_max = octave::numeric_limits<double>::NaN ();\n              octave_idx_type idx_j = 0;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  if (ridx (i) != idx_j)\n                    break;\n                  else\n                    idx_j++;\n                }\n\n              if (idx_j != nr)\n                tmp_max = 0.;\n\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  double tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (octave::math::isnan (tmp_max) || tmp < tmp_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                    }\n\n                }\n\n              if (octave::math::isnan (tmp_max) && ! nanflag)\n                idx_arg.elem (j) = idx_j;\n              else\n                idx_arg.elem (j) = (octave::math::isnan (tmp_max) ? 0 : idx_j);\n              if (tmp_max != 0.)\n                nel++;\n            }\n        }\n      else\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double tmp_max = octave::numeric_limits<double>::NaN ();\n              double abs_max = octave::numeric_limits<double>::NaN ();\n              octave_idx_type idx_j = 0;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  if (ridx (i) != idx_j)\n                    break;\n                  else\n                    idx_j++;\n                }\n\n              if (idx_j != nr)\n                {\n                  tmp_max = 0.;\n                  abs_max = 0.;\n                }\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  double tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n\n                  double abs_tmp = std::abs (tmp);\n                  if (octave::math::isnan (abs_max) || abs_tmp < abs_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      abs_max = abs_tmp;\n                    }\n                  else if (abs_tmp == abs_max && tmp < tmp_max)\n                    {\n                      idx_j = ridx (i);\n                      tmp_max = tmp;\n                      abs_max = abs_tmp;\n                    }\n\n                }\n\n              if (octave::math::isnan (tmp_max) && ! nanflag)\n                idx_arg.elem (j) = idx_j;\n              else\n                idx_arg.elem (j) = (octave::math::isnan (tmp_max) ? 0 : idx_j);\n              if (tmp_max != 0.)\n                nel++;\n            }\n        }\n\n      result = SparseMatrix (1, nc, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          double tmp = elem (idx_arg(j), j);\n          if (tmp != 0.)\n            {\n              result.xdata (ii) = tmp;\n              result.xridx (ii++) = 0;\n            }\n          result.xcidx (j+1) = ii;\n\n        }\n    }\n  else\n    {\n      idx_arg.resize (dim_vector (nr, nc == 0 ? 0 : 1), 0);\n\n      if (nr == 0 || nc == 0 || dim >= dv.ndims ())\n        return SparseMatrix (nr, nc == 0 ? 0 : 1);\n\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, found, nr);\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        found[i] = 0;\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n          if (found[ridx (i)] == -j)\n            found[ridx (i)] = -j - 1;\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        if (found[i] > -nc && found[i] < 0)\n          idx_arg.elem (i) = -found[i];\n\n      if (realabs)\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  octave_idx_type ir = ridx (i);\n                  octave_idx_type ix = idx_arg.elem (ir);\n                  double tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_arg.elem (ir) = j;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (ix == -1 || octave::math::isnan (elem (ir, ix)) ||\n                           tmp < elem (ir, ix))\n                    idx_arg.elem (ir) = j;\n                }\n            }\n        }\n      else\n        {\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                {\n                  octave_idx_type ir = ridx (i);\n                  octave_idx_type ix = idx_arg.elem (ir);\n                  double tmp = data (i);\n\n                  if (octave::math::isnan (tmp) && ! nanflag)\n                    {\n                      idx_arg.elem (ir) = j;\n                      break;\n                    }\n                  else if (octave::math::isnan (tmp))\n                    continue;\n                  else if (ix == -1 || octave::math::isnan (elem (ir, ix)) ||\n                           std::abs (tmp) < std::abs (elem (ir, ix)))\n                    idx_arg.elem (ir) = j;\n                  else if (std::abs (tmp) == std::abs (elem (ir, ix)) &&\n                           tmp < elem (ir, ix))\n                    idx_arg.elem (ir) = j;\n                }\n            }\n        }\n\n      octave_idx_type nel = 0;\n      for (octave_idx_type j = 0; j < nr; j++)\n        if (idx_arg.elem (j) == -1 || elem (j, idx_arg.elem (j)) != 0.)\n          nel++;\n\n      result = SparseMatrix (nr, 1, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      result.xcidx (1) = nel;\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          if (idx_arg(j) == -1)\n            {\n              idx_arg(j) = 0;\n              result.xdata (ii) = octave::numeric_limits<double>::NaN ();\n              result.xridx (ii++) = j;\n            }\n          else\n            {\n              double tmp = elem (j, idx_arg(j));\n              if (tmp != 0.)\n                {\n                  result.xdata (ii) = tmp;\n                  result.xridx (ii++) = j;\n                }\n            }\n        }\n    }\n\n  return result;\n}\n\n/*\n\n%!assert (max (max (speye (65536))), sparse (1))\n%!assert (min (min (speye (65536))), sparse (0))\n%!assert (size (max (sparse (8, 0), [], 1)), [1, 0])\n%!assert (size (max (sparse (8, 0), [], 2)), [8, 0])\n%!assert (size (max (sparse (0, 8), [], 1)), [0, 8])\n%!assert (size (max (sparse (0, 8), [], 2)), [0, 1])\n%!assert (size (min (sparse (8, 0), [], 1)), [1, 0])\n%!assert (size (min (sparse (8, 0), [], 2)), [8, 0])\n%!assert (size (min (sparse (0, 8), [], 1)), [0, 8])\n%!assert (size (min (sparse (0, 8), [], 2)), [0, 1])\n\n*/\n\nRowVector\nSparseMatrix::row (octave_idx_type i) const\n{\n  octave_idx_type nc = columns ();\n  RowVector retval (nc, 0);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type k = cidx (j); k < cidx (j+1); k++)\n      {\n        if (ridx (k) == i)\n          {\n            retval(j) = data (k);\n            break;\n          }\n      }\n\n  return retval;\n}\n\nColumnVector\nSparseMatrix::column (octave_idx_type i) const\n{\n  octave_idx_type nr = rows ();\n  ColumnVector retval (nr, 0);\n\n  for (octave_idx_type k = cidx (i); k < cidx (i+1); k++)\n    retval(ridx (k)) = data (k);\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::concat (const SparseMatrix& rb,\n                      const Array<octave_idx_type>& ra_idx)\n{\n  // Don't use numel to avoid all possibility of an overflow\n  if (rb.rows () > 0 && rb.cols () > 0)\n    insert (rb, ra_idx(0), ra_idx(1));\n  return *this;\n}\n\nSparseComplexMatrix\nSparseMatrix::concat (const SparseComplexMatrix& rb,\n                      const Array<octave_idx_type>& ra_idx)\n{\n  SparseComplexMatrix retval (*this);\n  if (rb.rows () > 0 && rb.cols () > 0)\n    retval.insert (rb, ra_idx(0), ra_idx(1));\n  return retval;\n}\n\nSparseMatrix\nreal (const SparseComplexMatrix& a)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n  octave_idx_type nz = a.nnz ();\n  SparseMatrix r (nr, nc, nz);\n\n  for (octave_idx_type i = 0; i < nc +1; i++)\n    r.cidx (i) = a.cidx (i);\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    {\n      r.data (i) = std::real (a.data (i));\n      r.ridx (i) = a.ridx (i);\n    }\n\n  r.maybe_compress (true);\n  return r;\n}\n\nSparseMatrix\nimag (const SparseComplexMatrix& a)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n  octave_idx_type nz = a.nnz ();\n  SparseMatrix r (nr, nc, nz);\n\n  for (octave_idx_type i = 0; i < nc +1; i++)\n    r.cidx (i) = a.cidx (i);\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    {\n      r.data (i) = std::imag (a.data (i));\n      r.ridx (i) = a.ridx (i);\n    }\n\n  r.maybe_compress (true);\n  return r;\n}\n\n/*\n\n%!assert (nnz (real (sparse ([1i,1]))), 1)\n%!assert (nnz (real (sparse ([1i,1]))), 1)\n\n*/\n\n// Local function to check if matrix is singular based on rcond.\nstatic inline\nbool\nis_singular (const double rcond)\n{\n  return (std::abs (rcond) <= std::numeric_limits<double>::epsilon ());\n}\n\nSparseMatrix\nSparseMatrix::inverse () const\n{\n  octave_idx_type info;\n  double rcond;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcond, 0, 0);\n}\n\nSparseMatrix\nSparseMatrix::inverse (MatrixType& mattype) const\n{\n  octave_idx_type info;\n  double rcond;\n  return inverse (mattype, info, rcond, 0, 0);\n}\n\nSparseMatrix\nSparseMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const\n{\n  double rcond;\n  return inverse (mattype, info, rcond, 0, 0);\n}\n\nSparseMatrix\nSparseMatrix::dinverse (MatrixType& mattype, octave_idx_type& info,\n                        double& rcond, const bool,\n                        const bool calccond) const\n{\n  SparseMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  info = 0;\n\n  if (nr == 0 || nc == 0 || nr != nc)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  // Print spparms(\"spumoni\") info if requested\n  int typ = mattype.type ();\n  mattype.info ();\n\n  if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n    (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n  if (typ == MatrixType::Permuted_Diagonal)\n    retval = transpose ();\n  else\n    retval = *this;\n\n  // Force make_unique to be called\n  double *v = retval.data ();\n\n  if (calccond)\n    {\n      double dmax = 0.;\n      double dmin = octave::numeric_limits<double>::Inf ();\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          double tmp = fabs (v[i]);\n          if (tmp > dmax)\n            dmax = tmp;\n          if (tmp < dmin)\n            dmin = tmp;\n        }\n      rcond = dmin / dmax;\n    }\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    v[i] = 1.0 / v[i];\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::tinverse (MatrixType& mattype, octave_idx_type& info,\n                        double& rcond, const bool,\n                        const bool calccond) const\n{\n  SparseMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  info = 0;\n\n  if (nr == 0 || nc == 0 || nr != nc)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  // Print spparms(\"spumoni\") info if requested\n  int typ = mattype.type ();\n  mattype.info ();\n\n  if (typ != MatrixType::Upper && typ != MatrixType::Permuted_Upper\n      && typ != MatrixType::Lower && typ != MatrixType::Permuted_Lower)\n    (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n  double anorm = 0.;\n  double ainvnorm = 0.;\n\n  if (calccond)\n    {\n      // Calculate the 1-norm of matrix for rcond calculation\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          double atmp = 0.;\n          for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n            atmp += fabs (data (i));\n          if (atmp > anorm)\n            anorm = atmp;\n        }\n    }\n\n  if (typ == MatrixType::Upper || typ == MatrixType::Lower)\n    {\n      octave_idx_type nz = nnz ();\n      octave_idx_type cx = 0;\n      octave_idx_type nz2 = nz;\n      retval = SparseMatrix (nr, nc, nz2);\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_quit ();\n          // place the 1 in the identity position\n          octave_idx_type cx_colstart = cx;\n\n          if (cx == nz2)\n            {\n              nz2 *= 2;\n              retval.change_capacity (nz2);\n            }\n\n          retval.xcidx (i) = cx;\n          retval.xridx (cx) = i;\n          retval.xdata (cx) = 1.0;\n          cx++;\n\n          // iterate across columns of input matrix\n          for (octave_idx_type j = i+1; j < nr; j++)\n            {\n              double v = 0.;\n              // iterate to calculate sum\n              octave_idx_type colXp = retval.xcidx (i);\n              octave_idx_type colUp = cidx (j);\n              octave_idx_type rpX, rpU;\n\n              if (cidx (j) == cidx (j+1))\n                (*current_liboctave_error_handler) (\"division by zero\");\n\n              do\n                {\n                  octave_quit ();\n                  rpX = retval.xridx (colXp);\n                  rpU = ridx (colUp);\n\n                  if (rpX < rpU)\n                    colXp++;\n                  else if (rpX > rpU)\n                    colUp++;\n                  else\n                    {\n                      v -= retval.xdata (colXp) * data (colUp);\n                      colXp++;\n                      colUp++;\n                    }\n                }\n              while (rpX < j && rpU < j && colXp < cx && colUp < nz);\n\n              // get A(m,m)\n              if (typ == MatrixType::Upper)\n                colUp = cidx (j+1) - 1;\n              else\n                colUp = cidx (j);\n              double pivot = data (colUp);\n              if (pivot == 0. || ridx (colUp) != j)\n                (*current_liboctave_error_handler) (\"division by zero\");\n\n              if (v != 0.)\n                {\n                  if (cx == nz2)\n                    {\n                      nz2 *= 2;\n                      retval.change_capacity (nz2);\n                    }\n\n                  retval.xridx (cx) = j;\n                  retval.xdata (cx) = v / pivot;\n                  cx++;\n                }\n            }\n\n          // get A(m,m)\n          octave_idx_type colUp;\n          if (typ == MatrixType::Upper)\n            colUp = cidx (i+1) - 1;\n          else\n            colUp = cidx (i);\n          double pivot = data (colUp);\n          if (pivot == 0. || ridx (colUp) != i)\n            (*current_liboctave_error_handler) (\"division by zero\");\n\n          if (pivot != 1.0)\n            for (octave_idx_type j = cx_colstart; j < cx; j++)\n              retval.xdata (j) /= pivot;\n        }\n      retval.xcidx (nr) = cx;\n      retval.maybe_compress ();\n    }\n  else\n    {\n      octave_idx_type nz = nnz ();\n      octave_idx_type cx = 0;\n      octave_idx_type nz2 = nz;\n      retval = SparseMatrix (nr, nc, nz2);\n\n      OCTAVE_LOCAL_BUFFER (double, work, nr);\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nr);\n\n      octave_idx_type *perm = mattype.triangular_perm ();\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          for (octave_idx_type i = 0; i < nr; i++)\n            rperm[perm[i]] = i;\n        }\n      else\n        {\n          for (octave_idx_type i = 0; i < nr; i++)\n            rperm[i] = perm[i];\n          for (octave_idx_type i = 0; i < nr; i++)\n            perm[rperm[i]] = i;\n        }\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_quit ();\n          octave_idx_type iidx = rperm[i];\n\n          for (octave_idx_type j = 0; j < nr; j++)\n            work[j] = 0.;\n\n          // place the 1 in the identity position\n          work[iidx] = 1.0;\n\n          // iterate across columns of input matrix\n          for (octave_idx_type j = iidx+1; j < nr; j++)\n            {\n              double v = 0.;\n              octave_idx_type jidx = perm[j];\n              // iterate to calculate sum\n              for (octave_idx_type k = cidx (jidx);\n                   k < cidx (jidx+1); k++)\n                {\n                  octave_quit ();\n                  v -= work[ridx (k)] * data (k);\n                }\n\n              // get A(m,m)\n              double pivot;\n              if (typ == MatrixType::Permuted_Upper)\n                pivot = data (cidx (jidx+1) - 1);\n              else\n                pivot = data (cidx (jidx));\n              if (pivot == 0.)\n                (*current_liboctave_error_handler) (\"division by zero\");\n\n              work[j] = v / pivot;\n            }\n\n          // get A(m,m)\n          octave_idx_type colUp;\n          if (typ == MatrixType::Permuted_Upper)\n            colUp = cidx (perm[iidx]+1) - 1;\n          else\n            colUp = cidx (perm[iidx]);\n\n          double pivot = data (colUp);\n          if (pivot == 0.)\n            (*current_liboctave_error_handler) (\"division by zero\");\n\n          octave_idx_type new_cx = cx;\n          for (octave_idx_type j = iidx; j < nr; j++)\n            if (work[j] != 0.0)\n              {\n                new_cx++;\n                if (pivot != 1.0)\n                  work[j] /= pivot;\n              }\n\n          if (cx < new_cx)\n            {\n              nz2 = (2*nz2 < new_cx ? new_cx : 2*nz2);\n              retval.change_capacity (nz2);\n            }\n\n          retval.xcidx (i) = cx;\n          for (octave_idx_type j = iidx; j < nr; j++)\n            if (work[j] != 0.)\n              {\n                retval.xridx (cx) = j;\n                retval.xdata (cx++) = work[j];\n              }\n        }\n\n      retval.xcidx (nr) = cx;\n      retval.maybe_compress ();\n    }\n\n  if (calccond)\n    {\n      // Calculate the 1-norm of inverse matrix for rcond calculation\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          double atmp = 0.;\n          for (octave_idx_type i = retval.cidx (j);\n               i < retval.cidx (j+1); i++)\n            atmp += fabs (retval.data (i));\n          if (atmp > ainvnorm)\n            ainvnorm = atmp;\n        }\n\n      rcond = 1. / ainvnorm / anorm;\n    }\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::inverse (MatrixType& mattype, octave_idx_type& info,\n                       double& rcond, bool, bool calc_cond) const\n{\n  if (nnz () == 0)\n    {\n      (*current_liboctave_error_handler)\n        (\"inverse of the null matrix not defined\");\n    }\n\n  int typ = mattype.type (false);\n  SparseMatrix ret;\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    ret = dinverse (mattype, info, rcond, true, calc_cond);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    ret = tinverse (mattype, info, rcond, true, calc_cond).transpose ();\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    {\n      MatrixType newtype = mattype.transpose ();\n      ret = transpose ().tinverse (newtype, info, rcond, true, calc_cond);\n    }\n  else\n    {\n      if (mattype.ishermitian ())\n        {\n          MatrixType tmp_typ (MatrixType::Upper);\n          octave::math::sparse_chol<SparseMatrix> fact (*this, info, false);\n          rcond = fact.rcond ();\n          if (info == 0)\n            {\n              double rcond2;\n              SparseMatrix Q = fact.Q ();\n              SparseMatrix InvL = fact.L ().transpose ().tinverse (tmp_typ,\n                                  info, rcond2, true, false);\n              ret = Q * InvL.transpose () * InvL * Q.transpose ();\n            }\n          else\n            {\n              // Matrix is either singular or not positive definite\n              mattype.mark_as_unsymmetric ();\n            }\n        }\n\n      if (! mattype.ishermitian ())\n        {\n          octave_idx_type n = rows ();\n          ColumnVector Qinit(n);\n          for (octave_idx_type i = 0; i < n; i++)\n            Qinit(i) = i;\n\n          MatrixType tmp_typ (MatrixType::Upper);\n          octave::math::sparse_lu<SparseMatrix> fact (*this,\n                                                      Qinit, Matrix (),\n                                                      false, false);\n          rcond = fact.rcond ();\n          if (rcond == 0.0)\n            {\n              // Return all Inf matrix with sparsity pattern of input.\n              octave_idx_type nz = nnz ();\n              ret = SparseMatrix (rows (), cols (), nz);\n              std::fill (ret.xdata (), ret.xdata () + nz,\n                         octave::numeric_limits<double>::Inf ());\n              std::copy_n (ridx (), nz, ret.xridx ());\n              std::copy_n (cidx (), cols () + 1, ret.xcidx ());\n\n              return ret;\n            }\n\n          double rcond2;\n          SparseMatrix InvL = fact.L ().transpose ().tinverse (tmp_typ,\n                              info, rcond2, true, false);\n          SparseMatrix InvU = fact.U ().tinverse (tmp_typ, info, rcond2,\n                                                  true, false).transpose ();\n          ret = fact.Pc ().transpose () * InvU * InvL * fact.Pr ();\n        }\n    }\n\n  return ret;\n}\n\nDET\nSparseMatrix::determinant () const\n{\n  octave_idx_type info;\n  double rcond;\n  return determinant (info, rcond, 0);\n}\n\nDET\nSparseMatrix::determinant (octave_idx_type& info) const\n{\n  double rcond;\n  return determinant (info, rcond, 0);\n}\n\nDET\nSparseMatrix::determinant (octave_idx_type& err, double& rcond, bool) const\n{\n  DET retval;\n\n#if defined (HAVE_UMFPACK)\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr == 0 || nc == 0 || nr != nc)\n    {\n      retval = DET (1.0);\n    }\n  else\n    {\n      err = 0;\n\n      // Setup the control parameters\n      Matrix Control (UMFPACK_CONTROL, 1);\n      double *control = Control.rwdata ();\n      UMFPACK_DNAME (defaults) (control);\n\n      double tmp = octave::sparse_params::get_key (\"spumoni\");\n      if (! octave::math::isnan (tmp))\n        Control (UMFPACK_PRL) = tmp;\n\n      tmp = octave::sparse_params::get_key (\"piv_tol\");\n      if (! octave::math::isnan (tmp))\n        {\n          Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;\n          Control (UMFPACK_PIVOT_TOLERANCE) = tmp;\n        }\n\n      // Set whether we are allowed to modify Q or not\n      tmp = octave::sparse_params::get_key (\"autoamd\");\n      if (! octave::math::isnan (tmp))\n        Control (UMFPACK_FIXQ) = tmp;\n\n      // Turn-off UMFPACK scaling for LU\n      Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;\n\n      UMFPACK_DNAME (report_control) (control);\n\n      const octave_idx_type *Ap = cidx ();\n      const octave_idx_type *Ai = ridx ();\n      const double *Ax = data ();\n\n      UMFPACK_DNAME (report_matrix) (nr, nc,\n                                     octave::to_suitesparse_intptr (Ap),\n                                     octave::to_suitesparse_intptr (Ai),\n                                     Ax, 1, control);\n\n      void *Symbolic;\n      Matrix Info (1, UMFPACK_INFO);\n      double *info = Info.rwdata ();\n      int status = UMFPACK_DNAME (qsymbolic) (nr, nc,\n                                              octave::to_suitesparse_intptr (Ap),\n                                              octave::to_suitesparse_intptr (Ai),\n                                              Ax, nullptr, &Symbolic, control, info);\n\n      if (status < 0)\n        {\n          UMFPACK_DNAME (report_status) (control, status);\n          UMFPACK_DNAME (report_info) (control, info);\n\n          UMFPACK_DNAME (free_symbolic) (&Symbolic);\n\n          (*current_liboctave_error_handler)\n            (\"SparseMatrix::determinant symbolic factorization failed\");\n        }\n      else\n        {\n          UMFPACK_DNAME (report_symbolic) (Symbolic, control);\n\n          void *Numeric;\n          status = UMFPACK_DNAME (numeric) (octave::to_suitesparse_intptr (Ap),\n                                            octave::to_suitesparse_intptr (Ai),\n                                            Ax, Symbolic,\n                                            &Numeric, control, info);\n          UMFPACK_DNAME (free_symbolic) (&Symbolic);\n\n          rcond = Info (UMFPACK_RCOND);\n\n          if (status < 0)\n            {\n              UMFPACK_DNAME (report_status) (control, status);\n              UMFPACK_DNAME (report_info) (control, info);\n\n              UMFPACK_DNAME (free_numeric) (&Numeric);\n              (*current_liboctave_error_handler)\n                (\"SparseMatrix::determinant numeric factorization failed\");\n            }\n          else\n            {\n              UMFPACK_DNAME (report_numeric) (Numeric, control);\n\n              double c10, e10;\n\n              status = UMFPACK_DNAME (get_determinant) (&c10, &e10, Numeric,\n                                                        info);\n\n              if (status < 0)\n                {\n                  UMFPACK_DNAME (report_status) (control, status);\n                  UMFPACK_DNAME (report_info) (control, info);\n\n                  (*current_liboctave_error_handler)\n                    (\"SparseMatrix::determinant error calculating determinant\");\n                }\n              else\n                retval = DET (c10, e10, 10);\n\n              UMFPACK_DNAME (free_numeric) (&Numeric);\n            }\n        }\n    }\n\n#else\n\n  octave_unused_parameter (err);\n  octave_unused_parameter (rcond);\n\n  (*current_liboctave_error_handler)\n    (\"support for UMFPACK was unavailable or disabled \"\n     \"when liboctave was built\");\n\n#endif\n\n  return retval;\n}\n\nMatrix\nSparseMatrix::dsolve (MatrixType& mattype, const Matrix& b,\n                      octave_idx_type& err,\n                      double& rcond, solve_singularity_handler,\n                      bool calc_cond) const\n{\n  Matrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = (nc < nr ? nc : nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = Matrix (nc, b.cols (), 0.0);\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      retval.resize (nc, b.cols (), 0.);\n      if (typ == MatrixType::Diagonal)\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          for (octave_idx_type i = 0; i < nm; i++)\n            retval(i, j) = b(i, j) / data (i);\n      else\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          for (octave_idx_type k = 0; k < nc; k++)\n            for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n              retval(k, j) = b(ridx (i), j) / data (i);\n\n      if (calc_cond)\n        {\n          double dmax = 0.;\n          double dmin = octave::numeric_limits<double>::Inf ();\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              double tmp = fabs (data (i));\n              if (tmp > dmax)\n                dmax = tmp;\n              if (tmp < dmin)\n                dmin = tmp;\n            }\n          rcond = dmin / dmax;\n        }\n      else\n        rcond = 1.;\n    }\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::dsolve (MatrixType& mattype, const SparseMatrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler, bool calc_cond) const\n{\n  SparseMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = (nc < nr ? nc : nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseMatrix (nc, b_nc, b_nz);\n\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      if (typ == MatrixType::Diagonal)\n        for (octave_idx_type j = 0; j < b_nc; j++)\n          {\n            for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n              {\n                if (b.ridx (i) >= nm)\n                  break;\n                retval.xridx (ii) = b.ridx (i);\n                retval.xdata (ii++) = b.data (i) / data (b.ridx (i));\n              }\n            retval.xcidx (j+1) = ii;\n          }\n      else\n        for (octave_idx_type j = 0; j < b_nc; j++)\n          {\n            for (octave_idx_type l = 0; l < nc; l++)\n              for (octave_idx_type i = cidx (l); i < cidx (l+1); i++)\n                {\n                  bool found = false;\n                  octave_idx_type k;\n                  for (k = b.cidx (j); k < b.cidx (j+1); k++)\n                    if (ridx (i) == b.ridx (k))\n                      {\n                        found = true;\n                        break;\n                      }\n                  if (found)\n                    {\n                      retval.xridx (ii) = l;\n                      retval.xdata (ii++) = b.data (k) / data (i);\n                    }\n                }\n            retval.xcidx (j+1) = ii;\n          }\n\n      if (calc_cond)\n        {\n          double dmax = 0.;\n          double dmin = octave::numeric_limits<double>::Inf ();\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              double tmp = fabs (data (i));\n              if (tmp > dmax)\n                dmax = tmp;\n              if (tmp < dmin)\n                dmin = tmp;\n            }\n          rcond = dmin / dmax;\n        }\n      else\n        rcond = 1.;\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseMatrix::dsolve (MatrixType& mattype, const ComplexMatrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler, bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = (nc < nr ? nc : nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      retval.resize (nc, b.cols (), 0);\n      if (typ == MatrixType::Diagonal)\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          for (octave_idx_type i = 0; i < nm; i++)\n            retval(i, j) = b(i, j) / data (i);\n      else\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          for (octave_idx_type k = 0; k < nc; k++)\n            for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n              retval(k, j) = b(ridx (i), j) / data (i);\n\n      if (calc_cond)\n        {\n          double dmax = 0.;\n          double dmin = octave::numeric_limits<double>::Inf ();\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              double tmp = fabs (data (i));\n              if (tmp > dmax)\n                dmax = tmp;\n              if (tmp < dmin)\n                dmin = tmp;\n            }\n          rcond = dmin / dmax;\n        }\n      else\n        rcond = 1.;\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseMatrix::dsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler, bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = (nc < nr ? nc : nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseComplexMatrix (nc, b_nc, b_nz);\n\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      if (typ == MatrixType::Diagonal)\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          {\n            for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n              {\n                if (b.ridx (i) >= nm)\n                  break;\n                retval.xridx (ii) = b.ridx (i);\n                retval.xdata (ii++) = b.data (i) / data (b.ridx (i));\n              }\n            retval.xcidx (j+1) = ii;\n          }\n      else\n        for (octave_idx_type j = 0; j < b.cols (); j++)\n          {\n            for (octave_idx_type l = 0; l < nc; l++)\n              for (octave_idx_type i = cidx (l); i < cidx (l+1); i++)\n                {\n                  bool found = false;\n                  octave_idx_type k;\n                  for (k = b.cidx (j); k < b.cidx (j+1); k++)\n                    if (ridx (i) == b.ridx (k))\n                      {\n                        found = true;\n                        break;\n                      }\n                  if (found)\n                    {\n                      retval.xridx (ii) = l;\n                      retval.xdata (ii++) = b.data (k) / data (i);\n                    }\n                }\n            retval.xcidx (j+1) = ii;\n          }\n\n      if (calc_cond)\n        {\n          double dmax = 0.;\n          double dmin = octave::numeric_limits<double>::Inf ();\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              double tmp = fabs (data (i));\n              if (tmp > dmax)\n                dmax = tmp;\n              if (tmp < dmin)\n                dmin = tmp;\n            }\n          rcond = dmin / dmax;\n        }\n      else\n        rcond = 1.;\n    }\n\n  return retval;\n}\n\nMatrix\nSparseMatrix::utsolve (MatrixType& mattype, const Matrix& b,\n                       octave_idx_type& err, double& rcond,\n                       solve_singularity_handler sing_handler,\n                       bool calc_cond) const\n{\n  Matrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = Matrix (nc, b.cols (), 0.0);\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      octave_idx_type b_nc = b.cols ();\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += fabs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          retval.resize (nc, b_nc);\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (double, work, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  octave_idx_type kidx = perm[k];\n\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (kidx+1)-1) != k\n                          || data (cidx (kidx+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      double tmp = work[k] / data (cidx (kidx+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (kidx);\n                           i < cidx (kidx+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (perm[i], j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      octave_idx_type iidx = perm[k];\n\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (iidx+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (iidx);\n                               i < cidx (iidx+1)-1; i++)\n                            {\n                              octave_idx_type idx2 = ridx (i);\n                              work[idx2] = work[idx2] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (double, work, nm);\n          retval.resize (nc, b_nc);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k+1)-1) != k\n                          || data (cidx (k+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      double tmp = work[k] / data (cidx (k+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (i, j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (k+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::utsolve (MatrixType& mattype, const SparseMatrix& b,\n                       octave_idx_type& err, double& rcond,\n                       solve_singularity_handler sing_handler,\n                       bool calc_cond) const\n{\n  SparseMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += fabs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseMatrix (nc, b_nc, b_nz);\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      octave_idx_type x_nz = b_nz;\n\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (double, work, nm);\n\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc);\n          for (octave_idx_type i = 0; i < nc; i++)\n            rperm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  octave_idx_type kidx = perm[k];\n\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (kidx+1)-1) != k\n                          || data (cidx (kidx+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      double tmp = work[k] / data (cidx (kidx+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (kidx);\n                           i < cidx (kidx+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[rperm[i]] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[rperm[i]];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      octave_idx_type iidx = perm[k];\n\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (iidx+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (iidx);\n                               i < cidx (iidx+1)-1; i++)\n                            {\n                              octave_idx_type idx2 = ridx (i);\n                              work[idx2] = work[idx2] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (double, work, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k+1)-1) != k\n                          || data (cidx (k+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      double tmp = work[k] / data (cidx (k+1)-1);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (k+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1)-1; i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n  return retval;\n}\n\nComplexMatrix\nSparseMatrix::utsolve (MatrixType& mattype, const ComplexMatrix& b,\n                       octave_idx_type& err, double& rcond,\n                       solve_singularity_handler sing_handler,\n                       bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      octave_idx_type b_nc = b.cols ();\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += fabs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          retval.resize (nc, b_nc);\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (Complex, cwork, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                cwork[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                cwork[i] = 0.;\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  octave_idx_type kidx = perm[k];\n\n                  if (cwork[k] != 0.)\n                    {\n                      if (ridx (cidx (kidx+1)-1) != k\n                          || data (cidx (kidx+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = cwork[k] / data (cidx (kidx+1)-1);\n                      cwork[k] = tmp;\n                      for (octave_idx_type i = cidx (kidx);\n                           i < cidx (kidx+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          cwork[iidx] = cwork[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (perm[i], j) = cwork[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              OCTAVE_LOCAL_BUFFER (double, work, nm);\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      octave_idx_type iidx = perm[k];\n\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (iidx+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (iidx);\n                               i < cidx (iidx+1)-1; i++)\n                            {\n                              octave_idx_type idx2 = ridx (i);\n                              work[idx2] = work[idx2] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, cwork, nm);\n          retval.resize (nc, b_nc);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                cwork[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                cwork[i] = 0.;\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  if (cwork[k] != 0.)\n                    {\n                      if (ridx (cidx (k+1)-1) != k\n                          || data (cidx (k+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = cwork[k] / data (cidx (k+1)-1);\n                      cwork[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          cwork[iidx] = cwork[iidx] - tmp  * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (i, j) = cwork[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              OCTAVE_LOCAL_BUFFER (double, work, nm);\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (k+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1)-1; i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseMatrix::utsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                       octave_idx_type& err, double& rcond,\n                       solve_singularity_handler sing_handler,\n                       bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += fabs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseComplexMatrix (nc, b_nc, b_nz);\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      octave_idx_type x_nz = b_nz;\n\n      if (typ == MatrixType::Permuted_Upper)\n        {\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (Complex, cwork, nm);\n\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc);\n          for (octave_idx_type i = 0; i < nc; i++)\n            rperm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                cwork[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                cwork[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  octave_idx_type kidx = perm[k];\n\n                  if (cwork[k] != 0.)\n                    {\n                      if (ridx (cidx (kidx+1)-1) != k\n                          || data (cidx (kidx+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = cwork[k] / data (cidx (kidx+1)-1);\n                      cwork[k] = tmp;\n                      for (octave_idx_type i = cidx (kidx);\n                           i < cidx (kidx+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          cwork[iidx] = cwork[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (cwork[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (cwork[rperm[i]] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = cwork[rperm[i]];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              OCTAVE_LOCAL_BUFFER (double, work, nm);\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      octave_idx_type iidx = perm[k];\n\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (iidx+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (iidx);\n                               i < cidx (iidx+1)-1; i++)\n                            {\n                              octave_idx_type idx2 = ridx (i);\n                              work[idx2] = work[idx2] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, cwork, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                cwork[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                cwork[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = nc-1; k >= 0; k--)\n                {\n                  if (cwork[k] != 0.)\n                    {\n                      if (ridx (cidx (k+1)-1) != k\n                          || data (cidx (k+1)-1) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = cwork[k] / data (cidx (k+1)-1);\n                      cwork[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          cwork[iidx] = cwork[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (cwork[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (cwork[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = cwork[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              OCTAVE_LOCAL_BUFFER (double, work, nm);\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k >= 0; k--)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (k+1)-1);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1)-1; i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = 0; i < j+1; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nMatrix\nSparseMatrix::ltsolve (MatrixType& mattype, const Matrix& b,\n                       octave_idx_type& err, double& rcond,\n                       solve_singularity_handler sing_handler,\n                       bool calc_cond) const\n{\n  Matrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = Matrix (nc, b.cols (), 0.0);\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      octave_idx_type b_nc = b.cols ();\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += fabs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      if (typ == MatrixType::Permuted_Lower)\n        {\n          retval.resize (nc, b_nc);\n          OCTAVE_LOCAL_BUFFER (double, work, nm);\n\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, inv_perm, nr);\n          for (octave_idx_type i = 0; i < nr; i++)\n            inv_perm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              if (nc > nr)\n                for (octave_idx_type i = 0; i < nm; i++)\n                  work[i] = 0.;\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[inv_perm[i]] = b(i, j);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      octave_idx_type minr = nr;\n                      octave_idx_type mini = 0;\n\n                      // Check that permutation leads to lower triangular form\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        if (inv_perm[ridx (i)] < minr)\n                          {\n                            minr = inv_perm[ridx (i)];\n                            mini = i;\n                          }\n\n                      if (minr != k || data (mini) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      double tmp = work[k] / data (mini);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        {\n                          if (i == mini)\n                            continue;\n\n                          octave_idx_type iidx = inv_perm[ridx (i)];\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval(i, j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = 0; k < nc; k++)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          octave_idx_type minr = nr;\n                          octave_idx_type mini = 0;\n\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            if (inv_perm[ridx (i)] < minr)\n                              {\n                                minr = inv_perm[ridx (i)];\n                                mini = i;\n                              }\n\n                          double tmp = work[k] / data (mini);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            {\n                              if (i == mini)\n                                continue;\n\n                              octave_idx_type iidx = inv_perm[ridx (i)];\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n\n                  double atmp = 0.;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (double, work, nm);\n          retval.resize (nc, b_nc, 0.);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                work[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                work[i] = 0.;\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k)) != k || data (cidx (k)) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      double tmp = work[k] / data (cidx (k));\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (i, j) = work[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k < nc; k++)\n                    {\n\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (k));\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k)+1;\n                               i < cidx (k+1); i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::ltsolve (MatrixType& mattype, const SparseMatrix& b,\n                       octave_idx_type& err, double& rcond,\n                       solve_singularity_handler sing_handler,\n                       bool calc_cond) const\n{\n  SparseMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += fabs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseMatrix (nc, b_nc, b_nz);\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      octave_idx_type x_nz = b_nz;\n\n      if (typ == MatrixType::Permuted_Lower)\n        {\n          OCTAVE_LOCAL_BUFFER (double, work, nm);\n\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, inv_perm, nr);\n          for (octave_idx_type i = 0; i < nr; i++)\n            inv_perm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[inv_perm[b.ridx (i)]] = b.data (i);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      octave_idx_type minr = nr;\n                      octave_idx_type mini = 0;\n\n                      // Check that permutation leads to lower triangular form\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        if (inv_perm[ridx (i)] < minr)\n                          {\n                            minr = inv_perm[ridx (i)];\n                            mini = i;\n                          }\n\n                      if (minr != k || data (mini) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      double tmp = work[k] / data (mini);\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        {\n                          if (i == mini)\n                            continue;\n\n                          octave_idx_type iidx = inv_perm[ridx (i)];\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = 0; k < nc; k++)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          octave_idx_type minr = nr;\n                          octave_idx_type mini = 0;\n\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            if (inv_perm[ridx (i)] < minr)\n                              {\n                                minr = inv_perm[ridx (i)];\n                                mini = i;\n                              }\n\n                          double tmp = work[k] / data (mini);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            {\n                              if (i == mini)\n                                continue;\n\n                              octave_idx_type iidx = inv_perm[ridx (i)];\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (double, work, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                work[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (work[k] != 0.)\n                    {\n                      if (ridx (cidx (k)) != k || data (cidx (k)) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      double tmp = work[k] / data (cidx (k));\n                      work[k] = tmp;\n                      for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          work[iidx] = work[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (work[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = work[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k < nc; k++)\n                    {\n\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (k));\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k)+1;\n                               i < cidx (k+1); i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseMatrix::ltsolve (MatrixType& mattype, const ComplexMatrix& b,\n                       octave_idx_type& err, double& rcond,\n                       solve_singularity_handler sing_handler,\n                       bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      octave_idx_type b_nc = b.cols ();\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += fabs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      if (typ == MatrixType::Permuted_Lower)\n        {\n          retval.resize (nc, b_nc);\n          OCTAVE_LOCAL_BUFFER (Complex, cwork, nm);\n\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, inv_perm, nr);\n          for (octave_idx_type i = 0; i < nr; i++)\n            inv_perm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                cwork[i] = 0.;\n              for (octave_idx_type i = 0; i < nr; i++)\n                cwork[inv_perm[i]] = b(i, j);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (cwork[k] != 0.)\n                    {\n                      octave_idx_type minr = nr;\n                      octave_idx_type mini = 0;\n\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        if (inv_perm[ridx (i)] < minr)\n                          {\n                            minr = inv_perm[ridx (i)];\n                            mini = i;\n                          }\n\n                      if (minr != k || data (mini) == 0)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = cwork[k] / data (mini);\n                      cwork[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        {\n                          if (i == mini)\n                            continue;\n\n                          octave_idx_type iidx = inv_perm[ridx (i)];\n                          cwork[iidx] = cwork[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval(i, j) = cwork[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              OCTAVE_LOCAL_BUFFER (double, work, nm);\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = 0; k < nc; k++)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          octave_idx_type minr = nr;\n                          octave_idx_type mini = 0;\n\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            if (inv_perm[ridx (i)] < minr)\n                              {\n                                minr = inv_perm[ridx (i)];\n                                mini = i;\n                              }\n\n                          double tmp = work[k] / data (mini);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            {\n                              if (i == mini)\n                                continue;\n\n                              octave_idx_type iidx = inv_perm[ridx (i)];\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, cwork, nm);\n          retval.resize (nc, b_nc, 0.);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nr; i++)\n                cwork[i] = b(i, j);\n              for (octave_idx_type i = nr; i < nc; i++)\n                cwork[i] = 0.;\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (cwork[k] != 0.)\n                    {\n                      if (ridx (cidx (k)) != k || data (cidx (k)) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = cwork[k] / data (cidx (k));\n                      cwork[k] = tmp;\n                      for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          cwork[iidx] = cwork[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                retval.xelem (i, j) = cwork[i];\n            }\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              OCTAVE_LOCAL_BUFFER (double, work, nm);\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k < nc; k++)\n                    {\n\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (k));\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k)+1;\n                               i < cidx (k+1); i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseMatrix::ltsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                       octave_idx_type& err, double& rcond,\n                       solve_singularity_handler sing_handler,\n                       bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nm = std::max (nc, nr);\n  err = 0;\n\n  if (nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n\n      double anorm = 0.;\n      double ainvnorm = 0.;\n      rcond = 1.;\n\n      if (calc_cond)\n        {\n          // Calculate the 1-norm of matrix for rcond calculation\n          for (octave_idx_type j = 0; j < nc; j++)\n            {\n              double atmp = 0.;\n              for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                atmp += fabs (data (i));\n              if (atmp > anorm)\n                anorm = atmp;\n            }\n        }\n\n      octave_idx_type b_nc = b.cols ();\n      octave_idx_type b_nz = b.nnz ();\n      retval = SparseComplexMatrix (nc, b_nc, b_nz);\n      retval.xcidx (0) = 0;\n      octave_idx_type ii = 0;\n      octave_idx_type x_nz = b_nz;\n\n      if (typ == MatrixType::Permuted_Lower)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, cwork, nm);\n\n          octave_idx_type *perm = mattype.triangular_perm ();\n          OCTAVE_LOCAL_BUFFER (octave_idx_type, inv_perm, nr);\n          for (octave_idx_type i = 0; i < nr; i++)\n            inv_perm[perm[i]] = i;\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                cwork[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                cwork[inv_perm[b.ridx (i)]] = b.data (i);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (cwork[k] != 0.)\n                    {\n                      octave_idx_type minr = nr;\n                      octave_idx_type mini = 0;\n\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        if (inv_perm[ridx (i)] < minr)\n                          {\n                            minr = inv_perm[ridx (i)];\n                            mini = i;\n                          }\n\n                      if (minr != k || data (mini) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = cwork[k] / data (mini);\n                      cwork[k] = tmp;\n                      for (octave_idx_type i = cidx (k); i < cidx (k+1); i++)\n                        {\n                          if (i == mini)\n                            continue;\n\n                          octave_idx_type iidx = inv_perm[ridx (i)];\n                          cwork[iidx] = cwork[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (cwork[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (cwork[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = cwork[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              OCTAVE_LOCAL_BUFFER (double, work, nm);\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = 0; k < nc; k++)\n                    {\n                      if (work[k] != 0.)\n                        {\n                          octave_idx_type minr = nr;\n                          octave_idx_type mini = 0;\n\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            if (inv_perm[ridx (i)] < minr)\n                              {\n                                minr = inv_perm[ridx (i)];\n                                mini = i;\n                              }\n\n                          double tmp = work[k] / data (mini);\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k);\n                               i < cidx (k+1); i++)\n                            {\n                              if (i == mini)\n                                continue;\n\n                              octave_idx_type iidx = inv_perm[ridx (i)];\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n      else\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, cwork, nm);\n\n          for (octave_idx_type j = 0; j < b_nc; j++)\n            {\n              for (octave_idx_type i = 0; i < nm; i++)\n                cwork[i] = 0.;\n              for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                cwork[b.ridx (i)] = b.data (i);\n\n              for (octave_idx_type k = 0; k < nc; k++)\n                {\n                  if (cwork[k] != 0.)\n                    {\n                      if (ridx (cidx (k)) != k || data (cidx (k)) == 0.)\n                        {\n                          err = -2;\n                          goto triangular_error;\n                        }\n\n                      Complex tmp = cwork[k] / data (cidx (k));\n                      cwork[k] = tmp;\n                      for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++)\n                        {\n                          octave_idx_type iidx = ridx (i);\n                          cwork[iidx] = cwork[iidx] - tmp * data (i);\n                        }\n                    }\n                }\n\n              // Count nonzeros in work vector and adjust space in\n              // retval if needed\n              octave_idx_type new_nnz = 0;\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (cwork[i] != 0.)\n                  new_nnz++;\n\n              if (ii + new_nnz > x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                  retval.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              for (octave_idx_type i = 0; i < nc; i++)\n                if (cwork[i] != 0.)\n                  {\n                    retval.xridx (ii) = i;\n                    retval.xdata (ii++) = cwork[i];\n                  }\n              retval.xcidx (j+1) = ii;\n            }\n\n          retval.maybe_compress ();\n\n          if (calc_cond)\n            {\n              // Calculation of 1-norm of inv(*this)\n              OCTAVE_LOCAL_BUFFER (double, work, nm);\n              for (octave_idx_type i = 0; i < nm; i++)\n                work[i] = 0.;\n\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  work[j] = 1.;\n\n                  for (octave_idx_type k = j; k < nc; k++)\n                    {\n\n                      if (work[k] != 0.)\n                        {\n                          double tmp = work[k] / data (cidx (k));\n                          work[k] = tmp;\n                          for (octave_idx_type i = cidx (k)+1;\n                               i < cidx (k+1); i++)\n                            {\n                              octave_idx_type iidx = ridx (i);\n                              work[iidx] = work[iidx] - tmp * data (i);\n                            }\n                        }\n                    }\n                  double atmp = 0;\n                  for (octave_idx_type i = j; i < nc; i++)\n                    {\n                      atmp += fabs (work[i]);\n                      work[i] = 0.;\n                    }\n                  if (atmp > ainvnorm)\n                    ainvnorm = atmp;\n                }\n              rcond = 1. / ainvnorm / anorm;\n            }\n        }\n\n    triangular_error:\n      if (err != 0)\n        {\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n\n      if (is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          err = -2;\n\n          if (sing_handler)\n            {\n              sing_handler (rcond);\n              mattype.mark_as_rectangular ();\n            }\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n    }\n\n  return retval;\n}\n\nMatrix\nSparseMatrix::trisolve (MatrixType& mattype, const Matrix& b,\n                        octave_idx_type& err, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond) const\n{\n  Matrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = Matrix (nc, b.cols (), 0.0);\n  else if (calc_cond)\n    (*current_liboctave_error_handler)\n      (\"calculation of condition number not implemented\");\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Tridiagonal_Hermitian)\n        {\n          OCTAVE_LOCAL_BUFFER (double, D, nr);\n          OCTAVE_LOCAL_BUFFER (double, DL, nr - 1);\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii);\n                  ii += 2;\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                  }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT b_nr = octave::to_f77_int (b.rows ());\n          F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n          retval = b;\n          double *result = retval.rwdata ();\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (dptsv, DPTSV, (tmp_nr, b_nc, D, DL, result,\n                                   b_nr, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = 0;\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Tridiagonal;\n            }\n          else\n            rcond = 1.;\n        }\n\n      if (typ == MatrixType::Tridiagonal)\n        {\n          OCTAVE_LOCAL_BUFFER (double, DU, nr - 1);\n          OCTAVE_LOCAL_BUFFER (double, D, nr);\n          OCTAVE_LOCAL_BUFFER (double, DL, nr - 1);\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii++);\n                  DU[j] = data (ii++);\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                  DU[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                    else if (ridx (i) == j - 1)\n                      DU[j-1] = data (i);\n                  }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT b_nr = octave::to_f77_int (b.rows ());\n          F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n          retval = b;\n          double *result = retval.rwdata ();\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (dgtsv, DGTSV, (tmp_nr, b_nc, DL, D, DU, result,\n                                   b_nr, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              rcond = 0.;\n              err = -2;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            rcond = 1.;\n        }\n      else if (typ != MatrixType::Tridiagonal_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::trisolve (MatrixType& mattype, const SparseMatrix& b,\n                        octave_idx_type& err, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond) const\n{\n  SparseMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseMatrix (nc, b.cols ());\n  else if (calc_cond)\n    (*current_liboctave_error_handler)\n      (\"calculation of condition number not implemented\");\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      // Note can't treat symmetric case as there is no dpttrf function\n      if (typ == MatrixType::Tridiagonal\n          || typ == MatrixType::Tridiagonal_Hermitian)\n        {\n          OCTAVE_LOCAL_BUFFER (double, DU2, nr - 2);\n          OCTAVE_LOCAL_BUFFER (double, DU, nr - 1);\n          OCTAVE_LOCAL_BUFFER (double, D, nr);\n          OCTAVE_LOCAL_BUFFER (double, DL, nr - 1);\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii++);\n                  DU[j] = data (ii++);\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                  DU[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                    else if (ridx (i) == j - 1)\n                      DU[j-1] = data (i);\n                  }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (dgttrf, DGTTRF, (tmp_nr, DL, D, DU, DU2, pipvt, tmp_err));\n\n          if (err != 0)\n            {\n              rcond = 0.0;\n              err = -2;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              rcond = 1.0;\n              char job = 'N';\n              octave_idx_type x_nz = b.nnz ();\n              octave_idx_type b_nc = b.cols ();\n              retval = SparseMatrix (nr, b_nc, x_nz);\n              retval.xcidx (0) = 0;\n              octave_idx_type ii = 0;\n\n              OCTAVE_LOCAL_BUFFER (double, work, nr);\n\n              for (octave_idx_type j = 0; j < b_nc; j++)\n                {\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    work[i] = 0.;\n                  for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n                    work[b.ridx (i)] = b.data (i);\n\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n\n                  F77_XFCN (dgttrs, DGTTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, 1, DL, D, DU, DU2, pipvt,\n                             work, b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  // Count nonzeros in work vector and adjust\n                  // space in retval if needed\n                  octave_idx_type new_nnz = 0;\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    if (work[i] != 0.)\n                      new_nnz++;\n\n                  if (ii + new_nnz > x_nz)\n                    {\n                      // Resize the sparse matrix\n                      octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                      retval.change_capacity (sz);\n                      x_nz = sz;\n                    }\n\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    if (work[i] != 0.)\n                      {\n                        retval.xridx (ii) = i;\n                        retval.xdata (ii++) = work[i];\n                      }\n                  retval.xcidx (j+1) = ii;\n                }\n\n              retval.maybe_compress ();\n            }\n        }\n      else if (typ != MatrixType::Tridiagonal_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseMatrix::trisolve (MatrixType& mattype, const ComplexMatrix& b,\n                        octave_idx_type& err, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else if (calc_cond)\n    (*current_liboctave_error_handler)\n      (\"calculation of condition number not implemented\");\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Tridiagonal_Hermitian)\n        {\n          OCTAVE_LOCAL_BUFFER (double, D, nr);\n          OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii);\n                  ii += 2;\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                  }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT b_nr = octave::to_f77_int (b.rows ());\n          F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n          rcond = 1.;\n\n          retval = b;\n          Complex *result = retval.rwdata ();\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zptsv, ZPTSV, (tmp_nr, b_nc, D, F77_DBLE_CMPLX_ARG (DL),\n                                   F77_DBLE_CMPLX_ARG (result),\n                                   b_nr, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = 0;\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Tridiagonal;\n            }\n        }\n\n      if (typ == MatrixType::Tridiagonal)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1);\n          OCTAVE_LOCAL_BUFFER (Complex, D, nr);\n          OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii++);\n                  DU[j] = data (ii++);\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                  DU[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                    else if (ridx (i) == j - 1)\n                      DU[j-1] = data (i);\n                  }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT b_nr = octave::to_f77_int (b.rows ());\n          F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n          rcond = 1.;\n\n          retval = b;\n          Complex *result = retval.rwdata ();\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (zgtsv, ZGTSV, (tmp_nr, b_nc, F77_DBLE_CMPLX_ARG (DL),\n                                   F77_DBLE_CMPLX_ARG (D),\n                                   F77_DBLE_CMPLX_ARG (DU),\n                                   F77_DBLE_CMPLX_ARG (result),\n                                   b_nr, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              rcond = 0.;\n              err = -2;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n        }\n      else if (typ != MatrixType::Tridiagonal_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseMatrix::trisolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                        octave_idx_type& err, double& rcond,\n                        solve_singularity_handler sing_handler,\n                        bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else if (calc_cond)\n    (*current_liboctave_error_handler)\n      (\"calculation of condition number not implemented\");\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      // Note can't treat symmetric case as there is no dpttrf function\n      if (typ == MatrixType::Tridiagonal\n          || typ == MatrixType::Tridiagonal_Hermitian)\n        {\n          OCTAVE_LOCAL_BUFFER (double, DU2, nr - 2);\n          OCTAVE_LOCAL_BUFFER (double, DU, nr - 1);\n          OCTAVE_LOCAL_BUFFER (double, D, nr);\n          OCTAVE_LOCAL_BUFFER (double, DL, nr - 1);\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          if (mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < nc-1; j++)\n                {\n                  D[j] = data (ii++);\n                  DL[j] = data (ii++);\n                  DU[j] = data (ii++);\n                }\n              D[nc-1] = data (ii);\n            }\n          else\n            {\n              D[0] = 0.;\n              for (octave_idx_type i = 0; i < nr - 1; i++)\n                {\n                  D[i+1] = 0.;\n                  DL[i] = 0.;\n                  DU[i] = 0.;\n                }\n\n              for (octave_idx_type j = 0; j < nc; j++)\n                for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                  {\n                    if (ridx (i) == j)\n                      D[j] = data (i);\n                    else if (ridx (i) == j + 1)\n                      DL[j] = data (i);\n                    else if (ridx (i) == j - 1)\n                      DU[j-1] = data (i);\n                  }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (dgttrf, DGTTRF, (tmp_nr, DL, D, DU, DU2, pipvt, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              rcond = 0.0;\n              err = -2;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              rcond = 1.;\n              char job = 'N';\n              F77_INT b_nr = octave::to_f77_int (b.rows ());\n              octave_idx_type b_nc = b.cols ();\n              OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);\n              OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);\n\n              // Take a first guess that the number of nonzero terms\n              // will be as many as in b\n              octave_idx_type x_nz = b.nnz ();\n              octave_idx_type ii = 0;\n              retval = SparseComplexMatrix (b_nr, b_nc, x_nz);\n\n              retval.xcidx (0) = 0;\n              for (octave_idx_type j = 0; j < b_nc; j++)\n                {\n\n                  for (F77_INT i = 0; i < b_nr; i++)\n                    {\n                      Complex c = b(i, j);\n                      Bx[i] = c.real ();\n                      Bz[i] = c.imag ();\n                    }\n\n                  F77_XFCN (dgttrs, DGTTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, 1, DL, D, DU, DU2, pipvt,\n                             Bx, b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    {\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n\n                  F77_XFCN (dgttrs, DGTTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, 1, DL, D, DU, DU2, pipvt,\n                             Bz, b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    {\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n\n                  // Count nonzeros in work vector and adjust\n                  // space in retval if needed\n                  octave_idx_type new_nnz = 0;\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    if (Bx[i] != 0. || Bz[i] != 0.)\n                      new_nnz++;\n\n                  if (ii + new_nnz > x_nz)\n                    {\n                      // Resize the sparse matrix\n                      octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                      retval.change_capacity (sz);\n                      x_nz = sz;\n                    }\n\n                  for (octave_idx_type i = 0; i < nr; i++)\n                    if (Bx[i] != 0. || Bz[i] != 0.)\n                      {\n                        retval.xridx (ii) = i;\n                        retval.xdata (ii++) = Complex (Bx[i], Bz[i]);\n                      }\n\n                  retval.xcidx (j+1) = ii;\n                }\n\n              retval.maybe_compress ();\n            }\n        }\n      else if (typ != MatrixType::Tridiagonal_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nMatrix\nSparseMatrix::bsolve (MatrixType& mattype, const Matrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler sing_handler,\n                      bool calc_cond) const\n{\n  Matrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = Matrix (nc, b.cols (), 0.0);\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Banded_Hermitian)\n        {\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_lower + 1;\n          Matrix m_band (ldm, nc);\n          double *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              {\n                octave_idx_type ri = ridx (i);\n                if (ri >= j)\n                  m_band(ri - j, j) = data (i);\n              }\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            anorm = m_band.abs ().sum ().row (0).max ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          char job = 'L';\n          F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     tmp_nr, n_lower, tmp_data, ldm, tmp_err\n                                     F77_CHAR_ARG_LEN (1)));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              // Matrix is not positive definite!! Fall through to\n              // unsymmetric banded solver.\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Banded;\n              rcond = 0.0;\n              err = 0;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<double> z (dim_vector (3 * nr, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nr, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (dpbcon, DPBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, tmp_data, ldm,\n                             anorm, rcond, pz, piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  retval = b;\n                  double *result = retval.rwdata ();\n\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n                  F77_XFCN (dpbtrs, DPBTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, b_nc, tmp_data,\n                             ldm, result, b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    {\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseMatrix::solve solve failed\");\n                      err = -1;\n                    }\n                }\n            }\n        }\n\n      if (typ == MatrixType::Banded)\n        {\n          // Create the storage for the banded form of the sparse matrix\n          F77_INT n_upper = octave::to_f77_int (mattype.nupper ());\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_upper + 2 * n_lower + 1;\n\n          Matrix m_band (ldm, nc);\n          double *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm = 0.0;\n          if (calc_cond)\n            {\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  double atmp = 0.;\n                  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                    atmp += fabs (data (i));\n                  if (atmp > anorm)\n                    anorm = atmp;\n                }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (dgbtrf, DGBTRF, (tmp_nr, tmp_nr, n_lower, n_upper,\n                                     tmp_data, ldm, pipvt, tmp_err));\n\n          err = tmp_err;\n\n          // Throw away extra info LAPACK gives so as to not\n          // change output.\n          if (err != 0)\n            {\n              err = -2;\n              rcond = 0.0;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  char job = '1';\n                  Array<double> z (dim_vector (3 * nr, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nr, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_INT tmp_nc = octave::to_f77_int (nc);\n\n                  F77_XFCN (dgbcon, DGBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nc, n_lower, n_upper, tmp_data, ldm, pipvt,\n                             anorm, rcond, pz, piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  retval = b;\n                  double *result = retval.rwdata ();\n\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n                  char job = 'N';\n                  F77_XFCN (dgbtrs, DGBTRS,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, n_upper, b_nc, tmp_data,\n                             ldm, pipvt, result, b_nr, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n                }\n            }\n        }\n      else if (typ != MatrixType::Banded_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::bsolve (MatrixType& mattype, const SparseMatrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler sing_handler,\n                      bool calc_cond) const\n{\n  SparseMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Banded_Hermitian)\n        {\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = octave::to_f77_int (n_lower + 1);\n\n          Matrix m_band (ldm, nc);\n          double *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              {\n                octave_idx_type ri = ridx (i);\n                if (ri >= j)\n                  m_band(ri - j, j) = data (i);\n              }\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            anorm = m_band.abs ().sum ().row (0).max ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          char job = 'L';\n          F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     tmp_nr, n_lower, tmp_data, ldm, tmp_err\n                                     F77_CHAR_ARG_LEN (1)));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Banded;\n              rcond = 0.0;\n              err = 0;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<double> z (dim_vector (3 * nr, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nr, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (dpbcon, DPBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, tmp_data, ldm,\n                             anorm, rcond, pz, piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  octave_idx_type b_nc = b.cols ();\n                  OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);\n\n                  // Take a first guess that the number of nonzero terms\n                  // will be as many as in b\n                  octave_idx_type x_nz = b.nnz ();\n                  octave_idx_type ii = 0;\n                  retval = SparseMatrix (b_nr, b_nc, x_nz);\n\n                  retval.xcidx (0) = 0;\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n                      for (F77_INT i = 0; i < b_nr; i++)\n                        Bx[i] = b.elem (i, j);\n\n                      F77_XFCN (dpbtrs, DPBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, 1, tmp_data,\n                                 ldm, Bx, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      if (err != 0)\n                        {\n                          // FIXME: Should this be a warning?\n                          (*current_liboctave_error_handler)\n                            (\"SparseMatrix::solve solve failed\");\n                          err = -1;\n                          break;\n                        }\n\n                      for (F77_INT i = 0; i < b_nr; i++)\n                        {\n                          double tmp = Bx[i];\n                          if (tmp != 0.0)\n                            {\n                              if (ii == x_nz)\n                                {\n                                  // Resize the sparse matrix\n                                  octave_idx_type sz;\n                                  sz = (static_cast<double> (b_nc) - j) / b_nc\n                                       * x_nz;\n                                  sz = x_nz + (sz > 100 ? sz : 100);\n                                  retval.change_capacity (sz);\n                                  x_nz = sz;\n                                }\n                              retval.xdata (ii) = tmp;\n                              retval.xridx (ii++) = i;\n                            }\n                        }\n                      retval.xcidx (j+1) = ii;\n                    }\n\n                  retval.maybe_compress ();\n                }\n            }\n        }\n\n      if (typ == MatrixType::Banded)\n        {\n          // Create the storage for the banded form of the sparse matrix\n          F77_INT n_upper = octave::to_f77_int (mattype.nupper ());\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = octave::to_f77_int (n_upper + 2 * n_lower + 1);\n\n          Matrix m_band (ldm, nc);\n          double *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (octave_idx_type j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            {\n              anorm = 0.0;\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  double atmp = 0.0;\n                  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                    atmp += fabs (data (i));\n                  if (atmp > anorm)\n                    anorm = atmp;\n                }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (dgbtrf, DGBTRF, (tmp_nr, tmp_nr, n_lower, n_upper,\n                                     tmp_data, ldm, pipvt, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = -2;\n              rcond = 0.0;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  char job = '1';\n                  Array<double> z (dim_vector (3 * nr, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nr, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_INT tmp_nc = octave::to_f77_int (nc);\n\n                  F77_XFCN (dgbcon, DGBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nc, n_lower, n_upper, tmp_data, ldm, pipvt,\n                             anorm, rcond, pz, piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  char job = 'N';\n                  octave_idx_type x_nz = b.nnz ();\n                  octave_idx_type b_nc = b.cols ();\n                  retval = SparseMatrix (nr, b_nc, x_nz);\n                  retval.xcidx (0) = 0;\n                  octave_idx_type ii = 0;\n\n                  OCTAVE_LOCAL_BUFFER (double, work, nr);\n\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        work[i] = 0.;\n                      for (octave_idx_type i = b.cidx (j);\n                           i < b.cidx (j+1); i++)\n                        work[b.ridx (i)] = b.data (i);\n\n                      F77_INT b_nr = octave::to_f77_int (b.rows ());\n\n                      F77_XFCN (dgbtrs, DGBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, n_upper, 1, tmp_data,\n                                 ldm, pipvt, work, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      // Count nonzeros in work vector and adjust\n                      // space in retval if needed\n                      octave_idx_type new_nnz = 0;\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (work[i] != 0.)\n                          new_nnz++;\n\n                      if (ii + new_nnz > x_nz)\n                        {\n                          // Resize the sparse matrix\n                          octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                          retval.change_capacity (sz);\n                          x_nz = sz;\n                        }\n\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (work[i] != 0.)\n                          {\n                            retval.xridx (ii) = i;\n                            retval.xdata (ii++) = work[i];\n                          }\n                      retval.xcidx (j+1) = ii;\n                    }\n\n                  retval.maybe_compress ();\n                }\n            }\n        }\n      else if (typ != MatrixType::Banded_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseMatrix::bsolve (MatrixType& mattype, const ComplexMatrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler sing_handler,\n                      bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Banded_Hermitian)\n        {\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_lower + 1;\n\n          Matrix m_band (ldm, nc);\n          double *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              {\n                octave_idx_type ri = ridx (i);\n                if (ri >= j)\n                  m_band(ri - j, j) = data (i);\n              }\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            anorm = m_band.abs ().sum ().row (0).max ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          char job = 'L';\n          F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     tmp_nr, n_lower, tmp_data, ldm, tmp_err\n                                     F77_CHAR_ARG_LEN (1)));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              // Matrix is not positive definite!! Fall through to\n              // unsymmetric banded solver.\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Banded;\n              rcond = 0.0;\n              err = 0;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<double> z (dim_vector (3 * nr, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nr, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (dpbcon, DPBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, tmp_data, ldm,\n                             anorm, rcond, pz, piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  octave_idx_type b_nc = b.cols ();\n\n                  OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);\n                  OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);\n\n                  retval.resize (b_nr, b_nc);\n\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n                      for (F77_INT i = 0; i < b_nr; i++)\n                        {\n                          Complex c = b(i, j);\n                          Bx[i] = c.real ();\n                          Bz[i] = c.imag ();\n                        }\n\n                      F77_XFCN (dpbtrs, DPBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, 1, tmp_data,\n                                 ldm, Bx, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      if (err != 0)\n                        {\n                          // FIXME: Should this be a warning?\n                          (*current_liboctave_error_handler)\n                            (\"SparseMatrix::solve solve failed\");\n                          err = -1;\n                          break;\n                        }\n\n                      F77_XFCN (dpbtrs, DPBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, 1, tmp_data,\n                                 ldm, Bz, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      if (err != 0)\n                        {\n                          // FIXME: Should this be a warning?\n                          (*current_liboctave_error_handler)\n                            (\"SparseMatrix::solve solve failed\");\n                          err = -1;\n                          break;\n                        }\n\n                      for (octave_idx_type i = 0; i < b_nr; i++)\n                        retval(i, j) = Complex (Bx[i], Bz[i]);\n                    }\n                }\n            }\n        }\n\n      if (typ == MatrixType::Banded)\n        {\n          // Create the storage for the banded form of the sparse matrix\n          F77_INT n_upper = octave::to_f77_int (mattype.nupper ());\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_upper + 2 * n_lower + 1;\n\n          Matrix m_band (ldm, nc);\n          double *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            {\n              anorm = 0.0;\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  double atmp = 0.0;\n                  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                    atmp += fabs (data (i));\n                  if (atmp > anorm)\n                    anorm = atmp;\n                }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (dgbtrf, DGBTRF, (tmp_nr, tmp_nr, n_lower, n_upper,\n                                     tmp_data, ldm, pipvt, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = -2;\n              rcond = 0.0;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  char job = '1';\n                  Array<double> z (dim_vector (3 * nr, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nr, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_INT tmp_nc = octave::to_f77_int (nc);\n\n                  F77_XFCN (dgbcon, DGBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nc, n_lower, n_upper, tmp_data, ldm, pipvt,\n                             anorm, rcond, pz, piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  char job = 'N';\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  octave_idx_type b_nc = b.cols ();\n                  retval.resize (nr, b_nc);\n\n                  OCTAVE_LOCAL_BUFFER (double, Bz, nr);\n                  OCTAVE_LOCAL_BUFFER (double, Bx, nr);\n\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        {\n                          Complex c = b(i, j);\n                          Bx[i] = c.real ();\n                          Bz[i] = c.imag ();\n                        }\n\n                      F77_XFCN (dgbtrs, DGBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, n_upper, 1, tmp_data,\n                                 ldm, pipvt, Bx, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      F77_XFCN (dgbtrs, DGBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, n_upper, 1, tmp_data,\n                                 ldm, pipvt, Bz, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        retval(i, j) = Complex (Bx[i], Bz[i]);\n                    }\n                }\n            }\n        }\n      else if (typ != MatrixType::Banded_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseMatrix::bsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler sing_handler,\n                      bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Banded_Hermitian)\n        {\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_lower + 1;\n\n          Matrix m_band (ldm, nc);\n          double *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              {\n                octave_idx_type ri = ridx (i);\n                if (ri >= j)\n                  m_band(ri - j, j) = data (i);\n              }\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            anorm = m_band.abs ().sum ().row (0).max ();\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          F77_INT tmp_err = 0;\n\n          char job = 'L';\n          F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     tmp_nr, n_lower, tmp_data, ldm, tmp_err\n                                     F77_CHAR_ARG_LEN (1)));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              // Matrix is not positive definite!! Fall through to\n              // unsymmetric banded solver.\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Banded;\n\n              rcond = 0.0;\n              err = 0;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<double> z (dim_vector (3 * nr, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nr, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (dpbcon, DPBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nr, n_lower, tmp_data, ldm,\n                             anorm, rcond, pz, piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  octave_idx_type b_nc = b.cols ();\n                  OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);\n                  OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);\n\n                  // Take a first guess that the number of nonzero terms\n                  // will be as many as in b\n                  octave_idx_type x_nz = b.nnz ();\n                  octave_idx_type ii = 0;\n                  retval = SparseComplexMatrix (b_nr, b_nc, x_nz);\n\n                  retval.xcidx (0) = 0;\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n\n                      for (F77_INT i = 0; i < b_nr; i++)\n                        {\n                          Complex c = b(i, j);\n                          Bx[i] = c.real ();\n                          Bz[i] = c.imag ();\n                        }\n\n                      F77_XFCN (dpbtrs, DPBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, 1, tmp_data,\n                                 ldm, Bx, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      if (err != 0)\n                        {\n                          // FIXME: Should this be a warning?\n                          (*current_liboctave_error_handler)\n                            (\"SparseMatrix::solve solve failed\");\n                          err = -1;\n                          break;\n                        }\n\n                      F77_XFCN (dpbtrs, DPBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, 1, tmp_data,\n                                 ldm, Bz, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      if (err != 0)\n                        {\n                          // FIXME: Should this be a warning?\n                          (*current_liboctave_error_handler)\n                            (\"SparseMatrix::solve solve failed\");\n\n                          err = -1;\n                          break;\n                        }\n\n                      // Count nonzeros in work vector and adjust\n                      // space in retval if needed\n                      octave_idx_type new_nnz = 0;\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (Bx[i] != 0. || Bz[i] != 0.)\n                          new_nnz++;\n\n                      if (ii + new_nnz > x_nz)\n                        {\n                          // Resize the sparse matrix\n                          octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                          retval.change_capacity (sz);\n                          x_nz = sz;\n                        }\n\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (Bx[i] != 0. || Bz[i] != 0.)\n                          {\n                            retval.xridx (ii) = i;\n                            retval.xdata (ii++) = Complex (Bx[i], Bz[i]);\n                          }\n\n                      retval.xcidx (j+1) = ii;\n                    }\n\n                  retval.maybe_compress ();\n                }\n            }\n        }\n\n      if (typ == MatrixType::Banded)\n        {\n          // Create the storage for the banded form of the sparse matrix\n          F77_INT n_upper = octave::to_f77_int (mattype.nupper ());\n          F77_INT n_lower = octave::to_f77_int (mattype.nlower ());\n          F77_INT ldm = n_upper + 2 * n_lower + 1;\n\n          Matrix m_band (ldm, nc);\n          double *tmp_data = m_band.rwdata ();\n\n          if (! mattype.is_dense ())\n            {\n              octave_idx_type ii = 0;\n\n              for (F77_INT j = 0; j < ldm; j++)\n                for (octave_idx_type i = 0; i < nc; i++)\n                  tmp_data[ii++] = 0.;\n            }\n\n          for (octave_idx_type j = 0; j < nc; j++)\n            for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n              m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);\n\n          // Calculate the norm of the matrix, for later use.\n          double anorm;\n          if (calc_cond)\n            {\n              anorm = 0.0;\n              for (octave_idx_type j = 0; j < nr; j++)\n                {\n                  double atmp = 0.0;\n                  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)\n                    atmp += fabs (data (i));\n                  if (atmp > anorm)\n                    anorm = atmp;\n                }\n            }\n\n          F77_INT tmp_nr = octave::to_f77_int (nr);\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          F77_INT tmp_err = 0;\n\n          F77_XFCN (dgbtrf, DGBTRF, (tmp_nr, tmp_nr, n_lower, n_upper,\n                                     tmp_data, ldm, pipvt, tmp_err));\n\n          err = tmp_err;\n\n          if (err != 0)\n            {\n              err = -2;\n              rcond = 0.0;\n\n              if (sing_handler)\n                {\n                  sing_handler (rcond);\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                octave::warn_singular_matrix ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  char job = '1';\n                  Array<double> z (dim_vector (3 * nr, 1));\n                  double *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nr, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_INT tmp_nc = octave::to_f77_int (nc);\n\n                  F77_XFCN (dgbcon, DGBCON,\n                            (F77_CONST_CHAR_ARG2 (&job, 1),\n                             tmp_nc, n_lower, n_upper, tmp_data, ldm, pipvt,\n                             anorm, rcond, pz, piz, tmp_err\n                             F77_CHAR_ARG_LEN (1)));\n\n                  err = tmp_err;\n\n                  if (err != 0)\n                    err = -2;\n\n                  if (is_singular (rcond) || octave::math::isnan (rcond))\n                    {\n                      err = -2;\n\n                      if (sing_handler)\n                        {\n                          sing_handler (rcond);\n                          mattype.mark_as_rectangular ();\n                        }\n                      else\n                        octave::warn_singular_matrix (rcond);\n                    }\n                }\n              else\n                rcond = 1.;\n\n              if (err == 0)\n                {\n                  char job = 'N';\n                  octave_idx_type x_nz = b.nnz ();\n                  F77_INT b_nr = octave::to_f77_int (b.rows ());\n                  octave_idx_type b_nc = b.cols ();\n                  retval = SparseComplexMatrix (nr, b_nc, x_nz);\n                  retval.xcidx (0) = 0;\n                  octave_idx_type ii = 0;\n\n                  OCTAVE_LOCAL_BUFFER (double, Bx, nr);\n                  OCTAVE_LOCAL_BUFFER (double, Bz, nr);\n\n                  for (octave_idx_type j = 0; j < b_nc; j++)\n                    {\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        {\n                          Bx[i] = 0.;\n                          Bz[i] = 0.;\n                        }\n                      for (octave_idx_type i = b.cidx (j);\n                           i < b.cidx (j+1); i++)\n                        {\n                          Complex c = b.data (i);\n                          Bx[b.ridx (i)] = c.real ();\n                          Bz[b.ridx (i)] = c.imag ();\n                        }\n\n                      F77_XFCN (dgbtrs, DGBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, n_upper, 1, tmp_data,\n                                 ldm, pipvt, Bx, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      F77_XFCN (dgbtrs, DGBTRS,\n                                (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 tmp_nr, n_lower, n_upper, 1, tmp_data,\n                                 ldm, pipvt, Bz, b_nr, tmp_err\n                                 F77_CHAR_ARG_LEN (1)));\n\n                      err = tmp_err;\n\n                      // Count nonzeros in work vector and adjust\n                      // space in retval if needed\n                      octave_idx_type new_nnz = 0;\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (Bx[i] != 0. || Bz[i] != 0.)\n                          new_nnz++;\n\n                      if (ii + new_nnz > x_nz)\n                        {\n                          // Resize the sparse matrix\n                          octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;\n                          retval.change_capacity (sz);\n                          x_nz = sz;\n                        }\n\n                      for (octave_idx_type i = 0; i < nr; i++)\n                        if (Bx[i] != 0. || Bz[i] != 0.)\n                          {\n                            retval.xridx (ii) = i;\n                            retval.xdata (ii++) = Complex (Bx[i], Bz[i]);\n                          }\n                      retval.xcidx (j+1) = ii;\n                    }\n\n                  retval.maybe_compress ();\n                }\n            }\n        }\n      else if (typ != MatrixType::Banded_Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nvoid *\nSparseMatrix::factorize (octave_idx_type& err, double& rcond, Matrix& Control,\n                         Matrix& Info, solve_singularity_handler sing_handler,\n                         bool calc_cond) const\n{\n  // The return values\n  void *Numeric = nullptr;\n  err = 0;\n\n#if defined (HAVE_UMFPACK)\n\n  // Setup the control parameters\n  Control = Matrix (UMFPACK_CONTROL, 1);\n  double *control = Control.rwdata ();\n  UMFPACK_DNAME (defaults) (control);\n\n  double tmp = octave::sparse_params::get_key (\"spumoni\");\n  if (! octave::math::isnan (tmp))\n    Control (UMFPACK_PRL) = tmp;\n  tmp = octave::sparse_params::get_key (\"piv_tol\");\n  if (! octave::math::isnan (tmp))\n    {\n      Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;\n      Control (UMFPACK_PIVOT_TOLERANCE) = tmp;\n    }\n\n  // Set whether we are allowed to modify Q or not\n  tmp = octave::sparse_params::get_key (\"autoamd\");\n  if (! octave::math::isnan (tmp))\n    Control (UMFPACK_FIXQ) = tmp;\n\n  UMFPACK_DNAME (report_control) (control);\n\n  const octave_idx_type *Ap = cidx ();\n  const octave_idx_type *Ai = ridx ();\n  const double *Ax = data ();\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  UMFPACK_DNAME (report_matrix) (nr, nc,\n                                 octave::to_suitesparse_intptr (Ap),\n                                 octave::to_suitesparse_intptr (Ai),\n                                 Ax, 1, control);\n\n  void *Symbolic;\n  Info = Matrix (1, UMFPACK_INFO);\n  double *info = Info.rwdata ();\n  int status = UMFPACK_DNAME (qsymbolic) (nr, nc,\n                                          octave::to_suitesparse_intptr (Ap),\n                                          octave::to_suitesparse_intptr (Ai),\n                                          Ax, nullptr, &Symbolic, control, info);\n\n  if (status < 0)\n    {\n      UMFPACK_DNAME (report_status) (control, status);\n      UMFPACK_DNAME (report_info) (control, info);\n\n      UMFPACK_DNAME (free_symbolic) (&Symbolic);\n\n      // FIXME: Should this be a warning?\n      (*current_liboctave_error_handler)\n        (\"SparseMatrix::solve symbolic factorization failed\");\n      err = -1;\n    }\n  else\n    {\n      UMFPACK_DNAME (report_symbolic) (Symbolic, control);\n\n      status = UMFPACK_DNAME (numeric) (octave::to_suitesparse_intptr (Ap),\n                                        octave::to_suitesparse_intptr (Ai),\n                                        Ax, Symbolic, &Numeric, control, info);\n      UMFPACK_DNAME (free_symbolic) (&Symbolic);\n\n      if (calc_cond)\n        rcond = Info (UMFPACK_RCOND);\n      else\n        rcond = 1.;\n\n      if (status == UMFPACK_WARNING_singular_matrix\n          || is_singular (rcond) || octave::math::isnan (rcond))\n        {\n          UMFPACK_DNAME (report_numeric) (Numeric, control);\n\n          err = -2;\n\n          if (sing_handler)\n            sing_handler (rcond);\n          else\n            octave::warn_singular_matrix (rcond);\n        }\n      else if (status < 0)\n        {\n          UMFPACK_DNAME (report_status) (control, status);\n          UMFPACK_DNAME (report_info) (control, info);\n\n          // FIXME: Should this be a warning?\n          (*current_liboctave_error_handler)\n            (\"SparseMatrix::solve numeric factorization failed\");\n\n          err = -1;\n        }\n      else\n        {\n          UMFPACK_DNAME (report_numeric) (Numeric, control);\n        }\n    }\n\n  if (err != 0)\n    UMFPACK_DNAME (free_numeric) (&Numeric);\n\n#else\n\n  octave_unused_parameter (rcond);\n  octave_unused_parameter (Control);\n  octave_unused_parameter (Info);\n  octave_unused_parameter (sing_handler);\n  octave_unused_parameter (calc_cond);\n\n  (*current_liboctave_error_handler)\n    (\"support for UMFPACK was unavailable or disabled \"\n     \"when liboctave was built\");\n\n#endif\n\n  return Numeric;\n}\n\nMatrix\nSparseMatrix::fsolve (MatrixType& mattype, const Matrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler sing_handler,\n                      bool calc_cond) const\n{\n  Matrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = Matrix (nc, b.cols (), 0.0);\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Hermitian)\n        {\n#if defined (HAVE_CHOLMOD)\n          cholmod_common Common;\n          cholmod_common *cm = &Common;\n\n          // Setup initial parameters\n          CHOLMOD_NAME(start) (cm);\n          cm->prefer_zomplex = false;\n\n          double spu = octave::sparse_params::get_key (\"spumoni\");\n          if (spu == 0.)\n            {\n              cm->print = -1;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n            }\n          else\n            {\n              cm->print = static_cast<int> (spu) + 2;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);\n            }\n\n          cm->error_handler = &SparseCholError;\n          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);\n          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n          cm->final_ll = true;\n\n          cholmod_sparse Astore;\n          cholmod_sparse *A = &Astore;\n          A->nrow = nr;\n          A->ncol = nc;\n\n          A->p = const_cast<octave_idx_type *> (cidx ());\n          A->i = const_cast<octave_idx_type *> (ridx ());\n          A->nzmax = nnz ();\n          A->packed = true;\n          A->sorted = true;\n          A->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          A->itype = CHOLMOD_LONG;\n#else\n          A->itype = CHOLMOD_INT;\n#endif\n          A->dtype = CHOLMOD_DOUBLE;\n          A->stype = 1;\n          A->xtype = CHOLMOD_REAL;\n\n          A->x = const_cast<double *> (data ());\n\n          cholmod_dense Bstore;\n          cholmod_dense *B = &Bstore;\n          B->nrow = b.rows ();\n          B->ncol = b.cols ();\n          B->d = B->nrow;\n          B->nzmax = B->nrow * B->ncol;\n          B->dtype = CHOLMOD_DOUBLE;\n          B->xtype = CHOLMOD_REAL;\n\n          B->x = const_cast<double *> (b.data ());\n\n          cholmod_factor *L = CHOLMOD_NAME(analyze) (A, cm);\n          CHOLMOD_NAME(factorize) (A, L, cm);\n          if (calc_cond)\n            rcond = CHOLMOD_NAME(rcond)(L, cm);\n          else\n            rcond = 1.0;\n\n          if (rcond == 0.0)\n            {\n              // Either its indefinite or singular.  Try UMFPACK\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (is_singular (rcond) || octave::math::isnan (rcond))\n                {\n                  err = -2;\n\n                  if (sing_handler)\n                    {\n                      sing_handler (rcond);\n                      mattype.mark_as_rectangular ();\n                    }\n                  else\n                    octave::warn_singular_matrix (rcond);\n\n                  return retval;\n                }\n\n              cholmod_dense *X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm);\n\n              retval.resize (b.rows (), b.cols ());\n              for (octave_idx_type j = 0; j < b.cols (); j++)\n                {\n                  octave_idx_type jr = j * b.rows ();\n                  for (octave_idx_type i = 0; i < b.rows (); i++)\n                    retval.xelem (i, j) = static_cast<double *> (X->x)[jr + i];\n                }\n\n              CHOLMOD_NAME(free_dense) (&X, cm);\n              CHOLMOD_NAME(free_factor) (&L, cm);\n              CHOLMOD_NAME(finish) (cm);\n              static char blank_name[] = \" \";\n              CHOLMOD_NAME(print_common) (blank_name, cm);\n            }\n#else\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:missing-dependency\",\n             \"support for CHOLMOD was unavailable or disabled \"\n             \"when liboctave was built\");\n\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n#endif\n        }\n\n      if (typ == MatrixType::Full)\n        {\n#if defined (HAVE_UMFPACK)\n          Matrix Control, Info;\n          void *Numeric\n            = factorize (err, rcond, Control, Info, sing_handler, calc_cond);\n\n          if (err == 0)\n            {\n              // one iterative refinement instead of the default two in UMFPACK\n              Control (UMFPACK_IRSTEP) = 1;\n              const double *Bx = b.data ();\n              retval.resize (b.rows (), b.cols ());\n              double *result = retval.rwdata ();\n              octave_idx_type b_nr = b.rows ();\n              octave_idx_type b_nc = b.cols ();\n              int status = 0;\n              double *control = Control.rwdata ();\n              double *info = Info.rwdata ();\n              const octave_idx_type *Ap = cidx ();\n              const octave_idx_type *Ai = ridx ();\n              const double *Ax = data ();\n\n              for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr)\n                {\n                  status = UMFPACK_DNAME (solve) (UMFPACK_A,\n                                                  octave::to_suitesparse_intptr (Ap),\n                                                  octave::to_suitesparse_intptr (Ai),\n                                                  Ax, &result[iidx], &Bx[iidx],\n                                                  Numeric, control, info);\n                  if (status < 0)\n                    {\n                      UMFPACK_DNAME (report_status) (control, status);\n\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n                }\n\n              UMFPACK_DNAME (report_info) (control, info);\n\n              UMFPACK_DNAME (free_numeric) (&Numeric);\n            }\n          else\n            mattype.mark_as_rectangular ();\n\n#else\n          octave_unused_parameter (rcond);\n          octave_unused_parameter (sing_handler);\n          octave_unused_parameter (calc_cond);\n\n          (*current_liboctave_error_handler)\n            (\"support for UMFPACK was unavailable or disabled \"\n             \"when liboctave was built\");\n#endif\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::fsolve (MatrixType& mattype, const SparseMatrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler sing_handler,\n                      bool calc_cond) const\n{\n  SparseMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Hermitian)\n        {\n#if defined (HAVE_CHOLMOD)\n          cholmod_common Common;\n          cholmod_common *cm = &Common;\n\n          // Setup initial parameters\n          CHOLMOD_NAME(start) (cm);\n          cm->prefer_zomplex = false;\n\n          double spu = octave::sparse_params::get_key (\"spumoni\");\n          if (spu == 0.)\n            {\n              cm->print = -1;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n            }\n          else\n            {\n              cm->print = static_cast<int> (spu) + 2;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);\n            }\n\n          cm->error_handler = &SparseCholError;\n          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);\n          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n          cm->final_ll = true;\n\n          cholmod_sparse Astore;\n          cholmod_sparse *A = &Astore;\n          A->nrow = nr;\n          A->ncol = nc;\n\n          A->p = const_cast<octave_idx_type *> (cidx ());\n          A->i = const_cast<octave_idx_type *> (ridx ());\n          A->nzmax = nnz ();\n          A->packed = true;\n          A->sorted = true;\n          A->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          A->itype = CHOLMOD_LONG;\n#else\n          A->itype = CHOLMOD_INT;\n#endif\n          A->dtype = CHOLMOD_DOUBLE;\n          A->stype = 1;\n          A->xtype = CHOLMOD_REAL;\n\n          A->x = const_cast<double *> (data ());\n\n          cholmod_sparse Bstore;\n          cholmod_sparse *B = &Bstore;\n          B->nrow = b.rows ();\n          B->ncol = b.cols ();\n          B->p = const_cast<octave_idx_type *> (b.cidx ());\n          B->i = const_cast<octave_idx_type *> (b.ridx ());\n          B->nzmax = b.nnz ();\n          B->packed = true;\n          B->sorted = true;\n          B->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          B->itype = CHOLMOD_LONG;\n#else\n          B->itype = CHOLMOD_INT;\n#endif\n          B->dtype = CHOLMOD_DOUBLE;\n          B->stype = 0;\n          B->xtype = CHOLMOD_REAL;\n\n          B->x = const_cast<double *> (b.data ());\n\n          cholmod_factor *L = CHOLMOD_NAME(analyze) (A, cm);\n          CHOLMOD_NAME(factorize) (A, L, cm);\n          if (calc_cond)\n            rcond = CHOLMOD_NAME(rcond)(L, cm);\n          else\n            rcond = 1.;\n\n          if (rcond == 0.0)\n            {\n              // Either its indefinite or singular.  Try UMFPACK\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (is_singular (rcond) || octave::math::isnan (rcond))\n                {\n                  err = -2;\n\n                  if (sing_handler)\n                    {\n                      sing_handler (rcond);\n                      mattype.mark_as_rectangular ();\n                    }\n                  else\n                    octave::warn_singular_matrix (rcond);\n\n                  return retval;\n                }\n\n              cholmod_sparse *X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm);\n\n              retval = SparseMatrix\n                       (octave::from_size_t (X->nrow),\n                        octave::from_size_t (X->ncol),\n                        octave::from_suitesparse_long (CHOLMOD_NAME(nnz)\n                                                       (X, cm)));\n              for (octave_idx_type j = 0;\n                   j <= static_cast<octave_idx_type> (X->ncol); j++)\n                retval.xcidx (j) = static_cast<octave_idx_type *> (X->p)[j];\n              for (octave_idx_type j = 0;\n                   j < octave::from_suitesparse_long (CHOLMOD_NAME(nnz) (X, cm));\n                   j++)\n                {\n                  retval.xridx (j) = static_cast<octave_idx_type *> (X->i)[j];\n                  retval.xdata (j) = static_cast<double *> (X->x)[j];\n                }\n\n              CHOLMOD_NAME(free_sparse) (&X, cm);\n              CHOLMOD_NAME(free_factor) (&L, cm);\n              CHOLMOD_NAME(finish) (cm);\n              static char blank_name[] = \" \";\n              CHOLMOD_NAME(print_common) (blank_name, cm);\n            }\n#else\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:missing-dependency\",\n             \"support for CHOLMOD was unavailable or disabled \"\n             \"when liboctave was built\");\n\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n#endif\n        }\n\n      if (typ == MatrixType::Full)\n        {\n#if defined (HAVE_UMFPACK)\n          Matrix Control, Info;\n          void *Numeric = factorize (err, rcond, Control, Info,\n                                     sing_handler, calc_cond);\n\n          if (err == 0)\n            {\n              // one iterative refinement instead of the default two in UMFPACK\n              Control (UMFPACK_IRSTEP) = 1;\n              octave_idx_type b_nr = b.rows ();\n              octave_idx_type b_nc = b.cols ();\n              int status = 0;\n              double *control = Control.rwdata ();\n              double *info = Info.rwdata ();\n              const octave_idx_type *Ap = cidx ();\n              const octave_idx_type *Ai = ridx ();\n              const double *Ax = data ();\n\n              OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);\n              OCTAVE_LOCAL_BUFFER (double, Xx, b_nr);\n\n              // Take a first guess that the number of nonzero terms\n              // will be as many as in b\n              octave_idx_type x_nz = b.nnz ();\n              octave_idx_type ii = 0;\n              retval = SparseMatrix (b_nr, b_nc, x_nz);\n\n              retval.xcidx (0) = 0;\n              for (octave_idx_type j = 0; j < b_nc; j++)\n                {\n\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    Bx[i] = b.elem (i, j);\n\n                  status = UMFPACK_DNAME (solve) (UMFPACK_A,\n                                                  octave::to_suitesparse_intptr (Ap),\n                                                  octave::to_suitesparse_intptr (Ai),\n                                                  Ax, Xx, Bx, Numeric,\n                                                  control, info);\n                  if (status < 0)\n                    {\n                      UMFPACK_DNAME (report_status) (control, status);\n\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    {\n                      double tmp = Xx[i];\n                      if (tmp != 0.0)\n                        {\n                          if (ii == x_nz)\n                            {\n                              // Resize the sparse matrix\n                              octave_idx_type sz;\n                              sz = (static_cast<double> (b_nc) - j) / b_nc\n                                   * x_nz;\n                              sz = x_nz + (sz > 100 ? sz : 100);\n                              retval.change_capacity (sz);\n                              x_nz = sz;\n                            }\n                          retval.xdata (ii) = tmp;\n                          retval.xridx (ii++) = i;\n                        }\n                    }\n                  retval.xcidx (j+1) = ii;\n                }\n\n              retval.maybe_compress ();\n\n              UMFPACK_DNAME (report_info) (control, info);\n\n              UMFPACK_DNAME (free_numeric) (&Numeric);\n            }\n          else\n            mattype.mark_as_rectangular ();\n\n#else\n          octave_unused_parameter (rcond);\n          octave_unused_parameter (sing_handler);\n          octave_unused_parameter (calc_cond);\n\n          (*current_liboctave_error_handler)\n            (\"support for UMFPACK was unavailable or disabled \"\n             \"when liboctave was built\");\n#endif\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseMatrix::fsolve (MatrixType& mattype, const ComplexMatrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler sing_handler,\n                      bool calc_cond) const\n{\n  ComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0));\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Hermitian)\n        {\n#if defined (HAVE_CHOLMOD)\n          cholmod_common Common;\n          cholmod_common *cm = &Common;\n\n          // Setup initial parameters\n          CHOLMOD_NAME(start) (cm);\n          cm->prefer_zomplex = false;\n\n          double spu = octave::sparse_params::get_key (\"spumoni\");\n          if (spu == 0.)\n            {\n              cm->print = -1;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n            }\n          else\n            {\n              cm->print = static_cast<int> (spu) + 2;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);\n            }\n\n          cm->error_handler = &SparseCholError;\n          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);\n          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n          cm->final_ll = true;\n\n          cholmod_sparse Astore;\n          cholmod_sparse *A = &Astore;\n          A->nrow = nr;\n          A->ncol = nc;\n\n          A->p = const_cast<octave_idx_type *> (cidx ());\n          A->i = const_cast<octave_idx_type *> (ridx ());\n          A->nzmax = nnz ();\n          A->packed = true;\n          A->sorted = true;\n          A->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          A->itype = CHOLMOD_LONG;\n#else\n          A->itype = CHOLMOD_INT;\n#endif\n          A->dtype = CHOLMOD_DOUBLE;\n          A->stype = 1;\n          A->xtype = CHOLMOD_REAL;\n\n          A->x = const_cast<double *> (data ());\n\n          cholmod_dense Bstore;\n          cholmod_dense *B = &Bstore;\n          B->nrow = b.rows ();\n          B->ncol = b.cols ();\n          B->d = B->nrow;\n          B->nzmax = B->nrow * B->ncol;\n          B->dtype = CHOLMOD_DOUBLE;\n          B->xtype = CHOLMOD_COMPLEX;\n\n          B->x = const_cast<Complex *> (b.data ());\n\n          cholmod_factor *L = CHOLMOD_NAME(analyze) (A, cm);\n          CHOLMOD_NAME(factorize) (A, L, cm);\n          if (calc_cond)\n            rcond = CHOLMOD_NAME(rcond)(L, cm);\n          else\n            rcond = 1.0;\n\n          if (rcond == 0.0)\n            {\n              // Either its indefinite or singular.  Try UMFPACK\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (is_singular (rcond) || octave::math::isnan (rcond))\n                {\n                  err = -2;\n\n                  if (sing_handler)\n                    {\n                      sing_handler (rcond);\n                      mattype.mark_as_rectangular ();\n                    }\n                  else\n                    octave::warn_singular_matrix (rcond);\n\n                  return retval;\n                }\n\n              cholmod_dense *X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm);\n\n              retval.resize (b.rows (), b.cols ());\n              for (octave_idx_type j = 0; j < b.cols (); j++)\n                {\n                  octave_idx_type jr = j * b.rows ();\n                  for (octave_idx_type i = 0; i < b.rows (); i++)\n                    retval.xelem (i, j) = static_cast<Complex *> (X->x)[jr + i];\n                }\n\n              CHOLMOD_NAME(free_dense) (&X, cm);\n              CHOLMOD_NAME(free_factor) (&L, cm);\n              CHOLMOD_NAME(finish) (cm);\n              static char blank_name[] = \" \";\n              CHOLMOD_NAME(print_common) (blank_name, cm);\n            }\n#else\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:missing-dependency\",\n             \"support for CHOLMOD was unavailable or disabled \"\n             \"when liboctave was built\");\n\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n#endif\n        }\n\n      if (typ == MatrixType::Full)\n        {\n#if defined (HAVE_UMFPACK)\n          Matrix Control, Info;\n          void *Numeric = factorize (err, rcond, Control, Info,\n                                     sing_handler, calc_cond);\n\n          if (err == 0)\n            {\n              // one iterative refinement instead of the default two in UMFPACK\n              Control (UMFPACK_IRSTEP) = 1;\n              octave_idx_type b_nr = b.rows ();\n              octave_idx_type b_nc = b.cols ();\n              int status = 0;\n              double *control = Control.rwdata ();\n              double *info = Info.rwdata ();\n              const octave_idx_type *Ap = cidx ();\n              const octave_idx_type *Ai = ridx ();\n              const double *Ax = data ();\n\n              OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);\n              OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);\n\n              retval.resize (b_nr, b_nc);\n\n              OCTAVE_LOCAL_BUFFER (double, Xx, b_nr);\n              OCTAVE_LOCAL_BUFFER (double, Xz, b_nr);\n\n              for (octave_idx_type j = 0; j < b_nc; j++)\n                {\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    {\n                      Complex c = b(i, j);\n                      Bx[i] = c.real ();\n                      Bz[i] = c.imag ();\n                    }\n\n                  status = UMFPACK_DNAME (solve) (UMFPACK_A,\n                                                  octave::to_suitesparse_intptr (Ap),\n                                                  octave::to_suitesparse_intptr (Ai),\n                                                  Ax, Xx, Bx, Numeric,\n                                                  control, info);\n                  int status2 = UMFPACK_DNAME (solve) (UMFPACK_A,\n                                                       octave::to_suitesparse_intptr (Ap),\n                                                       octave::to_suitesparse_intptr (Ai),\n                                                       Ax, Xz, Bz,\n                                                       Numeric, control, info);\n\n                  if (status < 0 || status2 < 0)\n                    {\n                      UMFPACK_DNAME (report_status) (control, status);\n\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    retval(i, j) = Complex (Xx[i], Xz[i]);\n                }\n\n              UMFPACK_DNAME (report_info) (control, info);\n\n              UMFPACK_DNAME (free_numeric) (&Numeric);\n            }\n          else\n            mattype.mark_as_rectangular ();\n\n#else\n          octave_unused_parameter (rcond);\n          octave_unused_parameter (sing_handler);\n          octave_unused_parameter (calc_cond);\n\n          (*current_liboctave_error_handler)\n            (\"support for UMFPACK was unavailable or disabled \"\n             \"when liboctave was built\");\n#endif\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseMatrix::fsolve (MatrixType& mattype, const SparseComplexMatrix& b,\n                      octave_idx_type& err, double& rcond,\n                      solve_singularity_handler sing_handler,\n                      bool calc_cond) const\n{\n  SparseComplexMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  err = 0;\n\n  if (nr != nc || nr != b.rows ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b.cols () == 0)\n    retval = SparseComplexMatrix (nc, b.cols ());\n  else\n    {\n      // Print spparms(\"spumoni\") info if requested\n      int typ = mattype.type ();\n      mattype.info ();\n\n      if (typ == MatrixType::Hermitian)\n        {\n#if defined (HAVE_CHOLMOD)\n          cholmod_common Common;\n          cholmod_common *cm = &Common;\n\n          // Setup initial parameters\n          CHOLMOD_NAME(start) (cm);\n          cm->prefer_zomplex = false;\n\n          double spu = octave::sparse_params::get_key (\"spumoni\");\n          if (spu == 0.)\n            {\n              cm->print = -1;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n            }\n          else\n            {\n              cm->print = static_cast<int> (spu) + 2;\n              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);\n            }\n\n          cm->error_handler = &SparseCholError;\n          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);\n          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n          cm->final_ll = true;\n\n          cholmod_sparse Astore;\n          cholmod_sparse *A = &Astore;\n          A->nrow = nr;\n          A->ncol = nc;\n\n          A->p = const_cast<octave_idx_type *> (cidx ());\n          A->i = const_cast<octave_idx_type *> (ridx ());\n          A->nzmax = nnz ();\n          A->packed = true;\n          A->sorted = true;\n          A->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          A->itype = CHOLMOD_LONG;\n#else\n          A->itype = CHOLMOD_INT;\n#endif\n          A->dtype = CHOLMOD_DOUBLE;\n          A->stype = 1;\n          A->xtype = CHOLMOD_REAL;\n\n          A->x = const_cast<double *> (data ());\n\n          cholmod_sparse Bstore;\n          cholmod_sparse *B = &Bstore;\n          B->nrow = b.rows ();\n          B->ncol = b.cols ();\n          B->p = const_cast<octave_idx_type *> (b.cidx ());\n          B->i = const_cast<octave_idx_type *> (b.ridx ());\n          B->nzmax = b.nnz ();\n          B->packed = true;\n          B->sorted = true;\n          B->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n          B->itype = CHOLMOD_LONG;\n#else\n          B->itype = CHOLMOD_INT;\n#endif\n          B->dtype = CHOLMOD_DOUBLE;\n          B->stype = 0;\n          B->xtype = CHOLMOD_COMPLEX;\n\n          B->x = const_cast<Complex *> (b.data ());\n\n          cholmod_factor *L = CHOLMOD_NAME(analyze) (A, cm);\n          CHOLMOD_NAME(factorize) (A, L, cm);\n          if (calc_cond)\n            rcond = CHOLMOD_NAME(rcond)(L, cm);\n          else\n            rcond = 1.0;\n\n          if (rcond == 0.0)\n            {\n              // Either its indefinite or singular.  Try UMFPACK\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (is_singular (rcond) || octave::math::isnan (rcond))\n                {\n                  err = -2;\n\n                  if (sing_handler)\n                    {\n                      sing_handler (rcond);\n                      mattype.mark_as_rectangular ();\n                    }\n                  else\n                    octave::warn_singular_matrix (rcond);\n\n                  return retval;\n                }\n\n              cholmod_sparse *X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm);\n\n              retval = SparseComplexMatrix\n                       (octave::from_size_t (X->nrow),\n                        octave::from_size_t (X->ncol),\n                        octave::from_suitesparse_long (CHOLMOD_NAME(nnz)\n                                                       (X, cm)));\n              for (octave_idx_type j = 0;\n                   j <= static_cast<octave_idx_type> (X->ncol); j++)\n                retval.xcidx (j) = static_cast<octave_idx_type *> (X->p)[j];\n              for (octave_idx_type j = 0;\n                   j < octave::from_suitesparse_long (CHOLMOD_NAME(nnz) (X, cm));\n                   j++)\n                {\n                  retval.xridx (j) = static_cast<octave_idx_type *> (X->i)[j];\n                  retval.xdata (j) = static_cast<Complex *> (X->x)[j];\n                }\n\n              CHOLMOD_NAME(free_sparse) (&X, cm);\n              CHOLMOD_NAME(free_factor) (&L, cm);\n              CHOLMOD_NAME(finish) (cm);\n              static char blank_name[] = \" \";\n              CHOLMOD_NAME(print_common) (blank_name, cm);\n            }\n#else\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:missing-dependency\",\n             \"support for CHOLMOD was unavailable or disabled \"\n             \"when liboctave was built\");\n\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n#endif\n        }\n\n      if (typ == MatrixType::Full)\n        {\n#if defined (HAVE_UMFPACK)\n          Matrix Control, Info;\n          void *Numeric = factorize (err, rcond, Control, Info,\n                                     sing_handler, calc_cond);\n\n          if (err == 0)\n            {\n              // one iterative refinement instead of the default two in UMFPACK\n              Control (UMFPACK_IRSTEP) = 1;\n              octave_idx_type b_nr = b.rows ();\n              octave_idx_type b_nc = b.cols ();\n              int status = 0;\n              double *control = Control.rwdata ();\n              double *info = Info.rwdata ();\n              const octave_idx_type *Ap = cidx ();\n              const octave_idx_type *Ai = ridx ();\n              const double *Ax = data ();\n\n              OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);\n              OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);\n\n              // Take a first guess that the number of nonzero terms\n              // will be as many as in b\n              octave_idx_type x_nz = b.nnz ();\n              octave_idx_type ii = 0;\n              retval = SparseComplexMatrix (b_nr, b_nc, x_nz);\n\n              OCTAVE_LOCAL_BUFFER (double, Xx, b_nr);\n              OCTAVE_LOCAL_BUFFER (double, Xz, b_nr);\n\n              retval.xcidx (0) = 0;\n              for (octave_idx_type j = 0; j < b_nc; j++)\n                {\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    {\n                      Complex c = b(i, j);\n                      Bx[i] = c.real ();\n                      Bz[i] = c.imag ();\n                    }\n\n                  status = UMFPACK_DNAME (solve) (UMFPACK_A,\n                                                  octave::to_suitesparse_intptr (Ap),\n                                                  octave::to_suitesparse_intptr (Ai),\n                                                  Ax, Xx, Bx, Numeric,\n                                                  control, info);\n                  int status2 = UMFPACK_DNAME (solve) (UMFPACK_A,\n                                                       octave::to_suitesparse_intptr (Ap),\n                                                       octave::to_suitesparse_intptr (Ai),\n                                                       Ax, Xz, Bz,\n                                                       Numeric, control, info);\n\n                  if (status < 0 || status2 < 0)\n                    {\n                      UMFPACK_DNAME (report_status) (control, status);\n\n                      // FIXME: Should this be a warning?\n                      (*current_liboctave_error_handler)\n                        (\"SparseMatrix::solve solve failed\");\n\n                      err = -1;\n                      break;\n                    }\n\n                  for (octave_idx_type i = 0; i < b_nr; i++)\n                    {\n                      Complex tmp = Complex (Xx[i], Xz[i]);\n                      if (tmp != 0.0)\n                        {\n                          if (ii == x_nz)\n                            {\n                              // Resize the sparse matrix\n                              octave_idx_type sz;\n                              sz = (static_cast<double> (b_nc) - j) / b_nc\n                                   * x_nz;\n                              sz = x_nz + (sz > 100 ? sz : 100);\n                              retval.change_capacity (sz);\n                              x_nz = sz;\n                            }\n                          retval.xdata (ii) = tmp;\n                          retval.xridx (ii++) = i;\n                        }\n                    }\n                  retval.xcidx (j+1) = ii;\n                }\n\n              retval.maybe_compress ();\n\n              UMFPACK_DNAME (report_info) (control, info);\n\n              UMFPACK_DNAME (free_numeric) (&Numeric);\n            }\n          else\n            mattype.mark_as_rectangular ();\n#else\n          octave_unused_parameter (rcond);\n          octave_unused_parameter (sing_handler);\n          octave_unused_parameter (calc_cond);\n\n          (*current_liboctave_error_handler)\n            (\"support for UMFPACK was unavailable or disabled \"\n             \"when liboctave was built\");\n#endif\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nMatrix\nSparseMatrix::solve (MatrixType& mattype, const Matrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nMatrix\nSparseMatrix::solve (MatrixType& mattype, const Matrix& b,\n                     octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nMatrix\nSparseMatrix::solve (MatrixType& mattype, const Matrix& b,\n                     octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nMatrix\nSparseMatrix::solve (MatrixType& mattype, const Matrix& b, octave_idx_type& err,\n                     double& rcond, solve_singularity_handler sing_handler,\n                     bool singular_fallback) const\n{\n  Matrix retval;\n  int typ = mattype.type (false);\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  // Only calculate the condition number for CHOLMOD/UMFPACK\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    retval = dsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)\n    retval = bsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Tridiagonal\n           || typ == MatrixType::Tridiagonal_Hermitian)\n    retval = trisolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, err, rcond, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  // Rectangular or one of the above solvers flags a singular matrix\n  if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)\n    {\n      rcond = 1.;\n      retval = dmsolve<Matrix, SparseMatrix, Matrix> (*this, b, err);\n    }\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::solve (MatrixType& mattype, const SparseMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseMatrix\nSparseMatrix::solve (MatrixType& mattype, const SparseMatrix& b,\n                     octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseMatrix\nSparseMatrix::solve (MatrixType& mattype, const SparseMatrix& b,\n                     octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseMatrix\nSparseMatrix::solve (MatrixType& mattype, const SparseMatrix& b,\n                     octave_idx_type& err, double& rcond,\n                     solve_singularity_handler sing_handler,\n                     bool singular_fallback) const\n{\n  SparseMatrix retval;\n  int typ = mattype.type (false);\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    retval = dsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)\n    retval = bsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Tridiagonal\n           || typ == MatrixType::Tridiagonal_Hermitian)\n    retval = trisolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, err, rcond, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)\n    {\n      rcond = 1.;\n      retval = dmsolve<SparseMatrix, SparseMatrix, SparseMatrix>\n               (*this, b, err);\n    }\n\n  return retval;\n}\n\nComplexMatrix\nSparseMatrix::solve (MatrixType& mattype, const ComplexMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n                     octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n                     octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseMatrix::solve (MatrixType& mattype, const ComplexMatrix& b,\n                     octave_idx_type& err, double& rcond,\n                     solve_singularity_handler sing_handler,\n                     bool singular_fallback) const\n{\n  ComplexMatrix retval;\n  int typ = mattype.type (false);\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    retval = dsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)\n    retval = bsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Tridiagonal\n           || typ == MatrixType::Tridiagonal_Hermitian)\n    retval = trisolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, err, rcond, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)\n    {\n      rcond = 1.;\n      retval = dmsolve<ComplexMatrix, SparseMatrix, ComplexMatrix>\n               (*this, b, err);\n    }\n\n  return retval;\n}\n\nSparseComplexMatrix\nSparseMatrix::solve (MatrixType& mattype, const SparseComplexMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseMatrix::solve (MatrixType& mattype, const SparseComplexMatrix& b,\n                     octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseMatrix::solve (MatrixType& mattype, const SparseComplexMatrix& b,\n                     octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseMatrix::solve (MatrixType& mattype, const SparseComplexMatrix& b,\n                     octave_idx_type& err, double& rcond,\n                     solve_singularity_handler sing_handler,\n                     bool singular_fallback) const\n{\n  SparseComplexMatrix retval;\n  int typ = mattype.type (false);\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)\n    retval = dsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)\n    retval = bsolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Tridiagonal\n           || typ == MatrixType::Tridiagonal_Hermitian)\n    retval = trisolve (mattype, b, err, rcond, sing_handler, false);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, err, rcond, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)\n    {\n      rcond = 1.;\n      retval = dmsolve<SparseComplexMatrix, SparseMatrix, SparseComplexMatrix>\n               (*this, b, err);\n    }\n\n  return retval;\n}\n\nColumnVector\nSparseMatrix::solve (MatrixType& mattype, const ColumnVector& b) const\n{\n  octave_idx_type info; double rcond;\n  return solve (mattype, b, info, rcond);\n}\n\nColumnVector\nSparseMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n                     octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond);\n}\n\nColumnVector\nSparseMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n                     octave_idx_type& info, double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nColumnVector\nSparseMatrix::solve (MatrixType& mattype, const ColumnVector& b,\n                     octave_idx_type& info, double& rcond,\n                     solve_singularity_handler sing_handler) const\n{\n  Matrix tmp (b);\n  return solve (mattype, tmp, info, rcond,\n                sing_handler).column (static_cast<octave_idx_type> (0));\n}\n\nComplexColumnVector\nSparseMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n                     octave_idx_type& info) const\n{\n  double rcond;\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n                     octave_idx_type& info,\n                     double& rcond) const\n{\n  return solve (mattype, b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseMatrix::solve (MatrixType& mattype, const ComplexColumnVector& b,\n                     octave_idx_type& info, double& rcond,\n                     solve_singularity_handler sing_handler) const\n{\n  ComplexMatrix tmp (b);\n  return solve (mattype, tmp, info, rcond,\n                sing_handler).column (static_cast<octave_idx_type> (0));\n}\n\nMatrix\nSparseMatrix::solve (const Matrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nMatrix\nSparseMatrix::solve (const Matrix& b, octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nMatrix\nSparseMatrix::solve (const Matrix& b, octave_idx_type& info,\n                     double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nMatrix\nSparseMatrix::solve (const Matrix& b, octave_idx_type& err, double& rcond,\n                     solve_singularity_handler sing_handler) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, err, rcond, sing_handler);\n}\n\nSparseMatrix\nSparseMatrix::solve (const SparseMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseMatrix\nSparseMatrix::solve (const SparseMatrix& b,\n                     octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseMatrix\nSparseMatrix::solve (const SparseMatrix& b,\n                     octave_idx_type& info, double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseMatrix\nSparseMatrix::solve (const SparseMatrix& b, octave_idx_type& err, double& rcond,\n                     solve_singularity_handler sing_handler) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, err, rcond, sing_handler);\n}\n\nComplexMatrix\nSparseMatrix::solve (const ComplexMatrix& b, octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseMatrix::solve (const ComplexMatrix& b, octave_idx_type& info,\n                     double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexMatrix\nSparseMatrix::solve (const ComplexMatrix& b, octave_idx_type& err,\n                     double& rcond,\n                     solve_singularity_handler sing_handler) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, err, rcond, sing_handler);\n}\n\nSparseComplexMatrix\nSparseMatrix::solve (const SparseComplexMatrix& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseMatrix::solve (const SparseComplexMatrix& b, octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseMatrix::solve (const SparseComplexMatrix& b, octave_idx_type& info,\n                     double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nSparseComplexMatrix\nSparseMatrix::solve (const SparseComplexMatrix& b,\n                     octave_idx_type& err, double& rcond,\n                     solve_singularity_handler sing_handler) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, err, rcond, sing_handler);\n}\n\nColumnVector\nSparseMatrix::solve (const ColumnVector& b) const\n{\n  octave_idx_type info; double rcond;\n  return solve (b, info, rcond);\n}\n\nColumnVector\nSparseMatrix::solve (const ColumnVector& b, octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond);\n}\n\nColumnVector\nSparseMatrix::solve (const ColumnVector& b, octave_idx_type& info,\n                     double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nColumnVector\nSparseMatrix::solve (const ColumnVector& b, octave_idx_type& info,\n                     double& rcond,\n                     solve_singularity_handler sing_handler) const\n{\n  Matrix tmp (b);\n  return solve (tmp, info, rcond,\n                sing_handler).column (static_cast<octave_idx_type> (0));\n}\n\nComplexColumnVector\nSparseMatrix::solve (const ComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const\n{\n  double rcond;\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,\n                     double& rcond) const\n{\n  return solve (b, info, rcond, nullptr);\n}\n\nComplexColumnVector\nSparseMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,\n                     double& rcond,\n                     solve_singularity_handler sing_handler) const\n{\n  ComplexMatrix tmp (b);\n  return solve (tmp, info, rcond,\n                sing_handler).column (static_cast<octave_idx_type> (0));\n}\n\n// other operations.\n\nbool\nSparseMatrix::any_element_is_negative (bool neg_zero) const\n{\n  octave_idx_type nel = nnz ();\n\n  if (neg_zero)\n    {\n      for (octave_idx_type i = 0; i < nel; i++)\n        if (octave::math::signbit (data (i)))\n          return true;\n    }\n  else\n    {\n      for (octave_idx_type i = 0; i < nel; i++)\n        if (data (i) < 0)\n          return true;\n    }\n\n  return false;\n}\n\nbool\nSparseMatrix::any_element_is_nan () const\n{\n  octave_idx_type nel = nnz ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      double val = data (i);\n      if (octave::math::isnan (val))\n        return true;\n    }\n\n  return false;\n}\n\nbool\nSparseMatrix::any_element_is_inf_or_nan () const\n{\n  octave_idx_type nel = nnz ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      double val = data (i);\n      if (octave::math::isinf (val) || octave::math::isnan (val))\n        return true;\n    }\n\n  return false;\n}\n\nbool\nSparseMatrix::any_element_not_one_or_zero () const\n{\n  octave_idx_type nel = nnz ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      double val = data (i);\n      if (val != 0.0 && val != 1.0)\n        return true;\n    }\n\n  return false;\n}\n\nbool\nSparseMatrix::all_elements_are_zero () const\n{\n  octave_idx_type nel = nnz ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    if (data (i) != 0)\n      return false;\n\n  return true;\n}\n\nbool\nSparseMatrix::all_elements_are_int_or_inf_or_nan () const\n{\n  octave_idx_type nel = nnz ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      double val = data (i);\n      if (octave::math::isnan (val) || octave::math::is_integer (val))\n        continue;\n      else\n        return false;\n    }\n\n  return true;\n}\n\n// Return nonzero if any element of M is not an integer.  Also extract\n// the largest and smallest values and return them in MAX_VAL and MIN_VAL.\n\nbool\nSparseMatrix::all_integers (double& max_val, double& min_val) const\n{\n  octave_idx_type nel = nnz ();\n\n  if (nel == 0)\n    return false;\n\n  max_val = data (0);\n  min_val = data (0);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      double val = data (i);\n\n      if (val > max_val)\n        max_val = val;\n\n      if (val < min_val)\n        min_val = val;\n\n      if (! octave::math::is_integer (val))\n        return false;\n    }\n\n  return true;\n}\n\nbool\nSparseMatrix::too_large_for_float () const\n{\n  return test_any (octave::too_large_for_float);\n}\n\nSparseBoolMatrix\nSparseMatrix::operator ! () const\n{\n  if (any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  octave_idx_type nz1 = nnz ();\n  octave_idx_type nz2 = nr*nc - nz1;\n\n  SparseBoolMatrix r (nr, nc, nz2);\n\n  octave_idx_type ii = 0;\n  octave_idx_type jj = 0;\n  r.cidx (0) = 0;\n  for (octave_idx_type i = 0; i < nc; i++)\n    {\n      for (octave_idx_type j = 0; j < nr; j++)\n        {\n          if (jj < cidx (i+1) && ridx (jj) == j)\n            jj++;\n          else\n            {\n              r.data (ii) = true;\n              r.ridx (ii++) = j;\n            }\n        }\n      r.cidx (i+1) = ii;\n    }\n\n  return r;\n}\n\n// FIXME: Do these really belong here?  Maybe they should be in a base class?\n\nSparseBoolMatrix\nSparseMatrix::all (int dim) const\n{\n  SPARSE_ANY_ALL_HEADER\n  SPARSE_ALL_OP (dim);\n}\n\nSparseBoolMatrix\nSparseMatrix::any (int dim) const\n{\n  SPARSE_ANY_ALL_HEADER\n  SPARSE_ANY_OP (dim);\n}\n\nSparseMatrix\nSparseMatrix::cumprod (int dim, bool nanflag) const\n{\n  if (dim > 1)\n    return *this;\n  SPARSE_CUMPROD (SparseMatrix, double, cumprod);\n}\n\nSparseMatrix\nSparseMatrix::cumsum (int dim, bool nanflag) const\n{\n#define NAN_EXPR                           \\\n  if (! octave::math::isnan (data (j)))    \\\n    t += data (j);                         \\\n  else                                     \\\n    t += 0.0\n\n#define EXPR                               \\\n  t += data (j)\n\n  if (dim > 1)\n    return *this;\n  SPARSE_CUMSUM (SparseMatrix, double, cumsum, NAN_EXPR, EXPR);\n\n#undef NAN_EXPR\n#undef EXPR\n}\n\nSparseMatrix\nSparseMatrix::prod (int dim, bool nanflag) const\n{\n  if (dim > 1)\n    return *this;\n  else if ((rows () == 1 && dim == -1) || dim == 1)\n    return transpose ().prod (0, nanflag).transpose ();\n  else\n    {\n    #define ROW_EXPR                           \\\n      double d = data (i);                     \\\n      if (nanflag && octave::math::isnan (d))  \\\n        tmp[ridx (i)] *= 1.0;                  \\\n      else                                     \\\n        tmp[ridx (i)] *= d\n\n    #define COL_EXPR                           \\\n      double d = data (i);                     \\\n      if (nanflag && octave::math::isnan (d))  \\\n        tmp[j] *= 1.0;                         \\\n      else                                     \\\n        tmp[j] *= d\n\n      SPARSE_BASE_REDUCTION_OP (SparseMatrix, double, ROW_EXPR, COL_EXPR,\n                                (cidx (j+1) - cidx (j) < nr ? 0.0 : 1.0), 1.0);\n\n    #undef ROW_EXPR\n    #undef COL_EXPR\n    }\n}\n\nSparseMatrix\nSparseMatrix::sum (int dim, bool nanflag) const\n{\n#define ROW_EXPR                           \\\n  double d = data (i);                     \\\n  if (nanflag && octave::math::isnan (d))  \\\n    tmp[ridx (i)] += 0.0;                  \\\n  else                                     \\\n    tmp[ridx (i)] += d\n\n#define COL_EXPR                           \\\n  double d = data (i);                     \\\n  if (nanflag && octave::math::isnan (d))  \\\n    tmp[j] += 0.0;                         \\\n  else                                     \\\n    tmp[j] += d\n\n  if (dim > 1)\n    return *this;\n  SPARSE_BASE_REDUCTION_OP (SparseMatrix, double, ROW_EXPR, COL_EXPR,\n                            0.0, 0.0);\n\n#undef ROW_EXPR\n#undef COL_EXPR\n}\n\nSparseMatrix\nSparseMatrix::xsum (int dim, bool nanflag) const\n{\n  if (dim > 1)\n    return *this;\n  SPARSE_XSUM_REDUCTION_OP (SparseMatrix, double);\n}\n\nSparseMatrix\nSparseMatrix::sumsq (int dim, bool nanflag) const\n{\n#define EXPR r.data (nel++) = data (i) * data (i);\n\n#define ROW_EXPR                           \\\n  double d = data (i);                     \\\n  if (nanflag && octave::math::isnan (d))  \\\n    tmp[ridx (i)] += 0.0;                  \\\n  else                                     \\\n    tmp[ridx (i)] += d * d\n\n#define COL_EXPR                           \\\n  double d = data (i);                     \\\n  if (nanflag && octave::math::isnan (d))  \\\n    tmp[j] += 0.0;                         \\\n  else                                     \\\n    tmp[j] += d * d\n\n  SPARSE_SUMSQ_HEADER (SparseMatrix, EXPR)\n  SPARSE_BASE_REDUCTION_OP (SparseMatrix, double, ROW_EXPR, COL_EXPR,\n                            0.0, 0.0);\n\n#undef EXPR\n#undef ROW_EXPR\n#undef COL_EXPR\n}\n\nSparseMatrix\nSparseMatrix::abs () const\n{\n  octave_idx_type nz = nnz ();\n\n  SparseMatrix retval (*this);\n\n  for (octave_idx_type i = 0; i < nz; i++)\n    retval.data (i) = fabs (retval.data (i));\n\n  return retval;\n}\n\nSparseMatrix\nSparseMatrix::diag (octave_idx_type k) const\n{\n  return MSparse<double>::diag (k);\n}\n\nMatrix\nSparseMatrix::matrix_value () const\n{\n  return Sparse<double>::array_value ();\n}\n\nstd::ostream&\noperator << (std::ostream& os, const SparseMatrix& a)\n{\n  octave_idx_type nc = a.cols ();\n\n  // add one to the printed indices to go from\n  //  zero-based to one-based arrays\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      octave_quit ();\n      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)\n        {\n          os << a.ridx (i) + 1 << ' '  << j + 1 << ' ';\n          octave::write_value<double> (os, a.data (i));\n          os << \"\\n\";\n        }\n    }\n\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, SparseMatrix& a)\n{\n  typedef SparseMatrix::element_type elt_type;\n\n  return read_sparse_matrix<elt_type> (is, a, octave::read_value<double>);\n}\n\nSparseMatrix\nSparseMatrix::squeeze () const\n{\n  return MSparse<double>::squeeze ();\n}\n\nSparseMatrix\nSparseMatrix::reshape (const dim_vector& new_dims) const\n{\n  return MSparse<double>::reshape (new_dims);\n}\n\nSparseMatrix\nSparseMatrix::permute (const Array<octave_idx_type>& vec, bool inv) const\n{\n  return MSparse<double>::permute (vec, inv);\n}\n\nSparseMatrix\nSparseMatrix::ipermute (const Array<octave_idx_type>& vec) const\n{\n  return MSparse<double>::ipermute (vec);\n}\n\n// matrix by matrix -> matrix operations\n\nSparseMatrix\noperator * (const SparseMatrix& m, const SparseMatrix& a)\n{\n  SPARSE_SPARSE_MUL (SparseMatrix, double, double);\n}\n\nMatrix\noperator * (const Matrix& m, const SparseMatrix& a)\n{\n  FULL_SPARSE_MUL (Matrix, double);\n}\n\nMatrix\nmul_trans (const Matrix& m, const SparseMatrix& a)\n{\n  FULL_SPARSE_MUL_TRANS (Matrix, double, );\n}\n\nMatrix\noperator * (const SparseMatrix& m, const Matrix& a)\n{\n  SPARSE_FULL_MUL (Matrix, double);\n}\n\nMatrix\ntrans_mul (const SparseMatrix& m, const Matrix& a)\n{\n  SPARSE_FULL_TRANS_MUL (Matrix, double, );\n}\n\n// diag * sparse and sparse * diag\n\nSparseMatrix\noperator * (const DiagMatrix& d, const SparseMatrix& a)\n{\n  return do_mul_dm_sm<SparseMatrix> (d, a);\n}\n\nSparseMatrix\noperator * (const SparseMatrix& a, const DiagMatrix& d)\n{\n  return do_mul_sm_dm<SparseMatrix> (a, d);\n}\n\nSparseMatrix\noperator + (const DiagMatrix& d, const SparseMatrix& a)\n{\n  return do_add_dm_sm<SparseMatrix> (d, a);\n}\n\nSparseMatrix\noperator - (const DiagMatrix& d, const SparseMatrix& a)\n{\n  return do_sub_dm_sm<SparseMatrix> (d, a);\n}\n\nSparseMatrix\noperator + (const SparseMatrix& a, const DiagMatrix& d)\n{\n  return do_add_sm_dm<SparseMatrix> (a, d);\n}\n\nSparseMatrix\noperator - (const SparseMatrix& a, const DiagMatrix& d)\n{\n  return do_sub_sm_dm<SparseMatrix> (a, d);\n}\n\n// perm * sparse and sparse * perm\n\nSparseMatrix\noperator * (const PermMatrix& p, const SparseMatrix& a)\n{\n  return octinternal_do_mul_pm_sm (p, a);\n}\n\nSparseMatrix\noperator * (const SparseMatrix& a, const PermMatrix& p)\n{\n  return octinternal_do_mul_sm_pm (a, p);\n}\n\n// FIXME: it would be nice to share code among the min/max functions below.\n\n#define EMPTY_RETURN_CHECK(T)                   \\\n  if (nr == 0 || nc == 0)                       \\\n    return T (nr, nc);\n\nSparseMatrix\nmin (double d, const SparseMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return min (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmin (double d, const SparseMatrix& m, const bool nanflag)\n{\n  const bool realabs = true;\n  return min (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmin (double d, const SparseMatrix& m, const bool nanflag, const bool realabs)\n{\n  SparseMatrix result;\n\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (SparseMatrix);\n\n  // Count the number of nonzero elements\n  if (d < 0.)\n    {\n      result = SparseMatrix (nr, nc, d);\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n          {\n            double tmp = octave::math::min (d, m.data (i), nanflag, realabs);\n            if (tmp != 0.)\n              {\n                octave_idx_type idx = m.ridx (i) + j * nr;\n                result.xdata (idx) = tmp;\n                result.xridx (idx) = m.ridx (i);\n              }\n          }\n    }\n  else\n    {\n      octave_idx_type nel = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n          if (octave::math::min (d, m.data (i), nanflag, realabs) != 0.)\n            nel++;\n\n      result = SparseMatrix (nr, nc, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n            {\n              double tmp = octave::math::min (d, m.data (i), nanflag, realabs);\n\n              if (tmp != 0.)\n                {\n                  result.xdata (ii) = tmp;\n                  result.xridx (ii++) = m.ridx (i);\n                }\n            }\n          result.xcidx (j+1) = ii;\n        }\n    }\n\n  return result;\n}\n\nSparseMatrix\nmin (const SparseMatrix& m, double d)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return min (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmin (const SparseMatrix& m, double d, const bool nanflag)\n{\n  const bool realabs = true;\n  return min (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmin (const SparseMatrix& m, double d, const bool nanflag, const bool realabs)\n{\n  return min (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmin (const SparseMatrix& a, const SparseMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return min (a, b, nanflag, realabs);\n}\n\nSparseMatrix\nmin (const SparseMatrix& a, const SparseMatrix& b, const bool nanflag)\n{\n  const bool realabs = true;\n  return min (a, b, nanflag, realabs);\n}\n\nSparseMatrix\nmin (const SparseMatrix& a, const SparseMatrix& b, const bool nanflag,\n     const bool realabs)\n{\n  SparseMatrix r;\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nr == b_nr && a_nc == b_nc)\n    {\n      r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));\n\n      octave_idx_type jx = 0;\n      r.cidx (0) = 0;\n      for (octave_idx_type i = 0 ; i < a_nc ; i++)\n        {\n          octave_idx_type ja = a.cidx (i);\n          octave_idx_type ja_max = a.cidx (i+1);\n          bool ja_lt_max = ja < ja_max;\n\n          octave_idx_type jb = b.cidx (i);\n          octave_idx_type jb_max = b.cidx (i+1);\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  double tmp = octave::math::min (a.data (ja), 0.,\n                                                  nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.ridx (jx) = a.ridx (ja);\n                      r.data (jx) = tmp;\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                }\n              else if ((! ja_lt_max)\n                       || (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))\n                {\n                  double tmp = octave::math::min (0., b.data (jb),\n                                                  nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.ridx (jx) = b.ridx (jb);\n                      r.data (jx) = tmp;\n                      jx++;\n                    }\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n              else\n                {\n                  double tmp = octave::math::min (a.data (ja), b.data (jb),\n                                                  nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.data (jx) = tmp;\n                      r.ridx (jx) = a.ridx (ja);\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n\n      r.maybe_compress ();\n    }\n  else\n    {\n      if (a_nr == 0 && (b_nr == 0 || b_nr == 1))\n        {\n          if (a_nc == 1 || b_nc == 1 || a_nc == b_nc)\n            r.resize (a_nr, std::max (a_nc, b_nc));\n          else\n            octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (a_nc == 0 && (b_nc == 0 || b_nc == 1))\n        {\n          if (a_nr == 1 || b_nr == 1 || a_nr == b_nr)\n            r.resize (std::max (a_nr, b_nr), a_nc);\n          else\n            octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (b_nr == 0 && (a_nr == 0 || a_nr == 1))\n        {\n          if (b_nc == 1 || a_nc == 1 || b_nc == a_nc)\n            r.resize (b_nr, std::max (a_nc, b_nc));\n          else\n            octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (b_nc == 0 && (a_nc == 0 || a_nc == 1))\n        {\n          if (b_nr == 1 || a_nr == 1 || b_nr == a_nr)\n            r.resize (std::max (a_nr, b_nr), b_nc);\n          else\n            octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else\n        octave::err_nonconformant (\"min\", a_nr, a_nc, b_nr, b_nc);\n    }\n\n  return r;\n}\n\nSparseMatrix\nmax (double d, const SparseMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return max (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmax (double d, const SparseMatrix& m, const bool nanflag)\n{\n  const bool realabs = true;\n  return max (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmax (double d, const SparseMatrix& m, const bool nanflag, const bool realabs)\n{\n  SparseMatrix result;\n\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (SparseMatrix);\n\n  // Count the number of nonzero elements\n  if (d > 0.)\n    {\n      result = SparseMatrix (nr, nc, d);\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n          {\n            double tmp = octave::math::max (d, m.data (i), nanflag, realabs);\n\n            if (tmp != 0.)\n              {\n                octave_idx_type idx = m.ridx (i) + j * nr;\n                result.xdata (idx) = tmp;\n                result.xridx (idx) = m.ridx (i);\n              }\n          }\n    }\n  else\n    {\n      octave_idx_type nel = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n          if (octave::math::max (d, m.data (i), nanflag, realabs) != 0.)\n            nel++;\n\n      result = SparseMatrix (nr, nc, nel);\n\n      octave_idx_type ii = 0;\n      result.xcidx (0) = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n            {\n              double tmp = octave::math::max (d, m.data (i), nanflag, realabs);\n              if (tmp != 0.)\n                {\n                  result.xdata (ii) = tmp;\n                  result.xridx (ii++) = m.ridx (i);\n                }\n            }\n          result.xcidx (j+1) = ii;\n        }\n    }\n\n  return result;\n}\n\nSparseMatrix\nmax (const SparseMatrix& m, double d)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return max (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmax (const SparseMatrix& m, double d, const bool nanflag)\n{\n  const bool realabs = true;\n  return max (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmax (const SparseMatrix& m, double d, const bool nanflag, const bool realabs)\n{\n  return max (d, m, nanflag, realabs);\n}\n\nSparseMatrix\nmax (const SparseMatrix& a, const SparseMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return max (a, b, nanflag, realabs);\n}\n\nSparseMatrix\nmax (const SparseMatrix& a, const SparseMatrix& b, const bool nanflag)\n{\n  const bool realabs = true;\n  return max (a, b, nanflag, realabs);\n}\n\nSparseMatrix\nmax (const SparseMatrix& a, const SparseMatrix& b, const bool nanflag,\n     const bool realabs)\n{\n  SparseMatrix r;\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nr == b_nr && a_nc == b_nc)\n    {\n      r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));\n\n      octave_idx_type jx = 0;\n      r.cidx (0) = 0;\n      for (octave_idx_type i = 0 ; i < a_nc ; i++)\n        {\n          octave_idx_type ja = a.cidx (i);\n          octave_idx_type ja_max = a.cidx (i+1);\n          bool ja_lt_max = ja < ja_max;\n\n          octave_idx_type jb = b.cidx (i);\n          octave_idx_type jb_max = b.cidx (i+1);\n          bool jb_lt_max = jb < jb_max;\n\n          while (ja_lt_max || jb_lt_max)\n            {\n              octave_quit ();\n              if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))\n                {\n                  double tmp = octave::math::max (a.data (ja), 0.,\n                                                  nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.ridx (jx) = a.ridx (ja);\n                      r.data (jx) = tmp;\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                }\n              else if ((! ja_lt_max)\n                       || (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))\n                {\n                  double tmp = octave::math::max (0., b.data (jb),\n                                                  nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.ridx (jx) = b.ridx (jb);\n                      r.data (jx) = tmp;\n                      jx++;\n                    }\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n              else\n                {\n                  double tmp = octave::math::max (a.data (ja), b.data (jb),\n                                                  nanflag, realabs);\n                  if (tmp != 0.)\n                    {\n                      r.data (jx) = tmp;\n                      r.ridx (jx) = a.ridx (ja);\n                      jx++;\n                    }\n                  ja++;\n                  ja_lt_max= ja < ja_max;\n                  jb++;\n                  jb_lt_max= jb < jb_max;\n                }\n            }\n          r.cidx (i+1) = jx;\n        }\n\n      r.maybe_compress ();\n    }\n  else\n    {\n      if (a_nr == 0 && (b_nr == 0 || b_nr == 1))\n        {\n          if (a_nc == 1 || b_nc == 1 || a_nc == b_nc)\n            r.resize (a_nr, std::max (a_nc, b_nc));\n          else\n            octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (a_nc == 0 && (b_nc == 0 || b_nc == 1))\n        {\n          if (a_nr == 1 || b_nr == 1 || a_nr == b_nr)\n            r.resize (std::max (a_nr, b_nr), a_nc);\n          else\n            octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (b_nr == 0 && (a_nr == 0 || a_nr == 1))\n        {\n          if (b_nc == 1 || a_nc == 1 || b_nc == a_nc)\n            r.resize (b_nr, std::max (a_nc, b_nc));\n          else\n            octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else if (b_nc == 0 && (a_nc == 0 || a_nc == 1))\n        {\n          if (b_nr == 1 || a_nr == 1 || b_nr == a_nr)\n            r.resize (std::max (a_nr, b_nr), b_nc);\n          else\n            octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n        }\n      else\n        octave::err_nonconformant (\"max\", a_nr, a_nc, b_nr, b_nc);\n    }\n\n  return r;\n}\n\nSPARSE_SMS_CMP_OPS (SparseMatrix, double)\nSPARSE_SMS_BOOL_OPS (SparseMatrix, double)\n\nSPARSE_SSM_CMP_OPS (double, SparseMatrix)\nSPARSE_SSM_BOOL_OPS (double, SparseMatrix)\n\nSPARSE_SMSM_CMP_OPS (SparseMatrix, SparseMatrix)\nSPARSE_SMSM_BOOL_OPS (SparseMatrix, SparseMatrix)\n"
  },
  {
    "path": "liboctave/array/dSparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dSparse_h)\n#define octave_dSparse_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n#include \"DET.h\"\n#include \"MSparse.h\"\n#include \"MatrixType.h\"\n#include \"Sparse-op-decls.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"dNDArray.h\"\n\nclass SparseMatrix : public MSparse<double>\n{\npublic:\n\n  // Corresponding dense matrix type for this sparse matrix type.\n  typedef Matrix dense_matrix_type;\n\n  typedef void (*solve_singularity_handler) (double rcond);\n\n  SparseMatrix () : MSparse<double> () { }\n\n  SparseMatrix (octave_idx_type r, octave_idx_type c)\n    : MSparse<double> (r, c) { }\n\n  SparseMatrix (const dim_vector& dv, octave_idx_type nz = 0) :\n    MSparse<double> (dv, nz) { }\n\n  explicit SparseMatrix (octave_idx_type r, octave_idx_type c, double val)\n    : MSparse<double> (r, c, val) { }\n\n  SparseMatrix (const SparseMatrix& a) : MSparse<double> (a) { }\n\n  SparseMatrix (const SparseMatrix& a, const dim_vector& dv)\n    : MSparse<double> (a, dv) { }\n\n  SparseMatrix (const MSparse<double>& a) : MSparse<double> (a) { }\n\n  SparseMatrix (const Sparse<double>& a) : MSparse<double> (a) { }\n\n  explicit OCTAVE_API SparseMatrix (const SparseBoolMatrix& a);\n\n  explicit SparseMatrix (const Matrix& a) : MSparse<double> (a) { }\n\n  explicit SparseMatrix (const NDArray& a) : MSparse<double> (a) { }\n\n  SparseMatrix (const Array<double>& a, const octave::idx_vector& r,\n                const octave::idx_vector& c, octave_idx_type nr = -1,\n                octave_idx_type nc = -1, bool sum_terms = true,\n                octave_idx_type nzm = -1)\n    : MSparse<double> (a, r, c, nr, nc, sum_terms, nzm) { }\n\n  explicit OCTAVE_API SparseMatrix (const DiagMatrix& a);\n\n  explicit SparseMatrix (const PermMatrix& a) : MSparse<double> (a) { }\n\n  SparseMatrix (octave_idx_type r, octave_idx_type c,\n                octave_idx_type num_nz) : MSparse<double> (r, c, num_nz) { }\n\n  SparseMatrix& operator = (const SparseMatrix& a)\n  {\n    MSparse<double>::operator = (a);\n    return *this;\n  }\n\n  ~SparseMatrix () = default;\n\n  OCTAVE_API bool operator == (const SparseMatrix& a) const;\n  OCTAVE_API bool operator != (const SparseMatrix& a) const;\n\n  OCTAVE_API bool issymmetric () const;\n\n  OCTAVE_API SparseMatrix\n  max (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API SparseMatrix\n  max (Array<octave_idx_type>& index, int dim = -1,\n       bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API SparseMatrix\n  min (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API SparseMatrix\n  min (Array<octave_idx_type>& index, int dim = -1,\n       bool nanflag = true, bool realabs = true) const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API SparseMatrix&\n  insert (const SparseMatrix& a, octave_idx_type r, octave_idx_type c);\n\n  OCTAVE_API SparseMatrix&\n  insert (const SparseMatrix& a, const Array<octave_idx_type>& indx);\n\n  OCTAVE_API SparseMatrix\n  concat (const SparseMatrix& rb, const Array<octave_idx_type>& ra_idx);\n  OCTAVE_API SparseComplexMatrix\n  concat (const SparseComplexMatrix& rb, const Array<octave_idx_type>& ra_idx);\n\n  friend OCTAVE_API SparseMatrix real (const SparseComplexMatrix& a);\n  friend OCTAVE_API SparseMatrix imag (const SparseComplexMatrix& a);\n\n  SparseMatrix transpose () const\n  {\n    return MSparse<double>::transpose ();\n  }\n  SparseMatrix hermitian () const { return transpose (); }\n\n  // extract row or column i.\n\n  OCTAVE_API RowVector row (octave_idx_type i) const;\n\n  OCTAVE_API ColumnVector column (octave_idx_type i) const;\n\nprivate:\n  OCTAVE_API SparseMatrix\n  dinverse (MatrixType& mattype, octave_idx_type& info, double& rcond,\n            const bool force = false, const bool calccond = true) const;\n\n  OCTAVE_API SparseMatrix\n  tinverse (MatrixType& mattype, octave_idx_type& info, double& rcond,\n            const bool force = false, const bool calccond = true) const;\n\npublic:\n  OCTAVE_API SparseMatrix inverse () const;\n  OCTAVE_API SparseMatrix inverse (MatrixType& mattype) const;\n  OCTAVE_API SparseMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info) const;\n  OCTAVE_API SparseMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info, double& rcond,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API DET determinant () const;\n  OCTAVE_API DET determinant (octave_idx_type& info) const;\n  OCTAVE_API DET determinant (octave_idx_type& info, double& rcond,\n                              bool calc_cond = true) const;\n\nprivate:\n  // Diagonal matrix solvers\n  OCTAVE_API Matrix\n  dsolve (MatrixType& typ, const Matrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  OCTAVE_API ComplexMatrix\n  dsolve (MatrixType& typ, const ComplexMatrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  OCTAVE_API SparseMatrix\n  dsolve (MatrixType& typ, const SparseMatrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  OCTAVE_API SparseComplexMatrix\n  dsolve (MatrixType& typ, const SparseComplexMatrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  // Upper triangular matrix solvers\n  OCTAVE_API Matrix\n  utsolve (MatrixType& typ, const Matrix& b, octave_idx_type& info,\n           double& rcond, solve_singularity_handler sing_handler,\n           bool calc_cond = false) const;\n\n  OCTAVE_API ComplexMatrix\n  utsolve (MatrixType& typ, const ComplexMatrix& b, octave_idx_type& info,\n           double& rcond, solve_singularity_handler sing_handler,\n           bool calc_cond = false) const;\n\n  OCTAVE_API SparseMatrix\n  utsolve (MatrixType& typ, const SparseMatrix& b, octave_idx_type& info,\n           double& rcond, solve_singularity_handler sing_handler,\n           bool calc_cond = false) const;\n\n  OCTAVE_API SparseComplexMatrix\n  utsolve (MatrixType& typ, const SparseComplexMatrix& b, octave_idx_type& info,\n           double& rcond, solve_singularity_handler sing_handler,\n           bool calc_cond = false) const;\n\n  // Lower triangular matrix solvers\n  OCTAVE_API Matrix\n  ltsolve (MatrixType& typ, const Matrix& b, octave_idx_type& info,\n           double& rcond, solve_singularity_handler sing_handler,\n           bool calc_cond = false) const;\n\n  OCTAVE_API ComplexMatrix\n  ltsolve (MatrixType& typ, const ComplexMatrix& b, octave_idx_type& info,\n           double& rcond, solve_singularity_handler sing_handler,\n           bool calc_cond = false) const;\n\n  OCTAVE_API SparseMatrix\n  ltsolve (MatrixType& typ, const SparseMatrix& b, octave_idx_type& info,\n           double& rcond, solve_singularity_handler sing_handler,\n           bool calc_cond = false) const;\n\n  OCTAVE_API SparseComplexMatrix\n  ltsolve (MatrixType& typ, const SparseComplexMatrix& b, octave_idx_type& info,\n           double& rcond, solve_singularity_handler sing_handler,\n           bool calc_cond = false) const;\n\n  // Tridiagonal matrix solvers\n  OCTAVE_API Matrix\n  trisolve (MatrixType& typ, const Matrix& b, octave_idx_type& info,\n            double& rcond, solve_singularity_handler sing_handler,\n            bool calc_cond = false) const;\n\n  OCTAVE_API ComplexMatrix\n  trisolve (MatrixType& typ, const ComplexMatrix& b, octave_idx_type& info,\n            double& rcond, solve_singularity_handler sing_handler,\n            bool calc_cond = false) const;\n\n  OCTAVE_API SparseMatrix\n  trisolve (MatrixType& typ, const SparseMatrix& b, octave_idx_type& info,\n            double& rcond, solve_singularity_handler sing_handler,\n            bool calc_cond = false) const;\n\n  OCTAVE_API SparseComplexMatrix\n  trisolve (MatrixType& typ, const SparseComplexMatrix& b, octave_idx_type& info,\n            double& rcond, solve_singularity_handler sing_handler,\n            bool calc_cond = false) const;\n\n  // Banded matrix solvers (umfpack/cholesky)\n  OCTAVE_API Matrix\n  bsolve (MatrixType& typ, const Matrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  OCTAVE_API ComplexMatrix\n  bsolve (MatrixType& typ, const ComplexMatrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  OCTAVE_API SparseMatrix\n  bsolve (MatrixType& typ, const SparseMatrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  OCTAVE_API SparseComplexMatrix\n  bsolve (MatrixType& typ, const SparseComplexMatrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  // Full matrix solvers (umfpack/cholesky)\n  OCTAVE_API void *\n  factorize (octave_idx_type& err, double& rcond, Matrix& Control,\n             Matrix& Info, solve_singularity_handler sing_handler,\n             bool calc_cond = false) const;\n\n  OCTAVE_API Matrix\n  fsolve (MatrixType& typ, const Matrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  OCTAVE_API ComplexMatrix\n  fsolve (MatrixType& typ, const ComplexMatrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  OCTAVE_API SparseMatrix\n  fsolve (MatrixType& typ, const SparseMatrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\n  OCTAVE_API SparseComplexMatrix\n  fsolve (MatrixType& typ, const SparseComplexMatrix& b, octave_idx_type& info,\n          double& rcond, solve_singularity_handler sing_handler,\n          bool calc_cond = false) const;\n\npublic:\n  // Generic interface to solver with no probing of type\n  OCTAVE_API Matrix solve (MatrixType& typ, const Matrix& b) const;\n  OCTAVE_API Matrix\n  solve (MatrixType& typ, const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API Matrix\n  solve (MatrixType& typ, const Matrix& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API Matrix\n  solve (MatrixType& typ, const Matrix& b, octave_idx_type& info,\n         double& rcond, solve_singularity_handler sing_handler,\n         bool singular_fallback = true) const;\n\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& typ, const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& typ, const ComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& typ, const ComplexMatrix& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API ComplexMatrix\n  solve (MatrixType& typ, const ComplexMatrix& b, octave_idx_type& info,\n         double& rcond, solve_singularity_handler sing_handler,\n         bool singular_fallback = true) const;\n\n  OCTAVE_API SparseMatrix solve (MatrixType& typ, const SparseMatrix& b) const;\n  OCTAVE_API SparseMatrix\n  solve (MatrixType& typ, const SparseMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API SparseMatrix\n  solve (MatrixType& typ, const SparseMatrix& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API SparseMatrix\n  solve (MatrixType& typ, const SparseMatrix& b, octave_idx_type& info,\n         double& rcond, solve_singularity_handler sing_handler,\n         bool singular_fallback = true) const;\n\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& typ, const SparseComplexMatrix& b) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& typ, const SparseComplexMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& typ, const SparseComplexMatrix& b,\n         octave_idx_type& info, double& rcond) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (MatrixType& typ, const SparseComplexMatrix& b,\n         octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler,\n         bool singular_fallabck = true) const;\n\n  OCTAVE_API ColumnVector solve (MatrixType& typ, const ColumnVector& b) const;\n  OCTAVE_API ColumnVector\n  solve (MatrixType& typ, const ColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ColumnVector\n  solve (MatrixType& typ, const ColumnVector& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API ColumnVector\n  solve (MatrixType& typ, const ColumnVector& b, octave_idx_type& info,\n         double& rcond, solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& typ, const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& typ, const ComplexColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& typ, const ComplexColumnVector& b,\n         octave_idx_type& info, double& rcond) const;\n  OCTAVE_API ComplexColumnVector\n  solve (MatrixType& typ, const ComplexColumnVector& b,\n         octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  // Generic interface to solver with probing of type\n  OCTAVE_API Matrix solve (const Matrix& b) const;\n  OCTAVE_API Matrix solve (const Matrix& b, octave_idx_type& info) const;\n  OCTAVE_API Matrix\n  solve (const Matrix& b, octave_idx_type& info, double& rcond) const;\n  OCTAVE_API Matrix\n  solve (const Matrix& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API ComplexMatrix solve (const ComplexMatrix& b) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info, double& rcond) const;\n  OCTAVE_API ComplexMatrix\n  solve (const ComplexMatrix& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API SparseMatrix solve (const SparseMatrix& b) const;\n  OCTAVE_API SparseMatrix\n  solve (const SparseMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API SparseMatrix\n  solve (const SparseMatrix& b, octave_idx_type& info, double& rcond) const;\n  OCTAVE_API SparseMatrix\n  solve (const SparseMatrix& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API SparseComplexMatrix solve (const SparseComplexMatrix& b) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (const SparseComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (const SparseComplexMatrix& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API SparseComplexMatrix\n  solve (const SparseComplexMatrix& b, octave_idx_type& info,\n         double& rcond, solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API ColumnVector solve (const ColumnVector& b) const;\n  OCTAVE_API ColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info, double& rcond) const;\n  OCTAVE_API ColumnVector\n  solve (const ColumnVector& b, octave_idx_type& info, double& rcond,\n         solve_singularity_handler sing_handler) const;\n\n  OCTAVE_API ComplexColumnVector solve (const ComplexColumnVector& b) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info,\n         double& rcond) const;\n  OCTAVE_API ComplexColumnVector\n  solve (const ComplexColumnVector& b, octave_idx_type& info,\n         double& rcond, solve_singularity_handler sing_handler) const;\n\n  // other operations\n\n  OCTAVE_API bool any_element_is_negative (bool = false) const;\n  OCTAVE_API bool any_element_is_nan () const;\n  OCTAVE_API bool any_element_is_inf_or_nan () const;\n  OCTAVE_API bool any_element_not_one_or_zero () const;\n  OCTAVE_API bool all_elements_are_zero () const;\n  OCTAVE_API bool all_elements_are_int_or_inf_or_nan () const;\n  OCTAVE_API bool all_integers (double& max_val, double& min_val) const;\n  OCTAVE_API bool too_large_for_float () const;\n\n  OCTAVE_API SparseBoolMatrix operator ! () const;\n\n  OCTAVE_API SparseBoolMatrix all (int dim = -1) const;\n  OCTAVE_API SparseBoolMatrix any (int dim = -1) const;\n\n  OCTAVE_API SparseMatrix cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseMatrix cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseMatrix prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseMatrix sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseMatrix xsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseMatrix sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API SparseMatrix abs () const;\n\n  OCTAVE_API SparseMatrix diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API Matrix matrix_value () const;\n\n  OCTAVE_API SparseMatrix squeeze () const;\n\n  OCTAVE_API SparseMatrix reshape (const dim_vector& new_dims) const;\n\n  OCTAVE_API SparseMatrix\n  permute (const Array<octave_idx_type>& vec, bool inv = false) const;\n\n  OCTAVE_API SparseMatrix ipermute (const Array<octave_idx_type>& vec) const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream& operator << (std::ostream& os,\n                                               const SparseMatrix& a);\n  friend OCTAVE_API std::istream& operator >> (std::istream& is,\n                                               SparseMatrix& a);\n\n};\n\n// Publish externally used friend functions.\n\nextern OCTAVE_API SparseMatrix real (const SparseComplexMatrix& a);\nextern OCTAVE_API SparseMatrix imag (const SparseComplexMatrix& a);\n\n// Other operators.\n\nextern OCTAVE_API SparseMatrix operator * (const SparseMatrix& a,\n                                           const SparseMatrix& b);\nextern OCTAVE_API Matrix operator * (const Matrix& a,\n                                     const SparseMatrix& b);\nextern OCTAVE_API Matrix mul_trans (const Matrix& a,\n                                    const SparseMatrix& b);\nextern OCTAVE_API Matrix operator * (const SparseMatrix& a,\n                                     const Matrix& b);\nextern OCTAVE_API Matrix trans_mul (const SparseMatrix& a,\n                                    const Matrix& b);\n\nextern OCTAVE_API SparseMatrix operator * (const DiagMatrix&,\n                                           const SparseMatrix&);\nextern OCTAVE_API SparseMatrix operator * (const SparseMatrix&,\n                                           const DiagMatrix&);\n\nextern OCTAVE_API SparseMatrix operator + (const DiagMatrix&,\n                                           const SparseMatrix&);\nextern OCTAVE_API SparseMatrix operator + (const SparseMatrix&,\n                                           const DiagMatrix&);\nextern OCTAVE_API SparseMatrix operator - (const DiagMatrix&,\n                                           const SparseMatrix&);\nextern OCTAVE_API SparseMatrix operator - (const SparseMatrix&,\n                                           const DiagMatrix&);\n\nextern OCTAVE_API SparseMatrix operator * (const PermMatrix&,\n                                           const SparseMatrix&);\nextern OCTAVE_API SparseMatrix operator * (const SparseMatrix&,\n                                           const PermMatrix&);\n\nextern OCTAVE_API SparseMatrix min (double d, const SparseMatrix& m);\nextern OCTAVE_API SparseMatrix min (double d, const SparseMatrix& m,\n                                    const bool nanflag);\nextern OCTAVE_API SparseMatrix min (double d, const SparseMatrix& m,\n                                    const bool nanflag, const bool realabs);\nextern OCTAVE_API SparseMatrix min (const SparseMatrix& m, double d);\nextern OCTAVE_API SparseMatrix min (const SparseMatrix& m, double d,\n                                    const bool nanflag);\nextern OCTAVE_API SparseMatrix min (const SparseMatrix& m, double d,\n                                    const bool nanflag, const bool realabs);\nextern OCTAVE_API SparseMatrix min (const SparseMatrix& a,\n                                    const SparseMatrix& b);\nextern OCTAVE_API SparseMatrix min (const SparseMatrix& a,\n                                    const SparseMatrix& b, const bool nanflag);\nextern OCTAVE_API SparseMatrix min (const SparseMatrix& a,\n                                    const SparseMatrix& b,\n                                    const bool nanflag, const bool realabs);\n\nextern OCTAVE_API SparseMatrix max (double d, const SparseMatrix& m);\nextern OCTAVE_API SparseMatrix max (double d, const SparseMatrix& m,\n                                    const bool nanflag);\nextern OCTAVE_API SparseMatrix max (double d, const SparseMatrix& m,\n                                    const bool nanflag, const bool realabs);\nextern OCTAVE_API SparseMatrix max (const SparseMatrix& m, double d);\nextern OCTAVE_API SparseMatrix max (const SparseMatrix& m, double d,\n                                    const bool nanflag);\nextern OCTAVE_API SparseMatrix max (const SparseMatrix& m, double d,\n                                    const bool nanflag, const bool realabs);\nextern OCTAVE_API SparseMatrix max (const SparseMatrix& a,\n                                    const SparseMatrix& b);\nextern OCTAVE_API SparseMatrix max (const SparseMatrix& a,\n                                    const SparseMatrix& b, const bool nanflag);\nextern OCTAVE_API SparseMatrix max (const SparseMatrix& a,\n                                    const SparseMatrix& b,\n                                    const bool nanflag, const bool realabs);\n\nSPARSE_SMS_CMP_OP_DECLS (SparseMatrix, double, OCTAVE_API)\nSPARSE_SMS_BOOL_OP_DECLS (SparseMatrix, double, OCTAVE_API)\n\nSPARSE_SSM_CMP_OP_DECLS (double, SparseMatrix, OCTAVE_API)\nSPARSE_SSM_BOOL_OP_DECLS (double, SparseMatrix, OCTAVE_API)\n\nSPARSE_SMSM_CMP_OP_DECLS (SparseMatrix, SparseMatrix, OCTAVE_API)\nSPARSE_SMSM_BOOL_OP_DECLS (SparseMatrix, SparseMatrix, OCTAVE_API)\n\nSPARSE_FORWARD_DEFS (MSparse, SparseMatrix, Matrix, double)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/dim-vector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// or <https://octave.org/copyright/>.\n//\n// Copyirght (C) 2009, 2010 VZLU Prague\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n\n#include \"Array-oct.h\"\n#include \"dim-vector.h\"\n\nvoid\ndim_vector::chop_all_singletons ()\n{\n  int j = 0;\n  int nd = ndims ();\n\n  for (int i = 0; i < nd; i++)\n    {\n      if (xelem(i) != 1)\n        xelem(j++) = xelem(i);\n    }\n\n  if (j == 1)\n    xelem(1) = 1;\n\n  m_num_dims = (j > 2 ? j : 2);\n}\n\nstd::string\ndim_vector::str (char sep) const\n{\n  std::ostringstream buf;\n\n  for (int i = 0; i < ndims (); i++)\n    {\n      buf << xelem (i);\n\n      if (i < ndims () - 1)\n        buf << sep;\n    }\n\n  std::string retval = buf.str ();\n\n  return retval;\n}\n\nint\ndim_vector::num_ones () const\n{\n  int retval = 0;\n\n  for (int i = 0; i < ndims (); i++)\n    if (xelem (i) == 1)\n      retval++;\n\n  return retval;\n}\n\ndim_vector\ndim_vector::squeeze () const\n{\n  dim_vector new_dims = *this;\n  new_dims.chop_all_singletons ();\n\n  // preserve orientation if there is only one non-singleton dimension left\n  if (new_dims.ndims () == 2 && xelem(0) == 1 && new_dims.elem(1) == 1)\n    return new_dims.as_row ();\n\n  return new_dims;\n}\n\n// This is the rule for cat().  cat (dim, A, B) works if one\n// of the following holds, in this order:\n//\n// 1. size (A, k) == size (B, k) for all k != dim.\n// In this case, size (C, dim) = size (A, dim) + size (B, dim) and\n// other sizes remain intact.\n//\n// 2. A is 0x0, in which case B is the result\n// 3. B is 0x0, in which case A is the result\n\nbool\ndim_vector::concat (const dim_vector& dvb, int dim)\n{\n  int orig_nd = ndims ();\n  int ndb = dvb.ndims ();\n  int new_nd = (dim < ndb ? ndb : dim + 1);\n  if (new_nd > orig_nd)\n    resize (new_nd, 1);\n  else\n    new_nd = orig_nd;\n\n  bool match = true;\n\n  for (int i = 0; i < ndb; i++)\n    {\n      if (i != dim && xelem(i) != dvb(i))\n        {\n          match = false;\n          break;\n        }\n    }\n\n  for (int i = ndb; i < new_nd; i++)\n    {\n      if (i != dim && xelem(i) != 1)\n        {\n          match = false;\n          break;\n        }\n    }\n\n  if (match)\n    xelem(dim) += (dim < ndb ? dvb(dim) : 1);\n  else\n    {\n      // Dimensions don't match.  The only allowed fix is to omit 0x0.\n      if (ndb == 2 && dvb(0) == 0 && dvb(1) == 0)\n        match = true;\n      else if (orig_nd == 2 && xelem(0) == 0 && xelem(1) == 0)\n        {\n          *this = dvb;\n          match = true;\n        }\n    }\n\n  chop_trailing_singletons ();\n\n  return match;\n}\n\n// Rules for horzcat/vertcat are yet looser.\n// two arrays A, B can be concatenated\n// horizontally (dim = 2) or vertically (dim = 1) if one of the\n// following holds, in this order:\n//\n// 1. cat (dim, A, B) works\n//\n// 2. A, B are 2-D and one of them is an empty vector, in which\n// case the result is the other one except if both of them\n// are empty vectors, in which case the result is 0x0.\n\nbool\ndim_vector::hvcat (const dim_vector& dvb, int dim)\n{\n  if (concat (dvb, dim))\n    return true;\n  else if (ndims () == 2 && dvb.ndims () == 2)\n    {\n      bool e2dv = xelem(0) + xelem(1) == 1;\n      bool e2dvb = dvb(0) + dvb(1) == 1;\n      if (e2dvb)\n        {\n          if (e2dv)\n            *this = dim_vector ();\n          return true;\n        }\n      else if (e2dv)\n        {\n          *this = dvb;\n          return true;\n        }\n    }\n\n  return false;\n}\n\ndim_vector\ndim_vector::redim (int n) const\n{\n  int n_dims = ndims ();\n\n  if (n_dims == n)\n    return *this;\n  else if (n_dims < n)\n    {\n      dim_vector retval = alloc (n);\n\n      std::copy_n (m_dims, n_dims, retval.m_dims);\n      std::fill_n (retval.m_dims + n_dims, n - n_dims, 1);\n\n      return retval;\n    }\n  else\n    {\n      if (n < 1)\n        n = 1;\n\n      dim_vector retval = alloc (n);\n\n      std::copy_n (m_dims, n-1, retval.m_dims);\n\n      // Accumulate overflow dimensions into last remaining dimension\n      int k = xelem(n-1);\n      for (int i = n; i < n_dims; i++)\n        k *= xelem(i);\n\n      retval.xelem(n-1) = k;\n\n      // All dim_vectors are at least 2-D.  Make Nx1 if necessary.\n      if (n == 1)\n        retval.xelem(1) = 1;\n\n      return retval;\n    }\n}\n\nArray<octave_idx_type>\ndim_vector::as_array () const\n{\n  octave_idx_type nd = ndims ();\n\n  Array<octave_idx_type> retval (dim_vector (1, nd));\n\n  for (octave_idx_type i = 0; i < nd; i++)\n    retval(i) = elem (i);\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/array/dim-vector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// or <https://octave.org/copyright/>.\n//\n// Copyirght (C) 2009, 2010 VZLU Prague\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dim_vector_h)\n#define octave_dim_vector_h 1\n\n#include \"octave-config.h\"\n\n#include <algorithm>\n#include <initializer_list>\n#include <limits>\n#include <string>\n\n#include \"Array-fwd.h\"\n#include \"lo-utils.h\"\n#include \"oct-refcount.h\"\n\n//! Vector representing the dimensions (size) of an Array.\n//!\n//! A dim_vector is used to represent dimensions of an Array.  It is used\n//! on its constructor to specify its size, or when reshaping it.\n//!\n//! @code{.cc}\n//! // Matrix with 10 rows and 20 columns.\n//! Matrix m Matrix (dim_vector (10, 20));\n//!\n//! // Change its size to 5 rows and 40 columns.\n//! Matrix m2 = m.reshape (dim_vector (5, 40));\n//!\n//! // Five dimensional Array of length 10, 20, 3, 8, 7 on each dimension.\n//! NDArray a (dim_vector (10, 20, 3, 8, 7));\n//!\n//! // Uninitialized array of same size as other.\n//! NDArray b (a.dims ());\n//! @endcode\n//!\n//! The main thing to understand about this class, is that methods such as\n//! ndims() and numel(), return the value for an Array of these dimensions,\n//! not the actual number of elements in the dim_vector.\n//!\n//! @code{.cc}\n//! dim_vector d (10, 5, 3);\n//! octave_idx_type n = d.numel (); // returns 150\n//! octave_idx_type nd = d.ndims (); // returns 3\n//! @endcode\n//!\n//! ## Implementation details ##\n//!\n//! This implementation is more tricky than Array, but the big plus is that\n//! dim_vector requires only one allocation instead of two.  It is (slightly)\n//! patterned after GCC's basic_string implementation.  rep is a pointer to an\n//! array of memory, comprising count, length, and the data:\n//!\n//! @verbatim\n//!        <count>\n//!        <ndims>\n//! rep --> <dims[0]>\n//!        <dims[1]>\n//!        ...\n//! @endverbatim\n//!\n//! The inlines count(), ndims() recover this data from the rep.  Note\n//! that rep points to the beginning of dims to grant faster access\n//! (reinterpret_cast is assumed to be an inexpensive operation).\n\nclass OCTAVE_API dim_vector\n{\nprivate:\n\n  octave_idx_type m_num_dims;\n\n  octave_idx_type *m_dims;\n\npublic:\n\n  //! Construct dim_vector for a N dimensional array.\n  //!\n  //! Each argument to constructor defines the length of an additional\n  //! dimension.  A dim_vector always represents a minimum of 2 dimensions\n  //! (just like an Array has at least 2 dimensions) and there is no\n  //! upper limit on the number of dimensions.\n  //!\n  //! @code{.cc}\n  //! dim_vector dv (7, 5);\n  //! Matrix mat (dv);\n  //! @endcode\n  //!\n  //! The constructed dim_vector @c dv will have two elements, @f$[7, 5]@f$,\n  //! one for each dimension.  It can then be used to construct a Matrix\n  //! with such dimensions, i.e., 7 rows and 5 columns.\n  //!\n  //! @code{.cc}\n  //! NDArray x (dim_vector (7, 5, 10));\n  //! @endcode\n  //!\n  //! This will construct a 3-dimensional NDArray of lengths 7, 5, and 10,\n  //! on the first, second, and third dimension (rows, columns, and pages)\n  //! respectively.\n  //!\n  //! Note that there is no constructor that accepts only one\n  //! dimension length to avoid confusion.  The source for such confusion\n  //! is that constructor could mean:\n  //!   - a column vector, i.e., assume @f$[N, 1]@f$;\n  //!   - a square matrix, i.e., as is common in Octave interpreter;\n  //!   - support for a 1-dimensional Array (does not exist);\n  //!\n  //! Using r, c, and lengths... as arguments, allow us to check at compile\n  //! time that there's at least 2 dimensions specified, while maintaining\n  //! type safety.\n\n  template <typename... Ints>\n  dim_vector (const octave_idx_type r, const octave_idx_type c,\n              Ints... lengths)\n    : m_num_dims (2 + sizeof... (Ints)), m_dims (new octave_idx_type [m_num_dims])\n  {\n    std::initializer_list<octave_idx_type> all_lengths = {r, c, lengths...};\n    octave_idx_type *ptr = m_dims;\n    for (const octave_idx_type l: all_lengths)\n      *ptr++ = l;\n  }\n\n  // Fast access with absolutely no checking\n\n  octave_idx_type& xelem (int i) { return m_dims[i]; }\n\n  octave_idx_type xelem (int i) const { return m_dims[i]; }\n\n  // Safe access to elements\n\n  octave_idx_type& elem (int i)\n  {\n    return xelem (i);\n  }\n\n  octave_idx_type elem (int i) const { return xelem (i); }\n\n  void chop_trailing_singletons ()\n  {\n    while (m_num_dims > 2 && xelem(m_num_dims-1) == 1)\n      m_num_dims--;\n  }\n\n  OCTAVE_API void chop_all_singletons ();\n\nprivate:\n\n  explicit dim_vector (octave_idx_type ndims)\n    : m_num_dims (ndims < 2 ? 2 : ndims), m_dims (new octave_idx_type [m_num_dims])\n  {\n    std::fill_n (m_dims, m_num_dims, 0);\n  }\n\npublic:\n\n  // The maximum allowed value for a dimension extent.  This will\n  // normally be a tiny bit off the maximum value of octave_idx_type.\n  // Currently, 1 is subtracted to allow safe conversion of any 2-D Array\n  // into Sparse but this offset may change in the future.\n\n  static constexpr octave_idx_type dim_max ()\n  {\n    return std::numeric_limits<octave_idx_type>::max () - 1;\n  }\n\n  explicit dim_vector ()\n    : m_num_dims (2), m_dims (new octave_idx_type [m_num_dims])\n  {\n    std::fill_n (m_dims, m_num_dims, 0);\n  }\n\n  dim_vector (const dim_vector& dv)\n    : m_num_dims (dv.m_num_dims), m_dims (new octave_idx_type [m_num_dims])\n  {\n    std::copy_n (dv.m_dims, m_num_dims, m_dims);\n  }\n\n  dim_vector (dim_vector&& dv)\n    : m_num_dims (0), m_dims (nullptr)\n  {\n    *this = std::move (dv);\n  }\n\n  static dim_vector alloc (int n)\n  {\n    return dim_vector (n);\n  }\n\n  dim_vector& operator = (const dim_vector& dv)\n  {\n    if (&dv != this)\n      {\n        delete [] m_dims;\n\n        m_num_dims = dv.m_num_dims;\n        m_dims = new octave_idx_type [m_num_dims];\n\n        std::copy_n (dv.m_dims, m_num_dims, m_dims);\n      }\n\n    return *this;\n  }\n\n  dim_vector& operator = (dim_vector&& dv)\n  {\n    if (&dv != this)\n      {\n        // Because we define a move constructor and a move assignment\n        // operator, m_dims may be a nullptr here.  We should only need to\n        // protect the destructor in a similar way.\n\n        delete [] m_dims;\n\n        m_num_dims = dv.m_num_dims;\n        m_dims = dv.m_dims;\n\n        dv.m_num_dims = 0;\n        dv.m_dims = nullptr;\n      }\n\n    return *this;\n  }\n\n  ~dim_vector ()\n  {\n    // Because we define a move constructor and a move assignment\n    // operator, m_dims may be a nullptr here.  We should only need to\n    // protect the move assignment operator in a similar way.\n\n    delete [] m_dims;\n  }\n\n  //! Number of dimensions.\n  //!\n  //! Returns the number of dimensions of the dim_vector.  This is number of\n  //! elements in the dim_vector including trailing singletons.  It is also\n  //! the number of dimensions an Array with this dim_vector would have.\n\n  octave_idx_type ndims () const { return m_num_dims; }\n\n  //! Number of dimensions.\n  //! Synonymous with ndims().\n  //!\n  //! While this method is not officially deprecated, consider using ndims()\n  //! instead to avoid confusion.  Array does not have length because of its\n  //! odd definition as length of the longest dimension.\n\n  int length () const { return ndims (); }\n\n  octave_idx_type& operator () (int i) { return elem (i); }\n\n  octave_idx_type operator () (int i) const { return elem (i); }\n\n  void resize (int n, int fill_value = 0)\n  {\n    if (n < 2)\n      n = 2;\n\n    if (n == m_num_dims)\n      return;\n\n    if (n < m_num_dims)\n      {\n        m_num_dims = n;\n        return;\n      }\n\n    octave_idx_type *new_rep = new octave_idx_type [n];\n\n    std::copy_n (m_dims, m_num_dims, new_rep);\n    std::fill_n (new_rep + m_num_dims, n - m_num_dims, fill_value);\n\n    delete [] m_dims;\n\n    m_dims = new_rep;\n\n    m_num_dims = n;\n  }\n\n  OCTAVE_API std::string str (char sep = 'x') const;\n\n  bool all_zero () const\n  {\n    return std::all_of (m_dims, m_dims + ndims (),\n                        [] (octave_idx_type dim) { return dim == 0; });\n  }\n\n  bool empty_2d () const\n  {\n    return ndims () == 2 && (xelem (0) == 0 || xelem (1) == 0);\n  }\n\n  bool zero_by_zero () const\n  {\n    return ndims () == 2 && xelem (0) == 0 && xelem (1) == 0;\n  }\n\n  bool any_zero () const\n  {\n    return std::any_of (m_dims, m_dims + ndims (),\n                        [] (octave_idx_type dim) { return dim == 0; });\n  }\n\n  OCTAVE_API int num_ones () const;\n\n  bool all_ones () const\n  {\n    return (num_ones () == ndims ());\n  }\n\n  //! Number of elements that a matrix with this dimensions would have.\n  //!\n  //! Return the number of elements that a matrix with this dimension\n  //! vector would have, NOT the number of dimensions (elements in the\n  //! dimension vector).\n\n  octave_idx_type numel (int n = 0) const\n  {\n    int n_dims = ndims ();\n\n    octave_idx_type retval = 1;\n\n    for (int i = n; i < n_dims; i++)\n      retval *= elem (i);\n\n    return retval;\n  }\n\n  //! The following function will throw a std::bad_alloc ()\n  //! exception if the requested size is larger than can be indexed by\n  //! octave_idx_type.  This may be smaller than the actual amount of\n  //! memory that can be safely allocated on a system.  However, if we\n  //! don't fail here, we can end up with a mysterious crash inside a\n  //! function that is iterating over an array using octave_idx_type\n  //! indices.\n\n  // IF we ever require C++26 we can use ckd_mul in the following\n  // function and not have to check for or explicitly call\n  // __builtin_mul_overflow.\n  octave_idx_type safe_numel () const\n  {\n    octave_idx_type n = xelem(0);\n\n    if (n > dim_max ())\n      throw std::bad_alloc ();\n\n    if (n == 0)\n      return 0;\n\n    for (int i = 1; i < ndims (); i++)\n      {\n#if defined (__has_builtin) && __has_builtin (__builtin_mul_overflow)\n        bool overflow = __builtin_mul_overflow (n, xelem(i), &n);\n#else\n        // Function call overhead, much less efficient than using the\n        // built-in function or ckd_mul (C23 / C++26)\n        bool overflow = octave::math::int_multiply_overflow (n, xelem(i), &n);\n#endif\n\n        if (overflow || n > dim_max ())\n          throw std::bad_alloc ();\n\n        if (n == 0)\n          return 0;\n      }\n\n    return n;\n  }\n\n  bool any_neg () const\n  {\n    return std::any_of (m_dims, m_dims + ndims (),\n                        [] (octave_idx_type dim) { return dim < 0; });\n  }\n\n  OCTAVE_API dim_vector squeeze () const;\n\n  //! This corresponds to cat().\n  OCTAVE_API bool concat (const dim_vector& dvb, int dim);\n\n  //! This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).\n  // The rules are more relaxed here.\n  OCTAVE_API bool hvcat (const dim_vector& dvb, int dim);\n\n  //! Force certain dimensionality, preserving numel ().  Missing\n  //! dimensions are set to 1, redundant are folded into the trailing\n  //! one.  If n = 1, the result is 2-D and the second dim is 1\n  //! (dim_vectors are always at least 2-D).\n\n  OCTAVE_API dim_vector redim (int n) const;\n\n  dim_vector as_column () const\n  {\n    if (ndims () == 2 && xelem (1) == 1)\n      return *this;\n    else\n      return dim_vector (numel (), 1);\n  }\n\n  dim_vector as_row () const\n  {\n    if (ndims () == 2 && xelem (0) == 1)\n      return *this;\n    else\n      return dim_vector (1, numel ());\n  }\n\n  bool isvector () const\n  {\n    return (ndims () == 2 && (xelem (0) == 1 || xelem (1) == 1));\n  }\n\n  bool is_nd_vector () const\n  {\n    int num_non_one = 0;\n\n    for (int i = 0; i < ndims (); i++)\n      {\n        if (xelem (i) != 1)\n          {\n            num_non_one++;\n\n            if (num_non_one > 1)\n              break;\n          }\n      }\n\n    return num_non_one == 1;\n  }\n\n  // Create a vector with length N.  If this object is a vector,\n  // preserve the orientation, otherwise, create a column vector.\n\n  dim_vector make_nd_vector (octave_idx_type n) const\n  {\n    dim_vector orig_dims;\n\n    if (is_nd_vector ())\n      {\n        orig_dims = *this;\n\n        for (int i = 0; i < orig_dims.ndims (); i++)\n          {\n            if (orig_dims(i) != 1)\n              {\n                orig_dims(i) = n;\n                break;\n              }\n          }\n      }\n    else\n      orig_dims = dim_vector (n, 1);\n\n    return orig_dims;\n  }\n\n  int first_non_singleton (int def = 0) const\n  {\n    for (int i = 0; i < ndims (); i++)\n      {\n        if (xelem (i) != 1)\n          return i;\n      }\n\n    return def;\n  }\n\n  //! Linear index from an index tuple.\n  octave_idx_type compute_index (const octave_idx_type *idx) const\n  { return compute_index (idx, ndims ()); }\n\n  //! Linear index from an incomplete index tuple (nidx < length ()).\n  octave_idx_type compute_index (const octave_idx_type *idx, int nidx) const\n  {\n    octave_idx_type k = 0;\n    for (int i = nidx - 1; i >= 0; i--)\n      k = xelem(i) * k + idx[i];\n\n    return k;\n  }\n\n  //! Increment a multi-dimensional index tuple, optionally starting\n  //! from an offset position and return the index of the last index\n  //! position that was changed, or length () if just cycled over.\n\n  int increment_index (octave_idx_type *idx, int start = 0) const\n  {\n    int i;\n    for (i = start; i < ndims (); i++)\n      {\n        if (++(*idx) == xelem(i))\n          *idx++ = 0;\n        else\n          break;\n      }\n    return i;\n  }\n\n  //! Return cumulative dimensions.\n\n  dim_vector cumulative () const\n  {\n    int nd = ndims ();\n    dim_vector retval = alloc (nd);\n\n    octave_idx_type k = 1;\n    for (int i = 0; i < nd; i++)\n      retval.xelem(i) = (k *= xelem(i));\n\n    return retval;\n  }\n\n  //! Compute a linear index from an index tuple.  Dimensions are\n  //! required to be cumulative.\n\n  octave_idx_type cum_compute_index (const octave_idx_type *idx) const\n  {\n    octave_idx_type k = idx[0];\n\n    for (int i = 1; i < ndims (); i++)\n      k += xelem(i-1) * idx[i];\n\n    return k;\n  }\n\n  friend OCTAVE_API bool\n  operator == (const dim_vector& a, const dim_vector& b);\n\n  OCTAVE_API Array<octave_idx_type> as_array () const;\n};\n\ninline bool\noperator == (const dim_vector& a, const dim_vector& b)\n{\n  // Fast case.\n  if (a.m_dims == b.m_dims)\n    return true;\n\n  int a_len = a.ndims ();\n  int b_len = b.ndims ();\n\n  if (a_len != b_len)\n    return false;\n\n  return std::equal (a.m_dims, a.m_dims + a_len, b.m_dims);\n}\n\ninline bool\noperator != (const dim_vector& a, const dim_vector& b)\n{\n  return ! operator == (a, b);\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fCColVector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"blas-proto.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// FloatComplex Column Vector class\n\nFloatComplexColumnVector::FloatComplexColumnVector (const FloatColumnVector& a)\n  : MArray<FloatComplex> (a)\n{ }\n\nbool\nFloatComplexColumnVector::operator == (const FloatComplexColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  if (len != a.numel ())\n    return 0;\n  return mx_inline_equal (len, data (), a.data ());\n}\n\nbool\nFloatComplexColumnVector::operator != (const FloatComplexColumnVector& a) const\n{\n  return !(*this == a);\n}\n\n// destructive insert/delete/reorder operations\n\nFloatComplexColumnVector&\nFloatComplexColumnVector::insert (const FloatColumnVector& a, octave_idx_type r)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatComplexColumnVector&\nFloatComplexColumnVector::insert (const FloatComplexColumnVector& a,\n                                  octave_idx_type r)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatComplexColumnVector&\nFloatComplexColumnVector::fill (float val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexColumnVector&\nFloatComplexColumnVector::fill (const FloatComplex& val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexColumnVector&\nFloatComplexColumnVector::fill (float val,\n                                octave_idx_type r1, octave_idx_type r2)\n{\n  octave_idx_type len = numel ();\n\n  if (r1 < 0 || r2 < 0 || r1 >= len || r2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  if (r2 >= r1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = r1; i <= r2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexColumnVector&\nFloatComplexColumnVector::fill (const FloatComplex& val,\n                                octave_idx_type r1, octave_idx_type r2)\n{\n  octave_idx_type len = numel ();\n\n  if (r1 < 0 || r2 < 0 || r1 >= len || r2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  if (r2 >= r1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = r1; i <= r2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexColumnVector\nFloatComplexColumnVector::stack (const FloatColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nr_insert = len;\n  FloatComplexColumnVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nr_insert);\n  return retval;\n}\n\nFloatComplexColumnVector\nFloatComplexColumnVector::stack (const FloatComplexColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nr_insert = len;\n  FloatComplexColumnVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nr_insert);\n  return retval;\n}\n\nFloatComplexRowVector\nFloatComplexColumnVector::hermitian () const\n{\n  return MArray<FloatComplex>::hermitian (std::conj);\n}\n\nFloatComplexRowVector\nFloatComplexColumnVector::transpose () const\n{\n  return MArray<FloatComplex>::transpose ();\n}\n\nFloatColumnVector\nFloatComplexColumnVector::abs () const\n{\n  return do_mx_unary_map<float, FloatComplex, std::abs> (*this);\n}\n\nFloatComplexColumnVector\nconj (const FloatComplexColumnVector& a)\n{\n  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float>> (a);\n}\n\n// resize is the destructive equivalent for this one\n\nFloatComplexColumnVector\nFloatComplexColumnVector::extract (octave_idx_type r1, octave_idx_type r2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  octave_idx_type new_r = r2 - r1 + 1;\n\n  FloatComplexColumnVector result (new_r);\n\n  for (octave_idx_type i = 0; i < new_r; i++)\n    result.elem (i) = elem (r1+i);\n\n  return result;\n}\n\nFloatComplexColumnVector\nFloatComplexColumnVector::extract_n (octave_idx_type r1,\n                                     octave_idx_type n) const\n{\n  FloatComplexColumnVector result (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    result.elem (i) = elem (r1+i);\n\n  return result;\n}\n\n// column vector by column vector -> column vector operations\n\nFloatComplexColumnVector&\nFloatComplexColumnVector::operator += (const FloatColumnVector& a)\n{\n  octave_idx_type len = numel ();\n\n  octave_idx_type a_len = a.numel ();\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator +=\", len, a_len);\n\n  if (len == 0)\n    return *this;\n\n  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!\n\n  mx_inline_add2 (len, d, a.data ());\n  return *this;\n}\n\nFloatComplexColumnVector&\nFloatComplexColumnVector::operator -= (const FloatColumnVector& a)\n{\n  octave_idx_type len = numel ();\n\n  octave_idx_type a_len = a.numel ();\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator -=\", len, a_len);\n\n  if (len == 0)\n    return *this;\n\n  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!\n\n  mx_inline_sub2 (len, d, a.data ());\n  return *this;\n}\n\n// matrix by column vector -> column vector operations\n\nFloatComplexColumnVector\noperator * (const FloatComplexMatrix& m, const FloatColumnVector& a)\n{\n  FloatComplexColumnVector tmp (a);\n  return m * tmp;\n}\n\nFloatComplexColumnVector\noperator * (const FloatComplexMatrix& m, const FloatComplexColumnVector& a)\n{\n  FloatComplexColumnVector retval;\n\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  retval.clear (nr);\n\n  if (nr != 0)\n    {\n      if (nc == 0)\n        retval.fill (0.0);\n      else\n        {\n          FloatComplex *y = retval.rwdata ();\n\n          F77_XFCN (cgemv, CGEMV, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                                   nr, nc, 1.0f, F77_CONST_CMPLX_ARG (m.data ()), nr,\n                                   F77_CONST_CMPLX_ARG (a.data ()), 1, 0.0f, F77_CMPLX_ARG (y), 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n    }\n\n  return retval;\n}\n\n// matrix by column vector -> column vector operations\n\nFloatComplexColumnVector\noperator * (const FloatMatrix& m, const FloatComplexColumnVector& a)\n{\n  FloatComplexMatrix tmp (m);\n  return tmp * a;\n}\n\n// diagonal matrix by column vector -> column vector operations\n\nFloatComplexColumnVector\noperator * (const FloatDiagMatrix& m, const FloatComplexColumnVector& a)\n{\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  if (nc == 0 || nr == 0)\n    return FloatComplexColumnVector (0);\n\n  FloatComplexColumnVector result (nr);\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    result.elem (i) = a.elem (i) * m.elem (i, i);\n\n  for (octave_idx_type i = a_len; i < nr; i++)\n    result.elem (i) = 0.0;\n\n  return result;\n}\n\nFloatComplexColumnVector\noperator * (const FloatComplexDiagMatrix& m, const FloatColumnVector& a)\n{\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  if (nc == 0 || nr == 0)\n    return FloatComplexColumnVector (0);\n\n  FloatComplexColumnVector result (nr);\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    result.elem (i) = a.elem (i) * m.elem (i, i);\n\n  for (octave_idx_type i = a_len; i < nr; i++)\n    result.elem (i) = 0.0;\n\n  return result;\n}\n\nFloatComplexColumnVector\noperator * (const FloatComplexDiagMatrix& m, const FloatComplexColumnVector& a)\n{\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  if (nc == 0 || nr == 0)\n    return FloatComplexColumnVector (0);\n\n  FloatComplexColumnVector result (nr);\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    result.elem (i) = a.elem (i) * m.elem (i, i);\n\n  for (octave_idx_type i = a_len; i < nr; i++)\n    result.elem (i) = 0.0;\n\n  return result;\n}\n\n// other operations\n\nFloatComplex\nFloatComplexColumnVector::min () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0.0;\n\n  FloatComplex res = elem (0);\n  float absres = std::abs (res);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (std::abs (elem (i)) < absres)\n      {\n        res = elem (i);\n        absres = std::abs (res);\n      }\n\n  return res;\n}\n\nFloatComplex\nFloatComplexColumnVector::max () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0.0;\n\n  FloatComplex res = elem (0);\n  float absres = std::abs (res);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (std::abs (elem (i)) > absres)\n      {\n        res = elem (i);\n        absres = std::abs (res);\n      }\n\n  return res;\n}\n\n// i/o\n\nstd::ostream&\noperator << (std::ostream& os, const FloatComplexColumnVector& a)\n{\n//  int field_width = os.precision () + 7;\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    os << /* setw (field_width) << */ a.elem (i) << \"\\n\";\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, FloatComplexColumnVector& a)\n{\n  octave_idx_type len = a.numel ();\n\n  if (len > 0)\n    {\n      float tmp;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          is >> tmp;\n          if (is)\n            a.elem (i) = tmp;\n          else\n            break;\n        }\n    }\n  return is;\n}\n"
  },
  {
    "path": "liboctave/array/fCColVector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fCColVector_h)\n#define octave_fCColVector_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API FloatComplexColumnVector : public MArray<FloatComplex>\n{\n  friend class FloatComplexMatrix;\n  friend class FloatComplexRowVector;\n\npublic:\n\n  FloatComplexColumnVector ()\n    : MArray<FloatComplex> (dim_vector (0, 1)) { }\n\n  explicit FloatComplexColumnVector (octave_idx_type n)\n    : MArray<FloatComplex> (dim_vector (n, 1)) { }\n\n  explicit FloatComplexColumnVector (const dim_vector& dv)\n    : MArray<FloatComplex> (dv.as_column ()) { }\n\n  FloatComplexColumnVector (octave_idx_type n, const FloatComplex& val)\n    : MArray<FloatComplex> (dim_vector (n, 1), val) { }\n\n  FloatComplexColumnVector (const FloatComplexColumnVector& a)\n    : MArray<FloatComplex> (a) { }\n\n  FloatComplexColumnVector (const MArray<FloatComplex>& a)\n    : MArray<FloatComplex> (a.as_column ()) { }\n\n  FloatComplexColumnVector (const Array<FloatComplex>& a)\n    : MArray<FloatComplex> (a.as_column ()) { }\n\n  explicit OCTAVE_API FloatComplexColumnVector (const FloatColumnVector& a);\n\n  FloatComplexColumnVector& operator = (const FloatComplexColumnVector& a)\n  {\n    MArray<FloatComplex>::operator = (a);\n    return *this;\n  }\n\n  ~FloatComplexColumnVector () = default;\n\n  OCTAVE_API bool operator == (const FloatComplexColumnVector& a) const;\n  OCTAVE_API bool operator != (const FloatComplexColumnVector& a) const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API FloatComplexColumnVector&\n  insert (const FloatColumnVector& a, octave_idx_type r);\n  OCTAVE_API FloatComplexColumnVector&\n  insert (const FloatComplexColumnVector& a, octave_idx_type r);\n\n  OCTAVE_API FloatComplexColumnVector& fill (float val);\n  OCTAVE_API FloatComplexColumnVector& fill (const FloatComplex& val);\n  OCTAVE_API FloatComplexColumnVector&\n  fill (float val, octave_idx_type r1, octave_idx_type r2);\n  OCTAVE_API FloatComplexColumnVector&\n  fill (const FloatComplex& val, octave_idx_type r1, octave_idx_type r2);\n\n  OCTAVE_API FloatComplexColumnVector stack (const FloatColumnVector& a) const;\n  OCTAVE_API FloatComplexColumnVector\n  stack (const FloatComplexColumnVector& a) const;\n\n  OCTAVE_API FloatComplexRowVector hermitian () const;\n  OCTAVE_API FloatComplexRowVector transpose () const;\n\n  friend OCTAVE_API FloatComplexColumnVector\n  OCTAVE_API conj (const FloatComplexColumnVector& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API FloatComplexColumnVector\n  extract (octave_idx_type r1, octave_idx_type r2) const;\n\n  OCTAVE_API FloatComplexColumnVector\n  extract_n (octave_idx_type r1, octave_idx_type n) const;\n\n  // column vector by column vector -> column vector operations\n\n  OCTAVE_API FloatComplexColumnVector&\n  operator += (const FloatColumnVector& a);\n  OCTAVE_API FloatComplexColumnVector&\n  operator -= (const FloatColumnVector& a);\n\n  // matrix by column vector -> column vector operations\n\n  friend OCTAVE_API FloatComplexColumnVector\n  operator * (const FloatComplexMatrix& a, const FloatColumnVector& b);\n\n  friend OCTAVE_API FloatComplexColumnVector\n  operator * (const FloatComplexMatrix& a, const FloatComplexColumnVector& b);\n\n  // matrix by column vector -> column vector operations\n\n  friend OCTAVE_API FloatComplexColumnVector\n  operator * (const FloatMatrix& a, const FloatComplexColumnVector& b);\n\n  // diagonal matrix by column vector -> column vector operations\n\n  friend OCTAVE_API FloatComplexColumnVector\n  operator * (const FloatDiagMatrix& a, const FloatComplexColumnVector& b);\n\n  friend OCTAVE_API FloatComplexColumnVector\n  operator * (const FloatComplexDiagMatrix& a, const ColumnVector& b);\n\n  friend OCTAVE_API FloatComplexColumnVector\n  operator * (const FloatComplexDiagMatrix& a, const FloatComplexColumnVector& b);\n\n  // other operations\n\n  OCTAVE_API FloatComplex min () const;\n  OCTAVE_API FloatComplex max () const;\n\n  OCTAVE_API FloatColumnVector abs () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const FloatComplexColumnVector& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, FloatComplexColumnVector& a);\n\n  void resize (octave_idx_type n, const FloatComplex& rfv = FloatComplex (0))\n  {\n    Array<FloatComplex>::resize (dim_vector (n, 1), rfv);\n  }\n\n  void clear (octave_idx_type n)\n  { Array<FloatComplex>::clear (n, 1); }\n\n};\n\nMARRAY_FORWARD_DEFS (MArray, FloatComplexColumnVector, FloatComplex)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fCDiagMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"lo-ieee.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// FloatComplex Diagonal Matrix class\n\nFloatComplexDiagMatrix::FloatComplexDiagMatrix (const FloatDiagMatrix& a)\n  : MDiagArray2<FloatComplex> (a.rows (), a.cols ())\n{\n  for (octave_idx_type i = 0; i < length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nbool\nFloatComplexDiagMatrix::operator == (const FloatComplexDiagMatrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return 0;\n\n  return mx_inline_equal (length (), data (), a.data ());\n}\n\nbool\nFloatComplexDiagMatrix::operator != (const FloatComplexDiagMatrix& a) const\n{\n  return !(*this == a);\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (float val)\n{\n  for (octave_idx_type i = 0; i < length (); i++)\n    elem (i, i) = val;\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatComplex& val)\n{\n  for (octave_idx_type i = 0; i < length (); i++)\n    elem (i, i) = val;\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (float val,\n                              octave_idx_type beg, octave_idx_type end)\n{\n  if (beg < 0 || end >= length () || end < beg)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = beg; i <= end; i++)\n    elem (i, i) = val;\n\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatComplex& val,\n                              octave_idx_type beg, octave_idx_type end)\n{\n  if (beg < 0 || end >= length () || end < beg)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = beg; i <= end; i++)\n    elem (i, i) = val;\n\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatColumnVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatComplexColumnVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatRowVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatComplexRowVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatColumnVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatComplexColumnVector& a,\n                              octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatRowVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::fill (const FloatComplexRowVector& a,\n                              octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nFloatDiagMatrix\nFloatComplexDiagMatrix::abs () const\n{\n  return FloatDiagMatrix (extract_diag ().abs (), rows (), columns ());\n}\n\nFloatComplexDiagMatrix\nconj (const FloatComplexDiagMatrix& a)\n{\n  return FloatComplexDiagMatrix (conj (a.extract_diag ()), a.rows (),\n                                 a.columns ());\n}\n\n// resize is the destructive analog for this one\n\nFloatComplexMatrix\nFloatComplexDiagMatrix::extract (octave_idx_type r1, octave_idx_type c1,\n                                 octave_idx_type r2, octave_idx_type c2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  octave_idx_type new_r = r2 - r1 + 1;\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  FloatComplexMatrix result (new_r, new_c);\n\n  for (octave_idx_type j = 0; j < new_c; j++)\n    for (octave_idx_type i = 0; i < new_r; i++)\n      result.elem (i, j) = elem (r1+i, c1+j);\n\n  return result;\n}\n\n// extract row or column i.\n\nFloatComplexRowVector\nFloatComplexDiagMatrix::row (octave_idx_type i) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (i < 0 || i >= r)\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n\n  FloatComplexRowVector retval (c, 0.0);\n  if (r <= c || i < c)\n    retval.elem (i) = elem (i, i);\n\n  return retval;\n}\n\nFloatComplexRowVector\nFloatComplexDiagMatrix::row (char *s) const\n{\n  if (! s)\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n\n  char c = s[0];\n  if (c == 'f' || c == 'F')\n    return row (static_cast<octave_idx_type> (0));\n  else if (c == 'l' || c == 'L')\n    return row (rows () - 1);\n  else\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n}\n\nFloatComplexColumnVector\nFloatComplexDiagMatrix::column (octave_idx_type i) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (i < 0 || i >= c)\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n\n  FloatComplexColumnVector retval (r, 0.0);\n  if (r >= c || i < r)\n    retval.elem (i) = elem (i, i);\n\n  return retval;\n}\n\nFloatComplexColumnVector\nFloatComplexDiagMatrix::column (char *s) const\n{\n  if (! s)\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n\n  char c = s[0];\n  if (c == 'f' || c == 'F')\n    return column (static_cast<octave_idx_type> (0));\n  else if (c == 'l' || c == 'L')\n    return column (cols () - 1);\n  else\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n}\n\nFloatComplexDiagMatrix\nFloatComplexDiagMatrix::inverse () const\n{\n  octave_idx_type info;\n  return inverse (info);\n}\n\nFloatComplexDiagMatrix\nFloatComplexDiagMatrix::inverse (octave_idx_type& info) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (r != c)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  FloatComplexDiagMatrix retval (r, c);\n\n  info = 0;\n  for (octave_idx_type i = 0; i < length (); i++)\n    {\n      if (elem (i, i) == 0.0f)\n        {\n          info = -1;\n          return *this;\n        }\n      else\n        retval.elem (i, i) = 1.0f / elem (i, i);\n    }\n\n  return retval;\n}\n\nFloatComplexDiagMatrix\nFloatComplexDiagMatrix::pseudo_inverse (float tol) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  octave_idx_type len = length ();\n\n  FloatComplexDiagMatrix retval (c, r);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      float val = std::abs (elem (i, i));\n      if (val < tol || val == 0.0f)\n        retval.elem (i, i) = 0.0f;\n      else\n        retval.elem (i, i) = 1.0f / elem (i, i);\n    }\n\n  return retval;\n}\n\nbool\nFloatComplexDiagMatrix::all_elements_are_real () const\n{\n  return mx_inline_all_real (length (), data ());\n}\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\nFloatComplexDiagMatrix&\nFloatComplexDiagMatrix::operator += (const FloatDiagMatrix& a)\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r != a_nr || c != a_nc)\n    octave::err_nonconformant (\"operator +=\", r, c, a_nr, a_nc);\n\n  if (r == 0 || c == 0)\n    return *this;\n\n  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!\n\n  mx_inline_add2 (length (), d, a.data ());\n  return *this;\n}\n\nFloatComplexDiagMatrix\noperator * (const FloatComplexDiagMatrix& a, const FloatDiagMatrix& b)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  FloatComplexDiagMatrix c (a_nr, b_nc);\n\n  octave_idx_type len = c.length ();\n  octave_idx_type lenm = (len < a_nc ? len : a_nc);\n\n  for (octave_idx_type i = 0; i < lenm; i++)\n    c.dgxelem (i) = a.dgelem (i) * b.dgelem (i);\n  for (octave_idx_type i = lenm; i < len; i++)\n    c.dgxelem (i) = 0.0f;\n\n  return c;\n}\n\nFloatComplexDiagMatrix\noperator * (const FloatDiagMatrix& a, const FloatComplexDiagMatrix& b)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  if (a_nr == 0 || a_nc == 0 || b_nc == 0)\n    return FloatComplexDiagMatrix (a_nr, a_nc, 0.0);\n\n  FloatComplexDiagMatrix c (a_nr, b_nc);\n\n  octave_idx_type len = (a_nr < b_nc ? a_nr : b_nc);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      float a_element = a.elem (i, i);\n      FloatComplex b_element = b.elem (i, i);\n\n      c.elem (i, i) = a_element * b_element;\n    }\n\n  return c;\n}\n\nFloatComplexDiagMatrix\noperator * (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  if (a_nr == 0 || a_nc == 0 || b_nc == 0)\n    return FloatComplexDiagMatrix (a_nr, a_nc, 0.0);\n\n  FloatComplexDiagMatrix c (a_nr, b_nc);\n\n  octave_idx_type len = (a_nr < b_nc ? a_nr : b_nc);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      FloatComplex a_element = a.elem (i, i);\n      FloatComplex b_element = b.elem (i, i);\n\n      c.elem (i, i) = a_element * b_element;\n    }\n\n  return c;\n}\n\n// other operations\n\nFloatComplexDET\nFloatComplexDiagMatrix::determinant () const\n{\n  FloatComplexDET det (1.0f);\n  if (rows () != cols ())\n    (*current_liboctave_error_handler) (\"determinant requires square matrix\");\n\n  octave_idx_type len = length ();\n  for (octave_idx_type i = 0; i < len; i++)\n    det *= elem (i, i);\n\n  return det;\n}\n\nfloat\nFloatComplexDiagMatrix::rcond () const\n{\n  FloatColumnVector av = extract_diag (0).map<float> (std::abs);\n  float amx = av.max ();\n  float amn = av.min ();\n  return amx == 0 ? 0.0f : amn / amx;\n}\n\n// i/o\n\nstd::ostream&\noperator << (std::ostream& os, const FloatComplexDiagMatrix& a)\n{\n  FloatComplex ZERO (0.0);\n//  int field_width = os.precision () + 7;\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    {\n      for (octave_idx_type j = 0; j < a.cols (); j++)\n        {\n          if (i == j)\n            os << ' ' /* setw (field_width) */ << a.elem (i, i);\n          else\n            os << ' ' /* setw (field_width) */ << ZERO;\n        }\n      os << \"\\n\";\n    }\n  return os;\n}\n"
  },
  {
    "path": "liboctave/array/fCDiagMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fCDiagMatrix_h)\n#define octave_fCDiagMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"DET.h\"\n#include \"MDiagArray2.h\"\n#include \"fCColVector.h\"\n#include \"fCRowVector.h\"\n#include \"fColVector.h\"\n#include \"fRowVector.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API FloatComplexDiagMatrix : public MDiagArray2<FloatComplex>\n{\npublic:\n\n  typedef FloatComplexMatrix full_matrix_type;\n\n  typedef float real_elt_type;\n  typedef FloatComplex complex_elt_type;\n  typedef FloatComplex element_type;\n\n  FloatComplexDiagMatrix () = default;\n\n  FloatComplexDiagMatrix (const FloatComplexDiagMatrix& a) = default;\n\n  FloatComplexDiagMatrix& operator = (const FloatComplexDiagMatrix& a) = default;\n\n  ~FloatComplexDiagMatrix () = default;\n\n  FloatComplexDiagMatrix (octave_idx_type r,\n                          octave_idx_type c)\n    : MDiagArray2<FloatComplex> (r, c) { }\n\n  FloatComplexDiagMatrix (octave_idx_type r, octave_idx_type c,\n                          const FloatComplex& val)\n    : MDiagArray2<FloatComplex> (r, c, val) { }\n\n  explicit FloatComplexDiagMatrix (const Array<FloatComplex>& a)\n    : MDiagArray2<FloatComplex> (a) { }\n\n  FloatComplexDiagMatrix (const Array<FloatComplex>& a, octave_idx_type r,\n                          octave_idx_type c)\n    : MDiagArray2<FloatComplex> (a, r, c) { }\n\n  explicit FloatComplexDiagMatrix (const Array<float>& a)\n    : MDiagArray2<FloatComplex> (Array<FloatComplex> (a)) { }\n\n  explicit OCTAVE_API FloatComplexDiagMatrix (const FloatDiagMatrix& a);\n\n  FloatComplexDiagMatrix (const MDiagArray2<FloatComplex>& a)\n    : MDiagArray2<FloatComplex> (a) { }\n\n  template <typename U>\n  FloatComplexDiagMatrix (const DiagArray2<U>& a)\n    : MDiagArray2<FloatComplex> (a) { }\n\n  OCTAVE_API bool operator == (const FloatComplexDiagMatrix& a) const;\n  OCTAVE_API bool operator != (const FloatComplexDiagMatrix& a) const;\n\n  OCTAVE_API FloatComplexDiagMatrix& fill (float val);\n  OCTAVE_API FloatComplexDiagMatrix& fill (const FloatComplex& val);\n  OCTAVE_API FloatComplexDiagMatrix&\n  fill (float val, octave_idx_type beg, octave_idx_type end);\n  OCTAVE_API FloatComplexDiagMatrix&\n  fill (const FloatComplex& val, octave_idx_type beg, octave_idx_type end);\n  OCTAVE_API FloatComplexDiagMatrix& fill (const FloatColumnVector& a);\n  OCTAVE_API FloatComplexDiagMatrix& fill (const FloatComplexColumnVector& a);\n  OCTAVE_API FloatComplexDiagMatrix& fill (const FloatRowVector& a);\n  OCTAVE_API FloatComplexDiagMatrix& fill (const FloatComplexRowVector& a);\n  OCTAVE_API FloatComplexDiagMatrix&\n  fill (const FloatColumnVector& a, octave_idx_type beg);\n  OCTAVE_API FloatComplexDiagMatrix&\n  fill (const FloatComplexColumnVector& a, octave_idx_type beg);\n  OCTAVE_API FloatComplexDiagMatrix&\n  fill (const FloatRowVector& a, octave_idx_type beg);\n  OCTAVE_API FloatComplexDiagMatrix&\n  fill (const FloatComplexRowVector& a, octave_idx_type beg);\n\n  FloatComplexDiagMatrix hermitian () const\n  { return MDiagArray2<FloatComplex>::hermitian (std::conj); }\n  FloatComplexDiagMatrix transpose () const\n  { return MDiagArray2<FloatComplex>::transpose (); }\n  OCTAVE_API FloatDiagMatrix abs () const;\n\n  friend OCTAVE_API FloatComplexDiagMatrix\n  conj (const FloatComplexDiagMatrix& a);\n\n  // resize is the destructive analog for this one\n\n  OCTAVE_API FloatComplexMatrix\n  extract (octave_idx_type r1, octave_idx_type c1,\n           octave_idx_type r2, octave_idx_type c2) const;\n\n  // extract row or column i\n\n  OCTAVE_API FloatComplexRowVector row (octave_idx_type i) const;\n  OCTAVE_API FloatComplexRowVector row (char *s) const;\n\n  OCTAVE_API FloatComplexColumnVector column (octave_idx_type i) const;\n  OCTAVE_API FloatComplexColumnVector column (char *s) const;\n\n  OCTAVE_API FloatComplexDiagMatrix inverse (octave_idx_type& info) const;\n  OCTAVE_API FloatComplexDiagMatrix inverse () const;\n  OCTAVE_API FloatComplexDiagMatrix pseudo_inverse (float tol = 0.0f) const;\n\n  OCTAVE_API bool all_elements_are_real () const;\n\n  // diagonal matrix by diagonal matrix -> diagonal matrix operations\n\n  OCTAVE_API FloatComplexDiagMatrix& operator += (const FloatDiagMatrix& a);\n  OCTAVE_API FloatComplexDiagMatrix& operator -= (const FloatDiagMatrix& a);\n\n  // other operations\n\n  FloatComplexColumnVector extract_diag (octave_idx_type k = 0) const\n  { return MDiagArray2<FloatComplex>::extract_diag (k); }\n\n  OCTAVE_API FloatComplexDET determinant () const;\n  OCTAVE_API float rcond () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const FloatComplexDiagMatrix& a);\n\n};\n\nOCTAVE_API FloatComplexDiagMatrix conj (const FloatComplexDiagMatrix& a);\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\nOCTAVE_API FloatComplexDiagMatrix\noperator * (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b);\n\nOCTAVE_API FloatComplexDiagMatrix\noperator * (const FloatComplexDiagMatrix& a, const FloatDiagMatrix& b);\n\nOCTAVE_API FloatComplexDiagMatrix\noperator * (const FloatDiagMatrix& a, const FloatComplexDiagMatrix& b);\n\nMDIAGARRAY2_FORWARD_DEFS (MDiagArray2, FloatComplexDiagMatrix, FloatComplex)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fCMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <cmath>\n#include <complex>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"DET.h\"\n#include \"blas-proto.h\"\n#include \"boolMatrix.h\"\n#include \"chMatrix.h\"\n#include \"chol.h\"\n#include \"fCColVector.h\"\n#include \"fCDiagMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"fCNDArray.h\"\n#include \"fCRowVector.h\"\n#include \"lapack-proto.h\"\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"mx-fcm-fdm.h\"\n#include \"mx-fcm-fs.h\"\n#include \"mx-fdm-fcm.h\"\n#include \"mx-inlines.cc\"\n#include \"mx-op-defs.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-norm.h\"\n#include \"schur.h\"\n#include \"svd.h\"\n\nstatic const FloatComplex FloatComplex_NaN_result (octave::numeric_limits<float>::NaN (),\n                                                   octave::numeric_limits<float>::NaN ());\n\n// FloatComplex Matrix class\n\nFloatComplexMatrix::FloatComplexMatrix (const FloatMatrix& a)\n  : FloatComplexNDArray (a)\n{ }\n\nFloatComplexMatrix::FloatComplexMatrix (const FloatRowVector& rv)\n  : FloatComplexNDArray (rv)\n{ }\n\nFloatComplexMatrix::FloatComplexMatrix (const FloatColumnVector& cv)\n  : FloatComplexNDArray (cv)\n{ }\n\nFloatComplexMatrix::FloatComplexMatrix (const FloatDiagMatrix& a)\n  : FloatComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nFloatComplexMatrix::FloatComplexMatrix (const MDiagArray2<float>& a)\n  : FloatComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nFloatComplexMatrix::FloatComplexMatrix (const DiagArray2<float>& a)\n  : FloatComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nFloatComplexMatrix::FloatComplexMatrix (const FloatComplexRowVector& rv)\n  : FloatComplexNDArray (rv)\n{ }\n\nFloatComplexMatrix::FloatComplexMatrix (const FloatComplexColumnVector& cv)\n  : FloatComplexNDArray (cv)\n{ }\n\nFloatComplexMatrix::FloatComplexMatrix (const FloatComplexDiagMatrix& a)\n  : FloatComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nFloatComplexMatrix::FloatComplexMatrix (const MDiagArray2<FloatComplex>& a)\n  : FloatComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nFloatComplexMatrix::FloatComplexMatrix (const DiagArray2<FloatComplex>& a)\n  : FloatComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\n// FIXME: could we use a templated mixed-type copy function\n// here?\n\nFloatComplexMatrix::FloatComplexMatrix (const boolMatrix& a)\n  : FloatComplexNDArray (a)\n{ }\n\nFloatComplexMatrix::FloatComplexMatrix (const charMatrix& a)\n  : FloatComplexNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    for (octave_idx_type j = 0; j < a.cols (); j++)\n      elem (i, j) = static_cast<unsigned char> (a.elem (i, j));\n}\n\nFloatComplexMatrix::FloatComplexMatrix (const FloatMatrix& re,\n                                        const FloatMatrix& im)\n  : FloatComplexNDArray (re.dims ())\n{\n  if (im.rows () != rows () || im.cols () != cols ())\n    (*current_liboctave_error_handler) (\"complex: internal error\");\n\n  octave_idx_type nel = numel ();\n  for (octave_idx_type i = 0; i < nel; i++)\n    xelem (i) = FloatComplex (re(i), im(i));\n}\n\nbool\nFloatComplexMatrix::operator == (const FloatComplexMatrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return false;\n\n  return mx_inline_equal (numel (), data (), a.data ());\n}\n\nbool\nFloatComplexMatrix::operator != (const FloatComplexMatrix& a) const\n{\n  return !(*this == a);\n}\n\nbool\nFloatComplexMatrix::ishermitian () const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (issquare () && nr > 0)\n    {\n      for (octave_idx_type i = 0; i < nr; i++)\n        for (octave_idx_type j = i; j < nc; j++)\n          if (elem (i, j) != conj (elem (j, i)))\n            return false;\n\n      return true;\n    }\n\n  return false;\n}\n\n// destructive insert/delete/reorder operations\n\nFloatComplexMatrix&\nFloatComplexMatrix::insert (const FloatMatrix& a,\n                            octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_nr >0 && a_nc > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = 0; j < a_nc; j++)\n        for (octave_idx_type i = 0; i < a_nr; i++)\n          xelem (r+i, c+j) = a.elem (i, j);\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::insert (const FloatRowVector& a,\n                            octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r, c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::insert (const FloatColumnVector& a,\n                            octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::insert (const FloatDiagMatrix& a,\n                            octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);\n\n  octave_idx_type a_len = a.length ();\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c+i) = a.elem (i, i);\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::insert (const FloatComplexMatrix& a,\n                            octave_idx_type r, octave_idx_type c)\n{\n  Array<FloatComplex>::insert (a, r, c);\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::insert (const FloatComplexRowVector& a,\n                            octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n  if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (r, c+i) = a.elem (i);\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::insert (const FloatComplexColumnVector& a,\n                            octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::insert (const FloatComplexDiagMatrix& a,\n                            octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);\n\n  octave_idx_type a_len = a.length ();\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c+i) = a.elem (i, i);\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::fill (float val)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::fill (const FloatComplex& val)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::fill (float val, octave_idx_type r1, octave_idx_type c1,\n                          octave_idx_type r2, octave_idx_type c2)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0\n      || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (r2 >= r1 && c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = c1; j <= c2; j++)\n        for (octave_idx_type i = r1; i <= r2; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::fill (const FloatComplex& val,\n                          octave_idx_type r1, octave_idx_type c1,\n                          octave_idx_type r2, octave_idx_type c2)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0\n      || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (r2 >= r1 && c2 >=c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = c1; j <= c2; j++)\n        for (octave_idx_type i = r1; i <= r2; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::append (const FloatMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatComplexMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::append (const FloatRowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != 1)\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatComplexMatrix retval (nr, nc + a.numel ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::append (const FloatColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.numel ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatComplexMatrix retval (nr, nc + 1);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::append (const FloatDiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatComplexMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::append (const FloatComplexMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatComplexMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::append (const FloatComplexRowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != 1)\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatComplexMatrix retval (nr, nc + a.numel ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::append (const FloatComplexColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.numel ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatComplexMatrix retval (nr, nc + 1);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::append (const FloatComplexDiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatComplexMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::stack (const FloatMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatComplexMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::stack (const FloatRowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.numel ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatComplexMatrix retval (nr + 1, nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::stack (const FloatColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != 1)\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatComplexMatrix retval (nr + a.numel (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::stack (const FloatDiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatComplexMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::stack (const FloatComplexMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatComplexMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::stack (const FloatComplexRowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.numel ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatComplexMatrix retval (nr + 1, nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::stack (const FloatComplexColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != 1)\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatComplexMatrix retval (nr + a.numel (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::stack (const FloatComplexDiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatComplexMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatComplexMatrix\nconj (const FloatComplexMatrix& a)\n{\n  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float>> (a);\n}\n\n// resize is the destructive equivalent for this one\n\nFloatComplexMatrix\nFloatComplexMatrix::extract (octave_idx_type r1, octave_idx_type c1,\n                             octave_idx_type r2, octave_idx_type c2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  return index (octave::idx_vector (r1, r2+1), octave::idx_vector (c1, c2+1));\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::extract_n (octave_idx_type r1, octave_idx_type c1,\n                               octave_idx_type nr, octave_idx_type nc) const\n{\n  return index (octave::idx_vector (r1, r1 + nr), octave::idx_vector (c1, c1 + nc));\n}\n\n// extract row or column i.\n\nFloatComplexRowVector\nFloatComplexMatrix::row (octave_idx_type i) const\n{\n  return index (octave::idx_vector (i), octave::idx_vector::colon);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::column (octave_idx_type i) const\n{\n  return index (octave::idx_vector::colon, octave::idx_vector (i));\n}\n\n// Local function to calculate the 1-norm.\nstatic\nfloat\nnorm1 (const FloatComplexMatrix& a)\n{\n  float anorm = 0.0;\n  FloatRowVector colsum = a.abs ().sum ().row (0);\n\n  for (octave_idx_type i = 0; i < colsum.numel (); i++)\n    {\n      float sum = colsum.xelem (i);\n      if (octave::math::isinf (sum) || octave::math::isnan (sum))\n        {\n          anorm = sum;  // Pass Inf or NaN to output\n          break;\n        }\n      else\n        anorm = std::max (anorm, sum);\n    }\n\n  return anorm;\n}\n\n// Local function to check if matrix is singular based on rcond.\nstatic inline\nbool\nis_singular (const float rcond)\n{\n  return (std::abs (rcond) <= std::numeric_limits<float>::epsilon ());\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::inverse () const\n{\n  octave_idx_type info;\n  float rcon;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, false, false);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::inverse (octave_idx_type& info) const\n{\n  float rcon;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, false, false);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::inverse (octave_idx_type& info, float& rcon, bool force,\n                             bool calc_cond) const\n{\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, force, calc_cond);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::inverse (MatrixType& mattype) const\n{\n  octave_idx_type info;\n  float rcon;\n  return inverse (mattype, info, rcon, false, false);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const\n{\n  float rcon;\n  return inverse (mattype, info, rcon, false, false);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::tinverse (MatrixType& mattype, octave_idx_type& info,\n                              float& rcon, bool force, bool calc_cond) const\n{\n  FloatComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc || nr == 0 || nc == 0)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  int typ = mattype.type ();\n  char uplo = (typ == MatrixType::Lower ? 'L' : 'U');\n  char udiag = 'N';\n  retval = *this;\n  FloatComplex *tmp_data = retval.rwdata ();\n\n  F77_INT tmp_info = 0;\n\n  F77_XFCN (ctrtri, CTRTRI, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                             F77_CONST_CHAR_ARG2 (&udiag, 1),\n                             nr, F77_CMPLX_ARG (tmp_data), nr, tmp_info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  info = tmp_info;\n\n  // Throw away extra info LAPACK gives so as to not change output.\n  rcon = 0.0;\n  if (info != 0)\n    info = -1;\n  else if (calc_cond)\n    {\n      F77_INT ztrcon_info = 0;\n      char job = '1';\n\n      OCTAVE_LOCAL_BUFFER (FloatComplex, cwork, 2*nr);\n      OCTAVE_LOCAL_BUFFER (float, rwork, nr);\n\n      F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                 F77_CONST_CHAR_ARG2 (&udiag, 1),\n                                 nr, F77_CMPLX_ARG (tmp_data), nr, rcon,\n                                 F77_CMPLX_ARG (cwork), rwork, ztrcon_info\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (ztrcon_info != 0)\n        info = -1;\n    }\n\n  if (info == -1 && ! force)\n    retval = *this; // Restore matrix contents.\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::finverse (MatrixType& mattype, octave_idx_type& info,\n                              float& rcon, bool force, bool calc_cond) const\n{\n  FloatComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  Array<F77_INT> ipvt (dim_vector (nr, 1));\n  F77_INT *pipvt = ipvt.rwdata ();\n\n  retval = *this;\n  FloatComplex *tmp_data = retval.rwdata ();\n\n  Array<FloatComplex> z (dim_vector (1, 1));\n  F77_INT lwork = -1;\n\n  // Query the optimum work array size.\n\n  F77_INT tmp_info = 0;\n\n  F77_XFCN (cgetri, CGETRI, (nc, F77_CMPLX_ARG (tmp_data), nr, pipvt,\n                             F77_CMPLX_ARG (z.rwdata ()), lwork,\n                             tmp_info));\n\n  lwork = static_cast<F77_INT> (std::real (z(0)));\n  lwork = (lwork < 2 * nc ? 2 * nc : lwork);\n  z.resize (dim_vector (lwork, 1));\n  FloatComplex *pz = z.rwdata ();\n\n  info = 0;\n  tmp_info = 0;\n\n  // Calculate norm of the matrix (always, see bug #45577) for later use.\n  float anorm = norm1 (retval);\n\n  // Work around bug #45577, LAPACK crashes Octave if norm is NaN\n  // and bug #46330, segfault with matrices containing Inf & NaN\n  if (octave::math::isnan (anorm) || octave::math::isinf (anorm))\n    info = -1;\n  else\n    {\n      F77_XFCN (cgetrf, CGETRF, (nc, nc, F77_CMPLX_ARG (tmp_data), nr, pipvt,\n                                 tmp_info));\n\n      info = tmp_info;\n    }\n\n  // Throw away extra info LAPACK gives so as to not change output.\n  rcon = 0.0;\n  if (info != 0)\n    info = -1;\n  else if (calc_cond)\n    {\n      if (octave::math::isnan (anorm))\n        rcon = octave::numeric_limits<float>::NaN ();\n      else\n        {\n          F77_INT cgecon_info = 0;\n\n          // Now calculate the condition number for non-singular matrix.\n          char job = '1';\n          Array<float> rz (dim_vector (2 * nc, 1));\n          float *prz = rz.rwdata ();\n          F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     nc, F77_CMPLX_ARG (tmp_data), nr, anorm,\n                                     rcon, F77_CMPLX_ARG (pz), prz, cgecon_info\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (cgecon_info != 0)\n            info = -1;\n        }\n    }\n\n  if ((info == -1 && ! force)\n      || octave::math::isnan (anorm) || octave::math::isinf (anorm))\n    retval = *this;  // Restore contents.\n  else\n    {\n      F77_INT zgetri_info = 0;\n\n      F77_XFCN (cgetri, CGETRI, (nc, F77_CMPLX_ARG (tmp_data), nr, pipvt,\n                                 F77_CMPLX_ARG (pz), lwork, zgetri_info));\n\n      if (zgetri_info != 0)\n        info = -1;\n    }\n\n  if (info != 0)\n    mattype.mark_as_rectangular ();\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info,\n                             float& rcon, bool force, bool calc_cond) const\n{\n  int typ = mattype.type (false);\n  FloatComplexMatrix ret;\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal)  // a scalar is classified as Diagonal.\n    {\n      FloatComplex scalar = this->elem (0);\n      float real = std::real (scalar);\n      float imag = std::imag (scalar);\n\n      if (real == 0 && imag == 0)\n        ret = FloatComplexMatrix (1, 1,\n                                  FloatComplex (octave::numeric_limits<float>::Inf (), 0.0));\n      else\n        ret = FloatComplex (1, 0) / (*this);\n\n      if (calc_cond)\n        {\n          if (octave::math::isfinite (real) && octave::math::isfinite (imag)\n              && (real != 0 || imag != 0))\n            rcon = 1.0f;\n          else if (octave::math::isinf (real) || octave::math::isinf (imag)\n                   || (real == 0 && imag == 0))\n            rcon = 0.0f;\n          else\n            rcon = octave::numeric_limits<float>::NaN ();\n        }\n    }\n  else if (typ == MatrixType::Upper || typ == MatrixType::Lower)\n    ret = tinverse (mattype, info, rcon, force, calc_cond);\n  else\n    {\n      if (mattype.ishermitian ())\n        {\n          octave::math::chol<FloatComplexMatrix> chol (*this, info, true, calc_cond);\n          if (info == 0)\n            {\n              if (calc_cond)\n                rcon = chol.rcond ();\n              else\n                rcon = 1.0;\n              ret = chol.inverse ();\n            }\n          else\n            mattype.mark_as_unsymmetric ();\n        }\n\n      if (! mattype.ishermitian ())\n        ret = finverse (mattype, info, rcon, force, calc_cond);\n\n      if ((calc_cond || mattype.ishermitian ()) && rcon == 0.0)\n        {\n          ret = FloatComplexMatrix (rows (), columns (),\n                                    FloatComplex (octave::numeric_limits<float>::Inf (), 0.0));\n        }\n    }\n\n  return ret;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::pseudo_inverse (float tol) const\n{\n  FloatComplexMatrix retval;\n\n  octave::math::svd<FloatComplexMatrix> result\n    (*this, octave::math::svd<FloatComplexMatrix>::Type::economy);\n\n  FloatDiagMatrix S = result.singular_values ();\n  FloatComplexMatrix U = result.left_singular_matrix ();\n  FloatComplexMatrix V = result.right_singular_matrix ();\n\n  FloatColumnVector sigma = S.extract_diag ();\n\n  octave_idx_type r = sigma.numel () - 1;\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (tol <= 0.0)\n    {\n      tol = std::max (nr, nc) * sigma.elem (0)\n            * std::numeric_limits<float>::epsilon ();\n\n      if (tol == 0)\n        tol = std::numeric_limits<float>::min ();\n    }\n\n  while (r >= 0 && sigma.elem (r) < tol)\n    r--;\n\n  if (r < 0)\n    retval = FloatComplexMatrix (nc, nr, 0.0);\n  else\n    {\n      FloatComplexMatrix Ur = U.extract (0, 0, nr-1, r);\n      FloatDiagMatrix D = FloatDiagMatrix (sigma.extract (0, r)).inverse ();\n      FloatComplexMatrix Vr = V.extract (0, 0, nc-1, r);\n      retval = Vr * D * Ur.hermitian ();\n    }\n\n  return retval;\n}\n\n#if defined (HAVE_FFTW)\n\nFloatComplexMatrix\nFloatComplexMatrix::fourier () const\n{\n  std::size_t nr = rows ();\n  std::size_t nc = cols ();\n\n  FloatComplexMatrix retval (nr, nc);\n\n  std::size_t npts, nsamples;\n\n  if (nr == 1 || nc == 1)\n    {\n      npts = (nr > nc ? nr : nc);\n      nsamples = 1;\n    }\n  else\n    {\n      npts = nr;\n      nsamples = nc;\n    }\n\n  const FloatComplex *in (data ());\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::fft (in, out, npts, nsamples);\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::ifourier () const\n{\n  std::size_t nr = rows ();\n  std::size_t nc = cols ();\n\n  FloatComplexMatrix retval (nr, nc);\n\n  std::size_t npts, nsamples;\n\n  if (nr == 1 || nc == 1)\n    {\n      npts = (nr > nc ? nr : nc);\n      nsamples = 1;\n    }\n  else\n    {\n      npts = nr;\n      nsamples = nc;\n    }\n\n  const FloatComplex *in (data ());\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::ifft (in, out, npts, nsamples);\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::fourier2d () const\n{\n  dim_vector dv (rows (), cols ());\n\n  FloatComplexMatrix retval (rows (), cols ());\n  const FloatComplex *in (data ());\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::fftNd (in, out, 2, dv);\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::ifourier2d () const\n{\n  dim_vector dv (rows (), cols ());\n\n  FloatComplexMatrix retval (rows (), cols ());\n  const FloatComplex *in (data ());\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::ifftNd (in, out, 2, dv);\n\n  return retval;\n}\n\n#else\n\nFloatComplexMatrix\nFloatComplexMatrix::fourier () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexMatrix ();\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::ifourier () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexMatrix ();\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::fourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexMatrix ();\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::ifourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexMatrix ();\n}\n\n#endif\n\nFloatComplexDET\nFloatComplexMatrix::determinant () const\n{\n  octave_idx_type info;\n  float rcon;\n  return determinant (info, rcon, 0);\n}\n\nFloatComplexDET\nFloatComplexMatrix::determinant (octave_idx_type& info) const\n{\n  float rcon;\n  return determinant (info, rcon, 0);\n}\n\nFloatComplexDET\nFloatComplexMatrix::determinant (octave_idx_type& info, float& rcon,\n                                 bool calc_cond) const\n{\n  MatrixType mattype (*this);\n  return determinant (mattype, info, rcon, calc_cond);\n}\n\nFloatComplexDET\nFloatComplexMatrix::determinant (MatrixType& mattype,\n                                 octave_idx_type& info, float& rcon,\n                                 bool calc_cond) const\n{\n  FloatComplexDET retval (1.0);\n\n  info = 0;\n  rcon = 0.0;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"matrix must be square\");\n\n  int typ = mattype.type ();\n\n  // Even though the matrix is marked as singular (Rectangular), we may\n  // still get a useful number from the LU factorization, because it always\n  // completes.\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n  else if (typ == MatrixType::Rectangular)\n    typ = MatrixType::Full;\n\n  if (typ == MatrixType::Lower || typ == MatrixType::Upper)\n    {\n      for (F77_INT i = 0; i < nc; i++)\n        retval *= elem (i, i);\n    }\n  else if (typ == MatrixType::Hermitian)\n    {\n      FloatComplexMatrix atmp = *this;\n      FloatComplex *tmp_data = atmp.rwdata ();\n\n      float anorm;\n      if (calc_cond)\n        anorm = norm1 (*this);\n\n      F77_INT tmp_info = 0;\n\n      char job = 'L';\n      F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                 F77_CMPLX_ARG (tmp_data), nr, tmp_info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      info = tmp_info;\n\n      if (info != 0)\n        {\n          rcon = 0.0;\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n        }\n      else\n        {\n          if (calc_cond)\n            {\n              Array<FloatComplex> z (dim_vector (2 * nc, 1));\n              FloatComplex *pz = z.rwdata ();\n              Array<float> rz (dim_vector (nc, 1));\n              float *prz = rz.rwdata ();\n\n              F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                         nr, F77_CMPLX_ARG (tmp_data), nr, anorm,\n                                         rcon, F77_CMPLX_ARG (pz), prz, tmp_info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n\n              if (info != 0)\n                rcon = 0.0;\n            }\n\n          for (F77_INT i = 0; i < nc; i++)\n            retval *= atmp(i, i);\n\n          retval = retval.square ();\n        }\n    }\n  else if (typ != MatrixType::Full)\n    (*current_liboctave_error_handler) (\"det: invalid dense matrix type\");\n\n  if (typ == MatrixType::Full)\n    {\n      Array<F77_INT> ipvt (dim_vector (nr, 1));\n      F77_INT *pipvt = ipvt.rwdata ();\n\n      FloatComplexMatrix atmp = *this;\n      FloatComplex *tmp_data = atmp.rwdata ();\n\n      info = 0;\n\n      // Calculate norm of the matrix (always, see bug #45577) for later use.\n      float anorm = norm1 (*this);\n\n      F77_INT tmp_info = 0;\n\n      // Work around bug #45577, LAPACK crashes Octave if norm is NaN\n      if (octave::math::isnan (anorm))\n        info = -1;\n      else\n        {\n          F77_XFCN (cgetrf, CGETRF, (nr, nr, F77_CMPLX_ARG (tmp_data), nr, pipvt,\n                                     tmp_info));\n\n          info = tmp_info;\n        }\n\n      // Throw away extra info LAPACK gives so as to not change output.\n      rcon = 0.0;\n      if (info != 0)\n        {\n          info = -1;\n          retval = FloatComplexDET ();\n        }\n      else\n        {\n          if (calc_cond)\n            {\n              // Now calc the condition number for non-singular matrix.\n              char job = '1';\n              Array<FloatComplex> z (dim_vector (2 * nc, 1));\n              FloatComplex *pz = z.rwdata ();\n              Array<float> rz (dim_vector (2 * nc, 1));\n              float *prz = rz.rwdata ();\n\n              F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                         nc, F77_CMPLX_ARG (tmp_data), nr, anorm,\n                                         rcon, F77_CMPLX_ARG (pz), prz, tmp_info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n            }\n\n          if (info != 0)\n            {\n              info = -1;\n              retval = FloatComplexDET ();\n            }\n          else\n            {\n              for (F77_INT i = 0; i < nc; i++)\n                {\n                  FloatComplex c = atmp(i, i);\n                  retval *= (ipvt(i) != (i+1)) ? -c : c;\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\nfloat\nFloatComplexMatrix::rcond () const\n{\n  MatrixType mattype (*this);\n  return rcond (mattype);\n}\n\nfloat\nFloatComplexMatrix::rcond (MatrixType& mattype) const\n{\n  float rcon = octave::numeric_limits<float>::NaN ();\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"matrix must be square\");\n\n  if (nr == 0 || nc == 0)\n    rcon = octave::numeric_limits<float>::Inf ();\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ == MatrixType::Unknown)\n        typ = mattype.type (*this);\n\n      // Only calculate the condition number for LU/Cholesky\n      if (typ == MatrixType::Upper)\n        {\n          const FloatComplex *tmp_data = data ();\n          F77_INT info = 0;\n          char norm = '1';\n          char uplo = 'U';\n          char dia = 'N';\n\n          Array<FloatComplex> z (dim_vector (2 * nc, 1));\n          FloatComplex *pz = z.rwdata ();\n          Array<float> rz (dim_vector (nc, 1));\n          float *prz = rz.rwdata ();\n\n          F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, F77_CONST_CMPLX_ARG (tmp_data), nr, rcon,\n                                     F77_CMPLX_ARG (pz), prz, info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (info != 0)\n            rcon = 0;\n        }\n      else if (typ == MatrixType::Permuted_Upper)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n      else if (typ == MatrixType::Lower)\n        {\n          const FloatComplex *tmp_data = data ();\n          F77_INT info = 0;\n          char norm = '1';\n          char uplo = 'L';\n          char dia = 'N';\n\n          Array<FloatComplex> z (dim_vector (2 * nc, 1));\n          FloatComplex *pz = z.rwdata ();\n          Array<float> rz (dim_vector (nc, 1));\n          float *prz = rz.rwdata ();\n\n          F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, F77_CONST_CMPLX_ARG (tmp_data), nr, rcon,\n                                     F77_CMPLX_ARG (pz), prz, info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (info != 0)\n            rcon = 0.0;\n        }\n      else if (typ == MatrixType::Permuted_Lower)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n      else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n        {\n          float anorm = -1.0;\n\n          if (typ == MatrixType::Hermitian)\n            {\n              F77_INT info = 0;\n              char job = 'L';\n\n              FloatComplexMatrix atmp = *this;\n              FloatComplex *tmp_data = atmp.rwdata ();\n\n              anorm = norm1 (atmp);\n\n              F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                         F77_CMPLX_ARG (tmp_data), nr, info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              if (info != 0)\n                {\n                  rcon = 0.0;\n\n                  mattype.mark_as_unsymmetric ();\n                  typ = MatrixType::Full;\n                }\n              else\n                {\n                  Array<FloatComplex> z (dim_vector (2 * nc, 1));\n                  FloatComplex *pz = z.rwdata ();\n                  Array<float> rz (dim_vector (nc, 1));\n                  float *prz = rz.rwdata ();\n\n                  F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, F77_CMPLX_ARG (tmp_data), nr, anorm,\n                                             rcon, F77_CMPLX_ARG (pz), prz, info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  if (info != 0)\n                    rcon = 0.0;\n                }\n            }\n\n          if (typ == MatrixType::Full)\n            {\n              F77_INT info = 0;\n\n              FloatComplexMatrix atmp = *this;\n              FloatComplex *tmp_data = atmp.rwdata ();\n\n              Array<F77_INT> ipvt (dim_vector (nr, 1));\n              F77_INT *pipvt = ipvt.rwdata ();\n\n              if (anorm < 0.0)\n                anorm = norm1 (atmp);\n\n              Array<FloatComplex> z (dim_vector (2 * nc, 1));\n              FloatComplex *pz = z.rwdata ();\n              Array<float> rz (dim_vector (2 * nc, 1));\n              float *prz = rz.rwdata ();\n\n              // Work around bug #45577, LAPACK crashes Octave if norm is NaN\n              if (octave::math::isnan (anorm))\n                info = -1;\n              else\n                F77_XFCN (cgetrf, CGETRF, (nr, nr, F77_CMPLX_ARG (tmp_data),\n                                           nr, pipvt, info));\n\n              if (info != 0)\n                {\n                  rcon = 0.0;\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                {\n                  char job = '1';\n                  F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nc, F77_CMPLX_ARG (tmp_data), nr, anorm,\n                                             rcon, F77_CMPLX_ARG (pz), prz, info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  if (info != 0)\n                    rcon = 0.0;\n                }\n            }\n        }\n      else\n        rcon = 0.0;\n    }\n\n  return rcon;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::utsolve (MatrixType& mattype, const FloatComplexMatrix& b,\n                             octave_idx_type& info, float& rcon,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond, blas_trans_type transt) const\n{\n  FloatComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    retval = FloatComplexMatrix (nc, b_nc, FloatComplex (0.0, 0.0));\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ == MatrixType::Permuted_Upper || typ == MatrixType::Upper)\n        {\n          rcon = 1.0;\n          info = 0;\n\n          if (typ == MatrixType::Permuted_Upper)\n            (*current_liboctave_error_handler)\n              (\"permuted triangular matrix not implemented\");\n          else\n            {\n              const FloatComplex *tmp_data = data ();\n\n              retval = b;\n              FloatComplex *result = retval.rwdata ();\n\n              char uplo = 'U';\n              char trans = get_blas_char (transt);\n              char dia = 'N';\n\n              F77_INT tmp_info = 0;\n\n              F77_XFCN (ctrtrs, CTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                         F77_CONST_CHAR_ARG2 (&trans, 1),\n                                         F77_CONST_CHAR_ARG2 (&dia, 1),\n                                         nr, b_nc, F77_CONST_CMPLX_ARG (tmp_data), nr,\n                                         F77_CMPLX_ARG (result), nr, tmp_info\n                                         F77_CHAR_ARG_LEN (1)\n                                         F77_CHAR_ARG_LEN (1)\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n\n              if (calc_cond)\n                {\n                  char norm = '1';\n                  uplo = 'U';\n                  dia = 'N';\n\n                  Array<FloatComplex> z (dim_vector (2 * nc, 1));\n                  FloatComplex *pz = z.rwdata ();\n                  Array<float> rz (dim_vector (nc, 1));\n                  float *prz = rz.rwdata ();\n\n                  F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                             F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                             F77_CONST_CHAR_ARG2 (&dia, 1),\n                                             nr, F77_CONST_CMPLX_ARG (tmp_data), nr, rcon,\n                                             F77_CMPLX_ARG (pz), prz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)\n                                             F77_CHAR_ARG_LEN (1)\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      info = -2;\n\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n            }\n        }\n      else\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::ltsolve (MatrixType& mattype, const FloatComplexMatrix& b,\n                             octave_idx_type& info, float& rcon,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond, blas_trans_type transt) const\n{\n  FloatComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    retval = FloatComplexMatrix (nc, b_nc, FloatComplex (0.0, 0.0));\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ == MatrixType::Permuted_Lower || typ == MatrixType::Lower)\n        {\n          rcon = 1.0;\n          info = 0;\n\n          if (typ == MatrixType::Permuted_Lower)\n            (*current_liboctave_error_handler)\n              (\"permuted triangular matrix not implemented\");\n          else\n            {\n              const FloatComplex *tmp_data = data ();\n\n              retval = b;\n              FloatComplex *result = retval.rwdata ();\n\n              char uplo = 'L';\n              char trans = get_blas_char (transt);\n              char dia = 'N';\n\n              F77_INT tmp_info = 0;\n\n              F77_XFCN (ctrtrs, CTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                         F77_CONST_CHAR_ARG2 (&trans, 1),\n                                         F77_CONST_CHAR_ARG2 (&dia, 1),\n                                         nr, b_nc, F77_CONST_CMPLX_ARG (tmp_data), nr,\n                                         F77_CMPLX_ARG (result), nr, tmp_info\n                                         F77_CHAR_ARG_LEN (1)\n                                         F77_CHAR_ARG_LEN (1)\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n\n              if (calc_cond)\n                {\n                  char norm = '1';\n                  uplo = 'L';\n                  dia = 'N';\n\n                  Array<FloatComplex> z (dim_vector (2 * nc, 1));\n                  FloatComplex *pz = z.rwdata ();\n                  Array<float> rz (dim_vector (nc, 1));\n                  float *prz = rz.rwdata ();\n\n                  F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                             F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                             F77_CONST_CHAR_ARG2 (&dia, 1),\n                                             nr, F77_CONST_CMPLX_ARG (tmp_data), nr, rcon,\n                                             F77_CMPLX_ARG (pz), prz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)\n                                             F77_CHAR_ARG_LEN (1)\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      info = -2;\n\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n            }\n        }\n      else\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::fsolve (MatrixType& mattype, const FloatComplexMatrix& b,\n                            octave_idx_type& info, float& rcon,\n                            solve_singularity_handler sing_handler,\n                            bool calc_cond) const\n{\n  FloatComplexMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != nc || nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b_nc == 0)\n    retval = FloatComplexMatrix (nc, b_nc, FloatComplex (0.0, 0.0));\n  else\n    {\n      int typ = mattype.type ();\n\n      // Calculate the norm of the matrix for later use when determining rcon.\n      float anorm = -1.0;\n\n      if (typ == MatrixType::Hermitian)\n        {\n          info = 0;\n          char job = 'L';\n\n          FloatComplexMatrix atmp = *this;\n          FloatComplex *tmp_data = atmp.rwdata ();\n\n          // The norm of the matrix for later use when determining rcon.\n          if (calc_cond)\n            anorm = norm1 (atmp);\n\n          F77_INT tmp_info = 0;\n\n          F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                     F77_CMPLX_ARG (tmp_data), nr, tmp_info\n                                     F77_CHAR_ARG_LEN (1)));\n\n          info = tmp_info;\n\n          // Throw away extra info LAPACK gives so as to not change output.\n          rcon = 0.0;\n          if (info != 0)\n            {\n              info = -2;\n\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<FloatComplex> z (dim_vector (2 * nc, 1));\n                  FloatComplex *pz = z.rwdata ();\n                  Array<float> rz (dim_vector (nc, 1));\n                  float *prz = rz.rwdata ();\n\n                  F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, F77_CMPLX_ARG (tmp_data), nr, anorm,\n                                             rcon, F77_CMPLX_ARG (pz), prz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      info = -2;\n\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n\n              if (info == 0)\n                {\n                  retval = b;\n                  FloatComplex *result = retval.rwdata ();\n\n                  F77_XFCN (cpotrs, CPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, b_nc, F77_CMPLX_ARG (tmp_data), nr,\n                                             F77_CMPLX_ARG (result), b_nr, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n                }\n              else\n                {\n                  mattype.mark_as_unsymmetric ();\n                  typ = MatrixType::Full;\n                }\n            }\n        }\n\n      if (typ == MatrixType::Full)\n        {\n          info = 0;\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          FloatComplexMatrix atmp = *this;\n          FloatComplex *tmp_data = atmp.rwdata ();\n\n          Array<FloatComplex> z (dim_vector (2 * nc, 1));\n          FloatComplex *pz = z.rwdata ();\n          Array<float> rz (dim_vector (2 * nc, 1));\n          float *prz = rz.rwdata ();\n\n          // Calculate the norm of the matrix, for later use.\n          if (calc_cond && anorm < 0.0)\n            anorm = norm1 (atmp);\n\n          F77_INT tmp_info = 0;\n\n          // Work around bug #45577, LAPACK crashes Octave if norm is NaN\n          // and bug #46330, segfault with matrices containing Inf & NaN\n          if (octave::math::isnan (anorm) || octave::math::isinf (anorm))\n            info = -2;\n          else\n            {\n              F77_XFCN (cgetrf, CGETRF, (nr, nr, F77_CMPLX_ARG (tmp_data),\n                                         nr, pipvt, tmp_info));\n\n              info = tmp_info;\n            }\n\n          // Throw away extra info LAPACK gives so as to not change output.\n          rcon = 0.0;\n          if (info != 0)\n            {\n              info = -2;\n\n              if (sing_handler)\n                sing_handler (rcon);\n              else\n                octave::warn_singular_matrix ();\n\n              mattype.mark_as_rectangular ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  // Calculate the condition number for non-singular matrix.\n                  char job = '1';\n                  F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nc, F77_CMPLX_ARG (tmp_data), nr, anorm,\n                                             rcon, F77_CMPLX_ARG (pz), prz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n\n              if (info == 0)\n                {\n                  retval = b;\n                  FloatComplex *result = retval.rwdata ();\n\n                  char job = 'N';\n                  F77_XFCN (cgetrs, CGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, b_nc, F77_CMPLX_ARG (tmp_data), nr,\n                                             pipvt, F77_CMPLX_ARG (result), b_nr, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n                }\n              else\n                mattype.mark_as_rectangular ();\n            }\n        }\n\n      if (octave::math::isinf (anorm))\n        {\n          retval = FloatComplexMatrix (b_nr, b_nc,\n                                       FloatComplex (0, 0));\n          mattype.mark_as_full ();\n        }\n    }\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatMatrix& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatMatrix& b,\n                           octave_idx_type& info) const\n{\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatMatrix& b,\n                           octave_idx_type& info, float& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatMatrix& b,\n                           octave_idx_type& info, float& rcon,\n                           solve_singularity_handler sing_handler,\n                           bool singular_fallback, blas_trans_type transt) const\n{\n  FloatComplexMatrix tmp (b);\n  return solve (mattype, tmp, info, rcon, sing_handler, singular_fallback,\n                transt);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (MatrixType& mattype,\n                           const FloatComplexMatrix& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatComplexMatrix& b,\n                           octave_idx_type& info) const\n{\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatComplexMatrix& b,\n                           octave_idx_type& info, float& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatComplexMatrix& b,\n                           octave_idx_type& info, float& rcon,\n                           solve_singularity_handler sing_handler,\n                           bool singular_fallback,\n                           blas_trans_type transt) const\n{\n  FloatComplexMatrix retval;\n  int typ = mattype.type ();\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  // Only calculate the condition number for LU/Cholesky\n  if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, info, rcon, sing_handler, true, transt);\n  else if (typ == MatrixType::Lower\n           || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, info, rcon, sing_handler, true, transt);\n  else if (transt == blas_trans)\n    return transpose ().solve (mattype, b, info, rcon, sing_handler,\n                               singular_fallback);\n  else if (transt == blas_conj_trans)\n    retval = hermitian ().solve (mattype, b, info, rcon, sing_handler,\n                                 singular_fallback);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, info, rcon, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  // Rectangular or one of the above solvers flags a singular matrix\n  if (singular_fallback && mattype.type () == MatrixType::Rectangular)\n    {\n      octave_idx_type rank;\n      retval = lssolve (b, info, rank, rcon);\n    }\n\n  return retval;\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (MatrixType& mattype,\n                           const FloatColumnVector& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (mattype, FloatComplexColumnVector (b), info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatColumnVector& b,\n                           octave_idx_type& info) const\n{\n  float rcon;\n  return solve (mattype, FloatComplexColumnVector (b), info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatColumnVector& b,\n                           octave_idx_type& info, float& rcon) const\n{\n  return solve (mattype, FloatComplexColumnVector (b), info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (MatrixType& mattype, const FloatColumnVector& b,\n                           octave_idx_type& info, float& rcon,\n                           solve_singularity_handler sing_handler,\n                           blas_trans_type transt) const\n{\n  return solve (mattype, FloatComplexColumnVector (b), info, rcon,\n                sing_handler, transt);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (MatrixType& mattype,\n                           const FloatComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (MatrixType& mattype,\n                           const FloatComplexColumnVector& b,\n                           octave_idx_type& info) const\n{\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (MatrixType& mattype,\n                           const FloatComplexColumnVector& b,\n                           octave_idx_type& info, float& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (MatrixType& mattype,\n                           const FloatComplexColumnVector& b,\n                           octave_idx_type& info, float& rcon,\n                           solve_singularity_handler sing_handler,\n                           blas_trans_type transt) const\n{\n\n  FloatComplexMatrix tmp (b);\n  tmp = solve (mattype, tmp, info, rcon, sing_handler, true, transt);\n  return tmp.column (static_cast<octave_idx_type> (0));\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (const FloatMatrix& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (const FloatMatrix& b, octave_idx_type& info) const\n{\n  float rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (const FloatMatrix& b, octave_idx_type& info,\n                           float& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (const FloatMatrix& b, octave_idx_type& info,\n                           float& rcon,\n                           solve_singularity_handler sing_handler,\n                           blas_trans_type transt) const\n{\n  FloatComplexMatrix tmp (b);\n  return solve (tmp, info, rcon, sing_handler, transt);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (const FloatComplexMatrix& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (const FloatComplexMatrix& b,\n                           octave_idx_type& info) const\n{\n  float rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info,\n                           float& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info,\n                           float& rcon,\n                           solve_singularity_handler sing_handler,\n                           blas_trans_type transt) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, info, rcon, sing_handler, true, transt);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (const FloatColumnVector& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (FloatComplexColumnVector (b), info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (const FloatColumnVector& b,\n                           octave_idx_type& info) const\n{\n  float rcon;\n  return solve (FloatComplexColumnVector (b), info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (const FloatColumnVector& b, octave_idx_type& info,\n                           float& rcon) const\n{\n  return solve (FloatComplexColumnVector (b), info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (const FloatColumnVector& b, octave_idx_type& info,\n                           float& rcon,\n                           solve_singularity_handler sing_handler,\n                           blas_trans_type transt) const\n{\n  return solve (FloatComplexColumnVector (b), info, rcon, sing_handler, transt);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (const FloatComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (const FloatComplexColumnVector& b,\n                           octave_idx_type& info) const\n{\n  float rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (const FloatComplexColumnVector& b,\n                           octave_idx_type& info,\n                           float& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::solve (const FloatComplexColumnVector& b,\n                           octave_idx_type& info,\n                           float& rcon,\n                           solve_singularity_handler sing_handler,\n                           blas_trans_type transt) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, info, rcon, sing_handler, transt);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::lssolve (const FloatMatrix& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (FloatComplexMatrix (b), info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (FloatComplexMatrix (b), info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info,\n                             octave_idx_type& rank) const\n{\n  float rcon;\n  return lssolve (FloatComplexMatrix (b), info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info,\n                             octave_idx_type& rank, float& rcon) const\n{\n  return lssolve (FloatComplexMatrix (b), info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::lssolve (const FloatComplexMatrix& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::lssolve (const FloatComplexMatrix& b,\n                             octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info,\n                             octave_idx_type& rank) const\n{\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info,\n                             octave_idx_type& rank, float& rcon) const\n{\n  FloatComplexMatrix retval;\n\n  F77_INT m = octave::to_f77_int (rows ());\n  F77_INT n = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n  F77_INT nrhs = b_nc;  // alias for code readability\n\n  if (m != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (m == 0 || n == 0 || b_nc == 0)\n    retval = FloatComplexMatrix (n, b_nc, FloatComplex (0.0, 0.0));\n  else\n    {\n      F77_INT minmn = (m < n ? m : n);\n      F77_INT maxmn = (m > n ? m : n);\n      rcon = -1.0;\n\n      if (m != n)\n        {\n          retval = FloatComplexMatrix (maxmn, nrhs);\n\n          for (F77_INT j = 0; j < nrhs; j++)\n            for (F77_INT i = 0; i < m; i++)\n              retval.elem (i, j) = b.elem (i, j);\n        }\n      else\n        retval = b;\n\n      FloatComplexMatrix atmp = *this;\n      FloatComplex *tmp_data = atmp.rwdata ();\n\n      FloatComplex *pretval = retval.rwdata ();\n      Array<float> s (dim_vector (minmn, 1));\n      float *ps = s.rwdata ();\n\n      // Ask ZGELSD what the dimension of WORK should be.\n      F77_INT lwork = -1;\n\n      Array<FloatComplex> work (dim_vector (1, 1));\n\n      F77_INT smlsiz;\n      F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 (\"CGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   0, 0, 0, 0, smlsiz\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      F77_INT mnthr;\n      F77_FUNC (xilaenv, XILAENV) (6, F77_CONST_CHAR_ARG2 (\"CGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   m, n, nrhs, -1, mnthr\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      // We compute the size of rwork and iwork because ZGELSD in\n      // older versions of LAPACK does not return them on a query\n      // call.\n      float dminmn = static_cast<float> (minmn);\n      float dsmlsizp1 = static_cast<float> (smlsiz+1);\n      float tmp = octave::math::log2 (dminmn / dsmlsizp1);\n\n      F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;\n      if (nlvl < 0)\n        nlvl = 0;\n\n      F77_INT lrwork = minmn*(10 + 2*smlsiz + 8*nlvl)\n                       + 3*smlsiz*nrhs\n                       + std::max ((smlsiz+1)*(smlsiz+1),\n                                   n*(1+nrhs) + 2*nrhs);\n      if (lrwork < 1)\n        lrwork = 1;\n      Array<float> rwork (dim_vector (lrwork, 1));\n      float *prwork = rwork.rwdata ();\n\n      F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;\n      if (liwork < 1)\n        liwork = 1;\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n      F77_INT *piwork = iwork.rwdata ();\n\n      F77_INT tmp_info = 0;\n      F77_INT tmp_rank = 0;\n\n      F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data), m,\n                                 F77_CMPLX_ARG (pretval), maxmn,\n                                 ps, rcon, tmp_rank, F77_CMPLX_ARG (work.rwdata ()),\n                                 lwork, prwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      // The workspace query is broken in at least LAPACK 3.0.0\n      // through 3.1.1 when n >= mnthr.  The obtuse formula below\n      // should provide sufficient workspace for ZGELSD to operate\n      // efficiently.\n      if (n > m && n >= mnthr)\n        {\n          F77_INT addend = m;\n\n          if (2*m-4 > addend)\n            addend = 2*m-4;\n\n          if (nrhs > addend)\n            addend = nrhs;\n\n          if (n-3*m > addend)\n            addend = n-3*m;\n\n          const F77_INT lworkaround = 4*m + m*m + addend;\n\n          if (std::real (work(0)) < lworkaround)\n            work(0) = lworkaround;\n        }\n      else if (m >= n)\n        {\n          F77_INT lworkaround = 2*m + m*nrhs;\n\n          if (std::real (work(0)) < lworkaround)\n            work(0) = lworkaround;\n        }\n\n      lwork = static_cast<F77_INT> (std::real (work(0)));\n      work.resize (dim_vector (lwork, 1));\n\n      float anorm = norm1 (*this);\n\n      if (octave::math::isinf (anorm))\n        {\n          rcon = 0.0;\n          retval = FloatComplexMatrix (n, b_nc, 0.0);\n        }\n      else if (octave::math::isnan (anorm))\n        {\n          rcon = octave::numeric_limits<float>::NaN ();\n          retval = FloatComplexMatrix (n, b_nc,\n                                       octave::numeric_limits<float>::NaN ());\n        }\n      else\n        {\n          F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data),\n                                     m, F77_CMPLX_ARG (pretval),\n                                     maxmn, ps, rcon, tmp_rank,\n                                     F77_CMPLX_ARG (work.rwdata ()),\n                                     lwork, prwork, piwork, tmp_info));\n\n          info = tmp_info;\n          rank = tmp_rank;\n\n          if (s.elem (0) == 0.0)\n            rcon = 0.0;\n          else\n            rcon = s.elem (minmn - 1) / s.elem (0);\n\n          retval.resize (n, nrhs);\n        }\n    }\n\n  return retval;\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::lssolve (const FloatColumnVector& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (FloatComplexColumnVector (b), info, rank, rcon);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::lssolve (const FloatColumnVector& b,\n                             octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (FloatComplexColumnVector (b), info, rank, rcon);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info,\n                             octave_idx_type& rank) const\n{\n  float rcon;\n  return lssolve (FloatComplexColumnVector (b), info, rank, rcon);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info,\n                             octave_idx_type& rank, float& rcon) const\n{\n  return lssolve (FloatComplexColumnVector (b), info, rank, rcon);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::lssolve (const FloatComplexColumnVector& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::lssolve (const FloatComplexColumnVector& b,\n                             octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::lssolve (const FloatComplexColumnVector& b,\n                             octave_idx_type& info,\n                             octave_idx_type& rank) const\n{\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::lssolve (const FloatComplexColumnVector& b,\n                             octave_idx_type& info,\n                             octave_idx_type& rank, float& rcon) const\n{\n  FloatComplexColumnVector retval;\n\n  F77_INT nrhs = 1;\n\n  F77_INT m = octave::to_f77_int (rows ());\n  F77_INT n = octave::to_f77_int (cols ());\n\n  F77_INT b_nel = octave::to_f77_int (b.numel ());\n\n  if (m != b_nel)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (m == 0 || n == 0)\n    retval = FloatComplexColumnVector (n, FloatComplex (0.0, 0.0));\n  else\n    {\n      F77_INT minmn = (m < n ? m : n);\n      F77_INT maxmn = (m > n ? m : n);\n      rcon = -1.0;\n\n      if (m != n)\n        {\n          retval = FloatComplexColumnVector (maxmn);\n\n          for (F77_INT i = 0; i < m; i++)\n            retval.elem (i) = b.elem (i);\n        }\n      else\n        retval = b;\n\n      FloatComplexMatrix atmp = *this;\n      FloatComplex *tmp_data = atmp.rwdata ();\n\n      FloatComplex *pretval = retval.rwdata ();\n      Array<float> s (dim_vector (minmn, 1));\n      float *ps = s.rwdata ();\n\n      // Ask ZGELSD what the dimension of WORK should be.\n      F77_INT lwork = -1;\n\n      Array<FloatComplex> work (dim_vector (1, 1));\n\n      F77_INT smlsiz;\n      F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 (\"CGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   0, 0, 0, 0, smlsiz\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      // We compute the size of rwork and iwork because ZGELSD in\n      // older versions of LAPACK does not return them on a query\n      // call.\n      float dminmn = static_cast<float> (minmn);\n      float dsmlsizp1 = static_cast<float> (smlsiz+1);\n      float tmp = octave::math::log2 (dminmn / dsmlsizp1);\n\n      F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;\n      if (nlvl < 0)\n        nlvl = 0;\n\n      F77_INT lrwork = minmn*(10 + 2*smlsiz + 8*nlvl)\n                       + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1);\n      if (lrwork < 1)\n        lrwork = 1;\n      Array<float> rwork (dim_vector (lrwork, 1));\n      float *prwork = rwork.rwdata ();\n\n      F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;\n      if (liwork < 1)\n        liwork = 1;\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n      F77_INT *piwork = iwork.rwdata ();\n\n      F77_INT tmp_info = 0;\n      F77_INT tmp_rank = 0;\n\n      F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data), m,\n                                 F77_CMPLX_ARG (pretval), maxmn,\n                                 ps, rcon, tmp_rank, F77_CMPLX_ARG (work.rwdata ()),\n                                 lwork, prwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      lwork = static_cast<F77_INT> (std::real (work(0)));\n      work.resize (dim_vector (lwork, 1));\n      rwork.resize (dim_vector (static_cast<F77_INT> (rwork(0)), 1));\n      iwork.resize (dim_vector (iwork(0), 1));\n\n      F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data), m,\n                                 F77_CMPLX_ARG (pretval),\n                                 maxmn, ps, rcon, tmp_rank,\n                                 F77_CMPLX_ARG (work.rwdata ()), lwork,\n                                 prwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      if (rank < minmn)\n        {\n          if (s.elem (0) == 0.0)\n            rcon = 0.0;\n          else\n            rcon = s.elem (minmn - 1) / s.elem (0);\n\n          retval.resize (n);\n        }\n    }\n\n  return retval;\n}\n\n// column vector by row vector -> matrix operations\n\nFloatComplexMatrix\noperator * (const FloatColumnVector& v, const FloatComplexRowVector& a)\n{\n  FloatComplexColumnVector tmp (v);\n  return tmp * a;\n}\n\nFloatComplexMatrix\noperator * (const FloatComplexColumnVector& a, const FloatRowVector& b)\n{\n  FloatComplexRowVector tmp (b);\n  return a * tmp;\n}\n\nFloatComplexMatrix\noperator * (const FloatComplexColumnVector& v, const FloatComplexRowVector& a)\n{\n  FloatComplexMatrix retval;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  if (len != 0)\n    {\n      F77_INT a_len = octave::to_f77_int (a.numel ());\n\n      retval = FloatComplexMatrix (len, a_len);\n      FloatComplex *c = retval.rwdata ();\n\n      F77_XFCN (cgemm, CGEMM, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                               F77_CONST_CHAR_ARG2 (\"N\", 1),\n                               len, a_len, 1, 1.0, F77_CONST_CMPLX_ARG (v.data ()), len,\n                               F77_CONST_CMPLX_ARG (a.data ()), 1, 0.0, F77_CMPLX_ARG (c), len\n                               F77_CHAR_ARG_LEN (1)\n                               F77_CHAR_ARG_LEN (1)));\n    }\n\n  return retval;\n}\n\n// matrix by diagonal matrix -> matrix operations\n\nFloatComplexMatrix&\nFloatComplexMatrix::operator += (const FloatDiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator +=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) += a.elem (i, i);\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::operator -= (const FloatDiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator -=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) -= a.elem (i, i);\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::operator += (const FloatComplexDiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator +=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) += a.elem (i, i);\n\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::operator -= (const FloatComplexDiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator -=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) -= a.elem (i, i);\n\n  return *this;\n}\n\n// matrix by matrix -> matrix operations\n\nFloatComplexMatrix&\nFloatComplexMatrix::operator += (const FloatMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator +=\", nr, nc, a_nr, a_nc);\n\n  if (nr == 0 || nc == 0)\n    return *this;\n\n  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!\n\n  mx_inline_add2 (numel (), d, a.data ());\n  return *this;\n}\n\nFloatComplexMatrix&\nFloatComplexMatrix::operator -= (const FloatMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator -=\", nr, nc, a_nr, a_nc);\n\n  if (nr == 0 || nc == 0)\n    return *this;\n\n  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!\n\n  mx_inline_sub2 (numel (), d, a.data ());\n  return *this;\n}\n\n// other operations\n\nboolMatrix\nFloatComplexMatrix::all (int dim) const\n{\n  return FloatComplexNDArray::all (dim);\n}\n\nboolMatrix\nFloatComplexMatrix::any (int dim) const\n{\n  return FloatComplexNDArray::any (dim);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::flip (int dim) const\n{\n  return FloatComplexNDArray::flip (dim);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::cumprod (int dim, bool nanflag) const\n{\n  return FloatComplexNDArray::cumprod (dim, nanflag);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::cumsum (int dim, bool nanflag) const\n{\n  return FloatComplexNDArray::cumsum (dim, nanflag);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::prod (int dim, bool nanflag) const\n{\n  return FloatComplexNDArray::prod (dim, nanflag);\n}\n\nComplexMatrix\nFloatComplexMatrix::dprod (int dim, bool nanflag) const\n{\n  return FloatComplexNDArray::dprod (dim, nanflag);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::sum (int dim, bool nanflag) const\n{\n  return FloatComplexNDArray::sum (dim, nanflag);\n}\n\nComplexMatrix\nFloatComplexMatrix::dsum (int dim, bool nanflag) const\n{\n  return FloatComplexNDArray::dsum (dim, nanflag);\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::sumsq (int dim, bool nanflag) const\n{\n  return FloatComplexNDArray::sumsq (dim, nanflag);\n}\n\nComplexMatrix\nFloatComplexMatrix::dsumsq (int dim, bool nanflag) const\n{\n  return FloatComplexNDArray::dsumsq (dim, nanflag);\n}\n\nFloatMatrix\nFloatComplexMatrix::abs () const\n{\n  return FloatComplexNDArray::abs ();\n}\n\nFloatComplexMatrix\nFloatComplexMatrix::diag (octave_idx_type k) const\n{\n  return FloatComplexNDArray::diag (k);\n}\n\nFloatComplexDiagMatrix\nFloatComplexMatrix::diag (octave_idx_type m, octave_idx_type n) const\n{\n  FloatComplexDiagMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr == 1 || nc == 1)\n    retval = FloatComplexDiagMatrix (*this, m, n);\n  else\n    (*current_liboctave_error_handler) (\"diag: expecting vector argument\");\n\n  return retval;\n}\n\nbool\nFloatComplexMatrix::row_is_real_only (octave_idx_type i) const\n{\n  bool retval = true;\n\n  octave_idx_type nc = columns ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      if (std::imag (elem (i, j)) != 0.0)\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nbool\nFloatComplexMatrix::column_is_real_only (octave_idx_type j) const\n{\n  bool retval = true;\n\n  octave_idx_type nr = rows ();\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    {\n      if (std::imag (elem (i, j)) != 0.0)\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::row_min () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return row_min (dummy_idx);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::row_min (Array<octave_idx_type>& idx_arg) const\n{\n  FloatComplexColumnVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nr);\n      idx_arg.resize (dim_vector (nr, 1));\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          bool real_only = row_is_real_only (i);\n\n          octave_idx_type idx_j;\n\n          FloatComplex tmp_min;\n\n          float abs_min = octave::numeric_limits<float>::NaN ();\n\n          for (idx_j = 0; idx_j < nc; idx_j++)\n            {\n              tmp_min = elem (i, idx_j);\n\n              if (! octave::math::isnan (tmp_min))\n                {\n                  abs_min = (real_only ? tmp_min.real ()\n                                       : std::abs (tmp_min));\n                  break;\n                }\n            }\n\n          for (octave_idx_type j = idx_j+1; j < nc; j++)\n            {\n              FloatComplex tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n\n              float abs_tmp = (real_only ? tmp.real () : std::abs (tmp));\n\n              if (abs_tmp < abs_min)\n                {\n                  idx_j = j;\n                  tmp_min = tmp;\n                  abs_min = abs_tmp;\n                }\n            }\n\n          if (octave::math::isnan (tmp_min))\n            {\n              result.elem (i) = FloatComplex_NaN_result;\n              idx_arg.elem (i) = 0;\n            }\n          else\n            {\n              result.elem (i) = tmp_min;\n              idx_arg.elem (i) = idx_j;\n            }\n        }\n    }\n\n  return result;\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::row_max () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return row_max (dummy_idx);\n}\n\nFloatComplexColumnVector\nFloatComplexMatrix::row_max (Array<octave_idx_type>& idx_arg) const\n{\n  FloatComplexColumnVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nr);\n      idx_arg.resize (dim_vector (nr, 1));\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          bool real_only = row_is_real_only (i);\n\n          octave_idx_type idx_j;\n\n          FloatComplex tmp_max;\n\n          float abs_max = octave::numeric_limits<float>::NaN ();\n\n          for (idx_j = 0; idx_j < nc; idx_j++)\n            {\n              tmp_max = elem (i, idx_j);\n\n              if (! octave::math::isnan (tmp_max))\n                {\n                  abs_max = (real_only ? tmp_max.real ()\n                                       : std::abs (tmp_max));\n                  break;\n                }\n            }\n\n          for (octave_idx_type j = idx_j+1; j < nc; j++)\n            {\n              FloatComplex tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n\n              float abs_tmp = (real_only ? tmp.real () : std::abs (tmp));\n\n              if (abs_tmp > abs_max)\n                {\n                  idx_j = j;\n                  tmp_max = tmp;\n                  abs_max = abs_tmp;\n                }\n            }\n\n          if (octave::math::isnan (tmp_max))\n            {\n              result.elem (i) = FloatComplex_NaN_result;\n              idx_arg.elem (i) = 0;\n            }\n          else\n            {\n              result.elem (i) = tmp_max;\n              idx_arg.elem (i) = idx_j;\n            }\n        }\n    }\n\n  return result;\n}\n\nFloatComplexRowVector\nFloatComplexMatrix::column_min () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return column_min (dummy_idx);\n}\n\nFloatComplexRowVector\nFloatComplexMatrix::column_min (Array<octave_idx_type>& idx_arg) const\n{\n  FloatComplexRowVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nc);\n      idx_arg.resize (dim_vector (1, nc));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          bool real_only = column_is_real_only (j);\n\n          octave_idx_type idx_i;\n\n          FloatComplex tmp_min;\n\n          float abs_min = octave::numeric_limits<float>::NaN ();\n\n          for (idx_i = 0; idx_i < nr; idx_i++)\n            {\n              tmp_min = elem (idx_i, j);\n\n              if (! octave::math::isnan (tmp_min))\n                {\n                  abs_min = (real_only ? tmp_min.real ()\n                                       : std::abs (tmp_min));\n                  break;\n                }\n            }\n\n          for (octave_idx_type i = idx_i+1; i < nr; i++)\n            {\n              FloatComplex tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n\n              float abs_tmp = (real_only ? tmp.real () : std::abs (tmp));\n\n              if (abs_tmp < abs_min)\n                {\n                  idx_i = i;\n                  tmp_min = tmp;\n                  abs_min = abs_tmp;\n                }\n            }\n\n          if (octave::math::isnan (tmp_min))\n            {\n              result.elem (j) = FloatComplex_NaN_result;\n              idx_arg.elem (j) = 0;\n            }\n          else\n            {\n              result.elem (j) = tmp_min;\n              idx_arg.elem (j) = idx_i;\n            }\n        }\n    }\n\n  return result;\n}\n\nFloatComplexRowVector\nFloatComplexMatrix::column_max () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return column_max (dummy_idx);\n}\n\nFloatComplexRowVector\nFloatComplexMatrix::column_max (Array<octave_idx_type>& idx_arg) const\n{\n  FloatComplexRowVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nc);\n      idx_arg.resize (dim_vector (1, nc));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          bool real_only = column_is_real_only (j);\n\n          octave_idx_type idx_i;\n\n          FloatComplex tmp_max;\n\n          float abs_max = octave::numeric_limits<float>::NaN ();\n\n          for (idx_i = 0; idx_i < nr; idx_i++)\n            {\n              tmp_max = elem (idx_i, j);\n\n              if (! octave::math::isnan (tmp_max))\n                {\n                  abs_max = (real_only ? tmp_max.real ()\n                                       : std::abs (tmp_max));\n                  break;\n                }\n            }\n\n          for (octave_idx_type i = idx_i+1; i < nr; i++)\n            {\n              FloatComplex tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n\n              float abs_tmp = (real_only ? tmp.real () : std::abs (tmp));\n\n              if (abs_tmp > abs_max)\n                {\n                  idx_i = i;\n                  tmp_max = tmp;\n                  abs_max = abs_tmp;\n                }\n            }\n\n          if (octave::math::isnan (tmp_max))\n            {\n              result.elem (j) = FloatComplex_NaN_result;\n              idx_arg.elem (j) = 0;\n            }\n          else\n            {\n              result.elem (j) = tmp_max;\n              idx_arg.elem (j) = idx_i;\n            }\n        }\n    }\n\n  return result;\n}\n\n// i/o\n\nstd::ostream&\noperator << (std::ostream& os, const FloatComplexMatrix& a)\n{\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    {\n      for (octave_idx_type j = 0; j < a.cols (); j++)\n        {\n          os << ' ';\n          octave::write_value<Complex> (os, a.elem (i, j));\n        }\n      os << \"\\n\";\n    }\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, FloatComplexMatrix& a)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      FloatComplex tmp;\n      for (octave_idx_type i = 0; i < nr; i++)\n        for (octave_idx_type j = 0; j < nc; j++)\n          {\n            tmp = octave::read_value<FloatComplex> (is);\n            if (is)\n              a.elem (i, j) = tmp;\n            else\n              return is;\n          }\n    }\n\n  return is;\n}\n\nFloatComplexMatrix\nGivens (const FloatComplex& x, const FloatComplex& y)\n{\n  float cc;\n  FloatComplex cs, temp_r;\n\n  F77_FUNC (clartg, CLARTG) (F77_CONST_CMPLX_ARG (&x), F77_CONST_CMPLX_ARG (&y),\n                             cc, F77_CMPLX_ARG (&cs), F77_CMPLX_ARG (&temp_r));\n\n  FloatComplexMatrix g (2, 2);\n\n  g.elem (0, 0) = cc;\n  g.elem (1, 1) = cc;\n  g.elem (0, 1) = cs;\n  g.elem (1, 0) = -conj (cs);\n\n  return g;\n}\n\nFloatComplexMatrix\nSylvester (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n           const FloatComplexMatrix& c)\n{\n  FloatComplexMatrix retval;\n\n  // FIXME: need to check that a, b, and c are all the same\n  // size.\n\n  // Compute Schur decompositions\n\n  octave::math::schur<FloatComplexMatrix> as (a, \"U\");\n  octave::math::schur<FloatComplexMatrix> bs (b, \"U\");\n\n  // Transform c to new coordinates.\n\n  FloatComplexMatrix ua = as.unitary_schur_matrix ();\n  FloatComplexMatrix sch_a = as.schur_matrix ();\n\n  FloatComplexMatrix ub = bs.unitary_schur_matrix ();\n  FloatComplexMatrix sch_b = bs.schur_matrix ();\n\n  FloatComplexMatrix cx = ua.hermitian () * c * ub;\n\n  // Solve the sylvester equation, back-transform, and return the\n  // solution.\n\n  F77_INT a_nr = octave::to_f77_int (a.rows ());\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n\n  float scale;\n  F77_INT info;\n\n  FloatComplex *pa = sch_a.rwdata ();\n  FloatComplex *pb = sch_b.rwdata ();\n  FloatComplex *px = cx.rwdata ();\n\n  F77_XFCN (ctrsyl, CTRSYL, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             1, a_nr, b_nr, F77_CMPLX_ARG (pa), a_nr, F77_CMPLX_ARG (pb),\n                             b_nr, F77_CMPLX_ARG (px), a_nr, scale, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // FIXME: check info?\n\n  retval = ua * cx * ub.hermitian ();\n\n  return retval;\n}\n\nFloatComplexMatrix\noperator * (const FloatComplexMatrix& m, const FloatMatrix& a)\n{\n  if (m.columns () > std::min (m.rows (), a.columns ()) / 10)\n    return FloatComplexMatrix (real (m) * a, imag (m) * a);\n  else\n    return m * FloatComplexMatrix (a);\n}\n\nFloatComplexMatrix\noperator * (const FloatMatrix& m, const FloatComplexMatrix& a)\n{\n  if (a.rows () > std::min (m.rows (), a.columns ()) / 10)\n    return FloatComplexMatrix (m * real (a), m * imag (a));\n  else\n    return FloatComplexMatrix (m) * a;\n}\n\n/*\n\n## Simple Dot Product, Matrix-Vector, and Matrix-Matrix Unit tests\n%!assert (single ([1+i 2+i 3+i]) * single ([ 4+i ; 5+i ; 6+i]), single (29+21i), 5e-7)\n%!assert (single ([1+i 2+i ; 3+i 4+i]) * single ([5+i ; 6+i]), single ([15 + 14i ; 37 + 18i]), 5e-7)\n%!assert (single ([1+i 2+i ; 3+i 4+i ]) * single ([5+i 6+i ; 7+i 8+i]), single ([17 + 15i 20 + 17i; 41 + 19i 48 + 21i]), 5e-7)\n%!assert (single ([1 i])*single ([i 0])', single (-i))\n\n## Test some simple identities\n%!shared M, cv, rv\n%! M = single (randn (10,10))+ i*single (rand (10,10));\n%! cv = single (randn (10,1))+ i*single (rand (10,1));\n%! rv = single (randn (1,10))+ i*single (rand (1,10));\n%!assert ([M*cv,M*cv], M*[cv,cv], 5e-6)\n%!assert ([M.'*cv,M.'*cv], M.'*[cv,cv], 5e-6)\n%!assert ([M'*cv,M'*cv], M'*[cv,cv], 5e-6)\n%!assert ([rv*M;rv*M], [rv;rv]*M, 5e-6)\n%!assert ([rv*M.';rv*M.'], [rv;rv]*M.', 5e-6)\n%!assert ([rv*M';rv*M'], [rv;rv]*M', 5e-6)\n%!assert (2*rv*cv, [rv,rv]*[cv;cv], 5e-6)\n\n*/\n\nstatic char\nget_blas_trans_arg (bool trans, bool conj)\n{\n  return trans ? (conj ? 'C' : 'T') : 'N';\n}\n\n// the general GEMM operation\n\nFloatComplexMatrix\nxgemm (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n       blas_trans_type transa, blas_trans_type transb)\n{\n  FloatComplexMatrix retval;\n\n  bool tra = transa != blas_no_trans;\n  bool trb = transb != blas_no_trans;\n  bool cja = transa == blas_conj_trans;\n  bool cjb = transb == blas_conj_trans;\n\n  F77_INT a_nr = octave::to_f77_int (tra ? a.cols () : a.rows ());\n  F77_INT a_nc = octave::to_f77_int (tra ? a.rows () : a.cols ());\n\n  F77_INT b_nr = octave::to_f77_int (trb ? b.cols () : b.rows ());\n  F77_INT b_nc = octave::to_f77_int (trb ? b.rows () : b.cols ());\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  if (a_nr == 0 || a_nc == 0 || b_nc == 0)\n    retval = FloatComplexMatrix (a_nr, b_nc, 0.0);\n  else if (a.data () == b.data () && a_nr == b_nc && tra != trb)\n    {\n      F77_INT lda = octave::to_f77_int (a.rows ());\n\n      // FIXME: looking at the reference BLAS, it appears that it\n      // should not be necessary to initialize the output matrix if\n      // BETA is 0 in the call to CHERK, but ATLAS appears to\n      // use the result matrix before zeroing the elements.\n\n      retval = FloatComplexMatrix (a_nr, b_nc, 0.0);\n      FloatComplex *c = retval.rwdata ();\n\n      const char ctra = get_blas_trans_arg (tra, cja);\n      if (cja || cjb)\n        {\n          F77_XFCN (cherk, CHERK, (F77_CONST_CHAR_ARG2 (\"U\", 1),\n                                   F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   a_nr, a_nc, 1.0,\n                                   F77_CONST_CMPLX_ARG (a.data ()), lda, 0.0, F77_CMPLX_ARG (c), a_nr\n                                   F77_CHAR_ARG_LEN (1)\n                                   F77_CHAR_ARG_LEN (1)));\n          for (F77_INT j = 0; j < a_nr; j++)\n            for (F77_INT i = 0; i < j; i++)\n              retval.xelem (j, i) = octave::math::conj (retval.xelem (i, j));\n        }\n      else\n        {\n          F77_XFCN (csyrk, CSYRK, (F77_CONST_CHAR_ARG2 (\"U\", 1),\n                                   F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   a_nr, a_nc, 1.0,\n                                   F77_CONST_CMPLX_ARG (a.data ()), lda, 0.0, F77_CMPLX_ARG (c), a_nr\n                                   F77_CHAR_ARG_LEN (1)\n                                   F77_CHAR_ARG_LEN (1)));\n          for (F77_INT j = 0; j < a_nr; j++)\n            for (F77_INT i = 0; i < j; i++)\n              retval.xelem (j, i) = retval.xelem (i, j);\n\n        }\n\n    }\n  else\n    {\n      F77_INT lda = octave::to_f77_int (a.rows ());\n      F77_INT tda = octave::to_f77_int (a.cols ());\n      F77_INT ldb = octave::to_f77_int (b.rows ());\n      F77_INT tdb = octave::to_f77_int (b.cols ());\n\n      retval = FloatComplexMatrix (a_nr, b_nc, 0.0);\n      FloatComplex *c = retval.rwdata ();\n\n      if (b_nc == 1 && a_nr == 1)\n        {\n          if (cja == cjb)\n            {\n              F77_FUNC (xcdotu, XCDOTU) (a_nc, F77_CONST_CMPLX_ARG (a.data ()), 1,\n                                         F77_CONST_CMPLX_ARG (b.data ()), 1,\n                                         F77_CMPLX_ARG (c));\n              if (cja) *c = octave::math::conj (*c);\n            }\n          else if (cja)\n            F77_FUNC (xcdotc, XCDOTC) (a_nc, F77_CONST_CMPLX_ARG (a.data ()), 1,\n                                       F77_CONST_CMPLX_ARG (b.data ()), 1,\n                                       F77_CMPLX_ARG (c));\n          else\n            F77_FUNC (xcdotc, XCDOTC) (a_nc, F77_CONST_CMPLX_ARG (b.data ()), 1,\n                                       F77_CONST_CMPLX_ARG (a.data ()), 1,\n                                       F77_CMPLX_ARG (c));\n        }\n      else if (b_nc == 1 && ! cjb)\n        {\n          const char ctra = get_blas_trans_arg (tra, cja);\n          F77_XFCN (cgemv, CGEMV, (F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   lda, tda, 1.0, F77_CONST_CMPLX_ARG (a.data ()), lda,\n                                   F77_CONST_CMPLX_ARG (b.data ()), 1, 0.0, F77_CMPLX_ARG (c), 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n      else if (a_nr == 1 && ! cja && ! cjb)\n        {\n          const char crevtrb = get_blas_trans_arg (! trb, cjb);\n          F77_XFCN (cgemv, CGEMV, (F77_CONST_CHAR_ARG2 (&crevtrb, 1),\n                                   ldb, tdb, 1.0, F77_CONST_CMPLX_ARG (b.data ()), ldb,\n                                   F77_CONST_CMPLX_ARG (a.data ()), 1, 0.0, F77_CMPLX_ARG (c), 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n      else\n        {\n          const char ctra = get_blas_trans_arg (tra, cja);\n          const char ctrb = get_blas_trans_arg (trb, cjb);\n          F77_XFCN (cgemm, CGEMM, (F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   F77_CONST_CHAR_ARG2 (&ctrb, 1),\n                                   a_nr, b_nc, a_nc, 1.0, F77_CONST_CMPLX_ARG (a.data ()),\n                                   lda, F77_CONST_CMPLX_ARG (b.data ()), ldb, 0.0, F77_CMPLX_ARG (c), a_nr\n                                   F77_CHAR_ARG_LEN (1)\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n    }\n\n  return retval;\n}\n\nFloatComplexMatrix\noperator * (const FloatComplexMatrix& a, const FloatComplexMatrix& b)\n{\n  return xgemm (a, b);\n}\n\n// FIXME: it would be nice to share code among the min/max\n// functions below.\n\n#define EMPTY_RETURN_CHECK(T)                   \\\n  if (nr == 0 || nc == 0)                       \\\n    return T (nr, nc);\n\nFloatComplexMatrix\nmin (FloatComplex& c, const FloatComplexMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmin (FloatComplex& c, const FloatComplexMatrix& m, const bool nanflag)\n{\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmin (FloatComplex& c, const FloatComplexMatrix& m,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (FloatComplexMatrix);\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::min (c, m(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatComplexMatrix\nmin (const FloatComplexMatrix& m, FloatComplex& c)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmin (const FloatComplexMatrix& m, FloatComplex& c, const bool nanflag)\n{\n  const bool realabs = false;\n  return min (c, m, nanflag, realabs);\n}\n\n\nFloatComplexMatrix\nmin (const FloatComplexMatrix& m, FloatComplex& c,\n     const bool nanflag, const bool realabs)\n{\n  return min (c, m, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmin (const FloatComplexMatrix& a, const FloatComplexMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return min (a, b, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmin (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n     const bool nanflag)\n{\n  const bool realabs = false;\n  return min (a, b, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmin (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n\n  if (nr != b.rows () || nc != b.columns ())\n    (*current_liboctave_error_handler)\n      (\"two-arg min requires same size arguments\");\n\n  EMPTY_RETURN_CHECK (FloatComplexMatrix);\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::min (a(i, j), b(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatComplexMatrix\nmax (FloatComplex& c, const FloatComplexMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmax (FloatComplex& c, const FloatComplexMatrix& m, const bool nanflag)\n{\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmax (FloatComplex& c, const FloatComplexMatrix& m,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (FloatComplexMatrix);\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::max (c, m(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatComplexMatrix\nmax (const FloatComplexMatrix& m, FloatComplex& c)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmax (const FloatComplexMatrix& m, FloatComplex& c, const bool nanflag)\n{\n  const bool realabs = false;\n  return max (c, m, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmax (const FloatComplexMatrix& m, const FloatComplex& c,\n     const bool nanflag, const bool realabs)\n{\n  return max (c, m, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmax (const FloatComplexMatrix& a, const FloatComplexMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = false;\n  return max (a, b, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmax (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n     const bool nanflag)\n{\n  const bool realabs = false;\n  return max (a, b, nanflag, realabs);\n}\n\nFloatComplexMatrix\nmax (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n\n  if (nr != b.rows () || nc != b.columns ())\n    (*current_liboctave_error_handler)\n      (\"two-arg max requires same size arguments\");\n\n  EMPTY_RETURN_CHECK (FloatComplexMatrix);\n\n  FloatComplexMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::max (a(i, j), b(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatComplexMatrix\nlinspace (const FloatComplexColumnVector& x1,\n          const FloatComplexColumnVector& x2,\n          octave_idx_type n)\n\n{\n  octave_idx_type m = x1.numel ();\n\n  if (x2.numel () != m)\n    (*current_liboctave_error_handler)\n      (\"linspace: vectors must be of equal length\");\n\n  FloatComplexMatrix retval;\n\n  if (n < 1)\n    {\n      retval.clear (m, 0);\n      return retval;\n    }\n\n  retval.clear (m, n);\n  for (octave_idx_type i = 0; i < m; i++)\n    retval.insert (linspace (x1(i), x2(i), n), i, 0);\n\n  return retval;\n}\n\nMS_CMP_OPS (FloatComplexMatrix, FloatComplex)\nMS_BOOL_OPS (FloatComplexMatrix, FloatComplex)\n\nSM_CMP_OPS (FloatComplex, FloatComplexMatrix)\nSM_BOOL_OPS (FloatComplex, FloatComplexMatrix)\n\nMM_CMP_OPS (FloatComplexMatrix, FloatComplexMatrix)\nMM_BOOL_OPS (FloatComplexMatrix, FloatComplexMatrix)\n"
  },
  {
    "path": "liboctave/array/fCMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fCMatrix_h)\n#define octave_fCMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"DET.h\"\n#include \"MArray.h\"\n#include \"MDiagArray2.h\"\n#include \"MatrixType.h\"\n#include \"fCNDArray.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-cmplx.h\"\n\nclass OCTAVE_API FloatComplexMatrix : public FloatComplexNDArray\n{\npublic:\n\n  typedef FloatComplexColumnVector column_vector_type;\n  typedef FloatComplexRowVector row_vector_type;\n\n  typedef FloatColumnVector real_column_vector_type;\n  typedef FloatRowVector real_row_vector_type;\n\n  typedef FloatMatrix real_matrix_type;\n  typedef FloatComplexMatrix complex_matrix_type;\n\n  typedef FloatDiagMatrix real_diag_matrix_type;\n  typedef FloatComplexDiagMatrix complex_diag_matrix_type;\n\n  typedef float real_elt_type;\n  typedef FloatComplex complex_elt_type;\n\n  typedef void (*solve_singularity_handler) (float rcon);\n\n  FloatComplexMatrix () = default;\n\n  FloatComplexMatrix (const FloatComplexMatrix& a) = default;\n\n  FloatComplexMatrix& operator = (const FloatComplexMatrix& a) = default;\n\n  ~FloatComplexMatrix () = default;\n\n  FloatComplexMatrix (octave_idx_type r, octave_idx_type c)\n    : FloatComplexNDArray (dim_vector (r, c)) { }\n\n  FloatComplexMatrix (octave_idx_type r, octave_idx_type c,\n                      const FloatComplex& val)\n    : FloatComplexNDArray (dim_vector (r, c), val) { }\n\n  FloatComplexMatrix (const dim_vector& dv)\n    : FloatComplexNDArray (dv.redim (2)) { }\n\n  FloatComplexMatrix (const dim_vector& dv, const FloatComplex& val)\n    : FloatComplexNDArray (dv.redim (2), val) { }\n\n  template <typename U>\n  FloatComplexMatrix (const MArray<U>& a)\n    : FloatComplexNDArray (a.as_matrix ()) { }\n\n  template <typename U>\n  FloatComplexMatrix (const Array<U>& a)\n    : FloatComplexNDArray (a.as_matrix ()) { }\n\n  explicit OCTAVE_API FloatComplexMatrix (const FloatMatrix& a);\n\n  explicit OCTAVE_API FloatComplexMatrix (const FloatRowVector& rv);\n\n  explicit OCTAVE_API FloatComplexMatrix (const FloatColumnVector& cv);\n\n  explicit OCTAVE_API FloatComplexMatrix (const FloatDiagMatrix& a);\n\n  explicit OCTAVE_API FloatComplexMatrix (const MDiagArray2<float>& a);\n\n  explicit OCTAVE_API FloatComplexMatrix (const DiagArray2<float>& a);\n\n  explicit OCTAVE_API FloatComplexMatrix (const FloatComplexRowVector& rv);\n\n  explicit OCTAVE_API FloatComplexMatrix (const FloatComplexColumnVector& cv);\n\n  explicit OCTAVE_API FloatComplexMatrix (const FloatComplexDiagMatrix& a);\n\n  explicit OCTAVE_API FloatComplexMatrix (const MDiagArray2<FloatComplex>& a);\n\n  explicit OCTAVE_API FloatComplexMatrix (const DiagArray2<FloatComplex>& a);\n\n  explicit OCTAVE_API FloatComplexMatrix (const boolMatrix& a);\n\n  explicit OCTAVE_API FloatComplexMatrix (const charMatrix& a);\n\n  OCTAVE_API FloatComplexMatrix (const FloatMatrix& re, const FloatMatrix& im);\n\n  OCTAVE_API bool operator == (const FloatComplexMatrix& a) const;\n  OCTAVE_API bool operator != (const FloatComplexMatrix& a) const;\n\n  OCTAVE_API bool ishermitian () const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API FloatComplexMatrix&\n  insert (const FloatMatrix& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatComplexMatrix&\n  insert (const FloatRowVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatComplexMatrix&\n  insert (const FloatColumnVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatComplexMatrix&\n  insert (const FloatDiagMatrix& a, octave_idx_type r, octave_idx_type c);\n\n  OCTAVE_API FloatComplexMatrix&\n  insert (const FloatComplexMatrix& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatComplexMatrix&\n  insert (const FloatComplexRowVector& a, octave_idx_type r,\n          octave_idx_type c);\n  OCTAVE_API FloatComplexMatrix&\n  insert (const FloatComplexColumnVector& a, octave_idx_type r,\n          octave_idx_type c);\n  OCTAVE_API FloatComplexMatrix&\n  insert (const FloatComplexDiagMatrix& a, octave_idx_type r,\n          octave_idx_type c);\n\n  OCTAVE_API FloatComplexMatrix& fill (float val);\n  OCTAVE_API FloatComplexMatrix& fill (const FloatComplex& val);\n  OCTAVE_API FloatComplexMatrix&\n  fill (float val, octave_idx_type r1, octave_idx_type c1,\n        octave_idx_type r2, octave_idx_type c2);\n  OCTAVE_API FloatComplexMatrix&\n  fill (const FloatComplex& val, octave_idx_type r1, octave_idx_type c1,\n        octave_idx_type r2, octave_idx_type c2);\n\n  OCTAVE_API FloatComplexMatrix append (const FloatMatrix& a) const;\n  OCTAVE_API FloatComplexMatrix append (const FloatRowVector& a) const;\n  OCTAVE_API FloatComplexMatrix append (const FloatColumnVector& a) const;\n  OCTAVE_API FloatComplexMatrix append (const FloatDiagMatrix& a) const;\n\n  OCTAVE_API FloatComplexMatrix append (const FloatComplexMatrix& a) const;\n  OCTAVE_API FloatComplexMatrix append (const FloatComplexRowVector& a) const;\n  OCTAVE_API FloatComplexMatrix\n  append (const FloatComplexColumnVector& a) const;\n  OCTAVE_API FloatComplexMatrix append (const FloatComplexDiagMatrix& a) const;\n\n  OCTAVE_API FloatComplexMatrix stack (const FloatMatrix& a) const;\n  OCTAVE_API FloatComplexMatrix stack (const FloatRowVector& a) const;\n  OCTAVE_API FloatComplexMatrix stack (const FloatColumnVector& a) const;\n  OCTAVE_API FloatComplexMatrix stack (const FloatDiagMatrix& a) const;\n\n  OCTAVE_API FloatComplexMatrix stack (const FloatComplexMatrix& a) const;\n  OCTAVE_API FloatComplexMatrix stack (const FloatComplexRowVector& a) const;\n  OCTAVE_API FloatComplexMatrix stack (const FloatComplexColumnVector& a) const;\n  OCTAVE_API FloatComplexMatrix stack (const FloatComplexDiagMatrix& a) const;\n\n  FloatComplexMatrix hermitian () const\n  { return MArray<FloatComplex>::hermitian (std::conj); }\n  FloatComplexMatrix transpose () const\n  { return MArray<FloatComplex>::transpose (); }\n\n  friend OCTAVE_API FloatComplexMatrix conj (const FloatComplexMatrix& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API FloatComplexMatrix\n  extract (octave_idx_type r1, octave_idx_type c1,\n           octave_idx_type r2, octave_idx_type c2) const;\n\n  OCTAVE_API FloatComplexMatrix\n  extract_n (octave_idx_type r1, octave_idx_type c1,\n             octave_idx_type nr, octave_idx_type nc) const;\n\n  // extract row or column i.\n\n  OCTAVE_API FloatComplexRowVector row (octave_idx_type i) const;\n\n  OCTAVE_API FloatComplexColumnVector column (octave_idx_type i) const;\n\n  void resize (octave_idx_type nr, octave_idx_type nc,\n               const FloatComplex& rfv = FloatComplex (0))\n  {\n    MArray<FloatComplex>::resize (dim_vector (nr, nc), rfv);\n  }\n\nprivate:\n  FloatComplexMatrix tinverse (MatrixType& mattype, octave_idx_type& info,\n                               float& rcon, bool force, bool calc_cond) const;\n\n  FloatComplexMatrix finverse (MatrixType& mattype, octave_idx_type& info,\n                               float& rcon, bool force, bool calc_cond) const;\n\npublic:\n  OCTAVE_API FloatComplexMatrix inverse () const;\n  OCTAVE_API FloatComplexMatrix inverse (octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  inverse (octave_idx_type& info, float& rcon,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API FloatComplexMatrix inverse (MatrixType& mattype) const;\n  OCTAVE_API FloatComplexMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info, float& rcon,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API FloatComplexMatrix pseudo_inverse (float tol = 0.0) const;\n\n  OCTAVE_API FloatComplexMatrix fourier () const;\n  OCTAVE_API FloatComplexMatrix ifourier () const;\n\n  OCTAVE_API FloatComplexMatrix fourier2d () const;\n  OCTAVE_API FloatComplexMatrix ifourier2d () const;\n\n  OCTAVE_API FloatComplexDET determinant () const;\n  OCTAVE_API FloatComplexDET determinant (octave_idx_type& info) const;\n  OCTAVE_API FloatComplexDET\n  determinant (octave_idx_type& info, float& rcon,\n               bool calc_cond = true) const;\n  OCTAVE_API FloatComplexDET\n  determinant (MatrixType& mattype, octave_idx_type& info,\n               float& rcon, bool calc_cond = true) const;\n\n  OCTAVE_API float rcond () const;\n  OCTAVE_API float rcond (MatrixType& mattype) const;\n\nprivate:\n  // Upper triangular matrix solvers\n  FloatComplexMatrix utsolve (MatrixType& mattype, const FloatComplexMatrix& b,\n                              octave_idx_type& info, float& rcon,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond = false,\n                              blas_trans_type transt = blas_no_trans) const;\n\n  // Lower triangular matrix solvers\n  FloatComplexMatrix ltsolve (MatrixType& mattype, const FloatComplexMatrix& b,\n                              octave_idx_type& info, float& rcon,\n                              solve_singularity_handler sing_handler,\n                              bool calc_cond = false,\n                              blas_trans_type transt = blas_no_trans) const;\n\n  // Full matrix solvers (umfpack/cholesky)\n  FloatComplexMatrix fsolve (MatrixType& mattype, const FloatComplexMatrix& b,\n                             octave_idx_type& info, float& rcon,\n                             solve_singularity_handler sing_handler,\n                             bool calc_cond = false) const;\n\npublic:\n  // Generic interface to solver with no probing of type\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatMatrix& b) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatMatrix& b, octave_idx_type& info,\n         float& rcon) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatMatrix& b, octave_idx_type& info,\n         float& rcon, solve_singularity_handler sing_handler,\n         bool singular_fallback = true,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatComplexMatrix& b) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatComplexMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatComplexMatrix& b,\n         octave_idx_type& info, float& rcon) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatComplexMatrix& b,\n         octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         bool singular_fallback = true,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatColumnVector& b) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatColumnVector& b,\n         octave_idx_type& info, float& rcon) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatColumnVector& b,\n         octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatComplexColumnVector& b) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatComplexColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatComplexColumnVector& b,\n         octave_idx_type& info, float& rcon) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatComplexColumnVector& b,\n         octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  // Generic interface to solver with probing of type\n  OCTAVE_API FloatComplexMatrix solve (const FloatMatrix& b) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (const FloatMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (const FloatMatrix& b, octave_idx_type& info, float& rcon) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (const FloatMatrix& b, octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexMatrix solve (const FloatComplexMatrix& b) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (const FloatComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (const FloatComplexMatrix& b, octave_idx_type& info,\n         float& rcon) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (const FloatComplexMatrix& b, octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexColumnVector solve (const FloatColumnVector& b) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatColumnVector& b, octave_idx_type& info,\n         float& rcon) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatColumnVector& b, octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatComplexColumnVector& b) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatComplexColumnVector& b, octave_idx_type& info,\n         float& rcon) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatComplexColumnVector& b, octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexMatrix lssolve (const FloatMatrix& b) const;\n  OCTAVE_API FloatComplexMatrix\n  lssolve (const FloatMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  lssolve (const FloatMatrix& b, octave_idx_type& info, octave_idx_type& rank) const;\n  OCTAVE_API FloatComplexMatrix\n  lssolve (const FloatMatrix& b, octave_idx_type& info, octave_idx_type& rank,\n           float& rcon) const;\n\n  OCTAVE_API FloatComplexMatrix lssolve (const FloatComplexMatrix& b) const;\n  OCTAVE_API FloatComplexMatrix\n  lssolve (const FloatComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  lssolve (const FloatComplexMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API FloatComplexMatrix\n  lssolve (const FloatComplexMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank, float& rcon) const;\n\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatColumnVector& b) const;\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank, float& rcon) const;\n\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatComplexColumnVector& b) const;\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank, float& rcon) const;\n\n  // matrix by diagonal matrix -> matrix operations\n\n  OCTAVE_API FloatComplexMatrix& operator += (const FloatDiagMatrix& a);\n  OCTAVE_API FloatComplexMatrix& operator -= (const FloatDiagMatrix& a);\n\n  OCTAVE_API FloatComplexMatrix& operator += (const FloatComplexDiagMatrix& a);\n  OCTAVE_API FloatComplexMatrix& operator -= (const FloatComplexDiagMatrix& a);\n\n  // matrix by matrix -> matrix operations\n\n  OCTAVE_API FloatComplexMatrix& operator += (const FloatMatrix& a);\n  OCTAVE_API FloatComplexMatrix& operator -= (const FloatMatrix& a);\n\n  // unary operations\n\n  OCTAVE_API boolMatrix operator ! () const;\n\n  // other operations\n\n  OCTAVE_API boolMatrix all (int dim = -1) const;\n  OCTAVE_API boolMatrix any (int dim = -1) const;\n\n  OCTAVE_API FloatComplexMatrix flip (int dim = -1) const;\n  OCTAVE_API FloatComplexMatrix cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatComplexMatrix cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatComplexMatrix prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexMatrix dprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatComplexMatrix sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexMatrix dsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatComplexMatrix sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexMatrix dsumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatMatrix abs () const;\n\n  OCTAVE_API FloatComplexMatrix diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API FloatComplexDiagMatrix\n  diag (octave_idx_type m, octave_idx_type n) const;\n\n  OCTAVE_API bool row_is_real_only (octave_idx_type) const;\n  OCTAVE_API bool column_is_real_only (octave_idx_type) const;\n\n  OCTAVE_API FloatComplexColumnVector row_min () const;\n  OCTAVE_API FloatComplexColumnVector row_max () const;\n\n  OCTAVE_API FloatComplexColumnVector\n  row_min (Array<octave_idx_type>& index) const;\n  OCTAVE_API FloatComplexColumnVector\n  row_max (Array<octave_idx_type>& index) const;\n\n  OCTAVE_API FloatComplexRowVector column_min () const;\n  OCTAVE_API FloatComplexRowVector column_max () const;\n\n  OCTAVE_API FloatComplexRowVector\n  column_min (Array<octave_idx_type>& index) const;\n  OCTAVE_API FloatComplexRowVector\n  column_max (Array<octave_idx_type>& index) const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const FloatComplexMatrix& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, FloatComplexMatrix& a);\n};\n\nextern OCTAVE_API FloatComplexMatrix conj (const FloatComplexMatrix& a);\n\n// column vector by row vector -> matrix operations\n\nextern OCTAVE_API FloatComplexMatrix\noperator * (const FloatColumnVector& a, const FloatComplexRowVector& b);\n\nextern OCTAVE_API FloatComplexMatrix\noperator * (const FloatComplexColumnVector& a, const FloatRowVector& b);\n\nextern OCTAVE_API FloatComplexMatrix\noperator * (const FloatComplexColumnVector& a, const FloatComplexRowVector& b);\n\nextern OCTAVE_API FloatComplexMatrix\nGivens (const FloatComplex&, const FloatComplex&);\n\nextern OCTAVE_API FloatComplexMatrix\nSylvester (const FloatComplexMatrix&, const FloatComplexMatrix&,\n           const FloatComplexMatrix&);\n\nextern OCTAVE_API FloatComplexMatrix\nxgemm (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n       blas_trans_type transa = blas_no_trans,\n       blas_trans_type transb = blas_no_trans);\n\nextern OCTAVE_API FloatComplexMatrix operator * (const FloatMatrix&,\n                                                 const FloatComplexMatrix&);\nextern OCTAVE_API FloatComplexMatrix operator * (const FloatComplexMatrix&,\n                                                 const FloatMatrix&);\nextern OCTAVE_API FloatComplexMatrix operator * (const FloatComplexMatrix&,\n                                                 const FloatComplexMatrix&);\n\nextern OCTAVE_API FloatComplexMatrix\nmin (FloatComplex& c, const FloatComplexMatrix& m);\nextern OCTAVE_API FloatComplexMatrix\nmin (FloatComplex& c, const FloatComplexMatrix& m, const bool nanflag);\nextern OCTAVE_API FloatComplexMatrix\nmin (FloatComplex& c, const FloatComplexMatrix& m, const bool nanflag,\n     const bool realabs);\nextern OCTAVE_API FloatComplexMatrix\nmin (const FloatComplexMatrix& m, FloatComplex& c);\nextern OCTAVE_API FloatComplexMatrix\nmin (const FloatComplexMatrix& m, FloatComplex& c, const bool nanflag);\nextern OCTAVE_API FloatComplexMatrix\nmin (const FloatComplexMatrix& m, FloatComplex& c, const bool nanflag,\n     const bool realabs);\nextern OCTAVE_API FloatComplexMatrix\nmin (const FloatComplexMatrix& a, const FloatComplexMatrix& b);\nextern OCTAVE_API FloatComplexMatrix\nmin (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n     const bool nanflag);\nextern OCTAVE_API FloatComplexMatrix\nmin (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n     const bool nanflag, const bool realabs);\n\nextern OCTAVE_API FloatComplexMatrix\nmax (FloatComplex& c, const FloatComplexMatrix& m);\nextern OCTAVE_API FloatComplexMatrix\nmax (FloatComplex& c, const FloatComplexMatrix& m, const bool nanflag);\nextern OCTAVE_API FloatComplexMatrix\nmax (FloatComplex& c, const FloatComplexMatrix& m, const bool nanflag,\n     const bool realabs);\nextern OCTAVE_API FloatComplexMatrix\nmax (const FloatComplexMatrix& m, FloatComplex& c);\nextern OCTAVE_API FloatComplexMatrix\nmax (const FloatComplexMatrix& m, FloatComplex& c, const bool nanflag);\nextern OCTAVE_API FloatComplexMatrix\nmax (const FloatComplexMatrix& m, FloatComplex& c, const bool nanflag,\n     const bool realabs);\nextern OCTAVE_API FloatComplexMatrix\nmax (const FloatComplexMatrix& a, const FloatComplexMatrix& b);\nextern OCTAVE_API FloatComplexMatrix\nmax (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n     const bool nanflag);\nextern OCTAVE_API FloatComplexMatrix\nmax (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n     const bool nanflag, const bool realabs);\n\nextern OCTAVE_API FloatComplexMatrix\nlinspace (const FloatComplexColumnVector& x1,\n          const FloatComplexColumnVector& x2,\n          octave_idx_type n);\n\nMS_CMP_OP_DECLS (FloatComplexMatrix, FloatComplex, OCTAVE_API)\nMS_BOOL_OP_DECLS (FloatComplexMatrix, FloatComplex, OCTAVE_API)\n\nSM_CMP_OP_DECLS (FloatComplex, FloatComplexMatrix, OCTAVE_API)\nSM_BOOL_OP_DECLS (FloatComplex, FloatComplexMatrix, OCTAVE_API)\n\nMM_CMP_OP_DECLS (FloatComplexMatrix, FloatComplexMatrix, OCTAVE_API)\nMM_BOOL_OP_DECLS (FloatComplexMatrix, FloatComplexMatrix, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, FloatComplexMatrix, FloatComplex)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fCNDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <complex>\n#include <istream>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"f77-fcn.h\"\n#include \"fCNDArray.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"mx-base.h\"\n#include \"mx-fcnda-fs.h\"\n#include \"mx-op-defs.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n\n#include \"bsxfun-defs.cc\"\n\nFloatComplexNDArray::FloatComplexNDArray (const charNDArray& a)\n  : MArray<FloatComplex> (a.dims ())\n{\n  octave_idx_type n = a.numel ();\n  for (octave_idx_type i = 0; i < n; i++)\n    xelem (i) = static_cast<unsigned char> (a(i));\n}\n\n#if defined (HAVE_FFTW)\n\nFloatComplexNDArray\nFloatComplexNDArray::fourier (int dim) const\n{\n  const dim_vector& dv = dims ();\n\n  if (dim > dv.ndims () || dim < 0)\n    return FloatComplexNDArray ();\n\n  octave_idx_type stride = 1;\n  octave_idx_type n = dv(dim);\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  octave_idx_type howmany = numel () / dv(dim);\n  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));\n  octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);\n  octave_idx_type dist = (stride == 1 ? n : 1);\n\n  const FloatComplex *in (data ());\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out (retval.rwdata ());\n\n  // Need to be careful here about the distance between fft's\n  for (octave_idx_type k = 0; k < nloop; k++)\n    octave::fftw::fft (in + k * stride * n, out + k * stride * n,\n                       n, howmany, stride, dist);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::ifourier (int dim) const\n{\n  const dim_vector& dv = dims ();\n\n  if (dim > dv.ndims () || dim < 0)\n    return FloatComplexNDArray ();\n\n  octave_idx_type stride = 1;\n  octave_idx_type n = dv(dim);\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  octave_idx_type howmany = numel () / dv(dim);\n  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));\n  octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);\n  octave_idx_type dist = (stride == 1 ? n : 1);\n\n  const FloatComplex *in (data ());\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out (retval.rwdata ());\n\n  // Need to be careful here about the distance between fft's\n  for (octave_idx_type k = 0; k < nloop; k++)\n    octave::fftw::ifft (in + k * stride * n, out + k * stride * n,\n                        n, howmany, stride, dist);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::fourier2d () const\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 2)\n    return FloatComplexNDArray ();\n\n  dim_vector dv2 (dv(0), dv(1));\n  const FloatComplex *in = data ();\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out = retval.rwdata ();\n  octave_idx_type howmany = numel () / dv(0) / dv(1);\n  octave_idx_type dist = dv(0) * dv(1);\n\n  for (octave_idx_type i=0; i < howmany; i++)\n    octave::fftw::fftNd (in + i*dist, out + i*dist, 2, dv2);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::ifourier2d () const\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 2)\n    return FloatComplexNDArray ();\n\n  dim_vector dv2 (dv(0), dv(1));\n  const FloatComplex *in = data ();\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out = retval.rwdata ();\n  octave_idx_type howmany = numel () / dv(0) / dv(1);\n  octave_idx_type dist = dv(0) * dv(1);\n\n  for (octave_idx_type i=0; i < howmany; i++)\n    octave::fftw::ifftNd (in + i*dist, out + i*dist, 2, dv2);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::fourierNd () const\n{\n  const dim_vector& dv = dims ();\n  int rank = dv.ndims ();\n\n  const FloatComplex *in (data ());\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::fftNd (in, out, rank, dv);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::ifourierNd () const\n{\n  const dim_vector& dv = dims ();\n  int rank = dv.ndims ();\n\n  const FloatComplex *in (data ());\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::ifftNd (in, out, rank, dv);\n\n  return retval;\n}\n\n#else\n\nFloatComplexNDArray\nFloatComplexNDArray::fourier (int dim) const\n{\n  octave_unused_parameter (dim);\n\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::ifourier (int dim) const\n{\n  octave_unused_parameter (dim);\n\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::fourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::ifourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::fourierNd () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::ifourierNd () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\n#endif\n\n// unary operations\n\nboolNDArray\nFloatComplexNDArray::operator ! () const\n{\n  if (any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n\n  return do_mx_unary_op<bool, FloatComplex> (*this, mx_inline_not);\n}\n\n// FIXME: this is not quite the right thing.\n\nbool\nFloatComplexNDArray::any_element_is_nan () const\n{\n  return do_mx_check<FloatComplex> (*this, mx_inline_any_nan);\n}\n\nbool\nFloatComplexNDArray::any_element_is_inf_or_nan () const\n{\n  return ! do_mx_check<FloatComplex> (*this, mx_inline_all_finite);\n}\n\n// Return true if no elements have imaginary components.\n\nbool\nFloatComplexNDArray::all_elements_are_real () const\n{\n  return do_mx_check<FloatComplex> (*this, mx_inline_all_real);\n}\n\n// Return nonzero if any element of CM has a non-integer real or\n// imaginary part.  Also extract the largest and smallest (real or\n// imaginary) values and return them in MAX_VAL and MIN_VAL.\n\nbool\nFloatComplexNDArray::all_integers (float& max_val, float& min_val) const\n{\n  octave_idx_type nel = numel ();\n\n  if (nel > 0)\n    {\n      FloatComplex val = elem (0);\n\n      float r_val = val.real ();\n      float i_val = val.imag ();\n\n      max_val = r_val;\n      min_val = r_val;\n\n      if (i_val > max_val)\n        max_val = i_val;\n\n      if (i_val < max_val)\n        min_val = i_val;\n    }\n  else\n    return false;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      FloatComplex val = elem (i);\n\n      float r_val = val.real ();\n      float i_val = val.imag ();\n\n      if (r_val > max_val)\n        max_val = r_val;\n\n      if (i_val > max_val)\n        max_val = i_val;\n\n      if (r_val < min_val)\n        min_val = r_val;\n\n      if (i_val < min_val)\n        min_val = i_val;\n\n      if (octave::math::round (r_val) != r_val\n          || octave::math::round (i_val) != i_val)\n        return false;\n    }\n\n  return true;\n}\n\nbool\nFloatComplexNDArray::too_large_for_float () const\n{\n  return false;\n}\n\nboolNDArray\nFloatComplexNDArray::all (int dim) const\n{\n  return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_all);\n}\n\nboolNDArray\nFloatComplexNDArray::any (int dim) const\n{\n  return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_any);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::flip (int dim) const\n{\n  return do_mx_flip_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_flip);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::cumprod (int dim, bool nanflag) const\n{\n  return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim, nanflag,\n                                                   mx_inline_cumprod);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::cumsum (int dim, bool nanflag) const\n{\n  return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim, nanflag,\n                                                   mx_inline_cumsum);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::prod (int dim, bool nanflag) const\n{\n  return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, nanflag,\n                                                   mx_inline_prod);\n}\n\nComplexNDArray\nFloatComplexNDArray::dprod (int dim, bool nanflag) const\n{\n  return do_mx_red_op<Complex, FloatComplex> (*this, dim, nanflag,\n                                              mx_inline_dprod);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::sum (int dim, bool nanflag) const\n{\n  return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, nanflag,\n                                                   mx_inline_sum);\n}\n\nComplexNDArray\nFloatComplexNDArray::dsum (int dim, bool nanflag) const\n{\n  return do_mx_red_op<Complex, FloatComplex> (*this, dim, nanflag,\n                                              mx_inline_dsum);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::sumsq (int dim, bool nanflag) const\n{\n  return do_mx_red_op<float, FloatComplex> (*this, dim, nanflag,\n                                            mx_inline_sumsq);\n}\n\nComplexNDArray\nFloatComplexNDArray::dsumsq (int dim, bool nanflag) const\n{\n  return do_mx_red_op<double, FloatComplex> (*this, dim, nanflag,\n                                             mx_inline_dsumsq);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::diff (octave_idx_type order, int dim) const\n{\n  return do_mx_diff_op<FloatComplex> (*this, dim, order, mx_inline_diff);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::concat (const FloatComplexNDArray& rb,\n                             const Array<octave_idx_type>& ra_idx)\n{\n  if (rb.numel () > 0)\n    insert (rb, ra_idx);\n  return *this;\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::concat (const FloatNDArray& rb,\n                             const Array<octave_idx_type>& ra_idx)\n{\n  FloatComplexNDArray tmp (rb);\n  if (rb.numel () > 0)\n    insert (tmp, ra_idx);\n  return *this;\n}\n\nFloatComplexNDArray\nconcat (NDArray& ra, FloatComplexNDArray& rb,\n        const Array<octave_idx_type>& ra_idx)\n{\n  FloatComplexNDArray retval (ra);\n  if (rb.numel () > 0)\n    retval.insert (rb, ra_idx);\n  return retval;\n}\n\nstatic const FloatComplex FloatComplex_NaN_result (octave::numeric_limits<float>::NaN (),\n                                                   octave::numeric_limits<float>::NaN ());\n\nFloatComplexNDArray\nFloatComplexNDArray::max (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<FloatComplex> (*this, dim, nanflag,\n                                        realabs, mx_inline_cmax);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::max (Array<octave_idx_type>& idx_arg,\n                          int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<FloatComplex> (*this, idx_arg, dim,\n                                        nanflag, realabs, mx_inline_cmax);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::min (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<FloatComplex> (*this, dim, nanflag,\n                                        realabs, mx_inline_cmin);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::min (Array<octave_idx_type>& idx_arg,\n                          int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<FloatComplex> (*this, idx_arg, dim,\n                                        nanflag, realabs, mx_inline_cmin);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::cummax (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<FloatComplex> (*this, dim, nanflag,\n                                           realabs, mx_inline_ccummax);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::cummax (Array<octave_idx_type>& idx_arg,\n                             int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<FloatComplex> (*this, idx_arg, dim, nanflag,\n                                           realabs, mx_inline_ccummax);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::cummin (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<FloatComplex> (*this, dim, nanflag,\n                                           realabs, mx_inline_ccummin);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::cummin (Array<octave_idx_type>& idx_arg,\n                             int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<FloatComplex> (*this, idx_arg, dim, nanflag,\n                                           realabs, mx_inline_ccummin);\n}\n\nFloatNDArray\nFloatComplexNDArray::abs () const\n{\n  return do_mx_unary_map<float, FloatComplex, std::abs> (*this);\n}\n\nboolNDArray\nFloatComplexNDArray::isnan () const\n{\n  return do_mx_unary_map<bool, FloatComplex, octave::math::isnan> (*this);\n}\n\nboolNDArray\nFloatComplexNDArray::isinf () const\n{\n  return do_mx_unary_map<bool, FloatComplex, octave::math::isinf> (*this);\n}\n\nboolNDArray\nFloatComplexNDArray::isfinite () const\n{\n  return do_mx_unary_map<bool, FloatComplex, octave::math::isfinite> (*this);\n}\n\nFloatComplexNDArray\nconj (const FloatComplexNDArray& a)\n{\n  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float>> (a);\n}\n\nFloatComplexNDArray&\nFloatComplexNDArray::insert (const NDArray& a,\n                             octave_idx_type r, octave_idx_type c)\n{\n  const dim_vector& a_dv = a.dims ();\n  const dim_vector& dv = dims ();\n\n  int n = a_dv.ndims ();\n\n  if (n == dv.ndims ())\n    {\n      Array<octave_idx_type> a_ra_idx (dim_vector (a_dv.ndims (), 1), 0);\n\n      a_ra_idx.elem (0) = r;\n      a_ra_idx.elem (1) = c;\n\n      for (int i = 0; i < n; i++)\n        {\n          if (a_ra_idx(i) < 0 || (a_ra_idx(i) + a_dv(i)) > dv(i))\n            (*current_liboctave_error_handler)\n              (\"Array<T>::insert: range error for insert\");\n        }\n\n      a_ra_idx.elem (0) = 0;\n      a_ra_idx.elem (1) = 0;\n\n      octave_idx_type n_elt = a.numel ();\n\n      // IS make_unique () NECESSARY HERE?\n\n      for (octave_idx_type i = 0; i < n_elt; i++)\n        {\n          Array<octave_idx_type> ra_idx = a_ra_idx;\n\n          ra_idx.elem (0) = a_ra_idx(0) + r;\n          ra_idx.elem (1) = a_ra_idx(1) + c;\n\n          elem (ra_idx) = a.elem (a_ra_idx);\n\n          increment_index (a_ra_idx, a_dv);\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"Array<T>::insert: invalid indexing operation\");\n\n  return *this;\n}\n\nFloatComplexNDArray&\nFloatComplexNDArray::insert (const FloatComplexNDArray& a,\n                             octave_idx_type r, octave_idx_type c)\n{\n  Array<FloatComplex>::insert (a, r, c);\n  return *this;\n}\n\nFloatComplexNDArray&\nFloatComplexNDArray::insert (const FloatComplexNDArray& a,\n                             const Array<octave_idx_type>& ra_idx)\n{\n  Array<FloatComplex>::insert (a, ra_idx);\n  return *this;\n}\n\nvoid\nFloatComplexNDArray::increment_index (Array<octave_idx_type>& ra_idx,\n                                      const dim_vector& dimensions,\n                                      int start_dimension)\n{\n  ::increment_index (ra_idx, dimensions, start_dimension);\n}\n\noctave_idx_type\nFloatComplexNDArray::compute_index (Array<octave_idx_type>& ra_idx,\n                                    const dim_vector& dimensions)\n{\n  return ::compute_index (ra_idx, dimensions);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::diag (octave_idx_type k) const\n{\n  return MArray<FloatComplex>::diag (k);\n}\n\nFloatComplexNDArray\nFloatComplexNDArray::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return MArray<FloatComplex>::diag (m, n);\n}\n\n// This contains no information on the array structure !!!\nstd::ostream&\noperator << (std::ostream& os, const FloatComplexNDArray& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      os << ' ';\n      octave::write_value<Complex> (os, a.elem (i));\n      os << \"\\n\";\n    }\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, FloatComplexNDArray& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  if (nel > 0)\n    {\n      FloatComplex tmp;\n      for (octave_idx_type i = 0; i < nel; i++)\n        {\n          tmp = octave::read_value<FloatComplex> (is);\n          if (is)\n            a.elem (i) = tmp;\n          else\n            return is;\n        }\n    }\n\n  return is;\n}\n\nMINMAX_FCNS (FloatComplexNDArray, FloatComplex)\n\nNDS_CMP_OPS (FloatComplexNDArray, FloatComplex)\nNDS_BOOL_OPS (FloatComplexNDArray, FloatComplex)\n\nSND_CMP_OPS (FloatComplex, FloatComplexNDArray)\nSND_BOOL_OPS (FloatComplex, FloatComplexNDArray)\n\nNDND_CMP_OPS (FloatComplexNDArray, FloatComplexNDArray)\nNDND_BOOL_OPS (FloatComplexNDArray, FloatComplexNDArray)\n\nFloatComplexNDArray& operator *= (FloatComplexNDArray& a, float s)\n{\n  if (a.is_shared ())\n    a = a * s;\n  else\n    do_ms_inplace_op<FloatComplex, float> (a, s, mx_inline_mul2);\n  return a;\n}\n\nFloatComplexNDArray&\noperator /= (FloatComplexNDArray& a, float s)\n{\n  if (a.is_shared ())\n    a = a / s;\n  else\n    do_ms_inplace_op<FloatComplex, float> (a, s, mx_inline_div2);\n  return a;\n}\n\nBSXFUN_STDOP_DEFS_MXLOOP (FloatComplexNDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (FloatComplexNDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, FloatComplexNDArray, mx_inline_pow)\n"
  },
  {
    "path": "liboctave/array/fCNDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fCNDArray_h)\n#define octave_fCNDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"bsxfun-decl.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n\nclass OCTAVE_API FloatComplexNDArray : public MArray<FloatComplex>\n{\npublic:\n\n  FloatComplexNDArray () : MArray<FloatComplex> () { }\n\n  FloatComplexNDArray (const dim_vector& dv) : MArray<FloatComplex> (dv) { }\n\n  FloatComplexNDArray (const dim_vector& dv, const FloatComplex& val)\n    : MArray<FloatComplex> (dv, val) { }\n\n  FloatComplexNDArray (const FloatComplexNDArray& a)\n    : MArray<FloatComplex> (a) { }\n\n  template <typename U>\n  FloatComplexNDArray (const MArray<U>& a) : MArray<FloatComplex> (a) { }\n\n  template <typename U>\n  FloatComplexNDArray (const Array<U>& a) : MArray<FloatComplex> (a) { }\n\n  OCTAVE_API FloatComplexNDArray (const charNDArray&);\n\n  FloatComplexNDArray& operator = (const FloatComplexNDArray& a)\n  {\n    MArray<FloatComplex>::operator = (a);\n    return *this;\n  }\n\n  ~FloatComplexNDArray () = default;\n\n  // unary operations\n\n  OCTAVE_API boolNDArray operator ! () const;\n\n  // FIXME: this is not quite the right thing.\n\n  OCTAVE_API bool any_element_is_nan () const;\n  OCTAVE_API bool any_element_is_inf_or_nan () const;\n  OCTAVE_API bool all_elements_are_real () const;\n  OCTAVE_API bool all_integers (float& max_val, float& min_val) const;\n  OCTAVE_API bool too_large_for_float () const;\n\n  OCTAVE_API boolNDArray all (int dim = -1) const;\n  OCTAVE_API boolNDArray any (int dim = -1) const;\n\n  OCTAVE_API FloatComplexNDArray flip (int dim = -1) const;\n  OCTAVE_API FloatComplexNDArray cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatComplexNDArray cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatComplexNDArray prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexNDArray dprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatComplexNDArray sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexNDArray dsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatComplexNDArray sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API ComplexNDArray dsumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatComplexNDArray\n  concat (const FloatComplexNDArray& rb, const Array<octave_idx_type>& ra_idx);\n  OCTAVE_API FloatComplexNDArray\n  concat (const FloatNDArray& rb, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API FloatComplexNDArray\n  max (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API FloatComplexNDArray\n  max (Array<octave_idx_type>& index, int dim = -1,\n       bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API FloatComplexNDArray\n  min (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API FloatComplexNDArray\n  min (Array<octave_idx_type>& index, int dim = -1,\n       bool nanflag = true, bool realabs = false) const;\n\n  OCTAVE_API FloatComplexNDArray\n  cummax (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API FloatComplexNDArray\n  cummax (Array<octave_idx_type>& index, int dim = -1,\n          bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API FloatComplexNDArray\n  cummin (int dim = -1, bool nanflag = true, bool realabs = false) const;\n  OCTAVE_API FloatComplexNDArray\n  cummin (Array<octave_idx_type>& index, int dim = -1,\n          bool nanflag = true, bool realabs = false) const;\n\n  OCTAVE_API FloatComplexNDArray\n  diff (octave_idx_type order = 1, int dim = -1) const;\n\n  OCTAVE_API FloatComplexNDArray&\n  insert (const NDArray& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatComplexNDArray&\n  insert (const FloatComplexNDArray& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatComplexNDArray&\n  insert (const FloatComplexNDArray& a, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API FloatNDArray abs () const;\n  OCTAVE_API boolNDArray isnan () const;\n  OCTAVE_API boolNDArray isinf () const;\n  OCTAVE_API boolNDArray isfinite () const;\n\n  friend OCTAVE_API FloatComplexNDArray conj (const FloatComplexNDArray& a);\n\n  OCTAVE_API FloatComplexNDArray fourier (int dim = 1) const;\n  OCTAVE_API FloatComplexNDArray ifourier (int dim = 1) const;\n\n  OCTAVE_API FloatComplexNDArray fourier2d () const;\n  OCTAVE_API FloatComplexNDArray ifourier2d () const;\n\n  OCTAVE_API FloatComplexNDArray fourierNd () const;\n  OCTAVE_API FloatComplexNDArray ifourierNd () const;\n\n  FloatComplexNDArray squeeze () const\n  { return MArray<FloatComplex>::squeeze (); }\n\n  static OCTAVE_API void\n  increment_index (Array<octave_idx_type>& ra_idx,\n                   const dim_vector& dimensions, int start_dimension = 0);\n\n  static OCTAVE_API octave_idx_type\n  compute_index (Array<octave_idx_type>& ra_idx, const dim_vector& dimensions);\n\n  // i/o\n\n  friend OCTAVE_API std::ostream& operator << (std::ostream& os,\n                                               const FloatComplexNDArray& a);\n  friend OCTAVE_API std::istream& operator >> (std::istream& is,\n                                               FloatComplexNDArray& a);\n\n  //  bool all_elements_are_real () const;\n  //  bool all_integers (float& max_val, float& min_val) const;\n\n  OCTAVE_API FloatComplexNDArray diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API FloatComplexNDArray\n  diag (octave_idx_type m, octave_idx_type n) const;\n\n  FloatComplexNDArray& changesign ()\n  {\n    MArray<FloatComplex>::changesign ();\n    return *this;\n  }\n\n};\n\nextern OCTAVE_API FloatComplexNDArray conj (const FloatComplexNDArray& a);\n\nMINMAX_DECLS (FloatComplexNDArray, FloatComplex, OCTAVE_API)\n\nNDS_CMP_OP_DECLS (FloatComplexNDArray, FloatComplex, OCTAVE_API)\nNDS_BOOL_OP_DECLS (FloatComplexNDArray, FloatComplex, OCTAVE_API)\n\nSND_CMP_OP_DECLS (FloatComplex, FloatComplexNDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (FloatComplex, FloatComplexNDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (FloatComplexNDArray, FloatComplexNDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (FloatComplexNDArray, FloatComplexNDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, FloatComplexNDArray, FloatComplex)\n\nextern OCTAVE_API FloatComplexNDArray& operator *= (FloatComplexNDArray& a,\n                                                    float s);\nextern OCTAVE_API FloatComplexNDArray& operator /= (FloatComplexNDArray& a,\n                                                    float s);\n\nBSXFUN_STDOP_DECLS (FloatComplexNDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (FloatComplexNDArray, OCTAVE_API)\n\nBSXFUN_OP_DECL (pow, FloatComplexNDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fCRowVector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n#include <type_traits>\n\n#include \"Array-util.h\"\n#include \"blas-proto.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// FloatComplex Row Vector class\n\nbool\nFloatComplexRowVector::operator == (const FloatComplexRowVector& a) const\n{\n  octave_idx_type len = numel ();\n  if (len != a.numel ())\n    return 0;\n  return mx_inline_equal (len, data (), a.data ());\n}\n\nbool\nFloatComplexRowVector::operator != (const FloatComplexRowVector& a) const\n{\n  return !(*this == a);\n}\n\n// destructive insert/delete/reorder operations\n\nFloatComplexRowVector&\nFloatComplexRowVector::insert (const FloatRowVector& a, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (c < 0 || c + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatComplexRowVector&\nFloatComplexRowVector::insert (const FloatComplexRowVector& a,\n                               octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (c < 0 || c + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatComplexRowVector&\nFloatComplexRowVector::fill (float val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexRowVector&\nFloatComplexRowVector::fill (const FloatComplex& val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexRowVector&\nFloatComplexRowVector::fill (float val, octave_idx_type c1, octave_idx_type c2)\n{\n  octave_idx_type len = numel ();\n\n  if (c1 < 0 || c2 < 0 || c1 >= len || c2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = c1; i <= c2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexRowVector&\nFloatComplexRowVector::fill (const FloatComplex& val,\n                             octave_idx_type c1, octave_idx_type c2)\n{\n  octave_idx_type len = numel ();\n\n  if (c1 < 0 || c2 < 0 || c1 >= len || c2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = c1; i <= c2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatComplexRowVector\nFloatComplexRowVector::append (const FloatRowVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nc_insert = len;\n  FloatComplexRowVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nc_insert);\n  return retval;\n}\n\nFloatComplexRowVector\nFloatComplexRowVector::append (const FloatComplexRowVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nc_insert = len;\n  FloatComplexRowVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nc_insert);\n  return retval;\n}\n\nFloatComplexColumnVector\nFloatComplexRowVector::hermitian () const\n{\n  return MArray<FloatComplex>::hermitian (std::conj);\n}\n\nFloatComplexColumnVector\nFloatComplexRowVector::transpose () const\n{\n  return MArray<FloatComplex>::transpose ();\n}\n\nFloatComplexRowVector\nconj (const FloatComplexRowVector& a)\n{\n  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float>> (a);\n}\n\n// resize is the destructive equivalent for this one\n\nFloatComplexRowVector\nFloatComplexRowVector::extract (octave_idx_type c1, octave_idx_type c2) const\n{\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  FloatComplexRowVector result (new_c);\n\n  for (octave_idx_type i = 0; i < new_c; i++)\n    result.elem (i) = elem (c1+i);\n\n  return result;\n}\n\nFloatComplexRowVector\nFloatComplexRowVector::extract_n (octave_idx_type r1, octave_idx_type n) const\n{\n  FloatComplexRowVector result (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    result.elem (i) = elem (r1+i);\n\n  return result;\n}\n\n// row vector by row vector -> row vector operations\n\nFloatComplexRowVector&\nFloatComplexRowVector::operator += (const FloatRowVector& a)\n{\n  octave_idx_type len = numel ();\n\n  octave_idx_type a_len = a.numel ();\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator +=\", len, a_len);\n\n  if (len == 0)\n    return *this;\n\n  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!\n\n  mx_inline_add2 (len, d, a.data ());\n  return *this;\n}\n\nFloatComplexRowVector&\nFloatComplexRowVector::operator -= (const FloatRowVector& a)\n{\n  octave_idx_type len = numel ();\n\n  octave_idx_type a_len = a.numel ();\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator -=\", len, a_len);\n\n  if (len == 0)\n    return *this;\n\n  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!\n\n  mx_inline_sub2 (len, d, a.data ());\n  return *this;\n}\n\n// row vector by matrix -> row vector\n\nFloatComplexRowVector\noperator * (const FloatComplexRowVector& v, const FloatComplexMatrix& a)\n{\n  FloatComplexRowVector retval;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  F77_INT a_nr = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (a_nr != len)\n    octave::err_nonconformant (\"operator *\", 1, len, a_nr, a_nc);\n\n  if (len == 0)\n    retval.resize (a_nc, 0.0);\n  else\n    {\n      // Transpose A to form A'*x == (x'*A)'\n\n      F77_INT ld = a_nr;\n\n      retval.resize (a_nc);\n      FloatComplex *y = retval.rwdata ();\n\n      F77_XFCN (cgemv, CGEMV, (F77_CONST_CHAR_ARG2 (\"T\", 1),\n                               a_nr, a_nc, 1.0, F77_CONST_CMPLX_ARG (a.data ()),\n                               ld, F77_CONST_CMPLX_ARG (v.data ()), 1, 0.0, F77_CMPLX_ARG (y), 1\n                               F77_CHAR_ARG_LEN (1)));\n    }\n\n  return retval;\n}\n\nFloatComplexRowVector\noperator * (const FloatRowVector& v, const FloatComplexMatrix& a)\n{\n  FloatComplexRowVector tmp (v);\n  return tmp * a;\n}\n\n// other operations\n\nFloatComplex\nFloatComplexRowVector::min () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return FloatComplex (0.0);\n\n  FloatComplex res = elem (0);\n  float absres = std::abs (res);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (std::abs (elem (i)) < absres)\n      {\n        res = elem (i);\n        absres = std::abs (res);\n      }\n\n  return res;\n}\n\nFloatComplex\nFloatComplexRowVector::max () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return FloatComplex (0.0);\n\n  FloatComplex res = elem (0);\n  float absres = std::abs (res);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (std::abs (elem (i)) > absres)\n      {\n        res = elem (i);\n        absres = std::abs (res);\n      }\n\n  return res;\n}\n\n// i/o\n\nstd::ostream&\noperator << (std::ostream& os, const FloatComplexRowVector& a)\n{\n//  int field_width = os.precision () + 7;\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    os << ' ' /* setw (field_width) */ << a.elem (i);\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, FloatComplexRowVector& a)\n{\n  octave_idx_type len = a.numel ();\n\n  if (len > 0)\n    {\n      FloatComplex tmp;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          is >> tmp;\n          if (is)\n            a.elem (i) = tmp;\n          else\n            break;\n        }\n    }\n  return is;\n}\n\n// row vector by column vector -> scalar\n\n// row vector by column vector -> scalar\n\nFloatComplex\noperator * (const FloatComplexRowVector& v, const FloatColumnVector& a)\n{\n  FloatComplexColumnVector tmp (a);\n  return v * tmp;\n}\n\nFloatComplex\noperator * (const FloatComplexRowVector& v, const FloatComplexColumnVector& a)\n{\n  FloatComplex retval (0.0, 0.0);\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator *\", len, a_len);\n\n  if (len != 0)\n    F77_FUNC (xcdotu, XCDOTU) (len, F77_CONST_CMPLX_ARG (v.data ()), 1,\n                               F77_CONST_CMPLX_ARG (a.data ()), 1, F77_CMPLX_ARG (&retval));\n\n  return retval;\n}\n\n// other operations\n\nFloatComplexRowVector\nlinspace (const FloatComplex& x1, const FloatComplex& x2, octave_idx_type n_in)\n{\n  FloatComplexRowVector retval;\n\n  if (n_in < 1)\n    return retval;\n  else if (n_in == 1)\n    {\n      retval.resize (1, x2);\n      return retval;\n    }\n  else if (x1 == x2)\n    {\n      retval.resize (n_in, x2);\n      return retval;\n    }\n\n  // Use unsigned type (guaranteed n_in > 1 at this point) so that divisions\n  // by 2 can be replaced by compiler with shift right instructions.\n  typedef std::make_unsigned<octave_idx_type>::type unsigned_octave_idx_type;\n\n  unsigned_octave_idx_type n = n_in;\n\n  // Set endpoints, rather than calculate, for maximum accuracy.\n  retval.clear (n);\n  retval.xelem (0) = x1;\n  retval.xelem (n-1) = x2;\n\n  // Construct linspace symmetrically from both ends.\n  bool isnan_delta = false;\n  FloatComplex delta = (x2 - x1) / (n - 1.0f);\n  if (octave::math::isinf (delta))\n    {\n      if (octave::math::isinf (delta.real ()))\n        delta.real (octave::numeric_limits<float>::NaN ());\n      if (octave::math::isinf (delta.imag ()))\n        delta.imag (octave::numeric_limits<float>::NaN ());\n      isnan_delta = true;\n    }\n\n  unsigned_octave_idx_type n2 = n/2;\n  for (unsigned_octave_idx_type i = 1; i < n2; i++)\n    {\n      retval.xelem (i) = x1 + static_cast<float> (i)*delta;\n      retval.xelem (n-1-i) = x2 - static_cast<float> (i)*delta;\n    }\n  if (n % 2 == 1)  // Middle element if number of elements is odd.\n    {\n      if (x1 == -x2)\n        retval.xelem (n2) = 0;\n      else\n        {\n          FloatComplex c = (x1 + x2) / 2.0f;\n          if (isnan_delta)\n            {\n              if (octave::math::isnan (delta.real ()))\n                c.real (octave::numeric_limits<float>::NaN ());\n              if (octave::math::isnan (delta.imag ()))\n                c.imag (octave::numeric_limits<float>::NaN ());\n            }\n          retval.xelem (n2) = c;\n        }\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/array/fCRowVector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fCRowVector_h)\n#define octave_fCRowVector_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"fRowVector.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API FloatComplexRowVector : public MArray<FloatComplex>\n{\n  friend class FloatComplexColumnVector;\n\npublic:\n\n  FloatComplexRowVector ()\n    : MArray<FloatComplex> (dim_vector (1, 0)) { }\n\n  explicit FloatComplexRowVector (octave_idx_type n)\n    : MArray<FloatComplex> (dim_vector (1, n)) { }\n\n  explicit FloatComplexRowVector (const dim_vector& dv)\n    : MArray<FloatComplex> (dv.as_row ()) { }\n\n  FloatComplexRowVector (octave_idx_type n, const FloatComplex& val)\n    : MArray<FloatComplex> (dim_vector (1, n), val) { }\n\n  FloatComplexRowVector (const FloatComplexRowVector& a)\n    : MArray<FloatComplex> (a) { }\n\n  FloatComplexRowVector (const MArray<FloatComplex>& a)\n    : MArray<FloatComplex> (a.as_row ()) { }\n\n  FloatComplexRowVector (const Array<FloatComplex>& a)\n    : MArray<FloatComplex> (a.as_row ()) { }\n\n  explicit FloatComplexRowVector (const FloatRowVector& a)\n    : MArray<FloatComplex> (a) { }\n\n  FloatComplexRowVector& operator = (const FloatComplexRowVector& a)\n  {\n    MArray<FloatComplex>::operator = (a);\n    return *this;\n  }\n\n  ~FloatComplexRowVector () = default;\n\n  OCTAVE_API bool operator == (const FloatComplexRowVector& a) const;\n  OCTAVE_API bool operator != (const FloatComplexRowVector& a) const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API FloatComplexRowVector&\n  insert (const FloatRowVector& a, octave_idx_type c);\n  OCTAVE_API FloatComplexRowVector&\n  insert (const FloatComplexRowVector& a, octave_idx_type c);\n\n  OCTAVE_API FloatComplexRowVector& fill (float val);\n  OCTAVE_API FloatComplexRowVector& fill (const FloatComplex& val);\n  OCTAVE_API FloatComplexRowVector&\n  fill (float val, octave_idx_type c1, octave_idx_type c2);\n  OCTAVE_API FloatComplexRowVector&\n  fill (const FloatComplex& val, octave_idx_type c1, octave_idx_type c2);\n\n  OCTAVE_API FloatComplexRowVector append (const FloatRowVector& a) const;\n  OCTAVE_API FloatComplexRowVector\n  append (const FloatComplexRowVector& a) const;\n\n  OCTAVE_API FloatComplexColumnVector hermitian () const;\n  OCTAVE_API FloatComplexColumnVector transpose () const;\n\n  friend OCTAVE_API FloatComplexRowVector\n  conj (const FloatComplexRowVector& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API FloatComplexRowVector\n  extract (octave_idx_type c1, octave_idx_type c2) const;\n\n  OCTAVE_API FloatComplexRowVector\n  extract_n (octave_idx_type c1, octave_idx_type n) const;\n\n  // row vector by row vector -> row vector operations\n\n  OCTAVE_API FloatComplexRowVector& operator += (const FloatRowVector& a);\n  OCTAVE_API FloatComplexRowVector& operator -= (const FloatRowVector& a);\n\n  // row vector by matrix -> row vector\n\n  friend OCTAVE_API FloatComplexRowVector\n  operator * (const FloatComplexRowVector& a, const FloatComplexMatrix& b);\n\n  friend OCTAVE_API FloatComplexRowVector\n  operator * (const FloatRowVector& a, const FloatComplexMatrix& b);\n\n  // other operations\n\n  OCTAVE_API FloatComplex min () const;\n  OCTAVE_API FloatComplex max () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const FloatComplexRowVector& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, FloatComplexRowVector& a);\n\n  void resize (octave_idx_type n, const FloatComplex& rfv = FloatComplex (0))\n  {\n    Array<FloatComplex>::resize (dim_vector (1, n), rfv);\n  }\n\n  void clear (octave_idx_type n)\n  { Array<FloatComplex>::clear (1, n); }\n\n};\n\n// row vector by column vector -> scalar\n\nOCTAVE_API FloatComplex\noperator * (const FloatComplexRowVector& a, const ColumnVector& b);\n\nOCTAVE_API FloatComplex\noperator * (const FloatComplexRowVector& a, const FloatComplexColumnVector& b);\n\n// other operations\n\nOCTAVE_API FloatComplexRowVector\nlinspace (const FloatComplex& x1, const FloatComplex& x2, octave_idx_type n);\n\nMARRAY_FORWARD_DEFS (MArray, FloatComplexRowVector, FloatComplex)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fColVector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"blas-proto.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// Column Vector class.\n\nbool\nFloatColumnVector::operator == (const FloatColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  if (len != a.numel ())\n    return 0;\n  return mx_inline_equal (len, data (), a.data ());\n}\n\nbool\nFloatColumnVector::operator != (const FloatColumnVector& a) const\n{\n  return !(*this == a);\n}\n\nFloatColumnVector&\nFloatColumnVector::insert (const FloatColumnVector& a, octave_idx_type r)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatColumnVector&\nFloatColumnVector::fill (float val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatColumnVector&\nFloatColumnVector::fill (float val, octave_idx_type r1, octave_idx_type r2)\n{\n  octave_idx_type len = numel ();\n\n  if (r1 < 0 || r2 < 0 || r1 >= len || r2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  if (r2 >= r1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = r1; i <= r2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatColumnVector\nFloatColumnVector::stack (const FloatColumnVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nr_insert = len;\n  FloatColumnVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nr_insert);\n  return retval;\n}\n\nFloatRowVector\nFloatColumnVector::transpose () const\n{\n  return MArray<float>::transpose ();\n}\n\nFloatColumnVector\nFloatColumnVector::abs () const\n{\n  return do_mx_unary_map<float, float, std::abs> (*this);\n}\n\nFloatColumnVector\nreal (const FloatComplexColumnVector& a)\n{\n  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_real);\n}\n\nFloatColumnVector\nimag (const FloatComplexColumnVector& a)\n{\n  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_imag);\n}\n\n// resize is the destructive equivalent for this one\n\nFloatColumnVector\nFloatColumnVector::extract (octave_idx_type r1, octave_idx_type r2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n\n  octave_idx_type new_r = r2 - r1 + 1;\n\n  FloatColumnVector result (new_r);\n\n  for (octave_idx_type i = 0; i < new_r; i++)\n    result.xelem (i) = elem (r1+i);\n\n  return result;\n}\n\nFloatColumnVector\nFloatColumnVector::extract_n (octave_idx_type r1, octave_idx_type n) const\n{\n  FloatColumnVector result (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    result.xelem (i) = elem (r1+i);\n\n  return result;\n}\n\n// matrix by column vector -> column vector operations\n\nFloatColumnVector\noperator * (const FloatMatrix& m, const FloatColumnVector& a)\n{\n  FloatColumnVector retval;\n\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  retval.clear (nr);\n\n  if (nr != 0)\n    {\n      if (nc == 0)\n        retval.fill (0.0);\n      else\n        {\n          float *y = retval.rwdata ();\n\n          F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                                   nr, nc, 1.0f, m.data (), nr,\n                                   a.data (), 1, 0.0f, y, 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n    }\n\n  return retval;\n}\n\n// diagonal matrix by column vector -> column vector operations\n\nFloatColumnVector\noperator * (const FloatDiagMatrix& m, const FloatColumnVector& a)\n{\n  FloatColumnVector retval;\n\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (nc != a_len)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_len, 1);\n\n  if (nr == 0 || nc == 0)\n    retval.resize (nr, 0.0);\n  else\n    {\n      retval.resize (nr);\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        retval.elem (i) = a.elem (i) * m.elem (i, i);\n\n      for (octave_idx_type i = a_len; i < nr; i++)\n        retval.elem (i) = 0.0;\n    }\n\n  return retval;\n}\n\n// other operations\n\nfloat\nFloatColumnVector::min () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0.0;\n\n  float res = elem (0);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (elem (i) < res)\n      res = elem (i);\n\n  return res;\n}\n\nfloat\nFloatColumnVector::max () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0.0;\n\n  float res = elem (0);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (elem (i) > res)\n      res = elem (i);\n\n  return res;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const FloatColumnVector& a)\n{\n//  int field_width = os.precision () + 7;\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    os << /* setw (field_width) << */ a.elem (i) << \"\\n\";\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, FloatColumnVector& a)\n{\n  octave_idx_type len = a.numel ();\n\n  if (len > 0)\n    {\n      float tmp;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          is >> tmp;\n          if (is)\n            a.elem (i) = tmp;\n          else\n            break;\n        }\n    }\n  return is;\n}\n"
  },
  {
    "path": "liboctave/array/fColVector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fColVector_h)\n#define octave_fColVector_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API FloatColumnVector : public MArray<float>\n{\npublic:\n\n  FloatColumnVector () : MArray<float> (dim_vector (0, 1)) { }\n\n  explicit FloatColumnVector (octave_idx_type n)\n    : MArray<float> (dim_vector (n, 1)) { }\n\n  explicit FloatColumnVector (const dim_vector& dv)\n    : MArray<float> (dv.as_column ()) { }\n\n  FloatColumnVector (octave_idx_type n, float val)\n    : MArray<float> (dim_vector (n, 1), val) { }\n\n  FloatColumnVector (const FloatColumnVector& a) : MArray<float> (a) { }\n\n  FloatColumnVector (const MArray<float>& a)\n    : MArray<float> (a.as_column ()) { }\n\n  FloatColumnVector (const Array<float>& a)\n    : MArray<float> (a.as_column ()) { }\n\n  FloatColumnVector& operator = (const FloatColumnVector& a)\n  {\n    MArray<float>::operator = (a);\n    return *this;\n  }\n\n  ~FloatColumnVector () = default;\n\n  OCTAVE_API bool operator == (const FloatColumnVector& a) const;\n  OCTAVE_API bool operator != (const FloatColumnVector& a) const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API FloatColumnVector&\n  insert (const FloatColumnVector& a, octave_idx_type r);\n\n  OCTAVE_API FloatColumnVector& fill (float val);\n  OCTAVE_API FloatColumnVector&\n  fill (float val, octave_idx_type r1, octave_idx_type r2);\n\n  OCTAVE_API FloatColumnVector stack (const FloatColumnVector& a) const;\n\n  OCTAVE_API FloatRowVector transpose () const;\n\n  friend OCTAVE_API FloatColumnVector real (const FloatComplexColumnVector& a);\n  friend OCTAVE_API FloatColumnVector imag (const FloatComplexColumnVector& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API FloatColumnVector\n  extract (octave_idx_type r1, octave_idx_type r2) const;\n\n  OCTAVE_API FloatColumnVector\n  extract_n (octave_idx_type r1, octave_idx_type n) const;\n\n  // matrix by column vector -> column vector operations\n\n  friend OCTAVE_API FloatColumnVector\n  operator * (const FloatMatrix& a, const FloatColumnVector& b);\n\n  // diagonal matrix by column vector -> column vector operations\n\n  friend OCTAVE_API FloatColumnVector\n  operator * (const FloatDiagMatrix& a, const FloatColumnVector& b);\n\n  // other operations\n\n  OCTAVE_API float min () const;\n  OCTAVE_API float max () const;\n\n  OCTAVE_API FloatColumnVector abs () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const FloatColumnVector& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, FloatColumnVector& a);\n\n  void resize (octave_idx_type n, const float& rfv = 0)\n  {\n    Array<float>::resize (dim_vector (n, 1), rfv);\n  }\n\n  void clear (octave_idx_type n)\n  { Array<float>::clear (n, 1); }\n\n};\n\n// Publish externally used friend functions.\n\nextern OCTAVE_API FloatColumnVector real (const FloatComplexColumnVector& a);\nextern OCTAVE_API FloatColumnVector imag (const FloatComplexColumnVector& a);\n\nMARRAY_FORWARD_DEFS (MArray, FloatColumnVector, float)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fDiagMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// Diagonal Matrix class.\n\nbool\nFloatDiagMatrix::operator == (const FloatDiagMatrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return 0;\n\n  return mx_inline_equal (length (), data (), a.data ());\n}\n\nbool\nFloatDiagMatrix::operator != (const FloatDiagMatrix& a) const\n{\n  return !(*this == a);\n}\n\nFloatDiagMatrix&\nFloatDiagMatrix::fill (float val)\n{\n  for (octave_idx_type i = 0; i < length (); i++)\n    elem (i, i) = val;\n  return *this;\n}\n\nFloatDiagMatrix&\nFloatDiagMatrix::fill (float val, octave_idx_type beg, octave_idx_type end)\n{\n  if (beg < 0 || end >= length () || end < beg)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = beg; i <= end; i++)\n    elem (i, i) = val;\n\n  return *this;\n}\n\nFloatDiagMatrix&\nFloatDiagMatrix::fill (const FloatColumnVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nFloatDiagMatrix&\nFloatDiagMatrix::fill (const FloatRowVector& a)\n{\n  octave_idx_type len = length ();\n  if (a.numel () != len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (i, i) = a.elem (i);\n\n  return *this;\n}\n\nFloatDiagMatrix&\nFloatDiagMatrix::fill (const FloatColumnVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nFloatDiagMatrix&\nFloatDiagMatrix::fill (const FloatRowVector& a, octave_idx_type beg)\n{\n  octave_idx_type a_len = a.numel ();\n  if (beg < 0 || beg + a_len >= length ())\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  for (octave_idx_type i = 0; i < a_len; i++)\n    elem (i+beg, i+beg) = a.elem (i);\n\n  return *this;\n}\n\nFloatDiagMatrix\nFloatDiagMatrix::abs () const\n{\n  return FloatDiagMatrix (extract_diag ().abs (), rows (), columns ());\n}\n\nFloatDiagMatrix\nreal (const FloatComplexDiagMatrix& a)\n{\n  return FloatDiagMatrix (real (a.extract_diag ()), a.rows (), a.columns ());\n}\n\nFloatDiagMatrix\nimag (const FloatComplexDiagMatrix& a)\n{\n  return FloatDiagMatrix (imag (a.extract_diag ()), a.rows (), a.columns ());\n}\n\nFloatMatrix\nFloatDiagMatrix::extract (octave_idx_type r1, octave_idx_type c1,\n                          octave_idx_type r2, octave_idx_type c2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  octave_idx_type new_r = r2 - r1 + 1;\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  FloatMatrix result (new_r, new_c);\n\n  for (octave_idx_type j = 0; j < new_c; j++)\n    for (octave_idx_type i = 0; i < new_r; i++)\n      result.elem (i, j) = elem (r1+i, c1+j);\n\n  return result;\n}\n\n// extract row or column i.\n\nFloatRowVector\nFloatDiagMatrix::row (octave_idx_type i) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (i < 0 || i >= r)\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n\n  FloatRowVector retval (c, 0.0);\n  if (r <= c || i < c)\n    retval.elem (i) = elem (i, i);\n\n  return retval;\n}\n\nFloatRowVector\nFloatDiagMatrix::row (char *s) const\n{\n  if (! s)\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n\n  char c = s[0];\n  if (c == 'f' || c == 'F')\n    return row (static_cast<octave_idx_type> (0));\n  else if (c == 'l' || c == 'L')\n    return row (rows () - 1);\n  else\n    (*current_liboctave_error_handler) (\"invalid row selection\");\n}\n\nFloatColumnVector\nFloatDiagMatrix::column (octave_idx_type i) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  if (i < 0 || i >= c)\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n\n  FloatColumnVector retval (r, 0.0);\n  if (r >= c || i < r)\n    retval.elem (i) = elem (i, i);\n\n  return retval;\n}\n\nFloatColumnVector\nFloatDiagMatrix::column (char *s) const\n{\n  if (! s)\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n\n  char c = s[0];\n  if (c == 'f' || c == 'F')\n    return column (static_cast<octave_idx_type> (0));\n  else if (c == 'l' || c == 'L')\n    return column (cols () - 1);\n  else\n    (*current_liboctave_error_handler) (\"invalid column selection\");\n}\n\nFloatDiagMatrix\nFloatDiagMatrix::inverse () const\n{\n  octave_idx_type info;\n  return inverse (info);\n}\n\nFloatDiagMatrix\nFloatDiagMatrix::inverse (octave_idx_type& info) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  octave_idx_type len = length ();\n  if (r != c)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  FloatDiagMatrix retval (r, c);\n\n  info = 0;\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      if (elem (i, i) == 0.0)\n        retval.elem (i, i) = octave::numeric_limits<float>::Inf ();\n      else\n        retval.elem (i, i) = 1.0 / elem (i, i);\n    }\n\n  return retval;\n}\n\nFloatDiagMatrix\nFloatDiagMatrix::pseudo_inverse (float tol) const\n{\n  octave_idx_type r = rows ();\n  octave_idx_type c = cols ();\n  octave_idx_type len = length ();\n\n  FloatDiagMatrix retval (c, r);\n\n  for (octave_idx_type i = 0; i < len; i++)\n    {\n      float val = std::abs (elem (i, i));\n      if (val < tol || val == 0.0f)\n        retval.elem (i, i) = 0.0f;\n      else\n        retval.elem (i, i) = 1.0f / elem (i, i);\n    }\n\n  return retval;\n}\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\nFloatDiagMatrix\noperator * (const FloatDiagMatrix& a, const FloatDiagMatrix& b)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  FloatDiagMatrix c (a_nr, b_nc);\n\n  octave_idx_type len = c.length ();\n  octave_idx_type lenm = (len < a_nc ? len : a_nc);\n\n  for (octave_idx_type i = 0; i < lenm; i++)\n    c.dgxelem (i) = a.dgelem (i) * b.dgelem (i);\n  for (octave_idx_type i = lenm; i < len; i++)\n    c.dgxelem (i) = 0.0f;\n\n  return c;\n}\n\n// other operations\n\nFloatDET\nFloatDiagMatrix::determinant () const\n{\n  FloatDET det (1.0f);\n  if (rows () != cols ())\n    (*current_liboctave_error_handler) (\"determinant requires square matrix\");\n\n  octave_idx_type len = length ();\n  for (octave_idx_type i = 0; i < len; i++)\n    det *= elem (i, i);\n\n  return det;\n}\n\nfloat\nFloatDiagMatrix::rcond () const\n{\n  FloatColumnVector av = extract_diag (0).map<float> (fabsf);\n  float amx = av.max ();\n  float amn = av.min ();\n  return amx == 0 ? 0.0f : amn / amx;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const FloatDiagMatrix& a)\n{\n//  int field_width = os.precision () + 7;\n\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    {\n      for (octave_idx_type j = 0; j < a.cols (); j++)\n        {\n          if (i == j)\n            os << ' ' /* setw (field_width) */ << a.elem (i, i);\n          else\n            os << ' ' /* setw (field_width) */ << 0.0;\n        }\n      os << \"\\n\";\n    }\n  return os;\n}\n"
  },
  {
    "path": "liboctave/array/fDiagMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fDiagMatrix_h)\n#define octave_fDiagMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"DET.h\"\n#include \"MDiagArray2.h\"\n#include \"fColVector.h\"\n#include \"fRowVector.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API FloatDiagMatrix : public MDiagArray2<float>\n{\npublic:\n\n  typedef FloatMatrix full_matrix_type;\n\n  FloatDiagMatrix () = default;\n\n  FloatDiagMatrix (const FloatDiagMatrix& a) = default;\n\n  FloatDiagMatrix& operator = (const FloatDiagMatrix& a) = default;\n\n  ~FloatDiagMatrix () = default;\n\n  FloatDiagMatrix (octave_idx_type r, octave_idx_type c)\n    : MDiagArray2<float> (r, c) { }\n\n  FloatDiagMatrix (octave_idx_type r, octave_idx_type c, float val)\n    : MDiagArray2<float> (r, c, val) { }\n\n  FloatDiagMatrix (const MDiagArray2<float>& a) : MDiagArray2<float> (a) { }\n\n  template <typename U>\n  FloatDiagMatrix (const DiagArray2<U>& a) : MDiagArray2<float> (a) { }\n\n  explicit FloatDiagMatrix (const Array<double>& a) : MDiagArray2<float> (a) { }\n\n  FloatDiagMatrix (const Array<float>& a, octave_idx_type r, octave_idx_type c)\n    : MDiagArray2<float> (a, r, c) { }\n\n  OCTAVE_API bool operator == (const FloatDiagMatrix& a) const;\n  OCTAVE_API bool operator != (const FloatDiagMatrix& a) const;\n\n  OCTAVE_API FloatDiagMatrix& fill (float val);\n  OCTAVE_API FloatDiagMatrix&\n  fill (float val, octave_idx_type beg, octave_idx_type end);\n  OCTAVE_API FloatDiagMatrix& fill (const FloatColumnVector& a);\n  OCTAVE_API FloatDiagMatrix& fill (const FloatRowVector& a);\n  OCTAVE_API FloatDiagMatrix&\n  fill (const FloatColumnVector& a, octave_idx_type beg);\n  OCTAVE_API FloatDiagMatrix&\n  fill (const FloatRowVector& a, octave_idx_type beg);\n\n  FloatDiagMatrix transpose () const\n  { return MDiagArray2<float>::transpose (); }\n\n  OCTAVE_API FloatDiagMatrix abs () const;\n\n  friend OCTAVE_API FloatDiagMatrix real (const FloatComplexDiagMatrix& a);\n  friend OCTAVE_API FloatDiagMatrix imag (const FloatComplexDiagMatrix& a);\n\n  // resize is the destructive analog for this one\n\n  OCTAVE_API FloatMatrix\n  extract (octave_idx_type r1, octave_idx_type c1,\n           octave_idx_type r2, octave_idx_type c2) const;\n\n  // extract row or column i.\n\n  OCTAVE_API FloatRowVector row (octave_idx_type i) const;\n  OCTAVE_API FloatRowVector row (char *s) const;\n\n  OCTAVE_API FloatColumnVector column (octave_idx_type i) const;\n  OCTAVE_API FloatColumnVector column (char *s) const;\n\n  OCTAVE_API FloatDiagMatrix inverse () const;\n  OCTAVE_API FloatDiagMatrix inverse (octave_idx_type& info) const;\n  OCTAVE_API FloatDiagMatrix pseudo_inverse (float tol = 0.0f) const;\n\n  // other operations\n\n  FloatColumnVector extract_diag (octave_idx_type k = 0) const\n  { return MDiagArray2<float>::extract_diag (k); }\n\n  OCTAVE_API FloatDET determinant () const;\n  OCTAVE_API float rcond () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const FloatDiagMatrix& a);\n\n};\n\nOCTAVE_API FloatDiagMatrix real (const FloatComplexDiagMatrix& a);\nOCTAVE_API FloatDiagMatrix imag (const FloatComplexDiagMatrix& a);\n\n// diagonal matrix by diagonal matrix -> diagonal matrix operations\n\nOCTAVE_API FloatDiagMatrix\noperator * (const FloatDiagMatrix& a, const FloatDiagMatrix& b);\n\nMDIAGARRAY2_FORWARD_DEFS (MDiagArray2, FloatDiagMatrix, float)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fMatrix.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <cmath>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"DET.h\"\n#include \"PermMatrix.h\"\n#include \"blas-proto.h\"\n#include \"boolMatrix.h\"\n#include \"byte-swap.h\"\n#include \"chMatrix.h\"\n#include \"chol.h\"\n#include \"fCColVector.h\"\n#include \"fCMatrix.h\"\n#include \"fColVector.h\"\n#include \"fDiagMatrix.h\"\n#include \"fMatrix.h\"\n#include \"fMatrix.h\"\n#include \"fNDArray.h\"\n#include \"fRowVector.h\"\n#include \"lapack-proto.h\"\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"mx-fdm-fm.h\"\n#include \"mx-fm-fdm.h\"\n#include \"mx-inlines.cc\"\n#include \"mx-op-defs.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-norm.h\"\n#include \"quit.h\"\n#include \"schur.h\"\n#include \"svd.h\"\n\n// Matrix class.\n\nFloatMatrix::FloatMatrix (const FloatRowVector& rv)\n  : FloatNDArray (rv)\n{ }\n\nFloatMatrix::FloatMatrix (const FloatColumnVector& cv)\n  : FloatNDArray (cv)\n{ }\n\nFloatMatrix::FloatMatrix (const FloatDiagMatrix& a)\n  : FloatNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nFloatMatrix::FloatMatrix (const MDiagArray2<float>& a)\n  : FloatNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nFloatMatrix::FloatMatrix (const DiagArray2<float>& a)\n  : FloatNDArray (a.dims (), 0.0)\n{\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) = a.elem (i, i);\n}\n\nFloatMatrix::FloatMatrix (const PermMatrix& a)\n  : FloatNDArray (a.dims (), 0.0)\n{\n  const Array<octave_idx_type> ia (a.col_perm_vec ());\n  octave_idx_type len = a.rows ();\n  for (octave_idx_type i = 0; i < len; i++)\n    elem (ia(i), i) = 1.0;\n}\n\n// FIXME: could we use a templated mixed-type copy function here?\n\nFloatMatrix::FloatMatrix (const boolMatrix& a)\n  : FloatNDArray (a)\n{ }\n\nFloatMatrix::FloatMatrix (const charMatrix& a)\n  : FloatNDArray (a.dims ())\n{\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    for (octave_idx_type j = 0; j < a.cols (); j++)\n      elem (i, j) = static_cast<unsigned char> (a.elem (i, j));\n}\n\nbool\nFloatMatrix::operator == (const FloatMatrix& a) const\n{\n  if (rows () != a.rows () || cols () != a.cols ())\n    return false;\n\n  return mx_inline_equal (numel (), data (), a.data ());\n}\n\nbool\nFloatMatrix::operator != (const FloatMatrix& a) const\n{\n  return !(*this == a);\n}\n\nbool\nFloatMatrix::issymmetric () const\n{\n  if (issquare () && rows () > 0)\n    {\n      for (octave_idx_type i = 0; i < rows (); i++)\n        for (octave_idx_type j = i+1; j < cols (); j++)\n          if (elem (i, j) != elem (j, i))\n            return false;\n\n      return true;\n    }\n\n  return false;\n}\n\nFloatMatrix&\nFloatMatrix::insert (const FloatMatrix& a,\n                     octave_idx_type r, octave_idx_type c)\n{\n  FloatNDArray::insert (a, r, c);\n  return *this;\n}\n\nFloatMatrix&\nFloatMatrix::insert (const FloatRowVector& a,\n                     octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r, c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatMatrix&\nFloatMatrix::insert (const FloatColumnVector& a,\n                     octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatMatrix&\nFloatMatrix::insert (const FloatDiagMatrix& a,\n                     octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);\n\n  octave_idx_type a_len = a.length ();\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (r+i, c+i) = a.elem (i, i);\n    }\n\n  return *this;\n}\n\nFloatMatrix&\nFloatMatrix::fill (float val)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = 0; i < nr; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nFloatMatrix&\nFloatMatrix::fill (float val, octave_idx_type r1, octave_idx_type c1,\n                   octave_idx_type r2, octave_idx_type c2)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0\n      || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (r2 >= r1 && c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type j = c1; j <= c2; j++)\n        for (octave_idx_type i = r1; i <= r2; i++)\n          xelem (i, j) = val;\n    }\n\n  return *this;\n}\n\nFloatMatrix\nFloatMatrix::append (const FloatMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::append (const FloatRowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != 1)\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatMatrix retval (nr, nc + a.numel ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::append (const FloatColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.numel ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatMatrix retval (nr, nc + 1);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::append (const FloatDiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nr != a.rows ())\n    (*current_liboctave_error_handler) (\"row dimension mismatch for append\");\n\n  octave_idx_type nc_insert = nc;\n  FloatMatrix retval (nr, nc + a.cols ());\n  retval.insert (*this, 0, 0);\n  retval.insert (a, 0, nc_insert);\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::stack (const FloatMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::stack (const FloatRowVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.numel ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatMatrix retval (nr + 1, nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::stack (const FloatColumnVector& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != 1)\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatMatrix retval (nr + a.numel (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::stack (const FloatDiagMatrix& a) const\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n  if (nc != a.cols ())\n    (*current_liboctave_error_handler) (\"column dimension mismatch for stack\");\n\n  octave_idx_type nr_insert = nr;\n  FloatMatrix retval (nr + a.rows (), nc);\n  retval.insert (*this, 0, 0);\n  retval.insert (a, nr_insert, 0);\n  return retval;\n}\n\nFloatMatrix\nreal (const FloatComplexMatrix& a)\n{\n  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_real);\n}\n\nFloatMatrix\nimag (const FloatComplexMatrix& a)\n{\n  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_imag);\n}\n\nFloatMatrix\nFloatMatrix::extract (octave_idx_type r1, octave_idx_type c1,\n                      octave_idx_type r2, octave_idx_type c2) const\n{\n  if (r1 > r2) { std::swap (r1, r2); }\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  return index (octave::idx_vector (r1, r2+1), octave::idx_vector (c1, c2+1));\n}\n\nFloatMatrix\nFloatMatrix::extract_n (octave_idx_type r1, octave_idx_type c1,\n                        octave_idx_type nr, octave_idx_type nc) const\n{\n  return index (octave::idx_vector (r1, r1 + nr), octave::idx_vector (c1, c1 + nc));\n}\n\n// extract row or column i.\n\nFloatRowVector\nFloatMatrix::row (octave_idx_type i) const\n{\n  return index (octave::idx_vector (i), octave::idx_vector::colon);\n}\n\nFloatColumnVector\nFloatMatrix::column (octave_idx_type i) const\n{\n  return index (octave::idx_vector::colon, octave::idx_vector (i));\n}\n\n// Local function to calculate the 1-norm.\nstatic\nfloat\nnorm1 (const FloatMatrix& a)\n{\n  float anorm = 0.0;\n  FloatRowVector colsum = a.abs ().sum ().row (0);\n\n  for (octave_idx_type i = 0; i < colsum.numel (); i++)\n    {\n      float sum = colsum.xelem (i);\n      if (octave::math::isinf (sum) || octave::math::isnan (sum))\n        {\n          anorm = sum;  // Pass Inf or NaN to output\n          break;\n        }\n      else\n        anorm = std::max (anorm, sum);\n    }\n\n  return anorm;\n}\n\n// Local function to check if matrix is singular based on rcond.\nstatic inline\nbool\nis_singular (const float rcond)\n{\n  return (std::abs (rcond) <= std::numeric_limits<float>::epsilon ());\n}\n\nFloatMatrix\nFloatMatrix::inverse () const\n{\n  octave_idx_type info;\n  float rcon;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, false, false);\n}\n\nFloatMatrix\nFloatMatrix::inverse (octave_idx_type& info) const\n{\n  float rcon;\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, false, false);\n}\n\nFloatMatrix\nFloatMatrix::inverse (octave_idx_type& info, float& rcon,\n                      bool force, bool calc_cond) const\n{\n  MatrixType mattype (*this);\n  return inverse (mattype, info, rcon, force, calc_cond);\n}\n\nFloatMatrix\nFloatMatrix::inverse (MatrixType& mattype) const\n{\n  octave_idx_type info;\n  float rcon;\n  return inverse (mattype, info, rcon, false, false);\n}\n\nFloatMatrix\nFloatMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const\n{\n  float rcon;\n  return inverse (mattype, info, rcon, false, false);\n}\n\nFloatMatrix\nFloatMatrix::tinverse (MatrixType& mattype, octave_idx_type& info, float& rcon,\n                       bool force, bool calc_cond) const\n{\n  FloatMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc || nr == 0 || nc == 0)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  int typ = mattype.type ();\n  char uplo = (typ == MatrixType::Lower ? 'L' : 'U');\n  char udiag = 'N';\n  retval = *this;\n  float *tmp_data = retval.rwdata ();\n\n  F77_INT tmp_info = 0;\n\n  F77_XFCN (strtri, STRTRI, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                             F77_CONST_CHAR_ARG2 (&udiag, 1),\n                             nr, tmp_data, nr, tmp_info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  info = tmp_info;\n\n  // Throw away extra info LAPACK gives so as to not change output.\n  rcon = 0.0;\n  if (info != 0)\n    info = -1;\n  else if (calc_cond)\n    {\n      F77_INT dtrcon_info = 0;\n      char job = '1';\n\n      OCTAVE_LOCAL_BUFFER (float, work, 3 * nr);\n      OCTAVE_LOCAL_BUFFER (F77_INT, iwork, nr);\n\n      F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                 F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                 F77_CONST_CHAR_ARG2 (&udiag, 1),\n                                 nr, tmp_data, nr, rcon,\n                                 work, iwork, dtrcon_info\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (dtrcon_info != 0)\n        info = -1;\n    }\n\n  if (info == -1 && ! force)\n    retval = *this; // Restore matrix contents.\n\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::finverse (MatrixType& mattype, octave_idx_type& info, float& rcon,\n                       bool force, bool calc_cond) const\n{\n  FloatMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc || nr == 0 || nc == 0)\n    (*current_liboctave_error_handler) (\"inverse requires square matrix\");\n\n  Array<F77_INT> ipvt (dim_vector (nr, 1));\n  F77_INT *pipvt = ipvt.rwdata ();\n\n  retval = *this;\n  float *tmp_data = retval.rwdata ();\n\n  Array<float> z (dim_vector (1, 1));\n  F77_INT lwork = -1;\n\n  F77_INT tmp_info = 0;\n\n  // Query the optimum work array size.\n  F77_XFCN (sgetri, SGETRI, (nc, tmp_data, nr, pipvt,\n                             z.rwdata (), lwork, tmp_info));\n\n  lwork = static_cast<F77_INT> (z(0));\n  lwork = (lwork < 4 * nc ? 4 * nc : lwork);\n  z.resize (dim_vector (lwork, 1));\n  float *pz = z.rwdata ();\n\n  info = 0;\n  tmp_info = 0;\n\n  // Calculate the norm of the matrix for later use when determining rcon.\n  float anorm;\n  if (calc_cond)\n    anorm = norm1 (retval);\n\n  F77_XFCN (sgetrf, SGETRF, (nc, nc, tmp_data, nr, pipvt, tmp_info));\n\n  info = tmp_info;\n\n  // Throw away extra info LAPACK gives so as to not change output.\n  rcon = 0.0;\n  if (info != 0)\n    info = -1;\n  else if (calc_cond)\n    {\n      if (octave::math::isnan (anorm))\n        rcon = octave::numeric_limits<float>::NaN ();\n      else\n        {\n          F77_INT sgecon_info = 0;\n\n          // Now calculate the condition number for non-singular matrix.\n          char job = '1';\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n          F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                     nc, tmp_data, nr, anorm,\n                                     rcon, pz, piz, sgecon_info\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (sgecon_info != 0)\n            info = -1;\n        }\n    }\n\n  if (info == -1 && ! force)\n    retval = *this; // Restore matrix contents.\n  else\n    {\n      F77_INT dgetri_info = 0;\n\n      F77_XFCN (sgetri, SGETRI, (nc, tmp_data, nr, pipvt,\n                                 pz, lwork, dgetri_info));\n\n      if (dgetri_info != 0)\n        info = -1;\n    }\n\n  if (info != 0)\n    mattype.mark_as_rectangular ();\n\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::inverse (MatrixType& mattype, octave_idx_type& info, float& rcon,\n                      bool force, bool calc_cond) const\n{\n  int typ = mattype.type (false);\n  FloatMatrix ret;\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  if (typ == MatrixType::Diagonal)  // a scalar is classified as Diagonal.\n    {\n      ret = 1 / (*this);\n      if (calc_cond)\n        {\n          float scalar = this->elem (0);\n          if (octave::math::isfinite (scalar) && scalar != 0)\n            rcon = 1.0f;\n          else if (octave::math::isinf (scalar) || scalar == 0)\n            rcon = 0.0f;\n          else\n            rcon = octave::numeric_limits<float>::NaN ();\n        }\n    }\n  else if (typ == MatrixType::Upper || typ == MatrixType::Lower)\n    ret = tinverse (mattype, info, rcon, force, calc_cond);\n  else\n    {\n      if (mattype.ishermitian ())\n        {\n          octave::math::chol<FloatMatrix> chol (*this, info, true, calc_cond);\n          if (info == 0)\n            {\n              if (calc_cond)\n                rcon = chol.rcond ();\n              else\n                rcon = 1.0;\n              ret = chol.inverse ();\n            }\n          else\n            mattype.mark_as_unsymmetric ();\n        }\n\n      if (! mattype.ishermitian ())\n        ret = finverse (mattype, info, rcon, force, calc_cond);\n\n      if ((calc_cond || mattype.ishermitian ()) && rcon == 0.0)\n        ret = FloatMatrix (rows (), columns (),\n                           octave::numeric_limits<float>::Inf ());\n    }\n\n  return ret;\n}\n\nFloatMatrix\nFloatMatrix::pseudo_inverse (float tol) const\n{\n  octave::math::svd<FloatMatrix> result (*this,\n                                         octave::math::svd<FloatMatrix>::Type::economy);\n\n  FloatDiagMatrix S = result.singular_values ();\n  FloatMatrix U = result.left_singular_matrix ();\n  FloatMatrix V = result.right_singular_matrix ();\n\n  FloatColumnVector sigma = S.extract_diag ();\n\n  octave_idx_type r = sigma.numel () - 1;\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (tol <= 0.0)\n    {\n      tol = std::max (nr, nc) * sigma.elem (0)\n            * std::numeric_limits<float>::epsilon ();\n\n      if (tol == 0)\n        tol = std::numeric_limits<float>::min ();\n    }\n\n  while (r >= 0 && sigma.elem (r) < tol)\n    r--;\n\n  if (r < 0)\n    return FloatMatrix (nc, nr, 0.0);\n  else\n    {\n      FloatMatrix Ur = U.extract (0, 0, nr-1, r);\n      FloatDiagMatrix D = FloatDiagMatrix (sigma.extract (0, r)).inverse ();\n      FloatMatrix Vr = V.extract (0, 0, nc-1, r);\n      return Vr * D * Ur.transpose ();\n    }\n}\n\n#if defined (HAVE_FFTW)\n\nFloatComplexMatrix\nFloatMatrix::fourier () const\n{\n  std::size_t nr = rows ();\n  std::size_t nc = cols ();\n\n  FloatComplexMatrix retval (nr, nc);\n\n  std::size_t npts, nsamples;\n\n  if (nr == 1 || nc == 1)\n    {\n      npts = (nr > nc ? nr : nc);\n      nsamples = 1;\n    }\n  else\n    {\n      npts = nr;\n      nsamples = nc;\n    }\n\n  const float *in (data ());\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::fft (in, out, npts, nsamples);\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatMatrix::ifourier () const\n{\n  std::size_t nr = rows ();\n  std::size_t nc = cols ();\n\n  FloatComplexMatrix retval (nr, nc);\n\n  std::size_t npts, nsamples;\n\n  if (nr == 1 || nc == 1)\n    {\n      npts = (nr > nc ? nr : nc);\n      nsamples = 1;\n    }\n  else\n    {\n      npts = nr;\n      nsamples = nc;\n    }\n\n  FloatComplexMatrix tmp (*this);\n  FloatComplex *in (tmp.rwdata ());\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::ifft (in, out, npts, nsamples);\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatMatrix::fourier2d () const\n{\n  dim_vector dv (rows (), cols ());\n\n  const float *in = data ();\n  FloatComplexMatrix retval (rows (), cols ());\n  octave::fftw::fftNd (in, retval.rwdata (), 2, dv);\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatMatrix::ifourier2d () const\n{\n  dim_vector dv (rows (), cols ());\n\n  FloatComplexMatrix retval (*this);\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::ifftNd (out, out, 2, dv);\n\n  return retval;\n}\n\n#else\n\nFloatComplexMatrix\nFloatMatrix::fourier () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexMatrix ();\n}\n\nFloatComplexMatrix\nFloatMatrix::ifourier () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexMatrix ();\n}\n\nFloatComplexMatrix\nFloatMatrix::fourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexMatrix ();\n}\n\nFloatComplexMatrix\nFloatMatrix::ifourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexMatrix ();\n}\n\n#endif\n\nFloatDET\nFloatMatrix::determinant () const\n{\n  octave_idx_type info;\n  float rcon;\n  return determinant (info, rcon, 0);\n}\n\nFloatDET\nFloatMatrix::determinant (octave_idx_type& info) const\n{\n  float rcon;\n  return determinant (info, rcon, 0);\n}\n\nFloatDET\nFloatMatrix::determinant (octave_idx_type& info, float& rcon,\n                          bool calc_cond) const\n{\n  MatrixType mattype (*this);\n  return determinant (mattype, info, rcon, calc_cond);\n}\n\nFloatDET\nFloatMatrix::determinant (MatrixType& mattype,\n                          octave_idx_type& info, float& rcon,\n                          bool calc_cond) const\n{\n  FloatDET retval (1.0);\n\n  info = 0;\n  rcon = 0.0;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"matrix must be square\");\n\n  int typ = mattype.type ();\n\n  // Even though the matrix is marked as singular (Rectangular), we may\n  // still get a useful number from the LU factorization, because it always\n  // completes.\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n  else if (typ == MatrixType::Rectangular)\n    typ = MatrixType::Full;\n\n  if (typ == MatrixType::Lower || typ == MatrixType::Upper)\n    {\n      for (F77_INT i = 0; i < nc; i++)\n        retval *= elem (i, i);\n    }\n  else if (typ == MatrixType::Hermitian)\n    {\n      FloatMatrix atmp = *this;\n      float *tmp_data = atmp.rwdata ();\n\n      // Calculate the norm of the matrix for later use when determining rcon.\n      float anorm;\n      if (calc_cond)\n        anorm = norm1 (*this);\n\n      F77_INT tmp_info = 0;\n\n      char job = 'L';\n      F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                 tmp_data, nr, tmp_info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      info = tmp_info;\n\n      if (info != 0)\n        {\n          rcon = 0.0;\n          mattype.mark_as_unsymmetric ();\n          typ = MatrixType::Full;\n        }\n      else\n        {\n          if (calc_cond)\n            {\n              Array<float> z (dim_vector (3 * nc, 1));\n              float *pz = z.rwdata ();\n              Array<F77_INT> iz (dim_vector (nc, 1));\n              F77_INT *piz = iz.rwdata ();\n\n              F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                         nr, tmp_data, nr, anorm,\n                                         rcon, pz, piz, tmp_info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n\n              if (info != 0)\n                rcon = 0.0;\n            }\n\n          for (F77_INT i = 0; i < nc; i++)\n            retval *= atmp(i, i);\n\n          retval = retval.square ();\n        }\n    }\n  else if (typ != MatrixType::Full)\n    (*current_liboctave_error_handler) (\"det: invalid dense matrix type\");\n\n  if (typ == MatrixType::Full)\n    {\n      Array<F77_INT> ipvt (dim_vector (nr, 1));\n      F77_INT *pipvt = ipvt.rwdata ();\n\n      FloatMatrix atmp = *this;\n      float *tmp_data = atmp.rwdata ();\n\n      info = 0;\n      F77_INT tmp_info = 0;\n\n      // Calculate the norm of the matrix for later use when determining rcon.\n      float anorm;\n      if (calc_cond)\n        anorm = norm1 (*this);\n\n      F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, tmp_info));\n\n      info = tmp_info;\n\n      // Throw away extra info LAPACK gives so as to not change output.\n      rcon = 0.0;\n      if (info != 0)\n        {\n          info = -1;\n          retval = FloatDET ();\n        }\n      else\n        {\n          if (calc_cond)\n            {\n              // Now calc the condition number for non-singular matrix.\n              char job = '1';\n              Array<float> z (dim_vector (4 * nc, 1));\n              float *pz = z.rwdata ();\n              Array<F77_INT> iz (dim_vector (nc, 1));\n              F77_INT *piz = iz.rwdata ();\n\n              F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                         nc, tmp_data, nr, anorm,\n                                         rcon, pz, piz, tmp_info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n            }\n\n          if (info != 0)\n            {\n              info = -1;\n              retval = FloatDET ();\n            }\n          else\n            {\n              for (F77_INT i = 0; i < nc; i++)\n                {\n                  float c = atmp(i, i);\n                  retval *= (ipvt(i) != (i+1)) ? -c : c;\n                }\n            }\n        }\n    }\n\n  return retval;\n}\n\nfloat\nFloatMatrix::rcond () const\n{\n  MatrixType mattype (*this);\n  return rcond (mattype);\n}\n\nfloat\nFloatMatrix::rcond (MatrixType& mattype) const\n{\n  float rcon = octave::numeric_limits<float>::NaN ();\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"matrix must be square\");\n\n  if (nr == 0 || nc == 0)\n    rcon = octave::numeric_limits<float>::Inf ();\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ == MatrixType::Unknown)\n        typ = mattype.type (*this);\n\n      // Only calculate the condition number for LU/Cholesky\n      if (typ == MatrixType::Upper)\n        {\n          const float *tmp_data = data ();\n          F77_INT info = 0;\n          char norm = '1';\n          char uplo = 'U';\n          char dia = 'N';\n\n          Array<float> z (dim_vector (3 * nc, 1));\n          float *pz = z.rwdata ();\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n\n          F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, tmp_data, nr, rcon,\n                                     pz, piz, info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (info != 0)\n            rcon = 0.0;\n        }\n      else if (typ == MatrixType::Permuted_Upper)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n      else if (typ == MatrixType::Lower)\n        {\n          const float *tmp_data = data ();\n          F77_INT info = 0;\n          char norm = '1';\n          char uplo = 'L';\n          char dia = 'N';\n\n          Array<float> z (dim_vector (3 * nc, 1));\n          float *pz = z.rwdata ();\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n\n          F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                     F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                     F77_CONST_CHAR_ARG2 (&dia, 1),\n                                     nr, tmp_data, nr, rcon,\n                                     pz, piz, info\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)\n                                     F77_CHAR_ARG_LEN (1)));\n\n          if (info != 0)\n            rcon = 0.0;\n        }\n      else if (typ == MatrixType::Permuted_Lower)\n        (*current_liboctave_error_handler)\n          (\"permuted triangular matrix not implemented\");\n      else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n        {\n          float anorm = -1.0;\n\n          if (typ == MatrixType::Hermitian)\n            {\n              F77_INT info = 0;\n              char job = 'L';\n\n              FloatMatrix atmp = *this;\n              float *tmp_data = atmp.rwdata ();\n\n              anorm = norm1 (atmp);\n\n              F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                         tmp_data, nr, info\n                                         F77_CHAR_ARG_LEN (1)));\n\n              if (info != 0)\n                {\n                  rcon = 0.0;\n                  mattype.mark_as_unsymmetric ();\n                  typ = MatrixType::Full;\n                }\n              else\n                {\n                  Array<float> z (dim_vector (3 * nc, 1));\n                  float *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nc, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, tmp_data, nr, anorm,\n                                             rcon, pz, piz, info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  if (info != 0)\n                    rcon = 0.0;\n                }\n            }\n\n          if (typ == MatrixType::Full)\n            {\n              F77_INT info = 0;\n\n              FloatMatrix atmp = *this;\n              float *tmp_data = atmp.rwdata ();\n\n              Array<F77_INT> ipvt (dim_vector (nr, 1));\n              F77_INT *pipvt = ipvt.rwdata ();\n\n              if (anorm < 0.0)\n                anorm = norm1 (atmp);\n\n              Array<float> z (dim_vector (4 * nc, 1));\n              float *pz = z.rwdata ();\n              Array<F77_INT> iz (dim_vector (nc, 1));\n              F77_INT *piz = iz.rwdata ();\n\n              F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, info));\n\n              if (info != 0)\n                {\n                  rcon = 0.0;\n                  mattype.mark_as_rectangular ();\n                }\n              else\n                {\n                  char job = '1';\n                  F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nc, tmp_data, nr, anorm,\n                                             rcon, pz, piz, info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  if (info != 0)\n                    rcon = 0.0;\n                }\n            }\n        }\n      else\n        rcon = 0.0;\n    }\n\n  return rcon;\n}\n\nFloatMatrix\nFloatMatrix::utsolve (MatrixType& mattype, const FloatMatrix& b,\n                      octave_idx_type& info,\n                      float& rcon, solve_singularity_handler sing_handler,\n                      bool calc_cond, blas_trans_type transt) const\n{\n  FloatMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    retval = FloatMatrix (nc, b_nc, 0.0);\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ == MatrixType::Permuted_Upper || typ == MatrixType::Upper)\n        {\n          rcon = 1.0;\n          info = 0;\n\n          if (typ == MatrixType::Permuted_Upper)\n            (*current_liboctave_error_handler)\n              (\"permuted triangular matrix not implemented\");\n          else\n            {\n              const float *tmp_data = data ();\n\n              retval = b;\n              float *result = retval.rwdata ();\n\n              char uplo = 'U';\n              char trans = get_blas_char (transt);\n              char dia = 'N';\n\n              F77_INT tmp_info = 0;\n\n              F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                         F77_CONST_CHAR_ARG2 (&trans, 1),\n                                         F77_CONST_CHAR_ARG2 (&dia, 1),\n                                         nr, b_nc, tmp_data, nr,\n                                         result, nr, tmp_info\n                                         F77_CHAR_ARG_LEN (1)\n                                         F77_CHAR_ARG_LEN (1)\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n\n              if (calc_cond)\n                {\n                  char norm = '1';\n                  uplo = 'U';\n                  dia = 'N';\n\n                  Array<float> z (dim_vector (3 * nc, 1));\n                  float *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nc, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                             F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                             F77_CONST_CHAR_ARG2 (&dia, 1),\n                                             nr, tmp_data, nr, rcon,\n                                             pz, piz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)\n                                             F77_CHAR_ARG_LEN (1)\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      info = -2;\n\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n\n            }\n        }\n      else\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::ltsolve (MatrixType& mattype, const FloatMatrix& b,\n                      octave_idx_type& info,\n                      float& rcon, solve_singularity_handler sing_handler,\n                      bool calc_cond, blas_trans_type transt) const\n{\n  FloatMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    retval = FloatMatrix (nc, b_nc, 0.0);\n  else\n    {\n      int typ = mattype.type ();\n\n      if (typ == MatrixType::Permuted_Lower || typ == MatrixType::Lower)\n        {\n          rcon = 1.0;\n          info = 0;\n\n          if (typ == MatrixType::Permuted_Lower)\n            (*current_liboctave_error_handler)\n              (\"permuted triangular matrix not implemented\");\n          else\n            {\n              const float *tmp_data = data ();\n\n              retval = b;\n              float *result = retval.rwdata ();\n\n              char uplo = 'L';\n              char trans = get_blas_char (transt);\n              char dia = 'N';\n\n              F77_INT tmp_info = 0;\n\n              F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                         F77_CONST_CHAR_ARG2 (&trans, 1),\n                                         F77_CONST_CHAR_ARG2 (&dia, 1),\n                                         nr, b_nc, tmp_data, nr,\n                                         result, nr, tmp_info\n                                         F77_CHAR_ARG_LEN (1)\n                                         F77_CHAR_ARG_LEN (1)\n                                         F77_CHAR_ARG_LEN (1)));\n\n              info = tmp_info;\n\n              if (calc_cond)\n                {\n                  char norm = '1';\n                  uplo = 'L';\n                  dia = 'N';\n\n                  Array<float> z (dim_vector (3 * nc, 1));\n                  float *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nc, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),\n                                             F77_CONST_CHAR_ARG2 (&uplo, 1),\n                                             F77_CONST_CHAR_ARG2 (&dia, 1),\n                                             nr, tmp_data, nr, rcon,\n                                             pz, piz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)\n                                             F77_CHAR_ARG_LEN (1)\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      info = -2;\n\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n            }\n        }\n      else\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::fsolve (MatrixType& mattype, const FloatMatrix& b,\n                     octave_idx_type& info,\n                     float& rcon, solve_singularity_handler sing_handler,\n                     bool calc_cond) const\n{\n  FloatMatrix retval;\n\n  F77_INT nr = octave::to_f77_int (rows ());\n  F77_INT nc = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (nr != nc || nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (nr == 0 || b_nc == 0)\n    retval = FloatMatrix (nc, b_nc, 0.0);\n  else\n    {\n      int typ = mattype.type ();\n\n      // Calculate the norm of the matrix for later use when determining rcon.\n      float anorm = -1.0;\n\n      if (typ == MatrixType::Hermitian)\n        {\n          info = 0;\n          char job = 'L';\n\n          FloatMatrix atmp = *this;\n          float *tmp_data = atmp.rwdata ();\n\n          // The norm of the matrix for later use when determining rcon.\n          if (calc_cond)\n            anorm = norm1 (atmp);\n\n          F77_INT tmp_info = 0;\n\n          F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,\n                                     tmp_data, nr, tmp_info\n                                     F77_CHAR_ARG_LEN (1)));\n\n          info = tmp_info;\n\n          // Throw away extra info LAPACK gives so as to not change output.\n          rcon = 0.0;\n          if (info != 0)\n            {\n              info = -2;\n\n              mattype.mark_as_unsymmetric ();\n              typ = MatrixType::Full;\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  Array<float> z (dim_vector (3 * nc, 1));\n                  float *pz = z.rwdata ();\n                  Array<F77_INT> iz (dim_vector (nc, 1));\n                  F77_INT *piz = iz.rwdata ();\n\n                  F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, tmp_data, nr, anorm,\n                                             rcon, pz, piz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      info = -2;\n\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n\n              if (info == 0)\n                {\n                  retval = b;\n                  float *result = retval.rwdata ();\n\n                  F77_XFCN (spotrs, SPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, b_nc, tmp_data, nr,\n                                             result, b_nr, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n                }\n              else\n                {\n                  mattype.mark_as_unsymmetric ();\n                  typ = MatrixType::Full;\n                }\n            }\n        }\n\n      if (typ == MatrixType::Full)\n        {\n          info = 0;\n\n          Array<F77_INT> ipvt (dim_vector (nr, 1));\n          F77_INT *pipvt = ipvt.rwdata ();\n\n          FloatMatrix atmp = *this;\n          float *tmp_data = atmp.rwdata ();\n\n          if (calc_cond && anorm < 0.0)\n            anorm = norm1 (atmp);\n\n          Array<float> z (dim_vector (4 * nc, 1));\n          float *pz = z.rwdata ();\n          Array<F77_INT> iz (dim_vector (nc, 1));\n          F77_INT *piz = iz.rwdata ();\n\n          F77_INT tmp_info = 0;\n\n          F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, tmp_info));\n\n          info = tmp_info;\n\n          // Throw away extra info LAPACK gives so as to not change output.\n          rcon = 0.0;\n          if (info != 0)\n            {\n              info = -2;\n\n              if (sing_handler)\n                sing_handler (rcon);\n              else\n                octave::warn_singular_matrix ();\n\n              mattype.mark_as_rectangular ();\n            }\n          else\n            {\n              if (calc_cond)\n                {\n                  // Calculate the condition number for non-singular matrix.\n                  char job = '1';\n                  F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nc, tmp_data, nr, anorm,\n                                             rcon, pz, piz, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n\n                  if (info != 0)\n                    info = -2;\n\n                  if (is_singular (rcon) || octave::math::isnan (rcon))\n                    {\n                      if (sing_handler)\n                        sing_handler (rcon);\n                      else\n                        octave::warn_singular_matrix (rcon);\n                    }\n                }\n\n              if (info == 0)\n                {\n                  retval = b;\n                  float *result = retval.rwdata ();\n\n                  char job = 'N';\n                  F77_XFCN (sgetrs, SGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),\n                                             nr, b_nc, tmp_data, nr,\n                                             pipvt, result, b_nr, tmp_info\n                                             F77_CHAR_ARG_LEN (1)));\n\n                  info = tmp_info;\n                }\n              else\n                mattype.mark_as_rectangular ();\n            }\n        }\n      else if (typ != MatrixType::Hermitian)\n        (*current_liboctave_error_handler) (\"incorrect matrix type\");\n    }\n\n  return retval;\n}\n\nFloatMatrix\nFloatMatrix::solve (MatrixType& mattype, const FloatMatrix& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatMatrix\nFloatMatrix::solve (MatrixType& mattype, const FloatMatrix& b,\n                    octave_idx_type& info) const\n{\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatMatrix\nFloatMatrix::solve (MatrixType& mattype, const FloatMatrix& b,\n                    octave_idx_type& info, float& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatMatrix\nFloatMatrix::solve (MatrixType& mattype, const FloatMatrix& b,\n                    octave_idx_type& info,\n                    float& rcon, solve_singularity_handler sing_handler,\n                    bool singular_fallback, blas_trans_type transt) const\n{\n  FloatMatrix retval;\n  int typ = mattype.type ();\n\n  if (typ == MatrixType::Unknown)\n    typ = mattype.type (*this);\n\n  // Only calculate the condition number for LU/Cholesky\n  if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)\n    retval = utsolve (mattype, b, info, rcon, sing_handler, true, transt);\n  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)\n    retval = ltsolve (mattype, b, info, rcon, sing_handler, true, transt);\n  else if (transt == blas_trans || transt == blas_conj_trans)\n    return transpose ().solve (mattype, b, info, rcon, sing_handler,\n                               singular_fallback);\n  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)\n    retval = fsolve (mattype, b, info, rcon, sing_handler, true);\n  else if (typ != MatrixType::Rectangular)\n    (*current_liboctave_error_handler) (\"unknown matrix type\");\n\n  // Rectangular or one of the above solvers flags a singular matrix\n  if (singular_fallback && mattype.type () == MatrixType::Rectangular)\n    {\n      octave_idx_type rank;\n      retval = lssolve (b, info, rank, rcon);\n    }\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatMatrix::solve (MatrixType& mattype, const FloatComplexMatrix& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatMatrix::solve (MatrixType& mattype, const FloatComplexMatrix& b,\n                    octave_idx_type& info) const\n{\n  float rcon;\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatComplexMatrix\nFloatMatrix::solve (MatrixType& mattype, const FloatComplexMatrix& b,\n                    octave_idx_type& info,\n                    float& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nstatic FloatMatrix\nstack_complex_matrix (const FloatComplexMatrix& cm)\n{\n  octave_idx_type m = cm.rows ();\n  octave_idx_type n = cm.cols ();\n  octave_idx_type nel = m*n;\n  FloatMatrix retval (m, 2*n);\n  const FloatComplex *cmd = cm.data ();\n  float *rd = retval.rwdata ();\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      rd[i] = std::real (cmd[i]);\n      rd[nel+i] = std::imag (cmd[i]);\n    }\n  return retval;\n}\n\nstatic FloatComplexMatrix\nunstack_complex_matrix (const FloatMatrix& sm)\n{\n  octave_idx_type m = sm.rows ();\n  octave_idx_type n = sm.cols () / 2;\n  octave_idx_type nel = m*n;\n  FloatComplexMatrix retval (m, n);\n  const float *smd = sm.data ();\n  FloatComplex *rd = retval.rwdata ();\n  for (octave_idx_type i = 0; i < nel; i++)\n    rd[i] = FloatComplex (smd[i], smd[nel+i]);\n  return retval;\n}\n\nFloatComplexMatrix\nFloatMatrix::solve (MatrixType& mattype, const FloatComplexMatrix& b,\n                    octave_idx_type& info,\n                    float& rcon, solve_singularity_handler sing_handler,\n                    bool singular_fallback, blas_trans_type transt) const\n{\n  FloatMatrix tmp = stack_complex_matrix (b);\n  tmp = solve (mattype, tmp, info, rcon, sing_handler, singular_fallback,\n               transt);\n  return unstack_complex_matrix (tmp);\n}\n\nFloatColumnVector\nFloatMatrix::solve (MatrixType& mattype, const FloatColumnVector& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (mattype, b, info, rcon);\n}\n\nFloatColumnVector\nFloatMatrix::solve (MatrixType& mattype, const FloatColumnVector& b,\n                    octave_idx_type& info) const\n{\n  float rcon;\n  return solve (mattype, b, info, rcon);\n}\n\nFloatColumnVector\nFloatMatrix::solve (MatrixType& mattype, const FloatColumnVector& b,\n                    octave_idx_type& info,\n                    float& rcon) const\n{\n  return solve (mattype, b, info, rcon, nullptr);\n}\n\nFloatColumnVector\nFloatMatrix::solve (MatrixType& mattype, const FloatColumnVector& b,\n                    octave_idx_type& info,\n                    float& rcon, solve_singularity_handler sing_handler,\n                    blas_trans_type transt) const\n{\n  FloatMatrix tmp (b);\n  tmp = solve (mattype, tmp, info, rcon, sing_handler, true, transt);\n  return tmp.column (static_cast<octave_idx_type> (0));\n}\n\nFloatComplexColumnVector\nFloatMatrix::solve (MatrixType& mattype,\n                    const FloatComplexColumnVector& b) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (mattype, b);\n}\n\nFloatComplexColumnVector\nFloatMatrix::solve (MatrixType& mattype, const FloatComplexColumnVector& b,\n                    octave_idx_type& info) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (mattype, b, info);\n}\n\nFloatComplexColumnVector\nFloatMatrix::solve (MatrixType& mattype, const FloatComplexColumnVector& b,\n                    octave_idx_type& info, float& rcon) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (mattype, b, info, rcon);\n}\n\nFloatComplexColumnVector\nFloatMatrix::solve (MatrixType& mattype, const FloatComplexColumnVector& b,\n                    octave_idx_type& info, float& rcon,\n                    solve_singularity_handler sing_handler,\n                    blas_trans_type transt) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (mattype, b, info, rcon, sing_handler, transt);\n}\n\nFloatMatrix\nFloatMatrix::solve (const FloatMatrix& b) const\n{\n  octave_idx_type info;\n  float rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatMatrix\nFloatMatrix::solve (const FloatMatrix& b, octave_idx_type& info) const\n{\n  float rcon;\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatMatrix\nFloatMatrix::solve (const FloatMatrix& b, octave_idx_type& info,\n                    float& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatMatrix\nFloatMatrix::solve (const FloatMatrix& b, octave_idx_type& info,\n                    float& rcon, solve_singularity_handler sing_handler,\n                    blas_trans_type transt) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, info, rcon, sing_handler, true, transt);\n}\n\nFloatComplexMatrix\nFloatMatrix::solve (const FloatComplexMatrix& b) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (b);\n}\n\nFloatComplexMatrix\nFloatMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (b, info);\n}\n\nFloatComplexMatrix\nFloatMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info,\n                    float& rcon) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (b, info, rcon);\n}\n\nFloatComplexMatrix\nFloatMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info,\n                    float& rcon,\n                    solve_singularity_handler sing_handler,\n                    blas_trans_type transt) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (b, info, rcon, sing_handler, transt);\n}\n\nFloatColumnVector\nFloatMatrix::solve (const FloatColumnVector& b) const\n{\n  octave_idx_type info; float rcon;\n  return solve (b, info, rcon);\n}\n\nFloatColumnVector\nFloatMatrix::solve (const FloatColumnVector& b, octave_idx_type& info) const\n{\n  float rcon;\n  return solve (b, info, rcon);\n}\n\nFloatColumnVector\nFloatMatrix::solve (const FloatColumnVector& b, octave_idx_type& info,\n                    float& rcon) const\n{\n  return solve (b, info, rcon, nullptr);\n}\n\nFloatColumnVector\nFloatMatrix::solve (const FloatColumnVector& b, octave_idx_type& info,\n                    float& rcon, solve_singularity_handler sing_handler,\n                    blas_trans_type transt) const\n{\n  MatrixType mattype (*this);\n  return solve (mattype, b, info, rcon, sing_handler, transt);\n}\n\nFloatComplexColumnVector\nFloatMatrix::solve (const FloatComplexColumnVector& b) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (b);\n}\n\nFloatComplexColumnVector\nFloatMatrix::solve (const FloatComplexColumnVector& b,\n                    octave_idx_type& info) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (b, info);\n}\n\nFloatComplexColumnVector\nFloatMatrix::solve (const FloatComplexColumnVector& b, octave_idx_type& info,\n                    float& rcon) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (b, info, rcon);\n}\n\nFloatComplexColumnVector\nFloatMatrix::solve (const FloatComplexColumnVector& b, octave_idx_type& info,\n                    float& rcon, solve_singularity_handler sing_handler,\n                    blas_trans_type transt) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.solve (b, info, rcon, sing_handler, transt);\n}\n\nFloatMatrix\nFloatMatrix::lssolve (const FloatMatrix& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatMatrix\nFloatMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatMatrix\nFloatMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info,\n                      octave_idx_type& rank) const\n{\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\n\nFloatMatrix\nFloatMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info,\n                      octave_idx_type& rank, float& rcon) const\n{\n  FloatMatrix retval;\n\n  F77_INT m = octave::to_f77_int (rows ());\n  F77_INT n = octave::to_f77_int (cols ());\n\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n  F77_INT nrhs = b_nc;  // alias for code readability\n\n  if (m != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (m == 0 || n == 0 || b_nc == 0)\n    retval = FloatMatrix (n, b_nc, 0.0);\n  else\n    {\n      F77_INT minmn = (m < n ? m : n);\n      F77_INT maxmn = (m > n ? m : n);\n      rcon = -1.0;\n      if (m != n)\n        {\n          retval = FloatMatrix (maxmn, nrhs, 0.0);\n\n          for (F77_INT j = 0; j < nrhs; j++)\n            for (F77_INT i = 0; i < m; i++)\n              retval.elem (i, j) = b.elem (i, j);\n        }\n      else\n        retval = b;\n\n      FloatMatrix atmp = *this;\n      float *tmp_data = atmp.rwdata ();\n\n      float *pretval = retval.rwdata ();\n      Array<float> s (dim_vector (minmn, 1));\n      float *ps = s.rwdata ();\n\n      // Ask DGELSD what the dimension of WORK should be.\n      F77_INT lwork = -1;\n\n      Array<float> work (dim_vector (1, 1));\n\n      F77_INT smlsiz;\n      F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 (\"SGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   0, 0, 0, 0, smlsiz\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      F77_INT mnthr;\n      F77_FUNC (xilaenv, XILAENV) (6, F77_CONST_CHAR_ARG2 (\"SGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   m, n, nrhs, -1, mnthr\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      // We compute the size of iwork because DGELSD in older versions\n      // of LAPACK does not return it on a query call.\n      float dminmn = static_cast<float> (minmn);\n      float dsmlsizp1 = static_cast<float> (smlsiz+1);\n      float tmp = octave::math::log2 (dminmn / dsmlsizp1);\n\n      F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;\n      if (nlvl < 0)\n        nlvl = 0;\n\n      F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;\n      if (liwork < 1)\n        liwork = 1;\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n      F77_INT *piwork = iwork.rwdata ();\n\n      F77_INT tmp_info = 0;\n      F77_INT tmp_rank = 0;\n\n      F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,\n                                 ps, rcon, tmp_rank, work.rwdata (),\n                                 lwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      // The workspace query is broken in at least LAPACK 3.0.0\n      // through 3.1.1 when n >= mnthr.  The obtuse formula below\n      // should provide sufficient workspace for DGELSD to operate\n      // efficiently.\n      if (n > m && n >= mnthr)\n        {\n          const F77_INT wlalsd\n            = 9*m + 2*m*smlsiz + 8*m*nlvl + m*nrhs + (smlsiz+1)*(smlsiz+1);\n\n          F77_INT addend = m;\n\n          if (2*m-4 > addend)\n            addend = 2*m-4;\n\n          if (nrhs > addend)\n            addend = nrhs;\n\n          if (n-3*m > addend)\n            addend = n-3*m;\n\n          if (wlalsd > addend)\n            addend = wlalsd;\n\n          const F77_INT lworkaround = 4*m + m*m + addend;\n\n          if (work(0) < lworkaround)\n            work(0) = lworkaround;\n        }\n      else if (m >= n)\n        {\n          F77_INT lworkaround\n            = 12*n + 2*n*smlsiz + 8*n*nlvl + n*nrhs + (smlsiz+1)*(smlsiz+1);\n\n          if (work(0) < lworkaround)\n            work(0) = lworkaround;\n        }\n\n      lwork = static_cast<F77_INT> (work(0));\n      work.resize (dim_vector (lwork, 1));\n\n      float anorm = norm1 (*this);\n\n      if (octave::math::isinf (anorm))\n        {\n          rcon = 0.0;\n          retval = FloatMatrix (n, b_nc, 0.0);\n        }\n      else if (octave::math::isnan (anorm))\n        {\n          rcon = octave::numeric_limits<float>::NaN ();\n          retval = FloatMatrix (n, b_nc,\n                                octave::numeric_limits<float>::NaN ());\n        }\n      else\n        {\n          F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,\n                                     maxmn, ps, rcon, tmp_rank,\n                                     work.rwdata (), lwork,\n                                     piwork, tmp_info));\n\n          info = tmp_info;\n          rank = tmp_rank;\n\n          if (s.elem (0) == 0.0)\n            rcon = 0.0;\n          else\n            rcon = s.elem (minmn - 1) / s.elem (0);\n\n          retval.resize (n, nrhs);\n        }\n    }\n\n  return retval;\n}\n\nFloatComplexMatrix\nFloatMatrix::lssolve (const FloatComplexMatrix& b) const\n{\n  FloatComplexMatrix tmp (*this);\n  octave_idx_type info;\n  octave_idx_type rank;\n  float rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info) const\n{\n  FloatComplexMatrix tmp (*this);\n  octave_idx_type rank;\n  float rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info,\n                      octave_idx_type& rank) const\n{\n  FloatComplexMatrix tmp (*this);\n  float rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nFloatComplexMatrix\nFloatMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info,\n                      octave_idx_type& rank, float& rcon) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nFloatColumnVector\nFloatMatrix::lssolve (const FloatColumnVector& b) const\n{\n  octave_idx_type info;\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatColumnVector\nFloatMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info) const\n{\n  octave_idx_type rank;\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatColumnVector\nFloatMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info,\n                      octave_idx_type& rank) const\n{\n  float rcon;\n  return lssolve (b, info, rank, rcon);\n}\n\nFloatColumnVector\nFloatMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info,\n                      octave_idx_type& rank, float& rcon) const\n{\n  FloatColumnVector retval;\n\n  F77_INT nrhs = 1;\n\n  F77_INT m = octave::to_f77_int (rows ());\n  F77_INT n = octave::to_f77_int (cols ());\n\n  if (m != b.numel ())\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch solution of linear equations\");\n\n  if (m == 0 || n == 0)\n    retval = FloatColumnVector (n, 0.0);\n  else\n    {\n      F77_INT minmn = (m < n ? m : n);\n      F77_INT maxmn = (m > n ? m : n);\n      rcon = -1.0;\n\n      if (m != n)\n        {\n          retval = FloatColumnVector (maxmn, 0.0);\n\n          for (F77_INT i = 0; i < m; i++)\n            retval.elem (i) = b.elem (i);\n        }\n      else\n        retval = b;\n\n      FloatMatrix atmp = *this;\n      float *tmp_data = atmp.rwdata ();\n\n      float *pretval = retval.rwdata ();\n      Array<float> s (dim_vector (minmn, 1));\n      float *ps = s.rwdata ();\n\n      // Ask DGELSD what the dimension of WORK should be.\n      F77_INT lwork = -1;\n\n      Array<float> work (dim_vector (1, 1));\n\n      F77_INT smlsiz;\n      F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 (\"SGELSD\", 6),\n                                   F77_CONST_CHAR_ARG2 (\" \", 1),\n                                   0, 0, 0, 0, smlsiz\n                                   F77_CHAR_ARG_LEN (6)\n                                   F77_CHAR_ARG_LEN (1));\n\n      // We compute the size of iwork because DGELSD in older versions\n      // of LAPACK does not return it on a query call.\n      float dminmn = static_cast<float> (minmn);\n      float dsmlsizp1 = static_cast<float> (smlsiz+1);\n      float tmp = octave::math::log2 (dminmn / dsmlsizp1);\n\n      F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;\n      if (nlvl < 0)\n        nlvl = 0;\n\n      F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;\n      if (liwork < 1)\n        liwork = 1;\n      Array<F77_INT> iwork (dim_vector (liwork, 1));\n      F77_INT *piwork = iwork.rwdata ();\n\n      F77_INT tmp_info = 0;\n      F77_INT tmp_rank = 0;\n\n      F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,\n                                 ps, rcon, tmp_rank, work.rwdata (),\n                                 lwork, piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      lwork = static_cast<F77_INT> (work(0));\n      work.resize (dim_vector (lwork, 1));\n\n      F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,\n                                 maxmn, ps, rcon, tmp_rank,\n                                 work.rwdata (), lwork,\n                                 piwork, tmp_info));\n\n      info = tmp_info;\n      rank = tmp_rank;\n\n      if (rank < minmn)\n        {\n          if (s.elem (0) == 0.0)\n            rcon = 0.0;\n          else\n            rcon = s.elem (minmn - 1) / s.elem (0);\n        }\n\n      retval.resize (n);\n    }\n\n  return retval;\n}\n\nFloatComplexColumnVector\nFloatMatrix::lssolve (const FloatComplexColumnVector& b) const\n{\n  FloatComplexMatrix tmp (*this);\n  octave_idx_type info;\n  octave_idx_type rank;\n  float rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nFloatComplexColumnVector\nFloatMatrix::lssolve (const FloatComplexColumnVector& b,\n                      octave_idx_type& info) const\n{\n  FloatComplexMatrix tmp (*this);\n  octave_idx_type rank;\n  float rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nFloatComplexColumnVector\nFloatMatrix::lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,\n                      octave_idx_type& rank) const\n{\n  FloatComplexMatrix tmp (*this);\n  float rcon;\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nFloatComplexColumnVector\nFloatMatrix::lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,\n                      octave_idx_type& rank, float& rcon) const\n{\n  FloatComplexMatrix tmp (*this);\n  return tmp.lssolve (b, info, rank, rcon);\n}\n\nFloatMatrix&\nFloatMatrix::operator += (const FloatDiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator +=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) += a.elem (i, i);\n\n  return *this;\n}\n\nFloatMatrix&\nFloatMatrix::operator -= (const FloatDiagMatrix& a)\n{\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nr || nc != a_nc)\n    octave::err_nonconformant (\"operator -=\", nr, nc, a_nr, a_nc);\n\n  for (octave_idx_type i = 0; i < a.length (); i++)\n    elem (i, i) -= a.elem (i, i);\n\n  return *this;\n}\n\n// column vector by row vector -> matrix operations\n\nFloatMatrix\noperator * (const FloatColumnVector& v, const FloatRowVector& a)\n{\n  FloatMatrix retval;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  if (len != 0)\n    {\n      F77_INT a_len = octave::to_f77_int (a.numel ());\n\n      retval = FloatMatrix (len, a_len);\n      float *c = retval.rwdata ();\n\n      F77_XFCN (sgemm, SGEMM, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                               F77_CONST_CHAR_ARG2 (\"N\", 1),\n                               len, a_len, 1, 1.0, v.data (), len,\n                               a.data (), 1, 0.0, c, len\n                               F77_CHAR_ARG_LEN (1)\n                               F77_CHAR_ARG_LEN (1)));\n    }\n\n  return retval;\n}\n\n// unary operations\n\nboolMatrix\nFloatMatrix::all (int dim) const\n{\n  return FloatNDArray::all (dim);\n}\n\nboolMatrix\nFloatMatrix::any (int dim) const\n{\n  return FloatNDArray::any (dim);\n}\n\nFloatMatrix\nFloatMatrix::flip (int dim) const\n{\n  return FloatNDArray::flip (dim);\n}\n\nFloatMatrix\nFloatMatrix::cumprod (int dim, bool nanflag) const\n{\n  return FloatNDArray::cumprod (dim, nanflag);\n}\n\nFloatMatrix\nFloatMatrix::cumsum (int dim, bool nanflag) const\n{\n  return FloatNDArray::cumsum (dim, nanflag);\n}\n\nFloatMatrix\nFloatMatrix::prod (int dim, bool nanflag) const\n{\n  return FloatNDArray::prod (dim, nanflag);\n}\n\nMatrix\nFloatMatrix::dprod (int dim, bool nanflag) const\n{\n  return FloatNDArray::dprod (dim, nanflag);\n}\n\nFloatMatrix\nFloatMatrix::sum (int dim, bool nanflag) const\n{\n  return FloatNDArray::sum (dim, nanflag);\n}\n\nMatrix\nFloatMatrix::dsum (int dim, bool nanflag) const\n{\n  return FloatNDArray::dsum (dim, nanflag);\n}\n\nFloatMatrix\nFloatMatrix::sumsq (int dim, bool nanflag) const\n{\n  return FloatNDArray::sumsq (dim, nanflag);\n}\n\nMatrix\nFloatMatrix::dsumsq (int dim, bool nanflag) const\n{\n  return FloatNDArray::dsumsq (dim, nanflag);\n}\n\nFloatMatrix\nFloatMatrix::abs () const\n{\n  return FloatNDArray::abs ();\n}\n\nFloatMatrix\nFloatMatrix::diag (octave_idx_type k) const\n{\n  return FloatNDArray::diag (k);\n}\n\nFloatDiagMatrix\nFloatMatrix::diag (octave_idx_type m, octave_idx_type n) const\n{\n  FloatDiagMatrix retval;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr == 1 || nc == 1)\n    retval = FloatDiagMatrix (*this, m, n);\n  else\n    (*current_liboctave_error_handler) (\"diag: expecting vector argument\");\n\n  return retval;\n}\n\nFloatColumnVector\nFloatMatrix::row_min () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return row_min (dummy_idx);\n}\n\nFloatColumnVector\nFloatMatrix::row_min (Array<octave_idx_type>& idx_arg) const\n{\n  FloatColumnVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nr);\n      idx_arg.resize (dim_vector (nr, 1));\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_idx_type idx_j;\n\n          float tmp_min = octave::numeric_limits<float>::NaN ();\n\n          for (idx_j = 0; idx_j < nc; idx_j++)\n            {\n              tmp_min = elem (i, idx_j);\n\n              if (! octave::math::isnan (tmp_min))\n                break;\n            }\n\n          for (octave_idx_type j = idx_j+1; j < nc; j++)\n            {\n              float tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n              else if (tmp < tmp_min)\n                {\n                  idx_j = j;\n                  tmp_min = tmp;\n                }\n            }\n\n          result.elem (i) = tmp_min;\n          idx_arg.elem (i) = (octave::math::isnan (tmp_min) ? 0 : idx_j);\n        }\n    }\n\n  return result;\n}\n\nFloatColumnVector\nFloatMatrix::row_max () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return row_max (dummy_idx);\n}\n\nFloatColumnVector\nFloatMatrix::row_max (Array<octave_idx_type>& idx_arg) const\n{\n  FloatColumnVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nr);\n      idx_arg.resize (dim_vector (nr, 1));\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_idx_type idx_j;\n\n          float tmp_max = octave::numeric_limits<float>::NaN ();\n\n          for (idx_j = 0; idx_j < nc; idx_j++)\n            {\n              tmp_max = elem (i, idx_j);\n\n              if (! octave::math::isnan (tmp_max))\n                break;\n            }\n\n          for (octave_idx_type j = idx_j+1; j < nc; j++)\n            {\n              float tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n              else if (tmp > tmp_max)\n                {\n                  idx_j = j;\n                  tmp_max = tmp;\n                }\n            }\n\n          result.elem (i) = tmp_max;\n          idx_arg.elem (i) = (octave::math::isnan (tmp_max) ? 0 : idx_j);\n        }\n    }\n\n  return result;\n}\n\nFloatRowVector\nFloatMatrix::column_min () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return column_min (dummy_idx);\n}\n\nFloatRowVector\nFloatMatrix::column_min (Array<octave_idx_type>& idx_arg) const\n{\n  FloatRowVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nc);\n      idx_arg.resize (dim_vector (1, nc));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_idx_type idx_i;\n\n          float tmp_min = octave::numeric_limits<float>::NaN ();\n\n          for (idx_i = 0; idx_i < nr; idx_i++)\n            {\n              tmp_min = elem (idx_i, j);\n\n              if (! octave::math::isnan (tmp_min))\n                break;\n            }\n\n          for (octave_idx_type i = idx_i+1; i < nr; i++)\n            {\n              float tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n              else if (tmp < tmp_min)\n                {\n                  idx_i = i;\n                  tmp_min = tmp;\n                }\n            }\n\n          result.elem (j) = tmp_min;\n          idx_arg.elem (j) = (octave::math::isnan (tmp_min) ? 0 : idx_i);\n        }\n    }\n\n  return result;\n}\n\nFloatRowVector\nFloatMatrix::column_max () const\n{\n  Array<octave_idx_type> dummy_idx;\n  return column_max (dummy_idx);\n}\n\nFloatRowVector\nFloatMatrix::column_max (Array<octave_idx_type>& idx_arg) const\n{\n  FloatRowVector result;\n\n  octave_idx_type nr = rows ();\n  octave_idx_type nc = cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      result.resize (nc);\n      idx_arg.resize (dim_vector (1, nc));\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_idx_type idx_i;\n\n          float tmp_max = octave::numeric_limits<float>::NaN ();\n\n          for (idx_i = 0; idx_i < nr; idx_i++)\n            {\n              tmp_max = elem (idx_i, j);\n\n              if (! octave::math::isnan (tmp_max))\n                break;\n            }\n\n          for (octave_idx_type i = idx_i+1; i < nr; i++)\n            {\n              float tmp = elem (i, j);\n\n              if (octave::math::isnan (tmp))\n                continue;\n              else if (tmp > tmp_max)\n                {\n                  idx_i = i;\n                  tmp_max = tmp;\n                }\n            }\n\n          result.elem (j) = tmp_max;\n          idx_arg.elem (j) = (octave::math::isnan (tmp_max) ? 0 : idx_i);\n        }\n    }\n\n  return result;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const FloatMatrix& a)\n{\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    {\n      for (octave_idx_type j = 0; j < a.cols (); j++)\n        {\n          os << ' ';\n          octave::write_value<float> (os, a.elem (i, j));\n        }\n      os << \"\\n\";\n    }\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, FloatMatrix& a)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr > 0 && nc > 0)\n    {\n      float tmp;\n      for (octave_idx_type i = 0; i < nr; i++)\n        for (octave_idx_type j = 0; j < nc; j++)\n          {\n            tmp = octave::read_value<float> (is);\n            if (is)\n              a.elem (i, j) = tmp;\n            else\n              return is;\n          }\n    }\n\n  return is;\n}\n\nFloatMatrix\nGivens (float x, float y)\n{\n  float cc, s, temp_r;\n\n  F77_FUNC (slartg, SLARTG) (x, y, cc, s, temp_r);\n\n  FloatMatrix g (2, 2);\n\n  g.elem (0, 0) = cc;\n  g.elem (1, 1) = cc;\n  g.elem (0, 1) = s;\n  g.elem (1, 0) = -s;\n\n  return g;\n}\n\nFloatMatrix\nSylvester (const FloatMatrix& a, const FloatMatrix& b, const FloatMatrix& c)\n{\n  FloatMatrix retval;\n\n  // FIXME: need to check that a, b, and c are all the same size.\n\n  // Compute Schur decompositions.\n\n  octave::math::schur<FloatMatrix> as (a, \"U\");\n  octave::math::schur<FloatMatrix> bs (b, \"U\");\n\n  // Transform c to new coordinates.\n\n  FloatMatrix ua = as.unitary_schur_matrix ();\n  FloatMatrix sch_a = as.schur_matrix ();\n\n  FloatMatrix ub = bs.unitary_schur_matrix ();\n  FloatMatrix sch_b = bs.schur_matrix ();\n\n  FloatMatrix cx = ua.transpose () * c * ub;\n\n  // Solve the sylvester equation, back-transform, and return the\n  // solution.\n\n  F77_INT a_nr = octave::to_f77_int (a.rows ());\n  F77_INT b_nr = octave::to_f77_int (b.rows ());\n\n  float scale;\n  F77_INT info;\n\n  float *pa = sch_a.rwdata ();\n  float *pb = sch_b.rwdata ();\n  float *px = cx.rwdata ();\n\n  F77_XFCN (strsyl, STRSYL, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             1, a_nr, b_nr, pa, a_nr, pb,\n                             b_nr, px, a_nr, scale, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // FIXME: check info?\n\n  retval = ua*cx*ub.transpose ();\n\n  return retval;\n}\n\n// matrix by matrix -> matrix operations\n\n/*\n## Simple Dot Product, Matrix-Vector, and Matrix-Matrix Unit tests\n%!assert (single ([1 2 3]) * single ([ 4 ; 5 ; 6]), single (32), 5e-7)\n%!assert (single ([1 2 ; 3 4]) * single ([5 ; 6]), single ([17 ; 39]), 5e-7)\n%!assert (single ([1 2 ; 3 4]) * single ([5 6 ; 7 8]), single ([19 22; 43 50]), 5e-7)\n\n## Test some simple identities\n%!shared M, cv, rv\n%! M = single (randn (10,10));\n%! cv = single (randn (10,1));\n%! rv = single (randn (1,10));\n%!assert ([M*cv,M*cv], M*[cv,cv], 5e-6)\n%!assert ([M'*cv,M'*cv], M'*[cv,cv], 5e-6)\n%!assert ([rv*M;rv*M], [rv;rv]*M, 5e-6)\n%!assert ([rv*M';rv*M'], [rv;rv]*M', 5e-6)\n%!assert (2*rv*cv, [rv,rv]*[cv;cv], 5e-6)\n\n*/\n\nstatic char\nget_blas_trans_arg (bool trans)\n{\n  return trans ? 'T' : 'N';\n}\n\n// the general GEMM operation\n\nFloatMatrix\nxgemm (const FloatMatrix& a, const FloatMatrix& b,\n       blas_trans_type transa, blas_trans_type transb)\n{\n  FloatMatrix retval;\n\n  bool tra = transa != blas_no_trans;\n  bool trb = transb != blas_no_trans;\n\n  F77_INT a_nr = octave::to_f77_int (tra ? a.cols () : a.rows ());\n  F77_INT a_nc = octave::to_f77_int (tra ? a.rows () : a.cols ());\n\n  F77_INT b_nr = octave::to_f77_int (trb ? b.cols () : b.rows ());\n  F77_INT b_nc = octave::to_f77_int (trb ? b.rows () : b.cols ());\n\n  if (a_nc != b_nr)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, b_nr, b_nc);\n\n  if (a_nr == 0 || a_nc == 0 || b_nc == 0)\n    retval = FloatMatrix (a_nr, b_nc, 0.0);\n  else if (a.data () == b.data () && a_nr == b_nc && tra != trb)\n    {\n      F77_INT lda = octave::to_f77_int (a.rows ());\n\n      retval = FloatMatrix (a_nr, b_nc);\n      float *c = retval.rwdata ();\n\n      const char ctra = get_blas_trans_arg (tra);\n      F77_XFCN (ssyrk, SSYRK, (F77_CONST_CHAR_ARG2 (\"U\", 1),\n                               F77_CONST_CHAR_ARG2 (&ctra, 1),\n                               a_nr, a_nc, 1.0,\n                               a.data (), lda, 0.0, c, a_nr\n                               F77_CHAR_ARG_LEN (1)\n                               F77_CHAR_ARG_LEN (1)));\n      for (int j = 0; j < a_nr; j++)\n        for (int i = 0; i < j; i++)\n          retval.xelem (j, i) = retval.xelem (i, j);\n\n    }\n  else\n    {\n      F77_INT lda = octave::to_f77_int (a.rows ());\n      F77_INT tda = octave::to_f77_int (a.cols ());\n      F77_INT ldb = octave::to_f77_int (b.rows ());\n      F77_INT tdb = octave::to_f77_int (b.cols ());\n\n      retval = FloatMatrix (a_nr, b_nc);\n      float *c = retval.rwdata ();\n\n      if (b_nc == 1)\n        {\n          if (a_nr == 1)\n            F77_FUNC (xsdot, XSDOT) (a_nc, a.data (), 1, b.data (), 1, *c);\n          else\n            {\n              const char ctra = get_blas_trans_arg (tra);\n              F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                       lda, tda, 1.0, a.data (), lda,\n                                       b.data (), 1, 0.0, c, 1\n                                       F77_CHAR_ARG_LEN (1)));\n            }\n        }\n      else if (a_nr == 1)\n        {\n          const char crevtrb = get_blas_trans_arg (! trb);\n          F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 (&crevtrb, 1),\n                                   ldb, tdb, 1.0, b.data (), ldb,\n                                   a.data (), 1, 0.0, c, 1\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n      else\n        {\n          const char ctra = get_blas_trans_arg (tra);\n          const char ctrb = get_blas_trans_arg (trb);\n          F77_XFCN (sgemm, SGEMM, (F77_CONST_CHAR_ARG2 (&ctra, 1),\n                                   F77_CONST_CHAR_ARG2 (&ctrb, 1),\n                                   a_nr, b_nc, a_nc, 1.0, a.data (),\n                                   lda, b.data (), ldb, 0.0, c, a_nr\n                                   F77_CHAR_ARG_LEN (1)\n                                   F77_CHAR_ARG_LEN (1)));\n        }\n    }\n\n  return retval;\n}\n\nFloatMatrix\noperator * (const FloatMatrix& a, const FloatMatrix& b)\n{\n  return xgemm (a, b);\n}\n\n// FIXME: it would be nice to share code among the min/max functions below.\n\n#define EMPTY_RETURN_CHECK(T)                   \\\n  if (nr == 0 || nc == 0)                       \\\n    return T (nr, nc);\n\nFloatMatrix\nmin (float f, const FloatMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return min (f, m, nanflag, realabs);\n}\n\nFloatMatrix\nmin (float f, const FloatMatrix& m, const bool nanflag)\n{\n  const bool realabs = true;\n  return min (f, m, nanflag, realabs);\n}\n\nFloatMatrix\nmin (float f, const FloatMatrix& m, const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (FloatMatrix);\n\n  FloatMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::min (f, m(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatMatrix\nmin (const FloatMatrix& m, float f)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return min (f, m, nanflag, realabs);\n}\n\nFloatMatrix\nmin (const FloatMatrix& m, float f, const bool nanflag)\n{\n  const bool realabs = true;\n  return min (f, m, nanflag, realabs);\n}\n\nFloatMatrix\nmin (const FloatMatrix& m, float f, const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (FloatMatrix);\n\n  FloatMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::min (m(i, j), f, nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatMatrix\nmin (const FloatMatrix& a, const FloatMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return min (a, b, nanflag, realabs);\n}\n\nFloatMatrix\nmin (const FloatMatrix& a, const FloatMatrix& b, const bool nanflag)\n{\n  const bool realabs = true;\n  return min (a, b, nanflag, realabs);\n}\n\nFloatMatrix\nmin (const FloatMatrix& a, const FloatMatrix& b,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n\n  if (nr != b.rows () || nc != b.columns ())\n    (*current_liboctave_error_handler)\n      (\"two-arg min requires same size arguments\");\n\n  EMPTY_RETURN_CHECK (FloatMatrix);\n\n  FloatMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::min (a(i, j), b(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatMatrix\nmax (float f, const FloatMatrix& m)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return max (f, m, nanflag, realabs);\n}\n\nFloatMatrix\nmax (float f, const FloatMatrix& m, const bool nanflag)\n{\n  const bool realabs = true;\n  return max (f, m, nanflag, realabs);\n}\n\nFloatMatrix\nmax (float f, const FloatMatrix& m, const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (FloatMatrix);\n\n  FloatMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::max (f, m(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatMatrix\nmax (const FloatMatrix& m, float f)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return max (f, m, nanflag, realabs);\n}\n\nFloatMatrix\nmax (const FloatMatrix& m, float f, const bool nanflag)\n{\n  const bool realabs = true;\n  return max (f, m, nanflag, realabs);\n}\n\nFloatMatrix\nmax (const FloatMatrix& m, float f, const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = m.rows ();\n  octave_idx_type nc = m.columns ();\n\n  EMPTY_RETURN_CHECK (FloatMatrix);\n\n  FloatMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::max (m(i, j), f, nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatMatrix\nmax (const FloatMatrix& a, const FloatMatrix& b)\n{\n  const bool nanflag = true;\n  const bool realabs = true;\n  return max (a, b, nanflag, realabs);\n}\n\nFloatMatrix\nmax (const FloatMatrix& a, const FloatMatrix& b, const bool nanflag)\n{\n  const bool realabs = true;\n  return max (a, b, nanflag, realabs);\n}\n\nFloatMatrix\nmax (const FloatMatrix& a, const FloatMatrix& b,\n     const bool nanflag, const bool realabs)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.columns ();\n\n  if (nr != b.rows () || nc != b.columns ())\n    (*current_liboctave_error_handler)\n      (\"two-arg max requires same size arguments\");\n\n  EMPTY_RETURN_CHECK (FloatMatrix);\n\n  FloatMatrix result (nr, nc);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      {\n        octave_quit ();\n        result(i, j) = octave::math::max (a(i, j), b(i, j), nanflag, realabs);\n      }\n\n  return result;\n}\n\nFloatMatrix\nlinspace (const FloatColumnVector& x1,\n          const FloatColumnVector& x2,\n          octave_idx_type n)\n\n{\n  octave_idx_type m = x1.numel ();\n\n  if (x2.numel () != m)\n    (*current_liboctave_error_handler)\n      (\"linspace: vectors must be of equal length\");\n\n  FloatMatrix retval;\n\n  if (n < 1)\n    {\n      retval.clear (m, 0);\n      return retval;\n    }\n\n  retval.clear (m, n);\n  for (octave_idx_type i = 0; i < m; i++)\n    retval.insert (linspace (x1(i), x2(i), n), i, 0);\n\n  return retval;\n}\n\nMS_CMP_OPS (FloatMatrix, float)\nMS_BOOL_OPS (FloatMatrix, float)\n\nSM_CMP_OPS (float, FloatMatrix)\nSM_BOOL_OPS (float, FloatMatrix)\n\nMM_CMP_OPS (FloatMatrix, FloatMatrix)\nMM_BOOL_OPS (FloatMatrix, FloatMatrix)\n"
  },
  {
    "path": "liboctave/array/fMatrix.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fMatrix_h)\n#define octave_fMatrix_h 1\n\n#include \"octave-config.h\"\n\n#include \"DET.h\"\n#include \"MArray.h\"\n#include \"MDiagArray2.h\"\n#include \"MatrixType.h\"\n#include \"fNDArray.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n\nclass OCTAVE_API FloatMatrix : public FloatNDArray\n{\npublic:\n\n  typedef FloatColumnVector column_vector_type;\n  typedef FloatRowVector row_vector_type;\n\n  typedef FloatColumnVector real_column_vector_type;\n  typedef FloatRowVector real_row_vector_type;\n\n  typedef FloatMatrix real_matrix_type;\n  typedef FloatComplexMatrix complex_matrix_type;\n\n  typedef FloatDiagMatrix real_diag_matrix_type;\n  typedef FloatComplexDiagMatrix complex_diag_matrix_type;\n\n  typedef float real_elt_type;\n  typedef FloatComplex complex_elt_type;\n\n  typedef void (*solve_singularity_handler) (float rcon);\n\n  FloatMatrix () = default;\n\n  FloatMatrix (const FloatMatrix& a) = default;\n\n  FloatMatrix& operator = (const FloatMatrix& a) = default;\n\n  ~FloatMatrix () = default;\n\n  FloatMatrix (octave_idx_type r, octave_idx_type c)\n    : FloatNDArray (dim_vector (r, c)) { }\n\n  FloatMatrix (octave_idx_type r, octave_idx_type c, float val)\n    : FloatNDArray (dim_vector (r, c), val) { }\n\n  FloatMatrix (const dim_vector& dv) : FloatNDArray (dv.redim (2)) { }\n\n  FloatMatrix (const dim_vector& dv, float val)\n    : FloatNDArray (dv.redim (2), val) { }\n\n  template <typename U>\n  FloatMatrix (const MArray<U>& a) : FloatNDArray (a.as_matrix ()) { }\n\n  template <typename U>\n  FloatMatrix (const Array<U>& a) : FloatNDArray (a.as_matrix ()) { }\n\n  explicit OCTAVE_API FloatMatrix (const FloatRowVector& rv);\n\n  explicit OCTAVE_API FloatMatrix (const FloatColumnVector& cv);\n\n  explicit OCTAVE_API FloatMatrix (const FloatDiagMatrix& a);\n\n  explicit OCTAVE_API FloatMatrix (const MDiagArray2<float>& a);\n\n  explicit OCTAVE_API FloatMatrix (const DiagArray2<float>& a);\n\n  explicit OCTAVE_API FloatMatrix (const PermMatrix& a);\n\n  explicit OCTAVE_API FloatMatrix (const boolMatrix& a);\n\n  explicit OCTAVE_API FloatMatrix (const charMatrix& a);\n\n  OCTAVE_API bool operator == (const FloatMatrix& a) const;\n  OCTAVE_API bool operator != (const FloatMatrix& a) const;\n\n  OCTAVE_API bool issymmetric () const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API FloatMatrix&\n  insert (const FloatMatrix& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatMatrix&\n  insert (const FloatRowVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatMatrix&\n  insert (const FloatColumnVector& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatMatrix&\n  insert (const FloatDiagMatrix& a, octave_idx_type r, octave_idx_type c);\n\n  OCTAVE_API FloatMatrix& fill (float val);\n  OCTAVE_API FloatMatrix&\n  fill (float val, octave_idx_type r1, octave_idx_type c1,\n        octave_idx_type r2, octave_idx_type c2);\n\n  OCTAVE_API FloatMatrix append (const FloatMatrix& a) const;\n  OCTAVE_API FloatMatrix append (const FloatRowVector& a) const;\n  OCTAVE_API FloatMatrix append (const FloatColumnVector& a) const;\n  OCTAVE_API FloatMatrix append (const FloatDiagMatrix& a) const;\n\n  OCTAVE_API FloatMatrix stack (const FloatMatrix& a) const;\n  OCTAVE_API FloatMatrix stack (const FloatRowVector& a) const;\n  OCTAVE_API FloatMatrix stack (const FloatColumnVector& a) const;\n  OCTAVE_API FloatMatrix stack (const FloatDiagMatrix& a) const;\n\n  friend OCTAVE_API FloatMatrix real (const FloatComplexMatrix& a);\n  friend OCTAVE_API FloatMatrix imag (const FloatComplexMatrix& a);\n\n  friend class FloatComplexMatrix;\n\n  FloatMatrix hermitian () const { return MArray<float>::transpose (); }\n  FloatMatrix transpose () const { return MArray<float>::transpose (); }\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API FloatMatrix\n  extract (octave_idx_type r1, octave_idx_type c1,\n           octave_idx_type r2, octave_idx_type c2) const;\n\n  OCTAVE_API FloatMatrix\n  extract_n (octave_idx_type r1, octave_idx_type c1,\n             octave_idx_type nr, octave_idx_type nc) const;\n\n  // extract row or column i.\n\n  OCTAVE_API FloatRowVector row (octave_idx_type i) const;\n\n  OCTAVE_API FloatColumnVector column (octave_idx_type i) const;\n\n  void resize (octave_idx_type nr, octave_idx_type nc, float rfv = 0)\n  {\n    MArray<float>::resize (dim_vector (nr, nc), rfv);\n  }\n\nprivate:\n  FloatMatrix tinverse (MatrixType& mattype, octave_idx_type& info,\n                        float& rcon, bool force, bool calc_cond) const;\n\n  FloatMatrix finverse (MatrixType& mattype, octave_idx_type& info,\n                        float& rcon, bool force, bool calc_cond) const;\n\npublic:\n  OCTAVE_API FloatMatrix inverse () const;\n  OCTAVE_API FloatMatrix inverse (octave_idx_type& info) const;\n  OCTAVE_API FloatMatrix\n  inverse (octave_idx_type& info, float& rcon,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API FloatMatrix inverse (MatrixType& mattype) const;\n  OCTAVE_API FloatMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info) const;\n  OCTAVE_API FloatMatrix\n  inverse (MatrixType& mattype, octave_idx_type& info, float& rcon,\n           bool force = false, bool calc_cond = true) const;\n\n  OCTAVE_API FloatMatrix pseudo_inverse (float tol = 0.0) const;\n\n  OCTAVE_API FloatComplexMatrix fourier () const;\n  OCTAVE_API FloatComplexMatrix ifourier () const;\n\n  OCTAVE_API FloatComplexMatrix fourier2d () const;\n  OCTAVE_API FloatComplexMatrix ifourier2d () const;\n\n  OCTAVE_API FloatDET determinant () const;\n  OCTAVE_API FloatDET determinant (octave_idx_type& info) const;\n  OCTAVE_API FloatDET\n  determinant (octave_idx_type& info, float& rcon,\n               bool calc_cond = true) const;\n  OCTAVE_API FloatDET\n  determinant (MatrixType& mattype, octave_idx_type& info, float& rcon,\n               bool calc_cond = true) const;\n\n  OCTAVE_API float rcond () const;\n  OCTAVE_API float rcond (MatrixType& mattype) const;\n\nprivate:\n  // Upper triangular matrix solvers\n  FloatMatrix utsolve (MatrixType& mattype, const FloatMatrix& b,\n                       octave_idx_type& info,\n                       float& rcon, solve_singularity_handler sing_handler,\n                       bool calc_cond = false,\n                       blas_trans_type transt = blas_no_trans) const;\n\n  // Lower triangular matrix solvers\n  FloatMatrix ltsolve (MatrixType& mattype, const FloatMatrix& b,\n                       octave_idx_type& info,\n                       float& rcon, solve_singularity_handler sing_handler,\n                       bool calc_cond = false,\n                       blas_trans_type transt = blas_no_trans) const;\n\n  // Full matrix solvers (lu/cholesky)\n  FloatMatrix fsolve (MatrixType& mattype, const FloatMatrix& b,\n                      octave_idx_type& info,\n                      float& rcon, solve_singularity_handler sing_handler,\n                      bool calc_cond = false) const;\n\npublic:\n  // Generic interface to solver with no probing of type\n  OCTAVE_API FloatMatrix\n  solve (MatrixType& mattype, const FloatMatrix& b) const;\n  OCTAVE_API FloatMatrix\n  solve (MatrixType& mattype, const FloatMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API FloatMatrix\n  solve (MatrixType& mattype, const FloatMatrix& b, octave_idx_type& info,\n         float& rcon) const;\n  OCTAVE_API FloatMatrix\n  solve (MatrixType& mattype, const FloatMatrix& b, octave_idx_type& info,\n         float& rcon, solve_singularity_handler sing_handler,\n         bool singular_fallback = true,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatComplexMatrix& b) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatComplexMatrix& b,\n         octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatComplexMatrix& b,\n         octave_idx_type& info, float& rcon) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (MatrixType& mattype, const FloatComplexMatrix& b,\n         octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler, bool singular_fallback = true,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatColumnVector\n  solve (MatrixType& mattype, const FloatColumnVector& b) const;\n  OCTAVE_API FloatColumnVector\n  solve (MatrixType& mattype, const FloatColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API FloatColumnVector\n  solve (MatrixType& mattype, const FloatColumnVector& b,\n         octave_idx_type& info, float& rcon) const;\n  OCTAVE_API FloatColumnVector\n  solve (MatrixType& mattype, const FloatColumnVector& b,\n         octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatComplexColumnVector& b) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatComplexColumnVector& b,\n         octave_idx_type& info) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatComplexColumnVector& b,\n         octave_idx_type& info, float& rcon) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (MatrixType& mattype, const FloatComplexColumnVector& b,\n         octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  // Generic interface to solver with probing of type\n  OCTAVE_API FloatMatrix solve (const FloatMatrix& b) const;\n  OCTAVE_API FloatMatrix\n  solve (const FloatMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API FloatMatrix\n  solve (const FloatMatrix& b, octave_idx_type& info, float& rcon) const;\n  OCTAVE_API FloatMatrix\n  solve (const FloatMatrix& b, octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexMatrix solve (const FloatComplexMatrix& b) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (const FloatComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (const FloatComplexMatrix& b, octave_idx_type& info,\n         float& rcon) const;\n  OCTAVE_API FloatComplexMatrix\n  solve (const FloatComplexMatrix& b, octave_idx_type& info,\n         float& rcon, solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatColumnVector solve (const FloatColumnVector& b) const;\n  OCTAVE_API FloatColumnVector\n  solve (const FloatColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API FloatColumnVector\n  solve (const FloatColumnVector& b, octave_idx_type& info, float& rcon) const;\n  OCTAVE_API FloatColumnVector\n  solve (const FloatColumnVector& b, octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatComplexColumnVector& b) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatComplexColumnVector& b, octave_idx_type& info,\n         float& rcon) const;\n  OCTAVE_API FloatComplexColumnVector\n  solve (const FloatComplexColumnVector& b, octave_idx_type& info, float& rcon,\n         solve_singularity_handler sing_handler,\n         blas_trans_type transt = blas_no_trans) const;\n\n  // Singular solvers\n  OCTAVE_API FloatMatrix lssolve (const FloatMatrix& b) const;\n  OCTAVE_API FloatMatrix\n  lssolve (const FloatMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API FloatMatrix\n  lssolve (const FloatMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API FloatMatrix\n  lssolve (const FloatMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank, float& rcon) const;\n\n  OCTAVE_API FloatComplexMatrix lssolve (const FloatComplexMatrix& b) const;\n  OCTAVE_API FloatComplexMatrix\n  lssolve (const FloatComplexMatrix& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexMatrix\n  lssolve (const FloatComplexMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API FloatComplexMatrix\n  lssolve (const FloatComplexMatrix& b, octave_idx_type& info,\n           octave_idx_type& rank, float& rcon) const;\n\n  OCTAVE_API FloatColumnVector lssolve (const FloatColumnVector& b) const;\n  OCTAVE_API FloatColumnVector\n  lssolve (const FloatColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API FloatColumnVector\n  lssolve (const FloatColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API FloatColumnVector\n  lssolve (const FloatColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank, float& rcon) const;\n\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatComplexColumnVector& b) const;\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatComplexColumnVector& b, octave_idx_type& info) const;\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank) const;\n  OCTAVE_API FloatComplexColumnVector\n  lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,\n           octave_idx_type& rank, float& rcon) const;\n\n  OCTAVE_API FloatMatrix& operator += (const FloatDiagMatrix& a);\n  OCTAVE_API FloatMatrix& operator -= (const FloatDiagMatrix& a);\n\n  // other operations\n\n  OCTAVE_API boolMatrix all (int dim = -1) const;\n  OCTAVE_API boolMatrix any (int dim = -1) const;\n\n  OCTAVE_API FloatMatrix flip (int dim = -1) const;\n  OCTAVE_API FloatMatrix cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatMatrix cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatMatrix prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API Matrix dprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatMatrix sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API Matrix dsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatMatrix sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API Matrix dsumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatMatrix abs () const;\n\n  OCTAVE_API FloatMatrix diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API FloatDiagMatrix diag (octave_idx_type m, octave_idx_type n) const;\n\n  OCTAVE_API FloatColumnVector row_min () const;\n  OCTAVE_API FloatColumnVector row_max () const;\n\n  OCTAVE_API FloatColumnVector row_min (Array<octave_idx_type>& index) const;\n  OCTAVE_API FloatColumnVector row_max (Array<octave_idx_type>& index) const;\n\n  OCTAVE_API FloatRowVector column_min () const;\n  OCTAVE_API FloatRowVector column_max () const;\n\n  OCTAVE_API FloatRowVector column_min (Array<octave_idx_type>& index) const;\n  OCTAVE_API FloatRowVector column_max (Array<octave_idx_type>& index) const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const FloatMatrix& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, FloatMatrix& a);\n};\n\n// Publish externally used friend functions.\n\nextern OCTAVE_API FloatMatrix real (const FloatComplexMatrix& a);\nextern OCTAVE_API FloatMatrix imag (const FloatComplexMatrix& a);\n\n// column vector by row vector -> matrix operations\n\nextern OCTAVE_API FloatMatrix operator * (const FloatColumnVector& a,\n                                          const FloatRowVector& b);\n\n// Other functions.\n\nextern OCTAVE_API FloatMatrix Givens (float, float);\n\nextern OCTAVE_API FloatMatrix Sylvester (const FloatMatrix&, const FloatMatrix&,\n                                         const FloatMatrix&);\n\nextern OCTAVE_API FloatMatrix xgemm (const FloatMatrix& a, const FloatMatrix& b,\n                                     blas_trans_type transa = blas_no_trans,\n                                     blas_trans_type transb = blas_no_trans);\n\nextern OCTAVE_API FloatMatrix operator * (const FloatMatrix& a,\n                                          const FloatMatrix& b);\n\nextern OCTAVE_API FloatMatrix min (float f, const FloatMatrix& m);\nextern OCTAVE_API FloatMatrix min (float f, const FloatMatrix& m,\n                                   const bool nanflag);\nextern OCTAVE_API FloatMatrix min (float f, const FloatMatrix& m,\n                                   const bool nanflag, const bool realabs);\nextern OCTAVE_API FloatMatrix min (const FloatMatrix& m, float f);\nextern OCTAVE_API FloatMatrix min (const FloatMatrix& m, float f,\n                                   const bool nanflag);\nextern OCTAVE_API FloatMatrix min (const FloatMatrix& m, float f,\n                                   const bool nanflag, const bool realabs);\nextern OCTAVE_API FloatMatrix min (const FloatMatrix& a, const FloatMatrix& b);\nextern OCTAVE_API FloatMatrix min (const FloatMatrix& a, const FloatMatrix& b,\n                                   const bool nanflag);\nextern OCTAVE_API FloatMatrix min (const FloatMatrix& a, const FloatMatrix& b,\n                                   const bool nanflag, const bool realabs);\n\nextern OCTAVE_API FloatMatrix max (float f, const FloatMatrix& m);\nextern OCTAVE_API FloatMatrix max (float f, const FloatMatrix& m,\n                                   const bool nanflag);\nextern OCTAVE_API FloatMatrix max (float f, const FloatMatrix& m,\n                                   const bool nanflag, const bool realabs);\nextern OCTAVE_API FloatMatrix max (const FloatMatrix& m, float f);\nextern OCTAVE_API FloatMatrix max (const FloatMatrix& m, float f,\n                                   const bool nanflag);\nextern OCTAVE_API FloatMatrix max (const FloatMatrix& m, float f,\n                                   const bool nanflag, const bool realabs);\nextern OCTAVE_API FloatMatrix max (const FloatMatrix& a, const FloatMatrix& b);\nextern OCTAVE_API FloatMatrix max (const FloatMatrix& a, const FloatMatrix& b,\n                                   const bool nanflag);\nextern OCTAVE_API FloatMatrix max (const FloatMatrix& a, const FloatMatrix& b,\n                                   const bool nanflag, const bool realabs);\n\nextern OCTAVE_API FloatMatrix linspace (const FloatColumnVector& x1,\n                                        const FloatColumnVector& x2,\n                                        octave_idx_type n);\n\nMS_CMP_OP_DECLS (FloatMatrix, float, OCTAVE_API)\nMS_BOOL_OP_DECLS (FloatMatrix, float, OCTAVE_API)\n\nSM_CMP_OP_DECLS (float, FloatMatrix, OCTAVE_API)\nSM_BOOL_OP_DECLS (float, FloatMatrix, OCTAVE_API)\n\nMM_CMP_OP_DECLS (FloatMatrix, FloatMatrix, OCTAVE_API)\nMM_BOOL_OP_DECLS (FloatMatrix, FloatMatrix, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, FloatMatrix, float)\n\ntemplate <typename T>\nvoid read_int (std::istream& is, bool swap_bytes, T& val);\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fNDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"Array-util.h\"\n#include \"f77-fcn.h\"\n#include \"fNDArray.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"mx-base.h\"\n#include \"mx-op-defs.h\"\n#include \"oct-error.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n\n#include \"bsxfun-defs.cc\"\n\nFloatNDArray::FloatNDArray (const charNDArray& a)\n  : MArray<float> (a.dims ())\n{\n  octave_idx_type n = a.numel ();\n  for (octave_idx_type i = 0; i < n; i++)\n    xelem (i) = static_cast<unsigned char> (a(i));\n}\n\n#if defined (HAVE_FFTW)\n\nFloatComplexNDArray\nFloatNDArray::fourier (int dim) const\n{\n  const dim_vector& dv = dims ();\n\n  if (dim > dv.ndims () || dim < 0)\n    return FloatComplexNDArray ();\n\n  octave_idx_type stride = 1;\n  octave_idx_type n = dv(dim);\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  octave_idx_type howmany = numel () / dv(dim);\n  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));\n  octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);\n  octave_idx_type dist = (stride == 1 ? n : 1);\n\n  const float *in (data ());\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out (retval.rwdata ());\n\n  // Need to be careful here about the distance between fft's\n  for (octave_idx_type k = 0; k < nloop; k++)\n    octave::fftw::fft (in + k * stride * n, out + k * stride * n,\n                       n, howmany, stride, dist);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatNDArray::ifourier (int dim) const\n{\n  const dim_vector& dv = dims ();\n\n  if (dim > dv.ndims () || dim < 0)\n    return FloatComplexNDArray ();\n\n  octave_idx_type stride = 1;\n  octave_idx_type n = dv(dim);\n\n  for (int i = 0; i < dim; i++)\n    stride *= dv(i);\n\n  octave_idx_type howmany = numel () / dv(dim);\n  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));\n  octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);\n  octave_idx_type dist = (stride == 1 ? n : 1);\n\n  FloatComplexNDArray retval (*this);\n  FloatComplex *out (retval.rwdata ());\n\n  // Need to be careful here about the distance between fft's\n  for (octave_idx_type k = 0; k < nloop; k++)\n    octave::fftw::ifft (out + k * stride * n, out + k * stride * n,\n                        n, howmany, stride, dist);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatNDArray::fourier2d () const\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 2)\n    return FloatComplexNDArray ();\n\n  dim_vector dv2 (dv(0), dv(1));\n  const float *in = data ();\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out = retval.rwdata ();\n  octave_idx_type howmany = numel () / dv(0) / dv(1);\n  octave_idx_type dist = dv(0) * dv(1);\n\n  for (octave_idx_type i=0; i < howmany; i++)\n    octave::fftw::fftNd (in + i*dist, out + i*dist, 2, dv2);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatNDArray::ifourier2d () const\n{\n  const dim_vector& dv = dims ();\n  if (dv.ndims () < 2)\n    return FloatComplexNDArray ();\n\n  dim_vector dv2 (dv(0), dv(1));\n  FloatComplexNDArray retval (*this);\n  FloatComplex *out = retval.rwdata ();\n  octave_idx_type howmany = numel () / dv(0) / dv(1);\n  octave_idx_type dist = dv(0) * dv(1);\n\n  for (octave_idx_type i=0; i < howmany; i++)\n    octave::fftw::ifftNd (out + i*dist, out + i*dist, 2, dv2);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatNDArray::fourierNd () const\n{\n  const dim_vector& dv = dims ();\n  int rank = dv.ndims ();\n\n  const float *in (data ());\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::fftNd (in, out, rank, dv);\n\n  return retval;\n}\n\nFloatComplexNDArray\nFloatNDArray::ifourierNd () const\n{\n  const dim_vector& dv = dims ();\n  int rank = dv.ndims ();\n\n  FloatComplexNDArray tmp (*this);\n  FloatComplex *in (tmp.rwdata ());\n  FloatComplexNDArray retval (dv);\n  FloatComplex *out (retval.rwdata ());\n\n  octave::fftw::ifftNd (in, out, rank, dv);\n\n  return retval;\n}\n\n#else\n\nFloatComplexNDArray\nFloatNDArray::fourier (int dim) const\n{\n  octave_unused_parameter (dim);\n\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatNDArray::ifourier (int dim) const\n{\n  octave_unused_parameter (dim);\n\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatNDArray::fourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatNDArray::ifourier2d () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatNDArray::fourierNd () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\nFloatComplexNDArray\nFloatNDArray::ifourierNd () const\n{\n  (*current_liboctave_error_handler)\n    (\"support for FFTW was unavailable or disabled when liboctave was built\");\n\n  return FloatComplexNDArray ();\n}\n\n#endif\n\n// unary operations\n\nboolNDArray\nFloatNDArray::operator ! () const\n{\n  if (any_element_is_nan ())\n    octave::err_nan_to_logical_conversion ();\n\n  return do_mx_unary_op<bool, float> (*this, mx_inline_not);\n}\n\nbool\nFloatNDArray::any_element_is_negative (bool neg_zero) const\n{\n  return (neg_zero ? test_all (octave::math::negative_sign)\n          : do_mx_check<float> (*this, mx_inline_any_negative));\n}\n\nbool\nFloatNDArray::any_element_is_positive (bool neg_zero) const\n{\n  return (neg_zero ? test_all (octave::math::positive_sign)\n          : do_mx_check<float> (*this, mx_inline_any_positive));\n}\n\nbool\nFloatNDArray::any_element_is_nan () const\n{\n  return do_mx_check<float> (*this, mx_inline_any_nan);\n}\n\nbool\nFloatNDArray::any_element_is_inf_or_nan () const\n{\n  return ! do_mx_check<float> (*this, mx_inline_all_finite);\n}\n\nbool\nFloatNDArray::any_element_not_one_or_zero () const\n{\n  return ! test_all (octave::is_one_or_zero);\n}\n\nbool\nFloatNDArray::all_elements_are_zero () const\n{\n  return test_all (octave::is_zero);\n}\n\nbool\nFloatNDArray::all_elements_are_int_or_inf_or_nan () const\n{\n  return test_all (octave::is_int_or_inf_or_nan);\n}\n\n// Return nonzero if any element of M is not an integer.  Also extract\n// the largest and smallest values and return them in MAX_VAL and MIN_VAL.\n\nbool\nFloatNDArray::all_integers (float& max_val, float& min_val) const\n{\n  octave_idx_type nel = numel ();\n\n  if (nel > 0)\n    {\n      max_val = elem (0);\n      min_val = elem (0);\n    }\n  else\n    return false;\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      float val = elem (i);\n\n      if (val > max_val)\n        max_val = val;\n\n      if (val < min_val)\n        min_val = val;\n\n      if (! octave::math::is_integer (val))\n        return false;\n    }\n\n  return true;\n}\n\nbool\nFloatNDArray::all_integers () const\n{\n  return test_all (octave::math::is_integer);\n}\n\nbool\nFloatNDArray::too_large_for_float () const\n{\n  return false;\n}\n\n// FIXME: this is not quite the right thing.\n\nboolNDArray\nFloatNDArray::all (int dim) const\n{\n  return do_mx_red_op<bool, float> (*this, dim, mx_inline_all);\n}\n\nboolNDArray\nFloatNDArray::any (int dim) const\n{\n  return do_mx_red_op<bool, float> (*this, dim, mx_inline_any);\n}\n\nFloatNDArray\nFloatNDArray::flip (int dim) const\n{\n  return do_mx_flip_op<float, float> (*this, dim, mx_inline_flip);\n}\n\nFloatNDArray\nFloatNDArray::cumprod (int dim, bool nanflag) const\n{\n  return do_mx_cum_op<float, float> (*this, dim, nanflag, mx_inline_cumprod);\n}\n\nFloatNDArray\nFloatNDArray::cumsum (int dim, bool nanflag) const\n{\n  return do_mx_cum_op<float, float> (*this, dim, nanflag, mx_inline_cumsum);\n}\n\nFloatNDArray\nFloatNDArray::prod (int dim, bool nanflag) const\n{\n  return do_mx_red_op<float, float> (*this, dim, nanflag, mx_inline_prod);\n}\n\nNDArray\nFloatNDArray::dprod (int dim, bool nanflag) const\n{\n  return do_mx_red_op<double, float> (*this, dim, nanflag, mx_inline_dprod);\n}\n\nFloatNDArray\nFloatNDArray::sum (int dim, bool nanflag) const\n{\n  return do_mx_red_op<float, float> (*this, dim, nanflag, mx_inline_sum);\n}\n\nNDArray\nFloatNDArray::dsum (int dim, bool nanflag) const\n{\n  return do_mx_red_op<double, float> (*this, dim, nanflag, mx_inline_dsum);\n}\n\nFloatNDArray\nFloatNDArray::sumsq (int dim, bool nanflag) const\n{\n  return do_mx_red_op<float, float> (*this, dim, nanflag, mx_inline_sumsq);\n}\n\nNDArray\nFloatNDArray::dsumsq (int dim, bool nanflag) const\n{\n  return do_mx_red_op<double, float> (*this, dim, nanflag, mx_inline_dsumsq);\n}\n\nFloatNDArray\nFloatNDArray::max (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<float> (*this, dim, nanflag, realabs, mx_inline_max);\n}\n\nFloatNDArray\nFloatNDArray::max (Array<octave_idx_type>& idx_arg,\n                   int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<float> (*this, idx_arg, dim,\n                                 nanflag, realabs, mx_inline_max);\n}\n\nFloatNDArray\nFloatNDArray::min (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<float> (*this, dim, nanflag, realabs, mx_inline_min);\n}\n\nFloatNDArray\nFloatNDArray::min (Array<octave_idx_type>& idx_arg,\n                   int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<float> (*this, idx_arg, dim,\n                                 nanflag, realabs, mx_inline_min);\n}\n\nFloatNDArray\nFloatNDArray::cummax (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<float> (*this, dim, nanflag,\n                                    realabs, mx_inline_cummax);\n}\n\nFloatNDArray\nFloatNDArray::cummax (Array<octave_idx_type>& idx_arg,\n                      int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<float> (*this, idx_arg, dim, nanflag,\n                                    realabs, mx_inline_cummax);\n}\n\nFloatNDArray\nFloatNDArray::cummin (int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<float> (*this, dim, nanflag,\n                                    realabs, mx_inline_cummin);\n}\n\nFloatNDArray\nFloatNDArray::cummin (Array<octave_idx_type>& idx_arg,\n                      int dim, bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<float> (*this, idx_arg, dim, nanflag,\n                                    realabs, mx_inline_cummin);\n}\n\nFloatNDArray\nFloatNDArray::diff (octave_idx_type order, int dim) const\n{\n  return do_mx_diff_op<float> (*this, dim, order, mx_inline_diff);\n}\n\nFloatNDArray\nFloatNDArray::concat (const FloatNDArray& rb,\n                      const Array<octave_idx_type>& ra_idx)\n{\n  if (rb.numel () > 0)\n    insert (rb, ra_idx);\n  return *this;\n}\n\nFloatComplexNDArray\nFloatNDArray::concat (const FloatComplexNDArray& rb,\n                      const Array<octave_idx_type>& ra_idx)\n{\n  FloatComplexNDArray retval (*this);\n  if (rb.numel () > 0)\n    retval.insert (rb, ra_idx);\n  return retval;\n}\n\ncharNDArray\nFloatNDArray::concat (const charNDArray& rb,\n                      const Array<octave_idx_type>& ra_idx)\n{\n  charNDArray retval (dims ());\n  octave_idx_type nel = numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      float d = elem (i);\n\n      if (octave::math::isnan (d))\n        (*current_liboctave_error_handler)\n          (\"invalid conversion from NaN to character\");\n\n      octave_idx_type ival = octave::math::nint_big (d);\n\n      if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())\n        // FIXME: is there something better to do?  Should we warn the user?\n        ival = 0;\n\n      retval.elem (i) = static_cast<char> (ival);\n    }\n\n  if (rb.isempty ())\n    return retval;\n\n  retval.insert (rb, ra_idx);\n  return retval;\n}\n\nFloatNDArray\nreal (const FloatComplexNDArray& a)\n{\n  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_real);\n}\n\nFloatNDArray\nimag (const FloatComplexNDArray& a)\n{\n  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_imag);\n}\n\nFloatNDArray&\nFloatNDArray::insert (const FloatNDArray& a,\n                      octave_idx_type r, octave_idx_type c)\n{\n  Array<float>::insert (a, r, c);\n  return *this;\n}\n\nFloatNDArray&\nFloatNDArray::insert (const FloatNDArray& a,\n                      const Array<octave_idx_type>& ra_idx)\n{\n  Array<float>::insert (a, ra_idx);\n  return *this;\n}\n\nFloatNDArray\nFloatNDArray::abs () const\n{\n  return do_mx_unary_map<float, float, std::abs> (*this);\n}\n\nboolNDArray\nFloatNDArray::isnan () const\n{\n  return do_mx_unary_map<bool, float, octave::math::isnan> (*this);\n}\n\nboolNDArray\nFloatNDArray::isinf () const\n{\n  return do_mx_unary_map<bool, float, octave::math::isinf> (*this);\n}\n\nboolNDArray\nFloatNDArray::isfinite () const\n{\n  return do_mx_unary_map<bool, float, octave::math::isfinite> (*this);\n}\n\nvoid\nFloatNDArray::increment_index (Array<octave_idx_type>& ra_idx,\n                               const dim_vector& dimensions,\n                               int start_dimension)\n{\n  ::increment_index (ra_idx, dimensions, start_dimension);\n}\n\noctave_idx_type\nFloatNDArray::compute_index (Array<octave_idx_type>& ra_idx,\n                             const dim_vector& dimensions)\n{\n  return ::compute_index (ra_idx, dimensions);\n}\n\nFloatNDArray\nFloatNDArray::diag (octave_idx_type k) const\n{\n  return MArray<float>::diag (k);\n}\n\nFloatNDArray\nFloatNDArray::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return MArray<float>::diag (m, n);\n}\n\n// This contains no information on the array structure !!!\nstd::ostream&\noperator << (std::ostream& os, const FloatNDArray& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      os << ' ';\n      octave::write_value<float> (os, a.elem (i));\n      os << \"\\n\";\n    }\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, FloatNDArray& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  if (nel > 0)\n    {\n      float tmp;\n      for (octave_idx_type i = 0; i < nel; i++)\n        {\n          tmp = octave::read_value<float> (is);\n          if (is)\n            a.elem (i) = tmp;\n          else\n            return is;\n        }\n    }\n\n  return is;\n}\n\nMINMAX_FCNS (FloatNDArray, float)\n\nNDS_CMP_OPS (FloatNDArray, float)\nNDS_BOOL_OPS (FloatNDArray, float)\n\nSND_CMP_OPS (float, FloatNDArray)\nSND_BOOL_OPS (float, FloatNDArray)\n\nNDND_CMP_OPS (FloatNDArray, FloatNDArray)\nNDND_BOOL_OPS (FloatNDArray, FloatNDArray)\n\nBSXFUN_STDOP_DEFS_MXLOOP (FloatNDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (FloatNDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, FloatNDArray, mx_inline_pow)\nBSXFUN_OP2_DEF_MXLOOP (pow, FloatComplexNDArray, FloatComplexNDArray,\n                       FloatNDArray, mx_inline_pow)\nBSXFUN_OP2_DEF_MXLOOP (pow, FloatComplexNDArray, FloatNDArray,\n                       FloatComplexNDArray, mx_inline_pow)\n"
  },
  {
    "path": "liboctave/array/fNDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fNDArray_h)\n#define octave_fNDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"intNDArray-fwd.h\"\n#include \"MArray.h\"\n#include \"bsxfun-decl.h\"\n#include \"mx-defs.h\"\n#include \"mx-op-decl.h\"\n\nclass OCTAVE_API FloatNDArray : public MArray<float>\n{\npublic:\n\n  FloatNDArray () : MArray<float> () { }\n\n  FloatNDArray (const dim_vector& dv) : MArray<float> (dv) { }\n\n  FloatNDArray (const dim_vector& dv, float val)\n    : MArray<float> (dv, val) { }\n\n  FloatNDArray (const FloatNDArray& a) : MArray<float> (a) { }\n\n  template <typename U>\n  FloatNDArray (const MArray<U>& a) : MArray<float> (a) { }\n\n  template <typename U>\n  FloatNDArray (const Array<U>& a) : MArray<float> (a) { }\n\n  template <typename U>\n  explicit FloatNDArray (const intNDArray<U>& a) : MArray<float> (a) { }\n\n  OCTAVE_API FloatNDArray (const charNDArray&);\n\n  FloatNDArray& operator = (const FloatNDArray& a)\n  {\n    MArray<float>::operator = (a);\n    return *this;\n  }\n\n  ~FloatNDArray () = default;\n\n  // unary operations\n\n  OCTAVE_API boolNDArray operator ! () const;\n\n  OCTAVE_API bool any_element_is_negative (bool = false) const;\n  OCTAVE_API bool any_element_is_positive (bool = false) const;\n  OCTAVE_API bool any_element_is_nan () const;\n  OCTAVE_API bool any_element_is_inf_or_nan () const;\n  OCTAVE_API bool any_element_not_one_or_zero () const;\n  OCTAVE_API bool all_elements_are_zero () const;\n  OCTAVE_API bool all_elements_are_int_or_inf_or_nan () const;\n  OCTAVE_API bool all_integers (float& max_val, float& min_val) const;\n  OCTAVE_API bool all_integers () const;\n  OCTAVE_API bool too_large_for_float () const;\n\n  // FIXME: this is not quite the right thing.\n\n  OCTAVE_API boolNDArray all (int dim = -1) const;\n  OCTAVE_API boolNDArray any (int dim = -1) const;\n\n  OCTAVE_API FloatNDArray flip (int dim = -1) const;\n  OCTAVE_API FloatNDArray cumprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatNDArray cumsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatNDArray prod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API NDArray dprod (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatNDArray sum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API NDArray dsum (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatNDArray sumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API NDArray dsumsq (int dim = -1, bool nanflag = false) const;\n  OCTAVE_API FloatNDArray\n  concat (const FloatNDArray& rb, const Array<octave_idx_type>& ra_idx);\n  OCTAVE_API FloatComplexNDArray\n  concat (const FloatComplexNDArray& rb, const Array<octave_idx_type>& ra_idx);\n  OCTAVE_API charNDArray\n  concat (const charNDArray& rb, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API FloatNDArray\n  max (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API FloatNDArray max (Array<octave_idx_type>& index, int dim = -1,\n                               bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API FloatNDArray\n  min (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API FloatNDArray min (Array<octave_idx_type>& index, int dim = -1,\n                               bool nanflag = true, bool realabs = true) const;\n\n  OCTAVE_API FloatNDArray\n  cummax (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API FloatNDArray cummax (Array<octave_idx_type>& index, int dim = -1,\n                                  bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API FloatNDArray\n  cummin (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API FloatNDArray cummin (Array<octave_idx_type>& index, int dim = -1,\n                                  bool nanflag = true, bool realabs = true) const;\n\n  OCTAVE_API FloatNDArray diff (octave_idx_type order = 1, int dim = -1) const;\n\n  OCTAVE_API FloatNDArray&\n  insert (const FloatNDArray& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API FloatNDArray&\n  insert (const FloatNDArray& a, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API FloatNDArray abs () const;\n  OCTAVE_API boolNDArray isnan () const;\n  OCTAVE_API boolNDArray isinf () const;\n  OCTAVE_API boolNDArray isfinite () const;\n\n  OCTAVE_API FloatComplexNDArray fourier (int dim = 1) const;\n  OCTAVE_API FloatComplexNDArray ifourier (int dim = 1) const;\n\n  OCTAVE_API FloatComplexNDArray fourier2d () const;\n  OCTAVE_API FloatComplexNDArray ifourier2d () const;\n\n  OCTAVE_API FloatComplexNDArray fourierNd () const;\n  OCTAVE_API FloatComplexNDArray ifourierNd () const;\n\n  friend OCTAVE_API FloatNDArray real (const FloatComplexNDArray& a);\n  friend OCTAVE_API FloatNDArray imag (const FloatComplexNDArray& a);\n\n  friend class FloatComplexNDArray;\n\n  FloatNDArray squeeze () const { return MArray<float>::squeeze (); }\n\n  static OCTAVE_API void\n  increment_index (Array<octave_idx_type>& ra_idx,\n                   const dim_vector& dimensions, int start_dimension = 0);\n\n  static OCTAVE_API octave_idx_type\n  compute_index (Array<octave_idx_type>& ra_idx, const dim_vector& dimensions);\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const FloatNDArray& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, FloatNDArray& a);\n\n  OCTAVE_API FloatNDArray diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API FloatNDArray diag (octave_idx_type m, octave_idx_type n) const;\n\n  FloatNDArray& changesign ()\n  {\n    MArray<float>::changesign ();\n    return *this;\n  }\n\n};\n\n// Publish externally used friend functions.\n\nextern OCTAVE_API FloatNDArray real (const FloatComplexNDArray& a);\nextern OCTAVE_API FloatNDArray imag (const FloatComplexNDArray& a);\n\nMINMAX_DECLS (FloatNDArray, float, OCTAVE_API)\n\nNDS_CMP_OP_DECLS (FloatNDArray, float, OCTAVE_API)\nNDS_BOOL_OP_DECLS (FloatNDArray, float, OCTAVE_API)\n\nSND_CMP_OP_DECLS (float, FloatNDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (float, FloatNDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (FloatNDArray, FloatNDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (FloatNDArray, FloatNDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, FloatNDArray, float)\n\nBSXFUN_STDOP_DECLS (FloatNDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (FloatNDArray, OCTAVE_API)\n\nBSXFUN_OP_DECL (pow, FloatNDArray, OCTAVE_API)\nBSXFUN_OP2_DECL (pow, FloatComplexNDArray, FloatComplexNDArray,\n                 FloatNDArray, OCTAVE_API)\nBSXFUN_OP2_DECL (pow, FloatComplexNDArray, FloatNDArray,\n                 FloatComplexNDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/fRowVector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <istream>\n#include <ostream>\n#include <type_traits>\n\n#include \"Array-util.h\"\n#include \"blas-proto.h\"\n#include \"mx-base.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n\n// Row Vector class.\n\nbool\nFloatRowVector::operator == (const FloatRowVector& a) const\n{\n  octave_idx_type len = numel ();\n  if (len != a.numel ())\n    return 0;\n  return mx_inline_equal (len, data (), a.data ());\n}\n\nbool\nFloatRowVector::operator != (const FloatRowVector& a) const\n{\n  return !(*this == a);\n}\n\nFloatRowVector&\nFloatRowVector::insert (const FloatRowVector& a, octave_idx_type c)\n{\n  octave_idx_type a_len = a.numel ();\n\n  if (c < 0 || c + a_len > numel ())\n    (*current_liboctave_error_handler) (\"range error for insert\");\n\n  if (a_len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < a_len; i++)\n        xelem (c+i) = a.elem (i);\n    }\n\n  return *this;\n}\n\nFloatRowVector&\nFloatRowVector::fill (float val)\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = 0; i < len; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatRowVector&\nFloatRowVector::fill (float val, octave_idx_type c1, octave_idx_type c2)\n{\n  octave_idx_type len = numel ();\n\n  if (c1 < 0 || c2 < 0 || c1 >= len || c2 >= len)\n    (*current_liboctave_error_handler) (\"range error for fill\");\n\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  if (c2 >= c1)\n    {\n      make_unique ();\n\n      for (octave_idx_type i = c1; i <= c2; i++)\n        xelem (i) = val;\n    }\n\n  return *this;\n}\n\nFloatRowVector\nFloatRowVector::append (const FloatRowVector& a) const\n{\n  octave_idx_type len = numel ();\n  octave_idx_type nc_insert = len;\n  FloatRowVector retval (len + a.numel ());\n  retval.insert (*this, 0);\n  retval.insert (a, nc_insert);\n  return retval;\n}\n\nFloatColumnVector\nFloatRowVector::transpose () const\n{\n  return MArray<float>::transpose ();\n}\n\nFloatRowVector\nreal (const FloatComplexRowVector& a)\n{\n  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_real);\n}\n\nFloatRowVector\nimag (const FloatComplexRowVector& a)\n{\n  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_imag);\n}\n\nFloatRowVector\nFloatRowVector::extract (octave_idx_type c1, octave_idx_type c2) const\n{\n  if (c1 > c2) { std::swap (c1, c2); }\n\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  FloatRowVector result (new_c);\n\n  for (octave_idx_type i = 0; i < new_c; i++)\n    result.xelem (i) = elem (c1+i);\n\n  return result;\n}\n\nFloatRowVector\nFloatRowVector::extract_n (octave_idx_type r1, octave_idx_type n) const\n{\n  FloatRowVector result (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    result.xelem (i) = elem (r1+i);\n\n  return result;\n}\n\n// row vector by matrix -> row vector\n\nFloatRowVector\noperator * (const FloatRowVector& v, const FloatMatrix& a)\n{\n  FloatRowVector retval;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  F77_INT a_nr = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (a_nr != len)\n    octave::err_nonconformant (\"operator *\", 1, len, a_nr, a_nc);\n\n  if (len == 0)\n    retval.resize (a_nc, 0.0);\n  else\n    {\n      // Transpose A to form A'*x == (x'*A)'\n\n      F77_INT ld = a_nr;\n\n      retval.resize (a_nc);\n      float *y = retval.rwdata ();\n\n      F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 (\"T\", 1),\n                               a_nr, a_nc, 1.0, a.data (),\n                               ld, v.data (), 1, 0.0, y, 1\n                               F77_CHAR_ARG_LEN (1)));\n    }\n\n  return retval;\n}\n\n// other operations\n\nfloat\nFloatRowVector::min () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0;\n\n  float res = elem (0);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (elem (i) < res)\n      res = elem (i);\n\n  return res;\n}\n\nfloat\nFloatRowVector::max () const\n{\n  octave_idx_type len = numel ();\n  if (len == 0)\n    return 0;\n\n  float res = elem (0);\n\n  for (octave_idx_type i = 1; i < len; i++)\n    if (elem (i) > res)\n      res = elem (i);\n\n  return res;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const FloatRowVector& a)\n{\n//  int field_width = os.precision () + 7;\n\n  for (octave_idx_type i = 0; i < a.numel (); i++)\n    os << ' ' /* setw (field_width) */ << a.elem (i);\n  return os;\n}\n\nstd::istream&\noperator >> (std::istream& is, FloatRowVector& a)\n{\n  octave_idx_type len = a.numel ();\n\n  if (len > 0)\n    {\n      float tmp;\n      for (octave_idx_type i = 0; i < len; i++)\n        {\n          is >> tmp;\n          if (is)\n            a.elem (i) = tmp;\n          else\n            break;\n        }\n    }\n  return is;\n}\n\n// other operations\n\nFloatRowVector\nlinspace (float x1, float x2, octave_idx_type n_in)\n{\n  FloatRowVector retval;\n\n  if (n_in < 1)\n    return retval;\n  else if (n_in == 1)\n    {\n      retval.resize (1, x2);\n      return retval;\n    }\n  else if (x1 == x2)\n    {\n      retval.resize (n_in, x2);\n      return retval;\n    }\n\n  // Use unsigned type (guaranteed n_in > 1 at this point) so that divisions\n  // by 2 can be replaced by compiler with shift right instructions.\n  typedef std::make_unsigned<octave_idx_type>::type unsigned_octave_idx_type;\n\n  unsigned_octave_idx_type n = n_in;\n\n  // Set endpoints, rather than calculate, for maximum accuracy.\n  retval.clear (n);\n  retval.xelem (0) = x1;\n  retval.xelem (n-1) = x2;\n\n  // Construct linspace symmetrically from both ends.\n  bool isnan_delta = false;\n  float delta = (x2 - x1) / (n - 1);\n  if (octave::math::isinf (delta))\n    {\n      delta = octave::numeric_limits<float>::NaN ();\n      isnan_delta = true;\n    }\n\n  unsigned_octave_idx_type n2 = n/2;\n  for (unsigned_octave_idx_type i = 1; i < n2; i++)\n    {\n      retval.xelem (i) = x1 + i*delta;\n      retval.xelem (n-1-i) = x2 - i*delta;\n    }\n  if (n % 2 == 1)  // Middle element if number of elements is odd.\n    {\n      if (x1 == -x2)\n        retval.xelem (n2) = 0;\n      else if (isnan_delta)\n        retval.xelem (n2) = octave::numeric_limits<float>::NaN ();\n      else\n        retval.xelem (n2) = (x1 + x2) / 2;\n    }\n\n  return retval;\n}\n\n// row vector by column vector -> scalar\n\nfloat\noperator * (const FloatRowVector& v, const FloatColumnVector& a)\n{\n  float retval = 0.0;\n\n  F77_INT len = octave::to_f77_int (v.numel ());\n\n  F77_INT a_len = octave::to_f77_int (a.numel ());\n\n  if (len != a_len)\n    octave::err_nonconformant (\"operator *\", len, a_len);\n\n  if (len != 0)\n    F77_FUNC (xsdot, XSDOT) (len, v.data (), 1, a.data (), 1, retval);\n\n  return retval;\n}\n\nFloatComplex\noperator * (const FloatRowVector& v, const FloatComplexColumnVector& a)\n{\n  FloatComplexRowVector tmp (v);\n  return tmp * a;\n}\n"
  },
  {
    "path": "liboctave/array/fRowVector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fRowVector_h)\n#define octave_fRowVector_h 1\n\n#include \"octave-config.h\"\n\n#include \"MArray.h\"\n#include \"mx-defs.h\"\n\nclass OCTAVE_API FloatRowVector : public MArray<float>\n{\npublic:\n\n  FloatRowVector () : MArray<float> (dim_vector (1, 0)) { }\n\n  explicit FloatRowVector (octave_idx_type n)\n    : MArray<float> (dim_vector (1, n)) { }\n\n  explicit FloatRowVector (const dim_vector& dv)\n    : MArray<float> (dv.as_row ()) { }\n\n  FloatRowVector (octave_idx_type n, float val)\n    : MArray<float> (dim_vector (1, n), val) { }\n\n  FloatRowVector (const FloatRowVector& a) : MArray<float> (a) { }\n\n  FloatRowVector (const MArray<float>& a) : MArray<float> (a.as_row ()) { }\n\n  FloatRowVector (const Array<float>& a) : MArray<float> (a.as_row ()) { }\n\n  FloatRowVector& operator = (const FloatRowVector& a)\n  {\n    MArray<float>::operator = (a);\n    return *this;\n  }\n\n  ~FloatRowVector () = default;\n\n  OCTAVE_API bool operator == (const FloatRowVector& a) const;\n  OCTAVE_API bool operator != (const FloatRowVector& a) const;\n\n  // destructive insert/delete/reorder operations\n\n  OCTAVE_API FloatRowVector&\n  insert (const FloatRowVector& a, octave_idx_type c);\n\n  OCTAVE_API FloatRowVector& fill (float val);\n  OCTAVE_API FloatRowVector&\n  fill (float val, octave_idx_type c1, octave_idx_type c2);\n\n  OCTAVE_API FloatRowVector append (const FloatRowVector& a) const;\n\n  OCTAVE_API FloatColumnVector transpose () const;\n\n  friend OCTAVE_API FloatRowVector real (const FloatComplexRowVector& a);\n  friend OCTAVE_API FloatRowVector imag (const FloatComplexRowVector& a);\n\n  // resize is the destructive equivalent for this one\n\n  OCTAVE_API FloatRowVector\n  extract (octave_idx_type c1, octave_idx_type c2) const;\n\n  OCTAVE_API FloatRowVector\n  extract_n (octave_idx_type c1, octave_idx_type n) const;\n\n  // row vector by matrix -> row vector\n\n  friend OCTAVE_API FloatRowVector\n  operator * (const FloatRowVector& a, const FloatMatrix& b);\n\n  // other operations\n\n  OCTAVE_API float min () const;\n  OCTAVE_API float max () const;\n\n  // i/o\n\n  friend OCTAVE_API std::ostream&\n  operator << (std::ostream& os, const FloatRowVector& a);\n  friend OCTAVE_API std::istream&\n  operator >> (std::istream& is, FloatRowVector& a);\n\n  void resize (octave_idx_type n, const float& rfv = 0)\n  {\n    Array<float>::resize (dim_vector (1, n), rfv);\n  }\n\n  void clear (octave_idx_type n)\n  { Array<float>::clear (1, n); }\n\n};\n\n// row vector by column vector -> scalar\n\nfloat OCTAVE_API operator * (const FloatRowVector& a,\n                             const FloatColumnVector& b);\n\nComplex OCTAVE_API operator * (const FloatRowVector& a,\n                               const ComplexColumnVector& b);\n\n// other operations\n\nOCTAVE_API FloatRowVector linspace (float x1, float x2, octave_idx_type n);\n\nMARRAY_FORWARD_DEFS (MArray, FloatRowVector, float)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/idx-vector.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <limits>\n#include <ostream>\n\n#include \"Array-oct.h\"\n#include \"Array-util.h\"\n#include \"Range.h\"\n#include \"Sparse.h\"\n#include \"idx-vector.h\"\n\n#include \"mappers.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n\nstatic constexpr octave_idx_type IDX_MAX = dim_vector::dim_max ();\n\n// Maximum IDX that can be resolved is set by maximum integer value when\n// octave_idx_type is int32_t, or by flintmax (2^53) when it is int64_t.\nstatic constexpr double IDX_MAX_DBL\n  = std::min (double (IDX_MAX),\n              double (static_cast<int64_t> (1) << std::numeric_limits<double>::digits));\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nOCTAVE_NORETURN static void err_invalid_range ()\n{\n  (*current_liboctave_error_handler) (\"invalid range used as index\");\n}\n\nOCTAVE_NORETURN static void\nerr_index_out_of_range ()\n{\n  (*current_liboctave_error_handler)\n    (\"internal error: idx_vector index out of range\");\n}\n\nidx_vector::idx_vector_rep *\nidx_vector::nil_rep ()\n{\n  static idx_vector_rep ivr;\n  return &ivr;\n}\n\nArray<octave_idx_type>\nidx_vector::idx_base_rep::as_array ()\n{\n  (*current_liboctave_error_handler)\n    (\"internal error: as_array not allowed for this index class\");\n\n  // Never actually executed, but required to silence compiler warning\n  return Array<octave_idx_type> ();\n}\n\nidx_vector::idx_colon_rep::idx_colon_rep (char c)\n  : idx_base_rep ()\n{\n  if (c != ':')\n    (*current_liboctave_error_handler)\n      (\"internal error: invalid character converted to idx_vector; must be ':'\");\n}\n\noctave_idx_type\nidx_vector::idx_colon_rep::checkelem (octave_idx_type i) const\n{\n  if (i < 0)\n    err_index_out_of_range ();\n\n  return i;\n}\n\nidx_vector::idx_base_rep *\nidx_vector::idx_colon_rep::sort_idx (Array<octave_idx_type>&)\n{\n  (*current_liboctave_error_handler)\n    (\"internal error: idx_colon_rep::sort_idx\");\n}\n\nstd::ostream&\nidx_vector::idx_colon_rep::print (std::ostream& os) const\n{\n  return os << ':';\n}\n\nidx_vector::idx_range_rep::idx_range_rep (octave_idx_type start,\n    octave_idx_type limit,\n    octave_idx_type step)\n  : idx_base_rep (), m_start(start),\n    // Round length away from zero to catch incomplete intervals\n    m_len (step\n           ? std::max ((limit - start + step - (step > 0 ? 1 : -1)) / step,\n                       static_cast<octave_idx_type> (0))\n           : -1),\n    m_step (step)\n{\n  if (m_len < 0)\n    err_invalid_range ();\n  if (m_start < 0)\n    err_invalid_index (m_start);\n  if (m_step < 0 && m_start + (m_len-1)*m_step < 0)\n    err_invalid_index (m_start + (m_len-1)*m_step);\n}\n\nidx_vector::idx_range_rep::idx_range_rep (const range<double>& r)\n  : idx_base_rep (), m_start (0), m_len (r.numel ()), m_step (1)\n{\n  if (m_len < 0)\n    err_invalid_range ();\n\n  if (m_len > 0)\n    {\n      if (r.all_elements_are_ints ())\n        {\n          m_start = static_cast<octave_idx_type> (r.base ()) - 1;\n          m_step = static_cast<octave_idx_type> (r.increment ());\n          if (m_start < 0)\n            err_invalid_index (m_start);\n          if (m_step < 0 && m_start + (m_len - 1)*m_step < 0)\n            err_invalid_index (m_start + (m_len - 1)*m_step);\n        }\n      else\n        {\n          // find first non-integer, then gripe about it\n          double b = r.base ();\n          double inc = r.increment ();\n          err_invalid_index (b != std::trunc (b) ? b : b + inc);\n        }\n    }\n}\n\noctave_idx_type\nidx_vector::idx_range_rep::checkelem (octave_idx_type i) const\n{\n  if (i < 0 || i >= m_len)\n    err_index_out_of_range ();\n\n  return m_start + i*m_step;\n}\n\nidx_vector::idx_base_rep *\nidx_vector::idx_range_rep::sort_uniq_clone (bool)\n{\n  if (m_step < 0)\n    return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT);\n  else\n    {\n      m_count++;\n      return this;\n    }\n}\n\nidx_vector::idx_base_rep *\nidx_vector::idx_range_rep::sort_idx (Array<octave_idx_type>& idx)\n{\n  if (m_step < 0 && m_len > 0)\n    {\n      idx.clear (1, m_len);\n      for (octave_idx_type i = 0; i < m_len; i++)\n        idx.xelem (i) = m_len - 1 - i;\n      return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT);\n    }\n  else\n    {\n      idx.clear (1, m_len);\n      for (octave_idx_type i = 0; i < m_len; i++)\n        idx.xelem (i) = i;\n      m_count++;\n      return this;\n    }\n}\n\nstd::ostream&\nidx_vector::idx_range_rep::print (std::ostream& os) const\n{\n  os << m_start << ':' << m_step << ':' << m_start + m_len *m_step;\n  return os;\n}\n\nrange<double>\nidx_vector::idx_range_rep::unconvert () const\n{\n  return range<double>::make_n_element_range\n         (static_cast<double> (m_start+1), static_cast<double> (m_step), m_len);\n}\n\nArray<octave_idx_type>\nidx_vector::idx_range_rep::as_array ()\n{\n  Array<octave_idx_type> retval (dim_vector (1, m_len));\n  for (octave_idx_type i = 0; i < m_len; i++)\n    retval.xelem (i) = m_start + i*m_step;\n\n  return retval;\n}\n\ninline octave_idx_type\nconvert_index (octave_idx_type i, octave_idx_type& ext)\n{\n  if (i <= 0)\n    err_invalid_index (i-1);\n\n  if (ext < i)\n    ext = i;\n\n  return i - 1;\n}\n\ninline octave_idx_type\nconvert_index (double x, octave_idx_type& ext)\n{\n  // NOTE: Benchmark before making any changes to this expression.\n  if (! std::isfinite (x)\n      || x <= 0\n      || x > IDX_MAX_DBL\n      || x != std::trunc (x))\n    err_invalid_index (x - 1.0);\n\n  octave_idx_type i = static_cast<octave_idx_type> (x);\n\n  return convert_index (i, ext);\n}\n\ninline octave_idx_type\nconvert_index (float x, octave_idx_type& ext)\n{\n  return convert_index (static_cast<double> (x), ext);\n}\n\ntemplate <typename T>\ninline octave_idx_type\nconvert_index (octave_int<T> x, octave_idx_type& ext)\n{\n  octave_idx_type i = octave_int<octave_idx_type> (x).value ();\n\n  return convert_index (i, ext);\n}\n\ninline octave_idx_type\nconvert_index (octave_int<uint64_t> x, octave_idx_type& ext)\n{\n  if (x.value () > static_cast<uint64_t> (IDX_MAX))\n    err_invalid_index (x.value () - 1);\n\n  octave_idx_type i = octave_int<octave_idx_type> (x).value ();\n\n  return convert_index (i, ext);\n}\n\ntemplate <typename T>\nidx_vector::idx_scalar_rep::idx_scalar_rep (T x)\n  : idx_base_rep (), m_data (0)\n{\n  octave_idx_type dummy = 0;\n\n  m_data = convert_index (x, dummy);\n}\n\nidx_vector::idx_scalar_rep::idx_scalar_rep (octave_idx_type i)\n  : idx_base_rep (), m_data (i)\n{\n  if (m_data < 0)\n    err_invalid_index (m_data);\n}\n\noctave_idx_type\nidx_vector::idx_scalar_rep::checkelem (octave_idx_type i) const\n{\n  if (i != 0)\n    err_index_out_of_range ();\n\n  return m_data;\n}\n\nidx_vector::idx_base_rep *\nidx_vector::idx_scalar_rep::sort_idx (Array<octave_idx_type>& idx)\n{\n  idx.clear (1, 1);\n  idx.fill (0);\n  m_count++;\n  return this;\n}\n\nstd::ostream&\nidx_vector::idx_scalar_rep::print (std::ostream& os) const\n{\n  return os << m_data;\n}\n\ndouble\nidx_vector::idx_scalar_rep::unconvert () const\n{\n  return m_data + 1;\n}\n\nArray<octave_idx_type>\nidx_vector::idx_scalar_rep::as_array ()\n{\n  return Array<octave_idx_type> (dim_vector (1, 1), m_data);\n}\n\ntemplate <typename T>\nidx_vector::idx_vector_rep::idx_vector_rep (const Array<T>& nda)\n  : idx_base_rep (), m_data (nullptr), m_len (nda.numel ()), m_ext (0),\n    m_aowner (nullptr), m_orig_dims (nda.dims ())\n{\n  if (m_len != 0)\n    {\n      std::unique_ptr<octave_idx_type []> d (new octave_idx_type [m_len]);\n\n      for (octave_idx_type i = 0; i < m_len; i++)\n        d[i] = convert_index (nda.xelem (i), m_ext);\n\n      m_data = d.release ();\n    }\n}\n\n// Note that this makes a shallow copy of the index array.\n\nidx_vector::idx_vector_rep::idx_vector_rep (const Array<octave_idx_type>& inda)\n  : idx_base_rep (), m_data (inda.data ()), m_len (inda.numel ()), m_ext (0),\n    m_aowner (new Array<octave_idx_type> (inda)), m_orig_dims (inda.dims ())\n{\n  if (m_len != 0)\n    {\n      octave_idx_type max = -1;\n      for (octave_idx_type i = 0; i < m_len; i++)\n        {\n          octave_idx_type k = inda.xelem (i);\n          if (k < 0)\n            err_invalid_index (k);\n          else if (k > max)\n            max = k;\n        }\n\n      m_ext = max + 1;\n    }\n}\n\nidx_vector::idx_vector_rep::idx_vector_rep (const Array<octave_idx_type>& inda,\n    octave_idx_type ext, direct)\n  : idx_base_rep (), m_data (inda.data ()), m_len (inda.numel ()),\n    m_ext (ext), m_aowner (new Array<octave_idx_type> (inda)),\n    m_orig_dims (inda.dims ())\n{\n  // No checking.\n  if (m_ext < 0)\n    {\n      octave_idx_type max = -1;\n      for (octave_idx_type i = 0; i < m_len; i++)\n        if (m_data[i] > max)\n          max = m_data[i];\n\n      m_ext = max + 1;\n    }\n}\n\nidx_vector::idx_vector_rep::idx_vector_rep (bool b)\n  : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0),\n    m_aowner (nullptr), m_orig_dims (m_len, m_len)\n{\n  if (m_len != 0)\n    {\n      octave_idx_type *d = new octave_idx_type [1];\n      d[0] = 0;\n      m_data = d;\n      m_ext = 1;\n    }\n}\n\nidx_vector::idx_vector_rep::idx_vector_rep (const Array<bool>& bnda,\n    octave_idx_type nnz)\n  : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (0),\n    m_aowner (nullptr), m_orig_dims ()\n{\n  if (nnz < 0)\n    m_len = bnda.nnz ();\n\n  const dim_vector dv = bnda.dims ();\n\n  m_orig_dims = dv.make_nd_vector (m_len);\n\n  if (m_len != 0)\n    {\n      octave_idx_type *d = new octave_idx_type [m_len];\n\n      octave_idx_type ntot = bnda.numel ();\n\n      octave_idx_type k = 0;\n      for (octave_idx_type i = 0; i < ntot; i++)\n        if (bnda.xelem (i))\n          d[k++] = i;\n\n      m_data = d;\n\n      m_ext = d[k-1] + 1;\n    }\n}\n\nidx_vector::idx_vector_rep::idx_vector_rep (const Sparse<bool>& bnda)\n  : idx_base_rep (), m_data (nullptr), m_len (bnda.nnz ()), m_ext (0),\n    m_aowner (nullptr), m_orig_dims ()\n{\n  const dim_vector dv = bnda.dims ();\n\n  m_orig_dims = dv.make_nd_vector (m_len);\n\n  if (m_len != 0)\n    {\n      octave_idx_type *d = new octave_idx_type [m_len];\n\n      octave_idx_type k = 0;\n      octave_idx_type nc = bnda.cols ();\n      octave_idx_type nr = bnda.rows ();\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        for (octave_idx_type i = bnda.cidx (j); i < bnda.cidx (j+1); i++)\n          if (bnda.data (i))\n            d[k++] = j * nr + bnda.ridx (i);\n\n      m_data = d;\n\n      m_ext = d[k-1] + 1;\n    }\n}\n\nidx_vector::idx_vector_rep::~idx_vector_rep ()\n{\n  if (m_aowner)\n    delete m_aowner;\n  else\n    delete [] m_data;\n}\n\noctave_idx_type\nidx_vector::idx_vector_rep::checkelem (octave_idx_type n) const\n{\n  if (n < 0 || n >= m_len)\n    err_invalid_index (n);\n\n  return xelem (n);\n}\n\nidx_vector::idx_base_rep *\nidx_vector::idx_vector_rep::sort_uniq_clone (bool uniq)\n{\n  if (m_len == 0)\n    {\n      m_count++;\n      return this;\n    }\n\n  // This is wrapped in unique_ptr so that we don't leak on out-of-memory.\n  std::unique_ptr<idx_vector_rep> new_rep\n  (new idx_vector_rep (nullptr, m_len, m_ext, m_orig_dims, DIRECT));\n\n  if (m_ext > m_len*math::log2 (1.0 + m_len))\n    {\n      // Use standard sort via octave_sort.\n      octave_idx_type *new_data = new octave_idx_type [m_len];\n      new_rep->m_data = new_data;\n\n      std::copy_n (m_data, m_len, new_data);\n      octave_sort<octave_idx_type> lsort;\n      lsort.set_compare (ASCENDING);\n      lsort.sort (new_data, m_len);\n\n      if (uniq)\n        {\n          octave_idx_type new_len = std::unique (new_data, new_data + m_len)\n                                    - new_data;\n          new_rep->m_len = new_len;\n          if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1)\n            new_rep->m_orig_dims = dim_vector (1, new_len);\n          else\n            new_rep->m_orig_dims = dim_vector (new_len, 1);\n        }\n    }\n  else if (uniq)\n    {\n      // Use two-pass bucket sort (only a mask array needed).\n      OCTAVE_LOCAL_BUFFER_INIT (bool, has, m_ext, false);\n      for (octave_idx_type i = 0; i < m_len; i++)\n        has[m_data[i]] = true;\n\n      octave_idx_type new_len = 0;\n      for (octave_idx_type i = 0; i < m_ext; i++)\n        new_len += has[i];\n\n      new_rep->m_len = new_len;\n      if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1)\n        new_rep->m_orig_dims = dim_vector (1, new_len);\n      else\n        new_rep->m_orig_dims = dim_vector (new_len, 1);\n\n      octave_idx_type *new_data = new octave_idx_type [new_len];\n      new_rep->m_data = new_data;\n\n      for (octave_idx_type i = 0, j = 0; i < m_ext; i++)\n        if (has[i])\n          new_data[j++] = i;\n    }\n  else\n    {\n      // Use two-pass bucket sort.\n      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, cnt, m_ext, 0);\n      for (octave_idx_type i = 0; i < m_len; i++)\n        cnt[m_data[i]]++;\n\n      octave_idx_type *new_data = new octave_idx_type [m_len];\n      new_rep->m_data = new_data;\n\n      for (octave_idx_type i = 0, j = 0; i < m_ext; i++)\n        {\n          for (octave_idx_type k = 0; k < cnt[i]; k++)\n            new_data[j++] = i;\n        }\n    }\n\n  return new_rep.release ();\n}\n\nidx_vector::idx_base_rep *\nidx_vector::idx_vector_rep::sort_idx (Array<octave_idx_type>& idx)\n{\n  // This is wrapped in unique_ptr so that we don't leak on out-of-memory.\n  std::unique_ptr<idx_vector_rep> new_rep\n  (new idx_vector_rep (nullptr, m_len, m_ext, m_orig_dims, DIRECT));\n\n  if (m_ext > m_len*math::log2 (1.0 + m_len))\n    {\n      // Use standard sort via octave_sort.\n      idx.clear (m_orig_dims);\n      octave_idx_type *idx_data = idx.rwdata ();\n      for (octave_idx_type i = 0; i < m_len; i++)\n        idx_data[i] = i;\n\n      octave_idx_type *new_data = new octave_idx_type [m_len];\n      new_rep->m_data = new_data;\n      std::copy_n (m_data, m_len, new_data);\n\n      octave_sort<octave_idx_type> lsort;\n      lsort.set_compare (ASCENDING);\n      lsort.sort (new_data, idx_data, m_len);\n    }\n  else\n    {\n      // Use two-pass bucket sort.\n      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, cnt, m_ext, 0);\n\n      for (octave_idx_type i = 0; i < m_len; i++)\n        cnt[m_data[i]]++;\n\n      idx.clear (m_orig_dims);\n      octave_idx_type *idx_data = idx.rwdata ();\n\n      octave_idx_type *new_data = new octave_idx_type [m_len];\n      new_rep->m_data = new_data;\n\n      for (octave_idx_type i = 0, k = 0; i < m_ext; i++)\n        {\n          octave_idx_type j = cnt[i];\n          cnt[i] = k;\n          k += j;\n        }\n\n      for (octave_idx_type i = 0; i < m_len; i++)\n        {\n          octave_idx_type j = m_data[i];\n          octave_idx_type k = cnt[j]++;\n          new_data[k] = j;\n          idx_data[k] = i;\n        }\n    }\n\n  return new_rep.release ();\n}\n\nstd::ostream&\nidx_vector::idx_vector_rep::print (std::ostream& os) const\n{\n  os << '[';\n\n  for (octave_idx_type i = 0; i < m_len - 1; i++)\n    os << m_data[i] << ',' << ' ';\n\n  if (m_len > 0)\n    os << m_data[m_len-1];\n\n  os << ']';\n\n  return os;\n}\n\nArray<double>\nidx_vector::idx_vector_rep::unconvert () const\n{\n  Array<double> retval (m_orig_dims);\n  for (octave_idx_type i = 0; i < m_len; i++)\n    retval.xelem (i) = m_data[i] + 1;\n  return retval;\n}\n\nArray<octave_idx_type>\nidx_vector::idx_vector_rep::as_array ()\n{\n  if (m_aowner)\n    return *m_aowner;\n  else\n    {\n      Array<octave_idx_type> retval (m_orig_dims);\n\n      if (m_data)\n        {\n          std::memcpy (retval.rwdata (), m_data, m_len* sizeof (octave_idx_type));\n          // Delete the old copy and share the m_data instead to save memory.\n          delete [] m_data;\n        }\n\n      m_data = retval.rwdata ();\n      m_aowner = new Array<octave_idx_type> (retval);\n\n      return retval;\n    }\n}\n\nidx_vector::idx_mask_rep::idx_mask_rep (bool b)\n  : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0),\n    m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims (m_len, m_len)\n{\n  if (m_len != 0)\n    {\n      bool *d = new bool [1];\n      d[0] = true;\n      m_data = d;\n      m_ext = 1;\n    }\n}\n\nidx_vector::idx_mask_rep::idx_mask_rep (const Array<bool>& bnda,\n                                        octave_idx_type nnz)\n  : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (bnda.numel ()),\n    m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims ()\n{\n  if (nnz < 0)\n    m_len = bnda.nnz ();\n\n  // We truncate the extent as much as possible.  For Matlab\n  // compatibility, but maybe it's not a bad idea anyway.\n  while (m_ext > 0 && ! bnda(m_ext-1))\n    m_ext--;\n\n  const dim_vector dv = bnda.dims ();\n\n  m_orig_dims = dv.make_nd_vector (m_len);\n\n  m_aowner = new Array<bool> (bnda);\n  m_data = bnda.data ();\n}\n\nidx_vector::idx_mask_rep::~idx_mask_rep ()\n{\n  if (m_aowner)\n    delete m_aowner;\n  else\n    delete [] m_data;\n}\n\noctave_idx_type\nidx_vector::idx_mask_rep::xelem (octave_idx_type n) const\n{\n  if (n == m_lsti + 1)\n    {\n      m_lsti = n;\n      while (! m_data[++m_lste]) ;\n    }\n  else\n    {\n      m_lsti = n++;\n      m_lste = -1;\n      while (n > 0)\n        if (m_data[++m_lste]) --n;\n    }\n  return m_lste;\n}\n\noctave_idx_type\nidx_vector::idx_mask_rep::checkelem (octave_idx_type n) const\n{\n  if (n < 0 || n >= m_len)\n    err_invalid_index (n);\n\n  return xelem (n);\n}\n\nstd::ostream&\nidx_vector::idx_mask_rep::print (std::ostream& os) const\n{\n  os << '[';\n\n  for (octave_idx_type i = 0; i < m_ext - 1; i++)\n    os << m_data[i] << ',' << ' ';\n\n  if (m_ext > 0)\n    os << m_data[m_ext-1];\n\n  os << ']';\n\n  return os;\n}\n\nArray<bool>\nidx_vector::idx_mask_rep::unconvert () const\n{\n  if (m_aowner)\n    return *m_aowner;\n  else\n    {\n      Array<bool> retval (dim_vector (m_ext, 1));\n      for (octave_idx_type i = 0; i < m_ext; i++)\n        retval.xelem (i) = m_data[i];\n      return retval;\n    }\n}\n\nArray<octave_idx_type>\nidx_vector::idx_mask_rep::as_array ()\n{\n  if (m_aowner)\n    return m_aowner->find ().reshape (m_orig_dims);\n  else\n    {\n      Array<bool> retval (m_orig_dims);\n      for (octave_idx_type i = 0, j = 0; i < m_ext; i++)\n        if (m_data[i])\n          retval.xelem (j++) = i;\n\n      return retval;\n    }\n}\n\nidx_vector::idx_base_rep *\nidx_vector::idx_mask_rep::sort_idx (Array<octave_idx_type>& idx)\n{\n  idx.clear (m_len, 1);\n  for (octave_idx_type i = 0; i < m_len; i++)\n    idx.xelem (i) = i;\n\n  m_count++;\n  return this;\n}\n\nconst idx_vector idx_vector::colon (new idx_vector::idx_colon_rep ());\n\nidx_vector::idx_vector (const Array<bool>& bnda)\n  : m_rep (nullptr)\n{\n  // Convert only if it means saving at least half the memory.\n  static constexpr int factor = (2 * sizeof (octave_idx_type));\n  octave_idx_type nnz = bnda.nnz ();\n  if (nnz <= bnda.numel () / factor)\n    m_rep = new idx_vector_rep (bnda, nnz);\n  else\n    m_rep = new idx_mask_rep (bnda, nnz);\n}\n\nbool\nidx_vector::maybe_reduce (octave_idx_type n, const idx_vector& j,\n                          octave_idx_type nj)\n{\n  bool reduced = false;\n\n  // Empty index always reduces.\n  if (m_rep->length (n) == 0)\n    {\n      *this = idx_vector ();\n      return true;\n    }\n\n  // Possibly skip singleton dims.\n  if (n == 1 && m_rep->is_colon_equiv (n))\n    {\n      *this = j;\n      return true;\n    }\n\n  if (nj == 1 && j.is_colon_equiv (nj))\n    return true;\n\n  switch (j.idx_class ())\n    {\n    case class_colon:\n      switch (m_rep->idx_class ())\n        {\n        case class_colon:\n          // (:,:) reduces to (:)\n          reduced = true;\n          break;\n\n        case class_scalar:\n          {\n            // (i,:) reduces to a range.\n            idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n            octave_idx_type k = r->get_data ();\n            *this = new idx_range_rep (k, nj, n, DIRECT);\n            reduced = true;\n          }\n          break;\n\n        case class_range:\n          {\n            // (i:k:end,:) reduces to a range if i <= k and k divides n.\n            idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n            octave_idx_type s = r->get_start ();\n            octave_idx_type l = r->length (n);\n            octave_idx_type t = r->get_step ();\n            if (l*t == n)\n              {\n                *this = new idx_range_rep (s, l * nj, t, DIRECT);\n                reduced = true;\n              }\n          }\n          break;\n\n        default:\n          break;\n        }\n      break;\n\n    case class_range:\n      switch (m_rep->idx_class ())\n        {\n        case class_colon:\n          {\n            // (:,i:j) reduces to a range (the m_step must be 1)\n            idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.m_rep);\n            if (rj->get_step () == 1)\n              {\n                octave_idx_type sj = rj->get_start ();\n                octave_idx_type lj = rj->length (nj);\n                *this = new idx_range_rep (sj * n, lj * n, 1, DIRECT);\n                reduced = true;\n              }\n          }\n          break;\n\n        case class_scalar:\n          {\n            // (k,i:d:j) reduces to a range.\n            idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n            idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.m_rep);\n            octave_idx_type k = r->get_data ();\n            octave_idx_type sj = rj->get_start ();\n            octave_idx_type lj = rj->length (nj);\n            octave_idx_type tj = rj->get_step ();\n            *this = new idx_range_rep (n * sj + k, lj, n * tj, DIRECT);\n            reduced = true;\n          }\n          break;\n\n        case class_range:\n          {\n            // (i:k:end,p:q) reduces to a range if i <= k and k divides n.\n            // (ones (1, m), ones (1, n)) reduces to (ones (1, m*n))\n            idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n            octave_idx_type s = r->get_start ();\n            octave_idx_type l = r->length (n);\n            octave_idx_type t = r->get_step ();\n            idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.m_rep);\n            octave_idx_type sj = rj->get_start ();\n            octave_idx_type lj = rj->length (nj);\n            octave_idx_type tj = rj->get_step ();\n            if ((l*t == n && tj == 1) || (t == 0 && tj == 0))\n              {\n                *this = new idx_range_rep (s + n * sj, l * lj, t, DIRECT);\n                reduced = true;\n              }\n          }\n          break;\n\n        default:\n          break;\n        }\n      break;\n\n    case class_scalar:\n      switch (m_rep->idx_class ())\n        {\n        case class_scalar:\n          {\n            // (i,j) reduces to a single index.\n            idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n            idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.m_rep);\n            octave_idx_type k = r->get_data () + n * rj->get_data ();\n            *this = new idx_scalar_rep (k, DIRECT);\n            reduced = true;\n          }\n          break;\n\n        case class_range:\n          {\n            // (i:d:j,k) reduces to a range.\n            idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n            idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.m_rep);\n            octave_idx_type s = r->get_start ();\n            octave_idx_type l = r->length (nj);\n            octave_idx_type t = r->get_step ();\n            octave_idx_type k = rj->get_data ();\n            *this = new idx_range_rep (n * k + s, l, t, DIRECT);\n            reduced = true;\n          }\n          break;\n\n        case class_colon:\n          {\n            // (:,k) reduces to a range.\n            idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.m_rep);\n            octave_idx_type k = rj->get_data ();\n            *this = new idx_range_rep (n * k, n, 1, DIRECT);\n            reduced = true;\n          }\n          break;\n\n        default:\n          break;\n        }\n      break;\n\n    default:\n      break;\n    }\n\n  return reduced;\n}\n\nbool\nidx_vector::is_cont_range (octave_idx_type n, octave_idx_type& l,\n                           octave_idx_type& u) const\n{\n  bool res = false;\n\n  switch (m_rep->idx_class ())\n    {\n    case class_colon:\n      l = 0; u = n;\n      res = true;\n      break;\n\n    case class_range:\n      {\n        idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n        if (r->get_step () == 1)\n          {\n            l = r->get_start ();\n            u = l + r->length (n);\n            res = true;\n          }\n      }\n      break;\n\n    case class_scalar:\n      {\n        idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n        l = r->get_data ();\n        u = l + 1;\n        res = true;\n      }\n      break;\n\n    case class_mask:\n      {\n        idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n        octave_idx_type m_ext = r->extent (0);\n        octave_idx_type m_len = r->length (0);\n        if (m_ext == m_len)\n          {\n            l = 0;\n            u = m_len;\n            res = true;\n          }\n      }\n\n    default:\n      break;\n    }\n\n  return res;\n}\n\noctave_idx_type\nidx_vector::increment () const\n{\n  octave_idx_type retval = 0;\n\n  switch (m_rep->idx_class ())\n    {\n    case class_colon:\n      retval = 1;\n      break;\n\n    case class_range:\n      retval = dynamic_cast<idx_range_rep *> (m_rep) -> get_step ();\n      break;\n\n    case class_vector:\n    case class_mask:\n      {\n        if (length (0) > 1)\n          retval = elem (1) - elem (0);\n      }\n      break;\n\n    default:\n      break;\n    }\n\n  return retval;\n}\n\nconst octave_idx_type *\nidx_vector::raw ()\n{\n  if (m_rep->idx_class () != class_vector)\n    *this = idx_vector (as_array (), extent (0));\n\n  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);\n\n  liboctave_panic_unless (r != nullptr);\n\n  return r->get_data ();\n}\n\nvoid\nidx_vector::copy_data (octave_idx_type *m_data) const\n{\n  octave_idx_type m_len = m_rep->length (0);\n\n  switch (m_rep->idx_class ())\n    {\n    case class_invalid:\n      (*current_liboctave_error_handler) (\"unexpected: invalid index\");\n      break;\n\n    case class_colon:\n      (*current_liboctave_error_handler) (\"colon not allowed\");\n      break;\n\n    case class_range:\n      {\n        idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n        octave_idx_type m_start = r->get_start ();\n        octave_idx_type m_step = r->get_step ();\n        octave_idx_type i, j;\n        if (m_step == 1)\n          for (i = m_start, j = m_start + m_len; i < j; i++) *m_data++ = i;\n        else if (m_step == -1)\n          for (i = m_start, j = m_start - m_len; i > j; i--) *m_data++ = i;\n        else\n          for (i = 0, j = m_start; i < m_len; i++, j += m_step) *m_data++ = j;\n      }\n      break;\n\n    case class_scalar:\n      {\n        idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n        *m_data = r->get_data ();\n      }\n      break;\n\n    case class_vector:\n      {\n        idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);\n        const octave_idx_type *rdata = r->get_data ();\n        std::copy_n (rdata, m_len, m_data);\n      }\n      break;\n\n    case class_mask:\n      {\n        idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n        const bool *mask = r->get_data ();\n        octave_idx_type m_ext = r->extent (0);\n        for (octave_idx_type i = 0, j = 0; i < m_ext; i++)\n          if (mask[i])\n            m_data[j++] = i;\n      }\n      break;\n\n      // We should have handled all possible enum values above.  Rely on\n      // compiler diagnostics to warn if we haven't.  For example, GCC's\n      // -Wswitch option, enabled by -Wall, will provide a warning.\n    }\n}\n\nidx_vector\nidx_vector::complement (octave_idx_type n) const\n{\n  idx_vector retval;\n  if (extent (n) > n)\n    (*current_liboctave_error_handler)\n      (\"internal error: out of range complement index requested\");\n\n  if (idx_class () == class_mask)\n    {\n      idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n      octave_idx_type nz = r->length (0);\n      octave_idx_type m_ext = r->extent (0);\n      Array<bool> mask (dim_vector (n, 1));\n      const bool *m_data = r->get_data ();\n      bool *ndata = mask.rwdata ();\n      for (octave_idx_type i = 0; i < m_ext; i++)\n        ndata[i] = ! m_data[i];\n      std::fill_n (ndata + m_ext, n - m_ext, true);\n      retval = new idx_mask_rep (mask, n - nz);\n    }\n  else\n    {\n      Array<bool> mask (dim_vector (n, 1), true);\n      fill (false, length (n), mask.rwdata ());\n      retval = idx_vector (mask);\n    }\n\n  return retval;\n}\n\nbool\nidx_vector::is_permutation (octave_idx_type n) const\n{\n  bool retval = false;\n\n  if (is_colon_equiv (n))\n    retval = true;\n  else if (length(n) == n && extent(n) == n)\n    {\n      OCTAVE_LOCAL_BUFFER_INIT (bool, left, n, true);\n\n      retval = true;\n\n      for (octave_idx_type i = 0, m_len = length (); i < m_len; i++)\n        {\n          octave_idx_type k = xelem (i);\n          if (left[k])\n            left[k] = false;\n          else\n            {\n              retval = false;\n              break;\n            }\n        }\n    }\n\n  return retval;\n}\n\nidx_vector\nidx_vector::inverse_permutation (octave_idx_type n) const\n{\n  liboctave_panic_unless (n == length (n));\n\n  idx_vector retval;\n\n  switch (idx_class ())\n    {\n    case class_range:\n      {\n        if (increment () == -1)\n          retval = sorted ();\n        else\n          retval = *this;\n        break;\n      }\n    case class_vector:\n      {\n        idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);\n        const octave_idx_type *ri = r->get_data ();\n        Array<octave_idx_type> idx (orig_dimensions ());\n        for (octave_idx_type i = 0; i < n; i++)\n          idx.xelem (ri[i]) = i;\n        retval = new idx_vector_rep (idx, r->extent (0), DIRECT);\n        break;\n      }\n    default:\n      retval = *this;\n      break;\n    }\n\n  return retval;\n}\n\nidx_vector\nidx_vector::unmask () const\n{\n  if (idx_class () == class_mask)\n    {\n      idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n      const bool *m_data = r->get_data ();\n      octave_idx_type m_ext = r->extent (0);\n      octave_idx_type m_len = r->length (0);\n      octave_idx_type *idata = new octave_idx_type [m_len];\n\n      for (octave_idx_type i = 0, j = 0; i < m_ext; i++)\n        if (m_data[i])\n          idata[j++] = i;\n\n      m_ext = (m_len > 0 ? idata[m_len - 1] + 1 : 0);\n\n      return new idx_vector_rep (idata, m_len, m_ext, r->orig_dimensions (),\n                                 DIRECT);\n    }\n  else\n    return *this;\n}\n\nvoid\nidx_vector::unconvert (idx_class_type& iclass,\n                       double& scalar, range<double>& range,\n                       Array<double>& array, Array<bool>& mask) const\n{\n  iclass = idx_class ();\n  switch (iclass)\n    {\n    case class_invalid:\n      (*current_liboctave_error_handler) (\"unexpected: invalid index\");\n      break;\n\n    case class_colon:\n      break;\n\n    case class_range:\n      {\n        idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n        range = r->unconvert ();\n      }\n      break;\n\n    case class_scalar:\n      {\n        idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n        scalar = r->unconvert ();\n      }\n      break;\n\n    case class_vector:\n      {\n        idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);\n        array = r->unconvert ();\n      }\n      break;\n\n    case class_mask:\n      {\n        idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n        mask = r->unconvert ();\n      }\n      break;\n\n      // We should have handled all possible enum values above.  Rely on\n      // compiler diagnostics to warn if we haven't.  For example, GCC's\n      // -Wswitch option, enabled by -Wall, will provide a warning.\n    }\n}\n\nArray<octave_idx_type>\nidx_vector::as_array () const\n{\n  return m_rep->as_array ();\n}\n\nbool\nidx_vector::isvector () const\n{\n  return idx_class () != class_vector || orig_dimensions ().isvector ();\n}\n\noctave_idx_type\nidx_vector::freeze (octave_idx_type z_len, const char *, bool resize_ok)\n{\n  if (! resize_ok && extent (z_len) > z_len)\n    (*current_liboctave_error_handler)\n      (\"invalid matrix index = %\" OCTAVE_IDX_TYPE_FORMAT, extent (z_len));\n\n  return length (z_len);\n}\n\noctave_idx_type\nidx_vector::ones_count () const\n{\n  octave_idx_type n = 0;\n\n  if (is_colon ())\n    n = 1;\n  else\n    {\n      for (octave_idx_type i = 0; i < length (1); i++)\n        if (xelem (i) == 0)\n          n++;\n    }\n\n  return n;\n}\n\n// Instantiate the octave_int constructors we want.\n#define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T)                          \\\n  template OCTAVE_API idx_vector::idx_scalar_rep::idx_scalar_rep (T);   \\\n  template OCTAVE_API idx_vector::idx_vector_rep::idx_vector_rep (const Array<T>&);\n\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (float)\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (double)\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int8)\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int16)\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int32)\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int64)\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint8)\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint16)\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint32)\nINSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint64)\n\nOCTAVE_END_NAMESPACE(octave)\n\n/*\n\n%!error id=Octave:index-out-of-bounds 1(find ([1,1] != 0))\n%!assert ((1:3)(find ([1,0,1] != 0)), [1,3])\n\n*/\n"
  },
  {
    "path": "liboctave/array/idx-vector.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_idx_vector_h)\n#define octave_idx_vector_h 1\n\n#include \"octave-config.h\"\n\n#include <cstring>\n\n#include <algorithm>\n#include <iosfwd>\n#include <memory>\n\n#include \"Array-fwd.h\"\n#include \"Sparse-fwd.h\"\n#include \"dim-vector.h\"\n#include \"oct-error.h\"\n#include \"oct-inttypes.h\"\n#include \"oct-refcount.h\"\n#include \"range-fwd.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Design rationale:\n//\n// idx_vector is a reference-counting, polymorphic pointer, that can\n// contain 4 types of index objects: a magic colon, a range, a scalar,\n// or an index vector.\n//\n// Polymorphic methods for single element access are provided, as well\n// as templates implementing \"early dispatch\", i.e., hoisting the checks\n// for index type out of loops.\n\nclass OCTAVE_API idx_vector\n{\npublic:\n\n  enum idx_class_type\n  {\n    class_invalid = -1,\n    class_colon = 0,\n    class_range,\n    class_scalar,\n    class_vector,\n    class_mask\n  };\n\n  template <typename T, typename D> friend class std::unique_ptr;\n\nprivate:\n\n  class OCTAVE_API idx_base_rep\n  {\n  public:\n\n    idx_base_rep () : m_count (1) { }\n\n    OCTAVE_DISABLE_COPY_MOVE (idx_base_rep)\n\n    virtual ~idx_base_rep () = default;\n\n    // Non-range-checking element query.\n    virtual octave_idx_type xelem (octave_idx_type i) const = 0;\n\n    // Range-checking element query.\n    virtual octave_idx_type checkelem (octave_idx_type i) const = 0;\n\n    // Length of the index vector.\n    virtual octave_idx_type length (octave_idx_type n) const = 0;\n\n    // The maximum index + 1.  The actual dimension is passed in.\n    virtual octave_idx_type extent (octave_idx_type n) const = 0;\n\n    // Index class.\n    virtual idx_class_type idx_class () const { return class_invalid; }\n\n    // Sorts, maybe uniqifies, and returns a clone object pointer.\n    virtual idx_base_rep * sort_uniq_clone (bool uniq = false) = 0;\n    // Sorts, and returns a sorting permutation (aka Array::sort).\n    virtual idx_base_rep * sort_idx (Array<octave_idx_type>&) = 0;\n\n    // Checks whether the index is colon or a range equivalent to colon.\n    virtual bool is_colon_equiv (octave_idx_type) const { return false; }\n\n    // The original dimensions of object (used when subscribing by matrices).\n    virtual dim_vector orig_dimensions () const { return dim_vector (); }\n\n    // i/o\n    virtual std::ostream& print (std::ostream& os) const = 0;\n\n    virtual Array<octave_idx_type> as_array ();\n\n    refcount<octave_idx_type> m_count;\n  };\n\n  // The magic colon index.\n  class OCTAVE_API idx_colon_rep : public idx_base_rep\n  {\n  public:\n\n    idx_colon_rep () = default;\n\n    OCTAVE_API idx_colon_rep (char c);\n\n    OCTAVE_DISABLE_COPY_MOVE (idx_colon_rep)\n\n    ~idx_colon_rep () = default;\n\n    octave_idx_type xelem (octave_idx_type i) const { return i; }\n\n    OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const;\n\n    octave_idx_type length (octave_idx_type n) const { return n; }\n\n    octave_idx_type extent (octave_idx_type n) const { return n; }\n\n    idx_class_type idx_class () const { return class_colon; }\n\n    idx_base_rep * sort_uniq_clone (bool = false)\n    { m_count++; return this; }\n\n    OCTAVE_NORETURN idx_base_rep * sort_idx (Array<octave_idx_type>&);\n\n    bool is_colon_equiv (octave_idx_type) const { return true; }\n\n    OCTAVE_API std::ostream& print (std::ostream& os) const;\n  };\n\n  // To distinguish the \"direct\" constructors that blindly trust the data.\n  enum direct { DIRECT };\n\n  // The integer range index.\n  class OCTAVE_API idx_range_rep : public idx_base_rep\n  {\n  public:\n\n    idx_range_rep () = delete;\n\n    idx_range_rep (octave_idx_type start, octave_idx_type len,\n                   octave_idx_type step, direct)\n      : idx_base_rep (), m_start (start), m_len (len), m_step (step) { }\n\n    // Zero-based constructor for index range starting at `start` (inclusive)\n    // and ending at `limit` (exclusive) in steps of `step`.\n    idx_range_rep (octave_idx_type start, octave_idx_type limit,\n                   octave_idx_type step);\n\n    OCTAVE_API idx_range_rep (const range<double>&);\n\n    OCTAVE_DISABLE_COPY_MOVE (idx_range_rep)\n\n    ~idx_range_rep () = default;\n\n    octave_idx_type xelem (octave_idx_type i) const\n    { return m_start + i * m_step; }\n\n    octave_idx_type checkelem (octave_idx_type i) const;\n\n    octave_idx_type length (octave_idx_type) const { return m_len; }\n\n    octave_idx_type extent (octave_idx_type n) const\n    {\n      return m_len ? std::max (n, m_start + 1 + (m_step < 0 ? 0 : m_step * (m_len - 1))) : n;\n    }\n\n    idx_class_type idx_class () const { return class_range; }\n\n    OCTAVE_API idx_base_rep * sort_uniq_clone (bool uniq = false);\n\n    OCTAVE_API idx_base_rep * sort_idx (Array<octave_idx_type>&);\n\n    bool is_colon_equiv (octave_idx_type n) const\n    { return m_start == 0 && m_step == 1 && m_len == n; }\n\n    dim_vector orig_dimensions () const\n    { return dim_vector (1, m_len); }\n\n    octave_idx_type get_start () const { return m_start; }\n\n    octave_idx_type get_step () const { return m_step; }\n\n    OCTAVE_API std::ostream& print (std::ostream& os) const;\n\n    OCTAVE_API range<double> unconvert () const;\n\n    OCTAVE_API Array<octave_idx_type> as_array ();\n\n  private:\n\n    octave_idx_type m_start, m_len, m_step;\n  };\n\n  // The integer scalar index.\n  class OCTAVE_API idx_scalar_rep : public idx_base_rep\n  {\n  public:\n\n    idx_scalar_rep () = delete;\n\n    idx_scalar_rep (octave_idx_type i, direct) : idx_base_rep (), m_data (i) { }\n\n    OCTAVE_DISABLE_COPY_MOVE (idx_scalar_rep)\n\n    ~idx_scalar_rep () = default;\n\n    // Zero-based constructor.\n    OCTAVE_API idx_scalar_rep (octave_idx_type i);\n\n    template <typename T>\n    idx_scalar_rep (T x);\n\n    octave_idx_type xelem (octave_idx_type) const { return m_data; }\n\n    OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const;\n\n    octave_idx_type length (octave_idx_type) const { return 1; }\n\n    octave_idx_type extent (octave_idx_type n) const\n    { return std::max (n, m_data + 1); }\n\n    idx_class_type idx_class () const { return class_scalar; }\n\n    idx_base_rep * sort_uniq_clone (bool = false)\n    { m_count++; return this; }\n\n    OCTAVE_API idx_base_rep * sort_idx (Array<octave_idx_type>&);\n\n    bool is_colon_equiv (octave_idx_type n) const\n    { return n == 1 && m_data == 0; }\n\n    dim_vector orig_dimensions () const { return dim_vector (1, 1); }\n\n    octave_idx_type get_data () const { return m_data; }\n\n    OCTAVE_API std::ostream& print (std::ostream& os) const;\n\n    OCTAVE_API double unconvert () const;\n\n    OCTAVE_API Array<octave_idx_type> as_array ();\n\n  private:\n\n    octave_idx_type m_data;\n  };\n\n  // The integer vector index.\n  class OCTAVE_API idx_vector_rep : public idx_base_rep\n  {\n  public:\n\n    idx_vector_rep ()\n      : m_data (nullptr), m_len (0), m_ext (0), m_aowner (nullptr), m_orig_dims () { }\n\n    // Direct constructor.\n    idx_vector_rep (octave_idx_type *data, octave_idx_type len,\n                    octave_idx_type ext, const dim_vector& od, direct)\n      : idx_base_rep (), m_data (data), m_len (len), m_ext (ext),\n        m_aowner (nullptr), m_orig_dims (od)\n    { }\n\n    // Zero-based constructor.\n    OCTAVE_API idx_vector_rep (const Array<octave_idx_type>& inda);\n\n    OCTAVE_API idx_vector_rep (const Array<octave_idx_type>& inda,\n                               octave_idx_type ext, direct);\n\n    template <typename T>\n    idx_vector_rep (const Array<T>&);\n\n    OCTAVE_API idx_vector_rep (bool);\n\n    OCTAVE_API idx_vector_rep (const Array<bool>&, octave_idx_type = -1);\n\n    OCTAVE_API idx_vector_rep (const Sparse<bool>&);\n\n    OCTAVE_DISABLE_COPY_MOVE (idx_vector_rep)\n\n    ~idx_vector_rep ();\n\n    octave_idx_type xelem (octave_idx_type i) const { return m_data[i]; }\n\n    OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const;\n\n    octave_idx_type length (octave_idx_type) const { return m_len; }\n\n    octave_idx_type extent (octave_idx_type n) const\n    { return std::max (n, m_ext); }\n\n    idx_class_type idx_class () const { return class_vector; }\n\n    idx_base_rep * sort_uniq_clone (bool uniq = false);\n\n    OCTAVE_API idx_base_rep * sort_idx (Array<octave_idx_type>&);\n\n    dim_vector orig_dimensions () const { return m_orig_dims; }\n\n    const octave_idx_type * get_data () const { return m_data; }\n\n    OCTAVE_API std::ostream& print (std::ostream& os) const;\n\n    OCTAVE_API Array<double> unconvert () const;\n\n    OCTAVE_API Array<octave_idx_type> as_array ();\n\n  private:\n\n    const octave_idx_type *m_data;\n    octave_idx_type m_len;\n    octave_idx_type m_ext;\n\n    // This is a trick to allow user-given zero-based arrays to be used\n    // as indices without copying.  If the following pointer is nonzero,\n    // we do not own the data, but rather have an Array<octave_idx_type>\n    // object that provides us the data.  Note that we need a pointer\n    // because we deferred the Array<T> declaration and we do not want\n    // it yet to be defined.\n\n    Array<octave_idx_type> *m_aowner;\n\n    dim_vector m_orig_dims;\n  };\n\n  // The logical mask index.\n  class OCTAVE_API idx_mask_rep : public idx_base_rep\n  {\n  public:\n\n    idx_mask_rep () = delete;\n\n    // Direct constructor.\n    idx_mask_rep (bool *data, octave_idx_type len,\n                  octave_idx_type ext, const dim_vector& od, direct)\n      : idx_base_rep (), m_data (data), m_len (len), m_ext (ext),\n        m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims (od)\n    { }\n\n    OCTAVE_API idx_mask_rep (bool);\n\n    OCTAVE_API idx_mask_rep (const Array<bool>&, octave_idx_type = -1);\n\n    OCTAVE_DISABLE_COPY_MOVE (idx_mask_rep)\n\n    OCTAVE_API ~idx_mask_rep ();\n\n    octave_idx_type xelem (octave_idx_type i) const;\n\n    octave_idx_type checkelem (octave_idx_type i) const;\n\n    octave_idx_type length (octave_idx_type) const { return m_len; }\n\n    octave_idx_type extent (octave_idx_type n) const\n    { return std::max (n, m_ext); }\n\n    idx_class_type idx_class () const { return class_mask; }\n\n    idx_base_rep * sort_uniq_clone (bool = false)\n    { m_count++; return this; }\n\n    OCTAVE_API idx_base_rep * sort_idx (Array<octave_idx_type>&);\n\n    dim_vector orig_dimensions () const { return m_orig_dims; }\n\n    bool is_colon_equiv (octave_idx_type n) const\n    { return m_len == n && m_ext == n; }\n\n    const bool * get_data () const { return m_data; }\n\n    OCTAVE_API std::ostream& print (std::ostream& os) const;\n\n    OCTAVE_API Array<bool> unconvert () const;\n\n    OCTAVE_API Array<octave_idx_type> as_array ();\n\n  private:\n\n    const bool *m_data;\n    octave_idx_type m_len;\n    octave_idx_type m_ext;\n\n    // FIXME: I'm not sure if this is a good design.  Maybe it would be\n    // better to employ some sort of generalized iteration scheme.\n    mutable octave_idx_type m_lsti;\n    mutable octave_idx_type m_lste;\n\n    // This is a trick to allow user-given mask arrays to be used as\n    // indices without copying.  If the following pointer is nonzero, we\n    // do not own the data, but rather have an Array<bool> object that\n    // provides us the data.  Note that we need a pointer because we\n    // deferred the Array<T> declaration and we do not want it yet to be\n    // defined.\n\n    Array<bool> *m_aowner;\n\n    dim_vector m_orig_dims;\n  };\n\n  idx_vector (idx_base_rep *r) : m_rep (r) { }\n\n  // The shared empty vector representation (for fast default\n  // constructor).\n  static OCTAVE_API idx_vector_rep * nil_rep ();\n\npublic:\n\n  // Fast empty constructor.\n  idx_vector () : m_rep (nil_rep ()) { m_rep->m_count++; }\n\n  // Zero-based constructors (for use from C++).\n  idx_vector (octave_idx_type i) : m_rep (new idx_scalar_rep (i)) { }\n\n#if OCTAVE_SIZEOF_INT != OCTAVE_SIZEOF_IDX_TYPE\n  idx_vector (int i)\n    : m_rep (new idx_scalar_rep (static_cast<octave_idx_type> (i))) { }\n#endif\n\n#if (OCTAVE_SIZEOF_F77_INT_TYPE != OCTAVE_SIZEOF_IDX_TYPE \\\n     && OCTAVE_SIZEOF_F77_INT_TYPE != OCTAVE_SIZEOF_INT)\n  idx_vector (octave_f77_int_type i)\n    : m_rep (new idx_scalar_rep (static_cast<octave_idx_type> (i))) { }\n#endif\n\n  idx_vector (octave_idx_type start, octave_idx_type limit,\n              octave_idx_type step = 1)\n    : m_rep (new idx_range_rep (start, limit, step)) { }\n\n  static idx_vector\n  make_range (octave_idx_type start, octave_idx_type step,\n              octave_idx_type len)\n  {\n    return idx_vector (new idx_range_rep (start, len, step, DIRECT));\n  }\n\n  idx_vector (const Array<octave_idx_type>& inda)\n    : m_rep (new idx_vector_rep (inda)) { }\n\n  // Directly pass extent, no checking.\n  idx_vector (const Array<octave_idx_type>& inda, octave_idx_type ext)\n    : m_rep (new idx_vector_rep (inda, ext, DIRECT)) { }\n\n  // Colon is best constructed by simply copying (or referencing) this member.\n  static const idx_vector colon;\n\n  // or passing ':' here\n  idx_vector (char c) : m_rep (new idx_colon_rep (c)) { }\n\n  // Conversion constructors (used by interpreter).\n\n  template <typename T>\n  idx_vector (octave_int<T> x) : m_rep (new idx_scalar_rep (x)) { }\n\n  idx_vector (double x) : m_rep (new idx_scalar_rep (x)) { }\n\n  idx_vector (float x) : m_rep (new idx_scalar_rep (x)) { }\n\n  // A scalar bool does not necessarily map to scalar index.\n  idx_vector (bool x) : m_rep (new idx_mask_rep (x)) { }\n\n  template <typename T>\n  idx_vector (const Array<octave_int<T>>& nda)\n    : m_rep (new idx_vector_rep (nda)) { }\n\n  idx_vector (const Array<double>& nda) : m_rep (new idx_vector_rep (nda)) { }\n\n  idx_vector (const Array<float>& nda) : m_rep (new idx_vector_rep (nda)) { }\n\n  OCTAVE_API idx_vector (const Array<bool>& nda);\n\n  idx_vector (const range<double>& r) : m_rep (new idx_range_rep (r)) { }\n\n  idx_vector (const Sparse<bool>& nda) : m_rep (new idx_vector_rep (nda)) { }\n\n  idx_vector (const idx_vector& a) : m_rep (a.m_rep) { m_rep->m_count++; }\n\n  ~idx_vector ()\n  {\n    if (--m_rep->m_count == 0 && m_rep != nil_rep ())\n      delete m_rep;\n  }\n\n  idx_vector& operator = (const idx_vector& a)\n  {\n    if (this != &a)\n      {\n        if (--m_rep->m_count == 0 && m_rep != nil_rep ())\n          delete m_rep;\n\n        m_rep = a.m_rep;\n        m_rep->m_count++;\n      }\n    return *this;\n  }\n\n  idx_class_type idx_class () const { return m_rep->idx_class (); }\n\n  octave_idx_type length (octave_idx_type n = 0) const\n  { return m_rep->length (n); }\n\n  octave_idx_type extent (octave_idx_type n) const\n  { return m_rep->extent (n); }\n\n  octave_idx_type xelem (octave_idx_type n) const\n  { return m_rep->xelem (n); }\n\n  octave_idx_type checkelem (octave_idx_type n) const\n  { return m_rep->xelem (n); }\n\n  octave_idx_type operator () (octave_idx_type n) const\n  { return m_rep->xelem (n); }\n\n  bool is_colon () const\n  { return m_rep->idx_class () == class_colon; }\n\n  bool is_scalar () const\n  { return m_rep->idx_class () == class_scalar; }\n\n  bool is_range () const\n  { return m_rep->idx_class () == class_range; }\n\n  bool is_colon_equiv (octave_idx_type n) const\n  { return m_rep->is_colon_equiv (n); }\n\n  idx_vector sorted (bool uniq = false) const\n  { return idx_vector (m_rep->sort_uniq_clone (uniq)); }\n\n  idx_vector sorted (Array<octave_idx_type>& sidx) const\n  { return idx_vector (m_rep->sort_idx (sidx)); }\n\n  dim_vector orig_dimensions () const { return m_rep->orig_dimensions (); }\n\n  octave_idx_type orig_rows () const\n  { return orig_dimensions () (0); }\n\n  octave_idx_type orig_columns () const\n  { return orig_dimensions () (1); }\n\n  int orig_empty () const\n  { return (! is_colon () && orig_dimensions ().any_zero ()); }\n\n  // i/o\n\n  std::ostream& print (std::ostream& os) const { return m_rep->print (os); }\n\n  friend std::ostream& operator << (std::ostream& os, const idx_vector& a)\n  { return a.print (os); }\n\n  // Slice with specializations.  No checking of bounds!\n  //\n  // This is equivalent to the following loop (but much faster):\n  //\n  // for (octave_idx_type i = 0; i < idx->length (n); i++)\n  //   dest[i] = src[idx(i)];\n  // return i;\n  //\n  template <typename T>\n  octave_idx_type\n  index (const T *src, octave_idx_type n, T *dest) const\n  {\n    octave_idx_type len = m_rep->length (n);\n\n    switch (m_rep->idx_class ())\n      {\n      case class_invalid:\n        (*current_liboctave_error_handler) (\"unexpected: invalid index\");\n        break;\n\n      case class_colon:\n        std::copy_n (src, len, dest);\n        break;\n\n      case class_range:\n        {\n          idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n          octave_idx_type start = r->get_start ();\n          octave_idx_type step = r->get_step ();\n          const T *ssrc = src + start;\n          if (step == 1)\n            std::copy_n (ssrc, len, dest);\n          else if (step == -1)\n            std::reverse_copy (ssrc - len + 1, ssrc + 1, dest);\n          else if (step == 0)\n            std::fill_n (dest, len, *ssrc);\n          else\n            {\n              for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)\n                dest[i] = ssrc[j];\n            }\n        }\n        break;\n\n      case class_scalar:\n        {\n          idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n          dest[0] = src[r->get_data ()];\n        }\n        break;\n\n      case class_vector:\n        {\n          idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);\n          const octave_idx_type *data = r->get_data ();\n          for (octave_idx_type i = 0; i < len; i++)\n            dest[i] = src[data[i]];\n        }\n        break;\n\n      case class_mask:\n        {\n          idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n          const bool *data = r->get_data ();\n          octave_idx_type ext = r->extent (0);\n          for (octave_idx_type i = 0; i < ext; i++)\n            if (data[i]) *dest++ = src[i];\n        }\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n    return len;\n  }\n\n  // Slice assignment with specializations.  No checking of bounds!\n  //\n  // This is equivalent to the following loop (but much faster):\n  //\n  // for (octave_idx_type i = 0; i < idx->length (n); i++)\n  //   dest[idx(i)] = src[i];\n  // return i;\n  //\n  template <typename T>\n  octave_idx_type\n  assign (const T *src, octave_idx_type n, T *dest) const\n  {\n    octave_idx_type len = m_rep->length (n);\n\n    switch (m_rep->idx_class ())\n      {\n      case class_invalid:\n        (*current_liboctave_error_handler) (\"unexpected: invalid index\");\n        break;\n\n      case class_colon:\n        std::copy_n (src, len, dest);\n        break;\n\n      case class_range:\n        {\n          idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n          octave_idx_type start = r->get_start ();\n          octave_idx_type step = r->get_step ();\n          T *sdest = dest + start;\n          if (step == 1)\n            std::copy_n (src, len, sdest);\n          else if (step == -1)\n            std::reverse_copy (src, src + len, sdest - len + 1);\n          else\n            {\n              for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)\n                sdest[j] = src[i];\n            }\n        }\n        break;\n\n      case class_scalar:\n        {\n          idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n          dest[r->get_data ()] = src[0];\n        }\n        break;\n\n      case class_vector:\n        {\n          idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);\n          const octave_idx_type *data = r->get_data ();\n          for (octave_idx_type i = 0; i < len; i++)\n            dest[data[i]] = src[i];\n        }\n        break;\n\n      case class_mask:\n        {\n          idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n          const bool *data = r->get_data ();\n          octave_idx_type ext = r->extent (0);\n          for (octave_idx_type i = 0; i < ext; i++)\n            if (data[i]) dest[i] = *src++;\n        }\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n    return len;\n  }\n\n  // Slice fill with specializations.  No checking of bounds!\n  //\n  // This is equivalent to the following loop (but much faster):\n  //\n  // for (octave_idx_type i = 0; i < idx->length (n); i++)\n  //   dest[idx(i)] = val;\n  // return i;\n  //\n  template <typename T>\n  octave_idx_type\n  fill (const T& val, octave_idx_type n, T *dest) const\n  {\n    octave_idx_type len = m_rep->length (n);\n\n    switch (m_rep->idx_class ())\n      {\n      case class_invalid:\n        (*current_liboctave_error_handler) (\"unexpected: invalid index\");\n        break;\n\n      case class_colon:\n        std::fill_n (dest, len, val);\n        break;\n\n      case class_range:\n        {\n          idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n          octave_idx_type start = r->get_start ();\n          octave_idx_type step = r->get_step ();\n          T *sdest = dest + start;\n          if (step == 1)\n            std::fill_n (sdest, len, val);\n          else if (step == -1)\n            std::fill (sdest - len + 1, sdest + 1, val);\n          else\n            {\n              for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)\n                sdest[j] = val;\n            }\n        }\n        break;\n\n      case class_scalar:\n        {\n          idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n          dest[r->get_data ()] = val;\n        }\n        break;\n\n      case class_vector:\n        {\n          idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);\n          const octave_idx_type *data = r->get_data ();\n          for (octave_idx_type i = 0; i < len; i++)\n            dest[data[i]] = val;\n        }\n        break;\n\n      case class_mask:\n        {\n          idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n          const bool *data = r->get_data ();\n          octave_idx_type ext = r->extent (0);\n          for (octave_idx_type i = 0; i < ext; i++)\n            if (data[i]) dest[i] = val;\n        }\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n    return len;\n  }\n\n  // Generic non-breakable indexed loop.  The loop body should be\n  // encapsulated in a single functor body.  This is equivalent to the\n  // following loop (but faster, at least for simple inlined bodies):\n  //\n  // for (octave_idx_type i = 0; i < idx->length (n); i++) body (idx(i));\n\n  template <typename Functor>\n  void\n  loop (octave_idx_type n, Functor body) const\n  {\n    octave_idx_type len = m_rep->length (n);\n\n    switch (m_rep->idx_class ())\n      {\n      case class_invalid:\n        (*current_liboctave_error_handler) (\"unexpected: invalid index\");\n        break;\n\n      case class_colon:\n        for (octave_idx_type i = 0; i < len; i++) body (i);\n        break;\n\n      case class_range:\n        {\n          idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n          octave_idx_type start = r->get_start ();\n          octave_idx_type step = r->get_step ();\n          octave_idx_type i, j;\n          if (step == 1)\n            for (i = start, j = start + len; i < j; i++) body (i);\n          else if (step == -1)\n            for (i = start, j = start - len; i > j; i--) body (i);\n          else\n            for (i = 0, j = start; i < len; i++, j += step) body (j);\n        }\n        break;\n\n      case class_scalar:\n        {\n          idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n          body (r->get_data ());\n        }\n        break;\n\n      case class_vector:\n        {\n          idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);\n          const octave_idx_type *data = r->get_data ();\n          for (octave_idx_type i = 0; i < len; i++) body (data[i]);\n        }\n        break;\n\n      case class_mask:\n        {\n          idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n          const bool *data = r->get_data ();\n          octave_idx_type ext = r->extent (0);\n          for (octave_idx_type i = 0; i < ext; i++)\n            if (data[i]) body (i);\n        }\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n  }\n\n  // Generic breakable indexed loop.  The loop body should be\n  // encapsulated in a single functor body.  This is equivalent to the\n  // following loop (but faster, at least for simple inlined bodies):\n  //\n  // for (octave_idx_type i = 0; i < idx->length (n); i++)\n  //   if (body (idx(i))) break;\n  // return i;\n  //\n\n  template <typename Functor>\n  octave_idx_type\n  bloop (octave_idx_type n, Functor body) const\n  {\n    octave_idx_type len = m_rep->length (n), ret;\n\n    switch (m_rep->idx_class ())\n      {\n      case class_invalid:\n        (*current_liboctave_error_handler) (\"unexpected: invalid index\");\n        break;\n\n      case class_colon:\n        {\n          octave_idx_type i;\n          for (i = 0; i < len && body (i); i++) ;\n          ret = i;\n        }\n        break;\n\n      case class_range:\n        {\n          idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);\n          octave_idx_type start = r->get_start ();\n          octave_idx_type step = r->get_step ();\n          octave_idx_type i, j;\n          if (step == 1)\n            for (i = start, j = start + len; i < j && body (i); i++) ;\n          else if (step == -1)\n            for (i = start, j = start - len; i > j && body (i); i--) ;\n          else\n            for (i = 0, j = start; i < len && body (j); i++, j += step) ;\n          ret = i;\n        }\n        break;\n\n      case class_scalar:\n        {\n          idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);\n          ret = (body (r->get_data ()) ? 1 : 0);\n        }\n        break;\n\n      case class_vector:\n        {\n          idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);\n          const octave_idx_type *data = r->get_data ();\n          octave_idx_type i;\n          for (i = 0; i < len && body (data[i]); i++) ;\n          ret = i;\n        }\n        break;\n\n      case class_mask:\n        {\n          idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);\n          const bool *data = r->get_data ();\n          octave_idx_type ext = r->extent (0);\n          octave_idx_type j = 0;\n          for (octave_idx_type i = 0; i < ext; i++)\n            {\n              if (data[i])\n                {\n                  if (body (i))\n                    break;\n                  else\n                    j++;\n                }\n            }\n\n          ret = j;\n        }\n        break;\n\n        // We should have handled all possible enum values above.  Rely\n        // on compiler diagnostics to warn if we haven't.  For example,\n        // GCC's -Wswitch option, enabled by -Wall, will provide a\n        // warning.\n      }\n\n    return ret;\n  }\n\n  // Rationale:\n  // This method is the key to \"smart indexing\".  When indexing cartesian\n  // arrays, sometimes consecutive index vectors can be reduced into a\n  // single index.  If rows (A) = k and i.maybe_reduce (j) gives k, then\n  // A(i,j)(:) is equal to A(k)(:).\n\n  // If the next index can be reduced, returns true and updates this.\n  OCTAVE_API bool\n  maybe_reduce (octave_idx_type n, const idx_vector& j, octave_idx_type nj);\n\n  OCTAVE_API bool\n  is_cont_range (octave_idx_type n, octave_idx_type& l,\n                 octave_idx_type& u) const;\n\n  // Returns the increment for ranges and colon, 0 for scalars and empty\n  // vectors, 1st difference otherwise.\n  OCTAVE_API octave_idx_type increment () const;\n\n  OCTAVE_API idx_vector\n  complement (octave_idx_type n) const;\n\n  OCTAVE_API bool is_permutation (octave_idx_type n) const;\n\n  // Returns the inverse permutation.  If this is not a permutation on 1:n, the\n  // result is undefined (but no error unless extent () != n).\n  OCTAVE_API idx_vector inverse_permutation (octave_idx_type n) const;\n\n  // Copies all the indices to a given array.  Not allowed for colons.\n  OCTAVE_API void copy_data (octave_idx_type *data) const;\n\n  // If the index is a mask, convert it to index vector.\n  OCTAVE_API idx_vector unmask () const;\n\n  // Unconverts the index to a scalar, Range, double array or a mask.\n  OCTAVE_API void\n  unconvert (idx_class_type& iclass, double& scalar, range<double>& range,\n             Array<double>& array, Array<bool>& mask) const;\n\n  OCTAVE_API Array<octave_idx_type> as_array () const;\n\n  // Raw pointer to index array.  This is non-const because it may be\n  // necessary to mutate the index.\n  const OCTAVE_API octave_idx_type * raw ();\n\n  OCTAVE_API bool isvector () const;\n\n  // FIXME: these are here for compatibility.  They should be removed\n  // when no longer in use.\n\n  octave_idx_type elem (octave_idx_type n) const\n  { return (*this) (n); }\n\n  bool is_colon_equiv (octave_idx_type n, int) const\n  { return is_colon_equiv (n); }\n\n  OCTAVE_API octave_idx_type\n  freeze (octave_idx_type z_len, const char *tag, bool resize_ok = false);\n\n  void sort (bool uniq = false)\n  { *this = sorted (uniq); }\n\n  OCTAVE_API octave_idx_type ones_count () const;\n\n  octave_idx_type max () const { return extent (1) - 1; }\n\nprivate:\n\n  idx_base_rep *m_rep;\n\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n// Provide the following typedef for backward compatibility.  Don't\n// deprecate (yet) because it is used extensively.\n\ntypedef octave::idx_vector idx_vector;\n\n#endif\n"
  },
  {
    "path": "liboctave/array/int16NDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"int16NDArray.h\"\n#include \"mx-op-defs.h\"\n#include \"intNDArray.cc\"\n\n#include \"bsxfun-defs.cc\"\n\nINSTANTIATE_INTNDARRAY (octave_int16);\n\ntemplate OCTAVE_API\nstd::ostream&\noperator << (std::ostream& os, const intNDArray<octave_int16>& a);\n\ntemplate OCTAVE_API\nstd::istream&\noperator >> (std::istream& is, intNDArray<octave_int16>& a);\n\nNDS_CMP_OPS (int16NDArray, octave_int16)\nNDS_BOOL_OPS (int16NDArray, octave_int16)\n\nSND_CMP_OPS (octave_int16, int16NDArray)\nSND_BOOL_OPS (octave_int16, int16NDArray)\n\nNDND_CMP_OPS (int16NDArray, int16NDArray)\nNDND_BOOL_OPS (int16NDArray, int16NDArray)\n\nMINMAX_FCNS (int16NDArray, octave_int16)\n\nBSXFUN_STDOP_DEFS_MXLOOP (int16NDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (int16NDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, int16NDArray, mx_inline_pow)\n\nBSXFUN_POW_MIXED_MXLOOP (int16NDArray)\n"
  },
  {
    "path": "liboctave/array/int16NDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_int16NDArray_h)\n#define octave_int16NDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"bsxfun-decl.h\"\n#include \"intNDArray.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-inttypes-fwd.h\"\n\ntypedef intNDArray<octave_int16> int16NDArray;\n\nNDS_CMP_OP_DECLS (int16NDArray, octave_int16, OCTAVE_API)\nNDS_BOOL_OP_DECLS (int16NDArray, octave_int16, OCTAVE_API)\n\nSND_CMP_OP_DECLS (octave_int16, int16NDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (octave_int16, int16NDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (int16NDArray, int16NDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (int16NDArray, int16NDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, int16NDArray, octave_int16)\n\nMINMAX_DECLS (int16NDArray, octave_int16, OCTAVE_API)\n\nBSXFUN_STDOP_DECLS (int16NDArray, OCTAVE_API)\nBSXFUN_MIXED_INT_DECLS(int16NDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (int16NDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/int32NDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"int32NDArray.h\"\n#include \"mx-op-defs.h\"\n#include \"intNDArray.cc\"\n\n#include \"bsxfun-defs.cc\"\n\nINSTANTIATE_INTNDARRAY (octave_int32);\n\ntemplate OCTAVE_API\nstd::ostream&\noperator << (std::ostream& os, const intNDArray<octave_int32>& a);\n\ntemplate OCTAVE_API\nstd::istream&\noperator >> (std::istream& is, intNDArray<octave_int32>& a);\n\nNDS_CMP_OPS (int32NDArray, octave_int32)\nNDS_BOOL_OPS (int32NDArray, octave_int32)\n\nSND_CMP_OPS (octave_int32, int32NDArray)\nSND_BOOL_OPS (octave_int32, int32NDArray)\n\nNDND_CMP_OPS (int32NDArray, int32NDArray)\nNDND_BOOL_OPS (int32NDArray, int32NDArray)\n\nMINMAX_FCNS (int32NDArray, octave_int32)\n\nBSXFUN_STDOP_DEFS_MXLOOP (int32NDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (int32NDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, int32NDArray, mx_inline_pow)\nBSXFUN_POW_MIXED_MXLOOP (int32NDArray)\n"
  },
  {
    "path": "liboctave/array/int32NDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_int32NDArray_h)\n#define octave_int32NDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"bsxfun-decl.h\"\n#include \"intNDArray.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-inttypes-fwd.h\"\n\ntypedef intNDArray<octave_int32> int32NDArray;\n\nNDS_CMP_OP_DECLS (int32NDArray, octave_int32, OCTAVE_API)\nNDS_BOOL_OP_DECLS (int32NDArray, octave_int32, OCTAVE_API)\n\nSND_CMP_OP_DECLS (octave_int32, int32NDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (octave_int32, int32NDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (int32NDArray, int32NDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (int32NDArray, int32NDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, int32NDArray, octave_int32)\n\nMINMAX_DECLS (int32NDArray, octave_int32, OCTAVE_API)\n\nBSXFUN_STDOP_DECLS (int32NDArray, OCTAVE_API)\nBSXFUN_MIXED_INT_DECLS(int32NDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (int32NDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/int64NDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"int64NDArray.h\"\n#include \"mx-op-defs.h\"\n#include \"intNDArray.cc\"\n\n#include \"bsxfun-defs.cc\"\n\nINSTANTIATE_INTNDARRAY (octave_int64);\n\ntemplate OCTAVE_API\nstd::ostream&\noperator << (std::ostream& os, const intNDArray<octave_int64>& a);\n\ntemplate OCTAVE_API\nstd::istream&\noperator >> (std::istream& is, intNDArray<octave_int64>& a);\n\nNDS_CMP_OPS (int64NDArray, octave_int64)\nNDS_BOOL_OPS (int64NDArray, octave_int64)\n\nSND_CMP_OPS (octave_int64, int64NDArray)\nSND_BOOL_OPS (octave_int64, int64NDArray)\n\nNDND_CMP_OPS (int64NDArray, int64NDArray)\nNDND_BOOL_OPS (int64NDArray, int64NDArray)\n\nMINMAX_FCNS (int64NDArray, octave_int64)\n\nBSXFUN_STDOP_DEFS_MXLOOP (int64NDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (int64NDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, int64NDArray, mx_inline_pow)\n\nBSXFUN_POW_MIXED_MXLOOP (int64NDArray)\n"
  },
  {
    "path": "liboctave/array/int64NDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_int64NDArray_h)\n#define octave_int64NDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"bsxfun-decl.h\"\n#include \"intNDArray.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-inttypes-fwd.h\"\n\ntypedef intNDArray<octave_int64> int64NDArray;\n\nNDS_CMP_OP_DECLS (int64NDArray, octave_int64, OCTAVE_API)\nNDS_BOOL_OP_DECLS (int64NDArray, octave_int64, OCTAVE_API)\n\nSND_CMP_OP_DECLS (octave_int64, int64NDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (octave_int64, int64NDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (int64NDArray, int64NDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (int64NDArray, int64NDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, int64NDArray, octave_int64)\n\nMINMAX_DECLS (int64NDArray, octave_int64, OCTAVE_API)\n\nBSXFUN_STDOP_DECLS (int64NDArray, OCTAVE_API)\nBSXFUN_MIXED_INT_DECLS(int64NDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (int64NDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/int8NDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"int8NDArray.h\"\n#include \"mx-op-defs.h\"\n#include \"intNDArray.cc\"\n\n#include \"bsxfun-defs.cc\"\n\nINSTANTIATE_INTNDARRAY (octave_int8);\n\ntemplate OCTAVE_API\nstd::ostream&\noperator << (std::ostream& os, const intNDArray<octave_int8>& a);\n\ntemplate OCTAVE_API\nstd::istream&\noperator >> (std::istream& is, intNDArray<octave_int8>& a);\n\nNDS_CMP_OPS (int8NDArray, octave_int8)\nNDS_BOOL_OPS (int8NDArray, octave_int8)\n\nSND_CMP_OPS (octave_int8, int8NDArray)\nSND_BOOL_OPS (octave_int8, int8NDArray)\n\nNDND_CMP_OPS (int8NDArray, int8NDArray)\nNDND_BOOL_OPS (int8NDArray, int8NDArray)\n\nMINMAX_FCNS (int8NDArray, octave_int8)\n\nBSXFUN_STDOP_DEFS_MXLOOP (int8NDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (int8NDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, int8NDArray, mx_inline_pow)\nBSXFUN_POW_MIXED_MXLOOP (int8NDArray)\n"
  },
  {
    "path": "liboctave/array/int8NDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_int8NDArray_h)\n#define octave_int8NDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"bsxfun-decl.h\"\n#include \"intNDArray.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-inttypes-fwd.h\"\n\ntypedef intNDArray<octave_int8> int8NDArray;\n\nNDS_CMP_OP_DECLS (int8NDArray, octave_int8, OCTAVE_API)\nNDS_BOOL_OP_DECLS (int8NDArray, octave_int8, OCTAVE_API)\n\nSND_CMP_OP_DECLS (octave_int8, int8NDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (octave_int8, int8NDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (int8NDArray, int8NDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (int8NDArray, int8NDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, int8NDArray, octave_int8)\n\nMINMAX_DECLS (int8NDArray, octave_int8, OCTAVE_API)\n\nBSXFUN_STDOP_DECLS (int8NDArray, OCTAVE_API)\nBSXFUN_MIXED_INT_DECLS(int8NDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (int8NDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/intNDArray-fwd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_intNDArray_fwd_h)\n#define octave_intNDArray_fwd_h 1\n\n#include \"octave-config.h\"\n\ntemplate <typename T> class OCTAVE_API intNDArray;\n\n#endif\n"
  },
  {
    "path": "liboctave/array/intNDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include \"Array-util.h\"\n#include \"mx-base.h\"\n#include \"lo-ieee.h\"\n#include \"mx-inlines.cc\"\n\n// unary operations\n\ntemplate <typename T>\nboolNDArray\nintNDArray<T>::operator ! () const\n{\n  boolNDArray b (this->dims ());\n\n  for (octave_idx_type i = 0; i < this->numel (); i++)\n    b.elem (i) = ! this->elem (i);\n\n  return b;\n}\n\ntemplate <typename T>\nbool\nintNDArray<T>::any_element_not_one_or_zero () const\n{\n  octave_idx_type nel = this->numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      T val = this->elem (i);\n\n      if (val != 0.0 && val != 1.0)\n        return true;\n    }\n\n  return false;\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::diag (octave_idx_type k) const\n{\n  return MArray<T>::diag (k);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::diag (octave_idx_type m, octave_idx_type n) const\n{\n  return MArray<T>::diag (m, n);\n}\n\n// FIXME: this is not quite the right thing.\n\ntemplate <typename T>\nboolNDArray\nintNDArray<T>::all (int dim) const\n{\n  return do_mx_red_op<bool, T > (*this, dim, mx_inline_all);\n}\n\ntemplate <typename T>\nboolNDArray\nintNDArray<T>::any (int dim) const\n{\n  return do_mx_red_op<bool, T > (*this, dim, mx_inline_any);\n}\n\ntemplate <typename T>\nvoid\nintNDArray<T>::increment_index (Array<octave_idx_type>& ra_idx,\n                                const dim_vector& dimensions,\n                                int start_dimension)\n{\n  ::increment_index (ra_idx, dimensions, start_dimension);\n}\n\ntemplate <typename T>\noctave_idx_type\nintNDArray<T>::compute_index (Array<octave_idx_type>& ra_idx,\n                              const dim_vector& dimensions)\n{\n  return ::compute_index (ra_idx, dimensions);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::concat (const intNDArray<T>& rb,\n                       const Array<octave_idx_type>& ra_idx)\n{\n  if (rb.numel () > 0)\n    insert (rb, ra_idx);\n  return *this;\n}\n\ntemplate <typename T>\nintNDArray<T>&\nintNDArray<T>::insert (const intNDArray<T>& a, octave_idx_type r,\n                       octave_idx_type c)\n{\n  Array<T>::insert (a, r, c);\n  return *this;\n}\n\ntemplate <typename T>\nintNDArray<T>&\nintNDArray<T>::insert (const intNDArray<T>& a,\n                       const Array<octave_idx_type>& ra_idx)\n{\n  Array<T>::insert (a, ra_idx);\n  return *this;\n}\n\n// This contains no information on the array structure !!!\n\ntemplate <typename T>\nstd::ostream&\noperator << (std::ostream& os, const intNDArray<T>& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    os << ' ' << a.elem (i) << \"\\n\";\n\n  return os;\n}\n\ntemplate <typename T>\nstd::istream&\noperator >> (std::istream& is, intNDArray<T>& a)\n{\n  octave_idx_type nel = a.numel ();\n\n  if (nel > 0)\n    {\n      T tmp;\n\n      for (octave_idx_type i = 0; i < nel; i++)\n        {\n          is >> tmp;\n\n          if (is)\n            a.elem (i) = tmp;\n          else\n            return is;\n        }\n    }\n\n  return is;\n}\n\n// FIXME: should abs and signum just be mapper functions?\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::abs () const\n{\n  octave_idx_type nel = this->numel ();\n  intNDArray<T> ret (this->dims ());\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      T val = this->elem (i);\n      ret.xelem (i) = val.abs ();\n    }\n\n  return ret;\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::signum () const\n{\n  octave_idx_type nel = this->numel ();\n  intNDArray<T> ret (this->dims ());\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    {\n      T val = this->elem (i);\n      ret.xelem (i) = val.signum ();\n    }\n\n  return ret;\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::flip (int dim) const\n{\n  return do_mx_flip_op<T, T> (*this, dim, mx_inline_flip);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::cumprod (int dim) const\n{\n  return do_mx_cum_op<T, T> (*this, dim, mx_inline_cumprod);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::cumsum (int dim) const\n{\n  return do_mx_cum_op<T, T> (*this, dim, mx_inline_cumsum);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::prod (int dim) const\n{\n  return do_mx_red_op<T, T> (*this, dim, mx_inline_prod);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::sum (int dim) const\n{\n  return do_mx_red_op<T, T> (*this, dim, mx_inline_sum);\n}\n\ntemplate <typename T>\nNDArray\nintNDArray<T>::dsum (int dim) const\n{\n  return do_mx_red_op<double, T> (*this, dim, mx_inline_dsum);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::sumsq (int dim) const\n{\n  return do_mx_red_op<T, T> (*this, dim, mx_inline_sumsq);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::max (int dim, [[maybe_unused]] bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<T> (*this, dim, realabs, mx_inline_intmax);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::max (Array<octave_idx_type>& idx_arg,\n                    int dim, [[maybe_unused]] bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<T> (*this, idx_arg, dim, realabs, mx_inline_intmax);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::min (int dim, [[maybe_unused]] bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<T> (*this, dim, realabs, mx_inline_intmin);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::min (Array<octave_idx_type>& idx_arg,\n                    int dim, [[maybe_unused]] bool nanflag, bool realabs) const\n{\n  return do_mx_minmax_op<T> (*this, idx_arg, dim, realabs, mx_inline_intmin);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::cummax (int dim, [[maybe_unused]] bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<T> (*this, dim, realabs, mx_inline_intcummax);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::cummax (Array<octave_idx_type>& idx_arg,\n                       int dim, [[maybe_unused]] bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<T> (*this, idx_arg, dim, realabs, mx_inline_intcummax);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::cummin (int dim, [[maybe_unused]] bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<T> (*this, dim, realabs, mx_inline_intcummin);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::cummin (Array<octave_idx_type>& idx_arg,\n                       int dim, [[maybe_unused]] bool nanflag, bool realabs) const\n{\n  return do_mx_cumminmax_op<T> (*this, idx_arg, dim, realabs, mx_inline_intcummin);\n}\n\ntemplate <typename T>\nintNDArray<T>\nintNDArray<T>::diff (octave_idx_type order, int dim) const\n{\n  return do_mx_diff_op<T> (*this, dim, order, mx_inline_diff);\n}\n\n#if defined (__clang__)\n#  define INSTANTIATE_INTNDARRAY(T) template class OCTAVE_API intNDArray<T>\n#else\n#  define INSTANTIATE_INTNDARRAY(T) template class intNDArray<T>\n#endif\n"
  },
  {
    "path": "liboctave/array/intNDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_intNDArray_h)\n#define octave_intNDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"intNDArray-fwd.h\"\n#include \"mx-fwd.h\"\n#include \"MArray.h\"\n#include \"boolNDArray.h\"\n\ntemplate <typename T>\nclass intNDArray : public MArray<T>\n{\npublic:\n\n  using typename MArray<T>::element_type;\n\n  intNDArray () = default;\n\n  intNDArray (const intNDArray<T>& a) = default;\n\n  intNDArray& operator = (const intNDArray<T>& a) = default;\n\n  ~intNDArray () = default;\n\n  intNDArray (T val) : MArray<T> (dim_vector (1, 1), val) { }\n\n  intNDArray (const dim_vector& dv) : MArray<T> (dv) { }\n\n  intNDArray (const dim_vector& dv, T val)\n    : MArray<T> (dv, val) { }\n\n  template <typename U>\n  intNDArray (const Array<U>& a) : MArray<T> (a) { }\n\n  template <typename U>\n  intNDArray (const MArray<U>& a) : MArray<T> (a) { }\n\n  template <typename U>\n  intNDArray (const intNDArray<U>& a) : MArray<T> (a) { }\n\n  OCTAVE_API boolNDArray operator ! () const;\n\n  bool any_element_is_nan () const { return false; }\n  OCTAVE_API bool any_element_not_one_or_zero () const;\n\n  OCTAVE_API intNDArray diag (octave_idx_type k = 0) const;\n\n  OCTAVE_API intNDArray diag (octave_idx_type m, octave_idx_type n) const;\n\n  intNDArray& changesign ()\n  {\n    MArray<T>::changesign ();\n    return *this;\n  }\n\n  // FIXME: this is not quite the right thing.\n\n  OCTAVE_API boolNDArray all (int dim = -1) const;\n  OCTAVE_API boolNDArray any (int dim = -1) const;\n\n  OCTAVE_API intNDArray flip (int dim) const;\n  OCTAVE_API intNDArray cumprod (int dim) const;\n  OCTAVE_API intNDArray cumsum (int dim) const;\n  OCTAVE_API intNDArray prod (int dim) const;\n  OCTAVE_API intNDArray sum (int dim) const;\n  OCTAVE_API NDArray dsum (int dim) const;\n  OCTAVE_API intNDArray sumsq (int dim) const;\n\n  OCTAVE_API intNDArray\n  max (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API intNDArray max (Array<octave_idx_type>& index, int dim = -1,\n                             bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API intNDArray\n  min (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API intNDArray min (Array<octave_idx_type>& index, int dim = -1,\n                             bool nanflag = true, bool realabs = true) const;\n\n  OCTAVE_API intNDArray\n  cummax (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API intNDArray cummax (Array<octave_idx_type>& index, int dim = -1,\n                                bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API intNDArray\n  cummin (int dim = -1, bool nanflag = true, bool realabs = true) const;\n  OCTAVE_API intNDArray cummin (Array<octave_idx_type>& index, int dim = -1,\n                                bool nanflag = true, bool realabs = true) const;\n\n  OCTAVE_API intNDArray diff (octave_idx_type order = 1, int dim = -1) const;\n\n  OCTAVE_API intNDArray abs () const;\n  OCTAVE_API intNDArray signum () const;\n\n  intNDArray squeeze () const\n  { return intNDArray<T> (MArray<T>::squeeze ()); }\n\n  intNDArray transpose () const\n  { return intNDArray<T> (MArray<T>::transpose ()); }\n\n  OCTAVE_API intNDArray\n  concat (const intNDArray<T>& rb, const Array<octave_idx_type>& ra_idx);\n\n  OCTAVE_API intNDArray&\n  insert (const intNDArray<T>& a, octave_idx_type r, octave_idx_type c);\n  OCTAVE_API intNDArray&\n  insert (const intNDArray<T>& a, const Array<octave_idx_type>& ra_idx);\n\n  static OCTAVE_API void\n  increment_index (Array<octave_idx_type>& ra_idx,\n                   const dim_vector& dimensions, int start_dimension = 0);\n\n  static OCTAVE_API octave_idx_type\n  compute_index (Array<octave_idx_type>& ra_idx, const dim_vector& dimensions);\n};\n\n// i/o\n\ntemplate <typename T>\nOCTAVE_API std::ostream&\noperator << (std::ostream& os, const intNDArray<T>& a);\n\ntemplate <typename T>\nOCTAVE_API std::istream&\noperator >> (std::istream& is, intNDArray<T>& a);\n\n#endif\n"
  },
  {
    "path": "liboctave/array/module.mk",
    "content": "ARRAY_INC = \\\n  %reldir%/Array-base.h \\\n  %reldir%/Array-fwd.h \\\n  %reldir%/Array-oct.h \\\n  %reldir%/Array-util.h \\\n  %reldir%/CColVector.h \\\n  %reldir%/CDiagMatrix.h \\\n  %reldir%/CMatrix.h \\\n  %reldir%/CNDArray.h \\\n  %reldir%/CRowVector.h \\\n  %reldir%/CSparse.h \\\n  %reldir%/DiagArray2.h \\\n  %reldir%/MArray-fwd.h \\\n  %reldir%/MArray.h \\\n  %reldir%/MDiagArray2.h \\\n  %reldir%/MSparse.h \\\n  %reldir%/Matrix.h \\\n  %reldir%/MatrixType.h \\\n  %reldir%/PermMatrix.h \\\n  %reldir%/Range.h \\\n  %reldir%/Sparse-fwd.h \\\n  %reldir%/Sparse.h \\\n  %reldir%/boolMatrix.h \\\n  %reldir%/boolNDArray.h \\\n  %reldir%/boolSparse.h \\\n  %reldir%/chMatrix.h \\\n  %reldir%/chNDArray.h \\\n  %reldir%/dColVector.h \\\n  %reldir%/dDiagMatrix.h \\\n  %reldir%/dMatrix.h \\\n  %reldir%/dNDArray.h \\\n  %reldir%/dRowVector.h \\\n  %reldir%/dSparse.h \\\n  %reldir%/dim-vector.h \\\n  %reldir%/fCColVector.h \\\n  %reldir%/fCDiagMatrix.h \\\n  %reldir%/fCMatrix.h \\\n  %reldir%/fCNDArray.h \\\n  %reldir%/fCRowVector.h \\\n  %reldir%/fColVector.h \\\n  %reldir%/fDiagMatrix.h \\\n  %reldir%/fMatrix.h \\\n  %reldir%/fNDArray.h \\\n  %reldir%/fRowVector.h \\\n  %reldir%/idx-vector.h \\\n  %reldir%/int16NDArray.h \\\n  %reldir%/int32NDArray.h \\\n  %reldir%/int64NDArray.h \\\n  %reldir%/int8NDArray.h \\\n  %reldir%/intNDArray-fwd.h \\\n  %reldir%/intNDArray.h \\\n  %reldir%/mx-fwd.h \\\n  %reldir%/range-fwd.h \\\n  %reldir%/uint16NDArray.h \\\n  %reldir%/uint32NDArray.h \\\n  %reldir%/uint64NDArray.h \\\n  %reldir%/uint8NDArray.h\n\nARRAY_SRC = \\\n  %reldir%/Array-C.cc \\\n  %reldir%/Array-b.cc \\\n  %reldir%/Array-ch.cc \\\n  %reldir%/Array-d.cc \\\n  %reldir%/Array-f.cc \\\n  %reldir%/Array-fC.cc \\\n  %reldir%/Array-i.cc \\\n  %reldir%/Array-idx-vec.cc \\\n  %reldir%/Array-s.cc \\\n  %reldir%/Array-str.cc \\\n  %reldir%/Array-util.cc \\\n  %reldir%/Array-voidp.cc \\\n  %reldir%/CColVector.cc \\\n  %reldir%/CDiagMatrix.cc \\\n  %reldir%/CMatrix.cc \\\n  %reldir%/CNDArray.cc \\\n  %reldir%/CRowVector.cc \\\n  %reldir%/CSparse.cc \\\n  %reldir%/MArray-C.cc \\\n  %reldir%/MArray-d.cc \\\n  %reldir%/MArray-f.cc \\\n  %reldir%/MArray-fC.cc \\\n  %reldir%/MArray-i.cc \\\n  %reldir%/MArray-s.cc \\\n  %reldir%/MSparse-C.cc \\\n  %reldir%/MSparse-d.cc \\\n  %reldir%/MatrixType.cc \\\n  %reldir%/PermMatrix.cc \\\n  %reldir%/Range.cc \\\n  %reldir%/Sparse-C.cc \\\n  %reldir%/Sparse-b.cc \\\n  %reldir%/Sparse-d.cc \\\n  %reldir%/boolMatrix.cc \\\n  %reldir%/boolNDArray.cc \\\n  %reldir%/boolSparse.cc \\\n  %reldir%/chMatrix.cc \\\n  %reldir%/chNDArray.cc \\\n  %reldir%/dColVector.cc \\\n  %reldir%/dDiagMatrix.cc \\\n  %reldir%/dMatrix.cc \\\n  %reldir%/dNDArray.cc \\\n  %reldir%/dRowVector.cc \\\n  %reldir%/dSparse.cc \\\n  %reldir%/dim-vector.cc \\\n  %reldir%/fCColVector.cc \\\n  %reldir%/fCDiagMatrix.cc \\\n  %reldir%/fCMatrix.cc \\\n  %reldir%/fCNDArray.cc \\\n  %reldir%/fCRowVector.cc \\\n  %reldir%/fColVector.cc \\\n  %reldir%/fDiagMatrix.cc \\\n  %reldir%/fMatrix.cc \\\n  %reldir%/fNDArray.cc \\\n  %reldir%/fRowVector.cc \\\n  %reldir%/idx-vector.cc \\\n  %reldir%/int16NDArray.cc \\\n  %reldir%/int32NDArray.cc \\\n  %reldir%/int64NDArray.cc \\\n  %reldir%/int8NDArray.cc \\\n  %reldir%/uint16NDArray.cc \\\n  %reldir%/uint32NDArray.cc \\\n  %reldir%/uint64NDArray.cc \\\n  %reldir%/uint8NDArray.cc\n\nLIBOCTAVE_TEMPLATE_SRC += \\\n  %reldir%/Array-base.cc \\\n  %reldir%/Array-oct.cc \\\n  %reldir%/DiagArray2.cc \\\n  %reldir%/MArray.cc \\\n  %reldir%/MDiagArray2.cc \\\n  %reldir%/MSparse.cc \\\n  %reldir%/Sparse.cc \\\n  %reldir%/intNDArray.cc\n\nnoinst_LTLIBRARIES += %reldir%/libarray.la\n\n%canon_reldir%_libarray_la_SOURCES = $(ARRAY_SRC)\n\n%canon_reldir%_libarray_la_CPPFLAGS = \\\n  $(liboctave_liboctave_la_CPPFLAGS) \\\n  $(FFTW_XCPPFLAGS) \\\n  $(SPARSE_XCPPFLAGS)\n\nliboctave_liboctave_la_LIBADD += %reldir%/libarray.la\n"
  },
  {
    "path": "liboctave/array/mx-fwd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mx_fwd_h)\n#define octave_mx_fwd_h 1\n\n#include \"octave-config.h\"\n\nclass OCTAVE_API Matrix;\nclass OCTAVE_API ComplexMatrix;\nclass OCTAVE_API FloatMatrix;\nclass OCTAVE_API FloatComplexMatrix;\nclass OCTAVE_API boolMatrix;\nclass OCTAVE_API charMatrix;\n\nclass OCTAVE_API NDArray;\nclass OCTAVE_API ComplexNDArray;\nclass OCTAVE_API FloatNDArray;\nclass OCTAVE_API FloatComplexNDArray;\nclass OCTAVE_API boolNDArray;\nclass OCTAVE_API charNDArray;\n\nclass OCTAVE_API ColumnVector;\nclass OCTAVE_API ComplexColumnVector;\nclass OCTAVE_API FloatColumnVector;\nclass OCTAVE_API FloatComplexColumnVector;\n\nclass OCTAVE_API RowVector;\nclass OCTAVE_API ComplexRowVector;\nclass OCTAVE_API FloatRowVector;\nclass OCTAVE_API FloatComplexRowVector;\n\nclass OCTAVE_API SparseMatrix;\nclass OCTAVE_API SparseComplexMatrix;\nclass OCTAVE_API SparseBoolMatrix;\n\nclass OCTAVE_API DiagMatrix;\nclass OCTAVE_API ComplexDiagMatrix;\nclass OCTAVE_API FloatDiagMatrix;\nclass OCTAVE_API FloatComplexDiagMatrix;\n\nclass OCTAVE_API PermMatrix;\n\n#endif\n"
  },
  {
    "path": "liboctave/array/range-fwd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2021-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_range_fwd_h)\n#define octave_range_fwd_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T, typename ENABLE = void> class OCTAVE_API range;\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/uint16NDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"uint16NDArray.h\"\n#include \"mx-op-defs.h\"\n#include \"intNDArray.cc\"\n\n#include \"bsxfun-defs.cc\"\n\nINSTANTIATE_INTNDARRAY (octave_uint16);\n\ntemplate OCTAVE_API\nstd::ostream&\noperator << (std::ostream& os, const intNDArray<octave_uint16>& a);\n\ntemplate OCTAVE_API\nstd::istream&\noperator >> (std::istream& is, intNDArray<octave_uint16>& a);\n\nNDS_CMP_OPS (uint16NDArray, octave_uint16)\nNDS_BOOL_OPS (uint16NDArray, octave_uint16)\n\nSND_CMP_OPS (octave_uint16, uint16NDArray)\nSND_BOOL_OPS (octave_uint16, uint16NDArray)\n\nNDND_CMP_OPS (uint16NDArray, uint16NDArray)\nNDND_BOOL_OPS (uint16NDArray, uint16NDArray)\n\nMINMAX_FCNS (uint16NDArray, octave_uint16)\n\nBSXFUN_STDOP_DEFS_MXLOOP (uint16NDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (uint16NDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, uint16NDArray, mx_inline_pow)\nBSXFUN_POW_MIXED_MXLOOP (uint16NDArray)\n"
  },
  {
    "path": "liboctave/array/uint16NDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_uint16NDArray_h)\n#define octave_uint16NDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"bsxfun-decl.h\"\n#include \"intNDArray.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-inttypes-fwd.h\"\n\ntypedef intNDArray<octave_uint16> uint16NDArray;\n\nNDS_CMP_OP_DECLS (uint16NDArray, octave_uint16, OCTAVE_API)\nNDS_BOOL_OP_DECLS (uint16NDArray, octave_uint16, OCTAVE_API)\n\nSND_CMP_OP_DECLS (octave_uint16, uint16NDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (octave_uint16, uint16NDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (uint16NDArray, uint16NDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (uint16NDArray, uint16NDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, uint16NDArray, octave_uint16)\n\nMINMAX_DECLS (uint16NDArray, octave_uint16, OCTAVE_API)\n\nBSXFUN_STDOP_DECLS (uint16NDArray, OCTAVE_API)\nBSXFUN_MIXED_INT_DECLS(uint16NDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (uint16NDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/uint32NDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"uint32NDArray.h\"\n#include \"mx-op-defs.h\"\n#include \"intNDArray.cc\"\n\n#include \"bsxfun-defs.cc\"\n\nINSTANTIATE_INTNDARRAY (octave_uint32);\n\ntemplate OCTAVE_API\nstd::ostream&\noperator << (std::ostream& os, const intNDArray<octave_uint32>& a);\n\ntemplate OCTAVE_API\nstd::istream&\noperator >> (std::istream& is, intNDArray<octave_uint32>& a);\n\nNDS_CMP_OPS (uint32NDArray, octave_uint32)\nNDS_BOOL_OPS (uint32NDArray, octave_uint32)\n\nSND_CMP_OPS (octave_uint32, uint32NDArray)\nSND_BOOL_OPS (octave_uint32, uint32NDArray)\n\nNDND_CMP_OPS (uint32NDArray, uint32NDArray)\nNDND_BOOL_OPS (uint32NDArray, uint32NDArray)\n\nMINMAX_FCNS (uint32NDArray, octave_uint32)\n\nBSXFUN_STDOP_DEFS_MXLOOP (uint32NDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (uint32NDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, uint32NDArray, mx_inline_pow)\nBSXFUN_POW_MIXED_MXLOOP (uint32NDArray)\n"
  },
  {
    "path": "liboctave/array/uint32NDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_uint32NDArray_h)\n#define octave_uint32NDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"bsxfun-decl.h\"\n#include \"intNDArray.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-inttypes-fwd.h\"\n\ntypedef intNDArray<octave_uint32> uint32NDArray;\n\nNDS_CMP_OP_DECLS (uint32NDArray, octave_uint32, OCTAVE_API)\nNDS_BOOL_OP_DECLS (uint32NDArray, octave_uint32, OCTAVE_API)\n\nSND_CMP_OP_DECLS (octave_uint32, uint32NDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (octave_uint32, uint32NDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (uint32NDArray, uint32NDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (uint32NDArray, uint32NDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, uint32NDArray, octave_uint32)\n\nMINMAX_DECLS (uint32NDArray, octave_uint32, OCTAVE_API)\n\nBSXFUN_STDOP_DECLS (uint32NDArray, OCTAVE_API)\nBSXFUN_MIXED_INT_DECLS(uint32NDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (uint32NDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/uint64NDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"uint64NDArray.h\"\n#include \"mx-op-defs.h\"\n#include \"intNDArray.cc\"\n\n#include \"bsxfun-defs.cc\"\n\nINSTANTIATE_INTNDARRAY (octave_uint64);\n\ntemplate OCTAVE_API\nstd::ostream&\noperator << (std::ostream& os, const intNDArray<octave_uint64>& a);\n\ntemplate OCTAVE_API\nstd::istream&\noperator >> (std::istream& is, intNDArray<octave_uint64>& a);\n\nNDS_CMP_OPS (uint64NDArray, octave_uint64)\nNDS_BOOL_OPS (uint64NDArray, octave_uint64)\n\nSND_CMP_OPS (octave_uint64, uint64NDArray)\nSND_BOOL_OPS (octave_uint64, uint64NDArray)\n\nNDND_CMP_OPS (uint64NDArray, uint64NDArray)\nNDND_BOOL_OPS (uint64NDArray, uint64NDArray)\n\nMINMAX_FCNS (uint64NDArray, octave_uint64)\n\nBSXFUN_STDOP_DEFS_MXLOOP (uint64NDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (uint64NDArray)\n\nBSXFUN_OP_DEF_MXLOOP (pow, uint64NDArray, mx_inline_pow)\nBSXFUN_POW_MIXED_MXLOOP (uint64NDArray)\n"
  },
  {
    "path": "liboctave/array/uint64NDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_uint64NDArray_h)\n#define octave_uint64NDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"bsxfun-decl.h\"\n#include \"intNDArray.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-inttypes-fwd.h\"\n\ntypedef intNDArray<octave_uint64> uint64NDArray;\n\nNDS_CMP_OP_DECLS (uint64NDArray, octave_uint64, OCTAVE_API)\nNDS_BOOL_OP_DECLS (uint64NDArray, octave_uint64, OCTAVE_API)\n\nSND_CMP_OP_DECLS (octave_uint64, uint64NDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (octave_uint64, uint64NDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (uint64NDArray, uint64NDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (uint64NDArray, uint64NDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, uint64NDArray, octave_uint64)\n\nMINMAX_DECLS (uint64NDArray, octave_uint64, OCTAVE_API)\n\nBSXFUN_STDOP_DECLS (uint64NDArray, OCTAVE_API)\nBSXFUN_MIXED_INT_DECLS(uint64NDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (uint64NDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/array/uint8NDArray.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"uint8NDArray.h\"\n#include \"mx-op-defs.h\"\n#include \"intNDArray.cc\"\n\n#include \"bsxfun-defs.cc\"\n\nINSTANTIATE_INTNDARRAY (octave_uint8);\n\ntemplate OCTAVE_API\nstd::ostream&\noperator << (std::ostream& os, const intNDArray<octave_uint8>& a);\n\ntemplate OCTAVE_API\nstd::istream&\noperator >> (std::istream& is, intNDArray<octave_uint8>& a);\n\nNDS_CMP_OPS (uint8NDArray, octave_uint8)\nNDS_BOOL_OPS (uint8NDArray, octave_uint8)\n\nSND_CMP_OPS (octave_uint8, uint8NDArray)\nSND_BOOL_OPS (octave_uint8, uint8NDArray)\n\nNDND_CMP_OPS (uint8NDArray, uint8NDArray)\nNDND_BOOL_OPS (uint8NDArray, uint8NDArray)\n\nMINMAX_FCNS (uint8NDArray, octave_uint8)\n\nBSXFUN_STDOP_DEFS_MXLOOP (uint8NDArray)\nBSXFUN_STDREL_DEFS_MXLOOP (uint8NDArray)\n\nBSXFUN_POW_MIXED_MXLOOP (uint8NDArray)\nBSXFUN_OP_DEF_MXLOOP (pow, uint8NDArray, mx_inline_pow)\n"
  },
  {
    "path": "liboctave/array/uint8NDArray.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_uint8NDArray_h)\n#define octave_uint8NDArray_h 1\n\n#include \"octave-config.h\"\n\n#include \"bsxfun-decl.h\"\n#include \"intNDArray.h\"\n#include \"mx-op-decl.h\"\n#include \"oct-inttypes-fwd.h\"\n\ntypedef intNDArray<octave_uint8> uint8NDArray;\n\nNDS_CMP_OP_DECLS (uint8NDArray, octave_uint8, OCTAVE_API)\nNDS_BOOL_OP_DECLS (uint8NDArray, octave_uint8, OCTAVE_API)\n\nSND_CMP_OP_DECLS (octave_uint8, uint8NDArray, OCTAVE_API)\nSND_BOOL_OP_DECLS (octave_uint8, uint8NDArray, OCTAVE_API)\n\nNDND_CMP_OP_DECLS (uint8NDArray, uint8NDArray, OCTAVE_API)\nNDND_BOOL_OP_DECLS (uint8NDArray, uint8NDArray, OCTAVE_API)\n\nMARRAY_FORWARD_DEFS (MArray, uint8NDArray, octave_uint8)\n\nMINMAX_DECLS (uint8NDArray, octave_uint8, OCTAVE_API)\n\nBSXFUN_STDOP_DECLS (uint8NDArray, OCTAVE_API)\nBSXFUN_MIXED_INT_DECLS(uint8NDArray, OCTAVE_API)\nBSXFUN_STDREL_DECLS (uint8NDArray, OCTAVE_API)\n\n#endif\n"
  },
  {
    "path": "liboctave/external/Faddeeva/Faddeeva.cc",
    "content": "//  -*- mode:c++; tab-width:2; indent-tabs-mode:nil;  -*-\n\n/* Copyright (c) 2012 Massachusetts Institute of Technology\n * \n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n * \n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \n */\n\n/* (Note that this file can be compiled with either C++, in which\n    case it uses C++ std::complex<double>, or C, in which case it\n    uses C99 double complex.) */\n\n/* Available at: http://ab-initio.mit.edu/Faddeeva\n\n   Computes various error functions (erf, erfc, erfi, erfcx), \n   including the Dawson integral, in the complex plane, based\n   on algorithms for the computation of the Faddeeva function \n              w(z) = exp(-z^2) * erfc(-i*z).\n   Given w(z), the error functions are mostly straightforward\n   to compute, except for certain regions where we have to\n   switch to Taylor expansions to avoid cancellation errors\n   [e.g., near the origin for erf(z)].\n\n   To compute the Faddeeva function, we use a combination of two\n   algorithms:\n\n   For sufficiently large |z|, we use a continued-fraction expansion\n   for w(z) similar to those described in:\n\n      Walter Gautschi, \"Efficient computation of the complex error\n      function,\" SIAM J. Numer. Anal. 7(1), pp. 187-198 (1970)\n\n      G. P. M. Poppe and C. M. J. Wijers, \"More efficient computation\n      of the complex error function,\" ACM Trans. Math. Soft. 16(1),\n      pp. 38-46 (1990).\n\n   Unlike those papers, however, we switch to a completely different\n   algorithm for smaller |z|:\n\n      Mofreh R. Zaghloul and Ahmed N. Ali, \"Algorithm 916: Computing the\n      Faddeyeva and Voigt Functions,\" ACM Trans. Math. Soft. 38(2), 15\n      (2011).\n\n   (I initially used this algorithm for all z, but it turned out to be\n    significantly slower than the continued-fraction expansion for\n    larger |z|.  On the other hand, it is competitive for smaller |z|, \n    and is significantly more accurate than the Poppe & Wijers code\n    in some regions, e.g., in the vicinity of z=1+1i.)\n\n   Note that this is an INDEPENDENT RE-IMPLEMENTATION of these algorithms,\n   based on the description in the papers ONLY.  In particular, I did\n   not refer to the authors' Fortran or Matlab implementations, respectively,\n   (which are under restrictive ACM copyright terms and therefore unusable\n    in free/open-source software).\n\n   Steven G. Johnson, Massachusetts Institute of Technology\n   http://math.mit.edu/~stevenj\n   October 2012.\n\n    -- Note that Algorithm 916 assumes that the erfc(x) function, \n       or rather the scaled function erfcx(x) = exp(x*x)*erfc(x),\n       is supplied for REAL arguments x.   I originally used an\n       erfcx routine derived from DERFC in SLATEC, but I have\n       since replaced it with a much faster routine written by\n       me which uses a combination of continued-fraction expansions\n       and a lookup table of Chebyshev polynomials.  For speed,\n       I implemented a similar algorithm for Im[w(x)] of real x,\n       since this comes up frequently in the other error functions.\n\n   A small test program is included the end, which checks\n   the w(z) etc. results against several known values.  To compile\n   the test function, compile with -DTEST_FADDEEVA (that is,\n   #define TEST_FADDEEVA).\n\n   If HAVE_CONFIG_H is #defined (e.g., by compiling with -DHAVE_CONFIG_H),\n   then we #include \"config.h\", which is assumed to be a GNU autoconf-style\n   header defining HAVE_* macros to indicate the presence of features.  In\n   particular, if HAVE_ISNAN and HAVE_ISINF are #defined, we use those\n   functions in math.h instead of defining our own, and if HAVE_ERF and/or\n   HAVE_ERFC are defined we use those functions from <cmath> for erf and\n   erfc of real arguments, respectively, instead of defining our own.\n\n   REVISION HISTORY:\n       4 October 2012: Initial public release (SGJ)\n       5 October 2012: Revised (SGJ) to fix spelling error,\n                       start summation for large x at round(x/a) (> 1)\n                       rather than ceil(x/a) as in the original\n                       paper, which should slightly improve performance\n                       (and, apparently, slightly improves accuracy)\n      19 October 2012: Revised (SGJ) to fix bugs for large x, large -y,\n                       and 15<x<26. Performance improvements. Prototype\n                       now supplies default value for relerr.\n      24 October 2012: Switch to continued-fraction expansion for\n                       sufficiently large z, for performance reasons.\n                       Also, avoid spurious overflow for |z| > 1e154.\n                       Set relerr argument to min(relerr,0.1).\n      27 October 2012: Enhance accuracy in Re[w(z)] taken by itself,\n                       by switching to Alg. 916 in a region near\n                       the real-z axis where continued fractions\n                       have poor relative accuracy in Re[w(z)].  Thanks\n                       to M. Zaghloul for the tip.\n      29 October 2012: Replace SLATEC-derived erfcx routine with\n                       completely rewritten code by me, using a very\n                       different algorithm which is much faster.\n      30 October 2012: Implemented special-case code for real z\n                       (where real part is exp(-x^2) and imag part is\n                        Dawson integral), using algorithm similar to erfx.\n                       Export ImFaddeeva_w function to make Dawson's\n                       integral directly accessible.\n      3 November 2012: Provide implementations of erf, erfc, erfcx,\n                       and Dawson functions in Faddeeva:: namespace,\n                       in addition to Faddeeva::w.  Provide header\n                       file Faddeeva.hh.\n      4 November 2012: Slightly faster erf for real arguments.\n                       Updated MATLAB and Octave plugins.\n     27 November 2012: Support compilation with either C++ or\n                       plain C (using C99 complex numbers).\n                       For real x, use standard-library erf(x)\n                       and erfc(x) if available (for C99 or C++11).\n                       #include \"config.h\" if HAVE_CONFIG_H is #defined.\n     15 December 2012: Portability fixes (copysign, Inf/NaN creation),\n                       use CMPLX/__builtin_complex if available in C,\n                       slight accuracy improvements to erf and dawson\n                       functions near the origin.  Use gnulib functions\n                       if GNULIB_NAMESPACE is defined.\n     18 December 2012: Slight tweaks (remove recomputation of x*x in Dawson)\n          12 May 2015: Bugfix for systems lacking copysign function.\n*/\n\n/////////////////////////////////////////////////////////////////////////\n/* If this file is compiled as a part of a larger project,\n   support using an autoconf-style config.h header file\n   (with various \"HAVE_*\" #defines to indicate features)\n   if HAVE_CONFIG_H is #defined (in GNU autotools style). */\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n/////////////////////////////////////////////////////////////////////////\n// macros to allow us to use either C++ or C (with C99 features)\n\n#if defined (__cplusplus)\n\n#  include \"lo-ieee.h\"\n\n#  include \"Faddeeva.hh\"\n\n#  include <cfloat>\n#  include <cmath>\n\n// use std::numeric_limits, since 1./0. and 0./0. fail with some compilers (MS)\n#  define Inf octave::numeric_limits<double>::Inf ()\n#  define NaN octave::numeric_limits<double>::NaN ()\n\ntypedef std::complex<double> cmplx;\n\n// Use C-like complex syntax, since the C syntax is more restrictive\n#  define cexp(z) exp(z)\n#  define creal(z) real(z)\n#  define cimag(z) imag(z)\n#  define cpolar(r,t) polar(r,t)\n\n#  define C(a,b) cmplx(a,b)\n\n#  define FADDEEVA(name) Faddeeva::name\n#  define FADDEEVA_RE(name) Faddeeva::name\n\n// isnan/isinf were introduced in C++11\n#  if (__cplusplus < 201103L) && (!defined(HAVE_ISNAN) || !defined(HAVE_ISINF))\nstatic inline bool my_isnan(double x) { return x != x; }\n#    define isnan my_isnan\nstatic inline bool my_isinf(double x) { return 1/x == 0.; }\n#    define isinf my_isinf\n#  elif (__cplusplus >= 201103L)\n// g++ gets confused between the C and C++ isnan/isinf functions\n#    define isnan std::isnan\n#    define isinf std::isinf\n#  endif\n\n// copysign was introduced in C++11 (and is also in POSIX and C99)\n#  if defined(_WIN32) || defined(__WIN32__)\n#    define copysign _copysign // of course MS had to be different\n#  elif defined(GNULIB_NAMESPACE) // we are using using gnulib <cmath>\n#    define copysign GNULIB_NAMESPACE::copysign\n#  elif (__cplusplus < 201103L) && !defined(HAVE_COPYSIGN) && !defined(__linux__) && !(defined(__APPLE__) && defined(__MACH__)) && !defined(_AIX)\nstatic inline double my_copysign(double x, double y) { return x<0 != y<0 ? -x : x; }\n#    define copysign my_copysign\n#  endif\n\n// If we are using the gnulib <cmath> (e.g. in the GNU Octave sources),\n// gnulib generates a link warning if we use ::floor instead of gnulib::floor.\n// This warning is completely innocuous because the only difference between\n// gnulib::floor and the system ::floor (and only on ancient OSF systems)\n// has to do with floor(-0), which doesn't occur in the usage below, but\n// the Octave developers prefer that we silence the warning.\n#  if defined (GNULIB_NAMESPACE)\n#    define floor GNULIB_NAMESPACE::floor\n#  endif\n\n#else // !__cplusplus, i.e., pure C (requires C99 features)\n\n#  include \"Faddeeva.h\"\n\n#  define _GNU_SOURCE // enable GNU libc NAN extension if possible\n\n#  include <float.h>\n#  include <math.h>\n\ntypedef double complex cmplx;\n\n#  define FADDEEVA(name) Faddeeva_ ## name\n#  define FADDEEVA_RE(name) Faddeeva_ ## name ## _re\n\n/* Constructing complex numbers like 0+i*NaN is problematic in C99\n   without the C11 CMPLX macro, because 0.+I*NAN may give NaN+i*NAN if\n   I is a complex (rather than imaginary) constant.  For some reason,\n   however, it works fine in (pre-4.7) gcc if I define Inf and NaN as\n   1/0 and 0/0 (and only if I compile with optimization -O1 or more),\n   but not if I use the INFINITY or NAN macros. */\n\n/* __builtin_complex was introduced in gcc 4.7, but the C11 CMPLX macro\n   may not be defined unless we are using a recent (2012) version of\n   glibc and compile with -std=c11... note that icc lies about being\n   gcc and probably doesn't have this builtin(?), so exclude icc explicitly */\n#  if !defined(CMPLX) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !(defined(__ICC) || defined(__INTEL_COMPILER))\n#    define CMPLX(a,b) __builtin_complex((double) (a), (double) (b))\n#  endif\n\n#  if defined (CMPLX) // C11\n#    define C(a,b) CMPLX(a,b)\n#    define Inf INFINITY // C99 infinity\n#    if defined (NAN) // GNU libc extension\n#      define NaN NAN\n#    else\n#      define NaN (0./0.) // NaN\n#    endif\n#  else\n#    define C(a,b) ((a) + I*(b))\n#    define Inf (1./0.)\n#    define NaN (0./0.)\n#  endif\n\nstatic inline cmplx cpolar(double r, double t)\n{\n  if (r == 0.0 && !isnan(t))\n    return 0.0;\n  else\n    return C(r * cos(t), r * sin(t));\n}\n\n#endif // !__cplusplus, i.e., pure C (requires C99 features)\n\n/////////////////////////////////////////////////////////////////////////\n// Auxiliary routines to compute other special functions based on w(z)\n\n// compute erfcx(z) = exp(z^2) erfz(z)\ncmplx FADDEEVA(erfcx)(cmplx z, double relerr)\n{\n  return FADDEEVA(w)(C(-cimag(z), creal(z)), relerr);\n}\n\n// compute the error function erf(x)\ndouble FADDEEVA_RE(erf)(double x)\n{\n#if !defined(__cplusplus)\n  return erf(x); // C99 supplies erf in math.h\n#elif (__cplusplus >= 201103L) || defined(HAVE_ERF)\n  return ::erf(x); // C++11 supplies std::erf in cmath\n#else\n  double mx2 = -x*x;\n  if (mx2 < -750) // underflow\n    return (x >= 0 ? 1.0 : -1.0);\n\n  if (x >= 0) {\n    if (x < 8e-2) goto taylor;\n    return 1.0 - exp(mx2) * FADDEEVA_RE(erfcx)(x);\n  }\n  else { // x < 0\n    if (x > -8e-2) goto taylor;\n    return exp(mx2) * FADDEEVA_RE(erfcx)(-x) - 1.0;\n  }\n\n  // Use Taylor series for small |x|, to avoid cancellation inaccuracy\n  //   erf(x) = 2/sqrt(pi) * x * (1 - x^2/3 + x^4/10 - x^6/42 + x^8/216 + ...)\n taylor:\n  return x * (1.1283791670955125739\n              + mx2 * (0.37612638903183752464\n                       + mx2 * (0.11283791670955125739\n                                + mx2 * (0.026866170645131251760\n                                         + mx2 * 0.0052239776254421878422))));\n#endif\n}\n\n// compute the error function erf(z)\ncmplx FADDEEVA(erf)(cmplx z, double relerr)\n{\n  double x = creal(z), y = cimag(z);\n\n  if (y == 0)\n    return C(FADDEEVA_RE(erf)(x),\n             y); // preserve sign of 0\n  if (x == 0) // handle separately for speed & handling of y = Inf or NaN\n    return C(x, // preserve sign of 0\n             /* handle y -> Inf limit manually, since\n                exp(y^2) -> Inf but Im[w(y)] -> 0, so\n                IEEE will give us a NaN when it should be Inf */\n             y*y > 720 ? (y > 0 ? Inf : -Inf)\n             : exp(y*y) * FADDEEVA(w_im)(y));\n  \n  double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow\n  double mIm_z2 = -2*x*y; // Im(-z^2)\n  if (mRe_z2 < -750) // underflow\n    return (x >= 0 ? 1.0 : -1.0);\n\n  /* Handle positive and negative x via different formulas,\n     using the mirror symmetries of w, to avoid overflow/underflow\n     problems from multiplying exponentially large and small quantities. */\n  if (x >= 0) {\n    if (x < 8e-2) {\n      if (fabs(y) < 1e-2)\n        goto taylor;\n      else if (fabs(mIm_z2) < 5e-3 && x < 5e-3)\n        goto taylor_erfi;\n    }\n    /* don't use complex exp function, since that will produce spurious NaN\n       values when multiplying w in an overflow situation. */\n    return 1.0 - exp(mRe_z2) *\n      (C(cos(mIm_z2), sin(mIm_z2))\n       * FADDEEVA(w)(C(-y,x), relerr));\n  }\n  else { // x < 0\n    if (x > -8e-2) { // duplicate from above to avoid fabs(x) call\n      if (fabs(y) < 1e-2)\n        goto taylor;\n      else if (fabs(mIm_z2) < 5e-3 && x > -5e-3)\n        goto taylor_erfi;\n    }\n    else if (isnan(x))\n      return C(NaN, y == 0 ? 0 : NaN);\n    /* don't use complex exp function, since that will produce spurious NaN\n       values when multiplying w in an overflow situation. */\n    return exp(mRe_z2) *\n      (C(cos(mIm_z2), sin(mIm_z2))\n       * FADDEEVA(w)(C(y,-x), relerr)) - 1.0;\n  }\n\n  // Use Taylor series for small |z|, to avoid cancellation inaccuracy\n  //   erf(z) = 2/sqrt(pi) * z * (1 - z^2/3 + z^4/10 - z^6/42 + z^8/216 + ...)\n taylor:\n  {\n    cmplx mz2 = C(mRe_z2, mIm_z2); // -z^2\n    return z * (1.1283791670955125739\n                + mz2 * (0.37612638903183752464\n                         + mz2 * (0.11283791670955125739\n                                  + mz2 * (0.026866170645131251760\n                                          + mz2 * 0.0052239776254421878422))));\n  }\n\n  /* for small |x| and small |xy|, \n     use Taylor series to avoid cancellation inaccuracy:\n       erf(x+iy) = erf(iy)\n          + 2*exp(y^2)/sqrt(pi) *\n            [ x * (1 - x^2 * (1+2y^2)/3 + x^4 * (3+12y^2+4y^4)/30 + ... \n              - i * x^2 * y * (1 - x^2 * (3+2y^2)/6 + ...) ]\n     where:\n        erf(iy) = exp(y^2) * Im[w(y)]\n  */\n taylor_erfi:\n  {\n    double x2 = x*x, y2 = y*y;\n    double expy2 = exp(y2);\n    return C\n      (expy2 * x * (1.1283791670955125739\n                    - x2 * (0.37612638903183752464\n                            + 0.75225277806367504925*y2)\n                    + x2*x2 * (0.11283791670955125739\n                               + y2 * (0.45135166683820502956\n                                       + 0.15045055561273500986*y2))),\n       expy2 * (FADDEEVA(w_im)(y)\n                - x2*y * (1.1283791670955125739 \n                          - x2 * (0.56418958354775628695 \n                                  + 0.37612638903183752464*y2))));\n  }\n}\n\n// erfi(z) = -i erf(iz)\ncmplx FADDEEVA(erfi)(cmplx z, double relerr)\n{\n  cmplx e = FADDEEVA(erf)(C(-cimag(z),creal(z)), relerr);\n  return C(cimag(e), -creal(e));\n}\n\n// erfi(x) = -i erf(ix)\ndouble FADDEEVA_RE(erfi)(double x)\n{\n  return x*x > 720 ? (x > 0 ? Inf : -Inf)\n    : exp(x*x) * FADDEEVA(w_im)(x);\n}\n\n// erfc(x) = 1 - erf(x)\ndouble FADDEEVA_RE(erfc)(double x)\n{\n#if !defined(__cplusplus)\n  return erfc(x); // C99 supplies erfc in math.h\n#elif (__cplusplus >= 201103L) || defined(HAVE_ERFC)\n  return ::erfc(x); // C++11 supplies std::erfc in cmath\n#else\n  if (x*x > 750) // underflow\n    return (x >= 0 ? 0.0 : 2.0);\n  return (x >= 0 ? exp(-x*x) * FADDEEVA_RE(erfcx)(x) \n                 : 2. - exp(-x*x) * FADDEEVA_RE(erfcx)(-x));\n#endif\n}\n\n// erfc(z) = 1 - erf(z)\ncmplx FADDEEVA(erfc)(cmplx z, double relerr)\n{\n  double x = creal(z), y = cimag(z);\n\n  if (x == 0.)\n    return C(1,\n             /* handle y -> Inf limit manually, since\n                exp(y^2) -> Inf but Im[w(y)] -> 0, so\n                IEEE will give us a NaN when it should be Inf */\n             y*y > 720 ? (y > 0 ? -Inf : Inf)\n             : -exp(y*y) * FADDEEVA(w_im)(y));\n  if (y == 0.) {\n    if (x*x > 750) // underflow\n      return C(x >= 0 ? 0.0 : 2.0,\n               -y); // preserve sign of 0\n    return C(x >= 0 ? exp(-x*x) * FADDEEVA_RE(erfcx)(x) \n             : 2. - exp(-x*x) * FADDEEVA_RE(erfcx)(-x),\n             -y); // preserve sign of zero\n  }\n\n  double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow\n  double mIm_z2 = -2*x*y; // Im(-z^2)\n  if (mRe_z2 < -750) // underflow\n    return (x >= 0 ? 0.0 : 2.0);\n\n  if (x >= 0)\n    return cexp(C(mRe_z2, mIm_z2))\n      * FADDEEVA(w)(C(-y,x), relerr);\n  else\n    return 2.0 - cexp(C(mRe_z2, mIm_z2))\n      * FADDEEVA(w)(C(y,-x), relerr);\n}\n\n// compute Dawson(x) = sqrt(pi)/2  *  exp(-x^2) * erfi(x)\ndouble FADDEEVA_RE(Dawson)(double x)\n{\n  const double spi2 = 0.8862269254527580136490837416705725913990; // sqrt(pi)/2\n  return spi2 * FADDEEVA(w_im)(x);\n}\n\n// compute Dawson(z) = sqrt(pi)/2  *  exp(-z^2) * erfi(z)\ncmplx FADDEEVA(Dawson)(cmplx z, double relerr)\n{\n  const double spi2 = 0.8862269254527580136490837416705725913990; // sqrt(pi)/2\n  double x = creal(z), y = cimag(z);\n\n  // handle axes separately for speed & proper handling of x or y = Inf or NaN\n  if (y == 0)\n    return C(spi2 * FADDEEVA(w_im)(x),\n             -y); // preserve sign of 0\n  if (x == 0) {\n    double y2 = y*y;\n    if (y2 < 2.5e-5) { // Taylor expansion\n      return C(x, // preserve sign of 0\n               y * (1.\n                    + y2 * (0.6666666666666666666666666666666666666667\n                            + y2 * 0.26666666666666666666666666666666666667)));\n    }\n    return C(x, // preserve sign of 0\n             spi2 * (y >= 0 \n                     ? exp(y2) - FADDEEVA_RE(erfcx)(y)\n                     : FADDEEVA_RE(erfcx)(-y) - exp(y2)));\n  }\n\n  double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow\n  double mIm_z2 = -2*x*y; // Im(-z^2)\n  cmplx mz2 = C(mRe_z2, mIm_z2); // -z^2\n\n  /* Handle positive and negative x via different formulas,\n     using the mirror symmetries of w, to avoid overflow/underflow\n     problems from multiplying exponentially large and small quantities. */\n  if (y >= 0) {\n    if (y < 5e-3) {\n      if (fabs(x) < 5e-3)\n        goto taylor;\n      else if (fabs(mIm_z2) < 5e-3)\n        goto taylor_realaxis;\n    }\n    cmplx res = cexp(mz2) - FADDEEVA(w)(z, relerr);\n    return spi2 * C(-cimag(res), creal(res));\n  }\n  else { // y < 0\n    if (y > -5e-3) { // duplicate from above to avoid fabs(x) call\n      if (fabs(x) < 5e-3)\n        goto taylor;\n      else if (fabs(mIm_z2) < 5e-3)\n        goto taylor_realaxis;\n    }\n    else if (isnan(y))\n      return C(x == 0 ? 0 : NaN, NaN);\n    cmplx res = FADDEEVA(w)(-z, relerr) - cexp(mz2);\n    return spi2 * C(-cimag(res), creal(res));\n  }\n\n  // Use Taylor series for small |z|, to avoid cancellation inaccuracy\n  //     dawson(z) = z - 2/3 z^3 + 4/15 z^5 + ...\n taylor:\n  return z * (1.\n              + mz2 * (0.6666666666666666666666666666666666666667\n                       + mz2 * 0.2666666666666666666666666666666666666667));\n\n  /* for small |y| and small |xy|, \n     use Taylor series to avoid cancellation inaccuracy:\n       dawson(x + iy)\n        = D + y^2 (D + x - 2Dx^2)\n            + y^4 (D/2 + 5x/6 - 2Dx^2 - x^3/3 + 2Dx^4/3)\n        + iy [ (1-2Dx) + 2/3 y^2 (1 - 3Dx - x^2 + 2Dx^3)\n              + y^4/15 (4 - 15Dx - 9x^2 + 20Dx^3 + 2x^4 - 4Dx^5) ] + ...\n     where D = dawson(x) \n\n     However, for large |x|, 2Dx -> 1 which gives cancellation problems in\n     this series (many of the leading terms cancel).  So, for large |x|,\n     we need to substitute a continued-fraction expansion for D.\n\n        dawson(x) = 0.5 / (x-0.5/(x-1/(x-1.5/(x-2/(x-2.5/(x...))))))\n\n     The 6 terms shown here seems to be the minimum needed to be\n     accurate as soon as the simpler Taylor expansion above starts\n     breaking down.  Using this 6-term expansion, factoring out the\n     denominator, and simplifying with Maple, we obtain:\n\n      Re dawson(x + iy) * (-15 + 90x^2 - 60x^4 + 8x^6) / x\n        = 33 - 28x^2 + 4x^4 + y^2 (18 - 4x^2) + 4 y^4\n      Im dawson(x + iy) * (-15 + 90x^2 - 60x^4 + 8x^6) / y\n        = -15 + 24x^2 - 4x^4 + 2/3 y^2 (6x^2 - 15) - 4 y^4\n\n     Finally, for |x| > 5e7, we can use a simpler 1-term continued-fraction\n     expansion for the real part, and a 2-term expansion for the imaginary\n     part.  (This avoids overflow problems for huge |x|.)  This yields:\n     \n     Re dawson(x + iy) = [1 + y^2 (1 + y^2/2 - (xy)^2/3)] / (2x)\n     Im dawson(x + iy) = y [ -1 - 2/3 y^2 + y^4/15 (2x^2 - 4) ] / (2x^2 - 1)\n\n */\n taylor_realaxis:\n  {\n    double x2 = x*x;\n    if (x2 > 1600) { // |x| > 40\n      double y2 = y*y;\n      if (x2 > 25e14) {// |x| > 5e7\n        double xy2 = (x*y)*(x*y);\n        return C((0.5 + y2 * (0.5 + 0.25*y2\n                              - 0.16666666666666666667*xy2)) / x,\n                 y * (-1 + y2 * (-0.66666666666666666667\n                                 + 0.13333333333333333333*xy2\n                                 - 0.26666666666666666667*y2))\n                 / (2*x2 - 1));\n      }\n      return (1. / (-15 + x2*(90 + x2*(-60 + 8*x2)))) *\n        C(x * (33 + x2 * (-28 + 4*x2)\n               + y2 * (18 - 4*x2 + 4*y2)),\n          y * (-15 + x2 * (24 - 4*x2)\n               + y2 * (4*x2 - 10 - 4*y2)));\n    }\n    else {\n      double D = spi2 * FADDEEVA(w_im)(x);\n      double y2 = y*y;\n      return C\n        (D + y2 * (D + x - 2*D*x2)\n         + y2*y2 * (D * (0.5 - x2 * (2 - 0.66666666666666666667*x2))\n                    + x * (0.83333333333333333333\n                           - 0.33333333333333333333 * x2)),\n         y * (1 - 2*D*x\n              + y2 * 0.66666666666666666667 * (1 - x2 - D*x * (3 - 2*x2))\n              + y2*y2 * (0.26666666666666666667 -\n                         x2 * (0.6 - 0.13333333333333333333 * x2)\n                         - D*x * (1 - x2 * (1.3333333333333333333\n                                            - 0.26666666666666666667 * x2)))));\n    }\n  }\n}\n\n/////////////////////////////////////////////////////////////////////////\n\n// return sinc(x) = sin(x)/x, given both x and sin(x) \n// [since we only use this in cases where sin(x) has already been computed]\nstatic inline double sinc(double x, double sinx) { \n  return fabs(x) < 1e-4 ? 1 - (0.1666666666666666666667)*x*x : sinx / x; \n}\n\n// sinh(x) via Taylor series, accurate to machine precision for |x| < 1e-2\nstatic inline double sinh_taylor(double x) {\n  return x * (1 + (x*x) * (0.1666666666666666666667\n                           + 0.00833333333333333333333 * (x*x)));\n}\n\nstatic inline double sqr(double x) { return x*x; }\n\n// precomputed table of expa2n2[n-1] = exp(-a2*n*n)\n// for double-precision a2 = 0.26865... in FADDEEVA(w), below.\nstatic const double expa2n2[] = {\n  7.64405281671221563e-01,\n  3.41424527166548425e-01,\n  8.91072646929412548e-02,\n  1.35887299055460086e-02,\n  1.21085455253437481e-03,\n  6.30452613933449404e-05,\n  1.91805156577114683e-06,\n  3.40969447714832381e-08,\n  3.54175089099469393e-10,\n  2.14965079583260682e-12,\n  7.62368911833724354e-15,\n  1.57982797110681093e-17,\n  1.91294189103582677e-20,\n  1.35344656764205340e-23,\n  5.59535712428588720e-27,\n  1.35164257972401769e-30,\n  1.90784582843501167e-34,\n  1.57351920291442930e-38,\n  7.58312432328032845e-43,\n  2.13536275438697082e-47,\n  3.51352063787195769e-52,\n  3.37800830266396920e-57,\n  1.89769439468301000e-62,\n  6.22929926072668851e-68,\n  1.19481172006938722e-73,\n  1.33908181133005953e-79,\n  8.76924303483223939e-86,\n  3.35555576166254986e-92,\n  7.50264110688173024e-99,\n  9.80192200745410268e-106,\n  7.48265412822268959e-113,\n  3.33770122566809425e-120,\n  8.69934598159861140e-128,\n  1.32486951484088852e-135,\n  1.17898144201315253e-143,\n  6.13039120236180012e-152,\n  1.86258785950822098e-160,\n  3.30668408201432783e-169,\n  3.43017280887946235e-178,\n  2.07915397775808219e-187,\n  7.36384545323984966e-197,\n  1.52394760394085741e-206,\n  1.84281935046532100e-216,\n  1.30209553802992923e-226,\n  5.37588903521080531e-237,\n  1.29689584599763145e-247,\n  1.82813078022866562e-258,\n  1.50576355348684241e-269,\n  7.24692320799294194e-281,\n  2.03797051314726829e-292,\n  3.34880215927873807e-304,\n  0.0 // underflow (also prevents reads past array end, below)\n};\n\n/////////////////////////////////////////////////////////////////////////\n\ncmplx FADDEEVA(w)(cmplx z, double relerr)\n{\n  if (creal(z) == 0.0)\n    return C(FADDEEVA_RE(erfcx)(cimag(z)), \n             creal(z)); // give correct sign of 0 in cimag(w)\n  else if (cimag(z) == 0)\n    return C(exp(-sqr(creal(z))),\n             FADDEEVA(w_im)(creal(z)));\n\n  double a, a2, c;\n  if (relerr <= DBL_EPSILON) {\n    relerr = DBL_EPSILON;\n    a = 0.518321480430085929872; // pi / sqrt(-log(eps*0.5))\n    c = 0.329973702884629072537; // (2/pi) * a;\n    a2 = 0.268657157075235951582; // a^2\n  }\n  else {\n    const double pi = 3.14159265358979323846264338327950288419716939937510582;\n    if (relerr > 0.1) relerr = 0.1; // not sensible to compute < 1 digit\n    a = pi / sqrt(-log(relerr*0.5));\n    c = (2/pi)*a;\n    a2 = a*a;\n  }\n  const double x = fabs(creal(z));\n  const double y = cimag(z), ya = fabs(y);\n\n  cmplx ret = 0.; // return value\n\n  double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0;\n\n#define USE_CONTINUED_FRACTION 1 // 1 to use continued fraction for large |z|\n\n#if USE_CONTINUED_FRACTION\n  if (ya > 7 || (x > 6  // continued fraction is faster\n                 /* As pointed out by M. Zaghloul, the continued\n                    fraction seems to give a large relative error in\n                    Re w(z) for |x| ~ 6 and small |y|, so use\n                    algorithm 816 in this region: */\n                 && (ya > 0.1 || (x > 8 && ya > 1e-10) || x > 28))) {\n    \n    /* Poppe & Wijers suggest using a number of terms\n           nu = 3 + 1442 / (26*rho + 77)\n       where rho = sqrt((x/x0)^2 + (y/y0)^2) where x0=6.3, y0=4.4.\n       (They only use this expansion for rho >= 1, but rho a little less\n        than 1 seems okay too.)\n       Instead, I did my own fit to a slightly different function\n       that avoids the hypotenuse calculation, using NLopt to minimize\n       the sum of the squares of the errors in nu with the constraint\n       that the estimated nu be >= minimum nu to attain machine precision.\n       I also separate the regions where nu == 2 and nu == 1. */\n    const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi)\n    double xs = (y < 0 ? -creal(z) : creal(z)); // compute for -z if y < 0\n    if (x + ya > 4000) { // nu <= 2\n      if (x + ya > 1e7) { // nu == 1, w(z) = i/sqrt(pi) / z\n        // scale to avoid overflow\n        if (x > ya) {\n          double yax = ya / xs; \n          double denom = ispi / (xs + yax*ya);\n          ret = C(denom*yax, denom);\n        }\n        else if (isinf(ya))\n          return ((isnan(x) || y < 0) \n                  ? C(NaN,NaN) : C(0,0));\n        else {\n          double xya = xs / ya;\n          double denom = ispi / (xya*xs + ya);\n          ret = C(denom, denom*xya);\n        }\n      }\n      else { // nu == 2, w(z) = i/sqrt(pi) * z / (z*z - 0.5)\n        double dr = xs*xs - ya*ya - 0.5, di = 2*xs*ya;\n        double denom = ispi / (dr*dr + di*di);\n        ret = C(denom * (xs*di-ya*dr), denom * (xs*dr+ya*di));\n      }\n    }\n    else { // compute nu(z) estimate and do general continued fraction\n      const double c0=3.9, c1=11.398, c2=0.08254, c3=0.1421, c4=0.2023; // fit\n      double nu = floor(c0 + c1 / (c2*x + c3*ya + c4));\n      double wr = xs, wi = ya;\n      for (nu = 0.5 * (nu - 1); nu > 0.4; nu -= 0.5) {\n        // w <- z - nu/w:\n        double denom = nu / (wr*wr + wi*wi);\n        wr = xs - wr * denom;\n        wi = ya + wi * denom;\n      }\n      { // w(z) = i/sqrt(pi) / w:\n        double denom = ispi / (wr*wr + wi*wi);\n        ret = C(denom*wi, denom*wr);\n      }\n    }\n    if (y < 0) {\n      // use w(z) = 2.0*exp(-z*z) - w(-z), \n      // but be careful of overflow in exp(-z*z) \n      //                                = exp(-(xs*xs-ya*ya) -2*i*xs*ya) \n      return 2.0*cexp(C((ya-xs)*(xs+ya), 2*xs*y)) - ret;\n    }\n    else\n      return ret;\n  }\n#else // !USE_CONTINUED_FRACTION\n  if (x + ya > 1e7) { // w(z) = i/sqrt(pi) / z, to machine precision\n    const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi)\n    double xs = (y < 0 ? -creal(z) : creal(z)); // compute for -z if y < 0\n    // scale to avoid overflow\n    if (x > ya) {\n      double yax = ya / xs; \n      double denom = ispi / (xs + yax*ya);\n      ret = C(denom*yax, denom);\n    }\n    else {\n      double xya = xs / ya;\n      double denom = ispi / (xya*xs + ya);\n      ret = C(denom, denom*xya);\n    }\n    if (y < 0) {\n      // use w(z) = 2.0*exp(-z*z) - w(-z), \n      // but be careful of overflow in exp(-z*z) \n      //                                = exp(-(xs*xs-ya*ya) -2*i*xs*ya) \n      return 2.0*cexp(C((ya-xs)*(xs+ya), 2*xs*y)) - ret;\n    }\n    else\n      return ret;\n  }\n#endif // !USE_CONTINUED_FRACTION \n\n  /* Note: The test that seems to be suggested in the paper is x <\n     sqrt(-log(DBL_MIN)), about 26.6, since otherwise exp(-x^2)\n     underflows to zero and sum1,sum2,sum4 are zero.  However, long\n     before this occurs, the sum1,sum2,sum4 contributions are\n     negligible in double precision; I find that this happens for x >\n     about 6, for all y.  On the other hand, I find that the case\n     where we compute all of the sums is faster (at least with the\n     precomputed expa2n2 table) until about x=10.  Furthermore, if we\n     try to compute all of the sums for x > 20, I find that we\n     sometimes run into numerical problems because underflow/overflow\n     problems start to appear in the various coefficients of the sums,\n     below.  Therefore, we use x < 10 here. */\n  else if (x < 10) {\n    double prod2ax = 1, prodm2ax = 1;\n    double expx2;\n\n    if (isnan(y))\n      return C(y,y);\n    \n    /* Somewhat ugly copy-and-paste duplication here, but I see significant\n       speedups from using the special-case code with the precomputed\n       exponential, and the x < 5e-4 special case is needed for accuracy. */\n\n    if (relerr == DBL_EPSILON) { // use precomputed exp(-a2*(n*n)) table\n      if (x < 5e-4) { // compute sum4 and sum5 together as sum5-sum4\n        const double x2 = x*x;\n        expx2 = 1 - x2 * (1 - 0.5*x2); // exp(-x*x) via Taylor\n        // compute exp(2*a*x) and exp(-2*a*x) via Taylor, to double precision\n        const double ax2 = 1.036642960860171859744*x; // 2*a*x\n        const double exp2ax =\n          1 + ax2 * (1 + ax2 * (0.5 + 0.166666666666666666667*ax2));\n        const double expm2ax =\n          1 - ax2 * (1 - ax2 * (0.5 - 0.166666666666666666667*ax2));\n        for (int n = 1; 1; ++n) {\n          const double coef = expa2n2[n-1] * expx2 / (a2*(n*n) + y*y);\n          prod2ax *= exp2ax;\n          prodm2ax *= expm2ax;\n          sum1 += coef;\n          sum2 += coef * prodm2ax;\n          sum3 += coef * prod2ax;\n          \n          // really = sum5 - sum4\n          sum5 += coef * (2*a) * n * sinh_taylor((2*a)*n*x);\n          \n          // test convergence via sum3\n          if (coef * prod2ax < relerr * sum3) break;\n        }\n      }\n      else { // x > 5e-4, compute sum4 and sum5 separately\n        expx2 = exp(-x*x);\n        const double exp2ax = exp((2*a)*x), expm2ax = 1 / exp2ax;\n        for (int n = 1; 1; ++n) {\n          const double coef = expa2n2[n-1] * expx2 / (a2*(n*n) + y*y);\n          prod2ax *= exp2ax;\n          prodm2ax *= expm2ax;\n          sum1 += coef;\n          sum2 += coef * prodm2ax;\n          sum4 += (coef * prodm2ax) * (a*n);\n          sum3 += coef * prod2ax;\n          sum5 += (coef * prod2ax) * (a*n);\n          // test convergence via sum5, since this sum has the slowest decay\n          if ((coef * prod2ax) * (a*n) < relerr * sum5) break;\n        }\n      }\n    }\n    else { // relerr != DBL_EPSILON, compute exp(-a2*(n*n)) on the fly\n      const double exp2ax = exp((2*a)*x), expm2ax = 1 / exp2ax;\n      if (x < 5e-4) { // compute sum4 and sum5 together as sum5-sum4\n        const double x2 = x*x;\n        expx2 = 1 - x2 * (1 - 0.5*x2); // exp(-x*x) via Taylor\n        for (int n = 1; 1; ++n) {\n          const double coef = exp(-a2*(n*n)) * expx2 / (a2*(n*n) + y*y);\n          prod2ax *= exp2ax;\n          prodm2ax *= expm2ax;\n          sum1 += coef;\n          sum2 += coef * prodm2ax;\n          sum3 += coef * prod2ax;\n          \n          // really = sum5 - sum4\n          sum5 += coef * (2*a) * n * sinh_taylor((2*a)*n*x);\n          \n          // test convergence via sum3\n          if (coef * prod2ax < relerr * sum3) break;\n        }\n      }\n      else { // x > 5e-4, compute sum4 and sum5 separately\n        expx2 = exp(-x*x);\n        for (int n = 1; 1; ++n) {\n          const double coef = exp(-a2*(n*n)) * expx2 / (a2*(n*n) + y*y);\n          prod2ax *= exp2ax;\n          prodm2ax *= expm2ax;\n          sum1 += coef;\n          sum2 += coef * prodm2ax;\n          sum4 += (coef * prodm2ax) * (a*n);\n          sum3 += coef * prod2ax;\n          sum5 += (coef * prod2ax) * (a*n);\n          // test convergence via sum5, since this sum has the slowest decay\n          if ((coef * prod2ax) * (a*n) < relerr * sum5) break;\n        }\n      }\n    }\n    const double expx2erfcxy = // avoid spurious overflow for large negative y\n      y > -6 // for y < -6, erfcx(y) = 2*exp(y*y) to double precision\n      ? expx2*FADDEEVA_RE(erfcx)(y) : 2*exp(y*y-x*x);\n    if (y > 5) { // imaginary terms cancel\n      const double sinxy = sin(x*y);\n      ret = (expx2erfcxy - c*y*sum1) * cos(2*x*y)\n        + (c*x*expx2) * sinxy * sinc(x*y, sinxy);\n    }\n    else {\n      double xs = creal(z);\n      const double sinxy = sin(xs*y);\n      const double sin2xy = sin(2*xs*y), cos2xy = cos(2*xs*y);\n      const double coef1 = expx2erfcxy - c*y*sum1;\n      const double coef2 = c*xs*expx2;\n      ret = C(coef1 * cos2xy + coef2 * sinxy * sinc(xs*y, sinxy),\n              coef2 * sinc(2*xs*y, sin2xy) - coef1 * sin2xy);\n    }\n  }\n  else { // x large: only sum3 & sum5 contribute (see above note)    \n    if (isnan(x))\n      return C(x,x);\n    if (isnan(y))\n      return C(y,y);\n\n#if USE_CONTINUED_FRACTION\n    ret = exp(-x*x); // |y| < 1e-10, so we only need exp(-x*x) term\n#else\n    if (y < 0) {\n      /* erfcx(y) ~ 2*exp(y*y) + (< 1) if y < 0, so\n         erfcx(y)*exp(-x*x) ~ 2*exp(y*y-x*x) term may not be negligible\n         if y*y - x*x > -36 or so.  So, compute this term just in case.\n         We also need the -exp(-x*x) term to compute Re[w] accurately\n         in the case where y is very small. */\n      ret = cpolar(2*exp(y*y-x*x) - exp(-x*x), -2*creal(z)*y);\n    }\n    else\n      ret = exp(-x*x); // not negligible in real part if y very small\n#endif\n    // (round instead of ceil as in original paper; note that x/a > 1 here)\n    double n0 = floor(x/a + 0.5); // sum in both directions, starting at n0\n    double dx = a*n0 - x;\n    sum3 = exp(-dx*dx) / (a2*(n0*n0) + y*y);\n    sum5 = a*n0 * sum3;\n    double exp1 = exp(4*a*dx), exp1dn = 1;\n    int dn;\n    for (dn = 1; n0 - dn > 0; ++dn) { // loop over n0-dn and n0+dn terms\n      double np = n0 + dn, nm = n0 - dn;\n      double tp = exp(-sqr(a*dn+dx));\n      double tm = tp * (exp1dn *= exp1); // trick to get tm from tp\n      tp /= (a2*(np*np) + y*y);\n      tm /= (a2*(nm*nm) + y*y);\n      sum3 += tp + tm;\n      sum5 += a * (np * tp + nm * tm);\n      if (a * (np * tp + nm * tm) < relerr * sum5) goto finish;\n    }\n    while (1) { // loop over n0+dn terms only (since n0-dn <= 0)\n      double np = n0 + dn++;\n      double tp = exp(-sqr(a*dn+dx)) / (a2*(np*np) + y*y);\n      sum3 += tp;\n      sum5 += a * np * tp;\n      if (a * np * tp < relerr * sum5) goto finish;\n    }\n  }\n finish:\n  return ret + C((0.5*c)*y*(sum2+sum3), \n                 (0.5*c)*copysign(sum5-sum4, creal(z)));\n}\n\n/////////////////////////////////////////////////////////////////////////\n\n/* erfcx(x) = exp(x^2) erfc(x) function, for real x, written by\n   Steven G. Johnson, October 2012.\n\n   This function combines a few different ideas.\n\n   First, for x > 50, it uses a continued-fraction expansion (same as\n   for the Faddeeva function, but with algebraic simplifications for z=i*x).\n\n   Second, for 0 <= x <= 50, it uses Chebyshev polynomial approximations,\n   but with two twists:\n\n      a) It maps x to y = 4 / (4+x) in [0,1].  This simple transformation,\n         inspired by a similar transformation in the octave-forge/specfun\n         erfcx by Soren Hauberg, results in much faster Chebyshev convergence\n         than other simple transformations I have examined.\n\n      b) Instead of using a single Chebyshev polynomial for the entire\n         [0,1] y interval, we break the interval up into 100 equal\n         subintervals, with a switch/lookup table, and use much lower\n         degree Chebyshev polynomials in each subinterval.  This greatly\n         improves performance in my tests.\n\n   For x < 0, we use the relationship erfcx(-x) = 2 exp(x^2) - erfc(x),\n   with the usual checks for overflow etcetera.\n\n   Performance-wise, it seems to be substantially faster than either\n   the SLATEC DERFC function [or an erfcx function derived therefrom]\n   or Cody's CALERF function (from netlib.org/specfun), while\n   retaining near machine precision in accuracy.  */\n\n/* Given y100=100*y, where y = 4/(4+x) for x >= 0, compute erfc(x).\n\n   Uses a look-up table of 100 different Chebyshev polynomials\n   for y intervals [0,0.01], [0.01,0.02], ...., [0.99,1], generated\n   with the help of Maple and a little shell script.   This allows\n   the Chebyshev polynomials to be of significantly lower degree (about 1/4)\n   compared to fitting the whole [0,1] interval with a single polynomial. */\nstatic double erfcx_y100(double y100)\n{\n  switch (static_cast<int> (y100)) {\ncase 0: {\ndouble t = 2*y100 - 1;\nreturn 0.70878032454106438663e-3 + (0.71234091047026302958e-3 + (0.35779077297597742384e-5 + (0.17403143962587937815e-7 + (0.81710660047307788845e-10 + (0.36885022360434957634e-12 + 0.15917038551111111111e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 1: {\ndouble t = 2*y100 - 3;\nreturn 0.21479143208285144230e-2 + (0.72686402367379996033e-3 + (0.36843175430938995552e-5 + (0.18071841272149201685e-7 + (0.85496449296040325555e-10 + (0.38852037518534291510e-12 + 0.16868473576888888889e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 2: {\ndouble t = 2*y100 - 5;\nreturn 0.36165255935630175090e-2 + (0.74182092323555510862e-3 + (0.37948319957528242260e-5 + (0.18771627021793087350e-7 + (0.89484715122415089123e-10 + (0.40935858517772440862e-12 + 0.17872061464888888889e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 3: {\ndouble t = 2*y100 - 7;\nreturn 0.51154983860031979264e-2 + (0.75722840734791660540e-3 + (0.39096425726735703941e-5 + (0.19504168704300468210e-7 + (0.93687503063178993915e-10 + (0.43143925959079664747e-12 + 0.18939926435555555556e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 4: {\ndouble t = 2*y100 - 9;\nreturn 0.66457513172673049824e-2 + (0.77310406054447454920e-3 + (0.40289510589399439385e-5 + (0.20271233238288381092e-7 + (0.98117631321709100264e-10 + (0.45484207406017752971e-12 + 0.20076352213333333333e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 5: {\ndouble t = 2*y100 - 11;\nreturn 0.82082389970241207883e-2 + (0.78946629611881710721e-3 + (0.41529701552622656574e-5 + (0.21074693344544655714e-7 + (0.10278874108587317989e-9 + (0.47965201390613339638e-12 + 0.21285907413333333333e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 6: {\ndouble t = 2*y100 - 13;\nreturn 0.98039537275352193165e-2 + (0.80633440108342840956e-3 + (0.42819241329736982942e-5 + (0.21916534346907168612e-7 + (0.10771535136565470914e-9 + (0.50595972623692822410e-12 + 0.22573462684444444444e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 7: {\ndouble t = 2*y100 - 15;\nreturn 0.11433927298290302370e-1 + (0.82372858383196561209e-3 + (0.44160495311765438816e-5 + (0.22798861426211986056e-7 + (0.11291291745879239736e-9 + (0.53386189365816880454e-12 + 0.23944209546666666667e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 8: {\ndouble t = 2*y100 - 17;\nreturn 0.13099232878814653979e-1 + (0.84167002467906968214e-3 + (0.45555958988457506002e-5 + (0.23723907357214175198e-7 + (0.11839789326602695603e-9 + (0.56346163067550237877e-12 + 0.25403679644444444444e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 9: {\ndouble t = 2*y100 - 19;\nreturn 0.14800987015587535621e-1 + (0.86018092946345943214e-3 + (0.47008265848816866105e-5 + (0.24694040760197315333e-7 + (0.12418779768752299093e-9 + (0.59486890370320261949e-12 + 0.26957764568888888889e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 10: {\ndouble t = 2*y100 - 21;\nreturn 0.16540351739394069380e-1 + (0.87928458641241463952e-3 + (0.48520195793001753903e-5 + (0.25711774900881709176e-7 + (0.13030128534230822419e-9 + (0.62820097586874779402e-12 + 0.28612737351111111111e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 11: {\ndouble t = 2*y100 - 23;\nreturn 0.18318536789842392647e-1 + (0.89900542647891721692e-3 + (0.50094684089553365810e-5 + (0.26779777074218070482e-7 + (0.13675822186304615566e-9 + (0.66358287745352705725e-12 + 0.30375273884444444444e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 12: {\ndouble t = 2*y100 - 25;\nreturn 0.20136801964214276775e-1 + (0.91936908737673676012e-3 + (0.51734830914104276820e-5 + (0.27900878609710432673e-7 + (0.14357976402809042257e-9 + (0.70114790311043728387e-12 + 0.32252476000000000000e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 13: {\ndouble t = 2*y100 - 27;\nreturn 0.21996459598282740954e-1 + (0.94040248155366777784e-3 + (0.53443911508041164739e-5 + (0.29078085538049374673e-7 + (0.15078844500329731137e-9 + (0.74103813647499204269e-12 + 0.34251892320000000000e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 14: {\ndouble t = 2*y100 - 29;\nreturn 0.23898877187226319502e-1 + (0.96213386835900177540e-3 + (0.55225386998049012752e-5 + (0.30314589961047687059e-7 + (0.15840826497296335264e-9 + (0.78340500472414454395e-12 + 0.36381553564444444445e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 15: {\ndouble t = 2*y100 - 31;\nreturn 0.25845480155298518485e-1 + (0.98459293067820123389e-3 + (0.57082915920051843672e-5 + (0.31613782169164830118e-7 + (0.16646478745529630813e-9 + (0.82840985928785407942e-12 + 0.38649975768888888890e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 16: {\ndouble t = 2*y100 - 33;\nreturn 0.27837754783474696598e-1 + (0.10078108563256892757e-2 + (0.59020366493792212221e-5 + (0.32979263553246520417e-7 + (0.17498524159268458073e-9 + (0.87622459124842525110e-12 + 0.41066206488888888890e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 17: {\ndouble t = 2*y100 - 35;\nreturn 0.29877251304899307550e-1 + (0.10318204245057349310e-2 + (0.61041829697162055093e-5 + (0.34414860359542720579e-7 + (0.18399863072934089607e-9 + (0.92703227366365046533e-12 + 0.43639844053333333334e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 18: {\ndouble t = 2*y100 - 37;\nreturn 0.31965587178596443475e-1 + (0.10566560976716574401e-2 + (0.63151633192414586770e-5 + (0.35924638339521924242e-7 + (0.19353584758781174038e-9 + (0.98102783859889264382e-12 + 0.46381060817777777779e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 19: {\ndouble t = 2*y100 - 39;\nreturn 0.34104450552588334840e-1 + (0.10823541191350532574e-2 + (0.65354356159553934436e-5 + (0.37512918348533521149e-7 + (0.20362979635817883229e-9 + (0.10384187833037282363e-11 + 0.49300625262222222221e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 20: {\ndouble t = 2*y100 - 41;\nreturn 0.36295603928292425716e-1 + (0.11089526167995268200e-2 + (0.67654845095518363577e-5 + (0.39184292949913591646e-7 + (0.21431552202133775150e-9 + (0.10994259106646731797e-11 + 0.52409949102222222221e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 21: {\ndouble t = 2*y100 - 43;\nreturn 0.38540888038840509795e-1 + (0.11364917134175420009e-2 + (0.70058230641246312003e-5 + (0.40943644083718586939e-7 + (0.22563034723692881631e-9 + (0.11642841011361992885e-11 + 0.55721092871111111110e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 22: {\ndouble t = 2*y100 - 45;\nreturn 0.40842225954785960651e-1 + (0.11650136437945673891e-2 + (0.72569945502343006619e-5 + (0.42796161861855042273e-7 + (0.23761401711005024162e-9 + (0.12332431172381557035e-11 + 0.59246802364444444445e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 23: {\ndouble t = 2*y100 - 47;\nreturn 0.43201627431540222422e-1 + (0.11945628793917272199e-2 + (0.75195743532849206263e-5 + (0.44747364553960993492e-7 + (0.25030885216472953674e-9 + (0.13065684400300476484e-11 + 0.63000532853333333334e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 24: {\ndouble t = 2*y100 - 49;\nreturn 0.45621193513810471438e-1 + (0.12251862608067529503e-2 + (0.77941720055551920319e-5 + (0.46803119830954460212e-7 + (0.26375990983978426273e-9 + (0.13845421370977119765e-11 + 0.66996477404444444445e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 25: {\ndouble t = 2*y100 - 51;\nreturn 0.48103121413299865517e-1 + (0.12569331386432195113e-2 + (0.80814333496367673980e-5 + (0.48969667335682018324e-7 + (0.27801515481905748484e-9 + (0.14674637611609884208e-11 + 0.71249589351111111110e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 26: {\ndouble t = 2*y100 - 53;\nreturn 0.50649709676983338501e-1 + (0.12898555233099055810e-2 + (0.83820428414568799654e-5 + (0.51253642652551838659e-7 + (0.29312563849675507232e-9 + (0.15556512782814827846e-11 + 0.75775607822222222221e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 27: {\ndouble t = 2*y100 - 55;\nreturn 0.53263363664388864181e-1 + (0.13240082443256975769e-2 + (0.86967260015007658418e-5 + (0.53662102750396795566e-7 + (0.30914568786634796807e-9 + (0.16494420240828493176e-11 + 0.80591079644444444445e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 28: {\ndouble t = 2*y100 - 57;\nreturn 0.55946601353500013794e-1 + (0.13594491197408190706e-2 + (0.90262520233016380987e-5 + (0.56202552975056695376e-7 + (0.32613310410503135996e-9 + (0.17491936862246367398e-11 + 0.85713381688888888890e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 29: {\ndouble t = 2*y100 - 59;\nreturn 0.58702059496154081813e-1 + (0.13962391363223647892e-2 + (0.93714365487312784270e-5 + (0.58882975670265286526e-7 + (0.34414937110591753387e-9 + (0.18552853109751857859e-11 + 0.91160736711111111110e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 30: {\ndouble t = 2*y100 - 61;\nreturn 0.61532500145144778048e-1 + (0.14344426411912015247e-2 + (0.97331446201016809696e-5 + (0.61711860507347175097e-7 + (0.36325987418295300221e-9 + (0.19681183310134518232e-11 + 0.96952238400000000000e-14 * t) * t) * t) * t) * t) * t;\n}\ncase 31: {\ndouble t = 2*y100 - 63;\nreturn 0.64440817576653297993e-1 + (0.14741275456383131151e-2 + (0.10112293819576437838e-4 + (0.64698236605933246196e-7 + (0.38353412915303665586e-9 + (0.20881176114385120186e-11 + 0.10310784480000000000e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 32: {\ndouble t = 2*y100 - 65;\nreturn 0.67430045633130393282e-1 + (0.15153655418916540370e-2 + (0.10509857606888328667e-4 + (0.67851706529363332855e-7 + (0.40504602194811140006e-9 + (0.22157325110542534469e-11 + 0.10964842115555555556e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 33: {\ndouble t = 2*y100 - 67;\nreturn 0.70503365513338850709e-1 + (0.15582323336495709827e-2 + (0.10926868866865231089e-4 + (0.71182482239613507542e-7 + (0.42787405890153386710e-9 + (0.23514379522274416437e-11 + 0.11659571751111111111e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 34: {\ndouble t = 2*y100 - 69;\nreturn 0.73664114037944596353e-1 + (0.16028078812438820413e-2 + (0.11364423678778207991e-4 + (0.74701423097423182009e-7 + (0.45210162777476488324e-9 + (0.24957355004088569134e-11 + 0.12397238257777777778e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 35: {\ndouble t = 2*y100 - 71;\nreturn 0.76915792420819562379e-1 + (0.16491766623447889354e-2 + (0.11823685320041302169e-4 + (0.78420075993781544386e-7 + (0.47781726956916478925e-9 + (0.26491544403815724749e-11 + 0.13180196462222222222e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 36: {\ndouble t = 2*y100 - 73;\nreturn 0.80262075578094612819e-1 + (0.16974279491709504117e-2 + (0.12305888517309891674e-4 + (0.82350717698979042290e-7 + (0.50511496109857113929e-9 + (0.28122528497626897696e-11 + 0.14010889635555555556e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 37: {\ndouble t = 2*y100 - 75;\nreturn 0.83706822008980357446e-1 + (0.17476561032212656962e-2 + (0.12812343958540763368e-4 + (0.86506399515036435592e-7 + (0.53409440823869467453e-9 + (0.29856186620887555043e-11 + 0.14891851591111111111e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 38: {\ndouble t = 2*y100 - 77;\nreturn 0.87254084284461718231e-1 + (0.17999608886001962327e-2 + (0.13344443080089492218e-4 + (0.90900994316429008631e-7 + (0.56486134972616465316e-9 + (0.31698707080033956934e-11 + 0.15825697795555555556e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 39: {\ndouble t = 2*y100 - 79;\nreturn 0.90908120182172748487e-1 + (0.18544478050657699758e-2 + (0.13903663143426120077e-4 + (0.95549246062549906177e-7 + (0.59752787125242054315e-9 + (0.33656597366099099413e-11 + 0.16815130613333333333e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 40: {\ndouble t = 2*y100 - 81;\nreturn 0.94673404508075481121e-1 + (0.19112284419887303347e-2 + (0.14491572616545004930e-4 + (0.10046682186333613697e-6 + (0.63221272959791000515e-9 + (0.35736693975589130818e-11 + 0.17862931591111111111e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 41: {\ndouble t = 2*y100 - 83;\nreturn 0.98554641648004456555e-1 + (0.19704208544725622126e-2 + (0.15109836875625443935e-4 + (0.10567036667675984067e-6 + (0.66904168640019354565e-9 + (0.37946171850824333014e-11 + 0.18971959040000000000e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 42: {\ndouble t = 2*y100 - 85;\nreturn 0.10255677889470089531e0 + (0.20321499629472857418e-2 + (0.15760224242962179564e-4 + (0.11117756071353507391e-6 + (0.70814785110097658502e-9 + (0.40292553276632563925e-11 + 0.20145143075555555556e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 43: {\ndouble t = 2*y100 - 87;\nreturn 0.10668502059865093318e0 + (0.20965479776148731610e-2 + (0.16444612377624983565e-4 + (0.11700717962026152749e-6 + (0.74967203250938418991e-9 + (0.42783716186085922176e-11 + 0.21385479360000000000e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 44: {\ndouble t = 2*y100 - 89;\nreturn 0.11094484319386444474e0 + (0.21637548491908170841e-2 + (0.17164995035719657111e-4 + (0.12317915750735938089e-6 + (0.79376309831499633734e-9 + (0.45427901763106353914e-11 + 0.22696025653333333333e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 45: {\ndouble t = 2*y100 - 91;\nreturn 0.11534201115268804714e0 + (0.22339187474546420375e-2 + (0.17923489217504226813e-4 + (0.12971465288245997681e-6 + (0.84057834180389073587e-9 + (0.48233721206418027227e-11 + 0.24079890062222222222e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 46: {\ndouble t = 2*y100 - 93;\nreturn 0.11988259392684094740e0 + (0.23071965691918689601e-2 + (0.18722342718958935446e-4 + (0.13663611754337957520e-6 + (0.89028385488493287005e-9 + (0.51210161569225846701e-11 + 0.25540227111111111111e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 47: {\ndouble t = 2*y100 - 95;\nreturn 0.12457298393509812907e0 + (0.23837544771809575380e-2 + (0.19563942105711612475e-4 + (0.14396736847739470782e-6 + (0.94305490646459247016e-9 + (0.54366590583134218096e-11 + 0.27080225920000000000e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 48: {\ndouble t = 2*y100 - 97;\nreturn 0.12941991566142438816e0 + (0.24637684719508859484e-2 + (0.20450821127475879816e-4 + (0.15173366280523906622e-6 + (0.99907632506389027739e-9 + (0.57712760311351625221e-11 + 0.28703099555555555556e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 49: {\ndouble t = 2*y100 - 99;\nreturn 0.13443048593088696613e0 + (0.25474249981080823877e-2 + (0.21385669591362915223e-4 + (0.15996177579900443030e-6 + (0.10585428844575134013e-8 + (0.61258809536787882989e-11 + 0.30412080142222222222e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 50: {\ndouble t = 2*y100 - 101;\nreturn 0.13961217543434561353e0 + (0.26349215871051761416e-2 + (0.22371342712572567744e-4 + (0.16868008199296822247e-6 + (0.11216596910444996246e-8 + (0.65015264753090890662e-11 + 0.32210394506666666666e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 51: {\ndouble t = 2*y100 - 103;\nreturn 0.14497287157673800690e0 + (0.27264675383982439814e-2 + (0.23410870961050950197e-4 + (0.17791863939526376477e-6 + (0.11886425714330958106e-8 + (0.68993039665054288034e-11 + 0.34101266222222222221e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 52: {\ndouble t = 2*y100 - 105;\nreturn 0.15052089272774618151e0 + (0.28222846410136238008e-2 + (0.24507470422713397006e-4 + (0.18770927679626136909e-6 + (0.12597184587583370712e-8 + (0.73203433049229821618e-11 + 0.36087889048888888890e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 53: {\ndouble t = 2*y100 - 107;\nreturn 0.15626501395774612325e0 + (0.29226079376196624949e-2 + (0.25664553693768450545e-4 + (0.19808568415654461964e-6 + (0.13351257759815557897e-8 + (0.77658124891046760667e-11 + 0.38173420035555555555e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 54: {\ndouble t = 2*y100 - 109;\nreturn 0.16221449434620737567e0 + (0.30276865332726475672e-2 + (0.26885741326534564336e-4 + (0.20908350604346384143e-6 + (0.14151148144240728728e-8 + (0.82369170665974313027e-11 + 0.40360957457777777779e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 55: {\ndouble t = 2*y100 - 111;\nreturn 0.16837910595412130659e0 + (0.31377844510793082301e-2 + (0.28174873844911175026e-4 + (0.22074043807045782387e-6 + (0.14999481055996090039e-8 + (0.87348993661930809254e-11 + 0.42653528977777777779e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 56: {\ndouble t = 2*y100 - 113;\nreturn 0.17476916455659369953e0 + (0.32531815370903068316e-2 + (0.29536024347344364074e-4 + (0.23309632627767074202e-6 + (0.15899007843582444846e-8 + (0.92610375235427359475e-11 + 0.45054073102222222221e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 57: {\ndouble t = 2*y100 - 115;\nreturn 0.18139556223643701364e0 + (0.33741744168096996041e-2 + (0.30973511714709500836e-4 + (0.24619326937592290996e-6 + (0.16852609412267750744e-8 + (0.98166442942854895573e-11 + 0.47565418097777777779e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 58: {\ndouble t = 2*y100 - 117;\nreturn 0.18826980194443664549e0 + (0.35010775057740317997e-2 + (0.32491914440014267480e-4 + (0.26007572375886319028e-6 + (0.17863299617388376116e-8 + (0.10403065638343878679e-10 + 0.50190265831111111110e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 59: {\ndouble t = 2*y100 - 119;\nreturn 0.19540403413693967350e0 + (0.36342240767211326315e-2 + (0.34096085096200907289e-4 + (0.27479061117017637474e-6 + (0.18934228504790032826e-8 + (0.11021679075323598664e-10 + 0.52931171733333333334e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 60: {\ndouble t = 2*y100 - 121;\nreturn 0.20281109560651886959e0 + (0.37739673859323597060e-2 + (0.35791165457592409054e-4 + (0.29038742889416172404e-6 + (0.20068685374849001770e-8 + (0.11673891799578381999e-10 + 0.55790523093333333334e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 61: {\ndouble t = 2*y100 - 123;\nreturn 0.21050455062669334978e0 + (0.39206818613925652425e-2 + (0.37582602289680101704e-4 + (0.30691836231886877385e-6 + (0.21270101645763677824e-8 + (0.12361138551062899455e-10 + 0.58770520160000000000e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 62: {\ndouble t = 2*y100 - 125;\nreturn 0.21849873453703332479e0 + (0.40747643554689586041e-2 + (0.39476163820986711501e-4 + (0.32443839970139918836e-6 + (0.22542053491518680200e-8 + (0.13084879235290858490e-10 + 0.61873153262222222221e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 63: {\ndouble t = 2*y100 - 127;\nreturn 0.22680879990043229327e0 + (0.42366354648628516935e-2 + (0.41477956909656896779e-4 + (0.34300544894502810002e-6 + (0.23888264229264067658e-8 + (0.13846596292818514601e-10 + 0.65100183751111111110e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 64: {\ndouble t = 2*y100 - 129;\nreturn 0.23545076536988703937e0 + (0.44067409206365170888e-2 + (0.43594444916224700881e-4 + (0.36268045617760415178e-6 + (0.25312606430853202748e-8 + (0.14647791812837903061e-10 + 0.68453122631111111110e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 65: {\ndouble t = 2*y100 - 131;\nreturn 0.24444156740777432838e0 + (0.45855530511605787178e-2 + (0.45832466292683085475e-4 + (0.38352752590033030472e-6 + (0.26819103733055603460e-8 + (0.15489984390884756993e-10 + 0.71933206364444444445e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 66: {\ndouble t = 2*y100 - 133;\nreturn 0.25379911500634264643e0 + (0.47735723208650032167e-2 + (0.48199253896534185372e-4 + (0.40561404245564732314e-6 + (0.28411932320871165585e-8 + (0.16374705736458320149e-10 + 0.75541379822222222221e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 67: {\ndouble t = 2*y100 - 135;\nreturn 0.26354234756393613032e0 + (0.49713289477083781266e-2 + (0.50702455036930367504e-4 + (0.42901079254268185722e-6 + (0.30095422058900481753e-8 + (0.17303497025347342498e-10 + 0.79278273368888888890e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 68: {\ndouble t = 2*y100 - 137;\nreturn 0.27369129607732343398e0 + (0.51793846023052643767e-2 + (0.53350152258326602629e-4 + (0.45379208848865015485e-6 + (0.31874057245814381257e-8 + (0.18277905010245111046e-10 + 0.83144182364444444445e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 69: {\ndouble t = 2*y100 - 139;\nreturn 0.28426714781640316172e0 + (0.53983341916695141966e-2 + (0.56150884865255810638e-4 + (0.48003589196494734238e-6 + (0.33752476967570796349e-8 + (0.19299477888083469086e-10 + 0.87139049137777777779e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 70: {\ndouble t = 2*y100 - 141;\nreturn 0.29529231465348519920e0 + (0.56288077305420795663e-2 + (0.59113671189913307427e-4 + (0.50782393781744840482e-6 + (0.35735475025851713168e-8 + (0.20369760937017070382e-10 + 0.91262442613333333334e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 71: {\ndouble t = 2*y100 - 143;\nreturn 0.30679050522528838613e0 + (0.58714723032745403331e-2 + (0.62248031602197686791e-4 + (0.53724185766200945789e-6 + (0.37827999418960232678e-8 + (0.21490291930444538307e-10 + 0.95513539182222222221e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 72: {\ndouble t = 2*y100 - 145;\nreturn 0.31878680111173319425e0 + (0.61270341192339103514e-2 + (0.65564012259707640976e-4 + (0.56837930287837738996e-6 + (0.40035151353392378882e-8 + (0.22662596341239294792e-10 + 0.99891109760000000000e-13 * t) * t) * t) * t) * t) * t;\n}\ncase 73: {\ndouble t = 2*y100 - 147;\nreturn 0.33130773722152622027e0 + (0.63962406646798080903e-2 + (0.69072209592942396666e-4 + (0.60133006661885941812e-6 + (0.42362183765883466691e-8 + (0.23888182347073698382e-10 + 0.10439349811555555556e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 74: {\ndouble t = 2*y100 - 149;\nreturn 0.34438138658041336523e0 + (0.66798829540414007258e-2 + (0.72783795518603561144e-4 + (0.63619220443228800680e-6 + (0.44814499336514453364e-8 + (0.25168535651285475274e-10 + 0.10901861383111111111e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 75: {\ndouble t = 2*y100 - 151;\nreturn 0.35803744972380175583e0 + (0.69787978834882685031e-2 + (0.76710543371454822497e-4 + (0.67306815308917386747e-6 + (0.47397647975845228205e-8 + (0.26505114141143050509e-10 + 0.11376390933333333333e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 76: {\ndouble t = 2*y100 - 153;\nreturn 0.37230734890119724188e0 + (0.72938706896461381003e-2 + (0.80864854542670714092e-4 + (0.71206484718062688779e-6 + (0.50117323769745883805e-8 + (0.27899342394100074165e-10 + 0.11862637614222222222e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 77: {\ndouble t = 2*y100 - 155;\nreturn 0.38722432730555448223e0 + (0.76260375162549802745e-2 + (0.85259785810004603848e-4 + (0.75329383305171327677e-6 + (0.52979361368388119355e-8 + (0.29352606054164086709e-10 + 0.12360253370666666667e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 78: {\ndouble t = 2*y100 - 157;\nreturn 0.40282355354616940667e0 + (0.79762880915029728079e-2 + (0.89909077342438246452e-4 + (0.79687137961956194579e-6 + (0.55989731807360403195e-8 + (0.30866246101464869050e-10 + 0.12868841946666666667e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 79: {\ndouble t = 2*y100 - 159;\nreturn 0.41914223158913787649e0 + (0.83456685186950463538e-2 + (0.94827181359250161335e-4 + (0.84291858561783141014e-6 + (0.59154537751083485684e-8 + (0.32441553034347469291e-10 + 0.13387957943111111111e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 80: {\ndouble t = 2*y100 - 161;\nreturn 0.43621971639463786896e0 + (0.87352841828289495773e-2 + (0.10002929142066799966e-3 + (0.89156148280219880024e-6 + (0.62480008150788597147e-8 + (0.34079760983458878910e-10 + 0.13917107176888888889e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 81: {\ndouble t = 2*y100 - 163;\nreturn 0.45409763548534330981e0 + (0.91463027755548240654e-2 + (0.10553137232446167258e-3 + (0.94293113464638623798e-6 + (0.65972492312219959885e-8 + (0.35782041795476563662e-10 + 0.14455745872000000000e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 82: {\ndouble t = 2*y100 - 165;\nreturn 0.47282001668512331468e0 + (0.95799574408860463394e-2 + (0.11135019058000067469e-3 + (0.99716373005509038080e-6 + (0.69638453369956970347e-8 + (0.37549499088161345850e-10 + 0.15003280712888888889e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 83: {\ndouble t = 2*y100 - 167;\nreturn 0.49243342227179841649e0 + (0.10037550043909497071e-1 + (0.11750334542845234952e-3 + (0.10544006716188967172e-5 + (0.73484461168242224872e-8 + (0.39383162326435752965e-10 + 0.15559069118222222222e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 84: {\ndouble t = 2*y100 - 169;\nreturn 0.51298708979209258326e0 + (0.10520454564612427224e-1 + (0.12400930037494996655e-3 + (0.11147886579371265246e-5 + (0.77517184550568711454e-8 + (0.41283980931872622611e-10 + 0.16122419680000000000e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 85: {\ndouble t = 2*y100 - 171;\nreturn 0.53453307979101369843e0 + (0.11030120618800726938e-1 + (0.13088741519572269581e-3 + (0.11784797595374515432e-5 + (0.81743383063044825400e-8 + (0.43252818449517081051e-10 + 0.16692592640000000000e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 86: {\ndouble t = 2*y100 - 173;\nreturn 0.55712643071169299478e0 + (0.11568077107929735233e-1 + (0.13815797838036651289e-3 + (0.12456314879260904558e-5 + (0.86169898078969313597e-8 + (0.45290446811539652525e-10 + 0.17268801084444444444e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 87: {\ndouble t = 2*y100 - 175;\nreturn 0.58082532122519320968e0 + (0.12135935999503877077e-1 + (0.14584223996665838559e-3 + (0.13164068573095710742e-5 + (0.90803643355106020163e-8 + (0.47397540713124619155e-10 + 0.17850211608888888889e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 88: {\ndouble t = 2*y100 - 177;\nreturn 0.60569124025293375554e0 + (0.12735396239525550361e-1 + (0.15396244472258863344e-3 + (0.13909744385382818253e-5 + (0.95651595032306228245e-8 + (0.49574672127669041550e-10 + 0.18435945564444444444e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 89: {\ndouble t = 2*y100 - 179;\nreturn 0.63178916494715716894e0 + (0.13368247798287030927e-1 + (0.16254186562762076141e-3 + (0.14695084048334056083e-5 + (0.10072078109604152350e-7 + (0.51822304995680707483e-10 + 0.19025081422222222222e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 90: {\ndouble t = 2*y100 - 181;\nreturn 0.65918774689725319200e0 + (0.14036375850601992063e-1 + (0.17160483760259706354e-3 + (0.15521885688723188371e-5 + (0.10601827031535280590e-7 + (0.54140790105837520499e-10 + 0.19616655146666666667e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 91: {\ndouble t = 2*y100 - 183;\nreturn 0.68795950683174433822e0 + (0.14741765091365869084e-1 + (0.18117679143520433835e-3 + (0.16392004108230585213e-5 + (0.11155116068018043001e-7 + (0.56530360194925690374e-10 + 0.20209663662222222222e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 92: {\ndouble t = 2*y100 - 185;\nreturn 0.71818103808729967036e0 + (0.15486504187117112279e-1 + (0.19128428784550923217e-3 + (0.17307350969359975848e-5 + (0.11732656736113607751e-7 + (0.58991125287563833603e-10 + 0.20803065333333333333e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 93: {\ndouble t = 2*y100 - 187;\nreturn 0.74993321911726254661e0 + (0.16272790364044783382e-1 + (0.20195505163377912645e-3 + (0.18269894883203346953e-5 + (0.12335161021630225535e-7 + (0.61523068312169087227e-10 + 0.21395783431111111111e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 94: {\ndouble t = 2*y100 - 189;\nreturn 0.78330143531283492729e0 + (0.17102934132652429240e-1 + (0.21321800585063327041e-3 + (0.19281661395543913713e-5 + (0.12963340087354341574e-7 + (0.64126040998066348872e-10 + 0.21986708942222222222e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 95: {\ndouble t = 2*y100 - 191;\nreturn 0.81837581041023811832e0 + (0.17979364149044223802e-1 + (0.22510330592753129006e-3 + (0.20344732868018175389e-5 + (0.13617902941839949718e-7 + (0.66799760083972474642e-10 + 0.22574701262222222222e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 96: {\ndouble t = 2*y100 - 193;\nreturn 0.85525144775685126237e0 + (0.18904632212547561026e-1 + (0.23764237370371255638e-3 + (0.21461248251306387979e-5 + (0.14299555071870523786e-7 + (0.69543803864694171934e-10 + 0.23158593688888888889e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 97: {\ndouble t = 2*y100 - 195;\nreturn 0.89402868170849933734e0 + (0.19881418399127202569e-1 + (0.25086793128395995798e-3 + (0.22633402747585233180e-5 + (0.15008997042116532283e-7 + (0.72357609075043941261e-10 + 0.23737194737777777778e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 98: {\ndouble t = 2*y100 - 197;\nreturn 0.93481333942870796363e0 + (0.20912536329780368893e-1 + (0.26481403465998477969e-3 + (0.23863447359754921676e-5 + (0.15746923065472184451e-7 + (0.75240468141720143653e-10 + 0.24309291271111111111e-12 * t) * t) * t) * t) * t) * t;\n}\ncase 99: {\ndouble t = 2*y100 - 199;\nreturn 0.97771701335885035464e0 + (0.22000938572830479551e-1 + (0.27951610702682383001e-3 + (0.25153688325245314530e-5 + (0.16514019547822821453e-7 + (0.78191526829368231251e-10 + 0.24873652355555555556e-12 * t) * t) * t) * t) * t) * t;\n}\n  }\n  // we only get here if y = 1, i.e. |x| < 4*eps, in which case\n  // erfcx is within 1e-15 of 1..\n  return 1.0;\n}\n\ndouble FADDEEVA_RE(erfcx)(double x)\n{\n  if (x >= 0) {\n    if (x > 50) { // continued-fraction expansion is faster\n      const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi)\n      if (x > 5e7) // 1-term expansion, important to avoid overflow\n        return ispi / x;\n      /* 5-term expansion (rely on compiler for CSE), simplified from:\n                ispi / (x+0.5/(x+1/(x+1.5/(x+2/x))))  */\n      return ispi*((x*x) * (x*x+4.5) + 2) / (x * ((x*x) * (x*x+5) + 3.75));\n    }\n    return erfcx_y100(400/(4+x));\n  }\n  else\n    return x < -26.7 ? HUGE_VAL : (x < -6.1 ? 2*exp(x*x) \n                                   : 2*exp(x*x) - erfcx_y100(400/(4-x)));\n}\n\n/////////////////////////////////////////////////////////////////////////\n/* Compute a scaled Dawson integral \n            FADDEEVA(w_im)(x) = 2*Dawson(x)/sqrt(pi)\n   equivalent to the imaginary part w(x) for real x.\n\n   Uses methods similar to the erfcx calculation above: continued fractions\n   for large |x|, a lookup table of Chebyshev polynomials for smaller |x|,\n   and finally a Taylor expansion for |x|<0.01.\n   \n   Steven G. Johnson, October 2012. */\n\n/* Given y100=100*y, where y = 1/(1+x) for x >= 0, compute w_im(x).\n\n   Uses a look-up table of 100 different Chebyshev polynomials\n   for y intervals [0,0.01], [0.01,0.02], ...., [0.99,1], generated\n   with the help of Maple and a little shell script.   This allows\n   the Chebyshev polynomials to be of significantly lower degree (about 1/30)\n   compared to fitting the whole [0,1] interval with a single polynomial. */\nstatic double w_im_y100(double y100, double x) {\n  switch (static_cast<int> (y100)) {\n    case 0: {\n      double t = 2*y100 - 1;\n      return 0.28351593328822191546e-2 + (0.28494783221378400759e-2 + (0.14427470563276734183e-4 + (0.10939723080231588129e-6 + (0.92474307943275042045e-9 + (0.89128907666450075245e-11 + 0.92974121935111111110e-13 * t) * t) * t) * t) * t) * t;\n    }\n    case 1: {\n      double t = 2*y100 - 3;\n      return 0.85927161243940350562e-2 + (0.29085312941641339862e-2 + (0.15106783707725582090e-4 + (0.11716709978531327367e-6 + (0.10197387816021040024e-8 + (0.10122678863073360769e-10 + 0.10917479678400000000e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 2: {\n      double t = 2*y100 - 5;\n      return 0.14471159831187703054e-1 + (0.29703978970263836210e-2 + (0.15835096760173030976e-4 + (0.12574803383199211596e-6 + (0.11278672159518415848e-8 + (0.11547462300333495797e-10 + 0.12894535335111111111e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 3: {\n      double t = 2*y100 - 7;\n      return 0.20476320420324610618e-1 + (0.30352843012898665856e-2 + (0.16617609387003727409e-4 + (0.13525429711163116103e-6 + (0.12515095552507169013e-8 + (0.13235687543603382345e-10 + 0.15326595042666666667e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 4: {\n      double t = 2*y100 - 9;\n      return 0.26614461952489004566e-1 + (0.31034189276234947088e-2 + (0.17460268109986214274e-4 + (0.14582130824485709573e-6 + (0.13935959083809746345e-8 + (0.15249438072998932900e-10 + 0.18344741882133333333e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 5: {\n      double t = 2*y100 - 11;\n      return 0.32892330248093586215e-1 + (0.31750557067975068584e-2 + (0.18369907582308672632e-4 + (0.15761063702089457882e-6 + (0.15577638230480894382e-8 + (0.17663868462699097951e-10 + (0.22126732680711111111e-12 + 0.30273474177737853668e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 6: {\n      double t = 2*y100 - 13;\n      return 0.39317207681134336024e-1 + (0.32504779701937539333e-2 + (0.19354426046513400534e-4 + (0.17081646971321290539e-6 + (0.17485733959327106250e-8 + (0.20593687304921961410e-10 + (0.26917401949155555556e-12 + 0.38562123837725712270e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 7: {\n      double t = 2*y100 - 15;\n      return 0.45896976511367738235e-1 + (0.33300031273110976165e-2 + (0.20423005398039037313e-4 + (0.18567412470376467303e-6 + (0.19718038363586588213e-8 + (0.24175006536781219807e-10 + (0.33059982791466666666e-12 + 0.49756574284439426165e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 8: {\n      double t = 2*y100 - 17;\n      return 0.52640192524848962855e-1 + (0.34139883358846720806e-2 + (0.21586390240603337337e-4 + (0.20247136501568904646e-6 + (0.22348696948197102935e-8 + (0.28597516301950162548e-10 + (0.41045502119111111110e-12 + 0.65151614515238361946e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 9: {\n      double t = 2*y100 - 19;\n      return 0.59556171228656770456e-1 + (0.35028374386648914444e-2 + (0.22857246150998562824e-4 + (0.22156372146525190679e-6 + (0.25474171590893813583e-8 + (0.34122390890697400584e-10 + (0.51593189879111111110e-12 + 0.86775076853908006938e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 10: {\n      double t = 2*y100 - 21;\n      return 0.66655089485108212551e-1 + (0.35970095381271285568e-2 + (0.24250626164318672928e-4 + (0.24339561521785040536e-6 + (0.29221990406518411415e-8 + (0.41117013527967776467e-10 + (0.65786450716444444445e-12 + 0.11791885745450623331e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 11: {\n      double t = 2*y100 - 23;\n      return 0.73948106345519174661e-1 + (0.36970297216569341748e-2 + (0.25784588137312868792e-4 + (0.26853012002366752770e-6 + (0.33763958861206729592e-8 + (0.50111549981376976397e-10 + (0.85313857496888888890e-12 + 0.16417079927706899860e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 12: {\n      double t = 2*y100 - 25;\n      return 0.81447508065002963203e-1 + (0.38035026606492705117e-2 + (0.27481027572231851896e-4 + (0.29769200731832331364e-6 + (0.39336816287457655076e-8 + (0.61895471132038157624e-10 + (0.11292303213511111111e-11 + 0.23558532213703884304e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 13: {\n      double t = 2*y100 - 27;\n      return 0.89166884027582716628e-1 + (0.39171301322438946014e-2 + (0.29366827260422311668e-4 + (0.33183204390350724895e-6 + (0.46276006281647330524e-8 + (0.77692631378169813324e-10 + (0.15335153258844444444e-11 + 0.35183103415916026911e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 14: {\n      double t = 2*y100 - 29;\n      return 0.97121342888032322019e-1 + (0.40387340353207909514e-2 + (0.31475490395950776930e-4 + (0.37222714227125135042e-6 + (0.55074373178613809996e-8 + (0.99509175283990337944e-10 + (0.21552645758222222222e-11 + 0.55728651431872687605e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 15: {\n      double t = 2*y100 - 31;\n      return 0.10532778218603311137e0 + (0.41692873614065380607e-2 + (0.33849549774889456984e-4 + (0.42064596193692630143e-6 + (0.66494579697622432987e-8 + (0.13094103581931802337e-9 + (0.31896187409777777778e-11 + 0.97271974184476560742e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 16: {\n      double t = 2*y100 - 33;\n      return 0.11380523107427108222e0 + (0.43099572287871821013e-2 + (0.36544324341565929930e-4 + (0.47965044028581857764e-6 + (0.81819034238463698796e-8 + (0.17934133239549647357e-9 + (0.50956666166186293627e-11 + (0.18850487318190638010e-12 + 0.79697813173519853340e-14 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 17: {\n      double t = 2*y100 - 35;\n      return 0.12257529703447467345e0 + (0.44621675710026986366e-2 + (0.39634304721292440285e-4 + (0.55321553769873381819e-6 + (0.10343619428848520870e-7 + (0.26033830170470368088e-9 + (0.87743837749108025357e-11 + (0.34427092430230063401e-12 + 0.10205506615709843189e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 18: {\n      double t = 2*y100 - 37;\n      return 0.13166276955656699478e0 + (0.46276970481783001803e-2 + (0.43225026380496399310e-4 + (0.64799164020016902656e-6 + (0.13580082794704641782e-7 + (0.39839800853954313927e-9 + (0.14431142411840000000e-10 + 0.42193457308830027541e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 19: {\n      double t = 2*y100 - 39;\n      return 0.14109647869803356475e0 + (0.48088424418545347758e-2 + (0.47474504753352150205e-4 + (0.77509866468724360352e-6 + (0.18536851570794291724e-7 + (0.60146623257887570439e-9 + (0.18533978397305276318e-10 + (0.41033845938901048380e-13 - 0.46160680279304825485e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 20: {\n      double t = 2*y100 - 41;\n      return 0.15091057940548936603e0 + (0.50086864672004685703e-2 + (0.52622482832192230762e-4 + (0.95034664722040355212e-6 + (0.25614261331144718769e-7 + (0.80183196716888606252e-9 + (0.12282524750534352272e-10 + (-0.10531774117332273617e-11 - 0.86157181395039646412e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 21: {\n      double t = 2*y100 - 43;\n      return 0.16114648116017010770e0 + (0.52314661581655369795e-2 + (0.59005534545908331315e-4 + (0.11885518333915387760e-5 + (0.33975801443239949256e-7 + (0.82111547144080388610e-9 + (-0.12357674017312854138e-10 + (-0.24355112256914479176e-11 - 0.75155506863572930844e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 22: {\n      double t = 2*y100 - 45;\n      return 0.17185551279680451144e0 + (0.54829002967599420860e-2 + (0.67013226658738082118e-4 + (0.14897400671425088807e-5 + (0.40690283917126153701e-7 + (0.44060872913473778318e-9 + (-0.52641873433280000000e-10 - 0.30940587864543343124e-11 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 23: {\n      double t = 2*y100 - 47;\n      return 0.18310194559815257381e0 + (0.57701559375966953174e-2 + (0.76948789401735193483e-4 + (0.18227569842290822512e-5 + (0.41092208344387212276e-7 + (-0.44009499965694442143e-9 + (-0.92195414685628803451e-10 + (-0.22657389705721753299e-11 + 0.10004784908106839254e-12 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 24: {\n      double t = 2*y100 - 49;\n      return 0.19496527191546630345e0 + (0.61010853144364724856e-2 + (0.88812881056342004864e-4 + (0.21180686746360261031e-5 + (0.30652145555130049203e-7 + (-0.16841328574105890409e-8 + (-0.11008129460612823934e-9 + (-0.12180794204544515779e-12 + 0.15703325634590334097e-12 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 25: {\n      double t = 2*y100 - 51;\n      return 0.20754006813966575720e0 + (0.64825787724922073908e-2 + (0.10209599627522311893e-3 + (0.22785233392557600468e-5 + (0.73495224449907568402e-8 + (-0.29442705974150112783e-8 + (-0.94082603434315016546e-10 + (0.23609990400179321267e-11 + 0.14141908654269023788e-12 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 26: {\n      double t = 2*y100 - 53;\n      return 0.22093185554845172146e0 + (0.69182878150187964499e-2 + (0.11568723331156335712e-3 + (0.22060577946323627739e-5 + (-0.26929730679360840096e-7 + (-0.38176506152362058013e-8 + (-0.47399503861054459243e-10 + (0.40953700187172127264e-11 + 0.69157730376118511127e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 27: {\n      double t = 2*y100 - 55;\n      return 0.23524827304057813918e0 + (0.74063350762008734520e-2 + (0.12796333874615790348e-3 + (0.18327267316171054273e-5 + (-0.66742910737957100098e-7 + (-0.40204740975496797870e-8 + (0.14515984139495745330e-10 + (0.44921608954536047975e-11 - 0.18583341338983776219e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 28: {\n      double t = 2*y100 - 57;\n      return 0.25058626331812744775e0 + (0.79377285151602061328e-2 + (0.13704268650417478346e-3 + (0.11427511739544695861e-5 + (-0.10485442447768377485e-6 + (-0.34850364756499369763e-8 + (0.72656453829502179208e-10 + (0.36195460197779299406e-11 - 0.84882136022200714710e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 29: {\n      double t = 2*y100 - 59;\n      return 0.26701724900280689785e0 + (0.84959936119625864274e-2 + (0.14112359443938883232e-3 + (0.17800427288596909634e-6 + (-0.13443492107643109071e-6 + (-0.23512456315677680293e-8 + (0.11245846264695936769e-9 + (0.19850501334649565404e-11 - 0.11284666134635050832e-12 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 30: {\n      double t = 2*y100 - 61;\n      return 0.28457293586253654144e0 + (0.90581563892650431899e-2 + (0.13880520331140646738e-3 + (-0.97262302362522896157e-6 + (-0.15077100040254187366e-6 + (-0.88574317464577116689e-9 + (0.12760311125637474581e-9 + (0.20155151018282695055e-12 - 0.10514169375181734921e-12 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 31: {\n      double t = 2*y100 - 63;\n      return 0.30323425595617385705e0 + (0.95968346790597422934e-2 + (0.12931067776725883939e-3 + (-0.21938741702795543986e-5 + (-0.15202888584907373963e-6 + (0.61788350541116331411e-9 + (0.11957835742791248256e-9 + (-0.12598179834007710908e-11 - 0.75151817129574614194e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 32: {\n      double t = 2*y100 - 65;\n      return 0.32292521181517384379e0 + (0.10082957727001199408e-1 + (0.11257589426154962226e-3 + (-0.33670890319327881129e-5 + (-0.13910529040004008158e-6 + (0.19170714373047512945e-8 + (0.94840222377720494290e-10 + (-0.21650018351795353201e-11 - 0.37875211678024922689e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 33: {\n      double t = 2*y100 - 67;\n      return 0.34351233557911753862e0 + (0.10488575435572745309e-1 + (0.89209444197248726614e-4 + (-0.43893459576483345364e-5 + (-0.11488595830450424419e-6 + (0.28599494117122464806e-8 + (0.61537542799857777779e-10 - 0.24935749227658002212e-11 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 34: {\n      double t = 2*y100 - 69;\n      return 0.36480946642143669093e0 + (0.10789304203431861366e-1 + (0.60357993745283076834e-4 + (-0.51855862174130669389e-5 + (-0.83291664087289801313e-7 + (0.33898011178582671546e-8 + (0.27082948188277716482e-10 + (-0.23603379397408694974e-11 + 0.19328087692252869842e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 35: {\n      double t = 2*y100 - 71;\n      return 0.38658679935694939199e0 + (0.10966119158288804999e-1 + (0.27521612041849561426e-4 + (-0.57132774537670953638e-5 + (-0.48404772799207914899e-7 + (0.35268354132474570493e-8 + (-0.32383477652514618094e-11 + (-0.19334202915190442501e-11 + 0.32333189861286460270e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 36: {\n      double t = 2*y100 - 73;\n      return 0.40858275583808707870e0 + (0.11006378016848466550e-1 + (-0.76396376685213286033e-5 + (-0.59609835484245791439e-5 + (-0.13834610033859313213e-7 + (0.33406952974861448790e-8 + (-0.26474915974296612559e-10 + (-0.13750229270354351983e-11 + 0.36169366979417390637e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 37: {\n      double t = 2*y100 - 75;\n      return 0.43051714914006682977e0 + (0.10904106549500816155e-1 + (-0.43477527256787216909e-4 + (-0.59429739547798343948e-5 + (0.17639200194091885949e-7 + (0.29235991689639918688e-8 + (-0.41718791216277812879e-10 + (-0.81023337739508049606e-12 + 0.33618915934461994428e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 38: {\n      double t = 2*y100 - 77;\n      return 0.45210428135559607406e0 + (0.10659670756384400554e-1 + (-0.78488639913256978087e-4 + (-0.56919860886214735936e-5 + (0.44181850467477733407e-7 + (0.23694306174312688151e-8 + (-0.49492621596685443247e-10 + (-0.31827275712126287222e-12 + 0.27494438742721623654e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 39: {\n      double t = 2*y100 - 79;\n      return 0.47306491195005224077e0 + (0.10279006119745977570e-1 + (-0.11140268171830478306e-3 + (-0.52518035247451432069e-5 + (0.64846898158889479518e-7 + (0.17603624837787337662e-8 + (-0.51129481592926104316e-10 + (0.62674584974141049511e-13 + 0.20055478560829935356e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 40: {\n      double t = 2*y100 - 81;\n      return 0.49313638965719857647e0 + (0.97725799114772017662e-2 + (-0.14122854267291533334e-3 + (-0.46707252568834951907e-5 + (0.79421347979319449524e-7 + (0.11603027184324708643e-8 + (-0.48269605844397175946e-10 + (0.32477251431748571219e-12 + 0.12831052634143527985e-13 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 41: {\n      double t = 2*y100 - 83;\n      return 0.51208057433416004042e0 + (0.91542422354009224951e-2 + (-0.16726530230228647275e-3 + (-0.39964621752527649409e-5 + (0.88232252903213171454e-7 + (0.61343113364949928501e-9 + (-0.42516755603130443051e-10 + (0.47910437172240209262e-12 + 0.66784341874437478953e-14 * t) * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 42: {\n      double t = 2*y100 - 85;\n      return 0.52968945458607484524e0 + (0.84400880445116786088e-2 + (-0.18908729783854258774e-3 + (-0.32725905467782951931e-5 + (0.91956190588652090659e-7 + (0.14593989152420122909e-9 + (-0.35239490687644444445e-10 + 0.54613829888448694898e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 43: {\n      double t = 2*y100 - 87;\n      return 0.54578857454330070965e0 + (0.76474155195880295311e-2 + (-0.20651230590808213884e-3 + (-0.25364339140543131706e-5 + (0.91455367999510681979e-7 + (-0.23061359005297528898e-9 + (-0.27512928625244444444e-10 + 0.54895806008493285579e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 44: {\n      double t = 2*y100 - 89;\n      return 0.56023851910298493910e0 + (0.67938321739997196804e-2 + (-0.21956066613331411760e-3 + (-0.18181127670443266395e-5 + (0.87650335075416845987e-7 + (-0.51548062050366615977e-9 + (-0.20068462174044444444e-10 + 0.50912654909758187264e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 45: {\n      double t = 2*y100 - 91;\n      return 0.57293478057455721150e0 + (0.58965321010394044087e-2 + (-0.22841145229276575597e-3 + (-0.11404605562013443659e-5 + (0.81430290992322326296e-7 + (-0.71512447242755357629e-9 + (-0.13372664928000000000e-10 + 0.44461498336689298148e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 46: {\n      double t = 2*y100 - 93;\n      return 0.58380635448407827360e0 + (0.49717469530842831182e-2 + (-0.23336001540009645365e-3 + (-0.51952064448608850822e-6 + (0.73596577815411080511e-7 + (-0.84020916763091566035e-9 + (-0.76700972702222222221e-11 + 0.36914462807972467044e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 47: {\n      double t = 2*y100 - 95;\n      return 0.59281340237769489597e0 + (0.40343592069379730568e-2 + (-0.23477963738658326185e-3 + (0.34615944987790224234e-7 + (0.64832803248395814574e-7 + (-0.90329163587627007971e-9 + (-0.30421940400000000000e-11 + 0.29237386653743536669e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 48: {\n      double t = 2*y100 - 97;\n      return 0.59994428743114271918e0 + (0.30976579788271744329e-2 + (-0.23308875765700082835e-3 + (0.51681681023846925160e-6 + (0.55694594264948268169e-7 + (-0.91719117313243464652e-9 + (0.53982743680000000000e-12 + 0.22050829296187771142e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 49: {\n      double t = 2*y100 - 99;\n      return 0.60521224471819875444e0 + (0.21732138012345456060e-2 + (-0.22872428969625997456e-3 + (0.92588959922653404233e-6 + (0.46612665806531930684e-7 + (-0.89393722514414153351e-9 + (0.31718550353777777778e-11 + 0.15705458816080549117e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 50: {\n      double t = 2*y100 - 101;\n      return 0.60865189969791123620e0 + (0.12708480848877451719e-2 + (-0.22212090111534847166e-3 + (0.12636236031532793467e-5 + (0.37904037100232937574e-7 + (-0.84417089968101223519e-9 + (0.49843180828444444445e-11 + 0.10355439441049048273e-12 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 51: {\n      double t = 2*y100 - 103;\n      return 0.61031580103499200191e0 + (0.39867436055861038223e-3 + (-0.21369573439579869291e-3 + (0.15339402129026183670e-5 + (0.29787479206646594442e-7 + (-0.77687792914228632974e-9 + (0.61192452741333333334e-11 + 0.60216691829459295780e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 52: {\n      double t = 2*y100 - 105;\n      return 0.61027109047879835868e0 + (-0.43680904508059878254e-3 + (-0.20383783788303894442e-3 + (0.17421743090883439959e-5 + (0.22400425572175715576e-7 + (-0.69934719320045128997e-9 + (0.67152759655111111110e-11 + 0.26419960042578359995e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 53: {\n      double t = 2*y100 - 107;\n      return 0.60859639489217430521e0 + (-0.12305921390962936873e-2 + (-0.19290150253894682629e-3 + (0.18944904654478310128e-5 + (0.15815530398618149110e-7 + (-0.61726850580964876070e-9 + 0.68987888999111111110e-11 * t) * t) * t) * t) * t) * t;\n    }\n    case 54: {\n      double t = 2*y100 - 109;\n      return 0.60537899426486075181e0 + (-0.19790062241395705751e-2 + (-0.18120271393047062253e-3 + (0.19974264162313241405e-5 + (0.10055795094298172492e-7 + (-0.53491997919318263593e-9 + (0.67794550295111111110e-11 - 0.17059208095741511603e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 55: {\n      double t = 2*y100 - 111;\n      return 0.60071229457904110537e0 + (-0.26795676776166354354e-2 + (-0.16901799553627508781e-3 + (0.20575498324332621581e-5 + (0.51077165074461745053e-8 + (-0.45536079828057221858e-9 + (0.64488005516444444445e-11 - 0.29311677573152766338e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 56: {\n      double t = 2*y100 - 113;\n      return 0.59469361520112714738e0 + (-0.33308208190600993470e-2 + (-0.15658501295912405679e-3 + (0.20812116912895417272e-5 + (0.93227468760614182021e-9 + (-0.38066673740116080415e-9 + (0.59806790359111111110e-11 - 0.36887077278950440597e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 57: {\n      double t = 2*y100 - 115;\n      return 0.58742228631775388268e0 + (-0.39321858196059227251e-2 + (-0.14410441141450122535e-3 + (0.20743790018404020716e-5 + (-0.25261903811221913762e-8 + (-0.31212416519526924318e-9 + (0.54328422462222222221e-11 - 0.40864152484979815972e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 58: {\n      double t = 2*y100 - 117;\n      return 0.57899804200033018447e0 + (-0.44838157005618913447e-2 + (-0.13174245966501437965e-3 + (0.20425306888294362674e-5 + (-0.53330296023875447782e-8 + (-0.25041289435539821014e-9 + (0.48490437205333333334e-11 - 0.42162206939169045177e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 59: {\n      double t = 2*y100 - 119;\n      return 0.56951968796931245974e0 + (-0.49864649488074868952e-2 + (-0.11963416583477567125e-3 + (0.19906021780991036425e-5 + (-0.75580140299436494248e-8 + (-0.19576060961919820491e-9 + (0.42613011928888888890e-11 - 0.41539443304115604377e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 60: {\n      double t = 2*y100 - 121;\n      return 0.55908401930063918964e0 + (-0.54413711036826877753e-2 + (-0.10788661102511914628e-3 + (0.19229663322982839331e-5 + (-0.92714731195118129616e-8 + (-0.14807038677197394186e-9 + (0.36920870298666666666e-11 - 0.39603726688419162617e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 61: {\n      double t = 2*y100 - 123;\n      return 0.54778496152925675315e0 + (-0.58501497933213396670e-2 + (-0.96582314317855227421e-4 + (0.18434405235069270228e-5 + (-0.10541580254317078711e-7 + (-0.10702303407788943498e-9 + (0.31563175582222222222e-11 - 0.36829748079110481422e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 62: {\n      double t = 2*y100 - 125;\n      return 0.53571290831682823999e0 + (-0.62147030670760791791e-2 + (-0.85782497917111760790e-4 + (0.17553116363443470478e-5 + (-0.11432547349815541084e-7 + (-0.72157091369041330520e-10 + (0.26630811607111111111e-11 - 0.33578660425893164084e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 63: {\n      double t = 2*y100 - 127;\n      return 0.52295422962048434978e0 + (-0.65371404367776320720e-2 + (-0.75530164941473343780e-4 + (0.16613725797181276790e-5 + (-0.12003521296598910761e-7 + (-0.42929753689181106171e-10 + (0.22170894940444444444e-11 - 0.30117697501065110505e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 64: {\n      double t = 2*y100 - 129;\n      return 0.50959092577577886140e0 + (-0.68197117603118591766e-2 + (-0.65852936198953623307e-4 + (0.15639654113906716939e-5 + (-0.12308007991056524902e-7 + (-0.18761997536910939570e-10 + (0.18198628922666666667e-11 - 0.26638355362285200932e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 65: {\n      double t = 2*y100 - 131;\n      return 0.49570040481823167970e0 + (-0.70647509397614398066e-2 + (-0.56765617728962588218e-4 + (0.14650274449141448497e-5 + (-0.12393681471984051132e-7 + (0.92904351801168955424e-12 + (0.14706755960177777778e-11 - 0.23272455351266325318e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 66: {\n      double t = 2*y100 - 133;\n      return 0.48135536250935238066e0 + (-0.72746293327402359783e-2 + (-0.48272489495730030780e-4 + (0.13661377309113939689e-5 + (-0.12302464447599382189e-7 + (0.16707760028737074907e-10 + (0.11672928324444444444e-11 - 0.20105801424709924499e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 67: {\n      double t = 2*y100 - 135;\n      return 0.46662374675511439448e0 + (-0.74517177649528487002e-2 + (-0.40369318744279128718e-4 + (0.12685621118898535407e-5 + (-0.12070791463315156250e-7 + (0.29105507892605823871e-10 + (0.90653314645333333334e-12 - 0.17189503312102982646e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 68: {\n      double t = 2*y100 - 137;\n      return 0.45156879030168268778e0 + (-0.75983560650033817497e-2 + (-0.33045110380705139759e-4 + (0.11732956732035040896e-5 + (-0.11729986947158201869e-7 + (0.38611905704166441308e-10 + (0.68468768305777777779e-12 - 0.14549134330396754575e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 69: {\n      double t = 2*y100 - 139;\n      return 0.43624909769330896904e0 + (-0.77168291040309554679e-2 + (-0.26283612321339907756e-4 + (0.10811018836893550820e-5 + (-0.11306707563739851552e-7 + (0.45670446788529607380e-10 + (0.49782492549333333334e-12 - 0.12191983967561779442e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 70: {\n      double t = 2*y100 - 141;\n      return 0.42071877443548481181e0 + (-0.78093484015052730097e-2 + (-0.20064596897224934705e-4 + (0.99254806680671890766e-6 + (-0.10823412088884741451e-7 + (0.50677203326904716247e-10 + (0.34200547594666666666e-12 - 0.10112698698356194618e-13 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 71: {\n      double t = 2*y100 - 143;\n      return 0.40502758809710844280e0 + (-0.78780384460872937555e-2 + (-0.14364940764532853112e-4 + (0.90803709228265217384e-6 + (-0.10298832847014466907e-7 + (0.53981671221969478551e-10 + (0.21342751381333333333e-12 - 0.82975901848387729274e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 72: {\n      double t = 2*y100 - 145;\n      return 0.38922115269731446690e0 + (-0.79249269708242064120e-2 + (-0.91595258799106970453e-5 + (0.82783535102217576495e-6 + (-0.97484311059617744437e-8 + (0.55889029041660225629e-10 + (0.10851981336888888889e-12 - 0.67278553237853459757e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 73: {\n      double t = 2*y100 - 147;\n      return 0.37334112915460307335e0 + (-0.79519385109223148791e-2 + (-0.44219833548840469752e-5 + (0.75209719038240314732e-6 + (-0.91848251458553190451e-8 + (0.56663266668051433844e-10 + (0.23995894257777777778e-13 - 0.53819475285389344313e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 74: {\n      double t = 2*y100 - 149;\n      return 0.35742543583374223085e0 + (-0.79608906571527956177e-2 + (-0.12530071050975781198e-6 + (0.68088605744900552505e-6 + (-0.86181844090844164075e-8 + (0.56530784203816176153e-10 + (-0.43120012248888888890e-13 - 0.42372603392496813810e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 75: {\n      double t = 2*y100 - 151;\n      return 0.34150846431979618536e0 + (-0.79534924968773806029e-2 + (0.37576885610891515813e-5 + (0.61419263633090524326e-6 + (-0.80565865409945960125e-8 + (0.55684175248749269411e-10 + (-0.95486860764444444445e-13 - 0.32712946432984510595e-14 * t) * t) * t) * t) * t) * t) * t;\n    }\n    case 76: {\n      double t = 2*y100 - 153;\n      return 0.32562129649136346824e0 + (-0.79313448067948884309e-2 + (0.72539159933545300034e-5 + (0.55195028297415503083e-6 + (-0.75063365335570475258e-8 + (0.54281686749699595941e-10 - 0.13545424295111111111e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 77: {\n      double t = 2*y100 - 155;\n      return 0.30979191977078391864e0 + (-0.78959416264207333695e-2 + (0.10389774377677210794e-4 + (0.49404804463196316464e-6 + (-0.69722488229411164685e-8 + (0.52469254655951393842e-10 - 0.16507860650666666667e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 78: {\n      double t = 2*y100 - 157;\n      return 0.29404543811214459904e0 + (-0.78486728990364155356e-2 + (0.13190885683106990459e-4 + (0.44034158861387909694e-6 + (-0.64578942561562616481e-8 + (0.50354306498006928984e-10 - 0.18614473550222222222e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 79: {\n      double t = 2*y100 - 159;\n      return 0.27840427686253660515e0 + (-0.77908279176252742013e-2 + (0.15681928798708548349e-4 + (0.39066226205099807573e-6 + (-0.59658144820660420814e-8 + (0.48030086420373141763e-10 - 0.20018995173333333333e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 80: {\n      double t = 2*y100 - 161;\n      return 0.26288838011163800908e0 + (-0.77235993576119469018e-2 + (0.17886516796198660969e-4 + (0.34482457073472497720e-6 + (-0.54977066551955420066e-8 + (0.45572749379147269213e-10 - 0.20852924954666666667e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 81: {\n      double t = 2*y100 - 163;\n      return 0.24751539954181029717e0 + (-0.76480877165290370975e-2 + (0.19827114835033977049e-4 + (0.30263228619976332110e-6 + (-0.50545814570120129947e-8 + (0.43043879374212005966e-10 - 0.21228012028444444444e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 82: {\n      double t = 2*y100 - 165;\n      return 0.23230087411688914593e0 + (-0.75653060136384041587e-2 + (0.21524991113020016415e-4 + (0.26388338542539382413e-6 + (-0.46368974069671446622e-8 + (0.40492715758206515307e-10 - 0.21238627815111111111e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 83: {\n      double t = 2*y100 - 167;\n      return 0.21725840021297341931e0 + (-0.74761846305979730439e-2 + (0.23000194404129495243e-4 + (0.22837400135642906796e-6 + (-0.42446743058417541277e-8 + (0.37958104071765923728e-10 - 0.20963978568888888889e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 84: {\n      double t = 2*y100 - 169;\n      return 0.20239979200788191491e0 + (-0.73815761980493466516e-2 + (0.24271552727631854013e-4 + (0.19590154043390012843e-6 + (-0.38775884642456551753e-8 + (0.35470192372162901168e-10 - 0.20470131678222222222e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 85: {\n      double t = 2*y100 - 171;\n      return 0.18773523211558098962e0 + (-0.72822604530339834448e-2 + (0.25356688567841293697e-4 + (0.16626710297744290016e-6 + (-0.35350521468015310830e-8 + (0.33051896213898864306e-10 - 0.19811844544000000000e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 86: {\n      double t = 2*y100 - 173;\n      return 0.17327341258479649442e0 + (-0.71789490089142761950e-2 + (0.26272046822383820476e-4 + (0.13927732375657362345e-6 + (-0.32162794266956859603e-8 + (0.30720156036105652035e-10 - 0.19034196304000000000e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 87: {\n      double t = 2*y100 - 175;\n      return 0.15902166648328672043e0 + (-0.70722899934245504034e-2 + (0.27032932310132226025e-4 + (0.11474573347816568279e-6 + (-0.29203404091754665063e-8 + (0.28487010262547971859e-10 - 0.18174029063111111111e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 88: {\n      double t = 2*y100 - 177;\n      return 0.14498609036610283865e0 + (-0.69628725220045029273e-2 + (0.27653554229160596221e-4 + (0.92493727167393036470e-7 + (-0.26462055548683583849e-8 + (0.26360506250989943739e-10 - 0.17261211260444444444e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 89: {\n      double t = 2*y100 - 179;\n      return 0.13117165798208050667e0 + (-0.68512309830281084723e-2 + (0.28147075431133863774e-4 + (0.72351212437979583441e-7 + (-0.23927816200314358570e-8 + (0.24345469651209833155e-10 - 0.16319736960000000000e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 90: {\n      double t = 2*y100 - 181;\n      return 0.11758232561160626306e0 + (-0.67378491192463392927e-2 + (0.28525664781722907847e-4 + (0.54156999310046790024e-7 + (-0.21589405340123827823e-8 + (0.22444150951727334619e-10 - 0.15368675584000000000e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 91: {\n      double t = 2*y100 - 183;\n      return 0.10422112945361673560e0 + (-0.66231638959845581564e-2 + (0.28800551216363918088e-4 + (0.37758983397952149613e-7 + (-0.19435423557038933431e-8 + (0.20656766125421362458e-10 - 0.14422990012444444444e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 92: {\n      double t = 2*y100 - 185;\n      return 0.91090275493541084785e-1 + (-0.65075691516115160062e-2 + (0.28982078385527224867e-4 + (0.23014165807643012781e-7 + (-0.17454532910249875958e-8 + (0.18981946442680092373e-10 - 0.13494234691555555556e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 93: {\n      double t = 2*y100 - 187;\n      return 0.78191222288771379358e-1 + (-0.63914190297303976434e-2 + (0.29079759021299682675e-4 + (0.97885458059415717014e-8 + (-0.15635596116134296819e-8 + (0.17417110744051331974e-10 - 0.12591151763555555556e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 94: {\n      double t = 2*y100 - 189;\n      return 0.65524757106147402224e-1 + (-0.62750311956082444159e-2 + (0.29102328354323449795e-4 + (-0.20430838882727954582e-8 + (-0.13967781903855367270e-8 + (0.15958771833747057569e-10 - 0.11720175765333333333e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 95: {\n      double t = 2*y100 - 191;\n      return 0.53091065838453612773e-1 + (-0.61586898417077043662e-2 + (0.29057796072960100710e-4 + (-0.12597414620517987536e-7 + (-0.12440642607426861943e-8 + (0.14602787128447932137e-10 - 0.10885859114666666667e-12 * t) * t) * t) * t) * t) * t;\n    }\n    case 96: {\n      double t = 2*y100 - 193;\n      return 0.40889797115352738582e-1 + (-0.60426484889413678200e-2 + (0.28953496450191694606e-4 + (-0.21982952021823718400e-7 + (-0.11044169117553026211e-8 + (0.13344562332430552171e-10 - 0.10091231402844444444e-12 * t) * t) * t) * t) * t) * t;\n    }\n  case 97: case 98:\n  case 99: case 100: { // use Taylor expansion for small x (|x| <= 0.0309...)\n      //  (2/sqrt(pi)) * (x - 2/3 x^3  + 4/15 x^5  - 8/105 x^7 + 16/945 x^9) \n      double x2 = x*x;\n      return x * (1.1283791670955125739\n                  - x2 * (0.75225277806367504925\n                          - x2 * (0.30090111122547001970\n                                  - x2 * (0.085971746064420005629\n                                          - x2 * 0.016931216931216931217))));\n    }\n  }\n  /* Since 0 <= y100 < 101, this is only reached if x is NaN,\n     in which case we should return NaN. */\n  return NaN;\n}\n\ndouble FADDEEVA(w_im)(double x)\n{\n  if (x >= 0) {\n    if (x > 45) { // continued-fraction expansion is faster\n      const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi)\n      if (x > 5e7) // 1-term expansion, important to avoid overflow\n        return ispi / x;\n      /* 5-term expansion (rely on compiler for CSE), simplified from:\n                ispi / (x-0.5/(x-1/(x-1.5/(x-2/x))))  */\n      return ispi*((x*x) * (x*x-4.5) + 2) / (x * ((x*x) * (x*x-5) + 3.75));\n    }\n    return w_im_y100(100/(1+x), x);\n  }\n  else { // = -FADDEEVA(w_im)(-x)\n    if (x < -45) { // continued-fraction expansion is faster\n      const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi)\n      if (x < -5e7) // 1-term expansion, important to avoid overflow\n        return ispi / x;\n      /* 5-term expansion (rely on compiler for CSE), simplified from:\n                ispi / (x-0.5/(x-1/(x-1.5/(x-2/x))))  */\n      return ispi*((x*x) * (x*x-4.5) + 2) / (x * ((x*x) * (x*x-5) + 3.75));\n    }\n    return -w_im_y100(100/(1-x), -x);\n  }\n}\n\n/////////////////////////////////////////////////////////////////////////\n\n// Compile with -DTEST_FADDEEVA to compile a little test program\n#if defined (TEST_FADDEEVA)\n\n#if defined (__cplusplus)\n#  include <cstdio>\n#else\n#  include <stdio.h>\n#endif\n\n// compute relative error |b-a|/|a|, handling case of NaN and Inf,\nstatic double relerr(double a, double b) {\n  if (isnan(a) || isnan(b) || isinf(a) || isinf(b)) {\n    if ((isnan(a) && !isnan(b)) || (!isnan(a) && isnan(b)) ||\n        (isinf(a) && !isinf(b)) || (!isinf(a) && isinf(b)) ||\n        (isinf(a) && isinf(b) && a*b < 0))\n      return Inf; // \"infinite\" error\n    return 0; // matching infinity/nan results counted as zero error\n  }\n  if (a == 0)\n    return b == 0 ? 0 : Inf;\n  else\n    return fabs((b-a) / a);\n}\n\nint main(void) {\n  double errmax_all = 0;\n  {\n    printf(\"############# w(z) tests #############\\n\");\n#define NTST 57 // define instead of const for C compatibility\n    cmplx z[NTST] = {\n      C(624.2,-0.26123),\n      C(-0.4,3.),\n      C(0.6,2.),\n      C(-1.,1.),\n      C(-1.,-9.),\n      C(-1.,9.),\n      C(-0.0000000234545,1.1234),\n      C(-3.,5.1),\n      C(-53,30.1),\n      C(0.0,0.12345),\n      C(11,1),\n      C(-22,-2),\n      C(9,-28),\n      C(21,-33),\n      C(1e5,1e5),\n      C(1e14,1e14),\n      C(-3001,-1000),\n      C(1e160,-1e159),\n      C(-6.01,0.01),\n      C(-0.7,-0.7),\n      C(2.611780000000000e+01, 4.540909610972489e+03),\n      C(0.8e7,0.3e7),\n      C(-20,-19.8081),\n      C(1e-16,-1.1e-16),\n      C(2.3e-8,1.3e-8),\n      C(6.3,-1e-13),\n      C(6.3,1e-20),\n      C(1e-20,6.3),\n      C(1e-20,16.3),\n      C(9,1e-300),\n      C(6.01,0.11),\n      C(8.01,1.01e-10),\n      C(28.01,1e-300),\n      C(10.01,1e-200),\n      C(10.01,-1e-200),\n      C(10.01,0.99e-10),\n      C(10.01,-0.99e-10),\n      C(1e-20,7.01),\n      C(-1,7.01),\n      C(5.99,7.01),\n      C(1,0),\n      C(55,0),\n      C(-0.1,0),\n      C(1e-20,0),\n      C(0,5e-14),\n      C(0,51),\n      C(Inf,0),\n      C(-Inf,0),\n      C(0,Inf),\n      C(0,-Inf),\n      C(Inf,Inf),\n      C(Inf,-Inf),\n      C(NaN,NaN),\n      C(NaN,0),\n      C(0,NaN),\n      C(NaN,Inf),\n      C(Inf,NaN)\n    };\n    cmplx w[NTST] = { /* w(z), computed with WolframAlpha\n                                   ... note that WolframAlpha is problematic\n                                   some of the above inputs, so I had to\n                                   use the continued-fraction expansion\n                                   in WolframAlpha in some cases, or switch\n                                   to Maple */\n      C(-3.78270245518980507452677445620103199303131110e-7,\n        0.000903861276433172057331093754199933411710053155),\n      C(0.1764906227004816847297495349730234591778719532788,\n        -0.02146550539468457616788719893991501311573031095617),\n      C(0.2410250715772692146133539023007113781272362309451,\n        0.06087579663428089745895459735240964093522265589350),\n      C(0.30474420525691259245713884106959496013413834051768,\n        -0.20821893820283162728743734725471561394145872072738),\n      C(7.317131068972378096865595229600561710140617977e34,\n        8.321873499714402777186848353320412813066170427e34),\n      C(0.0615698507236323685519612934241429530190806818395,\n        -0.00676005783716575013073036218018565206070072304635),\n      C(0.3960793007699874918961319170187598400134746631,\n        -5.593152259116644920546186222529802777409274656e-9),\n      C(0.08217199226739447943295069917990417630675021771804,\n        -0.04701291087643609891018366143118110965272615832184),\n      C(0.00457246000350281640952328010227885008541748668738,\n        -0.00804900791411691821818731763401840373998654987934),\n      C(0.8746342859608052666092782112565360755791467973338452,\n        0.),\n      C(0.00468190164965444174367477874864366058339647648741,\n        0.0510735563901306197993676329845149741675029197050),\n      C(-0.0023193175200187620902125853834909543869428763219,\n        -0.025460054739731556004902057663500272721780776336),\n      C(9.11463368405637174660562096516414499772662584e304,\n        3.97101807145263333769664875189354358563218932e305),\n      C(-4.4927207857715598976165541011143706155432296e281,\n        -2.8019591213423077494444700357168707775769028e281),\n      C(2.820947917809305132678577516325951485807107151e-6,\n        2.820947917668257736791638444590253942253354058e-6),\n      C(2.82094791773878143474039725787438662716372268e-15,\n        2.82094791773878143474039725773333923127678361e-15),\n      C(-0.0000563851289696244350147899376081488003110150498,\n        -0.000169211755126812174631861529808288295454992688),\n      C(-5.586035480670854326218608431294778077663867e-162,\n        5.586035480670854326218608431294778077663867e-161),\n      C(0.00016318325137140451888255634399123461580248456,\n        -0.095232456573009287370728788146686162555021209999),\n      C(0.69504753678406939989115375989939096800793577783885,\n        -1.8916411171103639136680830887017670616339912024317),\n      C(0.0001242418269653279656612334210746733213167234822,\n        7.145975826320186888508563111992099992116786763e-7),\n      C(2.318587329648353318615800865959225429377529825e-8,\n        6.182899545728857485721417893323317843200933380e-8),\n      C(-0.0133426877243506022053521927604277115767311800303,\n        -0.0148087097143220769493341484176979826888871576145),\n      C(1.00000000000000012412170838050638522857747934,\n        1.12837916709551279389615890312156495593616433e-16),\n      C(0.9999999853310704677583504063775310832036830015,\n        2.595272024519678881897196435157270184030360773e-8),\n      C(-1.4731421795638279504242963027196663601154624e-15,\n        0.090727659684127365236479098488823462473074709),\n      C(5.79246077884410284575834156425396800754409308e-18,\n        0.0907276596841273652364790985059772809093822374),\n      C(0.0884658993528521953466533278764830881245144368,\n        1.37088352495749125283269718778582613192166760e-22),\n      C(0.0345480845419190424370085249304184266813447878,\n        2.11161102895179044968099038990446187626075258e-23),\n      C(6.63967719958073440070225527042829242391918213e-36,\n        0.0630820900592582863713653132559743161572639353),\n      C(0.00179435233208702644891092397579091030658500743634,\n        0.0951983814805270647939647438459699953990788064762),\n      C(9.09760377102097999924241322094863528771095448e-13,\n        0.0709979210725138550986782242355007611074966717),\n      C(7.2049510279742166460047102593255688682910274423e-304,\n        0.0201552956479526953866611812593266285000876784321),\n      C(3.04543604652250734193622967873276113872279682e-44,\n        0.0566481651760675042930042117726713294607499165),\n      C(3.04543604652250734193622967873276113872279682e-44,\n        0.0566481651760675042930042117726713294607499165),\n      C(0.5659928732065273429286988428080855057102069081e-12,\n        0.056648165176067504292998527162143030538756683302),\n      C(-0.56599287320652734292869884280802459698927645e-12,\n        0.0566481651760675042929985271621430305387566833029),\n      C(0.0796884251721652215687859778119964009569455462,\n        1.11474461817561675017794941973556302717225126e-22),\n      C(0.07817195821247357458545539935996687005781943386550,\n        -0.01093913670103576690766705513142246633056714279654),\n      C(0.04670032980990449912809326141164730850466208439937,\n        0.03944038961933534137558064191650437353429669886545),\n      C(0.36787944117144232159552377016146086744581113103176,\n        0.60715770584139372911503823580074492116122092866515),\n      C(0,\n        0.010259688805536830986089913987516716056946786526145),\n      C(0.99004983374916805357390597718003655777207908125383,\n        -0.11208866436449538036721343053869621153527769495574),\n      C(0.99999999999999999999999999999999999999990000,\n        1.12837916709551257389615890312154517168802603e-20),\n      C(0.999999999999943581041645226871305192054749891144158,\n        0),\n      C(0.0110604154853277201542582159216317923453996211744250,\n        0),\n      C(0,0),\n      C(0,0),\n      C(0,0),\n      C(Inf,0),\n      C(0,0),\n      C(NaN,NaN),\n      C(NaN,NaN),\n      C(NaN,NaN),\n      C(NaN,0),\n      C(NaN,NaN),\n      C(NaN,NaN)\n    };\n    double errmax = 0;\n    for (int i = 0; i < NTST; ++i) {\n      cmplx fw = FADDEEVA(w)(z[i],0.);\n      double re_err = relerr(creal(w[i]), creal(fw));\n      double im_err = relerr(cimag(w[i]), cimag(fw));\n      printf(\"w(%g%+gi) = %g%+gi (vs. %g%+gi), re/im rel. err. = %0.2g/%0.2g)\\n\",\n             creal(z[i]),cimag(z[i]), creal(fw),cimag(fw), creal(w[i]),cimag(w[i]),\n             re_err, im_err);\n      if (re_err > errmax) errmax = re_err;\n      if (im_err > errmax) errmax = im_err;\n    }\n    if (errmax > 1e-13) {\n      printf(\"FAILURE -- relative error %g too large!\\n\", errmax);\n      return 1;\n    }\n    printf(\"SUCCESS (max relative error = %g)\\n\", errmax);\n    if (errmax > errmax_all) errmax_all = errmax;\n  }\n  {\n#undef NTST\n#define NTST 41 // define instead of const for C compatibility\n    cmplx z[NTST] = {\n      C(1,2),\n      C(-1,2),\n      C(1,-2),\n      C(-1,-2),\n      C(9,-28),\n      C(21,-33),\n      C(1e3,1e3),\n      C(-3001,-1000),\n      C(1e160,-1e159),\n      C(5.1e-3, 1e-8),\n      C(-4.9e-3, 4.95e-3),\n      C(4.9e-3, 0.5),\n      C(4.9e-4, -0.5e1),\n      C(-4.9e-5, -0.5e2),\n      C(5.1e-3, 0.5),\n      C(5.1e-4, -0.5e1),\n      C(-5.1e-5, -0.5e2),\n      C(1e-6,2e-6),\n      C(0,2e-6),\n      C(0,2),\n      C(0,20),\n      C(0,200),\n      C(Inf,0),\n      C(-Inf,0),\n      C(0,Inf),\n      C(0,-Inf),\n      C(Inf,Inf),\n      C(Inf,-Inf),\n      C(NaN,NaN),\n      C(NaN,0),\n      C(0,NaN),\n      C(NaN,Inf),\n      C(Inf,NaN),\n      C(1e-3,NaN),\n      C(7e-2,7e-2),\n      C(7e-2,-7e-4),\n      C(-9e-2,7e-4),\n      C(-9e-2,9e-2),\n      C(-7e-4,9e-2),\n      C(7e-2,0.9e-2),\n      C(7e-2,1.1e-2)\n    };\n    cmplx w[NTST] = { // erf(z[i]), evaluated with Maple\n      C(-0.5366435657785650339917955593141927494421,\n        -5.049143703447034669543036958614140565553),\n      C(0.5366435657785650339917955593141927494421,\n        -5.049143703447034669543036958614140565553),\n      C(-0.5366435657785650339917955593141927494421,\n        5.049143703447034669543036958614140565553),\n      C(0.5366435657785650339917955593141927494421,\n        5.049143703447034669543036958614140565553),\n      C(0.3359473673830576996788000505817956637777e304,\n        -0.1999896139679880888755589794455069208455e304),\n      C(0.3584459971462946066523939204836760283645e278,\n        0.3818954885257184373734213077678011282505e280),\n      C(0.9996020422657148639102150147542224526887,\n        0.00002801044116908227889681753993542916894856),\n      C(-1, 0),\n      C(1, 0),\n      C(0.005754683859034800134412990541076554934877,\n        0.1128349818335058741511924929801267822634e-7),\n      C(-0.005529149142341821193633460286828381876955,\n        0.005585388387864706679609092447916333443570),\n      C(0.007099365669981359632319829148438283865814,\n        0.6149347012854211635026981277569074001219),\n      C(0.3981176338702323417718189922039863062440e8,\n        -0.8298176341665249121085423917575122140650e10),\n      C(-Inf,\n        -Inf),\n      C(0.007389128308257135427153919483147229573895,\n        0.6149332524601658796226417164791221815139),\n      C(0.4143671923267934479245651547534414976991e8,\n        -0.8298168216818314211557046346850921446950e10),\n      C(-Inf,\n        -Inf),\n      C(0.1128379167099649964175513742247082845155e-5,\n        0.2256758334191777400570377193451519478895e-5),\n      C(0,\n        0.2256758334194034158904576117253481476197e-5),\n      C(0,\n        18.56480241457555259870429191324101719886),\n      C(0,\n        0.1474797539628786202447733153131835124599e173),\n      C(0,\n        Inf),\n      C(1,0),\n      C(-1,0),\n      C(0,Inf),\n      C(0,-Inf),\n      C(NaN,NaN),\n      C(NaN,NaN),\n      C(NaN,NaN),\n      C(NaN,0),\n      C(0,NaN),\n      C(NaN,NaN),\n      C(NaN,NaN),\n      C(NaN,NaN),\n      C(0.07924380404615782687930591956705225541145,\n        0.07872776218046681145537914954027729115247),\n      C(0.07885775828512276968931773651224684454495,\n        -0.0007860046704118224342390725280161272277506),\n      C(-0.1012806432747198859687963080684978759881,\n        0.0007834934747022035607566216654982820299469),\n      C(-0.1020998418798097910247132140051062512527,\n        0.1010030778892310851309082083238896270340),\n      C(-0.0007962891763147907785684591823889484764272,\n        0.1018289385936278171741809237435404896152),\n      C(0.07886408666470478681566329888615410479530,\n        0.01010604288780868961492224347707949372245),\n      C(0.07886723099940260286824654364807981336591,\n        0.01235199327873258197931147306290916629654)\n    };\n#define TST(f,isc)                                                      \\\n    printf(\"############# \" #f \"(z) tests #############\\n\");            \\\n    double errmax = 0;                                                  \\\n    for (int i = 0; i < NTST; ++i) {                                    \\\n      cmplx fw = FADDEEVA(f)(z[i],0.);                  \\\n      double re_err = relerr(creal(w[i]), creal(fw));                   \\\n      double im_err = relerr(cimag(w[i]), cimag(fw));                   \\\n      printf(#f \"(%g%+gi) = %g%+gi (vs. %g%+gi), re/im rel. err. = %0.2g/%0.2g)\\n\", \\\n             creal(z[i]),cimag(z[i]), creal(fw),cimag(fw), creal(w[i]),cimag(w[i]), \\\n             re_err, im_err);                                           \\\n      if (re_err > errmax) errmax = re_err;                             \\\n      if (im_err > errmax) errmax = im_err;                             \\\n    }                                                                   \\\n    if (errmax > 1e-13) {                                               \\\n      printf(\"FAILURE -- relative error %g too large!\\n\", errmax);      \\\n      return 1;                                                         \\\n    }                                                                   \\\n    printf(\"Checking \" #f \"(x) special case...\\n\");                     \\\n    for (int i = 0; i < 10000; ++i) {                                   \\\n      double x = pow(10., -300. + i * 600. / (10000 - 1));              \\\n      double re_err = relerr(FADDEEVA_RE(f)(x),                         \\\n                             creal(FADDEEVA(f)(C(x,x*isc),0.)));        \\\n      if (re_err > errmax) errmax = re_err;                             \\\n      re_err = relerr(FADDEEVA_RE(f)(-x),                               \\\n                      creal(FADDEEVA(f)(C(-x,x*isc),0.)));              \\\n      if (re_err > errmax) errmax = re_err;                             \\\n    }                                                                   \\\n    {                                                                   \\\n      double re_err = relerr(FADDEEVA_RE(f)(Inf),                       \\\n                             creal(FADDEEVA(f)(C(Inf,0.),0.))); \\\n      if (re_err > errmax) errmax = re_err;                             \\\n      re_err = relerr(FADDEEVA_RE(f)(-Inf),                             \\\n                      creal(FADDEEVA(f)(C(-Inf,0.),0.)));               \\\n      if (re_err > errmax) errmax = re_err;                             \\\n      re_err = relerr(FADDEEVA_RE(f)(NaN),                              \\\n                      creal(FADDEEVA(f)(C(NaN,0.),0.)));                \\\n      if (re_err > errmax) errmax = re_err;                             \\\n    }                                                                   \\\n    if (errmax > 1e-13) {                                               \\\n      printf(\"FAILURE -- relative error %g too large!\\n\", errmax);      \\\n      return 1;                                                         \\\n    }                                                                   \\\n    printf(\"SUCCESS (max relative error = %g)\\n\", errmax);              \\\n    if (errmax > errmax_all) errmax_all = errmax\n\n    TST(erf, 1e-20);\n  }\n  {\n    // since erfi just calls through to erf, just one test should\n    // be sufficient to make sure I didn't screw up the signs or something\n#undef NTST\n#define NTST 1 // define instead of const for C compatibility\n    cmplx z[NTST] = { C(1.234,0.5678) };\n    cmplx w[NTST] = { // erfi(z[i]), computed with Maple\n      C(1.081032284405373149432716643834106923212,\n        1.926775520840916645838949402886591180834)\n    };\n    TST(erfi, 0);\n  }\n  {\n    // since erfcx just calls through to w, just one test should\n    // be sufficient to make sure I didn't screw up the signs or something\n#undef NTST\n#define NTST 1 // define instead of const for C compatibility\n    cmplx z[NTST] = { C(1.234,0.5678) };\n    cmplx w[NTST] = { // erfcx(z[i]), computed with Maple\n      C(0.3382187479799972294747793561190487832579,\n        -0.1116077470811648467464927471872945833154)\n    };\n    TST(erfcx, 0);\n  }\n  {\n#undef NTST\n#define NTST 30 // define instead of const for C compatibility\n    cmplx z[NTST] = {\n      C(1,2),\n      C(-1,2),\n      C(1,-2),\n      C(-1,-2),\n      C(9,-28),\n      C(21,-33),\n      C(1e3,1e3),\n      C(-3001,-1000),\n      C(1e160,-1e159),\n      C(5.1e-3, 1e-8),\n      C(0,2e-6),\n      C(0,2),\n      C(0,20),\n      C(0,200),\n      C(2e-6,0),\n      C(2,0),\n      C(20,0),\n      C(200,0),\n      C(Inf,0),\n      C(-Inf,0),\n      C(0,Inf),\n      C(0,-Inf),\n      C(Inf,Inf),\n      C(Inf,-Inf),\n      C(NaN,NaN),\n      C(NaN,0),\n      C(0,NaN),\n      C(NaN,Inf),\n      C(Inf,NaN),\n      C(88,0)\n    };\n    cmplx w[NTST] = { // erfc(z[i]), evaluated with Maple\n      C(1.536643565778565033991795559314192749442,\n        5.049143703447034669543036958614140565553),\n      C(0.4633564342214349660082044406858072505579,\n        5.049143703447034669543036958614140565553),\n      C(1.536643565778565033991795559314192749442,\n        -5.049143703447034669543036958614140565553),\n      C(0.4633564342214349660082044406858072505579,\n        -5.049143703447034669543036958614140565553),\n      C(-0.3359473673830576996788000505817956637777e304,\n        0.1999896139679880888755589794455069208455e304),\n      C(-0.3584459971462946066523939204836760283645e278,\n        -0.3818954885257184373734213077678011282505e280),\n      C(0.0003979577342851360897849852457775473112748,\n        -0.00002801044116908227889681753993542916894856),\n      C(2, 0),\n      C(0, 0),\n      C(0.9942453161409651998655870094589234450651,\n        -0.1128349818335058741511924929801267822634e-7),\n      C(1,\n        -0.2256758334194034158904576117253481476197e-5),\n      C(1,\n        -18.56480241457555259870429191324101719886),\n      C(1,\n        -0.1474797539628786202447733153131835124599e173),\n      C(1, -Inf),\n      C(0.9999977432416658119838633199332831406314,\n        0),\n      C(0.004677734981047265837930743632747071389108,\n        0),\n      C(0.5395865611607900928934999167905345604088e-175,\n        0),\n      C(0, 0),\n      C(0, 0),\n      C(2, 0),\n      C(1, -Inf),\n      C(1, Inf),\n      C(NaN, NaN),\n      C(NaN, NaN),\n      C(NaN, NaN),\n      C(NaN, 0),\n      C(1, NaN),\n      C(NaN, NaN),\n      C(NaN, NaN),\n      C(0,0)\n    };\n    TST(erfc, 1e-20);\n  }\n  {\n#undef NTST\n#define NTST 48 // define instead of const for C compatibility\n    cmplx z[NTST] = {\n      C(2,1),\n      C(-2,1),\n      C(2,-1),\n      C(-2,-1),\n      C(-28,9),\n      C(33,-21),\n      C(1e3,1e3),\n      C(-1000,-3001),\n      C(1e-8, 5.1e-3),\n      C(4.95e-3, -4.9e-3),\n      C(5.1e-3, 5.1e-3),\n      C(0.5, 4.9e-3),\n      C(-0.5e1, 4.9e-4),\n      C(-0.5e2, -4.9e-5),\n      C(0.5e3, 4.9e-6),\n      C(0.5, 5.1e-3),\n      C(-0.5e1, 5.1e-4),\n      C(-0.5e2, -5.1e-5),\n      C(1e-6,2e-6),\n      C(2e-6,0),\n      C(2,0),\n      C(20,0),\n      C(200,0),\n      C(0,4.9e-3),\n      C(0,-5.1e-3),\n      C(0,2e-6),\n      C(0,-2),\n      C(0,20),\n      C(0,-200),\n      C(Inf,0),\n      C(-Inf,0),\n      C(0,Inf),\n      C(0,-Inf),\n      C(Inf,Inf),\n      C(Inf,-Inf),\n      C(NaN,NaN),\n      C(NaN,0),\n      C(0,NaN),\n      C(NaN,Inf),\n      C(Inf,NaN),\n      C(39, 6.4e-5),\n      C(41, 6.09e-5),\n      C(4.9e7, 5e-11),\n      C(5.1e7, 4.8e-11),\n      C(1e9, 2.4e-12),\n      C(1e11, 2.4e-14),\n      C(1e13, 2.4e-16),\n      C(1e300, 2.4e-303)\n    };\n    cmplx w[NTST] = { // dawson(z[i]), evaluated with Maple\n      C(0.1635394094345355614904345232875688576839,\n        -0.1531245755371229803585918112683241066853),\n      C(-0.1635394094345355614904345232875688576839,\n        -0.1531245755371229803585918112683241066853),\n      C(0.1635394094345355614904345232875688576839,\n        0.1531245755371229803585918112683241066853),\n      C(-0.1635394094345355614904345232875688576839,\n        0.1531245755371229803585918112683241066853),\n      C(-0.01619082256681596362895875232699626384420,\n        -0.005210224203359059109181555401330902819419),\n      C(0.01078377080978103125464543240346760257008,\n        0.006866888783433775382193630944275682670599),\n      C(-0.5808616819196736225612296471081337245459,\n        0.6688593905505562263387760667171706325749),\n      C(Inf,\n        -Inf),\n      C(0.1000052020902036118082966385855563526705e-7,\n        0.005100088434920073153418834680320146441685),\n      C(0.004950156837581592745389973960217444687524,\n        -0.004899838305155226382584756154100963570500),\n      C(0.005100176864319675957314822982399286703798,\n        0.005099823128319785355949825238269336481254),\n      C(0.4244534840871830045021143490355372016428,\n        0.002820278933186814021399602648373095266538),\n      C(-0.1021340733271046543881236523269967674156,\n        -0.00001045696456072005761498961861088944159916),\n      C(-0.01000200120119206748855061636187197886859,\n        0.9805885888237419500266621041508714123763e-8),\n      C(0.001000002000012000023960527532953151819595,\n        -0.9800058800588007290937355024646722133204e-11),\n      C(0.4244549085628511778373438768121222815752,\n        0.002935393851311701428647152230552122898291),\n      C(-0.1021340732357117208743299813648493928105,\n        -0.00001088377943049851799938998805451564893540),\n      C(-0.01000200120119126652710792390331206563616,\n        0.1020612612857282306892368985525393707486e-7),\n      C(0.1000000000007333333333344266666666664457e-5,\n        0.2000000000001333333333323199999999978819e-5),\n      C(0.1999999999994666666666675199999999990248e-5,\n        0),\n      C(0.3013403889237919660346644392864226952119,\n        0),\n      C(0.02503136792640367194699495234782353186858,\n        0),\n      C(0.002500031251171948248596912483183760683918,\n        0),\n      C(0,0.004900078433419939164774792850907128053308),\n      C(0,-0.005100088434920074173454208832365950009419),\n      C(0,0.2000000000005333333333341866666666676419e-5),\n      C(0,-48.16001211429122974789822893525016528191),\n      C(0,0.4627407029504443513654142715903005954668e174),\n      C(0,-Inf),\n      C(0,0),\n      C(-0,0),\n      C(0, Inf),\n      C(0, -Inf),\n      C(NaN, NaN),\n      C(NaN, NaN),\n      C(NaN, NaN),\n      C(NaN, 0),\n      C(0, NaN),\n      C(NaN, NaN),\n      C(NaN, NaN),\n      C(0.01282473148489433743567240624939698290584,\n        -0.2105957276516618621447832572909153498104e-7),\n      C(0.01219875253423634378984109995893708152885,\n        -0.1813040560401824664088425926165834355953e-7),\n      C(0.1020408163265306334945473399689037886997e-7,\n        -0.1041232819658476285651490827866174985330e-25),\n      C(0.9803921568627452865036825956835185367356e-8,\n        -0.9227220299884665067601095648451913375754e-26),\n      C(0.5000000000000000002500000000000000003750e-9,\n        -0.1200000000000000001800000188712838420241e-29),\n      C(5.00000000000000000000025000000000000000000003e-12,\n        -1.20000000000000000000018000000000000000000004e-36),\n      C(5.00000000000000000000000002500000000000000000e-14,\n        -1.20000000000000000000000001800000000000000000e-42),\n      C(5e-301, 0)\n    };\n    TST(Dawson, 1e-20);\n  }\n  printf(\"#####################################\\n\");\n  printf(\"SUCCESS (max relative error = %g)\\n\", errmax_all);\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/external/Faddeeva/Faddeeva.hh",
    "content": "/* Copyright (c) 2012 Massachusetts Institute of Technology\n * \n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n * \n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \n */\n\n/* Available at: http://ab-initio.mit.edu/Faddeeva\n\n   Header file for Faddeeva.cc; see that file for more information. */\n\n#ifndef FADDEEVA_HH\n#define FADDEEVA_HH 1\n\n#include <complex>\n\nnamespace Faddeeva {\n\n// compute w(z) = exp(-z^2) erfc(-iz) [ Faddeeva / scaled complex error func ]\nextern std::complex<double> w(std::complex<double> z,double relerr=0);\nextern double w_im(double x); // special-case code for Im[w(x)] of real x\n\n// Various functions that we can compute with the help of w(z)\n\n// compute erfcx(z) = exp(z^2) erfc(z)\nextern std::complex<double> erfcx(std::complex<double> z, double relerr=0);\nextern double erfcx(double x); // special case for real x\n\n// compute erf(z), the error function of complex arguments\nextern std::complex<double> erf(std::complex<double> z, double relerr=0);\nextern double erf(double x); // special case for real x\n\n// compute erfi(z) = -i erf(iz), the imaginary error function\nextern std::complex<double> erfi(std::complex<double> z, double relerr=0);\nextern double erfi(double x); // special case for real x\n\n// compute erfc(z) = 1 - erf(z), the complementary error function\nextern std::complex<double> erfc(std::complex<double> z, double relerr=0);\nextern double erfc(double x); // special case for real x\n\n// compute Dawson(z) = sqrt(pi)/2  *  exp(-z^2) * erfi(z)\nextern std::complex<double> Dawson(std::complex<double> z, double relerr=0);\nextern double Dawson(double x); // special case for real x\n\n} // namespace Faddeeva\n\n#endif // FADDEEVA_HH\n"
  },
  {
    "path": "liboctave/external/Faddeeva/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/Faddeeva.cc \\\n  %reldir%/Faddeeva.hh\n"
  },
  {
    "path": "liboctave/external/amos/README",
    "content": "The files in this directory have been modified from those found on\nnetlib by changing the following subroutine names\n\n  zabs --> xzabs\n  zexp --> xzexp\n  zlog --> xzlog\n  zsqrt --> xzsqrt\n\nto avoid conflicts with non-standard but commonly used Fortran\nintrinsic function names.\n\nJohn W. Eaton\njwe@octave.org\n\nWed Nov 11 17:29:50 1998\n\nMore files have been modified to recover Matlab compatibility for\nBessel functions. Now the output is always computed, independently\nfrom the magnitude of the input\n\n  cbesh.f\n  cbesi.f\n  cbesj.f\n  cbesk.f\n  zbesh.f\n  zbesi.f\n  zbesj.f\n  zbesk.f\n\nMichele Ginesi\nmichele.ginesi@gmail.com\n\nSat Jul 22 11:43:40 2017\n"
  },
  {
    "path": "liboctave/external/amos/cacai.f",
    "content": "      SUBROUTINE CACAI(Z, FNU, KODE, MR, N, Y, NZ, RL, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  CACAI\nC***REFER TO  CAIRY\nC\nC     CACAI APPLIES THE ANALYTIC CONTINUATION FORMULA\nC\nC         K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN)\nC                 MP=PI*MR*CMPLX(0.0,1.0)\nC\nC     TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT\nC     HALF Z PLANE FOR USE WITH CAIRY WHERE FNU=1/3 OR 2/3 AND N=1.\nC     CACAI IS THE SAME AS CACON WITH THE PARTS FOR LARGER ORDERS AND\nC     RECURRENCE REMOVED. A RECURSIVE CALL TO CACON CAN RESULT IF CACON\nC     IS CALLED FROM CAIRY.\nC\nC***ROUTINES CALLED  CASYI,CBKNU,CMLRI,CSERI,CS1S2,R1MACH\nC***END PROLOGUE  CACAI\n      COMPLEX CSGN, CSPN, C1, C2, Y, Z, ZN, CY\n      REAL ALIM, ARG, ASCLE, AZ, CPN, DFNU, ELIM, FMR, FNU, PI, RL,\n     * SGN, SPN, TOL, YY, R1MACH\n      INTEGER INU, IUF, KODE, MR, N, NN, NW, NZ\n      DIMENSION Y(N), CY(2)\n      DATA PI / 3.14159265358979324E0 /\n      NZ = 0\n      ZN = -Z\n      AZ = CABS(Z)\n      NN = N\n      DFNU = FNU + FLOAT(N-1)\n      IF (AZ.LE.2.0E0) GO TO 10\n      IF (AZ*AZ*0.25E0.GT.DFNU+1.0E0) GO TO 20\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     POWER SERIES FOR THE I FUNCTION\nC-----------------------------------------------------------------------\n      CALL CSERI(ZN, FNU, KODE, NN, Y, NW, TOL, ELIM, ALIM)\n      GO TO 40\n   20 CONTINUE\n      IF (AZ.LT.RL) GO TO 30\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION\nC-----------------------------------------------------------------------\n      CALL CASYI(ZN, FNU, KODE, NN, Y, NW, RL, TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 70\n      GO TO 40\n   30 CONTINUE\nC-----------------------------------------------------------------------\nC     MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION\nC-----------------------------------------------------------------------\n      CALL CMLRI(ZN, FNU, KODE, NN, Y, NW, TOL)\n      IF(NW.LT.0) GO TO 70\n   40 CONTINUE\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION\nC-----------------------------------------------------------------------\n      CALL CBKNU(ZN, FNU, KODE, 1, CY, NW, TOL, ELIM, ALIM)\n      IF (NW.NE.0) GO TO 70\n      FMR = FLOAT(MR)\n      SGN = -SIGN(PI,FMR)\n      CSGN = CMPLX(0.0E0,SGN)\n      IF (KODE.EQ.1) GO TO 50\n      YY = -AIMAG(ZN)\n      CPN = COS(YY)\n      SPN = SIN(YY)\n      CSGN = CSGN*CMPLX(CPN,SPN)\n   50 CONTINUE\nC-----------------------------------------------------------------------\nC     CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(FNU)\n      ARG = (FNU-FLOAT(INU))*SGN\n      CPN = COS(ARG)\n      SPN = SIN(ARG)\n      CSPN = CMPLX(CPN,SPN)\n      IF (MOD(INU,2).EQ.1) CSPN = -CSPN\n      C1 = CY(1)\n      C2 = Y(1)\n      IF (KODE.EQ.1) GO TO 60\n      IUF = 0\n      ASCLE = 1.0E+3*R1MACH(1)/TOL\n      CALL CS1S2(ZN, C1, C2, NW, ASCLE, ALIM, IUF)\n      NZ = NZ + NW\n   60 CONTINUE\n      Y(1) = CSPN*C1 + CSGN*C2\n      RETURN\n   70 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cacon.f",
    "content": "      SUBROUTINE CACON(Z, FNU, KODE, MR, N, Y, NZ, RL, FNUL, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  CACON\nC***REFER TO  CBESK,CBESH\nC\nC     CACON APPLIES THE ANALYTIC CONTINUATION FORMULA\nC\nC         K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN)\nC                 MP=PI*MR*CMPLX(0.0,1.0)\nC\nC     TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT\nC     HALF Z PLANE\nC\nC***ROUTINES CALLED  CBINU,CBKNU,CS1S2,R1MACH\nC***END PROLOGUE  CACON\n      COMPLEX CK, CONE, CS, CSCL, CSCR, CSGN, CSPN, CSS, CSR, C1, C2,\n     * RZ, SC1, SC2, ST, S1, S2, Y, Z, ZN, CY\n      REAL ALIM, ARG, ASCLE, AS2, BSCLE, BRY, CPN, C1I, C1M, C1R, ELIM,\n     * FMR, FNU, FNUL, PI, RL, SGN, SPN, TOL, YY, R1MACH\n      INTEGER I, INU, IUF, KFLAG, KODE, MR, N, NN, NW, NZ\n      DIMENSION Y(N), CY(2), CSS(3), CSR(3), BRY(3)\n      DATA PI / 3.14159265358979324E0 /\n      DATA CONE / (1.0E0,0.0E0) /\n      NZ = 0\n      ZN = -Z\n      NN = N\n      CALL CBINU(ZN, FNU, KODE, NN, Y, NW, RL, FNUL, TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 80\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION\nC-----------------------------------------------------------------------\n      NN = MIN0(2,N)\n      CALL CBKNU(ZN, FNU, KODE, NN, CY, NW, TOL, ELIM, ALIM)\n      IF (NW.NE.0) GO TO 80\n      S1 = CY(1)\n      FMR = FLOAT(MR)\n      SGN = -SIGN(PI,FMR)\n      CSGN = CMPLX(0.0E0,SGN)\n      IF (KODE.EQ.1) GO TO 10\n      YY = -AIMAG(ZN)\n      CPN = COS(YY)\n      SPN = SIN(YY)\n      CSGN = CSGN*CMPLX(CPN,SPN)\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(FNU)\n      ARG = (FNU-FLOAT(INU))*SGN\n      CPN = COS(ARG)\n      SPN = SIN(ARG)\n      CSPN = CMPLX(CPN,SPN)\n      IF (MOD(INU,2).EQ.1) CSPN = -CSPN\n      IUF = 0\n      C1 = S1\n      C2 = Y(1)\n      ASCLE = 1.0E+3*R1MACH(1)/TOL\n      IF (KODE.EQ.1) GO TO 20\n      CALL CS1S2(ZN, C1, C2, NW, ASCLE, ALIM, IUF)\n      NZ = NZ + NW\n      SC1 = C1\n   20 CONTINUE\n      Y(1) = CSPN*C1 + CSGN*C2\n      IF (N.EQ.1) RETURN\n      CSPN = -CSPN\n      S2 = CY(2)\n      C1 = S2\n      C2 = Y(2)\n      IF (KODE.EQ.1) GO TO 30\n      CALL CS1S2(ZN, C1, C2, NW, ASCLE, ALIM, IUF)\n      NZ = NZ + NW\n      SC2 = C1\n   30 CONTINUE\n      Y(2) = CSPN*C1 + CSGN*C2\n      IF (N.EQ.2) RETURN\n      CSPN = -CSPN\n      RZ = CMPLX(2.0E0,0.0E0)/ZN\n      CK = CMPLX(FNU+1.0E0,0.0E0)*RZ\nC-----------------------------------------------------------------------\nC     SCALE NEAR EXPONENT EXTREMES DURING RECURRENCE ON K FUNCTIONS\nC-----------------------------------------------------------------------\n      CSCL = CMPLX(1.0E0/TOL,0.0E0)\n      CSCR = CMPLX(TOL,0.0E0)\n      CSS(1) = CSCL\n      CSS(2) = CONE\n      CSS(3) = CSCR\n      CSR(1) = CSCR\n      CSR(2) = CONE\n      CSR(3) = CSCL\n      BRY(1) = ASCLE\n      BRY(2) = 1.0E0/ASCLE\n      BRY(3) = R1MACH(2)\n      AS2 = CABS(S2)\n      KFLAG = 2\n      IF (AS2.GT.BRY(1)) GO TO 40\n      KFLAG = 1\n      GO TO 50\n   40 CONTINUE\n      IF (AS2.LT.BRY(2)) GO TO 50\n      KFLAG = 3\n   50 CONTINUE\n      BSCLE = BRY(KFLAG)\n      S1 = S1*CSS(KFLAG)\n      S2 = S2*CSS(KFLAG)\n      CS = CSR(KFLAG)\n      DO 70 I=3,N\n        ST = S2\n        S2 = CK*S2 + S1\n        S1 = ST\n        C1 = S2*CS\n        ST = C1\n        C2 = Y(I)\n        IF (KODE.EQ.1) GO TO 60\n        IF (IUF.LT.0) GO TO 60\n        CALL CS1S2(ZN, C1, C2, NW, ASCLE, ALIM, IUF)\n        NZ = NZ + NW\n        SC1 = SC2\n        SC2 = C1\n        IF (IUF.NE.3) GO TO 60\n        IUF = -4\n        S1 = SC1*CSS(KFLAG)\n        S2 = SC2*CSS(KFLAG)\n        ST = SC2\n   60   CONTINUE\n        Y(I) = CSPN*C1 + CSGN*C2\n        CK = CK + RZ\n        CSPN = -CSPN\n        IF (KFLAG.GE.3) GO TO 70\n        C1R = REAL(C1)\n        C1I = AIMAG(C1)\n        C1R = ABS(C1R)\n        C1I = ABS(C1I)\n        C1M = AMAX1(C1R,C1I)\n        IF (C1M.LE.BSCLE) GO TO 70\n        KFLAG = KFLAG + 1\n        BSCLE = BRY(KFLAG)\n        S1 = S1*CS\n        S2 = ST\n        S1 = S1*CSS(KFLAG)\n        S2 = S2*CSS(KFLAG)\n        CS = CSR(KFLAG)\n   70 CONTINUE\n      RETURN\n   80 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cairy.f",
    "content": "      SUBROUTINE CAIRY(Z, ID, KODE, AI, NZ, IERR)\nC***BEGIN PROLOGUE  CAIRY\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z\nC***DESCRIPTION\nC\nC         ON KODE=1, CAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR\nC         ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON\nC         KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)*\nC         DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN\nC         -PI/3.LT.ARG(Z).LT.PI/3 AND THE EXPONENTIAL GROWTH IN\nC         PI/3.LT.ABS(ARG(Z)).LT.PI WHERE ZTA=(2/3)*Z*CSQRT(Z)\nC\nC         WHILE THE AIRY FUNCTIONS AI(Z) AND DAI(Z)/DZ ARE ANALYTIC IN\nC         THE WHOLE Z PLANE, THE CORRESPONDING SCALED FUNCTIONS DEFINED\nC         FOR KODE=2 HAVE A CUT ALONG THE NEGATIVE REAL AXIS.\nC         DEFINITIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF\nC         MATHEMATICAL FUNCTIONS (REF. 1).\nC\nC         INPUT\nC           Z      - Z=CMPLX(X,Y)\nC           ID     - ORDER OF DERIVATIVE, ID=0 OR ID=1\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             AI=AI(Z)                ON ID=0 OR\nC                             AI=DAI(Z)/DZ            ON ID=1\nC                        = 2  RETURNS\nC                             AI=CEXP(ZTA)*AI(Z)       ON ID=0 OR\nC                             AI=CEXP(ZTA)*DAI(Z)/DZ   ON ID=1 WHERE\nC                             ZTA=(2/3)*Z*CSQRT(Z)\nC\nC         OUTPUT\nC           AI     - COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND\nC                    KODE\nC           NZ     - UNDERFLOW INDICATOR\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ= 1   , AI=CMPLX(0.0,0.0) DUE TO UNDERFLOW IN\nC                              -PI/3.LT.ARG(Z).LT.PI/3 ON KODE=1\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, REAL(ZTA)\nC                            TOO LARGE WITH KODE=1.\nC                    IERR=3, CABS(Z) LARGE      - COMPUTATION COMPLETED\nC                            LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION\nC                            PRODUCE LESS THAN HALF OF MACHINE ACCURACY\nC                    IERR=4, CABS(Z) TOO LARGE  - NO COMPUTATION\nC                            COMPLETE LOSS OF ACCURACY BY ARGUMENT\nC                            REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC\nC***LONG DESCRIPTION\nC\nC         AI AND DAI ARE COMPUTED FOR CABS(Z).GT.1.0 FROM THE K BESSEL\nC         FUNCTIONS BY\nC\nC            AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA)\nC                           C=1.0/(PI*SQRT(3.0))\nC                           ZTA=(2/3)*Z**(3/2)\nC\nC         WITH THE POWER SERIES FOR CABS(Z).LE.1.0.\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES\nC         OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF\nC         THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR),\nC         THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR\nC         FLAG IERR=3 IS TRIGGERED WHERE UR=R1MACH(4)=UNIT ROUNDOFF.\nC         ALSO, IF THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN\nC         ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT\nC         FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE\nC         LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA\nC         MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2,\nC         AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE\nC         PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE\nC         PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT-\nC         ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG-\nC         NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN\nC         DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN\nC         EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES,\nC         NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE\nC         PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER\nC         MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  CACAI,CBKNU,I1MACH,R1MACH\nC***END PROLOGUE  CAIRY\n      COMPLEX AI, CONE, CSQ, CY, S1, S2, TRM1, TRM2, Z, ZTA, Z3\n      REAL AA, AD, AK, ALIM, ATRM, AZ, AZ3, BK, CK, COEF, C1, C2, DIG,\n     * DK, D1, D2, ELIM, FID, FNU, RL, R1M5, SFAC, TOL, TTH, ZI, ZR,\n     * Z3I, Z3R, R1MACH, BB, ALAZ\n      INTEGER ID, IERR, IFLAG, K, KODE, K1, K2, MR, NN, NZ, I1MACH\n      DIMENSION CY(1)\n      DATA TTH, C1, C2, COEF /6.66666666666666667E-01,\n     * 3.55028053887817240E-01,2.58819403792806799E-01,\n     * 1.83776298473930683E-01/\n      DATA  CONE / (1.0E0,0.0E0) /\nC***FIRST EXECUTABLE STATEMENT  CAIRY\n      IERR = 0\n      NZ=0\n      IF (ID.LT.0 .OR. ID.GT.1) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (IERR.NE.0) RETURN\n      AZ = CABS(Z)\n      TOL = AMAX1(R1MACH(4),1.0E-18)\n      FID = FLOAT(ID)\n      IF (AZ.GT.1.0E0) GO TO 60\nC-----------------------------------------------------------------------\nC     POWER SERIES FOR CABS(Z).LE.1.\nC-----------------------------------------------------------------------\n      S1 = CONE\n      S2 = CONE\n      IF (AZ.LT.TOL) GO TO 160\n      AA = AZ*AZ\n      IF (AA.LT.TOL/AZ) GO TO 40\n      TRM1 = CONE\n      TRM2 = CONE\n      ATRM = 1.0E0\n      Z3 = Z*Z*Z\n      AZ3 = AZ*AA\n      AK = 2.0E0 + FID\n      BK = 3.0E0 - FID - FID\n      CK = 4.0E0 - FID\n      DK = 3.0E0 + FID + FID\n      D1 = AK*DK\n      D2 = BK*CK\n      AD = AMIN1(D1,D2)\n      AK = 24.0E0 + 9.0E0*FID\n      BK = 30.0E0 - 9.0E0*FID\n      Z3R = REAL(Z3)\n      Z3I = AIMAG(Z3)\n      DO 30 K=1,25\n        TRM1 = TRM1*CMPLX(Z3R/D1,Z3I/D1)\n        S1 = S1 + TRM1\n        TRM2 = TRM2*CMPLX(Z3R/D2,Z3I/D2)\n        S2 = S2 + TRM2\n        ATRM = ATRM*AZ3/AD\n        D1 = D1 + AK\n        D2 = D2 + BK\n        AD = AMIN1(D1,D2)\n        IF (ATRM.LT.TOL*AD) GO TO 40\n        AK = AK + 18.0E0\n        BK = BK + 18.0E0\n   30 CONTINUE\n   40 CONTINUE\n      IF (ID.EQ.1) GO TO 50\n      AI = S1*CMPLX(C1,0.0E0) - Z*S2*CMPLX(C2,0.0E0)\n      IF (KODE.EQ.1) RETURN\n      ZTA = Z*CSQRT(Z)*CMPLX(TTH,0.0E0)\n      AI = AI*CEXP(ZTA)\n      RETURN\n   50 CONTINUE\n      AI = -S2*CMPLX(C2,0.0E0)\n      IF (AZ.GT.TOL) AI = AI + Z*Z*S1*CMPLX(C1/(1.0E0+FID),0.0E0)\n      IF (KODE.EQ.1) RETURN\n      ZTA = Z*CSQRT(Z)*CMPLX(TTH,0.0E0)\n      AI = AI*CEXP(ZTA)\n      RETURN\nC-----------------------------------------------------------------------\nC     CASE FOR CABS(Z).GT.1.0\nC-----------------------------------------------------------------------\n   60 CONTINUE\n      FNU = (1.0E0+FID)/3.0E0\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC-----------------------------------------------------------------------\n      K1 = I1MACH(12)\n      K2 = I1MACH(13)\n      R1M5 = R1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303E0*(FLOAT(K)*R1M5-3.0E0)\n      K1 = I1MACH(11) - 1\n      AA = R1M5*FLOAT(K1)\n      DIG = AMIN1(AA,18.0E0)\n      AA = AA*2.303E0\n      ALIM = ELIM + AMAX1(-AA,-41.45E0)\n      RL = 1.2E0*DIG + 3.0E0\n      ALAZ=ALOG(AZ)\nC-----------------------------------------------------------------------\nC     TEST FOR RANGE\nC-----------------------------------------------------------------------\n      AA=0.5E0/TOL\n      BB=FLOAT(I1MACH(9))*0.5E0\n      AA=AMIN1(AA,BB)\n      AA=AA**TTH\n      IF (AZ.GT.AA) GO TO 260\n      AA=SQRT(AA)\n      IF (AZ.GT.AA) IERR=3\n      CSQ=CSQRT(Z)\n      ZTA=Z*CSQ*CMPLX(TTH,0.0E0)\nC-----------------------------------------------------------------------\nC     RE(ZTA).LE.0 WHEN RE(Z).LT.0, ESPECIALLY WHEN IM(Z) IS SMALL\nC-----------------------------------------------------------------------\n      IFLAG = 0\n      SFAC = 1.0E0\n      ZI = AIMAG(Z)\n      ZR = REAL(Z)\n      AK = AIMAG(ZTA)\n      IF (ZR.GE.0.0E0) GO TO 70\n      BK = REAL(ZTA)\n      CK = -ABS(BK)\n      ZTA = CMPLX(CK,AK)\n   70 CONTINUE\n      IF (ZI.NE.0.0E0) GO TO 80\n      IF (ZR.GT.0.0E0) GO TO 80\n      ZTA = CMPLX(0.0E0,AK)\n   80 CONTINUE\n      AA = REAL(ZTA)\n      IF (AA.GE.0.0E0 .AND. ZR.GT.0.0E0) GO TO 100\n      IF (KODE.EQ.2) GO TO 90\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST\nC-----------------------------------------------------------------------\n      IF (AA.GT.(-ALIM)) GO TO 90\n      AA = -AA + 0.25E0*ALAZ\n      IFLAG = 1\n      SFAC = TOL\n      IF (AA.GT.ELIM) GO TO 240\n   90 CONTINUE\nC-----------------------------------------------------------------------\nC     CBKNU AND CACAI RETURN EXP(ZTA)*K(FNU,ZTA) ON KODE=2\nC-----------------------------------------------------------------------\n      MR = 1\n      IF (ZI.LT.0.0E0) MR = -1\n      CALL CACAI(ZTA, FNU, KODE, MR, 1, CY, NN, RL, TOL, ELIM, ALIM)\n      IF (NN.LT.0) GO TO 250\n      NZ = NZ + NN\n      GO TO 120\n  100 CONTINUE\n      IF (KODE.EQ.2) GO TO 110\nC-----------------------------------------------------------------------\nC     UNDERFLOW TEST\nC-----------------------------------------------------------------------\n      IF (AA.LT.ALIM) GO TO 110\n      AA = -AA - 0.25E0*ALAZ\n      IFLAG = 2\n      SFAC = 1.0E0/TOL\n      IF (AA.LT.(-ELIM)) GO TO 180\n  110 CONTINUE\n      CALL CBKNU(ZTA, FNU, KODE, 1, CY, NZ, TOL, ELIM, ALIM)\n  120 CONTINUE\n      S1 = CY(1)*CMPLX(COEF,0.0E0)\n      IF (IFLAG.NE.0) GO TO 140\n      IF (ID.EQ.1) GO TO 130\n      AI = CSQ*S1\n      RETURN\n  130 AI = -Z*S1\n      RETURN\n  140 CONTINUE\n      S1 = S1*CMPLX(SFAC,0.0E0)\n      IF (ID.EQ.1) GO TO 150\n      S1 = S1*CSQ\n      AI = S1*CMPLX(1.0E0/SFAC,0.0E0)\n      RETURN\n  150 CONTINUE\n      S1 = -S1*Z\n      AI = S1*CMPLX(1.0E0/SFAC,0.0E0)\n      RETURN\n  160 CONTINUE\n      AA = 1.0E+3*R1MACH(1)\n      S1 = CMPLX(0.0E0,0.0E0)\n      IF (ID.EQ.1) GO TO 170\n      IF (AZ.GT.AA) S1 = CMPLX(C2,0.0E0)*Z\n      AI = CMPLX(C1,0.0E0) - S1\n      RETURN\n  170 CONTINUE\n      AI = -CMPLX(C2,0.0E0)\n      AA = SQRT(AA)\n      IF (AZ.GT.AA) S1 = Z*Z*CMPLX(0.5E0,0.0E0)\n      AI = AI + S1*CMPLX(C1,0.0E0)\n      RETURN\n  180 CONTINUE\n      NZ = 1\n      AI = CMPLX(0.0E0,0.0E0)\n      RETURN\n  240 CONTINUE\n      NZ = 0\n      IERR=2\n      RETURN\n  250 CONTINUE\n      IF(NN.EQ.(-1)) GO TO 240\n      NZ=0\n      IERR=5\n      RETURN\n  260 CONTINUE\n      IERR=4\n      NZ=0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/casyi.f",
    "content": "      SUBROUTINE CASYI(Z, FNU, KODE, N, Y, NZ, RL, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  CASYI\nC***REFER TO  CBESI,CBESK\nC\nC     CASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z).GE.0.0 BY\nC     MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE\nC     REGION CABS(Z).GT.MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL RETURN.\nC     NZ.LT.0 INDICATES AN OVERFLOW ON KODE=1.\nC\nC***ROUTINES CALLED  R1MACH\nC***END PROLOGUE  CASYI\n      COMPLEX AK1, CK, CONE, CS1, CS2, CZ, CZERO, DK, EZ, P1, RZ, S2,\n     * Y, Z\n      REAL AA, ACZ, AEZ, AK, ALIM, ARG, ARM, ATOL, AZ, BB, BK, DFNU,\n     * DNU2, ELIM, FDN, FNU, PI, RL, RTPI, RTR1, S, SGN, SQK, TOL, X,\n     * YY, R1MACH\n      INTEGER I, IB, IL, INU, J, JL, K, KODE, KODED, M, N, NN, NZ\n      DIMENSION Y(N)\n      DATA PI, RTPI  /3.14159265358979324E0 , 0.159154943091895336E0 /\n      DATA CZERO, CONE / (0.0E0,0.0E0), (1.0E0,0.0E0) /\nC\n      NZ = 0\n      AZ = CABS(Z)\n      X = REAL(Z)\n      ARM = 1.0E+3*R1MACH(1)\n      RTR1 = SQRT(ARM)\n      IL = MIN0(2,N)\n      DFNU = FNU + FLOAT(N-IL)\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST\nC-----------------------------------------------------------------------\n      AK1 = CMPLX(RTPI,0.0E0)/Z\n      AK1 = CSQRT(AK1)\n      CZ = Z\n      IF (KODE.EQ.2) CZ = Z - CMPLX(X,0.0E0)\n      ACZ = REAL(CZ)\n      IF (ABS(ACZ).GT.ELIM) GO TO 80\n      DNU2 = DFNU + DFNU\n      KODED = 1\n      IF ((ABS(ACZ).GT.ALIM) .AND. (N.GT.2)) GO TO 10\n      KODED = 0\n      AK1 = AK1*CEXP(CZ)\n   10 CONTINUE\n      FDN = 0.0E0\n      IF (DNU2.GT.RTR1) FDN = DNU2*DNU2\n      EZ = Z*CMPLX(8.0E0,0.0E0)\nC-----------------------------------------------------------------------\nC     WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE\nC     FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE\nC     EXPANSION FOR THE IMAGINARY PART.\nC-----------------------------------------------------------------------\n      AEZ = 8.0E0*AZ\n      S = TOL/AEZ\n      JL = INT(RL+RL) + 2\n      YY = AIMAG(Z)\n      P1 = CZERO\n      IF (YY.EQ.0.0E0) GO TO 20\nC-----------------------------------------------------------------------\nC     CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF\nC     SIGNIFICANCE WHEN FNU OR N IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(FNU)\n      ARG = (FNU-FLOAT(INU))*PI\n      INU = INU + N - IL\n      AK = -SIN(ARG)\n      BK = COS(ARG)\n      IF (YY.LT.0.0E0) BK = -BK\n      P1 = CMPLX(AK,BK)\n      IF (MOD(INU,2).EQ.1) P1 = -P1\n   20 CONTINUE\n      DO 50 K=1,IL\n        SQK = FDN - 1.0E0\n        ATOL = S*ABS(SQK)\n        SGN = 1.0E0\n        CS1 = CONE\n        CS2 = CONE\n        CK = CONE\n        AK = 0.0E0\n        AA = 1.0E0\n        BB = AEZ\n        DK = EZ\n        DO 30 J=1,JL\n          CK = CK*CMPLX(SQK,0.0E0)/DK\n          CS2 = CS2 + CK\n          SGN = -SGN\n          CS1 = CS1 + CK*CMPLX(SGN,0.0E0)\n          DK = DK + EZ\n          AA = AA*ABS(SQK)/BB\n          BB = BB + AEZ\n          AK = AK + 8.0E0\n          SQK = SQK - AK\n          IF (AA.LE.ATOL) GO TO 40\n   30   CONTINUE\n        GO TO 90\n   40   CONTINUE\n        S2 = CS1\n        IF (X+X.LT.ELIM) S2 = S2 + P1*CS2*CEXP(-Z-Z)\n        FDN = FDN + 8.0E0*DFNU + 4.0E0\n        P1 = -P1\n        M = N - IL + K\n        Y(M) = S2*AK1\n   50 CONTINUE\n      IF (N.LE.2) RETURN\n      NN = N\n      K = NN - 2\n      AK = FLOAT(K)\n      RZ = (CONE+CONE)/Z\n      IB = 3\n      DO 60 I=IB,NN\n        Y(K) = CMPLX(AK+FNU,0.0E0)*RZ*Y(K+1) + Y(K+2)\n        AK = AK - 1.0E0\n        K = K - 1\n   60 CONTINUE\n      IF (KODED.EQ.0) RETURN\n      CK = CEXP(CZ)\n      DO 70 I=1,NN\n        Y(I) = Y(I)*CK\n   70 CONTINUE\n      RETURN\n   80 CONTINUE\n      NZ = -1\n      RETURN\n   90 CONTINUE\n      NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbesh.f",
    "content": "      SUBROUTINE CBESH(Z, FNU, KODE, M, N, CY, NZ, IERR)\nC***BEGIN PROLOGUE  CBESH\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  H-BESSEL FUNCTIONS,BESSEL FUNCTIONS OF COMPLEX ARGUMENT,\nC             BESSEL FUNCTIONS OF THIRD KIND,HANKEL FUNCTIONS\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE THE H-BESSEL FUNCTIONS OF A COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC         ON KODE=1, CBESH COMPUTES AN N MEMBER SEQUENCE OF COMPLEX\nC         HANKEL (BESSEL) FUNCTIONS CY(J)=H(M,FNU+J-1,Z) FOR KINDS M=1\nC         OR 2, REAL, NONNEGATIVE ORDERS FNU+J-1, J=1,...,N, AND COMPLEX\nC         Z.NE.CMPLX(0.0E0,0.0E0) IN THE CUT PLANE -PI.LT.ARG(Z).LE.PI.\nC         ON KODE=2, CBESH COMPUTES THE SCALED HANKEL FUNCTIONS\nC\nC         CY(I)=H(M,FNU+J-1,Z)*EXP(-MM*Z*I)       MM=3-2M,      I**2=-1.\nC\nC         WHICH REMOVES THE EXPONENTIAL BEHAVIOR IN BOTH THE UPPER\nC         AND LOWER HALF PLANES. DEFINITIONS AND NOTATION ARE FOUND IN\nC         THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS (REF. 1).\nC\nC         INPUT\nC           Z      - Z=CMPLX(X,Y), Z.NE.CMPLX(0.,0.),-PI.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL H FUNCTION, FNU.GE.0.0E0\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(J)=H(M,FNU+J-1,Z),      J=1,...,N\nC                        = 2  RETURNS\nC                             CY(J)=H(M,FNU+J-1,Z)*EXP(-I*Z*(3-2M))\nC                                  J=1,...,N  ,  I**2=-1\nC           M      - KIND OF HANKEL FUNCTION, M=1 OR 2\nC           N      - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1\nC\nC         OUTPUT\nC           CY     - A COMPLEX VECTOR WHOSE FIRST N COMPONENTS CONTAIN\nC                    VALUES FOR THE SEQUENCE\nC                    CY(J)=H(M,FNU+J-1,Z)  OR\nC                    CY(J)=H(M,FNU+J-1,Z)*EXP(-I*Z*(3-2M))  J=1,...,N\nC                    DEPENDING ON KODE, I**2=-1.\nC           NZ     - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW,\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ.GT.0 , FIRST NZ COMPONENTS OF CY SET TO ZERO\nC                              DUE TO UNDERFLOW, CY(J)=CMPLX(0.0,0.0)\nC                              J=1,...,NZ WHEN Y.GT.0.0 AND M=1 OR\nC                              Y.LT.0.0 AND M=2. FOR THE COMPLMENTARY\nC                              HALF PLANES, NZ STATES ONLY THE NUMBER\nC                              OF UNDERFLOWS.\nC           IERR    -ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, FNU+N-1 TOO\nC                            LARGE OR CABS(Z) TOO SMALL OR BOTH\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         THE COMPUTATION IS CARRIED OUT BY THE RELATION\nC\nC         H(M,FNU,Z)=(1/MP)*EXP(-MP*FNU)*K(FNU,Z*EXP(-MP))\nC             MP=MM*HPI*I,  MM=3-2*M,  HPI=PI/2,  I**2=-1\nC\nC         FOR M=1 OR 2 WHERE THE K BESSEL FUNCTION IS COMPUTED FOR THE\nC         RIGHT HALF PLANE RE(Z).GE.0.0. THE K FUNCTION IS CONTINUED\nC         TO THE LEFT HALF PLANE BY THE RELATION\nC\nC         K(FNU,Z*EXP(MP)) = EXP(-MP*FNU)*K(FNU,Z)-MP*I(FNU,Z)\nC         MP=MR*PI*I, MR=+1 OR -1, RE(Z).GT.0, I**2=-1\nC\nC         WHERE I(FNU,Z) IS THE I BESSEL FUNCTION.\nC\nC         EXPONENTIAL DECAY OF H(M,FNU,Z) OCCURS IN THE UPPER HALF Z\nC         PLANE FOR M=1 AND THE LOWER HALF Z PLANE FOR M=2.  EXPONENTIAL\nC         GROWTH OCCURS IN THE COMPLEMENTARY HALF PLANES.  SCALING\nC         BY EXP(-MM*Z*I) REMOVES THE EXPONENTIAL BEHAVIOR IN THE\nC         WHOLE Z PLANE FOR Z TO INFINITY.\nC\nC         FOR NEGATIVE ORDERS,THE FORMULAE\nC\nC               H(1,-FNU,Z) = H(1,FNU,Z)*CEXP( PI*FNU*I)\nC               H(2,-FNU,Z) = H(2,FNU,Z)*CEXP(-PI*FNU*I)\nC                         I**2=-1\nC\nC         CAN BE USED.\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=R1MACH(4)=UNIT ROUNDOFF. ALSO\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  CACON,CBKNU,CBUNK,CUOIK,I1MACH,R1MACH\nC***END PROLOGUE  CBESH\nC\n      COMPLEX CY, Z, ZN, ZT, CSGN\n      REAL AA, ALIM, ALN, ARG, AZ, CPN, DIG, ELIM, FMM, FN, FNU, FNUL,\n     * HPI, RHPI, RL, R1M5, SGN, SPN, TOL, UFL, XN, XX, YN, YY, R1MACH,\n     * BB, ASCLE, RTOL, ATOL\n      INTEGER I, IERR, INU, INUH, IR, K, KODE, K1, K2, M,\n     * MM, MR, N, NN, NUF, NW, NZ, I1MACH\n      DIMENSION CY(N)\nC\n      DATA HPI /1.57079632679489662E0/\nC\nC***FIRST EXECUTABLE STATEMENT  CBESH\n      NZ=0\n      XX = REAL(Z)\n      YY = AIMAG(Z)\n      IERR = 0\n      IF (XX.EQ.0.0E0 .AND. YY.EQ.0.0E0) IERR=1\n      IF (FNU.LT.0.0E0) IERR=1\n      IF (M.LT.1 .OR. M.GT.2) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\n      NN = N\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU\nC-----------------------------------------------------------------------\n      TOL = AMAX1(R1MACH(4),1.0E-18)\n      K1 = I1MACH(12)\n      K2 = I1MACH(13)\n      R1M5 = R1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303E0*(FLOAT(K)*R1M5-3.0E0)\n      K1 = I1MACH(11) - 1\n      AA = R1M5*FLOAT(K1)\n      DIG = AMIN1(AA,18.0E0)\n      AA = AA*2.303E0\n      ALIM = ELIM + AMAX1(-AA,-41.45E0)\n      FNUL = 10.0E0 + 6.0E0*(DIG-3.0E0)\n      RL = 1.2E0*DIG + 3.0E0\n      FN = FNU + FLOAT(NN-1)\n      MM = 3 - M - M\n      FMM = FLOAT(MM)\n      ZN = Z*CMPLX(0.0E0,-FMM)\n      XN = REAL(ZN)\n      YN = AIMAG(ZN)\n      AZ = CABS(Z)\nC-----------------------------------------------------------------------\nC     TEST FOR RANGE\nC-----------------------------------------------------------------------\n      AA = 0.5E0/TOL\n      BB=FLOAT(I1MACH(9))*0.5E0\n      AA=AMIN1(AA,BB)\n      IF(AZ.GT.AA) GO TO 240\n      IF(FN.GT.AA) GO TO 240\n      AA=SQRT(AA)\n      IF(AZ.GT.AA) IERR=3\n      IF(FN.GT.AA) IERR=3\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST ON THE LAST MEMBER OF THE SEQUENCE\nC-----------------------------------------------------------------------\n   35 CONTINUE\n      UFL = R1MACH(1)*1.0E+3\n      IF (AZ.LT.UFL) GO TO 220\n      IF (FNU.GT.FNUL) GO TO 90\n      IF (FN.LE.1.0E0) GO TO 70\n      IF (FN.GT.2.0E0) GO TO 60\n      IF (AZ.GT.TOL) GO TO 70\n      ARG = 0.5E0*AZ\n      ALN = -FN*ALOG(ARG)\n      IF (ALN.GT.ELIM) GO TO 220\n      GO TO 70\n   60 CONTINUE\n      CALL CUOIK(ZN, FNU, KODE, 2, NN, CY, NUF, TOL, ELIM, ALIM)\n      IF (NUF.LT.0) GO TO 220\n      NZ = NZ + NUF\n      NN = NN - NUF\nC-----------------------------------------------------------------------\nC     HERE NN=N OR NN=0 SINCE NUF=0,NN, OR -1 ON RETURN FROM CUOIK\nC     IF NUF=NN, THEN CY(I)=CZERO FOR ALL I\nC-----------------------------------------------------------------------\n      IF (NN.EQ.0) GO TO 130\n   70 CONTINUE\n      IF ((XN.LT.0.0E0) .OR. (XN.EQ.0.0E0 .AND. YN.LT.0.0E0 .AND.\n     * M.EQ.2)) GO TO 80\nC-----------------------------------------------------------------------\nC     RIGHT HALF PLANE COMPUTATION, XN.GE.0. .AND. (XN.NE.0. .OR.\nC     YN.GE.0. .OR. M=1)\nC-----------------------------------------------------------------------\n      CALL CBKNU(ZN, FNU, KODE, NN, CY, NZ, TOL, ELIM, ALIM)\n      GO TO 110\nC-----------------------------------------------------------------------\nC     LEFT HALF PLANE COMPUTATION\nC-----------------------------------------------------------------------\n   80 CONTINUE\n      MR = -MM\n      CALL CACON(ZN, FNU, KODE, MR, NN, CY, NW, RL, FNUL, TOL, ELIM,\n     * ALIM)\n      IF (NW.LT.0) GO TO 230\n      NZ=NW\n      GO TO 110\n   90 CONTINUE\nC-----------------------------------------------------------------------\nC     UNIFORM ASYMPTOTIC EXPANSIONS FOR FNU.GT.FNUL\nC-----------------------------------------------------------------------\n      MR = 0\n      IF ((XN.GE.0.0E0) .AND. (XN.NE.0.0E0 .OR. YN.GE.0.0E0 .OR.\n     * M.NE.2)) GO TO 100\n      MR = -MM\n      IF (XN.EQ.0.0E0 .AND. YN.LT.0.0E0) ZN = -ZN\n  100 CONTINUE\n      CALL CBUNK(ZN, FNU, KODE, MR, NN, CY, NW, TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 230\n      NZ = NZ + NW\n  110 CONTINUE\nC-----------------------------------------------------------------------\nC     H(M,FNU,Z) = -FMM*(I/HPI)*(ZT**FNU)*K(FNU,-Z*ZT)\nC\nC     ZT=EXP(-FMM*HPI*I) = CMPLX(0.0,-FMM), FMM=3-2*M, M=1,2\nC-----------------------------------------------------------------------\n      SGN = SIGN(HPI,-FMM)\nC-----------------------------------------------------------------------\nC     CALCULATE EXP(FNU*HPI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(FNU)\n      INUH = INU/2\n      IR = INU - 2*INUH\n      ARG = (FNU-FLOAT(INU-IR))*SGN\n      RHPI = 1.0E0/SGN\n      CPN = RHPI*COS(ARG)\n      SPN = RHPI*SIN(ARG)\nC     ZN = CMPLX(-SPN,CPN)\n      CSGN = CMPLX(-SPN,CPN)\nC     IF (MOD(INUH,2).EQ.1) ZN = -ZN\n      IF (MOD(INUH,2).EQ.1) CSGN = -CSGN\n      ZT = CMPLX(0.0E0,-FMM)\n      RTOL = 1.0E0/TOL\n      ASCLE = UFL*RTOL\n      DO 120 I=1,NN\nC       CY(I) = CY(I)*ZN\nC       ZN = ZN*ZT\n        ZN=CY(I)\n        AA=REAL(ZN)\n        BB=AIMAG(ZN)\n        ATOL=1.0E0\n        IF (AMAX1(ABS(AA),ABS(BB)).GT.ASCLE) GO TO 125\n          ZN = ZN*CMPLX(RTOL,0.0E0)\n          ATOL = TOL\n  125   CONTINUE\n        ZN = ZN*CSGN\n        CY(I) = ZN*CMPLX(ATOL,0.0E0)\n        CSGN = CSGN*ZT\n  120 CONTINUE\n      RETURN\n  130 CONTINUE\n      IF (XN.LT.0.0E0) GO TO 220\n      RETURN\n  220 CONTINUE\n      IERR=2\n      NZ=0\n      RETURN\n  230 CONTINUE\n      IF(NW.EQ.(-1)) GO TO 220\n      NZ=0\n      IERR=5\n      RETURN\n  240 CONTINUE\n      IERR=4\n      GO TO 35\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbesi.f",
    "content": "      SUBROUTINE CBESI(Z, FNU, KODE, N, CY, NZ, IERR)\nC***BEGIN PROLOGUE  CBESI\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  I-BESSEL FUNCTION,COMPLEX BESSEL FUNCTION,\nC             MODIFIED BESSEL FUNCTION OF THE FIRST KIND\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE I-BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC         ON KODE=1, CBESI COMPUTES AN N MEMBER SEQUENCE OF COMPLEX\nC         BESSEL FUNCTIONS CY(J)=I(FNU+J-1,Z) FOR REAL, NONNEGATIVE\nC         ORDERS FNU+J-1, J=1,...,N AND COMPLEX Z IN THE CUT PLANE\nC         -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESI RETURNS THE SCALED\nC         FUNCTIONS\nC\nC         CY(J)=EXP(-ABS(X))*I(FNU+J-1,Z)   J = 1,...,N , X=REAL(Z)\nC\nC         WITH THE EXPONENTIAL GROWTH REMOVED IN BOTH THE LEFT AND\nC         RIGHT HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND\nC         NOTATION ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL\nC         FUNCTIONS (REF.1)\nC\nC         INPUT\nC           Z      - Z=CMPLX(X,Y),  -PI.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL I FUNCTION, FNU.GE.0.0E0\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(J)=I(FNU+J-1,Z), J=1,...,N\nC                        = 2  RETURNS\nC                             CY(J)=I(FNU+J-1,Z)*EXP(-ABS(X)), J=1,...,N\nC           N      - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1\nC\nC         OUTPUT\nC           CY     - A COMPLEX VECTOR WHOSE FIRST N COMPONENTS CONTAIN\nC                    VALUES FOR THE SEQUENCE\nC                    CY(J)=I(FNU+J-1,Z)  OR\nC                    CY(J)=I(FNU+J-1,Z)*EXP(-ABS(X))  J=1,...,N\nC                    DEPENDING ON KODE, X=REAL(Z)\nC           NZ     - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW,\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ.GT.0 , LAST NZ COMPONENTS OF CY SET TO ZERO\nC                              DUE TO UNDERFLOW, CY(J)=CMPLX(0.0,0.0),\nC                              J = N-NZ+1,...,N\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, REAL(Z) TOO\nC                            LARGE ON KODE=1\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         THE COMPUTATION IS CARRIED OUT BY THE POWER SERIES FOR\nC         SMALL CABS(Z), THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z),\nC         THE MILLER ALGORITHM NORMALIZED BY THE WRONSKIAN AND A\nC         NEUMANN SERIES FOR IMTERMEDIATE MAGNITUDES, AND THE\nC         UNIFORM ASYMPTOTIC EXPANSIONS FOR I(FNU,Z) AND J(FNU,Z)\nC         FOR LARGE ORDERS. BACKWARD RECURRENCE IS USED TO GENERATE\nC         SEQUENCES OR REDUCE ORDERS WHEN NECESSARY.\nC\nC         THE CALCULATIONS ABOVE ARE DONE IN THE RIGHT HALF PLANE AND\nC         CONTINUED INTO THE LEFT HALF PLANE BY THE FORMULA\nC\nC         I(FNU,Z*EXP(M*PI)) = EXP(M*PI*FNU)*I(FNU,Z)  REAL(Z).GT.0.0\nC                       M = +I OR -I,  I**2=-1\nC\nC         FOR NEGATIVE ORDERS,THE FORMULA\nC\nC              I(-FNU,Z) = I(FNU,Z) + (2/PI)*SIN(PI*FNU)*K(FNU,Z)\nC\nC         CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO INTEGERS, THE\nC         THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE POSITIVE\nC         INTEGER,THE MAGNITUDE OF I(-FNU,Z)=I(FNU,Z) IS A LARGE\nC         NEGATIVE POWER OF TEN. BUT WHEN FNU IS NOT AN INTEGER,\nC         K(FNU,Z) DOMINATES IN MAGNITUDE WITH A LARGE POSITIVE POWER OF\nC         TEN AND THE MOST THAT THE SECOND TERM CAN BE REDUCED IS BY\nC         UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, WIDE CHANGES CAN\nC         OCCUR WITHIN UNIT ROUNDOFF OF A LARGE INTEGER FOR FNU. HERE,\nC         LARGE MEANS FNU.GT.CABS(Z).\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=R1MACH(4)=UNIT ROUNDOFF. ALSO\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  CBINU,I1MACH,R1MACH\nC***END PROLOGUE  CBESI\n      COMPLEX CONE, CSGN, CY, Z, ZN\n      REAL AA, ALIM, ARG, DIG, ELIM, FNU, FNUL, PI, RL, R1M5, S1, S2,\n     * TOL, XX, YY, R1MACH, AZ, FN, BB, ASCLE, RTOL, ATOL\n      INTEGER I, IERR, INU, K, KODE, K1, K2, N, NN, NZ, I1MACH\n      DIMENSION CY(N)\n      DATA PI /3.14159265358979324E0/\n      DATA CONE / (1.0E0,0.0E0) /\nC\nC***FIRST EXECUTABLE STATEMENT  CBESI\n      IERR = 0\n      NZ=0\n      IF (FNU.LT.0.0E0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\n      XX = REAL(Z)\n      YY = AIMAG(Z)\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU.\nC-----------------------------------------------------------------------\n      TOL = AMAX1(R1MACH(4),1.0E-18)\n      K1 = I1MACH(12)\n      K2 = I1MACH(13)\n      R1M5 = R1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303E0*(FLOAT(K)*R1M5-3.0E0)\n      K1 = I1MACH(11) - 1\n      AA = R1M5*FLOAT(K1)\n      DIG = AMIN1(AA,18.0E0)\n      AA = AA*2.303E0\n      ALIM = ELIM + AMAX1(-AA,-41.45E0)\n      RL = 1.2E0*DIG + 3.0E0\n      FNUL = 10.0E0 + 6.0E0*(DIG-3.0E0)\n      AZ = CABS(Z)\nC-----------------------------------------------------------------------\nC     TEST FOR RANGE\nC-----------------------------------------------------------------------\n      AA = 0.5E0/TOL\n      BB=FLOAT(I1MACH(9))*0.5E0\n      AA=AMIN1(AA,BB)\n      IF(AZ.GT.AA) GO TO 140\n      FN=FNU+FLOAT(N-1)\n      IF(FN.GT.AA) GO TO 140\n      AA=SQRT(AA)\n      IF(AZ.GT.AA) IERR=3\n      IF(FN.GT.AA) IERR=3\n   35 CONTINUE\n      ZN = Z\n      CSGN = CONE\n      IF (XX.GE.0.0E0) GO TO 40\n      ZN = -Z\nC-----------------------------------------------------------------------\nC     CALCULATE CSGN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(FNU)\n      ARG = (FNU-FLOAT(INU))*PI\n      IF (YY.LT.0.0E0) ARG = -ARG\n      S1 = COS(ARG)\n      S2 = SIN(ARG)\n      CSGN = CMPLX(S1,S2)\n      IF (MOD(INU,2).EQ.1) CSGN = -CSGN\n   40 CONTINUE\n      CALL CBINU(ZN, FNU, KODE, N, CY, NZ, RL, FNUL, TOL, ELIM, ALIM)\n      IF (NZ.LT.0) GO TO 120\n      IF (XX.GE.0.0E0) RETURN\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION TO THE LEFT HALF PLANE\nC-----------------------------------------------------------------------\n      NN = N - NZ\n      IF (NN.EQ.0) RETURN\n      RTOL = 1.0E0/TOL\n      ASCLE = R1MACH(1)*RTOL*1.0E+3\n      DO 50 I=1,NN\nC       CY(I) = CY(I)*CSGN\n        ZN=CY(I)\n        AA=REAL(ZN)\n        BB=AIMAG(ZN)\n        ATOL=1.0E0\n        IF (AMAX1(ABS(AA),ABS(BB)).GT.ASCLE) GO TO 55\n          ZN = ZN*CMPLX(RTOL,0.0E0)\n          ATOL = TOL\n   55   CONTINUE\n        ZN = ZN*CSGN\n        CY(I) = ZN*CMPLX(ATOL,0.0E0)\n        CSGN = -CSGN\n   50 CONTINUE\n      RETURN\n  120 CONTINUE\n      IF(NZ.EQ.(-2)) GO TO 130\n      NZ = 0\n      IERR=2\n      RETURN\n  130 CONTINUE\n      NZ=0\n      IERR=5\n      RETURN\n  140 CONTINUE\n      IERR=4\n      GO TO 35\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbesj.f",
    "content": "      SUBROUTINE CBESJ(Z, FNU, KODE, N, CY, NZ, IERR)\nC***BEGIN PROLOGUE  CBESJ\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  J-BESSEL FUNCTION,BESSEL FUNCTION OF COMPLEX ARGUMENT,\nC             BESSEL FUNCTION OF FIRST KIND\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE THE J-BESSEL FUNCTION OF A COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC         ON KODE=1, CBESJ COMPUTES AN N MEMBER  SEQUENCE OF COMPLEX\nC         BESSEL FUNCTIONS CY(I)=J(FNU+I-1,Z) FOR REAL, NONNEGATIVE\nC         ORDERS FNU+I-1, I=1,...,N AND COMPLEX Z IN THE CUT PLANE\nC         -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESJ RETURNS THE SCALED\nC         FUNCTIONS\nC\nC         CY(I)=EXP(-ABS(Y))*J(FNU+I-1,Z)   I = 1,...,N , Y=AIMAG(Z)\nC\nC         WHICH REMOVE THE EXPONENTIAL GROWTH IN BOTH THE UPPER AND\nC         LOWER HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION\nC         ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS\nC         (REF. 1).\nC\nC         INPUT\nC           Z      - Z=CMPLX(X,Y),  -PI.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL J FUNCTION, FNU.GE.0.0E0\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(I)=J(FNU+I-1,Z), I=1,...,N\nC                        = 2  RETURNS\nC                             CY(I)=J(FNU+I-1,Z)*EXP(-ABS(Y)), I=1,...\nC           N      - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1\nC\nC         OUTPUT\nC           CY     - A COMPLEX VECTOR WHOSE FIRST N COMPONENTS CONTAIN\nC                    VALUES FOR THE SEQUENCE\nC                    CY(I)=J(FNU+I-1,Z)  OR\nC                    CY(I)=J(FNU+I-1,Z)*EXP(-ABS(Y))  I=1,...,N\nC                    DEPENDING ON KODE, Y=AIMAG(Z).\nC           NZ     - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW,\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ.GT.0 , LAST NZ COMPONENTS OF CY SET TO ZERO\nC                              DUE TO UNDERFLOW, CY(I)=CMPLX(0.0,0.0),\nC                              I = N-NZ+1,...,N\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, AIMAG(Z)\nC                            TOO LARGE ON KODE=1\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         THE COMPUTATION IS CARRIED OUT BY THE FORMULA\nC\nC         J(FNU,Z)=EXP( FNU*PI*I/2)*I(FNU,-I*Z)    AIMAG(Z).GE.0.0\nC\nC         J(FNU,Z)=EXP(-FNU*PI*I/2)*I(FNU, I*Z)    AIMAG(Z).LT.0.0\nC\nC         WHERE I**2 = -1 AND I(FNU,Z) IS THE I BESSEL FUNCTION.\nC\nC         FOR NEGATIVE ORDERS,THE FORMULA\nC\nC              J(-FNU,Z) = J(FNU,Z)*COS(PI*FNU) - Y(FNU,Z)*SIN(PI*FNU)\nC\nC         CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO INTEGERS, THE\nC         THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE POSITIVE\nC         INTEGER,THE MAGNITUDE OF J(-FNU,Z)=J(FNU,Z)*COS(PI*FNU) IS A\nC         LARGE NEGATIVE POWER OF TEN. BUT WHEN FNU IS NOT AN INTEGER,\nC         Y(FNU,Z) DOMINATES IN MAGNITUDE WITH A LARGE POSITIVE POWER OF\nC         TEN AND THE MOST THAT THE SECOND TERM CAN BE REDUCED IS BY\nC         UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, WIDE CHANGES CAN\nC         OCCUR WITHIN UNIT ROUNDOFF OF A LARGE INTEGER FOR FNU. HERE,\nC         LARGE MEANS FNU.GT.CABS(Z).\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=R1MACH(4)=UNIT ROUNDOFF. ALSO\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  CBINU,I1MACH,R1MACH\nC***END PROLOGUE  CBESJ\nC\n      COMPLEX CI, CSGN, CY, Z, ZN\n      REAL AA, ALIM, ARG, DIG, ELIM, FNU, FNUL, HPI, RL, R1, R1M5, R2,\n     * TOL, YY, R1MACH, AZ, FN, BB, ASCLE, RTOL, ATOL\n      INTEGER I, IERR, INU, INUH, IR, KODE, K1, K2, N, NL, NZ, I1MACH, K\n      DIMENSION CY(N)\n      DATA HPI /1.57079632679489662E0/\nC\nC***FIRST EXECUTABLE STATEMENT  CBESJ\n      IERR = 0\n      NZ=0\n      IF (FNU.LT.0.0E0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU.\nC-----------------------------------------------------------------------\n      TOL = AMAX1(R1MACH(4),1.0E-18)\n      K1 = I1MACH(12)\n      K2 = I1MACH(13)\n      R1M5 = R1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303E0*(FLOAT(K)*R1M5-3.0E0)\n      K1 = I1MACH(11) - 1\n      AA = R1M5*FLOAT(K1)\n      DIG = AMIN1(AA,18.0E0)\n      AA = AA*2.303E0\n      ALIM = ELIM + AMAX1(-AA,-41.45E0)\n      RL = 1.2E0*DIG + 3.0E0\n      FNUL = 10.0E0 + 6.0E0*(DIG-3.0E0)\n      CI = CMPLX(0.0E0,1.0E0)\n      YY = AIMAG(Z)\n      AZ = CABS(Z)\nC-----------------------------------------------------------------------\nC     TEST FOR RANGE\nC-----------------------------------------------------------------------\n      AA = 0.5E0/TOL\n      BB=FLOAT(I1MACH(9))*0.5E0\n      AA=AMIN1(AA,BB)\n      FN=FNU+FLOAT(N-1)\n      IF(AZ.GT.AA) GO TO 140\n      IF(FN.GT.AA) GO TO 140\n      AA=SQRT(AA)\n      IF(AZ.GT.AA) IERR=3\n      IF(FN.GT.AA) IERR=3\nC-----------------------------------------------------------------------\nC     CALCULATE CSGN=EXP(FNU*HPI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n  35  CONTINUE\n      INU = INT(FNU)\n      INUH = INU/2\n      IR = INU - 2*INUH\n      ARG = (FNU-FLOAT(INU-IR))*HPI\n      R1 = COS(ARG)\n      R2 = SIN(ARG)\n      CSGN = CMPLX(R1,R2)\n      IF (MOD(INUH,2).EQ.1) CSGN = -CSGN\nC-----------------------------------------------------------------------\nC     ZN IS IN THE RIGHT HALF PLANE\nC-----------------------------------------------------------------------\n      ZN = -Z*CI\n      IF (YY.GE.0.0E0) GO TO 40\n      ZN = -ZN\n      CSGN = CONJG(CSGN)\n      CI = CONJG(CI)\n   40 CONTINUE\n      CALL CBINU(ZN, FNU, KODE, N, CY, NZ, RL, FNUL, TOL, ELIM, ALIM)\n      IF (NZ.LT.0) GO TO 120\n      NL = N - NZ\n      IF (NL.EQ.0) RETURN\n      RTOL = 1.0E0/TOL\n      ASCLE = R1MACH(1)*RTOL*1.0E+3\n      DO 50 I=1,NL\nC       CY(I)=CY(I)*CSGN\n        ZN=CY(I)\n        AA=REAL(ZN)\n        BB=AIMAG(ZN)\n        ATOL=1.0E0\n        IF (AMAX1(ABS(AA),ABS(BB)).GT.ASCLE) GO TO 55\n          ZN = ZN*CMPLX(RTOL,0.0E0)\n          ATOL = TOL\n   55   CONTINUE\n        ZN = ZN*CSGN\n        CY(I) = ZN*CMPLX(ATOL,0.0E0)\n        CSGN = CSGN*CI\n   50 CONTINUE\n      RETURN\n  120 CONTINUE\n      IF(NZ.EQ.(-2)) GO TO 130\n      NZ = 0\n      IERR = 2\n      RETURN\n  130 CONTINUE\n      NZ=0\n      IERR=5\n      RETURN\n  140 CONTINUE\n      IERR=4\n      GO TO 35\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbesk.f",
    "content": "      SUBROUTINE CBESK(Z, FNU, KODE, N, CY, NZ, IERR)\nC***BEGIN PROLOGUE  CBESK\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  K-BESSEL FUNCTION,COMPLEX BESSEL FUNCTION,\nC             MODIFIED BESSEL FUNCTION OF THE SECOND KIND,\nC             BESSEL FUNCTION OF THE THIRD KIND\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE K-BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC         ON KODE=1, CBESK COMPUTES AN N MEMBER SEQUENCE OF COMPLEX\nC         BESSEL FUNCTIONS CY(J)=K(FNU+J-1,Z) FOR REAL, NONNEGATIVE\nC         ORDERS FNU+J-1, J=1,...,N AND COMPLEX Z.NE.CMPLX(0.0,0.0)\nC         IN THE CUT PLANE -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESK\nC         RETURNS THE SCALED K FUNCTIONS,\nC\nC         CY(J)=EXP(Z)*K(FNU+J-1,Z) , J=1,...,N,\nC\nC         WHICH REMOVE THE EXPONENTIAL BEHAVIOR IN BOTH THE LEFT AND\nC         RIGHT HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND\nC         NOTATION ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL\nC         FUNCTIONS (REF. 1).\nC\nC         INPUT\nC           Z      - Z=CMPLX(X,Y),Z.NE.CMPLX(0.,0.),-PI.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL K FUNCTION, FNU.GE.0.0E0\nC           N      - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(I)=K(FNU+I-1,Z), I=1,...,N\nC                        = 2  RETURNS\nC                             CY(I)=K(FNU+I-1,Z)*EXP(Z), I=1,...,N\nC\nC         OUTPUT\nC           CY     - A COMPLEX VECTOR WHOSE FIRST N COMPONENTS CONTAIN\nC                    VALUES FOR THE SEQUENCE\nC                    CY(I)=K(FNU+I-1,Z), I=1,...,N OR\nC                    CY(I)=K(FNU+I-1,Z)*EXP(Z), I=1,...,N\nC                    DEPENDING ON KODE\nC           NZ     - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW.\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ.GT.0 , FIRST NZ COMPONENTS OF CY SET TO ZERO\nC                              DUE TO UNDERFLOW, CY(I)=CMPLX(0.0,0.0),\nC                              I=1,...,N WHEN X.GE.0.0. WHEN X.LT.0.0\nC                              NZ STATES ONLY THE NUMBER OF UNDERFLOWS\nC                              IN THE SEQUENCE.\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, FNU+N-1 IS\nC                            TOO LARGE OR CABS(Z) IS TOO SMALL OR BOTH\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         EQUATIONS OF THE REFERENCE ARE IMPLEMENTED FOR SMALL ORDERS\nC         DNU AND DNU+1.0 IN THE RIGHT HALF PLANE X.GE.0.0. FORWARD\nC         RECURRENCE GENERATES HIGHER ORDERS. K IS CONTINUED TO THE LEFT\nC         HALF PLANE BY THE RELATION\nC\nC         K(FNU,Z*EXP(MP)) = EXP(-MP*FNU)*K(FNU,Z)-MP*I(FNU,Z)\nC         MP=MR*PI*I, MR=+1 OR -1, RE(Z).GT.0, I**2=-1\nC\nC         WHERE I(FNU,Z) IS THE I BESSEL FUNCTION.\nC\nC         FOR LARGE ORDERS, FNU.GT.FNUL, THE K FUNCTION IS COMPUTED\nC         BY MEANS OF ITS UNIFORM ASYMPTOTIC EXPANSIONS.\nC\nC         FOR NEGATIVE ORDERS, THE FORMULA\nC\nC                       K(-FNU,Z) = K(FNU,Z)\nC\nC         CAN BE USED.\nC\nC         CBESK ASSUMES THAT A SIGNIFICANT DIGIT SINH(X) FUNCTION IS\nC         AVAILABLE.\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=R1MACH(4)=UNIT ROUNDOFF. ALSO\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983.\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  CACON,CBKNU,CBUNK,CUOIK,I1MACH,R1MACH\nC***END PROLOGUE  CBESK\nC\n      COMPLEX CY, Z\n      REAL AA, ALIM, ALN, ARG, AZ, DIG, ELIM, FN, FNU, FNUL, RL, R1M5,\n     * TOL, UFL, XX, YY, R1MACH, BB\n      INTEGER IERR, K, KODE, K1, K2, MR, N, NN, NUF, NW, NZ, I1MACH\n      DIMENSION CY(N)\nC***FIRST EXECUTABLE STATEMENT  CBESK\n      IERR = 0\n      NZ=0\n      XX = REAL(Z)\n      YY = AIMAG(Z)\n      IF (YY.EQ.0.0E0 .AND. XX.EQ.0.0E0) IERR=1\n      IF (FNU.LT.0.0E0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\n      NN = N\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU\nC-----------------------------------------------------------------------\n      TOL = AMAX1(R1MACH(4),1.0E-18)\n      K1 = I1MACH(12)\n      K2 = I1MACH(13)\n      R1M5 = R1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303E0*(FLOAT(K)*R1M5-3.0E0)\n      K1 = I1MACH(11) - 1\n      AA = R1M5*FLOAT(K1)\n      DIG = AMIN1(AA,18.0E0)\n      AA = AA*2.303E0\n      ALIM = ELIM + AMAX1(-AA,-41.45E0)\n      FNUL = 10.0E0 + 6.0E0*(DIG-3.0E0)\n      RL = 1.2E0*DIG + 3.0E0\n      AZ = CABS(Z)\n      FN = FNU + FLOAT(NN-1)\nC-----------------------------------------------------------------------\nC     TEST FOR RANGE\nC-----------------------------------------------------------------------\n      AA = 0.5E0/TOL\n      BB=FLOAT(I1MACH(9))*0.5E0\n      AA=AMIN1(AA,BB)\n      IF(AZ.GT.AA) GO TO 210\n      IF(FN.GT.AA) GO TO 210\n      AA=SQRT(AA)\n      IF(AZ.GT.AA) IERR=3\n      IF(FN.GT.AA) IERR=3\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST ON THE LAST MEMBER OF THE SEQUENCE\nC-----------------------------------------------------------------------\nC     UFL = EXP(-ELIM)\n   35 CONTINUE\n      UFL = R1MACH(1)*1.0E+3\n      IF (AZ.LT.UFL) GO TO 180\n      IF (FNU.GT.FNUL) GO TO 80\n      IF (FN.LE.1.0E0) GO TO 60\n      IF (FN.GT.2.0E0) GO TO 50\n      IF (AZ.GT.TOL) GO TO 60\n      ARG = 0.5E0*AZ\n      ALN = -FN*ALOG(ARG)\n      IF (ALN.GT.ELIM) GO TO 180\n      GO TO 60\n   50 CONTINUE\n      CALL CUOIK(Z, FNU, KODE, 2, NN, CY, NUF, TOL, ELIM, ALIM)\n      IF (NUF.LT.0) GO TO 180\n      NZ = NZ + NUF\n      NN = NN - NUF\nC-----------------------------------------------------------------------\nC     HERE NN=N OR NN=0 SINCE NUF=0,NN, OR -1 ON RETURN FROM CUOIK\nC     IF NUF=NN, THEN CY(I)=CZERO FOR ALL I\nC-----------------------------------------------------------------------\n      IF (NN.EQ.0) GO TO 100\n   60 CONTINUE\n      IF (XX.LT.0.0E0) GO TO 70\nC-----------------------------------------------------------------------\nC     RIGHT HALF PLANE COMPUTATION, REAL(Z).GE.0.\nC-----------------------------------------------------------------------\n      CALL CBKNU(Z, FNU, KODE, NN, CY, NW, TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 200\n      NZ=NW\n      RETURN\nC-----------------------------------------------------------------------\nC     LEFT HALF PLANE COMPUTATION\nC     PI/2.LT.ARG(Z).LE.PI AND -PI.LT.ARG(Z).LT.-PI/2.\nC-----------------------------------------------------------------------\n   70 CONTINUE\n      IF (NZ.NE.0) GO TO 180\n      MR = 1\n      IF (YY.LT.0.0E0) MR = -1\n      CALL CACON(Z, FNU, KODE, MR, NN, CY, NW, RL, FNUL, TOL, ELIM,\n     * ALIM)\n      IF (NW.LT.0) GO TO 200\n      NZ=NW\n      RETURN\nC-----------------------------------------------------------------------\nC     UNIFORM ASYMPTOTIC EXPANSIONS FOR FNU.GT.FNUL\nC-----------------------------------------------------------------------\n   80 CONTINUE\n      MR = 0\n      IF (XX.GE.0.0E0) GO TO 90\n      MR = 1\n      IF (YY.LT.0.0E0) MR = -1\n   90 CONTINUE\n      CALL CBUNK(Z, FNU, KODE, MR, NN, CY, NW, TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 200\n      NZ = NZ + NW\n      RETURN\n  100 CONTINUE\n      IF (XX.LT.0.0E0) GO TO 180\n      RETURN\n  180 CONTINUE\n      NZ = 0\n      IERR=2\n      RETURN\n  200 CONTINUE\n      IF(NW.EQ.(-1)) GO TO 180\n      NZ=0\n      IERR=5\n      RETURN\n  210 CONTINUE\n      IERR=4\n      GO TO 35\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbesy.f",
    "content": "      SUBROUTINE CBESY(Z, FNU, KODE, N, CY, NZ, CWRK, IERR)\nC***BEGIN PROLOGUE  CBESY\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  Y-BESSEL FUNCTION,BESSEL FUNCTION OF COMPLEX ARGUMENT,\nC             BESSEL FUNCTION OF SECOND KIND\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE THE Y-BESSEL FUNCTION OF A COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC         ON KODE=1, CBESY COMPUTES AN N MEMBER SEQUENCE OF COMPLEX\nC         BESSEL FUNCTIONS CY(I)=Y(FNU+I-1,Z) FOR REAL, NONNEGATIVE\nC         ORDERS FNU+I-1, I=1,...,N AND COMPLEX Z IN THE CUT PLANE\nC         -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESY RETURNS THE SCALED\nC         FUNCTIONS\nC\nC         CY(I)=EXP(-ABS(Y))*Y(FNU+I-1,Z)   I = 1,...,N , Y=AIMAG(Z)\nC\nC         WHICH REMOVE THE EXPONENTIAL GROWTH IN BOTH THE UPPER AND\nC         LOWER HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION\nC         ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS\nC         (REF. 1).\nC\nC         INPUT\nC           Z      - Z=CMPLX(X,Y), Z.NE.CMPLX(0.,0.),-PI.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL Y FUNCTION, FNU.GE.0.0E0\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(I)=Y(FNU+I-1,Z), I=1,...,N\nC                        = 2  RETURNS\nC                             CY(I)=Y(FNU+I-1,Z)*EXP(-ABS(Y)), I=1,...,N\nC                             WHERE Y=AIMAG(Z)\nC           N      - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1\nC           CWRK   - A COMPLEX WORK VECTOR OF DIMENSION AT LEAST N\nC\nC         OUTPUT\nC           CY     - A COMPLEX VECTOR WHOSE FIRST N COMPONENTS CONTAIN\nC                    VALUES FOR THE SEQUENCE\nC                    CY(I)=Y(FNU+I-1,Z)  OR\nC                    CY(I)=Y(FNU+I-1,Z)*EXP(-ABS(Y))  I=1,...,N\nC                    DEPENDING ON KODE.\nC           NZ     - NZ=0 , A NORMAL RETURN\nC                    NZ.GT.0 , NZ COMPONENTS OF CY SET TO ZERO DUE TO\nC                    UNDERFLOW (GENERALLY ON KODE=2)\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, FNU+N-1 IS\nC                            TOO LARGE OR CABS(Z) IS TOO SMALL OR BOTH\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         THE COMPUTATION IS CARRIED OUT BY THE FORMULA\nC\nC         Y(FNU,Z)=0.5*(H(1,FNU,Z)-H(2,FNU,Z))/I\nC\nC         WHERE I**2 = -1 AND THE HANKEL BESSEL FUNCTIONS H(1,FNU,Z)\nC         AND H(2,FNU,Z) ARE CALCULATED IN CBESH.\nC\nC         FOR NEGATIVE ORDERS,THE FORMULA\nC\nC              Y(-FNU,Z) = Y(FNU,Z)*COS(PI*FNU) + J(FNU,Z)*SIN(PI*FNU)\nC\nC         CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO HALF ODD\nC         INTEGERS THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE\nC         POSITIVE HALF ODD INTEGER,THE MAGNITUDE OF Y(-FNU,Z)=J(FNU,Z)*\nC         SIN(PI*FNU) IS A LARGE NEGATIVE POWER OF TEN. BUT WHEN FNU IS\nC         NOT A HALF ODD INTEGER, Y(FNU,Z) DOMINATES IN MAGNITUDE WITH A\nC         LARGE POSITIVE POWER OF TEN AND THE MOST THAT THE SECOND TERM\nC         CAN BE REDUCED IS BY UNIT ROUNDOFF FROM THE COEFFICIENT. THUS,\nC         WIDE CHANGES CAN OCCUR WITHIN UNIT ROUNDOFF OF A LARGE HALF\nC         ODD INTEGER. HERE, LARGE MEANS FNU.GT.CABS(Z).\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=R1MACH(4)=UNIT ROUNDOFF. ALSO\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  CBESH,I1MACH,R1MACH\nC***END PROLOGUE  CBESY\nC\n      COMPLEX CWRK, CY, C1, C2, EX, HCI, Z, ZU, ZV\n      REAL ELIM, EY, FNU, R1, R2, TAY, XX, YY, R1MACH, ASCLE, RTOL,\n     * ATOL, AA, BB\n      INTEGER I, IERR, K, KODE, K1, K2, N, NZ, NZ1, NZ2, I1MACH\n      DIMENSION CY(N), CWRK(N)\nC***FIRST EXECUTABLE STATEMENT  CBESY\n      XX = REAL(Z)\n      YY = AIMAG(Z)\n      IERR = 0\n      NZ=0\n      IF (XX.EQ.0.0E0 .AND. YY.EQ.0.0E0) IERR=1\n      IF (FNU.LT.0.0E0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\n      HCI = CMPLX(0.0E0,0.5E0)\n      CALL CBESH(Z, FNU, KODE, 1, N, CY, NZ1, IERR)\n      IF (IERR.NE.0.AND.IERR.NE.3) GO TO 170\n      CALL CBESH(Z, FNU, KODE, 2, N, CWRK, NZ2, IERR)\n      IF (IERR.NE.0.AND.IERR.NE.3) GO TO 170\n      NZ = MIN0(NZ1,NZ2)\n      IF (KODE.EQ.2) GO TO 60\n      DO 50 I=1,N\n        CY(I) = HCI*(CWRK(I)-CY(I))\n   50 CONTINUE\n      RETURN\n   60 CONTINUE\n      TOL = AMAX1(R1MACH(4),1.0E-18)\n      K1 = I1MACH(12)\n      K2 = I1MACH(13)\n      K = MIN0(IABS(K1),IABS(K2))\n      R1M5 = R1MACH(5)\nC-----------------------------------------------------------------------\nC     ELIM IS THE APPROXIMATE EXPONENTIAL UNDER- AND OVERFLOW LIMIT\nC-----------------------------------------------------------------------\n      ELIM = 2.303E0*(FLOAT(K)*R1M5-3.0E0)\n      R1 = COS(XX)\n      R2 = SIN(XX)\n      EX = CMPLX(R1,R2)\n      EY = 0.0E0\n      TAY = ABS(YY+YY)\n      IF (TAY.LT.ELIM) EY = EXP(-TAY)\n      IF (YY.LT.0.0E0) GO TO 90\n      C1 = EX*CMPLX(EY,0.0E0)\n      C2 = CONJG(EX)\n   70 CONTINUE\n      NZ = 0\n      RTOL = 1.0E0/TOL\n      ASCLE = R1MACH(1)*RTOL*1.0E+3\n      DO 80 I=1,N\nC       CY(I) = HCI*(C2*CWRK(I)-C1*CY(I))\n        ZV = CWRK(I)\n        AA=REAL(ZV)\n        BB=AIMAG(ZV)\n        ATOL=1.0E0\n        IF (AMAX1(ABS(AA),ABS(BB)).GT.ASCLE) GO TO 75\n          ZV = ZV*CMPLX(RTOL,0.0E0)\n          ATOL = TOL\n   75   CONTINUE\n        ZV = ZV*C2*HCI\n        ZV = ZV*CMPLX(ATOL,0.0E0)\n        ZU=CY(I)\n        AA=REAL(ZU)\n        BB=AIMAG(ZU)\n        ATOL=1.0E0\n        IF (AMAX1(ABS(AA),ABS(BB)).GT.ASCLE) GO TO 85\n          ZU = ZU*CMPLX(RTOL,0.0E0)\n          ATOL = TOL\n   85   CONTINUE\n        ZU = ZU*C1*HCI\n        ZU = ZU*CMPLX(ATOL,0.0E0)\n        CY(I) = ZV - ZU\n        IF (CY(I).EQ.CMPLX(0.0E0,0.0E0) .AND. EY.EQ.0.0E0) NZ = NZ + 1\n   80 CONTINUE\n      RETURN\n   90 CONTINUE\n      C1 = EX\n      C2 = CONJG(EX)*CMPLX(EY,0.0E0)\n      GO TO 70\n  170 CONTINUE\n      NZ = 0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbinu.f",
    "content": "      SUBROUTINE CBINU(Z, FNU, KODE, N, CY, NZ, RL, FNUL, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  CBINU\nC***REFER TO  CBESH,CBESI,CBESJ,CBESK,CAIRY,CBIRY\nC\nC     CBINU COMPUTES THE I FUNCTION IN THE RIGHT HALF Z PLANE\nC\nC***ROUTINES CALLED  CASYI,CBUNI,CMLRI,CSERI,CUOIK,CWRSK\nC***END PROLOGUE  CBINU\n      COMPLEX CW, CY, CZERO, Z\n      REAL ALIM, AZ, DFNU, ELIM, FNU, FNUL, RL, TOL\n      INTEGER I, INW, KODE, N, NLAST, NN, NUI, NW, NZ\n      DIMENSION CY(N), CW(2)\n      DATA CZERO / (0.0E0,0.0E0) /\nC\n      NZ = 0\n      AZ = CABS(Z)\n      NN = N\n      DFNU = FNU + FLOAT(N-1)\n      IF (AZ.LE.2.0E0) GO TO 10\n      IF (AZ*AZ*0.25E0.GT.DFNU+1.0E0) GO TO 20\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     POWER SERIES\nC-----------------------------------------------------------------------\n      CALL CSERI(Z, FNU, KODE, NN, CY, NW, TOL, ELIM, ALIM)\n      INW = IABS(NW)\n      NZ = NZ + INW\n      NN = NN - INW\n      IF (NN.EQ.0) RETURN\n      IF (NW.GE.0) GO TO 120\n      DFNU = FNU + FLOAT(NN-1)\n   20 CONTINUE\n      IF (AZ.LT.RL) GO TO 40\n      IF (DFNU.LE.1.0E0) GO TO 30\n      IF (AZ+AZ.LT.DFNU*DFNU) GO TO 50\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR LARGE Z\nC-----------------------------------------------------------------------\n   30 CONTINUE\n      CALL CASYI(Z, FNU, KODE, NN, CY, NW, RL, TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 130\n      GO TO 120\n   40 CONTINUE\n      IF (DFNU.LE.1.0E0) GO TO 70\n   50 CONTINUE\nC-----------------------------------------------------------------------\nC     OVERFLOW AND UNDERFLOW TEST ON I SEQUENCE FOR MILLER ALGORITHM\nC-----------------------------------------------------------------------\n      CALL CUOIK(Z, FNU, KODE, 1, NN, CY, NW, TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 130\n      NZ = NZ + NW\n      NN = NN - NW\n      IF (NN.EQ.0) RETURN\n      DFNU = FNU+FLOAT(NN-1)\n      IF (DFNU.GT.FNUL) GO TO 110\n      IF (AZ.GT.FNUL) GO TO 110\n   60 CONTINUE\n      IF (AZ.GT.RL) GO TO 80\n   70 CONTINUE\nC-----------------------------------------------------------------------\nC     MILLER ALGORITHM NORMALIZED BY THE SERIES\nC-----------------------------------------------------------------------\n      CALL CMLRI(Z, FNU, KODE, NN, CY, NW, TOL)\n      IF(NW.LT.0) GO TO 130\n      GO TO 120\n   80 CONTINUE\nC-----------------------------------------------------------------------\nC     MILLER ALGORITHM NORMALIZED BY THE WRONSKIAN\nC-----------------------------------------------------------------------\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST ON K FUNCTIONS USED IN WRONSKIAN\nC-----------------------------------------------------------------------\n      CALL CUOIK(Z, FNU, KODE, 2, 2, CW, NW, TOL, ELIM, ALIM)\n      IF (NW.GE.0) GO TO 100\n      NZ = NN\n      DO 90 I=1,NN\n        CY(I) = CZERO\n   90 CONTINUE\n      RETURN\n  100 CONTINUE\n      IF (NW.GT.0) GO TO 130\n      CALL CWRSK(Z, FNU, KODE, NN, CY, NW, CW, TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 130\n      GO TO 120\n  110 CONTINUE\nC-----------------------------------------------------------------------\nC     INCREMENT FNU+NN-1 UP TO FNUL, COMPUTE AND RECUR BACKWARD\nC-----------------------------------------------------------------------\n      NUI = INT(FNUL-DFNU) + 1\n      NUI = MAX0(NUI,0)\n      CALL CBUNI(Z, FNU, KODE, NN, CY, NW, NUI, NLAST, FNUL, TOL, ELIM,\n     * ALIM)\n      IF (NW.LT.0) GO TO 130\n      NZ = NZ + NW\n      IF (NLAST.EQ.0) GO TO 120\n      NN = NLAST\n      GO TO 60\n  120 CONTINUE\n      RETURN\n  130 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbiry.f",
    "content": "      SUBROUTINE CBIRY(Z, ID, KODE, BI, IERR)\nC***BEGIN PROLOGUE  CBIRY\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE AIRY FUNCTIONS BI(Z) AND DBI(Z) FOR COMPLEX Z\nC***DESCRIPTION\nC\nC         ON KODE=1, CBIRY COMPUTES THE COMPLEX AIRY FUNCTION BI(Z) OR\nC         ITS DERIVATIVE DBI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON\nC         KODE=2, A SCALING OPTION CEXP(-AXZTA)*BI(Z) OR CEXP(-AXZTA)*\nC         DBI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL BEHAVIOR IN\nC         BOTH THE LEFT AND RIGHT HALF PLANES WHERE\nC         ZTA=(2/3)*Z*CSQRT(Z)=CMPLX(XZTA,YZTA) AND AXZTA=ABS(XZTA).\nC         DEFINITIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF\nC         MATHEMATICAL FUNCTIONS (REF. 1).\nC\nC         INPUT\nC           Z      - Z=CMPLX(X,Y)\nC           ID     - ORDER OF DERIVATIVE, ID=0 OR ID=1\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             BI=BI(Z)                 ON ID=0 OR\nC                             BI=DBI(Z)/DZ             ON ID=1\nC                        = 2  RETURNS\nC                             BI=CEXP(-AXZTA)*BI(Z)     ON ID=0 OR\nC                             BI=CEXP(-AXZTA)*DBI(Z)/DZ ON ID=1 WHERE\nC                             ZTA=(2/3)*Z*CSQRT(Z)=CMPLX(XZTA,YZTA)\nC                             AND AXZTA=ABS(XZTA)\nC\nC         OUTPUT\nC           BI     - COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND\nC                    KODE\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, REAL(Z)\nC                            TOO LARGE WITH KODE=1\nC                    IERR=3, CABS(Z) LARGE      - COMPUTATION COMPLETED\nC                            LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION\nC                            PRODUCE LESS THAN HALF OF MACHINE ACCURACY\nC                    IERR=4, CABS(Z) TOO LARGE  - NO COMPUTATION\nC                            COMPLETE LOSS OF ACCURACY BY ARGUMENT\nC                            REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         BI AND DBI ARE COMPUTED FOR CABS(Z).GT.1.0 FROM THE I BESSEL\nC         FUNCTIONS BY\nC\nC                BI(Z)=C*SQRT(Z)*( I(-1/3,ZTA) + I(1/3,ZTA) )\nC               DBI(Z)=C *  Z  * ( I(-2/3,ZTA) + I(2/3,ZTA) )\nC                               C=1.0/SQRT(3.0)\nC                               ZTA=(2/3)*Z**(3/2)\nC\nC         WITH THE POWER SERIES FOR CABS(Z).LE.1.0.\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES\nC         OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF\nC         THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR),\nC         THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR\nC         FLAG IERR=3 IS TRIGGERED WHERE UR=R1MACH(4)=UNIT ROUNDOFF.\nC         ALSO, IF THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN\nC         ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT\nC         FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE\nC         LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA\nC         MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2,\nC         AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE\nC         PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE\nC         PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT-\nC         ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG-\nC         NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN\nC         DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN\nC         EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES,\nC         NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE\nC         PRECISION ARITHMETIC.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  CBINU,I1MACH,R1MACH\nC***END PROLOGUE  CBIRY\n      COMPLEX BI, CONE, CSQ, CY, S1, S2, TRM1, TRM2, Z, ZTA, Z3\n      REAL AA, AD, AK, ALIM, ATRM, AZ, AZ3, BB, BK, CK, COEF, C1, C2,\n     * DIG, DK, D1, D2, ELIM, FID, FMR, FNU, FNUL, PI, RL, R1M5, SFAC,\n     * TOL, TTH, ZI, ZR, Z3I, Z3R, R1MACH\n      INTEGER ID, IERR, K, KODE, K1, K2, NZ, I1MACH\n      DIMENSION CY(2)\n      DATA TTH, C1, C2, COEF, PI /6.66666666666666667E-01,\n     * 6.14926627446000736E-01,4.48288357353826359E-01,\n     * 5.77350269189625765E-01,3.14159265358979324E+00/\n      DATA  CONE / (1.0E0,0.0E0) /\nC***FIRST EXECUTABLE STATEMENT  CBIRY\n      IERR = 0\n      NZ=0\n      IF (ID.LT.0 .OR. ID.GT.1) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (IERR.NE.0) RETURN\n      AZ = CABS(Z)\n      TOL = AMAX1(R1MACH(4),1.0E-18)\n      FID = FLOAT(ID)\n      IF (AZ.GT.1.0E0) GO TO 60\nC-----------------------------------------------------------------------\nC     POWER SERIES FOR CABS(Z).LE.1.\nC-----------------------------------------------------------------------\n      S1 = CONE\n      S2 = CONE\n      IF (AZ.LT.TOL) GO TO 110\n      AA = AZ*AZ\n      IF (AA.LT.TOL/AZ) GO TO 40\n      TRM1 = CONE\n      TRM2 = CONE\n      ATRM = 1.0E0\n      Z3 = Z*Z*Z\n      AZ3 = AZ*AA\n      AK = 2.0E0 + FID\n      BK = 3.0E0 - FID - FID\n      CK = 4.0E0 - FID\n      DK = 3.0E0 + FID + FID\n      D1 = AK*DK\n      D2 = BK*CK\n      AD = AMIN1(D1,D2)\n      AK = 24.0E0 + 9.0E0*FID\n      BK = 30.0E0 - 9.0E0*FID\n      Z3R = REAL(Z3)\n      Z3I = AIMAG(Z3)\n      DO 30 K=1,25\n        TRM1 = TRM1*CMPLX(Z3R/D1,Z3I/D1)\n        S1 = S1 + TRM1\n        TRM2 = TRM2*CMPLX(Z3R/D2,Z3I/D2)\n        S2 = S2 + TRM2\n        ATRM = ATRM*AZ3/AD\n        D1 = D1 + AK\n        D2 = D2 + BK\n        AD = AMIN1(D1,D2)\n        IF (ATRM.LT.TOL*AD) GO TO 40\n        AK = AK + 18.0E0\n        BK = BK + 18.0E0\n   30 CONTINUE\n   40 CONTINUE\n      IF (ID.EQ.1) GO TO 50\n      BI = S1*CMPLX(C1,0.0E0) + Z*S2*CMPLX(C2,0.0E0)\n      IF (KODE.EQ.1) RETURN\n      ZTA = Z*CSQRT(Z)*CMPLX(TTH,0.0E0)\n      AA = REAL(ZTA)\n      AA = -ABS(AA)\n      BI = BI*CMPLX(EXP(AA),0.0E0)\n      RETURN\n   50 CONTINUE\n      BI = S2*CMPLX(C2,0.0E0)\n      IF (AZ.GT.TOL) BI = BI + Z*Z*S1*CMPLX(C1/(1.0E0+FID),0.0E0)\n      IF (KODE.EQ.1) RETURN\n      ZTA = Z*CSQRT(Z)*CMPLX(TTH,0.0E0)\n      AA = REAL(ZTA)\n      AA = -ABS(AA)\n      BI = BI*CMPLX(EXP(AA),0.0E0)\n      RETURN\nC-----------------------------------------------------------------------\nC     CASE FOR CABS(Z).GT.1.0\nC-----------------------------------------------------------------------\n   60 CONTINUE\n      FNU = (1.0E0+FID)/3.0E0\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU.\nC-----------------------------------------------------------------------\n      K1 = I1MACH(12)\n      K2 = I1MACH(13)\n      R1M5 = R1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303E0*(FLOAT(K)*R1M5-3.0E0)\n      K1 = I1MACH(11) - 1\n      AA = R1M5*FLOAT(K1)\n      DIG = AMIN1(AA,18.0E0)\n      AA = AA*2.303E0\n      ALIM = ELIM + AMAX1(-AA,-41.45E0)\n      RL = 1.2E0*DIG + 3.0E0\n      FNUL = 10.0E0 + 6.0E0*(DIG-3.0E0)\nC-----------------------------------------------------------------------\nC     TEST FOR RANGE\nC-----------------------------------------------------------------------\n      AA=0.5E0/TOL\n      BB=FLOAT(I1MACH(9))*0.5E0\n      AA=AMIN1(AA,BB)\n      AA=AA**TTH\n      IF (AZ.GT.AA) GO TO 190\n      AA=SQRT(AA)\n      IF (AZ.GT.AA) IERR=3\n      CSQ=CSQRT(Z)\n      ZTA=Z*CSQ*CMPLX(TTH,0.0E0)\nC-----------------------------------------------------------------------\nC     RE(ZTA).LE.0 WHEN RE(Z).LT.0, ESPECIALLY WHEN IM(Z) IS SMALL\nC-----------------------------------------------------------------------\n      SFAC = 1.0E0\n      ZI = AIMAG(Z)\n      ZR = REAL(Z)\n      AK = AIMAG(ZTA)\n      IF (ZR.GE.0.0E0) GO TO 70\n      BK = REAL(ZTA)\n      CK = -ABS(BK)\n      ZTA = CMPLX(CK,AK)\n   70 CONTINUE\n      IF (ZI.EQ.0.0E0 .AND. ZR.LE.0.0E0) ZTA = CMPLX(0.0E0,AK)\n      AA = REAL(ZTA)\n      IF (KODE.EQ.2) GO TO 80\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST\nC-----------------------------------------------------------------------\n      BB = ABS(AA)\n      IF (BB.LT.ALIM) GO TO 80\n      BB = BB + 0.25E0*ALOG(AZ)\n      SFAC = TOL\n      IF (BB.GT.ELIM) GO TO 170\n   80 CONTINUE\n      FMR = 0.0E0\n      IF (AA.GE.0.0E0 .AND. ZR.GT.0.0E0) GO TO 90\n      FMR = PI\n      IF (ZI.LT.0.0E0) FMR = -PI\n      ZTA = -ZTA\n   90 CONTINUE\nC-----------------------------------------------------------------------\nC     AA=FACTOR FOR ANALYTIC CONTINUATION OF I(FNU,ZTA)\nC     KODE=2 RETURNS EXP(-ABS(XZTA))*I(FNU,ZTA) FROM CBINU\nC-----------------------------------------------------------------------\n      CALL CBINU(ZTA, FNU, KODE, 1, CY, NZ, RL, FNUL, TOL, ELIM, ALIM)\n      IF (NZ.LT.0) GO TO 180\n      AA = FMR*FNU\n      Z3 = CMPLX(SFAC,0.0E0)\n      S1 = CY(1)*CMPLX(COS(AA),SIN(AA))*Z3\n      FNU = (2.0E0-FID)/3.0E0\n      CALL CBINU(ZTA, FNU, KODE, 2, CY, NZ, RL, FNUL, TOL, ELIM, ALIM)\n      CY(1) = CY(1)*Z3\n      CY(2) = CY(2)*Z3\nC-----------------------------------------------------------------------\nC     BACKWARD RECUR ONE STEP FOR ORDERS -1/3 OR -2/3\nC-----------------------------------------------------------------------\n      S2 = CY(1)*CMPLX(FNU+FNU,0.0E0)/ZTA + CY(2)\n      AA = FMR*(FNU-1.0E0)\n      S1 = (S1+S2*CMPLX(COS(AA),SIN(AA)))*CMPLX(COEF,0.0E0)\n      IF (ID.EQ.1) GO TO 100\n      S1 = CSQ*S1\n      BI = S1*CMPLX(1.0E0/SFAC,0.0E0)\n      RETURN\n  100 CONTINUE\n      S1 = Z*S1\n      BI = S1*CMPLX(1.0E0/SFAC,0.0E0)\n      RETURN\n  110 CONTINUE\n      AA = C1*(1.0E0-FID) + FID*C2\n      BI = CMPLX(AA,0.0E0)\n      RETURN\n  170 CONTINUE\n      NZ=0\n      IERR=2\n      RETURN\n  180 CONTINUE\n      IF(NZ.EQ.(-1)) GO TO 170\n      NZ=0\n      IERR=5\n      RETURN\n  190 CONTINUE\n      IERR=4\n      NZ=0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbknu.f",
    "content": "      SUBROUTINE CBKNU(Z, FNU, KODE, N, Y, NZ, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  CBKNU\nC***REFER TO  CBESI,CBESK,CAIRY,CBESH\nC\nC     CBKNU COMPUTES THE K BESSEL FUNCTION IN THE RIGHT HALF Z PLANE\nC\nC***ROUTINES CALLED  CKSCL,CSHCH,GAMLN,I1MACH,R1MACH,CUCHK\nC***END PROLOGUE  CBKNU\nC\n      COMPLEX CCH, CK, COEF, CONE, CRSC, CS, CSCL, CSH, CSR, CSS, CTWO,\n     * CZ, CZERO, F, FMU, P, PT, P1, P2, Q, RZ, SMU, ST, S1, S2, Y, Z,\n     * ZD, CELM, CY\n      REAL AA, AK, ALIM, ASCLE, A1, A2, BB, BK, BRY, CAZ, CC, DNU,\n     * DNU2, ELIM, ETEST, FC, FHS, FK, FKS, FNU, FPI, G1, G2, HPI, PI,\n     * P2I, P2M, P2R, RK, RTHPI, R1, S, SPI, TM, TOL, TTH, T1, T2, XX,\n     * YY, GAMLN, R1MACH, HELIM, ELM, XD, YD, ALAS, AS\n      INTEGER I, IDUM, IFLAG, INU, K, KFLAG, KK, KMAX, KODE, KODED, N,\n     * NZ, I1MACH, NW, J, IC, INUB\n      DIMENSION BRY(3), CC(8), CSS(3), CSR(3), Y(N), CY(2)\nC\n      DATA KMAX / 30 /\n      DATA R1 / 2.0E0 /\n      DATA CZERO,CONE,CTWO /(0.0E0,0.0E0),(1.0E0,0.0E0),(2.0E0,0.0E0)/\nC\n      DATA PI, RTHPI, SPI ,HPI, FPI, TTH /\n     1     3.14159265358979324E0,       1.25331413731550025E0,\n     2     1.90985931710274403E0,       1.57079632679489662E0,\n     3     1.89769999331517738E0,       6.66666666666666666E-01/\nC\n      DATA CC(1), CC(2), CC(3), CC(4), CC(5), CC(6), CC(7), CC(8)/\n     1     5.77215664901532861E-01,    -4.20026350340952355E-02,\n     2    -4.21977345555443367E-02,     7.21894324666309954E-03,\n     3    -2.15241674114950973E-04,    -2.01348547807882387E-05,\n     4     1.13302723198169588E-06,     6.11609510448141582E-09/\nC\n      XX = REAL(Z)\n      YY = AIMAG(Z)\n      CAZ = CABS(Z)\n      CSCL = CMPLX(1.0E0/TOL,0.0E0)\n      CRSC = CMPLX(TOL,0.0E0)\n      CSS(1) = CSCL\n      CSS(2) = CONE\n      CSS(3) = CRSC\n      CSR(1) = CRSC\n      CSR(2) = CONE\n      CSR(3) = CSCL\n      BRY(1) = 1.0E+3*R1MACH(1)/TOL\n      BRY(2) = 1.0E0/BRY(1)\n      BRY(3) = R1MACH(2)\n      NZ = 0\n      IFLAG = 0\n      KODED = KODE\n      RZ = CTWO/Z\n      INU = INT(FNU+0.5E0)\n      DNU = FNU - FLOAT(INU)\n      IF (ABS(DNU).EQ.0.5E0) GO TO 110\n      DNU2 = 0.0E0\n      IF (ABS(DNU).GT.TOL) DNU2 = DNU*DNU\n      IF (CAZ.GT.R1) GO TO 110\nC-----------------------------------------------------------------------\nC     SERIES FOR CABS(Z).LE.R1\nC-----------------------------------------------------------------------\n      FC = 1.0E0\n      SMU = CLOG(RZ)\n      FMU = SMU*CMPLX(DNU,0.0E0)\n      CALL CSHCH(FMU, CSH, CCH)\n      IF (DNU.EQ.0.0E0) GO TO 10\n      FC = DNU*PI\n      FC = FC/SIN(FC)\n      SMU = CSH*CMPLX(1.0E0/DNU,0.0E0)\n   10 CONTINUE\n      A2 = 1.0E0 + DNU\nC-----------------------------------------------------------------------\nC     GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU)\nC-----------------------------------------------------------------------\n      T2 = EXP(-GAMLN(A2,IDUM))\n      T1 = 1.0E0/(T2*FC)\n      IF (ABS(DNU).GT.0.1E0) GO TO 40\nC-----------------------------------------------------------------------\nC     SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU)\nC-----------------------------------------------------------------------\n      AK = 1.0E0\n      S = CC(1)\n      DO 20 K=2,8\n        AK = AK*DNU2\n        TM = CC(K)*AK\n        S = S + TM\n        IF (ABS(TM).LT.TOL) GO TO 30\n   20 CONTINUE\n   30 G1 = -S\n      GO TO 50\n   40 CONTINUE\n      G1 = (T1-T2)/(DNU+DNU)\n   50 CONTINUE\n      G2 = 0.5E0*(T1+T2)*FC\n      G1 = G1*FC\n      F = CMPLX(G1,0.0E0)*CCH + SMU*CMPLX(G2,0.0E0)\n      PT = CEXP(FMU)\n      P = CMPLX(0.5E0/T2,0.0E0)*PT\n      Q = CMPLX(0.5E0/T1,0.0E0)/PT\n      S1 = F\n      S2 = P\n      AK = 1.0E0\n      A1 = 1.0E0\n      CK = CONE\n      BK = 1.0E0 - DNU2\n      IF (INU.GT.0 .OR. N.GT.1) GO TO 80\nC-----------------------------------------------------------------------\nC     GENERATE K(FNU,Z), 0.0D0 .LE. FNU .LT. 0.5D0 AND N=1\nC-----------------------------------------------------------------------\n      IF (CAZ.LT.TOL) GO TO 70\n      CZ = Z*Z*CMPLX(0.25E0,0.0E0)\n      T1 = 0.25E0*CAZ*CAZ\n   60 CONTINUE\n      F = (F*CMPLX(AK,0.0E0)+P+Q)*CMPLX(1.0E0/BK,0.0E0)\n      P = P*CMPLX(1.0E0/(AK-DNU),0.0E0)\n      Q = Q*CMPLX(1.0E0/(AK+DNU),0.0E0)\n      RK = 1.0E0/AK\n      CK = CK*CZ*CMPLX(RK,0.0)\n      S1 = S1 + CK*F\n      A1 = A1*T1*RK\n      BK = BK + AK + AK + 1.0E0\n      AK = AK + 1.0E0\n      IF (A1.GT.TOL) GO TO 60\n   70 CONTINUE\n      Y(1) = S1\n      IF (KODED.EQ.1) RETURN\n      Y(1) = S1*CEXP(Z)\n      RETURN\nC-----------------------------------------------------------------------\nC     GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE\nC-----------------------------------------------------------------------\n   80 CONTINUE\n      IF (CAZ.LT.TOL) GO TO 100\n      CZ = Z*Z*CMPLX(0.25E0,0.0E0)\n      T1 = 0.25E0*CAZ*CAZ\n   90 CONTINUE\n      F = (F*CMPLX(AK,0.0E0)+P+Q)*CMPLX(1.0E0/BK,0.0E0)\n      P = P*CMPLX(1.0E0/(AK-DNU),0.0E0)\n      Q = Q*CMPLX(1.0E0/(AK+DNU),0.0E0)\n      RK = 1.0E0/AK\n      CK = CK*CZ*CMPLX(RK,0.0E0)\n      S1 = S1 + CK*F\n      S2 = S2 + CK*(P-F*CMPLX(AK,0.0E0))\n      A1 = A1*T1*RK\n      BK = BK + AK + AK + 1.0E0\n      AK = AK + 1.0E0\n      IF (A1.GT.TOL) GO TO 90\n  100 CONTINUE\n      KFLAG = 2\n      BK = REAL(SMU)\n      A1 = FNU + 1.0E0\n      AK = A1*ABS(BK)\n      IF (AK.GT.ALIM) KFLAG = 3\n      P2 = S2*CSS(KFLAG)\n      S2 = P2*RZ\n      S1 = S1*CSS(KFLAG)\n      IF (KODED.EQ.1) GO TO 210\n      F = CEXP(Z)\n      S1 = S1*F\n      S2 = S2*F\n      GO TO 210\nC-----------------------------------------------------------------------\nC     IFLAG=0 MEANS NO UNDERFLOW OCCURRED\nC     IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH\nC     KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD\nC     RECURSION\nC-----------------------------------------------------------------------\n  110 CONTINUE\n      COEF = CMPLX(RTHPI,0.0E0)/CSQRT(Z)\n      KFLAG = 2\n      IF (KODED.EQ.2) GO TO 120\n      IF (XX.GT.ALIM) GO TO 290\nC     BLANK LINE\n      A1 = EXP(-XX)*REAL(CSS(KFLAG))\n      PT = CMPLX(A1,0.0E0)*CMPLX(COS(YY),-SIN(YY))\n      COEF = COEF*PT\n  120 CONTINUE\n      IF (ABS(DNU).EQ.0.5E0) GO TO 300\nC-----------------------------------------------------------------------\nC     MILLER ALGORITHM FOR CABS(Z).GT.R1\nC-----------------------------------------------------------------------\n      AK = COS(PI*DNU)\n      AK = ABS(AK)\n      IF (AK.EQ.0.0E0) GO TO 300\n      FHS = ABS(0.25E0-DNU2)\n      IF (FHS.EQ.0.0E0) GO TO 300\nC-----------------------------------------------------------------------\nC     COMPUTE R2=F(E). IF CABS(Z).GE.R2, USE FORWARD RECURRENCE TO\nC     DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON\nC     12.LE.E.LE.60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(11))=\nC     TOL WHERE B IS THE BASE OF THE ARITHMETIC.\nC-----------------------------------------------------------------------\n      T1 = FLOAT(I1MACH(11)-1)*R1MACH(5)*3.321928094E0\n      T1 = AMAX1(T1,12.0E0)\n      T1 = AMIN1(T1,60.0E0)\n      T2 = TTH*T1 - 6.0E0\n      IF (XX.NE.0.0E0) GO TO 130\n      T1 = HPI\n      GO TO 140\n  130 CONTINUE\n      T1 = ATAN(YY/XX)\n      T1 = ABS(T1)\n  140 CONTINUE\n      IF (T2.GT.CAZ) GO TO 170\nC-----------------------------------------------------------------------\nC     FORWARD RECURRENCE LOOP WHEN CABS(Z).GE.R2\nC-----------------------------------------------------------------------\n      ETEST = AK/(PI*CAZ*TOL)\n      FK = 1.0E0\n      IF (ETEST.LT.1.0E0) GO TO 180\n      FKS = 2.0E0\n      RK = CAZ + CAZ + 2.0E0\n      A1 = 0.0E0\n      A2 = 1.0E0\n      DO 150 I=1,KMAX\n        AK = FHS/FKS\n        BK = RK/(FK+1.0E0)\n        TM = A2\n        A2 = BK*A2 - AK*A1\n        A1 = TM\n        RK = RK + 2.0E0\n        FKS = FKS + FK + FK + 2.0E0\n        FHS = FHS + FK + FK\n        FK = FK + 1.0E0\n        TM = ABS(A2)*FK\n        IF (ETEST.LT.TM) GO TO 160\n  150 CONTINUE\n      GO TO 310\n  160 CONTINUE\n      FK = FK + SPI*T1*SQRT(T2/CAZ)\n      FHS = ABS(0.25E0-DNU2)\n      GO TO 180\n  170 CONTINUE\nC-----------------------------------------------------------------------\nC     COMPUTE BACKWARD INDEX K FOR CABS(Z).LT.R2\nC-----------------------------------------------------------------------\n      A2 = SQRT(CAZ)\n      AK = FPI*AK/(TOL*SQRT(A2))\n      AA = 3.0E0*T1/(1.0E0+CAZ)\n      BB = 14.7E0*T1/(28.0E0+CAZ)\n      AK = (ALOG(AK)+CAZ*COS(AA)/(1.0E0+0.008E0*CAZ))/COS(BB)\n      FK = 0.12125E0*AK*AK/CAZ + 1.5E0\n  180 CONTINUE\n      K = INT(FK)\nC-----------------------------------------------------------------------\nC     BACKWARD RECURRENCE LOOP FOR MILLER ALGORITHM\nC-----------------------------------------------------------------------\n      FK = FLOAT(K)\n      FKS = FK*FK\n      P1 = CZERO\n      P2 = CMPLX(TOL,0.0E0)\n      CS = P2\n      DO 190 I=1,K\n        A1 = FKS - FK\n        A2 = (FKS+FK)/(A1+FHS)\n        RK = 2.0E0/(FK+1.0E0)\n        T1 = (FK+XX)*RK\n        T2 = YY*RK\n        PT = P2\n        P2 = (P2*CMPLX(T1,T2)-P1)*CMPLX(A2,0.0E0)\n        P1 = PT\n        CS = CS + P2\n        FKS = A1 - FK + 1.0E0\n        FK = FK - 1.0E0\n  190 CONTINUE\nC-----------------------------------------------------------------------\nC     COMPUTE (P2/CS)=(P2/CABS(CS))*(CONJG(CS)/CABS(CS)) FOR BETTER\nC     SCALING\nC-----------------------------------------------------------------------\n      TM = CABS(CS)\n      PT = CMPLX(1.0E0/TM,0.0E0)\n      S1 = PT*P2\n      CS = CONJG(CS)*PT\n      S1 = COEF*S1*CS\n      IF (INU.GT.0 .OR. N.GT.1) GO TO 200\n      ZD = Z\n      IF(IFLAG.EQ.1) GO TO 270\n      GO TO 240\n  200 CONTINUE\nC-----------------------------------------------------------------------\nC     COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING\nC-----------------------------------------------------------------------\n      TM = CABS(P2)\n      PT = CMPLX(1.0E0/TM,0.0E0)\n      P1 = PT*P1\n      P2 = CONJG(P2)*PT\n      PT = P1*P2\n      S2 = S1*(CONE+(CMPLX(DNU+0.5E0,0.0E0)-PT)/Z)\nC-----------------------------------------------------------------------\nC     FORWARD RECURSION ON THE THREE TERM RECURSION RELATION WITH\nC     SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3\nC-----------------------------------------------------------------------\n  210 CONTINUE\n      CK = CMPLX(DNU+1.0E0,0.0E0)*RZ\n      IF (N.EQ.1) INU = INU - 1\n      IF (INU.GT.0) GO TO 220\n      IF (N.EQ.1) S1=S2\n      ZD = Z\n      IF(IFLAG.EQ.1) GO TO 270\n      GO TO 240\n  220 CONTINUE\n      INUB = 1\n      IF (IFLAG.EQ.1) GO TO 261\n  225 CONTINUE\n      P1 = CSR(KFLAG)\n      ASCLE = BRY(KFLAG)\n      DO 230 I=INUB,INU\n        ST = S2\n        S2 = CK*S2 + S1\n        S1 = ST\n        CK = CK + RZ\n        IF (KFLAG.GE.3) GO TO 230\n        P2 = S2*P1\n        P2R = REAL(P2)\n        P2I = AIMAG(P2)\n        P2R = ABS(P2R)\n        P2I = ABS(P2I)\n        P2M = AMAX1(P2R,P2I)\n        IF (P2M.LE.ASCLE) GO TO 230\n        KFLAG = KFLAG + 1\n        ASCLE = BRY(KFLAG)\n        S1 = S1*P1\n        S2 = P2\n        S1 = S1*CSS(KFLAG)\n        S2 = S2*CSS(KFLAG)\n        P1 = CSR(KFLAG)\n  230 CONTINUE\n      IF (N.EQ.1) S1 = S2\n  240 CONTINUE\n      Y(1) = S1*CSR(KFLAG)\n      IF (N.EQ.1) RETURN\n      Y(2) = S2*CSR(KFLAG)\n      IF (N.EQ.2) RETURN\n      KK = 2\n  250 CONTINUE\n      KK = KK + 1\n      IF (KK.GT.N) RETURN\n      P1 = CSR(KFLAG)\n      ASCLE = BRY(KFLAG)\n      DO 260 I=KK,N\n        P2 = S2\n        S2 = CK*S2 + S1\n        S1 = P2\n        CK = CK + RZ\n        P2 = S2*P1\n        Y(I) = P2\n        IF (KFLAG.GE.3) GO TO 260\n        P2R = REAL(P2)\n        P2I = AIMAG(P2)\n        P2R = ABS(P2R)\n        P2I = ABS(P2I)\n        P2M = AMAX1(P2R,P2I)\n        IF (P2M.LE.ASCLE) GO TO 260\n        KFLAG = KFLAG + 1\n        ASCLE = BRY(KFLAG)\n        S1 = S1*P1\n        S2 = P2\n        S1 = S1*CSS(KFLAG)\n        S2 = S2*CSS(KFLAG)\n        P1 = CSR(KFLAG)\n  260 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW\nC-----------------------------------------------------------------------\n  261 CONTINUE\n      HELIM = 0.5E0*ELIM\n      ELM = EXP(-ELIM)\n      CELM = CMPLX(ELM,0.0)\n      ASCLE = BRY(1)\n      ZD = Z\n      XD = XX\n      YD = YY\n      IC = -1\n      J = 2\n      DO 262 I=1,INU\n        ST = S2\n        S2 = CK*S2+S1\n        S1 = ST\n        CK = CK+RZ\n        AS = CABS(S2)\n        ALAS = ALOG(AS)\n        P2R = -XD+ALAS\n        IF(P2R.LT.(-ELIM)) GO TO 263\n        P2 = -ZD+CLOG(S2)\n        P2R = REAL(P2)\n        P2I = AIMAG(P2)\n        P2M = EXP(P2R)/TOL\n        P1 = CMPLX(P2M,0.0E0)*CMPLX(COS(P2I),SIN(P2I))\n        CALL CUCHK(P1,NW,ASCLE,TOL)\n        IF(NW.NE.0) GO TO 263\n        J=3-J\n        CY(J) = P1\n        IF(IC.EQ.(I-1)) GO TO 264\n        IC = I\n        GO TO 262\n  263   CONTINUE\n        IF(ALAS.LT.HELIM) GO TO 262\n        XD = XD-ELIM\n        S1 = S1*CELM\n        S2 = S2*CELM\n        ZD = CMPLX(XD,YD)\n  262 CONTINUE\n      IF(N.EQ.1) S1 = S2\n      GO TO 270\n  264 CONTINUE\n      KFLAG = 1\n      INUB = I+1\n      S2 = CY(J)\n      J = 3 - J\n      S1 = CY(J)\n      IF(INUB.LE.INU) GO TO 225\n      IF(N.EQ.1) S1 = S2\n      GO TO 240\n  270 CONTINUE\n      Y(1) = S1\n      IF (N.EQ.1) GO TO 280\n      Y(2) = S2\n  280 CONTINUE\n      ASCLE = BRY(1)\n      CALL CKSCL(ZD, FNU, N, Y, NZ, RZ, ASCLE, TOL, ELIM)\n      INU = N - NZ\n      IF (INU.LE.0) RETURN\n      KK = NZ + 1\n      S1 = Y(KK)\n      Y(KK) = S1*CSR(1)\n      IF (INU.EQ.1) RETURN\n      KK = NZ + 2\n      S2 = Y(KK)\n      Y(KK) = S2*CSR(1)\n      IF (INU.EQ.2) RETURN\n      T2 = FNU + FLOAT(KK-1)\n      CK = CMPLX(T2,0.0E0)*RZ\n      KFLAG = 1\n      GO TO 250\n  290 CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE BY EXP(Z), IFLAG = 1 CASES\nC-----------------------------------------------------------------------\n      KODED = 2\n      IFLAG = 1\n      KFLAG = 2\n      GO TO 120\nC-----------------------------------------------------------------------\nC     FNU=HALF ODD INTEGER CASE, DNU=-0.5\nC-----------------------------------------------------------------------\n  300 CONTINUE\n      S1 = COEF\n      S2 = COEF\n      GO TO 210\n  310 CONTINUE\n      NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbuni.f",
    "content": "      SUBROUTINE CBUNI(Z, FNU, KODE, N, Y, NZ, NUI, NLAST, FNUL, TOL,\n     * ELIM, ALIM)\nC***BEGIN PROLOGUE  CBUNI\nC***REFER TO  CBESI,CBESK\nC\nC     CBUNI COMPUTES THE I BESSEL FUNCTION FOR LARGE CABS(Z).GT.\nC     FNUL AND FNU+N-1.LT.FNUL. THE ORDER IS INCREASED FROM\nC     FNU+N-1 GREATER THAN FNUL BY ADDING NUI AND COMPUTING\nC     ACCORDING TO THE UNIFORM ASYMPTOTIC EXPANSION FOR I(FNU,Z)\nC     ON IFORM=1 AND THE EXPANSION FOR J(FNU,Z) ON IFORM=2\nC\nC***ROUTINES CALLED  CUNI1,CUNI2,R1MACH\nC***END PROLOGUE  CBUNI\n      COMPLEX CSCL, CSCR, CY, RZ, ST, S1, S2, Y, Z\n      REAL ALIM, AX, AY, DFNU, ELIM, FNU, FNUI, FNUL, GNU, TOL, XX, YY,\n     * ASCLE, BRY, STR, STI, STM, R1MACH\n      INTEGER I, IFLAG, IFORM, K, KODE, N, NL, NLAST, NUI, NW, NZ\n      DIMENSION Y(N), CY(2), BRY(3)\n      NZ = 0\n      XX = REAL(Z)\n      YY = AIMAG(Z)\n      AX = ABS(XX)*1.7321E0\n      AY = ABS(YY)\n      IFORM = 1\n      IF (AY.GT.AX) IFORM = 2\n      IF (NUI.EQ.0) GO TO 60\n      FNUI = FLOAT(NUI)\n      DFNU = FNU + FLOAT(N-1)\n      GNU = DFNU + FNUI\n      IF (IFORM.EQ.2) GO TO 10\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR I(FNU,Z) FOR LARGE FNU APPLIED IN\nC     -PI/3.LE.ARG(Z).LE.PI/3\nC-----------------------------------------------------------------------\n      CALL CUNI1(Z, GNU, KODE, 2, CY, NW, NLAST, FNUL, TOL, ELIM, ALIM)\n      GO TO 20\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR J(FNU,Z*EXP(M*HPI)) FOR LARGE FNU\nC     APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I\nC     AND HPI=PI/2\nC-----------------------------------------------------------------------\n      CALL CUNI2(Z, GNU, KODE, 2, CY, NW, NLAST, FNUL, TOL, ELIM, ALIM)\n   20 CONTINUE\n      IF (NW.LT.0) GO TO 50\n      IF (NW.NE.0) GO TO 90\n      AY = CABS(CY(1))\nC----------------------------------------------------------------------\nC     SCALE BACKWARD RECURRENCE, BRY(3) IS DEFINED BUT NEVER USED\nC----------------------------------------------------------------------\n      BRY(1) = 1.0E+3*R1MACH(1)/TOL\n      BRY(2) = 1.0E0/BRY(1)\n      BRY(3) = BRY(2)\n      IFLAG = 2\n      ASCLE = BRY(2)\n      AX = 1.0E0\n      CSCL = CMPLX(AX,0.0E0)\n      IF (AY.GT.BRY(1)) GO TO 21\n      IFLAG = 1\n      ASCLE = BRY(1)\n      AX = 1.0E0/TOL\n      CSCL = CMPLX(AX,0.0E0)\n      GO TO 25\n   21 CONTINUE\n      IF (AY.LT.BRY(2)) GO TO 25\n      IFLAG = 3\n      ASCLE = BRY(3)\n      AX = TOL\n      CSCL = CMPLX(AX,0.0E0)\n   25 CONTINUE\n      AY = 1.0E0/AX\n      CSCR = CMPLX(AY,0.0E0)\n      S1 = CY(2)*CSCL\n      S2 = CY(1)*CSCL\n      RZ = CMPLX(2.0E0,0.0E0)/Z\n      DO 30 I=1,NUI\n        ST = S2\n        S2 = CMPLX(DFNU+FNUI,0.0E0)*RZ*S2 + S1\n        S1 = ST\n        FNUI = FNUI - 1.0E0\n        IF (IFLAG.GE.3) GO TO 30\n        ST = S2*CSCR\n        STR = REAL(ST)\n        STI = AIMAG(ST)\n        STR = ABS(STR)\n        STI = ABS(STI)\n        STM = AMAX1(STR,STI)\n        IF (STM.LE.ASCLE) GO TO 30\n        IFLAG = IFLAG+1\n        ASCLE = BRY(IFLAG)\n        S1 = S1*CSCR\n        S2 = ST\n        AX = AX*TOL\n        AY = 1.0E0/AX\n        CSCL = CMPLX(AX,0.0E0)\n        CSCR = CMPLX(AY,0.0E0)\n        S1 = S1*CSCL\n        S2 = S2*CSCL\n   30 CONTINUE\n      Y(N) = S2*CSCR\n      IF (N.EQ.1) RETURN\n      NL = N - 1\n      FNUI = FLOAT(NL)\n      K = NL\n      DO 40 I=1,NL\n        ST = S2\n        S2 = CMPLX(FNU+FNUI,0.0E0)*RZ*S2 + S1\n        S1 = ST\n        ST = S2*CSCR\n        Y(K) = ST\n        FNUI = FNUI - 1.0E0\n        K = K - 1\n        IF (IFLAG.GE.3) GO TO 40\n        STR = REAL(ST)\n        STI = AIMAG(ST)\n        STR = ABS(STR)\n        STI = ABS(STI)\n        STM = AMAX1(STR,STI)\n        IF (STM.LE.ASCLE) GO TO 40\n        IFLAG = IFLAG+1\n        ASCLE = BRY(IFLAG)\n        S1 = S1*CSCR\n        S2 = ST\n        AX = AX*TOL\n        AY = 1.0E0/AX\n        CSCL = CMPLX(AX,0.0E0)\n        CSCR = CMPLX(AY,0.0E0)\n        S1 = S1*CSCL\n        S2 = S2*CSCL\n   40 CONTINUE\n      RETURN\n   50 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n   60 CONTINUE\n      IF (IFORM.EQ.2) GO TO 70\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR I(FNU,Z) FOR LARGE FNU APPLIED IN\nC     -PI/3.LE.ARG(Z).LE.PI/3\nC-----------------------------------------------------------------------\n      CALL CUNI1(Z, FNU, KODE, N, Y, NW, NLAST, FNUL, TOL, ELIM, ALIM)\n      GO TO 80\n   70 CONTINUE\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR J(FNU,Z*EXP(M*HPI)) FOR LARGE FNU\nC     APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I\nC     AND HPI=PI/2\nC-----------------------------------------------------------------------\n      CALL CUNI2(Z, FNU, KODE, N, Y, NW, NLAST, FNUL, TOL, ELIM, ALIM)\n   80 CONTINUE\n      IF (NW.LT.0) GO TO 50\n      NZ = NW\n      RETURN\n   90 CONTINUE\n      NLAST = N\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cbunk.f",
    "content": "      SUBROUTINE CBUNK(Z, FNU, KODE, MR, N, Y, NZ, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  CBUNK\nC***REFER TO  CBESK,CBESH\nC\nC     CBUNK COMPUTES THE K BESSEL FUNCTION FOR FNU.GT.FNUL.\nC     ACCORDING TO THE UNIFORM ASYMPTOTIC EXPANSION FOR K(FNU,Z)\nC     IN CUNK1 AND THE EXPANSION FOR H(2,FNU,Z) IN CUNK2\nC\nC***ROUTINES CALLED  CUNK1,CUNK2\nC***END PROLOGUE  CBUNK\n      COMPLEX Y, Z\n      REAL ALIM, AX, AY, ELIM, FNU, TOL, XX, YY\n      INTEGER KODE, MR, N, NZ\n      DIMENSION Y(N)\n      NZ = 0\n      XX = REAL(Z)\n      YY = AIMAG(Z)\n      AX = ABS(XX)*1.7321E0\n      AY = ABS(YY)\n      IF (AY.GT.AX) GO TO 10\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR K(FNU,Z) FOR LARGE FNU APPLIED IN\nC     -PI/3.LE.ARG(Z).LE.PI/3\nC-----------------------------------------------------------------------\n      CALL CUNK1(Z, FNU, KODE, MR, N, Y, NZ, TOL, ELIM, ALIM)\n      GO TO 20\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR H(2,FNU,Z*EXP(M*HPI)) FOR LARGE FNU\nC     APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I\nC     AND HPI=PI/2\nC-----------------------------------------------------------------------\n      CALL CUNK2(Z, FNU, KODE, MR, N, Y, NZ, TOL, ELIM, ALIM)\n   20 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/ckscl.f",
    "content": "      SUBROUTINE CKSCL(ZR, FNU, N, Y, NZ, RZ, ASCLE, TOL, ELIM)\nC***BEGIN PROLOGUE  CKSCL\nC***REFER TO  CBKNU,CUNK1,CUNK2\nC\nC     SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE\nC     ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN\nC     RETURN WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL.\nC\nC***ROUTINES CALLED  CUCHK\nC***END PROLOGUE  CKSCL\n      COMPLEX CK, CS, CY, CZERO, RZ, S1, S2, Y, ZR, ZD, CELM\n      REAL AA, ASCLE, ACS, AS, CSI, CSR, ELIM, FN, FNU, TOL, XX, ZRI,\n     * ELM, ALAS, HELIM\n      INTEGER I, IC, K, KK, N, NN, NW, NZ\n      DIMENSION Y(N), CY(2)\n      DATA CZERO / (0.0E0,0.0E0) /\nC\n      NZ = 0\n      IC = 0\n      XX = REAL(ZR)\n      NN = MIN0(2,N)\n      DO 10 I=1,NN\n        S1 = Y(I)\n        CY(I) = S1\n        AS = CABS(S1)\n        ACS = -XX + ALOG(AS)\n        NZ = NZ + 1\n        Y(I) = CZERO\n        IF (ACS.LT.(-ELIM)) GO TO 10\n        CS = -ZR + CLOG(S1)\n        CSR = REAL(CS)\n        CSI = AIMAG(CS)\n        AA = EXP(CSR)/TOL\n        CS = CMPLX(AA,0.0E0)*CMPLX(COS(CSI),SIN(CSI))\n        CALL CUCHK(CS, NW, ASCLE, TOL)\n        IF (NW.NE.0) GO TO 10\n        Y(I) = CS\n        NZ = NZ - 1\n        IC = I\n   10 CONTINUE\n      IF (N.EQ.1) RETURN\n      IF (IC.GT.1) GO TO 20\n      Y(1) = CZERO\n      NZ = 2\n   20 CONTINUE\n      IF (N.EQ.2) RETURN\n      IF (NZ.EQ.0) RETURN\n      FN = FNU + 1.0E0\n      CK = CMPLX(FN,0.0E0)*RZ\n      S1 = CY(1)\n      S2 = CY(2)\n      HELIM = 0.5E0*ELIM\n      ELM = EXP(-ELIM)\n      CELM = CMPLX(ELM,0.0E0)\n      ZRI =AIMAG(ZR)\n      ZD = ZR\nC\nC     FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF\nC     S2 GETS LARGER THAN EXP(ELIM/2)\nC\n      DO 30 I=3,N\n        KK = I\n        CS = S2\n        S2 = CK*S2 + S1\n        S1 = CS\n        CK = CK + RZ\n        AS = CABS(S2)\n        ALAS = ALOG(AS)\n        ACS = -XX + ALAS\n        NZ = NZ + 1\n        Y(I) = CZERO\n        IF (ACS.LT.(-ELIM)) GO TO 25\n        CS = -ZD + CLOG(S2)\n        CSR = REAL(CS)\n        CSI = AIMAG(CS)\n        AA = EXP(CSR)/TOL\n        CS = CMPLX(AA,0.0E0)*CMPLX(COS(CSI),SIN(CSI))\n        CALL CUCHK(CS, NW, ASCLE, TOL)\n        IF (NW.NE.0) GO TO 25\n        Y(I) = CS\n        NZ = NZ - 1\n        IF (IC.EQ.(KK-1)) GO TO 40\n        IC = KK\n        GO TO 30\n   25   CONTINUE\n        IF(ALAS.LT.HELIM) GO TO 30\n        XX = XX-ELIM\n        S1 = S1*CELM\n        S2 = S2*CELM\n        ZD = CMPLX(XX,ZRI)\n   30 CONTINUE\n      NZ = N\n      IF(IC.EQ.N) NZ=N-1\n      GO TO 45\n   40 CONTINUE\n      NZ = KK - 2\n   45 CONTINUE\n      DO 50 K=1,NZ\n        Y(K) = CZERO\n   50 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cmlri.f",
    "content": "      SUBROUTINE CMLRI(Z, FNU, KODE, N, Y, NZ, TOL)\nC***BEGIN PROLOGUE  CMLRI\nC***REFER TO  CBESI,CBESK\nC\nC     CMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z).GE.0.0 BY THE\nC     MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES.\nC\nC***ROUTINES CALLED  GAMLN,R1MACH\nC***END PROLOGUE  CMLRI\n      COMPLEX CK, CNORM, CONE, CTWO, CZERO, PT, P1, P2, RZ, SUM, Y, Z\n      REAL ACK, AK, AP, AT, AZ, BK, FKAP, FKK, FLAM, FNF, FNU, RHO,\n     * RHO2, SCLE, TFNF, TOL, TST, X, GAMLN, R1MACH\n      INTEGER I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, KODE, M, N\n      DIMENSION Y(N)\n      DATA CZERO,CONE,CTWO /(0.0E0,0.0E0),(1.0E0,0.0E0),(2.0E0,0.0E0)/\n      SCLE = 1.0E+3*R1MACH(1)/TOL\n      NZ=0\n      AZ = CABS(Z)\n      X = REAL(Z)\n      IAZ = INT(AZ)\n      IFNU = INT(FNU)\n      INU = IFNU + N - 1\n      AT = FLOAT(IAZ) + 1.0E0\n      CK = CMPLX(AT,0.0E0)/Z\n      RZ = CTWO/Z\n      P1 = CZERO\n      P2 = CONE\n      ACK = (AT+1.0E0)/AZ\n      RHO = ACK + SQRT(ACK*ACK-1.0E0)\n      RHO2 = RHO*RHO\n      TST = (RHO2+RHO2)/((RHO2-1.0E0)*(RHO-1.0E0))\n      TST = TST/TOL\nC-----------------------------------------------------------------------\nC     COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES\nC-----------------------------------------------------------------------\n      AK = AT\n      DO 10 I=1,80\n        PT = P2\n        P2 = P1 - CK*P2\n        P1 = PT\n        CK = CK + RZ\n        AP = CABS(P2)\n        IF (AP.GT.TST*AK*AK) GO TO 20\n        AK = AK + 1.0E0\n   10 CONTINUE\n      GO TO 110\n   20 CONTINUE\n      I = I + 1\n      K = 0\n      IF (INU.LT.IAZ) GO TO 40\nC-----------------------------------------------------------------------\nC     COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS\nC-----------------------------------------------------------------------\n      P1 = CZERO\n      P2 = CONE\n      AT = FLOAT(INU) + 1.0E0\n      CK = CMPLX(AT,0.0E0)/Z\n      ACK = AT/AZ\n      TST = SQRT(ACK/TOL)\n      ITIME = 1\n      DO 30 K=1,80\n        PT = P2\n        P2 = P1 - CK*P2\n        P1 = PT\n        CK = CK + RZ\n        AP = CABS(P2)\n        IF (AP.LT.TST) GO TO 30\n        IF (ITIME.EQ.2) GO TO 40\n        ACK = CABS(CK)\n        FLAM = ACK + SQRT(ACK*ACK-1.0E0)\n        FKAP = AP/CABS(P1)\n        RHO = AMIN1(FLAM,FKAP)\n        TST = TST*SQRT(RHO/(RHO*RHO-1.0E0))\n        ITIME = 2\n   30 CONTINUE\n      GO TO 110\n   40 CONTINUE\nC-----------------------------------------------------------------------\nC     BACKWARD RECURRENCE AND SUM NORMALIZING RELATION\nC-----------------------------------------------------------------------\n      K = K + 1\n      KK = MAX0(I+IAZ,K+INU)\n      FKK = FLOAT(KK)\n      P1 = CZERO\nC-----------------------------------------------------------------------\nC     SCALE P2 AND SUM BY SCLE\nC-----------------------------------------------------------------------\n      P2 = CMPLX(SCLE,0.0E0)\n      FNF = FNU - FLOAT(IFNU)\n      TFNF = FNF + FNF\n      BK = GAMLN(FKK+TFNF+1.0E0,IDUM) - GAMLN(FKK+1.0E0,IDUM)\n     *     -GAMLN(TFNF+1.0E0,IDUM)\n      BK = EXP(BK)\n      SUM = CZERO\n      KM = KK - INU\n      DO 50 I=1,KM\n        PT = P2\n        P2 = P1 + CMPLX(FKK+FNF,0.0E0)*RZ*P2\n        P1 = PT\n        AK = 1.0E0 - TFNF/(FKK+TFNF)\n        ACK = BK*AK\n        SUM = SUM + CMPLX(ACK+BK,0.0E0)*P1\n        BK = ACK\n        FKK = FKK - 1.0E0\n   50 CONTINUE\n      Y(N) = P2\n      IF (N.EQ.1) GO TO 70\n      DO 60 I=2,N\n        PT = P2\n        P2 = P1 + CMPLX(FKK+FNF,0.0E0)*RZ*P2\n        P1 = PT\n        AK = 1.0E0 - TFNF/(FKK+TFNF)\n        ACK = BK*AK\n        SUM = SUM + CMPLX(ACK+BK,0.0E0)*P1\n        BK = ACK\n        FKK = FKK - 1.0E0\n        M = N - I + 1\n        Y(M) = P2\n   60 CONTINUE\n   70 CONTINUE\n      IF (IFNU.LE.0) GO TO 90\n      DO 80 I=1,IFNU\n        PT = P2\n        P2 = P1 + CMPLX(FKK+FNF,0.0E0)*RZ*P2\n        P1 = PT\n        AK = 1.0E0 - TFNF/(FKK+TFNF)\n        ACK = BK*AK\n        SUM = SUM + CMPLX(ACK+BK,0.0E0)*P1\n        BK = ACK\n        FKK = FKK - 1.0E0\n   80 CONTINUE\n   90 CONTINUE\n      PT = Z\n      IF (KODE.EQ.2) PT = PT - CMPLX(X,0.0E0)\n      P1 = -CMPLX(FNF,0.0E0)*CLOG(RZ) + PT\n      AP = GAMLN(1.0E0+FNF,IDUM)\n      PT = P1 - CMPLX(AP,0.0E0)\nC-----------------------------------------------------------------------\nC     THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW\nC     IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES\nC-----------------------------------------------------------------------\n      P2 = P2 + SUM\n      AP = CABS(P2)\n      P1 = CMPLX(1.0E0/AP,0.0E0)\n      CK = CEXP(PT)*P1\n      PT = CONJG(P2)*P1\n      CNORM = CK*PT\n      DO 100 I=1,N\n        Y(I) = Y(I)*CNORM\n  100 CONTINUE\n      RETURN\n  110 CONTINUE\n      NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/crati.f",
    "content": "      SUBROUTINE CRATI(Z, FNU, N, CY, TOL)\nC***BEGIN PROLOGUE  CRATI\nC***REFER TO  CBESI,CBESK,CBESH\nC\nC     CRATI COMPUTES RATIOS OF I BESSEL FUNCTIONS BY BACKWARD\nC     RECURRENCE.  THE STARTING INDEX IS DETERMINED BY FORWARD\nC     RECURRENCE AS DESCRIBED IN J. RES. OF NAT. BUR. OF STANDARDS-B,\nC     MATHEMATICAL SCIENCES, VOL 77B, P111-114, SEPTEMBER, 1973,\nC     BESSEL FUNCTIONS I AND J OF COMPLEX ARGUMENT AND INTEGER ORDER,\nC     BY D. J. SOOKNE.\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  CRATI\n      COMPLEX CDFNU, CONE, CY, CZERO, PT, P1, P2, RZ, T1, Z\n      REAL AK, AMAGZ, AP1, AP2, ARG, AZ, DFNU, FDNU, FLAM, FNU, FNUP,\n     * RAP1, RHO, TEST, TEST1, TOL\n      INTEGER I, ID, IDNU, INU, ITIME, K, KK, MAGZ, N\n      DIMENSION CY(N)\n      DATA CZERO, CONE / (0.0E0,0.0E0), (1.0E0,0.0E0) /\n      AZ = CABS(Z)\n      INU = INT(FNU)\n      IDNU = INU + N - 1\n      FDNU = FLOAT(IDNU)\n      MAGZ = INT(AZ)\n      AMAGZ = FLOAT(MAGZ+1)\n      FNUP = AMAX1(AMAGZ,FDNU)\n      ID = IDNU - MAGZ - 1\n      ITIME = 1\n      K = 1\n      RZ = (CONE+CONE)/Z\n      T1 = CMPLX(FNUP,0.0E0)*RZ\n      P2 = -T1\n      P1 = CONE\n      T1 = T1 + RZ\n      IF (ID.GT.0) ID = 0\n      AP2 = CABS(P2)\n      AP1 = CABS(P1)\nC-----------------------------------------------------------------------\nC     THE OVERFLOW TEST ON K(FNU+I-1,Z) BEFORE THE CALL TO CBKNX\nC     GUARANTEES THAT P2 IS ON SCALE. SCALE TEST1 AND ALL SUBSEQUENT\nC     P2 VALUES BY AP1 TO ENSURE THAT AN OVERFLOW DOES NOT OCCUR\nC     PREMATURELY.\nC-----------------------------------------------------------------------\n      ARG = (AP2+AP2)/(AP1*TOL)\n      TEST1 = SQRT(ARG)\n      TEST = TEST1\n      RAP1 = 1.0E0/AP1\n      P1 = P1*CMPLX(RAP1,0.0E0)\n      P2 = P2*CMPLX(RAP1,0.0E0)\n      AP2 = AP2*RAP1\n   10 CONTINUE\n      K = K + 1\n      AP1 = AP2\n      PT = P2\n      P2 = P1 - T1*P2\n      P1 = PT\n      T1 = T1 + RZ\n      AP2 = CABS(P2)\n      IF (AP1.LE.TEST) GO TO 10\n      IF (ITIME.EQ.2) GO TO 20\n      AK = CABS(T1)*0.5E0\n      FLAM = AK + SQRT(AK*AK-1.0E0)\n      RHO = AMIN1(AP2/AP1,FLAM)\n      TEST = TEST1*SQRT(RHO/(RHO*RHO-1.0E0))\n      ITIME = 2\n      GO TO 10\n   20 CONTINUE\n      KK = K + 1 - ID\n      AK = FLOAT(KK)\n      DFNU = FNU + FLOAT(N-1)\n      CDFNU = CMPLX(DFNU,0.0E0)\n      T1 = CMPLX(AK,0.0E0)\n      P1 = CMPLX(1.0E0/AP2,0.0E0)\n      P2 = CZERO\n      DO 30 I=1,KK\n        PT = P1\n        P1 = RZ*(CDFNU+T1)*P1 + P2\n        P2 = PT\n        T1 = T1 - CONE\n   30 CONTINUE\n      IF (REAL(P1).NE.0.0E0 .OR. AIMAG(P1).NE.0.0E0) GO TO 40\n      P1 = CMPLX(TOL,TOL)\n   40 CONTINUE\n      CY(N) = P2/P1\n      IF (N.EQ.1) RETURN\n      K = N - 1\n      AK = FLOAT(K)\n      T1 = CMPLX(AK,0.0E0)\n      CDFNU = CMPLX(FNU,0.0E0)*RZ\n      DO 60 I=2,N\n        PT = CDFNU + T1*RZ + CY(K+1)\n        IF (REAL(PT).NE.0.0E0 .OR. AIMAG(PT).NE.0.0E0) GO TO 50\n        PT = CMPLX(TOL,TOL)\n   50   CONTINUE\n        CY(K) = CONE/PT\n        T1 = T1 - CONE\n        K = K - 1\n   60 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cs1s2.f",
    "content": "      SUBROUTINE CS1S2(ZR, S1, S2, NZ, ASCLE, ALIM, IUF)\nC***BEGIN PROLOGUE  CS1S2\nC***REFER TO  CBESK,CAIRY\nC\nC     CS1S2 TESTS FOR A POSSIBLE UNDERFLOW RESULTING FROM THE\nC     ADDITION OF THE I AND K FUNCTIONS IN THE ANALYTIC CON-\nC     TINUATION FORMULA WHERE S1=K FUNCTION AND S2=I FUNCTION.\nC     ON KODE=1 THE I AND K FUNCTIONS ARE DIFFERENT ORDERS OF\nC     MAGNITUDE, BUT FOR KODE=2 THEY CAN BE OF THE SAME ORDER\nC     OF MAGNITUDE AND THE MAXIMUM MUST BE AT LEAST ONE\nC     PRECISION ABOVE THE UNDERFLOW LIMIT.\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  CS1S2\n      COMPLEX CZERO, C1, S1, S1D, S2, ZR\n      REAL AA, ALIM, ALN, ASCLE, AS1, AS2, XX\n      INTEGER IUF, NZ\n      DATA CZERO / (0.0E0,0.0E0) /\n      NZ = 0\n      AS1 = CABS(S1)\n      AS2 = CABS(S2)\n      AA = REAL(S1)\n      ALN = AIMAG(S1)\n      IF (AA.EQ.0.0E0 .AND. ALN.EQ.0.0E0) GO TO 10\n      IF (AS1.EQ.0.0E0) GO TO 10\n      XX = REAL(ZR)\n      ALN = -XX - XX + ALOG(AS1)\n      S1D = S1\n      S1 = CZERO\n      AS1 = 0.0E0\n      IF (ALN.LT.(-ALIM)) GO TO 10\n      C1 = CLOG(S1D) - ZR - ZR\n      S1 = CEXP(C1)\n      AS1 = CABS(S1)\n      IUF = IUF + 1\n   10 CONTINUE\n      AA = AMAX1(AS1,AS2)\n      IF (AA.GT.ASCLE) RETURN\n      S1 = CZERO\n      S2 = CZERO\n      NZ = 1\n      IUF = 0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cseri.f",
    "content": "      SUBROUTINE CSERI(Z, FNU, KODE, N, Y, NZ, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  CSERI\nC***REFER TO  CBESI,CBESK\nC\nC     CSERI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z).GE.0.0 BY\nC     MEANS OF THE POWER SERIES FOR LARGE CABS(Z) IN THE\nC     REGION CABS(Z).LE.2*SQRT(FNU+1). NZ=0 IS A NORMAL RETURN.\nC     NZ.GT.0 MEANS THAT THE LAST NZ COMPONENTS WERE SET TO ZERO\nC     DUE TO UNDERFLOW. NZ.LT.0 MEANS UNDERFLOW OCCURRED, BUT THE\nC     CONDITION CABS(Z).LE.2*SQRT(FNU+1) WAS VIOLATED AND THE\nC     COMPUTATION MUST BE COMPLETED IN ANOTHER ROUTINE WITH N=N-ABS(NZ).\nC\nC***ROUTINES CALLED  CUCHK,GAMLN,R1MACH\nC***END PROLOGUE  CSERI\n      COMPLEX AK1, CK, COEF, CONE, CRSC, CZ, CZERO, HZ, RZ, S1, S2, W,\n     * Y, Z\n      REAL AA, ACZ, AK, ALIM, ARM, ASCLE, ATOL, AZ, DFNU, ELIM, FNU,\n     * FNUP, RAK1, RS, RTR1, S, SS, TOL, X, GAMLN, R1MACH\n      INTEGER I, IB, IDUM, IFLAG, IL, K, KODE, L, M, N, NN, NW, NZ\n      DIMENSION Y(N), W(2)\n      DATA CZERO, CONE / (0.0E0,0.0E0), (1.0E0,0.0E0) /\nC\n      NZ = 0\n      AZ = CABS(Z)\n      IF (AZ.EQ.0.0E0) GO TO 150\n      X = REAL(Z)\n      ARM = 1.0E+3*R1MACH(1)\n      RTR1 = SQRT(ARM)\n      CRSC = CMPLX(1.0E0,0.0E0)\n      IFLAG = 0\n      IF (AZ.LT.ARM) GO TO 140\n      HZ = Z*CMPLX(0.5E0,0.0E0)\n      CZ = CZERO\n      IF (AZ.GT.RTR1) CZ = HZ*HZ\n      ACZ = CABS(CZ)\n      NN = N\n      CK = CLOG(HZ)\n   10 CONTINUE\n      DFNU = FNU + FLOAT(NN-1)\n      FNUP = DFNU + 1.0E0\nC-----------------------------------------------------------------------\nC     UNDERFLOW TEST\nC-----------------------------------------------------------------------\n      AK1 = CK*CMPLX(DFNU,0.0E0)\n      AK = GAMLN(FNUP,IDUM)\n      AK1 = AK1 - CMPLX(AK,0.0E0)\n      IF (KODE.EQ.2) AK1 = AK1 - CMPLX(X,0.0E0)\n      RAK1 = REAL(AK1)\n      IF (RAK1.GT.(-ELIM)) GO TO 30\n   20 CONTINUE\n      NZ = NZ + 1\n      Y(NN) = CZERO\n      IF (ACZ.GT.DFNU) GO TO 170\n      NN = NN - 1\n      IF (NN.EQ.0) RETURN\n      GO TO 10\n   30 CONTINUE\n      IF (RAK1.GT.(-ALIM)) GO TO 40\n      IFLAG = 1\n      SS = 1.0E0/TOL\n      CRSC = CMPLX(TOL,0.0E0)\n      ASCLE = ARM*SS\n   40 CONTINUE\n      AK = AIMAG(AK1)\n      AA = EXP(RAK1)\n      IF (IFLAG.EQ.1) AA = AA*SS\n      COEF = CMPLX(AA,0.0E0)*CMPLX(COS(AK),SIN(AK))\n      ATOL = TOL*ACZ/FNUP\n      IL = MIN0(2,NN)\n      DO 80 I=1,IL\n        DFNU = FNU + FLOAT(NN-I)\n        FNUP = DFNU + 1.0E0\n        S1 = CONE\n        IF (ACZ.LT.TOL*FNUP) GO TO 60\n        AK1 = CONE\n        AK = FNUP + 2.0E0\n        S = FNUP\n        AA = 2.0E0\n   50   CONTINUE\n        RS = 1.0E0/S\n        AK1 = AK1*CZ*CMPLX(RS,0.0E0)\n        S1 = S1 + AK1\n        S = S + AK\n        AK = AK + 2.0E0\n        AA = AA*ACZ*RS\n        IF (AA.GT.ATOL) GO TO 50\n   60   CONTINUE\n        M = NN - I + 1\n        S2 = S1*COEF\n        W(I) = S2\n        IF (IFLAG.EQ.0) GO TO 70\n        CALL CUCHK(S2, NW, ASCLE, TOL)\n        IF (NW.NE.0) GO TO 20\n   70   CONTINUE\n        Y(M) = S2*CRSC\n        IF (I.NE.IL) COEF = COEF*CMPLX(DFNU,0.0E0)/HZ\n   80 CONTINUE\n      IF (NN.LE.2) RETURN\n      K = NN - 2\n      AK = FLOAT(K)\n      RZ = (CONE+CONE)/Z\n      IF (IFLAG.EQ.1) GO TO 110\n      IB = 3\n   90 CONTINUE\n      DO 100 I=IB,NN\n        Y(K) = CMPLX(AK+FNU,0.0E0)*RZ*Y(K+1) + Y(K+2)\n        AK = AK - 1.0E0\n        K = K - 1\n  100 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     RECUR BACKWARD WITH SCALED VALUES\nC-----------------------------------------------------------------------\n  110 CONTINUE\nC-----------------------------------------------------------------------\nC     EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION ABOVE THE\nC     UNDERFLOW LIMIT = ASCLE = R1MACH(1)*CSCL*1.0E+3\nC-----------------------------------------------------------------------\n      S1 = W(1)\n      S2 = W(2)\n      DO 120 L=3,NN\n        CK = S2\n        S2 = S1 + CMPLX(AK+FNU,0.0E0)*RZ*S2\n        S1 = CK\n        CK = S2*CRSC\n        Y(K) = CK\n        AK = AK - 1.0E0\n        K = K - 1\n        IF (CABS(CK).GT.ASCLE) GO TO 130\n  120 CONTINUE\n      RETURN\n  130 CONTINUE\n      IB = L + 1\n      IF (IB.GT.NN) RETURN\n      GO TO 90\n  140 CONTINUE\n      NZ = N\n      IF (FNU.EQ.0.0E0) NZ = NZ - 1\n  150 CONTINUE\n      Y(1) = CZERO\n      IF (FNU.EQ.0.0E0) Y(1) = CONE\n      IF (N.EQ.1) RETURN\n      DO 160 I=2,N\n        Y(I) = CZERO\n  160 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     RETURN WITH NZ.LT.0 IF CABS(Z*Z/4).GT.FNU+N-NZ-1 COMPLETE\nC     THE CALCULATION IN CBINU WITH N=N-IABS(NZ)\nC-----------------------------------------------------------------------\n  170 CONTINUE\n      NZ = -NZ\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cshch.f",
    "content": "      SUBROUTINE CSHCH(Z, CSH, CCH)\nC***BEGIN PROLOGUE  CSHCH\nC***REFER TO  CBESK,CBESH\nC\nC     CSHCH COMPUTES THE COMPLEX HYPERBOLIC FUNCTIONS CSH=SINH(X+I*Y)\nC     AND CCH=COSH(X+I*Y), WHERE I**2=-1.\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  CSHCH\n      COMPLEX CCH, CSH, Z\n      REAL CCHI, CCHR, CH, CN, CSHI, CSHR, SH, SN, X, Y, COSH, SINH\n      X = REAL(Z)\n      Y = AIMAG(Z)\n      SH = SINH(X)\n      CH = COSH(X)\n      SN = SIN(Y)\n      CN = COS(Y)\n      CSHR = SH*CN\n      CSHI = CH*SN\n      CSH = CMPLX(CSHR,CSHI)\n      CCHR = CH*CN\n      CCHI = SH*SN\n      CCH = CMPLX(CCHR,CCHI)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cuchk.f",
    "content": "      SUBROUTINE CUCHK(Y, NZ, ASCLE, TOL)\nC***BEGIN PROLOGUE  CUCHK\nC***REFER TO CSERI,CUOIK,CUNK1,CUNK2,CUNI1,CUNI2,CKSCL\nC\nC      Y ENTERS AS A SCALED QUANTITY WHOSE MAGNITUDE IS GREATER THAN\nC      EXP(-ALIM)=ASCLE=1.0E+3*R1MACH(1)/TOL. THE TEST IS MADE TO SEE\nC      IF THE MAGNITUDE OF THE REAL OR IMAGINARY PART WOULD UNDER FLOW\nC      WHEN Y IS SCALED (BY TOL) TO ITS PROPER VALUE. Y IS ACCEPTED\nC      IF THE UNDERFLOW IS AT LEAST ONE PRECISION BELOW THE MAGNITUDE\nC      OF THE LARGEST COMPONENT; OTHERWISE THE PHASE ANGLE DOES NOT HAVE\nC      ABSOLUTE ACCURACY AND AN UNDERFLOW IS ASSUMED.\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  CUCHK\nC\n      COMPLEX Y\n      REAL ASCLE, SS, ST, TOL, YR, YI\n      INTEGER NZ\n      NZ = 0\n      YR = REAL(Y)\n      YI = AIMAG(Y)\n      YR = ABS(YR)\n      YI = ABS(YI)\n      ST = AMIN1(YR,YI)\n      IF (ST.GT.ASCLE) RETURN\n      SS = AMAX1(YR,YI)\n      ST=ST/TOL\n      IF (SS.LT.ST) NZ = 1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cunhj.f",
    "content": "      SUBROUTINE CUNHJ(Z, FNU, IPMTR, TOL, PHI, ARG, ZETA1, ZETA2,\n     * ASUM, BSUM)\nC***BEGIN PROLOGUE  CUNHJ\nC***REFER TO  CBESI,CBESK\nC\nC     REFERENCES\nC         HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ AND I.A.\nC         STEGUN, AMS55, NATIONAL BUREAU OF STANDARDS, 1965, CHAPTER 9.\nC\nC         ASYMPTOTICS AND SPECIAL FUNCTIONS BY F.W.J. OLVER, ACADEMIC\nC         PRESS, N.Y., 1974, PAGE 420\nC\nC     ABSTRACT\nC         CUNHJ COMPUTES PARAMETERS FOR BESSEL FUNCTIONS C(FNU,Z) =\nC         J(FNU,Z), Y(FNU,Z) OR H(I,FNU,Z) I=1,2 FOR LARGE ORDERS FNU\nC         BY MEANS OF THE UNIFORM ASYMPTOTIC EXPANSION\nC\nC         C(FNU,Z)=C1*PHI*( ASUM*AIRY(ARG) + C2*BSUM*DAIRY(ARG) )\nC\nC         FOR PROPER CHOICES OF C1, C2, AIRY AND DAIRY WHERE AIRY IS\nC         AN AIRY FUNCTION AND DAIRY IS ITS DERIVATIVE.\nC\nC               (2/3)*FNU*ZETA**1.5 = ZETA1-ZETA2,\nC\nC         ZETA1=0.5*FNU*CLOG((1+W)/(1-W)), ZETA2=FNU*W FOR SCALING\nC         PURPOSES IN AIRY FUNCTIONS FROM CAIRY OR CBIRY.\nC\nC         MCONJ=SIGN OF AIMAG(Z), BUT IS AMBIGUOUS WHEN Z IS REAL AND\nC         MUST BE SPECIFIED. IPMTR=0 RETURNS ALL PARAMETERS. IPMTR=\nC         1 COMPUTES ALL EXCEPT ASUM AND BSUM.\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  CUNHJ\n      COMPLEX ARG, ASUM, BSUM, CFNU, CONE, CR, CZERO, DR, P, PHI,\n     * PRZTH, PTFN, RFN13, RTZTA, RZTH, SUMA, SUMB, TFN, T2, UP, W, W2,\n     * Z, ZA, ZB, ZC, ZETA, ZETA1, ZETA2, ZTH\n      REAL ALFA, ANG, AP, AR, ATOL, AW2, AZTH, BETA, BR, BTOL, C, EX1,\n     * EX2, FNU, FN13, FN23, GAMA, HPI, PI, PP, RFNU, RFNU2, THPI, TOL,\n     * WI, WR, ZCI, ZCR, ZETAI, ZETAR, ZTHI, ZTHR, ASUMR, ASUMI, BSUMR,\n     * BSUMI, TEST, TSTR, TSTI, AC\n      INTEGER IAS, IBS, IPMTR, IS, J, JR, JU, K, KMAX, KP1, KS, L, LR,\n     * LRP1, L1, L2, M\n      DIMENSION AR(14), BR(14), C(105), ALFA(180), BETA(210), GAMA(30),\n     * AP(30), P(30), UP(14), CR(14), DR(14)\n      DATA AR(1), AR(2), AR(3), AR(4), AR(5), AR(6), AR(7), AR(8),\n     1     AR(9), AR(10), AR(11), AR(12), AR(13), AR(14)/\n     2     1.00000000000000000E+00,     1.04166666666666667E-01,\n     3     8.35503472222222222E-02,     1.28226574556327160E-01,\n     4     2.91849026464140464E-01,     8.81627267443757652E-01,\n     5     3.32140828186276754E+00,     1.49957629868625547E+01,\n     6     7.89230130115865181E+01,     4.74451538868264323E+02,\n     7     3.20749009089066193E+03,     2.40865496408740049E+04,\n     8     1.98923119169509794E+05,     1.79190200777534383E+06/\n      DATA BR(1), BR(2), BR(3), BR(4), BR(5), BR(6), BR(7), BR(8),\n     1     BR(9), BR(10), BR(11), BR(12), BR(13), BR(14)/\n     2     1.00000000000000000E+00,    -1.45833333333333333E-01,\n     3    -9.87413194444444444E-02,    -1.43312053915895062E-01,\n     4    -3.17227202678413548E-01,    -9.42429147957120249E-01,\n     5    -3.51120304082635426E+00,    -1.57272636203680451E+01,\n     6    -8.22814390971859444E+01,    -4.92355370523670524E+02,\n     7    -3.31621856854797251E+03,    -2.48276742452085896E+04,\n     8    -2.04526587315129788E+05,    -1.83844491706820990E+06/\n      DATA C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10),\n     1     C(11), C(12), C(13), C(14), C(15), C(16), C(17), C(18),\n     2     C(19), C(20), C(21), C(22), C(23), C(24)/\n     3     1.00000000000000000E+00,    -2.08333333333333333E-01,\n     4     1.25000000000000000E-01,     3.34201388888888889E-01,\n     5    -4.01041666666666667E-01,     7.03125000000000000E-02,\n     6    -1.02581259645061728E+00,     1.84646267361111111E+00,\n     7    -8.91210937500000000E-01,     7.32421875000000000E-02,\n     8     4.66958442342624743E+00,    -1.12070026162229938E+01,\n     9     8.78912353515625000E+00,    -2.36408691406250000E+00,\n     A     1.12152099609375000E-01,    -2.82120725582002449E+01,\n     B     8.46362176746007346E+01,    -9.18182415432400174E+01,\n     C     4.25349987453884549E+01,    -7.36879435947963170E+00,\n     D     2.27108001708984375E-01,     2.12570130039217123E+02,\n     E    -7.65252468141181642E+02,     1.05999045252799988E+03/\n      DATA C(25), C(26), C(27), C(28), C(29), C(30), C(31), C(32),\n     1     C(33), C(34), C(35), C(36), C(37), C(38), C(39), C(40),\n     2     C(41), C(42), C(43), C(44), C(45), C(46), C(47), C(48)/\n     3    -6.99579627376132541E+02,     2.18190511744211590E+02,\n     4    -2.64914304869515555E+01,     5.72501420974731445E-01,\n     5    -1.91945766231840700E+03,     8.06172218173730938E+03,\n     6    -1.35865500064341374E+04,     1.16553933368645332E+04,\n     7    -5.30564697861340311E+03,     1.20090291321635246E+03,\n     8    -1.08090919788394656E+02,     1.72772750258445740E+00,\n     9     2.02042913309661486E+04,    -9.69805983886375135E+04,\n     A     1.92547001232531532E+05,    -2.03400177280415534E+05,\n     B     1.22200464983017460E+05,    -4.11926549688975513E+04,\n     C     7.10951430248936372E+03,    -4.93915304773088012E+02,\n     D     6.07404200127348304E+00,    -2.42919187900551333E+05,\n     E     1.31176361466297720E+06,    -2.99801591853810675E+06/\n      DATA C(49), C(50), C(51), C(52), C(53), C(54), C(55), C(56),\n     1     C(57), C(58), C(59), C(60), C(61), C(62), C(63), C(64),\n     2     C(65), C(66), C(67), C(68), C(69), C(70), C(71), C(72)/\n     3     3.76327129765640400E+06,    -2.81356322658653411E+06,\n     4     1.26836527332162478E+06,    -3.31645172484563578E+05,\n     5     4.52187689813627263E+04,    -2.49983048181120962E+03,\n     6     2.43805296995560639E+01,     3.28446985307203782E+06,\n     7    -1.97068191184322269E+07,     5.09526024926646422E+07,\n     8    -7.41051482115326577E+07,     6.63445122747290267E+07,\n     9    -3.75671766607633513E+07,     1.32887671664218183E+07,\n     A    -2.78561812808645469E+06,     3.08186404612662398E+05,\n     B    -1.38860897537170405E+04,     1.10017140269246738E+02,\n     C    -4.93292536645099620E+07,     3.25573074185765749E+08,\n     D    -9.39462359681578403E+08,     1.55359689957058006E+09,\n     E    -1.62108055210833708E+09,     1.10684281682301447E+09/\n      DATA C(73), C(74), C(75), C(76), C(77), C(78), C(79), C(80),\n     1     C(81), C(82), C(83), C(84), C(85), C(86), C(87), C(88),\n     2     C(89), C(90), C(91), C(92), C(93), C(94), C(95), C(96)/\n     3    -4.95889784275030309E+08,     1.42062907797533095E+08,\n     4    -2.44740627257387285E+07,     2.24376817792244943E+06,\n     5    -8.40054336030240853E+04,     5.51335896122020586E+02,\n     6     8.14789096118312115E+08,    -5.86648149205184723E+09,\n     7     1.86882075092958249E+10,    -3.46320433881587779E+10,\n     8     4.12801855797539740E+10,    -3.30265997498007231E+10,\n     9     1.79542137311556001E+10,    -6.56329379261928433E+09,\n     A     1.55927986487925751E+09,    -2.25105661889415278E+08,\n     B     1.73951075539781645E+07,    -5.49842327572288687E+05,\n     C     3.03809051092238427E+03,    -1.46792612476956167E+10,\n     D     1.14498237732025810E+11,    -3.99096175224466498E+11,\n     E     8.19218669548577329E+11,    -1.09837515608122331E+12/\n      DATA C(97), C(98), C(99), C(100), C(101), C(102), C(103), C(104),\n     1     C(105)/\n     2     1.00815810686538209E+12,    -6.45364869245376503E+11,\n     3     2.87900649906150589E+11,    -8.78670721780232657E+10,\n     4     1.76347306068349694E+10,    -2.16716498322379509E+09,\n     5     1.43157876718888981E+08,    -3.87183344257261262E+06,\n     6     1.82577554742931747E+04/\n      DATA ALFA(1), ALFA(2), ALFA(3), ALFA(4), ALFA(5), ALFA(6),\n     1     ALFA(7), ALFA(8), ALFA(9), ALFA(10), ALFA(11), ALFA(12),\n     2     ALFA(13), ALFA(14), ALFA(15), ALFA(16), ALFA(17), ALFA(18),\n     3     ALFA(19), ALFA(20), ALFA(21), ALFA(22)/\n     4    -4.44444444444444444E-03,    -9.22077922077922078E-04,\n     5    -8.84892884892884893E-05,     1.65927687832449737E-04,\n     6     2.46691372741792910E-04,     2.65995589346254780E-04,\n     7     2.61824297061500945E-04,     2.48730437344655609E-04,\n     8     2.32721040083232098E-04,     2.16362485712365082E-04,\n     9     2.00738858762752355E-04,     1.86267636637545172E-04,\n     A     1.73060775917876493E-04,     1.61091705929015752E-04,\n     B     1.50274774160908134E-04,     1.40503497391269794E-04,\n     C     1.31668816545922806E-04,     1.23667445598253261E-04,\n     D     1.16405271474737902E-04,     1.09798298372713369E-04,\n     E     1.03772410422992823E-04,     9.82626078369363448E-05/\n      DATA ALFA(23), ALFA(24), ALFA(25), ALFA(26), ALFA(27), ALFA(28),\n     1     ALFA(29), ALFA(30), ALFA(31), ALFA(32), ALFA(33), ALFA(34),\n     2     ALFA(35), ALFA(36), ALFA(37), ALFA(38), ALFA(39), ALFA(40),\n     3     ALFA(41), ALFA(42), ALFA(43), ALFA(44)/\n     4     9.32120517249503256E-05,     8.85710852478711718E-05,\n     5     8.42963105715700223E-05,     8.03497548407791151E-05,\n     6     7.66981345359207388E-05,     7.33122157481777809E-05,\n     7     7.01662625163141333E-05,     6.72375633790160292E-05,\n     8     6.93735541354588974E-04,     2.32241745182921654E-04,\n     9    -1.41986273556691197E-05,    -1.16444931672048640E-04,\n     A    -1.50803558053048762E-04,    -1.55121924918096223E-04,\n     B    -1.46809756646465549E-04,    -1.33815503867491367E-04,\n     C    -1.19744975684254051E-04,    -1.06184319207974020E-04,\n     D    -9.37699549891194492E-05,    -8.26923045588193274E-05,\n     E    -7.29374348155221211E-05,    -6.44042357721016283E-05/\n      DATA ALFA(45), ALFA(46), ALFA(47), ALFA(48), ALFA(49), ALFA(50),\n     1     ALFA(51), ALFA(52), ALFA(53), ALFA(54), ALFA(55), ALFA(56),\n     2     ALFA(57), ALFA(58), ALFA(59), ALFA(60), ALFA(61), ALFA(62),\n     3     ALFA(63), ALFA(64), ALFA(65), ALFA(66)/\n     4    -5.69611566009369048E-05,    -5.04731044303561628E-05,\n     5    -4.48134868008882786E-05,    -3.98688727717598864E-05,\n     6    -3.55400532972042498E-05,    -3.17414256609022480E-05,\n     7    -2.83996793904174811E-05,    -2.54522720634870566E-05,\n     8    -2.28459297164724555E-05,    -2.05352753106480604E-05,\n     9    -1.84816217627666085E-05,    -1.66519330021393806E-05,\n     A    -1.50179412980119482E-05,    -1.35554031379040526E-05,\n     B    -1.22434746473858131E-05,    -1.10641884811308169E-05,\n     C    -3.54211971457743841E-04,    -1.56161263945159416E-04,\n     D     3.04465503594936410E-05,     1.30198655773242693E-04,\n     E     1.67471106699712269E-04,     1.70222587683592569E-04/\n      DATA ALFA(67), ALFA(68), ALFA(69), ALFA(70), ALFA(71), ALFA(72),\n     1     ALFA(73), ALFA(74), ALFA(75), ALFA(76), ALFA(77), ALFA(78),\n     2     ALFA(79), ALFA(80), ALFA(81), ALFA(82), ALFA(83), ALFA(84),\n     3     ALFA(85), ALFA(86), ALFA(87), ALFA(88)/\n     4     1.56501427608594704E-04,     1.36339170977445120E-04,\n     5     1.14886692029825128E-04,     9.45869093034688111E-05,\n     6     7.64498419250898258E-05,     6.07570334965197354E-05,\n     7     4.74394299290508799E-05,     3.62757512005344297E-05,\n     8     2.69939714979224901E-05,     1.93210938247939253E-05,\n     9     1.30056674793963203E-05,     7.82620866744496661E-06,\n     A     3.59257485819351583E-06,     1.44040049814251817E-07,\n     B    -2.65396769697939116E-06,    -4.91346867098485910E-06,\n     C    -6.72739296091248287E-06,    -8.17269379678657923E-06,\n     D    -9.31304715093561232E-06,    -1.02011418798016441E-05,\n     E    -1.08805962510592880E-05,    -1.13875481509603555E-05/\n      DATA ALFA(89), ALFA(90), ALFA(91), ALFA(92), ALFA(93), ALFA(94),\n     1     ALFA(95), ALFA(96), ALFA(97), ALFA(98), ALFA(99), ALFA(100),\n     2     ALFA(101), ALFA(102), ALFA(103), ALFA(104), ALFA(105),\n     3     ALFA(106), ALFA(107), ALFA(108), ALFA(109), ALFA(110)/\n     4    -1.17519675674556414E-05,    -1.19987364870944141E-05,\n     5     3.78194199201772914E-04,     2.02471952761816167E-04,\n     6    -6.37938506318862408E-05,    -2.38598230603005903E-04,\n     7    -3.10916256027361568E-04,    -3.13680115247576316E-04,\n     8    -2.78950273791323387E-04,    -2.28564082619141374E-04,\n     9    -1.75245280340846749E-04,    -1.25544063060690348E-04,\n     A    -8.22982872820208365E-05,    -4.62860730588116458E-05,\n     B    -1.72334302366962267E-05,     5.60690482304602267E-06,\n     C     2.31395443148286800E-05,     3.62642745856793957E-05,\n     D     4.58006124490188752E-05,     5.24595294959114050E-05,\n     E     5.68396208545815266E-05,     5.94349820393104052E-05/\n      DATA ALFA(111), ALFA(112), ALFA(113), ALFA(114), ALFA(115),\n     1     ALFA(116), ALFA(117), ALFA(118), ALFA(119), ALFA(120),\n     2     ALFA(121), ALFA(122), ALFA(123), ALFA(124), ALFA(125),\n     3     ALFA(126), ALFA(127), ALFA(128), ALFA(129), ALFA(130)/\n     4     6.06478527578421742E-05,     6.08023907788436497E-05,\n     5     6.01577894539460388E-05,     5.89199657344698500E-05,\n     6     5.72515823777593053E-05,     5.52804375585852577E-05,\n     7     5.31063773802880170E-05,     5.08069302012325706E-05,\n     8     4.84418647620094842E-05,     4.60568581607475370E-05,\n     9    -6.91141397288294174E-04,    -4.29976633058871912E-04,\n     A     1.83067735980039018E-04,     6.60088147542014144E-04,\n     B     8.75964969951185931E-04,     8.77335235958235514E-04,\n     C     7.49369585378990637E-04,     5.63832329756980918E-04,\n     D     3.68059319971443156E-04,     1.88464535514455599E-04/\n      DATA ALFA(131), ALFA(132), ALFA(133), ALFA(134), ALFA(135),\n     1     ALFA(136), ALFA(137), ALFA(138), ALFA(139), ALFA(140),\n     2     ALFA(141), ALFA(142), ALFA(143), ALFA(144), ALFA(145),\n     3     ALFA(146), ALFA(147), ALFA(148), ALFA(149), ALFA(150)/\n     4     3.70663057664904149E-05,    -8.28520220232137023E-05,\n     5    -1.72751952869172998E-04,    -2.36314873605872983E-04,\n     6    -2.77966150694906658E-04,    -3.02079514155456919E-04,\n     7    -3.12594712643820127E-04,    -3.12872558758067163E-04,\n     8    -3.05678038466324377E-04,    -2.93226470614557331E-04,\n     9    -2.77255655582934777E-04,    -2.59103928467031709E-04,\n     A    -2.39784014396480342E-04,    -2.20048260045422848E-04,\n     B    -2.00443911094971498E-04,    -1.81358692210970687E-04,\n     C    -1.63057674478657464E-04,    -1.45712672175205844E-04,\n     D    -1.29425421983924587E-04,    -1.14245691942445952E-04/\n      DATA ALFA(151), ALFA(152), ALFA(153), ALFA(154), ALFA(155),\n     1     ALFA(156), ALFA(157), ALFA(158), ALFA(159), ALFA(160),\n     2     ALFA(161), ALFA(162), ALFA(163), ALFA(164), ALFA(165),\n     3     ALFA(166), ALFA(167), ALFA(168), ALFA(169), ALFA(170)/\n     4     1.92821964248775885E-03,     1.35592576302022234E-03,\n     5    -7.17858090421302995E-04,    -2.58084802575270346E-03,\n     6    -3.49271130826168475E-03,    -3.46986299340960628E-03,\n     7    -2.82285233351310182E-03,    -1.88103076404891354E-03,\n     8    -8.89531718383947600E-04,     3.87912102631035228E-06,\n     9     7.28688540119691412E-04,     1.26566373053457758E-03,\n     A     1.62518158372674427E-03,     1.83203153216373172E-03,\n     B     1.91588388990527909E-03,     1.90588846755546138E-03,\n     C     1.82798982421825727E-03,     1.70389506421121530E-03,\n     D     1.55097127171097686E-03,     1.38261421852276159E-03/\n      DATA ALFA(171), ALFA(172), ALFA(173), ALFA(174), ALFA(175),\n     1     ALFA(176), ALFA(177), ALFA(178), ALFA(179), ALFA(180)/\n     2     1.20881424230064774E-03,     1.03676532638344962E-03,\n     3     8.71437918068619115E-04,     7.16080155297701002E-04,\n     4     5.72637002558129372E-04,     4.42089819465802277E-04,\n     5     3.24724948503090564E-04,     2.20342042730246599E-04,\n     6     1.28412898401353882E-04,     4.82005924552095464E-05/\n      DATA BETA(1), BETA(2), BETA(3), BETA(4), BETA(5), BETA(6),\n     1     BETA(7), BETA(8), BETA(9), BETA(10), BETA(11), BETA(12),\n     2     BETA(13), BETA(14), BETA(15), BETA(16), BETA(17), BETA(18),\n     3     BETA(19), BETA(20), BETA(21), BETA(22)/\n     4     1.79988721413553309E-02,     5.59964911064388073E-03,\n     5     2.88501402231132779E-03,     1.80096606761053941E-03,\n     6     1.24753110589199202E-03,     9.22878876572938311E-04,\n     7     7.14430421727287357E-04,     5.71787281789704872E-04,\n     8     4.69431007606481533E-04,     3.93232835462916638E-04,\n     9     3.34818889318297664E-04,     2.88952148495751517E-04,\n     A     2.52211615549573284E-04,     2.22280580798883327E-04,\n     B     1.97541838033062524E-04,     1.76836855019718004E-04,\n     C     1.59316899661821081E-04,     1.44347930197333986E-04,\n     D     1.31448068119965379E-04,     1.20245444949302884E-04,\n     E     1.10449144504599392E-04,     1.01828770740567258E-04/\n      DATA BETA(23), BETA(24), BETA(25), BETA(26), BETA(27), BETA(28),\n     1     BETA(29), BETA(30), BETA(31), BETA(32), BETA(33), BETA(34),\n     2     BETA(35), BETA(36), BETA(37), BETA(38), BETA(39), BETA(40),\n     3     BETA(41), BETA(42), BETA(43), BETA(44)/\n     4     9.41998224204237509E-05,     8.74130545753834437E-05,\n     5     8.13466262162801467E-05,     7.59002269646219339E-05,\n     6     7.09906300634153481E-05,     6.65482874842468183E-05,\n     7     6.25146958969275078E-05,     5.88403394426251749E-05,\n     8    -1.49282953213429172E-03,    -8.78204709546389328E-04,\n     9    -5.02916549572034614E-04,    -2.94822138512746025E-04,\n     A    -1.75463996970782828E-04,    -1.04008550460816434E-04,\n     B    -5.96141953046457895E-05,    -3.12038929076098340E-05,\n     C    -1.26089735980230047E-05,    -2.42892608575730389E-07,\n     D     8.05996165414273571E-06,     1.36507009262147391E-05,\n     E     1.73964125472926261E-05,     1.98672978842133780E-05/\n      DATA BETA(45), BETA(46), BETA(47), BETA(48), BETA(49), BETA(50),\n     1     BETA(51), BETA(52), BETA(53), BETA(54), BETA(55), BETA(56),\n     2     BETA(57), BETA(58), BETA(59), BETA(60), BETA(61), BETA(62),\n     3     BETA(63), BETA(64), BETA(65), BETA(66)/\n     4     2.14463263790822639E-05,     2.23954659232456514E-05,\n     5     2.28967783814712629E-05,     2.30785389811177817E-05,\n     6     2.30321976080909144E-05,     2.28236073720348722E-05,\n     7     2.25005881105292418E-05,     2.20981015361991429E-05,\n     8     2.16418427448103905E-05,     2.11507649256220843E-05,\n     9     2.06388749782170737E-05,     2.01165241997081666E-05,\n     A     1.95913450141179244E-05,     1.90689367910436740E-05,\n     B     1.85533719641636667E-05,     1.80475722259674218E-05,\n     C     5.52213076721292790E-04,     4.47932581552384646E-04,\n     D     2.79520653992020589E-04,     1.52468156198446602E-04,\n     E     6.93271105657043598E-05,     1.76258683069991397E-05/\n      DATA BETA(67), BETA(68), BETA(69), BETA(70), BETA(71), BETA(72),\n     1     BETA(73), BETA(74), BETA(75), BETA(76), BETA(77), BETA(78),\n     2     BETA(79), BETA(80), BETA(81), BETA(82), BETA(83), BETA(84),\n     3     BETA(85), BETA(86), BETA(87), BETA(88)/\n     4    -1.35744996343269136E-05,    -3.17972413350427135E-05,\n     5    -4.18861861696693365E-05,    -4.69004889379141029E-05,\n     6    -4.87665447413787352E-05,    -4.87010031186735069E-05,\n     7    -4.74755620890086638E-05,    -4.55813058138628452E-05,\n     8    -4.33309644511266036E-05,    -4.09230193157750364E-05,\n     9    -3.84822638603221274E-05,    -3.60857167535410501E-05,\n     A    -3.37793306123367417E-05,    -3.15888560772109621E-05,\n     B    -2.95269561750807315E-05,    -2.75978914828335759E-05,\n     C    -2.58006174666883713E-05,    -2.41308356761280200E-05,\n     D    -2.25823509518346033E-05,    -2.11479656768912971E-05,\n     E    -1.98200638885294927E-05,    -1.85909870801065077E-05/\n      DATA BETA(89), BETA(90), BETA(91), BETA(92), BETA(93), BETA(94),\n     1     BETA(95), BETA(96), BETA(97), BETA(98), BETA(99), BETA(100),\n     2     BETA(101), BETA(102), BETA(103), BETA(104), BETA(105),\n     3     BETA(106), BETA(107), BETA(108), BETA(109), BETA(110)/\n     4    -1.74532699844210224E-05,    -1.63997823854497997E-05,\n     5    -4.74617796559959808E-04,    -4.77864567147321487E-04,\n     6    -3.20390228067037603E-04,    -1.61105016119962282E-04,\n     7    -4.25778101285435204E-05,     3.44571294294967503E-05,\n     8     7.97092684075674924E-05,     1.03138236708272200E-04,\n     9     1.12466775262204158E-04,     1.13103642108481389E-04,\n     A     1.08651634848774268E-04,     1.01437951597661973E-04,\n     B     9.29298396593363896E-05,     8.40293133016089978E-05,\n     C     7.52727991349134062E-05,     6.69632521975730872E-05,\n     D     5.92564547323194704E-05,     5.22169308826975567E-05,\n     E     4.58539485165360646E-05,     4.01445513891486808E-05/\n      DATA BETA(111), BETA(112), BETA(113), BETA(114), BETA(115),\n     1     BETA(116), BETA(117), BETA(118), BETA(119), BETA(120),\n     2     BETA(121), BETA(122), BETA(123), BETA(124), BETA(125),\n     3     BETA(126), BETA(127), BETA(128), BETA(129), BETA(130)/\n     4     3.50481730031328081E-05,     3.05157995034346659E-05,\n     5     2.64956119950516039E-05,     2.29363633690998152E-05,\n     6     1.97893056664021636E-05,     1.70091984636412623E-05,\n     7     1.45547428261524004E-05,     1.23886640995878413E-05,\n     8     1.04775876076583236E-05,     8.79179954978479373E-06,\n     9     7.36465810572578444E-04,     8.72790805146193976E-04,\n     A     6.22614862573135066E-04,     2.85998154194304147E-04,\n     B     3.84737672879366102E-06,    -1.87906003636971558E-04,\n     C    -2.97603646594554535E-04,    -3.45998126832656348E-04,\n     D    -3.53382470916037712E-04,    -3.35715635775048757E-04/\n      DATA BETA(131), BETA(132), BETA(133), BETA(134), BETA(135),\n     1     BETA(136), BETA(137), BETA(138), BETA(139), BETA(140),\n     2     BETA(141), BETA(142), BETA(143), BETA(144), BETA(145),\n     3     BETA(146), BETA(147), BETA(148), BETA(149), BETA(150)/\n     4    -3.04321124789039809E-04,    -2.66722723047612821E-04,\n     5    -2.27654214122819527E-04,    -1.89922611854562356E-04,\n     6    -1.55058918599093870E-04,    -1.23778240761873630E-04,\n     7    -9.62926147717644187E-05,    -7.25178327714425337E-05,\n     8    -5.22070028895633801E-05,    -3.50347750511900522E-05,\n     9    -2.06489761035551757E-05,    -8.70106096849767054E-06,\n     A     1.13698686675100290E-06,     9.16426474122778849E-06,\n     B     1.56477785428872620E-05,     2.08223629482466847E-05,\n     C     2.48923381004595156E-05,     2.80340509574146325E-05,\n     D     3.03987774629861915E-05,     3.21156731406700616E-05/\n      DATA BETA(151), BETA(152), BETA(153), BETA(154), BETA(155),\n     1     BETA(156), BETA(157), BETA(158), BETA(159), BETA(160),\n     2     BETA(161), BETA(162), BETA(163), BETA(164), BETA(165),\n     3     BETA(166), BETA(167), BETA(168), BETA(169), BETA(170)/\n     4    -1.80182191963885708E-03,    -2.43402962938042533E-03,\n     5    -1.83422663549856802E-03,    -7.62204596354009765E-04,\n     6     2.39079475256927218E-04,     9.49266117176881141E-04,\n     7     1.34467449701540359E-03,     1.48457495259449178E-03,\n     8     1.44732339830617591E-03,     1.30268261285657186E-03,\n     9     1.10351597375642682E-03,     8.86047440419791759E-04,\n     A     6.73073208165665473E-04,     4.77603872856582378E-04,\n     B     3.05991926358789362E-04,     1.60315694594721630E-04,\n     C     4.00749555270613286E-05,    -5.66607461635251611E-05,\n     D    -1.32506186772982638E-04,    -1.90296187989614057E-04/\n      DATA BETA(171), BETA(172), BETA(173), BETA(174), BETA(175),\n     1     BETA(176), BETA(177), BETA(178), BETA(179), BETA(180),\n     2     BETA(181), BETA(182), BETA(183), BETA(184), BETA(185),\n     3     BETA(186), BETA(187), BETA(188), BETA(189), BETA(190)/\n     4    -2.32811450376937408E-04,    -2.62628811464668841E-04,\n     5    -2.82050469867598672E-04,    -2.93081563192861167E-04,\n     6    -2.97435962176316616E-04,    -2.96557334239348078E-04,\n     7    -2.91647363312090861E-04,    -2.83696203837734166E-04,\n     8    -2.73512317095673346E-04,    -2.61750155806768580E-04,\n     9     6.38585891212050914E-03,     9.62374215806377941E-03,\n     A     7.61878061207001043E-03,     2.83219055545628054E-03,\n     B    -2.09841352012720090E-03,    -5.73826764216626498E-03,\n     C    -7.70804244495414620E-03,    -8.21011692264844401E-03,\n     D    -7.65824520346905413E-03,    -6.47209729391045177E-03/\n      DATA BETA(191), BETA(192), BETA(193), BETA(194), BETA(195),\n     1     BETA(196), BETA(197), BETA(198), BETA(199), BETA(200),\n     2     BETA(201), BETA(202), BETA(203), BETA(204), BETA(205),\n     3     BETA(206), BETA(207), BETA(208), BETA(209), BETA(210)/\n     4    -4.99132412004966473E-03,    -3.45612289713133280E-03,\n     5    -2.01785580014170775E-03,    -7.59430686781961401E-04,\n     6     2.84173631523859138E-04,     1.10891667586337403E-03,\n     7     1.72901493872728771E-03,     2.16812590802684701E-03,\n     8     2.45357710494539735E-03,     2.61281821058334862E-03,\n     9     2.67141039656276912E-03,     2.65203073395980430E-03,\n     A     2.57411652877287315E-03,     2.45389126236094427E-03,\n     B     2.30460058071795494E-03,     2.13684837686712662E-03,\n     C     1.95896528478870911E-03,     1.77737008679454412E-03,\n     D     1.59690280765839059E-03,     1.42111975664438546E-03/\n      DATA GAMA(1), GAMA(2), GAMA(3), GAMA(4), GAMA(5), GAMA(6),\n     1     GAMA(7), GAMA(8), GAMA(9), GAMA(10), GAMA(11), GAMA(12),\n     2     GAMA(13), GAMA(14), GAMA(15), GAMA(16), GAMA(17), GAMA(18),\n     3     GAMA(19), GAMA(20), GAMA(21), GAMA(22)/\n     4     6.29960524947436582E-01,     2.51984209978974633E-01,\n     5     1.54790300415655846E-01,     1.10713062416159013E-01,\n     6     8.57309395527394825E-02,     6.97161316958684292E-02,\n     7     5.86085671893713576E-02,     5.04698873536310685E-02,\n     8     4.42600580689154809E-02,     3.93720661543509966E-02,\n     9     3.54283195924455368E-02,     3.21818857502098231E-02,\n     A     2.94646240791157679E-02,     2.71581677112934479E-02,\n     B     2.51768272973861779E-02,     2.34570755306078891E-02,\n     C     2.19508390134907203E-02,     2.06210828235646240E-02,\n     D     1.94388240897880846E-02,     1.83810633800683158E-02,\n     E     1.74293213231963172E-02,     1.65685837786612353E-02/\n      DATA GAMA(23), GAMA(24), GAMA(25), GAMA(26), GAMA(27), GAMA(28),\n     1     GAMA(29), GAMA(30)/\n     2     1.57865285987918445E-02,     1.50729501494095594E-02,\n     3     1.44193250839954639E-02,     1.38184805735341786E-02,\n     4     1.32643378994276568E-02,     1.27517121970498651E-02,\n     5     1.22761545318762767E-02,     1.18338262398482403E-02/\n      DATA EX1, EX2, HPI, PI, THPI /\n     1     3.33333333333333333E-01,     6.66666666666666667E-01,\n     2     1.57079632679489662E+00,     3.14159265358979324E+00,\n     3     4.71238898038468986E+00/\n      DATA CZERO, CONE / (0.0E0,0.0E0), (1.0E0,0.0E0) /\nC\n      RFNU = 1.0E0/FNU\nC     ZB = Z*CMPLX(RFNU,0.0E0)\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST (Z/FNU TOO SMALL)\nC-----------------------------------------------------------------------\n      TSTR = REAL(Z)\n      TSTI = AIMAG(Z)\n      TEST = R1MACH(1)*1.0E+3\n      AC = FNU*TEST\n      IF (ABS(TSTR).GT.AC .OR. ABS(TSTI).GT.AC) GO TO 15\n      AC = 2.0E0*ABS(ALOG(TEST))+FNU\n      ZETA1 = CMPLX(AC,0.0E0)\n      ZETA2 = CMPLX(FNU,0.0E0)\n      PHI=CONE\n      ARG=CONE\n      RETURN\n   15 CONTINUE\n      ZB = Z*CMPLX(RFNU,0.0E0)\n      RFNU2 = RFNU*RFNU\nC-----------------------------------------------------------------------\nC     COMPUTE IN THE FOURTH QUADRANT\nC-----------------------------------------------------------------------\n      FN13 = FNU**EX1\n      FN23 = FN13*FN13\n      RFN13 = CMPLX(1.0E0/FN13,0.0E0)\n      W2 = CONE - ZB*ZB\n      AW2 = CABS(W2)\n      IF (AW2.GT.0.25E0) GO TO 130\nC-----------------------------------------------------------------------\nC     POWER SERIES FOR CABS(W2).LE.0.25E0\nC-----------------------------------------------------------------------\n      K = 1\n      P(1) = CONE\n      SUMA = CMPLX(GAMA(1),0.0E0)\n      AP(1) = 1.0E0\n      IF (AW2.LT.TOL) GO TO 20\n      DO 10 K=2,30\n        P(K) = P(K-1)*W2\n        SUMA = SUMA + P(K)*CMPLX(GAMA(K),0.0E0)\n        AP(K) = AP(K-1)*AW2\n        IF (AP(K).LT.TOL) GO TO 20\n   10 CONTINUE\n      K = 30\n   20 CONTINUE\n      KMAX = K\n      ZETA = W2*SUMA\n      ARG = ZETA*CMPLX(FN23,0.0E0)\n      ZA = CSQRT(SUMA)\n      ZETA2 = CSQRT(W2)*CMPLX(FNU,0.0E0)\n      ZETA1 = ZETA2*(CONE+ZETA*ZA*CMPLX(EX2,0.0E0))\n      ZA = ZA + ZA\n      PHI = CSQRT(ZA)*RFN13\n      IF (IPMTR.EQ.1) GO TO 120\nC-----------------------------------------------------------------------\nC     SUM SERIES FOR ASUM AND BSUM\nC-----------------------------------------------------------------------\n      SUMB = CZERO\n      DO 30 K=1,KMAX\n        SUMB = SUMB + P(K)*CMPLX(BETA(K),0.0E0)\n   30 CONTINUE\n      ASUM = CZERO\n      BSUM = SUMB\n      L1 = 0\n      L2 = 30\n      BTOL = TOL*CABS(BSUM)\n      ATOL = TOL\n      PP = 1.0E0\n      IAS = 0\n      IBS = 0\n      IF (RFNU2.LT.TOL) GO TO 110\n      DO 100 IS=2,7\n        ATOL = ATOL/RFNU2\n        PP = PP*RFNU2\n        IF (IAS.EQ.1) GO TO 60\n        SUMA = CZERO\n        DO 40 K=1,KMAX\n          M = L1 + K\n          SUMA = SUMA + P(K)*CMPLX(ALFA(M),0.0E0)\n          IF (AP(K).LT.ATOL) GO TO 50\n   40   CONTINUE\n   50   CONTINUE\n        ASUM = ASUM + SUMA*CMPLX(PP,0.0E0)\n        IF (PP.LT.TOL) IAS = 1\n   60   CONTINUE\n        IF (IBS.EQ.1) GO TO 90\n        SUMB = CZERO\n        DO 70 K=1,KMAX\n          M = L2 + K\n          SUMB = SUMB + P(K)*CMPLX(BETA(M),0.0E0)\n          IF (AP(K).LT.ATOL) GO TO 80\n   70   CONTINUE\n   80   CONTINUE\n        BSUM = BSUM + SUMB*CMPLX(PP,0.0E0)\n        IF (PP.LT.BTOL) IBS = 1\n   90   CONTINUE\n        IF (IAS.EQ.1 .AND. IBS.EQ.1) GO TO 110\n        L1 = L1 + 30\n        L2 = L2 + 30\n  100 CONTINUE\n  110 CONTINUE\n      ASUM = ASUM + CONE\n      PP = RFNU*REAL(RFN13)\n      BSUM = BSUM*CMPLX(PP,0.0E0)\n  120 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     CABS(W2).GT.0.25E0\nC-----------------------------------------------------------------------\n  130 CONTINUE\n      W = CSQRT(W2)\n      WR = REAL(W)\n      WI = AIMAG(W)\n      IF (WR.LT.0.0E0) WR = 0.0E0\n      IF (WI.LT.0.0E0) WI = 0.0E0\n      W = CMPLX(WR,WI)\n      ZA = (CONE+W)/ZB\n      ZC = CLOG(ZA)\n      ZCR = REAL(ZC)\n      ZCI = AIMAG(ZC)\n      IF (ZCI.LT.0.0E0) ZCI = 0.0E0\n      IF (ZCI.GT.HPI) ZCI = HPI\n      IF (ZCR.LT.0.0E0) ZCR = 0.0E0\n      ZC = CMPLX(ZCR,ZCI)\n      ZTH = (ZC-W)*CMPLX(1.5E0,0.0E0)\n      CFNU = CMPLX(FNU,0.0E0)\n      ZETA1 = ZC*CFNU\n      ZETA2 = W*CFNU\n      AZTH = CABS(ZTH)\n      ZTHR = REAL(ZTH)\n      ZTHI = AIMAG(ZTH)\n      ANG = THPI\n      IF (ZTHR.GE.0.0E0 .AND. ZTHI.LT.0.0E0) GO TO 140\n      ANG = HPI\n      IF (ZTHR.EQ.0.0E0) GO TO 140\n      ANG = ATAN(ZTHI/ZTHR)\n      IF (ZTHR.LT.0.0E0) ANG = ANG + PI\n  140 CONTINUE\n      PP = AZTH**EX2\n      ANG = ANG*EX2\n      ZETAR = PP*COS(ANG)\n      ZETAI = PP*SIN(ANG)\n      IF (ZETAI.LT.0.0E0) ZETAI = 0.0E0\n      ZETA = CMPLX(ZETAR,ZETAI)\n      ARG = ZETA*CMPLX(FN23,0.0E0)\n      RTZTA = ZTH/ZETA\n      ZA = RTZTA/W\n      PHI = CSQRT(ZA+ZA)*RFN13\n      IF (IPMTR.EQ.1) GO TO 120\n      TFN = CMPLX(RFNU,0.0E0)/W\n      RZTH = CMPLX(RFNU,0.0E0)/ZTH\n      ZC = RZTH*CMPLX(AR(2),0.0E0)\n      T2 = CONE/W2\n      UP(2) = (T2*CMPLX(C(2),0.0E0)+CMPLX(C(3),0.0E0))*TFN\n      BSUM = UP(2) + ZC\n      ASUM = CZERO\n      IF (RFNU.LT.TOL) GO TO 220\n      PRZTH = RZTH\n      PTFN = TFN\n      UP(1) = CONE\n      PP = 1.0E0\n      BSUMR = REAL(BSUM)\n      BSUMI = AIMAG(BSUM)\n      BTOL = TOL*(ABS(BSUMR)+ABS(BSUMI))\n      KS = 0\n      KP1 = 2\n      L = 3\n      IAS = 0\n      IBS = 0\n      DO 210 LR=2,12,2\n        LRP1 = LR + 1\nC-----------------------------------------------------------------------\nC     COMPUTE TWO ADDITIONAL CR, DR, AND UP FOR TWO MORE TERMS IN\nC     NEXT SUMA AND SUMB\nC-----------------------------------------------------------------------\n        DO 160 K=LR,LRP1\n          KS = KS + 1\n          KP1 = KP1 + 1\n          L = L + 1\n          ZA = CMPLX(C(L),0.0E0)\n          DO 150 J=2,KP1\n            L = L + 1\n            ZA = ZA*T2 + CMPLX(C(L),0.0E0)\n  150     CONTINUE\n          PTFN = PTFN*TFN\n          UP(KP1) = PTFN*ZA\n          CR(KS) = PRZTH*CMPLX(BR(KS+1),0.0E0)\n          PRZTH = PRZTH*RZTH\n          DR(KS) = PRZTH*CMPLX(AR(KS+2),0.0E0)\n  160   CONTINUE\n        PP = PP*RFNU2\n        IF (IAS.EQ.1) GO TO 180\n        SUMA = UP(LRP1)\n        JU = LRP1\n        DO 170 JR=1,LR\n          JU = JU - 1\n          SUMA = SUMA + CR(JR)*UP(JU)\n  170   CONTINUE\n        ASUM = ASUM + SUMA\n        ASUMR = REAL(ASUM)\n        ASUMI = AIMAG(ASUM)\n        TEST = ABS(ASUMR) + ABS(ASUMI)\n        IF (PP.LT.TOL .AND. TEST.LT.TOL) IAS = 1\n  180   CONTINUE\n        IF (IBS.EQ.1) GO TO 200\n        SUMB = UP(LR+2) + UP(LRP1)*ZC\n        JU = LRP1\n        DO 190 JR=1,LR\n          JU = JU - 1\n          SUMB = SUMB + DR(JR)*UP(JU)\n  190   CONTINUE\n        BSUM = BSUM + SUMB\n        BSUMR = REAL(BSUM)\n        BSUMI = AIMAG(BSUM)\n        TEST = ABS(BSUMR) + ABS(BSUMI)\n        IF (PP.LT.BTOL .AND. TEST.LT.TOL) IBS = 1\n  200   CONTINUE\n        IF (IAS.EQ.1 .AND. IBS.EQ.1) GO TO 220\n  210 CONTINUE\n  220 CONTINUE\n      ASUM = ASUM + CONE\n      BSUM = -BSUM*RFN13/RTZTA\n      GO TO 120\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cuni1.f",
    "content": "      SUBROUTINE CUNI1(Z, FNU, KODE, N, Y, NZ, NLAST, FNUL, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  CUNI1\nC***REFER TO  CBESI,CBESK\nC\nC     CUNI1 COMPUTES I(FNU,Z)  BY MEANS OF THE UNIFORM ASYMPTOTIC\nC     EXPANSION FOR I(FNU,Z) IN -PI/3.LE.ARG Z.LE.PI/3.\nC\nC     FNUL IS THE SMALLEST ORDER PERMITTED FOR THE ASYMPTOTIC\nC     EXPANSION. NLAST=0 MEANS ALL OF THE Y VALUES WERE SET.\nC     NLAST.NE.0 IS THE NUMBER LEFT TO BE COMPUTED BY ANOTHER\nC     FORMULA FOR ORDERS FNU TO FNU+NLAST-1 BECAUSE FNU+NLAST-1.LT.FNUL.\nC     Y(I)=CZERO FOR I=NLAST+1,N\nC\nC***ROUTINES CALLED  CUCHK,CUNIK,CUOIK,R1MACH\nC***END PROLOGUE  CUNI1\n      COMPLEX CFN, CONE, CRSC, CSCL, CSR, CSS, CWRK, CZERO, C1, C2,\n     * PHI, RZ, SUM, S1, S2, Y, Z, ZETA1, ZETA2, CY\n      REAL ALIM, APHI, ASCLE, BRY, C2I, C2M, C2R, ELIM, FN, FNU, FNUL,\n     * RS1, TOL, YY, R1MACH\n      INTEGER I, IFLAG, INIT, K, KODE, M, N, ND, NLAST, NN, NUF, NW, NZ\n      DIMENSION BRY(3), Y(N), CWRK(16), CSS(3), CSR(3), CY(2)\n      DATA CZERO, CONE / (0.0E0,0.0E0), (1.0E0,0.0E0) /\nC\n      NZ = 0\n      ND = N\n      NLAST = 0\nC-----------------------------------------------------------------------\nC     COMPUTED VALUES WITH EXPONENTS BETWEEN ALIM AND ELIM IN MAG-\nC     NITUDE ARE SCALED TO KEEP INTERMEDIATE ARITHMETIC ON SCALE,\nC     EXP(ALIM)=EXP(ELIM)*TOL\nC-----------------------------------------------------------------------\n      CSCL = CMPLX(1.0E0/TOL,0.0E0)\n      CRSC = CMPLX(TOL,0.0E0)\n      CSS(1) = CSCL\n      CSS(2) = CONE\n      CSS(3) = CRSC\n      CSR(1) = CRSC\n      CSR(2) = CONE\n      CSR(3) = CSCL\n      BRY(1) = 1.0E+3*R1MACH(1)/TOL\nC-----------------------------------------------------------------------\nC     CHECK FOR UNDERFLOW AND OVERFLOW ON FIRST MEMBER\nC-----------------------------------------------------------------------\n      FN = AMAX1(FNU,1.0E0)\n      INIT = 0\n      CALL CUNIK(Z, FN, 1, 1, TOL, INIT, PHI, ZETA1, ZETA2, SUM, CWRK)\n      IF (KODE.EQ.1) GO TO 10\n      CFN = CMPLX(FN,0.0E0)\n      S1 = -ZETA1 + CFN*(CFN/(Z+ZETA2))\n      GO TO 20\n   10 CONTINUE\n      S1 = -ZETA1 + ZETA2\n   20 CONTINUE\n      RS1 = REAL(S1)\n      IF (ABS(RS1).GT.ELIM) GO TO 130\n   30 CONTINUE\n      NN = MIN0(2,ND)\n      DO 80 I=1,NN\n        FN = FNU + FLOAT(ND-I)\n        INIT = 0\n        CALL CUNIK(Z, FN, 1, 0, TOL, INIT, PHI, ZETA1, ZETA2, SUM, CWRK)\n        IF (KODE.EQ.1) GO TO 40\n        CFN = CMPLX(FN,0.0E0)\n        YY = AIMAG(Z)\n        S1 = -ZETA1 + CFN*(CFN/(Z+ZETA2)) + CMPLX(0.0E0,YY)\n        GO TO 50\n   40   CONTINUE\n        S1 = -ZETA1 + ZETA2\n   50   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = REAL(S1)\n        IF (ABS(RS1).GT.ELIM) GO TO 110\n        IF (I.EQ.1) IFLAG = 2\n        IF (ABS(RS1).LT.ALIM) GO TO 60\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = CABS(PHI)\n        RS1 = RS1 + ALOG(APHI)\n        IF (ABS(RS1).GT.ELIM) GO TO 110\n        IF (I.EQ.1) IFLAG = 1\n        IF (RS1.LT.0.0E0) GO TO 60\n        IF (I.EQ.1) IFLAG = 3\n   60   CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE S1 IF CABS(S1).LT.ASCLE\nC-----------------------------------------------------------------------\n        S2 = PHI*SUM\n        C2R = REAL(S1)\n        C2I = AIMAG(S1)\n        C2M = EXP(C2R)*REAL(CSS(IFLAG))\n        S1 = CMPLX(C2M,0.0E0)*CMPLX(COS(C2I),SIN(C2I))\n        S2 = S2*S1\n        IF (IFLAG.NE.1) GO TO 70\n        CALL CUCHK(S2, NW, BRY(1), TOL)\n        IF (NW.NE.0) GO TO 110\n   70   CONTINUE\n        M = ND - I + 1\n        CY(I) = S2\n        Y(M) = S2*CSR(IFLAG)\n   80 CONTINUE\n      IF (ND.LE.2) GO TO 100\n      RZ = CMPLX(2.0E0,0.0E0)/Z\n      BRY(2) = 1.0E0/BRY(1)\n      BRY(3) = R1MACH(2)\n      S1 = CY(1)\n      S2 = CY(2)\n      C1 = CSR(IFLAG)\n      ASCLE = BRY(IFLAG)\n      K = ND - 2\n      FN = FLOAT(K)\n      DO 90 I=3,ND\n        C2 = S2\n        S2 = S1 + CMPLX(FNU+FN,0.0E0)*RZ*S2\n        S1 = C2\n        C2 = S2*C1\n        Y(K) = C2\n        K = K - 1\n        FN = FN - 1.0E0\n        IF (IFLAG.GE.3) GO TO 90\n        C2R = REAL(C2)\n        C2I = AIMAG(C2)\n        C2R = ABS(C2R)\n        C2I = ABS(C2I)\n        C2M = AMAX1(C2R,C2I)\n        IF (C2M.LE.ASCLE) GO TO 90\n        IFLAG = IFLAG + 1\n        ASCLE = BRY(IFLAG)\n        S1 = S1*C1\n        S2 = C2\n        S1 = S1*CSS(IFLAG)\n        S2 = S2*CSS(IFLAG)\n        C1 = CSR(IFLAG)\n   90 CONTINUE\n  100 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     SET UNDERFLOW AND UPDATE PARAMETERS\nC-----------------------------------------------------------------------\n  110 CONTINUE\n      IF (RS1.GT.0.0E0) GO TO 120\n      Y(ND) = CZERO\n      NZ = NZ + 1\n      ND = ND - 1\n      IF (ND.EQ.0) GO TO 100\n      CALL CUOIK(Z, FNU, KODE, 1, ND, Y, NUF, TOL, ELIM, ALIM)\n      IF (NUF.LT.0) GO TO 120\n      ND = ND - NUF\n      NZ = NZ + NUF\n      IF (ND.EQ.0) GO TO 100\n      FN = FNU + FLOAT(ND-1)\n      IF (FN.GE.FNUL) GO TO 30\n      NLAST = ND\n      RETURN\n  120 CONTINUE\n      NZ = -1\n      RETURN\n  130 CONTINUE\n      IF (RS1.GT.0.0E0) GO TO 120\n      NZ = N\n      DO 140 I=1,N\n        Y(I) = CZERO\n  140 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cuni2.f",
    "content": "      SUBROUTINE CUNI2(Z, FNU, KODE, N, Y, NZ, NLAST, FNUL, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  CUNI2\nC***REFER TO  CBESI,CBESK\nC\nC     CUNI2 COMPUTES I(FNU,Z) IN THE RIGHT HALF PLANE BY MEANS OF\nC     UNIFORM ASYMPTOTIC EXPANSION FOR J(FNU,ZN) WHERE ZN IS Z*I\nC     OR -Z*I AND ZN IS IN THE RIGHT HALF PLANE ALSO.\nC\nC     FNUL IS THE SMALLEST ORDER PERMITTED FOR THE ASYMPTOTIC\nC     EXPANSION. NLAST=0 MEANS ALL OF THE Y VALUES WERE SET.\nC     NLAST.NE.0 IS THE NUMBER LEFT TO BE COMPUTED BY ANOTHER\nC     FORMULA FOR ORDERS FNU TO FNU+NLAST-1 BECAUSE FNU+NLAST-1.LT.FNUL.\nC     Y(I)=CZERO FOR I=NLAST+1,N\nC\nC***ROUTINES CALLED  CAIRY,CUCHK,CUNHJ,CUOIK,R1MACH\nC***END PROLOGUE  CUNI2\n      COMPLEX AI, ARG, ASUM, BSUM, CFN, CI, CID, CIP, CONE, CRSC, CSCL,\n     * CSR, CSS, CY, CZERO, C1, C2, DAI, PHI, RZ, S1, S2, Y, Z, ZB,\n     * ZETA1, ZETA2, ZN, ZAR\n      REAL AARG, AIC, ALIM, ANG, APHI, ASCLE, AY, BRY, CAR, C2I, C2M,\n     * C2R, ELIM, FN, FNU, FNUL, HPI, RS1, SAR, TOL, YY, R1MACH\n      INTEGER I, IFLAG, IN, INU, J, K, KODE, N, NAI, ND, NDAI, NLAST,\n     * NN, NUF, NW, NZ, IDUM\n      DIMENSION BRY(3), Y(N), CIP(4), CSS(3), CSR(3), CY(2)\n      DATA CZERO,CONE,CI/(0.0E0,0.0E0),(1.0E0,0.0E0),(0.0E0,1.0E0)/\n      DATA CIP(1),CIP(2),CIP(3),CIP(4)/\n     1 (1.0E0,0.0E0), (0.0E0,1.0E0), (-1.0E0,0.0E0), (0.0E0,-1.0E0)/\n      DATA HPI, AIC  /\n     1      1.57079632679489662E+00,     1.265512123484645396E+00/\nC\n      NZ = 0\n      ND = N\n      NLAST = 0\nC-----------------------------------------------------------------------\nC     COMPUTED VALUES WITH EXPONENTS BETWEEN ALIM AND ELIM IN MAG-\nC     NITUDE ARE SCALED TO KEEP INTERMEDIATE ARITHMETIC ON SCALE,\nC     EXP(ALIM)=EXP(ELIM)*TOL\nC-----------------------------------------------------------------------\n      CSCL = CMPLX(1.0E0/TOL,0.0E0)\n      CRSC = CMPLX(TOL,0.0E0)\n      CSS(1) = CSCL\n      CSS(2) = CONE\n      CSS(3) = CRSC\n      CSR(1) = CRSC\n      CSR(2) = CONE\n      CSR(3) = CSCL\n      BRY(1) = 1.0E+3*R1MACH(1)/TOL\n      YY = AIMAG(Z)\nC-----------------------------------------------------------------------\nC     ZN IS IN THE RIGHT HALF PLANE AFTER ROTATION BY CI OR -CI\nC-----------------------------------------------------------------------\n      ZN = -Z*CI\n      ZB = Z\n      CID = -CI\n      INU = INT(FNU)\n      ANG = HPI*(FNU-FLOAT(INU))\n      CAR = COS(ANG)\n      SAR = SIN(ANG)\n      C2 = CMPLX(CAR,SAR)\n      ZAR = C2\n      IN = INU + N - 1\n      IN = MOD(IN,4)\n      C2 = C2*CIP(IN+1)\n      IF (YY.GT.0.0E0) GO TO 10\n      ZN = CONJG(-ZN)\n      ZB = CONJG(ZB)\n      CID = -CID\n      C2 = CONJG(C2)\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     CHECK FOR UNDERFLOW AND OVERFLOW ON FIRST MEMBER\nC-----------------------------------------------------------------------\n      FN = AMAX1(FNU,1.0E0)\n      CALL CUNHJ(ZN, FN, 1, TOL, PHI, ARG, ZETA1, ZETA2, ASUM, BSUM)\n      IF (KODE.EQ.1) GO TO 20\n      CFN = CMPLX(FNU,0.0E0)\n      S1 = -ZETA1 + CFN*(CFN/(ZB+ZETA2))\n      GO TO 30\n   20 CONTINUE\n      S1 = -ZETA1 + ZETA2\n   30 CONTINUE\n      RS1 = REAL(S1)\n      IF (ABS(RS1).GT.ELIM) GO TO 150\n   40 CONTINUE\n      NN = MIN0(2,ND)\n      DO 90 I=1,NN\n        FN = FNU + FLOAT(ND-I)\n        CALL CUNHJ(ZN, FN, 0, TOL, PHI, ARG, ZETA1, ZETA2, ASUM, BSUM)\n        IF (KODE.EQ.1) GO TO 50\n        CFN = CMPLX(FN,0.0E0)\n        AY = ABS(YY)\n        S1 = -ZETA1 + CFN*(CFN/(ZB+ZETA2)) + CMPLX(0.0E0,AY)\n        GO TO 60\n   50   CONTINUE\n        S1 = -ZETA1 + ZETA2\n   60   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = REAL(S1)\n        IF (ABS(RS1).GT.ELIM) GO TO 120\n        IF (I.EQ.1) IFLAG = 2\n        IF (ABS(RS1).LT.ALIM) GO TO 70\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\nC-----------------------------------------------------------------------\n        APHI = CABS(PHI)\n        AARG = CABS(ARG)\n        RS1 = RS1 + ALOG(APHI) - 0.25E0*ALOG(AARG) - AIC\n        IF (ABS(RS1).GT.ELIM) GO TO 120\n        IF (I.EQ.1) IFLAG = 1\n        IF (RS1.LT.0.0E0) GO TO 70\n        IF (I.EQ.1) IFLAG = 3\n   70   CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR\nC     EXPONENT EXTREMES\nC-----------------------------------------------------------------------\n        CALL CAIRY(ARG, 0, 2, AI, NAI, IDUM)\n        CALL CAIRY(ARG, 1, 2, DAI, NDAI, IDUM)\n        S2 = PHI*(AI*ASUM+DAI*BSUM)\n        C2R = REAL(S1)\n        C2I = AIMAG(S1)\n        C2M = EXP(C2R)*REAL(CSS(IFLAG))\n        S1 = CMPLX(C2M,0.0E0)*CMPLX(COS(C2I),SIN(C2I))\n        S2 = S2*S1\n        IF (IFLAG.NE.1) GO TO 80\n        CALL CUCHK(S2, NW, BRY(1), TOL)\n        IF (NW.NE.0) GO TO 120\n   80   CONTINUE\n        IF (YY.LE.0.0E0) S2 = CONJG(S2)\n        J = ND - I + 1\n        S2 = S2*C2\n        CY(I) = S2\n        Y(J) = S2*CSR(IFLAG)\n        C2 = C2*CID\n   90 CONTINUE\n      IF (ND.LE.2) GO TO 110\n      RZ = CMPLX(2.0E0,0.0E0)/Z\n      BRY(2) = 1.0E0/BRY(1)\n      BRY(3) = R1MACH(2)\n      S1 = CY(1)\n      S2 = CY(2)\n      C1 = CSR(IFLAG)\n      ASCLE = BRY(IFLAG)\n      K = ND - 2\n      FN = FLOAT(K)\n      DO 100 I=3,ND\n        C2 = S2\n        S2 = S1 + CMPLX(FNU+FN,0.0E0)*RZ*S2\n        S1 = C2\n        C2 = S2*C1\n        Y(K) = C2\n        K = K - 1\n        FN = FN - 1.0E0\n        IF (IFLAG.GE.3) GO TO 100\n        C2R = REAL(C2)\n        C2I = AIMAG(C2)\n        C2R = ABS(C2R)\n        C2I = ABS(C2I)\n        C2M = AMAX1(C2R,C2I)\n        IF (C2M.LE.ASCLE) GO TO 100\n        IFLAG = IFLAG + 1\n        ASCLE = BRY(IFLAG)\n        S1 = S1*C1\n        S2 = C2\n        S1 = S1*CSS(IFLAG)\n        S2 = S2*CSS(IFLAG)\n        C1 = CSR(IFLAG)\n  100 CONTINUE\n  110 CONTINUE\n      RETURN\n  120 CONTINUE\n      IF (RS1.GT.0.0E0) GO TO 140\nC-----------------------------------------------------------------------\nC     SET UNDERFLOW AND UPDATE PARAMETERS\nC-----------------------------------------------------------------------\n      Y(ND) = CZERO\n      NZ = NZ + 1\n      ND = ND - 1\n      IF (ND.EQ.0) GO TO 110\n      CALL CUOIK(Z, FNU, KODE, 1, ND, Y, NUF, TOL, ELIM, ALIM)\n      IF (NUF.LT.0) GO TO 140\n      ND = ND - NUF\n      NZ = NZ + NUF\n      IF (ND.EQ.0) GO TO 110\n      FN = FNU + FLOAT(ND-1)\n      IF (FN.LT.FNUL) GO TO 130\nC      FN = AIMAG(CID)\nC      J = NUF + 1\nC      K = MOD(J,4) + 1\nC      S1 = CIP(K)\nC      IF (FN.LT.0.0E0) S1 = CONJG(S1)\nC      C2 = C2*S1\n      IN = INU + ND - 1\n      IN = MOD(IN,4) + 1\n      C2 = ZAR*CIP(IN)\n      IF (YY.LE.0.0E0)C2=CONJG(C2)\n      GO TO 40\n  130 CONTINUE\n      NLAST = ND\n      RETURN\n  140 CONTINUE\n      NZ = -1\n      RETURN\n  150 CONTINUE\n      IF (RS1.GT.0.0E0) GO TO 140\n      NZ = N\n      DO 160 I=1,N\n        Y(I) = CZERO\n  160 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cunik.f",
    "content": "      SUBROUTINE CUNIK(ZR, FNU, IKFLG, IPMTR, TOL, INIT, PHI, ZETA1,\n     * ZETA2, SUM, CWRK)\nC***BEGIN PROLOGUE  CUNIK\nC***REFER TO  CBESI,CBESK\nC\nC        CUNIK COMPUTES PARAMETERS FOR THE UNIFORM ASYMPTOTIC\nC        EXPANSIONS OF THE I AND K FUNCTIONS ON IKFLG= 1 OR 2\nC        RESPECTIVELY BY\nC\nC        W(FNU,ZR) = PHI*EXP(ZETA)*SUM\nC\nC        WHERE       ZETA=-ZETA1 + ZETA2       OR\nC                          ZETA1 - ZETA2\nC\nC        THE FIRST CALL MUST HAVE INIT=0. SUBSEQUENT CALLS WITH THE\nC        SAME ZR AND FNU WILL RETURN THE I OR K FUNCTION ON IKFLG=\nC        1 OR 2 WITH NO CHANGE IN INIT. CWRK IS A COMPLEX WORK\nC        ARRAY. IPMTR=0 COMPUTES ALL PARAMETERS. IPMTR=1 COMPUTES PHI,\nC        ZETA1,ZETA2.\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  CUNIK\n      COMPLEX CFN, CON, CONE, CRFN, CWRK, CZERO, PHI, S, SR, SUM, T,\n     * T2, ZETA1, ZETA2, ZN, ZR\n      REAL AC, C, FNU, RFN, TEST, TOL, TSTR, TSTI\n      INTEGER I, IKFLG, INIT, IPMTR, J, K, L\n      DIMENSION C(120), CWRK(16), CON(2)\n      DATA CZERO, CONE / (0.0E0,0.0E0), (1.0E0,0.0E0) /\n      DATA CON(1), CON(2)  /\n     1(3.98942280401432678E-01,0.0E0),(1.25331413731550025E+00,0.0E0)/\n      DATA C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10),\n     1     C(11), C(12), C(13), C(14), C(15), C(16), C(17), C(18),\n     2     C(19), C(20), C(21), C(22), C(23), C(24)/\n     3     1.00000000000000000E+00,    -2.08333333333333333E-01,\n     4     1.25000000000000000E-01,     3.34201388888888889E-01,\n     5    -4.01041666666666667E-01,     7.03125000000000000E-02,\n     6    -1.02581259645061728E+00,     1.84646267361111111E+00,\n     7    -8.91210937500000000E-01,     7.32421875000000000E-02,\n     8     4.66958442342624743E+00,    -1.12070026162229938E+01,\n     9     8.78912353515625000E+00,    -2.36408691406250000E+00,\n     A     1.12152099609375000E-01,    -2.82120725582002449E+01,\n     B     8.46362176746007346E+01,    -9.18182415432400174E+01,\n     C     4.25349987453884549E+01,    -7.36879435947963170E+00,\n     D     2.27108001708984375E-01,     2.12570130039217123E+02,\n     E    -7.65252468141181642E+02,     1.05999045252799988E+03/\n      DATA C(25), C(26), C(27), C(28), C(29), C(30), C(31), C(32),\n     1     C(33), C(34), C(35), C(36), C(37), C(38), C(39), C(40),\n     2     C(41), C(42), C(43), C(44), C(45), C(46), C(47), C(48)/\n     3    -6.99579627376132541E+02,     2.18190511744211590E+02,\n     4    -2.64914304869515555E+01,     5.72501420974731445E-01,\n     5    -1.91945766231840700E+03,     8.06172218173730938E+03,\n     6    -1.35865500064341374E+04,     1.16553933368645332E+04,\n     7    -5.30564697861340311E+03,     1.20090291321635246E+03,\n     8    -1.08090919788394656E+02,     1.72772750258445740E+00,\n     9     2.02042913309661486E+04,    -9.69805983886375135E+04,\n     A     1.92547001232531532E+05,    -2.03400177280415534E+05,\n     B     1.22200464983017460E+05,    -4.11926549688975513E+04,\n     C     7.10951430248936372E+03,    -4.93915304773088012E+02,\n     D     6.07404200127348304E+00,    -2.42919187900551333E+05,\n     E     1.31176361466297720E+06,    -2.99801591853810675E+06/\n      DATA C(49), C(50), C(51), C(52), C(53), C(54), C(55), C(56),\n     1     C(57), C(58), C(59), C(60), C(61), C(62), C(63), C(64),\n     2     C(65), C(66), C(67), C(68), C(69), C(70), C(71), C(72)/\n     3     3.76327129765640400E+06,    -2.81356322658653411E+06,\n     4     1.26836527332162478E+06,    -3.31645172484563578E+05,\n     5     4.52187689813627263E+04,    -2.49983048181120962E+03,\n     6     2.43805296995560639E+01,     3.28446985307203782E+06,\n     7    -1.97068191184322269E+07,     5.09526024926646422E+07,\n     8    -7.41051482115326577E+07,     6.63445122747290267E+07,\n     9    -3.75671766607633513E+07,     1.32887671664218183E+07,\n     A    -2.78561812808645469E+06,     3.08186404612662398E+05,\n     B    -1.38860897537170405E+04,     1.10017140269246738E+02,\n     C    -4.93292536645099620E+07,     3.25573074185765749E+08,\n     D    -9.39462359681578403E+08,     1.55359689957058006E+09,\n     E    -1.62108055210833708E+09,     1.10684281682301447E+09/\n      DATA C(73), C(74), C(75), C(76), C(77), C(78), C(79), C(80),\n     1     C(81), C(82), C(83), C(84), C(85), C(86), C(87), C(88),\n     2     C(89), C(90), C(91), C(92), C(93), C(94), C(95), C(96)/\n     3    -4.95889784275030309E+08,     1.42062907797533095E+08,\n     4    -2.44740627257387285E+07,     2.24376817792244943E+06,\n     5    -8.40054336030240853E+04,     5.51335896122020586E+02,\n     6     8.14789096118312115E+08,    -5.86648149205184723E+09,\n     7     1.86882075092958249E+10,    -3.46320433881587779E+10,\n     8     4.12801855797539740E+10,    -3.30265997498007231E+10,\n     9     1.79542137311556001E+10,    -6.56329379261928433E+09,\n     A     1.55927986487925751E+09,    -2.25105661889415278E+08,\n     B     1.73951075539781645E+07,    -5.49842327572288687E+05,\n     C     3.03809051092238427E+03,    -1.46792612476956167E+10,\n     D     1.14498237732025810E+11,    -3.99096175224466498E+11,\n     E     8.19218669548577329E+11,    -1.09837515608122331E+12/\n      DATA C(97), C(98), C(99), C(100), C(101), C(102), C(103), C(104),\n     1     C(105), C(106), C(107), C(108), C(109), C(110), C(111),\n     2     C(112), C(113), C(114), C(115), C(116), C(117), C(118)/\n     3     1.00815810686538209E+12,    -6.45364869245376503E+11,\n     4     2.87900649906150589E+11,    -8.78670721780232657E+10,\n     5     1.76347306068349694E+10,    -2.16716498322379509E+09,\n     6     1.43157876718888981E+08,    -3.87183344257261262E+06,\n     7     1.82577554742931747E+04,     2.86464035717679043E+11,\n     8    -2.40629790002850396E+12,     9.10934118523989896E+12,\n     9    -2.05168994109344374E+13,     3.05651255199353206E+13,\n     A    -3.16670885847851584E+13,     2.33483640445818409E+13,\n     B    -1.23204913055982872E+13,     4.61272578084913197E+12,\n     C    -1.19655288019618160E+12,     2.05914503232410016E+11,\n     D    -2.18229277575292237E+10,     1.24700929351271032E+09/\n      DATA C(119), C(120)/\n     1    -2.91883881222208134E+07,     1.18838426256783253E+05/\nC\n      IF (INIT.NE.0) GO TO 40\nC-----------------------------------------------------------------------\nC     INITIALIZE ALL VARIABLES\nC-----------------------------------------------------------------------\n      RFN = 1.0E0/FNU\n      CRFN = CMPLX(RFN,0.0E0)\nC     T = ZR*CRFN\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST (ZR/FNU TOO SMALL)\nC-----------------------------------------------------------------------\n      TSTR = REAL(ZR)\n      TSTI = AIMAG(ZR)\n      TEST = R1MACH(1)*1.0E+3\n      AC = FNU*TEST\n      IF (ABS(TSTR).GT.AC .OR. ABS(TSTI).GT.AC) GO TO 15\n      AC = 2.0E0*ABS(ALOG(TEST))+FNU\n      ZETA1 = CMPLX(AC,0.0E0)\n      ZETA2 = CMPLX(FNU,0.0E0)\n      PHI=CONE\n      RETURN\n   15 CONTINUE\n      T=ZR*CRFN\n      S = CONE + T*T\n      SR = CSQRT(S)\n      CFN = CMPLX(FNU,0.0E0)\n      ZN = (CONE+SR)/T\n      ZETA1 = CFN*CLOG(ZN)\n      ZETA2 = CFN*SR\n      T = CONE/SR\n      SR = T*CRFN\n      CWRK(16) = CSQRT(SR)\n      PHI = CWRK(16)*CON(IKFLG)\n      IF (IPMTR.NE.0) RETURN\n      T2 = CONE/S\n      CWRK(1) = CONE\n      CRFN = CONE\n      AC = 1.0E0\n      L = 1\n      DO 20 K=2,15\n        S = CZERO\n        DO 10 J=1,K\n          L = L + 1\n          S = S*T2 + CMPLX(C(L),0.0E0)\n   10   CONTINUE\n        CRFN = CRFN*SR\n        CWRK(K) = CRFN*S\n        AC = AC*RFN\n        TSTR = REAL(CWRK(K))\n        TSTI = AIMAG(CWRK(K))\n        TEST = ABS(TSTR) + ABS(TSTI)\n        IF (AC.LT.TOL .AND. TEST.LT.TOL) GO TO 30\n   20 CONTINUE\n      K = 15\n   30 CONTINUE\n      INIT = K\n   40 CONTINUE\n      IF (IKFLG.EQ.2) GO TO 60\nC-----------------------------------------------------------------------\nC     COMPUTE SUM FOR THE I FUNCTION\nC-----------------------------------------------------------------------\n      S = CZERO\n      DO 50 I=1,INIT\n        S = S + CWRK(I)\n   50 CONTINUE\n      SUM = S\n      PHI = CWRK(16)*CON(1)\n      RETURN\n   60 CONTINUE\nC-----------------------------------------------------------------------\nC     COMPUTE SUM FOR THE K FUNCTION\nC-----------------------------------------------------------------------\n      S = CZERO\n      T = CONE\n      DO 70 I=1,INIT\n        S = S + T*CWRK(I)\n        T = -T\n   70 CONTINUE\n      SUM = S\n      PHI = CWRK(16)*CON(2)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cunk1.f",
    "content": "      SUBROUTINE CUNK1(Z, FNU, KODE, MR, N, Y, NZ, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  CUNK1\nC***REFER TO  CBESK\nC\nC     CUNK1 COMPUTES K(FNU,Z) AND ITS ANALYTIC CONTINUATION FROM THE\nC     RIGHT HALF PLANE TO THE LEFT HALF PLANE BY MEANS OF THE\nC     UNIFORM ASYMPTOTIC EXPANSION.\nC     MR INDICATES THE DIRECTION OF ROTATION FOR ANALYTIC CONTINUATION.\nC     NZ=-1 MEANS AN OVERFLOW WILL OCCUR\nC\nC***ROUTINES CALLED  CS1S2,CUCHK,CUNIK,R1MACH\nC***END PROLOGUE  CUNK1\n      COMPLEX CFN, CK, CONE, CRSC, CS, CSCL, CSGN, CSPN, CSR, CSS,\n     * CWRK, CY, CZERO, C1, C2, PHI,  RZ, SUM,  S1, S2, Y, Z,\n     * ZETA1,  ZETA2,  ZR, PHID, ZETA1D, ZETA2D, SUMD\n      REAL ALIM, ANG, APHI, ASC, ASCLE, BRY, CPN, C2I, C2M, C2R, ELIM,\n     * FMR, FN, FNF, FNU, PI, RS1, SGN, SPN, TOL, X, R1MACH\n      INTEGER I, IB, IFLAG, IFN, IL, INIT, INU, IUF, K, KDFLG, KFLAG,\n     * KK, KODE, MR, N, NW, NZ, J, IPARD, INITD, IC\n      DIMENSION BRY(3), INIT(2), Y(N), SUM(2), PHI(2), ZETA1(2),\n     * ZETA2(2), CY(2), CWRK(16,3), CSS(3), CSR(3)\n      DATA CZERO, CONE / (0.0E0,0.0E0) , (1.0E0,0.0E0) /\n      DATA PI / 3.14159265358979324E0 /\nC\n      KDFLG = 1\n      NZ = 0\nC-----------------------------------------------------------------------\nC     EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION GREATER THAN\nC     THE UNDERFLOW LIMIT\nC-----------------------------------------------------------------------\n      CSCL = CMPLX(1.0E0/TOL,0.0E0)\n      CRSC = CMPLX(TOL,0.0E0)\n      CSS(1) = CSCL\n      CSS(2) = CONE\n      CSS(3) = CRSC\n      CSR(1) = CRSC\n      CSR(2) = CONE\n      CSR(3) = CSCL\n      BRY(1) = 1.0E+3*R1MACH(1)/TOL\n      BRY(2) = 1.0E0/BRY(1)\n      BRY(3) = R1MACH(2)\n      X = REAL(Z)\n      ZR = Z\n      IF (X.LT.0.0E0) ZR = -Z\n      J=2\n      DO 70 I=1,N\nC-----------------------------------------------------------------------\nC     J FLIP FLOPS BETWEEN 1 AND 2 IN J = 3 - J\nC-----------------------------------------------------------------------\n        J = 3 - J\n        FN = FNU + FLOAT(I-1)\n        INIT(J) = 0\n        CALL CUNIK(ZR, FN, 2, 0, TOL, INIT(J), PHI(J), ZETA1(J),\n     *   ZETA2(J), SUM(J), CWRK(1,J))\n        IF (KODE.EQ.1) GO TO 20\n        CFN = CMPLX(FN,0.0E0)\n        S1 = ZETA1(J) - CFN*(CFN/(ZR+ZETA2(J)))\n        GO TO 30\n   20   CONTINUE\n        S1 = ZETA1(J) - ZETA2(J)\n   30   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = REAL(S1)\n        IF (ABS(RS1).GT.ELIM) GO TO 60\n        IF (KDFLG.EQ.1) KFLAG = 2\n        IF (ABS(RS1).LT.ALIM) GO TO 40\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = CABS(PHI(J))\n        RS1 = RS1 + ALOG(APHI)\n        IF (ABS(RS1).GT.ELIM) GO TO 60\n        IF (KDFLG.EQ.1) KFLAG = 1\n        IF (RS1.LT.0.0E0) GO TO 40\n        IF (KDFLG.EQ.1) KFLAG = 3\n   40   CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR\nC     EXPONENT EXTREMES\nC-----------------------------------------------------------------------\n        S2 = PHI(J)*SUM(J)\n        C2R = REAL(S1)\n        C2I = AIMAG(S1)\n        C2M = EXP(C2R)*REAL(CSS(KFLAG))\n        S1 = CMPLX(C2M,0.0E0)*CMPLX(COS(C2I),SIN(C2I))\n        S2 = S2*S1\n        IF (KFLAG.NE.1) GO TO 50\n        CALL CUCHK(S2, NW, BRY(1), TOL)\n        IF (NW.NE.0) GO TO 60\n   50   CONTINUE\n        CY(KDFLG) = S2\n        Y(I) = S2*CSR(KFLAG)\n        IF (KDFLG.EQ.2) GO TO 75\n        KDFLG = 2\n        GO TO 70\n   60   CONTINUE\n        IF (RS1.GT.0.0E0) GO TO 290\nC-----------------------------------------------------------------------\nC     FOR X.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW\nC-----------------------------------------------------------------------\n        IF (X.LT.0.0E0) GO TO 290\n        KDFLG = 1\n        Y(I) = CZERO\n        NZ=NZ+1\n        IF (I.EQ.1) GO TO 70\n        IF (Y(I-1).EQ.CZERO) GO TO 70\n        Y(I-1) = CZERO\n        NZ=NZ+1\n   70 CONTINUE\n      I=N\n   75 CONTINUE\n      RZ = CMPLX(2.0E0,0.0E0)/ZR\n      CK = CMPLX(FN,0.0E0)*RZ\n      IB = I+1\n      IF (N.LT.IB) GO TO 160\nC-----------------------------------------------------------------------\nC     TEST LAST MEMBER FOR UNDERFLOW AND OVERFLOW, SET SEQUENCE TO ZERO\nC     ON UNDERFLOW\nC-----------------------------------------------------------------------\n      FN = FNU+FLOAT(N-1)\n      IPARD = 1\n      IF (MR.NE.0) IPARD = 0\n      INITD = 0\n      CALL CUNIK(ZR,FN,2,IPARD,TOL,INITD,PHID,ZETA1D,ZETA2D,SUMD,\n     *CWRK(1,3))\n      IF (KODE.EQ.1) GO TO 80\n      CFN=CMPLX(FN,0.0E0)\n      S1=ZETA1D-CFN*(CFN/(ZR+ZETA2D))\n      GO TO 90\n   80 CONTINUE\n      S1=ZETA1D-ZETA2D\n   90 CONTINUE\n      RS1=REAL(S1)\n      IF (ABS(RS1).GT.ELIM) GO TO 95\n      IF (ABS(RS1).LT.ALIM) GO TO 100\nC-----------------------------------------------------------------------\nC     REFINE ESTIMATE AND TEST\nC-----------------------------------------------------------------------\n      APHI=CABS(PHID)\n      RS1=RS1+ALOG(APHI)\n      IF (ABS(RS1).LT.ELIM) GO TO 100\n   95 CONTINUE\n      IF (RS1.GT.0.0E0) GO TO 290\nC-----------------------------------------------------------------------\nC     FOR X.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW\nC-----------------------------------------------------------------------\n      IF (X.LT.0.0E0) GO TO 290\n      NZ=N\n      DO 96 I=1,N\n        Y(I) = CZERO\n   96 CONTINUE\n      RETURN\n  100 CONTINUE\nC-----------------------------------------------------------------------\nC     RECUR FORWARD FOR REMAINDER OF THE SEQUENCE\nC-----------------------------------------------------------------------\n      S1 = CY(1)\n      S2 = CY(2)\n      C1 = CSR(KFLAG)\n      ASCLE = BRY(KFLAG)\n      DO 120 I=IB,N\n        C2 = S2\n        S2 = CK*S2 + S1\n        S1 = C2\n        CK = CK + RZ\n        C2 = S2*C1\n        Y(I) = C2\n        IF (KFLAG.GE.3) GO TO 120\n        C2R = REAL(C2)\n        C2I = AIMAG(C2)\n        C2R = ABS(C2R)\n        C2I = ABS(C2I)\n        C2M = AMAX1(C2R,C2I)\n        IF (C2M.LE.ASCLE) GO TO 120\n        KFLAG = KFLAG + 1\n        ASCLE = BRY(KFLAG)\n        S1 = S1*C1\n        S2 = C2\n        S1 = S1*CSS(KFLAG)\n        S2 = S2*CSS(KFLAG)\n        C1 = CSR(KFLAG)\n  120 CONTINUE\n  160 CONTINUE\n      IF (MR.EQ.0) RETURN\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION FOR RE(Z).LT.0.0E0\nC-----------------------------------------------------------------------\n      NZ = 0\n      FMR = FLOAT(MR)\n      SGN = -SIGN(PI,FMR)\nC-----------------------------------------------------------------------\nC     CSPN AND CSGN ARE COEFF OF K AND I FUNCIONS RESP.\nC-----------------------------------------------------------------------\n      CSGN = CMPLX(0.0E0,SGN)\n      INU = INT(FNU)\n      FNF = FNU - FLOAT(INU)\n      IFN = INU + N - 1\n      ANG = FNF*SGN\n      CPN = COS(ANG)\n      SPN = SIN(ANG)\n      CSPN = CMPLX(CPN,SPN)\n      IF (MOD(IFN,2).EQ.1) CSPN = -CSPN\n      ASC = BRY(1)\n      KK = N\n      IUF = 0\n      KDFLG = 1\n      IB = IB-1\n      IC = IB-1\n      DO 260 K=1,N\n        FN = FNU + FLOAT(KK-1)\nC-----------------------------------------------------------------------\nC     LOGIC TO SORT OUT CASES WHOSE PARAMETERS WERE SET FOR THE K\nC     FUNCTION ABOVE\nC-----------------------------------------------------------------------\n        M=3\n        IF (N.GT.2) GO TO 175\n  170   CONTINUE\n        INITD = INIT(J)\n        PHID = PHI(J)\n        ZETA1D = ZETA1(J)\n        ZETA2D = ZETA2(J)\n        SUMD = SUM(J)\n        M = J\n        J = 3 - J\n        GO TO 180\n  175   CONTINUE\n        IF ((KK.EQ.N).AND.(IB.LT.N)) GO TO 180\n        IF ((KK.EQ.IB).OR.(KK.EQ.IC)) GO TO 170\n        INITD = 0\n  180   CONTINUE\n        CALL CUNIK(ZR, FN, 1, 0, TOL, INITD, PHID, ZETA1D,\n     *   ZETA2D, SUMD, CWRK(1,M))\n        IF (KODE.EQ.1) GO TO 190\n        CFN = CMPLX(FN,0.0E0)\n        S1 = -ZETA1D + CFN*(CFN/(ZR+ZETA2D))\n        GO TO 200\n  190   CONTINUE\n        S1 = -ZETA1D + ZETA2D\n  200   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = REAL(S1)\n        IF (ABS(RS1).GT.ELIM) GO TO 250\n        IF (KDFLG.EQ.1) IFLAG = 2\n        IF (ABS(RS1).LT.ALIM) GO TO 210\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = CABS(PHID)\n        RS1 = RS1 + ALOG(APHI)\n        IF (ABS(RS1).GT.ELIM) GO TO 250\n        IF (KDFLG.EQ.1) IFLAG = 1\n        IF (RS1.LT.0.0E0) GO TO 210\n        IF (KDFLG.EQ.1) IFLAG = 3\n  210   CONTINUE\n        S2 = CSGN*PHID*SUMD\n        C2R = REAL(S1)\n        C2I = AIMAG(S1)\n        C2M = EXP(C2R)*REAL(CSS(IFLAG))\n        S1 = CMPLX(C2M,0.0E0)*CMPLX(COS(C2I),SIN(C2I))\n        S2 = S2*S1\n        IF (IFLAG.NE.1) GO TO 220\n        CALL CUCHK(S2, NW, BRY(1), TOL)\n        IF (NW.NE.0) S2 = CMPLX(0.0E0,0.0E0)\n  220   CONTINUE\n        CY(KDFLG) = S2\n        C2 = S2\n        S2 = S2*CSR(IFLAG)\nC-----------------------------------------------------------------------\nC     ADD I AND K FUNCTIONS, K SEQUENCE IN Y(I), I=1,N\nC-----------------------------------------------------------------------\n        S1 = Y(KK)\n        IF (KODE.EQ.1) GO TO 240\n        CALL CS1S2(ZR, S1, S2, NW, ASC, ALIM, IUF)\n        NZ = NZ + NW\n  240   CONTINUE\n        Y(KK) = S1*CSPN + S2\n        KK = KK - 1\n        CSPN = -CSPN\n        IF (C2.NE.CZERO) GO TO 245\n        KDFLG = 1\n        GO TO 260\n  245   CONTINUE\n        IF (KDFLG.EQ.2) GO TO 265\n        KDFLG = 2\n        GO TO 260\n  250   CONTINUE\n        IF (RS1.GT.0.0E0) GO TO 290\n        S2 = CZERO\n        GO TO 220\n  260 CONTINUE\n      K = N\n  265 CONTINUE\n      IL = N - K\n      IF (IL.EQ.0) RETURN\nC-----------------------------------------------------------------------\nC     RECUR BACKWARD FOR REMAINDER OF I SEQUENCE AND ADD IN THE\nC     K FUNCTIONS, SCALING THE I SEQUENCE DURING RECURRENCE TO KEEP\nC     INTERMEDIATE ARITHMETIC ON SCALE NEAR EXPONENT EXTREMES.\nC-----------------------------------------------------------------------\n      S1 = CY(1)\n      S2 = CY(2)\n      CS = CSR(IFLAG)\n      ASCLE = BRY(IFLAG)\n      FN = FLOAT(INU+IL)\n      DO 280 I=1,IL\n        C2 = S2\n        S2 = S1 + CMPLX(FN+FNF,0.0E0)*RZ*S2\n        S1 = C2\n        FN = FN - 1.0E0\n        C2 = S2*CS\n        CK = C2\n        C1 = Y(KK)\n        IF (KODE.EQ.1) GO TO 270\n        CALL CS1S2(ZR, C1, C2, NW, ASC, ALIM, IUF)\n        NZ = NZ + NW\n  270   CONTINUE\n        Y(KK) = C1*CSPN + C2\n        KK = KK - 1\n        CSPN = -CSPN\n        IF (IFLAG.GE.3) GO TO 280\n        C2R = REAL(CK)\n        C2I = AIMAG(CK)\n        C2R = ABS(C2R)\n        C2I = ABS(C2I)\n        C2M = AMAX1(C2R,C2I)\n        IF (C2M.LE.ASCLE) GO TO 280\n        IFLAG = IFLAG + 1\n        ASCLE = BRY(IFLAG)\n        S1 = S1*CS\n        S2 = CK\n        S1 = S1*CSS(IFLAG)\n        S2 = S2*CSS(IFLAG)\n        CS = CSR(IFLAG)\n  280 CONTINUE\n      RETURN\n  290 CONTINUE\n      NZ = -1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cunk2.f",
    "content": "      SUBROUTINE CUNK2(Z, FNU, KODE, MR, N, Y, NZ, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  CUNK2\nC***REFER TO  CBESK\nC\nC     CUNK2 COMPUTES K(FNU,Z) AND ITS ANALYTIC CONTINUATION FROM THE\nC     RIGHT HALF PLANE TO THE LEFT HALF PLANE BY MEANS OF THE\nC     UNIFORM ASYMPTOTIC EXPANSIONS FOR H(KIND,FNU,ZN) AND J(FNU,ZN)\nC     WHERE ZN IS IN THE RIGHT HALF PLANE, KIND=(3-MR)/2, MR=+1 OR\nC     -1. HERE ZN=ZR*I OR -ZR*I WHERE ZR=Z IF Z IS IN THE RIGHT\nC     HALF PLANE OR ZR=-Z IF Z IS IN THE LEFT HALF PLANE. MR INDIC-\nC     ATES THE DIRECTION OF ROTATION FOR ANALYTIC CONTINUATION.\nC     NZ=-1 MEANS AN OVERFLOW WILL OCCUR\nC\nC***ROUTINES CALLED  CAIRY,CS1S2,CUCHK,CUNHJ,R1MACH\nC***END PROLOGUE  CUNK2\n      COMPLEX AI, ARG, ASUM, BSUM, CFN, CI, CIP,\n     * CK, CONE, CRSC, CR1, CR2, CS, CSCL, CSGN, CSPN, CSR, CSS, CY,\n     * CZERO, C1, C2, DAI, PHI,  RZ, S1, S2, Y, Z, ZB, ZETA1,\n     * ZETA2, ZN, ZR, PHID, ARGD, ZETA1D, ZETA2D, ASUMD, BSUMD\n      REAL AARG, AIC, ALIM, ANG, APHI, ASC, ASCLE, BRY, CAR, CPN, C2I,\n     * C2M, C2R, ELIM, FMR, FN, FNF, FNU, HPI, PI, RS1, SAR, SGN, SPN,\n     * TOL, X, YY, R1MACH\n      INTEGER I, IB, IFLAG, IFN, IL, IN, INU, IUF, K, KDFLG, KFLAG, KK,\n     * KODE, MR, N, NAI, NDAI, NW, NZ, IDUM, J, IPARD, IC\n      DIMENSION BRY(3), Y(N), ASUM(2), BSUM(2), PHI(2), ARG(2),\n     * ZETA1(2), ZETA2(2), CY(2), CIP(4), CSS(3), CSR(3)\n      DATA CZERO, CONE, CI, CR1, CR2 /\n     1         (0.0E0,0.0E0),(1.0E0,0.0E0),(0.0E0,1.0E0),\n     1(1.0E0,1.73205080756887729E0),(-0.5E0,-8.66025403784438647E-01)/\n      DATA HPI, PI, AIC /\n     1     1.57079632679489662E+00,     3.14159265358979324E+00,\n     1     1.26551212348464539E+00/\n      DATA CIP(1),CIP(2),CIP(3),CIP(4)/\n     1 (1.0E0,0.0E0), (0.0E0,-1.0E0), (-1.0E0,0.0E0), (0.0E0,1.0E0)/\nC\n      KDFLG = 1\n      NZ = 0\nC-----------------------------------------------------------------------\nC     EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION GREATER THAN\nC     THE UNDERFLOW LIMIT\nC-----------------------------------------------------------------------\n      CSCL = CMPLX(1.0E0/TOL,0.0E0)\n      CRSC = CMPLX(TOL,0.0E0)\n      CSS(1) = CSCL\n      CSS(2) = CONE\n      CSS(3) = CRSC\n      CSR(1) = CRSC\n      CSR(2) = CONE\n      CSR(3) = CSCL\n      BRY(1) = 1.0E+3*R1MACH(1)/TOL\n      BRY(2) = 1.0E0/BRY(1)\n      BRY(3) = R1MACH(2)\n      X = REAL(Z)\n      ZR = Z\n      IF (X.LT.0.0E0) ZR = -Z\n      YY = AIMAG(ZR)\n      ZN = -ZR*CI\n      ZB = ZR\n      INU = INT(FNU)\n      FNF = FNU - FLOAT(INU)\n      ANG = -HPI*FNF\n      CAR = COS(ANG)\n      SAR = SIN(ANG)\n      CPN = -HPI*CAR\n      SPN = -HPI*SAR\n      C2 = CMPLX(-SPN,CPN)\n      KK = MOD(INU,4) + 1\n      CS = CR1*C2*CIP(KK)\n      IF (YY.GT.0.0E0) GO TO 10\n      ZN = CONJG(-ZN)\n      ZB = CONJG(ZB)\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     K(FNU,Z) IS COMPUTED FROM H(2,FNU,-I*Z) WHERE Z IS IN THE FIRST\nC     QUADRANT. FOURTH QUADRANT VALUES (YY.LE.0.0E0) ARE COMPUTED BY\nC     CONJUGATION SINCE THE K FUNCTION IS REAL ON THE POSITIVE REAL AXIS\nC-----------------------------------------------------------------------\n      J = 2\n      DO 70 I=1,N\nC-----------------------------------------------------------------------\nC     J FLIP FLOPS BETWEEN 1 AND 2 IN J = 3 - J\nC-----------------------------------------------------------------------\n        J = 3 - J\n        FN = FNU + FLOAT(I-1)\n        CALL CUNHJ(ZN, FN, 0, TOL, PHI(J), ARG(J), ZETA1(J), ZETA2(J),\n     *   ASUM(J), BSUM(J))\n        IF (KODE.EQ.1) GO TO 20\n        CFN = CMPLX(FN,0.0E0)\n        S1 = ZETA1(J) - CFN*(CFN/(ZB+ZETA2(J)))\n        GO TO 30\n   20   CONTINUE\n        S1 = ZETA1(J) - ZETA2(J)\n   30   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = REAL(S1)\n        IF (ABS(RS1).GT.ELIM) GO TO 60\n        IF (KDFLG.EQ.1) KFLAG = 2\n        IF (ABS(RS1).LT.ALIM) GO TO 40\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = CABS(PHI(J))\n        AARG = CABS(ARG(J))\n        RS1 = RS1 + ALOG(APHI) - 0.25E0*ALOG(AARG) - AIC\n        IF (ABS(RS1).GT.ELIM) GO TO 60\n        IF (KDFLG.EQ.1) KFLAG = 1\n        IF (RS1.LT.0.0E0) GO TO 40\n        IF (KDFLG.EQ.1) KFLAG = 3\n   40   CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR\nC     EXPONENT EXTREMES\nC-----------------------------------------------------------------------\n        C2 = ARG(J)*CR2\n        CALL CAIRY(C2, 0, 2, AI, NAI, IDUM)\n        CALL CAIRY(C2, 1, 2, DAI, NDAI, IDUM)\n        S2 = CS*PHI(J)*(AI*ASUM(J)+CR2*DAI*BSUM(J))\n        C2R = REAL(S1)\n        C2I = AIMAG(S1)\n        C2M = EXP(C2R)*REAL(CSS(KFLAG))\n        S1 = CMPLX(C2M,0.0E0)*CMPLX(COS(C2I),SIN(C2I))\n        S2 = S2*S1\n        IF (KFLAG.NE.1) GO TO 50\n        CALL CUCHK(S2, NW, BRY(1), TOL)\n        IF (NW.NE.0) GO TO 60\n   50   CONTINUE\n        IF (YY.LE.0.0E0) S2 = CONJG(S2)\n        CY(KDFLG) = S2\n        Y(I) = S2*CSR(KFLAG)\n        CS = -CI*CS\n        IF (KDFLG.EQ.2) GO TO 75\n        KDFLG = 2\n        GO TO 70\n   60   CONTINUE\n        IF (RS1.GT.0.0E0) GO TO 300\nC-----------------------------------------------------------------------\nC     FOR X.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW\nC-----------------------------------------------------------------------\n        IF (X.LT.0.0E0) GO TO 300\n        KDFLG = 1\n        Y(I) = CZERO\n        CS = -CI*CS\n        NZ=NZ+1\n        IF (I.EQ.1) GO TO 70\n        IF (Y(I-1).EQ.CZERO) GO TO 70\n        Y(I-1) = CZERO\n        NZ=NZ+1\n   70 CONTINUE\n      I=N\n   75 CONTINUE\n      RZ = CMPLX(2.0E0,0.0E0)/ZR\n      CK = CMPLX(FN,0.0E0)*RZ\n      IB = I + 1\n      IF (N.LT.IB) GO TO 170\nC-----------------------------------------------------------------------\nC     TEST LAST MEMBER FOR UNDERFLOW AND OVERFLOW, SET SEQUENCE TO ZERO\nC     ON UNDERFLOW\nC-----------------------------------------------------------------------\n      FN = FNU+FLOAT(N-1)\n      IPARD = 1\n      IF (MR.NE.0) IPARD = 0\n      CALL CUNHJ(ZN,FN,IPARD,TOL,PHID,ARGD,ZETA1D,ZETA2D,ASUMD,BSUMD)\n      IF (KODE.EQ.1) GO TO 80\n      CFN=CMPLX(FN,0.0E0)\n      S1=ZETA1D-CFN*(CFN/(ZB+ZETA2D))\n      GO TO 90\n   80 CONTINUE\n      S1=ZETA1D-ZETA2D\n   90 CONTINUE\n      RS1=REAL(S1)\n      IF (ABS(RS1).GT.ELIM) GO TO 95\n      IF (ABS(RS1).LT.ALIM) GO TO 100\nC-----------------------------------------------------------------------\nC     REFINE ESTIMATE AND TEST\nC-----------------------------------------------------------------------\n      APHI=CABS(PHID)\n      AARG = CABS(ARGD)\n      RS1=RS1+ALOG(APHI)-0.25E0*ALOG(AARG)-AIC\n      IF (ABS(RS1).LT.ELIM) GO TO 100\n   95 CONTINUE\n      IF (RS1.GT.0.0E0) GO TO 300\nC-----------------------------------------------------------------------\nC     FOR X.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW\nC-----------------------------------------------------------------------\n      IF (X.LT.0.0E0) GO TO 300\n      NZ=N\n      DO 96 I=1,N\n        Y(I) = CZERO\n   96 CONTINUE\n      RETURN\n  100 CONTINUE\nC-----------------------------------------------------------------------\nC     SCALED FORWARD RECURRENCE FOR REMAINDER OF THE SEQUENCE\nC-----------------------------------------------------------------------\n      S1 = CY(1)\n      S2 = CY(2)\n      C1 = CSR(KFLAG)\n      ASCLE = BRY(KFLAG)\n      DO 120 I=IB,N\n        C2 = S2\n        S2 = CK*S2 + S1\n        S1 = C2\n        CK = CK + RZ\n        C2 = S2*C1\n        Y(I) = C2\n        IF (KFLAG.GE.3) GO TO 120\n        C2R = REAL(C2)\n        C2I = AIMAG(C2)\n        C2R = ABS(C2R)\n        C2I = ABS(C2I)\n        C2M = AMAX1(C2R,C2I)\n        IF (C2M.LE.ASCLE) GO TO 120\n        KFLAG = KFLAG + 1\n        ASCLE = BRY(KFLAG)\n        S1 = S1*C1\n        S2 = C2\n        S1 = S1*CSS(KFLAG)\n        S2 = S2*CSS(KFLAG)\n        C1 = CSR(KFLAG)\n  120 CONTINUE\n  170 CONTINUE\n      IF (MR.EQ.0) RETURN\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION FOR RE(Z).LT.0.0E0\nC-----------------------------------------------------------------------\n      NZ = 0\n      FMR = FLOAT(MR)\n      SGN = -SIGN(PI,FMR)\nC-----------------------------------------------------------------------\nC     CSPN AND CSGN ARE COEFF OF K AND I FUNCTIONS RESP.\nC-----------------------------------------------------------------------\n      CSGN = CMPLX(0.0E0,SGN)\n      IF (YY.LE.0.0E0) CSGN = CONJG(CSGN)\n      IFN = INU + N - 1\n      ANG = FNF*SGN\n      CPN = COS(ANG)\n      SPN = SIN(ANG)\n      CSPN = CMPLX(CPN,SPN)\n      IF (MOD(IFN,2).EQ.1) CSPN = -CSPN\nC-----------------------------------------------------------------------\nC     CS=COEFF OF THE J FUNCTION TO GET THE I FUNCTION. I(FNU,Z) IS\nC     COMPUTED FROM EXP(I*FNU*HPI)*J(FNU,-I*Z) WHERE Z IS IN THE FIRST\nC     QUADRANT. FOURTH QUADRANT VALUES (YY.LE.0.0E0) ARE COMPUTED BY\nC     CONJUGATION SINCE THE I FUNCTION IS REAL ON THE POSITIVE REAL AXIS\nC-----------------------------------------------------------------------\n      CS = CMPLX(CAR,-SAR)*CSGN\n      IN = MOD(IFN,4) + 1\n      C2 = CIP(IN)\n      CS = CS*CONJG(C2)\n      ASC = BRY(1)\n      KK = N\n      KDFLG = 1\n      IB = IB-1\n      IC = IB-1\n      IUF = 0\n      DO 270 K=1,N\nC-----------------------------------------------------------------------\nC     LOGIC TO SORT OUT CASES WHOSE PARAMETERS WERE SET FOR THE K\nC     FUNCTION ABOVE\nC-----------------------------------------------------------------------\n        FN = FNU+FLOAT(KK-1)\n        IF (N.GT.2) GO TO 180\n  175   CONTINUE\n        PHID = PHI(J)\n        ARGD = ARG(J)\n        ZETA1D = ZETA1(J)\n        ZETA2D = ZETA2(J)\n        ASUMD = ASUM(J)\n        BSUMD = BSUM(J)\n        J = 3 - J\n        GO TO 190\n  180   CONTINUE\n        IF ((KK.EQ.N).AND.(IB.LT.N)) GO TO 190\n        IF ((KK.EQ.IB).OR.(KK.EQ.IC)) GO TO 175\n        CALL CUNHJ(ZN, FN, 0, TOL, PHID, ARGD, ZETA1D, ZETA2D,\n     *   ASUMD, BSUMD)\n  190   CONTINUE\n        IF (KODE.EQ.1) GO TO 200\n        CFN = CMPLX(FN,0.0E0)\n        S1 = -ZETA1D + CFN*(CFN/(ZB+ZETA2D))\n        GO TO 210\n  200   CONTINUE\n        S1 = -ZETA1D + ZETA2D\n  210   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = REAL(S1)\n        IF (ABS(RS1).GT.ELIM) GO TO 260\n        IF (KDFLG.EQ.1) IFLAG = 2\n        IF (ABS(RS1).LT.ALIM) GO TO 220\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = CABS(PHID)\n        AARG = CABS(ARGD)\n        RS1 = RS1 + ALOG(APHI) - 0.25E0*ALOG(AARG) - AIC\n        IF (ABS(RS1).GT.ELIM) GO TO 260\n        IF (KDFLG.EQ.1) IFLAG = 1\n        IF (RS1.LT.0.0E0) GO TO 220\n        IF (KDFLG.EQ.1) IFLAG = 3\n  220   CONTINUE\n        CALL CAIRY(ARGD, 0, 2, AI, NAI, IDUM)\n        CALL CAIRY(ARGD, 1, 2, DAI, NDAI, IDUM)\n        S2 = CS*PHID*(AI*ASUMD+DAI*BSUMD)\n        C2R = REAL(S1)\n        C2I = AIMAG(S1)\n        C2M = EXP(C2R)*REAL(CSS(IFLAG))\n        S1 = CMPLX(C2M,0.0E0)*CMPLX(COS(C2I),SIN(C2I))\n        S2 = S2*S1\n        IF (IFLAG.NE.1) GO TO 230\n        CALL CUCHK(S2, NW, BRY(1), TOL)\n        IF (NW.NE.0) S2 = CMPLX(0.0E0,0.0E0)\n  230   CONTINUE\n        IF (YY.LE.0.0E0) S2 = CONJG(S2)\n        CY(KDFLG) = S2\n        C2 = S2\n        S2 = S2*CSR(IFLAG)\nC-----------------------------------------------------------------------\nC     ADD I AND K FUNCTIONS, K SEQUENCE IN Y(I), I=1,N\nC-----------------------------------------------------------------------\n        S1 = Y(KK)\n        IF (KODE.EQ.1) GO TO 250\n        CALL CS1S2(ZR, S1, S2, NW, ASC, ALIM, IUF)\n        NZ = NZ + NW\n  250   CONTINUE\n        Y(KK) = S1*CSPN + S2\n        KK = KK - 1\n        CSPN = -CSPN\n        CS = -CS*CI\n        IF (C2.NE.CZERO) GO TO 255\n        KDFLG = 1\n        GO TO 270\n  255   CONTINUE\n        IF (KDFLG.EQ.2) GO TO 275\n        KDFLG = 2\n        GO TO 270\n  260   CONTINUE\n        IF (RS1.GT.0.0E0) GO TO 300\n        S2 = CZERO\n        GO TO 230\n  270 CONTINUE\n      K = N\n  275 CONTINUE\n      IL = N-K\n      IF (IL.EQ.0) RETURN\nC-----------------------------------------------------------------------\nC     RECUR BACKWARD FOR REMAINDER OF I SEQUENCE AND ADD IN THE\nC     K FUNCTIONS, SCALING THE I SEQUENCE DURING RECURRENCE TO KEEP\nC     INTERMEDIATE ARITHMETIC ON SCALE NEAR EXPONENT EXTREMES.\nC-----------------------------------------------------------------------\n      S1 = CY(1)\n      S2 = CY(2)\n      CS = CSR(IFLAG)\n      ASCLE = BRY(IFLAG)\n      FN = FLOAT(INU+IL)\n      DO 290 I=1,IL\n        C2 = S2\n        S2 = S1 + CMPLX(FN+FNF,0.0E0)*RZ*S2\n        S1 = C2\n        FN = FN - 1.0E0\n        C2 = S2*CS\n        CK = C2\n        C1 = Y(KK)\n        IF (KODE.EQ.1) GO TO 280\n        CALL CS1S2(ZR, C1, C2, NW, ASC, ALIM, IUF)\n        NZ = NZ + NW\n  280   CONTINUE\n        Y(KK) = C1*CSPN + C2\n        KK = KK - 1\n        CSPN = -CSPN\n        IF (IFLAG.GE.3) GO TO 290\n        C2R = REAL(CK)\n        C2I = AIMAG(CK)\n        C2R = ABS(C2R)\n        C2I = ABS(C2I)\n        C2M = AMAX1(C2R,C2I)\n        IF (C2M.LE.ASCLE) GO TO 290\n        IFLAG = IFLAG + 1\n        ASCLE = BRY(IFLAG)\n        S1 = S1*CS\n        S2 = CK\n        S1 = S1*CSS(IFLAG)\n        S2 = S2*CSS(IFLAG)\n        CS = CSR(IFLAG)\n  290 CONTINUE\n      RETURN\n  300 CONTINUE\n      NZ = -1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cuoik.f",
    "content": "      SUBROUTINE CUOIK(Z, FNU, KODE, IKFLG, N, Y, NUF, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  CUOIK\nC***REFER TO  CBESI,CBESK,CBESH\nC\nC     CUOIK COMPUTES THE LEADING TERMS OF THE UNIFORM ASYMPTOTIC\nC     EXPANSIONS FOR THE I AND K FUNCTIONS AND COMPARES THEM\nC     (IN LOGARITHMIC FORM) TO ALIM AND ELIM FOR OVER AND UNDERFLOW\nC     WHERE ALIM.LT.ELIM. IF THE MAGNITUDE, BASED ON THE LEADING\nC     EXPONENTIAL, IS LESS THAN ALIM OR GREATER THAN -ALIM, THEN\nC     THE RESULT IS ON SCALE. IF NOT, THEN A REFINED TEST USING OTHER\nC     MULTIPLIERS (IN LOGARITHMIC FORM) IS MADE BASED ON ELIM. HERE\nC     EXP(-ELIM)=SMALLEST MACHINE NUMBER*1.0E+3 AND EXP(-ALIM)=\nC     EXP(-ELIM)/TOL\nC\nC     IKFLG=1 MEANS THE I SEQUENCE IS TESTED\nC          =2 MEANS THE K SEQUENCE IS TESTED\nC     NUF = 0 MEANS THE LAST MEMBER OF THE SEQUENCE IS ON SCALE\nC         =-1 MEANS AN OVERFLOW WOULD OCCUR\nC     IKFLG=1 AND NUF.GT.0 MEANS THE LAST NUF Y VALUES WERE SET TO ZERO\nC             THE FIRST N-NUF VALUES MUST BE SET BY ANOTHER ROUTINE\nC     IKFLG=2 AND NUF.EQ.N MEANS ALL Y VALUES WERE SET TO ZERO\nC     IKFLG=2 AND 0.LT.NUF.LT.N NOT CONSIDERED. Y MUST BE SET BY\nC             ANOTHER ROUTINE\nC\nC***ROUTINES CALLED  CUCHK,CUNHJ,CUNIK,R1MACH\nC***END PROLOGUE  CUOIK\n      COMPLEX ARG, ASUM, BSUM, CWRK, CZ, CZERO, PHI, SUM, Y, Z, ZB,\n     * ZETA1, ZETA2, ZN, ZR\n      REAL AARG, AIC, ALIM, APHI, ASCLE, AX, AY, ELIM, FNN, FNU, GNN,\n     * GNU, RCZ, TOL, X, YY\n      INTEGER I, IFORM, IKFLG, INIT, KODE, N, NN, NUF, NW\n      DIMENSION Y(N), CWRK(16)\n      DATA CZERO / (0.0E0,0.0E0) /\n      DATA AIC / 1.265512123484645396E+00 /\n      NUF = 0\n      NN = N\n      X = REAL(Z)\n      ZR = Z\n      IF (X.LT.0.0E0) ZR = -Z\n      ZB = ZR\n      YY = AIMAG(ZR)\n      AX = ABS(X)*1.7321E0\n      AY = ABS(YY)\n      IFORM = 1\n      IF (AY.GT.AX) IFORM = 2\n      GNU = AMAX1(FNU,1.0E0)\n      IF (IKFLG.EQ.1) GO TO 10\n      FNN = FLOAT(NN)\n      GNN = FNU + FNN - 1.0E0\n      GNU = AMAX1(GNN,FNN)\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     ONLY THE MAGNITUDE OF ARG AND PHI ARE NEEDED ALONG WITH THE\nC     REAL PARTS OF ZETA1, ZETA2 AND ZB. NO ATTEMPT IS MADE TO GET\nC     THE SIGN OF THE IMAGINARY PART CORRECT.\nC-----------------------------------------------------------------------\n      IF (IFORM.EQ.2) GO TO 20\n      INIT = 0\n      CALL CUNIK(ZR, GNU, IKFLG, 1, TOL, INIT, PHI, ZETA1, ZETA2, SUM,\n     * CWRK)\n      CZ = -ZETA1 + ZETA2\n      GO TO 40\n   20 CONTINUE\n      ZN = -ZR*CMPLX(0.0E0,1.0E0)\n      IF (YY.GT.0.0E0) GO TO 30\n      ZN = CONJG(-ZN)\n   30 CONTINUE\n      CALL CUNHJ(ZN, GNU, 1, TOL, PHI, ARG, ZETA1, ZETA2, ASUM, BSUM)\n      CZ = -ZETA1 + ZETA2\n      AARG = CABS(ARG)\n   40 CONTINUE\n      IF (KODE.EQ.2) CZ = CZ - ZB\n      IF (IKFLG.EQ.2) CZ = -CZ\n      APHI = CABS(PHI)\n      RCZ = REAL(CZ)\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST\nC-----------------------------------------------------------------------\n      IF (RCZ.GT.ELIM) GO TO 170\n      IF (RCZ.LT.ALIM) GO TO 50\n      RCZ = RCZ + ALOG(APHI)\n      IF (IFORM.EQ.2) RCZ = RCZ - 0.25E0*ALOG(AARG) - AIC\n      IF (RCZ.GT.ELIM) GO TO 170\n      GO TO 100\n   50 CONTINUE\nC-----------------------------------------------------------------------\nC     UNDERFLOW TEST\nC-----------------------------------------------------------------------\n      IF (RCZ.LT.(-ELIM)) GO TO 60\n      IF (RCZ.GT.(-ALIM)) GO TO 100\n      RCZ = RCZ + ALOG(APHI)\n      IF (IFORM.EQ.2) RCZ = RCZ - 0.25E0*ALOG(AARG) - AIC\n      IF (RCZ.GT.(-ELIM)) GO TO 80\n   60 CONTINUE\n      DO 70 I=1,NN\n        Y(I) = CZERO\n   70 CONTINUE\n      NUF = NN\n      RETURN\n   80 CONTINUE\n      ASCLE = 1.0E+3*R1MACH(1)/TOL\n      CZ = CZ + CLOG(PHI)\n      IF (IFORM.EQ.1) GO TO 90\n      CZ = CZ - CMPLX(0.25E0,0.0E0)*CLOG(ARG) - CMPLX(AIC,0.0E0)\n   90 CONTINUE\n      AX = EXP(RCZ)/TOL\n      AY = AIMAG(CZ)\n      CZ = CMPLX(AX,0.0E0)*CMPLX(COS(AY),SIN(AY))\n      CALL CUCHK(CZ, NW, ASCLE, TOL)\n      IF (NW.EQ.1) GO TO 60\n  100 CONTINUE\n      IF (IKFLG.EQ.2) RETURN\n      IF (N.EQ.1) RETURN\nC-----------------------------------------------------------------------\nC     SET UNDERFLOWS ON I SEQUENCE\nC-----------------------------------------------------------------------\n  110 CONTINUE\n      GNU = FNU + FLOAT(NN-1)\n      IF (IFORM.EQ.2) GO TO 120\n      INIT = 0\n      CALL CUNIK(ZR, GNU, IKFLG, 1, TOL, INIT, PHI, ZETA1, ZETA2, SUM,\n     * CWRK)\n      CZ = -ZETA1 + ZETA2\n      GO TO 130\n  120 CONTINUE\n      CALL CUNHJ(ZN, GNU, 1, TOL, PHI, ARG, ZETA1, ZETA2, ASUM, BSUM)\n      CZ = -ZETA1 + ZETA2\n      AARG = CABS(ARG)\n  130 CONTINUE\n      IF (KODE.EQ.2) CZ = CZ - ZB\n      APHI = CABS(PHI)\n      RCZ = REAL(CZ)\n      IF (RCZ.LT.(-ELIM)) GO TO 140\n      IF (RCZ.GT.(-ALIM)) RETURN\n      RCZ = RCZ + ALOG(APHI)\n      IF (IFORM.EQ.2) RCZ = RCZ - 0.25E0*ALOG(AARG) - AIC\n      IF (RCZ.GT.(-ELIM)) GO TO 150\n  140 CONTINUE\n      Y(NN) = CZERO\n      NN = NN - 1\n      NUF = NUF + 1\n      IF (NN.EQ.0) RETURN\n      GO TO 110\n  150 CONTINUE\n      ASCLE = 1.0E+3*R1MACH(1)/TOL\n      CZ = CZ + CLOG(PHI)\n      IF (IFORM.EQ.1) GO TO 160\n      CZ = CZ - CMPLX(0.25E0,0.0E0)*CLOG(ARG) - CMPLX(AIC,0.0E0)\n  160 CONTINUE\n      AX = EXP(RCZ)/TOL\n      AY = AIMAG(CZ)\n      CZ = CMPLX(AX,0.0E0)*CMPLX(COS(AY),SIN(AY))\n      CALL CUCHK(CZ, NW, ASCLE, TOL)\n      IF (NW.EQ.1) GO TO 140\n      RETURN\n  170 CONTINUE\n      NUF = -1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/cwrsk.f",
    "content": "      SUBROUTINE CWRSK(ZR, FNU, KODE, N, Y, NZ, CW, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  CWRSK\nC***REFER TO  CBESI,CBESK\nC\nC     CWRSK COMPUTES THE I BESSEL FUNCTION FOR RE(Z).GE.0.0 BY\nC     NORMALIZING THE I FUNCTION RATIOS FROM CRATI BY THE WRONSKIAN\nC\nC***ROUTINES CALLED  CBKNU,CRATI,R1MACH\nC***END PROLOGUE  CWRSK\n      COMPLEX CINU, CSCL, CT, CW, C1, C2, RCT, ST, Y, ZR\n      REAL ACT, ACW, ALIM, ASCLE, ELIM, FNU, S1, S2, TOL, YY\n      INTEGER I, KODE, N, NW, NZ\n      DIMENSION Y(N), CW(2)\nC-----------------------------------------------------------------------\nC     I(FNU+I-1,Z) BY BACKWARD RECURRENCE FOR RATIOS\nC     Y(I)=I(FNU+I,Z)/I(FNU+I-1,Z) FROM CRATI NORMALIZED BY THE\nC     WRONSKIAN WITH K(FNU,Z) AND K(FNU+1,Z) FROM CBKNU.\nC-----------------------------------------------------------------------\n      NZ = 0\n      CALL CBKNU(ZR, FNU, KODE, 2, CW, NW, TOL, ELIM, ALIM)\n      IF (NW.NE.0) GO TO 50\n      CALL CRATI(ZR, FNU, N, Y, TOL)\nC-----------------------------------------------------------------------\nC     RECUR FORWARD ON I(FNU+1,Z) = R(FNU,Z)*I(FNU,Z),\nC     R(FNU+J-1,Z)=Y(J),  J=1,...,N\nC-----------------------------------------------------------------------\n      CINU = CMPLX(1.0E0,0.0E0)\n      IF (KODE.EQ.1) GO TO 10\n      YY = AIMAG(ZR)\n      S1 = COS(YY)\n      S2 = SIN(YY)\n      CINU = CMPLX(S1,S2)\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     ON LOW EXPONENT MACHINES THE K FUNCTIONS CAN BE CLOSE TO BOTH\nC     THE UNDER AND OVERFLOW LIMITS AND THE NORMALIZATION MUST BE\nC     SCALED TO PREVENT OVER OR UNDERFLOW. CUOIK HAS DETERMINED THAT\nC     THE RESULT IS ON SCALE.\nC-----------------------------------------------------------------------\n      ACW = CABS(CW(2))\n      ASCLE = 1.0E+3*R1MACH(1)/TOL\n      CSCL = CMPLX(1.0E0,0.0E0)\n      IF (ACW.GT.ASCLE) GO TO 20\n      CSCL = CMPLX(1.0E0/TOL,0.0E0)\n      GO TO 30\n   20 CONTINUE\n      ASCLE = 1.0E0/ASCLE\n      IF (ACW.LT.ASCLE) GO TO 30\n      CSCL = CMPLX(TOL,0.0E0)\n   30 CONTINUE\n      C1 = CW(1)*CSCL\n      C2 = CW(2)*CSCL\n      ST = Y(1)\nC-----------------------------------------------------------------------\nC     CINU=CINU*(CONJG(CT)/CABS(CT))*(1.0E0/CABS(CT) PREVENTS\nC     UNDER- OR OVERFLOW PREMATURELY BY SQUARING CABS(CT)\nC-----------------------------------------------------------------------\n      CT = ZR*(C2+ST*C1)\n      ACT = CABS(CT)\n      RCT = CMPLX(1.0E0/ACT,0.0E0)\n      CT = CONJG(CT)*RCT\n      CINU = CINU*RCT*CT\n      Y(1) = CINU*CSCL\n      IF (N.EQ.1) RETURN\n      DO 40 I=2,N\n        CINU = ST*CINU\n        ST = Y(I)\n        Y(I) = CINU*CSCL\n   40 CONTINUE\n      RETURN\n   50 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/dgamln.f",
    "content": "      DOUBLE PRECISION FUNCTION DGAMLN(Z,IERR)\nC***BEGIN PROLOGUE  DGAMLN\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  830501   (YYMMDD)\nC***CATEGORY NO.  B5F\nC***KEYWORDS  GAMMA FUNCTION,LOGARITHM OF GAMMA FUNCTION\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE THE LOGARITHM OF THE GAMMA FUNCTION\nC***DESCRIPTION\nC\nC               **** A DOUBLE PRECISION ROUTINE ****\nC         DGAMLN COMPUTES THE NATURAL LOG OF THE GAMMA FUNCTION FOR\nC         Z.GT.0.  THE ASYMPTOTIC EXPANSION IS USED TO GENERATE VALUES\nC         GREATER THAN ZMIN WHICH ARE ADJUSTED BY THE RECURSION\nC         G(Z+1)=Z*G(Z) FOR Z.LE.ZMIN.  THE FUNCTION WAS MADE AS\nC         PORTABLE AS POSSIBLE BY COMPUTIMG ZMIN FROM THE NUMBER OF BASE\nC         10 DIGITS IN A WORD, RLN=AMAX1(-ALOG10(R1MACH(4)),0.5E-18)\nC         LIMITED TO 18 DIGITS OF (RELATIVE) ACCURACY.\nC\nC         SINCE INTEGER ARGUMENTS ARE COMMON, A TABLE LOOK UP ON 100\nC         VALUES IS USED FOR SPEED OF EXECUTION.\nC\nC     DESCRIPTION OF ARGUMENTS\nC\nC         INPUT      Z IS D0UBLE PRECISION\nC           Z      - ARGUMENT, Z.GT.0.0D0\nC\nC         OUTPUT      DGAMLN IS DOUBLE PRECISION\nC           DGAMLN  - NATURAL LOG OF THE GAMMA FUNCTION AT Z.NE.0.0D0\nC           IERR    - ERROR FLAG\nC                     IERR=0, NORMAL RETURN, COMPUTATION COMPLETED\nC                     IERR=1, Z.LE.0.0D0,    NO COMPUTATION\nC\nC\nC***REFERENCES  COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC***ROUTINES CALLED  I1MACH,D1MACH\nC***END PROLOGUE  DGAMLN\n      DOUBLE PRECISION CF, CON, FLN, FZ, GLN, RLN, S, TLG, TRM, TST,\n     * T1, WDTOL, Z, ZDMY, ZINC, ZM, ZMIN, ZP, ZSQ, D1MACH\n      INTEGER I, IERR, I1M, K, MZ, NZ, I1MACH\n      DIMENSION CF(22), GLN(100)\nC           LNGAMMA(N), N=1,100\n      DATA GLN(1), GLN(2), GLN(3), GLN(4), GLN(5), GLN(6), GLN(7),\n     1     GLN(8), GLN(9), GLN(10), GLN(11), GLN(12), GLN(13), GLN(14),\n     2     GLN(15), GLN(16), GLN(17), GLN(18), GLN(19), GLN(20),\n     3     GLN(21), GLN(22)/\n     4     0.00000000000000000D+00,     0.00000000000000000D+00,\n     5     6.93147180559945309D-01,     1.79175946922805500D+00,\n     6     3.17805383034794562D+00,     4.78749174278204599D+00,\n     7     6.57925121201010100D+00,     8.52516136106541430D+00,\n     8     1.06046029027452502D+01,     1.28018274800814696D+01,\n     9     1.51044125730755153D+01,     1.75023078458738858D+01,\n     A     1.99872144956618861D+01,     2.25521638531234229D+01,\n     B     2.51912211827386815D+01,     2.78992713838408916D+01,\n     C     3.06718601060806728D+01,     3.35050734501368889D+01,\n     D     3.63954452080330536D+01,     3.93398841871994940D+01,\n     E     4.23356164607534850D+01,     4.53801388984769080D+01/\n      DATA GLN(23), GLN(24), GLN(25), GLN(26), GLN(27), GLN(28),\n     1     GLN(29), GLN(30), GLN(31), GLN(32), GLN(33), GLN(34),\n     2     GLN(35), GLN(36), GLN(37), GLN(38), GLN(39), GLN(40),\n     3     GLN(41), GLN(42), GLN(43), GLN(44)/\n     4     4.84711813518352239D+01,     5.16066755677643736D+01,\n     5     5.47847293981123192D+01,     5.80036052229805199D+01,\n     6     6.12617017610020020D+01,     6.45575386270063311D+01,\n     7     6.78897431371815350D+01,     7.12570389671680090D+01,\n     8     7.46582363488301644D+01,     7.80922235533153106D+01,\n     9     8.15579594561150372D+01,     8.50544670175815174D+01,\n     A     8.85808275421976788D+01,     9.21361756036870925D+01,\n     B     9.57196945421432025D+01,     9.93306124547874269D+01,\n     C     1.02968198614513813D+02,     1.06631760260643459D+02,\n     D     1.10320639714757395D+02,     1.14034211781461703D+02,\n     E     1.17771881399745072D+02,     1.21533081515438634D+02/\n      DATA GLN(45), GLN(46), GLN(47), GLN(48), GLN(49), GLN(50),\n     1     GLN(51), GLN(52), GLN(53), GLN(54), GLN(55), GLN(56),\n     2     GLN(57), GLN(58), GLN(59), GLN(60), GLN(61), GLN(62),\n     3     GLN(63), GLN(64), GLN(65), GLN(66)/\n     4     1.25317271149356895D+02,     1.29123933639127215D+02,\n     5     1.32952575035616310D+02,     1.36802722637326368D+02,\n     6     1.40673923648234259D+02,     1.44565743946344886D+02,\n     7     1.48477766951773032D+02,     1.52409592584497358D+02,\n     8     1.56360836303078785D+02,     1.60331128216630907D+02,\n     9     1.64320112263195181D+02,     1.68327445448427652D+02,\n     A     1.72352797139162802D+02,     1.76395848406997352D+02,\n     B     1.80456291417543771D+02,     1.84533828861449491D+02,\n     C     1.88628173423671591D+02,     1.92739047287844902D+02,\n     D     1.96866181672889994D+02,     2.01009316399281527D+02,\n     E     2.05168199482641199D+02,     2.09342586752536836D+02/\n      DATA GLN(67), GLN(68), GLN(69), GLN(70), GLN(71), GLN(72),\n     1     GLN(73), GLN(74), GLN(75), GLN(76), GLN(77), GLN(78),\n     2     GLN(79), GLN(80), GLN(81), GLN(82), GLN(83), GLN(84),\n     3     GLN(85), GLN(86), GLN(87), GLN(88)/\n     4     2.13532241494563261D+02,     2.17736934113954227D+02,\n     5     2.21956441819130334D+02,     2.26190548323727593D+02,\n     6     2.30439043565776952D+02,     2.34701723442818268D+02,\n     7     2.38978389561834323D+02,     2.43268849002982714D+02,\n     8     2.47572914096186884D+02,     2.51890402209723194D+02,\n     9     2.56221135550009525D+02,     2.60564940971863209D+02,\n     A     2.64921649798552801D+02,     2.69291097651019823D+02,\n     B     2.73673124285693704D+02,     2.78067573440366143D+02,\n     C     2.82474292687630396D+02,     2.86893133295426994D+02,\n     D     2.91323950094270308D+02,     2.95766601350760624D+02,\n     E     3.00220948647014132D+02,     3.04686856765668715D+02/\n      DATA GLN(89), GLN(90), GLN(91), GLN(92), GLN(93), GLN(94),\n     1     GLN(95), GLN(96), GLN(97), GLN(98), GLN(99), GLN(100)/\n     2     3.09164193580146922D+02,     3.13652829949879062D+02,\n     3     3.18152639620209327D+02,     3.22663499126726177D+02,\n     4     3.27185287703775217D+02,     3.31717887196928473D+02,\n     5     3.36261181979198477D+02,     3.40815058870799018D+02,\n     6     3.45379407062266854D+02,     3.49954118040770237D+02,\n     7     3.54539085519440809D+02,     3.59134205369575399D+02/\nC             COEFFICIENTS OF ASYMPTOTIC EXPANSION\n      DATA CF(1), CF(2), CF(3), CF(4), CF(5), CF(6), CF(7), CF(8),\n     1     CF(9), CF(10), CF(11), CF(12), CF(13), CF(14), CF(15),\n     2     CF(16), CF(17), CF(18), CF(19), CF(20), CF(21), CF(22)/\n     3     8.33333333333333333D-02,    -2.77777777777777778D-03,\n     4     7.93650793650793651D-04,    -5.95238095238095238D-04,\n     5     8.41750841750841751D-04,    -1.91752691752691753D-03,\n     6     6.41025641025641026D-03,    -2.95506535947712418D-02,\n     7     1.79644372368830573D-01,    -1.39243221690590112D+00,\n     8     1.34028640441683920D+01,    -1.56848284626002017D+02,\n     9     2.19310333333333333D+03,    -3.61087712537249894D+04,\n     A     6.91472268851313067D+05,    -1.52382215394074162D+07,\n     B     3.82900751391414141D+08,    -1.08822660357843911D+10,\n     C     3.47320283765002252D+11,    -1.23696021422692745D+13,\n     D     4.88788064793079335D+14,    -2.13203339609193739D+16/\nC\nC             LN(2*PI)\n      DATA CON                    /     1.83787706640934548D+00/\nC\nC***FIRST EXECUTABLE STATEMENT  DGAMLN\n      IERR=0\n      IF (Z.LE.0.0D0) GO TO 70\n      IF (Z.GT.101.0D0) GO TO 10\n      NZ = INT(SNGL(Z))\n      FZ = Z - FLOAT(NZ)\n      IF (FZ.GT.0.0D0) GO TO 10\n      IF (NZ.GT.100) GO TO 10\n      DGAMLN = GLN(NZ)\n      RETURN\n   10 CONTINUE\n      WDTOL = D1MACH(4)\n      WDTOL = DMAX1(WDTOL,0.5D-18)\n      I1M = I1MACH(14)\n      RLN = D1MACH(5)*FLOAT(I1M)\n      FLN = DMIN1(RLN,20.0D0)\n      FLN = DMAX1(FLN,3.0D0)\n      FLN = FLN - 3.0D0\n      ZM = 1.8000D0 + 0.3875D0*FLN\n      MZ = INT(SNGL(ZM)) + 1\n      ZMIN = FLOAT(MZ)\n      ZDMY = Z\n      ZINC = 0.0D0\n      IF (Z.GE.ZMIN) GO TO 20\n      ZINC = ZMIN - FLOAT(NZ)\n      ZDMY = Z + ZINC\n   20 CONTINUE\n      ZP = 1.0D0/ZDMY\n      T1 = CF(1)*ZP\n      S = T1\n      IF (ZP.LT.WDTOL) GO TO 40\n      ZSQ = ZP*ZP\n      TST = T1*WDTOL\n      DO 30 K=2,22\n        ZP = ZP*ZSQ\n        TRM = CF(K)*ZP\n        IF (DABS(TRM).LT.TST) GO TO 40\n        S = S + TRM\n   30 CONTINUE\n   40 CONTINUE\n      IF (ZINC.NE.0.0D0) GO TO 50\n      TLG = DLOG(Z)\n      DGAMLN = Z*(TLG-1.0D0) + 0.5D0*(CON-TLG) + S\n      RETURN\n   50 CONTINUE\n      ZP = 1.0D0\n      NZ = INT(SNGL(ZINC))\n      DO 60 I=1,NZ\n        ZP = ZP*(Z+FLOAT(I-1))\n   60 CONTINUE\n      TLG = DLOG(ZDMY)\n      DGAMLN = ZDMY*(TLG-1.0D0) - DLOG(ZP) + 0.5D0*(CON-TLG) + S\n      RETURN\nC\nC\n   70 CONTINUE\n      IERR=1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/gamln.f",
    "content": "      FUNCTION GAMLN(Z,IERR)\nC***BEGIN PROLOGUE  GAMLN\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  830501   (YYMMDD)\nC***CATEGORY NO.  B5F\nC***KEYWORDS  GAMMA FUNCTION,LOGARITHM OF GAMMA FUNCTION\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE THE LOGARITHM OF THE GAMMA FUNCTION\nC***DESCRIPTION\nC\nC         GAMLN COMPUTES THE NATURAL LOG OF THE GAMMA FUNCTION FOR\nC         Z.GT.0.  THE ASYMPTOTIC EXPANSION IS USED TO GENERATE VALUES\nC         GREATER THAN ZMIN WHICH ARE ADJUSTED BY THE RECURSION\nC         G(Z+1)=Z*G(Z) FOR Z.LE.ZMIN.  THE FUNCTION WAS MADE AS\nC         PORTABLE AS POSSIBLE BY COMPUTIMG ZMIN FROM THE NUMBER OF BASE\nC         10 DIGITS IN A WORD, RLN=AMAX1(-ALOG10(R1MACH(4)),0.5E-18)\nC         LIMITED TO 18 DIGITS OF (RELATIVE) ACCURACY.\nC\nC         SINCE INTEGER ARGUMENTS ARE COMMON, A TABLE LOOK UP ON 100\nC         VALUES IS USED FOR SPEED OF EXECUTION.\nC\nC     DESCRIPTION OF ARGUMENTS\nC\nC         INPUT\nC           Z      - REAL ARGUMENT, Z.GT.0.0E0\nC\nC         OUTPUT\nC           GAMLN  - NATURAL LOG OF THE GAMMA FUNCTION AT Z\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN, COMPUTATION COMPLETED\nC                    IERR=1, Z.LE.0.0E0,    NO COMPUTATION\nC\nC***REFERENCES  COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC***ROUTINES CALLED  I1MACH,R1MACH\nC***END PROLOGUE  GAMLN\nC\n      INTEGER I, I1M, K, MZ, NZ, IERR, I1MACH\n      REAL CF, CON, FLN, FZ, GLN, RLN, S, TLG, TRM, TST, T1, WDTOL, Z,\n     * ZDMY, ZINC, ZM, ZMIN, ZP, ZSQ\n      REAL R1MACH\n      DIMENSION CF(22), GLN(100)\nC           LNGAMMA(N), N=1,100\n      DATA GLN(1), GLN(2), GLN(3), GLN(4), GLN(5), GLN(6), GLN(7),\n     1     GLN(8), GLN(9), GLN(10), GLN(11), GLN(12), GLN(13), GLN(14),\n     2     GLN(15), GLN(16), GLN(17), GLN(18), GLN(19), GLN(20),\n     3     GLN(21), GLN(22)/\n     4     0.00000000000000000E+00,     0.00000000000000000E+00,\n     5     6.93147180559945309E-01,     1.79175946922805500E+00,\n     6     3.17805383034794562E+00,     4.78749174278204599E+00,\n     7     6.57925121201010100E+00,     8.52516136106541430E+00,\n     8     1.06046029027452502E+01,     1.28018274800814696E+01,\n     9     1.51044125730755153E+01,     1.75023078458738858E+01,\n     A     1.99872144956618861E+01,     2.25521638531234229E+01,\n     B     2.51912211827386815E+01,     2.78992713838408916E+01,\n     C     3.06718601060806728E+01,     3.35050734501368889E+01,\n     D     3.63954452080330536E+01,     3.93398841871994940E+01,\n     E     4.23356164607534850E+01,     4.53801388984769080E+01/\n      DATA GLN(23), GLN(24), GLN(25), GLN(26), GLN(27), GLN(28),\n     1     GLN(29), GLN(30), GLN(31), GLN(32), GLN(33), GLN(34),\n     2     GLN(35), GLN(36), GLN(37), GLN(38), GLN(39), GLN(40),\n     3     GLN(41), GLN(42), GLN(43), GLN(44)/\n     4     4.84711813518352239E+01,     5.16066755677643736E+01,\n     5     5.47847293981123192E+01,     5.80036052229805199E+01,\n     6     6.12617017610020020E+01,     6.45575386270063311E+01,\n     7     6.78897431371815350E+01,     7.12570389671680090E+01,\n     8     7.46582363488301644E+01,     7.80922235533153106E+01,\n     9     8.15579594561150372E+01,     8.50544670175815174E+01,\n     A     8.85808275421976788E+01,     9.21361756036870925E+01,\n     B     9.57196945421432025E+01,     9.93306124547874269E+01,\n     C     1.02968198614513813E+02,     1.06631760260643459E+02,\n     D     1.10320639714757395E+02,     1.14034211781461703E+02,\n     E     1.17771881399745072E+02,     1.21533081515438634E+02/\n      DATA GLN(45), GLN(46), GLN(47), GLN(48), GLN(49), GLN(50),\n     1     GLN(51), GLN(52), GLN(53), GLN(54), GLN(55), GLN(56),\n     2     GLN(57), GLN(58), GLN(59), GLN(60), GLN(61), GLN(62),\n     3     GLN(63), GLN(64), GLN(65), GLN(66)/\n     4     1.25317271149356895E+02,     1.29123933639127215E+02,\n     5     1.32952575035616310E+02,     1.36802722637326368E+02,\n     6     1.40673923648234259E+02,     1.44565743946344886E+02,\n     7     1.48477766951773032E+02,     1.52409592584497358E+02,\n     8     1.56360836303078785E+02,     1.60331128216630907E+02,\n     9     1.64320112263195181E+02,     1.68327445448427652E+02,\n     A     1.72352797139162802E+02,     1.76395848406997352E+02,\n     B     1.80456291417543771E+02,     1.84533828861449491E+02,\n     C     1.88628173423671591E+02,     1.92739047287844902E+02,\n     D     1.96866181672889994E+02,     2.01009316399281527E+02,\n     E     2.05168199482641199E+02,     2.09342586752536836E+02/\n      DATA GLN(67), GLN(68), GLN(69), GLN(70), GLN(71), GLN(72),\n     1     GLN(73), GLN(74), GLN(75), GLN(76), GLN(77), GLN(78),\n     2     GLN(79), GLN(80), GLN(81), GLN(82), GLN(83), GLN(84),\n     3     GLN(85), GLN(86), GLN(87), GLN(88)/\n     4     2.13532241494563261E+02,     2.17736934113954227E+02,\n     5     2.21956441819130334E+02,     2.26190548323727593E+02,\n     6     2.30439043565776952E+02,     2.34701723442818268E+02,\n     7     2.38978389561834323E+02,     2.43268849002982714E+02,\n     8     2.47572914096186884E+02,     2.51890402209723194E+02,\n     9     2.56221135550009525E+02,     2.60564940971863209E+02,\n     A     2.64921649798552801E+02,     2.69291097651019823E+02,\n     B     2.73673124285693704E+02,     2.78067573440366143E+02,\n     C     2.82474292687630396E+02,     2.86893133295426994E+02,\n     D     2.91323950094270308E+02,     2.95766601350760624E+02,\n     E     3.00220948647014132E+02,     3.04686856765668715E+02/\n      DATA GLN(89), GLN(90), GLN(91), GLN(92), GLN(93), GLN(94),\n     1     GLN(95), GLN(96), GLN(97), GLN(98), GLN(99), GLN(100)/\n     2     3.09164193580146922E+02,     3.13652829949879062E+02,\n     3     3.18152639620209327E+02,     3.22663499126726177E+02,\n     4     3.27185287703775217E+02,     3.31717887196928473E+02,\n     5     3.36261181979198477E+02,     3.40815058870799018E+02,\n     6     3.45379407062266854E+02,     3.49954118040770237E+02,\n     7     3.54539085519440809E+02,     3.59134205369575399E+02/\nC             COEFFICIENTS OF ASYMPTOTIC EXPANSION\n      DATA CF(1), CF(2), CF(3), CF(4), CF(5), CF(6), CF(7), CF(8),\n     1     CF(9), CF(10), CF(11), CF(12), CF(13), CF(14), CF(15),\n     2     CF(16), CF(17), CF(18), CF(19), CF(20), CF(21), CF(22)/\n     3     8.33333333333333333E-02,    -2.77777777777777778E-03,\n     4     7.93650793650793651E-04,    -5.95238095238095238E-04,\n     5     8.41750841750841751E-04,    -1.91752691752691753E-03,\n     6     6.41025641025641026E-03,    -2.95506535947712418E-02,\n     7     1.79644372368830573E-01,    -1.39243221690590112E+00,\n     8     1.34028640441683920E+01,    -1.56848284626002017E+02,\n     9     2.19310333333333333E+03,    -3.61087712537249894E+04,\n     A     6.91472268851313067E+05,    -1.52382215394074162E+07,\n     B     3.82900751391414141E+08,    -1.08822660357843911E+10,\n     C     3.47320283765002252E+11,    -1.23696021422692745E+13,\n     D     4.88788064793079335E+14,    -2.13203339609193739E+16/\nC\nC             LN(2*PI)\n      DATA CON                    /     1.83787706640934548E+00/\nC\nC***FIRST EXECUTABLE STATEMENT  GAMLN\n      IERR=0\n      IF (Z.LE.0.0E0) GO TO 70\n      IF (Z.GT.101.0E0) GO TO 10\n      NZ = INT(Z)\n      FZ = Z - FLOAT(NZ)\n      IF (FZ.GT.0.0E0) GO TO 10\n      IF (NZ.GT.100) GO TO 10\n      GAMLN = GLN(NZ)\n      RETURN\n   10 CONTINUE\n      WDTOL = R1MACH(4)\n      WDTOL = AMAX1(WDTOL,0.5E-18)\n      I1M = I1MACH(11)\n      RLN = R1MACH(5)*FLOAT(I1M)\n      FLN = AMIN1(RLN,20.0E0)\n      FLN = AMAX1(FLN,3.0E0)\n      FLN = FLN - 3.0E0\n      ZM = 1.8000E0 + 0.3875E0*FLN\n      MZ = INT(ZM) + 1\n      ZMIN = FLOAT(MZ)\n      ZDMY = Z\n      ZINC = 0.0E0\n      IF (Z.GE.ZMIN) GO TO 20\n      ZINC = ZMIN - FLOAT(NZ)\n      ZDMY = Z + ZINC\n   20 CONTINUE\n      ZP = 1.0E0/ZDMY\n      T1 = CF(1)*ZP\n      S = T1\n      IF (ZP.LT.WDTOL) GO TO 40\n      ZSQ = ZP*ZP\n      TST = T1*WDTOL\n      DO 30 K=2,22\n        ZP = ZP*ZSQ\n        TRM = CF(K)*ZP\n        IF (ABS(TRM).LT.TST) GO TO 40\n        S = S + TRM\n   30 CONTINUE\n   40 CONTINUE\n      IF (ZINC.NE.0.0E0) GO TO 50\n      TLG = ALOG(Z)\n      GAMLN = Z*(TLG-1.0E0) + 0.5E0*(CON-TLG) + S\n      RETURN\n   50 CONTINUE\n      ZP = 1.0E0\n      NZ = INT(ZINC)\n      DO 60 I=1,NZ\n        ZP = ZP*(Z+FLOAT(I-1))\n   60 CONTINUE\n      TLG = ALOG(ZDMY)\n      GAMLN = ZDMY*(TLG-1.0E0) - ALOG(ZP) + 0.5E0*(CON-TLG) + S\n      RETURN\nC\nC\n   70 CONTINUE\n      IERR=1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/cacai.f \\\n  %reldir%/cacon.f \\\n  %reldir%/cbesh.f \\\n  %reldir%/cbesi.f \\\n  %reldir%/cbesj.f \\\n  %reldir%/cbesk.f \\\n  %reldir%/cbesy.f \\\n  %reldir%/cbinu.f \\\n  %reldir%/cbuni.f \\\n  %reldir%/cbunk.f \\\n  %reldir%/cunk1.f \\\n  %reldir%/cunk2.f \\\n  %reldir%/crati.f \\\n  %reldir%/cshch.f \\\n  %reldir%/cuni1.f \\\n  %reldir%/cuoik.f \\\n  %reldir%/cairy.f \\\n  %reldir%/cbiry.f \\\n  %reldir%/ckscl.f \\\n  %reldir%/cs1s2.f \\\n  %reldir%/cuchk.f \\\n  %reldir%/cuni2.f \\\n  %reldir%/cwrsk.f \\\n  %reldir%/casyi.f \\\n  %reldir%/cbknu.f \\\n  %reldir%/cmlri.f \\\n  %reldir%/cseri.f \\\n  %reldir%/cunhj.f \\\n  %reldir%/cunik.f \\\n  %reldir%/dgamln.f \\\n  %reldir%/gamln.f \\\n  %reldir%/xzabs.f \\\n  %reldir%/xzexp.f \\\n  %reldir%/xzlog.f \\\n  %reldir%/xzsqrt.f \\\n  %reldir%/zacai.f \\\n  %reldir%/zacon.f \\\n  %reldir%/zairy.f \\\n  %reldir%/zasyi.f \\\n  %reldir%/zbesh.f \\\n  %reldir%/zbesi.f \\\n  %reldir%/zbesj.f \\\n  %reldir%/zbesk.f \\\n  %reldir%/zbesy.f \\\n  %reldir%/zbinu.f \\\n  %reldir%/zbiry.f \\\n  %reldir%/zbknu.f \\\n  %reldir%/zbuni.f \\\n  %reldir%/zbunk.f \\\n  %reldir%/zdiv.f \\\n  %reldir%/zkscl.f \\\n  %reldir%/zmlri.f \\\n  %reldir%/zmlt.f \\\n  %reldir%/zrati.f \\\n  %reldir%/zs1s2.f \\\n  %reldir%/zseri.f \\\n  %reldir%/zshch.f \\\n  %reldir%/zuchk.f \\\n  %reldir%/zunhj.f \\\n  %reldir%/zuni1.f \\\n  %reldir%/zuni2.f \\\n  %reldir%/zunik.f \\\n  %reldir%/zunk1.f \\\n  %reldir%/zunk2.f \\\n  %reldir%/zuoik.f \\\n  %reldir%/zwrsk.f\n\nliboctave_EXTRA_DIST += \\\n  %reldir%/README\n"
  },
  {
    "path": "liboctave/external/amos/xzabs.f",
    "content": "      DOUBLE PRECISION FUNCTION XZABS(ZR, ZI)\nC***BEGIN PROLOGUE  XZABS\nC***REFER TO  ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY\nC\nC     XZABS COMPUTES THE ABSOLUTE VALUE OR MAGNITUDE OF A DOUBLE\nC     PRECISION COMPLEX VARIABLE CMPLX(ZR,ZI)\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  XZABS\n      DOUBLE PRECISION ZR, ZI, U, V, Q, S\n      U = DABS(ZR)\n      V = DABS(ZI)\n      S = U + V\nC-----------------------------------------------------------------------\nC     S*1.0D0 MAKES AN UNNORMALIZED UNDERFLOW ON CDC MACHINES INTO A\nC     TRUE FLOATING ZERO\nC-----------------------------------------------------------------------\n      S = S*1.0D+0\n      IF (S.EQ.0.0D+0) GO TO 20\n      IF (U.GT.V) GO TO 10\n      Q = U/V\n      XZABS = V*DSQRT(1.D+0+Q*Q)\n      RETURN\n   10 Q = V/U\n      XZABS = U*DSQRT(1.D+0+Q*Q)\n      RETURN\n   20 XZABS = 0.0D+0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/xzexp.f",
    "content": "      SUBROUTINE XZEXP(AR, AI, BR, BI)\nC***BEGIN PROLOGUE  XZEXP\nC***REFER TO  ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY\nC\nC     DOUBLE PRECISION COMPLEX EXPONENTIAL FUNCTION B=EXP(A)\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  XZEXP\n      DOUBLE PRECISION AR, AI, BR, BI, ZM, CA, CB\n      ZM = DEXP(AR)\n      CA = ZM*DCOS(AI)\n      CB = ZM*DSIN(AI)\n      BR = CA\n      BI = CB\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/xzlog.f",
    "content": "      SUBROUTINE XZLOG(AR, AI, BR, BI, IERR)\nC***BEGIN PROLOGUE  XZLOG\nC***REFER TO  ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY\nC\nC     DOUBLE PRECISION COMPLEX LOGARITHM B=CLOG(A)\nC     IERR=0,NORMAL RETURN      IERR=1, Z=CMPLX(0.0,0.0)\nC***ROUTINES CALLED  XZABS\nC***END PROLOGUE  XZLOG\n      DOUBLE PRECISION AR, AI, BR, BI, ZM, DTHETA, DPI, DHPI\n      DOUBLE PRECISION XZABS\n      DATA DPI , DHPI  / 3.141592653589793238462643383D+0,\n     1                   1.570796326794896619231321696D+0/\nC\n      IERR=0\n      IF (AR.EQ.0.0D+0) GO TO 10\n      IF (AI.EQ.0.0D+0) GO TO 20\n      DTHETA = DATAN(AI/AR)\n      IF (DTHETA.LE.0.0D+0) GO TO 40\n      IF (AR.LT.0.0D+0) DTHETA = DTHETA - DPI\n      GO TO 50\n   10 IF (AI.EQ.0.0D+0) GO TO 60\n      BI = DHPI\n      BR = DLOG(DABS(AI))\n      IF (AI.LT.0.0D+0) BI = -BI\n      RETURN\n   20 IF (AR.GT.0.0D+0) GO TO 30\n      BR = DLOG(DABS(AR))\n      BI = DPI\n      RETURN\n   30 BR = DLOG(AR)\n      BI = 0.0D+0\n      RETURN\n   40 IF (AR.LT.0.0D+0) DTHETA = DTHETA + DPI\n   50 ZM = XZABS(AR,AI)\n      BR = DLOG(ZM)\n      BI = DTHETA\n      RETURN\n   60 CONTINUE\n      IERR=1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/xzsqrt.f",
    "content": "      SUBROUTINE XZSQRT(AR, AI, BR, BI)\nC***BEGIN PROLOGUE  XZSQRT\nC***REFER TO  ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY\nC\nC     DOUBLE PRECISION COMPLEX SQUARE ROOT, B=CSQRT(A)\nC\nC***ROUTINES CALLED  XZABS\nC***END PROLOGUE  XZSQRT\n      DOUBLE PRECISION AR, AI, BR, BI, ZM, DTHETA, DPI, DRT\n      DOUBLE PRECISION XZABS\n      DATA DRT , DPI / 7.071067811865475244008443621D-1,\n     1                 3.141592653589793238462643383D+0/\n      ZM = XZABS(AR,AI)\n      ZM = DSQRT(ZM)\n      IF (AR.EQ.0.0D+0) GO TO 10\n      IF (AI.EQ.0.0D+0) GO TO 20\n      DTHETA = DATAN(AI/AR)\n      IF (DTHETA.LE.0.0D+0) GO TO 40\n      IF (AR.LT.0.0D+0) DTHETA = DTHETA - DPI\n      GO TO 50\n   10 IF (AI.GT.0.0D+0) GO TO 60\n      IF (AI.LT.0.0D+0) GO TO 70\n      BR = 0.0D+0\n      BI = 0.0D+0\n      RETURN\n   20 IF (AR.GT.0.0D+0) GO TO 30\n      BR = 0.0D+0\n      BI = DSQRT(DABS(AR))\n      RETURN\n   30 BR = DSQRT(AR)\n      BI = 0.0D+0\n      RETURN\n   40 IF (AR.LT.0.0D+0) DTHETA = DTHETA + DPI\n   50 DTHETA = DTHETA*0.5D+0\n      BR = ZM*DCOS(DTHETA)\n      BI = ZM*DSIN(DTHETA)\n      RETURN\n   60 BR = ZM*DRT\n      BI = ZM*DRT\n      RETURN\n   70 BR = ZM*DRT\n      BI = -ZM*DRT\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zacai.f",
    "content": "      SUBROUTINE ZACAI(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL,\n     * ELIM, ALIM)\nC***BEGIN PROLOGUE  ZACAI\nC***REFER TO  ZAIRY\nC\nC     ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA\nC\nC         K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN)\nC                 MP=PI*MR*CMPLX(0.0,1.0)\nC\nC     TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT\nC     HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1.\nC     ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND\nC     RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT IF ZACON\nC     IS CALLED FROM ZAIRY.\nC\nC***ROUTINES CALLED  ZASYI,ZBKNU,ZMLRI,ZSERI,ZS1S2,D1MACH,XZABS\nC***END PROLOGUE  ZACAI\nC     COMPLEX CSGN,CSPN,C1,C2,Y,Z,ZN,CY\n      DOUBLE PRECISION ALIM, ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR,\n     * CSPNI, C1R, C1I, C2R, C2I, CYR, CYI, DFNU, ELIM, FMR, FNU, PI,\n     * RL, SGN, TOL, YY, YR, YI, ZR, ZI, ZNR, ZNI, D1MACH, XZABS\n      INTEGER INU, IUF, KODE, MR, N, NN, NW, NZ\n      DIMENSION YR(N), YI(N), CYR(2), CYI(2)\n      DATA PI / 3.14159265358979324D0 /\n      NZ = 0\n      ZNR = -ZR\n      ZNI = -ZI\n      AZ = XZABS(ZR,ZI)\n      NN = N\n      DFNU = FNU + DBLE(FLOAT(N-1))\n      IF (AZ.LE.2.0D0) GO TO 10\n      IF (AZ*AZ*0.25D0.GT.DFNU+1.0D0) GO TO 20\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     POWER SERIES FOR THE I FUNCTION\nC-----------------------------------------------------------------------\n      CALL ZSERI(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL, ELIM, ALIM)\n      GO TO 40\n   20 CONTINUE\n      IF (AZ.LT.RL) GO TO 30\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION\nC-----------------------------------------------------------------------\n      CALL ZASYI(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM,\n     * ALIM)\n      IF (NW.LT.0) GO TO 80\n      GO TO 40\n   30 CONTINUE\nC-----------------------------------------------------------------------\nC     MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION\nC-----------------------------------------------------------------------\n      CALL ZMLRI(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL)\n      IF(NW.LT.0) GO TO 80\n   40 CONTINUE\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION\nC-----------------------------------------------------------------------\n      CALL ZBKNU(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, NW, TOL, ELIM, ALIM)\n      IF (NW.NE.0) GO TO 80\n      FMR = DBLE(FLOAT(MR))\n      SGN = -DSIGN(PI,FMR)\n      CSGNR = 0.0D0\n      CSGNI = SGN\n      IF (KODE.EQ.1) GO TO 50\n      YY = -ZNI\n      CSGNR = -CSGNI*DSIN(YY)\n      CSGNI = CSGNI*DCOS(YY)\n   50 CONTINUE\nC-----------------------------------------------------------------------\nC     CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(SNGL(FNU))\n      ARG = (FNU-DBLE(FLOAT(INU)))*SGN\n      CSPNR = DCOS(ARG)\n      CSPNI = DSIN(ARG)\n      IF (MOD(INU,2).EQ.0) GO TO 60\n      CSPNR = -CSPNR\n      CSPNI = -CSPNI\n   60 CONTINUE\n      C1R = CYR(1)\n      C1I = CYI(1)\n      C2R = YR(1)\n      C2I = YI(1)\n      IF (KODE.EQ.1) GO TO 70\n      IUF = 0\n      ASCLE = 1.0D+3*D1MACH(1)/TOL\n      CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF)\n      NZ = NZ + NW\n   70 CONTINUE\n      YR(1) = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I\n      YI(1) = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R\n      RETURN\n   80 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zacon.f",
    "content": "      SUBROUTINE ZACON(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, FNUL,\n     * TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  ZACON\nC***REFER TO  ZBESK,ZBESH\nC\nC     ZACON APPLIES THE ANALYTIC CONTINUATION FORMULA\nC\nC         K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN)\nC                 MP=PI*MR*CMPLX(0.0,1.0)\nC\nC     TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT\nC     HALF Z PLANE\nC\nC***ROUTINES CALLED  ZBINU,ZBKNU,ZS1S2,D1MACH,XZABS,ZMLT\nC***END PROLOGUE  ZACON\nC     COMPLEX CK,CONE,CSCL,CSCR,CSGN,CSPN,CY,CZERO,C1,C2,RZ,SC1,SC2,ST,\nC    *S1,S2,Y,Z,ZN\n      DOUBLE PRECISION ALIM, ARG, ASCLE, AS2, AZN, BRY, BSCLE, CKI,\n     * CKR, CONER, CPN, CSCL, CSCR, CSGNI, CSGNR, CSPNI, CSPNR,\n     * CSR, CSRR, CSSR, CYI, CYR, C1I, C1M, C1R, C2I, C2R, ELIM, FMR,\n     * FN, FNU, FNUL, PI, PTI, PTR, RAZN, RL, RZI, RZR, SC1I, SC1R,\n     * SC2I, SC2R, SGN, SPN, STI, STR, S1I, S1R, S2I, S2R, TOL, YI, YR,\n     * YY, ZEROR, ZI, ZNI, ZNR, ZR, D1MACH, XZABS\n      INTEGER I, INU, IUF, KFLAG, KODE, MR, N, NN, NW, NZ\n      DIMENSION YR(N), YI(N), CYR(2), CYI(2), CSSR(3), CSRR(3), BRY(3)\n      DATA PI / 3.14159265358979324D0 /\n      DATA ZEROR,CONER / 0.0D0,1.0D0 /\n      NZ = 0\n      ZNR = -ZR\n      ZNI = -ZI\n      NN = N\n      CALL ZBINU(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, FNUL, TOL,\n     * ELIM, ALIM)\n      IF (NW.LT.0) GO TO 90\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION\nC-----------------------------------------------------------------------\n      NN = MIN0(2,N)\n      CALL ZBKNU(ZNR, ZNI, FNU, KODE, NN, CYR, CYI, NW, TOL, ELIM, ALIM)\n      IF (NW.NE.0) GO TO 90\n      S1R = CYR(1)\n      S1I = CYI(1)\n      FMR = DBLE(FLOAT(MR))\n      SGN = -DSIGN(PI,FMR)\n      CSGNR = ZEROR\n      CSGNI = SGN\n      IF (KODE.EQ.1) GO TO 10\n      YY = -ZNI\n      CPN = DCOS(YY)\n      SPN = DSIN(YY)\n      CALL ZMLT(CSGNR, CSGNI, CPN, SPN, CSGNR, CSGNI)\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(SNGL(FNU))\n      ARG = (FNU-DBLE(FLOAT(INU)))*SGN\n      CPN = DCOS(ARG)\n      SPN = DSIN(ARG)\n      CSPNR = CPN\n      CSPNI = SPN\n      IF (MOD(INU,2).EQ.0) GO TO 20\n      CSPNR = -CSPNR\n      CSPNI = -CSPNI\n   20 CONTINUE\n      IUF = 0\n      C1R = S1R\n      C1I = S1I\n      C2R = YR(1)\n      C2I = YI(1)\n      ASCLE = 1.0D+3*D1MACH(1)/TOL\n      IF (KODE.EQ.1) GO TO 30\n      CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF)\n      NZ = NZ + NW\n      SC1R = C1R\n      SC1I = C1I\n   30 CONTINUE\n      CALL ZMLT(CSPNR, CSPNI, C1R, C1I, STR, STI)\n      CALL ZMLT(CSGNR, CSGNI, C2R, C2I, PTR, PTI)\n      YR(1) = STR + PTR\n      YI(1) = STI + PTI\n      IF (N.EQ.1) RETURN\n      CSPNR = -CSPNR\n      CSPNI = -CSPNI\n      S2R = CYR(2)\n      S2I = CYI(2)\n      C1R = S2R\n      C1I = S2I\n      C2R = YR(2)\n      C2I = YI(2)\n      IF (KODE.EQ.1) GO TO 40\n      CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF)\n      NZ = NZ + NW\n      SC2R = C1R\n      SC2I = C1I\n   40 CONTINUE\n      CALL ZMLT(CSPNR, CSPNI, C1R, C1I, STR, STI)\n      CALL ZMLT(CSGNR, CSGNI, C2R, C2I, PTR, PTI)\n      YR(2) = STR + PTR\n      YI(2) = STI + PTI\n      IF (N.EQ.2) RETURN\n      CSPNR = -CSPNR\n      CSPNI = -CSPNI\n      AZN = XZABS(ZNR,ZNI)\n      RAZN = 1.0D0/AZN\n      STR = ZNR*RAZN\n      STI = -ZNI*RAZN\n      RZR = (STR+STR)*RAZN\n      RZI = (STI+STI)*RAZN\n      FN = FNU + 1.0D0\n      CKR = FN*RZR\n      CKI = FN*RZI\nC-----------------------------------------------------------------------\nC     SCALE NEAR EXPONENT EXTREMES DURING RECURRENCE ON K FUNCTIONS\nC-----------------------------------------------------------------------\n      CSCL = 1.0D0/TOL\n      CSCR = TOL\n      CSSR(1) = CSCL\n      CSSR(2) = CONER\n      CSSR(3) = CSCR\n      CSRR(1) = CSCR\n      CSRR(2) = CONER\n      CSRR(3) = CSCL\n      BRY(1) = ASCLE\n      BRY(2) = 1.0D0/ASCLE\n      BRY(3) = D1MACH(2)\n      AS2 = XZABS(S2R,S2I)\n      KFLAG = 2\n      IF (AS2.GT.BRY(1)) GO TO 50\n      KFLAG = 1\n      GO TO 60\n   50 CONTINUE\n      IF (AS2.LT.BRY(2)) GO TO 60\n      KFLAG = 3\n   60 CONTINUE\n      BSCLE = BRY(KFLAG)\n      S1R = S1R*CSSR(KFLAG)\n      S1I = S1I*CSSR(KFLAG)\n      S2R = S2R*CSSR(KFLAG)\n      S2I = S2I*CSSR(KFLAG)\n      CSR = CSRR(KFLAG)\n      DO 80 I=3,N\n        STR = S2R\n        STI = S2I\n        S2R = CKR*STR - CKI*STI + S1R\n        S2I = CKR*STI + CKI*STR + S1I\n        S1R = STR\n        S1I = STI\n        C1R = S2R*CSR\n        C1I = S2I*CSR\n        STR = C1R\n        STI = C1I\n        C2R = YR(I)\n        C2I = YI(I)\n        IF (KODE.EQ.1) GO TO 70\n        IF (IUF.LT.0) GO TO 70\n        CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF)\n        NZ = NZ + NW\n        SC1R = SC2R\n        SC1I = SC2I\n        SC2R = C1R\n        SC2I = C1I\n        IF (IUF.NE.3) GO TO 70\n        IUF = -4\n        S1R = SC1R*CSSR(KFLAG)\n        S1I = SC1I*CSSR(KFLAG)\n        S2R = SC2R*CSSR(KFLAG)\n        S2I = SC2I*CSSR(KFLAG)\n        STR = SC2R\n        STI = SC2I\n   70   CONTINUE\n        PTR = CSPNR*C1R - CSPNI*C1I\n        PTI = CSPNR*C1I + CSPNI*C1R\n        YR(I) = PTR + CSGNR*C2R - CSGNI*C2I\n        YI(I) = PTI + CSGNR*C2I + CSGNI*C2R\n        CKR = CKR + RZR\n        CKI = CKI + RZI\n        CSPNR = -CSPNR\n        CSPNI = -CSPNI\n        IF (KFLAG.GE.3) GO TO 80\n        PTR = DABS(C1R)\n        PTI = DABS(C1I)\n        C1M = DMAX1(PTR,PTI)\n        IF (C1M.LE.BSCLE) GO TO 80\n        KFLAG = KFLAG + 1\n        BSCLE = BRY(KFLAG)\n        S1R = S1R*CSR\n        S1I = S1I*CSR\n        S2R = STR\n        S2I = STI\n        S1R = S1R*CSSR(KFLAG)\n        S1I = S1I*CSSR(KFLAG)\n        S2R = S2R*CSSR(KFLAG)\n        S2I = S2I*CSSR(KFLAG)\n        CSR = CSRR(KFLAG)\n   80 CONTINUE\n      RETURN\n   90 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zairy.f",
    "content": "      SUBROUTINE ZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ, IERR)\nC***BEGIN PROLOGUE  ZAIRY\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z\nC***DESCRIPTION\nC\nC                      ***A DOUBLE PRECISION ROUTINE***\nC         ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR\nC         ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON\nC         KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)*\nC         DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN\nC         -PI/3.LT.ARG(Z).LT.PI/3 AND THE EXPONENTIAL GROWTH IN\nC         PI/3.LT.ABS(ARG(Z)).LT.PI WHERE ZTA=(2/3)*Z*CSQRT(Z).\nC\nC         WHILE THE AIRY FUNCTIONS AI(Z) AND DAI(Z)/DZ ARE ANALYTIC IN\nC         THE WHOLE Z PLANE, THE CORRESPONDING SCALED FUNCTIONS DEFINED\nC         FOR KODE=2 HAVE A CUT ALONG THE NEGATIVE REAL AXIS.\nC         DEFINTIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF\nC         MATHEMATICAL FUNCTIONS (REF. 1).\nC\nC         INPUT      ZR,ZI ARE DOUBLE PRECISION\nC           ZR,ZI  - Z=CMPLX(ZR,ZI)\nC           ID     - ORDER OF DERIVATIVE, ID=0 OR ID=1\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             AI=AI(Z)                ON ID=0 OR\nC                             AI=DAI(Z)/DZ            ON ID=1\nC                        = 2  RETURNS\nC                             AI=CEXP(ZTA)*AI(Z)       ON ID=0 OR\nC                             AI=CEXP(ZTA)*DAI(Z)/DZ   ON ID=1 WHERE\nC                             ZTA=(2/3)*Z*CSQRT(Z)\nC\nC         OUTPUT     AIR,AII ARE DOUBLE PRECISION\nC           AIR,AII- COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND\nC                    KODE\nC           NZ     - UNDERFLOW INDICATOR\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ= 1   , AI=CMPLX(0.0D0,0.0D0) DUE TO UNDERFLOW IN\nC                              -PI/3.LT.ARG(Z).LT.PI/3 ON KODE=1\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, REAL(ZTA)\nC                            TOO LARGE ON KODE=1\nC                    IERR=3, CABS(Z) LARGE      - COMPUTATION COMPLETED\nC                            LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION\nC                            PRODUCE LESS THAN HALF OF MACHINE ACCURACY\nC                    IERR=4, CABS(Z) TOO LARGE  - NO COMPUTATION\nC                            COMPLETE LOSS OF ACCURACY BY ARGUMENT\nC                            REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         AI AND DAI ARE COMPUTED FOR CABS(Z).GT.1.0 FROM THE K BESSEL\nC         FUNCTIONS BY\nC\nC            AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA)\nC                           C=1.0/(PI*SQRT(3.0))\nC                            ZTA=(2/3)*Z**(3/2)\nC\nC         WITH THE POWER SERIES FOR CABS(Z).LE.1.0.\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES\nC         OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF\nC         THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR),\nC         THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR\nC         FLAG IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS\nC         DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION.\nC         ALSO, IF THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN\nC         ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT\nC         FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE\nC         LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA\nC         MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2,\nC         AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE\nC         PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE\nC         PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT-\nC         ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG-\nC         NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN\nC         DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN\nC         EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES,\nC         NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE\nC         PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER\nC         MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  ZACAI,ZBKNU,XZEXP,XZSQRT,I1MACH,D1MACH\nC***END PROLOGUE  ZAIRY\nC     COMPLEX AI,CONE,CSQ,CY,S1,S2,TRM1,TRM2,Z,ZTA,Z3\n      DOUBLE PRECISION AA, AD, AII, AIR, AK, ALIM, ATRM, AZ, AZ3, BK,\n     * CC, CK, COEF, CONEI, CONER, CSQI, CSQR, CYI, CYR, C1, C2, DIG,\n     * DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR,\n     * S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI,\n     * ZEROR, ZI, ZR, ZTAI, ZTAR, Z3I, Z3R, D1MACH, XZABS, ALAZ, BB\n      INTEGER ID, IERR, IFLAG, K, KODE, K1, K2, MR, NN, NZ, I1MACH\n      DIMENSION CYR(1), CYI(1)\n      DATA TTH, C1, C2, COEF /6.66666666666666667D-01,\n     * 3.55028053887817240D-01,2.58819403792806799D-01,\n     * 1.83776298473930683D-01/\n      DATA ZEROR, ZEROI, CONER, CONEI /0.0D0,0.0D0,1.0D0,0.0D0/\nC***FIRST EXECUTABLE STATEMENT  ZAIRY\n      IERR = 0\n      NZ=0\n      IF (ID.LT.0 .OR. ID.GT.1) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (IERR.NE.0) RETURN\n      AZ = XZABS(ZR,ZI)\n      TOL = DMAX1(D1MACH(4),1.0D-18)\n      FID = DBLE(FLOAT(ID))\n      IF (AZ.GT.1.0D0) GO TO 70\nC-----------------------------------------------------------------------\nC     POWER SERIES FOR CABS(Z).LE.1.\nC-----------------------------------------------------------------------\n      S1R = CONER\n      S1I = CONEI\n      S2R = CONER\n      S2I = CONEI\n      IF (AZ.LT.TOL) GO TO 170\n      AA = AZ*AZ\n      IF (AA.LT.TOL/AZ) GO TO 40\n      TRM1R = CONER\n      TRM1I = CONEI\n      TRM2R = CONER\n      TRM2I = CONEI\n      ATRM = 1.0D0\n      STR = ZR*ZR - ZI*ZI\n      STI = ZR*ZI + ZI*ZR\n      Z3R = STR*ZR - STI*ZI\n      Z3I = STR*ZI + STI*ZR\n      AZ3 = AZ*AA\n      AK = 2.0D0 + FID\n      BK = 3.0D0 - FID - FID\n      CK = 4.0D0 - FID\n      DK = 3.0D0 + FID + FID\n      D1 = AK*DK\n      D2 = BK*CK\n      AD = DMIN1(D1,D2)\n      AK = 24.0D0 + 9.0D0*FID\n      BK = 30.0D0 - 9.0D0*FID\n      DO 30 K=1,25\n        STR = (TRM1R*Z3R-TRM1I*Z3I)/D1\n        TRM1I = (TRM1R*Z3I+TRM1I*Z3R)/D1\n        TRM1R = STR\n        S1R = S1R + TRM1R\n        S1I = S1I + TRM1I\n        STR = (TRM2R*Z3R-TRM2I*Z3I)/D2\n        TRM2I = (TRM2R*Z3I+TRM2I*Z3R)/D2\n        TRM2R = STR\n        S2R = S2R + TRM2R\n        S2I = S2I + TRM2I\n        ATRM = ATRM*AZ3/AD\n        D1 = D1 + AK\n        D2 = D2 + BK\n        AD = DMIN1(D1,D2)\n        IF (ATRM.LT.TOL*AD) GO TO 40\n        AK = AK + 18.0D0\n        BK = BK + 18.0D0\n   30 CONTINUE\n   40 CONTINUE\n      IF (ID.EQ.1) GO TO 50\n      AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I)\n      AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R)\n      IF (KODE.EQ.1) RETURN\n      CALL XZSQRT(ZR, ZI, STR, STI)\n      ZTAR = TTH*(ZR*STR-ZI*STI)\n      ZTAI = TTH*(ZR*STI+ZI*STR)\n      CALL XZEXP(ZTAR, ZTAI, STR, STI)\n      PTR = AIR*STR - AII*STI\n      AII = AIR*STI + AII*STR\n      AIR = PTR\n      RETURN\n   50 CONTINUE\n      AIR = -S2R*C2\n      AII = -S2I*C2\n      IF (AZ.LE.TOL) GO TO 60\n      STR = ZR*S1R - ZI*S1I\n      STI = ZR*S1I + ZI*S1R\n      CC = C1/(1.0D0+FID)\n      AIR = AIR + CC*(STR*ZR-STI*ZI)\n      AII = AII + CC*(STR*ZI+STI*ZR)\n   60 CONTINUE\n      IF (KODE.EQ.1) RETURN\n      CALL XZSQRT(ZR, ZI, STR, STI)\n      ZTAR = TTH*(ZR*STR-ZI*STI)\n      ZTAI = TTH*(ZR*STI+ZI*STR)\n      CALL XZEXP(ZTAR, ZTAI, STR, STI)\n      PTR = STR*AIR - STI*AII\n      AII = STR*AII + STI*AIR\n      AIR = PTR\n      RETURN\nC-----------------------------------------------------------------------\nC     CASE FOR CABS(Z).GT.1.0\nC-----------------------------------------------------------------------\n   70 CONTINUE\n      FNU = (1.0D0+FID)/3.0D0\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC-----------------------------------------------------------------------\n      K1 = I1MACH(15)\n      K2 = I1MACH(16)\n      R1M5 = D1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0)\n      K1 = I1MACH(14) - 1\n      AA = R1M5*DBLE(FLOAT(K1))\n      DIG = DMIN1(AA,18.0D0)\n      AA = AA*2.303D0\n      ALIM = ELIM + DMAX1(-AA,-41.45D0)\n      RL = 1.2D0*DIG + 3.0D0\n      ALAZ = DLOG(AZ)\nC--------------------------------------------------------------------------\nC     TEST FOR PROPER RANGE\nC-----------------------------------------------------------------------\n      AA=0.5D0/TOL\n      BB=DBLE(FLOAT(I1MACH(9)))*0.5D0\n      AA=DMIN1(AA,BB)\n      AA=AA**TTH\n      IF (AZ.GT.AA) GO TO 260\n      AA=DSQRT(AA)\n      IF (AZ.GT.AA) IERR=3\n      CALL XZSQRT(ZR, ZI, CSQR, CSQI)\n      ZTAR = TTH*(ZR*CSQR-ZI*CSQI)\n      ZTAI = TTH*(ZR*CSQI+ZI*CSQR)\nC-----------------------------------------------------------------------\nC     RE(ZTA).LE.0 WHEN RE(Z).LT.0, ESPECIALLY WHEN IM(Z) IS SMALL\nC-----------------------------------------------------------------------\n      IFLAG = 0\n      SFAC = 1.0D0\n      AK = ZTAI\n      IF (ZR.GE.0.0D0) GO TO 80\n      BK = ZTAR\n      CK = -DABS(BK)\n      ZTAR = CK\n      ZTAI = AK\n   80 CONTINUE\n      IF (ZI.NE.0.0D0) GO TO 90\n      IF (ZR.GT.0.0D0) GO TO 90\n      ZTAR = 0.0D0\n      ZTAI = AK\n   90 CONTINUE\n      AA = ZTAR\n      IF (AA.GE.0.0D0 .AND. ZR.GT.0.0D0) GO TO 110\n      IF (KODE.EQ.2) GO TO 100\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST\nC-----------------------------------------------------------------------\n      IF (AA.GT.(-ALIM)) GO TO 100\n      AA = -AA + 0.25D0*ALAZ\n      IFLAG = 1\n      SFAC = TOL\n      IF (AA.GT.ELIM) GO TO 270\n  100 CONTINUE\nC-----------------------------------------------------------------------\nC     CBKNU AND CACON RETURN EXP(ZTA)*K(FNU,ZTA) ON KODE=2\nC-----------------------------------------------------------------------\n      MR = 1\n      IF (ZI.LT.0.0D0) MR = -1\n      CALL ZACAI(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, NN, RL, TOL,\n     * ELIM, ALIM)\n      IF (NN.LT.0) GO TO 280\n      NZ = NZ + NN\n      GO TO 130\n  110 CONTINUE\n      IF (KODE.EQ.2) GO TO 120\nC-----------------------------------------------------------------------\nC     UNDERFLOW TEST\nC-----------------------------------------------------------------------\n      IF (AA.LT.ALIM) GO TO 120\n      AA = -AA - 0.25D0*ALAZ\n      IFLAG = 2\n      SFAC = 1.0D0/TOL\n      IF (AA.LT.(-ELIM)) GO TO 210\n  120 CONTINUE\n      CALL ZBKNU(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, TOL, ELIM,\n     * ALIM)\n  130 CONTINUE\n      S1R = CYR(1)*COEF\n      S1I = CYI(1)*COEF\n      IF (IFLAG.NE.0) GO TO 150\n      IF (ID.EQ.1) GO TO 140\n      AIR = CSQR*S1R - CSQI*S1I\n      AII = CSQR*S1I + CSQI*S1R\n      RETURN\n  140 CONTINUE\n      AIR = -(ZR*S1R-ZI*S1I)\n      AII = -(ZR*S1I+ZI*S1R)\n      RETURN\n  150 CONTINUE\n      S1R = S1R*SFAC\n      S1I = S1I*SFAC\n      IF (ID.EQ.1) GO TO 160\n      STR = S1R*CSQR - S1I*CSQI\n      S1I = S1R*CSQI + S1I*CSQR\n      S1R = STR\n      AIR = S1R/SFAC\n      AII = S1I/SFAC\n      RETURN\n  160 CONTINUE\n      STR = -(S1R*ZR-S1I*ZI)\n      S1I = -(S1R*ZI+S1I*ZR)\n      S1R = STR\n      AIR = S1R/SFAC\n      AII = S1I/SFAC\n      RETURN\n  170 CONTINUE\n      AA = 1.0D+3*D1MACH(1)\n      S1R = ZEROR\n      S1I = ZEROI\n      IF (ID.EQ.1) GO TO 190\n      IF (AZ.LE.AA) GO TO 180\n      S1R = C2*ZR\n      S1I = C2*ZI\n  180 CONTINUE\n      AIR = C1 - S1R\n      AII = -S1I\n      RETURN\n  190 CONTINUE\n      AIR = -C2\n      AII = 0.0D0\n      AA = DSQRT(AA)\n      IF (AZ.LE.AA) GO TO 200\n      S1R = 0.5D0*(ZR*ZR-ZI*ZI)\n      S1I = ZR*ZI\n  200 CONTINUE\n      AIR = AIR + C1*S1R\n      AII = AII + C1*S1I\n      RETURN\n  210 CONTINUE\n      NZ = 1\n      AIR = ZEROR\n      AII = ZEROI\n      RETURN\n  270 CONTINUE\n      NZ = 0\n      IERR=2\n      RETURN\n  280 CONTINUE\n      IF(NN.EQ.(-1)) GO TO 270\n      NZ=0\n      IERR=5\n      RETURN\n  260 CONTINUE\n      IERR=4\n      NZ=0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zasyi.f",
    "content": "      SUBROUTINE ZASYI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  ZASYI\nC***REFER TO  ZBESI,ZBESK\nC\nC     ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z).GE.0.0 BY\nC     MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE\nC     REGION CABS(Z).GT.MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL RETURN.\nC     NZ.LT.0 INDICATES AN OVERFLOW ON KODE=1.\nC\nC***ROUTINES CALLED  D1MACH,XZABS,ZDIV,XZEXP,ZMLT,XZSQRT\nC***END PROLOGUE  ZASYI\nC     COMPLEX AK1,CK,CONE,CS1,CS2,CZ,CZERO,DK,EZ,P1,RZ,S2,Y,Z\n      DOUBLE PRECISION AA, AEZ, AK, AK1I, AK1R, ALIM, ARG, ARM, ATOL,\n     * AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI,\n     * CZR, DFNU, DKI, DKR, DNU2, ELIM, EZI, EZR, FDN, FNU, PI, P1I,\n     * P1R, RAZ, RL, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I,\n     * S2R, TOL, TZI, TZR, YI, YR, ZEROI, ZEROR, ZI, ZR, D1MACH, XZABS\n      INTEGER I, IB, IL, INU, J, JL, K, KODE, KODED, M, N, NN, NZ\n      DIMENSION YR(N), YI(N)\n      DATA PI, RTPI  /3.14159265358979324D0 , 0.159154943091895336D0 /\n      DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 /\nC\n      NZ = 0\n      AZ = XZABS(ZR,ZI)\n      ARM = 1.0D+3*D1MACH(1)\n      RTR1 = DSQRT(ARM)\n      IL = MIN0(2,N)\n      DFNU = FNU + DBLE(FLOAT(N-IL))\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST\nC-----------------------------------------------------------------------\n      RAZ = 1.0D0/AZ\n      STR = ZR*RAZ\n      STI = -ZI*RAZ\n      AK1R = RTPI*STR*RAZ\n      AK1I = RTPI*STI*RAZ\n      CALL XZSQRT(AK1R, AK1I, AK1R, AK1I)\n      CZR = ZR\n      CZI = ZI\n      IF (KODE.NE.2) GO TO 10\n      CZR = ZEROR\n      CZI = ZI\n   10 CONTINUE\n      IF (DABS(CZR).GT.ELIM) GO TO 100\n      DNU2 = DFNU + DFNU\n      KODED = 1\n      IF ((DABS(CZR).GT.ALIM) .AND. (N.GT.2)) GO TO 20\n      KODED = 0\n      CALL XZEXP(CZR, CZI, STR, STI)\n      CALL ZMLT(AK1R, AK1I, STR, STI, AK1R, AK1I)\n   20 CONTINUE\n      FDN = 0.0D0\n      IF (DNU2.GT.RTR1) FDN = DNU2*DNU2\n      EZR = ZR*8.0D0\n      EZI = ZI*8.0D0\nC-----------------------------------------------------------------------\nC     WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE\nC     FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE\nC     EXPANSION FOR THE IMAGINARY PART.\nC-----------------------------------------------------------------------\n      AEZ = 8.0D0*AZ\n      S = TOL/AEZ\n      JL = INT(SNGL(RL+RL)) + 2\n      P1R = ZEROR\n      P1I = ZEROI\n      IF (ZI.EQ.0.0D0) GO TO 30\nC-----------------------------------------------------------------------\nC     CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF\nC     SIGNIFICANCE WHEN FNU OR N IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(SNGL(FNU))\n      ARG = (FNU-DBLE(FLOAT(INU)))*PI\n      INU = INU + N - IL\n      AK = -DSIN(ARG)\n      BK = DCOS(ARG)\n      IF (ZI.LT.0.0D0) BK = -BK\n      P1R = AK\n      P1I = BK\n      IF (MOD(INU,2).EQ.0) GO TO 30\n      P1R = -P1R\n      P1I = -P1I\n   30 CONTINUE\n      DO 70 K=1,IL\n        SQK = FDN - 1.0D0\n        ATOL = S*DABS(SQK)\n        SGN = 1.0D0\n        CS1R = CONER\n        CS1I = CONEI\n        CS2R = CONER\n        CS2I = CONEI\n        CKR = CONER\n        CKI = CONEI\n        AK = 0.0D0\n        AA = 1.0D0\n        BB = AEZ\n        DKR = EZR\n        DKI = EZI\n        DO 40 J=1,JL\n          CALL ZDIV(CKR, CKI, DKR, DKI, STR, STI)\n          CKR = STR*SQK\n          CKI = STI*SQK\n          CS2R = CS2R + CKR\n          CS2I = CS2I + CKI\n          SGN = -SGN\n          CS1R = CS1R + CKR*SGN\n          CS1I = CS1I + CKI*SGN\n          DKR = DKR + EZR\n          DKI = DKI + EZI\n          AA = AA*DABS(SQK)/BB\n          BB = BB + AEZ\n          AK = AK + 8.0D0\n          SQK = SQK - AK\n          IF (AA.LE.ATOL) GO TO 50\n   40   CONTINUE\n        GO TO 110\n   50   CONTINUE\n        S2R = CS1R\n        S2I = CS1I\n        IF (ZR+ZR.GE.ELIM) GO TO 60\n        TZR = ZR + ZR\n        TZI = ZI + ZI\n        CALL XZEXP(-TZR, -TZI, STR, STI)\n        CALL ZMLT(STR, STI, P1R, P1I, STR, STI)\n        CALL ZMLT(STR, STI, CS2R, CS2I, STR, STI)\n        S2R = S2R + STR\n        S2I = S2I + STI\n   60   CONTINUE\n        FDN = FDN + 8.0D0*DFNU + 4.0D0\n        P1R = -P1R\n        P1I = -P1I\n        M = N - IL + K\n        YR(M) = S2R*AK1R - S2I*AK1I\n        YI(M) = S2R*AK1I + S2I*AK1R\n   70 CONTINUE\n      IF (N.LE.2) RETURN\n      NN = N\n      K = NN - 2\n      AK = DBLE(FLOAT(K))\n      STR = ZR*RAZ\n      STI = -ZI*RAZ\n      RZR = (STR+STR)*RAZ\n      RZI = (STI+STI)*RAZ\n      IB = 3\n      DO 80 I=IB,NN\n        YR(K) = (AK+FNU)*(RZR*YR(K+1)-RZI*YI(K+1)) + YR(K+2)\n        YI(K) = (AK+FNU)*(RZR*YI(K+1)+RZI*YR(K+1)) + YI(K+2)\n        AK = AK - 1.0D0\n        K = K - 1\n   80 CONTINUE\n      IF (KODED.EQ.0) RETURN\n      CALL XZEXP(CZR, CZI, CKR, CKI)\n      DO 90 I=1,NN\n        STR = YR(I)*CKR - YI(I)*CKI\n        YI(I) = YR(I)*CKI + YI(I)*CKR\n        YR(I) = STR\n   90 CONTINUE\n      RETURN\n  100 CONTINUE\n      NZ = -1\n      RETURN\n  110 CONTINUE\n      NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbesh.f",
    "content": "      SUBROUTINE ZBESH(ZR, ZI, FNU, KODE, M, N, CYR, CYI, NZ, IERR)\nC***BEGIN PROLOGUE  ZBESH\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  H-BESSEL FUNCTIONS,BESSEL FUNCTIONS OF COMPLEX ARGUMENT,\nC             BESSEL FUNCTIONS OF THIRD KIND,HANKEL FUNCTIONS\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE THE H-BESSEL FUNCTIONS OF A COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC                      ***A DOUBLE PRECISION ROUTINE***\nC         ON KODE=1, ZBESH COMPUTES AN N MEMBER SEQUENCE OF COMPLEX\nC         HANKEL (BESSEL) FUNCTIONS CY(J)=H(M,FNU+J-1,Z) FOR KINDS M=1\nC         OR 2, REAL, NONNEGATIVE ORDERS FNU+J-1, J=1,...,N, AND COMPLEX\nC         Z.NE.CMPLX(0.0,0.0) IN THE CUT PLANE -PI.LT.ARG(Z).LE.PI.\nC         ON KODE=2, ZBESH RETURNS THE SCALED HANKEL FUNCTIONS\nC\nC         CY(I)=EXP(-MM*Z*I)*H(M,FNU+J-1,Z)       MM=3-2*M,   I**2=-1.\nC\nC         WHICH REMOVES THE EXPONENTIAL BEHAVIOR IN BOTH THE UPPER AND\nC         LOWER HALF PLANES. DEFINITIONS AND NOTATION ARE FOUND IN THE\nC         NBS HANDBOOK OF MATHEMATICAL FUNCTIONS (REF. 1).\nC\nC         INPUT      ZR,ZI,FNU ARE DOUBLE PRECISION\nC           ZR,ZI  - Z=CMPLX(ZR,ZI), Z.NE.CMPLX(0.0D0,0.0D0),\nC                    -PT.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL H FUNCTION, FNU.GE.0.0D0\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(J)=H(M,FNU+J-1,Z),   J=1,...,N\nC                        = 2  RETURNS\nC                             CY(J)=H(M,FNU+J-1,Z)*EXP(-I*Z*(3-2M))\nC                                  J=1,...,N  ,  I**2=-1\nC           M      - KIND OF HANKEL FUNCTION, M=1 OR 2\nC           N      - NUMBER OF MEMBERS IN THE SEQUENCE, N.GE.1\nC\nC         OUTPUT     CYR,CYI ARE DOUBLE PRECISION\nC           CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS\nC                    CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE\nC                    CY(J)=H(M,FNU+J-1,Z)  OR\nC                    CY(J)=H(M,FNU+J-1,Z)*EXP(-I*Z*(3-2M))  J=1,...,N\nC                    DEPENDING ON KODE, I**2=-1.\nC           NZ     - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW,\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ.GT.0 , FIRST NZ COMPONENTS OF CY SET TO ZERO DUE\nC                              TO UNDERFLOW, CY(J)=CMPLX(0.0D0,0.0D0)\nC                              J=1,...,NZ WHEN Y.GT.0.0 AND M=1 OR\nC                              Y.LT.0.0 AND M=2. FOR THE COMPLMENTARY\nC                              HALF PLANES, NZ STATES ONLY THE NUMBER\nC                              OF UNDERFLOWS.\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, FNU TOO\nC                            LARGE OR CABS(Z) TOO SMALL OR BOTH\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         THE COMPUTATION IS CARRIED OUT BY THE RELATION\nC\nC         H(M,FNU,Z)=(1/MP)*EXP(-MP*FNU)*K(FNU,Z*EXP(-MP))\nC             MP=MM*HPI*I,  MM=3-2*M,  HPI=PI/2,  I**2=-1\nC\nC         FOR M=1 OR 2 WHERE THE K BESSEL FUNCTION IS COMPUTED FOR THE\nC         RIGHT HALF PLANE RE(Z).GE.0.0. THE K FUNCTION IS CONTINUED\nC         TO THE LEFT HALF PLANE BY THE RELATION\nC\nC         K(FNU,Z*EXP(MP)) = EXP(-MP*FNU)*K(FNU,Z)-MP*I(FNU,Z)\nC         MP=MR*PI*I, MR=+1 OR -1, RE(Z).GT.0, I**2=-1\nC\nC         WHERE I(FNU,Z) IS THE I BESSEL FUNCTION.\nC\nC         EXPONENTIAL DECAY OF H(M,FNU,Z) OCCURS IN THE UPPER HALF Z\nC         PLANE FOR M=1 AND THE LOWER HALF Z PLANE FOR M=2.  EXPONENTIAL\nC         GROWTH OCCURS IN THE COMPLEMENTARY HALF PLANES.  SCALING\nC         BY EXP(-MM*Z*I) REMOVES THE EXPONENTIAL BEHAVIOR IN THE\nC         WHOLE Z PLANE FOR Z TO INFINITY.\nC\nC         FOR NEGATIVE ORDERS,THE FORMULAE\nC\nC               H(1,-FNU,Z) = H(1,FNU,Z)*CEXP( PI*FNU*I)\nC               H(2,-FNU,Z) = H(2,FNU,Z)*CEXP(-PI*FNU*I)\nC                         I**2=-1\nC\nC         CAN BE USED.\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS\nC         DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION.\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0D-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  ZACON,ZBKNU,ZBUNK,ZUOIK,XZABS,I1MACH,D1MACH\nC***END PROLOGUE  ZBESH\nC\nC     COMPLEX CY,Z,ZN,ZT,CSGN\n      DOUBLE PRECISION AA, ALIM, ALN, ARG, AZ, CYI, CYR, DIG, ELIM,\n     * FMM, FN, FNU, FNUL, HPI, RHPI, RL, R1M5, SGN, STR, TOL, UFL, ZI,\n     * ZNI, ZNR, ZR, ZTI, D1MACH, XZABS, BB, ASCLE, RTOL, ATOL, STI,\n     * CSGNR, CSGNI\n      INTEGER I, IERR, INU, INUH, IR, K, KODE, K1, K2, M,\n     * MM, MR, N, NN, NUF, NW, NZ, I1MACH\n      DIMENSION CYR(N), CYI(N)\nC\n      DATA HPI /1.57079632679489662D0/\nC\nC***FIRST EXECUTABLE STATEMENT  ZBESH\n      IERR = 0\n      NZ=0\n      IF (ZR.EQ.0.0D0 .AND. ZI.EQ.0.0D0) IERR=1\n      IF (FNU.LT.0.0D0) IERR=1\n      IF (M.LT.1 .OR. M.GT.2) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\n      NN = N\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU\nC-----------------------------------------------------------------------\n      TOL = DMAX1(D1MACH(4),1.0D-18)\n      K1 = I1MACH(15)\n      K2 = I1MACH(16)\n      R1M5 = D1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0)\n      K1 = I1MACH(14) - 1\n      AA = R1M5*DBLE(FLOAT(K1))\n      DIG = DMIN1(AA,18.0D0)\n      AA = AA*2.303D0\n      ALIM = ELIM + DMAX1(-AA,-41.45D0)\n      FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0)\n      RL = 1.2D0*DIG + 3.0D0\n      FN = FNU + DBLE(FLOAT(NN-1))\n      MM = 3 - M - M\n      FMM = DBLE(FLOAT(MM))\n      ZNR = FMM*ZI\n      ZNI = -FMM*ZR\nC-----------------------------------------------------------------------\nC     TEST FOR PROPER RANGE\nC-----------------------------------------------------------------------\n      AZ = XZABS(ZR,ZI)\n      AA = 0.5D0/TOL\n      BB=DBLE(FLOAT(I1MACH(9)))*0.5D0\n      AA = DMIN1(AA,BB)\n      IF (AZ.GT.AA) GO TO 260\n      IF (FN.GT.AA) GO TO 260\n      AA = DSQRT(AA)\n      IF (AZ.GT.AA) IERR=3\n      IF (FN.GT.AA) IERR=3\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST ON THE LAST MEMBER OF THE SEQUENCE\nC-----------------------------------------------------------------------\n   35 CONTINUE\n      UFL = D1MACH(1)*1.0D+3\n      IF (AZ.LT.UFL) GO TO 230\n      IF (FNU.GT.FNUL) GO TO 90\n      IF (FN.LE.1.0D0) GO TO 70\n      IF (FN.GT.2.0D0) GO TO 60\n      IF (AZ.GT.TOL) GO TO 70\n      ARG = 0.5D0*AZ\n      ALN = -FN*DLOG(ARG)\n      IF (ALN.GT.ELIM) GO TO 230\n      GO TO 70\n   60 CONTINUE\n      CALL ZUOIK(ZNR, ZNI, FNU, KODE, 2, NN, CYR, CYI, NUF, TOL, ELIM,\n     * ALIM)\n      IF (NUF.LT.0) GO TO 230\n      NZ = NZ + NUF\n      NN = NN - NUF\nC-----------------------------------------------------------------------\nC     HERE NN=N OR NN=0 SINCE NUF=0,NN, OR -1 ON RETURN FROM CUOIK\nC     IF NUF=NN, THEN CY(I)=CZERO FOR ALL I\nC-----------------------------------------------------------------------\n      IF (NN.EQ.0) GO TO 140\n   70 CONTINUE\n      IF ((ZNR.LT.0.0D0) .OR. (ZNR.EQ.0.0D0 .AND. ZNI.LT.0.0D0 .AND.\n     * M.EQ.2)) GO TO 80\nC-----------------------------------------------------------------------\nC     RIGHT HALF PLANE COMPUTATION, XN.GE.0. .AND. (XN.NE.0. .OR.\nC     YN.GE.0. .OR. M=1)\nC-----------------------------------------------------------------------\n      CALL ZBKNU(ZNR, ZNI, FNU, KODE, NN, CYR, CYI, NZ, TOL, ELIM, ALIM)\n      GO TO 110\nC-----------------------------------------------------------------------\nC     LEFT HALF PLANE COMPUTATION\nC-----------------------------------------------------------------------\n   80 CONTINUE\n      MR = -MM\n      CALL ZACON(ZNR, ZNI, FNU, KODE, MR, NN, CYR, CYI, NW, RL, FNUL,\n     * TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 240\n      NZ=NW\n      GO TO 110\n   90 CONTINUE\nC-----------------------------------------------------------------------\nC     UNIFORM ASYMPTOTIC EXPANSIONS FOR FNU.GT.FNUL\nC-----------------------------------------------------------------------\n      MR = 0\n      IF ((ZNR.GE.0.0D0) .AND. (ZNR.NE.0.0D0 .OR. ZNI.GE.0.0D0 .OR.\n     * M.NE.2)) GO TO 100\n      MR = -MM\n      IF (ZNR.NE.0.0D0 .OR. ZNI.GE.0.0D0) GO TO 100\n      ZNR = -ZNR\n      ZNI = -ZNI\n  100 CONTINUE\n      CALL ZBUNK(ZNR, ZNI, FNU, KODE, MR, NN, CYR, CYI, NW, TOL, ELIM,\n     * ALIM)\n      IF (NW.LT.0) GO TO 240\n      NZ = NZ + NW\n  110 CONTINUE\nC-----------------------------------------------------------------------\nC     H(M,FNU,Z) = -FMM*(I/HPI)*(ZT**FNU)*K(FNU,-Z*ZT)\nC\nC     ZT=EXP(-FMM*HPI*I) = CMPLX(0.0,-FMM), FMM=3-2*M, M=1,2\nC-----------------------------------------------------------------------\n      SGN = DSIGN(HPI,-FMM)\nC-----------------------------------------------------------------------\nC     CALCULATE EXP(FNU*HPI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(SNGL(FNU))\n      INUH = INU/2\n      IR = INU - 2*INUH\n      ARG = (FNU-DBLE(FLOAT(INU-IR)))*SGN\n      RHPI = 1.0D0/SGN\nC     ZNI = RHPI*DCOS(ARG)\nC     ZNR = -RHPI*DSIN(ARG)\n      CSGNI = RHPI*DCOS(ARG)\n      CSGNR = -RHPI*DSIN(ARG)\n      IF (MOD(INUH,2).EQ.0) GO TO 120\nC     ZNR = -ZNR\nC     ZNI = -ZNI\n      CSGNR = -CSGNR\n      CSGNI = -CSGNI\n  120 CONTINUE\n      ZTI = -FMM\n      RTOL = 1.0D0/TOL\n      ASCLE = UFL*RTOL\n      DO 130 I=1,NN\nC       STR = CYR(I)*ZNR - CYI(I)*ZNI\nC       CYI(I) = CYR(I)*ZNI + CYI(I)*ZNR\nC       CYR(I) = STR\nC       STR = -ZNI*ZTI\nC       ZNI = ZNR*ZTI\nC       ZNR = STR\n        AA = CYR(I)\n        BB = CYI(I)\n        ATOL = 1.0D0\n        IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 135\n          AA = AA*RTOL\n          BB = BB*RTOL\n          ATOL = TOL\n  135 CONTINUE\n      STR = AA*CSGNR - BB*CSGNI\n      STI = AA*CSGNI + BB*CSGNR\n      CYR(I) = STR*ATOL\n      CYI(I) = STI*ATOL\n      STR = -CSGNI*ZTI\n      CSGNI = CSGNR*ZTI\n      CSGNR = STR\n  130 CONTINUE\n      RETURN\n  140 CONTINUE\n      IF (ZNR.LT.0.0D0) GO TO 230\n      RETURN\n  230 CONTINUE\n      NZ=0\n      IERR=2\n      RETURN\n  240 CONTINUE\n      IF(NW.EQ.(-1)) GO TO 230\n      NZ=0\n      IERR=5\n      RETURN\n  260 CONTINUE\n      IERR=4\n      GO TO 35\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbesi.f",
    "content": "      SUBROUTINE ZBESI(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, IERR)\nC***BEGIN PROLOGUE  ZBESI\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  I-BESSEL FUNCTION,COMPLEX BESSEL FUNCTION,\nC             MODIFIED BESSEL FUNCTION OF THE FIRST KIND\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE I-BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC                    ***A DOUBLE PRECISION ROUTINE***\nC         ON KODE=1, ZBESI COMPUTES AN N MEMBER SEQUENCE OF COMPLEX\nC         BESSEL FUNCTIONS CY(J)=I(FNU+J-1,Z) FOR REAL, NONNEGATIVE\nC         ORDERS FNU+J-1, J=1,...,N AND COMPLEX Z IN THE CUT PLANE\nC         -PI.LT.ARG(Z).LE.PI. ON KODE=2, ZBESI RETURNS THE SCALED\nC         FUNCTIONS\nC\nC         CY(J)=EXP(-ABS(X))*I(FNU+J-1,Z)   J = 1,...,N , X=REAL(Z)\nC\nC         WITH THE EXPONENTIAL GROWTH REMOVED IN BOTH THE LEFT AND\nC         RIGHT HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION\nC         ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS\nC         (REF. 1).\nC\nC         INPUT      ZR,ZI,FNU ARE DOUBLE PRECISION\nC           ZR,ZI  - Z=CMPLX(ZR,ZI),  -PI.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL I FUNCTION, FNU.GE.0.0D0\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(J)=I(FNU+J-1,Z), J=1,...,N\nC                        = 2  RETURNS\nC                             CY(J)=I(FNU+J-1,Z)*EXP(-ABS(X)), J=1,...,N\nC           N      - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1\nC\nC         OUTPUT     CYR,CYI ARE DOUBLE PRECISION\nC           CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS\nC                    CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE\nC                    CY(J)=I(FNU+J-1,Z)  OR\nC                    CY(J)=I(FNU+J-1,Z)*EXP(-ABS(X))  J=1,...,N\nC                    DEPENDING ON KODE, X=REAL(Z)\nC           NZ     - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW,\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ.GT.0 , LAST NZ COMPONENTS OF CY SET TO ZERO\nC                              TO UNDERFLOW, CY(J)=CMPLX(0.0D0,0.0D0)\nC                              J = N-NZ+1,...,N\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, REAL(Z) TOO\nC                            LARGE ON KODE=1\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         THE COMPUTATION IS CARRIED OUT BY THE POWER SERIES FOR\nC         SMALL CABS(Z), THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z),\nC         THE MILLER ALGORITHM NORMALIZED BY THE WRONSKIAN AND A\nC         NEUMANN SERIES FOR IMTERMEDIATE MAGNITUDES, AND THE\nC         UNIFORM ASYMPTOTIC EXPANSIONS FOR I(FNU,Z) AND J(FNU,Z)\nC         FOR LARGE ORDERS. BACKWARD RECURRENCE IS USED TO GENERATE\nC         SEQUENCES OR REDUCE ORDERS WHEN NECESSARY.\nC\nC         THE CALCULATIONS ABOVE ARE DONE IN THE RIGHT HALF PLANE AND\nC         CONTINUED INTO THE LEFT HALF PLANE BY THE FORMULA\nC\nC         I(FNU,Z*EXP(M*PI)) = EXP(M*PI*FNU)*I(FNU,Z)  REAL(Z).GT.0.0\nC                       M = +I OR -I,  I**2=-1\nC\nC         FOR NEGATIVE ORDERS,THE FORMULA\nC\nC              I(-FNU,Z) = I(FNU,Z) + (2/PI)*SIN(PI*FNU)*K(FNU,Z)\nC\nC         CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO INTEGERS, THE\nC         THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE POSITIVE\nC         INTEGER,THE MAGNITUDE OF I(-FNU,Z)=I(FNU,Z) IS A LARGE\nC         NEGATIVE POWER OF TEN. BUT WHEN FNU IS NOT AN INTEGER,\nC         K(FNU,Z) DOMINATES IN MAGNITUDE WITH A LARGE POSITIVE POWER OF\nC         TEN AND THE MOST THAT THE SECOND TERM CAN BE REDUCED IS BY\nC         UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, WIDE CHANGES CAN\nC         OCCUR WITHIN UNIT ROUNDOFF OF A LARGE INTEGER FOR FNU. HERE,\nC         LARGE MEANS FNU.GT.CABS(Z).\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS\nC         DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION.\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  ZBINU,I1MACH,D1MACH\nC***END PROLOGUE  ZBESI\nC     COMPLEX CONE,CSGN,CW,CY,CZERO,Z,ZN\n      DOUBLE PRECISION AA, ALIM, ARG, CONEI, CONER, CSGNI, CSGNR, CYI,\n     * CYR, DIG, ELIM, FNU, FNUL, PI, RL, R1M5, STR, TOL, ZI, ZNI, ZNR,\n     * ZR, D1MACH, AZ, BB, FN, XZABS, ASCLE, RTOL, ATOL, STI\n      INTEGER I, IERR, INU, K, KODE, K1,K2,N,NZ,NN, I1MACH\n      DIMENSION CYR(N), CYI(N)\n      DATA PI /3.14159265358979324D0/\n      DATA CONER, CONEI /1.0D0,0.0D0/\nC\nC***FIRST EXECUTABLE STATEMENT  ZBESI\n      IERR = 0\n      NZ=0\n      IF (FNU.LT.0.0D0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU.\nC-----------------------------------------------------------------------\n      TOL = DMAX1(D1MACH(4),1.0D-18)\n      K1 = I1MACH(15)\n      K2 = I1MACH(16)\n      R1M5 = D1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0)\n      K1 = I1MACH(14) - 1\n      AA = R1M5*DBLE(FLOAT(K1))\n      DIG = DMIN1(AA,18.0D0)\n      AA = AA*2.303D0\n      ALIM = ELIM + DMAX1(-AA,-41.45D0)\n      RL = 1.2D0*DIG + 3.0D0\n      FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0)\nC-----------------------------------------------------------------------------\nC     TEST FOR PROPER RANGE\nC-----------------------------------------------------------------------\n      AZ = XZABS(ZR,ZI)\n      FN = FNU+DBLE(FLOAT(N-1))\n      AA = 0.5D0/TOL\n      BB=DBLE(FLOAT(I1MACH(9)))*0.5D0\n      AA = DMIN1(AA,BB)\n      IF (AZ.GT.AA) GO TO 260\n      IF (FN.GT.AA) GO TO 260\n      AA = DSQRT(AA)\n      IF (AZ.GT.AA) IERR=3\n      IF (FN.GT.AA) IERR=3\n   35 CONTINUE\n      ZNR = ZR\n      ZNI = ZI\n      CSGNR = CONER\n      CSGNI = CONEI\n      IF (ZR.GE.0.0D0) GO TO 40\n      ZNR = -ZR\n      ZNI = -ZI\nC-----------------------------------------------------------------------\nC     CALCULATE CSGN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n      INU = INT(SNGL(FNU))\n      ARG = (FNU-DBLE(FLOAT(INU)))*PI\n      IF (ZI.LT.0.0D0) ARG = -ARG\n      CSGNR = DCOS(ARG)\n      CSGNI = DSIN(ARG)\n      IF (MOD(INU,2).EQ.0) GO TO 40\n      CSGNR = -CSGNR\n      CSGNI = -CSGNI\n   40 CONTINUE\n      CALL ZBINU(ZNR, ZNI, FNU, KODE, N, CYR, CYI, NZ, RL, FNUL, TOL,\n     * ELIM, ALIM)\n      IF (NZ.LT.0) GO TO 120\n      IF (ZR.GE.0.0D0) RETURN\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION TO THE LEFT HALF PLANE\nC-----------------------------------------------------------------------\n      NN = N - NZ\n      IF (NN.EQ.0) RETURN\n      RTOL = 1.0D0/TOL\n      ASCLE = D1MACH(1)*RTOL*1.0D+3\n      DO 50 I=1,NN\nC       STR = CYR(I)*CSGNR - CYI(I)*CSGNI\nC       CYI(I) = CYR(I)*CSGNI + CYI(I)*CSGNR\nC       CYR(I) = STR\n        AA = CYR(I)\n        BB = CYI(I)\n        ATOL = 1.0D0\n        IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 55\n          AA = AA*RTOL\n          BB = BB*RTOL\n          ATOL = TOL\n   55   CONTINUE\n        STR = AA*CSGNR - BB*CSGNI\n        STI = AA*CSGNI + BB*CSGNR\n        CYR(I) = STR*ATOL\n        CYI(I) = STI*ATOL\n        CSGNR = -CSGNR\n        CSGNI = -CSGNI\n   50 CONTINUE\n      RETURN\n  120 CONTINUE\n      IF(NZ.EQ.(-2)) GO TO 130\n      NZ = 0\n      IERR=2\n      RETURN\n  130 CONTINUE\n      NZ=0\n      IERR=5\n      RETURN\n  260 CONTINUE\n      IERR=4\n      GO TO 35\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbesj.f",
    "content": "      SUBROUTINE ZBESJ(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, IERR)\nC***BEGIN PROLOGUE  ZBESJ\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  J-BESSEL FUNCTION,BESSEL FUNCTION OF COMPLEX ARGUMENT,\nC             BESSEL FUNCTION OF FIRST KIND\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE THE J-BESSEL FUNCTION OF A COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC                      ***A DOUBLE PRECISION ROUTINE***\nC         ON KODE=1, CBESJ COMPUTES AN N MEMBER  SEQUENCE OF COMPLEX\nC         BESSEL FUNCTIONS CY(I)=J(FNU+I-1,Z) FOR REAL, NONNEGATIVE\nC         ORDERS FNU+I-1, I=1,...,N AND COMPLEX Z IN THE CUT PLANE\nC         -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESJ RETURNS THE SCALED\nC         FUNCTIONS\nC\nC         CY(I)=EXP(-ABS(Y))*J(FNU+I-1,Z)   I = 1,...,N , Y=AIMAG(Z)\nC\nC         WHICH REMOVE THE EXPONENTIAL GROWTH IN BOTH THE UPPER AND\nC         LOWER HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION\nC         ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS\nC         (REF. 1).\nC\nC         INPUT      ZR,ZI,FNU ARE DOUBLE PRECISION\nC           ZR,ZI  - Z=CMPLX(ZR,ZI),  -PI.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL J FUNCTION, FNU.GE.0.0D0\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(I)=J(FNU+I-1,Z), I=1,...,N\nC                        = 2  RETURNS\nC                             CY(I)=J(FNU+I-1,Z)EXP(-ABS(Y)), I=1,...,N\nC           N      - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1\nC\nC         OUTPUT     CYR,CYI ARE DOUBLE PRECISION\nC           CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS\nC                    CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE\nC                    CY(I)=J(FNU+I-1,Z)  OR\nC                    CY(I)=J(FNU+I-1,Z)EXP(-ABS(Y))  I=1,...,N\nC                    DEPENDING ON KODE, Y=AIMAG(Z).\nC           NZ     - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW,\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ.GT.0 , LAST NZ COMPONENTS OF CY SET  ZERO DUE\nC                              TO UNDERFLOW, CY(I)=CMPLX(0.0D0,0.0D0),\nC                              I = N-NZ+1,...,N\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, AIMAG(Z)\nC                            TOO LARGE ON KODE=1\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         THE COMPUTATION IS CARRIED OUT BY THE FORMULA\nC\nC         J(FNU,Z)=EXP( FNU*PI*I/2)*I(FNU,-I*Z)    AIMAG(Z).GE.0.0\nC\nC         J(FNU,Z)=EXP(-FNU*PI*I/2)*I(FNU, I*Z)    AIMAG(Z).LT.0.0\nC\nC         WHERE I**2 = -1 AND I(FNU,Z) IS THE I BESSEL FUNCTION.\nC\nC         FOR NEGATIVE ORDERS,THE FORMULA\nC\nC              J(-FNU,Z) = J(FNU,Z)*COS(PI*FNU) - Y(FNU,Z)*SIN(PI*FNU)\nC\nC         CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO INTEGERS, THE\nC         THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE POSITIVE\nC         INTEGER,THE MAGNITUDE OF J(-FNU,Z)=J(FNU,Z)*COS(PI*FNU) IS A\nC         LARGE NEGATIVE POWER OF TEN. BUT WHEN FNU IS NOT AN INTEGER,\nC         Y(FNU,Z) DOMINATES IN MAGNITUDE WITH A LARGE POSITIVE POWER OF\nC         TEN AND THE MOST THAT THE SECOND TERM CAN BE REDUCED IS BY\nC         UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, WIDE CHANGES CAN\nC         OCCUR WITHIN UNIT ROUNDOFF OF A LARGE INTEGER FOR FNU. HERE,\nC         LARGE MEANS FNU.GT.CABS(Z).\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS\nC         DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION.\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  ZBINU,I1MACH,D1MACH\nC***END PROLOGUE  ZBESJ\nC\nC     COMPLEX CI,CSGN,CY,Z,ZN\n      DOUBLE PRECISION AA, ALIM, ARG, CII, CSGNI, CSGNR, CYI, CYR, DIG,\n     * ELIM, FNU, FNUL, HPI, RL, R1M5, STR, TOL, ZI, ZNI, ZNR, ZR,\n     * D1MACH, BB, FN, AZ, XZABS, ASCLE, RTOL, ATOL, STI\n      INTEGER I, IERR, INU, INUH, IR, K, KODE, K1, K2, N, NL, NZ, I1MACH\n      DIMENSION CYR(N), CYI(N)\n      DATA HPI /1.57079632679489662D0/\nC\nC***FIRST EXECUTABLE STATEMENT  ZBESJ\n      IERR = 0\n      NZ=0\n      IF (FNU.LT.0.0D0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU.\nC-----------------------------------------------------------------------\n      TOL = DMAX1(D1MACH(4),1.0D-18)\n      K1 = I1MACH(15)\n      K2 = I1MACH(16)\n      R1M5 = D1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0)\n      K1 = I1MACH(14) - 1\n      AA = R1M5*DBLE(FLOAT(K1))\n      DIG = DMIN1(AA,18.0D0)\n      AA = AA*2.303D0\n      ALIM = ELIM + DMAX1(-AA,-41.45D0)\n      RL = 1.2D0*DIG + 3.0D0\n      FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0)\nC-----------------------------------------------------------------------\nC     TEST FOR PROPER RANGE\nC-----------------------------------------------------------------------\n      AZ = XZABS(ZR,ZI)\n      FN = FNU+DBLE(FLOAT(N-1))\n      AA = 0.5D0/TOL\n      BB=DBLE(FLOAT(I1MACH(9)))*0.5D0\n      AA = DMIN1(AA,BB)\n      IF (AZ.GT.AA) GO TO 260\n      IF (FN.GT.AA) GO TO 260\n      AA = DSQRT(AA)\n      IF (AZ.GT.AA) IERR=3\n      IF (FN.GT.AA) IERR=3\nC-----------------------------------------------------------------------\nC     CALCULATE CSGN=EXP(FNU*HPI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE\nC     WHEN FNU IS LARGE\nC-----------------------------------------------------------------------\n  35  CONTINUE\n      CII = 1.0D0\n      INU = INT(SNGL(FNU))\n      INUH = INU/2\n      IR = INU - 2*INUH\n      ARG = (FNU-DBLE(FLOAT(INU-IR)))*HPI\n      CSGNR = DCOS(ARG)\n      CSGNI = DSIN(ARG)\n      IF (MOD(INUH,2).EQ.0) GO TO 40\n      CSGNR = -CSGNR\n      CSGNI = -CSGNI\n   40 CONTINUE\nC-----------------------------------------------------------------------\nC     ZN IS IN THE RIGHT HALF PLANE\nC-----------------------------------------------------------------------\n      ZNR = ZI\n      ZNI = -ZR\n      IF (ZI.GE.0.0D0) GO TO 50\n      ZNR = -ZNR\n      ZNI = -ZNI\n      CSGNI = -CSGNI\n      CII = -CII\n   50 CONTINUE\n      CALL ZBINU(ZNR, ZNI, FNU, KODE, N, CYR, CYI, NZ, RL, FNUL, TOL,\n     * ELIM, ALIM)\n      IF (NZ.LT.0) GO TO 130\n      NL = N - NZ\n      IF (NL.EQ.0) RETURN\n      RTOL = 1.0D0/TOL\n      ASCLE = D1MACH(1)*RTOL*1.0D+3\n      DO 60 I=1,NL\nC       STR = CYR(I)*CSGNR - CYI(I)*CSGNI\nC       CYI(I) = CYR(I)*CSGNI + CYI(I)*CSGNR\nC       CYR(I) = STR\n        AA = CYR(I)\n        BB = CYI(I)\n        ATOL = 1.0D0\n        IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 55\n          AA = AA*RTOL\n          BB = BB*RTOL\n          ATOL = TOL\n   55   CONTINUE\n        STR = AA*CSGNR - BB*CSGNI\n        STI = AA*CSGNI + BB*CSGNR\n        CYR(I) = STR*ATOL\n        CYI(I) = STI*ATOL\n        STR = -CSGNI*CII\n        CSGNI = CSGNR*CII\n        CSGNR = STR\n   60 CONTINUE\n      RETURN\n  130 CONTINUE\n      IF(NZ.EQ.(-2)) GO TO 140\n      NZ = 0\n      IERR = 2\n      RETURN\n  140 CONTINUE\n      NZ=0\n      IERR=5\n      RETURN\n  260 CONTINUE\n      IERR=4\n      GO TO 35\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbesk.f",
    "content": "      SUBROUTINE ZBESK(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, IERR)\nC***BEGIN PROLOGUE  ZBESK\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  K-BESSEL FUNCTION,COMPLEX BESSEL FUNCTION,\nC             MODIFIED BESSEL FUNCTION OF THE SECOND KIND,\nC             BESSEL FUNCTION OF THE THIRD KIND\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE K-BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC                      ***A DOUBLE PRECISION ROUTINE***\nC\nC         ON KODE=1, CBESK COMPUTES AN N MEMBER SEQUENCE OF COMPLEX\nC         BESSEL FUNCTIONS CY(J)=K(FNU+J-1,Z) FOR REAL, NONNEGATIVE\nC         ORDERS FNU+J-1, J=1,...,N AND COMPLEX Z.NE.CMPLX(0.0,0.0)\nC         IN THE CUT PLANE -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESK\nC         RETURNS THE SCALED K FUNCTIONS,\nC\nC         CY(J)=EXP(Z)*K(FNU+J-1,Z) , J=1,...,N,\nC\nC         WHICH REMOVE THE EXPONENTIAL BEHAVIOR IN BOTH THE LEFT AND\nC         RIGHT HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND\nC         NOTATION ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL\nC         FUNCTIONS (REF. 1).\nC\nC         INPUT      ZR,ZI,FNU ARE DOUBLE PRECISION\nC           ZR,ZI  - Z=CMPLX(ZR,ZI), Z.NE.CMPLX(0.0D0,0.0D0),\nC                    -PI.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL K FUNCTION, FNU.GE.0.0D0\nC           N      - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(I)=K(FNU+I-1,Z), I=1,...,N\nC                        = 2  RETURNS\nC                             CY(I)=K(FNU+I-1,Z)*EXP(Z), I=1,...,N\nC\nC         OUTPUT     CYR,CYI ARE DOUBLE PRECISION\nC           CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS\nC                    CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE\nC                    CY(I)=K(FNU+I-1,Z), I=1,...,N OR\nC                    CY(I)=K(FNU+I-1,Z)*EXP(Z), I=1,...,N\nC                    DEPENDING ON KODE\nC           NZ     - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW.\nC                    NZ= 0   , NORMAL RETURN\nC                    NZ.GT.0 , FIRST NZ COMPONENTS OF CY SET TO ZERO DUE\nC                              TO UNDERFLOW, CY(I)=CMPLX(0.0D0,0.0D0),\nC                              I=1,...,N WHEN X.GE.0.0. WHEN X.LT.0.0\nC                              NZ STATES ONLY THE NUMBER OF UNDERFLOWS\nC                              IN THE SEQUENCE.\nC\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, FNU IS\nC                            TOO LARGE OR CABS(Z) IS TOO SMALL OR BOTH\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         EQUATIONS OF THE REFERENCE ARE IMPLEMENTED FOR SMALL ORDERS\nC         DNU AND DNU+1.0 IN THE RIGHT HALF PLANE X.GE.0.0. FORWARD\nC         RECURRENCE GENERATES HIGHER ORDERS. K IS CONTINUED TO THE LEFT\nC         HALF PLANE BY THE RELATION\nC\nC         K(FNU,Z*EXP(MP)) = EXP(-MP*FNU)*K(FNU,Z)-MP*I(FNU,Z)\nC         MP=MR*PI*I, MR=+1 OR -1, RE(Z).GT.0, I**2=-1\nC\nC         WHERE I(FNU,Z) IS THE I BESSEL FUNCTION.\nC\nC         FOR LARGE ORDERS, FNU.GT.FNUL, THE K FUNCTION IS COMPUTED\nC         BY MEANS OF ITS UNIFORM ASYMPTOTIC EXPANSIONS.\nC\nC         FOR NEGATIVE ORDERS, THE FORMULA\nC\nC                       K(-FNU,Z) = K(FNU,Z)\nC\nC         CAN BE USED.\nC\nC         CBESK ASSUMES THAT A SIGNIFICANT DIGIT SINH(X) FUNCTION IS\nC         AVAILABLE.\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS\nC         DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION.\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983.\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  ZACON,ZBKNU,ZBUNK,ZUOIK,XZABS,I1MACH,D1MACH\nC***END PROLOGUE  ZBESK\nC\nC     COMPLEX CY,Z\n      DOUBLE PRECISION AA, ALIM, ALN, ARG, AZ, CYI, CYR, DIG, ELIM, FN,\n     * FNU, FNUL, RL, R1M5, TOL, UFL, ZI, ZR, D1MACH, XZABS, BB\n      INTEGER IERR, K, KODE, K1, K2, MR, N, NN, NUF, NW, NZ, I1MACH\n      DIMENSION CYR(N), CYI(N)\nC***FIRST EXECUTABLE STATEMENT  ZBESK\n      IERR = 0\n      NZ=0\n      IF (ZI.EQ.0.0E0 .AND. ZR.EQ.0.0E0) IERR=1\n      IF (FNU.LT.0.0D0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\n      NN = N\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU\nC-----------------------------------------------------------------------\n      TOL = DMAX1(D1MACH(4),1.0D-18)\n      K1 = I1MACH(15)\n      K2 = I1MACH(16)\n      R1M5 = D1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0)\n      K1 = I1MACH(14) - 1\n      AA = R1M5*DBLE(FLOAT(K1))\n      DIG = DMIN1(AA,18.0D0)\n      AA = AA*2.303D0\n      ALIM = ELIM + DMAX1(-AA,-41.45D0)\n      FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0)\n      RL = 1.2D0*DIG + 3.0D0\nC-----------------------------------------------------------------------------\nC     TEST FOR PROPER RANGE\nC-----------------------------------------------------------------------\n      AZ = XZABS(ZR,ZI)\n      FN = FNU + DBLE(FLOAT(NN-1))\n      AA = 0.5D0/TOL\n      BB=DBLE(FLOAT(I1MACH(9)))*0.5D0\n      AA = DMIN1(AA,BB)\n      IF (AZ.GT.AA) GO TO 260\n      IF (FN.GT.AA) GO TO 260\n      AA = DSQRT(AA)\n      IF (AZ.GT.AA) IERR=3\n      IF (FN.GT.AA) IERR=3\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST ON THE LAST MEMBER OF THE SEQUENCE\nC-----------------------------------------------------------------------\nC     UFL = DEXP(-ELIM)\n   35 CONTINUE\n      UFL = D1MACH(1)*1.0D+3\n      IF (AZ.LT.UFL) GO TO 180\n      IF (FNU.GT.FNUL) GO TO 80\n      IF (FN.LE.1.0D0) GO TO 60\n      IF (FN.GT.2.0D0) GO TO 50\n      IF (AZ.GT.TOL) GO TO 60\n      ARG = 0.5D0*AZ\n      ALN = -FN*DLOG(ARG)\n      IF (ALN.GT.ELIM) GO TO 180\n      GO TO 60\n   50 CONTINUE\n      CALL ZUOIK(ZR, ZI, FNU, KODE, 2, NN, CYR, CYI, NUF, TOL, ELIM,\n     * ALIM)\n      IF (NUF.LT.0) GO TO 180\n      NZ = NZ + NUF\n      NN = NN - NUF\nC-----------------------------------------------------------------------\nC     HERE NN=N OR NN=0 SINCE NUF=0,NN, OR -1 ON RETURN FROM CUOIK\nC     IF NUF=NN, THEN CY(I)=CZERO FOR ALL I\nC-----------------------------------------------------------------------\n      IF (NN.EQ.0) GO TO 100\n   60 CONTINUE\n      IF (ZR.LT.0.0D0) GO TO 70\nC-----------------------------------------------------------------------\nC     RIGHT HALF PLANE COMPUTATION, REAL(Z).GE.0.\nC-----------------------------------------------------------------------\n      CALL ZBKNU(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 200\n      NZ=NW\n      RETURN\nC-----------------------------------------------------------------------\nC     LEFT HALF PLANE COMPUTATION\nC     PI/2.LT.ARG(Z).LE.PI AND -PI.LT.ARG(Z).LT.-PI/2.\nC-----------------------------------------------------------------------\n   70 CONTINUE\n      IF (NZ.NE.0) GO TO 180\n      MR = 1\n      IF (ZI.LT.0.0D0) MR = -1\n      CALL ZACON(ZR, ZI, FNU, KODE, MR, NN, CYR, CYI, NW, RL, FNUL,\n     * TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 200\n      NZ=NW\n      RETURN\nC-----------------------------------------------------------------------\nC     UNIFORM ASYMPTOTIC EXPANSIONS FOR FNU.GT.FNUL\nC-----------------------------------------------------------------------\n   80 CONTINUE\n      MR = 0\n      IF (ZR.GE.0.0D0) GO TO 90\n      MR = 1\n      IF (ZI.LT.0.0D0) MR = -1\n   90 CONTINUE\n      CALL ZBUNK(ZR, ZI, FNU, KODE, MR, NN, CYR, CYI, NW, TOL, ELIM,\n     * ALIM)\n      IF (NW.LT.0) GO TO 200\n      NZ = NZ + NW\n      RETURN\n  100 CONTINUE\n      IF (ZR.LT.0.0D0) GO TO 180\n      RETURN\n  180 CONTINUE\n      NZ = 0\n      IERR=2\n      RETURN\n  200 CONTINUE\n      IF(NW.EQ.(-1)) GO TO 180\n      NZ=0\n      IERR=5\n      RETURN\n  260 CONTINUE\n      IERR=4\n      GO TO 35\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbesy.f",
    "content": "      SUBROUTINE ZBESY(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, CWRKR, CWRKI,\n     *                 IERR)\nC***BEGIN PROLOGUE  ZBESY\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  Y-BESSEL FUNCTION,BESSEL FUNCTION OF COMPLEX ARGUMENT,\nC             BESSEL FUNCTION OF SECOND KIND\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE THE Y-BESSEL FUNCTION OF A COMPLEX ARGUMENT\nC***DESCRIPTION\nC\nC                      ***A DOUBLE PRECISION ROUTINE***\nC\nC         ON KODE=1, CBESY COMPUTES AN N MEMBER SEQUENCE OF COMPLEX\nC         BESSEL FUNCTIONS CY(I)=Y(FNU+I-1,Z) FOR REAL, NONNEGATIVE\nC         ORDERS FNU+I-1, I=1,...,N AND COMPLEX Z IN THE CUT PLANE\nC         -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESY RETURNS THE SCALED\nC         FUNCTIONS\nC\nC         CY(I)=EXP(-ABS(Y))*Y(FNU+I-1,Z)   I = 1,...,N , Y=AIMAG(Z)\nC\nC         WHICH REMOVE THE EXPONENTIAL GROWTH IN BOTH THE UPPER AND\nC         LOWER HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION\nC         ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS\nC         (REF. 1).\nC\nC         INPUT      ZR,ZI,FNU ARE DOUBLE PRECISION\nC           ZR,ZI  - Z=CMPLX(ZR,ZI), Z.NE.CMPLX(0.0D0,0.0D0),\nC                    -PI.LT.ARG(Z).LE.PI\nC           FNU    - ORDER OF INITIAL Y FUNCTION, FNU.GE.0.0D0\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             CY(I)=Y(FNU+I-1,Z), I=1,...,N\nC                        = 2  RETURNS\nC                             CY(I)=Y(FNU+I-1,Z)*EXP(-ABS(Y)), I=1,...,N\nC                             WHERE Y=AIMAG(Z)\nC           N      - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1\nC           CWRKR, - DOUBLE PRECISION WORK VECTORS OF DIMENSION AT\nC           CWRKI    AT LEAST N\nC\nC         OUTPUT     CYR,CYI ARE DOUBLE PRECISION\nC           CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS\nC                    CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE\nC                    CY(I)=Y(FNU+I-1,Z)  OR\nC                    CY(I)=Y(FNU+I-1,Z)*EXP(-ABS(Y))  I=1,...,N\nC                    DEPENDING ON KODE.\nC           NZ     - NZ=0 , A NORMAL RETURN\nC                    NZ.GT.0 , NZ COMPONENTS OF CY SET TO ZERO DUE TO\nC                    UNDERFLOW (GENERALLY ON KODE=2)\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, FNU IS\nC                            TOO LARGE OR CABS(Z) IS TOO SMALL OR BOTH\nC                    IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE\nC                            BUT LOSSES OF SIGNIFCANCE BY ARGUMENT\nC                            REDUCTION PRODUCE LESS THAN HALF OF MACHINE\nC                            ACCURACY\nC                    IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA-\nC                            TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI-\nC                            CANCE BY ARGUMENT REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         THE COMPUTATION IS CARRIED OUT BY THE FORMULA\nC\nC         Y(FNU,Z)=0.5*(H(1,FNU,Z)-H(2,FNU,Z))/I\nC\nC         WHERE I**2 = -1 AND THE HANKEL BESSEL FUNCTIONS H(1,FNU,Z)\nC         AND H(2,FNU,Z) ARE CALCULATED IN CBESH.\nC\nC         FOR NEGATIVE ORDERS,THE FORMULA\nC\nC              Y(-FNU,Z) = Y(FNU,Z)*COS(PI*FNU) + J(FNU,Z)*SIN(PI*FNU)\nC\nC         CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO HALF ODD\nC         INTEGERS THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE\nC         POSITIVE HALF ODD INTEGER,THE MAGNITUDE OF Y(-FNU,Z)=J(FNU,Z)*\nC         SIN(PI*FNU) IS A LARGE NEGATIVE POWER OF TEN. BUT WHEN FNU IS\nC         NOT A HALF ODD INTEGER, Y(FNU,Z) DOMINATES IN MAGNITUDE WITH A\nC         LARGE POSITIVE POWER OF TEN AND THE MOST THAT THE SECOND TERM\nC         CAN BE REDUCED IS BY UNIT ROUNDOFF FROM THE COEFFICIENT. THUS,\nC         WIDE CHANGES CAN OCCUR WITHIN UNIT ROUNDOFF OF A LARGE HALF\nC         ODD INTEGER. HERE, LARGE MEANS FNU.GT.CABS(Z).\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS\nC         LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR.\nC         CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN\nC         LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG\nC         IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS\nC         DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION.\nC         IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS\nC         LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS\nC         MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE\nC         INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS\nC         RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3\nC         ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION\nC         ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION\nC         ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN\nC         THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT\nC         TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS\nC         IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC.\nC         SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 BY D. E. AMOS, SAND83-0083, MAY, 1983.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  ZBESH,I1MACH,D1MACH\nC***END PROLOGUE  ZBESY\nC\nC     COMPLEX CWRK,CY,C1,C2,EX,HCI,Z,ZU,ZV\n      DOUBLE PRECISION CWRKI, CWRKR, CYI, CYR, C1I, C1R, C2I, C2R,\n     * ELIM, EXI, EXR, EY, FNU, HCII, STI, STR, TAY, ZI, ZR, DEXP,\n     * D1MACH, ASCLE, RTOL, ATOL, AA, BB, TOL\n      INTEGER I, IERR, K, KODE, K1, K2, N, NZ, NZ1, NZ2, I1MACH\n      DIMENSION CYR(N), CYI(N), CWRKR(N), CWRKI(N)\nC***FIRST EXECUTABLE STATEMENT  ZBESY\n      IERR = 0\n      NZ=0\n      IF (ZR.EQ.0.0D0 .AND. ZI.EQ.0.0D0) IERR=1\n      IF (FNU.LT.0.0D0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (N.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\n      HCII = 0.5D0\n      CALL ZBESH(ZR, ZI, FNU, KODE, 1, N, CYR, CYI, NZ1, IERR)\n      IF (IERR.NE.0.AND.IERR.NE.3) GO TO 170\n      CALL ZBESH(ZR, ZI, FNU, KODE, 2, N, CWRKR, CWRKI, NZ2, IERR)\n      IF (IERR.NE.0.AND.IERR.NE.3) GO TO 170\n      NZ = MIN0(NZ1,NZ2)\n      IF (KODE.EQ.2) GO TO 60\n      DO 50 I=1,N\n        STR = CWRKR(I) - CYR(I)\n        STI = CWRKI(I) - CYI(I)\n        CYR(I) = -STI*HCII\n        CYI(I) = STR*HCII\n   50 CONTINUE\n      RETURN\n   60 CONTINUE\n      TOL = DMAX1(D1MACH(4),1.0D-18)\n      K1 = I1MACH(15)\n      K2 = I1MACH(16)\n      K = MIN0(IABS(K1),IABS(K2))\n      R1M5 = D1MACH(5)\nC-----------------------------------------------------------------------\nC     ELIM IS THE APPROXIMATE EXPONENTIAL UNDER- AND OVERFLOW LIMIT\nC-----------------------------------------------------------------------\n      ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0)\n      EXR = DCOS(ZR)\n      EXI = DSIN(ZR)\n      EY = 0.0D0\n      TAY = DABS(ZI+ZI)\n      IF (TAY.LT.ELIM) EY = DEXP(-TAY)\n      IF (ZI.LT.0.0D0) GO TO 90\n      C1R = EXR*EY\n      C1I = EXI*EY\n      C2R = EXR\n      C2I = -EXI\n   70 CONTINUE\n      NZ = 0\n      RTOL = 1.0D0/TOL\n      ASCLE = D1MACH(1)*RTOL*1.0D+3\n      DO 80 I=1,N\nC       STR = C1R*CYR(I) - C1I*CYI(I)\nC       STI = C1R*CYI(I) + C1I*CYR(I)\nC       STR = -STR + C2R*CWRKR(I) - C2I*CWRKI(I)\nC       STI = -STI + C2R*CWRKI(I) + C2I*CWRKR(I)\nC       CYR(I) = -STI*HCII\nC       CYI(I) = STR*HCII\n        AA = CWRKR(I)\n        BB = CWRKI(I)\n        ATOL = 1.0D0\n        IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 75\n          AA = AA*RTOL\n          BB = BB*RTOL\n          ATOL = TOL\n   75   CONTINUE\n        STR = (AA*C2R - BB*C2I)*ATOL\n        STI = (AA*C2I + BB*C2R)*ATOL\n        AA = CYR(I)\n        BB = CYI(I)\n        ATOL = 1.0D0\n        IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 85\n          AA = AA*RTOL\n          BB = BB*RTOL\n          ATOL = TOL\n   85   CONTINUE\n        STR = STR - (AA*C1R - BB*C1I)*ATOL\n        STI = STI - (AA*C1I + BB*C1R)*ATOL\n        CYR(I) = -STI*HCII\n        CYI(I) =  STR*HCII\n        IF (STR.EQ.0.0D0 .AND. STI.EQ.0.0D0 .AND. EY.EQ.0.0D0) NZ = NZ\n     *   + 1\n   80 CONTINUE\n      RETURN\n   90 CONTINUE\n      C1R = EXR\n      C1I = EXI\n      C2R = EXR*EY\n      C2I = -EXI*EY\n      GO TO 70\n  170 CONTINUE\n      NZ = 0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbinu.f",
    "content": "      SUBROUTINE ZBINU(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, RL, FNUL,\n     * TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  ZBINU\nC***REFER TO  ZBESH,ZBESI,ZBESJ,ZBESK,ZAIRY,ZBIRY\nC\nC     ZBINU COMPUTES THE I FUNCTION IN THE RIGHT HALF Z PLANE\nC\nC***ROUTINES CALLED  XZABS,ZASYI,ZBUNI,ZMLRI,ZSERI,ZUOIK,ZWRSK\nC***END PROLOGUE  ZBINU\n      DOUBLE PRECISION ALIM, AZ, CWI, CWR, CYI, CYR, DFNU, ELIM, FNU,\n     * FNUL, RL, TOL, ZEROI, ZEROR, ZI, ZR, XZABS\n      INTEGER I, INW, KODE, N, NLAST, NN, NUI, NW, NZ\n      DIMENSION CYR(N), CYI(N), CWR(2), CWI(2)\n      DATA ZEROR,ZEROI / 0.0D0, 0.0D0 /\nC\n      NZ = 0\n      AZ = XZABS(ZR,ZI)\n      NN = N\n      DFNU = FNU + DBLE(FLOAT(N-1))\n      IF (AZ.LE.2.0D0) GO TO 10\n      IF (AZ*AZ*0.25D0.GT.DFNU+1.0D0) GO TO 20\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     POWER SERIES\nC-----------------------------------------------------------------------\n      CALL ZSERI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, TOL, ELIM, ALIM)\n      INW = IABS(NW)\n      NZ = NZ + INW\n      NN = NN - INW\n      IF (NN.EQ.0) RETURN\n      IF (NW.GE.0) GO TO 120\n      DFNU = FNU + DBLE(FLOAT(NN-1))\n   20 CONTINUE\n      IF (AZ.LT.RL) GO TO 40\n      IF (DFNU.LE.1.0D0) GO TO 30\n      IF (AZ+AZ.LT.DFNU*DFNU) GO TO 50\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR LARGE Z\nC-----------------------------------------------------------------------\n   30 CONTINUE\n      CALL ZASYI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, RL, TOL, ELIM,\n     * ALIM)\n      IF (NW.LT.0) GO TO 130\n      GO TO 120\n   40 CONTINUE\n      IF (DFNU.LE.1.0D0) GO TO 70\n   50 CONTINUE\nC-----------------------------------------------------------------------\nC     OVERFLOW AND UNDERFLOW TEST ON I SEQUENCE FOR MILLER ALGORITHM\nC-----------------------------------------------------------------------\n      CALL ZUOIK(ZR, ZI, FNU, KODE, 1, NN, CYR, CYI, NW, TOL, ELIM,\n     * ALIM)\n      IF (NW.LT.0) GO TO 130\n      NZ = NZ + NW\n      NN = NN - NW\n      IF (NN.EQ.0) RETURN\n      DFNU = FNU+DBLE(FLOAT(NN-1))\n      IF (DFNU.GT.FNUL) GO TO 110\n      IF (AZ.GT.FNUL) GO TO 110\n   60 CONTINUE\n      IF (AZ.GT.RL) GO TO 80\n   70 CONTINUE\nC-----------------------------------------------------------------------\nC     MILLER ALGORITHM NORMALIZED BY THE SERIES\nC-----------------------------------------------------------------------\n      CALL ZMLRI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, TOL)\n      IF(NW.LT.0) GO TO 130\n      GO TO 120\n   80 CONTINUE\nC-----------------------------------------------------------------------\nC     MILLER ALGORITHM NORMALIZED BY THE WRONSKIAN\nC-----------------------------------------------------------------------\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST ON K FUNCTIONS USED IN WRONSKIAN\nC-----------------------------------------------------------------------\n      CALL ZUOIK(ZR, ZI, FNU, KODE, 2, 2, CWR, CWI, NW, TOL, ELIM,\n     * ALIM)\n      IF (NW.GE.0) GO TO 100\n      NZ = NN\n      DO 90 I=1,NN\n        CYR(I) = ZEROR\n        CYI(I) = ZEROI\n   90 CONTINUE\n      RETURN\n  100 CONTINUE\n      IF (NW.GT.0) GO TO 130\n      CALL ZWRSK(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, CWR, CWI, TOL,\n     * ELIM, ALIM)\n      IF (NW.LT.0) GO TO 130\n      GO TO 120\n  110 CONTINUE\nC-----------------------------------------------------------------------\nC     INCREMENT FNU+NN-1 UP TO FNUL, COMPUTE AND RECUR BACKWARD\nC-----------------------------------------------------------------------\n      NUI = INT(SNGL(FNUL-DFNU)) + 1\n      NUI = MAX0(NUI,0)\n      CALL ZBUNI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, NUI, NLAST, FNUL,\n     * TOL, ELIM, ALIM)\n      IF (NW.LT.0) GO TO 130\n      NZ = NZ + NW\n      IF (NLAST.EQ.0) GO TO 120\n      NN = NLAST\n      GO TO 60\n  120 CONTINUE\n      RETURN\n  130 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbiry.f",
    "content": "      SUBROUTINE ZBIRY(ZR, ZI, ID, KODE, BIR, BII, IERR)\nC***BEGIN PROLOGUE  ZBIRY\nC***DATE WRITTEN   830501   (YYMMDD)\nC***REVISION DATE  890801   (YYMMDD)\nC***CATEGORY NO.  B5K\nC***KEYWORDS  AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD\nC***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES\nC***PURPOSE  TO COMPUTE AIRY FUNCTIONS BI(Z) AND DBI(Z) FOR COMPLEX Z\nC***DESCRIPTION\nC\nC                      ***A DOUBLE PRECISION ROUTINE***\nC         ON KODE=1, CBIRY COMPUTES THE COMPLEX AIRY FUNCTION BI(Z) OR\nC         ITS DERIVATIVE DBI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON\nC         KODE=2, A SCALING OPTION CEXP(-AXZTA)*BI(Z) OR CEXP(-AXZTA)*\nC         DBI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL BEHAVIOR IN\nC         BOTH THE LEFT AND RIGHT HALF PLANES WHERE\nC         ZTA=(2/3)*Z*CSQRT(Z)=CMPLX(XZTA,YZTA) AND AXZTA=ABS(XZTA).\nC         DEFINTIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF\nC         MATHEMATICAL FUNCTIONS (REF. 1).\nC\nC         INPUT      ZR,ZI ARE DOUBLE PRECISION\nC           ZR,ZI  - Z=CMPLX(ZR,ZI)\nC           ID     - ORDER OF DERIVATIVE, ID=0 OR ID=1\nC           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION\nC                    KODE= 1  RETURNS\nC                             BI=BI(Z)                 ON ID=0 OR\nC                             BI=DBI(Z)/DZ             ON ID=1\nC                        = 2  RETURNS\nC                             BI=CEXP(-AXZTA)*BI(Z)     ON ID=0 OR\nC                             BI=CEXP(-AXZTA)*DBI(Z)/DZ ON ID=1 WHERE\nC                             ZTA=(2/3)*Z*CSQRT(Z)=CMPLX(XZTA,YZTA)\nC                             AND AXZTA=ABS(XZTA)\nC\nC         OUTPUT     BIR,BII ARE DOUBLE PRECISION\nC           BIR,BII- COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND\nC                    KODE\nC           IERR   - ERROR FLAG\nC                    IERR=0, NORMAL RETURN - COMPUTATION COMPLETED\nC                    IERR=1, INPUT ERROR   - NO COMPUTATION\nC                    IERR=2, OVERFLOW      - NO COMPUTATION, REAL(Z)\nC                            TOO LARGE ON KODE=1\nC                    IERR=3, CABS(Z) LARGE      - COMPUTATION COMPLETED\nC                            LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION\nC                            PRODUCE LESS THAN HALF OF MACHINE ACCURACY\nC                    IERR=4, CABS(Z) TOO LARGE  - NO COMPUTATION\nC                            COMPLETE LOSS OF ACCURACY BY ARGUMENT\nC                            REDUCTION\nC                    IERR=5, ERROR              - NO COMPUTATION,\nC                            ALGORITHM TERMINATION CONDITION NOT MET\nC\nC***LONG DESCRIPTION\nC\nC         BI AND DBI ARE COMPUTED FOR CABS(Z).GT.1.0 FROM THE I BESSEL\nC         FUNCTIONS BY\nC\nC                BI(Z)=C*SQRT(Z)*( I(-1/3,ZTA) + I(1/3,ZTA) )\nC               DBI(Z)=C *  Z  * ( I(-2/3,ZTA) + I(2/3,ZTA) )\nC                               C=1.0/SQRT(3.0)\nC                             ZTA=(2/3)*Z**(3/2)\nC\nC         WITH THE POWER SERIES FOR CABS(Z).LE.1.0.\nC\nC         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-\nC         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES\nC         OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF\nC         THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR),\nC         THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR\nC         FLAG IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS\nC         DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION.\nC         ALSO, IF THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN\nC         ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT\nC         FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE\nC         LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA\nC         MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2,\nC         AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE\nC         PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE\nC         PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT-\nC         ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG-\nC         NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN\nC         DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN\nC         EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES,\nC         NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE\nC         PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER\nC         MACHINES.\nC\nC         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX\nC         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT\nC         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-\nC         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE\nC         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),\nC         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF\nC         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY\nC         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN\nC         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY\nC         SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER\nC         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,\nC         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS\nC         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER\nC         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY\nC         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER\nC         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE\nC         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,\nC         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,\nC         OR -PI/2+P.\nC\nC***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ\nC                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF\nC                 COMMERCE, 1955.\nC\nC               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT\nC                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983\nC\nC               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-\nC                 1018, MAY, 1985\nC\nC               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX\nC                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.\nC                 MATH. SOFTWARE, 1986\nC\nC***ROUTINES CALLED  ZBINU,XZABS,ZDIV,XZSQRT,D1MACH,I1MACH\nC***END PROLOGUE  ZBIRY\nC     COMPLEX BI,CONE,CSQ,CY,S1,S2,TRM1,TRM2,Z,ZTA,Z3\n      DOUBLE PRECISION AA, AD, AK, ALIM, ATRM, AZ, AZ3, BB, BII, BIR,\n     * BK, CC, CK, COEF, CONEI, CONER, CSQI, CSQR, CYI, CYR, C1, C2,\n     * DIG, DK, D1, D2, EAA, ELIM, FID, FMR, FNU, FNUL, PI, RL, R1M5,\n     * SFAC, STI, STR, S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I,\n     * TRM2R, TTH, ZI, ZR, ZTAI, ZTAR, Z3I, Z3R, D1MACH, XZABS\n      INTEGER ID, IERR, K, KODE, K1, K2, NZ, I1MACH\n      DIMENSION CYR(2), CYI(2)\n      DATA TTH, C1, C2, COEF, PI /6.66666666666666667D-01,\n     * 6.14926627446000736D-01,4.48288357353826359D-01,\n     * 5.77350269189625765D-01,3.14159265358979324D+00/\n      DATA CONER, CONEI /1.0D0,0.0D0/\nC***FIRST EXECUTABLE STATEMENT  ZBIRY\n      IERR = 0\n      NZ=0\n      IF (ID.LT.0 .OR. ID.GT.1) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (IERR.NE.0) RETURN\n      AZ = XZABS(ZR,ZI)\n      TOL = DMAX1(D1MACH(4),1.0D-18)\n      FID = DBLE(FLOAT(ID))\n      IF (AZ.GT.1.0E0) GO TO 70\nC-----------------------------------------------------------------------\nC     POWER SERIES FOR CABS(Z).LE.1.\nC-----------------------------------------------------------------------\n      S1R = CONER\n      S1I = CONEI\n      S2R = CONER\n      S2I = CONEI\n      IF (AZ.LT.TOL) GO TO 130\n      AA = AZ*AZ\n      IF (AA.LT.TOL/AZ) GO TO 40\n      TRM1R = CONER\n      TRM1I = CONEI\n      TRM2R = CONER\n      TRM2I = CONEI\n      ATRM = 1.0D0\n      STR = ZR*ZR - ZI*ZI\n      STI = ZR*ZI + ZI*ZR\n      Z3R = STR*ZR - STI*ZI\n      Z3I = STR*ZI + STI*ZR\n      AZ3 = AZ*AA\n      AK = 2.0D0 + FID\n      BK = 3.0D0 - FID - FID\n      CK = 4.0D0 - FID\n      DK = 3.0D0 + FID + FID\n      D1 = AK*DK\n      D2 = BK*CK\n      AD = DMIN1(D1,D2)\n      AK = 24.0D0 + 9.0D0*FID\n      BK = 30.0D0 - 9.0D0*FID\n      DO 30 K=1,25\n        STR = (TRM1R*Z3R-TRM1I*Z3I)/D1\n        TRM1I = (TRM1R*Z3I+TRM1I*Z3R)/D1\n        TRM1R = STR\n        S1R = S1R + TRM1R\n        S1I = S1I + TRM1I\n        STR = (TRM2R*Z3R-TRM2I*Z3I)/D2\n        TRM2I = (TRM2R*Z3I+TRM2I*Z3R)/D2\n        TRM2R = STR\n        S2R = S2R + TRM2R\n        S2I = S2I + TRM2I\n        ATRM = ATRM*AZ3/AD\n        D1 = D1 + AK\n        D2 = D2 + BK\n        AD = DMIN1(D1,D2)\n        IF (ATRM.LT.TOL*AD) GO TO 40\n        AK = AK + 18.0D0\n        BK = BK + 18.0D0\n   30 CONTINUE\n   40 CONTINUE\n      IF (ID.EQ.1) GO TO 50\n      BIR = C1*S1R + C2*(ZR*S2R-ZI*S2I)\n      BII = C1*S1I + C2*(ZR*S2I+ZI*S2R)\n      IF (KODE.EQ.1) RETURN\n      CALL XZSQRT(ZR, ZI, STR, STI)\n      ZTAR = TTH*(ZR*STR-ZI*STI)\n      ZTAI = TTH*(ZR*STI+ZI*STR)\n      AA = ZTAR\n      AA = -DABS(AA)\n      EAA = DEXP(AA)\n      BIR = BIR*EAA\n      BII = BII*EAA\n      RETURN\n   50 CONTINUE\n      BIR = S2R*C2\n      BII = S2I*C2\n      IF (AZ.LE.TOL) GO TO 60\n      CC = C1/(1.0D0+FID)\n      STR = S1R*ZR - S1I*ZI\n      STI = S1R*ZI + S1I*ZR\n      BIR = BIR + CC*(STR*ZR-STI*ZI)\n      BII = BII + CC*(STR*ZI+STI*ZR)\n   60 CONTINUE\n      IF (KODE.EQ.1) RETURN\n      CALL XZSQRT(ZR, ZI, STR, STI)\n      ZTAR = TTH*(ZR*STR-ZI*STI)\n      ZTAI = TTH*(ZR*STI+ZI*STR)\n      AA = ZTAR\n      AA = -DABS(AA)\n      EAA = DEXP(AA)\n      BIR = BIR*EAA\n      BII = BII*EAA\n      RETURN\nC-----------------------------------------------------------------------\nC     CASE FOR CABS(Z).GT.1.0\nC-----------------------------------------------------------------------\n   70 CONTINUE\n      FNU = (1.0D0+FID)/3.0D0\nC-----------------------------------------------------------------------\nC     SET PARAMETERS RELATED TO MACHINE CONSTANTS.\nC     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.\nC     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.\nC     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND\nC     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR\nC     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.\nC     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.\nC     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).\nC     FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU.\nC-----------------------------------------------------------------------\n      K1 = I1MACH(15)\n      K2 = I1MACH(16)\n      R1M5 = D1MACH(5)\n      K = MIN0(IABS(K1),IABS(K2))\n      ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0)\n      K1 = I1MACH(14) - 1\n      AA = R1M5*DBLE(FLOAT(K1))\n      DIG = DMIN1(AA,18.0D0)\n      AA = AA*2.303D0\n      ALIM = ELIM + DMAX1(-AA,-41.45D0)\n      RL = 1.2D0*DIG + 3.0D0\n      FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0)\nC-----------------------------------------------------------------------\nC     TEST FOR RANGE\nC-----------------------------------------------------------------------\n      AA=0.5D0/TOL\n      BB=DBLE(FLOAT(I1MACH(9)))*0.5D0\n      AA=DMIN1(AA,BB)\n      AA=AA**TTH\n      IF (AZ.GT.AA) GO TO 260\n      AA=DSQRT(AA)\n      IF (AZ.GT.AA) IERR=3\n      CALL XZSQRT(ZR, ZI, CSQR, CSQI)\n      ZTAR = TTH*(ZR*CSQR-ZI*CSQI)\n      ZTAI = TTH*(ZR*CSQI+ZI*CSQR)\nC-----------------------------------------------------------------------\nC     RE(ZTA).LE.0 WHEN RE(Z).LT.0, ESPECIALLY WHEN IM(Z) IS SMALL\nC-----------------------------------------------------------------------\n      SFAC = 1.0D0\n      AK = ZTAI\n      IF (ZR.GE.0.0D0) GO TO 80\n      BK = ZTAR\n      CK = -DABS(BK)\n      ZTAR = CK\n      ZTAI = AK\n   80 CONTINUE\n      IF (ZI.NE.0.0D0 .OR. ZR.GT.0.0D0) GO TO 90\n      ZTAR = 0.0D0\n      ZTAI = AK\n   90 CONTINUE\n      AA = ZTAR\n      IF (KODE.EQ.2) GO TO 100\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST\nC-----------------------------------------------------------------------\n      BB = DABS(AA)\n      IF (BB.LT.ALIM) GO TO 100\n      BB = BB + 0.25D0*DLOG(AZ)\n      SFAC = TOL\n      IF (BB.GT.ELIM) GO TO 190\n  100 CONTINUE\n      FMR = 0.0D0\n      IF (AA.GE.0.0D0 .AND. ZR.GT.0.0D0) GO TO 110\n      FMR = PI\n      IF (ZI.LT.0.0D0) FMR = -PI\n      ZTAR = -ZTAR\n      ZTAI = -ZTAI\n  110 CONTINUE\nC-----------------------------------------------------------------------\nC     AA=FACTOR FOR ANALYTIC CONTINUATION OF I(FNU,ZTA)\nC     KODE=2 RETURNS EXP(-ABS(XZTA))*I(FNU,ZTA) FROM CBESI\nC-----------------------------------------------------------------------\n      CALL ZBINU(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, RL, FNUL, TOL,\n     * ELIM, ALIM)\n      IF (NZ.LT.0) GO TO 200\n      AA = FMR*FNU\n      Z3R = SFAC\n      STR = DCOS(AA)\n      STI = DSIN(AA)\n      S1R = (STR*CYR(1)-STI*CYI(1))*Z3R\n      S1I = (STR*CYI(1)+STI*CYR(1))*Z3R\n      FNU = (2.0D0-FID)/3.0D0\n      CALL ZBINU(ZTAR, ZTAI, FNU, KODE, 2, CYR, CYI, NZ, RL, FNUL, TOL,\n     * ELIM, ALIM)\n      CYR(1) = CYR(1)*Z3R\n      CYI(1) = CYI(1)*Z3R\n      CYR(2) = CYR(2)*Z3R\n      CYI(2) = CYI(2)*Z3R\nC-----------------------------------------------------------------------\nC     BACKWARD RECUR ONE STEP FOR ORDERS -1/3 OR -2/3\nC-----------------------------------------------------------------------\n      CALL ZDIV(CYR(1), CYI(1), ZTAR, ZTAI, STR, STI)\n      S2R = (FNU+FNU)*STR + CYR(2)\n      S2I = (FNU+FNU)*STI + CYI(2)\n      AA = FMR*(FNU-1.0D0)\n      STR = DCOS(AA)\n      STI = DSIN(AA)\n      S1R = COEF*(S1R+S2R*STR-S2I*STI)\n      S1I = COEF*(S1I+S2R*STI+S2I*STR)\n      IF (ID.EQ.1) GO TO 120\n      STR = CSQR*S1R - CSQI*S1I\n      S1I = CSQR*S1I + CSQI*S1R\n      S1R = STR\n      BIR = S1R/SFAC\n      BII = S1I/SFAC\n      RETURN\n  120 CONTINUE\n      STR = ZR*S1R - ZI*S1I\n      S1I = ZR*S1I + ZI*S1R\n      S1R = STR\n      BIR = S1R/SFAC\n      BII = S1I/SFAC\n      RETURN\n  130 CONTINUE\n      AA = C1*(1.0D0-FID) + FID*C2\n      BIR = AA\n      BII = 0.0D0\n      RETURN\n  190 CONTINUE\n      IERR=2\n      NZ=0\n      RETURN\n  200 CONTINUE\n      IF(NZ.EQ.(-1)) GO TO 190\n      NZ=0\n      IERR=5\n      RETURN\n  260 CONTINUE\n      IERR=4\n      NZ=0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbknu.f",
    "content": "      SUBROUTINE ZBKNU(ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  ZBKNU\nC***REFER TO  ZBESI,ZBESK,ZAIRY,ZBESH\nC\nC     ZBKNU COMPUTES THE K BESSEL FUNCTION IN THE RIGHT HALF Z PLANE.\nC\nC***ROUTINES CALLED  DGAMLN,I1MACH,D1MACH,ZKSCL,ZSHCH,ZUCHK,XZABS,ZDIV,\nC                    XZEXP,XZLOG,ZMLT,XZSQRT\nC***END PROLOGUE  ZBKNU\nC\n      DOUBLE PRECISION AA, AK, ALIM, ASCLE, A1, A2, BB, BK, BRY, CAZ,\n     * CBI, CBR, CC, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER,\n     * CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CSRR, CSSR, CTWOR,\n     * CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ELIM, ETEST, FC, FHS,\n     * FI, FK, FKS, FMUI, FMUR, FNU, FPI, FR, G1, G2, HPI, PI, PR, PTI,\n     * PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI,\n     * RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM,\n     * TOL, TTH, T1, T2, YI, YR, ZI, ZR, DGAMLN, D1MACH, XZABS, ELM,\n     * CELMR, ZDR, ZDI, AS, ALAS, HELIM, CYR, CYI\n      INTEGER I, IFLAG, INU, K, KFLAG, KK, KMAX, KODE, KODED, N, NZ,\n     * IDUM, I1MACH, J, IC, INUB, NW\n      DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2),\n     * CYI(2)\nC     COMPLEX Z,Y,A,B,RZ,SMU,FU,FMU,F,FLRZ,CZ,S1,S2,CSH,CCH\nC     COMPLEX CK,P,Q,COEF,P1,P2,CBK,PT,CZERO,CONE,CTWO,ST,EZ,CS,DK\nC\n      DATA KMAX / 30 /\n      DATA CZEROR,CZEROI,CONER,CONEI,CTWOR,R1/\n     1  0.0D0 , 0.0D0 , 1.0D0 , 0.0D0 , 2.0D0 , 2.0D0 /\n      DATA DPI, RTHPI, SPI ,HPI, FPI, TTH /\n     1     3.14159265358979324D0,       1.25331413731550025D0,\n     2     1.90985931710274403D0,       1.57079632679489662D0,\n     3     1.89769999331517738D0,       6.66666666666666666D-01/\n      DATA CC(1), CC(2), CC(3), CC(4), CC(5), CC(6), CC(7), CC(8)/\n     1     5.77215664901532861D-01,    -4.20026350340952355D-02,\n     2    -4.21977345555443367D-02,     7.21894324666309954D-03,\n     3    -2.15241674114950973D-04,    -2.01348547807882387D-05,\n     4     1.13302723198169588D-06,     6.11609510448141582D-09/\nC\n      CAZ = XZABS(ZR,ZI)\n      CSCLR = 1.0D0/TOL\n      CRSCR = TOL\n      CSSR(1) = CSCLR\n      CSSR(2) = 1.0D0\n      CSSR(3) = CRSCR\n      CSRR(1) = CRSCR\n      CSRR(2) = 1.0D0\n      CSRR(3) = CSCLR\n      BRY(1) = 1.0D+3*D1MACH(1)/TOL\n      BRY(2) = 1.0D0/BRY(1)\n      BRY(3) = D1MACH(2)\n      NZ = 0\n      IFLAG = 0\n      KODED = KODE\n      RCAZ = 1.0D0/CAZ\n      STR = ZR*RCAZ\n      STI = -ZI*RCAZ\n      RZR = (STR+STR)*RCAZ\n      RZI = (STI+STI)*RCAZ\n      INU = INT(SNGL(FNU+0.5D0))\n      DNU = FNU - DBLE(FLOAT(INU))\n      IF (DABS(DNU).EQ.0.5D0) GO TO 110\n      DNU2 = 0.0D0\n      IF (DABS(DNU).GT.TOL) DNU2 = DNU*DNU\n      IF (CAZ.GT.R1) GO TO 110\nC-----------------------------------------------------------------------\nC     SERIES FOR CABS(Z).LE.R1\nC-----------------------------------------------------------------------\n      FC = 1.0D0\n      CALL XZLOG(RZR, RZI, SMUR, SMUI, IDUM)\n      FMUR = SMUR*DNU\n      FMUI = SMUI*DNU\n      CALL ZSHCH(FMUR, FMUI, CSHR, CSHI, CCHR, CCHI)\n      IF (DNU.EQ.0.0D0) GO TO 10\n      FC = DNU*DPI\n      FC = FC/DSIN(FC)\n      SMUR = CSHR/DNU\n      SMUI = CSHI/DNU\n   10 CONTINUE\n      A2 = 1.0D0 + DNU\nC-----------------------------------------------------------------------\nC     GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU)\nC-----------------------------------------------------------------------\n      T2 = DEXP(-DGAMLN(A2,IDUM))\n      T1 = 1.0D0/(T2*FC)\n      IF (DABS(DNU).GT.0.1D0) GO TO 40\nC-----------------------------------------------------------------------\nC     SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU)\nC-----------------------------------------------------------------------\n      AK = 1.0D0\n      S = CC(1)\n      DO 20 K=2,8\n        AK = AK*DNU2\n        TM = CC(K)*AK\n        S = S + TM\n        IF (DABS(TM).LT.TOL) GO TO 30\n   20 CONTINUE\n   30 G1 = -S\n      GO TO 50\n   40 CONTINUE\n      G1 = (T1-T2)/(DNU+DNU)\n   50 CONTINUE\n      G2 = (T1+T2)*0.5D0\n      FR = FC*(CCHR*G1+SMUR*G2)\n      FI = FC*(CCHI*G1+SMUI*G2)\n      CALL XZEXP(FMUR, FMUI, STR, STI)\n      PR = 0.5D0*STR/T2\n      PI = 0.5D0*STI/T2\n      CALL ZDIV(0.5D0, 0.0D0, STR, STI, PTR, PTI)\n      QR = PTR/T1\n      QI = PTI/T1\n      S1R = FR\n      S1I = FI\n      S2R = PR\n      S2I = PI\n      AK = 1.0D0\n      A1 = 1.0D0\n      CKR = CONER\n      CKI = CONEI\n      BK = 1.0D0 - DNU2\n      IF (INU.GT.0 .OR. N.GT.1) GO TO 80\nC-----------------------------------------------------------------------\nC     GENERATE K(FNU,Z), 0.0D0 .LE. FNU .LT. 0.5D0 AND N=1\nC-----------------------------------------------------------------------\n      IF (CAZ.LT.TOL) GO TO 70\n      CALL ZMLT(ZR, ZI, ZR, ZI, CZR, CZI)\n      CZR = 0.25D0*CZR\n      CZI = 0.25D0*CZI\n      T1 = 0.25D0*CAZ*CAZ\n   60 CONTINUE\n      FR = (FR*AK+PR+QR)/BK\n      FI = (FI*AK+PI+QI)/BK\n      STR = 1.0D0/(AK-DNU)\n      PR = PR*STR\n      PI = PI*STR\n      STR = 1.0D0/(AK+DNU)\n      QR = QR*STR\n      QI = QI*STR\n      STR = CKR*CZR - CKI*CZI\n      RAK = 1.0D0/AK\n      CKI = (CKR*CZI+CKI*CZR)*RAK\n      CKR = STR*RAK\n      S1R = CKR*FR - CKI*FI + S1R\n      S1I = CKR*FI + CKI*FR + S1I\n      A1 = A1*T1*RAK\n      BK = BK + AK + AK + 1.0D0\n      AK = AK + 1.0D0\n      IF (A1.GT.TOL) GO TO 60\n   70 CONTINUE\n      YR(1) = S1R\n      YI(1) = S1I\n      IF (KODED.EQ.1) RETURN\n      CALL XZEXP(ZR, ZI, STR, STI)\n      CALL ZMLT(S1R, S1I, STR, STI, YR(1), YI(1))\n      RETURN\nC-----------------------------------------------------------------------\nC     GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE\nC-----------------------------------------------------------------------\n   80 CONTINUE\n      IF (CAZ.LT.TOL) GO TO 100\n      CALL ZMLT(ZR, ZI, ZR, ZI, CZR, CZI)\n      CZR = 0.25D0*CZR\n      CZI = 0.25D0*CZI\n      T1 = 0.25D0*CAZ*CAZ\n   90 CONTINUE\n      FR = (FR*AK+PR+QR)/BK\n      FI = (FI*AK+PI+QI)/BK\n      STR = 1.0D0/(AK-DNU)\n      PR = PR*STR\n      PI = PI*STR\n      STR = 1.0D0/(AK+DNU)\n      QR = QR*STR\n      QI = QI*STR\n      STR = CKR*CZR - CKI*CZI\n      RAK = 1.0D0/AK\n      CKI = (CKR*CZI+CKI*CZR)*RAK\n      CKR = STR*RAK\n      S1R = CKR*FR - CKI*FI + S1R\n      S1I = CKR*FI + CKI*FR + S1I\n      STR = PR - FR*AK\n      STI = PI - FI*AK\n      S2R = CKR*STR - CKI*STI + S2R\n      S2I = CKR*STI + CKI*STR + S2I\n      A1 = A1*T1*RAK\n      BK = BK + AK + AK + 1.0D0\n      AK = AK + 1.0D0\n      IF (A1.GT.TOL) GO TO 90\n  100 CONTINUE\n      KFLAG = 2\n      A1 = FNU + 1.0D0\n      AK = A1*DABS(SMUR)\n      IF (AK.GT.ALIM) KFLAG = 3\n      STR = CSSR(KFLAG)\n      P2R = S2R*STR\n      P2I = S2I*STR\n      CALL ZMLT(P2R, P2I, RZR, RZI, S2R, S2I)\n      S1R = S1R*STR\n      S1I = S1I*STR\n      IF (KODED.EQ.1) GO TO 210\n      CALL XZEXP(ZR, ZI, FR, FI)\n      CALL ZMLT(S1R, S1I, FR, FI, S1R, S1I)\n      CALL ZMLT(S2R, S2I, FR, FI, S2R, S2I)\n      GO TO 210\nC-----------------------------------------------------------------------\nC     IFLAG=0 MEANS NO UNDERFLOW OCCURRED\nC     IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH\nC     KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD\nC     RECURSION\nC-----------------------------------------------------------------------\n  110 CONTINUE\n      CALL XZSQRT(ZR, ZI, STR, STI)\n      CALL ZDIV(RTHPI, CZEROI, STR, STI, COEFR, COEFI)\n      KFLAG = 2\n      IF (KODED.EQ.2) GO TO 120\n      IF (ZR.GT.ALIM) GO TO 290\nC     BLANK LINE\n      STR = DEXP(-ZR)*CSSR(KFLAG)\n      STI = -STR*DSIN(ZI)\n      STR = STR*DCOS(ZI)\n      CALL ZMLT(COEFR, COEFI, STR, STI, COEFR, COEFI)\n  120 CONTINUE\n      IF (DABS(DNU).EQ.0.5D0) GO TO 300\nC-----------------------------------------------------------------------\nC     MILLER ALGORITHM FOR CABS(Z).GT.R1\nC-----------------------------------------------------------------------\n      AK = DCOS(DPI*DNU)\n      AK = DABS(AK)\n      IF (AK.EQ.CZEROR) GO TO 300\n      FHS = DABS(0.25D0-DNU2)\n      IF (FHS.EQ.CZEROR) GO TO 300\nC-----------------------------------------------------------------------\nC     COMPUTE R2=F(E). IF CABS(Z).GE.R2, USE FORWARD RECURRENCE TO\nC     DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON\nC     12.LE.E.LE.60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))=\nC     TOL WHERE B IS THE BASE OF THE ARITHMETIC.\nC-----------------------------------------------------------------------\n      T1 = DBLE(FLOAT(I1MACH(14)-1))\n      T1 = T1*D1MACH(5)*3.321928094D0\n      T1 = DMAX1(T1,12.0D0)\n      T1 = DMIN1(T1,60.0D0)\n      T2 = TTH*T1 - 6.0D0\n      IF (ZR.NE.0.0D0) GO TO 130\n      T1 = HPI\n      GO TO 140\n  130 CONTINUE\n      T1 = DATAN(ZI/ZR)\n      T1 = DABS(T1)\n  140 CONTINUE\n      IF (T2.GT.CAZ) GO TO 170\nC-----------------------------------------------------------------------\nC     FORWARD RECURRENCE LOOP WHEN CABS(Z).GE.R2\nC-----------------------------------------------------------------------\n      ETEST = AK/(DPI*CAZ*TOL)\n      FK = CONER\n      IF (ETEST.LT.CONER) GO TO 180\n      FKS = CTWOR\n      CKR = CAZ + CAZ + CTWOR\n      P1R = CZEROR\n      P2R = CONER\n      DO 150 I=1,KMAX\n        AK = FHS/FKS\n        CBR = CKR/(FK+CONER)\n        PTR = P2R\n        P2R = CBR*P2R - P1R*AK\n        P1R = PTR\n        CKR = CKR + CTWOR\n        FKS = FKS + FK + FK + CTWOR\n        FHS = FHS + FK + FK\n        FK = FK + CONER\n        STR = DABS(P2R)*FK\n        IF (ETEST.LT.STR) GO TO 160\n  150 CONTINUE\n      GO TO 310\n  160 CONTINUE\n      FK = FK + SPI*T1*DSQRT(T2/CAZ)\n      FHS = DABS(0.25D0-DNU2)\n      GO TO 180\n  170 CONTINUE\nC-----------------------------------------------------------------------\nC     COMPUTE BACKWARD INDEX K FOR CABS(Z).LT.R2\nC-----------------------------------------------------------------------\n      A2 = DSQRT(CAZ)\n      AK = FPI*AK/(TOL*DSQRT(A2))\n      AA = 3.0D0*T1/(1.0D0+CAZ)\n      BB = 14.7D0*T1/(28.0D0+CAZ)\n      AK = (DLOG(AK)+CAZ*DCOS(AA)/(1.0D0+0.008D0*CAZ))/DCOS(BB)\n      FK = 0.12125D0*AK*AK/CAZ + 1.5D0\n  180 CONTINUE\nC-----------------------------------------------------------------------\nC     BACKWARD RECURRENCE LOOP FOR MILLER ALGORITHM\nC-----------------------------------------------------------------------\n      K = INT(SNGL(FK))\n      FK = DBLE(FLOAT(K))\n      FKS = FK*FK\n      P1R = CZEROR\n      P1I = CZEROI\n      P2R = TOL\n      P2I = CZEROI\n      CSR = P2R\n      CSI = P2I\n      DO 190 I=1,K\n        A1 = FKS - FK\n        AK = (FKS+FK)/(A1+FHS)\n        RAK = 2.0D0/(FK+CONER)\n        CBR = (FK+ZR)*RAK\n        CBI = ZI*RAK\n        PTR = P2R\n        PTI = P2I\n        P2R = (PTR*CBR-PTI*CBI-P1R)*AK\n        P2I = (PTI*CBR+PTR*CBI-P1I)*AK\n        P1R = PTR\n        P1I = PTI\n        CSR = CSR + P2R\n        CSI = CSI + P2I\n        FKS = A1 - FK + CONER\n        FK = FK - CONER\n  190 CONTINUE\nC-----------------------------------------------------------------------\nC     COMPUTE (P2/CS)=(P2/CABS(CS))*(CONJG(CS)/CABS(CS)) FOR BETTER\nC     SCALING\nC-----------------------------------------------------------------------\n      TM = XZABS(CSR,CSI)\n      PTR = 1.0D0/TM\n      S1R = P2R*PTR\n      S1I = P2I*PTR\n      CSR = CSR*PTR\n      CSI = -CSI*PTR\n      CALL ZMLT(COEFR, COEFI, S1R, S1I, STR, STI)\n      CALL ZMLT(STR, STI, CSR, CSI, S1R, S1I)\n      IF (INU.GT.0 .OR. N.GT.1) GO TO 200\n      ZDR = ZR\n      ZDI = ZI\n      IF(IFLAG.EQ.1) GO TO 270\n      GO TO 240\n  200 CONTINUE\nC-----------------------------------------------------------------------\nC     COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING\nC-----------------------------------------------------------------------\n      TM = XZABS(P2R,P2I)\n      PTR = 1.0D0/TM\n      P1R = P1R*PTR\n      P1I = P1I*PTR\n      P2R = P2R*PTR\n      P2I = -P2I*PTR\n      CALL ZMLT(P1R, P1I, P2R, P2I, PTR, PTI)\n      STR = DNU + 0.5D0 - PTR\n      STI = -PTI\n      CALL ZDIV(STR, STI, ZR, ZI, STR, STI)\n      STR = STR + 1.0D0\n      CALL ZMLT(STR, STI, S1R, S1I, S2R, S2I)\nC-----------------------------------------------------------------------\nC     FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH\nC     SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3\nC-----------------------------------------------------------------------\n  210 CONTINUE\n      STR = DNU + 1.0D0\n      CKR = STR*RZR\n      CKI = STR*RZI\n      IF (N.EQ.1) INU = INU - 1\n      IF (INU.GT.0) GO TO 220\n      IF (N.GT.1) GO TO 215\n      S1R = S2R\n      S1I = S2I\n  215 CONTINUE\n      ZDR = ZR\n      ZDI = ZI\n      IF(IFLAG.EQ.1) GO TO 270\n      GO TO 240\n  220 CONTINUE\n      INUB = 1\n      IF(IFLAG.EQ.1) GO TO 261\n  225 CONTINUE\n      P1R = CSRR(KFLAG)\n      ASCLE = BRY(KFLAG)\n      DO 230 I=INUB,INU\n        STR = S2R\n        STI = S2I\n        S2R = CKR*STR - CKI*STI + S1R\n        S2I = CKR*STI + CKI*STR + S1I\n        S1R = STR\n        S1I = STI\n        CKR = CKR + RZR\n        CKI = CKI + RZI\n        IF (KFLAG.GE.3) GO TO 230\n        P2R = S2R*P1R\n        P2I = S2I*P1R\n        STR = DABS(P2R)\n        STI = DABS(P2I)\n        P2M = DMAX1(STR,STI)\n        IF (P2M.LE.ASCLE) GO TO 230\n        KFLAG = KFLAG + 1\n        ASCLE = BRY(KFLAG)\n        S1R = S1R*P1R\n        S1I = S1I*P1R\n        S2R = P2R\n        S2I = P2I\n        STR = CSSR(KFLAG)\n        S1R = S1R*STR\n        S1I = S1I*STR\n        S2R = S2R*STR\n        S2I = S2I*STR\n        P1R = CSRR(KFLAG)\n  230 CONTINUE\n      IF (N.NE.1) GO TO 240\n      S1R = S2R\n      S1I = S2I\n  240 CONTINUE\n      STR = CSRR(KFLAG)\n      YR(1) = S1R*STR\n      YI(1) = S1I*STR\n      IF (N.EQ.1) RETURN\n      YR(2) = S2R*STR\n      YI(2) = S2I*STR\n      IF (N.EQ.2) RETURN\n      KK = 2\n  250 CONTINUE\n      KK = KK + 1\n      IF (KK.GT.N) RETURN\n      P1R = CSRR(KFLAG)\n      ASCLE = BRY(KFLAG)\n      DO 260 I=KK,N\n        P2R = S2R\n        P2I = S2I\n        S2R = CKR*P2R - CKI*P2I + S1R\n        S2I = CKI*P2R + CKR*P2I + S1I\n        S1R = P2R\n        S1I = P2I\n        CKR = CKR + RZR\n        CKI = CKI + RZI\n        P2R = S2R*P1R\n        P2I = S2I*P1R\n        YR(I) = P2R\n        YI(I) = P2I\n        IF (KFLAG.GE.3) GO TO 260\n        STR = DABS(P2R)\n        STI = DABS(P2I)\n        P2M = DMAX1(STR,STI)\n        IF (P2M.LE.ASCLE) GO TO 260\n        KFLAG = KFLAG + 1\n        ASCLE = BRY(KFLAG)\n        S1R = S1R*P1R\n        S1I = S1I*P1R\n        S2R = P2R\n        S2I = P2I\n        STR = CSSR(KFLAG)\n        S1R = S1R*STR\n        S1I = S1I*STR\n        S2R = S2R*STR\n        S2I = S2I*STR\n        P1R = CSRR(KFLAG)\n  260 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW\nC-----------------------------------------------------------------------\n  261 CONTINUE\n      HELIM = 0.5D0*ELIM\n      ELM = DEXP(-ELIM)\n      CELMR = ELM\n      ASCLE = BRY(1)\n      ZDR = ZR\n      ZDI = ZI\n      IC = -1\n      J = 2\n      DO 262 I=1,INU\n        STR = S2R\n        STI = S2I\n        S2R = STR*CKR-STI*CKI+S1R\n        S2I = STI*CKR+STR*CKI+S1I\n        S1R = STR\n        S1I = STI\n        CKR = CKR+RZR\n        CKI = CKI+RZI\n        AS = XZABS(S2R,S2I)\n        ALAS = DLOG(AS)\n        P2R = -ZDR+ALAS\n        IF(P2R.LT.(-ELIM)) GO TO 263\n        CALL XZLOG(S2R,S2I,STR,STI,IDUM)\n        P2R = -ZDR+STR\n        P2I = -ZDI+STI\n        P2M = DEXP(P2R)/TOL\n        P1R = P2M*DCOS(P2I)\n        P1I = P2M*DSIN(P2I)\n        CALL ZUCHK(P1R,P1I,NW,ASCLE,TOL)\n        IF(NW.NE.0) GO TO 263\n        J = 3 - J\n        CYR(J) = P1R\n        CYI(J) = P1I\n        IF(IC.EQ.(I-1)) GO TO 264\n        IC = I\n        GO TO 262\n  263   CONTINUE\n        IF(ALAS.LT.HELIM) GO TO 262\n        ZDR = ZDR-ELIM\n        S1R = S1R*CELMR\n        S1I = S1I*CELMR\n        S2R = S2R*CELMR\n        S2I = S2I*CELMR\n  262 CONTINUE\n      IF(N.NE.1) GO TO 270\n      S1R = S2R\n      S1I = S2I\n      GO TO 270\n  264 CONTINUE\n      KFLAG = 1\n      INUB = I+1\n      S2R = CYR(J)\n      S2I = CYI(J)\n      J = 3 - J\n      S1R = CYR(J)\n      S1I = CYI(J)\n      IF(INUB.LE.INU) GO TO 225\n      IF(N.NE.1) GO TO 240\n      S1R = S2R\n      S1I = S2I\n      GO TO 240\n  270 CONTINUE\n      YR(1) = S1R\n      YI(1) = S1I\n      IF(N.EQ.1) GO TO 280\n      YR(2) = S2R\n      YI(2) = S2I\n  280 CONTINUE\n      ASCLE = BRY(1)\n      CALL ZKSCL(ZDR,ZDI,FNU,N,YR,YI,NZ,RZR,RZI,ASCLE,TOL,ELIM)\n      INU = N - NZ\n      IF (INU.LE.0) RETURN\n      KK = NZ + 1\n      S1R = YR(KK)\n      S1I = YI(KK)\n      YR(KK) = S1R*CSRR(1)\n      YI(KK) = S1I*CSRR(1)\n      IF (INU.EQ.1) RETURN\n      KK = NZ + 2\n      S2R = YR(KK)\n      S2I = YI(KK)\n      YR(KK) = S2R*CSRR(1)\n      YI(KK) = S2I*CSRR(1)\n      IF (INU.EQ.2) RETURN\n      T2 = FNU + DBLE(FLOAT(KK-1))\n      CKR = T2*RZR\n      CKI = T2*RZI\n      KFLAG = 1\n      GO TO 250\n  290 CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE BY DEXP(Z), IFLAG = 1 CASES\nC-----------------------------------------------------------------------\n      KODED = 2\n      IFLAG = 1\n      KFLAG = 2\n      GO TO 120\nC-----------------------------------------------------------------------\nC     FNU=HALF ODD INTEGER CASE, DNU=-0.5\nC-----------------------------------------------------------------------\n  300 CONTINUE\n      S1R = COEFR\n      S1I = COEFI\n      S2R = COEFR\n      S2I = COEFI\n      GO TO 210\nC\nC\n  310 CONTINUE\n      NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbuni.f",
    "content": "      SUBROUTINE ZBUNI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, NUI, NLAST,\n     * FNUL, TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  ZBUNI\nC***REFER TO  ZBESI,ZBESK\nC\nC     ZBUNI COMPUTES THE I BESSEL FUNCTION FOR LARGE CABS(Z).GT.\nC     FNUL AND FNU+N-1.LT.FNUL. THE ORDER IS INCREASED FROM\nC     FNU+N-1 GREATER THAN FNUL BY ADDING NUI AND COMPUTING\nC     ACCORDING TO THE UNIFORM ASYMPTOTIC EXPANSION FOR I(FNU,Z)\nC     ON IFORM=1 AND THE EXPANSION FOR J(FNU,Z) ON IFORM=2\nC\nC***ROUTINES CALLED  ZUNI1,ZUNI2,XZABS,D1MACH\nC***END PROLOGUE  ZBUNI\nC     COMPLEX CSCL,CSCR,CY,RZ,ST,S1,S2,Y,Z\n      DOUBLE PRECISION ALIM, AX, AY, CSCLR, CSCRR, CYI, CYR, DFNU,\n     * ELIM, FNU, FNUI, FNUL, GNU, RAZ, RZI, RZR, STI, STR, S1I, S1R,\n     * S2I, S2R, TOL, YI, YR, ZI, ZR, XZABS, ASCLE, BRY, C1R, C1I, C1M,\n     * D1MACH\n      INTEGER I, IFLAG, IFORM, K, KODE, N, NL, NLAST, NUI, NW, NZ\n      DIMENSION YR(N), YI(N), CYR(2), CYI(2), BRY(3)\n      NZ = 0\n      AX = DABS(ZR)*1.7321D0\n      AY = DABS(ZI)\n      IFORM = 1\n      IF (AY.GT.AX) IFORM = 2\n      IF (NUI.EQ.0) GO TO 60\n      FNUI = DBLE(FLOAT(NUI))\n      DFNU = FNU + DBLE(FLOAT(N-1))\n      GNU = DFNU + FNUI\n      IF (IFORM.EQ.2) GO TO 10\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR I(FNU,Z) FOR LARGE FNU APPLIED IN\nC     -PI/3.LE.ARG(Z).LE.PI/3\nC-----------------------------------------------------------------------\n      CALL ZUNI1(ZR, ZI, GNU, KODE, 2, CYR, CYI, NW, NLAST, FNUL, TOL,\n     * ELIM, ALIM)\n      GO TO 20\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR J(FNU,Z*EXP(M*HPI)) FOR LARGE FNU\nC     APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I\nC     AND HPI=PI/2\nC-----------------------------------------------------------------------\n      CALL ZUNI2(ZR, ZI, GNU, KODE, 2, CYR, CYI, NW, NLAST, FNUL, TOL,\n     * ELIM, ALIM)\n   20 CONTINUE\n      IF (NW.LT.0) GO TO 50\n      IF (NW.NE.0) GO TO 90\n      STR = XZABS(CYR(1),CYI(1))\nC----------------------------------------------------------------------\nC     SCALE BACKWARD RECURRENCE, BRY(3) IS DEFINED BUT NEVER USED\nC----------------------------------------------------------------------\n      BRY(1)=1.0D+3*D1MACH(1)/TOL\n      BRY(2) = 1.0D0/BRY(1)\n      BRY(3) = BRY(2)\n      IFLAG = 2\n      ASCLE = BRY(2)\n      CSCLR = 1.0D0\n      IF (STR.GT.BRY(1)) GO TO 21\n      IFLAG = 1\n      ASCLE = BRY(1)\n      CSCLR = 1.0D0/TOL\n      GO TO 25\n   21 CONTINUE\n      IF (STR.LT.BRY(2)) GO TO 25\n      IFLAG = 3\n      ASCLE=BRY(3)\n      CSCLR = TOL\n   25 CONTINUE\n      CSCRR = 1.0D0/CSCLR\n      S1R = CYR(2)*CSCLR\n      S1I = CYI(2)*CSCLR\n      S2R = CYR(1)*CSCLR\n      S2I = CYI(1)*CSCLR\n      RAZ = 1.0D0/XZABS(ZR,ZI)\n      STR = ZR*RAZ\n      STI = -ZI*RAZ\n      RZR = (STR+STR)*RAZ\n      RZI = (STI+STI)*RAZ\n      DO 30 I=1,NUI\n        STR = S2R\n        STI = S2I\n        S2R = (DFNU+FNUI)*(RZR*STR-RZI*STI) + S1R\n        S2I = (DFNU+FNUI)*(RZR*STI+RZI*STR) + S1I\n        S1R = STR\n        S1I = STI\n        FNUI = FNUI - 1.0D0\n        IF (IFLAG.GE.3) GO TO 30\n        STR = S2R*CSCRR\n        STI = S2I*CSCRR\n        C1R = DABS(STR)\n        C1I = DABS(STI)\n        C1M = DMAX1(C1R,C1I)\n        IF (C1M.LE.ASCLE) GO TO 30\n        IFLAG = IFLAG+1\n        ASCLE = BRY(IFLAG)\n        S1R = S1R*CSCRR\n        S1I = S1I*CSCRR\n        S2R = STR\n        S2I = STI\n        CSCLR = CSCLR*TOL\n        CSCRR = 1.0D0/CSCLR\n        S1R = S1R*CSCLR\n        S1I = S1I*CSCLR\n        S2R = S2R*CSCLR\n        S2I = S2I*CSCLR\n   30 CONTINUE\n      YR(N) = S2R*CSCRR\n      YI(N) = S2I*CSCRR\n      IF (N.EQ.1) RETURN\n      NL = N - 1\n      FNUI = DBLE(FLOAT(NL))\n      K = NL\n      DO 40 I=1,NL\n        STR = S2R\n        STI = S2I\n        S2R = (FNU+FNUI)*(RZR*STR-RZI*STI) + S1R\n        S2I = (FNU+FNUI)*(RZR*STI+RZI*STR) + S1I\n        S1R = STR\n        S1I = STI\n        STR = S2R*CSCRR\n        STI = S2I*CSCRR\n        YR(K) = STR\n        YI(K) = STI\n        FNUI = FNUI - 1.0D0\n        K = K - 1\n        IF (IFLAG.GE.3) GO TO 40\n        C1R = DABS(STR)\n        C1I = DABS(STI)\n        C1M = DMAX1(C1R,C1I)\n        IF (C1M.LE.ASCLE) GO TO 40\n        IFLAG = IFLAG+1\n        ASCLE = BRY(IFLAG)\n        S1R = S1R*CSCRR\n        S1I = S1I*CSCRR\n        S2R = STR\n        S2I = STI\n        CSCLR = CSCLR*TOL\n        CSCRR = 1.0D0/CSCLR\n        S1R = S1R*CSCLR\n        S1I = S1I*CSCLR\n        S2R = S2R*CSCLR\n        S2I = S2I*CSCLR\n   40 CONTINUE\n      RETURN\n   50 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n   60 CONTINUE\n      IF (IFORM.EQ.2) GO TO 70\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR I(FNU,Z) FOR LARGE FNU APPLIED IN\nC     -PI/3.LE.ARG(Z).LE.PI/3\nC-----------------------------------------------------------------------\n      CALL ZUNI1(ZR, ZI, FNU, KODE, N, YR, YI, NW, NLAST, FNUL, TOL,\n     * ELIM, ALIM)\n      GO TO 80\n   70 CONTINUE\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR J(FNU,Z*EXP(M*HPI)) FOR LARGE FNU\nC     APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I\nC     AND HPI=PI/2\nC-----------------------------------------------------------------------\n      CALL ZUNI2(ZR, ZI, FNU, KODE, N, YR, YI, NW, NLAST, FNUL, TOL,\n     * ELIM, ALIM)\n   80 CONTINUE\n      IF (NW.LT.0) GO TO 50\n      NZ = NW\n      RETURN\n   90 CONTINUE\n      NLAST = N\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zbunk.f",
    "content": "      SUBROUTINE ZBUNK(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  ZBUNK\nC***REFER TO  ZBESK,ZBESH\nC\nC     ZBUNK COMPUTES THE K BESSEL FUNCTION FOR FNU.GT.FNUL.\nC     ACCORDING TO THE UNIFORM ASYMPTOTIC EXPANSION FOR K(FNU,Z)\nC     IN ZUNK1 AND THE EXPANSION FOR H(2,FNU,Z) IN ZUNK2\nC\nC***ROUTINES CALLED  ZUNK1,ZUNK2\nC***END PROLOGUE  ZBUNK\nC     COMPLEX Y,Z\n      DOUBLE PRECISION ALIM, AX, AY, ELIM, FNU, TOL, YI, YR, ZI, ZR\n      INTEGER KODE, MR, N, NZ\n      DIMENSION YR(N), YI(N)\n      NZ = 0\n      AX = DABS(ZR)*1.7321D0\n      AY = DABS(ZI)\n      IF (AY.GT.AX) GO TO 10\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR K(FNU,Z) FOR LARGE FNU APPLIED IN\nC     -PI/3.LE.ARG(Z).LE.PI/3\nC-----------------------------------------------------------------------\n      CALL ZUNK1(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, ALIM)\n      GO TO 20\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     ASYMPTOTIC EXPANSION FOR H(2,FNU,Z*EXP(M*HPI)) FOR LARGE FNU\nC     APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I\nC     AND HPI=PI/2\nC-----------------------------------------------------------------------\n      CALL ZUNK2(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, ALIM)\n   20 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zdiv.f",
    "content": "      SUBROUTINE ZDIV(AR, AI, BR, BI, CR, CI)\nC***BEGIN PROLOGUE  ZDIV\nC***REFER TO  ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY\nC\nC     DOUBLE PRECISION COMPLEX DIVIDE C=A/B.\nC\nC***ROUTINES CALLED  XZABS\nC***END PROLOGUE  ZDIV\n      DOUBLE PRECISION AR, AI, BR, BI, CR, CI, BM, CA, CB, CC, CD\n      DOUBLE PRECISION XZABS\n      BM = 1.0D0/XZABS(BR,BI)\n      CC = BR*BM\n      CD = BI*BM\n      CA = (AR*CC+AI*CD)*BM\n      CB = (AI*CC-AR*CD)*BM\n      CR = CA\n      CI = CB\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zkscl.f",
    "content": "      SUBROUTINE ZKSCL(ZRR,ZRI,FNU,N,YR,YI,NZ,RZR,RZI,ASCLE,TOL,ELIM)\nC***BEGIN PROLOGUE  ZKSCL\nC***REFER TO  ZBESK\nC\nC     SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE\nC     ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN\nC     RETURN WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL.\nC\nC***ROUTINES CALLED  ZUCHK,XZABS,XZLOG\nC***END PROLOGUE  ZKSCL\nC     COMPLEX CK,CS,CY,CZERO,RZ,S1,S2,Y,ZR,ZD,CELM\n      DOUBLE PRECISION ACS, AS, ASCLE, CKI, CKR, CSI, CSR, CYI,\n     * CYR, ELIM, FN, FNU, RZI, RZR, STR, S1I, S1R, S2I,\n     * S2R, TOL, YI, YR, ZEROI, ZEROR, ZRI, ZRR, XZABS,\n     * ZDR, ZDI, CELMR, ELM, HELIM, ALAS\n      INTEGER I, IC, IDUM, KK, N, NN, NW, NZ\n      DIMENSION YR(N), YI(N), CYR(2), CYI(2)\n      DATA ZEROR,ZEROI / 0.0D0 , 0.0D0 /\nC\n      NZ = 0\n      IC = 0\n      NN = MIN0(2,N)\n      DO 10 I=1,NN\n        S1R = YR(I)\n        S1I = YI(I)\n        CYR(I) = S1R\n        CYI(I) = S1I\n        AS = XZABS(S1R,S1I)\n        ACS = -ZRR + DLOG(AS)\n        NZ = NZ + 1\n        YR(I) = ZEROR\n        YI(I) = ZEROI\n        IF (ACS.LT.(-ELIM)) GO TO 10\n        CALL XZLOG(S1R, S1I, CSR, CSI, IDUM)\n        CSR = CSR - ZRR\n        CSI = CSI - ZRI\n        STR = DEXP(CSR)/TOL\n        CSR = STR*DCOS(CSI)\n        CSI = STR*DSIN(CSI)\n        CALL ZUCHK(CSR, CSI, NW, ASCLE, TOL)\n        IF (NW.NE.0) GO TO 10\n        YR(I) = CSR\n        YI(I) = CSI\n        IC = I\n        NZ = NZ - 1\n   10 CONTINUE\n      IF (N.EQ.1) RETURN\n      IF (IC.GT.1) GO TO 20\n      YR(1) = ZEROR\n      YI(1) = ZEROI\n      NZ = 2\n   20 CONTINUE\n      IF (N.EQ.2) RETURN\n      IF (NZ.EQ.0) RETURN\n      FN = FNU + 1.0D0\n      CKR = FN*RZR\n      CKI = FN*RZI\n      S1R = CYR(1)\n      S1I = CYI(1)\n      S2R = CYR(2)\n      S2I = CYI(2)\n      HELIM = 0.5D0*ELIM\n      ELM = DEXP(-ELIM)\n      CELMR = ELM\n      ZDR = ZRR\n      ZDI = ZRI\nC\nC     FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF\nC     S2 GETS LARGER THAN EXP(ELIM/2)\nC\n      DO 30 I=3,N\n        KK = I\n        CSR = S2R\n        CSI = S2I\n        S2R = CKR*CSR - CKI*CSI + S1R\n        S2I = CKI*CSR + CKR*CSI + S1I\n        S1R = CSR\n        S1I = CSI\n        CKR = CKR + RZR\n        CKI = CKI + RZI\n        AS = XZABS(S2R,S2I)\n        ALAS = DLOG(AS)\n        ACS = -ZDR + ALAS\n        NZ = NZ + 1\n        YR(I) = ZEROR\n        YI(I) = ZEROI\n        IF (ACS.LT.(-ELIM)) GO TO 25\n        CALL XZLOG(S2R, S2I, CSR, CSI, IDUM)\n        CSR = CSR - ZDR\n        CSI = CSI - ZDI\n        STR = DEXP(CSR)/TOL\n        CSR = STR*DCOS(CSI)\n        CSI = STR*DSIN(CSI)\n        CALL ZUCHK(CSR, CSI, NW, ASCLE, TOL)\n        IF (NW.NE.0) GO TO 25\n        YR(I) = CSR\n        YI(I) = CSI\n        NZ = NZ - 1\n        IF (IC.EQ.KK-1) GO TO 40\n        IC = KK\n        GO TO 30\n   25   CONTINUE\n        IF(ALAS.LT.HELIM) GO TO 30\n        ZDR = ZDR - ELIM\n        S1R = S1R*CELMR\n        S1I = S1I*CELMR\n        S2R = S2R*CELMR\n        S2I = S2I*CELMR\n   30 CONTINUE\n      NZ = N\n      IF(IC.EQ.N) NZ=N-1\n      GO TO 45\n   40 CONTINUE\n      NZ = KK - 2\n   45 CONTINUE\n      DO 50 I=1,NZ\n        YR(I) = ZEROR\n        YI(I) = ZEROI\n   50 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zmlri.f",
    "content": "      SUBROUTINE ZMLRI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL)\nC***BEGIN PROLOGUE  ZMLRI\nC***REFER TO  ZBESI,ZBESK\nC\nC     ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z).GE.0.0 BY THE\nC     MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES.\nC\nC***ROUTINES CALLED  DGAMLN,D1MACH,XZABS,XZEXP,XZLOG,ZMLT\nC***END PROLOGUE  ZMLRI\nC     COMPLEX CK,CNORM,CONE,CTWO,CZERO,PT,P1,P2,RZ,SUM,Y,Z\n      DOUBLE PRECISION ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI,\n     * CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, FNU, PTI, PTR, P1I,\n     * P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI,\n     * SUMR, TFNF, TOL, TST, YI, YR, ZEROI, ZEROR, ZI, ZR, DGAMLN,\n     * D1MACH, XZABS\n      INTEGER I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, KODE, M, N, NZ\n      DIMENSION YR(N), YI(N)\n      DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 /\n      SCLE = D1MACH(1)/TOL\n      NZ=0\n      AZ = XZABS(ZR,ZI)\n      IAZ = INT(SNGL(AZ))\n      IFNU = INT(SNGL(FNU))\n      INU = IFNU + N - 1\n      AT = DBLE(FLOAT(IAZ)) + 1.0D0\n      RAZ = 1.0D0/AZ\n      STR = ZR*RAZ\n      STI = -ZI*RAZ\n      CKR = STR*AT*RAZ\n      CKI = STI*AT*RAZ\n      RZR = (STR+STR)*RAZ\n      RZI = (STI+STI)*RAZ\n      P1R = ZEROR\n      P1I = ZEROI\n      P2R = CONER\n      P2I = CONEI\n      ACK = (AT+1.0D0)*RAZ\n      RHO = ACK + DSQRT(ACK*ACK-1.0D0)\n      RHO2 = RHO*RHO\n      TST = (RHO2+RHO2)/((RHO2-1.0D0)*(RHO-1.0D0))\n      TST = TST/TOL\nC-----------------------------------------------------------------------\nC     COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES\nC-----------------------------------------------------------------------\n      AK = AT\n      DO 10 I=1,80\n        PTR = P2R\n        PTI = P2I\n        P2R = P1R - (CKR*PTR-CKI*PTI)\n        P2I = P1I - (CKI*PTR+CKR*PTI)\n        P1R = PTR\n        P1I = PTI\n        CKR = CKR + RZR\n        CKI = CKI + RZI\n        AP = XZABS(P2R,P2I)\n        IF (AP.GT.TST*AK*AK) GO TO 20\n        AK = AK + 1.0D0\n   10 CONTINUE\n      GO TO 110\n   20 CONTINUE\n      I = I + 1\n      K = 0\n      IF (INU.LT.IAZ) GO TO 40\nC-----------------------------------------------------------------------\nC     COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS\nC-----------------------------------------------------------------------\n      P1R = ZEROR\n      P1I = ZEROI\n      P2R = CONER\n      P2I = CONEI\n      AT = DBLE(FLOAT(INU)) + 1.0D0\n      STR = ZR*RAZ\n      STI = -ZI*RAZ\n      CKR = STR*AT*RAZ\n      CKI = STI*AT*RAZ\n      ACK = AT*RAZ\n      TST = DSQRT(ACK/TOL)\n      ITIME = 1\n      DO 30 K=1,80\n        PTR = P2R\n        PTI = P2I\n        P2R = P1R - (CKR*PTR-CKI*PTI)\n        P2I = P1I - (CKR*PTI+CKI*PTR)\n        P1R = PTR\n        P1I = PTI\n        CKR = CKR + RZR\n        CKI = CKI + RZI\n        AP = XZABS(P2R,P2I)\n        IF (AP.LT.TST) GO TO 30\n        IF (ITIME.EQ.2) GO TO 40\n        ACK = XZABS(CKR,CKI)\n        FLAM = ACK + DSQRT(ACK*ACK-1.0D0)\n        FKAP = AP/XZABS(P1R,P1I)\n        RHO = DMIN1(FLAM,FKAP)\n        TST = TST*DSQRT(RHO/(RHO*RHO-1.0D0))\n        ITIME = 2\n   30 CONTINUE\n      GO TO 110\n   40 CONTINUE\nC-----------------------------------------------------------------------\nC     BACKWARD RECURRENCE AND SUM NORMALIZING RELATION\nC-----------------------------------------------------------------------\n      K = K + 1\n      KK = MAX0(I+IAZ,K+INU)\n      FKK = DBLE(FLOAT(KK))\n      P1R = ZEROR\n      P1I = ZEROI\nC-----------------------------------------------------------------------\nC     SCALE P2 AND SUM BY SCLE\nC-----------------------------------------------------------------------\n      P2R = SCLE\n      P2I = ZEROI\n      FNF = FNU - DBLE(FLOAT(IFNU))\n      TFNF = FNF + FNF\n      BK = DGAMLN(FKK+TFNF+1.0D0,IDUM) - DGAMLN(FKK+1.0D0,IDUM) -\n     * DGAMLN(TFNF+1.0D0,IDUM)\n      BK = DEXP(BK)\n      SUMR = ZEROR\n      SUMI = ZEROI\n      KM = KK - INU\n      DO 50 I=1,KM\n        PTR = P2R\n        PTI = P2I\n        P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI)\n        P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI)\n        P1R = PTR\n        P1I = PTI\n        AK = 1.0D0 - TFNF/(FKK+TFNF)\n        ACK = BK*AK\n        SUMR = SUMR + (ACK+BK)*P1R\n        SUMI = SUMI + (ACK+BK)*P1I\n        BK = ACK\n        FKK = FKK - 1.0D0\n   50 CONTINUE\n      YR(N) = P2R\n      YI(N) = P2I\n      IF (N.EQ.1) GO TO 70\n      DO 60 I=2,N\n        PTR = P2R\n        PTI = P2I\n        P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI)\n        P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI)\n        P1R = PTR\n        P1I = PTI\n        AK = 1.0D0 - TFNF/(FKK+TFNF)\n        ACK = BK*AK\n        SUMR = SUMR + (ACK+BK)*P1R\n        SUMI = SUMI + (ACK+BK)*P1I\n        BK = ACK\n        FKK = FKK - 1.0D0\n        M = N - I + 1\n        YR(M) = P2R\n        YI(M) = P2I\n   60 CONTINUE\n   70 CONTINUE\n      IF (IFNU.LE.0) GO TO 90\n      DO 80 I=1,IFNU\n        PTR = P2R\n        PTI = P2I\n        P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI)\n        P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR)\n        P1R = PTR\n        P1I = PTI\n        AK = 1.0D0 - TFNF/(FKK+TFNF)\n        ACK = BK*AK\n        SUMR = SUMR + (ACK+BK)*P1R\n        SUMI = SUMI + (ACK+BK)*P1I\n        BK = ACK\n        FKK = FKK - 1.0D0\n   80 CONTINUE\n   90 CONTINUE\n      PTR = ZR\n      PTI = ZI\n      IF (KODE.EQ.2) PTR = ZEROR\n      CALL XZLOG(RZR, RZI, STR, STI, IDUM)\n      P1R = -FNF*STR + PTR\n      P1I = -FNF*STI + PTI\n      AP = DGAMLN(1.0D0+FNF,IDUM)\n      PTR = P1R - AP\n      PTI = P1I\nC-----------------------------------------------------------------------\nC     THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW\nC     IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES\nC-----------------------------------------------------------------------\n      P2R = P2R + SUMR\n      P2I = P2I + SUMI\n      AP = XZABS(P2R,P2I)\n      P1R = 1.0D0/AP\n      CALL XZEXP(PTR, PTI, STR, STI)\n      CKR = STR*P1R\n      CKI = STI*P1R\n      PTR = P2R*P1R\n      PTI = -P2I*P1R\n      CALL ZMLT(CKR, CKI, PTR, PTI, CNORMR, CNORMI)\n      DO 100 I=1,N\n        STR = YR(I)*CNORMR - YI(I)*CNORMI\n        YI(I) = YR(I)*CNORMI + YI(I)*CNORMR\n        YR(I) = STR\n  100 CONTINUE\n      RETURN\n  110 CONTINUE\n      NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zmlt.f",
    "content": "      SUBROUTINE ZMLT(AR, AI, BR, BI, CR, CI)\nC***BEGIN PROLOGUE  ZMLT\nC***REFER TO  ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY\nC\nC     DOUBLE PRECISION COMPLEX MULTIPLY, C=A*B.\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  ZMLT\n      DOUBLE PRECISION AR, AI, BR, BI, CR, CI, CA, CB\n      CA = AR*BR - AI*BI\n      CB = AR*BI + AI*BR\n      CR = CA\n      CI = CB\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zrati.f",
    "content": "      SUBROUTINE ZRATI(ZR, ZI, FNU, N, CYR, CYI, TOL)\nC***BEGIN PROLOGUE  ZRATI\nC***REFER TO  ZBESI,ZBESK,ZBESH\nC\nC     ZRATI COMPUTES RATIOS OF I BESSEL FUNCTIONS BY BACKWARD\nC     RECURRENCE.  THE STARTING INDEX IS DETERMINED BY FORWARD\nC     RECURRENCE AS DESCRIBED IN J. RES. OF NAT. BUR. OF STANDARDS-B,\nC     MATHEMATICAL SCIENCES, VOL 77B, P111-114, SEPTEMBER, 1973,\nC     BESSEL FUNCTIONS I AND J OF COMPLEX ARGUMENT AND INTEGER ORDER,\nC     BY D. J. SOOKNE.\nC\nC***ROUTINES CALLED  XZABS,ZDIV\nC***END PROLOGUE  ZRATI\nC     COMPLEX Z,CY(1),CONE,CZERO,P1,P2,T1,RZ,PT,CDFNU\n      DOUBLE PRECISION AK, AMAGZ, AP1, AP2, ARG, AZ, CDFNUI, CDFNUR,\n     * CONEI, CONER, CYI, CYR, CZEROI, CZEROR, DFNU, FDNU, FLAM, FNU,\n     * FNUP, PTI, PTR, P1I, P1R, P2I, P2R, RAK, RAP1, RHO, RT2, RZI,\n     * RZR, TEST, TEST1, TOL, TTI, TTR, T1I, T1R, ZI, ZR, XZABS\n      INTEGER I, ID, IDNU, INU, ITIME, K, KK, MAGZ, N\n      DIMENSION CYR(N), CYI(N)\n      DATA CZEROR,CZEROI,CONER,CONEI,RT2/\n     1 0.0D0, 0.0D0, 1.0D0, 0.0D0, 1.41421356237309505D0 /\n      AZ = XZABS(ZR,ZI)\n      INU = INT(SNGL(FNU))\n      IDNU = INU + N - 1\n      MAGZ = INT(SNGL(AZ))\n      AMAGZ = DBLE(FLOAT(MAGZ+1))\n      FDNU = DBLE(FLOAT(IDNU))\n      FNUP = DMAX1(AMAGZ,FDNU)\n      ID = IDNU - MAGZ - 1\n      ITIME = 1\n      K = 1\n      PTR = 1.0D0/AZ\n      RZR = PTR*(ZR+ZR)*PTR\n      RZI = -PTR*(ZI+ZI)*PTR\n      T1R = RZR*FNUP\n      T1I = RZI*FNUP\n      P2R = -T1R\n      P2I = -T1I\n      P1R = CONER\n      P1I = CONEI\n      T1R = T1R + RZR\n      T1I = T1I + RZI\n      IF (ID.GT.0) ID = 0\n      AP2 = XZABS(P2R,P2I)\n      AP1 = XZABS(P1R,P1I)\nC-----------------------------------------------------------------------\nC     THE OVERFLOW TEST ON K(FNU+I-1,Z) BEFORE THE CALL TO CBKNU\nC     GUARANTEES THAT P2 IS ON SCALE. SCALE TEST1 AND ALL SUBSEQUENT\nC     P2 VALUES BY AP1 TO ENSURE THAT AN OVERFLOW DOES NOT OCCUR\nC     PREMATURELY.\nC-----------------------------------------------------------------------\n      ARG = (AP2+AP2)/(AP1*TOL)\n      TEST1 = DSQRT(ARG)\n      TEST = TEST1\n      RAP1 = 1.0D0/AP1\n      P1R = P1R*RAP1\n      P1I = P1I*RAP1\n      P2R = P2R*RAP1\n      P2I = P2I*RAP1\n      AP2 = AP2*RAP1\n   10 CONTINUE\n      K = K + 1\n      AP1 = AP2\n      PTR = P2R\n      PTI = P2I\n      P2R = P1R - (T1R*PTR-T1I*PTI)\n      P2I = P1I - (T1R*PTI+T1I*PTR)\n      P1R = PTR\n      P1I = PTI\n      T1R = T1R + RZR\n      T1I = T1I + RZI\n      AP2 = XZABS(P2R,P2I)\n      IF (AP1.LE.TEST) GO TO 10\n      IF (ITIME.EQ.2) GO TO 20\n      AK = XZABS(T1R,T1I)*0.5D0\n      FLAM = AK + DSQRT(AK*AK-1.0D0)\n      RHO = DMIN1(AP2/AP1,FLAM)\n      TEST = TEST1*DSQRT(RHO/(RHO*RHO-1.0D0))\n      ITIME = 2\n      GO TO 10\n   20 CONTINUE\n      KK = K + 1 - ID\n      AK = DBLE(FLOAT(KK))\n      T1R = AK\n      T1I = CZEROI\n      DFNU = FNU + DBLE(FLOAT(N-1))\n      P1R = 1.0D0/AP2\n      P1I = CZEROI\n      P2R = CZEROR\n      P2I = CZEROI\n      DO 30 I=1,KK\n        PTR = P1R\n        PTI = P1I\n        RAP1 = DFNU + T1R\n        TTR = RZR*RAP1\n        TTI = RZI*RAP1\n        P1R = (PTR*TTR-PTI*TTI) + P2R\n        P1I = (PTR*TTI+PTI*TTR) + P2I\n        P2R = PTR\n        P2I = PTI\n        T1R = T1R - CONER\n   30 CONTINUE\n      IF (P1R.NE.CZEROR .OR. P1I.NE.CZEROI) GO TO 40\n      P1R = TOL\n      P1I = TOL\n   40 CONTINUE\n      CALL ZDIV(P2R, P2I, P1R, P1I, CYR(N), CYI(N))\n      IF (N.EQ.1) RETURN\n      K = N - 1\n      AK = DBLE(FLOAT(K))\n      T1R = AK\n      T1I = CZEROI\n      CDFNUR = FNU*RZR\n      CDFNUI = FNU*RZI\n      DO 60 I=2,N\n        PTR = CDFNUR + (T1R*RZR-T1I*RZI) + CYR(K+1)\n        PTI = CDFNUI + (T1R*RZI+T1I*RZR) + CYI(K+1)\n        AK = XZABS(PTR,PTI)\n        IF (AK.NE.CZEROR) GO TO 50\n        PTR = TOL\n        PTI = TOL\n        AK = TOL*RT2\n   50   CONTINUE\n        RAK = CONER/AK\n        CYR(K) = RAK*PTR*RAK\n        CYI(K) = -RAK*PTI*RAK\n        T1R = T1R - CONER\n        K = K - 1\n   60 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zs1s2.f",
    "content": "      SUBROUTINE ZS1S2(ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM,\n     * IUF)\nC***BEGIN PROLOGUE  ZS1S2\nC***REFER TO  ZBESK,ZAIRY\nC\nC     ZS1S2 TESTS FOR A POSSIBLE UNDERFLOW RESULTING FROM THE\nC     ADDITION OF THE I AND K FUNCTIONS IN THE ANALYTIC CON-\nC     TINUATION FORMULA WHERE S1=K FUNCTION AND S2=I FUNCTION.\nC     ON KODE=1 THE I AND K FUNCTIONS ARE DIFFERENT ORDERS OF\nC     MAGNITUDE, BUT FOR KODE=2 THEY CAN BE OF THE SAME ORDER\nC     OF MAGNITUDE AND THE MAXIMUM MUST BE AT LEAST ONE\nC     PRECISION ABOVE THE UNDERFLOW LIMIT.\nC\nC***ROUTINES CALLED  XZABS,XZEXP,XZLOG\nC***END PROLOGUE  ZS1S2\nC     COMPLEX CZERO,C1,S1,S1D,S2,ZR\n      DOUBLE PRECISION AA, ALIM, ALN, ASCLE, AS1, AS2, C1I, C1R, S1DI,\n     * S1DR, S1I, S1R, S2I, S2R, ZEROI, ZEROR, ZRI, ZRR, XZABS\n      INTEGER IUF, IDUM, NZ\n      DATA ZEROR,ZEROI  / 0.0D0 , 0.0D0 /\n      NZ = 0\n      AS1 = XZABS(S1R,S1I)\n      AS2 = XZABS(S2R,S2I)\n      IF (S1R.EQ.0.0D0 .AND. S1I.EQ.0.0D0) GO TO 10\n      IF (AS1.EQ.0.0D0) GO TO 10\n      ALN = -ZRR - ZRR + DLOG(AS1)\n      S1DR = S1R\n      S1DI = S1I\n      S1R = ZEROR\n      S1I = ZEROI\n      AS1 = ZEROR\n      IF (ALN.LT.(-ALIM)) GO TO 10\n      CALL XZLOG(S1DR, S1DI, C1R, C1I, IDUM)\n      C1R = C1R - ZRR - ZRR\n      C1I = C1I - ZRI - ZRI\n      CALL XZEXP(C1R, C1I, S1R, S1I)\n      AS1 = XZABS(S1R,S1I)\n      IUF = IUF + 1\n   10 CONTINUE\n      AA = DMAX1(AS1,AS2)\n      IF (AA.GT.ASCLE) RETURN\n      S1R = ZEROR\n      S1I = ZEROI\n      S2R = ZEROR\n      S2I = ZEROI\n      NZ = 1\n      IUF = 0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zseri.f",
    "content": "      SUBROUTINE ZSERI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  ZSERI\nC***REFER TO  ZBESI,ZBESK\nC\nC     ZSERI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z).GE.0.0 BY\nC     MEANS OF THE POWER SERIES FOR LARGE CABS(Z) IN THE\nC     REGION CABS(Z).LE.2*SQRT(FNU+1). NZ=0 IS A NORMAL RETURN.\nC     NZ.GT.0 MEANS THAT THE LAST NZ COMPONENTS WERE SET TO ZERO\nC     DUE TO UNDERFLOW. NZ.LT.0 MEANS UNDERFLOW OCCURRED, BUT THE\nC     CONDITION CABS(Z).LE.2*SQRT(FNU+1) WAS VIOLATED AND THE\nC     COMPUTATION MUST BE COMPLETED IN ANOTHER ROUTINE WITH N=N-ABS(NZ).\nC\nC***ROUTINES CALLED  DGAMLN,D1MACH,ZUCHK,XZABS,ZDIV,XZLOG,ZMLT\nC***END PROLOGUE  ZSERI\nC     COMPLEX AK1,CK,COEF,CONE,CRSC,CSCL,CZ,CZERO,HZ,RZ,S1,S2,Y,Z\n      DOUBLE PRECISION AA, ACZ, AK, AK1I, AK1R, ALIM, ARM, ASCLE, ATOL,\n     * AZ, CKI, CKR, COEFI, COEFR, CONEI, CONER, CRSCR, CZI, CZR, DFNU,\n     * ELIM, FNU, FNUP, HZI, HZR, RAZ, RS, RTR1, RZI, RZR, S, SS, STI,\n     * STR, S1I, S1R, S2I, S2R, TOL, YI, YR, WI, WR, ZEROI, ZEROR, ZI,\n     * ZR, DGAMLN, D1MACH, XZABS\n      INTEGER I, IB, IDUM, IFLAG, IL, K, KODE, L, M, N, NN, NZ, NW\n      DIMENSION YR(N), YI(N), WR(2), WI(2)\n      DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 /\nC\n      NZ = 0\n      AZ = XZABS(ZR,ZI)\n      IF (AZ.EQ.0.0D0) GO TO 160\n      ARM = 1.0D+3*D1MACH(1)\n      RTR1 = DSQRT(ARM)\n      CRSCR = 1.0D0\n      IFLAG = 0\n      IF (AZ.LT.ARM) GO TO 150\n      HZR = 0.5D0*ZR\n      HZI = 0.5D0*ZI\n      CZR = ZEROR\n      CZI = ZEROI\n      IF (AZ.LE.RTR1) GO TO 10\n      CALL ZMLT(HZR, HZI, HZR, HZI, CZR, CZI)\n   10 CONTINUE\n      ACZ = XZABS(CZR,CZI)\n      NN = N\n      CALL XZLOG(HZR, HZI, CKR, CKI, IDUM)\n   20 CONTINUE\n      DFNU = FNU + DBLE(FLOAT(NN-1))\n      FNUP = DFNU + 1.0D0\nC-----------------------------------------------------------------------\nC     UNDERFLOW TEST\nC-----------------------------------------------------------------------\n      AK1R = CKR*DFNU\n      AK1I = CKI*DFNU\n      AK = DGAMLN(FNUP,IDUM)\n      AK1R = AK1R - AK\n      IF (KODE.EQ.2) AK1R = AK1R - ZR\n      IF (AK1R.GT.(-ELIM)) GO TO 40\n   30 CONTINUE\n      NZ = NZ + 1\n      YR(NN) = ZEROR\n      YI(NN) = ZEROI\n      IF (ACZ.GT.DFNU) GO TO 190\n      NN = NN - 1\n      IF (NN.EQ.0) RETURN\n      GO TO 20\n   40 CONTINUE\n      IF (AK1R.GT.(-ALIM)) GO TO 50\n      IFLAG = 1\n      SS = 1.0D0/TOL\n      CRSCR = TOL\n      ASCLE = ARM*SS\n   50 CONTINUE\n      AA = DEXP(AK1R)\n      IF (IFLAG.EQ.1) AA = AA*SS\n      COEFR = AA*DCOS(AK1I)\n      COEFI = AA*DSIN(AK1I)\n      ATOL = TOL*ACZ/FNUP\n      IL = MIN0(2,NN)\n      DO 90 I=1,IL\n        DFNU = FNU + DBLE(FLOAT(NN-I))\n        FNUP = DFNU + 1.0D0\n        S1R = CONER\n        S1I = CONEI\n        IF (ACZ.LT.TOL*FNUP) GO TO 70\n        AK1R = CONER\n        AK1I = CONEI\n        AK = FNUP + 2.0D0\n        S = FNUP\n        AA = 2.0D0\n   60   CONTINUE\n        RS = 1.0D0/S\n        STR = AK1R*CZR - AK1I*CZI\n        STI = AK1R*CZI + AK1I*CZR\n        AK1R = STR*RS\n        AK1I = STI*RS\n        S1R = S1R + AK1R\n        S1I = S1I + AK1I\n        S = S + AK\n        AK = AK + 2.0D0\n        AA = AA*ACZ*RS\n        IF (AA.GT.ATOL) GO TO 60\n   70   CONTINUE\n        S2R = S1R*COEFR - S1I*COEFI\n        S2I = S1R*COEFI + S1I*COEFR\n        WR(I) = S2R\n        WI(I) = S2I\n        IF (IFLAG.EQ.0) GO TO 80\n        CALL ZUCHK(S2R, S2I, NW, ASCLE, TOL)\n        IF (NW.NE.0) GO TO 30\n   80   CONTINUE\n        M = NN - I + 1\n        YR(M) = S2R*CRSCR\n        YI(M) = S2I*CRSCR\n        IF (I.EQ.IL) GO TO 90\n        CALL ZDIV(COEFR, COEFI, HZR, HZI, STR, STI)\n        COEFR = STR*DFNU\n        COEFI = STI*DFNU\n   90 CONTINUE\n      IF (NN.LE.2) RETURN\n      K = NN - 2\n      AK = DBLE(FLOAT(K))\n      RAZ = 1.0D0/AZ\n      STR = ZR*RAZ\n      STI = -ZI*RAZ\n      RZR = (STR+STR)*RAZ\n      RZI = (STI+STI)*RAZ\n      IF (IFLAG.EQ.1) GO TO 120\n      IB = 3\n  100 CONTINUE\n      DO 110 I=IB,NN\n        YR(K) = (AK+FNU)*(RZR*YR(K+1)-RZI*YI(K+1)) + YR(K+2)\n        YI(K) = (AK+FNU)*(RZR*YI(K+1)+RZI*YR(K+1)) + YI(K+2)\n        AK = AK - 1.0D0\n        K = K - 1\n  110 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     RECUR BACKWARD WITH SCALED VALUES\nC-----------------------------------------------------------------------\n  120 CONTINUE\nC-----------------------------------------------------------------------\nC     EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION ABOVE THE\nC     UNDERFLOW LIMIT = ASCLE = D1MACH(1)*SS*1.0D+3\nC-----------------------------------------------------------------------\n      S1R = WR(1)\n      S1I = WI(1)\n      S2R = WR(2)\n      S2I = WI(2)\n      DO 130 L=3,NN\n        CKR = S2R\n        CKI = S2I\n        S2R = S1R + (AK+FNU)*(RZR*CKR-RZI*CKI)\n        S2I = S1I + (AK+FNU)*(RZR*CKI+RZI*CKR)\n        S1R = CKR\n        S1I = CKI\n        CKR = S2R*CRSCR\n        CKI = S2I*CRSCR\n        YR(K) = CKR\n        YI(K) = CKI\n        AK = AK - 1.0D0\n        K = K - 1\n        IF (XZABS(CKR,CKI).GT.ASCLE) GO TO 140\n  130 CONTINUE\n      RETURN\n  140 CONTINUE\n      IB = L + 1\n      IF (IB.GT.NN) RETURN\n      GO TO 100\n  150 CONTINUE\n      NZ = N\n      IF (FNU.EQ.0.0D0) NZ = NZ - 1\n  160 CONTINUE\n      YR(1) = ZEROR\n      YI(1) = ZEROI\n      IF (FNU.NE.0.0D0) GO TO 170\n      YR(1) = CONER\n      YI(1) = CONEI\n  170 CONTINUE\n      IF (N.EQ.1) RETURN\n      DO 180 I=2,N\n        YR(I) = ZEROR\n        YI(I) = ZEROI\n  180 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     RETURN WITH NZ.LT.0 IF CABS(Z*Z/4).GT.FNU+N-NZ-1 COMPLETE\nC     THE CALCULATION IN CBINU WITH N=N-IABS(NZ)\nC-----------------------------------------------------------------------\n  190 CONTINUE\n      NZ = -NZ\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zshch.f",
    "content": "      SUBROUTINE ZSHCH(ZR, ZI, CSHR, CSHI, CCHR, CCHI)\nC***BEGIN PROLOGUE  ZSHCH\nC***REFER TO  ZBESK,ZBESH\nC\nC     ZSHCH COMPUTES THE COMPLEX HYPERBOLIC FUNCTIONS CSH=SINH(X+I*Y)\nC     AND CCH=COSH(X+I*Y), WHERE I**2=-1.\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  ZSHCH\nC\n      DOUBLE PRECISION CCHI, CCHR, CH, CN, CSHI, CSHR, SH, SN, ZI, ZR,\n     * DCOSH, DSINH\n      SH = DSINH(ZR)\n      CH = DCOSH(ZR)\n      SN = DSIN(ZI)\n      CN = DCOS(ZI)\n      CSHR = SH*CN\n      CSHI = CH*SN\n      CCHR = CH*CN\n      CCHI = SH*SN\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zuchk.f",
    "content": "      SUBROUTINE ZUCHK(YR, YI, NZ, ASCLE, TOL)\nC***BEGIN PROLOGUE  ZUCHK\nC***REFER TO ZSERI,ZUOIK,ZUNK1,ZUNK2,ZUNI1,ZUNI2,ZKSCL\nC\nC      Y ENTERS AS A SCALED QUANTITY WHOSE MAGNITUDE IS GREATER THAN\nC      EXP(-ALIM)=ASCLE=1.0E+3*D1MACH(1)/TOL. THE TEST IS MADE TO SEE\nC      IF THE MAGNITUDE OF THE REAL OR IMAGINARY PART WOULD UNDERFLOW\nC      WHEN Y IS SCALED (BY TOL) TO ITS PROPER VALUE. Y IS ACCEPTED\nC      IF THE UNDERFLOW IS AT LEAST ONE PRECISION BELOW THE MAGNITUDE\nC      OF THE LARGEST COMPONENT; OTHERWISE THE PHASE ANGLE DOES NOT HAVE\nC      ABSOLUTE ACCURACY AND AN UNDERFLOW IS ASSUMED.\nC\nC***ROUTINES CALLED  (NONE)\nC***END PROLOGUE  ZUCHK\nC\nC     COMPLEX Y\n      DOUBLE PRECISION ASCLE, SS, ST, TOL, WR, WI, YR, YI\n      INTEGER NZ\n      NZ = 0\n      WR = DABS(YR)\n      WI = DABS(YI)\n      ST = DMIN1(WR,WI)\n      IF (ST.GT.ASCLE) RETURN\n      SS = DMAX1(WR,WI)\n      ST = ST/TOL\n      IF (SS.LT.ST) NZ = 1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zunhj.f",
    "content": "      SUBROUTINE ZUNHJ(ZR, ZI, FNU, IPMTR, TOL, PHIR, PHII, ARGR, ARGI,\n     * ZETA1R, ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI)\nC***BEGIN PROLOGUE  ZUNHJ\nC***REFER TO  ZBESI,ZBESK\nC\nC     REFERENCES\nC         HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ AND I.A.\nC         STEGUN, AMS55, NATIONAL BUREAU OF STANDARDS, 1965, CHAPTER 9.\nC\nC         ASYMPTOTICS AND SPECIAL FUNCTIONS BY F.W.J. OLVER, ACADEMIC\nC         PRESS, N.Y., 1974, PAGE 420\nC\nC     ABSTRACT\nC         ZUNHJ COMPUTES PARAMETERS FOR BESSEL FUNCTIONS C(FNU,Z) =\nC         J(FNU,Z), Y(FNU,Z) OR H(I,FNU,Z) I=1,2 FOR LARGE ORDERS FNU\nC         BY MEANS OF THE UNIFORM ASYMPTOTIC EXPANSION\nC\nC         C(FNU,Z)=C1*PHI*( ASUM*AIRY(ARG) + C2*BSUM*DAIRY(ARG) )\nC\nC         FOR PROPER CHOICES OF C1, C2, AIRY AND DAIRY WHERE AIRY IS\nC         AN AIRY FUNCTION AND DAIRY IS ITS DERIVATIVE.\nC\nC               (2/3)*FNU*ZETA**1.5 = ZETA1-ZETA2,\nC\nC         ZETA1=0.5*FNU*CLOG((1+W)/(1-W)), ZETA2=FNU*W FOR SCALING\nC         PURPOSES IN AIRY FUNCTIONS FROM CAIRY OR CBIRY.\nC\nC         MCONJ=SIGN OF AIMAG(Z), BUT IS AMBIGUOUS WHEN Z IS REAL AND\nC         MUST BE SPECIFIED. IPMTR=0 RETURNS ALL PARAMETERS. IPMTR=\nC         1 COMPUTES ALL EXCEPT ASUM AND BSUM.\nC\nC***ROUTINES CALLED  XZABS,ZDIV,XZLOG,XZSQRT,D1MACH\nC***END PROLOGUE  ZUNHJ\nC     COMPLEX ARG,ASUM,BSUM,CFNU,CONE,CR,CZERO,DR,P,PHI,PRZTH,PTFN,\nC    *RFN13,RTZTA,RZTH,SUMA,SUMB,TFN,T2,UP,W,W2,Z,ZA,ZB,ZC,ZETA,ZETA1,\nC    *ZETA2,ZTH\n      DOUBLE PRECISION ALFA, ANG, AP, AR, ARGI, ARGR, ASUMI, ASUMR,\n     * ATOL, AW2, AZTH, BETA, BR, BSUMI, BSUMR, BTOL, C, CONEI, CONER,\n     * CRI, CRR, DRI, DRR, EX1, EX2, FNU, FN13, FN23, GAMA, GPI, HPI,\n     * PHII, PHIR, PI, PP, PR, PRZTHI, PRZTHR, PTFNI, PTFNR, RAW, RAW2,\n     * RAZTH, RFNU, RFNU2, RFN13, RTZTI, RTZTR, RZTHI, RZTHR, STI, STR,\n     * SUMAI, SUMAR, SUMBI, SUMBR, TEST, TFNI, TFNR, THPI, TOL, TZAI,\n     * TZAR, T2I, T2R, UPI, UPR, WI, WR, W2I, W2R, ZAI, ZAR, ZBI, ZBR,\n     * ZCI, ZCR, ZEROI, ZEROR, ZETAI, ZETAR, ZETA1I, ZETA1R, ZETA2I,\n     * ZETA2R, ZI, ZR, ZTHI, ZTHR, XZABS, AC, D1MACH\n      INTEGER IAS, IBS, IPMTR, IS, J, JR, JU, K, KMAX, KP1, KS, L, LR,\n     * LRP1, L1, L2, M, IDUM\n      DIMENSION AR(14), BR(14), C(105), ALFA(180), BETA(210), GAMA(30),\n     * AP(30), PR(30), PI(30), UPR(14), UPI(14), CRR(14), CRI(14),\n     * DRR(14), DRI(14)\n      DATA AR(1), AR(2), AR(3), AR(4), AR(5), AR(6), AR(7), AR(8),\n     1     AR(9), AR(10), AR(11), AR(12), AR(13), AR(14)/\n     2     1.00000000000000000D+00,     1.04166666666666667D-01,\n     3     8.35503472222222222D-02,     1.28226574556327160D-01,\n     4     2.91849026464140464D-01,     8.81627267443757652D-01,\n     5     3.32140828186276754D+00,     1.49957629868625547D+01,\n     6     7.89230130115865181D+01,     4.74451538868264323D+02,\n     7     3.20749009089066193D+03,     2.40865496408740049D+04,\n     8     1.98923119169509794D+05,     1.79190200777534383D+06/\n      DATA BR(1), BR(2), BR(3), BR(4), BR(5), BR(6), BR(7), BR(8),\n     1     BR(9), BR(10), BR(11), BR(12), BR(13), BR(14)/\n     2     1.00000000000000000D+00,    -1.45833333333333333D-01,\n     3    -9.87413194444444444D-02,    -1.43312053915895062D-01,\n     4    -3.17227202678413548D-01,    -9.42429147957120249D-01,\n     5    -3.51120304082635426D+00,    -1.57272636203680451D+01,\n     6    -8.22814390971859444D+01,    -4.92355370523670524D+02,\n     7    -3.31621856854797251D+03,    -2.48276742452085896D+04,\n     8    -2.04526587315129788D+05,    -1.83844491706820990D+06/\n      DATA C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10),\n     1     C(11), C(12), C(13), C(14), C(15), C(16), C(17), C(18),\n     2     C(19), C(20), C(21), C(22), C(23), C(24)/\n     3     1.00000000000000000D+00,    -2.08333333333333333D-01,\n     4     1.25000000000000000D-01,     3.34201388888888889D-01,\n     5    -4.01041666666666667D-01,     7.03125000000000000D-02,\n     6    -1.02581259645061728D+00,     1.84646267361111111D+00,\n     7    -8.91210937500000000D-01,     7.32421875000000000D-02,\n     8     4.66958442342624743D+00,    -1.12070026162229938D+01,\n     9     8.78912353515625000D+00,    -2.36408691406250000D+00,\n     A     1.12152099609375000D-01,    -2.82120725582002449D+01,\n     B     8.46362176746007346D+01,    -9.18182415432400174D+01,\n     C     4.25349987453884549D+01,    -7.36879435947963170D+00,\n     D     2.27108001708984375D-01,     2.12570130039217123D+02,\n     E    -7.65252468141181642D+02,     1.05999045252799988D+03/\n      DATA C(25), C(26), C(27), C(28), C(29), C(30), C(31), C(32),\n     1     C(33), C(34), C(35), C(36), C(37), C(38), C(39), C(40),\n     2     C(41), C(42), C(43), C(44), C(45), C(46), C(47), C(48)/\n     3    -6.99579627376132541D+02,     2.18190511744211590D+02,\n     4    -2.64914304869515555D+01,     5.72501420974731445D-01,\n     5    -1.91945766231840700D+03,     8.06172218173730938D+03,\n     6    -1.35865500064341374D+04,     1.16553933368645332D+04,\n     7    -5.30564697861340311D+03,     1.20090291321635246D+03,\n     8    -1.08090919788394656D+02,     1.72772750258445740D+00,\n     9     2.02042913309661486D+04,    -9.69805983886375135D+04,\n     A     1.92547001232531532D+05,    -2.03400177280415534D+05,\n     B     1.22200464983017460D+05,    -4.11926549688975513D+04,\n     C     7.10951430248936372D+03,    -4.93915304773088012D+02,\n     D     6.07404200127348304D+00,    -2.42919187900551333D+05,\n     E     1.31176361466297720D+06,    -2.99801591853810675D+06/\n      DATA C(49), C(50), C(51), C(52), C(53), C(54), C(55), C(56),\n     1     C(57), C(58), C(59), C(60), C(61), C(62), C(63), C(64),\n     2     C(65), C(66), C(67), C(68), C(69), C(70), C(71), C(72)/\n     3     3.76327129765640400D+06,    -2.81356322658653411D+06,\n     4     1.26836527332162478D+06,    -3.31645172484563578D+05,\n     5     4.52187689813627263D+04,    -2.49983048181120962D+03,\n     6     2.43805296995560639D+01,     3.28446985307203782D+06,\n     7    -1.97068191184322269D+07,     5.09526024926646422D+07,\n     8    -7.41051482115326577D+07,     6.63445122747290267D+07,\n     9    -3.75671766607633513D+07,     1.32887671664218183D+07,\n     A    -2.78561812808645469D+06,     3.08186404612662398D+05,\n     B    -1.38860897537170405D+04,     1.10017140269246738D+02,\n     C    -4.93292536645099620D+07,     3.25573074185765749D+08,\n     D    -9.39462359681578403D+08,     1.55359689957058006D+09,\n     E    -1.62108055210833708D+09,     1.10684281682301447D+09/\n      DATA C(73), C(74), C(75), C(76), C(77), C(78), C(79), C(80),\n     1     C(81), C(82), C(83), C(84), C(85), C(86), C(87), C(88),\n     2     C(89), C(90), C(91), C(92), C(93), C(94), C(95), C(96)/\n     3    -4.95889784275030309D+08,     1.42062907797533095D+08,\n     4    -2.44740627257387285D+07,     2.24376817792244943D+06,\n     5    -8.40054336030240853D+04,     5.51335896122020586D+02,\n     6     8.14789096118312115D+08,    -5.86648149205184723D+09,\n     7     1.86882075092958249D+10,    -3.46320433881587779D+10,\n     8     4.12801855797539740D+10,    -3.30265997498007231D+10,\n     9     1.79542137311556001D+10,    -6.56329379261928433D+09,\n     A     1.55927986487925751D+09,    -2.25105661889415278D+08,\n     B     1.73951075539781645D+07,    -5.49842327572288687D+05,\n     C     3.03809051092238427D+03,    -1.46792612476956167D+10,\n     D     1.14498237732025810D+11,    -3.99096175224466498D+11,\n     E     8.19218669548577329D+11,    -1.09837515608122331D+12/\n      DATA C(97), C(98), C(99), C(100), C(101), C(102), C(103), C(104),\n     1     C(105)/\n     2     1.00815810686538209D+12,    -6.45364869245376503D+11,\n     3     2.87900649906150589D+11,    -8.78670721780232657D+10,\n     4     1.76347306068349694D+10,    -2.16716498322379509D+09,\n     5     1.43157876718888981D+08,    -3.87183344257261262D+06,\n     6     1.82577554742931747D+04/\n      DATA ALFA(1), ALFA(2), ALFA(3), ALFA(4), ALFA(5), ALFA(6),\n     1     ALFA(7), ALFA(8), ALFA(9), ALFA(10), ALFA(11), ALFA(12),\n     2     ALFA(13), ALFA(14), ALFA(15), ALFA(16), ALFA(17), ALFA(18),\n     3     ALFA(19), ALFA(20), ALFA(21), ALFA(22)/\n     4    -4.44444444444444444D-03,    -9.22077922077922078D-04,\n     5    -8.84892884892884893D-05,     1.65927687832449737D-04,\n     6     2.46691372741792910D-04,     2.65995589346254780D-04,\n     7     2.61824297061500945D-04,     2.48730437344655609D-04,\n     8     2.32721040083232098D-04,     2.16362485712365082D-04,\n     9     2.00738858762752355D-04,     1.86267636637545172D-04,\n     A     1.73060775917876493D-04,     1.61091705929015752D-04,\n     B     1.50274774160908134D-04,     1.40503497391269794D-04,\n     C     1.31668816545922806D-04,     1.23667445598253261D-04,\n     D     1.16405271474737902D-04,     1.09798298372713369D-04,\n     E     1.03772410422992823D-04,     9.82626078369363448D-05/\n      DATA ALFA(23), ALFA(24), ALFA(25), ALFA(26), ALFA(27), ALFA(28),\n     1     ALFA(29), ALFA(30), ALFA(31), ALFA(32), ALFA(33), ALFA(34),\n     2     ALFA(35), ALFA(36), ALFA(37), ALFA(38), ALFA(39), ALFA(40),\n     3     ALFA(41), ALFA(42), ALFA(43), ALFA(44)/\n     4     9.32120517249503256D-05,     8.85710852478711718D-05,\n     5     8.42963105715700223D-05,     8.03497548407791151D-05,\n     6     7.66981345359207388D-05,     7.33122157481777809D-05,\n     7     7.01662625163141333D-05,     6.72375633790160292D-05,\n     8     6.93735541354588974D-04,     2.32241745182921654D-04,\n     9    -1.41986273556691197D-05,    -1.16444931672048640D-04,\n     A    -1.50803558053048762D-04,    -1.55121924918096223D-04,\n     B    -1.46809756646465549D-04,    -1.33815503867491367D-04,\n     C    -1.19744975684254051D-04,    -1.06184319207974020D-04,\n     D    -9.37699549891194492D-05,    -8.26923045588193274D-05,\n     E    -7.29374348155221211D-05,    -6.44042357721016283D-05/\n      DATA ALFA(45), ALFA(46), ALFA(47), ALFA(48), ALFA(49), ALFA(50),\n     1     ALFA(51), ALFA(52), ALFA(53), ALFA(54), ALFA(55), ALFA(56),\n     2     ALFA(57), ALFA(58), ALFA(59), ALFA(60), ALFA(61), ALFA(62),\n     3     ALFA(63), ALFA(64), ALFA(65), ALFA(66)/\n     4    -5.69611566009369048D-05,    -5.04731044303561628D-05,\n     5    -4.48134868008882786D-05,    -3.98688727717598864D-05,\n     6    -3.55400532972042498D-05,    -3.17414256609022480D-05,\n     7    -2.83996793904174811D-05,    -2.54522720634870566D-05,\n     8    -2.28459297164724555D-05,    -2.05352753106480604D-05,\n     9    -1.84816217627666085D-05,    -1.66519330021393806D-05,\n     A    -1.50179412980119482D-05,    -1.35554031379040526D-05,\n     B    -1.22434746473858131D-05,    -1.10641884811308169D-05,\n     C    -3.54211971457743841D-04,    -1.56161263945159416D-04,\n     D     3.04465503594936410D-05,     1.30198655773242693D-04,\n     E     1.67471106699712269D-04,     1.70222587683592569D-04/\n      DATA ALFA(67), ALFA(68), ALFA(69), ALFA(70), ALFA(71), ALFA(72),\n     1     ALFA(73), ALFA(74), ALFA(75), ALFA(76), ALFA(77), ALFA(78),\n     2     ALFA(79), ALFA(80), ALFA(81), ALFA(82), ALFA(83), ALFA(84),\n     3     ALFA(85), ALFA(86), ALFA(87), ALFA(88)/\n     4     1.56501427608594704D-04,     1.36339170977445120D-04,\n     5     1.14886692029825128D-04,     9.45869093034688111D-05,\n     6     7.64498419250898258D-05,     6.07570334965197354D-05,\n     7     4.74394299290508799D-05,     3.62757512005344297D-05,\n     8     2.69939714979224901D-05,     1.93210938247939253D-05,\n     9     1.30056674793963203D-05,     7.82620866744496661D-06,\n     A     3.59257485819351583D-06,     1.44040049814251817D-07,\n     B    -2.65396769697939116D-06,    -4.91346867098485910D-06,\n     C    -6.72739296091248287D-06,    -8.17269379678657923D-06,\n     D    -9.31304715093561232D-06,    -1.02011418798016441D-05,\n     E    -1.08805962510592880D-05,    -1.13875481509603555D-05/\n      DATA ALFA(89), ALFA(90), ALFA(91), ALFA(92), ALFA(93), ALFA(94),\n     1     ALFA(95), ALFA(96), ALFA(97), ALFA(98), ALFA(99), ALFA(100),\n     2     ALFA(101), ALFA(102), ALFA(103), ALFA(104), ALFA(105),\n     3     ALFA(106), ALFA(107), ALFA(108), ALFA(109), ALFA(110)/\n     4    -1.17519675674556414D-05,    -1.19987364870944141D-05,\n     5     3.78194199201772914D-04,     2.02471952761816167D-04,\n     6    -6.37938506318862408D-05,    -2.38598230603005903D-04,\n     7    -3.10916256027361568D-04,    -3.13680115247576316D-04,\n     8    -2.78950273791323387D-04,    -2.28564082619141374D-04,\n     9    -1.75245280340846749D-04,    -1.25544063060690348D-04,\n     A    -8.22982872820208365D-05,    -4.62860730588116458D-05,\n     B    -1.72334302366962267D-05,     5.60690482304602267D-06,\n     C     2.31395443148286800D-05,     3.62642745856793957D-05,\n     D     4.58006124490188752D-05,     5.24595294959114050D-05,\n     E     5.68396208545815266D-05,     5.94349820393104052D-05/\n      DATA ALFA(111), ALFA(112), ALFA(113), ALFA(114), ALFA(115),\n     1     ALFA(116), ALFA(117), ALFA(118), ALFA(119), ALFA(120),\n     2     ALFA(121), ALFA(122), ALFA(123), ALFA(124), ALFA(125),\n     3     ALFA(126), ALFA(127), ALFA(128), ALFA(129), ALFA(130)/\n     4     6.06478527578421742D-05,     6.08023907788436497D-05,\n     5     6.01577894539460388D-05,     5.89199657344698500D-05,\n     6     5.72515823777593053D-05,     5.52804375585852577D-05,\n     7     5.31063773802880170D-05,     5.08069302012325706D-05,\n     8     4.84418647620094842D-05,     4.60568581607475370D-05,\n     9    -6.91141397288294174D-04,    -4.29976633058871912D-04,\n     A     1.83067735980039018D-04,     6.60088147542014144D-04,\n     B     8.75964969951185931D-04,     8.77335235958235514D-04,\n     C     7.49369585378990637D-04,     5.63832329756980918D-04,\n     D     3.68059319971443156D-04,     1.88464535514455599D-04/\n      DATA ALFA(131), ALFA(132), ALFA(133), ALFA(134), ALFA(135),\n     1     ALFA(136), ALFA(137), ALFA(138), ALFA(139), ALFA(140),\n     2     ALFA(141), ALFA(142), ALFA(143), ALFA(144), ALFA(145),\n     3     ALFA(146), ALFA(147), ALFA(148), ALFA(149), ALFA(150)/\n     4     3.70663057664904149D-05,    -8.28520220232137023D-05,\n     5    -1.72751952869172998D-04,    -2.36314873605872983D-04,\n     6    -2.77966150694906658D-04,    -3.02079514155456919D-04,\n     7    -3.12594712643820127D-04,    -3.12872558758067163D-04,\n     8    -3.05678038466324377D-04,    -2.93226470614557331D-04,\n     9    -2.77255655582934777D-04,    -2.59103928467031709D-04,\n     A    -2.39784014396480342D-04,    -2.20048260045422848D-04,\n     B    -2.00443911094971498D-04,    -1.81358692210970687D-04,\n     C    -1.63057674478657464D-04,    -1.45712672175205844D-04,\n     D    -1.29425421983924587D-04,    -1.14245691942445952D-04/\n      DATA ALFA(151), ALFA(152), ALFA(153), ALFA(154), ALFA(155),\n     1     ALFA(156), ALFA(157), ALFA(158), ALFA(159), ALFA(160),\n     2     ALFA(161), ALFA(162), ALFA(163), ALFA(164), ALFA(165),\n     3     ALFA(166), ALFA(167), ALFA(168), ALFA(169), ALFA(170)/\n     4     1.92821964248775885D-03,     1.35592576302022234D-03,\n     5    -7.17858090421302995D-04,    -2.58084802575270346D-03,\n     6    -3.49271130826168475D-03,    -3.46986299340960628D-03,\n     7    -2.82285233351310182D-03,    -1.88103076404891354D-03,\n     8    -8.89531718383947600D-04,     3.87912102631035228D-06,\n     9     7.28688540119691412D-04,     1.26566373053457758D-03,\n     A     1.62518158372674427D-03,     1.83203153216373172D-03,\n     B     1.91588388990527909D-03,     1.90588846755546138D-03,\n     C     1.82798982421825727D-03,     1.70389506421121530D-03,\n     D     1.55097127171097686D-03,     1.38261421852276159D-03/\n      DATA ALFA(171), ALFA(172), ALFA(173), ALFA(174), ALFA(175),\n     1     ALFA(176), ALFA(177), ALFA(178), ALFA(179), ALFA(180)/\n     2     1.20881424230064774D-03,     1.03676532638344962D-03,\n     3     8.71437918068619115D-04,     7.16080155297701002D-04,\n     4     5.72637002558129372D-04,     4.42089819465802277D-04,\n     5     3.24724948503090564D-04,     2.20342042730246599D-04,\n     6     1.28412898401353882D-04,     4.82005924552095464D-05/\n      DATA BETA(1), BETA(2), BETA(3), BETA(4), BETA(5), BETA(6),\n     1     BETA(7), BETA(8), BETA(9), BETA(10), BETA(11), BETA(12),\n     2     BETA(13), BETA(14), BETA(15), BETA(16), BETA(17), BETA(18),\n     3     BETA(19), BETA(20), BETA(21), BETA(22)/\n     4     1.79988721413553309D-02,     5.59964911064388073D-03,\n     5     2.88501402231132779D-03,     1.80096606761053941D-03,\n     6     1.24753110589199202D-03,     9.22878876572938311D-04,\n     7     7.14430421727287357D-04,     5.71787281789704872D-04,\n     8     4.69431007606481533D-04,     3.93232835462916638D-04,\n     9     3.34818889318297664D-04,     2.88952148495751517D-04,\n     A     2.52211615549573284D-04,     2.22280580798883327D-04,\n     B     1.97541838033062524D-04,     1.76836855019718004D-04,\n     C     1.59316899661821081D-04,     1.44347930197333986D-04,\n     D     1.31448068119965379D-04,     1.20245444949302884D-04,\n     E     1.10449144504599392D-04,     1.01828770740567258D-04/\n      DATA BETA(23), BETA(24), BETA(25), BETA(26), BETA(27), BETA(28),\n     1     BETA(29), BETA(30), BETA(31), BETA(32), BETA(33), BETA(34),\n     2     BETA(35), BETA(36), BETA(37), BETA(38), BETA(39), BETA(40),\n     3     BETA(41), BETA(42), BETA(43), BETA(44)/\n     4     9.41998224204237509D-05,     8.74130545753834437D-05,\n     5     8.13466262162801467D-05,     7.59002269646219339D-05,\n     6     7.09906300634153481D-05,     6.65482874842468183D-05,\n     7     6.25146958969275078D-05,     5.88403394426251749D-05,\n     8    -1.49282953213429172D-03,    -8.78204709546389328D-04,\n     9    -5.02916549572034614D-04,    -2.94822138512746025D-04,\n     A    -1.75463996970782828D-04,    -1.04008550460816434D-04,\n     B    -5.96141953046457895D-05,    -3.12038929076098340D-05,\n     C    -1.26089735980230047D-05,    -2.42892608575730389D-07,\n     D     8.05996165414273571D-06,     1.36507009262147391D-05,\n     E     1.73964125472926261D-05,     1.98672978842133780D-05/\n      DATA BETA(45), BETA(46), BETA(47), BETA(48), BETA(49), BETA(50),\n     1     BETA(51), BETA(52), BETA(53), BETA(54), BETA(55), BETA(56),\n     2     BETA(57), BETA(58), BETA(59), BETA(60), BETA(61), BETA(62),\n     3     BETA(63), BETA(64), BETA(65), BETA(66)/\n     4     2.14463263790822639D-05,     2.23954659232456514D-05,\n     5     2.28967783814712629D-05,     2.30785389811177817D-05,\n     6     2.30321976080909144D-05,     2.28236073720348722D-05,\n     7     2.25005881105292418D-05,     2.20981015361991429D-05,\n     8     2.16418427448103905D-05,     2.11507649256220843D-05,\n     9     2.06388749782170737D-05,     2.01165241997081666D-05,\n     A     1.95913450141179244D-05,     1.90689367910436740D-05,\n     B     1.85533719641636667D-05,     1.80475722259674218D-05,\n     C     5.52213076721292790D-04,     4.47932581552384646D-04,\n     D     2.79520653992020589D-04,     1.52468156198446602D-04,\n     E     6.93271105657043598D-05,     1.76258683069991397D-05/\n      DATA BETA(67), BETA(68), BETA(69), BETA(70), BETA(71), BETA(72),\n     1     BETA(73), BETA(74), BETA(75), BETA(76), BETA(77), BETA(78),\n     2     BETA(79), BETA(80), BETA(81), BETA(82), BETA(83), BETA(84),\n     3     BETA(85), BETA(86), BETA(87), BETA(88)/\n     4    -1.35744996343269136D-05,    -3.17972413350427135D-05,\n     5    -4.18861861696693365D-05,    -4.69004889379141029D-05,\n     6    -4.87665447413787352D-05,    -4.87010031186735069D-05,\n     7    -4.74755620890086638D-05,    -4.55813058138628452D-05,\n     8    -4.33309644511266036D-05,    -4.09230193157750364D-05,\n     9    -3.84822638603221274D-05,    -3.60857167535410501D-05,\n     A    -3.37793306123367417D-05,    -3.15888560772109621D-05,\n     B    -2.95269561750807315D-05,    -2.75978914828335759D-05,\n     C    -2.58006174666883713D-05,    -2.41308356761280200D-05,\n     D    -2.25823509518346033D-05,    -2.11479656768912971D-05,\n     E    -1.98200638885294927D-05,    -1.85909870801065077D-05/\n      DATA BETA(89), BETA(90), BETA(91), BETA(92), BETA(93), BETA(94),\n     1     BETA(95), BETA(96), BETA(97), BETA(98), BETA(99), BETA(100),\n     2     BETA(101), BETA(102), BETA(103), BETA(104), BETA(105),\n     3     BETA(106), BETA(107), BETA(108), BETA(109), BETA(110)/\n     4    -1.74532699844210224D-05,    -1.63997823854497997D-05,\n     5    -4.74617796559959808D-04,    -4.77864567147321487D-04,\n     6    -3.20390228067037603D-04,    -1.61105016119962282D-04,\n     7    -4.25778101285435204D-05,     3.44571294294967503D-05,\n     8     7.97092684075674924D-05,     1.03138236708272200D-04,\n     9     1.12466775262204158D-04,     1.13103642108481389D-04,\n     A     1.08651634848774268D-04,     1.01437951597661973D-04,\n     B     9.29298396593363896D-05,     8.40293133016089978D-05,\n     C     7.52727991349134062D-05,     6.69632521975730872D-05,\n     D     5.92564547323194704D-05,     5.22169308826975567D-05,\n     E     4.58539485165360646D-05,     4.01445513891486808D-05/\n      DATA BETA(111), BETA(112), BETA(113), BETA(114), BETA(115),\n     1     BETA(116), BETA(117), BETA(118), BETA(119), BETA(120),\n     2     BETA(121), BETA(122), BETA(123), BETA(124), BETA(125),\n     3     BETA(126), BETA(127), BETA(128), BETA(129), BETA(130)/\n     4     3.50481730031328081D-05,     3.05157995034346659D-05,\n     5     2.64956119950516039D-05,     2.29363633690998152D-05,\n     6     1.97893056664021636D-05,     1.70091984636412623D-05,\n     7     1.45547428261524004D-05,     1.23886640995878413D-05,\n     8     1.04775876076583236D-05,     8.79179954978479373D-06,\n     9     7.36465810572578444D-04,     8.72790805146193976D-04,\n     A     6.22614862573135066D-04,     2.85998154194304147D-04,\n     B     3.84737672879366102D-06,    -1.87906003636971558D-04,\n     C    -2.97603646594554535D-04,    -3.45998126832656348D-04,\n     D    -3.53382470916037712D-04,    -3.35715635775048757D-04/\n      DATA BETA(131), BETA(132), BETA(133), BETA(134), BETA(135),\n     1     BETA(136), BETA(137), BETA(138), BETA(139), BETA(140),\n     2     BETA(141), BETA(142), BETA(143), BETA(144), BETA(145),\n     3     BETA(146), BETA(147), BETA(148), BETA(149), BETA(150)/\n     4    -3.04321124789039809D-04,    -2.66722723047612821D-04,\n     5    -2.27654214122819527D-04,    -1.89922611854562356D-04,\n     6    -1.55058918599093870D-04,    -1.23778240761873630D-04,\n     7    -9.62926147717644187D-05,    -7.25178327714425337D-05,\n     8    -5.22070028895633801D-05,    -3.50347750511900522D-05,\n     9    -2.06489761035551757D-05,    -8.70106096849767054D-06,\n     A     1.13698686675100290D-06,     9.16426474122778849D-06,\n     B     1.56477785428872620D-05,     2.08223629482466847D-05,\n     C     2.48923381004595156D-05,     2.80340509574146325D-05,\n     D     3.03987774629861915D-05,     3.21156731406700616D-05/\n      DATA BETA(151), BETA(152), BETA(153), BETA(154), BETA(155),\n     1     BETA(156), BETA(157), BETA(158), BETA(159), BETA(160),\n     2     BETA(161), BETA(162), BETA(163), BETA(164), BETA(165),\n     3     BETA(166), BETA(167), BETA(168), BETA(169), BETA(170)/\n     4    -1.80182191963885708D-03,    -2.43402962938042533D-03,\n     5    -1.83422663549856802D-03,    -7.62204596354009765D-04,\n     6     2.39079475256927218D-04,     9.49266117176881141D-04,\n     7     1.34467449701540359D-03,     1.48457495259449178D-03,\n     8     1.44732339830617591D-03,     1.30268261285657186D-03,\n     9     1.10351597375642682D-03,     8.86047440419791759D-04,\n     A     6.73073208165665473D-04,     4.77603872856582378D-04,\n     B     3.05991926358789362D-04,     1.60315694594721630D-04,\n     C     4.00749555270613286D-05,    -5.66607461635251611D-05,\n     D    -1.32506186772982638D-04,    -1.90296187989614057D-04/\n      DATA BETA(171), BETA(172), BETA(173), BETA(174), BETA(175),\n     1     BETA(176), BETA(177), BETA(178), BETA(179), BETA(180),\n     2     BETA(181), BETA(182), BETA(183), BETA(184), BETA(185),\n     3     BETA(186), BETA(187), BETA(188), BETA(189), BETA(190)/\n     4    -2.32811450376937408D-04,    -2.62628811464668841D-04,\n     5    -2.82050469867598672D-04,    -2.93081563192861167D-04,\n     6    -2.97435962176316616D-04,    -2.96557334239348078D-04,\n     7    -2.91647363312090861D-04,    -2.83696203837734166D-04,\n     8    -2.73512317095673346D-04,    -2.61750155806768580D-04,\n     9     6.38585891212050914D-03,     9.62374215806377941D-03,\n     A     7.61878061207001043D-03,     2.83219055545628054D-03,\n     B    -2.09841352012720090D-03,    -5.73826764216626498D-03,\n     C    -7.70804244495414620D-03,    -8.21011692264844401D-03,\n     D    -7.65824520346905413D-03,    -6.47209729391045177D-03/\n      DATA BETA(191), BETA(192), BETA(193), BETA(194), BETA(195),\n     1     BETA(196), BETA(197), BETA(198), BETA(199), BETA(200),\n     2     BETA(201), BETA(202), BETA(203), BETA(204), BETA(205),\n     3     BETA(206), BETA(207), BETA(208), BETA(209), BETA(210)/\n     4    -4.99132412004966473D-03,    -3.45612289713133280D-03,\n     5    -2.01785580014170775D-03,    -7.59430686781961401D-04,\n     6     2.84173631523859138D-04,     1.10891667586337403D-03,\n     7     1.72901493872728771D-03,     2.16812590802684701D-03,\n     8     2.45357710494539735D-03,     2.61281821058334862D-03,\n     9     2.67141039656276912D-03,     2.65203073395980430D-03,\n     A     2.57411652877287315D-03,     2.45389126236094427D-03,\n     B     2.30460058071795494D-03,     2.13684837686712662D-03,\n     C     1.95896528478870911D-03,     1.77737008679454412D-03,\n     D     1.59690280765839059D-03,     1.42111975664438546D-03/\n      DATA GAMA(1), GAMA(2), GAMA(3), GAMA(4), GAMA(5), GAMA(6),\n     1     GAMA(7), GAMA(8), GAMA(9), GAMA(10), GAMA(11), GAMA(12),\n     2     GAMA(13), GAMA(14), GAMA(15), GAMA(16), GAMA(17), GAMA(18),\n     3     GAMA(19), GAMA(20), GAMA(21), GAMA(22)/\n     4     6.29960524947436582D-01,     2.51984209978974633D-01,\n     5     1.54790300415655846D-01,     1.10713062416159013D-01,\n     6     8.57309395527394825D-02,     6.97161316958684292D-02,\n     7     5.86085671893713576D-02,     5.04698873536310685D-02,\n     8     4.42600580689154809D-02,     3.93720661543509966D-02,\n     9     3.54283195924455368D-02,     3.21818857502098231D-02,\n     A     2.94646240791157679D-02,     2.71581677112934479D-02,\n     B     2.51768272973861779D-02,     2.34570755306078891D-02,\n     C     2.19508390134907203D-02,     2.06210828235646240D-02,\n     D     1.94388240897880846D-02,     1.83810633800683158D-02,\n     E     1.74293213231963172D-02,     1.65685837786612353D-02/\n      DATA GAMA(23), GAMA(24), GAMA(25), GAMA(26), GAMA(27), GAMA(28),\n     1     GAMA(29), GAMA(30)/\n     2     1.57865285987918445D-02,     1.50729501494095594D-02,\n     3     1.44193250839954639D-02,     1.38184805735341786D-02,\n     4     1.32643378994276568D-02,     1.27517121970498651D-02,\n     5     1.22761545318762767D-02,     1.18338262398482403D-02/\n      DATA EX1, EX2, HPI, GPI, THPI /\n     1     3.33333333333333333D-01,     6.66666666666666667D-01,\n     2     1.57079632679489662D+00,     3.14159265358979324D+00,\n     3     4.71238898038468986D+00/\n      DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 /\nC\n      RFNU = 1.0D0/FNU\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST (Z/FNU TOO SMALL)\nC-----------------------------------------------------------------------\n      TEST = D1MACH(1)*1.0D+3\n      AC = FNU*TEST\n      IF (DABS(ZR).GT.AC .OR. DABS(ZI).GT.AC) GO TO 15\n      ZETA1R = 2.0D0*DABS(DLOG(TEST))+FNU\n      ZETA1I = 0.0D0\n      ZETA2R = FNU\n      ZETA2I = 0.0D0\n      PHIR = 1.0D0\n      PHII = 0.0D0\n      ARGR = 1.0D0\n      ARGI = 0.0D0\n      RETURN\n   15 CONTINUE\n      ZBR = ZR*RFNU\n      ZBI = ZI*RFNU\n      RFNU2 = RFNU*RFNU\nC-----------------------------------------------------------------------\nC     COMPUTE IN THE FOURTH QUADRANT\nC-----------------------------------------------------------------------\n      FN13 = FNU**EX1\n      FN23 = FN13*FN13\n      RFN13 = 1.0D0/FN13\n      W2R = CONER - ZBR*ZBR + ZBI*ZBI\n      W2I = CONEI - ZBR*ZBI - ZBR*ZBI\n      AW2 = XZABS(W2R,W2I)\n      IF (AW2.GT.0.25D0) GO TO 130\nC-----------------------------------------------------------------------\nC     POWER SERIES FOR CABS(W2).LE.0.25D0\nC-----------------------------------------------------------------------\n      K = 1\n      PR(1) = CONER\n      PI(1) = CONEI\n      SUMAR = GAMA(1)\n      SUMAI = ZEROI\n      AP(1) = 1.0D0\n      IF (AW2.LT.TOL) GO TO 20\n      DO 10 K=2,30\n        PR(K) = PR(K-1)*W2R - PI(K-1)*W2I\n        PI(K) = PR(K-1)*W2I + PI(K-1)*W2R\n        SUMAR = SUMAR + PR(K)*GAMA(K)\n        SUMAI = SUMAI + PI(K)*GAMA(K)\n        AP(K) = AP(K-1)*AW2\n        IF (AP(K).LT.TOL) GO TO 20\n   10 CONTINUE\n      K = 30\n   20 CONTINUE\n      KMAX = K\n      ZETAR = W2R*SUMAR - W2I*SUMAI\n      ZETAI = W2R*SUMAI + W2I*SUMAR\n      ARGR = ZETAR*FN23\n      ARGI = ZETAI*FN23\n      CALL XZSQRT(SUMAR, SUMAI, ZAR, ZAI)\n      CALL XZSQRT(W2R, W2I, STR, STI)\n      ZETA2R = STR*FNU\n      ZETA2I = STI*FNU\n      STR = CONER + EX2*(ZETAR*ZAR-ZETAI*ZAI)\n      STI = CONEI + EX2*(ZETAR*ZAI+ZETAI*ZAR)\n      ZETA1R = STR*ZETA2R - STI*ZETA2I\n      ZETA1I = STR*ZETA2I + STI*ZETA2R\n      ZAR = ZAR + ZAR\n      ZAI = ZAI + ZAI\n      CALL XZSQRT(ZAR, ZAI, STR, STI)\n      PHIR = STR*RFN13\n      PHII = STI*RFN13\n      IF (IPMTR.EQ.1) GO TO 120\nC-----------------------------------------------------------------------\nC     SUM SERIES FOR ASUM AND BSUM\nC-----------------------------------------------------------------------\n      SUMBR = ZEROR\n      SUMBI = ZEROI\n      DO 30 K=1,KMAX\n        SUMBR = SUMBR + PR(K)*BETA(K)\n        SUMBI = SUMBI + PI(K)*BETA(K)\n   30 CONTINUE\n      ASUMR = ZEROR\n      ASUMI = ZEROI\n      BSUMR = SUMBR\n      BSUMI = SUMBI\n      L1 = 0\n      L2 = 30\n      BTOL = TOL*(DABS(BSUMR)+DABS(BSUMI))\n      ATOL = TOL\n      PP = 1.0D0\n      IAS = 0\n      IBS = 0\n      IF (RFNU2.LT.TOL) GO TO 110\n      DO 100 IS=2,7\n        ATOL = ATOL/RFNU2\n        PP = PP*RFNU2\n        IF (IAS.EQ.1) GO TO 60\n        SUMAR = ZEROR\n        SUMAI = ZEROI\n        DO 40 K=1,KMAX\n          M = L1 + K\n          SUMAR = SUMAR + PR(K)*ALFA(M)\n          SUMAI = SUMAI + PI(K)*ALFA(M)\n          IF (AP(K).LT.ATOL) GO TO 50\n   40   CONTINUE\n   50   CONTINUE\n        ASUMR = ASUMR + SUMAR*PP\n        ASUMI = ASUMI + SUMAI*PP\n        IF (PP.LT.TOL) IAS = 1\n   60   CONTINUE\n        IF (IBS.EQ.1) GO TO 90\n        SUMBR = ZEROR\n        SUMBI = ZEROI\n        DO 70 K=1,KMAX\n          M = L2 + K\n          SUMBR = SUMBR + PR(K)*BETA(M)\n          SUMBI = SUMBI + PI(K)*BETA(M)\n          IF (AP(K).LT.ATOL) GO TO 80\n   70   CONTINUE\n   80   CONTINUE\n        BSUMR = BSUMR + SUMBR*PP\n        BSUMI = BSUMI + SUMBI*PP\n        IF (PP.LT.BTOL) IBS = 1\n   90   CONTINUE\n        IF (IAS.EQ.1 .AND. IBS.EQ.1) GO TO 110\n        L1 = L1 + 30\n        L2 = L2 + 30\n  100 CONTINUE\n  110 CONTINUE\n      ASUMR = ASUMR + CONER\n      PP = RFNU*RFN13\n      BSUMR = BSUMR*PP\n      BSUMI = BSUMI*PP\n  120 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     CABS(W2).GT.0.25D0\nC-----------------------------------------------------------------------\n  130 CONTINUE\n      CALL XZSQRT(W2R, W2I, WR, WI)\n      IF (WR.LT.0.0D0) WR = 0.0D0\n      IF (WI.LT.0.0D0) WI = 0.0D0\n      STR = CONER + WR\n      STI = WI\n      CALL ZDIV(STR, STI, ZBR, ZBI, ZAR, ZAI)\n      CALL XZLOG(ZAR, ZAI, ZCR, ZCI, IDUM)\n      IF (ZCI.LT.0.0D0) ZCI = 0.0D0\n      IF (ZCI.GT.HPI) ZCI = HPI\n      IF (ZCR.LT.0.0D0) ZCR = 0.0D0\n      ZTHR = (ZCR-WR)*1.5D0\n      ZTHI = (ZCI-WI)*1.5D0\n      ZETA1R = ZCR*FNU\n      ZETA1I = ZCI*FNU\n      ZETA2R = WR*FNU\n      ZETA2I = WI*FNU\n      AZTH = XZABS(ZTHR,ZTHI)\n      ANG = THPI\n      IF (ZTHR.GE.0.0D0 .AND. ZTHI.LT.0.0D0) GO TO 140\n      ANG = HPI\n      IF (ZTHR.EQ.0.0D0) GO TO 140\n      ANG = DATAN(ZTHI/ZTHR)\n      IF (ZTHR.LT.0.0D0) ANG = ANG + GPI\n  140 CONTINUE\n      PP = AZTH**EX2\n      ANG = ANG*EX2\n      ZETAR = PP*DCOS(ANG)\n      ZETAI = PP*DSIN(ANG)\n      IF (ZETAI.LT.0.0D0) ZETAI = 0.0D0\n      ARGR = ZETAR*FN23\n      ARGI = ZETAI*FN23\n      CALL ZDIV(ZTHR, ZTHI, ZETAR, ZETAI, RTZTR, RTZTI)\n      CALL ZDIV(RTZTR, RTZTI, WR, WI, ZAR, ZAI)\n      TZAR = ZAR + ZAR\n      TZAI = ZAI + ZAI\n      CALL XZSQRT(TZAR, TZAI, STR, STI)\n      PHIR = STR*RFN13\n      PHII = STI*RFN13\n      IF (IPMTR.EQ.1) GO TO 120\n      RAW = 1.0D0/DSQRT(AW2)\n      STR = WR*RAW\n      STI = -WI*RAW\n      TFNR = STR*RFNU*RAW\n      TFNI = STI*RFNU*RAW\n      RAZTH = 1.0D0/AZTH\n      STR = ZTHR*RAZTH\n      STI = -ZTHI*RAZTH\n      RZTHR = STR*RAZTH*RFNU\n      RZTHI = STI*RAZTH*RFNU\n      ZCR = RZTHR*AR(2)\n      ZCI = RZTHI*AR(2)\n      RAW2 = 1.0D0/AW2\n      STR = W2R*RAW2\n      STI = -W2I*RAW2\n      T2R = STR*RAW2\n      T2I = STI*RAW2\n      STR = T2R*C(2) + C(3)\n      STI = T2I*C(2)\n      UPR(2) = STR*TFNR - STI*TFNI\n      UPI(2) = STR*TFNI + STI*TFNR\n      BSUMR = UPR(2) + ZCR\n      BSUMI = UPI(2) + ZCI\n      ASUMR = ZEROR\n      ASUMI = ZEROI\n      IF (RFNU.LT.TOL) GO TO 220\n      PRZTHR = RZTHR\n      PRZTHI = RZTHI\n      PTFNR = TFNR\n      PTFNI = TFNI\n      UPR(1) = CONER\n      UPI(1) = CONEI\n      PP = 1.0D0\n      BTOL = TOL*(DABS(BSUMR)+DABS(BSUMI))\n      KS = 0\n      KP1 = 2\n      L = 3\n      IAS = 0\n      IBS = 0\n      DO 210 LR=2,12,2\n        LRP1 = LR + 1\nC-----------------------------------------------------------------------\nC     COMPUTE TWO ADDITIONAL CR, DR, AND UP FOR TWO MORE TERMS IN\nC     NEXT SUMA AND SUMB\nC-----------------------------------------------------------------------\n        DO 160 K=LR,LRP1\n          KS = KS + 1\n          KP1 = KP1 + 1\n          L = L + 1\n          ZAR = C(L)\n          ZAI = ZEROI\n          DO 150 J=2,KP1\n            L = L + 1\n            STR = ZAR*T2R - T2I*ZAI + C(L)\n            ZAI = ZAR*T2I + ZAI*T2R\n            ZAR = STR\n  150     CONTINUE\n          STR = PTFNR*TFNR - PTFNI*TFNI\n          PTFNI = PTFNR*TFNI + PTFNI*TFNR\n          PTFNR = STR\n          UPR(KP1) = PTFNR*ZAR - PTFNI*ZAI\n          UPI(KP1) = PTFNI*ZAR + PTFNR*ZAI\n          CRR(KS) = PRZTHR*BR(KS+1)\n          CRI(KS) = PRZTHI*BR(KS+1)\n          STR = PRZTHR*RZTHR - PRZTHI*RZTHI\n          PRZTHI = PRZTHR*RZTHI + PRZTHI*RZTHR\n          PRZTHR = STR\n          DRR(KS) = PRZTHR*AR(KS+2)\n          DRI(KS) = PRZTHI*AR(KS+2)\n  160   CONTINUE\n        PP = PP*RFNU2\n        IF (IAS.EQ.1) GO TO 180\n        SUMAR = UPR(LRP1)\n        SUMAI = UPI(LRP1)\n        JU = LRP1\n        DO 170 JR=1,LR\n          JU = JU - 1\n          SUMAR = SUMAR + CRR(JR)*UPR(JU) - CRI(JR)*UPI(JU)\n          SUMAI = SUMAI + CRR(JR)*UPI(JU) + CRI(JR)*UPR(JU)\n  170   CONTINUE\n        ASUMR = ASUMR + SUMAR\n        ASUMI = ASUMI + SUMAI\n        TEST = DABS(SUMAR) + DABS(SUMAI)\n        IF (PP.LT.TOL .AND. TEST.LT.TOL) IAS = 1\n  180   CONTINUE\n        IF (IBS.EQ.1) GO TO 200\n        SUMBR = UPR(LR+2) + UPR(LRP1)*ZCR - UPI(LRP1)*ZCI\n        SUMBI = UPI(LR+2) + UPR(LRP1)*ZCI + UPI(LRP1)*ZCR\n        JU = LRP1\n        DO 190 JR=1,LR\n          JU = JU - 1\n          SUMBR = SUMBR + DRR(JR)*UPR(JU) - DRI(JR)*UPI(JU)\n          SUMBI = SUMBI + DRR(JR)*UPI(JU) + DRI(JR)*UPR(JU)\n  190   CONTINUE\n        BSUMR = BSUMR + SUMBR\n        BSUMI = BSUMI + SUMBI\n        TEST = DABS(SUMBR) + DABS(SUMBI)\n        IF (PP.LT.BTOL .AND. TEST.LT.BTOL) IBS = 1\n  200   CONTINUE\n        IF (IAS.EQ.1 .AND. IBS.EQ.1) GO TO 220\n  210 CONTINUE\n  220 CONTINUE\n      ASUMR = ASUMR + CONER\n      STR = -BSUMR*RFN13\n      STI = -BSUMI*RFN13\n      CALL ZDIV(STR, STI, RTZTR, RTZTI, BSUMR, BSUMI)\n      GO TO 120\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zuni1.f",
    "content": "      SUBROUTINE ZUNI1(ZR, ZI, FNU, KODE, N, YR, YI, NZ, NLAST, FNUL,\n     * TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  ZUNI1\nC***REFER TO  ZBESI,ZBESK\nC\nC     ZUNI1 COMPUTES I(FNU,Z)  BY MEANS OF THE UNIFORM ASYMPTOTIC\nC     EXPANSION FOR I(FNU,Z) IN -PI/3.LE.ARG Z.LE.PI/3.\nC\nC     FNUL IS THE SMALLEST ORDER PERMITTED FOR THE ASYMPTOTIC\nC     EXPANSION. NLAST=0 MEANS ALL OF THE Y VALUES WERE SET.\nC     NLAST.NE.0 IS THE NUMBER LEFT TO BE COMPUTED BY ANOTHER\nC     FORMULA FOR ORDERS FNU TO FNU+NLAST-1 BECAUSE FNU+NLAST-1.LT.FNUL.\nC     Y(I)=CZERO FOR I=NLAST+1,N\nC\nC***ROUTINES CALLED  ZUCHK,ZUNIK,ZUOIK,D1MACH,XZABS\nC***END PROLOGUE  ZUNI1\nC     COMPLEX CFN,CONE,CRSC,CSCL,CSR,CSS,CWRK,CZERO,C1,C2,PHI,RZ,SUM,S1,\nC    *S2,Y,Z,ZETA1,ZETA2\n      DOUBLE PRECISION ALIM, APHI, ASCLE, BRY, CONER, CRSC,\n     * CSCL, CSRR, CSSR, CWRKI, CWRKR, C1R, C2I, C2M, C2R, ELIM, FN,\n     * FNU, FNUL, PHII, PHIR, RAST, RS1, RZI, RZR, STI, STR, SUMI,\n     * SUMR, S1I, S1R, S2I, S2R, TOL, YI, YR, ZEROI, ZEROR, ZETA1I,\n     * ZETA1R, ZETA2I, ZETA2R, ZI, ZR, CYR, CYI, D1MACH, XZABS\n      INTEGER I, IFLAG, INIT, K, KODE, M, N, ND, NLAST, NN, NUF, NW, NZ\n      DIMENSION BRY(3), YR(N), YI(N), CWRKR(16), CWRKI(16), CSSR(3),\n     * CSRR(3), CYR(2), CYI(2)\n      DATA ZEROR,ZEROI,CONER / 0.0D0, 0.0D0, 1.0D0 /\nC\n      NZ = 0\n      ND = N\n      NLAST = 0\nC-----------------------------------------------------------------------\nC     COMPUTED VALUES WITH EXPONENTS BETWEEN ALIM AND ELIM IN MAG-\nC     NITUDE ARE SCALED TO KEEP INTERMEDIATE ARITHMETIC ON SCALE,\nC     EXP(ALIM)=EXP(ELIM)*TOL\nC-----------------------------------------------------------------------\n      CSCL = 1.0D0/TOL\n      CRSC = TOL\n      CSSR(1) = CSCL\n      CSSR(2) = CONER\n      CSSR(3) = CRSC\n      CSRR(1) = CRSC\n      CSRR(2) = CONER\n      CSRR(3) = CSCL\n      BRY(1) = 1.0D+3*D1MACH(1)/TOL\nC-----------------------------------------------------------------------\nC     CHECK FOR UNDERFLOW AND OVERFLOW ON FIRST MEMBER\nC-----------------------------------------------------------------------\n      FN = DMAX1(FNU,1.0D0)\n      INIT = 0\n      CALL ZUNIK(ZR, ZI, FN, 1, 1, TOL, INIT, PHIR, PHII, ZETA1R,\n     * ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI)\n      IF (KODE.EQ.1) GO TO 10\n      STR = ZR + ZETA2R\n      STI = ZI + ZETA2I\n      RAST = FN/XZABS(STR,STI)\n      STR = STR*RAST*RAST\n      STI = -STI*RAST*RAST\n      S1R = -ZETA1R + STR\n      S1I = -ZETA1I + STI\n      GO TO 20\n   10 CONTINUE\n      S1R = -ZETA1R + ZETA2R\n      S1I = -ZETA1I + ZETA2I\n   20 CONTINUE\n      RS1 = S1R\n      IF (DABS(RS1).GT.ELIM) GO TO 130\n   30 CONTINUE\n      NN = MIN0(2,ND)\n      DO 80 I=1,NN\n        FN = FNU + DBLE(FLOAT(ND-I))\n        INIT = 0\n        CALL ZUNIK(ZR, ZI, FN, 1, 0, TOL, INIT, PHIR, PHII, ZETA1R,\n     *   ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI)\n        IF (KODE.EQ.1) GO TO 40\n        STR = ZR + ZETA2R\n        STI = ZI + ZETA2I\n        RAST = FN/XZABS(STR,STI)\n        STR = STR*RAST*RAST\n        STI = -STI*RAST*RAST\n        S1R = -ZETA1R + STR\n        S1I = -ZETA1I + STI + ZI\n        GO TO 50\n   40   CONTINUE\n        S1R = -ZETA1R + ZETA2R\n        S1I = -ZETA1I + ZETA2I\n   50   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = S1R\n        IF (DABS(RS1).GT.ELIM) GO TO 110\n        IF (I.EQ.1) IFLAG = 2\n        IF (DABS(RS1).LT.ALIM) GO TO 60\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = XZABS(PHIR,PHII)\n        RS1 = RS1 + DLOG(APHI)\n        IF (DABS(RS1).GT.ELIM) GO TO 110\n        IF (I.EQ.1) IFLAG = 1\n        IF (RS1.LT.0.0D0) GO TO 60\n        IF (I.EQ.1) IFLAG = 3\n   60   CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE S1 IF CABS(S1).LT.ASCLE\nC-----------------------------------------------------------------------\n        S2R = PHIR*SUMR - PHII*SUMI\n        S2I = PHIR*SUMI + PHII*SUMR\n        STR = DEXP(S1R)*CSSR(IFLAG)\n        S1R = STR*DCOS(S1I)\n        S1I = STR*DSIN(S1I)\n        STR = S2R*S1R - S2I*S1I\n        S2I = S2R*S1I + S2I*S1R\n        S2R = STR\n        IF (IFLAG.NE.1) GO TO 70\n        CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL)\n        IF (NW.NE.0) GO TO 110\n   70   CONTINUE\n        CYR(I) = S2R\n        CYI(I) = S2I\n        M = ND - I + 1\n        YR(M) = S2R*CSRR(IFLAG)\n        YI(M) = S2I*CSRR(IFLAG)\n   80 CONTINUE\n      IF (ND.LE.2) GO TO 100\n      RAST = 1.0D0/XZABS(ZR,ZI)\n      STR = ZR*RAST\n      STI = -ZI*RAST\n      RZR = (STR+STR)*RAST\n      RZI = (STI+STI)*RAST\n      BRY(2) = 1.0D0/BRY(1)\n      BRY(3) = D1MACH(2)\n      S1R = CYR(1)\n      S1I = CYI(1)\n      S2R = CYR(2)\n      S2I = CYI(2)\n      C1R = CSRR(IFLAG)\n      ASCLE = BRY(IFLAG)\n      K = ND - 2\n      FN = DBLE(FLOAT(K))\n      DO 90 I=3,ND\n        C2R = S2R\n        C2I = S2I\n        S2R = S1R + (FNU+FN)*(RZR*C2R-RZI*C2I)\n        S2I = S1I + (FNU+FN)*(RZR*C2I+RZI*C2R)\n        S1R = C2R\n        S1I = C2I\n        C2R = S2R*C1R\n        C2I = S2I*C1R\n        YR(K) = C2R\n        YI(K) = C2I\n        K = K - 1\n        FN = FN - 1.0D0\n        IF (IFLAG.GE.3) GO TO 90\n        STR = DABS(C2R)\n        STI = DABS(C2I)\n        C2M = DMAX1(STR,STI)\n        IF (C2M.LE.ASCLE) GO TO 90\n        IFLAG = IFLAG + 1\n        ASCLE = BRY(IFLAG)\n        S1R = S1R*C1R\n        S1I = S1I*C1R\n        S2R = C2R\n        S2I = C2I\n        S1R = S1R*CSSR(IFLAG)\n        S1I = S1I*CSSR(IFLAG)\n        S2R = S2R*CSSR(IFLAG)\n        S2I = S2I*CSSR(IFLAG)\n        C1R = CSRR(IFLAG)\n   90 CONTINUE\n  100 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     SET UNDERFLOW AND UPDATE PARAMETERS\nC-----------------------------------------------------------------------\n  110 CONTINUE\n      IF (RS1.GT.0.0D0) GO TO 120\n      YR(ND) = ZEROR\n      YI(ND) = ZEROI\n      NZ = NZ + 1\n      ND = ND - 1\n      IF (ND.EQ.0) GO TO 100\n      CALL ZUOIK(ZR, ZI, FNU, KODE, 1, ND, YR, YI, NUF, TOL, ELIM, ALIM)\n      IF (NUF.LT.0) GO TO 120\n      ND = ND - NUF\n      NZ = NZ + NUF\n      IF (ND.EQ.0) GO TO 100\n      FN = FNU + DBLE(FLOAT(ND-1))\n      IF (FN.GE.FNUL) GO TO 30\n      NLAST = ND\n      RETURN\n  120 CONTINUE\n      NZ = -1\n      RETURN\n  130 CONTINUE\n      IF (RS1.GT.0.0D0) GO TO 120\n      NZ = N\n      DO 140 I=1,N\n        YR(I) = ZEROR\n        YI(I) = ZEROI\n  140 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zuni2.f",
    "content": "      SUBROUTINE ZUNI2(ZR, ZI, FNU, KODE, N, YR, YI, NZ, NLAST, FNUL,\n     * TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  ZUNI2\nC***REFER TO  ZBESI,ZBESK\nC\nC     ZUNI2 COMPUTES I(FNU,Z) IN THE RIGHT HALF PLANE BY MEANS OF\nC     UNIFORM ASYMPTOTIC EXPANSION FOR J(FNU,ZN) WHERE ZN IS Z*I\nC     OR -Z*I AND ZN IS IN THE RIGHT HALF PLANE ALSO.\nC\nC     FNUL IS THE SMALLEST ORDER PERMITTED FOR THE ASYMPTOTIC\nC     EXPANSION. NLAST=0 MEANS ALL OF THE Y VALUES WERE SET.\nC     NLAST.NE.0 IS THE NUMBER LEFT TO BE COMPUTED BY ANOTHER\nC     FORMULA FOR ORDERS FNU TO FNU+NLAST-1 BECAUSE FNU+NLAST-1.LT.FNUL.\nC     Y(I)=CZERO FOR I=NLAST+1,N\nC\nC***ROUTINES CALLED  ZAIRY,ZUCHK,ZUNHJ,ZUOIK,D1MACH,XZABS\nC***END PROLOGUE  ZUNI2\nC     COMPLEX AI,ARG,ASUM,BSUM,CFN,CI,CID,CIP,CONE,CRSC,CSCL,CSR,CSS,\nC    *CZERO,C1,C2,DAI,PHI,RZ,S1,S2,Y,Z,ZB,ZETA1,ZETA2,ZN\n      DOUBLE PRECISION AARG, AIC, AII, AIR, ALIM, ANG, APHI, ARGI,\n     * ARGR, ASCLE, ASUMI, ASUMR, BRY, BSUMI, BSUMR, CIDI, CIPI, CIPR,\n     * CONER, CRSC, CSCL, CSRR, CSSR, C1R, C2I, C2M, C2R, DAII,\n     * DAIR, ELIM, FN, FNU, FNUL, HPI, PHII, PHIR, RAST, RAZ, RS1, RZI,\n     * RZR, STI, STR, S1I, S1R, S2I, S2R, TOL, YI, YR, ZBI, ZBR, ZEROI,\n     * ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, ZI, ZNI, ZNR, ZR, CYR,\n     * CYI, D1MACH, XZABS, CAR, SAR\n      INTEGER I, IFLAG, IN, INU, J, K, KODE, N, NAI, ND, NDAI, NLAST,\n     * NN, NUF, NW, NZ, IDUM\n      DIMENSION BRY(3), YR(N), YI(N), CIPR(4), CIPI(4), CSSR(3),\n     * CSRR(3), CYR(2), CYI(2)\n      DATA ZEROR,ZEROI,CONER / 0.0D0, 0.0D0, 1.0D0 /\n      DATA CIPR(1),CIPI(1),CIPR(2),CIPI(2),CIPR(3),CIPI(3),CIPR(4),\n     * CIPI(4)/ 1.0D0,0.0D0, 0.0D0,1.0D0, -1.0D0,0.0D0, 0.0D0,-1.0D0/\n      DATA HPI, AIC  /\n     1      1.57079632679489662D+00,     1.265512123484645396D+00/\nC\n      NZ = 0\n      ND = N\n      NLAST = 0\nC-----------------------------------------------------------------------\nC     COMPUTED VALUES WITH EXPONENTS BETWEEN ALIM AND ELIM IN MAG-\nC     NITUDE ARE SCALED TO KEEP INTERMEDIATE ARITHMETIC ON SCALE,\nC     EXP(ALIM)=EXP(ELIM)*TOL\nC-----------------------------------------------------------------------\n      CSCL = 1.0D0/TOL\n      CRSC = TOL\n      CSSR(1) = CSCL\n      CSSR(2) = CONER\n      CSSR(3) = CRSC\n      CSRR(1) = CRSC\n      CSRR(2) = CONER\n      CSRR(3) = CSCL\n      BRY(1) = 1.0D+3*D1MACH(1)/TOL\nC-----------------------------------------------------------------------\nC     ZN IS IN THE RIGHT HALF PLANE AFTER ROTATION BY CI OR -CI\nC-----------------------------------------------------------------------\n      ZNR = ZI\n      ZNI = -ZR\n      ZBR = ZR\n      ZBI = ZI\n      CIDI = -CONER\n      INU = INT(SNGL(FNU))\n      ANG = HPI*(FNU-DBLE(FLOAT(INU)))\n      C2R = DCOS(ANG)\n      C2I = DSIN(ANG)\n      CAR = C2R\n      SAR = C2I\n      IN = INU + N - 1\n      IN = MOD(IN,4) + 1\n      STR = C2R*CIPR(IN) - C2I*CIPI(IN)\n      C2I = C2R*CIPI(IN) + C2I*CIPR(IN)\n      C2R = STR\n      IF (ZI.GT.0.0D0) GO TO 10\n      ZNR = -ZNR\n      ZBI = -ZBI\n      CIDI = -CIDI\n      C2I = -C2I\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     CHECK FOR UNDERFLOW AND OVERFLOW ON FIRST MEMBER\nC-----------------------------------------------------------------------\n      FN = DMAX1(FNU,1.0D0)\n      CALL ZUNHJ(ZNR, ZNI, FN, 1, TOL, PHIR, PHII, ARGR, ARGI, ZETA1R,\n     * ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI)\n      IF (KODE.EQ.1) GO TO 20\n      STR = ZBR + ZETA2R\n      STI = ZBI + ZETA2I\n      RAST = FN/XZABS(STR,STI)\n      STR = STR*RAST*RAST\n      STI = -STI*RAST*RAST\n      S1R = -ZETA1R + STR\n      S1I = -ZETA1I + STI\n      GO TO 30\n   20 CONTINUE\n      S1R = -ZETA1R + ZETA2R\n      S1I = -ZETA1I + ZETA2I\n   30 CONTINUE\n      RS1 = S1R\n      IF (DABS(RS1).GT.ELIM) GO TO 150\n   40 CONTINUE\n      NN = MIN0(2,ND)\n      DO 90 I=1,NN\n        FN = FNU + DBLE(FLOAT(ND-I))\n        CALL ZUNHJ(ZNR, ZNI, FN, 0, TOL, PHIR, PHII, ARGR, ARGI,\n     *   ZETA1R, ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI)\n        IF (KODE.EQ.1) GO TO 50\n        STR = ZBR + ZETA2R\n        STI = ZBI + ZETA2I\n        RAST = FN/XZABS(STR,STI)\n        STR = STR*RAST*RAST\n        STI = -STI*RAST*RAST\n        S1R = -ZETA1R + STR\n        S1I = -ZETA1I + STI + DABS(ZI)\n        GO TO 60\n   50   CONTINUE\n        S1R = -ZETA1R + ZETA2R\n        S1I = -ZETA1I + ZETA2I\n   60   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = S1R\n        IF (DABS(RS1).GT.ELIM) GO TO 120\n        IF (I.EQ.1) IFLAG = 2\n        IF (DABS(RS1).LT.ALIM) GO TO 70\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\nC-----------------------------------------------------------------------\n        APHI = XZABS(PHIR,PHII)\n        AARG = XZABS(ARGR,ARGI)\n        RS1 = RS1 + DLOG(APHI) - 0.25D0*DLOG(AARG) - AIC\n        IF (DABS(RS1).GT.ELIM) GO TO 120\n        IF (I.EQ.1) IFLAG = 1\n        IF (RS1.LT.0.0D0) GO TO 70\n        IF (I.EQ.1) IFLAG = 3\n   70   CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR\nC     EXPONENT EXTREMES\nC-----------------------------------------------------------------------\n        CALL ZAIRY(ARGR, ARGI, 0, 2, AIR, AII, NAI, IDUM)\n        CALL ZAIRY(ARGR, ARGI, 1, 2, DAIR, DAII, NDAI, IDUM)\n        STR = DAIR*BSUMR - DAII*BSUMI\n        STI = DAIR*BSUMI + DAII*BSUMR\n        STR = STR + (AIR*ASUMR-AII*ASUMI)\n        STI = STI + (AIR*ASUMI+AII*ASUMR)\n        S2R = PHIR*STR - PHII*STI\n        S2I = PHIR*STI + PHII*STR\n        STR = DEXP(S1R)*CSSR(IFLAG)\n        S1R = STR*DCOS(S1I)\n        S1I = STR*DSIN(S1I)\n        STR = S2R*S1R - S2I*S1I\n        S2I = S2R*S1I + S2I*S1R\n        S2R = STR\n        IF (IFLAG.NE.1) GO TO 80\n        CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL)\n        IF (NW.NE.0) GO TO 120\n   80   CONTINUE\n        IF (ZI.LE.0.0D0) S2I = -S2I\n        STR = S2R*C2R - S2I*C2I\n        S2I = S2R*C2I + S2I*C2R\n        S2R = STR\n        CYR(I) = S2R\n        CYI(I) = S2I\n        J = ND - I + 1\n        YR(J) = S2R*CSRR(IFLAG)\n        YI(J) = S2I*CSRR(IFLAG)\n        STR = -C2I*CIDI\n        C2I = C2R*CIDI\n        C2R = STR\n   90 CONTINUE\n      IF (ND.LE.2) GO TO 110\n      RAZ = 1.0D0/XZABS(ZR,ZI)\n      STR = ZR*RAZ\n      STI = -ZI*RAZ\n      RZR = (STR+STR)*RAZ\n      RZI = (STI+STI)*RAZ\n      BRY(2) = 1.0D0/BRY(1)\n      BRY(3) = D1MACH(2)\n      S1R = CYR(1)\n      S1I = CYI(1)\n      S2R = CYR(2)\n      S2I = CYI(2)\n      C1R = CSRR(IFLAG)\n      ASCLE = BRY(IFLAG)\n      K = ND - 2\n      FN = DBLE(FLOAT(K))\n      DO 100 I=3,ND\n        C2R = S2R\n        C2I = S2I\n        S2R = S1R + (FNU+FN)*(RZR*C2R-RZI*C2I)\n        S2I = S1I + (FNU+FN)*(RZR*C2I+RZI*C2R)\n        S1R = C2R\n        S1I = C2I\n        C2R = S2R*C1R\n        C2I = S2I*C1R\n        YR(K) = C2R\n        YI(K) = C2I\n        K = K - 1\n        FN = FN - 1.0D0\n        IF (IFLAG.GE.3) GO TO 100\n        STR = DABS(C2R)\n        STI = DABS(C2I)\n        C2M = DMAX1(STR,STI)\n        IF (C2M.LE.ASCLE) GO TO 100\n        IFLAG = IFLAG + 1\n        ASCLE = BRY(IFLAG)\n        S1R = S1R*C1R\n        S1I = S1I*C1R\n        S2R = C2R\n        S2I = C2I\n        S1R = S1R*CSSR(IFLAG)\n        S1I = S1I*CSSR(IFLAG)\n        S2R = S2R*CSSR(IFLAG)\n        S2I = S2I*CSSR(IFLAG)\n        C1R = CSRR(IFLAG)\n  100 CONTINUE\n  110 CONTINUE\n      RETURN\n  120 CONTINUE\n      IF (RS1.GT.0.0D0) GO TO 140\nC-----------------------------------------------------------------------\nC     SET UNDERFLOW AND UPDATE PARAMETERS\nC-----------------------------------------------------------------------\n      YR(ND) = ZEROR\n      YI(ND) = ZEROI\n      NZ = NZ + 1\n      ND = ND - 1\n      IF (ND.EQ.0) GO TO 110\n      CALL ZUOIK(ZR, ZI, FNU, KODE, 1, ND, YR, YI, NUF, TOL, ELIM, ALIM)\n      IF (NUF.LT.0) GO TO 140\n      ND = ND - NUF\n      NZ = NZ + NUF\n      IF (ND.EQ.0) GO TO 110\n      FN = FNU + DBLE(FLOAT(ND-1))\n      IF (FN.LT.FNUL) GO TO 130\nC      FN = CIDI\nC      J = NUF + 1\nC      K = MOD(J,4) + 1\nC      S1R = CIPR(K)\nC      S1I = CIPI(K)\nC      IF (FN.LT.0.0D0) S1I = -S1I\nC      STR = C2R*S1R - C2I*S1I\nC      C2I = C2R*S1I + C2I*S1R\nC      C2R = STR\n      IN = INU + ND - 1\n      IN = MOD(IN,4) + 1\n      C2R = CAR*CIPR(IN) - SAR*CIPI(IN)\n      C2I = CAR*CIPI(IN) + SAR*CIPR(IN)\n      IF (ZI.LE.0.0D0) C2I = -C2I\n      GO TO 40\n  130 CONTINUE\n      NLAST = ND\n      RETURN\n  140 CONTINUE\n      NZ = -1\n      RETURN\n  150 CONTINUE\n      IF (RS1.GT.0.0D0) GO TO 140\n      NZ = N\n      DO 160 I=1,N\n        YR(I) = ZEROR\n        YI(I) = ZEROI\n  160 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zunik.f",
    "content": "      SUBROUTINE ZUNIK(ZRR, ZRI, FNU, IKFLG, IPMTR, TOL, INIT, PHIR,\n     * PHII, ZETA1R, ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI)\nC***BEGIN PROLOGUE  ZUNIK\nC***REFER TO  ZBESI,ZBESK\nC\nC        ZUNIK COMPUTES PARAMETERS FOR THE UNIFORM ASYMPTOTIC\nC        EXPANSIONS OF THE I AND K FUNCTIONS ON IKFLG= 1 OR 2\nC        RESPECTIVELY BY\nC\nC        W(FNU,ZR) = PHI*EXP(ZETA)*SUM\nC\nC        WHERE       ZETA=-ZETA1 + ZETA2       OR\nC                          ZETA1 - ZETA2\nC\nC        THE FIRST CALL MUST HAVE INIT=0. SUBSEQUENT CALLS WITH THE\nC        SAME ZR AND FNU WILL RETURN THE I OR K FUNCTION ON IKFLG=\nC        1 OR 2 WITH NO CHANGE IN INIT. CWRK IS A COMPLEX WORK\nC        ARRAY. IPMTR=0 COMPUTES ALL PARAMETERS. IPMTR=1 COMPUTES PHI,\nC        ZETA1,ZETA2.\nC\nC***ROUTINES CALLED  ZDIV,XZLOG,XZSQRT,D1MACH\nC***END PROLOGUE  ZUNIK\nC     COMPLEX CFN,CON,CONE,CRFN,CWRK,CZERO,PHI,S,SR,SUM,T,T2,ZETA1,\nC    *ZETA2,ZN,ZR\n      DOUBLE PRECISION AC, C, CON, CONEI, CONER, CRFNI, CRFNR, CWRKI,\n     * CWRKR, FNU, PHII, PHIR, RFN, SI, SR, SRI, SRR, STI, STR, SUMI,\n     * SUMR, TEST, TI, TOL, TR, T2I, T2R, ZEROI, ZEROR, ZETA1I, ZETA1R,\n     * ZETA2I, ZETA2R, ZNI, ZNR, ZRI, ZRR, D1MACH\n      INTEGER I, IDUM, IKFLG, INIT, IPMTR, J, K, L\n      DIMENSION C(120), CWRKR(16), CWRKI(16), CON(2)\n      DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 /\n      DATA CON(1), CON(2)  /\n     1 3.98942280401432678D-01,  1.25331413731550025D+00 /\n      DATA C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10),\n     1     C(11), C(12), C(13), C(14), C(15), C(16), C(17), C(18),\n     2     C(19), C(20), C(21), C(22), C(23), C(24)/\n     3     1.00000000000000000D+00,    -2.08333333333333333D-01,\n     4     1.25000000000000000D-01,     3.34201388888888889D-01,\n     5    -4.01041666666666667D-01,     7.03125000000000000D-02,\n     6    -1.02581259645061728D+00,     1.84646267361111111D+00,\n     7    -8.91210937500000000D-01,     7.32421875000000000D-02,\n     8     4.66958442342624743D+00,    -1.12070026162229938D+01,\n     9     8.78912353515625000D+00,    -2.36408691406250000D+00,\n     A     1.12152099609375000D-01,    -2.82120725582002449D+01,\n     B     8.46362176746007346D+01,    -9.18182415432400174D+01,\n     C     4.25349987453884549D+01,    -7.36879435947963170D+00,\n     D     2.27108001708984375D-01,     2.12570130039217123D+02,\n     E    -7.65252468141181642D+02,     1.05999045252799988D+03/\n      DATA C(25), C(26), C(27), C(28), C(29), C(30), C(31), C(32),\n     1     C(33), C(34), C(35), C(36), C(37), C(38), C(39), C(40),\n     2     C(41), C(42), C(43), C(44), C(45), C(46), C(47), C(48)/\n     3    -6.99579627376132541D+02,     2.18190511744211590D+02,\n     4    -2.64914304869515555D+01,     5.72501420974731445D-01,\n     5    -1.91945766231840700D+03,     8.06172218173730938D+03,\n     6    -1.35865500064341374D+04,     1.16553933368645332D+04,\n     7    -5.30564697861340311D+03,     1.20090291321635246D+03,\n     8    -1.08090919788394656D+02,     1.72772750258445740D+00,\n     9     2.02042913309661486D+04,    -9.69805983886375135D+04,\n     A     1.92547001232531532D+05,    -2.03400177280415534D+05,\n     B     1.22200464983017460D+05,    -4.11926549688975513D+04,\n     C     7.10951430248936372D+03,    -4.93915304773088012D+02,\n     D     6.07404200127348304D+00,    -2.42919187900551333D+05,\n     E     1.31176361466297720D+06,    -2.99801591853810675D+06/\n      DATA C(49), C(50), C(51), C(52), C(53), C(54), C(55), C(56),\n     1     C(57), C(58), C(59), C(60), C(61), C(62), C(63), C(64),\n     2     C(65), C(66), C(67), C(68), C(69), C(70), C(71), C(72)/\n     3     3.76327129765640400D+06,    -2.81356322658653411D+06,\n     4     1.26836527332162478D+06,    -3.31645172484563578D+05,\n     5     4.52187689813627263D+04,    -2.49983048181120962D+03,\n     6     2.43805296995560639D+01,     3.28446985307203782D+06,\n     7    -1.97068191184322269D+07,     5.09526024926646422D+07,\n     8    -7.41051482115326577D+07,     6.63445122747290267D+07,\n     9    -3.75671766607633513D+07,     1.32887671664218183D+07,\n     A    -2.78561812808645469D+06,     3.08186404612662398D+05,\n     B    -1.38860897537170405D+04,     1.10017140269246738D+02,\n     C    -4.93292536645099620D+07,     3.25573074185765749D+08,\n     D    -9.39462359681578403D+08,     1.55359689957058006D+09,\n     E    -1.62108055210833708D+09,     1.10684281682301447D+09/\n      DATA C(73), C(74), C(75), C(76), C(77), C(78), C(79), C(80),\n     1     C(81), C(82), C(83), C(84), C(85), C(86), C(87), C(88),\n     2     C(89), C(90), C(91), C(92), C(93), C(94), C(95), C(96)/\n     3    -4.95889784275030309D+08,     1.42062907797533095D+08,\n     4    -2.44740627257387285D+07,     2.24376817792244943D+06,\n     5    -8.40054336030240853D+04,     5.51335896122020586D+02,\n     6     8.14789096118312115D+08,    -5.86648149205184723D+09,\n     7     1.86882075092958249D+10,    -3.46320433881587779D+10,\n     8     4.12801855797539740D+10,    -3.30265997498007231D+10,\n     9     1.79542137311556001D+10,    -6.56329379261928433D+09,\n     A     1.55927986487925751D+09,    -2.25105661889415278D+08,\n     B     1.73951075539781645D+07,    -5.49842327572288687D+05,\n     C     3.03809051092238427D+03,    -1.46792612476956167D+10,\n     D     1.14498237732025810D+11,    -3.99096175224466498D+11,\n     E     8.19218669548577329D+11,    -1.09837515608122331D+12/\n      DATA C(97), C(98), C(99), C(100), C(101), C(102), C(103), C(104),\n     1     C(105), C(106), C(107), C(108), C(109), C(110), C(111),\n     2     C(112), C(113), C(114), C(115), C(116), C(117), C(118)/\n     3     1.00815810686538209D+12,    -6.45364869245376503D+11,\n     4     2.87900649906150589D+11,    -8.78670721780232657D+10,\n     5     1.76347306068349694D+10,    -2.16716498322379509D+09,\n     6     1.43157876718888981D+08,    -3.87183344257261262D+06,\n     7     1.82577554742931747D+04,     2.86464035717679043D+11,\n     8    -2.40629790002850396D+12,     9.10934118523989896D+12,\n     9    -2.05168994109344374D+13,     3.05651255199353206D+13,\n     A    -3.16670885847851584D+13,     2.33483640445818409D+13,\n     B    -1.23204913055982872D+13,     4.61272578084913197D+12,\n     C    -1.19655288019618160D+12,     2.05914503232410016D+11,\n     D    -2.18229277575292237D+10,     1.24700929351271032D+09/\n      DATA C(119), C(120)/\n     1    -2.91883881222208134D+07,     1.18838426256783253D+05/\nC\n      IF (INIT.NE.0) GO TO 40\nC-----------------------------------------------------------------------\nC     INITIALIZE ALL VARIABLES\nC-----------------------------------------------------------------------\n      RFN = 1.0D0/FNU\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST (ZR/FNU TOO SMALL)\nC-----------------------------------------------------------------------\n      TEST = D1MACH(1)*1.0D+3\n      AC = FNU*TEST\n      IF (DABS(ZRR).GT.AC .OR. DABS(ZRI).GT.AC) GO TO 15\n      ZETA1R = 2.0D0*DABS(DLOG(TEST))+FNU\n      ZETA1I = 0.0D0\n      ZETA2R = FNU\n      ZETA2I = 0.0D0\n      PHIR = 1.0D0\n      PHII = 0.0D0\n      RETURN\n   15 CONTINUE\n      TR = ZRR*RFN\n      TI = ZRI*RFN\n      SR = CONER + (TR*TR-TI*TI)\n      SI = CONEI + (TR*TI+TI*TR)\n      CALL XZSQRT(SR, SI, SRR, SRI)\n      STR = CONER + SRR\n      STI = CONEI + SRI\n      CALL ZDIV(STR, STI, TR, TI, ZNR, ZNI)\n      CALL XZLOG(ZNR, ZNI, STR, STI, IDUM)\n      ZETA1R = FNU*STR\n      ZETA1I = FNU*STI\n      ZETA2R = FNU*SRR\n      ZETA2I = FNU*SRI\n      CALL ZDIV(CONER, CONEI, SRR, SRI, TR, TI)\n      SRR = TR*RFN\n      SRI = TI*RFN\n      CALL XZSQRT(SRR, SRI, CWRKR(16), CWRKI(16))\n      PHIR = CWRKR(16)*CON(IKFLG)\n      PHII = CWRKI(16)*CON(IKFLG)\n      IF (IPMTR.NE.0) RETURN\n      CALL ZDIV(CONER, CONEI, SR, SI, T2R, T2I)\n      CWRKR(1) = CONER\n      CWRKI(1) = CONEI\n      CRFNR = CONER\n      CRFNI = CONEI\n      AC = 1.0D0\n      L = 1\n      DO 20 K=2,15\n        SR = ZEROR\n        SI = ZEROI\n        DO 10 J=1,K\n          L = L + 1\n          STR = SR*T2R - SI*T2I + C(L)\n          SI = SR*T2I + SI*T2R\n          SR = STR\n   10   CONTINUE\n        STR = CRFNR*SRR - CRFNI*SRI\n        CRFNI = CRFNR*SRI + CRFNI*SRR\n        CRFNR = STR\n        CWRKR(K) = CRFNR*SR - CRFNI*SI\n        CWRKI(K) = CRFNR*SI + CRFNI*SR\n        AC = AC*RFN\n        TEST = DABS(CWRKR(K)) + DABS(CWRKI(K))\n        IF (AC.LT.TOL .AND. TEST.LT.TOL) GO TO 30\n   20 CONTINUE\n      K = 15\n   30 CONTINUE\n      INIT = K\n   40 CONTINUE\n      IF (IKFLG.EQ.2) GO TO 60\nC-----------------------------------------------------------------------\nC     COMPUTE SUM FOR THE I FUNCTION\nC-----------------------------------------------------------------------\n      SR = ZEROR\n      SI = ZEROI\n      DO 50 I=1,INIT\n        SR = SR + CWRKR(I)\n        SI = SI + CWRKI(I)\n   50 CONTINUE\n      SUMR = SR\n      SUMI = SI\n      PHIR = CWRKR(16)*CON(1)\n      PHII = CWRKI(16)*CON(1)\n      RETURN\n   60 CONTINUE\nC-----------------------------------------------------------------------\nC     COMPUTE SUM FOR THE K FUNCTION\nC-----------------------------------------------------------------------\n      SR = ZEROR\n      SI = ZEROI\n      TR = CONER\n      DO 70 I=1,INIT\n        SR = SR + TR*CWRKR(I)\n        SI = SI + TR*CWRKI(I)\n        TR = -TR\n   70 CONTINUE\n      SUMR = SR\n      SUMI = SI\n      PHIR = CWRKR(16)*CON(2)\n      PHII = CWRKI(16)*CON(2)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zunk1.f",
    "content": "      SUBROUTINE ZUNK1(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  ZUNK1\nC***REFER TO  ZBESK\nC\nC     ZUNK1 COMPUTES K(FNU,Z) AND ITS ANALYTIC CONTINUATION FROM THE\nC     RIGHT HALF PLANE TO THE LEFT HALF PLANE BY MEANS OF THE\nC     UNIFORM ASYMPTOTIC EXPANSION.\nC     MR INDICATES THE DIRECTION OF ROTATION FOR ANALYTIC CONTINUATION.\nC     NZ=-1 MEANS AN OVERFLOW WILL OCCUR\nC\nC***ROUTINES CALLED  ZKSCL,ZS1S2,ZUCHK,ZUNIK,D1MACH,XZABS\nC***END PROLOGUE  ZUNK1\nC     COMPLEX CFN,CK,CONE,CRSC,CS,CSCL,CSGN,CSPN,CSR,CSS,CWRK,CY,CZERO,\nC    *C1,C2,PHI,PHID,RZ,SUM,SUMD,S1,S2,Y,Z,ZETA1,ZETA1D,ZETA2,ZETA2D,ZR\n      DOUBLE PRECISION ALIM, ANG, APHI, ASC, ASCLE, BRY, CKI, CKR,\n     * CONER, CRSC, CSCL, CSGNI, CSPNI, CSPNR, CSR, CSRR, CSSR,\n     * CWRKI, CWRKR, CYI, CYR, C1I, C1R, C2I, C2M, C2R, ELIM, FMR, FN,\n     * FNF, FNU, PHIDI, PHIDR, PHII, PHIR, PI, RAST, RAZR, RS1, RZI,\n     * RZR, SGN, STI, STR, SUMDI, SUMDR, SUMI, SUMR, S1I, S1R, S2I,\n     * S2R, TOL, YI, YR, ZEROI, ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R,\n     * ZET1DI, ZET1DR, ZET2DI, ZET2DR, ZI, ZR, ZRI, ZRR, D1MACH, XZABS\n      INTEGER I, IB, IFLAG, IFN, IL, INIT, INU, IUF, K, KDFLG, KFLAG,\n     * KK, KODE, MR, N, NW, NZ, INITD, IC, IPARD, J\n      DIMENSION BRY(3), INIT(2), YR(N), YI(N), SUMR(2), SUMI(2),\n     * ZETA1R(2), ZETA1I(2), ZETA2R(2), ZETA2I(2), CYR(2), CYI(2),\n     * CWRKR(16,3), CWRKI(16,3), CSSR(3), CSRR(3), PHIR(2), PHII(2)\n      DATA ZEROR,ZEROI,CONER / 0.0D0, 0.0D0, 1.0D0 /\n      DATA PI / 3.14159265358979324D0 /\nC\n      KDFLG = 1\n      NZ = 0\nC-----------------------------------------------------------------------\nC     EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION GREATER THAN\nC     THE UNDERFLOW LIMIT\nC-----------------------------------------------------------------------\n      CSCL = 1.0D0/TOL\n      CRSC = TOL\n      CSSR(1) = CSCL\n      CSSR(2) = CONER\n      CSSR(3) = CRSC\n      CSRR(1) = CRSC\n      CSRR(2) = CONER\n      CSRR(3) = CSCL\n      BRY(1) = 1.0D+3*D1MACH(1)/TOL\n      BRY(2) = 1.0D0/BRY(1)\n      BRY(3) = D1MACH(2)\n      ZRR = ZR\n      ZRI = ZI\n      IF (ZR.GE.0.0D0) GO TO 10\n      ZRR = -ZR\n      ZRI = -ZI\n   10 CONTINUE\n      J = 2\n      DO 70 I=1,N\nC-----------------------------------------------------------------------\nC     J FLIP FLOPS BETWEEN 1 AND 2 IN J = 3 - J\nC-----------------------------------------------------------------------\n        J = 3 - J\n        FN = FNU + DBLE(FLOAT(I-1))\n        INIT(J) = 0\n        CALL ZUNIK(ZRR, ZRI, FN, 2, 0, TOL, INIT(J), PHIR(J), PHII(J),\n     *   ZETA1R(J), ZETA1I(J), ZETA2R(J), ZETA2I(J), SUMR(J), SUMI(J),\n     *   CWRKR(1,J), CWRKI(1,J))\n        IF (KODE.EQ.1) GO TO 20\n        STR = ZRR + ZETA2R(J)\n        STI = ZRI + ZETA2I(J)\n        RAST = FN/XZABS(STR,STI)\n        STR = STR*RAST*RAST\n        STI = -STI*RAST*RAST\n        S1R = ZETA1R(J) - STR\n        S1I = ZETA1I(J) - STI\n        GO TO 30\n   20   CONTINUE\n        S1R = ZETA1R(J) - ZETA2R(J)\n        S1I = ZETA1I(J) - ZETA2I(J)\n   30   CONTINUE\n        RS1 = S1R\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        IF (DABS(RS1).GT.ELIM) GO TO 60\n        IF (KDFLG.EQ.1) KFLAG = 2\n        IF (DABS(RS1).LT.ALIM) GO TO 40\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = XZABS(PHIR(J),PHII(J))\n        RS1 = RS1 + DLOG(APHI)\n        IF (DABS(RS1).GT.ELIM) GO TO 60\n        IF (KDFLG.EQ.1) KFLAG = 1\n        IF (RS1.LT.0.0D0) GO TO 40\n        IF (KDFLG.EQ.1) KFLAG = 3\n   40   CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR\nC     EXPONENT EXTREMES\nC-----------------------------------------------------------------------\n        S2R = PHIR(J)*SUMR(J) - PHII(J)*SUMI(J)\n        S2I = PHIR(J)*SUMI(J) + PHII(J)*SUMR(J)\n        STR = DEXP(S1R)*CSSR(KFLAG)\n        S1R = STR*DCOS(S1I)\n        S1I = STR*DSIN(S1I)\n        STR = S2R*S1R - S2I*S1I\n        S2I = S1R*S2I + S2R*S1I\n        S2R = STR\n        IF (KFLAG.NE.1) GO TO 50\n        CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL)\n        IF (NW.NE.0) GO TO 60\n   50   CONTINUE\n        CYR(KDFLG) = S2R\n        CYI(KDFLG) = S2I\n        YR(I) = S2R*CSRR(KFLAG)\n        YI(I) = S2I*CSRR(KFLAG)\n        IF (KDFLG.EQ.2) GO TO 75\n        KDFLG = 2\n        GO TO 70\n   60   CONTINUE\n        IF (RS1.GT.0.0D0) GO TO 300\nC-----------------------------------------------------------------------\nC     FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW\nC-----------------------------------------------------------------------\n        IF (ZR.LT.0.0D0) GO TO 300\n        KDFLG = 1\n        YR(I)=ZEROR\n        YI(I)=ZEROI\n        NZ=NZ+1\n        IF (I.EQ.1) GO TO 70\n        IF ((YR(I-1).EQ.ZEROR).AND.(YI(I-1).EQ.ZEROI)) GO TO 70\n        YR(I-1)=ZEROR\n        YI(I-1)=ZEROI\n        NZ=NZ+1\n   70 CONTINUE\n      I = N\n   75 CONTINUE\n      RAZR = 1.0D0/XZABS(ZRR,ZRI)\n      STR = ZRR*RAZR\n      STI = -ZRI*RAZR\n      RZR = (STR+STR)*RAZR\n      RZI = (STI+STI)*RAZR\n      CKR = FN*RZR\n      CKI = FN*RZI\n      IB = I + 1\n      IF (N.LT.IB) GO TO 160\nC-----------------------------------------------------------------------\nC     TEST LAST MEMBER FOR UNDERFLOW AND OVERFLOW. SET SEQUENCE TO ZERO\nC     ON UNDERFLOW.\nC-----------------------------------------------------------------------\n      FN = FNU + DBLE(FLOAT(N-1))\n      IPARD = 1\n      IF (MR.NE.0) IPARD = 0\n      INITD = 0\n      CALL ZUNIK(ZRR, ZRI, FN, 2, IPARD, TOL, INITD, PHIDR, PHIDI,\n     * ZET1DR, ZET1DI, ZET2DR, ZET2DI, SUMDR, SUMDI, CWRKR(1,3),\n     * CWRKI(1,3))\n      IF (KODE.EQ.1) GO TO 80\n      STR = ZRR + ZET2DR\n      STI = ZRI + ZET2DI\n      RAST = FN/XZABS(STR,STI)\n      STR = STR*RAST*RAST\n      STI = -STI*RAST*RAST\n      S1R = ZET1DR - STR\n      S1I = ZET1DI - STI\n      GO TO 90\n   80 CONTINUE\n      S1R = ZET1DR - ZET2DR\n      S1I = ZET1DI - ZET2DI\n   90 CONTINUE\n      RS1 = S1R\n      IF (DABS(RS1).GT.ELIM) GO TO 95\n      IF (DABS(RS1).LT.ALIM) GO TO 100\nC----------------------------------------------------------------------------\nC     REFINE ESTIMATE AND TEST\nC-------------------------------------------------------------------------\n      APHI = XZABS(PHIDR,PHIDI)\n      RS1 = RS1+DLOG(APHI)\n      IF (DABS(RS1).LT.ELIM) GO TO 100\n   95 CONTINUE\n      IF (DABS(RS1).GT.0.0D0) GO TO 300\nC-----------------------------------------------------------------------\nC     FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW\nC-----------------------------------------------------------------------\n      IF (ZR.LT.0.0D0) GO TO 300\n      NZ = N\n      DO 96 I=1,N\n        YR(I) = ZEROR\n        YI(I) = ZEROI\n   96 CONTINUE\n      RETURN\nC---------------------------------------------------------------------------\nC     FORWARD RECUR FOR REMAINDER OF THE SEQUENCE\nC----------------------------------------------------------------------------\n  100 CONTINUE\n      S1R = CYR(1)\n      S1I = CYI(1)\n      S2R = CYR(2)\n      S2I = CYI(2)\n      C1R = CSRR(KFLAG)\n      ASCLE = BRY(KFLAG)\n      DO 120 I=IB,N\n        C2R = S2R\n        C2I = S2I\n        S2R = CKR*C2R - CKI*C2I + S1R\n        S2I = CKR*C2I + CKI*C2R + S1I\n        S1R = C2R\n        S1I = C2I\n        CKR = CKR + RZR\n        CKI = CKI + RZI\n        C2R = S2R*C1R\n        C2I = S2I*C1R\n        YR(I) = C2R\n        YI(I) = C2I\n        IF (KFLAG.GE.3) GO TO 120\n        STR = DABS(C2R)\n        STI = DABS(C2I)\n        C2M = DMAX1(STR,STI)\n        IF (C2M.LE.ASCLE) GO TO 120\n        KFLAG = KFLAG + 1\n        ASCLE = BRY(KFLAG)\n        S1R = S1R*C1R\n        S1I = S1I*C1R\n        S2R = C2R\n        S2I = C2I\n        S1R = S1R*CSSR(KFLAG)\n        S1I = S1I*CSSR(KFLAG)\n        S2R = S2R*CSSR(KFLAG)\n        S2I = S2I*CSSR(KFLAG)\n        C1R = CSRR(KFLAG)\n  120 CONTINUE\n  160 CONTINUE\n      IF (MR.EQ.0) RETURN\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION FOR RE(Z).LT.0.0D0\nC-----------------------------------------------------------------------\n      NZ = 0\n      FMR = DBLE(FLOAT(MR))\n      SGN = -DSIGN(PI,FMR)\nC-----------------------------------------------------------------------\nC     CSPN AND CSGN ARE COEFF OF K AND I FUNCTIONS RESP.\nC-----------------------------------------------------------------------\n      CSGNI = SGN\n      INU = INT(SNGL(FNU))\n      FNF = FNU - DBLE(FLOAT(INU))\n      IFN = INU + N - 1\n      ANG = FNF*SGN\n      CSPNR = DCOS(ANG)\n      CSPNI = DSIN(ANG)\n      IF (MOD(IFN,2).EQ.0) GO TO 170\n      CSPNR = -CSPNR\n      CSPNI = -CSPNI\n  170 CONTINUE\n      ASC = BRY(1)\n      IUF = 0\n      KK = N\n      KDFLG = 1\n      IB = IB - 1\n      IC = IB - 1\n      DO 270 K=1,N\n        FN = FNU + DBLE(FLOAT(KK-1))\nC-----------------------------------------------------------------------\nC     LOGIC TO SORT OUT CASES WHOSE PARAMETERS WERE SET FOR THE K\nC     FUNCTION ABOVE\nC-----------------------------------------------------------------------\n        M=3\n        IF (N.GT.2) GO TO 175\n  172   CONTINUE\n        INITD = INIT(J)\n        PHIDR = PHIR(J)\n        PHIDI = PHII(J)\n        ZET1DR = ZETA1R(J)\n        ZET1DI = ZETA1I(J)\n        ZET2DR = ZETA2R(J)\n        ZET2DI = ZETA2I(J)\n        SUMDR = SUMR(J)\n        SUMDI = SUMI(J)\n        M = J\n        J = 3 - J\n        GO TO 180\n  175   CONTINUE\n        IF ((KK.EQ.N).AND.(IB.LT.N)) GO TO 180\n        IF ((KK.EQ.IB).OR.(KK.EQ.IC)) GO TO 172\n        INITD = 0\n  180   CONTINUE\n        CALL ZUNIK(ZRR, ZRI, FN, 1, 0, TOL, INITD, PHIDR, PHIDI,\n     *   ZET1DR, ZET1DI, ZET2DR, ZET2DI, SUMDR, SUMDI,\n     *   CWRKR(1,M), CWRKI(1,M))\n        IF (KODE.EQ.1) GO TO 200\n        STR = ZRR + ZET2DR\n        STI = ZRI + ZET2DI\n        RAST = FN/XZABS(STR,STI)\n        STR = STR*RAST*RAST\n        STI = -STI*RAST*RAST\n        S1R = -ZET1DR + STR\n        S1I = -ZET1DI + STI\n        GO TO 210\n  200   CONTINUE\n        S1R = -ZET1DR + ZET2DR\n        S1I = -ZET1DI + ZET2DI\n  210   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = S1R\n        IF (DABS(RS1).GT.ELIM) GO TO 260\n        IF (KDFLG.EQ.1) IFLAG = 2\n        IF (DABS(RS1).LT.ALIM) GO TO 220\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = XZABS(PHIDR,PHIDI)\n        RS1 = RS1 + DLOG(APHI)\n        IF (DABS(RS1).GT.ELIM) GO TO 260\n        IF (KDFLG.EQ.1) IFLAG = 1\n        IF (RS1.LT.0.0D0) GO TO 220\n        IF (KDFLG.EQ.1) IFLAG = 3\n  220   CONTINUE\n        STR = PHIDR*SUMDR - PHIDI*SUMDI\n        STI = PHIDR*SUMDI + PHIDI*SUMDR\n        S2R = -CSGNI*STI\n        S2I = CSGNI*STR\n        STR = DEXP(S1R)*CSSR(IFLAG)\n        S1R = STR*DCOS(S1I)\n        S1I = STR*DSIN(S1I)\n        STR = S2R*S1R - S2I*S1I\n        S2I = S2R*S1I + S2I*S1R\n        S2R = STR\n        IF (IFLAG.NE.1) GO TO 230\n        CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL)\n        IF (NW.EQ.0) GO TO 230\n        S2R = ZEROR\n        S2I = ZEROI\n  230   CONTINUE\n        CYR(KDFLG) = S2R\n        CYI(KDFLG) = S2I\n        C2R = S2R\n        C2I = S2I\n        S2R = S2R*CSRR(IFLAG)\n        S2I = S2I*CSRR(IFLAG)\nC-----------------------------------------------------------------------\nC     ADD I AND K FUNCTIONS, K SEQUENCE IN Y(I), I=1,N\nC-----------------------------------------------------------------------\n        S1R = YR(KK)\n        S1I = YI(KK)\n        IF (KODE.EQ.1) GO TO 250\n        CALL ZS1S2(ZRR, ZRI, S1R, S1I, S2R, S2I, NW, ASC, ALIM, IUF)\n        NZ = NZ + NW\n  250   CONTINUE\n        YR(KK) = S1R*CSPNR - S1I*CSPNI + S2R\n        YI(KK) = CSPNR*S1I + CSPNI*S1R + S2I\n        KK = KK - 1\n        CSPNR = -CSPNR\n        CSPNI = -CSPNI\n        IF (C2R.NE.0.0D0 .OR. C2I.NE.0.0D0) GO TO 255\n        KDFLG = 1\n        GO TO 270\n  255   CONTINUE\n        IF (KDFLG.EQ.2) GO TO 275\n        KDFLG = 2\n        GO TO 270\n  260   CONTINUE\n        IF (RS1.GT.0.0D0) GO TO 300\n        S2R = ZEROR\n        S2I = ZEROI\n        GO TO 230\n  270 CONTINUE\n      K = N\n  275 CONTINUE\n      IL = N - K\n      IF (IL.EQ.0) RETURN\nC-----------------------------------------------------------------------\nC     RECUR BACKWARD FOR REMAINDER OF I SEQUENCE AND ADD IN THE\nC     K FUNCTIONS, SCALING THE I SEQUENCE DURING RECURRENCE TO KEEP\nC     INTERMEDIATE ARITHMETIC ON SCALE NEAR EXPONENT EXTREMES.\nC-----------------------------------------------------------------------\n      S1R = CYR(1)\n      S1I = CYI(1)\n      S2R = CYR(2)\n      S2I = CYI(2)\n      CSR = CSRR(IFLAG)\n      ASCLE = BRY(IFLAG)\n      FN = DBLE(FLOAT(INU+IL))\n      DO 290 I=1,IL\n        C2R = S2R\n        C2I = S2I\n        S2R = S1R + (FN+FNF)*(RZR*C2R-RZI*C2I)\n        S2I = S1I + (FN+FNF)*(RZR*C2I+RZI*C2R)\n        S1R = C2R\n        S1I = C2I\n        FN = FN - 1.0D0\n        C2R = S2R*CSR\n        C2I = S2I*CSR\n        CKR = C2R\n        CKI = C2I\n        C1R = YR(KK)\n        C1I = YI(KK)\n        IF (KODE.EQ.1) GO TO 280\n        CALL ZS1S2(ZRR, ZRI, C1R, C1I, C2R, C2I, NW, ASC, ALIM, IUF)\n        NZ = NZ + NW\n  280   CONTINUE\n        YR(KK) = C1R*CSPNR - C1I*CSPNI + C2R\n        YI(KK) = C1R*CSPNI + C1I*CSPNR + C2I\n        KK = KK - 1\n        CSPNR = -CSPNR\n        CSPNI = -CSPNI\n        IF (IFLAG.GE.3) GO TO 290\n        C2R = DABS(CKR)\n        C2I = DABS(CKI)\n        C2M = DMAX1(C2R,C2I)\n        IF (C2M.LE.ASCLE) GO TO 290\n        IFLAG = IFLAG + 1\n        ASCLE = BRY(IFLAG)\n        S1R = S1R*CSR\n        S1I = S1I*CSR\n        S2R = CKR\n        S2I = CKI\n        S1R = S1R*CSSR(IFLAG)\n        S1I = S1I*CSSR(IFLAG)\n        S2R = S2R*CSSR(IFLAG)\n        S2I = S2I*CSSR(IFLAG)\n        CSR = CSRR(IFLAG)\n  290 CONTINUE\n      RETURN\n  300 CONTINUE\n      NZ = -1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zunk2.f",
    "content": "      SUBROUTINE ZUNK2(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM,\n     * ALIM)\nC***BEGIN PROLOGUE  ZUNK2\nC***REFER TO  ZBESK\nC\nC     ZUNK2 COMPUTES K(FNU,Z) AND ITS ANALYTIC CONTINUATION FROM THE\nC     RIGHT HALF PLANE TO THE LEFT HALF PLANE BY MEANS OF THE\nC     UNIFORM ASYMPTOTIC EXPANSIONS FOR H(KIND,FNU,ZN) AND J(FNU,ZN)\nC     WHERE ZN IS IN THE RIGHT HALF PLANE, KIND=(3-MR)/2, MR=+1 OR\nC     -1. HERE ZN=ZR*I OR -ZR*I WHERE ZR=Z IF Z IS IN THE RIGHT\nC     HALF PLANE OR ZR=-Z IF Z IS IN THE LEFT HALF PLANE. MR INDIC-\nC     ATES THE DIRECTION OF ROTATION FOR ANALYTIC CONTINUATION.\nC     NZ=-1 MEANS AN OVERFLOW WILL OCCUR\nC\nC***ROUTINES CALLED  ZAIRY,ZKSCL,ZS1S2,ZUCHK,ZUNHJ,D1MACH,XZABS\nC***END PROLOGUE  ZUNK2\nC     COMPLEX AI,ARG,ARGD,ASUM,ASUMD,BSUM,BSUMD,CFN,CI,CIP,CK,CONE,CRSC,\nC    *CR1,CR2,CS,CSCL,CSGN,CSPN,CSR,CSS,CY,CZERO,C1,C2,DAI,PHI,PHID,RZ,\nC    *S1,S2,Y,Z,ZB,ZETA1,ZETA1D,ZETA2,ZETA2D,ZN,ZR\n      DOUBLE PRECISION AARG, AIC, AII, AIR, ALIM, ANG, APHI, ARGDI,\n     * ARGDR, ARGI, ARGR, ASC, ASCLE, ASUMDI, ASUMDR, ASUMI, ASUMR,\n     * BRY, BSUMDI, BSUMDR, BSUMI, BSUMR, CAR, CIPI, CIPR, CKI, CKR,\n     * CONER, CRSC, CR1I, CR1R, CR2I, CR2R, CSCL, CSGNI, CSI,\n     * CSPNI, CSPNR, CSR, CSRR, CSSR, CYI, CYR, C1I, C1R, C2I, C2M,\n     * C2R, DAII, DAIR, ELIM, FMR, FN, FNF, FNU, HPI, PHIDI, PHIDR,\n     * PHII, PHIR, PI, PTI, PTR, RAST, RAZR, RS1, RZI, RZR, SAR, SGN,\n     * STI, STR, S1I, S1R, S2I, S2R, TOL, YI, YR, YY, ZBI, ZBR, ZEROI,\n     * ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, ZET1DI, ZET1DR, ZET2DI,\n     * ZET2DR, ZI, ZNI, ZNR, ZR, ZRI, ZRR, D1MACH, XZABS\n      INTEGER I, IB, IFLAG, IFN, IL, IN, INU, IUF, K, KDFLG, KFLAG, KK,\n     * KODE, MR, N, NAI, NDAI, NW, NZ, IDUM, J, IPARD, IC\n      DIMENSION BRY(3), YR(N), YI(N), ASUMR(2), ASUMI(2), BSUMR(2),\n     * BSUMI(2), PHIR(2), PHII(2), ARGR(2), ARGI(2), ZETA1R(2),\n     * ZETA1I(2), ZETA2R(2), ZETA2I(2), CYR(2), CYI(2), CIPR(4),\n     * CIPI(4), CSSR(3), CSRR(3)\n      DATA ZEROR,ZEROI,CONER,CR1R,CR1I,CR2R,CR2I /\n     1         0.0D0, 0.0D0, 1.0D0,\n     1 1.0D0,1.73205080756887729D0 , -0.5D0,-8.66025403784438647D-01 /\n      DATA HPI, PI, AIC /\n     1     1.57079632679489662D+00,     3.14159265358979324D+00,\n     1     1.26551212348464539D+00/\n      DATA CIPR(1),CIPI(1),CIPR(2),CIPI(2),CIPR(3),CIPI(3),CIPR(4),\n     * CIPI(4) /\n     1  1.0D0,0.0D0 ,  0.0D0,-1.0D0 ,  -1.0D0,0.0D0 ,  0.0D0,1.0D0 /\nC\n      KDFLG = 1\n      NZ = 0\nC-----------------------------------------------------------------------\nC     EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION GREATER THAN\nC     THE UNDERFLOW LIMIT\nC-----------------------------------------------------------------------\n      CSCL = 1.0D0/TOL\n      CRSC = TOL\n      CSSR(1) = CSCL\n      CSSR(2) = CONER\n      CSSR(3) = CRSC\n      CSRR(1) = CRSC\n      CSRR(2) = CONER\n      CSRR(3) = CSCL\n      BRY(1) = 1.0D+3*D1MACH(1)/TOL\n      BRY(2) = 1.0D0/BRY(1)\n      BRY(3) = D1MACH(2)\n      ZRR = ZR\n      ZRI = ZI\n      IF (ZR.GE.0.0D0) GO TO 10\n      ZRR = -ZR\n      ZRI = -ZI\n   10 CONTINUE\n      YY = ZRI\n      ZNR = ZRI\n      ZNI = -ZRR\n      ZBR = ZRR\n      ZBI = ZRI\n      INU = INT(SNGL(FNU))\n      FNF = FNU - DBLE(FLOAT(INU))\n      ANG = -HPI*FNF\n      CAR = DCOS(ANG)\n      SAR = DSIN(ANG)\n      C2R = HPI*SAR\n      C2I = -HPI*CAR\n      KK = MOD(INU,4) + 1\n      STR = C2R*CIPR(KK) - C2I*CIPI(KK)\n      STI = C2R*CIPI(KK) + C2I*CIPR(KK)\n      CSR = CR1R*STR - CR1I*STI\n      CSI = CR1R*STI + CR1I*STR\n      IF (YY.GT.0.0D0) GO TO 20\n      ZNR = -ZNR\n      ZBI = -ZBI\n   20 CONTINUE\nC-----------------------------------------------------------------------\nC     K(FNU,Z) IS COMPUTED FROM H(2,FNU,-I*Z) WHERE Z IS IN THE FIRST\nC     QUADRANT. FOURTH QUADRANT VALUES (YY.LE.0.0E0) ARE COMPUTED BY\nC     CONJUGATION SINCE THE K FUNCTION IS REAL ON THE POSITIVE REAL AXIS\nC-----------------------------------------------------------------------\n      J = 2\n      DO 80 I=1,N\nC-----------------------------------------------------------------------\nC     J FLIP FLOPS BETWEEN 1 AND 2 IN J = 3 - J\nC-----------------------------------------------------------------------\n        J = 3 - J\n        FN = FNU + DBLE(FLOAT(I-1))\n        CALL ZUNHJ(ZNR, ZNI, FN, 0, TOL, PHIR(J), PHII(J), ARGR(J),\n     *   ARGI(J), ZETA1R(J), ZETA1I(J), ZETA2R(J), ZETA2I(J), ASUMR(J),\n     *   ASUMI(J), BSUMR(J), BSUMI(J))\n        IF (KODE.EQ.1) GO TO 30\n        STR = ZBR + ZETA2R(J)\n        STI = ZBI + ZETA2I(J)\n        RAST = FN/XZABS(STR,STI)\n        STR = STR*RAST*RAST\n        STI = -STI*RAST*RAST\n        S1R = ZETA1R(J) - STR\n        S1I = ZETA1I(J) - STI\n        GO TO 40\n   30   CONTINUE\n        S1R = ZETA1R(J) - ZETA2R(J)\n        S1I = ZETA1I(J) - ZETA2I(J)\n   40   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = S1R\n        IF (DABS(RS1).GT.ELIM) GO TO 70\n        IF (KDFLG.EQ.1) KFLAG = 2\n        IF (DABS(RS1).LT.ALIM) GO TO 50\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = XZABS(PHIR(J),PHII(J))\n        AARG = XZABS(ARGR(J),ARGI(J))\n        RS1 = RS1 + DLOG(APHI) - 0.25D0*DLOG(AARG) - AIC\n        IF (DABS(RS1).GT.ELIM) GO TO 70\n        IF (KDFLG.EQ.1) KFLAG = 1\n        IF (RS1.LT.0.0D0) GO TO 50\n        IF (KDFLG.EQ.1) KFLAG = 3\n   50   CONTINUE\nC-----------------------------------------------------------------------\nC     SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR\nC     EXPONENT EXTREMES\nC-----------------------------------------------------------------------\n        C2R = ARGR(J)*CR2R - ARGI(J)*CR2I\n        C2I = ARGR(J)*CR2I + ARGI(J)*CR2R\n        CALL ZAIRY(C2R, C2I, 0, 2, AIR, AII, NAI, IDUM)\n        CALL ZAIRY(C2R, C2I, 1, 2, DAIR, DAII, NDAI, IDUM)\n        STR = DAIR*BSUMR(J) - DAII*BSUMI(J)\n        STI = DAIR*BSUMI(J) + DAII*BSUMR(J)\n        PTR = STR*CR2R - STI*CR2I\n        PTI = STR*CR2I + STI*CR2R\n        STR = PTR + (AIR*ASUMR(J)-AII*ASUMI(J))\n        STI = PTI + (AIR*ASUMI(J)+AII*ASUMR(J))\n        PTR = STR*PHIR(J) - STI*PHII(J)\n        PTI = STR*PHII(J) + STI*PHIR(J)\n        S2R = PTR*CSR - PTI*CSI\n        S2I = PTR*CSI + PTI*CSR\n        STR = DEXP(S1R)*CSSR(KFLAG)\n        S1R = STR*DCOS(S1I)\n        S1I = STR*DSIN(S1I)\n        STR = S2R*S1R - S2I*S1I\n        S2I = S1R*S2I + S2R*S1I\n        S2R = STR\n        IF (KFLAG.NE.1) GO TO 60\n        CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL)\n        IF (NW.NE.0) GO TO 70\n   60   CONTINUE\n        IF (YY.LE.0.0D0) S2I = -S2I\n        CYR(KDFLG) = S2R\n        CYI(KDFLG) = S2I\n        YR(I) = S2R*CSRR(KFLAG)\n        YI(I) = S2I*CSRR(KFLAG)\n        STR = CSI\n        CSI = -CSR\n        CSR = STR\n        IF (KDFLG.EQ.2) GO TO 85\n        KDFLG = 2\n        GO TO 80\n   70   CONTINUE\n        IF (RS1.GT.0.0D0) GO TO 320\nC-----------------------------------------------------------------------\nC     FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW\nC-----------------------------------------------------------------------\n        IF (ZR.LT.0.0D0) GO TO 320\n        KDFLG = 1\n        YR(I)=ZEROR\n        YI(I)=ZEROI\n        NZ=NZ+1\n        STR = CSI\n        CSI =-CSR\n        CSR = STR\n        IF (I.EQ.1) GO TO 80\n        IF ((YR(I-1).EQ.ZEROR).AND.(YI(I-1).EQ.ZEROI)) GO TO 80\n        YR(I-1)=ZEROR\n        YI(I-1)=ZEROI\n        NZ=NZ+1\n   80 CONTINUE\n      I = N\n   85 CONTINUE\n      RAZR = 1.0D0/XZABS(ZRR,ZRI)\n      STR = ZRR*RAZR\n      STI = -ZRI*RAZR\n      RZR = (STR+STR)*RAZR\n      RZI = (STI+STI)*RAZR\n      CKR = FN*RZR\n      CKI = FN*RZI\n      IB = I + 1\n      IF (N.LT.IB) GO TO 180\nC-----------------------------------------------------------------------\nC     TEST LAST MEMBER FOR UNDERFLOW AND OVERFLOW. SET SEQUENCE TO ZERO\nC     ON UNDERFLOW.\nC-----------------------------------------------------------------------\n      FN = FNU + DBLE(FLOAT(N-1))\n      IPARD = 1\n      IF (MR.NE.0) IPARD = 0\n      CALL ZUNHJ(ZNR, ZNI, FN, IPARD, TOL, PHIDR, PHIDI, ARGDR, ARGDI,\n     * ZET1DR, ZET1DI, ZET2DR, ZET2DI, ASUMDR, ASUMDI, BSUMDR, BSUMDI)\n      IF (KODE.EQ.1) GO TO 90\n      STR = ZBR + ZET2DR\n      STI = ZBI + ZET2DI\n      RAST = FN/XZABS(STR,STI)\n      STR = STR*RAST*RAST\n      STI = -STI*RAST*RAST\n      S1R = ZET1DR - STR\n      S1I = ZET1DI - STI\n      GO TO 100\n   90 CONTINUE\n      S1R = ZET1DR - ZET2DR\n      S1I = ZET1DI - ZET2DI\n  100 CONTINUE\n      RS1 = S1R\n      IF (DABS(RS1).GT.ELIM) GO TO 105\n      IF (DABS(RS1).LT.ALIM) GO TO 120\nC----------------------------------------------------------------------------\nC     REFINE ESTIMATE AND TEST\nC-------------------------------------------------------------------------\n      APHI = XZABS(PHIDR,PHIDI)\n      RS1 = RS1+DLOG(APHI)\n      IF (DABS(RS1).LT.ELIM) GO TO 120\n  105 CONTINUE\n      IF (RS1.GT.0.0D0) GO TO 320\nC-----------------------------------------------------------------------\nC     FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW\nC-----------------------------------------------------------------------\n      IF (ZR.LT.0.0D0) GO TO 320\n      NZ = N\n      DO 106 I=1,N\n        YR(I) = ZEROR\n        YI(I) = ZEROI\n  106 CONTINUE\n      RETURN\n  120 CONTINUE\n      S1R = CYR(1)\n      S1I = CYI(1)\n      S2R = CYR(2)\n      S2I = CYI(2)\n      C1R = CSRR(KFLAG)\n      ASCLE = BRY(KFLAG)\n      DO 130 I=IB,N\n        C2R = S2R\n        C2I = S2I\n        S2R = CKR*C2R - CKI*C2I + S1R\n        S2I = CKR*C2I + CKI*C2R + S1I\n        S1R = C2R\n        S1I = C2I\n        CKR = CKR + RZR\n        CKI = CKI + RZI\n        C2R = S2R*C1R\n        C2I = S2I*C1R\n        YR(I) = C2R\n        YI(I) = C2I\n        IF (KFLAG.GE.3) GO TO 130\n        STR = DABS(C2R)\n        STI = DABS(C2I)\n        C2M = DMAX1(STR,STI)\n        IF (C2M.LE.ASCLE) GO TO 130\n        KFLAG = KFLAG + 1\n        ASCLE = BRY(KFLAG)\n        S1R = S1R*C1R\n        S1I = S1I*C1R\n        S2R = C2R\n        S2I = C2I\n        S1R = S1R*CSSR(KFLAG)\n        S1I = S1I*CSSR(KFLAG)\n        S2R = S2R*CSSR(KFLAG)\n        S2I = S2I*CSSR(KFLAG)\n        C1R = CSRR(KFLAG)\n  130 CONTINUE\n  180 CONTINUE\n      IF (MR.EQ.0) RETURN\nC-----------------------------------------------------------------------\nC     ANALYTIC CONTINUATION FOR RE(Z).LT.0.0D0\nC-----------------------------------------------------------------------\n      NZ = 0\n      FMR = DBLE(FLOAT(MR))\n      SGN = -DSIGN(PI,FMR)\nC-----------------------------------------------------------------------\nC     CSPN AND CSGN ARE COEFF OF K AND I FUNCIONS RESP.\nC-----------------------------------------------------------------------\n      CSGNI = SGN\n      IF (YY.LE.0.0D0) CSGNI = -CSGNI\n      IFN = INU + N - 1\n      ANG = FNF*SGN\n      CSPNR = DCOS(ANG)\n      CSPNI = DSIN(ANG)\n      IF (MOD(IFN,2).EQ.0) GO TO 190\n      CSPNR = -CSPNR\n      CSPNI = -CSPNI\n  190 CONTINUE\nC-----------------------------------------------------------------------\nC     CS=COEFF OF THE J FUNCTION TO GET THE I FUNCTION. I(FNU,Z) IS\nC     COMPUTED FROM EXP(I*FNU*HPI)*J(FNU,-I*Z) WHERE Z IS IN THE FIRST\nC     QUADRANT. FOURTH QUADRANT VALUES (YY.LE.0.0E0) ARE COMPUTED BY\nC     CONJUGATION SINCE THE I FUNCTION IS REAL ON THE POSITIVE REAL AXIS\nC-----------------------------------------------------------------------\n      CSR = SAR*CSGNI\n      CSI = CAR*CSGNI\n      IN = MOD(IFN,4) + 1\n      C2R = CIPR(IN)\n      C2I = CIPI(IN)\n      STR = CSR*C2R + CSI*C2I\n      CSI = -CSR*C2I + CSI*C2R\n      CSR = STR\n      ASC = BRY(1)\n      IUF = 0\n      KK = N\n      KDFLG = 1\n      IB = IB - 1\n      IC = IB - 1\n      DO 290 K=1,N\n        FN = FNU + DBLE(FLOAT(KK-1))\nC-----------------------------------------------------------------------\nC     LOGIC TO SORT OUT CASES WHOSE PARAMETERS WERE SET FOR THE K\nC     FUNCTION ABOVE\nC-----------------------------------------------------------------------\n        IF (N.GT.2) GO TO 175\n  172   CONTINUE\n        PHIDR = PHIR(J)\n        PHIDI = PHII(J)\n        ARGDR = ARGR(J)\n        ARGDI = ARGI(J)\n        ZET1DR = ZETA1R(J)\n        ZET1DI = ZETA1I(J)\n        ZET2DR = ZETA2R(J)\n        ZET2DI = ZETA2I(J)\n        ASUMDR = ASUMR(J)\n        ASUMDI = ASUMI(J)\n        BSUMDR = BSUMR(J)\n        BSUMDI = BSUMI(J)\n        J = 3 - J\n        GO TO 210\n  175   CONTINUE\n        IF ((KK.EQ.N).AND.(IB.LT.N)) GO TO 210\n        IF ((KK.EQ.IB).OR.(KK.EQ.IC)) GO TO 172\n        CALL ZUNHJ(ZNR, ZNI, FN, 0, TOL, PHIDR, PHIDI, ARGDR,\n     *   ARGDI, ZET1DR, ZET1DI, ZET2DR, ZET2DI, ASUMDR,\n     *   ASUMDI, BSUMDR, BSUMDI)\n  210   CONTINUE\n        IF (KODE.EQ.1) GO TO 220\n        STR = ZBR + ZET2DR\n        STI = ZBI + ZET2DI\n        RAST = FN/XZABS(STR,STI)\n        STR = STR*RAST*RAST\n        STI = -STI*RAST*RAST\n        S1R = -ZET1DR + STR\n        S1I = -ZET1DI + STI\n        GO TO 230\n  220   CONTINUE\n        S1R = -ZET1DR + ZET2DR\n        S1I = -ZET1DI + ZET2DI\n  230   CONTINUE\nC-----------------------------------------------------------------------\nC     TEST FOR UNDERFLOW AND OVERFLOW\nC-----------------------------------------------------------------------\n        RS1 = S1R\n        IF (DABS(RS1).GT.ELIM) GO TO 280\n        IF (KDFLG.EQ.1) IFLAG = 2\n        IF (DABS(RS1).LT.ALIM) GO TO 240\nC-----------------------------------------------------------------------\nC     REFINE  TEST AND SCALE\nC-----------------------------------------------------------------------\n        APHI = XZABS(PHIDR,PHIDI)\n        AARG = XZABS(ARGDR,ARGDI)\n        RS1 = RS1 + DLOG(APHI) - 0.25D0*DLOG(AARG) - AIC\n        IF (DABS(RS1).GT.ELIM) GO TO 280\n        IF (KDFLG.EQ.1) IFLAG = 1\n        IF (RS1.LT.0.0D0) GO TO 240\n        IF (KDFLG.EQ.1) IFLAG = 3\n  240   CONTINUE\n        CALL ZAIRY(ARGDR, ARGDI, 0, 2, AIR, AII, NAI, IDUM)\n        CALL ZAIRY(ARGDR, ARGDI, 1, 2, DAIR, DAII, NDAI, IDUM)\n        STR = DAIR*BSUMDR - DAII*BSUMDI\n        STI = DAIR*BSUMDI + DAII*BSUMDR\n        STR = STR + (AIR*ASUMDR-AII*ASUMDI)\n        STI = STI + (AIR*ASUMDI+AII*ASUMDR)\n        PTR = STR*PHIDR - STI*PHIDI\n        PTI = STR*PHIDI + STI*PHIDR\n        S2R = PTR*CSR - PTI*CSI\n        S2I = PTR*CSI + PTI*CSR\n        STR = DEXP(S1R)*CSSR(IFLAG)\n        S1R = STR*DCOS(S1I)\n        S1I = STR*DSIN(S1I)\n        STR = S2R*S1R - S2I*S1I\n        S2I = S2R*S1I + S2I*S1R\n        S2R = STR\n        IF (IFLAG.NE.1) GO TO 250\n        CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL)\n        IF (NW.EQ.0) GO TO 250\n        S2R = ZEROR\n        S2I = ZEROI\n  250   CONTINUE\n        IF (YY.LE.0.0D0) S2I = -S2I\n        CYR(KDFLG) = S2R\n        CYI(KDFLG) = S2I\n        C2R = S2R\n        C2I = S2I\n        S2R = S2R*CSRR(IFLAG)\n        S2I = S2I*CSRR(IFLAG)\nC-----------------------------------------------------------------------\nC     ADD I AND K FUNCTIONS, K SEQUENCE IN Y(I), I=1,N\nC-----------------------------------------------------------------------\n        S1R = YR(KK)\n        S1I = YI(KK)\n        IF (KODE.EQ.1) GO TO 270\n        CALL ZS1S2(ZRR, ZRI, S1R, S1I, S2R, S2I, NW, ASC, ALIM, IUF)\n        NZ = NZ + NW\n  270   CONTINUE\n        YR(KK) = S1R*CSPNR - S1I*CSPNI + S2R\n        YI(KK) = S1R*CSPNI + S1I*CSPNR + S2I\n        KK = KK - 1\n        CSPNR = -CSPNR\n        CSPNI = -CSPNI\n        STR = CSI\n        CSI = -CSR\n        CSR = STR\n        IF (C2R.NE.0.0D0 .OR. C2I.NE.0.0D0) GO TO 255\n        KDFLG = 1\n        GO TO 290\n  255   CONTINUE\n        IF (KDFLG.EQ.2) GO TO 295\n        KDFLG = 2\n        GO TO 290\n  280   CONTINUE\n        IF (RS1.GT.0.0D0) GO TO 320\n        S2R = ZEROR\n        S2I = ZEROI\n        GO TO 250\n  290 CONTINUE\n      K = N\n  295 CONTINUE\n      IL = N - K\n      IF (IL.EQ.0) RETURN\nC-----------------------------------------------------------------------\nC     RECUR BACKWARD FOR REMAINDER OF I SEQUENCE AND ADD IN THE\nC     K FUNCTIONS, SCALING THE I SEQUENCE DURING RECURRENCE TO KEEP\nC     INTERMEDIATE ARITHMETIC ON SCALE NEAR EXPONENT EXTREMES.\nC-----------------------------------------------------------------------\n      S1R = CYR(1)\n      S1I = CYI(1)\n      S2R = CYR(2)\n      S2I = CYI(2)\n      CSR = CSRR(IFLAG)\n      ASCLE = BRY(IFLAG)\n      FN = DBLE(FLOAT(INU+IL))\n      DO 310 I=1,IL\n        C2R = S2R\n        C2I = S2I\n        S2R = S1R + (FN+FNF)*(RZR*C2R-RZI*C2I)\n        S2I = S1I + (FN+FNF)*(RZR*C2I+RZI*C2R)\n        S1R = C2R\n        S1I = C2I\n        FN = FN - 1.0D0\n        C2R = S2R*CSR\n        C2I = S2I*CSR\n        CKR = C2R\n        CKI = C2I\n        C1R = YR(KK)\n        C1I = YI(KK)\n        IF (KODE.EQ.1) GO TO 300\n        CALL ZS1S2(ZRR, ZRI, C1R, C1I, C2R, C2I, NW, ASC, ALIM, IUF)\n        NZ = NZ + NW\n  300   CONTINUE\n        YR(KK) = C1R*CSPNR - C1I*CSPNI + C2R\n        YI(KK) = C1R*CSPNI + C1I*CSPNR + C2I\n        KK = KK - 1\n        CSPNR = -CSPNR\n        CSPNI = -CSPNI\n        IF (IFLAG.GE.3) GO TO 310\n        C2R = DABS(CKR)\n        C2I = DABS(CKI)\n        C2M = DMAX1(C2R,C2I)\n        IF (C2M.LE.ASCLE) GO TO 310\n        IFLAG = IFLAG + 1\n        ASCLE = BRY(IFLAG)\n        S1R = S1R*CSR\n        S1I = S1I*CSR\n        S2R = CKR\n        S2I = CKI\n        S1R = S1R*CSSR(IFLAG)\n        S1I = S1I*CSSR(IFLAG)\n        S2R = S2R*CSSR(IFLAG)\n        S2I = S2I*CSSR(IFLAG)\n        CSR = CSRR(IFLAG)\n  310 CONTINUE\n      RETURN\n  320 CONTINUE\n      NZ = -1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zuoik.f",
    "content": "      SUBROUTINE ZUOIK(ZR, ZI, FNU, KODE, IKFLG, N, YR, YI, NUF, TOL,\n     * ELIM, ALIM)\nC***BEGIN PROLOGUE  ZUOIK\nC***REFER TO  ZBESI,ZBESK,ZBESH\nC\nC     ZUOIK COMPUTES THE LEADING TERMS OF THE UNIFORM ASYMPTOTIC\nC     EXPANSIONS FOR THE I AND K FUNCTIONS AND COMPARES THEM\nC     (IN LOGARITHMIC FORM) TO ALIM AND ELIM FOR OVER AND UNDERFLOW\nC     WHERE ALIM.LT.ELIM. IF THE MAGNITUDE, BASED ON THE LEADING\nC     EXPONENTIAL, IS LESS THAN ALIM OR GREATER THAN -ALIM, THEN\nC     THE RESULT IS ON SCALE. IF NOT, THEN A REFINED TEST USING OTHER\nC     MULTIPLIERS (IN LOGARITHMIC FORM) IS MADE BASED ON ELIM. HERE\nC     EXP(-ELIM)=SMALLEST MACHINE NUMBER*1.0E+3 AND EXP(-ALIM)=\nC     EXP(-ELIM)/TOL\nC\nC     IKFLG=1 MEANS THE I SEQUENCE IS TESTED\nC          =2 MEANS THE K SEQUENCE IS TESTED\nC     NUF = 0 MEANS THE LAST MEMBER OF THE SEQUENCE IS ON SCALE\nC         =-1 MEANS AN OVERFLOW WOULD OCCUR\nC     IKFLG=1 AND NUF.GT.0 MEANS THE LAST NUF Y VALUES WERE SET TO ZERO\nC             THE FIRST N-NUF VALUES MUST BE SET BY ANOTHER ROUTINE\nC     IKFLG=2 AND NUF.EQ.N MEANS ALL Y VALUES WERE SET TO ZERO\nC     IKFLG=2 AND 0.LT.NUF.LT.N NOT CONSIDERED. Y MUST BE SET BY\nC             ANOTHER ROUTINE\nC\nC***ROUTINES CALLED  ZUCHK,ZUNHJ,ZUNIK,D1MACH,XZABS,XZLOG\nC***END PROLOGUE  ZUOIK\nC     COMPLEX ARG,ASUM,BSUM,CWRK,CZ,CZERO,PHI,SUM,Y,Z,ZB,ZETA1,ZETA2,ZN,\nC    *ZR\n      DOUBLE PRECISION AARG, AIC, ALIM, APHI, ARGI, ARGR, ASUMI, ASUMR,\n     * ASCLE, AX, AY, BSUMI, BSUMR, CWRKI, CWRKR, CZI, CZR, ELIM, FNN,\n     * FNU, GNN, GNU, PHII, PHIR, RCZ, STR, STI, SUMI, SUMR, TOL, YI,\n     * YR, ZBI, ZBR, ZEROI, ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, ZI,\n     * ZNI, ZNR, ZR, ZRI, ZRR, D1MACH, XZABS\n      INTEGER I, IDUM, IFORM, IKFLG, INIT, KODE, N, NN, NUF, NW\n      DIMENSION YR(N), YI(N), CWRKR(16), CWRKI(16)\n      DATA ZEROR,ZEROI / 0.0D0, 0.0D0 /\n      DATA AIC / 1.265512123484645396D+00 /\n      NUF = 0\n      NN = N\n      ZRR = ZR\n      ZRI = ZI\n      IF (ZR.GE.0.0D0) GO TO 10\n      ZRR = -ZR\n      ZRI = -ZI\n   10 CONTINUE\n      ZBR = ZRR\n      ZBI = ZRI\n      AX = DABS(ZR)*1.7321D0\n      AY = DABS(ZI)\n      IFORM = 1\n      IF (AY.GT.AX) IFORM = 2\n      GNU = DMAX1(FNU,1.0D0)\n      IF (IKFLG.EQ.1) GO TO 20\n      FNN = DBLE(FLOAT(NN))\n      GNN = FNU + FNN - 1.0D0\n      GNU = DMAX1(GNN,FNN)\n   20 CONTINUE\nC-----------------------------------------------------------------------\nC     ONLY THE MAGNITUDE OF ARG AND PHI ARE NEEDED ALONG WITH THE\nC     REAL PARTS OF ZETA1, ZETA2 AND ZB. NO ATTEMPT IS MADE TO GET\nC     THE SIGN OF THE IMAGINARY PART CORRECT.\nC-----------------------------------------------------------------------\n      IF (IFORM.EQ.2) GO TO 30\n      INIT = 0\n      CALL ZUNIK(ZRR, ZRI, GNU, IKFLG, 1, TOL, INIT, PHIR, PHII,\n     * ZETA1R, ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI)\n      CZR = -ZETA1R + ZETA2R\n      CZI = -ZETA1I + ZETA2I\n      GO TO 50\n   30 CONTINUE\n      ZNR = ZRI\n      ZNI = -ZRR\n      IF (ZI.GT.0.0D0) GO TO 40\n      ZNR = -ZNR\n   40 CONTINUE\n      CALL ZUNHJ(ZNR, ZNI, GNU, 1, TOL, PHIR, PHII, ARGR, ARGI, ZETA1R,\n     * ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI)\n      CZR = -ZETA1R + ZETA2R\n      CZI = -ZETA1I + ZETA2I\n      AARG = XZABS(ARGR,ARGI)\n   50 CONTINUE\n      IF (KODE.EQ.1) GO TO 60\n      CZR = CZR - ZBR\n      CZI = CZI - ZBI\n   60 CONTINUE\n      IF (IKFLG.EQ.1) GO TO 70\n      CZR = -CZR\n      CZI = -CZI\n   70 CONTINUE\n      APHI = XZABS(PHIR,PHII)\n      RCZ = CZR\nC-----------------------------------------------------------------------\nC     OVERFLOW TEST\nC-----------------------------------------------------------------------\n      IF (RCZ.GT.ELIM) GO TO 210\n      IF (RCZ.LT.ALIM) GO TO 80\n      RCZ = RCZ + DLOG(APHI)\n      IF (IFORM.EQ.2) RCZ = RCZ - 0.25D0*DLOG(AARG) - AIC\n      IF (RCZ.GT.ELIM) GO TO 210\n      GO TO 130\n   80 CONTINUE\nC-----------------------------------------------------------------------\nC     UNDERFLOW TEST\nC-----------------------------------------------------------------------\n      IF (RCZ.LT.(-ELIM)) GO TO 90\n      IF (RCZ.GT.(-ALIM)) GO TO 130\n      RCZ = RCZ + DLOG(APHI)\n      IF (IFORM.EQ.2) RCZ = RCZ - 0.25D0*DLOG(AARG) - AIC\n      IF (RCZ.GT.(-ELIM)) GO TO 110\n   90 CONTINUE\n      DO 100 I=1,NN\n        YR(I) = ZEROR\n        YI(I) = ZEROI\n  100 CONTINUE\n      NUF = NN\n      RETURN\n  110 CONTINUE\n      ASCLE = 1.0D+3*D1MACH(1)/TOL\n      CALL XZLOG(PHIR, PHII, STR, STI, IDUM)\n      CZR = CZR + STR\n      CZI = CZI + STI\n      IF (IFORM.EQ.1) GO TO 120\n      CALL XZLOG(ARGR, ARGI, STR, STI, IDUM)\n      CZR = CZR - 0.25D0*STR - AIC\n      CZI = CZI - 0.25D0*STI\n  120 CONTINUE\n      AX = DEXP(RCZ)/TOL\n      AY = CZI\n      CZR = AX*DCOS(AY)\n      CZI = AX*DSIN(AY)\n      CALL ZUCHK(CZR, CZI, NW, ASCLE, TOL)\n      IF (NW.NE.0) GO TO 90\n  130 CONTINUE\n      IF (IKFLG.EQ.2) RETURN\n      IF (N.EQ.1) RETURN\nC-----------------------------------------------------------------------\nC     SET UNDERFLOWS ON I SEQUENCE\nC-----------------------------------------------------------------------\n  140 CONTINUE\n      GNU = FNU + DBLE(FLOAT(NN-1))\n      IF (IFORM.EQ.2) GO TO 150\n      INIT = 0\n      CALL ZUNIK(ZRR, ZRI, GNU, IKFLG, 1, TOL, INIT, PHIR, PHII,\n     * ZETA1R, ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI)\n      CZR = -ZETA1R + ZETA2R\n      CZI = -ZETA1I + ZETA2I\n      GO TO 160\n  150 CONTINUE\n      CALL ZUNHJ(ZNR, ZNI, GNU, 1, TOL, PHIR, PHII, ARGR, ARGI, ZETA1R,\n     * ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI)\n      CZR = -ZETA1R + ZETA2R\n      CZI = -ZETA1I + ZETA2I\n      AARG = XZABS(ARGR,ARGI)\n  160 CONTINUE\n      IF (KODE.EQ.1) GO TO 170\n      CZR = CZR - ZBR\n      CZI = CZI - ZBI\n  170 CONTINUE\n      APHI = XZABS(PHIR,PHII)\n      RCZ = CZR\n      IF (RCZ.LT.(-ELIM)) GO TO 180\n      IF (RCZ.GT.(-ALIM)) RETURN\n      RCZ = RCZ + DLOG(APHI)\n      IF (IFORM.EQ.2) RCZ = RCZ - 0.25D0*DLOG(AARG) - AIC\n      IF (RCZ.GT.(-ELIM)) GO TO 190\n  180 CONTINUE\n      YR(NN) = ZEROR\n      YI(NN) = ZEROI\n      NN = NN - 1\n      NUF = NUF + 1\n      IF (NN.EQ.0) RETURN\n      GO TO 140\n  190 CONTINUE\n      ASCLE = 1.0D+3*D1MACH(1)/TOL\n      CALL XZLOG(PHIR, PHII, STR, STI, IDUM)\n      CZR = CZR + STR\n      CZI = CZI + STI\n      IF (IFORM.EQ.1) GO TO 200\n      CALL XZLOG(ARGR, ARGI, STR, STI, IDUM)\n      CZR = CZR - 0.25D0*STR - AIC\n      CZI = CZI - 0.25D0*STI\n  200 CONTINUE\n      AX = DEXP(RCZ)/TOL\n      AY = CZI\n      CZR = AX*DCOS(AY)\n      CZI = AX*DSIN(AY)\n      CALL ZUCHK(CZR, CZI, NW, ASCLE, TOL)\n      IF (NW.NE.0) GO TO 180\n      RETURN\n  210 CONTINUE\n      NUF = -1\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/amos/zwrsk.f",
    "content": "      SUBROUTINE ZWRSK(ZRR, ZRI, FNU, KODE, N, YR, YI, NZ, CWR, CWI,\n     * TOL, ELIM, ALIM)\nC***BEGIN PROLOGUE  ZWRSK\nC***REFER TO  ZBESI,ZBESK\nC\nC     ZWRSK COMPUTES THE I BESSEL FUNCTION FOR RE(Z).GE.0.0 BY\nC     NORMALIZING THE I FUNCTION RATIOS FROM ZRATI BY THE WRONSKIAN\nC\nC***ROUTINES CALLED  D1MACH,ZBKNU,ZRATI,XZABS\nC***END PROLOGUE  ZWRSK\nC     COMPLEX CINU,CSCL,CT,CW,C1,C2,RCT,ST,Y,ZR\n      DOUBLE PRECISION ACT, ACW, ALIM, ASCLE, CINUI, CINUR, CSCLR, CTI,\n     * CTR, CWI, CWR, C1I, C1R, C2I, C2R, ELIM, FNU, PTI, PTR, RACT,\n     * STI, STR, TOL, YI, YR, ZRI, ZRR, XZABS, D1MACH\n      INTEGER I, KODE, N, NW, NZ\n      DIMENSION YR(N), YI(N), CWR(2), CWI(2)\nC-----------------------------------------------------------------------\nC     I(FNU+I-1,Z) BY BACKWARD RECURRENCE FOR RATIOS\nC     Y(I)=I(FNU+I,Z)/I(FNU+I-1,Z) FROM CRATI NORMALIZED BY THE\nC     WRONSKIAN WITH K(FNU,Z) AND K(FNU+1,Z) FROM CBKNU.\nC-----------------------------------------------------------------------\n      NZ = 0\n      CALL ZBKNU(ZRR, ZRI, FNU, KODE, 2, CWR, CWI, NW, TOL, ELIM, ALIM)\n      IF (NW.NE.0) GO TO 50\n      CALL ZRATI(ZRR, ZRI, FNU, N, YR, YI, TOL)\nC-----------------------------------------------------------------------\nC     RECUR FORWARD ON I(FNU+1,Z) = R(FNU,Z)*I(FNU,Z),\nC     R(FNU+J-1,Z)=Y(J),  J=1,...,N\nC-----------------------------------------------------------------------\n      CINUR = 1.0D0\n      CINUI = 0.0D0\n      IF (KODE.EQ.1) GO TO 10\n      CINUR = DCOS(ZRI)\n      CINUI = DSIN(ZRI)\n   10 CONTINUE\nC-----------------------------------------------------------------------\nC     ON LOW EXPONENT MACHINES THE K FUNCTIONS CAN BE CLOSE TO BOTH\nC     THE UNDER AND OVERFLOW LIMITS AND THE NORMALIZATION MUST BE\nC     SCALED TO PREVENT OVER OR UNDERFLOW. CUOIK HAS DETERMINED THAT\nC     THE RESULT IS ON SCALE.\nC-----------------------------------------------------------------------\n      ACW = XZABS(CWR(2),CWI(2))\n      ASCLE = 1.0D+3*D1MACH(1)/TOL\n      CSCLR = 1.0D0\n      IF (ACW.GT.ASCLE) GO TO 20\n      CSCLR = 1.0D0/TOL\n      GO TO 30\n   20 CONTINUE\n      ASCLE = 1.0D0/ASCLE\n      IF (ACW.LT.ASCLE) GO TO 30\n      CSCLR = TOL\n   30 CONTINUE\n      C1R = CWR(1)*CSCLR\n      C1I = CWI(1)*CSCLR\n      C2R = CWR(2)*CSCLR\n      C2I = CWI(2)*CSCLR\n      STR = YR(1)\n      STI = YI(1)\nC-----------------------------------------------------------------------\nC     CINU=CINU*(CONJG(CT)/CABS(CT))*(1.0D0/CABS(CT) PREVENTS\nC     UNDER- OR OVERFLOW PREMATURELY BY SQUARING CABS(CT)\nC-----------------------------------------------------------------------\n      PTR = STR*C1R - STI*C1I\n      PTI = STR*C1I + STI*C1R\n      PTR = PTR + C2R\n      PTI = PTI + C2I\n      CTR = ZRR*PTR - ZRI*PTI\n      CTI = ZRR*PTI + ZRI*PTR\n      ACT = XZABS(CTR,CTI)\n      RACT = 1.0D0/ACT\n      CTR = CTR*RACT\n      CTI = -CTI*RACT\n      PTR = CINUR*RACT\n      PTI = CINUI*RACT\n      CINUR = PTR*CTR - PTI*CTI\n      CINUI = PTR*CTI + PTI*CTR\n      YR(1) = CINUR*CSCLR\n      YI(1) = CINUI*CSCLR\n      IF (N.EQ.1) RETURN\n      DO 40 I=2,N\n        PTR = STR*CINUR - STI*CINUI\n        CINUI = STR*CINUI + STI*CINUR\n        CINUR = PTR\n        STR = YR(I)\n        STI = YI(I)\n        YR(I) = CINUR*CSCLR\n        YI(I) = CINUI*CSCLR\n   40 CONTINUE\n      RETURN\n   50 CONTINUE\n      NZ = -1\n      IF(NW.EQ.(-2)) NZ=-2\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/blas-xtra/cdotc3.f",
    "content": "c Copyright (C) 2009-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      subroutine cdotc3(m,n,k,a,b,c)\nc purpose:      a 3-dimensional dot product.\nc               c = sum (conj (a) .* b, 2), where a and b are 3d arrays.\nc arguments:\nc m,n,k (in)    the dimensions of a and b\nc a,b (in)      complex input arrays of size (m,k,n)\nc c (out)       complex output array, size (m,n)\n      integer m,n,k,i,j,l\n      complex a(m,k,n),b(m,k,n)\n      complex c(m,n)\n\n      complex cdotc\n      external cdotc\n\nc quick return if possible.\n      if (m <= 0 .or. n <= 0) return\n\n      if (m == 1) then\nc the column-major case.\n        do j = 1,n\n          c(1,j) = cdotc(k,a(1,1,j),1,b(1,1,j),1)\n        end do\n      else\nc We prefer performance here, because that's what we generally\nc do by default in reduction functions. Besides, the accuracy\nc of xDOT is questionable. Hence, do a cache-aligned nested loop.\n        do j = 1,n\n          do i = 1,m\n            c(i,j) = 0e0\n          end do\n          do l = 1,k\n            do i = 1,m\n              c(i,j) = c(i,j) + conjg(a(i,l,j))*b(i,l,j)\n            end do\n          end do\n        end do\n      end if\n\n      end subroutine\n"
  },
  {
    "path": "liboctave/external/blas-xtra/cmatm3.f",
    "content": "c Copyright (C) 2009-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      subroutine cmatm3(m,n,k,np,a,b,c)\nc purpose:      a 3-dimensional matrix product.\nc               given a (m,k,np) array a and (k,n,np) array b,\nc               calculates a (m,n,np) array c such that\nc                 for i = 1:np\nc                 c(:,:,i) = a(:,:,i) * b(:,:,i)\nc\nc arguments:\nc m,n,k (in)    the dimensions\nc np (in)       number of multiplications\nc a (in)        a complex input array, size (m,k,np)\nc b (in)        a complex input array, size (k,n,np)\nc c (out)       a complex output array, size (m,n,np)\n      integer m,n,k,np\n      complex a(m*k,np),b(k*n,np)\n      complex c(m*n,np)\n\n      complex cdotu,one,zero\n      parameter (one = 1e0, zero = 0e0)\n      external cdotu,cgemv,cgemm\n      integer i\n\nc quick return if possible.\n      if (np <= 0) return\n\n      if (m == 1) then\n        if (n == 1) then\n          do i = 1,np\n            c(1,i) = cdotu(k,a(1,i),1,b(1,i),1)\n          end do\n        else\n          do i = 1,np\n            call cgemv(\"T\",k,n,one,b(1,i),k,a(1,i),1,zero,c(1,i),1)\n          end do\n        end if\n      else\n        if (n == 1) then\n          do i = 1,np\n            call cgemv(\"N\",m,k,one,a(1,i),m,b(1,i),1,zero,c(1,i),1)\n          end do\n        else\n          do i = 1,np\n            call cgemm(\"N\",\"N\",m,n,k,\n     +                 one,a(1,i),m,b(1,i),k,zero,c(1,i),m)\n          end do\n        end if\n      end if\n\n      end subroutine\n"
  },
  {
    "path": "liboctave/external/blas-xtra/ddot3.f",
    "content": "c Copyright (C) 2009-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      subroutine ddot3(m,n,k,a,b,c)\nc purpose:      a 3-dimensional dot product.\nc               c = sum (a .* b, 2), where a and b are 3d arrays.\nc arguments:\nc m,n,k (in)    the dimensions of a and b\nc a,b (in)      double prec. input arrays of size (m,k,n)\nc c (out)       double prec. output array, size (m,n)\n      integer m,n,k,i,j,l\n      double precision a(m,k,n),b(m,k,n)\n      double precision c(m,n)\n\n      double precision ddot\n      external ddot\n\n\nc quick return if possible.\n      if (m <= 0 .or. n <= 0) return\n\n      if (m == 1) then\nc the column-major case.\n        do j = 1,n\n          c(1,j) = ddot(k,a(1,1,j),1,b(1,1,j),1)\n        end do\n      else\nc We prefer performance here, because that's what we generally\nc do by default in reduction functions. Besides, the accuracy\nc of xDOT is questionable. Hence, do a cache-aligned nested loop.\n        do j = 1,n\n          do i = 1,m\n            c(i,j) = 0d0\n          end do\n          do l = 1,k\n            do i = 1,m\n              c(i,j) = c(i,j) + a(i,l,j)*b(i,l,j)\n            end do\n          end do\n        end do\n      end if\n\n      end subroutine\n"
  },
  {
    "path": "liboctave/external/blas-xtra/dmatm3.f",
    "content": "c Copyright (C) 2009-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      subroutine dmatm3(m,n,k,np,a,b,c)\nc purpose:      a 3-dimensional matrix product.\nc               given a (m,k,np) array a and (k,n,np) array b,\nc               calculates a (m,n,np) array c such that\nc                 for i = 1:np\nc                 c(:,:,i) = a(:,:,i) * b(:,:,i)\nc\nc arguments:\nc m,n,k (in)    the dimensions\nc np (in)       number of multiplications\nc a (in)        a double prec. input array, size (m,k,np)\nc b (in)        a double prec. input array, size (k,n,np)\nc c (out)       a double prec. output array, size (m,n,np)\n      integer m,n,k,np\n      double precision a(m*k,np),b(k*n,np)\n      double precision c(m*n,np)\n\n      double precision ddot,one,zero\n      parameter (one = 1d0, zero = 0d0)\n      external ddot,dgemv,dgemm\n      integer i\n\nc quick return if possible.\n      if (np <= 0) return\n\n      if (m == 1) then\n        if (n == 1) then\n          do i = 1,np\n            c(1,i) = ddot(k,a(1,i),1,b(1,i),1)\n          end do\n        else\n          do i = 1,np\n            call dgemv(\"T\",k,n,one,b(1,i),k,a(1,i),1,zero,c(1,i),1)\n          end do\n        end if\n      else\n        if (n == 1) then\n          do i = 1,np\n            call dgemv(\"N\",m,k,one,a(1,i),m,b(1,i),1,zero,c(1,i),1)\n          end do\n        else\n          do i = 1,np\n            call dgemm(\"N\",\"N\",m,n,k,\n     +                 one,a(1,i),m,b(1,i),k,zero,c(1,i),m)\n          end do\n        end if\n      end if\n\n      end subroutine\n"
  },
  {
    "path": "liboctave/external/blas-xtra/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/ddot3.f \\\n  %reldir%/zdotc3.f \\\n  %reldir%/sdot3.f \\\n  %reldir%/cdotc3.f \\\n  %reldir%/dmatm3.f \\\n  %reldir%/zmatm3.f \\\n  %reldir%/smatm3.f \\\n  %reldir%/cmatm3.f \\\n  %reldir%/xddot.f \\\n  %reldir%/xdnrm2.f \\\n  %reldir%/xdznrm2.f \\\n  %reldir%/xzdotc.f \\\n  %reldir%/xzdotu.f \\\n  %reldir%/xsdot.f \\\n  %reldir%/xsnrm2.f \\\n  %reldir%/xscnrm2.f \\\n  %reldir%/xcdotc.f \\\n  %reldir%/xcdotu.f\n\nXERBLA_SRC = \\\n  %reldir%/xerbla.cc\n\n%canon_reldir%_libxerbla_la_SOURCES = $(XERBLA_SRC)\n\n%canon_reldir%_libxerbla_la_CPPFLAGS = \\\n  $(liboctave_liboctave_la_CPPFLAGS)\n\nif AMCOND_BUILD_EXTERNAL_LIBXERBLA\n  octlib_LTLIBRARIES += %reldir%/libxerbla.la\n\n  %canon_reldir%_libxerbla_la_LDFLAGS = \\\n    -avoid-version \\\n    $(NO_UNDEFINED_LDFLAG) \\\n    -bindir $(bindir) \\\n    $(WARN_LDFLAGS)\nelse\n  noinst_LTLIBRARIES += %reldir%/libxerbla.la\n\n  liboctave_liboctave_la_LIBADD += %reldir%/libxerbla.la\nendif\n"
  },
  {
    "path": "liboctave/external/blas-xtra/sdot3.f",
    "content": "c Copyright (C) 2009-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      subroutine sdot3(m,n,k,a,b,c)\nc purpose:      a 3-dimensional dot product.\nc               c = sum (a .* b, 2), where a and b are 3d arrays.\nc arguments:\nc m,n,k (in)    the dimensions of a and b\nc a,b (in)      real input arrays of size (m,k,n)\nc c (out)       real output array, size (m,n)\n      integer m,n,k,i,j,l\n      real a(m,k,n),b(m,k,n)\n      real c(m,n)\n\n      real sdot\n      external sdot\n\nc quick return if possible.\n      if (m <= 0 .or. n <= 0) return\n\n      if (m == 1) then\nc the column-major case.\n        do j = 1,n\n          c(1,j) = sdot(k,a(1,1,j),1,b(1,1,j),1)\n        end do\n      else\nc We prefer performance here, because that's what we generally\nc do by default in reduction functions. Besides, the accuracy\nc of xDOT is questionable. Hence, do a cache-aligned nested loop.\n        do j = 1,n\n          do i = 1,m\n            c(i,j) = 0d0\n          end do\n          do l = 1,k\n            do i = 1,m\n              c(i,j) = c(i,j) + a(i,l,j)*b(i,l,j)\n            end do\n          end do\n        end do\n      end if\n\n      end subroutine\n"
  },
  {
    "path": "liboctave/external/blas-xtra/smatm3.f",
    "content": "c Copyright (C) 2009-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      subroutine smatm3(m,n,k,np,a,b,c)\nc purpose:      a 3-dimensional matrix product.\nc               given a (m,k,np) array a and (k,n,np) array b,\nc               calculates a (m,n,np) array c such that\nc                 for i = 1:np\nc                 c(:,:,i) = a(:,:,i) * b(:,:,i)\nc\nc arguments:\nc m,n,k (in)    the dimensions\nc np (in)       number of multiplications\nc a (in)        a real input array, size (m,k,np)\nc b (in)        a real input array, size (k,n,np)\nc c (out)       a real output array, size (m,n,np)\n      integer m,n,k,np\n      real a(m*k,np),b(k*n,np)\n      real c(m*n,np)\n\n      real sdot,one,zero\n      parameter (one = 1e0, zero = 0e0)\n      external sdot,sgemv,sgemm\n      integer i\n\nc quick return if possible.\n      if (np <= 0) return\n\n      if (m == 1) then\n        if (n == 1) then\n          do i = 1,np\n            c(1,i) = sdot(k,a(1,i),1,b(1,i),1)\n          end do\n        else\n          do i = 1,np\n            call sgemv(\"T\",k,n,one,b(1,i),k,a(1,i),1,zero,c(1,i),1)\n          end do\n        end if\n      else\n        if (n == 1) then\n          do i = 1,np\n            call sgemv(\"N\",m,k,one,a(1,i),m,b(1,i),1,zero,c(1,i),1)\n          end do\n        else\n          do i = 1,np\n            call sgemm(\"N\",\"N\",m,n,k,\n     +                 one,a(1,i),m,b(1,i),k,zero,c(1,i),m)\n          end do\n        end if\n      end if\n\n      end subroutine\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xcdotc.f",
    "content": "      subroutine xcdotc (n, zx, incx, zy, incy, retval)\n      complex cdotc, zx(*), zy(*), retval\n      integer n, incx, incy\n      external cdotc\n      retval = cdotc (n, zx, incx, zy, incy)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xcdotu.f",
    "content": "      subroutine xcdotu (n, zx, incx, zy, incy, retval)\n      complex cdotu, zx(*), zy(*), retval\n      integer n, incx, incy\n      external cdotu\n      retval = cdotu (n, zx, incx, zy, incy)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xddot.f",
    "content": "      subroutine xddot (n, dx, incx, dy, incy, retval)\n      double precision ddot, dx(*), dy(*), retval\n      integer n, incx, incy\n      retval = ddot (n, dx, incx, dy, incy)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xdnrm2.f",
    "content": "      subroutine xdnrm2 (n, x, incx, retval)\n      double precision dnrm2, x(*), retval\n      integer n, incx\n      retval = dnrm2 (n, x, incx)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xdznrm2.f",
    "content": "      subroutine xdznrm2 (n, x, incx, retval)\n      double precision dznrm2, retval\n      double complex x(*)\n      integer n, incx\n      retval = dznrm2 (n, x, incx)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xerbla.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n\n#include \"blas-proto.h\"\n#include \"f77-fcn.h\"\n\ntypedef void (*xerbla_handler_fptr) (void);\n\n/* Pointer to function to call to handle error.  In the Octave\n   interpreter we set this to a function that throws an exception and\n   transfers control to the enclosing try/catch block.  That is\n   typically at the top-level REPL.\n\n   We must use a function pointer instead of simply calling error\n   directly here because this function is called by LAPACK and BLAS\n   subroutines.  To build shared libraries of those packages on Windows\n   requires that all symbols be known when the shared library is\n   constructed.  If we call error directly, that would mean that the\n   BLAS and LAPACK libraries would have to depend on Octave...  */\n\nstatic xerbla_handler_fptr xerbla_handler = nullptr;\n\nextern \"C\" void\noctave_set_xerbla_handler (xerbla_handler_fptr fcn)\n{\n  xerbla_handler = fcn;\n}\n\n/* Replacement for BLAS and LAPACK XERBLA subroutine that calls an\n   optionally installed handler function.  */\n\nF77_RET_T\nF77_FUNC (xerbla, XERBLA) (F77_CONST_CHAR_ARG_DEF (s_arg, len),\n                           const F77_INT& info\n                           F77_CHAR_ARG_LEN_DEF (len))\n{\n  const char *s = F77_CHAR_ARG_USE (s_arg);\n  int slen = F77_CHAR_ARG_LEN_USE (s_arg, len);\n\n  std::cerr << std::string (s, slen) << \": parameter number \" << info\n            << \" is invalid\" << std::endl;\n\n  if (xerbla_handler)\n    (*xerbla_handler) ();\n\n  F77_RETURN (0)\n}\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xscnrm2.f",
    "content": "      subroutine xscnrm2 (n, x, incx, retval)\n      real scnrm2, retval\n      complex x(*)\n      integer n, incx\n      retval = scnrm2 (n, x, incx)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xsdot.f",
    "content": "      subroutine xsdot (n, dx, incx, dy, incy, retval)\n      real ddot, dx(*), dy(*), retval, sdot\n      integer n, incx, incy\n      retval = sdot (n, dx, incx, dy, incy)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xsnrm2.f",
    "content": "      subroutine xsnrm2 (n, x, incx, retval)\n      real snrm2, x(*), retval\n      integer n, incx\n      retval = snrm2 (n, x, incx)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xzdotc.f",
    "content": "      subroutine xzdotc (n, zx, incx, zy, incy, retval)\n      double complex zdotc, zx(*), zy(*), retval\n      integer n, incx, incy\n      external zdotc\n      retval = zdotc (n, zx, incx, zy, incy)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/xzdotu.f",
    "content": "      subroutine xzdotu (n, zx, incx, zy, incy, retval)\n      double complex zdotu, zx(*), zy(*), retval\n      integer n, incx, incy\n      external zdotu\n      retval = zdotu (n, zx, incx, zy, incy)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/blas-xtra/zdotc3.f",
    "content": "c Copyright (C) 2009-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      subroutine zdotc3(m,n,k,a,b,c)\nc purpose:      a 3-dimensional dot product.\nc               c = sum (conj (a) .* b, 2), where a and b are 3d arrays.\nc arguments:\nc m,n,k (in)    the dimensions of a and b\nc a,b (in)      double complex input arrays of size (m,k,n)\nc c (out)       double complex output array, size (m,n)\n      integer m,n,k,i,j,l\n      double complex a(m,k,n),b(m,k,n)\n      double complex c(m,n)\n\n      double complex zdotc\n      external zdotc\n\nc quick return if possible.\n      if (m <= 0 .or. n <= 0) return\n\n      if (m == 1) then\nc the column-major case.\n        do j = 1,n\n          c(1,j) = zdotc(k,a(1,1,j),1,b(1,1,j),1)\n        end do\n      else\nc We prefer performance here, because that's what we generally\nc do by default in reduction functions. Besides, the accuracy\nc of xDOT is questionable. Hence, do a cache-aligned nested loop.\n        do j = 1,n\n          do i = 1,m\n            c(i,j) = 0d0\n          end do\n          do l = 1,k\n            do i = 1,m\n              c(i,j) = c(i,j) + conjg(a(i,l,j))*b(i,l,j)\n            end do\n          end do\n        end do\n      end if\n\n      end subroutine\n"
  },
  {
    "path": "liboctave/external/blas-xtra/zmatm3.f",
    "content": "c Copyright (C) 2009-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      subroutine zmatm3(m,n,k,np,a,b,c)\nc purpose:      a 3-dimensional matrix product.\nc               given a (m,k,np) array a and (k,n,np) array b,\nc               calculates a (m,n,np) array c such that\nc                 for i = 1:np\nc                 c(:,:,i) = a(:,:,i) * b(:,:,i)\nc\nc arguments:\nc m,n,k (in)    the dimensions\nc np (in)       number of multiplications\nc a (in)        a double complex input array, size (m,k,np)\nc b (in)        a double complex input array, size (k,n,np)\nc c (out)       a double complex output array, size (m,n,np)\n      integer m,n,k,np\n      double complex a(m*k,np),b(k*n,np)\n      double complex c(m*n,np)\n\n      double complex zdotu,one,zero\n      parameter (one = 1d0, zero = 0d0)\n      external zdotu,zgemv,zgemm\n      integer i\n\nc quick return if possible.\n      if (np <= 0) return\n\n      if (m == 1) then\n        if (n == 1) then\n          do i = 1,np\n            c(1,i) = zdotu(k,a(1,i),1,b(1,i),1)\n          end do\n        else\n          do i = 1,np\n            call zgemv(\"T\",k,n,one,b(1,i),k,a(1,i),1,zero,c(1,i),1)\n          end do\n        end if\n      else\n        if (n == 1) then\n          do i = 1,np\n            call zgemv(\"N\",m,k,one,a(1,i),m,b(1,i),1,zero,c(1,i),1)\n          end do\n        else\n          do i = 1,np\n            call zgemm(\"N\",\"N\",m,n,k,\n     +                 one,a(1,i),m,b(1,i),k,zero,c(1,i),m)\n          end do\n        end if\n      end if\n\n      end subroutine\n"
  },
  {
    "path": "liboctave/external/daspk/datv.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DATV (NEQ, Y, TN, YPRIME, SAVR, V, WGHT, YPTEM, RES,\n     *   IRES, PSOL, Z, VTEM, WP, IWP, CJ, EPLIN, IER, NRE, NPSL,\n     *   RPAR,IPAR)\nC\nC***BEGIN PROLOGUE  DATV\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC This routine computes the product\nC\nC   Z = (D-inverse)*(P-inverse)*(dF/dY)*(D*V),\nC\nC where F(Y) = G(T, Y, CJ*(Y-A)), CJ is a scalar proportional to 1/H,\nC and A involves the past history of Y.  The quantity CJ*(Y-A) is\nC an approximation to the first derivative of Y and is stored\nC in the array YPRIME.  Note that dF/dY = dG/dY + CJ*dG/dYPRIME.\nC\nC D is a diagonal scaling matrix, and P is the left preconditioning\nC matrix.  V is assumed to have L2 norm equal to 1.\nC The product is stored in Z and is computed by means of a\nC difference quotient, a call to RES, and one call to PSOL.\nC\nC      On entry\nC\nC          NEQ = Problem size, passed to RES and PSOL.\nC\nC            Y = Array containing current dependent variable vector.\nC\nC       YPRIME = Array containing current first derivative of y.\nC\nC         SAVR = Array containing current value of G(T,Y,YPRIME).\nC\nC            V = Real array of length NEQ (can be the same array as Z).\nC\nC         WGHT = Array of length NEQ containing scale factors.\nC                1/WGHT(I) are the diagonal elements of the matrix D.\nC\nC        YPTEM = Work array of length NEQ.\nC\nC         VTEM = Work array of length NEQ used to store the\nC                unscaled version of V.\nC\nC         WP = Real work array used by preconditioner PSOL.\nC\nC         IWP = Integer work array used by preconditioner PSOL.\nC\nC           CJ = Scalar proportional to current value of\nC                1/(step size H).\nC\nC\nC      On return\nC\nC            Z = Array of length NEQ containing desired scaled\nC                matrix-vector product.\nC\nC         IRES = Error flag from RES.\nC\nC          IER = Error flag from PSOL.\nC\nC         NRE  = The number of calls to RES.\nC\nC         NPSL = The number of calls to PSOL.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   RES, PSOL\nC\nC***END PROLOGUE  DATV\nC\n      INTEGER NEQ, IRES, IWP, IER, NRE, NPSL, IPAR\n      DOUBLE PRECISION Y, TN, YPRIME, SAVR, V, WGHT, YPTEM, Z, VTEM,\n     1   WP, CJ, RPAR\n      DIMENSION Y(*), YPRIME(*), SAVR(*), V(*), WGHT(*), YPTEM(*),\n     1   Z(*), VTEM(*), WP(*), IWP(*), RPAR(*), IPAR(*)\n      INTEGER I\n      DOUBLE PRECISION EPLIN\n      EXTERNAL  RES, PSOL\nC\n      IRES = 0\nC-----------------------------------------------------------------------\nC Set VTEM = D * V.\nC-----------------------------------------------------------------------\n      DO 10 I = 1,NEQ\n 10     VTEM(I) = V(I)/WGHT(I)\n      IER = 0\nC-----------------------------------------------------------------------\nC Store Y in Z and increment Z by VTEM.\nC Store YPRIME in YPTEM and increment YPTEM by VTEM*CJ.\nC-----------------------------------------------------------------------\n      DO 20 I = 1,NEQ\n        YPTEM(I) = YPRIME(I) + VTEM(I)*CJ\n 20     Z(I) = Y(I) + VTEM(I)\nC-----------------------------------------------------------------------\nC Call RES with incremented Y, YPRIME arguments\nC stored in Z, YPTEM.  VTEM is overwritten with new residual.\nC-----------------------------------------------------------------------\n      CONTINUE\n      CALL RES(TN,Z,YPTEM,CJ,VTEM,IRES,RPAR,IPAR)\n      NRE = NRE + 1\n      IF (IRES .LT. 0) RETURN\nC-----------------------------------------------------------------------\nC Set Z = (dF/dY) * VBAR using difference quotient.\nC (VBAR is old value of VTEM before calling RES)\nC-----------------------------------------------------------------------\n      DO 70 I = 1,NEQ\n 70     Z(I) = VTEM(I) - SAVR(I)\nC-----------------------------------------------------------------------\nC Apply inverse of left preconditioner to Z.\nC-----------------------------------------------------------------------\n      CALL PSOL (NEQ, TN, Y, YPRIME, SAVR, YPTEM, CJ, WGHT, WP, IWP,\n     1   Z, EPLIN, IER, RPAR, IPAR)\n      NPSL = NPSL + 1\n      IF (IER .NE. 0) RETURN\nC-----------------------------------------------------------------------\nC Apply D-inverse to Z and return.\nC-----------------------------------------------------------------------\n      DO 90 I = 1,NEQ\n 90     Z(I) = Z(I)*WGHT(I)\n      RETURN\nC\nC------END OF SUBROUTINE DATV-------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dcnst0.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DCNST0 (NEQ, Y, ICNSTR, IRET)\nC\nC***BEGIN PROLOGUE  DCNST0\nC***DATE WRITTEN   950808   (YYMMDD)\nC***REVISION DATE  950808   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC This subroutine checks for constraint violations in the initial\nC approximate solution u.\nC\nC On entry\nC\nC   NEQ    -- size of the nonlinear system, and the length of arrays\nC             Y and ICNSTR.\nC\nC   Y      -- real array containing the initial approximate root.\nC\nC   ICNSTR -- INTEGER array of length NEQ containing flags indicating\nC             which entries in Y are to be constrained.\nC             if ICNSTR(I) =  2, then Y(I) must be .GT. 0,\nC             if ICNSTR(I) =  1, then Y(I) must be .GE. 0,\nC             if ICNSTR(I) = -1, then Y(I) must be .LE. 0, while\nC             if ICNSTR(I) = -2, then Y(I) must be .LT. 0, while\nC             if ICNSTR(I) =  0, then Y(I) is not constrained.\nC\nC On return\nC\nC   IRET   -- output flag.\nC             IRET=0    means that u satisfied all constraints.\nC             IRET.NE.0 means that Y(IRET) failed to satisfy its\nC                       constraint.\nC\nC-----------------------------------------------------------------------\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(NEQ), ICNSTR(NEQ)\n      SAVE ZERO\n      DATA ZERO/0.D0/\nC-----------------------------------------------------------------------\nC Check constraints for initial Y.  If a constraint has been violated,\nC set IRET = I to signal an error return to calling routine.\nC-----------------------------------------------------------------------\n      IRET = 0\n      DO 100 I = 1,NEQ\n         IF (ICNSTR(I) .EQ. 2) THEN\n            IF (Y(I) .LE. ZERO) THEN\n               IRET = I\n               RETURN\n            ENDIF\n         ELSEIF (ICNSTR(I) .EQ. 1) THEN\n            IF (Y(I) .LT. ZERO) THEN\n               IRET = I\n               RETURN\n            ENDIF\n         ELSEIF (ICNSTR(I) .EQ. -1) THEN\n            IF (Y(I) .GT. ZERO) THEN\n               IRET = I\n               RETURN\n            ENDIF\n         ELSEIF (ICNSTR(I) .EQ. -2) THEN\n            IF (Y(I) .GE. ZERO) THEN\n               IRET = I\n               RETURN\n            ENDIF\n        ENDIF\n 100  CONTINUE\n      RETURN\nC----------------------- END OF SUBROUTINE DCNST0 ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dcnstr.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DCNSTR (NEQ, Y, YNEW, ICNSTR, TAU, RLX, IRET, IVAR)\nC\nC***BEGIN PROLOGUE  DCNSTR\nC***DATE WRITTEN   950808   (YYMMDD)\nC***REVISION DATE  950814   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC This subroutine checks for constraint violations in the proposed\nC new approximate solution YNEW.\nC If a constraint violation occurs, then a new step length, TAU,\nC is calculated, and this value is to be given to the linesearch routine\nC to calculate a new approximate solution YNEW.\nC\nC On entry:\nC\nC   NEQ    -- size of the nonlinear system, and the length of arrays\nC             Y, YNEW and ICNSTR.\nC\nC   Y      -- real array containing the current approximate y.\nC\nC   YNEW   -- real array containing the new approximate y.\nC\nC   ICNSTR -- INTEGER array of length NEQ containing flags indicating\nC             which entries in YNEW are to be constrained.\nC             if ICNSTR(I) =  2, then YNEW(I) must be .GT. 0,\nC             if ICNSTR(I) =  1, then YNEW(I) must be .GE. 0,\nC             if ICNSTR(I) = -1, then YNEW(I) must be .LE. 0, while\nC             if ICNSTR(I) = -2, then YNEW(I) must be .LT. 0, while\nC             if ICNSTR(I) =  0, then YNEW(I) is not constrained.\nC\nC   RLX    -- real scalar restricting update, if ICNSTR(I) = 2 or -2,\nC             to ABS( (YNEW-Y)/Y ) < FAC2*RLX in component I.\nC\nC   TAU    -- the current size of the step length for the linesearch.\nC\nC On return\nC\nC   TAU    -- the adjusted size of the step length if a constraint\nC             violation occurred (otherwise, it is unchanged).  it is\nC             the step length to give to the linesearch routine.\nC\nC   IRET   -- output flag.\nC             IRET=0 means that YNEW satisfied all constraints.\nC             IRET=1 means that YNEW failed to satisfy all the\nC                    constraints, and a new linesearch step\nC                    must be computed.\nC\nC   IVAR   -- index of variable causing constraint to be violated.\nC\nC-----------------------------------------------------------------------\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(NEQ), YNEW(NEQ), ICNSTR(NEQ)\n      SAVE FAC, FAC2, ZERO\n      DATA FAC /0.6D0/, FAC2 /0.9D0/, ZERO/0.0D0/\nC-----------------------------------------------------------------------\nC Check constraints for proposed new step YNEW.  If a constraint has\nC been violated, then calculate a new step length, TAU, to be\nC used in the linesearch routine.\nC-----------------------------------------------------------------------\n      IRET = 0\n      RDYMX = ZERO\n      IVAR = 0\n      DO 100 I = 1,NEQ\nC\n         IF (ICNSTR(I) .EQ. 2) THEN\n            RDY = ABS( (YNEW(I)-Y(I))/Y(I) )\n            IF (RDY .GT. RDYMX) THEN\n               RDYMX = RDY\n               IVAR = I\n            ENDIF\n            IF (YNEW(I) .LE. ZERO) THEN\n               TAU = FAC*TAU\n               IVAR = I\n               IRET = 1\n               RETURN\n            ENDIF\nC\n         ELSEIF (ICNSTR(I) .EQ. 1) THEN\n            IF (YNEW(I) .LT. ZERO) THEN\n               TAU = FAC*TAU\n               IVAR = I\n               IRET = 1\n               RETURN\n            ENDIF\nC\n         ELSEIF (ICNSTR(I) .EQ. -1) THEN\n            IF (YNEW(I) .GT. ZERO) THEN\n               TAU = FAC*TAU\n               IVAR = I\n               IRET = 1\n               RETURN\n            ENDIF\nC\n         ELSEIF (ICNSTR(I) .EQ. -2) THEN\n            RDY = ABS( (YNEW(I)-Y(I))/Y(I) )\n            IF (RDY .GT. RDYMX) THEN\n               RDYMX = RDY\n               IVAR = I\n            ENDIF\n            IF (YNEW(I) .GE. ZERO) THEN\n               TAU = FAC*TAU\n               IVAR = I\n               IRET = 1\n               RETURN\n            ENDIF\nC\n         ENDIF\n 100  CONTINUE\n\n      IF(RDYMX .GE. RLX) THEN\n         TAU = FAC2*TAU*RLX/RDYMX\n         IRET = 1\n      ENDIF\nC\n      RETURN\nC----------------------- END OF SUBROUTINE DCNSTR ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/ddasic.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DDASIC (X, Y, YPRIME, NEQ, ICOPT, ID, RES, JAC, PSOL,\n     *   H, WT, NIC, IDID, RPAR, IPAR, PHI, SAVR, DELTA, E, YIC, YPIC,\n     *   PWK, WM, IWM, HMIN, UROUND, EPLI, SQRTN, RSQRTN, EPCONI,\n     *   STPTOL, JFLG, ICNFLG, ICNSTR, NLSIC)\nC\nC***BEGIN PROLOGUE  DDASIC\nC***REFER TO  DDASPK\nC***DATE WRITTEN   940628   (YYMMDD)\nC***REVISION DATE  941206   (YYMMDD)\nC***REVISION DATE  950714   (YYMMDD)\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DDASIC is a driver routine to compute consistent initial values\nC     for Y and YPRIME.  There are two different options:\nC     Denoting the differential variables in Y by Y_d, and\nC     the algebraic variables by Y_a, the problem solved is either:\nC     1.  Given Y_d, calculate Y_a and Y_d', or\nC     2.  Given Y', calculate Y.\nC     In either case, initial values for the given components\nC     are input, and initial guesses for the unknown components\nC     must also be provided as input.\nC\nC     The external routine NLSIC solves the resulting nonlinear system.\nC\nC     The parameters represent\nC\nC     X  --        Independent variable.\nC     Y  --        Solution vector at X.\nC     YPRIME --    Derivative of solution vector.\nC     NEQ --       Number of equations to be integrated.\nC     ICOPT     -- Flag indicating initial condition option chosen.\nC                    ICOPT = 1 for option 1 above.\nC                    ICOPT = 2 for option 2.\nC     ID        -- Array of dimension NEQ, which must be initialized\nC                  if option 1 is chosen.\nC                    ID(i) = +1 if Y_i is a differential variable,\nC                    ID(i) = -1 if Y_i is an algebraic variable.\nC     RES --       External user-supplied subroutine to evaluate the\nC                  residual.  See RES description in DDASPK prologue.\nC     JAC --       External user-supplied routine to update Jacobian\nC                  or preconditioner information in the nonlinear solver\nC                  (optional).  See JAC description in DDASPK prologue.\nC     PSOL --      External user-supplied routine to solve\nC                  a linear system using preconditioning.\nC                  See PSOL in DDASPK prologue.\nC     H --         Scaling factor in iteration matrix.  DDASIC may\nC                  reduce H to achieve convergence.\nC     WT --        Vector of weights for error criterion.\nC     NIC --       Input number of initial condition calculation call\nC                  (= 1 or 2).\nC     IDID --      Completion code.  See IDID in DDASPK prologue.\nC     RPAR,IPAR -- Real and integer parameter arrays that\nC                  are used for communication between the\nC                  calling program and external user routines.\nC                  They are not altered by DNSK\nC     PHI --       Work space for DDASIC of length at least 2*NEQ.\nC     SAVR --      Work vector for DDASIC of length NEQ.\nC     DELTA --     Work vector for DDASIC of length NEQ.\nC     E --         Work vector for DDASIC of length NEQ.\nC     YIC,YPIC --  Work vectors for DDASIC, each of length NEQ.\nC     PWK --       Work vector for DDASIC of length NEQ.\nC     WM,IWM --    Real and integer arrays storing\nC                  information required by the linear solver.\nC     EPCONI --    Test constant for Newton iteration convergence.\nC     ICNFLG --    Flag showing whether constraints on Y are to apply.\nC     ICNSTR --    Integer array of length NEQ with constraint types.\nC\nC     The other parameters are for use internally by DDASIC.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   DCOPY, NLSIC\nC\nC***END PROLOGUE  DDASIC\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),ID(*),WT(*),PHI(NEQ,*)\n      DIMENSION SAVR(*),DELTA(*),E(*),YIC(*),YPIC(*),PWK(*)\n      DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*), ICNSTR(*)\n      EXTERNAL RES, JAC, PSOL, NLSIC\nC\n      PARAMETER (LCFN=15)\n      PARAMETER (LMXNH=34)\nC\nC The following parameters are data-loaded here:\nC     RHCUT  = factor by which H is reduced on retry of Newton solve.\nC     RATEMX = maximum convergence rate for which Newton iteration\nC              is considered converging.\nC\n      SAVE RHCUT, RATEMX\n      DATA RHCUT/0.1D0/, RATEMX/0.8D0/\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 1.\nC     Initializations.\nC     JSKIP is a flag set to 1 when NIC = 2 and NH = 1, to signal that\nC     the initial call to the JAC routine is to be skipped then.\nC     Save Y and YPRIME in PHI.  Initialize IDID, NH, and CJ.\nC-----------------------------------------------------------------------\nC\n      MXNH = IWM(LMXNH)\n      IDID = 1\n      NH = 1\n      JSKIP = 0\n      IF (NIC .EQ. 2) JSKIP = 1\n      CALL DCOPY (NEQ, Y, 1, PHI(1,1), 1)\n      CALL DCOPY (NEQ, YPRIME, 1, PHI(1,2), 1)\nC\n      IF (ICOPT .EQ. 2) THEN\n        CJ = 0.0D0\n      ELSE\n        CJ = 1.0D0/H\n      ENDIF\nC\nC-----------------------------------------------------------------------\nC     BLOCK 2\nC     Call the nonlinear system solver to obtain\nC     consistent initial values for Y and YPRIME.\nC-----------------------------------------------------------------------\nC\n 200  CONTINUE\n      CALL NLSIC(X,Y,YPRIME,NEQ,ICOPT,ID,RES,JAC,PSOL,H,WT,JSKIP,\n     *   RPAR,IPAR,SAVR,DELTA,E,YIC,YPIC,PWK,WM,IWM,CJ,UROUND,\n     *   EPLI,SQRTN,RSQRTN,EPCONI,RATEMX,STPTOL,JFLG,ICNFLG,ICNSTR,\n     *   IERNLS)\nC\n      IF (IERNLS .EQ. 0) RETURN\nC\nC-----------------------------------------------------------------------\nC     BLOCK 3\nC     The nonlinear solver was unsuccessful.  Increment NCFN.\nC     Return with IDID = -12 if either\nC       IERNLS = -1: error is considered unrecoverable,\nC       ICOPT = 2: we are doing initialization problem type 2, or\nC       NH = MXNH: the maximum number of H values has been tried.\nC     Otherwise (problem 1 with IERNLS .GE. 1), reduce H and try again.\nC     If IERNLS > 1, restore Y and YPRIME to their original values.\nC-----------------------------------------------------------------------\nC\n      IWM(LCFN) = IWM(LCFN) + 1\n      JSKIP = 0\nC\n      IF (IERNLS .EQ. -1) GO TO 350\n      IF (ICOPT .EQ. 2) GO TO 350\n      IF (NH .EQ. MXNH) GO TO 350\nC\n      NH = NH + 1\n      H = H*RHCUT\n      CJ = 1.0D0/H\nC\n      IF (IERNLS .EQ. 1) GO TO 200\nC\n      CALL DCOPY (NEQ, PHI(1,1), 1, Y, 1)\n      CALL DCOPY (NEQ, PHI(1,2), 1, YPRIME, 1)\n      GO TO 200\nC\n 350  IDID = -12\n      RETURN\nC\nC------END OF SUBROUTINE DDASIC-----------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/ddasid.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DDASID(X,Y,YPRIME,NEQ,ICOPT,ID,RES,JACD,PDUM,H,WT,\n     *  JSDUM,RPAR,IPAR,DUMSVR,DELTA,R,YIC,YPIC,DUMPWK,WM,IWM,CJ,UROUND,\n     *  DUME,DUMS,DUMR,EPCON,RATEMX,STPTOL,JFDUM,\n     *  ICNFLG,ICNSTR,IERNLS)\nC\nC***BEGIN PROLOGUE  DDASID\nC***REFER TO  DDASPK\nC***DATE WRITTEN   940701   (YYMMDD)\nC***REVISION DATE  950808   (YYMMDD)\nC***REVISION DATE  951110   Removed unreachable block 390.\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC\nC     DDASID solves a nonlinear system of algebraic equations of the\nC     form G(X,Y,YPRIME) = 0 for the unknown parts of Y and YPRIME in\nC     the initial conditions.\nC\nC     The method used is a modified Newton scheme.\nC\nC     The parameters represent\nC\nC     X         -- Independent variable.\nC     Y         -- Solution vector.\nC     YPRIME    -- Derivative of solution vector.\nC     NEQ       -- Number of unknowns.\nC     ICOPT     -- Initial condition option chosen (1 or 2).\nC     ID        -- Array of dimension NEQ, which must be initialized\nC                  if ICOPT = 1.  See DDASIC.\nC     RES       -- External user-supplied subroutine to evaluate the\nC                  residual.  See RES description in DDASPK prologue.\nC     JACD      -- External user-supplied routine to evaluate the\nC                  Jacobian.  See JAC description for the case\nC                  INFO(12) = 0 in the DDASPK prologue.\nC     PDUM      -- Dummy argument.\nC     H         -- Scaling factor for this initial condition calc.\nC     WT        -- Vector of weights for error criterion.\nC     JSDUM     -- Dummy argument.\nC     RPAR,IPAR -- Real and integer arrays used for communication\nC                  between the calling program and external user\nC                  routines.  They are not altered within DASPK.\nC     DUMSVR    -- Dummy argument.\nC     DELTA     -- Work vector for NLS of length NEQ.\nC     R         -- Work vector for NLS of length NEQ.\nC     YIC,YPIC  -- Work vectors for NLS, each of length NEQ.\nC     DUMPWK    -- Dummy argument.\nC     WM,IWM    -- Real and integer arrays storing matrix information\nC                  such as the matrix of partial derivatives,\nC                  permutation vector, and various other information.\nC     CJ        -- Matrix parameter = 1/H (ICOPT = 1) or 0 (ICOPT = 2).\nC     UROUND    -- Unit roundoff.\nC     DUME      -- Dummy argument.\nC     DUMS      -- Dummy argument.\nC     DUMR      -- Dummy argument.\nC     EPCON     -- Tolerance to test for convergence of the Newton\nC                  iteration.\nC     RATEMX    -- Maximum convergence rate for which Newton iteration\nC                  is considered converging.\nC     JFDUM     -- Dummy argument.\nC     STPTOL    -- Tolerance used in calculating the minimum lambda\nC                  value allowed.\nC     ICNFLG    -- Integer scalar.  If nonzero, then constraint\nC                  violations in the proposed new approximate solution\nC                  will be checked for, and the maximum step length\nC                  will be adjusted accordingly.\nC     ICNSTR    -- Integer array of length NEQ containing flags for\nC                  checking constraints.\nC     IERNLS    -- Error flag for nonlinear solver.\nC                   0   ==> nonlinear solver converged.\nC                   1,2 ==> recoverable error inside nonlinear solver.\nC                           1 => retry with current Y, YPRIME\nC                           2 => retry with original Y, YPRIME\nC                  -1   ==> unrecoverable error in nonlinear solver.\nC\nC     All variables with \"DUM\" in their names are dummy variables\nC     which are not used in this routine.\nC\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   RES, DMATD, DNSID\nC\nC***END PROLOGUE  DDASID\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),ID(*),WT(*),ICNSTR(*)\n      DIMENSION DELTA(*),R(*),YIC(*),YPIC(*)\n      DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)\n      EXTERNAL  RES, JACD\nC\n      PARAMETER (LNRE=12, LNJE=13, LMXNIT=32, LMXNJ=33)\nC\nC\nC     Perform initializations.\nC\n      MXNIT = IWM(LMXNIT)\n      MXNJ = IWM(LMXNJ)\n      IERNLS = 0\n      NJ = 0\nC\nC     Call RES to initialize DELTA.\nC\n      IRES = 0\n      IWM(LNRE) = IWM(LNRE) + 1\n      CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)\n      IF (IRES .LT. 0) GO TO 370\nC\nC     Looping point for updating the Jacobian.\nC\n300   CONTINUE\nC\nC     Initialize all error flags to zero.\nC\n      IERJ = 0\n      IRES = 0\n      IERNEW = 0\nC\nC     Reevaluate the iteration matrix, J = dG/dY + CJ*dG/dYPRIME,\nC     where G(X,Y,YPRIME) = 0.\nC\n      NJ = NJ + 1\n      IWM(LNJE)=IWM(LNJE)+1\n      CALL DMATD(NEQ,X,Y,YPRIME,DELTA,CJ,H,IERJ,WT,R,\n     *              WM,IWM,RES,IRES,UROUND,JACD,RPAR,IPAR)\n      IF (IRES .LT. 0 .OR. IERJ .NE. 0) GO TO 370\nC\nC     Call the nonlinear Newton solver for up to MXNIT iterations.\nC\n      CALL DNSID(X,Y,YPRIME,NEQ,ICOPT,ID,RES,WT,RPAR,IPAR,DELTA,R,\n     *     YIC,YPIC,WM,IWM,CJ,EPCON,RATEMX,MXNIT,STPTOL,\n     *     ICNFLG,ICNSTR,IERNEW)\nC\n      IF (IERNEW .EQ. 1 .AND. NJ .LT. MXNJ) THEN\nC\nC        MXNIT iterations were done, the convergence rate is < 1,\nC        and the number of Jacobian evaluations is less than MXNJ.\nC        Call RES, reevaluate the Jacobian, and try again.\nC\n         IWM(LNRE)=IWM(LNRE)+1\n         CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)\n         IF (IRES .LT. 0) GO TO 370\n         GO TO 300\n         ENDIF\nC\n      IF (IERNEW .NE. 0) GO TO 380\n\n      RETURN\nC\nC\nC     Unsuccessful exits from nonlinear solver.\nC     Compute IERNLS accordingly.\nC\n370   IERNLS = 2\n      IF (IRES .LE. -2) IERNLS = -1\n      RETURN\nC\n380   IERNLS = MIN(IERNEW,2)\n      RETURN\nC\nC------END OF SUBROUTINE DDASID-----------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/ddasik.f",
    "content": "C Work perfored under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DDASIK(X,Y,YPRIME,NEQ,ICOPT,ID,RES,JACK,PSOL,H,WT,\n     *   JSKIP,RPAR,IPAR,SAVR,DELTA,R,YIC,YPIC,PWK,WM,IWM,CJ,UROUND,\n     *   EPLI,SQRTN,RSQRTN,EPCON,RATEMX,STPTOL,JFLG,\n     *   ICNFLG,ICNSTR,IERNLS)\nC\nC***BEGIN PROLOGUE  DDASIK\nC***REFER TO  DDASPK\nC***DATE WRITTEN   941026   (YYMMDD)\nC***REVISION DATE  950808   (YYMMDD)\nC***REVISION DATE  951110   Removed unreachable block 390.\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC\nC     DDASIK solves a nonlinear system of algebraic equations of the\nC     form G(X,Y,YPRIME) = 0 for the unknown parts of Y and YPRIME in\nC     the initial conditions.\nC\nC     An initial value for Y and initial guess for YPRIME are input.\nC\nC     The method used is a Newton scheme with Krylov iteration and a\nC     linesearch algorithm.\nC\nC     The parameters represent\nC\nC     X         -- Independent variable.\nC     Y         -- Solution vector at x.\nC     YPRIME    -- Derivative of solution vector.\nC     NEQ       -- Number of equations to be integrated.\nC     ICOPT     -- Initial condition option chosen (1 or 2).\nC     ID        -- Array of dimension NEQ, which must be initialized\nC                  if ICOPT = 1.  See DDASIC.\nC     RES       -- External user-supplied subroutine\nC                  to evaluate the residual.  See RES description\nC                  in DDASPK prologue.\nC     JACK     --  External user-supplied routine to update\nC                  the preconditioner.  (This is optional).\nC                  See JAC description for the case\nC                  INFO(12) = 1 in the DDASPK prologue.\nC     PSOL      -- External user-supplied routine to solve\nC                  a linear system using preconditioning.\nC                  (This is optional).  See explanation inside DDASPK.\nC     H         -- Scaling factor for this initial condition calc.\nC     WT        -- Vector of weights for error criterion.\nC     JSKIP     -- input flag to signal if initial JAC call is to be\nC                  skipped.  1 => skip the call, 0 => do not skip call.\nC     RPAR,IPAR -- Real and integer arrays used for communication\nC                  between the calling program and external user\nC                  routines.  They are not altered within DASPK.\nC     SAVR      -- Work vector for DDASIK of length NEQ.\nC     DELTA     -- Work vector for DDASIK of length NEQ.\nC     R         -- Work vector for DDASIK of length NEQ.\nC     YIC,YPIC  -- Work vectors for DDASIK, each of length NEQ.\nC     PWK       -- Work vector for DDASIK of length NEQ.\nC     WM,IWM    -- Real and integer arrays storing\nC                  matrix information for linear system\nC                  solvers, and various other information.\nC     CJ        -- Matrix parameter = 1/H (ICOPT = 1) or 0 (ICOPT = 2).\nC     UROUND    -- Unit roundoff.\nC     EPLI      -- convergence test constant.\nC                  See DDASPK prologue for more details.\nC     SQRTN     -- Square root of NEQ.\nC     RSQRTN    -- reciprical of square root of NEQ.\nC     EPCON     -- Tolerance to test for convergence of the Newton\nC                  iteration.\nC     RATEMX    -- Maximum convergence rate for which Newton iteration\nC                  is considered converging.\nC     JFLG      -- Flag showing whether a Jacobian routine is supplied.\nC     ICNFLG    -- Integer scalar.  If nonzero, then constraint\nC                  violations in the proposed new approximate solution\nC                  will be checked for, and the maximum step length\nC                  will be adjusted accordingly.\nC     ICNSTR    -- Integer array of length NEQ containing flags for\nC                  checking constraints.\nC     IERNLS    -- Error flag for nonlinear solver.\nC                   0   ==> nonlinear solver converged.\nC                   1,2 ==> recoverable error inside nonlinear solver.\nC                           1 => retry with current Y, YPRIME\nC                           2 => retry with original Y, YPRIME\nC                  -1   ==> unrecoverable error in nonlinear solver.\nC\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   RES, JACK, DNSIK, DCOPY\nC\nC***END PROLOGUE  DDASIK\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),ID(*),WT(*),ICNSTR(*)\n      DIMENSION SAVR(*),DELTA(*),R(*),YIC(*),YPIC(*),PWK(*)\n      DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)\n      EXTERNAL RES, JACK, PSOL\nC\n      PARAMETER (LNRE=12, LNJE=13, LLOCWP=29, LLCIWP=30)\n      PARAMETER (LMXNIT=32, LMXNJ=33)\nC\nC\nC     Perform initializations.\nC\n      LWP = IWM(LLOCWP)\n      LIWP = IWM(LLCIWP)\n      MXNIT = IWM(LMXNIT)\n      MXNJ = IWM(LMXNJ)\n      IERNLS = 0\n      NJ = 0\n      EPLIN = EPLI*EPCON\nC\nC     Call RES to initialize DELTA.\nC\n      IRES = 0\n      IWM(LNRE) = IWM(LNRE) + 1\n      CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)\n      IF (IRES .LT. 0) GO TO 370\nC\nC     Looping point for updating the preconditioner.\nC\n 300  CONTINUE\nC\nC     Initialize all error flags to zero.\nC\n      IERPJ = 0\n      IRES = 0\n      IERNEW = 0\nC\nC     If a Jacobian routine was supplied, call it.\nC\n      IF (JFLG .EQ. 1 .AND. JSKIP .EQ. 0) THEN\n        NJ = NJ + 1\n        IWM(LNJE)=IWM(LNJE)+1\n        CALL JACK (RES, IRES, NEQ, X, Y, YPRIME, WT, DELTA, R, H, CJ,\n     *     WM(LWP), IWM(LIWP), IERPJ, RPAR, IPAR)\n        IF (IRES .LT. 0 .OR. IERPJ .NE. 0) GO TO 370\n        ENDIF\n      JSKIP = 0\nC\nC     Call the nonlinear Newton solver for up to MXNIT iterations.\nC\n      CALL DNSIK(X,Y,YPRIME,NEQ,ICOPT,ID,RES,PSOL,WT,RPAR,IPAR,\n     *   SAVR,DELTA,R,YIC,YPIC,PWK,WM,IWM,CJ,SQRTN,RSQRTN,\n     *   EPLIN,EPCON,RATEMX,MXNIT,STPTOL,ICNFLG,ICNSTR,IERNEW)\nC\n      IF (IERNEW .EQ. 1 .AND. NJ .LT. MXNJ .AND. JFLG .EQ. 1) THEN\nC\nC       Up to MXNIT iterations were done, the convergence rate is < 1,\nC       a Jacobian routine is supplied, and the number of JACK calls\nC       is less than MXNJ.\nC       Copy the residual SAVR to DELTA, call JACK, and try again.\nC\n        CALL DCOPY (NEQ,  SAVR, 1, DELTA, 1)\n        GO TO 300\n        ENDIF\nC\n      IF (IERNEW .NE. 0) GO TO 380\n      RETURN\nC\nC\nC     Unsuccessful exits from nonlinear solver.\nC     Set IERNLS accordingly.\nC\n 370  IERNLS = 2\n      IF (IRES .LE. -2) IERNLS = -1\n      RETURN\nC\n 380  IERNLS = MIN(IERNEW,2)\n      RETURN\nC\nC----------------------- END OF SUBROUTINE DDASIK-----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/ddaspk.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DDASPK (RES, NEQ, T, Y, YPRIME, TOUT, INFO, RTOL, ATOL,\n     *   IDID, RWORK, LRW, IWORK, LIW, RPAR, IPAR, JAC, PSOL)\nC\nC***BEGIN PROLOGUE  DDASPK\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  910624\nC***REVISION DATE  920929   (CJ in RES call, RES counter fix.)\nC***REVISION DATE  921215   (Warnings on poor iteration performance)\nC***REVISION DATE  921216   (NRMAX as optional input)\nC***REVISION DATE  930315   (Name change: DDINI to DDINIT)\nC***REVISION DATE  940822   (Replaced initial condition calculation)\nC***REVISION DATE  941101   (Added linesearch in I.C. calculations)\nC***REVISION DATE  941220   (Misc. corrections throughout)\nC***REVISION DATE  950125   (Added DINVWT routine)\nC***REVISION DATE  950714   (Misc. corrections throughout)\nC***REVISION DATE  950802   (Default NRMAX = 5, based on tests.)\nC***REVISION DATE  950808   (Optional error test added.)\nC***REVISION DATE  950814   (Added I.C. constraints and INFO(14))\nC***REVISION DATE  950828   (Various minor corrections.)\nC***REVISION DATE  951006   (Corrected WT scaling in DFNRMK.)\nC***REVISION DATE  960129   (Corrected RL bug in DLINSD, DLINSK.)\nC***REVISION DATE  960301   (Added NONNEG to SAVE statement.)\nC***CATEGORY NO.  I1A2\nC***KEYWORDS  DIFFERENTIAL/ALGEBRAIC, BACKWARD DIFFERENTIATION FORMULAS,\nC             IMPLICIT DIFFERENTIAL SYSTEMS, KRYLOV ITERATION\nC***AUTHORS   Linda R. Petzold, Peter N. Brown, Alan C. Hindmarsh, and\nC                  Clement W. Ulrich\nC             Center for Computational Sciences & Engineering, L-316\nC             Lawrence Livermore National Laboratory\nC             P.O. Box 808,\nC             Livermore, CA 94551\nC***PURPOSE  This code solves a system of differential/algebraic\nC            equations of the form\nC               G(t,y,y') = 0 ,\nC            using a combination of Backward Differentiation Formula\nC            (BDF) methods and a choice of two linear system solution\nC            methods: direct (dense or band) or Krylov (iterative).\nC            This version is in double precision.\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC *Usage:\nC\nC      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\nC      INTEGER NEQ, INFO(N), IDID, LRW, LIW, IWORK(LIW), IPAR(*)\nC      DOUBLE PRECISION T, Y(*), YPRIME(*), TOUT, RTOL(*), ATOL(*),\nC         RWORK(LRW), RPAR(*)\nC      EXTERNAL  RES, JAC, PSOL\nC\nC      CALL DDASPK (RES, NEQ, T, Y, YPRIME, TOUT, INFO, RTOL, ATOL,\nC     *   IDID, RWORK, LRW, IWORK, LIW, RPAR, IPAR, JAC, PSOL)\nC\nC  Quantities which may be altered by the code are:\nC     T, Y(*), YPRIME(*), INFO(*), RTOL, ATOL, IDID, RWORK(*), IWORK(*)\nC\nC\nC *Arguments:\nC\nC  RES:EXT          This is the name of a subroutine which you\nC                   provide to define the residual function G(t,y,y')\nC                   of the differential/algebraic system.\nC\nC  NEQ:IN           This is the number of equations in the system.\nC\nC  T:INOUT          This is the current value of the independent\nC                   variable.\nC\nC  Y(*):INOUT       This array contains the solution components at T.\nC\nC  YPRIME(*):INOUT  This array contains the derivatives of the solution\nC                   components at T.\nC\nC  TOUT:IN          This is a point at which a solution is desired.\nC\nC  INFO(N):IN       This is an integer array used to communicate details\nC                   of how the solution is to be carried out, such as\nC                   tolerance type, matrix structure, step size and\nC                   order limits, and choice of nonlinear system method.\nC                   N must be at least 20.\nC\nC  RTOL,ATOL:INOUT  These quantities represent absolute and relative\nC                   error tolerances (on local error) which you provide\nC                   to indicate how accurately you wish the solution to\nC                   be computed.  You may choose them to be both scalars\nC                   or else both arrays of length NEQ.\nC\nC  IDID:OUT         This integer scalar is an indicator reporting what\nC                   the code did.  You must monitor this variable to\nC                   decide what action to take next.\nC\nC  RWORK:WORK       A real work array of length LRW which provides the\nC                   code with needed storage space.\nC\nC  LRW:IN           The length of RWORK.\nC\nC  IWORK:WORK       An integer work array of length LIW which provides\nC                   the code with needed storage space.\nC\nC  LIW:IN           The length of IWORK.\nC\nC  RPAR,IPAR:IN     These are real and integer parameter arrays which\nC                   you can use for communication between your calling\nC                   program and the RES, JAC, and PSOL subroutines.\nC\nC  JAC:EXT          This is the name of a subroutine which you may\nC                   provide (optionally) for calculating Jacobian\nC                   (partial derivative) data involved in solving linear\nC                   systems within DDASPK.\nC\nC  PSOL:EXT         This is the name of a subroutine which you must\nC                   provide for solving linear systems if you selected\nC                   a Krylov method.  The purpose of PSOL is to solve\nC                   linear systems involving a left preconditioner P.\nC\nC *Overview\nC\nC  The DDASPK solver uses the backward differentiation formulas of\nC  orders one through five to solve a system of the form G(t,y,y') = 0\nC  for y = Y and y' = YPRIME.  Values for Y and YPRIME at the initial\nC  time must be given as input.  These values should be consistent,\nC  that is, if T, Y, YPRIME are the given initial values, they should\nC  satisfy G(T,Y,YPRIME) = 0.  However, if consistent values are not\nC  known, in many cases you can have DDASPK solve for them -- see INFO(11).\nC  (This and other options are described in more detail below.)\nC\nC  Normally, DDASPK solves the system from T to TOUT.  It is easy to\nC  continue the solution to get results at additional TOUT.  This is\nC  the interval mode of operation.  Intermediate results can also be\nC  obtained easily by specifying INFO(3).\nC\nC  On each step taken by DDASPK, a sequence of nonlinear algebraic\nC  systems arises.  These are solved by one of two types of\nC  methods:\nC    * a Newton iteration with a direct method for the linear\nC      systems involved (INFO(12) = 0), or\nC    * a Newton iteration with a preconditioned Krylov iterative\nC      method for the linear systems involved (INFO(12) = 1).\nC\nC  The direct method choices are dense and band matrix solvers,\nC  with either a user-supplied or an internal difference quotient\nC  Jacobian matrix, as specified by INFO(5) and INFO(6).\nC  In the band case, INFO(6) = 1, you must supply half-bandwidths\nC  in IWORK(1) and IWORK(2).\nC\nC  The Krylov method is the Generalized Minimum Residual (GMRES)\nC  method, in either complete or incomplete form, and with\nC  scaling and preconditioning.  The method is implemented\nC  in an algorithm called SPIGMR.  Certain options in the Krylov\nC  method case are specified by INFO(13) and INFO(15).\nC\nC  If the Krylov method is chosen, you may supply a pair of routines,\nC  JAC and PSOL, to apply preconditioning to the linear system.\nC  If the system is A*x = b, the matrix is A = dG/dY + CJ*dG/dYPRIME\nC  (of order NEQ).  This system can then be preconditioned in the form\nC  (P-inverse)*A*x = (P-inverse)*b, with left preconditioner P.\nC  (DDASPK does not allow right preconditioning.)\nC  Then the Krylov method is applied to this altered, but equivalent,\nC  linear system, hopefully with much better performance than without\nC  preconditioning.  (In addition, a diagonal scaling matrix based on\nC  the tolerances is also introduced into the altered system.)\nC\nC  The JAC routine evaluates any data needed for solving systems\nC  with coefficient matrix P, and PSOL carries out that solution.\nC  In any case, in order to improve convergence, you should try to\nC  make P approximate the matrix A as much as possible, while keeping\nC  the system P*x = b reasonably easy and inexpensive to solve for x,\nC  given a vector b.\nC\nC\nC *Description\nC\nC------INPUT - WHAT TO DO ON THE FIRST CALL TO DDASPK-------------------\nC\nC\nC  The first call of the code is defined to be the start of each new\nC  problem.  Read through the descriptions of all the following items,\nC  provide sufficient storage space for designated arrays, set\nC  appropriate variables for the initialization of the problem, and\nC  give information about how you want the problem to be solved.\nC\nC\nC  RES -- Provide a subroutine of the form\nC\nC             SUBROUTINE RES (T, Y, YPRIME, CJ, DELTA, IRES, RPAR, IPAR)\nC\nC         to define the system of differential/algebraic\nC         equations which is to be solved. For the given values\nC         of T, Y and YPRIME, the subroutine should return\nC         the residual of the differential/algebraic system\nC             DELTA = G(T,Y,YPRIME)\nC         DELTA is a vector of length NEQ which is output from RES.\nC\nC         Subroutine RES must not alter T, Y, YPRIME, or CJ.\nC         You must declare the name RES in an EXTERNAL\nC         statement in your program that calls DDASPK.\nC         You must dimension Y, YPRIME, and DELTA in RES.\nC\nC         The input argument CJ can be ignored, or used to rescale\nC         constraint equations in the system (see Ref. 2, p. 145).\nC         Note: In this respect, DDASPK is not downward-compatible\nC         with DDASSL, which does not have the RES argument CJ.\nC\nC         IRES is an integer flag which is always equal to zero\nC         on input.  Subroutine RES should alter IRES only if it\nC         encounters an illegal value of Y or a stop condition.\nC         Set IRES = -1 if an input value is illegal, and DDASPK\nC         will try to solve the problem without getting IRES = -1.\nC         If IRES = -2, DDASPK will return control to the calling\nC         program with IDID = -11.\nC\nC         RPAR and IPAR are real and integer parameter arrays which\nC         you can use for communication between your calling program\nC         and subroutine RES. They are not altered by DDASPK. If you\nC         do not need RPAR or IPAR, ignore these parameters by treat-\nC         ing them as dummy arguments. If you do choose to use them,\nC         dimension them in your calling program and in RES as arrays\nC         of appropriate length.\nC\nC  NEQ -- Set it to the number of equations in the system (NEQ .GE. 1).\nC\nC  T -- Set it to the initial point of the integration. (T must be\nC       a variable.)\nC\nC  Y(*) -- Set this array to the initial values of the NEQ solution\nC          components at the initial point.  You must dimension Y of\nC          length at least NEQ in your calling program.\nC\nC  YPRIME(*) -- Set this array to the initial values of the NEQ first\nC               derivatives of the solution components at the initial\nC               point.  You must dimension YPRIME at least NEQ in your\nC               calling program.\nC\nC  TOUT - Set it to the first point at which a solution is desired.\nC         You cannot take TOUT = T.  Integration either forward in T\nC         (TOUT .GT. T) or backward in T (TOUT .LT. T) is permitted.\nC\nC         The code advances the solution from T to TOUT using step\nC         sizes which are automatically selected so as to achieve the\nC         desired accuracy.  If you wish, the code will return with the\nC         solution and its derivative at intermediate steps (the\nC         intermediate-output mode) so that you can monitor them,\nC         but you still must provide TOUT in accord with the basic\nC         aim of the code.\nC\nC         The first step taken by the code is a critical one because\nC         it must reflect how fast the solution changes near the\nC         initial point.  The code automatically selects an initial\nC         step size which is practically always suitable for the\nC         problem.  By using the fact that the code will not step past\nC         TOUT in the first step, you could, if necessary, restrict the\nC         length of the initial step.\nC\nC         For some problems it may not be permissible to integrate\nC         past a point TSTOP, because a discontinuity occurs there\nC         or the solution or its derivative is not defined beyond\nC         TSTOP.  When you have declared a TSTOP point (see INFO(4)\nC         and RWORK(1)), you have told the code not to integrate past\nC         TSTOP.  In this case any tout beyond TSTOP is invalid input.\nC\nC  INFO(*) - Use the INFO array to give the code more details about\nC            how you want your problem solved.  This array should be\nC            dimensioned of length 20, though DDASPK uses only the\nC            first 15 entries.  You must respond to all of the following\nC            items, which are arranged as questions.  The simplest use\nC            of DDASPK corresponds to setting all entries of INFO to 0.\nC\nC       INFO(1) - This parameter enables the code to initialize itself.\nC              You must set it to indicate the start of every new\nC              problem.\nC\nC          **** Is this the first call for this problem ...\nC                yes - set INFO(1) = 0\nC                 no - not applicable here.\nC                      See below for continuation calls.  ****\nC\nC       INFO(2) - How much accuracy you want of your solution\nC              is specified by the error tolerances RTOL and ATOL.\nC              The simplest use is to take them both to be scalars.\nC              To obtain more flexibility, they can both be arrays.\nC              The code must be told your choice.\nC\nC          **** Are both error tolerances RTOL, ATOL scalars ...\nC                yes - set INFO(2) = 0\nC                      and input scalars for both RTOL and ATOL\nC                 no - set INFO(2) = 1\nC                      and input arrays for both RTOL and ATOL ****\nC\nC       INFO(3) - The code integrates from T in the direction of TOUT\nC              by steps.  If you wish, it will return the computed\nC              solution and derivative at the next intermediate step\nC              (the intermediate-output mode) or TOUT, whichever comes\nC              first.  This is a good way to proceed if you want to\nC              see the behavior of the solution.  If you must have\nC              solutions at a great many specific TOUT points, this\nC              code will compute them efficiently.\nC\nC          **** Do you want the solution only at\nC               TOUT (and not at the next intermediate step) ...\nC                yes - set INFO(3) = 0\nC                 no - set INFO(3) = 1 ****\nC\nC       INFO(4) - To handle solutions at a great many specific\nC              values TOUT efficiently, this code may integrate past\nC              TOUT and interpolate to obtain the result at TOUT.\nC              Sometimes it is not possible to integrate beyond some\nC              point TSTOP because the equation changes there or it is\nC              not defined past TSTOP.  Then you must tell the code\nC              this stop condition.\nC\nC           **** Can the integration be carried out without any\nC                restrictions on the independent variable T ...\nC                 yes - set INFO(4) = 0\nC                  no - set INFO(4) = 1\nC                       and define the stopping point TSTOP by\nC                       setting RWORK(1) = TSTOP ****\nC\nC       INFO(5) - used only when INFO(12) = 0 (direct methods).\nC              To solve differential/algebraic systems you may wish\nC              to use a matrix of partial derivatives of the\nC              system of differential equations.  If you do not\nC              provide a subroutine to evaluate it analytically (see\nC              description of the item JAC in the call list), it will\nC              be approximated by numerical differencing in this code.\nC              Although it is less trouble for you to have the code\nC              compute partial derivatives by numerical differencing,\nC              the solution will be more reliable if you provide the\nC              derivatives via JAC.  Usually numerical differencing is\nC              more costly than evaluating derivatives in JAC, but\nC              sometimes it is not - this depends on your problem.\nC\nC           **** Do you want the code to evaluate the partial deriv-\nC                atives automatically by numerical differences ...\nC                 yes - set INFO(5) = 0\nC                  no - set INFO(5) = 1\nC                       and provide subroutine JAC for evaluating the\nC                       matrix of partial derivatives ****\nC\nC       INFO(6) - used only when INFO(12) = 0 (direct methods).\nC              DDASPK will perform much better if the matrix of\nC              partial derivatives, dG/dY + CJ*dG/dYPRIME (here CJ is\nC              a scalar determined by DDASPK), is banded and the code\nC              is told this.  In this case, the storage needed will be\nC              greatly reduced, numerical differencing will be performed\nC              much cheaper, and a number of important algorithms will\nC              execute much faster.  The differential equation is said\nC              to have half-bandwidths ML (lower) and MU (upper) if\nC              equation i involves only unknowns Y(j) with\nC                             i-ML .le. j .le. i+MU .\nC              For all i=1,2,...,NEQ.  Thus, ML and MU are the widths\nC              of the lower and upper parts of the band, respectively,\nC              with the main diagonal being excluded.  If you do not\nC              indicate that the equation has a banded matrix of partial\nC              derivatives the code works with a full matrix of NEQ**2\nC              elements (stored in the conventional way).  Computations\nC              with banded matrices cost less time and storage than with\nC              full matrices if  2*ML+MU .lt. NEQ.  If you tell the\nC              code that the matrix of partial derivatives has a banded\nC              structure and you want to provide subroutine JAC to\nC              compute the partial derivatives, then you must be careful\nC              to store the elements of the matrix in the special form\nC              indicated in the description of JAC.\nC\nC          **** Do you want to solve the problem using a full (dense)\nC               matrix (and not a special banded structure) ...\nC                yes - set INFO(6) = 0\nC                 no - set INFO(6) = 1\nC                       and provide the lower (ML) and upper (MU)\nC                       bandwidths by setting\nC                       IWORK(1)=ML\nC                       IWORK(2)=MU ****\nC\nC       INFO(7) - You can specify a maximum (absolute value of)\nC              stepsize, so that the code will avoid passing over very\nC              large regions.\nC\nC          ****  Do you want the code to decide on its own the maximum\nC                stepsize ...\nC                 yes - set INFO(7) = 0\nC                  no - set INFO(7) = 1\nC                       and define HMAX by setting\nC                       RWORK(2) = HMAX ****\nC\nC       INFO(8) -  Differential/algebraic problems may occasionally\nC              suffer from severe scaling difficulties on the first\nC              step.  If you know a great deal about the scaling of\nC              your problem, you can help to alleviate this problem\nC              by specifying an initial stepsize H0.\nC\nC          ****  Do you want the code to define its own initial\nC                stepsize ...\nC                 yes - set INFO(8) = 0\nC                  no - set INFO(8) = 1\nC                       and define H0 by setting\nC                       RWORK(3) = H0 ****\nC\nC       INFO(9) -  If storage is a severe problem, you can save some\nC              storage by restricting the maximum method order MAXORD.\nC              The default value is 5.  For each order decrease below 5,\nC              the code requires NEQ fewer locations, but it is likely\nC              to be slower.  In any case, you must have\nC              1 .le. MAXORD .le. 5.\nC          ****  Do you want the maximum order to default to 5 ...\nC                 yes - set INFO(9) = 0\nC                  no - set INFO(9) = 1\nC                       and define MAXORD by setting\nC                       IWORK(3) = MAXORD ****\nC\nC       INFO(10) - If you know that certain components of the\nC              solutions to your equations are always nonnegative\nC              (or nonpositive), it may help to set this\nC              parameter.  There are three options that are\nC              available:\nC              1.  To have constraint checking only in the initial\nC                  condition calculation.\nC              2.  To enforce nonnegativity in Y during the integration.\nC              3.  To enforce both options 1 and 2.\nC\nC              When selecting option 2 or 3, it is probably best to try the\nC              code without using this option first, and only use\nC              this option if that does not work very well.\nC\nC          ****  Do you want the code to solve the problem without\nC                invoking any special inequality constraints ...\nC                 yes - set INFO(10) = 0\nC                  no - set INFO(10) = 1 to have option 1 enforced\nC                  no - set INFO(10) = 2 to have option 2 enforced\nC                  no - set INFO(10) = 3 to have option 3 enforced ****\nC\nC                  If you have specified INFO(10) = 1 or 3, then you\nC                  will also need to identify how each component of Y\nC                  in the initial condition calculation is constrained.\nC                  You must set:\nC                  IWORK(40+I) = +1 if Y(I) must be .GE. 0,\nC                  IWORK(40+I) = +2 if Y(I) must be .GT. 0,\nC                  IWORK(40+I) = -1 if Y(I) must be .LE. 0, while\nC                  IWORK(40+I) = -2 if Y(I) must be .LT. 0, while\nC                  IWORK(40+I) =  0 if Y(I) is not constrained.\nC\nC       INFO(11) - DDASPK normally requires the initial T, Y, and\nC              YPRIME to be consistent.  That is, you must have\nC              G(T,Y,YPRIME) = 0 at the initial T.  If you do not know\nC              the initial conditions precisely, in some cases\nC              DDASPK may be able to compute it.\nC\nC              Denoting the differential variables in Y by Y_d\nC              and the algebraic variables by Y_a, DDASPK can solve\nC              one of two initialization problems:\nC              1.  Given Y_d, calculate Y_a and Y'_d, or\nC              2.  Given Y', calculate Y.\nC              In either case, initial values for the given\nC              components are input, and initial guesses for\nC              the unknown components must also be provided as input.\nC\nC          ****  Are the initial T, Y, YPRIME consistent ...\nC\nC                 yes - set INFO(11) = 0\nC                  no - set INFO(11) = 1 to calculate option 1 above,\nC                    or set INFO(11) = 2 to calculate option 2 ****\nC\nC                  If you have specified INFO(11) = 1, then you\nC                  will also need to identify  which are the\nC                  differential and which are the algebraic\nC                  components (algebraic components are components\nC                  whose derivatives do not appear explicitly\nC                  in the function G(T,Y,YPRIME)).  You must set:\nC                  IWORK(LID+I) = +1 if Y(I) is a differential variable\nC                  IWORK(LID+I) = -1 if Y(I) is an algebraic variable,\nC                  where LID = 40 if INFO(10) = 0 or 2 and LID = 40+NEQ\nC                  if INFO(10) = 1 or 3.\nC\nC       INFO(12) - Except for the addition of the RES argument CJ,\nC              DDASPK by default is downward-compatible with DDASSL,\nC              which uses only direct (dense or band) methods to solve\nC              the linear systems involved.  You must set INFO(12) to\nC              indicate whether you want the direct methods or the\nC              Krylov iterative method.\nC          ****   Do you want DDASPK to use standard direct methods\nC                 (dense or band) or the Krylov (iterative) method ...\nC                   direct methods - set INFO(12) = 0.\nC                   Krylov method  - set INFO(12) = 1,\nC                       and check the settings of INFO(13) and INFO(15).\nC\nC       INFO(13) - used when INFO(12) = 1 (Krylov methods).\nC              DDASPK uses scalars MAXL, KMP, NRMAX, and EPLI for the\nC              iterative solution of linear systems.  INFO(13) allows\nC              you to override the default values of these parameters.\nC              These parameters and their defaults are as follows:\nC              MAXL = maximum number of iterations in the SPIGMR\nC                 algorithm (MAXL .le. NEQ).  The default is\nC                 MAXL = MIN(5,NEQ).\nC              KMP = number of vectors on which orthogonalization is\nC                 done in the SPIGMR algorithm.  The default is\nC                 KMP = MAXL, which corresponds to complete GMRES\nC                 iteration, as opposed to the incomplete form.\nC              NRMAX = maximum number of restarts of the SPIGMR\nC                 algorithm per nonlinear iteration.  The default is\nC                 NRMAX = 5.\nC              EPLI = convergence test constant in SPIGMR algorithm.\nC                 The default is EPLI = 0.05.\nC              Note that the length of RWORK depends on both MAXL\nC              and KMP.  See the definition of LRW below.\nC          ****   Are MAXL, KMP, and EPLI to be given their\nC                 default values ...\nC                  yes - set INFO(13) = 0\nC                   no - set INFO(13) = 1,\nC                        and set all of the following:\nC                        IWORK(24) = MAXL (1 .le. MAXL .le. NEQ)\nC                        IWORK(25) = KMP  (1 .le. KMP .le. MAXL)\nC                        IWORK(26) = NRMAX  (NRMAX .ge. 0)\nC                        RWORK(10) = EPLI (0 .lt. EPLI .lt. 1.0) ****\nC\nC        INFO(14) - used with INFO(11) > 0 (initial condition\nC               calculation is requested).  In this case, you may\nC               request control to be returned to the calling program\nC               immediately after the initial condition calculation,\nC               before proceeding to the integration of the system\nC               (e.g. to examine the computed Y and YPRIME).\nC               If this is done, and if the initialization succeeded\nC               (IDID = 4), you should reset INFO(11) to 0 for the\nC               next call, to prevent the solver from repeating the\nC               initialization (and to avoid an infinite loop).\nC          ****   Do you want to proceed to the integration after\nC                 the initial condition calculation is done ...\nC                 yes - set INFO(14) = 0\nC                  no - set INFO(14) = 1                        ****\nC\nC        INFO(15) - used when INFO(12) = 1 (Krylov methods).\nC               When using preconditioning in the Krylov method,\nC               you must supply a subroutine, PSOL, which solves the\nC               associated linear systems using P.\nC               The usage of DDASPK is simpler if PSOL can carry out\nC               the solution without any prior calculation of data.\nC               However, if some partial derivative data is to be\nC               calculated in advance and used repeatedly in PSOL,\nC               then you must supply a JAC routine to do this,\nC               and set INFO(15) to indicate that JAC is to be called\nC               for this purpose.  For example, P might be an\nC               approximation to a part of the matrix A which can be\nC               calculated and LU-factored for repeated solutions of\nC               the preconditioner system.  The arrays WP and IWP\nC               (described under JAC and PSOL) can be used to\nC               communicate data between JAC and PSOL.\nC          ****   Does PSOL operate with no prior preparation ...\nC                 yes - set INFO(15) = 0 (no JAC routine)\nC                  no - set INFO(15) = 1\nC                       and supply a JAC routine to evaluate and\nC                       preprocess any required Jacobian data.  ****\nC\nC         INFO(16) - option to exclude algebraic variables from\nC               the error test.\nC          ****   Do you wish to control errors locally on\nC                 all the variables...\nC                 yes - set INFO(16) = 0\nC                  no - set INFO(16) = 1\nC                       If you have specified INFO(16) = 1, then you\nC                       will also need to identify  which are the\nC                       differential and which are the algebraic\nC                       components (algebraic components are components\nC                       whose derivatives do not appear explicitly\nC                       in the function G(T,Y,YPRIME)).  You must set:\nC                       IWORK(LID+I) = +1 if Y(I) is a differential\nC                                      variable, and\nC                       IWORK(LID+I) = -1 if Y(I) is an algebraic\nC                                      variable,\nC                       where LID = 40 if INFO(10) = 0 or 2 and\nC                       LID = 40 + NEQ if INFO(10) = 1 or 3.\nC\nC       INFO(17) - used when INFO(11) > 0 (DDASPK is to do an\nC              initial condition calculation).\nC              DDASPK uses several heuristic control quantities in the\nC              initial condition calculation.  They have default values,\nC              but can  also be set by the user using INFO(17).\nC              These parameters and their defaults are as follows:\nC              MXNIT  = maximum number of Newton iterations\nC                 per Jacobian or preconditioner evaluation.\nC                 The default is:\nC                 MXNIT =  5 in the direct case (INFO(12) = 0), and\nC                 MXNIT = 15 in the Krylov case (INFO(12) = 1).\nC              MXNJ   = maximum number of Jacobian or preconditioner\nC                 evaluations.  The default is:\nC                 MXNJ = 6 in the direct case (INFO(12) = 0), and\nC                 MXNJ = 2 in the Krylov case (INFO(12) = 1).\nC              MXNH   = maximum number of values of the artificial\nC                 stepsize parameter H to be tried if INFO(11) = 1.\nC                 The default is MXNH = 5.\nC                 NOTE: the maximum number of Newton iterations\nC                 allowed in all is MXNIT*MXNJ*MXNH if INFO(11) = 1,\nC                 and MXNIT*MXNJ if INFO(11) = 2.\nC              LSOFF  = flag to turn off the linesearch algorithm\nC                 (LSOFF = 0 means linesearch is on, LSOFF = 1 means\nC                 it is turned off).  The default is LSOFF = 0.\nC              STPTOL = minimum scaled step in linesearch algorithm.\nC                 The default is STPTOL = (unit roundoff)**(2/3).\nC              EPINIT = swing factor in the Newton iteration convergence\nC                 test.  The test is applied to the residual vector,\nC                 premultiplied by the approximate Jacobian (in the\nC                 direct case) or the preconditioner (in the Krylov\nC                 case).  For convergence, the weighted RMS norm of\nC                 this vector (scaled by the error weights) must be\nC                 less than EPINIT*EPCON, where EPCON = .33 is the\nC                 analogous test constant used in the time steps.\nC                 The default is EPINIT = .01.\nC          ****   Are the initial condition heuristic controls to be\nC                 given their default values...\nC                  yes - set INFO(17) = 0\nC                   no - set INFO(17) = 1,\nC                        and set all of the following:\nC                        IWORK(32) = MXNIT (.GT. 0)\nC                        IWORK(33) = MXNJ (.GT. 0)\nC                        IWORK(34) = MXNH (.GT. 0)\nC                        IWORK(35) = LSOFF ( = 0 or 1)\nC                        RWORK(14) = STPTOL (.GT. 0.0)\nC                        RWORK(15) = EPINIT (.GT. 0.0)  ****\nC\nC         INFO(18) - option to get extra printing in initial condition\nC                calculation.\nC          ****   Do you wish to have extra printing...\nC                 no  - set INFO(18) = 0\nC                 yes - set INFO(18) = 1 for minimal printing, or\nC                       set INFO(18) = 2 for full printing.\nC                       If you have specified INFO(18) .ge. 1, data\nC                       will be printed with the error handler routines.\nC                       To print to a non-default unit number L, include\nC                       the line  CALL XSETUN(L)  in your program.  ****\nC\nC   RTOL, ATOL -- You must assign relative (RTOL) and absolute (ATOL)\nC               error tolerances to tell the code how accurately you\nC               want the solution to be computed.  They must be defined\nC               as variables because the code may change them.\nC               you have two choices --\nC                     Both RTOL and ATOL are scalars (INFO(2) = 0), or\nC                     both RTOL and ATOL are vectors (INFO(2) = 1).\nC               In either case all components must be non-negative.\nC\nC               The tolerances are used by the code in a local error\nC               test at each step which requires roughly that\nC                        abs(local error in Y(i)) .le. EWT(i) ,\nC               where EWT(i) = RTOL*abs(Y(i)) + ATOL is an error weight\nC               quantity, for each vector component.\nC               (More specifically, a root-mean-square norm is used to\nC               measure the size of vectors, and the error test uses the\nC               magnitude of the solution at the beginning of the step.)\nC\nC               The true (global) error is the difference between the\nC               true solution of the initial value problem and the\nC               computed approximation.  Practically all present day\nC               codes, including this one, control the local error at\nC               each step and do not even attempt to control the global\nC               error directly.\nC\nC               Usually, but not always, the true accuracy of\nC               the computed Y is comparable to the error tolerances.\nC               This code will usually, but not always, deliver a more\nC               accurate solution if you reduce the tolerances and\nC               integrate again.  By comparing two such solutions you\nC               can get a fairly reliable idea of the true error in the\nC               solution at the larger tolerances.\nC\nC               Setting ATOL = 0. results in a pure relative error test\nC               on that component.  Setting RTOL = 0. results in a pure\nC               absolute error test on that component.  A mixed test\nC               with non-zero RTOL and ATOL corresponds roughly to a\nC               relative error test when the solution component is\nC               much bigger than ATOL and to an absolute error test\nC               when the solution component is smaller than the\nC               threshold ATOL.\nC\nC               The code will not attempt to compute a solution at an\nC               accuracy unreasonable for the machine being used.  It\nC               will advise you if you ask for too much accuracy and\nC               inform you as to the maximum accuracy it believes\nC               possible.\nC\nC  RWORK(*) -- a real work array, which should be dimensioned in your\nC               calling program with a length equal to the value of\nC               LRW (or greater).\nC\nC  LRW -- Set it to the declared length of the RWORK array.  The\nC               minimum length depends on the options you have selected,\nC               given by a base value plus additional storage as described\nC               below.\nC\nC               If INFO(12) = 0 (standard direct method), the base value is\nC               base = 50 + max(MAXORD+4,7)*NEQ.\nC               The default value is MAXORD = 5 (see INFO(9)).  With the\nC               default MAXORD, base = 50 + 9*NEQ.\nC               Additional storage must be added to the base value for\nC               any or all of the following options:\nC                 if INFO(6) = 0 (dense matrix), add NEQ**2\nC                 if INFO(6) = 1 (banded matrix), then\nC                    if INFO(5) = 0, add (2*ML+MU+1)*NEQ + 2*(NEQ/(ML+MU+1)+1),\nC                    if INFO(5) = 1, add (2*ML+MU+1)*NEQ,\nC                 if INFO(16) = 1, add NEQ.\nC\nC              If INFO(12) = 1 (Krylov method), the base value is\nC              base = 50 + (MAXORD+5)*NEQ + (MAXL+3+MIN0(1,MAXL-KMP))*NEQ +\nC                      + (MAXL+3)*MAXL + 1 + LENWP.\nC              See PSOL for description of LENWP.  The default values are:\nC              MAXORD = 5 (see INFO(9)), MAXL = min(5,NEQ) and KMP = MAXL\nC              (see INFO(13)).\nC              With the default values for MAXORD, MAXL and KMP,\nC              base = 91 + 18*NEQ + LENWP.\nC              Additional storage must be added to the base value for\nC              any or all of the following options:\nC                if INFO(16) = 1, add NEQ.\nC\nC\nC  IWORK(*) -- an integer work array, which should be dimensioned in\nC              your calling program with a length equal to the value\nC              of LIW (or greater).\nC\nC  LIW -- Set it to the declared length of the IWORK array.  The\nC             minimum length depends on the options you have selected,\nC             given by a base value plus additional storage as described\nC             below.\nC\nC             If INFO(12) = 0 (standard direct method), the base value is\nC             base = 40 + NEQ.\nC             IF INFO(10) = 1 or 3, add NEQ to the base value.\nC             If INFO(11) = 1 or INFO(16) =1, add NEQ to the base value.\nC\nC             If INFO(12) = 1 (Krylov method), the base value is\nC             base = 40 + LENIWP.\nC             See PSOL for description of LENIWP.\nC             IF INFO(10) = 1 or 3, add NEQ to the base value.\nC             If INFO(11) = 1 or INFO(16) = 1, add NEQ to the base value.\nC\nC\nC  RPAR, IPAR -- These are arrays of double precision and integer type,\nC             respectively, which are available for you to use\nC             for communication between your program that calls\nC             DDASPK and the RES subroutine (and the JAC and PSOL\nC             subroutines).  They are not altered by DDASPK.\nC             If you do not need RPAR or IPAR, ignore these\nC             parameters by treating them as dummy arguments.\nC             If you do choose to use them, dimension them in\nC             your calling program and in RES (and in JAC and PSOL)\nC             as arrays of appropriate length.\nC\nC  JAC -- This is the name of a routine that you may supply\nC         (optionally) that relates to the Jacobian matrix of the\nC         nonlinear system that the code must solve at each T step.\nC         The role of JAC (and its call sequence) depends on whether\nC         a direct (INFO(12) = 0) or Krylov (INFO(12) = 1) method\nC         is selected.\nC\nC         **** INFO(12) = 0 (direct methods):\nC           If you are letting the code generate partial derivatives\nC           numerically (INFO(5) = 0), then JAC can be absent\nC           (or perhaps a dummy routine to satisfy the loader).\nC           Otherwise you must supply a JAC routine to compute\nC           the matrix A = dG/dY + CJ*dG/dYPRIME.  It must have\nC           the form\nC\nC           SUBROUTINE JAC (T, Y, YPRIME, PD, CJ, RPAR, IPAR)\nC\nC           The JAC routine must dimension Y, YPRIME, and PD (and RPAR\nC           and IPAR if used).  CJ is a scalar which is input to JAC.\nC           For the given values of T, Y, and YPRIME, the JAC routine\nC           must evaluate the nonzero elements of the matrix A, and\nC           store these values in the array PD.  The elements of PD are\nC           set to zero before each call to JAC, so that only nonzero\nC           elements need to be defined.\nC           The way you store the elements into the PD array depends\nC           on the structure of the matrix indicated by INFO(6).\nC           *** INFO(6) = 0 (full or dense matrix) ***\nC               Give PD a first dimension of NEQ.  When you evaluate the\nC               nonzero partial derivatives of equation i (i.e. of G(i))\nC               with respect to component j (of Y and YPRIME), you must\nC               store the element in PD according to\nC                  PD(i,j) = dG(i)/dY(j) + CJ*dG(i)/dYPRIME(j).\nC           *** INFO(6) = 1 (banded matrix with half-bandwidths ML, MU\nC                            as described under INFO(6)) ***\nC               Give PD a first dimension of 2*ML+MU+1.  When you\nC               evaluate the nonzero partial derivatives of equation i\nC               (i.e. of G(i)) with respect to component j (of Y and\nC               YPRIME), you must store the element in PD according to\nC                  IROW = i - j + ML + MU + 1\nC                  PD(IROW,j) = dG(i)/dY(j) + CJ*dG(i)/dYPRIME(j).\nC\nC          **** INFO(12) = 1 (Krylov method):\nC            If you are not calculating Jacobian data in advance for use\nC            in PSOL (INFO(15) = 0), JAC can be absent (or perhaps a\nC            dummy routine to satisfy the loader).  Otherwise, you may\nC            supply a JAC routine to compute and preprocess any parts of\nC            of the Jacobian matrix  A = dG/dY + CJ*dG/dYPRIME that are\nC            involved in the preconditioner matrix P.\nC            It is to have the form\nC\nC            SUBROUTINE JAC (RES, IRES, NEQ, T, Y, YPRIME, REWT, SAVR,\nC                            WK, H, CJ, WP, IWP, IER, RPAR, IPAR)\nC\nC           The JAC routine must dimension Y, YPRIME, REWT, SAVR, WK,\nC           and (if used) WP, IWP, RPAR, and IPAR.\nC           The Y, YPRIME, and SAVR arrays contain the current values\nC           of Y, YPRIME, and the residual G, respectively.\nC           The array WK is work space of length NEQ.\nC           H is the step size.  CJ is a scalar, input to JAC, that is\nC           normally proportional to 1/H.  REWT is an array of\nC           reciprocal error weights, 1/EWT(i), where EWT(i) is\nC           RTOL*abs(Y(i)) + ATOL (unless you supplied routine DDAWTS\nC           instead), for use in JAC if needed.  For example, if JAC\nC           computes difference quotient approximations to partial\nC           derivatives, the REWT array may be useful in setting the\nC           increments used.  The JAC routine should do any\nC           factorization operations called for, in preparation for\nC           solving linear systems in PSOL.  The matrix P should\nC           be an approximation to the Jacobian,\nC           A = dG/dY + CJ*dG/dYPRIME.\nC\nC           WP and IWP are real and integer work arrays which you may\nC           use for communication between your JAC routine and your\nC           PSOL routine.  These may be used to store elements of the\nC           preconditioner P, or related matrix data (such as factored\nC           forms).  They are not altered by DDASPK.\nC           If you do not need WP or IWP, ignore these parameters by\nC           treating them as dummy arguments.  If you do use them,\nC           dimension them appropriately in your JAC and PSOL routines.\nC           See the PSOL description for instructions on setting\nC           the lengths of WP and IWP.\nC\nC           On return, JAC should set the error flag IER as follows..\nC             IER = 0    if JAC was successful,\nC             IER .ne. 0 if JAC was unsuccessful (e.g. if Y or YPRIME\nC                        was illegal, or a singular matrix is found).\nC           (If IER .ne. 0, a smaller stepsize will be tried.)\nC           IER = 0 on entry to JAC, so need be reset only on a failure.\nC           If RES is used within JAC, then a nonzero value of IRES will\nC           override any nonzero value of IER (see the RES description).\nC\nC         Regardless of the method type, subroutine JAC must not\nC         alter T, Y(*), YPRIME(*), H, CJ, or REWT(*).\nC         You must declare the name JAC in an EXTERNAL statement in\nC         your program that calls DDASPK.\nC\nC PSOL --  This is the name of a routine you must supply if you have\nC         selected a Krylov method (INFO(12) = 1) with preconditioning.\nC         In the direct case (INFO(12) = 0), PSOL can be absent\nC         (a dummy routine may have to be supplied to satisfy the\nC         loader).  Otherwise, you must provide a PSOL routine to\nC         solve linear systems arising from preconditioning.\nC         When supplied with INFO(12) = 1, the PSOL routine is to\nC         have the form\nC\nC         SUBROUTINE PSOL (NEQ, T, Y, YPRIME, SAVR, WK, CJ, WGHT,\nC                          WP, IWP, B, EPLIN, IER, RPAR, IPAR)\nC\nC         The PSOL routine must solve linear systems of the form\nC         P*x = b where P is the left preconditioner matrix.\nC\nC         The right-hand side vector b is in the B array on input, and\nC         PSOL must return the solution vector x in B.\nC         The Y, YPRIME, and SAVR arrays contain the current values\nC         of Y, YPRIME, and the residual G, respectively.\nC\nC         Work space required by JAC and/or PSOL, and space for data to\nC         be communicated from JAC to PSOL is made available in the form\nC         of arrays WP and IWP, which are parts of the RWORK and IWORK\nC         arrays, respectively.  The lengths of these real and integer\nC         work spaces WP and IWP must be supplied in LENWP and LENIWP,\nC         respectively, as follows..\nC           IWORK(27) = LENWP = length of real work space WP\nC           IWORK(28) = LENIWP = length of integer work space IWP.\nC\nC         WK is a work array of length NEQ for use by PSOL.\nC         CJ is a scalar, input to PSOL, that is normally proportional\nC         to 1/H (H = stepsize).  If the old value of CJ\nC         (at the time of the last JAC call) is needed, it must have\nC         been saved by JAC in WP.\nC\nC         WGHT is an array of weights, to be used if PSOL uses an\nC         iterative method and performs a convergence test.  (In terms\nC         of the argument REWT to JAC, WGHT is REWT/sqrt(NEQ).)\nC         If PSOL uses an iterative method, it should use EPLIN\nC         (a heuristic parameter) as the bound on the weighted norm of\nC         the residual for the computed solution.  Specifically, the\nC         residual vector R should satisfy\nC              SQRT (SUM ( (R(i)*WGHT(i))**2 ) ) .le. EPLIN\nC\nC         PSOL must not alter NEQ, T, Y, YPRIME, SAVR, CJ, WGHT, EPLIN.\nC\nC         On return, PSOL should set the error flag IER as follows..\nC           IER = 0 if PSOL was successful,\nC           IER .lt. 0 if an unrecoverable error occurred, meaning\nC                 control will be passed to the calling routine,\nC           IER .gt. 0 if a recoverable error occurred, meaning that\nC                 the step will be retried with the same step size\nC                 but with a call to JAC to update necessary data,\nC                 unless the Jacobian data is current, in which case\nC                 the step will be retried with a smaller step size.\nC           IER = 0 on entry to PSOL so need be reset only on a failure.\nC\nC         You must declare the name PSOL in an EXTERNAL statement in\nC         your program that calls DDASPK.\nC\nC\nC  OPTIONALLY REPLACEABLE SUBROUTINE:\nC\nC  DDASPK uses a weighted root-mean-square norm to measure the\nC  size of various error vectors.  The weights used in this norm\nC  are set in the following subroutine:\nC\nC    SUBROUTINE DDAWTS (NEQ, IWT, RTOL, ATOL, Y, EWT, RPAR, IPAR)\nC    DIMENSION RTOL(*), ATOL(*), Y(*), EWT(*), RPAR(*), IPAR(*)\nC\nC  A DDAWTS routine has been included with DDASPK which sets the\nC  weights according to\nC    EWT(I) = RTOL*ABS(Y(I)) + ATOL\nC  in the case of scalar tolerances (IWT = 0) or\nC    EWT(I) = RTOL(I)*ABS(Y(I)) + ATOL(I)\nC  in the case of array tolerances (IWT = 1).  (IWT is INFO(2).)\nC  In some special cases, it may be appropriate for you to define\nC  your own error weights by writing a subroutine DDAWTS to be\nC  called instead of the version supplied.  However, this should\nC  be attempted only after careful thought and consideration.\nC  If you supply this routine, you may use the tolerances and Y\nC  as appropriate, but do not overwrite these variables.  You\nC  may also use RPAR and IPAR to communicate data as appropriate.\nC  ***Note: Aside from the values of the weights, the choice of\nC  norm used in DDASPK (weighted root-mean-square) is not subject\nC  to replacement by the user.  In this respect, DDASPK is not\nC  downward-compatible with the original DDASSL solver (in which\nC  the norm routine was optionally user-replaceable).\nC\nC\nC------OUTPUT - AFTER ANY RETURN FROM DDASPK----------------------------\nC\nC  The principal aim of the code is to return a computed solution at\nC  T = TOUT, although it is also possible to obtain intermediate\nC  results along the way.  To find out whether the code achieved its\nC  goal or if the integration process was interrupted before the task\nC  was completed, you must check the IDID parameter.\nC\nC\nC   T -- The output value of T is the point to which the solution\nC        was successfully advanced.\nC\nC   Y(*) -- contains the computed solution approximation at T.\nC\nC   YPRIME(*) -- contains the computed derivative approximation at T.\nC\nC   IDID -- reports what the code did, described as follows:\nC\nC                     *** TASK COMPLETED ***\nC                Reported by positive values of IDID\nC\nC           IDID = 1 -- a step was successfully taken in the\nC                   intermediate-output mode.  The code has not\nC                   yet reached TOUT.\nC\nC           IDID = 2 -- the integration to TSTOP was successfully\nC                   completed (T = TSTOP) by stepping exactly to TSTOP.\nC\nC           IDID = 3 -- the integration to TOUT was successfully\nC                   completed (T = TOUT) by stepping past TOUT.\nC                   Y(*) and YPRIME(*) are obtained by interpolation.\nC\nC           IDID = 4 -- the initial condition calculation, with\nC                   INFO(11) > 0, was successful, and INFO(14) = 1.\nC                   No integration steps were taken, and the solution\nC                   is not considered to have been started.\nC\nC                    *** TASK INTERRUPTED ***\nC                Reported by negative values of IDID\nC\nC           IDID = -1 -- a large amount of work has been expended\nC                     (about 500 steps).\nC\nC           IDID = -2 -- the error tolerances are too stringent.\nC\nC           IDID = -3 -- the local error test cannot be satisfied\nC                     because you specified a zero component in ATOL\nC                     and the corresponding computed solution component\nC                     is zero.  Thus, a pure relative error test is\nC                     impossible for this component.\nC\nC           IDID = -5 -- there were repeated failures in the evaluation\nC                     or processing of the preconditioner (in JAC).\nC\nC           IDID = -6 -- DDASPK had repeated error test failures on the\nC                     last attempted step.\nC\nC           IDID = -7 -- the nonlinear system solver in the time integration\nC                     could not converge.\nC\nC           IDID = -8 -- the matrix of partial derivatives appears\nC                     to be singular (direct method).\nC\nC           IDID = -9 -- the nonlinear system solver in the time integration\nC                     failed to achieve convergence, and there were repeated\nC                     error test failures in this step.\nC\nC           IDID =-10 -- the nonlinear system solver in the time integration\nC                     failed to achieve convergence because IRES was equal\nC                     to -1.\nC\nC           IDID =-11 -- IRES = -2 was encountered and control is\nC                     being returned to the calling program.\nC\nC           IDID =-12 -- DDASPK failed to compute the initial Y, YPRIME.\nC\nC           IDID =-13 -- unrecoverable error encountered inside user's\nC                     PSOL routine, and control is being returned to\nC                     the calling program.\nC\nC           IDID =-14 -- the Krylov linear system solver could not\nC                     achieve convergence.\nC\nC           IDID =-15,..,-32 -- Not applicable for this code.\nC\nC                    *** TASK TERMINATED ***\nC                reported by the value of IDID=-33\nC\nC           IDID = -33 -- the code has encountered trouble from which\nC                   it cannot recover.  A message is printed\nC                   explaining the trouble and control is returned\nC                   to the calling program.  For example, this occurs\nC                   when invalid input is detected.\nC\nC   RTOL, ATOL -- these quantities remain unchanged except when\nC               IDID = -2.  In this case, the error tolerances have been\nC               increased by the code to values which are estimated to\nC               be appropriate for continuing the integration.  However,\nC               the reported solution at T was obtained using the input\nC               values of RTOL and ATOL.\nC\nC   RWORK, IWORK -- contain information which is usually of no interest\nC               to the user but necessary for subsequent calls.\nC               However, you may be interested in the performance data\nC               listed below.  These quantities are accessed in RWORK\nC               and IWORK but have internal mnemonic names, as follows..\nC\nC               RWORK(3)--contains H, the step size h to be attempted\nC                        on the next step.\nC\nC               RWORK(4)--contains TN, the current value of the\nC                        independent variable, i.e. the farthest point\nC                        integration has reached.  This will differ\nC                        from T if interpolation has been performed\nC                        (IDID = 3).\nC\nC               RWORK(7)--contains HOLD, the stepsize used on the last\nC                        successful step.  If INFO(11) = INFO(14) = 1,\nC                        this contains the value of H used in the\nC                        initial condition calculation.\nC\nC               IWORK(7)--contains K, the order of the method to be\nC                        attempted on the next step.\nC\nC               IWORK(8)--contains KOLD, the order of the method used\nC                        on the last step.\nC\nC               IWORK(11)--contains NST, the number of steps (in T)\nC                        taken so far.\nC\nC               IWORK(12)--contains NRE, the number of calls to RES\nC                        so far.\nC\nC               IWORK(13)--contains NJE, the number of calls to JAC so\nC                        far (Jacobian or preconditioner evaluations).\nC\nC               IWORK(14)--contains NETF, the total number of error test\nC                        failures so far.\nC\nC               IWORK(15)--contains NCFN, the total number of nonlinear\nC                        convergence failures so far (includes counts\nC                        of singular iteration matrix or singular\nC                        preconditioners).\nC\nC               IWORK(16)--contains NCFL, the number of convergence\nC                        failures of the linear iteration so far.\nC\nC               IWORK(17)--contains LENIW, the length of IWORK actually\nC                        required.  This is defined on normal returns\nC                        and on an illegal input return for\nC                        insufficient storage.\nC\nC               IWORK(18)--contains LENRW, the length of RWORK actually\nC                        required.  This is defined on normal returns\nC                        and on an illegal input return for\nC                        insufficient storage.\nC\nC               IWORK(19)--contains NNI, the total number of nonlinear\nC                        iterations so far (each of which calls a\nC                        linear solver).\nC\nC               IWORK(20)--contains NLI, the total number of linear\nC                        (Krylov) iterations so far.\nC\nC               IWORK(21)--contains NPS, the number of PSOL calls so\nC                        far, for preconditioning solve operations or\nC                        for solutions with the user-supplied method.\nC\nC               Note: The various counters in IWORK do not include\nC               counts during a call made with INFO(11) > 0 and\nC               INFO(14) = 1.\nC\nC\nC------INPUT - WHAT TO DO TO CONTINUE THE INTEGRATION  -----------------\nC              (CALLS AFTER THE FIRST)\nC\nC     This code is organized so that subsequent calls to continue the\nC     integration involve little (if any) additional effort on your\nC     part.  You must monitor the IDID parameter in order to determine\nC     what to do next.\nC\nC     Recalling that the principal task of the code is to integrate\nC     from T to TOUT (the interval mode), usually all you will need\nC     to do is specify a new TOUT upon reaching the current TOUT.\nC\nC     Do not alter any quantity not specifically permitted below.  In\nC     particular do not alter NEQ, T, Y(*), YPRIME(*), RWORK(*),\nC     IWORK(*), or the differential equation in subroutine RES.  Any\nC     such alteration constitutes a new problem and must be treated\nC     as such, i.e. you must start afresh.\nC\nC     You cannot change from array to scalar error control or vice\nC     versa (INFO(2)), but you can change the size of the entries of\nC     RTOL or ATOL.  Increasing a tolerance makes the equation easier\nC     to integrate.  Decreasing a tolerance will make the equation\nC     harder to integrate and should generally be avoided.\nC\nC     You can switch from the intermediate-output mode to the\nC     interval mode (INFO(3)) or vice versa at any time.\nC\nC     If it has been necessary to prevent the integration from going\nC     past a point TSTOP (INFO(4), RWORK(1)), keep in mind that the\nC     code will not integrate to any TOUT beyond the currently\nC     specified TSTOP.  Once TSTOP has been reached, you must change\nC     the value of TSTOP or set INFO(4) = 0.  You may change INFO(4)\nC     or TSTOP at any time but you must supply the value of TSTOP in\nC     RWORK(1) whenever you set INFO(4) = 1.\nC\nC     Do not change INFO(5), INFO(6), INFO(12-17) or their associated\nC     IWORK/RWORK locations unless you are going to restart the code.\nC\nC                    *** FOLLOWING A COMPLETED TASK ***\nC\nC     If..\nC     IDID = 1, call the code again to continue the integration\nC                  another step in the direction of TOUT.\nC\nC     IDID = 2 or 3, define a new TOUT and call the code again.\nC                  TOUT must be different from T.  You cannot change\nC                  the direction of integration without restarting.\nC\nC     IDID = 4, reset INFO(11) = 0 and call the code again to begin\nC                  the integration.  (If you leave INFO(11) > 0 and\nC                  INFO(14) = 1, you may generate an infinite loop.)\nC                  In this situation, the next call to DASPK is\nC                  considered to be the first call for the problem,\nC                  in that all initializations are done.\nC\nC                    *** FOLLOWING AN INTERRUPTED TASK ***\nC\nC     To show the code that you realize the task was interrupted and\nC     that you want to continue, you must take appropriate action and\nC     set INFO(1) = 1.\nC\nC     If..\nC     IDID = -1, the code has taken about 500 steps.  If you want to\nC                  continue, set INFO(1) = 1 and call the code again.\nC                  An additional 500 steps will be allowed.\nC\nC\nC     IDID = -2, the error tolerances RTOL, ATOL have been increased\nC                  to values the code estimates appropriate for\nC                  continuing.  You may want to change them yourself.\nC                  If you are sure you want to continue with relaxed\nC                  error tolerances, set INFO(1) = 1 and call the code\nC                  again.\nC\nC     IDID = -3, a solution component is zero and you set the\nC                  corresponding component of ATOL to zero.  If you\nC                  are sure you want to continue, you must first alter\nC                  the error criterion to use positive values of ATOL\nC                  for those components corresponding to zero solution\nC                  components, then set INFO(1) = 1 and call the code\nC                  again.\nC\nC     IDID = -4  --- cannot occur with this code.\nC\nC     IDID = -5, your JAC routine failed with the Krylov method.  Check\nC                  for errors in JAC and restart the integration.\nC\nC     IDID = -6, repeated error test failures occurred on the last\nC                  attempted step in DDASPK.  A singularity in the\nC                  solution may be present.  If you are absolutely\nC                  certain you want to continue, you should restart\nC                  the integration.  (Provide initial values of Y and\nC                  YPRIME which are consistent.)\nC\nC     IDID = -7, repeated convergence test failures occurred on the last\nC                  attempted step in DDASPK.  An inaccurate or ill-\nC                  conditioned Jacobian or preconditioner may be the\nC                  problem.  If you are absolutely certain you want\nC                  to continue, you should restart the integration.\nC\nC\nC     IDID = -8, the matrix of partial derivatives is singular, with\nC                  the use of direct methods.  Some of your equations\nC                  may be redundant.  DDASPK cannot solve the problem\nC                  as stated.  It is possible that the redundant\nC                  equations could be removed, and then DDASPK could\nC                  solve the problem.  It is also possible that a\nC                  solution to your problem either does not exist\nC                  or is not unique.\nC\nC     IDID = -9, DDASPK had multiple convergence test failures, preceded\nC                  by multiple error test failures, on the last\nC                  attempted step.  It is possible that your problem is\nC                  ill-posed and cannot be solved using this code.  Or,\nC                  there may be a discontinuity or a singularity in the\nC                  solution.  If you are absolutely certain you want to\nC                  continue, you should restart the integration.\nC\nC     IDID = -10, DDASPK had multiple convergence test failures\nC                  because IRES was equal to -1.  If you are\nC                  absolutely certain you want to continue, you\nC                  should restart the integration.\nC\nC     IDID = -11, there was an unrecoverable error (IRES = -2) from RES\nC                  inside the nonlinear system solver.  Determine the\nC                  cause before trying again.\nC\nC     IDID = -12, DDASPK failed to compute the initial Y and YPRIME\nC                  vectors.  This could happen because the initial\nC                  approximation to Y or YPRIME was not very good, or\nC                  because no consistent values of these vectors exist.\nC                  The problem could also be caused by an inaccurate or\nC                  singular iteration matrix, or a poor preconditioner.\nC\nC     IDID = -13, there was an unrecoverable error encountered inside\nC                  your PSOL routine.  Determine the cause before\nC                  trying again.\nC\nC     IDID = -14, the Krylov linear system solver failed to achieve\nC                  convergence.  This may be due to ill-conditioning\nC                  in the iteration matrix, or a singularity in the\nC                  preconditioner (if one is being used).\nC                  Another possibility is that there is a better\nC                  choice of Krylov parameters (see INFO(13)).\nC                  Possibly the failure is caused by redundant equations\nC                  in the system, or by inconsistent equations.\nC                  In that case, reformulate the system to make it\nC                  consistent and non-redundant.\nC\nC     IDID = -15,..,-32 --- Cannot occur with this code.\nC\nC                       *** FOLLOWING A TERMINATED TASK ***\nC\nC     If IDID = -33, you cannot continue the solution of this problem.\nC                  An attempt to do so will result in your run being\nC                  terminated.\nC\nC  ---------------------------------------------------------------------\nC\nC***REFERENCES\nC  1.  L. R. Petzold, A Description of DASSL: A Differential/Algebraic\nC      System Solver, in Scientific Computing, R. S. Stepleman et al.\nC      (Eds.), North-Holland, Amsterdam, 1983, pp. 65-68.\nC  2.  K. E. Brenan, S. L. Campbell, and L. R. Petzold, Numerical\nC      Solution of Initial-Value Problems in Differential-Algebraic\nC      Equations, Elsevier, New York, 1989.\nC  3.  P. N. Brown and A. C. Hindmarsh, Reduced Storage Matrix Methods\nC      in Stiff ODE Systems, J. Applied Mathematics and Computation,\nC      31 (1989), pp. 40-91.\nC  4.  P. N. Brown, A. C. Hindmarsh, and L. R. Petzold, Using Krylov\nC      Methods in the Solution of Large-Scale Differential-Algebraic\nC      Systems, SIAM J. Sci. Comp., 15 (1994), pp. 1467-1488.\nC  5.  P. N. Brown, A. C. Hindmarsh, and L. R. Petzold, Consistent\nC      Initial Condition Calculation for Differential-Algebraic\nC      Systems, LLNL Report UCRL-JC-122175, August 1995; submitted to\nC      SIAM J. Sci. Comp.\nC\nC***ROUTINES CALLED\nC\nC   The following are all the subordinate routines used by DDASPK.\nC\nC   DDASIC computes consistent initial conditions.\nC   DYYPNW updates Y and YPRIME in linesearch for initial condition\nC          calculation.\nC   DDSTP  carries out one step of the integration.\nC   DCNSTR/DCNST0 check the current solution for constraint violations.\nC   DDAWTS sets error weight quantities.\nC   DINVWT tests and inverts the error weights.\nC   DDATRP performs interpolation to get an output solution.\nC   DDWNRM computes the weighted root-mean-square norm of a vector.\nC   D1MACH provides the unit roundoff of the computer.\nC   XERRWD/XSETF/XSETUN/IXSAV is a package to handle error messages.\nC   DDASID nonlinear equation driver to initialize Y and YPRIME using\nC          direct linear system solver methods.  Interfaces to Newton\nC          solver (direct case).\nC   DNSID  solves the nonlinear system for unknown initial values by\nC          modified Newton iteration and direct linear system methods.\nC   DLINSD carries out linesearch algorithm for initial condition\nC          calculation (direct case).\nC   DFNRMD calculates weighted norm of preconditioned residual in\nC          initial condition calculation (direct case).\nC   DNEDD  nonlinear equation driver for direct linear system solver\nC          methods.  Interfaces to Newton solver (direct case).\nC   DMATD  assembles the iteration matrix (direct case).\nC   DNSD   solves the associated nonlinear system by modified\nC          Newton iteration and direct linear system methods.\nC   DSLVD  interfaces to linear system solver (direct case).\nC   DDASIK nonlinear equation driver to initialize Y and YPRIME using\nC          Krylov iterative linear system methods.  Interfaces to\nC          Newton solver (Krylov case).\nC   DNSIK  solves the nonlinear system for unknown initial values by\nC          Newton iteration and Krylov iterative linear system methods.\nC   DLINSK carries out linesearch algorithm for initial condition\nC          calculation (Krylov case).\nC   DFNRMK calculates weighted norm of preconditioned residual in\nC          initial condition calculation (Krylov case).\nC   DNEDK  nonlinear equation driver for iterative linear system solver\nC          methods.  Interfaces to Newton solver (Krylov case).\nC   DNSK   solves the associated nonlinear system by Inexact Newton\nC          iteration and (linear) Krylov iteration.\nC   DSLVK  interfaces to linear system solver (Krylov case).\nC   DSPIGM solves a linear system by SPIGMR algorithm.\nC   DATV   computes matrix-vector product in Krylov algorithm.\nC   DORTH  performs orthogonalization of Krylov basis vectors.\nC   DHEQR  performs QR factorization of Hessenberg matrix.\nC   DHELS  finds least-squares solution of Hessenberg linear system.\nC   DGETRF, DGETRS, DGBTRF, DGBTRS are LAPACK routines for solving\nC          linear systems (dense or band direct methods).\nC   DAXPY, DCOPY, DDOT, DNRM2, DSCAL are Basic Linear Algebra (BLAS)\nC          routines.\nC\nC The routines called directly by DDASPK are:\nC   DCNST0, DDAWTS, DINVWT, D1MACH, DDWNRM, DDASIC, DDATRP, DDSTP,\nC   XERRWD\nC\nC***END PROLOGUE DDASPK\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      LOGICAL DONE, LAVL, LCFN, LCFL, LWARN\n      DIMENSION Y(*),YPRIME(*)\n      DIMENSION INFO(20)\n      DIMENSION RWORK(LRW),IWORK(LIW)\n      DIMENSION RTOL(*),ATOL(*)\n      DIMENSION RPAR(*),IPAR(*)\n      CHARACTER MSG*80\n      EXTERNAL  RES, JAC, PSOL, DDASID, DDASIK, DNEDD, DNEDK\nC\nC     Set pointers into IWORK.\nC\n      PARAMETER (LML=1, LMU=2, LMTYPE=4,\n     *   LIWM=1, LMXORD=3, LJCALC=5, LPHASE=6, LK=7, LKOLD=8,\n     *   LNS=9, LNSTL=10, LNST=11, LNRE=12, LNJE=13, LETF=14, LNCFN=15,\n     *   LNCFL=16, LNIW=17, LNRW=18, LNNI=19, LNLI=20, LNPS=21,\n     *   LNPD=22, LMITER=23, LMAXL=24, LKMP=25, LNRMAX=26, LLNWP=27,\n     *   LLNIWP=28, LLOCWP=29, LLCIWP=30, LKPRIN=31,\n     *   LMXNIT=32, LMXNJ=33, LMXNH=34, LLSOFF=35, LICNS=41)\nC\nC     Set pointers into RWORK.\nC\n      PARAMETER (LTSTOP=1, LHMAX=2, LH=3, LTN=4, LCJ=5, LCJOLD=6,\n     *   LHOLD=7, LS=8, LROUND=9, LEPLI=10, LSQRN=11, LRSQRN=12,\n     *   LEPCON=13, LSTOL=14, LEPIN=15,\n     *   LALPHA=21, LBETA=27, LGAMMA=33, LPSI=39, LSIGMA=45, LDELTA=51)\nC\n      SAVE LID, LENID, NONNEG\nC\nC\nC***FIRST EXECUTABLE STATEMENT  DDASPK\nC\nC\n      IF(INFO(1).NE.0) GO TO 100\nC\nC-----------------------------------------------------------------------\nC     This block is executed for the initial call only.\nC     It contains checking of inputs and initializations.\nC-----------------------------------------------------------------------\nC\nC     First check INFO array to make sure all elements of INFO\nC     Are within the proper range.  (INFO(1) is checked later, because\nC     it must be tested on every call.) ITEMP holds the location\nC     within INFO which may be out of range.\nC\n      DO 10 I=2,9\n         ITEMP = I\n         IF (INFO(I) .NE. 0 .AND. INFO(I) .NE. 1) GO TO 701\n 10      CONTINUE\n      ITEMP = 10\n      IF(INFO(10).LT.0 .OR. INFO(10).GT.3) GO TO 701\n      ITEMP = 11\n      IF(INFO(11).LT.0 .OR. INFO(11).GT.2) GO TO 701\n      DO 15 I=12,17\n         ITEMP = I\n         IF (INFO(I) .NE. 0 .AND. INFO(I) .NE. 1) GO TO 701\n 15      CONTINUE\n      ITEMP = 18\n      IF(INFO(18).LT.0 .OR. INFO(18).GT.2) GO TO 701\n\nC\nC     Check NEQ to see if it is positive.\nC\n      IF (NEQ .LE. 0) GO TO 702\nC\nC     Check and compute maximum order.\nC\n      MXORD=5\n      IF (INFO(9) .NE. 0) THEN\n         MXORD=IWORK(LMXORD)\n         IF (MXORD .LT. 1 .OR. MXORD .GT. 5) GO TO 703\n         ENDIF\n      IWORK(LMXORD)=MXORD\nC\nC     Set and/or check inputs for constraint checking (INFO(10) .NE. 0).\nC     Set values for ICNFLG, NONNEG, and pointer LID.\nC\n      ICNFLG = 0\n      NONNEG = 0\n      LID = LICNS\n      IF (INFO(10) .EQ. 0) GO TO 20\n      IF (INFO(10) .EQ. 1) THEN\n         ICNFLG = 1\n         NONNEG = 0\n         LID = LICNS + NEQ\n      ELSEIF (INFO(10) .EQ. 2) THEN\n         ICNFLG = 0\n         NONNEG = 1\n      ELSE\n         ICNFLG = 1\n         NONNEG = 1\n         LID = LICNS + NEQ\n      ENDIF\nC\n 20   CONTINUE\nC\nC     Set and/or check inputs for Krylov solver (INFO(12) .NE. 0).\nC     If indicated, set default values for MAXL, KMP, NRMAX, and EPLI.\nC     Otherwise, verify inputs required for iterative solver.\nC\n      IF (INFO(12) .EQ. 0) GO TO 25\nC\n      IWORK(LMITER) = INFO(12)\n      IF (INFO(13) .EQ. 0) THEN\n         IWORK(LMAXL) = MIN(5,NEQ)\n         IWORK(LKMP) = IWORK(LMAXL)\n         IWORK(LNRMAX) = 5\n         RWORK(LEPLI) = 0.05D0\n      ELSE\n         IF(IWORK(LMAXL) .LT. 1 .OR. IWORK(LMAXL) .GT. NEQ) GO TO 720\n         IF(IWORK(LKMP) .LT. 1 .OR. IWORK(LKMP) .GT. IWORK(LMAXL))\n     1      GO TO 721\n         IF(IWORK(LNRMAX) .LT. 0) GO TO 722\n         IF(RWORK(LEPLI).LE.0.0D0 .OR. RWORK(LEPLI).GE.1.0D0)GO TO 723\n         ENDIF\nC\n 25   CONTINUE\nC\nC     Set and/or check controls for the initial condition calculation\nC     (INFO(11) .GT. 0).  If indicated, set default values.\nC     Otherwise, verify inputs required for iterative solver.\nC\n      IF (INFO(11) .EQ. 0) GO TO 30\n      IF (INFO(17) .EQ. 0) THEN\n        IWORK(LMXNIT) = 5\n        IF (INFO(12) .GT. 0) IWORK(LMXNIT) = 15\n        IWORK(LMXNJ) = 6\n        IF (INFO(12) .GT. 0) IWORK(LMXNJ) = 2\n        IWORK(LMXNH) = 5\n        IWORK(LLSOFF) = 0\n        RWORK(LEPIN) = 0.01D0\n      ELSE\n        IF (IWORK(LMXNIT) .LE. 0) GO TO 725\n        IF (IWORK(LMXNJ) .LE. 0) GO TO 725\n        IF (IWORK(LMXNH) .LE. 0) GO TO 725\n        LSOFF = IWORK(LLSOFF)\n        IF (LSOFF .LT. 0 .OR. LSOFF .GT. 1) GO TO 725\n        IF (RWORK(LEPIN) .LE. 0.0D0) GO TO 725\n        ENDIF\nC\n 30   CONTINUE\nC\nC     Below is the computation and checking of the work array lengths\nC     LENIW and LENRW, using direct methods (INFO(12) = 0) or\nC     the Krylov methods (INFO(12) = 1).\nC\n      LENIC = 0\n      IF (INFO(10) .EQ. 1 .OR. INFO(10) .EQ. 3) LENIC = NEQ\n      LENID = 0\n      IF (INFO(11) .EQ. 1 .OR. INFO(16) .EQ. 1) LENID = NEQ\n      IF (INFO(12) .EQ. 0) THEN\nC\nC        Compute MTYPE, etc.  Check ML and MU.\nC\n         NCPHI = MAX(MXORD + 1, 4)\n         IF(INFO(6).EQ.0) THEN\n            LENPD = NEQ**2\n            LENRW = 50 + (NCPHI+3)*NEQ + LENPD\n            IF(INFO(5).EQ.0) THEN\n               IWORK(LMTYPE)=2\n            ELSE\n               IWORK(LMTYPE)=1\n            ENDIF\n         ELSE\n            IF(IWORK(LML).LT.0.OR.IWORK(LML).GE.NEQ)GO TO 717\n            IF(IWORK(LMU).LT.0.OR.IWORK(LMU).GE.NEQ)GO TO 718\n            LENPD=(2*IWORK(LML)+IWORK(LMU)+1)*NEQ\n            IF(INFO(5).EQ.0) THEN\n               IWORK(LMTYPE)=5\n               MBAND=IWORK(LML)+IWORK(LMU)+1\n               MSAVE=(NEQ/MBAND)+1\n               LENRW = 50 + (NCPHI+3)*NEQ + LENPD + 2*MSAVE\n            ELSE\n               IWORK(LMTYPE)=4\n               LENRW = 50 + (NCPHI+3)*NEQ + LENPD\n            ENDIF\n         ENDIF\nC\nC        Compute LENIW, LENWP, LENIWP.\nC\n         LENIW = 40 + LENIC + LENID + NEQ\n         LENWP = 0\n         LENIWP = 0\nC\n      ELSE IF (INFO(12) .EQ. 1)  THEN\n         MAXL = IWORK(LMAXL)\n         LENWP = IWORK(LLNWP)\n         LENIWP = IWORK(LLNIWP)\n         LENPD = (MAXL+3+MIN0(1,MAXL-IWORK(LKMP)))*NEQ\n     1         + (MAXL+3)*MAXL + 1 + LENWP\n         LENRW = 50 + (IWORK(LMXORD)+5)*NEQ + LENPD\n         LENIW = 40 + LENIC + LENID + LENIWP\nC\n      ENDIF\n      IF(INFO(16) .NE. 0) LENRW = LENRW + NEQ\nC\nC     Check lengths of RWORK and IWORK.\nC\n      IWORK(LNIW)=LENIW\n      IWORK(LNRW)=LENRW\n      IWORK(LNPD)=LENPD\n      IWORK(LLOCWP) = LENPD-LENWP+1\n      IF(LRW.LT.LENRW)GO TO 704\n      IF(LIW.LT.LENIW)GO TO 705\nC\nC     Check ICNSTR for legality.\nC\n      IF (LENIC .GT. 0) THEN\n        DO 40 I = 1,NEQ\n          ICI = IWORK(LICNS-1+I)\n          IF (ICI .LT. -2 .OR. ICI .GT. 2) GO TO 726\n 40       CONTINUE\n        ENDIF\nC\nC     Check Y for consistency with constraints.\nC\n      IF (LENIC .GT. 0) THEN\n        CALL DCNST0(NEQ,Y,IWORK(LICNS),IRET)\n        IF (IRET .NE. 0) GO TO 727\n        ENDIF\nC\nC     Check ID for legality.\nC\n      IF (LENID .GT. 0) THEN\n        DO 50 I = 1,NEQ\n          IDI = IWORK(LID-1+I)\n          IF (IDI .NE. 1 .AND. IDI .NE. -1) GO TO 724\n 50       CONTINUE\n        ENDIF\nC\nC     Check to see that TOUT is different from T.\nC\n      IF(TOUT .EQ. T)GO TO 719\nC\nC     Check HMAX.\nC\n      IF(INFO(7) .NE. 0) THEN\n         HMAX = RWORK(LHMAX)\n         IF (HMAX .LE. 0.0D0) GO TO 710\n         ENDIF\nC\nC     Initialize counters and other flags.\nC\n      IWORK(LNST)=0\n      IWORK(LNRE)=0\n      IWORK(LNJE)=0\n      IWORK(LETF)=0\n      IWORK(LNCFN)=0\n      IWORK(LNNI)=0\n      IWORK(LNLI)=0\n      IWORK(LNPS)=0\n      IWORK(LNCFL)=0\n      IWORK(LKPRIN)=INFO(18)\n      IDID=1\n      GO TO 200\nC\nC-----------------------------------------------------------------------\nC     This block is for continuation calls only.\nC     Here we check INFO(1), and if the last step was interrupted,\nC     we check whether appropriate action was taken.\nC-----------------------------------------------------------------------\nC\n100   CONTINUE\n      IF(INFO(1).EQ.1)GO TO 110\n      ITEMP = 1\n      IF(INFO(1).NE.-1)GO TO 701\nC\nC     If we are here, the last step was interrupted by an error\nC     condition from DDSTP, and appropriate action was not taken.\nC     This is a fatal error.\nC\n      MSG = 'DASPK--  THE LAST STEP TERMINATED WITH A NEGATIVE'\n      CALL XERRWD(MSG,49,201,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASPK--  VALUE (=I1) OF IDID AND NO APPROPRIATE'\n      CALL XERRWD(MSG,47,202,0,1,IDID,0,0,0.0D0,0.0D0)\n      MSG = 'DASPK--  ACTION WAS TAKEN. RUN TERMINATED'\n      CALL XERRWD(MSG,41,203,1,0,0,0,0,0.0D0,0.0D0)\n      RETURN\n110   CONTINUE\nC\nC-----------------------------------------------------------------------\nC     This block is executed on all calls.\nC\nC     Counters are saved for later checks of performance.\nC     Then the error tolerance parameters are checked, and the\nC     work array pointers are set.\nC-----------------------------------------------------------------------\nC\n200   CONTINUE\nC\nC     Save counters for use later.\nC\n      IWORK(LNSTL)=IWORK(LNST)\n      NLI0 = IWORK(LNLI)\n      NNI0 = IWORK(LNNI)\n      NCFN0 = IWORK(LNCFN)\n      NCFL0 = IWORK(LNCFL)\n      NWARN = 0\nC\nC     Check RTOL and ATOL.\nC\n      NZFLG = 0\n      RTOLI = RTOL(1)\n      ATOLI = ATOL(1)\n      DO 210 I=1,NEQ\n         IF (INFO(2) .EQ. 1) RTOLI = RTOL(I)\n         IF (INFO(2) .EQ. 1) ATOLI = ATOL(I)\n         IF (RTOLI .GT. 0.0D0 .OR. ATOLI .GT. 0.0D0) NZFLG = 1\n         IF (RTOLI .LT. 0.0D0) GO TO 706\n         IF (ATOLI .LT. 0.0D0) GO TO 707\n210      CONTINUE\n      IF (NZFLG .EQ. 0) GO TO 708\nC\nC     Set pointers to RWORK and IWORK segments.\nC     For direct methods, SAVR is not used.\nC\n      IWORK(LLCIWP) = LID + LENID\n      LSAVR = LDELTA\n      IF (INFO(12) .NE. 0) LSAVR = LDELTA + NEQ\n      LE = LSAVR + NEQ\n      LWT = LE + NEQ\n      LVT = LWT\n      IF (INFO(16) .NE. 0) LVT = LWT + NEQ\n      LPHI = LVT + NEQ\n      LWM = LPHI + (IWORK(LMXORD)+1)*NEQ\n      IF (INFO(1) .EQ. 1) GO TO 400\nC\nC-----------------------------------------------------------------------\nC     This block is executed on the initial call only.\nC     Set the initial step size, the error weight vector, and PHI.\nC     Compute unknown initial components of Y and YPRIME, if requested.\nC-----------------------------------------------------------------------\nC\n300   CONTINUE\n      TN=T\n      IDID=1\nC\nC     Set error weight array WT and altered weight array VT.\nC\n      CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,Y,RWORK(LWT),RPAR,IPAR)\n      CALL DINVWT(NEQ,RWORK(LWT),IER)\n      IF (IER .NE. 0) GO TO 713\n      IF (INFO(16) .NE. 0) THEN\n        DO 305 I = 1, NEQ\n 305      RWORK(LVT+I-1) = MAX(IWORK(LID+I-1),0)*RWORK(LWT+I-1)\n        ENDIF\nC\nC     Compute unit roundoff and HMIN.\nC\n      UROUND = D1MACH(4)\n      RWORK(LROUND) = UROUND\n      HMIN = 4.0D0*UROUND*MAX(ABS(T),ABS(TOUT))\nC\nC     Set/check STPTOL control for initial condition calculation.\nC\n      IF (INFO(11) .NE. 0) THEN\n        IF( INFO(17) .EQ. 0) THEN\n          RWORK(LSTOL) = UROUND**.6667D0\n        ELSE\n          IF (RWORK(LSTOL) .LE. 0.0D0) GO TO 725\n          ENDIF\n        ENDIF\nC\nC     Compute EPCON and square root of NEQ and its reciprocal, used\nC     inside iterative solver.\nC\n      RWORK(LEPCON) = 0.33D0\n      FLOATN = NEQ\n      RWORK(LSQRN) = SQRT(FLOATN)\n      RWORK(LRSQRN) = 1.D0/RWORK(LSQRN)\nC\nC     Check initial interval to see that it is long enough.\nC\n      TDIST = ABS(TOUT - T)\n      IF(TDIST .LT. HMIN) GO TO 714\nC\nC     Check H0, if this was input.\nC\n      IF (INFO(8) .EQ. 0) GO TO 310\n         H0 = RWORK(LH)\n         IF ((TOUT - T)*H0 .LT. 0.0D0) GO TO 711\n         IF (H0 .EQ. 0.0D0) GO TO 712\n         GO TO 320\n310    CONTINUE\nC\nC     Compute initial stepsize, to be used by either\nC     DDSTP or DDASIC, depending on INFO(11).\nC\n      H0 = 0.001D0*TDIST\n      YPNORM = DDWNRM(NEQ,YPRIME,RWORK(LVT),RPAR,IPAR)\n      IF (YPNORM .GT. 0.5D0/H0) H0 = 0.5D0/YPNORM\n      H0 = SIGN(H0,TOUT-T)\nC\nC     Adjust H0 if necessary to meet HMAX bound.\nC\n320   IF (INFO(7) .EQ. 0) GO TO 330\n         RH = ABS(H0)/RWORK(LHMAX)\n         IF (RH .GT. 1.0D0) H0 = H0/RH\nC\nC     Check against TSTOP, if applicable.\nC\n330   IF (INFO(4) .EQ. 0) GO TO 340\n         TSTOP = RWORK(LTSTOP)\n         IF ((TSTOP - T)*H0 .LT. 0.0D0) GO TO 715\n         IF ((T + H0 - TSTOP)*H0 .GT. 0.0D0) H0 = TSTOP - T\n         IF ((TSTOP - TOUT)*H0 .LT. 0.0D0) GO TO 709\nC\n340   IF (INFO(11) .EQ. 0) GO TO 370\nC\nC     Compute unknown components of initial Y and YPRIME, depending\nC     on INFO(11) and INFO(12).  INFO(12) represents the nonlinear\nC     solver type (direct/Krylov).  Pass the name of the specific\nC     nonlinear solver, depending on INFO(12).  The location of the work\nC     arrays SAVR, YIC, YPIC, PWK also differ in the two cases.\nC\n      NWT = 1\n      EPCONI = RWORK(LEPIN)*RWORK(LEPCON)\n350   IF (INFO(12) .EQ. 0) THEN\n         LYIC = LPHI + 2*NEQ\n         LYPIC = LYIC + NEQ\n         LPWK = LYPIC\n         CALL DDASIC(TN,Y,YPRIME,NEQ,INFO(11),IWORK(LID),\n     *     RES,JAC,PSOL,H0,RWORK(LWT),NWT,IDID,RPAR,IPAR,\n     *     RWORK(LPHI),RWORK(LSAVR),RWORK(LDELTA),RWORK(LE),\n     *     RWORK(LYIC),RWORK(LYPIC),RWORK(LPWK),RWORK(LWM),IWORK(LIWM),\n     *     HMIN,RWORK(LROUND),RWORK(LEPLI),RWORK(LSQRN),RWORK(LRSQRN),\n     *     EPCONI,RWORK(LSTOL),INFO(15),ICNFLG,IWORK(LICNS),DDASID)\n      ELSE IF (INFO(12) .EQ. 1) THEN\n         LYIC = LWM\n         LYPIC = LYIC + NEQ\n         LPWK = LYPIC + NEQ\n         CALL DDASIC(TN,Y,YPRIME,NEQ,INFO(11),IWORK(LID),\n     *     RES,JAC,PSOL,H0,RWORK(LWT),NWT,IDID,RPAR,IPAR,\n     *     RWORK(LPHI),RWORK(LSAVR),RWORK(LDELTA),RWORK(LE),\n     *     RWORK(LYIC),RWORK(LYPIC),RWORK(LPWK),RWORK(LWM),IWORK(LIWM),\n     *     HMIN,RWORK(LROUND),RWORK(LEPLI),RWORK(LSQRN),RWORK(LRSQRN),\n     *     EPCONI,RWORK(LSTOL),INFO(15),ICNFLG,IWORK(LICNS),DDASIK)\n      ENDIF\nC\n      IF (IDID .LT. 0) GO TO 600\nC\nC     DDASIC was successful.  If this was the first call to DDASIC,\nC     update the WT array (with the current Y) and call it again.\nC\n      IF (NWT .EQ. 2) GO TO 355\n      NWT = 2\n      CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,Y,RWORK(LWT),RPAR,IPAR)\n      CALL DINVWT(NEQ,RWORK(LWT),IER)\n      IF (IER .NE. 0) GO TO 713\n      GO TO 350\nC\nC     If INFO(14) = 1, return now with IDID = 4.\nC\n355   IF (INFO(14) .EQ. 1) THEN\n        IDID = 4\n        H = H0\n        IF (INFO(11) .EQ. 1) RWORK(LHOLD) = H0\n        GO TO 590\n      ENDIF\nC\nC     Update the WT and VT arrays one more time, with the new Y.\nC\n      CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,Y,RWORK(LWT),RPAR,IPAR)\n      CALL DINVWT(NEQ,RWORK(LWT),IER)\n      IF (IER .NE. 0) GO TO 713\n      IF (INFO(16) .NE. 0) THEN\n        DO 357 I = 1, NEQ\n 357      RWORK(LVT+I-1) = MAX(IWORK(LID+I-1),0)*RWORK(LWT+I-1)\n        ENDIF\nC\nC     Reset the initial stepsize to be used by DDSTP.\nC     Use H0, if this was input.  Otherwise, recompute H0,\nC     and adjust it if necessary to meet HMAX bound.\nC\n      IF (INFO(8) .NE. 0) THEN\n         H0 = RWORK(LH)\n         GO TO 360\n         ENDIF\nC\n      H0 = 0.001D0*TDIST\n      YPNORM = DDWNRM(NEQ,YPRIME,RWORK(LVT),RPAR,IPAR)\n      IF (YPNORM .GT. 0.5D0/H0) H0 = 0.5D0/YPNORM\n      H0 = SIGN(H0,TOUT-T)\nC\n360   IF (INFO(7) .NE. 0) THEN\n         RH = ABS(H0)/RWORK(LHMAX)\n         IF (RH .GT. 1.0D0) H0 = H0/RH\n         ENDIF\nC\nC     Check against TSTOP, if applicable.\nC\n      IF (INFO(4) .NE. 0) THEN\n         TSTOP = RWORK(LTSTOP)\n         IF ((T + H0 - TSTOP)*H0 .GT. 0.0D0) H0 = TSTOP - T\n         ENDIF\nC\nC     Load H and RWORK(LH) with H0.\nC\n370   H = H0\n      RWORK(LH) = H\nC\nC     Load Y and H*YPRIME into PHI(*,1) and PHI(*,2).\nC\n      ITEMP = LPHI + NEQ\n      DO 380 I = 1,NEQ\n         RWORK(LPHI + I - 1) = Y(I)\n380      RWORK(ITEMP + I - 1) = H*YPRIME(I)\nC\n      GO TO 500\nC\nC-----------------------------------------------------------------------\nC     This block is for continuation calls only.\nC     Its purpose is to check stop conditions before taking a step.\nC     Adjust H if necessary to meet HMAX bound.\nC-----------------------------------------------------------------------\nC\n400   CONTINUE\n      UROUND=RWORK(LROUND)\n      DONE = .FALSE.\n      TN=RWORK(LTN)\n      H=RWORK(LH)\n      IF(INFO(7) .EQ. 0) GO TO 410\n         RH = ABS(H)/RWORK(LHMAX)\n         IF(RH .GT. 1.0D0) H = H/RH\n410   CONTINUE\n      IF(T .EQ. TOUT) GO TO 719\n      IF((T - TOUT)*H .GT. 0.0D0) GO TO 711\n      IF(INFO(4) .EQ. 1) GO TO 430\n      IF(INFO(3) .EQ. 1) GO TO 420\n      IF((TN-TOUT)*H.LT.0.0D0)GO TO 490\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T=TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n420   IF((TN-T)*H .LE. 0.0D0) GO TO 490\n      IF((TN - TOUT)*H .GT. 0.0D0) GO TO 425\n      CALL DDATRP(TN,TN,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TN\n      IDID = 1\n      DONE = .TRUE.\n      GO TO 490\n425   CONTINUE\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n430   IF(INFO(3) .EQ. 1) GO TO 440\n      TSTOP=RWORK(LTSTOP)\n      IF((TN-TSTOP)*H.GT.0.0D0) GO TO 715\n      IF((TSTOP-TOUT)*H.LT.0.0D0)GO TO 709\n      IF((TN-TOUT)*H.LT.0.0D0)GO TO 450\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *   RWORK(LPHI),RWORK(LPSI))\n      T=TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n440   TSTOP = RWORK(LTSTOP)\n      IF((TN-TSTOP)*H .GT. 0.0D0) GO TO 715\n      IF((TSTOP-TOUT)*H .LT. 0.0D0) GO TO 709\n      IF((TN-T)*H .LE. 0.0D0) GO TO 450\n      IF((TN - TOUT)*H .GT. 0.0D0) GO TO 445\n      CALL DDATRP(TN,TN,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TN\n      IDID = 1\n      DONE = .TRUE.\n      GO TO 490\n445   CONTINUE\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n450   CONTINUE\nC\nC     Check whether we are within roundoff of TSTOP.\nC\n      IF(ABS(TN-TSTOP).GT.100.0D0*UROUND*\n     *   (ABS(TN)+ABS(H)))GO TO 460\n      CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      IDID=2\n      T=TSTOP\n      DONE = .TRUE.\n      GO TO 490\n460   TNEXT=TN+H\n      IF((TNEXT-TSTOP)*H.LE.0.0D0)GO TO 490\n      H=TSTOP-TN\n      RWORK(LH)=H\nC\n490   IF (DONE) GO TO 590\nC\nC-----------------------------------------------------------------------\nC     The next block contains the call to the one-step integrator DDSTP.\nC     This is a looping point for the integration steps.\nC     Check for too many steps.\nC     Check for poor Newton/Krylov performance.\nC     Update WT.  Check for too much accuracy requested.\nC     Compute minimum stepsize.\nC-----------------------------------------------------------------------\nC\n500   CONTINUE\nC\nC     Check for too many steps.\nC\n      IF((IWORK(LNST)-IWORK(LNSTL)).LT.500) GO TO 505\n           IDID=-1\n           GO TO 527\nC\nC Check for poor Newton/Krylov performance.\nC\n505   IF (INFO(12) .EQ. 0) GO TO 510\n      NSTD = IWORK(LNST) - IWORK(LNSTL)\n      NNID = IWORK(LNNI) - NNI0\n      IF (NSTD .LT. 10 .OR. NNID .EQ. 0) GO TO 510\n      AVLIN = REAL(IWORK(LNLI) - NLI0)/REAL(NNID)\n      RCFN = REAL(IWORK(LNCFN) - NCFN0)/REAL(NSTD)\n      RCFL = REAL(IWORK(LNCFL) - NCFL0)/REAL(NNID)\n      FMAXL = IWORK(LMAXL)\n      LAVL = AVLIN .GT. FMAXL\n      LCFN = RCFN .GT. 0.9D0\n      LCFL = RCFL .GT. 0.9D0\n      LWARN = LAVL .OR. LCFN .OR. LCFL\n      IF (.NOT.LWARN) GO TO 510\n      NWARN = NWARN + 1\n      IF (NWARN .GT. 10) GO TO 510\n      IF (LAVL) THEN\n        MSG = 'DASPK-- Warning. Poor iterative algorithm performance   '\n        CALL XERRWD (MSG, 56, 501, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n        MSG = '      at T = R1. Average no. of linear iterations = R2  '\n        CALL XERRWD (MSG, 56, 501, 0, 0, 0, 0, 2, TN, AVLIN)\n        ENDIF\n      IF (LCFN) THEN\n        MSG = 'DASPK-- Warning. Poor iterative algorithm performance   '\n        CALL XERRWD (MSG, 56, 502, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n        MSG = '      at T = R1. Nonlinear convergence failure rate = R2'\n        CALL XERRWD (MSG, 56, 502, 0, 0, 0, 0, 2, TN, RCFN)\n        ENDIF\n      IF (LCFL) THEN\n        MSG = 'DASPK-- Warning. Poor iterative algorithm performance   '\n        CALL XERRWD (MSG, 56, 503, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n        MSG = '      at T = R1. Linear convergence failure rate = R2   '\n        CALL XERRWD (MSG, 56, 503, 0, 0, 0, 0, 2, TN, RCFL)\n        ENDIF\nC\nC     Update WT and VT, if this is not the first call.\nC\n510   CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,RWORK(LPHI),RWORK(LWT),\n     *            RPAR,IPAR)\n      CALL DINVWT(NEQ,RWORK(LWT),IER)\n      IF (IER .NE. 0) THEN\n        IDID = -3\n        GO TO 527\n        ENDIF\n      IF (INFO(16) .NE. 0) THEN\n        DO 515 I = 1, NEQ\n 515      RWORK(LVT+I-1) = MAX(IWORK(LID+I-1),0)*RWORK(LWT+I-1)\n        ENDIF\nC\nC     Test for too much accuracy requested.\nC\n      R = DDWNRM(NEQ,RWORK(LPHI),RWORK(LWT),RPAR,IPAR)*100.0D0*UROUND\n      IF (R .LE. 1.0D0) GO TO 525\nC\nC     Multiply RTOL and ATOL by R and return.\nC\n      IF(INFO(2).EQ.1)GO TO 523\n           RTOL(1)=R*RTOL(1)\n           ATOL(1)=R*ATOL(1)\n           IDID=-2\n           GO TO 527\n523   DO 524 I=1,NEQ\n           RTOL(I)=R*RTOL(I)\n524        ATOL(I)=R*ATOL(I)\n      IDID=-2\n      GO TO 527\n525   CONTINUE\nC\nC     Compute minimum stepsize.\nC\n      HMIN=4.0D0*UROUND*MAX(ABS(TN),ABS(TOUT))\nC\nC     Test H vs. HMAX\n      IF (INFO(7) .NE. 0) THEN\n         RH = ABS(H)/RWORK(LHMAX)\n         IF (RH .GT. 1.0D0) H = H/RH\n         ENDIF\nC\nC     Call the one-step integrator.\nC     Note that INFO(12) represents the nonlinear solver type.\nC     Pass the required nonlinear solver, depending upon INFO(12).\nC\n      IF (INFO(12) .EQ. 0) THEN\n         CALL DDSTP(TN,Y,YPRIME,NEQ,\n     *      RES,JAC,PSOL,H,RWORK(LWT),RWORK(LVT),INFO(1),IDID,RPAR,IPAR,\n     *      RWORK(LPHI),RWORK(LSAVR),RWORK(LDELTA),RWORK(LE),\n     *      RWORK(LWM),IWORK(LIWM),\n     *      RWORK(LALPHA),RWORK(LBETA),RWORK(LGAMMA),\n     *      RWORK(LPSI),RWORK(LSIGMA),\n     *      RWORK(LCJ),RWORK(LCJOLD),RWORK(LHOLD),RWORK(LS),HMIN,\n     *      RWORK(LROUND), RWORK(LEPLI),RWORK(LSQRN),RWORK(LRSQRN),\n     *      RWORK(LEPCON), IWORK(LPHASE),IWORK(LJCALC),INFO(15),\n     *      IWORK(LK), IWORK(LKOLD),IWORK(LNS),NONNEG,INFO(12),\n     *      DNEDD)\n      ELSE IF (INFO(12) .EQ. 1) THEN\n         CALL DDSTP(TN,Y,YPRIME,NEQ,\n     *      RES,JAC,PSOL,H,RWORK(LWT),RWORK(LVT),INFO(1),IDID,RPAR,IPAR,\n     *      RWORK(LPHI),RWORK(LSAVR),RWORK(LDELTA),RWORK(LE),\n     *      RWORK(LWM),IWORK(LIWM),\n     *      RWORK(LALPHA),RWORK(LBETA),RWORK(LGAMMA),\n     *      RWORK(LPSI),RWORK(LSIGMA),\n     *      RWORK(LCJ),RWORK(LCJOLD),RWORK(LHOLD),RWORK(LS),HMIN,\n     *      RWORK(LROUND), RWORK(LEPLI),RWORK(LSQRN),RWORK(LRSQRN),\n     *      RWORK(LEPCON), IWORK(LPHASE),IWORK(LJCALC),INFO(15),\n     *      IWORK(LK), IWORK(LKOLD),IWORK(LNS),NONNEG,INFO(12),\n     *      DNEDK)\n      ENDIF\nC\n527   IF(IDID.LT.0)GO TO 600\nC\nC-----------------------------------------------------------------------\nC     This block handles the case of a successful return from DDSTP\nC     (IDID=1).  Test for stop conditions.\nC-----------------------------------------------------------------------\nC\n      IF(INFO(4).NE.0)GO TO 540\n           IF(INFO(3).NE.0)GO TO 530\n             IF((TN-TOUT)*H.LT.0.0D0)GO TO 500\n             CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *         IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n             IDID=3\n             T=TOUT\n             GO TO 580\n530          IF((TN-TOUT)*H.GE.0.0D0)GO TO 535\n             T=TN\n             IDID=1\n             GO TO 580\n535          CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *         IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n             IDID=3\n             T=TOUT\n             GO TO 580\n540   IF(INFO(3).NE.0)GO TO 550\n      IF((TN-TOUT)*H.LT.0.0D0)GO TO 542\n         CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *     IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n         T=TOUT\n         IDID=3\n         GO TO 580\n542   IF(ABS(TN-TSTOP).LE.100.0D0*UROUND*\n     *   (ABS(TN)+ABS(H)))GO TO 545\n      TNEXT=TN+H\n      IF((TNEXT-TSTOP)*H.LE.0.0D0)GO TO 500\n      H=TSTOP-TN\n      GO TO 500\n545   CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,\n     *  IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n      IDID=2\n      T=TSTOP\n      GO TO 580\n550   IF((TN-TOUT)*H.GE.0.0D0)GO TO 555\n      IF(ABS(TN-TSTOP).LE.100.0D0*UROUND*(ABS(TN)+ABS(H)))GO TO 552\n      T=TN\n      IDID=1\n      GO TO 580\n552   CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,\n     *  IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n      IDID=2\n      T=TSTOP\n      GO TO 580\n555   CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *   IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n      T=TOUT\n      IDID=3\n580   CONTINUE\nC\nC-----------------------------------------------------------------------\nC     All successful returns from DDASPK are made from this block.\nC-----------------------------------------------------------------------\nC\n590   CONTINUE\n      RWORK(LTN)=TN\n      RWORK(LH)=H\n      RETURN\nC\nC-----------------------------------------------------------------------\nC     This block handles all unsuccessful returns other than for\nC     illegal input.\nC-----------------------------------------------------------------------\nC\n600   CONTINUE\n      ITEMP = -IDID\n      GO TO (610,620,630,700,655,640,650,660,670,675,\n     *  680,685,690,695), ITEMP\nC\nC     The maximum number of steps was taken before\nC     reaching tout.\nC\n610   MSG = 'DASPK--  AT CURRENT T (=R1)  500 STEPS'\n      CALL XERRWD(MSG,38,610,0,0,0,0,1,TN,0.0D0)\n      MSG = 'DASPK--  TAKEN ON THIS CALL BEFORE REACHING TOUT'\n      CALL XERRWD(MSG,48,611,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     Too much accuracy for machine precision.\nC\n620   MSG = 'DASPK--  AT T (=R1) TOO MUCH ACCURACY REQUESTED'\n      CALL XERRWD(MSG,47,620,0,0,0,0,1,TN,0.0D0)\n      MSG = 'DASPK--  FOR PRECISION OF MACHINE. RTOL AND ATOL'\n      CALL XERRWD(MSG,48,621,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASPK--  WERE INCREASED TO APPROPRIATE VALUES'\n      CALL XERRWD(MSG,45,622,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     WT(I) .LE. 0.0D0 for some I (not at start of problem).\nC\n630   MSG = 'DASPK--  AT T (=R1) SOME ELEMENT OF WT'\n      CALL XERRWD(MSG,38,630,0,0,0,0,1,TN,0.0D0)\n      MSG = 'DASPK--  HAS BECOME .LE. 0.0'\n      CALL XERRWD(MSG,28,631,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     Error test failed repeatedly or with H=HMIN.\nC\n640   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,640,0,0,0,0,2,TN,H)\n      MSG='DASPK--  ERROR TEST FAILED REPEATEDLY OR WITH ABS(H)=HMIN'\n      CALL XERRWD(MSG,57,641,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     Nonlinear solver failed to converge repeatedly or with H=HMIN.\nC\n650   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,650,0,0,0,0,2,TN,H)\n      MSG = 'DASPK--  NONLINEAR SOLVER FAILED TO CONVERGE'\n      CALL XERRWD(MSG,44,651,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASPK--  REPEATEDLY OR WITH ABS(H)=HMIN'\n      CALL XERRWD(MSG,40,652,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     The preconditioner had repeated failures.\nC\n655   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,655,0,0,0,0,2,TN,H)\n      MSG = 'DASPK--  PRECONDITIONER HAD REPEATED FAILURES.'\n      CALL XERRWD(MSG,46,656,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     The iteration matrix is singular.\nC\n660   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,660,0,0,0,0,2,TN,H)\n      MSG = 'DASPK--  ITERATION MATRIX IS SINGULAR.'\n      CALL XERRWD(MSG,38,661,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     Nonlinear system failure preceded by error test failures.\nC\n670   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,670,0,0,0,0,2,TN,H)\n      MSG = 'DASPK--  NONLINEAR SOLVER COULD NOT CONVERGE.'\n      CALL XERRWD(MSG,45,671,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASPK--  ALSO, THE ERROR TEST FAILED REPEATEDLY.'\n      CALL XERRWD(MSG,49,672,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     Nonlinear system failure because IRES = -1.\nC\n675   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,675,0,0,0,0,2,TN,H)\n      MSG = 'DASPK--  NONLINEAR SYSTEM SOLVER COULD NOT CONVERGE'\n      CALL XERRWD(MSG,51,676,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASPK--  BECAUSE IRES WAS EQUAL TO MINUS ONE'\n      CALL XERRWD(MSG,44,677,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     Failure because IRES = -2.\nC\n680   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2)'\n      CALL XERRWD(MSG,40,680,0,0,0,0,2,TN,H)\n      MSG = 'DASPK--  IRES WAS EQUAL TO MINUS TWO'\n      CALL XERRWD(MSG,36,681,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     Failed to compute initial YPRIME.\nC\n685   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,685,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASPK--  INITIAL (Y,YPRIME) COULD NOT BE COMPUTED'\n      CALL XERRWD(MSG,49,686,0,0,0,0,2,TN,H0)\n      GO TO 700\nC\nC     Failure because IER was negative from PSOL.\nC\n690   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2)'\n      CALL XERRWD(MSG,40,690,0,0,0,0,2,TN,H)\n      MSG = 'DASPK--  IER WAS NEGATIVE FROM PSOL'\n      CALL XERRWD(MSG,35,691,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC     Failure because the linear system solver could not converge.\nC\n695   MSG = 'DASPK--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,695,0,0,0,0,2,TN,H)\n      MSG = 'DASPK--  LINEAR SYSTEM SOLVER COULD NOT CONVERGE.'\n      CALL XERRWD(MSG,50,696,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 700\nC\nC\n700   CONTINUE\n      INFO(1)=-1\n      T=TN\n      RWORK(LTN)=TN\n      RWORK(LH)=H\n      RETURN\nC\nC-----------------------------------------------------------------------\nC     This block handles all error returns due to illegal input,\nC     as detected before calling DDSTP.\nC     First the error message routine is called.  If this happens\nC     twice in succession, execution is terminated.\nC-----------------------------------------------------------------------\nC\n701   MSG = 'DASPK--  ELEMENT (=I1) OF INFO VECTOR IS NOT VALID'\n      CALL XERRWD(MSG,50,1,0,1,ITEMP,0,0,0.0D0,0.0D0)\n      GO TO 750\n702   MSG = 'DASPK--  NEQ (=I1) .LE. 0'\n      CALL XERRWD(MSG,25,2,0,1,NEQ,0,0,0.0D0,0.0D0)\n      GO TO 750\n703   MSG = 'DASPK--  MAXORD (=I1) NOT IN RANGE'\n      CALL XERRWD(MSG,34,3,0,1,MXORD,0,0,0.0D0,0.0D0)\n      GO TO 750\n704   MSG='DASPK--  RWORK LENGTH NEEDED, LENRW (=I1), EXCEEDS LRW (=I2)'\n      CALL XERRWD(MSG,60,4,0,2,LENRW,LRW,0,0.0D0,0.0D0)\n      GO TO 750\n705   MSG='DASPK--  IWORK LENGTH NEEDED, LENIW (=I1), EXCEEDS LIW (=I2)'\n      CALL XERRWD(MSG,60,5,0,2,LENIW,LIW,0,0.0D0,0.0D0)\n      GO TO 750\n706   MSG = 'DASPK--  SOME ELEMENT OF RTOL IS .LT. 0'\n      CALL XERRWD(MSG,39,6,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n707   MSG = 'DASPK--  SOME ELEMENT OF ATOL IS .LT. 0'\n      CALL XERRWD(MSG,39,7,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n708   MSG = 'DASPK--  ALL ELEMENTS OF RTOL AND ATOL ARE ZERO'\n      CALL XERRWD(MSG,47,8,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n709   MSG='DASPK--  INFO(4) = 1 AND TSTOP (=R1) BEHIND TOUT (=R2)'\n      CALL XERRWD(MSG,54,9,0,0,0,0,2,TSTOP,TOUT)\n      GO TO 750\n710   MSG = 'DASPK--  HMAX (=R1) .LT. 0.0'\n      CALL XERRWD(MSG,28,10,0,0,0,0,1,HMAX,0.0D0)\n      GO TO 750\n711   MSG = 'DASPK--  TOUT (=R1) BEHIND T (=R2)'\n      CALL XERRWD(MSG,34,11,0,0,0,0,2,TOUT,T)\n      GO TO 750\n712   MSG = 'DASPK--  INFO(8)=1 AND H0=0.0'\n      CALL XERRWD(MSG,29,12,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n713   MSG = 'DASPK--  SOME ELEMENT OF WT IS .LE. 0.0'\n      CALL XERRWD(MSG,39,13,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n714   MSG='DASPK-- TOUT (=R1) TOO CLOSE TO T (=R2) TO START INTEGRATION'\n      CALL XERRWD(MSG,60,14,0,0,0,0,2,TOUT,T)\n      GO TO 750\n715   MSG = 'DASPK--  INFO(4)=1 AND TSTOP (=R1) BEHIND T (=R2)'\n      CALL XERRWD(MSG,49,15,0,0,0,0,2,TSTOP,T)\n      GO TO 750\n717   MSG = 'DASPK--  ML (=I1) ILLEGAL. EITHER .LT. 0 OR .GT. NEQ'\n      CALL XERRWD(MSG,52,17,0,1,IWORK(LML),0,0,0.0D0,0.0D0)\n      GO TO 750\n718   MSG = 'DASPK--  MU (=I1) ILLEGAL. EITHER .LT. 0 OR .GT. NEQ'\n      CALL XERRWD(MSG,52,18,0,1,IWORK(LMU),0,0,0.0D0,0.0D0)\n      GO TO 750\n719   MSG = 'DASPK--  TOUT (=R1) IS EQUAL TO T (=R2)'\n      CALL XERRWD(MSG,39,19,0,0,0,0,2,TOUT,T)\n      GO TO 750\n720   MSG = 'DASPK--  MAXL (=I1) ILLEGAL. EITHER .LT. 1 OR .GT. NEQ'\n      CALL XERRWD(MSG,54,20,0,1,IWORK(LMAXL),0,0,0.0D0,0.0D0)\n      GO TO 750\n721   MSG = 'DASPK--  KMP (=I1) ILLEGAL. EITHER .LT. 1 OR .GT. MAXL'\n      CALL XERRWD(MSG,54,21,0,1,IWORK(LKMP),0,0,0.0D0,0.0D0)\n      GO TO 750\n722   MSG = 'DASPK--  NRMAX (=I1) ILLEGAL. .LT. 0'\n      CALL XERRWD(MSG,36,22,0,1,IWORK(LNRMAX),0,0,0.0D0,0.0D0)\n      GO TO 750\n723   MSG = 'DASPK--  EPLI (=R1) ILLEGAL. EITHER .LE. 0.D0 OR .GE. 1.D0'\n      CALL XERRWD(MSG,58,23,0,0,0,0,1,RWORK(LEPLI),0.0D0)\n      GO TO 750\n724   MSG = 'DASPK--  ILLEGAL IWORK VALUE FOR INFO(11) .NE. 0'\n      CALL XERRWD(MSG,48,24,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n725   MSG = 'DASPK--  ONE OF THE INPUTS FOR INFO(17) = 1 IS ILLEGAL'\n      CALL XERRWD(MSG,54,25,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n726   MSG = 'DASPK--  ILLEGAL IWORK VALUE FOR INFO(10) .NE. 0'\n      CALL XERRWD(MSG,48,26,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n727   MSG = 'DASPK--  Y(I) AND IWORK(40+I) (I=I1) INCONSISTENT'\n      CALL XERRWD(MSG,49,27,0,1,IRET,0,0,0.0D0,0.0D0)\n      GO TO 750\n750   IF(INFO(1).EQ.-1) GO TO 760\n      INFO(1)=-1\n      IDID=-33\n      RETURN\n760   MSG = 'DASPK--  REPEATED OCCURRENCES OF ILLEGAL INPUT'\n      CALL XERRWD(MSG,46,701,0,0,0,0,0,0.0D0,0.0D0)\n770   MSG = 'DASPK--  RUN TERMINATED. APPARENT INFINITE LOOP'\n      CALL XERRWD(MSG,47,702,1,0,0,0,0,0.0D0,0.0D0)\n      RETURN\nC\nC------END OF SUBROUTINE DDASPK-----------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/ddstp.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DDSTP(X,Y,YPRIME,NEQ,RES,JAC,PSOL,H,WT,VT,\n     *  JSTART,IDID,RPAR,IPAR,PHI,SAVR,DELTA,E,WM,IWM,\n     *  ALPHA,BETA,GAMMA,PSI,SIGMA,CJ,CJOLD,HOLD,S,HMIN,UROUND,\n     *  EPLI,SQRTN,RSQRTN,EPCON,IPHASE,JCALC,JFLG,K,KOLD,NS,NONNEG,\n     *  NTYPE,NLS)\nC\nC***BEGIN PROLOGUE  DDSTP\nC***REFER TO  DDASPK\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***REVISION DATE  940909   (YYMMDD) (Reset PSI(1), PHI(*,2) at 690)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DDSTP solves a system of differential/algebraic equations of\nC     the form G(X,Y,YPRIME) = 0, for one step (normally from X to X+H).\nC\nC     The methods used are modified divided difference, fixed leading\nC     coefficient forms of backward differentiation formulas.\nC     The code adjusts the stepsize and order to control the local error\nC     per step.\nC\nC\nC     The parameters represent\nC     X  --        Independent variable.\nC     Y  --        Solution vector at X.\nC     YPRIME --    Derivative of solution vector\nC                  after successful step.\nC     NEQ --       Number of equations to be integrated.\nC     RES --       External user-supplied subroutine\nC                  to evaluate the residual.  See RES description\nC                  in DDASPK prologue.\nC     JAC --       External user-supplied routine to update\nC                  Jacobian or preconditioner information in the\nC                  nonlinear solver.  See JAC description in DDASPK\nC                  prologue.\nC     PSOL --      External user-supplied routine to solve\nC                  a linear system using preconditioning.\nC                  (This is optional).  See PSOL in DDASPK prologue.\nC     H --         Appropriate step size for next step.\nC                  Normally determined by the code.\nC     WT --        Vector of weights for error criterion used in Newton test.\nC     VT --        Masked vector of weights used in error test.\nC     JSTART --    Integer variable set 0 for\nC                  first step, 1 otherwise.\nC     IDID --      Completion code returned from the nonlinear solver.\nC                  See IDID description in DDASPK prologue.\nC     RPAR,IPAR -- Real and integer parameter arrays that\nC                  are used for communication between the\nC                  calling program and external user routines.\nC                  They are not altered by DNSK\nC     PHI --       Array of divided differences used by\nC                  DDSTP. The length is NEQ*(K+1), where\nC                  K is the maximum order.\nC     SAVR --      Work vector for DDSTP of length NEQ.\nC     DELTA,E --   Work vectors for DDSTP of length NEQ.\nC     WM,IWM --    Real and integer arrays storing\nC                  information required by the linear solver.\nC\nC     The other parameters are information\nC     which is needed internally by DDSTP to\nC     continue from step to step.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   NLS, DDWNRM, DDATRP\nC\nC***END PROLOGUE  DDSTP\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),WT(*),VT(*)\n      DIMENSION PHI(NEQ,*),SAVR(*),DELTA(*),E(*)\n      DIMENSION WM(*),IWM(*)\n      DIMENSION PSI(*),ALPHA(*),BETA(*),GAMMA(*),SIGMA(*)\n      DIMENSION RPAR(*),IPAR(*)\n      EXTERNAL  RES, JAC, PSOL, NLS\nC\n      PARAMETER (LMXORD=3)\n      PARAMETER (LNST=11, LETF=14, LCFN=15)\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 1.\nC     Initialize.  On the first call, set\nC     the order to 1 and initialize\nC     other variables.\nC-----------------------------------------------------------------------\nC\nC     Initializations for all calls\nC\n      XOLD=X\n      NCF=0\n      NEF=0\n      IF(JSTART .NE. 0) GO TO 120\nC\nC     If this is the first step, perform\nC     other initializations\nC\n      K=1\n      KOLD=0\n      HOLD=0.0D0\n      PSI(1)=H\n      CJ = 1.D0/H\n      IPHASE = 0\n      NS=0\n120   CONTINUE\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 2\nC     Compute coefficients of formulas for\nC     this step.\nC-----------------------------------------------------------------------\n200   CONTINUE\n      KP1=K+1\n      KP2=K+2\n      KM1=K-1\n      IF(H.NE.HOLD.OR.K .NE. KOLD) NS = 0\n      NS=MIN0(NS+1,KOLD+2)\n      NSP1=NS+1\n      IF(KP1 .LT. NS)GO TO 230\nC\n      BETA(1)=1.0D0\n      ALPHA(1)=1.0D0\n      TEMP1=H\n      GAMMA(1)=0.0D0\n      SIGMA(1)=1.0D0\n      DO 210 I=2,KP1\n         TEMP2=PSI(I-1)\n         PSI(I-1)=TEMP1\n         BETA(I)=BETA(I-1)*PSI(I-1)/TEMP2\n         TEMP1=TEMP2+H\n         ALPHA(I)=H/TEMP1\n         SIGMA(I)=(I-1)*SIGMA(I-1)*ALPHA(I)\n         GAMMA(I)=GAMMA(I-1)+ALPHA(I-1)/H\n210      CONTINUE\n      PSI(KP1)=TEMP1\n230   CONTINUE\nC\nC     Compute ALPHAS, ALPHA0\nC\n      ALPHAS = 0.0D0\n      ALPHA0 = 0.0D0\n      DO 240 I = 1,K\n        ALPHAS = ALPHAS - 1.0D0/I\n        ALPHA0 = ALPHA0 - ALPHA(I)\n240     CONTINUE\nC\nC     Compute leading coefficient CJ\nC\n      CJLAST = CJ\n      CJ = -ALPHAS/H\nC\nC     Compute variable stepsize error coefficient CK\nC\n      CK = ABS(ALPHA(KP1) + ALPHAS - ALPHA0)\n      CK = MAX(CK,ALPHA(KP1))\nC\nC     Change PHI to PHI STAR\nC\n      IF(KP1 .LT. NSP1) GO TO 280\n      DO 270 J=NSP1,KP1\n         DO 260 I=1,NEQ\n260         PHI(I,J)=BETA(J)*PHI(I,J)\n270      CONTINUE\n280   CONTINUE\nC\nC     Update time\nC\n      X=X+H\nC\nC     Initialize IDID to 1\nC\n      IDID = 1\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 3\nC     Call the nonlinear system solver to obtain the solution and\nC     derivative.\nC-----------------------------------------------------------------------\nC\n      CALL NLS(X,Y,YPRIME,NEQ,\n     *   RES,JAC,PSOL,H,WT,JSTART,IDID,RPAR,IPAR,PHI,GAMMA,\n     *   SAVR,DELTA,E,WM,IWM,CJ,CJOLD,CJLAST,S,\n     *   UROUND,EPLI,SQRTN,RSQRTN,EPCON,JCALC,JFLG,KP1,\n     *   NONNEG,NTYPE,IERNLS)\nC\n      IF(IERNLS .NE. 0)GO TO 600\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 4\nC     Estimate the errors at orders K,K-1,K-2\nC     as if constant stepsize was used. Estimate\nC     the local error at order K and test\nC     whether the current step is successful.\nC-----------------------------------------------------------------------\nC\nC     Estimate errors at orders K,K-1,K-2\nC\n      ENORM = DDWNRM(NEQ,E,VT,RPAR,IPAR)\n      ERK = SIGMA(K+1)*ENORM\n      TERK = (K+1)*ERK\n      EST = ERK\n      KNEW=K\n      IF(K .EQ. 1)GO TO 430\n      DO 405 I = 1,NEQ\n405     DELTA(I) = PHI(I,KP1) + E(I)\n      ERKM1=SIGMA(K)*DDWNRM(NEQ,DELTA,VT,RPAR,IPAR)\n      TERKM1 = K*ERKM1\n      IF(K .GT. 2)GO TO 410\n      IF(TERKM1 .LE. 0.5*TERK)GO TO 420\n      GO TO 430\n410   CONTINUE\n      DO 415 I = 1,NEQ\n415     DELTA(I) = PHI(I,K) + DELTA(I)\n      ERKM2=SIGMA(K-1)*DDWNRM(NEQ,DELTA,VT,RPAR,IPAR)\n      TERKM2 = (K-1)*ERKM2\n      IF(MAX(TERKM1,TERKM2).GT.TERK)GO TO 430\nC\nC     Lower the order\nC\n420   CONTINUE\n      KNEW=K-1\n      EST = ERKM1\nC\nC\nC     Calculate the local error for the current step\nC     to see if the step was successful\nC\n430   CONTINUE\n      ERR = CK * ENORM\n      IF(ERR .GT. 1.0D0)GO TO 600\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 5\nC     The step is successful. Determine\nC     the best order and stepsize for\nC     the next step. Update the differences\nC     for the next step.\nC-----------------------------------------------------------------------\n      IDID=1\n      IWM(LNST)=IWM(LNST)+1\n      KDIFF=K-KOLD\n      KOLD=K\n      HOLD=H\nC\nC\nC     Estimate the error at order K+1 unless\nC        already decided to lower order, or\nC        already using maximum order, or\nC        stepsize not constant, or\nC        order raised in previous step\nC\n      IF(KNEW.EQ.KM1.OR.K.EQ.IWM(LMXORD))IPHASE=1\n      IF(IPHASE .EQ. 0)GO TO 545\n      IF(KNEW.EQ.KM1)GO TO 540\n      IF(K.EQ.IWM(LMXORD)) GO TO 550\n      IF(KP1.GE.NS.OR.KDIFF.EQ.1)GO TO 550\n      DO 510 I=1,NEQ\n510      DELTA(I)=E(I)-PHI(I,KP2)\n      ERKP1 = (1.0D0/(K+2))*DDWNRM(NEQ,DELTA,VT,RPAR,IPAR)\n      TERKP1 = (K+2)*ERKP1\n      IF(K.GT.1)GO TO 520\n      IF(TERKP1.GE.0.5D0*TERK)GO TO 550\n      GO TO 530\n520   IF(TERKM1.LE.MIN(TERK,TERKP1))GO TO 540\n      IF(TERKP1.GE.TERK.OR.K.EQ.IWM(LMXORD))GO TO 550\nC\nC     Raise order\nC\n530   K=KP1\n      EST = ERKP1\n      GO TO 550\nC\nC     Lower order\nC\n540   K=KM1\n      EST = ERKM1\n      GO TO 550\nC\nC     If IPHASE = 0, increase order by one and multiply stepsize by\nC     factor two\nC\n545   K = KP1\n      HNEW = H*2.0D0\n      H = HNEW\n      GO TO 575\nC\nC\nC     Determine the appropriate stepsize for\nC     the next step.\nC\n550   HNEW=H\n      TEMP2=K+1\n      R=(2.0D0*EST+0.0001D0)**(-1.0D0/TEMP2)\n      IF(R .LT. 2.0D0) GO TO 555\n      HNEW = 2.0D0*H\n      GO TO 560\n555   IF(R .GT. 1.0D0) GO TO 560\n      R = MAX(0.5D0,MIN(0.9D0,R))\n      HNEW = H*R\n560   H=HNEW\nC\nC\nC     Update differences for next step\nC\n575   CONTINUE\n      IF(KOLD.EQ.IWM(LMXORD))GO TO 585\n      DO 580 I=1,NEQ\n580      PHI(I,KP2)=E(I)\n585   CONTINUE\n      DO 590 I=1,NEQ\n590      PHI(I,KP1)=PHI(I,KP1)+E(I)\n      DO 595 J1=2,KP1\n         J=KP1-J1+1\n         DO 595 I=1,NEQ\n595      PHI(I,J)=PHI(I,J)+PHI(I,J+1)\n      JSTART = 1\n      RETURN\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 6\nC     The step is unsuccessful. Restore X,PSI,PHI\nC     Determine appropriate stepsize for\nC     continuing the integration, or exit with\nC     an error flag if there have been many\nC     failures.\nC-----------------------------------------------------------------------\n600   IPHASE = 1\nC\nC     Restore X,PHI,PSI\nC\n      X=XOLD\n      IF(KP1.LT.NSP1)GO TO 630\n      DO 620 J=NSP1,KP1\n         TEMP1=1.0D0/BETA(J)\n         DO 610 I=1,NEQ\n610         PHI(I,J)=TEMP1*PHI(I,J)\n620      CONTINUE\n630   CONTINUE\n      DO 640 I=2,KP1\n640      PSI(I-1)=PSI(I)-H\nC\nC\nC     Test whether failure is due to nonlinear solver\nC     or error test\nC\n      IF(IERNLS .EQ. 0)GO TO 660\n      IWM(LCFN)=IWM(LCFN)+1\nC\nC\nC     The nonlinear solver failed to converge.\nC     Determine the cause of the failure and take appropriate action.\nC     If IERNLS .LT. 0, then return.  Otherwise, reduce the stepsize\nC     and try again, unless too many failures have occurred.\nC\n      IF (IERNLS .LT. 0) GO TO 675\n      NCF = NCF + 1\n      R = 0.25D0\n      H = H*R\n      IF (NCF .LT. 10 .AND. ABS(H) .GE. HMIN) GO TO 690\n      IF (IDID .EQ. 1) IDID = -7\n      IF (NEF .GE. 3) IDID = -9\n      GO TO 675\nC\nC\nC     The nonlinear solver converged, and the cause\nC     of the failure was the error estimate\nC     exceeding the tolerance.\nC\n660   NEF=NEF+1\n      IWM(LETF)=IWM(LETF)+1\n      IF (NEF .GT. 1) GO TO 665\nC\nC     On first error test failure, keep current order or lower\nC     order by one.  Compute new stepsize based on differences\nC     of the solution.\nC\n      K = KNEW\n      TEMP2 = K + 1\n      R = 0.90D0*(2.0D0*EST+0.0001D0)**(-1.0D0/TEMP2)\n      R = MAX(0.25D0,MIN(0.9D0,R))\n      H = H*R\n      IF (ABS(H) .GE. HMIN) GO TO 690\n      IDID = -6\n      GO TO 675\nC\nC     On second error test failure, use the current order or\nC     decrease order by one.  Reduce the stepsize by a factor of\nC     one quarter.\nC\n665   IF (NEF .GT. 2) GO TO 670\n      K = KNEW\n      R = 0.25D0\n      H = R*H\n      IF (ABS(H) .GE. HMIN) GO TO 690\n      IDID = -6\n      GO TO 675\nC\nC     On third and subsequent error test failures, set the order to\nC     one, and reduce the stepsize by a factor of one quarter.\nC\n670   K = 1\n      R = 0.25D0\n      H = R*H\n      IF (ABS(H) .GE. HMIN) GO TO 690\n      IDID = -6\n      GO TO 675\nC\nC\nC\nC\nC     For all crashes, restore Y to its last value,\nC     interpolate to find YPRIME at last X, and return.\nC\nC     Before returning, verify that the user has not set\nC     IDID to a nonnegative value.  If the user has set IDID\nC     to a nonnegative value, then reset IDID to be -7, indicating\nC     a failure in the nonlinear system solver.\nC\n675   CONTINUE\n      CALL DDATRP(X,X,Y,YPRIME,NEQ,K,PHI,PSI)\n      JSTART = 1\n      IF (IDID .GE. 0) IDID = -7\n      RETURN\nC\nC\nC     Go back and try this step again.\nC     If this is the first step, reset PSI(1) and rescale PHI(*,2).\nC\n690   IF (KOLD .EQ. 0) THEN\n        PSI(1) = H\n        DO 695 I = 1,NEQ\n695       PHI(I,2) = R*PHI(I,2)\n        ENDIF\n      GO TO 200\nC\nC------END OF SUBROUTINE DDSTP------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/ddwnrm.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      DOUBLE PRECISION FUNCTION DDWNRM(NEQ,V,RWT,RPAR,IPAR)\nC\nC***BEGIN PROLOGUE  DDWNRM\nC***ROUTINES CALLED  (NONE)\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***END PROLOGUE  DDWNRM\nC-----------------------------------------------------------------------\nC     This function routine computes the weighted\nC     root-mean-square norm of the vector of length\nC     NEQ contained in the array V, with reciprocal weights\nC     contained in the array RWT of length NEQ.\nC        DDWNRM=SQRT((1/NEQ)*SUM(V(I)*RWT(I))**2)\nC-----------------------------------------------------------------------\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION V(*),RWT(*)\n      DIMENSION RPAR(*),IPAR(*)\n      DDWNRM = 0.0D0\n      VMAX = 0.0D0\n      DO 10 I = 1,NEQ\n        IF(ABS(V(I)*RWT(I)) .GT. VMAX) VMAX = ABS(V(I)*RWT(I))\n10    CONTINUE\n      IF(VMAX .LE. 0.0D0) GO TO 30\n      SUM = 0.0D0\n      DO 20 I = 1,NEQ\n20      SUM = SUM + ((V(I)*RWT(I))/VMAX)**2\n      DDWNRM = VMAX*SQRT(SUM/NEQ)\n30    CONTINUE\n      RETURN\nC\nC------END OF FUNCTION DDWNRM-------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dfnrmd.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DFNRMD (NEQ, Y, T, YPRIME, R, CJ, WT, RES, IRES,\n     *                   FNORM, WM, IWM, RPAR, IPAR)\nC\nC***BEGIN PROLOGUE  DFNRMD\nC***REFER TO  DLINSD\nC***DATE WRITTEN   941025   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DFNRMD calculates the scaled preconditioned norm of the nonlinear\nC     function used in the nonlinear iteration for obtaining consistent\nC     initial conditions.  Specifically, DFNRMD calculates the weighted\nC     root-mean-square norm of the vector (J-inverse)*G(T,Y,YPRIME),\nC     where J is the Jacobian matrix.\nC\nC     In addition to the parameters described in the calling program\nC     DLINSD, the parameters represent\nC\nC     R      -- Array of length NEQ that contains\nC               (J-inverse)*G(T,Y,YPRIME) on return.\nC     FNORM  -- Scalar containing the weighted norm of R on return.\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   RES, DSLVD, DDWNRM\nC\nC***END PROLOGUE  DFNRMD\nC\nC\n      IMPLICIT DOUBLE PRECISION (A-H,O-Z)\n      EXTERNAL RES\n      DIMENSION Y(*), YPRIME(*), WT(*), R(*)\n      DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)\nC-----------------------------------------------------------------------\nC     Call RES routine.\nC-----------------------------------------------------------------------\n      IRES = 0\n      CALL RES(T,Y,YPRIME,CJ,R,IRES,RPAR,IPAR)\n      IF (IRES .LT. 0) RETURN\nC-----------------------------------------------------------------------\nC     Apply inverse of Jacobian to vector R.\nC-----------------------------------------------------------------------\n      CALL DSLVD(NEQ,R,WM,IWM)\nC-----------------------------------------------------------------------\nC     Calculate norm of R.\nC-----------------------------------------------------------------------\n      FNORM = DDWNRM(NEQ,R,WT,RPAR,IPAR)\nC\n      RETURN\nC----------------------- END OF SUBROUTINE DFNRMD ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dfnrmk.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DFNRMK (NEQ, Y, T, YPRIME, SAVR, R, CJ, WT,\n     *                   SQRTN, RSQRTN, RES, IRES, PSOL, IRIN, IER,\n     *                   FNORM, EPLIN, WP, IWP, PWK, RPAR, IPAR)\nC\nC***BEGIN PROLOGUE  DFNRMK\nC***REFER TO  DLINSK\nC***DATE WRITTEN   940830   (YYMMDD)\nC***REVISION DATE  951006   (SQRTN, RSQRTN, and scaling of WT added.)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DFNRMK calculates the scaled preconditioned norm of the nonlinear\nC     function used in the nonlinear iteration for obtaining consistent\nC     initial conditions.  Specifically, DFNRMK calculates the weighted\nC     root-mean-square norm of the vector (P-inverse)*G(T,Y,YPRIME),\nC     where P is the preconditioner matrix.\nC\nC     In addition to the parameters described in the calling program\nC     DLINSK, the parameters represent\nC\nC     IRIN   -- Flag showing whether the current residual vector is\nC               input in SAVR.  1 means it is, 0 means it is not.\nC     R      -- Array of length NEQ that contains\nC               (P-inverse)*G(T,Y,YPRIME) on return.\nC     FNORM  -- Scalar containing the weighted norm of R on return.\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   RES, DCOPY, DSCAL, PSOL, DDWNRM\nC\nC***END PROLOGUE  DFNRMK\nC\nC\n      IMPLICIT DOUBLE PRECISION (A-H,O-Z)\n      EXTERNAL RES, PSOL\n      DIMENSION Y(*), YPRIME(*), WT(*), SAVR(*), R(*), PWK(*)\n      DIMENSION WP(*), IWP(*), RPAR(*), IPAR(*)\nC-----------------------------------------------------------------------\nC     Call RES routine if IRIN = 0.\nC-----------------------------------------------------------------------\n      IF (IRIN .EQ. 0) THEN\n        IRES = 0\n        CALL RES (T, Y, YPRIME, CJ, SAVR, IRES, RPAR, IPAR)\n        IF (IRES .LT. 0) RETURN\n        ENDIF\nC-----------------------------------------------------------------------\nC     Apply inverse of left preconditioner to vector R.\nC     First scale WT array by 1/sqrt(N), and undo scaling afterward.\nC-----------------------------------------------------------------------\n      CALL DCOPY(NEQ, SAVR, 1, R, 1)\n      CALL DSCAL (NEQ, RSQRTN, WT, 1)\n      IER = 0\n      CALL PSOL (NEQ, T, Y, YPRIME, SAVR, PWK, CJ, WT, WP, IWP,\n     *           R, EPLIN, IER, RPAR, IPAR)\n      CALL DSCAL (NEQ, SQRTN, WT, 1)\n      IF (IER .NE. 0) RETURN\nC-----------------------------------------------------------------------\nC     Calculate norm of R.\nC-----------------------------------------------------------------------\n      FNORM = DDWNRM (NEQ, R, WT, RPAR, IPAR)\nC\n      RETURN\nC----------------------- END OF SUBROUTINE DFNRMK ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dhels.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DHELS (A, LDA, N, Q, B)\nC\nC***BEGIN PROLOGUE  DHELS\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC This is similar to the LINPACK routine DGESL except that\nC A is an upper Hessenberg matrix.\nC\nC     DHELS solves the least squares problem\nC\nC           MIN (B-A*X,B-A*X)\nC\nC     using the factors computed by DHEQR.\nC\nC     On entry\nC\nC        A       DOUBLE PRECISION (LDA, N)\nC                The output from DHEQR which contains the upper\nC                triangular factor R in the QR decomposition of A.\nC\nC        LDA     INTEGER\nC                The leading dimension of the array  A .\nC\nC        N       INTEGER\nC                A is originally an (N+1) by N matrix.\nC\nC        Q       DOUBLE PRECISION(2*N)\nC                The coefficients of the N givens rotations\nC                used in the QR factorization of A.\nC\nC        B       DOUBLE PRECISION(N+1)\nC                The right hand side vector.\nC\nC\nC     On return\nC\nC        B       The solution vector X.\nC\nC\nC     Modification of LINPACK.\nC     Peter Brown, Lawrence Livermore Natl. Lab.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   DAXPY\nC\nC***END PROLOGUE  DHELS\nC\n      INTEGER LDA, N\n      DOUBLE PRECISION A(LDA,*), B(*), Q(*)\n      INTEGER IQ, K, KB, KP1\n      DOUBLE PRECISION C, S, T, T1, T2\nC\nC        Minimize (B-A*X,B-A*X).\nC        First form Q*B.\nC\n         DO 20 K = 1, N\n            KP1 = K + 1\n            IQ = 2*(K-1) + 1\n            C = Q(IQ)\n            S = Q(IQ+1)\n            T1 = B(K)\n            T2 = B(KP1)\n            B(K) = C*T1 - S*T2\n            B(KP1) = S*T1 + C*T2\n   20    CONTINUE\nC\nC        Now solve R*X = Q*B.\nC\n         DO 40 KB = 1, N\n            K = N + 1 - KB\n            B(K) = B(K)/A(K,K)\n            T = -B(K)\n            CALL DAXPY (K-1, T, A(1,K), 1, B(1), 1)\n   40    CONTINUE\n      RETURN\nC\nC------END OF SUBROUTINE DHELS------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dheqr.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DHEQR (A, LDA, N, Q, INFO, IJOB)\nC\nC***BEGIN PROLOGUE  DHEQR\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     This routine performs a QR decomposition of an upper\nC     Hessenberg matrix A.  There are two options available:\nC\nC          (1)  performing a fresh decomposition\nC          (2)  updating the QR factors by adding a row and A\nC               column to the matrix A.\nC\nC     DHEQR decomposes an upper Hessenberg matrix by using Givens\nC     rotations.\nC\nC     On entry\nC\nC        A       DOUBLE PRECISION(LDA, N)\nC                The matrix to be decomposed.\nC\nC        LDA     INTEGER\nC                The leading dimension of the array A.\nC\nC        N       INTEGER\nC                A is an (N+1) by N Hessenberg matrix.\nC\nC        IJOB    INTEGER\nC                = 1     Means that a fresh decomposition of the\nC                        matrix A is desired.\nC                .GE. 2  Means that the current decomposition of A\nC                        will be updated by the addition of a row\nC                        and a column.\nC     On return\nC\nC        A       The upper triangular matrix R.\nC                The factorization can be written Q*A = R, where\nC                Q is a product of Givens rotations and R is upper\nC                triangular.\nC\nC        Q       DOUBLE PRECISION(2*N)\nC                The factors C and S of each Givens rotation used\nC                in decomposing A.\nC\nC        INFO    INTEGER\nC                = 0  normal value.\nC                = K  If  A(K,K) .EQ. 0.0.  This is not an error\nC                     condition for this subroutine, but it does\nC                     indicate that DHELS will divide by zero\nC                     if called.\nC\nC     Modification of LINPACK.\nC     Peter Brown, Lawrence Livermore Natl. Lab.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED (NONE)\nC\nC***END PROLOGUE  DHEQR\nC\n      INTEGER LDA, N, INFO, IJOB\n      DOUBLE PRECISION A(LDA,*), Q(*)\n      INTEGER I, IQ, J, K, KM1, KP1, NM1\n      DOUBLE PRECISION C, S, T, T1, T2\nC\n      IF (IJOB .GT. 1) GO TO 70\nC-----------------------------------------------------------------------\nC A new factorization is desired.\nC-----------------------------------------------------------------------\nC\nC     QR decomposition without pivoting.\nC\n      INFO = 0\n      DO 60 K = 1, N\n         KM1 = K - 1\n         KP1 = K + 1\nC\nC           Compute Kth column of R.\nC           First, multiply the Kth column of A by the previous\nC           K-1 Givens rotations.\nC\n            IF (KM1 .LT. 1) GO TO 20\n            DO 10 J = 1, KM1\n              I = 2*(J-1) + 1\n              T1 = A(J,K)\n              T2 = A(J+1,K)\n              C = Q(I)\n              S = Q(I+1)\n              A(J,K) = C*T1 - S*T2\n              A(J+1,K) = S*T1 + C*T2\n   10         CONTINUE\nC\nC           Compute Givens components C and S.\nC\n   20       CONTINUE\n            IQ = 2*KM1 + 1\n            T1 = A(K,K)\n            T2 = A(KP1,K)\n            IF (T2 .NE. 0.0D0) GO TO 30\n              C = 1.0D0\n              S = 0.0D0\n              GO TO 50\n   30       CONTINUE\n            IF (ABS(T2) .LT. ABS(T1)) GO TO 40\n              T = T1/T2\n              S = -1.0D0/SQRT(1.0D0+T*T)\n              C = -S*T\n              GO TO 50\n   40       CONTINUE\n              T = T2/T1\n              C = 1.0D0/SQRT(1.0D0+T*T)\n              S = -C*T\n   50       CONTINUE\n            Q(IQ) = C\n            Q(IQ+1) = S\n            A(K,K) = C*T1 - S*T2\n            IF (A(K,K) .EQ. 0.0D0) INFO = K\n   60 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC The old factorization of A will be updated.  A row and a column\nC has been added to the matrix A.\nC N by N-1 is now the old size of the matrix.\nC-----------------------------------------------------------------------\n  70  CONTINUE\n      NM1 = N - 1\nC-----------------------------------------------------------------------\nC Multiply the new column by the N previous Givens rotations.\nC-----------------------------------------------------------------------\n      DO 100 K = 1,NM1\n        I = 2*(K-1) + 1\n        T1 = A(K,N)\n        T2 = A(K+1,N)\n        C = Q(I)\n        S = Q(I+1)\n        A(K,N) = C*T1 - S*T2\n        A(K+1,N) = S*T1 + C*T2\n 100    CONTINUE\nC-----------------------------------------------------------------------\nC Complete update of decomposition by forming last Givens rotation,\nC and multiplying it times the column vector (A(N,N),A(NP1,N)).\nC-----------------------------------------------------------------------\n      INFO = 0\n      T1 = A(N,N)\n      T2 = A(N+1,N)\n      IF (T2 .NE. 0.0D0) GO TO 110\n        C = 1.0D0\n        S = 0.0D0\n        GO TO 130\n 110  CONTINUE\n      IF (ABS(T2) .LT. ABS(T1)) GO TO 120\n        T = T1/T2\n        S = -1.0D0/SQRT(1.0D0+T*T)\n        C = -S*T\n        GO TO 130\n 120  CONTINUE\n        T = T2/T1\n        C = 1.0D0/SQRT(1.0D0+T*T)\n        S = -C*T\n 130  CONTINUE\n      IQ = 2*N - 1\n      Q(IQ) = C\n      Q(IQ+1) = S\n      A(N,N) = C*T1 - S*T2\n      IF (A(N,N) .EQ. 0.0D0) INFO = N\n      RETURN\nC\nC------END OF SUBROUTINE DHEQR------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dinvwt.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DINVWT(NEQ,WT,IER)\nC\nC***BEGIN PROLOGUE  DINVWT\nC***REFER TO  DDASPK\nC***ROUTINES CALLED  (NONE)\nC***DATE WRITTEN   950125   (YYMMDD)\nC***END PROLOGUE  DINVWT\nC-----------------------------------------------------------------------\nC     This subroutine checks the error weight vector WT, of length NEQ,\nC     for components that are .le. 0, and if none are found, it\nC     inverts the WT(I) in place.  This replaces division operations\nC     with multiplications in all norm evaluations.\nC     IER is returned as 0 if all WT(I) were found positive,\nC     and the first I with WT(I) .le. 0.0 otherwise.\nC-----------------------------------------------------------------------\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION WT(*)\nC\n      DO 10 I = 1,NEQ\n        IF (WT(I) .LE. 0.0D0) GO TO 30\n 10     CONTINUE\n      DO 20 I = 1,NEQ\n 20     WT(I) = 1.0D0/WT(I)\n      IER = 0\n      RETURN\nC\n 30   IER = I\n      RETURN\nC\nC------END OF SUBROUTINE DINVWT-----------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dlinsd.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DLINSD (NEQ, Y, T, YPRIME, CJ, P, PNRM, WT, LSOFF,\n     *                   STPTOL, IRET, RES, IRES, WM, IWM,\n     *                   FNRM, ICOPT, ID, R, YNEW, YPNEW, ICNFLG,\n     *                   ICNSTR, RLX, RPAR, IPAR)\nC\nC***BEGIN PROLOGUE  DLINSD\nC***REFER TO  DNSID\nC***DATE WRITTEN   941025   (YYMMDD)\nC***REVISION DATE  941215   (YYMMDD)\nC***REVISION DATE  960129   Moved line RL = ONE to top block.\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DLINSD uses a linesearch algorithm to calculate a new (Y,YPRIME)\nC     pair (YNEW,YPNEW) such that\nC\nC     f(YNEW,YPNEW) .le. (1 - 2*ALPHA*RL)*f(Y,YPRIME) ,\nC\nC     where 0 < RL <= 1.  Here, f(y,y') is defined as\nC\nC      f(y,y') = (1/2)*norm( (J-inverse)*G(t,y,y') )**2 ,\nC\nC     where norm() is the weighted RMS vector norm, G is the DAE\nC     system residual function, and J is the system iteration matrix\nC     (Jacobian).\nC\nC     In addition to the parameters defined elsewhere, we have\nC\nC     P       -- Approximate Newton step used in backtracking.\nC     PNRM    -- Weighted RMS norm of P.\nC     LSOFF   -- Flag showing whether the linesearch algorithm is\nC                to be invoked.  0 means do the linesearch, and\nC                1 means turn off linesearch.\nC     STPTOL  -- Tolerance used in calculating the minimum lambda\nC                value allowed.\nC     ICNFLG  -- Integer scalar.  If nonzero, then constraint violations\nC                in the proposed new approximate solution will be\nC                checked for, and the maximum step length will be\nC                adjusted accordingly.\nC     ICNSTR  -- Integer array of length NEQ containing flags for\nC                checking constraints.\nC     RLX     -- Real scalar restricting update size in DCNSTR.\nC     YNEW    -- Array of length NEQ used to hold the new Y in\nC                performing the linesearch.\nC     YPNEW   -- Array of length NEQ used to hold the new YPRIME in\nC                performing the linesearch.\nC     Y       -- Array of length NEQ containing the new Y (i.e.,=YNEW).\nC     YPRIME  -- Array of length NEQ containing the new YPRIME\nC                (i.e.,=YPNEW).\nC     FNRM    -- Real scalar containing SQRT(2*f(Y,YPRIME)) for the\nC                current (Y,YPRIME) on input and output.\nC     R       -- Work array of length NEQ, containing the scaled\nC                residual (J-inverse)*G(t,y,y') on return.\nC     IRET    -- Return flag.\nC                IRET=0 means that a satisfactory (Y,YPRIME) was found.\nC                IRET=1 means that the routine failed to find a new\nC                       (Y,YPRIME) that was sufficiently distinct from\nC                       the current (Y,YPRIME) pair.\nC                IRET=2 means IRES .ne. 0 from RES.\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   DFNRMD, DYYPNW, DCOPY\nC\nC***END PROLOGUE  DLINSD\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      EXTERNAL  RES\n      DIMENSION Y(*), YPRIME(*), WT(*), R(*), ID(*)\n      DIMENSION WM(*), IWM(*)\n      DIMENSION YNEW(*), YPNEW(*), P(*), ICNSTR(*)\n      DIMENSION RPAR(*), IPAR(*)\n      CHARACTER MSG*80\nC\n      PARAMETER (LNRE=12, LKPRIN=31)\nC\n      SAVE ALPHA, ONE, TWO\n      DATA ALPHA/1.0D-4/, ONE/1.0D0/, TWO/2.0D0/\nC\n      KPRIN=IWM(LKPRIN)\nC\n      F1NRM = (FNRM*FNRM)/TWO\n      RATIO = ONE\n      IF (KPRIN .GE. 2) THEN\n        MSG = '------ IN ROUTINE DLINSD-- PNRM = (R1) )'\n        CALL XERRWD(MSG, 40, 901, 0, 0, 0, 0, 1, PNRM, 0.0D0)\n        ENDIF\n      TAU = PNRM\n      IVIO = 0\n      RL = ONE\nC-----------------------------------------------------------------------\nC Check for violations of the constraints, if any are imposed.\nC If any violations are found, the step vector P is rescaled, and the\nC constraint check is repeated, until no violations are found.\nC-----------------------------------------------------------------------\n      IF (ICNFLG .NE. 0) THEN\n 10      CONTINUE\n         CALL DYYPNW (NEQ,Y,YPRIME,CJ,RL,P,ICOPT,ID,YNEW,YPNEW)\n         CALL DCNSTR (NEQ, Y, YNEW, ICNSTR, TAU, RLX, IRET, IVAR)\n         IF (IRET .EQ. 1) THEN\n            IVIO = 1\n            RATIO1 = TAU/PNRM\n            RATIO = RATIO*RATIO1\n            DO 20 I = 1,NEQ\n 20           P(I) = P(I)*RATIO1\n            PNRM = TAU\n            IF (KPRIN .GE. 2) THEN\n              MSG = '------ CONSTRAINT VIOL., PNRM = (R1), INDEX = (I1)'\n              CALL XERRWD(MSG, 50, 902, 0, 1, IVAR, 0, 1, PNRM, 0.0D0)\n              ENDIF\n            IF (PNRM .LE. STPTOL) THEN\n              IRET = 1\n              RETURN\n              ENDIF\n            GO TO 10\n            ENDIF\n         ENDIF\nC\n      SLPI = (-TWO*F1NRM)*RATIO\n      RLMIN = STPTOL/PNRM\n      IF (LSOFF .EQ. 0 .AND. KPRIN .GE. 2) THEN\n        MSG = '------ MIN. LAMBDA = (R1)'\n        CALL XERRWD(MSG, 25, 903, 0, 0, 0, 0, 1, RLMIN, 0.0D0)\n        ENDIF\nC-----------------------------------------------------------------------\nC Begin iteration to find RL value satisfying alpha-condition.\nC If RL becomes less than RLMIN, then terminate with IRET = 1.\nC-----------------------------------------------------------------------\n 100  CONTINUE\n      CALL DYYPNW (NEQ,Y,YPRIME,CJ,RL,P,ICOPT,ID,YNEW,YPNEW)\n      CALL DFNRMD (NEQ, YNEW, T, YPNEW, R, CJ, WT, RES, IRES,\n     *              FNRMP, WM, IWM, RPAR, IPAR)\n      IWM(LNRE) = IWM(LNRE) + 1\n      IF (IRES .NE. 0) THEN\n        IRET = 2\n        RETURN\n        ENDIF\n      IF (LSOFF .EQ. 1) GO TO 150\nC\n      F1NRMP = FNRMP*FNRMP/TWO\n      IF (KPRIN .GE. 2) THEN\n        MSG = '------ LAMBDA = (R1)'\n        CALL XERRWD(MSG, 20, 904, 0, 0, 0, 0, 1, RL, 0.0D0)\n        MSG = '------ NORM(F1) = (R1),  NORM(F1NEW) = (R2)'\n        CALL XERRWD(MSG, 43, 905, 0, 0, 0, 0, 2, F1NRM, F1NRMP)\n        ENDIF\n      IF (F1NRMP .GT. F1NRM + ALPHA*SLPI*RL) GO TO 200\nC-----------------------------------------------------------------------\nC Alpha-condition is satisfied, or linesearch is turned off.\nC Copy YNEW,YPNEW to Y,YPRIME and return.\nC-----------------------------------------------------------------------\n 150  IRET = 0\n      CALL DCOPY (NEQ, YNEW, 1, Y, 1)\n      CALL DCOPY (NEQ, YPNEW, 1, YPRIME, 1)\n      FNRM = FNRMP\n      IF (KPRIN .GE. 1) THEN\n        MSG = '------ LEAVING ROUTINE DLINSD, FNRM = (R1)'\n        CALL XERRWD(MSG, 42, 906, 0, 0, 0, 0, 1, FNRM, 0.0D0)\n        ENDIF\n      RETURN\nC-----------------------------------------------------------------------\nC Alpha-condition not satisfied.  Perform backtrack to compute new RL\nC value.  If no satisfactory YNEW,YPNEW can be found sufficiently\nC distinct from Y,YPRIME, then return IRET = 1.\nC-----------------------------------------------------------------------\n 200  CONTINUE\n      IF (RL .LT. RLMIN) THEN\n        IRET = 1\n        RETURN\n        ENDIF\nC\n      RL = RL/TWO\n      GO TO 100\nC\nC----------------------- END OF SUBROUTINE DLINSD ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dlinsk.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DLINSK (NEQ, Y, T, YPRIME, SAVR, CJ, P, PNRM, WT,\n     *   SQRTN, RSQRTN, LSOFF, STPTOL, IRET, RES, IRES, PSOL, WM, IWM,\n     *   RHOK, FNRM, ICOPT, ID, WP, IWP, R, EPLIN, YNEW, YPNEW, PWK,\n     *   ICNFLG, ICNSTR, RLX, RPAR, IPAR)\nC\nC***BEGIN PROLOGUE  DLINSK\nC***REFER TO  DNSIK\nC***DATE WRITTEN   940830   (YYMMDD)\nC***REVISION DATE  951006   (Arguments SQRTN, RSQRTN added.)\nC***REVISION DATE  960129   Moved line RL = ONE to top block.\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DLINSK uses a linesearch algorithm to calculate a new (Y,YPRIME)\nC     pair (YNEW,YPNEW) such that\nC\nC     f(YNEW,YPNEW) .le. (1 - 2*ALPHA*RL)*f(Y,YPRIME) +\nC                          ALPHA*RL*RHOK*RHOK ,\nC\nC     where 0 < RL <= 1, and RHOK is the scaled preconditioned norm of\nC     the final residual vector in the Krylov iteration.\nC     Here, f(y,y') is defined as\nC\nC      f(y,y') = (1/2)*norm( (P-inverse)*G(t,y,y') )**2 ,\nC\nC     where norm() is the weighted RMS vector norm, G is the DAE\nC     system residual function, and P is the preconditioner used\nC     in the Krylov iteration.\nC\nC     In addition to the parameters defined elsewhere, we have\nC\nC     SAVR    -- Work array of length NEQ, containing the residual\nC                vector G(t,y,y') on return.\nC     P       -- Approximate Newton step used in backtracking.\nC     PNRM    -- Weighted RMS norm of P.\nC     LSOFF   -- Flag showing whether the linesearch algorithm is\nC                to be invoked.  0 means do the linesearch,\nC                1 means turn off linesearch.\nC     STPTOL  -- Tolerance used in calculating the minimum lambda\nC                value allowed.\nC     ICNFLG  -- Integer scalar.  If nonzero, then constraint violations\nC                in the proposed new approximate solution will be\nC                checked for, and the maximum step length will be\nC                adjusted accordingly.\nC     ICNSTR  -- Integer array of length NEQ containing flags for\nC                checking constraints.\nC     RHOK    -- Weighted norm of preconditioned Krylov residual.\nC     RLX     -- Real scalar restricting update size in DCNSTR.\nC     YNEW    -- Array of length NEQ used to hold the new Y in\nC                performing the linesearch.\nC     YPNEW   -- Array of length NEQ used to hold the new YPRIME in\nC                performing the linesearch.\nC     PWK     -- Work vector of length NEQ for use in PSOL.\nC     Y       -- Array of length NEQ containing the new Y (i.e.,=YNEW).\nC     YPRIME  -- Array of length NEQ containing the new YPRIME\nC                (i.e.,=YPNEW).\nC     FNRM    -- Real scalar containing SQRT(2*f(Y,YPRIME)) for the\nC                current (Y,YPRIME) on input and output.\nC     R       -- Work space length NEQ for residual vector.\nC     IRET    -- Return flag.\nC                IRET=0 means that a satisfactory (Y,YPRIME) was found.\nC                IRET=1 means that the routine failed to find a new\nC                       (Y,YPRIME) that was sufficiently distinct from\nC                       the current (Y,YPRIME) pair.\nC                IRET=2 means a failure in RES or PSOL.\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   DFNRMK, DYYPNW, DCOPY\nC\nC***END PROLOGUE  DLINSK\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      EXTERNAL  RES, PSOL\n      DIMENSION Y(*), YPRIME(*), P(*), WT(*), SAVR(*), R(*), ID(*)\n      DIMENSION WM(*), IWM(*), YNEW(*), YPNEW(*), PWK(*), ICNSTR(*)\n      DIMENSION WP(*), IWP(*), RPAR(*), IPAR(*)\n      CHARACTER MSG*80\nC\n      PARAMETER (LNRE=12, LNPS=21, LKPRIN=31)\nC\n      SAVE ALPHA, ONE, TWO\n      DATA ALPHA/1.0D-4/, ONE/1.0D0/, TWO/2.0D0/\nC\n      KPRIN=IWM(LKPRIN)\n      F1NRM = (FNRM*FNRM)/TWO\n      RATIO = ONE\nC\n      IF (KPRIN .GE. 2) THEN\n        MSG = '------ IN ROUTINE DLINSK-- PNRM = (R1) )'\n        CALL XERRWD(MSG, 40, 921, 0, 0, 0, 0, 1, PNRM, 0.0D0)\n        ENDIF\n      TAU = PNRM\n      IVIO = 0\n      RL = ONE\nC-----------------------------------------------------------------------\nC Check for violations of the constraints, if any are imposed.\nC If any violations are found, the step vector P is rescaled, and the\nC constraint check is repeated, until no violations are found.\nC-----------------------------------------------------------------------\n      IF (ICNFLG .NE. 0) THEN\n 10      CONTINUE\n         CALL DYYPNW (NEQ,Y,YPRIME,CJ,RL,P,ICOPT,ID,YNEW,YPNEW)\n         CALL DCNSTR (NEQ, Y, YNEW, ICNSTR, TAU, RLX, IRET, IVAR)\n         IF (IRET .EQ. 1) THEN\n            IVIO = 1\n            RATIO1 = TAU/PNRM\n            RATIO = RATIO*RATIO1\n            DO 20 I = 1,NEQ\n 20           P(I) = P(I)*RATIO1\n            PNRM = TAU\n            IF (KPRIN .GE. 2) THEN\n              MSG = '------ CONSTRAINT VIOL., PNRM = (R1), INDEX = (I1)'\n              CALL XERRWD(MSG, 50, 922, 0, 1, IVAR, 0, 1, PNRM, 0.0D0)\n              ENDIF\n            IF (PNRM .LE. STPTOL) THEN\n              IRET = 1\n              RETURN\n              ENDIF\n            GO TO 10\n            ENDIF\n         ENDIF\nC\n      SLPI = (-TWO*F1NRM + RHOK*RHOK)*RATIO\n      RLMIN = STPTOL/PNRM\n      IF (LSOFF .EQ. 0 .AND. KPRIN .GE. 2) THEN\n        MSG = '------ MIN. LAMBDA = (R1)'\n        CALL XERRWD(MSG, 25, 923, 0, 0, 0, 0, 1, RLMIN, 0.0D0)\n        ENDIF\nC-----------------------------------------------------------------------\nC Begin iteration to find RL value satisfying alpha-condition.\nC Update YNEW and YPNEW, then compute norm of new scaled residual and\nC perform alpha condition test.\nC-----------------------------------------------------------------------\n 100  CONTINUE\n      CALL DYYPNW (NEQ,Y,YPRIME,CJ,RL,P,ICOPT,ID,YNEW,YPNEW)\n      CALL DFNRMK (NEQ, YNEW, T, YPNEW, SAVR, R, CJ, WT, SQRTN, RSQRTN,\n     *  RES, IRES, PSOL, 0, IER, FNRMP, EPLIN, WP, IWP, PWK, RPAR, IPAR)\n      IWM(LNRE) = IWM(LNRE) + 1\n      IF (IRES .GE. 0) IWM(LNPS) = IWM(LNPS) + 1\n      IF (IRES .NE. 0 .OR. IER .NE. 0) THEN\n        IRET = 2\n        RETURN\n        ENDIF\n      IF (LSOFF .EQ. 1) GO TO 150\nC\n      F1NRMP = FNRMP*FNRMP/TWO\n      IF (KPRIN .GE. 2) THEN\n        MSG = '------ LAMBDA = (R1)'\n        CALL XERRWD(MSG, 20, 924, 0, 0, 0, 0, 1, RL, 0.0D0)\n        MSG = '------ NORM(F1) = (R1),  NORM(F1NEW) = (R2)'\n        CALL XERRWD(MSG, 43, 925, 0, 0, 0, 0, 2, F1NRM, F1NRMP)\n        ENDIF\n      IF (F1NRMP .GT. F1NRM + ALPHA*SLPI*RL) GO TO 200\nC-----------------------------------------------------------------------\nC Alpha-condition is satisfied, or linesearch is turned off.\nC Copy YNEW,YPNEW to Y,YPRIME and return.\nC-----------------------------------------------------------------------\n 150  IRET = 0\n      CALL DCOPY(NEQ, YNEW, 1, Y, 1)\n      CALL DCOPY(NEQ, YPNEW, 1, YPRIME, 1)\n      FNRM = FNRMP\n      IF (KPRIN .GE. 1) THEN\n        MSG = '------ LEAVING ROUTINE DLINSK, FNRM = (R1)'\n        CALL XERRWD(MSG, 42, 926, 0, 0, 0, 0, 1, FNRM, 0.0D0)\n        ENDIF\n      RETURN\nC-----------------------------------------------------------------------\nC Alpha-condition not satisfied.  Perform backtrack to compute new RL\nC value.  If RL is less than RLMIN, i.e. no satisfactory YNEW,YPNEW can\nC be found sufficiently distinct from Y,YPRIME, then return IRET = 1.\nC-----------------------------------------------------------------------\n 200  CONTINUE\n      IF (RL .LT. RLMIN) THEN\n        IRET = 1\n        RETURN\n        ENDIF\nC\n      RL = RL/TWO\n      GO TO 100\nC\nC----------------------- END OF SUBROUTINE DLINSK ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dmatd.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DMATD(NEQ,X,Y,YPRIME,DELTA,CJ,H,IER,EWT,E,\n     *                 WM,IWM,RES,IRES,UROUND,JACD,RPAR,IPAR)\nC\nC***BEGIN PROLOGUE  DMATD\nC***REFER TO  DDASPK\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***REVISION DATE  940701   (YYMMDD) (new LIPVT)\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     This routine computes the iteration matrix\nC     J = dG/dY+CJ*dG/dYPRIME (where G(X,Y,YPRIME)=0).\nC     Here J is computed by:\nC       the user-supplied routine JACD if IWM(MTYPE) is 1 or 4, or\nC       by numerical difference quotients if IWM(MTYPE) is 2 or 5.\nC\nC     The parameters have the following meanings.\nC     X        = Independent variable.\nC     Y        = Array containing predicted values.\nC     YPRIME   = Array containing predicted derivatives.\nC     DELTA    = Residual evaluated at (X,Y,YPRIME).\nC                (Used only if IWM(MTYPE)=2 or 5).\nC     CJ       = Scalar parameter defining iteration matrix.\nC     H        = Current stepsize in integration.\nC     IER      = Variable which is .NE. 0 if iteration matrix\nC                is singular, and 0 otherwise.\nC     EWT      = Vector of error weights for computing norms.\nC     E        = Work space (temporary) of length NEQ.\nC     WM       = Real work space for matrices.  On output\nC                it contains the LU decomposition\nC                of the iteration matrix.\nC     IWM      = Integer work space containing\nC                matrix information.\nC     RES      = External user-supplied subroutine\nC                to evaluate the residual.  See RES description\nC                in DDASPK prologue.\nC     IRES     = Flag which is equal to zero if no illegal values\nC                in RES, and less than zero otherwise.  (If IRES\nC                is less than zero, the matrix was not completed).\nC                In this case (if IRES .LT. 0), then IER = 0.\nC     UROUND   = The unit roundoff error of the machine being used.\nC     JACD     = Name of the external user-supplied routine\nC                to evaluate the iteration matrix.  (This routine\nC                is only used if IWM(MTYPE) is 1 or 4)\nC                See JAC description for the case INFO(12) = 0\nC                in DDASPK prologue.\nC     RPAR,IPAR= Real and integer parameter arrays that\nC                are used for communication between the\nC                calling program and external user routines.\nC                They are not altered by DMATD.\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   JACD, RES, DGETRF, DGBTRF\nC\nC***END PROLOGUE  DMATD\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),DELTA(*),EWT(*),E(*)\n      DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)\n      EXTERNAL  RES, JACD\nC\n      PARAMETER (LML=1, LMU=2, LMTYPE=4, LNRE=12, LNPD=22, LLCIWP=30)\nC\n      LIPVT = IWM(LLCIWP)\n      IER = 0\n      MTYPE=IWM(LMTYPE)\n      GO TO (100,200,300,400,500),MTYPE\nC\nC\nC     Dense user-supplied matrix.\nC\n100   LENPD=IWM(LNPD)\n      DO 110 I=1,LENPD\n110      WM(I)=0.0D0\n      CALL JACD(X,Y,YPRIME,WM,CJ,RPAR,IPAR)\n      GO TO 230\nC\nC\nC     Dense finite-difference-generated matrix.\nC\n200   IRES=0\n      NROW=0\n      SQUR = SQRT(UROUND)\n      DO 210 I=1,NEQ\n         DEL=SQUR*MAX(ABS(Y(I)),ABS(H*YPRIME(I)),\n     *     ABS(1.D0/EWT(I)))\n         DEL=SIGN(DEL,H*YPRIME(I))\n         DEL=(Y(I)+DEL)-Y(I)\n         YSAVE=Y(I)\n         YPSAVE=YPRIME(I)\n         Y(I)=Y(I)+DEL\n         YPRIME(I)=YPRIME(I)+CJ*DEL\n         IWM(LNRE)=IWM(LNRE)+1\n         CALL RES(X,Y,YPRIME,CJ,E,IRES,RPAR,IPAR)\n         IF (IRES .LT. 0) RETURN\n         DELINV=1.0D0/DEL\n         DO 220 L=1,NEQ\n220        WM(NROW+L)=(E(L)-DELTA(L))*DELINV\n      NROW=NROW+NEQ\n      Y(I)=YSAVE\n      YPRIME(I)=YPSAVE\n210   CONTINUE\nC\nC\nC     Do dense-matrix LU decomposition on J.\nC\n230      CALL DGETRF( NEQ, NEQ, WM, NEQ, IWM(LIPVT), IER)\n      RETURN\nC\nC\nC     Dummy section for IWM(MTYPE)=3.\nC\n300   RETURN\nC\nC\nC     Banded user-supplied matrix.\nC\n400   LENPD=IWM(LNPD)\n      DO 410 I=1,LENPD\n410      WM(I)=0.0D0\n      CALL JACD(X,Y,YPRIME,WM,CJ,RPAR,IPAR)\n      MEBAND=2*IWM(LML)+IWM(LMU)+1\n      GO TO 550\nC\nC\nC     Banded finite-difference-generated matrix.\nC\n500   MBAND=IWM(LML)+IWM(LMU)+1\n      MBA=MIN0(MBAND,NEQ)\n      MEBAND=MBAND+IWM(LML)\n      MEB1=MEBAND-1\n      MSAVE=(NEQ/MBAND)+1\n      ISAVE=IWM(LNPD)\n      IPSAVE=ISAVE+MSAVE\n      IRES=0\n      SQUR=SQRT(UROUND)\n      DO 540 J=1,MBA\n        DO 510 N=J,NEQ,MBAND\n          K= (N-J)/MBAND + 1\n          WM(ISAVE+K)=Y(N)\n          WM(IPSAVE+K)=YPRIME(N)\n          DEL=SQUR*MAX(ABS(Y(N)),ABS(H*YPRIME(N)),\n     *      ABS(1.D0/EWT(N)))\n          DEL=SIGN(DEL,H*YPRIME(N))\n          DEL=(Y(N)+DEL)-Y(N)\n          Y(N)=Y(N)+DEL\n510       YPRIME(N)=YPRIME(N)+CJ*DEL\n        IWM(LNRE)=IWM(LNRE)+1\n        CALL RES(X,Y,YPRIME,CJ,E,IRES,RPAR,IPAR)\n        IF (IRES .LT. 0) RETURN\n        DO 530 N=J,NEQ,MBAND\n          K= (N-J)/MBAND + 1\n          Y(N)=WM(ISAVE+K)\n          YPRIME(N)=WM(IPSAVE+K)\n          DEL=SQUR*MAX(ABS(Y(N)),ABS(H*YPRIME(N)),\n     *      ABS(1.D0/EWT(N)))\n          DEL=SIGN(DEL,H*YPRIME(N))\n          DEL=(Y(N)+DEL)-Y(N)\n          DELINV=1.0D0/DEL\n          I1=MAX0(1,(N-IWM(LMU)))\n          I2=MIN0(NEQ,(N+IWM(LML)))\n          II=N*MEB1-IWM(LML)\n          DO 520 I=I1,I2\n520         WM(II+I)=(E(I)-DELTA(I))*DELINV\n530     CONTINUE\n540   CONTINUE\nC\nC\nC     Do LU decomposition of banded J.\nC\n550   CALL DGBTRF(NEQ, NEQ, IWM(LML), IWM(LMU), WM, MEBAND,\n     *     IWM(LIPVT), IER)\n      RETURN\nC\nC------END OF SUBROUTINE DMATD------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dnedd.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DNEDD(X,Y,YPRIME,NEQ,RES,JACD,PDUM,H,WT,\n     *   JSTART,IDID,RPAR,IPAR,PHI,GAMMA,DUMSVR,DELTA,E,\n     *   WM,IWM,CJ,CJOLD,CJLAST,S,UROUND,DUME,DUMS,DUMR,\n     *   EPCON,JCALC,JFDUM,KP1,NONNEG,NTYPE,IERNLS)\nC\nC***BEGIN PROLOGUE  DNEDD\nC***REFER TO  DDASPK\nC***DATE WRITTEN   891219   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DNEDD solves a nonlinear system of\nC     algebraic equations of the form\nC     G(X,Y,YPRIME) = 0 for the unknown Y.\nC\nC     The method used is a modified Newton scheme.\nC\nC     The parameters represent\nC\nC     X         -- Independent variable.\nC     Y         -- Solution vector.\nC     YPRIME    -- Derivative of solution vector.\nC     NEQ       -- Number of unknowns.\nC     RES       -- External user-supplied subroutine\nC                  to evaluate the residual.  See RES description\nC                  in DDASPK prologue.\nC     JACD      -- External user-supplied routine to evaluate the\nC                  Jacobian.  See JAC description for the case\nC                  INFO(12) = 0 in the DDASPK prologue.\nC     PDUM      -- Dummy argument.\nC     H         -- Appropriate step size for next step.\nC     WT        -- Vector of weights for error criterion.\nC     JSTART    -- Indicates first call to this routine.\nC                  If JSTART = 0, then this is the first call,\nC                  otherwise it is not.\nC     IDID      -- Completion flag, output by DNEDD.\nC                  See IDID description in DDASPK prologue.\nC     RPAR,IPAR -- Real and integer arrays used for communication\nC                  between the calling program and external user\nC                  routines.  They are not altered within DASPK.\nC     PHI       -- Array of divided differences used by\nC                  DNEDD.  The length is NEQ*(K+1),where\nC                  K is the maximum order.\nC     GAMMA     -- Array used to predict Y and YPRIME.  The length\nC                  is MAXORD+1 where MAXORD is the maximum order.\nC     DUMSVR    -- Dummy argument.\nC     DELTA     -- Work vector for NLS of length NEQ.\nC     E         -- Error accumulation vector for NLS of length NEQ.\nC     WM,IWM    -- Real and integer arrays storing\nC                  matrix information such as the matrix\nC                  of partial derivatives, permutation\nC                  vector, and various other information.\nC     CJ        -- Parameter always proportional to 1/H.\nC     CJOLD     -- Saves the value of CJ as of the last call to DMATD.\nC                  Accounts for changes in CJ needed to\nC                  decide whether to call DMATD.\nC     CJLAST    -- Previous value of CJ.\nC     S         -- A scalar determined by the approximate rate\nC                  of convergence of the Newton iteration and used\nC                  in the convergence test for the Newton iteration.\nC\nC                  If RATE is defined to be an estimate of the\nC                  rate of convergence of the Newton iteration,\nC                  then S = RATE/(1.D0-RATE).\nC\nC                  The closer RATE is to 0., the faster the Newton\nC                  iteration is converging; the closer RATE is to 1.,\nC                  the slower the Newton iteration is converging.\nC\nC                  On the first Newton iteration with an up-dated\nC                  preconditioner S = 100.D0, Thus the initial\nC                  RATE of convergence is approximately 1.\nC\nC                  S is preserved from call to call so that the rate\nC                  estimate from a previous step can be applied to\nC                  the current step.\nC     UROUND    -- Unit roundoff.\nC     DUME      -- Dummy argument.\nC     DUMS      -- Dummy argument.\nC     DUMR      -- Dummy argument.\nC     EPCON     -- Tolerance to test for convergence of the Newton\nC                  iteration.\nC     JCALC     -- Flag used to determine when to update\nC                  the Jacobian matrix.  In general:\nC\nC                  JCALC = -1 ==> Call the DMATD routine to update\nC                                 the Jacobian matrix.\nC                  JCALC =  0 ==> Jacobian matrix is up-to-date.\nC                  JCALC =  1 ==> Jacobian matrix is out-dated,\nC                                 but DMATD will not be called unless\nC                                 JCALC is set to -1.\nC     JFDUM     -- Dummy argument.\nC     KP1       -- The current order(K) + 1;  updated across calls.\nC     NONNEG    -- Flag to determine nonnegativity constraints.\nC     NTYPE     -- Identification code for the NLS routine.\nC                   0  ==> modified Newton; direct solver.\nC     IERNLS    -- Error flag for nonlinear solver.\nC                   0  ==> nonlinear solver converged.\nC                   1  ==> recoverable error inside nonlinear solver.\nC                  -1  ==> unrecoverable error inside nonlinear solver.\nC\nC     All variables with \"DUM\" in their names are dummy variables\nC     which are not used in this routine.\nC\nC     Following is a list and description of local variables which\nC     may not have an obvious usage.  They are listed in roughly the\nC     order they occur in this subroutine.\nC\nC     The following group of variables are passed as arguments to\nC     the Newton iteration solver.  They are explained in greater detail\nC     in DNSD:\nC        TOLNEW, MULDEL, MAXIT, IERNEW\nC\nC     IERTYP -- Flag which tells whether this subroutine is correct.\nC               0 ==> correct subroutine.\nC               1 ==> incorrect subroutine.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   DDWNRM, RES, DMATD, DNSD\nC\nC***END PROLOGUE  DNEDD\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),WT(*)\n      DIMENSION DELTA(*),E(*)\n      DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)\n      DIMENSION PHI(NEQ,*),GAMMA(*)\n      EXTERNAL  RES, JACD\nC\n      PARAMETER (LNRE=12, LNJE=13)\nC\n      SAVE MULDEL, MAXIT, XRATE\n      DATA MULDEL/1/, MAXIT/4/, XRATE/0.25D0/\nC\nC     Verify that this is the correct subroutine.\nC\n      IERTYP = 0\n      IF (NTYPE .NE. 0) THEN\n         IERTYP = 1\n         GO TO 380\n         ENDIF\nC\nC     If this is the first step, perform initializations.\nC\n      IF (JSTART .EQ. 0) THEN\n         CJOLD = CJ\n         JCALC = -1\n         ENDIF\nC\nC     Perform all other initializations.\nC\n      IERNLS = 0\nC\nC     Decide whether new Jacobian is needed.\nC\n      TEMP1 = (1.0D0 - XRATE)/(1.0D0 + XRATE)\n      TEMP2 = 1.0D0/TEMP1\n      IF (CJ/CJOLD .LT. TEMP1 .OR. CJ/CJOLD .GT. TEMP2) JCALC = -1\n      IF (CJ .NE. CJLAST) S = 100.D0\nC\nC-----------------------------------------------------------------------\nC     Entry point for updating the Jacobian with current\nC     stepsize.\nC-----------------------------------------------------------------------\n300   CONTINUE\nC\nC     Initialize all error flags to zero.\nC\n      IERJ = 0\n      IRES = 0\n      IERNEW = 0\nC\nC     Predict the solution and derivative and compute the tolerance\nC     for the Newton iteration.\nC\n      DO 310 I=1,NEQ\n         Y(I)=PHI(I,1)\n310      YPRIME(I)=0.0D0\n      DO 330 J=2,KP1\n         DO 320 I=1,NEQ\n            Y(I)=Y(I)+PHI(I,J)\n320         YPRIME(I)=YPRIME(I)+GAMMA(J)*PHI(I,J)\n330   CONTINUE\n      PNORM = DDWNRM (NEQ,Y,WT,RPAR,IPAR)\n      TOLNEW = 100.D0*UROUND*PNORM\nC\nC     Call RES to initialize DELTA.\nC\n      IWM(LNRE)=IWM(LNRE)+1\n      CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)\n      IF (IRES .LT. 0) GO TO 380\nC\nC     If indicated, reevaluate the iteration matrix\nC     J = dG/dY + CJ*dG/dYPRIME (where G(X,Y,YPRIME)=0).\nC     Set JCALC to 0 as an indicator that this has been done.\nC\n      IF(JCALC .EQ. -1) THEN\n         IWM(LNJE)=IWM(LNJE)+1\n         JCALC=0\n         CALL DMATD(NEQ,X,Y,YPRIME,DELTA,CJ,H,IERJ,WT,E,WM,IWM,\n     *              RES,IRES,UROUND,JACD,RPAR,IPAR)\n         CJOLD=CJ\n         S = 100.D0\n         IF (IRES .LT. 0) GO TO 380\n         IF(IERJ .NE. 0)GO TO 380\n      ENDIF\nC\nC     Call the nonlinear Newton solver.\nC\n      TEMP1 = 2.0D0/(1.0D0 + CJ/CJOLD)\n      CALL DNSD(X,Y,YPRIME,NEQ,RES,PDUM,WT,RPAR,IPAR,DUMSVR,\n     *          DELTA,E,WM,IWM,CJ,DUMS,DUMR,DUME,EPCON,S,TEMP1,\n     *          TOLNEW,MULDEL,MAXIT,IRES,IDUM,IERNEW)\nC\n      IF (IERNEW .GT. 0 .AND. JCALC .NE. 0) THEN\nC\nC        The Newton iteration had a recoverable failure with an old\nC        iteration matrix.  Retry the step with a new iteration matrix.\nC\n         JCALC = -1\n         GO TO 300\n      ENDIF\nC\n      IF (IERNEW .NE. 0) GO TO 380\nC\nC     The Newton iteration has converged.  If nonnegativity of\nC     solution is required, set the solution nonnegative, if the\nC     perturbation to do it is small enough.  If the change is too\nC     large, then consider the corrector iteration to have failed.\nC\n375   IF(NONNEG .EQ. 0) GO TO 390\n      DO 377 I = 1,NEQ\n377      DELTA(I) = MIN(Y(I),0.0D0)\n      DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)\n      IF(DELNRM .GT. EPCON) GO TO 380\n      DO 378 I = 1,NEQ\n378      E(I) = E(I) - DELTA(I)\n      GO TO 390\nC\nC\nC     Exits from nonlinear solver.\nC     No convergence with current iteration\nC     matrix, or singular iteration matrix.\nC     Compute IERNLS and IDID accordingly.\nC\n380   CONTINUE\n      IF (IRES .LE. -2 .OR. IERTYP .NE. 0) THEN\n         IERNLS = -1\n         IF (IRES .LE. -2) IDID = -11\n         IF (IERTYP .NE. 0) IDID = -15\n      ELSE\n         IERNLS = 1\n         IF (IRES .LT. 0) IDID = -10\n         IF (IERJ .NE. 0) IDID = -8\n      ENDIF\nC\n390   JCALC = 1\n      RETURN\nC\nC------END OF SUBROUTINE DNEDD------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dnedk.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DNEDK(X,Y,YPRIME,NEQ,RES,JACK,PSOL,\n     *   H,WT,JSTART,IDID,RPAR,IPAR,PHI,GAMMA,SAVR,DELTA,E,\n     *   WM,IWM,CJ,CJOLD,CJLAST,S,UROUND,EPLI,SQRTN,RSQRTN,\n     *   EPCON,JCALC,JFLG,KP1,NONNEG,NTYPE,IERNLS)\nC\nC***BEGIN PROLOGUE  DNEDK\nC***REFER TO  DDASPK\nC***DATE WRITTEN   891219   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***REVISION DATE  940701   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DNEDK solves a nonlinear system of\nC     algebraic equations of the form\nC     G(X,Y,YPRIME) = 0 for the unknown Y.\nC\nC     The method used is a matrix-free Newton scheme.\nC\nC     The parameters represent\nC     X         -- Independent variable.\nC     Y         -- Solution vector at x.\nC     YPRIME    -- Derivative of solution vector\nC                  after successful step.\nC     NEQ       -- Number of equations to be integrated.\nC     RES       -- External user-supplied subroutine\nC                  to evaluate the residual.  See RES description\nC                  in DDASPK prologue.\nC     JACK     --  External user-supplied routine to update\nC                  the preconditioner.  (This is optional).\nC                  See JAC description for the case\nC                  INFO(12) = 1 in the DDASPK prologue.\nC     PSOL      -- External user-supplied routine to solve\nC                  a linear system using preconditioning.\nC                  (This is optional).  See explanation inside DDASPK.\nC     H         -- Appropriate step size for this step.\nC     WT        -- Vector of weights for error criterion.\nC     JSTART    -- Indicates first call to this routine.\nC                  If JSTART = 0, then this is the first call,\nC                  otherwise it is not.\nC     IDID      -- Completion flag, output by DNEDK.\nC                  See IDID description in DDASPK prologue.\nC     RPAR,IPAR -- Real and integer arrays used for communication\nC                  between the calling program and external user\nC                  routines.  They are not altered within DASPK.\nC     PHI       -- Array of divided differences used by\nC                  DNEDK.  The length is NEQ*(K+1), where\nC                  K is the maximum order.\nC     GAMMA     -- Array used to predict Y and YPRIME.  The length\nC                  is K+1, where K is the maximum order.\nC     SAVR      -- Work vector for DNEDK of length NEQ.\nC     DELTA     -- Work vector for DNEDK of length NEQ.\nC     E         -- Error accumulation vector for DNEDK of length NEQ.\nC     WM,IWM    -- Real and integer arrays storing\nC                  matrix information for linear system\nC                  solvers, and various other information.\nC     CJ        -- Parameter always proportional to 1/H.\nC     CJOLD     -- Saves the value of CJ as of the last call to DITMD.\nC                  Accounts for changes in CJ needed to\nC                  decide whether to call DITMD.\nC     CJLAST    -- Previous value of CJ.\nC     S         -- A scalar determined by the approximate rate\nC                  of convergence of the Newton iteration and used\nC                  in the convergence test for the Newton iteration.\nC\nC                  If RATE is defined to be an estimate of the\nC                  rate of convergence of the Newton iteration,\nC                  then S = RATE/(1.D0-RATE).\nC\nC                  The closer RATE is to 0., the faster the Newton\nC                  iteration is converging; the closer RATE is to 1.,\nC                  the slower the Newton iteration is converging.\nC\nC                  On the first Newton iteration with an up-dated\nC                  preconditioner S = 100.D0, Thus the initial\nC                  RATE of convergence is approximately 1.\nC\nC                  S is preserved from call to call so that the rate\nC                  estimate from a previous step can be applied to\nC                  the current step.\nC     UROUND    -- Unit roundoff.\nC     EPLI      -- convergence test constant.\nC                  See DDASPK prologue for more details.\nC     SQRTN     -- Square root of NEQ.\nC     RSQRTN    -- reciprical of square root of NEQ.\nC     EPCON     -- Tolerance to test for convergence of the Newton\nC                  iteration.\nC     JCALC     -- Flag used to determine when to update\nC                  the Jacobian matrix.  In general:\nC\nC                  JCALC = -1 ==> Call the DITMD routine to update\nC                                 the Jacobian matrix.\nC                  JCALC =  0 ==> Jacobian matrix is up-to-date.\nC                  JCALC =  1 ==> Jacobian matrix is out-dated,\nC                                 but DITMD will not be called unless\nC                                 JCALC is set to -1.\nC     JFLG      -- Flag showing whether a Jacobian routine is supplied.\nC     KP1       -- The current order + 1;  updated across calls.\nC     NONNEG    -- Flag to determine nonnegativity constraints.\nC     NTYPE     -- Identification code for the DNEDK routine.\nC                   1 ==> modified Newton; iterative linear solver.\nC                   2 ==> modified Newton; user-supplied linear solver.\nC     IERNLS    -- Error flag for nonlinear solver.\nC                   0 ==> nonlinear solver converged.\nC                   1 ==> recoverable error inside non-linear solver.\nC                  -1 ==> unrecoverable error inside non-linear solver.\nC\nC     The following group of variables are passed as arguments to\nC     the Newton iteration solver.  They are explained in greater detail\nC     in DNSK:\nC        TOLNEW, MULDEL, MAXIT, IERNEW\nC\nC     IERTYP -- Flag which tells whether this subroutine is correct.\nC               0 ==> correct subroutine.\nC               1 ==> incorrect subroutine.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   RES, JACK, DDWNRM, DNSK\nC\nC***END PROLOGUE  DNEDK\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),WT(*)\n      DIMENSION PHI(NEQ,*),SAVR(*),DELTA(*),E(*)\n      DIMENSION WM(*),IWM(*)\n      DIMENSION GAMMA(*),RPAR(*),IPAR(*)\n      EXTERNAL  RES, JACK, PSOL\nC\n      PARAMETER (LNRE=12, LNJE=13, LLOCWP=29, LLCIWP=30)\nC\n      SAVE MULDEL, MAXIT, XRATE\n      DATA MULDEL/0/, MAXIT/4/, XRATE/0.25D0/\nC\nC     Verify that this is the correct subroutine.\nC\n      IERTYP = 0\n      IF (NTYPE .NE. 1) THEN\n         IERTYP = 1\n         GO TO 380\n         ENDIF\nC\nC     If this is the first step, perform initializations.\nC\n      IF (JSTART .EQ. 0) THEN\n         CJOLD = CJ\n         JCALC = -1\n         S = 100.D0\n         ENDIF\nC\nC     Perform all other initializations.\nC\n      IERNLS = 0\n      LWP = IWM(LLOCWP)\n      LIWP = IWM(LLCIWP)\nC\nC     Decide whether to update the preconditioner.\nC\n      IF (JFLG .NE. 0) THEN\n         TEMP1 = (1.0D0 - XRATE)/(1.0D0 + XRATE)\n         TEMP2 = 1.0D0/TEMP1\n         IF (CJ/CJOLD .LT. TEMP1 .OR. CJ/CJOLD .GT. TEMP2) JCALC = -1\n         IF (CJ .NE. CJLAST) S = 100.D0\n      ELSE\n         JCALC = 0\n         ENDIF\nC\nC     Looping point for updating preconditioner with current stepsize.\nC\n300   CONTINUE\nC\nC     Initialize all error flags to zero.\nC\n      IERPJ = 0\n      IRES = 0\n      IERSL = 0\n      IERNEW = 0\nC\nC     Predict the solution and derivative and compute the tolerance\nC     for the Newton iteration.\nC\n      DO 310 I=1,NEQ\n         Y(I)=PHI(I,1)\n310      YPRIME(I)=0.0D0\n      DO 330 J=2,KP1\n         DO 320 I=1,NEQ\n            Y(I)=Y(I)+PHI(I,J)\n320         YPRIME(I)=YPRIME(I)+GAMMA(J)*PHI(I,J)\n330   CONTINUE\n      EPLIN = EPLI*EPCON\n      TOLNEW = EPLIN\nC\nC     Call RES to initialize DELTA.\nC\n      IWM(LNRE)=IWM(LNRE)+1\n      CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)\n      IF (IRES .LT. 0) GO TO 380\nC\nC\nC     If indicated, update the preconditioner.\nC     Set JCALC to 0 as an indicator that this has been done.\nC\n      IF(JCALC .EQ. -1)THEN\n         IWM(LNJE) = IWM(LNJE) + 1\n         JCALC=0\n         CALL JACK (RES, IRES, NEQ, X, Y, YPRIME, WT, DELTA, E, H, CJ,\n     *      WM(LWP), IWM(LIWP), IERPJ, RPAR, IPAR)\n         CJOLD=CJ\n         S = 100.D0\n         IF (IRES .LT. 0)  GO TO 380\n         IF (IERPJ .NE. 0) GO TO 380\n      ENDIF\nC\nC     Call the nonlinear Newton solver.\nC\n      CALL DNSK(X,Y,YPRIME,NEQ,RES,PSOL,WT,RPAR,IPAR,SAVR,\n     *   DELTA,E,WM,IWM,CJ,SQRTN,RSQRTN,EPLIN,EPCON,\n     *   S,TEMP1,TOLNEW,MULDEL,MAXIT,IRES,IERSL,IERNEW)\nC\n      IF (IERNEW .GT. 0 .AND. JCALC .NE. 0) THEN\nC\nC     The Newton iteration had a recoverable failure with an old\nC     preconditioner.  Retry the step with a new preconditioner.\nC\n         JCALC = -1\n         GO TO 300\n      ENDIF\nC\n      IF (IERNEW .NE. 0) GO TO 380\nC\nC     The Newton iteration has converged.  If nonnegativity of\nC     solution is required, set the solution nonnegative, if the\nC     perturbation to do it is small enough.  If the change is too\nC     large, then consider the corrector iteration to have failed.\nC\n      IF(NONNEG .EQ. 0) GO TO 390\n      DO 360 I = 1,NEQ\n 360    DELTA(I) = MIN(Y(I),0.0D0)\n      DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)\n      IF(DELNRM .GT. EPCON) GO TO 380\n      DO 370 I = 1,NEQ\n 370    E(I) = E(I) - DELTA(I)\n      GO TO 390\nC\nC\nC     Exits from nonlinear solver.\nC     No convergence with current preconditioner.\nC     Compute IERNLS and IDID accordingly.\nC\n380   CONTINUE\n      IF (IRES .LE. -2 .OR. IERSL .LT. 0 .OR. IERTYP .NE. 0) THEN\n         IERNLS = -1\n         IF (IRES .LE. -2) IDID = -11\n         IF (IERSL .LT. 0) IDID = -13\n         IF (IERTYP .NE. 0) IDID = -15\n      ELSE\n         IERNLS =  1\n         IF (IRES .EQ. -1) IDID = -10\n         IF (IERPJ .NE. 0) IDID = -5\n         IF (IERSL .GT. 0) IDID = -14\n      ENDIF\nC\nC\n390   JCALC = 1\n      RETURN\nC\nC------END OF SUBROUTINE DNEDK------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dnsd.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DNSD(X,Y,YPRIME,NEQ,RES,PDUM,WT,RPAR,IPAR,\n     *   DUMSVR,DELTA,E,WM,IWM,CJ,DUMS,DUMR,DUME,EPCON,\n     *   S,CONFAC,TOLNEW,MULDEL,MAXIT,IRES,IDUM,IERNEW)\nC\nC***BEGIN PROLOGUE  DNSD\nC***REFER TO  DDASPK\nC***DATE WRITTEN   891219   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***REVISION DATE  950126   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DNSD solves a nonlinear system of\nC     algebraic equations of the form\nC     G(X,Y,YPRIME) = 0 for the unknown Y.\nC\nC     The method used is a modified Newton scheme.\nC\nC     The parameters represent\nC\nC     X         -- Independent variable.\nC     Y         -- Solution vector.\nC     YPRIME    -- Derivative of solution vector.\nC     NEQ       -- Number of unknowns.\nC     RES       -- External user-supplied subroutine\nC                  to evaluate the residual.  See RES description\nC                  in DDASPK prologue.\nC     PDUM      -- Dummy argument.\nC     WT        -- Vector of weights for error criterion.\nC     RPAR,IPAR -- Real and integer arrays used for communication\nC                  between the calling program and external user\nC                  routines.  They are not altered within DASPK.\nC     DUMSVR    -- Dummy argument.\nC     DELTA     -- Work vector for DNSD of length NEQ.\nC     E         -- Error accumulation vector for DNSD of length NEQ.\nC     WM,IWM    -- Real and integer arrays storing\nC                  matrix information such as the matrix\nC                  of partial derivatives, permutation\nC                  vector, and various other information.\nC     CJ        -- Parameter always proportional to 1/H (step size).\nC     DUMS      -- Dummy argument.\nC     DUMR      -- Dummy argument.\nC     DUME      -- Dummy argument.\nC     EPCON     -- Tolerance to test for convergence of the Newton\nC                  iteration.\nC     S         -- Used for error convergence tests.\nC                  In the Newton iteration: S = RATE/(1 - RATE),\nC                  where RATE is the estimated rate of convergence\nC                  of the Newton iteration.\nC                  The calling routine passes the initial value\nC                  of S to the Newton iteration.\nC     CONFAC    -- A residual scale factor to improve convergence.\nC     TOLNEW    -- Tolerance on the norm of Newton correction in\nC                  alternative Newton convergence test.\nC     MULDEL    -- A flag indicating whether or not to multiply\nC                  DELTA by CONFAC.\nC                  0  ==> do not scale DELTA by CONFAC.\nC                  1  ==> scale DELTA by CONFAC.\nC     MAXIT     -- Maximum allowed number of Newton iterations.\nC     IRES      -- Error flag returned from RES.  See RES description\nC                  in DDASPK prologue.  If IRES = -1, then IERNEW\nC                  will be set to 1.\nC                  If IRES < -1, then IERNEW will be set to -1.\nC     IDUM      -- Dummy argument.\nC     IERNEW    -- Error flag for Newton iteration.\nC                   0  ==> Newton iteration converged.\nC                   1  ==> recoverable error inside Newton iteration.\nC                  -1  ==> unrecoverable error inside Newton iteration.\nC\nC     All arguments with \"DUM\" in their names are dummy arguments\nC     which are not used in this routine.\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   DSLVD, DDWNRM, RES\nC\nC***END PROLOGUE  DNSD\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),WT(*),DELTA(*),E(*)\n      DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)\n      EXTERNAL  RES\nC\n      PARAMETER (LNRE=12, LNNI=19)\nC\nC     Initialize Newton counter M and accumulation vector E.\nC\n      M = 0\n      DO 100 I=1,NEQ\n100     E(I)=0.0D0\nC\nC     Corrector loop.\nC\n300   CONTINUE\n      IWM(LNNI) = IWM(LNNI) + 1\nC\nC     If necessary, multiply residual by convergence factor.\nC\n      IF (MULDEL .EQ. 1) THEN\n         DO 320 I = 1,NEQ\n320        DELTA(I) = DELTA(I) * CONFAC\n        ENDIF\nC\nC     Compute a new iterate (back-substitution).\nC     Store the correction in DELTA.\nC\n      CALL DSLVD(NEQ,DELTA,WM,IWM)\nC\nC     Update Y, E, and YPRIME.\nC\n      DO 340 I=1,NEQ\n         Y(I)=Y(I)-DELTA(I)\n         E(I)=E(I)-DELTA(I)\n340      YPRIME(I)=YPRIME(I)-CJ*DELTA(I)\nC\nC     Test for convergence of the iteration.\nC\n      DELNRM=DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)\n      IF (DELNRM .LE. TOLNEW) GO TO 370\n      IF (M .EQ. 0) THEN\n        OLDNRM = DELNRM\n      ELSE\n        RATE = (DELNRM/OLDNRM)**(1.0D0/M)\n        IF (RATE .GT. 0.9D0) GO TO 380\n        S = RATE/(1.0D0 - RATE)\n      ENDIF\n      IF (S*DELNRM .LE. EPCON) GO TO 370\nC\nC     The corrector has not yet converged.\nC     Update M and test whether the\nC     maximum number of iterations have\nC     been tried.\nC\n      M=M+1\n      IF(M.GE.MAXIT) GO TO 380\nC\nC     Evaluate the residual,\nC     and go back to do another iteration.\nC\n      IWM(LNRE)=IWM(LNRE)+1\n      CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)\n      IF (IRES .LT. 0) GO TO 380\n      GO TO 300\nC\nC     The iteration has converged.\nC\n370   RETURN\nC\nC     The iteration has not converged.  Set IERNEW appropriately.\nC\n380   CONTINUE\n      IF (IRES .LE. -2 ) THEN\n         IERNEW = -1\n      ELSE\n         IERNEW = 1\n      ENDIF\n      RETURN\nC\nC\nC------END OF SUBROUTINE DNSD-------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dnsid.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DNSID(X,Y,YPRIME,NEQ,ICOPT,ID,RES,WT,RPAR,IPAR,\n     *   DELTA,R,YIC,YPIC,WM,IWM,CJ,EPCON,RATEMX,MAXIT,STPTOL,\n     *   ICNFLG,ICNSTR,IERNEW)\nC\nC***BEGIN PROLOGUE  DNSID\nC***REFER TO  DDASPK\nC***DATE WRITTEN   940701   (YYMMDD)\nC***REVISION DATE  950713   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DNSID solves a nonlinear system of algebraic equations of the\nC     form G(X,Y,YPRIME) = 0 for the unknown parts of Y and YPRIME\nC     in the initial conditions.\nC\nC     The method used is a modified Newton scheme.\nC\nC     The parameters represent\nC\nC     X         -- Independent variable.\nC     Y         -- Solution vector.\nC     YPRIME    -- Derivative of solution vector.\nC     NEQ       -- Number of unknowns.\nC     ICOPT     -- Initial condition option chosen (1 or 2).\nC     ID        -- Array of dimension NEQ, which must be initialized\nC                  if ICOPT = 1.  See DDASIC.\nC     RES       -- External user-supplied subroutine to evaluate the\nC                  residual.  See RES description in DDASPK prologue.\nC     WT        -- Vector of weights for error criterion.\nC     RPAR,IPAR -- Real and integer arrays used for communication\nC                  between the calling program and external user\nC                  routines.  They are not altered within DASPK.\nC     DELTA     -- Residual vector on entry, and work vector of\nC                  length NEQ for DNSID.\nC     WM,IWM    -- Real and integer arrays storing matrix information\nC                  such as the matrix of partial derivatives,\nC                  permutation vector, and various other information.\nC     CJ        -- Matrix parameter = 1/H (ICOPT = 1) or 0 (ICOPT = 2).\nC     R         -- Array of length NEQ used as workspace by the\nC                  linesearch routine DLINSD.\nC     YIC,YPIC  -- Work vectors for DLINSD, each of length NEQ.\nC     EPCON     -- Tolerance to test for convergence of the Newton\nC                  iteration.\nC     RATEMX    -- Maximum convergence rate for which Newton iteration\nC                  is considered converging.\nC     MAXIT     -- Maximum allowed number of Newton iterations.\nC     STPTOL    -- Tolerance used in calculating the minimum lambda\nC                  value allowed.\nC     ICNFLG    -- Integer scalar.  If nonzero, then constraint\nC                  violations in the proposed new approximate solution\nC                  will be checked for, and the maximum step length\nC                  will be adjusted accordingly.\nC     ICNSTR    -- Integer array of length NEQ containing flags for\nC                  checking constraints.\nC     IERNEW    -- Error flag for Newton iteration.\nC                   0  ==> Newton iteration converged.\nC                   1  ==> failed to converge, but RATE .le. RATEMX.\nC                   2  ==> failed to converge, RATE .gt. RATEMX.\nC                   3  ==> other recoverable error (IRES = -1, or\nC                          linesearch failed).\nC                  -1  ==> unrecoverable error (IRES = -2).\nC\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   DSLVD, DDWNRM, DLINSD, DCOPY\nC\nC***END PROLOGUE  DNSID\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),WT(*),R(*)\n      DIMENSION ID(*),DELTA(*), YIC(*), YPIC(*)\n      DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)\n      DIMENSION ICNSTR(*)\n      EXTERNAL  RES\nC\n      PARAMETER (LNNI=19, LLSOFF=35)\nC\nC\nC     Initializations.  M is the Newton iteration counter.\nC\n      LSOFF = IWM(LLSOFF)\n      M = 0\n      RATE = 1.0D0\n      RLX = 0.4D0\nC\nC     Compute a new step vector DELTA by back-substitution.\nC\n      CALL DSLVD (NEQ, DELTA, WM, IWM)\nC\nC     Get norm of DELTA.  Return now if norm(DELTA) .le. EPCON.\nC\n      DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)\n      FNRM = DELNRM\n      IF (FNRM .LE. EPCON) RETURN\nC\nC     Newton iteration loop.\nC\n 300  CONTINUE\n      IWM(LNNI) = IWM(LNNI) + 1\nC\nC     Call linesearch routine for global strategy and set RATE\nC\n      OLDFNM = FNRM\nC\n      CALL DLINSD (NEQ, Y, X, YPRIME, CJ, DELTA, DELNRM, WT, LSOFF,\n     *             STPTOL, IRET, RES, IRES, WM, IWM, FNRM, ICOPT, ID,\n     *             R, YIC, YPIC, ICNFLG, ICNSTR, RLX, RPAR, IPAR)\nC\n      RATE = FNRM/OLDFNM\nC\nC     Check for error condition from linesearch.\n      IF (IRET .NE. 0) GO TO 390\nC\nC     Test for convergence of the iteration, and return or loop.\nC\n      IF (FNRM .LE. EPCON) RETURN\nC\nC     The iteration has not yet converged.  Update M.\nC     Test whether the maximum number of iterations have been tried.\nC\n      M = M + 1\n      IF (M .GE. MAXIT) GO TO 380\nC\nC     Copy the residual to DELTA and its norm to DELNRM, and loop for\nC     another iteration.\nC\n      CALL DCOPY (NEQ, R, 1, DELTA, 1)\n      DELNRM = FNRM\n      GO TO 300\nC\nC     The maximum number of iterations was done.  Set IERNEW and return.\nC\n 380  IF (RATE .LE. RATEMX) THEN\n         IERNEW = 1\n      ELSE\n         IERNEW = 2\n      ENDIF\n      RETURN\nC\n 390  IF (IRES .LE. -2) THEN\n         IERNEW = -1\n      ELSE\n         IERNEW = 3\n      ENDIF\n      RETURN\nC\nC\nC------END OF SUBROUTINE DNSID------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dnsik.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DNSIK(X,Y,YPRIME,NEQ,ICOPT,ID,RES,PSOL,WT,RPAR,IPAR,\n     *   SAVR,DELTA,R,YIC,YPIC,PWK,WM,IWM,CJ,SQRTN,RSQRTN,EPLIN,EPCON,\n     *   RATEMX,MAXIT,STPTOL,ICNFLG,ICNSTR,IERNEW)\nC\nC***BEGIN PROLOGUE  DNSIK\nC***REFER TO  DDASPK\nC***DATE WRITTEN   940701   (YYMMDD)\nC***REVISION DATE  950714   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DNSIK solves a nonlinear system of algebraic equations of the\nC     form G(X,Y,YPRIME) = 0 for the unknown parts of Y and YPRIME in\nC     the initial conditions.\nC\nC     The method used is a Newton scheme combined with a linesearch\nC     algorithm, using Krylov iterative linear system methods.\nC\nC     The parameters represent\nC\nC     X         -- Independent variable.\nC     Y         -- Solution vector.\nC     YPRIME    -- Derivative of solution vector.\nC     NEQ       -- Number of unknowns.\nC     ICOPT     -- Initial condition option chosen (1 or 2).\nC     ID        -- Array of dimension NEQ, which must be initialized\nC                  if ICOPT = 1.  See DDASIC.\nC     RES       -- External user-supplied subroutine\nC                  to evaluate the residual.  See RES description\nC                  in DDASPK prologue.\nC     PSOL      -- External user-supplied routine to solve\nC                  a linear system using preconditioning.\nC                  See explanation inside DDASPK.\nC     WT        -- Vector of weights for error criterion.\nC     RPAR,IPAR -- Real and integer arrays used for communication\nC                  between the calling program and external user\nC                  routines.  They are not altered within DASPK.\nC     SAVR      -- Work vector for DNSIK of length NEQ.\nC     DELTA     -- Residual vector on entry, and work vector of\nC                  length NEQ for DNSIK.\nC     R         -- Work vector for DNSIK of length NEQ.\nC     YIC,YPIC  -- Work vectors for DNSIK, each of length NEQ.\nC     PWK       -- Work vector for DNSIK of length NEQ.\nC     WM,IWM    -- Real and integer arrays storing\nC                  matrix information such as the matrix\nC                  of partial derivatives, permutation\nC                  vector, and various other information.\nC     CJ        -- Matrix parameter = 1/H (ICOPT = 1) or 0 (ICOPT = 2).\nC     SQRTN     -- Square root of NEQ.\nC     RSQRTN    -- reciprical of square root of NEQ.\nC     EPLIN     -- Tolerance for linear system solver.\nC     EPCON     -- Tolerance to test for convergence of the Newton\nC                  iteration.\nC     RATEMX    -- Maximum convergence rate for which Newton iteration\nC                  is considered converging.\nC     MAXIT     -- Maximum allowed number of Newton iterations.\nC     STPTOL    -- Tolerance used in calculating the minimum lambda\nC                  value allowed.\nC     ICNFLG    -- Integer scalar.  If nonzero, then constraint\nC                  violations in the proposed new approximate solution\nC                  will be checked for, and the maximum step length\nC                  will be adjusted accordingly.\nC     ICNSTR    -- Integer array of length NEQ containing flags for\nC                  checking constraints.\nC     IERNEW    -- Error flag for Newton iteration.\nC                   0  ==> Newton iteration converged.\nC                   1  ==> failed to converge, but RATE .lt. 1.\nC                   2  ==> failed to converge, RATE .gt. RATEMX.\nC                   3  ==> other recoverable error.\nC                  -1  ==> unrecoverable error inside Newton iteration.\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   DFNRMK, DSLVK, DDWNRM, DLINSK, DCOPY\nC\nC***END PROLOGUE  DNSIK\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),WT(*),ID(*),DELTA(*),R(*),SAVR(*)\n      DIMENSION YIC(*),YPIC(*),PWK(*),WM(*),IWM(*), RPAR(*),IPAR(*)\n      DIMENSION ICNSTR(*)\n      EXTERNAL RES, PSOL\nC\n      PARAMETER (LNNI=19, LNPS=21, LLOCWP=29, LLCIWP=30)\n      PARAMETER (LLSOFF=35, LSTOL=14)\nC\nC\nC     Initializations.  M is the Newton iteration counter.\nC\n      LSOFF = IWM(LLSOFF)\n      M = 0\n      RATE = 1.0D0\n      LWP = IWM(LLOCWP)\n      LIWP = IWM(LLCIWP)\n      RLX = 0.4D0\nC\nC     Save residual in SAVR.\nC\n      CALL DCOPY (NEQ, DELTA, 1, SAVR, 1)\nC\nC     Compute norm of (P-inverse)*(residual).\nC\n      CALL DFNRMK (NEQ, Y, X, YPRIME, SAVR, R, CJ, WT, SQRTN, RSQRTN,\n     *   RES, IRES, PSOL, 1, IER, FNRM, EPLIN, WM(LWP), IWM(LIWP),\n     *   PWK, RPAR, IPAR)\n      IWM(LNPS) = IWM(LNPS) + 1\n      IF (IER .NE. 0) THEN\n        IERNEW = 3\n        RETURN\n      ENDIF\nC\nC     Return now if residual norm is .le. EPCON.\nC\n      IF (FNRM .LE. EPCON) RETURN\nC\nC     Newton iteration loop.\nC\n300   CONTINUE\n      IWM(LNNI) = IWM(LNNI) + 1\nC\nC     Compute a new step vector DELTA.\nC\n      CALL DSLVK (NEQ, Y, X, YPRIME, SAVR, DELTA, WT, WM, IWM,\n     *   RES, IRES, PSOL, IERSL, CJ, EPLIN, SQRTN, RSQRTN, RHOK,\n     *   RPAR, IPAR)\n      IF (IRES .NE. 0 .OR. IERSL .NE. 0) GO TO 390\nC\nC     Get norm of DELTA.  Return now if DELTA is zero.\nC\n      DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)\n      IF (DELNRM .EQ. 0.0D0) RETURN\nC\nC     Call linesearch routine for global strategy and set RATE.\nC\n      OLDFNM = FNRM\nC\n      CALL DLINSK (NEQ, Y, X, YPRIME, SAVR, CJ, DELTA, DELNRM, WT,\n     *   SQRTN, RSQRTN, LSOFF, STPTOL, IRET, RES, IRES, PSOL, WM, IWM,\n     *   RHOK, FNRM, ICOPT, ID, WM(LWP), IWM(LIWP), R, EPLIN, YIC, YPIC,\n     *   PWK, ICNFLG, ICNSTR, RLX, RPAR, IPAR)\nC\n      RATE = FNRM/OLDFNM\nC\nC     Check for error condition from linesearch.\n      IF (IRET .NE. 0) GO TO 390\nC\nC     Test for convergence of the iteration, and return or loop.\nC\n      IF (FNRM .LE. EPCON) RETURN\nC\nC     The iteration has not yet converged.  Update M.\nC     Test whether the maximum number of iterations have been tried.\nC\n      M=M+1\n      IF(M .GE. MAXIT) GO TO 380\nC\nC     Copy the residual SAVR to DELTA and loop for another iteration.\nC\n      CALL DCOPY (NEQ,  SAVR, 1, DELTA, 1)\n      GO TO 300\nC\nC     The maximum number of iterations was done.  Set IERNEW and return.\nC\n380   IF (RATE .LE. RATEMX) THEN\n         IERNEW = 1\n      ELSE\n         IERNEW = 2\n      ENDIF\n      RETURN\nC\n390   IF (IRES .LE. -2 .OR. IERSL .LT. 0) THEN\n         IERNEW = -1\n      ELSE\n         IERNEW = 3\n         IF (IRES .EQ. 0 .AND. IERSL .EQ. 1 .AND. M .GE. 2\n     1       .AND. RATE .LT. 1.0D0) IERNEW = 1\n      ENDIF\n      RETURN\nC\nC\nC----------------------- END OF SUBROUTINE DNSIK------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dnsk.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DNSK(X,Y,YPRIME,NEQ,RES,PSOL,WT,RPAR,IPAR,\n     *   SAVR,DELTA,E,WM,IWM,CJ,SQRTN,RSQRTN,EPLIN,EPCON,\n     *   S,CONFAC,TOLNEW,MULDEL,MAXIT,IRES,IERSL,IERNEW)\nC\nC***BEGIN PROLOGUE  DNSK\nC***REFER TO  DDASPK\nC***DATE WRITTEN   891219   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***REVISION DATE  950126   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DNSK solves a nonlinear system of\nC     algebraic equations of the form\nC     G(X,Y,YPRIME) = 0 for the unknown Y.\nC\nC     The method used is a modified Newton scheme.\nC\nC     The parameters represent\nC\nC     X         -- Independent variable.\nC     Y         -- Solution vector.\nC     YPRIME    -- Derivative of solution vector.\nC     NEQ       -- Number of unknowns.\nC     RES       -- External user-supplied subroutine\nC                  to evaluate the residual.  See RES description\nC                  in DDASPK prologue.\nC     PSOL      -- External user-supplied routine to solve\nC                  a linear system using preconditioning.\nC                  See explanation inside DDASPK.\nC     WT        -- Vector of weights for error criterion.\nC     RPAR,IPAR -- Real and integer arrays used for communication\nC                  between the calling program and external user\nC                  routines.  They are not altered within DASPK.\nC     SAVR      -- Work vector for DNSK of length NEQ.\nC     DELTA     -- Work vector for DNSK of length NEQ.\nC     E         -- Error accumulation vector for DNSK of length NEQ.\nC     WM,IWM    -- Real and integer arrays storing\nC                  matrix information such as the matrix\nC                  of partial derivatives, permutation\nC                  vector, and various other information.\nC     CJ        -- Parameter always proportional to 1/H (step size).\nC     SQRTN     -- Square root of NEQ.\nC     RSQRTN    -- reciprical of square root of NEQ.\nC     EPLIN     -- Tolerance for linear system solver.\nC     EPCON     -- Tolerance to test for convergence of the Newton\nC                  iteration.\nC     S         -- Used for error convergence tests.\nC                  In the Newton iteration: S = RATE/(1.D0-RATE),\nC                  where RATE is the estimated rate of convergence\nC                  of the Newton iteration.\nC\nC                  The closer RATE is to 0., the faster the Newton\nC                  iteration is converging; the closer RATE is to 1.,\nC                  the slower the Newton iteration is converging.\nC\nC                  The calling routine sends the initial value\nC                  of S to the Newton iteration.\nC     CONFAC    -- A residual scale factor to improve convergence.\nC     TOLNEW    -- Tolerance on the norm of Newton correction in\nC                  alternative Newton convergence test.\nC     MULDEL    -- A flag indicating whether or not to multiply\nC                  DELTA by CONFAC.\nC                  0  ==> do not scale DELTA by CONFAC.\nC                  1  ==> scale DELTA by CONFAC.\nC     MAXIT     -- Maximum allowed number of Newton iterations.\nC     IRES      -- Error flag returned from RES.  See RES description\nC                  in DDASPK prologue.  If IRES = -1, then IERNEW\nC                  will be set to 1.\nC                  If IRES < -1, then IERNEW will be set to -1.\nC     IERSL     -- Error flag for linear system solver.\nC                  See IERSL description in subroutine DSLVK.\nC                  If IERSL = 1, then IERNEW will be set to 1.\nC                  If IERSL < 0, then IERNEW will be set to -1.\nC     IERNEW    -- Error flag for Newton iteration.\nC                   0  ==> Newton iteration converged.\nC                   1  ==> recoverable error inside Newton iteration.\nC                  -1  ==> unrecoverable error inside Newton iteration.\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED\nC   RES, DSLVK, DDWNRM\nC\nC***END PROLOGUE  DNSK\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION Y(*),YPRIME(*),WT(*),DELTA(*),E(*),SAVR(*)\n      DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)\n      EXTERNAL  RES, PSOL\nC\n      PARAMETER (LNNI=19, LNRE=12)\nC\nC     Initialize Newton counter M and accumulation vector E.\nC\n      M = 0\n      DO 100 I=1,NEQ\n100     E(I) = 0.0D0\nC\nC     Corrector loop.\nC\n300   CONTINUE\n      IWM(LNNI) = IWM(LNNI) + 1\nC\nC     If necessary, multiply residual by convergence factor.\nC\n      IF (MULDEL .EQ. 1) THEN\n        DO 320 I = 1,NEQ\n320       DELTA(I) = DELTA(I) * CONFAC\n        ENDIF\nC\nC     Save residual in SAVR.\nC\n      DO 340 I = 1,NEQ\n340     SAVR(I) = DELTA(I)\nC\nC     Compute a new iterate.  Store the correction in DELTA.\nC\n      CALL DSLVK (NEQ, Y, X, YPRIME, SAVR, DELTA, WT, WM, IWM,\n     *   RES, IRES, PSOL, IERSL, CJ, EPLIN, SQRTN, RSQRTN, RHOK,\n     *   RPAR, IPAR)\n      IF (IRES .NE. 0 .OR. IERSL .NE. 0) GO TO 380\nC\nC     Update Y, E, and YPRIME.\nC\n      DO 360 I=1,NEQ\n         Y(I) = Y(I) - DELTA(I)\n         E(I) = E(I) - DELTA(I)\n360      YPRIME(I) = YPRIME(I) - CJ*DELTA(I)\nC\nC     Test for convergence of the iteration.\nC\n      DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)\n      IF (DELNRM .LE. TOLNEW) GO TO 370\n      IF (M .EQ. 0) THEN\n        OLDNRM = DELNRM\n      ELSE\n        RATE = (DELNRM/OLDNRM)**(1.0D0/M)\n        IF (RATE .GT. 0.9D0) GO TO 380\n        S = RATE/(1.0D0 - RATE)\n      ENDIF\n      IF (S*DELNRM .LE. EPCON) GO TO 370\nC\nC     The corrector has not yet converged.  Update M and test whether\nC     the maximum number of iterations have been tried.\nC\n      M = M + 1\n      IF (M .GE. MAXIT) GO TO 380\nC\nC     Evaluate the residual, and go back to do another iteration.\nC\n      IWM(LNRE) = IWM(LNRE) + 1\n      CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)\n      IF (IRES .LT. 0) GO TO 380\n      GO TO 300\nC\nC     The iteration has converged.\nC\n370    RETURN\nC\nC     The iteration has not converged.  Set IERNEW appropriately.\nC\n380   CONTINUE\n      IF (IRES .LE. -2 .OR. IERSL .LT. 0) THEN\n         IERNEW = -1\n      ELSE\n         IERNEW = 1\n      ENDIF\n      RETURN\nC\nC\nC------END OF SUBROUTINE DNSK-------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dorth.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DORTH (VNEW, V, HES, N, LL, LDHES, KMP, SNORMW)\nC\nC***BEGIN PROLOGUE  DORTH\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC This routine orthogonalizes the vector VNEW against the previous\nC KMP vectors in the V array.  It uses a modified Gram-Schmidt\nC orthogonalization procedure with conditional reorthogonalization.\nC\nC      On entry\nC\nC         VNEW = The vector of length N containing a scaled product\nC                OF The Jacobian and the vector V(*,LL).\nC\nC         V    = The N x LL array containing the previous LL\nC                orthogonal vectors V(*,1) to V(*,LL).\nC\nC         HES  = An LL x LL upper Hessenberg matrix containing,\nC                in HES(I,K), K.LT.LL, scaled inner products of\nC                A*V(*,K) and V(*,I).\nC\nC        LDHES = The leading dimension of the HES array.\nC\nC         N    = The order of the matrix A, and the length of VNEW.\nC\nC         LL   = The current order of the matrix HES.\nC\nC          KMP = The number of previous vectors the new vector VNEW\nC                must be made orthogonal to (KMP .LE. MAXL).\nC\nC\nC      On return\nC\nC         VNEW = The new vector orthogonal to V(*,I0),\nC                where I0 = MAX(1, LL-KMP+1).\nC\nC         HES  = Upper Hessenberg matrix with column LL filled in with\nC                scaled inner products of A*V(*,LL) and V(*,I).\nC\nC       SNORMW = L-2 norm of VNEW.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   DDOT, DNRM2, DAXPY\nC\nC***END PROLOGUE  DORTH\nC\n      INTEGER N, LL, LDHES, KMP\n      DOUBLE PRECISION VNEW, V, HES, SNORMW\n      DIMENSION VNEW(*), V(N,*), HES(LDHES,*)\n      INTEGER I, I0\n      DOUBLE PRECISION ARG, DDOT, DNRM2, SUMDSQ, TEM, VNRM\nC\nC-----------------------------------------------------------------------\nC Get norm of unaltered VNEW for later use.\nC-----------------------------------------------------------------------\n      VNRM = DNRM2 (N, VNEW, 1)\nC-----------------------------------------------------------------------\nC Do Modified Gram-Schmidt on VNEW = A*V(LL).\nC Scaled inner products give new column of HES.\nC Projections of earlier vectors are subtracted from VNEW.\nC-----------------------------------------------------------------------\n      I0 = MAX0(1,LL-KMP+1)\n      DO 10 I = I0,LL\n        HES(I,LL) = DDOT (N, V(1,I), 1, VNEW, 1)\n        TEM = -HES(I,LL)\n        CALL DAXPY (N, TEM, V(1,I), 1, VNEW, 1)\n 10     CONTINUE\nC-----------------------------------------------------------------------\nC Compute SNORMW = norm of VNEW.\nC If VNEW is small compared to its input value (in norm), then\nC Reorthogonalize VNEW to V(*,1) through V(*,LL).\nC Correct if relative correction exceeds 1000*(unit roundoff).\nC Finally, correct SNORMW using the dot products involved.\nC-----------------------------------------------------------------------\n      SNORMW = DNRM2 (N, VNEW, 1)\n      IF (VNRM + 0.001D0*SNORMW .NE. VNRM) RETURN\n      SUMDSQ = 0.0D0\n      DO 30 I = I0,LL\n        TEM = -DDOT (N, V(1,I), 1, VNEW, 1)\n        IF (HES(I,LL) + 0.001D0*TEM .EQ. HES(I,LL)) GO TO 30\n        HES(I,LL) = HES(I,LL) - TEM\n        CALL DAXPY (N, TEM, V(1,I), 1, VNEW, 1)\n        SUMDSQ = SUMDSQ + TEM**2\n 30     CONTINUE\n      IF (SUMDSQ .EQ. 0.0D0) RETURN\n      ARG = MAX(0.0D0,SNORMW**2 - SUMDSQ)\n      SNORMW = SQRT(ARG)\n      RETURN\nC\nC------END OF SUBROUTINE DORTH------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dslvd.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DSLVD(NEQ,DELTA,WM,IWM)\nC\nC***BEGIN PROLOGUE  DSLVD\nC***REFER TO  DDASPK\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***REVISION DATE  940701   (YYMMDD) (new LIPVT)\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     This routine manages the solution of the linear\nC     system arising in the Newton iteration.\nC     Real matrix information and real temporary storage\nC     is stored in the array WM.\nC     Integer matrix information is stored in the array IWM.\nC     For a dense matrix, the LAPACK routine DGETRS is called.\nC     For a banded matrix, the LAPACK routine DGBTRS is called.\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   DGETRS, DGBTRS\nC\nC***END PROLOGUE  DSLVD\nC\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      DIMENSION DELTA(*),WM(*),IWM(*)\nC\n      PARAMETER (LML=1, LMU=2, LMTYPE=4, LLCIWP=30)\nC\n      LIPVT = IWM(LLCIWP)\n      MTYPE=IWM(LMTYPE)\n      GO TO(100,100,300,400,400),MTYPE\nC\nC     Dense matrix.\nC\n100   CALL DGETRS('N', NEQ, 1, WM, NEQ, IWM(LIPVT), DELTA, NEQ, INLPCK)\n      RETURN\nC\nC     Dummy section for MTYPE=3.\nC\n300   CONTINUE\n      RETURN\nC\nC     Banded matrix.\nC\n400   MEBAND=2*IWM(LML)+IWM(LMU)+1\n      CALL DGBTRS('N', NEQ, IWM(LML), IWM(LMU), 1, WM, MEBAND,\n     *     IWM(LIPVT), DELTA, NEQ, INLPCK)\n      RETURN\nC\nC------END OF SUBROUTINE DSLVD------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dslvk.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DSLVK (NEQ, Y, TN, YPRIME, SAVR, X, EWT, WM, IWM,\n     *   RES, IRES, PSOL, IERSL, CJ, EPLIN, SQRTN, RSQRTN, RHOK,\n     *   RPAR, IPAR)\nC\nC***BEGIN PROLOGUE  DSLVK\nC***REFER TO  DDASPK\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***REVISION DATE  940928   Removed MNEWT and added RHOK in call list.\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC DSLVK uses a restart algorithm and interfaces to DSPIGM for\nC the solution of the linear system arising from a Newton iteration.\nC\nC In addition to variables described elsewhere,\nC communication with DSLVK uses the following variables..\nC WM    = Real work space containing data for the algorithm\nC         (Krylov basis vectors, Hessenberg matrix, etc.).\nC IWM   = Integer work space containing data for the algorithm.\nC X     = The right-hand side vector on input, and the solution vector\nC         on output, of length NEQ.\nC IRES  = Error flag from RES.\nC IERSL = Output flag ..\nC         IERSL =  0 means no trouble occurred (or user RES routine\nC                    returned IRES < 0)\nC         IERSL =  1 means the iterative method failed to converge\nC                    (DSPIGM returned IFLAG > 0.)\nC         IERSL = -1 means there was a nonrecoverable error in the\nC                    iterative solver, and an error exit will occur.\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   DSCAL, DCOPY, DSPIGM\nC\nC***END PROLOGUE  DSLVK\nC\n      INTEGER NEQ, IWM, IRES, IERSL, IPAR\n      DOUBLE PRECISION Y, TN, YPRIME, SAVR, X, EWT, WM, CJ, EPLIN,\n     1   SQRTN, RSQRTN, RHOK, RPAR\n      DIMENSION Y(*), YPRIME(*), SAVR(*), X(*), EWT(*),\n     1  WM(*), IWM(*), RPAR(*), IPAR(*)\nC\n      INTEGER IFLAG, IRST, NRSTS, NRMAX, LR, LDL, LHES, LGMR, LQ, LV,\n     1        LWK, LZ, MAXLP1, NPSL\n      INTEGER NLI, NPS, NCFL, NRE, MAXL, KMP, MITER\n      EXTERNAL  RES, PSOL\nC\n      PARAMETER (LNRE=12, LNCFL=16, LNLI=20, LNPS=21)\n      PARAMETER (LLOCWP=29, LLCIWP=30)\n      PARAMETER (LMITER=23, LMAXL=24, LKMP=25, LNRMAX=26)\nC\nC-----------------------------------------------------------------------\nC IRST is set to 1, to indicate restarting is in effect.\nC NRMAX is the maximum number of restarts.\nC-----------------------------------------------------------------------\n      DATA IRST/1/\nC\n      LIWP = IWM(LLCIWP)\n      NLI = IWM(LNLI)\n      NPS = IWM(LNPS)\n      NCFL = IWM(LNCFL)\n      NRE = IWM(LNRE)\n      LWP = IWM(LLOCWP)\n      MAXL = IWM(LMAXL)\n      KMP = IWM(LKMP)\n      NRMAX = IWM(LNRMAX)\n      MITER = IWM(LMITER)\n      IERSL = 0\n      IRES = 0\nC-----------------------------------------------------------------------\nC Use a restarting strategy to solve the linear system\nC P*X = -F.  Parse the work vector, and perform initializations.\nC Note that zero is the initial guess for X.\nC-----------------------------------------------------------------------\n      MAXLP1 = MAXL + 1\n      LV = 1\n      LR = LV + NEQ*MAXL\n      LHES = LR + NEQ + 1\n      LQ = LHES + MAXL*MAXLP1\n      LWK = LQ + 2*MAXL\n      LDL = LWK + MIN0(1,MAXL-KMP)*NEQ\n      LZ = LDL + NEQ\n      CALL DSCAL (NEQ, RSQRTN, EWT, 1)\n      CALL DCOPY (NEQ, X, 1, WM(LR), 1)\n      DO 110 I = 1,NEQ\n 110     X(I) = 0.D0\nC-----------------------------------------------------------------------\nC Top of loop for the restart algorithm.  Initial pass approximates\nC X and sets up a transformed system to perform subsequent restarts\nC to update X.  NRSTS is initialized to -1, because restarting\nC does not occur until after the first pass.\nC Update NRSTS; conditionally copy DL to R; call the DSPIGM\nC algorithm to solve A*Z = R;  updated counters;  update X with\nC the residual solution.\nC Note:  if convergence is not achieved after NRMAX restarts,\nC then the linear solver is considered to have failed.\nC-----------------------------------------------------------------------\n      NRSTS = -1\n 115  CONTINUE\n      NRSTS = NRSTS + 1\n      IF (NRSTS .GT. 0) CALL DCOPY (NEQ, WM(LDL), 1, WM(LR),1)\n      CALL DSPIGM (NEQ, TN, Y, YPRIME, SAVR, WM(LR), EWT, MAXL, MAXLP1,\n     1   KMP, EPLIN, CJ, RES, IRES, NRES, PSOL, NPSL, WM(LZ), WM(LV),\n     2   WM(LHES), WM(LQ), LGMR, WM(LWP), IWM(LIWP), WM(LWK),\n     3   WM(LDL), RHOK, IFLAG, IRST, NRSTS, RPAR, IPAR)\n      NLI = NLI + LGMR\n      NPS = NPS + NPSL\n      NRE = NRE + NRES\n      DO 120 I = 1,NEQ\n 120     X(I) = X(I) + WM(LZ+I-1)\n      IF ((IFLAG .EQ. 1) .AND. (NRSTS .LT. NRMAX) .AND. (IRES .EQ. 0))\n     1   GO TO 115\nC-----------------------------------------------------------------------\nC The restart scheme is finished.  Test IRES and IFLAG to see if\nC convergence was not achieved, and set flags accordingly.\nC-----------------------------------------------------------------------\n      IF (IRES .LT. 0) THEN\n         NCFL = NCFL + 1\n      ELSE IF (IFLAG .NE. 0) THEN\n         NCFL = NCFL + 1\n         IF (IFLAG .GT. 0) IERSL = 1\n         IF (IFLAG .LT. 0) IERSL = -1\n      ENDIF\nC-----------------------------------------------------------------------\nC Update IWM with counters, rescale EWT, and return.\nC-----------------------------------------------------------------------\n      IWM(LNLI)  = NLI\n      IWM(LNPS)  = NPS\n      IWM(LNCFL) = NCFL\n      IWM(LNRE)  = NRE\n      CALL DSCAL (NEQ, SQRTN, EWT, 1)\n      RETURN\nC\nC------END OF SUBROUTINE DSLVK------------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dspigm.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DSPIGM (NEQ, TN, Y, YPRIME, SAVR, R, WGHT, MAXL,\n     *   MAXLP1, KMP, EPLIN, CJ, RES, IRES, NRE, PSOL, NPSL, Z, V,\n     *   HES, Q, LGMR, WP, IWP, WK, DL, RHOK, IFLAG, IRST, NRSTS,\n     *   RPAR, IPAR)\nC\nC***BEGIN PROLOGUE  DSPIGM\nC***DATE WRITTEN   890101   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***REVISION DATE  940927   Removed MNEWT and added RHOK in call list.\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC This routine solves the linear system A * Z = R using a scaled\nC preconditioned version of the generalized minimum residual method.\nC An initial guess of Z = 0 is assumed.\nC\nC      On entry\nC\nC          NEQ = Problem size, passed to PSOL.\nC\nC           TN = Current Value of T.\nC\nC            Y = Array Containing current dependent variable vector.\nC\nC       YPRIME = Array Containing current first derivative of Y.\nC\nC         SAVR = Array containing current value of G(T,Y,YPRIME).\nC\nC            R = The right hand side of the system A*Z = R.\nC                R is also used as work space when computing\nC                the final approximation and will therefore be\nC                destroyed.\nC                (R is the same as V(*,MAXL+1) in the call to DSPIGM.)\nC\nC         WGHT = The vector of length NEQ containing the nonzero\nC                elements of the diagonal scaling matrix.\nC\nC         MAXL = The maximum allowable order of the matrix H.\nC\nC       MAXLP1 = MAXL + 1, used for dynamic dimensioning of HES.\nC\nC          KMP = The number of previous vectors the new vector, VNEW,\nC                must be made orthogonal to.  (KMP .LE. MAXL.)\nC\nC        EPLIN = Tolerance on residuals R-A*Z in weighted rms norm.\nC\nC           CJ = Scalar proportional to current value of\nC                1/(step size H).\nC\nC           WK = Real work array used by routine DATV and PSOL.\nC\nC           DL = Real work array used for calculation of the residual\nC                norm RHO when the method is incomplete (KMP.LT.MAXL)\nC                and/or when using restarting.\nC\nC           WP = Real work array used by preconditioner PSOL.\nC\nC          IWP = Integer work array used by preconditioner PSOL.\nC\nC         IRST = Method flag indicating if restarting is being\nC                performed.  IRST .GT. 0 means restarting is active,\nC                while IRST = 0 means restarting is not being used.\nC\nC        NRSTS = Counter for the number of restarts on the current\nC                call to DSPIGM.  If NRSTS .GT. 0, then the residual\nC                R is already scaled, and so scaling of R is not\nC                necessary.\nC\nC\nC      On Return\nC\nC         Z    = The final computed approximation to the solution\nC                of the system A*Z = R.\nC\nC         LGMR = The number of iterations performed and\nC                the current order of the upper Hessenberg\nC                matrix HES.\nC\nC         NRE  = The number of calls to RES (i.e. DATV)\nC\nC         NPSL = The number of calls to PSOL.\nC\nC         V    = The neq by (LGMR+1) array containing the LGMR\nC                orthogonal vectors V(*,1) to V(*,LGMR).\nC\nC         HES  = The upper triangular factor of the QR decomposition\nC                of the (LGMR+1) by LGMR upper Hessenberg matrix whose\nC                entries are the scaled inner-products of A*V(*,I)\nC                and V(*,K).\nC\nC         Q    = Real array of length 2*MAXL containing the components\nC                of the givens rotations used in the QR decomposition\nC                of HES.  It is loaded in DHEQR and used in DHELS.\nC\nC         IRES = Error flag from RES.\nC\nC           DL = Scaled preconditioned residual,\nC                (D-inverse)*(P-inverse)*(R-A*Z). Only loaded when\nC                performing restarts of the Krylov iteration.\nC\nC         RHOK = Weighted norm of final preconditioned residual.\nC\nC        IFLAG = Integer error flag..\nC                0 Means convergence in LGMR iterations, LGMR.LE.MAXL.\nC                1 Means the convergence test did not pass in MAXL\nC                  iterations, but the new residual norm (RHO) is\nC                  .LT. the old residual norm (RNRM), and so Z is\nC                  computed.\nC                2 Means the convergence test did not pass in MAXL\nC                  iterations, new residual norm (RHO) .GE. old residual\nC                  norm (RNRM), and the initial guess, Z = 0, is\nC                  returned.\nC                3 Means there was a recoverable error in PSOL\nC                  caused by the preconditioner being out of date.\nC               -1 Means there was an unrecoverable error in PSOL.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED\nC   PSOL, DNRM2, DSCAL, DATV, DORTH, DHEQR, DCOPY, DHELS, DAXPY\nC\nC***END PROLOGUE  DSPIGM\nC\n      INTEGER NEQ,MAXL,MAXLP1,KMP,IRES,NRE,NPSL,LGMR,IWP,\n     1   IFLAG,IRST,NRSTS,IPAR\n      DOUBLE PRECISION TN,Y,YPRIME,SAVR,R,WGHT,EPLIN,CJ,Z,V,HES,Q,WP,WK,\n     1   DL,RHOK,RPAR\n      DIMENSION Y(*), YPRIME(*), SAVR(*), R(*), WGHT(*), Z(*),\n     1   V(NEQ,*), HES(MAXLP1,*), Q(*), WP(*), IWP(*), WK(*), DL(*),\n     2   RPAR(*), IPAR(*)\n      INTEGER I, IER, INFO, IP1, I2, J, K, LL, LLP1\n      DOUBLE PRECISION RNRM,C,DLNRM,PROD,RHO,S,SNORMW,DNRM2,TEM\n      EXTERNAL  RES, PSOL\nC\n      IER = 0\n      IFLAG = 0\n      LGMR = 0\n      NPSL = 0\n      NRE = 0\nC-----------------------------------------------------------------------\nC The initial guess for Z is 0.  The initial residual is therefore\nC the vector R.  Initialize Z to 0.\nC-----------------------------------------------------------------------\n      DO 10 I = 1,NEQ\n 10     Z(I) = 0.0D0\nC-----------------------------------------------------------------------\nC Apply inverse of left preconditioner to vector R if NRSTS .EQ. 0.\nC Form V(*,1), the scaled preconditioned right hand side.\nC-----------------------------------------------------------------------\n      IF (NRSTS .EQ. 0) THEN\n         CALL PSOL (NEQ, TN, Y, YPRIME, SAVR, WK, CJ, WGHT, WP, IWP,\n     1      R, EPLIN, IER, RPAR, IPAR)\n         NPSL = 1\n         IF (IER .NE. 0) GO TO 300\n         DO 30 I = 1,NEQ\n 30         V(I,1) = R(I)*WGHT(I)\n      ELSE\n         DO 35 I = 1,NEQ\n 35         V(I,1) = R(I)\n      ENDIF\nC-----------------------------------------------------------------------\nC Calculate norm of scaled vector V(*,1) and normalize it\nC If, however, the norm of V(*,1) (i.e. the norm of the preconditioned\nC residual) is .le. EPLIN, then return with Z=0.\nC-----------------------------------------------------------------------\n      RNRM = DNRM2 (NEQ, V, 1)\n      IF (RNRM .LE. EPLIN) THEN\n        RHOK = RNRM\n        RETURN\n        ENDIF\n      TEM = 1.0D0/RNRM\n      CALL DSCAL (NEQ, TEM, V(1,1), 1)\nC-----------------------------------------------------------------------\nC Zero out the HES array.\nC-----------------------------------------------------------------------\n      DO 65 J = 1,MAXL\n        DO 60 I = 1,MAXLP1\n 60       HES(I,J) = 0.0D0\n 65     CONTINUE\nC-----------------------------------------------------------------------\nC Main loop to compute the vectors V(*,2) to V(*,MAXL).\nC The running product PROD is needed for the convergence test.\nC-----------------------------------------------------------------------\n      PROD = 1.0D0\n      DO 90 LL = 1,MAXL\n        LGMR = LL\nC-----------------------------------------------------------------------\nC Call routine DATV to compute VNEW = ABAR*V(LL), where ABAR is\nC the matrix A with scaling and inverse preconditioner factors applied.\nC Call routine DORTH to orthogonalize the new vector VNEW = V(*,LL+1).\nC call routine DHEQR to update the factors of HES.\nC-----------------------------------------------------------------------\n        CALL DATV (NEQ, Y, TN, YPRIME, SAVR, V(1,LL), WGHT, Z,\n     1     RES, IRES, PSOL, V(1,LL+1), WK, WP, IWP, CJ, EPLIN,\n     1     IER, NRE, NPSL, RPAR, IPAR)\n        IF (IRES .LT. 0) RETURN\n        IF (IER .NE. 0) GO TO 300\n        CALL DORTH (V(1,LL+1), V, HES, NEQ, LL, MAXLP1, KMP, SNORMW)\n        HES(LL+1,LL) = SNORMW\n        CALL DHEQR (HES, MAXLP1, LL, Q, INFO, LL)\n        IF (INFO .EQ. LL) GO TO 120\nC-----------------------------------------------------------------------\nC Update RHO, the estimate of the norm of the residual R - A*ZL.\nC If KMP .LT. MAXL, then the vectors V(*,1),...,V(*,LL+1) are not\nC necessarily orthogonal for LL .GT. KMP.  The vector DL must then\nC be computed, and its norm used in the calculation of RHO.\nC-----------------------------------------------------------------------\n        PROD = PROD*Q(2*LL)\n        RHO = ABS(PROD*RNRM)\n        IF ((LL.GT.KMP) .AND. (KMP.LT.MAXL)) THEN\n          IF (LL .EQ. KMP+1) THEN\n            CALL DCOPY (NEQ, V(1,1), 1, DL, 1)\n            DO 75 I = 1,KMP\n              IP1 = I + 1\n              I2 = I*2\n              S = Q(I2)\n              C = Q(I2-1)\n              DO 70 K = 1,NEQ\n 70             DL(K) = S*DL(K) + C*V(K,IP1)\n 75           CONTINUE\n            ENDIF\n          S = Q(2*LL)\n          C = Q(2*LL-1)/SNORMW\n          LLP1 = LL + 1\n          DO 80 K = 1,NEQ\n 80         DL(K) = S*DL(K) + C*V(K,LLP1)\n          DLNRM = DNRM2 (NEQ, DL, 1)\n          RHO = RHO*DLNRM\n          ENDIF\nC-----------------------------------------------------------------------\nC Test for convergence.  If passed, compute approximation ZL.\nC If failed and LL .LT. MAXL, then continue iterating.\nC-----------------------------------------------------------------------\n        IF (RHO .LE. EPLIN) GO TO 200\n        IF (LL .EQ. MAXL) GO TO 100\nC-----------------------------------------------------------------------\nC Rescale so that the norm of V(1,LL+1) is one.\nC-----------------------------------------------------------------------\n        TEM = 1.0D0/SNORMW\n        CALL DSCAL (NEQ, TEM, V(1,LL+1), 1)\n 90     CONTINUE\n 100  CONTINUE\n      IF (RHO .LT. RNRM) GO TO 150\n 120  CONTINUE\n      IFLAG = 2\n      DO 130 I = 1,NEQ\n 130     Z(I) = 0.D0\n      RETURN\n 150  IFLAG = 1\nC-----------------------------------------------------------------------\nC The tolerance was not met, but the residual norm was reduced.\nC If performing restarting (IRST .gt. 0) calculate the residual vector\nC RL and store it in the DL array.  If the incomplete version is\nC being used (KMP .lt. MAXL) then DL has already been calculated.\nC-----------------------------------------------------------------------\n      IF (IRST .GT. 0) THEN\n         IF (KMP .EQ. MAXL) THEN\nC\nC           Calculate DL from the V(I)'s.\nC\n            CALL DCOPY (NEQ, V(1,1), 1, DL, 1)\n            MAXLM1 = MAXL - 1\n            DO 175 I = 1,MAXLM1\n               IP1 = I + 1\n               I2 = I*2\n               S = Q(I2)\n               C = Q(I2-1)\n               DO 170 K = 1,NEQ\n 170              DL(K) = S*DL(K) + C*V(K,IP1)\n 175        CONTINUE\n            S = Q(2*MAXL)\n            C = Q(2*MAXL-1)/SNORMW\n            DO 180 K = 1,NEQ\n 180           DL(K) = S*DL(K) + C*V(K,MAXLP1)\n         ENDIF\nC\nC        Scale DL by RNRM*PROD to obtain the residual RL.\nC\n         TEM = RNRM*PROD\n         CALL DSCAL(NEQ, TEM, DL, 1)\n      ENDIF\nC-----------------------------------------------------------------------\nC Compute the approximation ZL to the solution.\nC Since the vector Z was used as work space, and the initial guess\nC of the Newton correction is zero, Z must be reset to zero.\nC-----------------------------------------------------------------------\n 200  CONTINUE\n      LL = LGMR\n      LLP1 = LL + 1\n      DO 210 K = 1,LLP1\n 210    R(K) = 0.0D0\n      R(1) = RNRM\n      CALL DHELS (HES, MAXLP1, LL, Q, R)\n      DO 220 K = 1,NEQ\n 220    Z(K) = 0.0D0\n      DO 230 I = 1,LL\n        CALL DAXPY (NEQ, R(I), V(1,I), 1, Z, 1)\n 230    CONTINUE\n      DO 240 I = 1,NEQ\n 240    Z(I) = Z(I)/WGHT(I)\nC Load RHO into RHOK.\n      RHOK = RHO\n      RETURN\nC-----------------------------------------------------------------------\nC This block handles error returns forced by routine PSOL.\nC-----------------------------------------------------------------------\n 300  CONTINUE\n      IF (IER .LT. 0) IFLAG = -1\n      IF (IER .GT. 0) IFLAG = 3\nC\n      RETURN\nC\nC------END OF SUBROUTINE DSPIGM-----------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/dyypnw.f",
    "content": "C Work performed under the auspices of the U.S. Department of Energy\nC by Lawrence Livermore National Laboratory under contract number\nC W-7405-Eng-48.\nC\n      SUBROUTINE DYYPNW (NEQ, Y, YPRIME, CJ, RL, P, ICOPT, ID,\n     *                   YNEW, YPNEW)\nC\nC***BEGIN PROLOGUE  DYYPNW\nC***REFER TO  DLINSK\nC***DATE WRITTEN   940830   (YYMMDD)\nC\nC\nC-----------------------------------------------------------------------\nC***DESCRIPTION\nC\nC     DYYPNW calculates the new (Y,YPRIME) pair needed in the\nC     linesearch algorithm based on the current lambda value.  It is\nC     called by DLINSK and DLINSD.  Based on the ICOPT and ID values,\nC     the corresponding entry in Y or YPRIME is updated.\nC\nC     In addition to the parameters described in the calling programs,\nC     the parameters represent\nC\nC     P      -- Array of length NEQ that contains the current\nC               approximate Newton step.\nC     RL     -- Scalar containing the current lambda value.\nC     YNEW   -- Array of length NEQ containing the updated Y vector.\nC     YPNEW  -- Array of length NEQ containing the updated YPRIME\nC               vector.\nC-----------------------------------------------------------------------\nC\nC***ROUTINES CALLED (NONE)\nC\nC***END PROLOGUE  DYYPNW\nC\nC\n      IMPLICIT DOUBLE PRECISION (A-H,O-Z)\n      DIMENSION Y(*), YPRIME(*), YNEW(*), YPNEW(*), ID(*), P(*)\nC\n      IF (ICOPT .EQ. 1) THEN\n         DO 10 I=1,NEQ\n            IF(ID(I) .LT. 0) THEN\n               YNEW(I) = Y(I) - RL*P(I)\n               YPNEW(I) = YPRIME(I)\n            ELSE\n               YNEW(I) = Y(I)\n               YPNEW(I) = YPRIME(I) - RL*CJ*P(I)\n            ENDIF\n 10      CONTINUE\n      ELSE\n         DO 20 I = 1,NEQ\n            YNEW(I) = Y(I) - RL*P(I)\n            YPNEW(I) = YPRIME(I)\n 20      CONTINUE\n      ENDIF\n      RETURN\nC----------------------- END OF SUBROUTINE DYYPNW ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/daspk/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/datv.f \\\n  %reldir%/dcnst0.f \\\n  %reldir%/dcnstr.f \\\n  %reldir%/ddasic.f \\\n  %reldir%/ddasid.f \\\n  %reldir%/ddasik.f \\\n  %reldir%/ddaspk.f \\\n  %reldir%/ddstp.f \\\n  %reldir%/ddwnrm.f \\\n  %reldir%/dfnrmd.f \\\n  %reldir%/dfnrmk.f \\\n  %reldir%/dhels.f \\\n  %reldir%/dheqr.f \\\n  %reldir%/dinvwt.f \\\n  %reldir%/dlinsd.f \\\n  %reldir%/dlinsk.f \\\n  %reldir%/dmatd.f \\\n  %reldir%/dnedd.f \\\n  %reldir%/dnedk.f \\\n  %reldir%/dnsd.f \\\n  %reldir%/dnsid.f \\\n  %reldir%/dnsik.f \\\n  %reldir%/dnsk.f \\\n  %reldir%/dorth.f \\\n  %reldir%/dslvd.f \\\n  %reldir%/dslvk.f \\\n  %reldir%/dspigm.f \\\n  %reldir%/dyypnw.f\n"
  },
  {
    "path": "liboctave/external/dasrt/ddasrt.f",
    "content": "      SUBROUTINE DDASRT (RES,NEQ,T,Y,YPRIME,TOUT,\n     *  INFO,RTOL,ATOL,IDID,RWORK,LRW,IWORK,LIW,RPAR,IPAR,JAC,\n     *  G,NG,JROOT)\nC\nC***BEGIN PROLOGUE  DDASRT\nC***DATE WRITTEN   821001   (YYMMDD)\nC***REVISION DATE  910624   (YYMMDD)\nC***KEYWORDS  DIFFERENTIAL/ALGEBRAIC,BACKWARD DIFFERENTIATION FORMULAS\nC             IMPLICIT DIFFERENTIAL SYSTEMS\nC***AUTHOR  PETZOLD,LINDA R.,COMPUTING AND MATHEMATICS RESEARCH DIVISION\nC             LAWRENCE LIVERMORE NATIONAL LABORATORY\nC             L - 316, P.O. Box 808,\nC             LIVERMORE, CA.    94550\nC***PURPOSE  This code solves a system of differential/algebraic\nC            equations of the form F(T,Y,YPRIME) = 0.\nC***DESCRIPTION\nC\nC *Usage:\nC\nC      IMPLICIT DOUBLE PRECISION (A-H,O-Z)\nC      EXTERNAL RES, JAC, G\nC      INTEGER NEQ, INFO(N), IDID, LRW, LIW, IWORK(LIW), IPAR, NG,\nC     *   JROOT(NG)\nC      DOUBLE PRECISION T, Y(NEQ), YPRIME(NEQ), TOUT, RTOL, ATOL,\nC     *   RWORK(LRW), RPAR\nC\nC      CALL DDASRT (RES, NEQ, T, Y, YPRIME, TOUT, INFO, RTOL, ATOL,\nC     *   IDID, RWORK, LRW, IWORK, LIW, RPAR, IPAR, JAC)\nC\nC\nC\nC *Arguments:\nC\nC  RES:EXT  This is a subroutine which you provide to define the\nC           differential/algebraic system.\nC\nC  NEQ:IN  This is the number of equations to be solved.\nC\nC  T:INOUT  This is the current value of the independent variable.\nC\nC  Y(*):INOUT  This array contains the solution components at T.\nC\nC  YPRIME(*):INOUT  This array contains the derivatives of the solution\nC                   components at T.\nC\nC  TOUT:IN  This is a point at which a solution is desired.\nC\nC  INFO(N):IN  The basic task of the code is to solve the system from T\nC              to TOUT and return an answer at TOUT.  INFO is an integer\nC              array which is used to communicate exactly how you want\nC              this task to be carried out.  N must be greater than or\nC              equal to 15.\nC\nC  RTOL,ATOL:INOUT  These quantities represent absolute and relative\nC                   error tolerances which you provide to indicate how\nC                   accurately you wish the solution to be computed.\nC                   You may choose them to be both scalars or else\nC                   both vectors.\nC\nC  IDID:OUT  This scalar quantity is an indicator reporting what the\nC            code did.  You must monitor this integer variable to decide\nC            what action to take next.\nC\nC  RWORK:WORK  A real work array of length LRW which provides the\nC               code with needed storage space.\nC\nC  LRW:IN  The length of RWORK.\nC\nC  IWORK:WORK  An integer work array of length LIW which probides the\nC               code with needed storage space.\nC\nC  LIW:IN  The length of IWORK.\nC\nC  RPAR,IPAR:IN  These are real and integer parameter arrays which\nC                you can use for communication between your calling\nC                program and the RES subroutine (and the JAC subroutine)\nC\nC  JAC:EXT  This is the name of a subroutine which you may choose to\nC           provide for defining a matrix of partial derivatives\nC           described below.\nC\nC  G  This is the name of the subroutine for defining\nC     constraint functions, G(T,Y), whose roots are desired\nC     during the integration.  This name must be declared\nC     external in the calling program.\nC\nC  NG  This is the number of constraint functions G(I).\nC      If there are none, set NG=0, and pass a dummy name\nC      for G.\nC\nC  JROOT  This is an integer array of length NG for output\nC         of root information.\nC\nC\nC *Description\nC\nC  QUANTITIES WHICH MAY BE ALTERED BY THE CODE ARE\nC     T,Y(*),YPRIME(*),INFO(1),RTOL,ATOL,\nC     IDID,RWORK(*) AND IWORK(*).\nC\nC  Subroutine DDASRT uses the backward differentiation formulas of\nC  orders one through five to solve a system of the above form for Y and\nC  YPRIME.  Values for Y and YPRIME at the initial time must be given as\nC  input.  These values must be consistent, (that is, if T,Y,YPRIME are\nC  the given initial values, they must satisfy F(T,Y,YPRIME) = 0.).  The\nC  subroutine solves the system from T to TOUT.\nC  It is easy to continue the solution to get results at additional\nC  TOUT.  This is the interval mode of operation.  Intermediate results\nC  can also be obtained easily by using the intermediate-output\nC  capability.  If DDASRT detects a sign-change in G(T,Y), then\nC  it will return the intermediate value of T and Y for which\nC  G(T,Y) = 0.\nC\nC  ---------INPUT-WHAT TO DO ON THE FIRST CALL TO DDASRT---------------\nC\nC\nC  The first call of the code is defined to be the start of each new\nC  problem. Read through the descriptions of all the following items,\nC  provide sufficient storage space for designated arrays, set\nC  appropriate variables for the initialization of the problem, and\nC  give information about how you want the problem to be solved.\nC\nC\nC  RES -- Provide a subroutine of the form\nC             SUBROUTINE RES(T,Y,YPRIME,DELTA,IRES,RPAR,IPAR)\nC         to define the system of differential/algebraic\nC         equations which is to be solved. For the given values\nC         of T,Y and YPRIME, the subroutine should\nC         return the residual of the defferential/algebraic\nC         system\nC             DELTA = F(T,Y,YPRIME)\nC         (DELTA(*) is a vector of length NEQ which is\nC         output for RES.)\nC\nC         Subroutine RES must not alter T,Y or YPRIME.\nC         You must declare the name RES in an external\nC         statement in your program that calls DDASRT.\nC         You must dimension Y,YPRIME and DELTA in RES.\nC\nC         IRES is an integer flag which is always equal to\nC         zero on input. Subroutine RES should alter IRES\nC         only if it encounters an illegal value of Y or\nC         a stop condition. Set IRES = -1 if an input value\nC         is illegal, and DDASRT will try to solve the problem\nC         without getting IRES = -1. If IRES = -2, DDASRT\nC         will return control to the calling program\nC         with IDID = -11.\nC\nC         RPAR and IPAR are real and integer parameter arrays which\nC         you can use for communication between your calling program\nC         and subroutine RES. They are not altered by DDASRT. If you\nC         do not need RPAR or IPAR, ignore these parameters by treat-\nC         ing them as dummy arguments. If you do choose to use them,\nC         dimension them in your calling program and in RES as arrays\nC         of appropriate length.\nC\nC  NEQ -- Set it to the number of differential equations.\nC         (NEQ .GE. 1)\nC\nC  T -- Set it to the initial point of the integration.\nC       T must be defined as a variable.\nC\nC  Y(*) -- Set this vector to the initial values of the NEQ solution\nC          components at the initial point. You must dimension Y of\nC          length at least NEQ in your calling program.\nC\nC  YPRIME(*) -- Set this vector to the initial values of\nC               the NEQ first derivatives of the solution\nC               components at the initial point. You\nC               must dimension YPRIME at least NEQ\nC               in your calling program. If you do not\nC               know initial values of some of the solution\nC               components, see the explanation of INFO(11).\nC\nC  TOUT - Set it to the first point at which a solution\nC         is desired. You can not take TOUT = T.\nC         integration either forward in T (TOUT .GT. T) or\nC         backward in T (TOUT .LT. T) is permitted.\nC\nC         The code advances the solution from T to TOUT using\nC         step sizes which are automatically selected so as to\nC         achieve the desired accuracy. If you wish, the code will\nC         return with the solution and its derivative at\nC         intermediate steps (intermediate-output mode) so that\nC         you can monitor them, but you still must provide TOUT in\nC         accord with the basic aim of the code.\nC\nC         the first step taken by the code is a critical one\nC         because it must reflect how fast the solution changes near\nC         the initial point. The code automatically selects an\nC         initial step size which is practically always suitable for\nC         the problem. By using the fact that the code will not step\nC         past TOUT in the first step, you could, if necessary,\nC         restrict the length of the initial step size.\nC\nC         For some problems it may not be permissable to integrate\nC         past a point TSTOP because a discontinuity occurs there\nC         or the solution or its derivative is not defined beyond\nC         TSTOP. When you have declared a TSTOP point (SEE INFO(4)\nC         and RWORK(1)), you have told the code not to integrate\nC         past TSTOP. In this case any TOUT beyond TSTOP is invalid\nC         input.\nC\nC  INFO(*) - Use the INFO array to give the code more details about\nC            how you want your problem solved. This array should be\nC            dimensioned of length 15, though DDASRT uses\nC            only the first twelve entries. You must respond to all of\nC            the following items which are arranged as questions. The\nC            simplest use of the code corresponds to answering all\nC            questions as yes, i.e. setting all entries of INFO to 0.\nC\nC       INFO(1) - This parameter enables the code to initialize\nC              itself. You must set it to indicate the start of every\nC              new problem.\nC\nC          **** Is this the first call for this problem ...\nC                Yes - Set INFO(1) = 0\nC                 No - Not applicable here.\nC                      See below for continuation calls.  ****\nC\nC       INFO(2) - How much accuracy you want of your solution\nC              is specified by the error tolerances RTOL and ATOL.\nC              The simplest use is to take them both to be scalars.\nC              To obtain more flexibility, they can both be vectors.\nC              The code must be told your choice.\nC\nC          **** Are both error tolerances RTOL, ATOL scalars ...\nC                Yes - Set INFO(2) = 0\nC                      and input scalars for both RTOL and ATOL\nC                 No - Set INFO(2) = 1\nC                      and input arrays for both RTOL and ATOL ****\nC\nC       INFO(3) - The code integrates from T in the direction\nC              of TOUT by steps. If you wish, it will return the\nC              computed solution and derivative at the next\nC              intermediate step (the intermediate-output mode) or\nC              TOUT, whichever comes first. This is a good way to\nC              proceed if you want to see the behavior of the solution.\nC              If you must have solutions at a great many specific\nC              TOUT points, this code will compute them efficiently.\nC\nC          **** Do you want the solution only at\nC                TOUT (and not at the next intermediate step) ...\nC                 Yes - Set INFO(3) = 0\nC                  No - Set INFO(3) = 1 ****\nC\nC       INFO(4) - To handle solutions at a great many specific\nC              values TOUT efficiently, this code may integrate past\nC              TOUT and interpolate to obtain the result at TOUT.\nC              Sometimes it is not possible to integrate beyond some\nC              point TSTOP because the equation changes there or it is\nC              not defined past TSTOP. Then you must tell the code\nC              not to go past.\nC\nC           **** Can the integration be carried out without any\nC                restrictions on the independent variable T ...\nC                 Yes - Set INFO(4)=0\nC                  No - Set INFO(4)=1\nC                       and define the stopping point TSTOP by\nC                       setting RWORK(1)=TSTOP ****\nC\nC       INFO(5) - To solve differential/algebraic problems it is\nC              necessary to use a matrix of partial derivatives of the\nC              system of differential equations. If you do not\nC              provide a subroutine to evaluate it analytically (see\nC              description of the item JAC in the call list), it will\nC              be approximated by numerical differencing in this code.\nC              although it is less trouble for you to have the code\nC              compute partial derivatives by numerical differencing,\nC              the solution will be more reliable if you provide the\nC              derivatives via JAC. Sometimes numerical differencing\nC              is cheaper than evaluating derivatives in JAC and\nC              sometimes it is not - this depends on your problem.\nC\nC           **** Do you want the code to evaluate the partial\nC                derivatives automatically by numerical differences ...\nC                   Yes - Set INFO(5)=0\nC                    No - Set INFO(5)=1\nC                  and provide subroutine JAC for evaluating the\nC                  matrix of partial derivatives ****\nC\nC       INFO(6) - DDASRT will perform much better if the matrix of\nC              partial derivatives, DG/DY + CJ*DG/DYPRIME,\nC              (here CJ is a scalar determined by DDASRT)\nC              is banded and the code is told this. In this\nC              case, the storage needed will be greatly reduced,\nC              numerical differencing will be performed much cheaper,\nC              and a number of important algorithms will execute much\nC              faster. The differential equation is said to have\nC              half-bandwidths ML (lower) and MU (upper) if equation i\nC              involves only unknowns Y(J) with\nC                             I-ML .LE. J .LE. I+MU\nC              for all I=1,2,...,NEQ. Thus, ML and MU are the widths\nC              of the lower and upper parts of the band, respectively,\nC              with the main diagonal being excluded. If you do not\nC              indicate that the equation has a banded matrix of partial\nC              derivatives, the code works with a full matrix of NEQ**2\nC              elements (stored in the conventional way). Computations\nC              with banded matrices cost less time and storage than with\nC              full matrices if 2*ML+MU .LT. NEQ. If you tell the\nC              code that the matrix of partial derivatives has a banded\nC              structure and you want to provide subroutine JAC to\nC              compute the partial derivatives, then you must be careful\nC              to store the elements of the matrix in the special form\nC              indicated in the description of JAC.\nC\nC          **** Do you want to solve the problem using a full\nC               (dense) matrix (and not a special banded\nC               structure) ...\nC                Yes - Set INFO(6)=0\nC                 No - Set INFO(6)=1\nC                       and provide the lower (ML) and upper (MU)\nC                       bandwidths by setting\nC                       IWORK(1)=ML\nC                       IWORK(2)=MU ****\nC\nC\nC        INFO(7) -- You can specify a maximum (absolute value of)\nC              stepsize, so that the code\nC              will avoid passing over very\nC              large regions.\nC\nC          ****  Do you want the code to decide\nC                on its own maximum stepsize?\nC                Yes - Set INFO(7)=0\nC                 No - Set INFO(7)=1\nC                      and define HMAX by setting\nC                      RWORK(2)=HMAX ****\nC\nC        INFO(8) -- Differential/algebraic problems\nC              may occaisionally suffer from\nC              severe scaling difficulties on the\nC              first step. If you know a great deal\nC              about the scaling of your problem, you can\nC              help to alleviate this problem by\nC              specifying an initial stepsize H0.\nC\nC          ****  Do you want the code to define\nC                its own initial stepsize?\nC                Yes - Set INFO(8)=0\nC                 No - Set INFO(8)=1\nC                      and define H0 by setting\nC                      RWORK(3)=H0 ****\nC\nC        INFO(9) -- If storage is a severe problem,\nC              you can save some locations by\nC              restricting the maximum order MAXORD.\nC              the default value is 5. for each\nC              order decrease below 5, the code\nC              requires NEQ fewer locations, however\nC              it is likely to be slower. In any\nC              case, you must have 1 .LE. MAXORD .LE. 5\nC          ****  Do you want the maximum order to\nC                default to 5?\nC                Yes - Set INFO(9)=0\nC                 No - Set INFO(9)=1\nC                      and define MAXORD by setting\nC                      IWORK(3)=MAXORD ****\nC\nC        INFO(10) --If you know that the solutions to your equations\nC               will always be nonnegative, it may help to set this\nC               parameter. However, it is probably best to\nC               try the code without using this option first,\nC               and only to use this option if that doesn't\nC               work very well.\nC           ****  Do you want the code to solve the problem without\nC                 invoking any special nonnegativity constraints?\nC                  Yes - Set INFO(10)=0\nC                   No - Set INFO(10)=1\nC\nC        INFO(11) --DDASRT normally requires the initial T,\nC               Y, and YPRIME to be consistent. That is,\nC               you must have F(T,Y,YPRIME) = 0 at the initial\nC               time. If you do not know the initial\nC               derivative precisely, you can let DDASRT try\nC               to compute it.\nC          ****   Are the initial T, Y, YPRIME consistent?\nC                 Yes - Set INFO(11) = 0\nC                  No - Set INFO(11) = 1,\nC                       and set YPRIME to an initial approximation\nC                       to YPRIME.  (If you have no idea what\nC                       YPRIME should be, set it to zero. Note\nC                       that the initial Y should be such\nC                       that there must exist a YPRIME so that\nC                       F(T,Y,YPRIME) = 0.)\nC\nC        INFO(12) --Maximum number of steps.\nC          ****   Do you want to let DDASRT use the default limit for\nC                 the number of steps?\nC                 Yes - Set INFO(12) = 0\nC                  No - Set INFO(12) = 1,\nC                       and define the maximum number of steps\nC                       by setting IWORK(21)=MXSTEP\nC\nC   RTOL, ATOL -- You must assign relative (RTOL) and absolute (ATOL\nC               error tolerances to tell the code how accurately you\nC               want the solution to be computed. They must be defined\nC               as variables because the code may change them. You\nC               have two choices --\nC                     Both RTOL and ATOL are scalars. (INFO(2)=0)\nC                     Both RTOL and ATOL are vectors. (INFO(2)=1)\nC               in either case all components must be non-negative.\nC\nC               The tolerances are used by the code in a local error\nC               test at each step which requires roughly that\nC                     ABS(LOCAL ERROR) .LE. RTOL*ABS(Y)+ATOL\nC               for each vector component.\nC               (More specifically, a root-mean-square norm is used to\nC               measure the size of vectors, and the error test uses the\nC               magnitude of the solution at the beginning of the step.)\nC\nC               The true (global) error is the difference between the\nC               true solution of the initial value problem and the\nC               computed approximation. Practically all present day\nC               codes, including this one, control the local error at\nC               each step and do not even attempt to control the global\nC               error directly.\nC               Usually, but not always, the true accuracy of the\nC               computed Y is comparable to the error tolerances. This\nC               code will usually, but not always, deliver a more\nC               accurate solution if you reduce the tolerances and\nC               integrate again. By comparing two such solutions you\nC               can get a fairly reliable idea of the true error in the\nC               solution at the bigger tolerances.\nC\nC               Setting ATOL=0. results in a pure relative error test on\nC               that component. Setting RTOL=0. results in a pure\nC               absolute error test on that component. A mixed test\nC               with non-zero RTOL and ATOL corresponds roughly to a\nC               relative error test when the solution component is much\nC               bigger than ATOL and to an absolute error test when the\nC               solution component is smaller than the threshhold ATOL.\nC\nC               The code will not attempt to compute a solution at an\nC               accuracy unreasonable for the machine being used. It\nC               will advise you if you ask for too much accuracy and\nC               inform you as to the maximum accuracy it believes\nC               possible.\nC\nC  RWORK(*) --  Dimension this real work array of length LRW in your\nC               calling program.\nC\nC  LRW -- Set it to the declared length of the RWORK array.\nC               You must have\nC                    LRW .GE. 50+(MAXORD+4)*NEQ+NEQ**2+3*NG\nC               for the full (dense) JACOBIAN case (when INFO(6)=0), or\nC                    LRW .GE. 50+(MAXORD+4)*NEQ+(2*ML+MU+1)*NEQ+3*NG\nC               for the banded user-defined JACOBIAN case\nC               (when INFO(5)=1 and INFO(6)=1), or\nC                     LRW .GE. 50+(MAXORD+4)*NEQ+(2*ML+MU+1)*NEQ\nC                           +2*(NEQ/(ML+MU+1)+1)+3*NG\nC               for the banded finite-difference-generated JACOBIAN case\nC               (when INFO(5)=0 and INFO(6)=1)\nC\nC  IWORK(*) --  Dimension this integer work array of length LIW in\nC               your calling program.\nC\nC  LIW -- Set it to the declared length of the IWORK array.\nC               you must have LIW .GE. 21+NEQ\nC\nC  RPAR, IPAR -- These are parameter arrays, of real and integer\nC               type, respectively. You can use them for communication\nC               between your program that calls DDASRT and the\nC               RES subroutine (and the JAC subroutine). They are not\nC               altered by DDASRT. If you do not need RPAR or IPAR,\nC               ignore these parameters by treating them as dummy\nC               arguments. If you do choose to use them, dimension\nC               them in your calling program and in RES (and in JAC)\nC               as arrays of appropriate length.\nC\nC  JAC -- If you have set INFO(5)=0, you can ignore this parameter\nC               by treating it as a dummy argument. Otherwise, you must\nC               provide a subroutine of the form\nC               JAC(T,Y,YPRIME,PD,CJ,RPAR,IPAR)\nC               to define the matrix of partial derivatives\nC               PD=DG/DY+CJ*DG/DYPRIME\nC               CJ is a scalar which is input to JAC.\nC               For the given values of T,Y,YPRIME, the\nC               subroutine must evaluate the non-zero partial\nC               derivatives for each equation and each solution\nC               component, and store these values in the\nC               matrix PD. The elements of PD are set to zero\nC               before each call to JAC so only non-zero elements\nC               need to be defined.\nC\nC               Subroutine JAC must not alter T,Y,(*),YPRIME(*), or CJ.\nC               You must declare the name JAC in an\nC               EXTERNAL STATEMENT in your program that calls\nC               DDASRT. You must dimension Y, YPRIME and PD\nC               in JAC.\nC\nC               The way you must store the elements into the PD matrix\nC               depends on the structure of the matrix which you\nC               indicated by INFO(6).\nC               *** INFO(6)=0 -- Full (dense) matrix ***\nC                   Give PD a first dimension of NEQ.\nC                   When you evaluate the (non-zero) partial derivative\nC                   of equation I with respect to variable J, you must\nC                   store it in PD according to\nC                   PD(I,J) = * DF(I)/DY(J)+CJ*DF(I)/DYPRIME(J)*\nC               *** INFO(6)=1 -- Banded JACOBIAN with ML lower and MU\nC                   upper diagonal bands (refer to INFO(6) description\nC                   of ML and MU) ***\nC                   Give PD a first dimension of 2*ML+MU+1.\nC                   when you evaluate the (non-zero) partial derivative\nC                   of equation I with respect to variable J, you must\nC                   store it in PD according to\nC                   IROW = I - J + ML + MU + 1\nC                   PD(IROW,J) = *DF(I)/DY(J)+CJ*DF(I)/DYPRIME(J)*\nC               RPAR and IPAR are real and integer parameter arrays\nC               which you can use for communication between your calling\nC               program and your JACOBIAN subroutine JAC. They are not\nC               altered by DDASRT. If you do not need RPAR or IPAR,\nC               ignore these parameters by treating them as dummy\nC               arguments. If you do choose to use them, dimension\nC               them in your calling program and in JAC as arrays of\nC               appropriate length.\nC\nC  G -- This is the name of the subroutine for defining constraint\nC               functions, whose roots are desired during the\nC               integration.  It is to have the form\nC                   SUBROUTINE G(NEQ,T,Y,NG,GOUT,RPAR,IPAR)\nC                   DIMENSION Y(NEQ),GOUT(NG),\nC               where NEQ, T, Y and NG are INPUT, and the array GOUT is\nC               output.  NEQ, T, and Y have the same meaning as in the\nC               RES routine, and GOUT is an array of length NG.\nC               For I=1,...,NG, this routine is to load into GOUT(I)\nC               the value at (T,Y) of the I-th constraint function G(I).\nC               DDASRT will find roots of the G(I) of odd multiplicity\nC               (that is, sign changes) as they occur during\nC               the integration.  G must be declared EXTERNAL in the\nC               calling program.\nC\nC               CAUTION..because of numerical errors in the functions\nC               G(I) due to roundoff and integration error, DDASRT\nC               may return false roots, or return the same root at two\nC               or more nearly equal values of T.  If such false roots\nC               are suspected, the user should consider smaller error\nC               tolerances and/or higher precision in the evaluation of\nC               the G(I).\nC\nC               If a root of some G(I) defines the end of the problem,\nC               the input to DDASRT should nevertheless allow\nC               integration to a point slightly past that ROOT, so\nC               that DDASRT can locate the root by interpolation.\nC\nC  NG -- The number of constraint functions G(I).  If there are none,\nC               set NG = 0, and pass a dummy name for G.\nC\nC JROOT -- This is an integer array of length NG.  It is used only for\nC               output.  On a return where one or more roots have been\nC               found, JROOT(I)=1 If G(I) has a root at T,\nC               or JROOT(I)=0 if not.\nC\nC\nC\nC  OPTIONALLY REPLACEABLE NORM ROUTINE:\nC  DDASRT uses a weighted norm DDANRM to measure the size\nC  of vectors such as the estimated error in each step.\nC  A FUNCTION subprogram\nC    DOUBLE PRECISION FUNCTION DDANRM(NEQ,V,WT,RPAR,IPAR)\nC    DIMENSION V(NEQ),WT(NEQ)\nC  is used to define this norm. Here, V is the vector\nC  whose norm is to be computed, and WT is a vector of\nC  weights.  A DDANRM routine has been included with DDASRT\nC  which computes the weighted root-mean-square norm\nC  given by\nC    DDANRM=SQRT((1/NEQ)*SUM(V(I)/WT(I))**2)\nC  this norm is suitable for most problems. In some\nC  special cases, it may be more convenient and/or\nC  efficient to define your own norm by writing a function\nC  subprogram to be called instead of DDANRM. This should\nC  ,however, be attempted only after careful thought and\nC  consideration.\nC\nC\nC------OUTPUT-AFTER ANY RETURN FROM DDASRT----\nC\nC  The principal aim of the code is to return a computed solution at\nC  TOUT, although it is also possible to obtain intermediate results\nC  along the way. To find out whether the code achieved its goal\nC  or if the integration process was interrupted before the task was\nC  completed, you must check the IDID parameter.\nC\nC\nC   T -- The solution was successfully advanced to the\nC               output value of T.\nC\nC   Y(*) -- Contains the computed solution approximation at T.\nC\nC   YPRIME(*) -- Contains the computed derivative\nC               approximation at T.\nC\nC   IDID -- Reports what the code did.\nC\nC                     *** Task completed ***\nC                Reported by positive values of IDID\nC\nC           IDID = 1 -- A step was successfully taken in the\nC                   intermediate-output mode. The code has not\nC                   yet reached TOUT.\nC\nC           IDID = 2 -- The integration to TSTOP was successfully\nC                   completed (T=TSTOP) by stepping exactly to TSTOP.\nC\nC           IDID = 3 -- The integration to TOUT was successfully\nC                   completed (T=TOUT) by stepping past TOUT.\nC                   Y(*) is obtained by interpolation.\nC                   YPRIME(*) is obtained by interpolation.\nC\nC           IDID = 4 -- The integration was successfully completed\nC                   by finding one or more roots of G at T.\nC\nC                    *** Task interrupted ***\nC                Reported by negative values of IDID\nC\nC           IDID = -1 -- A large amount of work has been expended.\nC                   (About INFO(12) steps)\nC\nC           IDID = -2 -- The error tolerances are too stringent.\nC\nC           IDID = -3 -- The local error test cannot be satisfied\nC                   because you specified a zero component in ATOL\nC                   and the corresponding computed solution\nC                   component is zero. Thus, a pure relative error\nC                   test is impossible for this component.\nC\nC           IDID = -6 -- DDASRT had repeated error test\nC                   failures on the last attempted step.\nC\nC           IDID = -7 -- The corrector could not converge.\nC\nC           IDID = -8 -- The matrix of partial derivatives\nC                   is singular.\nC\nC           IDID = -9 -- The corrector could not converge.\nC                   there were repeated error test failures\nC                   in this step.\nC\nC           IDID =-10 -- The corrector could not converge\nC                   because IRES was equal to minus one.\nC\nC           IDID =-11 -- IRES equal to -2 was encountered\nC                   and control is being returned to the\nC                   calling program.\nC\nC           IDID =-12 -- DDASRT failed to compute the initial\nC                   YPRIME.\nC\nC\nC\nC           IDID = -13,..,-32 -- Not applicable for this code\nC\nC                    *** Task terminated ***\nC                Reported by the value of IDID=-33\nC\nC           IDID = -33 -- The code has encountered trouble from which\nC                   it cannot recover. A message is printed\nC                   explaining the trouble and control is returned\nC                   to the calling program. For example, this occurs\nC                   when invalid input is detected.\nC\nC   RTOL, ATOL -- These quantities remain unchanged except when\nC               IDID = -2. In this case, the error tolerances have been\nC               increased by the code to values which are estimated to\nC               be appropriate for continuing the integration. However,\nC               the reported solution at T was obtained using the input\nC               values of RTOL and ATOL.\nC\nC   RWORK, IWORK -- Contain information which is usually of no\nC               interest to the user but necessary for subsequent calls.\nC               However, you may find use for\nC\nC               RWORK(3)--Which contains the step size H to be\nC                       attempted on the next step.\nC\nC               RWORK(4)--Which contains the current value of the\nC                       independent variable, i.e., the farthest point\nC                       integration has reached. This will be different\nC                       from T only when interpolation has been\nC                       performed (IDID=3).\nC\nC               RWORK(7)--Which contains the stepsize used\nC                       on the last successful step.\nC\nC               IWORK(7)--Which contains the order of the method to\nC                       be attempted on the next step.\nC\nC               IWORK(8)--Which contains the order of the method used\nC                       on the last step.\nC\nC               IWORK(11)--Which contains the number of steps taken so\nC                        far.\nC\nC               IWORK(12)--Which contains the number of calls to RES\nC                        so far.\nC\nC               IWORK(13)--Which contains the number of evaluations of\nC                        the matrix of partial derivatives needed so\nC                        far.\nC\nC               IWORK(14)--Which contains the total number\nC                        of error test failures so far.\nC\nC               IWORK(15)--Which contains the total number\nC                        of convergence test failures so far.\nC                        (includes singular iteration matrix\nC                        failures.)\nC\nC               IWORK(16)--Which contains the total number of calls\nC                        to the constraint function g so far\nC\nC\nC\nC   INPUT -- What to do to continue the integration\nC            (calls after the first)                **\nC\nC     This code is organized so that subsequent calls to continue the\nC     integration involve little (if any) additional effort on your\nC     part. You must monitor the IDID parameter in order to determine\nC     what to do next.\nC\nC     Recalling that the principal task of the code is to integrate\nC     from T to TOUT (the interval mode), usually all you will need\nC     to do is specify a new TOUT upon reaching the current TOUT.\nC\nC     Do not alter any quantity not specifically permitted below,\nC     in particular do not alter NEQ,T,Y(*),YPRIME(*),RWORK(*),IWORK(*)\nC     or the differential equation in subroutine RES. Any such\nC     alteration constitutes a new problem and must be treated as such,\nC     i.e., you must start afresh.\nC\nC     You cannot change from vector to scalar error control or vice\nC     versa (INFO(2)), but you can change the size of the entries of\nC     RTOL, ATOL. Increasing a tolerance makes the equation easier\nC     to integrate. Decreasing a tolerance will make the equation\nC     harder to integrate and should generally be avoided.\nC\nC     You can switch from the intermediate-output mode to the\nC     interval mode (INFO(3)) or vice versa at any time.\nC\nC     If it has been necessary to prevent the integration from going\nC     past a point TSTOP (INFO(4), RWORK(1)), keep in mind that the\nC     code will not integrate to any TOUT beyond the currently\nC     specified TSTOP. Once TSTOP has been reached you must change\nC     the value of TSTOP or set INFO(4)=0. You may change INFO(4)\nC     or TSTOP at any time but you must supply the value of TSTOP in\nC     RWORK(1) whenever you set INFO(4)=1.\nC\nC     Do not change INFO(5), INFO(6), IWORK(1), or IWORK(2)\nC     unless you are going to restart the code.\nC\nC                    *** Following a completed task ***\nC     If\nC     IDID = 1, call the code again to continue the integration\nC                  another step in the direction of TOUT.\nC\nC     IDID = 2 or 3, define a new TOUT and call the code again.\nC                  TOUT must be different from T. You cannot change\nC                  the direction of integration without restarting.\nC\nC     IDID = 4, call the code again to continue the integration\nC                  another step in the direction of TOUT.  You may\nC                  change the functions in G after a return with IDID=4,\nC                  but the number of constraint functions NG must remain\nC                  the same.  If you wish to change\nC                  the functions in RES or in G, then you\nC                  must restart the code.\nC\nC                    *** Following an interrupted task ***\nC                  To show the code that you realize the task was\nC                  interrupted and that you want to continue, you\nC                  must take appropriate action and set INFO(1) = 1\nC     If\nC     IDID = -1, The code has reached the step iteration.\nC                  If you want to continue, set INFO(1) = 1 and\nC                  call the code again.  See also INFO(12).\nC\nC     IDID = -2, The error tolerances RTOL, ATOL have been\nC                  increased to values the code estimates appropriate\nC                  for continuing. You may want to change them\nC                  yourself. If you are sure you want to continue\nC                  with relaxed error tolerances, set INFO(1)=1 and\nC                  call the code again.\nC\nC     IDID = -3, A solution component is zero and you set the\nC                  corresponding component of ATOL to zero. If you\nC                  are sure you want to continue, you must first\nC                  alter the error criterion to use positive values\nC                  for those components of ATOL corresponding to zero\nC                  solution components, then set INFO(1)=1 and call\nC                  the code again.\nC\nC     IDID = -4,-5  --- Cannot occur with this code.\nC\nC     IDID = -6, Repeated error test failures occurred on the\nC                  last attempted step in DDASRT. A singularity in the\nC                  solution may be present. If you are absolutely\nC                  certain you want to continue, you should restart\nC                  the integration. (Provide initial values of Y and\nC                  YPRIME which are consistent)\nC\nC     IDID = -7, Repeated convergence test failures occurred\nC                  on the last attempted step in DDASRT. An inaccurate\nC                  or ill-conditioned JACOBIAN may be the problem. If\nC                  you are absolutely certain you want to continue, you\nC                  should restart the integration.\nC\nC     IDID = -8, The matrix of partial derivatives is singular.\nC                  Some of your equations may be redundant.\nC                  DDASRT cannot solve the problem as stated.\nC                  It is possible that the redundant equations\nC                  could be removed, and then DDASRT could\nC                  solve the problem. It is also possible\nC                  that a solution to your problem either\nC                  does not exist or is not unique.\nC\nC     IDID = -9, DDASRT had multiple convergence test\nC                  failures, preceeded by multiple error\nC                  test failures, on the last attempted step.\nC                  It is possible that your problem\nC                  is ill-posed, and cannot be solved\nC                  using this code. Or, there may be a\nC                  discontinuity or a singularity in the\nC                  solution. If you are absolutely certain\nC                  you want to continue, you should restart\nC                  the integration.\nC\nC    IDID =-10, DDASRT had multiple convergence test failures\nC                  because IRES was equal to minus one.\nC                  If you are absolutely certain you want\nC                  to continue, you should restart the\nC                  integration.\nC\nC    IDID =-11, IRES=-2 was encountered, and control is being\nC                  returned to the calling program.\nC\nC    IDID =-12, DDASRT failed to compute the initial YPRIME.\nC               This could happen because the initial\nC               approximation to YPRIME was not very good, or\nC               if a YPRIME consistent with the initial Y\nC               does not exist. The problem could also be caused\nC               by an inaccurate or singular iteration matrix.\nC\nC\nC\nC     IDID = -13,..,-32 --- Cannot occur with this code.\nC\nC                       *** Following a terminated task ***\nC     If IDID= -33, you cannot continue the solution of this\nC                  problem. An attempt to do so will result in your\nC                  run being terminated.\nC\nC  ---------------------------------------------------------------------\nC\nC***REFERENCE\nC      K. E. Brenan, S. L. Campbell, and L. R. Petzold, Numerical\nC      Solution of Initial-Value Problems in Differential-Algebraic\nC      Equations, Elsevier, New York, 1989.\nC\nC***ROUTINES CALLED  DDASTP,DDAINI,DDANRM,DDAWTS,DDATRP,DRCHEK,DROOTS,\nC                    XERRWD,D1MACH\nC***END PROLOGUE  DDASRT\nC\nC**End\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      LOGICAL DONE\n      EXTERNAL RES, JAC, G\n      DIMENSION Y(*),YPRIME(*)\n      DIMENSION INFO(15)\n      DIMENSION RWORK(*),IWORK(*)\n      DIMENSION RTOL(*),ATOL(*)\n      DIMENSION RPAR(*),IPAR(*)\n      CHARACTER MSG*80\nC\nC     SET POINTERS INTO IWORK\n      PARAMETER (LML=1, LMU=2, LMXORD=3, LMTYPE=4, LNST=11,\n     *  LNRE=12, LNJE=13, LETF=14, LCTF=15, LNGE=16, LNPD=17,\n     *  LIRFND=18, LMXSTP=21, LIPVT=22, LJCALC=5, LPHASE=6, LK=7,\n     *  LKOLD=8, LNS=9, LNSTL=10, LIWM=1)\nC\nC     SET RELATIVE OFFSET INTO RWORK\n      PARAMETER (NPD=1)\nC\nC     SET POINTERS INTO RWORK\n      PARAMETER (LTSTOP=1, LHMAX=2, LH=3, LTN=4,\n     *  LCJ=5, LCJOLD=6, LHOLD=7, LS=8, LROUND=9,\n     *  LALPHA=11, LBETA=17, LGAMMA=23,\n     *  LPSI=29, LSIGMA=35, LT0=41, LTLAST=42, LALPHR=43, LX2=44,\n     *  LDELTA=51)\nC\nC***FIRST EXECUTABLE STATEMENT  DDASRT\n      IF(INFO(1).NE.0)GO TO 100\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK IS EXECUTED FOR THE INITIAL CALL ONLY.\nC     IT CONTAINS CHECKING OF INPUTS AND INITIALIZATIONS.\nC-----------------------------------------------------------------------\nC\nC     FIRST CHECK INFO ARRAY TO MAKE SURE ALL ELEMENTS OF INFO\nC     ARE EITHER ZERO OR ONE.\n      DO 10 I=2,12\n         IF(INFO(I).NE.0.AND.INFO(I).NE.1)GO TO 701\n10       CONTINUE\nC\n      IF(NEQ.LE.0)GO TO 702\nC\nC     CHECK AND COMPUTE MAXIMUM ORDER\n      MXORD=5\n      IF(INFO(9).EQ.0)GO TO 20\n         MXORD=IWORK(LMXORD)\n         IF(MXORD.LT.1.OR.MXORD.GT.5)GO TO 703\n20       IWORK(LMXORD)=MXORD\nC\nC     COMPUTE MTYPE,LENPD,LENRW.CHECK ML AND MU.\n      IF(INFO(6).NE.0)GO TO 40\n         LENPD=NEQ**2\n         LENRW=50+(IWORK(LMXORD)+4)*NEQ+LENPD+3*NG\n         IF(INFO(5).NE.0)GO TO 30\n            IWORK(LMTYPE)=2\n            GO TO 60\n30          IWORK(LMTYPE)=1\n            GO TO 60\n40    IF(IWORK(LML).LT.0.OR.IWORK(LML).GE.NEQ)GO TO 717\n      IF(IWORK(LMU).LT.0.OR.IWORK(LMU).GE.NEQ)GO TO 718\n      LENPD=(2*IWORK(LML)+IWORK(LMU)+1)*NEQ\n      IF(INFO(5).NE.0)GO TO 50\n         IWORK(LMTYPE)=5\n         MBAND=IWORK(LML)+IWORK(LMU)+1\n         MSAVE=(NEQ/MBAND)+1\n         LENRW=50+(IWORK(LMXORD)+4)*NEQ+LENPD+2*MSAVE+3*NG\n         GO TO 60\n50       IWORK(LMTYPE)=4\n         LENRW=50+(IWORK(LMXORD)+4)*NEQ+LENPD+3*NG\nC\nC     CHECK LENGTHS OF RWORK AND IWORK\n60    LENIW=21+NEQ\n      IWORK(LNPD)=LENPD\n      IF(LRW.LT.LENRW)GO TO 704\n      IF(LIW.LT.LENIW)GO TO 705\nC\nC     CHECK TO SEE THAT TOUT IS DIFFERENT FROM T\nC     Also check to see that NG is larger than 0.\n      IF(TOUT .EQ. T)GO TO 719\n      IF(NG .LT. 0) GO TO 730\nC\nC     CHECK HMAX\n      IF(INFO(7).EQ.0)GO TO 70\n         HMAX=RWORK(LHMAX)\n         IF(HMAX.LE.0.0D0)GO TO 710\n70    CONTINUE\nC\nC     CHECK AND COMPUTE MAXIMUM STEPS\n      MXSTP=500\n      IF(INFO(12).EQ.0)GO TO 80\n        MXSTP=IWORK(LMXSTP)\n        IF(MXSTP.LT.0)GO TO 716\n80      IWORK(LMXSTP)=MXSTP\nC\nC     INITIALIZE COUNTERS\n      IWORK(LNST)=0\n      IWORK(LNRE)=0\n      IWORK(LNJE)=0\n      IWORK(LNGE)=0\nC\n      IWORK(LNSTL)=0\n      IDID=1\n      GO TO 200\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK IS FOR CONTINUATION CALLS\nC     ONLY. HERE WE CHECK INFO(1),AND IF THE\nC     LAST STEP WAS INTERRUPTED WE CHECK WHETHER\nC     APPROPRIATE ACTION WAS TAKEN.\nC-----------------------------------------------------------------------\nC\n100   CONTINUE\n      IF(INFO(1).EQ.1)GO TO 110\n      IF(INFO(1).NE.-1)GO TO 701\nC     IF WE ARE HERE, THE LAST STEP WAS INTERRUPTED\nC     BY AN ERROR CONDITION FROM DDASTP,AND\nC     APPROPRIATE ACTION WAS NOT TAKEN. THIS\nC     IS A FATAL ERROR.\n      MSG = 'DASRT--  THE LAST STEP TERMINATED WITH A NEGATIVE'\n      CALL XERRWD(MSG,49,201,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASRT--  VALUE (=I1) OF IDID AND NO APPROPRIATE'\n      CALL XERRWD(MSG,47,202,0,1,IDID,0,0,0.0D0,0.0D0)\n      MSG = 'DASRT--  ACTION WAS TAKEN. RUN TERMINATED'\n      CALL XERRWD(MSG,41,203,1,0,0,0,0,0.0D0,0.0D0)\n      RETURN\n110   CONTINUE\n      IWORK(LNSTL)=IWORK(LNST)\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK IS EXECUTED ON ALL CALLS.\nC     THE ERROR TOLERANCE PARAMETERS ARE\nC     CHECKED, AND THE WORK ARRAY POINTERS\nC     ARE SET.\nC-----------------------------------------------------------------------\nC\n200   CONTINUE\nC     CHECK RTOL,ATOL\n      NZFLG=0\n      RTOLI=RTOL(1)\n      ATOLI=ATOL(1)\n      DO 210 I=1,NEQ\n         IF(INFO(2).EQ.1)RTOLI=RTOL(I)\n         IF(INFO(2).EQ.1)ATOLI=ATOL(I)\n         IF(RTOLI.GT.0.0D0.OR.ATOLI.GT.0.0D0)NZFLG=1\n         IF(RTOLI.LT.0.0D0)GO TO 706\n         IF(ATOLI.LT.0.0D0)GO TO 707\n210      CONTINUE\n      IF(NZFLG.EQ.0)GO TO 708\nC\nC     SET UP RWORK STORAGE.IWORK STORAGE IS FIXED\nC     IN DATA STATEMENT.\n      LG0=LDELTA+NEQ\n      LG1=LG0+NG\n      LGX=LG1+NG\n      LE=LGX+NG\n      LWT=LE+NEQ\n      LPHI=LWT+NEQ\n      LPD=LPHI+(IWORK(LMXORD)+1)*NEQ\n      LWM=LPD\n      NTEMP=NPD+IWORK(LNPD)\n      IF(INFO(1).EQ.1)GO TO 400\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK IS EXECUTED ON THE INITIAL CALL\nC     ONLY. SET THE INITIAL STEP SIZE, AND\nC     THE ERROR WEIGHT VECTOR, AND PHI.\nC     COMPUTE INITIAL YPRIME, IF NECESSARY.\nC-----------------------------------------------------------------------\nC\n300   CONTINUE\n      TN=T\n      IDID=1\nC\nC     SET ERROR WEIGHT VECTOR WT\n      CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,Y,RWORK(LWT),RPAR,IPAR)\n      DO 305 I = 1,NEQ\n         IF(RWORK(LWT+I-1).LE.0.0D0) GO TO 713\n305      CONTINUE\nC\nC     COMPUTE UNIT ROUNDOFF AND HMIN\n      UROUND = D1MACH(4)\n      RWORK(LROUND) = UROUND\n      HMIN = 4.0D0*UROUND*DMAX1(DABS(T),DABS(TOUT))\nC\nC     CHECK INITIAL INTERVAL TO SEE THAT IT IS LONG ENOUGH\n      TDIST = DABS(TOUT - T)\n      IF(TDIST .LT. HMIN) GO TO 714\nC\nC     CHECK H0, IF THIS WAS INPUT\n      IF (INFO(8) .EQ. 0) GO TO 310\n         HO = RWORK(LH)\n         IF ((TOUT - T)*HO .LT. 0.0D0) GO TO 711\n         IF (HO .EQ. 0.0D0) GO TO 712\n         GO TO 320\n310    CONTINUE\nC\nC     COMPUTE INITIAL STEPSIZE, TO BE USED BY EITHER\nC     DDASTP OR DDAINI, DEPENDING ON INFO(11)\n      HO = 0.001D0*TDIST\n      YPNORM = DDANRM(NEQ,YPRIME,RWORK(LWT),RPAR,IPAR)\n      IF (YPNORM .GT. 0.5D0/HO) HO = 0.5D0/YPNORM\n      HO = DSIGN(HO,TOUT-T)\nC     ADJUST HO IF NECESSARY TO MEET HMAX BOUND\n320   IF (INFO(7) .EQ. 0) GO TO 330\n         RH = DABS(HO)/RWORK(LHMAX)\n         IF (RH .GT. 1.0D0) HO = HO/RH\nC     COMPUTE TSTOP, IF APPLICABLE\n330   IF (INFO(4) .EQ. 0) GO TO 340\n         TSTOP = RWORK(LTSTOP)\n         IF ((TSTOP - T)*HO .LT. 0.0D0) GO TO 715\n         IF ((T + HO - TSTOP)*HO .GT. 0.0D0) HO = TSTOP - T\n         IF ((TSTOP - TOUT)*HO .LT. 0.0D0) GO TO 709\nC\nC     COMPUTE INITIAL DERIVATIVE, UPDATING TN AND Y, IF APPLICABLE\n340   IF (INFO(11) .EQ. 0) GO TO 350\n      CALL DDAINI(TN,Y,YPRIME,NEQ,\n     *  RES,JAC,HO,RWORK(LWT),IDID,RPAR,IPAR,\n     *  RWORK(LPHI),RWORK(LDELTA),RWORK(LE),\n     *  RWORK(LWM),IWORK(LIWM),HMIN,RWORK(LROUND),\n     *  INFO(10),NTEMP)\n      IF (IDID .LT. 0) GO TO 390\nC\nC     LOAD H WITH H0.  STORE H IN RWORK(LH)\n350   H = HO\n      RWORK(LH) = H\nC\nC     LOAD Y AND H*YPRIME INTO PHI(*,1) AND PHI(*,2)\n360   ITEMP = LPHI + NEQ\n      DO 370 I = 1,NEQ\n         RWORK(LPHI + I - 1) = Y(I)\n370      RWORK(ITEMP + I - 1) = H*YPRIME(I)\nC\nC     INITIALIZE T0 IN RWORK AND CHECK FOR A ZERO OF G NEAR THE\nC     INITIAL T.\nC\n      RWORK(LT0) = T\n      IWORK(LIRFND) = 0\n      RWORK(LPSI)=H\n      RWORK(LPSI+1)=2.0D0*H\n      IWORK(LKOLD)=1\n      IF(NG .EQ. 0) GO TO 390\n      CALL DRCHEK(1,G,NG,NEQ,T,TOUT,Y,RWORK(LE),RWORK(LPHI),\n     *  RWORK(LPSI),IWORK(LKOLD),RWORK(LG0),RWORK(LG1),\n     *  RWORK(LGX),JROOT,IRT,RWORK(LROUND),INFO(3),\n     *  RWORK,IWORK,RPAR,IPAR)\n      IF(IRT .NE. 0) GO TO 732\nC\nC     Check for a root in the interval (T0,TN], unless DDASRT\nC     did not have to initialize YPRIME.\nC\n      IF(NG .EQ. 0 .OR. INFO(11) .EQ. 0) GO TO 390\n      CALL DRCHEK(3,G,NG,NEQ,TN,TOUT,Y,RWORK(LE),RWORK(LPHI),\n     *  RWORK(LPSI),IWORK(LKOLD),RWORK(LG0),RWORK(LG1),\n     *  RWORK(LGX),JROOT,IRT,RWORK(LROUND),INFO(3),\n     *  RWORK,IWORK,RPAR,IPAR)\n      IF(IRT .NE. 1) GO TO 390\n      IWORK(LIRFND) = 1\n      IDID = 4\n      T = RWORK(LT0)\n      GO TO 580\nC\n390   GO TO 500\nC\nC-------------------------------------------------------\nC     THIS BLOCK IS FOR CONTINUATION CALLS ONLY. ITS\nC     PURPOSE IS TO CHECK STOP CONDITIONS BEFORE\nC     TAKING A STEP.\nC     ADJUST H IF NECESSARY TO MEET HMAX BOUND\nC-------------------------------------------------------\nC\n400   CONTINUE\n      UROUND=RWORK(LROUND)\n      DONE = .FALSE.\n      TN=RWORK(LTN)\n      H=RWORK(LH)\n      IF(NG .EQ. 0) GO TO 405\nC\nC     Check for a zero of G near TN.\nC\n      CALL DRCHEK(2,G,NG,NEQ,TN,TOUT,Y,RWORK(LE),RWORK(LPHI),\n     *  RWORK(LPSI),IWORK(LKOLD),RWORK(LG0),RWORK(LG1),\n     *  RWORK(LGX),JROOT,IRT,RWORK(LROUND),INFO(3),\n     *  RWORK,IWORK,RPAR,IPAR)\n      IF(IRT .NE. 1) GO TO 405\n      IWORK(LIRFND) = 1\n      IDID = 4\n      T = RWORK(LT0)\n      DONE = .TRUE.\n      GO TO 490\nC\n405   CONTINUE\n      IF(INFO(7) .EQ. 0) GO TO 410\n         RH = DABS(H)/RWORK(LHMAX)\n         IF(RH .GT. 1.0D0) H = H/RH\n410   CONTINUE\n      IF(T .EQ. TOUT) GO TO 719\n      IF((T - TOUT)*H .GT. 0.0D0) GO TO 711\n      IF(INFO(4) .EQ. 1) GO TO 430\n      IF(INFO(3) .EQ. 1) GO TO 420\n      IF((TN-TOUT)*H.LT.0.0D0)GO TO 490\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T=TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n420   IF((TN-T)*H .LE. 0.0D0) GO TO 490\n      IF((TN - TOUT)*H .GT. 0.0D0) GO TO 425\n      CALL DDATRP(TN,TN,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TN\n      IDID = 1\n      DONE = .TRUE.\n      GO TO 490\n425   CONTINUE\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n430   IF(INFO(3) .EQ. 1) GO TO 440\n      TSTOP=RWORK(LTSTOP)\n      IF((TN-TSTOP)*H.GT.0.0D0) GO TO 715\n      IF((TSTOP-TOUT)*H.LT.0.0D0)GO TO 709\n      IF((TN-TOUT)*H.LT.0.0D0)GO TO 450\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *   RWORK(LPHI),RWORK(LPSI))\n      T=TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n440   TSTOP = RWORK(LTSTOP)\n      IF((TN-TSTOP)*H .GT. 0.0D0) GO TO 715\n      IF((TSTOP-TOUT)*H .LT. 0.0D0) GO TO 709\n      IF((TN-T)*H .LE. 0.0D0) GO TO 450\n      IF((TN - TOUT)*H .GT. 0.0D0) GO TO 445\n      CALL DDATRP(TN,TN,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TN\n      IDID = 1\n      DONE = .TRUE.\n      GO TO 490\n445   CONTINUE\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n450   CONTINUE\nC     CHECK WHETHER WE ARE WITH IN ROUNDOFF OF TSTOP\n      IF(DABS(TN-TSTOP).GT.100.0D0*UROUND*\n     *   (DABS(TN)+DABS(H)))GO TO 460\n      CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      IDID=2\n      T=TSTOP\n      DONE = .TRUE.\n      GO TO 490\n460   TNEXT=TN+H\n      IF((TNEXT-TSTOP)*H.LE.0.0D0)GO TO 490\n      H=TSTOP-TN\n      RWORK(LH)=H\nC\n490   IF (DONE) GO TO 590\nC\nC-------------------------------------------------------\nC     THE NEXT BLOCK CONTAINS THE CALL TO THE\nC     ONE-STEP INTEGRATOR DDASTP.\nC     THIS IS A LOOPING POINT FOR THE INTEGRATION STEPS.\nC     CHECK FOR TOO MANY STEPS.\nC     UPDATE WT.\nC     CHECK FOR TOO MUCH ACCURACY REQUESTED.\nC     COMPUTE MINIMUM STEPSIZE.\nC-------------------------------------------------------\nC\n500   CONTINUE\nC     CHECK FOR FAILURE TO COMPUTE INITIAL YPRIME\n      IF (IDID .EQ. -12) GO TO 527\nC\nC     CHECK FOR TOO MANY STEPS\n      IF((IWORK(LNST)-IWORK(LNSTL)).LT.IWORK(LMXSTP))\n     *   GO TO 510\n           IDID=-1\n           GO TO 527\nC\nC     UPDATE WT\n510   CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,RWORK(LPHI),\n     *  RWORK(LWT),RPAR,IPAR)\n      DO 520 I=1,NEQ\n         IF(RWORK(I+LWT-1).GT.0.0D0)GO TO 520\n           IDID=-3\n           GO TO 527\n520   CONTINUE\nC\nC     TEST FOR TOO MUCH ACCURACY REQUESTED.\n      R=DDANRM(NEQ,RWORK(LPHI),RWORK(LWT),RPAR,IPAR)*\n     *   100.0D0*UROUND\n      IF(R.LE.1.0D0)GO TO 525\nC     MULTIPLY RTOL AND ATOL BY R AND RETURN\n      IF(INFO(2).EQ.1)GO TO 523\n           RTOL(1)=R*RTOL(1)\n           ATOL(1)=R*ATOL(1)\n           IDID=-2\n           GO TO 527\n523   DO 524 I=1,NEQ\n           RTOL(I)=R*RTOL(I)\n524        ATOL(I)=R*ATOL(I)\n      IDID=-2\n      GO TO 527\n525   CONTINUE\nC\nC     COMPUTE MINIMUM STEPSIZE\n      HMIN=4.0D0*UROUND*DMAX1(DABS(TN),DABS(TOUT))\nC\nC     TEST H VS. HMAX\n      IF (INFO(7) .EQ. 0) GO TO 526\n         RH = ABS(H)/RWORK(LHMAX)\n         IF (RH .GT. 1.0D0) H = H/RH\n526   CONTINUE\nC\n      CALL DDASTP(TN,Y,YPRIME,NEQ,\n     *   RES,JAC,H,RWORK(LWT),INFO(1),IDID,RPAR,IPAR,\n     *   RWORK(LPHI),RWORK(LDELTA),RWORK(LE),\n     *   RWORK(LWM),IWORK(LIWM),\n     *   RWORK(LALPHA),RWORK(LBETA),RWORK(LGAMMA),\n     *   RWORK(LPSI),RWORK(LSIGMA),\n     *   RWORK(LCJ),RWORK(LCJOLD),RWORK(LHOLD),\n     *   RWORK(LS),HMIN,RWORK(LROUND),\n     *   IWORK(LPHASE),IWORK(LJCALC),IWORK(LK),\n     *   IWORK(LKOLD),IWORK(LNS),INFO(10),NTEMP)\n527   IF(IDID.LT.0)GO TO 600\nC\nC--------------------------------------------------------\nC     THIS BLOCK HANDLES THE CASE OF A SUCCESSFUL RETURN\nC     FROM DDASTP (IDID=1).  TEST FOR STOP CONDITIONS.\nC--------------------------------------------------------\nC\n      IF(NG .EQ. 0) GO TO 529\nC\nC     Check for a zero of G near TN.\nC\n      CALL DRCHEK(3,G,NG,NEQ,TN,TOUT,Y,RWORK(LE),RWORK(LPHI),\n     *  RWORK(LPSI),IWORK(LKOLD),RWORK(LG0),RWORK(LG1),\n     *  RWORK(LGX),JROOT,IRT,RWORK(LROUND),INFO(3),\n     *  RWORK,IWORK,RPAR,IPAR)\n      IF(IRT .NE. 1) GO TO 529\n      IWORK(LIRFND) = 1\n      IDID = 4\n      T = RWORK(LT0)\n      GO TO 580\nC\n529   CONTINUE\n      IF(INFO(4).NE.0)GO TO 540\n           IF(INFO(3).NE.0)GO TO 530\n             IF((TN-TOUT)*H.LT.0.0D0)GO TO 500\n             CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *         IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n             IDID=3\n             T=TOUT\n             GO TO 580\n530          IF((TN-TOUT)*H.GE.0.0D0)GO TO 535\n             T=TN\n             IDID=1\n             GO TO 580\n535          CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *         IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n             IDID=3\n             T=TOUT\n             GO TO 580\n540   IF(INFO(3).NE.0)GO TO 550\n      IF((TN-TOUT)*H.LT.0.0D0)GO TO 542\n         CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *     IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n         T=TOUT\n         IDID=3\n         GO TO 580\n542   IF(DABS(TN-TSTOP).LE.100.0D0*UROUND*\n     *   (DABS(TN)+DABS(H)))GO TO 545\n      TNEXT=TN+H\n      IF((TNEXT-TSTOP)*H.LE.0.0D0)GO TO 500\n      H=TSTOP-TN\n      GO TO 500\n545   CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,\n     *  IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n      IDID=2\n      T=TSTOP\n      GO TO 580\n550   IF((TN-TOUT)*H.GE.0.0D0)GO TO 555\n      IF(DABS(TN-TSTOP).LE.100.0D0*UROUND*(DABS(TN)+DABS(H)))GO TO 552\n      T=TN\n      IDID=1\n      GO TO 580\n552   CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,\n     *  IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n      IDID=2\n      T=TSTOP\n      GO TO 580\n555   CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *   IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n      T=TOUT\n      IDID=3\n580   CONTINUE\nC\nC--------------------------------------------------------\nC     ALL SUCCESSFUL RETURNS FROM DDASRT ARE MADE FROM\nC     THIS BLOCK.\nC--------------------------------------------------------\nC\n590   CONTINUE\n      RWORK(LTN)=TN\n      RWORK(LH)=H\n      RWORK(LTLAST) = T\n      RETURN\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK HANDLES ALL UNSUCCESSFUL\nC     RETURNS OTHER THAN FOR ILLEGAL INPUT.\nC-----------------------------------------------------------------------\nC\n600   CONTINUE\n      ITEMP=-IDID\n      GO TO (610,620,630,690,690,640,650,660,670,675,\n     *  680,685), ITEMP\nC\nC     THE MAXIMUM NUMBER OF STEPS WAS TAKEN BEFORE\nC     REACHING TOUT\n610   MSG = 'DASRT--  AT CURRENT T (=R1)  500 STEPS'\n      CALL XERRWD(MSG,38,610,0,0,0,0,1,TN,0.0D0)\n      MSG = 'DASRT--  TAKEN ON THIS CALL BEFORE REACHING TOUT'\n      CALL XERRWD(MSG,48,611,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 690\nC\nC     TOO MUCH ACCURACY FOR MACHINE PRECISION\n620   MSG = 'DASRT--  AT T (=R1) TOO MUCH ACCURACY REQUESTED'\n      CALL XERRWD(MSG,47,620,0,0,0,0,1,TN,0.0D0)\n      MSG = 'DASRT--  FOR PRECISION OF MACHINE. RTOL AND ATOL'\n      CALL XERRWD(MSG,48,621,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASRT--  WERE INCREASED TO APPROPRIATE VALUES'\n      CALL XERRWD(MSG,45,622,0,0,0,0,0,0.0D0,0.0D0)\nC\n      GO TO 690\nC     WT(I) .LE. 0.0D0 FOR SOME I (NOT AT START OF PROBLEM)\n630   MSG = 'DASRT--  AT T (=R1) SOME ELEMENT OF WT'\n      CALL XERRWD(MSG,38,630,0,0,0,0,1,TN,0.0D0)\n      MSG = 'DASRT--  HAS BECOME .LE. 0.0'\n      CALL XERRWD(MSG,28,631,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 690\nC\nC     ERROR TEST FAILED REPEATEDLY OR WITH H=HMIN\n640   MSG = 'DASRT--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,640,0,0,0,0,2,TN,H)\n      MSG='DASRT--  ERROR TEST FAILED REPEATEDLY OR WITH ABS(H)=HMIN'\n      CALL XERRWD(MSG,57,641,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 690\nC\nC     CORRECTOR CONVERGENCE FAILED REPEATEDLY OR WITH H=HMIN\n650   MSG = 'DASRT--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,650,0,0,0,0,2,TN,H)\n      MSG = 'DASRT--  CORRECTOR FAILED TO CONVERGE REPEATEDLY'\n      CALL XERRWD(MSG,48,651,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASRT--  OR WITH ABS(H)=HMIN'\n      CALL XERRWD(MSG,28,652,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 690\nC\nC     THE ITERATION MATRIX IS SINGULAR\n660   MSG = 'DASRT--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,660,0,0,0,0,2,TN,H)\n      MSG = 'DASRT--  ITERATION MATRIX IS SINGULAR'\n      CALL XERRWD(MSG,37,661,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 690\nC\nC     CORRECTOR FAILURE PRECEEDED BY ERROR TEST FAILURES.\n670   MSG = 'DASRT--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,670,0,0,0,0,2,TN,H)\n      MSG = 'DASRT--  CORRECTOR COULD NOT CONVERGE.  ALSO, THE'\n      CALL XERRWD(MSG,49,671,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASRT--  ERROR TEST FAILED REPEATEDLY.'\n      CALL XERRWD(MSG,38,672,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 690\nC\nC     CORRECTOR FAILURE BECAUSE IRES = -1\n675   MSG = 'DASRT--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,675,0,0,0,0,2,TN,H)\n      MSG = 'DASRT--  CORRECTOR COULD NOT CONVERGE BECAUSE'\n      CALL XERRWD(MSG,45,676,0,0,0,0,0,0.0D0,0.0D0)\n      MSG = 'DASRT--  IRES WAS EQUAL TO MINUS ONE'\n      CALL XERRWD(MSG,36,677,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 690\nC\nC     FAILURE BECAUSE IRES = -2\n680   MSG = 'DASRT--  AT T (=R1) AND STEPSIZE H (=R2)'\n      CALL XERRWD(MSG,40,680,0,0,0,0,2,TN,H)\n      MSG = 'DASRT--  IRES WAS EQUAL TO MINUS TWO'\n      CALL XERRWD(MSG,36,681,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 690\nC\nC     FAILED TO COMPUTE INITIAL YPRIME\n685   MSG = 'DASRT--  AT T (=R1) AND STEPSIZE H (=R2) THE'\n      CALL XERRWD(MSG,44,685,0,0,0,0,2,TN,HO)\n      MSG = 'DASRT--  INITIAL YPRIME COULD NOT BE COMPUTED'\n      CALL XERRWD(MSG,45,686,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 690\n690   CONTINUE\n      INFO(1)=-1\n      T=TN\n      RWORK(LTN)=TN\n      RWORK(LH)=H\n      RETURN\nC-----------------------------------------------------------------------\nC     THIS BLOCK HANDLES ALL ERROR RETURNS DUE\nC     TO ILLEGAL INPUT, AS DETECTED BEFORE CALLING\nC     DDASTP. FIRST THE ERROR MESSAGE ROUTINE IS\nC     CALLED. IF THIS HAPPENS TWICE IN\nC     SUCCESSION, EXECUTION IS TERMINATED\nC\nC-----------------------------------------------------------------------\n701   MSG = 'DASRT--  SOME ELEMENT OF INFO VECTOR IS NOT ZERO OR ONE'\n      CALL XERRWD(MSG,55,1,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n702   MSG = 'DASRT--  NEQ (=I1) .LE. 0'\n      CALL XERRWD(MSG,25,2,0,1,NEQ,0,0,0.0D0,0.0D0)\n      GO TO 750\n703   MSG = 'DASRT--  MAXORD (=I1) NOT IN RANGE'\n      CALL XERRWD(MSG,34,3,0,1,MXORD,0,0,0.0D0,0.0D0)\n      GO TO 750\n704   MSG='DASRT--  RWORK LENGTH NEEDED, LENRW (=I1), EXCEEDS LRW (=I2)'\n      CALL XERRWD(MSG,60,4,0,2,LENRW,LRW,0,0.0D0,0.0D0)\n      GO TO 750\n705   MSG='DASRT--  IWORK LENGTH NEEDED, LENIW (=I1), EXCEEDS LIW (=I2)'\n      CALL XERRWD(MSG,60,5,0,2,LENIW,LIW,0,0.0D0,0.0D0)\n      GO TO 750\n706   MSG = 'DASRT--  SOME ELEMENT OF RTOL IS .LT. 0'\n      CALL XERRWD(MSG,39,6,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n707   MSG = 'DASRT--  SOME ELEMENT OF ATOL IS .LT. 0'\n      CALL XERRWD(MSG,39,7,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n708   MSG = 'DASRT--  ALL ELEMENTS OF RTOL AND ATOL ARE ZERO'\n      CALL XERRWD(MSG,47,8,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n709   MSG='DASRT--  INFO(4) = 1 AND TSTOP (=R1) BEHIND TOUT (=R2)'\n      CALL XERRWD(MSG,54,9,0,0,0,0,2,TSTOP,TOUT)\n      GO TO 750\n710   MSG = 'DASRT--  HMAX (=R1) .LT. 0.0'\n      CALL XERRWD(MSG,28,10,0,0,0,0,1,HMAX,0.0D0)\n      GO TO 750\n711   MSG = 'DASRT--  TOUT (=R1) BEHIND T (=R2)'\n      CALL XERRWD(MSG,34,11,0,0,0,0,2,TOUT,T)\n      GO TO 750\n712   MSG = 'DASRT--  INFO(8)=1 AND H0=0.0'\n      CALL XERRWD(MSG,29,12,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n713   MSG = 'DASRT--  SOME ELEMENT OF WT IS .LE. 0.0'\n      CALL XERRWD(MSG,39,13,0,0,0,0,0,0.0D0,0.0D0)\n      GO TO 750\n714   MSG='DASRT-- TOUT (=R1) TOO CLOSE TO T (=R2) TO START INTEGRATION'\n      CALL XERRWD(MSG,60,14,0,0,0,0,2,TOUT,T)\n      GO TO 750\n715   MSG = 'DASRT--  INFO(4)=1 AND TSTOP (=R1) BEHIND T (=R2)'\n      CALL XERRWD(MSG,49,15,0,0,0,0,2,TSTOP,T)\n      GO TO 750\n716   MSG = 'DASRT--  INFO(12)=1 AND MXSTP (=I1) .LT. 0'\n      CALL XERRWD(MSG,42,16,0,1,IWORK(LMXSTP),0,0,0.0D0,0.0D0)\n      GO TO 750\n717   MSG = 'DASRT--  ML (=I1) ILLEGAL. EITHER .LT. 0 OR .GT. NEQ'\n      CALL XERRWD(MSG,52,17,0,1,IWORK(LML),0,0,0.0D0,0.0D0)\n      GO TO 750\n718   MSG = 'DASRT--  MU (=I1) ILLEGAL. EITHER .LT. 0 OR .GT. NEQ'\n      CALL XERRWD(MSG,52,18,0,1,IWORK(LMU),0,0,0.0D0,0.0D0)\n      GO TO 750\n719   MSG = 'DASRT--  TOUT (=R1) IS EQUAL TO T (=R2)'\n      CALL XERRWD(MSG,39,19,0,0,0,0,2,TOUT,T)\n      GO TO 750\n730   MSG = 'DASRT--  NG (=I1) .LT. 0'\n      CALL XERRWD(MSG,24,30,1,1,NG,0,0,0.0D0,0.0D0)\n      GO TO 750\n732   MSG = 'DASRT--  ONE OR MORE COMPONENTS OF G HAS A ROOT'\n      CALL XERRWD(MSG,47,32,1,0,0,0,0,0.0D0,0.0D0)\n      MSG = '         TOO NEAR TO THE INITIAL POINT'\n      CALL XERRWD(MSG,38,32,1,0,0,0,0,0.0D0,0.0D0)\n750   IF(INFO(1).EQ.-1) GO TO 760\n      INFO(1)=-1\n      IDID=-33\n      RETURN\n760   MSG = 'DASRT--  REPEATED OCCURRENCES OF ILLEGAL INPUT'\n      CALL XERRWD(MSG,46,801,0,0,0,0,0,0.0D0,0.0D0)\n770   MSG = 'DASRT--  RUN TERMINATED. APPARENT INFINITE LOOP'\n      CALL XERRWD(MSG,47,802,1,0,0,0,0,0.0D0,0.0D0)\n      RETURN\nC-----------END OF SUBROUTINE DDASRT------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/dasrt/drchek.f",
    "content": "      SUBROUTINE DRCHEK (JOB, G, NG, NEQ, TN, TOUT, Y, YP, PHI, PSI,\n     *  KOLD, G0, G1, GX, JROOT, IRT, UROUND, INFO3, RWORK, IWORK,\n     *  RPAR, IPAR)\nC\nC***BEGIN PROLOGUE  DRCHEK\nC***REFER TO DDASRT\nC***ROUTINES CALLED  DDATRP, DROOTS, DCOPY\nC***DATE WRITTEN   821001   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***END PROLOGUE  DRCHEK\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      PARAMETER (LNGE=16, LIRFND=18, LLAST=19, LIMAX=20,\n     *           LT0=41, LTLAST=42, LALPHR=43, LX2=44)\n      EXTERNAL G\n      INTEGER JOB, NG, NEQ, KOLD, JROOT, IRT, INFO3, IWORK, IPAR\n      DOUBLE PRECISION TN, TOUT, Y, YP, PHI, PSI, G0, G1, GX, UROUND,\n     *  RWORK, RPAR\n      DIMENSION  Y(*), YP(*), PHI(NEQ,*), PSI(*),\n     1  G0(*), G1(*), GX(*), JROOT(*), RWORK(*), IWORK(*)\n      INTEGER I, JFLAG\n      DOUBLE PRECISION H\n      DOUBLE PRECISION HMING, T1, TEMP1, TEMP2, X\n      LOGICAL ZROOT\nC-----------------------------------------------------------------------\nC THIS ROUTINE CHECKS FOR THE PRESENCE OF A ROOT IN THE\nC VICINITY OF THE CURRENT T, IN A MANNER DEPENDING ON THE\nC INPUT FLAG JOB.  IT CALLS SUBROUTINE DROOTS TO LOCATE THE ROOT\nC AS PRECISELY AS POSSIBLE.\nC\nC IN ADDITION TO VARIABLES DESCRIBED PREVIOUSLY, DRCHEK\nC USES THE FOLLOWING FOR COMMUNICATION..\nC JOB    = INTEGER FLAG INDICATING TYPE OF CALL..\nC          JOB = 1 MEANS THE PROBLEM IS BEING INITIALIZED, AND DRCHEK\nC                  IS TO LOOK FOR A ROOT AT OR VERY NEAR THE INITIAL T.\nC          JOB = 2 MEANS A CONTINUATION CALL TO THE SOLVER WAS JUST\nC                  MADE, AND DRCHEK IS TO CHECK FOR A ROOT IN THE\nC                  RELEVANT PART OF THE STEP LAST TAKEN.\nC          JOB = 3 MEANS A SUCCESSFUL STEP WAS JUST TAKEN, AND DRCHEK\nC                  IS TO LOOK FOR A ROOT IN THE INTERVAL OF THE STEP.\nC G0     = ARRAY OF LENGTH NG, CONTAINING THE VALUE OF G AT T = T0.\nC          G0 IS INPUT FOR JOB .GE. 2 AND ON OUTPUT IN ALL CASES.\nC G1,GX  = ARRAYS OF LENGTH NG FOR WORK SPACE.\nC IRT    = COMPLETION FLAG..\nC          IRT = 0  MEANS NO ROOT WAS FOUND.\nC          IRT = -1 MEANS JOB = 1 AND A ROOT WAS FOUND TOO NEAR TO T.\nC          IRT = 1  MEANS A LEGITIMATE ROOT WAS FOUND (JOB = 2 OR 3).\nC                   ON RETURN, T0 IS THE ROOT LOCATION, AND Y IS THE\nC                   CORRESPONDING SOLUTION VECTOR.\nC T0     = VALUE OF T AT ONE ENDPOINT OF INTERVAL OF INTEREST.  ONLY\nC          ROOTS BEYOND T0 IN THE DIRECTION OF INTEGRATION ARE SOUGHT.\nC          T0 IS INPUT IF JOB .GE. 2, AND OUTPUT IN ALL CASES.\nC          T0 IS UPDATED BY DRCHEK, WHETHER A ROOT IS FOUND OR NOT.\nC          STORED IN THE GLOBAL ARRAY RWORK.\nC TLAST  = LAST VALUE OF T RETURNED BY THE SOLVER (INPUT ONLY).\nC          STORED IN THE GLOBAL ARRAY RWORK.\nC TOUT   = FINAL OUTPUT TIME FOR THE SOLVER.\nC IRFND  = INPUT FLAG SHOWING WHETHER THE LAST STEP TAKEN HAD A ROOT.\nC          IRFND = 1 IF IT DID, = 0 IF NOT.\nC          STORED IN THE GLOBAL ARRAY IWORK.\nC INFO3  = COPY OF INFO(3) (INPUT ONLY).\nC-----------------------------------------------------------------------\nC\n      H = PSI(1)\n      IRT = 0\n      DO 10 I = 1,NG\n 10     JROOT(I) = 0\n      HMING = (DABS(TN) + DABS(H))*UROUND*100.0D0\nC\n      GO TO (100, 200, 300), JOB\nC\nC EVALUATE G AT INITIAL T (STORED IN RWORK(LT0)), AND CHECK FOR\nC ZERO VALUES.----------------------------------------------------------\n 100  CONTINUE\n      CALL DDATRP(TN,RWORK(LT0),Y,YP,NEQ,KOLD,PHI,PSI)\n      CALL G (NEQ, RWORK(LT0), Y, NG, G0, RPAR, IPAR)\n      IWORK(LNGE) = 1\n      ZROOT = .FALSE.\n      DO 110 I = 1,NG\n 110    IF (DABS(G0(I)) .LE. 0.0D0) ZROOT = .TRUE.\n      IF (.NOT. ZROOT) GO TO 190\nC G HAS A ZERO AT T.  LOOK AT G AT T + (SMALL INCREMENT). --------------\n      TEMP1 = DSIGN(HMING,H)\n      RWORK(LT0) = RWORK(LT0) + TEMP1\n      TEMP2 = TEMP1/H\n      DO 120 I = 1,NEQ\n 120    Y(I) = Y(I) + TEMP2*PHI(I,2)\n      CALL G (NEQ, RWORK(LT0), Y, NG, G0, RPAR, IPAR)\n      IWORK(LNGE) = IWORK(LNGE) + 1\n      ZROOT = .FALSE.\n      DO 130 I = 1,NG\n 130    IF (DABS(G0(I)) .LE. 0.0D0) ZROOT = .TRUE.\n      IF (.NOT. ZROOT) GO TO 190\nC G HAS A ZERO AT T AND ALSO CLOSE TO T.  TAKE ERROR RETURN. -----------\n      IRT = -1\n      RETURN\nC\n 190  CONTINUE\n      RETURN\nC\nC\n 200  CONTINUE\n      IF (IWORK(LIRFND) .EQ. 0) GO TO 260\nC IF A ROOT WAS FOUND ON THE PREVIOUS STEP, EVALUATE G0 = G(T0). -------\n      CALL DDATRP (TN, RWORK(LT0), Y, YP, NEQ, KOLD, PHI, PSI)\n      CALL G (NEQ, RWORK(LT0), Y, NG, G0, RPAR, IPAR)\n      IWORK(LNGE) = IWORK(LNGE) + 1\n      ZROOT = .FALSE.\n      DO 210 I = 1,NG\n 210    IF (DABS(G0(I)) .LE. 0.0D0) ZROOT = .TRUE.\n      IF (.NOT. ZROOT) GO TO 260\nC G HAS A ZERO AT T0.  LOOK AT G AT T + (SMALL INCREMENT). -------------\n      TEMP1 = DSIGN(HMING,H)\n      RWORK(LT0) = RWORK(LT0) + TEMP1\n      IF ((RWORK(LT0) - TN)*H .LT. 0.0D0) GO TO 230\n      TEMP2 = TEMP1/H\n      DO 220 I = 1,NEQ\n 220    Y(I) = Y(I) + TEMP2*PHI(I,2)\n      GO TO 240\n 230  CALL DDATRP (TN, RWORK(LT0), Y, YP, NEQ, KOLD, PHI, PSI)\n 240  CALL G (NEQ, RWORK(LT0), Y, NG, G0, RPAR, IPAR)\n      IWORK(LNGE) = IWORK(LNGE) + 1\n      ZROOT = .FALSE.\n      DO 250 I = 1,NG\n        IF (DABS(G0(I)) .GT. 0.0D0) GO TO 250\n        JROOT(I) = 1\n        ZROOT = .TRUE.\n 250    CONTINUE\n      IF (.NOT. ZROOT) GO TO 260\nC G HAS A ZERO AT T0 AND ALSO CLOSE TO T0.  RETURN ROOT. ---------------\n      IRT = 1\n      RETURN\nC     HERE, G0 DOES NOT HAVE A ROOT\nC G0 HAS NO ZERO COMPONENTS.  PROCEED TO CHECK RELEVANT INTERVAL. ------\n 260  IF (TN .EQ. RWORK(LTLAST)) GO TO 390\nC\n 300  CONTINUE\nC SET T1 TO TN OR TOUT, WHICHEVER COMES FIRST, AND GET G AT T1. --------\n      IF (INFO3 .EQ. 1) GO TO 310\n      IF ((TOUT - TN)*H .GE. 0.0D0) GO TO 310\n      T1 = TOUT\n      IF ((T1 - RWORK(LT0))*H .LE. 0.0D0) GO TO 390\n      CALL DDATRP (TN, T1, Y, YP, NEQ, KOLD, PHI, PSI)\n      GO TO 330\n 310  T1 = TN\n      DO 320 I = 1,NEQ\n 320    Y(I) = PHI(I,1)\n 330  CALL G (NEQ, T1, Y, NG, G1, RPAR, IPAR)\n      IWORK(LNGE) = IWORK(LNGE) + 1\nC CALL DROOTS TO SEARCH FOR ROOT IN INTERVAL FROM T0 TO T1. ------------\n      JFLAG = 0\n 350  CONTINUE\n      CALL DROOTS (NG, HMING, JFLAG, RWORK(LT0), T1, G0, G1, GX, X,\n     *             JROOT, IWORK(LIMAX), IWORK(LLAST), RWORK(LALPHR),\n     *             RWORK(LX2))\n      IF (JFLAG .GT. 1) GO TO 360\n      CALL DDATRP (TN, X, Y, YP, NEQ, KOLD, PHI, PSI)\n      CALL G (NEQ, X, Y, NG, GX, RPAR, IPAR)\n      IWORK(LNGE) = IWORK(LNGE) + 1\n      GO TO 350\n 360  RWORK(LT0) = X\n      CALL DCOPY (NG, GX, 1, G0, 1)\n      IF (JFLAG .EQ. 4) GO TO 390\nC FOUND A ROOT.  INTERPOLATE TO X AND RETURN. --------------------------\n      CALL DDATRP (TN, X, Y, YP, NEQ, KOLD, PHI, PSI)\n      IRT = 1\n      RETURN\nC\n 390  CONTINUE\n      RETURN\nC---------------------- END OF SUBROUTINE DRCHEK -----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/dasrt/droots.f",
    "content": "      SUBROUTINE DROOTS (NG, HMIN, JFLAG, X0, X1, G0, G1, GX, X, JROOT,\n     *                   IMAX, LAST, ALPHA, X2)\nC\nC***BEGIN PROLOGUE  DROOTS\nC***REFER TO DDASRT\nC***ROUTINES CALLED  DCOPY\nC***DATE WRITTEN   821001   (YYMMDD)\nC***REVISION DATE  900926   (YYMMDD)\nC***END PROLOGUE  DROOTS\nC\n      IMPLICIT DOUBLE PRECISION(A-H,O-Z)\n      INTEGER NG, JFLAG, JROOT, IMAX, LAST\n      DOUBLE PRECISION HMIN, X0, X1, G0, G1, GX, X, ALPHA, X2\n      DIMENSION G0(NG), G1(NG), GX(NG), JROOT(NG)\nC-----------------------------------------------------------------------\nC THIS SUBROUTINE FINDS THE LEFTMOST ROOT OF A SET OF ARBITRARY\nC FUNCTIONS GI(X) (I = 1,...,NG) IN AN INTERVAL (X0,X1).  ONLY ROOTS\nC OF ODD MULTIPLICITY (I.E. CHANGES OF SIGN OF THE GI) ARE FOUND.\nC HERE THE SIGN OF X1 - X0 IS ARBITRARY, BUT IS CONSTANT FOR A GIVEN\nC PROBLEM, AND -LEFTMOST- MEANS NEAREST TO X0.\nC THE VALUES OF THE VECTOR-VALUED FUNCTION G(X) = (GI, I=1...NG)\nC ARE COMMUNICATED THROUGH THE CALL SEQUENCE OF DROOTS.\nC THE METHOD USED IS THE ILLINOIS ALGORITHM.\nC\nC REFERENCE..\nC KATHIE L. HIEBERT AND LAWRENCE F. SHAMPINE, IMPLICITLY DEFINED\nC OUTPUT POINTS FOR SOLUTIONS OF ODE-S, SANDIA REPORT SAND80-0180,\nC FEBRUARY, 1980.\nC\nC DESCRIPTION OF PARAMETERS.\nC\nC NG     = NUMBER OF FUNCTIONS GI, OR THE NUMBER OF COMPONENTS OF\nC          THE VECTOR VALUED FUNCTION G(X).  INPUT ONLY.\nC\nC HMIN   = RESOLUTION PARAMETER IN X.  INPUT ONLY.  WHEN A ROOT IS\nC          FOUND, IT IS LOCATED ONLY TO WITHIN AN ERROR OF HMIN IN X.\nC          TYPICALLY, HMIN SHOULD BE SET TO SOMETHING ON THE ORDER OF\nC               100 * UROUND * MAX(ABS(X0),ABS(X1)),\nC          WHERE UROUND IS THE UNIT ROUNDOFF OF THE MACHINE.\nC\nC JFLAG  = INTEGER FLAG FOR INPUT AND OUTPUT COMMUNICATION.\nC\nC          ON INPUT, SET JFLAG = 0 ON THE FIRST CALL FOR THE PROBLEM,\nC          AND LEAVE IT UNCHANGED UNTIL THE PROBLEM IS COMPLETED.\nC          (THE PROBLEM IS COMPLETED WHEN JFLAG .GE. 2 ON RETURN.)\nC\nC          ON OUTPUT, JFLAG HAS THE FOLLOWING VALUES AND MEANINGS..\nC          JFLAG = 1 MEANS DROOTS NEEDS A VALUE OF G(X).  SET GX = G(X)\nC                    AND CALL DROOTS AGAIN.\nC          JFLAG = 2 MEANS A ROOT HAS BEEN FOUND.  THE ROOT IS\nC                    AT X, AND GX CONTAINS G(X).  (ACTUALLY, X IS THE\nC                    RIGHTMOST APPROXIMATION TO THE ROOT ON AN INTERVAL\nC                    (X0,X1) OF SIZE HMIN OR LESS.)\nC          JFLAG = 3 MEANS X = X1 IS A ROOT, WITH ONE OR MORE OF THE GI\nC                    BEING ZERO AT X1 AND NO SIGN CHANGES IN (X0,X1).\nC                    GX CONTAINS G(X) ON OUTPUT.\nC          JFLAG = 4 MEANS NO ROOTS (OF ODD MULTIPLICITY) WERE\nC                    FOUND IN (X0,X1) (NO SIGN CHANGES).\nC\nC X0,X1  = ENDPOINTS OF THE INTERVAL WHERE ROOTS ARE SOUGHT.\nC          X1 AND X0 ARE INPUT WHEN JFLAG = 0 (FIRST CALL), AND\nC          MUST BE LEFT UNCHANGED BETWEEN CALLS UNTIL THE PROBLEM IS\nC          COMPLETED.  X0 AND X1 MUST BE DISTINCT, BUT X1 - X0 MAY BE\nC          OF EITHER SIGN.  HOWEVER, THE NOTION OF -LEFT- AND -RIGHT-\nC          WILL BE USED TO MEAN NEARER TO X0 OR X1, RESPECTIVELY.\nC          WHEN JFLAG .GE. 2 ON RETURN, X0 AND X1 ARE OUTPUT, AND\nC          ARE THE ENDPOINTS OF THE RELEVANT INTERVAL.\nC\nC G0,G1  = ARRAYS OF LENGTH NG CONTAINING THE VECTORS G(X0) AND G(X1),\nC          RESPECTIVELY.  WHEN JFLAG = 0, G0 AND G1 ARE INPUT AND\nC          NONE OF THE G0(I) SHOULD BE BE ZERO.\nC          WHEN JFLAG .GE. 2 ON RETURN, G0 AND G1 ARE OUTPUT.\nC\nC GX     = ARRAY OF LENGTH NG CONTAINING G(X).  GX IS INPUT\nC          WHEN JFLAG = 1, AND OUTPUT WHEN JFLAG .GE. 2.\nC\nC X      = INDEPENDENT VARIABLE VALUE.  OUTPUT ONLY.\nC          WHEN JFLAG = 1 ON OUTPUT, X IS THE POINT AT WHICH G(X)\nC          IS TO BE EVALUATED AND LOADED INTO GX.\nC          WHEN JFLAG = 2 OR 3, X IS THE ROOT.\nC          WHEN JFLAG = 4, X IS THE RIGHT ENDPOINT OF THE INTERVAL, X1.\nC\nC JROOT  = INTEGER ARRAY OF LENGTH NG.  OUTPUT ONLY.\nC          WHEN JFLAG = 2 OR 3, JROOT INDICATES WHICH COMPONENTS\nC          OF G(X) HAVE A ROOT AT X.  JROOT(I) IS 1 IF THE I-TH\nC          COMPONENT HAS A ROOT, AND JROOT(I) = 0 OTHERWISE.\nC\nC IMAX, LAST, ALPHA, X2 =\nC          BOOKKEEPING VARIABLES WHICH MUST BE SAVED FROM CALL\nC          TO CALL.  THEY ARE SAVED INSIDE THE CALLING ROUTINE,\nC          BUT THEY ARE USED ONLY WITHIN THIS ROUTINE.\nC-----------------------------------------------------------------------\n      INTEGER I, IMXOLD, NXLAST\n      DOUBLE PRECISION T2, TMAX, ZERO\n      LOGICAL ZROOT, SGNCHG, XROOT\n      DATA ZERO/0.0D0/\nC\n      IF (JFLAG .EQ. 1) GO TO 200\nC JFLAG .NE. 1.  CHECK FOR CHANGE IN SIGN OF G OR ZERO AT X1. ----------\n      IMAX = 0\n      TMAX = ZERO\n      ZROOT = .FALSE.\n      DO 120 I = 1,NG\n        IF (DABS(G1(I)) .GT. ZERO) GO TO 110\n        ZROOT = .TRUE.\n        GO TO 120\nC AT THIS POINT, G0(I) HAS BEEN CHECKED AND CANNOT BE ZERO. ------------\n 110    IF (DSIGN(1.0D0,G0(I)) .EQ. DSIGN(1.0D0,G1(I))) GO TO 120\n          T2 = DABS(G1(I)/(G1(I)-G0(I)))\n          IF (T2 .LE. TMAX) GO TO 120\n            TMAX = T2\n            IMAX = I\n 120    CONTINUE\n      IF (IMAX .GT. 0) GO TO 130\n      SGNCHG = .FALSE.\n      GO TO 140\n 130  SGNCHG = .TRUE.\n 140  IF (.NOT. SGNCHG) GO TO 400\nC THERE IS A SIGN CHANGE.  FIND THE FIRST ROOT IN THE INTERVAL. --------\n      XROOT = .FALSE.\n      NXLAST = 0\n      LAST = 1\nC\nC REPEAT UNTIL THE FIRST ROOT IN THE INTERVAL IS FOUND.  LOOP POINT. ---\n 150  CONTINUE\n      IF (XROOT) GO TO 300\n      IF (NXLAST .EQ. LAST) GO TO 160\n      ALPHA = 1.0D0\n      GO TO 180\n 160  IF (LAST .EQ. 0) GO TO 170\n      ALPHA = 0.5D0*ALPHA\n      GO TO 180\n 170  ALPHA = 2.0D0*ALPHA\n 180  X2 = X1 - (X1-X0)*G1(IMAX)/(G1(IMAX) - ALPHA*G0(IMAX))\n      IF ((DABS(X2-X0) .LT. HMIN) .AND.\n     1   (DABS(X1-X0) .GT. 10.0D0*HMIN)) X2 = X0 + 0.1D0*(X1-X0)\n      JFLAG = 1\n      X = X2\nC RETURN TO THE CALLING ROUTINE TO GET A VALUE OF GX = G(X). -----------\n      RETURN\nC CHECK TO SEE IN WHICH INTERVAL G CHANGES SIGN. -----------------------\n 200  IMXOLD = IMAX\n      IMAX = 0\n      TMAX = ZERO\n      ZROOT = .FALSE.\n      DO 220 I = 1,NG\n        IF (DABS(GX(I)) .GT. ZERO) GO TO 210\n        ZROOT = .TRUE.\n        GO TO 220\nC NEITHER G0(I) NOR GX(I) CAN BE ZERO AT THIS POINT. -------------------\n 210    IF (DSIGN(1.0D0,G0(I)) .EQ. DSIGN(1.0D0,GX(I))) GO TO 220\n          T2 = DABS(GX(I)/(GX(I) - G0(I)))\n          IF (T2 .LE. TMAX) GO TO 220\n            TMAX = T2\n            IMAX = I\n 220    CONTINUE\n      IF (IMAX .GT. 0) GO TO 230\n      SGNCHG = .FALSE.\n      IMAX = IMXOLD\n      GO TO 240\n 230  SGNCHG = .TRUE.\n 240  NXLAST = LAST\n      IF (.NOT. SGNCHG) GO TO 250\nC SIGN CHANGE BETWEEN X0 AND X2, SO REPLACE X1 WITH X2. ----------------\n      X1 = X2\n      CALL DCOPY (NG, GX, 1, G1, 1)\n      LAST = 1\n      XROOT = .FALSE.\n      GO TO 270\n 250  IF (.NOT. ZROOT) GO TO 260\nC ZERO VALUE AT X2 AND NO SIGN CHANGE IN (X0,X2), SO X2 IS A ROOT. -----\n      X1 = X2\n      CALL DCOPY (NG, GX, 1, G1, 1)\n      XROOT = .TRUE.\n      GO TO 270\nC NO SIGN CHANGE BETWEEN X0 AND X2.  REPLACE X0 WITH X2. ---------------\n 260  CONTINUE\n      CALL DCOPY (NG, GX, 1, G0, 1)\n      X0 = X2\n      LAST = 0\n      XROOT = .FALSE.\n 270  IF (DABS(X1-X0) .LE. HMIN) XROOT = .TRUE.\n      GO TO 150\nC\nC RETURN WITH X1 AS THE ROOT.  SET JROOT.  SET X = X1 AND GX = G1. -----\n 300  JFLAG = 2\n      X = X1\n      CALL DCOPY (NG, G1, 1, GX, 1)\n      DO 320 I = 1,NG\n        JROOT(I) = 0\n        IF (DABS(G1(I)) .GT. ZERO) GO TO 310\n          JROOT(I) = 1\n          GO TO 320\n 310    IF (DSIGN(1.0D0,G0(I)) .NE. DSIGN(1.0D0,G1(I))) JROOT(I) = 1\n 320    CONTINUE\n      RETURN\nC\nC NO SIGN CHANGE IN THE INTERVAL.  CHECK FOR ZERO AT RIGHT ENDPOINT. ---\n 400  IF (.NOT. ZROOT) GO TO 420\nC\nC ZERO VALUE AT X1 AND NO SIGN CHANGE IN (X0,X1).  RETURN JFLAG = 3. ---\n      X = X1\n      CALL DCOPY (NG, G1, 1, GX, 1)\n      DO 410 I = 1,NG\n        JROOT(I) = 0\n        IF (DABS(G1(I)) .LE. ZERO) JROOT (I) = 1\n 410  CONTINUE\n      JFLAG = 3\n      RETURN\nC\nC NO SIGN CHANGES IN THIS INTERVAL.  SET X = X1, RETURN JFLAG = 4. -----\n 420  CALL DCOPY (NG, G1, 1, GX, 1)\n      X = X1\n      JFLAG = 4\n      RETURN\nC---------------------- END OF SUBROUTINE DROOTS -----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/dasrt/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/ddasrt.f \\\n  %reldir%/drchek.f \\\n  %reldir%/droots.f\n"
  },
  {
    "path": "liboctave/external/dassl/ddaini.f",
    "content": "      SUBROUTINE DDAINI (X, Y, YPRIME, NEQ, RES, JAC, H, WT, IDID, RPAR,\n     +   IPAR, PHI, DELTA, E, WM, IWM, HMIN, UROUND, NONNEG, NTEMP)\nC***BEGIN PROLOGUE  DDAINI\nC***SUBSIDIARY\nC***PURPOSE  Initialization routine for DDASSL.\nC***LIBRARY   SLATEC (DASSL)\nC***TYPE      DOUBLE PRECISION (SDAINI-S, DDAINI-D)\nC***AUTHOR  PETZOLD, LINDA R., (LLNL)\nC***DESCRIPTION\nC-----------------------------------------------------------------\nC     DDAINI TAKES ONE STEP OF SIZE H OR SMALLER\nC     WITH THE BACKWARD EULER METHOD, TO\nC     FIND YPRIME.  X AND Y ARE UPDATED TO BE CONSISTENT WITH THE\nC     NEW STEP.  A MODIFIED DAMPED NEWTON ITERATION IS USED TO\nC     SOLVE THE CORRECTOR ITERATION.\nC\nC     THE INITIAL GUESS FOR YPRIME IS USED IN THE\nC     PREDICTION, AND IN FORMING THE ITERATION\nC     MATRIX, BUT IS NOT INVOLVED IN THE\nC     ERROR TEST. THIS MAY HAVE TROUBLE\nC     CONVERGING IF THE INITIAL GUESS IS NO\nC     GOOD, OR IF G(X,Y,YPRIME) DEPENDS\nC     NONLINEARLY ON YPRIME.\nC\nC     THE PARAMETERS REPRESENT:\nC     X --         INDEPENDENT VARIABLE\nC     Y --         SOLUTION VECTOR AT X\nC     YPRIME --    DERIVATIVE OF SOLUTION VECTOR\nC     NEQ --       NUMBER OF EQUATIONS\nC     H --         STEPSIZE. IMDER MAY USE A STEPSIZE\nC                  SMALLER THAN H.\nC     WT --        VECTOR OF WEIGHTS FOR ERROR\nC                  CRITERION\nC     IDID --      COMPLETION CODE WITH THE FOLLOWING MEANINGS\nC                  IDID= 1 -- YPRIME WAS FOUND SUCCESSFULLY\nC                  IDID=-12 -- DDAINI FAILED TO FIND YPRIME\nC     RPAR,IPAR -- REAL AND INTEGER PARAMETER ARRAYS\nC                  THAT ARE NOT ALTERED BY DDAINI\nC     PHI --       WORK SPACE FOR DDAINI\nC     DELTA,E --   WORK SPACE FOR DDAINI\nC     WM,IWM --    REAL AND INTEGER ARRAYS STORING\nC                  MATRIX INFORMATION\nC\nC-----------------------------------------------------------------\nC***ROUTINES CALLED  DDAJAC, DDANRM, DDASLV\nC***REVISION HISTORY  (YYMMDD)\nC   830315  DATE WRITTEN\nC   901009  Finished conversion to SLATEC 4.0 format (F.N.Fritsch)\nC   901019  Merged changes made by C. Ulrich with SLATEC 4.0 format.\nC   901026  Added explicit declarations for all variables and minor\nC           cosmetic changes to prologue.  (FNF)\nC   901030  Minor corrections to declarations.  (FNF)\nC***END PROLOGUE  DDAINI\nC\n      INTEGER  NEQ, IDID, IPAR(*), IWM(*), NONNEG, NTEMP\n      DOUBLE PRECISION\n     *   X, Y(*), YPRIME(*), H, WT(*), RPAR(*), PHI(NEQ,*), DELTA(*),\n     *   E(*), WM(*), HMIN, UROUND\n      EXTERNAL  RES, JAC\nC\n      EXTERNAL  DDAJAC, DDANRM, DDASLV\n      DOUBLE PRECISION  DDANRM\nC\n      INTEGER  I, IER, IRES, JCALC, LNJE, LNRE, M, MAXIT, MJAC, NCF,\n     *   NEF, NSF\n      DOUBLE PRECISION\n     *   CJ, DAMP, DELNRM, ERR, OLDNRM, R, RATE, S, XOLD, YNORM\n      LOGICAL  CONVGD\nC\n      PARAMETER (LNRE=12)\n      PARAMETER (LNJE=13)\nC\n      DATA MAXIT/10/,MJAC/5/\n      DATA DAMP/0.75D0/\nC\nC\nC---------------------------------------------------\nC     BLOCK 1.\nC     INITIALIZATIONS.\nC---------------------------------------------------\nC\nC***FIRST EXECUTABLE STATEMENT  DDAINI\n      IDID=1\n      NEF=0\n      NCF=0\n      NSF=0\n      XOLD=X\n      YNORM=DDANRM(NEQ,Y,WT,RPAR,IPAR)\nC\nC     SAVE Y AND YPRIME IN PHI\n      DO 100 I=1,NEQ\n         PHI(I,1)=Y(I)\n100      PHI(I,2)=YPRIME(I)\nC\nC\nC----------------------------------------------------\nC     BLOCK 2.\nC     DO ONE BACKWARD EULER STEP.\nC----------------------------------------------------\nC\nC     SET UP FOR START OF CORRECTOR ITERATION\n200   CJ=1.0D0/H\n      X=X+H\nC\nC     PREDICT SOLUTION AND DERIVATIVE\n      DO 250 I=1,NEQ\n250     Y(I)=Y(I)+H*YPRIME(I)\nC\n      JCALC=-1\n      M=0\n      CONVGD=.TRUE.\nC\nC\nC     CORRECTOR LOOP.\n300   IWM(LNRE)=IWM(LNRE)+1\n      IRES=0\nC\n      CALL RES(X,Y,YPRIME,DELTA,IRES,RPAR,IPAR)\n      IF (IRES.LT.0) GO TO 430\nC\nC\nC     EVALUATE THE ITERATION MATRIX\n      IF (JCALC.NE.-1) GO TO 310\n      IWM(LNJE)=IWM(LNJE)+1\n      JCALC=0\n      CALL DDAJAC(NEQ,X,Y,YPRIME,DELTA,CJ,H,\n     *   IER,WT,E,WM,IWM,RES,IRES,\n     *   UROUND,JAC,RPAR,IPAR,NTEMP)\nC\n      S=1000000.D0\n      IF (IRES.LT.0) GO TO 430\n      IF (IER.NE.0) GO TO 430\n      NSF=0\nC\nC\nC\nC     MULTIPLY RESIDUAL BY DAMPING FACTOR\n310   CONTINUE\n      DO 320 I=1,NEQ\n320      DELTA(I)=DELTA(I)*DAMP\nC\nC     COMPUTE A NEW ITERATE (BACK SUBSTITUTION)\nC     STORE THE CORRECTION IN DELTA\nC\n      CALL DDASLV(NEQ,DELTA,WM,IWM)\nC\nC     UPDATE Y AND YPRIME\n      DO 330 I=1,NEQ\n         Y(I)=Y(I)-DELTA(I)\n330      YPRIME(I)=YPRIME(I)-CJ*DELTA(I)\nC\nC     TEST FOR CONVERGENCE OF THE ITERATION.\nC\n      DELNRM=DDANRM(NEQ,DELTA,WT,RPAR,IPAR)\n      IF (DELNRM.LE.100.D0*UROUND*YNORM)\n     *   GO TO 400\nC\n      IF (M.GT.0) GO TO 340\n         OLDNRM=DELNRM\n         GO TO 350\nC\n340   RATE=(DELNRM/OLDNRM)**(1.0D0/M)\n      IF (RATE.GT.0.90D0) GO TO 430\n      S=RATE/(1.0D0-RATE)\nC\n350   IF (S*DELNRM .LE. 0.33D0) GO TO 400\nC\nC\nC     THE CORRECTOR HAS NOT YET CONVERGED. UPDATE\nC     M AND AND TEST WHETHER THE MAXIMUM\nC     NUMBER OF ITERATIONS HAVE BEEN TRIED.\nC     EVERY MJAC ITERATIONS, GET A NEW\nC     ITERATION MATRIX.\nC\n      M=M+1\n      IF (M.GE.MAXIT) GO TO 430\nC\n      IF ((M/MJAC)*MJAC.EQ.M) JCALC=-1\n      GO TO 300\nC\nC\nC     THE ITERATION HAS CONVERGED.\nC     CHECK NONNEGATIVITY CONSTRAINTS\n400   IF (NONNEG.EQ.0) GO TO 450\n      DO 410 I=1,NEQ\n410      DELTA(I)=MIN(Y(I),0.0D0)\nC\n      DELNRM=DDANRM(NEQ,DELTA,WT,RPAR,IPAR)\n      IF (DELNRM.GT.0.33D0) GO TO 430\nC\n      DO 420 I=1,NEQ\n         Y(I)=Y(I)-DELTA(I)\n420      YPRIME(I)=YPRIME(I)-CJ*DELTA(I)\n      GO TO 450\nC\nC\nC     EXITS FROM CORRECTOR LOOP.\n430   CONVGD=.FALSE.\n450   IF (.NOT.CONVGD) GO TO 600\nC\nC\nC\nC-----------------------------------------------------\nC     BLOCK 3.\nC     THE CORRECTOR ITERATION CONVERGED.\nC     DO ERROR TEST.\nC-----------------------------------------------------\nC\n      DO 510 I=1,NEQ\n510      E(I)=Y(I)-PHI(I,1)\n      ERR=DDANRM(NEQ,E,WT,RPAR,IPAR)\nC\n      IF (ERR.LE.1.0D0) RETURN\nC\nC\nC\nC--------------------------------------------------------\nC     BLOCK 4.\nC     THE BACKWARD EULER STEP FAILED. RESTORE X, Y\nC     AND YPRIME TO THEIR ORIGINAL VALUES.\nC     REDUCE STEPSIZE AND TRY AGAIN, IF\nC     POSSIBLE.\nC---------------------------------------------------------\nC\n600   CONTINUE\n      X = XOLD\n      DO 610 I=1,NEQ\n         Y(I)=PHI(I,1)\n610      YPRIME(I)=PHI(I,2)\nC\n      IF (CONVGD) GO TO 640\n      IF (IER.EQ.0) GO TO 620\n         NSF=NSF+1\n         H=H*0.25D0\n         IF (NSF.LT.3.AND.ABS(H).GE.HMIN) GO TO 690\n         IDID=-12\n         RETURN\n620   IF (IRES.GT.-2) GO TO 630\n         IDID=-12\n         RETURN\n630   NCF=NCF+1\n      H=H*0.25D0\n      IF (NCF.LT.10.AND.ABS(H).GE.HMIN) GO TO 690\n         IDID=-12\n         RETURN\nC\n640   NEF=NEF+1\n      R=0.90D0/(2.0D0*ERR+0.0001D0)\n      R=MAX(0.1D0,MIN(0.5D0,R))\n      H=H*R\n      IF (ABS(H).GE.HMIN.AND.NEF.LT.10) GO TO 690\n         IDID=-12\n         RETURN\n690      GO TO 200\nC\nC-------------END OF SUBROUTINE DDAINI----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/dassl/ddajac.f",
    "content": "      SUBROUTINE DDAJAC (NEQ, X, Y, YPRIME, DELTA, CJ, H,\n     +   IER, WT, E, WM, IWM, RES, IRES, UROUND, JAC, RPAR,\n     +   IPAR, NTEMP)\nC***BEGIN PROLOGUE  DDAJAC\nC***SUBSIDIARY\nC***PURPOSE  Compute the iteration matrix for DDASSL and form the\nC            LU-decomposition.\nC***LIBRARY   SLATEC (DASSL)\nC***TYPE      DOUBLE PRECISION (SDAJAC-S, DDAJAC-D)\nC***AUTHOR  PETZOLD, LINDA R., (LLNL)\nC***DESCRIPTION\nC-----------------------------------------------------------------------\nC     THIS ROUTINE COMPUTES THE ITERATION MATRIX\nC     PD=DG/DY+CJ*DG/DYPRIME (WHERE G(X,Y,YPRIME)=0).\nC     HERE PD IS COMPUTED BY THE USER-SUPPLIED\nC     ROUTINE JAC IF IWM(MTYPE) IS 1 OR 4, AND\nC     IT IS COMPUTED BY NUMERICAL FINITE DIFFERENCING\nC     IF IWM(MTYPE)IS 2 OR 5\nC     THE PARAMETERS HAVE THE FOLLOWING MEANINGS.\nC     Y        = ARRAY CONTAINING PREDICTED VALUES\nC     YPRIME   = ARRAY CONTAINING PREDICTED DERIVATIVES\nC     DELTA    = RESIDUAL EVALUATED AT (X,Y,YPRIME)\nC                (USED ONLY IF IWM(MTYPE)=2 OR 5)\nC     CJ       = SCALAR PARAMETER DEFINING ITERATION MATRIX\nC     H        = CURRENT STEPSIZE IN INTEGRATION\nC     IER      = VARIABLE WHICH IS .NE. 0\nC                IF ITERATION MATRIX IS SINGULAR,\nC                AND 0 OTHERWISE.\nC     WT       = VECTOR OF WEIGHTS FOR COMPUTING NORMS\nC     E        = WORK SPACE (TEMPORARY) OF LENGTH NEQ\nC     WM       = REAL WORK SPACE FOR MATRICES. ON\nC                OUTPUT IT CONTAINS THE LU DECOMPOSITION\nC                OF THE ITERATION MATRIX.\nC     IWM      = INTEGER WORK SPACE CONTAINING\nC                MATRIX INFORMATION\nC     RES      = NAME OF THE EXTERNAL USER-SUPPLIED ROUTINE\nC                TO EVALUATE THE RESIDUAL FUNCTION G(X,Y,YPRIME)\nC     IRES     = FLAG WHICH IS EQUAL TO ZERO IF NO ILLEGAL VALUES\nC                IN RES, AND LESS THAN ZERO OTHERWISE.  (IF IRES\nC                IS LESS THAN ZERO, THE MATRIX WAS NOT COMPLETED)\nC                IN THIS CASE (IF IRES .LT. 0), THEN IER = 0.\nC     UROUND   = THE UNIT ROUNDOFF ERROR OF THE MACHINE BEING USED.\nC     JAC      = NAME OF THE EXTERNAL USER-SUPPLIED ROUTINE\nC                TO EVALUATE THE ITERATION MATRIX (THIS ROUTINE\nC                IS ONLY USED IF IWM(MTYPE) IS 1 OR 4)\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED  DGBTRF, DGETRF\nC***REVISION HISTORY  (YYMMDD)\nC   830315  DATE WRITTEN\nC   901009  Finished conversion to SLATEC 4.0 format (F.N.Fritsch)\nC   901010  Modified three MAX calls to be all on one line.  (FNF)\nC   901019  Merged changes made by C. Ulrich with SLATEC 4.0 format.\nC   901026  Added explicit declarations for all variables and minor\nC           cosmetic changes to prologue.  (FNF)\nC   901101  Corrected PURPOSE.  (FNF)\nC   020204  Convert to use LAPACK\nC***END PROLOGUE  DDAJAC\nC\n      INTEGER  NEQ, IER, IWM(*), IRES, IPAR(*), NTEMP\n      DOUBLE PRECISION\n     *   X, Y(*), YPRIME(*), DELTA(*), CJ, H, WT(*), E(*), WM(*),\n     *   UROUND, RPAR(*)\n      EXTERNAL  RES, JAC\nC\n      EXTERNAL  DGBTRF, DGETRF\nC\n      INTEGER  I, I1, I2, II, IPSAVE, ISAVE, J, K, L, LENPD, LIPVT,\n     *   LML, LMTYPE, LMU, MBA, MBAND, MEB1, MEBAND, MSAVE, MTYPE, N,\n     *   NPD, NPDM1, NROW\n      DOUBLE PRECISION  DEL, DELINV, SQUR, YPSAVE, YSAVE\nC\n      PARAMETER (NPD=1)\n      PARAMETER (LML=1)\n      PARAMETER (LMU=2)\n      PARAMETER (LMTYPE=4)\n      PARAMETER (LIPVT=22)\nC\nC***FIRST EXECUTABLE STATEMENT  DDAJAC\n      IER = 0\n      NPDM1=NPD-1\n      MTYPE=IWM(LMTYPE)\n      GO TO (100,200,300,400,500),MTYPE\nC\nC\nC     DENSE USER-SUPPLIED MATRIX\n100   LENPD=NEQ*NEQ\n      DO 110 I=1,LENPD\n110      WM(NPDM1+I)=0.0D0\n      CALL JAC(X,Y,YPRIME,WM(NPD),CJ,RPAR,IPAR)\n      GO TO 230\nC\nC\nC     DENSE FINITE-DIFFERENCE-GENERATED MATRIX\n200   IRES=0\n      NROW=NPDM1\n      SQUR = SQRT(UROUND)\n      DO 210 I=1,NEQ\n         DEL=SQUR*MAX(ABS(Y(I)),ABS(H*YPRIME(I)),ABS(WT(I)))\n         DEL=SIGN(DEL,H*YPRIME(I))\n         DEL=(Y(I)+DEL)-Y(I)\n         YSAVE=Y(I)\n         YPSAVE=YPRIME(I)\n         Y(I)=Y(I)+DEL\n         YPRIME(I)=YPRIME(I)+CJ*DEL\n         CALL RES(X,Y,YPRIME,E,IRES,RPAR,IPAR)\n         IF (IRES .LT. 0) RETURN\n         DELINV=1.0D0/DEL\n         DO 220 L=1,NEQ\n220      WM(NROW+L)=(E(L)-DELTA(L))*DELINV\n      NROW=NROW+NEQ\n      Y(I)=YSAVE\n      YPRIME(I)=YPSAVE\n210   CONTINUE\nC\nC\nC     DO DENSE-MATRIX LU DECOMPOSITION ON PD\n230      CALL DGETRF( NEQ, NEQ, WM(NPD), NEQ, IWM(LIPVT), IER)\n      RETURN\nC\nC\nC     DUMMY SECTION FOR IWM(MTYPE)=3\n300   RETURN\nC\nC\nC     BANDED USER-SUPPLIED MATRIX\n400   LENPD=(2*IWM(LML)+IWM(LMU)+1)*NEQ\n      DO 410 I=1,LENPD\n410      WM(NPDM1+I)=0.0D0\n      CALL JAC(X,Y,YPRIME,WM(NPD),CJ,RPAR,IPAR)\n      MEBAND=2*IWM(LML)+IWM(LMU)+1\n      GO TO 550\nC\nC\nC     BANDED FINITE-DIFFERENCE-GENERATED MATRIX\n500   MBAND=IWM(LML)+IWM(LMU)+1\n      MBA=MIN(MBAND,NEQ)\n      MEBAND=MBAND+IWM(LML)\n      MEB1=MEBAND-1\n      MSAVE=(NEQ/MBAND)+1\n      ISAVE=NTEMP-1\n      IPSAVE=ISAVE+MSAVE\n      IRES=0\n      SQUR=SQRT(UROUND)\n      DO 540 J=1,MBA\n         DO 510 N=J,NEQ,MBAND\n          K= (N-J)/MBAND + 1\n          WM(ISAVE+K)=Y(N)\n          WM(IPSAVE+K)=YPRIME(N)\n          DEL=SQUR*MAX(ABS(Y(N)),ABS(H*YPRIME(N)),ABS(WT(N)))\n          DEL=SIGN(DEL,H*YPRIME(N))\n          DEL=(Y(N)+DEL)-Y(N)\n          Y(N)=Y(N)+DEL\n510       YPRIME(N)=YPRIME(N)+CJ*DEL\n      CALL RES(X,Y,YPRIME,E,IRES,RPAR,IPAR)\n      IF (IRES .LT. 0) RETURN\n      DO 530 N=J,NEQ,MBAND\n          K= (N-J)/MBAND + 1\n          Y(N)=WM(ISAVE+K)\n          YPRIME(N)=WM(IPSAVE+K)\n          DEL=SQUR*MAX(ABS(Y(N)),ABS(H*YPRIME(N)),ABS(WT(N)))\n          DEL=SIGN(DEL,H*YPRIME(N))\n          DEL=(Y(N)+DEL)-Y(N)\n          DELINV=1.0D0/DEL\n          I1=MAX(1,(N-IWM(LMU)))\n          I2=MIN(NEQ,(N+IWM(LML)))\n          II=N*MEB1-IWM(LML)+NPDM1\n          DO 520 I=I1,I2\n520         WM(II+I)=(E(I)-DELTA(I))*DELINV\n530      CONTINUE\n540   CONTINUE\nC\nC\nC     DO LU DECOMPOSITION OF BANDED PD\n550   CALL DGBTRF(NEQ, NEQ, IWM(LML), IWM(LMU), WM(NPD), MEBAND,\n     *     IWM(LIPVT), IER)\n      RETURN\nC------END OF SUBROUTINE DDAJAC------\n      END\n"
  },
  {
    "path": "liboctave/external/dassl/ddanrm.f",
    "content": "      DOUBLE PRECISION FUNCTION DDANRM (NEQ, V, WT, RPAR, IPAR)\nC***BEGIN PROLOGUE  DDANRM\nC***SUBSIDIARY\nC***PURPOSE  Compute vector norm for DDASSL.\nC***LIBRARY   SLATEC (DASSL)\nC***TYPE      DOUBLE PRECISION (SDANRM-S, DDANRM-D)\nC***AUTHOR  PETZOLD, LINDA R., (LLNL)\nC***DESCRIPTION\nC-----------------------------------------------------------------------\nC     THIS FUNCTION ROUTINE COMPUTES THE WEIGHTED\nC     ROOT-MEAN-SQUARE NORM OF THE VECTOR OF LENGTH\nC     NEQ CONTAINED IN THE ARRAY V,WITH WEIGHTS\nC     CONTAINED IN THE ARRAY WT OF LENGTH NEQ.\nC        DDANRM=SQRT((1/NEQ)*SUM(V(I)/WT(I))**2)\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   830315  DATE WRITTEN\nC   901009  Finished conversion to SLATEC 4.0 format (F.N.Fritsch)\nC   901019  Merged changes made by C. Ulrich with SLATEC 4.0 format.\nC   901026  Added explicit declarations for all variables and minor\nC           cosmetic changes to prologue.  (FNF)\nC***END PROLOGUE  DDANRM\nC\n      INTEGER  NEQ, IPAR(*)\n      DOUBLE PRECISION  V(NEQ), WT(NEQ), RPAR(*)\nC\n      INTEGER  I\n      DOUBLE PRECISION  SUM, VMAX\nC\nC***FIRST EXECUTABLE STATEMENT  DDANRM\n      DDANRM = 0.0D0\n      VMAX = 0.0D0\n      DO 10 I = 1,NEQ\n        IF(ABS(V(I)/WT(I)) .GT. VMAX) VMAX = ABS(V(I)/WT(I))\n10      CONTINUE\n      IF(VMAX .LE. 0.0D0) GO TO 30\n      SUM = 0.0D0\n      DO 20 I = 1,NEQ\n20      SUM = SUM + ((V(I)/WT(I))/VMAX)**2\n      DDANRM = VMAX*SQRT(SUM/NEQ)\n30    CONTINUE\n      RETURN\nC------END OF FUNCTION DDANRM------\n      END\n"
  },
  {
    "path": "liboctave/external/dassl/ddaslv.f",
    "content": "      SUBROUTINE DDASLV (NEQ, DELTA, WM, IWM)\nC***BEGIN PROLOGUE  DDASLV\nC***SUBSIDIARY\nC***PURPOSE  Linear system solver for DDASSL.\nC***LIBRARY   SLATEC (DASSL)\nC***TYPE      DOUBLE PRECISION (SDASLV-S, DDASLV-D)\nC***AUTHOR  PETZOLD, LINDA R., (LLNL)\nC***DESCRIPTION\nC-----------------------------------------------------------------------\nC     THIS ROUTINE MANAGES THE SOLUTION OF THE LINEAR\nC     SYSTEM ARISING IN THE NEWTON ITERATION.\nC     MATRICES AND REAL TEMPORARY STORAGE AND\nC     REAL INFORMATION ARE STORED IN THE ARRAY WM.\nC     INTEGER MATRIX INFORMATION IS STORED IN\nC     THE ARRAY IWM.\nC     FOR A DENSE MATRIX, THE LAPACK ROUTINE\nC     DGETRS IS CALLED.\nC     FOR A BANDED MATRIX,THE LAPACK ROUTINE\nC     DGBTRS IS CALLED.\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED  DGBTRS, DGETRF\nC***REVISION HISTORY  (YYMMDD)\nC   830315  DATE WRITTEN\nC   901009  Finished conversion to SLATEC 4.0 format (F.N.Fritsch)\nC   901019  Merged changes made by C. Ulrich with SLATEC 4.0 format.\nC   901026  Added explicit declarations for all variables and minor\nC           cosmetic changes to prologue.  (FNF)\nC   020204  Convert to use LAPACK\nC***END PROLOGUE  DDASLV\nC\n      INTEGER  NEQ, IWM(*)\n      DOUBLE PRECISION  DELTA(*), WM(*)\nC\n      EXTERNAL  DGBTRS, DGETRS\nC\n      INTEGER  LIPVT, LML, LMU, LMTYPE, MEBAND, MTYPE, NPD, INFO\n      PARAMETER (NPD=1)\n      PARAMETER (LML=1)\n      PARAMETER (LMU=2)\n      PARAMETER (LMTYPE=4)\n      PARAMETER (LIPVT=22)\nC\nC***FIRST EXECUTABLE STATEMENT  DDASLV\n      MTYPE=IWM(LMTYPE)\n      GO TO(100,100,300,400,400),MTYPE\nC\nC     DENSE MATRIX\n100   CALL DGETRS('N', NEQ, 1, WM(NPD), NEQ, IWM(LIPVT), DELTA, NEQ,\n     *     INFO)\n      RETURN\nC\nC     DUMMY SECTION FOR MTYPE=3\n300   CONTINUE\n      RETURN\nC\nC     BANDED MATRIX\n400   MEBAND=2*IWM(LML)+IWM(LMU)+1\n      CALL DGBTRS ('N', NEQ, IWM(LML), IWM(LMU), 1, WM(NPD), MEBAND,\n     *     IWM(LIPVT), DELTA, NEQ, INLPCK)\n      RETURN\nC------END OF SUBROUTINE DDASLV------\n      END\n"
  },
  {
    "path": "liboctave/external/dassl/ddassl.f",
    "content": "      SUBROUTINE DDASSL (RES, NEQ, T, Y, YPRIME, TOUT, INFO, RTOL, ATOL,\n     +   IDID, RWORK, LRW, IWORK, LIW, RPAR, IPAR, JAC)\nC***BEGIN PROLOGUE  DDASSL\nC***PURPOSE  This code solves a system of differential/algebraic\nC            equations of the form G(T,Y,YPRIME) = 0.\nC***LIBRARY   SLATEC (DASSL)\nC***CATEGORY  I1A2\nC***TYPE      DOUBLE PRECISION (SDASSL-S, DDASSL-D)\nC***KEYWORDS  DIFFERENTIAL/ALGEBRAIC, BACKWARD DIFFERENTIATION FORMULAS,\nC             IMPLICIT DIFFERENTIAL SYSTEMS\nC***AUTHOR  PETZOLD, LINDA R., (LLNL)\nC             COMPUTING AND MATHEMATICS RESEARCH DIVISION\nC             LAWRENCE LIVERMORE NATIONAL LABORATORY\nC             L - 316, P.O. BOX 808,\nC             LIVERMORE, CA.    94550\nC***DESCRIPTION\nC\nC *Usage:\nC\nC      EXTERNAL RES, JAC\nC      INTEGER NEQ, INFO(N), IDID, LRW, LIW, IWORK(LIW), IPAR\nC      DOUBLE PRECISION T, Y(NEQ), YPRIME(NEQ), TOUT, RTOL, ATOL,\nC     *   RWORK(LRW), RPAR\nC\nC      CALL DDASSL (RES, NEQ, T, Y, YPRIME, TOUT, INFO, RTOL, ATOL,\nC     *   IDID, RWORK, LRW, IWORK, LIW, RPAR, IPAR, JAC)\nC\nC\nC *Arguments:\nC  (In the following, all real arrays should be type DOUBLE PRECISION.)\nC\nC  RES:EXT     This is a subroutine which you provide to define the\nC              differential/algebraic system.\nC\nC  NEQ:IN      This is the number of equations to be solved.\nC\nC  T:INOUT     This is the current value of the independent variable.\nC\nC  Y(*):INOUT  This array contains the solution components at T.\nC\nC  YPRIME(*):INOUT  This array contains the derivatives of the solution\nC              components at T.\nC\nC  TOUT:IN     This is a point at which a solution is desired.\nC\nC  INFO(N):IN  The basic task of the code is to solve the system from T\nC              to TOUT and return an answer at TOUT.  INFO is an integer\nC              array which is used to communicate exactly how you want\nC              this task to be carried out.  (See below for details.)\nC              N must be greater than or equal to 15.\nC\nC  RTOL,ATOL:INOUT  These quantities represent relative and absolute\nC              error tolerances which you provide to indicate how\nC              accurately you wish the solution to be computed.  You\nC              may choose them to be both scalars or else both vectors.\nC              Caution:  In Fortran 77, a scalar is not the same as an\nC                        array of length 1.  Some compilers may object\nC                        to using scalars for RTOL,ATOL.\nC\nC  IDID:OUT    This scalar quantity is an indicator reporting what the\nC              code did.  You must monitor this integer variable to\nC              decide  what action to take next.\nC\nC  RWORK:WORK  A real work array of length LRW which provides the\nC              code with needed storage space.\nC\nC  LRW:IN      The length of RWORK.  (See below for required length.)\nC\nC  IWORK:WORK  An integer work array of length LIW which probides the\nC              code with needed storage space.\nC\nC  LIW:IN      The length of IWORK.  (See below for required length.)\nC\nC  RPAR,IPAR:IN  These are real and integer parameter arrays which\nC              you can use for communication between your calling\nC              program and the RES subroutine (and the JAC subroutine)\nC\nC  JAC:EXT     This is the name of a subroutine which you may choose\nC              to provide for defining a matrix of partial derivatives\nC              described below.\nC\nC  Quantities which may be altered by DDASSL are:\nC     T, Y(*), YPRIME(*), INFO(1), RTOL, ATOL,\nC     IDID, RWORK(*) AND IWORK(*)\nC\nC *Description\nC\nC  Subroutine DDASSL uses the backward differentiation formulas of\nC  orders one through five to solve a system of the above form for Y and\nC  YPRIME.  Values for Y and YPRIME at the initial time must be given as\nC  input.  These values must be consistent, (that is, if T,Y,YPRIME are\nC  the given initial values, they must satisfy G(T,Y,YPRIME) = 0.).  The\nC  subroutine solves the system from T to TOUT.  It is easy to continue\nC  the solution to get results at additional TOUT.  This is the interval\nC  mode of operation.  Intermediate results can also be obtained easily\nC  by using the intermediate-output capability.\nC\nC  The following detailed description is divided into subsections:\nC    1. Input required for the first call to DDASSL.\nC    2. Output after any return from DDASSL.\nC    3. What to do to continue the integration.\nC    4. Error messages.\nC\nC\nC  -------- INPUT -- WHAT TO DO ON THE FIRST CALL TO DDASSL ------------\nC\nC  The first call of the code is defined to be the start of each new\nC  problem. Read through the descriptions of all the following items,\nC  provide sufficient storage space for designated arrays, set\nC  appropriate variables for the initialization of the problem, and\nC  give information about how you want the problem to be solved.\nC\nC\nC  RES -- Provide a subroutine of the form\nC             SUBROUTINE RES(T,Y,YPRIME,DELTA,IRES,RPAR,IPAR)\nC         to define the system of differential/algebraic\nC         equations which is to be solved. For the given values\nC         of T,Y and YPRIME, the subroutine should\nC         return the residual of the defferential/algebraic\nC         system\nC             DELTA = G(T,Y,YPRIME)\nC         (DELTA(*) is a vector of length NEQ which is\nC         output for RES.)\nC\nC         Subroutine RES must not alter T,Y or YPRIME.\nC         You must declare the name RES in an external\nC         statement in your program that calls DDASSL.\nC         You must dimension Y,YPRIME and DELTA in RES.\nC\nC         IRES is an integer flag which is always equal to\nC         zero on input. Subroutine RES should alter IRES\nC         only if it encounters an illegal value of Y or\nC         a stop condition. Set IRES = -1 if an input value\nC         is illegal, and DDASSL will try to solve the problem\nC         without getting IRES = -1. If IRES = -2, DDASSL\nC         will return control to the calling program\nC         with IDID = -11.\nC\nC         RPAR and IPAR are real and integer parameter arrays which\nC         you can use for communication between your calling program\nC         and subroutine RES. They are not altered by DDASSL. If you\nC         do not need RPAR or IPAR, ignore these parameters by treat-\nC         ing them as dummy arguments. If you do choose to use them,\nC         dimension them in your calling program and in RES as arrays\nC         of appropriate length.\nC\nC  NEQ -- Set it to the number of differential equations.\nC         (NEQ .GE. 1)\nC\nC  T -- Set it to the initial point of the integration.\nC         T must be defined as a variable.\nC\nC  Y(*) -- Set this vector to the initial values of the NEQ solution\nC         components at the initial point. You must dimension Y of\nC         length at least NEQ in your calling program.\nC\nC  YPRIME(*) -- Set this vector to the initial values of the NEQ\nC         first derivatives of the solution components at the initial\nC         point.  You must dimension YPRIME at least NEQ in your\nC         calling program. If you do not know initial values of some\nC         of the solution components, see the explanation of INFO(11).\nC\nC  TOUT -- Set it to the first point at which a solution\nC         is desired. You can not take TOUT = T.\nC         integration either forward in T (TOUT .GT. T) or\nC         backward in T (TOUT .LT. T) is permitted.\nC\nC         The code advances the solution from T to TOUT using\nC         step sizes which are automatically selected so as to\nC         achieve the desired accuracy. If you wish, the code will\nC         return with the solution and its derivative at\nC         intermediate steps (intermediate-output mode) so that\nC         you can monitor them, but you still must provide TOUT in\nC         accord with the basic aim of the code.\nC\nC         The first step taken by the code is a critical one\nC         because it must reflect how fast the solution changes near\nC         the initial point. The code automatically selects an\nC         initial step size which is practically always suitable for\nC         the problem. By using the fact that the code will not step\nC         past TOUT in the first step, you could, if necessary,\nC         restrict the length of the initial step size.\nC\nC         For some problems it may not be permissible to integrate\nC         past a point TSTOP because a discontinuity occurs there\nC         or the solution or its derivative is not defined beyond\nC         TSTOP. When you have declared a TSTOP point (SEE INFO(4)\nC         and RWORK(1)), you have told the code not to integrate\nC         past TSTOP. In this case any TOUT beyond TSTOP is invalid\nC         input.\nC\nC  INFO(*) -- Use the INFO array to give the code more details about\nC         how you want your problem solved.  This array should be\nC         dimensioned of length 15, though DDASSL uses only the first\nC         eleven entries.  You must respond to all of the following\nC         items, which are arranged as questions.  The simplest use\nC         of the code corresponds to answering all questions as yes,\nC         i.e. setting all entries of INFO to 0.\nC\nC       INFO(1) - This parameter enables the code to initialize\nC              itself. You must set it to indicate the start of every\nC              new problem.\nC\nC          **** Is this the first call for this problem ...\nC                Yes - Set INFO(1) = 0\nC                 No - Not applicable here.\nC                      See below for continuation calls.  ****\nC\nC       INFO(2) - How much accuracy you want of your solution\nC              is specified by the error tolerances RTOL and ATOL.\nC              The simplest use is to take them both to be scalars.\nC              To obtain more flexibility, they can both be vectors.\nC              The code must be told your choice.\nC\nC          **** Are both error tolerances RTOL, ATOL scalars ...\nC                Yes - Set INFO(2) = 0\nC                      and input scalars for both RTOL and ATOL\nC                 No - Set INFO(2) = 1\nC                      and input arrays for both RTOL and ATOL ****\nC\nC       INFO(3) - The code integrates from T in the direction\nC              of TOUT by steps. If you wish, it will return the\nC              computed solution and derivative at the next\nC              intermediate step (the intermediate-output mode) or\nC              TOUT, whichever comes first. This is a good way to\nC              proceed if you want to see the behavior of the solution.\nC              If you must have solutions at a great many specific\nC              TOUT points, this code will compute them efficiently.\nC\nC          **** Do you want the solution only at\nC                TOUT (and not at the next intermediate step) ...\nC                 Yes - Set INFO(3) = 0\nC                  No - Set INFO(3) = 1 ****\nC\nC       INFO(4) - To handle solutions at a great many specific\nC              values TOUT efficiently, this code may integrate past\nC              TOUT and interpolate to obtain the result at TOUT.\nC              Sometimes it is not possible to integrate beyond some\nC              point TSTOP because the equation changes there or it is\nC              not defined past TSTOP. Then you must tell the code\nC              not to go past.\nC\nC           **** Can the integration be carried out without any\nC                restrictions on the independent variable T ...\nC                 Yes - Set INFO(4)=0\nC                  No - Set INFO(4)=1\nC                       and define the stopping point TSTOP by\nC                       setting RWORK(1)=TSTOP ****\nC\nC       INFO(5) - To solve differential/algebraic problems it is\nC              necessary to use a matrix of partial derivatives of the\nC              system of differential equations. If you do not\nC              provide a subroutine to evaluate it analytically (see\nC              description of the item JAC in the call list), it will\nC              be approximated by numerical differencing in this code.\nC              although it is less trouble for you to have the code\nC              compute partial derivatives by numerical differencing,\nC              the solution will be more reliable if you provide the\nC              derivatives via JAC. Sometimes numerical differencing\nC              is cheaper than evaluating derivatives in JAC and\nC              sometimes it is not - this depends on your problem.\nC\nC           **** Do you want the code to evaluate the partial\nC                derivatives automatically by numerical differences ...\nC                   Yes - Set INFO(5)=0\nC                    No - Set INFO(5)=1\nC                  and provide subroutine JAC for evaluating the\nC                  matrix of partial derivatives ****\nC\nC       INFO(6) - DDASSL will perform much better if the matrix of\nC              partial derivatives, DG/DY + CJ*DG/DYPRIME,\nC              (here CJ is a scalar determined by DDASSL)\nC              is banded and the code is told this. In this\nC              case, the storage needed will be greatly reduced,\nC              numerical differencing will be performed much cheaper,\nC              and a number of important algorithms will execute much\nC              faster. The differential equation is said to have\nC              half-bandwidths ML (lower) and MU (upper) if equation i\nC              involves only unknowns Y(J) with\nC                             I-ML .LE. J .LE. I+MU\nC              for all I=1,2,...,NEQ. Thus, ML and MU are the widths\nC              of the lower and upper parts of the band, respectively,\nC              with the main diagonal being excluded. If you do not\nC              indicate that the equation has a banded matrix of partial\nC              derivatives, the code works with a full matrix of NEQ**2\nC              elements (stored in the conventional way). Computations\nC              with banded matrices cost less time and storage than with\nC              full matrices if 2*ML+MU .LT. NEQ. If you tell the\nC              code that the matrix of partial derivatives has a banded\nC              structure and you want to provide subroutine JAC to\nC              compute the partial derivatives, then you must be careful\nC              to store the elements of the matrix in the special form\nC              indicated in the description of JAC.\nC\nC          **** Do you want to solve the problem using a full\nC               (dense) matrix (and not a special banded\nC               structure) ...\nC                Yes - Set INFO(6)=0\nC                 No - Set INFO(6)=1\nC                       and provide the lower (ML) and upper (MU)\nC                       bandwidths by setting\nC                       IWORK(1)=ML\nC                       IWORK(2)=MU ****\nC\nC\nC        INFO(7) -- You can specify a maximum (absolute value of)\nC              stepsize, so that the code\nC              will avoid passing over very\nC              large regions.\nC\nC          ****  Do you want the code to decide\nC                on its own maximum stepsize?\nC                Yes - Set INFO(7)=0\nC                 No - Set INFO(7)=1\nC                      and define HMAX by setting\nC                      RWORK(2)=HMAX ****\nC\nC        INFO(8) -- Differential/algebraic problems\nC              may occaisionally suffer from\nC              severe scaling difficulties on the\nC              first step. If you know a great deal\nC              about the scaling of your problem, you can\nC              help to alleviate this problem by\nC              specifying an initial stepsize HO.\nC\nC          ****  Do you want the code to define\nC                its own initial stepsize?\nC                Yes - Set INFO(8)=0\nC                 No - Set INFO(8)=1\nC                      and define HO by setting\nC                      RWORK(3)=HO ****\nC\nC        INFO(9) -- If storage is a severe problem,\nC              you can save some locations by\nC              restricting the maximum order MAXORD.\nC              the default value is 5. for each\nC              order decrease below 5, the code\nC              requires NEQ fewer locations, however\nC              it is likely to be slower. In any\nC              case, you must have 1 .LE. MAXORD .LE. 5\nC          ****  Do you want the maximum order to\nC                default to 5?\nC                Yes - Set INFO(9)=0\nC                 No - Set INFO(9)=1\nC                      and define MAXORD by setting\nC                      IWORK(3)=MAXORD ****\nC\nC        INFO(10) --If you know that the solutions to your equations\nC               will always be nonnegative, it may help to set this\nC               parameter. However, it is probably best to\nC               try the code without using this option first,\nC               and only to use this option if that doesn't\nC               work very well.\nC           ****  Do you want the code to solve the problem without\nC                 invoking any special nonnegativity constraints?\nC                  Yes - Set INFO(10)=0\nC                   No - Set INFO(10)=1\nC\nC        INFO(11) --DDASSL normally requires the initial T,\nC               Y, and YPRIME to be consistent. That is,\nC               you must have G(T,Y,YPRIME) = 0 at the initial\nC               time. If you do not know the initial\nC               derivative precisely, you can let DDASSL try\nC               to compute it.\nC          ****   Are the initialHE INITIAL T, Y, YPRIME consistent?\nC                 Yes - Set INFO(11) = 0\nC                  No - Set INFO(11) = 1,\nC                       and set YPRIME to an initial approximation\nC                       to YPRIME.  (If you have no idea what\nC                       YPRIME should be, set it to zero. Note\nC                       that the initial Y should be such\nC                       that there must exist a YPRIME so that\nC                       G(T,Y,YPRIME) = 0.)\nC\nC  RTOL, ATOL -- You must assign relative (RTOL) and absolute (ATOL\nC         error tolerances to tell the code how accurately you\nC         want the solution to be computed.  They must be defined\nC         as variables because the code may change them.  You\nC         have two choices --\nC               Both RTOL and ATOL are scalars. (INFO(2)=0)\nC               Both RTOL and ATOL are vectors. (INFO(2)=1)\nC         in either case all components must be non-negative.\nC\nC         The tolerances are used by the code in a local error\nC         test at each step which requires roughly that\nC               ABS(LOCAL ERROR) .LE. RTOL*ABS(Y)+ATOL\nC         for each vector component.\nC         (More specifically, a root-mean-square norm is used to\nC         measure the size of vectors, and the error test uses the\nC         magnitude of the solution at the beginning of the step.)\nC\nC         The true (global) error is the difference between the\nC         true solution of the initial value problem and the\nC         computed approximation.  Practically all present day\nC         codes, including this one, control the local error at\nC         each step and do not even attempt to control the global\nC         error directly.\nC         Usually, but not always, the true accuracy of the\nC         computed Y is comparable to the error tolerances. This\nC         code will usually, but not always, deliver a more\nC         accurate solution if you reduce the tolerances and\nC         integrate again.  By comparing two such solutions you\nC         can get a fairly reliable idea of the true error in the\nC         solution at the bigger tolerances.\nC\nC         Setting ATOL=0. results in a pure relative error test on\nC         that component.  Setting RTOL=0. results in a pure\nC         absolute error test on that component.  A mixed test\nC         with non-zero RTOL and ATOL corresponds roughly to a\nC         relative error test when the solution component is much\nC         bigger than ATOL and to an absolute error test when the\nC         solution component is smaller than the threshhold ATOL.\nC\nC         The code will not attempt to compute a solution at an\nC         accuracy unreasonable for the machine being used.  It will\nC         advise you if you ask for too much accuracy and inform\nC         you as to the maximum accuracy it believes possible.\nC\nC  RWORK(*) --  Dimension this real work array of length LRW in your\nC         calling program.\nC\nC  LRW -- Set it to the declared length of the RWORK array.\nC               You must have\nC                    LRW .GE. 40+(MAXORD+4)*NEQ+NEQ**2\nC               for the full (dense) JACOBIAN case (when INFO(6)=0), or\nC                    LRW .GE. 40+(MAXORD+4)*NEQ+(2*ML+MU+1)*NEQ\nC               for the banded user-defined JACOBIAN case\nC               (when INFO(5)=1 and INFO(6)=1), or\nC                     LRW .GE. 40+(MAXORD+4)*NEQ+(2*ML+MU+1)*NEQ\nC                           +2*(NEQ/(ML+MU+1)+1)\nC               for the banded finite-difference-generated JACOBIAN case\nC               (when INFO(5)=0 and INFO(6)=1)\nC\nC  IWORK(*) --  Dimension this integer work array of length LIW in\nC         your calling program.\nC\nC  LIW -- Set it to the declared length of the IWORK array.\nC               You must have LIW .GE. 21+NEQ\nC\nC  RPAR, IPAR -- These are parameter arrays, of real and integer\nC         type, respectively.  You can use them for communication\nC         between your program that calls DDASSL and the\nC         RES subroutine (and the JAC subroutine).  They are not\nC         altered by DDASSL.  If you do not need RPAR or IPAR,\nC         ignore these parameters by treating them as dummy\nC         arguments.  If you do choose to use them, dimension\nC         them in your calling program and in RES (and in JAC)\nC         as arrays of appropriate length.\nC\nC  JAC -- If you have set INFO(5)=0, you can ignore this parameter\nC         by treating it as a dummy argument.  Otherwise, you must\nC         provide a subroutine of the form\nC             SUBROUTINE JAC(T,Y,YPRIME,PD,CJ,RPAR,IPAR)\nC         to define the matrix of partial derivatives\nC             PD=DG/DY+CJ*DG/DYPRIME\nC         CJ is a scalar which is input to JAC.\nC         For the given values of T,Y,YPRIME, the\nC         subroutine must evaluate the non-zero partial\nC         derivatives for each equation and each solution\nC         component, and store these values in the\nC         matrix PD.  The elements of PD are set to zero\nC         before each call to JAC so only non-zero elements\nC         need to be defined.\nC\nC         Subroutine JAC must not alter T,Y,(*),YPRIME(*), or CJ.\nC         You must declare the name JAC in an EXTERNAL statement in\nC         your program that calls DDASSL.  You must dimension Y,\nC         YPRIME and PD in JAC.\nC\nC         The way you must store the elements into the PD matrix\nC         depends on the structure of the matrix which you\nC         indicated by INFO(6).\nC               *** INFO(6)=0 -- Full (dense) matrix ***\nC                   Give PD a first dimension of NEQ.\nC                   When you evaluate the (non-zero) partial derivative\nC                   of equation I with respect to variable J, you must\nC                   store it in PD according to\nC                   PD(I,J) = \"DG(I)/DY(J)+CJ*DG(I)/DYPRIME(J)\"\nC               *** INFO(6)=1 -- Banded JACOBIAN with ML lower and MU\nC                   upper diagonal bands (refer to INFO(6) description\nC                   of ML and MU) ***\nC                   Give PD a first dimension of 2*ML+MU+1.\nC                   when you evaluate the (non-zero) partial derivative\nC                   of equation I with respect to variable J, you must\nC                   store it in PD according to\nC                   IROW = I - J + ML + MU + 1\nC                   PD(IROW,J) = \"DG(I)/DY(J)+CJ*DG(I)/DYPRIME(J)\"\nC\nC         RPAR and IPAR are real and integer parameter arrays\nC         which you can use for communication between your calling\nC         program and your JACOBIAN subroutine JAC. They are not\nC         altered by DDASSL. If you do not need RPAR or IPAR,\nC         ignore these parameters by treating them as dummy\nC         arguments. If you do choose to use them, dimension\nC         them in your calling program and in JAC as arrays of\nC         appropriate length.\nC\nC\nC  OPTIONALLY REPLACEABLE NORM ROUTINE:\nC\nC     DDASSL uses a weighted norm DDANRM to measure the size\nC     of vectors such as the estimated error in each step.\nC     A FUNCTION subprogram\nC       DOUBLE PRECISION FUNCTION DDANRM(NEQ,V,WT,RPAR,IPAR)\nC       DIMENSION V(NEQ),WT(NEQ)\nC     is used to define this norm. Here, V is the vector\nC     whose norm is to be computed, and WT is a vector of\nC     weights.  A DDANRM routine has been included with DDASSL\nC     which computes the weighted root-mean-square norm\nC     given by\nC       DDANRM=SQRT((1/NEQ)*SUM(V(I)/WT(I))**2)\nC     this norm is suitable for most problems. In some\nC     special cases, it may be more convenient and/or\nC     efficient to define your own norm by writing a function\nC     subprogram to be called instead of DDANRM. This should,\nC     however, be attempted only after careful thought and\nC     consideration.\nC\nC\nC  -------- OUTPUT -- AFTER ANY RETURN FROM DDASSL ---------------------\nC\nC  The principal aim of the code is to return a computed solution at\nC  TOUT, although it is also possible to obtain intermediate results\nC  along the way. To find out whether the code achieved its goal\nC  or if the integration process was interrupted before the task was\nC  completed, you must check the IDID parameter.\nC\nC\nC  T -- The solution was successfully advanced to the\nC               output value of T.\nC\nC  Y(*) -- Contains the computed solution approximation at T.\nC\nC  YPRIME(*) -- Contains the computed derivative\nC               approximation at T.\nC\nC  IDID -- Reports what the code did.\nC\nC                     *** Task completed ***\nC                Reported by positive values of IDID\nC\nC           IDID = 1 -- A step was successfully taken in the\nC                   intermediate-output mode. The code has not\nC                   yet reached TOUT.\nC\nC           IDID = 2 -- The integration to TSTOP was successfully\nC                   completed (T=TSTOP) by stepping exactly to TSTOP.\nC\nC           IDID = 3 -- The integration to TOUT was successfully\nC                   completed (T=TOUT) by stepping past TOUT.\nC                   Y(*) is obtained by interpolation.\nC                   YPRIME(*) is obtained by interpolation.\nC\nC                    *** Task interrupted ***\nC                Reported by negative values of IDID\nC\nC           IDID = -1 -- A large amount of work has been expended.\nC                   (About 500 steps)\nC\nC           IDID = -2 -- The error tolerances are too stringent.\nC\nC           IDID = -3 -- The local error test cannot be satisfied\nC                   because you specified a zero component in ATOL\nC                   and the corresponding computed solution\nC                   component is zero. Thus, a pure relative error\nC                   test is impossible for this component.\nC\nC           IDID = -6 -- DDASSL had repeated error test\nC                   failures on the last attempted step.\nC\nC           IDID = -7 -- The corrector could not converge.\nC\nC           IDID = -8 -- The matrix of partial derivatives\nC                   is singular.\nC\nC           IDID = -9 -- The corrector could not converge.\nC                   there were repeated error test failures\nC                   in this step.\nC\nC           IDID =-10 -- The corrector could not converge\nC                   because IRES was equal to minus one.\nC\nC           IDID =-11 -- IRES equal to -2 was encountered\nC                   and control is being returned to the\nC                   calling program.\nC\nC           IDID =-12 -- DDASSL failed to compute the initial\nC                   YPRIME.\nC\nC\nC\nC           IDID = -13,..,-32 -- Not applicable for this code\nC\nC                    *** Task terminated ***\nC                Reported by the value of IDID=-33\nC\nC           IDID = -33 -- The code has encountered trouble from which\nC                   it cannot recover. A message is printed\nC                   explaining the trouble and control is returned\nC                   to the calling program. For example, this occurs\nC                   when invalid input is detected.\nC\nC  RTOL, ATOL -- These quantities remain unchanged except when\nC               IDID = -2. In this case, the error tolerances have been\nC               increased by the code to values which are estimated to\nC               be appropriate for continuing the integration. However,\nC               the reported solution at T was obtained using the input\nC               values of RTOL and ATOL.\nC\nC  RWORK, IWORK -- Contain information which is usually of no\nC               interest to the user but necessary for subsequent calls.\nC               However, you may find use for\nC\nC               RWORK(3)--Which contains the step size H to be\nC                       attempted on the next step.\nC\nC               RWORK(4)--Which contains the current value of the\nC                       independent variable, i.e., the farthest point\nC                       integration has reached. This will be different\nC                       from T only when interpolation has been\nC                       performed (IDID=3).\nC\nC               RWORK(7)--Which contains the stepsize used\nC                       on the last successful step.\nC\nC               IWORK(7)--Which contains the order of the method to\nC                       be attempted on the next step.\nC\nC               IWORK(8)--Which contains the order of the method used\nC                       on the last step.\nC\nC               IWORK(11)--Which contains the number of steps taken so\nC                        far.\nC\nC               IWORK(12)--Which contains the number of calls to RES\nC                        so far.\nC\nC               IWORK(13)--Which contains the number of evaluations of\nC                        the matrix of partial derivatives needed so\nC                        far.\nC\nC               IWORK(14)--Which contains the total number\nC                        of error test failures so far.\nC\nC               IWORK(15)--Which contains the total number\nC                        of convergence test failures so far.\nC                        (includes singular iteration matrix\nC                        failures.)\nC\nC\nC  -------- INPUT -- WHAT TO DO TO CONTINUE THE INTEGRATION ------------\nC                    (CALLS AFTER THE FIRST)\nC\nC  This code is organized so that subsequent calls to continue the\nC  integration involve little (if any) additional effort on your\nC  part. You must monitor the IDID parameter in order to determine\nC  what to do next.\nC\nC  Recalling that the principal task of the code is to integrate\nC  from T to TOUT (the interval mode), usually all you will need\nC  to do is specify a new TOUT upon reaching the current TOUT.\nC\nC  Do not alter any quantity not specifically permitted below,\nC  in particular do not alter NEQ,T,Y(*),YPRIME(*),RWORK(*),IWORK(*)\nC  or the differential equation in subroutine RES. Any such\nC  alteration constitutes a new problem and must be treated as such,\nC  i.e., you must start afresh.\nC\nC  You cannot change from vector to scalar error control or vice\nC  versa (INFO(2)), but you can change the size of the entries of\nC  RTOL, ATOL. Increasing a tolerance makes the equation easier\nC  to integrate. Decreasing a tolerance will make the equation\nC  harder to integrate and should generally be avoided.\nC\nC  You can switch from the intermediate-output mode to the\nC  interval mode (INFO(3)) or vice versa at any time.\nC\nC  If it has been necessary to prevent the integration from going\nC  past a point TSTOP (INFO(4), RWORK(1)), keep in mind that the\nC  code will not integrate to any TOUT beyond the currently\nC  specified TSTOP. Once TSTOP has been reached you must change\nC  the value of TSTOP or set INFO(4)=0. You may change INFO(4)\nC  or TSTOP at any time but you must supply the value of TSTOP in\nC  RWORK(1) whenever you set INFO(4)=1.\nC\nC  Do not change INFO(5), INFO(6), IWORK(1), or IWORK(2)\nC  unless you are going to restart the code.\nC\nC                 *** Following a completed task ***\nC  If\nC     IDID = 1, call the code again to continue the integration\nC                  another step in the direction of TOUT.\nC\nC     IDID = 2 or 3, define a new TOUT and call the code again.\nC                  TOUT must be different from T. You cannot change\nC                  the direction of integration without restarting.\nC\nC                 *** Following an interrupted task ***\nC               To show the code that you realize the task was\nC               interrupted and that you want to continue, you\nC               must take appropriate action and set INFO(1) = 1\nC  If\nC    IDID = -1, The code has taken about 500 steps.\nC                  If you want to continue, set INFO(1) = 1 and\nC                  call the code again. An additional 500 steps\nC                  will be allowed.\nC\nC    IDID = -2, The error tolerances RTOL, ATOL have been\nC                  increased to values the code estimates appropriate\nC                  for continuing. You may want to change them\nC                  yourself. If you are sure you want to continue\nC                  with relaxed error tolerances, set INFO(1)=1 and\nC                  call the code again.\nC\nC    IDID = -3, A solution component is zero and you set the\nC                  corresponding component of ATOL to zero. If you\nC                  are sure you want to continue, you must first\nC                  alter the error criterion to use positive values\nC                  for those components of ATOL corresponding to zero\nC                  solution components, then set INFO(1)=1 and call\nC                  the code again.\nC\nC    IDID = -4,-5  --- Cannot occur with this code.\nC\nC    IDID = -6, Repeated error test failures occurred on the\nC                  last attempted step in DDASSL. A singularity in the\nC                  solution may be present. If you are absolutely\nC                  certain you want to continue, you should restart\nC                  the integration. (Provide initial values of Y and\nC                  YPRIME which are consistent)\nC\nC    IDID = -7, Repeated convergence test failures occurred\nC                  on the last attempted step in DDASSL. An inaccurate\nC                  or ill-conditioned JACOBIAN may be the problem. If\nC                  you are absolutely certain you want to continue, you\nC                  should restart the integration.\nC\nC    IDID = -8, The matrix of partial derivatives is singular.\nC                  Some of your equations may be redundant.\nC                  DDASSL cannot solve the problem as stated.\nC                  It is possible that the redundant equations\nC                  could be removed, and then DDASSL could\nC                  solve the problem. It is also possible\nC                  that a solution to your problem either\nC                  does not exist or is not unique.\nC\nC    IDID = -9, DDASSL had multiple convergence test\nC                  failures, preceeded by multiple error\nC                  test failures, on the last attempted step.\nC                  It is possible that your problem\nC                  is ill-posed, and cannot be solved\nC                  using this code. Or, there may be a\nC                  discontinuity or a singularity in the\nC                  solution. If you are absolutely certain\nC                  you want to continue, you should restart\nC                  the integration.\nC\nC    IDID =-10, DDASSL had multiple convergence test failures\nC                  because IRES was equal to minus one.\nC                  If you are absolutely certain you want\nC                  to continue, you should restart the\nC                  integration.\nC\nC    IDID =-11, IRES=-2 was encountered, and control is being\nC                  returned to the calling program.\nC\nC    IDID =-12, DDASSL failed to compute the initial YPRIME.\nC                  This could happen because the initial\nC                  approximation to YPRIME was not very good, or\nC                  if a YPRIME consistent with the initial Y\nC                  does not exist. The problem could also be caused\nC                  by an inaccurate or singular iteration matrix.\nC\nC    IDID = -13,..,-32  --- Cannot occur with this code.\nC\nC\nC                 *** Following a terminated task ***\nC\nC  If IDID= -33, you cannot continue the solution of this problem.\nC                  An attempt to do so will result in your\nC                  run being terminated.\nC\nC\nC  -------- ERROR MESSAGES ---------------------------------------------\nC\nC      The SLATEC error print routine XERMSG is called in the event of\nC   unsuccessful completion of a task.  Most of these are treated as\nC   \"recoverable errors\", which means that (unless the user has directed\nC   otherwise) control will be returned to the calling program for\nC   possible action after the message has been printed.\nC\nC   In the event of a negative value of IDID other than -33, an appro-\nC   priate message is printed and the \"error number\" printed by XERMSG\nC   is the value of IDID.  There are quite a number of illegal input\nC   errors that can lead to a returned value IDID=-33.  The conditions\nC   and their printed \"error numbers\" are as follows:\nC\nC   Error number       Condition\nC\nC        1       Some element of INFO vector is not zero or one.\nC        2       NEQ .le. 0\nC        3       MAXORD not in range.\nC        4       LRW is less than the required length for RWORK.\nC        5       LIW is less than the required length for IWORK.\nC        6       Some element of RTOL is .lt. 0\nC        7       Some element of ATOL is .lt. 0\nC        8       All elements of RTOL and ATOL are zero.\nC        9       INFO(4)=1 and TSTOP is behind TOUT.\nC       10       HMAX .lt. 0.0\nC       11       TOUT is behind T.\nC       12       INFO(8)=1 and H0=0.0\nC       13       Some element of WT is .le. 0.0\nC       14       TOUT is too close to T to start integration.\nC       15       INFO(4)=1 and TSTOP is behind T.\nC       16       --( Not used in this version )--\nC       17       ML illegal.  Either .lt. 0 or .gt. NEQ\nC       18       MU illegal.  Either .lt. 0 or .gt. NEQ\nC       19       TOUT = T.\nC\nC   If DDASSL is called again without any action taken to remove the\nC   cause of an unsuccessful return, XERMSG will be called with a fatal\nC   error flag, which will cause unconditional termination of the\nC   program.  There are two such fatal errors:\nC\nC   Error number -998:  The last step was terminated with a negative\nC       value of IDID other than -33, and no appropriate action was\nC       taken.\nC\nC   Error number -999:  The previous call was terminated because of\nC       illegal input (IDID=-33) and there is illegal input in the\nC       present call, as well.  (Suspect infinite loop.)\nC\nC  ---------------------------------------------------------------------\nC\nC***REFERENCES  A DESCRIPTION OF DASSL: A DIFFERENTIAL/ALGEBRAIC\nC                 SYSTEM SOLVER, L. R. PETZOLD, SAND82-8637,\nC                 SANDIA NATIONAL LABORATORIES, SEPTEMBER 1982.\nC***ROUTINES CALLED  D1MACH, DDAINI, DDANRM, DDASTP, DDATRP, DDAWTS,\nC                    XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   830315  DATE WRITTEN\nC   880387  Code changes made.  All common statements have been\nC           replaced by a DATA statement, which defines pointers into\nC           RWORK, and PARAMETER statements which define pointers\nC           into IWORK.  As well the documentation has gone through\nC           grammatical changes.\nC   881005  The prologue has been changed to mixed case.\nC           The subordinate routines had revision dates changed to\nC           this date, although the documentation for these routines\nC           is all upper case.  No code changes.\nC   890511  Code changes made.  The DATA statement in the declaration\nC           section of DDASSL was replaced with a PARAMETER\nC           statement.  Also the statement S = 100.D0 was removed\nC           from the top of the Newton iteration in DDASTP.\nC           The subordinate routines had revision dates changed to\nC           this date.\nC   890517  The revision date syntax was replaced with the revision\nC           history syntax.  Also the \"DECK\" comment was added to\nC           the top of all subroutines.  These changes are consistent\nC           with new SLATEC guidelines.\nC           The subordinate routines had revision dates changed to\nC           this date.  No code changes.\nC   891013  Code changes made.\nC           Removed all occurrances of FLOAT or DBLE.  All operations\nC           are now performed with \"mixed-mode\" arithmetic.\nC           Also, specific function names were replaced with generic\nC           function names to be consistent with new SLATEC guidelines.\nC           In particular:\nC              Replaced DSQRT with SQRT everywhere.\nC              Replaced DABS with ABS everywhere.\nC              Replaced DMIN1 with MIN everywhere.\nC              Replaced MIN0 with MIN everywhere.\nC              Replaced DMAX1 with MAX everywhere.\nC              Replaced MAX0 with MAX everywhere.\nC              Replaced DSIGN with SIGN everywhere.\nC           Also replaced REVISION DATE with REVISION HISTORY in all\nC           subordinate routines.\nC  901004  Miscellaneous changes to prologue to complete conversion\nC          to SLATEC 4.0 format.  No code changes.  (F.N.Fritsch)\nC  901009  Corrected GAMS classification code and converted subsidiary\nC          routines to 4.0 format.  No code changes.  (F.N.Fritsch)\nC  901010  Converted XERRWV calls to XERMSG calls.  (R.Clemens,AFWL)\nC  901019  Code changes made.\nC          Merged SLATEC 4.0 changes with previous changes made\nC          by C. Ulrich.  Below is a history of the changes made by\nC          C. Ulrich. (Changes in subsidiary routines are implied\nC          by this history)\nC          891228  Bug was found and repaired inside the DDASSL\nC                  and DDAINI routines.  DDAINI was incorrectly\nC                  returning the initial T with Y and YPRIME\nC                  computed at T+H.  The routine now returns T+H\nC                  rather than the initial T.\nC                  Cosmetic changes made to DDASTP.\nC          900904  Three modifications were made to fix a bug (inside\nC                  DDASSL) re interpolation for continuation calls and\nC                  cases where TN is very close to TSTOP:\nC\nC                  1) In testing for whether H is too large, just\nC                     compare H to (TSTOP - TN), rather than\nC                     (TSTOP - TN) * (1-4*UROUND), and set H to\nC                     TSTOP - TN.  This will force DDASTP to step\nC                     exactly to TSTOP under certain situations\nC                     (i.e. when H returned from DDASTP would otherwise\nC                     take TN beyond TSTOP).\nC\nC                  2) Inside the DDASTP loop, interpolate exactly to\nC                     TSTOP if TN is very close to TSTOP (rather than\nC                     interpolating to within roundoff of TSTOP).\nC\nC                  3) Modified IDID description for IDID = 2 to say that\nC                     the solution is returned by stepping exactly to\nC                     TSTOP, rather than TOUT.  (In some cases the\nC                     solution is actually obtained by extrapolating\nC                     over a distance near unit roundoff to TSTOP,\nC                     but this small distance is deemed acceptable in\nC                     these circumstances.)\nC   901026  Added explicit declarations for all variables and minor\nC           cosmetic changes to prologue, removed unreferenced labels,\nC           and improved XERMSG calls.  (FNF)\nC   901030  Added ERROR MESSAGES section and reworked other sections to\nC           be of more uniform format.  (FNF)\nC   910624  Fixed minor bug related to HMAX (five lines ending in\nC           statement 526 in DDASSL).   (LRP)\nC\nC***END PROLOGUE  DDASSL\nC\nC**End\nC\nC     Declare arguments.\nC\n      INTEGER  NEQ, INFO(15), IDID, LRW, IWORK(*), LIW, IPAR(*)\n      DOUBLE PRECISION\n     *   T, Y(*), YPRIME(*), TOUT, RTOL(*), ATOL(*), RWORK(*),\n     *   RPAR(*)\n      EXTERNAL  RES, JAC\nC\nC     Declare externals.\nC\n      EXTERNAL  D1MACH, DDAINI, DDANRM, DDASTP, DDATRP, DDAWTS, XERMSG\n      DOUBLE PRECISION  D1MACH, DDANRM\nC\nC     Declare local variables.\nC\n      INTEGER  I, ITEMP, LALPHA, LBETA, LCJ, LCJOLD, LCTF, LDELTA,\n     *   LENIW, LENPD, LENRW, LE, LETF, LGAMMA, LH, LHMAX, LHOLD,\n     *   LMXSTP, LIPVT,\n     *   LJCALC, LK, LKOLD, LIWM, LML, LMTYPE, LMU, LMXORD, LNJE, LNPD,\n     *   LNRE, LNS, LNST, LNSTL, LPD, LPHASE, LPHI, LPSI, LROUND, LS,\n     *   LSIGMA, LTN, LTSTOP, LWM, LWT, MBAND, MSAVE, MXORD, NPD, NTEMP,\n     *   NZFLG\n      DOUBLE PRECISION\n     *   ATOLI, H, HMAX, HMIN, HO, R, RH, RTOLI, TDIST, TN, TNEXT,\n     *   TSTOP, UROUND, YPNORM\n      LOGICAL  DONE\nC       Auxiliary variables for conversion of values to be included in\nC       error messages.\n      CHARACTER*8  XERN1, XERN2\n      CHARACTER*16 XERN3, XERN4\nC\nC     SET POINTERS INTO IWORK\n      PARAMETER (LML=1, LMU=2, LMXORD=3, LMTYPE=4, LNST=11,\n     *  LNRE=12, LNJE=13, LETF=14, LCTF=15, LNPD=16, LMXSTP=21,\n     *  LIPVT=22, LJCALC=5, LPHASE=6, LK=7, LKOLD=8,\n     *  LNS=9, LNSTL=10, LIWM=1)\nC\nC     SET RELATIVE OFFSET INTO RWORK\n      PARAMETER (NPD=1)\nC\nC     SET POINTERS INTO RWORK\n      PARAMETER (LTSTOP=1, LHMAX=2, LH=3, LTN=4,\n     *  LCJ=5, LCJOLD=6, LHOLD=7, LS=8, LROUND=9,\n     *  LALPHA=11, LBETA=17, LGAMMA=23,\n     *  LPSI=29, LSIGMA=35, LDELTA=41)\nC\nC***FIRST EXECUTABLE STATEMENT  DDASSL\n      IF(INFO(1).NE.0)GO TO 100\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK IS EXECUTED FOR THE INITIAL CALL ONLY.\nC     IT CONTAINS CHECKING OF INPUTS AND INITIALIZATIONS.\nC-----------------------------------------------------------------------\nC\nC     FIRST CHECK INFO ARRAY TO MAKE SURE ALL ELEMENTS OF INFO\nC     ARE EITHER ZERO OR ONE.\n      DO 10 I=2,11\n         IF(INFO(I).NE.0.AND.INFO(I).NE.1)GO TO 701\n10       CONTINUE\nC\n      IF(NEQ.LE.0)GO TO 702\nC\nC     CHECK AND COMPUTE MAXIMUM ORDER\n      MXORD=5\n      IF(INFO(9).EQ.0)GO TO 20\n         MXORD=IWORK(LMXORD)\n         IF(MXORD.LT.1.OR.MXORD.GT.5)GO TO 703\n20       IWORK(LMXORD)=MXORD\nC\nC     COMPUTE MTYPE,LENPD,LENRW.CHECK ML AND MU.\n      IF(INFO(6).NE.0)GO TO 40\n         LENPD=NEQ**2\n         LENRW=40+(IWORK(LMXORD)+4)*NEQ+LENPD\n         IF(INFO(5).NE.0)GO TO 30\n            IWORK(LMTYPE)=2\n            GO TO 60\n30          IWORK(LMTYPE)=1\n            GO TO 60\n40    IF(IWORK(LML).LT.0.OR.IWORK(LML).GE.NEQ)GO TO 717\n      IF(IWORK(LMU).LT.0.OR.IWORK(LMU).GE.NEQ)GO TO 718\n      LENPD=(2*IWORK(LML)+IWORK(LMU)+1)*NEQ\n      IF(INFO(5).NE.0)GO TO 50\n         IWORK(LMTYPE)=5\n         MBAND=IWORK(LML)+IWORK(LMU)+1\n         MSAVE=(NEQ/MBAND)+1\n         LENRW=40+(IWORK(LMXORD)+4)*NEQ+LENPD+2*MSAVE\n         GO TO 60\n50       IWORK(LMTYPE)=4\n         LENRW=40+(IWORK(LMXORD)+4)*NEQ+LENPD\nC\nC     CHECK LENGTHS OF RWORK AND IWORK\n60    LENIW=21+NEQ\n      IWORK(LNPD)=LENPD\n      IF(LRW.LT.LENRW)GO TO 704\n      IF(LIW.LT.LENIW)GO TO 705\nC\nC     CHECK TO SEE THAT TOUT IS DIFFERENT FROM T\n      IF(TOUT .EQ. T)GO TO 719\nC\nC     CHECK HMAX\n      IF(INFO(7).EQ.0)GO TO 70\n         HMAX=RWORK(LHMAX)\n         IF(HMAX.LE.0.0D0)GO TO 710\n70    CONTINUE\nC\nC     CHECK AND COMPUTE MAXIMUM STEPS\n      MXSTP=500\n      IF(INFO(12).EQ.0)GO TO 80\n        MXSTP=IWORK(LMXSTP)\n        IF(MXSTP.LT.0)GO TO 716\n80      IWORK(LMXSTP)=MXSTP\nC\nC     INITIALIZE COUNTERS\n      IWORK(LNST)=0\n      IWORK(LNRE)=0\n      IWORK(LNJE)=0\nC\n      IWORK(LNSTL)=0\n      IDID=1\n      GO TO 200\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK IS FOR CONTINUATION CALLS\nC     ONLY. HERE WE CHECK INFO(1),AND IF THE\nC     LAST STEP WAS INTERRUPTED WE CHECK WHETHER\nC     APPROPRIATE ACTION WAS TAKEN.\nC-----------------------------------------------------------------------\nC\n100   CONTINUE\n      IF(INFO(1).EQ.1)GO TO 110\n      IF(INFO(1).NE.-1)GO TO 701\nC\nC     IF WE ARE HERE, THE LAST STEP WAS INTERRUPTED\nC     BY AN ERROR CONDITION FROM DDASTP,AND\nC     APPROPRIATE ACTION WAS NOT TAKEN. THIS\nC     IS A FATAL ERROR.\n      WRITE (XERN1, '(I8)') IDID\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'THE LAST STEP TERMINATED WITH A NEGATIVE VALUE OF IDID = ' //\n     *   XERN1 // ' AND NO APPROPRIATE ACTION WAS TAKEN.  ' //\n     *   'RUN TERMINATED', -998, 2)\n      RETURN\n110   CONTINUE\n      IWORK(LNSTL)=IWORK(LNST)\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK IS EXECUTED ON ALL CALLS.\nC     THE ERROR TOLERANCE PARAMETERS ARE\nC     CHECKED, AND THE WORK ARRAY POINTERS\nC     ARE SET.\nC-----------------------------------------------------------------------\nC\n200   CONTINUE\nC     CHECK RTOL,ATOL\n      NZFLG=0\n      RTOLI=RTOL(1)\n      ATOLI=ATOL(1)\n      DO 210 I=1,NEQ\n         IF(INFO(2).EQ.1)RTOLI=RTOL(I)\n         IF(INFO(2).EQ.1)ATOLI=ATOL(I)\n         IF(RTOLI.GT.0.0D0.OR.ATOLI.GT.0.0D0)NZFLG=1\n         IF(RTOLI.LT.0.0D0)GO TO 706\n         IF(ATOLI.LT.0.0D0)GO TO 707\n210      CONTINUE\n      IF(NZFLG.EQ.0)GO TO 708\nC\nC     SET UP RWORK STORAGE.IWORK STORAGE IS FIXED\nC     IN DATA STATEMENT.\n      LE=LDELTA+NEQ\n      LWT=LE+NEQ\n      LPHI=LWT+NEQ\n      LPD=LPHI+(IWORK(LMXORD)+1)*NEQ\n      LWM=LPD\n      NTEMP=NPD+IWORK(LNPD)\n      IF(INFO(1).EQ.1)GO TO 400\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK IS EXECUTED ON THE INITIAL CALL\nC     ONLY. SET THE INITIAL STEP SIZE, AND\nC     THE ERROR WEIGHT VECTOR, AND PHI.\nC     COMPUTE INITIAL YPRIME, IF NECESSARY.\nC-----------------------------------------------------------------------\nC\n      TN=T\n      IDID=1\nC\nC     SET ERROR WEIGHT VECTOR WT\n      CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,Y,RWORK(LWT),RPAR,IPAR)\n      DO 305 I = 1,NEQ\n         IF(RWORK(LWT+I-1).LE.0.0D0) GO TO 713\n305      CONTINUE\nC\nC     COMPUTE UNIT ROUNDOFF AND HMIN\n      UROUND = D1MACH(4)\n      RWORK(LROUND) = UROUND\n      HMIN = 4.0D0*UROUND*MAX(ABS(T),ABS(TOUT))\nC\nC     CHECK INITIAL INTERVAL TO SEE THAT IT IS LONG ENOUGH\n      TDIST = ABS(TOUT - T)\n      IF(TDIST .LT. HMIN) GO TO 714\nC\nC     CHECK HO, IF THIS WAS INPUT\n      IF (INFO(8) .EQ. 0) GO TO 310\n         HO = RWORK(LH)\n         IF ((TOUT - T)*HO .LT. 0.0D0) GO TO 711\n         IF (HO .EQ. 0.0D0) GO TO 712\n         GO TO 320\n310    CONTINUE\nC\nC     COMPUTE INITIAL STEPSIZE, TO BE USED BY EITHER\nC     DDASTP OR DDAINI, DEPENDING ON INFO(11)\n      HO = 0.001D0*TDIST\n      YPNORM = DDANRM(NEQ,YPRIME,RWORK(LWT),RPAR,IPAR)\n      IF (YPNORM .GT. 0.5D0/HO) HO = 0.5D0/YPNORM\n      HO = SIGN(HO,TOUT-T)\nC     ADJUST HO IF NECESSARY TO MEET HMAX BOUND\n320   IF (INFO(7) .EQ. 0) GO TO 330\n         RH = ABS(HO)/RWORK(LHMAX)\n         IF (RH .GT. 1.0D0) HO = HO/RH\nC     COMPUTE TSTOP, IF APPLICABLE\n330   IF (INFO(4) .EQ. 0) GO TO 340\n         TSTOP = RWORK(LTSTOP)\n         IF ((TSTOP - T)*HO .LT. 0.0D0) GO TO 715\n         IF ((T + HO - TSTOP)*HO .GT. 0.0D0) HO = TSTOP - T\n         IF ((TSTOP - TOUT)*HO .LT. 0.0D0) GO TO 709\nC\nC     COMPUTE INITIAL DERIVATIVE, UPDATING TN AND Y, IF APPLICABLE\n340   IF (INFO(11) .EQ. 0) GO TO 350\n      CALL DDAINI(TN,Y,YPRIME,NEQ,\n     *  RES,JAC,HO,RWORK(LWT),IDID,RPAR,IPAR,\n     *  RWORK(LPHI),RWORK(LDELTA),RWORK(LE),\n     *  RWORK(LWM),IWORK(LIWM),HMIN,RWORK(LROUND),\n     *  INFO(10),NTEMP)\n      IF (IDID .LT. 0) GO TO 390\nC\nC     LOAD H WITH HO.  STORE H IN RWORK(LH)\n350   H = HO\n      RWORK(LH) = H\nC\nC     LOAD Y AND H*YPRIME INTO PHI(*,1) AND PHI(*,2)\n      ITEMP = LPHI + NEQ\n      DO 370 I = 1,NEQ\n         RWORK(LPHI + I - 1) = Y(I)\n370      RWORK(ITEMP + I - 1) = H*YPRIME(I)\nC\n390   GO TO 500\nC\nC-------------------------------------------------------\nC     THIS BLOCK IS FOR CONTINUATION CALLS ONLY. ITS\nC     PURPOSE IS TO CHECK STOP CONDITIONS BEFORE\nC     TAKING A STEP.\nC     ADJUST H IF NECESSARY TO MEET HMAX BOUND\nC-------------------------------------------------------\nC\n400   CONTINUE\n      UROUND=RWORK(LROUND)\n      DONE = .FALSE.\n      TN=RWORK(LTN)\n      H=RWORK(LH)\n      IF(INFO(7) .EQ. 0) GO TO 410\n         RH = ABS(H)/RWORK(LHMAX)\n         IF(RH .GT. 1.0D0) H = H/RH\n410   CONTINUE\n      IF(T .EQ. TOUT) GO TO 719\n      IF((T - TOUT)*H .GT. 0.0D0) GO TO 711\n      IF(INFO(4) .EQ. 1) GO TO 430\n      IF(INFO(3) .EQ. 1) GO TO 420\n      IF((TN-TOUT)*H.LT.0.0D0)GO TO 490\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T=TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n420   IF((TN-T)*H .LE. 0.0D0) GO TO 490\n      IF((TN - TOUT)*H .GT. 0.0D0) GO TO 425\n      CALL DDATRP(TN,TN,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TN\n      IDID = 1\n      DONE = .TRUE.\n      GO TO 490\n425   CONTINUE\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n430   IF(INFO(3) .EQ. 1) GO TO 440\n      TSTOP=RWORK(LTSTOP)\n      IF((TN-TSTOP)*H.GT.0.0D0) GO TO 715\n      IF((TSTOP-TOUT)*H.LT.0.0D0)GO TO 709\n      IF((TN-TOUT)*H.LT.0.0D0)GO TO 450\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *   RWORK(LPHI),RWORK(LPSI))\n      T=TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n440   TSTOP = RWORK(LTSTOP)\n      IF((TN-TSTOP)*H .GT. 0.0D0) GO TO 715\n      IF((TSTOP-TOUT)*H .LT. 0.0D0) GO TO 709\n      IF((TN-T)*H .LE. 0.0D0) GO TO 450\n      IF((TN - TOUT)*H .GT. 0.0D0) GO TO 445\n      CALL DDATRP(TN,TN,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TN\n      IDID = 1\n      DONE = .TRUE.\n      GO TO 490\n445   CONTINUE\n      CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      T = TOUT\n      IDID = 3\n      DONE = .TRUE.\n      GO TO 490\n450   CONTINUE\nC     CHECK WHETHER WE ARE WITHIN ROUNDOFF OF TSTOP\n      IF(ABS(TN-TSTOP).GT.100.0D0*UROUND*\n     *   (ABS(TN)+ABS(H)))GO TO 460\n      CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,IWORK(LKOLD),\n     *  RWORK(LPHI),RWORK(LPSI))\n      IDID=2\n      T=TSTOP\n      DONE = .TRUE.\n      GO TO 490\n460   TNEXT=TN+H\n      IF((TNEXT-TSTOP)*H.LE.0.0D0)GO TO 490\n      H=TSTOP-TN\n      RWORK(LH)=H\nC\n490   IF (DONE) GO TO 580\nC\nC-------------------------------------------------------\nC     THE NEXT BLOCK CONTAINS THE CALL TO THE\nC     ONE-STEP INTEGRATOR DDASTP.\nC     THIS IS A LOOPING POINT FOR THE INTEGRATION STEPS.\nC     CHECK FOR TOO MANY STEPS.\nC     UPDATE WT.\nC     CHECK FOR TOO MUCH ACCURACY REQUESTED.\nC     COMPUTE MINIMUM STEPSIZE.\nC-------------------------------------------------------\nC\n500   CONTINUE\nC     CHECK FOR FAILURE TO COMPUTE INITIAL YPRIME\n      IF (IDID .EQ. -12) GO TO 527\nC\nC     CHECK FOR TOO MANY STEPS\n      IF((IWORK(LNST)-IWORK(LNSTL)).LT.IWORK(LMXSTP))\n     *   GO TO 510\n           IDID=-1\n           GO TO 527\nC\nC     UPDATE WT\n510   CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,RWORK(LPHI),\n     *  RWORK(LWT),RPAR,IPAR)\n      DO 520 I=1,NEQ\n         IF(RWORK(I+LWT-1).GT.0.0D0)GO TO 520\n           IDID=-3\n           GO TO 527\n520   CONTINUE\nC\nC     TEST FOR TOO MUCH ACCURACY REQUESTED.\n      R=DDANRM(NEQ,RWORK(LPHI),RWORK(LWT),RPAR,IPAR)*\n     *   100.0D0*UROUND\n      IF(R.LE.1.0D0)GO TO 525\nC     MULTIPLY RTOL AND ATOL BY R AND RETURN\n      IF(INFO(2).EQ.1)GO TO 523\n           RTOL(1)=R*RTOL(1)\n           ATOL(1)=R*ATOL(1)\n           IDID=-2\n           GO TO 527\n523   DO 524 I=1,NEQ\n           RTOL(I)=R*RTOL(I)\n524        ATOL(I)=R*ATOL(I)\n      IDID=-2\n      GO TO 527\n525   CONTINUE\nC\nC     COMPUTE MINIMUM STEPSIZE\n      HMIN=4.0D0*UROUND*MAX(ABS(TN),ABS(TOUT))\nC\nC     TEST H VS. HMAX\n      IF (INFO(7) .EQ. 0) GO TO 526\n         RH = ABS(H)/RWORK(LHMAX)\n         IF (RH .GT. 1.0D0) H = H/RH\n526   CONTINUE\nC\n      CALL DDASTP(TN,Y,YPRIME,NEQ,\n     *   RES,JAC,H,RWORK(LWT),INFO(1),IDID,RPAR,IPAR,\n     *   RWORK(LPHI),RWORK(LDELTA),RWORK(LE),\n     *   RWORK(LWM),IWORK(LIWM),\n     *   RWORK(LALPHA),RWORK(LBETA),RWORK(LGAMMA),\n     *   RWORK(LPSI),RWORK(LSIGMA),\n     *   RWORK(LCJ),RWORK(LCJOLD),RWORK(LHOLD),\n     *   RWORK(LS),HMIN,RWORK(LROUND),\n     *   IWORK(LPHASE),IWORK(LJCALC),IWORK(LK),\n     *   IWORK(LKOLD),IWORK(LNS),INFO(10),NTEMP)\n527   IF(IDID.LT.0)GO TO 600\nC\nC--------------------------------------------------------\nC     THIS BLOCK HANDLES THE CASE OF A SUCCESSFUL RETURN\nC     FROM DDASTP (IDID=1).  TEST FOR STOP CONDITIONS.\nC--------------------------------------------------------\nC\n      IF(INFO(4).NE.0)GO TO 540\n           IF(INFO(3).NE.0)GO TO 530\n             IF((TN-TOUT)*H.LT.0.0D0)GO TO 500\n             CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *         IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n             IDID=3\n             T=TOUT\n             GO TO 580\n530          IF((TN-TOUT)*H.GE.0.0D0)GO TO 535\n             T=TN\n             IDID=1\n             GO TO 580\n535          CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *         IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n             IDID=3\n             T=TOUT\n             GO TO 580\n540   IF(INFO(3).NE.0)GO TO 550\n      IF((TN-TOUT)*H.LT.0.0D0)GO TO 542\n         CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *     IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n         T=TOUT\n         IDID=3\n         GO TO 580\n542   IF(ABS(TN-TSTOP).LE.100.0D0*UROUND*\n     *   (ABS(TN)+ABS(H)))GO TO 545\n      TNEXT=TN+H\n      IF((TNEXT-TSTOP)*H.LE.0.0D0)GO TO 500\n      H=TSTOP-TN\n      GO TO 500\n545   CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,\n     *  IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n      IDID=2\n      T=TSTOP\n      GO TO 580\n550   IF((TN-TOUT)*H.GE.0.0D0)GO TO 555\n      IF(ABS(TN-TSTOP).LE.100.0D0*UROUND*(ABS(TN)+ABS(H)))GO TO 552\n      T=TN\n      IDID=1\n      GO TO 580\n552   CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,\n     *  IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n      IDID=2\n      T=TSTOP\n      GO TO 580\n555   CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,\n     *   IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))\n      T=TOUT\n      IDID=3\n      GO TO 580\nC\nC--------------------------------------------------------\nC     ALL SUCCESSFUL RETURNS FROM DDASSL ARE MADE FROM\nC     THIS BLOCK.\nC--------------------------------------------------------\nC\n580   CONTINUE\n      RWORK(LTN)=TN\n      RWORK(LH)=H\n      RETURN\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK HANDLES ALL UNSUCCESSFUL\nC     RETURNS OTHER THAN FOR ILLEGAL INPUT.\nC-----------------------------------------------------------------------\nC\n600   CONTINUE\n      ITEMP=-IDID\n      GO TO (610,620,630,690,690,640,650,660,670,675,\n     *  680,685), ITEMP\nC\nC     THE MAXIMUM NUMBER OF STEPS WAS TAKEN BEFORE\nC     REACHING TOUT\n610   WRITE (XERN3, '(1P,D15.6)') TN\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT CURRENT T = ' // XERN3 // ' 500 STEPS TAKEN ON THIS ' //\n     *   'CALL BEFORE REACHING TOUT', IDID, 1)\n      GO TO 690\nC\nC     TOO MUCH ACCURACY FOR MACHINE PRECISION\n620   WRITE (XERN3, '(1P,D15.6)') TN\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT T = ' // XERN3 // ' TOO MUCH ACCURACY REQUESTED FOR ' //\n     *   'PRECISION OF MACHINE. RTOL AND ATOL WERE INCREASED TO ' //\n     *   'APPROPRIATE VALUES', IDID, 1)\n      GO TO 690\nC\nC     WT(I) .LE. 0.0 FOR SOME I (NOT AT START OF PROBLEM)\n630   WRITE (XERN3, '(1P,D15.6)') TN\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT T = ' // XERN3 // ' SOME ELEMENT OF WT HAS BECOME .LE. ' //\n     *   '0.0', IDID, 1)\n      GO TO 690\nC\nC     ERROR TEST FAILED REPEATEDLY OR WITH H=HMIN\n640   WRITE (XERN3, '(1P,D15.6)') TN\n      WRITE (XERN4, '(1P,D15.6)') H\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT T = ' // XERN3 // ' AND STEPSIZE H = ' // XERN4 //\n     *   ' THE ERROR TEST FAILED REPEATEDLY OR WITH ABS(H)=HMIN',\n     *   IDID, 1)\n      GO TO 690\nC\nC     CORRECTOR CONVERGENCE FAILED REPEATEDLY OR WITH H=HMIN\n650   WRITE (XERN3, '(1P,D15.6)') TN\n      WRITE (XERN4, '(1P,D15.6)') H\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT T = ' // XERN3 // ' AND STEPSIZE H = ' // XERN4 //\n     *   ' THE CORRECTOR FAILED TO CONVERGE REPEATEDLY OR WITH ' //\n     *   'ABS(H)=HMIN', IDID, 1)\n      GO TO 690\nC\nC     THE ITERATION MATRIX IS SINGULAR\n660   WRITE (XERN3, '(1P,D15.6)') TN\n      WRITE (XERN4, '(1P,D15.6)') H\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT T = ' // XERN3 // ' AND STEPSIZE H = ' // XERN4 //\n     *   ' THE ITERATION MATRIX IS SINGULAR', IDID, 1)\n      GO TO 690\nC\nC     CORRECTOR FAILURE PRECEEDED BY ERROR TEST FAILURES.\n670   WRITE (XERN3, '(1P,D15.6)') TN\n      WRITE (XERN4, '(1P,D15.6)') H\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT T = ' // XERN3 // ' AND STEPSIZE H = ' // XERN4 //\n     *   ' THE CORRECTOR COULD NOT CONVERGE.  ALSO, THE ERROR TEST ' //\n     *   'FAILED REPEATEDLY.', IDID, 1)\n      GO TO 690\nC\nC     CORRECTOR FAILURE BECAUSE IRES = -1\n675   WRITE (XERN3, '(1P,D15.6)') TN\n      WRITE (XERN4, '(1P,D15.6)') H\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT T = ' // XERN3 // ' AND STEPSIZE H = ' // XERN4 //\n     *   ' THE CORRECTOR COULD NOT CONVERGE BECAUSE IRES WAS EQUAL ' //\n     *   'TO MINUS ONE', IDID, 1)\n      GO TO 690\nC\nC     FAILURE BECAUSE IRES = -2\n680   WRITE (XERN3, '(1P,D15.6)') TN\n      WRITE (XERN4, '(1P,D15.6)') H\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT T = ' // XERN3 // ' AND STEPSIZE H = ' // XERN4 //\n     *   ' IRES WAS EQUAL TO MINUS TWO', IDID, 1)\n      GO TO 690\nC\nC     FAILED TO COMPUTE INITIAL YPRIME\n685   WRITE (XERN3, '(1P,D15.6)') TN\n      WRITE (XERN4, '(1P,D15.6)') HO\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'AT T = ' // XERN3 // ' AND STEPSIZE H = ' // XERN4 //\n     *   ' THE INITIAL YPRIME COULD NOT BE COMPUTED', IDID, 1)\n      GO TO 690\nC\n690   CONTINUE\n      INFO(1)=-1\n      T=TN\n      RWORK(LTN)=TN\n      RWORK(LH)=H\n      RETURN\nC\nC-----------------------------------------------------------------------\nC     THIS BLOCK HANDLES ALL ERROR RETURNS DUE\nC     TO ILLEGAL INPUT, AS DETECTED BEFORE CALLING\nC     DDASTP. FIRST THE ERROR MESSAGE ROUTINE IS\nC     CALLED. IF THIS HAPPENS TWICE IN\nC     SUCCESSION, EXECUTION IS TERMINATED\nC\nC-----------------------------------------------------------------------\n701   CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'SOME ELEMENT OF INFO VECTOR IS NOT ZERO OR ONE', 1, 1)\n      GO TO 750\nC\n702   WRITE (XERN1, '(I8)') NEQ\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'NEQ = ' // XERN1 // ' .LE. 0', 2, 1)\n      GO TO 750\nC\n703   WRITE (XERN1, '(I8)') MXORD\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'MAXORD = ' // XERN1 // ' NOT IN RANGE', 3, 1)\n      GO TO 750\nC\n704   WRITE (XERN1, '(I8)') LENRW\n      WRITE (XERN2, '(I8)') LRW\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'RWORK LENGTH NEEDED, LENRW = ' // XERN1 //\n     *   ', EXCEEDS LRW = ' // XERN2, 4, 1)\n      GO TO 750\nC\n705   WRITE (XERN1, '(I8)') LENIW\n      WRITE (XERN2, '(I8)') LIW\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'IWORK LENGTH NEEDED, LENIW = ' // XERN1 //\n     *   ', EXCEEDS LIW = ' // XERN2, 5, 1)\n      GO TO 750\nC\n706   CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'SOME ELEMENT OF RTOL IS .LT. 0', 6, 1)\n      GO TO 750\nC\n707   CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'SOME ELEMENT OF ATOL IS .LT. 0', 7, 1)\n      GO TO 750\nC\n708   CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'ALL ELEMENTS OF RTOL AND ATOL ARE ZERO', 8, 1)\n      GO TO 750\nC\n709   WRITE (XERN3, '(1P,D15.6)') TSTOP\n      WRITE (XERN4, '(1P,D15.6)') TOUT\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'INFO(4) = 1 AND TSTOP = ' // XERN3 // ' BEHIND TOUT = ' //\n     *   XERN4, 9, 1)\n      GO TO 750\nC\n710   WRITE (XERN3, '(1P,D15.6)') HMAX\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'HMAX = ' // XERN3 // ' .LT. 0.0', 10, 1)\n      GO TO 750\nC\n711   WRITE (XERN3, '(1P,D15.6)') TOUT\n      WRITE (XERN4, '(1P,D15.6)') T\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'TOUT = ' // XERN3 // ' BEHIND T = ' // XERN4, 11, 1)\n      GO TO 750\nC\n712   CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'INFO(8)=1 AND H0=0.0', 12, 1)\n      GO TO 750\nC\n713   CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'SOME ELEMENT OF WT IS .LE. 0.0', 13, 1)\n      GO TO 750\nC\n714   WRITE (XERN3, '(1P,D15.6)') TOUT\n      WRITE (XERN4, '(1P,D15.6)') T\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'TOUT = ' // XERN3 // ' TOO CLOSE TO T = ' // XERN4 //\n     *   ' TO START INTEGRATION', 14, 1)\n      GO TO 750\nC\n715   WRITE (XERN3, '(1P,D15.6)') TSTOP\n      WRITE (XERN4, '(1P,D15.6)') T\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'INFO(4)=1 AND TSTOP = ' // XERN3 // ' BEHIND T = ' // XERN4,\n     *   15, 1)\n      GO TO 750\nC\n716   WRITE (XERN1, '(I8)') MXSTP\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'INFO(12)=1 AND MXSTP = ' // XERN1 // ' ILLEGAL.', 3, 1)\n      GO TO 750\nC\n717   WRITE (XERN1, '(I8)') IWORK(LML)\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'ML = ' // XERN1 // ' ILLEGAL.  EITHER .LT. 0 OR .GT. NEQ',\n     *   17, 1)\n      GO TO 750\nC\n718   WRITE (XERN1, '(I8)') IWORK(LMU)\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *   'MU = ' // XERN1 // ' ILLEGAL.  EITHER .LT. 0 OR .GT. NEQ',\n     *   18, 1)\n      GO TO 750\nC\n719   WRITE (XERN3, '(1P,D15.6)') TOUT\n      CALL XERMSG ('SLATEC', 'DDASSL',\n     *  'TOUT = T = ' // XERN3, 19, 1)\n      GO TO 750\nC\n750   IDID=-33\n      IF(INFO(1).EQ.-1) THEN\n         CALL XERMSG ('SLATEC', 'DDASSL',\n     *      'REPEATED OCCURRENCES OF ILLEGAL INPUT$$' //\n     *      'RUN TERMINATED. APPARENT INFINITE LOOP', -999, 2)\n      ENDIF\nC\n      INFO(1)=-1\n      RETURN\nC-----------END OF SUBROUTINE DDASSL------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/dassl/ddastp.f",
    "content": "      SUBROUTINE DDASTP (X, Y, YPRIME, NEQ, RES, JAC, H, WT, JSTART,\n     +   IDID, RPAR, IPAR, PHI, DELTA, E, WM, IWM, ALPHA, BETA, GAMMA,\n     +   PSI, SIGMA, CJ, CJOLD, HOLD, S, HMIN, UROUND, IPHASE, JCALC,\n     +   K, KOLD, NS, NONNEG, NTEMP)\nC***BEGIN PROLOGUE  DDASTP\nC***SUBSIDIARY\nC***PURPOSE  Perform one step of the DDASSL integration.\nC***LIBRARY   SLATEC (DASSL)\nC***TYPE      DOUBLE PRECISION (SDASTP-S, DDASTP-D)\nC***AUTHOR  PETZOLD, LINDA R., (LLNL)\nC***DESCRIPTION\nC-----------------------------------------------------------------------\nC     DDASTP SOLVES A SYSTEM OF DIFFERENTIAL/\nC     ALGEBRAIC EQUATIONS OF THE FORM\nC     G(X,Y,YPRIME) = 0,  FOR ONE STEP (NORMALLY\nC     FROM X TO X+H).\nC\nC     THE METHODS USED ARE MODIFIED DIVIDED\nC     DIFFERENCE,FIXED LEADING COEFFICIENT\nC     FORMS OF BACKWARD DIFFERENTIATION\nC     FORMULAS. THE CODE ADJUSTS THE STEPSIZE\nC     AND ORDER TO CONTROL THE LOCAL ERROR PER\nC     STEP.\nC\nC\nC     THE PARAMETERS REPRESENT\nC     X  --        INDEPENDENT VARIABLE\nC     Y  --        SOLUTION VECTOR AT X\nC     YPRIME --    DERIVATIVE OF SOLUTION VECTOR\nC                  AFTER SUCCESSFUL STEP\nC     NEQ --       NUMBER OF EQUATIONS TO BE INTEGRATED\nC     RES --       EXTERNAL USER-SUPPLIED SUBROUTINE\nC                  TO EVALUATE THE RESIDUAL.  THE CALL IS\nC                  CALL RES(X,Y,YPRIME,DELTA,IRES,RPAR,IPAR)\nC                  X,Y,YPRIME ARE INPUT.  DELTA IS OUTPUT.\nC                  ON INPUT, IRES=0.  RES SHOULD ALTER IRES ONLY\nC                  IF IT ENCOUNTERS AN ILLEGAL VALUE OF Y OR A\nC                  STOP CONDITION.  SET IRES=-1 IF AN INPUT VALUE\nC                  OF Y IS ILLEGAL, AND DDASTP WILL TRY TO SOLVE\nC                  THE PROBLEM WITHOUT GETTING IRES = -1.  IF\nC                  IRES=-2, DDASTP RETURNS CONTROL TO THE CALLING\nC                  PROGRAM WITH IDID = -11.\nC     JAC --       EXTERNAL USER-SUPPLIED ROUTINE TO EVALUATE\nC                  THE ITERATION MATRIX (THIS IS OPTIONAL)\nC                  THE CALL IS OF THE FORM\nC                  CALL JAC(X,Y,YPRIME,PD,CJ,RPAR,IPAR)\nC                  PD IS THE MATRIX OF PARTIAL DERIVATIVES,\nC                  PD=DG/DY+CJ*DG/DYPRIME\nC     H --         APPROPRIATE STEP SIZE FOR NEXT STEP.\nC                  NORMALLY DETERMINED BY THE CODE\nC     WT --        VECTOR OF WEIGHTS FOR ERROR CRITERION.\nC     JSTART --    INTEGER VARIABLE SET 0 FOR\nC                  FIRST STEP, 1 OTHERWISE.\nC     IDID --      COMPLETION CODE WITH THE FOLLOWING MEANINGS:\nC                  IDID= 1 -- THE STEP WAS COMPLETED SUCCESSFULLY\nC                  IDID=-6 -- THE ERROR TEST FAILED REPEATEDLY\nC                  IDID=-7 -- THE CORRECTOR COULD NOT CONVERGE\nC                  IDID=-8 -- THE ITERATION MATRIX IS SINGULAR\nC                  IDID=-9 -- THE CORRECTOR COULD NOT CONVERGE.\nC                             THERE WERE REPEATED ERROR TEST\nC                             FAILURES ON THIS STEP.\nC                  IDID=-10-- THE CORRECTOR COULD NOT CONVERGE\nC                             BECAUSE IRES WAS EQUAL TO MINUS ONE\nC                  IDID=-11-- IRES EQUAL TO -2 WAS ENCOUNTERED,\nC                             AND CONTROL IS BEING RETURNED TO\nC                             THE CALLING PROGRAM\nC     RPAR,IPAR -- REAL AND INTEGER PARAMETER ARRAYS THAT\nC                  ARE USED FOR COMMUNICATION BETWEEN THE\nC                  CALLING PROGRAM AND EXTERNAL USER ROUTINES\nC                  THEY ARE NOT ALTERED BY DDASTP\nC     PHI --       ARRAY OF DIVIDED DIFFERENCES USED BY\nC                  DDASTP. THE LENGTH IS NEQ*(K+1),WHERE\nC                  K IS THE MAXIMUM ORDER\nC     DELTA,E --   WORK VECTORS FOR DDASTP OF LENGTH NEQ\nC     WM,IWM --    REAL AND INTEGER ARRAYS STORING\nC                  MATRIX INFORMATION SUCH AS THE MATRIX\nC                  OF PARTIAL DERIVATIVES,PERMUTATION\nC                  VECTOR,AND VARIOUS OTHER INFORMATION.\nC\nC     THE OTHER PARAMETERS ARE INFORMATION\nC     WHICH IS NEEDED INTERNALLY BY DDASTP TO\nC     CONTINUE FROM STEP TO STEP.\nC\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED  DDAJAC, DDANRM, DDASLV, DDATRP\nC***REVISION HISTORY  (YYMMDD)\nC   830315  DATE WRITTEN\nC   901009  Finished conversion to SLATEC 4.0 format (F.N.Fritsch)\nC   901019  Merged changes made by C. Ulrich with SLATEC 4.0 format.\nC   901026  Added explicit declarations for all variables and minor\nC           cosmetic changes to prologue.  (FNF)\nC***END PROLOGUE  DDASTP\nC\n      INTEGER  NEQ, JSTART, IDID, IPAR(*), IWM(*), IPHASE, JCALC, K,\n     *   KOLD, NS, NONNEG, NTEMP\n      DOUBLE PRECISION\n     *   X, Y(*), YPRIME(*), H, WT(*), RPAR(*), PHI(NEQ,*), DELTA(*),\n     *   E(*), WM(*), ALPHA(*), BETA(*), GAMMA(*), PSI(*), SIGMA(*), CJ,\n     *   CJOLD, HOLD, S, HMIN, UROUND\n      EXTERNAL  RES, JAC\nC\n      EXTERNAL  DDAJAC, DDANRM, DDASLV, DDATRP\n      DOUBLE PRECISION  DDANRM\nC\n      INTEGER  I, IER, IRES, J, J1, KDIFF, KM1, KNEW, KP1, KP2, LCTF,\n     *   LETF, LMXORD, LNJE, LNRE, LNST, M, MAXIT, NCF, NEF, NSF, NSP1\n      DOUBLE PRECISION\n     *   ALPHA0, ALPHAS, CJLAST, CK, DELNRM, ENORM, ERK, ERKM1,\n     *   ERKM2, ERKP1, ERR, EST, HNEW, OLDNRM, PNORM, R, RATE, TEMP1,\n     *   TEMP2, TERK, TERKM1, TERKM2, TERKP1, XOLD, XRATE\n      LOGICAL  CONVGD\nC\n      PARAMETER (LMXORD=3)\n      PARAMETER (LNST=11)\n      PARAMETER (LNRE=12)\n      PARAMETER (LNJE=13)\n      PARAMETER (LETF=14)\n      PARAMETER (LCTF=15)\nC\n      DATA MAXIT/4/\n      DATA XRATE/0.25D0/\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 1.\nC     INITIALIZE. ON THE FIRST CALL,SET\nC     THE ORDER TO 1 AND INITIALIZE\nC     OTHER VARIABLES.\nC-----------------------------------------------------------------------\nC\nC     INITIALIZATIONS FOR ALL CALLS\nC***FIRST EXECUTABLE STATEMENT  DDASTP\n      IDID=1\n      XOLD=X\n      NCF=0\n      NSF=0\n      NEF=0\n      IF(JSTART .NE. 0) GO TO 120\nC\nC     IF THIS IS THE FIRST STEP,PERFORM\nC     OTHER INITIALIZATIONS\n      IWM(LETF) = 0\n      IWM(LCTF) = 0\n      K=1\n      KOLD=0\n      HOLD=0.0D0\n      JSTART=1\n      PSI(1)=H\n      CJOLD = 1.0D0/H\n      CJ = CJOLD\n      S = 100.D0\n      JCALC = -1\n      DELNRM=1.0D0\n      IPHASE = 0\n      NS=0\n120   CONTINUE\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 2\nC     COMPUTE COEFFICIENTS OF FORMULAS FOR\nC     THIS STEP.\nC-----------------------------------------------------------------------\n200   CONTINUE\n      KP1=K+1\n      KP2=K+2\n      KM1=K-1\n      XOLD=X\n      IF(H.NE.HOLD.OR.K .NE. KOLD) NS = 0\n      NS=MIN(NS+1,KOLD+2)\n      NSP1=NS+1\n      IF(KP1 .LT. NS)GO TO 230\nC\n      BETA(1)=1.0D0\n      ALPHA(1)=1.0D0\n      TEMP1=H\n      GAMMA(1)=0.0D0\n      SIGMA(1)=1.0D0\n      DO 210 I=2,KP1\n         TEMP2=PSI(I-1)\n         PSI(I-1)=TEMP1\n         BETA(I)=BETA(I-1)*PSI(I-1)/TEMP2\n         TEMP1=TEMP2+H\n         ALPHA(I)=H/TEMP1\n         SIGMA(I)=(I-1)*SIGMA(I-1)*ALPHA(I)\n         GAMMA(I)=GAMMA(I-1)+ALPHA(I-1)/H\n210      CONTINUE\n      PSI(KP1)=TEMP1\n230   CONTINUE\nC\nC     COMPUTE ALPHAS, ALPHA0\n      ALPHAS = 0.0D0\n      ALPHA0 = 0.0D0\n      DO 240 I = 1,K\n        ALPHAS = ALPHAS - 1.0D0/I\n        ALPHA0 = ALPHA0 - ALPHA(I)\n240     CONTINUE\nC\nC     COMPUTE LEADING COEFFICIENT CJ\n      CJLAST = CJ\n      CJ = -ALPHAS/H\nC\nC     COMPUTE VARIABLE STEPSIZE ERROR COEFFICIENT CK\n      CK = ABS(ALPHA(KP1) + ALPHAS - ALPHA0)\n      CK = MAX(CK,ALPHA(KP1))\nC\nC     DECIDE WHETHER NEW JACOBIAN IS NEEDED\n      TEMP1 = (1.0D0 - XRATE)/(1.0D0 + XRATE)\n      TEMP2 = 1.0D0/TEMP1\n      IF (CJ/CJOLD .LT. TEMP1 .OR. CJ/CJOLD .GT. TEMP2) JCALC = -1\n      IF (CJ .NE. CJLAST) S = 100.D0\nC\nC     CHANGE PHI TO PHI STAR\n      IF(KP1 .LT. NSP1) GO TO 280\n      DO 270 J=NSP1,KP1\n         DO 260 I=1,NEQ\n260         PHI(I,J)=BETA(J)*PHI(I,J)\n270      CONTINUE\n280   CONTINUE\nC\nC     UPDATE TIME\n      X=X+H\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 3\nC     PREDICT THE SOLUTION AND DERIVATIVE,\nC     AND SOLVE THE CORRECTOR EQUATION\nC-----------------------------------------------------------------------\nC\nC     FIRST,PREDICT THE SOLUTION AND DERIVATIVE\n300   CONTINUE\n      DO 310 I=1,NEQ\n         Y(I)=PHI(I,1)\n310      YPRIME(I)=0.0D0\n      DO 330 J=2,KP1\n         DO 320 I=1,NEQ\n            Y(I)=Y(I)+PHI(I,J)\n320         YPRIME(I)=YPRIME(I)+GAMMA(J)*PHI(I,J)\n330   CONTINUE\n      PNORM = DDANRM (NEQ,Y,WT,RPAR,IPAR)\nC\nC\nC\nC     SOLVE THE CORRECTOR EQUATION USING A\nC     MODIFIED NEWTON SCHEME.\n      CONVGD= .TRUE.\n      M=0\n      IWM(LNRE)=IWM(LNRE)+1\n      IRES = 0\n      CALL RES(X,Y,YPRIME,DELTA,IRES,RPAR,IPAR)\n      IF (IRES .LT. 0) GO TO 380\nC\nC\nC     IF INDICATED,REEVALUATE THE\nC     ITERATION MATRIX PD = DG/DY + CJ*DG/DYPRIME\nC     (WHERE G(X,Y,YPRIME)=0). SET\nC     JCALC TO 0 AS AN INDICATOR THAT\nC     THIS HAS BEEN DONE.\n      IF(JCALC .NE. -1)GO TO 340\n      IWM(LNJE)=IWM(LNJE)+1\n      JCALC=0\n      CALL DDAJAC(NEQ,X,Y,YPRIME,DELTA,CJ,H,\n     * IER,WT,E,WM,IWM,RES,IRES,UROUND,JAC,RPAR,\n     * IPAR,NTEMP)\n      CJOLD=CJ\n      S = 100.D0\n      IF (IRES .LT. 0) GO TO 380\n      IF(IER .NE. 0)GO TO 380\n      NSF=0\nC\nC\nC     INITIALIZE THE ERROR ACCUMULATION VECTOR E.\n340   CONTINUE\n      DO 345 I=1,NEQ\n345      E(I)=0.0D0\nC\nC\nC     CORRECTOR LOOP.\n350   CONTINUE\nC\nC     MULTIPLY RESIDUAL BY TEMP1 TO ACCELERATE CONVERGENCE\n      TEMP1 = 2.0D0/(1.0D0 + CJ/CJOLD)\n      DO 355 I = 1,NEQ\n355     DELTA(I) = DELTA(I) * TEMP1\nC\nC     COMPUTE A NEW ITERATE (BACK-SUBSTITUTION).\nC     STORE THE CORRECTION IN DELTA.\n      CALL DDASLV(NEQ,DELTA,WM,IWM)\nC\nC     UPDATE Y,E,AND YPRIME\n      DO 360 I=1,NEQ\n         Y(I)=Y(I)-DELTA(I)\n         E(I)=E(I)-DELTA(I)\n360      YPRIME(I)=YPRIME(I)-CJ*DELTA(I)\nC\nC     TEST FOR CONVERGENCE OF THE ITERATION\n      DELNRM=DDANRM(NEQ,DELTA,WT,RPAR,IPAR)\n      IF (DELNRM .LE. 100.D0*UROUND*PNORM) GO TO 375\n      IF (M .GT. 0) GO TO 365\n         OLDNRM = DELNRM\n         GO TO 367\n365   RATE = (DELNRM/OLDNRM)**(1.0D0/M)\n      IF (RATE .GT. 0.90D0) GO TO 370\n      S = RATE/(1.0D0 - RATE)\n367   IF (S*DELNRM .LE. 0.33D0) GO TO 375\nC\nC     THE CORRECTOR HAS NOT YET CONVERGED.\nC     UPDATE M AND TEST WHETHER THE\nC     MAXIMUM NUMBER OF ITERATIONS HAVE\nC     BEEN TRIED.\n      M=M+1\n      IF(M.GE.MAXIT)GO TO 370\nC\nC     EVALUATE THE RESIDUAL\nC     AND GO BACK TO DO ANOTHER ITERATION\n      IWM(LNRE)=IWM(LNRE)+1\n      IRES = 0\n      CALL RES(X,Y,YPRIME,DELTA,IRES,\n     *  RPAR,IPAR)\n      IF (IRES .LT. 0) GO TO 380\n      GO TO 350\nC\nC\nC     THE CORRECTOR FAILED TO CONVERGE IN MAXIT\nC     ITERATIONS. IF THE ITERATION MATRIX\nC     IS NOT CURRENT,RE-DO THE STEP WITH\nC     A NEW ITERATION MATRIX.\n370   CONTINUE\n      IF(JCALC.EQ.0)GO TO 380\n      JCALC=-1\n      GO TO 300\nC\nC\nC     THE ITERATION HAS CONVERGED.  IF NONNEGATIVITY OF SOLUTION IS\nC     REQUIRED, SET THE SOLUTION NONNEGATIVE, IF THE PERTURBATION\nC     TO DO IT IS SMALL ENOUGH.  IF THE CHANGE IS TOO LARGE, THEN\nC     CONSIDER THE CORRECTOR ITERATION TO HAVE FAILED.\n375   IF(NONNEG .EQ. 0) GO TO 390\n      DO 377 I = 1,NEQ\n377      DELTA(I) = MIN(Y(I),0.0D0)\n      DELNRM = DDANRM(NEQ,DELTA,WT,RPAR,IPAR)\n      IF(DELNRM .GT. 0.33D0) GO TO 380\n      DO 378 I = 1,NEQ\n378      E(I) = E(I) - DELTA(I)\n      GO TO 390\nC\nC\nC     EXITS FROM BLOCK 3\nC     NO CONVERGENCE WITH CURRENT ITERATION\nC     MATRIX,OR SINGULAR ITERATION MATRIX\n380   CONVGD= .FALSE.\n390   JCALC = 1\n      IF(.NOT.CONVGD)GO TO 600\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 4\nC     ESTIMATE THE ERRORS AT ORDERS K,K-1,K-2\nC     AS IF CONSTANT STEPSIZE WAS USED. ESTIMATE\nC     THE LOCAL ERROR AT ORDER K AND TEST\nC     WHETHER THE CURRENT STEP IS SUCCESSFUL.\nC-----------------------------------------------------------------------\nC\nC     ESTIMATE ERRORS AT ORDERS K,K-1,K-2\n      ENORM = DDANRM(NEQ,E,WT,RPAR,IPAR)\n      ERK = SIGMA(K+1)*ENORM\n      TERK = (K+1)*ERK\n      EST = ERK\n      KNEW=K\n      IF(K .EQ. 1)GO TO 430\n      DO 405 I = 1,NEQ\n405     DELTA(I) = PHI(I,KP1) + E(I)\n      ERKM1=SIGMA(K)*DDANRM(NEQ,DELTA,WT,RPAR,IPAR)\n      TERKM1 = K*ERKM1\n      IF(K .GT. 2)GO TO 410\n      IF(TERKM1 .LE. 0.5D0*TERK)GO TO 420\n      GO TO 430\n410   CONTINUE\n      DO 415 I = 1,NEQ\n415     DELTA(I) = PHI(I,K) + DELTA(I)\n      ERKM2=SIGMA(K-1)*DDANRM(NEQ,DELTA,WT,RPAR,IPAR)\n      TERKM2 = (K-1)*ERKM2\n      IF(MAX(TERKM1,TERKM2).GT.TERK)GO TO 430\nC     LOWER THE ORDER\n420   CONTINUE\n      KNEW=K-1\n      EST = ERKM1\nC\nC\nC     CALCULATE THE LOCAL ERROR FOR THE CURRENT STEP\nC     TO SEE IF THE STEP WAS SUCCESSFUL\n430   CONTINUE\n      ERR = CK * ENORM\n      IF(ERR .GT. 1.0D0)GO TO 600\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 5\nC     THE STEP IS SUCCESSFUL. DETERMINE\nC     THE BEST ORDER AND STEPSIZE FOR\nC     THE NEXT STEP. UPDATE THE DIFFERENCES\nC     FOR THE NEXT STEP.\nC-----------------------------------------------------------------------\n      IDID=1\n      IWM(LNST)=IWM(LNST)+1\n      KDIFF=K-KOLD\n      KOLD=K\n      HOLD=H\nC\nC\nC     ESTIMATE THE ERROR AT ORDER K+1 UNLESS:\nC        ALREADY DECIDED TO LOWER ORDER, OR\nC        ALREADY USING MAXIMUM ORDER, OR\nC        STEPSIZE NOT CONSTANT, OR\nC        ORDER RAISED IN PREVIOUS STEP\n      IF(KNEW.EQ.KM1.OR.K.EQ.IWM(LMXORD))IPHASE=1\n      IF(IPHASE .EQ. 0)GO TO 545\n      IF(KNEW.EQ.KM1)GO TO 540\n      IF(K.EQ.IWM(LMXORD)) GO TO 550\n      IF(KP1.GE.NS.OR.KDIFF.EQ.1)GO TO 550\n      DO 510 I=1,NEQ\n510      DELTA(I)=E(I)-PHI(I,KP2)\n      ERKP1 = (1.0D0/(K+2))*DDANRM(NEQ,DELTA,WT,RPAR,IPAR)\n      TERKP1 = (K+2)*ERKP1\n      IF(K.GT.1)GO TO 520\n      IF(TERKP1.GE.0.5D0*TERK)GO TO 550\n      GO TO 530\n520   IF(TERKM1.LE.MIN(TERK,TERKP1))GO TO 540\n      IF(TERKP1.GE.TERK.OR.K.EQ.IWM(LMXORD))GO TO 550\nC\nC     RAISE ORDER\n530   K=KP1\n      EST = ERKP1\n      GO TO 550\nC\nC     LOWER ORDER\n540   K=KM1\n      EST = ERKM1\n      GO TO 550\nC\nC     IF IPHASE = 0, INCREASE ORDER BY ONE AND MULTIPLY STEPSIZE BY\nC     FACTOR TWO\n545   K = KP1\n      HNEW = H*2.0D0\n      H = HNEW\n      GO TO 575\nC\nC\nC     DETERMINE THE APPROPRIATE STEPSIZE FOR\nC     THE NEXT STEP.\n550   HNEW=H\n      TEMP2=K+1\n      R=(2.0D0*EST+0.0001D0)**(-1.0D0/TEMP2)\n      IF(R .LT. 2.0D0) GO TO 555\n      HNEW = 2.0D0*H\n      GO TO 560\n555   IF(R .GT. 1.0D0) GO TO 560\n      R = MAX(0.5D0,MIN(0.9D0,R))\n      HNEW = H*R\n560   H=HNEW\nC\nC\nC     UPDATE DIFFERENCES FOR NEXT STEP\n575   CONTINUE\n      IF(KOLD.EQ.IWM(LMXORD))GO TO 585\n      DO 580 I=1,NEQ\n580      PHI(I,KP2)=E(I)\n585   CONTINUE\n      DO 590 I=1,NEQ\n590      PHI(I,KP1)=PHI(I,KP1)+E(I)\n      DO 595 J1=2,KP1\n         J=KP1-J1+1\n         DO 595 I=1,NEQ\n595      PHI(I,J)=PHI(I,J)+PHI(I,J+1)\n      RETURN\nC\nC\nC\nC\nC\nC-----------------------------------------------------------------------\nC     BLOCK 6\nC     THE STEP IS UNSUCCESSFUL. RESTORE X,PSI,PHI\nC     DETERMINE APPROPRIATE STEPSIZE FOR\nC     CONTINUING THE INTEGRATION, OR EXIT WITH\nC     AN ERROR FLAG IF THERE HAVE BEEN MANY\nC     FAILURES.\nC-----------------------------------------------------------------------\n600   IPHASE = 1\nC\nC     RESTORE X,PHI,PSI\n      X=XOLD\n      IF(KP1.LT.NSP1)GO TO 630\n      DO 620 J=NSP1,KP1\n         TEMP1=1.0D0/BETA(J)\n         DO 610 I=1,NEQ\n610         PHI(I,J)=TEMP1*PHI(I,J)\n620      CONTINUE\n630   CONTINUE\n      DO 640 I=2,KP1\n640      PSI(I-1)=PSI(I)-H\nC\nC\nC     TEST WHETHER FAILURE IS DUE TO CORRECTOR ITERATION\nC     OR ERROR TEST\n      IF(CONVGD)GO TO 660\n      IWM(LCTF)=IWM(LCTF)+1\nC\nC\nC     THE NEWTON ITERATION FAILED TO CONVERGE WITH\nC     A CURRENT ITERATION MATRIX.  DETERMINE THE CAUSE\nC     OF THE FAILURE AND TAKE APPROPRIATE ACTION.\n      IF(IER.EQ.0)GO TO 650\nC\nC     THE ITERATION MATRIX IS SINGULAR. REDUCE\nC     THE STEPSIZE BY A FACTOR OF 4. IF\nC     THIS HAPPENS THREE TIMES IN A ROW ON\nC     THE SAME STEP, RETURN WITH AN ERROR FLAG\n      NSF=NSF+1\n      R = 0.25D0\n      H=H*R\n      IF (NSF .LT. 3 .AND. ABS(H) .GE. HMIN) GO TO 690\n      IDID=-8\n      GO TO 675\nC\nC\nC     THE NEWTON ITERATION FAILED TO CONVERGE FOR A REASON\nC     OTHER THAN A SINGULAR ITERATION MATRIX.  IF IRES = -2, THEN\nC     RETURN.  OTHERWISE, REDUCE THE STEPSIZE AND TRY AGAIN, UNLESS\nC     TOO MANY FAILURES HAVE OCCURRED.\n650   CONTINUE\n      IF (IRES .GT. -2) GO TO 655\n      IDID = -11\n      GO TO 675\n655   NCF = NCF + 1\n      R = 0.25D0\n      H = H*R\n      IF (NCF .LT. 10 .AND. ABS(H) .GE. HMIN) GO TO 690\n      IDID = -7\n      IF (IRES .LT. 0) IDID = -10\n      IF (NEF .GE. 3) IDID = -9\n      GO TO 675\nC\nC\nC     THE NEWTON SCHEME CONVERGED,AND THE CAUSE\nC     OF THE FAILURE WAS THE ERROR ESTIMATE\nC     EXCEEDING THE TOLERANCE.\n660   NEF=NEF+1\n      IWM(LETF)=IWM(LETF)+1\n      IF (NEF .GT. 1) GO TO 665\nC\nC     ON FIRST ERROR TEST FAILURE, KEEP CURRENT ORDER OR LOWER\nC     ORDER BY ONE.  COMPUTE NEW STEPSIZE BASED ON DIFFERENCES\nC     OF THE SOLUTION.\n      K = KNEW\n      TEMP2 = K + 1\n      R = 0.90D0*(2.0D0*EST+0.0001D0)**(-1.0D0/TEMP2)\n      R = MAX(0.25D0,MIN(0.9D0,R))\n      H = H*R\n      IF (ABS(H) .GE. HMIN) GO TO 690\n      IDID = -6\n      GO TO 675\nC\nC     ON SECOND ERROR TEST FAILURE, USE THE CURRENT ORDER OR\nC     DECREASE ORDER BY ONE.  REDUCE THE STEPSIZE BY A FACTOR OF\nC     FOUR.\n665   IF (NEF .GT. 2) GO TO 670\n      K = KNEW\n      H = 0.25D0*H\n      IF (ABS(H) .GE. HMIN) GO TO 690\n      IDID = -6\n      GO TO 675\nC\nC     ON THIRD AND SUBSEQUENT ERROR TEST FAILURES, SET THE ORDER TO\nC     ONE AND REDUCE THE STEPSIZE BY A FACTOR OF FOUR.\n670   K = 1\n      H = 0.25D0*H\n      IF (ABS(H) .GE. HMIN) GO TO 690\n      IDID = -6\n      GO TO 675\nC\nC\nC\nC\nC     FOR ALL CRASHES, RESTORE Y TO ITS LAST VALUE,\nC     INTERPOLATE TO FIND YPRIME AT LAST X, AND RETURN\n675   CONTINUE\n      CALL DDATRP(X,X,Y,YPRIME,NEQ,K,PHI,PSI)\n      RETURN\nC\nC\nC     GO BACK AND TRY THIS STEP AGAIN\n690   GO TO 200\nC\nC------END OF SUBROUTINE DDASTP------\n      END\n"
  },
  {
    "path": "liboctave/external/dassl/ddatrp.f",
    "content": "      SUBROUTINE DDATRP (X, XOUT, YOUT, YPOUT, NEQ, KOLD, PHI, PSI)\nC***BEGIN PROLOGUE  DDATRP\nC***SUBSIDIARY\nC***PURPOSE  Interpolation routine for DDASSL.\nC***LIBRARY   SLATEC (DASSL)\nC***TYPE      DOUBLE PRECISION (SDATRP-S, DDATRP-D)\nC***AUTHOR  PETZOLD, LINDA R., (LLNL)\nC***DESCRIPTION\nC-----------------------------------------------------------------------\nC     THE METHODS IN SUBROUTINE DDASTP USE POLYNOMIALS\nC     TO APPROXIMATE THE SOLUTION. DDATRP APPROXIMATES THE\nC     SOLUTION AND ITS DERIVATIVE AT TIME XOUT BY EVALUATING\nC     ONE OF THESE POLYNOMIALS,AND ITS DERIVATIVE,THERE.\nC     INFORMATION DEFINING THIS POLYNOMIAL IS PASSED FROM\nC     DDASTP, SO DDATRP CANNOT BE USED ALONE.\nC\nC     THE PARAMETERS ARE:\nC     X     THE CURRENT TIME IN THE INTEGRATION.\nC     XOUT  THE TIME AT WHICH THE SOLUTION IS DESIRED\nC     YOUT  THE INTERPOLATED APPROXIMATION TO Y AT XOUT\nC           (THIS IS OUTPUT)\nC     YPOUT THE INTERPOLATED APPROXIMATION TO YPRIME AT XOUT\nC           (THIS IS OUTPUT)\nC     NEQ   NUMBER OF EQUATIONS\nC     KOLD  ORDER USED ON LAST SUCCESSFUL STEP\nC     PHI   ARRAY OF SCALED DIVIDED DIFFERENCES OF Y\nC     PSI   ARRAY OF PAST STEPSIZE HISTORY\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   830315  DATE WRITTEN\nC   901009  Finished conversion to SLATEC 4.0 format (F.N.Fritsch)\nC   901019  Merged changes made by C. Ulrich with SLATEC 4.0 format.\nC   901026  Added explicit declarations for all variables and minor\nC           cosmetic changes to prologue.  (FNF)\nC***END PROLOGUE  DDATRP\nC\n      INTEGER  NEQ, KOLD\n      DOUBLE PRECISION  X, XOUT, YOUT(*), YPOUT(*), PHI(NEQ,*), PSI(*)\nC\n      INTEGER  I, J, KOLDP1\n      DOUBLE PRECISION  C, D, GAMMA, TEMP1\nC\nC***FIRST EXECUTABLE STATEMENT  DDATRP\n      KOLDP1=KOLD+1\n      TEMP1=XOUT-X\n      DO 10 I=1,NEQ\n         YOUT(I)=PHI(I,1)\n10       YPOUT(I)=0.0D0\n      C=1.0D0\n      D=0.0D0\n      GAMMA=TEMP1/PSI(1)\n      DO 30 J=2,KOLDP1\n         D=D*GAMMA+C/PSI(J-1)\n         C=C*GAMMA\n         GAMMA=(TEMP1+PSI(J-1))/PSI(J)\n         DO 20 I=1,NEQ\n            YOUT(I)=YOUT(I)+C*PHI(I,J)\n20          YPOUT(I)=YPOUT(I)+D*PHI(I,J)\n30       CONTINUE\n      RETURN\nC\nC------END OF SUBROUTINE DDATRP------\n      END\n"
  },
  {
    "path": "liboctave/external/dassl/ddawts.f",
    "content": "      SUBROUTINE DDAWTS (NEQ, IWT, RTOL, ATOL, Y, WT, RPAR, IPAR)\nC***BEGIN PROLOGUE  DDAWTS\nC***SUBSIDIARY\nC***PURPOSE  Set error weight vector for DDASSL.\nC***LIBRARY   SLATEC (DASSL)\nC***TYPE      DOUBLE PRECISION (SDAWTS-S, DDAWTS-D)\nC***AUTHOR  PETZOLD, LINDA R., (LLNL)\nC***DESCRIPTION\nC-----------------------------------------------------------------------\nC     THIS SUBROUTINE SETS THE ERROR WEIGHT VECTOR\nC     WT ACCORDING TO WT(I)=RTOL(I)*ABS(Y(I))+ATOL(I),\nC     I=1,-,N.\nC     RTOL AND ATOL ARE SCALARS IF IWT = 0,\nC     AND VECTORS IF IWT = 1.\nC-----------------------------------------------------------------------\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   830315  DATE WRITTEN\nC   901009  Finished conversion to SLATEC 4.0 format (F.N.Fritsch)\nC   901019  Merged changes made by C. Ulrich with SLATEC 4.0 format.\nC   901026  Added explicit declarations for all variables and minor\nC           cosmetic changes to prologue.  (FNF)\nC***END PROLOGUE  DDAWTS\nC\n      INTEGER  NEQ, IWT, IPAR(*)\n      DOUBLE PRECISION  RTOL(*), ATOL(*), Y(*), WT(*), RPAR(*)\nC\n      INTEGER  I\n      DOUBLE PRECISION  ATOLI, RTOLI\nC\nC***FIRST EXECUTABLE STATEMENT  DDAWTS\n      RTOLI=RTOL(1)\n      ATOLI=ATOL(1)\n      DO 20 I=1,NEQ\n         IF (IWT .EQ.0) GO TO 10\n           RTOLI=RTOL(I)\n           ATOLI=ATOL(I)\n10         WT(I)=RTOLI*ABS(Y(I))+ATOLI\n20         CONTINUE\n      RETURN\nC-----------END OF SUBROUTINE DDAWTS------------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/dassl/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/ddaini.f \\\n  %reldir%/ddajac.f \\\n  %reldir%/ddanrm.f \\\n  %reldir%/ddaslv.f \\\n  %reldir%/ddassl.f \\\n  %reldir%/ddastp.f \\\n  %reldir%/ddatrp.f \\\n  %reldir%/ddawts.f\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/crsf2csf.f",
    "content": "c Copyright (C) 2010-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n\n       subroutine crsf2csf(n,t,u,c,s)\n       integer n\n       complex t(n,n),u(n,n)\n       real c(n-1),s(n-1)\n       real x,y,z\n       integer j\n       do j = 1,n-1\n          c(j) = 1\n       end do\n       j = 1\n       do while (j < n)\nc apply previous rotations to rows\n         call crcrot1(j,t(1,j),c,s)\n\n         y = t(j+1,j)\n         if (y /= 0) then\nc 2x2 block, form Givens rotation [c, i*s; i*s, c]\n           z = t(j,j+1)\n           c(j) = sqrt(z/(z-y))\n           s(j) = sqrt(y/(y-z))\nc apply new rotation to t(j:j+1,j)\n           call crcrot1(2,t(j,j),c(j),s(j))\nc apply all rotations to t(1:j+1,j+1)\n           call crcrot1(j+1,t(1,j+1),c,s)\nc apply new rotation to columns j,j+1\n           call crcrot2(j+1,t(1,j),t(1,j+1),c(j),s(j))\nc zero subdiagonal entry, skip next row\n           t(j+1,j) = 0\n           j = j + 2\n         else\n           j = j + 1\n         end if\n       end do\n\nc apply rotations to last column if needed\n       if (j == n) then\n         call crcrot1(j,t(1,j),c,s)\n       end if\n\nc apply stored rotations to all columns of u\n       do j = 1,n-1\n         if (c(j) /= 1) then\n           call crcrot2(n,u(1,j),u(1,j+1),c(j),s(j))\n         end if\n       end do\n\n       end subroutine\n\n       subroutine crcrot1(n,x,c,s)\nc apply rotations to a column from the left\n       integer n\n       complex x(n), t\n       real c(n-1),s(n-1)\n       integer i\n       do i = 1,n-1\n         if (c(i) /= 1) then\n           t = x(i)*c(i) - x(i+1)*cmplx(0,s(i))\n           x(i+1) = x(i+1)*c(i) - x(i)*cmplx(0,s(i))\n           x(i) = t\n         endif\n       end do\n       end subroutine\n\n       subroutine crcrot2(n,x,y,c,s)\nc apply a single rotation from the right to a pair of columns\n       integer n\n       complex x(n),y(n),t\n       real c, s\n       integer i\n       do i = 1,n\n         t = x(i)*c + y(i)*cmplx(0,s)\n         y(i) = y(i)*c + x(i)*cmplx(0,s)\n         x(i) = t\n       end do\n       end subroutine\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/xclange.f \\\n  %reldir%/xdlamch.f \\\n  %reldir%/xdlange.f \\\n  %reldir%/xilaenv.f \\\n  %reldir%/xslamch.f \\\n  %reldir%/xslange.f \\\n  %reldir%/xzlange.f \\\n  %reldir%/zrsf2csf.f \\\n  %reldir%/crsf2csf.f\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/xclange.f",
    "content": "      subroutine xclange (norm, m, n, a, lda, work, retval)\n      character norm\n      integer lda, m, n\n      complex a (lda, *)\n      real work (*), clange, retval\n      external clange\n      retval = clange (norm, m, n, a, lda, work)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/xdlamch.f",
    "content": "      subroutine xdlamch (cmach, retval)\n      character cmach\n      double precision retval, dlamch\n      retval = dlamch (cmach)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/xdlange.f",
    "content": "      subroutine xdlange (norm, m, n, a, lda, work, retval)\n      character norm\n      integer lda, m, n\n      double precision a (lda, *), work (*), dlange, retval\n      retval = dlange (norm, m, n, a, lda, work)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/xilaenv.f",
    "content": "      subroutine xilaenv (ispec, name, opts, n1, n2, n3, n4, retval)\n      character*(*) name, opts\n      integer ilaenv, ispec, n1, n2, n3, n4, retval\n      retval = ilaenv (ispec, name, opts, n1, n2, n3, n4)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/xslamch.f",
    "content": "      subroutine xslamch (cmach, retval)\n      character cmach\n      real retval, slamch\n      retval = slamch (cmach)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/xslange.f",
    "content": "      subroutine xslange (norm, m, n, a, lda, work, retval)\n      character norm\n      integer lda, m, n\n      real a (lda, *), work (*), slange, retval\n      retval = slange (norm, m, n, a, lda, work)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/xzlange.f",
    "content": "      subroutine xzlange (norm, m, n, a, lda, work, retval)\n      character norm\n      integer lda, m, n\n      double complex a (lda, *)\n      double precision work (*), zlange, retval\n      external zlange\n      retval = zlange (norm, m, n, a, lda, work)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/lapack-xtra/zrsf2csf.f",
    "content": "c Copyright (C) 2010-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n\n       subroutine zrsf2csf(n,t,u,c,s)\n       integer n\n       double complex t(n,n),u(n,n)\n       double precision c(n-1),s(n-1)\n       double precision x,y,z\n       integer j\n       do j = 1,n-1\n          c(j) = 1\n       end do\n       j = 1\n       do while (j < n)\nc apply previous rotations to rows\n         call zrcrot1(j,t(1,j),c,s)\n\n         y = t(j+1,j)\n         if (y /= 0) then\nc 2x2 block, form Givens rotation [c, i*s; i*s, c]\n           z = t(j,j+1)\n           c(j) = sqrt(z/(z-y))\n           s(j) = sqrt(y/(y-z))\nc apply new rotation to t(j:j+1,j)\n           call zrcrot1(2,t(j,j),c(j),s(j))\nc apply all rotations to t(1:j+1,j+1)\n           call zrcrot1(j+1,t(1,j+1),c,s)\nc apply new rotation to columns j,j+1\n           call zrcrot2(j+1,t(1,j),t(1,j+1),c(j),s(j))\nc zero subdiagonal entry, skip next row\n           t(j+1,j) = 0\n           j = j + 2\n         else\n           j = j + 1\n         end if\n       end do\n\nc apply rotations to last column if needed\n       if (j == n) then\n         call zrcrot1(j,t(1,j),c,s)\n       end if\n\nc apply stored rotations to all columns of u\n       do j = 1,n-1\n         if (c(j) /= 1) then\n           call zrcrot2(n,u(1,j),u(1,j+1),c(j),s(j))\n         end if\n       end do\n\n       end subroutine\n\n       subroutine zrcrot1(n,x,c,s)\nc apply rotations to a column from the left\n       integer n\n       double complex x(n), t\n       double precision c(n-1),s(n-1)\n       integer i\n       do i = 1,n-1\n         if (c(i) /= 1) then\n           t = x(i)*c(i) - x(i+1)*dcmplx(0,s(i))\n           x(i+1) = x(i+1)*c(i) - x(i)*dcmplx(0,s(i))\n           x(i) = t\n         endif\n       end do\n       end subroutine\n\n       subroutine zrcrot2(n,x,y,c,s)\nc apply a single rotation from the right to a pair of columns\n       integer n\n       double complex x(n),y(n),t\n       double precision c, s\n       integer i\n       do i = 1,n\n         t = x(i)*c + y(i)*dcmplx(0,s)\n         y(i) = y(i)*c + x(i)*dcmplx(0,s)\n         x(i) = t\n       end do\n       end subroutine\n"
  },
  {
    "path": "liboctave/external/mk-f77-def.in.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n: ${SED=@SED@}\n: ${AWK=@AWK@}\n\nF77_TOLOWER=\"@F77_TOLOWER@\"\nF77_APPEND_UNDERSCORE=\"@F77_APPEND_UNDERSCORE@\"\nF77_APPEND_EXTRA_UNDERSCORE=\"@F77_APPEND_EXTRA_UNDERSCORE@\"\n\nif test x$F77_TOLOWER = xyes; then\n  case_cmd=tolower\nelse\n  case_cmd=toupper\nfi\n\nif test x$F77_APPEND_UNDERSCORE = xyes; then\n  uscore=_\nelse\n  uscore=\nfi\n\nif test x$F77_APPEND_EXTRA_UNDERSCORE = xyes; then\n  awkcmd=\"$AWK '{ if (\\$0 ~ /_/) extra = \\\"_\\\"; else extra = \\\"\\\"; printf (\\\"%s%s%s\\n\\\", $case_cmd (\\$0), \\\"$uscore\\\", extra); }'\"\nelse\n  awkcmd=\"$AWK '{ printf (\\\"%s%s\\n\\\", tolower (\\$0), \\\"$uscore\\\"); }'\"\nfi\n\nif [ $# -gt 1 ]; then\n  srcdir=\"$1\"\n  shift\nfi\n\necho EXPORTS\nfor arg\ndo\n  case \"$arg\" in\n    *.f)\n      ## There are TABS in this sed command.\n      $SED -n -e 'y/ABCDEFGHIJLKMNOPQRSTUVWXYZ/abcdefghijlkmnopqrstuvwxyz/; s/^\\(      \\|\t\\)[ \t]*\\(.*function\\|subroutine\\|entry\\)[ \t]*\\([^ \t(]*\\).*$/\\3/p' \"$srcdir/$arg\" | eval $awkcmd\n    ;;\n  esac\ndone\n"
  },
  {
    "path": "liboctave/external/module.mk",
    "content": "nodist_%canon_reldir%_libexternal_la_SOURCES =\n\n%canon_reldir%_libexternal_la_FFLAGS = $(F77_INTEGER_8_FLAG)\n\n%canon_reldir%_libexternal_la_DEPENDENCIES = %reldir%/external.def\n\nEXTERNAL_INC =\n\nEXTERNAL_SOURCES =\n\ninclude %reldir%/amos/module.mk\ninclude %reldir%/blas-xtra/module.mk\ninclude %reldir%/daspk/module.mk\ninclude %reldir%/dasrt/module.mk\ninclude %reldir%/dassl/module.mk\ninclude %reldir%/Faddeeva/module.mk\ninclude %reldir%/lapack-xtra/module.mk\ninclude %reldir%/odepack/module.mk\ninclude %reldir%/quadpack/module.mk\ninclude %reldir%/ranlib/module.mk\ninclude %reldir%/slatec-err/module.mk\ninclude %reldir%/slatec-fn/module.mk\n\n%reldir%/external.def: $(%canon_reldir%_libexternal_la_SOURCES) %reldir%/mk-f77-def.sh\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(SHELL) %reldir%/mk-f77-def.sh $(srcdir) $(%canon_reldir%_libexternal_la_SOURCES) > $@-t && \\\n\tmv $@-t $@\n\nliboctave_CLEANFILES += \\\n  %reldir%/external.def \\\n  %reldir%/ranlib/ranlib.def \\\n  $(nodist_%canon_reldir%_libexternal_la_SOURCES)\n\nnoinst_LTLIBRARIES += %reldir%/libexternal.la\n\n%canon_reldir%_libexternal_la_SOURCES = $(EXTERNAL_SOURCES)\n\n%canon_reldir%_libexternal_la_CPPFLAGS = $(liboctave_liboctave_la_CPPFLAGS)\n\nliboctave_liboctave_la_LIBADD += %reldir%/libexternal.la\n\nliboctave_EXTRA_DIST += \\\n  %reldir%/mk-f77-def.in.sh\n\nGEN_CONFIG_SHELL += \\\n  %reldir%/mk-f77-def.sh\n"
  },
  {
    "path": "liboctave/external/odepack/dcfode.f",
    "content": "      SUBROUTINE DCFODE (METH, ELCO, TESCO)\nC***BEGIN PROLOGUE  DCFODE\nC***SUBSIDIARY\nC***PURPOSE  Set ODE integrator coefficients.\nC***TYPE      DOUBLE PRECISION (SCFODE-S, DCFODE-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  DCFODE is called by the integrator routine to set coefficients\nC  needed there.  The coefficients for the current method, as\nC  given by the value of METH, are set for all orders and saved.\nC  The maximum order assumed here is 12 if METH = 1 and 5 if METH = 2.\nC  (A smaller value of the maximum order is also allowed.)\nC  DCFODE is called once at the beginning of the problem,\nC  and is not called again unless and until METH is changed.\nC\nC  The ELCO array contains the basic method coefficients.\nC  The coefficients el(i), 1 .le. i .le. nq+1, for the method of\nC  order nq are stored in ELCO(i,nq).  They are given by a genetrating\nC  polynomial, i.e.,\nC      l(x) = el(1) + el(2)*x + ... + el(nq+1)*x**nq.\nC  For the implicit Adams methods, l(x) is given by\nC      dl/dx = (x+1)*(x+2)*...*(x+nq-1)/factorial(nq-1),    l(-1) = 0.\nC  For the BDF methods, l(x) is given by\nC      l(x) = (x+1)*(x+2)* ... *(x+nq)/K,\nC  where         K = factorial(nq)*(1 + 1/2 + ... + 1/nq).\nC\nC  The TESCO array contains test constants used for the\nC  local error test and the selection of step size and/or order.\nC  At order nq, TESCO(k,nq) is used for the selection of step\nC  size at order nq - 1 if k = 1, at order nq if k = 2, and at order\nC  nq + 1 if k = 3.\nC\nC***SEE ALSO  DLSODE\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC***END PROLOGUE  DCFODE\nC**End\n      INTEGER METH\n      INTEGER I, IB, NQ, NQM1, NQP1\n      DOUBLE PRECISION ELCO, TESCO\n      DOUBLE PRECISION AGAMQ, FNQ, FNQM1, PC, PINT, RAGQ,\n     1   RQFAC, RQ1FAC, TSIGN, XPIN\n      DIMENSION ELCO(13,12), TESCO(3,12)\n      DIMENSION PC(12)\nC\nC***FIRST EXECUTABLE STATEMENT  DCFODE\n      GO TO (100, 200), METH\nC\n 100  ELCO(1,1) = 1.0D0\n      ELCO(2,1) = 1.0D0\n      TESCO(1,1) = 0.0D0\n      TESCO(2,1) = 2.0D0\n      TESCO(1,2) = 1.0D0\n      TESCO(3,12) = 0.0D0\n      PC(1) = 1.0D0\n      RQFAC = 1.0D0\n      DO 140 NQ = 2,12\nC-----------------------------------------------------------------------\nC The PC array will contain the coefficients of the polynomial\nC     p(x) = (x+1)*(x+2)*...*(x+nq-1).\nC Initially, p(x) = 1.\nC-----------------------------------------------------------------------\n        RQ1FAC = RQFAC\n        RQFAC = RQFAC/NQ\n        NQM1 = NQ - 1\n        FNQM1 = NQM1\n        NQP1 = NQ + 1\nC Form coefficients of p(x)*(x+nq-1). ----------------------------------\n        PC(NQ) = 0.0D0\n        DO 110 IB = 1,NQM1\n          I = NQP1 - IB\n 110      PC(I) = PC(I-1) + FNQM1*PC(I)\n        PC(1) = FNQM1*PC(1)\nC Compute integral, -1 to 0, of p(x) and x*p(x). -----------------------\n        PINT = PC(1)\n        XPIN = PC(1)/2.0D0\n        TSIGN = 1.0D0\n        DO 120 I = 2,NQ\n          TSIGN = -TSIGN\n          PINT = PINT + TSIGN*PC(I)/I\n 120      XPIN = XPIN + TSIGN*PC(I)/(I+1)\nC Store coefficients in ELCO and TESCO. --------------------------------\n        ELCO(1,NQ) = PINT*RQ1FAC\n        ELCO(2,NQ) = 1.0D0\n        DO 130 I = 2,NQ\n 130      ELCO(I+1,NQ) = RQ1FAC*PC(I)/I\n        AGAMQ = RQFAC*XPIN\n        RAGQ = 1.0D0/AGAMQ\n        TESCO(2,NQ) = RAGQ\n        IF (NQ .LT. 12) TESCO(1,NQP1) = RAGQ*RQFAC/NQP1\n        TESCO(3,NQM1) = RAGQ\n 140    CONTINUE\n      RETURN\nC\n 200  PC(1) = 1.0D0\n      RQ1FAC = 1.0D0\n      DO 230 NQ = 1,5\nC-----------------------------------------------------------------------\nC The PC array will contain the coefficients of the polynomial\nC     p(x) = (x+1)*(x+2)*...*(x+nq).\nC Initially, p(x) = 1.\nC-----------------------------------------------------------------------\n        FNQ = NQ\n        NQP1 = NQ + 1\nC Form coefficients of p(x)*(x+nq). ------------------------------------\n        PC(NQP1) = 0.0D0\n        DO 210 IB = 1,NQ\n          I = NQ + 2 - IB\n 210      PC(I) = PC(I-1) + FNQ*PC(I)\n        PC(1) = FNQ*PC(1)\nC Store coefficients in ELCO and TESCO. --------------------------------\n        DO 220 I = 1,NQP1\n 220      ELCO(I,NQ) = PC(I)/PC(2)\n        ELCO(2,NQ) = 1.0D0\n        TESCO(1,NQ) = RQ1FAC\n        TESCO(2,NQ) = NQP1/ELCO(1,NQ)\n        TESCO(3,NQ) = (NQ+2)/ELCO(1,NQ)\n        RQ1FAC = RQ1FAC/FNQ\n 230    CONTINUE\n      RETURN\nC----------------------- END OF SUBROUTINE DCFODE ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/dewset.f",
    "content": "      SUBROUTINE DEWSET (N, ITOL, RTOL, ATOL, YCUR, EWT)\nC***BEGIN PROLOGUE  DEWSET\nC***SUBSIDIARY\nC***PURPOSE  Set error weight vector.\nC***TYPE      DOUBLE PRECISION (SEWSET-S, DEWSET-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  This subroutine sets the error weight vector EWT according to\nC      EWT(i) = RTOL(i)*ABS(YCUR(i)) + ATOL(i),  i = 1,...,N,\nC  with the subscript on RTOL and/or ATOL possibly replaced by 1 above,\nC  depending on the value of ITOL.\nC\nC***SEE ALSO  DLSODE\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC***END PROLOGUE  DEWSET\nC**End\n      INTEGER N, ITOL\n      INTEGER I\n      DOUBLE PRECISION RTOL, ATOL, YCUR, EWT\n      DIMENSION RTOL(*), ATOL(*), YCUR(N), EWT(N)\nC\nC***FIRST EXECUTABLE STATEMENT  DEWSET\n      GO TO (10, 20, 30, 40), ITOL\n 10   CONTINUE\n      DO 15 I = 1,N\n 15     EWT(I) = RTOL(1)*ABS(YCUR(I)) + ATOL(1)\n      RETURN\n 20   CONTINUE\n      DO 25 I = 1,N\n 25     EWT(I) = RTOL(1)*ABS(YCUR(I)) + ATOL(I)\n      RETURN\n 30   CONTINUE\n      DO 35 I = 1,N\n 35     EWT(I) = RTOL(I)*ABS(YCUR(I)) + ATOL(1)\n      RETURN\n 40   CONTINUE\n      DO 45 I = 1,N\n 45     EWT(I) = RTOL(I)*ABS(YCUR(I)) + ATOL(I)\n      RETURN\nC----------------------- END OF SUBROUTINE DEWSET ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/dintdy.f",
    "content": "      SUBROUTINE DINTDY (T, K, YH, NYH, DKY, IFLAG)\nC***BEGIN PROLOGUE  DINTDY\nC***SUBSIDIARY\nC***PURPOSE  Interpolate solution derivatives.\nC***TYPE      DOUBLE PRECISION (SINTDY-S, DINTDY-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  DINTDY computes interpolated values of the K-th derivative of the\nC  dependent variable vector y, and stores it in DKY.  This routine\nC  is called within the package with K = 0 and T = TOUT, but may\nC  also be called by the user for any K up to the current order.\nC  (See detailed instructions in the usage documentation.)\nC\nC  The computed values in DKY are gotten by interpolation using the\nC  Nordsieck history array YH.  This array corresponds uniquely to a\nC  vector-valued polynomial of degree NQCUR or less, and DKY is set\nC  to the K-th derivative of this polynomial at T.\nC  The formula for DKY is:\nC               q\nC   DKY(i)  =  sum  c(j,K) * (T - tn)**(j-K) * h**(-j) * YH(i,j+1)\nC              j=K\nC  where  c(j,K) = j*(j-1)*...*(j-K+1), q = NQCUR, tn = TCUR, h = HCUR.\nC  The quantities  nq = NQCUR, l = nq+1, N = NEQ, tn, and h are\nC  communicated by COMMON.  The above sum is done in reverse order.\nC  IFLAG is returned negative if either K or T is out of bounds.\nC\nC***SEE ALSO  DLSODE\nC***ROUTINES CALLED  XERRWD\nC***COMMON BLOCKS    DLS001\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC   010418  Reduced size of Common block /DLS001/. (ACH)\nC   031105  Restored 'own' variables to Common block /DLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC   050427  Corrected roundoff decrement in TP. (ACH)\nC***END PROLOGUE  DINTDY\nC**End\n      INTEGER K, NYH, IFLAG\n      DOUBLE PRECISION T, YH, DKY\n      DIMENSION YH(NYH,*), DKY(*)\n      INTEGER ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     1   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, CNYH,\n     2   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP\n      INTEGER ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     2   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      DOUBLE PRECISION CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      COMMON /DLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     2   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     3   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, CNYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     4   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, IC, J, JB, JB2, JJ, JJ1, JP1\n      DOUBLE PRECISION C, R, S, TP\n      CHARACTER*80 MSG\nC\nC***FIRST EXECUTABLE STATEMENT  DINTDY\n      IFLAG = 0\n      IF (K .LT. 0 .OR. K .GT. NQ) GO TO 80\n      TP = TN - HU -  100.0D0*UROUND*SIGN(ABS(TN) + ABS(HU), HU)\n      IF ((T-TP)*(T-TN) .GT. 0.0D0) GO TO 90\nC\n      S = (T - TN)/H\n      IC = 1\n      IF (K .EQ. 0) GO TO 15\n      JJ1 = L - K\n      DO 10 JJ = JJ1,NQ\n 10     IC = IC*JJ\n 15   C = IC\n      DO 20 I = 1,N\n 20     DKY(I) = C*YH(I,L)\n      IF (K .EQ. NQ) GO TO 55\n      JB2 = NQ - K\n      DO 50 JB = 1,JB2\n        J = NQ - JB\n        JP1 = J + 1\n        IC = 1\n        IF (K .EQ. 0) GO TO 35\n        JJ1 = JP1 - K\n        DO 30 JJ = JJ1,J\n 30       IC = IC*JJ\n 35     C = IC\n        DO 40 I = 1,N\n 40       DKY(I) = C*YH(I,JP1) + S*DKY(I)\n 50     CONTINUE\n      IF (K .EQ. 0) RETURN\n 55   R = H**(-K)\n      DO 60 I = 1,N\n 60     DKY(I) = R*DKY(I)\n      RETURN\nC\n 80   MSG = 'DINTDY-  K (=I1) illegal      '\n      CALL XERRWD (MSG, 30, 51, 0, 1, K, 0, 0, 0.0D0, 0.0D0)\n      IFLAG = -1\n      RETURN\n 90   MSG = 'DINTDY-  T (=R1) illegal      '\n      CALL XERRWD (MSG, 30, 52, 0, 0, 0, 0, 1, T, 0.0D0)\n      MSG='      T not in interval TCUR - HU (= R1) to TCUR (=R2)      '\n      CALL XERRWD (MSG, 60, 52, 0, 0, 0, 0, 2, TP, TN)\n      IFLAG = -2\n      RETURN\nC----------------------- END OF SUBROUTINE DINTDY ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/dlsode.f",
    "content": "      SUBROUTINE DLSODE (F, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK,\n     1                  ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, MF)\n      EXTERNAL F, JAC\n      INTEGER NEQ, ITOL, ITASK, ISTATE, IOPT, LRW, IWORK, LIW, MF\n      DOUBLE PRECISION Y, T, TOUT, RTOL, ATOL, RWORK\n      DIMENSION NEQ(*), Y(*), RTOL(*), ATOL(*), RWORK(LRW), IWORK(LIW)\nC***BEGIN PROLOGUE  DLSODE\nC***PURPOSE  Livermore Solver for Ordinary Differential Equations.\nC            DLSODE solves the initial-value problem for stiff or\nC            nonstiff systems of first-order ODE's,\nC               dy/dt = f(t,y),   or, in component form,\nC               dy(i)/dt = f(i) = f(i,t,y(1),y(2),...,y(N)),  i=1,...,N.\nC***CATEGORY  I1A\nC***TYPE      DOUBLE PRECISION (SLSODE-S, DLSODE-D)\nC***KEYWORDS  ORDINARY DIFFERENTIAL EQUATIONS, INITIAL VALUE PROBLEM,\nC             STIFF, NONSTIFF\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC             Center for Applied Scientific Computing, L-561\nC             Lawrence Livermore National Laboratory\nC             Livermore, CA 94551.\nC***DESCRIPTION\nC\nC     NOTE: The \"Usage\" and \"Arguments\" sections treat only a subset of\nC           available options, in condensed fashion.  The options\nC           covered and the information supplied will support most\nC           standard uses of DLSODE.\nC\nC           For more sophisticated uses, full details on all options are\nC           given in the concluding section, headed \"Long Description.\"\nC           A synopsis of the DLSODE Long Description is provided at the\nC           beginning of that section; general topics covered are:\nC           - Elements of the call sequence; optional input and output\nC           - Optional supplemental routines in the DLSODE package\nC           - internal COMMON block\nC\nC *Usage:\nC     Communication between the user and the DLSODE package, for normal\nC     situations, is summarized here.  This summary describes a subset\nC     of the available options.  See \"Long Description\" for complete\nC     details, including optional communication, nonstandard options,\nC     and instructions for special situations.\nC\nC     A sample program is given in the \"Examples\" section.\nC\nC     Refer to the argument descriptions for the definitions of the\nC     quantities that appear in the following sample declarations.\nC\nC     For MF = 10,\nC        PARAMETER  (LRW = 20 + 16*NEQ,           LIW = 20)\nC     For MF = 21 or 22,\nC        PARAMETER  (LRW = 22 +  9*NEQ + NEQ**2,  LIW = 20 + NEQ)\nC     For MF = 24 or 25,\nC        PARAMETER  (LRW = 22 + 10*NEQ + (2*ML+MU)*NEQ,\nC       *                                         LIW = 20 + NEQ)\nC\nC        EXTERNAL F, JAC\nC        INTEGER  NEQ, ITOL, ITASK, ISTATE, IOPT, LRW, IWORK(LIW),\nC       *         LIW, MF\nC        DOUBLE PRECISION Y(NEQ), T, TOUT, RTOL, ATOL(ntol), RWORK(LRW)\nC\nC        CALL DLSODE (F, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK,\nC       *            ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, MF)\nC\nC *Arguments:\nC     F     :EXT    Name of subroutine for right-hand-side vector f.\nC                   This name must be declared EXTERNAL in calling\nC                   program.  The form of F must be:\nC\nC                   SUBROUTINE  F (NEQ, T, Y, YDOT)\nC                   INTEGER  NEQ\nC                   DOUBLE PRECISION  T, Y(*), YDOT(*)\nC\nC                   The inputs are NEQ, T, Y.  F is to set\nC\nC                   YDOT(i) = f(i,T,Y(1),Y(2),...,Y(NEQ)),\nC                                                     i = 1, ..., NEQ .\nC\nC     NEQ   :IN     Number of first-order ODE's.\nC\nC     Y     :INOUT  Array of values of the y(t) vector, of length NEQ.\nC                   Input:  For the first call, Y should contain the\nC                           values of y(t) at t = T. (Y is an input\nC                           variable only if ISTATE = 1.)\nC                   Output: On return, Y will contain the values at the\nC                           new t-value.\nC\nC     T     :INOUT  Value of the independent variable.  On return it\nC                   will be the current value of t (normally TOUT).\nC\nC     TOUT  :IN     Next point where output is desired (.NE. T).\nC\nC     ITOL  :IN     1 or 2 according as ATOL (below) is a scalar or\nC                   an array.\nC\nC     RTOL  :IN     Relative tolerance parameter (scalar).\nC\nC     ATOL  :IN     Absolute tolerance parameter (scalar or array).\nC                   If ITOL = 1, ATOL need not be dimensioned.\nC                   If ITOL = 2, ATOL must be dimensioned at least NEQ.\nC\nC                   The estimated local error in Y(i) will be controlled\nC                   so as to be roughly less (in magnitude) than\nC\nC                   EWT(i) = RTOL*ABS(Y(i)) + ATOL     if ITOL = 1, or\nC                   EWT(i) = RTOL*ABS(Y(i)) + ATOL(i)  if ITOL = 2.\nC\nC                   Thus the local error test passes if, in each\nC                   component, either the absolute error is less than\nC                   ATOL (or ATOL(i)), or the relative error is less\nC                   than RTOL.\nC\nC                   Use RTOL = 0.0 for pure absolute error control, and\nC                   use ATOL = 0.0 (or ATOL(i) = 0.0) for pure relative\nC                   error control.  Caution:  Actual (global) errors may\nC                   exceed these local tolerances, so choose them\nC                   conservatively.\nC\nC     ITASK :IN     Flag indicating the task DLSODE is to perform.\nC                   Use ITASK = 1 for normal computation of output\nC                   values of y at t = TOUT.\nC\nC     ISTATE:INOUT  Index used for input and output to specify the state\nC                   of the calculation.\nC                   Input:\nC                    1   This is the first call for a problem.\nC                    2   This is a subsequent call.\nC                   Output:\nC                    1   Nothing was done, because TOUT was equal to T.\nC                    2   DLSODE was successful (otherwise, negative).\nC                        Note that ISTATE need not be modified after a\nC                        successful return.\nC                   -1   Excess work done on this call (perhaps wrong\nC                        MF).\nC                   -2   Excess accuracy requested (tolerances too\nC                        small).\nC                   -3   Illegal input detected (see printed message).\nC                   -4   Repeated error test failures (check all\nC                        inputs).\nC                   -5   Repeated convergence failures (perhaps bad\nC                        Jacobian supplied or wrong choice of MF or\nC                        tolerances).\nC                   -6   Error weight became zero during problem\nC                        (solution component i vanished, and ATOL or\nC                        ATOL(i) = 0.).\nC\nC     IOPT  :IN     Flag indicating whether optional inputs are used:\nC                   0   No.\nC                   1   Yes.  (See \"Optional inputs\" under \"Long\nC                       Description,\" Part 1.)\nC\nC     RWORK :WORK   Real work array of length at least:\nC                   20 + 16*NEQ                    for MF = 10,\nC                   22 +  9*NEQ + NEQ**2           for MF = 21 or 22,\nC                   22 + 10*NEQ + (2*ML + MU)*NEQ  for MF = 24 or 25.\nC\nC     LRW   :IN     Declared length of RWORK (in user's DIMENSION\nC                   statement).\nC\nC     IWORK :WORK   Integer work array of length at least:\nC                   20        for MF = 10,\nC                   20 + NEQ  for MF = 21, 22, 24, or 25.\nC\nC                   If MF = 24 or 25, input in IWORK(1),IWORK(2) the\nC                   lower and upper Jacobian half-bandwidths ML,MU.\nC\nC                   On return, IWORK contains information that may be\nC                   of interest to the user:\nC\nC            Name   Location   Meaning\nC            -----  ---------  -----------------------------------------\nC            NST    IWORK(11)  Number of steps taken for the problem so\nC                              far.\nC            NFE    IWORK(12)  Number of f evaluations for the problem\nC                              so far.\nC            NJE    IWORK(13)  Number of Jacobian evaluations (and of\nC                              matrix LU decompositions) for the problem\nC                              so far.\nC            NQU    IWORK(14)  Method order last used (successfully).\nC            LENRW  IWORK(17)  Length of RWORK actually required.  This\nC                              is defined on normal returns and on an\nC                              illegal input return for insufficient\nC                              storage.\nC            LENIW  IWORK(18)  Length of IWORK actually required.  This\nC                              is defined on normal returns and on an\nC                              illegal input return for insufficient\nC                              storage.\nC\nC     LIW   :IN     Declared length of IWORK (in user's DIMENSION\nC                   statement).\nC\nC     JAC   :EXT    Name of subroutine for Jacobian matrix (MF =\nC                   21 or 24).  If used, this name must be declared\nC                   EXTERNAL in calling program.  If not used, pass a\nC                   dummy name.  The form of JAC must be:\nC\nC                   SUBROUTINE JAC (NEQ, T, Y, ML, MU, PD, NROWPD)\nC                   INTEGER  NEQ, ML, MU, NROWPD\nC                   DOUBLE PRECISION  T, Y(*), PD(NROWPD,*)\nC\nC                   See item c, under \"Description\" below for more\nC                   information about JAC.\nC\nC     MF    :IN     Method flag.  Standard values are:\nC                   10  Nonstiff (Adams) method, no Jacobian used.\nC                   21  Stiff (BDF) method, user-supplied full Jacobian.\nC                   22  Stiff method, internally generated full\nC                       Jacobian.\nC                   24  Stiff method, user-supplied banded Jacobian.\nC                   25  Stiff method, internally generated banded\nC                       Jacobian.\nC\nC *Description:\nC     DLSODE solves the initial value problem for stiff or nonstiff\nC     systems of first-order ODE's,\nC\nC        dy/dt = f(t,y) ,\nC\nC     or, in component form,\nC\nC        dy(i)/dt = f(i) = f(i,t,y(1),y(2),...,y(NEQ))\nC                                                  (i = 1, ..., NEQ) .\nC\nC     DLSODE is a package based on the GEAR and GEARB packages, and on\nC     the October 23, 1978, version of the tentative ODEPACK user\nC     interface standard, with minor modifications.\nC\nC     The steps in solving such a problem are as follows.\nC\nC     a. First write a subroutine of the form\nC\nC           SUBROUTINE  F (NEQ, T, Y, YDOT)\nC           INTEGER  NEQ\nC           DOUBLE PRECISION  T, Y(*), YDOT(*)\nC\nC        which supplies the vector function f by loading YDOT(i) with\nC        f(i).\nC\nC     b. Next determine (or guess) whether or not the problem is stiff.\nC        Stiffness occurs when the Jacobian matrix df/dy has an\nC        eigenvalue whose real part is negative and large in magnitude\nC        compared to the reciprocal of the t span of interest.  If the\nC        problem is nonstiff, use method flag MF = 10.  If it is stiff,\nC        there are four standard choices for MF, and DLSODE requires the\nC        Jacobian matrix in some form.  This matrix is regarded either\nC        as full (MF = 21 or 22), or banded (MF = 24 or 25).  In the\nC        banded case, DLSODE requires two half-bandwidth parameters ML\nC        and MU. These are, respectively, the widths of the lower and\nC        upper parts of the band, excluding the main diagonal.  Thus the\nC        band consists of the locations (i,j) with\nC\nC           i - ML <= j <= i + MU ,\nC\nC        and the full bandwidth is ML + MU + 1 .\nC\nC     c. If the problem is stiff, you are encouraged to supply the\nC        Jacobian directly (MF = 21 or 24), but if this is not feasible,\nC        DLSODE will compute it internally by difference quotients (MF =\nC        22 or 25).  If you are supplying the Jacobian, write a\nC        subroutine of the form\nC\nC           SUBROUTINE  JAC (NEQ, T, Y, ML, MU, PD, NROWPD)\nC           INTEGER  NEQ, ML, MU, NRWOPD\nC           DOUBLE PRECISION  T, Y(*), PD(NROWPD,*)\nC\nC        which provides df/dy by loading PD as follows:\nC        - For a full Jacobian (MF = 21), load PD(i,j) with df(i)/dy(j),\nC          the partial derivative of f(i) with respect to y(j).  (Ignore\nC          the ML and MU arguments in this case.)\nC        - For a banded Jacobian (MF = 24), load PD(i-j+MU+1,j) with\nC          df(i)/dy(j); i.e., load the diagonal lines of df/dy into the\nC          rows of PD from the top down.\nC        - In either case, only nonzero elements need be loaded.\nC\nC     d. Write a main program that calls subroutine DLSODE once for each\nC        point at which answers are desired.  This should also provide\nC        for possible use of logical unit 6 for output of error messages\nC        by DLSODE.\nC\nC        Before the first call to DLSODE, set ISTATE = 1, set Y and T to\nC        the initial values, and set TOUT to the first output point.  To\nC        continue the integration after a successful return, simply\nC        reset TOUT and call DLSODE again.  No other parameters need be\nC        reset.\nC\nC *Examples:\nC     The following is a simple example problem, with the coding needed\nC     for its solution by DLSODE. The problem is from chemical kinetics,\nC     and consists of the following three rate equations:\nC\nC        dy1/dt = -.04*y1 + 1.E4*y2*y3\nC        dy2/dt = .04*y1 - 1.E4*y2*y3 - 3.E7*y2**2\nC        dy3/dt = 3.E7*y2**2\nC\nC     on the interval from t = 0.0 to t = 4.E10, with initial conditions\nC     y1 = 1.0, y2 = y3 = 0. The problem is stiff.\nC\nC     The following coding solves this problem with DLSODE, using\nC     MF = 21 and printing results at t = .4, 4., ..., 4.E10.  It uses\nC     ITOL = 2 and ATOL much smaller for y2 than for y1 or y3 because y2\nC     has much smaller values.  At the end of the run, statistical\nC     quantities of interest are printed.\nC\nC        EXTERNAL  FEX, JEX\nC        INTEGER  IOPT, IOUT, ISTATE, ITASK, ITOL, IWORK(23), LIW, LRW,\nC       *         MF, NEQ\nC        DOUBLE PRECISION  ATOL(3), RTOL, RWORK(58), T, TOUT, Y(3)\nC        NEQ = 3\nC        Y(1) = 1.D0\nC        Y(2) = 0.D0\nC        Y(3) = 0.D0\nC        T = 0.D0\nC        TOUT = .4D0\nC        ITOL = 2\nC        RTOL = 1.D-4\nC        ATOL(1) = 1.D-6\nC        ATOL(2) = 1.D-10\nC        ATOL(3) = 1.D-6\nC        ITASK = 1\nC        ISTATE = 1\nC        IOPT = 0\nC        LRW = 58\nC        LIW = 23\nC        MF = 21\nC        DO 40 IOUT = 1,12\nC          CALL DLSODE (FEX, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK,\nC       *               ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JEX, MF)\nC          WRITE(6,20)  T, Y(1), Y(2), Y(3)\nC    20    FORMAT(' At t =',D12.4,'   y =',3D14.6)\nC          IF (ISTATE .LT. 0)  GO TO 80\nC    40    TOUT = TOUT*10.D0\nC        WRITE(6,60)  IWORK(11), IWORK(12), IWORK(13)\nC    60  FORMAT(/' No. steps =',i4,',  No. f-s =',i4,',  No. J-s =',i4)\nC        STOP\nC    80  WRITE(6,90)  ISTATE\nC    90  FORMAT(///' Error halt.. ISTATE =',I3)\nC        STOP\nC        END\nC\nC        SUBROUTINE  FEX (NEQ, T, Y, YDOT)\nC        INTEGER  NEQ\nC        DOUBLE PRECISION  T, Y(3), YDOT(3)\nC        YDOT(1) = -.04D0*Y(1) + 1.D4*Y(2)*Y(3)\nC        YDOT(3) = 3.D7*Y(2)*Y(2)\nC        YDOT(2) = -YDOT(1) - YDOT(3)\nC        RETURN\nC        END\nC\nC        SUBROUTINE  JEX (NEQ, T, Y, ML, MU, PD, NRPD)\nC        INTEGER  NEQ, ML, MU, NRPD\nC        DOUBLE PRECISION  T, Y(3), PD(NRPD,3)\nC        PD(1,1) = -.04D0\nC        PD(1,2) = 1.D4*Y(3)\nC        PD(1,3) = 1.D4*Y(2)\nC        PD(2,1) = .04D0\nC        PD(2,3) = -PD(1,3)\nC        PD(3,2) = 6.D7*Y(2)\nC        PD(2,2) = -PD(1,2) - PD(3,2)\nC        RETURN\nC        END\nC\nC     The output from this program (on a Cray-1 in single precision)\nC     is as follows.\nC\nC     At t =  4.0000e-01   y =  9.851726e-01  3.386406e-05  1.479357e-02\nC     At t =  4.0000e+00   y =  9.055142e-01  2.240418e-05  9.446344e-02\nC     At t =  4.0000e+01   y =  7.158050e-01  9.184616e-06  2.841858e-01\nC     At t =  4.0000e+02   y =  4.504846e-01  3.222434e-06  5.495122e-01\nC     At t =  4.0000e+03   y =  1.831701e-01  8.940379e-07  8.168290e-01\nC     At t =  4.0000e+04   y =  3.897016e-02  1.621193e-07  9.610297e-01\nC     At t =  4.0000e+05   y =  4.935213e-03  1.983756e-08  9.950648e-01\nC     At t =  4.0000e+06   y =  5.159269e-04  2.064759e-09  9.994841e-01\nC     At t =  4.0000e+07   y =  5.306413e-05  2.122677e-10  9.999469e-01\nC     At t =  4.0000e+08   y =  5.494530e-06  2.197825e-11  9.999945e-01\nC     At t =  4.0000e+09   y =  5.129458e-07  2.051784e-12  9.999995e-01\nC     At t =  4.0000e+10   y = -7.170603e-08 -2.868241e-13  1.000000e+00\nC\nC     No. steps = 330,  No. f-s = 405,  No. J-s = 69\nC\nC *Accuracy:\nC     The accuracy of the solution depends on the choice of tolerances\nC     RTOL and ATOL.  Actual (global) errors may exceed these local\nC     tolerances, so choose them conservatively.\nC\nC *Cautions:\nC     The work arrays should not be altered between calls to DLSODE for\nC     the same problem, except possibly for the conditional and optional\nC     inputs.\nC\nC *Portability:\nC     Since NEQ is dimensioned inside DLSODE, some compilers may object\nC     to a call to DLSODE with NEQ a scalar variable.  In this event,\nC     use DIMENSION NEQ(1).  Similar remarks apply to RTOL and ATOL.\nC\nC     Note to Cray users:\nC     For maximum efficiency, use the CFT77 compiler.  Appropriate\nC     compiler optimization directives have been inserted for CFT77.\nC\nC *Reference:\nC     Alan C. Hindmarsh, \"ODEPACK, A Systematized Collection of ODE\nC     Solvers,\" in Scientific Computing, R. S. Stepleman, et al., Eds.\nC     (North-Holland, Amsterdam, 1983), pp. 55-64.\nC\nC *Long Description:\nC     The following complete description of the user interface to\nC     DLSODE consists of four parts:\nC\nC     1.  The call sequence to subroutine DLSODE, which is a driver\nC         routine for the solver.  This includes descriptions of both\nC         the call sequence arguments and user-supplied routines.\nC         Following these descriptions is a description of optional\nC         inputs available through the call sequence, and then a\nC         description of optional outputs in the work arrays.\nC\nC     2.  Descriptions of other routines in the DLSODE package that may\nC         be (optionally) called by the user.  These provide the ability\nC         to alter error message handling, save and restore the internal\nC         COMMON, and obtain specified derivatives of the solution y(t).\nC\nC     3.  Descriptions of COMMON block to be declared in overlay or\nC         similar environments, or to be saved when doing an interrupt\nC         of the problem and continued solution later.\nC\nC     4.  Description of two routines in the DLSODE package, either of\nC         which the user may replace with his own version, if desired.\nC         These relate to the measurement of errors.\nC\nC\nC                         Part 1.  Call Sequence\nC                         ----------------------\nC\nC     Arguments\nC     ---------\nC     The call sequence parameters used for input only are\nC\nC        F, NEQ, TOUT, ITOL, RTOL, ATOL, ITASK, IOPT, LRW, LIW, JAC, MF,\nC\nC     and those used for both input and output are\nC\nC        Y, T, ISTATE.\nC\nC     The work arrays RWORK and IWORK are also used for conditional and\nC     optional inputs and optional outputs.  (The term output here\nC     refers to the return from subroutine DLSODE to the user's calling\nC     program.)\nC\nC     The legality of input parameters will be thoroughly checked on the\nC     initial call for the problem, but not checked thereafter unless a\nC     change in input parameters is flagged by ISTATE = 3 on input.\nC\nC     The descriptions of the call arguments are as follows.\nC\nC     F        The name of the user-supplied subroutine defining the ODE\nC              system.  The system must be put in the first-order form\nC              dy/dt = f(t,y), where f is a vector-valued function of\nC              the scalar t and the vector y. Subroutine F is to compute\nC              the function f. It is to have the form\nC\nC                 SUBROUTINE F (NEQ, T, Y, YDOT)\nC                 DOUBLE PRECISION  T, Y(*), YDOT(*)\nC\nC              where NEQ, T, and Y are input, and the array YDOT =\nC              f(T,Y) is output.  Y and YDOT are arrays of length NEQ.\nC              Subroutine F should not alter Y(1),...,Y(NEQ).  F must be\nC              declared EXTERNAL in the calling program.\nC\nC              Subroutine F may access user-defined quantities in\nC              NEQ(2),... and/or in Y(NEQ(1)+1),..., if NEQ is an array\nC              (dimensioned in F) and/or Y has length exceeding NEQ(1).\nC              See the descriptions of NEQ and Y below.\nC\nC              If quantities computed in the F routine are needed\nC              externally to DLSODE, an extra call to F should be made\nC              for this purpose, for consistent and accurate results.\nC              If only the derivative dy/dt is needed, use DINTDY\nC              instead.\nC\nC     NEQ      The size of the ODE system (number of first-order\nC              ordinary differential equations).  Used only for input.\nC              NEQ may be decreased, but not increased, during the\nC              problem.  If NEQ is decreased (with ISTATE = 3 on input),\nC              the remaining components of Y should be left undisturbed,\nC              if these are to be accessed in F and/or JAC.\nC\nC              Normally, NEQ is a scalar, and it is generally referred\nC              to as a scalar in this user interface description.\nC              However, NEQ may be an array, with NEQ(1) set to the\nC              system size.  (The DLSODE package accesses only NEQ(1).)\nC              In either case, this parameter is passed as the NEQ\nC              argument in all calls to F and JAC.  Hence, if it is an\nC              array, locations NEQ(2),... may be used to store other\nC              integer data and pass it to F and/or JAC.  Subroutines\nC              F and/or JAC must include NEQ in a DIMENSION statement\nC              in that case.\nC\nC     Y        A real array for the vector of dependent variables, of\nC              length NEQ or more.  Used for both input and output on\nC              the first call (ISTATE = 1), and only for output on\nC              other calls.  On the first call, Y must contain the\nC              vector of initial values.  On output, Y contains the\nC              computed solution vector, evaluated at T. If desired,\nC              the Y array may be used for other purposes between\nC              calls to the solver.\nC\nC              This array is passed as the Y argument in all calls to F\nC              and JAC.  Hence its length may exceed NEQ, and locations\nC              Y(NEQ+1),... may be used to store other real data and\nC              pass it to F and/or JAC.  (The DLSODE package accesses\nC              only Y(1),...,Y(NEQ).)\nC\nC     T        The independent variable.  On input, T is used only on\nC              the first call, as the initial point of the integration.\nC              On output, after each call, T is the value at which a\nC              computed solution Y is evaluated (usually the same as\nC              TOUT).  On an error return, T is the farthest point\nC              reached.\nC\nC     TOUT     The next value of T at which a computed solution is\nC              desired.  Used only for input.\nC\nC              When starting the problem (ISTATE = 1), TOUT may be equal\nC              to T for one call, then should not equal T for the next\nC              call.  For the initial T, an input value of TOUT .NE. T\nC              is used in order to determine the direction of the\nC              integration (i.e., the algebraic sign of the step sizes)\nC              and the rough scale of the problem.  Integration in\nC              either direction (forward or backward in T) is permitted.\nC\nC              If ITASK = 2 or 5 (one-step modes), TOUT is ignored\nC              after the first call (i.e., the first call with\nC              TOUT .NE. T).  Otherwise, TOUT is required on every call.\nC\nC              If ITASK = 1, 3, or 4, the values of TOUT need not be\nC              monotone, but a value of TOUT which backs up is limited\nC              to the current internal T interval, whose endpoints are\nC              TCUR - HU and TCUR.  (See \"Optional Outputs\" below for\nC              TCUR and HU.)\nC\nC\nC     ITOL     An indicator for the type of error control.  See\nC              description below under ATOL.  Used only for input.\nC\nC     RTOL     A relative error tolerance parameter, either a scalar or\nC              an array of length NEQ.  See description below under\nC              ATOL.  Input only.\nC\nC     ATOL     An absolute error tolerance parameter, either a scalar or\nC              an array of length NEQ.  Input only.\nC\nC              The input parameters ITOL, RTOL, and ATOL determine the\nC              error control performed by the solver.  The solver will\nC              control the vector e = (e(i)) of estimated local errors\nC              in Y, according to an inequality of the form\nC\nC                 rms-norm of ( e(i)/EWT(i) ) <= 1,\nC\nC              where\nC\nC                 EWT(i) = RTOL(i)*ABS(Y(i)) + ATOL(i),\nC\nC              and the rms-norm (root-mean-square norm) here is\nC\nC                 rms-norm(v) = SQRT(sum v(i)**2 / NEQ).\nC\nC              Here EWT = (EWT(i)) is a vector of weights which must\nC              always be positive, and the values of RTOL and ATOL\nC              should all be nonnegative.  The following table gives the\nC              types (scalar/array) of RTOL and ATOL, and the\nC              corresponding form of EWT(i).\nC\nC              ITOL    RTOL      ATOL      EWT(i)\nC              ----    ------    ------    -----------------------------\nC              1       scalar    scalar    RTOL*ABS(Y(i)) + ATOL\nC              2       scalar    array     RTOL*ABS(Y(i)) + ATOL(i)\nC              3       array     scalar    RTOL(i)*ABS(Y(i)) + ATOL\nC              4       array     array     RTOL(i)*ABS(Y(i)) + ATOL(i)\nC\nC              When either of these parameters is a scalar, it need not\nC              be dimensioned in the user's calling program.\nC\nC              If none of the above choices (with ITOL, RTOL, and ATOL\nC              fixed throughout the problem) is suitable, more general\nC              error controls can be obtained by substituting\nC              user-supplied routines for the setting of EWT and/or for\nC              the norm calculation.  See Part 4 below.\nC\nC              If global errors are to be estimated by making a repeated\nC              run on the same problem with smaller tolerances, then all\nC              components of RTOL and ATOL (i.e., of EWT) should be\nC              scaled down uniformly.\nC\nC     ITASK    An index specifying the task to be performed.  Input\nC              only.  ITASK has the following values and meanings:\nC              1   Normal computation of output values of y(t) at\nC                  t = TOUT (by overshooting and interpolating).\nC              2   Take one step only and return.\nC              3   Stop at the first internal mesh point at or beyond\nC                  t = TOUT and return.\nC              4   Normal computation of output values of y(t) at\nC                  t = TOUT but without overshooting t = TCRIT.  TCRIT\nC                  must be input as RWORK(1).  TCRIT may be equal to or\nC                  beyond TOUT, but not behind it in the direction of\nC                  integration.  This option is useful if the problem\nC                  has a singularity at or beyond t = TCRIT.\nC              5   Take one step, without passing TCRIT, and return.\nC                  TCRIT must be input as RWORK(1).\nC\nC              Note:  If ITASK = 4 or 5 and the solver reaches TCRIT\nC              (within roundoff), it will return T = TCRIT (exactly) to\nC              indicate this (unless ITASK = 4 and TOUT comes before\nC              TCRIT, in which case answers at T = TOUT are returned\nC              first).\nC\nC     ISTATE   An index used for input and output to specify the state\nC              of the calculation.\nC\nC              On input, the values of ISTATE are as follows:\nC              1   This is the first call for the problem\nC                  (initializations will be done).  See \"Note\" below.\nC              2   This is not the first call, and the calculation is to\nC                  continue normally, with no change in any input\nC                  parameters except possibly TOUT and ITASK.  (If ITOL,\nC                  RTOL, and/or ATOL are changed between calls with\nC                  ISTATE = 2, the new values will be used but not\nC                  tested for legality.)\nC              3   This is not the first call, and the calculation is to\nC                  continue normally, but with a change in input\nC                  parameters other than TOUT and ITASK.  Changes are\nC                  allowed in NEQ, ITOL, RTOL, ATOL, IOPT, LRW, LIW, MF,\nC                  ML, MU, and any of the optional inputs except H0.\nC                  (See IWORK description for ML and MU.)\nC\nC              Note:  A preliminary call with TOUT = T is not counted as\nC              a first call here, as no initialization or checking of\nC              input is done.  (Such a call is sometimes useful for the\nC              purpose of outputting the initial conditions.)  Thus the\nC              first call for which TOUT .NE. T requires ISTATE = 1 on\nC              input.\nC\nC              On output, ISTATE has the following values and meanings:\nC               1  Nothing was done, as TOUT was equal to T with\nC                  ISTATE = 1 on input.\nC               2  The integration was performed successfully.\nC              -1  An excessive amount of work (more than MXSTEP steps)\nC                  was done on this call, before completing the\nC                  requested task, but the integration was otherwise\nC                  successful as far as T. (MXSTEP is an optional input\nC                  and is normally 500.)  To continue, the user may\nC                  simply reset ISTATE to a value >1 and call again (the\nC                  excess work step counter will be reset to 0).  In\nC                  addition, the user may increase MXSTEP to avoid this\nC                  error return; see \"Optional Inputs\" below.\nC              -2  Too much accuracy was requested for the precision of\nC                  the machine being used.  This was detected before\nC                  completing the requested task, but the integration\nC                  was successful as far as T. To continue, the\nC                  tolerance parameters must be reset, and ISTATE must\nC                  be set to 3. The optional output TOLSF may be used\nC                  for this purpose.  (Note:  If this condition is\nC                  detected before taking any steps, then an illegal\nC                  input return (ISTATE = -3) occurs instead.)\nC              -3  Illegal input was detected, before taking any\nC                  integration steps.  See written message for details.\nC                  (Note:  If the solver detects an infinite loop of\nC                  calls to the solver with illegal input, it will cause\nC                  the run to stop.)\nC              -4  There were repeated error-test failures on one\nC                  attempted step, before completing the requested task,\nC                  but the integration was successful as far as T.  The\nC                  problem may have a singularity, or the input may be\nC                  inappropriate.\nC              -5  There were repeated convergence-test failures on one\nC                  attempted step, before completing the requested task,\nC                  but the integration was successful as far as T. This\nC                  may be caused by an inaccurate Jacobian matrix, if\nC                  one is being used.\nC              -6  EWT(i) became zero for some i during the integration.\nC                  Pure relative error control (ATOL(i)=0.0) was\nC                  requested on a variable which has now vanished.  The\nC                  integration was successful as far as T.\nC\nC              Note:  Since the normal output value of ISTATE is 2, it\nC              does not need to be reset for normal continuation.  Also,\nC              since a negative input value of ISTATE will be regarded\nC              as illegal, a negative output value requires the user to\nC              change it, and possibly other inputs, before calling the\nC              solver again.\nC\nC     IOPT     An integer flag to specify whether any optional inputs\nC              are being used on this call.  Input only.  The optional\nC              inputs are listed under a separate heading below.\nC              0   No optional inputs are being used.  Default values\nC                  will be used in all cases.\nC              1   One or more optional inputs are being used.\nC\nC     RWORK    A real working array (double precision).  The length of\nC              RWORK must be at least\nC\nC                 20 + NYH*(MAXORD + 1) + 3*NEQ + LWM\nC\nC              where\nC                 NYH = the initial value of NEQ,\nC              MAXORD = 12 (if METH = 1) or 5 (if METH = 2) (unless a\nC                       smaller value is given as an optional input),\nC                 LWM = 0           if MITER = 0,\nC                 LWM = NEQ**2 + 2  if MITER = 1 or 2,\nC                 LWM = NEQ + 2     if MITER = 3, and\nC                 LWM = (2*ML + MU + 1)*NEQ + 2\nC                                   if MITER = 4 or 5.\nC              (See the MF description below for METH and MITER.)\nC\nC              Thus if MAXORD has its default value and NEQ is constant,\nC              this length is:\nC              20 + 16*NEQ                    for MF = 10,\nC              22 + 16*NEQ + NEQ**2           for MF = 11 or 12,\nC              22 + 17*NEQ                    for MF = 13,\nC              22 + 17*NEQ + (2*ML + MU)*NEQ  for MF = 14 or 15,\nC              20 +  9*NEQ                    for MF = 20,\nC              22 +  9*NEQ + NEQ**2           for MF = 21 or 22,\nC              22 + 10*NEQ                    for MF = 23,\nC              22 + 10*NEQ + (2*ML + MU)*NEQ  for MF = 24 or 25.\nC\nC              The first 20 words of RWORK are reserved for conditional\nC              and optional inputs and optional outputs.\nC\nC              The following word in RWORK is a conditional input:\nC              RWORK(1) = TCRIT, the critical value of t which the\nC                         solver is not to overshoot.  Required if ITASK\nC                         is 4 or 5, and ignored otherwise.  See ITASK.\nC\nC     LRW      The length of the array RWORK, as declared by the user.\nC              (This will be checked by the solver.)\nC\nC     IWORK    An integer work array.  Its length must be at least\nC              20       if MITER = 0 or 3 (MF = 10, 13, 20, 23), or\nC              20 + NEQ otherwise (MF = 11, 12, 14, 15, 21, 22, 24, 25).\nC              (See the MF description below for MITER.)  The first few\nC              words of IWORK are used for conditional and optional\nC              inputs and optional outputs.\nC\nC              The following two words in IWORK are conditional inputs:\nC              IWORK(1) = ML   These are the lower and upper half-\nC              IWORK(2) = MU   bandwidths, respectively, of the banded\nC                              Jacobian, excluding the main diagonal.\nC                         The band is defined by the matrix locations\nC                         (i,j) with i - ML <= j <= i + MU. ML and MU\nC                         must satisfy 0 <= ML,MU <= NEQ - 1. These are\nC                         required if MITER is 4 or 5, and ignored\nC                         otherwise.  ML and MU may in fact be the band\nC                         parameters for a matrix to which df/dy is only\nC                         approximately equal.\nC\nC     LIW      The length of the array IWORK, as declared by the user.\nC              (This will be checked by the solver.)\nC\nC     Note:  The work arrays must not be altered between calls to DLSODE\nC     for the same problem, except possibly for the conditional and\nC     optional inputs, and except for the last 3*NEQ words of RWORK.\nC     The latter space is used for internal scratch space, and so is\nC     available for use by the user outside DLSODE between calls, if\nC     desired (but not for use by F or JAC).\nC\nC     JAC      The name of the user-supplied routine (MITER = 1 or 4) to\nC              compute the Jacobian matrix, df/dy, as a function of the\nC              scalar t and the vector y.  (See the MF description below\nC              for MITER.)  It is to have the form\nC\nC                 SUBROUTINE JAC (NEQ, T, Y, ML, MU, PD, NROWPD)\nC                 DOUBLE PRECISION T, Y(*), PD(NROWPD,*)\nC\nC              where NEQ, T, Y, ML, MU, and NROWPD are input and the\nC              array PD is to be loaded with partial derivatives\nC              (elements of the Jacobian matrix) on output.  PD must be\nC              given a first dimension of NROWPD.  T and Y have the same\nC              meaning as in subroutine F.\nC\nC              In the full matrix case (MITER = 1), ML and MU are\nC              ignored, and the Jacobian is to be loaded into PD in\nC              columnwise manner, with df(i)/dy(j) loaded into PD(i,j).\nC\nC              In the band matrix case (MITER = 4), the elements within\nC              the band are to be loaded into PD in columnwise manner,\nC              with diagonal lines of df/dy loaded into the rows of PD.\nC              Thus df(i)/dy(j) is to be loaded into PD(i-j+MU+1,j).  ML\nC              and MU are the half-bandwidth parameters (see IWORK).\nC              The locations in PD in the two triangular areas which\nC              correspond to nonexistent matrix elements can be ignored\nC              or loaded arbitrarily, as they are overwritten by DLSODE.\nC\nC              JAC need not provide df/dy exactly. A crude approximation\nC              (possibly with a smaller bandwidth) will do.\nC\nC              In either case, PD is preset to zero by the solver, so\nC              that only the nonzero elements need be loaded by JAC.\nC              Each call to JAC is preceded by a call to F with the same\nC              arguments NEQ, T, and Y. Thus to gain some efficiency,\nC              intermediate quantities shared by both calculations may\nC              be saved in a user COMMON block by F and not recomputed\nC              by JAC, if desired.  Also, JAC may alter the Y array, if\nC              desired.  JAC must be declared EXTERNAL in the calling\nC              program.\nC\nC              Subroutine JAC may access user-defined quantities in\nC              NEQ(2),... and/or in Y(NEQ(1)+1),... if NEQ is an array\nC              (dimensioned in JAC) and/or Y has length exceeding\nC              NEQ(1).  See the descriptions of NEQ and Y above.\nC\nC     MF       The method flag.  Used only for input.  The legal values\nC              of MF are 10, 11, 12, 13, 14, 15, 20, 21, 22, 23, 24,\nC              and 25.  MF has decimal digits METH and MITER:\nC                 MF = 10*METH + MITER .\nC\nC              METH indicates the basic linear multistep method:\nC              1   Implicit Adams method.\nC              2   Method based on backward differentiation formulas\nC                  (BDF's).\nC\nC              MITER indicates the corrector iteration method:\nC              0   Functional iteration (no Jacobian matrix is\nC                  involved).\nC              1   Chord iteration with a user-supplied full (NEQ by\nC                  NEQ) Jacobian.\nC              2   Chord iteration with an internally generated\nC                  (difference quotient) full Jacobian (using NEQ\nC                  extra calls to F per df/dy value).\nC              3   Chord iteration with an internally generated\nC                  diagonal Jacobian approximation (using one extra call\nC                  to F per df/dy evaluation).\nC              4   Chord iteration with a user-supplied banded Jacobian.\nC              5   Chord iteration with an internally generated banded\nC                  Jacobian (using ML + MU + 1 extra calls to F per\nC                  df/dy evaluation).\nC\nC              If MITER = 1 or 4, the user must supply a subroutine JAC\nC              (the name is arbitrary) as described above under JAC.\nC              For other values of MITER, a dummy argument can be used.\nC\nC     Optional Inputs\nC     ---------------\nC     The following is a list of the optional inputs provided for in the\nC     call sequence.  (See also Part 2.)  For each such input variable,\nC     this table lists its name as used in this documentation, its\nC     location in the call sequence, its meaning, and the default value.\nC     The use of any of these inputs requires IOPT = 1, and in that case\nC     all of these inputs are examined.  A value of zero for any of\nC     these optional inputs will cause the default value to be used.\nC     Thus to use a subset of the optional inputs, simply preload\nC     locations 5 to 10 in RWORK and IWORK to 0.0 and 0 respectively,\nC     and then set those of interest to nonzero values.\nC\nC     Name    Location   Meaning and default value\nC     ------  ---------  -----------------------------------------------\nC     H0      RWORK(5)   Step size to be attempted on the first step.\nC                        The default value is determined by the solver.\nC     HMAX    RWORK(6)   Maximum absolute step size allowed.  The\nC                        default value is infinite.\nC     HMIN    RWORK(7)   Minimum absolute step size allowed.  The\nC                        default value is 0.  (This lower bound is not\nC                        enforced on the final step before reaching\nC                        TCRIT when ITASK = 4 or 5.)\nC     MAXORD  IWORK(5)   Maximum order to be allowed.  The default value\nC                        is 12 if METH = 1, and 5 if METH = 2. (See the\nC                        MF description above for METH.)  If MAXORD\nC                        exceeds the default value, it will be reduced\nC                        to the default value.  If MAXORD is changed\nC                        during the problem, it may cause the current\nC                        order to be reduced.\nC     MXSTEP  IWORK(6)   Maximum number of (internally defined) steps\nC                        allowed during one call to the solver.  The\nC                        default value is 500.\nC     MXHNIL  IWORK(7)   Maximum number of messages printed (per\nC                        problem) warning that T + H = T on a step\nC                        (H = step size).  This must be positive to\nC                        result in a nondefault value.  The default\nC                        value is 10.\nC\nC     Optional Outputs\nC     ----------------\nC     As optional additional output from DLSODE, the variables listed\nC     below are quantities related to the performance of DLSODE which\nC     are available to the user.  These are communicated by way of the\nC     work arrays, but also have internal mnemonic names as shown.\nC     Except where stated otherwise, all of these outputs are defined on\nC     any successful return from DLSODE, and on any return with ISTATE =\nC     -1, -2, -4, -5, or -6.  On an illegal input return (ISTATE = -3),\nC     they will be unchanged from their existing values (if any), except\nC     possibly for TOLSF, LENRW, and LENIW.  On any error return,\nC     outputs relevant to the error will be defined, as noted below.\nC\nC     Name   Location   Meaning\nC     -----  ---------  ------------------------------------------------\nC     HU     RWORK(11)  Step size in t last used (successfully).\nC     HCUR   RWORK(12)  Step size to be attempted on the next step.\nC     TCUR   RWORK(13)  Current value of the independent variable which\nC                       the solver has actually reached, i.e., the\nC                       current internal mesh point in t. On output,\nC                       TCUR will always be at least as far as the\nC                       argument T, but may be farther (if interpolation\nC                       was done).\nC     TOLSF  RWORK(14)  Tolerance scale factor, greater than 1.0,\nC                       computed when a request for too much accuracy\nC                       was detected (ISTATE = -3 if detected at the\nC                       start of the problem, ISTATE = -2 otherwise).\nC                       If ITOL is left unaltered but RTOL and ATOL are\nC                       uniformly scaled up by a factor of TOLSF for the\nC                       next call, then the solver is deemed likely to\nC                       succeed.  (The user may also ignore TOLSF and\nC                       alter the tolerance parameters in any other way\nC                       appropriate.)\nC     NST    IWORK(11)  Number of steps taken for the problem so far.\nC     NFE    IWORK(12)  Number of F evaluations for the problem so far.\nC     NJE    IWORK(13)  Number of Jacobian evaluations (and of matrix LU\nC                       decompositions) for the problem so far.\nC     NQU    IWORK(14)  Method order last used (successfully).\nC     NQCUR  IWORK(15)  Order to be attempted on the next step.\nC     IMXER  IWORK(16)  Index of the component of largest magnitude in\nC                       the weighted local error vector ( e(i)/EWT(i) ),\nC                       on an error return with ISTATE = -4 or -5.\nC     LENRW  IWORK(17)  Length of RWORK actually required.  This is\nC                       defined on normal returns and on an illegal\nC                       input return for insufficient storage.\nC     LENIW  IWORK(18)  Length of IWORK actually required.  This is\nC                       defined on normal returns and on an illegal\nC                       input return for insufficient storage.\nC\nC     The following two arrays are segments of the RWORK array which may\nC     also be of interest to the user as optional outputs.  For each\nC     array, the table below gives its internal name, its base address\nC     in RWORK, and its description.\nC\nC     Name  Base address  Description\nC     ----  ------------  ----------------------------------------------\nC     YH    21            The Nordsieck history array, of size NYH by\nC                         (NQCUR + 1), where NYH is the initial value of\nC                         NEQ.  For j = 0,1,...,NQCUR, column j + 1 of\nC                         YH contains HCUR**j/factorial(j) times the jth\nC                         derivative of the interpolating polynomial\nC                         currently representing the solution, evaluated\nC                         at t = TCUR.\nC     ACOR  LENRW-NEQ+1   Array of size NEQ used for the accumulated\nC                         corrections on each step, scaled on output to\nC                         represent the estimated local error in Y on\nC                         the last step.  This is the vector e in the\nC                         description of the error control.  It is\nC                         defined only on successful return from DLSODE.\nC\nC\nC                    Part 2.  Other Callable Routines\nC                    --------------------------------\nC\nC     The following are optional calls which the user may make to gain\nC     additional capabilities in conjunction with DLSODE.\nC\nC     Form of call              Function\nC     ------------------------  ----------------------------------------\nC     CALL XSETUN(LUN)          Set the logical unit number, LUN, for\nC                               output of messages from DLSODE, if the\nC                               default is not desired.  The default\nC                               value of LUN is 6. This call may be made\nC                               at any time and will take effect\nC                               immediately.\nC     CALL XSETF(MFLAG)         Set a flag to control the printing of\nC                               messages by DLSODE.  MFLAG = 0 means do\nC                               not print.  (Danger:  this risks losing\nC                               valuable information.)  MFLAG = 1 means\nC                               print (the default).  This call may be\nC                               made at any time and will take effect\nC                               immediately.\nC     CALL DSRCOM(RSAV,ISAV,JOB)  Saves and restores the contents of the\nC                               internal COMMON blocks used by DLSODE\nC                               (see Part 3 below).  RSAV must be a\nC                               real array of length 218 or more, and\nC                               ISAV must be an integer array of length\nC                               37 or more.  JOB = 1 means save COMMON\nC                               into RSAV/ISAV.  JOB = 2 means restore\nC                               COMMON from same.  DSRCOM is useful if\nC                               one is interrupting a run and restarting\nC                               later, or alternating between two or\nC                               more problems solved with DLSODE.\nC     CALL DINTDY(,,,,,)        Provide derivatives of y, of various\nC     (see below)               orders, at a specified point t, if\nC                               desired.  It may be called only after a\nC                               successful return from DLSODE.  Detailed\nC                               instructions follow.\nC\nC     Detailed instructions for using DINTDY\nC     --------------------------------------\nC     The form of the CALL is:\nC\nC           CALL DINTDY (T, K, RWORK(21), NYH, DKY, IFLAG)\nC\nC     The input parameters are:\nC\nC     T          Value of independent variable where answers are\nC                desired (normally the same as the T last returned by\nC                DLSODE).  For valid results, T must lie between\nC                TCUR - HU and TCUR.  (See \"Optional Outputs\" above\nC                for TCUR and HU.)\nC     K          Integer order of the derivative desired.  K must\nC                satisfy 0 <= K <= NQCUR, where NQCUR is the current\nC                order (see \"Optional Outputs\").  The capability\nC                corresponding to K = 0, i.e., computing y(t), is\nC                already provided by DLSODE directly.  Since\nC                NQCUR >= 1, the first derivative dy/dt is always\nC                available with DINTDY.\nC     RWORK(21)  The base address of the history array YH.\nC     NYH        Column length of YH, equal to the initial value of NEQ.\nC\nC     The output parameters are:\nC\nC     DKY        Real array of length NEQ containing the computed value\nC                of the Kth derivative of y(t).\nC     IFLAG      Integer flag, returned as 0 if K and T were legal,\nC                -1 if K was illegal, and -2 if T was illegal.\nC                On an error return, a message is also written.\nC\nC\nC                          Part 3.  Common Blocks\nC                          ----------------------\nC\nC     If DLSODE is to be used in an overlay situation, the user must\nC     declare, in the primary overlay, the variables in:\nC     (1) the call sequence to DLSODE,\nC     (2) the internal COMMON block /DLS001/, of length 255\nC         (218 double precision words followed by 37 integer words).\nC\nC     If DLSODE is used on a system in which the contents of internal\nC     COMMON blocks are not preserved between calls, the user should\nC     declare the above COMMON block in his main program to insure that\nC     its contents are preserved.\nC\nC     If the solution of a given problem by DLSODE is to be interrupted\nC     and then later continued, as when restarting an interrupted run or\nC     alternating between two or more problems, the user should save,\nC     following the return from the last DLSODE call prior to the\nC     interruption, the contents of the call sequence variables and the\nC     internal COMMON block, and later restore these values before the\nC     next DLSODE call for that problem.   In addition, if XSETUN and/or\nC     XSETF was called for non-default handling of error messages, then\nC     these calls must be repeated.  To save and restore the COMMON\nC     block, use subroutine DSRCOM (see Part 2 above).\nC\nC\nC              Part 4.  Optionally Replaceable Solver Routines\nC              -----------------------------------------------\nC\nC     Below are descriptions of two routines in the DLSODE package which\nC     relate to the measurement of errors.  Either routine can be\nC     replaced by a user-supplied version, if desired.  However, since\nC     such a replacement may have a major impact on performance, it\nC     should be done only when absolutely necessary, and only with great\nC     caution.  (Note:  The means by which the package version of a\nC     routine is superseded by the user's version may be system-\nC     dependent.)\nC\nC     DEWSET\nC     ------\nC     The following subroutine is called just before each internal\nC     integration step, and sets the array of error weights, EWT, as\nC     described under ITOL/RTOL/ATOL above:\nC\nC           SUBROUTINE DEWSET (NEQ, ITOL, RTOL, ATOL, YCUR, EWT)\nC\nC     where NEQ, ITOL, RTOL, and ATOL are as in the DLSODE call\nC     sequence, YCUR contains the current dependent variable vector,\nC     and EWT is the array of weights set by DEWSET.\nC\nC     If the user supplies this subroutine, it must return in EWT(i)\nC     (i = 1,...,NEQ) a positive quantity suitable for comparing errors\nC     in Y(i) to.  The EWT array returned by DEWSET is passed to the\nC     DVNORM routine (see below), and also used by DLSODE in the\nC     computation of the optional output IMXER, the diagonal Jacobian\nC     approximation, and the increments for difference quotient\nC     Jacobians.\nC\nC     In the user-supplied version of DEWSET, it may be desirable to use\nC     the current values of derivatives of y. Derivatives up to order NQ\nC     are available from the history array YH, described above under\nC     optional outputs.  In DEWSET, YH is identical to the YCUR array,\nC     extended to NQ + 1 columns with a column length of NYH and scale\nC     factors of H**j/factorial(j).  On the first call for the problem,\nC     given by NST = 0, NQ is 1 and H is temporarily set to 1.0.\nC     NYH is the initial value of NEQ.  The quantities NQ, H, and NST\nC     can be obtained by including in SEWSET the statements:\nC           DOUBLE PRECISION RLS\nC           COMMON /DLS001/ RLS(218),ILS(37)\nC           NQ = ILS(33)\nC           NST = ILS(34)\nC           H = RLS(212)\nC     Thus, for example, the current value of dy/dt can be obtained as\nC     YCUR(NYH+i)/H (i=1,...,NEQ) (and the division by H is unnecessary\nC     when NST = 0).\nC\nC     DVNORM\nC     ------\nC     DVNORM is a real function routine which computes the weighted\nC     root-mean-square norm of a vector v:\nC\nC        d = DVNORM (n, v, w)\nC\nC     where:\nC     n = the length of the vector,\nC     v = real array of length n containing the vector,\nC     w = real array of length n containing weights,\nC     d = SQRT( (1/n) * sum(v(i)*w(i))**2 ).\nC\nC     DVNORM is called with n = NEQ and with w(i) = 1.0/EWT(i), where\nC     EWT is as set by subroutine DEWSET.\nC\nC     If the user supplies this function, it should return a nonnegative\nC     value of DVNORM suitable for use in the error control in DLSODE.\nC     None of the arguments should be altered by DVNORM.  For example, a\nC     user-supplied DVNORM routine might:\nC     - Substitute a max-norm of (v(i)*w(i)) for the rms-norm, or\nC     - Ignore some components of v in the norm, with the effect of\nC       suppressing the error control on those components of Y.\nC  ---------------------------------------------------------------------\nC***ROUTINES CALLED  DEWSET, DINTDY, D1MACH, DSTODE, DVNORM, XERRWD\nC***COMMON BLOCKS    DLS001\nC***REVISION HISTORY  (YYYYMMDD)\nC 19791129  DATE WRITTEN\nC 19791213  Minor changes to declarations; DELP init. in STODE.\nC 19800118  Treat NEQ as array; integer declarations added throughout;\nC           minor changes to prologue.\nC 19800306  Corrected TESCO(1,NQP1) setting in CFODE.\nC 19800519  Corrected access of YH on forced order reduction;\nC           numerous corrections to prologues and other comments.\nC 19800617  In main driver, added loading of SQRT(UROUND) in RWORK;\nC           minor corrections to main prologue.\nC 19800923  Added zero initialization of HU and NQU.\nC 19801218  Revised XERRWD routine; minor corrections to main prologue.\nC 19810401  Minor changes to comments and an error message.\nC 19810814  Numerous revisions: replaced EWT by 1/EWT; used flags\nC           JCUR, ICF, IERPJ, IERSL between STODE and subordinates;\nC           added tuning parameters CCMAX, MAXCOR, MSBP, MXNCF;\nC           reorganized returns from STODE; reorganized type decls.;\nC           fixed message length in XERRWD; changed default LUNIT to 6;\nC           changed Common lengths; changed comments throughout.\nC 19870330  Major update by ACH: corrected comments throughout;\nC           removed TRET from Common; rewrote EWSET with 4 loops;\nC           fixed t test in INTDY; added Cray directives in STODE;\nC           in STODE, fixed DELP init. and logic around PJAC call;\nC           combined routines to save/restore Common;\nC           passed LEVEL = 0 in error message calls (except run abort).\nC 19890426  Modified prologue to SLATEC/LDOC format.  (FNF)\nC 19890501  Many improvements to prologue.  (FNF)\nC 19890503  A few final corrections to prologue.  (FNF)\nC 19890504  Minor cosmetic changes.  (FNF)\nC 19890510  Corrected description of Y in Arguments section.  (FNF)\nC 19890517  Minor corrections to prologue.  (FNF)\nC 19920514  Updated with prologue edited 891025 by G. Shaw for manual.\nC 19920515  Converted source lines to upper case.  (FNF)\nC 19920603  Revised XERRWD calls using mixed upper-lower case.  (ACH)\nC 19920616  Revised prologue comment regarding CFT.  (ACH)\nC 19921116  Revised prologue comments regarding Common.  (ACH).\nC 19930326  Added comment about non-reentrancy.  (FNF)\nC 19930723  Changed D1MACH to DUMACH. (FNF)\nC 19930801  Removed ILLIN and NTREP from Common (affects driver logic);\nC           minor changes to prologue and internal comments;\nC           changed Hollerith strings to quoted strings;\nC           changed internal comments to mixed case;\nC           replaced XERRWD with new version using character type;\nC           changed dummy dimensions from 1 to *. (ACH)\nC 19930809  Changed to generic intrinsic names; changed names of\nC           subprograms and Common blocks to DLSODE etc. (ACH)\nC 19930929  Eliminated use of REAL intrinsic; other minor changes. (ACH)\nC 20010412  Removed all 'own' variables from Common block /DLS001/\nC           (affects declarations in 6 routines). (ACH)\nC 20010509  Minor corrections to prologue. (ACH)\nC 20031105  Restored 'own' variables to Common block /DLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC 20031112  Added SAVE statements for data-loaded constants.\nC\nC***END PROLOGUE  DLSODE\nC\nC*Internal Notes:\nC\nC Other Routines in the DLSODE Package.\nC\nC In addition to Subroutine DLSODE, the DLSODE package includes the\nC following subroutines and function routines:\nC  DINTDY   computes an interpolated value of the y vector at t = TOUT.\nC  DSTODE   is the core integrator, which does one step of the\nC           integration and the associated error control.\nC  DCFODE   sets all method coefficients and test constants.\nC  DPREPJ   computes and preprocesses the Jacobian matrix J = df/dy\nC           and the Newton iteration matrix P = I - h*l0*J.\nC  DSOLSY   manages solution of linear system in chord iteration.\nC  DEWSET   sets the error weight vector EWT before each step.\nC  DVNORM   computes the weighted R.M.S. norm of a vector.\nC  DSRCOM   is a user-callable routine to save and restore\nC           the contents of the internal Common block.\nC  DGETRF AND DGETRS   ARE ROUTINES FROM LAPACK FOR SOLVING FULL\nC           SYSTEMS OF LINEAR ALGEBRAIC EQUATIONS.\nC  DGBTRF AND DGBTRS   ARE ROUTINES FROM LAPACK FOR SOLVING BANDED\nC           LINEAR SYSTEMS.\nC  D1MACH   computes the unit roundoff in a machine-independent manner.\nC  XERRWD, XSETUN, XSETF, IXSAV, IUMACH   handle the printing of all\nC           error messages and warnings.  XERRWD is machine-dependent.\nC Note: DVNORM, DUMACH, IXSAV, and IUMACH are function routines.\nC All the others are subroutines.\nC\nC**End\nC\nC  Declare externals.\n      EXTERNAL DPREPJ, DSOLSY\n      DOUBLE PRECISION D1MACH, DVNORM\nC\nC  Declare all other variables.\n      INTEGER ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     1   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, NYH,\n     2   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP\n      INTEGER ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     1   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, I1, I2, IFLAG, IMXER, KGO, LF0,\n     1   LENIW, LENRW, LENWM, ML, MORD, MU, MXHNL0, MXSTP0\n      DOUBLE PRECISION CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      DOUBLE PRECISION ATOLI, AYI, BIG, EWTI, H0, HMAX, HMX, RH, RTOLI,\n     1   TCRIT, TDIST, TNEXT, TOL, TOLSF, TP, SIZE, SUM, W0\n      DIMENSION MORD(2)\n      LOGICAL IHIT\n      CHARACTER*80 MSG\n      SAVE MORD, MXSTP0, MXHNL0\nC-----------------------------------------------------------------------\nC The following internal Common block contains\nC (a) variables which are local to any subroutine but whose values must\nC     be preserved between calls to the routine (\"own\" variables), and\nC (b) variables which are communicated between subroutines.\nC The block DLS001 is declared in subroutines DLSODE, DINTDY, DSTODE,\nC DPREPJ, and DSOLSY.\nC Groups of variables are replaced by dummy arrays in the Common\nC declarations in routines where those variables are not used.\nC-----------------------------------------------------------------------\n      COMMON /DLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     3   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, NYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     4   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\nC\n      DATA  MORD(1),MORD(2)/12,5/, MXSTP0/500/, MXHNL0/10/\nC-----------------------------------------------------------------------\nC Block A.\nC This code block is executed on every call.\nC It tests ISTATE and ITASK for legality and branches appropriately.\nC If ISTATE .GT. 1 but the flag INIT shows that initialization has\nC not yet been done, an error return occurs.\nC If ISTATE = 1 and TOUT = T, return immediately.\nC-----------------------------------------------------------------------\nC\nC***FIRST EXECUTABLE STATEMENT  DLSODE\n      IF (ISTATE .LT. 1 .OR. ISTATE .GT. 3) GO TO 601\n      IF (ITASK .LT. 1 .OR. ITASK .GT. 5) GO TO 602\n      IF (ISTATE .EQ. 1) GO TO 10\n      IF (INIT .EQ. 0) GO TO 603\n      IF (ISTATE .EQ. 2) GO TO 200\n      GO TO 20\n 10   INIT = 0\n      IF (TOUT .EQ. T) RETURN\nC-----------------------------------------------------------------------\nC Block B.\nC The next code block is executed for the initial call (ISTATE = 1),\nC or for a continuation call with parameter changes (ISTATE = 3).\nC It contains checking of all inputs and various initializations.\nC\nC First check legality of the non-optional inputs NEQ, ITOL, IOPT,\nC MF, ML, and MU.\nC-----------------------------------------------------------------------\n 20   IF (NEQ(1) .LE. 0) GO TO 604\n      IF (ISTATE .EQ. 1) GO TO 25\n      IF (NEQ(1) .GT. N) GO TO 605\n 25   N = NEQ(1)\n      IF (ITOL .LT. 1 .OR. ITOL .GT. 4) GO TO 606\n      IF (IOPT .LT. 0 .OR. IOPT .GT. 1) GO TO 607\n      METH = MF/10\n      MITER = MF - 10*METH\n      IF (METH .LT. 1 .OR. METH .GT. 2) GO TO 608\n      IF (MITER .LT. 0 .OR. MITER .GT. 5) GO TO 608\n      IF (MITER .LE. 3) GO TO 30\n      ML = IWORK(1)\n      MU = IWORK(2)\n      IF (ML .LT. 0 .OR. ML .GE. N) GO TO 609\n      IF (MU .LT. 0 .OR. MU .GE. N) GO TO 610\n 30   CONTINUE\nC Next process and check the optional inputs. --------------------------\n      IF (IOPT .EQ. 1) GO TO 40\n      MAXORD = MORD(METH)\n      MXSTEP = MXSTP0\n      MXHNIL = MXHNL0\n      IF (ISTATE .EQ. 1) H0 = 0.0D0\n      HMXI = 0.0D0\n      HMIN = 0.0D0\n      GO TO 60\n 40   MAXORD = IWORK(5)\n      IF (MAXORD .LT. 0) GO TO 611\n      IF (MAXORD .EQ. 0) MAXORD = 100\n      MAXORD = MIN(MAXORD,MORD(METH))\n      MXSTEP = IWORK(6)\n      IF (MXSTEP .LT. 0) GO TO 612\n      IF (MXSTEP .EQ. 0) MXSTEP = MXSTP0\n      MXHNIL = IWORK(7)\n      IF (MXHNIL .LT. 0) GO TO 613\n      IF (MXHNIL .EQ. 0) MXHNIL = MXHNL0\n      IF (ISTATE .NE. 1) GO TO 50\n      H0 = RWORK(5)\n      IF ((TOUT - T)*H0 .LT. 0.0D0) GO TO 614\n 50   HMAX = RWORK(6)\n      IF (HMAX .LT. 0.0D0) GO TO 615\n      HMXI = 0.0D0\n      IF (HMAX .GT. 0.0D0) HMXI = 1.0D0/HMAX\n      HMIN = RWORK(7)\n      IF (HMIN .LT. 0.0D0) GO TO 616\nC-----------------------------------------------------------------------\nC Set work array pointers and check lengths LRW and LIW.\nC Pointers to segments of RWORK and IWORK are named by prefixing L to\nC the name of the segment.  E.g., the segment YH starts at RWORK(LYH).\nC Segments of RWORK (in order) are denoted  YH, WM, EWT, SAVF, ACOR.\nC-----------------------------------------------------------------------\n 60   LYH = 21\n      IF (ISTATE .EQ. 1) NYH = N\n      LWM = LYH + (MAXORD + 1)*NYH\n      IF (MITER .EQ. 0) LENWM = 0\n      IF (MITER .EQ. 1 .OR. MITER .EQ. 2) LENWM = N*N + 2\n      IF (MITER .EQ. 3) LENWM = N + 2\n      IF (MITER .GE. 4) LENWM = (2*ML + MU + 1)*N + 2\n      LEWT = LWM + LENWM\n      LSAVF = LEWT + N\n      LACOR = LSAVF + N\n      LENRW = LACOR + N - 1\n      IWORK(17) = LENRW\n      LIWM = 1\n      LENIW = 20 + N\n      IF (MITER .EQ. 0 .OR. MITER .EQ. 3) LENIW = 20\n      IWORK(18) = LENIW\n      IF (LENRW .GT. LRW) GO TO 617\n      IF (LENIW .GT. LIW) GO TO 618\nC Check RTOL and ATOL for legality. ------------------------------------\n      RTOLI = RTOL(1)\n      ATOLI = ATOL(1)\n      DO 70 I = 1,N\n        IF (ITOL .GE. 3) RTOLI = RTOL(I)\n        IF (ITOL .EQ. 2 .OR. ITOL .EQ. 4) ATOLI = ATOL(I)\n        IF (RTOLI .LT. 0.0D0) GO TO 619\n        IF (ATOLI .LT. 0.0D0) GO TO 620\n 70     CONTINUE\n      IF (ISTATE .EQ. 1) GO TO 100\nC If ISTATE = 3, set flag to signal parameter changes to DSTODE. -------\n      JSTART = -1\n      IF (NQ .LE. MAXORD) GO TO 90\nC MAXORD was reduced below NQ.  Copy YH(*,MAXORD+2) into SAVF. ---------\n      DO 80 I = 1,N\n 80     RWORK(I+LSAVF-1) = RWORK(I+LWM-1)\nC Reload WM(1) = RWORK(LWM), since LWM may have changed. ---------------\n 90   IF (MITER .GT. 0) RWORK(LWM) = SQRT(UROUND)\n      IF (N .EQ. NYH) GO TO 200\nC NEQ was reduced.  Zero part of YH to avoid undefined references. -----\n      I1 = LYH + L*NYH\n      I2 = LYH + (MAXORD + 1)*NYH - 1\n      IF (I1 .GT. I2) GO TO 200\n      DO 95 I = I1,I2\n 95     RWORK(I) = 0.0D0\n      GO TO 200\nC-----------------------------------------------------------------------\nC Block C.\nC The next block is for the initial call only (ISTATE = 1).\nC It contains all remaining initializations, the initial call to F,\nC and the calculation of the initial step size.\nC The error weights in EWT are inverted after being loaded.\nC-----------------------------------------------------------------------\n 100  UROUND = D1MACH(4)\n      TN = T\n      IF (ITASK .NE. 4 .AND. ITASK .NE. 5) GO TO 110\n      TCRIT = RWORK(1)\n      IF ((TCRIT - TOUT)*(TOUT - T) .LT. 0.0D0) GO TO 625\n      IF (H0 .NE. 0.0D0 .AND. (T + H0 - TCRIT)*H0 .GT. 0.0D0)\n     1   H0 = TCRIT - T\n 110  JSTART = 0\n      IF (MITER .GT. 0) RWORK(LWM) = SQRT(UROUND)\n      NHNIL = 0\n      NST = 0\n      NJE = 0\n      NSLAST = 0\n      HU = 0.0D0\n      NQU = 0\n      CCMAX = 0.3D0\n      MAXCOR = 3\n      MSBP = 20\n      MXNCF = 10\nC Initial call to F.  (LF0 points to YH(*,2).) -------------------------\n      LF0 = LYH + NYH\n      CALL F (NEQ, T, Y, RWORK(LF0))\n      NFE = 1\nC Load the initial value vector in YH. ---------------------------------\n      DO 115 I = 1,N\n 115    RWORK(I+LYH-1) = Y(I)\nC Load and invert the EWT array.  (H is temporarily set to 1.0.) -------\n      NQ = 1\n      H = 1.0D0\n      CALL DEWSET (N, ITOL, RTOL, ATOL, RWORK(LYH), RWORK(LEWT))\n      DO 120 I = 1,N\n        IF (RWORK(I+LEWT-1) .LE. 0.0D0) GO TO 621\n 120    RWORK(I+LEWT-1) = 1.0D0/RWORK(I+LEWT-1)\nC-----------------------------------------------------------------------\nC The coding below computes the step size, H0, to be attempted on the\nC first step, unless the user has supplied a value for this.\nC First check that TOUT - T differs significantly from zero.\nC A scalar tolerance quantity TOL is computed, as MAX(RTOL(I))\nC if this is positive, or MAX(ATOL(I)/ABS(Y(I))) otherwise, adjusted\nC so as to be between 100*UROUND and 1.0E-3.\nC Then the computed value H0 is given by..\nC                                      NEQ\nC   H0**2 = TOL / ( w0**-2 + (1/NEQ) * SUM ( f(i)/ywt(i) )**2  )\nC                                       1\nC where   w0     = MAX ( ABS(T), ABS(TOUT) ),\nC         f(i)   = i-th component of initial value of f,\nC         ywt(i) = EWT(i)/TOL  (a weight for y(i)).\nC The sign of H0 is inferred from the initial values of TOUT and T.\nC-----------------------------------------------------------------------\n      IF (H0 .NE. 0.0D0) GO TO 180\n      TDIST = ABS(TOUT - T)\n      W0 = MAX(ABS(T),ABS(TOUT))\n      IF (TDIST .LT. 2.0D0*UROUND*W0) GO TO 622\n      TOL = RTOL(1)\n      IF (ITOL .LE. 2) GO TO 140\n      DO 130 I = 1,N\n 130    TOL = MAX(TOL,RTOL(I))\n 140  IF (TOL .GT. 0.0D0) GO TO 160\n      ATOLI = ATOL(1)\n      DO 150 I = 1,N\n        IF (ITOL .EQ. 2 .OR. ITOL .EQ. 4) ATOLI = ATOL(I)\n        AYI = ABS(Y(I))\n        IF (AYI .NE. 0.0D0) TOL = MAX(TOL,ATOLI/AYI)\n 150    CONTINUE\n 160  TOL = MAX(TOL,100.0D0*UROUND)\n      TOL = MIN(TOL,0.001D0)\n      SUM = DVNORM (N, RWORK(LF0), RWORK(LEWT))\n      SUM = 1.0D0/(TOL*W0*W0) + TOL*SUM**2\n      H0 = 1.0D0/SQRT(SUM)\n      H0 = MIN(H0,TDIST)\n      H0 = SIGN(H0,TOUT-T)\nC Adjust H0 if necessary to meet HMAX bound. ---------------------------\n 180  RH = ABS(H0)*HMXI\n      IF (RH .GT. 1.0D0) H0 = H0/RH\nC Load H with H0 and scale YH(*,2) by H0. ------------------------------\n      H = H0\n      DO 190 I = 1,N\n 190    RWORK(I+LF0-1) = H0*RWORK(I+LF0-1)\n      GO TO 270\nC-----------------------------------------------------------------------\nC Block D.\nC The next code block is for continuation calls only (ISTATE = 2 or 3)\nC and is to check stop conditions before taking a step.\nC-----------------------------------------------------------------------\n 200  NSLAST = NST\n      GO TO (210, 250, 220, 230, 240), ITASK\n 210  IF ((TN - TOUT)*H .LT. 0.0D0) GO TO 250\n      CALL DINTDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG)\n      IF (IFLAG .NE. 0) GO TO 627\n      T = TOUT\n      GO TO 420\n 220  TP = TN - HU*(1.0D0 + 100.0D0*UROUND)\n      IF ((TP - TOUT)*H .GT. 0.0D0) GO TO 623\n      IF ((TN - TOUT)*H .LT. 0.0D0) GO TO 250\n      GO TO 400\n 230  TCRIT = RWORK(1)\n      IF ((TN - TCRIT)*H .GT. 0.0D0) GO TO 624\n      IF ((TCRIT - TOUT)*H .LT. 0.0D0) GO TO 625\n      IF ((TN - TOUT)*H .LT. 0.0D0) GO TO 245\n      CALL DINTDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG)\n      IF (IFLAG .NE. 0) GO TO 627\n      T = TOUT\n      GO TO 420\n 240  TCRIT = RWORK(1)\n      IF ((TN - TCRIT)*H .GT. 0.0D0) GO TO 624\n 245  HMX = ABS(TN) + ABS(H)\n      IHIT = ABS(TN - TCRIT) .LE. 100.0D0*UROUND*HMX\n      IF (IHIT) GO TO 400\n      TNEXT = TN + H*(1.0D0 + 4.0D0*UROUND)\n      IF ((TNEXT - TCRIT)*H .LE. 0.0D0) GO TO 250\n      H = (TCRIT - TN)*(1.0D0 - 4.0D0*UROUND)\n      IF (ISTATE .EQ. 2) JSTART = -2\nC-----------------------------------------------------------------------\nC Block E.\nC The next block is normally executed for all calls and contains\nC the call to the one-step core integrator DSTODE.\nC\nC This is a looping point for the integration steps.\nC\nC First check for too many steps being taken, update EWT (if not at\nC start of problem), check for too much accuracy being requested, and\nC check for H below the roundoff level in T.\nC-----------------------------------------------------------------------\n 250  CONTINUE\n      IF ((NST-NSLAST) .GE. MXSTEP) GO TO 500\n      CALL DEWSET (N, ITOL, RTOL, ATOL, RWORK(LYH), RWORK(LEWT))\n      DO 260 I = 1,N\n        IF (RWORK(I+LEWT-1) .LE. 0.0D0) GO TO 510\n 260    RWORK(I+LEWT-1) = 1.0D0/RWORK(I+LEWT-1)\n 270  TOLSF = UROUND*DVNORM (N, RWORK(LYH), RWORK(LEWT))\n      IF (TOLSF .LE. 1.0D0) GO TO 280\n      TOLSF = TOLSF*2.0D0\n      IF (NST .EQ. 0) GO TO 626\n      GO TO 520\n 280  IF ((TN + H) .NE. TN) GO TO 290\n      NHNIL = NHNIL + 1\n      IF (NHNIL .GT. MXHNIL) GO TO 290\n      MSG = 'DLSODE-  Warning..internal T (=R1) and H (=R2) are'\n      CALL XERRWD (MSG, 50, 101, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      MSG='      such that in the machine, T + H = T on the next step  '\n      CALL XERRWD (MSG, 60, 101, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      MSG = '      (H = step size). Solver will continue anyway'\n      CALL XERRWD (MSG, 50, 101, 0, 0, 0, 0, 2, TN, H)\n      IF (NHNIL .LT. MXHNIL) GO TO 290\n      MSG = 'DLSODE-  Above warning has been issued I1 times.  '\n      CALL XERRWD (MSG, 50, 102, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      MSG = '      It will not be issued again for this problem'\n      CALL XERRWD (MSG, 50, 102, 0, 1, MXHNIL, 0, 0, 0.0D0, 0.0D0)\n 290  CONTINUE\nC-----------------------------------------------------------------------\nC  CALL DSTODE(NEQ,Y,YH,NYH,YH,EWT,SAVF,ACOR,WM,IWM,F,JAC,DPREPJ,DSOLSY)\nC-----------------------------------------------------------------------\n      CALL DSTODE (NEQ, Y, RWORK(LYH), NYH, RWORK(LYH), RWORK(LEWT),\n     1   RWORK(LSAVF), RWORK(LACOR), RWORK(LWM), IWORK(LIWM),\n     2   F, JAC, DPREPJ, DSOLSY)\n      KGO = 1 - KFLAG\n      GO TO (300, 530, 540), KGO\nC-----------------------------------------------------------------------\nC Block F.\nC The following block handles the case of a successful return from the\nC core integrator (KFLAG = 0).  Test for stop conditions.\nC-----------------------------------------------------------------------\n 300  INIT = 1\n      GO TO (310, 400, 330, 340, 350), ITASK\nC ITASK = 1.  If TOUT has been reached, interpolate. -------------------\n 310  IF ((TN - TOUT)*H .LT. 0.0D0) GO TO 250\n      CALL DINTDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG)\n      T = TOUT\n      GO TO 420\nC ITASK = 3.  Jump to exit if TOUT was reached. ------------------------\n 330  IF ((TN - TOUT)*H .GE. 0.0D0) GO TO 400\n      GO TO 250\nC ITASK = 4.  See if TOUT or TCRIT was reached.  Adjust H if necessary.\n 340  IF ((TN - TOUT)*H .LT. 0.0D0) GO TO 345\n      CALL DINTDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG)\n      T = TOUT\n      GO TO 420\n 345  HMX = ABS(TN) + ABS(H)\n      IHIT = ABS(TN - TCRIT) .LE. 100.0D0*UROUND*HMX\n      IF (IHIT) GO TO 400\n      TNEXT = TN + H*(1.0D0 + 4.0D0*UROUND)\n      IF ((TNEXT - TCRIT)*H .LE. 0.0D0) GO TO 250\n      H = (TCRIT - TN)*(1.0D0 - 4.0D0*UROUND)\n      JSTART = -2\n      GO TO 250\nC ITASK = 5.  See if TCRIT was reached and jump to exit. ---------------\n 350  HMX = ABS(TN) + ABS(H)\n      IHIT = ABS(TN - TCRIT) .LE. 100.0D0*UROUND*HMX\nC-----------------------------------------------------------------------\nC Block G.\nC The following block handles all successful returns from DLSODE.\nC If ITASK .NE. 1, Y is loaded from YH and T is set accordingly.\nC ISTATE is set to 2, and the optional outputs are loaded into the\nC work arrays before returning.\nC-----------------------------------------------------------------------\n 400  DO 410 I = 1,N\n 410    Y(I) = RWORK(I+LYH-1)\n      T = TN\n      IF (ITASK .NE. 4 .AND. ITASK .NE. 5) GO TO 420\n      IF (IHIT) T = TCRIT\n 420  ISTATE = 2\n      RWORK(11) = HU\n      RWORK(12) = H\n      RWORK(13) = TN\n      IWORK(11) = NST\n      IWORK(12) = NFE\n      IWORK(13) = NJE\n      IWORK(14) = NQU\n      IWORK(15) = NQ\n      RETURN\nC-----------------------------------------------------------------------\nC Block H.\nC The following block handles all unsuccessful returns other than\nC those for illegal input.  First the error message routine is called.\nC If there was an error test or convergence test failure, IMXER is set.\nC Then Y is loaded from YH and T is set to TN.  The optional outputs\nC are loaded into the work arrays before returning.\nC-----------------------------------------------------------------------\nC The maximum number of steps was taken before reaching TOUT. ----------\n 500  MSG = 'DLSODE-  At current T (=R1), MXSTEP (=I1) steps   '\n      CALL XERRWD (MSG, 50, 201, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      MSG = '      taken on this call before reaching TOUT     '\n      CALL XERRWD (MSG, 50, 201, 0, 1, MXSTEP, 0, 1, TN, 0.0D0)\n      ISTATE = -1\n      GO TO 580\nC EWT(I) .LE. 0.0 for some I (not at start of problem). ----------------\n 510  EWTI = RWORK(LEWT+I-1)\n      MSG = 'DLSODE-  At T (=R1), EWT(I1) has become R2 .LE. 0.'\n      CALL XERRWD (MSG, 50, 202, 0, 1, I, 0, 2, TN, EWTI)\n      ISTATE = -6\n      GO TO 580\nC Too much accuracy requested for machine precision. -------------------\n 520  MSG = 'DLSODE-  At T (=R1), too much accuracy requested  '\n      CALL XERRWD (MSG, 50, 203, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      MSG = '      for precision of machine..  see TOLSF (=R2) '\n      CALL XERRWD (MSG, 50, 203, 0, 0, 0, 0, 2, TN, TOLSF)\n      RWORK(14) = TOLSF\n      ISTATE = -2\n      GO TO 580\nC KFLAG = -1.  Error test failed repeatedly or with ABS(H) = HMIN. -----\n 530  MSG = 'DLSODE-  At T(=R1) and step size H(=R2), the error'\n      CALL XERRWD (MSG, 50, 204, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      MSG = '      test failed repeatedly or with ABS(H) = HMIN'\n      CALL XERRWD (MSG, 50, 204, 0, 0, 0, 0, 2, TN, H)\n      ISTATE = -4\n      GO TO 560\nC KFLAG = -2.  Convergence failed repeatedly or with ABS(H) = HMIN. ----\n 540  MSG = 'DLSODE-  At T (=R1) and step size H (=R2), the    '\n      CALL XERRWD (MSG, 50, 205, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      MSG = '      corrector convergence failed repeatedly     '\n      CALL XERRWD (MSG, 50, 205, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      MSG = '      or with ABS(H) = HMIN   '\n      CALL XERRWD (MSG, 30, 205, 0, 0, 0, 0, 2, TN, H)\n      ISTATE = -5\nC Compute IMXER if relevant. -------------------------------------------\n 560  BIG = 0.0D0\n      IMXER = 1\n      DO 570 I = 1,N\n        SIZE = ABS(RWORK(I+LACOR-1)*RWORK(I+LEWT-1))\n        IF (BIG .GE. SIZE) GO TO 570\n        BIG = SIZE\n        IMXER = I\n 570    CONTINUE\n      IWORK(16) = IMXER\nC Set Y vector, T, and optional outputs. -------------------------------\n 580  DO 590 I = 1,N\n 590    Y(I) = RWORK(I+LYH-1)\n      T = TN\n      RWORK(11) = HU\n      RWORK(12) = H\n      RWORK(13) = TN\n      IWORK(11) = NST\n      IWORK(12) = NFE\n      IWORK(13) = NJE\n      IWORK(14) = NQU\n      IWORK(15) = NQ\n      RETURN\nC-----------------------------------------------------------------------\nC Block I.\nC The following block handles all error returns due to illegal input\nC (ISTATE = -3), as detected before calling the core integrator.\nC First the error message routine is called.  If the illegal input\nC is a negative ISTATE, the run is aborted (apparent infinite loop).\nC-----------------------------------------------------------------------\n 601  MSG = 'DLSODE-  ISTATE (=I1) illegal '\n      CALL XERRWD (MSG, 30, 1, 0, 1, ISTATE, 0, 0, 0.0D0, 0.0D0)\n      IF (ISTATE .LT. 0) GO TO 800\n      GO TO 700\n 602  MSG = 'DLSODE-  ITASK (=I1) illegal  '\n      CALL XERRWD (MSG, 30, 2, 0, 1, ITASK, 0, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 603  MSG = 'DLSODE-  ISTATE .GT. 1 but DLSODE not initialized '\n      CALL XERRWD (MSG, 50, 3, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 604  MSG = 'DLSODE-  NEQ (=I1) .LT. 1     '\n      CALL XERRWD (MSG, 30, 4, 0, 1, NEQ(1), 0, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 605  MSG = 'DLSODE-  ISTATE = 3 and NEQ increased (I1 to I2)  '\n      CALL XERRWD (MSG, 50, 5, 0, 2, N, NEQ(1), 0, 0.0D0, 0.0D0)\n      GO TO 700\n 606  MSG = 'DLSODE-  ITOL (=I1) illegal   '\n      CALL XERRWD (MSG, 30, 6, 0, 1, ITOL, 0, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 607  MSG = 'DLSODE-  IOPT (=I1) illegal   '\n      CALL XERRWD (MSG, 30, 7, 0, 1, IOPT, 0, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 608  MSG = 'DLSODE-  MF (=I1) illegal     '\n      CALL XERRWD (MSG, 30, 8, 0, 1, MF, 0, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 609  MSG = 'DLSODE-  ML (=I1) illegal.. .LT.0 or .GE.NEQ (=I2)'\n      CALL XERRWD (MSG, 50, 9, 0, 2, ML, NEQ(1), 0, 0.0D0, 0.0D0)\n      GO TO 700\n 610  MSG = 'DLSODE-  MU (=I1) illegal.. .LT.0 or .GE.NEQ (=I2)'\n      CALL XERRWD (MSG, 50, 10, 0, 2, MU, NEQ(1), 0, 0.0D0, 0.0D0)\n      GO TO 700\n 611  MSG = 'DLSODE-  MAXORD (=I1) .LT. 0  '\n      CALL XERRWD (MSG, 30, 11, 0, 1, MAXORD, 0, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 612  MSG = 'DLSODE-  MXSTEP (=I1) .LT. 0  '\n      CALL XERRWD (MSG, 30, 12, 0, 1, MXSTEP, 0, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 613  MSG = 'DLSODE-  MXHNIL (=I1) .LT. 0  '\n      CALL XERRWD (MSG, 30, 13, 0, 1, MXHNIL, 0, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 614  MSG = 'DLSODE-  TOUT (=R1) behind T (=R2)      '\n      CALL XERRWD (MSG, 40, 14, 0, 0, 0, 0, 2, TOUT, T)\n      MSG = '      Integration direction is given by H0 (=R1)  '\n      CALL XERRWD (MSG, 50, 14, 0, 0, 0, 0, 1, H0, 0.0D0)\n      GO TO 700\n 615  MSG = 'DLSODE-  HMAX (=R1) .LT. 0.0  '\n      CALL XERRWD (MSG, 30, 15, 0, 0, 0, 0, 1, HMAX, 0.0D0)\n      GO TO 700\n 616  MSG = 'DLSODE-  HMIN (=R1) .LT. 0.0  '\n      CALL XERRWD (MSG, 30, 16, 0, 0, 0, 0, 1, HMIN, 0.0D0)\n      GO TO 700\n 617  CONTINUE\n      MSG='DLSODE-  RWORK length needed, LENRW (=I1), exceeds LRW (=I2)'\n      CALL XERRWD (MSG, 60, 17, 0, 2, LENRW, LRW, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 618  CONTINUE\n      MSG='DLSODE-  IWORK length needed, LENIW (=I1), exceeds LIW (=I2)'\n      CALL XERRWD (MSG, 60, 18, 0, 2, LENIW, LIW, 0, 0.0D0, 0.0D0)\n      GO TO 700\n 619  MSG = 'DLSODE-  RTOL(I1) is R1 .LT. 0.0        '\n      CALL XERRWD (MSG, 40, 19, 0, 1, I, 0, 1, RTOLI, 0.0D0)\n      GO TO 700\n 620  MSG = 'DLSODE-  ATOL(I1) is R1 .LT. 0.0        '\n      CALL XERRWD (MSG, 40, 20, 0, 1, I, 0, 1, ATOLI, 0.0D0)\n      GO TO 700\n 621  EWTI = RWORK(LEWT+I-1)\n      MSG = 'DLSODE-  EWT(I1) is R1 .LE. 0.0         '\n      CALL XERRWD (MSG, 40, 21, 0, 1, I, 0, 1, EWTI, 0.0D0)\n      GO TO 700\n 622  CONTINUE\n      MSG='DLSODE-  TOUT (=R1) too close to T(=R2) to start integration'\n      CALL XERRWD (MSG, 60, 22, 0, 0, 0, 0, 2, TOUT, T)\n      GO TO 700\n 623  CONTINUE\n      MSG='DLSODE-  ITASK = I1 and TOUT (=R1) behind TCUR - HU (= R2)  '\n      CALL XERRWD (MSG, 60, 23, 0, 1, ITASK, 0, 2, TOUT, TP)\n      GO TO 700\n 624  CONTINUE\n      MSG='DLSODE-  ITASK = 4 OR 5 and TCRIT (=R1) behind TCUR (=R2)   '\n      CALL XERRWD (MSG, 60, 24, 0, 0, 0, 0, 2, TCRIT, TN)\n      GO TO 700\n 625  CONTINUE\n      MSG='DLSODE-  ITASK = 4 or 5 and TCRIT (=R1) behind TOUT (=R2)   '\n      CALL XERRWD (MSG, 60, 25, 0, 0, 0, 0, 2, TCRIT, TOUT)\n      GO TO 700\n 626  MSG = 'DLSODE-  At start of problem, too much accuracy   '\n      CALL XERRWD (MSG, 50, 26, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      MSG='      requested for precision of machine..  See TOLSF (=R1) '\n      CALL XERRWD (MSG, 60, 26, 0, 0, 0, 0, 1, TOLSF, 0.0D0)\n      RWORK(14) = TOLSF\n      GO TO 700\n 627  MSG = 'DLSODE-  Trouble in DINTDY.  ITASK = I1, TOUT = R1'\n      CALL XERRWD (MSG, 50, 27, 0, 1, ITASK, 0, 1, TOUT, 0.0D0)\nC\n 700  ISTATE = -3\n      RETURN\nC\n 800  MSG = 'DLSODE-  Run aborted.. apparent infinite loop     '\n      CALL XERRWD (MSG, 50, 303, 2, 0, 0, 0, 0, 0.0D0, 0.0D0)\n      RETURN\nC----------------------- END OF SUBROUTINE DLSODE ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/dprepj.f",
    "content": "      SUBROUTINE DPREPJ (NEQ, Y, YH, NYH, EWT, FTEM, SAVF, WM, IWM,\n     1   F, JAC)\nC***BEGIN PROLOGUE  DPREPJ\nC***SUBSIDIARY\nC***PURPOSE  Compute and process Newton iteration matrix.\nC***TYPE      DOUBLE PRECISION (SPREPJ-S, DPREPJ-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  DPREPJ is called by DSTODE to compute and process the matrix\nC  P = I - h*el(1)*J , where J is an approximation to the Jacobian.\nC  Here J is computed by the user-supplied routine JAC if\nC  MITER = 1 or 4, or by finite differencing if MITER = 2, 3, or 5.\nC  If MITER = 3, a diagonal approximation to J is used.\nC  J is stored in WM and replaced by P.  If MITER .ne. 3, P is then\nC  subjected to LU decomposition in preparation for later solution\nC  of linear systems with P as coefficient matrix.  This is done\nC  by DGETRF if MITER = 1 or 2, and by DGBTRF if MITER = 4 or 5.\nC\nC  In addition to variables described in DSTODE and DLSODE prologues,\nC  communication with DPREPJ uses the following:\nC  Y     = array containing predicted values on entry.\nC  FTEM  = work array of length N (ACOR in DSTODE).\nC  SAVF  = array containing f evaluated at predicted y.\nC  WM    = real work space for matrices.  On output it contains the\nC          inverse diagonal matrix if MITER = 3 and the LU decomposition\nC          of P if MITER is 1, 2 , 4, or 5.\nC          Storage of matrix elements starts at WM(3).\nC          WM also contains the following matrix-related data:\nC          WM(1) = SQRT(UROUND), used in numerical Jacobian increments.\nC          WM(2) = H*EL0, saved for later use if MITER = 3.\nC  IWM   = integer work space containing pivot information, starting at\nC          IWM(21), if MITER is 1, 2, 4, or 5.  IWM also contains band\nC          parameters ML = IWM(1) and MU = IWM(2) if MITER is 4 or 5.\nC  EL0   = EL(1) (input).\nC  IERPJ = output error flag,  = 0 if no trouble, .gt. 0 if\nC          P matrix found to be singular.\nC  JCUR  = output flag = 1 to indicate that the Jacobian matrix\nC          (or approximation) is now current.\nC  This routine also uses the COMMON variables EL0, H, TN, UROUND,\nC  MITER, N, NFE, and NJE.\nC\nC***SEE ALSO  DLSODE\nC***ROUTINES CALLED  DGBTRF, DGETRF, DVNORM\nC***COMMON BLOCKS    DLS001\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890504  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC   010418  Reduced size of Common block /DLS001/. (ACH)\nC   031105  Restored 'own' variables to Common block /DLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC***END PROLOGUE  DPREPJ\nC**End\n      EXTERNAL F, JAC\n      INTEGER NEQ, NYH, IWM\n      DOUBLE PRECISION Y, YH, EWT, FTEM, SAVF, WM\n      DIMENSION NEQ(*), Y(*), YH(NYH,*), EWT(*), FTEM(*), SAVF(*),\n     1   WM(*), IWM(*)\n      INTEGER ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     2   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     1   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, CNYH,\n     2   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP\n      DOUBLE PRECISION CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      COMMON /DLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     2   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     3   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, CNYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     4   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, I1, I2, IER, II, J, J1, JJ, LENP,\n     1   MBA, MBAND, MEB1, MEBAND, ML, ML3, MU, NP1\n      DOUBLE PRECISION CON, DI, FAC, HL0, R, R0, SRUR, YI, YJ, YJJ,\n     1   DVNORM\nC\nC***FIRST EXECUTABLE STATEMENT  DPREPJ\n      NJE = NJE + 1\n      IERPJ = 0\n      JCUR = 1\n      HL0 = H*EL0\n      GO TO (100, 200, 300, 400, 500), MITER\nC If MITER = 1, call JAC and multiply by scalar. -----------------------\n 100  LENP = N*N\n      DO 110 I = 1,LENP\n 110    WM(I+2) = 0.0D0\n      CALL JAC (NEQ, TN, Y, 0, 0, WM(3), N)\n      CON = -HL0\n      DO 120 I = 1,LENP\n 120    WM(I+2) = WM(I+2)*CON\n      GO TO 240\nC If MITER = 2, make N calls to F to approximate J. --------------------\n 200  FAC = DVNORM (N, SAVF, EWT)\n      R0 = 1000.0D0*ABS(H)*UROUND*N*FAC\n      IF (R0 .EQ. 0.0D0) R0 = 1.0D0\n      SRUR = WM(1)\n      J1 = 2\n      DO 230 J = 1,N\n        YJ = Y(J)\n        R = MAX(SRUR*ABS(YJ),R0/EWT(J))\n        Y(J) = Y(J) + R\n        FAC = -HL0/R\n        CALL F (NEQ, TN, Y, FTEM)\n        DO 220 I = 1,N\n 220      WM(I+J1) = (FTEM(I) - SAVF(I))*FAC\n        Y(J) = YJ\n        J1 = J1 + N\n 230    CONTINUE\n      NFE = NFE + N\nC Add identity matrix. -------------------------------------------------\n 240  J = 3\n      NP1 = N + 1\n      DO 250 I = 1,N\n        WM(J) = WM(J) + 1.0D0\n 250    J = J + NP1\nC Do LU decomposition on P. --------------------------------------------\n      CALL DGETRF ( N, N, WM(3), N, IWM(21), IER)\n      IF (IER .NE. 0) IERPJ = 1\n      RETURN\nC If MITER = 3, construct a diagonal approximation to J and P. ---------\n 300  WM(2) = HL0\n      R = EL0*0.1D0\n      DO 310 I = 1,N\n 310    Y(I) = Y(I) + R*(H*SAVF(I) - YH(I,2))\n      CALL F (NEQ, TN, Y, WM(3))\n      NFE = NFE + 1\n      DO 320 I = 1,N\n        R0 = H*SAVF(I) - YH(I,2)\n        DI = 0.1D0*R0 - H*(WM(I+2) - SAVF(I))\n        WM(I+2) = 1.0D0\n        IF (ABS(R0) .LT. UROUND/EWT(I)) GO TO 320\n        IF (ABS(DI) .EQ. 0.0D0) GO TO 330\n        WM(I+2) = 0.1D0*R0/DI\n 320    CONTINUE\n      RETURN\n 330  IERPJ = 1\n      RETURN\nC If MITER = 4, call JAC and multiply by scalar. -----------------------\n 400  ML = IWM(1)\n      MU = IWM(2)\n      ML3 = ML + 3\n      MBAND = ML + MU + 1\n      MEBAND = MBAND + ML\n      LENP = MEBAND*N\n      DO 410 I = 1,LENP\n 410    WM(I+2) = 0.0D0\n      CALL JAC (NEQ, TN, Y, ML, MU, WM(ML3), MEBAND)\n      CON = -HL0\n      DO 420 I = 1,LENP\n 420    WM(I+2) = WM(I+2)*CON\n      GO TO 570\nC If MITER = 5, make MBAND calls to F to approximate J. ----------------\n 500  ML = IWM(1)\n      MU = IWM(2)\n      MBAND = ML + MU + 1\n      MBA = MIN(MBAND,N)\n      MEBAND = MBAND + ML\n      MEB1 = MEBAND - 1\n      SRUR = WM(1)\n      FAC = DVNORM (N, SAVF, EWT)\n      R0 = 1000.0D0*ABS(H)*UROUND*N*FAC\n      IF (R0 .EQ. 0.0D0) R0 = 1.0D0\n      DO 560 J = 1,MBA\n        DO 530 I = J,N,MBAND\n          YI = Y(I)\n          R = MAX(SRUR*ABS(YI),R0/EWT(I))\n 530      Y(I) = Y(I) + R\n        CALL F (NEQ, TN, Y, FTEM)\n        DO 550 JJ = J,N,MBAND\n          Y(JJ) = YH(JJ,1)\n          YJJ = Y(JJ)\n          R = MAX(SRUR*ABS(YJJ),R0/EWT(JJ))\n          FAC = -HL0/R\n          I1 = MAX(JJ-MU,1)\n          I2 = MIN(JJ+ML,N)\n          II = JJ*MEB1 - ML + 2\n          DO 540 I = I1,I2\n 540        WM(II+I) = (FTEM(I) - SAVF(I))*FAC\n 550      CONTINUE\n 560    CONTINUE\n      NFE = NFE + MBA\nC Add identity matrix. -------------------------------------------------\n 570  II = MBAND + 2\n      DO 580 I = 1,N\n        WM(II) = WM(II) + 1.0D0\n 580    II = II + MEBAND\nC Do LU decomposition of P. --------------------------------------------\n      CALL DGBTRF ( N, N, ML, MU, WM(3), MEBAND, IWM(21), IER)\n      IF (IER .NE. 0) IERPJ = 1\n      RETURN\nC----------------------- END OF SUBROUTINE DPREPJ ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/dsolsy.f",
    "content": "      SUBROUTINE DSOLSY (WM, IWM, X, TEM)\nC***BEGIN PROLOGUE  DSOLSY\nC***SUBSIDIARY\nC***PURPOSE  ODEPACK linear system solver.\nC***TYPE      DOUBLE PRECISION (SSOLSY-S, DSOLSY-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  This routine manages the solution of the linear system arising from\nC  a chord iteration.  It is called if MITER .ne. 0.\nC  If MITER is 1 or 2, it calls DGETRS to accomplish this.\nC  If MITER = 3 it updates the coefficient h*EL0 in the diagonal\nC  matrix, and then computes the solution.\nC  If MITER is 4 or 5, it calls DGBTRS.\nC  Communication with DSOLSY uses the following variables:\nC  WM    = real work space containing the inverse diagonal matrix if\nC          MITER = 3 and the LU decomposition of the matrix otherwise.\nC          Storage of matrix elements starts at WM(3).\nC          WM also contains the following matrix-related data:\nC          WM(1) = SQRT(UROUND) (not used here),\nC          WM(2) = HL0, the previous value of h*EL0, used if MITER = 3.\nC  IWM   = integer work space containing pivot information, starting at\nC          IWM(21), if MITER is 1, 2, 4, or 5.  IWM also contains band\nC          parameters ML = IWM(1) and MU = IWM(2) if MITER is 4 or 5.\nC  X     = the right-hand side vector on input, and the solution vector\nC          on output, of length N.\nC  TEM   = vector of work space of length N, not used in this version.\nC  IERSL = output flag (in COMMON).  IERSL = 0 if no trouble occurred.\nC          IERSL = 1 if a singular matrix arose with MITER = 3.\nC  This routine also uses the COMMON variables EL0, H, MITER, and N.\nC\nC***SEE ALSO  DLSODE\nC***ROUTINES CALLED  DGBTRS, DGETRS\nC***COMMON BLOCKS    DLS001\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC   010418  Reduced size of Common block /DLS001/. (ACH)\nC   031105  Restored 'own' variables to Common block /DLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC***END PROLOGUE  DSOLSY\nC**End\n      INTEGER IWM\n      DOUBLE PRECISION WM, X, TEM\n      DIMENSION WM(*), IWM(*), X(*), TEM(*)\n      INTEGER ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     1   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, NYH,\n     2   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP\n      INTEGER ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     2   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      DOUBLE PRECISION CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     2   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      COMMON /DLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     2   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     3   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, NYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     4   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, MEBAND, ML, MU\n      INTEGER INLPCK\n      DOUBLE PRECISION DI, HL0, PHL0, R\nC\nC***FIRST EXECUTABLE STATEMENT  DSOLSY\n      IERSL = 0\n      GO TO (100, 100, 300, 400, 400), MITER\n 100  CALL DGETRS ( 'N', N, 1, WM(3), N, IWM(21), X, N, INLPCK)\n      RETURN\nC\n 300  PHL0 = WM(2)\n      HL0 = H*EL0\n      WM(2) = HL0\n      IF (HL0 .EQ. PHL0) GO TO 330\n      R = HL0/PHL0\n      DO 320 I = 1,N\n        DI = 1.0D0 - R*(1.0D0 - 1.0D0/WM(I+2))\n        IF (ABS(DI) .EQ. 0.0D0) GO TO 390\n 320    WM(I+2) = 1.0D0/DI\n 330  DO 340 I = 1,N\n 340    X(I) = WM(I+2)*X(I)\n      RETURN\n 390  IERSL = 1\n      RETURN\nC\n 400  ML = IWM(1)\n      MU = IWM(2)\n      MEBAND = 2*ML + MU + 1\n      CALL DGBTRS ( 'N', N, ML, MU, 1, WM(3), MEBAND, IWM(21), X, N,\n     * INLPCK)\n      RETURN\nC----------------------- END OF SUBROUTINE DSOLSY ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/dstode.f",
    "content": "      SUBROUTINE DSTODE (NEQ, Y, YH, NYH, YH1, EWT, SAVF, ACOR,\n     1   WM, IWM, F, JAC, PJAC, SLVS)\nC***BEGIN PROLOGUE  DSTODE\nC***SUBSIDIARY\nC***PURPOSE  Performs one step of an ODEPACK integration.\nC***TYPE      DOUBLE PRECISION (SSTODE-S, DSTODE-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  DSTODE performs one step of the integration of an initial value\nC  problem for a system of ordinary differential equations.\nC  Note:  DSTODE is independent of the value of the iteration method\nC  indicator MITER, when this is .ne. 0, and hence is independent\nC  of the type of chord method used, or the Jacobian structure.\nC  Communication with DSTODE is done with the following variables:\nC\nC  NEQ    = integer array containing problem size in NEQ(1), and\nC           passed as the NEQ argument in all calls to F and JAC.\nC  Y      = an array of length .ge. N used as the Y argument in\nC           all calls to F and JAC.\nC  YH     = an NYH by LMAX array containing the dependent variables\nC           and their approximate scaled derivatives, where\nC           LMAX = MAXORD + 1.  YH(i,j+1) contains the approximate\nC           j-th derivative of y(i), scaled by h**j/factorial(j)\nC           (j = 0,1,...,NQ).  on entry for the first step, the first\nC           two columns of YH must be set from the initial values.\nC  NYH    = a constant integer .ge. N, the first dimension of YH.\nC  YH1    = a one-dimensional array occupying the same space as YH.\nC  EWT    = an array of length N containing multiplicative weights\nC           for local error measurements.  Local errors in Y(i) are\nC           compared to 1.0/EWT(i) in various error tests.\nC  SAVF   = an array of working storage, of length N.\nC           Also used for input of YH(*,MAXORD+2) when JSTART = -1\nC           and MAXORD .lt. the current order NQ.\nC  ACOR   = a work array of length N, used for the accumulated\nC           corrections.  On a successful return, ACOR(i) contains\nC           the estimated one-step local error in Y(i).\nC  WM,IWM = real and integer work arrays associated with matrix\nC           operations in chord iteration (MITER .ne. 0).\nC  PJAC   = name of routine to evaluate and preprocess Jacobian matrix\nC           and P = I - h*el0*JAC, if a chord method is being used.\nC  SLVS   = name of routine to solve linear system in chord iteration.\nC  CCMAX  = maximum relative change in h*el0 before PJAC is called.\nC  H      = the step size to be attempted on the next step.\nC           H is altered by the error control algorithm during the\nC           problem.  H can be either positive or negative, but its\nC           sign must remain constant throughout the problem.\nC  HMIN   = the minimum absolute value of the step size h to be used.\nC  HMXI   = inverse of the maximum absolute value of h to be used.\nC           HMXI = 0.0 is allowed and corresponds to an infinite hmax.\nC           HMIN and HMXI may be changed at any time, but will not\nC           take effect until the next change of h is considered.\nC  TN     = the independent variable. TN is updated on each step taken.\nC  JSTART = an integer used for input only, with the following\nC           values and meanings:\nC                0  perform the first step.\nC            .gt.0  take a new step continuing from the last.\nC               -1  take the next step with a new value of H, MAXORD,\nC                     N, METH, MITER, and/or matrix parameters.\nC               -2  take the next step with a new value of H,\nC                     but with other inputs unchanged.\nC           On return, JSTART is set to 1 to facilitate continuation.\nC  KFLAG  = a completion code with the following meanings:\nC                0  the step was succesful.\nC               -1  the requested error could not be achieved.\nC               -2  corrector convergence could not be achieved.\nC               -3  fatal error in PJAC or SLVS.\nC           A return with KFLAG = -1 or -2 means either\nC           abs(H) = HMIN or 10 consecutive failures occurred.\nC           On a return with KFLAG negative, the values of TN and\nC           the YH array are as of the beginning of the last\nC           step, and H is the last step size attempted.\nC  MAXORD = the maximum order of integration method to be allowed.\nC  MAXCOR = the maximum number of corrector iterations allowed.\nC  MSBP   = maximum number of steps between PJAC calls (MITER .gt. 0).\nC  MXNCF  = maximum number of convergence failures allowed.\nC  METH/MITER = the method flags.  See description in driver.\nC  N      = the number of first-order differential equations.\nC  The values of CCMAX, H, HMIN, HMXI, TN, JSTART, KFLAG, MAXORD,\nC  MAXCOR, MSBP, MXNCF, METH, MITER, and N are communicated via COMMON.\nC\nC***SEE ALSO  DLSODE\nC***ROUTINES CALLED  DCFODE, DVNORM\nC***COMMON BLOCKS    DLS001\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC   010418  Reduced size of Common block /DLS001/. (ACH)\nC   031105  Restored 'own' variables to Common block /DLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC***END PROLOGUE  DSTODE\nC**End\n      EXTERNAL F, JAC, PJAC, SLVS\n      INTEGER NEQ, NYH, IWM\n      DOUBLE PRECISION Y, YH, YH1, EWT, SAVF, ACOR, WM\n      DIMENSION NEQ(*), Y(*), YH(NYH,*), YH1(*), EWT(*), SAVF(*),\n     1   ACOR(*), WM(*), IWM(*)\n      INTEGER ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     1   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, CNYH,\n     2   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP\n      INTEGER ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     1   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, I1, IREDO, IRET, J, JB, M, NCF, NEWQ\n      DOUBLE PRECISION CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     2   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      DOUBLE PRECISION DCON, DDN, DEL, DELP, DSM, DUP, EXDN, EXSM, EXUP,\n     1   R, RH, RHDN, RHSM, RHUP, TOLD, DVNORM\n      COMMON /DLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     2   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   ILLIN, INIT, LYH, LEWT, LACOR, LSAVF, LWM, LIWM,\n     3   MXSTEP, MXHNIL, NHNIL, NTREP, NSLAST, CNYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     4   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\nC\nC***FIRST EXECUTABLE STATEMENT  DSTODE\n      KFLAG = 0\n      TOLD = TN\n      NCF = 0\n      IERPJ = 0\n      IERSL = 0\n      JCUR = 0\n      ICF = 0\n      DELP = 0.0D0\n      IF (JSTART .GT. 0) GO TO 200\n      IF (JSTART .EQ. -1) GO TO 100\n      IF (JSTART .EQ. -2) GO TO 160\nC-----------------------------------------------------------------------\nC On the first call, the order is set to 1, and other variables are\nC initialized.  RMAX is the maximum ratio by which H can be increased\nC in a single step.  It is initially 1.E4 to compensate for the small\nC initial H, but then is normally equal to 10.  If a failure\nC occurs (in corrector convergence or error test), RMAX is set to 2\nC for the next increase.\nC-----------------------------------------------------------------------\n      LMAX = MAXORD + 1\n      NQ = 1\n      L = 2\n      IALTH = 2\n      RMAX = 10000.0D0\n      RC = 0.0D0\n      EL0 = 1.0D0\n      CRATE = 0.7D0\n      HOLD = H\n      MEO = METH\n      NSLP = 0\n      IPUP = MITER\n      IRET = 3\n      GO TO 140\nC-----------------------------------------------------------------------\nC The following block handles preliminaries needed when JSTART = -1.\nC IPUP is set to MITER to force a matrix update.\nC If an order increase is about to be considered (IALTH = 1),\nC IALTH is reset to 2 to postpone consideration one more step.\nC If the caller has changed METH, DCFODE is called to reset\nC the coefficients of the method.\nC If the caller has changed MAXORD to a value less than the current\nC order NQ, NQ is reduced to MAXORD, and a new H chosen accordingly.\nC If H is to be changed, YH must be rescaled.\nC If H or METH is being changed, IALTH is reset to L = NQ + 1\nC to prevent further changes in H for that many steps.\nC-----------------------------------------------------------------------\n 100  IPUP = MITER\n      LMAX = MAXORD + 1\n      IF (IALTH .EQ. 1) IALTH = 2\n      IF (METH .EQ. MEO) GO TO 110\n      CALL DCFODE (METH, ELCO, TESCO)\n      MEO = METH\n      IF (NQ .GT. MAXORD) GO TO 120\n      IALTH = L\n      IRET = 1\n      GO TO 150\n 110  IF (NQ .LE. MAXORD) GO TO 160\n 120  NQ = MAXORD\n      L = LMAX\n      DO 125 I = 1,L\n 125    EL(I) = ELCO(I,NQ)\n      NQNYH = NQ*NYH\n      RC = RC*EL(1)/EL0\n      EL0 = EL(1)\n      CONIT = 0.5D0/(NQ+2)\n      DDN = DVNORM (N, SAVF, EWT)/TESCO(1,L)\n      EXDN = 1.0D0/L\n      RHDN = 1.0D0/(1.3D0*DDN**EXDN + 0.0000013D0)\n      RH = MIN(RHDN,1.0D0)\n      IREDO = 3\n      IF (H .EQ. HOLD) GO TO 170\n      RH = MIN(RH,ABS(H/HOLD))\n      H = HOLD\n      GO TO 175\nC-----------------------------------------------------------------------\nC DCFODE is called to get all the integration coefficients for the\nC current METH.  Then the EL vector and related constants are reset\nC whenever the order NQ is changed, or at the start of the problem.\nC-----------------------------------------------------------------------\n 140  CALL DCFODE (METH, ELCO, TESCO)\n 150  DO 155 I = 1,L\n 155    EL(I) = ELCO(I,NQ)\n      NQNYH = NQ*NYH\n      RC = RC*EL(1)/EL0\n      EL0 = EL(1)\n      CONIT = 0.5D0/(NQ+2)\n      GO TO (160, 170, 200), IRET\nC-----------------------------------------------------------------------\nC If H is being changed, the H ratio RH is checked against\nC RMAX, HMIN, and HMXI, and the YH array rescaled.  IALTH is set to\nC L = NQ + 1 to prevent a change of H for that many steps, unless\nC forced by a convergence or error test failure.\nC-----------------------------------------------------------------------\n 160  IF (H .EQ. HOLD) GO TO 200\n      RH = H/HOLD\n      H = HOLD\n      IREDO = 3\n      GO TO 175\n 170  RH = MAX(RH,HMIN/ABS(H))\n 175  RH = MIN(RH,RMAX)\n      RH = RH/MAX(1.0D0,ABS(H)*HMXI*RH)\n      R = 1.0D0\n      DO 180 J = 2,L\n        R = R*RH\n        DO 180 I = 1,N\n 180      YH(I,J) = YH(I,J)*R\n      H = H*RH\n      RC = RC*RH\n      IALTH = L\n      IF (IREDO .EQ. 0) GO TO 690\nC-----------------------------------------------------------------------\nC This section computes the predicted values by effectively\nC multiplying the YH array by the Pascal Triangle matrix.\nC RC is the ratio of new to old values of the coefficient  H*EL(1).\nC When RC differs from 1 by more than CCMAX, IPUP is set to MITER\nC to force PJAC to be called, if a Jacobian is involved.\nC In any case, PJAC is called at least every MSBP steps.\nC-----------------------------------------------------------------------\n 200  IF (ABS(RC-1.0D0) .GT. CCMAX) IPUP = MITER\n      IF (NST .GE. NSLP+MSBP) IPUP = MITER\n      TN = TN + H\n      I1 = NQNYH + 1\n      DO 215 JB = 1,NQ\n        I1 = I1 - NYH\nCdir$ ivdep\n        DO 210 I = I1,NQNYH\n 210      YH1(I) = YH1(I) + YH1(I+NYH)\n 215    CONTINUE\nC-----------------------------------------------------------------------\nC Up to MAXCOR corrector iterations are taken.  A convergence test is\nC made on the R.M.S. norm of each correction, weighted by the error\nC weight vector EWT.  The sum of the corrections is accumulated in the\nC vector ACOR(i).  The YH array is not altered in the corrector loop.\nC-----------------------------------------------------------------------\n 220  M = 0\n      DO 230 I = 1,N\n 230    Y(I) = YH(I,1)\n      CALL F (NEQ, TN, Y, SAVF)\n      NFE = NFE + 1\n      IF (IPUP .LE. 0) GO TO 250\nC-----------------------------------------------------------------------\nC If indicated, the matrix P = I - h*el(1)*J is reevaluated and\nC preprocessed before starting the corrector iteration.  IPUP is set\nC to 0 as an indicator that this has been done.\nC-----------------------------------------------------------------------\n      CALL PJAC (NEQ, Y, YH, NYH, EWT, ACOR, SAVF, WM, IWM, F, JAC)\n      IPUP = 0\n      RC = 1.0D0\n      NSLP = NST\n      CRATE = 0.7D0\n      IF (IERPJ .NE. 0) GO TO 430\n 250  DO 260 I = 1,N\n 260    ACOR(I) = 0.0D0\n 270  IF (MITER .NE. 0) GO TO 350\nC-----------------------------------------------------------------------\nC In the case of functional iteration, update Y directly from\nC the result of the last function evaluation.\nC-----------------------------------------------------------------------\n      DO 290 I = 1,N\n        SAVF(I) = H*SAVF(I) - YH(I,2)\n 290    Y(I) = SAVF(I) - ACOR(I)\n      DEL = DVNORM (N, Y, EWT)\n      DO 300 I = 1,N\n        Y(I) = YH(I,1) + EL(1)*SAVF(I)\n 300    ACOR(I) = SAVF(I)\n      GO TO 400\nC-----------------------------------------------------------------------\nC In the case of the chord method, compute the corrector error,\nC and solve the linear system with that as right-hand side and\nC P as coefficient matrix.\nC-----------------------------------------------------------------------\n 350  DO 360 I = 1,N\n 360    Y(I) = H*SAVF(I) - (YH(I,2) + ACOR(I))\n      CALL SLVS (WM, IWM, Y, SAVF)\n      IF (IERSL .LT. 0) GO TO 430\n      IF (IERSL .GT. 0) GO TO 410\n      DEL = DVNORM (N, Y, EWT)\n      DO 380 I = 1,N\n        ACOR(I) = ACOR(I) + Y(I)\n 380    Y(I) = YH(I,1) + EL(1)*ACOR(I)\nC-----------------------------------------------------------------------\nC Test for convergence.  If M.gt.0, an estimate of the convergence\nC rate constant is stored in CRATE, and this is used in the test.\nC-----------------------------------------------------------------------\n 400  IF (M .NE. 0) CRATE = MAX(0.2D0*CRATE,DEL/DELP)\n      DCON = DEL*MIN(1.0D0,1.5D0*CRATE)/(TESCO(2,NQ)*CONIT)\n      IF (DCON .LE. 1.0D0) GO TO 450\n      M = M + 1\n      IF (M .EQ. MAXCOR) GO TO 410\n      IF (M .GE. 2 .AND. DEL .GT. 2.0D0*DELP) GO TO 410\n      DELP = DEL\n      CALL F (NEQ, TN, Y, SAVF)\n      NFE = NFE + 1\n      GO TO 270\nC-----------------------------------------------------------------------\nC The corrector iteration failed to converge.\nC If MITER .ne. 0 and the Jacobian is out of date, PJAC is called for\nC the next try.  Otherwise the YH array is retracted to its values\nC before prediction, and H is reduced, if possible.  If H cannot be\nC reduced or MXNCF failures have occurred, exit with KFLAG = -2.\nC-----------------------------------------------------------------------\n 410  IF (MITER .EQ. 0 .OR. JCUR .EQ. 1) GO TO 430\n      ICF = 1\n      IPUP = MITER\n      GO TO 220\n 430  ICF = 2\n      NCF = NCF + 1\n      RMAX = 2.0D0\n      TN = TOLD\n      I1 = NQNYH + 1\n      DO 445 JB = 1,NQ\n        I1 = I1 - NYH\nCdir$ ivdep\n        DO 440 I = I1,NQNYH\n 440      YH1(I) = YH1(I) - YH1(I+NYH)\n 445    CONTINUE\n      IF (IERPJ .LT. 0 .OR. IERSL .LT. 0) GO TO 680\n      IF (ABS(H) .LE. HMIN*1.00001D0) GO TO 670\n      IF (NCF .EQ. MXNCF) GO TO 670\n      RH = 0.25D0\n      IPUP = MITER\n      IREDO = 1\n      GO TO 170\nC-----------------------------------------------------------------------\nC The corrector has converged.  JCUR is set to 0\nC to signal that the Jacobian involved may need updating later.\nC The local error test is made and control passes to statement 500\nC if it fails.\nC-----------------------------------------------------------------------\n 450  JCUR = 0\n      IF (M .EQ. 0) DSM = DEL/TESCO(2,NQ)\n      IF (M .GT. 0) DSM = DVNORM (N, ACOR, EWT)/TESCO(2,NQ)\n      IF (DSM .GT. 1.0D0) GO TO 500\nC-----------------------------------------------------------------------\nC After a successful step, update the YH array.\nC Consider changing H if IALTH = 1.  Otherwise decrease IALTH by 1.\nC If IALTH is then 1 and NQ .lt. MAXORD, then ACOR is saved for\nC use in a possible order increase on the next step.\nC If a change in H is considered, an increase or decrease in order\nC by one is considered also.  A change in H is made only if it is by a\nC factor of at least 1.1.  If not, IALTH is set to 3 to prevent\nC testing for that many steps.\nC-----------------------------------------------------------------------\n      KFLAG = 0\n      IREDO = 0\n      NST = NST + 1\n      HU = H\n      NQU = NQ\n      DO 470 J = 1,L\n        DO 470 I = 1,N\n 470      YH(I,J) = YH(I,J) + EL(J)*ACOR(I)\n      IALTH = IALTH - 1\n      IF (IALTH .EQ. 0) GO TO 520\n      IF (IALTH .GT. 1) GO TO 700\n      IF (L .EQ. LMAX) GO TO 700\n      DO 490 I = 1,N\n 490    YH(I,LMAX) = ACOR(I)\n      GO TO 700\nC-----------------------------------------------------------------------\nC The error test failed.  KFLAG keeps track of multiple failures.\nC Restore TN and the YH array to their previous values, and prepare\nC to try the step again.  Compute the optimum step size for this or\nC one lower order.  After 2 or more failures, H is forced to decrease\nC by a factor of 0.2 or less.\nC-----------------------------------------------------------------------\n 500  KFLAG = KFLAG - 1\n      TN = TOLD\n      I1 = NQNYH + 1\n      DO 515 JB = 1,NQ\n        I1 = I1 - NYH\nCdir$ ivdep\n        DO 510 I = I1,NQNYH\n 510      YH1(I) = YH1(I) - YH1(I+NYH)\n 515    CONTINUE\n      RMAX = 2.0D0\n      IF (ABS(H) .LE. HMIN*1.00001D0) GO TO 660\n      IF (KFLAG .LE. -3) GO TO 640\n      IREDO = 2\n      RHUP = 0.0D0\n      GO TO 540\nC-----------------------------------------------------------------------\nC Regardless of the success or failure of the step, factors\nC RHDN, RHSM, and RHUP are computed, by which H could be multiplied\nC at order NQ - 1, order NQ, or order NQ + 1, respectively.\nC In the case of failure, RHUP = 0.0 to avoid an order increase.\nC The largest of these is determined and the new order chosen\nC accordingly.  If the order is to be increased, we compute one\nC additional scaled derivative.\nC-----------------------------------------------------------------------\n 520  RHUP = 0.0D0\n      IF (L .EQ. LMAX) GO TO 540\n      DO 530 I = 1,N\n 530    SAVF(I) = ACOR(I) - YH(I,LMAX)\n      DUP = DVNORM (N, SAVF, EWT)/TESCO(3,NQ)\n      EXUP = 1.0D0/(L+1)\n      RHUP = 1.0D0/(1.4D0*DUP**EXUP + 0.0000014D0)\n 540  EXSM = 1.0D0/L\n      RHSM = 1.0D0/(1.2D0*DSM**EXSM + 0.0000012D0)\n      RHDN = 0.0D0\n      IF (NQ .EQ. 1) GO TO 560\n      DDN = DVNORM (N, YH(1,L), EWT)/TESCO(1,NQ)\n      EXDN = 1.0D0/NQ\n      RHDN = 1.0D0/(1.3D0*DDN**EXDN + 0.0000013D0)\n 560  IF (RHSM .GE. RHUP) GO TO 570\n      IF (RHUP .GT. RHDN) GO TO 590\n      GO TO 580\n 570  IF (RHSM .LT. RHDN) GO TO 580\n      NEWQ = NQ\n      RH = RHSM\n      GO TO 620\n 580  NEWQ = NQ - 1\n      RH = RHDN\n      IF (KFLAG .LT. 0 .AND. RH .GT. 1.0D0) RH = 1.0D0\n      GO TO 620\n 590  NEWQ = L\n      RH = RHUP\n      IF (RH .LT. 1.1D0) GO TO 610\n      R = EL(L)/L\n      DO 600 I = 1,N\n 600    YH(I,NEWQ+1) = ACOR(I)*R\n      GO TO 630\n 610  IALTH = 3\n      GO TO 700\n 620  IF ((KFLAG .EQ. 0) .AND. (RH .LT. 1.1D0)) GO TO 610\n      IF (KFLAG .LE. -2) RH = MIN(RH,0.2D0)\nC-----------------------------------------------------------------------\nC If there is a change of order, reset NQ, l, and the coefficients.\nC In any case H is reset according to RH and the YH array is rescaled.\nC Then exit from 690 if the step was OK, or redo the step otherwise.\nC-----------------------------------------------------------------------\n      IF (NEWQ .EQ. NQ) GO TO 170\n 630  NQ = NEWQ\n      L = NQ + 1\n      IRET = 2\n      GO TO 150\nC-----------------------------------------------------------------------\nC Control reaches this section if 3 or more failures have occured.\nC If 10 failures have occurred, exit with KFLAG = -1.\nC It is assumed that the derivatives that have accumulated in the\nC YH array have errors of the wrong order.  Hence the first\nC derivative is recomputed, and the order is set to 1.  Then\nC H is reduced by a factor of 10, and the step is retried,\nC until it succeeds or H reaches HMIN.\nC-----------------------------------------------------------------------\n 640  IF (KFLAG .EQ. -10) GO TO 660\n      RH = 0.1D0\n      RH = MAX(HMIN/ABS(H),RH)\n      H = H*RH\n      DO 645 I = 1,N\n 645    Y(I) = YH(I,1)\n      CALL F (NEQ, TN, Y, SAVF)\n      NFE = NFE + 1\n      DO 650 I = 1,N\n 650    YH(I,2) = H*SAVF(I)\n      IPUP = MITER\n      IALTH = 5\n      IF (NQ .EQ. 1) GO TO 200\n      NQ = 1\n      L = 2\n      IRET = 3\n      GO TO 150\nC-----------------------------------------------------------------------\nC All returns are made through this section.  H is saved in HOLD\nC to allow the caller to change H on the next step.\nC-----------------------------------------------------------------------\n 660  KFLAG = -1\n      GO TO 720\n 670  KFLAG = -2\n      GO TO 720\n 680  KFLAG = -3\n      GO TO 720\n 690  RMAX = 10.0D0\n 700  R = 1.0D0/TESCO(2,NQU)\n      DO 710 I = 1,N\n 710    ACOR(I) = ACOR(I)*R\n 720  HOLD = H\n      JSTART = 1\n      RETURN\nC----------------------- END OF SUBROUTINE DSTODE ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/dvnorm.f",
    "content": "      DOUBLE PRECISION FUNCTION DVNORM (N, V, W)\nC***BEGIN PROLOGUE  DVNORM\nC***SUBSIDIARY\nC***PURPOSE  Weighted root-mean-square vector norm.\nC***TYPE      DOUBLE PRECISION (SVNORM-S, DVNORM-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  This function routine computes the weighted root-mean-square norm\nC  of the vector of length N contained in the array V, with weights\nC  contained in the array W of length N:\nC    DVNORM = SQRT( (1/N) * SUM( V(i)*W(i) )**2 )\nC\nC***SEE ALSO  DLSODE\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC***END PROLOGUE  DVNORM\nC**End\n      INTEGER N,   I\n      DOUBLE PRECISION V, W,   SUM\n      DIMENSION V(N), W(N)\nC\nC***FIRST EXECUTABLE STATEMENT  DVNORM\n      SUM = 0.0D0\n      DO 10 I = 1,N\n 10     SUM = SUM + (V(I)*W(I))**2\n      DVNORM = SQRT(SUM/N)\n      RETURN\nC----------------------- END OF FUNCTION DVNORM ------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/dcfode.f \\\n  %reldir%/dewset.f \\\n  %reldir%/dintdy.f \\\n  %reldir%/dlsode.f \\\n  %reldir%/dprepj.f \\\n  %reldir%/dsolsy.f \\\n  %reldir%/dstode.f \\\n  %reldir%/dvnorm.f \\\n  %reldir%/scfode.f \\\n  %reldir%/sewset.f \\\n  %reldir%/sintdy.f \\\n  %reldir%/slsode.f \\\n  %reldir%/sprepj.f \\\n  %reldir%/ssolsy.f \\\n  %reldir%/sstode.f \\\n  %reldir%/svnorm.f\n"
  },
  {
    "path": "liboctave/external/odepack/scfode.f",
    "content": "      SUBROUTINE SCFODE (METH, ELCO, TESCO)\nC***BEGIN PROLOGUE  SCFODE\nC***SUBSIDIARY\nC***PURPOSE  Set ODE integrator coefficients.\nC***TYPE      SINGLE PRECISION (SCFODE-S, DCFODE-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  SCFODE is called by the integrator routine to set coefficients\nC  needed there.  The coefficients for the current method, as\nC  given by the value of METH, are set for all orders and saved.\nC  The maximum order assumed here is 12 if METH = 1 and 5 if METH = 2.\nC  (A smaller value of the maximum order is also allowed.)\nC  SCFODE is called once at the beginning of the problem,\nC  and is not called again unless and until METH is changed.\nC\nC  The ELCO array contains the basic method coefficients.\nC  The coefficients el(i), 1 .le. i .le. nq+1, for the method of\nC  order nq are stored in ELCO(i,nq).  They are given by a genetrating\nC  polynomial, i.e.,\nC      l(x) = el(1) + el(2)*x + ... + el(nq+1)*x**nq.\nC  For the implicit Adams methods, l(x) is given by\nC      dl/dx = (x+1)*(x+2)*...*(x+nq-1)/factorial(nq-1),    l(-1) = 0.\nC  For the BDF methods, l(x) is given by\nC      l(x) = (x+1)*(x+2)* ... *(x+nq)/K,\nC  where         K = factorial(nq)*(1 + 1/2 + ... + 1/nq).\nC\nC  The TESCO array contains test constants used for the\nC  local error test and the selection of step size and/or order.\nC  At order nq, TESCO(k,nq) is used for the selection of step\nC  size at order nq - 1 if k = 1, at order nq if k = 2, and at order\nC  nq + 1 if k = 3.\nC\nC***SEE ALSO  SLSODE\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC***END PROLOGUE  SCFODE\nC**End\n      INTEGER METH\n      INTEGER I, IB, NQ, NQM1, NQP1\n      REAL ELCO, TESCO\n      REAL AGAMQ, FNQ, FNQM1, PC, PINT, RAGQ,\n     1   RQFAC, RQ1FAC, TSIGN, XPIN\n      DIMENSION ELCO(13,12), TESCO(3,12)\n      DIMENSION PC(12)\nC\nC***FIRST EXECUTABLE STATEMENT  SCFODE\n      GO TO (100, 200), METH\nC\n 100  ELCO(1,1) = 1.0E0\n      ELCO(2,1) = 1.0E0\n      TESCO(1,1) = 0.0E0\n      TESCO(2,1) = 2.0E0\n      TESCO(1,2) = 1.0E0\n      TESCO(3,12) = 0.0E0\n      PC(1) = 1.0E0\n      RQFAC = 1.0E0\n      DO 140 NQ = 2,12\nC-----------------------------------------------------------------------\nC The PC array will contain the coefficients of the polynomial\nC     p(x) = (x+1)*(x+2)*...*(x+nq-1).\nC Initially, p(x) = 1.\nC-----------------------------------------------------------------------\n        RQ1FAC = RQFAC\n        RQFAC = RQFAC/NQ\n        NQM1 = NQ - 1\n        FNQM1 = NQM1\n        NQP1 = NQ + 1\nC Form coefficients of p(x)*(x+nq-1). ----------------------------------\n        PC(NQ) = 0.0E0\n        DO 110 IB = 1,NQM1\n          I = NQP1 - IB\n 110      PC(I) = PC(I-1) + FNQM1*PC(I)\n        PC(1) = FNQM1*PC(1)\nC Compute integral, -1 to 0, of p(x) and x*p(x). -----------------------\n        PINT = PC(1)\n        XPIN = PC(1)/2.0E0\n        TSIGN = 1.0E0\n        DO 120 I = 2,NQ\n          TSIGN = -TSIGN\n          PINT = PINT + TSIGN*PC(I)/I\n 120      XPIN = XPIN + TSIGN*PC(I)/(I+1)\nC Store coefficients in ELCO and TESCO. --------------------------------\n        ELCO(1,NQ) = PINT*RQ1FAC\n        ELCO(2,NQ) = 1.0E0\n        DO 130 I = 2,NQ\n 130      ELCO(I+1,NQ) = RQ1FAC*PC(I)/I\n        AGAMQ = RQFAC*XPIN\n        RAGQ = 1.0E0/AGAMQ\n        TESCO(2,NQ) = RAGQ\n        IF (NQ .LT. 12) TESCO(1,NQP1) = RAGQ*RQFAC/NQP1\n        TESCO(3,NQM1) = RAGQ\n 140    CONTINUE\n      RETURN\nC\n 200  PC(1) = 1.0E0\n      RQ1FAC = 1.0E0\n      DO 230 NQ = 1,5\nC-----------------------------------------------------------------------\nC The PC array will contain the coefficients of the polynomial\nC     p(x) = (x+1)*(x+2)*...*(x+nq).\nC Initially, p(x) = 1.\nC-----------------------------------------------------------------------\n        FNQ = NQ\n        NQP1 = NQ + 1\nC Form coefficients of p(x)*(x+nq). ------------------------------------\n        PC(NQP1) = 0.0E0\n        DO 210 IB = 1,NQ\n          I = NQ + 2 - IB\n 210      PC(I) = PC(I-1) + FNQ*PC(I)\n        PC(1) = FNQ*PC(1)\nC Store coefficients in ELCO and TESCO. --------------------------------\n        DO 220 I = 1,NQP1\n 220      ELCO(I,NQ) = PC(I)/PC(2)\n        ELCO(2,NQ) = 1.0E0\n        TESCO(1,NQ) = RQ1FAC\n        TESCO(2,NQ) = NQP1/ELCO(1,NQ)\n        TESCO(3,NQ) = (NQ+2)/ELCO(1,NQ)\n        RQ1FAC = RQ1FAC/FNQ\n 230    CONTINUE\n      RETURN\nC----------------------- END OF SUBROUTINE SCFODE ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/sewset.f",
    "content": "      SUBROUTINE SEWSET (N, ITOL, RTOL, ATOL, YCUR, EWT)\nC***BEGIN PROLOGUE  SEWSET\nC***SUBSIDIARY\nC***PURPOSE  Set error weight vector.\nC***TYPE      SINGLE PRECISION (SEWSET-S, DEWSET-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  This subroutine sets the error weight vector EWT according to\nC      EWT(i) = RTOL(i)*ABS(YCUR(i)) + ATOL(i),  i = 1,...,N,\nC  with the subscript on RTOL and/or ATOL possibly replaced by 1 above,\nC  depending on the value of ITOL.\nC\nC***SEE ALSO  SLSODE\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC***END PROLOGUE  SEWSET\nC**End\n      INTEGER N, ITOL\n      INTEGER I\n      REAL RTOL, ATOL, YCUR, EWT\n      DIMENSION RTOL(*), ATOL(*), YCUR(N), EWT(N)\nC\nC***FIRST EXECUTABLE STATEMENT  SEWSET\n      GO TO (10, 20, 30, 40), ITOL\n 10   CONTINUE\n      DO 15 I = 1,N\n 15     EWT(I) = RTOL(1)*ABS(YCUR(I)) + ATOL(1)\n      RETURN\n 20   CONTINUE\n      DO 25 I = 1,N\n 25     EWT(I) = RTOL(1)*ABS(YCUR(I)) + ATOL(I)\n      RETURN\n 30   CONTINUE\n      DO 35 I = 1,N\n 35     EWT(I) = RTOL(I)*ABS(YCUR(I)) + ATOL(1)\n      RETURN\n 40   CONTINUE\n      DO 45 I = 1,N\n 45     EWT(I) = RTOL(I)*ABS(YCUR(I)) + ATOL(I)\n      RETURN\nC----------------------- END OF SUBROUTINE SEWSET ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/sintdy.f",
    "content": "      SUBROUTINE SINTDY (T, K, YH, NYH, DKY, IFLAG)\nC***BEGIN PROLOGUE  SINTDY\nC***SUBSIDIARY\nC***PURPOSE  Interpolate solution derivatives.\nC***TYPE      SINGLE PRECISION (SINTDY-S, DINTDY-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  SINTDY computes interpolated values of the K-th derivative of the\nC  dependent variable vector y, and stores it in DKY.  This routine\nC  is called within the package with K = 0 and T = TOUT, but may\nC  also be called by the user for any K up to the current order.\nC  (See detailed instructions in the usage documentation.)\nC\nC  The computed values in DKY are gotten by interpolation using the\nC  Nordsieck history array YH.  This array corresponds uniquely to a\nC  vector-valued polynomial of degree NQCUR or less, and DKY is set\nC  to the K-th derivative of this polynomial at T.\nC  The formula for DKY is:\nC               q\nC   DKY(i)  =  sum  c(j,K) * (T - tn)**(j-K) * h**(-j) * YH(i,j+1)\nC              j=K\nC  where  c(j,K) = j*(j-1)*...*(j-K+1), q = NQCUR, tn = TCUR, h = HCUR.\nC  The quantities  nq = NQCUR, l = nq+1, N = NEQ, tn, and h are\nC  communicated by COMMON.  The above sum is done in reverse order.\nC  IFLAG is returned negative if either K or T is out of bounds.\nC\nC***SEE ALSO  SLSODE\nC***ROUTINES CALLED  XERRWV\nC***COMMON BLOCKS    SLS001\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC   010412  Reduced size of Common block /SLS001/. (ACH)\nC   031105  Restored 'own' variables to Common block /SLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC   050427  Corrected roundoff decrement in TP. (ACH)\nC***END PROLOGUE  SINTDY\nC**End\n      INTEGER K, NYH, IFLAG\n      REAL T, YH, DKY\n      DIMENSION YH(NYH,*), DKY(*)\n      INTEGER INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, CNYH,\n     1   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     1   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     2   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     3   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      REAL CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      COMMON /SLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, CNYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     3   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     4   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, IC, J, JB, JB2, JJ, JJ1, JP1\n      REAL C, R, S, TP\n      CHARACTER*80 MSG\nC\nC***FIRST EXECUTABLE STATEMENT  SINTDY\n      IFLAG = 0\n      IF (K .LT. 0 .OR. K .GT. NQ) GO TO 80\n      TP = TN - HU -  100.0E0*UROUND*SIGN(ABS(TN) + ABS(HU), HU)\n      IF ((T-TP)*(T-TN) .GT. 0.0E0) GO TO 90\nC\n      S = (T - TN)/H\n      IC = 1\n      IF (K .EQ. 0) GO TO 15\n      JJ1 = L - K\n      DO 10 JJ = JJ1,NQ\n 10     IC = IC*JJ\n 15   C = IC\n      DO 20 I = 1,N\n 20     DKY(I) = C*YH(I,L)\n      IF (K .EQ. NQ) GO TO 55\n      JB2 = NQ - K\n      DO 50 JB = 1,JB2\n        J = NQ - JB\n        JP1 = J + 1\n        IC = 1\n        IF (K .EQ. 0) GO TO 35\n        JJ1 = JP1 - K\n        DO 30 JJ = JJ1,J\n 30       IC = IC*JJ\n 35     C = IC\n        DO 40 I = 1,N\n 40       DKY(I) = C*YH(I,JP1) + S*DKY(I)\n 50     CONTINUE\n      IF (K .EQ. 0) RETURN\n 55   R = H**(-K)\n      DO 60 I = 1,N\n 60     DKY(I) = R*DKY(I)\n      RETURN\nC\n 80   MSG = 'SINTDY-  K (=I1) illegal      '\n      CALL XERRWV (MSG, 30, 51, 0, 1, K, 0, 0, 0.0E0, 0.0E0)\n      IFLAG = -1\n      RETURN\n 90   MSG = 'SINTDY-  T (=R1) illegal      '\n      CALL XERRWV (MSG, 30, 52, 0, 0, 0, 0, 1, T, 0.0E0)\n      MSG='      T not in interval TCUR - HU (= R1) to TCUR (=R2)      '\n      CALL XERRWV (MSG, 60, 52, 0, 0, 0, 0, 2, TP, TN)\n      IFLAG = -2\n      RETURN\nC----------------------- END OF SUBROUTINE SINTDY ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/slsode.f",
    "content": "      SUBROUTINE SLSODE (F, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK,\n     1                  ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, MF)\n      EXTERNAL F, JAC\n      INTEGER NEQ, ITOL, ITASK, ISTATE, IOPT, LRW, IWORK, LIW, MF\n      REAL Y, T, TOUT, RTOL, ATOL, RWORK\n      DIMENSION NEQ(*), Y(*), RTOL(*), ATOL(*), RWORK(LRW), IWORK(LIW)\nC***BEGIN PROLOGUE  SLSODE\nC***PURPOSE  Livermore Solver for Ordinary Differential Equations.\nC            SLSODE solves the initial-value problem for stiff or\nC            nonstiff systems of first-order ODE's,\nC               dy/dt = f(t,y),   or, in component form,\nC               dy(i)/dt = f(i) = f(i,t,y(1),y(2),...,y(N)),  i=1,...,N.\nC***CATEGORY  I1A\nC***TYPE      SINGLE PRECISION (SLSODE-S, DLSODE-D)\nC***KEYWORDS  ORDINARY DIFFERENTIAL EQUATIONS, INITIAL VALUE PROBLEM,\nC             STIFF, NONSTIFF\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC             Center for Applied Scientific Computing, L-561\nC             Lawrence Livermore National Laboratory\nC             Livermore, CA 94551.\nC***DESCRIPTION\nC\nC     NOTE: The \"Usage\" and \"Arguments\" sections treat only a subset of\nC           available options, in condensed fashion.  The options\nC           covered and the information supplied will support most\nC           standard uses of SLSODE.\nC\nC           For more sophisticated uses, full details on all options are\nC           given in the concluding section, headed \"Long Description.\"\nC           A synopsis of the SLSODE Long Description is provided at the\nC           beginning of that section; general topics covered are:\nC           - Elements of the call sequence; optional input and output\nC           - Optional supplemental routines in the SLSODE package\nC           - internal COMMON block\nC\nC *Usage:\nC     Communication between the user and the SLSODE package, for normal\nC     situations, is summarized here.  This summary describes a subset\nC     of the available options.  See \"Long Description\" for complete\nC     details, including optional communication, nonstandard options,\nC     and instructions for special situations.\nC\nC     A sample program is given in the \"Examples\" section.\nC\nC     Refer to the argument descriptions for the definitions of the\nC     quantities that appear in the following sample declarations.\nC\nC     For MF = 10,\nC        PARAMETER  (LRW = 20 + 16*NEQ,           LIW = 20)\nC     For MF = 21 or 22,\nC        PARAMETER  (LRW = 22 +  9*NEQ + NEQ**2,  LIW = 20 + NEQ)\nC     For MF = 24 or 25,\nC        PARAMETER  (LRW = 22 + 10*NEQ + (2*ML+MU)*NEQ,\nC       *                                         LIW = 20 + NEQ)\nC\nC        EXTERNAL F, JAC\nC        INTEGER  NEQ, ITOL, ITASK, ISTATE, IOPT, LRW, IWORK(LIW),\nC       *         LIW, MF\nC        REAL Y(NEQ), T, TOUT, RTOL, ATOL(ntol), RWORK(LRW)\nC\nC        CALL SLSODE (F, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK,\nC       *            ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, MF)\nC\nC *Arguments:\nC     F     :EXT    Name of subroutine for right-hand-side vector f.\nC                   This name must be declared EXTERNAL in calling\nC                   program.  The form of F must be:\nC\nC                   SUBROUTINE  F (NEQ, T, Y, YDOT)\nC                   INTEGER  NEQ\nC                   REAL T, Y(*), YDOT(*)\nC\nC                   The inputs are NEQ, T, Y.  F is to set\nC\nC                   YDOT(i) = f(i,T,Y(1),Y(2),...,Y(NEQ)),\nC                                                     i = 1, ..., NEQ .\nC\nC     NEQ   :IN     Number of first-order ODE's.\nC\nC     Y     :INOUT  Array of values of the y(t) vector, of length NEQ.\nC                   Input:  For the first call, Y should contain the\nC                           values of y(t) at t = T. (Y is an input\nC                           variable only if ISTATE = 1.)\nC                   Output: On return, Y will contain the values at the\nC                           new t-value.\nC\nC     T     :INOUT  Value of the independent variable.  On return it\nC                   will be the current value of t (normally TOUT).\nC\nC     TOUT  :IN     Next point where output is desired (.NE. T).\nC\nC     ITOL  :IN     1 or 2 according as ATOL (below) is a scalar or\nC                   an array.\nC\nC     RTOL  :IN     Relative tolerance parameter (scalar).\nC\nC     ATOL  :IN     Absolute tolerance parameter (scalar or array).\nC                   If ITOL = 1, ATOL need not be dimensioned.\nC                   If ITOL = 2, ATOL must be dimensioned at least NEQ.\nC\nC                   The estimated local error in Y(i) will be controlled\nC                   so as to be roughly less (in magnitude) than\nC\nC                   EWT(i) = RTOL*ABS(Y(i)) + ATOL     if ITOL = 1, or\nC                   EWT(i) = RTOL*ABS(Y(i)) + ATOL(i)  if ITOL = 2.\nC\nC                   Thus the local error test passes if, in each\nC                   component, either the absolute error is less than\nC                   ATOL (or ATOL(i)), or the relative error is less\nC                   than RTOL.\nC\nC                   Use RTOL = 0.0 for pure absolute error control, and\nC                   use ATOL = 0.0 (or ATOL(i) = 0.0) for pure relative\nC                   error control.  Caution:  Actual (global) errors may\nC                   exceed these local tolerances, so choose them\nC                   conservatively.\nC\nC     ITASK :IN     Flag indicating the task SLSODE is to perform.\nC                   Use ITASK = 1 for normal computation of output\nC                   values of y at t = TOUT.\nC\nC     ISTATE:INOUT  Index used for input and output to specify the state\nC                   of the calculation.\nC                   Input:\nC                    1   This is the first call for a problem.\nC                    2   This is a subsequent call.\nC                   Output:\nC                    1   Nothing was done, as TOUT was equal to T.\nC                    2   SLSODE was successful (otherwise, negative).\nC                        Note that ISTATE need not be modified after a\nC                        successful return.\nC                   -1   Excess work done on this call (perhaps wrong\nC                        MF).\nC                   -2   Excess accuracy requested (tolerances too\nC                        small).\nC                   -3   Illegal input detected (see printed message).\nC                   -4   Repeated error test failures (check all\nC                        inputs).\nC                   -5   Repeated convergence failures (perhaps bad\nC                        Jacobian supplied or wrong choice of MF or\nC                        tolerances).\nC                   -6   Error weight became zero during problem\nC                        (solution component i vanished, and ATOL or\nC                        ATOL(i) = 0.).\nC\nC     IOPT  :IN     Flag indicating whether optional inputs are used:\nC                   0   No.\nC                   1   Yes.  (See \"Optional inputs\" under \"Long\nC                       Description,\" Part 1.)\nC\nC     RWORK :WORK   Real work array of length at least:\nC                   20 + 16*NEQ                    for MF = 10,\nC                   22 +  9*NEQ + NEQ**2           for MF = 21 or 22,\nC                   22 + 10*NEQ + (2*ML + MU)*NEQ  for MF = 24 or 25.\nC\nC     LRW   :IN     Declared length of RWORK (in user's DIMENSION\nC                   statement).\nC\nC     IWORK :WORK   Integer work array of length at least:\nC                   20        for MF = 10,\nC                   20 + NEQ  for MF = 21, 22, 24, or 25.\nC\nC                   If MF = 24 or 25, input in IWORK(1),IWORK(2) the\nC                   lower and upper Jacobian half-bandwidths ML,MU.\nC\nC                   On return, IWORK contains information that may be\nC                   of interest to the user:\nC\nC            Name   Location   Meaning\nC            -----  ---------  -----------------------------------------\nC            NST    IWORK(11)  Number of steps taken for the problem so\nC                              far.\nC            NFE    IWORK(12)  Number of f evaluations for the problem\nC                              so far.\nC            NJE    IWORK(13)  Number of Jacobian evaluations (and of\nC                              matrix LU decompositions) for the problem\nC                              so far.\nC            NQU    IWORK(14)  Method order last used (successfully).\nC            LENRW  IWORK(17)  Length of RWORK actually required.  This\nC                              is defined on normal returns and on an\nC                              illegal input return for insufficient\nC                              storage.\nC            LENIW  IWORK(18)  Length of IWORK actually required.  This\nC                              is defined on normal returns and on an\nC                              illegal input return for insufficient\nC                              storage.\nC\nC     LIW   :IN     Declared length of IWORK (in user's DIMENSION\nC                   statement).\nC\nC     JAC   :EXT    Name of subroutine for Jacobian matrix (MF =\nC                   21 or 24).  If used, this name must be declared\nC                   EXTERNAL in calling program.  If not used, pass a\nC                   dummy name.  The form of JAC must be:\nC\nC                   SUBROUTINE JAC (NEQ, T, Y, ML, MU, PD, NROWPD)\nC                   INTEGER NEQ, ML, MU, NROWPD\nC                   REAL T, Y(*), PD(NROWPD,*)\nC\nC                   See item c, under \"Description\" below for more\nC                   information about JAC.\nC\nC     MF    :IN     Method flag.  Standard values are:\nC                   10  Nonstiff (Adams) method, no Jacobian used.\nC                   21  Stiff (BDF) method, user-supplied full Jacobian.\nC                   22  Stiff method, internally generated full\nC                       Jacobian.\nC                   24  Stiff method, user-supplied banded Jacobian.\nC                   25  Stiff method, internally generated banded\nC                       Jacobian.\nC\nC *Description:\nC     SLSODE solves the initial value problem for stiff or nonstiff\nC     systems of first-order ODE's,\nC\nC        dy/dt = f(t,y) ,\nC\nC     or, in component form,\nC\nC        dy(i)/dt = f(i) = f(i,t,y(1),y(2),...,y(NEQ))\nC                                                  (i = 1, ..., NEQ) .\nC\nC     SLSODE is a package based on the GEAR and GEARB packages, and on\nC     the October 23, 1978, version of the tentative ODEPACK user\nC     interface standard, with minor modifications.\nC\nC     The steps in solving such a problem are as follows.\nC\nC     a. First write a subroutine of the form\nC\nC           SUBROUTINE  F (NEQ, T, Y, YDOT)\nC           INTEGER  NEQ\nC           REAL T, Y(*), YDOT(*)\nC\nC        which supplies the vector function f by loading YDOT(i) with\nC        f(i).\nC\nC     b. Next determine (or guess) whether or not the problem is stiff.\nC        Stiffness occurs when the Jacobian matrix df/dy has an\nC        eigenvalue whose real part is negative and large in magnitude\nC        compared to the reciprocal of the t span of interest.  If the\nC        problem is nonstiff, use method flag MF = 10.  If it is stiff,\nC        there are four standard choices for MF, and SLSODE requires the\nC        Jacobian matrix in some form.  This matrix is regarded either\nC        as full (MF = 21 or 22), or banded (MF = 24 or 25).  In the\nC        banded case, SLSODE requires two half-bandwidth parameters ML\nC        and MU. These are, respectively, the widths of the lower and\nC        upper parts of the band, excluding the main diagonal.  Thus the\nC        band consists of the locations (i,j) with\nC\nC           i - ML <= j <= i + MU ,\nC\nC        and the full bandwidth is ML + MU + 1 .\nC\nC     c. If the problem is stiff, you are encouraged to supply the\nC        Jacobian directly (MF = 21 or 24), but if this is not feasible,\nC        SLSODE will compute it internally by difference quotients (MF =\nC        22 or 25).  If you are supplying the Jacobian, write a\nC        subroutine of the form\nC\nC           SUBROUTINE  JAC (NEQ, T, Y, ML, MU, PD, NROWPD)\nC           INTEGER  NEQ, ML, MU, NRWOPD\nC           REAL T, Y(*), PD(NROWPD,*)\nC\nC        which provides df/dy by loading PD as follows:\nC        - For a full Jacobian (MF = 21), load PD(i,j) with df(i)/dy(j),\nC          the partial derivative of f(i) with respect to y(j).  (Ignore\nC          the ML and MU arguments in this case.)\nC        - For a banded Jacobian (MF = 24), load PD(i-j+MU+1,j) with\nC          df(i)/dy(j); i.e., load the diagonal lines of df/dy into the\nC          rows of PD from the top down.\nC        - In either case, only nonzero elements need be loaded.\nC\nC     d. Write a main program that calls subroutine SLSODE once for each\nC        point at which answers are desired.  This should also provide\nC        for possible use of logical unit 6 for output of error messages\nC        by SLSODE.\nC\nC        Before the first call to SLSODE, set ISTATE = 1, set Y and T to\nC        the initial values, and set TOUT to the first output point.  To\nC        continue the integration after a successful return, simply\nC        reset TOUT and call SLSODE again.  No other parameters need be\nC        reset.\nC\nC *Examples:\nC     The following is a simple example problem, with the coding needed\nC     for its solution by SLSODE. The problem is from chemical kinetics,\nC     and consists of the following three rate equations:\nC\nC        dy1/dt = -.04*y1 + 1.E4*y2*y3\nC        dy2/dt = .04*y1 - 1.E4*y2*y3 - 3.E7*y2**2\nC        dy3/dt = 3.E7*y2**2\nC\nC     on the interval from t = 0.0 to t = 4.E10, with initial conditions\nC     y1 = 1.0, y2 = y3 = 0. The problem is stiff.\nC\nC     The following coding solves this problem with SLSODE, using\nC     MF = 21 and printing results at t = .4, 4., ..., 4.E10.  It uses\nC     ITOL = 2 and ATOL much smaller for y2 than for y1 or y3 because y2\nC     has much smaller values.  At the end of the run, statistical\nC     quantities of interest are printed.\nC\nC        EXTERNAL  FEX, JEX\nC        INTEGER  IOPT, IOUT, ISTATE, ITASK, ITOL, IWORK(23), LIW, LRW,\nC       *         MF, NEQ\nC        REAL  ATOL(3), RTOL, RWORK(58), T, TOUT, Y(3)\nC        NEQ = 3\nC        Y(1) = 1.\nC        Y(2) = 0.\nC        Y(3) = 0.\nC        T = 0.\nC        TOUT = .4\nC        ITOL = 2\nC        RTOL = 1.E-4\nC        ATOL(1) = 1.E-6\nC        ATOL(2) = 1.E-10\nC        ATOL(3) = 1.E-6\nC        ITASK = 1\nC        ISTATE = 1\nC        IOPT = 0\nC        LRW = 58\nC        LIW = 23\nC        MF = 21\nC        DO 40 IOUT = 1,12\nC          CALL SLSODE (FEX, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK,\nC       *               ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JEX, MF)\nC          WRITE(6,20)  T, Y(1), Y(2), Y(3)\nC    20    FORMAT(' At t =',E12.4,'   y =',3E14.6)\nC          IF (ISTATE .LT. 0)  GO TO 80\nC    40    TOUT = TOUT*10.\nC        WRITE(6,60)  IWORK(11), IWORK(12), IWORK(13)\nC    60  FORMAT(/' No. steps =',i4,',  No. f-s =',i4,',  No. J-s =',i4)\nC        STOP\nC    80  WRITE(6,90)  ISTATE\nC    90  FORMAT(///' Error halt.. ISTATE =',I3)\nC        STOP\nC        END\nC\nC        SUBROUTINE  FEX (NEQ, T, Y, YDOT)\nC        INTEGER  NEQ\nC        REAL  T, Y(3), YDOT(3)\nC        YDOT(1) = -.04*Y(1) + 1.E4*Y(2)*Y(3)\nC        YDOT(3) = 3.E7*Y(2)*Y(2)\nC        YDOT(2) = -YDOT(1) - YDOT(3)\nC        RETURN\nC        END\nC\nC        SUBROUTINE  JEX (NEQ, T, Y, ML, MU, PD, NRPD)\nC        INTEGER  NEQ, ML, MU, NRPD\nC        REAL  T, Y(3), PD(NRPD,3)\nC        PD(1,1) = -.04\nC        PD(1,2) = 1.E4*Y(3)\nC        PD(1,3) = 1.E4*Y(2)\nC        PD(2,1) = .04\nC        PD(2,3) = -PD(1,3)\nC        PD(3,2) = 6.E7*Y(2)\nC        PD(2,2) = -PD(1,2) - PD(3,2)\nC        RETURN\nC        END\nC\nC     The output from this program (on a Cray-1 in single precision)\nC     is as follows.\nC\nC     At t =  4.0000e-01   y =  9.851726e-01  3.386406e-05  1.479357e-02\nC     At t =  4.0000e+00   y =  9.055142e-01  2.240418e-05  9.446344e-02\nC     At t =  4.0000e+01   y =  7.158050e-01  9.184616e-06  2.841858e-01\nC     At t =  4.0000e+02   y =  4.504846e-01  3.222434e-06  5.495122e-01\nC     At t =  4.0000e+03   y =  1.831701e-01  8.940379e-07  8.168290e-01\nC     At t =  4.0000e+04   y =  3.897016e-02  1.621193e-07  9.610297e-01\nC     At t =  4.0000e+05   y =  4.935213e-03  1.983756e-08  9.950648e-01\nC     At t =  4.0000e+06   y =  5.159269e-04  2.064759e-09  9.994841e-01\nC     At t =  4.0000e+07   y =  5.306413e-05  2.122677e-10  9.999469e-01\nC     At t =  4.0000e+08   y =  5.494530e-06  2.197825e-11  9.999945e-01\nC     At t =  4.0000e+09   y =  5.129458e-07  2.051784e-12  9.999995e-01\nC     At t =  4.0000e+10   y = -7.170603e-08 -2.868241e-13  1.000000e+00\nC\nC     No. steps = 330,  No. f-s = 405,  No. J-s = 69\nC\nC *Accuracy:\nC     The accuracy of the solution depends on the choice of tolerances\nC     RTOL and ATOL.  Actual (global) errors may exceed these local\nC     tolerances, so choose them conservatively.\nC\nC *Cautions:\nC     The work arrays should not be altered between calls to SLSODE for\nC     the same problem, except possibly for the conditional and optional\nC     inputs.\nC\nC *Portability:\nC     Since NEQ is dimensioned inside SLSODE, some compilers may object\nC     to a call to SLSODE with NEQ a scalar variable.  In this event,\nC     use DIMENSION NEQ(1).  Similar remarks apply to RTOL and ATOL.\nC\nC     Note to Cray users:\nC     For maximum efficiency, use the CFT77 compiler.  Appropriate\nC     compiler optimization directives have been inserted for CFT77.\nC\nC *Reference:\nC     Alan C. Hindmarsh, \"ODEPACK, A Systematized Collection of ODE\nC     Solvers,\" in Scientific Computing, R. S. Stepleman, et al., Eds.\nC     (North-Holland, Amsterdam, 1983), pp. 55-64.\nC\nC *Long Description:\nC     The following complete description of the user interface to\nC     SLSODE consists of four parts:\nC\nC     1.  The call sequence to subroutine SLSODE, which is a driver\nC         routine for the solver.  This includes descriptions of both\nC         the call sequence arguments and user-supplied routines.\nC         Following these descriptions is a description of optional\nC         inputs available through the call sequence, and then a\nC         description of optional outputs in the work arrays.\nC\nC     2.  Descriptions of other routines in the SLSODE package that may\nC         be (optionally) called by the user.  These provide the ability\nC         to alter error message handling, save and restore the internal\nC         COMMON, and obtain specified derivatives of the solution y(t).\nC\nC     3.  Descriptions of COMMON block to be declared in overlay or\nC         similar environments, or to be saved when doing an interrupt\nC         of the problem and continued solution later.\nC\nC     4.  Description of two routines in the SLSODE package, either of\nC         which the user may replace with his own version, if desired.\nC         These relate to the measurement of errors.\nC\nC\nC                         Part 1.  Call Sequence\nC                         ----------------------\nC\nC     Arguments\nC     ---------\nC     The call sequence parameters used for input only are\nC\nC        F, NEQ, TOUT, ITOL, RTOL, ATOL, ITASK, IOPT, LRW, LIW, JAC, MF,\nC\nC     and those used for both input and output are\nC\nC        Y, T, ISTATE.\nC\nC     The work arrays RWORK and IWORK are also used for conditional and\nC     optional inputs and optional outputs.  (The term output here\nC     refers to the return from subroutine SLSODE to the user's calling\nC     program.)\nC\nC     The legality of input parameters will be thoroughly checked on the\nC     initial call for the problem, but not checked thereafter unless a\nC     change in input parameters is flagged by ISTATE = 3 on input.\nC\nC     The descriptions of the call arguments are as follows.\nC\nC     F        The name of the user-supplied subroutine defining the ODE\nC              system.  The system must be put in the first-order form\nC              dy/dt = f(t,y), where f is a vector-valued function of\nC              the scalar t and the vector y. Subroutine F is to compute\nC              the function f. It is to have the form\nC\nC                 SUBROUTINE F (NEQ, T, Y, YDOT)\nC                 REAL T, Y(*), YDOT(*)\nC\nC              where NEQ, T, and Y are input, and the array YDOT =\nC              f(T,Y) is output.  Y and YDOT are arrays of length NEQ.\nC              Subroutine F should not alter Y(1),...,Y(NEQ).  F must be\nC              declared EXTERNAL in the calling program.\nC\nC              Subroutine F may access user-defined quantities in\nC              NEQ(2),... and/or in Y(NEQ(1)+1),..., if NEQ is an array\nC              (dimensioned in F) and/or Y has length exceeding NEQ(1).\nC              See the descriptions of NEQ and Y below.\nC\nC              If quantities computed in the F routine are needed\nC              externally to SLSODE, an extra call to F should be made\nC              for this purpose, for consistent and accurate results.\nC              If only the derivative dy/dt is needed, use SINTDY\nC              instead.\nC\nC     NEQ      The size of the ODE system (number of first-order\nC              ordinary differential equations).  Used only for input.\nC              NEQ may be decreased, but not increased, during the\nC              problem.  If NEQ is decreased (with ISTATE = 3 on input),\nC              the remaining components of Y should be left undisturbed,\nC              if these are to be accessed in F and/or JAC.\nC\nC              Normally, NEQ is a scalar, and it is generally referred\nC              to as a scalar in this user interface description.\nC              However, NEQ may be an array, with NEQ(1) set to the\nC              system size.  (The SLSODE package accesses only NEQ(1).)\nC              In either case, this parameter is passed as the NEQ\nC              argument in all calls to F and JAC.  Hence, if it is an\nC              array, locations NEQ(2),... may be used to store other\nC              integer data and pass it to F and/or JAC.  Subroutines\nC              F and/or JAC must include NEQ in a DIMENSION statement\nC              in that case.\nC\nC     Y        A real array for the vector of dependent variables, of\nC              length NEQ or more.  Used for both input and output on\nC              the first call (ISTATE = 1), and only for output on\nC              other calls.  On the first call, Y must contain the\nC              vector of initial values.  On output, Y contains the\nC              computed solution vector, evaluated at T. If desired,\nC              the Y array may be used for other purposes between\nC              calls to the solver.\nC\nC              This array is passed as the Y argument in all calls to F\nC              and JAC.  Hence its length may exceed NEQ, and locations\nC              Y(NEQ+1),... may be used to store other real data and\nC              pass it to F and/or JAC.  (The SLSODE package accesses\nC              only Y(1),...,Y(NEQ).)\nC\nC     T        The independent variable.  On input, T is used only on\nC              the first call, as the initial point of the integration.\nC              On output, after each call, T is the value at which a\nC              computed solution Y is evaluated (usually the same as\nC              TOUT).  On an error return, T is the farthest point\nC              reached.\nC\nC     TOUT     The next value of T at which a computed solution is\nC              desired.  Used only for input.\nC\nC              When starting the problem (ISTATE = 1), TOUT may be equal\nC              to T for one call, then should not equal T for the next\nC              call.  For the initial T, an input value of TOUT .NE. T\nC              is used in order to determine the direction of the\nC              integration (i.e., the algebraic sign of the step sizes)\nC              and the rough scale of the problem.  Integration in\nC              either direction (forward or backward in T) is permitted.\nC\nC              If ITASK = 2 or 5 (one-step modes), TOUT is ignored\nC              after the first call (i.e., the first call with\nC              TOUT .NE. T).  Otherwise, TOUT is required on every call.\nC\nC              If ITASK = 1, 3, or 4, the values of TOUT need not be\nC              monotone, but a value of TOUT which backs up is limited\nC              to the current internal T interval, whose endpoints are\nC              TCUR - HU and TCUR.  (See \"Optional Outputs\" below for\nC              TCUR and HU.)\nC\nC\nC     ITOL     An indicator for the type of error control.  See\nC              description below under ATOL.  Used only for input.\nC\nC     RTOL     A relative error tolerance parameter, either a scalar or\nC              an array of length NEQ.  See description below under\nC              ATOL.  Input only.\nC\nC     ATOL     An absolute error tolerance parameter, either a scalar or\nC              an array of length NEQ.  Input only.\nC\nC              The input parameters ITOL, RTOL, and ATOL determine the\nC              error control performed by the solver.  The solver will\nC              control the vector e = (e(i)) of estimated local errors\nC              in Y, according to an inequality of the form\nC\nC                 rms-norm of ( e(i)/EWT(i) ) <= 1,\nC\nC              where\nC\nC                 EWT(i) = RTOL(i)*ABS(Y(i)) + ATOL(i),\nC\nC              and the rms-norm (root-mean-square norm) here is\nC\nC                 rms-norm(v) = SQRT(sum v(i)**2 / NEQ).\nC\nC              Here EWT = (EWT(i)) is a vector of weights which must\nC              always be positive, and the values of RTOL and ATOL\nC              should all be nonnegative.  The following table gives the\nC              types (scalar/array) of RTOL and ATOL, and the\nC              corresponding form of EWT(i).\nC\nC              ITOL    RTOL      ATOL      EWT(i)\nC              ----    ------    ------    -----------------------------\nC              1       scalar    scalar    RTOL*ABS(Y(i)) + ATOL\nC              2       scalar    array     RTOL*ABS(Y(i)) + ATOL(i)\nC              3       array     scalar    RTOL(i)*ABS(Y(i)) + ATOL\nC              4       array     array     RTOL(i)*ABS(Y(i)) + ATOL(i)\nC\nC              When either of these parameters is a scalar, it need not\nC              be dimensioned in the user's calling program.\nC\nC              If none of the above choices (with ITOL, RTOL, and ATOL\nC              fixed throughout the problem) is suitable, more general\nC              error controls can be obtained by substituting\nC              user-supplied routines for the setting of EWT and/or for\nC              the norm calculation.  See Part 4 below.\nC\nC              If global errors are to be estimated by making a repeated\nC              run on the same problem with smaller tolerances, then all\nC              components of RTOL and ATOL (i.e., of EWT) should be\nC              scaled down uniformly.\nC\nC     ITASK    An index specifying the task to be performed.  Input\nC              only.  ITASK has the following values and meanings:\nC              1   Normal computation of output values of y(t) at\nC                  t = TOUT (by overshooting and interpolating).\nC              2   Take one step only and return.\nC              3   Stop at the first internal mesh point at or beyond\nC                  t = TOUT and return.\nC              4   Normal computation of output values of y(t) at\nC                  t = TOUT but without overshooting t = TCRIT.  TCRIT\nC                  must be input as RWORK(1).  TCRIT may be equal to or\nC                  beyond TOUT, but not behind it in the direction of\nC                  integration.  This option is useful if the problem\nC                  has a singularity at or beyond t = TCRIT.\nC              5   Take one step, without passing TCRIT, and return.\nC                  TCRIT must be input as RWORK(1).\nC\nC              Note:  If ITASK = 4 or 5 and the solver reaches TCRIT\nC              (within roundoff), it will return T = TCRIT (exactly) to\nC              indicate this (unless ITASK = 4 and TOUT comes before\nC              TCRIT, in which case answers at T = TOUT are returned\nC              first).\nC\nC     ISTATE   An index used for input and output to specify the state\nC              of the calculation.\nC\nC              On input, the values of ISTATE are as follows:\nC              1   This is the first call for the problem\nC                  (initializations will be done).  See \"Note\" below.\nC              2   This is not the first call, and the calculation is to\nC                  continue normally, with no change in any input\nC                  parameters except possibly TOUT and ITASK.  (If ITOL,\nC                  RTOL, and/or ATOL are changed between calls with\nC                  ISTATE = 2, the new values will be used but not\nC                  tested for legality.)\nC              3   This is not the first call, and the calculation is to\nC                  continue normally, but with a change in input\nC                  parameters other than TOUT and ITASK.  Changes are\nC                  allowed in NEQ, ITOL, RTOL, ATOL, IOPT, LRW, LIW, MF,\nC                  ML, MU, and any of the optional inputs except H0.\nC                  (See IWORK description for ML and MU.)\nC\nC              Note:  A preliminary call with TOUT = T is not counted as\nC              a first call here, as no initialization or checking of\nC              input is done.  (Such a call is sometimes useful for the\nC              purpose of outputting the initial conditions.)  Thus the\nC              first call for which TOUT .NE. T requires ISTATE = 1 on\nC              input.\nC\nC              On output, ISTATE has the following values and meanings:\nC               1  Nothing was done, as TOUT was equal to T with\nC                  ISTATE = 1 on input.\nC               2  The integration was performed successfully.\nC              -1  An excessive amount of work (more than MXSTEP steps)\nC                  was done on this call, before completing the\nC                  requested task, but the integration was otherwise\nC                  successful as far as T. (MXSTEP is an optional input\nC                  and is normally 500.)  To continue, the user may\nC                  simply reset ISTATE to a value >1 and call again (the\nC                  excess work step counter will be reset to 0).  In\nC                  addition, the user may increase MXSTEP to avoid this\nC                  error return; see \"Optional Inputs\" below.\nC              -2  Too much accuracy was requested for the precision of\nC                  the machine being used.  This was detected before\nC                  completing the requested task, but the integration\nC                  was successful as far as T. To continue, the\nC                  tolerance parameters must be reset, and ISTATE must\nC                  be set to 3. The optional output TOLSF may be used\nC                  for this purpose.  (Note:  If this condition is\nC                  detected before taking any steps, then an illegal\nC                  input return (ISTATE = -3) occurs instead.)\nC              -3  Illegal input was detected, before taking any\nC                  integration steps.  See written message for details.\nC                  (Note:  If the solver detects an infinite loop of\nC                  calls to the solver with illegal input, it will cause\nC                  the run to stop.)\nC              -4  There were repeated error-test failures on one\nC                  attempted step, before completing the requested task,\nC                  but the integration was successful as far as T.  The\nC                  problem may have a singularity, or the input may be\nC                  inappropriate.\nC              -5  There were repeated convergence-test failures on one\nC                  attempted step, before completing the requested task,\nC                  but the integration was successful as far as T. This\nC                  may be caused by an inaccurate Jacobian matrix, if\nC                  one is being used.\nC              -6  EWT(i) became zero for some i during the integration.\nC                  Pure relative error control (ATOL(i)=0.0) was\nC                  requested on a variable which has now vanished.  The\nC                  integration was successful as far as T.\nC\nC              Note:  Since the normal output value of ISTATE is 2, it\nC              does not need to be reset for normal continuation.  Also,\nC              since a negative input value of ISTATE will be regarded\nC              as illegal, a negative output value requires the user to\nC              change it, and possibly other inputs, before calling the\nC              solver again.\nC\nC     IOPT     An integer flag to specify whether any optional inputs\nC              are being used on this call.  Input only.  The optional\nC              inputs are listed under a separate heading below.\nC              0   No optional inputs are being used.  Default values\nC                  will be used in all cases.\nC              1   One or more optional inputs are being used.\nC\nC     RWORK    A real working array (single precision).  The length of\nC              RWORK must be at least\nC\nC                 20 + NYH*(MAXORD + 1) + 3*NEQ + LWM\nC\nC              where\nC                 NYH = the initial value of NEQ,\nC              MAXORD = 12 (if METH = 1) or 5 (if METH = 2) (unless a\nC                       smaller value is given as an optional input),\nC                 LWM = 0           if MITER = 0,\nC                 LWM = NEQ**2 + 2  if MITER = 1 or 2,\nC                 LWM = NEQ + 2     if MITER = 3, and\nC                 LWM = (2*ML + MU + 1)*NEQ + 2\nC                                   if MITER = 4 or 5.\nC              (See the MF description below for METH and MITER.)\nC\nC              Thus if MAXORD has its default value and NEQ is constant,\nC              this length is:\nC              20 + 16*NEQ                    for MF = 10,\nC              22 + 16*NEQ + NEQ**2           for MF = 11 or 12,\nC              22 + 17*NEQ                    for MF = 13,\nC              22 + 17*NEQ + (2*ML + MU)*NEQ  for MF = 14 or 15,\nC              20 +  9*NEQ                    for MF = 20,\nC              22 +  9*NEQ + NEQ**2           for MF = 21 or 22,\nC              22 + 10*NEQ                    for MF = 23,\nC              22 + 10*NEQ + (2*ML + MU)*NEQ  for MF = 24 or 25.\nC\nC              The first 20 words of RWORK are reserved for conditional\nC              and optional inputs and optional outputs.\nC\nC              The following word in RWORK is a conditional input:\nC              RWORK(1) = TCRIT, the critical value of t which the\nC                         solver is not to overshoot.  Required if ITASK\nC                         is 4 or 5, and ignored otherwise.  See ITASK.\nC\nC     LRW      The length of the array RWORK, as declared by the user.\nC              (This will be checked by the solver.)\nC\nC     IWORK    An integer work array.  Its length must be at least\nC              20       if MITER = 0 or 3 (MF = 10, 13, 20, 23), or\nC              20 + NEQ otherwise (MF = 11, 12, 14, 15, 21, 22, 24, 25).\nC              (See the MF description below for MITER.)  The first few\nC              words of IWORK are used for conditional and optional\nC              inputs and optional outputs.\nC\nC              The following two words in IWORK are conditional inputs:\nC              IWORK(1) = ML   These are the lower and upper half-\nC              IWORK(2) = MU   bandwidths, respectively, of the banded\nC                              Jacobian, excluding the main diagonal.\nC                         The band is defined by the matrix locations\nC                         (i,j) with i - ML <= j <= i + MU. ML and MU\nC                         must satisfy 0 <= ML,MU <= NEQ - 1. These are\nC                         required if MITER is 4 or 5, and ignored\nC                         otherwise.  ML and MU may in fact be the band\nC                         parameters for a matrix to which df/dy is only\nC                         approximately equal.\nC\nC     LIW      The length of the array IWORK, as declared by the user.\nC              (This will be checked by the solver.)\nC\nC     Note:  The work arrays must not be altered between calls to SLSODE\nC     for the same problem, except possibly for the conditional and\nC     optional inputs, and except for the last 3*NEQ words of RWORK.\nC     The latter space is used for internal scratch space, and so is\nC     available for use by the user outside SLSODE between calls, if\nC     desired (but not for use by F or JAC).\nC\nC     JAC      The name of the user-supplied routine (MITER = 1 or 4) to\nC              compute the Jacobian matrix, df/dy, as a function of the\nC              scalar t and the vector y.  (See the MF description below\nC              for MITER.)  It is to have the form\nC\nC                 SUBROUTINE JAC (NEQ, T, Y, ML, MU, PD, NROWPD)\nC                 REAL T, Y(*), PD(NROWPD,*)\nC\nC              where NEQ, T, Y, ML, MU, and NROWPD are input and the\nC              array PD is to be loaded with partial derivatives\nC              (elements of the Jacobian matrix) on output.  PD must be\nC              given a first dimension of NROWPD.  T and Y have the same\nC              meaning as in subroutine F.\nC\nC              In the full matrix case (MITER = 1), ML and MU are\nC              ignored, and the Jacobian is to be loaded into PD in\nC              columnwise manner, with df(i)/dy(j) loaded into PD(i,j).\nC\nC              In the band matrix case (MITER = 4), the elements within\nC              the band are to be loaded into PD in columnwise manner,\nC              with diagonal lines of df/dy loaded into the rows of PD.\nC              Thus df(i)/dy(j) is to be loaded into PD(i-j+MU+1,j).  ML\nC              and MU are the half-bandwidth parameters (see IWORK).\nC              The locations in PD in the two triangular areas which\nC              correspond to nonexistent matrix elements can be ignored\nC              or loaded arbitrarily, as they are overwritten by SLSODE.\nC\nC              JAC need not provide df/dy exactly. A crude approximation\nC              (possibly with a smaller bandwidth) will do.\nC\nC              In either case, PD is preset to zero by the solver, so\nC              that only the nonzero elements need be loaded by JAC.\nC              Each call to JAC is preceded by a call to F with the same\nC              arguments NEQ, T, and Y. Thus to gain some efficiency,\nC              intermediate quantities shared by both calculations may\nC              be saved in a user COMMON block by F and not recomputed\nC              by JAC, if desired.  Also, JAC may alter the Y array, if\nC              desired.  JAC must be declared EXTERNAL in the calling\nC              program.\nC\nC              Subroutine JAC may access user-defined quantities in\nC              NEQ(2),... and/or in Y(NEQ(1)+1),... if NEQ is an array\nC              (dimensioned in JAC) and/or Y has length exceeding\nC              NEQ(1).  See the descriptions of NEQ and Y above.\nC\nC     MF       The method flag.  Used only for input.  The legal values\nC              of MF are 10, 11, 12, 13, 14, 15, 20, 21, 22, 23, 24,\nC              and 25.  MF has decimal digits METH and MITER:\nC                 MF = 10*METH + MITER .\nC\nC              METH indicates the basic linear multistep method:\nC              1   Implicit Adams method.\nC              2   Method based on backward differentiation formulas\nC                  (BDF's).\nC\nC              MITER indicates the corrector iteration method:\nC              0   Functional iteration (no Jacobian matrix is\nC                  involved).\nC              1   Chord iteration with a user-supplied full (NEQ by\nC                  NEQ) Jacobian.\nC              2   Chord iteration with an internally generated\nC                  (difference quotient) full Jacobian (using NEQ\nC                  extra calls to F per df/dy value).\nC              3   Chord iteration with an internally generated\nC                  diagonal Jacobian approximation (using one extra call\nC                  to F per df/dy evaluation).\nC              4   Chord iteration with a user-supplied banded Jacobian.\nC              5   Chord iteration with an internally generated banded\nC                  Jacobian (using ML + MU + 1 extra calls to F per\nC                  df/dy evaluation).\nC\nC              If MITER = 1 or 4, the user must supply a subroutine JAC\nC              (the name is arbitrary) as described above under JAC.\nC              For other values of MITER, a dummy argument can be used.\nC\nC     Optional Inputs\nC     ---------------\nC     The following is a list of the optional inputs provided for in the\nC     call sequence.  (See also Part 2.)  For each such input variable,\nC     this table lists its name as used in this documentation, its\nC     location in the call sequence, its meaning, and the default value.\nC     The use of any of these inputs requires IOPT = 1, and in that case\nC     all of these inputs are examined.  A value of zero for any of\nC     these optional inputs will cause the default value to be used.\nC     Thus to use a subset of the optional inputs, simply preload\nC     locations 5 to 10 in RWORK and IWORK to 0.0 and 0 respectively,\nC     and then set those of interest to nonzero values.\nC\nC     Name    Location   Meaning and default value\nC     ------  ---------  -----------------------------------------------\nC     H0      RWORK(5)   Step size to be attempted on the first step.\nC                        The default value is determined by the solver.\nC     HMAX    RWORK(6)   Maximum absolute step size allowed.  The\nC                        default value is infinite.\nC     HMIN    RWORK(7)   Minimum absolute step size allowed.  The\nC                        default value is 0.  (This lower bound is not\nC                        enforced on the final step before reaching\nC                        TCRIT when ITASK = 4 or 5.)\nC     MAXORD  IWORK(5)   Maximum order to be allowed.  The default value\nC                        is 12 if METH = 1, and 5 if METH = 2. (See the\nC                        MF description above for METH.)  If MAXORD\nC                        exceeds the default value, it will be reduced\nC                        to the default value.  If MAXORD is changed\nC                        during the problem, it may cause the current\nC                        order to be reduced.\nC     MXSTEP  IWORK(6)   Maximum number of (internally defined) steps\nC                        allowed during one call to the solver.  The\nC                        default value is 500.\nC     MXHNIL  IWORK(7)   Maximum number of messages printed (per\nC                        problem) warning that T + H = T on a step\nC                        (H = step size).  This must be positive to\nC                        result in a nondefault value.  The default\nC                        value is 10.\nC\nC     Optional Outputs\nC     ----------------\nC     As optional additional output from SLSODE, the variables listed\nC     below are quantities related to the performance of SLSODE which\nC     are available to the user.  These are communicated by way of the\nC     work arrays, but also have internal mnemonic names as shown.\nC     Except where stated otherwise, all of these outputs are defined on\nC     any successful return from SLSODE, and on any return with ISTATE =\nC     -1, -2, -4, -5, or -6.  On an illegal input return (ISTATE = -3),\nC     they will be unchanged from their existing values (if any), except\nC     possibly for TOLSF, LENRW, and LENIW.  On any error return,\nC     outputs relevant to the error will be defined, as noted below.\nC\nC     Name   Location   Meaning\nC     -----  ---------  ------------------------------------------------\nC     HU     RWORK(11)  Step size in t last used (successfully).\nC     HCUR   RWORK(12)  Step size to be attempted on the next step.\nC     TCUR   RWORK(13)  Current value of the independent variable which\nC                       the solver has actually reached, i.e., the\nC                       current internal mesh point in t. On output,\nC                       TCUR will always be at least as far as the\nC                       argument T, but may be farther (if interpolation\nC                       was done).\nC     TOLSF  RWORK(14)  Tolerance scale factor, greater than 1.0,\nC                       computed when a request for too much accuracy\nC                       was detected (ISTATE = -3 if detected at the\nC                       start of the problem, ISTATE = -2 otherwise).\nC                       If ITOL is left unaltered but RTOL and ATOL are\nC                       uniformly scaled up by a factor of TOLSF for the\nC                       next call, then the solver is deemed likely to\nC                       succeed.  (The user may also ignore TOLSF and\nC                       alter the tolerance parameters in any other way\nC                       appropriate.)\nC     NST    IWORK(11)  Number of steps taken for the problem so far.\nC     NFE    IWORK(12)  Number of F evaluations for the problem so far.\nC     NJE    IWORK(13)  Number of Jacobian evaluations (and of matrix LU\nC                       decompositions) for the problem so far.\nC     NQU    IWORK(14)  Method order last used (successfully).\nC     NQCUR  IWORK(15)  Order to be attempted on the next step.\nC     IMXER  IWORK(16)  Index of the component of largest magnitude in\nC                       the weighted local error vector ( e(i)/EWT(i) ),\nC                       on an error return with ISTATE = -4 or -5.\nC     LENRW  IWORK(17)  Length of RWORK actually required.  This is\nC                       defined on normal returns and on an illegal\nC                       input return for insufficient storage.\nC     LENIW  IWORK(18)  Length of IWORK actually required.  This is\nC                       defined on normal returns and on an illegal\nC                       input return for insufficient storage.\nC\nC     The following two arrays are segments of the RWORK array which may\nC     also be of interest to the user as optional outputs.  For each\nC     array, the table below gives its internal name, its base address\nC     in RWORK, and its description.\nC\nC     Name  Base address  Description\nC     ----  ------------  ----------------------------------------------\nC     YH    21            The Nordsieck history array, of size NYH by\nC                         (NQCUR + 1), where NYH is the initial value of\nC                         NEQ.  For j = 0,1,...,NQCUR, column j + 1 of\nC                         YH contains HCUR**j/factorial(j) times the jth\nC                         derivative of the interpolating polynomial\nC                         currently representing the solution, evaluated\nC                         at t = TCUR.\nC     ACOR  LENRW-NEQ+1   Array of size NEQ used for the accumulated\nC                         corrections on each step, scaled on output to\nC                         represent the estimated local error in Y on\nC                         the last step.  This is the vector e in the\nC                         description of the error control.  It is\nC                         defined only on successful return from SLSODE.\nC\nC\nC                    Part 2.  Other Callable Routines\nC                    --------------------------------\nC\nC     The following are optional calls which the user may make to gain\nC     additional capabilities in conjunction with SLSODE.\nC\nC     Form of call              Function\nC     ------------------------  ----------------------------------------\nC     CALL XSETUN(LUN)          Set the logical unit number, LUN, for\nC                               output of messages from SLSODE, if the\nC                               default is not desired.  The default\nC                               value of LUN is 6. This call may be made\nC                               at any time and will take effect\nC                               immediately.\nC     CALL XSETF(MFLAG)         Set a flag to control the printing of\nC                               messages by SLSODE.  MFLAG = 0 means do\nC                               not print.  (Danger:  this risks losing\nC                               valuable information.)  MFLAG = 1 means\nC                               print (the default).  This call may be\nC                               made at any time and will take effect\nC                               immediately.\nC     CALL SSRCOM(RSAV,ISAV,JOB)  Saves and restores the contents of the\nC                               internal COMMON blocks used by SLSODE\nC                               (see Part 3 below).  RSAV must be a\nC                               real array of length 218 or more, and\nC                               ISAV must be an integer array of length\nC                               37 or more.  JOB = 1 means save COMMON\nC                               into RSAV/ISAV.  JOB = 2 means restore\nC                               COMMON from same.  SSRCOM is useful if\nC                               one is interrupting a run and restarting\nC                               later, or alternating between two or\nC                               more problems solved with SLSODE.\nC     CALL SINTDY(,,,,,)        Provide derivatives of y, of various\nC     (see below)               orders, at a specified point t, if\nC                               desired.  It may be called only after a\nC                               successful return from SLSODE.  Detailed\nC                               instructions follow.\nC\nC     Detailed instructions for using SINTDY\nC     --------------------------------------\nC     The form of the CALL is:\nC\nC           CALL SINTDY (T, K, RWORK(21), NYH, DKY, IFLAG)\nC\nC     The input parameters are:\nC\nC     T          Value of independent variable where answers are\nC                desired (normally the same as the T last returned by\nC                SLSODE).  For valid results, T must lie between\nC                TCUR - HU and TCUR.  (See \"Optional Outputs\" above\nC                for TCUR and HU.)\nC     K          Integer order of the derivative desired.  K must\nC                satisfy 0 <= K <= NQCUR, where NQCUR is the current\nC                order (see \"Optional Outputs\").  The capability\nC                corresponding to K = 0, i.e., computing y(t), is\nC                already provided by SLSODE directly.  Since\nC                NQCUR >= 1, the first derivative dy/dt is always\nC                available with SINTDY.\nC     RWORK(21)  The base address of the history array YH.\nC     NYH        Column length of YH, equal to the initial value of NEQ.\nC\nC     The output parameters are:\nC\nC     DKY        Real array of length NEQ containing the computed value\nC                of the Kth derivative of y(t).\nC     IFLAG      Integer flag, returned as 0 if K and T were legal,\nC                -1 if K was illegal, and -2 if T was illegal.\nC                On an error return, a message is also written.\nC\nC\nC                          Part 3.  Common Blocks\nC                          ----------------------\nC\nC     If SLSODE is to be used in an overlay situation, the user must\nC     declare, in the primary overlay, the variables in:\nC     (1) the call sequence to SLSODE,\nC     (2) the internal COMMON block /SLS001/, of length 255\nC         (218 single precision words followed by 37 integer words).\nC\nC     If SLSODE is used on a system in which the contents of internal\nC     COMMON blocks are not preserved between calls, the user should\nC     declare the above COMMON block in his main program to insure that\nC     its contents are preserved.\nC\nC     If the solution of a given problem by SLSODE is to be interrupted\nC     and then later continued, as when restarting an interrupted run or\nC     alternating between two or more problems, the user should save,\nC     following the return from the last SLSODE call prior to the\nC     interruption, the contents of the call sequence variables and the\nC     internal COMMON block, and later restore these values before the\nC     next SLSODE call for that problem.   In addition, if XSETUN and/or\nC     XSETF was called for non-default handling of error messages, then\nC     these calls must be repeated.  To save and restore the COMMON\nC     block, use subroutine SSRCOM (see Part 2 above).\nC\nC\nC              Part 4.  Optionally Replaceable Solver Routines\nC              -----------------------------------------------\nC\nC     Below are descriptions of two routines in the SLSODE package which\nC     relate to the measurement of errors.  Either routine can be\nC     replaced by a user-supplied version, if desired.  However, since\nC     such a replacement may have a major impact on performance, it\nC     should be done only when absolutely necessary, and only with great\nC     caution.  (Note:  The means by which the package version of a\nC     routine is superseded by the user's version may be system-\nC     dependent.)\nC\nC     SEWSET\nC     ------\nC     The following subroutine is called just before each internal\nC     integration step, and sets the array of error weights, EWT, as\nC     described under ITOL/RTOL/ATOL above:\nC\nC           SUBROUTINE SEWSET (NEQ, ITOL, RTOL, ATOL, YCUR, EWT)\nC\nC     where NEQ, ITOL, RTOL, and ATOL are as in the SLSODE call\nC     sequence, YCUR contains the current dependent variable vector,\nC     and EWT is the array of weights set by SEWSET.\nC\nC     If the user supplies this subroutine, it must return in EWT(i)\nC     (i = 1,...,NEQ) a positive quantity suitable for comparing errors\nC     in Y(i) to.  The EWT array returned by SEWSET is passed to the\nC     SVNORM routine (see below), and also used by SLSODE in the\nC     computation of the optional output IMXER, the diagonal Jacobian\nC     approximation, and the increments for difference quotient\nC     Jacobians.\nC\nC     In the user-supplied version of SEWSET, it may be desirable to use\nC     the current values of derivatives of y. Derivatives up to order NQ\nC     are available from the history array YH, described above under\nC     optional outputs.  In SEWSET, YH is identical to the YCUR array,\nC     extended to NQ + 1 columns with a column length of NYH and scale\nC     factors of H**j/factorial(j).  On the first call for the problem,\nC     given by NST = 0, NQ is 1 and H is temporarily set to 1.0.\nC     NYH is the initial value of NEQ.  The quantities NQ, H, and NST\nC     can be obtained by including in SEWSET the statements:\nC           REAL RLS\nC           COMMON /SLS001/ RLS(218),ILS(37)\nC           NQ = ILS(33)\nC           NST = ILS(34)\nC           H = RLS(212)\nC     Thus, for example, the current value of dy/dt can be obtained as\nC     YCUR(NYH+i)/H (i=1,...,NEQ) (and the division by H is unnecessary\nC     when NST = 0).\nC\nC     SVNORM\nC     ------\nC     SVNORM is a real function routine which computes the weighted\nC     root-mean-square norm of a vector v:\nC\nC        d = SVNORM (n, v, w)\nC\nC     where:\nC     n = the length of the vector,\nC     v = real array of length n containing the vector,\nC     w = real array of length n containing weights,\nC     d = SQRT( (1/n) * sum(v(i)*w(i))**2 ).\nC\nC     SVNORM is called with n = NEQ and with w(i) = 1.0/EWT(i), where\nC     EWT is as set by subroutine SEWSET.\nC\nC     If the user supplies this function, it should return a nonnegative\nC     value of SVNORM suitable for use in the error control in SLSODE.\nC     None of the arguments should be altered by SVNORM.  For example, a\nC     user-supplied SVNORM routine might:\nC     - Substitute a max-norm of (v(i)*w(i)) for the rms-norm, or\nC     - Ignore some components of v in the norm, with the effect of\nC       suppressing the error control on those components of Y.\nC  ---------------------------------------------------------------------\nC***ROUTINES CALLED  SEWSET, SINTDY, R1MACH, SSTODE, SVNORM, XERRWV\nC***COMMON BLOCKS    SLS001\nC***REVISION HISTORY  (YYYYMMDD)\nC 19791129  DATE WRITTEN\nC 19791213  Minor changes to declarations; DELP init. in STODE.\nC 19800118  Treat NEQ as array; integer declarations added throughout;\nC           minor changes to prologue.\nC 19800306  Corrected TESCO(1,NQP1) setting in CFODE.\nC 19800519  Corrected access of YH on forced order reduction;\nC           numerous corrections to prologues and other comments.\nC 19800617  In main driver, added loading of SQRT(UROUND) in RWORK;\nC           minor corrections to main prologue.\nC 19800923  Added zero initialization of HU and NQU.\nC 19801218  Revised XERRWV routine; minor corrections to main prologue.\nC 19810401  Minor changes to comments and an error message.\nC 19810814  Numerous revisions: replaced EWT by 1/EWT; used flags\nC           JCUR, ICF, IERPJ, IERSL between STODE and subordinates;\nC           added tuning parameters CCMAX, MAXCOR, MSBP, MXNCF;\nC           reorganized returns from STODE; reorganized type decls.;\nC           fixed message length in XERRWV; changed default LUNIT to 6;\nC           changed Common lengths; changed comments throughout.\nC 19870330  Major update by ACH: corrected comments throughout;\nC           removed TRET from Common; rewrote EWSET with 4 loops;\nC           fixed t test in INTDY; added Cray directives in STODE;\nC           in STODE, fixed DELP init. and logic around PJAC call;\nC           combined routines to save/restore Common;\nC           passed LEVEL = 0 in error message calls (except run abort).\nC 19890426  Modified prologue to SLATEC/LDOC format.  (FNF)\nC 19890501  Many improvements to prologue.  (FNF)\nC 19890503  A few final corrections to prologue.  (FNF)\nC 19890504  Minor cosmetic changes.  (FNF)\nC 19890510  Corrected description of Y in Arguments section.  (FNF)\nC 19890517  Minor corrections to prologue.  (FNF)\nC 19920514  Updated with prologue edited 891025 by G. Shaw for manual.\nC 19920515  Converted source lines to upper case.  (FNF)\nC 19920603  Revised XERRWV calls using mixed upper-lower case.  (ACH)\nC 19920616  Revised prologue comment regarding CFT.  (ACH)\nC 19921116  Revised prologue comments regarding Common.  (ACH).\nC 19930326  Added comment about non-reentrancy.  (FNF)\nC 19930723  Changed R1MACH to RUMACH. (FNF)\nC 19930801  Removed ILLIN and NTREP from Common (affects driver logic);\nC           minor changes to prologue and internal comments;\nC           changed Hollerith strings to quoted strings;\nC           changed internal comments to mixed case;\nC           replaced XERRWV with new version using character type;\nC           changed dummy dimensions from 1 to *. (ACH)\nC 19930809  Changed to generic intrinsic names; changed names of\nC           subprograms and Common blocks to SLSODE etc. (ACH)\nC 19930929  Eliminated use of REAL intrinsic; other minor changes. (ACH)\nC 20010412  Removed all 'own' variables from Common block /SLS001/\nC           (affects declarations in 6 routines). (ACH)\nC 20010509  Minor corrections to prologue. (ACH)\nC 20031105  Restored 'own' variables to Common block /SLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC 20031112  Added SAVE statements for data-loaded constants.\nC\nC***  END PROLOGUE  SLSODE\nC\nC*Internal Notes:\nC\nC Other Routines in the SLSODE Package.\nC\nC In addition to Subroutine SLSODE, the SLSODE package includes the\nC following subroutines and function routines:\nC  SINTDY   computes an interpolated value of the y vector at t = TOUT.\nC  SSTODE   is the core integrator, which does one step of the\nC           integration and the associated error control.\nC  SCFODE   sets all method coefficients and test constants.\nC  SPREPJ   computes and preprocesses the Jacobian matrix J = df/dy\nC           and the Newton iteration matrix P = I - h*l0*J.\nC  SSOLSY   manages solution of linear system in chord iteration.\nC  SEWSET   sets the error weight vector EWT before each step.\nC  SVNORM   computes the weighted R.M.S. norm of a vector.\nC  SSRCOM   is a user-callable routine to save and restore\nC           the contents of the internal Common block.\nC  DGETRF AND DGETRS   ARE ROUTINES FROM LAPACK FOR SOLVING FULL\nC           SYSTEMS OF LINEAR ALGEBRAIC EQUATIONS.\nC  DGBTRF AND DGBTRS   ARE ROUTINES FROM LAPACK FOR SOLVING BANDED\nC           LINEAR SYSTEMS.\nC  R1MACH   computes the unit roundoff in a machine-independent manner.\nC  XERRWV, XSETUN, XSETF, IXSAV, IUMACH   handle the printing of all\nC           error messages and warnings.  XERRWV is machine-dependent.\nC Note: SVNORM, R1MACH, IXSAV, and IUMACH are function routines.\nC All the others are subroutines.\nC\nC**End\nC\nC  Declare externals.\n      EXTERNAL SPREPJ, SSOLSY\n      REAL R1MACH, SVNORM\nC\nC  Declare all other variables.\n      INTEGER INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, NYH,\n     1   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     1   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     2   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     3   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, I1, I2, IFLAG, IMXER, KGO, LF0,\n     1   LENIW, LENRW, LENWM, ML, MORD, MU, MXHNL0, MXSTP0\n      REAL CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      REAL ATOLI, AYI, BIG, EWTI, H0, HMAX, HMX, RH, RTOLI,\n     1   TCRIT, TDIST, TNEXT, TOL, TOLSF, TP, SIZE, SUM, W0\n      DIMENSION MORD(2)\n      LOGICAL IHIT\n      CHARACTER*80 MSG\n      SAVE MORD, MXSTP0, MXHNL0\nC-----------------------------------------------------------------------\nC The following internal Common block contains\nC (a) variables which are local to any subroutine but whose values must\nC     be preserved between calls to the routine (\"own\" variables), and\nC (b) variables which are communicated between subroutines.\nC The block SLS001 is declared in subroutines SLSODE, SINTDY, SSTODE,\nC SPREPJ, and SSOLSY.\nC Groups of variables are replaced by dummy arrays in the Common\nC declarations in routines where those variables are not used.\nC-----------------------------------------------------------------------\n      COMMON /SLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, NYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     3   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     4   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\nC\n      DATA  MORD(1),MORD(2)/12,5/, MXSTP0/500/, MXHNL0/10/\nC-----------------------------------------------------------------------\nC Block A.\nC This code block is executed on every call.\nC It tests ISTATE and ITASK for legality and branches appropriately.\nC If ISTATE .GT. 1 but the flag INIT shows that initialization has\nC not yet been done, an error return occurs.\nC If ISTATE = 1 and TOUT = T, return immediately.\nC-----------------------------------------------------------------------\nC\nC***FIRST EXECUTABLE STATEMENT  SLSODE\n      IF (ISTATE .LT. 1 .OR. ISTATE .GT. 3) GO TO 601\n      IF (ITASK .LT. 1 .OR. ITASK .GT. 5) GO TO 602\n      IF (ISTATE .EQ. 1) GO TO 10\n      IF (INIT .EQ. 0) GO TO 603\n      IF (ISTATE .EQ. 2) GO TO 200\n      GO TO 20\n 10   INIT = 0\n      IF (TOUT .EQ. T) RETURN\nC-----------------------------------------------------------------------\nC Block B.\nC The next code block is executed for the initial call (ISTATE = 1),\nC or for a continuation call with parameter changes (ISTATE = 3).\nC It contains checking of all inputs and various initializations.\nC\nC First check legality of the non-optional inputs NEQ, ITOL, IOPT,\nC MF, ML, and MU.\nC-----------------------------------------------------------------------\n 20   IF (NEQ(1) .LE. 0) GO TO 604\n      IF (ISTATE .EQ. 1) GO TO 25\n      IF (NEQ(1) .GT. N) GO TO 605\n 25   N = NEQ(1)\n      IF (ITOL .LT. 1 .OR. ITOL .GT. 4) GO TO 606\n      IF (IOPT .LT. 0 .OR. IOPT .GT. 1) GO TO 607\n      METH = MF/10\n      MITER = MF - 10*METH\n      IF (METH .LT. 1 .OR. METH .GT. 2) GO TO 608\n      IF (MITER .LT. 0 .OR. MITER .GT. 5) GO TO 608\n      IF (MITER .LE. 3) GO TO 30\n      ML = IWORK(1)\n      MU = IWORK(2)\n      IF (ML .LT. 0 .OR. ML .GE. N) GO TO 609\n      IF (MU .LT. 0 .OR. MU .GE. N) GO TO 610\n 30   CONTINUE\nC Next process and check the optional inputs. --------------------------\n      IF (IOPT .EQ. 1) GO TO 40\n      MAXORD = MORD(METH)\n      MXSTEP = MXSTP0\n      MXHNIL = MXHNL0\n      IF (ISTATE .EQ. 1) H0 = 0.0E0\n      HMXI = 0.0E0\n      HMIN = 0.0E0\n      GO TO 60\n 40   MAXORD = IWORK(5)\n      IF (MAXORD .LT. 0) GO TO 611\n      IF (MAXORD .EQ. 0) MAXORD = 100\n      MAXORD = MIN(MAXORD,MORD(METH))\n      MXSTEP = IWORK(6)\n      IF (MXSTEP .LT. 0) GO TO 612\n      IF (MXSTEP .EQ. 0) MXSTEP = MXSTP0\n      MXHNIL = IWORK(7)\n      IF (MXHNIL .LT. 0) GO TO 613\n      IF (MXHNIL .EQ. 0) MXHNIL = MXHNL0\n      IF (ISTATE .NE. 1) GO TO 50\n      H0 = RWORK(5)\n      IF ((TOUT - T)*H0 .LT. 0.0E0) GO TO 614\n 50   HMAX = RWORK(6)\n      IF (HMAX .LT. 0.0E0) GO TO 615\n      HMXI = 0.0E0\n      IF (HMAX .GT. 0.0E0) HMXI = 1.0E0/HMAX\n      HMIN = RWORK(7)\n      IF (HMIN .LT. 0.0E0) GO TO 616\nC-----------------------------------------------------------------------\nC Set work array pointers and check lengths LRW and LIW.\nC Pointers to segments of RWORK and IWORK are named by prefixing L to\nC the name of the segment.  E.g., the segment YH starts at RWORK(LYH).\nC Segments of RWORK (in order) are denoted  YH, WM, EWT, SAVF, ACOR.\nC-----------------------------------------------------------------------\n 60   LYH = 21\n      IF (ISTATE .EQ. 1) NYH = N\n      LWM = LYH + (MAXORD + 1)*NYH\n      IF (MITER .EQ. 0) LENWM = 0\n      IF (MITER .EQ. 1 .OR. MITER .EQ. 2) LENWM = N*N + 2\n      IF (MITER .EQ. 3) LENWM = N + 2\n      IF (MITER .GE. 4) LENWM = (2*ML + MU + 1)*N + 2\n      LEWT = LWM + LENWM\n      LSAVF = LEWT + N\n      LACOR = LSAVF + N\n      LENRW = LACOR + N - 1\n      IWORK(17) = LENRW\n      LIWM = 1\n      LENIW = 20 + N\n      IF (MITER .EQ. 0 .OR. MITER .EQ. 3) LENIW = 20\n      IWORK(18) = LENIW\n      IF (LENRW .GT. LRW) GO TO 617\n      IF (LENIW .GT. LIW) GO TO 618\nC Check RTOL and ATOL for legality. ------------------------------------\n      RTOLI = RTOL(1)\n      ATOLI = ATOL(1)\n      DO 70 I = 1,N\n        IF (ITOL .GE. 3) RTOLI = RTOL(I)\n        IF (ITOL .EQ. 2 .OR. ITOL .EQ. 4) ATOLI = ATOL(I)\n        IF (RTOLI .LT. 0.0E0) GO TO 619\n        IF (ATOLI .LT. 0.0E0) GO TO 620\n 70     CONTINUE\n      IF (ISTATE .EQ. 1) GO TO 100\nC If ISTATE = 3, set flag to signal parameter changes to SSTODE. -------\n      JSTART = -1\n      IF (NQ .LE. MAXORD) GO TO 90\nC MAXORD was reduced below NQ.  Copy YH(*,MAXORD+2) into SAVF. ---------\n      DO 80 I = 1,N\n 80     RWORK(I+LSAVF-1) = RWORK(I+LWM-1)\nC Reload WM(1) = RWORK(LWM), since LWM may have changed. ---------------\n 90   IF (MITER .GT. 0) RWORK(LWM) = SQRT(UROUND)\n      IF (N .EQ. NYH) GO TO 200\nC NEQ was reduced.  Zero part of YH to avoid undefined references. -----\n      I1 = LYH + L*NYH\n      I2 = LYH + (MAXORD + 1)*NYH - 1\n      IF (I1 .GT. I2) GO TO 200\n      DO 95 I = I1,I2\n 95     RWORK(I) = 0.0E0\n      GO TO 200\nC-----------------------------------------------------------------------\nC Block C.\nC The next block is for the initial call only (ISTATE = 1).\nC It contains all remaining initializations, the initial call to F,\nC and the calculation of the initial step size.\nC The error weights in EWT are inverted after being loaded.\nC-----------------------------------------------------------------------\n 100  UROUND = R1MACH(4)\n      TN = T\n      IF (ITASK .NE. 4 .AND. ITASK .NE. 5) GO TO 110\n      TCRIT = RWORK(1)\n      IF ((TCRIT - TOUT)*(TOUT - T) .LT. 0.0E0) GO TO 625\n      IF (H0 .NE. 0.0E0 .AND. (T + H0 - TCRIT)*H0 .GT. 0.0E0)\n     1   H0 = TCRIT - T\n 110  JSTART = 0\n      IF (MITER .GT. 0) RWORK(LWM) = SQRT(UROUND)\n      NHNIL = 0\n      NST = 0\n      NJE = 0\n      NSLAST = 0\n      HU = 0.0E0\n      NQU = 0\n      CCMAX = 0.3E0\n      MAXCOR = 3\n      MSBP = 20\n      MXNCF = 10\nC Initial call to F.  (LF0 points to YH(*,2).) -------------------------\n      LF0 = LYH + NYH\n      CALL F (NEQ, T, Y, RWORK(LF0))\n      NFE = 1\nC Load the initial value vector in YH. ---------------------------------\n      DO 115 I = 1,N\n 115    RWORK(I+LYH-1) = Y(I)\nC Load and invert the EWT array.  (H is temporarily set to 1.0.) -------\n      NQ = 1\n      H = 1.0E0\n      CALL SEWSET (N, ITOL, RTOL, ATOL, RWORK(LYH), RWORK(LEWT))\n      DO 120 I = 1,N\n        IF (RWORK(I+LEWT-1) .LE. 0.0E0) GO TO 621\n 120    RWORK(I+LEWT-1) = 1.0E0/RWORK(I+LEWT-1)\nC-----------------------------------------------------------------------\nC The coding below computes the step size, H0, to be attempted on the\nC first step, unless the user has supplied a value for this.\nC First check that TOUT - T differs significantly from zero.\nC A scalar tolerance quantity TOL is computed, as MAX(RTOL(I))\nC if this is positive, or MAX(ATOL(I)/ABS(Y(I))) otherwise, adjusted\nC so as to be between 100*UROUND and 1.0E-3.\nC Then the computed value H0 is given by..\nC                                      NEQ\nC   H0**2 = TOL / ( w0**-2 + (1/NEQ) * SUM ( f(i)/ywt(i) )**2  )\nC                                       1\nC where   w0     = MAX ( ABS(T), ABS(TOUT) ),\nC         f(i)   = i-th component of initial value of f,\nC         ywt(i) = EWT(i)/TOL  (a weight for y(i)).\nC The sign of H0 is inferred from the initial values of TOUT and T.\nC-----------------------------------------------------------------------\n      IF (H0 .NE. 0.0E0) GO TO 180\n      TDIST = ABS(TOUT - T)\n      W0 = MAX(ABS(T),ABS(TOUT))\n      IF (TDIST .LT. 2.0E0*UROUND*W0) GO TO 622\n      TOL = RTOL(1)\n      IF (ITOL .LE. 2) GO TO 140\n      DO 130 I = 1,N\n 130    TOL = MAX(TOL,RTOL(I))\n 140  IF (TOL .GT. 0.0E0) GO TO 160\n      ATOLI = ATOL(1)\n      DO 150 I = 1,N\n        IF (ITOL .EQ. 2 .OR. ITOL .EQ. 4) ATOLI = ATOL(I)\n        AYI = ABS(Y(I))\n        IF (AYI .NE. 0.0E0) TOL = MAX(TOL,ATOLI/AYI)\n 150    CONTINUE\n 160  TOL = MAX(TOL,100.0E0*UROUND)\n      TOL = MIN(TOL,0.001E0)\n      SUM = SVNORM (N, RWORK(LF0), RWORK(LEWT))\n      SUM = 1.0E0/(TOL*W0*W0) + TOL*SUM**2\n      H0 = 1.0E0/SQRT(SUM)\n      H0 = MIN(H0,TDIST)\n      H0 = SIGN(H0,TOUT-T)\nC Adjust H0 if necessary to meet HMAX bound. ---------------------------\n 180  RH = ABS(H0)*HMXI\n      IF (RH .GT. 1.0E0) H0 = H0/RH\nC Load H with H0 and scale YH(*,2) by H0. ------------------------------\n      H = H0\n      DO 190 I = 1,N\n 190    RWORK(I+LF0-1) = H0*RWORK(I+LF0-1)\n      GO TO 270\nC-----------------------------------------------------------------------\nC Block D.\nC The next code block is for continuation calls only (ISTATE = 2 or 3)\nC and is to check stop conditions before taking a step.\nC-----------------------------------------------------------------------\n 200  NSLAST = NST\n      GO TO (210, 250, 220, 230, 240), ITASK\n 210  IF ((TN - TOUT)*H .LT. 0.0E0) GO TO 250\n      CALL SINTDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG)\n      IF (IFLAG .NE. 0) GO TO 627\n      T = TOUT\n      GO TO 420\n 220  TP = TN - HU*(1.0E0 + 100.0E0*UROUND)\n      IF ((TP - TOUT)*H .GT. 0.0E0) GO TO 623\n      IF ((TN - TOUT)*H .LT. 0.0E0) GO TO 250\n      GO TO 400\n 230  TCRIT = RWORK(1)\n      IF ((TN - TCRIT)*H .GT. 0.0E0) GO TO 624\n      IF ((TCRIT - TOUT)*H .LT. 0.0E0) GO TO 625\n      IF ((TN - TOUT)*H .LT. 0.0E0) GO TO 245\n      CALL SINTDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG)\n      IF (IFLAG .NE. 0) GO TO 627\n      T = TOUT\n      GO TO 420\n 240  TCRIT = RWORK(1)\n      IF ((TN - TCRIT)*H .GT. 0.0E0) GO TO 624\n 245  HMX = ABS(TN) + ABS(H)\n      IHIT = ABS(TN - TCRIT) .LE. 100.0E0*UROUND*HMX\n      IF (IHIT) GO TO 400\n      TNEXT = TN + H*(1.0E0 + 4.0E0*UROUND)\n      IF ((TNEXT - TCRIT)*H .LE. 0.0E0) GO TO 250\n      H = (TCRIT - TN)*(1.0E0 - 4.0E0*UROUND)\n      IF (ISTATE .EQ. 2) JSTART = -2\nC-----------------------------------------------------------------------\nC Block E.\nC The next block is normally executed for all calls and contains\nC the call to the one-step core integrator SSTODE.\nC\nC This is a looping point for the integration steps.\nC\nC First check for too many steps being taken, update EWT (if not at\nC start of problem), check for too much accuracy being requested, and\nC check for H below the roundoff level in T.\nC-----------------------------------------------------------------------\n 250  CONTINUE\n      IF ((NST-NSLAST) .GE. MXSTEP) GO TO 500\n      CALL SEWSET (N, ITOL, RTOL, ATOL, RWORK(LYH), RWORK(LEWT))\n      DO 260 I = 1,N\n        IF (RWORK(I+LEWT-1) .LE. 0.0E0) GO TO 510\n 260    RWORK(I+LEWT-1) = 1.0E0/RWORK(I+LEWT-1)\n 270  TOLSF = UROUND*SVNORM (N, RWORK(LYH), RWORK(LEWT))\n      IF (TOLSF .LE. 1.0E0) GO TO 280\n      TOLSF = TOLSF*2.0E0\n      IF (NST .EQ. 0) GO TO 626\n      GO TO 520\n 280  IF ((TN + H) .NE. TN) GO TO 290\n      NHNIL = NHNIL + 1\n      IF (NHNIL .GT. MXHNIL) GO TO 290\n      MSG = 'SLSODE-  Warning..internal T (=R1) and H (=R2) are'\n      CALL XERRWV (MSG, 50, 101, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      MSG='      such that in the machine, T + H = T on the next step  '\n      CALL XERRWV (MSG, 60, 101, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      MSG = '      (H = step size). Solver will continue anyway'\n      CALL XERRWV (MSG, 50, 101, 0, 0, 0, 0, 2, TN, H)\n      IF (NHNIL .LT. MXHNIL) GO TO 290\n      MSG = 'SLSODE-  Above warning has been issued I1 times.  '\n      CALL XERRWV (MSG, 50, 102, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      MSG = '      It will not be issued again for this problem'\n      CALL XERRWV (MSG, 50, 102, 0, 1, MXHNIL, 0, 0, 0.0E0, 0.0E0)\n 290  CONTINUE\nC-----------------------------------------------------------------------\nC  CALL SSTODE(NEQ,Y,YH,NYH,YH,EWT,SAVF,ACOR,WM,IWM,F,JAC,SPREPJ,SSOLSY)\nC-----------------------------------------------------------------------\n      CALL SSTODE (NEQ, Y, RWORK(LYH), NYH, RWORK(LYH), RWORK(LEWT),\n     1   RWORK(LSAVF), RWORK(LACOR), RWORK(LWM), IWORK(LIWM),\n     2   F, JAC, SPREPJ, SSOLSY)\n      KGO = 1 - KFLAG\n      GO TO (300, 530, 540), KGO\nC-----------------------------------------------------------------------\nC Block F.\nC The following block handles the case of a successful return from the\nC core integrator (KFLAG = 0).  Test for stop conditions.\nC-----------------------------------------------------------------------\n 300  INIT = 1\n      GO TO (310, 400, 330, 340, 350), ITASK\nC ITASK = 1.  If TOUT has been reached, interpolate. -------------------\n 310  IF ((TN - TOUT)*H .LT. 0.0E0) GO TO 250\n      CALL SINTDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG)\n      T = TOUT\n      GO TO 420\nC ITASK = 3.  Jump to exit if TOUT was reached. ------------------------\n 330  IF ((TN - TOUT)*H .GE. 0.0E0) GO TO 400\n      GO TO 250\nC ITASK = 4.  See if TOUT or TCRIT was reached.  Adjust H if necessary.\n 340  IF ((TN - TOUT)*H .LT. 0.0E0) GO TO 345\n      CALL SINTDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG)\n      T = TOUT\n      GO TO 420\n 345  HMX = ABS(TN) + ABS(H)\n      IHIT = ABS(TN - TCRIT) .LE. 100.0E0*UROUND*HMX\n      IF (IHIT) GO TO 400\n      TNEXT = TN + H*(1.0E0 + 4.0E0*UROUND)\n      IF ((TNEXT - TCRIT)*H .LE. 0.0E0) GO TO 250\n      H = (TCRIT - TN)*(1.0E0 - 4.0E0*UROUND)\n      JSTART = -2\n      GO TO 250\nC ITASK = 5.  See if TCRIT was reached and jump to exit. ---------------\n 350  HMX = ABS(TN) + ABS(H)\n      IHIT = ABS(TN - TCRIT) .LE. 100.0E0*UROUND*HMX\nC-----------------------------------------------------------------------\nC Block G.\nC The following block handles all successful returns from SLSODE.\nC If ITASK .NE. 1, Y is loaded from YH and T is set accordingly.\nC ISTATE is set to 2, and the optional outputs are loaded into the\nC work arrays before returning.\nC-----------------------------------------------------------------------\n 400  DO 410 I = 1,N\n 410    Y(I) = RWORK(I+LYH-1)\n      T = TN\n      IF (ITASK .NE. 4 .AND. ITASK .NE. 5) GO TO 420\n      IF (IHIT) T = TCRIT\n 420  ISTATE = 2\n      RWORK(11) = HU\n      RWORK(12) = H\n      RWORK(13) = TN\n      IWORK(11) = NST\n      IWORK(12) = NFE\n      IWORK(13) = NJE\n      IWORK(14) = NQU\n      IWORK(15) = NQ\n      RETURN\nC-----------------------------------------------------------------------\nC Block H.\nC The following block handles all unsuccessful returns other than\nC those for illegal input.  First the error message routine is called.\nC If there was an error test or convergence test failure, IMXER is set.\nC Then Y is loaded from YH and T is set to TN.  The optional outputs\nC are loaded into the work arrays before returning.\nC-----------------------------------------------------------------------\nC The maximum number of steps was taken before reaching TOUT. ----------\n 500  MSG = 'SLSODE-  At current T (=R1), MXSTEP (=I1) steps   '\n      CALL XERRWV (MSG, 50, 201, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      MSG = '      taken on this call before reaching TOUT     '\n      CALL XERRWV (MSG, 50, 201, 0, 1, MXSTEP, 0, 1, TN, 0.0E0)\n      ISTATE = -1\n      GO TO 580\nC EWT(I) .LE. 0.0 for some I (not at start of problem). ----------------\n 510  EWTI = RWORK(LEWT+I-1)\n      MSG = 'SLSODE-  At T (=R1), EWT(I1) has become R2 .LE. 0.'\n      CALL XERRWV (MSG, 50, 202, 0, 1, I, 0, 2, TN, EWTI)\n      ISTATE = -6\n      GO TO 580\nC Too much accuracy requested for machine precision. -------------------\n 520  MSG = 'SLSODE-  At T (=R1), too much accuracy requested  '\n      CALL XERRWV (MSG, 50, 203, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      MSG = '      for precision of machine..  see TOLSF (=R2) '\n      CALL XERRWV (MSG, 50, 203, 0, 0, 0, 0, 2, TN, TOLSF)\n      RWORK(14) = TOLSF\n      ISTATE = -2\n      GO TO 580\nC KFLAG = -1.  Error test failed repeatedly or with ABS(H) = HMIN. -----\n 530  MSG = 'SLSODE-  At T(=R1) and step size H(=R2), the error'\n      CALL XERRWV (MSG, 50, 204, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      MSG = '      test failed repeatedly or with ABS(H) = HMIN'\n      CALL XERRWV (MSG, 50, 204, 0, 0, 0, 0, 2, TN, H)\n      ISTATE = -4\n      GO TO 560\nC KFLAG = -2.  Convergence failed repeatedly or with ABS(H) = HMIN. ----\n 540  MSG = 'SLSODE-  At T (=R1) and step size H (=R2), the    '\n      CALL XERRWV (MSG, 50, 205, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      MSG = '      corrector convergence failed repeatedly     '\n      CALL XERRWV (MSG, 50, 205, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      MSG = '      or with ABS(H) = HMIN   '\n      CALL XERRWV (MSG, 30, 205, 0, 0, 0, 0, 2, TN, H)\n      ISTATE = -5\nC Compute IMXER if relevant. -------------------------------------------\n 560  BIG = 0.0E0\n      IMXER = 1\n      DO 570 I = 1,N\n        SIZE = ABS(RWORK(I+LACOR-1)*RWORK(I+LEWT-1))\n        IF (BIG .GE. SIZE) GO TO 570\n        BIG = SIZE\n        IMXER = I\n 570    CONTINUE\n      IWORK(16) = IMXER\nC Set Y vector, T, and optional outputs. -------------------------------\n 580  DO 590 I = 1,N\n 590    Y(I) = RWORK(I+LYH-1)\n      T = TN\n      RWORK(11) = HU\n      RWORK(12) = H\n      RWORK(13) = TN\n      IWORK(11) = NST\n      IWORK(12) = NFE\n      IWORK(13) = NJE\n      IWORK(14) = NQU\n      IWORK(15) = NQ\n      RETURN\nC-----------------------------------------------------------------------\nC Block I.\nC The following block handles all error returns due to illegal input\nC (ISTATE = -3), as detected before calling the core integrator.\nC First the error message routine is called.  If the illegal input\nC is a negative ISTATE, the run is aborted (apparent infinite loop).\nC-----------------------------------------------------------------------\n 601  MSG = 'SLSODE-  ISTATE (=I1) illegal '\n      CALL XERRWV (MSG, 30, 1, 0, 1, ISTATE, 0, 0, 0.0E0, 0.0E0)\n      IF (ISTATE .LT. 0) GO TO 800\n      GO TO 700\n 602  MSG = 'SLSODE-  ITASK (=I1) illegal  '\n      CALL XERRWV (MSG, 30, 2, 0, 1, ITASK, 0, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 603  MSG = 'SLSODE-  ISTATE .GT. 1 but SLSODE not initialized '\n      CALL XERRWV (MSG, 50, 3, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 604  MSG = 'SLSODE-  NEQ (=I1) .LT. 1     '\n      CALL XERRWV (MSG, 30, 4, 0, 1, NEQ(1), 0, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 605  MSG = 'SLSODE-  ISTATE = 3 and NEQ increased (I1 to I2)  '\n      CALL XERRWV (MSG, 50, 5, 0, 2, N, NEQ(1), 0, 0.0E0, 0.0E0)\n      GO TO 700\n 606  MSG = 'SLSODE-  ITOL (=I1) illegal   '\n      CALL XERRWV (MSG, 30, 6, 0, 1, ITOL, 0, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 607  MSG = 'SLSODE-  IOPT (=I1) illegal   '\n      CALL XERRWV (MSG, 30, 7, 0, 1, IOPT, 0, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 608  MSG = 'SLSODE-  MF (=I1) illegal     '\n      CALL XERRWV (MSG, 30, 8, 0, 1, MF, 0, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 609  MSG = 'SLSODE-  ML (=I1) illegal.. .LT.0 or .GE.NEQ (=I2)'\n      CALL XERRWV (MSG, 50, 9, 0, 2, ML, NEQ(1), 0, 0.0E0, 0.0E0)\n      GO TO 700\n 610  MSG = 'SLSODE-  MU (=I1) illegal.. .LT.0 or .GE.NEQ (=I2)'\n      CALL XERRWV (MSG, 50, 10, 0, 2, MU, NEQ(1), 0, 0.0E0, 0.0E0)\n      GO TO 700\n 611  MSG = 'SLSODE-  MAXORD (=I1) .LT. 0  '\n      CALL XERRWV (MSG, 30, 11, 0, 1, MAXORD, 0, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 612  MSG = 'SLSODE-  MXSTEP (=I1) .LT. 0  '\n      CALL XERRWV (MSG, 30, 12, 0, 1, MXSTEP, 0, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 613  MSG = 'SLSODE-  MXHNIL (=I1) .LT. 0  '\n      CALL XERRWV (MSG, 30, 13, 0, 1, MXHNIL, 0, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 614  MSG = 'SLSODE-  TOUT (=R1) behind T (=R2)      '\n      CALL XERRWV (MSG, 40, 14, 0, 0, 0, 0, 2, TOUT, T)\n      MSG = '      Integration direction is given by H0 (=R1)  '\n      CALL XERRWV (MSG, 50, 14, 0, 0, 0, 0, 1, H0, 0.0E0)\n      GO TO 700\n 615  MSG = 'SLSODE-  HMAX (=R1) .LT. 0.0  '\n      CALL XERRWV (MSG, 30, 15, 0, 0, 0, 0, 1, HMAX, 0.0E0)\n      GO TO 700\n 616  MSG = 'SLSODE-  HMIN (=R1) .LT. 0.0  '\n      CALL XERRWV (MSG, 30, 16, 0, 0, 0, 0, 1, HMIN, 0.0E0)\n      GO TO 700\n 617  CONTINUE\n      MSG='SLSODE-  RWORK length needed, LENRW (=I1), exceeds LRW (=I2)'\n      CALL XERRWV (MSG, 60, 17, 0, 2, LENRW, LRW, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 618  CONTINUE\n      MSG='SLSODE-  IWORK length needed, LENIW (=I1), exceeds LIW (=I2)'\n      CALL XERRWV (MSG, 60, 18, 0, 2, LENIW, LIW, 0, 0.0E0, 0.0E0)\n      GO TO 700\n 619  MSG = 'SLSODE-  RTOL(I1) is R1 .LT. 0.0        '\n      CALL XERRWV (MSG, 40, 19, 0, 1, I, 0, 1, RTOLI, 0.0E0)\n      GO TO 700\n 620  MSG = 'SLSODE-  ATOL(I1) is R1 .LT. 0.0        '\n      CALL XERRWV (MSG, 40, 20, 0, 1, I, 0, 1, ATOLI, 0.0E0)\n      GO TO 700\n 621  EWTI = RWORK(LEWT+I-1)\n      MSG = 'SLSODE-  EWT(I1) is R1 .LE. 0.0         '\n      CALL XERRWV (MSG, 40, 21, 0, 1, I, 0, 1, EWTI, 0.0E0)\n      GO TO 700\n 622  CONTINUE\n      MSG='SLSODE-  TOUT (=R1) too close to T(=R2) to start integration'\n      CALL XERRWV (MSG, 60, 22, 0, 0, 0, 0, 2, TOUT, T)\n      GO TO 700\n 623  CONTINUE\n      MSG='SLSODE-  ITASK = I1 and TOUT (=R1) behind TCUR - HU (= R2)  '\n      CALL XERRWV (MSG, 60, 23, 0, 1, ITASK, 0, 2, TOUT, TP)\n      GO TO 700\n 624  CONTINUE\n      MSG='SLSODE-  ITASK = 4 OR 5 and TCRIT (=R1) behind TCUR (=R2)   '\n      CALL XERRWV (MSG, 60, 24, 0, 0, 0, 0, 2, TCRIT, TN)\n      GO TO 700\n 625  CONTINUE\n      MSG='SLSODE-  ITASK = 4 or 5 and TCRIT (=R1) behind TOUT (=R2)   '\n      CALL XERRWV (MSG, 60, 25, 0, 0, 0, 0, 2, TCRIT, TOUT)\n      GO TO 700\n 626  MSG = 'SLSODE-  At start of problem, too much accuracy   '\n      CALL XERRWV (MSG, 50, 26, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      MSG='      requested for precision of machine..  See TOLSF (=R1) '\n      CALL XERRWV (MSG, 60, 26, 0, 0, 0, 0, 1, TOLSF, 0.0E0)\n      RWORK(14) = TOLSF\n      GO TO 700\n 627  MSG = 'SLSODE-  Trouble in SINTDY.  ITASK = I1, TOUT = R1'\n      CALL XERRWV (MSG, 50, 27, 0, 1, ITASK, 0, 1, TOUT, 0.0E0)\nC\n 700  ISTATE = -3\n      RETURN\nC\n 800  MSG = 'SLSODE-  Run aborted.. apparent infinite loop     '\n      CALL XERRWV (MSG, 50, 303, 2, 0, 0, 0, 0, 0.0E0, 0.0E0)\n      RETURN\nC----------------------- END OF SUBROUTINE SLSODE ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/sprepj.f",
    "content": "      SUBROUTINE SPREPJ (NEQ, Y, YH, NYH, EWT, FTEM, SAVF, WM, IWM,\n     1   F, JAC)\nC***BEGIN PROLOGUE  SPREPJ\nC***SUBSIDIARY\nC***PURPOSE  Compute and process Newton iteration matrix.\nC***TYPE      SINGLE PRECISION (SPREPJ-S, DPREPJ-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  SPREPJ is called by SSTODE to compute and process the matrix\nC  P = I - h*el(1)*J , where J is an approximation to the Jacobian.\nC  Here J is computed by the user-supplied routine JAC if\nC  MITER = 1 or 4, or by finite differencing if MITER = 2, 3, or 5.\nC  If MITER = 3, a diagonal approximation to J is used.\nC  J is stored in WM and replaced by P.  If MITER .ne. 3, P is then\nC  subjected to LU decomposition in preparation for later solution\nC  of linear systems with P as coefficient matrix.  This is done\nC  by SGETRF if MITER = 1 or 2, and by SGBTRF if MITER = 4 or 5.\nC\nC  In addition to variables described in SSTODE and SLSODE prologues,\nC  communication with SPREPJ uses the following:\nC  Y     = array containing predicted values on entry.\nC  FTEM  = work array of length N (ACOR in SSTODE).\nC  SAVF  = array containing f evaluated at predicted y.\nC  WM    = real work space for matrices.  On output it contains the\nC          inverse diagonal matrix if MITER = 3 and the LU decomposition\nC          of P if MITER is 1, 2 , 4, or 5.\nC          Storage of matrix elements starts at WM(3).\nC          WM also contains the following matrix-related data:\nC          WM(1) = SQRT(UROUND), used in numerical Jacobian increments.\nC          WM(2) = H*EL0, saved for later use if MITER = 3.\nC  IWM   = integer work space containing pivot information, starting at\nC          IWM(21), if MITER is 1, 2, 4, or 5.  IWM also contains band\nC          parameters ML = IWM(1) and MU = IWM(2) if MITER is 4 or 5.\nC  EL0   = EL(1) (input).\nC  IERPJ = output error flag,  = 0 if no trouble, .gt. 0 if\nC          P matrix found to be singular.\nC  JCUR  = output flag = 1 to indicate that the Jacobian matrix\nC          (or approximation) is now current.\nC  This routine also uses the COMMON variables EL0, H, TN, UROUND,\nC  MITER, N, NFE, and NJE.\nC\nC***SEE ALSO  SLSODE\nC***ROUTINES CALLED  SGBTRF, SGETRF, SVNORM\nC***COMMON BLOCKS    SLS001\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890504  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC   010412  Reduced size of Common block /SLS001/. (ACH)\nC   031105  Restored 'own' variables to Common block /SLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC***END PROLOGUE  SPREPJ\nC**End\n      EXTERNAL F, JAC\n      INTEGER NEQ, NYH, IWM\n      REAL Y, YH, EWT, FTEM, SAVF, WM\n      DIMENSION NEQ(*), Y(*), YH(NYH,*), EWT(*), FTEM(*), SAVF(*),\n     1   WM(*), IWM(*)\n      INTEGER INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, CNYH,\n     1   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     1   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     2   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     3   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      REAL CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      COMMON /SLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, CNYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     3   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     4   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, I1, I2, IER, II, J, J1, JJ, LENP,\n     1   MBA, MBAND, MEB1, MEBAND, ML, ML3, MU, NP1\n      REAL CON, DI, FAC, HL0, R, R0, SRUR, YI, YJ, YJJ,\n     1   SVNORM\nC\nC***FIRST EXECUTABLE STATEMENT  SPREPJ\n      NJE = NJE + 1\n      IERPJ = 0\n      JCUR = 1\n      HL0 = H*EL0\n      GO TO (100, 200, 300, 400, 500), MITER\nC If MITER = 1, call JAC and multiply by scalar. -----------------------\n 100  LENP = N*N\n      DO 110 I = 1,LENP\n 110    WM(I+2) = 0.0E0\n      CALL JAC (NEQ, TN, Y, 0, 0, WM(3), N)\n      CON = -HL0\n      DO 120 I = 1,LENP\n 120    WM(I+2) = WM(I+2)*CON\n      GO TO 240\nC If MITER = 2, make N calls to F to approximate J. --------------------\n 200  FAC = SVNORM (N, SAVF, EWT)\n      R0 = 1000.0E0*ABS(H)*UROUND*N*FAC\n      IF (R0 .EQ. 0.0E0) R0 = 1.0E0\n      SRUR = WM(1)\n      J1 = 2\n      DO 230 J = 1,N\n        YJ = Y(J)\n        R = MAX(SRUR*ABS(YJ),R0/EWT(J))\n        Y(J) = Y(J) + R\n        FAC = -HL0/R\n        CALL F (NEQ, TN, Y, FTEM)\n        DO 220 I = 1,N\n 220      WM(I+J1) = (FTEM(I) - SAVF(I))*FAC\n        Y(J) = YJ\n        J1 = J1 + N\n 230    CONTINUE\n      NFE = NFE + N\nC Add identity matrix. -------------------------------------------------\n 240  J = 3\n      NP1 = N + 1\n      DO 250 I = 1,N\n        WM(J) = WM(J) + 1.0E0\n 250    J = J + NP1\nC Do LU decomposition on P. --------------------------------------------\n      CALL SGETRF (N, N, WM(3), N, IWM(21), IER)\n      IF (IER .NE. 0) IERPJ = 1\n      RETURN\nC If MITER = 3, construct a diagonal approximation to J and P. ---------\n 300  WM(2) = HL0\n      R = EL0*0.1E0\n      DO 310 I = 1,N\n 310    Y(I) = Y(I) + R*(H*SAVF(I) - YH(I,2))\n      CALL F (NEQ, TN, Y, WM(3))\n      NFE = NFE + 1\n      DO 320 I = 1,N\n        R0 = H*SAVF(I) - YH(I,2)\n        DI = 0.1E0*R0 - H*(WM(I+2) - SAVF(I))\n        WM(I+2) = 1.0E0\n        IF (ABS(R0) .LT. UROUND/EWT(I)) GO TO 320\n        IF (ABS(DI) .EQ. 0.0E0) GO TO 330\n        WM(I+2) = 0.1E0*R0/DI\n 320    CONTINUE\n      RETURN\n 330  IERPJ = 1\n      RETURN\nC If MITER = 4, call JAC and multiply by scalar. -----------------------\n 400  ML = IWM(1)\n      MU = IWM(2)\n      ML3 = ML + 3\n      MBAND = ML + MU + 1\n      MEBAND = MBAND + ML\n      LENP = MEBAND*N\n      DO 410 I = 1,LENP\n 410    WM(I+2) = 0.0E0\n      CALL JAC (NEQ, TN, Y, ML, MU, WM(ML3), MEBAND)\n      CON = -HL0\n      DO 420 I = 1,LENP\n 420    WM(I+2) = WM(I+2)*CON\n      GO TO 570\nC If MITER = 5, make MBAND calls to F to approximate J. ----------------\n 500  ML = IWM(1)\n      MU = IWM(2)\n      MBAND = ML + MU + 1\n      MBA = MIN(MBAND,N)\n      MEBAND = MBAND + ML\n      MEB1 = MEBAND - 1\n      SRUR = WM(1)\n      FAC = SVNORM (N, SAVF, EWT)\n      R0 = 1000.0E0*ABS(H)*UROUND*N*FAC\n      IF (R0 .EQ. 0.0E0) R0 = 1.0E0\n      DO 560 J = 1,MBA\n        DO 530 I = J,N,MBAND\n          YI = Y(I)\n          R = MAX(SRUR*ABS(YI),R0/EWT(I))\n 530      Y(I) = Y(I) + R\n        CALL F (NEQ, TN, Y, FTEM)\n        DO 550 JJ = J,N,MBAND\n          Y(JJ) = YH(JJ,1)\n          YJJ = Y(JJ)\n          R = MAX(SRUR*ABS(YJJ),R0/EWT(JJ))\n          FAC = -HL0/R\n          I1 = MAX(JJ-MU,1)\n          I2 = MIN(JJ+ML,N)\n          II = JJ*MEB1 - ML + 2\n          DO 540 I = I1,I2\n 540        WM(II+I) = (FTEM(I) - SAVF(I))*FAC\n 550      CONTINUE\n 560    CONTINUE\n      NFE = NFE + MBA\nC Add identity matrix. -------------------------------------------------\n 570  II = MBAND + 2\n      DO 580 I = 1,N\n        WM(II) = WM(II) + 1.0E0\n 580    II = II + MEBAND\nC Do LU decomposition of P. --------------------------------------------\n      CALL SGBTRF ( N, N, ML, MU, WM(3), MEBAND, IWM(21), IER)\n      IF (IER .NE. 0) IERPJ = 1\n      RETURN\nC----------------------- END OF SUBROUTINE SPREPJ ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/ssolsy.f",
    "content": "      SUBROUTINE SSOLSY (WM, IWM, X, TEM)\nC***BEGIN PROLOGUE  SSOLSY\nC***SUBSIDIARY\nC***PURPOSE  ODEPACK linear system solver.\nC***TYPE      SINGLE PRECISION (SSOLSY-S, DSOLSY-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  This routine manages the solution of the linear system arising from\nC  a chord iteration.  It is called if MITER .ne. 0.\nC  If MITER is 1 or 2, it calls SGETRF to accomplish this.\nC  If MITER = 3 it updates the coefficient h*EL0 in the diagonal\nC  matrix, and then computes the solution.\nC  If MITER is 4 or 5, it calls SGBTRS.\nC  Communication with SSOLSY uses the following variables:\nC  WM    = real work space containing the inverse diagonal matrix if\nC          MITER = 3 and the LU decomposition of the matrix otherwise.\nC          Storage of matrix elements starts at WM(3).\nC          WM also contains the following matrix-related data:\nC          WM(1) = SQRT(UROUND) (not used here),\nC          WM(2) = HL0, the previous value of h*EL0, used if MITER = 3.\nC  IWM   = integer work space containing pivot information, starting at\nC          IWM(21), if MITER is 1, 2, 4, or 5.  IWM also contains band\nC          parameters ML = IWM(1) and MU = IWM(2) if MITER is 4 or 5.\nC  X     = the right-hand side vector on input, and the solution vector\nC          on output, of length N.\nC  TEM   = vector of work space of length N, not used in this version.\nC  IERSL = output flag (in COMMON).  IERSL = 0 if no trouble occurred.\nC          IERSL = 1 if a singular matrix arose with MITER = 3.\nC  This routine also uses the COMMON variables EL0, H, MITER, and N.\nC\nC***SEE ALSO  SLSODE\nC***ROUTINES CALLED  SGBTRS, SGETRS\nC***COMMON BLOCKS    SLS001\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC   010412  Reduced size of Common block /SLS001/. (ACH)\nC   031105  Restored 'own' variables to Common block /SLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC***END PROLOGUE  SSOLSY\nC**End\n      INTEGER IWM\n      REAL WM, X, TEM\n      DIMENSION WM(*), IWM(*), X(*), TEM(*)\n      INTEGER INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, NYH,\n     1   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     1   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     2   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     3   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      REAL CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      COMMON /SLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, NYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     3   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     4   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, MEBAND, ML, MU\n      INTEGER INLPCK\n      REAL DI, HL0, PHL0, R\nC\nC***FIRST EXECUTABLE STATEMENT  SSOLSY\n      IERSL = 0\n      GO TO (100, 100, 300, 400, 400), MITER\n 100  CALL SGETRS ( 'N', N, 1, WM(3), N, IWM(21), X, N, INLPCK)\n      RETURN\nC\n 300  PHL0 = WM(2)\n      HL0 = H*EL0\n      WM(2) = HL0\n      IF (HL0 .EQ. PHL0) GO TO 330\n      R = HL0/PHL0\n      DO 320 I = 1,N\n        DI = 1.0E0 - R*(1.0E0 - 1.0E0/WM(I+2))\n        IF (ABS(DI) .EQ. 0.0E0) GO TO 390\n 320    WM(I+2) = 1.0E0/DI\n 330  DO 340 I = 1,N\n 340    X(I) = WM(I+2)*X(I)\n      RETURN\n 390  IERSL = 1\n      RETURN\nC\n 400  ML = IWM(1)\n      MU = IWM(2)\n      MEBAND = 2*ML + MU + 1\n      CALL SGBTRS ( 'N', N, ML, MU, 1, WM(3), MEBAND, IWM(21), X, N,\n     * INLPCK)\n      RETURN\nC----------------------- END OF SUBROUTINE SSOLSY ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/sstode.f",
    "content": "      SUBROUTINE SSTODE (NEQ, Y, YH, NYH, YH1, EWT, SAVF, ACOR,\n     1   WM, IWM, F, JAC, PJAC, SLVS)\nC***BEGIN PROLOGUE  SSTODE\nC***SUBSIDIARY\nC***PURPOSE  Performs one step of an ODEPACK integration.\nC***TYPE      SINGLE PRECISION (SSTODE-S, DSTODE-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  SSTODE performs one step of the integration of an initial value\nC  problem for a system of ordinary differential equations.\nC  Note:  SSTODE is independent of the value of the iteration method\nC  indicator MITER, when this is .ne. 0, and hence is independent\nC  of the type of chord method used, or the Jacobian structure.\nC  Communication with SSTODE is done with the following variables:\nC\nC  NEQ    = integer array containing problem size in NEQ(1), and\nC           passed as the NEQ argument in all calls to F and JAC.\nC  Y      = an array of length .ge. N used as the Y argument in\nC           all calls to F and JAC.\nC  YH     = an NYH by LMAX array containing the dependent variables\nC           and their approximate scaled derivatives, where\nC           LMAX = MAXORD + 1.  YH(i,j+1) contains the approximate\nC           j-th derivative of y(i), scaled by h**j/factorial(j)\nC           (j = 0,1,...,NQ).  on entry for the first step, the first\nC           two columns of YH must be set from the initial values.\nC  NYH    = a constant integer .ge. N, the first dimension of YH.\nC  YH1    = a one-dimensional array occupying the same space as YH.\nC  EWT    = an array of length N containing multiplicative weights\nC           for local error measurements.  Local errors in Y(i) are\nC           compared to 1.0/EWT(i) in various error tests.\nC  SAVF   = an array of working storage, of length N.\nC           Also used for input of YH(*,MAXORD+2) when JSTART = -1\nC           and MAXORD .lt. the current order NQ.\nC  ACOR   = a work array of length N, used for the accumulated\nC           corrections.  On a successful return, ACOR(i) contains\nC           the estimated one-step local error in Y(i).\nC  WM,IWM = real and integer work arrays associated with matrix\nC           operations in chord iteration (MITER .ne. 0).\nC  PJAC   = name of routine to evaluate and preprocess Jacobian matrix\nC           and P = I - h*el0*JAC, if a chord method is being used.\nC  SLVS   = name of routine to solve linear system in chord iteration.\nC  CCMAX  = maximum relative change in h*el0 before PJAC is called.\nC  H      = the step size to be attempted on the next step.\nC           H is altered by the error control algorithm during the\nC           problem.  H can be either positive or negative, but its\nC           sign must remain constant throughout the problem.\nC  HMIN   = the minimum absolute value of the step size h to be used.\nC  HMXI   = inverse of the maximum absolute value of h to be used.\nC           HMXI = 0.0 is allowed and corresponds to an infinite hmax.\nC           HMIN and HMXI may be changed at any time, but will not\nC           take effect until the next change of h is considered.\nC  TN     = the independent variable. TN is updated on each step taken.\nC  JSTART = an integer used for input only, with the following\nC           values and meanings:\nC                0  perform the first step.\nC            .gt.0  take a new step continuing from the last.\nC               -1  take the next step with a new value of H, MAXORD,\nC                     N, METH, MITER, and/or matrix parameters.\nC               -2  take the next step with a new value of H,\nC                     but with other inputs unchanged.\nC           On return, JSTART is set to 1 to facilitate continuation.\nC  KFLAG  = a completion code with the following meanings:\nC                0  the step was succesful.\nC               -1  the requested error could not be achieved.\nC               -2  corrector convergence could not be achieved.\nC               -3  fatal error in PJAC or SLVS.\nC           A return with KFLAG = -1 or -2 means either\nC           abs(H) = HMIN or 10 consecutive failures occurred.\nC           On a return with KFLAG negative, the values of TN and\nC           the YH array are as of the beginning of the last\nC           step, and H is the last step size attempted.\nC  MAXORD = the maximum order of integration method to be allowed.\nC  MAXCOR = the maximum number of corrector iterations allowed.\nC  MSBP   = maximum number of steps between PJAC calls (MITER .gt. 0).\nC  MXNCF  = maximum number of convergence failures allowed.\nC  METH/MITER = the method flags.  See description in driver.\nC  N      = the number of first-order differential equations.\nC  The values of CCMAX, H, HMIN, HMXI, TN, JSTART, KFLAG, MAXORD,\nC  MAXCOR, MSBP, MXNCF, METH, MITER, and N are communicated via COMMON.\nC\nC***SEE ALSO  SLSODE\nC***ROUTINES CALLED  SCFODE, SVNORM\nC***COMMON BLOCKS    SLS001\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC   010413  Reduced size of Common block /SLS001/. (ACH)\nC   031105  Restored 'own' variables to Common block /SLS001/, to\nC           enable interrupt/restart feature. (ACH)\nC***END PROLOGUE  SSTODE\nC**End\n      EXTERNAL F, JAC, PJAC, SLVS\n      INTEGER NEQ, NYH, IWM\n      REAL Y, YH, YH1, EWT, SAVF, ACOR, WM\n      DIMENSION NEQ(*), Y(*), YH(NYH,*), YH1(*), EWT(*), SAVF(*),\n     1   ACOR(*), WM(*), IWM(*)\n      INTEGER INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, CNYH,\n     1   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     1   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     2   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     3   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\n      INTEGER I, I1, IREDO, IRET, J, JB, M, NCF, NEWQ\n      REAL CONIT, CRATE, EL, ELCO, HOLD, RMAX, TESCO,\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND\n      REAL DCON, DDN, DEL, DELP, DSM, DUP, EXDN, EXSM, EXUP,\n     1   R, RH, RHDN, RHSM, RHUP, TOLD, SVNORM\n      COMMON /SLS001/ CONIT, CRATE, EL(13), ELCO(13,12),\n     1   HOLD, RMAX, TESCO(3,12),\n     1   CCMAX, EL0, H, HMIN, HMXI, HU, RC, TN, UROUND,\n     2   INIT, MXSTEP, MXHNIL, NHNIL, NSLAST, CNYH,\n     3   IALTH, IPUP, LMAX, MEO, NQNYH, NSLP,\n     3   ICF, IERPJ, IERSL, JCUR, JSTART, KFLAG, L,\n     4   LYH, LEWT, LACOR, LSAVF, LWM, LIWM, METH, MITER,\n     5   MAXORD, MAXCOR, MSBP, MXNCF, N, NQ, NST, NFE, NJE, NQU\nC\nC***FIRST EXECUTABLE STATEMENT  SSTODE\n      KFLAG = 0\n      TOLD = TN\n      NCF = 0\n      IERPJ = 0\n      IERSL = 0\n      JCUR = 0\n      ICF = 0\n      DELP = 0.0E0\n      IF (JSTART .GT. 0) GO TO 200\n      IF (JSTART .EQ. -1) GO TO 100\n      IF (JSTART .EQ. -2) GO TO 160\nC-----------------------------------------------------------------------\nC On the first call, the order is set to 1, and other variables are\nC initialized.  RMAX is the maximum ratio by which H can be increased\nC in a single step.  It is initially 1.E4 to compensate for the small\nC initial H, but then is normally equal to 10.  If a failure\nC occurs (in corrector convergence or error test), RMAX is set to 2\nC for the next increase.\nC-----------------------------------------------------------------------\n      LMAX = MAXORD + 1\n      NQ = 1\n      L = 2\n      IALTH = 2\n      RMAX = 10000.0E0\n      RC = 0.0E0\n      EL0 = 1.0E0\n      CRATE = 0.7E0\n      HOLD = H\n      MEO = METH\n      NSLP = 0\n      IPUP = MITER\n      IRET = 3\n      GO TO 140\nC-----------------------------------------------------------------------\nC The following block handles preliminaries needed when JSTART = -1.\nC IPUP is set to MITER to force a matrix update.\nC If an order increase is about to be considered (IALTH = 1),\nC IALTH is reset to 2 to postpone consideration one more step.\nC If the caller has changed METH, SCFODE is called to reset\nC the coefficients of the method.\nC If the caller has changed MAXORD to a value less than the current\nC order NQ, NQ is reduced to MAXORD, and a new H chosen accordingly.\nC If H is to be changed, YH must be rescaled.\nC If H or METH is being changed, IALTH is reset to L = NQ + 1\nC to prevent further changes in H for that many steps.\nC-----------------------------------------------------------------------\n 100  IPUP = MITER\n      LMAX = MAXORD + 1\n      IF (IALTH .EQ. 1) IALTH = 2\n      IF (METH .EQ. MEO) GO TO 110\n      CALL SCFODE (METH, ELCO, TESCO)\n      MEO = METH\n      IF (NQ .GT. MAXORD) GO TO 120\n      IALTH = L\n      IRET = 1\n      GO TO 150\n 110  IF (NQ .LE. MAXORD) GO TO 160\n 120  NQ = MAXORD\n      L = LMAX\n      DO 125 I = 1,L\n 125    EL(I) = ELCO(I,NQ)\n      NQNYH = NQ*NYH\n      RC = RC*EL(1)/EL0\n      EL0 = EL(1)\n      CONIT = 0.5E0/(NQ+2)\n      DDN = SVNORM (N, SAVF, EWT)/TESCO(1,L)\n      EXDN = 1.0E0/L\n      RHDN = 1.0E0/(1.3E0*DDN**EXDN + 0.0000013E0)\n      RH = MIN(RHDN,1.0E0)\n      IREDO = 3\n      IF (H .EQ. HOLD) GO TO 170\n      RH = MIN(RH,ABS(H/HOLD))\n      H = HOLD\n      GO TO 175\nC-----------------------------------------------------------------------\nC SCFODE is called to get all the integration coefficients for the\nC current METH.  Then the EL vector and related constants are reset\nC whenever the order NQ is changed, or at the start of the problem.\nC-----------------------------------------------------------------------\n 140  CALL SCFODE (METH, ELCO, TESCO)\n 150  DO 155 I = 1,L\n 155    EL(I) = ELCO(I,NQ)\n      NQNYH = NQ*NYH\n      RC = RC*EL(1)/EL0\n      EL0 = EL(1)\n      CONIT = 0.5E0/(NQ+2)\n      GO TO (160, 170, 200), IRET\nC-----------------------------------------------------------------------\nC If H is being changed, the H ratio RH is checked against\nC RMAX, HMIN, and HMXI, and the YH array rescaled.  IALTH is set to\nC L = NQ + 1 to prevent a change of H for that many steps, unless\nC forced by a convergence or error test failure.\nC-----------------------------------------------------------------------\n 160  IF (H .EQ. HOLD) GO TO 200\n      RH = H/HOLD\n      H = HOLD\n      IREDO = 3\n      GO TO 175\n 170  RH = MAX(RH,HMIN/ABS(H))\n 175  RH = MIN(RH,RMAX)\n      RH = RH/MAX(1.0E0,ABS(H)*HMXI*RH)\n      R = 1.0E0\n      DO 180 J = 2,L\n        R = R*RH\n        DO 180 I = 1,N\n 180      YH(I,J) = YH(I,J)*R\n      H = H*RH\n      RC = RC*RH\n      IALTH = L\n      IF (IREDO .EQ. 0) GO TO 690\nC-----------------------------------------------------------------------\nC This section computes the predicted values by effectively\nC multiplying the YH array by the Pascal Triangle matrix.\nC RC is the ratio of new to old values of the coefficient  H*EL(1).\nC When RC differs from 1 by more than CCMAX, IPUP is set to MITER\nC to force PJAC to be called, if a Jacobian is involved.\nC In any case, PJAC is called at least every MSBP steps.\nC-----------------------------------------------------------------------\n 200  IF (ABS(RC-1.0E0) .GT. CCMAX) IPUP = MITER\n      IF (NST .GE. NSLP+MSBP) IPUP = MITER\n      TN = TN + H\n      I1 = NQNYH + 1\n      DO 215 JB = 1,NQ\n        I1 = I1 - NYH\nCdir$ ivdep\n        DO 210 I = I1,NQNYH\n 210      YH1(I) = YH1(I) + YH1(I+NYH)\n 215    CONTINUE\nC-----------------------------------------------------------------------\nC Up to MAXCOR corrector iterations are taken.  A convergence test is\nC made on the R.M.S. norm of each correction, weighted by the error\nC weight vector EWT.  The sum of the corrections is accumulated in the\nC vector ACOR(i).  The YH array is not altered in the corrector loop.\nC-----------------------------------------------------------------------\n 220  M = 0\n      DO 230 I = 1,N\n 230    Y(I) = YH(I,1)\n      CALL F (NEQ, TN, Y, SAVF)\n      NFE = NFE + 1\n      IF (IPUP .LE. 0) GO TO 250\nC-----------------------------------------------------------------------\nC If indicated, the matrix P = I - h*el(1)*J is reevaluated and\nC preprocessed before starting the corrector iteration.  IPUP is set\nC to 0 as an indicator that this has been done.\nC-----------------------------------------------------------------------\n      CALL PJAC (NEQ, Y, YH, NYH, EWT, ACOR, SAVF, WM, IWM, F, JAC)\n      IPUP = 0\n      RC = 1.0E0\n      NSLP = NST\n      CRATE = 0.7E0\n      IF (IERPJ .NE. 0) GO TO 430\n 250  DO 260 I = 1,N\n 260    ACOR(I) = 0.0E0\n 270  IF (MITER .NE. 0) GO TO 350\nC-----------------------------------------------------------------------\nC In the case of functional iteration, update Y directly from\nC the result of the last function evaluation.\nC-----------------------------------------------------------------------\n      DO 290 I = 1,N\n        SAVF(I) = H*SAVF(I) - YH(I,2)\n 290    Y(I) = SAVF(I) - ACOR(I)\n      DEL = SVNORM (N, Y, EWT)\n      DO 300 I = 1,N\n        Y(I) = YH(I,1) + EL(1)*SAVF(I)\n 300    ACOR(I) = SAVF(I)\n      GO TO 400\nC-----------------------------------------------------------------------\nC In the case of the chord method, compute the corrector error,\nC and solve the linear system with that as right-hand side and\nC P as coefficient matrix.\nC-----------------------------------------------------------------------\n 350  DO 360 I = 1,N\n 360    Y(I) = H*SAVF(I) - (YH(I,2) + ACOR(I))\n      CALL SLVS (WM, IWM, Y, SAVF)\n      IF (IERSL .LT. 0) GO TO 430\n      IF (IERSL .GT. 0) GO TO 410\n      DEL = SVNORM (N, Y, EWT)\n      DO 380 I = 1,N\n        ACOR(I) = ACOR(I) + Y(I)\n 380    Y(I) = YH(I,1) + EL(1)*ACOR(I)\nC-----------------------------------------------------------------------\nC Test for convergence.  If M.gt.0, an estimate of the convergence\nC rate constant is stored in CRATE, and this is used in the test.\nC-----------------------------------------------------------------------\n 400  IF (M .NE. 0) CRATE = MAX(0.2E0*CRATE,DEL/DELP)\n      DCON = DEL*MIN(1.0E0,1.5E0*CRATE)/(TESCO(2,NQ)*CONIT)\n      IF (DCON .LE. 1.0E0) GO TO 450\n      M = M + 1\n      IF (M .EQ. MAXCOR) GO TO 410\n      IF (M .GE. 2 .AND. DEL .GT. 2.0E0*DELP) GO TO 410\n      DELP = DEL\n      CALL F (NEQ, TN, Y, SAVF)\n      NFE = NFE + 1\n      GO TO 270\nC-----------------------------------------------------------------------\nC The corrector iteration failed to converge.\nC If MITER .ne. 0 and the Jacobian is out of date, PJAC is called for\nC the next try.  Otherwise the YH array is retracted to its values\nC before prediction, and H is reduced, if possible.  If H cannot be\nC reduced or MXNCF failures have occurred, exit with KFLAG = -2.\nC-----------------------------------------------------------------------\n 410  IF (MITER .EQ. 0 .OR. JCUR .EQ. 1) GO TO 430\n      ICF = 1\n      IPUP = MITER\n      GO TO 220\n 430  ICF = 2\n      NCF = NCF + 1\n      RMAX = 2.0E0\n      TN = TOLD\n      I1 = NQNYH + 1\n      DO 445 JB = 1,NQ\n        I1 = I1 - NYH\nCdir$ ivdep\n        DO 440 I = I1,NQNYH\n 440      YH1(I) = YH1(I) - YH1(I+NYH)\n 445    CONTINUE\n      IF (IERPJ .LT. 0 .OR. IERSL .LT. 0) GO TO 680\n      IF (ABS(H) .LE. HMIN*1.00001E0) GO TO 670\n      IF (NCF .EQ. MXNCF) GO TO 670\n      RH = 0.25E0\n      IPUP = MITER\n      IREDO = 1\n      GO TO 170\nC-----------------------------------------------------------------------\nC The corrector has converged.  JCUR is set to 0\nC to signal that the Jacobian involved may need updating later.\nC The local error test is made and control passes to statement 500\nC if it fails.\nC-----------------------------------------------------------------------\n 450  JCUR = 0\n      IF (M .EQ. 0) DSM = DEL/TESCO(2,NQ)\n      IF (M .GT. 0) DSM = SVNORM (N, ACOR, EWT)/TESCO(2,NQ)\n      IF (DSM .GT. 1.0E0) GO TO 500\nC-----------------------------------------------------------------------\nC After a successful step, update the YH array.\nC Consider changing H if IALTH = 1.  Otherwise decrease IALTH by 1.\nC If IALTH is then 1 and NQ .lt. MAXORD, then ACOR is saved for\nC use in a possible order increase on the next step.\nC If a change in H is considered, an increase or decrease in order\nC by one is considered also.  A change in H is made only if it is by a\nC factor of at least 1.1.  If not, IALTH is set to 3 to prevent\nC testing for that many steps.\nC-----------------------------------------------------------------------\n      KFLAG = 0\n      IREDO = 0\n      NST = NST + 1\n      HU = H\n      NQU = NQ\n      DO 470 J = 1,L\n        DO 470 I = 1,N\n 470      YH(I,J) = YH(I,J) + EL(J)*ACOR(I)\n      IALTH = IALTH - 1\n      IF (IALTH .EQ. 0) GO TO 520\n      IF (IALTH .GT. 1) GO TO 700\n      IF (L .EQ. LMAX) GO TO 700\n      DO 490 I = 1,N\n 490    YH(I,LMAX) = ACOR(I)\n      GO TO 700\nC-----------------------------------------------------------------------\nC The error test failed.  KFLAG keeps track of multiple failures.\nC Restore TN and the YH array to their previous values, and prepare\nC to try the step again.  Compute the optimum step size for this or\nC one lower order.  After 2 or more failures, H is forced to decrease\nC by a factor of 0.2 or less.\nC-----------------------------------------------------------------------\n 500  KFLAG = KFLAG - 1\n      TN = TOLD\n      I1 = NQNYH + 1\n      DO 515 JB = 1,NQ\n        I1 = I1 - NYH\nCdir$ ivdep\n        DO 510 I = I1,NQNYH\n 510      YH1(I) = YH1(I) - YH1(I+NYH)\n 515    CONTINUE\n      RMAX = 2.0E0\n      IF (ABS(H) .LE. HMIN*1.00001E0) GO TO 660\n      IF (KFLAG .LE. -3) GO TO 640\n      IREDO = 2\n      RHUP = 0.0E0\n      GO TO 540\nC-----------------------------------------------------------------------\nC Regardless of the success or failure of the step, factors\nC RHDN, RHSM, and RHUP are computed, by which H could be multiplied\nC at order NQ - 1, order NQ, or order NQ + 1, respectively.\nC In the case of failure, RHUP = 0.0 to avoid an order increase.\nC The largest of these is determined and the new order chosen\nC accordingly.  If the order is to be increased, we compute one\nC additional scaled derivative.\nC-----------------------------------------------------------------------\n 520  RHUP = 0.0E0\n      IF (L .EQ. LMAX) GO TO 540\n      DO 530 I = 1,N\n 530    SAVF(I) = ACOR(I) - YH(I,LMAX)\n      DUP = SVNORM (N, SAVF, EWT)/TESCO(3,NQ)\n      EXUP = 1.0E0/(L+1)\n      RHUP = 1.0E0/(1.4E0*DUP**EXUP + 0.0000014E0)\n 540  EXSM = 1.0E0/L\n      RHSM = 1.0E0/(1.2E0*DSM**EXSM + 0.0000012E0)\n      RHDN = 0.0E0\n      IF (NQ .EQ. 1) GO TO 560\n      DDN = SVNORM (N, YH(1,L), EWT)/TESCO(1,NQ)\n      EXDN = 1.0E0/NQ\n      RHDN = 1.0E0/(1.3E0*DDN**EXDN + 0.0000013E0)\n 560  IF (RHSM .GE. RHUP) GO TO 570\n      IF (RHUP .GT. RHDN) GO TO 590\n      GO TO 580\n 570  IF (RHSM .LT. RHDN) GO TO 580\n      NEWQ = NQ\n      RH = RHSM\n      GO TO 620\n 580  NEWQ = NQ - 1\n      RH = RHDN\n      IF (KFLAG .LT. 0 .AND. RH .GT. 1.0E0) RH = 1.0E0\n      GO TO 620\n 590  NEWQ = L\n      RH = RHUP\n      IF (RH .LT. 1.1E0) GO TO 610\n      R = EL(L)/L\n      DO 600 I = 1,N\n 600    YH(I,NEWQ+1) = ACOR(I)*R\n      GO TO 630\n 610  IALTH = 3\n      GO TO 700\n 620  IF ((KFLAG .EQ. 0) .AND. (RH .LT. 1.1E0)) GO TO 610\n      IF (KFLAG .LE. -2) RH = MIN(RH,0.2E0)\nC-----------------------------------------------------------------------\nC If there is a change of order, reset NQ, l, and the coefficients.\nC In any case H is reset according to RH and the YH array is rescaled.\nC Then exit from 690 if the step was OK, or redo the step otherwise.\nC-----------------------------------------------------------------------\n      IF (NEWQ .EQ. NQ) GO TO 170\n 630  NQ = NEWQ\n      L = NQ + 1\n      IRET = 2\n      GO TO 150\nC-----------------------------------------------------------------------\nC Control reaches this section if 3 or more failures have occurred.\nC If 10 failures have occurred, exit with KFLAG = -1.\nC It is assumed that the derivatives that have accumulated in the\nC YH array have errors of the wrong order.  Hence the first\nC derivative is recomputed, and the order is set to 1.  Then\nC H is reduced by a factor of 10, and the step is retried,\nC until it succeeds or H reaches HMIN.\nC-----------------------------------------------------------------------\n 640  IF (KFLAG .EQ. -10) GO TO 660\n      RH = 0.1E0\n      RH = MAX(HMIN/ABS(H),RH)\n      H = H*RH\n      DO 645 I = 1,N\n 645    Y(I) = YH(I,1)\n      CALL F (NEQ, TN, Y, SAVF)\n      NFE = NFE + 1\n      DO 650 I = 1,N\n 650    YH(I,2) = H*SAVF(I)\n      IPUP = MITER\n      IALTH = 5\n      IF (NQ .EQ. 1) GO TO 200\n      NQ = 1\n      L = 2\n      IRET = 3\n      GO TO 150\nC-----------------------------------------------------------------------\nC All returns are made through this section.  H is saved in HOLD\nC to allow the caller to change H on the next step.\nC-----------------------------------------------------------------------\n 660  KFLAG = -1\n      GO TO 720\n 670  KFLAG = -2\n      GO TO 720\n 680  KFLAG = -3\n      GO TO 720\n 690  RMAX = 10.0E0\n 700  R = 1.0E0/TESCO(2,NQU)\n      DO 710 I = 1,N\n 710    ACOR(I) = ACOR(I)*R\n 720  HOLD = H\n      JSTART = 1\n      RETURN\nC----------------------- END OF SUBROUTINE SSTODE ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/odepack/svnorm.f",
    "content": "      REAL FUNCTION SVNORM (N, V, W)\nC***BEGIN PROLOGUE  SVNORM\nC***SUBSIDIARY\nC***PURPOSE  Weighted root-mean-square vector norm.\nC***TYPE      SINGLE PRECISION (SVNORM-S, DVNORM-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  This function routine computes the weighted root-mean-square norm\nC  of the vector of length N contained in the array V, with weights\nC  contained in the array W of length N:\nC    SVNORM = SQRT( (1/N) * SUM( V(i)*W(i) )**2 )\nC\nC***SEE ALSO  SLSODE\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890501  Modified prologue to SLATEC/LDOC format.  (FNF)\nC   890503  Minor cosmetic changes.  (FNF)\nC   930809  Renamed to allow single/double precision versions. (ACH)\nC***END PROLOGUE  SVNORM\nC**End\n      INTEGER N,   I\n      REAL V, W,   SUM\n      DIMENSION V(N), W(N)\nC\nC***FIRST EXECUTABLE STATEMENT  SVNORM\n      SUM = 0.0E0\n      DO 10 I = 1,N\n 10     SUM = SUM + (V(I)*W(I))**2\n      SVNORM = SQRT(SUM/N)\n      RETURN\nC----------------------- END OF FUNCTION SVNORM ------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/quadpack/dqagi.f",
    "content": "      SUBROUTINE DQAGI(F,BOUND,INF,EPSABS,EPSREL,RESULT,ABSERR,NEVAL,\n     *   IER,LIMIT,LENW,LAST,IWORK,WORK)\nC***BEGIN PROLOGUE  DQAGI\nC***DATE WRITTEN   800101   (YYMMDD)\nC***REVISION DATE  830518   (YYMMDD)\nC***CATEGORY NO.  H2A3A1,H2A4A1\nC***KEYWORDS  AUTOMATIC INTEGRATOR, INFINITE INTERVALS,\nC             GENERAL-PURPOSE, TRANSFORMATION, EXTRAPOLATION,\nC             GLOBALLY ADAPTIVE\nC***AUTHOR  PIESSENS,ROBERT,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC           DE DONCKER,ELISE,APPL. MATH. & PROGR. DIV. -K.U.LEUVEN\nC***PURPOSE  THE ROUTINE CALCULATES AN APPROXIMATION RESULT TO A GIVEN\nC            INTEGRAL   I = INTEGRAL OF F OVER (BOUND,+INFINITY)\nC            OR I = INTEGRAL OF F OVER (-INFINITY,BOUND)\nC            OR I = INTEGRAL OF F OVER (-INFINITY,+INFINITY)\nC            HOPEFULLY SATISFYING FOLLOWING CLAIM FOR ACCURACY\nC            ABS(I-RESULT).LE.MAX(EPSABS,EPSREL*ABS(I)).\nC***DESCRIPTION\nC\nC        INTEGRATION OVER INFINITE INTERVALS\nC        STANDARD FORTRAN SUBROUTINE\nC\nC        PARAMETERS\nC         ON ENTRY\nC            F      - SUBROUTINE F(X,RESULT) DEFINING THE INTEGRAND\nC                     FUNCTION F(X). THE ACTUAL NAME FOR F NEEDS TO BE\nC                     DECLARED E X T E R N A L IN THE DRIVER PROGRAM.\nC\nC            BOUND  - DOUBLE PRECISION\nC                     FINITE BOUND OF INTEGRATION RANGE\nC                     (HAS NO MEANING IF INTERVAL IS DOUBLY-INFINITE)\nC\nC            INF    - INTEGER\nC                     INDICATING THE KIND OF INTEGRATION RANGE INVOLVED\nC                     INF = 1 CORRESPONDS TO  (BOUND,+INFINITY),\nC                     INF = -1            TO  (-INFINITY,BOUND),\nC                     INF = 2             TO (-INFINITY,+INFINITY).\nC\nC            EPSABS - DOUBLE PRECISION\nC                     ABSOLUTE ACCURACY REQUESTED\nC            EPSREL - DOUBLE PRECISION\nC                     RELATIVE ACCURACY REQUESTED\nC                     IF  EPSABS.LE.0\nC                     AND EPSREL.LT.MAX(50*REL.MACH.ACC.,0.5D-28),\nC                     THE ROUTINE WILL END WITH IER = 6.\nC\nC\nC         ON RETURN\nC            RESULT - DOUBLE PRECISION\nC                     APPROXIMATION TO THE INTEGRAL\nC\nC            ABSERR - DOUBLE PRECISION\nC                     ESTIMATE OF THE MODULUS OF THE ABSOLUTE ERROR,\nC                     WHICH SHOULD EQUAL OR EXCEED ABS(I-RESULT)\nC\nC            NEVAL  - INTEGER\nC                     NUMBER OF INTEGRAND EVALUATIONS\nC\nC            IER    - INTEGER\nC                     IER = 0 NORMAL AND RELIABLE TERMINATION OF THE\nC                             ROUTINE. IT IS ASSUMED THAT THE REQUESTED\nC                             ACCURACY HAS BEEN ACHIEVED.\nC                   - IER.GT.0 ABNORMAL TERMINATION OF THE ROUTINE. THE\nC                             ESTIMATES FOR RESULT AND ERROR ARE LESS\nC                             RELIABLE. IT IS ASSUMED THAT THE REQUESTED\nC                             ACCURACY HAS NOT BEEN ACHIEVED.\nC            ERROR MESSAGES\nC                     IER = 1 MAXIMUM NUMBER OF SUBDIVISIONS ALLOWED\nC                             HAS BEEN ACHIEVED. ONE CAN ALLOW MORE\nC                             SUBDIVISIONS BY INCREASING THE VALUE OF\nC                             LIMIT (AND TAKING THE ACCORDING DIMENSION\nC                             ADJUSTMENTS INTO ACCOUNT). HOWEVER, IF\nC                             THIS YIELDS NO IMPROVEMENT IT IS ADVISED\nC                             TO ANALYZE THE INTEGRAND IN ORDER TO\nC                             DETERMINE THE INTEGRATION DIFFICULTIES. IF\nC                             THE POSITION OF A LOCAL DIFFICULTY CAN BE\nC                             DETERMINED (E.G. SINGULARITY,\nC                             DISCONTINUITY WITHIN THE INTERVAL) ONE\nC                             WILL PROBABLY GAIN FROM SPLITTING UP THE\nC                             INTERVAL AT THIS POINT AND CALLING THE\nC                             INTEGRATOR ON THE SUBRANGES. IF POSSIBLE,\nC                             AN APPROPRIATE SPECIAL-PURPOSE INTEGRATOR\nC                             SHOULD BE USED, WHICH IS DESIGNED FOR\nC                             HANDLING THE TYPE OF DIFFICULTY INVOLVED.\nC                         = 2 THE OCCURRENCE OF ROUNDOFF ERROR IS\nC                             DETECTED, WHICH PREVENTS THE REQUESTED\nC                             TOLERANCE FROM BEING ACHIEVED.\nC                             THE ERROR MAY BE UNDER-ESTIMATED.\nC                         = 3 EXTREMELY BAD INTEGRAND BEHAVIOUR OCCURS\nC                             AT SOME POINTS OF THE INTEGRATION\nC                             INTERVAL.\nC                         = 4 THE ALGORITHM DOES NOT CONVERGE.\nC                             ROUNDOFF ERROR IS DETECTED IN THE\nC                             EXTRAPOLATION TABLE.\nC                             IT IS ASSUMED THAT THE REQUESTED TOLERANCE\nC                             CANNOT BE ACHIEVED, AND THAT THE RETURNED\nC                             RESULT IS THE BEST WHICH CAN BE OBTAINED.\nC                         = 5 THE INTEGRAL IS PROBABLY DIVERGENT, OR\nC                             SLOWLY CONVERGENT. IT MUST BE NOTED THAT\nC                             DIVERGENCE CAN OCCUR WITH ANY OTHER VALUE\nC                             OF IER.\nC                         = 6 THE INPUT IS INVALID, BECAUSE\nC                             (EPSABS.LE.0 AND\nC                              EPSREL.LT.MAX(50*REL.MACH.ACC.,0.5D-28))\nC                              OR LIMIT.LT.1 OR LENIW.LT.LIMIT*4.\nC                             RESULT, ABSERR, NEVAL, LAST ARE SET TO\nC                             ZERO. EXEPT WHEN LIMIT OR LENIW IS\nC                             INVALID, IWORK(1), WORK(LIMIT*2+1) AND\nC                             WORK(LIMIT*3+1) ARE SET TO ZERO, WORK(1)\nC                             IS SET TO A AND WORK(LIMIT+1) TO B.\nC\nC         DIMENSIONING PARAMETERS\nC            LIMIT - INTEGER\nC                    DIMENSIONING PARAMETER FOR IWORK\nC                    LIMIT DETERMINES THE MAXIMUM NUMBER OF SUBINTERVALS\nC                    IN THE PARTITION OF THE GIVEN INTEGRATION INTERVAL\nC                    (A,B), LIMIT.GE.1.\nC                    IF LIMIT.LT.1, THE ROUTINE WILL END WITH IER = 6.\nC\nC            LENW  - INTEGER\nC                    DIMENSIONING PARAMETER FOR WORK\nC                    LENW MUST BE AT LEAST LIMIT*4.\nC                    IF LENW.LT.LIMIT*4, THE ROUTINE WILL END\nC                    WITH IER = 6.\nC\nC            LAST  - INTEGER\nC                    ON RETURN, LAST EQUALS THE NUMBER OF SUBINTERVALS\nC                    PRODUCED IN THE SUBDIVISION PROCESS, WHICH\nC                    DETERMINES THE NUMBER OF SIGNIFICANT ELEMENTS\nC                    ACTUALLY IN THE WORK ARRAYS.\nC\nC         WORK ARRAYS\nC            IWORK - INTEGER\nC                    VECTOR OF DIMENSION AT LEAST LIMIT, THE FIRST\nC                    K ELEMENTS OF WHICH CONTAIN POINTERS\nC                    TO THE ERROR ESTIMATES OVER THE SUBINTERVALS,\nC                    SUCH THAT WORK(LIMIT*3+IWORK(1)),... ,\nC                    WORK(LIMIT*3+IWORK(K)) FORM A DECREASING\nC                    SEQUENCE, WITH K = LAST IF LAST.LE.(LIMIT/2+2), AND\nC                    K = LIMIT+1-LAST OTHERWISE\nC\nC            WORK  - DOUBLE PRECISION\nC                    VECTOR OF DIMENSION AT LEAST LENW\nC                    ON RETURN\nC                    WORK(1), ..., WORK(LAST) CONTAIN THE LEFT\nC                     END POINTS OF THE SUBINTERVALS IN THE\nC                     PARTITION OF (A,B),\nC                    WORK(LIMIT+1), ..., WORK(LIMIT+LAST) CONTAIN\nC                     THE RIGHT END POINTS,\nC                    WORK(LIMIT*2+1), ...,WORK(LIMIT*2+LAST) CONTAIN THE\nC                     INTEGRAL APPROXIMATIONS OVER THE SUBINTERVALS,\nC                    WORK(LIMIT*3+1), ..., WORK(LIMIT*3)\nC                     CONTAIN THE ERROR ESTIMATES.\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  DQAGIE,XERROR\nC***END PROLOGUE  DQAGI\nC\n      DOUBLE PRECISION ABSERR,BOUND,EPSABS,EPSREL,RESULT,WORK\n      INTEGER IER,INF,IWORK,LAST,LENW,LIMIT,LVL,L1,L2,L3,NEVAL\nC\n      DIMENSION IWORK(LIMIT),WORK(LENW)\nC\n      EXTERNAL F\nC\nC         CHECK VALIDITY OF LIMIT AND LENW.\nC\nC***FIRST EXECUTABLE STATEMENT  DQAGI\n      IER = 6\n      NEVAL = 0\n      LAST = 0\n      RESULT = 0.0D+00\n      ABSERR = 0.0D+00\n      IF(LIMIT.LT.1.OR.LENW.LT.LIMIT*4) GO TO 10\nC\nC         PREPARE CALL FOR DQAGIE.\nC\n      L1 = LIMIT+1\n      L2 = LIMIT+L1\n      L3 = LIMIT+L2\nC\n      CALL DQAGIE(F,BOUND,INF,EPSABS,EPSREL,LIMIT,RESULT,ABSERR,\n     *  NEVAL,IER,WORK(1),WORK(L1),WORK(L2),WORK(L3),IWORK,LAST)\nC\nC         CALL ERROR HANDLER IF NECESSARY.\nC\n       LVL = 0\n10    IF(IER.EQ.6) LVL = 1\n      IF(IER.GT.0) CALL XERROR('ABNORMAL RETURN FROM DQAGI',26,IER,LVL)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/quadpack/dqagie.f",
    "content": "      SUBROUTINE DQAGIE(F,BOUND,INF,EPSABS,EPSREL,LIMIT,RESULT,ABSERR,\n     *   NEVAL,IER,ALIST,BLIST,RLIST,ELIST,IORD,LAST)\nC***BEGIN PROLOGUE  DQAGIE\nC***DATE WRITTEN   800101   (YYMMDD)\nC***REVISION DATE  830518   (YYMMDD)\nC***CATEGORY NO.  H2A3A1,H2A4A1\nC***KEYWORDS  AUTOMATIC INTEGRATOR, INFINITE INTERVALS,\nC             GENERAL-PURPOSE, TRANSFORMATION, EXTRAPOLATION,\nC             GLOBALLY ADAPTIVE\nC***AUTHOR  PIESSENS,ROBERT,APPL. MATH & PROGR. DIV - K.U.LEUVEN\nC           DE DONCKER,ELISE,APPL. MATH & PROGR. DIV - K.U.LEUVEN\nC***PURPOSE  THE ROUTINE CALCULATES AN APPROXIMATION RESULT TO A GIVEN\nC            INTEGRAL   I = INTEGRAL OF F OVER (BOUND,+INFINITY)\nC            OR I = INTEGRAL OF F OVER (-INFINITY,BOUND)\nC            OR I = INTEGRAL OF F OVER (-INFINITY,+INFINITY),\nC            HOPEFULLY SATISFYING FOLLOWING CLAIM FOR ACCURACY\nC            ABS(I-RESULT).LE.MAX(EPSABS,EPSREL*ABS(I))\nC***DESCRIPTION\nC\nC INTEGRATION OVER INFINITE INTERVALS\nC STANDARD FORTRAN SUBROUTINE\nC\nC            F      - SUBROUTINE F(X,IERR,RESULT) DEFINING THE INTEGRAND\nC                     FUNCTION F(X). THE ACTUAL NAME FOR F NEEDS TO BE\nC                     DECLARED E X T E R N A L IN THE DRIVER PROGRAM.\nC\nC            BOUND  - DOUBLE PRECISION\nC                     FINITE BOUND OF INTEGRATION RANGE\nC                     (HAS NO MEANING IF INTERVAL IS DOUBLY-INFINITE)\nC\nC            INF    - DOUBLE PRECISION\nC                     INDICATING THE KIND OF INTEGRATION RANGE INVOLVED\nC                     INF = 1 CORRESPONDS TO  (BOUND,+INFINITY),\nC                     INF = -1            TO  (-INFINITY,BOUND),\nC                     INF = 2             TO (-INFINITY,+INFINITY).\nC\nC            EPSABS - DOUBLE PRECISION\nC                     ABSOLUTE ACCURACY REQUESTED\nC            EPSREL - DOUBLE PRECISION\nC                     RELATIVE ACCURACY REQUESTED\nC                     IF  EPSABS.LE.0\nC                     AND EPSREL.LT.MAX(50*REL.MACH.ACC.,0.5D-28),\nC                     THE ROUTINE WILL END WITH IER = 6.\nC\nC            LIMIT  - INTEGER\nC                     GIVES AN UPPER BOUND ON THE NUMBER OF SUBINTERVALS\nC                     IN THE PARTITION OF (A,B), LIMIT.GE.1\nC\nC         ON RETURN\nC            RESULT - DOUBLE PRECISION\nC                     APPROXIMATION TO THE INTEGRAL\nC\nC            ABSERR - DOUBLE PRECISION\nC                     ESTIMATE OF THE MODULUS OF THE ABSOLUTE ERROR,\nC                     WHICH SHOULD EQUAL OR EXCEED ABS(I-RESULT)\nC\nC            NEVAL  - INTEGER\nC                     NUMBER OF INTEGRAND EVALUATIONS\nC\nC            IER    - INTEGER\nC                     IER = 0 NORMAL AND RELIABLE TERMINATION OF THE\nC                             ROUTINE. IT IS ASSUMED THAT THE REQUESTED\nC                             ACCURACY HAS BEEN ACHIEVED.\nC                     IER.GT.0 ABNORMAL TERMINATION OF THE ROUTINE. THE\nC                             ESTIMATES FOR RESULT AND ERROR ARE LESS\nC                             RELIABLE. IT IS ASSUMED THAT THE REQUESTED\nC                             ACCURACY HAS NOT BEEN ACHIEVED.\nC                     IER.LT.0 EXIT REQUESTED FROM USER-SUPPLIED\nC                             FUNCTION.\nC\nC            ERROR MESSAGES\nC                     IER = 1 MAXIMUM NUMBER OF SUBDIVISIONS ALLOWED\nC                             HAS BEEN ACHIEVED. ONE CAN ALLOW MORE\nC                             SUBDIVISIONS BY INCREASING THE VALUE OF\nC                             LIMIT (AND TAKING THE ACCORDING DIMENSION\nC                             ADJUSTMENTS INTO ACCOUNT). HOWEVER,IF\nC                             THIS YIELDS NO IMPROVEMENT IT IS ADVISED\nC                             TO ANALYZE THE INTEGRAND IN ORDER TO\nC                             DETERMINE THE INTEGRATION DIFFICULTIES.\nC                             IF THE POSITION OF A LOCAL DIFFICULTY CAN\nC                             BE DETERMINED (E.G. SINGULARITY,\nC                             DISCONTINUITY WITHIN THE INTERVAL) ONE\nC                             WILL PROBABLY GAIN FROM SPLITTING UP THE\nC                             INTERVAL AT THIS POINT AND CALLING THE\nC                             INTEGRATOR ON THE SUBRANGES. IF POSSIBLE,\nC                             AN APPROPRIATE SPECIAL-PURPOSE INTEGRATOR\nC                             SHOULD BE USED, WHICH IS DESIGNED FOR\nC                             HANDLING THE TYPE OF DIFFICULTY INVOLVED.\nC                         = 2 THE OCCURRENCE OF ROUNDOFF ERROR IS\nC                             DETECTED, WHICH PREVENTS THE REQUESTED\nC                             TOLERANCE FROM BEING ACHIEVED.\nC                             THE ERROR MAY BE UNDER-ESTIMATED.\nC                         = 3 EXTREMELY BAD INTEGRAND BEHAVIOUR OCCURS\nC                             AT SOME POINTS OF THE INTEGRATION\nC                             INTERVAL.\nC                         = 4 THE ALGORITHM DOES NOT CONVERGE.\nC                             ROUNDOFF ERROR IS DETECTED IN THE\nC                             EXTRAPOLATION TABLE.\nC                             IT IS ASSUMED THAT THE REQUESTED TOLERANCE\nC                             CANNOT BE ACHIEVED, AND THAT THE RETURNED\nC                             RESULT IS THE BEST WHICH CAN BE OBTAINED.\nC                         = 5 THE INTEGRAL IS PROBABLY DIVERGENT, OR\nC                             SLOWLY CONVERGENT. IT MUST BE NOTED THAT\nC                             DIVERGENCE CAN OCCUR WITH ANY OTHER VALUE\nC                             OF IER.\nC                         = 6 THE INPUT IS INVALID, BECAUSE\nC                             (EPSABS.LE.0 AND\nC                              EPSREL.LT.MAX(50*REL.MACH.ACC.,0.5D-28),\nC                             RESULT, ABSERR, NEVAL, LAST, RLIST(1),\nC                             ELIST(1) AND IORD(1) ARE SET TO ZERO.\nC                             ALIST(1) AND BLIST(1) ARE SET TO 0\nC                             AND 1 RESPECTIVELY.\nC\nC            ALIST  - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION AT LEAST LIMIT, THE FIRST\nC                      LAST  ELEMENTS OF WHICH ARE THE LEFT\nC                     END POINTS OF THE SUBINTERVALS IN THE PARTITION\nC                     OF THE TRANSFORMED INTEGRATION RANGE (0,1).\nC\nC            BLIST  - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION AT LEAST LIMIT, THE FIRST\nC                      LAST  ELEMENTS OF WHICH ARE THE RIGHT\nC                     END POINTS OF THE SUBINTERVALS IN THE PARTITION\nC                     OF THE TRANSFORMED INTEGRATION RANGE (0,1).\nC\nC            RLIST  - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION AT LEAST LIMIT, THE FIRST\nC                      LAST  ELEMENTS OF WHICH ARE THE INTEGRAL\nC                     APPROXIMATIONS ON THE SUBINTERVALS\nC\nC            ELIST  - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION AT LEAST LIMIT,  THE FIRST\nC                     LAST ELEMENTS OF WHICH ARE THE MODULI OF THE\nC                     ABSOLUTE ERROR ESTIMATES ON THE SUBINTERVALS\nC\nC            IORD   - INTEGER\nC                     VECTOR OF DIMENSION LIMIT, THE FIRST K\nC                     ELEMENTS OF WHICH ARE POINTERS TO THE\nC                     ERROR ESTIMATES OVER THE SUBINTERVALS,\nC                     SUCH THAT ELIST(IORD(1)), ..., ELIST(IORD(K))\nC                     FORM A DECREASING SEQUENCE, WITH K = LAST\nC                     IF LAST.LE.(LIMIT/2+2), AND K = LIMIT+1-LAST\nC                     OTHERWISE\nC\nC            LAST   - INTEGER\nC                     NUMBER OF SUBINTERVALS ACTUALLY PRODUCED\nC                     IN THE SUBDIVISION PROCESS\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH,DQELG,DQK15I,DQPSRT\nC***END PROLOGUE  DQAGIE\n      DOUBLE PRECISION ABSEPS,ABSERR,ALIST,AREA,AREA1,AREA12,AREA2,A1,\n     *  A2,BLIST,BOUN,BOUND,B1,B2,CORREC,DABS,DEFABS,DEFAB1,DEFAB2,\n     *  DMAX1,DRES,D1MACH,ELIST,EPMACH,EPSABS,EPSREL,ERLARG,ERLAST,\n     *  ERRBND,ERRMAX,ERROR1,ERROR2,ERRO12,ERRSUM,ERTEST,OFLOW,RESABS,\n     *  RESEPS,RESULT,RES3LA,RLIST,RLIST2,SMALL,UFLOW\n      INTEGER ID,IER,IERRO,INF,IORD,IROFF1,IROFF2,IROFF3,JUPBND,K,KSGN,\n     *  KTMIN,LAST,LIMIT,MAXERR,NEVAL,NRES,NRMAX,NUMRL2\n      LOGICAL EXTRAP,NOEXT\nC\n      DIMENSION ALIST(LIMIT),BLIST(LIMIT),ELIST(LIMIT),IORD(LIMIT),\n     *  RES3LA(3),RLIST(LIMIT),RLIST2(52)\nC\n      EXTERNAL F\nC\nC            THE DIMENSION OF RLIST2 IS DETERMINED BY THE VALUE OF\nC            LIMEXP IN SUBROUTINE DQELG.\nC\nC\nC            LIST OF MAJOR VARIABLES\nC            -----------------------\nC\nC           ALIST     - LIST OF LEFT END POINTS OF ALL SUBINTERVALS\nC                       CONSIDERED UP TO NOW\nC           BLIST     - LIST OF RIGHT END POINTS OF ALL SUBINTERVALS\nC                       CONSIDERED UP TO NOW\nC           RLIST(I)  - APPROXIMATION TO THE INTEGRAL OVER\nC                       (ALIST(I),BLIST(I))\nC           RLIST2    - ARRAY OF DIMENSION AT LEAST (LIMEXP+2),\nC                       CONTAINING THE PART OF THE EPSILON TABLE\nC                       WICH IS STILL NEEDED FOR FURTHER COMPUTATIONS\nC           ELIST(I)  - ERROR ESTIMATE APPLYING TO RLIST(I)\nC           MAXERR    - POINTER TO THE INTERVAL WITH LARGEST ERROR\nC                       ESTIMATE\nC           ERRMAX    - ELIST(MAXERR)\nC           ERLAST    - ERROR ON THE INTERVAL CURRENTLY SUBDIVIDED\nC                       (BEFORE THAT SUBDIVISION HAS TAKEN PLACE)\nC           AREA      - SUM OF THE INTEGRALS OVER THE SUBINTERVALS\nC           ERRSUM    - SUM OF THE ERRORS OVER THE SUBINTERVALS\nC           ERRBND    - REQUESTED ACCURACY MAX(EPSABS,EPSREL*\nC                       ABS(RESULT))\nC           *****1    - VARIABLE FOR THE LEFT SUBINTERVAL\nC           *****2    - VARIABLE FOR THE RIGHT SUBINTERVAL\nC           LAST      - INDEX FOR SUBDIVISION\nC           NRES      - NUMBER OF CALLS TO THE EXTRAPOLATION ROUTINE\nC           NUMRL2    - NUMBER OF ELEMENTS CURRENTLY IN RLIST2. IF AN\nC                       APPROPRIATE APPROXIMATION TO THE COMPOUNDED\nC                       INTEGRAL HAS BEEN OBTAINED, IT IS PUT IN\nC                       RLIST2(NUMRL2) AFTER NUMRL2 HAS BEEN INCREASED\nC                       BY ONE.\nC           SMALL     - LENGTH OF THE SMALLEST INTERVAL CONSIDERED UP\nC                       TO NOW, MULTIPLIED BY 1.5\nC           ERLARG    - SUM OF THE ERRORS OVER THE INTERVALS LARGER\nC                       THAN THE SMALLEST INTERVAL CONSIDERED UP TO NOW\nC           EXTRAP    - LOGICAL VARIABLE DENOTING THAT THE ROUTINE\nC                       IS ATTEMPTING TO PERFORM EXTRAPOLATION. I.E.\nC                       BEFORE SUBDIVIDING THE SMALLEST INTERVAL WE\nC                       TRY TO DECREASE THE VALUE OF ERLARG.\nC           NOEXT     - LOGICAL VARIABLE DENOTING THAT EXTRAPOLATION\nC                       IS NO LONGER ALLOWED (TRUE-VALUE)\nC\nC            MACHINE DEPENDENT CONSTANTS\nC            ---------------------------\nC\nC           EPMACH IS THE LARGEST RELATIVE SPACING.\nC           UFLOW IS THE SMALLEST POSITIVE MAGNITUDE.\nC           OFLOW IS THE LARGEST POSITIVE MAGNITUDE.\nC\nC***FIRST EXECUTABLE STATEMENT  DQAGIE\n       EPMACH = D1MACH(4)\nC\nC           TEST ON VALIDITY OF PARAMETERS\nC           -----------------------------\nC\n      IER = 0\n      NEVAL = 0\n      LAST = 0\n      RESULT = 0.0D+00\n      ABSERR = 0.0D+00\n      ALIST(1) = 0.0D+00\n      BLIST(1) = 0.1D+01\n      RLIST(1) = 0.0D+00\n      ELIST(1) = 0.0D+00\n      IORD(1) = 0\n      IF(EPSABS.LE.0.0D+00.AND.EPSREL.LT.DMAX1(0.5D+02*EPMACH,0.5D-28))\n     *  IER = 6\n       IF(IER.EQ.6) GO TO 999\nC\nC\nC           FIRST APPROXIMATION TO THE INTEGRAL\nC           -----------------------------------\nC\nC           DETERMINE THE INTERVAL TO BE MAPPED ONTO (0,1).\nC           IF INF = 2 THE INTEGRAL IS COMPUTED AS I = I1+I2, WHERE\nC           I1 = INTEGRAL OF F OVER (-INFINITY,0),\nC           I2 = INTEGRAL OF F OVER (0,+INFINITY).\nC\n      BOUN = BOUND\n      IF(INF.EQ.2) BOUN = 0.0D+00\n      CALL DQK15I(F,BOUN,INF,0.0D+00,0.1D+01,RESULT,ABSERR,\n     *  DEFABS,RESABS,IER)\n      IF (IER .LT. 0) RETURN\nC\nC           TEST ON ACCURACY\nC\n      LAST = 1\n      RLIST(1) = RESULT\n      ELIST(1) = ABSERR\n      IORD(1) = 1\n      DRES = DABS(RESULT)\n      ERRBND = DMAX1(EPSABS,EPSREL*DRES)\n      IF(ABSERR.LE.1.0D+02*EPMACH*DEFABS.AND.ABSERR.GT.ERRBND) IER = 2\n      IF(LIMIT.EQ.1) IER = 1\n      IF(IER.NE.0.OR.(ABSERR.LE.ERRBND.AND.ABSERR.NE.RESABS).OR.\n     *  ABSERR.EQ.0.0D+00) GO TO 130\nC\nC           INITIALIZATION\nC           --------------\nC\n      UFLOW = D1MACH(1)\n      OFLOW = D1MACH(2)\n      RLIST2(1) = RESULT\n      ERRMAX = ABSERR\n      MAXERR = 1\n      AREA = RESULT\n      ERRSUM = ABSERR\n      ABSERR = OFLOW\n      NRMAX = 1\n      NRES = 0\n      KTMIN = 0\n      NUMRL2 = 2\n      EXTRAP = .FALSE.\n      NOEXT = .FALSE.\n      IERRO = 0\n      IROFF1 = 0\n      IROFF2 = 0\n      IROFF3 = 0\n      KSGN = -1\n      IF(DRES.GE.(0.1D+01-0.5D+02*EPMACH)*DEFABS) KSGN = 1\nC\nC           MAIN DO-LOOP\nC           ------------\nC\n      DO 90 LAST = 2,LIMIT\nC\nC           BISECT THE SUBINTERVAL WITH NRMAX-TH LARGEST ERROR ESTIMATE.\nC\n        A1 = ALIST(MAXERR)\n        B1 = 0.5D+00*(ALIST(MAXERR)+BLIST(MAXERR))\n        A2 = B1\n        B2 = BLIST(MAXERR)\n        ERLAST = ERRMAX\n        CALL DQK15I(F,BOUN,INF,A1,B1,AREA1,ERROR1,RESABS,DEFAB1,IER)\n        IF (IER .LT. 0) RETURN\n        CALL DQK15I(F,BOUN,INF,A2,B2,AREA2,ERROR2,RESABS,DEFAB2,IER)\n        IF (IER .LT. 0) RETURN\nC\nC           IMPROVE PREVIOUS APPROXIMATIONS TO INTEGRAL\nC           AND ERROR AND TEST FOR ACCURACY.\nC\n        AREA12 = AREA1+AREA2\n        ERRO12 = ERROR1+ERROR2\n        ERRSUM = ERRSUM+ERRO12-ERRMAX\n        AREA = AREA+AREA12-RLIST(MAXERR)\n        IF(DEFAB1.EQ.ERROR1.OR.DEFAB2.EQ.ERROR2)GO TO 15\n        IF(DABS(RLIST(MAXERR)-AREA12).GT.0.1D-04*DABS(AREA12)\n     *  .OR.ERRO12.LT.0.99D+00*ERRMAX) GO TO 10\n        IF(EXTRAP) IROFF2 = IROFF2+1\n        IF(.NOT.EXTRAP) IROFF1 = IROFF1+1\n   10   IF(LAST.GT.10.AND.ERRO12.GT.ERRMAX) IROFF3 = IROFF3+1\n   15   RLIST(MAXERR) = AREA1\n        RLIST(LAST) = AREA2\n        ERRBND = DMAX1(EPSABS,EPSREL*DABS(AREA))\nC\nC           TEST FOR ROUNDOFF ERROR AND EVENTUALLY SET ERROR FLAG.\nC\n        IF(IROFF1+IROFF2.GE.10.OR.IROFF3.GE.20) IER = 2\n        IF(IROFF2.GE.5) IERRO = 3\nC\nC           SET ERROR FLAG IN THE CASE THAT THE NUMBER OF\nC           SUBINTERVALS EQUALS LIMIT.\nC\n        IF(LAST.EQ.LIMIT) IER = 1\nC\nC           SET ERROR FLAG IN THE CASE OF BAD INTEGRAND BEHAVIOUR\nC           AT SOME POINTS OF THE INTEGRATION RANGE.\nC\n        IF(DMAX1(DABS(A1),DABS(B2)).LE.(0.1D+01+0.1D+03*EPMACH)*\n     *  (DABS(A2)+0.1D+04*UFLOW)) IER = 4\nC\nC           APPEND THE NEWLY-CREATED INTERVALS TO THE LIST.\nC\n        IF(ERROR2.GT.ERROR1) GO TO 20\n        ALIST(LAST) = A2\n        BLIST(MAXERR) = B1\n        BLIST(LAST) = B2\n        ELIST(MAXERR) = ERROR1\n        ELIST(LAST) = ERROR2\n        GO TO 30\n   20   ALIST(MAXERR) = A2\n        ALIST(LAST) = A1\n        BLIST(LAST) = B1\n        RLIST(MAXERR) = AREA2\n        RLIST(LAST) = AREA1\n        ELIST(MAXERR) = ERROR2\n        ELIST(LAST) = ERROR1\nC\nC           CALL SUBROUTINE DQPSRT TO MAINTAIN THE DESCENDING ORDERING\nC           IN THE LIST OF ERROR ESTIMATES AND SELECT THE SUBINTERVAL\nC           WITH NRMAX-TH LARGEST ERROR ESTIMATE (TO BE BISECTED NEXT).\nC\n   30   CALL DQPSRT(LIMIT,LAST,MAXERR,ERRMAX,ELIST,IORD,NRMAX)\n        IF(ERRSUM.LE.ERRBND) GO TO 115\n        IF(IER.NE.0) GO TO 100\n        IF(LAST.EQ.2) GO TO 80\n        IF(NOEXT) GO TO 90\n        ERLARG = ERLARG-ERLAST\n        IF(DABS(B1-A1).GT.SMALL) ERLARG = ERLARG+ERRO12\n        IF(EXTRAP) GO TO 40\nC\nC           TEST WHETHER THE INTERVAL TO BE BISECTED NEXT IS THE\nC           SMALLEST INTERVAL.\nC\n        IF(DABS(BLIST(MAXERR)-ALIST(MAXERR)).GT.SMALL) GO TO 90\n        EXTRAP = .TRUE.\n        NRMAX = 2\n   40   IF(IERRO.EQ.3.OR.ERLARG.LE.ERTEST) GO TO 60\nC\nC           THE SMALLEST INTERVAL HAS THE LARGEST ERROR.\nC           BEFORE BISECTING DECREASE THE SUM OF THE ERRORS OVER THE\nC           LARGER INTERVALS (ERLARG) AND PERFORM EXTRAPOLATION.\nC\n        ID = NRMAX\n        JUPBND = LAST\n        IF(LAST.GT.(2+LIMIT/2)) JUPBND = LIMIT+3-LAST\n        DO 50 K = ID,JUPBND\n          MAXERR = IORD(NRMAX)\n          ERRMAX = ELIST(MAXERR)\n          IF(DABS(BLIST(MAXERR)-ALIST(MAXERR)).GT.SMALL) GO TO 90\n          NRMAX = NRMAX+1\n   50   CONTINUE\nC\nC           PERFORM EXTRAPOLATION.\nC\n   60   NUMRL2 = NUMRL2+1\n        RLIST2(NUMRL2) = AREA\n        CALL DQELG(NUMRL2,RLIST2,RESEPS,ABSEPS,RES3LA,NRES)\n        KTMIN = KTMIN+1\n        IF(KTMIN.GT.5.AND.ABSERR.LT.0.1D-02*ERRSUM) IER = 5\n        IF(ABSEPS.GE.ABSERR) GO TO 70\n        KTMIN = 0\n        ABSERR = ABSEPS\n        RESULT = RESEPS\n        CORREC = ERLARG\n        ERTEST = DMAX1(EPSABS,EPSREL*DABS(RESEPS))\n        IF(ABSERR.LE.ERTEST) GO TO 100\nC\nC            PREPARE BISECTION OF THE SMALLEST INTERVAL.\nC\n   70   IF(NUMRL2.EQ.1) NOEXT = .TRUE.\n        IF(IER.EQ.5) GO TO 100\n        MAXERR = IORD(1)\n        ERRMAX = ELIST(MAXERR)\n        NRMAX = 1\n        EXTRAP = .FALSE.\n        SMALL = SMALL*0.5D+00\n        ERLARG = ERRSUM\n        GO TO 90\n   80   SMALL = 0.375D+00\n        ERLARG = ERRSUM\n        ERTEST = ERRBND\n        RLIST2(2) = AREA\n   90 CONTINUE\nC\nC           SET FINAL RESULT AND ERROR ESTIMATE.\nC           ------------------------------------\nC\n  100 IF(ABSERR.EQ.OFLOW) GO TO 115\n      IF((IER+IERRO).EQ.0) GO TO 110\n      IF(IERRO.EQ.3) ABSERR = ABSERR+CORREC\n      IF(IER.EQ.0) IER = 3\n      IF(RESULT.NE.0.0D+00.AND.AREA.NE.0.0D+00)GO TO 105\n      IF(ABSERR.GT.ERRSUM)GO TO 115\n      IF(AREA.EQ.0.0D+00) GO TO 130\n      GO TO 110\n  105 IF(ABSERR/DABS(RESULT).GT.ERRSUM/DABS(AREA))GO TO 115\nC\nC           TEST ON DIVERGENCE\nC\n  110 IF(KSGN.EQ.(-1).AND.DMAX1(DABS(RESULT),DABS(AREA)).LE.\n     * DEFABS*0.1D-01) GO TO 130\n      IF(0.1D-01.GT.(RESULT/AREA).OR.(RESULT/AREA).GT.0.1D+03.\n     *OR.ERRSUM.GT.DABS(AREA)) IER = 6\n      GO TO 130\nC\nC           COMPUTE GLOBAL INTEGRAL SUM.\nC\n  115 RESULT = 0.0D+00\n      DO 120 K = 1,LAST\n        RESULT = RESULT+RLIST(K)\n  120 CONTINUE\n      ABSERR = ERRSUM\n  130 NEVAL = 30*LAST-15\n      IF(INF.EQ.2) NEVAL = 2*NEVAL\n      IF(IER.GT.2) IER=IER-1\n  999 RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/quadpack/dqagp.f",
    "content": "      SUBROUTINE DQAGP(F,A,B,NPTS2,POINTS,EPSABS,EPSREL,RESULT,ABSERR,\n     *   NEVAL,IER,LENIW,LENW,LAST,IWORK,WORK)\nC***BEGIN PROLOGUE  DQAGP\nC***DATE WRITTEN   800101   (YYMMDD)\nC***REVISION DATE  830518   (YYMMDD)\nC***CATEGORY NO.  H2A2A1\nC***KEYWORDS  AUTOMATIC INTEGRATOR, GENERAL-PURPOSE,\nC             SINGULARITIES AT USER SPECIFIED POINTS,\nC             EXTRAPOLATION, GLOBALLY ADAPTIVE\nC***AUTHOR  PIESSENS,ROBERT,APPL. MATH. & PROGR. DIV - K.U.LEUVEN\nC           DE DONCKER,ELISE,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC***PURPOSE  THE ROUTINE CALCULATES AN APPROXIMATION RESULT TO A GIVEN\nC            DEFINITE INTEGRAL I = INTEGRAL OF F OVER (A,B),\nC            HOPEFULLY SATISFYING FOLLOWING CLAIM FOR ACCURACY\nC            BREAK POINTS OF THE INTEGRATION INTERVAL, WHERE LOCAL\nC            DIFFICULTIES OF THE INTEGRAND MAY OCCUR (E.G.\nC            SINGULARITIES, DISCONTINUITIES), ARE PROVIDED BY THE USER.\nC***DESCRIPTION\nC\nC        COMPUTATION OF A DEFINITE INTEGRAL\nC        STANDARD FORTRAN SUBROUTINE\nC        DOUBLE PRECISION VERSION\nC\nC        PARAMETERS\nC         ON ENTRY\nC            F      - SUBROUTINE F(X,IERR,RESULT) DEFINING THE INTEGRAND\nC                     FUNCTION F(X). THE ACTUAL NAME FOR F NEEDS TO BE\nC                     DECLARED E X T E R N A L IN THE DRIVER PROGRAM.\nC\nC            A      - DOUBLE PRECISION\nC                     LOWER LIMIT OF INTEGRATION\nC\nC            B      - DOUBLE PRECISION\nC                     UPPER LIMIT OF INTEGRATION\nC\nC            NPTS2  - INTEGER\nC                     NUMBER EQUAL TO TWO MORE THAN THE NUMBER OF\nC                     USER-SUPPLIED BREAK POINTS WITHIN THE INTEGRATION\nC                     RANGE, NPTS.GE.2.\nC                     IF NPTS2.LT.2, THE ROUTINE WILL END WITH IER = 6.\nC\nC            POINTS - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION NPTS2, THE FIRST (NPTS2-2)\nC                     ELEMENTS OF WHICH ARE THE USER PROVIDED BREAK\nC                     POINTS. IF THESE POINTS DO NOT CONSTITUTE AN\nC                     ASCENDING SEQUENCE THERE WILL BE AN AUTOMATIC\nC                     SORTING.\nC\nC            EPSABS - DOUBLE PRECISION\nC                     ABSOLUTE ACCURACY REQUESTED\nC            EPSREL - DOUBLE PRECISION\nC                     RELATIVE ACCURACY REQUESTED\nC                     IF  EPSABS.LE.0\nC                     AND EPSREL.LT.MAX(50*REL.MACH.ACC.,0.5D-28),\nC                     THE ROUTINE WILL END WITH IER = 6.\nC\nC         ON RETURN\nC            RESULT - DOUBLE PRECISION\nC                     APPROXIMATION TO THE INTEGRAL\nC\nC            ABSERR - DOUBLE PRECISION\nC                     ESTIMATE OF THE MODULUS OF THE ABSOLUTE ERROR,\nC                     WHICH SHOULD EQUAL OR EXCEED ABS(I-RESULT)\nC\nC            NEVAL  - INTEGER\nC                     NUMBER OF INTEGRAND EVALUATIONS\nC\nC            IER    - INTEGER\nC                     IER = 0 NORMAL AND RELIABLE TERMINATION OF THE\nC                             ROUTINE. IT IS ASSUMED THAT THE REQUESTED\nC                             ACCURACY HAS BEEN ACHIEVED.\nC                     IER.GT.0 ABNORMAL TERMINATION OF THE ROUTINE.\nC                             THE ESTIMATES FOR INTEGRAL AND ERROR ARE\nC                             LESS RELIABLE. IT IS ASSUMED THAT THE\nC                             REQUESTED ACCURACY HAS NOT BEEN ACHIEVED.\nC            ERROR MESSAGES\nC                     IER = 1 MAXIMUM NUMBER OF SUBDIVISIONS ALLOWED\nC                             HAS BEEN ACHIEVED. ONE CAN ALLOW MORE\nC                             SUBDIVISIONS BY INCREASING THE VALUE OF\nC                             LIMIT (AND TAKING THE ACCORDING DIMENSION\nC                             ADJUSTMENTS INTO ACCOUNT). HOWEVER, IF\nC                             THIS YIELDS NO IMPROVEMENT IT IS ADVISED\nC                             TO ANALYZE THE INTEGRAND IN ORDER TO\nC                             DETERMINE THE INTEGRATION DIFFICULTIES. IF\nC                             THE POSITION OF A LOCAL DIFFICULTY CAN BE\nC                             DETERMINED (I.E. SINGULARITY,\nC                             DISCONTINUITY WITHIN THE INTERVAL), IT\nC                             SHOULD BE SUPPLIED TO THE ROUTINE AS AN\nC                             ELEMENT OF THE VECTOR POINTS. IF NECESSARY\nC                             AN APPROPRIATE SPECIAL-PURPOSE INTEGRATOR\nC                             MUST BE USED, WHICH IS DESIGNED FOR\nC                             HANDLING THE TYPE OF DIFFICULTY INVOLVED.\nC                         = 2 THE OCCURRENCE OF ROUNDOFF ERROR IS\nC                             DETECTED, WHICH PREVENTS THE REQUESTED\nC                             TOLERANCE FROM BEING ACHIEVED.\nC                             THE ERROR MAY BE UNDER-ESTIMATED.\nC                         = 3 EXTREMELY BAD INTEGRAND BEHAVIOUR OCCURS\nC                             AT SOME POINTS OF THE INTEGRATION\nC                             INTERVAL.\nC                         = 4 THE ALGORITHM DOES NOT CONVERGE.\nC                             ROUNDOFF ERROR IS DETECTED IN THE\nC                             EXTRAPOLATION TABLE.\nC                             IT IS PRESUMED THAT THE REQUESTED\nC                             TOLERANCE CANNOT BE ACHIEVED, AND THAT\nC                             THE RETURNED RESULT IS THE BEST WHICH\nC                             CAN BE OBTAINED.\nC                         = 5 THE INTEGRAL IS PROBABLY DIVERGENT, OR\nC                             SLOWLY CONVERGENT. IT MUST BE NOTED THAT\nC                             DIVERGENCE CAN OCCUR WITH ANY OTHER VALUE\nC                             OF IER.GT.0.\nC                         = 6 THE INPUT IS INVALID BECAUSE\nC                             NPTS2.LT.2 OR\nC                             BREAK POINTS ARE SPECIFIED OUTSIDE\nC                             THE INTEGRATION RANGE OR\nC                             (EPSABS.LE.0 AND\nC                              EPSREL.LT.MAX(50*REL.MACH.ACC.,0.5D-28))\nC                             RESULT, ABSERR, NEVAL, LAST ARE SET TO\nC                             ZERO. EXEPT WHEN LENIW OR LENW OR NPTS2 IS\nC                             INVALID, IWORK(1), IWORK(LIMIT+1),\nC                             WORK(LIMIT*2+1) AND WORK(LIMIT*3+1)\nC                             ARE SET TO ZERO.\nC                             WORK(1) IS SET TO A AND WORK(LIMIT+1)\nC                             TO B (WHERE LIMIT = (LENIW-NPTS2)/2).\nC\nC         DIMENSIONING PARAMETERS\nC            LENIW - INTEGER\nC                    DIMENSIONING PARAMETER FOR IWORK\nC                    LENIW DETERMINES LIMIT = (LENIW-NPTS2)/2,\nC                    WHICH IS THE MAXIMUM NUMBER OF SUBINTERVALS IN THE\nC                    PARTITION OF THE GIVEN INTEGRATION INTERVAL (A,B),\nC                    LENIW.GE.(3*NPTS2-2).\nC                    IF LENIW.LT.(3*NPTS2-2), THE ROUTINE WILL END WITH\nC                    IER = 6.\nC\nC            LENW  - INTEGER\nC                    DIMENSIONING PARAMETER FOR WORK\nC                    LENW MUST BE AT LEAST LENIW*2-NPTS2.\nC                    IF LENW.LT.LENIW*2-NPTS2, THE ROUTINE WILL END\nC                    WITH IER = 6.\nC\nC            LAST  - INTEGER\nC                    ON RETURN, LAST EQUALS THE NUMBER OF SUBINTERVALS\nC                    PRODUCED IN THE SUBDIVISION PROCESS, WHICH\nC                    DETERMINES THE NUMBER OF SIGNIFICANT ELEMENTS\nC                    ACTUALLY IN THE WORK ARRAYS.\nC\nC         WORK ARRAYS\nC            IWORK - INTEGER\nC                    VECTOR OF DIMENSION AT LEAST LENIW. ON RETURN,\nC                    THE FIRST K ELEMENTS OF WHICH CONTAIN\nC                    POINTERS TO THE ERROR ESTIMATES OVER THE\nC                    SUBINTERVALS, SUCH THAT WORK(LIMIT*3+IWORK(1)),...,\nC                    WORK(LIMIT*3+IWORK(K)) FORM A DECREASING\nC                    SEQUENCE, WITH K = LAST IF LAST.LE.(LIMIT/2+2), AND\nC                    K = LIMIT+1-LAST OTHERWISE\nC                    IWORK(LIMIT+1), ...,IWORK(LIMIT+LAST) CONTAIN THE\nC                     SUBDIVISION LEVELS OF THE SUBINTERVALS, I.E.\nC                     IF (AA,BB) IS A SUBINTERVAL OF (P1,P2)\nC                     WHERE P1 AS WELL AS P2 IS A USER-PROVIDED\nC                     BREAK POINT OR INTEGRATION LIMIT, THEN (AA,BB) HAS\nC                     LEVEL L IF ABS(BB-AA) = ABS(P2-P1)*2**(-L),\nC                    IWORK(LIMIT*2+1), ..., IWORK(LIMIT*2+NPTS2) HAVE\nC                     NO SIGNIFICANCE FOR THE USER,\nC                    NOTE THAT LIMIT = (LENIW-NPTS2)/2.\nC\nC            WORK  - DOUBLE PRECISION\nC                    VECTOR OF DIMENSION AT LEAST LENW\nC                    ON RETURN\nC                    WORK(1), ..., WORK(LAST) CONTAIN THE LEFT\nC                     END POINTS OF THE SUBINTERVALS IN THE\nC                     PARTITION OF (A,B),\nC                    WORK(LIMIT+1), ..., WORK(LIMIT+LAST) CONTAIN\nC                     THE RIGHT END POINTS,\nC                    WORK(LIMIT*2+1), ..., WORK(LIMIT*2+LAST) CONTAIN\nC                     THE INTEGRAL APPROXIMATIONS OVER THE SUBINTERVALS,\nC                    WORK(LIMIT*3+1), ..., WORK(LIMIT*3+LAST)\nC                     CONTAIN THE CORRESPONDING ERROR ESTIMATES,\nC                    WORK(LIMIT*4+1), ..., WORK(LIMIT*4+NPTS2)\nC                     CONTAIN THE INTEGRATION LIMITS AND THE\nC                     BREAK POINTS SORTED IN AN ASCENDING SEQUENCE.\nC                    NOTE THAT LIMIT = (LENIW-NPTS2)/2.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  DQAGPE,XERROR\nC***END PROLOGUE  DQAGP\nC\n      DOUBLE PRECISION A,ABSERR,B,EPSABS,EPSREL,POINTS,RESULT,WORK\n      INTEGER IER,IWORK,LAST,LENIW,LENW,LIMIT,LVL,L1,L2,L3,L4,NEVAL,\n     *  NPTS2\nC\n      DIMENSION IWORK(LENIW),POINTS(NPTS2),WORK(LENW)\nC\n      EXTERNAL F\nC\nC         CHECK VALIDITY OF LIMIT AND LENW.\nC\nC***FIRST EXECUTABLE STATEMENT  DQAGP\n      IER = 6\n      NEVAL = 0\n      LAST = 0\n      RESULT = 0.0D+00\n      ABSERR = 0.0D+00\n      IF(LENIW.LT.(3*NPTS2-2).OR.LENW.LT.(LENIW*2-NPTS2).OR.NPTS2.LT.2)\n     *  GO TO 10\nC\nC         PREPARE CALL FOR DQAGPE.\nC\n      LIMIT = (LENIW-NPTS2)/2\n      L1 = LIMIT+1\n      L2 = LIMIT+L1\n      L3 = LIMIT+L2\n      L4 = LIMIT+L3\nC\n      CALL DQAGPE(F,A,B,NPTS2,POINTS,EPSABS,EPSREL,LIMIT,RESULT,ABSERR,\n     *  NEVAL,IER,WORK(1),WORK(L1),WORK(L2),WORK(L3),WORK(L4),\n     *  IWORK(1),IWORK(L1),IWORK(L2),LAST)\nC\nC         CALL ERROR HANDLER IF NECESSARY.\nC\n      LVL = 0\n10    IF(IER.EQ.6) LVL = 1\n      IF(IER.GT.0) CALL XERROR('ABNORMAL RETURN FROM DQAGP',26,IER,LVL)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/quadpack/dqagpe.f",
    "content": "      SUBROUTINE DQAGPE(F,A,B,NPTS2,POINTS,EPSABS,EPSREL,LIMIT,RESULT,\n     *   ABSERR,NEVAL,IER,ALIST,BLIST,RLIST,ELIST,PTS,IORD,LEVEL,NDIN,\n     *   LAST)\nC***BEGIN PROLOGUE  DQAGPE\nC***DATE WRITTEN   800101   (YYMMDD)\nC***REVISION DATE  830518   (YYMMDD)\nC***CATEGORY NO.  H2A2A1\nC***KEYWORDS  AUTOMATIC INTEGRATOR, GENERAL-PURPOSE,\nC             SINGULARITIES AT USER SPECIFIED POINTS,\nC             EXTRAPOLATION, GLOBALLY ADAPTIVE.\nC***AUTHOR  PIESSENS,ROBERT ,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC           DE DONCKER,ELISE,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC***PURPOSE  THE ROUTINE CALCULATES AN APPROXIMATION RESULT TO A GIVEN\nC            DEFINITE INTEGRAL I = INTEGRAL OF F OVER (A,B), HOPEFULLY\nC            SATISFYING FOLLOWING CLAIM FOR ACCURACY ABS(I-RESULT).LE.\nC            MAX(EPSABS,EPSREL*ABS(I)). BREAK POINTS OF THE INTEGRATION\nC            INTERVAL, WHERE LOCAL DIFFICULTIES OF THE INTEGRAND MAY\nC            OCCUR(E.G. SINGULARITIES,DISCONTINUITIES),PROVIDED BY USER.\nC***DESCRIPTION\nC\nC        COMPUTATION OF A DEFINITE INTEGRAL\nC        STANDARD FORTRAN SUBROUTINE\nC        DOUBLE PRECISION VERSION\nC\nC        PARAMETERS\nC         ON ENTRY\nC            F      - SUBROUTINE F(X,IERR,RESULT) DEFINING THE INTEGRAND\nC                     FUNCTION F(X). THE ACTUAL NAME FOR F NEEDS TO BE\nC                     DECLARED E X T E R N A L IN THE DRIVER PROGRAM.\nC\nC            A      - DOUBLE PRECISION\nC                     LOWER LIMIT OF INTEGRATION\nC\nC            B      - DOUBLE PRECISION\nC                     UPPER LIMIT OF INTEGRATION\nC\nC            NPTS2  - INTEGER\nC                     NUMBER EQUAL TO TWO MORE THAN THE NUMBER OF\nC                     USER-SUPPLIED BREAK POINTS WITHIN THE INTEGRATION\nC                     RANGE, NPTS2.GE.2.\nC                     IF NPTS2.LT.2, THE ROUTINE WILL END WITH IER = 6.\nC\nC            POINTS - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION NPTS2, THE FIRST (NPTS2-2)\nC                     ELEMENTS OF WHICH ARE THE USER PROVIDED BREAK\nC                     POINTS. IF THESE POINTS DO NOT CONSTITUTE AN\nC                     ASCENDING SEQUENCE THERE WILL BE AN AUTOMATIC\nC                     SORTING.\nC\nC            EPSABS - DOUBLE PRECISION\nC                     ABSOLUTE ACCURACY REQUESTED\nC            EPSREL - DOUBLE PRECISION\nC                     RELATIVE ACCURACY REQUESTED\nC                     IF  EPSABS.LE.0\nC                     AND EPSREL.LT.MAX(50*REL.MACH.ACC.,0.5D-28),\nC                     THE ROUTINE WILL END WITH IER = 6.\nC\nC            LIMIT  - INTEGER\nC                     GIVES AN UPPER BOUND ON THE NUMBER OF SUBINTERVALS\nC                     IN THE PARTITION OF (A,B), LIMIT.GE.NPTS2\nC                     IF LIMIT.LT.NPTS2, THE ROUTINE WILL END WITH\nC                     IER = 6.\nC\nC         ON RETURN\nC            RESULT - DOUBLE PRECISION\nC                     APPROXIMATION TO THE INTEGRAL\nC\nC            ABSERR - DOUBLE PRECISION\nC                     ESTIMATE OF THE MODULUS OF THE ABSOLUTE ERROR,\nC                     WHICH SHOULD EQUAL OR EXCEED ABS(I-RESULT)\nC\nC            NEVAL  - INTEGER\nC                     NUMBER OF INTEGRAND EVALUATIONS\nC\nC            IER    - INTEGER\nC                     IER = 0 NORMAL AND RELIABLE TERMINATION OF THE\nC                             ROUTINE. IT IS ASSUMED THAT THE REQUESTED\nC                             ACCURACY HAS BEEN ACHIEVED.\nC                     IER.GT.0 ABNORMAL TERMINATION OF THE ROUTINE.\nC                             THE ESTIMATES FOR INTEGRAL AND ERROR ARE\nC                             LESS RELIABLE. IT IS ASSUMED THAT THE\nC                             REQUESTED ACCURACY HAS NOT BEEN ACHIEVED.\nC                      IER.LT.0 EXIT REQUESTED FROM USER-SUPPLIED\nC                             FUNCTION.\nC\nC            ERROR MESSAGES\nC                     IER = 1 MAXIMUM NUMBER OF SUBDIVISIONS ALLOWED\nC                             HAS BEEN ACHIEVED. ONE CAN ALLOW MORE\nC                             SUBDIVISIONS BY INCREASING THE VALUE OF\nC                             LIMIT (AND TAKING THE ACCORDING DIMENSION\nC                             ADJUSTMENTS INTO ACCOUNT). HOWEVER, IF\nC                             THIS YIELDS NO IMPROVEMENT IT IS ADVISED\nC                             TO ANALYZE THE INTEGRAND IN ORDER TO\nC                             DETERMINE THE INTEGRATION DIFFICULTIES. IF\nC                             THE POSITION OF A LOCAL DIFFICULTY CAN BE\nC                             DETERMINED (I.E. SINGULARITY,\nC                             DISCONTINUITY WITHIN THE INTERVAL), IT\nC                             SHOULD BE SUPPLIED TO THE ROUTINE AS AN\nC                             ELEMENT OF THE VECTOR POINTS. IF NECESSARY\nC                             AN APPROPRIATE SPECIAL-PURPOSE INTEGRATOR\nC                             MUST BE USED, WHICH IS DESIGNED FOR\nC                             HANDLING THE TYPE OF DIFFICULTY INVOLVED.\nC                         = 2 THE OCCURRENCE OF ROUNDOFF ERROR IS\nC                             DETECTED, WHICH PREVENTS THE REQUESTED\nC                             TOLERANCE FROM BEING ACHIEVED.\nC                             THE ERROR MAY BE UNDER-ESTIMATED.\nC                         = 3 EXTREMELY BAD INTEGRAND BEHAVIOUR OCCURS\nC                             AT SOME POINTS OF THE INTEGRATION\nC                             INTERVAL.\nC                         = 4 THE ALGORITHM DOES NOT CONVERGE.\nC                             ROUNDOFF ERROR IS DETECTED IN THE\nC                             EXTRAPOLATION TABLE. IT IS PRESUMED THAT\nC                             THE REQUESTED TOLERANCE CANNOT BE\nC                             ACHIEVED, AND THAT THE RETURNED RESULT IS\nC                             THE BEST WHICH CAN BE OBTAINED.\nC                         = 5 THE INTEGRAL IS PROBABLY DIVERGENT, OR\nC                             SLOWLY CONVERGENT. IT MUST BE NOTED THAT\nC                             DIVERGENCE CAN OCCUR WITH ANY OTHER VALUE\nC                             OF IER.GT.0.\nC                         = 6 THE INPUT IS INVALID BECAUSE\nC                             NPTS2.LT.2 OR\nC                             BREAK POINTS ARE SPECIFIED OUTSIDE\nC                             THE INTEGRATION RANGE OR\nC                             (EPSABS.LE.0 AND\nC                              EPSREL.LT.MAX(50*REL.MACH.ACC.,0.5D-28))\nC                             OR LIMIT.LT.NPTS2.\nC                             RESULT, ABSERR, NEVAL, LAST, RLIST(1),\nC                             AND ELIST(1) ARE SET TO ZERO. ALIST(1) AND\nC                             BLIST(1) ARE SET TO A AND B RESPECTIVELY.\nC\nC            ALIST  - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION AT LEAST LIMIT, THE FIRST\nC                      LAST  ELEMENTS OF WHICH ARE THE LEFT END POINTS\nC                     OF THE SUBINTERVALS IN THE PARTITION OF THE GIVEN\nC                     INTEGRATION RANGE (A,B)\nC\nC            BLIST  - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION AT LEAST LIMIT, THE FIRST\nC                      LAST  ELEMENTS OF WHICH ARE THE RIGHT END POINTS\nC                     OF THE SUBINTERVALS IN THE PARTITION OF THE GIVEN\nC                     INTEGRATION RANGE (A,B)\nC\nC            RLIST  - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION AT LEAST LIMIT, THE FIRST\nC                      LAST  ELEMENTS OF WHICH ARE THE INTEGRAL\nC                     APPROXIMATIONS ON THE SUBINTERVALS\nC\nC            ELIST  - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION AT LEAST LIMIT, THE FIRST\nC                      LAST  ELEMENTS OF WHICH ARE THE MODULI OF THE\nC                     ABSOLUTE ERROR ESTIMATES ON THE SUBINTERVALS\nC\nC            PTS    - DOUBLE PRECISION\nC                     VECTOR OF DIMENSION AT LEAST NPTS2, CONTAINING THE\nC                     INTEGRATION LIMITS AND THE BREAK POINTS OF THE\nC                     INTERVAL IN ASCENDING SEQUENCE.\nC\nC            LEVEL  - INTEGER\nC                     VECTOR OF DIMENSION AT LEAST LIMIT, CONTAINING THE\nC                     SUBDIVISION LEVELS OF THE SUBINTERVAL, I.E. IF\nC                     (AA,BB) IS A SUBINTERVAL OF (P1,P2) WHERE P1 AS\nC                     WELL AS P2 IS A USER-PROVIDED BREAK POINT OR\nC                     INTEGRATION LIMIT, THEN (AA,BB) HAS LEVEL L IF\nC                     ABS(BB-AA) = ABS(P2-P1)*2**(-L).\nC\nC            NDIN   - INTEGER\nC                     VECTOR OF DIMENSION AT LEAST NPTS2, AFTER FIRST\nC                     INTEGRATION OVER THE INTERVALS (PTS(I)),PTS(I+1),\nC                     I = 0,1, ..., NPTS2-2, THE ERROR ESTIMATES OVER\nC                     SOME OF THE INTERVALS MAY HAVE BEEN INCREASED\nC                     ARTIFICIALLY, IN ORDER TO PUT THEIR SUBDIVISION\nC                     FORWARD. IF THIS HAPPENS FOR THE SUBINTERVAL\nC                     NUMBERED K, NDIN(K) IS PUT TO 1, OTHERWISE\nC                     NDIN(K) = 0.\nC\nC            IORD   - INTEGER\nC                     VECTOR OF DIMENSION AT LEAST LIMIT, THE FIRST K\nC                     ELEMENTS OF WHICH ARE POINTERS TO THE\nC                     ERROR ESTIMATES OVER THE SUBINTERVALS,\nC                     SUCH THAT ELIST(IORD(1)), ..., ELIST(IORD(K))\nC                     FORM A DECREASING SEQUENCE, WITH K = LAST\nC                     IF LAST.LE.(LIMIT/2+2), AND K = LIMIT+1-LAST\nC                     OTHERWISE\nC\nC            LAST   - INTEGER\nC                     NUMBER OF SUBINTERVALS ACTUALLY PRODUCED IN THE\nC                     SUBDIVISIONS PROCESS\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH,DQELG,DQK21,DQPSRT\nC***END PROLOGUE  DQAGPE\n      DOUBLE PRECISION A,ABSEPS,ABSERR,ALIST,AREA,AREA1,AREA12,AREA2,A1,\n     *  A2,B,BLIST,B1,B2,CORREC,DABS,DEFABS,DEFAB1,DEFAB2,DMAX1,DMIN1,\n     *  DRES,D1MACH,ELIST,EPMACH,EPSABS,EPSREL,ERLARG,ERLAST,ERRBND,\n     *  ERRMAX,ERROR1,ERRO12,ERROR2,ERRSUM,ERTEST,OFLOW,POINTS,PTS,\n     *  RESA,RESABS,RESEPS,RESULT,RES3LA,RLIST,RLIST2,SIGN,TEMP,UFLOW\n      INTEGER I,ID,IER,IERRO,IND1,IND2,IORD,IP1,IROFF1,IROFF2,IROFF3,J,\n     *  JLOW,JUPBND,K,KSGN,KTMIN,LAST,LEVCUR,LEVEL,LEVMAX,LIMIT,MAXERR,\n     *  NDIN,NEVAL,NINT,NINTP1,NPTS,NPTS2,NRES,NRMAX,NUMRL2\n      LOGICAL EXTRAP,NOEXT\nC\nC\n      DIMENSION ALIST(LIMIT),BLIST(LIMIT),ELIST(LIMIT),IORD(LIMIT),\n     *  LEVEL(LIMIT),NDIN(NPTS2),POINTS(NPTS2),PTS(NPTS2),RES3LA(3),\n     *  RLIST(LIMIT),RLIST2(52)\nC\n      EXTERNAL F\nC\nC            THE DIMENSION OF RLIST2 IS DETERMINED BY THE VALUE OF\nC            LIMEXP IN SUBROUTINE EPSALG (RLIST2 SHOULD BE OF DIMENSION\nC            (LIMEXP+2) AT LEAST).\nC\nC\nC            LIST OF MAJOR VARIABLES\nC            -----------------------\nC\nC           ALIST     - LIST OF LEFT END POINTS OF ALL SUBINTERVALS\nC                       CONSIDERED UP TO NOW\nC           BLIST     - LIST OF RIGHT END POINTS OF ALL SUBINTERVALS\nC                       CONSIDERED UP TO NOW\nC           RLIST(I)  - APPROXIMATION TO THE INTEGRAL OVER\nC                       (ALIST(I),BLIST(I))\nC           RLIST2    - ARRAY OF DIMENSION AT LEAST LIMEXP+2\nC                       CONTAINING THE PART OF THE EPSILON TABLE WHICH\nC                       IS STILL NEEDED FOR FURTHER COMPUTATIONS\nC           ELIST(I)  - ERROR ESTIMATE APPLYING TO RLIST(I)\nC           MAXERR    - POINTER TO THE INTERVAL WITH LARGEST ERROR\nC                       ESTIMATE\nC           ERRMAX    - ELIST(MAXERR)\nC           ERLAST    - ERROR ON THE INTERVAL CURRENTLY SUBDIVIDED\nC                       (BEFORE THAT SUBDIVISION HAS TAKEN PLACE)\nC           AREA      - SUM OF THE INTEGRALS OVER THE SUBINTERVALS\nC           ERRSUM    - SUM OF THE ERRORS OVER THE SUBINTERVALS\nC           ERRBND    - REQUESTED ACCURACY MAX(EPSABS,EPSREL*\nC                       ABS(RESULT))\nC           *****1    - VARIABLE FOR THE LEFT SUBINTERVAL\nC           *****2    - VARIABLE FOR THE RIGHT SUBINTERVAL\nC           LAST      - INDEX FOR SUBDIVISION\nC           NRES      - NUMBER OF CALLS TO THE EXTRAPOLATION ROUTINE\nC           NUMRL2    - NUMBER OF ELEMENTS IN RLIST2. IF AN APPROPRIATE\nC                       APPROXIMATION TO THE COMPOUNDED INTEGRAL HAS\nC                       BEEN OBTAINED, IT IS PUT IN RLIST2(NUMRL2) AFTER\nC                       NUMRL2 HAS BEEN INCREASED BY ONE.\nC           ERLARG    - SUM OF THE ERRORS OVER THE INTERVALS LARGER\nC                       THAN THE SMALLEST INTERVAL CONSIDERED UP TO NOW\nC           EXTRAP    - LOGICAL VARIABLE DENOTING THAT THE ROUTINE\nC                       IS ATTEMPTING TO PERFORM EXTRAPOLATION. I.E.\nC                       BEFORE SUBDIVIDING THE SMALLEST INTERVAL WE\nC                       TRY TO DECREASE THE VALUE OF ERLARG.\nC           NOEXT     - LOGICAL VARIABLE DENOTING THAT EXTRAPOLATION IS\nC                       NO LONGER ALLOWED (TRUE-VALUE)\nC\nC            MACHINE DEPENDENT CONSTANTS\nC            ---------------------------\nC\nC           EPMACH IS THE LARGEST RELATIVE SPACING.\nC           UFLOW IS THE SMALLEST POSITIVE MAGNITUDE.\nC           OFLOW IS THE LARGEST POSITIVE MAGNITUDE.\nC\nC***FIRST EXECUTABLE STATEMENT  DQAGPE\n      EPMACH = D1MACH(4)\nC\nC            TEST ON VALIDITY OF PARAMETERS\nC            -----------------------------\nC\n      IER = 0\n      NEVAL = 0\n      LAST = 0\n      RESULT = 0.0D+00\n      ABSERR = 0.0D+00\n      ALIST(1) = A\n      BLIST(1) = B\n      RLIST(1) = 0.0D+00\n      ELIST(1) = 0.0D+00\n      IORD(1) = 0\n      LEVEL(1) = 0\n      NPTS = NPTS2-2\n      IF(NPTS2.LT.2.OR.LIMIT.LE.NPTS.OR.(EPSABS.LE.0.0D+00.AND.\n     *  EPSREL.LT.DMAX1(0.5D+02*EPMACH,0.5D-28))) IER = 6\n      IF(IER.EQ.6) GO TO 999\nC\nC            IF ANY BREAK POINTS ARE PROVIDED, SORT THEM INTO AN\nC            ASCENDING SEQUENCE.\nC\n      SIGN = 1.0D+00\n      IF(A.GT.B) SIGN = -1.0D+00\n      PTS(1) = DMIN1(A,B)\n      IF(NPTS.EQ.0) GO TO 15\n      DO 10 I = 1,NPTS\n        PTS(I+1) = POINTS(I)\n   10 CONTINUE\n   15 PTS(NPTS+2) = DMAX1(A,B)\n      NINT = NPTS+1\n      A1 = PTS(1)\n      IF(NPTS.EQ.0) GO TO 40\n      NINTP1 = NINT+1\n      DO 20 I = 1,NINT\n        IP1 = I+1\n        DO 20 J = IP1,NINTP1\n          IF(PTS(I).LE.PTS(J)) GO TO 20\n          TEMP = PTS(I)\n          PTS(I) = PTS(J)\n          PTS(J) = TEMP\n   20 CONTINUE\n      IF(PTS(1).NE.DMIN1(A,B).OR.PTS(NINTP1).NE.DMAX1(A,B)) IER = 6\n      IF(IER.EQ.6) GO TO 999\nC\nC            COMPUTE FIRST INTEGRAL AND ERROR APPROXIMATIONS.\nC            ------------------------------------------------\nC\n   40 RESABS = 0.0D+00\n      DO 50 I = 1,NINT\n        B1 = PTS(I+1)\n        CALL DQK21(F,A1,B1,AREA1,ERROR1,DEFABS,RESA,IER)\n        IF (IER .LT. 0) RETURN\n        ABSERR = ABSERR+ERROR1\n        RESULT = RESULT+AREA1\n        NDIN(I) = 0\n        IF(ERROR1.EQ.RESA.AND.ERROR1.NE.0.0D+00) NDIN(I) = 1\n        RESABS = RESABS+DEFABS\n        LEVEL(I) = 0\n        ELIST(I) = ERROR1\n        ALIST(I) = A1\n        BLIST(I) = B1\n        RLIST(I) = AREA1\n        IORD(I) = I\n        A1 = B1\n   50 CONTINUE\n      ERRSUM = 0.0D+00\n      DO 55 I = 1,NINT\n        IF(NDIN(I).EQ.1) ELIST(I) = ABSERR\n        ERRSUM = ERRSUM+ELIST(I)\n   55 CONTINUE\nC\nC           TEST ON ACCURACY.\nC\n      LAST = NINT\n      NEVAL = 21*NINT\n      DRES = DABS(RESULT)\n      ERRBND = DMAX1(EPSABS,EPSREL*DRES)\n      IF(ABSERR.LE.0.1D+03*EPMACH*RESABS.AND.ABSERR.GT.ERRBND) IER = 2\n      IF(NINT.EQ.1) GO TO 80\n      DO 70 I = 1,NPTS\n        JLOW = I+1\n        IND1 = IORD(I)\n        DO 60 J = JLOW,NINT\n          IND2 = IORD(J)\n          IF(ELIST(IND1).GT.ELIST(IND2)) GO TO 60\n          IND1 = IND2\n          K = J\n   60   CONTINUE\n        IF(IND1.EQ.IORD(I)) GO TO 70\n        IORD(K) = IORD(I)\n        IORD(I) = IND1\n   70 CONTINUE\n      IF(LIMIT.LT.NPTS2) IER = 1\n   80 IF(IER.NE.0.OR.ABSERR.LE.ERRBND) GO TO 210\nC\nC           INITIALIZATION\nC           --------------\nC\n      RLIST2(1) = RESULT\n      MAXERR = IORD(1)\n      ERRMAX = ELIST(MAXERR)\n      AREA = RESULT\n      NRMAX = 1\n      NRES = 0\n      NUMRL2 = 1\n      KTMIN = 0\n      EXTRAP = .FALSE.\n      NOEXT = .FALSE.\n      ERLARG = ERRSUM\n      ERTEST = ERRBND\n      LEVMAX = 1\n      IROFF1 = 0\n      IROFF2 = 0\n      IROFF3 = 0\n      IERRO = 0\n      UFLOW = D1MACH(1)\n      OFLOW = D1MACH(2)\n      ABSERR = OFLOW\n      KSGN = -1\n      IF(DRES.GE.(0.1D+01-0.5D+02*EPMACH)*RESABS) KSGN = 1\nC\nC           MAIN DO-LOOP\nC           ------------\nC\n      DO 160 LAST = NPTS2,LIMIT\nC\nC           BISECT THE SUBINTERVAL WITH THE NRMAX-TH LARGEST ERROR\nC           ESTIMATE.\nC\n        LEVCUR = LEVEL(MAXERR)+1\n        A1 = ALIST(MAXERR)\n        B1 = 0.5D+00*(ALIST(MAXERR)+BLIST(MAXERR))\n        A2 = B1\n        B2 = BLIST(MAXERR)\n        ERLAST = ERRMAX\n        CALL DQK21(F,A1,B1,AREA1,ERROR1,RESA,DEFAB1,IER)\n        IF (IER .LT. 0) RETURN\n        CALL DQK21(F,A2,B2,AREA2,ERROR2,RESA,DEFAB2,IER)\n        IF (IER .LT. 0) RETURN\nC\nC           IMPROVE PREVIOUS APPROXIMATIONS TO INTEGRAL\nC           AND ERROR AND TEST FOR ACCURACY.\nC\n        NEVAL = NEVAL+42\n        AREA12 = AREA1+AREA2\n        ERRO12 = ERROR1+ERROR2\n        ERRSUM = ERRSUM+ERRO12-ERRMAX\n        AREA = AREA+AREA12-RLIST(MAXERR)\n        IF(DEFAB1.EQ.ERROR1.OR.DEFAB2.EQ.ERROR2) GO TO 95\n        IF(DABS(RLIST(MAXERR)-AREA12).GT.0.1D-04*DABS(AREA12)\n     *  .OR.ERRO12.LT.0.99D+00*ERRMAX) GO TO 90\n        IF(EXTRAP) IROFF2 = IROFF2+1\n        IF(.NOT.EXTRAP) IROFF1 = IROFF1+1\n   90   IF(LAST.GT.10.AND.ERRO12.GT.ERRMAX) IROFF3 = IROFF3+1\n   95   LEVEL(MAXERR) = LEVCUR\n        LEVEL(LAST) = LEVCUR\n        RLIST(MAXERR) = AREA1\n        RLIST(LAST) = AREA2\n        ERRBND = DMAX1(EPSABS,EPSREL*DABS(AREA))\nC\nC           TEST FOR ROUNDOFF ERROR AND EVENTUALLY SET ERROR FLAG.\nC\n        IF(IROFF1+IROFF2.GE.10.OR.IROFF3.GE.20) IER = 2\n        IF(IROFF2.GE.5) IERRO = 3\nC\nC           SET ERROR FLAG IN THE CASE THAT THE NUMBER OF\nC           SUBINTERVALS EQUALS LIMIT.\nC\n        IF(LAST.EQ.LIMIT) IER = 1\nC\nC           SET ERROR FLAG IN THE CASE OF BAD INTEGRAND BEHAVIOUR\nC           AT A POINT OF THE INTEGRATION RANGE\nC\n        IF(DMAX1(DABS(A1),DABS(B2)).LE.(0.1D+01+0.1D+03*EPMACH)*\n     *  (DABS(A2)+0.1D+04*UFLOW)) IER = 4\nC\nC           APPEND THE NEWLY-CREATED INTERVALS TO THE LIST.\nC\n        IF(ERROR2.GT.ERROR1) GO TO 100\n        ALIST(LAST) = A2\n        BLIST(MAXERR) = B1\n        BLIST(LAST) = B2\n        ELIST(MAXERR) = ERROR1\n        ELIST(LAST) = ERROR2\n        GO TO 110\n  100   ALIST(MAXERR) = A2\n        ALIST(LAST) = A1\n        BLIST(LAST) = B1\n        RLIST(MAXERR) = AREA2\n        RLIST(LAST) = AREA1\n        ELIST(MAXERR) = ERROR2\n        ELIST(LAST) = ERROR1\nC\nC           CALL SUBROUTINE DQPSRT TO MAINTAIN THE DESCENDING ORDERING\nC           IN THE LIST OF ERROR ESTIMATES AND SELECT THE SUBINTERVAL\nC           WITH NRMAX-TH LARGEST ERROR ESTIMATE (TO BE BISECTED NEXT).\nC\n  110   CALL DQPSRT(LIMIT,LAST,MAXERR,ERRMAX,ELIST,IORD,NRMAX)\nC ***JUMP OUT OF DO-LOOP\n        IF(ERRSUM.LE.ERRBND) GO TO 190\nC ***JUMP OUT OF DO-LOOP\n        IF(IER.NE.0) GO TO 170\n        IF(NOEXT) GO TO 160\n        ERLARG = ERLARG-ERLAST\n        IF(LEVCUR+1.LE.LEVMAX) ERLARG = ERLARG+ERRO12\n        IF(EXTRAP) GO TO 120\nC\nC           TEST WHETHER THE INTERVAL TO BE BISECTED NEXT IS THE\nC           SMALLEST INTERVAL.\nC\n        IF(LEVEL(MAXERR)+1.LE.LEVMAX) GO TO 160\n        EXTRAP = .TRUE.\n        NRMAX = 2\n  120   IF(IERRO.EQ.3.OR.ERLARG.LE.ERTEST) GO TO 140\nC\nC           THE SMALLEST INTERVAL HAS THE LARGEST ERROR.\nC           BEFORE BISECTING DECREASE THE SUM OF THE ERRORS OVER\nC           THE LARGER INTERVALS (ERLARG) AND PERFORM EXTRAPOLATION.\nC\n        ID = NRMAX\n        JUPBND = LAST\n        IF(LAST.GT.(2+LIMIT/2)) JUPBND = LIMIT+3-LAST\n        DO 130 K = ID,JUPBND\n          MAXERR = IORD(NRMAX)\n          ERRMAX = ELIST(MAXERR)\nC ***JUMP OUT OF DO-LOOP\n          IF(LEVEL(MAXERR)+1.LE.LEVMAX) GO TO 160\n          NRMAX = NRMAX+1\n  130   CONTINUE\nC\nC           PERFORM EXTRAPOLATION.\nC\n  140   NUMRL2 = NUMRL2+1\n        RLIST2(NUMRL2) = AREA\n        IF(NUMRL2.LE.2) GO TO 155\n        CALL DQELG(NUMRL2,RLIST2,RESEPS,ABSEPS,RES3LA,NRES)\n        KTMIN = KTMIN+1\n        IF(KTMIN.GT.5.AND.ABSERR.LT.0.1D-02*ERRSUM) IER = 5\n        IF(ABSEPS.GE.ABSERR) GO TO 150\n        KTMIN = 0\n        ABSERR = ABSEPS\n        RESULT = RESEPS\n        CORREC = ERLARG\n        ERTEST = DMAX1(EPSABS,EPSREL*DABS(RESEPS))\nC ***JUMP OUT OF DO-LOOP\n        IF(ABSERR.LT.ERTEST) GO TO 170\nC\nC           PREPARE BISECTION OF THE SMALLEST INTERVAL.\nC\n  150   IF(NUMRL2.EQ.1) NOEXT = .TRUE.\n        IF(IER.GE.5) GO TO 170\n  155   MAXERR = IORD(1)\n        ERRMAX = ELIST(MAXERR)\n        NRMAX = 1\n        EXTRAP = .FALSE.\n        LEVMAX = LEVMAX+1\n        ERLARG = ERRSUM\n  160 CONTINUE\nC\nC           SET THE FINAL RESULT.\nC           ---------------------\nC\nC\n  170 IF(ABSERR.EQ.OFLOW) GO TO 190\n      IF((IER+IERRO).EQ.0) GO TO 180\n      IF(IERRO.EQ.3) ABSERR = ABSERR+CORREC\n      IF(IER.EQ.0) IER = 3\n      IF(RESULT.NE.0.0D+00.AND.AREA.NE.0.0D+00)GO TO 175\n      IF(ABSERR.GT.ERRSUM)GO TO 190\n      IF(AREA.EQ.0.0D+00) GO TO 210\n      GO TO 180\n  175 IF(ABSERR/DABS(RESULT).GT.ERRSUM/DABS(AREA))GO TO 190\nC\nC           TEST ON DIVERGENCE.\nC\n  180 IF(KSGN.EQ.(-1).AND.DMAX1(DABS(RESULT),DABS(AREA)).LE.\n     *  RESABS*0.1D-01) GO TO 210\n      IF(0.1D-01.GT.(RESULT/AREA).OR.(RESULT/AREA).GT.0.1D+03.OR.\n     *  ERRSUM.GT.DABS(AREA)) IER = 6\n      GO TO 210\nC\nC           COMPUTE GLOBAL INTEGRAL SUM.\nC\n  190 RESULT = 0.0D+00\n      DO 200 K = 1,LAST\n        RESULT = RESULT+RLIST(K)\n  200 CONTINUE\n      ABSERR = ERRSUM\n  210 IF(IER.GT.2) IER = IER-1\n      RESULT = RESULT*SIGN\n  999 RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/quadpack/dqelg.f",
    "content": "      SUBROUTINE DQELG(N,EPSTAB,RESULT,ABSERR,RES3LA,NRES)\nC***BEGIN PROLOGUE  DQELG\nC***REFER TO  DQAGIE,DQAGOE,DQAGPE,DQAGSE\nC***ROUTINES CALLED  D1MACH\nC***REVISION DATE  830518   (YYMMDD)\nC***KEYWORDS  EPSILON ALGORITHM, CONVERGENCE ACCELERATION,\nC             EXTRAPOLATION\nC***AUTHOR  PIESSENS,ROBERT,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC           DE DONCKER,ELISE,APPL. MATH & PROGR. DIV. - K.U.LEUVEN\nC***PURPOSE  THE ROUTINE DETERMINES THE LIMIT OF A GIVEN SEQUENCE OF\nC            APPROXIMATIONS, BY MEANS OF THE EPSILON ALGORITHM OF\nC            P.WYNN. AN ESTIMATE OF THE ABSOLUTE ERROR IS ALSO GIVEN.\nC            THE CONDENSED EPSILON TABLE IS COMPUTED. ONLY THOSE\nC            ELEMENTS NEEDED FOR THE COMPUTATION OF THE NEXT DIAGONAL\nC            ARE PRESERVED.\nC***DESCRIPTION\nC\nC           EPSILON ALGORITHM\nC           STANDARD FORTRAN SUBROUTINE\nC           DOUBLE PRECISION VERSION\nC\nC           PARAMETERS\nC              N      - INTEGER\nC                       EPSTAB(N) CONTAINS THE NEW ELEMENT IN THE\nC                       FIRST COLUMN OF THE EPSILON TABLE.\nC\nC              EPSTAB - DOUBLE PRECISION\nC                       VECTOR OF DIMENSION 52 CONTAINING THE ELEMENTS\nC                       OF THE TWO LOWER DIAGONALS OF THE TRIANGULAR\nC                       EPSILON TABLE. THE ELEMENTS ARE NUMBERED\nC                       STARTING AT THE RIGHT-HAND CORNER OF THE\nC                       TRIANGLE.\nC\nC              RESULT - DOUBLE PRECISION\nC                       RESULTING APPROXIMATION TO THE INTEGRAL\nC\nC              ABSERR - DOUBLE PRECISION\nC                       ESTIMATE OF THE ABSOLUTE ERROR COMPUTED FROM\nC                       RESULT AND THE 3 PREVIOUS RESULTS\nC\nC              RES3LA - DOUBLE PRECISION\nC                       VECTOR OF DIMENSION 3 CONTAINING THE LAST 3\nC                       RESULTS\nC\nC              NRES   - INTEGER\nC                       NUMBER OF CALLS TO THE ROUTINE\nC                       (SHOULD BE ZERO AT FIRST CALL)\nC\nC***END PROLOGUE  DQELG\nC\n      DOUBLE PRECISION ABSERR,DABS,DELTA1,DELTA2,DELTA3,DMAX1,D1MACH,\n     *  EPMACH,EPSINF,EPSTAB,ERROR,ERR1,ERR2,ERR3,E0,E1,E1ABS,E2,E3,\n     *  OFLOW,RES,RESULT,RES3LA,SS,TOL1,TOL2,TOL3\n      INTEGER I,IB,IB2,IE,INDX,K1,K2,K3,LIMEXP,N,NEWELM,NRES,NUM\n      DIMENSION EPSTAB(52),RES3LA(3)\nC\nC           LIST OF MAJOR VARIABLES\nC           -----------------------\nC\nC           E0     - THE 4 ELEMENTS ON WHICH THE COMPUTATION OF A NEW\nC           E1       ELEMENT IN THE EPSILON TABLE IS BASED\nC           E2\nC           E3                 E0\nC                        E3    E1    NEW\nC                              E2\nC           NEWELM - NUMBER OF ELEMENTS TO BE COMPUTED IN THE NEW\nC                    DIAGONAL\nC           ERROR  - ERROR = ABS(E1-E0)+ABS(E2-E1)+ABS(NEW-E2)\nC           RESULT - THE ELEMENT IN THE NEW DIAGONAL WITH LEAST VALUE\nC                    OF ERROR\nC\nC           MACHINE DEPENDENT CONSTANTS\nC           ---------------------------\nC\nC           EPMACH IS THE LARGEST RELATIVE SPACING.\nC           OFLOW IS THE LARGEST POSITIVE MAGNITUDE.\nC           LIMEXP IS THE MAXIMUM NUMBER OF ELEMENTS THE EPSILON\nC           TABLE CAN CONTAIN. IF THIS NUMBER IS REACHED, THE UPPER\nC           DIAGONAL OF THE EPSILON TABLE IS DELETED.\nC\nC***FIRST EXECUTABLE STATEMENT  DQELG\n      EPMACH = D1MACH(4)\n      OFLOW = D1MACH(2)\n      NRES = NRES+1\n      ABSERR = OFLOW\n      RESULT = EPSTAB(N)\n      IF(N.LT.3) GO TO 100\n      LIMEXP = 50\n      EPSTAB(N+2) = EPSTAB(N)\n      NEWELM = (N-1)/2\n      EPSTAB(N) = OFLOW\n      NUM = N\n      K1 = N\n      DO 40 I = 1,NEWELM\n        K2 = K1-1\n        K3 = K1-2\n        RES = EPSTAB(K1+2)\n        E0 = EPSTAB(K3)\n        E1 = EPSTAB(K2)\n        E2 = RES\n        E1ABS = DABS(E1)\n        DELTA2 = E2-E1\n        ERR2 = DABS(DELTA2)\n        TOL2 = DMAX1(DABS(E2),E1ABS)*EPMACH\n        DELTA3 = E1-E0\n        ERR3 = DABS(DELTA3)\n        TOL3 = DMAX1(E1ABS,DABS(E0))*EPMACH\n        IF(ERR2.GT.TOL2.OR.ERR3.GT.TOL3) GO TO 10\nC\nC           IF E0, E1 AND E2 ARE EQUAL TO WITHIN MACHINE\nC           ACCURACY, CONVERGENCE IS ASSUMED.\nC           RESULT = E2\nC           ABSERR = ABS(E1-E0)+ABS(E2-E1)\nC\n        RESULT = RES\n        ABSERR = ERR2+ERR3\nC ***JUMP OUT OF DO-LOOP\n        GO TO 100\n   10   E3 = EPSTAB(K1)\n        EPSTAB(K1) = E1\n        DELTA1 = E1-E3\n        ERR1 = DABS(DELTA1)\n        TOL1 = DMAX1(E1ABS,DABS(E3))*EPMACH\nC\nC           IF TWO ELEMENTS ARE VERY CLOSE TO EACH OTHER, OMIT\nC           A PART OF THE TABLE BY ADJUSTING THE VALUE OF N\nC\n        IF(ERR1.LE.TOL1.OR.ERR2.LE.TOL2.OR.ERR3.LE.TOL3) GO TO 20\n        SS = 0.1D+01/DELTA1+0.1D+01/DELTA2-0.1D+01/DELTA3\n        EPSINF = DABS(SS*E1)\nC\nC           TEST TO DETECT IRREGULAR BEHAVIOUR IN THE TABLE, AND\nC           EVENTUALLY OMIT A PART OF THE TABLE ADJUSTING THE VALUE\nC           OF N.\nC\n        IF(EPSINF.GT.0.1D-03) GO TO 30\n   20   N = I+I-1\nC ***JUMP OUT OF DO-LOOP\n        GO TO 50\nC\nC           COMPUTE A NEW ELEMENT AND EVENTUALLY ADJUST\nC           THE VALUE OF RESULT.\nC\n   30   RES = E1+0.1D+01/SS\n        EPSTAB(K1) = RES\n        K1 = K1-2\n        ERROR = ERR2+DABS(RES-E2)+ERR3\n        IF(ERROR.GT.ABSERR) GO TO 40\n        ABSERR = ERROR\n        RESULT = RES\n   40 CONTINUE\nC\nC           SHIFT THE TABLE.\nC\n   50 IF(N.EQ.LIMEXP) N = 2*(LIMEXP/2)-1\n      IB = 1\n      IF((NUM/2)*2.EQ.NUM) IB = 2\n      IE = NEWELM+1\n      DO 60 I=1,IE\n        IB2 = IB+2\n        EPSTAB(IB) = EPSTAB(IB2)\n        IB = IB2\n   60 CONTINUE\n      IF(NUM.EQ.N) GO TO 80\n      INDX = NUM-N+1\n      DO 70 I = 1,N\n        EPSTAB(I)= EPSTAB(INDX)\n        INDX = INDX+1\n   70 CONTINUE\n   80 IF(NRES.GE.4) GO TO 90\n      RES3LA(NRES) = RESULT\n      ABSERR = OFLOW\n      GO TO 100\nC\nC           COMPUTE ERROR ESTIMATE\nC\n   90 ABSERR = DABS(RESULT-RES3LA(3))+DABS(RESULT-RES3LA(2))\n     *  +DABS(RESULT-RES3LA(1))\n      RES3LA(1) = RES3LA(2)\n      RES3LA(2) = RES3LA(3)\n      RES3LA(3) = RESULT\n  100 ABSERR = DMAX1(ABSERR,0.5D+01*EPMACH*DABS(RESULT))\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/quadpack/dqk15i.f",
    "content": "      SUBROUTINE DQK15I(F,BOUN,INF,A,B,RESULT,ABSERR,RESABS,RESASC,\n     1   IERR)\nC***BEGIN PROLOGUE  DQK15I\nC***DATE WRITTEN   800101   (YYMMDD)\nC***REVISION DATE  830518   (YYMMDD)\nC***CATEGORY NO.  H2A3A2,H2A4A2\nC***KEYWORDS  15-POINT TRANSFORMED GAUSS-KRONROD RULES\nC***AUTHOR  PIESSENS,ROBERT,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC           DE DONCKER,ELISE,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC***PURPOSE  THE ORIGINAL (INFINITE INTEGRATION RANGE IS MAPPED\nC            ONTO THE INTERVAL (0,1) AND (A,B) IS A PART OF (0,1).\nC            IT IS THE PURPOSE TO COMPUTE\nC            I = INTEGRAL OF TRANSFORMED INTEGRAND OVER (A,B),\nC            J = INTEGRAL OF ABS(TRANSFORMED INTEGRAND) OVER (A,B).\nC***DESCRIPTION\nC\nC           INTEGRATION RULE\nC           STANDARD FORTRAN SUBROUTINE\nC           DOUBLE PRECISION VERSION\nC\nC           PARAMETERS\nC            ON ENTRY\nC              F      - SUBROUTINE F(X,IERR,RESULT) DEFINING THE INTEGRAND\nC                       FUNCTION F(X). THE ACTUAL NAME FOR F NEEDS TO BE\nC                       DECLARED E X T E R N A L IN THE CALLING PROGRAM.\nC\nC              BOUN   - DOUBLE PRECISION\nC                       FINITE BOUND OF ORIGINAL INTEGRATION\nC                       RANGE (SET TO ZERO IF INF = +2)\nC\nC              INF    - INTEGER\nC                       IF INF = -1, THE ORIGINAL INTERVAL IS\nC                                   (-INFINITY,BOUND),\nC                       IF INF = +1, THE ORIGINAL INTERVAL IS\nC                                   (BOUND,+INFINITY),\nC                       IF INF = +2, THE ORIGINAL INTERVAL IS\nC                                   (-INFINITY,+INFINITY) AND\nC                       THE INTEGRAL IS COMPUTED AS THE SUM OF TWO\nC                       INTEGRALS, ONE OVER (-INFINITY,0) AND ONE OVER\nC                       (0,+INFINITY).\nC\nC              A      - DOUBLE PRECISION\nC                       LOWER LIMIT FOR INTEGRATION OVER SUBRANGE\nC                       OF (0,1)\nC\nC              B      - DOUBLE PRECISION\nC                       UPPER LIMIT FOR INTEGRATION OVER SUBRANGE\nC                       OF (0,1)\nC\nC            ON RETURN\nC              RESULT - DOUBLE PRECISION\nC                       APPROXIMATION TO THE INTEGRAL I\nC                       RESULT IS COMPUTED BY APPLYING THE 15-POINT\nC                       KRONROD RULE(RESK) OBTAINED BY OPTIMAL ADDITION\nC                       OF ABSCISSAE TO THE 7-POINT GAUSS RULE(RESG).\nC\nC              ABSERR - DOUBLE PRECISION\nC                       ESTIMATE OF THE MODULUS OF THE ABSOLUTE ERROR,\nC                       WHICH SHOULD EQUAL OR EXCEED ABS(I-RESULT)\nC\nC              RESABS - DOUBLE PRECISION\nC                       APPROXIMATION TO THE INTEGRAL J\nC\nC              RESASC - DOUBLE PRECISION\nC                       APPROXIMATION TO THE INTEGRAL OF\nC                       ABS((TRANSFORMED INTEGRAND)-I/(B-A)) OVER (A,B)\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH\nC***END PROLOGUE  DQK15I\nC\n      DOUBLE PRECISION A,ABSC,ABSC1,ABSC2,ABSERR,B,BOUN,CENTR,DABS,DINF,\n     *  DMAX1,DMIN1,D1MACH,EPMACH,FC,FSUM,FVAL1,FVAL2,FV1,FV2,HLGTH,\n     *  RESABS,RESASC,RESG,RESK,RESKH,RESULT,TABSC1,TABSC2,UFLOW,WG,WGK,\n     *  XGK,FVALT\n      INTEGER INF,J\n      EXTERNAL F\nC\n      DIMENSION FV1(7),FV2(7),XGK(8),WGK(8),WG(8)\nC\nC           THE ABSCISSAE AND WEIGHTS ARE SUPPLIED FOR THE INTERVAL\nC           (-1,1).  BECAUSE OF SYMMETRY ONLY THE POSITIVE ABSCISSAE AND\nC           THEIR CORRESPONDING WEIGHTS ARE GIVEN.\nC\nC           XGK    - ABSCISSAE OF THE 15-POINT KRONROD RULE\nC                    XGK(2), XGK(4), ... ABSCISSAE OF THE 7-POINT\nC                    GAUSS RULE\nC                    XGK(1), XGK(3), ...  ABSCISSAE WHICH ARE OPTIMALLY\nC                    ADDED TO THE 7-POINT GAUSS RULE\nC\nC           WGK    - WEIGHTS OF THE 15-POINT KRONROD RULE\nC\nC           WG     - WEIGHTS OF THE 7-POINT GAUSS RULE, CORRESPONDING\nC                    TO THE ABSCISSAE XGK(2), XGK(4), ...\nC                    WG(1), WG(3), ... ARE SET TO ZERO.\nC\n      DATA WG(1) / 0.0D0 /\n      DATA WG(2) / 0.1294849661 6886969327 0611432679 082D0 /\n      DATA WG(3) / 0.0D0 /\n      DATA WG(4) / 0.2797053914 8927666790 1467771423 780D0 /\n      DATA WG(5) / 0.0D0 /\n      DATA WG(6) / 0.3818300505 0511894495 0369775488 975D0 /\n      DATA WG(7) / 0.0D0 /\n      DATA WG(8) / 0.4179591836 7346938775 5102040816 327D0 /\nC\n      DATA XGK(1) / 0.9914553711 2081263920 6854697526 329D0 /\n      DATA XGK(2) / 0.9491079123 4275852452 6189684047 851D0 /\n      DATA XGK(3) / 0.8648644233 5976907278 9712788640 926D0 /\n      DATA XGK(4) / 0.7415311855 9939443986 3864773280 788D0 /\n      DATA XGK(5) / 0.5860872354 6769113029 4144838258 730D0 /\n      DATA XGK(6) / 0.4058451513 7739716690 6606412076 961D0 /\n      DATA XGK(7) / 0.2077849550 0789846760 0689403773 245D0 /\n      DATA XGK(8) / 0.0000000000 0000000000 0000000000 000D0 /\nC\n      DATA WGK(1) / 0.0229353220 1052922496 3732008058 970D0 /\n      DATA WGK(2) / 0.0630920926 2997855329 0700663189 204D0 /\n      DATA WGK(3) / 0.1047900103 2225018383 9876322541 518D0 /\n      DATA WGK(4) / 0.1406532597 1552591874 5189590510 238D0 /\n      DATA WGK(5) / 0.1690047266 3926790282 6583426598 550D0 /\n      DATA WGK(6) / 0.1903505780 6478540991 3256402421 014D0 /\n      DATA WGK(7) / 0.2044329400 7529889241 4161999234 649D0 /\n      DATA WGK(8) / 0.2094821410 8472782801 2999174891 714D0 /\nC\nC\nC           LIST OF MAJOR VARIABLES\nC           -----------------------\nC\nC           CENTR  - MID POINT OF THE INTERVAL\nC           HLGTH  - HALF-LENGTH OF THE INTERVAL\nC           ABSC*  - ABSCISSA\nC           TABSC* - TRANSFORMED ABSCISSA\nC           FVAL*  - FUNCTION VALUE\nC           RESG   - RESULT OF THE 7-POINT GAUSS FORMULA\nC           RESK   - RESULT OF THE 15-POINT KRONROD FORMULA\nC           RESKH  - APPROXIMATION TO THE MEAN VALUE OF THE TRANSFORMED\nC                    INTEGRAND OVER (A,B), I.E. TO I/(B-A)\nC\nC           MACHINE DEPENDENT CONSTANTS\nC           ---------------------------\nC\nC           EPMACH IS THE LARGEST RELATIVE SPACING.\nC           UFLOW IS THE SMALLEST POSITIVE MAGNITUDE.\nC\nC***FIRST EXECUTABLE STATEMENT  DQK15I\n      EPMACH = D1MACH(4)\n      UFLOW = D1MACH(1)\n      DINF = MIN0(1,INF)\nC\n      CENTR = 0.5D+00*(A+B)\n      HLGTH = 0.5D+00*(B-A)\n      TABSC1 = BOUN+DINF*(0.1D+01-CENTR)/CENTR\n      IERR = 0\n      CALL F(TABSC1,IERR,FVAL1)\n      IF (IERR .LT. 0) RETURN\n      IF(INF.EQ.2) THEN\n        CALL F(-TABSC1,IERR,FVALT)\n        IF (IERR .LT. 0) RETURN\n        FVAL1 = FVAL1+FVALT\n      ENDIF\n      FC = (FVAL1/CENTR)/CENTR\nC\nC           COMPUTE THE 15-POINT KRONROD APPROXIMATION TO\nC           THE INTEGRAL, AND ESTIMATE THE ERROR.\nC\n      RESG = WG(8)*FC\n      RESK = WGK(8)*FC\n      RESABS = DABS(RESK)\n      DO 10 J=1,7\n        ABSC = HLGTH*XGK(J)\n        ABSC1 = CENTR-ABSC\n        ABSC2 = CENTR+ABSC\n        TABSC1 = BOUN+DINF*(0.1D+01-ABSC1)/ABSC1\n        TABSC2 = BOUN+DINF*(0.1D+01-ABSC2)/ABSC2\n        CALL F(TABSC1,IERR,FVAL1)\n        IF (IERR .LT. 0) RETURN\n        CALL F(TABSC2,IERR,FVAL2)\n        IF (IERR .LT. 0) RETURN\n        IF(INF.EQ.2) THEN\n          CALL F(-TABSC1,IERR,FVALT)\n          IF (IERR .LT. 0) RETURN\n          FVAL1 = FVAL1+FVALT\n        ENDIF\n        IF(INF.EQ.2) THEN\n          CALL F(-TABSC2,IERR,FVALT)\n          IF (IERR .LT. 0) RETURN\n          FVAL2 = FVAL2+FVALT\n        ENDIF\n        FVAL1 = (FVAL1/ABSC1)/ABSC1\n        FVAL2 = (FVAL2/ABSC2)/ABSC2\n        FV1(J) = FVAL1\n        FV2(J) = FVAL2\n        FSUM = FVAL1+FVAL2\n        RESG = RESG+WG(J)*FSUM\n        RESK = RESK+WGK(J)*FSUM\n        RESABS = RESABS+WGK(J)*(DABS(FVAL1)+DABS(FVAL2))\n   10 CONTINUE\n      RESKH = RESK*0.5D+00\n      RESASC = WGK(8)*DABS(FC-RESKH)\n      DO 20 J=1,7\n        RESASC = RESASC+WGK(J)*(DABS(FV1(J)-RESKH)+DABS(FV2(J)-RESKH))\n   20 CONTINUE\n      RESULT = RESK*HLGTH\n      RESASC = RESASC*HLGTH\n      RESABS = RESABS*HLGTH\n      ABSERR = DABS((RESK-RESG)*HLGTH)\n      IF(RESASC.NE.0.0D+00.AND.ABSERR.NE.0.D0) ABSERR = RESASC*\n     * DMIN1(0.1D+01,(0.2D+03*ABSERR/RESASC)**1.5D+00)\n      IF(RESABS.GT.UFLOW/(0.5D+02*EPMACH)) ABSERR = DMAX1\n     * ((EPMACH*0.5D+02)*RESABS,ABSERR)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/quadpack/dqk21.f",
    "content": "      SUBROUTINE DQK21(F,A,B,RESULT,ABSERR,RESABS,RESASC,IERR)\nC***BEGIN PROLOGUE  DQK21\nC***DATE WRITTEN   800101   (YYMMDD)\nC***REVISION DATE  830518   (YYMMDD)\nC***CATEGORY NO.  H2A1A2\nC***KEYWORDS  21-POINT GAUSS-KRONROD RULES\nC***AUTHOR  PIESSENS,ROBERT,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC           DE DONCKER,ELISE,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC***PURPOSE  TO COMPUTE I = INTEGRAL OF F OVER (A,B), WITH ERROR\nC                           ESTIMATE\nC                       J = INTEGRAL OF ABS(F) OVER (A,B)\nC***DESCRIPTION\nC\nC           INTEGRATION RULES\nC           STANDARD FORTRAN SUBROUTINE\nC           DOUBLE PRECISION VERSION\nC\nC           PARAMETERS\nC            ON ENTRY\nC              F      - SUBROUTINE F(X,IERR,RESULT) DEFINING THE INTEGRAND\nC                       FUNCTION F(X). THE ACTUAL NAME FOR F NEEDS TO BE\nC                       DECLARED E X T E R N A L IN THE DRIVER PROGRAM.\nC\nC              A      - DOUBLE PRECISION\nC                       LOWER LIMIT OF INTEGRATION\nC\nC              B      - DOUBLE PRECISION\nC                       UPPER LIMIT OF INTEGRATION\nC\nC            ON RETURN\nC              RESULT - DOUBLE PRECISION\nC                       APPROXIMATION TO THE INTEGRAL I\nC                       RESULT IS COMPUTED BY APPLYING THE 21-POINT\nC                       KRONROD RULE (RESK) OBTAINED BY OPTIMAL ADDITION\nC                       OF ABSCISSAE TO THE 10-POINT GAUSS RULE (RESG).\nC\nC              ABSERR - DOUBLE PRECISION\nC                       ESTIMATE OF THE MODULUS OF THE ABSOLUTE ERROR,\nC                       WHICH SHOULD NOT EXCEED ABS(I-RESULT)\nC\nC              RESABS - DOUBLE PRECISION\nC                       APPROXIMATION TO THE INTEGRAL J\nC\nC              RESASC - DOUBLE PRECISION\nC                       APPROXIMATION TO THE INTEGRAL OF ABS(F-I/(B-A))\nC                       OVER (A,B)\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH\nC***END PROLOGUE  DQK21\nC\n      DOUBLE PRECISION A,ABSC,ABSERR,B,CENTR,DABS,DHLGTH,DMAX1,DMIN1,\n     *  D1MACH,EPMACH,FC,FSUM,FVAL1,FVAL2,FV1,FV2,HLGTH,RESABS,RESASC,\n     *  RESG,RESK,RESKH,RESULT,UFLOW,WG,WGK,XGK\n      INTEGER J,JTW,JTWM1\n      EXTERNAL F\nC\n      DIMENSION FV1(10),FV2(10),WG(5),WGK(11),XGK(11)\nC\nC           THE ABSCISSAE AND WEIGHTS ARE GIVEN FOR THE INTERVAL (-1,1).\nC           BECAUSE OF SYMMETRY ONLY THE POSITIVE ABSCISSAE AND THEIR\nC           CORRESPONDING WEIGHTS ARE GIVEN.\nC\nC           XGK    - ABSCISSAE OF THE 21-POINT KRONROD RULE\nC                    XGK(2), XGK(4), ...  ABSCISSAE OF THE 10-POINT\nC                    GAUSS RULE\nC                    XGK(1), XGK(3), ...  ABSCISSAE WHICH ARE OPTIMALLY\nC                    ADDED TO THE 10-POINT GAUSS RULE\nC\nC           WGK    - WEIGHTS OF THE 21-POINT KRONROD RULE\nC\nC           WG     - WEIGHTS OF THE 10-POINT GAUSS RULE\nC\nC\nC GAUSS QUADRATURE WEIGHTS AND KRONRON QUADRATURE ABSCISSAE AND WEIGHTS\nC AS EVALUATED WITH 80 DECIMAL DIGIT ARITHMETIC BY L. W. FULLERTON,\nC BELL LABS, NOV. 1981.\nC\n      DATA WG  (  1) / 0.0666713443 0868813759 3568809893 332 D0 /\n      DATA WG  (  2) / 0.1494513491 5058059314 5776339657 697 D0 /\n      DATA WG  (  3) / 0.2190863625 1598204399 5534934228 163 D0 /\n      DATA WG  (  4) / 0.2692667193 0999635509 1226921569 469 D0 /\n      DATA WG  (  5) / 0.2955242247 1475287017 3892994651 338 D0 /\nC\n      DATA XGK (  1) / 0.9956571630 2580808073 5527280689 003 D0 /\n      DATA XGK (  2) / 0.9739065285 1717172007 7964012084 452 D0 /\n      DATA XGK (  3) / 0.9301574913 5570822600 1207180059 508 D0 /\n      DATA XGK (  4) / 0.8650633666 8898451073 2096688423 493 D0 /\n      DATA XGK (  5) / 0.7808177265 8641689706 3717578345 042 D0 /\n      DATA XGK (  6) / 0.6794095682 9902440623 4327365114 874 D0 /\n      DATA XGK (  7) / 0.5627571346 6860468333 9000099272 694 D0 /\n      DATA XGK (  8) / 0.4333953941 2924719079 9265943165 784 D0 /\n      DATA XGK (  9) / 0.2943928627 0146019813 1126603103 866 D0 /\n      DATA XGK ( 10) / 0.1488743389 8163121088 4826001129 720 D0 /\n      DATA XGK ( 11) / 0.0000000000 0000000000 0000000000 000 D0 /\nC\n      DATA WGK (  1) / 0.0116946388 6737187427 8064396062 192 D0 /\n      DATA WGK (  2) / 0.0325581623 0796472747 8818972459 390 D0 /\n      DATA WGK (  3) / 0.0547558965 7435199603 1381300244 580 D0 /\n      DATA WGK (  4) / 0.0750396748 1091995276 7043140916 190 D0 /\n      DATA WGK (  5) / 0.0931254545 8369760553 5065465083 366 D0 /\n      DATA WGK (  6) / 0.1093871588 0229764189 9210590325 805 D0 /\n      DATA WGK (  7) / 0.1234919762 6206585107 7958109831 074 D0 /\n      DATA WGK (  8) / 0.1347092173 1147332592 8054001771 707 D0 /\n      DATA WGK (  9) / 0.1427759385 7706008079 7094273138 717 D0 /\n      DATA WGK ( 10) / 0.1477391049 0133849137 4841515972 068 D0 /\n      DATA WGK ( 11) / 0.1494455540 0291690566 4936468389 821 D0 /\nC\nC\nC           LIST OF MAJOR VARIABLES\nC           -----------------------\nC\nC           CENTR  - MID POINT OF THE INTERVAL\nC           HLGTH  - HALF-LENGTH OF THE INTERVAL\nC           ABSC   - ABSCISSA\nC           FVAL*  - FUNCTION VALUE\nC           RESG   - RESULT OF THE 10-POINT GAUSS FORMULA\nC           RESK   - RESULT OF THE 21-POINT KRONROD FORMULA\nC           RESKH  - APPROXIMATION TO THE MEAN VALUE OF F OVER (A,B),\nC                    I.E. TO I/(B-A)\nC\nC\nC           MACHINE DEPENDENT CONSTANTS\nC           ---------------------------\nC\nC           EPMACH IS THE LARGEST RELATIVE SPACING.\nC           UFLOW IS THE SMALLEST POSITIVE MAGNITUDE.\nC\nC***FIRST EXECUTABLE STATEMENT  DQK21\n      EPMACH = D1MACH(4)\n      UFLOW = D1MACH(1)\nC\n      CENTR = 0.5D+00*(A+B)\n      HLGTH = 0.5D+00*(B-A)\n      DHLGTH = DABS(HLGTH)\nC\nC           COMPUTE THE 21-POINT KRONROD APPROXIMATION TO\nC           THE INTEGRAL, AND ESTIMATE THE ABSOLUTE ERROR.\nC\n      RESG = 0.0D+00\n      IERR = 0\n      CALL F(CENTR,IERR,FC)\n      IF (IERR .LT. 0) RETURN\n      RESK = WGK(11)*FC\n      RESABS = DABS(RESK)\n      DO 10 J=1,5\n        JTW = 2*J\n        ABSC = HLGTH*XGK(JTW)\n        CALL F(CENTR-ABSC,IERR,FVAL1)\n        IF (IERR .LT. 0) RETURN\n        CALL F(CENTR+ABSC,IERR,FVAL2)\n        IF (IERR .LT. 0) RETURN\n        FV1(JTW) = FVAL1\n        FV2(JTW) = FVAL2\n        FSUM = FVAL1+FVAL2\n        RESG = RESG+WG(J)*FSUM\n        RESK = RESK+WGK(JTW)*FSUM\n        RESABS = RESABS+WGK(JTW)*(DABS(FVAL1)+DABS(FVAL2))\n   10 CONTINUE\n      DO 15 J = 1,5\n        JTWM1 = 2*J-1\n        ABSC = HLGTH*XGK(JTWM1)\n        CALL F(CENTR-ABSC,IERR,FVAL1)\n        IF (IERR .LT. 0) RETURN\n        CALL F(CENTR+ABSC,IERR,FVAL2)\n        IF (IERR .LT. 0) RETURN\n        FV1(JTWM1) = FVAL1\n        FV2(JTWM1) = FVAL2\n        FSUM = FVAL1+FVAL2\n        RESK = RESK+WGK(JTWM1)*FSUM\n        RESABS = RESABS+WGK(JTWM1)*(DABS(FVAL1)+DABS(FVAL2))\n   15 CONTINUE\n      RESKH = RESK*0.5D+00\n      RESASC = WGK(11)*DABS(FC-RESKH)\n      DO 20 J=1,10\n        RESASC = RESASC+WGK(J)*(DABS(FV1(J)-RESKH)+DABS(FV2(J)-RESKH))\n   20 CONTINUE\n      RESULT = RESK*HLGTH\n      RESABS = RESABS*DHLGTH\n      RESASC = RESASC*DHLGTH\n      ABSERR = DABS((RESK-RESG)*HLGTH)\n      IF(RESASC.NE.0.0D+00.AND.ABSERR.NE.0.0D+00)\n     *  ABSERR = RESASC*DMIN1(0.1D+01,(0.2D+03*ABSERR/RESASC)**1.5D+00)\n      IF(RESABS.GT.UFLOW/(0.5D+02*EPMACH)) ABSERR = DMAX1\n     *  ((EPMACH*0.5D+02)*RESABS,ABSERR)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/quadpack/dqpsrt.f",
    "content": "      SUBROUTINE DQPSRT(LIMIT,LAST,MAXERR,ERMAX,ELIST,IORD,NRMAX)\nC***BEGIN PROLOGUE  DQPSRT\nC***REFER TO  DQAGE,DQAGIE,DQAGPE,DQAWSE\nC***ROUTINES CALLED  (NONE)\nC***REVISION DATE  810101   (YYMMDD)\nC***KEYWORDS  SEQUENTIAL SORTING\nC***AUTHOR  PIESSENS,ROBERT,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC           DE DONCKER,ELISE,APPL. MATH. & PROGR. DIV. - K.U.LEUVEN\nC***PURPOSE  THIS ROUTINE MAINTAINS THE DESCENDING ORDERING IN THE\nC            LIST OF THE LOCAL ERROR ESTIMATED RESULTING FROM THE\nC            INTERVAL SUBDIVISION PROCESS. AT EACH CALL TWO ERROR\nC            ESTIMATES ARE INSERTED USING THE SEQUENTIAL SEARCH\nC            METHOD, TOP-DOWN FOR THE LARGEST ERROR ESTIMATE AND\nC            BOTTOM-UP FOR THE SMALLEST ERROR ESTIMATE.\nC***DESCRIPTION\nC\nC           ORDERING ROUTINE\nC           STANDARD FORTRAN SUBROUTINE\nC           DOUBLE PRECISION VERSION\nC\nC           PARAMETERS (MEANING AT OUTPUT)\nC              LIMIT  - INTEGER\nC                       MAXIMUM NUMBER OF ERROR ESTIMATES THE LIST\nC                       CAN CONTAIN\nC\nC              LAST   - INTEGER\nC                       NUMBER OF ERROR ESTIMATES CURRENTLY IN THE LIST\nC\nC              MAXERR - INTEGER\nC                       MAXERR POINTS TO THE NRMAX-TH LARGEST ERROR\nC                       ESTIMATE CURRENTLY IN THE LIST\nC\nC              ERMAX  - DOUBLE PRECISION\nC                       NRMAX-TH LARGEST ERROR ESTIMATE\nC                       ERMAX = ELIST(MAXERR)\nC\nC              ELIST  - DOUBLE PRECISION\nC                       VECTOR OF DIMENSION LAST CONTAINING\nC                       THE ERROR ESTIMATES\nC\nC              IORD   - INTEGER\nC                       VECTOR OF DIMENSION LAST, THE FIRST K ELEMENTS\nC                       OF WHICH CONTAIN POINTERS TO THE ERROR\nC                       ESTIMATES, SUCH THAT\nC                       ELIST(IORD(1)),...,  ELIST(IORD(K))\nC                       FORM A DECREASING SEQUENCE, WITH\nC                       K = LAST IF LAST.LE.(LIMIT/2+2), AND\nC                       K = LIMIT+1-LAST OTHERWISE\nC\nC              NRMAX  - INTEGER\nC                       MAXERR = IORD(NRMAX)\nC\nC***END PROLOGUE  DQPSRT\nC\n      DOUBLE PRECISION ELIST,ERMAX,ERRMAX,ERRMIN\n      INTEGER I,IBEG,IDO,IORD,ISUCC,J,JBND,JUPBN,K,LAST,LIMIT,MAXERR,\n     *  NRMAX\n      DIMENSION ELIST(LAST),IORD(LAST)\nC\nC           CHECK WHETHER THE LIST CONTAINS MORE THAN\nC           TWO ERROR ESTIMATES.\nC\nC***FIRST EXECUTABLE STATEMENT  DQPSRT\n      IF(LAST.GT.2) GO TO 10\n      IORD(1) = 1\n      IORD(2) = 2\n      GO TO 90\nC\nC           THIS PART OF THE ROUTINE IS ONLY EXECUTED IF, DUE TO A\nC           DIFFICULT INTEGRAND, SUBDIVISION INCREASED THE ERROR\nC           ESTIMATE. IN THE NORMAL CASE THE INSERT PROCEDURE SHOULD\nC           START AFTER THE NRMAX-TH LARGEST ERROR ESTIMATE.\nC\n   10 ERRMAX = ELIST(MAXERR)\n      IF(NRMAX.EQ.1) GO TO 30\n      IDO = NRMAX-1\n      DO 20 I = 1,IDO\n        ISUCC = IORD(NRMAX-1)\nC ***JUMP OUT OF DO-LOOP\n        IF(ERRMAX.LE.ELIST(ISUCC)) GO TO 30\n        IORD(NRMAX) = ISUCC\n        NRMAX = NRMAX-1\n   20    CONTINUE\nC\nC           COMPUTE THE NUMBER OF ELEMENTS IN THE LIST TO BE MAINTAINED\nC           IN DESCENDING ORDER. THIS NUMBER DEPENDS ON THE NUMBER OF\nC           SUBDIVISIONS STILL ALLOWED.\nC\n   30 JUPBN = LAST\n      IF(LAST.GT.(LIMIT/2+2)) JUPBN = LIMIT+3-LAST\n      ERRMIN = ELIST(LAST)\nC\nC           INSERT ERRMAX BY TRAVERSING THE LIST TOP-DOWN,\nC           STARTING COMPARISON FROM THE ELEMENT ELIST(IORD(NRMAX+1)).\nC\n      JBND = JUPBN-1\n      IBEG = NRMAX+1\n      IF(IBEG.GT.JBND) GO TO 50\n      DO 40 I=IBEG,JBND\n        ISUCC = IORD(I)\nC ***JUMP OUT OF DO-LOOP\n        IF(ERRMAX.GE.ELIST(ISUCC)) GO TO 60\n        IORD(I-1) = ISUCC\n   40 CONTINUE\n   50 IORD(JBND) = MAXERR\n      IORD(JUPBN) = LAST\n      GO TO 90\nC\nC           INSERT ERRMIN BY TRAVERSING THE LIST BOTTOM-UP.\nC\n   60 IORD(I-1) = MAXERR\n      K = JBND\n      DO 70 J=I,JBND\n        ISUCC = IORD(K)\nC ***JUMP OUT OF DO-LOOP\n        IF(ERRMIN.LT.ELIST(ISUCC)) GO TO 80\n        IORD(K+1) = ISUCC\n        K = K-1\n   70 CONTINUE\n      IORD(I) = LAST\n      GO TO 90\n   80 IORD(K+1) = LAST\nC\nC           SET MAXERR AND ERMAX.\nC\n   90 MAXERR = IORD(NRMAX)\n      ERMAX = ELIST(MAXERR)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/quadpack/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/dqagi.f \\\n  %reldir%/dqagie.f \\\n  %reldir%/dqagp.f \\\n  %reldir%/dqagpe.f \\\n  %reldir%/dqelg.f \\\n  %reldir%/dqk15i.f \\\n  %reldir%/dqk21.f \\\n  %reldir%/dqpsrt.f \\\n  %reldir%/qagie.f \\\n  %reldir%/qagi.f \\\n  %reldir%/qagpe.f \\\n  %reldir%/qagp.f \\\n  %reldir%/qelg.f \\\n  %reldir%/qk15i.f \\\n  %reldir%/qk21.f \\\n  %reldir%/qpsrt.f \\\n  %reldir%/xerror.f\n"
  },
  {
    "path": "liboctave/external/quadpack/qagi.f",
    "content": "      subroutine qagi(f,bound,inf,epsabs,epsrel,result,abserr,neval,\n     *   ier,limit,lenw,last,iwork,work)\nc***begin prologue  qagi\nc***date written   800101   (yymmdd)\nc***revision date  830518   (yymmdd)\nc***category no.  h2a3a1,h2a4a1\nc***keywords  automatic integrator, infinite intervals,\nc             general-purpose, transformation, extrapolation,\nc             globally adaptive\nc***author  piessens,robert,appl. math. & progr. div. - k.u.leuven\nc           de doncker,elise,appl. math. & progr. div. -k.u.leuven\nc***purpose  the routine calculates an approximation result to a given\nc            integral   i = integral of f over (bound,+infinity)\nc                    or i = integral of f over (-infinity,bound)\nc                    or i = integral of f over (-infinity,+infinity)\nc            hopefully satisfying following claim for accuracy\nc            abs(i-result).le.max(epsabs,epsrel*abs(i)).\nc***description\nc\nc        integration over infinite intervals\nc        standard fortran subroutine\nc\nc        parameters\nc         on entry\nc            f      - subroutine f(x,result) defining the integrand\nc                     function f(x). the actual name for f needs to be\nc                     declared e x t e r n a l in the driver program.\nc\nc            bound  - real\nc                     finite bound of integration range\nc                     (has no meaning if interval is doubly-infinite)\nc\nc            inf    - integer\nc                     indicating the kind of integration range involved\nc                     inf = 1 corresponds to  (bound,+infinity),\nc                     inf = -1            to  (-infinity,bound),\nc                     inf = 2             to (-infinity,+infinity).\nc\nc            epsabs - real\nc                     absolute accuracy requested\nc            epsrel - real\nc                     relative accuracy requested\nc                     if  epsabs.le.0\nc                     and epsrel.lt.max(50*rel.mach.acc.,0.5d-28),\nc                     the routine will end with ier = 6.\nc\nc\nc         on return\nc            result - real\nc                     approximation to the integral\nc\nc            abserr - real\nc                     estimate of the modulus of the absolute error,\nc                     which should equal or exceed abs(i-result)\nc\nc            neval  - integer\nc                     number of integrand evaluations\nc\nc            ier    - integer\nc                     ier = 0 normal and reliable termination of the\nc                             routine. it is assumed that the requested\nc                             accuracy has been achieved.\nc                   - ier.gt.0 abnormal termination of the routine. the\nc                             estimates for result and error are less\nc                             reliable. it is assumed that the requested\nc                             accuracy has not been achieved.\nc            error messages\nc                     ier = 1 maximum number of subdivisions allowed\nc                             has been achieved. one can allow more\nc                             subdivisions by increasing the value of\nc                             limit (and taking the according dimension\nc                             adjustments into account). however, if\nc                             this yields no improvement it is advised\nc                             to analyze the integrand in order to\nc                             determine the integration difficulties. if\nc                             the position of a local difficulty can be\nc                             determined (e.g. singularity,\nc                             discontinuity within the interval) one\nc                             will probably gain from splitting up the\nc                             interval at this point and calling the\nc                             integrator on the subranges. if possible,\nc                             an appropriate special-purpose integrator\nc                             should be used, which is designed for\nc                             handling the type of difficulty involved.\nc                         = 2 the occurrence of roundoff error is\nc                             detected, which prevents the requested\nc                             tolerance from being achieved.\nc                             the error may be under-estimated.\nc                         = 3 extremely bad integrand behaviour occurs\nc                             at some points of the integration\nc                             interval.\nc                         = 4 the algorithm does not converge.\nc                             roundoff error is detected in the\nc                             extrapolation table.\nc                             it is assumed that the requested tolerance\nc                             cannot be achieved, and that the returned\nc                             result is the best which can be obtained.\nc                         = 5 the integral is probably divergent, or\nc                             slowly convergent. it must be noted that\nc                             divergence can occur with any other value\nc                             of ier.\nc                         = 6 the input is invalid, because\nc                             (epsabs.le.0 and\nc                              epsrel.lt.max(50*rel.mach.acc.,0.5d-28))\nc                              or limit.lt.1 or leniw.lt.limit*4.\nc                             result, abserr, neval, last are set to\nc                             zero. exept when limit or leniw is\nc                             invalid, iwork(1), work(limit*2+1) and\nc                             work(limit*3+1) are set to zero, work(1)\nc                             is set to a and work(limit+1) to b.\nc\nc         dimensioning parameters\nc            limit - integer\nc                    dimensioning parameter for iwork\nc                    limit determines the maximum number of subintervals\nc                    in the partition of the given integration interval\nc                    (a,b), limit.ge.1.\nc                    if limit.lt.1, the routine will end with ier = 6.\nc\nc            lenw  - integer\nc                    dimensioning parameter for work\nc                    lenw must be at least limit*4.\nc                    if lenw.lt.limit*4, the routine will end\nc                    with ier = 6.\nc\nc            last  - integer\nc                    on return, last equals the number of subintervals\nc                    produced in the subdivision process, which\nc                    determines the number of significant elements\nc                    actually in the work arrays.\nc\nc         work arrays\nc            iwork - integer\nc                    vector of dimension at least limit, the first\nc                    k elements of which contain pointers\nc                    to the error estimates over the subintervals,\nc                    such that work(limit*3+iwork(1)),... ,\nc                    work(limit*3+iwork(k)) form a decreasing\nc                    sequence, with k = last if last.le.(limit/2+2), and\nc                    k = limit+1-last otherwise\nc\nc            work  - real\nc                    vector of dimension at least lenw\nc                    on return\nc                    work(1), ..., work(last) contain the left\nc                     end points of the subintervals in the\nc                     partition of (a,b),\nc                    work(limit+1), ..., work(limit+last) contain\nc                     the right end points,\nc                    work(limit*2+1), ...,work(limit*2+last) contain the\nc                     integral approximations over the subintervals,\nc                    work(limit*3+1), ..., work(limit*3)\nc                     contain the error estimates.\nc***references  (none)\nc***routines called  qagie,xerror\nc***end prologue  qagi\nc\n      real   abserr,  epsabs,epsrel,result,work\n      integer ier,iwork,    lenw,limit,lvl,l1,l2,l3,neval\nc\n      dimension iwork(limit),work(lenw)\nc\n      external f\nc\nc         check validity of limit and lenw.\nc\nc***first executable statement  qagi\n      ier = 6\n      neval = 0\n      last = 0\n      result = 0.0e+00\n      abserr = 0.0e+00\n      if(limit.lt.1.or.lenw.lt.limit*4) go to 10\nc\nc         prepare call for qagie.\nc\n      l1 = limit+1\n      l2 = limit+l1\n      l3 = limit+l2\nc\n      call qagie(f,bound,inf,epsabs,epsrel,limit,result,abserr,\n     *  neval,ier,work(1),work(l1),work(l2),work(l3),iwork,last)\nc\nc         call error handler if necessary.\nc\n      lvl = 0\n10    if(ier.eq.6) lvl = 1\n      if(ier.ne.0) call xerror('abnormal return from  qagi',26,ier,lvl)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/quadpack/qagie.f",
    "content": "      subroutine qagie(f,bound,inf,epsabs,epsrel,limit,result,abserr,\n     *   neval,ier,alist,blist,rlist,elist,iord,last)\nc***begin prologue  qagie\nc***date written   800101   (yymmdd)\nc***revision date  830518   (yymmdd)\nc***category no.  h2a3a1,h2a4a1\nc***keywords  automatic integrator, infinite intervals,\nc             general-purpose, transformation, extrapolation,\nc             globally adaptive\nc***author  piessens,robert,appl. math & progr. div - k.u.leuven\nc           de doncker,elise,appl. math & progr. div - k.u.leuven\nc***purpose  the routine calculates an approximation result to a given\nc            integral   i = integral of f over (bound,+infinity)\nc                    or i = integral of f over (-infinity,bound)\nc                    or i = integral of f over (-infinity,+infinity),\nc                    hopefully satisfying following claim for accuracy\nc                    abs(i-result).le.max(epsabs,epsrel*abs(i))\nc***description\nc\nc integration over infinite intervals\nc standard fortran subroutine\nc\nc            f      - subroutine f(x,ierr,result) defining the integrand\nc                     function f(x). the actual name for f needs to be\nc                     declared e x t e r n a l in the driver program.\nc\nc            bound  - real\nc                     finite bound of integration range\nc                     (has no meaning if interval is doubly-infinite)\nc\nc            inf    - real\nc                     indicating the kind of integration range involved\nc                     inf = 1 corresponds to  (bound,+infinity),\nc                     inf = -1            to  (-infinity,bound),\nc                     inf = 2             to (-infinity,+infinity).\nc\nc            epsabs - real\nc                     absolute accuracy requested\nc            epsrel - real\nc                     relative accuracy requested\nc                     if  epsabs.le.0\nc                     and epsrel.lt.max(50*rel.mach.acc.,0.5d-28),\nc                     the routine will end with ier = 6.\nc\nc            limit  - integer\nc                     gives an upper bound on the number of subintervals\nc                     in the partition of (a,b), limit.ge.1\nc\nc         on return\nc            result - real\nc                     approximation to the integral\nc\nc            abserr - real\nc                     estimate of the modulus of the absolute error,\nc                     which should equal or exceed abs(i-result)\nc\nc            neval  - integer\nc                     number of integrand evaluations\nc\nc            ier    - integer\nc                     ier = 0 normal and reliable termination of the\nc                             routine. it is assumed that the requested\nc                             accuracy has been achieved.\nc                   - ier.gt.0 abnormal termination of the routine. the\nc                             estimates for result and error are less\nc                             reliable. it is assumed that the requested\nc                             accuracy has not been achieved.\nc            error messages\nc                     ier = 1 maximum number of subdivisions allowed\nc                             has been achieved. one can allow more\nc                             subdivisions by increasing the value of\nc                             limit (and taking the according dimension\nc                             adjustments into account). however,if\nc                             this yields no improvement it is advised\nc                             to analyze the integrand in order to\nc                             determine the integration difficulties.\nc                             if the position of a local difficulty can\nc                             be determined (e.g. singularity,\nc                             discontinuity within the interval) one\nc                             will probably gain from splitting up the\nc                             interval at this point and calling the\nc                             integrator on the subranges. if possible,\nc                             an appropriate special-purpose integrator\nc                             should be used, which is designed for\nc                             handling the type of difficulty involved.\nc                         = 2 the occurrence of roundoff error is\nc                             detected, which prevents the requested\nc                             tolerance from being achieved.\nc                             the error may be under-estimated.\nc                         = 3 extremely bad integrand behaviour occurs\nc                             at some points of the integration\nc                             interval.\nc                         = 4 the algorithm does not converge.\nc                             roundoff error is detected in the\nc                             extrapolation table.\nc                             it is assumed that the requested tolerance\nc                             cannot be achieved, and that the returned\nc                             result is the best which can be obtained.\nc                         = 5 the integral is probably divergent, or\nc                             slowly convergent. it must be noted that\nc                             divergence can occur with any other value\nc                             of ier.\nc                         = 6 the input is invalid, because\nc                             (epsabs.le.0 and\nc                              epsrel.lt.max(50*rel.mach.acc.,0.5d-28),\nc                             result, abserr, neval, last, rlist(1),\nc                             elist(1) and iord(1) are set to zero.\nc                             alist(1) and blist(1) are set to 0\nc                             and 1 respectively.\nc\nc            alist  - real\nc                     vector of dimension at least limit, the first\nc                      last  elements of which are the left\nc                     end points of the subintervals in the partition\nc                     of the transformed integration range (0,1).\nc\nc            blist  - real\nc                     vector of dimension at least limit, the first\nc                      last  elements of which are the right\nc                     end points of the subintervals in the partition\nc                     of the transformed integration range (0,1).\nc\nc            rlist  - real\nc                     vector of dimension at least limit, the first\nc                      last  elements of which are the integral\nc                     approximations on the subintervals\nc\nc            elist  - real\nc                     vector of dimension at least limit,  the first\nc                     last elements of which are the moduli of the\nc                     absolute error estimates on the subintervals\nc\nc            iord   - integer\nc                     vector of dimension limit, the first k\nc                     elements of which are pointers to the\nc                     error estimates over the subintervals,\nc                     such that elist(iord(1)), ..., elist(iord(k))\nc                     form a decreasing sequence, with k = last\nc                     if last.le.(limit/2+2), and k = limit+1-last\nc                     otherwise\nc\nc            last   - integer\nc                     number of subintervals actually produced\nc                     in the subdivision process\nc\nc***references  (none)\nc***routines called  qelg,qk15i,qpsrt,r1mach\nc***end prologue  qagie\nc\n      real abseps,abserr,alist,area,area1,area12,area2,a1,\n     *  a2,blist,boun,bound,b1,b2,correc,defabs,defab1,defab2,\n     *  dres,r1mach,elist,epmach,epsabs,epsrel,erlarg,erlast,\n     *  errbnd,errmax,error1,error2,erro12,errsum,ertest,oflow,resabs,\n     *  reseps,result,res3la,rlist,rlist2,small,uflow\n      integer id,ier,ierro,inf,iord,iroff1,iroff2,iroff3,jupbnd,k,ksgn,\n     *  ktmin,last,limit,maxerr,neval,nres,nrmax,numrl2\n      logical extrap,noext\nc\n      dimension alist(limit),blist(limit),elist(limit),iord(limit),\n     *  res3la(3),rlist(limit),rlist2(52)\nc\n      external f\nc\nc            the dimension of rlist2 is determined by the value of\nc            limexp in subroutine qelg.\nc\nc\nc            list of major variables\nc            -----------------------\nc\nc           alist     - list of left end points of all subintervals\nc                       considered up to now\nc           blist     - list of right end points of all subintervals\nc                       considered up to now\nc           rlist(i)  - approximation to the integral over\nc                       (alist(i),blist(i))\nc           rlist2    - array of dimension at least (limexp+2),\nc                       containing the part of the epsilon table\nc                       wich is still needed for further computations\nc           elist(i)  - error estimate applying to rlist(i)\nc           maxerr    - pointer to the interval with largest error\nc                       estimate\nc           errmax    - elist(maxerr)\nc           erlast    - error on the interval currently subdivided\nc                       (before that subdivision has taken place)\nc           area      - sum of the integrals over the subintervals\nc           errsum    - sum of the errors over the subintervals\nc           errbnd    - requested accuracy max(epsabs,epsrel*\nc                       abs(result))\nc           *****1    - variable for the left subinterval\nc           *****2    - variable for the right subinterval\nc           last      - index for subdivision\nc           nres      - number of calls to the extrapolation routine\nc           numrl2    - number of elements currently in rlist2. if an\nc                       appropriate approximation to the compounded\nc                       integral has been obtained, it is put in\nc                       rlist2(numrl2) after numrl2 has been increased\nc                       by one.\nc           small     - length of the smallest interval considered up\nc                       to now, multiplied by 1.5\nc           erlarg    - sum of the errors over the intervals larger\nc                       than the smallest interval considered up to now\nc           extrap    - logical variable denoting that the routine\nc                       is attempting to perform extrapolation. i.e.\nc                       before subdividing the smallest interval we\nc                       try to decrease the value of erlarg.\nc           noext     - logical variable denoting that extrapolation\nc                       is no longer allowed (true-value)\nc\nc            machine dependent constants\nc            ---------------------------\nc\nc           epmach is the largest relative spacing.\nc           uflow is the smallest positive magnitude.\nc           oflow is the largest positive magnitude.\nc\n       epmach = r1mach(4)\nc\nc           test on validity of parameters\nc           -----------------------------\nc\nc***first executable statement  qagie\n      ier = 0\n      neval = 0\n      last = 0\n      result = 0.0e+00\n      abserr = 0.0e+00\n      alist(1) = 0.0e+00\n      blist(1) = 0.1e+01\n      rlist(1) = 0.0e+00\n      elist(1) = 0.0e+00\n      iord(1) = 0\n      if(epsabs.le.0.0e+00.and.epsrel.lt.amax1(0.5e+02*epmach,0.5e-14))\n     *  ier = 6\n      if(ier.eq.6) go to 999\nc\nc\nc           first approximation to the integral\nc           -----------------------------------\nc\nc           determine the interval to be mapped onto (0,1).\nc           if inf = 2 the integral is computed as i = i1+i2, where\nc           i1 = integral of f over (-infinity,0),\nc           i2 = integral of f over (0,+infinity).\nc\n      boun = bound\n      if(inf.eq.2) boun = 0.0e+00\n      call qk15i(f,boun,inf,0.0e+00,0.1e+01,result,abserr,\n     *  defabs,resabs,ier)\n      if (ier.lt.0) return\nc\nc           test on accuracy\nc\n      last = 1\n      rlist(1) = result\n      elist(1) = abserr\n      iord(1) = 1\n      dres = abs(result)\n      errbnd = amax1(epsabs,epsrel*dres)\n      if(abserr.le.1.0e+02*epmach*defabs.and.abserr.gt.\n     *  errbnd) ier = 2\n      if(limit.eq.1) ier = 1\n      if(ier.ne.0.or.(abserr.le.errbnd.and.abserr.ne.resabs).or.\n     *  abserr.eq.0.0e+00) go to 130\nc\nc           initialization\nc           --------------\nc\n      uflow = r1mach(1)\n      oflow = r1mach(2)\n      rlist2(1) = result\n      errmax = abserr\n      maxerr = 1\n      area = result\n      errsum = abserr\n      abserr = oflow\n      nrmax = 1\n      nres = 0\n      ktmin = 0\n      numrl2 = 2\n      extrap = .false.\n      noext = .false.\n      ierro = 0\n      iroff1 = 0\n      iroff2 = 0\n      iroff3 = 0\n      ksgn = -1\n      if(dres.ge.(0.1e+01-0.5e+02*epmach)*defabs) ksgn = 1\nc\nc           main do-loop\nc           ------------\nc\n      do 90 last = 2,limit\nc\nc           bisect the subinterval with nrmax-th largest\nc           error estimate.\nc\n        a1 = alist(maxerr)\n        b1 = 0.5e+00*(alist(maxerr)+blist(maxerr))\n        a2 = b1\n        b2 = blist(maxerr)\n        erlast = errmax\n        call qk15i(f,boun,inf,a1,b1,area1,error1,resabs,defab1,ier)\n        if (ier.lt.0) return\n        call qk15i(f,boun,inf,a2,b2,area2,error2,resabs,defab2,ier)\n        if (ier.lt.0) return\nc\nc           improve previous approximations to integral\nc           and error and test for accuracy.\nc\n        area12 = area1+area2\n        erro12 = error1+error2\n        errsum = errsum+erro12-errmax\n        area = area+area12-rlist(maxerr)\n        if(defab1.eq.error1.or.defab2.eq.error2)go to 15\n        if(abs(rlist(maxerr)-area12).gt.0.1e-04*abs(area12)\n     *  .or.erro12.lt.0.99e+00*errmax) go to 10\n        if(extrap) iroff2 = iroff2+1\n        if(.not.extrap) iroff1 = iroff1+1\n   10   if(last.gt.10.and.erro12.gt.errmax) iroff3 = iroff3+1\n   15   rlist(maxerr) = area1\n        rlist(last) = area2\n        errbnd = amax1(epsabs,epsrel*abs(area))\nc\nc           test for roundoff error and eventually\nc           set error flag.\nc\n        if(iroff1+iroff2.ge.10.or.iroff3.ge.20) ier = 2\n        if(iroff2.ge.5) ierro = 3\nc\nc           set error flag in the case that the number of\nc           subintervals equals limit.\nc\n        if(last.eq.limit) ier = 1\nc\nc           set error flag in the case of bad integrand behaviour\nc           at some points of the integration range.\nc\n        if(amax1(abs(a1),abs(b2)).le.(0.1e+01+0.1e+03*epmach)*\n     *  (abs(a2)+0.1e+04*uflow)) ier = 4\nc\nc           append the newly-created intervals to the list.\nc\n        if(error2.gt.error1) go to 20\n        alist(last) = a2\n        blist(maxerr) = b1\n        blist(last) = b2\n        elist(maxerr) = error1\n        elist(last) = error2\n        go to 30\n   20   alist(maxerr) = a2\n        alist(last) = a1\n        blist(last) = b1\n        rlist(maxerr) = area2\n        rlist(last) = area1\n        elist(maxerr) = error2\n        elist(last) = error1\nc\nc           call subroutine qpsrt to maintain the descending ordering\nc           in the list of error estimates and select the\nc           subinterval with nrmax-th largest error estimate (to be\nc           bisected next).\nc\n   30   call qpsrt(limit,last,maxerr,errmax,elist,iord,nrmax)\n        if(errsum.le.errbnd) go to 115\n        if(ier.ne.0) go to 100\n        if(last.eq.2) go to 80\n        if(noext) go to 90\n        erlarg = erlarg-erlast\n        if(abs(b1-a1).gt.small) erlarg = erlarg+erro12\n        if(extrap) go to 40\nc\nc           test whether the interval to be bisected next is the\nc           smallest interval.\nc\n        if(abs(blist(maxerr)-alist(maxerr)).gt.small) go to 90\n        extrap = .true.\n        nrmax = 2\n   40   if(ierro.eq.3.or.erlarg.le.ertest) go to 60\nc\nc           the smallest interval has the largest error.\nc           before bisecting decrease the sum of the errors\nc           over the larger intervals (erlarg) and perform\nc           extrapolation.\nc\n        id = nrmax\n        jupbnd = last\n        if(last.gt.(2+limit/2)) jupbnd = limit+3-last\n        do 50 k = id,jupbnd\n          maxerr = iord(nrmax)\n          errmax = elist(maxerr)\n          if(abs(blist(maxerr)-alist(maxerr)).gt.small) go to 90\n          nrmax = nrmax+1\n   50   continue\nc\nc           perform extrapolation.\nc\n   60   numrl2 = numrl2+1\n        rlist2(numrl2) = area\n        call qelg(numrl2,rlist2,reseps,abseps,res3la,nres)\n        ktmin = ktmin+1\n        if(ktmin.gt.5.and.abserr.lt.0.1e-02*errsum) ier = 5\n        if(abseps.ge.abserr) go to 70\n        ktmin = 0\n        abserr = abseps\n        result = reseps\n        correc = erlarg\n        ertest = amax1(epsabs,epsrel*abs(reseps))\n        if(abserr.le.ertest) go to 100\nc\nc            prepare bisection of the smallest interval.\nc\n   70   if(numrl2.eq.1) noext = .true.\n        if(ier.eq.5) go to 100\n        maxerr = iord(1)\n        errmax = elist(maxerr)\n        nrmax = 1\n        extrap = .false.\n        small = small*0.5e+00\n        erlarg = errsum\n        go to 90\n   80   small = 0.375e+00\n        erlarg = errsum\n        ertest = errbnd\n        rlist2(2) = area\n   90 continue\nc\nc           set final result and error estimate.\nc           ------------------------------------\nc\n  100 if(abserr.eq.oflow) go to 115\n      if((ier+ierro).eq.0) go to 110\n      if(ierro.eq.3) abserr = abserr+correc\n      if(ier.eq.0) ier = 3\n      if(result.ne.0.0e+00.and.area.ne.0.0e+00)go to 105\n      if(abserr.gt.errsum)go to 115\n      if(area.eq.0.0e+00) go to 130\n      go to 110\n  105 if(abserr/abs(result).gt.errsum/abs(area))go to 115\nc\nc           test on divergence\nc\n  110 if(ksgn.eq.(-1).and.amax1(abs(result),abs(area)).le.\n     * defabs*0.1e-01) go to 130\n      if(0.1e-01.gt.(result/area).or.(result/area).gt.0.1e+03.\n     *or.errsum.gt.abs(area)) ier = 6\n      go to 130\nc\nc           compute global integral sum.\nc\n  115 result = 0.0e+00\n      do 120 k = 1,last\n        result = result+rlist(k)\n  120 continue\n      abserr = errsum\n  130 neval = 30*last-15\n      if(inf.eq.2) neval = 2*neval\n      if(ier.gt.2) ier=ier-1\n  999 return\n      end\n"
  },
  {
    "path": "liboctave/external/quadpack/qagp.f",
    "content": "      subroutine qagp(f,a,b,npts2,points,epsabs,epsrel,result,abserr,\n     *   neval,ier,leniw,lenw,last,iwork,work)\nc***begin prologue  qagp\nc***date written   800101   (yymmdd)\nc***revision date  830518   (yymmdd)\nc***category no.  h2a2a1\nc***keywords  automatic integrator, general-purpose,\nc             singularities at user specified points,\nc             extrapolation, globally adaptive\nc***author  piessens,robert,appl. math. & progr. div - k.u.leuven\nc           de doncker,elise,appl. math. & progr. div. - k.u.leuven\nc***purpose  the routine calculates an approximation result to a given\nc            definite integral i = integral of f over (a,b),\nc            hopefully satisfying following claim for accuracy\nc            break points of the integration interval, where local\nc            difficulties of the integrand may occur(e.g. singularities,\nc            discontinuities), are provided by the user.\nc***description\nc\nc        computation of a definite integral\nc        standard fortran subroutine\nc        real version\nc\nc        parameters\nc         on entry\nc            f      - subroutine f(x,ierr,result) defining the integrand\nc                     function f(x). the actual name for f needs to be\nc                     declared e x t e r n a l in the driver program.\nc\nc            a      - real\nc                     lower limit of integration\nc\nc            b      - real\nc                     upper limit of integration\nc\nc            npts2  - integer\nc                     number equal to two more than the number of\nc                     user-supplied break points within the integration\nc                     range, npts.ge.2.\nc                     if npts2.lt.2, the routine will end with ier = 6.\nc\nc            points - real\nc                     vector of dimension npts2, the first (npts2-2)\nc                     elements of which are the user provided break\nc                     points. if these points do not constitute an\nc                     ascending sequence there will be an automatic\nc                     sorting.\nc\nc            epsabs - real\nc                     absolute accuracy requested\nc            epsrel - real\nc                     relative accuracy requested\nc                     if  epsabs.le.0\nc                     and epsrel.lt.max(50*rel.mach.acc.,0.5d-28),\nc                     the routine will end with ier = 6.\nc\nc         on return\nc            result - real\nc                     approximation to the integral\nc\nc            abserr - real\nc                     estimate of the modulus of the absolute error,\nc                     which should equal or exceed abs(i-result)\nc\nc            neval  - integer\nc                     number of integrand evaluations\nc\nc            ier    - integer\nc                     ier = 0 normal and reliable termination of the\nc                             routine. it is assumed that the requested\nc                             accuracy has been achieved.\nc                     ier.gt.0 abnormal termination of the routine.\nc                             the estimates for integral and error are\nc                             less reliable. it is assumed that the\nc                             requested accuracy has not been achieved.\nc            error messages\nc                     ier = 1 maximum number of subdivisions allowed\nc                             has been achieved. one can allow more\nc                             subdivisions by increasing the value of\nc                             limit (and taking the according dimension\nc                             adjustments into account). however, if\nc                             this yields no improvement it is advised\nc                             to analyze the integrand in order to\nc                             determine the integration difficulties. if\nc                             the position of a local difficulty can be\nc                             determined (i.e. singularity,\nc                             discontinuity within the interval), it\nc                             should be supplied to the routine as an\nc                             element of the vector points. if necessary\nc                             an appropriate special-purpose integrator\nc                             must be used, which is designed for\nc                             handling the type of difficulty involved.\nc                         = 2 the occurrence of roundoff error is\nc                             detected, which prevents the requested\nc                             tolerance from being achieved.\nc                             the error may be under-estimated.\nc                         = 3 extremely bad integrand behaviour occurs\nc                             at some points of the integration\nc                             interval.\nc                         = 4 the algorithm does not converge.\nc                             roundoff error is detected in the\nc                             extrapolation table.\nc                             it is presumed that the requested\nc                             tolerance cannot be achieved, and that\nc                             the returned result is the best which\nc                             can be obtained.\nc                         = 5 the integral is probably divergent, or\nc                             slowly convergent. it must be noted that\nc                             divergence can occur with any other value\nc                             of ier.gt.0.\nc                         = 6 the input is invalid because\nc                             npts2.lt.2 or\nc                             break points are specified outside\nc                             the integration range or\nc                             (epsabs.le.0 and\nc                              epsrel.lt.max(50*rel.mach.acc.,0.5d-28))\nc                             result, abserr, neval, last are set to\nc                             zero. exept when leniw or lenw or npts2 is\nc                             invalid, iwork(1), iwork(limit+1),\nc                             work(limit*2+1) and work(limit*3+1)\nc                             are set to zero.\nc                             work(1) is set to a and work(limit+1)\nc                             to b (where limit = (leniw-npts2)/2).\nc\nc         dimensioning parameters\nc            leniw - integer\nc                    dimensioning parameter for iwork\nc                    leniw determines limit = (leniw-npts2)/2,\nc                    which is the maximum number of subintervals in the\nc                    partition of the given integration interval (a,b),\nc                    leniw.ge.(3*npts2-2).\nc                    if leniw.lt.(3*npts2-2), the routine will end with\nc                    ier = 6.\nc\nc            lenw  - integer\nc                    dimensioning parameter for work\nc                    lenw must be at least leniw*2-npts2.\nc                    if lenw.lt.leniw*2-npts2, the routine will end\nc                    with ier = 6.\nc\nc            last  - integer\nc                    on return, last equals the number of subintervals\nc                    produced in the subdivision process, which\nc                    determines the number of significant elements\nc                    actually in the work arrays.\nc\nc         work arrays\nc            iwork - integer\nc                    vector of dimension at least leniw. on return,\nc                    the first k elements of which contain\nc                    pointers to the error estimates over the\nc                    subintervals, such that work(limit*3+iwork(1)),...,\nc                    work(limit*3+iwork(k)) form a decreasing\nc                    sequence, with k = last if last.le.(limit/2+2), and\nc                    k = limit+1-last otherwise\nc                    iwork(limit+1), ...,iwork(limit+last) contain the\nc                     subdivision levels of the subintervals, i.e.\nc                     if (aa,bb) is a subinterval of (p1,p2)\nc                     where p1 as well as p2 is a user-provided\nc                     break point or integration limit, then (aa,bb) has\nc                     level l if abs(bb-aa) = abs(p2-p1)*2**(-l),\nc                    iwork(limit*2+1), ..., iwork(limit*2+npts2) have\nc                     no significance for the user,\nc                    note that limit = (leniw-npts2)/2.\nc\nc            work  - real\nc                    vector of dimension at least lenw\nc                    on return\nc                    work(1), ..., work(last) contain the left\nc                     end points of the subintervals in the\nc                     partition of (a,b),\nc                    work(limit+1), ..., work(limit+last) contain\nc                     the right end points,\nc                    work(limit*2+1), ..., work(limit*2+last) contain\nc                     the integral approximations over the subintervals,\nc                    work(limit*3+1), ..., work(limit*3+last)\nc                     contain the corresponding error estimates,\nc                    work(limit*4+1), ..., work(limit*4+npts2)\nc                     contain the integration limits and the\nc                     break points sorted in an ascending sequence.\nc                    note that limit = (leniw-npts2)/2.\nc\nc***references  (none)\nc***routines called  qagpe,xerror\nc***end prologue  qagp\nc\n      real a,abserr,b,epsabs,epsrel,points,result,work\n      integer ier,iwork,leniw,lenw,limit,lvl,l1,l2,l3,neval,npts2\nc\n      dimension iwork(leniw),points(npts2),work(lenw)\nc\n      external f\nc\nc         check validity of limit and lenw.\nc\nc***first executable statement  qagp\n      ier = 6\n      neval = 0\n      last = 0\n      result = 0.0e+00\n      abserr = 0.0e+00\n      if(leniw.lt.(3*npts2-2).or.lenw.lt.(leniw*2-npts2).or.npts2.lt.2)\n     *  go to 10\nc\nc         prepare call for qagpe.\nc\n      limit = (leniw-npts2)/2\n      l1 = limit+1\n      l2 = limit+l1\n      l3 = limit+l2\n      l4 = limit+l3\nc\n      call qagpe(f,a,b,npts2,points,epsabs,epsrel,limit,result,abserr,\n     *  neval,ier,work(1),work(l1),work(l2),work(l3),work(l4),\n     *  iwork(1),iwork(l1),iwork(l2),last)\nc\nc         call error handler if necessary.\nc\n      lvl = 0\n10    if(ier.eq.6) lvl = 1\n      if(ier.ne.0) call xerror('abnormal return from  qagp',26,ier,lvl)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/quadpack/qagpe.f",
    "content": "      subroutine qagpe(f,a,b,npts2,points,epsabs,epsrel,limit,result,\n     *   abserr,neval,ier,alist,blist,rlist,elist,pts,iord,level,ndin,\n     *   last)\nc***begin prologue  qagpe\nc***date written   800101   (yymmdd)\nc***revision date  830518   (yymmdd)\nc***category no.  h2a2a1\nc***keywords  automatic integrator, general-purpose,\nc             singularities at user specified points,\nc             extrapolation, globally adaptive.\nc***author  piessens,robert ,appl. math. & progr. div. - k.u.leuven\nc           de doncker,elise,appl. math. & progr. div. - k.u.leuven\nc***purpose  the routine calculates an approximation result to a given\nc            definite integral i = integral of f over (a,b),hopefully\nc            satisfying following claim for accuracy abs(i-result).le.\nc            max(epsabs,epsrel*abs(i)). break points of the integration\nc            interval, where local difficulties of the integrand may\nc            occur(e.g. singularities,discontinuities),provided by user.\nc***description\nc\nc        computation of a definite integral\nc        standard fortran subroutine\nc        real version\nc\nc        parameters\nc         on entry\nc            f      - subroutine f(x,ierr,result) defining the integrand\nc                     function f(x). the actual name for f needs to be\nc                     declared e x t e r n a l in the driver program.\nc\nc            a      - real\nc                     lower limit of integration\nc\nc            b      - real\nc                     upper limit of integration\nc\nc            npts2  - integer\nc                     number equal to two more than the number of\nc                     user-supplied break points within the integration\nc                     range, npts2.ge.2.\nc                     if npts2.lt.2, the routine will end with ier = 6.\nc\nc            points - real\nc                     vector of dimension npts2, the first (npts2-2)\nc                     elements of which are the user provided break\nc                     points. if these points do not constitute an\nc                     ascending sequence there will be an automatic\nc                     sorting.\nc\nc            epsabs - real\nc                     absolute accuracy requested\nc            epsrel - real\nc                     relative accuracy requested\nc                     if  epsabs.le.0\nc                     and epsrel.lt.max(50*rel.mach.acc.,0.5d-28),\nc                     the routine will end with ier = 6.\nc\nc            limit  - integer\nc                     gives an upper bound on the number of subintervals\nc                     in the partition of (a,b), limit.ge.npts2\nc                     if limit.lt.npts2, the routine will end with\nc                     ier = 6.\nc\nc         on return\nc            result - real\nc                     approximation to the integral\nc\nc            abserr - real\nc                     estimate of the modulus of the absolute error,\nc                     which should equal or exceed abs(i-result)\nc\nc            neval  - integer\nc                     number of integrand evaluations\nc\nc            ier    - integer\nc                     ier = 0 normal and reliable termination of the\nc                             routine. it is assumed that the requested\nc                             accuracy has been achieved.\nc                     ier.gt.0 abnormal termination of the routine.\nc                             the estimates for integral and error are\nc                             less reliable. it is assumed that the\nc                             requested accuracy has not been achieved.\nc            error messages\nc                     ier = 1 maximum number of subdivisions allowed\nc                             has been achieved. one can allow more\nc                             subdivisions by increasing the value of\nc                             limit (and taking the according dimension\nc                             adjustments into account). however, if\nc                             this yields no improvement it is advised\nc                             to analyze the integrand in order to\nc                             determine the integration difficulties. if\nc                             the position of a local difficulty can be\nc                             determined (i.e. singularity,\nc                             discontinuity within the interval), it\nc                             should be supplied to the routine as an\nc                             element of the vector points. if necessary\nc                             an appropriate special-purpose integrator\nc                             must be used, which is designed for\nc                             handling the type of difficulty involved.\nc                         = 2 the occurrence of roundoff error is\nc                             detected, which prevents the requested\nc                             tolerance from being achieved.\nc                             the error may be under-estimated.\nc                         = 3 extremely bad integrand behaviour occurs\nc                             at some points of the integration\nc                             interval.\nc                         = 4 the algorithm does not converge.\nc                             roundoff error is detected in the\nc                             extrapolation table. it is presumed that\nc                             the requested tolerance cannot be\nc                             achieved, and that the returned result is\nc                             the best which can be obtained.\nc                         = 5 the integral is probably divergent, or\nc                             slowly convergent. it must be noted that\nc                             divergence can occur with any other value\nc                             of ier.gt.0.\nc                         = 6 the input is invalid because\nc                             npts2.lt.2 or\nc                             break points are specified outside\nc                             the integration range or\nc                             (epsabs.le.0 and\nc                              epsrel.lt.max(50*rel.mach.acc.,0.5d-28))\nc                             or limit.lt.npts2.\nc                             result, abserr, neval, last, rlist(1),\nc                             and elist(1) are set to zero. alist(1) and\nc                             blist(1) are set to a and b respectively.\nc\nc            alist  - real\nc                     vector of dimension at least limit, the first\nc                      last  elements of which are the left end points\nc                     of the subintervals in the partition of the given\nc                     integration range (a,b)\nc\nc            blist  - real\nc                     vector of dimension at least limit, the first\nc                      last  elements of which are the right end points\nc                     of the subintervals in the partition of the given\nc                     integration range (a,b)\nc\nc            rlist  - real\nc                     vector of dimension at least limit, the first\nc                      last  elements of which are the integral\nc                     approximations on the subintervals\nc\nc            elist  - real\nc                     vector of dimension at least limit, the first\nc                      last  elements of which are the moduli of the\nc                     absolute error estimates on the subintervals\nc\nc            pts    - real\nc                     vector of dimension at least npts2, containing the\nc                     integration limits and the break points of the\nc                     interval in ascending sequence.\nc\nc            level  - integer\nc                     vector of dimension at least limit, containing the\nc                     subdivision levels of the subinterval, i.e. if\nc                     (aa,bb) is a subinterval of (p1,p2) where p1 as\nc                     well as p2 is a user-provided break point or\nc                     integration limit, then (aa,bb) has level l if\nc                     abs(bb-aa) = abs(p2-p1)*2**(-l).\nc\nc            ndin   - integer\nc                     vector of dimension at least npts2, after first\nc                     integration over the intervals (pts(i)),pts(i+1),\nc                     i = 0,1, ..., npts2-2, the error estimates over\nc                     some of the intervals may have been increased\nc                     artificially, in order to put their subdivision\nc                     forward. if this happens for the subinterval\nc                     numbered k, ndin(k) is put to 1, otherwise\nc                     ndin(k) = 0.\nc\nc            iord   - integer\nc                     vector of dimension at least limit, the first k\nc                     elements of which are pointers to the\nc                     error estimates over the subintervals,\nc                     such that elist(iord(1)), ..., elist(iord(k))\nc                     form a decreasing sequence, with k = last\nc                     if last.le.(limit/2+2), and k = limit+1-last\nc                     otherwise\nc\nc            last   - integer\nc                     number of subintervals actually produced in the\nc                     subdivisions process\nc\nc***references  (none)\nc***routines called  qelg,qk21,qpsrt,r1mach\nc***end prologue  qagpe\n      real a,abseps,abserr,alist,area,area1,area12,area2,a1,\n     *  a2,b,blist,b1,b2,correc,defabs,defab1,defab2,\n     *  dres,r1mach,elist,epmach,epsabs,epsrel,erlarg,erlast,errbnd,\n     *  errmax,error1,erro12,error2,errsum,ertest,oflow,points,pts,\n     *  resa,resabs,reseps,result,res3la,rlist,rlist2,sign,temp,\n     *  uflow\n      integer i,id,ier,ierro,ind1,ind2,iord,ip1,iroff1,iroff2,\n     *  iroff3,j,jlow,jupbnd,k,ksgn,ktmin,last,levcur,level,levmax,\n     *  limit,maxerr,ndin,neval,nint,nintp1,npts,npts2,nres,\n     *  nrmax,numrl2\n      logical extrap,noext\nc\nc\n      dimension alist(limit),blist(limit),elist(limit),iord(limit),\n     *  level(limit),ndin(npts2),points(npts2),pts(npts2),res3la(3),\n     *  rlist(limit),rlist2(52)\nc\n      external f\nc\nc            the dimension of rlist2 is determined by the value of\nc            limexp in subroutine epsalg (rlist2 should be of dimension\nc            (limexp+2) at least).\nc\nc\nc            list of major variables\nc            -----------------------\nc\nc           alist     - list of left end points of all subintervals\nc                       considered up to now\nc           blist     - list of right end points of all subintervals\nc                       considered up to now\nc           rlist(i)  - approximation to the integral over\nc                       (alist(i),blist(i))\nc           rlist2    - array of dimension at least limexp+2\nc                       containing the part of the epsilon table which\nc                       is still needed for further computations\nc           elist(i)  - error estimate applying to rlist(i)\nc           maxerr    - pointer to the interval with largest error\nc                       estimate\nc           errmax    - elist(maxerr)\nc           erlast    - error on the interval currently subdivided\nc                       (before that subdivision has taken place)\nc           area      - sum of the integrals over the subintervals\nc           errsum    - sum of the errors over the subintervals\nc           errbnd    - requested accuracy max(epsabs,epsrel*\nc                       abs(result))\nc           *****1    - variable for the left subinterval\nc           *****2    - variable for the right subinterval\nc           last      - index for subdivision\nc           nres      - number of calls to the extrapolation routine\nc           numrl2    - number of elements in rlist2. if an\nc                       appropriate approximation to the compounded\nc                       integral has been obtained, it is put in\nc                       rlist2(numrl2) after numrl2 has been increased\nc                       by one.\nc           erlarg    - sum of the errors over the intervals larger\nc                       than the smallest interval considered up to now\nc           extrap    - logical variable denoting that the routine\nc                       is attempting to perform extrapolation. i.e.\nc                       before subdividing the smallest interval we\nc                       try to decrease the value of erlarg.\nc           noext     - logical variable denoting that extrapolation is\nc                       no longer allowed (true-value)\nc\nc            machine dependent constants\nc            ---------------------------\nc\nc           epmach is the largest relative spacing.\nc           uflow is the smallest positive magnitude.\nc           oflow is the largest positive magnitude.\nc\nc***first executable statement  qagpe\n      epmach = r1mach(4)\nc\nc            test on validity of parameters\nc            -----------------------------\nc\n      ier = 0\n      neval = 0\n      last = 0\n      result = 0.0e+00\n      abserr = 0.0e+00\n      alist(1) = a\n      blist(1) = b\n      rlist(1) = 0.0e+00\n      elist(1) = 0.0e+00\n      iord(1) = 0\n      level(1) = 0\n      npts = npts2-2\n      if(npts2.lt.2.or.limit.le.npts.or.(epsabs.le.0.0e+00.and.\n     *  epsrel.lt.amax1(0.5e+02*epmach,0.5e-14))) ier = 6\n      if(ier.eq.6) go to 210\nc\nc            if any break points are provided, sort them into an\nc            ascending sequence.\nc\n      sign = 1.0e+00\n      if(a.gt.b) sign = -1.0e+00\n      pts(1) = amin1(a,b)\n      if(npts.eq.0) go to 15\n      do 10 i = 1,npts\n        pts(i+1) = points(i)\n   10 continue\n   15 pts(npts+2) = amax1(a,b)\n      nint = npts+1\n      a1 = pts(1)\n      if(npts.eq.0) go to 40\n      nintp1 = nint+1\n      do 20 i = 1,nint\n        ip1 = i+1\n        do 20 j = ip1,nintp1\n          if(pts(i).le.pts(j)) go to 20\n          temp = pts(i)\n          pts(i) = pts(j)\n          pts(j) = temp\n   20 continue\n      if(pts(1).ne.amin1(a,b).or.pts(nintp1).ne.\n     *  amax1(a,b)) ier = 6\n      if(ier.eq.6) go to 999\nc\nc            compute first integral and error approximations.\nc            ------------------------------------------------\nc\n   40 resabs = 0.0e+00\n      do 50 i = 1,nint\n        b1 = pts(i+1)\n        call qk21(f,a1,b1,area1,error1,defabs,resa,ier)\n        if (ier.lt.0) return\n        abserr = abserr+error1\n        result = result+area1\n        ndin(i) = 0\n        if(error1.eq.resa.and.error1.ne.0.0e+00) ndin(i) = 1\n        resabs = resabs+defabs\n        level(i) = 0\n        elist(i) = error1\n        alist(i) = a1\n        blist(i) = b1\n        rlist(i) = area1\n        iord(i) = i\n        a1 = b1\n   50 continue\n      errsum = 0.0e+00\n      do 55 i = 1,nint\n        if(ndin(i).eq.1) elist(i) = abserr\n        errsum = errsum+elist(i)\n   55 continue\nc\nc           test on accuracy.\nc\n      last = nint\n      neval = 21*nint\n      dres = abs(result)\n      errbnd = amax1(epsabs,epsrel*dres)\n      if(abserr.le.0.1e+03*epmach*resabs.and.abserr.gt.\n     *  errbnd) ier = 2\n      if(nint.eq.1) go to 80\n      do 70 i = 1,npts\n        jlow = i+1\n        ind1 = iord(i)\n        do 60 j = jlow,nint\n          ind2 = iord(j)\n          if(elist(ind1).gt.elist(ind2)) go to 60\n          ind1 = ind2\n          k = j\n   60   continue\n        if(ind1.eq.iord(i)) go to 70\n        iord(k) = iord(i)\n        iord(i) = ind1\n   70 continue\n      if(limit.lt.npts2) ier = 1\n   80 if(ier.ne.0.or.abserr.le.errbnd) go to 999\nc\nc           initialization\nc           --------------\nc\n      rlist2(1) = result\n      maxerr = iord(1)\n      errmax = elist(maxerr)\n      area = result\n      nrmax = 1\n      nres = 0\n      numrl2 = 1\n      ktmin = 0\n      extrap = .false.\n      noext = .false.\n      erlarg = errsum\n      ertest = errbnd\n      levmax = 1\n      iroff1 = 0\n      iroff2 = 0\n      iroff3 = 0\n      ierro = 0\n      uflow = r1mach(1)\n      oflow = r1mach(2)\n      abserr = oflow\n      ksgn = -1\n      if(dres.ge.(0.1e+01-0.5e+02*epmach)*resabs) ksgn = 1\nc\nc           main do-loop\nc           ------------\nc\n      do 160 last = npts2,limit\nc\nc           bisect the subinterval with the nrmax-th largest\nc           error estimate.\nc\n        levcur = level(maxerr)+1\n        a1 = alist(maxerr)\n        b1 = 0.5e+00*(alist(maxerr)+blist(maxerr))\n        a2 = b1\n        b2 = blist(maxerr)\n        erlast = errmax\n        call qk21(f,a1,b1,area1,error1,resa,defab1,ier)\n        if (ier.lt.0) return\n        call qk21(f,a2,b2,area2,error2,resa,defab2,ier)\n        if (ier.lt.0) return\nc\nc           improve previous approximations to integral\nc           and error and test for accuracy.\nc\n        neval = neval+42\n        area12 = area1+area2\n        erro12 = error1+error2\n        errsum = errsum+erro12-errmax\n        area = area+area12-rlist(maxerr)\n        if(defab1.eq.error1.or.defab2.eq.error2) go to 95\n        if(abs(rlist(maxerr)-area12).gt.0.1e-04*abs(area12)\n     *  .or.erro12.lt.0.99e+00*errmax) go to 90\n        if(extrap) iroff2 = iroff2+1\n        if(.not.extrap) iroff1 = iroff1+1\n   90   if(last.gt.10.and.erro12.gt.errmax) iroff3 = iroff3+1\n   95   level(maxerr) = levcur\n        level(last) = levcur\n        rlist(maxerr) = area1\n        rlist(last) = area2\n        errbnd = amax1(epsabs,epsrel*abs(area))\nc\nc           test for roundoff error and eventually\nc           set error flag.\nc\n        if(iroff1+iroff2.ge.10.or.iroff3.ge.20) ier = 2\n        if(iroff2.ge.5) ierro = 3\nc\nc           set error flag in the case that the number of\nc           subintervals equals limit.\nc\n        if(last.eq.limit) ier = 1\nc\nc           set error flag in the case of bad integrand behaviour\nc           at a point of the integration range\nc\n        if(amax1(abs(a1),abs(b2)).le.(0.1e+01+0.1e+03*epmach)*\n     *  (abs(a2)+0.1e+04*uflow)) ier = 4\nc\nc           append the newly-created intervals to the list.\nc\n        if(error2.gt.error1) go to 100\n        alist(last) = a2\n        blist(maxerr) = b1\n        blist(last) = b2\n        elist(maxerr) = error1\n        elist(last) = error2\n        go to 110\n  100   alist(maxerr) = a2\n        alist(last) = a1\n        blist(last) = b1\n        rlist(maxerr) = area2\n        rlist(last) = area1\n        elist(maxerr) = error2\n        elist(last) = error1\nc\nc           call subroutine qpsrt to maintain the descending ordering\nc           in the list of error estimates and select the\nc           subinterval with nrmax-th largest error estimate (to be\nc           bisected next).\nc\n  110   call qpsrt(limit,last,maxerr,errmax,elist,iord,nrmax)\nc ***jump out of do-loop\n        if(errsum.le.errbnd) go to 190\nc ***jump out of do-loop\n        if(ier.ne.0) go to 170\n        if(noext) go to 160\n        erlarg = erlarg-erlast\n        if(levcur+1.le.levmax) erlarg = erlarg+erro12\n        if(extrap) go to 120\nc\nc           test whether the interval to be bisected next is the\nc           smallest interval.\nc\n        if(level(maxerr)+1.le.levmax) go to 160\n        extrap = .true.\n        nrmax = 2\n  120   if(ierro.eq.3.or.erlarg.le.ertest) go to 140\nc\nc           the smallest interval has the largest error.\nc           before bisecting decrease the sum of the errors\nc           over the larger intervals (erlarg) and perform\nc           extrapolation.\nc\n        id = nrmax\n        jupbnd = last\n        if(last.gt.(2+limit/2)) jupbnd = limit+3-last\n        do 130 k = id,jupbnd\n          maxerr = iord(nrmax)\n          errmax = elist(maxerr)\nc ***jump out of do-loop\n          if(level(maxerr)+1.le.levmax) go to 160\n          nrmax = nrmax+1\n  130   continue\nc\nc           perform extrapolation.\nc\n  140   numrl2 = numrl2+1\n        rlist2(numrl2) = area\n        if(numrl2.le.2) go to 155\n        call qelg(numrl2,rlist2,reseps,abseps,res3la,nres)\n        ktmin = ktmin+1\n        if(ktmin.gt.5.and.abserr.lt.0.1e-02*errsum) ier = 5\n        if(abseps.ge.abserr) go to 150\n        ktmin = 0\n        abserr = abseps\n        result = reseps\n        correc = erlarg\n        ertest = amax1(epsabs,epsrel*abs(reseps))\nc ***jump out of do-loop\n        if(abserr.lt.ertest) go to 170\nc\nc           prepare bisection of the smallest interval.\nc\n  150   if(numrl2.eq.1) noext = .true.\n        if(ier.ge.5) go to 170\n  155   maxerr = iord(1)\n        errmax = elist(maxerr)\n        nrmax = 1\n        extrap = .false.\n        levmax = levmax+1\n        erlarg = errsum\n  160 continue\nc\nc           set the final result.\nc           ---------------------\nc\nc\n  170 if(abserr.eq.oflow) go to 190\n      if((ier+ierro).eq.0) go to 180\n      if(ierro.eq.3) abserr = abserr+correc\n      if(ier.eq.0) ier = 3\n      if(result.ne.0.0e+00.and.area.ne.0.0e+00)go to 175\n      if(abserr.gt.errsum)go to 190\n      if(area.eq.0.0e+00) go to 210\n      go to 180\n  175 if(abserr/abs(result).gt.errsum/abs(area))go to 190\nc\nc           test on divergence.\nc\n  180 if(ksgn.eq.(-1).and.amax1(abs(result),abs(area)).le.\n     *  resabs*0.1e-01) go to 210\n      if(0.1e-01.gt.(result/area).or.(result/area).gt.0.1e+03.or.\n     *  errsum.gt.abs(area)) ier = 6\n      go to 210\nc\nc           compute global integral sum.\nc\n  190 result = 0.0e+00\n      do 200 k = 1,last\n        result = result+rlist(k)\n  200 continue\n      abserr = errsum\n  210 if(ier.gt.2) ier = ier - 1\n      result = result*sign\n 999  return\n      end\n"
  },
  {
    "path": "liboctave/external/quadpack/qelg.f",
    "content": "      subroutine qelg(n,epstab,result,abserr,res3la,nres)\nc***begin prologue  qelg\nc***refer to  qagie,qagoe,qagpe,qagse\nc***routines called  r1mach\nc***revision date  830518   (yymmdd)\nc***keywords  epsilon algorithm, convergence acceleration,\nc             extrapolation\nc***author  piessens,robert,appl. math. & progr. div. - k.u.leuven\nc           de doncker,elise,appl. math & progr. div. - k.u.leuven\nc***purpose  the routine determines the limit of a given sequence of\nc            approximations, by means of the epsilon algorithm of\nc            p. wynn. an estimate of the absolute error is also given.\nc            the condensed epsilon table is computed. only those\nc            elements needed for the computation of the next diagonal\nc            are preserved.\nc***description\nc\nc           epsilon algorithm\nc           standard fortran subroutine\nc           real version\nc\nc           parameters\nc              n      - integer\nc                       epstab(n) contains the new element in the\nc                       first column of the epsilon table.\nc\nc              epstab - real\nc                       vector of dimension 52 containing the elements\nc                       of the two lower diagonals of the triangular\nc                       epsilon table. the elements are numbered\nc                       starting at the right-hand corner of the\nc                       triangle.\nc\nc              result - real\nc                       resulting approximation to the integral\nc\nc              abserr - real\nc                       estimate of the absolute error computed from\nc                       result and the 3 previous results\nc\nc              res3la - real\nc                       vector of dimension 3 containing the last 3\nc                       results\nc\nc              nres   - integer\nc                       number of calls to the routine\nc                       (should be zero at first call)\nc\nc***end prologue  qelg\nc\n      real abserr,delta1,delta2,delta3,r1mach,\n     *  epmach,epsinf,epstab,error,err1,err2,err3,e0,e1,e1abs,e2,e3,\n     *  oflow,res,result,res3la,ss,tol1,tol2,tol3\n      integer i,ib,ib2,ie,indx,k1,k2,k3,limexp,n,newelm,nres,num\n      dimension epstab(52),res3la(3)\nc\nc           list of major variables\nc           -----------------------\nc\nc           e0     - the 4 elements on which the\nc           e1       computation of a new element in\nc           e2       the epsilon table is based\nc           e3                 e0\nc                        e3    e1    new\nc                              e2\nc           newelm - number of elements to be computed in the new\nc                    diagonal\nc           error  - error = abs(e1-e0)+abs(e2-e1)+abs(new-e2)\nc           result - the element in the new diagonal with least value\nc                    of error\nc\nc           machine dependent constants\nc           ---------------------------\nc\nc           epmach is the largest relative spacing.\nc           oflow is the largest positive magnitude.\nc           limexp is the maximum number of elements the epsilon\nc           table can contain. if this number is reached, the upper\nc           diagonal of the epsilon table is deleted.\nc\nc***first executable statement  qelg\n      epmach = r1mach(4)\n      oflow = r1mach(2)\n      nres = nres+1\n      abserr = oflow\n      result = epstab(n)\n      if(n.lt.3) go to 100\n      limexp = 50\n      epstab(n+2) = epstab(n)\n      newelm = (n-1)/2\n      epstab(n) = oflow\n      num = n\n      k1 = n\n      do 40 i = 1,newelm\n        k2 = k1-1\n        k3 = k1-2\n        res = epstab(k1+2)\n        e0 = epstab(k3)\n        e1 = epstab(k2)\n        e2 = res\n        e1abs = abs(e1)\n        delta2 = e2-e1\n        err2 = abs(delta2)\n        tol2 = amax1(abs(e2),e1abs)*epmach\n        delta3 = e1-e0\n        err3 = abs(delta3)\n        tol3 = amax1(e1abs,abs(e0))*epmach\n        if(err2.gt.tol2.or.err3.gt.tol3) go to 10\nc\nc           if e0, e1 and e2 are equal to within machine\nc           accuracy, convergence is assumed.\nc           result = e2\nc           abserr = abs(e1-e0)+abs(e2-e1)\nc\n        result = res\n        abserr = err2+err3\nc ***jump out of do-loop\n        go to 100\n   10   e3 = epstab(k1)\n        epstab(k1) = e1\n        delta1 = e1-e3\n        err1 = abs(delta1)\n        tol1 = amax1(e1abs,abs(e3))*epmach\nc\nc           if two elements are very close to each other, omit\nc           a part of the table by adjusting the value of n\nc\n        if(err1.le.tol1.or.err2.le.tol2.or.err3.le.tol3) go to 20\n        ss = 0.1e+01/delta1+0.1e+01/delta2-0.1e+01/delta3\n        epsinf = abs(ss*e1)\nc\nc           test to detect irregular behaviour in the table, and\nc           eventually omit a part of the table adjusting the value\nc           of n.\nc\n        if(epsinf.gt.0.1e-03) go to 30\n   20   n = i+i-1\nc ***jump out of do-loop\n        go to 50\nc\nc           compute a new element and eventually adjust\nc           the value of result.\nc\n   30   res = e1+0.1e+01/ss\n        epstab(k1) = res\n        k1 = k1-2\n        error = err2+abs(res-e2)+err3\n        if(error.gt.abserr) go to 40\n        abserr = error\n        result = res\n   40 continue\nc\nc           shift the table.\nc\n   50 if(n.eq.limexp) n = 2*(limexp/2)-1\n      ib = 1\n      if((num/2)*2.eq.num) ib = 2\n      ie = newelm+1\n      do 60 i=1,ie\n        ib2 = ib+2\n        epstab(ib) = epstab(ib2)\n        ib = ib2\n   60 continue\n      if(num.eq.n) go to 80\n      indx = num-n+1\n      do 70 i = 1,n\n        epstab(i)= epstab(indx)\n        indx = indx+1\n   70 continue\n   80 if(nres.ge.4) go to 90\n      res3la(nres) = result\n      abserr = oflow\n      go to 100\nc\nc           compute error estimate\nc\n   90 abserr = abs(result-res3la(3))+abs(result-res3la(2))\n     *  +abs(result-res3la(1))\n      res3la(1) = res3la(2)\n      res3la(2) = res3la(3)\n      res3la(3) = result\n  100 abserr = amax1(abserr,0.5e+01*epmach*abs(result))\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/quadpack/qk15i.f",
    "content": "      subroutine qk15i(f,boun,inf,a,b,result,abserr,resabs,resasc,ierr)\nc***begin prologue  qk15i\nc***date written   800101   (yymmdd)\nc***revision date  830518   (yymmdd)\nc***category no.  h2a3a2,h2a4a2\nc***keywords  15-point transformed gauss-kronrod rules\nc***author  piessens,robert,appl. math. & progr. div. - k.u.leuven\nc           de doncker,elise,appl. math. & progr. div. - k.u.leuven\nc***purpose  the original (infinite integration range is mapped\nc            onto the interval (0,1) and (a,b) is a part of (0,1).\nc            it is the purpose to compute\nc            i = integral of transformed integrand over (a,b),\nc            j = integral of abs(transformed integrand) over (a,b).\nc***description\nc\nc           integration rule\nc           standard fortran subroutine\nc           real version\nc\nc           parameters\nc            on entry\nc              f      - subroutine f(x,ierr,result) defining the integrand\nc                       function f(x). the actual name for f needs to be\nc                       declared e x t e r n a l in the calling program.\nc\nc              boun   - real\nc                       finite bound of original integration\nc                       range (set to zero if inf = +2)\nc\nc              inf    - integer\nc                       if inf = -1, the original interval is\nc                                   (-infinity,bound),\nc                       if inf = +1, the original interval is\nc                                   (bound,+infinity),\nc                       if inf = +2, the original interval is\nc                                   (-infinity,+infinity) and\nc                       the integral is computed as the sum of two\nc                       integrals, one over (-infinity,0) and one over\nc                       (0,+infinity).\nc\nc              a      - real\nc                       lower limit for integration over subrange\nc                       of (0,1)\nc\nc              b      - real\nc                       upper limit for integration over subrange\nc                       of (0,1)\nc\nc            on return\nc              result - real\nc                       approximation to the integral i\nc                       result is computed by applying the 15-point\nc                       kronrod rule(resk) obtained by optimal addition\nc                       of abscissae to the 7-point gauss rule(resg).\nc\nc              abserr - real\nc                       estimate of the modulus of the absolute error,\nc                       which should equal or exceed abs(i-result)\nc\nc              resabs - real\nc                       approximation to the integral j\nc\nc              resasc - real\nc                       approximation to the integral of\nc                       abs((transformed integrand)-i/(b-a)) over (a,b)\nc\nc***references  (none)\nc***routines called  r1mach\nc***end prologue  qk15i\nc\n      real a,absc,absc1,absc2,abserr,b,boun,centr,\n     *  dinf,r1mach,epmach,fc,fsum,fval1,fval2,fvalt,fv1,\n     *  fv2,hlgth,resabs,resasc,resg,resk,reskh,result,tabsc1,tabsc2,\n     *  uflow,wg,wgk,xgk\n      integer inf,j,min0\n      external f\nc\n      dimension fv1(7),fv2(7),xgk(8),wgk(8),wg(8)\nc\nc           the abscissae and weights are supplied for the interval\nc           (-1,1).  because of symmetry only the positive abscissae and\nc           their corresponding weights are given.\nc\nc           xgk    - abscissae of the 15-point kronrod rule\nc                    xgk(2), xgk(4), ... abscissae of the 7-point\nc                    gauss rule\nc                    xgk(1), xgk(3), ...  abscissae which are optimally\nc                    added to the 7-point gauss rule\nc\nc           wgk    - weights of the 15-point kronrod rule\nc\nc           wg     - weights of the 7-point gauss rule, corresponding\nc                    to the abscissae xgk(2), xgk(4), ...\nc                    wg(1), wg(3), ... are set to zero.\nc\n      data xgk(1),xgk(2),xgk(3),xgk(4),xgk(5),xgk(6),xgk(7),\n     *  xgk(8)/\n     *     0.9914553711208126e+00,     0.9491079123427585e+00,\n     *     0.8648644233597691e+00,     0.7415311855993944e+00,\n     *     0.5860872354676911e+00,     0.4058451513773972e+00,\n     *     0.2077849550078985e+00,     0.0000000000000000e+00/\nc\n      data wgk(1),wgk(2),wgk(3),wgk(4),wgk(5),wgk(6),wgk(7),\n     *  wgk(8)/\n     *     0.2293532201052922e-01,     0.6309209262997855e-01,\n     *     0.1047900103222502e+00,     0.1406532597155259e+00,\n     *     0.1690047266392679e+00,     0.1903505780647854e+00,\n     *     0.2044329400752989e+00,     0.2094821410847278e+00/\nc\n      data wg(1),wg(2),wg(3),wg(4),wg(5),wg(6),wg(7),wg(8)/\n     *     0.0000000000000000e+00,     0.1294849661688697e+00,\n     *     0.0000000000000000e+00,     0.2797053914892767e+00,\n     *     0.0000000000000000e+00,     0.3818300505051189e+00,\n     *     0.0000000000000000e+00,     0.4179591836734694e+00/\nc\nc\nc           list of major variables\nc           -----------------------\nc\nc           centr  - mid point of the interval\nc           hlgth  - half-length of the interval\nc           absc*  - abscissa\nc           tabsc* - transformed abscissa\nc           fval*  - function value\nc           resg   - result of the 7-point gauss formula\nc           resk   - result of the 15-point kronrod formula\nc           reskh  - approximation to the mean value of the transformed\nc                    integrand over (a,b), i.e. to i/(b-a)\nc\nc           machine dependent constants\nc           ---------------------------\nc\nc           epmach is the largest relative spacing.\nc           uflow is the smallest positive magnitude.\nc\nc***first executable statement  qk15i\n      epmach = r1mach(4)\n      uflow = r1mach(1)\n      dinf = min0(1,inf)\nc\n      centr = 0.5e+00*(a+b)\n      hlgth = 0.5e+00*(b-a)\n      tabsc1 = boun+dinf*(0.1e+01-centr)/centr\n      call f(tabsc1, ierr, fval1)\n      if (ierr.lt.0) return\n      if(inf.eq.2) then\n         call f(-tabsc1, ierr, fval1)\n         if (ierr.lt.0) return\n         fval1 = fval1 + fvalt\n      endif\n      fc = (fval1/centr)/centr\nc\nc           compute the 15-point kronrod approximation to\nc           the integral, and estimate the error.\nc\n      resg = wg(8)*fc\n      resk = wgk(8)*fc\n      resabs = abs(resk)\n      do 10 j=1,7\n        absc = hlgth*xgk(j)\n        absc1 = centr-absc\n        absc2 = centr+absc\n        tabsc1 = boun+dinf*(0.1e+01-absc1)/absc1\n        tabsc2 = boun+dinf*(0.1e+01-absc2)/absc2\n        call f(tabsc1, ierr, fval1)\n        if (ierr.lt.0) return\n        call f(tabsc2, ierr, fval2)\n        if (ierr.lt.0) return\n        if(inf.eq.2) then\n           call f(-tabsc1,ierr,fvalt)\n           if (ierr.lt.0) return\n           fval1 = fval1 + fvalt\n        endif\n        if(inf.eq.2) then\n           call f(-tabsc2,ierr,fvalt)\n           if (ierr.lt.0) return\n           fval2 = fval2 + fvalt\n        endif\n        fval1 = (fval1/absc1)/absc1\n        fval2 = (fval2/absc2)/absc2\n        fv1(j) = fval1\n        fv2(j) = fval2\n        fsum = fval1+fval2\n        resg = resg+wg(j)*fsum\n        resk = resk+wgk(j)*fsum\n        resabs = resabs+wgk(j)*(abs(fval1)+abs(fval2))\n   10 continue\n      reskh = resk*0.5e+00\n      resasc = wgk(8)*abs(fc-reskh)\n      do 20 j=1,7\n        resasc = resasc+wgk(j)*(abs(fv1(j)-reskh)+abs(fv2(j)-reskh))\n   20 continue\n      result = resk*hlgth\n      resasc = resasc*hlgth\n      resabs = resabs*hlgth\n      abserr = abs((resk-resg)*hlgth)\n      if(resasc.ne.0.0e+00.and.abserr.ne.0.e0) abserr = resasc*\n     * amin1(0.1e+01,(0.2e+03*abserr/resasc)**1.5e+00)\n      if(resabs.gt.uflow/(0.5e+02*epmach)) abserr = amax1\n     * ((epmach*0.5e+02)*resabs,abserr)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/quadpack/qk21.f",
    "content": "      subroutine qk21(f,a,b,result,abserr,resabs,resasc,ierr)\nc***begin prologue  qk21\nc***date written   800101   (yymmdd)\nc***revision date  830518   (yymmdd)\nc***category no.  h2a1a2\nc***keywords  21-point gauss-kronrod rules\nc***author  piessens,robert,appl. math. & progr. div. - k.u.leuven\nc           de doncker,elise,appl. math. & progr. div. - k.u.leuven\nc***purpose  to compute i = integral of f over (a,b), with error\nc                           estimate\nc                       j = integral of abs(f) over (a,b)\nc***description\nc\nc           integration rules\nc           standard fortran subroutine\nc           real version\nc\nc           parameters\nc            on entry\nc              f      - subroutine f(x,ierr,result) defining the integrand\nc                       function f(x). the actual name for f needs to be\nc                       declared e x t e r n a l in the driver program.\nc\nc              a      - real\nc                       lower limit of integration\nc\nc              b      - real\nc                       upper limit of integration\nc\nc            on return\nc              result - real\nc                       approximation to the integral i\nc                       result is computed by applying the 21-point\nc                       kronrod rule (resk) obtained by optimal addition\nc                       of abscissae to the 10-point gauss rule (resg).\nc\nc              abserr - real\nc                       estimate of the modulus of the absolute error,\nc                       which should not exceed abs(i-result)\nc\nc              resabs - real\nc                       approximation to the integral j\nc\nc              resasc - real\nc                       approximation to the integral of abs(f-i/(b-a))\nc                       over (a,b)\nc\nc***references  (none)\nc***routines called  r1mach\nc***end prologue  qk21\nc\n      real a,absc,abserr,b,centr,dhlgth,epmach,fc,fsum,fval1,fval2,\n     *  fv1,fv2,hlgth,resabs,resg,resk,reskh,result,r1mach,uflow,wg,wgk,\n     *  xgk\n      integer j,jtw,jtwm1\n      external f\nc\n      dimension fv1(10),fv2(10),wg(5),wgk(11),xgk(11)\nc\nc           the abscissae and weights are given for the interval (-1,1).\nc           because of symmetry only the positive abscissae and their\nc           corresponding weights are given.\nc\nc           xgk    - abscissae of the 21-point kronrod rule\nc                    xgk(2), xgk(4), ...  abscissae of the 10-point\nc                    gauss rule\nc                    xgk(1), xgk(3), ...  abscissae which are optimally\nc                    added to the 10-point gauss rule\nc\nc           wgk    - weights of the 21-point kronrod rule\nc\nc           wg     - weights of the 10-point gauss rule\nc\n      data xgk(1),xgk(2),xgk(3),xgk(4),xgk(5),xgk(6),xgk(7),\n     *  xgk(8),xgk(9),xgk(10),xgk(11)/\n     *         0.9956571630258081e+00,     0.9739065285171717e+00,\n     *     0.9301574913557082e+00,     0.8650633666889845e+00,\n     *     0.7808177265864169e+00,     0.6794095682990244e+00,\n     *     0.5627571346686047e+00,     0.4333953941292472e+00,\n     *     0.2943928627014602e+00,     0.1488743389816312e+00,\n     *     0.0000000000000000e+00/\nc\n      data wgk(1),wgk(2),wgk(3),wgk(4),wgk(5),wgk(6),wgk(7),\n     *  wgk(8),wgk(9),wgk(10),wgk(11)/\n     *     0.1169463886737187e-01,     0.3255816230796473e-01,\n     *     0.5475589657435200e-01,     0.7503967481091995e-01,\n     *     0.9312545458369761e-01,     0.1093871588022976e+00,\n     *     0.1234919762620659e+00,     0.1347092173114733e+00,\n     *     0.1427759385770601e+00,     0.1477391049013385e+00,\n     *     0.1494455540029169e+00/\nc\n      data wg(1),wg(2),wg(3),wg(4),wg(5)/\n     *     0.6667134430868814e-01,     0.1494513491505806e+00,\n     *     0.2190863625159820e+00,     0.2692667193099964e+00,\n     *     0.2955242247147529e+00/\nc\nc\nc           list of major variables\nc           -----------------------\nc\nc           centr  - mid point of the interval\nc           hlgth  - half-length of the interval\nc           absc   - abscissa\nc           fval*  - function value\nc           resg   - result of the 10-point gauss formula\nc           resk   - result of the 21-point kronrod formula\nc           reskh  - approximation to the mean value of f over (a,b),\nc                    i.e. to i/(b-a)\nc\nc\nc           machine dependent constants\nc           ---------------------------\nc\nc           epmach is the largest relative spacing.\nc           uflow is the smallest positive magnitude.\nc\nc***first executable statement  qk21\n      epmach = r1mach(4)\n      uflow = r1mach(1)\nc\n      centr = 0.5e+00*(a+b)\n      hlgth = 0.5e+00*(b-a)\n      dhlgth = abs(hlgth)\nc\nc           compute the 21-point kronrod approximation to\nc           the integral, and estimate the absolute error.\nc\n      resg = 0.0e+00\n      call f(centr, ierr, fc)\n      if (ierr .lt. 0) return\n      resk = wgk(11)*fc\n      resabs = abs(resk)\n      do 10 j=1,5\n        jtw = 2*j\n        absc = hlgth*xgk(jtw)\n        call f(centr-absc,ierr,fval1)\n        if (ierr .lt. 0) return\n        call f(centr+absc,ierr,fval2)\n        if (ierr .lt. 0) return\n        fv1(jtw) = fval1\n        fv2(jtw) = fval2\n        fsum = fval1+fval2\n        resg = resg+wg(j)*fsum\n        resk = resk+wgk(jtw)*fsum\n        resabs = resabs+wgk(jtw)*(abs(fval1)+abs(fval2))\n   10 continue\n      do 15 j = 1,5\n        jtwm1 = 2*j-1\n        absc = hlgth*xgk(jtwm1)\n        call f(centr-absc,ierr,fval1)\n        if (ierr .lt. 0) return\n        call f(centr+absc,ierr,fval2)\n        if (ierr .lt. 0) return\n        fv1(jtwm1) = fval1\n        fv2(jtwm1) = fval2\n        fsum = fval1+fval2\n        resk = resk+wgk(jtwm1)*fsum\n        resabs = resabs+wgk(jtwm1)*(abs(fval1)+abs(fval2))\n   15 continue\n      reskh = resk*0.5e+00\n      resasc = wgk(11)*abs(fc-reskh)\n      do 20 j=1,10\n        resasc = resasc+wgk(j)*(abs(fv1(j)-reskh)+abs(fv2(j)-reskh))\n   20 continue\n      result = resk*hlgth\n      resabs = resabs*dhlgth\n      resasc = resasc*dhlgth\n      abserr = abs((resk-resg)*hlgth)\n      if(resasc.ne.0.0e+00.and.abserr.ne.0.0e+00)\n     *  abserr = resasc*amin1(0.1e+01,\n     *  (0.2e+03*abserr/resasc)**1.5e+00)\n      if(resabs.gt.uflow/(0.5e+02*epmach)) abserr = amax1\n     *  ((epmach*0.5e+02)*resabs,abserr)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/quadpack/qpsrt.f",
    "content": "      subroutine qpsrt(limit,last,maxerr,ermax,elist,iord,nrmax)\nc***begin prologue  qpsrt\nc***refer to  qage,qagie,qagpe,qagse,qawce,qawse,qawoe\nc***routines called  (none)\nc***keywords  sequential sorting\nc***description\nc\nc 1.        qpsrt\nc           ordering routine\nc              standard fortran subroutine\nc              real version\nc\nc 2.        purpose\nc              this routine maintains the descending ordering\nc              in the list of the local error estimates resulting from\nc              the interval subdivision process. at each call two error\nc              estimates are inserted using the sequential search\nc              method, top-down for the largest error estimate\nc              and bottom-up for the smallest error estimate.\nc\nc 3.        calling sequence\nc              call qpsrt(limit,last,maxerr,ermax,elist,iord,nrmax)\nc\nc           parameters (meaning at output)\nc              limit  - integer\nc                       maximum number of error estimates the list\nc                       can contain\nc\nc              last   - integer\nc                       number of error estimates currently\nc                       in the list\nc\nc              maxerr - integer\nc                       maxerr points to the nrmax-th largest error\nc                       estimate currently in the list\nc\nc              ermax  - real\nc                       nrmax-th largest error estimate\nc                       ermax = elist(maxerr)\nc\nc              elist  - real\nc                       vector of dimension last containing\nc                       the error estimates\nc\nc              iord   - integer\nc                       vector of dimension last, the first k\nc                       elements of which contain pointers\nc                       to the error estimates, such that\nc                       elist(iord(1)),... , elist(iord(k))\nc                       form a decreasing sequence, with\nc                       k = last if last.le.(limit/2+2), and\nc                       k = limit+1-last otherwise\nc\nc              nrmax  - integer\nc                       maxerr = iord(nrmax)\nc\nc 4.        no subroutines or functions needed\nc***end prologue  qpsrt\nc\n      real elist,ermax,errmax,errmin\n      integer i,ibeg,ido,iord,isucc,j,jbnd,jupbn,k,last,limit,maxerr,\n     *  nrmax\n      dimension elist(last),iord(last)\nc\nc           check whether the list contains more than\nc           two error estimates.\nc\nc***first executable statement  qpsrt\n      if(last.gt.2) go to 10\n      iord(1) = 1\n      iord(2) = 2\n      go to 90\nc\nc           this part of the routine is only executed\nc           if, due to a difficult integrand, subdivision\nc           increased the error estimate. in the normal case\nc           the insert procedure should start after the\nc           nrmax-th largest error estimate.\nc\n   10 errmax = elist(maxerr)\n      if(nrmax.eq.1) go to 30\n      ido = nrmax-1\n      do 20 i = 1,ido\n        isucc = iord(nrmax-1)\nc ***jump out of do-loop\n        if(errmax.le.elist(isucc)) go to 30\n        iord(nrmax) = isucc\n        nrmax = nrmax-1\n   20    continue\nc\nc           compute the number of elements in the list to\nc           be maintained in descending order. this number\nc           depends on the number of subdivisions still\nc           allowed.\nc\n   30 jupbn = last\n      if(last.gt.(limit/2+2)) jupbn = limit+3-last\n      errmin = elist(last)\nc\nc           insert errmax by traversing the list top-down,\nc           starting comparison from the element elist(iord(nrmax+1)).\nc\n      jbnd = jupbn-1\n      ibeg = nrmax+1\n      if(ibeg.gt.jbnd) go to 50\n      do 40 i=ibeg,jbnd\n        isucc = iord(i)\nc ***jump out of do-loop\n        if(errmax.ge.elist(isucc)) go to 60\n        iord(i-1) = isucc\n   40 continue\n   50 iord(jbnd) = maxerr\n      iord(jupbn) = last\n      go to 90\nc\nc           insert errmin by traversing the list bottom-up.\nc\n   60 iord(i-1) = maxerr\n      k = jbnd\n      do 70 j=i,jbnd\n        isucc = iord(k)\nc ***jump out of do-loop\n        if(errmin.lt.elist(isucc)) go to 80\n        iord(k+1) = isucc\n        k = k-1\n   70 continue\n      iord(i) = last\n      go to 90\n   80 iord(k+1) = last\nc\nc           set maxerr and ermax.\nc\n   90 maxerr = iord(nrmax)\n      ermax = elist(maxerr)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/quadpack/xerror.f",
    "content": "      SUBROUTINE XERROR(MESSG,NMESSG,NERR,LEVEL)\nC\nC     ABSTRACT\nC        XERROR PROCESSES A DIAGNOSTIC MESSAGE, IN A MANNER\nC        DETERMINED BY THE VALUE OF LEVEL AND THE CURRENT VALUE\nC        OF THE LIBRARY ERROR CONTROL FLAG, KONTRL.\nC        (SEE SUBROUTINE XSETF FOR DETAILS.)\nC\nC     DESCRIPTION OF PARAMETERS\nC      --INPUT--\nC        MESSG - THE HOLLERITH MESSAGE TO BE PROCESSED, CONTAINING\nC                NO MORE THAN 72 CHARACTERS.\nC        NMESSG- THE ACTUAL NUMBER OF CHARACTERS IN MESSG.\nC        NERR  - THE ERROR NUMBER ASSOCIATED WITH THIS MESSAGE.\nC                NERR MUST NOT BE ZERO.\nC        LEVEL - ERROR CATEGORY.\nC                =2 MEANS THIS IS AN UNCONDITIONALLY FATAL ERROR.\nC                =1 MEANS THIS IS A RECOVERABLE ERROR.  (I.E., IT IS\nC                   NON-FATAL IF XSETF HAS BEEN APPROPRIATELY CALLED.)\nC                =0 MEANS THIS IS A WARNING MESSAGE ONLY.\nC                =-1 MEANS THIS IS A WARNING MESSAGE WHICH IS TO BE\nC                   PRINTED AT MOST ONCE, REGARDLESS OF HOW MANY\nC                   TIMES THIS CALL IS EXECUTED.\nC\nC     EXAMPLES\nC        CALL XERROR(23HSMOOTH -- NUM WAS ZERO.,23,1,2)\nC        CALL XERROR(43HINTEG  -- LESS THAN FULL ACCURACY ACHIEVED.,\nC                    43,2,1)\nC        CALL XERROR(65HROOTER -- ACTUAL ZERO OF F FOUND BEFORE INTERVAL\nC    1 FULLY COLLAPSED.,65,3,0)\nC        CALL XERROR(39HEXP    -- UNDERFLOWS BEING SET TO ZERO.,39,1,-1)\nC\nC     WRITTEN BY RON JONES, WITH SLATEC COMMON MATH LIBRARY SUBCOMMITTEE\nC     LATEST REVISION ---  7 FEB 1979\nC\n      CHARACTER*(*) MESSG\n      INTEGER NMESSG, NERR, LEVEL\n      CALL XERRWD(MESSG,NMESSG,NERR,LEVEL,0,0,0,0,0.0D0,0.0D0)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/Basegen.doc",
    "content": "\n\n\n\n\n\n\n\n\n\n\n                                     RANDLIB\n\n            Library of Fortran Routines for Random Number Generation\n\n\n\n\n\n\n\n\n                          Base Generator Documentation\n\n\n\n\n\n\n\n\n                            Compiled and Written by:\n\n                                 Barry W. Brown\n                                  James Lovato\n\n\n\n\n\n\n\n\n\n\n                     Department of Biomathematics, Box 237\n                     The University of Texas, M.D. Anderson Cancer Center\n                     1515 Holcombe Boulevard\n                     Houston, TX      77030\n\n\n This work was supported by grant CA-16672 from the National Cancer Institute.\n\f\n\n\n\n                     Base Random Number Generator\n\n\n\nI. OVERVIEW AND DEFAULT BEHAVIOR\n\nThis   set of programs contains   32 virtual random number generators.\nEach generator can provide 1,048,576 blocks of numbers, and each block\nis of length 1,073,741,824.  Any generator can be set to the beginning\nor end of the current block or to its starting value.  The methods are\nfrom the paper  cited  immediately below, and  most of the  code  is a\ntransliteration from the Pascal of the paper into Fortran.\n\nP.  L'Ecuyer and S. Cote.   Implementing a Random  Number Package with\nSplitting Facilities.  ACM Transactions on Mathematical Software 17:1,\npp 98-111.\n\nMost users won't need the sophisticated  capabilities of this package,\nand will desire a single generator.  This single generator (which will\nhave a non-repeating length  of 2.3 X  10^18 numbers) is the  default.\nIn order to accommodate this use, the concept of the current generator\nis added to those of the  cited paper;  references to a  generator are\nalways to the current generator.  The  current generator  is initially\ngenerator number  1; it  can  be  changed by   SETCGN, and the ordinal\nnumber of the current generator can be obtained from GETCGN.\n\nThe user of the default can set the  initial values of the two integer\nseeds with SETALL.   If the user does  not set the   seeds, the random\nnumber   generation will  use   the  default   values, 1234567890  and\n123456789.  The values of the current seeds can be  achieved by a call\nto GETSD.  Random number may be obtained as integers ranging from 1 to\na large integer by reference to function IGNLGI or as a floating point\nnumber between 0 and 1 by a reference to function RANF.  These are the\nonly routines  needed by a user desiring   a single stream   of random\nnumbers.\n\nII. CONCEPTS\n\nA stream of pseudo-random numbers is a sequence, each member  of which\ncan be obtained either as an integer in  the range 1..2,147,483,563 or\nas a floating point number in the range [0..1].  The user is in charge\nof which representation is desired.\n\nThe method contains an algorithm  for generating a  stream with a very\nlong period, 2.3 X 10^18.   This  stream  in  partitioned into G (=32)\nvirtual generators.  Each virtual generator contains 2^20 (=1,048,576)\nblocks   of non-overlapping   random  numbers.   Each  block is   2^30\n(=1,073,741,824) in length.\n\f\n\n\nBase Random Number Generator Page 2\n\n\nThe state of a generator  is determined by two  integers called seeds.\nThe seeds can be  initialized  by the  user; the initial values of the\nfirst must lie between 1 and 2,147,483,562, that of the second between\n1 and 2,147,483,398.  Each time a number is generated,  the  values of\nthe seeds  change.   Three  values   of seeds are remembered   by  the\ngenerators  at all times:  the   value with  which the  generator  was\ninitialized, the value at the beginning of the current block,  and the\nvalue at the beginning of the next block.   The seeds of any generator\ncan be set to any of these three values at any time.\n\n    Of the  32 virtual   generators, exactly one    will  be  the  current\ngenerator, i.e., that one will  be used to  generate values for IGNLGI\nand RANDF.   Initially, the current generator is   set to number  one.\nThe current generator may be changed by calling SETCGN, and the number\nof the current generator can be obtained using GETCGN.\n\nIII. AN EXAMPLE\n\nAn example of  the  need  for these capabilities   is as follows.  Two\nstatistical techniques are being compared on  data of different sizes.\nThe first  technique uses   bootstrapping  and is  thought to   be  as\naccurate using less data   than the second method  which  employs only\nbrute force.\n\nFor the first method, a data set of size uniformly distributed between\n25 and 50 will be generated.  Then the data set  of the specified size\nwill be generated and alalyzed.  The second method will  choose a data\nset size between 100 and 200, generate the data  and alalyze it.  This\nprocess will be repeated 1000 times.\n\nFor  variance reduction, we  want the  random numbers  used in the two\nmethods to be the  same for each of  the 1000 comparisons.  But method\ntwo will  use more random  numbers than   method one and  without this\npackage, synchronization might be difficult.\n\nWith the package, it is a snap.  Use generator 1 to obtain  the sample\nsize for  method one and generator 2  to obtain the  data.  Then reset\nthe state to the beginning  of the current  block and do the same  for\nthe second method.  This assures that the initial data  for method two\nis that used by  method  one.  When both  have concluded,  advance the\nblock for both generators.\n\nIV.  THE INTERFACE\n\nA random number is obtained either  as a random  integer between 1 and\n2,147,483,562  by invoking integer  function  IGNLGI (I GeNerate LarGe\nInteger)  or as a  random  floating point  number  between 0 and 1  by\ninvoking real function RANF.  Neither function has arguments.\n\nThe  seed of the  first generator  can  be set by invoking  subroutine\nSETALL;   the values of   the seeds  of   the other 31 generators  are\ncalculated from this value.\n\f\n\n\nBase Random Number Generator Page 3\n\n\nThe number of  the current generator  can be set by calling subroutine\nSETCGN, which takes a single argument, the integer generator number in\nthe range 1..32.  The number of the current  generator can be obtained\nby invoking subroutine GETCGN  which returns the number  in its single\ninteger argument.\n\n\nV. CALLING SEQUENCES\n\n      A. SETTING THE SEED OF ALL GENERATORS\n\nC**********************************************************************\nC\nC      SUBROUTINE SETALL(ISEED1,ISEED2)\nC               SET ALL random number generators\nC\nC     Sets the initial seed of generator 1 to ISEED1 and ISEED2. The\nC     initial seeds of the other generators are set accordingly, and\nC     all generators states are set to these seeds.\nC\nC                              Arguments\nC\nC\nC     ISEED1 -> First of two integer seeds\nC                                   INTEGER ISEED1\nC\nC     ISEED2 -> Second of two integer seeds\nC                                   INTEGER ISEED1\nC\nC**********************************************************************\n\n\n      B. OBTAINING RANDOM NUMBERS\n\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNLGI()\nC               GeNerate LarGe Integer\nC\nC     Returns a random integer following a uniform distribution over\nC     (1, 2147483562) using the current generator.\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC     REAL FUNCTION RANF()\nC                RANDom number generator as a Function\nC\nC     Returns a random floating point number from a uniform distribution\nC     over 0 - 1 (endpoints of this interval are not returned) using the\nC     current generator\nC\nC**********************************************************************\n\f\n\n\nBase Random Number Generator                                    Page 4\n\n\n      C. SETTING AND OBTAINING THE NUMBER OF THE CURRENT GENERATOR\n\nC**********************************************************************\nC\nC     SUBROUTINE SETCGN( G )\nC                      Set GeNerator\nC\nC     Sets  the  current  generator to G. All references to a generator\nC     are to the current generator.\nC\nC                              Arguments\nC\nC     G --> Number of the current random number generator (1..32)\nC                    INTEGER G\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC      SUBROUTINE GETCGN(G)\nC                         Get GeNerator\nC\nC     Returns in G the number of the current random number generator\nC\nC                              Arguments\nC\nC     G <-- Number of the current random number generator (1..32)\nC                    INTEGER G\nC\nC**********************************************************************\n\n      D. OBTAINING OR CHANGING SEEDS IN CURRENT GENERATOR\n\nC**********************************************************************\nC\nC     SUBROUTINE ADVNST(K)\nC               ADV-a-N-ce ST-ate\nC\nC     Advances the state  of  the current  generator  by 2^K values  and\nC     resets the initial seed to that value.\nC\nC                              Arguments\nC\nC\nC     K -> The generator is advanced by 2^K values\nC                                   INTEGER K\nC\nC**********************************************************************\n\f\n\n\nBase Random Number Generator                                    Page 5\n\n\nC**********************************************************************\nC\nC     SUBROUTINE GETSD(ISEED1,ISEED2)\nC               GET SeeD\nC\nC     Returns the value of two integer seeds of the current generator\nC\nC                              Arguments\nC\nC\nC\nC     ISEED1 <- First integer seed of generator G\nC                                   INTEGER ISEED1\nC\nC     ISEED2 <- Second integer seed of generator G\nC                                   INTEGER ISEED1\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC     SUBROUTINE INITGN(ISDTYP)\nC          INIT-ialize current G-e-N-erator\nC\nC     Reinitializes the state of the current generator\nC\nC                              Arguments\nC\nC\nC     ISDTYP -> The state to which the generator is to be set\nC          ISDTYP = -1  => sets the seeds to their initial value\nC          ISDTYP =  0  => sets the seeds to the first value of\nC                          the current block\nC          ISDTYP =  1  => sets the seeds to the first value of\nC                          the next block\nC\nC                                   INTEGER ISDTYP\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC     SUBROUTINE SETSD(ISEED1,ISEED2)\nC               SET S-ee-D of current generator\nC\nC     Resets the initial  seed of  the current  generator to  ISEED1 and\nC     ISEED2. The seeds of the other generators remain unchanged.\nC\nC                              Arguments\nC\nC\nC     ISEED1 -> First integer seed\nC                                   INTEGER ISEED1\nC\nC     ISEED2 -> Second integer seed\nC                                   INTEGER ISEED1\nC\nC**********************************************************************\n\f\n\n\nBase Random Number Generator                                    Page 6\n\n\n      E. MISCELLANY\n\nC**********************************************************************\nC\nC     INTEGER FUNCTION MLTMOD(A,S,M)\nC\nC                    Returns (A*S) MOD M\nC\nC                              Arguments\nC\nC\nC     A, S, M  -->\nC                         INTEGER A,S,M\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC      SUBROUTINE SETANT(QVALUE)\nC               SET ANTithetic\nC\nC     Sets whether the current generator produces antithetic values.  If\nC     X   is  the value  normally returned  from  a uniform [0,1] random\nC     number generator then 1  - X is the antithetic  value. If X is the\nC     value  normally  returned  from a   uniform  [0,N]  random  number\nC     generator then N - 1 - X is the antithetic value.\nC\nC     All generators are initialized to NOT generate antithetic values.\nC\nC                              Arguments\nC\nC     QVALUE -> .TRUE. if generator G is to generating antithetic\nC                    values, otherwise .FALSE.\nC                                   LOGICAL QVALUE\nC\nC**********************************************************************\n"
  },
  {
    "path": "liboctave/external/ranlib/HOWTOGET",
    "content": "\n                                WHERE TO GET IT\n\n     Software written  by members  of the section   is freely available  to\n     anyone.  Reposting  on other   archives is  encouraged.  The  code  is\n     furnished in source form and as DOS and Macintosh executables. Readers\n     with Internet access  and a browser  might note the following web site\n     addresses:\n\n          University of Texas M. D. Anderson Cancer Center Home Page:\n                           http://utmdacc.mdacc.tmc.edu/\n\n                    Department of Biomathematics Home Page:\n                           http://odin.mdacc.tmc.edu/\n\n\n                              Available Software:\n                       http://odin.mdacc.tmc.edu/anonftp/\n\n\n     Our code can also be obtained  by anonymous ftp to odin.mdacc.tmc.edu.\n     The index is on file ./pub/index.\n\n     Our statistical  code is  also  posted  to statlib  after some  delay.\n     Statlib can be accessed at:\n                             http://lib.stat.cmu.edu/\n     See in particular:\n                    http://lib.stat.cmu.edu/general/Utexas/\n\n     The code is also archived at many other sites (at their option).  Use\n     your favorite search engine to find one close to you.\n"
  },
  {
    "path": "liboctave/external/ranlib/README",
    "content": "\n\n\n\n\n\n\n\n\n\n\n                                     RANDLIB\n\n            Library of Fortran Routines for Random Number Generation\n\n\n                          Version 1.3 -- August, 1997\n\n\n\n\n                                     README\n\n\n\n\n\n\n\n\n                            Compiled and Written by:\n\n                                 Barry W. Brown\n                                  James Lovato\n                                 Kathy Russell\n                                  John Venier\n\n\n\n\n\n\n\n\n\n                     Department of Biomathematics, Box 237\n                     The University of Texas, M.D. Anderson Cancer Center\n                     1515 Holcombe Boulevard\n                     Houston, TX      77030\n\n\n This work was supported by grant CA-16672 from the National Cancer Institute.\n\f\n\n\n                       THANKS TO OUR SUPPORTERS\n\nThis work  was supported  in part by  grant CA-16672 from the National\nCancer Institute.  We are grateful  to Larry and  Pat McNeil of Corpus\nCristi for their generous support.  Some equipment used in this effort\nwas provided by IBM as part of a cooperative study agreement; we thank\nthem.\n\n\n                          SUMMARY OF RANDLIB\n\nThe bottom level routines provide 32 virtual random number generators.\nEach generator can provide 1,048,576 blocks of numbers, and each block\nis of length 1,073,741,824.  Any generator can be set to the beginning\nor end  of the current  block or to  its starting value.  Packaging is\nprovided   so  that  if  these capabilities  are not  needed, a single\ngenerator with period 2.3 X 10^18 is seen.\n\nUsing this base, routines are provided that return:\n    (1)  Beta random deviates\n    (2)  Chi-square random deviates\n    (3)  Exponential random deviates\n    (4)  F random deviates\n    (5)  Gamma random deviates\n    (6)  Multivariate normal random deviates (mean and covariance\n         matrix specified)\n    (7)  Noncentral chi-square random deviates\n    (8)  Noncentral F random deviates\n    (9)  Univariate normal random deviates\n    (10) Random permutations of an integer array\n    (11) Real uniform random deviates between specified limits\n    (12) Binomial random deviates\n    (13) Negative Binomial random deviates\n    (14) Multinomial random deviates\n    (15) Poisson random deviates\n    (16) Integer uniform deviates between specified limits\n    (17) Seeds for the random number generator calculated from a\n         character string\n\n                             INSTALLATION\n\nDirectory src contains  the Fortran source.  The  Fortran code from this\ndirectory should be  compiled and placed  in a library.   Directory test\ncontains three test programs for this code.\n\f\n\n\n\n\n\n                            DOCUMENTATION\n\nDocumentation  is  on directory doc on the  distribution.   All of the\ndocumentation is  in the  form   of  character  (ASCII)    files.   An\nexplanation of the concepts involved in the base generator and details\nof its implementation are contained in Basegen.doc.  A summary  of all\nof the  available  routines is  contained  in randlib.chs  (chs  is  an\nabbreviation of 'cheat sheet').  The 'chs'  file  will probably be the\nreference to randlib  that is primarily used.   The  file, randlib.fdoc,\ncontains all comments heading  each routine.   There is somewhat  more\ninformation   in  'fdoc' than  'chs',  but  the additional information\nconsists primarily of references to the literature.\n\n\n\n                               SOURCES\n\nThe following routines,  which  were  written by others   and  lightly\nmodified for consistency in packaging, are included in RANDLIB.\n\n                        Bottom Level Routines\n\nThese routines are a transliteration of the Pascal in the reference to\nFortran.\n\nL'Ecuyer, P. and  Cote, S. \"Implementing  a Random Number Package with\nSplitting  Facilities.\"  ACM  Transactions   on Mathematical Software,\n17:98-111 (1991)\n\n                             Exponential\n\nThis code was obtained from Netlib.\n\nAhrens,  J.H. and  Dieter, U.   Computer Methods for Sampling From the\nExponential and Normal  Distributions.  Comm. ACM,  15,10 (Oct. 1972),\n873 - 882.\n\n                                Gamma\n\n(Case R >= 1.0)\n\nAhrens, J.H. and Dieter, U.  Generating Gamma  Variates by  a Modified\nRejection Technique.  Comm. ACM, 25,1 (Jan. 1982), 47 - 54.\nAlgorithm GD\n\n(Case 0.0 <= R <= 1.0)\n\nAhrens, J.H. and Dieter, U.  Computer Methods for Sampling from Gamma,\nBeta,  Poisson  and Binomial   Distributions.    Computing, 12 (1974),\n223-246.  Adaptation of algorithm GS.\n\f\n\n\n\n\n\n                                Normal\n\nThis code was obtained from netlib.\n\nAhrens, J.H.  and  Dieter, U.    Extensions of   Forsythe's Method for\nRandom Sampling  from  the Normal Distribution.  Math. Comput., 27,124\n(Oct. 1973), 927 - 937.\n\n                               Binomial\n\nThis code was kindly sent me by Dr. Kachitvichyanukul.\n\nKachitvichyanukul,  V. and Schmeiser, B.   W.  Binomial Random Variate\nGeneration.  Communications of the ACM, 31, 2 (February, 1988) 216.\n\n\n                               Poisson\n\nThis code was obtained from netlib.\n\nAhrens,  J.H. and Dieter, U.   Computer Generation of Poisson Deviates\nFrom Modified  Normal Distributions.  ACM Trans.  Math. Software, 8, 2\n(June 1982),163-179\n\n                                 Beta\n\nThis code was written by us following the recipe in the following.\n\nR. C.  H.   Cheng Generating  Beta Variables  with  Nonintegral  Shape\nParameters. Communications of  the ACM,  21:317-322 (1978) (Algorithms\nBB and BC)\n\n                               Linpack\n\nRoutines SPOFA and SDOT are used to perform the Cholesky decomposition\nof  the covariance  matrix  in  SETGMN  (used  for  the  generation of\nmultivariate normal deviates).\n\nDongarra, J.  J., Moler,   C.  B., Bunch, J.   R. and  Stewart, G.  W.\nLinpack User's Guide.  SIAM Press, Philadelphia.  (1979)\n\f\n\n\n\n                              LEGALITIES\n\nCode that appeared  in an    ACM  publication  is subject  to    their\nalgorithms policy:\n\n     Submittal of  an  algorithm    for publication  in   one of   the  ACM\n     Transactions implies that unrestricted use  of the algorithm within  a\n     computer is permissible.   General permission  to copy and  distribute\n     the algorithm without fee is granted provided that the copies  are not\n     made  or   distributed for  direct   commercial  advantage.    The ACM\n     copyright notice and the title of the publication and its date appear,\n     and  notice is given that copying  is by permission of the Association\n     for Computing Machinery.  To copy otherwise, or to republish, requires\n     a fee and/or specific permission.\n\n     Krogh, F.  Algorithms  Policy.  ACM  Tran.   Math.  Softw.   13(1987),\n     183-186.\n\nWe place the Randlib code that we have written in the public domain.\n\n                                 NO WARRANTY\n\n     WE PROVIDE ABSOLUTELY  NO WARRANTY  OF ANY  KIND  EITHER  EXPRESSED OR\n     IMPLIED,  INCLUDING BUT   NOT LIMITED TO,  THE  IMPLIED  WARRANTIES OF\n     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK\n     AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS  WITH YOU.  SHOULD\n     THIS PROGRAM PROVE  DEFECTIVE, YOU ASSUME  THE COST  OF  ALL NECESSARY\n     SERVICING, REPAIR OR CORRECTION.\n\n     IN NO  EVENT  SHALL THE UNIVERSITY  OF TEXAS OR  ANY  OF ITS COMPONENT\n     INSTITUTIONS INCLUDING M. D.   ANDERSON HOSPITAL BE LIABLE  TO YOU FOR\n     DAMAGES, INCLUDING ANY  LOST PROFITS, LOST MONIES,   OR OTHER SPECIAL,\n     INCIDENTAL   OR  CONSEQUENTIAL DAMAGES   ARISING   OUT  OF  THE USE OR\n     INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA OR\n     ITS ANALYSIS BEING  RENDERED INACCURATE OR  LOSSES SUSTAINED  BY THIRD\n     PARTIES) THE PROGRAM.\n\n     (Above NO WARRANTY modified from the GNU NO WARRANTY statement.)\n\f\n\n\n                         WHAT'S NEW IN VERSION 1.1?\n\n\nRandom number generation  for  the Negative Binomial  and  Multinomial\ndistributions has been included.\n\nTwo errors in the code  which generates random  numbers from the Gamma\ndistribution were fixed.\n\n\n                         WHAT'S NEW IN VERSION 1.2?\n\nWe changed the name  of the package  from 'ranlib' to 'randlib'.  This\nwas done so  that we can determine who  archives it.   'ranlib' is the\nname of a Unix utility which produces many spurious hits on a web\nsearch engine.\n\n\nThe linpack routines are now housed in the /src directory.\n\nIn  several routines, some   variables were   given an  explicit  SAVE\nattribute  and  some  dummy  initial values   were changed to  prevent\npotential errors.\n'genbet.f' 'ignbin.f'   'ignpoi.f' 'phrtsd.f'   'sexpo.f'   'sgamma.f'\n'snorm.f'\n\nIn several  routines, argument checking was  implemented; the code now\nbreaks if inappropriate values are passed to it.\n'genbet.f' A and B must be >= 1.0E-37 instead of 0.0\n'genexp.f' AV must be >= 0.0\n'gengam.f' A and R both must be > 0.0\n'gennor.f' SD must be >= 0.0\n'ignbin.f' N must be >= 0, and 0.0 <= PP <= 1.0.\n'ignnbn.f' N must be > 0, 0.0 < P < 1.0 (previously allowed N = 0)\n'ignpoi.f' MU must be >= 0.0\n\nFor the Non-Central  Chi-Squared and Non-Central  F distributions, the\ncase DF = 1.0 (DFN = 1.0 for the F) is now allowed.\n'gennch.f' 'gennf.f'\n\nWherever possible,  the   user-accessible  code  now calls    the base\ngenerators   directly.   This means   improved performance  and  fewer\ndependencies, but the routines should work  exactly as before from the\nuser's point of view.\n'genchi.f' 'genf.f' 'gennch.f' 'gennf.f' 'ignnbn.f'\n\nMany minor modifications  have been  made which  should make  the code\nmore robust, without changing how the code is used.\n'genbet.f'   'gengam.f'  'ignpoi.f'  'ignuin.f'  'sgamma.f' 'tstmid.f'\n\nFinally, five distributions have  been added to the  mid-level tester,\nwhich test the Exponential, Gamma, Multinomial, Negative Binomial, and\nNormal distributions.\n'tstmid.f'\n\f\n\n\n\n                   WHAT'S NOT NEW IN VERSION 1.2 ?\n\nNo calling sequences have changed.\n\n\t\t      WHAT'S NEW IN VERSION 1.3?\n\nThe calling sequence of SETGMN has been changed!  We added an argument\n(INTEGER LDCOVM) representing the leading actual dimension of COVM, to\nallow the user to use this routine in  the case that COVM is contained\nin a larger array.  This change also makes the routine more compatible\nwith  LINPACK    routines.  See  the    following files  for  details:\n'setgmn.f' in the /src directory, and 'randlib.fdoc' and 'randlib.chs'\nin the /doc directory.\n\nBriefly, the declaration of SETGMN has been changed\nfrom:\n      SUBROUTINE setgmn(meanv,covm,p,parm)\nto:\n      SUBROUTINE setgmn(meanv,covm,ldcovm,p,parm)\n\nThe program 'tstgmn.f' (in the /test directory) was changed to reflect\nthe change in the calling sequence of SETGMN.\n\n'randlib.fdoc' and 'randlib.chs' in the /doc directory were changed to\nrelect the change in the calling sequence of SETGMN.\n\nMinor changes were made in two routines  ('sgamma.f' and 'sexpo.f') to\nfix unusual bugs.\n\nThe protection from overflow   in deviate generation in  two  routines\n('genf.f'  and 'gennf.f')   was changed to   prevent a  constant  from\nunderflowing at compile time.\n\n                   WHAT'S NOT NEW IN VERSION 1.3 ?\n\nNo calling sequences (other than SETGMN) have changed.\n\n\t\t\t     MANY THANKS\n\nThe authors would like to thank the many users  who have reported bugs\nand  suggested improvements; Randlib  would  not  be  the  same  today\nwithout them.  We heartily encourage others to join them.\n"
  },
  {
    "path": "liboctave/external/ranlib/advnst.f",
    "content": "      SUBROUTINE advnst(k)\nC**********************************************************************\nC\nC     SUBROUTINE ADVNST(K)\nC               ADV-a-N-ce ST-ate\nC\nC     Advances the state  of  the current  generator  by 2^K values  and\nC     resets the initial seed to that value.\nC\nC     This is  a  transcription from   Pascal to  Fortran    of  routine\nC     Advance_State from the paper\nC\nC     L'Ecuyer, P. and  Cote, S. \"Implementing  a  Random Number Package\nC     with  Splitting   Facilities.\"  ACM  Transactions  on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     K -> The generator is advanced by2^K values\nC                                   INTEGER K\nC\nC**********************************************************************\nC     .. Parameters ..\n      INTEGER*4 numg\n      PARAMETER (numg=32)\nC     ..\nC     .. Scalar Arguments ..\n      INTEGER*4 k\nC     ..\nC     .. Scalars in Common ..\n      INTEGER*4 a1,a1vw,a1w,a2,a2vw,a2w,m1,m2\nC     ..\nC     .. Arrays in Common ..\n      INTEGER*4 cg1(numg),cg2(numg),ig1(numg),ig2(numg),lg1(numg),\n     +        lg2(numg)\n      LOGICAL qanti(numg)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 g,i,ib1,ib2\nC     ..\nC     .. External Functions ..\n      INTEGER*4 mltmod\n      LOGICAL qrgnin\n      EXTERNAL mltmod,qrgnin\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL getcgn,setsd\nC     ..\nC     .. Common blocks ..\n      COMMON /globe/m1,m2,a1,a2,a1w,a2w,a1vw,a2vw,ig1,ig2,lg1,lg2,cg1,\n     +       cg2,qanti\nC     ..\nC     .. Save statement ..\n      SAVE /globe/\nC     ..\nC     .. Executable Statements ..\nC     Abort unless random number generator initialized\n      IF (qrgnin()) GO TO 10\n      WRITE (*,*) ' ADVNST called before random number generator ',\n     +  ' initialized -- abort!'\n      CALL XSTOPX\n     + (' ADVNST called before random number generator initialized')\n\n   10 CALL getcgn(g)\nC\n      ib1 = a1\n      ib2 = a2\n      DO 20,i = 1,k\n          ib1 = mltmod(ib1,ib1,m1)\n          ib2 = mltmod(ib2,ib2,m2)\n   20 CONTINUE\n      CALL setsd(mltmod(ib1,cg1(g),m1),mltmod(ib2,cg2(g),m2))\nC\nC     NOW, IB1 = A1**K AND IB2 = A2**K\nC\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/genbet.f",
    "content": "      REAL FUNCTION genbet(aa,bb)\nC**********************************************************************\nC\nC     REAL FUNCTION GENBET( A, B )\nC               GeNerate BETa random deviate\nC\nC\nC                              Function\nC\nC\nC     Returns a single random deviate from the beta distribution with\nC     parameters A and B.  The density of the beta is\nC               x^(a-1) * (1-x)^(b-1) / B(a,b) for 0 < x < 1\nC\nC\nC                              Arguments\nC\nC\nC     A --> First parameter of the beta distribution\nC                         REAL A\nC     JJV                 (A > 1.0E-37)\nC\nC     B --> Second parameter of the beta distribution\nC                         REAL B\nC     JJV                 (B > 1.0E-37)\nC\nC\nC                              Method\nC\nC\nC     R. C. H. Cheng\nC     Generating Beta Variates with Nonintegral Shape Parameters\nC     Communications of the ACM, 21:317-322  (1978)\nC     (Algorithms BB and BC)\nC\nC**********************************************************************\nC     .. Parameters ..\nC     Close to the largest number that can be exponentiated\n      REAL expmax\nC     JJV changed this - 89 was too high, and LOG(1.0E38) = 87.49823\n      PARAMETER (expmax=87.49823)\nC     Close to the largest representable single precision number\n      REAL infnty\n      PARAMETER (infnty=1.0E38)\nC     JJV added the parameter minlog\nC     Close to the smallest number of which a LOG can be taken.\n      REAL minlog\n      PARAMETER (minlog=1.0E-37)\nC     ..\nC     .. Scalar Arguments ..\n      REAL aa,bb\nC     ..\nC     .. Local Scalars ..\n      REAL a,alpha,b,beta,delta,gamma,k1,k2,olda,oldb,r,s,t,u1,u2,v,w,y,\n     +     z\n      LOGICAL qsame\nC     ..\nC     .. External Functions ..\n      REAL ranf\n      EXTERNAL ranf\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC exp,log,max,min,sqrt\nC     ..\nC     .. Save statement ..\nC     JJV added a,b\n      SAVE olda,oldb,alpha,beta,gamma,k1,k2,a,b\nC     ..\nC     .. Data statements ..\nC     JJV changed these to ridiculous values\n      DATA olda,oldb/-1.0E37,-1.0E37/\nC     ..\nC     .. Executable Statements ..\n      qsame = (olda.EQ.aa) .AND. (oldb.EQ.bb)\n      IF (qsame) GO TO 20\nC     JJV added small minimum for small log problem in calc of W\n      IF (.NOT. (aa.LT.minlog.OR.bb.LT.minlog)) GO TO 10\n      WRITE (*,*) ' AA or BB < ',minlog,' in GENBET - Abort!'\n      WRITE (*,*) ' AA: ',aa,' BB ',bb\n      CALL XSTOPX (' AA or BB too small in GENBET - Abort!')\n\n   10 olda = aa\n      oldb = bb\n   20 IF (.NOT. (min(aa,bb).GT.1.0)) GO TO 100\n\n\nC     Alborithm BB\n\nC\nC     Initialize\nC\n      IF (qsame) GO TO 30\n      a = min(aa,bb)\n      b = max(aa,bb)\n      alpha = a + b\n      beta = sqrt((alpha-2.0)/ (2.0*a*b-alpha))\n      gamma = a + 1.0/beta\n   30 CONTINUE\n   40 u1 = ranf()\nC\nC     Step 1\nC\n      u2 = ranf()\n      v = beta*log(u1/ (1.0-u1))\nC     JJV altered this\n      IF (v.GT.expmax) GO TO 55\nC     JJV added checker to see if a*exp(v) will overflow\nC     JJV 50 _was_ w = a*exp(v); also note here a > 1.0\n   50 w = exp(v)\n      IF (w.GT.infnty/a) GO TO 55\n      w = a*w\n      GO TO 60\n 55   w = infnty\n\n   60 z = u1**2*u2\n      r = gamma*v - 1.3862944\n      s = a + r - w\nC\nC     Step 2\nC\n      IF ((s+2.609438).GE. (5.0*z)) GO TO 70\nC\nC     Step 3\nC\n      t = log(z)\n      IF (s.GT.t) GO TO 70\nC\nC     Step 4\nC\nC     JJV added checker to see if log(alpha/(b+w)) will\nC     JJV overflow.  If so, we count the log as -INF, and\nC     JJV consequently evaluate conditional as true, i.e.\nC     JJV the algorithm rejects the trial and starts over\nC     JJV May not need this here since ALPHA > 2.0\n      IF (alpha/(b+w).LT.minlog) GO TO 40\n\n      IF ((r+alpha*log(alpha/ (b+w))).LT.t) GO TO 40\nC\nC     Step 5\nC\n   70 IF (.NOT. (aa.EQ.a)) GO TO 80\n      genbet = w/ (b+w)\n      GO TO 90\n\n   80 genbet = b/ (b+w)\n   90 GO TO 230\n\n\nC     Algorithm BC\n\nC\nC     Initialize\nC\n  100 IF (qsame) GO TO 110\n      a = max(aa,bb)\n      b = min(aa,bb)\n      alpha = a + b\n      beta = 1.0/b\n      delta = 1.0 + a - b\n      k1 = delta* (0.0138889+0.0416667*b)/ (a*beta-0.777778)\n      k2 = 0.25 + (0.5+0.25/delta)*b\n  110 CONTINUE\n  120 u1 = ranf()\nC\nC     Step 1\nC\n      u2 = ranf()\n      IF (u1.GE.0.5) GO TO 130\nC\nC     Step 2\nC\n      y = u1*u2\n      z = u1*y\n      IF ((0.25*u2+z-y).GE.k1) GO TO 120\n      GO TO 170\nC\nC     Step 3\nC\n  130 z = u1**2*u2\n      IF (.NOT. (z.LE.0.25)) GO TO 160\n      v = beta*log(u1/ (1.0-u1))\n\nC     JJV instead of checking v > expmax at top, I will check\nC     JJV if a < 1, then check the appropriate values\n\n      IF (a.GT.1.0) GO TO 135\nC     JJV A < 1 so it can help out if EXP(V) would overflow\n      IF (v.GT.expmax) GO TO 132\n      w = a*exp(v)\n      GO TO 200\n 132  w = v + log(a)\n      IF (w.GT.expmax) GO TO 140\n      w = exp(w)\n      GO TO 200\n\nC     JJV in this case A > 1\n 135  IF (v.GT.expmax) GO TO 140\n      w = exp(v)\n      IF (w.GT.infnty/a) GO TO 140\n      w = a*w\n      GO TO 200\n 140  w = infnty\n      GO TO 200\n\n  160 IF (z.GE.k2) GO TO 120\nC\nC     Step 4\nC\nC\nC     Step 5\nC\n  170 v = beta*log(u1/ (1.0-u1))\n\nC     JJV same kind of checking as above\n      IF (a.GT.1.0) GO TO 175\nC     JJV A < 1 so it can help out if EXP(V) would overflow\n      IF (v.GT.expmax) GO TO 172\n      w = a*exp(v)\n      GO TO 190\n 172  w = v + log(a)\n      IF (w.GT.expmax) GO TO 180\n      w = exp(w)\n      GO TO 190\n\nC     JJV in this case A > 1\n 175  IF (v.GT.expmax) GO TO 180\n      w = exp(v)\n      IF (w.GT.infnty/a) GO TO 180\n      w = a*w\n      GO TO 190\n\n  180 w = infnty\n\nC     JJV here we also check to see if log overlows; if so, we treat it\nC     JJV as -INF, which means condition is true, i.e. restart\n  190 IF (alpha/(b+w).LT.minlog) GO TO 120\n      IF ((alpha* (log(alpha/ (b+w))+v)-1.3862944).LT.log(z)) GO TO 120\nC\nC     Step 6\nC\n  200 IF (.NOT. (a.EQ.aa)) GO TO 210\n      genbet = w/ (b+w)\n      GO TO 220\n\n  210 genbet = b/ (b+w)\n  220 CONTINUE\n  230 RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/genchi.f",
    "content": "      REAL FUNCTION genchi(df)\nC**********************************************************************\nC\nC     REAL FUNCTION GENCHI( DF )\nC                Generate random value of CHIsquare variable\nC\nC\nC                              Function\nC\nC\nC     Generates random deviate from the distribution of a chisquare\nC     with DF degrees of freedom random variable.\nC\nC\nC                              Arguments\nC\nC\nC     DF --> Degrees of freedom of the chisquare\nC            (Must be positive)\nC                         REAL DF\nC\nC\nC                              Method\nC\nC\nC     Uses relation between chisquare and gamma.\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL df\nC     ..\nC     .. External Functions ..\nC      REAL gengam\nC      EXTERNAL gengam\n      REAL sgamma\n      EXTERNAL sgamma\nC     ..\nC     .. Executable Statements ..\n      IF (.NOT. (df.LE.0.0)) GO TO 10\n      WRITE (*,*) 'DF <= 0 in GENCHI - ABORT'\n      WRITE (*,*) 'Value of DF: ',df\n      CALL XSTOPX ('DF <= 0 in GENCHI - ABORT')\n\nC     JJV changed this to call sgamma directly\nC   10 genchi = 2.0*gengam(1.0,df/2.0)\n 10   genchi = 2.0*sgamma(df/2.0)\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/genexp.f",
    "content": "      REAL FUNCTION genexp(av)\n\nC**********************************************************************\nC\nC     REAL FUNCTION GENEXP( AV )\nC\nC                    GENerate EXPonential random deviate\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from an exponential\nC     distribution with mean AV.\nC\nC\nC                              Arguments\nC\nC\nC     AV --> The mean of the exponential distribution from which\nC            a random deviate is to be generated.\nC                              REAL AV\nC     JJV                      (AV >= 0)\nC\nC     GENEXP <-- The random deviate.\nC                              REAL GENEXP\nC\nC\nC                              Method\nC\nC\nC     Renames SEXPO from TOMS as slightly modified by BWB to use RANF\nC     instead of SUNIF.\nC\nC     For details see:\nC\nC               Ahrens, J.H. and Dieter, U.\nC               Computer Methods for Sampling From the\nC               Exponential and Normal Distributions.\nC               Comm. ACM, 15,10 (Oct. 1972), 873 - 882.\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL av\nC     ..\nC     .. External Functions ..\n      REAL sexpo\n      EXTERNAL sexpo\nC     ..\nC     .. Executable Statements ..\nC     JJV added check to ensure AV >= 0.0\n      IF (av.GE.0.0) GO TO 10\n      WRITE (*,*) 'AV < 0.0 in GENEXP - ABORT'\n      WRITE (*,*) 'Value of AV: ',av\n      CALL XSTOPX ('AV < 0.0 in GENEXP - ABORT')\n\n 10   genexp = sexpo()*av\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/genf.f",
    "content": "      REAL FUNCTION genf(dfn,dfd)\nC**********************************************************************\nC\nC     REAL FUNCTION GENF( DFN, DFD )\nC                GENerate random deviate from the F distribution\nC\nC\nC                              Function\nC\nC\nC     Generates a random deviate from the F (variance ratio)\nC     distribution with DFN degrees of freedom in the numerator\nC     and DFD degrees of freedom in the denominator.\nC\nC\nC                              Arguments\nC\nC\nC     DFN --> Numerator degrees of freedom\nC             (Must be positive)\nC                              REAL DFN\nC      DFD --> Denominator degrees of freedom\nC             (Must be positive)\nC                              REAL DFD\nC\nC\nC                              Method\nC\nC\nC     Directly generates ratio of chisquare variates\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL dfd,dfn\nC     ..\nC     .. Local Scalars ..\n      REAL xden,xnum\nC     ..\nC     JJV changed this code to call sgamma directly\nC     .. External Functions ..\nC      REAL genchi\nC      EXTERNAL genchi\n      REAL sgamma\n      EXTERNAL sgamma\nC     ..\nC     .. Executable Statements ..\n      IF (.NOT. (dfn.LE.0.0.OR.dfd.LE.0.0)) GO TO 10\n      WRITE (*,*) 'Degrees of freedom nonpositive in GENF - abort!'\n      WRITE (*,*) 'DFN value: ',dfn,'DFD value: ',dfd\n      CALL XSTOPX ('Degrees of freedom nonpositive in GENF - abort!')\n\n 10   xnum = 2.0*sgamma(dfn/2.0)/dfn\n\nC      GENF = ( GENCHI( DFN ) / DFN ) / ( GENCHI( DFD ) / DFD )\n      xden = 2.0*sgamma(dfd/2.0)/dfd\nC     JJV changed constant so that it will not underflow at compile time\nC     JJV while not slowing generator by using double precision or logs.\nC      IF (.NOT. (xden.LE. (1.0E-38*xnum))) GO TO 20\n      IF (.NOT. (xden.LE. (1.0E-37*xnum))) GO TO 20\n      WRITE (*,*) ' GENF - generated numbers would cause overflow'\n      WRITE (*,*) ' Numerator ',xnum,' Denominator ',xden\nC     JJV next 2 lines changed to maintain truncation of large deviates.\nC      WRITE (*,*) ' GENF returning 1.0E38'\nC      genf = 1.0E38\n      WRITE (*,*) ' GENF returning 1.0E37'\n      genf = 1.0E37\n      GO TO 30\n\n   20 genf = xnum/xden\n   30 RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/gengam.f",
    "content": "      REAL FUNCTION gengam(a,r)\nC**********************************************************************\nC\nC     REAL FUNCTION GENGAM( A, R )\nC           GENerates random deviates from GAMma distribution\nC\nC\nC                              Function\nC\nC\nC     Generates random deviates from the gamma distribution whose\nC     density is\nC          (A**R)/Gamma(R) * X**(R-1) * Exp(-A*X)\nC\nC\nC                              Arguments\nC\nC\nC     JJV added the argument ranges supported\nC     A --> Location parameter of Gamma distribution\nC                              REAL A ( A > 0 )\nC\nC     R --> Shape parameter of Gamma distribution\nC                              REAL R ( R > 0 )\nC\nC\nC                              Method\nC\nC\nC     Renames SGAMMA from TOMS as slightly modified by BWB to use RANF\nC     instead of SUNIF.\nC\nC     For details see:\nC               (Case R >= 1.0)\nC               Ahrens, J.H. and Dieter, U.\nC               Generating Gamma Variates by a\nC               Modified Rejection Technique.\nC               Comm. ACM, 25,1 (Jan. 1982), 47 - 54.\nC     Algorithm GD\nC\nC     JJV altered the following to reflect sgamma argument ranges\nC               (Case 0.0 < R < 1.0)\nC               Ahrens, J.H. and Dieter, U.\nC               Computer Methods for Sampling from Gamma,\nC               Beta, Poisson and Binomial Distributions.\nC               Computing, 12 (1974), 223-246/\nC     Adapted algorithm GS.\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL a,r\nC     ..\nC     .. External Functions ..\n      REAL sgamma\n      EXTERNAL sgamma\nC     ..\nC     .. Executable Statements ..\n\nC     JJV added argument value checker\n      IF ( a.GT.0.0 .AND. r.GT.0.0 ) GO TO 10\n      WRITE (*,*) 'In GENGAM - Either (1) Location param A <= 0.0 or'\n      WRITE (*,*) '(2) Shape param R <= 0.0 - ABORT!'\n      WRITE (*,*) 'A value: ',a,'R value: ',r\n      CALL XSTOPX\n     + ('Location or shape param out of range in GENGAM - ABORT!')\nC     JJV end addition\n\n 10   gengam = sgamma(r)/a\nC      gengam = gengam/a\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/genmn.f",
    "content": "      SUBROUTINE genmn(parm,x,work)\nC**********************************************************************\nC\nC     SUBROUTINE GENMN(PARM,X,WORK)\nC              GENerate Multivariate Normal random deviate\nC\nC\nC                              Arguments\nC\nC\nC     PARM --> Parameters needed to generate multivariate normal\nC               deviates (MEANV and Cholesky decomposition of\nC               COVM). Set by a previous call to SETGMN.\nC               1 : 1                - size of deviate, P\nC               2 : P + 1            - mean vector\nC               P+2 : P*(P+3)/2 + 1  - upper half of cholesky\nC                                       decomposition of cov matrix\nC                                             REAL PARM(*)\nC\nC     X    <-- Vector deviate generated.\nC                                             REAL X(P)\nC\nC     WORK <--> Scratch array\nC                                             REAL WORK(P)\nC\nC\nC                              Method\nC\nC\nC     1) Generate P independent standard normal deviates - Ei ~ N(0,1)\nC\nC     2) Using Cholesky decomposition find A s.t. trans(A)*A = COVM\nC\nC     3) trans(A)E + MEANV ~ N(MEANV,COVM)\nC\nC**********************************************************************\nC     .. Array Arguments ..\n      REAL parm(*),work(*),x(*)\nC     ..\nC     .. Local Scalars ..\n      REAL ae\n      INTEGER*4 i,icount,j,p\nC     ..\nC     .. External Functions ..\n      REAL snorm\n      EXTERNAL snorm\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC int\nC     ..\nC     .. Executable Statements ..\n      p = int(parm(1))\nC\nC     Generate P independent normal deviates - WORK ~ N(0,1)\nC\n      DO 10,i = 1,p\n          work(i) = snorm()\n   10 CONTINUE\n      DO 30,i = 1,p\nC\nC     PARM (P+2 : P*(P+3)/2 + 1) contains A, the Cholesky\nC      decomposition of the desired covariance matrix.\nC          trans(A)(1,1) = PARM(P+2)\nC          trans(A)(2,1) = PARM(P+3)\nC          trans(A)(2,2) = PARM(P+2+P)\nC          trans(A)(3,1) = PARM(P+4)\nC          trans(A)(3,2) = PARM(P+3+P)\nC          trans(A)(3,3) = PARM(P+2-1+2P)  ...\nC\nC     trans(A)*WORK + MEANV ~ N(MEANV,COVM)\nC\n          icount = 0\n          ae = 0.0\n          DO 20,j = 1,i\n              icount = icount + j - 1\n              ae = ae + parm(i+ (j-1)*p-icount+p+1)*work(j)\n   20     CONTINUE\n          x(i) = ae + parm(i+1)\n   30 CONTINUE\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/genmul.f",
    "content": "      SUBROUTINE genmul(n,p,ncat,ix)\nC**********************************************************************\nC\nC            SUBROUTINE GENMUL( N, P, NCAT, IX )\nC     GENerate an observation from the MULtinomial distribution\nC\nC\nC                              Arguments\nC\nC\nC     N --> Number of events that will be classified into one of\nC           the categories 1..NCAT\nC                         INTEGER N\nC\nC     P --> Vector of probabilities.  P(i) is the probability that\nC           an event will be classified into category i.  Thus, P(i)\nC           must be [0,1]. Only the first NCAT-1 P(i) must be defined\nC           since P(NCAT) is 1.0 minus the sum of the first\nC           NCAT-1 P(i).\nC                         REAL P(NCAT-1)\nC\nC     NCAT --> Number of categories.  Length of P and IX.\nC                         INTEGER NCAT\nC\nC     IX <-- Observation from multinomial distribution.  All IX(i)\nC            will be nonnegative and their sum will be N.\nC                         INTEGER IX(NCAT)\nC\nC\nC                              Method\nC\nC\nC     Algorithm from page 559 of\nC\nC     Devroye, Luc\nC\nC     Non-Uniform Random Variate Generation.  Springer-Verlag,\nC     New York, 1986.\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      INTEGER*4 n,ncat\nC     ..\nC     .. Array Arguments ..\n      REAL p(*)\n      INTEGER*4 ix(*)\nC     ..\nC     .. Local Scalars ..\n      REAL prob,ptot,sum\n      INTEGER*4 i,icat,ntot\nC     ..\nC     .. External Functions ..\n      INTEGER*4 ignbin\n      EXTERNAL ignbin\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC abs\nC     ..\nC     .. Executable Statements ..\n\nC     Check Arguments\n      IF (n.LT.0) CALL XSTOPX ('N < 0 in GENMUL')\n      IF (ncat.LE.1) CALL XSTOPX ('NCAT <= 1 in GENMUL')\n      ptot = 0.0\n      DO 10,i = 1,ncat - 1\n          IF (p(i).LT.0.0) CALL XSTOPX ('Some P(i) < 0 in GENMUL')\n          IF (p(i).GT.1.0) CALL XSTOPX ('Some P(i) > 1 in GENMUL')\n          ptot = ptot + p(i)\n   10 CONTINUE\n      IF (ptot.GT.0.99999) CALL XSTOPX ('Sum of P(i) > 1 in GENMUL')\n\nC     Initialize variables\n      ntot = n\n      sum = 1.0\n      DO 20,i = 1,ncat\n          ix(i) = 0\n   20 CONTINUE\n\nC     Generate the observation\n      DO 30,icat = 1,ncat - 1\n          prob = p(icat)/sum\n          ix(icat) = ignbin(ntot,prob)\n          ntot = ntot - ix(icat)\n          IF (ntot.LE.0) RETURN\n          sum = sum - p(icat)\n   30 CONTINUE\n      ix(ncat) = ntot\n\nC     Finished\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/gennch.f",
    "content": "      REAL FUNCTION gennch(df,xnonc)\nC**********************************************************************\nC\nC     REAL FUNCTION GENNCH( DF, XNONC )\nC           Generate random value of Noncentral CHIsquare variable\nC\nC\nC                              Function\nC\nC\n\nC     Generates random deviate  from the  distribution  of a  noncentral\nC     chisquare with DF degrees  of freedom and noncentrality  parameter\nC     XNONC.\nC\nC\nC                              Arguments\nC\nC\nC     DF --> Degrees of freedom of the chisquare\nC            (Must be >= 1.0)\nC                         REAL DF\nC\nC     XNONC --> Noncentrality parameter of the chisquare\nC               (Must be >= 0.0)\nC                         REAL XNONC\nC\nC\nC                              Method\nC\nC\nC     Uses fact that  noncentral chisquare  is  the  sum of a  chisquare\nC     deviate with DF-1  degrees of freedom plus the  square of a normal\nC     deviate with mean sqrt(XNONC) and standard deviation 1.\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL df,xnonc\nC     ..\nC     .. External Functions ..\nC     JJV changed these to call SGAMMA and SNORM directly\nC      REAL genchi,gennor\nC      EXTERNAL genchi,gennor\n      REAL sgamma,snorm\n      EXTERNAL sgamma,snorm\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC sqrt\nC     ..\nC     JJV changed abort to df < 1, and added case: df = 1\nC     .. Executable Statements ..\n      IF (.NOT. (df.LT.1.0.OR.xnonc.LT.0.0)) GO TO 10\n      WRITE (*,*) 'DF < 1 or XNONC < 0 in GENNCH - ABORT'\n      WRITE (*,*) 'Value of DF: ',df,' Value of XNONC',xnonc\n      CALL XSTOPX ('DF < 1 or XNONC < 0 in GENNCH - ABORT')\n\nC     JJV changed this to call SGAMMA and SNORM directly\nC      gennch = genchi(df-1.0) + gennor(sqrt(xnonc),1.0)**2\n\n 10   IF (df.GE.1.000001) GO TO 20\nC     JJV case DF = 1.0\n      gennch = (snorm() + sqrt(xnonc))**2\n      GO TO 30\n\nC     JJV case DF > 1.0\n 20   gennch = 2.0*sgamma((df-1.0)/2.0) + (snorm() + sqrt(xnonc))**2\n 30   RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/gennf.f",
    "content": "      REAL FUNCTION gennf(dfn,dfd,xnonc)\n\nC**********************************************************************\nC\nC     REAL FUNCTION GENNF( DFN, DFD, XNONC )\nC           GENerate random deviate from the Noncentral F distribution\nC\nC\nC                              Function\nC\nC\nC     Generates a random deviate from the  noncentral F (variance ratio)\nC     distribution with DFN degrees of freedom in the numerator, and DFD\nC     degrees of freedom in the denominator, and noncentrality parameter\nC     XNONC.\nC\nC\nC                              Arguments\nC\nC\nC     DFN --> Numerator degrees of freedom\nC             (Must be >= 1.0)\nC                              REAL DFN\nC      DFD --> Denominator degrees of freedom\nC             (Must be positive)\nC                              REAL DFD\nC\nC     XNONC --> Noncentrality parameter\nC               (Must be nonnegative)\nC                              REAL XNONC\nC\nC\nC                              Method\nC\nC\nC     Directly generates ratio of noncentral numerator chisquare variate\nC     to central denominator chisquare variate.\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL dfd,dfn,xnonc\nC     ..\nC     .. Local Scalars ..\n      REAL xden,xnum\n      LOGICAL qcond\nC     ..\nC     .. External Functions ..\nC     JJV changed the code to call SGAMMA and SNORM directly\nC      REAL genchi,gennch\nC      EXTERNAL genchi,gennch\n      REAL sgamma,snorm\n      EXTERNAL sgamma,snorm\nC     ..\nC     .. Executable Statements ..\nC     JJV changed the argument checker to allow DFN = 1.0\nC     JJV in the same way as GENNCH was changed.\n      qcond = dfn .LT. 1.0 .OR. dfd .LE. 0.0 .OR. xnonc .LT. 0.0\n      IF (.NOT. (qcond)) GO TO 10\n      WRITE (*,*) 'In GENNF - Either (1) Numerator DF < 1.0 or'\n      WRITE (*,*) '(2) Denominator DF <= 0.0 or '\n      WRITE (*,*) '(3) Noncentrality parameter < 0.0'\n      WRITE (*,*) 'DFN value: ',dfn,'DFD value: ',dfd,'XNONC value: ',\n     +  xnonc\n\n      CALL XSTOPX\n     + ('Degrees of freedom or noncent param out of range in GENNF')\n\nC      GENNF = ( GENNCH( DFN, XNONC ) / DFN ) / ( GENCHI( DFD ) / DFD )\nC     JJV changed this to call SGAMMA and SNORM directly\nC     xnum = gennch(dfn,xnonc)/dfn\n 10   IF (dfn.GE.1.000001) GO TO 20\nC     JJV case dfn = 1.0 - here I am treating dfn as exactly 1.0\n      xnum = (snorm() + sqrt(xnonc))**2\n      GO TO 30\n\nC     JJV case dfn > 1.0\n 20   xnum = (2.0*sgamma((dfn-1.0)/2.0) + (snorm()+sqrt(xnonc))**2)/dfn\n\nC     xden = genchi(dfd)/dfd\n 30   xden = 2.0*sgamma(dfd/2.0)/dfd\n\nC     JJV changed constant so that it will not underflow at compile time\nC     JJV while not slowing generator by using double precision or logs.\nC      IF (.NOT. (xden.LE. (1.0E-38*xnum))) GO TO 40\n      IF (.NOT. (xden.LE. (1.0E-37*xnum))) GO TO 40\n      WRITE (*,*) ' GENNF - generated numbers would cause overflow'\n      WRITE (*,*) ' Numerator ',xnum,' Denominator ',xden\nC     JJV next 2 lines changed to maintain truncation of large deviates.\nC      WRITE (*,*) ' GENNF returning 1.0E38'\nC      gennf = 1.0E38\n      WRITE (*,*) ' GENNF returning 1.0E37'\n      gennf = 1.0E37\n      GO TO 50\n\n   40 gennf = xnum/xden\n   50 RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/gennor.f",
    "content": "      REAL FUNCTION gennor(av,sd)\nC**********************************************************************\nC\nC     REAL FUNCTION GENNOR( AV, SD )\nC\nC         GENerate random deviate from a NORmal distribution\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from a normal distribution\nC     with mean, AV, and standard deviation, SD.\nC\nC\nC                              Arguments\nC\nC\nC     AV --> Mean of the normal distribution.\nC                              REAL AV\nC\nC     SD --> Standard deviation of the normal distribution.\nC                              REAL SD\nC     JJV                      (SD >= 0)\nC\nC     GENNOR <-- Generated normal deviate.\nC                              REAL GENNOR\nC\nC\nC                              Method\nC\nC\nC     Renames SNORM from TOMS as slightly modified by BWB to use RANF\nC     instead of SUNIF.\nC\nC     For details see:\nC               Ahrens, J.H. and Dieter, U.\nC               Extensions of Forsythe's Method for Random\nC               Sampling from the Normal Distribution.\nC               Math. Comput., 27,124 (Oct. 1973), 927 - 937.\nC\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL av,sd\nC     ..\nC     .. External Functions ..\n      REAL snorm\n      EXTERNAL snorm\nC     ..\nC     .. Executable Statements ..\nC     JJV added check to ensure SD >= 0.0\n      IF (sd.GE.0.0) GO TO 10\n      WRITE (*,*) 'SD < 0.0 in GENNOR - ABORT'\n      WRITE (*,*) 'Value of SD: ',sd\n      CALL XSTOPX ('SD < 0.0 in GENNOR - ABORT')\n\n 10   gennor = sd*snorm() + av\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/genprm.f",
    "content": "      SUBROUTINE genprm(iarray,larray)\nC**********************************************************************\nC\nC    SUBROUTINE GENPRM( IARRAY, LARRAY )\nC               GENerate random PeRMutation of iarray\nC\nC\nC                              Arguments\nC\nC\nC     IARRAY <--> On output IARRAY is a random permutation of its\nC                 value on input\nC                         INTEGER IARRAY( LARRAY )\nC\nC     LARRAY <--> Length of IARRAY\nC                         INTEGER LARRAY\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      INTEGER*4 larray\nC     ..\nC     .. Array Arguments ..\n      INTEGER*4 iarray(larray)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 i,itmp,iwhich\nC     ..\nC     .. External Functions ..\n      INTEGER*4 ignuin\n      EXTERNAL ignuin\nC     ..\nC     .. Executable Statements ..\n      DO 10,i = 1,larray\n          iwhich = ignuin(i,larray)\n          itmp = iarray(iwhich)\n          iarray(iwhich) = iarray(i)\n          iarray(i) = itmp\n   10 CONTINUE\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/genunf.f",
    "content": "      REAL FUNCTION genunf(low,high)\nC**********************************************************************\nC\nC     REAL FUNCTION GENUNF( LOW, HIGH )\nC\nC               GeNerate Uniform Real between LOW and HIGH\nC\nC\nC                              Function\nC\nC\nC     Generates a real uniformly distributed between LOW and HIGH.\nC\nC\nC                              Arguments\nC\nC\nC     LOW --> Low bound (exclusive) on real value to be generated\nC                         REAL LOW\nC\nC     HIGH --> High bound (exclusive) on real value to be generated\nC                         REAL HIGH\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL high,low\nC     ..\nC     .. External Functions ..\n      REAL ranf\n      EXTERNAL ranf\nC     ..\nC     .. Executable Statements ..\n      IF (.NOT. (low.GT.high)) GO TO 10\n      WRITE (*,*) 'LOW > HIGH in GENUNF: LOW ',low,' HIGH: ',high\n      WRITE (*,*) 'Abort'\n      CALL XSTOPX ('LOW > High in GENUNF - Abort')\n\n   10 genunf = low + (high-low)*ranf()\n\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/getcgn.f",
    "content": "      SUBROUTINE getcgn(g)\n      INTEGER*4 g\nC**********************************************************************\nC\nC      SUBROUTINE GETCGN(G)\nC                         Get GeNerator\nC\nC     Returns in G the number of the current random number generator\nC\nC\nC                              Arguments\nC\nC\nC     G <-- Number of the current random number generator (1..32)\nC                    INTEGER G\nC\nC**********************************************************************\nC\n      INTEGER*4 curntg,numg\n      SAVE curntg\n      PARAMETER (numg=32)\n      DATA curntg/1/\nC\n      g = curntg\n      RETURN\n\n      ENTRY setcgn(g)\nC**********************************************************************\nC\nC     SUBROUTINE SETCGN( G )\nC                      Set GeNerator\nC\nC     Sets  the  current  generator to G.    All references to a generat\nC     are to the current generator.\nC\nC\nC                              Arguments\nC\nC\nC     G --> Number of the current random number generator (1..32)\nC                    INTEGER G\nC\nC**********************************************************************\nC\nC     Abort if generator number out of range\nC\n      IF (.NOT. (g.LT.0.OR.g.GT.numg)) GO TO 10\n      WRITE (*,*) ' Generator number out of range in SETCGN:',\n     +  ' Legal range is 1 to ',numg,' -- ABORT!'\n      CALL XSTOPX (' Generator number out of range in SETCGN')\n\n   10 curntg = g\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/getsd.f",
    "content": "      SUBROUTINE getsd(iseed1,iseed2)\nC**********************************************************************\nC\nC     SUBROUTINE GETSD(G,ISEED1,ISEED2)\nC               GET SeeD\nC\nC     Returns the value of two integer seeds of the current generator\nC\nC     This  is   a  transcription from  Pascal   to  Fortran  of routine\nC     Get_State from the paper\nC\nC     L'Ecuyer, P. and  Cote,  S. \"Implementing a Random Number  Package\nC     with   Splitting Facilities.\"  ACM  Transactions   on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC\nC     ISEED1 <- First integer seed of generator G\nC                                   INTEGER ISEED1\nC\nC     ISEED2 <- Second integer seed of generator G\nC                                   INTEGER ISEED1\nC\nC**********************************************************************\nC     .. Parameters ..\n      INTEGER*4 numg\n      PARAMETER (numg=32)\nC     ..\nC     .. Scalar Arguments ..\n      INTEGER*4 iseed1,iseed2\nC     ..\nC     .. Scalars in Common ..\n      INTEGER*4 a1,a1vw,a1w,a2,a2vw,a2w,m1,m2\nC     ..\nC     .. Arrays in Common ..\n      INTEGER*4 cg1(numg),cg2(numg),ig1(numg),ig2(numg),lg1(numg),\n     +        lg2(numg)\n      LOGICAL qanti(numg)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 g\nC     ..\nC     .. External Functions ..\n      LOGICAL qrgnin\n      EXTERNAL qrgnin\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL getcgn\nC     ..\nC     .. Common blocks ..\n      COMMON /globe/m1,m2,a1,a2,a1w,a2w,a1vw,a2vw,ig1,ig2,lg1,lg2,cg1,\n     +       cg2,qanti\nC     ..\nC     .. Save statement ..\n      SAVE /globe/\nC     ..\nC     .. Executable Statements ..\nC     Abort unless random number generator initialized\n      IF (qrgnin()) GO TO 10\n      WRITE (*,*) ' GETSD called before random number generator ',\n     +  ' initialized -- abort!'\n      CALL XSTOPX\n     + (' GETSD called before random number generator initialized')\n\n   10 CALL getcgn(g)\n      iseed1 = cg1(g)\n      iseed2 = cg2(g)\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/ignbin.f",
    "content": "      INTEGER*4 FUNCTION ignbin(n,pp)\nC**********************************************************************\nC\nC     INTEGER*4 FUNCTION IGNBIN( N, PP )\nC\nC                    GENerate BINomial random deviate\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from a binomial\nC     distribution whose number of trials is N and whose\nC     probability of an event in each trial is P.\nC\nC\nC                              Arguments\nC\nC\nC     N  --> The number of trials in the binomial distribution\nC            from which a random deviate is to be generated.\nC                              INTEGER N\nC     JJV                      (N >= 0)\nC\nC     PP --> The probability of an event in each trial of the\nC            binomial distribution from which a random deviate\nC            is to be generated.\nC                              REAL PP\nC     JJV                      (0.0 <= pp <= 1.0)\nC\nC     IGNBIN <-- A random deviate yielding the number of events\nC                from N independent trials, each of which has\nC                a probability of event P.\nC                              INTEGER IGNBIN\nC\nC\nC                              Note\nC\nC\nC     Uses RANF so the value of the seeds, ISEED1 and ISEED2 must be set\nC     by a call similar to the following\nC          DUM = RANSET( ISEED1, ISEED2 )\nC\nC\nC                              Method\nC\nC\nC     This is algorithm BTPE from:\nC\nC         Kachitvichyanukul, V. and Schmeiser, B. W.\nC\nC         Binomial Random Variate Generation.\nC         Communications of the ACM, 31, 2\nC         (February, 1988) 216.\nC\nC**********************************************************************\nC     SUBROUTINE BTPEC(N,PP,ISEED,JX)\nC\nC     BINOMIAL RANDOM VARIATE GENERATOR\nC     MEAN .LT. 30 -- INVERSE CDF\nC       MEAN .GE. 30 -- ALGORITHM BTPE:  ACCEPTANCE-REJECTION VIA\nC       FOUR REGION COMPOSITION.  THE FOUR REGIONS ARE A TRIANGLE\nC       (SYMMETRIC IN THE CENTER), A PAIR OF PARALLELOGRAMS (ABOVE\nC       THE TRIANGLE), AND EXPONENTIAL LEFT AND RIGHT TAILS.\nC\nC     BTPE REFERS TO BINOMIAL-TRIANGLE-PARALLELOGRAM-EXPONENTIAL.\nC     BTPEC REFERS TO BTPE AND \"COMBINED.\"  THUS BTPE IS THE\nC       RESEARCH AND BTPEC IS THE IMPLEMENTATION OF A COMPLETE\nC       USABLE ALGORITHM.\nC     REFERENCE:  VORATAS KACHITVICHYANUKUL AND BRUCE SCHMEISER,\nC       \"BINOMIAL RANDOM VARIATE GENERATION,\"\nC       COMMUNICATIONS OF THE ACM, FORTHCOMING\nC     WRITTEN:  SEPTEMBER 1980.\nC       LAST REVISED:  MAY 1985, JULY 1987\nC     REQUIRED SUBPROGRAM:  RAND() -- A UNIFORM (0,1) RANDOM NUMBER\nC                           GENERATOR\nC     ARGUMENTS\nC\nC       N : NUMBER OF BERNOULLI TRIALS            (INPUT)\nC       PP : PROBABILITY OF SUCCESS IN EACH TRIAL (INPUT)\nC       ISEED:  RANDOM NUMBER SEED                (INPUT AND OUTPUT)\nC       JX:  RANDOMLY GENERATED OBSERVATION       (OUTPUT)\nC\nC     VARIABLES\nC       PSAVE: VALUE OF PP FROM THE LAST CALL TO BTPEC\nC       NSAVE: VALUE OF N FROM THE LAST CALL TO BTPEC\nC       XNP:  VALUE OF THE MEAN FROM THE LAST CALL TO BTPEC\nC\nC       P: PROBABILITY USED IN THE GENERATION PHASE OF BTPEC\nC       FFM: TEMPORARY VARIABLE EQUAL TO XNP + P\nC       M:  INTEGER VALUE OF THE CURRENT MODE\nC       FM:  FLOATING POINT VALUE OF THE CURRENT MODE\nC       XNPQ: TEMPORARY VARIABLE USED IN SETUP AND SQUEEZING STEPS\nC       P1:  AREA OF THE TRIANGLE\nC       C:  HEIGHT OF THE PARALLELOGRAMS\nC       XM:  CENTER OF THE TRIANGLE\nC       XL:  LEFT END OF THE TRIANGLE\nC       XR:  RIGHT END OF THE TRIANGLE\nC       AL:  TEMPORARY VARIABLE\nC       XLL:  RATE FOR THE LEFT EXPONENTIAL TAIL\nC       XLR:  RATE FOR THE RIGHT EXPONENTIAL TAIL\nC       P2:  AREA OF THE PARALLELOGRAMS\nC       P3:  AREA OF THE LEFT EXPONENTIAL TAIL\nC       P4:  AREA OF THE RIGHT EXPONENTIAL TAIL\nC       U:  A U(0,P4) RANDOM VARIATE USED FIRST TO SELECT ONE OF THE\nC           FOUR REGIONS AND THEN CONDITIONALLY TO GENERATE A VALUE\nC           FROM THE REGION\nC       V:  A U(0,1) RANDOM NUMBER USED TO GENERATE THE RANDOM VALUE\nC           (REGION 1) OR TRANSFORMED INTO THE VARIATE TO ACCEPT OR\nC           REJECT THE CANDIDATE VALUE\nC       IX:  INTEGER CANDIDATE VALUE\nC       X:  PRELIMINARY CONTINUOUS CANDIDATE VALUE IN REGION 2 LOGIC\nC           AND A FLOATING POINT IX IN THE ACCEPT/REJECT LOGIC\nC       K:  ABSOLUTE VALUE OF (IX-M)\nC       F:  THE HEIGHT OF THE SCALED DENSITY FUNCTION USED IN THE\nC           ACCEPT/REJECT DECISION WHEN BOTH M AND IX ARE SMALL\nC           ALSO USED IN THE INVERSE TRANSFORMATION\nC       R: THE RATIO P/Q\nC       G: CONSTANT USED IN CALCULATION OF PROBABILITY\nC       MP:  MODE PLUS ONE, THE LOWER INDEX FOR EXPLICIT CALCULATION\nC            OF F WHEN IX IS GREATER THAN M\nC       IX1:  CANDIDATE VALUE PLUS ONE, THE LOWER INDEX FOR EXPLICIT\nC             CALCULATION OF F WHEN IX IS LESS THAN M\nC       I:  INDEX FOR EXPLICIT CALCULATION OF F FOR BTPE\nC       AMAXP: MAXIMUM ERROR OF THE LOGARITHM OF NORMAL BOUND\nC       YNORM: LOGARITHM OF NORMAL BOUND\nC       ALV:  NATURAL LOGARITHM OF THE ACCEPT/REJECT VARIATE V\nC\nC       X1,F1,Z,W,Z2,X2,F2, AND W2 ARE TEMPORARY VARIABLES TO BE\nC       USED IN THE FINAL ACCEPT/REJECT TEST\nC\nC       QN: PROBABILITY OF NO SUCCESS IN N TRIALS\nC\nC     REMARK\nC       IX AND JX COULD LOGICALLY BE THE SAME VARIABLE, WHICH WOULD\nC       SAVE A MEMORY POSITION AND A LINE OF CODE.  HOWEVER, SOME\nC       COMPILERS (E.G.,CDC MNF) OPTIMIZE BETTER WHEN THE ARGUMENTS\nC       ARE NOT INVOLVED.\nC\nC     ISEED NEEDS TO BE DOUBLE PRECISION IF THE IMSL ROUTINE\nC     GGUBFS IS USED TO GENERATE UNIFORM RANDOM NUMBER, OTHERWISE\nC     TYPE OF ISEED SHOULD BE DICTATED BY THE UNIFORM GENERATOR\nC\nC**********************************************************************\n\nC\nC\nC\nC*****DETERMINE APPROPRIATE ALGORITHM AND WHETHER SETUP IS NECESSARY\nC\nC     ..\nC     .. Scalar Arguments ..\n      REAL pp\n      INTEGER*4 n\nC     ..\nC     .. Local Scalars ..\n      REAL al,alv,amaxp,c,f,f1,f2,ffm,fm,g,p,p1,p2,p3,p4,psave,q,qn,r,u,\n     +     v,w,w2,x,x1,x2,xl,xll,xlr,xm,xnp,xnpq,xr,ynorm,z,z2\n      INTEGER*4 i,ix,ix1,k,m,mp,nsave\nC     ..\nC     .. External Functions ..\n      REAL ranf\n      EXTERNAL ranf\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC abs,alog,amin1,iabs,int,sqrt\nC     JJV ..\nC     JJV .. Save statement ..\n      SAVE p,q,m,fm,xnp,xnpq,p1,xm,xl,xr,c,xll,xlr,p2,p3,p4,qn,r,g,\n     +     psave,nsave\nC     JJV I am including the variables in data statements\nC     ..\nC     .. Data statements ..\nC     JJV made these ridiculous starting values - the hope is that\nC     JJV no one will call this the first time with them as args\n      DATA psave,nsave/-1.0E37,-214748365/\nC     ..\nC     .. Executable Statements ..\n      IF (pp.NE.psave) GO TO 10\n      IF (n.NE.nsave) GO TO 20\n      IF (xnp-30.0.LT.0.0) GO TO 150\n      GO TO 30\nC\nC*****SETUP, PERFORM ONLY WHEN PARAMETERS CHANGE\nC\n\nC     JJV added the argument checker - involved only renaming 10\nC     JJV and 20 to the checkers and adding checkers\nC     JJV Only remaining problem - if called initially with the\nC     JJV initial values of psave and nsave, it will hang\n 10   IF (pp.LT.0.0) CALL XSTOPX ('PP < 0.0 in IGNBIN - ABORT!')\n      IF (pp.GT.1.0) CALL XSTOPX ('PP > 1.0 in IGNBIN - ABORT!')\n      psave = pp\n      p = amin1(psave,1.-psave)\n      q = 1. - p\n 20   IF (n.LT.0) CALL XSTOPX ('N < 0 in IGNBIN - ABORT!')\n      xnp = n*p\n      nsave = n\n      IF (xnp.LT.30.) GO TO 140\n      ffm = xnp + p\n      m = ffm\n      fm = m\n      xnpq = xnp*q\n      p1 = int(2.195*sqrt(xnpq)-4.6*q) + 0.5\n      xm = fm + 0.5\n      xl = xm - p1\n      xr = xm + p1\n      c = 0.134 + 20.5/ (15.3+fm)\n      al = (ffm-xl)/ (ffm-xl*p)\n      xll = al* (1.+.5*al)\n      al = (xr-ffm)/ (xr*q)\n      xlr = al* (1.+.5*al)\n      p2 = p1* (1.+c+c)\n      p3 = p2 + c/xll\n      p4 = p3 + c/xlr\nC      WRITE(6,100) N,P,P1,P2,P3,P4,XL,XR,XM,FM\nC  100 FORMAT(I15,4F18.7/5F18.7)\nC\nC*****GENERATE VARIATE\nC\n   30 u = ranf()*p4\n      v = ranf()\nC\nC     TRIANGULAR REGION\nC\n      IF (u.GT.p1) GO TO 40\n      ix = xm - p1*v + u\n      GO TO 170\nC\nC     PARALLELOGRAM REGION\nC\n   40 IF (u.GT.p2) GO TO 50\n      x = xl + (u-p1)/c\n      v = v*c + 1. - abs(xm-x)/p1\n      IF (v.GT.1. .OR. v.LE.0.) GO TO 30\n      ix = x\n      GO TO 70\nC\nC     LEFT TAIL\nC\n   50 IF (u.GT.p3) GO TO 60\n      ix = xl + alog(v)/xll\n      IF (ix.LT.0) GO TO 30\n      v = v* (u-p2)*xll\n      GO TO 70\nC\nC     RIGHT TAIL\nC\n   60 ix = xr - alog(v)/xlr\n      IF (ix.GT.n) GO TO 30\n      v = v* (u-p3)*xlr\nC\nC*****DETERMINE APPROPRIATE WAY TO PERFORM ACCEPT/REJECT TEST\nC\n   70 k = iabs(ix-m)\n      IF (k.GT.20 .AND. k.LT.xnpq/2-1) GO TO 130\nC\nC     EXPLICIT EVALUATION\nC\n      f = 1.0\n      r = p/q\n      g = (n+1)*r\n      IF (m-ix.LT.0) GO TO 80\n      IF (m-ix.EQ.0) GO TO 120\n      GO TO 100\n   80 mp = m + 1\n      DO 90 i = mp,ix\n          f = f* (g/i-r)\n   90 CONTINUE\n      GO TO 120\n\n  100 ix1 = ix + 1\n      DO 110 i = ix1,m\n          f = f/ (g/i-r)\n  110 CONTINUE\n  120 IF (v-f.LE.0) GO TO 170\n      GO TO 30\nC\nC     SQUEEZING USING UPPER AND LOWER BOUNDS ON ALOG(F(X))\nC\n  130 amaxp = (k/xnpq)* ((k* (k/3.+.625)+.1666666666666)/xnpq+.5)\n      ynorm = -k*k/ (2.*xnpq)\n      alv = alog(v)\n      IF (alv.LT.ynorm-amaxp) GO TO 170\n      IF (alv.GT.ynorm+amaxp) GO TO 30\nC\nC     STIRLING'S FORMULA TO MACHINE ACCURACY FOR\nC     THE FINAL ACCEPTANCE/REJECTION TEST\nC\n      x1 = ix + 1\n      f1 = fm + 1.\n      z = n + 1 - fm\n      w = n - ix + 1.\n      z2 = z*z\n      x2 = x1*x1\n      f2 = f1*f1\n      w2 = w*w\n      IF (alv- (xm*alog(f1/x1)+ (n-m+.5)*alog(z/w)+ (ix-\n     +    m)*alog(w*p/ (x1*q))+ (13860.- (462.- (132.- (99.-\n     +    140./f2)/f2)/f2)/f2)/f1/166320.+ (13860.- (462.- (132.- (99.-\n     +    140./z2)/z2)/z2)/z2)/z/166320.+ (13860.- (462.- (132.- (99.-\n     +    140./x2)/x2)/x2)/x2)/x1/166320.+ (13860.- (462.- (132.- (99.-\n     +    140./w2)/w2)/w2)/w2)/w/166320.) .LE. 0.) GO TO 170\n      GO TO 30\nC\nC     INVERSE CDF LOGIC FOR MEAN LESS THAN 30\nC\n  140 qn = q**n\n      r = p/q\n      g = r* (n+1)\n  150 ix = 0\n      f = qn\n      u = ranf()\n  160 IF (u.LT.f) GO TO 170\n      IF (ix.GT.110) GO TO 150\n      u = u - f\n      ix = ix + 1\n      f = f* (g/ix-r)\n      GO TO 160\n\n  170 IF (psave.GT.0.5) ix = n - ix\n      ignbin = ix\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/ignlgi.f",
    "content": "      INTEGER*4 FUNCTION ignlgi()\nC**********************************************************************\nC\nC     INTEGER*4 FUNCTION IGNLGI()\nC               GeNerate LarGe Integer\nC\nC     Returns a random integer following a uniform distribution over\nC     (1, 2147483562) using the current generator.\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Random from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC**********************************************************************\nC     .. Parameters ..\n      INTEGER*4 numg\n      PARAMETER (numg=32)\nC     ..\nC     .. Scalars in Common ..\n      INTEGER*4 a1,a1vw,a1w,a2,a2vw,a2w,m1,m2\nC     ..\nC     .. Arrays in Common ..\n      INTEGER*4 cg1(numg),cg2(numg),ig1(numg),ig2(numg),lg1(numg),\n     +        lg2(numg)\n      LOGICAL qanti(numg)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 curntg,k,s1,s2,z\n      LOGICAL qqssd\nC     ..\nC     .. External Functions ..\n      LOGICAL qrgnin\n      EXTERNAL qrgnin\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL getcgn,inrgcm,rgnqsd,setall\nC     ..\nC     .. Common blocks ..\n      COMMON /globe/m1,m2,a1,a2,a1w,a2w,a1vw,a2vw,ig1,ig2,lg1,lg2,cg1,\n     +       cg2,qanti\nC     ..\nC     .. Save statement ..\n      SAVE /globe/\nC     ..\nC     .. Executable Statements ..\nC\nC     IF THE RANDOM NUMBER PACKAGE HAS NOT BEEN INITIALIZED YET, DO SO.\nC     IT CAN BE INITIALIZED IN ONE OF TWO WAYS : 1) THE FIRST CALL TO\nC     THIS ROUTINE  2) A CALL TO SETALL.\nC\n      IF (.NOT. (qrgnin())) CALL inrgcm()\n      CALL rgnqsd(qqssd)\n      IF (.NOT. (qqssd)) CALL setall(1234567890,123456789)\nC\nC     Get Current Generator\nC\n      CALL getcgn(curntg)\n      s1 = cg1(curntg)\n      s2 = cg2(curntg)\n      k = s1/53668\n      s1 = a1* (s1-k*53668) - k*12211\n      IF (s1.LT.0) s1 = s1 + m1\n      k = s2/52774\n      s2 = a2* (s2-k*52774) - k*3791\n      IF (s2.LT.0) s2 = s2 + m2\n      cg1(curntg) = s1\n      cg2(curntg) = s2\n      z = s1 - s2\n      IF (z.LT.1) z = z + m1 - 1\n      IF (qanti(curntg)) z = m1 - z\n      ignlgi = z\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/ignnbn.f",
    "content": "      INTEGER*4 FUNCTION ignnbn(n,p)\nC**********************************************************************\nC\nC     INTEGER*4 FUNCTION IGNNBN( N, P )\nC\nC                GENerate Negative BiNomial random deviate\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from a negative binomial\nC     distribution.\nC\nC\nC                              Arguments\nC\nC\nC     N  --> Required number of events.\nC                              INTEGER N\nC     JJV                      (N > 0)\nC\nC     P  --> The probability of an event during a Bernoulli trial.\nC                              REAL P\nC     JJV                      (0.0 < P < 1.0)\nC\nC\nC\nC                              Method\nC\nC\nC     Algorithm from page 480 of\nC\nC     Devroye, Luc\nC\nC     Non-Uniform Random Variate Generation.  Springer-Verlag,\nC     New York, 1986.\nC\nC**********************************************************************\nC     ..\nC     .. Scalar Arguments ..\n      REAL p\n      INTEGER*4 n\nC     ..\nC     .. Local Scalars ..\n      REAL y,a,r\nC     ..\nC     .. External Functions ..\nC     JJV changed to call SGAMMA directly\nC     REAL gengam\n      REAL sgamma\n      INTEGER*4 ignpoi\nC      EXTERNAL gengam,ignpoi\n      EXTERNAL sgamma,ignpoi\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC real\nC     ..\nC     .. Executable Statements ..\nC     Check Arguments\nC     JJV changed argumnet checker to abort if N <= 0\n      IF (n.LE.0) CALL XSTOPX ('N <= 0 in IGNNBN')\n      IF (p.LE.0.0) CALL XSTOPX ('P <= 0.0 in IGNNBN')\n      IF (p.GE.1.0) CALL XSTOPX ('P >= 1.0 in IGNNBN')\n\nC     Generate Y, a random gamma (n,(1-p)/p) variable\nC     JJV Note: the above parametrization is consistent with Devroye,\nC     JJV       but gamma (p/(1-p),n) is the equivalent in our code\n 10   r = real(n)\n      a = p/ (1.0-p)\nC      y = gengam(a,r)\n      y = sgamma(r)/a\n\nC     Generate a random Poisson(y) variable\n      ignnbn = ignpoi(y)\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/ignpoi.f",
    "content": "      INTEGER*4 FUNCTION ignpoi(mu)\nC**********************************************************************\nC\nC     INTEGER*4 FUNCTION IGNPOI( MU )\nC\nC                    GENerate POIsson random deviate\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from a Poisson\nC     distribution with mean MU.\nC\nC\nC                              Arguments\nC\nC\nC     MU --> The mean of the Poisson distribution from which\nC            a random deviate is to be generated.\nC                              REAL MU\nC     JJV                    (MU >= 0.0)\nC\nC     IGNPOI <-- The random deviate.\nC                              INTEGER IGNPOI (non-negative)\nC\nC\nC                              Method\nC\nC\nC     Renames KPOIS from TOMS as slightly modified by BWB to use RANF\nC     instead of SUNIF.\nC\nC     For details see:\nC\nC               Ahrens, J.H. and Dieter, U.\nC               Computer Generation of Poisson Deviates\nC               From Modified Normal Distributions.\nC               ACM Trans. Math. Software, 8, 2\nC               (June 1982),163-179\nC\nC**********************************************************************\nC**********************************************************************C\nC**********************************************************************C\nC                                                                      C\nC                                                                      C\nC     P O I S S O N  DISTRIBUTION                                      C\nC                                                                      C\nC                                                                      C\nC**********************************************************************C\nC**********************************************************************C\nC                                                                      C\nC     FOR DETAILS SEE:                                                 C\nC                                                                      C\nC               AHRENS, J.H. AND DIETER, U.                            C\nC               COMPUTER GENERATION OF POISSON DEVIATES                C\nC               FROM MODIFIED NORMAL DISTRIBUTIONS.                    C\nC               ACM TRANS. MATH. SOFTWARE, 8,2 (JUNE 1982), 163 - 179. C\nC                                                                      C\nC     (SLIGHTLY MODIFIED VERSION OF THE PROGRAM IN THE ABOVE ARTICLE)  C\nC                                                                      C\nC**********************************************************************C\nC\nC      INTEGER*4 FUNCTION IGNPOI(IR,MU)\nC\nC     INPUT:  IR=CURRENT STATE OF BASIC RANDOM NUMBER GENERATOR\nC             MU=MEAN MU OF THE POISSON DISTRIBUTION\nC     OUTPUT: IGNPOI=SAMPLE FROM THE POISSON-(MU)-DISTRIBUTION\nC\nC\nC\nC     MUPREV=PREVIOUS MU, MUOLD=MU AT LAST EXECUTION OF STEP P OR CASE B\nC     TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT\nC     COEFFICIENTS A(K) - FOR PX = FK*V*V*SUM(A(K)*V**K)-DEL\nC\nC\nC\nC     SEPARATION OF CASES A AND B\nC\nC     .. Scalar Arguments ..\n      REAL mu\nC     ..\nC     .. Local Scalars ..\n      REAL a0,a1,a2,a3,a4,a5,a6,a7,b1,b2,c,c0,c1,c2,c3,d,del,difmuk,e,\n     +     fk,fx,fy,g,muold,muprev,omega,p,p0,px,py,q,s,t,u,v,x,xx\nC     JJV I added a variable 'll' here - it is the 'l' for CASE A\n      INTEGER*4 j,k,kflag,l,ll,m\nC     ..\nC     .. Local Arrays ..\n      REAL fact(10),pp(35)\nC     ..\nC     .. External Functions ..\n      REAL ranf,sexpo,snorm\n      EXTERNAL ranf,sexpo,snorm\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC abs,alog,exp,float,ifix,max0,min0,sign,sqrt\nC     ..\nC     JJV added this for case: mu unchanged\nC     .. Save statement ..\n      SAVE s, d, l, ll, omega, c3, c2, c1, c0, c, m, p, q, p0,\n     +     a0, a1, a2, a3, a4, a5, a6, a7, fact, pp, muprev, muold\nC     ..\nC     JJV end addition - I am including vars in Data statements\nC     .. Data statements ..\nC     JJV changed initial values of MUPREV and MUOLD to -1.0E37\nC     JJV if no one calls IGNPOI with MU = -1.0E37 the first time,\nC     JJV the code shouldn't break\n      DATA muprev,muold/-1.0E37,-1.0E37/\n      DATA a0,a1,a2,a3,a4,a5,a6,a7/-.5,.3333333,-.2500068,.2000118,\n     +     -.1661269,.1421878,-.1384794,.1250060/\n      DATA fact/1.,1.,2.,6.,24.,120.,720.,5040.,40320.,362880./\n      DATA pp/35*0.0/\nC     ..\nC     .. Executable Statements ..\n\n      IF (mu.EQ.muprev) GO TO 10\n      IF (mu.LT.10.0) GO TO 120\nC\nC     C A S E  A. (RECALCULATION OF S,D,LL IF MU HAS CHANGED)\nC\nC     JJV This is the case where I changed 'l' to 'll'\nC     JJV Here 'll' is set once and used in a comparison once\n\n      muprev = mu\n      s = sqrt(mu)\n      d = 6.0*mu*mu\nC\nC             THE POISSON PROBABILITIES PK EXCEED THE DISCRETE NORMAL\nC             PROBABILITIES FK WHENEVER K >= M(MU). LL=IFIX(MU-1.1484)\nC             IS AN UPPER BOUND TO M(MU) FOR ALL MU >= 10 .\nC\n      ll = ifix(mu-1.1484)\nC\nC     STEP N. NORMAL SAMPLE - SNORM(IR) FOR STANDARD NORMAL DEVIATE\nC\n   10 g = mu + s*snorm()\n      IF (g.LT.0.0) GO TO 20\n      ignpoi = ifix(g)\nC\nC     STEP I. IMMEDIATE ACCEPTANCE IF IGNPOI IS LARGE ENOUGH\nC\n      IF (ignpoi.GE.ll) RETURN\nC\nC     STEP S. SQUEEZE ACCEPTANCE - SUNIF(IR) FOR (0,1)-SAMPLE U\nC\n      fk = float(ignpoi)\n      difmuk = mu - fk\n      u = ranf()\n      IF (d*u.GE.difmuk*difmuk*difmuk) RETURN\nC\nC     STEP P. PREPARATIONS FOR STEPS Q AND H.\nC             (RECALCULATIONS OF PARAMETERS IF NECESSARY)\nC             .3989423=(2*PI)**(-.5)  .416667E-1=1./24.  .1428571=1./7.\nC             THE QUANTITIES B1, B2, C3, C2, C1, C0 ARE FOR THE HERMITE\nC             APPROXIMATIONS TO THE DISCRETE NORMAL PROBABILITIES FK.\nC             C=.1069/MU GUARANTEES MAJORIZATION BY THE 'HAT'-FUNCTION.\nC\n   20 IF (mu.EQ.muold) GO TO 30\n      muold = mu\n      omega = .3989423/s\n      b1 = .4166667E-1/mu\n      b2 = .3*b1*b1\n      c3 = .1428571*b1*b2\n      c2 = b2 - 15.*c3\n      c1 = b1 - 6.*b2 + 45.*c3\n      c0 = 1. - b1 + 3.*b2 - 15.*c3\n      c = .1069/mu\n   30 IF (g.LT.0.0) GO TO 50\nC\nC             'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN)\nC\n      kflag = 0\n      GO TO 70\nC\nC     STEP Q. QUOTIENT ACCEPTANCE (RARE CASE)\nC\n   40 IF (fy-u*fy.LE.py*exp(px-fx)) RETURN\nC\nC     STEP E. EXPONENTIAL SAMPLE - SEXPO(IR) FOR STANDARD EXPONENTIAL\nC             DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT'\nC             (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.)\nC\n   50 e = sexpo()\n      u = ranf()\n      u = u + u - 1.0\n      t = 1.8 + sign(e,u)\n      IF (t.LE. (-.6744)) GO TO 50\n      ignpoi = ifix(mu+s*t)\n      fk = float(ignpoi)\n      difmuk = mu - fk\nC\nC             'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN)\nC\n      kflag = 1\n      GO TO 70\nC\nC     STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION)\nC\n   60 IF (c*abs(u).GT.py*exp(px+e)-fy*exp(fx+e)) GO TO 50\n      RETURN\nC\nC     STEP F. 'SUBROUTINE' F. CALCULATION OF PX,PY,FX,FY.\nC             CASE IGNPOI .LT. 10 USES FACTORIALS FROM TABLE FACT\nC\n   70 IF (ignpoi.GE.10) GO TO 80\n      px = -mu\n      py = mu**ignpoi/fact(ignpoi+1)\n      GO TO 110\nC\nC             CASE IGNPOI .GE. 10 USES POLYNOMIAL APPROXIMATION\nC             A0-A7 FOR ACCURACY WHEN ADVISABLE\nC             .8333333E-1=1./12.  .3989423=(2*PI)**(-.5)\nC\n   80 del = .8333333E-1/fk\n      del = del - 4.8*del*del*del\n      v = difmuk/fk\n      IF (abs(v).LE.0.25) GO TO 90\n      px = fk*alog(1.0+v) - difmuk - del\n      GO TO 100\n\n   90 px = fk*v*v* (((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v+a0) -\n     +     del\n  100 py = .3989423/sqrt(fk)\n  110 x = (0.5-difmuk)/s\n      xx = x*x\n      fx = -0.5*xx\n      fy = omega* (((c3*xx+c2)*xx+c1)*xx+c0)\n      IF (kflag.LE.0) GO TO 40\n      GO TO 60\nC\nC     C A S E  B. (START NEW TABLE AND CALCULATE P0 IF NECESSARY)\nC\nC     JJV changed MUPREV assignment from 0.0 to initial value\n  120 muprev = -1.0E37\n      IF (mu.EQ.muold) GO TO 130\nC     JJV added argument checker here\n      IF (mu.GE.0.0) GO TO 125\n      WRITE (*,*) 'MU < 0 in IGNPOI - ABORT'\n      WRITE (*,*) 'Value of MU: ',mu\n      CALL XSTOPX ('MU < 0 in IGNPOI - ABORT')\nC     JJV added line label here\n 125  muold = mu\n      m = max0(1,ifix(mu))\n      l = 0\n      p = exp(-mu)\n      q = p\n      p0 = p\nC\nC     STEP U. UNIFORM SAMPLE FOR INVERSION METHOD\nC\n  130 u = ranf()\n      ignpoi = 0\n      IF (u.LE.p0) RETURN\nC\nC     STEP T. TABLE COMPARISON UNTIL THE END PP(L) OF THE\nC             PP-TABLE OF CUMULATIVE POISSON PROBABILITIES\nC             (0.458=PP(9) FOR MU=10)\nC\n      IF (l.EQ.0) GO TO 150\n      j = 1\n      IF (u.GT.0.458) j = min0(l,m)\n      DO 140 k = j,l\n          IF (u.LE.pp(k)) GO TO 180\n  140 CONTINUE\n      IF (l.EQ.35) GO TO 130\nC\nC     STEP C. CREATION OF NEW POISSON PROBABILITIES P\nC             AND THEIR CUMULATIVES Q=PP(K)\nC\n  150 l = l + 1\n      DO 160 k = l,35\n          p = p*mu/float(k)\n          q = q + p\n          pp(k) = q\n          IF (u.LE.q) GO TO 170\n  160 CONTINUE\n      l = 35\n      GO TO 130\n\n  170 l = k\n  180 ignpoi = k\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/ignuin.f",
    "content": "      INTEGER*4 FUNCTION ignuin(low,high)\nC**********************************************************************\nC\nC     INTEGER*4 FUNCTION IGNUIN( LOW, HIGH )\nC\nC               GeNerate Uniform INteger\nC\nC\nC                              Function\nC\nC\nC     Generates an integer uniformly distributed between LOW and HIGH.\nC\nC\nC                              Arguments\nC\nC\nC     LOW --> Low bound (inclusive) on integer value to be generated\nC                         INTEGER LOW\nC\nC     HIGH --> High bound (inclusive) on integer value to be generated\nC                         INTEGER HIGH\nC\nC\nC                              Note\nC\nC\nC     If (HIGH-LOW) > 2,147,483,561 prints error message on * unit and\nC     stops the program.\nC\nC**********************************************************************\n\nC     IGNLGI generates integers between 1 and 2147483562\nC     MAXNUM is 1 less than maximum generable value\nC     .. Parameters ..\n      INTEGER*4 maxnum\n      PARAMETER (maxnum=2147483561)\n      CHARACTER*(*) err1,err2\n      PARAMETER (err1='LOW > HIGH in IGNUIN',\n     +          err2=' ( HIGH - LOW ) > 2,147,483,561 in IGNUIN')\nC     ..\nC     .. Scalar Arguments ..\n      INTEGER*4 high,low\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 err,ign,maxnow,range,ranp1\nC     ..\nC     .. External Functions ..\n      INTEGER*4 ignlgi\n      EXTERNAL ignlgi\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC mod\nC     ..\nC     .. Executable Statements ..\n      IF (.NOT. (low.GT.high)) GO TO 10\n      err = 1\nC      ABORT-PROGRAM\n      GO TO 80\n\n   10 range = high - low\n      IF (.NOT. (range.GT.maxnum)) GO TO 20\n      err = 2\nC      ABORT-PROGRAM\n      GO TO 80\n\n   20 IF (.NOT. (low.EQ.high)) GO TO 30\n      ignuin = low\n      RETURN\n\nC     Number to be generated should be in range 0..RANGE\nC     Set MAXNOW so that the number of integers in 0..MAXNOW is an\nC     integral multiple of the number in 0..RANGE\n\n   30 ranp1 = range + 1\n      maxnow = (maxnum/ranp1)*ranp1\n   40 ign = ignlgi() - 1\n      IF (.NOT. (ign.LE.maxnow)) GO TO 40\n      ignuin = low + mod(ign,ranp1)\n      RETURN\n\n   80 IF (.NOT. (err.EQ.1)) GO TO 90\n      WRITE (*,*) err1\n      GO TO 100\n\nC     TO ABORT-PROGRAM\n   90 WRITE (*,*) err2\n  100 WRITE (*,*) ' LOW: ',low,' HIGH: ',high\n      WRITE (*,*) ' Abort on Fatal ERROR'\n      IF (.NOT. (err.EQ.1)) GO TO 110\n      CALL XSTOPX ('LOW > HIGH in IGNUIN')\n\n  110 CALL XSTOPX (' ( HIGH - LOW ) > 2,147,483,561 in IGNUIN')\n\n  120 END\n"
  },
  {
    "path": "liboctave/external/ranlib/initgn.f",
    "content": "      SUBROUTINE initgn(isdtyp)\nC**********************************************************************\nC\nC     SUBROUTINE INITGN(ISDTYP)\nC          INIT-ialize current G-e-N-erator\nC\nC     Reinitializes the state of the current generator\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Init_Generator from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     ISDTYP -> The state to which the generator is to be set\nC\nC          ISDTYP = -1  => sets the seeds to their initial value\nC          ISDTYP =  0  => sets the seeds to the first value of\nC                          the current block\nC          ISDTYP =  1  => sets the seeds to the first value of\nC                          the next block\nC\nC                                   INTEGER ISDTYP\nC\nC**********************************************************************\nC     .. Parameters ..\n      INTEGER*4 numg\n      PARAMETER (numg=32)\nC     ..\nC     .. Scalar Arguments ..\n      INTEGER*4 isdtyp\nC     ..\nC     .. Scalars in Common ..\n      INTEGER*4 a1,a1vw,a1w,a2,a2vw,a2w,m1,m2\nC     ..\nC     .. Arrays in Common ..\n      INTEGER*4 cg1(numg),cg2(numg),ig1(numg),ig2(numg),lg1(numg),\n     +        lg2(numg)\n      LOGICAL qanti(numg)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 g\nC     ..\nC     .. External Functions ..\n      LOGICAL qrgnin\n      INTEGER*4 mltmod\n      EXTERNAL qrgnin,mltmod\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL getcgn\nC     ..\nC     .. Common blocks ..\n      COMMON /globe/m1,m2,a1,a2,a1w,a2w,a1vw,a2vw,ig1,ig2,lg1,lg2,cg1,\n     +       cg2,qanti\nC     ..\nC     .. Save statement ..\n      SAVE /globe/\nC     ..\nC     .. Executable Statements ..\nC     Abort unless random number generator initialized\n      IF (qrgnin()) GO TO 10\n      WRITE (*,*) ' INITGN called before random number generator ',\n     +  ' initialized -- abort!'\n      CALL XSTOPX\n     + (' INITGN called before random number generator initialized')\n\n   10 CALL getcgn(g)\n      IF ((-1).NE. (isdtyp)) GO TO 20\n      lg1(g) = ig1(g)\n      lg2(g) = ig2(g)\n      GO TO 50\n\n   20 IF ((0).NE. (isdtyp)) GO TO 30\n      CONTINUE\n      GO TO 50\nC     do nothing\n   30 IF ((1).NE. (isdtyp)) GO TO 40\n      lg1(g) = mltmod(a1w,lg1(g),m1)\n      lg2(g) = mltmod(a2w,lg2(g),m2)\n      GO TO 50\n\n   40 CALL XSTOPX ('ISDTYP NOT IN RANGE')\n\n   50 cg1(g) = lg1(g)\n      cg2(g) = lg2(g)\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/inrgcm.f",
    "content": "      SUBROUTINE inrgcm()\nC**********************************************************************\nC\nC     SUBROUTINE INRGCM()\nC          INitialize Random number Generator CoMmon\nC\nC\nC                              Function\nC\nC\nC     Initializes common area  for random number  generator.  This saves\nC     the  nuisance  of  a  BLOCK DATA  routine  and the  difficulty  of\nC     assuring that the routine is loaded with the other routines.\nC\nC**********************************************************************\nC     .. Parameters ..\n      INTEGER*4 numg\n      PARAMETER (numg=32)\nC     ..\nC     .. Scalars in Common ..\n      INTEGER*4 a1,a1vw,a1w,a2,a2vw,a2w,m1,m2\nC     ..\nC     .. Arrays in Common ..\n      INTEGER*4 cg1(numg),cg2(numg),ig1(numg),ig2(numg),lg1(numg),\n     +        lg2(numg)\n      LOGICAL qanti(numg)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 i\n      LOGICAL qdum\nC     ..\nC     .. External Functions ..\n      LOGICAL qrgnsn\n      EXTERNAL qrgnsn\nC     ..\nC     .. Common blocks ..\n      COMMON /globe/m1,m2,a1,a2,a1w,a2w,a1vw,a2vw,ig1,ig2,lg1,lg2,cg1,\n     +       cg2,qanti\nC     ..\nC     .. Save statement ..\n      SAVE /globe/\nC     ..\nC     .. Executable Statements ..\nC     V=20;                            W=30;\nC\nC     A1W = MOD(A1**(2**W),M1)         A2W = MOD(A2**(2**W),M2)\nC     A1VW = MOD(A1**(2**(V+W)),M1)    A2VW = MOD(A2**(2**(V+W)),M2)\nC\nC   If V or W is changed A1W, A2W, A1VW, and A2VW need to be recomputed.\nC    An efficient way to precompute a**(2*j) MOD m is to start with\nC    a and square it j times modulo m using the function MLTMOD.\nC\n      m1 = 2147483563\n      m2 = 2147483399\n      a1 = 40014\n      a2 = 40692\n      a1w = 1033780774\n      a2w = 1494757890\n      a1vw = 2082007225\n      a2vw = 784306273\n      DO 10,i = 1,numg\n          qanti(i) = .FALSE.\n   10 CONTINUE\nC\nC     Tell the world that common has been initialized\nC\n      qdum = qrgnsn(.TRUE.)\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/lennob.f",
    "content": "      INTEGER*4 FUNCTION lennob(string)\n      IMPLICIT INTEGER*4 (a-p,r-z),LOGICAL (q)\nC**********************************************************************\nC\nC     INTEGER*4 FUNCTION LENNOB( STRING )\nC                LENgth NOt counting trailing Blanks\nC\nC\nC                              Function\nC\nC\nC     Returns the length of STRING up to and including the last\nC     non-blank character.\nC\nC\nC                              Arguments\nC\nC\nC     STRING --> String whose length not counting trailing blanks\nC                is returned.\nC\nC**********************************************************************\n      CHARACTER*(*) string\n\n      end = len(string)\n      DO 20,i = end,1,-1\n          IF (.NOT. (string(i:i).NE.' ')) GO TO 10\n          lennob = i\n          RETURN\n\n   10     CONTINUE\n   20 CONTINUE\n      lennob = 0\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/mltmod.f",
    "content": "      INTEGER*4 FUNCTION mltmod(a,s,m)\nC**********************************************************************\nC\nC     INTEGER*4 FUNCTION MLTMOD(A,S,M)\nC\nC                    Returns (A*S) MOD M\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     MULtMod_Decompos from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     A, S, M  -->\nC                         INTEGER A,S,M\nC\nC**********************************************************************\nC     .. Parameters ..\n      INTEGER*4 h\n      PARAMETER (h=32768)\nC     ..\nC     .. Scalar Arguments ..\n      INTEGER*4 a,m,s\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 a0,a1,k,p,q,qh,rh\nC     ..\nC     .. Executable Statements ..\nC\nC     H = 2**((b-2)/2) where b = 32 because we are using a 32 bit\nC      machine. On a different machine recompute H\nC\n      IF (.NOT. (a.LE.0.OR.a.GE.m.OR.s.LE.0.OR.s.GE.m)) GO TO 10\n      WRITE (*,*) ' A, M, S out of order in MLTMOD - ABORT!'\n      WRITE (*,*) ' A = ',a,' S = ',s,' M = ',m\n      WRITE (*,*) ' MLTMOD requires: 0 < A < M; 0 < S < M'\n      CALL XSTOPX (' A, M, S out of order in MLTMOD - ABORT!')\n\n   10 IF (.NOT. (a.LT.h)) GO TO 20\n      a0 = a\n      p = 0\n      GO TO 120\n\n   20 a1 = a/h\n      a0 = a - h*a1\n      qh = m/h\n      rh = m - h*qh\n      IF (.NOT. (a1.GE.h)) GO TO 50\n      a1 = a1 - h\n      k = s/qh\n      p = h* (s-k*qh) - k*rh\n   30 IF (.NOT. (p.LT.0)) GO TO 40\n      p = p + m\n      GO TO 30\n\n   40 GO TO 60\n\n   50 p = 0\nC\nC     P = (A2*S*H)MOD M\nC\n   60 IF (.NOT. (a1.NE.0)) GO TO 90\n      q = m/a1\n      k = s/q\n      p = p - k* (m-a1*q)\n      IF (p.GT.0) p = p - m\n      p = p + a1* (s-k*q)\n   70 IF (.NOT. (p.LT.0)) GO TO 80\n      p = p + m\n      GO TO 70\n\n   80 CONTINUE\n   90 k = p/qh\nC\nC     P = ((A2*H + A1)*S)MOD M\nC\n      p = h* (p-k*qh) - k*rh\n  100 IF (.NOT. (p.LT.0)) GO TO 110\n      p = p + m\n      GO TO 100\n\n  110 CONTINUE\n  120 IF (.NOT. (a0.NE.0)) GO TO 150\nC\nC     P = ((A2*H + A1)*H*S)MOD M\nC\n      q = m/a0\n      k = s/q\n      p = p - k* (m-a0*q)\n      IF (p.GT.0) p = p - m\n      p = p + a0* (s-k*q)\n  130 IF (.NOT. (p.LT.0)) GO TO 140\n      p = p + m\n      GO TO 130\n\n  140 CONTINUE\n  150 mltmod = p\nC\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/module.mk",
    "content": "RANLIB_SRC = \\\n  %reldir%/advnst.f \\\n  %reldir%/genbet.f \\\n  %reldir%/genchi.f \\\n  %reldir%/genexp.f \\\n  %reldir%/genf.f \\\n  %reldir%/gengam.f \\\n  %reldir%/genmn.f \\\n  %reldir%/genmul.f \\\n  %reldir%/gennch.f \\\n  %reldir%/gennf.f \\\n  %reldir%/gennor.f \\\n  %reldir%/genprm.f \\\n  %reldir%/genunf.f \\\n  %reldir%/getcgn.f \\\n  %reldir%/getsd.f \\\n  %reldir%/ignbin.f \\\n  %reldir%/ignlgi.f \\\n  %reldir%/ignnbn.f \\\n  %reldir%/ignpoi.f \\\n  %reldir%/ignuin.f \\\n  %reldir%/initgn.f \\\n  %reldir%/inrgcm.f \\\n  %reldir%/lennob.f \\\n  %reldir%/mltmod.f \\\n  %reldir%/phrtsd.f \\\n  %reldir%/qrgnin.f \\\n  %reldir%/ranf.f \\\n  %reldir%/setall.f \\\n  %reldir%/setant.f \\\n  %reldir%/setgmn.f \\\n  %reldir%/setsd.f \\\n  %reldir%/sexpo.f \\\n  %reldir%/sgamma.f \\\n  %reldir%/snorm.f \\\n  %reldir%/wrap.f\n\nnoinst_LTLIBRARIES += %reldir%/libranlib.la\n\n%canon_reldir%_libranlib_la_SOURCES = $(RANLIB_SRC)\n\n%canon_reldir%_libranlib_la_DEPENDENCIES = %reldir%/ranlib.def\n\n## Special rules for files which must be built before compilation\n## ranlib directory may not exist in VPATH build; create it if necessary.\n%reldir%/ranlib.def: $(RANLIB_SRC) %reldir%/../mk-f77-def.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(SHELL) %reldir%/../mk-f77-def.sh $(srcdir) $(RANLIB_SRC) > $@-t && \\\n\tmv $@-t $@\n\nliboctave_liboctave_la_LIBADD += %reldir%/libranlib.la\n\nliboctave_EXTRA_DIST += \\\n  %reldir%/Basegen.doc \\\n  %reldir%/HOWTOGET \\\n  %reldir%/README \\\n  %reldir%/randlib.chs \\\n  %reldir%/randlib.fdoc \\\n  %reldir%/tstbot.for \\\n  %reldir%/tstgmn.for \\\n  %reldir%/tstmid.for\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "liboctave/external/ranlib/phrtsd.f",
    "content": "      SUBROUTINE phrtsd(phrase,seed1,seed2)\nC**********************************************************************\nC\nC     SUBROUTINE PHRTSD( PHRASE, SEED1, SEED2 )\nC               PHRase To SeeDs\nC\nC\nC                              Function\nC\nC\nC     Uses a phrase (character string) to generate two seeds for the RGN\nC     random number generator.\nC\nC\nC                              Arguments\nC\nC\nC     PHRASE --> Phrase to be used for random number generation\nC                         CHARACTER*(*) PHRASE\nC\nC     SEED1 <-- First seed for RGN generator\nC                         INTEGER SEED1\nC\nC     SEED2 <-- Second seed for RGN generator\nC                         INTEGER SEED2\nC\nC\nC                              Note\nC\nC\nC     Trailing blanks are eliminated before the seeds are generated.\nC\nC     Generated seed values will fall in the range 1..2^30\nC     (1..1,073,741,824)\nC\nC**********************************************************************\nC     .. Parameters ..\n      CHARACTER*(*) table\n      PARAMETER (table='abcdefghijklmnopqrstuvwxyz'//\n     +          'ABCDEFGHIJKLMNOPQRSTUVWXYZ'//'0123456789'//\n     +          '!@#$%^&*()_+[];:''\"<>?,./')\n      INTEGER*4 twop30\n      PARAMETER (twop30=1073741824)\n      INTEGER*4 sixty4\n      PARAMETER (sixty4=64)\nC     ..\nC     .. Scalar Arguments ..\n      INTEGER*4 seed1,seed2\n      CHARACTER phrase* (*)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 i,ichr,j,lphr,idxval\nC     ..\nC     .. Local Arrays ..\n      INTEGER*4 shift(0:4),values(5)\nC     ..\nC     .. External Functions ..\n      INTEGER*4 lennob\n      EXTERNAL lennob\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC index,mod\nC     ..\nC     JJV added Save statement for variable in Data statement\nC     .. Save statements ..\n      SAVE shift\nC     JJV end addition\nC     ..\nC     .. Data statements ..\n      DATA shift/1,64,4096,262144,16777216/\nC     ..\nC     .. Executable Statements ..\n      seed1 = 1234567890\n      seed2 = 123456789\n      lphr = lennob(phrase)\n      IF (lphr.LT.1) RETURN\n      DO 30,i = 1,lphr\n          idxval = index(table,phrase(i:i))\n          ichr = mod(idxval,sixty4)\n          IF (ichr.EQ.0) ichr = 63\n          DO 10,j = 1,5\n              values(j) = ichr - j\n              IF (values(j).LT.1) values(j) = values(j) + 63\n   10     CONTINUE\n          DO 20,j = 1,5\n              seed1 = mod(seed1+shift(j-1)*values(j),twop30)\n              seed2 = mod(seed2+shift(j-1)*values(6-j),twop30)\n   20     CONTINUE\n   30 CONTINUE\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/qrgnin.f",
    "content": "      LOGICAL FUNCTION qrgnin()\nC**********************************************************************\nC\nC     LOGICAL FUNCTION QRGNIN()\nC               Q Random GeNerators INitialized?\nC\nC     A trivial routine to determine whether or not the random\nC     number generator has been initialized.  Returns .TRUE. if\nC     it has, else .FALSE.\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      LOGICAL qvalue\nC     ..\nC     .. Local Scalars ..\n      LOGICAL qinit\nC     ..\nC     .. Entry Points ..\n      LOGICAL qrgnsn\nC     ..\nC     .. Save statement ..\n      SAVE qinit\nC     ..\nC     .. Data statements ..\n      DATA qinit/.FALSE./\nC     ..\nC     .. Executable Statements ..\n      qrgnin = qinit\n      RETURN\n\n      ENTRY qrgnsn(qvalue)\nC**********************************************************************\nC\nC     LOGICAL FUNCTION QRGNSN( QVALUE )\nC               Q Random GeNerators Set whether iNitialized\nC\nC     Sets state of whether random number generator is initialized\nC     to QVALUE.\nC\nC     This routine is actually an entry in QRGNIN, hence it is a\nC     logical function.  It returns the (meaningless) value .TRUE.\nC\nC**********************************************************************\n      qinit = qvalue\n      qrgnsn = .TRUE.\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/randlib.chs",
    "content": "                    SUMMARY OF ROUTINES IN RANDLIB\n\n0. Base Level Routines to Set and Obtain Values of Seeds\n\n(These should be the only base level routines used by  those who don't\nneed multiple generators with blocks of numbers.)\n\nC**********************************************************************\nC\nC      SUBROUTINE SETALL(ISEED1,ISEED2)\nC               SET ALL random number generators\nC      INTEGER ISEED1, ISEED2\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE GETSD(ISEED1,ISEED2)\nC               GET SeeD\nC     INTEGER ISEED1, ISEED2\nC\nC     Returns the value of two integer seeds of the current generator\nC     in ISEED1, ISEED2\nC\nC**********************************************************************\n\nI. Higher Level Routines\n\nC**********************************************************************\nC\nC     REAL FUNCTION GENBET( A, B )\nC               GeNerate BETa random deviate\nC     REAL A,B\nC\nC     Returns a single random deviate from the beta distribution with\nC     parameters A and B.  The density of the beta is\nC               x^(a-1) * (1-x)^(b-1) / B(a,b) for 0 < x < 1\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENCHI( DF )\nC                Generate random value of CHIsquare variable\nC     REAL DF\nC\nC     Generates random deviate from the distribution of a chisquare\nC     with DF degrees of freedom random variable.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENEXP( AV )\nC                    GENerate EXPonential random deviate\nC     REAL AV\nC\nC     Generates a single random deviate from an exponential\nC     distribution with mean AV.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENF( DFN, DFD )\nC                GENerate random deviate from the F distribution\nC     REAL DFN, DFD\nC\nC     Generates a random deviate from the F (variance ratio)\nC     distribution with DFN degrees of freedom in the numerator\nC     and DFD degrees of freedom in the denominator.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENGAM( A, R )\nC           GENerates random deviates from GAMma distribution\nC     REAL A, R\nC\nC     Generates random deviates from the gamma distribution whose\nC     density is\nC          (A**R)/Gamma(R) * X**(R-1) * Exp(-A*X)\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE GENMN(PARM,X,WORK)\nC              GENerate Multivariate Normal random deviate\nC     REAL PARM(*), X(*), WORK(*)\nC\nC     PARM is set by SETGMN which must be called prior to GENMN.  The\nC     generated deviates are placed in X.  WORK is a work array of the\nC     same size as X.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE GENMUL( N, P, NCAT, IX )\nC              GENerate MULtinomial random deviate\nC     REAL P(*)\nC     INTEGER N, NCAT, IX(*)\nC\nC     Generates deviates from a Multinomial distribution with NCAT\nC     categories.  P specifies the probability of an event in each\nC     category. The generated deviates are placed in IX.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENNCH( DF, XNONC )\nC           Generate random value of Noncentral CHIsquare variable\nC     REAL DF, XNONC\nC\nC     Generates random deviate  from the  distribution  of a  noncentral\nC     chisquare with DF degrees  of freedom and noncentrality  parameter\nC     XNONC.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENNF( DFN, DFD, XNONC )\nC           GENerate random deviate from the Noncentral F distribution\nC     REAL DFN, DFD, XNONC\nC\nC     Generates a random deviate from the  noncentral F (variance ratio)\nC     distribution with DFN degrees of freedom in the numerator, and DFD\nC     degrees of freedom in the denominator, and noncentrality parameter\nC     XNONC.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENNOR( AV, SD )\nC         GENerate random deviate from a NORmal distribution\nC     REAL AV, SD\nC\nC     Generates a single random deviate from a normal distribution\nC     with mean, AV, and standard deviation, SD.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC    SUBROUTINE GENPRM( IARRAY, LARRAY )\nC               GENerate random PeRMutation of iarray\nC    INTEGER IARRAY(LARRAY), LARRAY\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENUNF( LOW, HIGH )\nC               GeNerate Uniform Real between LOW and HIGH\nC     REAL LOW, HIGH\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNBIN( N, P )\nC                    GENerate BINomial random deviate\nC     INTEGER N\nC     REAL P\nC\nC     Returns a single random deviate from a binomial\nC     distribution whose number of trials is N and whose\nC     probability of an event in each trial is P.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNNBN( N, P )\nC               GENerate Negative BiNomial random deviate\nC     INTEGER N\nC     REAL P\nC\nC     Returns a single random deviate from a negative binomial\nC     distribution with number of events N and whose\nC     probability of an event in each trial is P.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNPOI( AV )\nC                    GENerate POIsson random deviate\nC     REAL AV\nC\nC     Generates a single random deviate from a Poisson\nC     distribution with mean AV.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNUIN( LOW, HIGH )\nC               GeNerate Uniform INteger\nC     INTEGER LOW, HIGH\nC\nC     Generates an integer uniformly distributed between LOW and HIGH.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE PHRTSD( PHRASE, SEED1, SEED2 )\nC               PHRase To SeeDs\nC     CHARACTER*(*) PHRASE\nC     INTEGER SEED1, SEED2\nC\nC     Uses a phrase (character string) to generate two seeds for the RGN\nC     random number generator.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION RANF()\nC                RANDom number generator as a Function\nC\nC     Returns a random floating point number from a uniform distribution\nC     over 0 - 1 (endpoints of this interval are not returned) using the\nC     current generator\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE SETGMN( MEANV, COVM, LDCOVM, P, PARM)\nC            SET Generate Multivariate Normal random deviate\nC     INTEGER LDCOVM, P\nC     REAL MEANV(P), COVM(LDCOVM,P), PARM(P*(P+3)/2 + 1)\nC\nC     P is the length of normal vectors to be generated, MEANV\nC     is the vector of their means and COVM(1:P,1:P) is their variance\nC     covariance matrix.  LDCOVM is the leading actual dimension of\nC     COVM, which this routine needs to know although only the\nC     (1:P,1:P) slice of COVM is used.\nC     Places information necessary to generate the deviates in PARM.\nC\nC**********************************************************************\n\nII. Uniform Generator and Associated Routines\n\n\n      A. SETTING THE SEED OF ALL GENERATORS\n\nC**********************************************************************\nC\nC      SUBROUTINE SETALL(ISEED1,ISEED2)\nC               SET ALL random number generators\nC      INTEGER ISEED1, ISEED2\nC\nC**********************************************************************\n\n      B. OBTAINING RANDOM NUMBERS\n\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNLGI()\nC               GeNerate LarGe Integer\nC\nC     Returns a random integer following a uniform distribution over\nC     (1, 2147483562) using the current generator.\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC     REAL FUNCTION RANF()\nC                RANDom number generator as a Function\nC\nC     Returns a random floating point number from a uniform distribution\nC     over 0 - 1 (endpoints of this interval are not returned) using the\nC     current generator\nC\nC**********************************************************************\n\n      C. SETTING AND OBTAINING THE NUMBER OF THE CURRENT GENERATOR\n\nC**********************************************************************\nC\nC     SUBROUTINE SETCGN( G )\nC                      Set GeNerator\nC     INTEGER G\nC\nC     Sets  the  current  generator to G. All references to a generator\nC     are to the current generator.\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC      SUBROUTINE GETCGN(G)\nC               GET Current GeNerator\nC      INTEGER G\nC\nC      Returns in G the number of the current random number generator\nC\nC**********************************************************************\n\n      D. OBTAINING OR CHANGING SEEDS IN CURRENT GENERATOR\n\nC**********************************************************************\nC\nC     SUBROUTINE ADVNST(K)\nC               ADV-a-N-ce ST-ate\nC     INTEGER K\nC\nC     Advances the state  of  the current  generator  by 2^K values  and\nC     resets the initial seed to that value.\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC     SUBROUTINE GETSD(ISEED1,ISEED2)\nC               GET SeeD\nC     INTEGER ISEED1, ISEED2\nC\nC     Returns the value of two integer seeds of the current generator\nC     in ISEED1, ISEED2\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC     SUBROUTINE INITGN(ISDTYP)\nC          INIT-ialize current G-e-N-erator\nC\nC     INTEGER ISDTYP    The state to which the generator is to be set\nC          ISDTYP = -1  => sets the seeds to their initial value\nC          ISDTYP =  0  => sets the seeds to the first value of\nC                          the current block\nC          ISDTYP =  1  => sets the seeds to the first value of\nC                          the next block\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC     SUBROUTINE SETSD(ISEED1,ISEED2)\nC               SET S-ee-D of current generator\nC\nC     Resets the initial  seed of  the current  generator to  ISEED1 and\nC     ISEED2. The seeds of the other generators remain unchanged.\nC\nC**********************************************************************\n\n      E. MISCELLANY\n\nC**********************************************************************\nC\nC     INTEGER FUNCTION MLTMOD(A,S,M)\nC                    Returns (A*S) MOD M\nC     INTEGER A, S, M\nC\nC**********************************************************************\n\nC**********************************************************************\nC\nC      SUBROUTINE SETANT(QVALUE)\nC               SET ANTithetic\nC      LOGICAL QVALUE\nC\nC     Sets whether the current generator produces antithetic values.  If\nC     X   is  the value  normally returned  from  a uniform [0,1] random\nC     number generator then 1  - X is the antithetic  value. If X is the\nC     value  normally  returned  from a   uniform  [0,N]  random  number\nC     generator then N - 1 - X is the antithetic value.\nC\nC     All generators are initialized to NOT generate antithetic values.\nC\nC**********************************************************************\n"
  },
  {
    "path": "liboctave/external/ranlib/randlib.fdoc",
    "content": "\n\n\n\n\n\n\n\n\n\n\n                                     RANDLIB\n\n            Library of Fortran Routines for Random Number Generation\n\n\n\n\n\n\n\n\n                       Full Documentation of Each Routine\n\n\n\n\n\n\n\n\n                            Compiled and Written by:\n\n                                 Barry W. Brown\n                                  James Lovato\n\n\n\n\n\n\n\n\n\n\n                     Department of Biomathematics, Box 237\n                     The University of Texas, M.D. Anderson Cancer Center\n                     1515 Holcombe Boulevard\n                     Houston, TX      77030\n\n\n This work was supported by grant CA-16672 from the National Cancer Institute.\n\f\nC**********************************************************************\nC\nC     SUBROUTINE ADVNST(K)\nC               ADV-a-N-ce ST-ate\nC\nC     Advances the state  of  the current  generator  by 2^K values  and\nC     resets the initial seed to that value.\nC\nC     This is  a  transcription from   Pascal to  Fortran    of  routine\nC     Advance_State from the paper\nC\nC     L'Ecuyer, P. and  Cote, S. \"Implementing  a  Random Number Package\nC     with  Splitting   Facilities.\"  ACM  Transactions  on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     K -> The generator is advanced by2^K values\nC                                   INTEGER K\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENBET( A, B )\nC               GeNerate BETa random deviate\nC\nC\nC                              Function\nC\nC\nC     Returns a single random deviate from the beta distribution with\nC     parameters A and B.  The density of the beta is\nC               x^(a-1) * (1-x)^(b-1) / B(a,b) for 0 < x < 1\nC\nC\nC                              Arguments\nC\nC\nC     A --> First parameter of the beta distribution\nC                         REAL A\nC                         (A >= 1.0E-37)\nC\nC     B --> Second parameter of the beta distribution\nC                         REAL B\nC                         (B >= 1.0E-37)\nC\nC\nC                              Method\nC\nC\nC     R. C. H. Cheng\nC     Generating Beta Variables with Nonintegral Shape Parameters\nC     Communications of the ACM, 21:317-322  (1978)\nC     (Algorithms BB and BC)\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENCHI( DF )\nC                Generate random value of CHIsquare variable\nC\nC\nC                              Function\nC\nC\nC     Generates random deviate from the distribution of a chisquare\nC     with DF degrees of freedom random variable.\nC\nC\nC                              Arguments\nC\nC\nC     DF --> Degrees of freedom of the chisquare\nC            (Must be positive)\nC                         REAL DF\nC\nC\nC                              Method\nC\nC\nC     Uses relation between chisquare and gamma.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENEXP( AV )\nC\nC                    GENerate EXPonential random deviate\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from an exponential\nC     distribution with mean AV.\nC\nC\nC                              Arguments\nC\nC\nC     AV --> The mean of the exponential distribution from which\nC            a random deviate is to be generated.\nC                              REAL AV\nC                              (AV >= 0)\nC\nC     GENEXP <-- The random deviate.\nC                              REAL GENEXP\nC\nC\nC                              Method\nC\nC\nC     Renames SEXPO from TOMS as slightly modified by BWB to use RANF\nC     instead of SUNIF.\nC\nC     For details see:\nC\nC               Ahrens, J.H. and Dieter, U.\nC               Computer Methods for Sampling From the\nC               Exponential and Normal Distributions.\nC               Comm. ACM, 15,10 (Oct. 1972), 873 - 882.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENF( DFN, DFD )\nC                GENerate random deviate from the F distribution\nC\nC\nC                              Function\nC\nC\nC     Generates a random deviate from the F (variance ratio)\nC     distribution with DFN degrees of freedom in the numerator\nC     and DFD degrees of freedom in the denominator.\nC\nC\nC                              Arguments\nC\nC\nC     DFN --> Numerator degrees of freedom\nC             (Must be positive)\nC                              REAL DFN\nC      DFD --> Denominator degrees of freedom\nC             (Must be positive)\nC                              REAL DFD\nC\nC\nC                              Method\nC\nC\nC     Directly generates ratio of chisquare variates\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENGAM( A, R )\nC           GENerates random deviates from GAMma distribution\nC\nC\nC                              Function\nC\nC\nC     Generates random deviates from the gamma distribution whose\nC     density is\nC          (A**R)/Gamma(R) * X**(R-1) * Exp(-A*X)\nC\nC\nC                              Arguments\nC\nC\nC     A --> Location parameter of Gamma distribution\nC                              REAL A ( A > 0 )\nC\nC     R --> Shape parameter of Gamma distribution\nC                              REAL R ( R > 0 )\nC\nC\nC                              Method\nC\nC\nC     Renames SGAMMA from TOMS as slightly modified by BWB to use RANF\nC     instead of SUNIF.\nC\nC     For details see:\nC               (Case R >= 1.0)\nC               Ahrens, J.H. and Dieter, U.\nC               Generating Gamma Variates by a\nC               Modified Rejection Technique.\nC               Comm. ACM, 25,1 (Jan. 1982), 47 - 54.\nC     Algorithm GD\nC\nC               (Case 0.0 < R < 1.0)\nC               Ahrens, J.H. and Dieter, U.\nC               Computer Methods for Sampling from Gamma,\nC               Beta, Poisson and Binomial Distributions.\nC               Computing, 12 (1974), 223-246/\nC     Adapted algorithm GS.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE GENMN(PARM,X,WORK)\nC              GENerate Multivariate Normal random deviate\nC\nC\nC                              Arguments\nC\nC\nC     PARM --> Parameters needed to generate multivariate normal\nC               deviates (MEANV and Cholesky decomposition of\nC               COVM). Set by a previous call to SETGMN.\nC\nC               1 : 1                - size of deviate, P\nC               2 : P + 1            - mean vector\nC               P+2 : P*(P+3)/2 + 1  - upper half of cholesky\nC                                       decomposition of cov matrix\nC                                             REAL PARM(*)\nC\nC     X    <-- Vector deviate generated.\nC                                             REAL X(P)\nC\nC     WORK <--> Scratch array\nC                                             REAL WORK(P)\nC\nC\nC                              Method\nC\nC\nC     1) Generate P independent standard normal deviates - Ei ~ N(0,1)\nC\nC     2) SETGMN uses Cholesky decomposition find A s.t. trans(A)*A = COV\nC\nC     3) Generate trans(A)*E + MEANV ~ N(MEANV,COVM)\nC\nC**********************************************************************\nC**********************************************************************\nC\nC            SUBROUTINE GENMUL( N, P, NCAT, IX )\nC     GENerate an observation from the MULtinomial distribution\nC\nC\nC                              Arguments\nC\nC\nC     N --> Number of events that will be classified into one of\nC           the categories 1..NCAT\nC                         INTEGER N\nC\t                  (N >= 0)\nC\nC     P --> Vector of probabilities.  P(i) is the probability that\nC           an event will be classified into category i.  Thus, P(i)\nC           must be [0,1]. Only the first NCAT-1 P(i) must be defined\nC           since P(NCAT) is 1.0 minus the sum of the first\nC           NCAT-1 P(i).\nC                         REAL P(NCAT-1)\nC\nC     NCAT --> Number of categories.  Length of P and IX.\nC                         INTEGER NCAT\nC\t                  (NCAT > 1)\nC\nC     IX <-- Observation from multinomial distribution.  All IX(i)\nC            will be nonnegative and their sum will be N.\nC                         INTEGER IX(NCAT)\nC\nC\nC                              Method\nC\nC\nC     Algorithm from page 559 of\nC\nC     Devroye, Luc\nC\nC     Non-Uniform Random Variate Generation.  Springer-Verlag,\nC     New York, 1986.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENNCH( DF, XNONC )\nC           Generate random value of Noncentral CHIsquare variable\nC\nC\nC                              Function\nC\nC\nC\nC     Generates random deviate  from the  distribution  of a  noncentral\nC     chisquare with DF degrees  of freedom and noncentrality  parameter\nC     XNONC.\nC\nC\nC                              Arguments\nC\nC\nC     DF --> Degrees of freedom of the chisquare\nC            (Must be >= 1.0)\nC                         REAL DF\nC\nC     XNONC --> Noncentrality parameter of the chisquare\nC               (Must be >= 0.0)\nC                         REAL XNONC\nC\nC\nC                              Method\nC\nC\nC     Uses fact that  noncentral chisquare  is  the  sum of a  chisquare\nC     deviate with DF-1  degrees of freedom plus the  square of a normal\nC     deviate with mean XNONC and standard deviation 1.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENNF( DFN, DFD, XNONC )\nC           GENerate random deviate from the Noncentral F distribution\nC\nC\nC                              Function\nC\nC\nC     Generates a random deviate from the  noncentral F (variance ratio)\nC     distribution with DFN degrees of freedom in the numerator, and DFD\nC     degrees of freedom in the denominator, and noncentrality parameter\nC     XNONC.\nC\nC\nC                              Arguments\nC\nC\nC     DFN --> Numerator degrees of freedom\nC             (Must be >= 1.0)\nC                              REAL DFN\nC      DFD --> Denominator degrees of freedom\nC             (Must be positive)\nC                              REAL DFD\nC\nC     XNONC --> Noncentrality parameter\nC               (Must be nonnegative)\nC                              REAL XNONC\nC\nC\nC                              Method\nC\nC\nC     Directly generates ratio of noncentral numerator chisquare variate\nC     to central denominator chisquare variate.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENNOR( AV, SD )\nC\nC         GENerate random deviate from a NORmal distribution\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from a normal distribution\nC     with mean, AV, and standard deviation, SD.\nC\nC\nC                              Arguments\nC\nC\nC     AV --> Mean of the normal distribution.\nC                              REAL AV\nC\nC     SD --> Standard deviation of the normal distribution.\nC                              REAL SD\nC                              (SD >= 0)\nC\nC     GENNOR <-- Generated normal deviate.\nC                              REAL GENNOR\nC\nC\nC                              Method\nC\nC\nC     Renames SNORM from TOMS as slightly modified by BWB to use RANF\nC     instead of SUNIF.\nC\nC     For details see:\nC               Ahrens, J.H. and Dieter, U.\nC               Extensions of Forsythe's Method for Random\nC               Sampling from the Normal Distribution.\nC               Math. Comput., 27,124 (Oct. 1973), 927 - 937.\nC\nC\nC**********************************************************************\nC**********************************************************************\nC\nC    SUBROUTINE GENPRM( IARRAY, LARRAY )\nC               GENerate random PeRMutation of iarray\nC\nC\nC                              Arguments\nC\nC\nC     IARRAY <--> On output IARRAY is a random permutation of its\nC                 value on input\nC                         INTEGER IARRAY( LARRAY )\nC\nC     LARRAY <--> Length of IARRAY\nC                         INTEGER LARRAY\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION GENUNF( LOW, HIGH )\nC\nC               GeNerate Uniform Real between LOW and HIGH\nC\nC\nC                              Function\nC\nC\nC     Generates a real uniformly distributed between LOW and HIGH.\nC\nC\nC                              Arguments\nC\nC\nC     LOW --> Low bound (exclusive) on real value to be generated\nC                         REAL LOW\nC\nC     HIGH --> High bound (exclusive) on real value to be generated\nC                         REAL HIGH\nC\nC**********************************************************************\nC**********************************************************************\nC\nC      SUBROUTINE GETCGN(G)\nC                         Get GeNerator\nC\nC     Returns in G the number of the current random number generator\nC\nC\nC                              Arguments\nC\nC\nC     G <-- Number of the current random number generator (1..32)\nC                    INTEGER G\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE GETSD(ISEED1,ISEED2)\nC               GET SeeD\nC\nC     Returns the value of two integer seeds of the current generator\nC\nC     This  is   a  transcription from  Pascal   to  Fortran  of routine\nC     Get_State from the paper\nC\nC     L'Ecuyer, P. and  Cote,  S. \"Implementing a Random Number  Package\nC     with   Splitting Facilities.\"  ACM  Transactions   on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC\nC     ISEED1 <- First integer seed of generator G\nC                                   INTEGER ISEED1\nC\nC     ISEED2 <- Second integer seed of generator G\nC                                   INTEGER ISEED1\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNBIN( N, P )\nC\nC                    GENerate BINomial random deviate\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from a binomial\nC     distribution whose number of trials is N and whose\nC     probability of an event in each trial is P.\nC\nC\nC                              Arguments\nC\nC\nC     N  --> The number of trials in the binomial distribution\nC            from which a random deviate is to be generated.\nC                              INTEGER N\nC                              (N >= 0)\nC\nC     P  --> The probability of an event in each trial of the\nC            binomial distribution from which a random deviate\nC            is to be generated.\nC                              REAL P\nC                              (0.0 <= P <= 1.0)\nC\nC     IGNBIN <-- A random deviate yielding the number of events\nC                from N independent trials, each of which has\nC                a probability of event P.\nC                              INTEGER IGNBIN\nC\nC\nC                              Note\nC\nC\nC     Uses RANF so the value of the seeds, ISEED1 and ISEED2 must be set\nC     by a call similar to the following\nC          DUM = RANSET( ISEED1, ISEED2 )\nC\nC\nC                              Method\nC\nC\nC     This is algorithm BTPE from:\nC\nC         Kachitvichyanukul, V. and Schmeiser, B. W.\nC\nC         Binomial Random Variate Generation.\nC         Communications of the ACM, 31, 2\nC         (February, 1988) 216.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNNBN( N, P )\nC\nC                GENerate Negative BiNomial random deviate\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from a negative binomial\nC     distribution.\nC\nC\nC                              Arguments\nC\nC\nC     N  --> Required number of events.\nC                              INTEGER N\nC                              (N > 0)\nC\nC     P  --> The probability of an event during a Bernoulli trial.\nC                              REAL P\nC                              (0.0 < P < 1.0)\nC\nC\nC\nC                              Method\nC\nC\nC     Algorithm from page 480 of\nC\nC     Devroye, Luc\nC\nC     Non-Uniform Random Variate Generation.  Springer-Verlag,\nC     New York, 1986.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNLGI()\nC               GeNerate LarGe Integer\nC\nC     Returns a random integer following a uniform distribution over\nC     (1, 2147483562) using the current generator.\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Random from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNPOI( MU )\nC\nC                    GENerate POIsson random deviate\nC\nC\nC                              Function\nC\nC\nC     Generates a single random deviate from a Poisson\nC     distribution with mean MU.\nC\nC\nC                              Arguments\nC\nC\nC     MU --> The mean of the Poisson distribution from which\nC            a random deviate is to be generated.\nC                              REAL MU\nC                            (MU >= 0.0)\nC\nC     IGNPOI <-- The random deviate.\nC                              REAL IGNPOI (non-negative)\nC\nC\nC                              Method\nC\nC\nC     Renames KPOIS from TOMS as slightly modified by BWB to use RANF\nC     instead of SUNIF.\nC\nC     For details see:\nC\nC               Ahrens, J.H. and Dieter, U.\nC               Computer Generation of Poisson Deviates\nC               From Modified Normal Distributions.\nC               ACM Trans. Math. Software, 8, 2\nC               (June 1982),163-179\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION IGNUIN( LOW, HIGH )\nC\nC               GeNerate Uniform INteger\nC\nC\nC                              Function\nC\nC\nC     Generates an integer uniformly distributed between LOW and HIGH.\nC\nC\nC                              Arguments\nC\nC\nC     LOW --> Low bound (inclusive) on integer value to be generated\nC                         INTEGER LOW\nC\nC     HIGH --> High bound (inclusive) on integer value to be generated\nC                         INTEGER HIGH\nC\nC\nC                              Note\nC\nC\nC     If (HIGH-LOW) > 2,147,483,561 prints error message on * unit and\nC     stops the program.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE INITGN(ISDTYP)\nC          INIT-ialize current G-e-N-erator\nC\nC     Reinitializes the state of the current generator\nC          ISDTYP = -1  => sets the state to its initial seed\nC          ISDTYP =  0  => sets the state to its last (previous) seed\nC          ISDTYP =  1  => sets the state to a new seed 2^w values\nC                              from its last seed\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Init_Generator from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     ISDTYP -> The state to which the generator is to be set\nC\nC                                   INTEGER ISDTYP\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE INRGCM()\nC          INitialize Random number Generator CoMmon\nC\nC\nC                              Function\nC\nC\nC     Initializes common area  for random number  generator.  This saves\nC     the  nuisance  of  a  BLOCK DATA  routine  and the  difficulty  of\nC     assuring that the routine is loaded with the other routines.\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     INTEGER FUNCTION MLTMOD(A,S,M)\nC\nC                    Returns (A*S) MOD M\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     MULtMod_Decompos from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     A, S, M  -->\nC                         INTEGER A,S,M\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE PHRTSD( PHRASE, SEED1, SEED2 )\nC               PHRase To SeeDs\nC\nC\nC                              Function\nC\nC\nC     Uses a phrase (character string) to generate two seeds for the RGN\nC     random number generator.\nC\nC\nC                              Arguments\nC\nC\nC     PHRASE --> Phrase to be used for random number generation\nC                         CHARACTER*(*) PHRASE\nC\nC     SEED1 <-- First seed for RGN generator\nC                         INTEGER SEED1\nC\nC     SEED2 <-- Second seed for RGN generator\nC                         INTEGER SEED2\nC\nC\nC                              Note\nC\nC\nC     Trailing blanks are eliminated before the seeds are generated.\nC\nC     Generated seed values will fall in the range 1..2^30\nC     (1..1,073,741,824)\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     REAL FUNCTION RANF()\nC                RANDom number generator as a Function\nC\nC     Returns a random floating point number from a uniform distribution\nC     over 0 - 1 (endpoints of this interval are not returned) using the\nC     current generator\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Uniform_01 from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC**********************************************************************\nC**********************************************************************\nC\nC      SUBROUTINE SETALL(ISEED1,ISEED2)\nC               SET ALL random number generators\nC\nC     Sets the initial seed of generator 1 to ISEED1 and ISEED2. The\nC     initial seeds of the other generators are set accordingly, and\nC     all generators states are set to these seeds.\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Set_Initial_Seed from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     ISEED1 -> First of two integer seeds\nC                                   INTEGER ISEED1\nC\nC     ISEED2 -> Second of two integer seeds\nC                                   INTEGER ISEED1\nC\nC**********************************************************************\nC**********************************************************************\nC\nC      SUBROUTINE SETANT(QVALUE)\nC               SET ANTithetic\nC\nC     Sets whether the current generator produces antithetic values.  If\nC     X   is  the value  normally returned  from  a uniform [0,1] random\nC     number generator then 1  - X is the antithetic  value. If X is the\nC     value  normally  returned  from a   uniform  [0,N]  random  number\nC     generator then N - 1 - X is the antithetic value.\nC\nC     All generators are initialized to NOT generate antithetic values.\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Set_Antithetic from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     QVALUE -> .TRUE. if generator G is to generating antithetic\nC                    values, otherwise .FALSE.\nC                                   LOGICAL QVALUE\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE SETCGN( G )\nC                      Set GeNerator\nC\nC     Sets  the  current  generator to G.    All references to a generato\nC     are to the current generator.\nC\nC\nC                              Arguments\nC\nC\nC     G --> Number of the current random number generator (1..32)\nC                    INTEGER G\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE SETGMN( MEANV, COVM, LDCOVM, P, PARM)\nC            SET Generate Multivariate Normal random deviate\nC\nC\nC                              Function\nC\nC\nC      Places P, MEANV, and the Cholesky factoriztion of COVM\nC      in PARM for GENMN.\nC\nC\nC                              Arguments\nC\nC\nC     MEANV --> Mean vector of multivariate normal distribution.\nC                                        REAL MEANV(P)\nC\nC     COVM   <--> (Input) Covariance   matrix    of  the  multivariate\nC                 normal distribution.  This routine uses only the\nC                 (1:P,1:P) slice of COVM, but needs to know LDCOVM.\nC\nC                 (Output) Destroyed on output\nC                                        REAL COVM(LDCOVM,P)\nC\nC     LDCOVM --> Leading actual dimension of COVM.\nC                                        INTEGER LDCOVM\nC\nC     P     --> Dimension of the normal, or length of MEANV.\nC                                        INTEGER P\nC\nC     PARM <-- Array of parameters needed to generate multivariate\nC                normal deviates (P, MEANV and Cholesky decomposition\nC                of COVM).\nC                1 : 1                - P\nC                2 : P + 1            - MEANV\nC                P+2 : P*(P+3)/2 + 1  - Cholesky decomposition of COVM\nC                                             REAL PARM(P*(P+3)/2 + 1)\nC\nC**********************************************************************\nC**********************************************************************\nC\nC     SUBROUTINE SETSD(ISEED1,ISEED2)\nC               SET S-ee-D of current generator\nC\nC     Resets the initial seed and state of generator g to ISEED1 and\nC     ISEED2. The seeds and states of the other generators  remain\nC     unchanged.\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Set_Seed from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     ISEED1 -> First integer seed\nC                                   INTEGER ISEED1\nC\nC     ISEED2 -> Second integer seed\nC                                   INTEGER ISEED1\nC\nC**********************************************************************\n"
  },
  {
    "path": "liboctave/external/ranlib/ranf.f",
    "content": "      REAL FUNCTION ranf()\nC**********************************************************************\nC\nC     REAL FUNCTION RANF()\nC                RANDom number generator as a Function\nC\nC     Returns a random floating point number from a uniform distribution\nC     over 0 - 1 (endpoints of this interval are not returned) using the\nC     current generator\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Uniform_01 from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC**********************************************************************\nC     .. External Functions ..\n      INTEGER*4 ignlgi\n      EXTERNAL ignlgi\nC     ..\nC     .. Executable Statements ..\nC\nC     4.656613057E-10 is 1/M1  M1 is set in a data statement in IGNLGI\nC      and is currently 2147483563. If M1 changes, change this also.\nC\n      ranf = ignlgi()*4.656613057E-10\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/setall.f",
    "content": "      SUBROUTINE setall(iseed1,iseed2)\nC**********************************************************************\nC\nC      SUBROUTINE SETALL(ISEED1,ISEED2)\nC               SET ALL random number generators\nC\nC     Sets the initial seed of generator 1 to ISEED1 and ISEED2. The\nC     initial seeds of the other generators are set accordingly, and\nC     all generators states are set to these seeds.\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Set_Initial_Seed from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     ISEED1 -> First of two integer seeds\nC                                   INTEGER ISEED1\nC\nC     ISEED2 -> Second of two integer seeds\nC                                   INTEGER ISEED1\nC\nC**********************************************************************\nC     .. Parameters ..\n      INTEGER*4 numg\n      PARAMETER (numg=32)\nC     ..\nC     .. Scalar Arguments ..\n      INTEGER*4 iseed1,iseed2\n      LOGICAL qssd\nC     ..\nC     .. Scalars in Common ..\n      INTEGER*4 a1,a1vw,a1w,a2,a2vw,a2w,m1,m2\nC     ..\nC     .. Arrays in Common ..\n      INTEGER*4 cg1(numg),cg2(numg),ig1(numg),ig2(numg),lg1(numg),\n     +        lg2(numg)\n      LOGICAL qanti(numg)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 g,ocgn\n      LOGICAL qqssd\nC     ..\nC     .. External Functions ..\n      INTEGER*4 mltmod\n      LOGICAL qrgnin\n      EXTERNAL mltmod,qrgnin\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL getcgn,initgn,inrgcm,setcgn\nC     ..\nC     .. Common blocks ..\n      COMMON /globe/m1,m2,a1,a2,a1w,a2w,a1vw,a2vw,ig1,ig2,lg1,lg2,cg1,\n     +       cg2,qanti\nC     ..\nC     .. Save statement ..\n      SAVE /globe/,qqssd\nC     ..\nC     .. Data statements ..\n      DATA qqssd/.FALSE./\nC     ..\nC     .. Executable Statements ..\nC\nC     TELL IGNLGI, THE ACTUAL NUMBER GENERATOR, THAT THIS ROUTINE\nC      HAS BEEN CALLED.\nC\n      qqssd = .TRUE.\n      CALL getcgn(ocgn)\nC\nC     Initialize Common Block if Necessary\nC\n      IF (.NOT. (qrgnin())) CALL inrgcm()\n      ig1(1) = iseed1\n      ig2(1) = iseed2\n      CALL initgn(-1)\n      DO 10,g = 2,numg\n          ig1(g) = mltmod(a1vw,ig1(g-1),m1)\n          ig2(g) = mltmod(a2vw,ig2(g-1),m2)\n          CALL setcgn(g)\n          CALL initgn(-1)\n   10 CONTINUE\n      CALL setcgn(ocgn)\n      RETURN\n\n      ENTRY rgnqsd(qssd)\nC**********************************************************************\nC\nC     SUBROUTINE RGNQSD\nC                    Random Number Generator Query SeeD set?\nC\nC     Returns (LOGICAL) QSSD as .TRUE. if SETALL has been invoked,\nC     otherwise returns .FALSE.\nC\nC**********************************************************************\n      qssd = qqssd\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/setant.f",
    "content": "      SUBROUTINE setant(qvalue)\nC**********************************************************************\nC\nC      SUBROUTINE SETANT(QVALUE)\nC               SET ANTithetic\nC\nC     Sets whether the current generator produces antithetic values.  If\nC     X   is  the value  normally returned  from  a uniform [0,1] random\nC     number generator then 1  - X is the antithetic  value. If X is the\nC     value  normally  returned  from a   uniform  [0,N]  random  number\nC     generator then N - 1 - X is the antithetic value.\nC\nC     All generators are initialized to NOT generate antithetic values.\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Set_Antithetic from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     QVALUE -> .TRUE. if generator G is to generating antithetic\nC                    values, otherwise .FALSE.\nC                                   LOGICAL QVALUE\nC\nC**********************************************************************\nC     .. Parameters ..\n      INTEGER*4 numg\n      PARAMETER (numg=32)\nC     ..\nC     .. Scalar Arguments ..\n      LOGICAL qvalue\nC     ..\nC     .. Scalars in Common ..\n      INTEGER*4 a1,a1vw,a1w,a2,a2vw,a2w,m1,m2\nC     ..\nC     .. Arrays in Common ..\n      INTEGER*4 cg1(numg),cg2(numg),ig1(numg),ig2(numg),lg1(numg),\n     +        lg2(numg)\n      LOGICAL qanti(numg)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 g\nC     ..\nC     .. External Functions ..\n      LOGICAL qrgnin\n      EXTERNAL qrgnin\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL getcgn\nC     ..\nC     .. Common blocks ..\n      COMMON /globe/m1,m2,a1,a2,a1w,a2w,a1vw,a2vw,ig1,ig2,lg1,lg2,cg1,\n     +       cg2,qanti\nC     ..\nC     .. Save statement ..\n      SAVE /globe/\nC     ..\nC     .. Executable Statements ..\nC     Abort unless random number generator initialized\n      IF (qrgnin()) GO TO 10\n      WRITE (*,*) ' SETANT called before random number generator ',\n     +  ' initialized -- abort!'\n      CALL XSTOPX\n     + (' SETANT called before random number generator initialized')\n\n   10 CALL getcgn(g)\n      qanti(g) = qvalue\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/setgmn.f",
    "content": "      SUBROUTINE setgmn(meanv,covm,ldcovm,p,parm)\nC      SUBROUTINE setgmn(meanv,covm,p,parm)\nC     JJV changed this routine to take leading dimension of COVM\nC     JJV argument and pass it to SPOTRF, making it easier to use\nC     JJV if the COVM which is used is contained in a larger matrix\nC     JJV and to make the routine more consistent with LAPACK.\nC     JJV Changes are in comments, declarations, and the call to SPOTRF.\nC**********************************************************************\nC\nC     SUBROUTINE SETGMN( MEANV, COVM, LDCOVM, P, PARM)\nC            SET Generate Multivariate Normal random deviate\nC\nC\nC                              Function\nC\nC\nC      Places P, MEANV, and the Cholesky factoriztion of COVM\nC      in PARM for GENMN.\nC\nC\nC                              Arguments\nC\nC\nC     MEANV --> Mean vector of multivariate normal distribution.\nC                                        REAL MEANV(P)\nC\nC     COVM   <--> (Input) Covariance   matrix    of  the  multivariate\nC                 normal distribution.  This routine uses only the\nC                 (1:P,1:P) slice of COVM, but needs to know LDCOVM.\nC\nC                 (Output) Destroyed on output\nC                                        REAL COVM(LDCOVM,P)\nC\nC     LDCOVM --> Leading actual dimension of COVM.\nC                                        INTEGER LDCOVM\nC\nC     P     --> Dimension of the normal, or length of MEANV.\nC                                        INTEGER P\nC\nC     PARM <-- Array of parameters needed to generate multivariate\nC                normal deviates (P, MEANV and Cholesky decomposition\nC                of COVM).\nC                1 : 1                - P\nC                2 : P + 1            - MEANV\nC                P+2 : P*(P+3)/2 + 1  - Cholesky decomposition of COVM\nC                                             REAL PARM(P*(P+3)/2 + 1)\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\nC      INTEGER p\n      INTEGER*4 p, ldcovm\nC     ..\nC     .. Array Arguments ..\nC      REAL covm(p,p),meanv(p),parm(p* (p+3)/2+1)\n      REAL covm(ldcovm,p),meanv(p),parm(p* (p+3)/2+1)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 i,icount,info,j\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL spotrf\nC     ..\nC     .. Executable Statements ..\nC\nC\nC     TEST THE INPUT\nC\n      IF (.NOT. (p.LE.0)) GO TO 10\n      WRITE (*,*) 'P nonpositive in SETGMN'\n      WRITE (*,*) 'Value of P: ',p\n      CALL XSTOPX ('P nonpositive in SETGMN')\n\n   10 parm(1) = p\nC\nC     PUT P AND MEANV INTO PARM\nC\n      DO 20,i = 2,p + 1\n          parm(i) = meanv(i-1)\n   20 CONTINUE\nC\nC      Cholesky decomposition to find A s.t. trans(A)*(A) = COVM\nC\nC      CALL spofa(covm,p,p,info)\nC      CALL spofa(covm,ldcovm,p,info)\n      CALL spotrf ( 'Upper', p, covm, ldcovm, info)\n      IF (.NOT. (info.NE.0)) GO TO 30\n      WRITE (*,*) ' COVM not positive definite in SETGMN'\n      CALL XSTOPX (' COVM not positive definite in SETGMN')\n\n   30 icount = p + 1\nC\nC     PUT UPPER HALF OF A, WHICH IS NOW THE CHOLESKY FACTOR, INTO PARM\nC          COVM(1,1) = PARM(P+2)\nC          COVM(1,2) = PARM(P+3)\nC                    :\nC          COVM(1,P) = PARM(2P+1)\nC          COVM(2,2) = PARM(2P+2)  ...\nC\n      DO 50,i = 1,p\n          DO 40,j = i,p\n              icount = icount + 1\n              parm(icount) = covm(i,j)\n   40     CONTINUE\n   50 CONTINUE\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/setsd.f",
    "content": "      SUBROUTINE setsd(iseed1,iseed2)\nC**********************************************************************\nC\nC     SUBROUTINE SETSD(ISEED1,ISEED2)\nC               SET S-ee-D of current generator\nC\nC     Resets the initial  seed of  the current  generator to  ISEED1 and\nC     ISEED2. The seeds of the other generators remain unchanged.\nC\nC     This is a transcription from Pascal to Fortran of routine\nC     Set_Seed from the paper\nC\nC     L'Ecuyer, P. and Cote, S. \"Implementing a Random Number Package\nC     with Splitting Facilities.\" ACM Transactions on Mathematical\nC     Software, 17:98-111 (1991)\nC\nC\nC                              Arguments\nC\nC\nC     ISEED1 -> First integer seed\nC                                   INTEGER ISEED1\nC\nC     ISEED2 -> Second integer seed\nC                                   INTEGER ISEED1\nC\nC**********************************************************************\nC     .. Parameters ..\n      INTEGER*4 numg\n      PARAMETER (numg=32)\nC     ..\nC     .. Scalar Arguments ..\n      INTEGER*4 iseed1,iseed2\nC     ..\nC     .. Scalars in Common ..\n      INTEGER*4 a1,a1vw,a1w,a2,a2vw,a2w,m1,m2\nC     ..\nC     .. Arrays in Common ..\n      INTEGER*4 cg1(numg),cg2(numg),ig1(numg),ig2(numg),lg1(numg),\n     +        lg2(numg)\n      LOGICAL qanti(numg)\nC     ..\nC     .. Local Scalars ..\n      INTEGER*4 g\nC     ..\nC     .. External Functions ..\n      LOGICAL qrgnin\n      EXTERNAL qrgnin\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL getcgn,initgn\nC     ..\nC     .. Common blocks ..\n      COMMON /globe/m1,m2,a1,a2,a1w,a2w,a1vw,a2vw,ig1,ig2,lg1,lg2,cg1,\n     +       cg2,qanti\nC     ..\nC     .. Save statement ..\n      SAVE /globe/\nC     ..\nC     .. Executable Statements ..\nC     Abort unless random number generator initialized\n      IF (qrgnin()) GO TO 10\n      WRITE (*,*) ' SETSD called before random number generator ',\n     +  ' initialized -- abort!'\n      CALL XSTOPX\n     + (' SETSD called before random number generator initialized')\n\n   10 CALL getcgn(g)\n      ig1(g) = iseed1\n      ig2(g) = iseed2\n      CALL initgn(-1)\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/sexpo.f",
    "content": "      REAL FUNCTION sexpo()\nC**********************************************************************C\nC                                                                      C\nC                                                                      C\nC     (STANDARD-)  E X P O N E N T I A L   DISTRIBUTION                C\nC                                                                      C\nC                                                                      C\nC**********************************************************************C\nC**********************************************************************C\nC                                                                      C\nC     FOR DETAILS SEE:                                                 C\nC                                                                      C\nC               AHRENS, J.H. AND DIETER, U.                            C\nC               COMPUTER METHODS FOR SAMPLING FROM THE                 C\nC               EXPONENTIAL AND NORMAL DISTRIBUTIONS.                  C\nC               COMM. ACM, 15,10 (OCT. 1972), 873 - 882.               C\nC                                                                      C\nC     ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM       C\nC     'SA' IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION)       C\nC                                                                      C\nC     Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of   C\nC     SUNIF.  The argument IR thus goes away.                          C\nC                                                                      C\nC**********************************************************************C\nC\nC\nC     Q(N) = SUM(ALOG(2.0)**K/K!)    K=1,..,N ,      THE HIGHEST N\nC     (HERE 8) IS DETERMINED BY Q(N)=1.0 WITHIN STANDARD PRECISION\nC\nC     JJV added a Save statement for q (in Data statement)\nC     .. Local Scalars ..\n      REAL a,q1,u,umin,ustar\n      INTEGER*4 i\nC     ..\nC     .. Local Arrays ..\n      REAL q(8)\nC     ..\nC     .. External Functions ..\n      REAL ranf\n      EXTERNAL ranf\nC     ..\nC     .. Equivalences ..\n      EQUIVALENCE (q(1),q1)\nC     ..\nC     .. Save statement ..\n      SAVE q\nC     ..\nC     .. Data statements ..\n      DATA q/.6931472,.9333737,.9888778,.9984959,.9998293,.9999833,\n     +     .9999986,.9999999/\nC     ..\nC\n   10 a = 0.0\n      u = ranf()\n      GO TO 30\n\n   20 a = a + q1\n   30 u = u + u\nC     JJV changed the following to reflect the true algorithm and\nC     JJV prevent unpredictable behavior if U is initially 0.5.\nC      IF (u.LE.1.0) GO TO 20\n      IF (u.LT.1.0) GO TO 20\n   40 u = u - 1.0\n      IF (u.GT.q1) GO TO 60\n   50 sexpo = a + u\n      RETURN\n\n   60 i = 1\n      ustar = ranf()\n      umin = ustar\n   70 ustar = ranf()\n      IF (ustar.LT.umin) umin = ustar\n   80 i = i + 1\n      IF (u.GT.q(i)) GO TO 70\n   90 sexpo = a + umin*q1\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/sgamma.f",
    "content": "      REAL FUNCTION sgamma(a)\nC**********************************************************************C\nC                                                                      C\nC                                                                      C\nC     (STANDARD-)  G A M M A  DISTRIBUTION                             C\nC                                                                      C\nC                                                                      C\nC**********************************************************************C\nC**********************************************************************C\nC                                                                      C\nC               PARAMETER  A >= 1.0  !                                 C\nC                                                                      C\nC**********************************************************************C\nC                                                                      C\nC     FOR DETAILS SEE:                                                 C\nC                                                                      C\nC               AHRENS, J.H. AND DIETER, U.                            C\nC               GENERATING GAMMA VARIATES BY A                         C\nC               MODIFIED REJECTION TECHNIQUE.                          C\nC               COMM. ACM, 25,1 (JAN. 1982), 47 - 54.                  C\nC                                                                      C\nC     STEP NUMBERS CORRESPOND TO ALGORITHM 'GD' IN THE ABOVE PAPER     C\nC                                 (STRAIGHTFORWARD IMPLEMENTATION)     C\nC                                                                      C\nC     Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of   C\nC     SUNIF.  The argument IR thus goes away.                          C\nC                                                                      C\nC**********************************************************************C\nC                                                                      C\nC               PARAMETER  0.0 < A < 1.0  !                            C\nC                                                                      C\nC**********************************************************************C\nC                                                                      C\nC     FOR DETAILS SEE:                                                 C\nC                                                                      C\nC               AHRENS, J.H. AND DIETER, U.                            C\nC               COMPUTER METHODS FOR SAMPLING FROM GAMMA,              C\nC               BETA, POISSON AND BINOMIAL DISTRIBUTIONS.              C\nC               COMPUTING, 12 (1974), 223 - 246.                       C\nC                                                                      C\nC     (ADAPTED IMPLEMENTATION OF ALGORITHM 'GS' IN THE ABOVE PAPER)    C\nC                                                                      C\nC**********************************************************************C\nC\nC\nC     INPUT: A =PARAMETER (MEAN) OF THE STANDARD GAMMA DISTRIBUTION\nC     OUTPUT: SGAMMA = SAMPLE FROM THE GAMMA-(A)-DISTRIBUTION\nC\nC     COEFFICIENTS Q(K) - FOR Q0 = SUM(Q(K)*A**(-K))\nC     COEFFICIENTS A(K) - FOR Q = Q0+(T*T/2)*SUM(A(K)*V**K)\nC     COEFFICIENTS E(K) - FOR EXP(Q)-1 = SUM(E(K)*Q**K)\nC\nC     .. Scalar Arguments ..\n      REAL a\nC     ..\nC     .. Local Scalars .. (JJV added B0 to fix rare and subtle bug)\n      REAL a1,a2,a3,a4,a5,a6,a7,aa,aaa,b,b0,c,d,e,e1,e2,e3,e4,e5,p,q,q0,\n     +     q1,q2,q3,q4,q5,q6,q7,r,s,s2,si,sqrt32,t,u,v,w,x\nC     ..\nC     .. External Functions ..\n      REAL ranf,sexpo,snorm\n      EXTERNAL ranf,sexpo,snorm\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC abs,alog,exp,sign,sqrt\nC     ..\nC     .. Save statement ..\nC     JJV added Save statement for vars in Data satatements\n      SAVE aa,aaa,s2,s,d,q0,b,si,c,q1,q2,q3,q4,q5,q6,q7,a1,a2,a3,a4,a5,\n     +     a6,a7,e1,e2,e3,e4,e5,sqrt32\nC     ..\nC     .. Data statements ..\nC\nC     PREVIOUS A PRE-SET TO ZERO - AA IS A', AAA IS A\"\nC     SQRT32 IS THE SQUAREROOT OF 32 = 5.656854249492380\nC\n      DATA q1,q2,q3,q4,q5,q6,q7/.04166669,.02083148,.00801191,.00144121,\n     +     -.00007388,.00024511,.00024240/\n      DATA a1,a2,a3,a4,a5,a6,a7/.3333333,-.2500030,.2000062,-.1662921,\n     +     .1423657,-.1367177,.1233795/\n      DATA e1,e2,e3,e4,e5/1.,.4999897,.1668290,.0407753,.0102930/\n      DATA aa/0.0/,aaa/0.0/,sqrt32/5.656854/\nC     ..\nC     .. Executable Statements ..\nC\n      IF (a.EQ.aa) GO TO 10\n      IF (a.LT.1.0) GO TO 130\nC\nC     STEP  1:  RECALCULATIONS OF S2,S,D IF A HAS CHANGED\nC\n      aa = a\n      s2 = a - 0.5\n      s = sqrt(s2)\n      d = sqrt32 - 12.0*s\nC\nC     STEP  2:  T=STANDARD NORMAL DEVIATE,\nC               X=(S,1/2)-NORMAL DEVIATE.\nC               IMMEDIATE ACCEPTANCE (I)\nC\n   10 t = snorm()\n      x = s + 0.5*t\n      sgamma = x*x\n      IF (t.GE.0.0) RETURN\nC\nC     STEP  3:  U= 0,1 -UNIFORM SAMPLE. SQUEEZE ACCEPTANCE (S)\nC\n      u = ranf()\n      IF (d*u.LE.t*t*t) RETURN\nC\nC     STEP  4:  RECALCULATIONS OF Q0,B,SI,C IF NECESSARY\nC\n      IF (a.EQ.aaa) GO TO 40\n      aaa = a\n      r = 1.0/a\n      q0 = ((((((q7*r+q6)*r+q5)*r+q4)*r+q3)*r+q2)*r+q1)*r\nC\nC               APPROXIMATION DEPENDING ON SIZE OF PARAMETER A\nC               THE CONSTANTS IN THE EXPRESSIONS FOR B, SI AND\nC               C WERE ESTABLISHED BY NUMERICAL EXPERIMENTS\nC\n      IF (a.LE.3.686) GO TO 30\n      IF (a.LE.13.022) GO TO 20\nC\nC               CASE 3:  A .GT. 13.022\nC\n      b = 1.77\n      si = .75\n      c = .1515/s\n      GO TO 40\nC\nC               CASE 2:  3.686 .LT. A .LE. 13.022\nC\n   20 b = 1.654 + .0076*s2\n      si = 1.68/s + .275\n      c = .062/s + .024\n      GO TO 40\nC\nC               CASE 1:  A .LE. 3.686\nC\n   30 b = .463 + s + .178*s2\n      si = 1.235\n      c = .195/s - .079 + .16*s\nC\nC     STEP  5:  NO QUOTIENT TEST IF X NOT POSITIVE\nC\n   40 IF (x.LE.0.0) GO TO 70\nC\nC     STEP  6:  CALCULATION OF V AND QUOTIENT Q\nC\n      v = t/ (s+s)\n      IF (abs(v).LE.0.25) GO TO 50\n      q = q0 - s*t + 0.25*t*t + (s2+s2)*alog(1.0+v)\n      GO TO 60\n\n   50 q = q0 + 0.5*t*t* ((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v\nC\nC     STEP  7:  QUOTIENT ACCEPTANCE (Q)\nC\n   60 IF (alog(1.0-u).LE.q) RETURN\nC\nC     STEP  8:  E=STANDARD EXPONENTIAL DEVIATE\nC               U= 0,1 -UNIFORM DEVIATE\nC               T=(B,SI)-DOUBLE EXPONENTIAL (LAPLACE) SAMPLE\nC\n   70 e = sexpo()\n      u = ranf()\n      u = u + u - 1.0\n      t = b + sign(si*e,u)\nC\nC     STEP  9:  REJECTION IF T .LT. TAU(1) = -.71874483771719\nC\n   80 IF (t.LT. (-.7187449)) GO TO 70\nC\nC     STEP 10:  CALCULATION OF V AND QUOTIENT Q\nC\n      v = t/ (s+s)\n      IF (abs(v).LE.0.25) GO TO 90\n      q = q0 - s*t + 0.25*t*t + (s2+s2)*alog(1.0+v)\n      GO TO 100\n\n   90 q = q0 + 0.5*t*t* ((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v\nC\nC     STEP 11:  HAT ACCEPTANCE (H) (IF Q NOT POSITIVE GO TO STEP 8)\nC\n  100 IF (q.LE.0.0) GO TO 70\n      IF (q.LE.0.5) GO TO 110\nC\nC     JJV modified the code through line 125 to handle large Q case\nC\n      IF (q.LT.15.0) GO TO 105\nC\nC     JJV Here Q is large enough that Q = log(exp(Q) - 1.0) (for real Q)\nC     JJV so reformulate test at 120 in terms of one EXP, if not too big\nC     JJV 87.49823 is close to the largest real which can be\nC     JJV exponentiated (87.49823 = log(1.0E38))\nC\n      IF ((q+e-0.5*t*t).GT.87.49823) GO TO 125\n      IF (c*abs(u).GT.exp(q+e-0.5*t*t)) GO TO 70\n      GO TO 125\n\n 105  w = exp(q) - 1.0\n      GO TO 120\n\n  110 w = ((((e5*q+e4)*q+e3)*q+e2)*q+e1)*q\nC\nC               IF T IS REJECTED, SAMPLE AGAIN AT STEP 8\nC\n  120 IF (c*abs(u).GT.w*exp(e-0.5*t*t)) GO TO 70\n 125  x = s + 0.5*t\n      sgamma = x*x\n      RETURN\nC\nC     ALTERNATE METHOD FOR PARAMETERS A BELOW 1  (.3678794=EXP(-1.))\nC\nC     JJV changed B to B0 (which was added to declarations for this)\nC     JJV in 130 to END to fix rare and subtle bug.\nC     JJV Line: '130 aa = 0.0' was removed (unnecessary, wasteful).\nC     JJV Reasons: the state of AA only serves to tell the A .GE. 1.0\nC     JJV case if certain A-dependant constants need to be recalculated.\nC     JJV The A .LT. 1.0 case (here) no longer changes any of these, and\nC     JJV the recalculation of B (which used to change with an\nC     JJV A .LT. 1.0 call) is governed by the state of AAA anyway.\nC\n 130  b0 = 1.0 + .3678794*a\n  140 p = b0*ranf()\n      IF (p.GE.1.0) GO TO 150\n      sgamma = exp(alog(p)/a)\n      IF (sexpo().LT.sgamma) GO TO 140\n      RETURN\n\n  150 sgamma = -alog((b0-p)/a)\n      IF (sexpo().LT. (1.0-a)*alog(sgamma)) GO TO 140\n      RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/snorm.f",
    "content": "      REAL FUNCTION snorm()\nC**********************************************************************C\nC                                                                      C\nC                                                                      C\nC     (STANDARD-)  N O R M A L  DISTRIBUTION                           C\nC                                                                      C\nC                                                                      C\nC**********************************************************************C\nC**********************************************************************C\nC                                                                      C\nC     FOR DETAILS SEE:                                                 C\nC                                                                      C\nC               AHRENS, J.H. AND DIETER, U.                            C\nC               EXTENSIONS OF FORSYTHE'S METHOD FOR RANDOM             C\nC               SAMPLING FROM THE NORMAL DISTRIBUTION.                 C\nC               MATH. COMPUT., 27,124 (OCT. 1973), 927 - 937.          C\nC                                                                      C\nC     ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM 'FL'  C\nC     (M=5) IN THE ABOVE PAPER     (SLIGHTLY MODIFIED IMPLEMENTATION)  C\nC                                                                      C\nC     Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of   C\nC     SUNIF.  The argument IR thus goes away.                          C\nC                                                                      C\nC**********************************************************************C\nC\nC\nC     THE DEFINITIONS OF THE CONSTANTS A(K), D(K), T(K) AND\nC     H(K) ARE ACCORDING TO THE ABOVEMENTIONED ARTICLE\nC\nC     .. Local Scalars ..\n      REAL aa,s,tt,u,ustar,w,y\n      INTEGER*4 i\nC     ..\nC     .. Local Arrays ..\n      REAL a(32),d(31),h(31),t(31)\nC     ..\nC     .. External Functions ..\n      REAL ranf\n      EXTERNAL ranf\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC float,int\nC     ..\nC     .. Save statement ..\nC     JJV added a Save statement for arrays initialized in Data statmts\n      SAVE a,d,t,h\nC     ..\nC     .. Data statements ..\n      DATA a/0.0,.3917609E-1,.7841241E-1,.1177699,.1573107,.1970991,\n     +     .2372021,.2776904,.3186394,.3601299,.4022501,.4450965,\n     +     .4887764,.5334097,.5791322,.6260990,.6744898,.7245144,\n     +     .7764218,.8305109,.8871466,.9467818,1.009990,1.077516,\n     +     1.150349,1.229859,1.318011,1.417797,1.534121,1.675940,\n     +     1.862732,2.153875/\n      DATA d/5*0.0,.2636843,.2425085,.2255674,.2116342,.1999243,\n     +     .1899108,.1812252,.1736014,.1668419,.1607967,.1553497,\n     +     .1504094,.1459026,.1417700,.1379632,.1344418,.1311722,\n     +     .1281260,.1252791,.1226109,.1201036,.1177417,.1155119,\n     +     .1134023,.1114027,.1095039/\n      DATA t/.7673828E-3,.2306870E-2,.3860618E-2,.5438454E-2,\n     +     .7050699E-2,.8708396E-2,.1042357E-1,.1220953E-1,.1408125E-1,\n     +     .1605579E-1,.1815290E-1,.2039573E-1,.2281177E-1,.2543407E-1,\n     +     .2830296E-1,.3146822E-1,.3499233E-1,.3895483E-1,.4345878E-1,\n     +     .4864035E-1,.5468334E-1,.6184222E-1,.7047983E-1,.8113195E-1,\n     +     .9462444E-1,.1123001,.1364980,.1716886,.2276241,.3304980,\n     +     .5847031/\n      DATA h/.3920617E-1,.3932705E-1,.3950999E-1,.3975703E-1,\n     +     .4007093E-1,.4045533E-1,.4091481E-1,.4145507E-1,.4208311E-1,\n     +     .4280748E-1,.4363863E-1,.4458932E-1,.4567523E-1,.4691571E-1,\n     +     .4833487E-1,.4996298E-1,.5183859E-1,.5401138E-1,.5654656E-1,\n     +     .5953130E-1,.6308489E-1,.6737503E-1,.7264544E-1,.7926471E-1,\n     +     .8781922E-1,.9930398E-1,.1155599,.1404344,.1836142,.2790016,\n     +     .7010474/\nC     ..\nC     .. Executable Statements ..\nC\n   10 u = ranf()\n      s = 0.0\n      IF (u.GT.0.5) s = 1.0\n      u = u + u - s\n   20 u = 32.0*u\n      i = int(u)\n      IF (i.EQ.32) i = 31\n      IF (i.EQ.0) GO TO 100\nC\nC                                START CENTER\nC\n   30 ustar = u - float(i)\n      aa = a(i)\n   40 IF (ustar.LE.t(i)) GO TO 60\n      w = (ustar-t(i))*h(i)\nC\nC                                EXIT   (BOTH CASES)\nC\n   50 y = aa + w\n      snorm = y\n      IF (s.EQ.1.0) snorm = -y\n      RETURN\nC\nC                                CENTER CONTINUED\nC\n   60 u = ranf()\n      w = u* (a(i+1)-aa)\n      tt = (0.5*w+aa)*w\n      GO TO 80\n\n   70 tt = u\n      ustar = ranf()\n   80 IF (ustar.GT.tt) GO TO 50\n   90 u = ranf()\n      IF (ustar.GE.u) GO TO 70\n      ustar = ranf()\n      GO TO 40\nC\nC                                START TAIL\nC\n  100 i = 6\n      aa = a(32)\n      GO TO 120\n\n  110 aa = aa + d(i)\n      i = i + 1\n  120 u = u + u\n      IF (u.LT.1.0) GO TO 110\n  130 u = u - 1.0\n  140 w = u*d(i)\n      tt = (0.5*w+aa)*w\n      GO TO 160\n\n  150 tt = u\n  160 ustar = ranf()\n      IF (ustar.GT.tt) GO TO 50\n  170 u = ranf()\n      IF (ustar.GE.u) GO TO 150\n      u = ranf()\n      GO TO 140\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/tstbot.for",
    "content": "      PROGRAM tstbot\nC**********************************************************************\nC\nC     A test program for the bottom level routines\nC\nC**********************************************************************\nC     Set up the random number generator\nC     .. Local Scalars ..\n      INTEGER ians,iblock,igen,iseed1,iseed2,itmp,ix,ixgen,nbad\nC     ..\nC     .. Local Arrays ..\n      INTEGER answer(10000),genlst(5)\nC     ..\nC     .. External Functions ..\n      INTEGER ignlgi\n      EXTERNAL ignlgi\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL getsd,initgn,setall,setcgn\nC     ..\nC     .. Data statements ..\n      DATA genlst/1,5,10,20,32/\nC     ..\nC     .. Executable Statements ..\n      nbad = 0\n      WRITE (*,9000)\n\n 9000 FORMAT (' For five virual generators of the 32'/\n     +       ' This test generates 10000 numbers then resets the block'/\n     +       '      and does it again'/\n     +       ' Any disagreements are reported -- there should be none'/)\nC\nC     Set up Generators\nC\n      CALL setall(12345,54321)\nC\nC     For a selected set of generators\nC\n      DO 60,ixgen = 1,5\n          igen = genlst(ixgen)\n          CALL setcgn(igen)\n          WRITE (*,*) ' Testing generator ',igen\nC\nC     Use 10 blocks\nC\n          CALL initgn(-1)\n          CALL getsd(iseed1,iseed2)\n          DO 20,iblock = 1,10\nC\nC     Generate 1000 numbers\nC\n              DO 10,ians = 1,1000\n                  ix = ians + (iblock-1)*1000\n                  answer(ix) = ignlgi()\n   10         CONTINUE\n              CALL initgn(+1)\n   20     CONTINUE\n          CALL initgn(-1)\nC\nC     Do it again and compare answers\nC\n          CALL getsd(iseed1,iseed2)\nC\nC     Use 10 blocks\nC\n          DO 50,iblock = 1,10\nC\nC     Generate 1000 numbers\nC\n              DO 40,ians = 1,1000\n                  ix = ians + (iblock-1)*1000\nC      ANSWER( IX ) = IGNLGI()\n                  itmp = ignlgi()\n                  IF (.NOT. (itmp.NE.answer(ix))) GO TO 30\n                  WRITE (*,9010) iblock,ians,ix,answer(ix),itmp\n\n 9010             FORMAT (' Disagreement on regeneration of numbers'/\n     +                   ' Block ',I2,' N within Block ',I2,\n     +                   ' Index in answer ',I5/\n     +                   ' Originally Generated ',I10,' Regenerated ',\n     +                   I10)\n\n                  nbad = nbad + 1\n                  IF (nbad.GT.10) STOP ' More than 10 mismatches'\n   30             CONTINUE\n   40         CONTINUE\n              CALL initgn(+1)\n   50     CONTINUE\n          WRITE (*,*) ' Finished testing generator ',igen\n          WRITE (*,*) ' Test completed successfully'\n   60 CONTINUE\n      STOP\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/tstgmn.for",
    "content": "C     JJV changed name to ONECOV to avoid confusion with array COVAR\nC     JJV this was also changed in the body of the function\nC      REAL FUNCTION covar(x,y,n)\n      REAL FUNCTION onecov(x,y,n)\nC     .. Scalar Arguments ..\n      INTEGER n\nC     ..\nC     .. Array Arguments ..\n      REAL x(n),y(n)\nC     ..\nC     .. Local Scalars ..\n      REAL avx,avy,varx,vary,xmax,xmin\n      INTEGER i\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL stat\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC real\nC     ..\nC     .. Executable Statements ..\n      CALL stat(x,n,avx,varx,xmin,xmax)\n      CALL stat(y,n,avy,vary,xmin,xmax)\nC      covar = 0.0\n      onecov = 0.0\n      DO 10,i = 1,n\nC      covar = covar + (x(i)-avx)* (y(i)-avy)\n         onecov = onecov + (x(i)-avx)* (y(i)-avy)\n 10   CONTINUE\nC      covar = covar/real(n-1)\n      onecov = onecov/real(n-1)\n      RETURN\n\n      END\n\nC     JJV Added argument LDXCOV (leading dimension of XCOVAR) to be\nC     JJV consistent with the program TSTGMN, see comments below.\nC     JJV This change necessitated changes in the declarations.\nC      SUBROUTINE prcomp(p,mean,xcovar,answer)\n      SUBROUTINE prcomp(p,mean,xcovar,ldxcov,answer)\n\nC      INTEGER p,maxp\n      INTEGER p,maxp,ldxcov\n      PARAMETER (maxp=10)\nC      REAL mean(p),xcovar(p,p),rcovar(maxp,maxp)\n      REAL mean(p),xcovar(ldxcov,p),rcovar(maxp,maxp)\n      REAL answer(1000,maxp)\nC     JJV added ONECOV because of name change to function COVAR\nC      REAL rmean(maxp),rvar(maxp)\n      REAL rmean(maxp),rvar(maxp),onecov\n      INTEGER maxobs\n      PARAMETER (maxobs=1000)\n\n      DO 10,i = 1,p\n          CALL stat(answer(1,i),maxobs,rmean(i),rvar(i),dum1,dum2)\n          WRITE (*,*) ' Variable Number',i\n          WRITE (*,*) ' Mean ',mean(i),' Generated ',rmean(i)\n          WRITE (*,*) ' Variance ',xcovar(i,i),' Generated',rvar(i)\n   10 CONTINUE\n      WRITE (*,*) '                   Covariances'\n      DO 30,i = 1,p\n          DO 20,j = 1,i - 1\n              WRITE (*,*) ' I = ',i,' J = ',j\nC     JJV changed COVAR to match new name\nC              rcovar(i,j) = covar(answer(1,i),answer(1,j),maxobs)\n              rcovar(i,j) = onecov(answer(1,i),answer(1,j),maxobs)\n              WRITE (*,*) ' Covariance ',xcovar(i,j),' Generated ',\n     +          rcovar(i,j)\n   20     CONTINUE\n   30 CONTINUE\n      RETURN\n\n      END\n\nC     JJV added LDCOV (leading dimension of COVAR) to be\nC     JJV consistent with the program TSTGMN, see comments below.\nC     JJV This change necessitated changes in the declarations.\nC      SUBROUTINE setcov(p,var,corr,covar)\n      SUBROUTINE setcov(p,var,corr,covar,ldcov)\nC     Set covariance matrix from variance and common correlation\nC     .. Scalar Arguments ..\n      REAL corr\nC      INTEGER p\n      INTEGER p,ldcov\nC     ..\nC     .. Array Arguments ..\nC      REAL covar(p,p),var(p)\n      REAL covar(ldcov,p),var(p)\nC     ..\nC     .. Local Scalars ..\n      INTEGER i,j\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC sqrt\nC     ..\nC     .. Executable Statements ..\n      DO 40,i = 1,p\n          DO 30,j = 1,p\n              IF (.NOT. (i.EQ.j)) GO TO 10\n              covar(i,j) = var(i)\n              GO TO 20\n\n   10         covar(i,j) = corr*sqrt(var(i)*var(j))\n   20         CONTINUE\n   30     CONTINUE\n   40 CONTINUE\n      RETURN\n\n      END\n\n      SUBROUTINE stat(x,n,av,var,xmin,xmax)\nC     .. Scalar Arguments ..\n      REAL av,var,xmax,xmin\n      INTEGER n\nC     ..\nC     .. Array Arguments ..\n      REAL x(n)\nC     ..\nC     .. Local Scalars ..\n      REAL sum\n      INTEGER i\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC real\nC     ..\nC     .. Executable Statements ..\n      xmin = x(1)\n      xmax = x(1)\n      sum = 0.0\n      DO 10,i = 1,n\n          sum = sum + x(i)\n          IF (x(i).LT.xmin) xmin = x(i)\n          IF (x(i).GT.xmax) xmax = x(i)\n   10 CONTINUE\n      av = sum/real(n)\n      sum = 0.0\n      DO 20,i = 1,n\n          sum = sum + (x(i)-av)**2\n   20 CONTINUE\n      var = sum/real(n-1)\n      RETURN\n\n      END\n\n      PROGRAM tstgmn\nC     Test Generation of Multivariate Normal Data\nC     JJV SETGMN was: SUBROUTINE setgmn(meanv,covm,p,parm)\nC     JJV         is: SUBROUTINE setgmn(meanv,covm,ldcovm,p,parm)\nC     JJV So the covariance matrices have been changed to 2-dim'l\nC     JJV matrices, and the additional argument has been added to\nC     JJV the subroutine call.  Additional changes have been made\nC     JJV to reflect this.  (in declarations, the matrix copy routine,\nC     JJV and in subroutine calls.)\nC     .. Parameters ..\n      INTEGER maxp\n      PARAMETER (maxp=10)\n      INTEGER maxobs\n      PARAMETER (maxobs=1000)\nC     JJV this parameter is no longer needed\nC      INTEGER p2\nC      PARAMETER (p2=maxp*maxp)\nC     ..\nC     .. Local Scalars ..\n      REAL corr\n      INTEGER i,iobs,is1,is2,j,p\n      CHARACTER phrase*100\nC     ..\nC     .. Local Arrays ..\nC      REAL answer(1000,maxp),ccovar(p2),covar(p2),mean(maxp),param(500),\nC     +     temp(maxp),var(maxp),work(maxp)\n      REAL answer(1000,maxp),ccovar(maxp,maxp),covar(maxp,maxp),\n     +     mean(maxp),param(500),temp(maxp),var(maxp),work(maxp)\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL genmn,phrtsd,prcomp,setall,setcov,setgmn\nC     ..\nC     .. Executable Statements ..\n      WRITE (*,9000)\n\n 9000 FORMAT (\n     +     ' Tests Multivariate Normal Generator for Up to 10 Variables'\n     +       /\n     +  ' User inputs means, variances, one correlation that is applied'\n     +       /'     to all pairs of variables'/\n     +       ' 1000 multivariate normal deviates are generated'/\n     +     ' Means, variances and covariances are calculated for these.'\n     +       )\n\n   10 WRITE (*,*) 'Enter number of variables for normal generator'\n      READ (*,*) p\n      WRITE (*,*) 'Enter mean vector of length ',p\n      READ (*,*) (mean(i),i=1,p)\n      WRITE (*,*) 'Enter variance vector of length ',p\n      READ (*,*) (var(i),i=1,p)\n      WRITE (*,*) 'Enter correlation of all variables'\n      READ (*,*) corr\nC      CALL setcov(p,var,corr,covar)\n      CALL setcov(p,var,corr,covar,maxp)\n      WRITE (*,*) ' Enter phrase to initialize rn generator'\n      READ (*,'(a)') phrase\n      CALL phrtsd(phrase,is1,is2)\n      CALL setall(is1,is2)\nC      DO 20,i = 1,p2\nC          ccovar(i) = covar(i)\nC 20   CONTINUE\n      DO 25,i = 1,maxp\n         DO 20,j = 1,maxp\n            ccovar(i,j) = covar(i,j)\n 20      CONTINUE\n 25   CONTINUE\nC\nC     Generate Variables\nC\nC      CALL setgmn(mean,ccovar,p,param)\n      CALL setgmn(mean,ccovar,maxp,p,param)\n      DO 40,iobs = 1,maxobs\n          CALL genmn(param,work,temp)\n          DO 30,j = 1,p\n              answer(iobs,j) = work(j)\n   30     CONTINUE\n   40 CONTINUE\nC      CALL prcomp(p,mean,covar,answer)\n      CALL prcomp(p,mean,covar,maxp,answer)\nC\nC     Print Comparison of Generated and Reconstructed Values\nC\n      GO TO 10\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/tstmid.for",
    "content": "      SUBROUTINE stat(x,n,av,var,xmin,xmax)\nC**********************************************************************\nC\nC     SUBROUTINE STAT( X, N, AV, VAR)\nC\nC               compute STATistics\nC\nC\nC                              Function\nC\nC\nC     Computes AVerage and VARiance of array X(N).\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL av,var,xmax,xmin\n      INTEGER n\nC     ..\nC     .. Array Arguments ..\n      REAL x(n)\nC     ..\nC     .. Local Scalars ..\n      REAL sum\n      INTEGER i\nC     ..\nC     .. Intrinsic Functions ..\n      INTRINSIC real\nC     ..\nC     .. Executable Statements ..\n      xmin = x(1)\n      xmax = x(1)\n      sum = 0.0\n      DO 10,i = 1,n\n          sum = sum + x(i)\n          IF (x(i).LT.xmin) xmin = x(i)\n          IF (x(i).GT.xmax) xmax = x(i)\n   10 CONTINUE\n      av = sum/real(n)\n      sum = 0.0\n      DO 20,i = 1,n\n          sum = sum + (x(i)-av)**2\n   20 CONTINUE\n      var = sum/real(n-1)\n      RETURN\n\n      END\n      PROGRAM tstall\n      IMPLICIT LOGICAL (q)\nC     Interactive test for PHRTSD\nC     .. Parameters ..\n      INTEGER mxwh,mxncat\n      PARAMETER (mxwh=15,mxncat=100)\nC     ..\nC     .. Local Scalars ..\n      REAL av,avtr,var,vartr,xmin,xmax,pevt,psum,rtry\n      INTEGER i,is1,is2,itmp,iwhich,j,mxint,nperm,nrep,ntot,ntry,ncat\n      CHARACTER ctype*4,phrase*100\nC     ..\nC     .. Local Arrays ..\n      REAL array(1000),param(3),prob(mxncat)\n      INTEGER iarray(1000),perm(500)\nC     ..\nC     .. External Functions ..\n      REAL genbet,genchi,genf,gennch,gennf,genunf,genexp,gengam,gennor\n      INTEGER ignuin,ignnbn\n      EXTERNAL genbet,genchi,genf,gennch,gennf,genunf,ignuin\nC     ..\nC     .. External Subroutines ..\n      EXTERNAL genprm,phrtsd,setall,stat,trstat,genmul\nC     ..\nC     .. Executable Statements ..\n      WRITE (*,9000)\n\n 9000 FORMAT (' Tests most generators of specific distributions.'/\n     +       ' Generates 1000 deviates: reports mean and variance.'/\n     +       ' Also reports theoretical mean and variance.'/\n     +       ' If theoretical mean or var doesn''t exist prints -1.'/\n     +       ' For permutations, generates one permutation of 1..n'/\n     +       '     and prints it.'/\n     +       ' For uniform integers asks for upper bound, number of'/\n     +       '     replicates per integer in 1..upper bound.'/\n     +       '     Prints table of num times each integer generated.'/\n     +       ' For multinomial asks for number of events to be'/\n     +       '     classified, number of categories in which they'/\n     +       '     are to be classified, and the probabilities that'/\n     +       '     an event will be classified in the categories,'/\n     +       '     for all but the last category.  Prints table of'/\n     +       '     number of events by category, true probability'/\n     +       '     associated with each category, and observed'/\n     +       '     proportion of events in each category.')\nC\nC     Menu for choosing tests\nC\n   10 WRITE (*,9010)\n\n 9010 FORMAT (' Enter number corresponding to choice:'/\n     +       '      (0) Exit this program'/\n     +       '      (1) Generate Chi-Square deviates'/\n     +       '      (2) Generate noncentral Chi-Square deviates'/\n     +       '      (3) Generate F deviates'/\n     +       '      (4) Generate noncentral F  deviates'/\n     +       '      (5) Generate random permutation'/\n     +       '      (6) Generate uniform integers'/\n     +       '      (7) Generate uniform reals'/\n     +       '      (8) Generate beta deviates'/\n     +       '      (9) Generate binomial outcomes'/\n     +       '     (10) Generate Poisson outcomes'/\n     +       '     (11) Generate exponential deviates'/\n     +       '     (12) Generate gamma deviates'/\n     +       '     (13) Generate multinomial outcomes'/\n     +       '     (14) Generate normal deviates'/\n     +       '     (15) Generate negative binomial outcomes'/)\n\n      READ (*,*) iwhich\n      IF (.NOT. (iwhich.LT.0.OR.iwhich.GT.mxwh)) GO TO 20\n      WRITE (*,*) ' Choices are 1..',mxwh,' - try again.'\n      GO TO 10\n\n   20 IF (iwhich.EQ.0) STOP ' Normal termination rn tests'\n      WRITE (*,*) ' Enter phrase to initialize rn generator'\n      READ (*,'(a)') phrase\n      CALL phrtsd(phrase,is1,is2)\n      CALL setall(is1,is2)\n\n      IF ((1).NE. (iwhich)) GO TO 40\nC\nC     Chi-square deviates\nC\n      ctype = 'chis'\n      WRITE (*,*) ' Enter (real) df for the chi-square generation'\n      READ (*,*) param(1)\n      DO 30,i = 1,1000\n          array(i) = genchi(param(1))\n   30 CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n\n 9020 FORMAT (' Mean Generated: ',T30,G15.7,5X,'True:',T60,\n     +       G15.7/' Variance Generated:',T30,G15.7,5X,'True:',T60,\n     +       G15.7/' Minimum: ',T30,G15.7,5X,'Maximum:',T60,G15.7)\n\n      GO TO 420\n\n   40 IF ((2).NE. (iwhich)) GO TO 60\n\nC\nC     Noncentral Chi-square deviates\nC\n      ctype = 'ncch'\n      WRITE (*,*) ' Enter (real) df'\n      WRITE (*,*) '       (real) noncentrality parameter'\n      READ (*,*) param(1),param(2)\n      DO 50,i = 1,1000\n          array(i) = gennch(param(1),param(2))\n   50 CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n   60 IF ((3).NE. (iwhich)) GO TO 80\n\nC\nC     F deviates\nC\n      ctype = 'f'\n      WRITE (*,*) ' Enter (real) df of the numerator'\n      WRITE (*,*) '       (real) df of the denominator'\n      READ (*,*) param(1),param(2)\n      DO 70,i = 1,1000\n          array(i) = genf(param(1),param(2))\n   70 CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n   80 IF ((4).NE. (iwhich)) GO TO 100\n\nC\nC     Noncentral F deviates\nC\n      ctype = 'ncf'\n      WRITE (*,*) ' Enter (real) df of the numerator'\n      WRITE (*,*) '       (real) df of the denominator'\n      WRITE (*,*) '       (real) noncentrality parameter'\n      READ (*,*) param(1),param(2),param(3)\n      DO 90,i = 1,1000\n          array(i) = gennf(param(1),param(2),param(3))\n   90 CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n  100 IF ((5).NE. (iwhich)) GO TO 140\n\nC\nC     Random permutation\nC\n  110 WRITE (*,*) ' Enter size of permutation'\n      READ (*,*) nperm\n      IF (.NOT. (nperm.LT.1.OR.nperm.GT.500)) GO TO 120\n      WRITE (*,*) ' Permutation size must be between 1 and 500 ',\n     +  '- try again!'\n      GO TO 110\n\n  120 WRITE (*,*) '       Random Permutation Generated - Size',nperm\n      DO 130,i = 1,500\n          perm(i) = i\n  130 CONTINUE\n      CALL genprm(perm,nperm)\n      WRITE (*,*) ' Perm Generated'\n      WRITE (*,'(20I4)') (perm(i),i=1,nperm)\n      GO TO 420\n\n  140 IF ((6).NE. (iwhich)) GO TO 170\n\nC\nC     Uniform integer\nC\n      WRITE (*,*) ' Enter maximum uniform integer'\n      READ (*,*) mxint\n      WRITE (*,*) ' Enter number of replications per integer'\n      READ (*,*) nrep\n      DO 150,i = 1,1000\n          iarray(i) = 0\n  150 CONTINUE\n      ntot = mxint*nrep\n      DO 160,i = 1,ntot\n          itmp = ignuin(1,mxint)\n          iarray(itmp) = iarray(itmp) + 1\n  160 CONTINUE\n      WRITE (*,*) '         Counts of Integers Generated'\n      WRITE (*,'(20I4)') (iarray(j),j=1,mxint)\n      GO TO 420\n\n  170 IF ((7).NE. (iwhich)) GO TO 190\n\nC\nC     Uniform real\nC\n      ctype = 'unif'\n      WRITE (*,*) ' Enter Low then High bound for uniforms'\n      READ (*,*) param(1),param(2)\n      DO 180,i = 1,1000\n          array(i) = genunf(param(1),param(2))\n  180 CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n  190 IF ((8).NE. (iwhich)) GO TO 210\n\nC\nC     Beta deviate\nC\n      ctype = 'beta'\n      WRITE (*,*) ' Enter A, B for Beta deviate'\n      READ (*,*) param(1),param(2)\n      DO 200,i = 1,1000\n          array(i) = genbet(param(1),param(2))\n  200 CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n  210 IF ((9).NE. (iwhich)) GO TO 240\n\nC\nC     Binomial outcomes\nC\n      ctype = 'bin'\n      WRITE (*,*) ' Enter number of trials, Prob event for ',\n     +  'binomial outcomes'\n      READ (*,*) ntry,pevt\n      DO 220,i = 1,1000\n          iarray(i) = ignbin(ntry,pevt)\n  220 CONTINUE\n      DO 230,i = 1,1000\n          array(i) = iarray(i)\n  230 CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      param(1) = ntry\n      param(2) = pevt\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n  240 IF ((10).NE. (iwhich)) GO TO 270\n\nC\nC     Poisson outcomes\nC\n      ctype = 'pois'\n      WRITE (*,*) ' Enter mean for Poisson generation'\n      READ (*,*) param(1)\n      DO 250,i = 1,1000\n          iarray(i) = ignpoi(param(1))\n  250 CONTINUE\n      DO 260,i = 1,1000\n          array(i) = iarray(i)\n  260 CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n  270 IF ((11).NE. (iwhich)) GO TO 290\n\nC\nC     Exponential deviates\nC\n      ctype = 'expo'\n      WRITE (*,*) ' Enter (real) AV for Exponential'\n      READ (*,*) param(1)\n      DO 280,i = 1,1000\n          array(i) = genexp(param(1))\n 280   CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n\n      GO TO 420\n\n 290  IF ((12).NE. (iwhich)) GO TO 310\n\nC\nC     Gamma deviates\nC\n      ctype = 'gamm'\n      WRITE (*,*) ' Enter (real) A, (real) R for Gamma deviate'\n      READ (*,*) param(1),param(2)\n      DO 300,i = 1,1000\n          array(i) = gengam(param(1),param(2))\n  300 CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n 310  IF ((13).NE. (iwhich)) GO TO 360\n\nC\nC     Multinomial outcomes\nC\n      WRITE (*,*) ' Enter (int) number of observations: '\n      READ (*,*) ntry\n 320  WRITE (*,*) ' Enter (int) num. of categories: <= ',mxncat\n      READ (*,*) ncat\n      IF (ncat.GT.mxncat) THEN\n         WRITE (*,*) ' number of categories must be <= ',mxncat\n         WRITE (*,*) ' Try again ... '\n         GO TO 320\n      END IF\n      WRITE (*,*) ' Enter (real) prob. vector of length ',ncat-1\n      READ (*,*) (prob(i),i=1,ncat-1)\n      CALL genmul(ntry,prob,ncat,iarray)\n      ntot = 0\n      IF (ntry.GT.0) THEN\n         rtry = real(ntry)\n         DO 330, i = 1,ncat\n            ntot = ntot + iarray(i)\n            array(i) = iarray(i)/rtry\n 330     CONTINUE\n      ELSE\n         DO 340, i = 1,ncat\n            ntot = ntot + iarray(i)\n            array(i) = 0.0\n 340     CONTINUE\n      ENDIF\n      psum = 0.0\n      DO 350, i = 1,ncat-1\n         psum = psum + prob(i)\n 350  CONTINUE\n      prob(ncat) = 1.0 - psum\n\n      WRITE (*,*) ' Total number of observations: ',ntot\n      WRITE (*,*) ' Total observations by category: '\n      WRITE (*,'(10I8)') (iarray(i),i=1,ncat)\n      WRITE (*,*) ' True probabilities by category: '\n      WRITE (*,'(8F10.7)') (prob(i),i=1,ncat)\n      WRITE (*,*) ' Observed proportions by category: '\n      WRITE (*,'(8F10.7)') (array(i),i=1,ncat)\n      GO TO 420\n\n 360  IF ((14).NE. (iwhich)) GO TO 380\n\nC\nC     Normal deviates\nC\n      ctype = 'norm'\n      WRITE (*,*) ' Enter (real) AV, (real) SD for Normal'\n      READ (*,*) param(1),param(2)\n      DO 370,i = 1,1000\n         array(i) = gennor(param(1),param(2))\n 370  CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n 380  IF ((15).NE. (iwhich)) GO TO 410\n\nC\nC     Negative Binomial outcomes\nC\n      ctype = 'nbin'\n      WRITE (*,*) ' Enter required (int) Number of events then '\n      WRITE (*,*) ' (real) Prob of an event for negative binomial'\n      READ (*,*) ntry,pevt\n      DO 390,i = 1,1000\n         iarray(i) = ignnbn(ntry,pevt)\n 390  CONTINUE\n      DO 400,i = 1,1000\n         array(i) = iarray(i)\n 400  CONTINUE\n      CALL stat(array,1000,av,var,xmin,xmax)\n      param(1) = ntry\n      param(2) = pevt\n      CALL trstat(ctype,param,avtr,vartr)\n      WRITE (*,9020) av,avtr,var,vartr,xmin,xmax\n      GO TO 420\n\n 410  CONTINUE\n 420  GO TO 10\n\n      END\n      SUBROUTINE trstat(ctype,parin,av,var)\n      IMPLICIT INTEGER (i-n),REAL (a-h,o-p,r-z),LOGICAL (q)\nC**********************************************************************\nC\nC     SUBROUTINE TRSTAT( TYPE, PARIN, AV, VAR )\nC               TRue STATistics\nC\nC     Returns mean and variance for a number of statistical distribution\nC     as a function of their parameters.\nC\nC\nC                              Arguments\nC\nC\nC     CTYPE --> Character string indicating type of distribution\nC             'chis' chisquare\nC             'ncch' noncentral chisquare\nC             'f'    F (variance ratio)\nC             'ncf'  noncentral f\nC             'unif' uniform\nC             'beta' beta distribution\nC             'bin'  binomial\nC             'pois' poisson\nC             'expo' exponential\nC             'gamm' gamma\nC             'norm' normal\nC             'nbin' negative binomial\nC                         CHARACTER*(4) TYPE\nC\nC     PARIN --> Array containing parameters of distribution\nC              chisquare\nC               PARIN(1) is df\nC              noncentral chisquare\nC               PARIN(1) is df\nC               PARIN(2) is noncentrality parameter\nC              F (variance ratio)\nC               PARIN(1) is df numerator\nC               PARIN(2) is df denominator\nC              noncentral F\nC               PARIN(1) is df numerator\nC               PARIN(2) is df denominator\nC               PARIN(3) is noncentrality parameter\nC              uniform\nC               PARIN(1) is LOW bound\nC               PARIN(2) is HIGH bound\nC              beta\nC               PARIN(1) is A\nC               PARIN(2) is B\nC              binomial\nC               PARIN(1) is Number of trials\nC               PARIN(2) is Prob Event at Each Trial\nC              poisson\nC               PARIN(1) is Mean\nC              exponential\nC               PARIN(1) is Mean\nC              gamma\nC               PARIN(1) is A\nC               PARIN(2) is R\nC              normal\nC               PARIN(1) is Mean\nC               PARIN(2) is Standard Deviation\nC              negative binomial\nC               PARIN(1) is required Number of events\nC               PARIN(2) is Probability of event\nC                         REAL PARIN(*)\nC\nC     AV <-- Mean of specified distribution with specified parameters\nC                         REAL AV\nC\nC     VAR <-- Variance of specified distribution with specified paramete\nC                         REAL VAR\nC\nC\nC                              Note\nC\nC\nC     AV and Var will be returned -1 if mean or variance is infinite\nC\nC**********************************************************************\nC     .. Scalar Arguments ..\n      REAL av,var\n      CHARACTER ctype* (4)\nC     ..\nC     .. Array Arguments ..\n      REAL parin(*)\nC     ..\nC     .. Local Scalars ..\n      REAL a,b,range\nC     ..\nC     .. Executable Statements ..\n      IF (('chis').NE. (ctype)) GO TO 10\n      av = parin(1)\n      var = 2.0*parin(1)\n      GO TO 210\n\n   10 IF (('ncch').NE. (ctype)) GO TO 20\n      a = parin(1) + parin(2)\n      b = parin(2)/a\n      av = a\n      var = 2.0*a* (1.0+b)\n      GO TO 210\n\n   20 IF (('f').NE. (ctype)) GO TO 70\n      IF (.NOT. (parin(2).LE.2.0001)) GO TO 30\n      av = -1.0\n      GO TO 40\n\n   30 av = parin(2)/ (parin(2)-2.0)\n   40 IF (.NOT. (parin(2).LE.4.0001)) GO TO 50\n      var = -1.0\n      GO TO 60\n\n   50 var = (2.0*parin(2)**2* (parin(1)+parin(2)-2.0))/\n     +      (parin(1)* (parin(2)-2.0)**2* (parin(2)-4.0))\n   60 GO TO 210\n\n   70 IF (('ncf').NE. (ctype)) GO TO 120\n      IF (.NOT. (parin(2).LE.2.0001)) GO TO 80\n      av = -1.0\n      GO TO 90\n\n   80 av = (parin(2)* (parin(1)+parin(3)))/ ((parin(2)-2.0)*parin(1))\n   90 IF (.NOT. (parin(2).LE.4.0001)) GO TO 100\n      var = -1.0\n      GO TO 110\n\n  100 a = (parin(1)+parin(3))**2 + (parin(1)+2.0*parin(3))*\n     +    (parin(2)-2.0)\n      b = (parin(2)-2.0)**2* (parin(2)-4.0)\n      var = 2.0* (parin(2)/parin(1))**2* (a/b)\n  110 GO TO 210\n\n  120 IF (('unif').NE. (ctype)) GO TO 130\n      range = parin(2) - parin(1)\n      av = parin(1) + range/2.0\n      var = range**2/12.0\n      GO TO 210\n\n  130 IF (('beta').NE. (ctype)) GO TO 140\n      av = parin(1)/ (parin(1)+parin(2))\n      var = (av*parin(2))/ ((parin(1)+parin(2))*\n     +      (parin(1)+parin(2)+1.0))\n      GO TO 210\n\n  140 IF (('bin').NE. (ctype)) GO TO 150\n      av = parin(1)*parin(2)\n      var = av* (1.0-parin(2))\n      GO TO 210\n\n  150 IF (('pois').NE. (ctype)) GO TO 160\n      av = parin(1)\n      var = parin(1)\n      GO TO 210\n\n 160  IF (('expo').NE. (ctype)) GO TO 170\n      av = parin(1)\n      var = parin(1)**2\n      GO TO 210\n\n 170  IF (('gamm').NE. (ctype)) GO TO 180\n      av = parin(2) / parin(1)\n      var = av / parin(1)\n      GO TO 210\n\n 180  IF (('norm').NE. (ctype)) GO TO 190\n      av = parin(1)\n      var = parin(2)**2\n      GO TO 210\n\n 190  IF (('nbin').NE. (ctype)) GO TO 200\n      av = parin(1) * (1.0 - parin(2)) / parin(2)\n      var = av / parin(2)\n      GO TO 210\n\n  200 WRITE (*,*) 'Unimplemented type ',ctype\n      STOP 'Unimplemented type in TRSTAT'\n\n  210 RETURN\n\n      END\n"
  },
  {
    "path": "liboctave/external/ranlib/wrap.f",
    "content": "      subroutine dgennor (av, sd, result)\n      double precision av, sd, result\n      real gennor\n      external gennor\n      result = gennor (real (av), real (sd))\n      return\n      end\n      subroutine dgenunf (low, high, result)\n      double precision low, high, result\n      real genunf\n      external genunf\n      result = genunf (real (low), real (high))\n      return\n      end\n      subroutine dgenexp (av, result)\n      double precision av, result\n      real genexp\n      external genexp\n      result = genexp (real (av))\n      return\n      end\n      subroutine dgengam (a, r, result)\n      double precision a, r, result\n      real gengam\n      external gengam\n      result = gengam (real (a), real (r))\n      return\n      end\n      subroutine dignpoi (mu, result)\n      double precision mu, result\n      integer*4 ignpoi\n      external ignpoi\n      result = ignpoi (real (mu))\n      return\n      end\n      subroutine fgennor (av, sd, result)\n      real av, sd, result\n      real gennor\n      external gennor\n      result = gennor (av, sd)\n      return\n      end\n      subroutine fgenunf (low, high, result)\n      real low, high, result\n      real genunf\n      external genunf\n      result = genunf (low, high)\n      return\n      end\n      subroutine fgenexp (av, result)\n      real av, result\n      real genexp\n      external genexp\n      result = genexp (av)\n      return\n      end\n      subroutine fgengam (a, r, result)\n      real a, r, result\n      real gengam\n      external gengam\n      result = gengam (a, r)\n      return\n      end\n      subroutine fignpoi (mu, result)\n      real mu, result\n      integer*4 ignpoi\n      external ignpoi\n      result = ignpoi (mu)\n      return\n      end\n"
  },
  {
    "path": "liboctave/external/slatec-err/fdump.f",
    "content": "*DECK FDUMP\n      SUBROUTINE FDUMP\nC***BEGIN PROLOGUE  FDUMP\nC***PURPOSE  Symbolic dump (should be locally written).\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3\nC***TYPE      ALL (FDUMP-A)\nC***KEYWORDS  ERROR, XERMSG\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC        ***Note*** Machine Dependent Routine\nC        FDUMP is intended to be replaced by a locally written\nC        version which produces a symbolic dump.  Failing this,\nC        it should be replaced by a version which prints the\nC        subprogram nesting list.  Note that this dump must be\nC        printed on each of up to five files, as indicated by the\nC        XGETUA routine.  See XSETUA and XGETUA for details.\nC\nC     Written by Ron Jones, with SLATEC Common Math Library Subcommittee\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   790801  DATE WRITTEN\nC   861211  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC***END PROLOGUE  FDUMP\nC***FIRST EXECUTABLE STATEMENT  FDUMP\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/ixsav.f",
    "content": "*DECK IXSAV\n      INTEGER FUNCTION IXSAV (IPAR, IVALUE, ISET)\nC***BEGIN PROLOGUE  IXSAV\nC***SUBSIDIARY\nC***PURPOSE  Save and recall error message control parameters.\nC***LIBRARY   MATHLIB\nC***CATEGORY  R3C\nC***TYPE      ALL (IXSAV-A)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  IXSAV saves and recalls one of two error message parameters:\nC    LUNIT, the logical unit number to which messages are printed, and\nC    MESFLG, the message print flag.\nC  This is a modification of the SLATEC library routine J4SAVE.\nC\nC  Saved local variables..\nC   LUNIT  = Logical unit number for messages.\nC   LUNDEF = Default logical unit number, data-loaded to 6 below\nC            (may be machine-dependent).\nC   MESFLG = Print control flag..\nC            1 means print all messages (the default).\nC            0 means no printing.\nC\nC  On input..\nC    IPAR   = Parameter indicator (1 for LUNIT, 2 for MESFLG).\nC    IVALUE = The value to be set for the parameter, if ISET = .TRUE.\nC    ISET   = Logical flag to indicate whether to read or write.\nC             If ISET = .TRUE., the parameter will be given\nC             the value IVALUE.  If ISET = .FALSE., the parameter\nC             will be unchanged, and IVALUE is a dummy argument.\nC\nC  On return..\nC    IXSAV = The (old) value of the parameter.\nC\nC***SEE ALSO  XERMSG, XERRWD, XERRWV\nC***ROUTINES CALLED  NONE\nC***REVISION HISTORY  (YYMMDD)\nC   921118  DATE WRITTEN\nC   930329  Modified prologue to SLATEC format. (FNF)\nC   941025  Minor modification re default unit number. (ACH)\nC***END PROLOGUE  IXSAV\nC\nC**End\n      LOGICAL ISET\n      INTEGER IPAR, IVALUE\nC-----------------------------------------------------------------------\n      INTEGER LUNIT, LUNDEF, MESFLG\nC-----------------------------------------------------------------------\nC The following Fortran-77 declaration is to cause the values of the\nC listed (local) variables to be saved between calls to this routine.\nC-----------------------------------------------------------------------\n      SAVE LUNIT, LUNDEF, MESFLG\n      DATA LUNIT/-1/, LUNDEF/6/, MESFLG/1/\nC\nC***FIRST EXECUTABLE STATEMENT  IXSAV\n      IF (IPAR .EQ. 1) THEN\n        IF (LUNIT .EQ. -1) LUNIT = LUNDEF\n        IXSAV = LUNIT\n        IF (ISET) LUNIT = IVALUE\n        ENDIF\nC\n      IF (IPAR .EQ. 2) THEN\n        IXSAV = MESFLG\n        IF (ISET) MESFLG = IVALUE\n        ENDIF\nC\n      RETURN\nC----------------------- End of Function IXSAV -------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/j4save.f",
    "content": "*DECK J4SAVE\n      FUNCTION J4SAVE (IWHICH, IVALUE, ISET)\nC***BEGIN PROLOGUE  J4SAVE\nC***SUBSIDIARY\nC***PURPOSE  Save or recall global variables needed by error\nC            handling routines.\nC***LIBRARY   SLATEC (XERROR)\nC***TYPE      INTEGER (J4SAVE-I)\nC***KEYWORDS  ERROR MESSAGES, ERROR NUMBER, RECALL, SAVE, XERROR\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC     Abstract\nC        J4SAVE saves and recalls several global variables needed\nC        by the library error handling routines.\nC\nC     Description of Parameters\nC      --Input--\nC        IWHICH - Index of item desired.\nC                = 1 Refers to current error number.\nC                = 2 Refers to current error control flag.\nC                = 3 Refers to current unit number to which error\nC                    messages are to be sent.  (0 means use standard.)\nC                = 4 Refers to the maximum number of times any\nC                     message is to be printed (as set by XERMAX).\nC                = 5 Refers to the total number of units to which\nC                     each error message is to be written.\nC                = 6 Refers to the 2nd unit for error messages\nC                = 7 Refers to the 3rd unit for error messages\nC                = 8 Refers to the 4th unit for error messages\nC                = 9 Refers to the 5th unit for error messages\nC        IVALUE - The value to be set for the IWHICH-th parameter,\nC                 if ISET is .TRUE. .\nC        ISET   - If ISET=.TRUE., the IWHICH-th parameter will BE\nC                 given the value, IVALUE.  If ISET=.FALSE., the\nC                 IWHICH-th parameter will be unchanged, and IVALUE\nC                 is a dummy parameter.\nC      --Output--\nC        The (old) value of the IWHICH-th parameter will be returned\nC        in the function value, J4SAVE.\nC\nC***SEE ALSO  XERMSG\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   790801  DATE WRITTEN\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900205  Minor modifications to prologue.  (WRB)\nC   900402  Added TYPE section.  (WRB)\nC   910411  Added KEYWORDS section.  (WRB)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  J4SAVE\n      LOGICAL ISET\n      INTEGER IPARAM(9)\n      SAVE IPARAM\n      DATA IPARAM(1),IPARAM(2),IPARAM(3),IPARAM(4)/0,2,0,-1/\n      DATA IPARAM(5)/1/\n      DATA IPARAM(6),IPARAM(7),IPARAM(8),IPARAM(9)/0,0,0,0/\nC***FIRST EXECUTABLE STATEMENT  J4SAVE\n      J4SAVE = IPARAM(IWHICH)\n      IF (ISET) IPARAM(IWHICH) = IVALUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/fdump.f \\\n  %reldir%/ixsav.f \\\n  %reldir%/j4save.f \\\n  %reldir%/xerclr.f \\\n  %reldir%/xercnt.f \\\n  %reldir%/xerhlt.f \\\n  %reldir%/xermsg.f \\\n  %reldir%/xerprn.f \\\n  %reldir%/xerrwd.f \\\n  %reldir%/xerrwv.f \\\n  %reldir%/xersve.f \\\n  %reldir%/xgetf.f \\\n  %reldir%/xgetua.f \\\n  %reldir%/xsetf.f \\\n  %reldir%/xsetua.f\n"
  },
  {
    "path": "liboctave/external/slatec-err/xerclr.f",
    "content": "*DECK XERCLR\n      SUBROUTINE XERCLR\nC***BEGIN PROLOGUE  XERCLR\nC***PURPOSE  Reset current error number to zero.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3C\nC***TYPE      ALL (XERCLR-A)\nC***KEYWORDS  ERROR, XERROR\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC     Abstract\nC        This routine simply resets the current error number to zero.\nC        This may be necessary in order to determine that a certain\nC        error has occurred again since the last time NUMXER was\nC        referenced.\nC\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  J4SAVE\nC***REVISION HISTORY  (YYMMDD)\nC   790801  DATE WRITTEN\nC   861211  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XERCLR\nC***FIRST EXECUTABLE STATEMENT  XERCLR\n      JUNK = J4SAVE(1,0,.TRUE.)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xercnt.f",
    "content": "*DECK XERCNT\n      SUBROUTINE XERCNT (LIBRAR, SUBROU, MESSG, NERR, LEVEL, KONTRL)\nC***BEGIN PROLOGUE  XERCNT\nC***SUBSIDIARY\nC***PURPOSE  Allow user control over handling of errors.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3C\nC***TYPE      ALL (XERCNT-A)\nC***KEYWORDS  ERROR, XERROR\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC     Abstract\nC        Allows user control over handling of individual errors.\nC        Just after each message is recorded, but before it is\nC        processed any further (i.e., before it is printed or\nC        a decision to abort is made), a call is made to XERCNT.\nC        If the user has provided his own version of XERCNT, he\nC        can then override the value of KONTROL used in processing\nC        this message by redefining its value.\nC        KONTRL may be set to any value from -2 to 2.\nC        The meanings for KONTRL are the same as in XSETF, except\nC        that the value of KONTRL changes only for this message.\nC        If KONTRL is set to a value outside the range from -2 to 2,\nC        it will be moved back into that range.\nC\nC     Description of Parameters\nC\nC      --Input--\nC        LIBRAR - the library that the routine is in.\nC        SUBROU - the subroutine that XERMSG is being called from\nC        MESSG  - the first 20 characters of the error message.\nC        NERR   - same as in the call to XERMSG.\nC        LEVEL  - same as in the call to XERMSG.\nC        KONTRL - the current value of the control flag as set\nC                 by a call to XSETF.\nC\nC      --Output--\nC        KONTRL - the new value of KONTRL.  If KONTRL is not\nC                 defined, it will remain at its original value.\nC                 This changed value of control affects only\nC                 the current occurrence of the current message.\nC\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   790801  DATE WRITTEN\nC   861211  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900206  Routine changed from user-callable to subsidiary.  (WRB)\nC   900510  Changed calling sequence to include LIBRARY and SUBROUTINE\nC           names, changed routine name from XERCTL to XERCNT.  (RWC)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XERCNT\n      CHARACTER*(*) LIBRAR, SUBROU, MESSG\nC***FIRST EXECUTABLE STATEMENT  XERCNT\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xerhlt.f",
    "content": "*DECK XERHLT\n      SUBROUTINE XERHLT (MESSG)\nC***BEGIN PROLOGUE  XERHLT\nC***SUBSIDIARY\nC***PURPOSE  Abort program execution and print error message.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3C\nC***TYPE      ALL (XERHLT-A)\nC***KEYWORDS  ABORT PROGRAM EXECUTION, ERROR, XERROR\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC     Abstract\nC        ***Note*** machine dependent routine\nC        XERHLT aborts the execution of the program.\nC        The error message causing the abort is given in the calling\nC        sequence, in case one needs it for printing on a dayfile,\nC        for example.\nC\nC     Description of Parameters\nC        MESSG is as in XERMSG.\nC\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   790801  DATE WRITTEN\nC   861211  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900206  Routine changed from user-callable to subsidiary.  (WRB)\nC   900510  Changed calling sequence to delete length of character\nC           and changed routine name from XERABT to XERHLT.  (RWC)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XERHLT\n      CHARACTER*(*) MESSG\nC***FIRST EXECUTABLE STATEMENT  XERHLT\n      CALL XSTOPX (MESSG)\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xermsg.f",
    "content": "*DECK XERMSG\n      SUBROUTINE XERMSG (LIBRAR, SUBROU, MESSG, NERR, LEVEL)\nC***BEGIN PROLOGUE  XERMSG\nC***PURPOSE  Process error messages for SLATEC and other libraries.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3C\nC***TYPE      ALL (XERMSG-A)\nC***KEYWORDS  ERROR MESSAGE, XERROR\nC***AUTHOR  Fong, Kirby, (NMFECC at LLNL)\nC***DESCRIPTION\nC\nC   XERMSG processes a diagnostic message in a manner determined by the\nC   value of LEVEL and the current value of the library error control\nC   flag, KONTRL.  See subroutine XSETF for details.\nC\nC    LIBRAR   A character constant (or character variable) with the name\nC             of the library.  This will be 'SLATEC' for the SLATEC\nC             Common Math Library.  The error handling package is\nC             general enough to be used by many libraries\nC             simultaneously, so it is desirable for the routine that\nC             detects and reports an error to identify the library name\nC             as well as the routine name.\nC\nC    SUBROU   A character constant (or character variable) with the name\nC             of the routine that detected the error.  Usually it is the\nC             name of the routine that is calling XERMSG.  There are\nC             some instances where a user callable library routine calls\nC             lower level subsidiary routines where the error is\nC             detected.  In such cases it may be more informative to\nC             supply the name of the routine the user called rather than\nC             the name of the subsidiary routine that detected the\nC             error.\nC\nC    MESSG    A character constant (or character variable) with the text\nC             of the error or warning message.  In the example below,\nC             the message is a character constant that contains a\nC             generic message.\nC\nC                   CALL XERMSG ('SLATEC', 'MMPY',\nC                  *'THE ORDER OF THE MATRIX EXCEEDS THE ROW DIMENSION',\nC                  *3, 1)\nC\nC             It is possible (and is sometimes desirable) to generate a\nC             specific message--e.g., one that contains actual numeric\nC             values.  Specific numeric values can be converted into\nC             character strings using formatted WRITE statements into\nC             character variables.  This is called standard Fortran\nC             internal file I/O and is exemplified in the first three\nC             lines of the following example.  You can also catenate\nC             substrings of characters to construct the error message.\nC             Here is an example showing the use of both writing to\nC             an internal file and catenating character strings.\nC\nC                   CHARACTER*5 CHARN, CHARL\nC                   WRITE (CHARN,10) N\nC                   WRITE (CHARL,10) LDA\nC                10 FORMAT(I5)\nC                   CALL XERMSG ('SLATEC', 'MMPY', 'THE ORDER'//CHARN//\nC                  *   ' OF THE MATRIX EXCEEDS ITS ROW DIMENSION OF'//\nC                  *   CHARL, 3, 1)\nC\nC             There are two subtleties worth mentioning.  One is that\nC             the // for character catenation is used to construct the\nC             error message so that no single character constant is\nC             continued to the next line.  This avoids confusion as to\nC             whether there are trailing blanks at the end of the line.\nC             The second is that by catenating the parts of the message\nC             as an actual argument rather than encoding the entire\nC             message into one large character variable, we avoid\nC             having to know how long the message will be in order to\nC             declare an adequate length for that large character\nC             variable.  XERMSG calls XERPRN to print the message using\nC             multiple lines if necessary.  If the message is very long,\nC             XERPRN will break it into pieces of 72 characters (as\nC             requested by XERMSG) for printing on multiple lines.\nC             Also, XERMSG asks XERPRN to prefix each line with ' *  '\nC             so that the total line length could be 76 characters.\nC             Note also that XERPRN scans the error message backwards\nC             to ignore trailing blanks.  Another feature is that\nC             the substring '$$' is treated as a new line sentinel\nC             by XERPRN.  If you want to construct a multiline\nC             message without having to count out multiples of 72\nC             characters, just use '$$' as a separator.  '$$'\nC             obviously must occur within 72 characters of the\nC             start of each line to have its intended effect since\nC             XERPRN is asked to wrap around at 72 characters in\nC             addition to looking for '$$'.\nC\nC    NERR     An integer value that is chosen by the library routine's\nC             author.  It must be in the range -99 to 999 (three\nC             printable digits).  Each distinct error should have its\nC             own error number.  These error numbers should be described\nC             in the machine readable documentation for the routine.\nC             The error numbers need be unique only within each routine,\nC             so it is reasonable for each routine to start enumerating\nC             errors from 1 and proceeding to the next integer.\nC\nC    LEVEL    An integer value in the range 0 to 2 that indicates the\nC             level (severity) of the error.  Their meanings are\nC\nC            -1  A warning message.  This is used if it is not clear\nC                that there really is an error, but the user's attention\nC                may be needed.  An attempt is made to only print this\nC                message once.\nC\nC             0  A warning message.  This is used if it is not clear\nC                that there really is an error, but the user's attention\nC                may be needed.\nC\nC             1  A recoverable error.  This is used even if the error is\nC                so serious that the routine cannot return any useful\nC                answer.  If the user has told the error package to\nC                return after recoverable errors, then XERMSG will\nC                return to the Library routine which can then return to\nC                the user's routine.  The user may also permit the error\nC                package to terminate the program upon encountering a\nC                recoverable error.\nC\nC             2  A fatal error.  XERMSG will not return to its caller\nC                after it receives a fatal error.  This level should\nC                hardly ever be used; it is much better to allow the\nC                user a chance to recover.  An example of one of the few\nC                cases in which it is permissible to declare a level 2\nC                error is a reverse communication Library routine that\nC                is likely to be called repeatedly until it integrates\nC                across some interval.  If there is a serious error in\nC                the input such that another step cannot be taken and\nC                the Library routine is called again without the input\nC                error having been corrected by the caller, the Library\nC                routine will probably be called forever with improper\nC                input.  In this case, it is reasonable to declare the\nC                error to be fatal.\nC\nC    Each of the arguments to XERMSG is input; none will be modified by\nC    XERMSG.  A routine may make multiple calls to XERMSG with warning\nC    level messages; however, after a call to XERMSG with a recoverable\nC    error, the routine should return to the user.  Do not try to call\nC    XERMSG with a second recoverable error after the first recoverable\nC    error because the error package saves the error number.  The user\nC    can retrieve this error number by calling another entry point in\nC    the error handling package and then clear the error number when\nC    recovering from the error.  Calling XERMSG in succession causes the\nC    old error number to be overwritten by the latest error number.\nC    This is considered harmless for error numbers associated with\nC    warning messages but must not be done for error numbers of serious\nC    errors.  After a call to XERMSG with a recoverable error, the user\nC    must be given a chance to call NUMXER or XERCLR to retrieve or\nC    clear the error number.\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  FDUMP, J4SAVE, XERCNT, XERHLT, XERPRN, XERSVE\nC***REVISION HISTORY  (YYMMDD)\nC   880101  DATE WRITTEN\nC   880621  REVISED AS DIRECTED AT SLATEC CML MEETING OF FEBRUARY 1988.\nC           THERE ARE TWO BASIC CHANGES.\nC           1.  A NEW ROUTINE, XERPRN, IS USED INSTEAD OF XERPRT TO\nC               PRINT MESSAGES.  THIS ROUTINE WILL BREAK LONG MESSAGES\nC               INTO PIECES FOR PRINTING ON MULTIPLE LINES.  '$$' IS\nC               ACCEPTED AS A NEW LINE SENTINEL.  A PREFIX CAN BE\nC               ADDED TO EACH LINE TO BE PRINTED.  XERMSG USES EITHER\nC               ' ***' OR ' *  ' AND LONG MESSAGES ARE BROKEN EVERY\nC               72 CHARACTERS (AT MOST) SO THAT THE MAXIMUM LINE\nC               LENGTH OUTPUT CAN NOW BE AS GREAT AS 76.\nC           2.  THE TEXT OF ALL MESSAGES IS NOW IN UPPER CASE SINCE THE\nC               FORTRAN STANDARD DOCUMENT DOES NOT ADMIT THE EXISTENCE\nC               OF LOWER CASE.\nC   880708  REVISED AFTER THE SLATEC CML MEETING OF JUNE 29 AND 30.\nC           THE PRINCIPAL CHANGES ARE\nC           1.  CLARIFY COMMENTS IN THE PROLOGUES\nC           2.  RENAME XRPRNT TO XERPRN\nC           3.  REWORK HANDLING OF '$$' IN XERPRN TO HANDLE BLANK LINES\nC               SIMILAR TO THE WAY FORMAT STATEMENTS HANDLE THE /\nC               CHARACTER FOR NEW RECORDS.\nC   890706  REVISED WITH THE HELP OF FRED FRITSCH AND REG CLEMENS TO\nC           CLEAN UP THE CODING.\nC   890721  REVISED TO USE NEW FEATURE IN XERPRN TO COUNT CHARACTERS IN\nC           PREFIX.\nC   891013  REVISED TO CORRECT COMMENTS.\nC   891214  Prologue converted to Version 4.0 format.  (WRB)\nC   900510  Changed test on NERR to be -9999999 < NERR < 99999999, but\nC           NERR .ne. 0, and on LEVEL to be -2 < LEVEL < 3.  Added\nC           LEVEL=-1 logic, changed calls to XERSAV to XERSVE, and\nC           XERCTL to XERCNT.  (RWC)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XERMSG\n      CHARACTER*(*) LIBRAR, SUBROU, MESSG\n      CHARACTER*8 XLIBR, XSUBR\n      CHARACTER*72  TEMP\n      CHARACTER*20  LFIRST\nC***FIRST EXECUTABLE STATEMENT  XERMSG\n      LKNTRL = J4SAVE (2, 0, .FALSE.)\n      MAXMES = J4SAVE (4, 0, .FALSE.)\nC\nC       LKNTRL IS A LOCAL COPY OF THE CONTROL FLAG KONTRL.\nC       MAXMES IS THE MAXIMUM NUMBER OF TIMES ANY PARTICULAR MESSAGE\nC          SHOULD BE PRINTED.  IF MAXMES IS LESS THAN ZERO, THERE IS\nC          NO LIMIT.\nC\nC       WE PRINT A FATAL ERROR MESSAGE AND TERMINATE FOR AN ERROR IN\nC          CALLING XERMSG.  THE ERROR NUMBER SHOULD BE POSITIVE,\nC          AND THE LEVEL SHOULD BE BETWEEN 0 AND 2.\nC\n      IF (NERR.LT.-9999999 .OR. NERR.GT.99999999 .OR. NERR.EQ.0 .OR.\n     *   LEVEL.LT.-1 .OR. LEVEL.GT.2) THEN\n         CALL XERPRN (' ***', -1, 'FATAL ERROR IN...$$ ' //\n     *      'XERMSG -- INVALID ERROR NUMBER OR LEVEL$$ '//\n     *      'JOB ABORT DUE TO FATAL ERROR.', 72)\n         CALL XERSVE (' ', ' ', ' ', 0, 0, 0, KDUMMY)\n         CALL XERHLT (' ***XERMSG -- INVALID INPUT')\n         RETURN\n      ENDIF\nC\nC       RECORD THE MESSAGE.\nC\n      I = J4SAVE (1, NERR, .TRUE.)\n      CALL XERSVE (LIBRAR, SUBROU, MESSG, 1, NERR, LEVEL, KOUNT)\nC\nC       HANDLE PRINT-ONCE WARNING MESSAGES.\nC\n      IF (LEVEL.EQ.-1 .AND. KOUNT.GT.1) RETURN\nC\nC       ALLOW TEMPORARY USER OVERRIDE OF THE CONTROL FLAG.\nC\n      XLIBR  = LIBRAR\n      XSUBR  = SUBROU\n      LFIRST = MESSG\n      LERR   = NERR\n      LLEVEL = LEVEL\n      CALL XERCNT (XLIBR, XSUBR, LFIRST, LERR, LLEVEL, LKNTRL)\nC\n      LKNTRL = MAX(-2, MIN(2,LKNTRL))\n      MKNTRL = ABS(LKNTRL)\nC\nC       SKIP PRINTING IF THE CONTROL FLAG VALUE AS RESET IN XERCNT IS\nC       ZERO AND THE ERROR IS NOT FATAL.\nC\n      IF (LEVEL.LT.2 .AND. LKNTRL.EQ.0) GO TO 30\n      IF (LEVEL.EQ.0 .AND. MAXMES.GE.0 .AND. KOUNT.GT.MAXMES) GO TO 30\n      IF (LEVEL.EQ.1 .AND. MAXMES.GE.0 .AND. KOUNT.GT.MAXMES\n     *    .AND. MKNTRL.EQ.1) GO TO 30\n      IF (LEVEL.EQ.2 .AND. MAXMES.GE.0 .AND. KOUNT.GT.MAX(1,MAXMES))\n     *    GO TO 30\nC\nC       ANNOUNCE THE NAMES OF THE LIBRARY AND SUBROUTINE BY BUILDING A\nC       MESSAGE IN CHARACTER VARIABLE TEMP (NOT EXCEEDING 66 CHARACTERS)\nC       AND SENDING IT OUT VIA XERPRN.  PRINT ONLY IF CONTROL FLAG\nC       IS NOT ZERO.\nC\n      IF (LKNTRL .NE. 0) THEN\n         TEMP(1:21) = 'MESSAGE FROM ROUTINE '\n         I = MIN(LEN(SUBROU), 16)\n         TEMP(22:21+I) = SUBROU(1:I)\n         TEMP(22+I:33+I) = ' IN LIBRARY '\n         LTEMP = 33 + I\n         I = MIN(LEN(LIBRAR), 16)\n         TEMP(LTEMP+1:LTEMP+I) = LIBRAR (1:I)\n         TEMP(LTEMP+I+1:LTEMP+I+1) = '.'\n         LTEMP = LTEMP + I + 1\n         CALL XERPRN (' ***', -1, TEMP(1:LTEMP), 72)\n      ENDIF\nC\nC       IF LKNTRL IS POSITIVE, PRINT AN INTRODUCTORY LINE BEFORE\nC       PRINTING THE MESSAGE.  THE INTRODUCTORY LINE TELLS THE CHOICE\nC       FROM EACH OF THE FOLLOWING THREE OPTIONS.\nC       1.  LEVEL OF THE MESSAGE\nC              'INFORMATIVE MESSAGE'\nC              'POTENTIALLY RECOVERABLE ERROR'\nC              'FATAL ERROR'\nC       2.  WHETHER CONTROL FLAG WILL ALLOW PROGRAM TO CONTINUE\nC              'PROG CONTINUES'\nC              'PROG ABORTED'\nC       3.  WHETHER OR NOT A TRACEBACK WAS REQUESTED.  (THE TRACEBACK\nC           MAY NOT BE IMPLEMENTED AT SOME SITES, SO THIS ONLY TELLS\nC           WHAT WAS REQUESTED, NOT WHAT WAS DELIVERED.)\nC              'TRACEBACK REQUESTED'\nC              'TRACEBACK NOT REQUESTED'\nC       NOTICE THAT THE LINE INCLUDING FOUR PREFIX CHARACTERS WILL NOT\nC       EXCEED 74 CHARACTERS.\nC       WE SKIP THE NEXT BLOCK IF THE INTRODUCTORY LINE IS NOT NEEDED.\nC\n      IF (LKNTRL .GT. 0) THEN\nC\nC       THE FIRST PART OF THE MESSAGE TELLS ABOUT THE LEVEL.\nC\n         IF (LEVEL .LE. 0) THEN\n            TEMP(1:20) = 'INFORMATIVE MESSAGE,'\n            LTEMP = 20\n         ELSEIF (LEVEL .EQ. 1) THEN\n            TEMP(1:30) = 'POTENTIALLY RECOVERABLE ERROR,'\n            LTEMP = 30\n         ELSE\n            TEMP(1:12) = 'FATAL ERROR,'\n            LTEMP = 12\n         ENDIF\nC\nC       THEN WHETHER THE PROGRAM WILL CONTINUE.\nC\n         IF ((MKNTRL.EQ.2 .AND. LEVEL.GE.1) .OR.\n     *       (MKNTRL.EQ.1 .AND. LEVEL.EQ.2)) THEN\n            TEMP(LTEMP+1:LTEMP+14) = ' PROG ABORTED,'\n            LTEMP = LTEMP + 14\n         ELSE\n            TEMP(LTEMP+1:LTEMP+16) = ' PROG CONTINUES,'\n            LTEMP = LTEMP + 16\n         ENDIF\nC\nC       FINALLY TELL WHETHER THERE SHOULD BE A TRACEBACK.\nC\n         IF (LKNTRL .GT. 0) THEN\n            TEMP(LTEMP+1:LTEMP+20) = ' TRACEBACK REQUESTED'\n            LTEMP = LTEMP + 20\n         ELSE\n            TEMP(LTEMP+1:LTEMP+24) = ' TRACEBACK NOT REQUESTED'\n            LTEMP = LTEMP + 24\n         ENDIF\n         CALL XERPRN (' ***', -1, TEMP(1:LTEMP), 72)\n      ENDIF\nC\nC       NOW SEND OUT THE MESSAGE.\nC\n      CALL XERPRN (' *  ', -1, MESSG, 72)\nC\nC       IF LKNTRL IS POSITIVE, WRITE THE ERROR NUMBER AND REQUEST A\nC          TRACEBACK.\nC\n      IF (LKNTRL .GT. 0) THEN\n         WRITE (TEMP, '(''ERROR NUMBER = '', I8)') NERR\n         DO 10 I=16,22\n            IF (TEMP(I:I) .NE. ' ') GO TO 20\n   10    CONTINUE\nC\n   20    CALL XERPRN (' *  ', -1, TEMP(1:15) // TEMP(I:23), 72)\n         CALL FDUMP\n      ENDIF\nC\nC       IF LKNTRL IS NOT ZERO, PRINT A BLANK LINE AND AN END OF MESSAGE.\nC\n      IF (LKNTRL .NE. 0) THEN\n         CALL XERPRN (' *  ', -1, ' ', 72)\n         CALL XERPRN (' ***', -1, 'END OF MESSAGE', 72)\n         CALL XERPRN ('    ',  0, ' ', 72)\n      ENDIF\nC\nC       IF THE ERROR IS NOT FATAL OR THE ERROR IS RECOVERABLE AND THE\nC       CONTROL FLAG IS SET FOR RECOVERY, THEN RETURN.\nC\n   30 IF (LEVEL.LE.0 .OR. (LEVEL.EQ.1 .AND. MKNTRL.LE.1)) RETURN\nC\nC       THE PROGRAM WILL BE STOPPED DUE TO AN UNRECOVERED ERROR OR A\nC       FATAL ERROR.  PRINT THE REASON FOR THE ABORT AND THE ERROR\nC       SUMMARY IF THE CONTROL FLAG AND THE MAXIMUM ERROR COUNT PERMIT.\nC\n      IF (LKNTRL.GT.0\n     *    .AND. (MAXMES.LT.0 .OR. KOUNT.LT.MAX(1,MAXMES))) THEN\n         IF (LEVEL .EQ. 1) THEN\n            CALL XERPRN\n     *         (' ***', -1, 'JOB ABORT DUE TO UNRECOVERED ERROR.', 72)\n         ELSE\n            CALL XERPRN(' ***', -1, 'JOB ABORT DUE TO FATAL ERROR.', 72)\n         ENDIF\n         CALL XERSVE (' ', ' ', ' ', -1, 0, 0, KDUMMY)\n         CALL XERHLT (' ')\n      ELSE\n         CALL XERHLT (MESSG)\n      ENDIF\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xerprn.f",
    "content": "*DECK XERPRN\n      SUBROUTINE XERPRN (PREFIX, NPREF, MESSG, NWRAP)\nC***BEGIN PROLOGUE  XERPRN\nC***SUBSIDIARY\nC***PURPOSE  Print error messages processed by XERMSG.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3C\nC***TYPE      ALL (XERPRN-A)\nC***KEYWORDS  ERROR MESSAGES, PRINTING, XERROR\nC***AUTHOR  Fong, Kirby, (NMFECC at LLNL)\nC***DESCRIPTION\nC\nC This routine sends one or more lines to each of the (up to five)\nC logical units to which error messages are to be sent.  This routine\nC is called several times by XERMSG, sometimes with a single line to\nC print and sometimes with a (potentially very long) message that may\nC wrap around into multiple lines.\nC\nC PREFIX  Input argument of type CHARACTER.  This argument contains\nC         characters to be put at the beginning of each line before\nC         the body of the message.  No more than 16 characters of\nC         PREFIX will be used.\nC\nC NPREF   Input argument of type INTEGER.  This argument is the number\nC         of characters to use from PREFIX.  If it is negative, the\nC         intrinsic function LEN is used to determine its length.  If\nC         it is zero, PREFIX is not used.  If it exceeds 16 or if\nC         LEN(PREFIX) exceeds 16, only the first 16 characters will be\nC         used.  If NPREF is positive and the length of PREFIX is less\nC         than NPREF, a copy of PREFIX extended with blanks to length\nC         NPREF will be used.\nC\nC MESSG   Input argument of type CHARACTER.  This is the text of a\nC         message to be printed.  If it is a long message, it will be\nC         broken into pieces for printing on multiple lines.  Each line\nC         will start with the appropriate prefix and be followed by a\nC         piece of the message.  NWRAP is the number of characters per\nC         piece; that is, after each NWRAP characters, we break and\nC         start a new line.  In addition the characters '$$' embedded\nC         in MESSG are a sentinel for a new line.  The counting of\nC         characters up to NWRAP starts over for each new line.  The\nC         value of NWRAP typically used by XERMSG is 72 since many\nC         older error messages in the SLATEC Library are laid out to\nC         rely on wrap-around every 72 characters.\nC\nC NWRAP   Input argument of type INTEGER.  This gives the maximum size\nC         piece into which to break MESSG for printing on multiple\nC         lines.  An embedded '$$' ends a line, and the count restarts\nC         at the following character.  If a line break does not occur\nC         on a blank (it would split a word) that word is moved to the\nC         next line.  Values of NWRAP less than 16 will be treated as\nC         16.  Values of NWRAP greater than 132 will be treated as 132.\nC         The actual line length will be NPREF + NWRAP after NPREF has\nC         been adjusted to fall between 0 and 16 and NWRAP has been\nC         adjusted to fall between 16 and 132.\nC\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  I1MACH, XGETUA\nC***REVISION HISTORY  (YYMMDD)\nC   880621  DATE WRITTEN\nC   880708  REVISED AFTER THE SLATEC CML SUBCOMMITTEE MEETING OF\nC           JUNE 29 AND 30 TO CHANGE THE NAME TO XERPRN AND TO REWORK\nC           THE HANDLING OF THE NEW LINE SENTINEL TO BEHAVE LIKE THE\nC           SLASH CHARACTER IN FORMAT STATEMENTS.\nC   890706  REVISED WITH THE HELP OF FRED FRITSCH AND REG CLEMENS TO\nC           STREAMLINE THE CODING AND FIX A BUG THAT CAUSED EXTRA BLANK\nC           LINES TO BE PRINTED.\nC   890721  REVISED TO ADD A NEW FEATURE.  A NEGATIVE VALUE OF NPREF\nC           CAUSES LEN(PREFIX) TO BE USED AS THE LENGTH.\nC   891013  REVISED TO CORRECT ERROR IN CALCULATING PREFIX LENGTH.\nC   891214  Prologue converted to Version 4.0 format.  (WRB)\nC   900510  Added code to break messages between words.  (RWC)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XERPRN\n      CHARACTER*(*) PREFIX, MESSG\n      INTEGER NPREF, NWRAP\n      CHARACTER*148 CBUFF\n      INTEGER IU(5), NUNIT\n      CHARACTER*2 NEWLIN\n      PARAMETER (NEWLIN = '$$')\nC***FIRST EXECUTABLE STATEMENT  XERPRN\n      CALL XGETUA(IU,NUNIT)\nC\nC       A ZERO VALUE FOR A LOGICAL UNIT NUMBER MEANS TO USE THE STANDARD\nC       ERROR MESSAGE UNIT INSTEAD.  I1MACH(4) RETRIEVES THE STANDARD\nC       ERROR MESSAGE UNIT.\nC\n      N = I1MACH(4)\n      DO 10 I=1,NUNIT\n         IF (IU(I) .EQ. 0) IU(I) = N\n   10 CONTINUE\nC\nC       LPREF IS THE LENGTH OF THE PREFIX.  THE PREFIX IS PLACED AT THE\nC       BEGINNING OF CBUFF, THE CHARACTER BUFFER, AND KEPT THERE DURING\nC       THE REST OF THIS ROUTINE.\nC\n      IF ( NPREF .LT. 0 ) THEN\n         LPREF = LEN(PREFIX)\n      ELSE\n         LPREF = NPREF\n      ENDIF\n      LPREF = MIN(16, LPREF)\n      IF (LPREF .NE. 0) CBUFF(1:LPREF) = PREFIX\nC\nC       LWRAP IS THE MAXIMUM NUMBER OF CHARACTERS WE WANT TO TAKE AT ONE\nC       TIME FROM MESSG TO PRINT ON ONE LINE.\nC\n      LWRAP = MAX(16, MIN(132, NWRAP))\nC\nC       SET LENMSG TO THE LENGTH OF MESSG, IGNORE ANY TRAILING BLANKS.\nC\n      LENMSG = LEN(MESSG)\n      N = LENMSG\n      DO 20 I=1,N\n         IF (MESSG(LENMSG:LENMSG) .NE. ' ') GO TO 30\n         LENMSG = LENMSG - 1\n   20 CONTINUE\n   30 CONTINUE\nC\nC       IF THE MESSAGE IS ALL BLANKS, THEN PRINT ONE BLANK LINE.\nC\n      IF (LENMSG .EQ. 0) THEN\n         CBUFF(LPREF+1:LPREF+1) = ' '\n         DO 40 I=1,NUNIT\n            WRITE(IU(I), '(A)') CBUFF(1:LPREF+1)\n   40    CONTINUE\n         RETURN\n      ENDIF\nC\nC       SET NEXTC TO THE POSITION IN MESSG WHERE THE NEXT SUBSTRING\nC       STARTS.  FROM THIS POSITION WE SCAN FOR THE NEW LINE SENTINEL.\nC       WHEN NEXTC EXCEEDS LENMSG, THERE IS NO MORE TO PRINT.\nC       WE LOOP BACK TO LABEL 50 UNTIL ALL PIECES HAVE BEEN PRINTED.\nC\nC       WE LOOK FOR THE NEXT OCCURRENCE OF THE NEW LINE SENTINEL.  THE\nC       INDEX INTRINSIC FUNCTION RETURNS ZERO IF THERE IS NO OCCURRENCE\nC       OR IF THE LENGTH OF THE FIRST ARGUMENT IS LESS THAN THE LENGTH\nC       OF THE SECOND ARGUMENT.\nC\nC       THERE ARE SEVERAL CASES WHICH SHOULD BE CHECKED FOR IN THE\nC       FOLLOWING ORDER.  WE ARE ATTEMPTING TO SET LPIECE TO THE NUMBER\nC       OF CHARACTERS THAT SHOULD BE TAKEN FROM MESSG STARTING AT\nC       POSITION NEXTC.\nC\nC       LPIECE .EQ. 0   THE NEW LINE SENTINEL DOES NOT OCCUR IN THE\nC                       REMAINDER OF THE CHARACTER STRING.  LPIECE\nC                       SHOULD BE SET TO LWRAP OR LENMSG+1-NEXTC,\nC                       WHICHEVER IS LESS.\nC\nC       LPIECE .EQ. 1   THE NEW LINE SENTINEL STARTS AT MESSG(NEXTC:\nC                       NEXTC).  LPIECE IS EFFECTIVELY ZERO, AND WE\nC                       PRINT NOTHING TO AVOID PRODUCING UNNECESSARY\nC                       BLANK LINES.  THIS TAKES CARE OF THE SITUATION\nC                       WHERE THE LIBRARY ROUTINE HAS A MESSAGE OF\nC                       EXACTLY 72 CHARACTERS FOLLOWED BY A NEW LINE\nC                       SENTINEL FOLLOWED BY MORE CHARACTERS.  NEXTC\nC                       SHOULD BE INCREMENTED BY 2.\nC\nC       LPIECE .GT. LWRAP+1  REDUCE LPIECE TO LWRAP.\nC\nC       ELSE            THIS LAST CASE MEANS 2 .LE. LPIECE .LE. LWRAP+1\nC                       RESET LPIECE = LPIECE-1.  NOTE THAT THIS\nC                       PROPERLY HANDLES THE END CASE WHERE LPIECE .EQ.\nC                       LWRAP+1.  THAT IS, THE SENTINEL FALLS EXACTLY\nC                       AT THE END OF A LINE.\nC\n      NEXTC = 1\n   50 LPIECE = INDEX(MESSG(NEXTC:LENMSG), NEWLIN)\n      IF (LPIECE .EQ. 0) THEN\nC\nC       THERE WAS NO NEW LINE SENTINEL FOUND.\nC\n         IDELTA = 0\n         LPIECE = MIN(LWRAP, LENMSG+1-NEXTC)\n         IF (LPIECE .LT. LENMSG+1-NEXTC) THEN\n            DO 52 I=LPIECE+1,2,-1\n               IF (MESSG(NEXTC+I-1:NEXTC+I-1) .EQ. ' ') THEN\n                  LPIECE = I-1\n                  IDELTA = 1\n                  GOTO 54\n               ENDIF\n   52       CONTINUE\n         ENDIF\n   54    CBUFF(LPREF+1:LPREF+LPIECE) = MESSG(NEXTC:NEXTC+LPIECE-1)\n         NEXTC = NEXTC + LPIECE + IDELTA\n      ELSEIF (LPIECE .EQ. 1) THEN\nC\nC       WE HAVE A NEW LINE SENTINEL AT MESSG(NEXTC:NEXTC+1).\nC       DON'T PRINT A BLANK LINE.\nC\n         NEXTC = NEXTC + 2\n         GO TO 50\n      ELSEIF (LPIECE .GT. LWRAP+1) THEN\nC\nC       LPIECE SHOULD BE SET DOWN TO LWRAP.\nC\n         IDELTA = 0\n         LPIECE = LWRAP\n         DO 56 I=LPIECE+1,2,-1\n            IF (MESSG(NEXTC+I-1:NEXTC+I-1) .EQ. ' ') THEN\n               LPIECE = I-1\n               IDELTA = 1\n               GOTO 58\n            ENDIF\n   56    CONTINUE\n   58    CBUFF(LPREF+1:LPREF+LPIECE) = MESSG(NEXTC:NEXTC+LPIECE-1)\n         NEXTC = NEXTC + LPIECE + IDELTA\n      ELSE\nC\nC       IF WE ARRIVE HERE, IT MEANS 2 .LE. LPIECE .LE. LWRAP+1.\nC       WE SHOULD DECREMENT LPIECE BY ONE.\nC\n         LPIECE = LPIECE - 1\n         CBUFF(LPREF+1:LPREF+LPIECE) = MESSG(NEXTC:NEXTC+LPIECE-1)\n         NEXTC  = NEXTC + LPIECE + 2\n      ENDIF\nC\nC       PRINT\nC\n      DO 60 I=1,NUNIT\n         WRITE(IU(I), '(A)') CBUFF(1:LPREF+LPIECE)\n   60 CONTINUE\nC\n      IF (NEXTC .LE. LENMSG) GO TO 50\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xerrwd.f",
    "content": "\n*DECK XERRWD\n      SUBROUTINE XERRWD (MSG, NMES, NERR, LEVEL, NI, I1, I2, NR, R1, R2)\nC***BEGIN PROLOGUE  XERRWD\nC***SUBSIDIARY\nC***PURPOSE  Write error message with values.\nC***LIBRARY   MATHLIB\nC***CATEGORY  R3C\nC***TYPE      DOUBLE PRECISION (XERRWV-S, XERRWD-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  Subroutines XERRWD, XSETF, XSETUN, and the function routine IXSAV,\nC  as given here, constitute a simplified version of the SLATEC error\nC  handling package.\nC\nC  All arguments are input arguments.\nC\nC  MSG    = The message (character array).\nC  NMES   = The length of MSG (number of characters).\nC  NERR   = The error number (not used).\nC  LEVEL  = The error level..\nC           0 or 1 means recoverable (control returns to caller).\nC           2 means fatal (run is aborted--see note below).\nC  NI     = Number of integers (0, 1, or 2) to be printed with message.\nC  I1,I2  = Integers to be printed, depending on NI.\nC  NR     = Number of reals (0, 1, or 2) to be printed with message.\nC  R1,R2  = Reals to be printed, depending on NR.\nC\nC  Note..  this routine is machine-dependent and specialized for use\nC  in limited context, in the following ways..\nC  1. The argument MSG is assumed to be of type CHARACTER, and\nC     the message is printed with a format of (1X,A).\nC  2. The message is assumed to take only one line.\nC     Multi-line messages are generated by repeated calls.\nC  3. If LEVEL = 2, control passes to the statement   STOP\nC     to abort the run.  This statement may be machine-dependent.\nC  4. R1 and R2 are assumed to be in double precision and are printed\nC     in D21.13 format.\nC\nC***ROUTINES CALLED  IXSAV\nC***REVISION HISTORY  (YYMMDD)\nC   920831  DATE WRITTEN\nC   921118  Replaced MFLGSV/LUNSAV by IXSAV. (ACH)\nC   930329  Modified prologue to SLATEC format. (FNF)\nC   930407  Changed MSG from CHARACTER*1 array to variable. (FNF)\nC   930922  Minor cosmetic change. (FNF)\nC***END PROLOGUE  XERRWD\nC\nC*Internal Notes:\nC\nC For a different default logical unit number, IXSAV (or a subsidiary\nC routine that it calls) will need to be modified.\nC For a different run-abort command, change the statement following\nC statement 100 at the end.\nC-----------------------------------------------------------------------\nC Subroutines called by XERRWD.. None\nC Function routine called by XERRWD.. IXSAV\nC-----------------------------------------------------------------------\nC**End\nC\nC  Declare arguments.\nC\n      DOUBLE PRECISION R1, R2\n      INTEGER NMES, NERR, LEVEL, NI, I1, I2, NR\n      CHARACTER*(*) MSG\nC\nC  Declare local variables.\nC\n      INTEGER LUNIT, IXSAV, MESFLG\nC\nC  Get logical unit number and message print flag.\nC\nC***FIRST EXECUTABLE STATEMENT  XERRWD\n      LUNIT = IXSAV (1, 0, .FALSE.)\n      MESFLG = IXSAV (2, 0, .FALSE.)\n      IF (MESFLG .EQ. 0) GO TO 100\nC\nC  Write the message.\nC\n      WRITE (LUNIT,10)  MSG(1:NMES)\n 10   FORMAT(1X,A)\n      IF (NI .EQ. 1) WRITE (LUNIT, 20) I1\n 20   FORMAT(6X,'In above message,  I1 =',I10)\n      IF (NI .EQ. 2) WRITE (LUNIT, 30) I1,I2\n 30   FORMAT(6X,'In above message,  I1 =',I10,3X,'I2 =',I10)\n      IF (NR .EQ. 1) WRITE (LUNIT, 40) R1\n 40   FORMAT(6X,'In above message,  R1 =',D21.13)\n      IF (NR .EQ. 2) WRITE (LUNIT, 50) R1,R2\n 50   FORMAT(6X,'In above,  R1 =',D21.13,3X,'R2 =',D21.13)\nC\nC  Abort the run if LEVEL = 2.\nC\n 100  IF (LEVEL .NE. 2) RETURN\n      CALL XSTOPX (' ')\nC----------------------- End of Subroutine XERRWD ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xerrwv.f",
    "content": "*DECK XERRWV\n      SUBROUTINE XERRWV (MSG, NMES, NERR, LEVEL, NI, I1, I2, NR, R1, R2)\nC***BEGIN PROLOGUE  XERRWV\nC***SUBSIDIARY\nC***PURPOSE  Write error message with values.\nC***CATEGORY  R3C\nC***TYPE      SINGLE PRECISION (XERRWV-S, XERRWD-D)\nC***AUTHOR  Hindmarsh, Alan C., (LLNL)\nC***DESCRIPTION\nC\nC  Subroutines XERRWV, XSETF, XSETUN, and the function routine IXSAV,\nC  as given here, constitute a simplified version of the SLATEC error\nC  handling package.\nC\nC  All arguments are input arguments.\nC\nC  MSG    = The message (character array).\nC  NMES   = The length of MSG (number of characters).\nC  NERR   = The error number (not used).\nC  LEVEL  = The error level..\nC           0 or 1 means recoverable (control returns to caller).\nC           2 means fatal (run is aborted--see note below).\nC  NI     = Number of integers (0, 1, or 2) to be printed with message.\nC  I1,I2  = Integers to be printed, depending on NI.\nC  NR     = Number of reals (0, 1, or 2) to be printed with message.\nC  R1,R2  = Reals to be printed, depending on NR.\nC\nC  Note..  this routine is machine-dependent and specialized for use\nC  in limited context, in the following ways..\nC  1. The argument MSG is assumed to be of type CHARACTER, and\nC     the message is printed with a format of (1X,A).\nC  2. The message is assumed to take only one line.\nC     Multi-line messages are generated by repeated calls.\nC  3. If LEVEL = 2, control passes to the statement   STOP\nC     to abort the run.  This statement may be machine-dependent.\nC  4. R1 and R2 are assumed to be in single precision and are printed\nC     in E21.13 format.\nC\nC***ROUTINES CALLED  IXSAV\nC***REVISION HISTORY  (YYMMDD)\nC   791129  DATE WRITTEN\nC   890413  Heavily revised, with Common eliminated. (ACH, PNB)\nC   921118  Replaced MFLGSV/LUNSAV by IXSAV. (ACH)\nC   930329  Modified prologue to SLATEC format. (FNF)\nC   930407  Changed MSG from CHARACTER*1 array to variable. (FNF)\nC   930922  Minor cosmetic change. (FNF)\nC***END PROLOGUE  XERRWV\nC\nC*Internal Notes:\nC\nC For a different default logical unit number, IXSAV (or a subsidiary\nC routine that it calls) will need to be modified.\nC For a different run-abort command, change the statement following\nC statement 100 at the end.\nC-----------------------------------------------------------------------\nC Subroutines called by XERRWV.. None\nC Function routine called by XERRWV.. IXSAV\nC-----------------------------------------------------------------------\nC**End\nC\nC  Declare arguments.\nC\n      REAL R1, R2\n      INTEGER NMES, NERR, LEVEL, NI, I1, I2, NR\n      CHARACTER*(*) MSG\nC\nC  Declare local variables.\nC\n      INTEGER LUNIT, IXSAV, MESFLG\nC\nC  Get logical unit number and message print flag.\nC\nC***FIRST EXECUTABLE STATEMENT  XERRWV\n      LUNIT = IXSAV (1, 0, .FALSE.)\n      MESFLG = IXSAV (2, 0, .FALSE.)\n      IF (MESFLG .EQ. 0) GO TO 100\nC\nC  Write the message.\nC\n      WRITE (LUNIT,10)  MSG(1:NMES)\n 10   FORMAT(1X,A)\n      IF (NI .EQ. 1) WRITE (LUNIT, 20) I1\n 20   FORMAT(6X,'In above message,  I1 =',I10)\n      IF (NI .EQ. 2) WRITE (LUNIT, 30) I1,I2\n 30   FORMAT(6X,'In above message,  I1 =',I10,3X,'I2 =',I10)\n      IF (NR .EQ. 1) WRITE (LUNIT, 40) R1\n 40   FORMAT(6X,'In above message,  R1 =',E21.13)\n      IF (NR .EQ. 2) WRITE (LUNIT, 50) R1,R2\n 50   FORMAT(6X,'In above,  R1 =',E21.13,3X,'R2 =',E21.13)\nC\nC  Abort the run if LEVEL = 2.\nC\n 100  IF (LEVEL .NE. 2) RETURN\n      CALL XSTOPX (' ')\nC----------------------- End of Subroutine XERRWV ----------------------\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xersve.f",
    "content": "*DECK XERSVE\n      SUBROUTINE XERSVE (LIBRAR, SUBROU, MESSG, KFLAG, NERR, LEVEL,\n     +   ICOUNT)\nC***BEGIN PROLOGUE  XERSVE\nC***SUBSIDIARY\nC***PURPOSE  Record that an error has occurred.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3\nC***TYPE      ALL (XERSVE-A)\nC***KEYWORDS  ERROR, XERROR\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC *Usage:\nC\nC        INTEGER  KFLAG, NERR, LEVEL, ICOUNT\nC        CHARACTER * (len) LIBRAR, SUBROU, MESSG\nC\nC        CALL XERSVE (LIBRAR, SUBROU, MESSG, KFLAG, NERR, LEVEL, ICOUNT)\nC\nC *Arguments:\nC\nC        LIBRAR :IN    is the library that the message is from.\nC        SUBROU :IN    is the subroutine that the message is from.\nC        MESSG  :IN    is the message to be saved.\nC        KFLAG  :IN    indicates the action to be performed.\nC                      when KFLAG > 0, the message in MESSG is saved.\nC                      when KFLAG=0 the tables will be dumped and\nC                      cleared.\nC                      when KFLAG < 0, the tables will be dumped and\nC                      not cleared.\nC        NERR   :IN    is the error number.\nC        LEVEL  :IN    is the error severity.\nC        ICOUNT :OUT   the number of times this message has been seen,\nC                      or zero if the table has overflowed and does not\nC                      contain this message specifically.  When KFLAG=0,\nC                      ICOUNT will not be altered.\nC\nC *Description:\nC\nC   Record that this error occurred and possibly dump and clear the\nC   tables.\nC\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  I1MACH, XGETUA\nC***REVISION HISTORY  (YYMMDD)\nC   800319  DATE WRITTEN\nC   861211  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900413  Routine modified to remove reference to KFLAG.  (WRB)\nC   900510  Changed to add LIBRARY NAME and SUBROUTINE to calling\nC           sequence, use IF-THEN-ELSE, make number of saved entries\nC           easily changeable, changed routine name from XERSAV to\nC           XERSVE.  (RWC)\nC   910626  Added LIBTAB and SUBTAB to SAVE statement.  (BKS)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XERSVE\n      PARAMETER (LENTAB=10)\n      INTEGER LUN(5)\n      CHARACTER*(*) LIBRAR, SUBROU, MESSG\n      CHARACTER*8  LIBTAB(LENTAB), SUBTAB(LENTAB), LIB, SUB\n      CHARACTER*20 MESTAB(LENTAB), MES\n      DIMENSION NERTAB(LENTAB), LEVTAB(LENTAB), KOUNT(LENTAB)\n      SAVE LIBTAB, SUBTAB, MESTAB, NERTAB, LEVTAB, KOUNT, KOUNTX, NMSG\n      DATA KOUNTX/0/, NMSG/0/\nC***FIRST EXECUTABLE STATEMENT  XERSVE\nC\n      IF (KFLAG.LE.0) THEN\nC\nC        Dump the table.\nC\n         IF (NMSG.EQ.0) RETURN\nC\nC        Print to each unit.\nC\n         CALL XGETUA (LUN, NUNIT)\n         DO 20 KUNIT = 1,NUNIT\n            IUNIT = LUN(KUNIT)\n            IF (IUNIT.EQ.0) IUNIT = I1MACH(4)\nC\nC           Print the table header.\nC\n            WRITE (IUNIT,9000)\nC\nC           Print body of table.\nC\n            DO 10 I = 1,NMSG\n               WRITE (IUNIT,9010) LIBTAB(I), SUBTAB(I), MESTAB(I),\n     *            NERTAB(I),LEVTAB(I),KOUNT(I)\n   10       CONTINUE\nC\nC           Print number of other errors.\nC\n            IF (KOUNTX.NE.0) WRITE (IUNIT,9020) KOUNTX\n            WRITE (IUNIT,9030)\n   20    CONTINUE\nC\nC        Clear the error tables.\nC\n         IF (KFLAG.EQ.0) THEN\n            NMSG = 0\n            KOUNTX = 0\n         ENDIF\n      ELSE\nC\nC        PROCESS A MESSAGE...\nC        SEARCH FOR THIS MESSG, OR ELSE AN EMPTY SLOT FOR THIS MESSG,\nC        OR ELSE DETERMINE THAT THE ERROR TABLE IS FULL.\nC\n         LIB = LIBRAR\n         SUB = SUBROU\n         MES = MESSG\n         DO 30 I = 1,NMSG\n            IF (LIB.EQ.LIBTAB(I) .AND. SUB.EQ.SUBTAB(I) .AND.\n     *         MES.EQ.MESTAB(I) .AND. NERR.EQ.NERTAB(I) .AND.\n     *         LEVEL.EQ.LEVTAB(I)) THEN\n                  KOUNT(I) = KOUNT(I) + 1\n                  ICOUNT = KOUNT(I)\n                  RETURN\n            ENDIF\n   30    CONTINUE\nC\n         IF (NMSG.LT.LENTAB) THEN\nC\nC           Empty slot found for new message.\nC\n            NMSG = NMSG + 1\n            LIBTAB(I) = LIB\n            SUBTAB(I) = SUB\n            MESTAB(I) = MES\n            NERTAB(I) = NERR\n            LEVTAB(I) = LEVEL\n            KOUNT (I) = 1\n            ICOUNT    = 1\n         ELSE\nC\nC           Table is full.\nC\n            KOUNTX = KOUNTX+1\n            ICOUNT = 0\n         ENDIF\n      ENDIF\n      RETURN\nC\nC     Formats.\nC\n 9000 FORMAT ('0          ERROR MESSAGE SUMMARY' /\n     +   ' LIBRARY    SUBROUTINE MESSAGE START             NERR',\n     +   '     LEVEL     COUNT')\n 9010 FORMAT (1X,A,3X,A,3X,A,3I10)\n 9020 FORMAT ('0OTHER ERRORS NOT INDIVIDUALLY TABULATED = ', I10)\n 9030 FORMAT (1X)\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xgetf.f",
    "content": "*DECK XGETF\n      SUBROUTINE XGETF (KONTRL)\nC***BEGIN PROLOGUE  XGETF\nC***PURPOSE  Return the current value of the error control flag.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3C\nC***TYPE      ALL (XGETF-A)\nC***KEYWORDS  ERROR, XERROR\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC   Abstract\nC        XGETF returns the current value of the error control flag\nC        in KONTRL.  See subroutine XSETF for flag value meanings.\nC        (KONTRL is an output parameter only.)\nC\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  J4SAVE\nC***REVISION HISTORY  (YYMMDD)\nC   790801  DATE WRITTEN\nC   861211  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XGETF\nC***FIRST EXECUTABLE STATEMENT  XGETF\n      KONTRL = J4SAVE(2,0,.FALSE.)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xgetua.f",
    "content": "*DECK XGETUA\n      SUBROUTINE XGETUA (IUNITA, N)\nC***BEGIN PROLOGUE  XGETUA\nC***PURPOSE  Return unit number(s) to which error messages are being\nC            sent.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3C\nC***TYPE      ALL (XGETUA-A)\nC***KEYWORDS  ERROR, XERROR\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC     Abstract\nC        XGETUA may be called to determine the unit number or numbers\nC        to which error messages are being sent.\nC        These unit numbers may have been set by a call to XSETUN,\nC        or a call to XSETUA, or may be a default value.\nC\nC     Description of Parameters\nC      --Output--\nC        IUNIT - an array of one to five unit numbers, depending\nC                on the value of N.  A value of zero refers to the\nC                default unit, as defined by the I1MACH machine\nC                constant routine.  Only IUNIT(1),...,IUNIT(N) are\nC                defined by XGETUA.  The values of IUNIT(N+1),...,\nC                IUNIT(5) are not defined (for N .LT. 5) or altered\nC                in any way by XGETUA.\nC        N     - the number of units to which copies of the\nC                error messages are being sent.  N will be in the\nC                range from 1 to 5.\nC\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  J4SAVE\nC***REVISION HISTORY  (YYMMDD)\nC   790801  DATE WRITTEN\nC   861211  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XGETUA\n      DIMENSION IUNITA(5)\nC***FIRST EXECUTABLE STATEMENT  XGETUA\n      N = J4SAVE(5,0,.FALSE.)\n      DO 30 I=1,N\n         INDEX = I+4\n         IF (I.EQ.1) INDEX = 3\n         IUNITA(I) = J4SAVE(INDEX,0,.FALSE.)\n   30 CONTINUE\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xsetf.f",
    "content": "*DECK XSETF\n      SUBROUTINE XSETF (KONTRL)\nC***BEGIN PROLOGUE  XSETF\nC***PURPOSE  Set the error control flag.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3A\nC***TYPE      ALL (XSETF-A)\nC***KEYWORDS  ERROR, XERROR\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC     Abstract\nC        XSETF sets the error control flag value to KONTRL.\nC        (KONTRL is an input parameter only.)\nC        The following table shows how each message is treated,\nC        depending on the values of KONTRL and LEVEL.  (See XERMSG\nC        for description of LEVEL.)\nC\nC        If KONTRL is zero or negative, no information other than the\nC        message itself (including numeric values, if any) will be\nC        printed.  If KONTRL is positive, introductory messages,\nC        trace-backs, etc., will be printed in addition to the message.\nC\nC              ABS(KONTRL)\nC        LEVEL        0              1              2\nC        value\nC          2        fatal          fatal          fatal\nC\nC          1     not printed      printed         fatal\nC\nC          0     not printed      printed        printed\nC\nC         -1     not printed      printed        printed\nC                                  only           only\nC                                  once           once\nC\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  J4SAVE, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   790801  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900510  Change call to XERRWV to XERMSG.  (RWC)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XSETF\n      CHARACTER *8 XERN1\nC***FIRST EXECUTABLE STATEMENT  XSETF\n      IF (ABS(KONTRL) .GT. 2) THEN\n         WRITE (XERN1, '(I8)') KONTRL\n         CALL XERMSG ('SLATEC', 'XSETF',\n     *      'INVALID ARGUMENT = ' // XERN1, 1, 2)\n         RETURN\n      ENDIF\nC\n      JUNK = J4SAVE(2,KONTRL,.TRUE.)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-err/xsetua.f",
    "content": "*DECK XSETUA\n      SUBROUTINE XSETUA (IUNITA, N)\nC***BEGIN PROLOGUE  XSETUA\nC***PURPOSE  Set logical unit numbers (up to 5) to which error\nC            messages are to be sent.\nC***LIBRARY   SLATEC (XERROR)\nC***CATEGORY  R3B\nC***TYPE      ALL (XSETUA-A)\nC***KEYWORDS  ERROR, XERROR\nC***AUTHOR  Jones, R. E., (SNLA)\nC***DESCRIPTION\nC\nC     Abstract\nC        XSETUA may be called to declare a list of up to five\nC        logical units, each of which is to receive a copy of\nC        each error message processed by this package.\nC        The purpose of XSETUA is to allow simultaneous printing\nC        of each error message on, say, a main output file,\nC        an interactive terminal, and other files such as graphics\nC        communication files.\nC\nC     Description of Parameters\nC      --Input--\nC        IUNIT - an array of up to five unit numbers.\nC                Normally these numbers should all be different\nC                (but duplicates are not prohibited.)\nC        N     - the number of unit numbers provided in IUNIT\nC                must have 1 .LE. N .LE. 5.\nC\nC***REFERENCES  R. E. Jones and D. K. Kahaner, XERROR, the SLATEC\nC                 Error-handling Package, SAND82-0800, Sandia\nC                 Laboratories, 1982.\nC***ROUTINES CALLED  J4SAVE, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   790801  DATE WRITTEN\nC   861211  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900510  Change call to XERRWV to XERMSG.  (RWC)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  XSETUA\n      DIMENSION IUNITA(5)\n      CHARACTER *8 XERN1\nC***FIRST EXECUTABLE STATEMENT  XSETUA\nC\n      IF (N.LT.1 .OR. N.GT.5) THEN\n         WRITE (XERN1, '(I8)') N\n         CALL XERMSG ('SLATEC', 'XSETUA',\n     *      'INVALID NUMBER OF UNITS, N = ' // XERN1, 1, 2)\n         RETURN\n      ENDIF\nC\n      DO 10 I=1,N\n         INDEX = I+4\n         IF (I.EQ.1) INDEX = 3\n         JUNK = J4SAVE(INDEX,IUNITA(I),.TRUE.)\n   10 CONTINUE\n      JUNK = J4SAVE(5,N,.TRUE.)\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/albeta.f",
    "content": "*DECK ALBETA\n      FUNCTION ALBETA (A, B)\nC***BEGIN PROLOGUE  ALBETA\nC***PURPOSE  Compute the natural logarithm of the complete Beta\nC            function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7B\nC***TYPE      SINGLE PRECISION (ALBETA-S, DLBETA-D, CLBETA-C)\nC***KEYWORDS  FNLIB, LOGARITHM OF THE COMPLETE BETA FUNCTION,\nC             SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC ALBETA computes the natural log of the complete beta function.\nC\nC Input Parameters:\nC       A   real and positive\nC       B   real and positive\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  ALNGAM, ALNREL, GAMMA, R9LGMC, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900326  Removed duplicate information from DESCRIPTION section.\nC           (WRB)\nC   900727  Added EXTERNAL statement.  (WRB)\nC***END PROLOGUE  ALBETA\n      EXTERNAL GAMMA\n      SAVE SQ2PIL\n      DATA SQ2PIL / 0.9189385332 0467274 E0 /\nC***FIRST EXECUTABLE STATEMENT  ALBETA\n      P = MIN (A, B)\n      Q = MAX (A, B)\nC\n      IF (P .LE. 0.0) CALL XERMSG ('SLATEC', 'ALBETA',\n     +   'BOTH ARGUMENTS MUST BE GT ZERO', 1, 2)\n      IF (P.GE.10.0) GO TO 30\n      IF (Q.GE.10.0) GO TO 20\nC\nC P AND Q ARE SMALL.\nC\n      ALBETA = LOG(GAMMA(P) * (GAMMA(Q)/GAMMA(P+Q)) )\n      RETURN\nC\nC P IS SMALL, BUT Q IS BIG.\nC\n 20   CORR = R9LGMC(Q) - R9LGMC(P+Q)\n      ALBETA = ALNGAM(P) + CORR + P - P*LOG(P+Q) +\n     1  (Q-0.5)*ALNREL(-P/(P+Q))\n      RETURN\nC\nC P AND Q ARE BIG.\nC\n 30   CORR = R9LGMC(P) + R9LGMC(Q) - R9LGMC(P+Q)\n      ALBETA = -0.5*LOG(Q) + SQ2PIL + CORR + (P-0.5)*LOG(P/(P+Q))\n     1  + Q*ALNREL(-P/(P+Q))\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/algams.f",
    "content": "*DECK ALGAMS\n      SUBROUTINE ALGAMS (X, ALGAM, SGNGAM)\nC***BEGIN PROLOGUE  ALGAMS\nC***PURPOSE  Compute the logarithm of the absolute value of the Gamma\nC            function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A\nC***TYPE      SINGLE PRECISION (ALGAMS-S, DLGAMS-D)\nC***KEYWORDS  ABSOLUTE VALUE OF THE LOGARITHM OF THE GAMMA FUNCTION,\nC             FNLIB, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Evaluates the logarithm of the absolute value of the gamma\nC function.\nC     X           - input argument\nC     ALGAM       - result\nC     SGNGAM      - is set to the sign of GAMMA(X) and will\nC                   be returned at +1.0 or -1.0.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  ALNGAM\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC***END PROLOGUE  ALGAMS\nC***FIRST EXECUTABLE STATEMENT  ALGAMS\n      ALGAM = ALNGAM(X)\n      SGNGAM = 1.0\n      IF (X.GT.0.0) RETURN\nC\n      INT = MOD (-AINT(X), 2.0) + 0.1\n      IF (INT.EQ.0) SGNGAM = -1.0\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/alngam.f",
    "content": "*DECK ALNGAM\n      FUNCTION ALNGAM (X)\nC***BEGIN PROLOGUE  ALNGAM\nC***PURPOSE  Compute the logarithm of the absolute value of the Gamma\nC            function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A\nC***TYPE      SINGLE PRECISION (ALNGAM-S, DLNGAM-D, CLNGAM-C)\nC***KEYWORDS  ABSOLUTE VALUE, COMPLETE GAMMA FUNCTION, FNLIB, LOGARITHM,\nC             SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC ALNGAM(X) computes the logarithm of the absolute value of the\nC gamma function at X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  GAMMA, R1MACH, R9LGMC, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900326  Removed duplicate information from DESCRIPTION section.\nC           (WRB)\nC   900727  Added EXTERNAL statement.  (WRB)\nC***END PROLOGUE  ALNGAM\n      LOGICAL FIRST\n      EXTERNAL GAMMA\n      SAVE SQ2PIL, SQPI2L, PI, XMAX, DXREL, FIRST\n      DATA SQ2PIL / 0.9189385332 0467274E0/\n      DATA SQPI2L / 0.2257913526 4472743E0/\n      DATA PI     / 3.1415926535 8979324E0/\n      DATA FIRST  /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  ALNGAM\n      IF (FIRST) THEN\n         XMAX = R1MACH(2)/LOG(R1MACH(2))\n         DXREL = SQRT (R1MACH(4))\n      ENDIF\n      FIRST = .FALSE.\nC\n      Y = ABS(X)\n      IF (Y.GT.10.0) GO TO 20\nC\nC LOG (ABS (GAMMA(X))) FOR  ABS(X) .LE. 10.0\nC\n      ALNGAM = LOG (ABS (GAMMA(X)))\n      RETURN\nC\nC LOG (ABS (GAMMA(X))) FOR ABS(X) .GT. 10.0\nC\n 20   IF (Y .GT. XMAX) CALL XERMSG ('SLATEC', 'ALNGAM',\n     +   'ABS(X) SO BIG ALNGAM OVERFLOWS', 2, 2)\nC\n      IF (X.GT.0.) ALNGAM = SQ2PIL + (X-0.5)*LOG(X) - X + R9LGMC(Y)\n      IF (X.GT.0.) RETURN\nC\n      SINPIY = ABS (SIN(PI*Y))\n      IF (SINPIY .EQ. 0.) CALL XERMSG ('SLATEC', 'ALNGAM',\n     +   'X IS A NEGATIVE INTEGER', 3, 2)\nC\n      IF (ABS((X-AINT(X-0.5))/X) .LT. DXREL) CALL XERMSG ('SLATEC',\n     +   'ALNGAM', 'ANSWER LT HALF PRECISION BECAUSE X TOO NEAR ' //\n     +   'NEGATIVE INTEGER', 1, 1)\nC\n      ALNGAM = SQPI2L + (X-0.5)*LOG(Y) - X - LOG(SINPIY) - R9LGMC(Y)\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/alnrel.f",
    "content": "*DECK ALNREL\n      FUNCTION ALNREL (X)\nC***BEGIN PROLOGUE  ALNREL\nC***PURPOSE  Evaluate ln(1+X) accurate in the sense of relative error.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C4B\nC***TYPE      SINGLE PRECISION (ALNREL-S, DLNREL-D, CLNREL-C)\nC***KEYWORDS  ELEMENTARY FUNCTIONS, FNLIB, LOGARITHM\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC ALNREL(X) evaluates ln(1+X) accurately in the sense of relative\nC error when X is very small.  This routine must be used to\nC maintain relative error accuracy whenever X is small and\nC accurately known.\nC\nC Series for ALNR       on the interval -3.75000D-01 to  3.75000D-01\nC                                        with weighted error   1.93E-17\nC                                         log weighted error  16.72\nC                               significant figures required  16.44\nC                                    decimal places required  17.40\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  CSEVL, INITS, R1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770401  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900326  Removed duplicate information from DESCRIPTION section.\nC           (WRB)\nC***END PROLOGUE  ALNREL\n      DIMENSION ALNRCS(23)\n      LOGICAL FIRST\n      SAVE ALNRCS, NLNREL, XMIN, FIRST\n      DATA ALNRCS( 1) /   1.0378693562 743770E0 /\n      DATA ALNRCS( 2) /   -.1336430150 4908918E0 /\n      DATA ALNRCS( 3) /    .0194082491 35520563E0 /\n      DATA ALNRCS( 4) /   -.0030107551 12753577E0 /\n      DATA ALNRCS( 5) /    .0004869461 47971548E0 /\n      DATA ALNRCS( 6) /   -.0000810548 81893175E0 /\n      DATA ALNRCS( 7) /    .0000137788 47799559E0 /\n      DATA ALNRCS( 8) /   -.0000023802 21089435E0 /\n      DATA ALNRCS( 9) /    .0000004164 04162138E0 /\n      DATA ALNRCS(10) /   -.0000000735 95828378E0 /\n      DATA ALNRCS(11) /    .0000000131 17611876E0 /\n      DATA ALNRCS(12) /   -.0000000023 54670931E0 /\n      DATA ALNRCS(13) /    .0000000004 25227732E0 /\n      DATA ALNRCS(14) /   -.0000000000 77190894E0 /\n      DATA ALNRCS(15) /    .0000000000 14075746E0 /\n      DATA ALNRCS(16) /   -.0000000000 02576907E0 /\n      DATA ALNRCS(17) /    .0000000000 00473424E0 /\n      DATA ALNRCS(18) /   -.0000000000 00087249E0 /\n      DATA ALNRCS(19) /    .0000000000 00016124E0 /\n      DATA ALNRCS(20) /   -.0000000000 00002987E0 /\n      DATA ALNRCS(21) /    .0000000000 00000554E0 /\n      DATA ALNRCS(22) /   -.0000000000 00000103E0 /\n      DATA ALNRCS(23) /    .0000000000 00000019E0 /\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  ALNREL\n      IF (FIRST) THEN\n         NLNREL = INITS (ALNRCS, 23, 0.1*R1MACH(3))\n         XMIN = -1.0 + SQRT(R1MACH(4))\n      ENDIF\n      FIRST = .FALSE.\nC\n      IF (X .LE. (-1.0)) CALL XERMSG ('SLATEC', 'ALNREL', 'X IS LE -1',\n     +   2, 2)\n      IF (X .LT. XMIN) CALL XERMSG ('SLATEC', 'ALNREL',\n     +   'ANSWER LT HALF PRECISION BECAUSE X TOO NEAR -1', 1, 1)\nC\n      IF (ABS(X).LE.0.375) ALNREL = X*(1. -\n     1  X*CSEVL (X/.375, ALNRCS, NLNREL))\n      IF (ABS(X).GT.0.375) ALNREL = LOG (1.0+X)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/csevl.f",
    "content": "*DECK CSEVL\n      FUNCTION CSEVL (X, CS, N)\nC***BEGIN PROLOGUE  CSEVL\nC***PURPOSE  Evaluate a Chebyshev series.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C3A2\nC***TYPE      SINGLE PRECISION (CSEVL-S, DCSEVL-D)\nC***KEYWORDS  CHEBYSHEV SERIES, FNLIB, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC  Evaluate the N-term Chebyshev series CS at X.  Adapted from\nC  a method presented in the paper by Broucke referenced below.\nC\nC       Input Arguments --\nC  X    value at which the series is to be evaluated.\nC  CS   array of N terms of a Chebyshev series.  In evaluating\nC       CS, only half the first coefficient is summed.\nC  N    number of terms in array CS.\nC\nC***REFERENCES  R. Broucke, Ten subroutines for the manipulation of\nC                 Chebyshev series, Algorithm 446, Communications of\nC                 the A.C.M. 16, (1973) pp. 254-256.\nC               L. Fox and I. B. Parker, Chebyshev Polynomials in\nC                 Numerical Analysis, Oxford University Press, 1968,\nC                 page 56.\nC***ROUTINES CALLED  R1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770401  DATE WRITTEN\nC   890831  Modified array declarations.  (WRB)\nC   890831  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900329  Prologued revised extensively and code rewritten to allow\nC           X to be slightly outside interval (-1,+1).  (WRB)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  CSEVL\n      REAL B0, B1, B2, CS(*), ONEPL, TWOX, X\n      LOGICAL FIRST\n      SAVE FIRST, ONEPL\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  CSEVL\n      IF (FIRST) ONEPL = 1.0E0 + R1MACH(4)\n      FIRST = .FALSE.\n      IF (N .LT. 1) CALL XERMSG ('SLATEC', 'CSEVL',\n     +   'NUMBER OF TERMS .LE. 0', 2, 2)\n      IF (N .GT. 1000) CALL XERMSG ('SLATEC', 'CSEVL',\n     +   'NUMBER OF TERMS .GT. 1000', 3, 2)\n      IF (ABS(X) .GT. ONEPL) CALL XERMSG ('SLATEC', 'CSEVL',\n     +   'X OUTSIDE THE INTERVAL (-1,+1)', 1, 1)\nC\n      B1 = 0.0E0\n      B0 = 0.0E0\n      TWOX = 2.0*X\n      DO 10 I = 1,N\n         B2 = B1\n         B1 = B0\n         NI = N + 1 - I\n         B0 = TWOX*B1 - B2 + CS(NI)\n   10 CONTINUE\nC\n      CSEVL = 0.5E0*(B0-B2)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/d9gmit.f",
    "content": "*DECK D9GMIT\n      DOUBLE PRECISION FUNCTION D9GMIT (A, X, ALGAP1, SGNGAM, ALX)\nC***BEGIN PROLOGUE  D9GMIT\nC***SUBSIDIARY\nC***PURPOSE  Compute Tricomi's incomplete Gamma function for small\nC            arguments.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7E\nC***TYPE      DOUBLE PRECISION (R9GMIT-S, D9GMIT-D)\nC***KEYWORDS  COMPLEMENTARY INCOMPLETE GAMMA FUNCTION, FNLIB, SMALL X,\nC             SPECIAL FUNCTIONS, TRICOMI\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Compute Tricomi's incomplete gamma function for small X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH, DLNGAM, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890911  Removed unnecessary intrinsics.  (WRB)\nC   890911  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900720  Routine changed from user-callable to subsidiary.  (WRB)\nC***END PROLOGUE  D9GMIT\n      DOUBLE PRECISION A, X, ALGAP1, SGNGAM, ALX, AE, AEPS, ALGS, ALG2,\n     1  BOT, EPS, FK, S, SGNG2, T, TE, D1MACH, DLNGAM\n      LOGICAL FIRST\n      SAVE EPS, BOT, FIRST\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  D9GMIT\n      IF (FIRST) THEN\n         EPS = 0.5D0*D1MACH(3)\n         BOT = LOG (D1MACH(1))\n      ENDIF\n      FIRST = .FALSE.\nC\n      IF (X .LE. 0.D0) CALL XERMSG ('SLATEC', 'D9GMIT',\n     +   'X SHOULD BE GT 0', 1, 2)\nC\n      MA = A + 0.5D0\n      IF (A.LT.0.D0) MA = A - 0.5D0\n      AEPS = A - MA\nC\n      AE = A\n      IF (A.LT.(-0.5D0)) AE = AEPS\nC\n      T = 1.D0\n      TE = AE\n      S = T\n      DO 20 K=1,200\n        FK = K\n        TE = -X*TE/FK\n        T = TE/(AE+FK)\n        S = S + T\n        IF (ABS(T).LT.EPS*ABS(S)) GO TO 30\n 20   CONTINUE\n      CALL XERMSG ('SLATEC', 'D9GMIT',\n     +   'NO CONVERGENCE IN 200 TERMS OF TAYLOR-S SERIES', 2, 2)\nC\n 30   IF (A.GE.(-0.5D0)) ALGS = -ALGAP1 + LOG(S)\n      IF (A.GE.(-0.5D0)) GO TO 60\nC\n      ALGS = -DLNGAM(1.D0+AEPS) + LOG(S)\n      S = 1.0D0\n      M = -MA - 1\n      IF (M.EQ.0) GO TO 50\n      T = 1.0D0\n      DO 40 K=1,M\n        T = X*T/(AEPS-(M+1-K))\n        S = S + T\n        IF (ABS(T).LT.EPS*ABS(S)) GO TO 50\n 40   CONTINUE\nC\n 50   D9GMIT = 0.0D0\n      ALGS = -MA*LOG(X) + ALGS\n      IF (S.EQ.0.D0 .OR. AEPS.EQ.0.D0) GO TO 60\nC\n      SGNG2 = SGNGAM * SIGN (1.0D0, S)\n      ALG2 = -X - ALGAP1 + LOG(ABS(S))\nC\n      IF (ALG2.GT.BOT) D9GMIT = SGNG2 * EXP(ALG2)\n      IF (ALGS.GT.BOT) D9GMIT = D9GMIT + EXP(ALGS)\n      RETURN\nC\n 60   D9GMIT = EXP (ALGS)\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/d9lgic.f",
    "content": "*DECK D9LGIC\n      DOUBLE PRECISION FUNCTION D9LGIC (A, X, ALX)\nC***BEGIN PROLOGUE  D9LGIC\nC***SUBSIDIARY\nC***PURPOSE  Compute the log complementary incomplete Gamma function\nC            for large X and for A .LE. X.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7E\nC***TYPE      DOUBLE PRECISION (R9LGIC-S, D9LGIC-D)\nC***KEYWORDS  COMPLEMENTARY INCOMPLETE GAMMA FUNCTION, FNLIB, LARGE X,\nC             LOGARITHM, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Compute the log complementary incomplete gamma function for large X\nC and for A .LE. X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900720  Routine changed from user-callable to subsidiary.  (WRB)\nC***END PROLOGUE  D9LGIC\n      DOUBLE PRECISION A, X, ALX, EPS, FK, P, R, S, T, XMA, XPA, D1MACH\n      SAVE EPS\n      DATA EPS / 0.D0 /\nC***FIRST EXECUTABLE STATEMENT  D9LGIC\n      IF (EPS.EQ.0.D0) EPS = 0.5D0*D1MACH(3)\nC\n      XPA = X + 1.0D0 - A\n      XMA = X - 1.D0 - A\nC\n      R = 0.D0\n      P = 1.D0\n      S = P\n      DO 10 K=1,300\n        FK = K\n        T = FK*(A-FK)*(1.D0+R)\n        R = -T/((XMA+2.D0*FK)*(XPA+2.D0*FK)+T)\n        P = R*P\n        S = S + P\n        IF (ABS(P).LT.EPS*S) GO TO 20\n 10   CONTINUE\n      CALL XERMSG ('SLATEC', 'D9LGIC',\n     +   'NO CONVERGENCE IN 300 TERMS OF CONTINUED FRACTION', 1, 2)\nC\n 20   D9LGIC = A*ALX - X + LOG(S/XPA)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/d9lgit.f",
    "content": "*DECK D9LGIT\n      DOUBLE PRECISION FUNCTION D9LGIT (A, X, ALGAP1)\nC***BEGIN PROLOGUE  D9LGIT\nC***SUBSIDIARY\nC***PURPOSE  Compute the logarithm of Tricomi's incomplete Gamma\nC            function with Perron's continued fraction for large X and\nC            A .GE. X.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7E\nC***TYPE      DOUBLE PRECISION (R9LGIT-S, D9LGIT-D)\nC***KEYWORDS  FNLIB, INCOMPLETE GAMMA FUNCTION, LOGARITHM,\nC             PERRON'S CONTINUED FRACTION, SPECIAL FUNCTIONS, TRICOMI\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Compute the log of Tricomi's incomplete gamma function with Perron's\nC continued fraction for large X and for A .GE. X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900720  Routine changed from user-callable to subsidiary.  (WRB)\nC***END PROLOGUE  D9LGIT\n      DOUBLE PRECISION A, X, ALGAP1, AX, A1X, EPS, FK, HSTAR, P, R, S,\n     1  SQEPS, T, D1MACH\n      LOGICAL FIRST\n      SAVE EPS, SQEPS, FIRST\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  D9LGIT\n      IF (FIRST) THEN\n         EPS = 0.5D0*D1MACH(3)\n         SQEPS = SQRT(D1MACH(4))\n      ENDIF\n      FIRST = .FALSE.\nC\n      IF (X .LE. 0.D0 .OR. A .LT. X) CALL XERMSG ('SLATEC', 'D9LGIT',\n     +   'X SHOULD BE GT 0.0 AND LE A', 2, 2)\nC\n      AX = A + X\n      A1X = AX + 1.0D0\n      R = 0.D0\n      P = 1.D0\n      S = P\n      DO 20 K=1,200\n        FK = K\n        T = (A+FK)*X*(1.D0+R)\n        R = T/((AX+FK)*(A1X+FK)-T)\n        P = R*P\n        S = S + P\n        IF (ABS(P).LT.EPS*S) GO TO 30\n 20   CONTINUE\n      CALL XERMSG ('SLATEC', 'D9LGIT',\n     +   'NO CONVERGENCE IN 200 TERMS OF CONTINUED FRACTION', 3, 2)\nC\n 30   HSTAR = 1.0D0 - X*S/A1X\n      IF (HSTAR .LT. SQEPS) CALL XERMSG ('SLATEC', 'D9LGIT',\n     +   'RESULT LESS THAN HALF PRECISION', 1, 1)\nC\n      D9LGIT = -X - ALGAP1 - LOG(HSTAR)\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/d9lgmc.f",
    "content": "*DECK D9LGMC\n      DOUBLE PRECISION FUNCTION D9LGMC (X)\nC***BEGIN PROLOGUE  D9LGMC\nC***SUBSIDIARY\nC***PURPOSE  Compute the log Gamma correction factor so that\nC            LOG(DGAMMA(X)) = LOG(SQRT(2*PI)) + (X-5.)*LOG(X) - X\nC            + D9LGMC(X).\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7E\nC***TYPE      DOUBLE PRECISION (R9LGMC-S, D9LGMC-D, C9LGMC-C)\nC***KEYWORDS  COMPLETE GAMMA FUNCTION, CORRECTION TERM, FNLIB,\nC             LOG GAMMA, LOGARITHM, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Compute the log gamma correction factor for X .GE. 10. so that\nC LOG (DGAMMA(X)) = LOG(SQRT(2*PI)) + (X-.5)*LOG(X) - X + D9lGMC(X)\nC\nC Series for ALGM       on the interval  0.          to  1.00000E-02\nC                                        with weighted error   1.28E-31\nC                                         log weighted error  30.89\nC                               significant figures required  29.81\nC                                    decimal places required  31.48\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH, DCSEVL, INITDS, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900720  Routine changed from user-callable to subsidiary.  (WRB)\nC***END PROLOGUE  D9LGMC\n      DOUBLE PRECISION X, ALGMCS(15), XBIG, XMAX, DCSEVL, D1MACH\n      LOGICAL FIRST\n      SAVE ALGMCS, NALGM, XBIG, XMAX, FIRST\n      DATA ALGMCS(  1) / +.1666389480 4518632472 0572965082 2 D+0      /\n      DATA ALGMCS(  2) / -.1384948176 0675638407 3298605913 5 D-4      /\n      DATA ALGMCS(  3) / +.9810825646 9247294261 5717154748 7 D-8      /\n      DATA ALGMCS(  4) / -.1809129475 5724941942 6330626671 9 D-10     /\n      DATA ALGMCS(  5) / +.6221098041 8926052271 2601554341 6 D-13     /\n      DATA ALGMCS(  6) / -.3399615005 4177219443 0333059966 6 D-15     /\n      DATA ALGMCS(  7) / +.2683181998 4826987489 5753884666 6 D-17     /\n      DATA ALGMCS(  8) / -.2868042435 3346432841 4462239999 9 D-19     /\n      DATA ALGMCS(  9) / +.3962837061 0464348036 7930666666 6 D-21     /\n      DATA ALGMCS( 10) / -.6831888753 9857668701 1199999999 9 D-23     /\n      DATA ALGMCS( 11) / +.1429227355 9424981475 7333333333 3 D-24     /\n      DATA ALGMCS( 12) / -.3547598158 1010705471 9999999999 9 D-26     /\n      DATA ALGMCS( 13) / +.1025680058 0104709120 0000000000 0 D-27     /\n      DATA ALGMCS( 14) / -.3401102254 3167487999 9999999999 9 D-29     /\n      DATA ALGMCS( 15) / +.1276642195 6300629333 3333333333 3 D-30     /\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  D9LGMC\n      IF (FIRST) THEN\n         NALGM = INITDS (ALGMCS, 15, REAL(D1MACH(3)) )\n         XBIG = 1.0D0/SQRT(D1MACH(3))\n         XMAX = EXP (MIN(LOG(D1MACH(2)/12.D0), -LOG(12.D0*D1MACH(1))))\n      ENDIF\n      FIRST = .FALSE.\nC\n      IF (X .LT. 10.D0) CALL XERMSG ('SLATEC', 'D9LGMC',\n     +   'X MUST BE GE 10', 1, 2)\n      IF (X.GE.XMAX) GO TO 20\nC\n      D9LGMC = 1.D0/(12.D0*X)\n      IF (X.LT.XBIG) D9LGMC = DCSEVL (2.0D0*(10.D0/X)**2-1.D0, ALGMCS,\n     1  NALGM) / X\n      RETURN\nC\n 20   D9LGMC = 0.D0\n      CALL XERMSG ('SLATEC', 'D9LGMC', 'X SO BIG D9LGMC UNDERFLOWS', 2,\n     +   1)\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dcsevl.f",
    "content": "*DECK DCSEVL\n      DOUBLE PRECISION FUNCTION DCSEVL (X, CS, N)\nC***BEGIN PROLOGUE  DCSEVL\nC***PURPOSE  Evaluate a Chebyshev series.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C3A2\nC***TYPE      DOUBLE PRECISION (CSEVL-S, DCSEVL-D)\nC***KEYWORDS  CHEBYSHEV SERIES, FNLIB, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC  Evaluate the N-term Chebyshev series CS at X.  Adapted from\nC  a method presented in the paper by Broucke referenced below.\nC\nC       Input Arguments --\nC  X    value at which the series is to be evaluated.\nC  CS   array of N terms of a Chebyshev series.  In evaluating\nC       CS, only half the first coefficient is summed.\nC  N    number of terms in array CS.\nC\nC***REFERENCES  R. Broucke, Ten subroutines for the manipulation of\nC                 Chebyshev series, Algorithm 446, Communications of\nC                 the A.C.M. 16, (1973) pp. 254-256.\nC               L. Fox and I. B. Parker, Chebyshev Polynomials in\nC                 Numerical Analysis, Oxford University Press, 1968,\nC                 page 56.\nC***ROUTINES CALLED  D1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770401  DATE WRITTEN\nC   890831  Modified array declarations.  (WRB)\nC   890831  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900329  Prologued revised extensively and code rewritten to allow\nC           X to be slightly outside interval (-1,+1).  (WRB)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  DCSEVL\n      DOUBLE PRECISION B0, B1, B2, CS(*), ONEPL, TWOX, X, D1MACH\n      LOGICAL FIRST\n      SAVE FIRST, ONEPL\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  DCSEVL\n      IF (FIRST) ONEPL = 1.0D0 + D1MACH(4)\n      FIRST = .FALSE.\n      IF (N .LT. 1) CALL XERMSG ('SLATEC', 'DCSEVL',\n     +   'NUMBER OF TERMS .LE. 0', 2, 2)\n      IF (N .GT. 1000) CALL XERMSG ('SLATEC', 'DCSEVL',\n     +   'NUMBER OF TERMS .GT. 1000', 3, 2)\n      IF (ABS(X) .GT. ONEPL) CALL XERMSG ('SLATEC', 'DCSEVL',\n     +   'X OUTSIDE THE INTERVAL (-1,+1)', 1, 1)\nC\n      B1 = 0.0D0\n      B0 = 0.0D0\n      TWOX = 2.0D0*X\n      DO 10 I = 1,N\n         B2 = B1\n         B1 = B0\n         NI = N + 1 - I\n         B0 = TWOX*B1 - B2 + CS(NI)\n   10 CONTINUE\nC\n      DCSEVL = 0.5D0*(B0-B2)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dgamlm.f",
    "content": "*DECK DGAMLM\n      SUBROUTINE DGAMLM (XMIN, XMAX)\nC***BEGIN PROLOGUE  DGAMLM\nC***PURPOSE  Compute the minimum and maximum bounds for the argument in\nC            the Gamma function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A, R2\nC***TYPE      DOUBLE PRECISION (GAMLIM-S, DGAMLM-D)\nC***KEYWORDS  COMPLETE GAMMA FUNCTION, FNLIB, LIMITS, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Calculate the minimum and maximum legal bounds for X in gamma(X).\nC XMIN and XMAX are not the only bounds, but they are the only non-\nC trivial ones to calculate.\nC\nC             Output Arguments --\nC XMIN   double precision minimum legal value of X in gamma(X).  Any\nC        smaller value of X might result in underflow.\nC XMAX   double precision maximum legal value of X in gamma(X).  Any\nC        larger value of X might cause overflow.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC***END PROLOGUE  DGAMLM\n      DOUBLE PRECISION XMIN, XMAX, ALNBIG, ALNSML, XLN, XOLD, D1MACH\nC***FIRST EXECUTABLE STATEMENT  DGAMLM\n      ALNSML = LOG(D1MACH(1))\n      XMIN = -ALNSML\n      DO 10 I=1,10\n        XOLD = XMIN\n        XLN = LOG(XMIN)\n        XMIN = XMIN - XMIN*((XMIN+0.5D0)*XLN - XMIN - 0.2258D0 + ALNSML)\n     1    / (XMIN*XLN+0.5D0)\n        IF (ABS(XMIN-XOLD).LT.0.005D0) GO TO 20\n 10   CONTINUE\n      CALL XERMSG ('SLATEC', 'DGAMLM', 'UNABLE TO FIND XMIN', 1, 2)\nC\n 20   XMIN = -XMIN + 0.01D0\nC\n      ALNBIG = LOG (D1MACH(2))\n      XMAX = ALNBIG\n      DO 30 I=1,10\n        XOLD = XMAX\n        XLN = LOG(XMAX)\n        XMAX = XMAX - XMAX*((XMAX-0.5D0)*XLN - XMAX + 0.9189D0 - ALNBIG)\n     1    / (XMAX*XLN-0.5D0)\n        IF (ABS(XMAX-XOLD).LT.0.005D0) GO TO 40\n 30   CONTINUE\n      CALL XERMSG ('SLATEC', 'DGAMLM', 'UNABLE TO FIND XMAX', 2, 2)\nC\n 40   XMAX = XMAX - 0.01D0\n      XMIN = MAX (XMIN, -XMAX+1.D0)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dgamma.f",
    "content": "*DECK DGAMMA\n      DOUBLE PRECISION FUNCTION DGAMMA (X)\nC***BEGIN PROLOGUE  DGAMMA\nC***PURPOSE  Compute the complete Gamma function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A\nC***TYPE      DOUBLE PRECISION (GAMMA-S, DGAMMA-D, CGAMMA-C)\nC***KEYWORDS  COMPLETE GAMMA FUNCTION, FNLIB, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC DGAMMA(X) calculates the double precision complete Gamma function\nC for double precision argument X.\nC\nC Series for GAM        on the interval  0.          to  1.00000E+00\nC                                        with weighted error   5.79E-32\nC                                         log weighted error  31.24\nC                               significant figures required  30.00\nC                                    decimal places required  32.05\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH, D9LGMC, DCSEVL, DGAMLM, INITDS, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890911  Removed unnecessary intrinsics.  (WRB)\nC   890911  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   920618  Removed space from variable name.  (RWC, WRB)\nC***END PROLOGUE  DGAMMA\n      DOUBLE PRECISION X, GAMCS(42), DXREL, PI, SINPIY, SQ2PIL, XMAX,\n     1  XMIN, Y, D9LGMC, DCSEVL, D1MACH\n      LOGICAL FIRST\nC\n      SAVE GAMCS, PI, SQ2PIL, NGAM, XMIN, XMAX, DXREL, FIRST\n      DATA GAMCS(  1) / +.8571195590 9893314219 2006239994 2 D-2      /\n      DATA GAMCS(  2) / +.4415381324 8410067571 9131577165 2 D-2      /\n      DATA GAMCS(  3) / +.5685043681 5993633786 3266458878 9 D-1      /\n      DATA GAMCS(  4) / -.4219835396 4185605010 1250018662 4 D-2      /\n      DATA GAMCS(  5) / +.1326808181 2124602205 8400679635 2 D-2      /\n      DATA GAMCS(  6) / -.1893024529 7988804325 2394702388 6 D-3      /\n      DATA GAMCS(  7) / +.3606925327 4412452565 7808221722 5 D-4      /\n      DATA GAMCS(  8) / -.6056761904 4608642184 8554829036 5 D-5      /\n      DATA GAMCS(  9) / +.1055829546 3022833447 3182350909 3 D-5      /\n      DATA GAMCS( 10) / -.1811967365 5423840482 9185589116 6 D-6      /\n      DATA GAMCS( 11) / +.3117724964 7153222777 9025459316 9 D-7      /\n      DATA GAMCS( 12) / -.5354219639 0196871408 7408102434 7 D-8      /\n      DATA GAMCS( 13) / +.9193275519 8595889468 8778682594 0 D-9      /\n      DATA GAMCS( 14) / -.1577941280 2883397617 6742327395 3 D-9      /\n      DATA GAMCS( 15) / +.2707980622 9349545432 6654043308 9 D-10     /\n      DATA GAMCS( 16) / -.4646818653 8257301440 8166105893 3 D-11     /\n      DATA GAMCS( 17) / +.7973350192 0074196564 6076717535 9 D-12     /\n      DATA GAMCS( 18) / -.1368078209 8309160257 9949917230 9 D-12     /\n      DATA GAMCS( 19) / +.2347319486 5638006572 3347177168 8 D-13     /\n      DATA GAMCS( 20) / -.4027432614 9490669327 6657053469 9 D-14     /\n      DATA GAMCS( 21) / +.6910051747 3721009121 3833697525 7 D-15     /\n      DATA GAMCS( 22) / -.1185584500 2219929070 5238712619 2 D-15     /\n      DATA GAMCS( 23) / +.2034148542 4963739552 0102605193 2 D-16     /\n      DATA GAMCS( 24) / -.3490054341 7174058492 7401294910 8 D-17     /\n      DATA GAMCS( 25) / +.5987993856 4853055671 3505106602 6 D-18     /\n      DATA GAMCS( 26) / -.1027378057 8722280744 9006977843 1 D-18     /\n      DATA GAMCS( 27) / +.1762702816 0605298249 4275966074 8 D-19     /\n      DATA GAMCS( 28) / -.3024320653 7353062609 5877211204 2 D-20     /\n      DATA GAMCS( 29) / +.5188914660 2183978397 1783355050 6 D-21     /\n      DATA GAMCS( 30) / -.8902770842 4565766924 4925160106 6 D-22     /\n      DATA GAMCS( 31) / +.1527474068 4933426022 7459689130 6 D-22     /\n      DATA GAMCS( 32) / -.2620731256 1873629002 5732833279 9 D-23     /\n      DATA GAMCS( 33) / +.4496464047 8305386703 3104657066 6 D-24     /\n      DATA GAMCS( 34) / -.7714712731 3368779117 0390152533 3 D-25     /\n      DATA GAMCS( 35) / +.1323635453 1260440364 8657271466 6 D-25     /\n      DATA GAMCS( 36) / -.2270999412 9429288167 0231381333 3 D-26     /\n      DATA GAMCS( 37) / +.3896418998 0039914493 2081663999 9 D-27     /\n      DATA GAMCS( 38) / -.6685198115 1259533277 9212799999 9 D-28     /\n      DATA GAMCS( 39) / +.1146998663 1400243843 4761386666 6 D-28     /\n      DATA GAMCS( 40) / -.1967938586 3451346772 9510399999 9 D-29     /\n      DATA GAMCS( 41) / +.3376448816 5853380903 3489066666 6 D-30     /\n      DATA GAMCS( 42) / -.5793070335 7821357846 2549333333 3 D-31     /\n      DATA PI / 3.1415926535 8979323846 2643383279 50 D0 /\n      DATA SQ2PIL / 0.9189385332 0467274178 0329736405 62 D0 /\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  DGAMMA\n      IF (FIRST) THEN\n         NGAM = INITDS (GAMCS, 42, 0.1*REAL(D1MACH(3)) )\nC\n         CALL DGAMLM (XMIN, XMAX)\n         DXREL = SQRT(D1MACH(4))\n      ENDIF\n      FIRST = .FALSE.\nC\n      Y = ABS(X)\n      IF (Y.GT.10.D0) GO TO 50\nC\nC COMPUTE GAMMA(X) FOR -XBND .LE. X .LE. XBND.  REDUCE INTERVAL AND FIND\nC GAMMA(1+Y) FOR 0.0 .LE. Y .LT. 1.0 FIRST OF ALL.\nC\n      N = X\n      IF (X.LT.0.D0) N = N - 1\n      Y = X - N\n      N = N - 1\n      DGAMMA = 0.9375D0 + DCSEVL (2.D0*Y-1.D0, GAMCS, NGAM)\n      IF (N.EQ.0) RETURN\nC\n      IF (N.GT.0) GO TO 30\nC\nC COMPUTE GAMMA(X) FOR X .LT. 1.0\nC\n      N = -N\n      IF (X .EQ. 0.D0) CALL XERMSG ('SLATEC', 'DGAMMA', 'X IS 0', 4, 2)\n      IF (X .LT. 0.0 .AND. X+N-2 .EQ. 0.D0) CALL XERMSG ('SLATEC',\n     +   'DGAMMA', 'X IS A NEGATIVE INTEGER', 4, 2)\n      IF (X .LT. (-0.5D0) .AND. ABS((X-AINT(X-0.5D0))/X) .LT. DXREL)\n     +   CALL XERMSG ('SLATEC', 'DGAMMA',\n     +   'ANSWER LT HALF PRECISION BECAUSE X TOO NEAR NEGATIVE INTEGER',\n     +   1, 1)\nC\n      DO 20 I=1,N\n        DGAMMA = DGAMMA/(X+I-1 )\n 20   CONTINUE\n      RETURN\nC\nC GAMMA(X) FOR X .GE. 2.0 AND X .LE. 10.0\nC\n 30   DO 40 I=1,N\n        DGAMMA = (Y+I) * DGAMMA\n 40   CONTINUE\n      RETURN\nC\nC GAMMA(X) FOR ABS(X) .GT. 10.0.  RECALL Y = ABS(X).\nC\n 50   IF (X .GT. XMAX) CALL XERMSG ('SLATEC', 'DGAMMA',\n     +   'X SO BIG GAMMA OVERFLOWS', 3, 2)\nC\n      DGAMMA = 0.D0\n      IF (X .LT. XMIN) CALL XERMSG ('SLATEC', 'DGAMMA',\n     +   'X SO SMALL GAMMA UNDERFLOWS', 2, 1)\n      IF (X.LT.XMIN) RETURN\nC\n      DGAMMA = EXP ((Y-0.5D0)*LOG(Y) - Y + SQ2PIL + D9LGMC(Y) )\n      IF (X.GT.0.D0) RETURN\nC\n      IF (ABS((X-AINT(X-0.5D0))/X) .LT. DXREL) CALL XERMSG ('SLATEC',\n     +   'DGAMMA',\n     +   'ANSWER LT HALF PRECISION, X TOO NEAR NEGATIVE INTEGER', 1, 1)\nC\n      SINPIY = SIN (PI*Y)\n      IF (SINPIY .EQ. 0.D0) CALL XERMSG ('SLATEC', 'DGAMMA',\n     +   'X IS A NEGATIVE INTEGER', 4, 2)\nC\n      DGAMMA = -PI/(Y*SINPIY*DGAMMA)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dgamr.f",
    "content": "*DECK DGAMR\n      DOUBLE PRECISION FUNCTION DGAMR (X)\nC***BEGIN PROLOGUE  DGAMR\nC***PURPOSE  Compute the reciprocal of the Gamma function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A\nC***TYPE      DOUBLE PRECISION (GAMR-S, DGAMR-D, CGAMR-C)\nC***KEYWORDS  FNLIB, RECIPROCAL GAMMA FUNCTION, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC DGAMR(X) calculates the double precision reciprocal of the\nC complete Gamma function for double precision argument X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  DGAMMA, DLGAMS, XERCLR, XGETF, XSETF\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900727  Added EXTERNAL statement.  (WRB)\nC***END PROLOGUE  DGAMR\n      DOUBLE PRECISION X, ALNGX, SGNGX, DGAMMA\n      EXTERNAL DGAMMA\nC***FIRST EXECUTABLE STATEMENT  DGAMR\n      DGAMR = 0.0D0\n      IF (X.LE.0.0D0 .AND. AINT(X).EQ.X) RETURN\nC\n      CALL XGETF (IROLD)\n      CALL XSETF (1)\n      IF (ABS(X).GT.10.0D0) GO TO 10\n      DGAMR = 1.0D0/DGAMMA(X)\n      CALL XERCLR\n      CALL XSETF (IROLD)\n      RETURN\nC\n 10   CALL DLGAMS (X, ALNGX, SGNGX)\n      CALL XERCLR\n      CALL XSETF (IROLD)\n      DGAMR = SGNGX * EXP(-ALNGX)\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dlbeta.f",
    "content": "*DECK DLBETA\n      DOUBLE PRECISION FUNCTION DLBETA (A, B)\nC***BEGIN PROLOGUE  DLBETA\nC***PURPOSE  Compute the natural logarithm of the complete Beta\nC            function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7B\nC***TYPE      DOUBLE PRECISION (ALBETA-S, DLBETA-D, CLBETA-C)\nC***KEYWORDS  FNLIB, LOGARITHM OF THE COMPLETE BETA FUNCTION,\nC             SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC DLBETA(A,B) calculates the double precision natural logarithm of\nC the complete beta function for double precision arguments\nC A and B.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D9LGMC, DGAMMA, DLNGAM, DLNREL, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900727  Added EXTERNAL statement.  (WRB)\nC***END PROLOGUE  DLBETA\n      DOUBLE PRECISION A, B, P, Q, CORR, SQ2PIL, D9LGMC, DGAMMA, DLNGAM,\n     1  DLNREL\n      EXTERNAL DGAMMA\n      SAVE SQ2PIL\n      DATA SQ2PIL / 0.9189385332 0467274178 0329736405 62 D0 /\nC***FIRST EXECUTABLE STATEMENT  DLBETA\n      P = MIN (A, B)\n      Q = MAX (A, B)\nC\n      IF (P .LE. 0.D0) CALL XERMSG ('SLATEC', 'DLBETA',\n     +   'BOTH ARGUMENTS MUST BE GT ZERO', 1, 2)\nC\n      IF (P.GE.10.D0) GO TO 30\n      IF (Q.GE.10.D0) GO TO 20\nC\nC P AND Q ARE SMALL.\nC\n      DLBETA = LOG (DGAMMA(P) * (DGAMMA(Q)/DGAMMA(P+Q)) )\n      RETURN\nC\nC P IS SMALL, BUT Q IS BIG.\nC\n 20   CORR = D9LGMC(Q) - D9LGMC(P+Q)\n      DLBETA = DLNGAM(P) + CORR + P - P*LOG(P+Q)\n     1  + (Q-0.5D0)*DLNREL(-P/(P+Q))\n      RETURN\nC\nC P AND Q ARE BIG.\nC\n 30   CORR = D9LGMC(P) + D9LGMC(Q) - D9LGMC(P+Q)\n      DLBETA = -0.5D0*LOG(Q) + SQ2PIL + CORR + (P-0.5D0)*LOG(P/(P+Q))\n     1  + Q*DLNREL(-P/(P+Q))\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dlgams.f",
    "content": "*DECK DLGAMS\n      SUBROUTINE DLGAMS (X, DLGAM, SGNGAM)\nC***BEGIN PROLOGUE  DLGAMS\nC***PURPOSE  Compute the logarithm of the absolute value of the Gamma\nC            function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A\nC***TYPE      DOUBLE PRECISION (ALGAMS-S, DLGAMS-D)\nC***KEYWORDS  ABSOLUTE VALUE OF THE LOGARITHM OF THE GAMMA FUNCTION,\nC             FNLIB, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC DLGAMS(X,DLGAM,SGNGAM) calculates the double precision natural\nC logarithm of the absolute value of the Gamma function for\nC double precision argument X and stores the result in double\nC precision argument DLGAM.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  DLNGAM\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC***END PROLOGUE  DLGAMS\n      DOUBLE PRECISION X, DLGAM, SGNGAM, DLNGAM\nC***FIRST EXECUTABLE STATEMENT  DLGAMS\n      DLGAM = DLNGAM(X)\n      SGNGAM = 1.0D0\n      IF (X.GT.0.D0) RETURN\nC\n      INT = MOD (-AINT(X), 2.0D0) + 0.1D0\n      IF (INT.EQ.0) SGNGAM = -1.0D0\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dlngam.f",
    "content": "*DECK DLNGAM\n      DOUBLE PRECISION FUNCTION DLNGAM (X)\nC***BEGIN PROLOGUE  DLNGAM\nC***PURPOSE  Compute the logarithm of the absolute value of the Gamma\nC            function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A\nC***TYPE      DOUBLE PRECISION (ALNGAM-S, DLNGAM-D, CLNGAM-C)\nC***KEYWORDS  ABSOLUTE VALUE, COMPLETE GAMMA FUNCTION, FNLIB, LOGARITHM,\nC             SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC DLNGAM(X) calculates the double precision logarithm of the\nC absolute value of the Gamma function for double precision\nC argument X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH, D9LGMC, DGAMMA, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900727  Added EXTERNAL statement.  (WRB)\nC***END PROLOGUE  DLNGAM\n      DOUBLE PRECISION X, DXREL, PI, SINPIY, SQPI2L, SQ2PIL, XMAX,\n     1  Y, DGAMMA, D9LGMC, D1MACH, TEMP\n      LOGICAL FIRST\n      EXTERNAL DGAMMA\n      SAVE SQ2PIL, SQPI2L, PI, XMAX, DXREL, FIRST\n      DATA SQ2PIL / 0.9189385332 0467274178 0329736405 62 D0 /\n      DATA SQPI2L / +.2257913526 4472743236 3097614947 441 D+0    /\n      DATA PI / 3.1415926535 8979323846 2643383279 50 D0 /\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  DLNGAM\n      IF (FIRST) THEN\n         TEMP = 1.D0/LOG(D1MACH(2))\n         XMAX = TEMP*D1MACH(2)\n         DXREL = SQRT(D1MACH(4))\n      ENDIF\n      FIRST = .FALSE.\nC\n      Y = ABS (X)\n      IF (Y.GT.10.D0) GO TO 20\nC\nC LOG (ABS (DGAMMA(X)) ) FOR ABS(X) .LE. 10.0\nC\n      DLNGAM = LOG (ABS (DGAMMA(X)) )\n      RETURN\nC\nC LOG ( ABS (DGAMMA(X)) ) FOR ABS(X) .GT. 10.0\nC\n 20   IF (Y .GT. XMAX) CALL XERMSG ('SLATEC', 'DLNGAM',\n     +   'ABS(X) SO BIG DLNGAM OVERFLOWS', 2, 2)\nC\n      IF (X.GT.0.D0) DLNGAM = SQ2PIL + (X-0.5D0)*LOG(X) - X + D9LGMC(Y)\n      IF (X.GT.0.D0) RETURN\nC\n      SINPIY = ABS (SIN(PI*Y))\n      IF (SINPIY .EQ. 0.D0) CALL XERMSG ('SLATEC', 'DLNGAM',\n     +   'X IS A NEGATIVE INTEGER', 3, 2)\nC\n      IF (ABS((X-AINT(X-0.5D0))/X) .LT. DXREL) CALL XERMSG ('SLATEC',\n     +   'DLNGAM',\n     +   'ANSWER LT HALF PRECISION BECAUSE X TOO NEAR NEGATIVE INTEGER',\n     +   1, 1)\nC\n      DLNGAM = SQPI2L + (X-0.5D0)*LOG(Y) - X - LOG(SINPIY) - D9LGMC(Y)\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dlnrel.f",
    "content": "*DECK DLNREL\n      DOUBLE PRECISION FUNCTION DLNREL (X)\nC***BEGIN PROLOGUE  DLNREL\nC***PURPOSE  Evaluate ln(1+X) accurate in the sense of relative error.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C4B\nC***TYPE      DOUBLE PRECISION (ALNREL-S, DLNREL-D, CLNREL-C)\nC***KEYWORDS  ELEMENTARY FUNCTIONS, FNLIB, LOGARITHM\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC DLNREL(X) calculates the double precision natural logarithm of\nC (1.0+X) for double precision argument X.  This routine should\nC be used when X is small and accurate to calculate the logarithm\nC accurately (in the relative error sense) in the neighborhood\nC of 1.0.\nC\nC Series for ALNR       on the interval -3.75000E-01 to  3.75000E-01\nC                                        with weighted error   6.35E-32\nC                                         log weighted error  31.20\nC                               significant figures required  30.93\nC                                    decimal places required  32.01\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  D1MACH, DCSEVL, INITDS, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC***END PROLOGUE  DLNREL\n      DOUBLE PRECISION ALNRCS(43), X, XMIN,  DCSEVL, D1MACH\n      LOGICAL FIRST\n      SAVE ALNRCS, NLNREL, XMIN, FIRST\n      DATA ALNRCS(  1) / +.1037869356 2743769800 6862677190 98 D+1     /\n      DATA ALNRCS(  2) / -.1336430150 4908918098 7660415531 33 D+0     /\n      DATA ALNRCS(  3) / +.1940824913 5520563357 9261993747 50 D-1     /\n      DATA ALNRCS(  4) / -.3010755112 7535777690 3765377765 92 D-2     /\n      DATA ALNRCS(  5) / +.4869461479 7154850090 4563665091 37 D-3     /\n      DATA ALNRCS(  6) / -.8105488189 3175356066 8099430086 22 D-4     /\n      DATA ALNRCS(  7) / +.1377884779 9559524782 9382514960 59 D-4     /\n      DATA ALNRCS(  8) / -.2380221089 4358970251 3699929149 35 D-5     /\n      DATA ALNRCS(  9) / +.4164041621 3865183476 3918599019 89 D-6     /\n      DATA ALNRCS( 10) / -.7359582837 8075994984 2668370319 98 D-7     /\n      DATA ALNRCS( 11) / +.1311761187 6241674949 1522943450 11 D-7     /\n      DATA ALNRCS( 12) / -.2354670931 7742425136 6960923301 75 D-8     /\n      DATA ALNRCS( 13) / +.4252277327 6034997775 6380529625 67 D-9     /\n      DATA ALNRCS( 14) / -.7719089413 4840796826 1081074933 00 D-10    /\n      DATA ALNRCS( 15) / +.1407574648 1359069909 2153564721 91 D-10    /\n      DATA ALNRCS( 16) / -.2576907205 8024680627 5370786275 84 D-11    /\n      DATA ALNRCS( 17) / +.4734240666 6294421849 1543950059 38 D-12    /\n      DATA ALNRCS( 18) / -.8724901267 4742641745 3012632926 75 D-13    /\n      DATA ALNRCS( 19) / +.1612461490 2740551465 7398331191 15 D-13    /\n      DATA ALNRCS( 20) / -.2987565201 5665773006 7107924168 15 D-14    /\n      DATA ALNRCS( 21) / +.5548070120 9082887983 0413216972 79 D-15    /\n      DATA ALNRCS( 22) / -.1032461915 8271569595 1413339619 32 D-15    /\n      DATA ALNRCS( 23) / +.1925023920 3049851177 8785032448 68 D-16    /\n      DATA ALNRCS( 24) / -.3595507346 5265150011 1897078442 66 D-17    /\n      DATA ALNRCS( 25) / +.6726454253 7876857892 1945742267 73 D-18    /\n      DATA ALNRCS( 26) / -.1260262416 8735219252 0824256375 46 D-18    /\n      DATA ALNRCS( 27) / +.2364488440 8606210044 9161589555 19 D-19    /\n      DATA ALNRCS( 28) / -.4441937705 0807936898 8783891797 33 D-20    /\n      DATA ALNRCS( 29) / +.8354659446 4034259016 2412939946 66 D-21    /\n      DATA ALNRCS( 30) / -.1573155941 6479562574 8992535210 66 D-21    /\n      DATA ALNRCS( 31) / +.2965312874 0247422686 1543697066 66 D-22    /\n      DATA ALNRCS( 32) / -.5594958348 1815947292 1560132266 66 D-23    /\n      DATA ALNRCS( 33) / +.1056635426 8835681048 1872841386 66 D-23    /\n      DATA ALNRCS( 34) / -.1997248368 0670204548 3149994666 66 D-24    /\n      DATA ALNRCS( 35) / +.3778297781 8839361421 0498559999 99 D-25    /\n      DATA ALNRCS( 36) / -.7153158688 9081740345 0381653333 33 D-26    /\n      DATA ALNRCS( 37) / +.1355248846 3674213646 5020245333 33 D-26    /\n      DATA ALNRCS( 38) / -.2569467304 8487567430 0798293333 33 D-27    /\n      DATA ALNRCS( 39) / +.4874775606 6216949076 4595199999 99 D-28    /\n      DATA ALNRCS( 40) / -.9254211253 0849715321 1323733333 33 D-29    /\n      DATA ALNRCS( 41) / +.1757859784 1760239233 2697600000 00 D-29    /\n      DATA ALNRCS( 42) / -.3341002667 7731010351 3770666666 66 D-30    /\n      DATA ALNRCS( 43) / +.6353393618 0236187354 1802666666 66 D-31    /\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  DLNREL\n      IF (FIRST) THEN\n         NLNREL = INITDS (ALNRCS, 43, 0.1*REAL(D1MACH(3)))\n         XMIN = -1.0D0 + SQRT(D1MACH(4))\n      ENDIF\n      FIRST = .FALSE.\nC\n      IF (X .LE. (-1.D0)) CALL XERMSG ('SLATEC', 'DLNREL', 'X IS LE -1'\n     +   , 2, 2)\n      IF (X .LT. XMIN) CALL XERMSG ('SLATEC', 'DLNREL',\n     +   'ANSWER LT HALF PRECISION BECAUSE X TOO NEAR -1', 1, 1)\nC\n      IF (ABS(X).LE.0.375D0) DLNREL = X*(1.D0 -\n     1  X*DCSEVL (X/.375D0, ALNRCS, NLNREL))\nC\n      IF (ABS(X).GT.0.375D0) DLNREL = LOG (1.0D0+X)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dpchim.f",
    "content": "*DECK DPCHIM\n      SUBROUTINE DPCHIM (N, X, F, D, INCFD, IERR)\nC***BEGIN PROLOGUE  DPCHIM\nC***PURPOSE  Set derivatives needed to determine a monotone piecewise\nC            cubic Hermite interpolant to given data.  Boundary values\nC            are provided which are compatible with monotonicity.  The\nC            interpolant will have an extremum at each point where mono-\nC            tonicity switches direction.  (See DPCHIC if user control\nC            is desired over boundary or switch conditions.)\nC***LIBRARY   SLATEC (PCHIP)\nC***CATEGORY  E1A\nC***TYPE      DOUBLE PRECISION (PCHIM-S, DPCHIM-D)\nC***KEYWORDS  CUBIC HERMITE INTERPOLATION, MONOTONE INTERPOLATION,\nC             PCHIP, PIECEWISE CUBIC INTERPOLATION\nC***AUTHOR  Fritsch, F. N., (LLNL)\nC             Lawrence Livermore National Laboratory\nC             P.O. Box 808  (L-316)\nC             Livermore, CA  94550\nC             FTS 532-4275, (510) 422-4275\nC***DESCRIPTION\nC\nC          DPCHIM:  Piecewise Cubic Hermite Interpolation to\nC                  Monotone data.\nC\nC     Sets derivatives needed to determine a monotone piecewise cubic\nC     Hermite interpolant to the data given in X and F.\nC\nC     Default boundary conditions are provided which are compatible\nC     with monotonicity.  (See DPCHIC if user control of boundary con-\nC     ditions is desired.)\nC\nC     If the data are only piecewise monotonic, the interpolant will\nC     have an extremum at each point where monotonicity switches direc-\nC     tion.  (See DPCHIC if user control is desired in such cases.)\nC\nC     To facilitate two-dimensional applications, includes an increment\nC     between successive values of the F- and D-arrays.\nC\nC     The resulting piecewise cubic Hermite function may be evaluated\nC     by DPCHFE or DPCHFD.\nC\nC ----------------------------------------------------------------------\nC\nC  Calling sequence:\nC\nC        PARAMETER  (INCFD = ...)\nC        INTEGER  N, IERR\nC        DOUBLE PRECISION  X(N), F(INCFD,N), D(INCFD,N)\nC\nC        CALL  DPCHIM (N, X, F, D, INCFD, IERR)\nC\nC   Parameters:\nC\nC     N -- (input) number of data points.  (Error return if N.LT.2 .)\nC           If N=2, simply does linear interpolation.\nC\nC     X -- (input) real*8 array of independent variable values.  The\nC           elements of X must be strictly increasing:\nC                X(I-1) .LT. X(I),  I = 2(1)N.\nC           (Error return if not.)\nC\nC     F -- (input) real*8 array of dependent variable values to be\nC           interpolated.  F(1+(I-1)*INCFD) is value corresponding to\nC           X(I).  DPCHIM is designed for monotonic data, but it will\nC           work for any F-array.  It will force extrema at points where\nC           monotonicity switches direction.  If some other treatment of\nC           switch points is desired, DPCHIC should be used instead.\nC                                     -----\nC     D -- (output) real*8 array of derivative values at the data\nC           points.  If the data are monotonic, these values will\nC           determine a monotone cubic Hermite function.\nC           The value corresponding to X(I) is stored in\nC                D(1+(I-1)*INCFD),  I=1(1)N.\nC           No other entries in D are changed.\nC\nC     INCFD -- (input) increment between successive values in F and D.\nC           This argument is provided primarily for 2-D applications.\nC           (Error return if  INCFD.LT.1 .)\nC\nC     IERR -- (output) error flag.\nC           Normal return:\nC              IERR = 0  (no errors).\nC           Warning error:\nC              IERR.GT.0  means that IERR switches in the direction\nC                 of monotonicity were detected.\nC           \"Recoverable\" errors:\nC              IERR = -1  if N.LT.2 .\nC              IERR = -2  if INCFD.LT.1 .\nC              IERR = -3  if the X-array is not strictly increasing.\nC             (The D-array has not been changed in any of these cases.)\nC               NOTE:  The above errors are checked in the order listed,\nC                   and following arguments have **NOT** been validated.\nC\nC***REFERENCES  1. F. N. Fritsch and J. Butland, A method for construc-\nC                 ting local monotone piecewise cubic interpolants, SIAM\nC                 Journal on Scientific and Statistical Computing 5, 2\nC                 (June 1984), pp. 300-304.\nC               2. F. N. Fritsch and R. E. Carlson, Monotone piecewise\nC                 cubic interpolation, SIAM Journal on Numerical Ana-\nC                 lysis 17, 2 (April 1980), pp. 238-246.\nC***ROUTINES CALLED  DPCHST, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   811103  DATE WRITTEN\nC   820201  1. Introduced  DPCHST  to reduce possible over/under-\nC             flow problems.\nC           2. Rearranged derivative formula for same reason.\nC   820602  1. Modified end conditions to be continuous functions\nC             of data when monotonicity switches in next interval.\nC           2. Modified formulas so end conditions are less prone\nC             of over/underflow problems.\nC   820803  Minor cosmetic changes for release 1.\nC   870707  Corrected XERROR calls for d.p. name(s).\nC   870813  Updated Reference 1.\nC   890206  Corrected XERROR calls.\nC   890411  Added SAVE statements (Vers. 3.2).\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890703  Corrected category record.  (WRB)\nC   890831  Modified array declarations.  (WRB)\nC   891006  Cosmetic changes to prologue.  (WRB)\nC   891006  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   920429  Revised format and order of references.  (WRB,FNF)\nC***END PROLOGUE  DPCHIM\nC  Programming notes:\nC\nC     1. The function  DPCHST(ARG1,ARG2)  is assumed to return zero if\nC        either argument is zero, +1 if they are of the same sign, and\nC        -1 if they are of opposite sign.\nC     2. To produce a single precision version, simply:\nC        a. Change DPCHIM to PCHIM wherever it occurs,\nC        b. Change DPCHST to PCHST wherever it occurs,\nC        c. Change all references to the Fortran intrinsics to their\nC           single precision equivalents,\nC        d. Change the double precision declarations to real, and\nC        e. Change the constants ZERO and THREE to single precision.\nC\nC  DECLARE ARGUMENTS.\nC\n      INTEGER  N, INCFD, IERR\n      DOUBLE PRECISION  X(*), F(INCFD,*), D(INCFD,*)\nC\nC  DECLARE LOCAL VARIABLES.\nC\n      INTEGER  I, NLESS1\n      DOUBLE PRECISION  DEL1, DEL2, DMAX, DMIN, DRAT1, DRAT2, DSAVE,\n     *      H1, H2, HSUM, HSUMT3, THREE, W1, W2, ZERO\n      SAVE ZERO, THREE\n      DOUBLE PRECISION  DPCHST\n      DATA  ZERO /0.D0/, THREE/3.D0/\nC\nC  VALIDITY-CHECK ARGUMENTS.\nC\nC***FIRST EXECUTABLE STATEMENT  DPCHIM\n      IF ( N.LT.2 )  GO TO 5001\n      IF ( INCFD.LT.1 )  GO TO 5002\n      DO 1  I = 2, N\n         IF ( X(I).LE.X(I-1) )  GO TO 5003\n    1 CONTINUE\nC\nC  FUNCTION DEFINITION IS OK, GO ON.\nC\n      IERR = 0\n      NLESS1 = N - 1\n      H1 = X(2) - X(1)\n      DEL1 = (F(1,2) - F(1,1))/H1\n      DSAVE = DEL1\nC\nC  SPECIAL CASE N=2 -- USE LINEAR INTERPOLATION.\nC\n      IF (NLESS1 .GT. 1)  GO TO 10\n      D(1,1) = DEL1\n      D(1,N) = DEL1\n      GO TO 5000\nC\nC  NORMAL CASE  (N .GE. 3).\nC\n   10 CONTINUE\n      H2 = X(3) - X(2)\n      DEL2 = (F(1,3) - F(1,2))/H2\nC\nC  SET D(1) VIA NON-CENTERED THREE-POINT FORMULA, ADJUSTED TO BE\nC     SHAPE-PRESERVING.\nC\n      HSUM = H1 + H2\n      W1 = (H1 + HSUM)/HSUM\n      W2 = -H1/HSUM\n      D(1,1) = W1*DEL1 + W2*DEL2\n      IF ( DPCHST(D(1,1),DEL1) .LE. ZERO)  THEN\n         D(1,1) = ZERO\n      ELSE IF ( DPCHST(DEL1,DEL2) .LT. ZERO)  THEN\nC        NEED DO THIS CHECK ONLY IF MONOTONICITY SWITCHES.\n         DMAX = THREE*DEL1\n         IF (ABS(D(1,1)) .GT. ABS(DMAX))  D(1,1) = DMAX\n      ENDIF\nC\nC  LOOP THROUGH INTERIOR POINTS.\nC\n      DO 50  I = 2, NLESS1\n         IF (I .EQ. 2)  GO TO 40\nC\n         H1 = H2\n         H2 = X(I+1) - X(I)\n         HSUM = H1 + H2\n         DEL1 = DEL2\n         DEL2 = (F(1,I+1) - F(1,I))/H2\n   40    CONTINUE\nC\nC        SET D(I)=0 UNLESS DATA ARE STRICTLY MONOTONIC.\nC\n         D(1,I) = ZERO\n         IF ( DPCHST(DEL1,DEL2) .LT. 0.)  GO TO 42\n         IF ( DPCHST(DEL1,DEL2) .EQ. 0.)  GO TO 41\n         GO TO 45\nC\nC        COUNT NUMBER OF CHANGES IN DIRECTION OF MONOTONICITY.\nC\n   41    CONTINUE\n         IF (DEL2 .EQ. ZERO)  GO TO 50\n         IF ( DPCHST(DSAVE,DEL2) .LT. ZERO)  IERR = IERR + 1\n         DSAVE = DEL2\n         GO TO 50\nC\n   42    CONTINUE\n         IERR = IERR + 1\n         DSAVE = DEL2\n         GO TO 50\nC\nC        USE BRODLIE MODIFICATION OF BUTLAND FORMULA.\nC\n   45    CONTINUE\n         HSUMT3 = HSUM+HSUM+HSUM\n         W1 = (HSUM + H1)/HSUMT3\n         W2 = (HSUM + H2)/HSUMT3\n         DMAX = MAX( ABS(DEL1), ABS(DEL2) )\n         DMIN = MIN( ABS(DEL1), ABS(DEL2) )\n         DRAT1 = DEL1/DMAX\n         DRAT2 = DEL2/DMAX\n         D(1,I) = DMIN/(W1*DRAT1 + W2*DRAT2)\nC\n   50 CONTINUE\nC\nC  SET D(N) VIA NON-CENTERED THREE-POINT FORMULA, ADJUSTED TO BE\nC     SHAPE-PRESERVING.\nC\n      W1 = -H2/HSUM\n      W2 = (H2 + HSUM)/HSUM\n      D(1,N) = W1*DEL1 + W2*DEL2\n      IF ( DPCHST(D(1,N),DEL2) .LE. ZERO)  THEN\n         D(1,N) = ZERO\n      ELSE IF ( DPCHST(DEL1,DEL2) .LT. ZERO)  THEN\nC        NEED DO THIS CHECK ONLY IF MONOTONICITY SWITCHES.\n         DMAX = THREE*DEL2\n         IF (ABS(D(1,N)) .GT. ABS(DMAX))  D(1,N) = DMAX\n      ENDIF\nC\nC  NORMAL RETURN.\nC\n 5000 CONTINUE\n      RETURN\nC\nC  ERROR RETURNS.\nC\n 5001 CONTINUE\nC     N.LT.2 RETURN.\n      IERR = -1\n      CALL XERMSG ('SLATEC', 'DPCHIM',\n     +   'NUMBER OF DATA POINTS LESS THAN TWO', IERR, 1)\n      RETURN\nC\n 5002 CONTINUE\nC     INCFD.LT.1 RETURN.\n      IERR = -2\n      CALL XERMSG ('SLATEC', 'DPCHIM', 'INCREMENT LESS THAN ONE', IERR,\n     +   1)\n      RETURN\nC\n 5003 CONTINUE\nC     X-ARRAY NOT STRICTLY INCREASING.\n      IERR = -3\n      CALL XERMSG ('SLATEC', 'DPCHIM',\n     +   'X-ARRAY NOT STRICTLY INCREASING', IERR, 1)\n      RETURN\nC------------- LAST LINE OF DPCHIM FOLLOWS -----------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dpchst.f",
    "content": "*DECK DPCHST\n      DOUBLE PRECISION FUNCTION DPCHST (ARG1, ARG2)\nC***BEGIN PROLOGUE  DPCHST\nC***SUBSIDIARY\nC***PURPOSE  DPCHIP Sign-Testing Routine\nC***LIBRARY   SLATEC (PCHIP)\nC***TYPE      DOUBLE PRECISION (PCHST-S, DPCHST-D)\nC***AUTHOR  Fritsch, F. N., (LLNL)\nC***DESCRIPTION\nC\nC         DPCHST:  DPCHIP Sign-Testing Routine.\nC\nC\nC     Returns:\nC        -1. if ARG1 and ARG2 are of opposite sign.\nC         0. if either argument is zero.\nC        +1. if ARG1 and ARG2 are of the same sign.\nC\nC     The object is to do this without multiplying ARG1*ARG2, to avoid\nC     possible over/underflow problems.\nC\nC  Fortran intrinsics used:  SIGN.\nC\nC***SEE ALSO  DPCHCE, DPCHCI, DPCHCS, DPCHIM\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   811103  DATE WRITTEN\nC   820805  Converted to SLATEC library version.\nC   870813  Minor cosmetic changes.\nC   890411  Added SAVE statements (Vers. 3.2).\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900328  Added TYPE section.  (WRB)\nC   910408  Updated AUTHOR and DATE WRITTEN sections in prologue.  (WRB)\nC   930503  Improved purpose.  (FNF)\nC***END PROLOGUE  DPCHST\nC\nC**End\nC\nC  DECLARE ARGUMENTS.\nC\n      DOUBLE PRECISION  ARG1, ARG2\nC\nC  DECLARE LOCAL VARIABLES.\nC\n      DOUBLE PRECISION  ONE, ZERO\n      SAVE ZERO, ONE\n      DATA  ZERO /0.D0/,  ONE/1.D0/\nC\nC  PERFORM THE TEST.\nC\nC***FIRST EXECUTABLE STATEMENT  DPCHST\n      DPCHST = SIGN(ONE,ARG1) * SIGN(ONE,ARG2)\n      IF ((ARG1.EQ.ZERO) .OR. (ARG2.EQ.ZERO))  DPCHST = ZERO\nC\n      RETURN\nC------------- LAST LINE OF DPCHST FOLLOWS -----------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/dpsifn.f",
    "content": "*DECK DPSIFN\n      SUBROUTINE DPSIFN (X, N, KODE, M, ANS, NZ, IERR)\nC***BEGIN PROLOGUE  DPSIFN\nC***PURPOSE  Compute derivatives of the Psi function.\nC***LIBRARY   SLATEC\nC***CATEGORY  C7C\nC***TYPE      DOUBLE PRECISION (PSIFN-S, DPSIFN-D)\nC***KEYWORDS  DERIVATIVES OF THE GAMMA FUNCTION, POLYGAMMA FUNCTION,\nC             PSI FUNCTION\nC***AUTHOR  Amos, D. E., (SNLA)\nC***DESCRIPTION\nC\nC         The following definitions are used in DPSIFN:\nC\nC      Definition 1\nC         PSI(X) = d/dx (ln(GAMMA(X)), the first derivative of\nC                  the log GAMMA function.\nC      Definition 2\nC                     K   K\nC         PSI(K,X) = d /dx (PSI(X)), the K-th derivative of PSI(X).\nC   ___________________________________________________________________\nC      DPSIFN computes a sequence of SCALED derivatives of\nC      the PSI function; i.e. for fixed X and M it computes\nC      the M-member sequence\nC\nC                    ((-1)**(K+1)/GAMMA(K+1))*PSI(K,X)\nC                       for K = N,...,N+M-1\nC\nC      where PSI(K,X) is as defined above.   For KODE=1, DPSIFN returns\nC      the scaled derivatives as described.  KODE=2 is operative only\nC      when K=0 and in that case DPSIFN returns -PSI(X) + LN(X).  That\nC      is, the logarithmic behavior for large X is removed when KODE=2\nC      and K=0.  When sums or differences of PSI functions are computed\nC      the logarithmic terms can be combined analytically and computed\nC      separately to help retain significant digits.\nC\nC         Note that CALL DPSIFN(X,0,1,1,ANS) results in\nC                   ANS = -PSI(X)\nC\nC     Input      X is DOUBLE PRECISION\nC           X      - Argument, X .gt. 0.0D0\nC           N      - First member of the sequence, 0 .le. N .le. 100\nC                    N=0 gives ANS(1) = -PSI(X)       for KODE=1\nC                                       -PSI(X)+LN(X) for KODE=2\nC           KODE   - Selection parameter\nC                    KODE=1 returns scaled derivatives of the PSI\nC                    function.\nC                    KODE=2 returns scaled derivatives of the PSI\nC                    function EXCEPT when N=0. In this case,\nC                    ANS(1) = -PSI(X) + LN(X) is returned.\nC           M      - Number of members of the sequence, M.ge.1\nC\nC    Output     ANS is DOUBLE PRECISION\nC           ANS    - A vector of length at least M whose first M\nC                    components contain the sequence of derivatives\nC                    scaled according to KODE.\nC           NZ     - Underflow flag\nC                    NZ.eq.0, A normal return\nC                    NZ.ne.0, Underflow, last NZ components of ANS are\nC                             set to zero, ANS(M-K+1)=0.0, K=1,...,NZ\nC           IERR   - Error flag\nC                    IERR=0, A normal return, computation completed\nC                    IERR=1, Input error,     no computation\nC                    IERR=2, Overflow,        X too small or N+M-1 too\nC                            large or both\nC                    IERR=3, Error,           N too large. Dimensioned\nC                            array TRMR(NMAX) is not large enough for N\nC\nC         The nominal computational accuracy is the maximum of unit\nC         roundoff (=D1MACH(4)) and 1.0D-18 since critical constants\nC         are given to only 18 digits.\nC\nC         PSIFN is the single precision version of DPSIFN.\nC\nC *Long Description:\nC\nC         The basic method of evaluation is the asymptotic expansion\nC         for large X.ge.XMIN followed by backward recursion on a two\nC         term recursion relation\nC\nC                  W(X+1) + X**(-N-1) = W(X).\nC\nC         This is supplemented by a series\nC\nC                  SUM( (X+K)**(-N-1) , K=0,1,2,... )\nC\nC         which converges rapidly for large N. Both XMIN and the\nC         number of terms of the series are calculated from the unit\nC         roundoff of the machine environment.\nC\nC***REFERENCES  Handbook of Mathematical Functions, National Bureau\nC                 of Standards Applied Mathematics Series 55, edited\nC                 by M. Abramowitz and I. A. Stegun, equations 6.3.5,\nC                 6.3.18, 6.4.6, 6.4.9 and 6.4.10, pp.258-260, 1964.\nC               D. E. Amos, A portable Fortran subroutine for\nC                 derivatives of the Psi function, Algorithm 610, ACM\nC                 Transactions on Mathematical Software 9, 4 (1983),\nC                 pp. 494-502.\nC***ROUTINES CALLED  D1MACH, I1MACH\nC***REVISION HISTORY  (YYMMDD)\nC   820601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890911  Removed unnecessary intrinsics.  (WRB)\nC   891006  Cosmetic changes to prologue.  (WRB)\nC   891006  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  DPSIFN\n      INTEGER I, IERR, J, K, KODE, M, MM, MX, N, NMAX, NN, NP, NX, NZ,\n     *  FN\n      INTEGER I1MACH\n      DOUBLE PRECISION ANS, ARG, B, DEN, ELIM, EPS, FLN,\n     * FX, RLN, RXSQ, R1M4, R1M5, S, SLOPE, T, TA, TK, TOL, TOLS, TRM,\n     * TRMR, TSS, TST, TT, T1, T2, WDTOL, X, XDMLN, XDMY, XINC, XLN,\n     * XM, XMIN, XQ, YINT\n      DOUBLE PRECISION D1MACH\n      DIMENSION B(22), TRM(22), TRMR(100), ANS(*)\n      SAVE NMAX, B\n      DATA NMAX /100/\nC-----------------------------------------------------------------------\nC             BERNOULLI NUMBERS\nC-----------------------------------------------------------------------\n      DATA B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), B(10),\n     * B(11), B(12), B(13), B(14), B(15), B(16), B(17), B(18), B(19),\n     * B(20), B(21), B(22) /1.00000000000000000D+00,\n     * -5.00000000000000000D-01,1.66666666666666667D-01,\n     * -3.33333333333333333D-02,2.38095238095238095D-02,\n     * -3.33333333333333333D-02,7.57575757575757576D-02,\n     * -2.53113553113553114D-01,1.16666666666666667D+00,\n     * -7.09215686274509804D+00,5.49711779448621554D+01,\n     * -5.29124242424242424D+02,6.19212318840579710D+03,\n     * -8.65802531135531136D+04,1.42551716666666667D+06,\n     * -2.72982310678160920D+07,6.01580873900642368D+08,\n     * -1.51163157670921569D+10,4.29614643061166667D+11,\n     * -1.37116552050883328D+13,4.88332318973593167D+14,\n     * -1.92965793419400681D+16/\nC\nC***FIRST EXECUTABLE STATEMENT  DPSIFN\n      IERR = 0\n      NZ=0\n      IF (X.LE.0.0D0) IERR=1\n      IF (N.LT.0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (M.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\n      MM=M\n      NX = MIN(-I1MACH(15),I1MACH(16))\n      R1M5 = D1MACH(5)\n      R1M4 = D1MACH(4)*0.5D0\n      WDTOL = MAX(R1M4,0.5D-18)\nC-----------------------------------------------------------------------\nC     ELIM = APPROXIMATE EXPONENTIAL OVER AND UNDERFLOW LIMIT\nC-----------------------------------------------------------------------\n      ELIM = 2.302D0*(NX*R1M5-3.0D0)\n      XLN = LOG(X)\n   41 CONTINUE\n      NN = N + MM - 1\n      FN = NN\n      T = (FN+1)*XLN\nC-----------------------------------------------------------------------\nC     OVERFLOW AND UNDERFLOW TEST FOR SMALL AND LARGE X\nC-----------------------------------------------------------------------\n      IF (ABS(T).GT.ELIM) GO TO 290\n      IF (X.LT.WDTOL) GO TO 260\nC-----------------------------------------------------------------------\nC     COMPUTE XMIN AND THE NUMBER OF TERMS OF THE SERIES, FLN+1\nC-----------------------------------------------------------------------\n      RLN = R1M5*I1MACH(14)\n      RLN = MIN(RLN,18.06D0)\n      FLN = MAX(RLN,3.0D0) - 3.0D0\n      YINT = 3.50D0 + 0.40D0*FLN\n      SLOPE = 0.21D0 + FLN*(0.0006038D0*FLN+0.008677D0)\n      XM = YINT + SLOPE*FN\n      MX = INT(XM) + 1\n      XMIN = MX\n      IF (N.EQ.0) GO TO 50\n      XM = -2.302D0*RLN - MIN(0.0D0,XLN)\n      ARG = XM/N\n      ARG = MIN(0.0D0,ARG)\n      EPS = EXP(ARG)\n      XM = 1.0D0 - EPS\n      IF (ABS(ARG).LT.1.0D-3) XM = -ARG\n      FLN = X*XM/EPS\n      XM = XMIN - X\n      IF (XM.GT.7.0D0 .AND. FLN.LT.15.0D0) GO TO 200\n   50 CONTINUE\n      XDMY = X\n      XDMLN = XLN\n      XINC = 0.0D0\n      IF (X.GE.XMIN) GO TO 60\n      NX = INT(X)\n      XINC = XMIN - NX\n      XDMY = X + XINC\n      XDMLN = LOG(XDMY)\n   60 CONTINUE\nC-----------------------------------------------------------------------\nC     GENERATE W(N+MM-1,X) BY THE ASYMPTOTIC EXPANSION\nC-----------------------------------------------------------------------\n      T = FN*XDMLN\n      T1 = XDMLN + XDMLN\n      T2 = T + XDMLN\n      TK = MAX(ABS(T),ABS(T1),ABS(T2))\n      IF (TK.GT.ELIM) GO TO 380\n      TSS = EXP(-T)\n      TT = 0.5D0/XDMY\n      T1 = TT\n      TST = WDTOL*TT\n      IF (NN.NE.0) T1 = TT + 1.0D0/FN\n      RXSQ = 1.0D0/(XDMY*XDMY)\n      TA = 0.5D0*RXSQ\n      T = (FN+1)*TA\n      S = T*B(3)\n      IF (ABS(S).LT.TST) GO TO 80\n      TK = 2.0D0\n      DO 70 K=4,22\n        T = T*((TK+FN+1)/(TK+1.0D0))*((TK+FN)/(TK+2.0D0))*RXSQ\n        TRM(K) = T*B(K)\n        IF (ABS(TRM(K)).LT.TST) GO TO 80\n        S = S + TRM(K)\n        TK = TK + 2.0D0\n   70 CONTINUE\n   80 CONTINUE\n      S = (S+T1)*TSS\n      IF (XINC.EQ.0.0D0) GO TO 100\nC-----------------------------------------------------------------------\nC     BACKWARD RECUR FROM XDMY TO X\nC-----------------------------------------------------------------------\n      NX = INT(XINC)\n      NP = NN + 1\n      IF (NX.GT.NMAX) GO TO 390\n      IF (NN.EQ.0) GO TO 160\n      XM = XINC - 1.0D0\n      FX = X + XM\nC-----------------------------------------------------------------------\nC     THIS LOOP SHOULD NOT BE CHANGED. FX IS ACCURATE WHEN X IS SMALL\nC-----------------------------------------------------------------------\n      DO 90 I=1,NX\n        TRMR(I) = FX**(-NP)\n        S = S + TRMR(I)\n        XM = XM - 1.0D0\n        FX = X + XM\n   90 CONTINUE\n  100 CONTINUE\n      ANS(MM) = S\n      IF (FN.EQ.0) GO TO 180\nC-----------------------------------------------------------------------\nC     GENERATE LOWER DERIVATIVES, J.LT.N+MM-1\nC-----------------------------------------------------------------------\n      IF (MM.EQ.1) RETURN\n      DO 150 J=2,MM\n        FN = FN - 1\n        TSS = TSS*XDMY\n        T1 = TT\n        IF (FN.NE.0) T1 = TT + 1.0D0/FN\n        T = (FN+1)*TA\n        S = T*B(3)\n        IF (ABS(S).LT.TST) GO TO 120\n        TK = 4 + FN\n        DO 110 K=4,22\n          TRM(K) = TRM(K)*(FN+1)/TK\n          IF (ABS(TRM(K)).LT.TST) GO TO 120\n          S = S + TRM(K)\n          TK = TK + 2.0D0\n  110   CONTINUE\n  120   CONTINUE\n        S = (S+T1)*TSS\n        IF (XINC.EQ.0.0D0) GO TO 140\n        IF (FN.EQ.0) GO TO 160\n        XM = XINC - 1.0D0\n        FX = X + XM\n        DO 130 I=1,NX\n          TRMR(I) = TRMR(I)*FX\n          S = S + TRMR(I)\n          XM = XM - 1.0D0\n          FX = X + XM\n  130   CONTINUE\n  140   CONTINUE\n        MX = MM - J + 1\n        ANS(MX) = S\n        IF (FN.EQ.0) GO TO 180\n  150 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     RECURSION FOR N = 0\nC-----------------------------------------------------------------------\n  160 CONTINUE\n      DO 170 I=1,NX\n        S = S + 1.0D0/(X+NX-I)\n  170 CONTINUE\n  180 CONTINUE\n      IF (KODE.EQ.2) GO TO 190\n      ANS(1) = S - XDMLN\n      RETURN\n  190 CONTINUE\n      IF (XDMY.EQ.X) RETURN\n      XQ = XDMY/X\n      ANS(1) = S - LOG(XQ)\n      RETURN\nC-----------------------------------------------------------------------\nC     COMPUTE BY SERIES (X+K)**(-(N+1)) , K=0,1,2,...\nC-----------------------------------------------------------------------\n  200 CONTINUE\n      NN = INT(FLN) + 1\n      NP = N + 1\n      T1 = (N+1)*XLN\n      T = EXP(-T1)\n      S = T\n      DEN = X\n      DO 210 I=1,NN\n        DEN = DEN + 1.0D0\n        TRM(I) = DEN**(-NP)\n        S = S + TRM(I)\n  210 CONTINUE\n      ANS(1) = S\n      IF (N.NE.0) GO TO 220\n      IF (KODE.EQ.2) ANS(1) = S + XLN\n  220 CONTINUE\n      IF (MM.EQ.1) RETURN\nC-----------------------------------------------------------------------\nC     GENERATE HIGHER DERIVATIVES, J.GT.N\nC-----------------------------------------------------------------------\n      TOL = WDTOL/5.0D0\n      DO 250 J=2,MM\n        T = T/X\n        S = T\n        TOLS = T*TOL\n        DEN = X\n        DO 230 I=1,NN\n          DEN = DEN + 1.0D0\n          TRM(I) = TRM(I)/DEN\n          S = S + TRM(I)\n          IF (TRM(I).LT.TOLS) GO TO 240\n  230   CONTINUE\n  240   CONTINUE\n        ANS(J) = S\n  250 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     SMALL X.LT.UNIT ROUND OFF\nC-----------------------------------------------------------------------\n  260 CONTINUE\n      ANS(1) = X**(-N-1)\n      IF (MM.EQ.1) GO TO 280\n      K = 1\n      DO 270 I=2,MM\n        ANS(K+1) = ANS(K)/X\n        K = K + 1\n  270 CONTINUE\n  280 CONTINUE\n      IF (N.NE.0) RETURN\n      IF (KODE.EQ.2) ANS(1) = ANS(1) + XLN\n      RETURN\n  290 CONTINUE\n      IF (T.GT.0.0D0) GO TO 380\n      NZ=0\n      IERR=2\n      RETURN\n  380 CONTINUE\n      NZ=NZ+1\n      ANS(MM)=0.0D0\n      MM=MM-1\n      IF (MM.EQ.0) RETURN\n      GO TO 41\n  390 CONTINUE\n      NZ=0\n      IERR=3\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/gamlim.f",
    "content": "*DECK GAMLIM\n      SUBROUTINE GAMLIM (XMIN, XMAX)\nC***BEGIN PROLOGUE  GAMLIM\nC***PURPOSE  Compute the minimum and maximum bounds for the argument in\nC            the Gamma function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A, R2\nC***TYPE      SINGLE PRECISION (GAMLIM-S, DGAMLM-D)\nC***KEYWORDS  COMPLETE GAMMA FUNCTION, FNLIB, LIMITS, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Calculate the minimum and maximum legal bounds for X in GAMMA(X).\nC XMIN and XMAX are not the only bounds, but they are the only non-\nC trivial ones to calculate.\nC\nC             Output Arguments --\nC XMIN   minimum legal value of X in GAMMA(X).  Any smaller value of\nC        X might result in underflow.\nC XMAX   maximum legal value of X in GAMMA(X).  Any larger value will\nC        cause overflow.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  R1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770401  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC***END PROLOGUE  GAMLIM\nC***FIRST EXECUTABLE STATEMENT  GAMLIM\n      ALNSML = LOG(R1MACH(1))\n      XMIN = -ALNSML\n      DO 10 I=1,10\n        XOLD = XMIN\n        XLN = LOG(XMIN)\n        XMIN = XMIN - XMIN*((XMIN+0.5)*XLN - XMIN - 0.2258 + ALNSML)\n     1    / (XMIN*XLN + 0.5)\n        IF (ABS(XMIN-XOLD).LT.0.005) GO TO 20\n 10   CONTINUE\n      CALL XERMSG ('SLATEC', 'GAMLIM', 'UNABLE TO FIND XMIN', 1, 2)\nC\n 20   XMIN = -XMIN + 0.01\nC\n      ALNBIG = LOG(R1MACH(2))\n      XMAX = ALNBIG\n      DO 30 I=1,10\n        XOLD = XMAX\n        XLN = LOG(XMAX)\n        XMAX = XMAX - XMAX*((XMAX-0.5)*XLN - XMAX + 0.9189 - ALNBIG)\n     1    / (XMAX*XLN - 0.5)\n        IF (ABS(XMAX-XOLD).LT.0.005) GO TO 40\n 30   CONTINUE\n      CALL XERMSG ('SLATEC', 'GAMLIM', 'UNABLE TO FIND XMAX', 2, 2)\nC\n 40   XMAX = XMAX - 0.01\n      XMIN = MAX (XMIN, -XMAX+1.)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/gamma.f",
    "content": "*DECK GAMMA\n      FUNCTION GAMMA (X)\nC***BEGIN PROLOGUE  GAMMA\nC***PURPOSE  Compute the complete Gamma function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A\nC***TYPE      SINGLE PRECISION (GAMMA-S, DGAMMA-D, CGAMMA-C)\nC***KEYWORDS  COMPLETE GAMMA FUNCTION, FNLIB, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC GAMMA computes the gamma function at X, where X is not 0, -1, -2, ....\nC GAMMA and X are single precision.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  CSEVL, GAMLIM, INITS, R1MACH, R9LGMC, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC***END PROLOGUE  GAMMA\n      DIMENSION GCS(23)\n      LOGICAL FIRST\n      SAVE GCS, PI, SQ2PIL, NGCS, XMIN, XMAX, DXREL, FIRST\n      DATA GCS   ( 1) / .0085711955 90989331E0/\n      DATA GCS   ( 2) / .0044153813 24841007E0/\n      DATA GCS   ( 3) / .0568504368 1599363E0/\n      DATA GCS   ( 4) /-.0042198353 96418561E0/\n      DATA GCS   ( 5) / .0013268081 81212460E0/\n      DATA GCS   ( 6) /-.0001893024 529798880E0/\n      DATA GCS   ( 7) / .0000360692 532744124E0/\n      DATA GCS   ( 8) /-.0000060567 619044608E0/\n      DATA GCS   ( 9) / .0000010558 295463022E0/\n      DATA GCS   (10) /-.0000001811 967365542E0/\n      DATA GCS   (11) / .0000000311 772496471E0/\n      DATA GCS   (12) /-.0000000053 542196390E0/\n      DATA GCS   (13) / .0000000009 193275519E0/\n      DATA GCS   (14) /-.0000000001 577941280E0/\n      DATA GCS   (15) / .0000000000 270798062E0/\n      DATA GCS   (16) /-.0000000000 046468186E0/\n      DATA GCS   (17) / .0000000000 007973350E0/\n      DATA GCS   (18) /-.0000000000 001368078E0/\n      DATA GCS   (19) / .0000000000 000234731E0/\n      DATA GCS   (20) /-.0000000000 000040274E0/\n      DATA GCS   (21) / .0000000000 000006910E0/\n      DATA GCS   (22) /-.0000000000 000001185E0/\n      DATA GCS   (23) / .0000000000 000000203E0/\n      DATA PI /3.14159 26535 89793 24E0/\nC SQ2PIL IS LOG (SQRT (2.*PI) )\n      DATA SQ2PIL /0.91893 85332 04672 74E0/\n      DATA FIRST /.TRUE./\nC\nC LANL DEPENDENT CODE REMOVED 81.02.04\nC\nC***FIRST EXECUTABLE STATEMENT  GAMMA\n      IF (FIRST) THEN\nC\nC ---------------------------------------------------------------------\nC INITIALIZE.  FIND LEGAL BOUNDS FOR X, AND DETERMINE THE NUMBER OF\nC TERMS IN THE SERIES REQUIRED TO ATTAIN AN ACCURACY TEN TIMES BETTER\nC THAN MACHINE PRECISION.\nC\n         NGCS = INITS (GCS, 23, 0.1*R1MACH(3))\nC\n         CALL GAMLIM (XMIN, XMAX)\n         DXREL = SQRT (R1MACH(4))\nC\nC ---------------------------------------------------------------------\nC FINISH INITIALIZATION.  START EVALUATING GAMMA(X).\nC\n      ENDIF\n      FIRST = .FALSE.\nC\n      Y = ABS(X)\n      IF (Y.GT.10.0) GO TO 50\nC\nC COMPUTE GAMMA(X) FOR ABS(X) .LE. 10.0.  REDUCE INTERVAL AND\nC FIND GAMMA(1+Y) FOR 0. .LE. Y .LT. 1. FIRST OF ALL.\nC\n      N = X\n      IF (X.LT.0.) N = N - 1\n      Y = X - N\n      N = N - 1\n      GAMMA = 0.9375 + CSEVL(2.*Y-1., GCS, NGCS)\n      IF (N.EQ.0) RETURN\nC\n      IF (N.GT.0) GO TO 30\nC\nC COMPUTE GAMMA(X) FOR X .LT. 1.\nC\n      N = -N\n      IF (X .EQ. 0.) CALL XERMSG ('SLATEC', 'GAMMA', 'X IS 0', 4, 2)\n      IF (X .LT. 0. .AND. X+N-2 .EQ. 0.) CALL XERMSG ('SLATEC', 'GAMMA'\n     1, 'X IS A NEGATIVE INTEGER', 4, 2)\n      IF (X .LT. (-0.5) .AND. ABS((X-AINT(X-0.5))/X) .LT. DXREL) CALL\n     1XERMSG ( 'SLATEC', 'GAMMA',\n     2'ANSWER LT HALF PRECISION BECAUSE X TOO NEAR NEGATIVE INTEGER'\n     3, 1, 1)\nC\n      DO 20 I=1,N\n        GAMMA = GAMMA / (X+I-1)\n 20   CONTINUE\n      RETURN\nC\nC GAMMA(X) FOR X .GE. 2.\nC\n 30   DO 40 I=1,N\n        GAMMA = (Y+I)*GAMMA\n 40   CONTINUE\n      RETURN\nC\nC COMPUTE GAMMA(X) FOR ABS(X) .GT. 10.0.  RECALL Y = ABS(X).\nC\n 50   IF (X .GT. XMAX) CALL XERMSG ('SLATEC', 'GAMMA',\n     +   'X SO BIG GAMMA OVERFLOWS', 3, 2)\nC\n      GAMMA = 0.\n      IF (X .LT. XMIN) CALL XERMSG ('SLATEC', 'GAMMA',\n     +   'X SO SMALL GAMMA UNDERFLOWS', 2, 1)\n      IF (X.LT.XMIN) RETURN\nC\n      GAMMA = EXP((Y-0.5)*LOG(Y) - Y + SQ2PIL + R9LGMC(Y) )\n      IF (X.GT.0.) RETURN\nC\n      IF (ABS((X-AINT(X-0.5))/X) .LT. DXREL) CALL XERMSG ('SLATEC',\n     +   'GAMMA',\n     +   'ANSWER LT HALF PRECISION, X TOO NEAR NEGATIVE INTEGER', 1, 1)\nC\n      SINPIY = SIN (PI*Y)\n      IF (SINPIY .EQ. 0.) CALL XERMSG ('SLATEC', 'GAMMA',\n     +   'X IS A NEGATIVE INTEGER', 4, 2)\nC\n      GAMMA = -PI / (Y*SINPIY*GAMMA)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/gamr.f",
    "content": "*DECK GAMR\n      FUNCTION GAMR (X)\nC***BEGIN PROLOGUE  GAMR\nC***PURPOSE  Compute the reciprocal of the Gamma function.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7A\nC***TYPE      SINGLE PRECISION (GAMR-S, DGAMR-D, CGAMR-C)\nC***KEYWORDS  FNLIB, RECIPROCAL GAMMA FUNCTION, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC GAMR is a single precision function that evaluates the reciprocal\nC of the gamma function for single precision argument X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  ALGAMS, GAMMA, XERCLR, XGETF, XSETF\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   861211  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900727  Added EXTERNAL statement.  (WRB)\nC***END PROLOGUE  GAMR\n      EXTERNAL GAMMA\nC***FIRST EXECUTABLE STATEMENT  GAMR\n      GAMR = 0.0\n      IF (X.LE.0.0 .AND. AINT(X).EQ.X) RETURN\nC\n      CALL XGETF (IROLD)\n      CALL XSETF (1)\n      IF (ABS(X).GT.10.0) GO TO 10\n      GAMR = 1.0/GAMMA(X)\n      CALL XERCLR\n      CALL XSETF (IROLD)\n      RETURN\nC\n 10   CALL ALGAMS (X, ALNGX, SGNGX)\n      CALL XERCLR\n      CALL XSETF (IROLD)\n      GAMR = SGNGX * EXP(-ALNGX)\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/initds.f",
    "content": "*DECK INITDS\n      FUNCTION INITDS (OS, NOS, ETA)\nC***BEGIN PROLOGUE  INITDS\nC***PURPOSE  Determine the number of terms needed in an orthogonal\nC            polynomial series so that it meets a specified accuracy.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C3A2\nC***TYPE      DOUBLE PRECISION (INITS-S, INITDS-D)\nC***KEYWORDS  CHEBYSHEV, FNLIB, INITIALIZE, ORTHOGONAL POLYNOMIAL,\nC             ORTHOGONAL SERIES, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC  Initialize the orthogonal series, represented by the array OS, so\nC  that INITDS is the number of terms needed to insure the error is no\nC  larger than ETA.  Ordinarily, ETA will be chosen to be one-tenth\nC  machine precision.\nC\nC             Input Arguments --\nC   OS     double precision array of NOS coefficients in an orthogonal\nC          series.\nC   NOS    number of coefficients in OS.\nC   ETA    single precision scalar containing requested accuracy of\nC          series.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890831  Modified array declarations.  (WRB)\nC   891115  Modified error message.  (WRB)\nC   891115  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC***END PROLOGUE  INITDS\n      DOUBLE PRECISION OS(*)\nC***FIRST EXECUTABLE STATEMENT  INITDS\n      IF (NOS .LT. 1) CALL XERMSG ('SLATEC', 'INITDS',\n     +   'Number of coefficients is less than 1', 2, 1)\nC\n      ERR = 0.\n      DO 10 II = 1,NOS\n        I = NOS + 1 - II\n        ERR = ERR + ABS(REAL(OS(I)))\n        IF (ERR.GT.ETA) GO TO 20\n   10 CONTINUE\nC\n   20 IF (I .EQ. NOS) CALL XERMSG ('SLATEC', 'INITDS',\n     +   'Chebyshev series too short for specified accuracy', 1, 1)\n      INITDS = I\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/inits.f",
    "content": "*DECK INITS\n      FUNCTION INITS (OS, NOS, ETA)\nC***BEGIN PROLOGUE  INITS\nC***PURPOSE  Determine the number of terms needed in an orthogonal\nC            polynomial series so that it meets a specified accuracy.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C3A2\nC***TYPE      SINGLE PRECISION (INITS-S, INITDS-D)\nC***KEYWORDS  CHEBYSHEV, FNLIB, INITIALIZE, ORTHOGONAL POLYNOMIAL,\nC             ORTHOGONAL SERIES, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC  Initialize the orthogonal series, represented by the array OS, so\nC  that INITS is the number of terms needed to insure the error is no\nC  larger than ETA.  Ordinarily, ETA will be chosen to be one-tenth\nC  machine precision.\nC\nC             Input Arguments --\nC   OS     single precision array of NOS coefficients in an orthogonal\nC          series.\nC   NOS    number of coefficients in OS.\nC   ETA    single precision scalar containing requested accuracy of\nC          series.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770401  DATE WRITTEN\nC   890831  Modified array declarations.  (WRB)\nC   891115  Modified error message.  (WRB)\nC   891115  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC***END PROLOGUE  INITS\n      REAL OS(*)\nC***FIRST EXECUTABLE STATEMENT  INITS\n      IF (NOS .LT. 1) CALL XERMSG ('SLATEC', 'INITS',\n     +   'Number of coefficients is less than 1', 2, 1)\nC\n      ERR = 0.\n      DO 10 II = 1,NOS\n        I = NOS + 1 - II\n        ERR = ERR + ABS(OS(I))\n        IF (ERR.GT.ETA) GO TO 20\n   10 CONTINUE\nC\n   20 IF (I .EQ. NOS) CALL XERMSG ('SLATEC', 'INITS',\n     +   'Chebyshev series too short for specified accuracy', 1, 1)\n      INITS = I\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/module.mk",
    "content": "EXTERNAL_SOURCES += \\\n  %reldir%/albeta.f \\\n  %reldir%/alngam.f \\\n  %reldir%/alnrel.f \\\n  %reldir%/algams.f \\\n  %reldir%/csevl.f \\\n  %reldir%/d9gmit.f \\\n  %reldir%/d9lgic.f \\\n  %reldir%/d9lgit.f \\\n  %reldir%/d9lgmc.f \\\n  %reldir%/dcsevl.f \\\n  %reldir%/dgamlm.f \\\n  %reldir%/dgamma.f \\\n  %reldir%/dgamr.f \\\n  %reldir%/dlbeta.f \\\n  %reldir%/dlgams.f \\\n  %reldir%/dlngam.f \\\n  %reldir%/dlnrel.f \\\n  %reldir%/dpchim.f \\\n  %reldir%/dpchst.f \\\n  %reldir%/dpsifn.f \\\n  %reldir%/gamlim.f \\\n  %reldir%/gamma.f \\\n  %reldir%/gamr.f \\\n  %reldir%/initds.f \\\n  %reldir%/inits.f \\\n  %reldir%/pchim.f \\\n  %reldir%/pchst.f \\\n  %reldir%/psifn.f \\\n  %reldir%/r9lgmc.f \\\n  %reldir%/r9lgit.f \\\n  %reldir%/r9gmit.f \\\n  %reldir%/r9lgic.f\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "liboctave/external/slatec-fn/pchim.f",
    "content": "*DECK PCHIM\n      SUBROUTINE PCHIM (N, X, F, D, INCFD, IERR)\nC***BEGIN PROLOGUE  PCHIM\nC***PURPOSE  Set derivatives needed to determine a monotone piecewise\nC            cubic Hermite interpolant to given data.  Boundary values\nC            are provided which are compatible with monotonicity.  The\nC            interpolant will have an extremum at each point where mono-\nC            tonicity switches direction.  (See PCHIC if user control is\nC            desired over boundary or switch conditions.)\nC***LIBRARY   SLATEC (PCHIP)\nC***CATEGORY  E1A\nC***TYPE      SINGLE PRECISION (PCHIM-S, DPCHIM-D)\nC***KEYWORDS  CUBIC HERMITE INTERPOLATION, MONOTONE INTERPOLATION,\nC             PCHIP, PIECEWISE CUBIC INTERPOLATION\nC***AUTHOR  Fritsch, F. N., (LLNL)\nC             Lawrence Livermore National Laboratory\nC             P.O. Box 808  (L-316)\nC             Livermore, CA  94550\nC             FTS 532-4275, (510) 422-4275\nC***DESCRIPTION\nC\nC          PCHIM:  Piecewise Cubic Hermite Interpolation to\nC                  Monotone data.\nC\nC     Sets derivatives needed to determine a monotone piecewise cubic\nC     Hermite interpolant to the data given in X and F.\nC\nC     Default boundary conditions are provided which are compatible\nC     with monotonicity.  (See PCHIC if user control of boundary con-\nC     ditions is desired.)\nC\nC     If the data are only piecewise monotonic, the interpolant will\nC     have an extremum at each point where monotonicity switches direc-\nC     tion.  (See PCHIC if user control is desired in such cases.)\nC\nC     To facilitate two-dimensional applications, includes an increment\nC     between successive values of the F- and D-arrays.\nC\nC     The resulting piecewise cubic Hermite function may be evaluated\nC     by PCHFE or PCHFD.\nC\nC ----------------------------------------------------------------------\nC\nC  Calling sequence:\nC\nC        PARAMETER  (INCFD = ...)\nC        INTEGER  N, IERR\nC        REAL  X(N), F(INCFD,N), D(INCFD,N)\nC\nC        CALL  PCHIM (N, X, F, D, INCFD, IERR)\nC\nC   Parameters:\nC\nC     N -- (input) number of data points.  (Error return if N.LT.2 .)\nC           If N=2, simply does linear interpolation.\nC\nC     X -- (input) real array of independent variable values.  The\nC           elements of X must be strictly increasing:\nC                X(I-1) .LT. X(I),  I = 2(1)N.\nC           (Error return if not.)\nC\nC     F -- (input) real array of dependent variable values to be inter-\nC           polated.  F(1+(I-1)*INCFD) is value corresponding to X(I).\nC           PCHIM is designed for monotonic data, but it will work for\nC           any F-array.  It will force extrema at points where mono-\nC           tonicity switches direction.  If some other treatment of\nC           switch points is desired, PCHIC should be used instead.\nC                                     -----\nC     D -- (output) real array of derivative values at the data points.\nC           If the data are monotonic, these values will determine a\nC           a monotone cubic Hermite function.\nC           The value corresponding to X(I) is stored in\nC                D(1+(I-1)*INCFD),  I=1(1)N.\nC           No other entries in D are changed.\nC\nC     INCFD -- (input) increment between successive values in F and D.\nC           This argument is provided primarily for 2-D applications.\nC           (Error return if  INCFD.LT.1 .)\nC\nC     IERR -- (output) error flag.\nC           Normal return:\nC              IERR = 0  (no errors).\nC           Warning error:\nC              IERR.GT.0  means that IERR switches in the direction\nC                 of monotonicity were detected.\nC           \"Recoverable\" errors:\nC              IERR = -1  if N.LT.2 .\nC              IERR = -2  if INCFD.LT.1 .\nC              IERR = -3  if the X-array is not strictly increasing.\nC             (The D-array has not been changed in any of these cases.)\nC               NOTE:  The above errors are checked in the order listed,\nC                   and following arguments have **NOT** been validated.\nC\nC***REFERENCES  1. F. N. Fritsch and J. Butland, A method for construc-\nC                 ting local monotone piecewise cubic interpolants, SIAM\nC                 Journal on Scientific and Statistical Computing 5, 2\nC                 (June 1984), pp. 300-304.\nC               2. F. N. Fritsch and R. E. Carlson, Monotone piecewise\nC                 cubic interpolation, SIAM Journal on Numerical Ana-\nC                 lysis 17, 2 (April 1980), pp. 238-246.\nC***ROUTINES CALLED  PCHST, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   811103  DATE WRITTEN\nC   820201  1. Introduced  PCHST  to reduce possible over/under-\nC             flow problems.\nC           2. Rearranged derivative formula for same reason.\nC   820602  1. Modified end conditions to be continuous functions\nC             of data when monotonicity switches in next interval.\nC           2. Modified formulas so end conditions are less prone\nC             of over/underflow problems.\nC   820803  Minor cosmetic changes for release 1.\nC   870813  Updated Reference 1.\nC   890411  Added SAVE statements (Vers. 3.2).\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890703  Corrected category record.  (WRB)\nC   890831  Modified array declarations.  (WRB)\nC   890831  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   920429  Revised format and order of references.  (WRB,FNF)\nC***END PROLOGUE  PCHIM\nC  Programming notes:\nC\nC     1. The function  PCHST(ARG1,ARG2)  is assumed to return zero if\nC        either argument is zero, +1 if they are of the same sign, and\nC        -1 if they are of opposite sign.\nC     2. To produce a double precision version, simply:\nC        a. Change PCHIM to DPCHIM wherever it occurs,\nC        b. Change PCHST to DPCHST wherever it occurs,\nC        c. Change all references to the Fortran intrinsics to their\nC           double precision equivalents,\nC        d. Change the real declarations to double precision, and\nC        e. Change the constants ZERO and THREE to double precision.\nC\nC  DECLARE ARGUMENTS.\nC\n      INTEGER  N, INCFD, IERR\n      REAL  X(*), F(INCFD,*), D(INCFD,*)\nC\nC  DECLARE LOCAL VARIABLES.\nC\n      INTEGER  I, NLESS1\n      REAL  DEL1, DEL2, DMAX, DMIN, DRAT1, DRAT2, DSAVE,\n     *      H1, H2, HSUM, HSUMT3, THREE, W1, W2, ZERO\n      SAVE ZERO, THREE\n      REAL  PCHST\n      DATA  ZERO /0./,  THREE /3./\nC\nC  VALIDITY-CHECK ARGUMENTS.\nC\nC***FIRST EXECUTABLE STATEMENT  PCHIM\n      IF ( N.LT.2 )  GO TO 5001\n      IF ( INCFD.LT.1 )  GO TO 5002\n      DO 1  I = 2, N\n         IF ( X(I).LE.X(I-1) )  GO TO 5003\n    1 CONTINUE\nC\nC  FUNCTION DEFINITION IS OK, GO ON.\nC\n      IERR = 0\n      NLESS1 = N - 1\n      H1 = X(2) - X(1)\n      DEL1 = (F(1,2) - F(1,1))/H1\n      DSAVE = DEL1\nC\nC  SPECIAL CASE N=2 -- USE LINEAR INTERPOLATION.\nC\n      IF (NLESS1 .GT. 1)  GO TO 10\n      D(1,1) = DEL1\n      D(1,N) = DEL1\n      GO TO 5000\nC\nC  NORMAL CASE  (N .GE. 3).\nC\n   10 CONTINUE\n      H2 = X(3) - X(2)\n      DEL2 = (F(1,3) - F(1,2))/H2\nC\nC  SET D(1) VIA NON-CENTERED THREE-POINT FORMULA, ADJUSTED TO BE\nC     SHAPE-PRESERVING.\nC\n      HSUM = H1 + H2\n      W1 = (H1 + HSUM)/HSUM\n      W2 = -H1/HSUM\n      D(1,1) = W1*DEL1 + W2*DEL2\n      IF ( PCHST(D(1,1),DEL1) .LE. ZERO)  THEN\n         D(1,1) = ZERO\n      ELSE IF ( PCHST(DEL1,DEL2) .LT. ZERO)  THEN\nC        NEED DO THIS CHECK ONLY IF MONOTONICITY SWITCHES.\n         DMAX = THREE*DEL1\n         IF (ABS(D(1,1)) .GT. ABS(DMAX))  D(1,1) = DMAX\n      ENDIF\nC\nC  LOOP THROUGH INTERIOR POINTS.\nC\n      DO 50  I = 2, NLESS1\n         IF (I .EQ. 2)  GO TO 40\nC\n         H1 = H2\n         H2 = X(I+1) - X(I)\n         HSUM = H1 + H2\n         DEL1 = DEL2\n         DEL2 = (F(1,I+1) - F(1,I))/H2\n   40    CONTINUE\nC\nC        SET D(I)=0 UNLESS DATA ARE STRICTLY MONOTONIC.\nC\n         D(1,I) = ZERO\n         IF ( PCHST(DEL1,DEL2) )  42, 41, 45\nC\nC        COUNT NUMBER OF CHANGES IN DIRECTION OF MONOTONICITY.\nC\n   41    CONTINUE\n         IF (DEL2 .EQ. ZERO)  GO TO 50\n         IF ( PCHST(DSAVE,DEL2) .LT. ZERO)  IERR = IERR + 1\n         DSAVE = DEL2\n         GO TO 50\nC\n   42    CONTINUE\n         IERR = IERR + 1\n         DSAVE = DEL2\n         GO TO 50\nC\nC        USE BRODLIE MODIFICATION OF BUTLAND FORMULA.\nC\n   45    CONTINUE\n         HSUMT3 = HSUM+HSUM+HSUM\n         W1 = (HSUM + H1)/HSUMT3\n         W2 = (HSUM + H2)/HSUMT3\n         DMAX = MAX( ABS(DEL1), ABS(DEL2) )\n         DMIN = MIN( ABS(DEL1), ABS(DEL2) )\n         DRAT1 = DEL1/DMAX\n         DRAT2 = DEL2/DMAX\n         D(1,I) = DMIN/(W1*DRAT1 + W2*DRAT2)\nC\n   50 CONTINUE\nC\nC  SET D(N) VIA NON-CENTERED THREE-POINT FORMULA, ADJUSTED TO BE\nC     SHAPE-PRESERVING.\nC\n      W1 = -H2/HSUM\n      W2 = (H2 + HSUM)/HSUM\n      D(1,N) = W1*DEL1 + W2*DEL2\n      IF ( PCHST(D(1,N),DEL2) .LE. ZERO)  THEN\n         D(1,N) = ZERO\n      ELSE IF ( PCHST(DEL1,DEL2) .LT. ZERO)  THEN\nC        NEED DO THIS CHECK ONLY IF MONOTONICITY SWITCHES.\n         DMAX = THREE*DEL2\n         IF (ABS(D(1,N)) .GT. ABS(DMAX))  D(1,N) = DMAX\n      ENDIF\nC\nC  NORMAL RETURN.\nC\n 5000 CONTINUE\n      RETURN\nC\nC  ERROR RETURNS.\nC\n 5001 CONTINUE\nC     N.LT.2 RETURN.\n      IERR = -1\n      CALL XERMSG ('SLATEC', 'PCHIM',\n     +   'NUMBER OF DATA POINTS LESS THAN TWO', IERR, 1)\n      RETURN\nC\n 5002 CONTINUE\nC     INCFD.LT.1 RETURN.\n      IERR = -2\n      CALL XERMSG ('SLATEC', 'PCHIM', 'INCREMENT LESS THAN ONE', IERR,\n     +   1)\n      RETURN\nC\n 5003 CONTINUE\nC     X-ARRAY NOT STRICTLY INCREASING.\n      IERR = -3\n      CALL XERMSG ('SLATEC', 'PCHIM', 'X-ARRAY NOT STRICTLY INCREASING'\n     +   , IERR, 1)\n      RETURN\nC------------- LAST LINE OF PCHIM FOLLOWS ------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/pchst.f",
    "content": "*DECK PCHST\n      REAL FUNCTION PCHST (ARG1, ARG2)\nC***BEGIN PROLOGUE  PCHST\nC***SUBSIDIARY\nC***PURPOSE  PCHIP Sign-Testing Routine\nC***LIBRARY   SLATEC (PCHIP)\nC***TYPE      SINGLE PRECISION (PCHST-S, DPCHST-D)\nC***AUTHOR  Fritsch, F. N., (LLNL)\nC***DESCRIPTION\nC\nC         PCHST:  PCHIP Sign-Testing Routine.\nC\nC     Returns:\nC        -1. if ARG1 and ARG2 are of opposite sign.\nC         0. if either argument is zero.\nC        +1. if ARG1 and ARG2 are of the same sign.\nC\nC     The object is to do this without multiplying ARG1*ARG2, to avoid\nC     possible over/underflow problems.\nC\nC  Fortran intrinsics used:  SIGN.\nC\nC***SEE ALSO  PCHCE, PCHCI, PCHCS, PCHIM\nC***ROUTINES CALLED  (NONE)\nC***REVISION HISTORY  (YYMMDD)\nC   811103  DATE WRITTEN\nC   820805  Converted to SLATEC library version.\nC   870813  Minor cosmetic changes.\nC   890411  Added SAVE statements (Vers. 3.2).\nC   890411  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900328  Added TYPE section.  (WRB)\nC   910408  Updated AUTHOR and DATE WRITTEN sections in prologue.  (WRB)\nC   930503  Improved purpose.  (FNF)\nC***END PROLOGUE  PCHST\nC\nC**End\nC\nC  DECLARE ARGUMENTS.\nC\n      REAL  ARG1, ARG2\nC\nC  DECLARE LOCAL VARIABLES.\nC\n      REAL  ONE, ZERO\n      SAVE ZERO, ONE\n      DATA  ZERO /0./,  ONE /1./\nC\nC  PERFORM THE TEST.\nC\nC***FIRST EXECUTABLE STATEMENT  PCHST\n      PCHST = SIGN(ONE,ARG1) * SIGN(ONE,ARG2)\n      IF ((ARG1.EQ.ZERO) .OR. (ARG2.EQ.ZERO))  PCHST = ZERO\nC\n      RETURN\nC------------- LAST LINE OF PCHST FOLLOWS ------------------------------\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/psifn.f",
    "content": "*DECK PSIFN\n      SUBROUTINE PSIFN (X, N, KODE, M, ANS, NZ, IERR)\nC***BEGIN PROLOGUE  PSIFN\nC***PURPOSE  Compute derivatives of the Psi function.\nC***LIBRARY   SLATEC\nC***CATEGORY  C7C\nC***TYPE      SINGLE PRECISION (PSIFN-S, DPSIFN-D)\nC***KEYWORDS  DERIVATIVES OF THE GAMMA FUNCTION, POLYGAMMA FUNCTION,\nC             PSI FUNCTION\nC***AUTHOR  Amos, D. E., (SNLA)\nC***DESCRIPTION\nC\nC         The following definitions are used in PSIFN:\nC\nC      Definition 1\nC         PSI(X) = d/dx (ln(GAMMA(X)), the first derivative of\nC                  the LOG GAMMA function.\nC      Definition 2\nC                     K   K\nC         PSI(K,X) = d /dx (PSI(X)), the K-th derivative of PSI(X).\nC   ___________________________________________________________________\nC       PSIFN computes a sequence of SCALED derivatives of\nC       the PSI function; i.e. for fixed X and M it computes\nC       the M-member sequence\nC\nC                  ((-1)**(K+1)/GAMMA(K+1))*PSI(K,X)\nC                    for K = N,...,N+M-1\nC\nC       where PSI(K,X) is as defined above.   For KODE=1, PSIFN returns\nC       the scaled derivatives as described.  KODE=2 is operative only\nC       when K=0 and in that case PSIFN returns -PSI(X) + LN(X).  That\nC       is, the logarithmic behavior for large X is removed when KODE=1\nC       and K=0.  When sums or differences of PSI functions are computed\nC       the logarithmic terms can be combined analytically and computed\nC       separately to help retain significant digits.\nC\nC         Note that CALL PSIFN(X,0,1,1,ANS) results in\nC                   ANS = -PSI(X)\nC\nC     Input\nC           X      - Argument, X .gt. 0.0E0\nC           N      - First member of the sequence, 0 .le. N .le. 100\nC                    N=0 gives ANS(1) = -PSI(X)       for KODE=1\nC                                       -PSI(X)+LN(X) for KODE=2\nC           KODE   - Selection parameter\nC                    KODE=1 returns scaled derivatives of the PSI\nC                    function.\nC                    KODE=2 returns scaled derivatives of the PSI\nC                    function EXCEPT when N=0. In this case,\nC                    ANS(1) = -PSI(X) + LN(X) is returned.\nC           M      - Number of members of the sequence, M .ge. 1\nC\nC    Output\nC           ANS    - A vector of length at least M whose first M\nC                    components contain the sequence of derivatives\nC                    scaled according to KODE.\nC           NZ     - Underflow flag\nC                    NZ.eq.0, A normal return\nC                    NZ.ne.0, Underflow, last NZ components of ANS are\nC                             set to zero, ANS(M-K+1)=0.0, K=1,...,NZ\nC           IERR   - Error flag\nC                    IERR=0, A normal return, computation completed\nC                    IERR=1, Input error,     no computation\nC                    IERR=2, Overflow,        X too small or N+M-1 too\nC                            large or both\nC                    IERR=3, Error,           N too large. Dimensioned\nC                            array TRMR(NMAX) is not large enough for N\nC\nC         The nominal computational accuracy is the maximum of unit\nC         roundoff (=R1MACH(4)) and 1.0E-18 since critical constants\nC         are given to only 18 digits.\nC\nC         DPSIFN is the Double Precision version of PSIFN.\nC\nC *Long Description:\nC\nC         The basic method of evaluation is the asymptotic expansion\nC         for large X.ge.XMIN followed by backward recursion on a two\nC         term recursion relation\nC\nC                  W(X+1) + X**(-N-1) = W(X).\nC\nC         This is supplemented by a series\nC\nC                  SUM( (X+K)**(-N-1) , K=0,1,2,... )\nC\nC         which converges rapidly for large N. Both XMIN and the\nC         number of terms of the series are calculated from the unit\nC         roundoff of the machine environment.\nC\nC***REFERENCES  Handbook of Mathematical Functions, National Bureau\nC                 of Standards Applied Mathematics Series 55, edited\nC                 by M. Abramowitz and I. A. Stegun, equations 6.3.5,\nC                 6.3.18, 6.4.6, 6.4.9 and 6.4.10, pp.258-260, 1964.\nC               D. E. Amos, A portable Fortran subroutine for\nC                 derivatives of the Psi function, Algorithm 610, ACM\nC                 Transactions on Mathematical Software 9, 4 (1983),\nC                 pp. 494-502.\nC***ROUTINES CALLED  I1MACH, R1MACH\nC***REVISION HISTORY  (YYMMDD)\nC   820601  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   920501  Reformatted the REFERENCES section.  (WRB)\nC***END PROLOGUE  PSIFN\n      INTEGER I, IERR, J, K, KODE, M, MM, MX, N, NMAX, NN, NP, NX, NZ\n      INTEGER I1MACH\n      REAL ANS, ARG, B, DEN, ELIM, EPS, FLN, FN, FNP, FNS, FX, RLN,\n     * RXSQ, R1M4, R1M5, S, SLOPE, T, TA, TK, TOL, TOLS, TRM, TRMR,\n     * TSS, TST, TT, T1, T2, WDTOL, X, XDMLN, XDMY, XINC, XLN, XM,\n     * XMIN, XQ, YINT\n      REAL R1MACH\n      DIMENSION B(22), TRM(22), TRMR(100), ANS(*)\n      SAVE NMAX, B\n      DATA NMAX /100/\nC-----------------------------------------------------------------------\nC             BERNOULLI NUMBERS\nC-----------------------------------------------------------------------\n      DATA B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), B(10),\n     * B(11), B(12), B(13), B(14), B(15), B(16), B(17), B(18), B(19),\n     * B(20), B(21), B(22) /1.00000000000000000E+00,\n     * -5.00000000000000000E-01,1.66666666666666667E-01,\n     * -3.33333333333333333E-02,2.38095238095238095E-02,\n     * -3.33333333333333333E-02,7.57575757575757576E-02,\n     * -2.53113553113553114E-01,1.16666666666666667E+00,\n     * -7.09215686274509804E+00,5.49711779448621554E+01,\n     * -5.29124242424242424E+02,6.19212318840579710E+03,\n     * -8.65802531135531136E+04,1.42551716666666667E+06,\n     * -2.72982310678160920E+07,6.01580873900642368E+08,\n     * -1.51163157670921569E+10,4.29614643061166667E+11,\n     * -1.37116552050883328E+13,4.88332318973593167E+14,\n     * -1.92965793419400681E+16/\nC\nC***FIRST EXECUTABLE STATEMENT  PSIFN\n      IERR = 0\n      NZ=0\n      IF (X.LE.0.0E0) IERR=1\n      IF (N.LT.0) IERR=1\n      IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1\n      IF (M.LT.1) IERR=1\n      IF (IERR.NE.0) RETURN\n      MM=M\n      NX = MIN(-I1MACH(12),I1MACH(13))\n      R1M5 = R1MACH(5)\n      R1M4 = R1MACH(4)*0.5E0\n      WDTOL = MAX(R1M4,0.5E-18)\nC-----------------------------------------------------------------------\nC     ELIM = APPROXIMATE EXPONENTIAL OVER AND UNDERFLOW LIMIT\nC-----------------------------------------------------------------------\n      ELIM = 2.302E0*(NX*R1M5-3.0E0)\n      XLN = LOG(X)\n   41 CONTINUE\n      NN = N + MM - 1\n      FN = NN\n      FNP = FN + 1.0E0\n      T = FNP*XLN\nC-----------------------------------------------------------------------\nC     OVERFLOW AND UNDERFLOW TEST FOR SMALL AND LARGE X\nC-----------------------------------------------------------------------\n      IF (ABS(T).GT.ELIM) GO TO 290\n      IF (X.LT.WDTOL) GO TO 260\nC-----------------------------------------------------------------------\nC     COMPUTE XMIN AND THE NUMBER OF TERMS OF THE SERIES, FLN+1\nC-----------------------------------------------------------------------\n      RLN = R1M5*I1MACH(11)\n      RLN = MIN(RLN,18.06E0)\n      FLN = MAX(RLN,3.0E0) - 3.0E0\n      YINT = 3.50E0 + 0.40E0*FLN\n      SLOPE = 0.21E0 + FLN*(0.0006038E0*FLN+0.008677E0)\n      XM = YINT + SLOPE*FN\n      MX = INT(XM) + 1\n      XMIN = MX\n      IF (N.EQ.0) GO TO 50\n      XM = -2.302E0*RLN - MIN(0.0E0,XLN)\n      FNS = N\n      ARG = XM/FNS\n      ARG = MIN(0.0E0,ARG)\n      EPS = EXP(ARG)\n      XM = 1.0E0 - EPS\n      IF (ABS(ARG).LT.1.0E-3) XM = -ARG\n      FLN = X*XM/EPS\n      XM = XMIN - X\n      IF (XM.GT.7.0E0 .AND. FLN.LT.15.0E0) GO TO 200\n   50 CONTINUE\n      XDMY = X\n      XDMLN = XLN\n      XINC = 0.0E0\n      IF (X.GE.XMIN) GO TO 60\n      NX = INT(X)\n      XINC = XMIN - NX\n      XDMY = X + XINC\n      XDMLN = LOG(XDMY)\n   60 CONTINUE\nC-----------------------------------------------------------------------\nC     GENERATE W(N+MM-1,X) BY THE ASYMPTOTIC EXPANSION\nC-----------------------------------------------------------------------\n      T = FN*XDMLN\n      T1 = XDMLN + XDMLN\n      T2 = T + XDMLN\n      TK = MAX(ABS(T),ABS(T1),ABS(T2))\n      IF (TK.GT.ELIM) GO TO 380\n      TSS = EXP(-T)\n      TT = 0.5E0/XDMY\n      T1 = TT\n      TST = WDTOL*TT\n      IF (NN.NE.0) T1 = TT + 1.0E0/FN\n      RXSQ = 1.0E0/(XDMY*XDMY)\n      TA = 0.5E0*RXSQ\n      T = FNP*TA\n      S = T*B(3)\n      IF (ABS(S).LT.TST) GO TO 80\n      TK = 2.0E0\n      DO 70 K=4,22\n        T = T*((TK+FN+1.0E0)/(TK+1.0E0))*((TK+FN)/(TK+2.0E0))*RXSQ\n        TRM(K) = T*B(K)\n        IF (ABS(TRM(K)).LT.TST) GO TO 80\n        S = S + TRM(K)\n        TK = TK + 2.0E0\n   70 CONTINUE\n   80 CONTINUE\n      S = (S+T1)*TSS\n      IF (XINC.EQ.0.0E0) GO TO 100\nC-----------------------------------------------------------------------\nC     BACKWARD RECUR FROM XDMY TO X\nC-----------------------------------------------------------------------\n      NX = INT(XINC)\n      NP = NN + 1\n      IF (NX.GT.NMAX) GO TO 390\n      IF (NN.EQ.0) GO TO 160\n      XM = XINC - 1.0E0\n      FX = X + XM\nC-----------------------------------------------------------------------\nC     THIS LOOP SHOULD NOT BE CHANGED. FX IS ACCURATE WHEN X IS SMALL\nC-----------------------------------------------------------------------\n      DO 90 I=1,NX\n        TRMR(I) = FX**(-NP)\n        S = S + TRMR(I)\n        XM = XM - 1.0E0\n        FX = X + XM\n   90 CONTINUE\n  100 CONTINUE\n      ANS(MM) = S\n      IF (FN.EQ.0.0E0) GO TO 180\nC-----------------------------------------------------------------------\nC     GENERATE LOWER DERIVATIVES, J.LT.N+MM-1\nC-----------------------------------------------------------------------\n      IF (MM.EQ.1) RETURN\n      DO 150 J=2,MM\n        FNP = FN\n        FN = FN - 1.0E0\n        TSS = TSS*XDMY\n        T1 = TT\n        IF (FN.NE.0.0E0) T1 = TT + 1.0E0/FN\n        T = FNP*TA\n        S = T*B(3)\n        IF (ABS(S).LT.TST) GO TO 120\n        TK = 3.0E0 + FNP\n        DO 110 K=4,22\n          TRM(K) = TRM(K)*FNP/TK\n          IF (ABS(TRM(K)).LT.TST) GO TO 120\n          S = S + TRM(K)\n          TK = TK + 2.0E0\n  110   CONTINUE\n  120   CONTINUE\n        S = (S+T1)*TSS\n        IF (XINC.EQ.0.0E0) GO TO 140\n        IF (FN.EQ.0.0E0) GO TO 160\n        XM = XINC - 1.0E0\n        FX = X + XM\n        DO 130 I=1,NX\n          TRMR(I) = TRMR(I)*FX\n          S = S + TRMR(I)\n          XM = XM - 1.0E0\n          FX = X + XM\n  130   CONTINUE\n  140   CONTINUE\n        MX = MM - J + 1\n        ANS(MX) = S\n        IF (FN.EQ.0.0E0) GO TO 180\n  150 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     RECURSION FOR N = 0\nC-----------------------------------------------------------------------\n  160 CONTINUE\n      DO 170 I=1,NX\n        S = S + 1.0E0/(X+NX-I)\n  170 CONTINUE\n  180 CONTINUE\n      IF (KODE.EQ.2) GO TO 190\n      ANS(1) = S - XDMLN\n      RETURN\n  190 CONTINUE\n      IF (XDMY.EQ.X) RETURN\n      XQ = XDMY/X\n      ANS(1) = S - LOG(XQ)\n      RETURN\nC-----------------------------------------------------------------------\nC     COMPUTE BY SERIES (X+K)**(-(N+1)) , K=0,1,2,...\nC-----------------------------------------------------------------------\n  200 CONTINUE\n      NN = INT(FLN) + 1\n      NP = N + 1\n      T1 = (FNS+1.0E0)*XLN\n      T = EXP(-T1)\n      S = T\n      DEN = X\n      DO 210 I=1,NN\n        DEN = DEN + 1.0E0\n        TRM(I) = DEN**(-NP)\n        S = S + TRM(I)\n  210 CONTINUE\n      ANS(1) = S\n      IF (N.NE.0) GO TO 220\n      IF (KODE.EQ.2) ANS(1) = S + XLN\n  220 CONTINUE\n      IF (MM.EQ.1) RETURN\nC-----------------------------------------------------------------------\nC     GENERATE HIGHER DERIVATIVES, J.GT.N\nC-----------------------------------------------------------------------\n      TOL = WDTOL/5.0E0\n      DO 250 J=2,MM\n        T = T/X\n        S = T\n        TOLS = T*TOL\n        DEN = X\n        DO 230 I=1,NN\n          DEN = DEN + 1.0E0\n          TRM(I) = TRM(I)/DEN\n          S = S + TRM(I)\n          IF (TRM(I).LT.TOLS) GO TO 240\n  230   CONTINUE\n  240   CONTINUE\n        ANS(J) = S\n  250 CONTINUE\n      RETURN\nC-----------------------------------------------------------------------\nC     SMALL X.LT.UNIT ROUND OFF\nC-----------------------------------------------------------------------\n  260 CONTINUE\n      ANS(1) = X**(-N-1)\n      IF (MM.EQ.1) GO TO 280\n      K = 1\n      DO 270 I=2,MM\n        ANS(K+1) = ANS(K)/X\n        K = K + 1\n  270 CONTINUE\n  280 CONTINUE\n      IF (N.NE.0) RETURN\n      IF (KODE.EQ.2) ANS(1) = ANS(1) + XLN\n      RETURN\n  290 CONTINUE\n      IF (T.GT.0.0E0) GO TO 380\n      NZ=0\n      IERR=2\n      RETURN\n  380 CONTINUE\n      NZ=NZ+1\n      ANS(MM)=0.0E0\n      MM=MM-1\n      IF(MM.EQ.0) RETURN\n      GO TO 41\n  390 CONTINUE\n      IERR=3\n      NZ=0\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/r9gmit.f",
    "content": "*DECK R9GMIT\n      FUNCTION R9GMIT (A, X, ALGAP1, SGNGAM, ALX)\nC***BEGIN PROLOGUE  R9GMIT\nC***SUBSIDIARY\nC***PURPOSE  Compute Tricomi's incomplete Gamma function for small\nC            arguments.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7E\nC***TYPE      SINGLE PRECISION (R9GMIT-S, D9GMIT-D)\nC***KEYWORDS  COMPLEMENTARY INCOMPLETE GAMMA FUNCTION, FNLIB, SMALL X,\nC             SPECIAL FUNCTIONS, TRICOMI\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Compute Tricomi's incomplete gamma function for small X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  ALNGAM, R1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900720  Routine changed from user-callable to subsidiary.  (WRB)\nC***END PROLOGUE  R9GMIT\n      SAVE EPS, BOT\n      DATA EPS, BOT / 2*0.0 /\nC***FIRST EXECUTABLE STATEMENT  R9GMIT\n      IF (EPS.EQ.0.0) EPS = 0.5*R1MACH(3)\n      IF (BOT.EQ.0.0) BOT = LOG(R1MACH(1))\nC\n      IF (X .LE. 0.0) CALL XERMSG ('SLATEC', 'R9GMIT',\n     +   'X SHOULD BE GT 0', 1, 2)\nC\n      MA = A + 0.5\n      IF (A.LT.0.0) MA = A - 0.5\n      AEPS = A - MA\nC\n      AE = A\n      IF (A.LT.(-0.5)) AE = AEPS\nC\n      T = 1.0\n      TE = AE\n      S = T\n      DO 20 K=1,200\n        FK = K\n        TE = -X*TE/FK\n        T = TE/(AE+FK)\n        S = S + T\n        IF (ABS(T).LT.EPS*ABS(S)) GO TO 30\n 20   CONTINUE\n      CALL XERMSG ('SLATEC', 'R9GMIT',\n     +   'NO CONVERGENCE IN 200 TERMS OF TAYLOR-S SERIES', 2, 2)\nC\n 30   IF (A.GE.(-0.5)) ALGS = -ALGAP1 + LOG(S)\n      IF (A.GE.(-0.5)) GO TO 60\nC\n      ALGS = -ALNGAM(1.0+AEPS) + LOG(S)\n      S = 1.0\n      M = -MA - 1\n      IF (M.EQ.0) GO TO 50\n      T = 1.0\n      DO 40 K=1,M\n        T = X*T/(AEPS-M-1+K)\n        S = S + T\n        IF (ABS(T).LT.EPS*ABS(S)) GO TO 50\n 40   CONTINUE\nC\n 50   R9GMIT = 0.0\n      ALGS = -MA*LOG(X) + ALGS\n      IF (S.EQ.0.0 .OR. AEPS.EQ.0.0) GO TO 60\nC\n      SGNG2 = SGNGAM*SIGN(1.0,S)\n      ALG2 = -X - ALGAP1 + LOG(ABS(S))\nC\n      IF (ALG2.GT.BOT) R9GMIT = SGNG2*EXP(ALG2)\n      IF (ALGS.GT.BOT) R9GMIT = R9GMIT + EXP(ALGS)\n      RETURN\nC\n 60   R9GMIT = EXP(ALGS)\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/r9lgic.f",
    "content": "*DECK R9LGIC\n      FUNCTION R9LGIC (A, X, ALX)\nC***BEGIN PROLOGUE  R9LGIC\nC***SUBSIDIARY\nC***PURPOSE  Compute the log complementary incomplete Gamma function\nC            for large X and for A .LE. X.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7E\nC***TYPE      SINGLE PRECISION (R9LGIC-S, D9LGIC-D)\nC***KEYWORDS  COMPLEMENTARY INCOMPLETE GAMMA FUNCTION, FNLIB, LARGE X,\nC             LOGARITHM, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Compute the log complementary incomplete gamma function for large X\nC and for A .LE. X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  R1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900720  Routine changed from user-callable to subsidiary.  (WRB)\nC***END PROLOGUE  R9LGIC\n      SAVE EPS\n      DATA EPS / 0.0 /\nC***FIRST EXECUTABLE STATEMENT  R9LGIC\n      IF (EPS.EQ.0.0) EPS = 0.5*R1MACH(3)\nC\n      XPA = X + 1.0 - A\n      XMA = X - 1.0 - A\nC\n      R = 0.0\n      P = 1.0\n      S = P\n      DO 10 K=1,200\n        FK = K\n        T = FK*(A-FK)*(1.0+R)\n        R = -T/((XMA+2.0*FK)*(XPA+2.0*FK)+T)\n        P = R*P\n        S = S + P\n        IF (ABS(P).LT.EPS*S) GO TO 20\n 10   CONTINUE\n      CALL XERMSG ('SLATEC', 'R9LGIC',\n     +   'NO CONVERGENCE IN 200 TERMS OF CONTINUED FRACTION', 1, 2)\nC\n 20   R9LGIC = A*ALX - X + LOG(S/XPA)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/r9lgit.f",
    "content": "*DECK R9LGIT\n      FUNCTION R9LGIT (A, X, ALGAP1)\nC***BEGIN PROLOGUE  R9LGIT\nC***SUBSIDIARY\nC***PURPOSE  Compute the logarithm of Tricomi's incomplete Gamma\nC            function with Perron's continued fraction for large X and\nC            A .GE. X.\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7E\nC***TYPE      SINGLE PRECISION (R9LGIT-S, D9LGIT-D)\nC***KEYWORDS  FNLIB, INCOMPLETE GAMMA FUNCTION, LOGARITHM,\nC             PERRON'S CONTINUED FRACTION, SPECIAL FUNCTIONS, TRICOMI\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Compute the log of Tricomi's incomplete gamma function with Perron's\nC continued fraction for large X and for A .GE. X.\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  R1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770701  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900720  Routine changed from user-callable to subsidiary.  (WRB)\nC***END PROLOGUE  R9LGIT\n      SAVE EPS, SQEPS\n      DATA EPS, SQEPS / 2*0.0 /\nC***FIRST EXECUTABLE STATEMENT  R9LGIT\n      IF (EPS.EQ.0.0) EPS = 0.5*R1MACH(3)\n      IF (SQEPS.EQ.0.0) SQEPS = SQRT(R1MACH(4))\nC\n      IF (X .LE. 0.0 .OR. A .LT. X) CALL XERMSG ('SLATEC', 'R9LGIT',\n     +   'X SHOULD BE GT 0.0 AND LE A', 2, 2)\nC\n      AX = A + X\n      A1X = AX + 1.0\n      R = 0.0\n      P = 1.0\n      S = P\n      DO 20 K=1,200\n        FK = K\n        T = (A+FK)*X*(1.0+R)\n        R = T/((AX+FK)*(A1X+FK)-T)\n        P = R*P\n        S = S + P\n        IF (ABS(P).LT.EPS*S) GO TO 30\n 20   CONTINUE\n      CALL XERMSG ('SLATEC', 'R9LGIT',\n     +   'NO CONVERGENCE IN 200 TERMS OF CONTINUED FRACTION', 3, 2)\nC\n 30   HSTAR = 1.0 - X*S/A1X\n      IF (HSTAR .LT. SQEPS) CALL XERMSG ('SLATEC', 'R9LGIT',\n     +   'RESULT LESS THAN HALF PRECISION', 1, 1)\nC\n      R9LGIT = -X - ALGAP1 - LOG(HSTAR)\nC\n      RETURN\n      END\n"
  },
  {
    "path": "liboctave/external/slatec-fn/r9lgmc.f",
    "content": "*DECK R9LGMC\n      FUNCTION R9LGMC (X)\nC***BEGIN PROLOGUE  R9LGMC\nC***SUBSIDIARY\nC***PURPOSE  Compute the log Gamma correction factor so that\nC            LOG(GAMMA(X)) = LOG(SQRT(2*PI)) + (X-.5)*LOG(X) - X\nC            + R9LGMC(X).\nC***LIBRARY   SLATEC (FNLIB)\nC***CATEGORY  C7E\nC***TYPE      SINGLE PRECISION (R9LGMC-S, D9LGMC-D, C9LGMC-C)\nC***KEYWORDS  COMPLETE GAMMA FUNCTION, CORRECTION TERM, FNLIB,\nC             LOG GAMMA, LOGARITHM, SPECIAL FUNCTIONS\nC***AUTHOR  Fullerton, W., (LANL)\nC***DESCRIPTION\nC\nC Compute the log gamma correction factor for X .GE. 10.0 so that\nC  LOG (GAMMA(X)) = LOG(SQRT(2*PI)) + (X-.5)*LOG(X) - X + R9LGMC(X)\nC\nC Series for ALGM       on the interval  0.          to  1.00000D-02\nC                                        with weighted error   3.40E-16\nC                                         log weighted error  15.47\nC                               significant figures required  14.39\nC                                    decimal places required  15.86\nC\nC***REFERENCES  (NONE)\nC***ROUTINES CALLED  CSEVL, INITS, R1MACH, XERMSG\nC***REVISION HISTORY  (YYMMDD)\nC   770801  DATE WRITTEN\nC   890531  Changed all specific intrinsics to generic.  (WRB)\nC   890531  REVISION DATE from Version 3.2\nC   891214  Prologue converted to Version 4.0 format.  (BAB)\nC   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ)\nC   900720  Routine changed from user-callable to subsidiary.  (WRB)\nC***END PROLOGUE  R9LGMC\n      DIMENSION ALGMCS(6)\n      LOGICAL FIRST\n      SAVE ALGMCS, NALGM, XBIG, XMAX, FIRST\n      DATA ALGMCS( 1) /    .1666389480 45186E0 /\n      DATA ALGMCS( 2) /   -.0000138494 817606E0 /\n      DATA ALGMCS( 3) /    .0000000098 108256E0 /\n      DATA ALGMCS( 4) /   -.0000000000 180912E0 /\n      DATA ALGMCS( 5) /    .0000000000 000622E0 /\n      DATA ALGMCS( 6) /   -.0000000000 000003E0 /\n      DATA FIRST /.TRUE./\nC***FIRST EXECUTABLE STATEMENT  R9LGMC\n      IF (FIRST) THEN\n         NALGM = INITS (ALGMCS, 6, R1MACH(3))\n         XBIG = 1.0/SQRT(R1MACH(3))\n         XMAX = EXP (MIN(LOG(R1MACH(2)/12.0), -LOG(12.0*R1MACH(1))) )\n      ENDIF\n      FIRST = .FALSE.\nC\n      IF (X .LT. 10.0) CALL XERMSG ('SLATEC', 'R9LGMC',\n     +   'X MUST BE GE 10', 1, 2)\n      IF (X.GE.XMAX) GO TO 20\nC\n      R9LGMC = 1.0/(12.0*X)\n      IF (X.LT.XBIG) R9LGMC = CSEVL (2.0*(10./X)**2-1., ALGMCS, NALGM)/X\n      RETURN\nC\n 20   R9LGMC = 0.0\n      CALL XERMSG ('SLATEC', 'R9LGMC', 'X SO BIG R9LGMC UNDERFLOWS', 2,\n     +   1)\n      RETURN\nC\n      END\n"
  },
  {
    "path": "liboctave/liboctave-build-info.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_liboctave_build_info_h)\n#define octave_liboctave_build_info_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nextern OCTAVE_API std::string liboctave_hg_id ();\n\n#endif\n"
  },
  {
    "path": "liboctave/liboctave-build-info.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"liboctave-build-info.h\"\n\nstd::string\nliboctave_hg_id ()\n{\n  return \"%OCTAVE_HG_ID%\";\n}\n"
  },
  {
    "path": "liboctave/mk-version-h.in.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n: ${SED=@SED@}\n\nOCTAVE_API_VERSION=\"@OCTAVE_API_VERSION@\"\nOCTAVE_CANONICAL_HOST_TYPE=\"@canonical_host_type@\"\nOCTAVE_COPYRIGHT=\"@OCTAVE_COPYRIGHT@\"\nOCTAVE_MAJOR_VERSION=\"@OCTAVE_MAJOR_VERSION@\"\nOCTAVE_MINOR_VERSION=\"@OCTAVE_MINOR_VERSION@\"\nOCTAVE_PATCH_VERSION=\"@OCTAVE_PATCH_VERSION@\"\nOCTAVE_RELEASE_DATE=\"@OCTAVE_RELEASE_DATE@\"\nOCTAVE_VERSION=\"@OCTAVE_VERSION@\"\n\n$SED \\\n  -e \"s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by mk-version-h.|\" \\\n  -e \"s|%OCTAVE_API_VERSION%|\\\"${OCTAVE_API_VERSION}\\\"|\" \\\n  -e \"s|%OCTAVE_CANONICAL_HOST_TYPE%|\\\"${OCTAVE_CANONICAL_HOST_TYPE}\\\"|\" \\\n  -e \"s|%OCTAVE_COPYRIGHT%|\\\"${OCTAVE_COPYRIGHT}\\\"|\" \\\n  -e \"s|%OCTAVE_MAJOR_VERSION%|${OCTAVE_MAJOR_VERSION}|\" \\\n  -e \"s|%OCTAVE_MINOR_VERSION%|${OCTAVE_MINOR_VERSION}|\" \\\n  -e \"s|%OCTAVE_PATCH_VERSION%|${OCTAVE_PATCH_VERSION}|\" \\\n  -e \"s|%OCTAVE_RELEASE_DATE%|\\\"${OCTAVE_RELEASE_DATE}\\\"|\" \\\n  -e \"s|%OCTAVE_VERSION%|\\\"${OCTAVE_VERSION}\\\"|\"\n"
  },
  {
    "path": "liboctave/module.mk",
    "content": "%canon_reldir%_EXTRA_DIST = \\\n  %reldir%/liboctave-build-info.in.cc \\\n  %reldir%/mk-version-h.in.sh \\\n  %reldir%/version.cc \\\n  %reldir%/version.in.h\n\nGEN_CONFIG_SHELL += \\\n  %reldir%/mk-version-h.sh\n\n%canon_reldir%_CLEANFILES =\n%canon_reldir%_DISTCLEANFILES =\n%canon_reldir%_MAINTAINERCLEANFILES =\n\n## Search local directories before those specified by the user.\n%canon_reldir%_liboctave_la_CPPFLAGS = \\\n  @OCTAVE_DLL_DEFS@ \\\n  @EXTERNAL_DLL_DEFS@ \\\n  -I%reldir% -I$(srcdir)/%reldir% \\\n  -I$(srcdir)/%reldir%/array \\\n  -I%reldir%/numeric -I$(srcdir)/%reldir%/numeric \\\n  -I%reldir%/operators -I$(srcdir)/%reldir%/operators \\\n  -I$(srcdir)/%reldir%/system \\\n  -I$(srcdir)/%reldir%/util \\\n  -I$(srcdir)/%reldir%/wrappers\n\noctlib_LTLIBRARIES += %reldir%/liboctave.la\n\n%canon_reldir%_pkgconfig_DATA = %reldir%/octave.pc\n\nBUILT_INCS = \\\n  $(BUILT_LIBOCTAVE_OPERATORS_INC) \\\n  $(LIBOCTAVE_OPT_INC)\n\nBUILT_SOURCES += \\\n  $(BUILT_INCS) \\\n  $(BUILT_LIBOCTAVE_OPERATORS_SOURCES) \\\n  %reldir%/version.h\n\nLIBOCTAVE_BUILT_NODISTFILES = \\\n  %reldir%/liboctave-build-info.cc \\\n  %reldir%/version.h\n\noctinclude_HEADERS += \\\n  %reldir%/liboctave-build-info.h \\\n  $(ARRAY_INC) \\\n  $(EXTERNAL_INC) \\\n  $(NUMERIC_INC) \\\n  $(LIBOCTAVE_OPERATORS_INC) \\\n  $(SYSTEM_INC) \\\n  $(UTIL_INC) \\\n  $(OTHER_INC) \\\n  $(LIBOCTAVE_TEMPLATE_SRC)\n\nnodist_octinclude_HEADERS += \\\n  $(BUILT_INCS) \\\n  %reldir%/version.h\n\n## C++ files that are #included, not compiled\nOTHER_INC =\n\n## C++ files with templates that are #included, not compiled\nLIBOCTAVE_TEMPLATE_SRC =\n\n## A list of all files that could include tests\n\n%canon_reldir%_liboctave_la_LIBADD =\n%canon_reldir%_liboctave_la_LDFLAGS =\n\ninclude %reldir%/array/module.mk\ninclude %reldir%/external/module.mk\ninclude %reldir%/numeric/module.mk\ninclude %reldir%/operators/module.mk\ninclude %reldir%/system/module.mk\ninclude %reldir%/util/module.mk\ninclude %reldir%/wrappers/module.mk\n\nnodist_%canon_reldir%_liboctave_la_SOURCES = \\\n  %reldir%/liboctave-build-info.cc \\\n  %reldir%/version.cc \\\n  %reldir%/version.h\n\n%canon_reldir%_liboctave_la_LIBADD += \\\n  libgnu/libgnu.la \\\n  $(LIBOCTAVE_LINK_DEPS)\n\n## Increment the following version numbers as needed and according\n## to the rules in the etc/HACKING.md file:\n\n%canon_reldir%_liboctave_current = 13\n%canon_reldir%_liboctave_revision = 0\n%canon_reldir%_liboctave_age = 0\n\n%canon_reldir%_liboctave_version_info = $(%canon_reldir%_liboctave_current):$(%canon_reldir%_liboctave_revision):$(%canon_reldir%_liboctave_age)\n\n%canon_reldir%_liboctave_la_LDFLAGS += \\\n  $(AM_LDFLAGS) \\\n  -version-info $(%canon_reldir%_liboctave_version_info) \\\n  $(NO_UNDEFINED_LDFLAG) \\\n  @XTRA_EXTERNAL_SH_LDFLAGS@ \\\n  -bindir $(bindir) \\\n  $(LIBOCTAVE_LINK_OPTS) \\\n  $(WARN_LDFLAGS)\n\n## Rules to build test files\n\nLIBOCTAVE_TST_SRC = \\\n  $(%canon_reldir%_array_libarray_la_SOURCES) \\\n  $(%canon_reldir%_numeric_libnumeric_la_SOURCES) \\\n  $(%canon_reldir%_system_libsystem_la_SOURCES) \\\n  $(%canon_reldir%_util_libutil_la_SOURCES) \\\n  $(LIBOCTAVE_TEMPLATE_SRC)\n\nLIBOCTAVE_TST_FILES_SRC := $(shell $(SHELL) build-aux/find-files-with-tests.sh \"$(srcdir)\" $(LIBOCTAVE_TST_SRC))\n\nLIBOCTAVE_TST_FILES := $(addsuffix -tst,$(LIBOCTAVE_TST_FILES_SRC))\n\nliboctavetestsdir := $(octtestsdir)\n\nnobase_liboctavetests_DATA = $(LIBOCTAVE_TST_FILES)\n\n%reldir%/version.h: %reldir%/version.in.h %reldir%/mk-version-h.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(call simple-filter-rule,%reldir%/mk-version-h.sh)\n\n%reldir%/liboctave-build-info.cc: %reldir%/liboctave-build-info.in.cc HG-ID | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(build-info-commands)\n\nOCTAVE_INTERPRETER_TARGETS += \\\n  $(LIBOCTAVE_TST_FILES)\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n\n%canon_reldir%_CLEANFILES += \\\n  $(LIBOCTAVE_BUILT_NODISTFILES) \\\n  $(LIBOCTAVE_TST_FILES)\n\n%canon_reldir%_DISTCLEANFILES += \\\n  $(%canon_reldir%_pkgconfig_DATA)\n\nBUILT_NODISTFILES += $(LIBOCTAVE_BUILT_NODISTFILES)\n\nCLEANFILES += $(%canon_reldir%_CLEANFILES)\nDISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)\nMAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)\n\nliboctave-clean:\n\trm -f $(%canon_reldir%_CLEANFILES)\n\nliboctave-distclean: liboctave-clean\n\trm -f $(%canon_reldir%_DISTCLEANFILES)\n\nliboctave-maintainer-clean: liboctave-distclean\n\trm -f $(%canon_reldir%_MAINTAINERCLEANFILES)\n"
  },
  {
    "path": "liboctave/numeric/CollocWt.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <limits>\n#include <ostream>\n\n#include \"Array-oct.h\"\n#include \"CollocWt.h\"\n#include \"mappers.h\"\n#include \"oct-error.h\"\n\n// The following routines jcobi, dif, and dfopr are based on the code\n// found in J. Villadsen and M. L. Michelsen, Solution of Differential\n// Equation Models by Polynomial Approximation, Prentice-Hall, 1978,\n// pp. 418-420.\n//\n// Translated to C++ by jwe.\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Compute the first three derivatives of the node polynomial.\n//\n//                 n0     (alpha,beta)           n1\n//   p  (x)  =  (x)   *  p (x)         *  (1 - x)\n//    nt                   n\n//\n// at the interpolation points.  Each of the parameters n0 and n1\n// may be given the value 0 or 1.  The total number of points\n// nt = n + n0 + n1\n//\n// The values of root must be known before a call to dif is possible.\n// They may be computed using jcobi.\n\nstatic void dif (octave_idx_type nt, double *root, double *dif1,\n                 double *dif2, double *dif3)\n{\n  // Evaluate derivatives of node polynomial using recursion formulas.\n\n  for (octave_idx_type i = 0; i < nt; i++)\n    {\n      double x = root[i];\n\n      dif1[i] = 1.0;\n      dif2[i] = 0.0;\n      dif3[i] = 0.0;\n\n      for (octave_idx_type j = 0; j < nt; j++)\n        {\n          if (j != i)\n            {\n              double y = x - root[j];\n\n              dif3[i] = y * dif3[i] + 3.0 * dif2[i];\n              dif2[i] = y * dif2[i] + 2.0 * dif1[i];\n              dif1[i] = y * dif1[i];\n            }\n        }\n    }\n}\n\n// Compute the zeros of the Jacobi polynomial.\n//\n//    (alpha,beta)\n//   p  (x)\n//    n\n//\n// Use dif to compute the derivatives of the node\n// polynomial\n//\n//                 n0     (alpha,beta)           n1\n//   p  (x)  =  (x)   *  p (x)         *  (1 - x)\n//    nt                   n\n//\n// at the interpolation points.\n//\n// See Villadsen and Michelsen, pages 131-132 and 418.\n//\n// Input parameters:\n//\n//   nd     : the dimension of the vectors dif1, dif2, dif3, and root\n//\n//   n      : the degree of the jacobi polynomial, (i.e., the number\n//            of interior interpolation points)\n//\n//   n0     : determines whether x = 0 is included as an\n//            interpolation point\n//\n//              n0 = 0  ==>  x = 0 is not included\n//              n0 = 1  ==>  x = 0 is included\n//\n//   n1     : determines whether x = 1 is included as an\n//            interpolation point\n//\n//              n1 = 0  ==>  x = 1 is not included\n//              n1 = 1  ==>  x = 1 is included\n//\n//   alpha  : the value of alpha in the description of the jacobi\n//            polynomial\n//\n//   beta   : the value of beta in the description of the jacobi\n//            polynomial\n//\n//   For a more complete explanation of alpha an beta, see Villadsen\n//   and Michelsen, pages 57 to 59.\n//\n// Output parameters:\n//\n//   root   : one-dimensional vector containing on exit the\n//            n + n0 + n1 zeros of the node polynomial used in the\n//            interpolation routine\n//\n//   dif1   : one-dimensional vector containing the first derivative\n//            of the node polynomial at the zeros\n//\n//   dif2   : one-dimensional vector containing the second derivative\n//            of the node polynomial at the zeros\n//\n//   dif3   : one-dimensional vector containing the third derivative\n//            of the node polynomial at the zeros\n\nstatic bool\njcobi (octave_idx_type n, octave_idx_type n0, octave_idx_type n1,\n       double alpha, double beta, double *dif1, double *dif2,\n       double *dif3, double *root)\n{\n  liboctave_panic_unless (n0 == 0 || n0 == 1);\n  liboctave_panic_unless (n1 == 0 || n1 == 1);\n\n  octave_idx_type nt = n + n0 + n1;\n\n  liboctave_panic_unless (nt >= 1);\n\n  // -- first evaluation of coefficients in recursion formulas.\n  // -- recursion coefficients are stored in dif1 and dif2.\n\n  double ab = alpha + beta;\n  double ad = beta - alpha;\n  double ap = beta * alpha;\n\n  dif1[0] = (ad / (ab + 2.0) + 1.0) / 2.0;\n  dif2[0] = 0.0;\n\n  if (n >= 2)\n    {\n      for (octave_idx_type i = 1; i < n; i++)\n        {\n          double z1 = i;\n          double z = ab + 2 * z1;\n\n          dif1[i] = (ab * ad / z / (z + 2.0) + 1.0) / 2.0;\n\n          if (i == 1)\n            dif2[i] = (ab + ap + z1) / z / z / (z + 1.0);\n          else\n            {\n              z *= z;\n              double y = z1 * (ab + z1);\n              y *= (ap + y);\n              dif2[i] = y / z / (z - 1.0);\n            }\n        }\n    }\n\n  // Root determination by Newton method with suppression of previously\n  // determined roots.\n\n  double x = 0.0;\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      bool done = false;\n\n      int k = 0;\n\n      while (! done)\n        {\n          double xd = 0.0;\n          double xn = 1.0;\n          double xd1 = 0.0;\n          double xn1 = 0.0;\n\n          for (octave_idx_type j = 0; j < n; j++)\n            {\n              double xp  = (dif1[j] - x) * xn  - dif2[j] * xd;\n              double xp1 = (dif1[j] - x) * xn1 - dif2[j] * xd1 - xn;\n\n              xd  = xn;\n              xd1 = xn1;\n              xn  = xp;\n              xn1 = xp1;\n            }\n\n          double zc = 1.0;\n          double z = xn / xn1;\n\n          if (i != 0)\n            {\n              for (octave_idx_type j = 1; j <= i; j++)\n                zc -= z / (x - root[j-1]);\n            }\n\n          z /= zc;\n          x -= z;\n\n          // Famous last words: 100 iterations should be more than\n          // enough in all cases.\n\n          if (++k > 100 || math::isnan (z))\n            return false;\n\n          if (std::abs (z) <= 100 * std::numeric_limits<double>::epsilon ())\n            done = true;\n        }\n\n      root[i] = x;\n      x += std::sqrt (std::numeric_limits<double>::epsilon ());\n    }\n\n  // Add interpolation points at x = 0 and/or x = 1.\n\n  if (n0 != 0)\n    {\n      for (octave_idx_type i = n; i > 0; i--)\n        root[i] = root[i-1];\n\n      root[0] = 0.0;\n    }\n\n  if (n1 != 0)\n    root[nt-1] = 1.0;\n\n  dif (nt, root, dif1, dif2, dif3);\n\n  return true;\n}\n\n// Compute derivative weights for orthogonal collocation.\n//\n// See Villadsen and Michelsen, pages 133-134, 419.\n//\n// Input parameters:\n//\n//   nd     : the dimension of the vectors dif1, dif2, dif3, and root\n//\n//   n      : the degree of the jacobi polynomial, (i.e., the number\n//            of interior interpolation points)\n//\n//   n0     : determines whether x = 0 is included as an\n//            interpolation point\n//\n//              n0 = 0  ==>  x = 0 is not included\n//              n0 = 1  ==>  x = 0 is included\n//\n//   n1     : determines whether x = 1 is included as an\n//            interpolation point\n//\n//              n1 = 0  ==>  x = 1 is not included\n//              n1 = 1  ==>  x = 1 is included\n//\n//   i      : the index of the node for which the weights are to be\n//            calculated\n//\n//   id     : indicator\n//\n//              id = 1  ==>  first derivative weights are computed\n//              id = 2  ==>  second derivative weights are computed\n//              id = 3  ==>  gaussian weights are computed (in this\n//                           case, the value of i is irrelevant)\n//\n// Output parameters:\n//\n//   dif1   : one-dimensional vector containing the first derivative\n//            of the node polynomial at the zeros\n//\n//   dif2   : one-dimensional vector containing the second derivative\n//            of the node polynomial at the zeros\n//\n//   dif3   : one-dimensional vector containing the third derivative\n//            of the node polynomial at the zeros\n//\n//   vect   : one-dimensional vector of computed weights\n\nstatic void\ndfopr (octave_idx_type n, octave_idx_type n0, octave_idx_type n1,\n       octave_idx_type i, octave_idx_type id, double *dif1,\n       double *dif2, double *dif3, double *root, double *vect)\n{\n  liboctave_panic_unless (n0 == 0 || n0 == 1);\n  liboctave_panic_unless (n1 == 0 || n1 == 1);\n\n  octave_idx_type nt = n + n0 + n1;\n\n  liboctave_panic_unless (nt >= 1);\n\n  liboctave_panic_unless (id == 1 || id == 2 || id == 3);\n\n  if (id != 3)\n    liboctave_panic_unless (i >= 0 && i < nt);\n\n  // Evaluate discretization matrices and Gaussian quadrature weights.\n  // Quadrature weights are normalized to sum to one.\n\n  if (id != 3)\n    {\n      for (octave_idx_type j = 0; j < nt; j++)\n        {\n          if (j == i)\n            {\n              if (id == 1)\n                vect[i] = dif2[i] / dif1[i] / 2.0;\n              else\n                vect[i] = dif3[i] / dif1[i] / 3.0;\n            }\n          else\n            {\n              double y = root[i] - root[j];\n\n              vect[j] = dif1[i] / dif1[j] / y;\n\n              if (id == 2)\n                vect[j] = vect[j] * (dif2[i] / dif1[i] - 2.0 / y);\n            }\n        }\n    }\n  else\n    {\n      double y = 0.0;\n\n      for (octave_idx_type j = 0; j < nt; j++)\n        {\n          double x = root[j];\n\n          double ax = x * (1.0 - x);\n\n          if (n0 == 0)\n            ax = ax / x / x;\n\n          if (n1 == 0)\n            ax = ax / (1.0 - x) / (1.0 - x);\n\n          vect[j] = ax / (dif1[j] * dif1[j]);\n\n          y += vect[j];\n        }\n\n      for (octave_idx_type j = 0; j < nt; j++)\n        vect[j] = vect[j] / y;\n    }\n}\n\n// Error handling.\n\nvoid\nCollocWt::error (const char *msg)\n{\n  (*current_liboctave_error_handler) (\"CollocWt: fatal error '%s'\", msg);\n}\n\nCollocWt&\nCollocWt::set_left (double val)\n{\n  if (val >= m_rb)\n    error (\"CollocWt: left bound greater than right bound\");\n\n  m_lb = val;\n  m_initialized = 0;\n  return *this;\n}\n\nCollocWt&\nCollocWt::set_right (double val)\n{\n  if (val <= m_lb)\n    error (\"CollocWt: right bound less than left bound\");\n\n  m_rb = val;\n  m_initialized = 0;\n  return *this;\n}\n\nvoid\nCollocWt::init ()\n{\n  // Check for possible errors.\n\n  double wid = m_rb - m_lb;\n  if (wid <= 0.0)\n    {\n      error (\"CollocWt: width less than or equal to zero\");\n    }\n\n  octave_idx_type nt = m_n + m_inc_left + m_inc_right;\n\n  if (nt < 0)\n    error (\"CollocWt: total number of collocation points less than zero\");\n  else if (nt == 0)\n    return;\n\n  Array<double> dif1 (dim_vector (nt, 1));\n  double *pdif1 = dif1.rwdata ();\n\n  Array<double> dif2 (dim_vector (nt, 1));\n  double *pdif2 = dif2.rwdata ();\n\n  Array<double> dif3 (dim_vector (nt, 1));\n  double *pdif3 = dif3.rwdata ();\n\n  Array<double> vect (dim_vector (nt, 1));\n  double *pvect = vect.rwdata ();\n\n  m_r.resize (nt, 1);\n  m_q.resize (nt, 1);\n  m_A.resize (nt, nt);\n  m_B.resize (nt, nt);\n\n  double *pr = m_r.rwdata ();\n\n  // Compute roots.\n\n  if (! jcobi (m_n, m_inc_left, m_inc_right, m_alpha, m_beta, pdif1,\n               pdif2, pdif3, pr))\n    error (\"jcobi: newton iteration failed\");\n\n  octave_idx_type id;\n\n  // First derivative weights.\n\n  id = 1;\n  for (octave_idx_type i = 0; i < nt; i++)\n    {\n      dfopr (m_n, m_inc_left, m_inc_right, i, id, pdif1, pdif2, pdif3,\n             pr, pvect);\n\n      for (octave_idx_type j = 0; j < nt; j++)\n        m_A(i, j) = vect(j);\n    }\n\n  // Second derivative weights.\n\n  id = 2;\n  for (octave_idx_type i = 0; i < nt; i++)\n    {\n      dfopr (m_n, m_inc_left, m_inc_right, i, id, pdif1, pdif2, pdif3,\n             pr, pvect);\n\n      for (octave_idx_type j = 0; j < nt; j++)\n        m_B(i, j) = vect(j);\n    }\n\n  // Gaussian quadrature weights.\n\n  id = 3;\n  double *pq = m_q.rwdata ();\n  dfopr (m_n, m_inc_left, m_inc_right, id, id, pdif1, pdif2, pdif3, pr, pq);\n\n  m_initialized = 1;\n}\n\nstd::ostream&\noperator << (std::ostream& os, const CollocWt& a)\n{\n  if (a.left_included ())\n    os << \"left  boundary is included\\n\";\n  else\n    os << \"left  boundary is not included\\n\";\n\n  if (a.right_included ())\n    os << \"right boundary is included\\n\";\n  else\n    os << \"right boundary is not included\\n\";\n\n  os << \"\\n\";\n\n  os << a.m_alpha << ' ' << a.m_beta << \"\\n\\n\"\n     << a.m_r << \"\\n\\n\"\n     << a.m_q << \"\\n\\n\"\n     << a.m_A << \"\\n\"\n     << a.m_B << \"\\n\";\n\n  return os;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/CollocWt.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_CollocWt_h)\n#define octave_CollocWt_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n#include \"dMatrix.h\"\n#include \"dColVector.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTAVE_API CollocWt\n{\npublic:\n\n  CollocWt ()\n    : m_n (0), m_inc_left (0), m_inc_right (0), m_lb (0.0), m_rb (1.0),\n      m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (),\n      m_initialized (false)\n  { }\n\n  CollocWt (octave_idx_type nc, octave_idx_type il, octave_idx_type ir)\n    : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (0.0), m_rb (1.0),\n      m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (),\n      m_initialized (false)\n  { }\n\n  CollocWt (octave_idx_type nc, octave_idx_type il, octave_idx_type ir,\n            double l, double rr)\n    : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (l), m_rb (rr),\n      m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (),\n      m_initialized (false)\n  { }\n\n  CollocWt (octave_idx_type nc, double a, double b, octave_idx_type il,\n            octave_idx_type ir)\n    : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (0.0), m_rb (1.0),\n      m_alpha (a), m_beta (b), m_r (), m_q (), m_A (), m_B (),\n      m_initialized (false)\n  { }\n\n  CollocWt (octave_idx_type nc, double a, double b, octave_idx_type il,\n            octave_idx_type ir,\n            double ll, double rr)\n    : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (ll), m_rb (rr),\n      m_alpha (a), m_beta (b), m_r (), m_q (), m_A (), m_B (),\n      m_initialized (false)\n  { }\n\n  CollocWt (const CollocWt& a) = default;\n\n  CollocWt& operator = (const CollocWt& a) = default;\n\n  ~CollocWt () = default;\n\n  CollocWt& resize (octave_idx_type nc)\n  {\n    m_n = nc;\n    m_initialized = false;\n    return *this;\n  }\n\n  CollocWt& add_left ()\n  {\n    m_inc_left = 1;\n    m_initialized = false;\n    return *this;\n  }\n\n  CollocWt& delete_left ()\n  {\n    m_inc_left = 0;\n    m_initialized = false;\n    return *this;\n  }\n\n  CollocWt& set_left (double val);\n\n  CollocWt& add_right ()\n  {\n    m_inc_right = 1;\n    m_initialized = false;\n    return *this;\n  }\n\n  CollocWt& delete_right ()\n  {\n    m_inc_right = 0;\n    m_initialized = false;\n    return *this;\n  }\n\n  CollocWt& set_right (double val);\n\n  CollocWt& set_alpha (double val)\n  {\n    m_alpha = val;\n    m_initialized = false;\n    return *this;\n  }\n\n  CollocWt& set_beta (double val)\n  {\n    m_beta = val;\n    m_initialized = false;\n    return *this;\n  }\n\n  octave_idx_type ncol () const { return m_n; }\n\n  octave_idx_type left_included () const { return m_inc_left; }\n  octave_idx_type right_included () const { return m_inc_right; }\n\n  double left () const { return m_lb; }\n  double right () const { return m_rb; }\n\n  double width () const { return m_rb - m_lb; }\n\n  double alpha () const { return m_alpha; }\n  double beta () const { return m_beta; }\n\n  ColumnVector roots ()\n  {\n    if (! m_initialized)\n      init ();\n\n    return m_r;\n  }\n\n  ColumnVector quad ()\n  {\n    if (! m_initialized)\n      init ();\n\n    return m_q;\n  }\n\n  ColumnVector quad_weights () { return quad (); }\n\n  Matrix first ()\n  {\n    if (! m_initialized)\n      init ();\n\n    return m_A;\n  }\n\n  Matrix second ()\n  {\n    if (! m_initialized)\n      init ();\n\n    return m_B;\n  }\n\n  friend std::ostream& operator << (std::ostream&, const CollocWt&);\n\nprotected:\n\n  octave_idx_type m_n;\n\n  octave_idx_type m_inc_left;\n  octave_idx_type m_inc_right;\n\n  double m_lb;\n  double m_rb;\n\n  double m_alpha;\n  double m_beta;\n\n  ColumnVector m_r;\n  ColumnVector m_q;\n\n  Matrix m_A;\n  Matrix m_B;\n\n  bool m_initialized;\n\n  void init ();\n\n  void error (const char *msg);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/DAE.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_DAE_h)\n#define octave_DAE_h 1\n\n#include \"octave-config.h\"\n\n#include \"DAEFunc.h\"\n#include \"base-dae.h\"\n\nclass OCTAVE_API DAE : public base_diff_alg_eqn, public DAEFunc\n{\npublic:\n\n  DAE ()\n    : base_diff_alg_eqn (), DAEFunc () { }\n\n  DAE (const ColumnVector& xx, double tt, DAEFunc& f)\n    : base_diff_alg_eqn (xx, tt), DAEFunc (f) { }\n\n  DAE (const ColumnVector& xx, const ColumnVector& xxdot,\n       double tt, DAEFunc& f)\n    : base_diff_alg_eqn (xx, xxdot, tt), DAEFunc (f) { }\n\n  DAE (const DAE& a)\n    : base_diff_alg_eqn (a), DAEFunc (a) { }\n\n  DAE& operator = (const DAE& a)\n  {\n    if (this != &a)\n      {\n        base_diff_alg_eqn::operator = (a);\n        DAEFunc::operator = (a);\n      }\n    return *this;\n  }\n\n  virtual ~DAE () = default;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/DAEFunc.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_DAEFunc_h)\n#define octave_DAEFunc_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\nclass DAEFunc\n{\npublic:\n\n  typedef ColumnVector (*DAERHSFunc) (const ColumnVector& x,\n                                      const ColumnVector& xdot,\n                                      double t, octave_idx_type& ires);\n\n  // This is really the form used by DASSL:\n  //\n  //   PD = DG/DY + CJ * DG/DYPRIME\n\n  typedef Matrix (*DAEJacFunc) (const ColumnVector& x,\n                                const ColumnVector& xdot,\n                                double t, double cj);\n\n  DAEFunc ()\n    : m_fcn (nullptr), m_jac (nullptr), m_reset (true) { }\n\n  DAEFunc (DAERHSFunc f)\n    : m_fcn (f), m_jac (nullptr), m_reset (true) { }\n\n  DAEFunc (DAERHSFunc f, DAEJacFunc j)\n    : m_fcn (f), m_jac (j), m_reset (true) { }\n\n  DAEFunc (const DAEFunc& a)\n    : m_fcn (a.m_fcn), m_jac (a.m_jac), m_reset (a.m_reset) { }\n\n  DAEFunc& operator = (const DAEFunc& a)\n  {\n    if (this != &a)\n      {\n        m_fcn = a.m_fcn;\n        m_jac = a.m_jac;\n        m_reset = a.m_reset;\n      }\n    return *this;\n  }\n\n  virtual ~DAEFunc () = default;\n\n  DAERHSFunc function () const { return m_fcn; }\n\n  DAEFunc& set_function (DAERHSFunc f)\n  {\n    m_fcn = f;\n    m_reset = true;\n    return *this;\n  }\n\n  DAEJacFunc jacobian_function () const { return m_jac; }\n\n  DAEFunc& set_jacobian_function (DAEJacFunc j)\n  {\n    m_jac = j;\n    m_reset = true;\n    return *this;\n  }\n\nprotected:\n\n  DAERHSFunc m_fcn;\n  DAEJacFunc m_jac;\n\n  // This variable is TRUE when this object is constructed, and also\n  // after any internal data has changed.  Derived classes may use\n  // this information (and change it) to know when to (re)initialize\n  // their own internal data related to this object.\n\n  bool m_reset;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/DAERT.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_DAERT_h)\n#define octave_DAERT_h 1\n\n#include \"octave-config.h\"\n\n#include \"DAE.h\"\n#include \"DAERTFunc.h\"\n#include \"base-dae.h\"\n\nclass DAERT : public base_diff_alg_eqn, public DAERTFunc\n{\npublic:\n\n  DAERT ()\n    : base_diff_alg_eqn (), DAERTFunc () { }\n\n  DAERT (const ColumnVector& xx, double tt, DAERTFunc& f)\n    : base_diff_alg_eqn (xx, tt), DAERTFunc (f) { }\n\n  DAERT (const ColumnVector& xx, const ColumnVector& xxdot, double tt,\n         DAERTFunc& f)\n    : base_diff_alg_eqn (xx, xxdot, tt), DAERTFunc (f) { }\n\n  DAERT (const DAERT& a)\n    : base_diff_alg_eqn (a), DAERTFunc (a) { }\n\n  DAERT& operator = (const DAERT& a)\n  {\n    if (this != &a)\n      {\n        base_diff_alg_eqn::operator = (a);\n        DAERTFunc::operator = (a);\n\n      }\n    return *this;\n  }\n\n  virtual ~DAERT () = default;\n\n  void initialize (const ColumnVector& xx, const ColumnVector& xxdot,\n                   double tt)\n  {\n    base_diff_alg_eqn::initialize (xx, xxdot, tt);\n  }\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/DAERTFunc.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_DAERTFunc_h)\n#define octave_DAERTFunc_h 1\n\n#include \"octave-config.h\"\n\n#include \"DAEFunc.h\"\n\nclass DAERTFunc : public DAEFunc\n{\npublic:\n\n  typedef ColumnVector (*DAERTConstrFunc) (const ColumnVector& x, double t);\n\n  DAERTFunc ()\n    : DAEFunc (), m_constr (nullptr), m_reset (true) { }\n\n  DAERTFunc (DAERHSFunc f)\n    : DAEFunc (f), m_constr (nullptr), m_reset (true) { }\n\n  DAERTFunc (DAERHSFunc f, DAEJacFunc j)\n    : DAEFunc (f, j), m_constr (nullptr), m_reset (true) { }\n\n  DAERTFunc (DAERHSFunc f, DAERTConstrFunc cf)\n    : DAEFunc (f), m_constr (cf), m_reset (true) { }\n\n  DAERTFunc (DAERHSFunc f, DAERTConstrFunc cf, DAEJacFunc j)\n    : DAEFunc (f, j), m_constr (cf), m_reset (true) { }\n\n  DAERTFunc (const DAERTFunc& a)\n    : DAEFunc (a), m_constr (a.m_constr), m_reset (a.m_reset) { }\n\n  DAERTFunc& operator = (const DAERTFunc& a)\n  {\n    if (this != &a)\n      {\n        DAEFunc::operator = (a);\n        m_constr = a.m_constr;\n        m_reset = a.m_reset;\n      }\n    return *this;\n  }\n\n  virtual ~DAERTFunc () = default;\n\n  DAERTConstrFunc constraint_function () const { return m_constr; }\n\n  DAERTFunc& set_constraint_function (DAERTConstrFunc cf)\n  {\n    m_constr = cf;\n    m_reset = true;\n    return *this;\n  }\n\nprotected:\n\n  DAERTConstrFunc m_constr;\n\n  // This variable is TRUE when this object is constructed, and also\n  // after any internal data has changed.  Derived classes may use\n  // this information (and change it) to know when to (re)initialize\n  // their own internal data related to this object.\n\n  bool m_reset;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/DASPK-opts.in",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nCLASS = \"DASPK\"\n\nINCLUDE = \"DAE.h\"\n\nOPTION\n  NAME = \"absolute tolerance\"\n  DOC_ITEM\nAbsolute tolerance.  May be either vector or scalar.  If a vector, it\nmust match the dimension of the state vector, and the relative\ntolerance must also be a vector of the same length.\n\n  END_DOC_ITEM\n  TYPE = \"Array<double>\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (1, 1));\n    $OPTVAR(0) = ::sqrt (std::numeric_limits<double>::epsilon ());\n  END_INIT_BODY\n  SET_CODE\n    void set_$OPT (double val)\n      {\n        $OPTVAR.resize (dim_vector (1, 1));\n        $OPTVAR(0) = (val > 0.0) ? val : ::sqrt (std::numeric_limits<double>::epsilon ());\n        m_reset = true;\n      }\n\n    void set_$OPT (const $TYPE& val)\n      { $OPTVAR = val; m_reset = true; }\n  END_SET_CODE\nEND_OPTION\n\nOPTION\n  NAME = \"relative tolerance\"\n  DOC_ITEM\nRelative tolerance.  May be either vector or scalar.  If a vector, it\nmust match the dimension of the state vector, and the absolute\ntolerance must also be a vector of the same length.\n\nThe local error test applied at each integration step is\n\n@example\n@group\n  abs (local error in x(i))\n       <= rtol(i) * abs (Y(i)) + atol(i)\n@end group\n@end example\n\n  END_DOC_ITEM\n  TYPE = \"Array<double>\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (1, 1));\n    $OPTVAR(0) = ::sqrt (std::numeric_limits<double>::epsilon ());\n  END_INIT_BODY\n  SET_CODE\n    void set_$OPT (double val)\n      {\n        $OPTVAR.resize (dim_vector (1, 1));\n        $OPTVAR(0) = (val > 0.0) ? val : ::sqrt (std::numeric_limits<double>::epsilon ());\n        m_reset = true;\n      }\n\n    void set_$OPT (const $TYPE& val)\n      { $OPTVAR = val; m_reset = true; }\n  END_SET_CODE\nEND_OPTION\n\nOPTION\n  NAME = \"compute consistent initial condition\"\n  DOC_ITEM\nDenoting the differential variables in the state vector by @samp{Y_d}\nand the algebraic variables by @samp{Y_a}, @code{ddaspk} can solve\none of two initialization problems:\n\n@enumerate\n@item Given Y_d, calculate Y_a and Y'_d\n\n@item Given Y', calculate Y.\n@end enumerate\n\nIn either case, initial values for the given components are input, and\ninitial guesses for the unknown components must also be provided as\ninput.  Set this option to 1 to solve the first problem, or 2 to solve\nthe second (the default is 0, so you must provide a set of\ninitial conditions that are consistent).\n\nIf this option is set to a nonzero value, you must also set the\n@qcode{\"algebraic variables\"} option to declare which variables in the\nproblem are algebraic.\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"0\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"use initial condition heuristics\"\n  DOC_ITEM\nSet to a nonzero value to use the initial condition heuristics options\ndescribed below.\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"0\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"initial condition heuristics\"\n  DOC_ITEM\nA vector of the following parameters that can be used to control the\ninitial condition calculation.\n\n@table @code\n@item MXNIT\nMaximum number of Newton iterations (default is 5).\n\n@item MXNJ\nMaximum number of Jacobian evaluations (default is 6).\n\n@item MXNH\nMaximum number of values of the artificial stepsize parameter to be\ntried if the @qcode{\"compute consistent initial condition\"} option has\nbeen set to 1 (default is 5).\n\nNote that the maximum total number of Newton iterations allowed is\n@code{MXNIT*MXNJ*MXNH} if the @qcode{\"compute consistent initial\ncondition\"} option has been set to 1 and @code{MXNIT*MXNJ} if it is\nset to 2.\n\n@item LSOFF\nSet to a nonzero value to disable the linesearch algorithm (default is\n0).\n\n@item STPTOL\nMinimum scaled step in linesearch algorithm (default is eps^(2/3)).\n\n@item EPINIT\nSwing factor in the Newton iteration convergence test.  The test is\napplied to the residual vector, premultiplied by the approximate\nJacobian.  For convergence, the weighted RMS norm of this vector\n(scaled by the error weights) must be less than @code{EPINIT*EPCON},\nwhere @code{EPCON} = 0.33 is the analogous test constant used in the\ntime steps.  The default is @code{EPINIT} = 0.01.\n@end table\n\n  END_DOC_ITEM\n  TYPE = \"Array<double>\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (6, 1));\n    $OPTVAR(0) = 5.0;\n    $OPTVAR(1) = 6.0;\n    $OPTVAR(2) = 5.0;\n    $OPTVAR(3) = 0.0;\n    $OPTVAR(4) = ::pow (std::numeric_limits<double>::epsilon (), 2.0/3.0);\n    $OPTVAR(5) = 0.01;\n  END_INIT_BODY\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"print initial condition info\"\n  DOC_ITEM\nSet this option to a nonzero value to display detailed information\nabout the initial condition calculation (default is 0).\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"0\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"exclude algebraic variables from error test\"\n  DOC_ITEM\nSet to a nonzero value to exclude algebraic variables from the error\ntest.  You must also set the @qcode{\"algebraic variables\"} option to\ndeclare which variables in the problem are algebraic (default is 0).\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"0\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"algebraic variables\"\n  DOC_ITEM\nA vector of the same length as the state vector.  A nonzero element\nindicates that the corresponding element of the state vector is an\nalgebraic variable (i.e., its derivative does not appear explicitly\nin the equation set).\n\nThis option is required by the\n@qcode{\"compute consistent initial condition\"} and\n@qcode{\"exclude algebraic variables from error test\"} options.\n\n  END_DOC_ITEM\n  TYPE = \"Array<octave_idx_type>\"\n  SET_ARG_TYPE = const $TYPE&\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (1, 1));\n    $OPTVAR(0) = 0;\n  END_INIT_BODY\n  SET_CODE\n    void set_$OPT (int val)\n      {\n        $OPTVAR.resize (dim_vector (1, 1));\n        $OPTVAR(0) = val;\n        m_reset = true;\n      }\n\n    void set_$OPT (const $TYPE& val)\n      { $OPTVAR = val; m_reset = true; }\n  END_SET_CODE\nEND_OPTION\n\nOPTION\n  NAME = \"enforce inequality constraints\"\n  DOC_ITEM\nSet to one of the following values to enforce the inequality\nconstraints specified by the @qcode{\"inequality constraint types\"}\noption (default is 0).\n\n@enumerate\n@item To have constraint checking only in the initial condition calculation.\n\n@item To enforce constraint checking during the integration.\n\n@item To enforce both options 1 and 2.\n@end enumerate\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"0\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"inequality constraint types\"\n  DOC_ITEM\nA vector of the same length as the state specifying the type of\ninequality constraint.  Each element of the vector corresponds to an\nelement of the state and should be assigned one of the following\ncodes\n\n@table @asis\n@item -2\nLess than zero.\n\n@item -1\nLess than or equal to zero.\n\n@item 0\nNot constrained.\n\n@item 1\nGreater than or equal to zero.\n\n@item 2\nGreater than zero.\n@end table\n\nThis option only has an effect if the\n@qcode{\"enforce inequality constraints\"} option is nonzero.\n\n  END_DOC_ITEM\n  TYPE = \"Array<octave_idx_type>\"\n  SET_ARG_TYPE = const $TYPE&\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (1, 1));\n    $OPTVAR(0) = 0;\n  END_INIT_BODY\n  SET_CODE\n    void set_$OPT (octave_idx_type val)\n      {\n        $OPTVAR.resize (dim_vector (1, 1));\n        $OPTVAR(0) = val;\n        m_reset = true;\n      }\n\n    void set_$OPT (const $TYPE& val)\n      { $OPTVAR = val; m_reset = true; }\n  END_SET_CODE\nEND_OPTION\n\nOPTION\n  NAME = \"initial step size\"\n  DOC_ITEM\nDifferential-algebraic problems may occasionally suffer from severe\nscaling difficulties on the first step.  If you know a great deal\nabout the scaling of your problem, you can help to alleviate this\nproblem by specifying an initial stepsize (default is computed\nautomatically).\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"-1.0\"\n  SET_EXPR = \"(val >= 0.0) ? val : -1.0\"\nEND_OPTION\n\nOPTION\n  NAME = \"maximum order\"\n  DOC_ITEM\nRestrict the maximum order of the solution method.  This option must\nbe between 1 and 5, inclusive (default is 5).\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"5\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"maximum step size\"\n  DOC_ITEM\nSetting the maximum stepsize will avoid passing over very large\nregions (default is not specified).\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"-1.0\"\n  SET_EXPR = \"(val >= 0.0) ? val : -1.0\"\nEND_OPTION\n"
  },
  {
    "path": "liboctave/numeric/DASPK.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n\n#include \"DASPK.h\"\n#include \"dMatrix.h\"\n#include \"f77-fcn.h\"\n#include \"oct-error.h\"\n\ntypedef F77_INT (*daspk_fcn_ptr) (const double&, const double *, const double *,\n                                  const double&, double *, F77_INT&, double *,\n                                  F77_INT *);\n\ntypedef F77_INT (*daspk_jac_ptr) (const double&, const double *, const double *,\n                                  double *, const double&, double *, F77_INT *);\n\ntypedef F77_INT (*daspk_psol_ptr) (const F77_INT&, const double&,\n                                   const double *, const double *,\n                                   const double *, const double&,\n                                   const double *, double *, F77_INT *,\n                                   double *, const double&, F77_INT&,\n                                   double *, F77_INT *);\n\nextern \"C\"\n{\n  F77_RET_T\n  F77_FUNC (ddaspk, DDASPK) (daspk_fcn_ptr, const F77_INT&, F77_DBLE&,\n                             F77_DBLE *, F77_DBLE *, F77_DBLE&, const F77_INT *,\n                             const F77_DBLE *, const F77_DBLE *, F77_INT&,\n                             F77_DBLE *, const F77_INT&, F77_INT *,\n                             const F77_INT&, const F77_DBLE *, const F77_INT *,\n                             daspk_jac_ptr, daspk_psol_ptr);\n}\n\nstatic DAEFunc::DAERHSFunc user_fcn;\nstatic DAEFunc::DAEJacFunc user_jac;\nstatic F77_INT nn;\n\nstatic F77_INT\nddaspk_f (const double& time, const double *state, const double *deriv,\n          const double&, double *delta, F77_INT& ires, double *, F77_INT *)\n{\n  ColumnVector tmp_deriv (nn);\n  ColumnVector tmp_state (nn);\n  ColumnVector tmp_delta (nn);\n\n  for (F77_INT i = 0; i < nn; i++)\n    {\n      tmp_deriv.elem (i) = deriv[i];\n      tmp_state.elem (i) = state[i];\n    }\n\n  octave_idx_type tmp_ires = ires;\n\n  tmp_delta = user_fcn (tmp_state, tmp_deriv, time, tmp_ires);\n\n  ires = octave::to_f77_int (tmp_ires);\n\n  if (ires >= 0)\n    {\n      if (tmp_delta.isempty ())\n        ires = -2;\n      else\n        {\n          for (F77_INT i = 0; i < nn; i++)\n            delta[i] = tmp_delta.elem (i);\n        }\n    }\n\n  return 0;\n}\n\n//NEQ, T, Y, YPRIME, SAVR, WK, CJ, WGHT,\n//C                          WP, IWP, B, EPLIN, IER, RPAR, IPAR)\n\nstatic F77_INT\nddaspk_psol (const F77_INT&, const double&, const double *,\n             const double *, const double *, const double&,\n             const double *, double *, F77_INT *, double *,\n             const double&, F77_INT&, double *, F77_INT *)\n{\n  (*current_liboctave_error_handler) (\"daspk: PSOL is not implemented\");\n\n  return 0;\n}\n\nstatic F77_INT\nddaspk_j (const double& time, const double *state, const double *deriv,\n          double *pd, const double& cj, double *, F77_INT *)\n{\n  // FIXME: would be nice to avoid copying the data.\n\n  ColumnVector tmp_state (nn);\n  ColumnVector tmp_deriv (nn);\n\n  for (F77_INT i = 0; i < nn; i++)\n    {\n      tmp_deriv.elem (i) = deriv[i];\n      tmp_state.elem (i) = state[i];\n    }\n\n  Matrix tmp_pd = user_jac (tmp_state, tmp_deriv, time, cj);\n\n  for (F77_INT j = 0; j < nn; j++)\n    for (F77_INT i = 0; i < nn; i++)\n      pd[nn * j + i] = tmp_pd.elem (i, j);\n\n  return 0;\n}\n\nColumnVector\nDASPK::do_integrate (double tout)\n{\n  // FIXME: should handle all this option stuff just once for each new problem.\n\n  ColumnVector retval;\n\n  if (! m_initialized || m_restart || DAEFunc::m_reset\n      || DASPK_options::m_reset)\n    {\n      m_integration_error = false;\n\n      m_initialized = true;\n\n      m_info.resize (dim_vector (20, 1));\n\n      for (F77_INT i = 0; i < 20; i++)\n        m_info(i) = 0;\n\n      F77_INT n = octave::to_f77_int (size ());\n\n      nn = n;\n\n      m_info(0) = 0;\n\n      if (m_stop_time_set)\n        {\n          m_rwork(0) = m_stop_time;\n          m_info(3) = 1;\n        }\n      else\n        m_info(3) = 0;\n\n      // DAEFunc\n\n      user_fcn = DAEFunc::function ();\n      user_jac = DAEFunc::jacobian_function ();\n\n      if (user_fcn)\n        {\n          octave_idx_type ires = 0;\n\n          ColumnVector res = (*user_fcn) (m_x, m_xdot, m_t, ires);\n\n          if (res.numel () != m_x.numel ())\n            {\n              // FIXME: Should this be a warning?\n              (*current_liboctave_error_handler)\n                (\"daspk: inconsistent sizes for state and residual vectors\");\n\n              m_integration_error = true;\n              return retval;\n            }\n        }\n      else\n        {\n          // FIXME: Should this be a warning?\n          (*current_liboctave_error_handler)\n            (\"daspk: no user supplied RHS subroutine!\");\n\n          m_integration_error = true;\n          return retval;\n        }\n\n      m_info(4) = (user_jac ? 1 : 0);\n\n      DAEFunc::m_reset = false;\n\n      octave_idx_type eiq = enforce_inequality_constraints ();\n      octave_idx_type ccic = compute_consistent_initial_condition ();\n      octave_idx_type eavfet = exclude_algebraic_variables_from_error_test ();\n\n      m_liw = 40 + n;\n      if (eiq == 1 || eiq == 3)\n        m_liw += n;\n      if (ccic == 1 || eavfet == 1)\n        m_liw += n;\n\n      m_lrw = 50 + 9*n + n*n;\n      if (eavfet == 1)\n        m_lrw += n;\n\n      m_iwork.resize (dim_vector (m_liw, 1));\n      m_rwork.resize (dim_vector (m_lrw, 1));\n\n      // DASPK_options\n\n      m_abs_tol = absolute_tolerance ();\n      m_rel_tol = relative_tolerance ();\n\n      F77_INT abs_tol_len = octave::to_f77_int (m_abs_tol.numel ());\n      F77_INT rel_tol_len = octave::to_f77_int (m_rel_tol.numel ());\n\n      if (abs_tol_len == 1 && rel_tol_len == 1)\n        {\n          m_info(1) = 0;\n        }\n      else if (abs_tol_len == n && rel_tol_len == n)\n        {\n          m_info(1) = 1;\n        }\n      else\n        {\n          // FIXME: Should this be a warning?\n          (*current_liboctave_error_handler)\n            (\"daspk: inconsistent sizes for tolerance arrays\");\n\n          m_integration_error = true;\n          return retval;\n        }\n\n      double hmax = maximum_step_size ();\n      if (hmax >= 0.0)\n        {\n          m_rwork(1) = hmax;\n          m_info(6) = 1;\n        }\n      else\n        m_info(6) = 0;\n\n      double h0 = initial_step_size ();\n      if (h0 >= 0.0)\n        {\n          m_rwork(2) = h0;\n          m_info(7) = 1;\n        }\n      else\n        m_info(7) = 0;\n\n      octave_idx_type maxord = maximum_order ();\n      if (maxord >= 0)\n        {\n          if (maxord > 0 && maxord < 6)\n            {\n              m_info(8) = 1;\n              m_iwork(2) = octave::to_f77_int (maxord);\n            }\n          else\n            {\n              // FIXME: Should this be a warning?\n              (*current_liboctave_error_handler)\n                (\"daspk: invalid value for maximum order\");\n              m_integration_error = true;\n              return retval;\n            }\n        }\n\n      switch (eiq)\n        {\n        case 1:\n        case 3:\n          {\n            Array<octave_idx_type> ict = inequality_constraint_types ();\n\n            F77_INT ict_nel = octave::to_f77_int (ict.numel ());\n\n            if (ict_nel == n)\n              {\n                for (F77_INT i = 0; i < n; i++)\n                  {\n                    F77_INT val = octave::to_f77_int (ict(i));\n                    if (val < -2 || val > 2)\n                      {\n                        // FIXME: Should this be a warning?\n                        (*current_liboctave_error_handler)\n                          (\"daspk: invalid value for inequality constraint type\");\n                        m_integration_error = true;\n                        return retval;\n                      }\n                    m_iwork(40+i) = val;\n                  }\n              }\n            else\n              {\n                // FIXME: Should this be a warning?\n                (*current_liboctave_error_handler)\n                  (\"daspk: inequality constraint types size mismatch\");\n                m_integration_error = true;\n                return retval;\n              }\n          }\n          OCTAVE_FALLTHROUGH;\n\n        case 0:\n        case 2:\n          m_info(9) = octave::to_f77_int (eiq);\n          break;\n\n        default:\n          // FIXME: Should this be a warning?\n          (*current_liboctave_error_handler)\n            (\"daspk: invalid value for enforce inequality constraints option\");\n          m_integration_error = true;\n          return retval;\n        }\n\n      if (ccic)\n        {\n          if (ccic == 1)\n            {\n              // FIXME: this code is duplicated below.\n\n              Array<octave_idx_type> av = algebraic_variables ();\n\n              F77_INT av_nel = octave::to_f77_int (av.numel ());\n\n              if (av_nel == n)\n                {\n                  F77_INT lid;\n                  if (eiq == 0 || eiq == 2)\n                    lid = 40;\n                  else if (eiq == 1 || eiq == 3)\n                    lid = 40 + n;\n                  else\n                    (*current_liboctave_error_handler)\n                      (\"daspk: invalid value for eiq: \"\n                       \"%\" OCTAVE_IDX_TYPE_FORMAT, eiq);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    m_iwork(lid+i) = (av(i) ? -1 : 1);\n                }\n              else\n                {\n                  // FIXME: Should this be a warning?\n                  (*current_liboctave_error_handler)\n                    (\"daspk: algebraic variables size mismatch\");\n                  m_integration_error = true;\n                  return retval;\n                }\n            }\n          else if (ccic != 2)\n            {\n              // FIXME: Should this be a warning?\n              (*current_liboctave_error_handler)\n                (\"daspk: invalid value for compute consistent initial condition option\");\n              m_integration_error = true;\n              return retval;\n            }\n\n          m_info(10) = octave::to_f77_int (ccic);\n        }\n\n      if (eavfet)\n        {\n          m_info(15) = 1;\n\n          // FIXME: this code is duplicated above.\n\n          Array<octave_idx_type> av = algebraic_variables ();\n\n          F77_INT av_nel = octave::to_f77_int (av.numel ());\n\n          if (av_nel == n)\n            {\n              F77_INT lid;\n              if (eiq == 0 || eiq == 2)\n                lid = 40;\n              else if (eiq == 1 || eiq == 3)\n                lid = 40 + n;\n              else\n                (*current_liboctave_error_handler)\n                  (\"daspk: invalid value for eiq: %\" OCTAVE_IDX_TYPE_FORMAT,\n                   eiq);\n\n              for (F77_INT i = 0; i < n; i++)\n                m_iwork(lid+i) = (av(i) ? -1 : 1);\n            }\n        }\n\n      if (use_initial_condition_heuristics ())\n        {\n          Array<double> ich = initial_condition_heuristics ();\n\n          if (ich.numel () == 6)\n            {\n              m_iwork(31) = octave::to_f77_int (octave::math::nint_big (ich(0)));\n              m_iwork(32) = octave::to_f77_int (octave::math::nint_big (ich(1)));\n              m_iwork(33) = octave::to_f77_int (octave::math::nint_big (ich(2)));\n              m_iwork(34) = octave::to_f77_int (octave::math::nint_big (ich(3)));\n\n              m_rwork(13) = ich(4);\n              m_rwork(14) = ich(5);\n            }\n          else\n            {\n              // FIXME: Should this be a warning?\n              (*current_liboctave_error_handler)\n                (\"daspk: invalid initial condition heuristics option\");\n              m_integration_error = true;\n              return retval;\n            }\n\n          m_info(16) = 1;\n        }\n\n      octave_idx_type pici = print_initial_condition_info ();\n      switch (pici)\n        {\n        case 0:\n        case 1:\n        case 2:\n          m_info(17) = octave::to_f77_int (pici);\n          break;\n\n        default:\n          // FIXME: Should this be a warning?\n          (*current_liboctave_error_handler)\n            (\"daspk: invalid value for print initial condition info option\");\n          m_integration_error = true;\n          return retval;\n          break;\n        }\n\n      DASPK_options::m_reset = false;\n\n      m_restart = false;\n    }\n\n  double *px = m_x.rwdata ();\n  double *pxdot = m_xdot.rwdata ();\n\n  F77_INT *pinfo = m_info.rwdata ();\n\n  double *prel_tol = m_rel_tol.rwdata ();\n  double *pabs_tol = m_abs_tol.rwdata ();\n\n  double *prwork = m_rwork.rwdata ();\n  F77_INT *piwork = m_iwork.rwdata ();\n\n  double *dummy = nullptr;\n  F77_INT *idummy = nullptr;\n\n  F77_INT tmp_istate = octave::to_f77_int (m_istate);\n\n  F77_XFCN (ddaspk, DDASPK, (ddaspk_f, nn, m_t, px, pxdot, tout, pinfo,\n                             prel_tol, pabs_tol, tmp_istate, prwork, m_lrw,\n                             piwork, m_liw, dummy, idummy, ddaspk_j,\n                             ddaspk_psol));\n\n  m_istate = tmp_istate;\n\n  switch (m_istate)\n    {\n    case 1: // A step was successfully taken in intermediate-output\n            // mode.  The code has not yet reached TOUT.\n    case 2: // The integration to TSTOP was successfully completed\n            // (T=TSTOP) by stepping exactly to TSTOP.\n    case 3: // The integration to TOUT was successfully completed\n            // (T=TOUT) by stepping past TOUT.  Y(*) is obtained by\n            // interpolation.  YPRIME(*) is obtained by interpolation.\n    case 4: // The initial condition calculation, with\n            // INFO(11) > 0, was successful, and INFO(14) = 1.\n            // No integration steps were taken, and the solution\n            // is not considered to have been started.\n      retval = m_x;\n      m_t = tout;\n      break;\n\n    case -1: // A large amount of work has been expended.  (~500 steps).\n    case -2: // The error tolerances are too stringent.\n    case -3: // The local error test cannot be satisfied because you\n             // specified a zero component in ATOL and the\n             // corresponding computed solution component is zero.\n             // Thus, a pure relative error test is impossible for\n             // this component.\n    case -6: // DDASPK had repeated error test failures on the last\n             // attempted step.\n    case -7: // The corrector could not converge.\n    case -8: // The matrix of partial derivatives is singular.\n    case -9: // The corrector could not converge.  There were repeated\n             // error test failures in this step.\n    case -10: // The corrector could not converge because IRES was\n              // equal to minus one.\n    case -11: // IRES equal to -2 was encountered and control is being\n              // returned to the calling program.\n    case -12: // DDASPK failed to compute the initial YPRIME.\n    case -13: // Unrecoverable error encountered inside user's\n              // PSOL routine, and control is being returned to\n              // the calling program.\n    case -14: // The Krylov linear system solver could not\n              // achieve convergence.\n    case -33: // The code has encountered trouble from which it cannot\n              // recover.  A message is printed explaining the trouble\n              // and control is returned to the calling program.  For\n              // example, this occurs when invalid input is detected.\n      m_integration_error = true;\n      break;\n\n    default:\n      m_integration_error = true;\n      (*current_liboctave_error_handler)\n        (\"unrecognized value of m_istate (= %\" OCTAVE_IDX_TYPE_FORMAT \") \"\n         \"returned from ddaspk\", m_istate);\n      break;\n    }\n\n  return retval;\n}\n\nMatrix\nDASPK::do_integrate (const ColumnVector& tout)\n{\n  Matrix dummy;\n  return integrate (tout, dummy);\n}\n\nMatrix\nDASPK::integrate (const ColumnVector& tout, Matrix& xdot_out)\n{\n  Matrix retval;\n\n  octave_idx_type n_out = tout.numel ();\n  F77_INT n = octave::to_f77_int (size ());\n\n  if (n_out > 0 && n > 0)\n    {\n      retval.resize (n_out, n);\n      xdot_out.resize (n_out, n);\n\n      for (F77_INT i = 0; i < n; i++)\n        {\n          retval.elem (0, i) = m_x.elem (i);\n          xdot_out.elem (0, i) = m_xdot.elem (i);\n        }\n\n      for (octave_idx_type j = 1; j < n_out; j++)\n        {\n          ColumnVector x_next = do_integrate (tout.elem (j));\n\n          if (m_integration_error)\n            return retval;\n\n          for (F77_INT i = 0; i < n; i++)\n            {\n              retval.elem (j, i) = x_next.elem (i);\n              xdot_out.elem (j, i) = m_xdot.elem (i);\n            }\n        }\n    }\n\n  return retval;\n}\n\nMatrix\nDASPK::do_integrate (const ColumnVector& tout, const ColumnVector& tcrit)\n{\n  Matrix dummy;\n  return integrate (tout, dummy, tcrit);\n}\n\nMatrix\nDASPK::integrate (const ColumnVector& tout, Matrix& xdot_out,\n                  const ColumnVector& tcrit)\n{\n  Matrix retval;\n\n  octave_idx_type n_out = tout.numel ();\n  F77_INT n = octave::to_f77_int (size ());\n\n  if (n_out > 0 && n > 0)\n    {\n      retval.resize (n_out, n);\n      xdot_out.resize (n_out, n);\n\n      for (F77_INT i = 0; i < n; i++)\n        {\n          retval.elem (0, i) = m_x.elem (i);\n          xdot_out.elem (0, i) = m_xdot.elem (i);\n        }\n\n      octave_idx_type n_crit = tcrit.numel ();\n\n      if (n_crit > 0)\n        {\n          octave_idx_type i_crit = 0;\n          octave_idx_type i_out = 1;\n          double next_crit = tcrit.elem (0);\n          double next_out;\n          while (i_out < n_out)\n            {\n              bool do_restart = false;\n\n              next_out = tout.elem (i_out);\n              if (i_crit < n_crit)\n                next_crit = tcrit.elem (i_crit);\n\n              bool save_output;\n              double t_out;\n\n              if (next_crit == next_out)\n                {\n                  set_stop_time (next_crit);\n                  t_out = next_out;\n                  save_output = true;\n                  i_out++;\n                  i_crit++;\n                  do_restart = true;\n                }\n              else if (next_crit < next_out)\n                {\n                  if (i_crit < n_crit)\n                    {\n                      set_stop_time (next_crit);\n                      t_out = next_crit;\n                      save_output = false;\n                      i_crit++;\n                      do_restart = true;\n                    }\n                  else\n                    {\n                      clear_stop_time ();\n                      t_out = next_out;\n                      save_output = true;\n                      i_out++;\n                    }\n                }\n              else\n                {\n                  set_stop_time (next_crit);\n                  t_out = next_out;\n                  save_output = true;\n                  i_out++;\n                }\n\n              ColumnVector x_next = do_integrate (t_out);\n\n              if (m_integration_error)\n                return retval;\n\n              if (save_output)\n                {\n                  for (F77_INT i = 0; i < n; i++)\n                    {\n                      retval.elem (i_out-1, i) = x_next.elem (i);\n                      xdot_out.elem (i_out-1, i) = m_xdot.elem (i);\n                    }\n                }\n\n              if (do_restart)\n                force_restart ();\n            }\n        }\n      else\n        {\n          retval = integrate (tout, xdot_out);\n\n          if (m_integration_error)\n            return retval;\n        }\n    }\n\n  return retval;\n}\n\nstd::string\nDASPK::error_message () const\n{\n  std::string retval;\n\n  std::ostringstream buf;\n  buf << m_t;\n  std::string t_curr = buf.str ();\n\n  switch (m_istate)\n    {\n    case 1:\n      retval = \"a step was successfully taken in intermediate-output mode.\";\n      break;\n\n    case 2:\n      retval = \"integration completed by stepping exactly to TOUT\";\n      break;\n\n    case 3:\n      retval = \"integration to tout completed by stepping past TOUT\";\n      break;\n\n    case 4:\n      retval = \"initial condition calculation completed successfully\";\n      break;\n\n    case -1:\n      retval = \"a large amount of work has been expended (t =\" + t_curr + ')';\n      break;\n\n    case -2:\n      retval = \"the error tolerances are too stringent\";\n      break;\n\n    case -3:\n      retval = \"error weight became zero during problem. (t = \" + t_curr +\n               \"; solution component i vanished, and atol or atol(i) == 0)\";\n      break;\n\n    case -6:\n      retval = \"repeated error test failures on the last attempted step (t = \"\n               + t_curr + ')';\n      break;\n\n    case -7:\n      retval = \"the corrector could not converge (t = \" + t_curr + ')';\n      break;\n\n    case -8:\n      retval = \"the matrix of partial derivatives is singular (t = \" + t_curr +\n               ')';\n      break;\n\n    case -9:\n      retval = \"the corrector could not converge (t = \" + t_curr +\n               \"; repeated test failures)\";\n      break;\n\n    case -10:\n      retval = \"corrector could not converge because IRES was -1 (t = \"\n               + t_curr + ')';\n      break;\n\n    case -11:\n      retval = \"return requested in user-supplied function (t = \" + t_curr +\n               ')';\n      break;\n\n    case -12:\n      retval = \"failed to compute consistent initial conditions\";\n      break;\n\n    case -13:\n      retval = \"unrecoverable error encountered inside user's PSOL function (t = \"\n               + t_curr + ')';\n      break;\n\n    case -14:\n      retval = \"the Krylov linear system solver failed to converge (t = \"\n               + t_curr + ')';\n      break;\n\n    case -33:\n      retval = \"unrecoverable error (see printed message)\";\n      break;\n\n    default:\n      retval = \"unknown error state\";\n      break;\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/numeric/DASPK.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_DASPK_h)\n#define octave_DASPK_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"Array-oct.h\"\n#include \"DASPK-opts.h\"\n\n#include \"mx-fwd.h\"\n\nclass OCTAVE_API DASPK : public DAE, public DASPK_options\n{\npublic:\n\n  DASPK ()\n    : DAE (), DASPK_options (), m_initialized (false), m_liw (0), m_lrw (0),\n      m_info (), m_iwork (), m_rwork (), m_abs_tol (), m_rel_tol () { }\n\n  DASPK (const ColumnVector& s, double tm, DAEFunc& f)\n    : DAE (s, tm, f), DASPK_options (), m_initialized (false), m_liw (0),\n      m_lrw (0), m_info (), m_iwork (), m_rwork (), m_abs_tol (), m_rel_tol ()\n  { }\n\n  DASPK (const ColumnVector& s, const ColumnVector& deriv,\n         double tm, DAEFunc& f)\n    : DAE (s, deriv, tm, f), DASPK_options (), m_initialized (false),\n      m_liw (0), m_lrw (0), m_info (), m_iwork (), m_rwork (), m_abs_tol (),\n      m_rel_tol () { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (DASPK)\n\n  ColumnVector do_integrate (double t);\n\n  Matrix do_integrate (const ColumnVector& tout);\n\n  Matrix do_integrate (const ColumnVector& tout, const ColumnVector& tcrit);\n\n  Matrix integrate (const ColumnVector& tout, Matrix& xdot_out);\n\n  Matrix integrate (const ColumnVector& tout, Matrix& xdot_out,\n                    const ColumnVector& tcrit);\n\n  std::string error_message () const;\n\nprivate:\n\n  bool m_initialized;\n\n  octave_f77_int_type m_liw;\n  octave_f77_int_type m_lrw;\n\n  Array<octave_f77_int_type> m_info;\n  Array<octave_f77_int_type> m_iwork;\n\n  Array<double> m_rwork;\n\n  Array<double> m_abs_tol;\n  Array<double> m_rel_tol;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/DASRT-opts.in",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nCLASS = \"DASRT\"\n\nINCLUDE = \"DAERT.h\"\n\nOPTION\n  NAME = \"absolute tolerance\"\n  DOC_ITEM\nAbsolute tolerance.  May be either vector or scalar.  If a vector, it\nmust match the dimension of the state vector, and the relative\ntolerance must also be a vector of the same length.\n\n  END_DOC_ITEM\n  TYPE = \"Array<double>\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (1, 1));\n    $OPTVAR(0) = ::sqrt (std::numeric_limits<double>::epsilon ());\n  END_INIT_BODY\n  SET_CODE\n    void set_$OPT (double val)\n      {\n        $OPTVAR.resize (dim_vector (1, 1));\n        $OPTVAR(0) = (val > 0.0) ? val : ::sqrt (std::numeric_limits<double>::epsilon ());\n        m_reset = true;\n      }\n\n    void set_$OPT (const $TYPE& val)\n      { $OPTVAR = val; m_reset = true; }\n  END_SET_CODE\nEND_OPTION\n\nOPTION\n  NAME = \"relative tolerance\"\n  DOC_ITEM\nRelative tolerance.  May be either vector or scalar.  If a vector, it\nmust match the dimension of the state vector, and the absolute\ntolerance must also be a vector of the same length.\n\nThe local error test applied at each integration step is\n\n@example\n@group\n  abs (local error in x(i)) <= ...\n      rtol(i) * abs (Y(i)) + atol(i)\n@end group\n@end example\n\n  END_DOC_ITEM\n  TYPE = \"Array<double>\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (1, 1));\n    $OPTVAR(0) = ::sqrt (std::numeric_limits<double>::epsilon ());\n  END_INIT_BODY\n  SET_CODE\n    void set_$OPT (double val)\n      {\n        $OPTVAR.resize (dim_vector (1, 1));\n        $OPTVAR(0) = (val > 0.0) ? val : ::sqrt (std::numeric_limits<double>::epsilon ());\n        m_reset = true;\n      }\n\n    void set_$OPT (const $TYPE& val)\n      { $OPTVAR = val; m_reset = true; }\n  END_SET_CODE\nEND_OPTION\n\nOPTION\n  NAME = \"initial step size\"\n  DOC_ITEM\nDifferential-algebraic problems may occasionally suffer from severe\nscaling difficulties on the first step.  If you know a great deal\nabout the scaling of your problem, you can help to alleviate this\nproblem by specifying an initial stepsize.\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"-1.0\"\n  SET_EXPR = \"(val >= 0.0) ? val : -1.0\"\nEND_OPTION\n\nOPTION\n  NAME = \"maximum order\"\n  DOC_ITEM\nRestrict the maximum order of the solution method.  This option must\nbe between 1 and 5, inclusive.\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"-1\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"maximum step size\"\n  DOC_ITEM\nSetting the maximum stepsize will avoid passing over very large\nregions.\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"-1.0\"\n  SET_EXPR = \"(val >= 0.0) ? val : -1.0\"\nEND_OPTION\n\nOPTION\n  NAME = \"step limit\"\n  DOC_ITEM\nMaximum number of integration steps to attempt on a single call to the\nunderlying Fortran code.\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"-1\"\n  SET_EXPR = \"(val >= 0) ? val : -1\"\nEND_OPTION\n"
  },
  {
    "path": "liboctave/numeric/DASRT.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n\n#include \"DASRT.h\"\n#include \"f77-fcn.h\"\n#include \"oct-error.h\"\n\ntypedef F77_INT (*dasrt_fcn_ptr) (const double&, const double *, const double *,\n                                  double *, F77_INT&, double *, F77_INT *);\n\ntypedef F77_INT (*dasrt_jac_ptr) (const double&, const double *, const double *,\n                                  double *, const double&, double *, F77_INT *);\n\ntypedef F77_INT (*dasrt_constr_ptr) (const F77_INT&, const double&,\n                                     const double *, const F77_INT&,\n                                     double *, double *, F77_INT *);\n\nextern \"C\"\n{\n  F77_RET_T\n  F77_FUNC (ddasrt, DDASRT) (dasrt_fcn_ptr, const F77_INT&, F77_DBLE&,\n                             F77_DBLE *, F77_DBLE *, const F77_DBLE&, F77_INT *,\n                             const F77_DBLE *, const F77_DBLE *, F77_INT&,\n                             F77_DBLE *, const F77_INT&, F77_INT *,\n                             const F77_INT&, F77_DBLE *, F77_INT *,\n                             dasrt_jac_ptr, dasrt_constr_ptr, const F77_INT&,\n                             F77_INT *);\n}\n\nstatic DAEFunc::DAERHSFunc user_fsub;\nstatic DAEFunc::DAEJacFunc user_jsub;\nstatic DAERTFunc::DAERTConstrFunc user_csub;\n\nstatic F77_INT nn;\n\nstatic F77_INT\nddasrt_f (const double& t, const double *state, const double *deriv,\n          double *delta, F77_INT& ires, double *, F77_INT *)\n{\n  ColumnVector tmp_state (nn);\n  ColumnVector tmp_deriv (nn);\n\n  for (F77_INT i = 0; i < nn; i++)\n    {\n      tmp_state(i) = state[i];\n      tmp_deriv(i) = deriv[i];\n    }\n\n  octave_idx_type tmp_ires = ires;\n\n  ColumnVector tmp_fval = (*user_fsub) (tmp_state, tmp_deriv, t, tmp_ires);\n\n  ires = octave::to_f77_int (tmp_ires);\n\n  if (tmp_fval.isempty ())\n    ires = -2;\n  else\n    {\n      for (F77_INT i = 0; i < nn; i++)\n        delta[i] = tmp_fval(i);\n    }\n\n  return 0;\n}\n\nF77_INT\nddasrt_j (const double& time, const double *state, const double *deriv,\n          double *pd, const double& cj, double *, F77_INT *)\n{\n  // FIXME: would be nice to avoid copying the data.\n\n  ColumnVector tmp_state (nn);\n  ColumnVector tmp_deriv (nn);\n\n  for (F77_INT i = 0; i < nn; i++)\n    {\n      tmp_deriv.elem (i) = deriv[i];\n      tmp_state.elem (i) = state[i];\n    }\n\n  Matrix tmp_pd = (*user_jsub) (tmp_state, tmp_deriv, time, cj);\n\n  for (F77_INT j = 0; j < nn; j++)\n    for (F77_INT i = 0; i < nn; i++)\n      pd[nn * j + i] = tmp_pd.elem (i, j);\n\n  return 0;\n}\n\nstatic F77_INT\nddasrt_g (const F77_INT& neq, const double& t, const double *state,\n          const F77_INT& m_ng, double *gout, double *, F77_INT *)\n{\n  F77_INT n = neq;\n\n  ColumnVector tmp_state (n);\n  for (F77_INT i = 0; i < n; i++)\n    tmp_state(i) = state[i];\n\n  ColumnVector tmp_fval = (*user_csub) (tmp_state, t);\n\n  for (F77_INT i = 0; i < m_ng; i++)\n    gout[i] = tmp_fval(i);\n\n  return 0;\n}\n\nvoid\nDASRT::integrate (double tout)\n{\n  // I suppose this is the safe thing to do.  If this is the first\n  // call, or if anything about the problem has changed, we should\n  // start completely fresh.\n\n  if (! m_initialized || m_restart\n      || DAEFunc::m_reset || DAERTFunc::m_reset || DASRT_options::m_reset)\n    {\n      m_integration_error = false;\n\n      m_initialized = true;\n\n      m_info.resize (dim_vector (15, 1));\n\n      for (F77_INT i = 0; i < 15; i++)\n        m_info(i) = 0;\n\n      F77_INT n = octave::to_f77_int (size ());\n\n      nn = n;\n\n      // DAERTFunc\n\n      user_csub = DAERTFunc::constraint_function ();\n\n      if (user_csub)\n        {\n          ColumnVector tmp = (*user_csub) (m_x, m_t);\n          m_ng = octave::to_f77_int (tmp.numel ());\n        }\n      else\n        m_ng = 0;\n\n      F77_INT maxord = octave::to_f77_int (maximum_order ());\n      if (maxord >= 0)\n        {\n          if (maxord > 0 && maxord < 6)\n            {\n              m_info(8) = 1;\n              m_iwork(2) = maxord;\n            }\n          else\n            {\n              (*current_liboctave_error_handler)\n                (\"dassl: invalid value for maximum order\");\n              m_integration_error = true;\n              return;\n            }\n        }\n\n      m_liw = 21 + n;\n      m_lrw = 50 + 9*n + n*n + 3*m_ng;\n\n      m_iwork.resize (dim_vector (m_liw, 1));\n      m_rwork.resize (dim_vector (m_lrw, 1));\n\n      m_info(0) = 0;\n\n      if (m_stop_time_set)\n        {\n          m_info(3) = 1;\n          m_rwork(0) = m_stop_time;\n        }\n      else\n        m_info(3) = 0;\n\n      m_restart = false;\n\n      // DAEFunc\n\n      user_fsub = DAEFunc::function ();\n      user_jsub = DAEFunc::jacobian_function ();\n\n      if (user_fsub)\n        {\n          octave_idx_type ires = 0;\n\n          ColumnVector fval = (*user_fsub) (m_x, m_xdot, m_t, ires);\n\n          if (fval.numel () != m_x.numel ())\n            {\n              (*current_liboctave_error_handler)\n                (\"dasrt: inconsistent sizes for state and residual vectors\");\n\n              m_integration_error = true;\n              return;\n            }\n        }\n      else\n        {\n          (*current_liboctave_error_handler)\n            (\"dasrt: no user supplied RHS subroutine!\");\n\n          m_integration_error = true;\n          return;\n        }\n\n      m_info(4) = (user_jsub ? 1 : 0);\n\n      DAEFunc::m_reset = false;\n\n      m_jroot.resize (dim_vector (m_ng, 1), 1);\n\n      DAERTFunc::m_reset = false;\n\n      // DASRT_options\n\n      double mss = maximum_step_size ();\n      if (mss >= 0.0)\n        {\n          m_rwork(1) = mss;\n          m_info(6) = 1;\n        }\n      else\n        m_info(6) = 0;\n\n      double iss = initial_step_size ();\n      if (iss >= 0.0)\n        {\n          m_rwork(2) = iss;\n          m_info(7) = 1;\n        }\n      else\n        m_info(7) = 0;\n\n      F77_INT sl = octave::to_f77_int (step_limit ());\n      if (sl >= 0)\n        {\n          m_info(11) = 1;\n          m_iwork(20) = sl;\n        }\n      else\n        m_info(11) = 0;\n\n      m_abs_tol = absolute_tolerance ();\n      m_rel_tol = relative_tolerance ();\n\n      F77_INT abs_tol_len = octave::to_f77_int (m_abs_tol.numel ());\n      F77_INT rel_tol_len = octave::to_f77_int (m_rel_tol.numel ());\n\n      if (abs_tol_len == 1 && rel_tol_len == 1)\n        {\n          m_info.elem (1) = 0;\n        }\n      else if (abs_tol_len == n && rel_tol_len == n)\n        {\n          m_info.elem (1) = 1;\n        }\n      else\n        {\n          (*current_liboctave_error_handler)\n            (\"dasrt: inconsistent sizes for tolerance arrays\");\n\n          m_integration_error = true;\n          return;\n        }\n\n      DASRT_options::m_reset = false;\n    }\n\n  double *px = m_x.rwdata ();\n  double *pxdot = m_xdot.rwdata ();\n\n  F77_INT *pinfo = m_info.rwdata ();\n\n  double *prel_tol = m_rel_tol.rwdata ();\n  double *pabs_tol = m_abs_tol.rwdata ();\n\n  double *prwork = m_rwork.rwdata ();\n  F77_INT *piwork = m_iwork.rwdata ();\n\n  F77_INT *pjroot = m_jroot.rwdata ();\n\n  double *dummy = nullptr;\n  F77_INT *idummy = nullptr;\n\n  F77_INT tmp_istate = octave::to_f77_int (m_istate);\n\n  F77_XFCN (ddasrt, DDASRT, (ddasrt_f, nn, m_t, px, pxdot, tout, pinfo,\n                             prel_tol, pabs_tol, tmp_istate, prwork, m_lrw,\n                             piwork, m_liw, dummy, idummy, ddasrt_j,\n                             ddasrt_g, m_ng, pjroot));\n\n  m_istate = tmp_istate;\n\n  switch (m_istate)\n    {\n    case 1: // A step was successfully taken in intermediate-output\n            // mode.  The code has not yet reached TOUT.\n    case 2: // The integration to TOUT was successfully completed\n            // (T=TOUT) by stepping exactly to TOUT.\n    case 3: // The integration to TOUT was successfully completed\n            // (T=TOUT) by stepping past TOUT.  Y(*) is obtained by\n            // interpolation.  YPRIME(*) is obtained by interpolation.\n      m_t = tout;\n      break;\n\n    case 4: //  The integration was successfully completed\n            // by finding one or more roots of G at T.\n      break;\n\n    case -1: // A large amount of work has been expended.\n    case -2: // The error tolerances are too stringent.\n    case -3: // The local error test cannot be satisfied because you\n             // specified a zero component in ATOL and the\n             // corresponding computed solution component is zero.\n             // Thus, a pure relative error test is impossible for\n             // this component.\n    case -6: // DDASRT had repeated error test failures on the last\n             // attempted step.\n    case -7: // The corrector could not converge.\n    case -8: // The matrix of partial derivatives is singular.\n    case -9: // The corrector could not converge.  There were repeated\n             // error test failures in this step.\n    case -10: // The corrector could not converge because IRES was\n              // equal to minus one.\n    case -11: // IRES equal to -2 was encountered and control is being\n              // returned to the calling program.\n    case -12: // DASSL failed to compute the initial YPRIME.\n    case -33: // The code has encountered trouble from which it cannot\n              // recover.  A message is printed explaining the trouble\n              // and control is returned to the calling program.  For\n              // example, this occurs when invalid input is detected.\n      m_integration_error = true;\n      break;\n\n    default:\n      m_integration_error = true;\n      (*current_liboctave_error_handler)\n        (\"unrecognized value of istate (= %\" OCTAVE_IDX_TYPE_FORMAT \") \"\n         \"returned from ddasrt\", m_istate);\n      break;\n    }\n}\n\nDASRT_result\nDASRT::integrate (const ColumnVector& tout)\n{\n  DASRT_result retval;\n\n  Matrix x_out;\n  Matrix xdot_out;\n  ColumnVector t_out = tout;\n\n  octave_idx_type n_out = tout.numel ();\n  F77_INT n = octave::to_f77_int (size ());\n\n  if (n_out > 0 && n > 0)\n    {\n      x_out.resize (n_out, n);\n      xdot_out.resize (n_out, n);\n\n      for (F77_INT i = 0; i < n; i++)\n        {\n          x_out(0, i) = m_x(i);\n          xdot_out(0, i) = m_xdot(i);\n        }\n\n      for (octave_idx_type j = 1; j < n_out; j++)\n        {\n          integrate (tout(j));\n\n          if (m_integration_error)\n            {\n              retval = DASRT_result (x_out, xdot_out, t_out);\n              return retval;\n            }\n\n          if (m_istate == 4)\n            t_out(j) = m_t;\n          else\n            t_out(j) = tout(j);\n\n          for (F77_INT i = 0; i < n; i++)\n            {\n              x_out(j, i) = m_x(i);\n              xdot_out(j, i) = m_xdot(i);\n            }\n\n          if (m_istate == 4)\n            {\n              x_out.resize (j+1, n);\n              xdot_out.resize (j+1, n);\n              t_out.resize (j+1);\n              break;\n            }\n        }\n    }\n\n  retval = DASRT_result (x_out, xdot_out, t_out);\n\n  return retval;\n}\n\nDASRT_result\nDASRT::integrate (const ColumnVector& tout, const ColumnVector& tcrit)\n{\n  DASRT_result retval;\n\n  Matrix x_out;\n  Matrix xdot_out;\n  ColumnVector t_outs = tout;\n\n  octave_idx_type n_out = tout.numel ();\n  F77_INT n = octave::to_f77_int (size ());\n\n  if (n_out > 0 && n > 0)\n    {\n      x_out.resize (n_out, n);\n      xdot_out.resize (n_out, n);\n\n      octave_idx_type n_crit = tcrit.numel ();\n\n      if (n_crit > 0)\n        {\n          octave_idx_type i_crit = 0;\n          octave_idx_type i_out = 1;\n          double next_crit = tcrit(0);\n          double next_out;\n          while (i_out < n_out)\n            {\n              bool do_restart = false;\n\n              next_out = tout(i_out);\n              if (i_crit < n_crit)\n                next_crit = tcrit(i_crit);\n\n              bool save_output = false;\n              double t_out;\n\n              if (next_crit == next_out)\n                {\n                  set_stop_time (next_crit);\n                  t_out = next_out;\n                  save_output = true;\n                  i_out++;\n                  i_crit++;\n                  do_restart = true;\n                }\n              else if (next_crit < next_out)\n                {\n                  if (i_crit < n_crit)\n                    {\n                      set_stop_time (next_crit);\n                      t_out = next_crit;\n                      save_output = false;\n                      i_crit++;\n                      do_restart = true;\n                    }\n                  else\n                    {\n                      clear_stop_time ();\n                      t_out = next_out;\n                      save_output = true;\n                      i_out++;\n                    }\n                }\n              else\n                {\n                  set_stop_time (next_crit);\n                  t_out = next_out;\n                  save_output = true;\n                  i_out++;\n                }\n\n              integrate (t_out);\n\n              if (m_integration_error)\n                {\n                  retval = DASRT_result (x_out, xdot_out, t_outs);\n                  return retval;\n                }\n\n              if (m_istate == 4)\n                t_out = m_t;\n\n              if (save_output)\n                {\n                  for (F77_INT i = 0; i < n; i++)\n                    {\n                      x_out(i_out-1, i) = m_x(i);\n                      xdot_out(i_out-1, i) = m_xdot(i);\n                    }\n\n                  t_outs(i_out-1) = t_out;\n\n                  if (m_istate == 4)\n                    {\n                      x_out.resize (i_out, n);\n                      xdot_out.resize (i_out, n);\n                      t_outs.resize (i_out);\n                      i_out = n_out;\n                    }\n                }\n\n              if (do_restart)\n                force_restart ();\n            }\n\n          retval = DASRT_result (x_out, xdot_out, t_outs);\n        }\n      else\n        {\n          retval = integrate (tout);\n\n          if (m_integration_error)\n            return retval;\n        }\n    }\n\n  return retval;\n}\n\nstd::string\nDASRT::error_message () const\n{\n  std::string retval;\n\n  std::ostringstream buf;\n  buf << m_t;\n  std::string t_curr = buf.str ();\n\n  switch (m_istate)\n    {\n    case 1:\n      retval = \"a step was successfully taken in intermediate-output mode.\";\n      break;\n\n    case 2:\n      retval = \"integration completed by stepping exactly to TOUT\";\n      break;\n\n    case 3:\n      retval = \"integration to tout completed by stepping past TOUT\";\n      break;\n\n    case 4:\n      retval = \"integration completed by finding one or more roots of G at T\";\n      break;\n\n    case -1:\n      retval = \"a large amount of work has been expended (t =\" + t_curr + ')';\n      break;\n\n    case -2:\n      retval = \"the error tolerances are too stringent\";\n      break;\n\n    case -3:\n      retval = \"error weight became zero during problem. (t = \" + t_curr +\n               \"; solution component i vanished, and atol or atol(i) == 0)\";\n      break;\n\n    case -6:\n      retval = \"repeated error test failures on the last attempted step (t = \"\n               + t_curr + ')';\n      break;\n\n    case -7:\n      retval = \"the corrector could not converge (t = \" + t_curr + ')';\n      break;\n\n    case -8:\n      retval = \"the matrix of partial derivatives is singular (t = \" + t_curr +\n               ')';\n      break;\n\n    case -9:\n      retval = \"the corrector could not converge (t = \" + t_curr +\n               \"; repeated test failures)\";\n      break;\n\n    case -10:\n      retval = \"corrector could not converge because IRES was -1 (t = \"\n               + t_curr + ')';\n      break;\n\n    case -11:\n      retval = \"return requested in user-supplied function (t = \" + t_curr +\n               ')';\n      break;\n\n    case -12:\n      retval = \"failed to compute consistent initial conditions\";\n      break;\n\n    case -33:\n      retval = \"unrecoverable error (see printed message)\";\n      break;\n\n    default:\n      retval = \"unknown error state\";\n      break;\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/numeric/DASRT.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_DASRT_h)\n#define octave_DASRT_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"Array-oct.h\"\n#include \"DASRT-opts.h\"\n#include \"dMatrix.h\"\n\nclass DASRT_result\n{\npublic:\n\n  DASRT_result ()\n    : m_x (), m_xdot (), m_t () { }\n\n  DASRT_result (const Matrix& x, const Matrix& xdot, const ColumnVector& t)\n    : m_x (x), m_xdot (xdot), m_t (t) { }\n\n  DASRT_result (const DASRT_result& r)\n    : m_x (r.m_x), m_xdot (r.m_xdot), m_t (r.m_t) { }\n\n  DASRT_result& operator = (const DASRT_result& r)\n  {\n    if (this != &r)\n      {\n        m_x = r.m_x;\n        m_xdot = r.m_xdot;\n        m_t = r.m_t;\n      }\n    return *this;\n  }\n\n  ~DASRT_result () = default;\n\n  Matrix state () const { return m_x; }\n  Matrix deriv () const { return m_xdot; }\n  ColumnVector times () const { return m_t; }\n\nprivate:\n\n  Matrix m_x;\n  Matrix m_xdot;\n  ColumnVector m_t;\n};\n\nclass OCTAVE_API DASRT : public DAERT, public DASRT_options\n{\npublic:\n\n  DASRT ()\n    : DAERT (), DASRT_options (), m_initialized (false),\n      m_liw (0), m_lrw (0), m_ng (0), m_info (), m_iwork (), m_jroot (),\n      m_rwork (), m_abs_tol (), m_rel_tol ()\n  { }\n\n  DASRT (const ColumnVector& s, double tm, DAERTFunc& f)\n    : DAERT (s, tm, f), DASRT_options (), m_initialized (false),\n      m_liw (0), m_lrw (0), m_ng (0), m_info (), m_iwork (), m_jroot (),\n      m_rwork (), m_abs_tol (), m_rel_tol ()\n  { }\n\n  DASRT (const ColumnVector& s, const ColumnVector& deriv,\n         double tm, DAERTFunc& f)\n    : DAERT (s, deriv, tm, f), DASRT_options (), m_initialized (false),\n      m_liw (0), m_lrw (0), m_ng (0), m_info (), m_iwork (), m_jroot (),\n      m_rwork (), m_abs_tol (), m_rel_tol ()\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (DASRT)\n\n  DASRT_result integrate (const ColumnVector& tout);\n\n  DASRT_result integrate (const ColumnVector& tout,\n                          const ColumnVector& tcrit);\n\n  std::string error_message () const;\n\nprivate:\n\n  bool m_initialized;\n\n  octave_f77_int_type m_liw;\n  octave_f77_int_type m_lrw;\n\n  octave_f77_int_type m_ng;\n\n  Array<octave_f77_int_type> m_info;\n  Array<octave_f77_int_type> m_iwork;\n  Array<octave_f77_int_type> m_jroot;\n\n  Array<double> m_rwork;\n\n  Array<double> m_abs_tol;\n  Array<double> m_rel_tol;\n\n  void integrate (double t);\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/DASSL-opts.in",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nCLASS = \"DASSL\"\n\nINCLUDE = \"DAE.h\"\n\nOPTION\n  NAME = \"absolute tolerance\"\n  DOC_ITEM\nAbsolute tolerance.  May be either vector or scalar.  If a vector, it\nmust match the dimension of the state vector, and the relative\ntolerance must also be a vector of the same length.\n\n  END_DOC_ITEM\n  TYPE = \"Array<double>\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (1, 1));\n    $OPTVAR(0) = ::sqrt (std::numeric_limits<double>::epsilon ());\n  END_INIT_BODY\n  SET_CODE\n    void set_$OPT (double val)\n      {\n        $OPTVAR.resize (dim_vector (1, 1));\n        $OPTVAR(0) = (val > 0.0) ? val : ::sqrt (std::numeric_limits<double>::epsilon ());\n        m_reset = true;\n      }\n\n    void set_$OPT (const $TYPE& val)\n      { $OPTVAR = val; m_reset = true; }\n  END_SET_CODE\nEND_OPTION\n\nOPTION\n  NAME = \"relative tolerance\"\n  DOC_ITEM\nRelative tolerance.  May be either vector or scalar.  If a vector, it\nmust match the dimension of the state vector, and the absolute\ntolerance must also be a vector of the same length.\n\nThe local error test applied at each integration step is\n\n@example\n@group\n  abs (local error in x(i))\n       <= rtol(i) * abs (Y(i)) + atol(i)\n@end group\n@end example\n\n  END_DOC_ITEM\n  TYPE = \"Array<double>\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (1, 1));\n    $OPTVAR(0) = ::sqrt (std::numeric_limits<double>::epsilon ());\n  END_INIT_BODY\n  SET_CODE\n    void set_$OPT (double val)\n      {\n        $OPTVAR.resize (dim_vector (1, 1));\n        $OPTVAR(0) = (val > 0.0) ? val : ::sqrt (std::numeric_limits<double>::epsilon ());\n        m_reset = true;\n      }\n\n    void set_$OPT (const $TYPE& val)\n      { $OPTVAR = val; m_reset = true; }\n  END_SET_CODE\nEND_OPTION\n\nOPTION\n  NAME = \"compute consistent initial condition\"\n  DOC_ITEM\nIf nonzero, @code{dassl} will attempt to compute a consistent set of initial\nconditions.  This is generally not reliable, so it is best to provide\na consistent set and leave this option set to zero.\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"0\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"enforce nonnegativity constraints\"\n  DOC_ITEM\nIf you know that the solutions to your equations will always be\nnon-negative, it may help to set this parameter to a nonzero\nvalue.  However, it is probably best to try leaving this option set to\nzero first, and only setting it to a nonzero value if that doesn't\nwork very well.\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"0\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"initial step size\"\n  DOC_ITEM\nDifferential-algebraic problems may occasionally suffer from severe\nscaling difficulties on the first step.  If you know a great deal\nabout the scaling of your problem, you can help to alleviate this\nproblem by specifying an initial stepsize.\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"-1.0\"\n  SET_EXPR = \"(val >= 0.0) ? val : -1.0\"\nEND_OPTION\n\nOPTION\n  NAME = \"maximum order\"\n  DOC_ITEM\nRestrict the maximum order of the solution method.  This option must\nbe between 1 and 5, inclusive.\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"-1\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"maximum step size\"\n  DOC_ITEM\nSetting the maximum stepsize will avoid passing over very large\nregions  (default is not specified).\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"-1.0\"\n  SET_EXPR = \"(val >= 0.0) ? val : -1.0\"\nEND_OPTION\n\nOPTION\n  NAME = \"step limit\"\n  DOC_ITEM\nMaximum number of integration steps to attempt on a single call to the\nunderlying Fortran code.\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"-1\"\n  SET_EXPR = \"(val >= 0) ? val : -1\"\nEND_OPTION\n"
  },
  {
    "path": "liboctave/numeric/DASSL.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n\n#include \"DASSL.h\"\n#include \"dMatrix.h\"\n#include \"f77-fcn.h\"\n#include \"oct-error.h\"\n\ntypedef F77_INT (*dassl_fcn_ptr) (const double&, const double *,\n                                  const double *, double *, F77_INT&,\n                                  double *, F77_INT *);\n\ntypedef F77_INT (*dassl_jac_ptr) (const double&, const double *,\n                                  const double *, double *, const double&,\n                                  double *, F77_INT *);\n\nextern \"C\"\n{\n  F77_RET_T\n  F77_FUNC (ddassl, DDASSL) (dassl_fcn_ptr, const F77_INT&, F77_DBLE&,\n                             F77_DBLE *, F77_DBLE *, F77_DBLE&, const F77_INT *,\n                             const F77_DBLE *, const F77_DBLE *, F77_INT&,\n                             F77_DBLE *, const F77_INT&, F77_INT *,\n                             const F77_INT&, const F77_DBLE *, const F77_INT *,\n                             dassl_jac_ptr);\n}\n\nstatic DAEFunc::DAERHSFunc user_fcn;\nstatic DAEFunc::DAEJacFunc user_jac;\n\nstatic F77_INT nn;\n\nstatic F77_INT\nddassl_f (const double& time, const double *state, const double *deriv,\n          double *delta, F77_INT& ires, double *, F77_INT *)\n{\n  // FIXME: would be nice to avoid copying the data.\n\n  ColumnVector tmp_deriv (nn);\n  ColumnVector tmp_state (nn);\n  ColumnVector tmp_delta (nn);\n\n  for (F77_INT i = 0; i < nn; i++)\n    {\n      tmp_deriv.elem (i) = deriv[i];\n      tmp_state.elem (i) = state[i];\n    }\n\n  octave_idx_type tmp_ires = ires;\n\n  tmp_delta = user_fcn (tmp_state, tmp_deriv, time, tmp_ires);\n\n  ires = octave::to_f77_int (tmp_ires);\n\n  if (ires >= 0)\n    {\n      if (tmp_delta.isempty ())\n        ires = -2;\n      else\n        {\n          for (F77_INT i = 0; i < nn; i++)\n            delta[i] = tmp_delta.elem (i);\n        }\n    }\n\n  return 0;\n}\n\nstatic F77_INT\nddassl_j (const double& time, const double *state, const double *deriv,\n          double *pd, const double& cj, double *, F77_INT *)\n{\n  // FIXME: would be nice to avoid copying the data.\n\n  ColumnVector tmp_state (nn);\n  ColumnVector tmp_deriv (nn);\n\n  for (F77_INT i = 0; i < nn; i++)\n    {\n      tmp_deriv.elem (i) = deriv[i];\n      tmp_state.elem (i) = state[i];\n    }\n\n  Matrix tmp_pd = user_jac (tmp_state, tmp_deriv, time, cj);\n\n  for (F77_INT j = 0; j < nn; j++)\n    for (F77_INT i = 0; i < nn; i++)\n      pd[nn * j + i] = tmp_pd.elem (i, j);\n\n  return 0;\n}\n\nColumnVector\nDASSL::do_integrate (double tout)\n{\n  ColumnVector retval;\n\n  if (! m_initialized || m_restart || DAEFunc::m_reset\n      || DASSL_options::m_reset)\n    {\n      m_integration_error = false;\n\n      m_initialized = true;\n\n      m_info.resize (dim_vector (15, 1));\n\n      for (F77_INT i = 0; i < 15; i++)\n        m_info(i) = 0;\n\n      F77_INT n = octave::to_f77_int (size ());\n\n      m_liw = 21 + n;\n      m_lrw = 40 + 9*n + n*n;\n\n      nn = n;\n\n      m_iwork.resize (dim_vector (m_liw, 1));\n      m_rwork.resize (dim_vector (m_lrw, 1));\n\n      m_info(0) = 0;\n\n      if (m_stop_time_set)\n        {\n          m_rwork(0) = m_stop_time;\n          m_info(3) = 1;\n        }\n      else\n        m_info(3) = 0;\n\n      m_restart = false;\n\n      // DAEFunc\n\n      user_fcn = DAEFunc::function ();\n      user_jac = DAEFunc::jacobian_function ();\n\n      if (user_fcn)\n        {\n          octave_idx_type ires = 0;\n\n          ColumnVector res = (*user_fcn) (m_x, m_xdot, m_t, ires);\n\n          if (res.numel () != m_x.numel ())\n            {\n              (*current_liboctave_error_handler)\n                (\"dassl: inconsistent sizes for state and residual vectors\");\n\n              m_integration_error = true;\n              return retval;\n            }\n        }\n      else\n        {\n          (*current_liboctave_error_handler)\n            (\"dassl: no user supplied RHS subroutine!\");\n\n          m_integration_error = true;\n          return retval;\n        }\n\n      m_info(4) = (user_jac ? 1 : 0);\n\n      DAEFunc::m_reset = false;\n\n      // DASSL_options\n\n      double hmax = maximum_step_size ();\n      if (hmax >= 0.0)\n        {\n          m_rwork(1) = hmax;\n          m_info(6) = 1;\n        }\n      else\n        m_info(6) = 0;\n\n      double h0 = initial_step_size ();\n      if (h0 >= 0.0)\n        {\n          m_rwork(2) = h0;\n          m_info(7) = 1;\n        }\n      else\n        m_info(7) = 0;\n\n      F77_INT sl = octave::to_f77_int (step_limit ());\n\n      if (sl >= 0)\n        {\n          m_info(11) = 1;\n          m_iwork(20) = sl;\n        }\n      else\n        m_info(11) = 0;\n\n      F77_INT maxord = octave::to_f77_int (maximum_order ());\n      if (maxord >= 0)\n        {\n          if (maxord > 0 && maxord < 6)\n            {\n              m_info(8) = 1;\n              m_iwork(2) = maxord;\n            }\n          else\n            {\n              (*current_liboctave_error_handler)\n                (\"dassl: invalid value for maximum order: %\"\n                 OCTAVE_F77_INT_TYPE_FORMAT, maxord);\n              m_integration_error = true;\n              return retval;\n            }\n        }\n\n      F77_INT enc = octave::to_f77_int (enforce_nonnegativity_constraints ());\n      m_info(9) = (enc ? 1 : 0);\n\n      F77_INT ccic = octave::to_f77_int (compute_consistent_initial_condition ());\n      m_info(10) = (ccic ? 1 : 0);\n\n      m_abs_tol = absolute_tolerance ();\n      m_rel_tol = relative_tolerance ();\n\n      F77_INT abs_tol_len = octave::to_f77_int (m_abs_tol.numel ());\n      F77_INT rel_tol_len = octave::to_f77_int (m_rel_tol.numel ());\n\n      if (abs_tol_len == 1 && rel_tol_len == 1)\n        {\n          m_info(1) = 0;\n        }\n      else if (abs_tol_len == n && rel_tol_len == n)\n        {\n          m_info(1) = 1;\n        }\n      else\n        {\n          (*current_liboctave_error_handler)\n            (\"dassl: inconsistent sizes for tolerance arrays\");\n\n          m_integration_error = true;\n          return retval;\n        }\n\n      DASSL_options::m_reset = false;\n    }\n\n  double *px = m_x.rwdata ();\n  double *pxdot = m_xdot.rwdata ();\n\n  F77_INT *pinfo = m_info.rwdata ();\n\n  double *prel_tol = m_rel_tol.rwdata ();\n  double *pabs_tol = m_abs_tol.rwdata ();\n\n  double *prwork = m_rwork.rwdata ();\n  F77_INT *piwork = m_iwork.rwdata ();\n\n  double *dummy = nullptr;\n  F77_INT *idummy = nullptr;\n\n  F77_INT tmp_istate = octave::to_f77_int (m_istate);\n\n  F77_XFCN (ddassl, DDASSL, (ddassl_f, nn, m_t, px, pxdot, tout, pinfo,\n                             prel_tol, pabs_tol, tmp_istate, prwork, m_lrw,\n                             piwork, m_liw, dummy, idummy, ddassl_j));\n\n  m_istate = tmp_istate;\n\n  switch (m_istate)\n    {\n    case 1: // A step was successfully taken in intermediate-output\n            // mode.  The code has not yet reached TOUT.\n    case 2: // The integration to TSTOP was successfully completed\n            // (T=TSTOP) by stepping exactly to TSTOP.\n    case 3: // The integration to TOUT was successfully completed\n            // (T=TOUT) by stepping past TOUT.  Y(*) is obtained by\n            // interpolation.  YPRIME(*) is obtained by interpolation.\n      retval = m_x;\n      m_t = tout;\n      break;\n\n    case -1: // A large amount of work has been expended.  (~500 steps).\n    case -2: // The error tolerances are too stringent.\n    case -3: // The local error test cannot be satisfied because you\n             // specified a zero component in ATOL and the\n             // corresponding computed solution component is zero.\n             // Thus, a pure relative error test is impossible for\n             // this component.\n    case -6: // DDASSL had repeated error test failures on the last\n             // attempted step.\n    case -7: // The corrector could not converge.\n    case -8: // The matrix of partial derivatives is singular.\n    case -9: // The corrector could not converge.  There were repeated\n             // error test failures in this step.\n    case -10: // The corrector could not converge because IRES was\n              // equal to minus one.\n    case -11: // IRES equal to -2 was encountered and control is being\n              // returned to the calling program.\n    case -12: // DDASSL failed to compute the initial YPRIME.\n    case -33: // The code has encountered trouble from which it cannot\n              // recover.  A message is printed explaining the trouble\n              // and control is returned to the calling program.  For\n              // example, this occurs when invalid input is detected.\n      m_integration_error = true;\n      break;\n\n    default:\n      m_integration_error = true;\n      (*current_liboctave_error_handler)\n        (\"unrecognized value of istate (= %\" OCTAVE_IDX_TYPE_FORMAT \") \"\n         \"returned from ddassl\", m_istate);\n      break;\n    }\n\n  return retval;\n}\n\nMatrix\nDASSL::do_integrate (const ColumnVector& tout)\n{\n  Matrix dummy;\n  return integrate (tout, dummy);\n}\n\nMatrix\nDASSL::integrate (const ColumnVector& tout, Matrix& xdot_out)\n{\n  Matrix retval;\n\n  octave_idx_type n_out = tout.numel ();\n  F77_INT n = octave::to_f77_int (size ());\n\n  if (n_out > 0 && n > 0)\n    {\n      retval.resize (n_out, n);\n      xdot_out.resize (n_out, n);\n\n      for (F77_INT i = 0; i < n; i++)\n        {\n          retval.elem (0, i) = m_x.elem (i);\n          xdot_out.elem (0, i) = m_xdot.elem (i);\n        }\n\n      for (octave_idx_type j = 1; j < n_out; j++)\n        {\n          ColumnVector x_next = do_integrate (tout.elem (j));\n\n          if (m_integration_error)\n            return retval;\n\n          for (F77_INT i = 0; i < n; i++)\n            {\n              retval.elem (j, i) = x_next.elem (i);\n              xdot_out.elem (j, i) = m_xdot.elem (i);\n            }\n        }\n    }\n\n  return retval;\n}\n\nMatrix\nDASSL::do_integrate (const ColumnVector& tout, const ColumnVector& tcrit)\n{\n  Matrix dummy;\n  return integrate (tout, dummy, tcrit);\n}\n\nMatrix\nDASSL::integrate (const ColumnVector& tout, Matrix& xdot_out,\n                  const ColumnVector& tcrit)\n{\n  Matrix retval;\n\n  octave_idx_type n_out = tout.numel ();\n  F77_INT n = octave::to_f77_int (size ());\n\n  if (n_out > 0 && n > 0)\n    {\n      retval.resize (n_out, n);\n      xdot_out.resize (n_out, n);\n\n      for (F77_INT i = 0; i < n; i++)\n        {\n          retval.elem (0, i) = m_x.elem (i);\n          xdot_out.elem (0, i) = m_xdot.elem (i);\n        }\n\n      octave_idx_type n_crit = tcrit.numel ();\n\n      if (n_crit > 0)\n        {\n          octave_idx_type i_crit = 0;\n          octave_idx_type i_out = 1;\n          double next_crit = tcrit.elem (0);\n          double next_out;\n          while (i_out < n_out)\n            {\n              bool do_restart = false;\n\n              next_out = tout.elem (i_out);\n              if (i_crit < n_crit)\n                next_crit = tcrit.elem (i_crit);\n\n              bool save_output;\n              double t_out;\n\n              if (next_crit == next_out)\n                {\n                  set_stop_time (next_crit);\n                  t_out = next_out;\n                  save_output = true;\n                  i_out++;\n                  i_crit++;\n                  do_restart = true;\n                }\n              else if (next_crit < next_out)\n                {\n                  if (i_crit < n_crit)\n                    {\n                      set_stop_time (next_crit);\n                      t_out = next_crit;\n                      save_output = false;\n                      i_crit++;\n                      do_restart = true;\n                    }\n                  else\n                    {\n                      clear_stop_time ();\n                      t_out = next_out;\n                      save_output = true;\n                      i_out++;\n                    }\n                }\n              else\n                {\n                  set_stop_time (next_crit);\n                  t_out = next_out;\n                  save_output = true;\n                  i_out++;\n                }\n\n              ColumnVector x_next = do_integrate (t_out);\n\n              if (m_integration_error)\n                return retval;\n\n              if (save_output)\n                {\n                  for (F77_INT i = 0; i < n; i++)\n                    {\n                      retval.elem (i_out-1, i) = x_next.elem (i);\n                      xdot_out.elem (i_out-1, i) = m_xdot.elem (i);\n                    }\n                }\n\n              if (do_restart)\n                force_restart ();\n            }\n        }\n      else\n        {\n          retval = integrate (tout, xdot_out);\n\n          if (m_integration_error)\n            return retval;\n        }\n    }\n\n  return retval;\n}\n\nstd::string\nDASSL::error_message () const\n{\n  std::string retval;\n\n  std::ostringstream buf;\n  buf << m_t;\n  std::string t_curr = buf.str ();\n\n  switch (m_istate)\n    {\n    case 1:\n      retval = \"a step was successfully taken in intermediate-output mode.\";\n      break;\n\n    case 2:\n      retval = \"integration completed by stepping exactly to TOUT\";\n      break;\n\n    case 3:\n      retval = \"integration to tout completed by stepping past TOUT\";\n      break;\n\n    case -1:\n      retval = \"a large amount of work has been expended (t =\" + t_curr + ')';\n      break;\n\n    case -2:\n      retval = \"the error tolerances are too stringent\";\n      break;\n\n    case -3:\n      retval = \"error weight became zero during problem. (t = \" + t_curr +\n               \"; solution component i vanished, and atol or atol(i) == 0)\";\n      break;\n\n    case -6:\n      retval = \"repeated error test failures on the last attempted step (t = \"\n               + t_curr + ')';\n      break;\n\n    case -7:\n      retval = \"the corrector could not converge (t = \" + t_curr + ')';\n      break;\n\n    case -8:\n      retval = \"the matrix of partial derivatives is singular (t = \" + t_curr +\n               ')';\n      break;\n\n    case -9:\n      retval = \"the corrector could not converge (t = \" + t_curr +\n               \"; repeated test failures)\";\n      break;\n\n    case -10:\n      retval = \"corrector could not converge because IRES was -1 (t = \"\n               + t_curr + ')';\n      break;\n\n    case -11:\n      retval = \"return requested in user-supplied function (t = \" + t_curr +\n               ')';\n      break;\n\n    case -12:\n      retval = \"failed to compute consistent initial conditions\";\n      break;\n\n    case -33:\n      retval = \"unrecoverable error (see printed message)\";\n      break;\n\n    default:\n      retval = \"unknown error state\";\n      break;\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/numeric/DASSL.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_DASSL_h)\n#define octave_DASSL_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"mx-fwd.h\"\n\n#include \"Array-oct.h\"\n#include \"DASSL-opts.h\"\n\nclass OCTAVE_API DASSL : public DAE, public DASSL_options\n{\npublic:\n\n  DASSL ()\n    : DAE (), DASSL_options (), m_initialized (false), m_liw (0), m_lrw (0),\n      m_info (), m_iwork (), m_rwork (), m_abs_tol (), m_rel_tol () { }\n\n  DASSL (const ColumnVector& s, double tm, DAEFunc& f)\n    : DAE (s, tm, f), DASSL_options (), m_initialized (false), m_liw (0),\n      m_lrw (0), m_info (), m_iwork (), m_rwork (), m_abs_tol (), m_rel_tol ()\n  { }\n\n  DASSL (const ColumnVector& s, const ColumnVector& deriv,\n         double tm, DAEFunc& f)\n    : DAE (s, deriv, tm, f), DASSL_options (), m_initialized (false),\n      m_liw (0), m_lrw (0), m_info (), m_iwork (), m_rwork (), m_abs_tol (),\n      m_rel_tol () { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (DASSL)\n\n  ColumnVector do_integrate (double t);\n\n  Matrix do_integrate (const ColumnVector& tout);\n\n  Matrix do_integrate (const ColumnVector& tout, const ColumnVector& tcrit);\n\n  Matrix integrate (const ColumnVector& tout, Matrix& xdot_out);\n\n  Matrix integrate (const ColumnVector& tout, Matrix& xdot_out,\n                    const ColumnVector& tcrit);\n\n  std::string error_message () const;\n\nprivate:\n\n  bool m_initialized;\n\n  octave_f77_int_type m_liw;\n  octave_f77_int_type m_lrw;\n\n  Array<octave_f77_int_type> m_info;\n  Array<octave_f77_int_type> m_iwork;\n\n  Array<double> m_rwork;\n\n  Array<double> m_abs_tol;\n  Array<double> m_rel_tol;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/DET.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_DET_h)\n#define octave_DET_h 1\n\n#include \"octave-config.h\"\n\n#include <cmath>\n\n#include \"mappers.h\"\n#include \"oct-cmplx.h\"\n\ntemplate <typename T>\nclass base_det\n{\npublic:\n\n  base_det (T c = 1, int e = 0)\n    : m_c2 (), m_e2 ()\n  {\n    m_c2 = octave::math::log2 (c, m_e2);\n    m_e2 += e;\n  }\n\n  base_det (T c, double e, double b)\n    : m_c2 (), m_e2 ()\n  {\n    e *= octave::math::log2 (b);\n    m_e2 = e;\n    c *= octave::math::exp2 (e - m_e2);\n    int f;\n    m_c2 = octave::math::log2 (c, f);\n    m_e2 += f;\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (base_det)\n\n  T coef () const { return m_c2; }\n  int exp () const { return m_e2; }\n\n  T value () const { return m_c2 * static_cast<T> (std::ldexp (1.0, m_e2)); }\n  operator T () const { return value (); }\n\n  base_det square () const { return base_det (m_c2*m_c2, m_e2+m_e2); }\n\n  void operator *= (T t)\n  {\n    int e;\n    m_c2 *= t;\n    // Renormalize m_c2 to [0.5, 1), and find required change in exponent.\n    m_c2 = octave::math::log2 (m_c2, e);\n    m_e2 += e;\n  }\n\nprivate:\n\n  T m_c2;\n  int m_e2;\n};\n\n// Provide the old types by typedefs.\ntypedef base_det<double> DET;\ntypedef base_det<float> FloatDET;\ntypedef base_det<Complex> ComplexDET;\ntypedef base_det<FloatComplex> FloatComplexDET;\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/EIG.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-oct.h\"\n#include \"EIG.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"lapack-proto.h\"\n#include \"oct-error.h\"\n\noctave_idx_type\nEIG::init (const Matrix& a, bool calc_rev, bool calc_lev, bool balance)\n{\n  if (a.any_element_is_inf_or_nan ())\n    (*current_liboctave_error_handler)\n      (\"EIG: matrix contains Inf or NaN values\");\n\n  if (a.issymmetric ())\n    return symmetric_init (a, calc_rev, calc_lev);\n\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (n != a_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  F77_INT info = 0;\n\n  Matrix atmp = a;\n  double *tmp_data = atmp.rwdata ();\n\n  Array<double> wr (dim_vector (n, 1));\n  double *pwr = wr.rwdata ();\n\n  Array<double> wi (dim_vector (n, 1));\n  double *pwi = wi.rwdata ();\n\n  F77_INT tnvr = (calc_rev ? n : 0);\n  Matrix vr (tnvr, tnvr);\n  double *pvr = vr.rwdata ();\n\n  F77_INT tnvl = (calc_lev ? n : 0);\n  Matrix vl (tnvl, tnvl);\n  double *pvl = vl.rwdata ();\n\n  F77_INT lwork = -1;\n  double dummy_work;\n\n  F77_INT ilo;\n  F77_INT ihi;\n\n  Array<double> scale (dim_vector (n, 1));\n  double *pscale = scale.rwdata ();\n\n  double abnrm;\n\n  Array<double> rconde (dim_vector (n, 1));\n  double *prconde = rconde.rwdata ();\n\n  Array<double> rcondv (dim_vector (n, 1));\n  double *prcondv = rcondv.rwdata ();\n\n  F77_INT dummy_iwork;\n\n  F77_XFCN (dgeevx, DGEEVX, (F77_CONST_CHAR_ARG2 (balance ? \"B\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             n, tmp_data, n, pwr, pwi, pvl,\n                             n, pvr, n, ilo, ihi, pscale,\n                             abnrm, prconde, prcondv, &dummy_work,\n                             lwork, &dummy_iwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"dgeevx workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work);\n  Array<double> work (dim_vector (lwork, 1));\n  double *pwork = work.rwdata ();\n\n  F77_XFCN (dgeevx, DGEEVX, (F77_CONST_CHAR_ARG2 (balance ? \"B\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             n, tmp_data, n, pwr, pwi, pvl,\n                             n, pvr, n, ilo, ihi, pscale,\n                             abnrm, prconde, prcondv, pwork,\n                             lwork, &dummy_iwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in dgeevx\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"dgeevx failed to converge\");\n\n  m_lambda.resize (n);\n  F77_INT nvr = (calc_rev ? n : 0);\n  m_v.resize (nvr, nvr);\n  F77_INT nvl = (calc_lev ? n : 0);\n  m_w.resize (nvl, nvl);\n\n  for (F77_INT j = 0; j < n; j++)\n    {\n      if (wi.elem (j) == 0.0)\n        {\n          m_lambda.elem (j) = Complex (wr.elem (j));\n          for (F77_INT i = 0; i < nvr; i++)\n            m_v.elem (i, j) = vr.elem (i, j);\n\n          for (F77_INT i = 0; i < nvl; i++)\n            m_w.elem (i, j) = vl.elem (i, j);\n        }\n      else\n        {\n          if (j+1 >= n)\n            (*current_liboctave_error_handler) (\"EIG: internal error\");\n\n          m_lambda.elem (j) = Complex (wr.elem (j), wi.elem (j));\n          m_lambda.elem (j+1) = Complex (wr.elem (j+1), wi.elem (j+1));\n\n          for (F77_INT i = 0; i < nvr; i++)\n            {\n              double real_part = vr.elem (i, j);\n              double imag_part = vr.elem (i, j+1);\n              m_v.elem (i, j) = Complex (real_part, imag_part);\n              m_v.elem (i, j+1) = Complex (real_part, -imag_part);\n            }\n\n          for (F77_INT i = 0; i < nvl; i++)\n            {\n              double real_part = vl.elem (i, j);\n              double imag_part = vl.elem (i, j+1);\n              m_w.elem (i, j) = Complex (real_part, imag_part);\n              m_w.elem (i, j+1) = Complex (real_part, -imag_part);\n            }\n          j++;\n        }\n    }\n\n  return info;\n}\n\noctave_idx_type\nEIG::symmetric_init (const Matrix& a, bool calc_rev, bool calc_lev)\n{\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (n != a_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  F77_INT info = 0;\n\n  Matrix atmp = a;\n  double *tmp_data = atmp.rwdata ();\n\n  ColumnVector wr (n);\n  double *pwr = wr.rwdata ();\n\n  F77_INT lwork = -1;\n  double dummy_work;\n\n  F77_XFCN (dsyev, DSYEV, (F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, tmp_data, n, pwr, &dummy_work, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"dsyev workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work);\n  Array<double> work (dim_vector (lwork, 1));\n  double *pwork = work.rwdata ();\n\n  F77_XFCN (dsyev, DSYEV, (F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, tmp_data, n, pwr, pwork, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in dsyev\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"dsyev failed to converge\");\n\n  m_lambda = ComplexColumnVector (wr);\n  m_v = (calc_rev ? ComplexMatrix (atmp) : ComplexMatrix ());\n  m_w = (calc_lev ? ComplexMatrix (atmp) : ComplexMatrix ());\n\n  return info;\n}\n\noctave_idx_type\nEIG::init (const ComplexMatrix& a, bool calc_rev, bool calc_lev, bool balance)\n{\n  if (a.any_element_is_inf_or_nan ())\n    (*current_liboctave_error_handler)\n      (\"EIG: matrix contains Inf or NaN values\");\n\n  if (a.ishermitian ())\n    return hermitian_init (a, calc_rev, calc_lev);\n\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (n != a_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  F77_INT info = 0;\n\n  ComplexMatrix atmp = a;\n  Complex *tmp_data = atmp.rwdata ();\n\n  ComplexColumnVector wr (n);\n  Complex *pw = wr.rwdata ();\n\n  F77_INT nvr = (calc_rev ? n : 0);\n  ComplexMatrix vrtmp (nvr, nvr);\n  Complex *pvr = vrtmp.rwdata ();\n\n  F77_INT nvl = (calc_lev ? n : 0);\n  ComplexMatrix vltmp (nvl, nvl);\n  Complex *pvl = vltmp.rwdata ();\n\n  F77_INT lwork = -1;\n  Complex dummy_work;\n\n  F77_INT lrwork = 2*n;\n  Array<double> rwork (dim_vector (lrwork, 1));\n  double *prwork = rwork.rwdata ();\n\n  F77_INT ilo;\n  F77_INT ihi;\n\n  Array<double> scale (dim_vector (n, 1));\n  double *pscale = scale.rwdata ();\n\n  double abnrm;\n\n  Array<double> rconde (dim_vector (n, 1));\n  double *prconde = rconde.rwdata ();\n\n  Array<double> rcondv (dim_vector (n, 1));\n  double *prcondv = rcondv.rwdata ();\n\n  F77_XFCN (zgeevx, ZGEEVX, (F77_CONST_CHAR_ARG2 (balance ? \"B\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             n, F77_DBLE_CMPLX_ARG (tmp_data), n,\n                             F77_DBLE_CMPLX_ARG (pw), F77_DBLE_CMPLX_ARG (pvl),\n                             n, F77_DBLE_CMPLX_ARG (pvr), n, ilo, ihi,\n                             pscale, abnrm, prconde, prcondv,\n                             F77_DBLE_CMPLX_ARG (&dummy_work), lwork, prwork,\n                             info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"zgeevx workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work.real ());\n  Array<Complex> work (dim_vector (lwork, 1));\n  Complex *pwork = work.rwdata ();\n\n  F77_XFCN (zgeevx, ZGEEVX, (F77_CONST_CHAR_ARG2 (balance ? \"B\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             n, F77_DBLE_CMPLX_ARG (tmp_data), n,\n                             F77_DBLE_CMPLX_ARG (pw), F77_DBLE_CMPLX_ARG (pvl),\n                             n, F77_DBLE_CMPLX_ARG (pvr), n, ilo, ihi,\n                             pscale, abnrm, prconde, prcondv,\n                             F77_DBLE_CMPLX_ARG (pwork), lwork, prwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in zgeevx\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"zgeevx failed to converge\");\n\n  m_lambda = wr;\n  m_v = vrtmp;\n  m_w = vltmp;\n\n  return info;\n}\n\noctave_idx_type\nEIG::hermitian_init (const ComplexMatrix& a, bool calc_rev, bool calc_lev)\n{\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (n != a_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  F77_INT info = 0;\n\n  ComplexMatrix atmp = a;\n  Complex *tmp_data = atmp.rwdata ();\n\n  ColumnVector wr (n);\n  double *pwr = wr.rwdata ();\n\n  F77_INT lwork = -1;\n  Complex dummy_work;\n\n  F77_INT lrwork = 3*n;\n  Array<double> rwork (dim_vector (lrwork, 1));\n  double *prwork = rwork.rwdata ();\n\n  F77_XFCN (zheev, ZHEEV, (F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, F77_DBLE_CMPLX_ARG (tmp_data), n, pwr,\n                           F77_DBLE_CMPLX_ARG (&dummy_work), lwork,\n                           prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"zheev workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work.real ());\n  Array<Complex> work (dim_vector (lwork, 1));\n  Complex *pwork = work.rwdata ();\n\n  F77_XFCN (zheev, ZHEEV, (F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, F77_DBLE_CMPLX_ARG (tmp_data), n, pwr,\n                           F77_DBLE_CMPLX_ARG (pwork), lwork, prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in zheev\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"zheev failed to converge\");\n\n  m_lambda = ComplexColumnVector (wr);\n  m_v = (calc_rev ? ComplexMatrix (atmp) : ComplexMatrix ());\n  m_w = (calc_lev ? ComplexMatrix (atmp) : ComplexMatrix ());\n\n  return info;\n}\n\noctave_idx_type\nEIG::init (const Matrix& a, const Matrix& b, bool calc_rev, bool calc_lev,\n           bool force_qz)\n{\n  if (a.any_element_is_inf_or_nan () || b.any_element_is_inf_or_nan ())\n    (*current_liboctave_error_handler)\n      (\"EIG: matrix contains Inf or NaN values\");\n\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT nb = octave::to_f77_int (b.rows ());\n\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (n != a_nc || nb != b_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  if (n != nb)\n    (*current_liboctave_error_handler) (\"EIG requires same size matrices\");\n\n  F77_INT info = 0;\n\n  Matrix tmp = b;\n  double *tmp_data = tmp.rwdata ();\n\n  if (! force_qz)\n    {\n      F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (\"L\", 1),\n                                 n, tmp_data, n,\n                                 info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (a.issymmetric () && b.issymmetric () && info == 0)\n        return symmetric_init (a, b, calc_rev, calc_lev);\n    }\n\n  Matrix atmp = a;\n  double *atmp_data = atmp.rwdata ();\n\n  Matrix btmp = b;\n  double *btmp_data = btmp.rwdata ();\n\n  Array<double> ar (dim_vector (n, 1));\n  double *par = ar.rwdata ();\n\n  Array<double> ai (dim_vector (n, 1));\n  double *pai = ai.rwdata ();\n\n  Array<double> beta (dim_vector (n, 1));\n  double *pbeta = beta.rwdata ();\n\n  F77_INT tnvr = (calc_rev ? n : 0);\n  Matrix vr (tnvr, tnvr);\n  double *pvr = vr.rwdata ();\n\n  F77_INT tnvl = (calc_lev ? n : 0);\n  Matrix vl (tnvl, tnvl);\n  double *pvl = vl.rwdata ();\n\n  F77_INT lwork = -1;\n  double dummy_work;\n\n  F77_XFCN (dggev, DGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           n, atmp_data, n, btmp_data, n,\n                           par, pai, pbeta,\n                           pvl, n, pvr, n,\n                           &dummy_work, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"dggev workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work);\n  Array<double> work (dim_vector (lwork, 1));\n  double *pwork = work.rwdata ();\n\n  F77_XFCN (dggev, DGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           n, atmp_data, n, btmp_data, n,\n                           par, pai, pbeta,\n                           pvl, n, pvr, n,\n                           pwork, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in dggev\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"dggev failed to converge\");\n\n  m_lambda.resize (n);\n  F77_INT nvr = (calc_rev ? n : 0);\n  m_v.resize (nvr, nvr);\n\n  F77_INT nvl = (calc_lev ? n : 0);\n  m_w.resize (nvl, nvl);\n\n  for (F77_INT j = 0; j < n; j++)\n    {\n      if (ai.elem (j) == 0.0)\n        {\n          m_lambda.elem (j) = Complex (ar.elem (j) / beta.elem (j));\n          for (F77_INT i = 0; i < nvr; i++)\n            m_v.elem (i, j) = vr.elem (i, j);\n          for (F77_INT i = 0; i < nvl; i++)\n            m_w.elem (i, j) = vl.elem (i, j);\n        }\n      else\n        {\n          if (j+1 >= n)\n            (*current_liboctave_error_handler) (\"EIG: internal error\");\n\n          m_lambda.elem (j) = Complex (ar.elem (j) / beta.elem (j),\n                                       ai.elem (j) / beta.elem (j));\n          m_lambda.elem (j+1) = Complex (ar.elem (j+1) / beta.elem (j+1),\n                                         ai.elem (j+1) / beta.elem (j+1));\n\n          for (F77_INT i = 0; i < nvr; i++)\n            {\n              double real_part = vr.elem (i, j);\n              double imag_part = vr.elem (i, j+1);\n              m_v.elem (i, j) = Complex (real_part, imag_part);\n              m_v.elem (i, j+1) = Complex (real_part, -imag_part);\n            }\n          for (F77_INT i = 0; i < nvl; i++)\n            {\n              double real_part = vl.elem (i, j);\n              double imag_part = vl.elem (i, j+1);\n              m_w.elem (i, j) = Complex (real_part, imag_part);\n              m_w.elem (i, j+1) = Complex (real_part, -imag_part);\n            }\n          j++;\n        }\n    }\n\n  return info;\n}\n\noctave_idx_type\nEIG::symmetric_init (const Matrix& a, const Matrix& b, bool calc_rev,\n                     bool calc_lev)\n{\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT nb = octave::to_f77_int (b.rows ());\n\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (n != a_nc || nb != b_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  if (n != nb)\n    (*current_liboctave_error_handler) (\"EIG requires same size matrices\");\n\n  F77_INT info = 0;\n\n  Matrix atmp = a;\n  double *atmp_data = atmp.rwdata ();\n\n  Matrix btmp = b;\n  double *btmp_data = btmp.rwdata ();\n\n  ColumnVector wr (n);\n  double *pwr = wr.rwdata ();\n\n  F77_INT lwork = -1;\n  double dummy_work;\n\n  F77_XFCN (dsygv, DSYGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, atmp_data, n,\n                           btmp_data, n,\n                           pwr, &dummy_work, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"dsygv workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work);\n  Array<double> work (dim_vector (lwork, 1));\n  double *pwork = work.rwdata ();\n\n  F77_XFCN (dsygv, DSYGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, atmp_data, n,\n                           btmp_data, n,\n                           pwr, pwork, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in dsygv\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"dsygv failed to converge\");\n\n  m_lambda = ComplexColumnVector (wr);\n  m_v = (calc_rev ? ComplexMatrix (atmp) : ComplexMatrix ());\n  m_w = (calc_lev ? ComplexMatrix (atmp) : ComplexMatrix ());\n\n  return info;\n}\n\noctave_idx_type\nEIG::init (const ComplexMatrix& a, const ComplexMatrix& b, bool calc_rev,\n           bool calc_lev, bool force_qz)\n{\n  if (a.any_element_is_inf_or_nan () || b.any_element_is_inf_or_nan ())\n    (*current_liboctave_error_handler)\n      (\"EIG: matrix contains Inf or NaN values\");\n\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT nb = octave::to_f77_int (b.rows ());\n\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (n != a_nc || nb != b_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  if (n != nb)\n    (*current_liboctave_error_handler) (\"EIG requires same size matrices\");\n\n  F77_INT info = 0;\n\n  ComplexMatrix tmp = b;\n  Complex *tmp_data = tmp.rwdata ();\n\n  if (! force_qz)\n    {\n      F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (\"L\", 1),\n                                 n, F77_DBLE_CMPLX_ARG (tmp_data), n,\n                                 info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (a.ishermitian () && b.ishermitian () && info == 0)\n        return hermitian_init (a, b, calc_rev, calc_lev);\n    }\n\n  ComplexMatrix atmp = a;\n  Complex *atmp_data = atmp.rwdata ();\n\n  ComplexMatrix btmp = b;\n  Complex *btmp_data = btmp.rwdata ();\n\n  ComplexColumnVector alpha (n);\n  Complex *palpha = alpha.rwdata ();\n\n  ComplexColumnVector beta (n);\n  Complex *pbeta = beta.rwdata ();\n\n  F77_INT nvr = (calc_rev ? n : 0);\n  ComplexMatrix vrtmp (nvr, nvr);\n  Complex *pvr = vrtmp.rwdata ();\n\n  F77_INT nvl = (calc_lev ? n : 0);\n  ComplexMatrix vltmp (nvl, nvl);\n  Complex *pvl = vltmp.rwdata ();\n\n  F77_INT lwork = -1;\n  Complex dummy_work;\n\n  F77_INT lrwork = 8*n;\n  Array<double> rwork (dim_vector (lrwork, 1));\n  double *prwork = rwork.rwdata ();\n\n  F77_XFCN (zggev, ZGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           n, F77_DBLE_CMPLX_ARG (atmp_data), n,\n                           F77_DBLE_CMPLX_ARG (btmp_data), n,\n                           F77_DBLE_CMPLX_ARG (palpha),\n                           F77_DBLE_CMPLX_ARG (pbeta),\n                           F77_DBLE_CMPLX_ARG (pvl), n,\n                           F77_DBLE_CMPLX_ARG (pvr), n,\n                           F77_DBLE_CMPLX_ARG (&dummy_work), lwork, prwork,\n                           info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"zggev workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work.real ());\n  Array<Complex> work (dim_vector (lwork, 1));\n  Complex *pwork = work.rwdata ();\n\n  F77_XFCN (zggev, ZGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           n, F77_DBLE_CMPLX_ARG (atmp_data), n,\n                           F77_DBLE_CMPLX_ARG (btmp_data), n,\n                           F77_DBLE_CMPLX_ARG (palpha),\n                           F77_DBLE_CMPLX_ARG (pbeta),\n                           F77_DBLE_CMPLX_ARG (pvl), n,\n                           F77_DBLE_CMPLX_ARG (pvr), n,\n                           F77_DBLE_CMPLX_ARG (pwork), lwork, prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in zggev\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"zggev failed to converge\");\n\n  m_lambda.resize (n);\n\n  for (F77_INT j = 0; j < n; j++)\n    m_lambda.elem (j) = alpha.elem (j) / beta.elem (j);\n\n  m_v = vrtmp;\n  m_w = vltmp;\n\n  return info;\n}\n\noctave_idx_type\nEIG::hermitian_init (const ComplexMatrix& a, const ComplexMatrix& b,\n                     bool calc_rev, bool calc_lev)\n{\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT nb = octave::to_f77_int (b.rows ());\n\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (n != a_nc || nb != b_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  if (n != nb)\n    (*current_liboctave_error_handler) (\"EIG requires same size matrices\");\n\n  F77_INT info = 0;\n\n  ComplexMatrix atmp = a;\n  Complex *atmp_data = atmp.rwdata ();\n\n  ComplexMatrix btmp = b;\n  Complex *btmp_data = btmp.rwdata ();\n\n  ColumnVector wr (n);\n  double *pwr = wr.rwdata ();\n\n  F77_INT lwork = -1;\n  Complex dummy_work;\n\n  F77_INT lrwork = 3*n;\n  Array<double> rwork (dim_vector (lrwork, 1));\n  double *prwork = rwork.rwdata ();\n\n  F77_XFCN (zhegv, ZHEGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, F77_DBLE_CMPLX_ARG (atmp_data), n,\n                           F77_DBLE_CMPLX_ARG (btmp_data), n,\n                           pwr, F77_DBLE_CMPLX_ARG (&dummy_work), lwork,\n                           prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"zhegv workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work.real ());\n  Array<Complex> work (dim_vector (lwork, 1));\n  Complex *pwork = work.rwdata ();\n\n  F77_XFCN (zhegv, ZHEGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, F77_DBLE_CMPLX_ARG (atmp_data), n,\n                           F77_DBLE_CMPLX_ARG (btmp_data), n,\n                           pwr, F77_DBLE_CMPLX_ARG (pwork), lwork, prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in zhegv\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"zhegv failed to converge\");\n\n  m_lambda = ComplexColumnVector (wr);\n  m_v = (calc_rev ? ComplexMatrix (atmp) : ComplexMatrix ());\n  m_w = (calc_lev ? ComplexMatrix (atmp) : ComplexMatrix ());\n\n  return info;\n}\n"
  },
  {
    "path": "liboctave/numeric/EIG.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_EIG_h)\n#define octave_EIG_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n#include \"mx-fwd.h\"\n\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n\nclass OCTAVE_API EIG\n{\n  friend class Matrix;\n  friend class ComplexMatrix;\n\npublic:\n\n  EIG () : m_lambda (), m_v (), m_w () { }\n\n  EIG (const Matrix& a, bool calc_rev = true,\n       bool calc_lev = true, bool balance = true)\n    : m_lambda (), m_v (), m_w ()\n  {\n    init (a, calc_rev, calc_lev, balance);\n  }\n\n  EIG (const Matrix& a, octave_idx_type& info,\n       bool calc_rev = true, bool calc_lev = true, bool balance = true)\n    : m_lambda (), m_v (), m_w ()\n  {\n    info = init (a, calc_rev, calc_lev, balance);\n  }\n\n  EIG (const Matrix& a, const Matrix& b,\n       bool calc_rev = true, bool calc_lev = true, bool force_qz = false)\n    : m_lambda (), m_v (), m_w ()\n  {\n    init (a, b, calc_rev, calc_lev, force_qz);\n  }\n\n  EIG (const Matrix& a, const Matrix& b, octave_idx_type& info,\n       bool calc_rev = true, bool calc_lev = true, bool force_qz = false)\n    : m_lambda (), m_v (), m_w ()\n  {\n    info = init (a, b, calc_rev, calc_lev, force_qz);\n  }\n\n  EIG (const ComplexMatrix& a, bool calc_rev = true,\n       bool calc_lev = true, bool balance = true)\n    : m_lambda (), m_v (), m_w ()\n  {\n    init (a, calc_rev, calc_lev, balance);\n  }\n\n  EIG (const ComplexMatrix& a, octave_idx_type& info,\n       bool calc_rev = true, bool calc_lev = true, bool balance = true)\n    : m_lambda (), m_v (), m_w ()\n  {\n    info = init (a, calc_rev, calc_lev, balance);\n  }\n\n  EIG (const ComplexMatrix& a, const ComplexMatrix& b,\n       bool calc_rev = true, bool calc_lev = true, bool force_qz = false)\n    : m_lambda (), m_v (), m_w ()\n  {\n    init (a, b, calc_rev, calc_lev, force_qz);\n  }\n\n  EIG (const ComplexMatrix& a, const ComplexMatrix& b,\n       octave_idx_type& info, bool calc_rev = true, bool calc_lev = true,\n       bool force_qz = false)\n    : m_lambda (), m_v (), m_w ()\n  {\n    info = init (a, b, calc_rev, calc_lev, force_qz);\n  }\n\n  EIG (const EIG& a) : m_lambda (a.m_lambda), m_v (a.m_v), m_w (a.m_w) { }\n\n  EIG& operator = (const EIG& a)\n  {\n    if (this != &a)\n      {\n        m_lambda = a.m_lambda;\n        m_v = a.m_v;\n        m_w = a.m_w;\n      }\n    return *this;\n  }\n\n  ~EIG () = default;\n\n  ComplexColumnVector eigenvalues () const { return m_lambda; }\n  ComplexMatrix right_eigenvectors () const { return m_v; }\n  ComplexMatrix left_eigenvectors () const { return m_w; }\n\n  friend std::ostream&  operator << (std::ostream& os, const EIG& a);\n\nprivate:\n\n  ComplexColumnVector m_lambda;\n  ComplexMatrix m_v;\n  ComplexMatrix m_w;\n\n  octave_idx_type init (const Matrix& a, bool calc_rev, bool calc_lev,\n                        bool balance);\n\n  octave_idx_type init (const Matrix& a, const Matrix& b,\n                        bool calc_rev, bool calc_lev, bool force_qz);\n\n  octave_idx_type init (const ComplexMatrix& a, bool calc_rev,\n                        bool calc_lev, bool balance);\n\n  octave_idx_type init (const ComplexMatrix& a, const ComplexMatrix& b,\n                        bool calc_rev, bool calc_lev, bool force_qz);\n\n  octave_idx_type symmetric_init (const Matrix& a, bool calc_rev,\n                                  bool calc_lev);\n\n  octave_idx_type symmetric_init (const Matrix& a, const Matrix& b,\n                                  bool calc_rev, bool calc_lev);\n\n  octave_idx_type hermitian_init (const ComplexMatrix& a,\n                                  bool calc_rev, bool calc_lev);\n\n  octave_idx_type hermitian_init (const ComplexMatrix& a,\n                                  const ComplexMatrix& b,\n                                  bool calc_rev, bool calc_lev);\n\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/LSODE-opts.in",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nCLASS = \"LSODE\"\n\nINCLUDE = \"ODE.h\"\n\nOPTION\n  NAME = \"absolute tolerance\"\n  DOC_ITEM\nAbsolute tolerance.  May be either vector or scalar.  If a vector, it\nmust match the dimension of the state vector.\n\n  END_DOC_ITEM\n  TYPE = \"Array<double>\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_BODY\n    $OPTVAR.resize (dim_vector (1, 1));\n    $OPTVAR(0) = ::sqrt (std::numeric_limits<double>::epsilon ());\n  END_INIT_BODY\n  SET_CODE\n    void set_$OPT (double val)\n      {\n        $OPTVAR.resize (dim_vector (1, 1));\n        $OPTVAR(0) = (val > 0.0) ? val : ::sqrt (std::numeric_limits<double>::epsilon ());\n        m_reset = true;\n      }\n\n    void set_$OPT (const $TYPE& val)\n      { $OPTVAR = val; m_reset = true; }\n  END_SET_CODE\nEND_OPTION\n\nOPTION\n  NAME = \"relative tolerance\"\n  DOC_ITEM\nRelative tolerance parameter.  Unlike the absolute tolerance, this\nparameter may only be a scalar.\n\nThe local error test applied at each integration step is\n\n@example\n@group\n  abs (local error in x(i)) <= ...\n      rtol * abs (y(i)) + atol(i)\n@end group\n@end example\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"::sqrt (std::numeric_limits<double>::epsilon ())\"\n  SET_EXPR = \"(val > 0.0) ? val : ::sqrt (std::numeric_limits<double>::epsilon ())\"\nEND_OPTION\n\nOPTION\n  NAME = \"integration method\"\n  DOC_ITEM\nA string specifying the method of integration to use to solve the ODE\nsystem.  Valid values are\n\n@table @asis\n@item  @qcode{\"adams\"}\n@itemx @qcode{\"non-stiff\"}\nNo Jacobian used (even if it is available).\n\n@item  @qcode{\"bdf\"}\n@itemx @qcode{\"stiff\"}\nUse stiff backward differentiation formula (BDF) method.  If a\nfunction to compute the Jacobian is not supplied, @code{lsode} will\ncompute a finite difference approximation of the Jacobian matrix.\n@end table\n\n  END_DOC_ITEM\n  TYPE = \"std::string\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_VALUE = \"\"stiff\"\"\n  SET_BODY\n    if (val == \"stiff\" || val == \"bdf\")\n      $OPTVAR = \"stiff\";\n    else if (val == \"non-stiff\" || val == \"adams\")\n      $OPTVAR = \"non-stiff\";\n    else\n      (*current_liboctave_error_handler)\n        (\"lsode_options: method must be \\\"stiff\\\", \\\"bdf\\\", \\\"non-stiff\\\", or \\\"adams\\\"\");\n  END_SET_BODY\nEND_OPTION\n\nOPTION\n  NAME = \"initial step size\"\n  DOC_ITEM\nThe step size to be attempted on the first step (default is determined\nautomatically).\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"-1.0\"\n  SET_EXPR = \"(val >= 0.0) ? val : -1.0\"\nEND_OPTION\n\nOPTION\n  NAME = \"maximum order\"\n  DOC_ITEM\nRestrict the maximum order of the solution method.  If using the Adams\nmethod, this option must be between 1 and 12.  Otherwise, it must be\nbetween 1 and 5, inclusive.\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"-1\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"maximum step size\"\n  DOC_ITEM\nSetting the maximum stepsize will avoid passing over very large\nregions  (default is not specified).\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"-1.0\"\n  SET_EXPR = \"(val >= 0.0) ? val : -1.0\"\nEND_OPTION\n\nOPTION\n  NAME = \"minimum step size\"\n  DOC_ITEM\nThe minimum absolute step size allowed (default is 0).\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"0.0\"\n  SET_EXPR = \"(val >= 0.0) ? val : 0.0\"\nEND_OPTION\n\nOPTION\n  NAME = \"step limit\"\n  DOC_ITEM\nMaximum number of steps allowed (default is 100000).\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"100000\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"jacobian type\"\n  DOC_ITEM\nA string specifying the type of Jacobian used with the stiff backward\ndifferentiation formula (BDF) integration method.  Valid values are\n\n@table @asis\n@item @qcode{\"full\"}\nThe default.  All partial derivatives are approximated or used from the\nuser-supplied Jacobian function.\n\n@item @qcode{\"banded\"}\nOnly the diagonal and the number of lower and upper subdiagonals specified by\nthe options @qcode{\"lower jacobian subdiagonals\"} and @qcode{\"upper jacobian\nsubdiagonals\"}, respectively, are approximated or used from the user-supplied\nJacobian function.  A user-supplied Jacobian function may set all other\npartial derivatives to arbitrary values.\n\n@item @qcode{\"diagonal\"}\nIf a Jacobian function is supplied by the user, this setting has no effect.\nA Jacobian approximated by @code{lsode} is restricted to the diagonal, where\neach partial derivative is computed by applying a finite change to all\nelements of the state together; if the real Jacobian is indeed always diagonal,\nthis has the same effect as applying the finite change only to the respective\nelement of the state, but is more efficient.\n@end table\n\n  END_DOC_ITEM\n  TYPE = \"std::string\"\n  SET_ARG_TYPE = \"const $TYPE&\"\n  INIT_VALUE = \"\"full\"\"\n  SET_BODY\n    if (val == \"full\" || val == \"banded\" || val == \"diagonal\")\n      $OPTVAR = val;\n    else\n      (*current_liboctave_error_handler)\n        (\"lsode_options: jacobian type must be \\\"full\\\", \\\"banded\\\", or \\\"diagonal\\\"\");\n  END_SET_BODY\nEND_OPTION\n\nOPTION\n  NAME = \"lower jacobian subdiagonals\"\n  DOC_ITEM\nNumber of lower subdiagonals used if option @qcode{\"jacobian type\"} is set to\n@qcode{\"banded\"}.  The default is zero.\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"0\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"upper jacobian subdiagonals\"\n  DOC_ITEM\nNumber of upper subdiagonals used if option @qcode{\"jacobian type\"} is set to\n@qcode{\"banded\"}.  The default is zero.\n\n  END_DOC_ITEM\n  TYPE = \"octave_idx_type\"\n  INIT_VALUE = \"0\"\n  SET_EXPR = \"val\"\nEND_OPTION\n"
  },
  {
    "path": "liboctave/numeric/LSODE.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n\n#include \"LSODE.h\"\n#include \"f77-fcn.h\"\n#include \"oct-error.h\"\n\ntypedef F77_INT (*lsode_fcn_ptr) (const F77_INT&, const double&, double *,\n                                  double *, F77_INT&);\n\ntypedef F77_INT (*lsode_jac_ptr) (const F77_INT&, const double&, double *,\n                                  const F77_INT&, const F77_INT&, double *,\n                                  const F77_INT&);\n\nextern \"C\"\n{\n  F77_RET_T\n  F77_FUNC (dlsode, DLSODE) (lsode_fcn_ptr, F77_INT&, F77_DBLE *, F77_DBLE&,\n                             F77_DBLE&, F77_INT&, F77_DBLE&, const F77_DBLE *,\n                             F77_INT&, F77_INT&, F77_INT&, F77_DBLE *,\n                             F77_INT&, F77_INT *, F77_INT&, lsode_jac_ptr,\n                             F77_INT&);\n}\n\nstatic ODEFunc::ODERHSFunc user_fcn;\nstatic ODEFunc::ODEJacFunc user_jac;\nstatic ColumnVector *tmp_x;\nstatic bool user_jac_ignore_ml_mu;\n\nstatic F77_INT\nlsode_f (const F77_INT& neq, const double& time, double *, double *deriv,\n         F77_INT& ierr)\n{\n  ColumnVector tmp_deriv;\n\n  // NOTE: this won't work if LSODE passes copies of the state vector.\n  //       In that case we have to create a temporary vector object\n  //       and copy.\n\n  tmp_deriv = (*user_fcn) (*tmp_x, time);\n\n  if (tmp_deriv.isempty ())\n    ierr = -1;\n  else\n    {\n      for (F77_INT i = 0; i < neq; i++)\n        deriv[i] = tmp_deriv.elem (i);\n    }\n\n  return 0;\n}\n\nstatic F77_INT\nlsode_j (const F77_INT& neq, const double& time, double *,\n         const F77_INT& ml, const F77_INT& mu,\n         double *pd, const F77_INT& nrowpd)\n{\n  Matrix tmp_jac (neq, neq);\n\n  // NOTE: this won't work if LSODE passes copies of the state vector.\n  //       In that case we have to create a temporary vector object\n  //       and copy.\n\n  tmp_jac = (*user_jac) (*tmp_x, time);\n\n  if (user_jac_ignore_ml_mu)\n    for (F77_INT j = 0; j < neq; j++)\n      for (F77_INT i = 0; i < neq; i++)\n        pd[nrowpd * j + i] = tmp_jac (i, j);\n  else\n    // upper left ends of subdiagonals in tmp_jac\n    for (F77_INT i = 0, j = mu; i <= ml; j == 0 ? i++ : j--)\n      // walk down the subdiagonal in tmp_jac\n      for (F77_INT k = i, l = j; k < neq && l < neq; k++, l++)\n        pd[nrowpd * l + k + mu - l] = tmp_jac (k, l);\n\n  return 0;\n}\n\nColumnVector\nLSODE::do_integrate (double tout)\n{\n  ColumnVector retval;\n\n  static F77_INT nn = 0;\n\n  if (! m_initialized || m_restart || ODEFunc::m_reset\n      || LSODE_options::m_reset)\n    {\n      m_integration_error = false;\n\n      m_initialized = true;\n\n      m_istate = 1;\n\n      F77_INT n = octave::to_f77_int (size ());\n\n      nn = n;\n\n      octave_idx_type max_maxord = 0;\n\n      user_jac_ignore_ml_mu = true;\n\n      m_iwork = Array<octave_f77_int_type> (dim_vector (2, 1));\n\n      m_iwork(0) = lower_jacobian_subdiagonals ();  // 'ML' in dlsode.f\n\n      m_iwork(1) = upper_jacobian_subdiagonals ();  // 'MU' in dlsode.f\n\n      if (integration_method () == \"stiff\")\n        {\n          max_maxord = 5;\n\n          if (m_jac)\n            {\n              if (jacobian_type () == \"banded\")\n                {\n                  m_method_flag = 24;\n                  user_jac_ignore_ml_mu = false;\n                }\n              else\n                m_method_flag = 21;\n            }\n          else\n            {\n              if (jacobian_type () == \"full\")\n                m_method_flag = 22;\n              else if (jacobian_type () == \"banded\")\n                m_method_flag = 25;\n              else if (jacobian_type () == \"diagonal\")\n                m_method_flag = 23;\n              else\n                {\n                  // should be prevented by lsode_options\n                  (*current_liboctave_error_handler)\n                    (\"lsode: internal error, wrong jacobian type\");\n                  m_integration_error = true;\n                  return retval;\n                }\n            }\n\n          m_liw = 20 + n;\n          m_lrw = 22 + n * (9 + n);\n        }\n      else\n        {\n          max_maxord = 12;\n\n          m_method_flag = 10;\n\n          m_liw = 20;\n          m_lrw = 22 + 16 * n;\n        }\n\n      m_iwork.resize (dim_vector (m_liw, 1));\n\n      for (F77_INT i = 4; i < 9; i++)\n        m_iwork(i) = 0;\n\n      m_rwork.resize (dim_vector (m_lrw, 1));\n\n      for (F77_INT i = 4; i < 9; i++)\n        m_rwork(i) = 0;\n\n      octave_idx_type maxord = maximum_order ();\n\n      if (maxord >= 0)\n        {\n          if (maxord > 0 && maxord <= max_maxord)\n            {\n              m_iwork(4) = octave::to_f77_int (maxord);\n              m_iopt = 1;\n            }\n          else\n            {\n              // FIXME: Should this be a warning?\n              (*current_liboctave_error_handler)\n                (\"lsode: invalid value for maximum order\");\n              m_integration_error = true;\n              return retval;\n            }\n        }\n\n      if (m_stop_time_set)\n        {\n          m_itask = 4;\n          m_rwork(0) = m_stop_time;\n          m_iopt = 1;\n        }\n      else\n        {\n          m_itask = 1;\n        }\n\n      m_restart = false;\n\n      // ODEFunc\n\n      // NOTE: this won't work if LSODE passes copies of the state vector.\n      //       In that case we have to create a temporary vector object\n      //       and copy.\n\n      tmp_x = &m_x;\n\n      user_fcn = function ();\n      user_jac = jacobian_function ();\n\n      ColumnVector m_xdot = (*user_fcn) (m_x, m_t);\n\n      if (m_x.numel () != m_xdot.numel ())\n        {\n          // FIXME: Should this be a warning?\n          (*current_liboctave_error_handler)\n            (\"lsode: inconsistent sizes for state and derivative vectors\");\n\n          m_integration_error = true;\n          return retval;\n        }\n\n      ODEFunc::m_reset = false;\n\n      // LSODE_options\n\n      m_rel_tol = relative_tolerance ();\n      m_abs_tol = absolute_tolerance ();\n\n      F77_INT abs_tol_len = octave::to_f77_int (m_abs_tol.numel ());\n\n      if (abs_tol_len == 1)\n        m_itol = 1;\n      else if (abs_tol_len == n)\n        m_itol = 2;\n      else\n        {\n          // FIXME: Should this be a warning?\n          (*current_liboctave_error_handler)\n            (\"lsode: inconsistent sizes for state and absolute tolerance vectors\");\n\n          m_integration_error = true;\n          return retval;\n        }\n\n      double iss = initial_step_size ();\n      if (iss >= 0.0)\n        {\n          m_rwork(4) = iss;\n          m_iopt = 1;\n        }\n\n      double maxss = maximum_step_size ();\n      if (maxss >= 0.0)\n        {\n          m_rwork(5) = maxss;\n          m_iopt = 1;\n        }\n\n      double minss = minimum_step_size ();\n      if (minss >= 0.0)\n        {\n          m_rwork(6) = minss;\n          m_iopt = 1;\n        }\n\n      F77_INT sl = octave::to_f77_int (step_limit ());\n      if (sl > 0)\n        {\n          m_iwork(5) = sl;\n          m_iopt = 1;\n        }\n\n      LSODE_options::m_reset = false;\n    }\n\n  double *px = m_x.rwdata ();\n\n  double *pabs_tol = m_abs_tol.rwdata ();\n\n  F77_INT *piwork = m_iwork.rwdata ();\n  double *prwork = m_rwork.rwdata ();\n\n  F77_INT tmp_istate = octave::to_f77_int (m_istate);\n\n  F77_XFCN (dlsode, DLSODE, (lsode_f, nn, px, m_t, tout, m_itol, m_rel_tol,\n                             pabs_tol, m_itask, tmp_istate, m_iopt, prwork,\n                             m_lrw, piwork, m_liw, lsode_j, m_method_flag));\n\n  m_istate = tmp_istate;\n\n  switch (m_istate)\n    {\n    case 1:  // prior to initial integration step.\n    case 2:  // lsode was successful.\n      retval = m_x;\n      m_t = tout;\n      break;\n\n    case -1:  // excess work done on this call (perhaps wrong mf).\n    case -2:  // excess accuracy requested (tolerances too small).\n    case -3:  // invalid input detected (see printed message).\n    case -4:  // repeated error test failures (check all inputs).\n    case -5:  // repeated convergence failures (perhaps bad Jacobian\n              // supplied or wrong choice of mf or tolerances).\n    case -6:  // error weight became zero during problem. (solution\n              // component i vanished, and atol or atol(i) = 0.)\n    case -13: // return requested in user-supplied function.\n      m_integration_error = true;\n      break;\n\n    default:\n      m_integration_error = true;\n      (*current_liboctave_error_handler)\n        (\"unrecognized value of istate (= %\" OCTAVE_IDX_TYPE_FORMAT \") \"\n         \"returned from lsode\", m_istate);\n      break;\n    }\n\n  return retval;\n}\n\nstd::string\nLSODE::error_message () const\n{\n  std::string retval;\n\n  std::ostringstream buf;\n  buf << m_t;\n  std::string t_curr = buf.str ();\n\n  switch (m_istate)\n    {\n    case 1:\n      retval = \"prior to initial integration step\";\n      break;\n\n    case 2:\n      retval = \"successful exit\";\n      break;\n\n    case 3:\n      retval = \"prior to continuation call with modified parameters\";\n      break;\n\n    case -1:\n      retval = \"excess work on this call (t = \" + t_curr +\n               \"; perhaps wrong integration method)\";\n      break;\n\n    case -2:\n      retval = \"excess accuracy requested (tolerances too small)\";\n      break;\n\n    case -3:\n      retval = \"invalid input detected (see printed message)\";\n      break;\n\n    case -4:\n      retval = \"repeated error test failures (t = \" + t_curr +\n               \"; check all inputs)\";\n      break;\n\n    case -5:\n      retval = \"repeated convergence failures (t = \" + t_curr +\n               \"; perhaps bad Jacobian supplied or wrong choice of integration method or tolerances)\";\n      break;\n\n    case -6:\n      retval = \"error weight became zero during problem. (t = \" + t_curr +\n               \"; solution component i vanished, and atol or atol(i) == 0)\";\n      break;\n\n    case -13:\n      retval = \"return requested in user-supplied function (t = \"\n               + t_curr + ')';\n      break;\n\n    default:\n      retval = \"unknown error state\";\n      break;\n    }\n\n  return retval;\n}\n\nMatrix\nLSODE::do_integrate (const ColumnVector& tout)\n{\n  Matrix retval;\n\n  octave_idx_type n_out = tout.numel ();\n  F77_INT n = octave::to_f77_int (size ());\n\n  if (n_out > 0 && n > 0)\n    {\n      retval.resize (n_out, n);\n\n      for (F77_INT i = 0; i < n; i++)\n        retval.elem (0, i) = m_x.elem (i);\n\n      for (octave_idx_type j = 1; j < n_out; j++)\n        {\n          ColumnVector x_next = do_integrate (tout.elem (j));\n\n          if (m_integration_error)\n            return retval;\n\n          for (F77_INT i = 0; i < n; i++)\n            retval.elem (j, i) = x_next.elem (i);\n        }\n    }\n\n  return retval;\n}\n\nMatrix\nLSODE::do_integrate (const ColumnVector& tout, const ColumnVector& tcrit)\n{\n  Matrix retval;\n\n  octave_idx_type n_out = tout.numel ();\n  F77_INT n = octave::to_f77_int (size ());\n\n  if (n_out > 0 && n > 0)\n    {\n      retval.resize (n_out, n);\n\n      for (F77_INT i = 0; i < n; i++)\n        retval.elem (0, i) = m_x.elem (i);\n\n      octave_idx_type n_crit = tcrit.numel ();\n\n      if (n_crit > 0)\n        {\n          octave_idx_type i_crit = 0;\n          octave_idx_type i_out = 1;\n          double next_crit = tcrit.elem (0);\n          double next_out;\n          while (i_out < n_out)\n            {\n              bool do_restart = false;\n\n              next_out = tout.elem (i_out);\n              if (i_crit < n_crit)\n                next_crit = tcrit.elem (i_crit);\n\n              bool save_output = false;\n              double t_out;\n\n              if (next_crit == next_out)\n                {\n                  set_stop_time (next_crit);\n                  t_out = next_out;\n                  save_output = true;\n                  i_out++;\n                  i_crit++;\n                  do_restart = true;\n                }\n              else if (next_crit < next_out)\n                {\n                  if (i_crit < n_crit)\n                    {\n                      set_stop_time (next_crit);\n                      t_out = next_crit;\n                      save_output = false;\n                      i_crit++;\n                      do_restart = true;\n                    }\n                  else\n                    {\n                      clear_stop_time ();\n                      t_out = next_out;\n                      save_output = true;\n                      i_out++;\n                    }\n                }\n              else\n                {\n                  set_stop_time (next_crit);\n                  t_out = next_out;\n                  save_output = true;\n                  i_out++;\n                }\n\n              ColumnVector x_next = do_integrate (t_out);\n\n              if (m_integration_error)\n                return retval;\n\n              if (save_output)\n                {\n                  for (F77_INT i = 0; i < n; i++)\n                    retval.elem (i_out-1, i) = x_next.elem (i);\n                }\n\n              if (do_restart)\n                force_restart ();\n            }\n        }\n      else\n        {\n          retval = do_integrate (tout);\n\n          if (m_integration_error)\n            return retval;\n        }\n    }\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/numeric/LSODE.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_LSODE_h)\n#define octave_LSODE_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"Array-oct.h\"\n#include \"LSODE-opts.h\"\n\nclass OCTAVE_API LSODE : public ODE, public LSODE_options\n{\npublic:\n\n  LSODE ()\n    : ODE (), LSODE_options (), m_initialized (false), m_method_flag (0),\n      m_itask (0), m_iopt (0), m_itol (0), m_liw (0), m_lrw (0),\n      m_iwork (), m_rwork (), m_rel_tol (0.0), m_abs_tol () { }\n\n  LSODE (const ColumnVector& s, double tm, const ODEFunc& f)\n    : ODE (s, tm, f), LSODE_options (), m_initialized (false),\n      m_method_flag (0), m_itask (0), m_iopt (0), m_itol (0), m_liw (0),\n      m_lrw (0), m_iwork (), m_rwork (), m_rel_tol (0.0), m_abs_tol () { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (LSODE)\n\n  ColumnVector do_integrate (double t);\n\n  Matrix do_integrate (const ColumnVector& tout);\n\n  Matrix do_integrate (const ColumnVector& tout, const ColumnVector& tcrit);\n\n  std::string error_message () const;\n\nprivate:\n\n  bool m_initialized;\n\n  octave_f77_int_type m_method_flag;\n  octave_f77_int_type m_itask;\n  octave_f77_int_type m_iopt;\n  octave_f77_int_type m_itol;\n\n  octave_f77_int_type m_liw;\n  octave_f77_int_type m_lrw;\n\n  Array<octave_f77_int_type> m_iwork;\n  Array<double> m_rwork;\n\n  double m_rel_tol;\n\n  Array<double> m_abs_tol;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/ODE.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ODE_h)\n#define octave_ODE_h 1\n\n#include \"octave-config.h\"\n\n#include \"ODEFunc.h\"\n#include \"base-de.h\"\n#include \"dMatrix.h\"\n\nclass ODE : public base_diff_eqn, public ODEFunc\n{\npublic:\n\n  ODE ()\n    : base_diff_eqn (), ODEFunc () { }\n\n  ODE (const ColumnVector& s, double tm, const ODEFunc& f)\n    : base_diff_eqn (s, tm), ODEFunc (f) { }\n\n  ODE (const ODE& a)\n    : base_diff_eqn (a), ODEFunc (a) { }\n\n  ODE& operator = (const ODE& a)\n  {\n    if (this != &a)\n      {\n        base_diff_eqn::operator = (a);\n        ODEFunc::operator = (a);\n      }\n    return *this;\n  }\n\n  virtual ~ODE () = default;\n\n  // Derived classes must provide functions to actually do the\n  // integration.\n\n  // Return the vector of states at output time t.\n  virtual ColumnVector do_integrate (double tt) = 0;\n\n  // Return a matrix of states at each output time specified by t.\n  // The rows of the result matrix should each correspond to a new\n  // output time.\n  virtual Matrix do_integrate (const ColumnVector& tt) = 0;\n\n  virtual Matrix do_integrate (const ColumnVector& tt,\n                               const ColumnVector& ttcrit) = 0;\n\n  // Lots of ways to call the single function and optionally set and\n  // get additional information.\n\n  // Integrate to t from current point.\n  virtual ColumnVector integrate (double tt)\n  { return do_integrate (tt); }\n\n  // Set new x0, t0 and integrate to t.\n  virtual ColumnVector integrate (const ColumnVector& x0, double t0, double tt)\n  {\n    initialize (x0, t0);\n    return do_integrate (tt);\n  }\n\n  // Integrate from current point and return output at all points\n  // specified by t.\n  virtual Matrix integrate (const ColumnVector& tt)\n  { return do_integrate (tt); }\n\n  // Set new x0, t0 and integrate to return output at all points\n  // specified by t.\n  virtual Matrix integrate (const ColumnVector& x0, double t0,\n                            const ColumnVector& tt)\n  {\n    initialize (x0, t0);\n    return do_integrate (tt);\n  }\n\n  // Integrate from current point and return output at all points\n  // specified by t.\n  virtual Matrix integrate (const ColumnVector& tt,\n                            const ColumnVector& ttcrit)\n  { return do_integrate (tt, ttcrit); }\n\n  // Set new x0, t0 and integrate to return output at all points\n  // specified by t.\n  virtual Matrix integrate (const ColumnVector& x0, double t0,\n                            const ColumnVector& tt,\n                            const ColumnVector& ttcrit)\n  {\n    initialize (x0, t0);\n    return do_integrate (tt, ttcrit);\n  }\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/ODEFunc.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ODEFunc_h)\n#define octave_ODEFunc_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\nclass ODEFunc\n{\npublic:\n\n  typedef ColumnVector (*ODERHSFunc) (const ColumnVector&, double);\n  typedef Matrix (*ODEJacFunc) (const ColumnVector&, double);\n\n  ODEFunc ()\n    : m_fcn (nullptr), m_jac (nullptr), m_reset (true) { }\n\n  ODEFunc (ODERHSFunc f)\n    : m_fcn (f), m_jac (nullptr), m_reset (true) { }\n\n  ODEFunc (ODERHSFunc f, ODEJacFunc j)\n    : m_fcn (f), m_jac (j), m_reset (true) { }\n\n  ODEFunc (const ODEFunc& a)\n    : m_fcn (a.m_fcn), m_jac (a.m_jac), m_reset (true) { }\n\n  ODEFunc& operator = (const ODEFunc& a)\n  {\n    if (this != &a)\n      {\n        m_fcn = a.m_fcn;\n        m_jac = a.m_jac;\n        m_reset = a.m_reset;\n      }\n    return *this;\n  }\n\n  virtual ~ODEFunc () = default;\n\n  ODERHSFunc function () const { return m_fcn; }\n\n  ODEFunc& set_function (ODERHSFunc f)\n  {\n    m_fcn = f;\n    m_reset = true;\n    return *this;\n  }\n\n  ODEJacFunc jacobian_function () const { return m_jac; }\n\n  ODEFunc& set_jacobian_function (ODEJacFunc j)\n  {\n    m_jac = j;\n    m_reset = true;\n    return *this;\n  }\n\nprotected:\n\n  ODERHSFunc m_fcn;\n  ODEJacFunc m_jac;\n\n  // This variable is TRUE when this object is constructed, and also\n  // after any internal data has changed.  Derived classes may use\n  // this information (and change it) to know when to (re)initialize\n  // their own internal data related to this object.\n\n  bool m_reset;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/ODES.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"ODES.h\"\n\nvoid\nODES::initialize (const ColumnVector& xx, double tt)\n{\n  base_diff_eqn::initialize (xx, tt);\n  m_xdot = ColumnVector (xx.numel (), 0.0);\n}\n\nvoid\nODES::initialize (const ColumnVector& xx, double tt,\n                  const ColumnVector& xtheta)\n{\n  base_diff_eqn::initialize (xx, tt);\n  m_xdot = ColumnVector (xx.numel (), 0.0);\n  m_theta = xtheta;\n}\n"
  },
  {
    "path": "liboctave/numeric/ODES.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ODES_h)\n#define octave_ODES_h 1\n\n#include \"octave-config.h\"\n\n#include \"ODESFunc.h\"\n#include \"base-de.h\"\n\nclass ODES : public base_diff_eqn, public ODESFunc\n{\npublic:\n\n  ODES ()\n    : base_diff_eqn (), ODESFunc (), m_xdot (), m_theta () { }\n\n  ODES (const ColumnVector& s, double tm, ODESFunc& f)\n    : base_diff_eqn (s, tm), ODESFunc (f), m_xdot (s.numel (), 0.0), m_theta ()\n  { }\n\n  ODES (const ColumnVector& s, const ColumnVector& xtheta, double tm,\n        ODESFunc& f)\n    : base_diff_eqn (s, tm), ODESFunc (f), m_xdot (s.numel (), 0.0),\n      m_theta (xtheta) { }\n\n  ODES (const ODES& a)\n    : base_diff_eqn (a), ODESFunc (a), m_xdot (a.m_xdot), m_theta (a.m_theta)\n  { }\n\n  ODES& operator = (const ODES& a)\n  {\n    if (this != &a)\n      {\n        base_diff_eqn::operator = (a);\n        ODESFunc::operator = (a);\n\n        m_xdot = a.m_xdot;\n        m_theta = a.m_theta;\n      }\n    return *this;\n  }\n\n  ~ODES () = default;\n\n  ColumnVector parameter_vector () { return m_theta; }\n\n  OCTAVE_API void initialize (const ColumnVector& x, double t);\n\n  OCTAVE_API void\n  initialize (const ColumnVector& x, double t, const ColumnVector& theta);\n\nprotected:\n\n  // State vector time derivatives.\n  ColumnVector m_xdot;\n\n  // Parameter vector.\n  ColumnVector m_theta;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/ODESFunc.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ODESFunc_h)\n#define octave_ODESFunc_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\n#include \"dMatrix.h\"\n\nclass ODESFunc\n{\npublic:\n\n  struct DAEJac\n  {\n    Matrix *dfdxdot;\n    Matrix *dfdx;\n  };\n\n  typedef ColumnVector (*ODES_fsub) (const ColumnVector& x, double,\n                                     const ColumnVector& theta);\n\n  typedef ColumnVector (*ODES_bsub) (const ColumnVector& x, double,\n                                     const ColumnVector& theta, int column);\n\n  typedef Matrix (*ODES_jsub) (const ColumnVector& x, double,\n                               const ColumnVector& theta);\n\n  ODESFunc ()\n    : m_fsub (nullptr), m_bsub (nullptr), m_jsub (nullptr) { }\n\n  ODESFunc (ODES_fsub f)\n    : m_fsub (f), m_bsub (nullptr), m_jsub (nullptr) { }\n\n  ODESFunc (ODES_fsub f, ODES_bsub b)\n    : m_fsub (f), m_bsub (b), m_jsub (nullptr) { }\n\n  ODESFunc (ODES_fsub f, ODES_bsub b, ODES_jsub j)\n    : m_fsub (f), m_bsub (b), m_jsub (j) { }\n\n  ODESFunc (const ODESFunc& a)\n    : m_fsub (a.m_fsub), m_bsub (a.m_bsub), m_jsub (a.m_jsub) { }\n\n  ODESFunc& operator = (const ODESFunc& a)\n  {\n    if (this != &a)\n      {\n        m_fsub = a.m_fsub;\n        m_bsub = a.m_bsub;\n        m_jsub = a.m_jsub;\n      }\n    return *this;\n  }\n\n  virtual ~ODESFunc () = default;\n\n  ODES_fsub fsub_function () const { return m_fsub; }\n\n  ODESFunc& set_fsub_function (ODES_fsub f)\n  {\n    m_fsub = f;\n    return *this;\n  }\n\n  ODES_bsub bsub_function () const { return m_bsub; }\n\n  ODESFunc& set_bsub_function (ODES_bsub b)\n  {\n    m_bsub = b;\n    return *this;\n  }\n\n  ODES_jsub jsub_function () const { return m_jsub; }\n\n  ODESFunc& set_jsub_function (ODES_jsub j)\n  {\n    m_jsub = j;\n    return *this;\n  }\n\nprotected:\n\n  ODES_fsub m_fsub;\n  ODES_bsub m_bsub;\n  ODES_jsub m_jsub;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/Quad-opts.in",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nCLASS = \"Quad\"\n\nOPTION\n  NAME = \"absolute tolerance\"\n  DOC_ITEM\nAbsolute tolerance; may be zero for pure relative error test.\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"::sqrt (std::numeric_limits<double>::epsilon ())\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"relative tolerance\"\n  DOC_ITEM\nNon-negative relative tolerance.  If the absolute tolerance is zero,\nthe relative tolerance must be greater than or equal to\n@w{@code{max (50*eps, 0.5e-28)}}.\n\n  END_DOC_ITEM\n  TYPE = \"double\"\n  INIT_VALUE = \"::sqrt (std::numeric_limits<double>::epsilon ())\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"single precision absolute tolerance\"\n  DOC_ITEM\nAbsolute tolerance for single precision; may be zero for pure relative\nerror test.\n\n  END_DOC_ITEM\n  TYPE = \"float\"\n  INIT_VALUE = \"::sqrt (std::numeric_limits<float>::epsilon ())\"\n  SET_EXPR = \"val\"\nEND_OPTION\n\nOPTION\n  NAME = \"single precision relative tolerance\"\n  DOC_ITEM\nNon-negative relative tolerance for single precision.  If the absolute\ntolerance is zero, the relative tolerance must be greater than or equal to\n@w{@code{max (50*eps, 0.5e-28)}}.\n  END_DOC_ITEM\n  TYPE = \"float\"\n  INIT_VALUE = \"::sqrt (std::numeric_limits<float>::epsilon ())\"\n  SET_EXPR = \"val\"\nEND_OPTION\n"
  },
  {
    "path": "liboctave/numeric/Quad.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-oct.h\"\n#include \"Quad.h\"\n#include \"f77-fcn.h\"\n#include \"oct-error.h\"\n#include \"quit.h\"\n\nstatic integrand_fcn user_fcn;\nstatic float_integrand_fcn float_user_fcn;\n\ntypedef F77_INT (*quad_fcn_ptr) (const double&, int&, double&);\ntypedef F77_INT (*quad_float_fcn_ptr) (const float&, int&, float&);\n\nextern \"C\"\n{\n  F77_RET_T\n  F77_FUNC (dqagp, DQAGP) (quad_fcn_ptr, const F77_DBLE&, const F77_DBLE&,\n                           const F77_INT&, const F77_DBLE *,\n                           const F77_DBLE&, const F77_DBLE&, F77_DBLE&,\n                           F77_DBLE&, F77_INT&, F77_INT&,\n                           const F77_INT&, const F77_INT&,\n                           F77_INT&, F77_INT *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (dqagi, DQAGI) (quad_fcn_ptr, const F77_DBLE&,\n                           const F77_INT&, const F77_DBLE&,\n                           const F77_DBLE&, F77_DBLE&, F77_DBLE&,\n                           F77_INT&, F77_INT&,\n                           const F77_INT&, const F77_INT&,\n                           F77_INT&, F77_INT *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (qagp, QAGP) (quad_float_fcn_ptr, const F77_REAL&, const F77_REAL&,\n                         const F77_INT&, const F77_REAL *, const F77_REAL&,\n                         const F77_REAL&, F77_REAL&, F77_REAL&, F77_INT&,\n                         F77_INT&, const F77_INT&,\n                         const F77_INT&, F77_INT&,\n                         F77_INT *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (qagi, QAGI) (quad_float_fcn_ptr, const F77_REAL&,\n                         const F77_INT&, const F77_REAL&,\n                         const F77_REAL&, F77_REAL&, F77_REAL&, F77_INT&,\n                         F77_INT&, const F77_INT&,\n                         const F77_INT&, F77_INT&,\n                         F77_INT *, F77_REAL *);\n}\n\nstatic F77_INT\nuser_function (const double& x, int&, double& result)\n{\n  result = (*user_fcn) (x);\n\n  return 0;\n}\n\nstatic F77_INT\nfloat_user_function (const float& x, int&, float& result)\n{\n  result = (*float_user_fcn) (x);\n\n  return 0;\n}\n\ndouble\nDefQuad::do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                       double& abserr)\n{\n  F77_INT npts = octave::to_f77_int (m_singularities.numel () + 2);\n  double *points = m_singularities.rwdata ();\n  double result = 0.0;\n\n  F77_INT leniw = 183*npts - 122;\n  Array<F77_INT> iwork (dim_vector (leniw, 1));\n  F77_INT *piwork = iwork.rwdata ();\n\n  F77_INT lenw = 2*leniw - npts;\n  Array<double> work (dim_vector (lenw, 1));\n  double *pwork = work.rwdata ();\n\n  user_fcn = m_f;\n  F77_INT last;\n\n  double abs_tol = absolute_tolerance ();\n  double rel_tol = relative_tolerance ();\n\n  // NEVAL and IER are output only parameters and F77_INT can not be a\n  // wider type than octave_idx_type so we can create local variables\n  // here that are the correct type for the Fortran subroutine and then\n  // copy them to the function parameters without needing to preserve\n  // and pass the values to the Fortran subroutine.\n\n  F77_INT xneval, xier;\n\n  F77_XFCN (dqagp, DQAGP, (user_function, m_lower_limit, m_upper_limit,\n                           npts, points, abs_tol, rel_tol, result,\n                           abserr, xneval, xier, leniw, lenw, last,\n                           piwork, pwork));\n\n  neval = xneval;\n  ier = xier;\n\n  return result;\n}\n\nfloat\nDefQuad::do_integrate (octave_idx_type&, octave_idx_type&, float&)\n{\n  (*current_liboctave_error_handler) (\"incorrect integration function called\");\n}\n\ndouble\nIndefQuad::do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                         double& abserr)\n{\n  double result = 0.0;\n\n  F77_INT leniw = 128;\n  Array<F77_INT> iwork (dim_vector (leniw, 1));\n  F77_INT *piwork = iwork.rwdata ();\n\n  F77_INT lenw = 8*leniw;\n  Array<double> work (dim_vector (lenw, 1));\n  double *pwork = work.rwdata ();\n\n  user_fcn = m_f;\n  F77_INT last;\n\n  F77_INT inf;\n  switch (m_type)\n    {\n    case bound_to_inf:\n      inf = 1;\n      break;\n\n    case neg_inf_to_bound:\n      inf = -1;\n      break;\n\n    case doubly_infinite:\n      inf = 2;\n      break;\n\n      // We should have handled all possible enum values above.  Rely on\n      // compiler diagnostics to warn if we haven't.  For example, GCC's\n      // -Wswitch option, enabled by -Wall, will provide a warning.\n    }\n\n  double abs_tol = absolute_tolerance ();\n  double rel_tol = relative_tolerance ();\n\n  // NEVAL and IER are output only parameters and F77_INT can not be a\n  // wider type than octave_idx_type so we can create local variables\n  // here that are the correct type for the Fortran subroutine and then\n  // copy them to the function parameters without needing to preserve\n  // and pass the values to the Fortran subroutine.\n\n  F77_INT xneval, xier;\n\n  F77_XFCN (dqagi, DQAGI, (user_function, m_bound, inf, abs_tol, rel_tol,\n                           result, abserr, xneval, xier, leniw, lenw,\n                           last, piwork, pwork));\n\n  neval = xneval;\n  ier = xier;\n\n  return result;\n}\n\nfloat\nIndefQuad::do_integrate (octave_idx_type&, octave_idx_type&, float&)\n{\n  (*current_liboctave_error_handler) (\"incorrect integration function called\");\n}\n\ndouble\nFloatDefQuad::do_integrate (octave_idx_type&, octave_idx_type&, double&)\n{\n  (*current_liboctave_error_handler) (\"incorrect integration function called\");\n}\n\nfloat\nFloatDefQuad::do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                            float& abserr)\n{\n  F77_INT npts = octave::to_f77_int (m_singularities.numel () + 2);\n  float *points = m_singularities.rwdata ();\n  float result = 0.0;\n\n  F77_INT leniw = 183*npts - 122;\n  Array<F77_INT> iwork (dim_vector (leniw, 1));\n  F77_INT *piwork = iwork.rwdata ();\n\n  F77_INT lenw = 2*leniw - npts;\n  Array<float> work (dim_vector (lenw, 1));\n  float *pwork = work.rwdata ();\n\n  float_user_fcn = m_ff;\n  F77_INT last;\n\n  float abs_tol = single_precision_absolute_tolerance ();\n  float rel_tol = single_precision_relative_tolerance ();\n\n  // NEVAL and IER are output only parameters and F77_INT can not be a\n  // wider type than octave_idx_type so we can create local variables\n  // here that are the correct type for the Fortran subroutine and then\n  // copy them to the function parameters without needing to preserve\n  // and pass the values to the Fortran subroutine.\n\n  F77_INT xneval, xier;\n\n  F77_XFCN (qagp, QAGP, (float_user_function, m_lower_limit, m_upper_limit,\n                         npts, points, abs_tol, rel_tol, result,\n                         abserr, xneval, xier, leniw, lenw, last,\n                         piwork, pwork));\n\n  neval = xneval;\n  ier = xier;\n\n  return result;\n}\n\ndouble\nFloatIndefQuad::do_integrate (octave_idx_type&, octave_idx_type&, double&)\n{\n  (*current_liboctave_error_handler) (\"incorrect integration function called\");\n}\n\nfloat\nFloatIndefQuad::do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                              float& abserr)\n{\n  float result = 0.0;\n\n  F77_INT leniw = 128;\n  Array<F77_INT> iwork (dim_vector (leniw, 1));\n  F77_INT *piwork = iwork.rwdata ();\n\n  F77_INT lenw = 8*leniw;\n  Array<float> work (dim_vector (lenw, 1));\n  float *pwork = work.rwdata ();\n\n  float_user_fcn = m_ff;\n  F77_INT last;\n\n  F77_INT inf;\n  switch (m_type)\n    {\n    case bound_to_inf:\n      inf = 1;\n      break;\n\n    case neg_inf_to_bound:\n      inf = -1;\n      break;\n\n    case doubly_infinite:\n      inf = 2;\n      break;\n\n      // We should have handled all possible enum values above.  Rely on\n      // compiler diagnostics to warn if we haven't.  For example, GCC's\n      // -Wswitch option, enabled by -Wall, will provide a warning.\n    }\n\n  float abs_tol = single_precision_absolute_tolerance ();\n  float rel_tol = single_precision_relative_tolerance ();\n\n  // NEVAL and IER are output only parameters and F77_INT can not be a\n  // wider type than octave_idx_type so we can create local variables\n  // here that are the correct type for the Fortran subroutine and then\n  // copy them to the function parameters without needing to preserve\n  // and pass the values to the Fortran subroutine.\n\n  F77_INT xneval, xier;\n\n  F77_XFCN (qagi, QAGI, (float_user_function, m_bound, inf, abs_tol, rel_tol,\n                         result, abserr, xneval, xier, leniw, lenw,\n                         last, piwork, pwork));\n\n  neval = xneval;\n  ier = xier;\n\n  return result;\n}\n"
  },
  {
    "path": "liboctave/numeric/Quad.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Quad_h)\n#define octave_Quad_h 1\n\n#include \"octave-config.h\"\n\n#include \"dColVector.h\"\n#include \"fColVector.h\"\n\ntypedef double (*integrand_fcn) (double x);\ntypedef float (*float_integrand_fcn) (float x);\n\n#include \"Quad-opts.h\"\n\nclass OCTAVE_API Quad : public Quad_options\n{\npublic:\n\n  Quad () = delete;\n\n  Quad (integrand_fcn fcn)\n    : Quad_options (), m_f (fcn), m_ff () { }\n\n  Quad (float_integrand_fcn fcn)\n    : Quad_options (), m_f (), m_ff (fcn) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE (Quad)\n\n  virtual ~Quad () = default;\n\n  virtual double integrate ()\n  {\n    octave_idx_type ier, neval;\n    double abserr;\n    return do_integrate (ier, neval, abserr);\n  }\n\n  virtual float float_integrate ()\n  {\n    octave_idx_type ier, neval;\n    float abserr;\n    return do_integrate (ier, neval, abserr);\n  }\n\n  virtual double integrate (octave_idx_type& ier)\n  {\n    octave_idx_type neval;\n    double abserr;\n    return do_integrate (ier, neval, abserr);\n  }\n\n  virtual float float_integrate (octave_idx_type& ier)\n  {\n    octave_idx_type neval;\n    float abserr;\n    return do_integrate (ier, neval, abserr);\n  }\n\n  virtual double integrate (octave_idx_type& ier, octave_idx_type& neval)\n  {\n    double abserr;\n    return do_integrate (ier, neval, abserr);\n  }\n\n  virtual float float_integrate (octave_idx_type& ier, octave_idx_type& neval)\n  {\n    float abserr;\n    return do_integrate (ier, neval, abserr);\n  }\n\n  virtual double integrate (octave_idx_type& ier, octave_idx_type& neval,\n                            double& abserr)\n  {\n    return do_integrate (ier, neval, abserr);\n  }\n\n  virtual float float_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                                 float& abserr)\n  {\n    return do_integrate (ier, neval, abserr);\n  }\n\n  virtual double do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                               double& abserr) = 0;\n\n  virtual float do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                              float& abserr) = 0;\n\nprotected:\n\n  integrand_fcn m_f;\n  float_integrand_fcn m_ff;\n};\n\nclass OCTAVE_API DefQuad : public Quad\n{\npublic:\n\n  DefQuad () = delete;\n\n  DefQuad (integrand_fcn fcn)\n    : Quad (fcn), m_lower_limit (0.0), m_upper_limit (1.0), m_singularities ()\n  { }\n\n  DefQuad (integrand_fcn fcn, double ll, double ul)\n    : Quad (fcn), m_lower_limit (ll), m_upper_limit (ul), m_singularities ()\n  { }\n\n  DefQuad (integrand_fcn fcn, double ll, double ul,\n           const ColumnVector& sing)\n    : Quad (fcn), m_lower_limit (ll), m_upper_limit (ul),\n      m_singularities (sing) { }\n\n  DefQuad (integrand_fcn fcn, const ColumnVector& sing)\n    : Quad (fcn), m_lower_limit (0.0), m_upper_limit (1.0),\n      m_singularities (sing) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (DefQuad)\n\n  double do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                       double& abserr);\n\n  OCTAVE_NORETURN float do_integrate (octave_idx_type& ier,\n                                      octave_idx_type& neval, float& abserr);\n\nprivate:\n\n  double m_lower_limit;\n  double m_upper_limit;\n\n  ColumnVector m_singularities;\n};\n\nclass OCTAVE_API IndefQuad : public Quad\n{\npublic:\n\n  enum IntegralType { bound_to_inf, neg_inf_to_bound, doubly_infinite };\n\n  IndefQuad () = delete;\n\n  IndefQuad (integrand_fcn fcn)\n    : Quad (fcn), m_bound (0.0), m_type (bound_to_inf) { }\n\n  IndefQuad (integrand_fcn fcn, double b, IntegralType t)\n    : Quad (fcn), m_bound (b), m_type (t) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (IndefQuad)\n\n  double do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                       double& abserr);\n\n  OCTAVE_NORETURN float do_integrate (octave_idx_type& ier,\n                                      octave_idx_type& neval, float& abserr);\n\nprivate:\n\n  double m_bound;\n  IntegralType m_type;\n};\n\nclass OCTAVE_API FloatDefQuad : public Quad\n{\npublic:\n\n  FloatDefQuad () = delete;\n\n  FloatDefQuad (float_integrand_fcn fcn)\n    : Quad (fcn), m_lower_limit (0.0), m_upper_limit (1.0), m_singularities ()\n  { }\n\n  FloatDefQuad (float_integrand_fcn fcn, float ll, float ul)\n    : Quad (fcn), m_lower_limit (ll), m_upper_limit (ul), m_singularities ()\n  { }\n\n  FloatDefQuad (float_integrand_fcn fcn, float ll, float ul,\n                const FloatColumnVector& sing)\n    : Quad (fcn), m_lower_limit (ll), m_upper_limit (ul),\n      m_singularities (sing) { }\n\n  FloatDefQuad (float_integrand_fcn fcn, const FloatColumnVector& sing)\n    : Quad (fcn), m_lower_limit (0.0), m_upper_limit (1.0),\n      m_singularities (sing) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (FloatDefQuad)\n\n  OCTAVE_NORETURN double do_integrate (octave_idx_type& ier,\n                                       octave_idx_type& neval, double& abserr);\n\n  float do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                      float& abserr);\n\nprivate:\n\n  float m_lower_limit;\n  float m_upper_limit;\n\n  FloatColumnVector m_singularities;\n};\n\nclass OCTAVE_API FloatIndefQuad : public Quad\n{\npublic:\n\n  enum IntegralType { bound_to_inf, neg_inf_to_bound, doubly_infinite };\n\n  FloatIndefQuad () = delete;\n\n  FloatIndefQuad (float_integrand_fcn fcn)\n    : Quad (fcn), m_bound (0.0), m_type (bound_to_inf) { }\n\n  FloatIndefQuad (float_integrand_fcn fcn, double b, IntegralType t)\n    : Quad (fcn), m_bound (b), m_type (t) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (FloatIndefQuad)\n\n  OCTAVE_NORETURN double do_integrate (octave_idx_type& ier,\n                                       octave_idx_type& neval, double& abserr);\n\n  float do_integrate (octave_idx_type& ier, octave_idx_type& neval,\n                      float& abserr);\n\nprivate:\n\n  float m_bound;\n  IntegralType m_type;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/aepbalance.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"CMatrix.h\"\n#include \"aepbalance.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"fColVector.h\"\n#include \"fMatrix.h\"\n#include \"lapack-proto.h\"\n#include \"oct-error.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic inline char\nget_job (bool noperm, bool noscal)\n{\n  return noperm ? (noscal ? 'N' : 'S') : (noscal ? 'P' : 'B');\n}\n\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <>\nOCTAVE_API\naepbalance<Matrix>::aepbalance (const Matrix& a, bool noperm, bool noscal)\n  : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (),\n    m_job (get_job (noperm, noscal))\n{\n  F77_INT n = to_f77_int (a.cols ());\n\n  if (a.rows () != n)\n    (*current_liboctave_error_handler)\n      (\"aepbalance: requires square matrix\");\n\n  m_scale = ColumnVector (n);\n\n  F77_INT info, t_ilo, t_ihi;\n\n  F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n,\n                             m_balanced_mat.rwdata (), n,\n                             t_ilo, t_ihi, m_scale.rwdata (), info\n                             F77_CHAR_ARG_LEN (1)));\n\n  m_ilo = t_ilo;\n  m_ihi = t_ihi;\n}\n\ntemplate <>\nOCTAVE_API Matrix\naepbalance<Matrix>::balancing_matrix () const\n{\n  F77_INT n = to_f77_int (m_balanced_mat.rows ());\n\n  Matrix balancing_mat (n, n, 0.0);\n  for (F77_INT i = 0; i < n; i++)\n    balancing_mat.elem (i, i) = 1.0;\n\n  F77_INT info;\n  F77_INT t_ilo = to_f77_int (m_ilo);\n  F77_INT t_ihi = to_f77_int (m_ihi);\n\n  char side = 'R';\n\n  F77_XFCN (dgebak, DGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1),\n                             F77_CONST_CHAR_ARG2 (&side, 1),\n                             n, t_ilo, t_ihi, m_scale.data (), n,\n                             balancing_mat.rwdata (), n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  return balancing_mat;\n}\n\ntemplate <>\nOCTAVE_API\naepbalance<FloatMatrix>::aepbalance (const FloatMatrix& a, bool noperm,\n                                     bool noscal)\n  : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (),\n    m_job (get_job (noperm, noscal))\n{\n  F77_INT n = to_f77_int (a.cols ());\n\n  if (a.rows () != n)\n    (*current_liboctave_error_handler)\n      (\"aepbalance: requires square matrix\");\n\n  m_scale = FloatColumnVector (n);\n\n  F77_INT info, t_ilo, t_ihi;\n\n  F77_XFCN (sgebal, SGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n,\n                             m_balanced_mat.rwdata (), n, t_ilo,\n                             t_ihi, m_scale.rwdata (), info\n                             F77_CHAR_ARG_LEN (1)));\n\n  m_ilo = t_ilo;\n  m_ihi = t_ihi;\n}\n\ntemplate <>\nOCTAVE_API FloatMatrix\naepbalance<FloatMatrix>::balancing_matrix () const\n{\n  F77_INT n = to_f77_int (m_balanced_mat.rows ());\n\n  FloatMatrix balancing_mat (n, n, 0.0);\n  for (F77_INT i = 0; i < n; i++)\n    balancing_mat.elem (i, i) = 1.0;\n\n  F77_INT info;\n  F77_INT t_ilo = to_f77_int (m_ilo);\n  F77_INT t_ihi = to_f77_int (m_ihi);\n\n  char side = 'R';\n\n  F77_XFCN (sgebak, SGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1),\n                             F77_CONST_CHAR_ARG2 (&side, 1),\n                             n, t_ilo, t_ihi, m_scale.data (), n,\n                             balancing_mat.rwdata (), n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  return balancing_mat;\n}\n\ntemplate <>\nOCTAVE_API\naepbalance<ComplexMatrix>::aepbalance (const ComplexMatrix& a, bool noperm,\n                                       bool noscal)\n  : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (),\n    m_job (get_job (noperm, noscal))\n{\n  F77_INT n = to_f77_int (a.cols ());\n\n  if (a.rows () != n)\n    (*current_liboctave_error_handler)\n      (\"aepbalance: requires square matrix\");\n\n  m_scale = ColumnVector (n);\n\n  F77_INT info, t_ilo, t_ihi;\n\n  F77_XFCN (zgebal, ZGEBAL,\n            (F77_CONST_CHAR_ARG2 (&m_job, 1), n,\n             F77_DBLE_CMPLX_ARG (m_balanced_mat.rwdata ()),\n             n, t_ilo, t_ihi, m_scale.rwdata (), info\n             F77_CHAR_ARG_LEN (1)));\n\n  m_ilo = t_ilo;\n  m_ihi = t_ihi;\n}\n\ntemplate <>\nOCTAVE_API ComplexMatrix\naepbalance<ComplexMatrix>::balancing_matrix () const\n{\n  F77_INT n = to_f77_int (m_balanced_mat.rows ());\n\n  ComplexMatrix balancing_mat (n, n, 0.0);\n  for (F77_INT i = 0; i < n; i++)\n    balancing_mat.elem (i, i) = 1.0;\n\n  F77_INT info;\n  F77_INT t_ilo = to_f77_int (m_ilo);\n  F77_INT t_ihi = to_f77_int (m_ihi);\n\n  char side = 'R';\n\n  F77_XFCN (zgebak, ZGEBAK,\n            (F77_CONST_CHAR_ARG2 (&m_job, 1),\n             F77_CONST_CHAR_ARG2 (&side, 1),\n             n, t_ilo, t_ihi, m_scale.data (), n,\n             F77_DBLE_CMPLX_ARG (balancing_mat.rwdata ()),\n             n, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)));\n\n  return balancing_mat;\n}\n\ntemplate <>\nOCTAVE_API\naepbalance<FloatComplexMatrix>::aepbalance (const FloatComplexMatrix& a,\n    bool noperm, bool noscal)\n  : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (),\n    m_job (get_job (noperm, noscal))\n{\n  F77_INT n = to_f77_int (a.cols ());\n\n  if (a.rows () != n)\n    (*current_liboctave_error_handler)\n      (\"aepbalance: requires square matrix\");\n\n  m_scale = FloatColumnVector (n);\n\n  F77_INT info, t_ilo, t_ihi;\n\n  F77_XFCN (cgebal, CGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n,\n                             F77_CMPLX_ARG (m_balanced_mat.rwdata ()),\n                             n, t_ilo, t_ihi, m_scale.rwdata (), info\n                             F77_CHAR_ARG_LEN (1)));\n\n  m_ilo = t_ilo;\n  m_ihi = t_ihi;\n}\n\ntemplate <>\nOCTAVE_API FloatComplexMatrix\naepbalance<FloatComplexMatrix>::balancing_matrix () const\n{\n  F77_INT n = to_f77_int (m_balanced_mat.rows ());\n\n  FloatComplexMatrix balancing_mat (n, n, 0.0);\n  for (F77_INT i = 0; i < n; i++)\n    balancing_mat.elem (i, i) = 1.0;\n\n  F77_INT info;\n  F77_INT t_ilo = to_f77_int (m_ilo);\n  F77_INT t_ihi = to_f77_int (m_ihi);\n\n  char side = 'R';\n\n  F77_XFCN (cgebak, CGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1),\n                             F77_CONST_CHAR_ARG2 (&side, 1),\n                             n, t_ilo, t_ihi, m_scale.data (), n,\n                             F77_CMPLX_ARG (balancing_mat.rwdata ()),\n                             n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  return balancing_mat;\n}\n\n// Instantiations we need.\n\ntemplate class aepbalance<Matrix>;\n\ntemplate class aepbalance<FloatMatrix>;\n\ntemplate class aepbalance<ComplexMatrix>;\n\ntemplate class aepbalance<FloatComplexMatrix>;\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/aepbalance.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_aepbalance_h)\n#define octave_aepbalance_h 1\n\n#include \"octave-config.h\"\n\n#include <algorithm>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename MT>\nclass aepbalance\n{\npublic:\n\n  typedef typename MT::real_column_vector_type VT;\n\n  aepbalance () : m_balanced_mat (), m_scale (), m_ilo (), m_ihi (), m_job () { }\n\n  OCTAVE_API aepbalance (const MT& a, bool noperm = false, bool noscal = false);\n\n  aepbalance (const aepbalance& a)\n    : m_balanced_mat (a.m_balanced_mat), m_scale (a.m_scale),\n      m_ilo(a.m_ilo), m_ihi(a.m_ihi), m_job(a.m_job)\n  { }\n\n  aepbalance& operator = (const aepbalance& a)\n  {\n    if (this != &a)\n      {\n        m_balanced_mat = a.m_balanced_mat;\n        m_scale = a.m_scale;\n        m_ilo = a.m_ilo;\n        m_ihi = a.m_ihi;\n        m_job = a.m_job;\n      }\n\n    return *this;\n  }\n\n  virtual ~aepbalance () = default;\n\n  OCTAVE_API MT balancing_matrix () const;\n\n  MT balanced_matrix () const\n  {\n    return m_balanced_mat;\n  }\n\n  VT permuting_vector () const\n  {\n    octave_idx_type n = m_balanced_mat.rows ();\n\n    VT pv (n);\n\n    for (octave_idx_type i = 0; i < n; i++)\n      pv(i) = i+1;\n\n    for (octave_idx_type i = n-1; i >= m_ihi; i--)\n      {\n        octave_idx_type j = m_scale(i) - 1;\n        std::swap (pv(i), pv(j));\n      }\n\n    for (octave_idx_type i = 0; i < m_ilo-1; i++)\n      {\n        octave_idx_type j = m_scale(i) - 1;\n        std::swap (pv(i), pv(j));\n      }\n\n    return pv;\n  }\n\n  VT scaling_vector () const\n  {\n    octave_idx_type n = m_balanced_mat.rows ();\n\n    VT scv (n);\n\n    for (octave_idx_type i = 0; i < m_ilo-1; i++)\n      scv(i) = 1;\n\n    for (octave_idx_type i = m_ilo-1; i < m_ihi; i++)\n      scv(i) = m_scale(i);\n\n    for (octave_idx_type i = m_ihi; i < n; i++)\n      scv(i) = 1;\n\n    return scv;\n  }\n\nprotected:\n\n  MT m_balanced_mat;\n  VT m_scale;\n  octave_idx_type m_ilo;\n  octave_idx_type m_ihi;\n  char m_job;\n};\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/amos-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_amos_proto_h)\n#define octave_amos_proto_h 1\n\n#include \"octave-config.h\"\n\n#include \"f77-fcn.h\"\n\nextern \"C\"\n{\n  // AIRY\n\n  F77_RET_T\n  F77_FUNC (cairy, CAIRY) (const F77_CMPLX *, const F77_INT&,\n                           const F77_INT&, F77_CMPLX *,\n                           F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zairy, ZAIRY) (const F77_DBLE&, const F77_DBLE&,\n                           const F77_INT&, const F77_INT&,\n                           F77_DBLE&, F77_DBLE&, F77_INT&,\n                           F77_INT&);\n\n  // BESH\n\n  F77_RET_T\n  F77_FUNC (cbesh, CBESH) (const F77_CMPLX *, const F77_REAL&,\n                           const F77_INT&, const F77_INT&,\n                           const F77_INT&, F77_CMPLX *,\n                           F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zbesh, ZBESH) (const F77_DBLE&, const F77_DBLE&, const F77_DBLE&,\n                           const F77_INT&, const F77_INT&,\n                           const F77_INT&, F77_DBLE *, F77_DBLE *,\n                           F77_INT&, F77_INT&);\n\n  // BESI\n\n  F77_RET_T\n  F77_FUNC (cbesi, CBESI) (const F77_CMPLX *, const F77_REAL&,\n                           const F77_INT&, const F77_INT&,\n                           F77_CMPLX *, F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zbesi, ZBESI) (const F77_DBLE&, const F77_DBLE&, const F77_DBLE&,\n                           const F77_INT&, const F77_INT&,\n                           F77_DBLE *, F77_DBLE *, F77_INT&,\n                           F77_INT&);\n\n  // BESJ\n\n  F77_RET_T\n  F77_FUNC (cbesj, CBESJ) (const F77_CMPLX *, const F77_REAL&,\n                           const F77_INT&, const F77_INT&,\n                           F77_CMPLX *, F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zbesj, ZBESJ) (const F77_DBLE&, const F77_DBLE&, const F77_DBLE&,\n                           const F77_INT&, const F77_INT&,\n                           F77_DBLE *, F77_DBLE *, F77_INT&,\n                           F77_INT&);\n\n  // BESK\n\n  F77_RET_T\n  F77_FUNC (cbesk, CBESK) (const F77_CMPLX *, const F77_REAL&,\n                           const F77_INT&, const F77_INT&,\n                           F77_CMPLX *, F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zbesk, ZBESK) (const F77_DBLE&, const F77_DBLE&, const F77_DBLE&,\n                           const F77_INT&, const F77_INT&,\n                           F77_DBLE *, F77_DBLE *, F77_INT&,\n                           F77_INT&);\n\n  // BESY\n\n  F77_RET_T\n  F77_FUNC (cbesy, CBESY) (const F77_CMPLX *, const F77_REAL&,\n                           const F77_INT&, const F77_INT&,\n                           F77_CMPLX *, F77_INT&,\n                           F77_CMPLX *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zbesy, ZBESY) (const F77_DBLE&, const F77_DBLE&, const F77_DBLE&,\n                           const F77_INT&, const F77_INT&,\n                           F77_DBLE *, F77_DBLE *, F77_INT&, F77_DBLE *,\n                           F77_DBLE *, F77_INT&);\n\n  // BIRY\n\n  F77_RET_T\n  F77_FUNC (cbiry, CBIRY) (const F77_CMPLX *, const F77_INT&, const F77_INT&,\n                           const F77_CMPLX *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zbiry, ZBIRY) (const F77_DBLE&, const F77_DBLE&,\n                           const F77_INT&, const F77_INT&,\n                           F77_DBLE&, F77_DBLE&, F77_INT&);\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/arpack-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_arpack_proto_h)\n#define octave_arpack_proto_h 1\n\n#include \"octave-config.h\"\n\n#include \"f77-fcn.h\"\n\nextern \"C\"\n{\n\n#if defined (HAVE_ARPACK)\n\n  // NAUPD\n\n  F77_RET_T\n  F77_FUNC (dnaupd, DNAUPD) (F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT&, const F77_DBLE&,\n                             F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT *,\n                             F77_INT *, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (znaupd, ZNAUPD) (F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_DBLE&,\n                             F77_DBLE_CMPLX *, const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT *,\n                             F77_INT *, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // NEUPD\n\n  F77_RET_T\n  F77_FUNC (dneupd, DNEUPD) (const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT *, F77_DBLE *, F77_DBLE *,\n                             F77_DBLE *, const F77_INT&, const F77_DBLE&,\n                             const F77_DBLE&, F77_DBLE *,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT&, const F77_DBLE&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT *,\n                             F77_INT *, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zneupd, ZNEUPD) (const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT *, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             F77_DBLE_CMPLX *,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_DBLE&,\n                             F77_DBLE_CMPLX *, const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT *,\n                             F77_INT *, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // SAUPD\n\n  F77_RET_T\n  F77_FUNC (dsaupd, DSAUPD) (F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_DBLE&,\n                             F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT *,\n                             F77_INT *, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // SEUPD\n\n  F77_RET_T\n  F77_FUNC (dseupd, DSEUPD) (const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT *, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, const F77_DBLE&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_DBLE&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT *,\n                             F77_INT *, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n#endif\n\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/base-dae.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_base_dae_h)\n#define octave_base_dae_h 1\n\n#include \"octave-config.h\"\n\n#include \"base-de.h\"\n\nclass base_diff_alg_eqn : public base_diff_eqn\n{\npublic:\n\n  base_diff_alg_eqn ()\n    : base_diff_eqn (), m_xdot () { }\n\n  base_diff_alg_eqn (const ColumnVector& xx, double tt)\n    : base_diff_eqn (xx, tt), m_xdot (xx.numel (), 0.0) { }\n\n  base_diff_alg_eqn (const ColumnVector& xx, const ColumnVector& xxdot,\n                     double tt)\n    : base_diff_eqn (xx, tt), m_xdot (xxdot) { }\n\n  base_diff_alg_eqn (const base_diff_alg_eqn& a)\n    : base_diff_eqn (a), m_xdot (a.m_xdot) { }\n\n  virtual ~base_diff_alg_eqn () = default;\n\n  base_diff_alg_eqn& operator = (const base_diff_alg_eqn& a)\n  {\n    if (this != &a)\n      {\n        base_diff_eqn::operator = (a);\n        m_xdot = a.m_xdot;\n      }\n    return *this;\n  }\n\n  void initialize (const ColumnVector& x0, double t0)\n  {\n    base_diff_eqn::initialize (x0, t0);\n    m_xdot = ColumnVector (x0.numel (), 0.0);\n  }\n\n  void initialize (const ColumnVector& x0, const ColumnVector& xdot0,\n                   double t0)\n  {\n    base_diff_eqn::initialize (x0, t0);\n    m_xdot = xdot0;\n  }\n\n  ColumnVector state_derivative () { return m_xdot; }\n\nprotected:\n\n  ColumnVector m_xdot;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/base-de.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_base_de_h)\n#define octave_base_de_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"dColVector.h\"\n\nclass base_diff_eqn\n{\npublic:\n\n  base_diff_eqn ()\n    : m_x (), m_t (0.0), m_stop_time (0.0), m_stop_time_set (false),\n      m_restart (true), m_integration_error (false), m_istate (0) { }\n\n  base_diff_eqn (const ColumnVector& xx, double tt)\n    : m_x (xx), m_t (tt), m_stop_time (0.0), m_stop_time_set (false),\n      m_restart (true), m_integration_error (false), m_istate (0) { }\n\n  base_diff_eqn (const base_diff_eqn& a)\n    : m_x (a.m_x), m_t (a.m_t), m_stop_time (0.0), m_stop_time_set (false),\n      m_restart (true), m_integration_error (false), m_istate (0) { }\n\n  virtual ~base_diff_eqn () = default;\n\n  base_diff_eqn& operator = (const base_diff_eqn& a)\n  {\n    if (this != &a)\n      {\n        m_x = a.m_x;\n        m_t = a.m_t;\n        m_stop_time = a.m_stop_time;\n        m_stop_time_set = a.m_stop_time_set;\n        m_restart = a.m_restart;\n        m_integration_error = a.m_integration_error;\n        m_istate = a.m_istate;\n      }\n\n    return *this;\n  }\n\n  void initialize (const ColumnVector& x0, double t0)\n  {\n    m_x = x0;\n    m_t = t0;\n    m_integration_error = false;\n    m_istate = 0;\n    force_restart ();\n  }\n\n  octave_idx_type size () const { return m_x.numel (); }\n\n  ColumnVector state () const { return m_x; }\n\n  double time () const { return m_t; }\n\n  void set_stop_time (double tt)\n  {\n    m_stop_time_set = true;\n    m_stop_time = tt;\n    force_restart ();\n  }\n\n  void clear_stop_time ()\n  {\n    m_stop_time_set = false;\n    force_restart ();\n  }\n\n  virtual void force_restart () { m_restart = true; }\n\n  bool integration_ok () const { return ! m_integration_error; }\n\n  octave_idx_type integration_state () const { return m_istate; }\n\n  virtual std::string error_message () const = 0;\n\nprotected:\n\n  ColumnVector m_x;\n\n  double m_t;\n\n  double m_stop_time;\n\n  bool m_stop_time_set;\n\n  bool m_restart;\n\n  bool m_integration_error;\n\n  octave_idx_type m_istate;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/blas-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_blas_proto_h)\n#define octave_blas_proto_h 1\n\n#include \"octave-config.h\"\n\n#include \"f77-fcn.h\"\n\nextern \"C\"\n{\n  // DOT (liboctave/external/blas-xtra)\n\n  F77_RET_T\n  F77_FUNC (xddot, XDDOT) (const F77_INT&, const F77_DBLE *,\n                           const F77_INT&, const F77_DBLE *,\n                           const F77_INT&, F77_DBLE&);\n\n  F77_RET_T\n  F77_FUNC (xsdot, XSDOT) (const F77_INT&, const F77_REAL *,\n                           const F77_INT&, const F77_REAL *,\n                           const F77_INT&, F77_REAL&);\n\n  // DOT3\n\n  F77_RET_T\n  F77_FUNC (ddot3, DDOT3) (const F77_INT&, const F77_INT&,\n                           const F77_INT&, const F77_DBLE *,\n                           const F77_DBLE *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (sdot3, SDOT3) (const F77_INT&, const F77_INT&,\n                           const F77_INT&, const F77_REAL *,\n                           const F77_REAL *, F77_REAL *);\n\n  // DOTC (liboctave/external/blas-xtra)\n\n  F77_RET_T\n  F77_FUNC (xcdotc, XCDOTC) (const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *);\n\n  F77_RET_T\n  F77_FUNC (xzdotc, XZDOTC) (const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *);\n\n  // DOTC3\n\n  F77_RET_T\n  F77_FUNC (cdotc3, CDOTC3) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_CMPLX *,\n                             const F77_CMPLX *, F77_CMPLX *);\n\n  F77_RET_T\n  F77_FUNC (zdotc3, ZDOTC3) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_DBLE_CMPLX *, F77_DBLE_CMPLX *);\n\n  // DOTU (liboctave/external/blas-xtra)\n\n  F77_RET_T\n  F77_FUNC (xcdotu, XCDOTU) (const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *);\n\n  F77_RET_T\n  F77_FUNC (xzdotu, XZDOTU) (const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *);\n\n  // GEMM\n\n  F77_RET_T\n  F77_FUNC (cgemm, CGEMM) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_INT&, const F77_CMPLX&,\n                           const F77_CMPLX *, const F77_INT&,\n                           const F77_CMPLX *, const F77_INT&,\n                           const F77_CMPLX&, F77_CMPLX *,\n                           const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgemm, DGEMM) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_INT&, const F77_DBLE&,\n                           const F77_DBLE *, const F77_INT&,\n                           const F77_DBLE *, const F77_INT&,\n                           const F77_DBLE&, F77_DBLE *,\n                           const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgemm, SGEMM) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_INT&, const F77_REAL&,\n                           const F77_REAL *, const F77_INT&,\n                           const F77_REAL *, const F77_INT&,\n                           const F77_REAL&, F77_REAL *,\n                           const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgemm, ZGEMM) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_INT&, const F77_DBLE_CMPLX&,\n                           const F77_DBLE_CMPLX *, const F77_INT&,\n                           const F77_DBLE_CMPLX *, const F77_INT&,\n                           const F77_DBLE_CMPLX&, F77_DBLE_CMPLX *,\n                           const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  // GEMV\n\n  F77_RET_T\n  F77_FUNC (cgemv, CGEMV) (F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_CMPLX&, const F77_CMPLX *,\n                           const F77_INT&, const F77_CMPLX *,\n                           const F77_INT&, const F77_CMPLX&,\n                           F77_CMPLX *, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgemv, DGEMV) (F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_DBLE&, const F77_DBLE *,\n                           const F77_INT&, const F77_DBLE *,\n                           const F77_INT&, const F77_DBLE&,\n                           F77_DBLE *, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgemv, SGEMV) (F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_REAL&, const F77_REAL *,\n                           const F77_INT&, const F77_REAL *,\n                           const F77_INT&, const F77_REAL&,\n                           F77_REAL *, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgemv, ZGEMV) (F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_DBLE_CMPLX&, const F77_DBLE_CMPLX *,\n                           const F77_INT&, const F77_DBLE_CMPLX *,\n                           const F77_INT&, const F77_DBLE_CMPLX&,\n                           F77_DBLE_CMPLX *, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL);\n\n  // MATM3\n\n  F77_RET_T\n  F77_FUNC (cmatm3, CMATM3) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_INT&,\n                             const F77_CMPLX *, const F77_CMPLX *,\n                             F77_CMPLX *);\n  F77_RET_T\n  F77_FUNC (dmatm3, DMATM3) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE *, const F77_DBLE *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (smatm3, SMATM3) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_INT&,\n                             const F77_REAL *, const F77_REAL *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zmatm3, ZMATM3) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE_CMPLX *, const F77_DBLE_CMPLX *,\n                             F77_DBLE_CMPLX *);\n\n  // NRM2 (liboctave/external/blas-xtra)\n\n  F77_RET_T\n  F77_FUNC (xdnrm2, XDNRM2) (const F77_INT&, const F77_DBLE *,\n                             const F77_INT&, F77_DBLE&);\n\n  F77_RET_T\n  F77_FUNC (xsnrm2, XSNRM2) (const F77_INT&, const F77_REAL *,\n                             const F77_INT&, F77_REAL&);\n\n  F77_RET_T\n  F77_FUNC (xdznrm2, XDZNRM2) (const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE&);\n\n  F77_RET_T\n  F77_FUNC (xscnrm2, XSCNRM2) (const F77_INT&, const F77_CMPLX *,\n                               const F77_INT&, F77_REAL&);\n\n  // XERBLA\n\n  OCTAVE_API\n  F77_RET_T\n  F77_FUNC (xerbla, XERBLA) (F77_CONST_CHAR_ARG_DECL, const F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // Declarations for the *axpy BLAS functions\n  // The *axpy functions are used by convolution.\n\n  F77_RET_T\n  F77_FUNC (daxpy, DAXPY) (const F77_INT&, const F77_DBLE&, const F77_DBLE *,\n                           const F77_INT&, F77_DBLE *, const F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (saxpy, SAXPY) (const F77_INT&, const F77_REAL&, const F77_REAL *,\n                           const F77_INT&, F77_REAL *, const F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zaxpy, ZAXPY) (const F77_INT&, const F77_DBLE_CMPLX&,\n                           const F77_DBLE_CMPLX *, const F77_INT&,\n                           F77_DBLE_CMPLX *, const F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (caxpy, CAXPY) (const F77_INT&, const F77_CMPLX&,\n                           const F77_CMPLX *, const F77_INT&,\n                           F77_CMPLX *, const F77_INT&);\n\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/bsxfun-decl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_bsxfun_decl_h)\n#define octave_bsxfun_decl_h 1\n\n#define BSXFUN_OP_DECL(OP, ARRAY, API)                          \\\n  extern API ARRAY bsxfun_ ## OP (const ARRAY&, const ARRAY&);\n\n#define BSXFUN1_OP_DECL(OP, ARRAY, API)                          \\\n  extern API ARRAY bsxfun_ ## OP (const ARRAY&, const ARRAY&, const bool);\n\n#define BSXFUN2_OP_DECL(OP, ARRAY, API)                          \\\n  extern API ARRAY bsxfun_ ## OP (const ARRAY&, const ARRAY&,    \\\n                                  const bool, const bool);\n\n#define BSXFUN_OP2_DECL(OP, ARRAY, ARRAY1, ARRAY2, API)                 \\\n  extern API ARRAY bsxfun_ ## OP (const ARRAY1&, const ARRAY2&);\n\n#define BSXFUN_REL_DECL(OP, ARRAY, API)                                 \\\n  extern API boolNDArray bsxfun_ ## OP (const ARRAY&, const ARRAY&);\n\n#define BSXFUN_STDOP_DECLS(ARRAY, API)          \\\n  BSXFUN_OP_DECL (add, ARRAY, API)              \\\n  BSXFUN_OP_DECL (sub, ARRAY, API)              \\\n  BSXFUN_OP_DECL (mul, ARRAY, API)              \\\n  BSXFUN_OP_DECL (div, ARRAY, API)              \\\n  BSXFUN_OP_DECL (pow, ARRAY, API)              \\\n  BSXFUN_OP_DECL (min, ARRAY, API)              \\\n  BSXFUN_OP_DECL (max, ARRAY, API)              \\\n  BSXFUN1_OP_DECL (min, ARRAY, API)             \\\n  BSXFUN1_OP_DECL (max, ARRAY, API)             \\\n  BSXFUN2_OP_DECL (min, ARRAY, API)             \\\n  BSXFUN2_OP_DECL (max, ARRAY, API)\n\n#define BSXFUN_MIXED_INT_DECLS(INT_TYPE, API)                   \\\n  BSXFUN_OP2_DECL (pow, INT_TYPE, INT_TYPE, NDArray, API)       \\\n  BSXFUN_OP2_DECL (pow, INT_TYPE, INT_TYPE, FloatNDArray, API)  \\\n  BSXFUN_OP2_DECL (pow, INT_TYPE, NDArray, INT_TYPE, API)       \\\n  BSXFUN_OP2_DECL (pow, INT_TYPE, FloatNDArray, INT_TYPE, API)\n\n#define BSXFUN_STDREL_DECLS(ARRAY, API)         \\\n  BSXFUN_REL_DECL (eq, ARRAY, API)              \\\n  BSXFUN_REL_DECL (ne, ARRAY, API)              \\\n  BSXFUN_REL_DECL (lt, ARRAY, API)              \\\n  BSXFUN_REL_DECL (le, ARRAY, API)              \\\n  BSXFUN_REL_DECL (gt, ARRAY, API)              \\\n  BSXFUN_REL_DECL (ge, ARRAY, API)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/bsxfun-defs.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_bsxfun_defs_h)\n#define octave_bsxfun_defs_h 1\n\n// This file should *not* include config.h.  It is only included in other C++\n// source files that should have included config.h before including this file.\n\n#include <algorithm>\n\n#include \"dim-vector.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n\ntemplate <typename R, typename X, typename Y>\nArray<R>\ndo_bsxfun_op (const Array<X>& x, const Array<Y>& y,\n              void (*op_vv) (std::size_t, R *, const X *, const Y *),\n              void (*op_sv) (std::size_t, R *, X, const Y *),\n              void (*op_vs) (std::size_t, R *, const X *, Y))\n{\n  int nd = std::max (x.ndims (), y.ndims ());\n  const dim_vector& dvx = x.dims ().redim (nd);\n  const dim_vector& dvy = y.dims ().redim (nd);\n\n  // Construct the result dimensions.\n  dim_vector dvr;\n  dvr.resize (nd);\n  for (int i = 0; i < nd; i++)\n    {\n      octave_idx_type xk = dvx(i);\n      octave_idx_type yk = dvy(i);\n      if (xk == 1)\n        dvr(i) = yk;\n      else if (yk == 1 || xk == yk)\n        dvr(i) = xk;\n      else\n        (*current_liboctave_error_handler)\n          (\"bsxfun: nonconformant dimensions: %s and %s\",\n           x.dims ().str ().c_str (), y.dims ().str ().c_str ());\n    }\n\n  Array<R> retval (dvr);\n\n  const X *xvec = x.data ();\n  const Y *yvec = y.data ();\n  R *rvec = retval.rwdata ();\n\n  // Fold the common leading dimensions.\n  octave_idx_type start, ldr = 1;\n  for (start = 0; start < nd; start++)\n    {\n      if (dvx(start) != dvy(start))\n        break;\n      ldr *= dvr(start);\n    }\n\n  if (retval.isempty ())\n    ; // do nothing\n  else if (start == nd)\n    op_vv (retval.numel (), rvec, xvec, yvec);\n  else\n    {\n      // Determine the type of the low-level loop.\n      bool xsing = false;\n      bool ysing = false;\n      if (ldr == 1)\n        {\n          xsing = dvx(start) == 1;\n          ysing = dvy(start) == 1;\n          if (xsing || ysing)\n            {\n              ldr *= dvx(start) * dvy(start);\n              start++;\n            }\n        }\n      dim_vector cdvx = dvx.cumulative ();\n      dim_vector cdvy = dvy.cumulative ();\n      // Nullify singleton dims to achieve a spread effect.\n      for (int i = std::max (start, octave_idx_type (1)); i < nd; i++)\n        {\n          if (dvx(i) == 1)\n            cdvx(i-1) = 0;\n          if (dvy(i) == 1)\n            cdvy(i-1) = 0;\n        }\n\n      octave_idx_type niter = dvr.numel (start);\n      // The index array.\n      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, idx, nd, 0);\n      for (octave_idx_type iter = 0; iter < niter; iter++)\n        {\n          octave_quit ();\n\n          // Compute indices.\n          // FIXME: performance impact noticeable?\n          octave_idx_type xidx = cdvx.cum_compute_index (idx);\n          octave_idx_type yidx = cdvy.cum_compute_index (idx);\n          octave_idx_type ridx = dvr.compute_index (idx);\n\n          // Apply the low-level loop.\n          if (xsing)\n            op_sv (ldr, rvec + ridx, xvec[xidx], yvec + yidx);\n          else if (ysing)\n            op_vs (ldr, rvec + ridx, xvec + xidx, yvec[yidx]);\n          else\n            op_vv (ldr, rvec + ridx, xvec + xidx, yvec + yidx);\n\n          dvr.increment_index (idx + start, start);\n        }\n    }\n\n  return retval;\n}\n\ntemplate <typename R, typename X>\nvoid\ndo_inplace_bsxfun_op (Array<R>& r, const Array<X>& x,\n                      void (*op_vv) (std::size_t, R *, const X *),\n                      void (*op_vs) (std::size_t, R *, X))\n{\n  const dim_vector& dvr = r.dims ();\n  dim_vector dvx = x.dims ();\n  octave_idx_type nd = r.ndims ();\n  dvx = dvx.redim (nd);\n\n  const X *xvec = x.data ();\n  R *rvec = r.rwdata ();\n\n  // Fold the common leading dimensions.\n  octave_idx_type start, ldr = 1;\n  for (start = 0; start < nd; start++)\n    {\n      if (dvr(start) != dvx(start))\n        break;\n      ldr *= dvr(start);\n    }\n\n  if (r.isempty ())\n    ; // do nothing\n  else if (start == nd)\n    op_vv (r.numel (), rvec, xvec);\n  else\n    {\n      // Determine the type of the low-level loop.\n      bool xsing = false;\n      if (ldr == 1)\n        {\n          xsing = dvx(start) == 1;\n          if (xsing)\n            {\n              ldr *= dvr(start) * dvx(start);\n              start++;\n            }\n        }\n\n      dim_vector cdvx = dvx.cumulative ();\n      // Nullify singleton dims to achieve a spread effect.\n      for (int i = std::max (start, octave_idx_type (1)); i < nd; i++)\n        {\n          if (dvx(i) == 1)\n            cdvx(i-1) = 0;\n        }\n\n      octave_idx_type niter = dvr.numel (start);\n      // The index array.\n      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, idx, nd, 0);\n      for (octave_idx_type iter = 0; iter < niter; iter++)\n        {\n          octave_quit ();\n\n          // Compute indices.\n          // FIXME: performance impact noticeable?\n          octave_idx_type xidx = cdvx.cum_compute_index (idx);\n          octave_idx_type ridx = dvr.compute_index (idx);\n\n          // Apply the low-level loop.\n          if (xsing)\n            op_vs (ldr, rvec + ridx, xvec[xidx]);\n          else\n            op_vv (ldr, rvec + ridx, xvec + xidx);\n\n          dvr.increment_index (idx + start, start);\n        }\n    }\n}\n\n// Specialization for min/max with extra nanflag and realabs optional arguments\n\ntemplate <typename R, typename X, typename Y>\nArray<R>\ndo_bsxfun1_op (const Array<X>& x, const Array<Y>& y, const bool nanflag,\n               void (*op_vv) (std::size_t, R *, const X *, const Y *,\n                              const bool),\n               void (*op_sv) (std::size_t, R *, X, const Y *, const bool),\n               void (*op_vs) (std::size_t, R *, const X *, Y, const bool))\n{\n  int nd = std::max (x.ndims (), y.ndims ());\n  const dim_vector& dvx = x.dims ().redim (nd);\n  const dim_vector& dvy = y.dims ().redim (nd);\n\n  // Construct the result dimensions.\n  dim_vector dvr;\n  dvr.resize (nd);\n  for (int i = 0; i < nd; i++)\n    {\n      octave_idx_type xk = dvx(i);\n      octave_idx_type yk = dvy(i);\n      if (xk == 1)\n        dvr(i) = yk;\n      else if (yk == 1 || xk == yk)\n        dvr(i) = xk;\n      else\n        (*current_liboctave_error_handler)\n          (\"bsxfun: nonconformant dimensions: %s and %s\",\n           x.dims ().str ().c_str (), y.dims ().str ().c_str ());\n    }\n\n  Array<R> retval (dvr);\n\n  const X *xvec = x.data ();\n  const Y *yvec = y.data ();\n  R *rvec = retval.rwdata ();\n\n  // Fold the common leading dimensions.\n  octave_idx_type start, ldr = 1;\n  for (start = 0; start < nd; start++)\n    {\n      if (dvx(start) != dvy(start))\n        break;\n      ldr *= dvr(start);\n    }\n\n  if (retval.isempty ())\n    ; // do nothing\n  else if (start == nd)\n    op_vv (retval.numel (), rvec, xvec, yvec, nanflag);\n  else\n    {\n      // Determine the type of the low-level loop.\n      bool xsing = false;\n      bool ysing = false;\n      if (ldr == 1)\n        {\n          xsing = dvx(start) == 1;\n          ysing = dvy(start) == 1;\n          if (xsing || ysing)\n            {\n              ldr *= dvx(start) * dvy(start);\n              start++;\n            }\n        }\n      dim_vector cdvx = dvx.cumulative ();\n      dim_vector cdvy = dvy.cumulative ();\n      // Nullify singleton dims to achieve a spread effect.\n      for (int i = std::max (start, octave_idx_type (1)); i < nd; i++)\n        {\n          if (dvx(i) == 1)\n            cdvx(i-1) = 0;\n          if (dvy(i) == 1)\n            cdvy(i-1) = 0;\n        }\n\n      octave_idx_type niter = dvr.numel (start);\n      // The index array.\n      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, idx, nd, 0);\n      for (octave_idx_type iter = 0; iter < niter; iter++)\n        {\n          octave_quit ();\n\n          // Compute indices.\n          // FIXME: performance impact noticeable?\n          octave_idx_type xidx = cdvx.cum_compute_index (idx);\n          octave_idx_type yidx = cdvy.cum_compute_index (idx);\n          octave_idx_type ridx = dvr.compute_index (idx);\n\n          // Apply the low-level loop.\n          if (xsing)\n            op_sv (ldr, rvec + ridx, xvec[xidx], yvec + yidx, nanflag);\n          else if (ysing)\n            op_vs (ldr, rvec + ridx, xvec + xidx, yvec[yidx], nanflag);\n          else\n            op_vv (ldr, rvec + ridx, xvec + xidx, yvec + yidx, nanflag);\n\n          dvr.increment_index (idx + start, start);\n        }\n    }\n\n  return retval;\n}\n\ntemplate <typename R, typename X, typename Y>\nArray<R>\ndo_bsxfun2_op (const Array<X>& x, const Array<Y>& y, const bool nanflag,\n               const bool realabs,\n               void (*op_vv) (std::size_t, R *, const X *, const Y *,\n                              const bool, const bool),\n               void (*op_sv) (std::size_t, R *, X, const Y *,\n                              const bool, const bool),\n               void (*op_vs) (std::size_t, R *, const X *, Y,\n                              const bool, const bool))\n{\n  int nd = std::max (x.ndims (), y.ndims ());\n  const dim_vector& dvx = x.dims ().redim (nd);\n  const dim_vector& dvy = y.dims ().redim (nd);\n\n  // Construct the result dimensions.\n  dim_vector dvr;\n  dvr.resize (nd);\n  for (int i = 0; i < nd; i++)\n    {\n      octave_idx_type xk = dvx(i);\n      octave_idx_type yk = dvy(i);\n      if (xk == 1)\n        dvr(i) = yk;\n      else if (yk == 1 || xk == yk)\n        dvr(i) = xk;\n      else\n        (*current_liboctave_error_handler)\n          (\"bsxfun: nonconformant dimensions: %s and %s\",\n           x.dims ().str ().c_str (), y.dims ().str ().c_str ());\n    }\n\n  Array<R> retval (dvr);\n\n  const X *xvec = x.data ();\n  const Y *yvec = y.data ();\n  R *rvec = retval.rwdata ();\n\n  // Fold the common leading dimensions.\n  octave_idx_type start, ldr = 1;\n  for (start = 0; start < nd; start++)\n    {\n      if (dvx(start) != dvy(start))\n        break;\n      ldr *= dvr(start);\n    }\n\n  if (retval.isempty ())\n    ; // do nothing\n  else if (start == nd)\n    op_vv (retval.numel (), rvec, xvec, yvec, nanflag, realabs);\n  else\n    {\n      // Determine the type of the low-level loop.\n      bool xsing = false;\n      bool ysing = false;\n      if (ldr == 1)\n        {\n          xsing = dvx(start) == 1;\n          ysing = dvy(start) == 1;\n          if (xsing || ysing)\n            {\n              ldr *= dvx(start) * dvy(start);\n              start++;\n            }\n        }\n      dim_vector cdvx = dvx.cumulative ();\n      dim_vector cdvy = dvy.cumulative ();\n      // Nullify singleton dims to achieve a spread effect.\n      for (int i = std::max (start, octave_idx_type (1)); i < nd; i++)\n        {\n          if (dvx(i) == 1)\n            cdvx(i-1) = 0;\n          if (dvy(i) == 1)\n            cdvy(i-1) = 0;\n        }\n\n      octave_idx_type niter = dvr.numel (start);\n      // The index array.\n      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, idx, nd, 0);\n      for (octave_idx_type iter = 0; iter < niter; iter++)\n        {\n          octave_quit ();\n\n          // Compute indices.\n          // FIXME: performance impact noticeable?\n          octave_idx_type xidx = cdvx.cum_compute_index (idx);\n          octave_idx_type yidx = cdvy.cum_compute_index (idx);\n          octave_idx_type ridx = dvr.compute_index (idx);\n\n          // Apply the low-level loop.\n          if (xsing)\n            op_sv (ldr, rvec + ridx, xvec[xidx], yvec + yidx, nanflag, realabs);\n          else if (ysing)\n            op_vs (ldr, rvec + ridx, xvec + xidx, yvec[yidx], nanflag, realabs);\n          else\n            op_vv (ldr, rvec + ridx, xvec + xidx, yvec + yidx, nanflag, realabs);\n\n          dvr.increment_index (idx + start, start);\n        }\n    }\n\n  return retval;\n}\n\n#define BSXFUN_OP_DEF(OP, ARRAY)                        \\\n  ARRAY bsxfun_ ## OP (const ARRAY& x, const ARRAY& y)\n\n#define BSXFUN1_OP_DEF(OP, ARRAY)                        \\\n  ARRAY bsxfun_ ## OP (const ARRAY& x, const ARRAY& y,   \\\n                       const bool nanflag)\n\n#define BSXFUN2_OP_DEF(OP, ARRAY)                        \\\n  ARRAY bsxfun_ ## OP (const ARRAY& x, const ARRAY& y,   \\\n                       const bool nanflag, const bool realabs)\n\n#define BSXFUN_OP2_DEF(OP, ARRAY, ARRAY1, ARRAY2)               \\\n  ARRAY bsxfun_ ## OP (const ARRAY1& x, const ARRAY2& y)\n\n#define BSXFUN_REL_DEF(OP, ARRAY)                               \\\n  boolNDArray bsxfun_ ## OP (const ARRAY& x, const ARRAY& y)\n\n#define BSXFUN_OP_DEF_MXLOOP(OP, ARRAY, LOOP)                           \\\n  BSXFUN_OP_DEF(OP, ARRAY)                                              \\\n  { return do_bsxfun_op<ARRAY::element_type, ARRAY::element_type, ARRAY::element_type> \\\n      (x, y, LOOP, LOOP, LOOP); }\n\n#define BSXFUN1_OP_DEF_MXLOOP(OP, ARRAY, LOOP)                           \\\n  BSXFUN1_OP_DEF(OP, ARRAY)                                              \\\n  { return do_bsxfun1_op<ARRAY::element_type, ARRAY::element_type, ARRAY::element_type> \\\n      (x, y, nanflag, LOOP, LOOP, LOOP); }\n\n#define BSXFUN2_OP_DEF_MXLOOP(OP, ARRAY, LOOP)                           \\\n  BSXFUN2_OP_DEF(OP, ARRAY)                                              \\\n  { return do_bsxfun2_op<ARRAY::element_type, ARRAY::element_type, ARRAY::element_type> \\\n      (x, y, nanflag, realabs, LOOP, LOOP, LOOP); }\n\n#define BSXFUN_OP2_DEF_MXLOOP(OP, ARRAY, ARRAY1, ARRAY2, LOOP)          \\\n  BSXFUN_OP2_DEF(OP, ARRAY, ARRAY1, ARRAY2)                             \\\n  { return do_bsxfun_op<ARRAY::element_type, ARRAY1::element_type, ARRAY2::element_type> \\\n      (x, y, LOOP, LOOP, LOOP); }\n\n#define BSXFUN_REL_DEF_MXLOOP(OP, ARRAY, LOOP)                          \\\n  BSXFUN_REL_DEF(OP, ARRAY)                                             \\\n  { return do_bsxfun_op<bool, ARRAY::element_type, ARRAY::element_type> \\\n      (x, y, LOOP, LOOP, LOOP); }\n\n#define BSXFUN_STDOP_DEFS_MXLOOP(ARRAY)                 \\\n  BSXFUN_OP_DEF_MXLOOP (add, ARRAY, mx_inline_add)      \\\n  BSXFUN_OP_DEF_MXLOOP (sub, ARRAY, mx_inline_sub)      \\\n  BSXFUN_OP_DEF_MXLOOP (mul, ARRAY, mx_inline_mul)      \\\n  BSXFUN_OP_DEF_MXLOOP (div, ARRAY, mx_inline_div)      \\\n  BSXFUN_OP_DEF_MXLOOP (min, ARRAY, mx_inline_xmin)     \\\n  BSXFUN_OP_DEF_MXLOOP (max, ARRAY, mx_inline_xmax)     \\\n  BSXFUN1_OP_DEF_MXLOOP (min, ARRAY, mx_inline_xmin)    \\\n  BSXFUN1_OP_DEF_MXLOOP (max, ARRAY, mx_inline_xmax)    \\\n  BSXFUN2_OP_DEF_MXLOOP (min, ARRAY, mx_inline_xmin)    \\\n  BSXFUN2_OP_DEF_MXLOOP (max, ARRAY, mx_inline_xmax)\n\n#define BSXFUN_STDREL_DEFS_MXLOOP(ARRAY)                \\\n  BSXFUN_REL_DEF_MXLOOP (eq, ARRAY, mx_inline_eq)       \\\n  BSXFUN_REL_DEF_MXLOOP (ne, ARRAY, mx_inline_ne)       \\\n  BSXFUN_REL_DEF_MXLOOP (lt, ARRAY, mx_inline_lt)       \\\n  BSXFUN_REL_DEF_MXLOOP (le, ARRAY, mx_inline_le)       \\\n  BSXFUN_REL_DEF_MXLOOP (gt, ARRAY, mx_inline_gt)       \\\n  BSXFUN_REL_DEF_MXLOOP (ge, ARRAY, mx_inline_ge)\n\n//For bsxfun power with mixed integer/float types\n#define BSXFUN_POW_MIXED_MXLOOP(INT_TYPE)                                      \\\n  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, INT_TYPE, NDArray, mx_inline_pow)      \\\n  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, INT_TYPE, FloatNDArray, mx_inline_pow) \\\n  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, NDArray, INT_TYPE, mx_inline_pow)      \\\n  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, FloatNDArray, INT_TYPE, mx_inline_pow)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/bsxfun.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_bsxfun_h)\n#define octave_bsxfun_h 1\n\n#include \"octave-config.h\"\n\n#include <algorithm>\n#include <string>\n\n#include \"dim-vector.h\"\n#include \"oct-error.h\"\n\ninline\nbool\nis_valid_bsxfun (const dim_vector& xdv, const dim_vector& ydv)\n{\n  for (int i = 0; i < std::min (xdv.ndims (), ydv.ndims ()); i++)\n    {\n      octave_idx_type xk = xdv(i);\n      octave_idx_type yk = ydv(i);\n      // Check the three conditions for valid bsxfun dims\n      if (! ((xk == yk) || (xk == 1 && yk != 1) || (xk != 1 && yk == 1)))\n        return false;\n    }\n\n  return true;\n}\n\n// For inplace operations the size of the resulting matrix cannot be changed.\n// Therefore we can only apply singleton expansion on the second matrix which\n// alters the conditions to check.\ninline\nbool\nis_valid_inplace_bsxfun (const dim_vector& rdv, const dim_vector& xdv)\n{\n  octave_idx_type r_nd = rdv.ndims ();\n  octave_idx_type x_nd = xdv.ndims ();\n  if (r_nd < x_nd)\n    return false;\n\n  for (int i = 0; i < x_nd; i++)\n    {\n      octave_idx_type rk = rdv(i);\n      octave_idx_type xk = xdv(i);\n\n      // Only two valid conditions to check; can't stretch rk\n      if ((rk != xk) && xk != 1)\n        return false;\n    }\n\n  return true;\n}\n\n#include \"bsxfun-defs.cc\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/chol.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <vector>\n\n#include \"Array-oct.h\"\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n#include \"chol.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"fCColVector.h\"\n#include \"fCMatrix.h\"\n#include \"fColVector.h\"\n#include \"fMatrix.h\"\n#include \"lapack-proto.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-norm.h\"\n#include \"qrupdate-proto.h\"\n\n#if ! defined (HAVE_QRUPDATE)\n#  include \"qr.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic inline void\nblas_potri (const F77_INT& n, Matrix& r, F77_INT& info, bool is_upper)\n{\n  const char *str = is_upper ? \"U\" : \"L\";\n  F77_FUNC (dpotri, DPOTRI) (F77_CONST_CHAR_ARG2 (str, 1), n, r.rwdata (), n,\n                             info F77_CHAR_ARG_LEN (1));\n}\n\nstatic inline void\nblas_potri (const F77_INT& n, FloatMatrix& r, F77_INT& info, bool is_upper)\n{\n  const char *str = is_upper ? \"U\" : \"L\";\n  F77_FUNC (spotri, SPOTRI) (F77_CONST_CHAR_ARG2 (str, 1), n, r.rwdata (), n,\n                             info F77_CHAR_ARG_LEN (1));\n}\n\nstatic inline void\nblas_potri (const F77_INT& n, ComplexMatrix& r, F77_INT& info, bool is_upper)\n{\n  const char *str = is_upper ? \"U\" : \"L\";\n  F77_FUNC (zpotri, ZPOTRI) (F77_CONST_CHAR_ARG2 (str, 1), n,\n                             F77_DBLE_CMPLX_ARG (r.rwdata ()), n, info\n                             F77_CHAR_ARG_LEN (1));\n}\n\nstatic inline void\nblas_potri (const F77_INT& n, FloatComplexMatrix& r, F77_INT& info, bool is_upper)\n{\n  const char *str = is_upper ? \"U\" : \"L\";\n  F77_FUNC (cpotri, CPOTRI) (F77_CONST_CHAR_ARG2 (str, 1), n,\n                             F77_CMPLX_ARG (r.rwdata ()), n, info\n                             F77_CHAR_ARG_LEN (1));\n}\n\ntemplate <typename T>\nstatic T\nchol2inv_internal (const T& r, bool is_upper = true)\n{\n  octave_idx_type nr = r.rows ();\n  octave_idx_type nc = r.cols ();\n\n  if (nr != nc)\n    (*current_liboctave_error_handler) (\"chol2inv requires square matrix\");\n\n  F77_INT n = to_f77_int (nc);\n  F77_INT info;\n\n  T retval = r;\n  blas_potri (n, retval, info, is_upper);\n  // FIXME: Error based on value of info?\n\n  if (n > 1)\n    {\n      // If someone thinks of a more graceful way of doing this\n      // (or faster for that matter :-)), please let me know!\n      if (is_upper)\n        for (octave_idx_type j = 0; j < nc; j++)\n          for (octave_idx_type i = j+1; i < nr; i++)\n            retval.xelem (i, j) = math::conj (retval.xelem (j, i));\n      else\n        for (octave_idx_type j = 0; j < nc; j++)\n          for (octave_idx_type i = j+1; i < nr; i++)\n            retval.xelem (j, i) = math::conj (retval.xelem (i, j));\n    }\n\n  return retval;\n}\n\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nT\nchol2inv (const T& r)\n{\n  return chol2inv_internal<T> (r);\n}\n\n// Compute the inverse of a matrix using the Cholesky factorization.\ntemplate <typename T>\nT\nchol<T>::inverse () const\n{\n  return chol2inv_internal<T> (m_chol_mat, m_is_upper);\n}\n\ntemplate <typename T>\nvoid\nchol<T>::set (const T& R)\n{\n  if (! R.issquare ())\n    (*current_liboctave_error_handler) (\"chol: requires square matrix\");\n\n  m_chol_mat = R;\n}\n\n#if ! defined (HAVE_QRUPDATE)\n\ntemplate <typename T>\nvoid\nchol<T>::update (const VT& u)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type n = m_chol_mat.rows ();\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  init (m_chol_mat.hermitian () * m_chol_mat + T (u) * T (u).hermitian (),\n        true, false);\n}\n\ntemplate <typename T>\nbool\nsingular (const T& a)\n{\n  static typename T::element_type zero (0);\n  for (octave_idx_type i = 0; i < a.rows (); i++)\n    if (a(i, i) == zero) return true;\n  return false;\n}\n\ntemplate <typename T>\noctave_idx_type\nchol<T>::downdate (const VT& u)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type info = -1;\n\n  octave_idx_type n = m_chol_mat.rows ();\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  if (singular (m_chol_mat))\n    info = 2;\n  else\n    {\n      info = init (m_chol_mat.hermitian () * m_chol_mat\n                   - T (u) * T (u).hermitian (), true, false);\n      if (info) info = 1;\n    }\n\n  return info;\n}\n\ntemplate <typename T>\noctave_idx_type\nchol<T>::insert_sym (const VT& u, octave_idx_type j)\n{\n  static typename T::element_type zero (0);\n\n  warn_qrupdate_once ();\n\n  octave_idx_type info = -1;\n\n  octave_idx_type n = m_chol_mat.rows ();\n\n  if (u.numel () != n + 1)\n    (*current_liboctave_error_handler) (\"cholinsert: dimension mismatch\");\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"cholinsert: index out of range\");\n\n  if (singular (m_chol_mat))\n    info = 2;\n  else if (std::imag (u(j)) != zero)\n    info = 3;\n  else\n    {\n      T a = m_chol_mat.hermitian () * m_chol_mat;\n      T a1 (n+1, n+1);\n      for (octave_idx_type k = 0; k < n+1; k++)\n        for (octave_idx_type l = 0; l < n+1; l++)\n          {\n            if (l == j)\n              a1(k, l) = u(k);\n            else if (k == j)\n              a1(k, l) = math::conj (u(l));\n            else\n              a1(k, l) = a(k < j ? k : k-1, l < j ? l : l-1);\n          }\n      info = init (a1, true, false);\n      if (info) info = 1;\n    }\n\n  return info;\n}\n\ntemplate <typename T>\nvoid\nchol<T>::delete_sym (octave_idx_type j)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type n = m_chol_mat.rows ();\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"choldelete: index out of range\");\n\n  T a = m_chol_mat.hermitian () * m_chol_mat;\n  a.delete_elements (1, idx_vector (j));\n  a.delete_elements (0, idx_vector (j));\n  init (a, true, false);\n}\n\ntemplate <typename T>\nvoid\nchol<T>::shift_sym (octave_idx_type i, octave_idx_type j)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type n = m_chol_mat.rows ();\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"cholshift: index out of range\");\n\n  T a = m_chol_mat.hermitian () * m_chol_mat;\n  Array<octave_idx_type> p (dim_vector (n, 1));\n  for (octave_idx_type k = 0; k < n; k++) p(k) = k;\n  if (i < j)\n    {\n      for (octave_idx_type k = i; k < j; k++) p(k) = k+1;\n      p(j) = i;\n    }\n  else if (j < i)\n    {\n      p(j) = i;\n      for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1;\n    }\n\n  init (a.index (idx_vector (p), idx_vector (p)), true, false);\n}\n\n#endif\n\n// Specializations.\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<Matrix>::init (const Matrix& a, bool upper, bool calc_cond)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"chol: requires square matrix\");\n\n  F77_INT n = to_f77_int (a_nc);\n  F77_INT info;\n\n  m_is_upper = upper;\n\n  m_chol_mat.clear (n, n);\n  if (m_is_upper)\n    for (octave_idx_type j = 0; j < n; j++)\n      {\n        for (octave_idx_type i = 0; i <= j; i++)\n          m_chol_mat.xelem (i, j) = a(i, j);\n        for (octave_idx_type i = j+1; i < n; i++)\n          m_chol_mat.xelem (i, j) = 0.0;\n      }\n  else\n    for (octave_idx_type j = 0; j < n; j++)\n      {\n        for (octave_idx_type i = 0; i < j; i++)\n          m_chol_mat.xelem (i, j) = 0.0;\n        for (octave_idx_type i = j; i < n; i++)\n          m_chol_mat.xelem (i, j) = a(i, j);\n      }\n  double *h = m_chol_mat.rwdata ();\n\n  // Calculate the norm of the matrix, for later use.\n  double anorm = 0;\n  if (calc_cond)\n    anorm = octave::xnorm (a, 1);\n\n  if (m_is_upper)\n    F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (\"U\", 1), n, h, n, info\n                               F77_CHAR_ARG_LEN (1)));\n  else\n    F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (\"L\", 1), n, h, n, info\n                               F77_CHAR_ARG_LEN (1)));\n\n  m_rcond = 0.0;\n  if (info > 0)\n    m_chol_mat.resize (info - 1, info - 1);\n  else if (calc_cond)\n    {\n      F77_INT dpocon_info = 0;\n\n      // Now calculate the condition number for non-singular matrix.\n      Array<double> z (dim_vector (3*n, 1));\n      double *pz = z.rwdata ();\n      OCTAVE_LOCAL_BUFFER (F77_INT, iz, n);\n      if (m_is_upper)\n        F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (\"U\", 1), n, h,\n                                   n, anorm, m_rcond, pz, iz, dpocon_info\n                                   F77_CHAR_ARG_LEN (1)));\n      else\n        F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (\"L\", 1), n, h,\n                                   n, anorm, m_rcond, pz, iz, dpocon_info\n                                   F77_CHAR_ARG_LEN (1)));\n\n      if (dpocon_info != 0)\n        info = -1;\n    }\n\n  return info;\n}\n\n#if defined (HAVE_QRUPDATE)\n\ntemplate <>\nOCTAVE_API void\nchol<Matrix>::update (const ColumnVector& u)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  std::vector<double> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (double, w, n);\n\n  F77_XFCN (dch1up, DCH1UP, (n, m_chol_mat.rwdata (), n,\n                             utmp.data (), w));\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<Matrix>::downdate (const ColumnVector& u)\n{\n  F77_INT info = -1;\n\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  std::vector<double> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (double, w, n);\n\n  F77_XFCN (dch1dn, DCH1DN, (n, m_chol_mat.rwdata (), n,\n                             utmp.data (), w, info));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<Matrix>::insert_sym (const ColumnVector& u, octave_idx_type j_arg)\n{\n  F77_INT info = -1;\n\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT j = to_f77_int (j_arg);\n\n  if (u.numel () != n + 1)\n    (*current_liboctave_error_handler) (\"cholinsert: dimension mismatch\");\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"cholinsert: index out of range\");\n\n  std::vector<double> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (double, w, n);\n\n  m_chol_mat.resize (n+1, n+1);\n  F77_INT ldcm = to_f77_int (m_chol_mat.rows ());\n\n  F77_XFCN (dchinx, DCHINX, (n, m_chol_mat.rwdata (), ldcm,\n                             j + 1, utmp.data (), w, info));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API void\nchol<Matrix>::delete_sym (octave_idx_type j_arg)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT j = to_f77_int (j_arg);\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"choldelete: index out of range\");\n\n  OCTAVE_LOCAL_BUFFER (double, w, n);\n\n  F77_XFCN (dchdex, DCHDEX, (n, m_chol_mat.rwdata (), n, j + 1, w));\n\n  m_chol_mat.resize (n-1, n-1);\n}\n\ntemplate <>\nOCTAVE_API void\nchol<Matrix>::shift_sym (octave_idx_type i_arg, octave_idx_type j_arg)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT i = to_f77_int (i_arg);\n  F77_INT j = to_f77_int (j_arg);\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"cholshift: index out of range\");\n\n  OCTAVE_LOCAL_BUFFER (double, w, 2*n);\n\n  F77_XFCN (dchshx, DCHSHX, (n, m_chol_mat.rwdata (), n,\n                             i + 1, j + 1, w));\n}\n\n#endif\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<FloatMatrix>::init (const FloatMatrix& a, bool upper, bool calc_cond)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"chol: requires square matrix\");\n\n  F77_INT n = to_f77_int (a_nc);\n  F77_INT info;\n\n  m_is_upper = upper;\n\n  m_chol_mat.clear (n, n);\n  if (m_is_upper)\n    for (octave_idx_type j = 0; j < n; j++)\n      {\n        for (octave_idx_type i = 0; i <= j; i++)\n          m_chol_mat.xelem (i, j) = a(i, j);\n        for (octave_idx_type i = j+1; i < n; i++)\n          m_chol_mat.xelem (i, j) = 0.0f;\n      }\n  else\n    for (octave_idx_type j = 0; j < n; j++)\n      {\n        for (octave_idx_type i = 0; i < j; i++)\n          m_chol_mat.xelem (i, j) = 0.0f;\n        for (octave_idx_type i = j; i < n; i++)\n          m_chol_mat.xelem (i, j) = a(i, j);\n      }\n  float *h = m_chol_mat.rwdata ();\n\n  // Calculate the norm of the matrix, for later use.\n  float anorm = 0;\n  if (calc_cond)\n    anorm = octave::xnorm (a, 1);\n\n  if (m_is_upper)\n    F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (\"U\", 1), n, h, n, info\n                               F77_CHAR_ARG_LEN (1)));\n  else\n    F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (\"L\", 1), n, h, n, info\n                               F77_CHAR_ARG_LEN (1)));\n\n  m_rcond = 0.0;\n  if (info > 0)\n    m_chol_mat.resize (info - 1, info - 1);\n  else if (calc_cond)\n    {\n      F77_INT spocon_info = 0;\n\n      // Now calculate the condition number for non-singular matrix.\n      Array<float> z (dim_vector (3*n, 1));\n      float *pz = z.rwdata ();\n      OCTAVE_LOCAL_BUFFER (F77_INT, iz, n);\n      if (m_is_upper)\n        F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (\"U\", 1), n, h,\n                                   n, anorm, m_rcond, pz, iz, spocon_info\n                                   F77_CHAR_ARG_LEN (1)));\n      else\n        F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (\"L\", 1), n, h,\n                                   n, anorm, m_rcond, pz, iz, spocon_info\n                                   F77_CHAR_ARG_LEN (1)));\n\n      if (spocon_info != 0)\n        info = -1;\n    }\n\n  return info;\n}\n\n#if defined (HAVE_QRUPDATE)\n\ntemplate <>\nOCTAVE_API void\nchol<FloatMatrix>::update (const FloatColumnVector& u)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  std::vector<float> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (float, w, n);\n\n  F77_XFCN (sch1up, SCH1UP, (n, m_chol_mat.rwdata (), n,\n                             utmp.data (), w));\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<FloatMatrix>::downdate (const FloatColumnVector& u)\n{\n  F77_INT info = -1;\n\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  std::vector<float> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (float, w, n);\n\n  F77_XFCN (sch1dn, SCH1DN, (n, m_chol_mat.rwdata (), n,\n                             utmp.data (), w, info));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<FloatMatrix>::insert_sym (const FloatColumnVector& u,\n                               octave_idx_type j_arg)\n{\n  F77_INT info = -1;\n\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT j = to_f77_int (j_arg);\n\n  if (u.numel () != n + 1)\n    (*current_liboctave_error_handler) (\"cholinsert: dimension mismatch\");\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"cholinsert: index out of range\");\n\n  std::vector<float> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (float, w, n);\n\n  m_chol_mat.resize (n+1, n+1);\n  F77_INT ldcm = to_f77_int (m_chol_mat.rows ());\n\n  F77_XFCN (schinx, SCHINX, (n, m_chol_mat.rwdata (), ldcm,\n                             j + 1, utmp.data (), w, info));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API void\nchol<FloatMatrix>::delete_sym (octave_idx_type j_arg)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT j = to_f77_int (j_arg);\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"choldelete: index out of range\");\n\n  OCTAVE_LOCAL_BUFFER (float, w, n);\n\n  F77_XFCN (schdex, SCHDEX, (n, m_chol_mat.rwdata (), n,\n                             j + 1, w));\n\n  m_chol_mat.resize (n-1, n-1);\n}\n\ntemplate <>\nOCTAVE_API void\nchol<FloatMatrix>::shift_sym (octave_idx_type i_arg, octave_idx_type j_arg)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT i = to_f77_int (i_arg);\n  F77_INT j = to_f77_int (j_arg);\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"cholshift: index out of range\");\n\n  OCTAVE_LOCAL_BUFFER (float, w, 2*n);\n\n  F77_XFCN (schshx, SCHSHX, (n, m_chol_mat.rwdata (), n,\n                             i + 1, j + 1, w));\n}\n\n#endif\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<ComplexMatrix>::init (const ComplexMatrix& a, bool upper, bool calc_cond)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"chol: requires square matrix\");\n\n  F77_INT n = to_f77_int (a_nc);\n  F77_INT info;\n\n  m_is_upper = upper;\n\n  m_chol_mat.clear (n, n);\n  if (m_is_upper)\n    for (octave_idx_type j = 0; j < n; j++)\n      {\n        for (octave_idx_type i = 0; i <= j; i++)\n          m_chol_mat.xelem (i, j) = a(i, j);\n        for (octave_idx_type i = j+1; i < n; i++)\n          m_chol_mat.xelem (i, j) = 0.0;\n      }\n  else\n    for (octave_idx_type j = 0; j < n; j++)\n      {\n        for (octave_idx_type i = 0; i < j; i++)\n          m_chol_mat.xelem (i, j) = 0.0;\n        for (octave_idx_type i = j; i < n; i++)\n          m_chol_mat.xelem (i, j) = a(i, j);\n      }\n  Complex *h = m_chol_mat.rwdata ();\n\n  // Calculate the norm of the matrix, for later use.\n  double anorm = 0;\n  if (calc_cond)\n    anorm = octave::xnorm (a, 1);\n\n  if (m_is_upper)\n    F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (\"U\", 1), n,\n                               F77_DBLE_CMPLX_ARG (h), n, info\n                               F77_CHAR_ARG_LEN (1)));\n  else\n    F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (\"L\", 1), n,\n                               F77_DBLE_CMPLX_ARG (h), n, info\n                               F77_CHAR_ARG_LEN (1)));\n\n  m_rcond = 0.0;\n  if (info > 0)\n    m_chol_mat.resize (info - 1, info - 1);\n  else if (calc_cond)\n    {\n      F77_INT zpocon_info = 0;\n\n      // Now calculate the condition number for non-singular matrix.\n      Array<Complex> z (dim_vector (2*n, 1));\n      Complex *pz = z.rwdata ();\n      Array<double> rz (dim_vector (n, 1));\n      double *prz = rz.rwdata ();\n      F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (\"U\", 1), n,\n                                 F77_DBLE_CMPLX_ARG (h), n, anorm, m_rcond,\n                                 F77_DBLE_CMPLX_ARG (pz), prz, zpocon_info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (zpocon_info != 0)\n        info = -1;\n    }\n\n  return info;\n}\n\n#if defined (HAVE_QRUPDATE)\n\ntemplate <>\nOCTAVE_API void\nchol<ComplexMatrix>::update (const ComplexColumnVector& u)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  std::vector<Complex> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (double, rw, n);\n\n  F77_XFCN (zch1up, ZCH1UP, (n,\n                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             n,\n                             F77_DBLE_CMPLX_ARG (utmp.data ()),\n                             rw));\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<ComplexMatrix>::downdate (const ComplexColumnVector& u)\n{\n  F77_INT info = -1;\n\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  std::vector<Complex> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (double, rw, n);\n\n  F77_XFCN (zch1dn, ZCH1DN, (n,\n                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             n,\n                             F77_DBLE_CMPLX_ARG (utmp.data ()),\n                             rw, info));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<ComplexMatrix>::insert_sym (const ComplexColumnVector& u,\n                                 octave_idx_type j_arg)\n{\n  F77_INT info = -1;\n\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT j = to_f77_int (j_arg);\n\n  if (u.numel () != n + 1)\n    (*current_liboctave_error_handler) (\"cholinsert: dimension mismatch\");\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"cholinsert: index out of range\");\n\n  std::vector<Complex> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (double, rw, n);\n\n  m_chol_mat.resize (n+1, n+1);\n  F77_INT ldcm = to_f77_int (m_chol_mat.rows ());\n\n  F77_XFCN (zchinx, ZCHINX, (n,\n                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             ldcm, j + 1,\n                             F77_DBLE_CMPLX_ARG (utmp.data ()),\n                             rw, info));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API void\nchol<ComplexMatrix>::delete_sym (octave_idx_type j_arg)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT j = to_f77_int (j_arg);\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"choldelete: index out of range\");\n\n  OCTAVE_LOCAL_BUFFER (double, rw, n);\n\n  F77_XFCN (zchdex, ZCHDEX, (n,\n                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             n, j + 1, rw));\n\n  m_chol_mat.resize (n-1, n-1);\n}\n\ntemplate <>\nOCTAVE_API void\nchol<ComplexMatrix>::shift_sym (octave_idx_type i_arg,\n                                octave_idx_type j_arg)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT i = to_f77_int (i_arg);\n  F77_INT j = to_f77_int (j_arg);\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"cholshift: index out of range\");\n\n  OCTAVE_LOCAL_BUFFER (Complex, w, n);\n  OCTAVE_LOCAL_BUFFER (double, rw, n);\n\n  F77_XFCN (zchshx, ZCHSHX, (n,\n                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             n, i + 1, j + 1,\n                             F77_DBLE_CMPLX_ARG (w), rw));\n}\n\n#endif\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<FloatComplexMatrix>::init (const FloatComplexMatrix& a, bool upper,\n                                bool calc_cond)\n{\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"chol: requires square matrix\");\n\n  F77_INT n = to_f77_int (a_nc);\n  F77_INT info;\n\n  m_is_upper = upper;\n\n  m_chol_mat.clear (n, n);\n  if (m_is_upper)\n    for (octave_idx_type j = 0; j < n; j++)\n      {\n        for (octave_idx_type i = 0; i <= j; i++)\n          m_chol_mat.xelem (i, j) = a(i, j);\n        for (octave_idx_type i = j+1; i < n; i++)\n          m_chol_mat.xelem (i, j) = 0.0f;\n      }\n  else\n    for (octave_idx_type j = 0; j < n; j++)\n      {\n        for (octave_idx_type i = 0; i < j; i++)\n          m_chol_mat.xelem (i, j) = 0.0f;\n        for (octave_idx_type i = j; i < n; i++)\n          m_chol_mat.xelem (i, j) = a(i, j);\n      }\n  FloatComplex *h = m_chol_mat.rwdata ();\n\n  // Calculate the norm of the matrix, for later use.\n  float anorm = 0;\n  if (calc_cond)\n    anorm = octave::xnorm (a, 1);\n\n  if (m_is_upper)\n    F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (\"U\", 1),\n                               n, F77_CMPLX_ARG (h), n, info\n                               F77_CHAR_ARG_LEN (1)));\n  else\n    F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (\"L\", 1),\n                               n, F77_CMPLX_ARG (h), n, info\n                               F77_CHAR_ARG_LEN (1)));\n\n  m_rcond = 0.0;\n  if (info > 0)\n    m_chol_mat.resize (info - 1, info - 1);\n  else if (calc_cond)\n    {\n      F77_INT cpocon_info = 0;\n\n      // Now calculate the condition number for non-singular matrix.\n      Array<FloatComplex> z (dim_vector (2*n, 1));\n      FloatComplex *pz = z.rwdata ();\n      Array<float> rz (dim_vector (n, 1));\n      float *prz = rz.rwdata ();\n      F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (\"U\", 1), n,\n                                 F77_CMPLX_ARG (h), n, anorm, m_rcond,\n                                 F77_CMPLX_ARG (pz), prz, cpocon_info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (cpocon_info != 0)\n        info = -1;\n    }\n\n  return info;\n}\n\n#if defined (HAVE_QRUPDATE)\n\ntemplate <>\nOCTAVE_API void\nchol<FloatComplexMatrix>::update (const FloatComplexColumnVector& u)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  std::vector<FloatComplex> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (float, rw, n);\n\n  F77_XFCN (cch1up, CCH1UP, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             n, F77_CMPLX_ARG (utmp.data ()), rw));\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<FloatComplexMatrix>::downdate (const FloatComplexColumnVector& u)\n{\n  F77_INT info = -1;\n\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n\n  if (u.numel () != n)\n    (*current_liboctave_error_handler) (\"cholupdate: dimension mismatch\");\n\n  std::vector<FloatComplex> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (float, rw, n);\n\n  F77_XFCN (cch1dn, CCH1DN, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             n, F77_CMPLX_ARG (utmp.data ()),\n                             rw, info));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nchol<FloatComplexMatrix>::insert_sym (const FloatComplexColumnVector& u,\n                                      octave_idx_type j_arg)\n{\n  F77_INT info = -1;\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n\n  if (u.numel () != n + 1)\n    (*current_liboctave_error_handler) (\"cholinsert: dimension mismatch\");\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"cholinsert: index out of range\");\n\n  std::vector<FloatComplex> utmp (u.data (), u.data () + u.numel ());\n\n  OCTAVE_LOCAL_BUFFER (float, rw, n);\n\n  m_chol_mat.resize (n+1, n+1);\n  F77_INT ldcm = to_f77_int (m_chol_mat.rows ());\n\n  F77_XFCN (cchinx, CCHINX, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             ldcm, j + 1,\n                             F77_CMPLX_ARG (utmp.data ()),\n                             rw, info));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API void\nchol<FloatComplexMatrix>::delete_sym (octave_idx_type j_arg)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT j = to_f77_int (j_arg);\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"choldelete: index out of range\");\n\n  OCTAVE_LOCAL_BUFFER (float, rw, n);\n\n  F77_XFCN (cchdex, CCHDEX, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             n, j + 1, rw));\n\n  m_chol_mat.resize (n-1, n-1);\n}\n\ntemplate <>\nOCTAVE_API void\nchol<FloatComplexMatrix>::shift_sym (octave_idx_type i_arg,\n                                     octave_idx_type j_arg)\n{\n  F77_INT n = to_f77_int (m_chol_mat.rows ());\n  F77_INT i = to_f77_int (i_arg);\n  F77_INT j = to_f77_int (j_arg);\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"cholshift: index out of range\");\n\n  OCTAVE_LOCAL_BUFFER (FloatComplex, w, n);\n  OCTAVE_LOCAL_BUFFER (float, rw, n);\n\n  F77_XFCN (cchshx, CCHSHX, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),\n                             n, i + 1, j + 1, F77_CMPLX_ARG (w), rw));\n}\n\n#endif\n\n// Instantiations we need.\n\ntemplate class chol<Matrix>;\n\ntemplate class chol<FloatMatrix>;\n\ntemplate class chol<ComplexMatrix>;\n\ntemplate class chol<FloatComplexMatrix>;\n\ntemplate OCTAVE_API Matrix\nchol2inv<Matrix> (const Matrix& r);\n\ntemplate OCTAVE_API ComplexMatrix\nchol2inv<ComplexMatrix> (const ComplexMatrix& r);\n\ntemplate OCTAVE_API FloatMatrix\nchol2inv<FloatMatrix> (const FloatMatrix& r);\n\ntemplate OCTAVE_API FloatComplexMatrix\nchol2inv<FloatComplexMatrix> (const FloatComplexMatrix& r);\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/chol.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_chol_h)\n#define octave_chol_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nclass chol\n{\npublic:\n\n  typedef typename T::column_vector_type VT;\n  typedef typename T::real_elt_type COND_T;\n\n  chol () : m_chol_mat (), m_rcond (0), m_is_upper (true) { }\n\n  chol (const T& a, bool upper = true, bool calc_cond = false)\n    : m_chol_mat (), m_rcond (0)\n  {\n    init (a, upper, calc_cond);\n  }\n\n  chol (const T& a, octave_idx_type& info, bool upper = true,\n        bool calc_cond = false)\n    : m_chol_mat (), m_rcond (0)\n  {\n    info = init (a, upper, calc_cond);\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (chol)\n\n  T chol_matrix () const { return m_chol_mat; }\n\n  COND_T rcond () const { return m_rcond; }\n\n  // Compute the inverse of a matrix using the Cholesky factorization.\n  OCTAVE_API T inverse () const;\n\n  OCTAVE_API void set (const T& R);\n\n  OCTAVE_API void update (const VT& u);\n\n  OCTAVE_API octave_idx_type downdate (const VT& u);\n\n  OCTAVE_API octave_idx_type insert_sym (const VT& u, octave_idx_type j);\n\n  OCTAVE_API void delete_sym (octave_idx_type j);\n\n  OCTAVE_API void shift_sym (octave_idx_type i, octave_idx_type j);\n\nprivate:\n\n  T m_chol_mat;\n\n  COND_T m_rcond;\n\n  bool m_is_upper;\n\n  OCTAVE_API octave_idx_type init (const T& a, bool upper, bool calc_cond);\n};\n\ntemplate <typename T>\nOCTAVE_API T\nchol2inv (const T& r);\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/eigs-base.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <ostream>\n\n#include \"Array-oct.h\"\n#include \"CSparse.h\"\n#include \"MatrixType.h\"\n#include \"PermMatrix.h\"\n#include \"arpack-proto.h\"\n#include \"blas-proto.h\"\n#include \"chol.h\"\n#include \"dSparse.h\"\n#include \"eigs-base.h\"\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"lu.h\"\n#include \"mx-ops.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-rand.h\"\n#include \"sparse-chol.h\"\n#include \"sparse-lu.h\"\n\n#if defined (HAVE_ARPACK)\n\nstatic void\nwarn_convergence ()\n{\n  (*current_liboctave_warning_with_id_handler)\n    (\"Octave:convergence\",\n     \"eigs: 'A - sigma*B' is singular, indicating sigma is exactly \"\n     \"an eigenvalue so convergence is not guaranteed\");\n}\n\n// Conversion from error number to strings\nstd::string\narpack_errno2str (const octave_idx_type& errnum, const std::string& fcn_name)\n{\n  std::string msg;\n  std::string bug_msg = \"\\nThis should not happen.  Please, see https://www.gnu.org/software/octave/bugs.html, and file a bug report\";\n\n  switch (errnum)\n    {\n    case -1:\n      msg = \"N must be positive\";\n      break;\n\n    case -2:\n      msg = \"NEV must be positive\";\n      break;\n\n    case -3:\n      msg = \"NCV-NEV >= 2 and less than or equal to N\";\n      break;\n\n    case -4:\n      msg = \"The maximum number of Arnoldi update iterations allowed must be greater than zero\";\n      break;\n\n    case -5:\n      msg = \"WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'\";\n      break;\n\n    case -6:\n      msg = \"BMAT must be one of 'I' or 'G'\";\n      break;\n\n    case -7:\n      msg = \"Length of private work WORKL array is insufficient\";\n      break;\n\n    case -8:\n      msg = \"Error return from LAPACK eigenvalue calculation\";\n      break;\n\n    case -9:\n      if (fcn_name.compare (\"zneupd\") == 0)\n        msg = \"Error return from calculation of eigenvectors.  Informational error from LAPACK routine ztrevc\";\n      else if (fcn_name.compare (\"dneupd\") == 0)\n        msg = \"Error return from calculation of eigenvectors.  Informational error from LAPACK routine dtrevc\";\n      else\n        msg = \"Starting vector is zero\";\n\n      break;\n\n    case -10:\n      if (fcn_name.compare (\"dneupd\") == 0\n          || fcn_name.compare (\"dnaupd\") == 0)\n        msg = \"IPARAM(7) must be 1,2,3,4\";\n      else if (fcn_name.compare (\"zneupd\") == 0\n               || fcn_name.compare (\"znaupd\") == 0)\n        msg = \"IPARAM(7) must be 1,2,3\";\n      else\n        msg = \"IPARAM(7) must be 1,2,3,4,5\";\n\n      break;\n\n    case -11:\n      msg = \"IPARAM(7) = 1 and BMAT = 'G' are incompatible\";\n      break;\n\n    case -12:\n      if (fcn_name.compare (\"dnaupd\") == 0\n          || fcn_name.compare (\"znaupd\") == 0\n          || fcn_name.compare (\"dsaupd\") == 0)\n        msg = std::string (\"IPARAM(1) must be equal to 0 or 1\");\n      else if (fcn_name.compare (\"dneupd\") == 0\n               || fcn_name.compare (\"zneupd\") == 0)\n        msg = \"HOWMNY = 'S' not yet implemented\";\n      else\n        msg = \"NEV and WHICH = 'BE' are incompatible\";\n\n      break;\n\n    case -13:\n      if (fcn_name.compare (\"dneupd\") == 0\n          || fcn_name.compare (\"zneupd\") == 0)\n        msg = \"HOWMNY must be one of 'A' or 'P' if RVEC = .true.\";\n      else if (fcn_name.compare (\"dsaupd\") == 0)\n        msg = \"NEV and WHICH = 'BE' are incompatible\";\n\n      break;\n\n    case -14:\n      if (fcn_name.compare (\"dneupd\") == 0)\n        msg = \"DNAUPD did not find any eigenvalues to sufficient accuracy.\";\n      else if (fcn_name.compare (\"zneupd\") == 0)\n        msg = \"ZNAUPD did not find any eigenvalues to sufficient accuracy.\";\n      else if (fcn_name.compare (\"dseupd\") == 0)\n        msg = \"DSAUPD did not find any eigenvalues to sufficient accuracy.\";\n\n      msg += \"  Consider changing tolerance (TOL), maximum iterations (MAXIT), number of Lanzcos basis vectors (P), or starting vector (V0) in OPTS structure.\";\n\n      break;\n\n    case -15:\n      if (fcn_name.compare (\"dseupd\") == 0)\n        msg = \"HOWMNY must be one of 'A' or 'S' if RVEC = .true.\";\n\n      break;\n\n    case -16:\n      if (fcn_name.compare (\"dseupd\") == 0)\n        msg = \"HOWMNY = 'S' not yet implemented\";\n\n      break;\n\n    case -9999:\n      if (fcn_name.compare (\"dnaupd\") == 0)\n        msg = \"Could not build an Arnoldi factorization.  IPARAM(5) returns the size of the current Arnoldi factorization\";\n\n      break;\n\n    case 1:\n      if (fcn_name.compare (\"dneupd\") == 0)\n        msg = \"The Schur form computed by LAPACK routine dlahqr could not be reordered by LAPACK routine dtrsen.  Re-enter subroutine DNEUPD with IPARAM(5)=NCV and increase the size of the arrays DR and DI to have dimension at least dimension NCV and allocate at least NCV columns for Z.  NOTE: Not necessary if Z and V share the same space.  Please notify the authors if this error occurs.\";\n      else if (fcn_name.compare (\"dnaupd\") == 0\n               || fcn_name.compare (\"znaupd\") == 0\n               || fcn_name.compare (\"dsaupd\") == 0)\n        msg = \"Maximum number of iterations taken.  All possible eigenvalues of OP has been found.  IPARAM(5) returns the number of wanted converged Ritz values\";\n      else if (fcn_name.compare (\"znaupd\") == 0)\n        msg = \"The Schur form computed by LAPACK routine csheqr could not be reordered by LAPACK routine ztrsen.  Re-enter subroutine ZNEUPD with IPARAM(5)=NCV and increase the size of the array D to have dimension at least dimension NCV and allocate at least NCV columns for Z.  NOTE: Not necessary if Z and V share the same space.  Please notify the authors if this error occurs.\";\n\n      break;\n\n    case 2:\n      if (fcn_name.compare (\"dnaupd\") == 0\n          || fcn_name.compare (\"znaupd\") == 0\n          || fcn_name.compare (\"dsaupd\") == 0)\n        msg = \"No longer an informational error.  Deprecated starting with release 2 of ARPACK.\";\n\n      break;\n\n    case 3:\n      if (fcn_name.compare (\"dnaupd\") == 0\n          || fcn_name.compare (\"znaupd\") == 0\n          || fcn_name.compare (\"dsaupd\") == 0)\n        msg = \"No shifts could be applied during a cycle of the implicitly restarted Arnoldi iteration.  One possibility is to increase the size of NCV relative to NEV.\";\n\n      break;\n\n    }\n\n  if ((errnum != -9) && (errnum != -14) && (errnum != -9999))\n    msg.append (bug_msg);  // This is a bug in Octave interface to ARPACK\n\n  return msg;\n}\n\ntemplate <typename M, typename SM>\nstatic octave_idx_type\nlusolve (const SM& L, const SM& U, M& m)\n{\n  octave_idx_type err = 0;\n  double rcond;\n  MatrixType utyp (MatrixType::Upper);\n\n  // Sparse L is lower triangular, Dense L is permuted lower triangular!!!\n  MatrixType ltyp (MatrixType::Lower);\n  m = L.solve (ltyp, m, err, rcond, nullptr);\n  if (err)\n    return err;\n\n  m = U.solve (utyp, m, err, rcond, nullptr);\n\n  return err;\n}\n\ntemplate <typename SM, typename M>\nstatic M\nltsolve (const SM& L, const ColumnVector& Q, const M& m)\n{\n  // Solve (Q_mat * L) * x = m, that is L * x = Q_mat' * m = m(Q)\n  octave_idx_type n = L.cols ();\n  octave_idx_type b_nc = m.cols ();\n  octave_idx_type err = 0;\n  double rcond;\n  MatrixType ltyp (MatrixType::Lower);\n  M retval (n, b_nc);\n  const double *qv = Q.data ();\n  for (octave_idx_type j = 0; j < b_nc; j++)\n    {\n      for (octave_idx_type i = 0; i < n; i++)\n        retval.elem (i, j) = m.elem (static_cast<octave_idx_type> (qv[i]), j);\n    }\n  return L.solve (ltyp, retval, err, rcond, nullptr);\n}\n\ntemplate <typename SM, typename M>\nstatic M\nutsolve (const SM& U, const ColumnVector& Q, const M& m)\n{\n  // Solve (U * Q_mat') * x = m by U * tmp = m, x(Q) = tmp (Q_mat * tmp = x)\n  octave_idx_type n = U.cols ();\n  octave_idx_type b_nc = m.cols ();\n  octave_idx_type err = 0;\n  double rcond;\n  MatrixType utyp (MatrixType::Upper);\n  M tmp = U.solve (utyp, m, err, rcond, nullptr);\n  M retval;\n  const double *qv = Q.data ();\n\n  if (! err)\n    {\n      retval.resize (n, b_nc);\n      for (octave_idx_type j = 0; j < b_nc; j++)\n        {\n          for (octave_idx_type i = 0; i < n; i++)\n            retval.elem (static_cast<octave_idx_type> (qv[i]), j)\n              = tmp.elem (i, j);\n        }\n    }\n\n  return retval;\n}\n\nstatic bool\nvector_product (const SparseMatrix& m, const double *x, double *y)\n{\n  octave_idx_type nc = m.cols ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    y[j] = 0.;\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n      y[m.ridx (i)] += m.data (i) * x[j];\n\n  return true;\n}\n\nstatic bool\nvector_product (const Matrix& m, const double *x, double *y)\n{\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_XFCN (dgemv, DGEMV, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                           nr, nc, 1.0, m.data (), nr,\n                           x, 1, 0.0, y, 1\n                           F77_CHAR_ARG_LEN (1)));\n\n  return true;\n}\n\nstatic bool\nvector_product (const SparseComplexMatrix& m, const Complex *x,\n                Complex *y)\n{\n  octave_idx_type nc = m.cols ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    y[j] = 0.;\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)\n      y[m.ridx (i)] += m.data (i) * x[j];\n\n  return true;\n}\n\nstatic bool\nvector_product (const ComplexMatrix& m, const Complex *x, Complex *y)\n{\n  F77_INT nr = octave::to_f77_int (m.rows ());\n  F77_INT nc = octave::to_f77_int (m.cols ());\n\n  F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                           nr, nc, 1.0, F77_CONST_DBLE_CMPLX_ARG (m.data ()),\n                           nr,\n                           F77_CONST_DBLE_CMPLX_ARG (x), 1, 0.0,\n                           F77_DBLE_CMPLX_ARG (y), 1\n                           F77_CHAR_ARG_LEN (1)));\n\n  return true;\n}\n\nstatic bool\nmake_cholb (Matrix& b, Matrix& bt, ColumnVector& permB)\n{\n  octave_idx_type info;\n  octave::math::chol<Matrix> fact (b, info);\n  octave_idx_type n = b.cols ();\n\n  if (info != 0)\n    return false;\n  else\n    {\n      bt = fact.chol_matrix (); // upper triangular\n      b = bt.transpose ();\n      permB = ColumnVector (n);\n      for (octave_idx_type i = 0; i < n; i++)\n        permB(i) = i;\n      return true;\n    }\n}\n\nstatic bool\nmake_cholb (SparseMatrix& b, SparseMatrix& bt, ColumnVector& permB)\n{\n  octave_idx_type info;\n  octave::math::sparse_chol<SparseMatrix> fact (b, info, false);\n\n  if (info != 0)\n    return false;\n  else\n    {\n      b = fact.L (); // lower triangular\n      bt = b.transpose ();\n      permB = fact.perm () - 1.0;\n      return true;\n    }\n}\n\nstatic bool\nmake_cholb (ComplexMatrix& b, ComplexMatrix& bt, ColumnVector& permB)\n{\n  octave_idx_type info;\n  octave::math::chol<ComplexMatrix> fact (b, info);\n  octave_idx_type n = b.cols ();\n\n  if (info != 0)\n    return false;\n  else\n    {\n      bt = fact.chol_matrix (); // upper triangular\n      b = bt.hermitian ();\n      permB = ColumnVector (n);\n      for (octave_idx_type i = 0; i < n; i++)\n        permB(i) = i;\n      return true;\n    }\n}\n\nstatic bool\nmake_cholb (SparseComplexMatrix& b, SparseComplexMatrix& bt,\n            ColumnVector& permB)\n{\n  octave_idx_type info;\n  octave::math::sparse_chol<SparseComplexMatrix> fact (b, info, false);\n\n  if (info != 0)\n    return false;\n  else\n    {\n      b = fact.L (); // lower triangular\n      bt = b.hermitian ();\n      permB = fact.perm () - 1.0;\n      return true;\n    }\n}\n\nstatic bool\nLuAminusSigmaB (const SparseMatrix& m, const SparseMatrix& b,\n                bool cholB, const ColumnVector& permB, double sigma,\n                SparseMatrix& L, SparseMatrix& U, octave_idx_type *P,\n                octave_idx_type *Q, ColumnVector& r)\n{\n  bool have_b = ! b.isempty ();\n  octave_idx_type n = m.rows ();\n\n  // Calculate LU decomposition of 'M = A - sigma * B'\n  // P * (R \\ M) * Q = L * U\n  SparseMatrix AminusSigmaB (m);\n\n  if (sigma != 0.0)\n    {\n      if (have_b)\n        {\n          if (cholB)\n            {\n              if (permB.numel ())\n                {\n                  SparseMatrix tmp (n, n, n);\n                  for (octave_idx_type i = 0; i < n; i++)\n                    {\n                      tmp.xcidx (i) = i;\n                      tmp.xridx (i) = static_cast<octave_idx_type> (permB(i));\n                      tmp.xdata (i) = 1;\n                    }\n                  tmp.xcidx (n) = n;\n\n                  AminusSigmaB -= sigma * tmp *\n                                  b.transpose () * b * tmp.transpose ();\n                }\n              else\n                AminusSigmaB -= sigma * b.transpose () * b;\n            }\n          else\n            AminusSigmaB -= sigma * b;\n        }\n      else\n        {\n          SparseMatrix sigmat (n, n, n);\n\n          // Create sigma * speye (n,n)\n          sigmat.xcidx (0) = 0;\n          for (octave_idx_type i = 0; i < n; i++)\n            {\n              sigmat.xdata (i) = sigma;\n              sigmat.xridx (i) = i;\n              sigmat.xcidx (i+1) = i + 1;\n            }\n\n          AminusSigmaB -= sigmat;\n        }\n    }\n\n  octave::math::sparse_lu<SparseMatrix> fact (AminusSigmaB, Matrix (), true);\n\n  L = fact.L ();\n  U = fact.U ();\n  SparseMatrix R = fact.R ();\n  for (octave_idx_type i = 0; i < n; i++)\n    r(i) = R.xdata(i);\n\n  const octave_idx_type *P2 = fact.row_perm ();\n  const octave_idx_type *Q2 = fact.col_perm ();\n\n  for (octave_idx_type j = 0; j < n; j++)\n    {\n      P[j] = P2[j];\n      Q[j] = Q2[j];\n    }\n\n  // Test condition number of LU decomposition\n  double minU = octave::numeric_limits<double>::NaN ();\n  double maxU = octave::numeric_limits<double>::NaN ();\n  for (octave_idx_type j = 0; j < n; j++)\n    {\n      double d = 0.;\n      if (U.xcidx (j+1) > U.xcidx (j)\n          && U.xridx (U.xcidx (j+1)-1) == j)\n        d = std::abs (U.xdata (U.xcidx (j+1)-1));\n\n      if (octave::math::isnan (minU) || d < minU)\n        minU = d;\n\n      if (octave::math::isnan (maxU) || d > maxU)\n        maxU = d;\n    }\n\n  double rcond = (minU / maxU);\n  // Prevent use of extra precision.\n  double rcond_plus_one = rcond + 1.0;\n\n  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))\n    warn_convergence ();\n\n  return true;\n}\n\nstatic bool\nLuAminusSigmaB (const Matrix& m, const Matrix& b,\n                bool cholB, const ColumnVector& permB, double sigma,\n                Matrix& L, Matrix& U, octave_idx_type *P, octave_idx_type *Q,\n                ColumnVector& r)\n{\n  bool have_b = ! b.isempty ();\n  octave_idx_type n = m.cols ();\n\n  // Calculate LU decomposition of 'M = A - sigma * B'\n  // P * M = L * U\n  Matrix AminusSigmaB (m);\n\n  if (sigma != 0.0)\n    {\n      if (have_b)\n        {\n          if (cholB)\n            {\n              Matrix tmp = sigma * b.transpose () * b;\n              const double *pB = permB.data ();\n              double *p = AminusSigmaB.rwdata ();\n\n              if (permB.numel ())\n                {\n                  for (octave_idx_type j = 0;\n                       j < b.cols (); j++)\n                    for (octave_idx_type i = 0;\n                         i < b.rows (); i++)\n                      *p++ -= tmp.xelem (static_cast<octave_idx_type> (pB[i]),\n                                         static_cast<octave_idx_type> (pB[j]));\n                }\n              else\n                AminusSigmaB -= tmp;\n            }\n          else\n            AminusSigmaB -= sigma * b;\n        }\n      else\n        {\n          double *p = AminusSigmaB.rwdata ();\n\n          for (octave_idx_type i = 0; i < n; i++)\n            p[i*(n+1)] -= sigma;\n        }\n    }\n\n  octave::math::lu<Matrix> fact (AminusSigmaB);\n\n  L = fact.L ();\n  U = fact.U ();\n  ColumnVector P2 = fact.P_vec();\n\n  for (octave_idx_type j = 0; j < n; j++)\n    {\n      Q[j] = j;\n      P[j] = P2(j) - 1;\n      r(j) = 1.;\n    }\n\n  // Test condition number of LU decomposition\n  double minU = octave::numeric_limits<double>::NaN ();\n  double maxU = octave::numeric_limits<double>::NaN ();\n  for (octave_idx_type j = 0; j < n; j++)\n    {\n      double d = std::abs (U.xelem (j, j));\n      if (octave::math::isnan (minU) || d < minU)\n        minU = d;\n\n      if (octave::math::isnan (maxU) || d > maxU)\n        maxU = d;\n    }\n\n  double rcond = (minU / maxU);\n  // Prevent use of extra precision.\n  double rcond_plus_one = rcond + 1.0;\n\n  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))\n    warn_convergence ();\n\n  return true;\n}\n\nstatic bool\nLuAminusSigmaB (const SparseComplexMatrix& m, const SparseComplexMatrix& b,\n                bool cholB, const ColumnVector& permB, Complex sigma,\n                SparseComplexMatrix& L, SparseComplexMatrix& U,\n                octave_idx_type *P, octave_idx_type *Q, ColumnVector& r)\n{\n  bool have_b = ! b.isempty ();\n  octave_idx_type n = m.rows ();\n\n  // Calculate LU decomposition of 'M = A - sigma * B'\n  // P * (R \\ M) * Q = L * U\n  SparseComplexMatrix AminusSigmaB (m);\n\n  if (std::real (sigma) != 0.0 || std::imag (sigma) != 0.0)\n    {\n      if (have_b)\n        {\n          if (cholB)\n            {\n              if (permB.numel ())\n                {\n                  SparseMatrix tmp (n, n, n);\n                  for (octave_idx_type i = 0; i < n; i++)\n                    {\n                      tmp.xcidx (i) = i;\n                      tmp.xridx (i) = static_cast<octave_idx_type> (permB(i));\n                      tmp.xdata (i) = 1;\n                    }\n                  tmp.xcidx (n) = n;\n\n                  AminusSigmaB -= tmp * b.hermitian () * b *\n                                  tmp.transpose () * sigma;\n                }\n              else\n                AminusSigmaB -= sigma * b.hermitian () * b;\n            }\n          else\n            AminusSigmaB -= sigma * b;\n        }\n      else\n        {\n          SparseComplexMatrix sigmat (n, n, n);\n\n          // Create sigma * speye (n,n)\n          sigmat.xcidx (0) = 0;\n          for (octave_idx_type i = 0; i < n; i++)\n            {\n              sigmat.xdata (i) = sigma;\n              sigmat.xridx (i) = i;\n              sigmat.xcidx (i+1) = i + 1;\n            }\n\n          AminusSigmaB -= sigmat;\n        }\n    }\n\n  octave::math::sparse_lu<SparseComplexMatrix> fact (AminusSigmaB, Matrix(),\n                                                     true);\n\n  L = fact.L ();\n  U = fact.U ();\n  SparseMatrix R = fact.R ();\n  for (octave_idx_type i = 0; i < n; i++)\n    r(i) = R.xdata(i);\n\n  const octave_idx_type *P2 = fact.row_perm ();\n  const octave_idx_type *Q2 = fact.col_perm ();\n\n  for (octave_idx_type j = 0; j < n; j++)\n    {\n      P[j] = P2[j];\n      Q[j] = Q2[j];\n    }\n\n  // Test condition number of LU decomposition\n  double minU = octave::numeric_limits<double>::NaN ();\n  double maxU = octave::numeric_limits<double>::NaN ();\n  for (octave_idx_type j = 0; j < n; j++)\n    {\n      double d = 0.;\n      if (U.xcidx (j+1) > U.xcidx (j)\n          && U.xridx (U.xcidx (j+1)-1) == j)\n        d = std::abs (U.xdata (U.xcidx (j+1)-1));\n\n      if (octave::math::isnan (minU) || d < minU)\n        minU = d;\n\n      if (octave::math::isnan (maxU) || d > maxU)\n        maxU = d;\n    }\n\n  double rcond = (minU / maxU);\n  // Prevent use of extra precision.\n  double rcond_plus_one = rcond + 1.0;\n\n  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))\n    warn_convergence ();\n\n  return true;\n}\n\nstatic bool\nLuAminusSigmaB (const ComplexMatrix& m, const ComplexMatrix& b,\n                bool cholB, const ColumnVector& permB, Complex sigma,\n                ComplexMatrix& L, ComplexMatrix& U, octave_idx_type *P,\n                octave_idx_type *Q, ColumnVector& r)\n{\n  bool have_b = ! b.isempty ();\n  octave_idx_type n = m.cols ();\n\n  // Calculate LU decomposition of 'M = A - sigma * B'\n  // P * M = L * U\n  ComplexMatrix AminusSigmaB (m);\n\n  if (std::real (sigma) != 0.0 || std::imag (sigma) != 0.0)\n    {\n      if (have_b)\n        {\n          if (cholB)\n            {\n              ComplexMatrix tmp = sigma * b.hermitian () * b;\n              const double *pB = permB.data ();\n              Complex *p = AminusSigmaB.rwdata ();\n\n              if (permB.numel ())\n                {\n                  for (octave_idx_type j = 0;\n                       j < b.cols (); j++)\n                    for (octave_idx_type i = 0;\n                         i < b.rows (); i++)\n                      *p++ -= tmp.xelem (static_cast<octave_idx_type> (pB[i]),\n                                         static_cast<octave_idx_type> (pB[j]));\n                }\n              else\n                AminusSigmaB -= tmp;\n            }\n          else\n            AminusSigmaB -= sigma * b;\n        }\n      else\n        {\n          Complex *p = AminusSigmaB.rwdata ();\n\n          for (octave_idx_type i = 0; i < n; i++)\n            p[i*(n+1)] -= sigma;\n        }\n    }\n\n  octave::math::lu<ComplexMatrix> fact (AminusSigmaB);\n\n  L = fact.L ();\n  U = fact.U ();\n  ColumnVector P2 = fact.P_vec ();\n\n  for (octave_idx_type j = 0; j < n; j++)\n    {\n      Q[j] = j;\n      P[j] = P2(j) - 1;\n      r(j) = 1.;\n    }\n\n  // Test condition number of LU decomposition\n  double minU = octave::numeric_limits<double>::NaN ();\n  double maxU = octave::numeric_limits<double>::NaN ();\n  for (octave_idx_type j = 0; j < n; j++)\n    {\n      double d = std::abs (U.xelem (j, j));\n      if (octave::math::isnan (minU) || d < minU)\n        minU = d;\n\n      if (octave::math::isnan (maxU) || d > maxU)\n        maxU = d;\n    }\n\n  double rcond = (minU / maxU);\n  // Prevent use of extra precision.\n  double rcond_plus_one = rcond + 1.0;\n\n  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))\n    warn_convergence ();\n\n  return true;\n}\n\ntemplate <typename M>\noctave_idx_type\nEigsRealSymmetricMatrix (const M& m, const std::string typ,\n                         octave_idx_type k_arg, octave_idx_type p_arg,\n                         octave_idx_type& info, Matrix& eig_vec,\n                         ColumnVector& eig_val, const M& _b,\n                         ColumnVector& permB, ColumnVector& resid,\n                         std::ostream& os, double tol, bool rvec,\n                         bool cholB, int disp, int maxit)\n{\n  F77_INT k = octave::to_f77_int (k_arg);\n  F77_INT p = octave::to_f77_int (p_arg);\n  M b(_b);\n  F77_INT n = octave::to_f77_int (m.cols ());\n  F77_INT mode = 1;\n  bool have_b = ! b.isempty ();\n  bool note3 = false;\n  char bmat = 'I';\n  double sigma = 0.;\n  M bt;\n\n  if (m.rows () != m.cols ())\n    (*current_liboctave_error_handler) (\"eigs: A must be square\");\n  if (have_b && (m.rows () != b.rows () || m.rows () != b.cols ()))\n    (*current_liboctave_error_handler)\n      (\"eigs: B must be square and the same size as A\");\n\n  if (resid.isempty ())\n    {\n      std::string rand_dist = octave::rand::distribution ();\n      octave::rand::distribution (\"uniform\");\n      resid = ColumnVector (octave::rand::vector (n));\n      octave::rand::distribution (rand_dist);\n    }\n  else if (m.cols () != resid.numel ())\n    (*current_liboctave_error_handler) (\"eigs: opts.v0 must be n-by-1\");\n\n  if (n < 3)\n    (*current_liboctave_error_handler) (\"eigs: n must be at least 3\");\n\n  if (p < 0)\n    {\n      p = k * 2;\n\n      if (p < 20)\n        p = 20;\n\n      if (p > n)\n        p = n;\n    }\n\n  if (k < 1 || k > n - 2)\n    (*current_liboctave_error_handler)\n      (\"eigs: Invalid number of eigenvalues to extract\"\n       \" (must be 0 < k < n-1-1).\\n\"\n       \"      Use 'eig (full (A))' instead\");\n\n  if (p <= k || p > n)\n    (*current_liboctave_error_handler)\n      (\"eigs: opts.p must be greater than k and less than or equal to n\");\n\n  if (have_b && cholB && ! permB.isempty ())\n    {\n      // Check the we really have a permutation vector\n      if (permB.numel () != n)\n        (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n\n      Array<bool> checked (dim_vector (n, 1), false);\n      for (F77_INT i = 0; i < n; i++)\n        {\n          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));\n\n          if (checked(bidx) || bidx < 0 || bidx >= n)\n            (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n        }\n    }\n\n  if (typ != \"LM\" && typ != \"SM\" && typ != \"LA\" && typ != \"SA\"\n      && typ != \"BE\" && typ != \"LR\" && typ != \"SR\" && typ != \"LI\"\n      && typ != \"SI\")\n    (*current_liboctave_error_handler) (\"eigs: unrecognized sigma value\");\n\n  if (typ == \"LI\" || typ == \"SI\" || typ == \"LR\" || typ == \"SR\")\n    (*current_liboctave_error_handler)\n      (\"eigs: invalid sigma value for real symmetric problem\");\n\n  if (have_b)\n    {\n      // See Note 3 dsaupd\n      note3 = true;\n      if (cholB)\n        {\n          bt = b;\n          b = b.transpose ();\n          if (permB.isempty ())\n            {\n              permB = ColumnVector (n);\n              for (F77_INT i = 0; i < n; i++)\n                permB(i) = i;\n            }\n        }\n      else\n        {\n          if (! make_cholb (b, bt, permB))\n            (*current_liboctave_error_handler)\n              (\"eigs: The matrix B is not positive definite\");\n        }\n    }\n\n  Array<F77_INT> ip (dim_vector (11, 1));\n  F77_INT *iparam = ip.rwdata ();\n\n  ip(0) = 1; //ishift\n  ip(1) = 0;   // ip(1) not referenced\n  ip(2) = maxit; // mxiter, maximum number of iterations\n  ip(3) = 1; // NB blocksize in recurrence\n  ip(4) = 0; // nconv, number of Ritz values that satisfy convergence\n  ip(5) = 0; //ip(5) not referenced\n  ip(6) = mode; // mode\n  ip(7) = 0;\n  ip(8) = 0;\n  ip(9) = 0;\n  ip(10) = 0;\n  // ip(7) to ip(10) return values\n\n  Array<F77_INT> iptr (dim_vector (14, 1));\n  F77_INT *ipntr = iptr.rwdata ();\n\n  F77_INT ido = 0;\n  int iter = 0;\n  F77_INT elems;\n  F77_INT lwork;\n\n  if (octave::math::int_multiply_overflow (n, p, &elems))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n  if (octave::math::int_multiply_overflow (p, p + 8, &lwork))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n\n  OCTAVE_LOCAL_BUFFER (double, v, elems);\n  OCTAVE_LOCAL_BUFFER (double, workl, lwork);\n  OCTAVE_LOCAL_BUFFER (double, workd, 3 * n);\n  double *presid = resid.rwdata ();\n\n  do\n    {\n      F77_INT tmp_info = octave::to_f77_int (info);\n\n      F77_FUNC (dsaupd, DSAUPD)\n      (ido, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n       F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n       k, tol, presid, p, v, n, iparam,\n       ipntr, workd, workl, lwork, tmp_info\n       F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n      info = tmp_info;\n\n      if (disp > 0 && ! octave::math::isnan (workl[iptr (5)-1]))\n        {\n          if (iter++)\n            {\n              os << \"Iteration \" << iter - 1 <<\n                 \": a few Ritz values of the \" << p << \"-by-\" <<\n                 p << \" matrix\\n\";\n              if (ido == 99) // convergence\n                {\n                  for (F77_INT i = 0; i < k; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n              else\n                {\n                  // the wanted Ritz estimates are at the end\n                  for (F77_INT i = p - k; i < p; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n            }\n\n          // This is a kludge, as ARPACK doesn't give its\n          // iteration pointer.  But as workl[iptr(5)-1] is\n          // an output value updated at each iteration, setting\n          // a value in this array to NaN and testing for it\n          // is a way of obtaining the iteration counter.\n          if (ido != 99)\n            workl[iptr(5)-1] = octave::numeric_limits<double>::NaN ();\n        }\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          if (have_b)\n            {\n              Matrix mtmp (n, 1);\n              for (F77_INT i = 0; i < n; i++)\n                mtmp(i, 0) = workd[i + iptr(0) - 1];\n\n              mtmp = ltsolve (b, permB, m * utsolve (bt, permB, mtmp));\n\n              for (F77_INT i = 0; i < n; i++)\n                workd[i+iptr(1)-1] = mtmp(i, 0);\n            }\n          else if (! vector_product (m, workd + iptr(0) - 1,\n                                     workd + iptr(1) - 1))\n            break;\n        }\n      else\n        {\n          if (info < 0)\n            (*current_liboctave_error_handler)\n              (\"eigs: error in dsaupd: %s\",\n               arpack_errno2str (info, \"dsaupd\").c_str ());\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT info2;\n\n  // We have a problem in that the size of the C++ bool\n  // type relative to the fortran logical type.  It appears\n  // that fortran uses 4- or 8-bytes per logical and C++ 1-byte\n  // per bool, though this might be system dependent.  As\n  // long as the HOWMNY arg is not \"S\", the logical array\n  // is just workspace for ARPACK, so use int type to\n  // avoid problems.\n  Array<F77_INT> s (dim_vector (p, 1));\n  F77_INT *sel = s.rwdata ();\n\n  eig_vec.resize (n, k);\n  double *z = eig_vec.rwdata ();\n\n  eig_val.resize (k);\n  double *d = eig_val.rwdata ();\n\n  F77_FUNC (dseupd, DSEUPD)\n  (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1), sel, d, z, n, sigma,\n   F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n   F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2), k, tol, presid, p, v, n, iparam,\n   ipntr, workd, workl, lwork, info2 F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(1)\n   F77_CHAR_ARG_LEN(2));\n\n  if (info2 == 0)\n    {\n      for (F77_INT i = ip(4); i < k; i++)\n        d[i] = octave::numeric_limits<double>::NaN ();\n      F77_INT k2 = ip(4) / 2;\n      if (typ != \"SM\" && typ != \"BE\" && ! (typ == \"SA\" && rvec))\n        {\n          for (F77_INT i = 0; i < k2; i++)\n            {\n              double dtmp = d[i];\n              d[i] = d[ip(4) - i - 1];\n              d[ip(4) - i - 1] = dtmp;\n            }\n        }\n\n      if (rvec)\n        {\n          for (F77_INT i = ip(4); i < k; i++)\n            {\n              F77_INT off1 = i * n;\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = octave::numeric_limits<double>::NaN ();\n            }\n          if (typ != \"SM\" && typ != \"BE\" && typ != \"SA\")\n            {\n              OCTAVE_LOCAL_BUFFER (double, dtmp, n);\n\n              for (F77_INT i = 0; i < k2; i++)\n                {\n                  F77_INT off1 = i * n;\n                  F77_INT off2 = (ip(4) - i - 1) * n;\n\n                  if (off1 == off2)\n                    continue;\n\n                  for (F77_INT j = 0; j < n; j++)\n                    dtmp[j] = z[off1 + j];\n\n                  for (F77_INT j = 0; j < n; j++)\n                    z[off1 + j] = z[off2 + j];\n\n                  for (F77_INT j = 0; j < n; j++)\n                    z[off2 + j] = dtmp[j];\n                }\n            }\n\n          if (note3)\n            eig_vec = utsolve (bt, permB, eig_vec);\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"eigs: error in dseupd: %s\",\n       arpack_errno2str (info2, \"dseupd\").c_str ());\n\n  return ip(4);\n}\n\ntemplate <typename M>\noctave_idx_type\nEigsRealSymmetricMatrixShift (const M& m, double sigma,\n                              octave_idx_type k_arg, octave_idx_type p_arg,\n                              octave_idx_type& info, Matrix& eig_vec,\n                              ColumnVector& eig_val, const M& _b,\n                              ColumnVector& permB, ColumnVector& resid,\n                              std::ostream& os, double tol, bool rvec,\n                              bool cholB, int disp, int maxit)\n{\n  F77_INT k = octave::to_f77_int (k_arg);\n  F77_INT p = octave::to_f77_int (p_arg);\n  M b(_b);\n  F77_INT n = octave::to_f77_int (m.cols ());\n  F77_INT mode = 3;\n  bool have_b = ! b.isempty ();\n  std::string typ = \"LM\";\n\n  if (m.rows () != m.cols ())\n    (*current_liboctave_error_handler) (\"eigs: A must be square\");\n  if (have_b && (m.rows () != b.rows () || m.rows () != b.cols ()))\n    (*current_liboctave_error_handler)\n      (\"eigs: B must be square and the same size as A\");\n\n  // FIXME: The \"SM\" type for mode 1 seems unstable though faster!!\n  //if (! std::abs (sigma))\n  //  return EigsRealSymmetricMatrix (m, \"SM\", k, p, info, eig_vec, eig_val,\n  //                                _b, permB, resid, os, tol, rvec, cholB,\n  //                                disp, maxit);\n\n  if (resid.isempty ())\n    {\n      std::string rand_dist = octave::rand::distribution ();\n      octave::rand::distribution (\"uniform\");\n      resid = ColumnVector (octave::rand::vector (n));\n      octave::rand::distribution (rand_dist);\n    }\n  else if (m.cols () != resid.numel ())\n    (*current_liboctave_error_handler) (\"eigs: opts.v0 must be n-by-1\");\n\n  if (n < 3)\n    (*current_liboctave_error_handler) (\"eigs: n must be at least 3\");\n\n  if (k <= 0 || k >= n - 1)\n    (*current_liboctave_error_handler)\n      (\"eigs: Invalid number of eigenvalues to extract\"\n       \" (must be 0 < k < n-1-1).\\n\"\n       \"      Use 'eig (full (A))' instead\");\n\n  if (p < 0)\n    {\n      p = k * 2;\n\n      if (p < 20)\n        p = 20;\n\n      if (p > n)\n        p = n;\n    }\n\n  if (p <= k || p > n)\n    (*current_liboctave_error_handler)\n      (\"eigs: opts.p must be greater than k and less than or equal to n\");\n\n  if (have_b && cholB && ! permB.isempty ())\n    {\n      // Check the we really have a permutation vector\n      if (permB.numel () != n)\n        (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n\n      Array<bool> checked (dim_vector (n, 1), false);\n      for (F77_INT i = 0; i < n; i++)\n        {\n          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));\n\n          if (checked(bidx) || bidx < 0 || bidx >= n)\n            (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n        }\n    }\n\n  char bmat = 'I';\n  if (have_b)\n    bmat = 'G';\n\n  Array<F77_INT> ip (dim_vector (11, 1));\n  F77_INT *iparam = ip.rwdata ();\n\n  ip(0) = 1; //ishift\n  ip(1) = 0;   // ip(1) not referenced\n  ip(2) = maxit; // mxiter, maximum number of iterations\n  ip(3) = 1; // NB blocksize in recurrence\n  ip(4) = 0; // nconv, number of Ritz values that satisfy convergence\n  ip(5) = 0; //ip(5) not referenced\n  ip(6) = mode; // mode\n  ip(7) = 0;\n  ip(8) = 0;\n  ip(9) = 0;\n  ip(10) = 0;\n  // ip(7) to ip(10) return values\n\n  Array<F77_INT> iptr (dim_vector (14, 1));\n  F77_INT *ipntr = iptr.rwdata ();\n\n  F77_INT ido = 0;\n  int iter = 0;\n  M L, U;\n  ColumnVector r(n);\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, P, (have_b ? b.rows () : m.rows ()));\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Q, (have_b ? b.cols () : m.cols ()));\n\n  if (! LuAminusSigmaB (m, b, cholB, permB, sigma, L, U, P, Q, r))\n    return -1;\n\n  F77_INT elems;\n  F77_INT lwork;\n\n  if (octave::math::int_multiply_overflow (n, p, &elems))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n  if (octave::math::int_multiply_overflow (p, p + 8, &lwork))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n\n  OCTAVE_LOCAL_BUFFER (double, v, elems);\n  OCTAVE_LOCAL_BUFFER (double, workl, lwork);\n  OCTAVE_LOCAL_BUFFER (double, workd, 3 * n);\n  double *presid = resid.rwdata ();\n\n  do\n    {\n      F77_INT tmp_info = octave::to_f77_int (info);\n\n      F77_FUNC (dsaupd, DSAUPD)\n      (ido, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n       F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n       k, tol, presid, p, v, n, iparam,\n       ipntr, workd, workl, lwork, tmp_info\n       F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n      info = tmp_info;\n\n      if (disp > 0 && ! octave::math::isnan (workl[iptr (5)-1]))\n        {\n          if (iter++)\n            {\n              os << \"Iteration \" << iter - 1 <<\n                 \": a few Ritz values of the \" << p << \"-by-\" <<\n                 p << \" matrix\\n\";\n              if (ido == 99) // convergence\n                {\n                  for (F77_INT i = 0; i < k; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n              else\n                {\n                  // the wanted Ritz estimates are at the end\n                  for (F77_INT i = p - k; i < p; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n            }\n\n          // This is a kludge, as ARPACK doesn't give its\n          // iteration pointer.  But as workl[iptr(5)-1] is\n          // an output value updated at each iteration, setting\n          // a value in this array to NaN and testing for it\n          // is a way of obtaining the iteration counter.\n          if (ido != 99)\n            workl[iptr(5)-1] = octave::numeric_limits<double>::NaN ();\n        }\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          if (have_b)\n            {\n              if (ido == -1)\n                {\n                  OCTAVE_LOCAL_BUFFER (double, dtmp, n);\n\n                  vector_product (b, workd+iptr(0)-1, dtmp);\n\n                  Matrix tmp (n, 1);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    tmp(i, 0) = dtmp[P[i]] / r(P[i]);\n\n                  lusolve (L, U, tmp);\n\n                  double *ip2 = workd+iptr(1)-1;\n                  for (F77_INT i = 0; i < n; i++)\n                    ip2[Q[i]] = tmp(i, 0);\n                }\n              else if (ido == 2)\n                vector_product (b, workd+iptr(0)-1, workd+iptr(1)-1);\n              else\n                {\n                  double *ip2 = workd+iptr(2)-1;\n                  Matrix tmp (n, 1);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    tmp(i, 0) = ip2[P[i]] / r(P[i]);\n\n                  lusolve (L, U, tmp);\n\n                  ip2 = workd+iptr(1)-1;\n                  for (F77_INT i = 0; i < n; i++)\n                    ip2[Q[i]] = tmp(i, 0);\n                }\n            }\n          else\n            {\n              // ido cannot be 2 for non-generalized problems (see dsaupd2).\n              double *ip2 = workd+iptr(0)-1;\n              Matrix tmp (n, 1);\n\n              for (F77_INT i = 0; i < n; i++)\n                tmp(i, 0) = ip2[P[i]] / r(P[i]);\n\n              lusolve (L, U, tmp);\n\n              ip2 = workd+iptr(1)-1;\n              for (F77_INT i = 0; i < n; i++)\n                ip2[Q[i]] = tmp(i, 0);\n            }\n        }\n      else\n        {\n          if (info < 0)\n            (*current_liboctave_error_handler)\n              (\"eigs: error in dsaupd: %s\",\n               arpack_errno2str (info, \"dsaupd\").c_str ());\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT info2;\n\n  // We have a problem in that the size of the C++ bool\n  // type relative to the fortran logical type.  It appears\n  // that fortran uses 4- or 8-bytes per logical and C++ 1-byte\n  // per bool, though this might be system dependent.  As\n  // long as the HOWMNY arg is not \"S\", the logical array\n  // is just workspace for ARPACK, so use int type to\n  // avoid problems.\n  Array<F77_INT> s (dim_vector (p, 1));\n  F77_INT *sel = s.rwdata ();\n\n  eig_vec.resize (n, k);\n  double *z = eig_vec.rwdata ();\n\n  eig_val.resize (k);\n  double *d = eig_val.rwdata ();\n\n  F77_FUNC (dseupd, DSEUPD)\n  (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1), sel, d, z, n, sigma,\n   F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n   F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n   k, tol, presid, p, v, n, iparam, ipntr, workd, workl, lwork, info2\n   F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n  if (info2 == 0)\n    {\n      for (F77_INT i = ip(4); i < k; i++)\n        d[i] = octave::numeric_limits<double>::NaN ();\n      F77_INT k2 = ip(4) / 2;\n      for (F77_INT i = 0; i < k2; i++)\n        {\n          double dtmp = d[i];\n          d[i] = d[ip(4) - i - 1];\n          d[ip(4) - i - 1] = dtmp;\n        }\n\n      if (rvec)\n        {\n          OCTAVE_LOCAL_BUFFER (double, dtmp, n);\n\n          for (F77_INT i = ip(4); i < k; i++)\n            {\n              F77_INT off1 = i * n;\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = octave::numeric_limits<double>::NaN ();\n            }\n          for (F77_INT i = 0; i < k2; i++)\n            {\n              F77_INT off1 = i * n;\n              F77_INT off2 = (ip(4) - i - 1) * n;\n\n              if (off1 == off2)\n                continue;\n\n              for (F77_INT j = 0; j < n; j++)\n                dtmp[j] = z[off1 + j];\n\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = z[off2 + j];\n\n              for (F77_INT j = 0; j < n; j++)\n                z[off2 + j] = dtmp[j];\n            }\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"eigs: error in dseupd: %s\",\n       arpack_errno2str (info2, \"dseupd\").c_str ());\n\n  return ip(4);\n}\n\ntemplate <typename M>\noctave_idx_type\nEigsRealSymmetricFunc (EigsFunc fcn, octave_idx_type n_arg,\n                       const std::string& _typ, double sigma,\n                       octave_idx_type k_arg, octave_idx_type p_arg,\n                       octave_idx_type& info, Matrix& eig_vec,\n                       ColumnVector& eig_val, const M& _b,\n                       ColumnVector& permB, ColumnVector& resid,\n                       std::ostream& os, double tol, bool rvec,\n                       bool cholB, int disp, int maxit)\n{\n  F77_INT n = octave::to_f77_int (n_arg);\n  F77_INT k = octave::to_f77_int (k_arg);\n  F77_INT p = octave::to_f77_int (p_arg);\n  M b(_b);\n  std::string typ (_typ);\n  bool have_sigma = (sigma ? true : false);\n  bool have_b = ! b.isempty ();\n  bool note3 = false;\n  char bmat = 'I';\n  F77_INT mode = 1;\n  int err = 0;\n  M bt;\n\n  if (resid.isempty ())\n    {\n      std::string rand_dist = octave::rand::distribution ();\n      octave::rand::distribution (\"uniform\");\n      resid = ColumnVector (octave::rand::vector (n));\n      octave::rand::distribution (rand_dist);\n    }\n  else if (n != resid.numel ())\n    (*current_liboctave_error_handler) (\"eigs: opts.v0 must be n-by-1\");\n\n  if (n < 3)\n    (*current_liboctave_error_handler) (\"eigs: n must be at least 3\");\n\n  if (p < 0)\n    {\n      p = k * 2;\n\n      if (p < 20)\n        p = 20;\n\n      if (p > n)\n        p = n;\n    }\n\n  if (k <= 0 || k >= n - 1)\n    (*current_liboctave_error_handler)\n      (\"eigs: Invalid number of eigenvalues to extract\"\n       \" (must be 0 < k < n-1).\\n\"\n       \"      Use 'eig (full (A))' instead\");\n\n  if (p <= k || p > n)\n    (*current_liboctave_error_handler)\n      (\"eigs: opts.p must be greater than k and less than or equal to n\");\n\n  if (have_b && cholB && ! permB.isempty ())\n    {\n      // Check the we really have a permutation vector\n      if (permB.numel () != n)\n        (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n\n      Array<bool> checked (dim_vector (n, 1), false);\n      for (F77_INT i = 0; i < n; i++)\n        {\n          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));\n\n          if (checked(bidx) || bidx < 0 || bidx >= n)\n            (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n        }\n    }\n\n  if (! have_sigma)\n    {\n      if (typ != \"LM\" && typ != \"SM\" && typ != \"LA\" && typ != \"SA\"\n          && typ != \"BE\" && typ != \"LR\" && typ != \"SR\" && typ != \"LI\"\n          && typ != \"SI\")\n        (*current_liboctave_error_handler) (\"eigs: unrecognized sigma value\");\n\n      if (typ == \"LI\" || typ == \"SI\" || typ == \"LR\" || typ == \"SR\")\n        (*current_liboctave_error_handler)\n          (\"eigs: invalid sigma value for real symmetric problem\");\n\n      if (typ != \"SM\" && have_b)\n        note3 = true;\n\n      if (typ == \"SM\")\n        {\n          typ = \"LM\";\n          sigma = 0.;\n          mode = 3;\n          if (have_b)\n            bmat = 'G';\n        }\n    }\n  else if (! std::abs (sigma))\n    {\n      typ = \"SM\";\n      if (have_b)\n        bmat = 'G';\n    }\n  else\n    {\n      typ = \"LM\";\n      mode = 3;\n      if (have_b)\n        bmat = 'G';\n    }\n\n  if (mode == 1 && have_b)\n    {\n      // See Note 3 dsaupd\n      note3 = true;\n      if (cholB)\n        {\n          bt = b;\n          b = b.transpose ();\n          if (permB.isempty ())\n            {\n              permB = ColumnVector (n);\n              for (F77_INT i = 0; i < n; i++)\n                permB(i) = i;\n            }\n        }\n      else\n        {\n          if (! make_cholb (b, bt, permB))\n            (*current_liboctave_error_handler)\n              (\"eigs: The matrix B is not positive definite\");\n        }\n    }\n\n  Array<F77_INT> ip (dim_vector (11, 1));\n  F77_INT *iparam = ip.rwdata ();\n\n  ip(0) = 1; //ishift\n  ip(1) = 0;   // ip(1) not referenced\n  ip(2) = maxit; // mxiter, maximum number of iterations\n  ip(3) = 1; // NB blocksize in recurrence\n  ip(4) = 0; // nconv, number of Ritz values that satisfy convergence\n  ip(5) = 0; //ip(5) not referenced\n  ip(6) = mode; // mode\n  ip(7) = 0;\n  ip(8) = 0;\n  ip(9) = 0;\n  ip(10) = 0;\n  // ip(7) to ip(10) return values\n\n  Array<F77_INT> iptr (dim_vector (14, 1));\n  F77_INT *ipntr = iptr.rwdata ();\n\n  F77_INT ido = 0;\n  int iter = 0;\n  F77_INT elems;\n  F77_INT lwork;\n\n  if (octave::math::int_multiply_overflow (n, p, &elems))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n  if (octave::math::int_multiply_overflow (p, p + 8, &lwork))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n\n  OCTAVE_LOCAL_BUFFER (double, v, elems);\n  OCTAVE_LOCAL_BUFFER (double, workl, lwork);\n  OCTAVE_LOCAL_BUFFER (double, workd, 3 * n);\n  double *presid = resid.rwdata ();\n\n  do\n    {\n      F77_INT tmp_info = octave::to_f77_int (info);\n\n      F77_FUNC (dsaupd, DSAUPD)\n      (ido, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n       F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n       k, tol, presid, p, v, n, iparam,\n       ipntr, workd, workl, lwork, tmp_info\n       F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n      info = tmp_info;\n\n      if (disp > 0 && ! octave::math::isnan (workl[iptr (5)-1]))\n        {\n          if (iter++)\n            {\n              os << \"Iteration \" << iter - 1 <<\n                 \": a few Ritz values of the \" << p << \"-by-\" <<\n                 p << \" matrix\\n\";\n              if (ido == 99) // convergence\n                {\n                  for (F77_INT i = 0; i < k; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n              else\n                {\n                  // the wanted Ritz estimates are at the end\n                  for (F77_INT i = p - k; i < p; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n            }\n\n          // This is a kludge, as ARPACK doesn't give its\n          // iteration pointer.  But as workl[iptr(5)-1] is\n          // an output value updated at each iteration, setting\n          // a value in this array to NaN and testing for it\n          // is a way of obtaining the iteration counter.\n          if (ido != 99)\n            workl[iptr(5)-1] = octave::numeric_limits<double>::NaN ();\n        }\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          if (have_b)\n            {\n              if (mode == 1) // regular mode with factorized B\n                {\n                  Matrix mtmp (n, 1);\n                  for (F77_INT i = 0; i < n; i++)\n                    mtmp(i, 0) = workd[i + iptr(0) - 1];\n\n                  mtmp = utsolve (bt, permB, mtmp);\n                  ColumnVector y = fcn (mtmp, err);\n\n                  if (err)\n                    return false;\n\n                  mtmp = ltsolve (b, permB, y);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    workd[i+iptr(1)-1] = mtmp(i, 0);\n                }\n              else // shift-invert mode\n                {\n                  if (ido == -1)\n                    {\n                      OCTAVE_LOCAL_BUFFER (double, dtmp, n);\n\n                      vector_product (b, workd+iptr(0)-1, dtmp);\n\n                      ColumnVector x(n);\n\n                      for (F77_INT i = 0; i < n; i++)\n                        x(i) = dtmp[i];\n\n                      ColumnVector y = fcn (x, err);\n\n                      if (err)\n                        return false;\n\n                      double *ip2 = workd + iptr(1) - 1;\n                      for (F77_INT i = 0; i < n; i++)\n                        ip2[i] = y(i);\n                    }\n                  else if (ido == 2)\n                    vector_product (b, workd+iptr(0)-1, workd+iptr(1)-1);\n                  else\n                    {\n                      double *ip2 = workd+iptr(2)-1;\n                      ColumnVector x(n);\n\n                      for (F77_INT i = 0; i < n; i++)\n                        x(i) = *ip2++;\n\n                      ColumnVector y = fcn (x, err);\n\n                      if (err)\n                        return false;\n\n                      ip2 = workd + iptr(1) - 1;\n                      for (F77_INT i = 0; i < n; i++)\n                        *ip2++ = y(i);\n                    }\n                }\n            }\n          else\n            {\n              double *ip2 = workd + iptr(0) - 1;\n              ColumnVector x(n);\n\n              for (F77_INT i = 0; i < n; i++)\n                x(i) = *ip2++;\n\n              ColumnVector y = fcn (x, err);\n\n              if (err)\n                return false;\n\n              ip2 = workd + iptr(1) - 1;\n              for (F77_INT i = 0; i < n; i++)\n                *ip2++ = y(i);\n            }\n        }\n      else\n        {\n          if (info < 0)\n            (*current_liboctave_error_handler)\n              (\"eigs: error in dsaupd: %s\",\n               arpack_errno2str (info, \"dsaupd\").c_str ());\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT info2;\n\n  // We have a problem in that the size of the C++ bool\n  // type relative to the fortran logical type.  It appears\n  // that fortran uses 4- or 8-bytes per logical and C++ 1-byte\n  // per bool, though this might be system dependent.  As\n  // long as the HOWMNY arg is not \"S\", the logical array\n  // is just workspace for ARPACK, so use int type to\n  // avoid problems.\n  Array<F77_INT> s (dim_vector (p, 1));\n  F77_INT *sel = s.rwdata ();\n\n  eig_vec.resize (n, k);\n  double *z = eig_vec.rwdata ();\n\n  eig_val.resize (k);\n  double *d = eig_val.rwdata ();\n\n  F77_FUNC (dseupd, DSEUPD)\n  (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1), sel, d, z, n, sigma,\n   F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n   F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n   k, tol, presid, p, v, n, iparam, ipntr, workd, workl, lwork, info2\n   F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n  if (info2 == 0)\n    {\n      for (F77_INT i = ip(4); i < k; i++)\n        d[i] = octave::numeric_limits<double>::NaN ();\n      F77_INT k2 = ip(4) / 2;\n      if (mode == 3 || (mode == 1 && typ != \"SM\" && typ != \"BE\"))\n        {\n          for (F77_INT i = 0; i < k2; i++)\n            {\n              double dtmp = d[i];\n              d[i] = d[ip(4) - i - 1];\n              d[ip(4) - i - 1] = dtmp;\n            }\n        }\n\n      if (rvec)\n        {\n          for (F77_INT i = ip(4); i < k; i++)\n            {\n              F77_INT off1 = i * n;\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = octave::numeric_limits<double>::NaN ();\n            }\n          if (mode == 3 || (mode == 1 && typ != \"SM\" && typ != \"BE\"))\n            {\n              OCTAVE_LOCAL_BUFFER (double, dtmp, n);\n\n              for (F77_INT i = 0; i < k2; i++)\n                {\n                  F77_INT off1 = i * n;\n                  F77_INT off2 = (ip(4) - i - 1) * n;\n\n                  if (off1 == off2)\n                    continue;\n\n                  for (F77_INT j = 0; j < n; j++)\n                    dtmp[j] = z[off1 + j];\n\n                  for (F77_INT j = 0; j < n; j++)\n                    z[off1 + j] = z[off2 + j];\n\n                  for (F77_INT j = 0; j < n; j++)\n                    z[off2 + j] = dtmp[j];\n                }\n            }\n          if (note3)\n            eig_vec = utsolve (bt, permB, eig_vec);\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"eigs: error in dseupd: %s\",\n       arpack_errno2str (info2, \"dseupd\").c_str ());\n\n  return ip(4);\n}\n\ntemplate <typename M>\noctave_idx_type\nEigsRealNonSymmetricMatrix (const M& m, const std::string typ,\n                            octave_idx_type k_arg, octave_idx_type p_arg,\n                            octave_idx_type& info, ComplexMatrix& eig_vec,\n                            ComplexColumnVector& eig_val, const M& _b,\n                            ColumnVector& permB, ColumnVector& resid,\n                            std::ostream& os, double tol, bool rvec,\n                            bool cholB, int disp, int maxit)\n{\n  F77_INT k = octave::to_f77_int (k_arg);\n  F77_INT p = octave::to_f77_int (p_arg);\n  M b(_b);\n  F77_INT n = octave::to_f77_int (m.cols ());\n  F77_INT mode = 1;\n  bool have_b = ! b.isempty ();\n  bool note3 = false;\n  char bmat = 'I';\n  double sigmar = 0.;\n  double sigmai = 0.;\n  M bt;\n\n  if (m.rows () != m.cols ())\n    (*current_liboctave_error_handler) (\"eigs: A must be square\");\n  if (have_b && (m.rows () != b.rows () || m.rows () != b.cols ()))\n    (*current_liboctave_error_handler)\n      (\"eigs: B must be square and the same size as A\");\n\n  if (resid.isempty ())\n    {\n      std::string rand_dist = octave::rand::distribution ();\n      octave::rand::distribution (\"uniform\");\n      resid = ColumnVector (octave::rand::vector (n));\n      octave::rand::distribution (rand_dist);\n    }\n  else if (m.cols () != resid.numel ())\n    (*current_liboctave_error_handler) (\"eigs: opts.v0 must be n-by-1\");\n\n  if (n < 3)\n    (*current_liboctave_error_handler) (\"eigs: n must be at least 3\");\n\n  if (p < 0)\n    {\n      p = k * 2 + 1;\n\n      if (p < 20)\n        p = 20;\n\n      if (p > n)\n        p = n;\n    }\n\n  if (k <= 0 || k >= n - 1)\n    (*current_liboctave_error_handler)\n      (\"eigs: Invalid number of eigenvalues to extract\"\n       \" (must be 0 < k < n-1).\\n\"\n       \"      Use 'eig (full (A))' instead\");\n\n  if (p <= k || p > n)\n    (*current_liboctave_error_handler)\n      (\"eigs: opts.p must be greater than k and less than or equal to n\");\n\n  if (have_b && cholB && ! permB.isempty ())\n    {\n      // Check the we really have a permutation vector\n      if (permB.numel () != n)\n        (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n\n      Array<bool> checked (dim_vector (n, 1), false);\n      for (F77_INT i = 0; i < n; i++)\n        {\n          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));\n\n          if (checked(bidx) || bidx < 0 || bidx >= n)\n            (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n        }\n    }\n\n  if (typ != \"LM\" && typ != \"SM\" && typ != \"LA\" && typ != \"SA\"\n      && typ != \"BE\" && typ != \"LR\" && typ != \"SR\" && typ != \"LI\"\n      && typ != \"SI\")\n    (*current_liboctave_error_handler) (\"eigs: unrecognized sigma value\");\n\n  if (typ == \"LA\" || typ == \"SA\" || typ == \"BE\")\n    (*current_liboctave_error_handler)\n      (\"eigs: invalid sigma value for unsymmetric problem\");\n\n  if (have_b)\n    {\n      // See Note 3 dsaupd\n      note3 = true;\n      if (cholB)\n        {\n          bt = b;\n          b = b.transpose ();\n          if (permB.isempty ())\n            {\n              permB = ColumnVector (n);\n              for (F77_INT i = 0; i < n; i++)\n                permB(i) = i;\n            }\n        }\n      else\n        {\n          if (! make_cholb (b, bt, permB))\n            (*current_liboctave_error_handler)\n              (\"eigs: The matrix B is not positive definite\");\n        }\n    }\n\n  Array<F77_INT> ip (dim_vector (11, 1));\n  F77_INT *iparam = ip.rwdata ();\n\n  ip(0) = 1; //ishift\n  ip(1) = 0;   // ip(1) not referenced\n  ip(2) = maxit; // mxiter, maximum number of iterations\n  ip(3) = 1; // NB blocksize in recurrence\n  ip(4) = 0; // nconv, number of Ritz values that satisfy convergence\n  ip(5) = 0; //ip(5) not referenced\n  ip(6) = mode; // mode\n  ip(7) = 0;\n  ip(8) = 0;\n  ip(9) = 0;\n  ip(10) = 0;\n  // ip(7) to ip(10) return values\n\n  Array<F77_INT> iptr (dim_vector (14, 1));\n  F77_INT *ipntr = iptr.rwdata ();\n\n  F77_INT ido = 0;\n  int iter = 0;\n  F77_INT elems;\n  F77_INT lwork;\n\n  if (octave::math::int_multiply_overflow (n, p + 1, &elems))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n  if (octave::math::int_multiply_overflow (3 * p, p + 2, &lwork))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n\n  OCTAVE_LOCAL_BUFFER (double, v, elems);\n  OCTAVE_LOCAL_BUFFER (double, workl, lwork + 1);\n  OCTAVE_LOCAL_BUFFER (double, workd, 3 * n + 1);\n  double *presid = resid.rwdata ();\n\n  do\n    {\n      F77_INT tmp_info = octave::to_f77_int (info);\n\n      // On exit, ip(4) <= k + 1 is the number of converged eigenvalues.\n      // See dnaupd2.\n      F77_FUNC (dnaupd, DNAUPD)\n      (ido, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n       F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n       k, tol, presid, p, v, n, iparam,\n       ipntr, workd, workl, lwork, tmp_info\n       F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n      // k is not changed\n\n      info = tmp_info;\n\n      if (disp > 0 && ! octave::math::isnan(workl[iptr(5)-1]))\n        {\n          if (iter++)\n            {\n              os << \"Iteration \" << iter - 1 <<\n                 \": a few Ritz values of the \" << p << \"-by-\" <<\n                 p << \" matrix\\n\";\n              if (ido == 99) // convergence\n                {\n                  os << \"    \" << workl[iptr(5)+k] << \"\\n\";\n                  for (F77_INT i = 0; i < k; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n              else\n                {\n                  // the wanted Ritz estimates are at the end\n                  for (F77_INT i = p - k - 1; i < p; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n            }\n\n          // This is a kludge, as ARPACK doesn't give its\n          // iteration pointer.  But as workl[iptr(5)-1] is\n          // an output value updated at each iteration, setting\n          // a value in this array to NaN and testing for it\n          // is a way of obtaining the iteration counter.\n          if (ido != 99)\n            workl[iptr(5)-1] = octave::numeric_limits<double>::NaN ();\n        }\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          if (have_b)\n            {\n              Matrix mtmp (n, 1);\n              for (F77_INT i = 0; i < n; i++)\n                mtmp(i, 0) = workd[i + iptr(0) - 1];\n\n              mtmp = ltsolve (b, permB, m * utsolve (bt, permB, mtmp));\n\n              for (F77_INT i = 0; i < n; i++)\n                workd[i+iptr(1)-1] = mtmp(i, 0);\n            }\n          else if (! vector_product (m, workd + iptr(0) - 1,\n                                     workd + iptr(1) - 1))\n            break;\n        }\n      else\n        {\n          if (info < 0)\n            (*current_liboctave_error_handler)\n              (\"eigs: error in dnaupd: %s\",\n               arpack_errno2str (info, \"dnaupd\").c_str ());\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT info2;\n\n  // We have a problem in that the size of the C++ bool\n  // type relative to the fortran logical type.  It appears\n  // that fortran uses 4- or 8-bytes per logical and C++ 1-byte\n  // per bool, though this might be system dependent.  As\n  // long as the HOWMNY arg is not \"S\", the logical array\n  // is just workspace for ARPACK, so use int type to\n  // avoid problems.\n  Array<F77_INT> s (dim_vector (p, 1));\n  F77_INT *sel = s.rwdata ();\n\n  // FIXME: initialize eig_vec2 to zero; apparently dneupd can skip\n  // the assignment to elements of Z that represent imaginary parts.\n  // Found with valgrind and\n  //\n  //   A = [1,0,0,-1;0,1,0,0;0,0,1,0;0,0,2,1];\n  //   [vecs, vals, f] = eigs (A, 1)\n\n  Matrix eig_vec2 (n, k + 1, 0.0);\n  double *z = eig_vec2.rwdata ();\n\n  OCTAVE_LOCAL_BUFFER (double, dr, k + 1);\n  OCTAVE_LOCAL_BUFFER (double, di, k + 1);\n  OCTAVE_LOCAL_BUFFER (double, workev, 3 * p);\n  for (F77_INT i = 0; i < k+1; i++)\n    dr[i] = di[i] = 0.;\n\n  F77_INT k0 = k;  // original number of eigenvalues required\n  F77_FUNC (dneupd, DNEUPD)\n  (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1), sel, dr, di, z, n, sigmar,\n   sigmai, workev, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n   F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2), k, tol, presid, p, v, n, iparam,\n   ipntr, workd, workl, lwork, info2 F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(1)\n   F77_CHAR_ARG_LEN(2));\n  // on exit, if (and only if) rvec == true, k may have been increased by one\n  // and be equal to ip(4), see dngets.\n\n  if (! rvec && ip(4) > k)\n    k = ip(4);\n\n  eig_val.resize (k);\n  Complex *d = eig_val.rwdata ();\n\n  if (info2 == 0)\n    {\n      bool have_cplx_eig = false;\n      for (F77_INT i = 0; i < ip(4); i++)\n        {\n          if (di[i] == 0)\n            d[i] = Complex (dr[i], 0.);\n          else\n            {\n              have_cplx_eig = true;\n              d[i] = Complex (dr[i], di[i]);\n            }\n        }\n      if (have_cplx_eig)\n        {\n          for (F77_INT i = ip(4); i < k; i++)\n            d[i] = Complex (octave::numeric_limits<double>::NaN (),\n                            octave::numeric_limits<double>::NaN ());\n        }\n      else\n        {\n          for (F77_INT i = ip(4); i < k; i++)\n            d[i] = Complex (octave::numeric_limits<double>::NaN (), 0.);\n        }\n      if (! rvec)\n        {\n          // ARPACK seems to give the eigenvalues in reversed order\n          F77_INT k2 = ip(4) / 2;\n          for (F77_INT i = 0; i < k2; i++)\n            {\n              Complex dtmp = d[i];\n              d[i] = d[ip(4) - i - 1];\n              d[ip(4) - i - 1] = dtmp;\n            }\n        }\n      else\n        {\n          // When eigenvectors required, ARPACK seems to give the right order\n          eig_vec.resize (n, k);\n          F77_INT i = 0;\n          while (i < ip(4))\n            {\n              F77_INT off1 = i * n;\n              F77_INT off2 = (i+1) * n;\n              if (std::imag (eig_val(i)) == 0)\n                {\n                  for (F77_INT j = 0; j < n; j++)\n                    eig_vec(j, i) = Complex (z[j+off1], 0.);\n                  i++;\n                }\n              else\n                {\n                  for (F77_INT j = 0; j < n; j++)\n                    {\n                      eig_vec(j, i) = Complex (z[j+off1], z[j+off2]);\n                      if (i < ip(4) - 1)\n                        eig_vec(j, i+1) = Complex (z[j+off1], -z[j+off2]);\n                    }\n                  i+=2;\n                }\n            }\n          if (have_cplx_eig)\n            {\n              for (F77_INT ii = ip(4); ii < k; ii++)\n                for (F77_INT jj = 0; jj < n; jj++)\n                  eig_vec(jj, ii)\n                    = Complex (octave::numeric_limits<double>::NaN (),\n                               octave::numeric_limits<double>::NaN ());\n            }\n          else\n            {\n              for (F77_INT ii = ip(4); ii < k; ii++)\n                for (F77_INT jj = 0; jj < n; jj++)\n                  eig_vec(jj, ii)\n                    = Complex (octave::numeric_limits<double>::NaN (), 0.);\n            }\n          if (note3)\n            eig_vec = utsolve (bt, permB, eig_vec);\n        }\n      if (k0 < k)\n        {\n          eig_val.resize (k0);\n          eig_vec.resize (n, k0);\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"eigs: error in dneupd: %s\",\n       arpack_errno2str (info2, \"dneupd\").c_str ());\n\n  return ip(4);\n}\n\ntemplate <typename M>\noctave_idx_type\nEigsRealNonSymmetricMatrixShift (const M& m, double sigmar,\n                                 octave_idx_type k_arg, octave_idx_type p_arg,\n                                 octave_idx_type& info,\n                                 ComplexMatrix& eig_vec,\n                                 ComplexColumnVector& eig_val, const M& _b,\n                                 ColumnVector& permB, ColumnVector& resid,\n                                 std::ostream& os, double tol, bool rvec,\n                                 bool cholB, int disp, int maxit)\n{\n  F77_INT k = octave::to_f77_int (k_arg);\n  F77_INT p = octave::to_f77_int (p_arg);\n  M b(_b);\n  F77_INT n = octave::to_f77_int (m.cols ());\n  F77_INT mode = 3;\n  bool have_b = ! b.isempty ();\n  std::string typ = \"LM\";\n  double sigmai = 0.;\n\n  if (m.rows () != m.cols ())\n    (*current_liboctave_error_handler) (\"eigs: A must be square\");\n  if (have_b && (m.rows () != b.rows () || m.rows () != b.cols ()))\n    (*current_liboctave_error_handler)\n      (\"eigs: B must be square and the same size as A\");\n\n  // FIXME: The \"SM\" type for mode 1 seems unstable though faster!!\n  //if (! std::abs (sigmar))\n  //  return EigsRealNonSymmetricMatrix (m, \"SM\", k, p, info, eig_vec, eig_val,\n  //                                   _b, permB, resid, os, tol, rvec, cholB,\n  //                                   disp, maxit);\n\n  if (resid.isempty ())\n    {\n      std::string rand_dist = octave::rand::distribution ();\n      octave::rand::distribution (\"uniform\");\n      resid = ColumnVector (octave::rand::vector (n));\n      octave::rand::distribution (rand_dist);\n    }\n  else if (m.cols () != resid.numel ())\n    (*current_liboctave_error_handler) (\"eigs: opts.v0 must be n-by-1\");\n\n  if (n < 3)\n    (*current_liboctave_error_handler) (\"eigs: n must be at least 3\");\n\n  if (p < 0)\n    {\n      p = k * 2 + 1;\n\n      if (p < 20)\n        p = 20;\n\n      if (p > n)\n        p = n;\n    }\n\n  if (k <= 0 || k >= n - 1)\n    (*current_liboctave_error_handler)\n      (\"eigs: Invalid number of eigenvalues to extract\"\n       \" (must be 0 < k < n-1).\\n\"\n       \"      Use 'eig (full (A))' instead\");\n\n  if (p <= k || p > n)\n    (*current_liboctave_error_handler)\n      (\"eigs: opts.p must be greater than k and less than or equal to n\");\n\n  if (have_b && cholB && ! permB.isempty ())\n    {\n      // Check that we really have a permutation vector\n      if (permB.numel () != n)\n        (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n\n      Array<bool> checked (dim_vector (n, 1), false);\n      for (F77_INT i = 0; i < n; i++)\n        {\n          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));\n\n          if (checked(bidx) || bidx < 0 || bidx >= n)\n            (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n        }\n    }\n\n  char bmat = 'I';\n  if (have_b)\n    bmat = 'G';\n\n  Array<F77_INT> ip (dim_vector (11, 1));\n  F77_INT *iparam = ip.rwdata ();\n\n  ip(0) = 1; //ishift\n  ip(1) = 0;   // ip(1) not referenced\n  ip(2) = maxit; // mxiter, maximum number of iterations\n  ip(3) = 1; // NB blocksize in recurrence\n  ip(4) = 0; // nconv, number of Ritz values that satisfy convergence\n  ip(5) = 0; //ip(5) not referenced\n  ip(6) = mode; // mode\n  ip(7) = 0;\n  ip(8) = 0;\n  ip(9) = 0;\n  ip(10) = 0;\n  // ip(7) to ip(10) return values\n\n  Array<F77_INT> iptr (dim_vector (14, 1));\n  F77_INT *ipntr = iptr.rwdata ();\n\n  F77_INT ido = 0;\n  int iter = 0;\n  M L, U;\n  ColumnVector r(n);\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, P, (have_b ? b.rows () : m.rows ()));\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Q, (have_b ? b.cols () : m.cols ()));\n\n  if (! LuAminusSigmaB (m, b, cholB, permB, sigmar, L, U, P, Q, r))\n    return -1;\n\n  F77_INT elems;\n  F77_INT lwork;\n\n  if (octave::math::int_multiply_overflow (n, p + 1, &elems))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n  if (octave::math::int_multiply_overflow (3 * p, p + 2, &lwork))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n\n  OCTAVE_LOCAL_BUFFER (double, v, elems);\n  OCTAVE_LOCAL_BUFFER (double, workl, lwork + 1);\n  OCTAVE_LOCAL_BUFFER (double, workd, 3 * n + 1);\n  double *presid = resid.rwdata ();\n\n  do\n    {\n      F77_INT tmp_info = octave::to_f77_int (info);\n\n      // On exit, ip(4) <= k + 1 is the number of converged eigenvalues.\n      // See dnaupd2.\n      F77_FUNC (dnaupd, DNAUPD)\n      (ido, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n       F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n       k, tol, presid, p, v, n, iparam,\n       ipntr, workd, workl, lwork, tmp_info\n       F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n      // k is not changed\n\n      info = tmp_info;\n\n      if (disp > 0 && ! octave::math::isnan (workl[iptr (5)-1]))\n        {\n          if (iter++)\n            {\n              os << \"Iteration \" << iter - 1 <<\n                 \": a few Ritz values of the \" << p << \"-by-\" <<\n                 p << \" matrix\\n\";\n              if (ido == 99) // convergence\n                {\n                  os << \"    \" << workl[iptr(5)+k] << \"\\n\";\n                  for (F77_INT i = 0; i < k; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n              else\n                {\n                  // the wanted Ritz estimates are at the end\n                  for (F77_INT i = p - k - 1; i < p; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n            }\n\n          // This is a kludge, as ARPACK doesn't give its\n          // iteration pointer.  But as workl[iptr(5)-1] is\n          // an output value updated at each iteration, setting\n          // a value in this array to NaN and testing for it\n          // is a way of obtaining the iteration counter.\n          if (ido != 99)\n            workl[iptr(5)-1] = octave::numeric_limits<double>::NaN ();\n        }\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          if (have_b)\n            {\n              if (ido == -1)\n                {\n                  OCTAVE_LOCAL_BUFFER (double, dtmp, n);\n\n                  vector_product (b, workd+iptr(0)-1, dtmp);\n\n                  Matrix tmp (n, 1);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    tmp(i, 0) = dtmp[P[i]] / r(P[i]);\n\n                  lusolve (L, U, tmp);\n\n                  double *ip2 = workd+iptr(1)-1;\n                  for (F77_INT i = 0; i < n; i++)\n                    ip2[Q[i]] = tmp(i, 0);\n                }\n              else if (ido == 2)\n                vector_product (b, workd+iptr(0)-1, workd+iptr(1)-1);\n              else\n                {\n                  double *ip2 = workd+iptr(2)-1;\n                  Matrix tmp (n, 1);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    tmp(i, 0) = ip2[P[i]] / r(P[i]);\n\n                  lusolve (L, U, tmp);\n\n                  ip2 = workd+iptr(1)-1;\n                  for (F77_INT i = 0; i < n; i++)\n                    ip2[Q[i]] = tmp(i, 0);\n                }\n            }\n          else\n            {\n              // ido cannot be 2 for non-generalized problems (see dnaupd2).\n              double *ip2 = workd+iptr(0)-1;\n              Matrix tmp (n, 1);\n\n              for (F77_INT i = 0; i < n; i++)\n                tmp(i, 0) = ip2[P[i]] / r(P[i]);\n\n              lusolve (L, U, tmp);\n\n              ip2 = workd+iptr(1)-1;\n              for (F77_INT i = 0; i < n; i++)\n                ip2[Q[i]] = tmp(i, 0);\n            }\n        }\n      else\n        {\n          if (info < 0)\n            (*current_liboctave_error_handler)\n              (\"eigs: error in dnaupd: %s\",\n               arpack_errno2str (info, \"dnaupd\").c_str ());\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT info2;\n\n  // We have a problem in that the size of the C++ bool\n  // type relative to the fortran logical type.  It appears\n  // that fortran uses 4- or 8-bytes per logical and C++ 1-byte\n  // per bool, though this might be system dependent.  As\n  // long as the HOWMNY arg is not \"S\", the logical array\n  // is just workspace for ARPACK, so use int type to\n  // avoid problems.\n  Array<F77_INT> s (dim_vector (p, 1));\n  F77_INT *sel = s.rwdata ();\n\n  // FIXME: initialize eig_vec2 to zero; apparently dneupd can skip\n  // the assignment to elements of Z that represent imaginary parts.\n  // Found with valgrind and\n  //\n  //   A = [1,0,0,-1;0,1,0,0;0,0,1,0;0,0,2,1];\n  //   [vecs, vals, f] = eigs (A, 1)\n\n  Matrix eig_vec2 (n, k + 1, 0.0);\n  double *z = eig_vec2.rwdata ();\n\n  OCTAVE_LOCAL_BUFFER (double, dr, k + 1);\n  OCTAVE_LOCAL_BUFFER (double, di, k + 1);\n  OCTAVE_LOCAL_BUFFER (double, workev, 3 * p);\n  for (F77_INT i = 0; i < k+1; i++)\n    dr[i] = di[i] = 0.;\n\n  F77_INT k0 = k;  // original number of eigenvalues required\n  F77_FUNC (dneupd, DNEUPD)\n  (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1), sel, dr, di, z, n, sigmar,\n   sigmai, workev, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n   F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2), k, tol, presid, p, v, n, iparam,\n   ipntr, workd, workl, lwork, info2 F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(1)\n   F77_CHAR_ARG_LEN(2));\n  // On exit, if (and only if) rvec == true, k may have been increased by one\n  // and be equal to ip(4), see dngets.\n\n  if (! rvec && ip(4) > k)\n    k = ip(4);\n\n  eig_val.resize (k);\n  Complex *d = eig_val.rwdata ();\n\n  if (info2 == 0)\n    {\n      bool have_cplx_eig = false;\n      for (F77_INT i = 0; i < ip(4); i++)\n        {\n          if (di[i] == 0.)\n            d[i] = Complex (dr[i], 0.);\n          else\n            {\n              have_cplx_eig = true;\n              d[i] = Complex (dr[i], di[i]);\n            }\n        }\n      if (have_cplx_eig)\n        {\n          for (F77_INT i = ip(4); i < k; i++)\n            d[i] = Complex (octave::numeric_limits<double>::NaN (),\n                            octave::numeric_limits<double>::NaN ());\n        }\n      else\n        {\n          for (F77_INT i = ip(4); i < k; i++)\n            d[i] = Complex (octave::numeric_limits<double>::NaN (), 0.);\n        }\n\n      if (! rvec)\n        {\n          // ARPACK seems to give the eigenvalues in reversed order\n          F77_INT k2 = ip(4) / 2;\n          for (F77_INT i = 0; i < k2; i++)\n            {\n              Complex dtmp = d[i];\n              d[i] = d[ip(4) - i - 1];\n              d[ip(4) - i - 1] = dtmp;\n            }\n        }\n      else\n        {\n          // When eigenvectors required, ARPACK seems to give the right order\n          eig_vec.resize (n, k);\n          F77_INT i = 0;\n          while (i < ip(4))\n            {\n              F77_INT off1 = i * n;\n              F77_INT off2 = (i+1) * n;\n              if (std::imag (eig_val(i)) == 0)\n                {\n                  for (F77_INT j = 0; j < n; j++)\n                    eig_vec(j, i) = Complex (z[j+off1], 0.);\n                  i++;\n                }\n              else\n                {\n                  for (F77_INT j = 0; j < n; j++)\n                    {\n                      eig_vec(j, i) = Complex (z[j+off1], z[j+off2]);\n                      if (i < ip(4) - 1)\n                        eig_vec(j, i+1) = Complex (z[j+off1], -z[j+off2]);\n                    }\n                  i+=2;\n                }\n            }\n          if (have_cplx_eig)\n            {\n              for (F77_INT ii = ip(4); ii < k; ii++)\n                for (F77_INT jj = 0; jj < n; jj++)\n                  eig_vec(jj, ii)\n                    = Complex (octave::numeric_limits<double>::NaN (),\n                               octave::numeric_limits<double>::NaN ());\n            }\n          else\n            {\n              for (F77_INT ii = ip(4); ii < k; ii++)\n                for (F77_INT jj = 0; jj < n; jj++)\n                  eig_vec(jj, ii)\n                    = Complex (octave::numeric_limits<double>::NaN (), 0.);\n            }\n        }\n      if (k0 < k)\n        {\n          eig_val.resize (k0);\n          eig_vec.resize (n, k0);\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"eigs: error in dneupd: %s\",\n       arpack_errno2str (info2, \"dneupd\").c_str ());\n\n  return ip(4);\n}\n\ntemplate <typename M>\noctave_idx_type\nEigsRealNonSymmetricFunc (EigsFunc fcn, octave_idx_type n_arg,\n                          const std::string& _typ, double sigmar,\n                          octave_idx_type k_arg, octave_idx_type p_arg,\n                          octave_idx_type& info, ComplexMatrix& eig_vec,\n                          ComplexColumnVector& eig_val, const M& _b,\n                          ColumnVector& permB, ColumnVector& resid,\n                          std::ostream& os, double tol, bool rvec,\n                          bool cholB, int disp, int maxit)\n{\n  F77_INT n = octave::to_f77_int (n_arg);\n  F77_INT k = octave::to_f77_int (k_arg);\n  F77_INT p = octave::to_f77_int (p_arg);\n  M b(_b);\n  std::string typ (_typ);\n  bool have_sigma = (sigmar ? true : false);\n  double sigmai = 0.;\n  F77_INT mode = 1;\n  bool have_b = ! b.isempty ();\n  bool note3 = false;\n  char bmat = 'I';\n  int err = 0;\n  M bt;\n\n  if (resid.isempty ())\n    {\n      std::string rand_dist = octave::rand::distribution ();\n      octave::rand::distribution (\"uniform\");\n      resid = ColumnVector (octave::rand::vector (n));\n      octave::rand::distribution (rand_dist);\n    }\n  else if (n != resid.numel ())\n    (*current_liboctave_error_handler) (\"eigs: opts.v0 must be n-by-1\");\n\n  if (n < 3)\n    (*current_liboctave_error_handler) (\"eigs: n must be at least 3\");\n\n  if (p < 0)\n    {\n      p = k * 2 + 1;\n\n      if (p < 20)\n        p = 20;\n\n      if (p > n)\n        p = n;\n    }\n\n  if (k <= 0 || k >= n - 1)\n    (*current_liboctave_error_handler)\n      (\"eigs: Invalid number of eigenvalues to extract\"\n       \" (must be 0 < k < n-1).\\n\"\n       \"      Use 'eig (full (A))' instead\");\n\n  if (p <= k || p > n)\n    (*current_liboctave_error_handler)\n      (\"eigs: opts.p must be greater than k and less than or equal to n\");\n\n  if (have_b && cholB && ! permB.isempty ())\n    {\n      // Check the we really have a permutation vector\n      if (permB.numel () != n)\n        (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n\n      Array<bool> checked (dim_vector (n, 1), false);\n      for (F77_INT i = 0; i < n; i++)\n        {\n          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));\n\n          if (checked(bidx) || bidx < 0 || bidx >= n)\n            (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n        }\n    }\n\n  if (! have_sigma)\n    {\n      if (typ != \"LM\" && typ != \"SM\" && typ != \"LA\" && typ != \"SA\"\n          && typ != \"BE\" && typ != \"LR\" && typ != \"SR\" && typ != \"LI\"\n          && typ != \"SI\")\n        (*current_liboctave_error_handler) (\"eigs: unrecognized sigma value\");\n\n      if (typ == \"LA\" || typ == \"SA\" || typ == \"BE\")\n        (*current_liboctave_error_handler)\n          (\"eigs: invalid sigma value for unsymmetric problem\");\n\n      if (typ != \"SM\" && have_b)\n        note3 = true;\n\n      if (typ == \"SM\")\n        {\n          typ = \"LM\";\n          sigmar = 0.;\n          mode = 3;\n          if (have_b)\n            bmat = 'G';\n        }\n    }\n  else if (! std::abs (sigmar))\n    {\n      typ = \"SM\";\n      if (have_b)\n        bmat = 'G';\n    }\n  else\n    {\n      typ = \"LM\";\n      mode = 3;\n      if (have_b)\n        bmat = 'G';\n    }\n\n  if (mode == 1 && have_b)\n    {\n      // See Note 3 dsaupd\n      note3 = true;\n      if (cholB)\n        {\n          bt = b;\n          b = b.transpose ();\n          if (permB.isempty ())\n            {\n              permB = ColumnVector (n);\n              for (F77_INT i = 0; i < n; i++)\n                permB(i) = i;\n            }\n        }\n      else\n        {\n          if (! make_cholb (b, bt, permB))\n            (*current_liboctave_error_handler)\n              (\"eigs: The matrix B is not positive definite\");\n        }\n    }\n\n  Array<F77_INT> ip (dim_vector (11, 1));\n  F77_INT *iparam = ip.rwdata ();\n\n  ip(0) = 1; //ishift\n  ip(1) = 0;   // ip(1) not referenced\n  ip(2) = maxit; // mxiter, maximum number of iterations\n  ip(3) = 1; // NB blocksize in recurrence\n  ip(4) = 0; // nconv, number of Ritz values that satisfy convergence\n  ip(5) = 0; //ip(5) not referenced\n  ip(6) = mode; // mode\n  ip(7) = 0;\n  ip(8) = 0;\n  ip(9) = 0;\n  ip(10) = 0;\n  // ip(7) to ip(10) return values\n\n  Array<F77_INT> iptr (dim_vector (14, 1));\n  F77_INT *ipntr = iptr.rwdata ();\n\n  F77_INT ido = 0;\n  int iter = 0;\n  F77_INT elems;\n  F77_INT lwork;\n\n  if (octave::math::int_multiply_overflow (n, p + 1, &elems))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n  if (octave::math::int_multiply_overflow (3 * p, p + 2, &lwork))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n\n  OCTAVE_LOCAL_BUFFER (double, v, elems);\n  OCTAVE_LOCAL_BUFFER (double, workl, lwork + 1);\n  OCTAVE_LOCAL_BUFFER (double, workd, 3 * n + 1);\n\n  double *presid = resid.rwdata ();\n\n  do\n    {\n      F77_INT tmp_info = octave::to_f77_int (info);\n\n      // On exit, ip(4) <= k + 1 is the number of converged eigenvalues\n      // see dnaupd2.\n      F77_FUNC (dnaupd, DNAUPD)\n      (ido, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n       F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n       k, tol, presid, p, v, n, iparam,\n       ipntr, workd, workl, lwork, tmp_info\n       F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n      // k is not changed\n\n      info = tmp_info;\n\n      if (disp > 0 && ! octave::math::isnan(workl[iptr(5)-1]))\n        {\n          if (iter++)\n            {\n              os << \"Iteration \" << iter - 1 <<\n                 \": a few Ritz values of the \" << p << \"-by-\" <<\n                 p << \" matrix\\n\";\n              if (ido == 99) // convergence\n                {\n                  os << \"    \" << workl[iptr(5)+k] << \"\\n\";\n                  for (F77_INT i = 0; i < k; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n              else\n                {\n                  // the wanted Ritz estimates are at the end\n                  for (F77_INT i = p - k - 1; i < p; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n            }\n\n          // This is a kludge, as ARPACK doesn't give its\n          // iteration pointer.  But as workl[iptr(5)-1] is\n          // an output value updated at each iteration, setting\n          // a value in this array to NaN and testing for it\n          // is a way of obtaining the iteration counter.\n          if (ido != 99)\n            workl[iptr(5)-1] = octave::numeric_limits<double>::NaN ();\n        }\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          if (have_b)\n            {\n              if (mode == 1) // regular mode with factorized B\n                {\n                  Matrix mtmp (n, 1);\n                  for (F77_INT i = 0; i < n; i++)\n                    mtmp(i, 0) = workd[i + iptr(0) - 1];\n\n                  mtmp = utsolve (bt, permB, mtmp);\n                  ColumnVector y = fcn (mtmp, err);\n\n                  if (err)\n                    return false;\n\n                  mtmp = ltsolve (b, permB, y);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    workd[i+iptr(1)-1] = mtmp(i, 0);\n                }\n              else // shift-invert mode\n                {\n                  if (ido == -1)\n                    {\n                      OCTAVE_LOCAL_BUFFER (double, dtmp, n);\n\n                      vector_product (b, workd+iptr(0)-1, dtmp);\n\n                      ColumnVector x(n);\n\n                      for (F77_INT i = 0; i < n; i++)\n                        x(i) = dtmp[i];\n\n                      ColumnVector y = fcn (x, err);\n\n                      if (err)\n                        return false;\n\n                      double *ip2 = workd + iptr(1) - 1;\n                      for (F77_INT i = 0; i < n; i++)\n                        ip2[i] = y(i);\n                    }\n                  else if (ido == 2)\n                    vector_product (b, workd+iptr(0)-1, workd+iptr(1)-1);\n                  else\n                    {\n                      double *ip2 = workd+iptr(2)-1;\n                      ColumnVector x(n);\n\n                      for (F77_INT i = 0; i < n; i++)\n                        x(i) = *ip2++;\n\n                      ColumnVector y = fcn (x, err);\n\n                      if (err)\n                        return false;\n\n                      ip2 = workd + iptr(1) - 1;\n                      for (F77_INT i = 0; i < n; i++)\n                        *ip2++ = y(i);\n                    }\n                }\n            }\n          else\n            {\n              double *ip2 = workd + iptr(0) - 1;\n              ColumnVector x(n);\n\n              for (F77_INT i = 0; i < n; i++)\n                x(i) = *ip2++;\n\n              ColumnVector y = fcn (x, err);\n\n              if (err)\n                return false;\n\n              ip2 = workd + iptr(1) - 1;\n              for (F77_INT i = 0; i < n; i++)\n                *ip2++ = y(i);\n            }\n        }\n      else\n        {\n          if (info < 0)\n            (*current_liboctave_error_handler)\n              (\"eigs: error in dnaupd: %s\",\n               arpack_errno2str (info, \"dnaupd\").c_str ());\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT info2;\n\n  // We have a problem in that the size of the C++ bool\n  // type relative to the fortran logical type.  It appears\n  // that fortran uses 4- or 8-bytes per logical and C++ 1-byte\n  // per bool, though this might be system dependent.  As\n  // long as the HOWMNY arg is not \"S\", the logical array\n  // is just workspace for ARPACK, so use int type to\n  // avoid problems.\n  Array<F77_INT> s (dim_vector (p, 1));\n  F77_INT *sel = s.rwdata ();\n\n  // FIXME: initialize eig_vec2 to zero; apparently dneupd can skip\n  // the assignment to elements of Z that represent imaginary parts.\n  // Found with valgrind and\n  //\n  //   A = [1,0,0,-1;0,1,0,0;0,0,1,0;0,0,2,1];\n  //   [vecs, vals, f] = eigs (A, 1)\n\n  Matrix eig_vec2 (n, k + 1, 0.0);\n  double *z = eig_vec2.rwdata ();\n\n  OCTAVE_LOCAL_BUFFER (double, dr, k + 1);\n  OCTAVE_LOCAL_BUFFER (double, di, k + 1);\n  OCTAVE_LOCAL_BUFFER (double, workev, 3 * p);\n  for (F77_INT i = 0; i < k+1; i++)\n    dr[i] = di[i] = 0.;\n\n  F77_INT k0 = k;  // original number of eigenvalues required\n  F77_FUNC (dneupd, DNEUPD)\n  (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1), sel, dr, di, z, n, sigmar,\n   sigmai, workev, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n   F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2), k, tol, presid, p, v, n, iparam,\n   ipntr, workd, workl, lwork, info2 F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(1)\n   F77_CHAR_ARG_LEN(2));\n  // On exit, if (and only if) rvec == true, k may have been increased by one\n  // and be equal to ip(4), see dngets.\n\n  if (! rvec && ip(4) > k)\n    k = ip(4);\n\n  eig_val.resize (k);\n  Complex *d = eig_val.rwdata ();\n\n  if (info2 == 0)\n    {\n      bool have_cplx_eig = false;\n      for (F77_INT i = 0; i < ip(4); i++)\n        {\n          if (di[i] == 0.)\n            d[i] = Complex (dr[i], 0.);\n          else\n            {\n              have_cplx_eig = true;\n              d[i] = Complex (dr[i], di[i]);\n            }\n        }\n      if (have_cplx_eig)\n        {\n          for (F77_INT i = ip(4); i < k; i++)\n            d[i] = Complex (octave::numeric_limits<double>::NaN (),\n                            octave::numeric_limits<double>::NaN ());\n        }\n      else\n        {\n          for (F77_INT i = ip(4); i < k; i++)\n            d[i] = Complex (octave::numeric_limits<double>::NaN (), 0.);\n        }\n\n      if (! rvec)\n        {\n          // ARPACK seems to give the eigenvalues in reversed order\n          octave_idx_type k2 = ip(4) / 2;\n          for (F77_INT i = 0; i < k2; i++)\n            {\n              Complex dtmp = d[i];\n              d[i] = d[ip(4) - i - 1];\n              d[ip(4) - i - 1] = dtmp;\n            }\n        }\n      else\n        {\n          // ARPACK seems to give the eigenvalues in reversed order\n          eig_vec.resize (n, k);\n          F77_INT i = 0;\n          while (i < ip(4))\n            {\n              F77_INT off1 = i * n;\n              F77_INT off2 = (i+1) * n;\n              if (std::imag (eig_val(i)) == 0)\n                {\n                  for (F77_INT j = 0; j < n; j++)\n                    eig_vec(j, i) = Complex (z[j+off1], 0.);\n                  i++;\n                }\n              else\n                {\n                  for (F77_INT j = 0; j < n; j++)\n                    {\n                      eig_vec(j, i) = Complex (z[j+off1], z[j+off2]);\n                      if (i < ip(4) - 1)\n                        eig_vec(j, i+1) = Complex (z[j+off1], -z[j+off2]);\n                    }\n                  i+=2;\n                }\n            }\n          if (have_cplx_eig)\n            {\n              for (F77_INT ii = ip(4); ii < k; ii++)\n                for (F77_INT jj = 0; jj < n; jj++)\n                  eig_vec(jj, ii)\n                    = Complex (octave::numeric_limits<double>::NaN (),\n                               octave::numeric_limits<double>::NaN ());\n            }\n          else\n            {\n              for (F77_INT ii = ip(4); ii < k; ii++)\n                for (F77_INT jj = 0; jj < n; jj++)\n                  eig_vec(jj, ii)\n                    = Complex (octave::numeric_limits<double>::NaN (), 0.);\n            }\n          if (note3)\n            eig_vec = utsolve (bt, permB, eig_vec);\n        }\n      if (k0 < k)\n        {\n          eig_val.resize (k0);\n          eig_vec.resize (n, k0);\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"eigs: error in dneupd: %s\",\n       arpack_errno2str (info2, \"dneupd\").c_str ());\n\n  return ip(4);\n}\n\ntemplate <typename M>\noctave_idx_type\nEigsComplexNonSymmetricMatrix (const M& m, const std::string typ,\n                               octave_idx_type k_arg, octave_idx_type p_arg,\n                               octave_idx_type& info, ComplexMatrix& eig_vec,\n                               ComplexColumnVector& eig_val, const M& _b,\n                               ColumnVector& permB,\n                               ComplexColumnVector& cresid,\n                               std::ostream& os, double tol, bool rvec,\n                               bool cholB, int disp, int maxit)\n{\n  F77_INT k = octave::to_f77_int (k_arg);\n  F77_INT p = octave::to_f77_int (p_arg);\n  M b(_b);\n  F77_INT n = octave::to_f77_int (m.cols ());\n  F77_INT mode = 1;\n  bool have_b = ! b.isempty ();\n  bool note3 = false;\n  char bmat = 'I';\n  Complex sigma = 0.;\n  M bt;\n\n  if (m.rows () != m.cols ())\n    (*current_liboctave_error_handler) (\"eigs: A must be square\");\n  if (have_b && (m.rows () != b.rows () || m.rows () != b.cols ()))\n    (*current_liboctave_error_handler)\n      (\"eigs: B must be square and the same size as A\");\n\n  if (cresid.isempty ())\n    {\n      std::string rand_dist = octave::rand::distribution ();\n      octave::rand::distribution (\"uniform\");\n      Array<double> rr (octave::rand::vector (n));\n      Array<double> ri (octave::rand::vector (n));\n      cresid = ComplexColumnVector (n);\n      for (F77_INT i = 0; i < n; i++)\n        cresid(i) = Complex (rr(i), ri(i));\n      octave::rand::distribution (rand_dist);\n    }\n  else if (m.cols () != cresid.numel ())\n    (*current_liboctave_error_handler) (\"eigs: opts.v0 must be n-by-1\");\n\n  if (n < 3)\n    (*current_liboctave_error_handler) (\"eigs: n must be at least 3\");\n\n  if (p < 0)\n    {\n      p = k * 2 + 1;\n\n      if (p < 20)\n        p = 20;\n\n      if (p > n)\n        p = n;\n    }\n\n  if (k <= 0 || k >= n - 1)\n    (*current_liboctave_error_handler)\n      (\"eigs: Invalid number of eigenvalues to extract\"\n       \" (must be 0 < k < n-1).\\n\"\n       \"      Use 'eig (full (A))' instead\");\n\n  if (p <= k || p > n)\n    (*current_liboctave_error_handler)\n      (\"eigs: opts.p must be greater than k and less than or equal to n\");\n\n  if (have_b && cholB && ! permB.isempty ())\n    {\n      // Check the we really have a permutation vector\n      if (permB.numel () != n)\n        (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n\n      Array<bool> checked (dim_vector (n, 1), false);\n      for (F77_INT i = 0; i < n; i++)\n        {\n          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));\n\n          if (checked(bidx) || bidx < 0 || bidx >= n)\n            (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n        }\n    }\n\n  if (typ != \"LM\" && typ != \"SM\" && typ != \"LA\" && typ != \"SA\"\n      && typ != \"BE\" && typ != \"LR\" && typ != \"SR\" && typ != \"LI\"\n      && typ != \"SI\")\n    (*current_liboctave_error_handler) (\"eigs: unrecognized sigma value\");\n\n  if (typ == \"LA\" || typ == \"SA\" || typ == \"BE\")\n    (*current_liboctave_error_handler)\n      (\"eigs: invalid sigma value for complex problem\");\n\n  if (have_b)\n    {\n      // See Note 3 dsaupd\n      note3 = true;\n      if (cholB)\n        {\n          bt = b;\n          b = b.hermitian ();\n          if (permB.isempty ())\n            {\n              permB = ColumnVector (n);\n              for (F77_INT i = 0; i < n; i++)\n                permB(i) = i;\n            }\n        }\n      else\n        {\n          if (! make_cholb (b, bt, permB))\n            (*current_liboctave_error_handler)\n              (\"eigs: The matrix B is not positive definite\");\n        }\n    }\n\n  Array<F77_INT> ip (dim_vector (11, 1));\n  F77_INT *iparam = ip.rwdata ();\n\n  ip(0) = 1; //ishift\n  ip(1) = 0;   // ip(1) not referenced\n  ip(2) = maxit; // mxiter, maximum number of iterations\n  ip(3) = 1; // NB blocksize in recurrence\n  ip(4) = 0; // nconv, number of Ritz values that satisfy convergence\n  ip(5) = 0; //ip(5) not referenced\n  ip(6) = mode; // mode\n  ip(7) = 0;\n  ip(8) = 0;\n  ip(9) = 0;\n  ip(10) = 0;\n  // ip(7) to ip(10) return values\n\n  Array<F77_INT> iptr (dim_vector (14, 1));\n  F77_INT *ipntr = iptr.rwdata ();\n\n  F77_INT ido = 0;\n  int iter = 0;\n  F77_INT elems;\n  F77_INT lwork;\n\n  if (octave::math::int_multiply_overflow (n, p, &elems))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n  if (octave::math::int_multiply_overflow (p, 3 * p + 5, &lwork))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n\n  OCTAVE_LOCAL_BUFFER (Complex, v, elems);\n  OCTAVE_LOCAL_BUFFER (Complex, workl, lwork);\n  OCTAVE_LOCAL_BUFFER (Complex, workd, 3 * n);\n  OCTAVE_LOCAL_BUFFER (double, rwork, p);\n  Complex *presid = cresid.rwdata ();\n\n  do\n    {\n      F77_INT tmp_info = octave::to_f77_int (info);\n\n      F77_FUNC (znaupd, ZNAUPD)\n      (ido, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n       F77_CONST_CHAR_ARG2 (typ.c_str (), 2),\n       k, tol, F77_DBLE_CMPLX_ARG (presid), p, F77_DBLE_CMPLX_ARG (v), n,\n       iparam, ipntr,\n       F77_DBLE_CMPLX_ARG (workd), F77_DBLE_CMPLX_ARG (workl), lwork, rwork,\n       tmp_info F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n      info = tmp_info;\n\n      if (disp > 0 && ! octave::math::isnan (workl[iptr (5)-1]))\n        {\n          if (iter++)\n            {\n              os << \"Iteration \" << iter - 1 <<\n                 \": a few Ritz values of the \" << p << \"-by-\" <<\n                 p << \" matrix\\n\";\n              if (ido == 99) // convergence\n                {\n                  for (F77_INT i = 0; i < k; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n              else\n                {\n                  // the wanted Ritz estimates are at the end\n                  for (F77_INT i = p - k; i < p; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n            }\n\n          // This is a kludge, as ARPACK doesn't give its\n          // iteration pointer.  But as workl[iptr(5)-1] is\n          // an output value updated at each iteration, setting\n          // a value in this array to NaN and testing for it\n          // is a way of obtaining the iteration counter.\n          if (ido != 99)\n            workl[iptr(5)-1] = octave::numeric_limits<double>::NaN ();\n        }\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          if (have_b)\n            {\n              ComplexMatrix mtmp (n, 1);\n              for (F77_INT i = 0; i < n; i++)\n                mtmp(i, 0) = workd[i + iptr(0) - 1];\n              mtmp = ltsolve (b, permB, m * utsolve (bt, permB, mtmp));\n              for (F77_INT i = 0; i < n; i++)\n                workd[i+iptr(1)-1] = mtmp(i, 0);\n\n            }\n          else if (! vector_product (m, workd + iptr(0) - 1,\n                                     workd + iptr(1) - 1))\n            break;\n        }\n      else\n        {\n          if (info < 0)\n            (*current_liboctave_error_handler)\n              (\"eigs: error %\" OCTAVE_IDX_TYPE_FORMAT \" in znaupd: %s\",\n               info, arpack_errno2str (info, \"znaupd\").c_str ());\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT info2;\n\n  // We have a problem in that the size of the C++ bool\n  // type relative to the fortran logical type.  It appears\n  // that fortran uses 4- or 8-bytes per logical and C++ 1-byte\n  // per bool, though this might be system dependent.  As\n  // long as the HOWMNY arg is not \"S\", the logical array\n  // is just workspace for ARPACK, so use int type to\n  // avoid problems.\n  Array<F77_INT> s (dim_vector (p, 1));\n  F77_INT *sel = s.rwdata ();\n\n  eig_vec.resize (n, k);\n  Complex *z = eig_vec.rwdata ();\n\n  eig_val.resize (k+1);\n  Complex *d = eig_val.rwdata ();\n\n  OCTAVE_LOCAL_BUFFER (Complex, workev, 2 * p);\n\n  F77_FUNC (zneupd, ZNEUPD)\n  (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1), sel, F77_DBLE_CMPLX_ARG (d),\n   F77_DBLE_CMPLX_ARG (z), n, F77_CONST_DBLE_CMPLX_ARG (&sigma),\n   F77_DBLE_CMPLX_ARG (workev),\n   F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n   F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n   k, tol, F77_DBLE_CMPLX_ARG (presid), p, F77_DBLE_CMPLX_ARG (v), n,\n   iparam, ipntr,\n   F77_DBLE_CMPLX_ARG (workd), F77_DBLE_CMPLX_ARG (workl), lwork, rwork,\n   info2 F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n  if (info2 == 0)\n    {\n      for (F77_INT i = ip(4); i < k; i++)\n        d[i] = Complex (octave::numeric_limits<double>::NaN (),\n                        octave::numeric_limits<double>::NaN ());\n\n      F77_INT k2 = ip(4) / 2;\n      for (F77_INT i = 0; i < k2; i++)\n        {\n          Complex ctmp = d[i];\n          d[i] = d[ip(4) - i - 1];\n          d[ip(4) - i - 1] = ctmp;\n        }\n      eig_val.resize (k);\n\n      if (rvec)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, ctmp, n);\n\n          for (F77_INT i = ip(4); i < k; i++)\n            {\n              F77_INT off1 = i * n;\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = Complex (octave::numeric_limits<double>::NaN (),\n                                       octave::numeric_limits<double>::NaN ());\n            }\n\n          for (F77_INT i = 0; i < k2; i++)\n            {\n              F77_INT off1 = i * n;\n              F77_INT off2 = (ip(4) - i - 1) * n;\n\n              if (off1 == off2)\n                continue;\n\n              for (F77_INT j = 0; j < n; j++)\n                ctmp[j] = z[off1 + j];\n\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = z[off2 + j];\n\n              for (F77_INT j = 0; j < n; j++)\n                z[off2 + j] = ctmp[j];\n            }\n\n          if (note3)\n            eig_vec = utsolve (bt, permB, eig_vec);\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"eigs: error in zneupd: %s\",\n       arpack_errno2str (info2, \"zneupd\").c_str ());\n\n  return ip(4);\n}\n\ntemplate <typename M>\noctave_idx_type\nEigsComplexNonSymmetricMatrixShift (const M& m, Complex sigma,\n                                    octave_idx_type k_arg, octave_idx_type p_arg,\n                                    octave_idx_type& info,\n                                    ComplexMatrix& eig_vec,\n                                    ComplexColumnVector& eig_val, const M& _b,\n                                    ColumnVector& permB,\n                                    ComplexColumnVector& cresid,\n                                    std::ostream& os, double tol, bool rvec,\n                                    bool cholB, int disp, int maxit)\n{\n  F77_INT k = octave::to_f77_int (k_arg);\n  F77_INT p = octave::to_f77_int (p_arg);\n  M b(_b);\n  F77_INT n = octave::to_f77_int (m.cols ());\n  F77_INT mode = 3;\n  bool have_b = ! b.isempty ();\n  std::string typ = \"LM\";\n\n  if (m.rows () != m.cols ())\n    (*current_liboctave_error_handler) (\"eigs: A must be square\");\n  if (have_b && (m.rows () != b.rows () || m.rows () != b.cols ()))\n    (*current_liboctave_error_handler)\n      (\"eigs: B must be square and the same size as A\");\n\n  // FIXME: The \"SM\" type for mode 1 seems unstable though faster!!\n  //if (! std::abs (sigma))\n  //  return EigsComplexNonSymmetricMatrix (m, \"SM\", k, p, info, eig_vec,\n  //                                      eig_val, _b, permB, cresid, os, tol,\n  //                                      rvec, cholB, disp, maxit);\n\n  if (cresid.isempty ())\n    {\n      std::string rand_dist = octave::rand::distribution ();\n      octave::rand::distribution (\"uniform\");\n      Array<double> rr (octave::rand::vector (n));\n      Array<double> ri (octave::rand::vector (n));\n      cresid = ComplexColumnVector (n);\n      for (F77_INT i = 0; i < n; i++)\n        cresid(i) = Complex (rr(i), ri(i));\n      octave::rand::distribution (rand_dist);\n    }\n  else if (m.cols () != cresid.numel ())\n    (*current_liboctave_error_handler) (\"eigs: opts.v0 must be n-by-1\");\n\n  if (n < 3)\n    (*current_liboctave_error_handler) (\"eigs: n must be at least 3\");\n\n  if (p < 0)\n    {\n      p = k * 2 + 1;\n\n      if (p < 20)\n        p = 20;\n\n      if (p > n)\n        p = n;\n    }\n\n  if (k <= 0 || k >= n - 1)\n    (*current_liboctave_error_handler)\n      (\"eigs: Invalid number of eigenvalues to extract\"\n       \" (must be 0 < k < n-1).\\n\"\n       \"      Use 'eig (full (A))' instead\");\n\n  if (p <= k || p > n)\n    (*current_liboctave_error_handler)\n      (\"eigs: opts.p must be greater than k and less than or equal to n\");\n\n  if (have_b && cholB && ! permB.isempty ())\n    {\n      // Check that we really have a permutation vector\n      if (permB.numel () != n)\n        (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n\n      Array<bool> checked (dim_vector (n, 1), false);\n      for (F77_INT i = 0; i < n; i++)\n        {\n          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));\n\n          if (checked(bidx) || bidx < 0 || bidx >= n)\n            (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n        }\n    }\n\n  char bmat = 'I';\n  if (have_b)\n    bmat = 'G';\n\n  Array<F77_INT> ip (dim_vector (11, 1));\n  F77_INT *iparam = ip.rwdata ();\n\n  ip(0) = 1; //ishift\n  ip(1) = 0;   // ip(1) not referenced\n  ip(2) = maxit; // mxiter, maximum number of iterations\n  ip(3) = 1; // NB blocksize in recurrence\n  ip(4) = 0; // nconv, number of Ritz values that satisfy convergence\n  ip(5) = 0; //ip(5) not referenced\n  ip(6) = mode; // mode\n  ip(7) = 0;\n  ip(8) = 0;\n  ip(9) = 0;\n  ip(10) = 0;\n  // ip(7) to ip(10) return values\n\n  Array<F77_INT> iptr (dim_vector (14, 1));\n  F77_INT *ipntr = iptr.rwdata ();\n\n  F77_INT ido = 0;\n  int iter = 0;\n  M L, U;\n  ColumnVector r(n);\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, P, (have_b ? b.rows () : m.rows ()));\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Q, (have_b ? b.cols () : m.cols ()));\n\n  if (! LuAminusSigmaB (m, b, cholB, permB, sigma, L, U, P, Q, r))\n    return -1;\n\n  F77_INT elems;\n  F77_INT lwork;\n\n  if (octave::math::int_multiply_overflow (n, p, &elems))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n  if (octave::math::int_multiply_overflow (p, 3 * p + 5, &lwork))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n\n  OCTAVE_LOCAL_BUFFER (Complex, v, elems);\n  OCTAVE_LOCAL_BUFFER (Complex, workl, lwork);\n  OCTAVE_LOCAL_BUFFER (Complex, workd, 3 * n);\n  OCTAVE_LOCAL_BUFFER (double, rwork, p);\n  Complex *presid = cresid.rwdata ();\n\n  do\n    {\n      F77_INT tmp_info = octave::to_f77_int (info);\n\n      F77_FUNC (znaupd, ZNAUPD)\n      (ido, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n       F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n       k, tol, F77_DBLE_CMPLX_ARG (presid), p, F77_DBLE_CMPLX_ARG (v), n,\n       iparam, ipntr,\n       F77_DBLE_CMPLX_ARG (workd), F77_DBLE_CMPLX_ARG (workl), lwork, rwork,\n       tmp_info F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n      info = tmp_info;\n\n      if (disp > 0 && ! octave::math::isnan(workl[iptr(5)-1]))\n        {\n          if (iter++)\n            {\n              os << \"Iteration \" << iter - 1 <<\n                 \": a few Ritz values of the \" << p << \"-by-\" <<\n                 p << \" matrix\\n\";\n              if (ido == 99) // convergence\n                {\n                  for (F77_INT i = 0; i < k; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n              else\n                {\n                  // the wanted Ritz estimates are at the end\n                  for (F77_INT i = p - k; i < p; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n            }\n\n          // This is a kludge, as ARPACK doesn't give its\n          // iteration pointer.  But as workl[iptr(5)-1] is\n          // an output value updated at each iteration, setting\n          // a value in this array to NaN and testing for it\n          // is a way of obtaining the iteration counter.\n          if (ido != 99)\n            workl[iptr(5)-1] = octave::numeric_limits<double>::NaN ();\n        }\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          if (have_b)\n            {\n              if (ido == -1)\n                {\n                  OCTAVE_LOCAL_BUFFER (Complex, ctmp, n);\n\n                  vector_product (b, workd+iptr(0)-1, ctmp);\n\n                  ComplexMatrix tmp (n, 1);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    tmp(i, 0) = ctmp[P[i]] / r(P[i]);\n\n                  lusolve (L, U, tmp);\n\n                  Complex *ip2 = workd+iptr(1)-1;\n                  for (F77_INT i = 0; i < n; i++)\n                    ip2[Q[i]] = tmp(i, 0);\n                }\n              else if (ido == 2)\n                vector_product (b, workd + iptr(0) - 1, workd + iptr(1) - 1);\n              else\n                {\n                  Complex *ip2 = workd+iptr(2)-1;\n                  ComplexMatrix tmp (n, 1);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    tmp(i, 0) = ip2[P[i]] / r(P[i]);\n\n                  lusolve (L, U, tmp);\n\n                  ip2 = workd+iptr(1)-1;\n                  for (F77_INT i = 0; i < n; i++)\n                    ip2[Q[i]] = tmp(i, 0);\n                }\n            }\n          else\n            {\n              // ido cannot be 2 for non-generalized problems (see znaup2).\n              Complex *ip2 = workd+iptr(0)-1;\n              ComplexMatrix tmp (n, 1);\n\n              for (F77_INT i = 0; i < n; i++)\n                tmp(i, 0) = ip2[P[i]] / r(P[i]);\n\n              lusolve (L, U, tmp);\n\n              ip2 = workd+iptr(1)-1;\n              for (F77_INT i = 0; i < n; i++)\n                ip2[Q[i]] = tmp(i, 0);\n            }\n        }\n      else\n        {\n          if (info < 0)\n            (*current_liboctave_error_handler)\n              (\"eigs: error %\" OCTAVE_IDX_TYPE_FORMAT \" in znaupd: %s\",\n               info, arpack_errno2str (info, \"znaupd\").c_str ());\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT info2;\n\n  // We have a problem in that the size of the C++ bool\n  // type relative to the fortran logical type.  It appears\n  // that fortran uses 4- or 8-bytes per logical and C++ 1-byte\n  // per bool, though this might be system dependent.  As\n  // long as the HOWMNY arg is not \"S\", the logical array\n  // is just workspace for ARPACK, so use int type to\n  // avoid problems.\n  Array<F77_INT> s (dim_vector (p, 1));\n  F77_INT *sel = s.rwdata ();\n\n  eig_vec.resize (n, k);\n  Complex *z = eig_vec.rwdata ();\n\n  eig_val.resize (k+1);\n  Complex *d = eig_val.rwdata ();\n\n  OCTAVE_LOCAL_BUFFER (Complex, workev, 2 * p);\n\n  F77_FUNC (zneupd, ZNEUPD)\n  (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1), sel, F77_DBLE_CMPLX_ARG (d),\n   F77_DBLE_CMPLX_ARG (z), n, F77_CONST_DBLE_CMPLX_ARG (&sigma),\n   F77_DBLE_CMPLX_ARG (workev),\n   F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n   F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n   k, tol, F77_DBLE_CMPLX_ARG (presid), p, F77_DBLE_CMPLX_ARG (v), n,\n   iparam, ipntr,\n   F77_DBLE_CMPLX_ARG (workd), F77_DBLE_CMPLX_ARG (workl), lwork, rwork,\n   info2 F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n  if (info2 == 0)\n    {\n      for (F77_INT i = ip(4); i < k; i++)\n        d[i] = Complex (octave::numeric_limits<double>::NaN (),\n                        octave::numeric_limits<double>::NaN ());\n\n      F77_INT k2 = ip(4) / 2;\n      for (F77_INT i = 0; i < k2; i++)\n        {\n          Complex ctmp = d[i];\n          d[i] = d[ip(4) - i - 1];\n          d[ip(4) - i - 1] = ctmp;\n        }\n      eig_val.resize (k);\n\n      if (rvec)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, ctmp, n);\n\n          for (F77_INT i = ip(4); i < k; i++)\n            {\n              F77_INT off1 = i * n;\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = Complex (octave::numeric_limits<double>::NaN (),\n                                       octave::numeric_limits<double>::NaN ());\n            }\n\n          for (F77_INT i = 0; i < k2; i++)\n            {\n              F77_INT off1 = i * n;\n              F77_INT off2 = (ip(4) - i - 1) * n;\n\n              if (off1 == off2)\n                continue;\n\n              for (F77_INT j = 0; j < n; j++)\n                ctmp[j] = z[off1 + j];\n\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = z[off2 + j];\n\n              for (F77_INT j = 0; j < n; j++)\n                z[off2 + j] = ctmp[j];\n            }\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"eigs: error in zneupd: %s\",\n       arpack_errno2str (info2, \"zneupd\").c_str ());\n\n  return ip(4);\n}\n\ntemplate <typename M>\noctave_idx_type\nEigsComplexNonSymmetricFunc (EigsComplexFunc fcn, octave_idx_type n_arg,\n                             const std::string& _typ, Complex sigma,\n                             octave_idx_type k_arg, octave_idx_type p_arg,\n                             octave_idx_type& info, ComplexMatrix& eig_vec,\n                             ComplexColumnVector& eig_val, const M& _b,\n                             ColumnVector& permB, ComplexColumnVector& cresid,\n                             std::ostream& os, double tol, bool rvec,\n                             bool cholB, int disp, int maxit)\n{\n  F77_INT n = octave::to_f77_int (n_arg);\n  F77_INT k = octave::to_f77_int (k_arg);\n  F77_INT p = octave::to_f77_int (p_arg);\n  M b(_b);\n  std::string typ (_typ);\n  bool have_sigma = (std::abs (sigma) ? true : false);\n  F77_INT mode = 1;\n  bool have_b = ! b.isempty ();\n  bool note3 = false;\n  char bmat = 'I';\n  int err = 0;\n  M bt;\n\n  if (cresid.isempty ())\n    {\n      std::string rand_dist = octave::rand::distribution ();\n      octave::rand::distribution (\"uniform\");\n      Array<double> rr (octave::rand::vector (n));\n      Array<double> ri (octave::rand::vector (n));\n      cresid = ComplexColumnVector (n);\n      for (F77_INT i = 0; i < n; i++)\n        cresid(i) = Complex (rr(i), ri(i));\n      octave::rand::distribution (rand_dist);\n    }\n  else if (n != cresid.numel ())\n    (*current_liboctave_error_handler) (\"eigs: opts.v0 must be n-by-1\");\n\n  if (n < 3)\n    (*current_liboctave_error_handler) (\"eigs: n must be at least 3\");\n\n  if (p < 0)\n    {\n      p = k * 2 + 1;\n\n      if (p < 20)\n        p = 20;\n\n      if (p > n)\n        p = n;\n    }\n\n  if (k <= 0 || k >= n - 1)\n    (*current_liboctave_error_handler)\n      (\"eigs: Invalid number of eigenvalues to extract\"\n       \" (must be 0 < k < n-1).\\n\"\n       \"      Use 'eig (full (A))' instead\");\n\n  if (p <= k || p > n)\n    (*current_liboctave_error_handler)\n      (\"eigs: opts.p must be greater than k and less than or equal to n\");\n\n  if (have_b && cholB && ! permB.isempty ())\n    {\n      // Check the we really have a permutation vector\n      if (permB.numel () != n)\n        (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n\n      Array<bool> checked (dim_vector (n, 1), false);\n      for (F77_INT i = 0; i < n; i++)\n        {\n          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));\n\n          if (checked(bidx) || bidx < 0 || bidx >= n)\n            (*current_liboctave_error_handler) (\"eigs: permB vector invalid\");\n        }\n    }\n\n  if (! have_sigma)\n    {\n      if (typ != \"LM\" && typ != \"SM\" && typ != \"LA\" && typ != \"SA\"\n          && typ != \"BE\" && typ != \"LR\" && typ != \"SR\" && typ != \"LI\"\n          && typ != \"SI\")\n        (*current_liboctave_error_handler) (\"eigs: unrecognized sigma value\");\n\n      if (typ == \"LA\" || typ == \"SA\" || typ == \"BE\")\n        (*current_liboctave_error_handler)\n          (\"eigs: invalid sigma value for complex problem\");\n\n      if (typ != \"SM\" && have_b)\n        note3 = true;\n\n      if (typ == \"SM\")\n        {\n          typ = \"LM\";\n          sigma = 0.;\n          mode = 3;\n          if (have_b)\n            bmat ='G';\n        }\n    }\n  else if (! std::abs (sigma))\n    {\n      typ = \"SM\";\n      if (have_b)\n        bmat = 'G';\n    }\n  else\n    {\n      typ = \"LM\";\n      mode = 3;\n      if (have_b)\n        bmat = 'G';\n    }\n\n  if (mode == 1 && have_b)\n    {\n      // See Note 3 dsaupd\n      note3 = true;\n      if (cholB)\n        {\n          bt = b;\n          b = b.hermitian ();\n          if (permB.isempty ())\n            {\n              permB = ColumnVector (n);\n              for (F77_INT i = 0; i < n; i++)\n                permB(i) = i;\n            }\n        }\n      else\n        {\n          if (! make_cholb (b, bt, permB))\n            (*current_liboctave_error_handler)\n              (\"eigs: The matrix B is not positive definite\");\n        }\n    }\n\n  Array<F77_INT> ip (dim_vector (11, 1));\n  F77_INT *iparam = ip.rwdata ();\n\n  ip(0) = 1; //ishift\n  ip(1) = 0;   // ip(1) not referenced\n  ip(2) = maxit; // mxiter, maximum number of iterations\n  ip(3) = 1; // NB blocksize in recurrence\n  ip(4) = 0; // nconv, number of Ritz values that satisfy convergence\n  ip(5) = 0; //ip(5) not referenced\n  ip(6) = mode; // mode\n  ip(7) = 0;\n  ip(8) = 0;\n  ip(9) = 0;\n  ip(10) = 0;\n  // ip(7) to ip(10) return values\n\n  Array<F77_INT> iptr (dim_vector (14, 1));\n  F77_INT *ipntr = iptr.rwdata ();\n\n  F77_INT ido = 0;\n  int iter = 0;\n  F77_INT elems;\n  F77_INT lwork;\n\n  if (octave::math::int_multiply_overflow (n, p, &elems))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n  if (octave::math::int_multiply_overflow (p, 3 * p + 5, &lwork))\n    (*current_liboctave_error_handler)\n      (\"eigs: array too large for Fortran integers\");\n\n  OCTAVE_LOCAL_BUFFER (Complex, v, elems);\n  OCTAVE_LOCAL_BUFFER (Complex, workl, lwork);\n  OCTAVE_LOCAL_BUFFER (Complex, workd, 3 * n);\n  OCTAVE_LOCAL_BUFFER (double, rwork, p);\n  Complex *presid = cresid.rwdata ();\n\n  do\n    {\n      F77_INT tmp_info = octave::to_f77_int (info);\n\n      F77_FUNC (znaupd, ZNAUPD)\n      (ido, F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n       F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n       k, tol, F77_DBLE_CMPLX_ARG (presid), p, F77_DBLE_CMPLX_ARG (v), n,\n       iparam, ipntr,\n       F77_DBLE_CMPLX_ARG (workd), F77_DBLE_CMPLX_ARG (workl), lwork, rwork,\n       tmp_info F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n      info = tmp_info;\n\n      if (disp > 0 && ! octave::math::isnan(workl[iptr(5)-1]))\n        {\n          if (iter++)\n            {\n              os << \"Iteration \" << iter - 1 <<\n                 \": a few Ritz values of the \" << p << \"-by-\" <<\n                 p << \" matrix\\n\";\n              if (ido == 99) // convergence\n                {\n                  for (F77_INT i = 0; i < k; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n              else\n                {\n                  // the wanted Ritz estimates are at the end\n                  for (F77_INT i = p - k; i < p; i++)\n                    os << \"    \" << workl[iptr(5)+i-1] << \"\\n\";\n                }\n            }\n\n          // This is a kludge, as ARPACK doesn't give its\n          // iteration pointer.  But as workl[iptr(5)-1] is\n          // an output value updated at each iteration, setting\n          // a value in this array to NaN and testing for it\n          // is a way of obtaining the iteration counter.\n          if (ido != 99)\n            workl[iptr(5)-1] = octave::numeric_limits<double>::NaN ();\n        }\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          if (have_b)\n            {\n              if (mode == 1) // regular mode with factorized B\n                {\n                  ComplexMatrix mtmp (n, 1);\n                  for (F77_INT i = 0; i < n; i++)\n                    mtmp(i, 0) = workd[i + iptr(0) - 1];\n\n                  mtmp = utsolve (bt, permB, mtmp);\n                  ComplexColumnVector y = fcn (mtmp, err);\n\n                  if (err)\n                    return false;\n\n                  mtmp = ltsolve (b, permB, y);\n\n                  for (F77_INT i = 0; i < n; i++)\n                    workd[i+iptr(1)-1] = mtmp(i, 0);\n                }\n              else // shift-invert mode\n                {\n                  if (ido == -1)\n                    {\n                      OCTAVE_LOCAL_BUFFER (Complex, ctmp, n);\n\n                      vector_product (b, workd+iptr(0)-1, ctmp);\n\n                      ComplexColumnVector x(n);\n\n                      for (F77_INT i = 0; i < n; i++)\n                        x(i) = ctmp[i];\n\n                      ComplexColumnVector y = fcn (x, err);\n\n                      if (err)\n                        return false;\n\n                      Complex *ip2 = workd+iptr(1)-1;\n                      for (F77_INT i = 0; i < n; i++)\n                        ip2[i] = y(i);\n                    }\n                  else if (ido == 2)\n                    vector_product (b, workd+iptr(0)-1, workd+iptr(1)-1);\n                  else\n                    {\n                      Complex *ip2 = workd+iptr(2)-1;\n                      ComplexColumnVector x(n);\n\n                      for (F77_INT i = 0; i < n; i++)\n                        x(i) = *ip2++;\n\n                      ComplexColumnVector y = fcn (x, err);\n\n                      if (err)\n                        return false;\n\n                      ip2 = workd + iptr(1) - 1;\n                      for (F77_INT i = 0; i < n; i++)\n                        *ip2++ = y(i);\n                    }\n                }\n            }\n          else\n            {\n              Complex *ip2 = workd + iptr(0) - 1;\n              ComplexColumnVector x(n);\n\n              for (F77_INT i = 0; i < n; i++)\n                x(i) = *ip2++;\n\n              ComplexColumnVector y = fcn (x, err);\n\n              if (err)\n                return false;\n\n              ip2 = workd + iptr(1) - 1;\n              for (F77_INT i = 0; i < n; i++)\n                *ip2++ = y(i);\n            }\n        }\n      else\n        {\n          if (info < 0)\n            (*current_liboctave_error_handler)\n              (\"eigs: error %\" OCTAVE_IDX_TYPE_FORMAT \" in znaupd: %s\",\n               info, arpack_errno2str (info, \"znaupd\").c_str ());\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT info2;\n\n  // We have a problem in that the size of the C++ bool\n  // type relative to the fortran logical type.  It appears\n  // that fortran uses 4- or 8-bytes per logical and C++ 1-byte\n  // per bool, though this might be system dependent.  As\n  // long as the HOWMNY arg is not \"S\", the logical array\n  // is just workspace for ARPACK, so use int type to\n  // avoid problems.\n  Array<F77_INT> s (dim_vector (p, 1));\n  F77_INT *sel = s.rwdata ();\n\n  eig_vec.resize (n, k);\n  Complex *z = eig_vec.rwdata ();\n\n  eig_val.resize (k+1);\n  Complex *d = eig_val.rwdata ();\n\n  OCTAVE_LOCAL_BUFFER (Complex, workev, 2 * p);\n\n  F77_FUNC (zneupd, ZNEUPD)\n  (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1), sel, F77_DBLE_CMPLX_ARG (d),\n   F77_DBLE_CMPLX_ARG (z), n, F77_DBLE_CMPLX_ARG (&sigma),\n   F77_DBLE_CMPLX_ARG (workev),\n   F77_CONST_CHAR_ARG2 (&bmat, 1), n,\n   F77_CONST_CHAR_ARG2 ((typ.c_str ()), 2),\n   k, tol, F77_DBLE_CMPLX_ARG (presid), p, F77_DBLE_CMPLX_ARG (v), n,\n   iparam, ipntr,\n   F77_DBLE_CMPLX_ARG (workd), F77_DBLE_CMPLX_ARG (workl), lwork, rwork,\n   info2 F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(1) F77_CHAR_ARG_LEN(2));\n\n  if (info2 == 0)\n    {\n      for (F77_INT i = ip(4); i < k; i++)\n        d[i] = Complex (octave::numeric_limits<double>::NaN (),\n                        octave::numeric_limits<double>::NaN ());\n\n      F77_INT k2 = ip(4) / 2;\n      for (F77_INT i = 0; i < k2; i++)\n        {\n          Complex ctmp = d[i];\n          d[i] = d[ip(4) - i - 1];\n          d[ip(4) - i - 1] = ctmp;\n        }\n      eig_val.resize (k);\n\n      if (rvec)\n        {\n          OCTAVE_LOCAL_BUFFER (Complex, ctmp, n);\n\n          for (F77_INT i = ip(4); i < k; i++)\n            {\n              F77_INT off1 = i * n;\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = Complex (octave::numeric_limits<double>::NaN (),\n                                       octave::numeric_limits<double>::NaN ());\n            }\n\n          for (F77_INT i = 0; i < k2; i++)\n            {\n              F77_INT off1 = i * n;\n              F77_INT off2 = (ip(4) - i - 1) * n;\n\n              if (off1 == off2)\n                continue;\n\n              for (F77_INT j = 0; j < n; j++)\n                ctmp[j] = z[off1 + j];\n\n              for (F77_INT j = 0; j < n; j++)\n                z[off1 + j] = z[off2 + j];\n\n              for (F77_INT j = 0; j < n; j++)\n                z[off2 + j] = ctmp[j];\n            }\n          if (note3)\n            eig_vec = utsolve (bt, permB, eig_vec);\n        }\n    }\n  else\n    (*current_liboctave_error_handler)\n      (\"eigs: error in zneupd: %s\",\n       arpack_errno2str (info2, \"zneupd\").c_str ());\n\n  return ip(4);\n}\n\n// Instantiations for the types we need.\n\n// Matrix\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealSymmetricMatrix<Matrix>\n  (const Matrix& m, const std::string typ, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, Matrix& eig_vec,\n   ColumnVector& eig_val, const Matrix& _b, ColumnVector& permB,\n   ColumnVector& resid, std::ostream& os, double tol, bool rvec,\n   bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealSymmetricMatrixShift<Matrix>\n  (const Matrix& m, double sigma, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, Matrix& eig_vec,\n   ColumnVector& eig_val, const Matrix& _b, ColumnVector& permB,\n   ColumnVector& resid, std::ostream& os, double tol, bool rvec,\n   bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealSymmetricFunc<Matrix>\n  (EigsFunc fcn, octave_idx_type n, const std::string& _typ, double sigma,\n   octave_idx_type k, octave_idx_type p, octave_idx_type& info,\n   Matrix& eig_vec, ColumnVector& eig_val, const Matrix& _b,\n   ColumnVector& permB, ColumnVector& resid, std::ostream& os, double tol,\n   bool rvec, bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealNonSymmetricMatrix<Matrix>\n  (const Matrix& m, const std::string typ, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,\n   ComplexColumnVector& eig_val, const Matrix& _b, ColumnVector& permB,\n   ColumnVector& resid, std::ostream& os, double tol, bool rvec,\n   bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealNonSymmetricMatrixShift<Matrix>\n  (const Matrix& m, double sigmar, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,\n   ComplexColumnVector& eig_val, const Matrix& _b, ColumnVector& permB,\n   ColumnVector& resid, std::ostream& os, double tol, bool rvec,\n   bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealNonSymmetricFunc<Matrix>\n  (EigsFunc fcn, octave_idx_type n, const std::string& _typ, double sigmar,\n   octave_idx_type k, octave_idx_type p, octave_idx_type& info,\n   ComplexMatrix& eig_vec, ComplexColumnVector& eig_val, const Matrix& _b,\n   ColumnVector& permB, ColumnVector& resid, std::ostream& os, double tol,\n   bool rvec, bool cholB, int disp, int maxit);\n\n// SparseMatrix\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealSymmetricMatrix<SparseMatrix>\n  (const SparseMatrix& m, const std::string typ, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, Matrix& eig_vec,\n   ColumnVector& eig_val, const SparseMatrix& _b, ColumnVector& permB,\n   ColumnVector& resid, std::ostream& os, double tol, bool rvec,\n   bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealSymmetricMatrixShift<SparseMatrix>\n  (const SparseMatrix& m, double sigma, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, Matrix& eig_vec,\n   ColumnVector& eig_val, const SparseMatrix& _b, ColumnVector& permB,\n   ColumnVector& resid, std::ostream& os, double tol, bool rvec,\n   bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealSymmetricFunc<SparseMatrix>\n  (EigsFunc fcn, octave_idx_type n, const std::string& _typ, double sigma,\n   octave_idx_type k, octave_idx_type p, octave_idx_type& info,\n   Matrix& eig_vec, ColumnVector& eig_val, const SparseMatrix& _b,\n   ColumnVector& permB, ColumnVector& resid, std::ostream& os, double tol,\n   bool rvec, bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealNonSymmetricMatrix<SparseMatrix>\n  (const SparseMatrix& m, const std::string typ, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,\n   ComplexColumnVector& eig_val, const SparseMatrix& _b, ColumnVector& permB,\n   ColumnVector& resid, std::ostream& os, double tol, bool rvec,\n   bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealNonSymmetricMatrixShift<SparseMatrix>\n  (const SparseMatrix& m, double sigmar, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,\n   ComplexColumnVector& eig_val, const SparseMatrix& _b, ColumnVector& permB,\n   ColumnVector& resid, std::ostream& os, double tol, bool rvec,\n   bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsRealNonSymmetricFunc<SparseMatrix>\n  (EigsFunc fcn, octave_idx_type n, const std::string& _typ, double sigmar,\n   octave_idx_type k, octave_idx_type p, octave_idx_type& info,\n   ComplexMatrix& eig_vec, ComplexColumnVector& eig_val,\n   const SparseMatrix& _b, ColumnVector& permB, ColumnVector& resid,\n   std::ostream& os, double tol, bool rvec, bool cholB, int disp, int maxit);\n\n// ComplexMatrix\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsComplexNonSymmetricMatrix<ComplexMatrix>\n  (const ComplexMatrix& m, const std::string typ, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,\n   ComplexColumnVector& eig_val, const ComplexMatrix& _b, ColumnVector& permB,\n   ComplexColumnVector& cresid, std::ostream& os, double tol,\n   bool rvec, bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsComplexNonSymmetricMatrixShift<ComplexMatrix>\n  (const ComplexMatrix& m, Complex sigma, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,\n   ComplexColumnVector& eig_val, const ComplexMatrix& _b, ColumnVector& permB,\n   ComplexColumnVector& cresid, std::ostream& os, double tol,\n   bool rvec, bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsComplexNonSymmetricFunc<ComplexMatrix>\n  (EigsComplexFunc fcn, octave_idx_type n, const std::string& _typ, Complex sigma,\n   octave_idx_type k, octave_idx_type p, octave_idx_type& info,\n   ComplexMatrix& eig_vec, ComplexColumnVector& eig_val,\n   const ComplexMatrix& _b, ColumnVector& permB, ComplexColumnVector& cresid,\n   std::ostream& os, double tol, bool rvec, bool cholB, int disp, int maxit);\n\n// SparseComplexMatrix\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsComplexNonSymmetricMatrix<SparseComplexMatrix>\n  (const SparseComplexMatrix& m, const std::string typ, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,\n   ComplexColumnVector& eig_val, const SparseComplexMatrix& _b,\n   ColumnVector& permB, ComplexColumnVector& cresid, std::ostream& os,\n   double tol, bool rvec, bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsComplexNonSymmetricMatrixShift<SparseComplexMatrix>\n  (const SparseComplexMatrix& m, Complex sigma, octave_idx_type k,\n   octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,\n   ComplexColumnVector& eig_val, const SparseComplexMatrix& _b,\n   ColumnVector& permB, ComplexColumnVector& cresid, std::ostream& os,\n   double tol, bool rvec, bool cholB, int disp, int maxit);\n\ntemplate\nOCTAVE_API octave_idx_type\nEigsComplexNonSymmetricFunc<SparseComplexMatrix>\n  (EigsComplexFunc fcn, octave_idx_type n, const std::string& _typ, Complex sigma,\n   octave_idx_type k, octave_idx_type p, octave_idx_type& info,\n   ComplexMatrix& eig_vec, ComplexColumnVector& eig_val,\n   const SparseComplexMatrix& _b, ColumnVector& permB,\n   ComplexColumnVector& cresid, std::ostream& os, double tol, bool rvec,\n   bool cholB, int disp, int maxit);\n#endif\n"
  },
  {
    "path": "liboctave/numeric/eigs-base.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_eigs_base_h)\n#define octave_eigs_base_h 1\n\n#include \"octave-config.h\"\n\n#include <functional>\n#include <iosfwd>\n#include <string>\n\n#include \"mx-fwd.h\"\n#include \"oct-cmplx.h\"\n\ntypedef\nstd::function<ColumnVector (const ColumnVector& x, int& eigs_error)> EigsFunc;\n\ntypedef\nstd::function<ComplexColumnVector\n              (const ComplexColumnVector& x, int& eigs_error)> EigsComplexFunc;\n\ntemplate <typename M>\nOCTAVE_API octave_idx_type\nEigsRealSymmetricMatrix (const M& m, const std::string typ,\n                         octave_idx_type k, octave_idx_type p,\n                         octave_idx_type& info, Matrix& eig_vec,\n                         ColumnVector& eig_val, const M& _b,\n                         ColumnVector& permB, ColumnVector& resid,\n                         std::ostream& os, double tol, bool rvec,\n                         bool cholB, int disp, int maxit);\n\ntemplate <typename M>\nOCTAVE_API octave_idx_type\nEigsRealSymmetricMatrixShift (const M& m, double sigma,\n                              octave_idx_type k, octave_idx_type p,\n                              octave_idx_type& info, Matrix& eig_vec,\n                              ColumnVector& eig_val, const M& _b,\n                              ColumnVector& permB, ColumnVector& resid,\n                              std::ostream& os, double tol, bool rvec,\n                              bool cholB, int disp, int maxit);\n\ntemplate <typename M>\nOCTAVE_API octave_idx_type\nEigsRealSymmetricFunc (EigsFunc fcn, octave_idx_type n,\n                       const std::string& _typ, double sigma,\n                       octave_idx_type k, octave_idx_type p,\n                       octave_idx_type& info, Matrix& eig_vec,\n                       ColumnVector& eig_val, const M& _b,\n                       ColumnVector& permB, ColumnVector& resid,\n                       std::ostream& os, double tol, bool rvec,\n                       bool cholB, int disp, int maxit);\n\ntemplate <typename M>\nOCTAVE_API octave_idx_type\nEigsRealNonSymmetricMatrix (const M& m, const std::string typ,\n                            octave_idx_type k, octave_idx_type p,\n                            octave_idx_type& info, ComplexMatrix& eig_vec,\n                            ComplexColumnVector& eig_val, const M& _b,\n                            ColumnVector& permB, ColumnVector& resid,\n                            std::ostream& os, double tol, bool rvec,\n                            bool cholB, int disp, int maxit);\n\ntemplate <typename M>\nOCTAVE_API octave_idx_type\nEigsRealNonSymmetricMatrixShift (const M& m, double sigmar,\n                                 octave_idx_type k, octave_idx_type p,\n                                 octave_idx_type& info,\n                                 ComplexMatrix& eig_vec,\n                                 ComplexColumnVector& eig_val, const M& _b,\n                                 ColumnVector& permB, ColumnVector& resid,\n                                 std::ostream& os, double tol, bool rvec,\n                                 bool cholB, int disp, int maxit);\n\ntemplate <typename M>\nOCTAVE_API octave_idx_type\nEigsRealNonSymmetricFunc (EigsFunc fcn, octave_idx_type n,\n                          const std::string& _typ, double sigmar,\n                          octave_idx_type k, octave_idx_type p,\n                          octave_idx_type& info, ComplexMatrix& eig_vec,\n                          ComplexColumnVector& eig_val, const M& _b,\n                          ColumnVector& permB, ColumnVector& resid,\n                          std::ostream& os, double tol, bool rvec,\n                          bool cholB, int disp, int maxit);\n\ntemplate <typename M>\nOCTAVE_API octave_idx_type\nEigsComplexNonSymmetricMatrix (const M& m, const std::string typ,\n                               octave_idx_type k, octave_idx_type p,\n                               octave_idx_type& info, ComplexMatrix& eig_vec,\n                               ComplexColumnVector& eig_val, const M& _b,\n                               ColumnVector& permB,\n                               ComplexColumnVector& cresid,\n                               std::ostream& os, double tol, bool rvec,\n                               bool cholB, int disp, int maxit);\n\ntemplate <typename M>\nOCTAVE_API octave_idx_type\nEigsComplexNonSymmetricMatrixShift (const M& m, Complex sigma,\n                                    octave_idx_type k, octave_idx_type p,\n                                    octave_idx_type& info,\n                                    ComplexMatrix& eig_vec,\n                                    ComplexColumnVector& eig_val, const M& _b,\n                                    ColumnVector& permB,\n                                    ComplexColumnVector& cresid,\n                                    std::ostream& os, double tol, bool rvec,\n                                    bool cholB, int disp, int maxit);\n\ntemplate <typename M>\nOCTAVE_API octave_idx_type\nEigsComplexNonSymmetricFunc (EigsComplexFunc fcn, octave_idx_type n,\n                             const std::string& _typ, Complex sigma,\n                             octave_idx_type k, octave_idx_type p,\n                             octave_idx_type& info, ComplexMatrix& eig_vec,\n                             ComplexColumnVector& eig_val, const M& _b,\n                             ColumnVector& permB, ComplexColumnVector& cresid,\n                             std::ostream& os, double tol, bool rvec,\n                             bool cholB, int disp, int maxit);\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/fEIG.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-oct.h\"\n#include \"fColVector.h\"\n#include \"fEIG.h\"\n#include \"fMatrix.h\"\n#include \"lapack-proto.h\"\n#include \"oct-error.h\"\n\noctave_idx_type\nFloatEIG::init (const FloatMatrix& a, bool calc_rev, bool calc_lev,\n                bool balance)\n{\n  if (a.any_element_is_inf_or_nan ())\n    (*current_liboctave_error_handler)\n      (\"EIG: matrix contains Inf or NaN values\");\n\n  if (a.issymmetric ())\n    return symmetric_init (a, calc_rev, calc_lev);\n\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (n != a_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  F77_INT info = 0;\n\n  FloatMatrix atmp = a;\n  float *tmp_data = atmp.rwdata ();\n\n  Array<float> wr (dim_vector (n, 1));\n  float *pwr = wr.rwdata ();\n\n  Array<float> wi (dim_vector (n, 1));\n  float *pwi = wi.rwdata ();\n\n  F77_INT nvr = (calc_rev ? n : 0);\n  FloatMatrix vr (nvr, nvr);\n  float *pvr = vr.rwdata ();\n\n  F77_INT nvl = (calc_lev ? n : 0);\n  FloatMatrix vl (nvl, nvl);\n  float *pvl = vl.rwdata ();\n\n  F77_INT lwork = -1;\n  float dummy_work;\n\n  F77_INT ilo;\n  F77_INT ihi;\n\n  Array<float> scale (dim_vector (n, 1));\n  float *pscale = scale.rwdata ();\n\n  float abnrm;\n\n  Array<float> rconde (dim_vector (n, 1));\n  float *prconde = rconde.rwdata ();\n\n  Array<float> rcondv (dim_vector (n, 1));\n  float *prcondv = rcondv.rwdata ();\n\n  F77_INT dummy_iwork;\n\n  F77_XFCN (sgeevx, SGEEVX, (F77_CONST_CHAR_ARG2 (balance ? \"B\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             n, tmp_data, n, pwr, pwi,\n                             pvl, n, pvr, n,\n                             ilo, ihi, pscale, abnrm, prconde, prcondv,\n                             &dummy_work, lwork, &dummy_iwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"sgeevx workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work);\n  Array<float> work (dim_vector (lwork, 1));\n  float *pwork = work.rwdata ();\n\n  F77_XFCN (sgeevx, SGEEVX, (F77_CONST_CHAR_ARG2 (balance ? \"B\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             n, tmp_data, n, pwr, pwi,\n                             pvl, n, pvr, n,\n                             ilo, ihi, pscale, abnrm, prconde, prcondv,\n                             pwork, lwork, &dummy_iwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in sgeevx\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"sgeevx failed to converge\");\n\n  m_lambda.resize (n);\n  m_v.resize (nvr, nvr);\n  m_w.resize (nvl, nvl);\n\n  for (F77_INT j = 0; j < n; j++)\n    {\n      if (wi.elem (j) == 0.0)\n        {\n          m_lambda.elem (j) = FloatComplex (wr.elem (j));\n          for (octave_idx_type i = 0; i < nvr; i++)\n            m_v.elem (i, j) = vr.elem (i, j);\n\n          for (F77_INT i = 0; i < nvl; i++)\n            m_w.elem (i, j) = vl.elem (i, j);\n        }\n      else\n        {\n          if (j+1 >= n)\n            (*current_liboctave_error_handler) (\"EIG: internal error\");\n\n          m_lambda.elem (j) = FloatComplex (wr.elem (j), wi.elem (j));\n          m_lambda.elem (j+1) = FloatComplex (wr.elem (j+1), wi.elem (j+1));\n\n          for (F77_INT i = 0; i < nvr; i++)\n            {\n              float real_part = vr.elem (i, j);\n              float imag_part = vr.elem (i, j+1);\n              m_v.elem (i, j) = FloatComplex (real_part, imag_part);\n              m_v.elem (i, j+1) = FloatComplex (real_part, -imag_part);\n            }\n          for (F77_INT i = 0; i < nvl; i++)\n            {\n              float real_part = vl.elem (i, j);\n              float imag_part = vl.elem (i, j+1);\n              m_w.elem (i, j) = FloatComplex (real_part, imag_part);\n              m_w.elem (i, j+1) = FloatComplex (real_part, -imag_part);\n            }\n          j++;\n        }\n    }\n\n  return info;\n}\n\noctave_idx_type\nFloatEIG::symmetric_init (const FloatMatrix& a, bool calc_rev, bool calc_lev)\n{\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (n != a_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  F77_INT info = 0;\n\n  FloatMatrix atmp = a;\n  float *tmp_data = atmp.rwdata ();\n\n  FloatColumnVector wr (n);\n  float *pwr = wr.rwdata ();\n\n  F77_INT lwork = -1;\n  float dummy_work;\n\n  F77_XFCN (ssyev, SSYEV, (F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, tmp_data, n, pwr, &dummy_work, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"ssyev workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work);\n  Array<float> work (dim_vector (lwork, 1));\n  float *pwork = work.rwdata ();\n\n  F77_XFCN (ssyev, SSYEV, (F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, tmp_data, n, pwr, pwork, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in ssyev\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"ssyev failed to converge\");\n\n  m_lambda = FloatComplexColumnVector (wr);\n  m_v = (calc_rev ? FloatComplexMatrix (atmp) : FloatComplexMatrix ());\n  m_w = (calc_lev ? FloatComplexMatrix (atmp) : FloatComplexMatrix ());\n\n  return info;\n}\n\noctave_idx_type\nFloatEIG::init (const FloatComplexMatrix& a, bool calc_rev, bool calc_lev,\n                bool balance)\n{\n  if (a.any_element_is_inf_or_nan ())\n    (*current_liboctave_error_handler)\n      (\"EIG: matrix contains Inf or NaN values\");\n\n  if (a.ishermitian ())\n    return hermitian_init (a, calc_rev, calc_lev);\n\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (n != a_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  F77_INT info = 0;\n\n  FloatComplexMatrix atmp = a;\n  FloatComplex *tmp_data = atmp.rwdata ();\n\n  FloatComplexColumnVector wr (n);\n  FloatComplex *pw = wr.rwdata ();\n\n  F77_INT nvr = (calc_rev ? n : 0);\n  FloatComplexMatrix vrtmp (nvr, nvr);\n  FloatComplex *pvr = vrtmp.rwdata ();\n\n  F77_INT nvl = (calc_lev ? n : 0);\n  FloatComplexMatrix vltmp (nvl, nvl);\n  FloatComplex *pvl = vltmp.rwdata ();\n\n  F77_INT lwork = -1;\n  FloatComplex dummy_work;\n\n  F77_INT lrwork = 2*n;\n  Array<float> rwork (dim_vector (lrwork, 1));\n  float *prwork = rwork.rwdata ();\n\n  F77_INT ilo;\n  F77_INT ihi;\n\n  Array<float> scale (dim_vector (n, 1));\n  float *pscale = scale.rwdata ();\n\n  float abnrm;\n\n  Array<float> rconde (dim_vector (n, 1));\n  float *prconde = rconde.rwdata ();\n\n  Array<float> rcondv (dim_vector (n, 1));\n  float *prcondv = rcondv.rwdata ();\n\n  F77_XFCN (cgeevx, CGEEVX, (F77_CONST_CHAR_ARG2 (balance ? \"B\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             n, F77_CMPLX_ARG (tmp_data), n, F77_CMPLX_ARG (pw),\n                             F77_CMPLX_ARG (pvl), n, F77_CMPLX_ARG (pvr), n,\n                             ilo, ihi, pscale, abnrm, prconde, prcondv,\n                             F77_CMPLX_ARG (&dummy_work), lwork, prwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"cgeevx workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work.real ());\n  Array<FloatComplex> work (dim_vector (lwork, 1));\n  FloatComplex *pwork = work.rwdata ();\n\n  F77_XFCN (cgeevx, CGEEVX, (F77_CONST_CHAR_ARG2 (balance ? \"B\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                             F77_CONST_CHAR_ARG2 (\"N\", 1),\n                             n, F77_CMPLX_ARG (tmp_data), n, F77_CMPLX_ARG (pw),\n                             F77_CMPLX_ARG (pvl), n, F77_CMPLX_ARG (pvr), n,\n                             ilo, ihi, pscale, abnrm, prconde, prcondv,\n                             F77_CMPLX_ARG (pwork), lwork, prwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in cgeevx\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"cgeevx failed to converge\");\n\n  m_lambda = wr;\n  m_v = vrtmp;\n  m_w = vltmp;\n\n  return info;\n}\n\noctave_idx_type\nFloatEIG::hermitian_init (const FloatComplexMatrix& a, bool calc_rev,\n                          bool calc_lev)\n{\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n\n  if (n != a_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  F77_INT info = 0;\n\n  FloatComplexMatrix atmp = a;\n  FloatComplex *tmp_data = atmp.rwdata ();\n\n  FloatColumnVector wr (n);\n  float *pwr = wr.rwdata ();\n\n  F77_INT lwork = -1;\n  FloatComplex dummy_work;\n\n  F77_INT lrwork = 3*n;\n  Array<float> rwork (dim_vector (lrwork, 1));\n  float *prwork = rwork.rwdata ();\n\n  F77_XFCN (cheev, CHEEV, (F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, F77_CMPLX_ARG (tmp_data), n, pwr,\n                           F77_CMPLX_ARG (&dummy_work), lwork,\n                           prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"cheev workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work.real ());\n  Array<FloatComplex> work (dim_vector (lwork, 1));\n  FloatComplex *pwork = work.rwdata ();\n\n  F77_XFCN (cheev, CHEEV, (F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, F77_CMPLX_ARG (tmp_data), n, pwr,\n                           F77_CMPLX_ARG (pwork), lwork, prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in cheev\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"cheev failed to converge\");\n\n  m_lambda = FloatComplexColumnVector (wr);\n  m_v = (calc_rev ? FloatComplexMatrix (atmp) : FloatComplexMatrix ());\n  m_w = (calc_lev ? FloatComplexMatrix (atmp) : FloatComplexMatrix ());\n\n  return info;\n}\n\noctave_idx_type\nFloatEIG::init (const FloatMatrix& a, const FloatMatrix& b, bool calc_rev,\n                bool calc_lev, bool force_qz)\n{\n  if (a.any_element_is_inf_or_nan () || b.any_element_is_inf_or_nan ())\n    (*current_liboctave_error_handler)\n      (\"EIG: matrix contains Inf or NaN values\");\n\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT nb = octave::to_f77_int (b.rows ());\n\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (n != a_nc || nb != b_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  if (n != nb)\n    (*current_liboctave_error_handler) (\"EIG requires same size matrices\");\n\n  F77_INT info = 0;\n\n  FloatMatrix tmp = b;\n  float *tmp_data = tmp.rwdata ();\n  if (! force_qz)\n    {\n      F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (\"L\", 1),\n                                 n, tmp_data, n,\n                                 info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (a.issymmetric () && b.issymmetric () && info == 0)\n        return symmetric_init (a, b, calc_rev, calc_lev);\n    }\n\n  FloatMatrix atmp = a;\n  float *atmp_data = atmp.rwdata ();\n\n  FloatMatrix btmp = b;\n  float *btmp_data = btmp.rwdata ();\n\n  Array<float> ar (dim_vector (n, 1));\n  float *par = ar.rwdata ();\n\n  Array<float> ai (dim_vector (n, 1));\n  float *pai = ai.rwdata ();\n\n  Array<float> beta (dim_vector (n, 1));\n  float *pbeta = beta.rwdata ();\n\n  F77_INT nvr = (calc_rev ? n : 0);\n  FloatMatrix vr (nvr, nvr);\n  float *pvr = vr.rwdata ();\n\n  F77_INT nvl = (calc_lev ? n : 0);\n  FloatMatrix vl (nvl, nvl);\n  float *pvl = vl.rwdata ();\n\n  F77_INT lwork = -1;\n  float dummy_work;\n\n  F77_XFCN (sggev, SGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           n, atmp_data, n, btmp_data, n,\n                           par, pai, pbeta,\n                           pvl, n, pvr, n,\n                           &dummy_work, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"sggev workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work);\n  Array<float> work (dim_vector (lwork, 1));\n  float *pwork = work.rwdata ();\n\n  F77_XFCN (sggev, SGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           n, atmp_data, n, btmp_data, n,\n                           par, pai, pbeta,\n                           pvl, n, pvr, n,\n                           pwork, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in sggev\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"sggev failed to converge\");\n\n  m_lambda.resize (n);\n  m_v.resize (nvr, nvr);\n  m_w.resize (nvl, nvl);\n\n\n  for (F77_INT j = 0; j < n; j++)\n    {\n      if (ai.elem (j) == 0.0)\n        {\n          m_lambda.elem (j) = FloatComplex (ar.elem (j) / beta.elem (j));\n          for (F77_INT i = 0; i < nvr; i++)\n            m_v.elem (i, j) = vr.elem (i, j);\n\n          for (F77_INT i = 0; i < nvl; i++)\n            m_w.elem (i, j) = vl.elem (i, j);\n        }\n      else\n        {\n          if (j+1 >= n)\n            (*current_liboctave_error_handler) (\"EIG: internal error\");\n\n          m_lambda.elem (j) = FloatComplex (ar.elem (j) / beta.elem (j),\n                                            ai.elem (j) / beta.elem (j));\n          m_lambda.elem (j+1) = FloatComplex (ar.elem (j+1) / beta.elem (j+1),\n                                              ai.elem (j+1) / beta.elem (j+1));\n\n          for (F77_INT i = 0; i < nvr; i++)\n            {\n              float real_part = vr.elem (i, j);\n              float imag_part = vr.elem (i, j+1);\n              m_v.elem (i, j) = FloatComplex (real_part, imag_part);\n              m_v.elem (i, j+1) = FloatComplex (real_part, -imag_part);\n            }\n          for (F77_INT i = 0; i < nvl; i++)\n            {\n              float real_part = vl.elem (i, j);\n              float imag_part = vl.elem (i, j+1);\n              m_w.elem (i, j) = FloatComplex (real_part, imag_part);\n              m_w.elem (i, j+1) = FloatComplex (real_part, -imag_part);\n            }\n          j++;\n        }\n    }\n\n  return info;\n}\n\noctave_idx_type\nFloatEIG::symmetric_init (const FloatMatrix& a, const FloatMatrix& b,\n                          bool calc_rev, bool calc_lev)\n{\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT nb = octave::to_f77_int (b.rows ());\n\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (n != a_nc || nb != b_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  if (n != nb)\n    (*current_liboctave_error_handler) (\"EIG requires same size matrices\");\n\n  F77_INT info = 0;\n\n  FloatMatrix atmp = a;\n  float *atmp_data = atmp.rwdata ();\n\n  FloatMatrix btmp = b;\n  float *btmp_data = btmp.rwdata ();\n\n  FloatColumnVector wr (n);\n  float *pwr = wr.rwdata ();\n\n  F77_INT lwork = -1;\n  float dummy_work;\n\n  F77_XFCN (ssygv, SSYGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, atmp_data, n,\n                           btmp_data, n,\n                           pwr, &dummy_work, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"ssygv workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work);\n  Array<float> work (dim_vector (lwork, 1));\n  float *pwork = work.rwdata ();\n\n  F77_XFCN (ssygv, SSYGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, atmp_data, n,\n                           btmp_data, n,\n                           pwr, pwork, lwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in ssygv\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"ssygv failed to converge\");\n\n  m_lambda = FloatComplexColumnVector (wr);\n  m_v = (calc_rev ? FloatComplexMatrix (atmp) : FloatComplexMatrix ());\n  m_w = (calc_lev ? FloatComplexMatrix (atmp) : FloatComplexMatrix ());\n\n  return info;\n}\n\noctave_idx_type\nFloatEIG::init (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n                bool calc_rev, bool calc_lev, bool force_qz)\n{\n  if (a.any_element_is_inf_or_nan () || b.any_element_is_inf_or_nan ())\n    (*current_liboctave_error_handler)\n      (\"EIG: matrix contains Inf or NaN values\");\n\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT nb = octave::to_f77_int (b.rows ());\n\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (n != a_nc || nb != b_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  if (n != nb)\n    (*current_liboctave_error_handler) (\"EIG requires same size matrices\");\n\n  F77_INT info = 0;\n\n  FloatComplexMatrix tmp = b;\n  FloatComplex *tmp_data = tmp.rwdata ();\n\n  if (! force_qz)\n    {\n      F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (\"L\", 1),\n                                 n, F77_CMPLX_ARG (tmp_data), n,\n                                 info\n                                 F77_CHAR_ARG_LEN (1)));\n\n      if (a.ishermitian () && b.ishermitian () && info == 0)\n        return hermitian_init (a, b, calc_rev, calc_lev);\n    }\n\n  FloatComplexMatrix atmp = a;\n  FloatComplex *atmp_data = atmp.rwdata ();\n\n  FloatComplexMatrix btmp = b;\n  FloatComplex *btmp_data = btmp.rwdata ();\n\n  FloatComplexColumnVector alpha (n);\n  FloatComplex *palpha = alpha.rwdata ();\n\n  FloatComplexColumnVector beta (n);\n  FloatComplex *pbeta = beta.rwdata ();\n\n  F77_INT nvr = (calc_rev ? n : 0);\n  FloatComplexMatrix vrtmp (nvr, nvr);\n  FloatComplex *pvr = vrtmp.rwdata ();\n\n  F77_INT nvl = (calc_lev ? n : 0);\n  FloatComplexMatrix vltmp (nvl, nvl);\n  FloatComplex *pvl = vltmp.rwdata ();\n\n  F77_INT lwork = -1;\n  FloatComplex dummy_work;\n\n  F77_INT lrwork = 8*n;\n  Array<float> rwork (dim_vector (lrwork, 1));\n  float *prwork = rwork.rwdata ();\n\n  F77_XFCN (cggev, CGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           n, F77_CMPLX_ARG (atmp_data), n,\n                           F77_CMPLX_ARG (btmp_data), n,\n                           F77_CMPLX_ARG (palpha), F77_CMPLX_ARG (pbeta),\n                           F77_CMPLX_ARG (pvl), n, F77_CMPLX_ARG (pvr), n,\n                           F77_CMPLX_ARG (&dummy_work), lwork, prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"cggev workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work.real ());\n  Array<FloatComplex> work (dim_vector (lwork, 1));\n  FloatComplex *pwork = work.rwdata ();\n\n  F77_XFCN (cggev, CGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           n, F77_CMPLX_ARG (atmp_data), n,\n                           F77_CMPLX_ARG (btmp_data), n,\n                           F77_CMPLX_ARG (palpha), F77_CMPLX_ARG (pbeta),\n                           F77_CMPLX_ARG (pvl), n, F77_CMPLX_ARG (pvr), n,\n                           F77_CMPLX_ARG (pwork), lwork, prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in cggev\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"cggev failed to converge\");\n\n  m_lambda.resize (n);\n\n  for (F77_INT j = 0; j < n; j++)\n    m_lambda.elem (j) = alpha.elem (j) / beta.elem (j);\n\n  m_v = vrtmp;\n  m_w = vltmp;\n\n  return info;\n}\n\noctave_idx_type\nFloatEIG::hermitian_init (const FloatComplexMatrix& a,\n                          const FloatComplexMatrix& b,\n                          bool calc_rev, bool calc_lev)\n{\n  F77_INT n = octave::to_f77_int (a.rows ());\n  F77_INT nb = octave::to_f77_int (b.rows ());\n\n  F77_INT a_nc = octave::to_f77_int (a.cols ());\n  F77_INT b_nc = octave::to_f77_int (b.cols ());\n\n  if (n != a_nc || nb != b_nc)\n    (*current_liboctave_error_handler) (\"EIG requires square matrix\");\n\n  if (n != nb)\n    (*current_liboctave_error_handler) (\"EIG requires same size matrices\");\n\n  F77_INT info = 0;\n\n  FloatComplexMatrix atmp = a;\n  FloatComplex *atmp_data = atmp.rwdata ();\n\n  FloatComplexMatrix btmp = b;\n  FloatComplex *btmp_data = btmp.rwdata ();\n\n  FloatColumnVector wr (n);\n  float *pwr = wr.rwdata ();\n\n  F77_INT lwork = -1;\n  FloatComplex dummy_work;\n\n  F77_INT lrwork = 3*n;\n  Array<float> rwork (dim_vector (lrwork, 1));\n  float *prwork = rwork.rwdata ();\n\n  F77_XFCN (chegv, CHEGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, F77_CMPLX_ARG (atmp_data), n,\n                           F77_CMPLX_ARG (btmp_data), n,\n                           pwr, F77_CMPLX_ARG (&dummy_work), lwork,\n                           prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info != 0)\n    (*current_liboctave_error_handler) (\"zhegv workspace query failed\");\n\n  lwork = static_cast<F77_INT> (dummy_work.real ());\n  Array<FloatComplex> work (dim_vector (lwork, 1));\n  FloatComplex *pwork = work.rwdata ();\n\n  F77_XFCN (chegv, CHEGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? \"V\" : \"N\", 1),\n                           F77_CONST_CHAR_ARG2 (\"U\", 1),\n                           n, F77_CMPLX_ARG (atmp_data), n,\n                           F77_CMPLX_ARG (btmp_data), n,\n                           pwr, F77_CMPLX_ARG (pwork), lwork, prwork, info\n                           F77_CHAR_ARG_LEN (1)\n                           F77_CHAR_ARG_LEN (1)));\n\n  if (info < 0)\n    (*current_liboctave_error_handler) (\"unrecoverable error in zhegv\");\n\n  if (info > 0)\n    (*current_liboctave_error_handler) (\"zhegv failed to converge\");\n\n  m_lambda = FloatComplexColumnVector (wr);\n  m_v = (calc_rev ? FloatComplexMatrix (atmp) : FloatComplexMatrix ());\n  m_w = (calc_lev ? FloatComplexMatrix (atmp) : FloatComplexMatrix ());\n\n  return info;\n}\n"
  },
  {
    "path": "liboctave/numeric/fEIG.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fEIG_h)\n#define octave_fEIG_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\n#include \"mx-fwd.h\"\n\n#include \"fCColVector.h\"\n#include \"fCMatrix.h\"\n\nclass OCTAVE_API FloatEIG\n{\n  friend class FloatMatrix;\n  friend class FloatComplexMatrix;\n\npublic:\n\n  FloatEIG () : m_lambda (), m_v (), m_w () { }\n\n  FloatEIG (const FloatMatrix& a, bool calc_rev = true,\n            bool calc_lev = true, bool balance = true)\n    : m_lambda (), m_v (), m_w ()\n  {\n    init (a, calc_rev, calc_lev, balance);\n  }\n\n  FloatEIG (const FloatMatrix& a, octave_idx_type& info,\n            bool calc_rev = true, bool calc_lev = true, bool balance = true)\n    : m_lambda (), m_v (), m_w ()\n  {\n    info = init (a, calc_rev, calc_lev, balance);\n  }\n\n  FloatEIG (const FloatMatrix& a, const FloatMatrix& b,\n            bool calc_rev = true, bool calc_lev = true, bool force_qz = false)\n    : m_lambda (), m_v (), m_w ()\n  {\n    init (a, b, calc_rev, calc_lev, force_qz);\n  }\n\n  FloatEIG (const FloatMatrix& a, const FloatMatrix& b, octave_idx_type& info,\n            bool calc_rev = true, bool calc_lev = true, bool force_qz = false)\n    : m_lambda (), m_v (), m_w ()\n  {\n    info = init (a, b, calc_rev, calc_lev, force_qz);\n  }\n\n  FloatEIG (const FloatComplexMatrix& a, bool calc_rev = true,\n            bool calc_lev = true, bool balance = true)\n    : m_lambda (), m_v (), m_w ()\n  {\n    init (a, calc_rev, calc_lev, balance);\n  }\n\n  FloatEIG (const FloatComplexMatrix& a, octave_idx_type& info,\n            bool calc_rev = true, bool calc_lev = true, bool balance = true)\n    : m_lambda (), m_v (), m_w ()\n  {\n    info = init (a, calc_rev, calc_lev, balance);\n  }\n\n  FloatEIG (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n            bool calc_rev = true, bool calc_lev = true, bool force_qz = false)\n    : m_lambda (), m_v (), m_w ()\n  {\n    init (a, b, calc_rev, calc_lev, force_qz);\n  }\n\n  FloatEIG (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n            octave_idx_type& info, bool calc_rev = true, bool calc_lev = true,\n            bool force_qz = false)\n    : m_lambda (), m_v (), m_w ()\n  {\n    info = init (a, b, calc_rev, calc_lev, force_qz);\n  }\n\n  FloatEIG (const FloatEIG& a) : m_lambda (a.m_lambda), m_v (a.m_v), m_w (a.m_w) { }\n\n  FloatEIG& operator = (const FloatEIG& a)\n  {\n    if (this != &a)\n      {\n        m_lambda = a.m_lambda;\n        m_v = a.m_v;\n        m_w = a.m_w;\n      }\n    return *this;\n  }\n\n  ~FloatEIG () = default;\n\n  FloatComplexColumnVector eigenvalues () const { return m_lambda; }\n  FloatComplexMatrix right_eigenvectors () const { return m_v; }\n  FloatComplexMatrix left_eigenvectors () const { return m_w; }\n\n  friend std::ostream&  operator << (std::ostream& os, const FloatEIG& a);\n\nprivate:\n\n  FloatComplexColumnVector m_lambda;\n  FloatComplexMatrix m_v;\n  FloatComplexMatrix m_w;\n\n  octave_idx_type init (const FloatMatrix& a, bool calc_rev, bool calc_lev,\n                        bool balance);\n\n  octave_idx_type init (const FloatMatrix& a, const FloatMatrix& b,\n                        bool calc_rev, bool calc_lev, bool force_qz);\n\n  octave_idx_type init (const FloatComplexMatrix& a, bool calc_rev,\n                        bool calc_lev, bool balance);\n\n  octave_idx_type init (const FloatComplexMatrix& a,\n                        const FloatComplexMatrix& b,\n                        bool calc_rev, bool calc_lev, bool force_qz);\n\n  octave_idx_type symmetric_init (const FloatMatrix& a, bool calc_rev,\n                                  bool calc_lev);\n\n  octave_idx_type symmetric_init (const FloatMatrix& a, const FloatMatrix& b,\n                                  bool calc_rev, bool calc_lev);\n\n  octave_idx_type hermitian_init (const FloatComplexMatrix& a,\n                                  bool calc_rev, bool calc_lev);\n\n  octave_idx_type hermitian_init (const FloatComplexMatrix& a,\n                                  const FloatComplexMatrix& b,\n                                  bool calc_rev, bool calc_lev);\n\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/gepbalance.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"CMatrix.h\"\n#include \"dMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"fMatrix.h\"\n#include \"gepbalance.h\"\n#include \"lapack-proto.h\"\n#include \"lo-array-errwarn.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"quit.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <>\nOCTAVE_API octave_idx_type\ngepbalance<Matrix>::init (const Matrix& a, const Matrix& b,\n                          const std::string& balance_job)\n{\n  F77_INT n = to_f77_int (a.cols ());\n\n  if (a.rows () != n)\n    (*current_liboctave_error_handler)\n      (\"GEPBALANCE requires square matrix\");\n\n  if (a.dims () != b.dims ())\n    err_nonconformant (\"GEPBALANCE\", n, n, b.rows(), b.cols());\n\n  F77_INT info;\n  F77_INT ilo;\n  F77_INT ihi;\n\n  OCTAVE_LOCAL_BUFFER (double, plscale, n);\n  OCTAVE_LOCAL_BUFFER (double, prscale, n);\n  OCTAVE_LOCAL_BUFFER (double, pwork, 6 * n);\n\n  m_balanced_mat = a;\n  double *p_balanced_mat = m_balanced_mat.rwdata ();\n  m_balanced_mat2 = b;\n  double *p_balanced_mat2 = m_balanced_mat2.rwdata ();\n\n  char job = balance_job[0];\n\n  F77_XFCN (dggbal, DGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             n, p_balanced_mat, n, p_balanced_mat2,\n                             n, ilo, ihi, plscale, prscale, pwork, info\n                             F77_CHAR_ARG_LEN  (1)));\n\n  m_balancing_mat = Matrix (n, n, 0.0);\n  m_balancing_mat2 = Matrix (n, n, 0.0);\n  for (F77_INT i = 0; i < n; i++)\n    {\n      octave_quit ();\n      m_balancing_mat.elem (i, i) = 1.0;\n      m_balancing_mat2.elem (i, i) = 1.0;\n    }\n\n  double *p_balancing_mat = m_balancing_mat.rwdata ();\n  double *p_balancing_mat2 = m_balancing_mat2.rwdata ();\n\n  // first left\n  F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (\"L\", 1),\n                             n, ilo, ihi, plscale, prscale,\n                             n, p_balancing_mat, n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // then right\n  F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (\"R\", 1),\n                             n, ilo, ihi, plscale, prscale,\n                             n, p_balancing_mat2, n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\ngepbalance<FloatMatrix>::init (const FloatMatrix& a, const FloatMatrix& b,\n                               const std::string& balance_job)\n{\n  F77_INT n = to_f77_int (a.cols ());\n\n  if (a.rows () != n)\n    (*current_liboctave_error_handler)\n      (\"FloatGEPBALANCE requires square matrix\");\n\n  if (a.dims () != b.dims ())\n    err_nonconformant (\"FloatGEPBALANCE\",\n                       n, n, b.rows(), b.cols());\n\n  F77_INT info;\n  F77_INT ilo;\n  F77_INT ihi;\n\n  OCTAVE_LOCAL_BUFFER (float, plscale, n);\n  OCTAVE_LOCAL_BUFFER (float, prscale, n);\n  OCTAVE_LOCAL_BUFFER (float, pwork, 6 * n);\n\n  m_balanced_mat = a;\n  float *p_balanced_mat = m_balanced_mat.rwdata ();\n  m_balanced_mat2 = b;\n  float *p_balanced_mat2 = m_balanced_mat2.rwdata ();\n\n  char job = balance_job[0];\n\n  F77_XFCN (sggbal, SGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             n, p_balanced_mat, n, p_balanced_mat2,\n                             n, ilo, ihi, plscale, prscale, pwork, info\n                             F77_CHAR_ARG_LEN  (1)));\n\n  m_balancing_mat = FloatMatrix (n, n, 0.0);\n  m_balancing_mat2 = FloatMatrix (n, n, 0.0);\n  for (F77_INT i = 0; i < n; i++)\n    {\n      octave_quit ();\n      m_balancing_mat.elem (i, i) = 1.0;\n      m_balancing_mat2.elem (i, i) = 1.0;\n    }\n\n  float *p_balancing_mat = m_balancing_mat.rwdata ();\n  float *p_balancing_mat2 = m_balancing_mat2.rwdata ();\n\n  // first left\n  F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (\"L\", 1),\n                             n, ilo, ihi, plscale, prscale,\n                             n, p_balancing_mat, n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // then right\n  F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (\"R\", 1),\n                             n, ilo, ihi, plscale, prscale,\n                             n, p_balancing_mat2, n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\ngepbalance<ComplexMatrix>::init (const ComplexMatrix& a,\n                                 const ComplexMatrix& b,\n                                 const std::string& balance_job)\n{\n  F77_INT n = to_f77_int (a.cols ());\n\n  if (a.rows () != n)\n    (*current_liboctave_error_handler)\n      (\"ComplexGEPBALANCE requires square matrix\");\n\n  if (a.dims () != b.dims ())\n    err_nonconformant (\"ComplexGEPBALANCE\",\n                       n, n, b.rows(), b.cols());\n\n  F77_INT info;\n  F77_INT ilo;\n  F77_INT ihi;\n\n  OCTAVE_LOCAL_BUFFER (double, plscale, n);\n  OCTAVE_LOCAL_BUFFER (double, prscale, n);\n  OCTAVE_LOCAL_BUFFER (double, pwork, 6 * n);\n\n  m_balanced_mat = a;\n  Complex *p_balanced_mat = m_balanced_mat.rwdata ();\n  m_balanced_mat2 = b;\n  Complex *p_balanced_mat2 = m_balanced_mat2.rwdata ();\n\n  char job = balance_job[0];\n\n  F77_XFCN (zggbal, ZGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             n, F77_DBLE_CMPLX_ARG (p_balanced_mat),\n                             n, F77_DBLE_CMPLX_ARG (p_balanced_mat2),\n                             n, ilo, ihi, plscale, prscale, pwork, info\n                             F77_CHAR_ARG_LEN (1)));\n\n  m_balancing_mat = Matrix (n, n, 0.0);\n  m_balancing_mat2 = Matrix (n, n, 0.0);\n  for (F77_INT i = 0; i < n; i++)\n    {\n      octave_quit ();\n      m_balancing_mat.elem (i, i) = 1.0;\n      m_balancing_mat2.elem (i, i) = 1.0;\n    }\n\n  double *p_balancing_mat = m_balancing_mat.rwdata ();\n  double *p_balancing_mat2 = m_balancing_mat2.rwdata ();\n\n  // first left\n  F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (\"L\", 1),\n                             n, ilo, ihi, plscale, prscale,\n                             n, p_balancing_mat, n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // then right\n  F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (\"R\", 1),\n                             n, ilo, ihi, plscale, prscale,\n                             n, p_balancing_mat2, n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\ngepbalance<FloatComplexMatrix>::init (const FloatComplexMatrix& a,\n                                      const FloatComplexMatrix& b,\n                                      const std::string& balance_job)\n{\n  F77_INT n = to_f77_int (a.cols ());\n\n  if (a.rows () != n)\n    {\n      (*current_liboctave_error_handler)\n        (\"FloatComplexGEPBALANCE requires square matrix\");\n      return -1;\n    }\n\n  if (a.dims () != b.dims ())\n    err_nonconformant (\"FloatComplexGEPBALANCE\",\n                       n, n, b.rows(), b.cols());\n\n  F77_INT info;\n  F77_INT ilo;\n  F77_INT ihi;\n\n  OCTAVE_LOCAL_BUFFER (float, plscale, n);\n  OCTAVE_LOCAL_BUFFER (float, prscale, n);\n  OCTAVE_LOCAL_BUFFER (float, pwork, 6 * n);\n\n  m_balanced_mat = a;\n  FloatComplex *p_balanced_mat = m_balanced_mat.rwdata ();\n  m_balanced_mat2 = b;\n  FloatComplex *p_balanced_mat2 = m_balanced_mat2.rwdata ();\n\n  char job = balance_job[0];\n\n  F77_XFCN (cggbal, CGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             n, F77_CMPLX_ARG (p_balanced_mat),\n                             n, F77_CMPLX_ARG (p_balanced_mat2),\n                             n, ilo, ihi, plscale, prscale, pwork, info\n                             F77_CHAR_ARG_LEN (1)));\n\n  m_balancing_mat = FloatMatrix (n, n, 0.0);\n  m_balancing_mat2 = FloatMatrix (n, n, 0.0);\n  for (F77_INT i = 0; i < n; i++)\n    {\n      octave_quit ();\n      m_balancing_mat.elem (i, i) = 1.0;\n      m_balancing_mat2.elem (i, i) = 1.0;\n    }\n\n  float *p_balancing_mat = m_balancing_mat.rwdata ();\n  float *p_balancing_mat2 = m_balancing_mat2.rwdata ();\n\n  // first left\n  F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (\"L\", 1),\n                             n, ilo, ihi, plscale, prscale,\n                             n, p_balancing_mat, n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // then right\n  F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (\"R\", 1),\n                             n, ilo, ihi, plscale, prscale,\n                             n, p_balancing_mat2, n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  return info;\n}\n\n// Instantiations we need.\n\ntemplate class gepbalance<Matrix>;\n\ntemplate class gepbalance<FloatMatrix>;\n\ntemplate class gepbalance<ComplexMatrix>;\n\ntemplate class gepbalance<FloatComplexMatrix>;\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/gepbalance.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gepbalance_h)\n#define octave_gepbalance_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nclass gepbalance\n{\npublic:\n\n  typedef typename T::real_matrix_type RT;\n\n  gepbalance ()\n    : m_balanced_mat (), m_balanced_mat2 (), m_balancing_mat (),\n      m_balancing_mat2 ()\n  { }\n\n  gepbalance (const T& a, const T& b, const std::string& job)\n    : m_balanced_mat (), m_balanced_mat2 (), m_balancing_mat (),\n      m_balancing_mat2 ()\n  {\n    init (a, b, job);\n  }\n\n  gepbalance (const gepbalance& a)\n    : m_balanced_mat (a.m_balanced_mat),\n      m_balanced_mat2 (a.m_balanced_mat2),\n      m_balancing_mat (a.m_balancing_mat),\n      m_balancing_mat2 (a.m_balancing_mat2)\n  { }\n\n  gepbalance& operator = (const gepbalance& a)\n  {\n    if (this != &a)\n      {\n        m_balanced_mat = a.m_balanced_mat;\n        m_balanced_mat2 = a.m_balanced_mat2;\n        m_balancing_mat = a.m_balancing_mat;\n        m_balancing_mat2 = a.m_balancing_mat2;\n      }\n\n    return *this;\n  }\n\n  ~gepbalance () = default;\n\n  T balanced_matrix () const { return m_balanced_mat; }\n\n  T balanced_matrix2 () const { return m_balanced_mat2; }\n\n  RT balancing_matrix () const { return m_balancing_mat; }\n\n  RT balancing_matrix2 () const { return m_balancing_mat2; }\n\nprivate:\n\n  T m_balanced_mat;\n  T m_balanced_mat2;\n  RT m_balancing_mat;\n  RT m_balancing_mat2;\n\n  OCTAVE_API octave_idx_type\n  init (const T& a, const T& b, const std::string& job);\n};\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/gsvd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1997-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <unordered_map>\n\n#include \"CMatrix.h\"\n#include \"dDiagMatrix.h\"\n#include \"dMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"fDiagMatrix.h\"\n#include \"fMatrix.h\"\n#include \"gsvd.h\"\n#include \"lapack-proto.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-shlib.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic std::unordered_map<std::string, void *> gsvd_fcn;\n\nstatic bool have_DGGSVD3 = false;\nstatic bool gsvd_initialized = false;\n\n/* Hack to stringize results of F77_FUNC macro. */\n#define xSTRINGIZE(x) #x\n#define STRINGIZE(x) xSTRINGIZE(x)\n\nstatic void\ninitialize_gsvd ()\n{\n  if (gsvd_initialized)\n    return;\n\n  dynamic_library libs (\"\");\n  if (! libs)\n    (*current_liboctave_error_handler)\n      (\"gsvd: unable to query LAPACK library\");\n\n  have_DGGSVD3 = (libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3)))\n                  != nullptr);\n\n  if (have_DGGSVD3)\n    {\n      gsvd_fcn[\"dg\"] = libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3)));\n      gsvd_fcn[\"sg\"] = libs.search (STRINGIZE (F77_FUNC (sggsvd3, SGGSVD3)));\n      gsvd_fcn[\"zg\"] = libs.search (STRINGIZE (F77_FUNC (zggsvd3, ZGGSVD3)));\n      gsvd_fcn[\"cg\"] = libs.search (STRINGIZE (F77_FUNC (cggsvd3, CGGSVD3)));\n    }\n  else\n    {\n      gsvd_fcn[\"dg\"] = libs.search (STRINGIZE (F77_FUNC (dggsvd, DGGSVD)));\n      gsvd_fcn[\"sg\"] = libs.search (STRINGIZE (F77_FUNC (sggsvd, SGGSVD)));\n      gsvd_fcn[\"zg\"] = libs.search (STRINGIZE (F77_FUNC (zggsvd, ZGGSVD)));\n      gsvd_fcn[\"cg\"] = libs.search (STRINGIZE (F77_FUNC (cggsvd, CGGSVD)));\n    }\n\n  gsvd_initialized = true;\n}\n\n/* Clean up macro namespace as soon as we are done using them */\n#undef xSTRINGIZE\n#undef STRINGIZE\n\ntemplate<class T1>\nstruct real_ggsvd_ptr\n{\n  typedef F77_RET_T (*type)\n    (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   T1 *,                      // A(LDA,N)\n   const F77_INT&,            // LDA\n   T1 *,                      // B(LDB,N)\n   const F77_INT&,            // LDB\n   T1 *,                      // ALPHA(N)\n   T1 *,                      // BETA(N)\n   T1 *,                      // U(LDU,M)\n   const F77_INT&,            // LDU\n   T1 *,                      // V(LDV,P)\n   const F77_INT&,            // LDV\n   T1 *,                      // Q(LDQ,N)\n   const F77_INT&,            // LDQ\n   T1 *,                      // WORK\n   F77_INT *,                 // IWORK(N)\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n};\n\ntemplate<class T1>\nstruct real_ggsvd3_ptr\n{\n  typedef F77_RET_T (*type)\n    (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   T1 *,                      // A(LDA,N)\n   const F77_INT&,            // LDA\n   T1 *,                      // B(LDB,N)\n   const F77_INT&,            // LDB\n   T1 *,                      // ALPHA(N)\n   T1 *,                      // BETA(N)\n   T1 *,                      // U(LDU,M)\n   const F77_INT&,            // LDU\n   T1 *,                      // V(LDV,P)\n   const F77_INT&,            // LDV\n   T1 *,                      // Q(LDQ,N)\n   const F77_INT&,            // LDQ\n   T1 *,                      // WORK\n   const F77_INT&,            // LWORK\n   F77_INT *,                 // IWORK(N)\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n};\n\ntemplate<class T1, class T2>\nstruct comp_ggsvd_ptr\n{\n  typedef F77_RET_T (*type)\n    (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   T1 *,                      // A(LDA,N)\n   const F77_INT&,            // LDA\n   T1 *,                      // B(LDB,N)\n   const F77_INT&,            // LDB\n   T2 *,                      // ALPHA(N)\n   T2 *,                      // BETA(N)\n   T1 *,                      // U(LDU,M)\n   const F77_INT&,            // LDU\n   T1 *,                      // V(LDV,P)\n   const F77_INT&,            // LDV\n   T1 *,                      // Q(LDQ,N)\n   const F77_INT&,            // LDQ\n   T1 *,                      // WORK\n   T2 *,                      // RWORK\n   F77_INT *,                 // IWORK(N)\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n};\n\ntemplate<class T1, class T2>\nstruct comp_ggsvd3_ptr\n{\n  typedef F77_RET_T (*type)\n    (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   T1 *,                      // A(LDA,N)\n   const F77_INT&,            // LDA\n   T1 *,                      // B(LDB,N)\n   const F77_INT&,            // LDB\n   T2 *,                      // ALPHA(N)\n   T2 *,                      // BETA(N)\n   T1 *,                      // U(LDU,M)\n   const F77_INT&,            // LDU\n   T1 *,                      // V(LDV,P)\n   const F77_INT&,            // LDV\n   T1 *,                      // Q(LDQ,N)\n   const F77_INT&,            // LDQ\n   T1 *,                      // WORK\n   const F77_INT&,            // LWORK\n   T2 *,                      // RWORK\n   F77_INT *,                 // IWORK(N)\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n};\n\n// template specializations\ntypedef real_ggsvd_ptr<F77_DBLE>::type dggsvd_type;\ntypedef real_ggsvd3_ptr<F77_DBLE>::type dggsvd3_type;\ntypedef real_ggsvd_ptr<F77_REAL>::type sggsvd_type;\ntypedef real_ggsvd3_ptr<F77_REAL>::type sggsvd3_type;\ntypedef comp_ggsvd_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd_type;\ntypedef comp_ggsvd3_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd3_type;\ntypedef comp_ggsvd_ptr<F77_CMPLX, F77_REAL>::type cggsvd_type;\ntypedef comp_ggsvd3_ptr<F77_CMPLX, F77_REAL>::type cggsvd3_type;\n\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <>\nvoid\ngsvd<Matrix>::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m,\n                     F77_INT n, F77_INT p, F77_INT& k, F77_INT& l,\n                     double *tmp_dataA, F77_INT m1, double *tmp_dataB,\n                     F77_INT p1, Matrix& alpha, Matrix& beta, double *u,\n                     F77_INT nrow_u, double *v, F77_INT nrow_v, double *q,\n                     F77_INT nrow_q, double *work, F77_INT lwork,\n                     F77_INT *iwork, F77_INT& info)\n{\n  if (! gsvd_initialized)\n    initialize_gsvd ();\n\n  if (have_DGGSVD3)\n    {\n      dggsvd3_type f_ptr = reinterpret_cast<dggsvd3_type> (gsvd_fcn[\"dg\"]);\n      f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),\n             F77_CONST_CHAR_ARG2 (&jobv, 1),\n             F77_CONST_CHAR_ARG2 (&jobq, 1),\n             m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,\n             alpha.rwdata (), beta.rwdata (),\n             u, nrow_u, v, nrow_v, q, nrow_q,\n             work, lwork, iwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1));\n    }\n  else\n    {\n      dggsvd_type f_ptr = reinterpret_cast<dggsvd_type> (gsvd_fcn[\"dg\"]);\n      f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),\n             F77_CONST_CHAR_ARG2 (&jobv, 1),\n             F77_CONST_CHAR_ARG2 (&jobq, 1),\n             m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,\n             alpha.rwdata (), beta.rwdata (),\n             u, nrow_u, v, nrow_v, q, nrow_q,\n             work, iwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1));\n    }\n}\n\ntemplate <>\nvoid\ngsvd<FloatMatrix>::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m,\n                          F77_INT n, F77_INT p, F77_INT& k, F77_INT& l,\n                          float *tmp_dataA, F77_INT m1, float *tmp_dataB,\n                          F77_INT p1, FloatMatrix& alpha,\n                          FloatMatrix& beta, float *u, F77_INT nrow_u,\n                          float *v, F77_INT nrow_v, float *q,\n                          F77_INT nrow_q, float *work,\n                          F77_INT lwork, F77_INT *iwork, F77_INT& info)\n{\n  if (! gsvd_initialized)\n    initialize_gsvd ();\n\n  if (have_DGGSVD3)\n    {\n      sggsvd3_type f_ptr = reinterpret_cast<sggsvd3_type> (gsvd_fcn[\"sg\"]);\n      f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),\n             F77_CONST_CHAR_ARG2 (&jobv, 1),\n             F77_CONST_CHAR_ARG2 (&jobq, 1),\n             m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,\n             alpha.rwdata (), beta.rwdata (),\n             u, nrow_u, v, nrow_v, q, nrow_q,\n             work, lwork, iwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1));\n    }\n  else\n    {\n      sggsvd_type f_ptr = reinterpret_cast<sggsvd_type> (gsvd_fcn[\"sg\"]);\n      f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),\n             F77_CONST_CHAR_ARG2 (&jobv, 1),\n             F77_CONST_CHAR_ARG2 (&jobq, 1),\n             m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,\n             alpha.rwdata (), beta.rwdata (),\n             u, nrow_u, v, nrow_v, q, nrow_q,\n             work, iwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1));\n    }\n}\n\ntemplate <>\nvoid\ngsvd<ComplexMatrix>::ggsvd (char& jobu, char& jobv, char& jobq,\n                            F77_INT m, F77_INT n, F77_INT p, F77_INT& k,\n                            F77_INT& l, Complex *tmp_dataA, F77_INT m1,\n                            Complex *tmp_dataB, F77_INT p1, Matrix& alpha,\n                            Matrix& beta, Complex *u, F77_INT nrow_u,\n                            Complex *v, F77_INT nrow_v, Complex *q,\n                            F77_INT nrow_q, Complex *work,\n                            F77_INT lwork, F77_INT *iwork, F77_INT& info)\n{\n  if (! gsvd_initialized)\n    initialize_gsvd ();\n\n  OCTAVE_LOCAL_BUFFER(double, rwork, 2*n);\n\n  if (have_DGGSVD3)\n    {\n      zggsvd3_type f_ptr = reinterpret_cast<zggsvd3_type> (gsvd_fcn[\"zg\"]);\n      f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),\n             F77_CONST_CHAR_ARG2 (&jobv, 1),\n             F77_CONST_CHAR_ARG2 (&jobq, 1),\n             m, n, p, k, l,\n             F77_DBLE_CMPLX_ARG (tmp_dataA), m1,\n             F77_DBLE_CMPLX_ARG (tmp_dataB), p1,\n             alpha.rwdata (), beta.rwdata (),\n             F77_DBLE_CMPLX_ARG (u), nrow_u,\n             F77_DBLE_CMPLX_ARG (v), nrow_v,\n             F77_DBLE_CMPLX_ARG (q), nrow_q,\n             F77_DBLE_CMPLX_ARG (work),\n             lwork, rwork, iwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1));\n    }\n  else\n    {\n      zggsvd_type f_ptr = reinterpret_cast<zggsvd_type> (gsvd_fcn[\"zg\"]);\n      f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),\n             F77_CONST_CHAR_ARG2 (&jobv, 1),\n             F77_CONST_CHAR_ARG2 (&jobq, 1),\n             m, n, p, k, l,\n             F77_DBLE_CMPLX_ARG (tmp_dataA), m1,\n             F77_DBLE_CMPLX_ARG (tmp_dataB), p1,\n             alpha.rwdata (), beta.rwdata (),\n             F77_DBLE_CMPLX_ARG (u), nrow_u,\n             F77_DBLE_CMPLX_ARG (v), nrow_v,\n             F77_DBLE_CMPLX_ARG (q), nrow_q,\n             F77_DBLE_CMPLX_ARG (work),\n             rwork, iwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1));\n    }\n}\n\ntemplate <>\nvoid\ngsvd<FloatComplexMatrix>::ggsvd (char& jobu, char& jobv, char& jobq,\n                                 F77_INT m, F77_INT n, F77_INT p,\n                                 F77_INT& k, F77_INT& l,\n                                 FloatComplex *tmp_dataA, F77_INT m1,\n                                 FloatComplex *tmp_dataB, F77_INT p1,\n                                 FloatMatrix& alpha, FloatMatrix& beta,\n                                 FloatComplex *u, F77_INT nrow_u,\n                                 FloatComplex *v, F77_INT nrow_v,\n                                 FloatComplex *q, F77_INT nrow_q,\n                                 FloatComplex *work, F77_INT lwork,\n                                 F77_INT *iwork, F77_INT& info)\n{\n  if (! gsvd_initialized)\n    initialize_gsvd ();\n\n  OCTAVE_LOCAL_BUFFER(float, rwork, 2*n);\n\n  if (have_DGGSVD3)\n    {\n      cggsvd3_type f_ptr = reinterpret_cast<cggsvd3_type> (gsvd_fcn[\"cg\"]);\n      f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),\n             F77_CONST_CHAR_ARG2 (&jobv, 1),\n             F77_CONST_CHAR_ARG2 (&jobq, 1),\n             m, n, p, k, l,\n             F77_CMPLX_ARG (tmp_dataA), m1,\n             F77_CMPLX_ARG (tmp_dataB), p1,\n             alpha.rwdata (), beta.rwdata (),\n             F77_CMPLX_ARG (u), nrow_u,\n             F77_CMPLX_ARG (v), nrow_v,\n             F77_CMPLX_ARG (q), nrow_q,\n             F77_CMPLX_ARG (work), lwork,\n             rwork, iwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1));\n    }\n  else\n    {\n      cggsvd_type f_ptr = reinterpret_cast<cggsvd_type> (gsvd_fcn[\"cg\"]);\n      f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),\n             F77_CONST_CHAR_ARG2 (&jobv, 1),\n             F77_CONST_CHAR_ARG2 (&jobq, 1),\n             m, n, p, k, l,\n             F77_CMPLX_ARG (tmp_dataA), m1,\n             F77_CMPLX_ARG (tmp_dataB), p1,\n             alpha.rwdata (), beta.rwdata (),\n             F77_CMPLX_ARG (u), nrow_u,\n             F77_CMPLX_ARG (v), nrow_v,\n             F77_CMPLX_ARG (q), nrow_q,\n             F77_CMPLX_ARG (work),\n             rwork, iwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1));\n    }\n}\n\ntemplate <typename T>\nT\ngsvd<T>::left_singular_matrix_A () const\n{\n  if (m_type == gsvd::Type::sigma_only)\n    (*current_liboctave_error_handler)\n      (\"gsvd: U not computed because type == gsvd::sigma_only\");\n\n  return m_left_smA;\n}\n\ntemplate <typename T>\nT\ngsvd<T>::left_singular_matrix_B () const\n{\n  if (m_type == gsvd::Type::sigma_only)\n    (*current_liboctave_error_handler)\n      (\"gsvd: V not computed because type == gsvd::sigma_only\");\n\n  return m_left_smB;\n}\n\ntemplate <typename T>\nT\ngsvd<T>::right_singular_matrix () const\n{\n  if (m_type == gsvd::Type::sigma_only)\n    (*current_liboctave_error_handler)\n      (\"gsvd: X not computed because type == gsvd::sigma_only\");\n\n  return m_right_sm;\n}\n\ntemplate <typename T>\ngsvd<T>::gsvd (const T& a, const T& b, gsvd::Type gsvd_type)\n{\n  if (a.isempty () || b.isempty ())\n    (*current_liboctave_error_handler)\n      (\"gsvd: A and B cannot be empty matrices\");\n\n  F77_INT info;\n\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n  F77_INT p = to_f77_int (b.rows ());\n\n  T atmp = a;\n  P *tmp_dataA = atmp.rwdata ();\n\n  T btmp = b;\n  P *tmp_dataB = btmp.rwdata ();\n\n  char jobu = 'U';\n  char jobv = 'V';\n  char jobq = 'Q';\n\n  F77_INT nrow_u = m;\n  F77_INT nrow_v = p;\n  F77_INT nrow_q = n;\n\n  F77_INT k, l;\n\n  switch (gsvd_type)\n    {\n    case gsvd<T>::Type::sigma_only:\n\n      // FIXME: In LAPACK 3.0, problem below seems to be fixed,\n      //        so we now set jobX = 'N'.\n      //\n      // For calculating sigma_only, both jobu and jobv should be 'N', but\n      // there seems to be a bug in dgesvd from LAPACK V2.0.  To\n      // demonstrate the bug, set both jobu and jobv to 'N' and find the\n      // singular values of [eye(3), eye(3)].  The result is\n      // [-sqrt(2), -sqrt(2), -sqrt(2)].\n\n      jobu = jobv = jobq = 'N';\n      nrow_u = nrow_v = nrow_q = 1;\n      break;\n\n    default:\n      break;\n    }\n\n  m_type = gsvd_type;\n\n  if (jobu != 'N')\n    m_left_smA.resize (nrow_u, m);\n\n  P *u = m_left_smA.rwdata ();\n\n  if (jobv != 'N')\n    m_left_smB.resize (nrow_v, p);\n\n  P *v = m_left_smB.rwdata ();\n\n  if (jobq != 'N')\n    m_right_sm.resize (nrow_q, n);\n\n  P *q = m_right_sm.rwdata ();\n\n  real_matrix alpha (n, 1);\n  real_matrix beta (n, 1);\n\n  OCTAVE_LOCAL_BUFFER(F77_INT, iwork, n);\n\n  if (! gsvd_initialized)\n    initialize_gsvd ();\n\n  F77_INT lwork;\n  if (have_DGGSVD3)\n    {\n      lwork = -1;\n      P work_tmp;\n\n      gsvd<T>::ggsvd (jobu, jobv, jobq, m, n, p, k, l,\n                      tmp_dataA, m, tmp_dataB, p,\n                      alpha, beta, u, nrow_u, v, nrow_v, q, nrow_q,\n                      &work_tmp, lwork, iwork, info);\n\n      lwork = static_cast<F77_INT> (std::abs (work_tmp));\n    }\n  else\n    {\n      lwork = std::max ({3*n, m, p}) + n;\n    }\n  info = 0;\n\n  OCTAVE_LOCAL_BUFFER(P, work, lwork);\n\n  gsvd<T>::ggsvd (jobu, jobv, jobq, m, n, p, k, l,\n                  tmp_dataA, m, tmp_dataB, p,\n                  alpha, beta, u, nrow_u, v, nrow_v, q, nrow_q,\n                  work, lwork, iwork, info);\n\n  if (info < 0)\n    (*current_liboctave_error_handler)\n      (\"*ggsvd.f: argument %\" OCTAVE_F77_INT_TYPE_FORMAT \" illegal\",\n       -info);\n\n  if (info > 0)\n    (*current_liboctave_error_handler)\n      (\"*ggsvd.f: Jacobi-type procedure failed to converge\");\n\n  F77_INT i, j;\n\n  if (gsvd_type != gsvd<T>::Type::sigma_only)\n    {\n      // Size according to LAPACK is k+l,k+l, but this needs\n      // to be nxn for Matlab compatibility.\n      T R (n, n, 0.0);\n      int astart = n-k-l;\n      if (m - k - l >= 0)\n        {\n          // R is stored in A(1:K+L,N-K-L+1:N)\n          for (i = 0; i < k+l; i++)\n            for (j = 0; j < k+l; j++)\n              R.xelem (i, j) = atmp.xelem (i, astart + j);\n        }\n      else\n        {\n          // (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N)\n          // ( 0  R22 R23 )\n          for (i = 0; i < m; i++)\n            for (j = 0; j < k+l; j++)\n              R.xelem (i, j) = atmp.xelem (i, astart + j);\n          // and R33 is stored in B(M-K+1:L,N+M-K-L+1:N)\n          for (i = m; i < k + l; i++)\n            for (j = n - l - k + m; j < n; j++)\n              R.xelem (i, j) = btmp.xelem (i - k, j);\n        }\n\n      // Output X = Q*R'\n      // FIXME: Is there a way to call BLAS multiply directly\n      //        with flags so that R is transposed?\n      m_right_sm = m_right_sm * R.hermitian ();\n    }\n\n  // Fill in C and S\n  F77_INT rank;\n  bool fill_ptn;\n  if (m-k-l >= 0)\n    {\n      rank = l;\n      fill_ptn = true;\n    }\n  else\n    {\n      rank = m-k;\n      fill_ptn = false;\n    }\n\n  if (gsvd_type == gsvd<T>::Type::sigma_only)\n    {\n      // Return column vector with results\n      m_sigmaA.resize (k+l, 1);\n      m_sigmaB.resize (k+l, 1);\n\n      if (fill_ptn)\n        {\n          for (i = 0; i < k; i++)\n            {\n              m_sigmaA.xelem (i) = 1.0;\n              m_sigmaB.xelem (i) = 0.0;\n            }\n          for (i = k, j = k+l-1; i < k+l; i++, j--)\n            {\n              m_sigmaA.xelem (i) = alpha.xelem (i);\n              m_sigmaB.xelem (i) = beta.xelem (i);\n            }\n        }\n      else\n        {\n          for (i = 0; i < k; i++)\n            {\n              m_sigmaA.xelem (i) = 1.0;\n              m_sigmaB.xelem (i) = 0.0;\n            }\n          for (i = k; i < m; i++)\n            {\n              m_sigmaA.xelem (i) = alpha.xelem (i);\n              m_sigmaB.xelem (i) = beta.xelem (i);\n            }\n          for (i = m; i < k+l; i++)\n            {\n              m_sigmaA.xelem (i) = 0.0;\n              m_sigmaB.xelem (i) = 1.0;\n            }\n        }\n    }\n  else  // returning all matrices\n    {\n      // Number of columns according to LAPACK is k+l, but this needs\n      // to be n for Matlab compatibility.\n      m_sigmaA.resize (m, n);\n      m_sigmaB.resize (p, n);\n\n      for (i = 0; i < k; i++)\n        m_sigmaA.xelem (i, i) = 1.0;\n\n      for (i = 0; i < rank; i++)\n        {\n          m_sigmaA.xelem (k+i, k+i) = alpha.xelem (k+i);\n          m_sigmaB.xelem (i, k+i) = beta.xelem (k+i);\n        }\n\n      if (! fill_ptn)\n        {\n          for (i = m; i < n; i++)\n            m_sigmaB.xelem (i-k, i) = 1.0;\n        }\n\n    }\n}\n\n// Instantiations needed in octave::math namespace.\ntemplate class gsvd<Matrix>;\ntemplate class gsvd<FloatMatrix>;\ntemplate class gsvd<ComplexMatrix>;\ntemplate class gsvd<FloatComplexMatrix>;\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/gsvd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1997-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gsvd_h)\n#define octave_gsvd_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nclass OCTAVE_API gsvd\n{\npublic:\n\n  enum class Type\n  {\n    std,\n    economy,\n    sigma_only\n  };\n\n  gsvd () : m_sigmaA (), m_sigmaB (), m_left_smA (), m_left_smB (), m_right_sm ()\n  { }\n\n  gsvd (const T& a, const T& b,\n        gsvd::Type gsvd_type = gsvd<T>::Type::std);\n\n  gsvd (const gsvd& a)\n    : m_type (a.m_type),\n      m_sigmaA (a.m_sigmaA), m_sigmaB (a.m_sigmaB),\n      m_left_smA (a.m_left_smA), m_left_smB (a.m_left_smB), m_right_sm (a.m_right_sm)\n  { }\n\n  gsvd& operator = (const gsvd& a)\n  {\n    if (this != &a)\n      {\n        m_type = a.m_type;\n        m_sigmaA = a.m_sigmaA;\n        m_sigmaB = a.m_sigmaB;\n        m_left_smA = a.m_left_smA;\n        m_left_smB = a.m_left_smB;\n        m_right_sm = a.m_right_sm;\n      }\n\n    return *this;\n  }\n\n  ~gsvd () = default;\n\n  typename T::real_matrix_type\n  singular_values_A () const { return m_sigmaA; }\n\n  typename T::real_matrix_type\n  singular_values_B () const { return m_sigmaB; }\n\n  T left_singular_matrix_A () const;\n  T left_singular_matrix_B () const;\n\n  T right_singular_matrix () const;\n\nprivate:\n  typedef typename T::value_type P;\n  typedef typename T::real_matrix_type real_matrix;\n\n  void ggsvd (char& jobu, char& jobv, char& jobq, octave_f77_int_type m,\n              octave_f77_int_type n, octave_f77_int_type p,\n              octave_f77_int_type& k, octave_f77_int_type& l,\n              P *tmp_dataA, octave_f77_int_type m1,\n              P *tmp_dataB, octave_f77_int_type p1,\n              real_matrix& alpha, real_matrix& beta,\n              P *u, octave_f77_int_type nrow_u,\n              P *v, octave_f77_int_type nrow_v,\n              P *q, octave_f77_int_type nrow_q,\n              P *work, octave_f77_int_type lwork,\n              octave_f77_int_type *iwork,\n              octave_f77_int_type& info);\n\n  //--------\n\n  gsvd::Type m_type;\n  real_matrix m_sigmaA, m_sigmaB;\n  T m_left_smA, m_left_smB;\n  T m_right_sm;\n};\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/hess.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-oct.h\"\n#include \"CMatrix.h\"\n#include \"dMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"fMatrix.h\"\n#include \"hess.h\"\n#include \"lapack-proto.h\"\n#include \"oct-error.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <>\nOCTAVE_API octave_idx_type\nhess<Matrix>::init (const Matrix& a)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.cols ());\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"hess: requires square matrix\");\n\n  char job = 'N';\n  char side = 'R';\n\n  F77_INT n = a_nc;\n  F77_INT lwork = 32 * n;\n  F77_INT info;\n  F77_INT ilo;\n  F77_INT ihi;\n\n  m_hess_mat = a;\n  double *h = m_hess_mat.rwdata ();\n\n  Array<double> scale (dim_vector (n, 1));\n  double *pscale = scale.rwdata ();\n\n  F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             n, h, n, ilo, ihi, pscale, info\n                             F77_CHAR_ARG_LEN (1)));\n\n  Array<double> tau (dim_vector (n-1, 1));\n  double *ptau = tau.rwdata ();\n\n  Array<double> work (dim_vector (lwork, 1));\n  double *pwork = work.rwdata ();\n\n  F77_XFCN (dgehrd, DGEHRD, (n, ilo, ihi, h, n, ptau, pwork,\n                             lwork, info));\n\n  m_unitary_hess_mat = m_hess_mat;\n  double *z = m_unitary_hess_mat.rwdata ();\n\n  F77_XFCN (dorghr, DORGHR, (n, ilo, ihi, z, n, ptau, pwork,\n                             lwork, info));\n\n  F77_XFCN (dgebak, DGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (&side, 1),\n                             n, ilo, ihi, pscale, n, z,\n                             n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // If someone thinks of a more graceful way of doing\n  // this (or faster for that matter :-)), please let\n  // me know!\n\n  if (n > 2)\n    for (F77_INT j = 0; j < a_nc; j++)\n      for (F77_INT i = j+2; i < a_nr; i++)\n        m_hess_mat.elem (i, j) = 0;\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nhess<FloatMatrix>::init (const FloatMatrix& a)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.cols ());\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"hess: requires square matrix\");\n\n  char job = 'N';\n  char side = 'R';\n\n  F77_INT n = a_nc;\n  F77_INT lwork = 32 * n;\n  F77_INT info;\n  F77_INT ilo;\n  F77_INT ihi;\n\n  m_hess_mat = a;\n  float *h = m_hess_mat.rwdata ();\n\n  Array<float> scale (dim_vector (n, 1));\n  float *pscale = scale.rwdata ();\n\n  F77_XFCN (sgebal, SGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             n, h, n, ilo, ihi, pscale, info\n                             F77_CHAR_ARG_LEN (1)));\n\n  Array<float> tau (dim_vector (n-1, 1));\n  float *ptau = tau.rwdata ();\n\n  Array<float> work (dim_vector (lwork, 1));\n  float *pwork = work.rwdata ();\n\n  F77_XFCN (sgehrd, SGEHRD, (n, ilo, ihi, h, n, ptau, pwork,\n                             lwork, info));\n\n  m_unitary_hess_mat = m_hess_mat;\n  float *z = m_unitary_hess_mat.rwdata ();\n\n  F77_XFCN (sorghr, SORGHR, (n, ilo, ihi, z, n, ptau, pwork,\n                             lwork, info));\n\n  F77_XFCN (sgebak, SGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (&side, 1),\n                             n, ilo, ihi, pscale, n, z,\n                             n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // If someone thinks of a more graceful way of doing\n  // this (or faster for that matter :-)), please let\n  // me know!\n\n  if (n > 2)\n    for (F77_INT j = 0; j < a_nc; j++)\n      for (F77_INT i = j+2; i < a_nr; i++)\n        m_hess_mat.elem (i, j) = 0;\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nhess<ComplexMatrix>::init (const ComplexMatrix& a)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.cols ());\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"hess: requires square matrix\");\n\n  char job = 'N';\n  char side = 'R';\n\n  F77_INT n = a_nc;\n  F77_INT lwork = 32 * n;\n  F77_INT info;\n  F77_INT ilo;\n  F77_INT ihi;\n\n  m_hess_mat = a;\n  Complex *h = m_hess_mat.rwdata ();\n\n  Array<double> scale (dim_vector (n, 1));\n  double *pscale = scale.rwdata ();\n\n  F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             n, F77_DBLE_CMPLX_ARG (h), n, ilo, ihi, pscale, info\n                             F77_CHAR_ARG_LEN (1)));\n\n  Array<Complex> tau (dim_vector (n-1, 1));\n  Complex *ptau = tau.rwdata ();\n\n  Array<Complex> work (dim_vector (lwork, 1));\n  Complex *pwork = work.rwdata ();\n\n  F77_XFCN (zgehrd, ZGEHRD, (n, ilo, ihi, F77_DBLE_CMPLX_ARG (h), n,\n                             F77_DBLE_CMPLX_ARG (ptau), F77_DBLE_CMPLX_ARG (pwork), lwork, info));\n\n  m_unitary_hess_mat = m_hess_mat;\n  Complex *z = m_unitary_hess_mat.rwdata ();\n\n  F77_XFCN (zunghr, ZUNGHR, (n, ilo, ihi, F77_DBLE_CMPLX_ARG (z), n,\n                             F77_DBLE_CMPLX_ARG (ptau), F77_DBLE_CMPLX_ARG (pwork),\n                             lwork, info));\n\n  F77_XFCN (zgebak, ZGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (&side, 1),\n                             n, ilo, ihi, pscale, n, F77_DBLE_CMPLX_ARG (z), n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // If someone thinks of a more graceful way of\n  // doing this (or faster for that matter :-)),\n  // please let me know!\n\n  if (n > 2)\n    for (F77_INT j = 0; j < a_nc; j++)\n      for (F77_INT i = j+2; i < a_nr; i++)\n        m_hess_mat.elem (i, j) = 0;\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API octave_idx_type\nhess<FloatComplexMatrix>::init (const FloatComplexMatrix& a)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.cols ());\n\n  if (a_nr != a_nc)\n    {\n      (*current_liboctave_error_handler) (\"hess: requires square matrix\");\n      return -1;\n    }\n\n  char job = 'N';\n  char side = 'R';\n\n  F77_INT n = a_nc;\n  F77_INT lwork = 32 * n;\n  F77_INT info;\n  F77_INT ilo;\n  F77_INT ihi;\n\n  m_hess_mat = a;\n  FloatComplex *h = m_hess_mat.rwdata ();\n\n  Array<float> scale (dim_vector (n, 1));\n  float *pscale = scale.rwdata ();\n\n  F77_XFCN (cgebal, CGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             n, F77_CMPLX_ARG (h), n, ilo, ihi, pscale, info\n                             F77_CHAR_ARG_LEN (1)));\n\n  Array<FloatComplex> tau (dim_vector (n-1, 1));\n  FloatComplex *ptau = tau.rwdata ();\n\n  Array<FloatComplex> work (dim_vector (lwork, 1));\n  FloatComplex *pwork = work.rwdata ();\n\n  F77_XFCN (cgehrd, CGEHRD, (n, ilo, ihi, F77_CMPLX_ARG (h), n,\n                             F77_CMPLX_ARG (ptau), F77_CMPLX_ARG (pwork), lwork, info));\n\n  m_unitary_hess_mat = m_hess_mat;\n  FloatComplex *z = m_unitary_hess_mat.rwdata ();\n\n  F77_XFCN (cunghr, CUNGHR, (n, ilo, ihi, F77_CMPLX_ARG (z), n,\n                             F77_CMPLX_ARG (ptau), F77_CMPLX_ARG (pwork),\n                             lwork, info));\n\n  F77_XFCN (cgebak, CGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1),\n                             F77_CONST_CHAR_ARG2 (&side, 1),\n                             n, ilo, ihi, pscale, n, F77_CMPLX_ARG (z), n, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  // If someone thinks of a more graceful way of\n  // doing this (or faster for that matter :-)),\n  // please let me know!\n\n  if (n > 2)\n    for (F77_INT j = 0; j < a_nc; j++)\n      for (F77_INT i = j+2; i < a_nr; i++)\n        m_hess_mat.elem (i, j) = 0;\n\n  return info;\n}\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/hess.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_hess_h)\n#define octave_hess_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nclass hess\n{\npublic:\n\n  hess ()\n    : m_hess_mat (), m_unitary_hess_mat ()\n  { }\n\n  hess (const T& a)\n    : m_hess_mat (), m_unitary_hess_mat ()\n  {\n    init (a);\n  }\n\n  hess (const T& a, octave_idx_type& info)\n    : m_hess_mat (), m_unitary_hess_mat ()\n  {\n    info = init (a);\n  }\n\n  hess (const hess& a)\n    : m_hess_mat (a.m_hess_mat), m_unitary_hess_mat (a.m_unitary_hess_mat)\n  { }\n\n  hess& operator = (const hess& a)\n  {\n    if (this != &a)\n      {\n        m_hess_mat = a.m_hess_mat;\n        m_unitary_hess_mat = a.m_unitary_hess_mat;\n      }\n\n    return *this;\n  }\n\n  ~hess () = default;\n\n  T hess_matrix () const { return m_hess_mat; }\n\n  T unitary_hess_matrix () const { return m_unitary_hess_mat; }\n\nprivate:\n\n  T m_hess_mat;\n  T m_unitary_hess_mat;\n\n  OCTAVE_API octave_idx_type init (const T& a);\n};\n\ntemplate <typename T>\nextern OCTAVE_API std::ostream&\noperator << (std::ostream& os, const hess<T>& a);\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lapack-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lapack_proto_h)\n#define octave_lapack_proto_h 1\n\n#include \"octave-config.h\"\n\n#include \"f77-fcn.h\"\n#include \"oct-cmplx.h\"\n\nextern \"C\"\n{\n  // GBCON\n\n  F77_RET_T\n  F77_FUNC (dgbcon, DGBCON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_INT *,\n                             const F77_DBLE&, F77_DBLE&, F77_DBLE *,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgbcon, ZGBCON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_INT *,\n                             const F77_DBLE&, F77_DBLE&, F77_DBLE_CMPLX *,\n                             F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GBTRF\n\n  F77_RET_T\n  F77_FUNC (dgbtrf, DGBTRF) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_INT *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgbtrf, ZGBTRF) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_INT *, F77_INT&);\n\n  // GBTRS\n\n  F77_RET_T\n  F77_FUNC (dgbtrs, DGBTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE *, const F77_INT&,\n                             const F77_INT *, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgbtrs, ZGBTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE_CMPLX *, const F77_INT&,\n                             const F77_INT *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GEBAL\n\n  F77_RET_T\n  F77_FUNC (cgebal, CGEBAL) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&,\n                             F77_INT&, F77_REAL *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgebal, DGEBAL) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&,\n                             F77_INT&, F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgebal, SGEBAL) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&,\n                             F77_INT&, F77_REAL *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgebal, ZGEBAL) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&,\n                             F77_INT&, F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GEBAK\n\n  F77_RET_T\n  F77_FUNC (cgebak, CGEBAK) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_REAL *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgebak, DGEBAK) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgebak, SGEBAK) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgebak, ZGEBAK) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_DBLE *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GECON\n\n  F77_RET_T\n  F77_FUNC (cgecon, CGECON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, const F77_REAL&, F77_REAL&,\n                             F77_CMPLX *, F77_REAL *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgecon, DGECON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_DBLE&, F77_DBLE&,\n                             F77_DBLE *, F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgecon, SGECON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, const F77_REAL&, F77_REAL&,\n                             F77_REAL *, F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgecon, ZGECON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_DBLE&, F77_DBLE&,\n                             F77_DBLE_CMPLX *, F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GEHRD\n\n  F77_RET_T\n  F77_FUNC (cgehrd, CGEHRD) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *, F77_CMPLX *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dgehrd, DGEHRD) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sgehrd, SGEHRD) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *, F77_REAL *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgehrd, ZGEHRD) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&);\n\n  // GEQP3\n\n  F77_RET_T\n  F77_FUNC (cgeqp3, CGEQP3) (const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_INT *, F77_CMPLX *, F77_CMPLX *,\n                             const F77_INT&, F77_REAL *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dgeqp3, DGEQP3) (const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_INT *, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sgeqp3, SGEQP3) (const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_INT *, F77_REAL *, F77_REAL *,\n                             const F77_INT&, F77_INT&);\n  F77_RET_T\n  F77_FUNC (zgeqp3, ZGEQP3) (const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_INT *, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE *, F77_INT&);\n\n  // GEQRF\n\n  F77_RET_T\n  F77_FUNC (cgeqrf, CGEQRF) (const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, F77_CMPLX *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dgeqrf, DGEQRF) (const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sgeqrf, SGEQRF) (const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, F77_REAL *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgeqrf, ZGEQRF) (const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&);\n\n  // GELQF\n\n  F77_RET_T\n  F77_FUNC (cgelqf, CGELQF) (const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, F77_CMPLX *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dgelqf, DGELQF) (const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sgelqf, SGELQF) (const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, F77_REAL *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgelqf, ZGELQF) (const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&);\n\n  // ORMLQ\n\n  F77_RET_T\n  F77_FUNC (cormlq, CORMLQ) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dormlq, DORMLQ) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sormlq, SORMLQ) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zormlq, ZORMLQ) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // ORMQR\n\n  F77_RET_T\n  F77_FUNC (cormqr, CORMQR) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dormqr, DORMQR) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sormqr, SORMQR) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zormqr, ZORMQR) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GESDD\n\n  F77_RET_T\n  F77_FUNC (cgesdd, CGESDD) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&, F77_REAL *,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&, F77_REAL *,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgesdd, DGESDD) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgesdd, SGESDD) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&, F77_REAL *,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgesdd, ZGESDD) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&, F77_DBLE *,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&, F77_DBLE *,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n  // GESVD\n\n  F77_RET_T\n  F77_FUNC (cgesvd, CGESVD) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&, F77_REAL *,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_REAL *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgesvd, DGESVD) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgesvd, SGESVD) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&, F77_REAL *,\n                             F77_REAL *, const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgesvd, ZGESVD) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE *, F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GEJSV\n\n  F77_RET_T\n  F77_FUNC (cgejsv, CGEJSV) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&, F77_REAL *,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_REAL *,  const F77_INT&,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgejsv, DGEJSV) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgejsv, SGEJSV) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&, F77_REAL *,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgejsv, ZGEJSV) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&, F77_DBLE *,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE *,       const F77_INT&,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GEESX\n\n  typedef F77_INT (*double_selector) (const F77_DBLE&, const F77_DBLE&);\n  typedef F77_INT (*float_selector) (const F77_REAL&, const F77_REAL&);\n  typedef F77_INT (*complex_selector) (const F77_DBLE_CMPLX&);\n  typedef F77_INT (*float_complex_selector) (const F77_CMPLX&);\n\n  F77_RET_T\n  F77_FUNC (cgeesx, CGEESX) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             float_complex_selector,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&,\n                             F77_CMPLX *, F77_CMPLX *,\n                             const F77_INT&, F77_REAL&, F77_REAL&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_REAL *, F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgeesx, DGEESX) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             double_selector,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&,\n                             F77_DBLE *, F77_DBLE *, F77_DBLE *, const F77_INT&,\n                             F77_DBLE&, F77_DBLE&, F77_DBLE *, const F77_INT&,\n                             F77_INT *, const F77_INT&,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgeesx, SGEESX) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             float_selector,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&,\n                             F77_REAL *, F77_REAL *, F77_REAL *, const F77_INT&,\n                             F77_REAL&, F77_REAL&, F77_REAL *, const F77_INT&,\n                             F77_INT *, const F77_INT&,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgeesx, ZGEESX) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             complex_selector,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&,\n                             F77_DBLE_CMPLX *, F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE&, F77_DBLE&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE *,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GEEVX\n\n  F77_RET_T\n  F77_FUNC (cgeevx, CGEEVX) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&,\n                             F77_INT&, F77_REAL *, F77_REAL&, F77_REAL *,\n                             F77_REAL *, F77_CMPLX *, const F77_INT&,\n                             F77_REAL *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgeevx, DGEEVX) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *, F77_DBLE *,\n                             F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&,\n                             F77_INT&, F77_DBLE *, F77_DBLE&,\n                             F77_DBLE *, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT *,\n                             F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgeevx, SGEEVX) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *, F77_REAL *, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&,\n                             F77_INT&, F77_REAL *, F77_REAL&, F77_REAL *,\n                             F77_REAL *, F77_REAL *, const F77_INT&,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgeevx, ZGEEVX) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             F77_DBLE_CMPLX *, const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&,\n                             F77_INT&, F77_DBLE *, F77_DBLE&,\n                             F77_DBLE *, F77_DBLE *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE *,\n                             F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GELSD\n\n  F77_RET_T\n  F77_FUNC (cgelsd, CGELSD) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_REAL *, F77_REAL&,\n                             F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_REAL *,\n                             F77_INT *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dgelsd, DGELSD) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *, F77_DBLE&,\n                             F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT *,\n                             F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sgelsd, SGELSD) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *, F77_REAL&,\n                             F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT *,\n                             F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgelsd, ZGELSD) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE *, F77_DBLE&,\n                             F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE *,\n                             F77_INT *, F77_INT&);\n\n  // GELSY\n\n  F77_RET_T\n  F77_FUNC (cgelsy, CGELSY) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT *,\n                             F77_REAL&, F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_REAL *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dgelsy, DGELSY) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT *,\n                             F77_DBLE&, F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sgelsy, SGELSY) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT *,\n                             F77_REAL&, F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgelsy, ZGELSY) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT *,\n                             F77_DBLE&, F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE *,\n                             F77_INT&);\n\n  // GETRF\n\n  F77_RET_T\n  F77_FUNC (cgetrf, CGETRF) (const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_INT *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dgetrf, DGETRF) (const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_INT *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sgetrf, SGETRF) (const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&,\n                             F77_INT *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgetrf, ZGETRF) (const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_INT *, F77_INT&);\n\n  // GETRI\n\n  F77_RET_T\n  F77_FUNC (cgetri, CGETRI) (const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, const F77_INT *,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dgetri, DGETRI) (const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_INT *,\n                             F77_DBLE *, const F77_INT&,\n                             F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sgetri, SGETRI) (const F77_INT&, F77_REAL *,\n                             const F77_INT&, const F77_INT *,\n                             F77_REAL *, const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgetri, ZGETRI) (const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_INT *,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_INT&);\n\n  // GETRS\n\n  F77_RET_T\n  F77_FUNC (cgetrs, CGETRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             const F77_INT *, F77_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgetrs, DGETRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE *, const F77_INT&,\n                             const F77_INT *, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sgetrs, SGETRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_REAL *, const F77_INT&,\n                             const F77_INT *, F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgetrs, ZGETRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             const F77_INT *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GGBAL\n\n  F77_RET_T\n  F77_FUNC (cggbal, CGGBAL) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N,\n                             F77_CMPLX *A, const F77_INT& LDA,\n                             F77_CMPLX *B, const F77_INT& LDB,\n                             F77_INT& ILO, F77_INT& IHI,\n                             F77_REAL *LSCALE, F77_REAL *RSCALE,\n                             F77_REAL *WORK, F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dggbal, DGGBAL) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N, F77_DBLE *A,\n                             const F77_INT& LDA, F77_DBLE *B,\n                             const F77_INT& LDB, F77_INT& ILO,\n                             F77_INT& IHI, F77_DBLE *LSCALE,\n                             F77_DBLE *RSCALE, F77_DBLE *WORK,\n                             F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sggbal, SGGBAL) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N, F77_REAL *A,\n                             const F77_INT& LDA, F77_REAL *B,\n                             const F77_INT& LDB,\n                             F77_INT& ILO, F77_INT& IHI,\n                             F77_REAL *LSCALE, F77_REAL *RSCALE,\n                             F77_REAL *WORK, F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zggbal, ZGGBAL) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N, F77_DBLE_CMPLX *A,\n                             const F77_INT& LDA, F77_DBLE_CMPLX *B,\n                             const F77_INT& LDB, F77_INT& ILO,\n                             F77_INT& IHI, F77_DBLE *LSCALE,\n                             F77_DBLE *RSCALE, F77_DBLE *WORK,\n                             F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GGBAK\n\n  F77_RET_T\n  F77_FUNC (dggbak, DGGBAK) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N,\n                             const F77_INT& ILO,\n                             const F77_INT& IHI,\n                             const F77_DBLE *LSCALE, const F77_DBLE *RSCALE,\n                             F77_INT& M, F77_DBLE *V,\n                             const F77_INT& LDV, F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sggbak, SGGBAK) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N,\n                             const F77_INT& ILO,\n                             const F77_INT& IHI,\n                             const F77_REAL *LSCALE, const F77_REAL *RSCALE,\n                             F77_INT& M, F77_REAL *V,\n                             const F77_INT& LDV, F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zggbak, ZGGBAK) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N,\n                             const F77_INT& ILO,\n                             const F77_INT& IHI,\n                             const F77_DBLE *LSCALE, const F77_DBLE *RSCALE,\n                             F77_INT& M, F77_DBLE_CMPLX *V,\n                             const F77_INT& LDV, F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GGEV\n\n  F77_RET_T\n  F77_FUNC (cggev, CGGEV) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_CMPLX *,\n                           const F77_INT&, F77_CMPLX *,\n                           const F77_INT&, F77_CMPLX *,\n                           F77_CMPLX *, F77_CMPLX *,\n                           const F77_INT&, F77_CMPLX *,\n                           const F77_INT&, F77_CMPLX *,\n                           const F77_INT&, F77_REAL *, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dggev, DGGEV) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&,\n                           F77_DBLE *, const F77_INT&,\n                           F77_DBLE *, const F77_INT&,\n                           F77_DBLE *, F77_DBLE *, F77_DBLE *, F77_DBLE *,\n                           const F77_INT&, F77_DBLE *,\n                           const F77_INT&, F77_DBLE *,\n                           const F77_INT&, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sggev, SGGEV) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_REAL *,\n                           const F77_INT&, F77_REAL *,\n                           const F77_INT&, F77_REAL *, F77_REAL *, F77_REAL *,\n                           F77_REAL *, const F77_INT&, F77_REAL *,\n                           const F77_INT&, F77_REAL *,\n                           const F77_INT&, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zggev, ZGGEV) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&,\n                           F77_DBLE_CMPLX *, const F77_INT&,\n                           F77_DBLE_CMPLX *, const F77_INT&,\n                           F77_DBLE_CMPLX *, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                           const F77_INT&, F77_DBLE_CMPLX *,\n                           const F77_INT&, F77_DBLE_CMPLX *,\n                           const F77_INT&, F77_DBLE *, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  // GGHRD\n\n  F77_RET_T\n  F77_FUNC (dgghrd, DGGHRD) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N,\n                             const F77_INT& ILO,\n                             const F77_INT& IHI, F77_DBLE *A,\n                             const F77_INT& LDA, F77_DBLE *B,\n                             const F77_INT& LDB, F77_DBLE *Q,\n                             const F77_INT& LDQ, F77_DBLE *Z,\n                             const F77_INT& LDZ, F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgghrd, ZGGHRD) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N,\n                             const F77_INT& ILO,\n                             const F77_INT& IHI, F77_DBLE_CMPLX *A,\n                             const F77_INT& LDA, F77_DBLE_CMPLX *B,\n                             const F77_INT& LDB, F77_DBLE_CMPLX *Q,\n                             const F77_INT& LDQ, F77_DBLE_CMPLX *Z,\n                             const F77_INT& LDZ, F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // GGSVD\n\n  F77_RET_T\n  F77_FUNC (dggsvd, DGGSVD)\n  (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   F77_DBLE *,                // A(LDA,N)\n   const F77_INT&,            // LDA\n   F77_DBLE *,                // B(LDB,N)\n   const F77_INT&,            // LDB\n   F77_DBLE *,                // ALPHA(N)\n   F77_DBLE *,                // BETA(N)\n   F77_DBLE *,                // U(LDU,M)\n   const F77_INT&,            // LDU\n   F77_DBLE *,                // V(LDV,P)\n   const F77_INT&,            // LDV\n   F77_DBLE *,                // Q(LDQ,N)\n   const F77_INT&,            // LDQ\n   F77_DBLE *,                // WORK\n   F77_INT *,                 // IWORK(N)\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sggsvd, SGGSVD)\n  (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   F77_REAL *,                // A\n   const F77_INT&,            // LDA\n   F77_REAL *,                // B\n   const F77_INT&,            // LDB\n   F77_REAL *,                // ALPHA\n   F77_REAL *,                // BETA\n   F77_REAL *,                // U\n   const F77_INT&,            // LDU\n   F77_REAL *,                // V\n   const F77_INT&,            // LDV\n   F77_REAL *,                // Q\n   const F77_INT&,            // LDQ\n   F77_REAL *,                // WORK\n   F77_INT *,                 // IWORK\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zggsvd, ZGGSVD)\n  (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   F77_DBLE_CMPLX *,          // A(LDA,N)\n   const F77_INT&,            // LDA\n   F77_DBLE_CMPLX *,          // B(LDB,N)\n   const F77_INT&,            // LDB\n   F77_DBLE *,                // ALPHA(N)\n   F77_DBLE *,                // BETA(N)\n   F77_DBLE_CMPLX *,          // U(LDU,M)\n   const F77_INT&,            // LDU\n   F77_DBLE_CMPLX *,          // V(LDV,P)\n   const F77_INT&,            // LDV\n   F77_DBLE_CMPLX *,          // Q(LDQ,N)\n   const F77_INT&,            // LDQ\n   F77_DBLE_CMPLX *,          // WORK\n   F77_DBLE *,                // RWORK\n   F77_INT *,                 // IWORK(N)\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (cggsvd, CGGSVD)\n  (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   F77_CMPLX *,               // A\n   const F77_INT&,            // LDA\n   F77_CMPLX *,               // B\n   const F77_INT&,            // LDB\n   F77_REAL *,                // ALPHA\n   F77_REAL *,                // BETA\n   F77_CMPLX *,               // U\n   const F77_INT&,            // LDU\n   F77_CMPLX *,               // V\n   const F77_INT&,            // LDV\n   F77_CMPLX *,               // Q\n   const F77_INT&,            // LDQ\n   F77_CMPLX *,               // WORK\n   F77_REAL *,                // RWORK\n   F77_INT *,                 // IWORK\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n\n  // GGSVD3\n\n  F77_RET_T\n  F77_FUNC (dggsvd3, DGGSVD3)\n  (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   F77_DBLE *,                // A(LDA,N)\n   const F77_INT&,            // LDA\n   F77_DBLE *,                // B(LDB,N)\n   const F77_INT&,            // LDB\n   F77_DBLE *,                // ALPHA(N)\n   F77_DBLE *,                // BETA(N)\n   F77_DBLE *,                // U(LDU,M)\n   const F77_INT&,            // LDU\n   F77_DBLE *,                // V(LDV,P)\n   const F77_INT&,            // LDV\n   F77_DBLE *,                // Q(LDQ,N)\n   const F77_INT&,            // LDQ\n   F77_DBLE *,                // WORK\n   const F77_INT&,            // LWORK\n   F77_INT *,                 // IWORK(N)\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (sggsvd3, SGGSVD3)\n  (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   F77_REAL *,                // A\n   const F77_INT&,            // LDA\n   F77_REAL *,                // B\n   const F77_INT&,            // LDB\n   F77_REAL *,                // ALPHA\n   F77_REAL *,                // BETA\n   F77_REAL *,                // U\n   const F77_INT&,            // LDU\n   F77_REAL *,                // V\n   const F77_INT&,            // LDV\n   F77_REAL *,                // Q\n   const F77_INT&,            // LDQ\n   F77_REAL *,                // WORK\n   const F77_INT&,            // LWORK\n   F77_INT *,                 // IWORK\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zggsvd3, ZGGSVD3)\n  (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   F77_DBLE_CMPLX *,          // A(LDA,N)\n   const F77_INT&,            // LDA\n   F77_DBLE_CMPLX *,          // B(LDB,N)\n   const F77_INT&,            // LDB\n   F77_DBLE *,                // ALPHA(N)\n   F77_DBLE *,                // BETA(N)\n   F77_DBLE_CMPLX *,          // U(LDU,M)\n   const F77_INT&,            // LDU\n   F77_DBLE_CMPLX *,          // V(LDV,P)\n   const F77_INT&,            // LDV\n   F77_DBLE_CMPLX *,          // Q(LDQ,N)\n   const F77_INT&,            // LDQ\n   F77_DBLE_CMPLX *,          // WORK\n   const F77_INT&,            // LWORK\n   F77_DBLE *,                // RWORK\n   F77_INT *,                 // IWORK(N)\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (cggsvd3, CGGSVD3)\n  (F77_CONST_CHAR_ARG_DECL,   // JOBU\n   F77_CONST_CHAR_ARG_DECL,   // JOBV\n   F77_CONST_CHAR_ARG_DECL,   // JOBQ\n   const F77_INT&,            // M\n   const F77_INT&,            // N\n   const F77_INT&,            // P\n   F77_INT&,                  // K\n   F77_INT&,                  // L\n   F77_CMPLX *,               // A\n   const F77_INT&,            // LDA\n   F77_CMPLX *,               // B\n   const F77_INT&,            // LDB\n   F77_REAL *,                // ALPHA\n   F77_REAL *,                // BETA\n   F77_CMPLX *,               // U\n   const F77_INT&,            // LDU\n   F77_CMPLX *,               // V\n   const F77_INT&,            // LDV\n   F77_CMPLX *,               // Q\n   const F77_INT&,            // LDQ\n   F77_CMPLX *,               // WORK\n   const F77_INT&,            // LWORK\n   F77_REAL *,                // RWORK\n   F77_INT *,                 // IWORK\n   F77_INT&                   // INFO\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL\n   F77_CHAR_ARG_LEN_DECL);\n\n  // GTSV\n\n  F77_RET_T\n  F77_FUNC (dgtsv, DGTSV) (const F77_INT&, const F77_INT&,\n                           F77_DBLE *, F77_DBLE *, F77_DBLE *, F77_DBLE *,\n                           const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgtsv, ZGTSV) (const F77_INT&, const F77_INT&,\n                           F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                           F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                           const F77_INT&, F77_INT&);\n\n  // GTTRF\n\n  F77_RET_T\n  F77_FUNC (dgttrf, DGTTRF) (const F77_INT&, F77_DBLE *, F77_DBLE *,\n                             F77_DBLE *, F77_DBLE *, F77_INT *,\n                             F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zgttrf, ZGTTRF) (const F77_INT&, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             F77_DBLE_CMPLX *, F77_DBLE_CMPLX *, F77_INT *,\n                             F77_INT&);\n\n  // GTTRS\n\n  F77_RET_T\n  F77_FUNC (dgttrs, DGTTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE *, const F77_DBLE *,\n                             const F77_DBLE *, const F77_DBLE *,\n                             const F77_INT *, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zgttrs, ZGTTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE_CMPLX *, const F77_DBLE_CMPLX *,\n                             const F77_DBLE_CMPLX *, const F77_DBLE_CMPLX *,\n                             const F77_INT *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // HEEV\n\n  F77_RET_T\n  F77_FUNC (cheev, CHEEV) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_CMPLX *,\n                           const F77_INT&, F77_REAL *, F77_CMPLX *,\n                           const F77_INT&, F77_REAL *, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zheev, ZHEEV) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_DBLE_CMPLX *,\n                           const F77_INT&, F77_DBLE *,\n                           F77_DBLE_CMPLX *, const F77_INT&, F77_DBLE *,\n                           F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  // HEGV\n\n  F77_RET_T\n  F77_FUNC (chegv, CHEGV) (const F77_INT&,\n                           F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_CMPLX *,\n                           const F77_INT&, F77_CMPLX *,\n                           const F77_INT&, F77_REAL *, F77_CMPLX *,\n                           const F77_INT&, F77_REAL *, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zhegv, ZHEGV) (const F77_INT&,\n                           F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_DBLE_CMPLX *,\n                           const F77_INT&, F77_DBLE_CMPLX *,\n                           const F77_INT&, F77_DBLE *, F77_DBLE_CMPLX *,\n                           const F77_INT&, F77_DBLE *, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  // HERK\n\n  F77_RET_T\n  F77_FUNC (cherk, CHERK) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_REAL&, const F77_CMPLX *,\n                           const F77_INT&, const F77_REAL&,\n                           F77_CMPLX *, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zherk, ZHERK) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_DBLE&, const F77_DBLE_CMPLX *,\n                           const F77_INT&, const F77_DBLE&, F77_DBLE_CMPLX *,\n                           const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  // HGEQZ\n\n  F77_RET_T\n  F77_FUNC (dhgeqz, DHGEQZ) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N,\n                             const F77_INT& ILO,\n                             const F77_INT& IHI,\n                             F77_DBLE *A, const F77_INT& LDA, F77_DBLE *B,\n                             const F77_INT& LDB, F77_DBLE *ALPHAR,\n                             F77_DBLE *ALPHAI, F77_DBLE *BETA, F77_DBLE *Q,\n                             const F77_INT& LDQ, F77_DBLE *Z,\n                             const F77_INT& LDZ, F77_DBLE *WORK,\n                             const F77_INT& LWORK,\n                             F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zhgeqz, ZHGEQZ) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT& N,\n                             const F77_INT& ILO,\n                             const F77_INT& IHI,\n                             F77_DBLE_CMPLX *A, const F77_INT& LDA,\n                             F77_DBLE_CMPLX *B, const F77_INT& LDB,\n                             F77_DBLE_CMPLX *ALPHA, F77_DBLE_CMPLX *BETA,\n                             F77_DBLE_CMPLX *CQ, const F77_INT& LDQ,\n                             F77_DBLE_CMPLX *CZ, const F77_INT& LDZ,\n                             F77_DBLE_CMPLX *WORK, const F77_INT& LWORK,\n                             F77_DBLE *RWORK, F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // LAENV (liboctave/external/lapack-xtra)\n\n  F77_RET_T\n  F77_FUNC (xilaenv, XILAENV) (const F77_INT&,\n                               F77_CONST_CHAR_ARG_DECL,\n                               F77_CONST_CHAR_ARG_DECL,\n                               const F77_INT&, const F77_INT&,\n                               const F77_INT&, const F77_INT&,\n                               F77_INT&\n                               F77_CHAR_ARG_LEN_DECL\n                               F77_CHAR_ARG_LEN_DECL);\n\n  // LAG2\n\n  F77_RET_T\n  F77_FUNC (dlag2, DLAG2) (const F77_DBLE *A, const F77_INT& LDA,\n                           const F77_DBLE *B, const F77_INT& LDB,\n                           const F77_DBLE& SAFMIN, F77_DBLE& SCALE1,\n                           F77_DBLE& SCALE2, F77_DBLE& WR1, F77_DBLE& WR2,\n                           F77_DBLE& WI);\n\n  // LAMCH (liboctave/external/lapack-xtra)\n\n  F77_RET_T\n  F77_FUNC (xdlamch, XDLAMCH) (F77_CONST_CHAR_ARG_DECL,\n                               F77_DBLE& retval\n                               F77_CHAR_ARG_LEN_DECL);\n\n  // LANGE (liboctave/external/lapack-xtra)\n\n  F77_RET_T\n  F77_FUNC (xclange, XCLANGE) (F77_CONST_CHAR_ARG_DECL,\n                               const F77_INT&, const F77_INT&,\n                               const F77_CMPLX *, const F77_INT&,\n                               F77_REAL *, F77_REAL&\n                               F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (xdlange, XDLANGE) (F77_CONST_CHAR_ARG_DECL,\n                               const F77_INT&, const F77_INT&,\n                               const F77_DBLE *, const F77_INT&,\n                               F77_DBLE *, F77_DBLE&\n                               F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (xslange, XSLANGE) (F77_CONST_CHAR_ARG_DECL,\n                               const F77_INT&,\n                               const F77_INT&, const F77_REAL *,\n                               const F77_INT&, F77_REAL *, F77_REAL&\n                               F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (xzlange, XZLANGE) (F77_CONST_CHAR_ARG_DECL,\n                               const F77_INT&, const F77_INT&,\n                               const F77_DBLE_CMPLX *, const F77_INT&,\n                               F77_DBLE *, F77_DBLE&\n                               F77_CHAR_ARG_LEN_DECL);\n  // LARTG\n\n  F77_RET_T\n  F77_FUNC (clartg, CLARTG) (const F77_CMPLX *, const F77_CMPLX *,\n                             F77_REAL&, F77_CMPLX *, F77_CMPLX *);\n\n  F77_RET_T\n  F77_FUNC (dlartg, DLARTG) (const F77_DBLE&, const F77_DBLE&, F77_DBLE&,\n                             F77_DBLE&, F77_DBLE&);\n\n  F77_RET_T\n  F77_FUNC (slartg, SLARTG) (const F77_REAL&, const F77_REAL&, F77_REAL&,\n                             F77_REAL&, F77_REAL&);\n\n  F77_RET_T\n  F77_FUNC (zlartg, ZLARTG) (const F77_DBLE_CMPLX *, const F77_DBLE_CMPLX *,\n                             F77_DBLE&,\n                             F77_DBLE_CMPLX *, F77_DBLE_CMPLX *);\n\n  // ORGHR\n\n  F77_RET_T\n  F77_FUNC (dorghr, DORGHR) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sorghr, SORGHR) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *, F77_REAL *,\n                             const F77_INT&, F77_INT&);\n\n  // ORGQR\n\n  F77_RET_T\n  F77_FUNC (dorgqr, DORGQR) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *, F77_DBLE *,\n                             const F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sorgqr, SORGQR) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *, F77_REAL *,\n                             const F77_INT&, F77_INT&);\n\n  // PBCON\n\n  F77_RET_T\n  F77_FUNC (dpbcon, DPBCON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             const F77_DBLE&, F77_DBLE&, F77_DBLE *,\n                             F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zpbcon, ZPBCON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&, const F77_DBLE&,\n                             F77_DBLE&, F77_DBLE_CMPLX *, F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // PBTRF\n\n  F77_RET_T\n  F77_FUNC (dpbtrf, DPBTRF) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zpbtrf, ZPBTRF) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // PBTRS\n\n  F77_RET_T\n  F77_FUNC (dpbtrs, DPBTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zpbtrs, ZPBTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // POCON\n\n  F77_RET_T\n  F77_FUNC (cpocon, CPOCON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, const F77_REAL&, F77_REAL&,\n                             F77_CMPLX *, F77_REAL *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dpocon, DPOCON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_DBLE&,\n                             F77_DBLE&, F77_DBLE *, F77_INT *,\n                             F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (spocon, SPOCON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, const F77_REAL&,\n                             F77_REAL&, F77_REAL *, F77_INT *,\n                             F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zpocon, ZPOCON) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_DBLE&,\n                             F77_DBLE&, F77_DBLE_CMPLX *, F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // POTRF\n\n  F77_RET_T\n  F77_FUNC (cpotrf, CPOTRF) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dpotrf, DPOTRF) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (spotrf, SPOTRF) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zpotrf, ZPOTRF) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // POTRI\n\n  F77_RET_T\n  F77_FUNC (cpotri, CPOTRI) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dpotri, DPOTRI) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (spotri, SPOTRI) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zpotri, ZPOTRI) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // POTRS\n\n  F77_RET_T\n  F77_FUNC (spotrs, SPOTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_REAL *, const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (cpotrs, CPOTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dpotrs, DPOTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zpotrs, ZPOTRS) (F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // PTSV\n\n  F77_RET_T\n  F77_FUNC (dptsv, DPTSV) (const F77_INT&, const F77_INT&,\n                           F77_DBLE *, F77_DBLE *, F77_DBLE *, const F77_INT&,\n                           F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zptsv, ZPTSV) (const F77_INT&, const F77_INT&,\n                           F77_DBLE *, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                           const F77_INT&, F77_INT&);\n\n  // RSF2CSF (liboctave/external/lapack-xtra)\n\n  F77_RET_T\n  F77_FUNC (zrsf2csf, ZRSF2CSF) (const F77_INT&, F77_DBLE_CMPLX *,\n                                 F77_DBLE_CMPLX *, F77_DBLE *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (crsf2csf, CRSF2CSF) (const F77_INT&, F77_CMPLX *,\n                                 F77_CMPLX *, F77_REAL *, F77_REAL *);\n\n  // SYEV\n\n  F77_RET_T\n  F77_FUNC (dsyev, DSYEV) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_DBLE *,\n                           const F77_INT&, F77_DBLE *, F77_DBLE *,\n                           const F77_INT&, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ssyev, SSYEV) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_REAL *,\n                           const F77_INT&, F77_REAL *, F77_REAL *,\n                           const F77_INT&, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  // SYGV\n\n  F77_RET_T\n  F77_FUNC (dsygv, DSYGV) (const F77_INT&,\n                           F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_DBLE *,\n                           const F77_INT&, F77_DBLE *,\n                           const F77_INT&, F77_DBLE *, F77_DBLE *,\n                           const F77_INT&, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ssygv, SSYGV) (const F77_INT&,\n                           F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, F77_REAL *,\n                           const F77_INT&, F77_REAL *,\n                           const F77_INT&, F77_REAL *, F77_REAL *,\n                           const F77_INT&, F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  // SYRK\n\n  F77_RET_T\n  F77_FUNC (csyrk, CSYRK) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_CMPLX&, const F77_CMPLX *,\n                           const F77_INT&, const F77_CMPLX&,\n                           F77_CMPLX *, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dsyrk, DSYRK) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_DBLE&, const F77_DBLE *, const F77_INT&,\n                           const F77_DBLE&, F77_DBLE *, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ssyrk, SSYRK) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_REAL&, const F77_REAL *, const F77_INT&,\n                           const F77_REAL&, F77_REAL *, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (zsyrk, ZSYRK) (F77_CONST_CHAR_ARG_DECL,\n                           F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_DBLE_CMPLX&, const F77_DBLE_CMPLX *,\n                           const F77_INT&, const F77_DBLE_CMPLX&,\n                           F77_DBLE_CMPLX *, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n  // TGEVC\n\n  // Documentation for DTGEVC incorrectly states that VR, VL are\n  // complex*16; they are declared in DTGEVC as double precision\n  // (probably a cut and paste problem fro ZTGEVC).\n  F77_RET_T\n  F77_FUNC (dtgevc, DTGEVC) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT *SELECT,\n                             const F77_INT& N, F77_DBLE *A,\n                             const F77_INT& LDA, F77_DBLE *B,\n                             const F77_INT& LDB, F77_DBLE *VL,\n                             const F77_INT& LDVL, F77_DBLE *VR,\n                             const F77_INT& LDVR,\n                             const F77_INT& MM, F77_INT& M,\n                             F77_DBLE *WORK, F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ztgevc, ZTGEVC) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT *SELECT,\n                             const F77_INT& N, const F77_DBLE_CMPLX *A,\n                             const F77_INT& LDA, const F77_DBLE_CMPLX *B,\n                             const F77_INT& LDB, F77_DBLE_CMPLX *xVL,\n                             const F77_INT& LDVL, F77_DBLE_CMPLX *xVR,\n                             const F77_INT& LDVR,\n                             const F77_INT& MM, F77_INT& M,\n                             F77_DBLE_CMPLX *CWORK, F77_DBLE *RWORK,\n                             F77_INT& INFO\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // TGSEN\n\n  F77_RET_T\n  F77_FUNC (dtgsen, DTGSEN) (const F77_INT& IJOB,\n                             const F77_LOGICAL& WANTQ,\n                             const F77_LOGICAL& WANTZ,\n                             const F77_LOGICAL *SELECT,\n                             const F77_INT& N,\n                             F77_DBLE *A,\n                             const F77_INT& LDA,\n                             F77_DBLE *B,\n                             const F77_INT& LDB,\n                             F77_DBLE *ALPHAR,\n                             F77_DBLE *ALPHAI,\n                             F77_DBLE *BETA,\n                             F77_DBLE *Q,\n                             const F77_INT& LDQ,\n                             F77_DBLE *Z,\n                             const F77_INT& LDZ,\n                             F77_INT& M,\n                             F77_DBLE& PL,\n                             F77_DBLE& PR,\n                             F77_DBLE *DIF,\n                             F77_DBLE *WORK,\n                             const F77_INT& LWORK,\n                             F77_INT *IWORK,\n                             const F77_INT& LIWORK,\n                             F77_INT& INFO);\n\n  F77_RET_T\n  F77_FUNC (ztgsen, ZTGSEN) (const F77_INT& IJOB,\n                             const F77_LOGICAL& WANTQ,\n                             const F77_LOGICAL& WANTZ,\n                             const F77_LOGICAL *SELECT,\n                             const F77_INT& N,\n                             F77_DBLE_CMPLX *A,\n                             const F77_INT& LDA,\n                             F77_DBLE_CMPLX *B,\n                             const F77_INT& LDB,\n                             F77_DBLE_CMPLX *ALPHA,\n                             F77_DBLE_CMPLX *BETA,\n                             F77_DBLE_CMPLX *Q,\n                             const F77_INT& LDQ,\n                             F77_DBLE_CMPLX *Z,\n                             const F77_INT& LDZ,\n                             F77_INT& M,\n                             F77_DBLE& PL,\n                             F77_DBLE& PR,\n                             F77_DBLE *DIF,\n                             F77_DBLE_CMPLX *WORK,\n                             const F77_INT& LWORK,\n                             F77_INT *IWORK,\n                             const F77_INT& LIWORK,\n                             F77_INT& INFO);\n\n  // TRCON\n\n  F77_RET_T\n  F77_FUNC (ctrcon, CTRCON) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, F77_REAL&, F77_CMPLX *,\n                             F77_REAL *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dtrcon, DTRCON) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_DBLE *,\n                             const F77_INT&, F77_DBLE&,\n                             F77_DBLE *, F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n  F77_RET_T\n  F77_FUNC (strcon, STRCON) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_REAL *,\n                             const F77_INT&, F77_REAL&,\n                             F77_REAL *, F77_INT *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ztrcon, ZTRCON) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE&,\n                             F77_DBLE_CMPLX *, F77_DBLE *, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // TREXC\n\n  // Real versions\n  F77_RET_T\n  F77_FUNC (dtrexc, DTREXC) (F77_CONST_CHAR_ARG_DECL,\n                            const F77_INT&,\n                            F77_DBLE *,\n                            const F77_INT&,\n                            F77_DBLE *,\n                            const F77_INT&,\n                            F77_INT&,\n                            F77_INT&,\n                            F77_DBLE *,\n                            F77_INT&\n                            F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (strexc, STREXC) (F77_CONST_CHAR_ARG_DECL,\n                            const F77_INT&,\n                            F77_REAL *,\n                            const F77_INT&,\n                            F77_REAL *,\n                            const F77_INT&,\n                            F77_INT&,\n                            F77_INT&,\n                            F77_REAL *,\n                            F77_INT&\n                            F77_CHAR_ARG_LEN_DECL);\n\n  // Complex versions\n  F77_RET_T\n  F77_FUNC (ztrexc, ZTREXC) (F77_CONST_CHAR_ARG_DECL,\n                            const F77_INT&,\n                            F77_DBLE_CMPLX *,\n                            const F77_INT&,\n                            F77_DBLE_CMPLX *,\n                            const F77_INT&,\n                            const F77_INT&,\n                            F77_INT&,\n                            F77_INT&\n                            F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ctrexc, CTREXC) (F77_CONST_CHAR_ARG_DECL,\n                            const F77_INT&,\n                            F77_CMPLX *,\n                            const F77_INT&,\n                            F77_CMPLX *,\n                            const F77_INT&,\n                            const F77_INT&,\n                            F77_INT&,\n                            F77_INT&\n                            F77_CHAR_ARG_LEN_DECL);\n\n  // TRSEN\n\n  F77_RET_T\n  F77_FUNC (ctrsen, CTRSEN) (F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *, F77_INT&,\n                             F77_REAL&, F77_REAL&, F77_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dtrsen, DTRSEN) (F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT *, const F77_INT&,\n                             F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *, F77_DBLE *,\n                             F77_INT&, F77_DBLE&, F77_DBLE&, F77_DBLE *,\n                             const F77_INT&, F77_INT *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (strsen, STRSEN) (F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT *, const F77_INT&,\n                             F77_REAL *, const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *, F77_REAL *,\n                             F77_INT&, F77_REAL&, F77_REAL&, F77_REAL *,\n                             const F77_INT&, F77_INT *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ztrsen, ZTRSEN) (F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, F77_INT&, F77_DBLE&,\n                             F77_DBLE&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // TRSYL\n\n  F77_RET_T\n  F77_FUNC (ctrsyl, CTRSYL) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, F77_REAL&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dtrsyl, DTRSYL) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_DBLE *,\n                             const F77_INT&, const F77_DBLE *,\n                             const F77_INT&, const F77_DBLE *,\n                             const F77_INT&, F77_DBLE&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (strsyl, STRSYL) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_REAL *,\n                             const F77_INT&, const F77_REAL *,\n                             const F77_INT&, const F77_REAL *,\n                             const F77_INT&, F77_REAL&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ztrsyl, ZTRSYL) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // TRTRI\n\n  F77_RET_T\n  F77_FUNC (ctrtri, CTRTRI) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dtrtri, DTRTRI) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (strtri, STRTRI) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ztrtri, ZTRTRI) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // TRTRS\n\n  F77_RET_T\n  F77_FUNC (ctrtrs, CTRTRS) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dtrtrs, DTRTRS) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE *, const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (strtrs, STRTRS) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             const F77_INT&, const F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (ztrtrs, ZTRTRS) (F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE_CMPLX *, const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  // UNGHR\n\n  F77_RET_T\n  F77_FUNC (cunghr, CUNGHR) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zunghr, ZUNGHR) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&);\n  // UNGQR\n\n  F77_RET_T\n  F77_FUNC (cungqr, CUNGQR) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zungqr, ZUNGQR) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_INT&);\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lo-amos-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_amos_proto_h)\n#define octave_lo_amos_proto_h 1\n\n#warning 'header file \"lo-amos-proto.h\" is deprecated, use \"amos-proto.h\" instead'\n\n#include \"amos-proto.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lo-arpack-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_arpack_proto_h)\n#define octave_lo_arpack_proto_h 1\n\n#warning 'header file \"lo-arpack-proto.h\" is deprecated, use \"arpack-proto.h\" instead'\n\n#include \"arpack-proto.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lo-blas-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_blas_proto_h)\n#define octave_lo_blas_proto_h 1\n\n#warning 'header file \"lo-blas-proto.h\" is deprecated, use \"blas-proto.h\" instead'\n\n#include \"blas-proto.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lo-lapack-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_lapack_proto_h)\n#define octave_lo_lapack_proto_h 1\n\n#warning 'header file \"lo-lapack-proto.h\" is deprecated, use \"lapack-proto.h\" instead'\n\n#include \"lapack-proto.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lo-mappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_mappers_h)\n#define octave_lo_mappers_h 1\n\n#warning 'header file \"lo-mappers.h\" is deprecated, use \"mappers.h\" instead'\n\n#include \"mappers.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lo-qrupdate-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_qrupdate_proto_h)\n#define octave_lo_qrupdate_proto_h 1\n\n#warning 'header file \"lo-qrupdate-proto.h\" is deprecated, use \"qrupdate-proto.h\" instead'\n\n#include \"qrupdate-proto.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lo-ranlib-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_ranlib_proto_h)\n#define octave_lo_ranlib_proto_h 1\n\n#warning 'header file \"lo-ranlib-proto.h\" is deprecated, use \"ranlib-proto.h\" instead'\n\n#include \"ranlib-proto.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lo-slatec-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_slatec_proto_h)\n#define octave_lo_slatec_proto_h 1\n\n#warning 'header file \"lo-slatec-proto.h\" is deprecated, use \"slatec-proto.h\" instead'\n\n#include \"slatec-proto.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lo-specfun.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_specfun_h)\n#define octave_lo_specfun_h 1\n\n#warning 'header file \"lo-specfun.h\" is deprecated, use \"oct-specfun.h\" instead'\n\n#include \"oct-specfun.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/lu.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <vector>\n\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n#include \"PermMatrix.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"fCColVector.h\"\n#include \"fCMatrix.h\"\n#include \"fColVector.h\"\n#include \"fMatrix.h\"\n#include \"lapack-proto.h\"\n#include \"lu.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"qrupdate-proto.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\n// FIXME: PermMatrix::col_perm_vec returns Array<octave_idx_type>\n// but m_ipvt is an Array<octave_f77_int_type>.  This could cause\n// trouble for large arrays if octave_f77_int_type is 32-bits but\n// octave_idx_type is 64.  Since this constructor is called from\n// Fluupdate, it could be given values that are out of range.  We\n// should ensure that the values are within range here.\n\ntemplate <typename T>\nlu<T>::lu (const T& l, const T& u, const PermMatrix& p)\n  : m_a_fact (u), m_L (l), m_ipvt (p.transpose ().col_perm_vec ())\n{\n  if (l.columns () != u.rows ())\n    (*current_liboctave_error_handler) (\"lu: dimension mismatch\");\n}\n\ntemplate <typename T>\nbool\nlu<T>::packed () const\n{\n  return m_L.dims () == dim_vector ();\n}\n\ntemplate <typename T>\nvoid\nlu<T>::unpack ()\n{\n  if (packed ())\n    {\n      m_L = L ();\n      m_a_fact = U (); // FIXME: sub-optimal\n\n      // FIXME: getp returns Array<octave_idx_type> but m_ipvt is\n      // Array<octave_f77_int_type>.  However, getp produces its\n      // result from a valid m_ipvt array so validation should not be\n      // necessary.  OTOH, it might be better to have a version of\n      // getp that doesn't cause us to convert from\n      // Array<octave_f77_int_type> to Array<octave_idx_type> and\n      // back again.\n\n      m_ipvt = getp ();\n    }\n}\n\ntemplate <typename T>\nT\nlu<T>::L () const\n{\n  if (packed ())\n    {\n      octave_idx_type a_nr = m_a_fact.rows ();\n      octave_idx_type a_nc = m_a_fact.columns ();\n      octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc);\n\n      T l (a_nr, mn, ELT_T (0.0));\n\n      for (octave_idx_type i = 0; i < a_nr; i++)\n        {\n          if (i < a_nc)\n            l.xelem (i, i) = 1.0;\n\n          for (octave_idx_type j = 0; j < (i < a_nc ? i : a_nc); j++)\n            l.xelem (i, j) = m_a_fact.xelem (i, j);\n        }\n\n      return l;\n    }\n  else\n    return m_L;\n}\n\ntemplate <typename T>\nT\nlu<T>::U () const\n{\n  if (packed ())\n    {\n      octave_idx_type a_nr = m_a_fact.rows ();\n      octave_idx_type a_nc = m_a_fact.columns ();\n      octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc);\n\n      T u (mn, a_nc, ELT_T (0.0));\n\n      for (octave_idx_type i = 0; i < mn; i++)\n        {\n          for (octave_idx_type j = i; j < a_nc; j++)\n            u.xelem (i, j) = m_a_fact.xelem (i, j);\n        }\n\n      return u;\n    }\n  else\n    return m_a_fact;\n}\n\ntemplate <typename T>\nT\nlu<T>::Y () const\n{\n  if (! packed ())\n    (*current_liboctave_error_handler)\n      (\"lu: Y () not implemented for unpacked form\");\n\n  return m_a_fact;\n}\n\ntemplate <typename T>\nArray<octave_idx_type>\nlu<T>::getp () const\n{\n  if (packed ())\n    {\n      octave_idx_type a_nr = m_a_fact.rows ();\n\n      Array<octave_idx_type> pvt (dim_vector (a_nr, 1));\n\n      for (octave_idx_type i = 0; i < a_nr; i++)\n        pvt.xelem (i) = i;\n\n      for (octave_idx_type i = 0; i < m_ipvt.numel (); i++)\n        {\n          octave_idx_type k = m_ipvt.xelem (i);\n\n          if (k != i)\n            {\n              octave_idx_type tmp = pvt.xelem (k);\n              pvt.xelem (k) = pvt.xelem (i);\n              pvt.xelem (i) = tmp;\n            }\n        }\n\n      return pvt;\n    }\n  else\n    return m_ipvt;\n}\n\ntemplate <typename T>\nPermMatrix\nlu<T>::P () const\n{\n  return PermMatrix (getp (), false);\n}\n\ntemplate <typename T>\nColumnVector\nlu<T>::P_vec () const\n{\n  octave_idx_type a_nr = m_a_fact.rows ();\n\n  ColumnVector p (a_nr);\n\n  Array<octave_idx_type> pvt = getp ();\n\n  for (octave_idx_type i = 0; i < a_nr; i++)\n    p.xelem (i) = static_cast<double> (pvt.xelem (i) + 1);\n\n  return p;\n}\n\ntemplate <typename T>\nbool\nlu<T>::regular () const\n{\n  bool retval = true;\n\n  octave_idx_type k = std::min (m_a_fact.rows (), m_a_fact.columns ());\n\n  for (octave_idx_type i = 0; i < k; i++)\n    {\n      if (m_a_fact(i, i) == ELT_T ())\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\n#if ! defined (HAVE_QRUPDATE_LUU)\n\ntemplate <typename T>\nvoid\nlu<T>::update (const VT&, const VT&)\n{\n  (*current_liboctave_error_handler)\n    (\"luupdate: support for qrupdate with LU updates \"\n     \"was unavailable or disabled when liboctave was built\");\n}\n\ntemplate <typename T>\nvoid\nlu<T>::update (const T&, const T&)\n{\n  (*current_liboctave_error_handler)\n    (\"luupdate: support for qrupdate with LU updates \"\n     \"was unavailable or disabled when liboctave was built\");\n}\n\ntemplate <typename T>\nvoid\nlu<T>::update_piv (const VT&, const VT&)\n{\n  (*current_liboctave_error_handler)\n    (\"luupdate: support for qrupdate with LU updates \"\n     \"was unavailable or disabled when liboctave was built\");\n}\n\ntemplate <typename T>\nvoid\nlu<T>::update_piv (const T&, const T&)\n{\n  (*current_liboctave_error_handler)\n    (\"luupdate: support for qrupdate with LU updates \"\n     \"was unavailable or disabled when liboctave was built\");\n}\n\n#endif\n\n// Specializations.\n\ntemplate <>\nOCTAVE_API\nlu<Matrix>::lu (const Matrix& a)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.columns ());\n  F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);\n\n  m_ipvt.resize (dim_vector (mn, 1));\n  F77_INT *pipvt = m_ipvt.rwdata ();\n\n  m_a_fact = a;\n  double *tmp_data = m_a_fact.rwdata ();\n\n  F77_INT info = 0;\n\n  F77_XFCN (dgetrf, DGETRF, (a_nr, a_nc, tmp_data, a_nr, pipvt, info));\n\n  for (F77_INT i = 0; i < mn; i++)\n    pipvt[i] -= 1;\n}\n\n#if defined (HAVE_QRUPDATE_LUU)\n\ntemplate <>\nOCTAVE_API void\nlu<Matrix>::update (const ColumnVector& u, const ColumnVector& v)\n{\n  if (packed ())\n    unpack ();\n\n  Matrix& l = m_L;\n  Matrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  std::vector<double> utmp (u.data (), u.data () + u.numel ());\n  std::vector<double> vtmp (v.data (), v.data () + v.numel ());\n  F77_XFCN (dlu1up, DLU1UP, (m, n, l.rwdata (), m, r.rwdata (),\n                             k, utmp.data (), vtmp.data ()));\n}\n\ntemplate <>\nOCTAVE_API void\nlu<Matrix>::update (const Matrix& u, const Matrix& v)\n{\n  if (packed ())\n    unpack ();\n\n  Matrix& l = m_L;\n  Matrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nr = to_f77_int (u.rows ());\n  F77_INT u_nc = to_f77_int (u.columns ());\n\n  F77_INT v_nr = to_f77_int (v.rows ());\n  F77_INT v_nc = to_f77_int (v.columns ());\n\n  if (u_nr != m || v_nr != n || u_nc != v_nc)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  for (F77_INT i = 0; i < u_nc; i++)\n    {\n      std::vector<double> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      std::vector<double> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (dlu1up, DLU1UP, (m, n, l.rwdata (),\n                                 m, r.rwdata (), k,\n                                 utmp.data (), vtmp.data ()));\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nlu<Matrix>::update_piv (const ColumnVector& u, const ColumnVector& v)\n{\n  if (packed ())\n    unpack ();\n\n  Matrix& l = m_L;\n  Matrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  const std::vector<double> utmp (u.data (), u.data () + u.numel ());\n  const std::vector<double> vtmp (v.data (), v.data () + v.numel ());\n  OCTAVE_LOCAL_BUFFER (double, w, m);\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment\n  F77_XFCN (dlup1up, DLUP1UP, (m, n, l.rwdata (),\n                               m, r.rwdata (), k,\n                               m_ipvt.rwdata (),\n                               utmp.data (), vtmp.data (), w));\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement\n}\n\ntemplate <>\nOCTAVE_API void\nlu<Matrix>::update_piv (const Matrix& u, const Matrix& v)\n{\n  if (packed ())\n    unpack ();\n\n  Matrix& l = m_L;\n  Matrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nr = to_f77_int (u.rows ());\n  F77_INT u_nc = to_f77_int (u.columns ());\n\n  F77_INT v_nr = to_f77_int (v.rows ());\n  F77_INT v_nc = to_f77_int (v.columns ());\n\n  if (u_nr != m || v_nr != n || u_nc != v_nc)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  OCTAVE_LOCAL_BUFFER (double, w, m);\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment\n  for (F77_INT i = 0; i < u_nc; i++)\n    {\n      const std::vector<double> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      const std::vector<double> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (dlup1up, DLUP1UP, (m, n, l.rwdata (),\n                                   m, r.rwdata (), k,\n                                   m_ipvt.rwdata (),\n                                   utmp.data (), vtmp.data (), w));\n    }\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement\n}\n\n#endif\n\ntemplate <>\nOCTAVE_API\nlu<FloatMatrix>::lu (const FloatMatrix& a)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.columns ());\n  F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);\n\n  m_ipvt.resize (dim_vector (mn, 1));\n  F77_INT *pipvt = m_ipvt.rwdata ();\n\n  m_a_fact = a;\n  float *tmp_data = m_a_fact.rwdata ();\n\n  F77_INT info = 0;\n\n  F77_XFCN (sgetrf, SGETRF, (a_nr, a_nc, tmp_data, a_nr, pipvt, info));\n\n  for (F77_INT i = 0; i < mn; i++)\n    pipvt[i] -= 1;\n}\n\n#if defined (HAVE_QRUPDATE_LUU)\n\ntemplate <>\nOCTAVE_API void\nlu<FloatMatrix>::update (const FloatColumnVector& u,\n                         const FloatColumnVector& v)\n{\n  if (packed ())\n    unpack ();\n\n  FloatMatrix& l = m_L;\n  FloatMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  std::vector<float> utmp (u.data (), u.data () + u.numel ());\n  std::vector<float> vtmp (v.data (), v.data () + v.numel ());\n  F77_XFCN (slu1up, SLU1UP, (m, n, l.rwdata (),\n                             m, r.rwdata (), k,\n                             utmp.data (), vtmp.data ()));\n}\n\ntemplate <>\nOCTAVE_API void\nlu<FloatMatrix>::update (const FloatMatrix& u, const FloatMatrix& v)\n{\n  if (packed ())\n    unpack ();\n\n  FloatMatrix& l = m_L;\n  FloatMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nr = to_f77_int (u.rows ());\n  F77_INT u_nc = to_f77_int (u.columns ());\n\n  F77_INT v_nr = to_f77_int (v.rows ());\n  F77_INT v_nc = to_f77_int (v.columns ());\n\n  if (u_nr != m || v_nr != n || u_nc != v_nc)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  for (F77_INT i = 0; i < u_nc; i++)\n    {\n      std::vector<float> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      std::vector<float> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (slu1up, SLU1UP, (m, n, l.rwdata (),\n                                 m, r.rwdata (), k,\n                                 utmp.data (), vtmp.data ()));\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nlu<FloatMatrix>::update_piv (const FloatColumnVector& u,\n                             const FloatColumnVector& v)\n{\n  if (packed ())\n    unpack ();\n\n  FloatMatrix& l = m_L;\n  FloatMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  const std::vector<float> utmp (u.data (), u.data () + u.numel ());\n  const std::vector<float> vtmp (v.data (), v.data () + v.numel ());\n  OCTAVE_LOCAL_BUFFER (float, w, m);\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment\n  F77_XFCN (slup1up, SLUP1UP, (m, n, l.rwdata (),\n                               m, r.rwdata (), k,\n                               m_ipvt.rwdata (),\n                               utmp.data (), vtmp.data (), w));\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement\n}\n\ntemplate <>\nOCTAVE_API void\nlu<FloatMatrix>::update_piv (const FloatMatrix& u, const FloatMatrix& v)\n{\n  if (packed ())\n    unpack ();\n\n  FloatMatrix& l = m_L;\n  FloatMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nr = to_f77_int (u.rows ());\n  F77_INT u_nc = to_f77_int (u.columns ());\n\n  F77_INT v_nr = to_f77_int (v.rows ());\n  F77_INT v_nc = to_f77_int (v.columns ());\n\n  if (u_nr != m || v_nr != n || u_nc != v_nc)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  OCTAVE_LOCAL_BUFFER (float, w, m);\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment\n  for (F77_INT i = 0; i < u_nc; i++)\n    {\n      const std::vector<float> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      const std::vector<float> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (slup1up, SLUP1UP, (m, n, l.rwdata (),\n                                   m, r.rwdata (), k,\n                                   m_ipvt.rwdata (),\n                                   utmp.data (), vtmp.data (), w));\n    }\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement\n}\n\n#endif\n\ntemplate <>\nOCTAVE_API\nlu<ComplexMatrix>::lu (const ComplexMatrix& a)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.columns ());\n  F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);\n\n  m_ipvt.resize (dim_vector (mn, 1));\n  F77_INT *pipvt = m_ipvt.rwdata ();\n\n  m_a_fact = a;\n  Complex *tmp_data = m_a_fact.rwdata ();\n\n  F77_INT info = 0;\n\n  F77_XFCN (zgetrf, ZGETRF, (a_nr, a_nc, F77_DBLE_CMPLX_ARG (tmp_data),\n                             a_nr, pipvt, info));\n\n  for (F77_INT i = 0; i < mn; i++)\n    pipvt[i] -= 1;\n}\n\n#if defined (HAVE_QRUPDATE_LUU)\n\ntemplate <>\nOCTAVE_API void\nlu<ComplexMatrix>::update (const ComplexColumnVector& u,\n                           const ComplexColumnVector& v)\n{\n  if (packed ())\n    unpack ();\n\n  ComplexMatrix& l = m_L;\n  ComplexMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  std::vector<Complex> utmp (u.data (), u.data () + u.numel ());\n  std::vector<Complex> vtmp (v.data (), v.data () + v.numel ());\n  F77_XFCN (zlu1up, ZLU1UP, (m, n, F77_DBLE_CMPLX_ARG (l.rwdata ()), m,\n                             F77_DBLE_CMPLX_ARG (r.rwdata ()), k,\n                             F77_DBLE_CMPLX_ARG (utmp.data ()),\n                             F77_DBLE_CMPLX_ARG (vtmp.data ())));\n}\n\ntemplate <>\nOCTAVE_API void\nlu<ComplexMatrix>::update (const ComplexMatrix& u, const ComplexMatrix& v)\n{\n  if (packed ())\n    unpack ();\n\n  ComplexMatrix& l = m_L;\n  ComplexMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nr = to_f77_int (u.rows ());\n  F77_INT u_nc = to_f77_int (u.columns ());\n\n  F77_INT v_nr = to_f77_int (v.rows ());\n  F77_INT v_nc = to_f77_int (v.columns ());\n\n  if (u_nr != m || v_nr != n || u_nc != v_nc)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  for (F77_INT i = 0; i < u_nc; i++)\n    {\n      std::vector<Complex> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      std::vector<Complex> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (zlu1up, ZLU1UP, (m, n,\n                                 F77_DBLE_CMPLX_ARG (l.rwdata ()),\n                                 m, F77_DBLE_CMPLX_ARG (r.rwdata ()),\n                                 k,\n                                 F77_DBLE_CMPLX_ARG (utmp.data ()),\n                                 F77_DBLE_CMPLX_ARG (vtmp.data ())));\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nlu<ComplexMatrix>::update_piv (const ComplexColumnVector& u,\n                               const ComplexColumnVector& v)\n{\n  if (packed ())\n    unpack ();\n\n  ComplexMatrix& l = m_L;\n  ComplexMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  const std::vector<Complex> utmp (u.data (), u.data () + u.numel ());\n  const std::vector<Complex> vtmp (v.data (), v.data () + v.numel ());\n  OCTAVE_LOCAL_BUFFER (Complex, w, m);\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment\n  F77_XFCN (zlup1up, ZLUP1UP, (m, n, F77_DBLE_CMPLX_ARG (l.rwdata ()),\n                               m, F77_DBLE_CMPLX_ARG (r.rwdata ()), k,\n                               m_ipvt.rwdata (),\n                               F77_CONST_DBLE_CMPLX_ARG (utmp.data ()),\n                               F77_CONST_DBLE_CMPLX_ARG (vtmp.data ()),\n                               F77_DBLE_CMPLX_ARG (w)));\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement\n}\n\ntemplate <>\nOCTAVE_API void\nlu<ComplexMatrix>::update_piv (const ComplexMatrix& u,\n                               const ComplexMatrix& v)\n{\n  if (packed ())\n    unpack ();\n\n  ComplexMatrix& l = m_L;\n  ComplexMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nr = to_f77_int (u.rows ());\n  F77_INT u_nc = to_f77_int (u.columns ());\n\n  F77_INT v_nr = to_f77_int (v.rows ());\n  F77_INT v_nc = to_f77_int (v.columns ());\n\n  if (u_nr != m || v_nr != n || u_nc != v_nc)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  OCTAVE_LOCAL_BUFFER (Complex, w, m);\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment\n  for (F77_INT i = 0; i < u_nc; i++)\n    {\n      const std::vector<Complex> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      const std::vector<Complex> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (zlup1up, ZLUP1UP, (m, n,\n                                   F77_DBLE_CMPLX_ARG (l.rwdata ()),\n                                   m,\n                                   F77_DBLE_CMPLX_ARG (r.rwdata ()),\n                                   k, m_ipvt.rwdata (),\n                                   F77_CONST_DBLE_CMPLX_ARG (utmp.data ()),\n                                   F77_CONST_DBLE_CMPLX_ARG (vtmp.data ()),\n                                   F77_DBLE_CMPLX_ARG (w)));\n    }\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement\n}\n\n#endif\n\ntemplate <>\nOCTAVE_API\nlu<FloatComplexMatrix>::lu (const FloatComplexMatrix& a)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.columns ());\n  F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);\n\n  m_ipvt.resize (dim_vector (mn, 1));\n  F77_INT *pipvt = m_ipvt.rwdata ();\n\n  m_a_fact = a;\n  FloatComplex *tmp_data = m_a_fact.rwdata ();\n\n  F77_INT info = 0;\n\n  F77_XFCN (cgetrf, CGETRF, (a_nr, a_nc, F77_CMPLX_ARG (tmp_data), a_nr,\n                             pipvt, info));\n\n  for (F77_INT i = 0; i < mn; i++)\n    pipvt[i] -= 1;\n}\n\n#if defined (HAVE_QRUPDATE_LUU)\n\ntemplate <>\nOCTAVE_API void\nlu<FloatComplexMatrix>::update (const FloatComplexColumnVector& u,\n                                const FloatComplexColumnVector& v)\n{\n  if (packed ())\n    unpack ();\n\n  FloatComplexMatrix& l = m_L;\n  FloatComplexMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  std::vector<FloatComplex> utmp (u.data (), u.data () + u.numel ());\n  std::vector<FloatComplex> vtmp (v.data (), v.data () + v.numel ());\n  F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.rwdata ()), m,\n                             F77_CMPLX_ARG (r.rwdata ()), k,\n                             F77_CMPLX_ARG (utmp.data ()),\n                             F77_CMPLX_ARG (vtmp.data ())));\n}\n\ntemplate <>\nOCTAVE_API void\nlu<FloatComplexMatrix>::update (const FloatComplexMatrix& u,\n                                const FloatComplexMatrix& v)\n{\n  if (packed ())\n    unpack ();\n\n  FloatComplexMatrix& l = m_L;\n  FloatComplexMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nr = to_f77_int (u.rows ());\n  F77_INT u_nc = to_f77_int (u.columns ());\n\n  F77_INT v_nr = to_f77_int (v.rows ());\n  F77_INT v_nc = to_f77_int (v.columns ());\n\n  if (u_nr != m || v_nr != n || u_nc != v_nc)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  for (F77_INT i = 0; i < u_nc; i++)\n    {\n      std::vector<FloatComplex> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      std::vector<FloatComplex> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.rwdata ()),\n                                 m, F77_CMPLX_ARG (r.rwdata ()), k,\n                                 F77_CMPLX_ARG (utmp.data ()),\n                                 F77_CMPLX_ARG (vtmp.data ())));\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nlu<FloatComplexMatrix>::update_piv (const FloatComplexColumnVector& u,\n                                    const FloatComplexColumnVector& v)\n{\n  if (packed ())\n    unpack ();\n\n  FloatComplexMatrix& l = m_L;\n  FloatComplexMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  const std::vector<FloatComplex> utmp (u.data (), u.data () + u.numel ());\n  const std::vector<FloatComplex> vtmp (v.data (), v.data () + v.numel ());\n  OCTAVE_LOCAL_BUFFER (FloatComplex, w, m);\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment\n  F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.rwdata ()),\n                               m, F77_CMPLX_ARG (r.rwdata ()), k,\n                               m_ipvt.rwdata (),\n                               F77_CONST_CMPLX_ARG (utmp.data ()),\n                               F77_CONST_CMPLX_ARG (vtmp.data ()),\n                               F77_CMPLX_ARG (w)));\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement\n}\n\ntemplate <>\nOCTAVE_API void\nlu<FloatComplexMatrix>::update_piv (const FloatComplexMatrix& u,\n                                    const FloatComplexMatrix& v)\n{\n  if (packed ())\n    unpack ();\n\n  FloatComplexMatrix& l = m_L;\n  FloatComplexMatrix& r = m_a_fact;\n\n  F77_INT m = to_f77_int (l.rows ());\n  F77_INT n = to_f77_int (r.columns ());\n  F77_INT k = to_f77_int (l.columns ());\n\n  F77_INT u_nr = to_f77_int (u.rows ());\n  F77_INT u_nc = to_f77_int (u.columns ());\n\n  F77_INT v_nr = to_f77_int (v.rows ());\n  F77_INT v_nc = to_f77_int (v.columns ());\n\n  if (u_nr != m || v_nr != n || u_nc != v_nc)\n    (*current_liboctave_error_handler) (\"luupdate: dimensions mismatch\");\n\n  OCTAVE_LOCAL_BUFFER (FloatComplex, w, m);\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment\n  for (F77_INT i = 0; i < u_nc; i++)\n    {\n      const std::vector<FloatComplex> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      const std::vector<FloatComplex> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.rwdata ()),\n                                   m, F77_CMPLX_ARG (r.rwdata ()), k,\n                                   m_ipvt.rwdata (),\n                                   F77_CONST_CMPLX_ARG (utmp.data ()),\n                                   F77_CONST_CMPLX_ARG (vtmp.data ()),\n                                   F77_CMPLX_ARG (w)));\n    }\n  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement\n}\n\n#endif\n\n// Instantiations we need.\n\ntemplate class lu<Matrix>;\n\ntemplate class lu<FloatMatrix>;\n\ntemplate class lu<ComplexMatrix>;\n\ntemplate class lu<FloatComplexMatrix>;\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/lu.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lu_h)\n#define octave_lu_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\n#include \"Array-oct.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nclass lu\n{\npublic:\n\n  typedef typename T::column_vector_type VT;\n  typedef typename T::element_type ELT_T;\n\n  lu ()\n    : m_a_fact (), m_L (), m_ipvt () { }\n\n  OCTAVE_API lu (const T& a);\n\n  lu (const lu& a)\n    : m_a_fact (a.m_a_fact), m_L (a.m_L), m_ipvt (a.m_ipvt) { }\n\n  OCTAVE_API lu (const T& l, const T& u, const PermMatrix& p);\n\n  lu& operator = (const lu& a)\n  {\n    if (this != &a)\n      {\n        m_a_fact = a.m_a_fact;\n        m_L = a.m_L;\n        m_ipvt = a.m_ipvt;\n      }\n\n    return *this;\n  }\n\n  virtual ~lu () = default;\n\n  OCTAVE_API bool packed () const;\n\n  OCTAVE_API void unpack ();\n\n  OCTAVE_API T L () const;\n\n  OCTAVE_API T U () const;\n\n  OCTAVE_API T Y () const;\n\n  OCTAVE_API PermMatrix P () const;\n\n  OCTAVE_API ColumnVector P_vec () const;\n\n  OCTAVE_API bool regular () const;\n\n  OCTAVE_API void update (const VT& u, const VT& v);\n\n  OCTAVE_API void update (const T& u, const T& v);\n\n  OCTAVE_API void update_piv (const VT& u, const VT& v);\n\n  OCTAVE_API void update_piv (const T& u, const T& v);\n\nprotected:\n\n  // The result of getp is passed to other Octave Matrix functions,\n  // so we use octave_idx_type.\n  OCTAVE_API Array<octave_idx_type> getp () const;\n\n  T m_a_fact;\n  T m_L;\n\n  // This is internal storage that is passed to Fortran,\n  // so we need a Fortran INTEGER.\n  Array<octave_f77_int_type> m_ipvt;\n};\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/mappers.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"mappers.h\"\n#include \"math-wrappers.h\"\n#include \"oct-specfun.h\"\n\n// FIXME: We used to have this situation:\n//\n//   Functions that forward to gnulib belong here so we can keep\n//   gnulib:: out of mappers.h.\n//\n// but now we just use std:: and explicit wrappers in C++ code so maybe\n// some of the forwarding functions can be defined inline here.\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\nbool\nisna (double x)\n{\n  return lo_ieee_is_NA (x);\n}\n\nbool\nisna (const Complex& x)\n{\n  return (isna (std::real (x)) || isna (std::imag (x)));\n}\n\nbool\nisna (float x)\n{\n  return lo_ieee_is_NA (x);\n}\n\nbool\nisna (const FloatComplex& x)\n{\n  return (isna (std::real (x)) || isna (std::imag (x)));\n}\n\nbool\nis_NaN_or_NA (const Complex& x)\n{\n  return (isnan (std::real (x)) || isnan (std::imag (x)));\n}\n\nbool\nis_NaN_or_NA (const FloatComplex& x)\n{\n  return (isnan (std::real (x)) || isnan (std::imag (x)));\n}\n\n// Matlab returns a different phase for acos, asin then std library\n// which requires a small function to remap the phase.\nComplex\nacos (const Complex& x)\n{\n  Complex y = std::acos (x);\n\n  if (std::imag (x) == 0.0 && std::real (x) > 1.0)\n    return std::conj (y);\n  else\n    return y;\n}\n\nFloatComplex\nacos (const FloatComplex& x)\n{\n  FloatComplex y = std::acos (x);\n\n  if (std::imag (x) == 0.0f && std::real (x) > 1.0f)\n    return std::conj (y);\n  else\n    return y;\n}\n\nComplex\nasin (const Complex& x)\n{\n  Complex y = std::asin (x);\n\n  if (std::imag (x) == 0.0 && std::real (x) > 1.0)\n    return std::conj (y);\n  else\n    return y;\n}\n\nFloatComplex\nasin (const FloatComplex& x)\n{\n  FloatComplex y = std::asin (x);\n\n  if (std::imag (x) == 0.0f && std::real (x) > 1.0f)\n    return std::conj (y);\n  else\n    return y;\n}\n\ndouble\nfrexp (double x, int *expptr)\n{\n  return octave_frexp_wrapper (x, expptr);\n}\n\nfloat\nfrexp (float x, int *expptr)\n{\n  return octave_frexpf_wrapper (x, expptr);\n}\n\nComplex\nlog2 (const Complex& x)\n{\n  return std::log (x) / M_LN2;\n}\n\nFloatComplex\nlog2 (const FloatComplex& x)\n{\n  return std::log (x) / static_cast<float> (M_LN2);\n}\n\ndouble\nlog2 (double x, int& exp)\n{\n  return frexp (x, &exp);\n}\n\nfloat\nlog2 (float x, int& exp)\n{\n  return frexp (x, &exp);\n}\n\nComplex\nlog2 (const Complex& x, int& exp)\n{\n  double ax = std::abs (x);\n  double lax = log2 (ax, exp);\n  return (ax != lax) ? (x / ax) * lax : x;\n}\n\nFloatComplex\nlog2 (const FloatComplex& x, int& exp)\n{\n  float ax = std::abs (x);\n  float lax = log2 (ax, exp);\n  return (ax != lax) ? (x / ax) * lax : x;\n}\n\nbool\nnegative_sign (double x) { return signbit (x); }\nbool\nnegative_sign (float x) { return signbit (x); }\n\n// Sometimes you need a large integer, but not always.\n\noctave_idx_type\nnint_big (double x)\n{\n  static constexpr double out_of_range_top\n    = static_cast<double> (std::numeric_limits<octave_idx_type>::max ()) + 1.0;\n\n  if (x >= out_of_range_top)\n    return std::numeric_limits<octave_idx_type>::max ();\n  else if (x < std::numeric_limits<octave_idx_type>::min ())\n    return std::numeric_limits<octave_idx_type>::min ();\n  else\n    return static_cast<octave_idx_type> (round (x));\n}\n\noctave_idx_type\nnint_big (float x)\n{\n  static constexpr float out_of_range_top\n    = static_cast<float> (std::numeric_limits<octave_idx_type>::max ()) + 1.0;\n\n  if (x >= out_of_range_top)\n    return std::numeric_limits<octave_idx_type>::max ();\n  else if (x < std::numeric_limits<octave_idx_type>::min ())\n    return std::numeric_limits<octave_idx_type>::min ();\n  else\n    return static_cast<octave_idx_type> (round (x));\n}\n\nint\nnint (double x)\n{\n  if (x > std::numeric_limits<int>::max ())\n    return std::numeric_limits<int>::max ();\n  else if (x < std::numeric_limits<int>::min ())\n    return std::numeric_limits<int>::min ();\n  else\n    return static_cast<int> (round (x));\n}\n\nint\nnint (float x)\n{\n  static constexpr float out_of_range_top\n    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.0;\n\n  if (x >= out_of_range_top)\n    return std::numeric_limits<int>::max ();\n  else if (x < std::numeric_limits<int>::min ())\n    return std::numeric_limits<int>::min ();\n  else\n    return static_cast<int> (round (x));\n}\n\nComplex\nrc_acos (double x)\n{\n  return fabs (x) > 1.0 ? acos (Complex (x)) : Complex (std::acos (x));\n}\n\nFloatComplex\nrc_acos (float x)\n{\n  return fabsf (x) > 1.0f ? acos (FloatComplex (x))\n                          : FloatComplex (std::acos (x));\n}\n\nComplex\nrc_acosh (double x)\n{\n  return x < 1.0 ? acosh (Complex (x)) : Complex (acosh (x));\n}\n\nFloatComplex\nrc_acosh (float x)\n{\n  return x < 1.0f ? acosh (FloatComplex (x)) : FloatComplex (acosh (x));\n}\n\nComplex\nrc_asin (double x)\n{\n  return fabs (x) > 1.0 ? asin (Complex (x)) : Complex (std::asin (x));\n}\n\nFloatComplex\nrc_asin (float x)\n{\n  return fabsf (x) > 1.0f ? asin (FloatComplex (x))\n                          : FloatComplex (::asinf (x));\n}\n\nComplex\nrc_atanh (double x)\n{\n  return fabs (x) > 1.0 ? atanh (Complex (x)) : Complex (atanh (x));\n}\n\nFloatComplex\nrc_atanh (float x)\n{\n  return fabsf (x) > 1.0f ? atanh (FloatComplex (x))\n                          : FloatComplex (atanh (x));\n}\n\nComplex\nrc_log (double x)\n{\n  return x < 0.0 ? Complex (std::log (-x), M_PI) : Complex (std::log (x));\n}\n\nFloatComplex\nrc_log (float x)\n{\n  return x < 0.0f ? FloatComplex (std::log (-x), static_cast<float> (M_PI))\n                  : FloatComplex (std::log (x));\n}\n\nComplex\nrc_log2 (double x)\n{\n  constexpr double PI_LN2 = 4.53236014182719380962;  // = pi / log(2)\n  return x < 0.0 ? Complex (log2 (-x), PI_LN2) : Complex (log2 (x));\n}\n\nFloatComplex\nrc_log2 (float x)\n{\n  constexpr float PI_LN2 = 4.53236014182719380962f;  // = pi / log(2)\n  return x < 0.0f ? FloatComplex (log2 (-x), PI_LN2)\n                  : FloatComplex (log2 (x));\n}\n\nComplex\nrc_log10 (double x)\n{\n  constexpr double PI_LN10 = 1.36437635384184134748;  // = pi / log(10)\n  return x < 0.0 ? Complex (log10 (-x), PI_LN10) : Complex (log10 (x));\n}\n\nFloatComplex\nrc_log10 (float x)\n{\n  constexpr float PI_LN10 = 1.36437635384184134748f;  // = pi / log(10)\n  return x < 0.0f ? FloatComplex (log10 (-x), PI_LN10)\n                  : FloatComplex (log10f (x));\n}\n\nComplex\nrc_sqrt (double x)\n{\n  return x < 0.0 ? Complex (0.0, std::sqrt (-x)) : Complex (std::sqrt (x));\n}\n\nFloatComplex\nrc_sqrt (float x)\n{\n  return x < 0.0f ? FloatComplex (0.0f, std::sqrt (-x))\n                  : FloatComplex (std::sqrt (x));\n}\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/mappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_mappers_h)\n#define octave_oct_mappers_h 1\n\n#include \"octave-config.h\"\n\n#include <cmath>\n\n#include <limits>\n\n#include \"lo-ieee.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-inttypes-fwd.h\"\n\n// Provides some commonly repeated, basic loop templates.\n\n// Specialization for octave_int types\ntemplate <typename T>\ninline auto mappers_abs (const octave_int<T>& x)\n{\n    if constexpr (std::is_unsigned_v<T>)\n        return x;  // abs doesn't make sense for unsigned types\n    else\n        return std::abs (x.value ());\n}\n\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\nextern OCTAVE_API bool isna (double x);\nextern OCTAVE_API bool isna (float x);\nextern OCTAVE_API bool isna (const Complex& x);\nextern OCTAVE_API bool isna (const FloatComplex& x);\n\nextern OCTAVE_API bool is_NaN_or_NA (const Complex& x);\nextern OCTAVE_API bool is_NaN_or_NA (const FloatComplex& x);\n\ninline double copysign (double x, double y) { return std::copysign (x, y); }\ninline float copysign (float x, float y) { return std::copysignf (x, y); }\n\ninline double signbit (double x) { return std::signbit (x); }\ninline float signbit (float x) { return std::signbit (x); }\n\n// Test for negative sign.\nextern OCTAVE_API bool negative_sign (double x);\nextern OCTAVE_API bool negative_sign (float x);\n\n// Test for positive sign.\ninline bool positive_sign (double x) { return ! negative_sign (x); }\ninline bool positive_sign (float x) { return ! negative_sign (x); }\n\nextern OCTAVE_API Complex acos (const Complex& x);\nextern OCTAVE_API FloatComplex acos (const FloatComplex& x);\n\nextern OCTAVE_API Complex asin (const Complex& x);\nextern OCTAVE_API FloatComplex asin (const FloatComplex& x);\n\ninline Complex atan (const Complex& x) { return std::atan (x); }\ninline FloatComplex atan (const FloatComplex& x) { return std::atan (x); }\n\n// The C++ standard would normally return a std::complex value for conj\n// even when the input is fully real.  Octave overrides this.\ninline double conj (double x) { return x; }\ninline float conj (float x) { return x; }\n\ntemplate <typename T>\nstd::complex<T>\nconj (const std::complex<T>& x)\n{\n  return std::conj (x);\n}\n\ninline double log2 (double x) { return std::log2 (x); }\ninline float log2 (float x) { return std::log2f (x); }\n\nextern OCTAVE_API Complex log2 (const Complex& x);\nextern OCTAVE_API FloatComplex log2 (const FloatComplex& x);\n\nextern OCTAVE_API double log2 (double x, int& exp);\nextern OCTAVE_API float log2 (float x, int& exp);\n\nextern OCTAVE_API Complex log2 (const Complex& x, int& exp);\nextern OCTAVE_API FloatComplex log2 (const FloatComplex& x, int& exp);\n\ninline double exp2 (double x) { return std::exp2 (x); }\ninline float exp2 (float x) { return std::exp2f (x); }\n\ntemplate <typename T>\nstd::complex<T>\nceil (const std::complex<T>& x)\n{\n  return std::complex<T> (std::ceil (std::real (x)),\n                          std::ceil (std::imag (x)));\n}\n\ntemplate <typename T>\nstd::complex<T>\ntrunc (const std::complex<T>& x)\n{\n  return std::complex<T> (std::trunc (std::real (x)),\n                          std::trunc (std::imag (x)));\n}\n\n// Provide alias for trunc under the more familiar name of fix.\ninline double fix (double x) { return std::trunc (x); }\ninline float fix (float x) { return std::trunc (x); }\n\ntemplate <typename T>\nstd::complex<T>\nfix (const std::complex<T>& x)\n{\n  return trunc (x);\n}\n\ntemplate <typename T>\nstd::complex<T>\nfloor (const std::complex<T>& x)\n{\n  return std::complex<T> (std::floor (std::real (x)),\n                          std::floor (std::imag (x)));\n}\n\ninline double round (double x) { return std::round (x); }\ninline float round (float x) { return std::roundf (x); }\n\ntemplate <typename T>\nstd::complex<T>\nround (const std::complex<T>& x)\n{\n  return std::complex<T> (round (std::real (x)), round (std::imag (x)));\n}\n\ninline double\nroundb (double x)\n{\n  double t = round (x);\n\n  if (fabs (x - t) == 0.5)\n    t = 2 * std::trunc (0.5 * t);\n\n  return t;\n}\n\ninline float\nroundb (float x)\n{\n  float t = round (x);\n\n  if (fabsf (x - t) == 0.5f)\n    t = 2 * std::trunc (0.5f * t);\n\n  return t;\n}\n\ntemplate <typename T>\nstd::complex<T>\nroundb (const std::complex<T>& x)\n{\n  return std::complex<T> (roundb (std::real (x)), roundb (std::imag (x)));\n}\n\nextern OCTAVE_API double frexp (double x, int *expptr);\nextern OCTAVE_API float frexp (float x, int *expptr);\n\n// Functions testing for NaN, Inf, and finite elements\n\ninline bool isnan (bool) { return false; }\ninline bool isnan (char) { return false; }\n\ninline bool isnan (double x) { return std::isnan (x); }\ninline bool isnan (float x) { return std::isnan (x); }\n\ntemplate <typename T>\nbool\nisnan (const octave_int<T>&)\n{\n  return false;\n}\n\ntemplate <typename T>\nbool\nisnan (const std::complex<T>& x)\n{\n  return (std::isnan (std::real (x)) || std::isnan (std::imag (x)));\n}\n\ninline bool isinf (double x) { return std::isinf (x); }\ninline bool isinf (float x) { return std::isinf (x); }\n\ntemplate <typename T>\nbool\nisinf (const octave_int<T>&)\n{\n  return false;\n}\n\ntemplate <typename T>\nbool\nisinf (const std::complex<T>& x)\n{\n  return (std::isinf (std::real (x)) || std::isinf (std::imag (x)));\n}\n\ninline bool isfinite (double x) { return std::isfinite (x); }\ninline bool isfinite (float x) { return std::isfinite (x); }\n\ntemplate <typename T>\nbool\nisfinite (const std::complex<T>& x)\n{\n  return (isfinite (std::real (x)) && isfinite (std::imag (x)));\n}\n\n// Some useful tests, that are commonly repeated.\n// Test for a finite integer.\n\n// A large benchmark of std::round vs std::trunc showed that trunc was some\n// 3 times faster than round, taking some 1.4 nanoseconds for trunc and\n// some 4.1 nanoseconds for round.\ninline bool is_integer (double x) { return isfinite (x) && x == std::trunc (x); }\ninline bool is_integer (float x) { return isfinite (x) && x == std::trunc (x); }\n\nOCTAVE_DEPRECATED (11, \"use octave::math::is_integer instead\")\ninline bool isinteger (double x) { return is_integer (x); }\n\nOCTAVE_DEPRECATED (11, \"use octave::math::is_integer instead\")\ninline bool isinteger (float x) { return is_integer (x); }\n\ninline double\nsignum (double x)\n{\n  double tmp = 0.0;\n\n  if (x < 0.0)\n    tmp = -1.0;\n  else if (x > 0.0)\n    tmp = 1.0;\n\n  return isnan (x) ? numeric_limits<double>::NaN () : tmp;\n}\n\ninline float\nsignum (float x)\n{\n  float tmp = 0.0f;\n\n  if (x < 0.0f)\n    tmp = -1.0f;\n  else if (x > 0.0f)\n    tmp = 1.0f;\n\n  return isnan (x) ? numeric_limits<float>::NaN () : tmp;\n}\n\ntemplate <typename T>\nstd::complex<T>\nsignum (const std::complex<T>& x)\n{\n  T tmp = std::abs (x);\n\n  return tmp == 0 ? 0.0 : x / tmp;\n}\n\n// FIXME: Deprecated in Octave 11.  Remove in Octave 13.\n// Convert X to the nearest integer value.  Should not pass NaN to\n// this function.\n\n// For integer types?  Hmm.  Need to be sure T is an integer type...\ntemplate <typename T>\nOCTAVE_DEPRECATED (11, \"use octave::math::round instead\")\nT\nx_nint (T x)\n{\n  return x;\n}\n\ntemplate <>\nOCTAVE_DEPRECATED (11, \"use octave::math::round instead\")\ninline double x_nint (double x)\n{\n  return round (x);\n}\n\ntemplate <>\nOCTAVE_DEPRECATED (11, \"use octave::math::round instead\")\ninline float x_nint (float x)\n{\n  return round (x);\n}\n\nextern OCTAVE_API octave_idx_type nint_big (double x);\nextern OCTAVE_API octave_idx_type nint_big (float x);\n\nextern OCTAVE_API int nint (double x);\nextern OCTAVE_API int nint (float x);\n\ntemplate <typename T>\nT\nmod (T x, T y)\n{\n  T retval;\n\n  if (y == 0)\n    retval = x;\n  else\n    {\n      T q = x / y;\n\n      if (round (y) != y\n          && (std::abs ((q - round (q)) / round (q))\n              < std::numeric_limits<T>::epsilon ()))\n        retval = 0;\n      else\n        {\n          T n = std::floor (q);\n\n          // Prevent use of extra precision.\n          T tmp = y * n;\n\n          retval = x - tmp;\n        }\n    }\n\n  if (x != y && y != 0)\n    retval = copysign (retval, y);\n\n  return retval;\n}\n\ntemplate <typename T>\nT\nrem (T x, T y)\n{\n  T retval;\n\n  if (y == 0)\n    retval = numeric_limits<T>::NaN ();\n  else\n    {\n      T q = x / y;\n\n      if (round (y) != y\n          && (std::abs ((q - round (q)) / round (q))\n              < std::numeric_limits<T>::epsilon ()))\n        retval = 0;\n      else\n        {\n          T n = std::trunc (q);\n\n          // Prevent use of extra precision.\n          T tmp = y * n;\n\n          retval = x - tmp;\n        }\n    }\n\n  if (x != y && y != 0)\n    retval = copysign (retval, x);\n\n  return retval;\n}\n\n// Generic min, max definitions\ntemplate <typename T>\nT\nmin (T x, T y)\n{\n  return x <= y ? x : y;\n}\n\ntemplate <typename T>\nT\nmax (T x, T y)\n{\n  return x >= y ? x : y;\n}\n\n// This form is favorable.  GCC will translate (x <= y ? x : y) without a\n// jump, hence the only conditional jump involved will be the first\n// (isnan), infrequent and hence friendly to branch prediction.\n\ninline char\nmin (char x, char y)\n{\n  return x <= y ? x : y;\n}\n\ninline char\nmax (char x, char y)\n{\n  return x >= y ? x : y;\n}\n\ninline double\nmin (double x, double y)\n{\n  return isnan (y) ? x : (x <= y ? x : y);\n}\n\ninline double\nmax (double x, double y)\n{\n  return isnan (y) ? x : (x >= y ? x : y);\n}\n\ninline double\nmin (double x, double y, const bool nanflag)\n{\n  double out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else\n    out = isnan (y) ? x : (x <= y ? x : y);\n  return out;\n}\n\ninline double\nmax (double x, double y, const bool nanflag)\n{\n  double out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else\n    out = isnan (y) ? x : (x >= y ? x : y);\n  return out;\n}\n\ninline double\nmin (double x, double y, const bool nanflag, const bool realabs)\n{\n  double out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else if (realabs)\n    out = isnan (y) ? x : (x <= y ? x : y);\n  else\n    out = isnan (y) ? x :\n          (std::abs (x) < std::abs (y) ? x : (std::abs (x) == std::abs (y) && x <= y ? x : y));\n  return out;\n}\n\ninline double\nmax (double x, double y, const bool nanflag, const bool realabs)\n{\n  double out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else if (realabs)\n    out = isnan (y) ? x : (x >= y ? x : y);\n  else\n    out = isnan (y) ? x :\n          (std::abs (x) > std::abs (y) ? x : (std::abs (x) == std::abs (y) && x >= y ? x : y));\n  return out;\n}\n\ninline float\nmin (float x, float y)\n{\n  return isnan (y) ? x : (x <= y ? x : y);\n}\n\ninline float\nmax (float x, float y)\n{\n  return isnan (y) ? x : (x >= y ? x : y);\n}\n\ninline float\nmin (float x, float y, const bool nanflag)\n{\n  float out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else\n    out = isnan (y) ? x : (x <= y ? x : y);\n  return out;\n}\n\ninline float\nmax (float x, float y, const bool nanflag)\n{\n  float out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else\n    out = isnan (y) ? x : (x >= y ? x : y);\n  return out;\n}\n\ninline float\nmin (float x, float y, const bool nanflag, const bool realabs)\n{\n  float out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else if (realabs)\n    out = isnan (y) ? x : (x <= y ? x : y);\n  else\n    out = isnan (y) ? x :\n          (std::abs (x) < std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && x <= y ? x : y));\n  return out;\n}\n\ninline float\nmax (float x, float y, const bool nanflag, const bool realabs)\n{\n  float out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else if (realabs)\n    out = isnan (y) ? x : (x >= y ? x : y);\n  else\n    out = isnan (y) ? x :\n          (std::abs (x) > std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && x >= y ? x : y));\n  return out;\n}\n\ninline std::complex<double>\nmin (const std::complex<double>& x, const std::complex<double>& y)\n{\n  return isnan (y) ? x : (std::abs (x) < std::abs (y) ? x :\n         (std::abs (x) == std::abs (y) && std::arg (x) <= std::arg (y) ? x : y));\n}\n\ninline std::complex<double>\nmax (const std::complex<double>& x, const std::complex<double>& y)\n{\n  return isnan (y) ? x : (std::abs (x) > std::abs (y) ? x :\n         (std::abs (x) == std::abs (y) && std::arg (x) >= std::arg (y) ? x : y));\n}\n\ninline std::complex<double>\nmin (const std::complex<double>& x, const std::complex<double>& y,\n     const bool nanflag)\n{\n  std::complex<double> out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else\n    out = isnan (y) ? x : (std::abs (x) < std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && std::arg (x) <= std::arg (y) ? x : y));\n  return out;\n}\n\ninline std::complex<double>\nmax (const std::complex<double>& x, const std::complex<double>& y,\n     const bool nanflag)\n{\n  std::complex<double> out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else\n    out = isnan (y) ? x : (std::abs (x) > std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && std::arg (x) >= std::arg (y) ? x : y));\n  return out;\n}\n\ninline std::complex<double>\nmin (const std::complex<double>& x, const std::complex<double>& y,\n     const bool nanflag, const bool realabs)\n{\n  std::complex<double> out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else if (realabs)\n    out = isnan (y) ? x : (std::real (x) < std::real (y) ? x :\n          (std::real (x) == std::real (y) &&\n           std::imag (x) <= std::imag (y) ? x : y));\n  else\n    out = isnan (y) ? x : (std::abs (x) < std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && std::arg (x) <= std::arg (y) ? x : y));\n  return out;\n}\n\ninline std::complex<double>\nmax (const std::complex<double>& x, const std::complex<double>& y,\n     const bool nanflag, const bool realabs)\n{\n  std::complex<double> out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else if (realabs)\n    out = isnan (y) ? x : (std::real (x) > std::real (y) ? x :\n          (std::real (x) == std::real (y) &&\n           std::imag (x) >= std::imag (y) ? x : y));\n  else\n    out = isnan (y) ? x : (std::abs (x) > std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && std::arg (x) >= std::arg (y) ? x : y));\n  return out;\n}\n\ninline std::complex<float>\nmin (const std::complex<float>& x, const std::complex<float>& y)\n{\n  return isnan (y) ? x : (abs (x) < abs (y) ? x :\n         (std::abs (x) == std::abs (y) && std::arg (x) <= std::arg (y) ? x : y));\n}\n\ninline std::complex<float>\nmax (const std::complex<float>& x, const std::complex<float>& y)\n{\n  return isnan (y) ? x : (abs (x) > abs (y) ? x :\n         (std::abs (x) == std::abs (y) && std::arg (x) >= std::arg (y) ? x : y));\n}\n\ninline std::complex<float>\nmin (const std::complex<float>& x, const std::complex<float>& y,\n     const bool nanflag)\n{\n  std::complex<float> out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else\n    out = isnan (y) ? x : (std::abs (x) < std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && std::arg (x) <= std::arg (y) ? x : y));\n  return out;\n}\n\ninline std::complex<float>\nmax (const std::complex<float>& x, const std::complex<float>& y,\n     const bool nanflag)\n{\n  std::complex<float> out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else\n    out = isnan (y) ? x : (std::abs (x) > std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && std::arg (x) >= std::arg (y) ? x : y));\n  return out;\n}\n\ninline std::complex<float>\nmin (const std::complex<float>& x, const std::complex<float>& y,\n     const bool nanflag, const bool realabs)\n{\n  std::complex<float> out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else if (realabs)\n    out = isnan (y) ? x : (std::real (x) < std::real (y) ? x :\n          (std::real (x) == std::real (y) &&\n           std::imag (x) <= std::imag (y) ? x : y));\n  else\n    out = isnan (y) ? x : (std::abs (x) < std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && std::arg (x) <= std::arg (y) ? x : y));\n  return out;\n}\n\ninline std::complex<float>\nmax (const std::complex<float>& x, const std::complex<float>& y,\n     const bool nanflag, const bool realabs)\n{\n  std::complex<float> out;\n  if (! nanflag && (isnan (x) || isnan (y)))\n    out = NAN;\n  else if (realabs)\n    out = isnan (y) ? x : (std::real (x) > std::real (y) ? x :\n          (std::real (x) == std::real (y) &&\n           std::imag (x) >= std::imag (y) ? x : y));\n  else\n    out = isnan (y) ? x : (std::abs (x) > std::abs (y) ? x :\n          (std::abs (x) == std::abs (y) && std::arg (x) >= std::arg (y) ? x : y));\n  return out;\n}\n\ntemplate <typename T>\ninline octave_int<T>\nmin (const octave_int<T>& x, const octave_int<T>& y)\n{\n  return x.value () <= y.value () ? x : y;\n}\n\ntemplate <typename T>\ninline octave_int<T>\nmax (const octave_int<T>& x, const octave_int<T>& y)\n{\n  return x.value () >= y.value () ? x : y;\n}\n\ntemplate <typename T>\ninline octave_int<T>\nmin (const octave_int<T>& x, const octave_int<T>& y,\n     [[maybe_unused]] const bool nanflag)\n{\n  return x.value () <= y.value () ? x : y;\n}\n\ntemplate <typename T>\ninline octave_int<T>\nmax (const octave_int<T>& x, const octave_int<T>& y,\n     [[maybe_unused]] const bool nanflag)\n{\n  return x.value () >= y.value () ? x : y;\n}\n\ntemplate <typename T>\ninline octave_int<T>\nmin (const octave_int<T>& x, const octave_int<T>& y,\n     [[maybe_unused]] const bool nanflag, const bool realabs)\n{\n  octave_int<T> out;\n  if (realabs)\n    out = x.value () <= y.value () ? x : y;\n  else\n    out = mappers_abs (x) < mappers_abs (y) ? x :\n          (mappers_abs (x) == mappers_abs (y) &&\n           x.value () <= y.value () ? x : y);\n  return out;\n}\n\ntemplate <typename T>\ninline octave_int<T>\nmax (const octave_int<T>& x, const octave_int<T>& y,\n     [[maybe_unused]] const bool nanflag, const bool realabs)\n{\n  octave_int<T> out;\n  if (realabs)\n    out = x.value () >= y.value () ? x : y;\n  else\n    out = mappers_abs (x) > mappers_abs (y) ? x :\n          (mappers_abs (x) == mappers_abs (y) &&\n           x.value () >= y.value () ? x : y);\n  return out;\n}\n\n// These map reals to Complex.\n\nextern OCTAVE_API Complex rc_acos (double);\nextern OCTAVE_API FloatComplex rc_acos (float);\n\nextern OCTAVE_API Complex rc_acosh (double);\nextern OCTAVE_API FloatComplex rc_acosh (float);\n\nextern OCTAVE_API Complex rc_asin (double);\nextern OCTAVE_API FloatComplex rc_asin (float);\n\nextern OCTAVE_API Complex rc_atanh (double);\nextern OCTAVE_API FloatComplex rc_atanh (float);\n\nextern OCTAVE_API Complex rc_log (double);\nextern OCTAVE_API FloatComplex rc_log (float);\n\nextern OCTAVE_API Complex rc_log2 (double);\nextern OCTAVE_API FloatComplex rc_log2 (float);\n\nextern OCTAVE_API Complex rc_log10 (double);\nextern OCTAVE_API FloatComplex rc_log10 (float);\n\nextern OCTAVE_API Complex rc_sqrt (double);\nextern OCTAVE_API FloatComplex rc_sqrt (float);\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/module.mk",
    "content": "LIBOCTAVE_OPT_INC = \\\n  %reldir%/DASPK-opts.h \\\n  %reldir%/DASRT-opts.h \\\n  %reldir%/DASSL-opts.h \\\n  %reldir%/LSODE-opts.h \\\n  %reldir%/Quad-opts.h\n\nLIBOCTAVE_OPT_IN = $(LIBOCTAVE_OPT_INC:.h=.in)\n\nNUMERIC_INC = \\\n  %reldir%/CollocWt.h \\\n  %reldir%/DAE.h \\\n  %reldir%/DAEFunc.h \\\n  %reldir%/DAERT.h \\\n  %reldir%/DAERTFunc.h \\\n  %reldir%/DASPK.h \\\n  %reldir%/DASRT.h \\\n  %reldir%/DASSL.h \\\n  %reldir%/DET.h \\\n  %reldir%/EIG.h \\\n  %reldir%/LSODE.h \\\n  %reldir%/ODE.h \\\n  %reldir%/ODEFunc.h \\\n  %reldir%/ODES.h \\\n  %reldir%/ODESFunc.h \\\n  %reldir%/Quad.h \\\n  %reldir%/aepbalance.h \\\n  %reldir%/amos-proto.h \\\n  %reldir%/arpack-proto.h \\\n  %reldir%/base-dae.h \\\n  %reldir%/base-de.h \\\n  %reldir%/blas-proto.h \\\n  %reldir%/bsxfun-decl.h \\\n  %reldir%/bsxfun.h \\\n  %reldir%/chol.h \\\n  %reldir%/eigs-base.h \\\n  %reldir%/fEIG.h \\\n  %reldir%/gepbalance.h \\\n  %reldir%/gsvd.h \\\n  %reldir%/hess.h \\\n  %reldir%/lapack-proto.h \\\n  %reldir%/lo-amos-proto.h \\\n  %reldir%/lo-arpack-proto.h \\\n  %reldir%/lo-blas-proto.h \\\n  %reldir%/lo-lapack-proto.h \\\n  %reldir%/lo-mappers.h \\\n  %reldir%/lo-qrupdate-proto.h \\\n  %reldir%/lo-ranlib-proto.h \\\n  %reldir%/lo-slatec-proto.h \\\n  %reldir%/lo-specfun.h \\\n  %reldir%/lu.h \\\n  %reldir%/mappers.h \\\n  %reldir%/oct-convn.h \\\n  %reldir%/oct-fftw.h \\\n  %reldir%/oct-norm.h \\\n  %reldir%/oct-rand.h \\\n  %reldir%/oct-specfun.h \\\n  %reldir%/oct-spparms.h \\\n  %reldir%/qr.h \\\n  %reldir%/qrp.h \\\n  %reldir%/qrupdate-proto.h \\\n  %reldir%/randgamma.h \\\n  %reldir%/randmtzig.h \\\n  %reldir%/randpoisson.h \\\n  %reldir%/ranlib-proto.h \\\n  %reldir%/schur.h \\\n  %reldir%/slatec-proto.h \\\n  %reldir%/sparse-chol.h \\\n  %reldir%/sparse-dmsolve.h \\\n  %reldir%/sparse-lu.h \\\n  %reldir%/sparse-qr.h \\\n  %reldir%/svd.h\n\nNUMERIC_SRC = \\\n  %reldir%/CollocWt.cc \\\n  %reldir%/DASPK.cc \\\n  %reldir%/DASRT.cc \\\n  %reldir%/DASSL.cc \\\n  %reldir%/EIG.cc \\\n  %reldir%/gsvd.cc \\\n  %reldir%/LSODE.cc \\\n  %reldir%/ODES.cc \\\n  %reldir%/Quad.cc \\\n  %reldir%/aepbalance.cc \\\n  %reldir%/chol.cc \\\n  %reldir%/eigs-base.cc \\\n  %reldir%/fEIG.cc \\\n  %reldir%/gepbalance.cc \\\n  %reldir%/hess.cc \\\n  %reldir%/lu.cc \\\n  %reldir%/mappers.cc \\\n  %reldir%/oct-convn.cc \\\n  %reldir%/oct-fftw.cc \\\n  %reldir%/oct-norm.cc \\\n  %reldir%/oct-rand.cc \\\n  %reldir%/oct-specfun.cc \\\n  %reldir%/oct-spparms.cc \\\n  %reldir%/qr.cc \\\n  %reldir%/qrp.cc \\\n  %reldir%/randgamma.cc \\\n  %reldir%/randmtzig.cc \\\n  %reldir%/randpoisson.cc \\\n  %reldir%/schur.cc \\\n  %reldir%/sparse-chol.cc \\\n  %reldir%/sparse-dmsolve.cc \\\n  %reldir%/sparse-lu.cc \\\n  %reldir%/sparse-qr.cc \\\n  %reldir%/svd.cc\n\nLIBOCTAVE_TEMPLATE_SRC += \\\n  %reldir%/bsxfun-defs.cc\n\n## Special rules for sources which must be built before rest of compilation.\n$(LIBOCTAVE_OPT_INC) : %.h : %.in\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(PERL) $(srcdir)/build-aux/mk-opts.pl --opt-class-header $< > $@-t && \\\n\tmv $@-t $@\n\n$(LIBOCTAVE_OPT_INC) : $(srcdir)/build-aux/mk-opts.pl\n\nnoinst_LTLIBRARIES += %reldir%/libnumeric.la\n\n%canon_reldir%_libnumeric_la_SOURCES = $(NUMERIC_SRC)\n\n%canon_reldir%_libnumeric_la_CPPFLAGS = \\\n  $(liboctave_liboctave_la_CPPFLAGS) \\\n  -I$(srcdir)/liboctave/external/Faddeeva \\\n  $(FFTW_XCPPFLAGS) \\\n  $(SPARSE_XCPPFLAGS)\n\nliboctave_liboctave_la_LIBADD += %reldir%/libnumeric.la\n\nliboctave_EXTRA_DIST += $(LIBOCTAVE_OPT_IN)\n\nliboctave_CLEANFILES += \\\n  $(LIBOCTAVE_OPT_INC)\n"
  },
  {
    "path": "liboctave/numeric/oct-convn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n\n#include \"Array-oct.h\"\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n#include \"CNDArray.h\"\n#include \"CRowVector.h\"\n#include \"MArray.h\"\n#include \"blas-proto.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"dNDArray.h\"\n#include \"dRowVector.h\"\n#include \"f77-fcn.h\"\n#include \"fCColVector.h\"\n#include \"fCMatrix.h\"\n#include \"fCNDArray.h\"\n#include \"fCRowVector.h\"\n#include \"fColVector.h\"\n#include \"fMatrix.h\"\n#include \"fNDArray.h\"\n#include \"fRowVector.h\"\n#include \"oct-convn.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Overload function \"blas_axpy\" to wrap BLAS ?axpy\n\nstatic inline void\nblas_axpy (const F77_INT& n, const double& alpha, const double *x,\n           const F77_INT& incx, double *y, const F77_INT& incy)\n{\n  F77_FUNC (daxpy, DAXPY) (n, alpha, x, incx, y, incy);\n}\n\nstatic inline void\nblas_axpy (const F77_INT& n, const float& alpha, const float *x,\n           const F77_INT& incx, float *y, const F77_INT& incy)\n{\n  F77_FUNC (saxpy, SAXPY) (n, alpha, x, incx, y, incy);\n}\n\nstatic inline void\nblas_axpy (const F77_INT& n, const Complex& alpha,\n           const Complex *x, const F77_INT& incx,\n           Complex *y, const F77_INT& incy)\n{\n  F77_FUNC (zaxpy, ZAXPY) (n, *F77_CONST_DBLE_CMPLX_ARG (&alpha),\n                           F77_CONST_DBLE_CMPLX_ARG (x), incx,\n                           F77_DBLE_CMPLX_ARG (y), incy);\n}\n\nstatic inline void\nblas_axpy (const F77_INT& n, const FloatComplex& alpha,\n           const FloatComplex *x, const F77_INT& incx,\n           FloatComplex *y, const F77_INT& incy)\n{\n  F77_FUNC (caxpy, CAXPY) (n, *F77_CONST_CMPLX_ARG (&alpha),\n                           F77_CONST_CMPLX_ARG (x), incx,\n                           F77_CMPLX_ARG (y), incy);\n}\n\n\n// 2-D convolution with a matrix kernel.\ntemplate <typename T, typename R>\nstatic void\nconvolve_2d (const T *a, F77_INT ma, F77_INT na,\n             const R *b, F77_INT mb, F77_INT nb,\n             T *c, bool inner)\n{\n  if (inner)\n    {\n      // Inner convolution (\"valid\")\n      const F77_INT len = ma - mb + 1;  // Pre-calculate length\n      for (F77_INT k = 0; k < na - nb + 1; k++)\n        for (F77_INT j = 0; j < nb; j++)\n          for (F77_INT i = 0; i < mb; i++)\n            {\n              // Create a T value from R\n              T b_val = static_cast<T>(b[i + j*mb]);\n\n              // Call the appropriate blas_axpy function based on type T\n              blas_axpy (len, b_val, &a[mb-i-1 + (k+nb-j-1)*ma], 1,\n                         &c[k*len], 1);\n            }\n    }\n  else\n    {\n      // Outer convolution (\"full\")\n      const F77_INT len = ma + mb - 1;  // Pre-calculate length\n      for (F77_INT k = 0; k < na; k++)\n        for (F77_INT j = 0; j < nb; j++)\n          for (F77_INT i = 0; i < mb; i++)\n            {\n              // Create a T value from R\n              T b_val = static_cast<T>(b[i + j*mb]);\n\n              // Call the appropriate blas_axpy function based on type T\n              blas_axpy (ma, b_val, &a[k*ma], 1, &c[i + (j+k)*len], 1);\n            }\n    }\n}\n\ntemplate <typename T, typename R>\nvoid\nconvolve_nd (const T *a, const dim_vector& ad, const dim_vector& acd,\n             const R *b, const dim_vector& bd, const dim_vector& bcd,\n             T *c, const dim_vector& ccd, int nd, bool inner)\n{\n  if (nd == 2)\n    {\n      F77_INT ad0 = to_f77_int (ad(0));\n      F77_INT ad1 = to_f77_int (ad(1));\n\n      F77_INT bd0 = to_f77_int (bd(0));\n      F77_INT bd1 = to_f77_int (bd(1));\n\n      convolve_2d<T, R> (a, ad0, ad1, b, bd0, bd1, c, inner);\n    }\n  else\n    {\n      octave_idx_type ma = acd(nd-2);\n      octave_idx_type na = ad(nd-1);\n      octave_idx_type mb = bcd(nd-2);\n      octave_idx_type nb = bd(nd-1);\n      octave_idx_type ldc = ccd(nd-2);\n\n      if (inner)\n        {\n          for (octave_idx_type ja = 0; ja < na - nb + 1; ja++)\n            for (octave_idx_type jb = 0; jb < nb; jb++)\n              convolve_nd<T, R> (a + ma*(ja+jb), ad, acd,\n                                 b + mb*(nb-jb-1), bd, bcd,\n                                 c + ldc*ja, ccd, nd-1, inner);\n        }\n      else\n        {\n          for (octave_idx_type ja = 0; ja < na; ja++)\n            for (octave_idx_type jb = 0; jb < nb; jb++)\n              convolve_nd<T, R> (a + ma*ja, ad, acd, b + mb*jb, bd, bcd,\n                                 c + ldc*(ja+jb), ccd, nd-1, inner);\n        }\n    }\n}\n\n// Arbitrary convolutor.\ntemplate <typename T, typename R>\nstatic MArray<T>\nconvolve (const MArray<T>& a, const MArray<R>& b, convn_type ct)\n{\n  if (a.isempty () || b.isempty ())\n    return MArray<T> ();\n\n  const int nd = std::max (a.ndims (), b.ndims ());\n  const dim_vector adims = a.dims ().redim (nd);\n  dim_vector apdims = a.dims ().redim (nd);         // permuted adims\n  const dim_vector bdims = b.dims ().redim (nd);\n  dim_vector cdims = dim_vector::alloc (nd);\n\n  for (int i = 0; i < nd; i++)\n    {\n      if (ct == convn_valid)\n        cdims(i) = std::max (adims(i) - bdims(i) + 1,\n                             static_cast<octave_idx_type> (0));\n      else\n        cdims(i) = std::max (adims(i) + bdims(i) - 1,\n                             static_cast<octave_idx_type> (0));\n    }\n\n  // \"valid\" shape can sometimes result in empty matrices which must avoid\n  // calling Fortran code which does not expect this (bug #52067)\n  if (cdims.numel () == 0)\n    return MArray<T> (cdims);\n\n  // Permute dimensions of a/b/c such that the dimensions of a are ordered\n  // by decreasing number of elements (for efficiency in Fortran loops).\n  Array<octave_idx_type> order (dim_vector (1, nd));\n  for (int i = 0; i < nd; i++)\n    order(i) = i;\n\n  // Since the number of dimensions is nearly always small, it is faster\n  // to sort them inline instead of calling octave_sort::sort ().\n  bool reordered = false;\n  for (int i = 0; i < nd; i++)\n    for (int j = (i+1); j < nd; j++)\n      if (apdims(i) < apdims(j))\n        {\n          std::swap (apdims(i), apdims(j));\n          std::swap (cdims(i), cdims(j));\n          std::swap (order(i), order(j));\n          reordered = true;\n        }\n\n  // Initialize output based on the current order of cdims.\n  MArray<T> c (cdims, T ());\n\n  if (reordered)  // adims was reordered, so the inputs must be as well.\n    {\n      // Permute the inputs\n      const MArray<T> ap = a.permute (order);\n      const MArray<R> bp = b.permute (order);\n      const dim_vector bpdims = bp.dims ().redim (nd);\n\n      // Do convolution on the permuted arrays.\n      convolve_nd<T, R> (ap.data (), apdims, apdims.cumulative (),\n                         bp.data (), bpdims, bpdims.cumulative (),\n                         c.rwdata (), cdims.cumulative (),\n                         nd, ct == convn_valid);\n\n      // Permute back to original order.\n      c = c.ipermute (order);\n    }\n  else  // No reordering ==> no need to create permuted arrays.\n    {\n      // Do convolution on the original arrays.\n      convolve_nd<T, R> (a.data (), adims, adims.cumulative (),\n                         b.data (), bdims, bdims.cumulative (),\n                         c.rwdata (), cdims.cumulative (),\n                         nd, ct == convn_valid);\n    }\n\n  if (ct == convn_same)\n    {\n      // Pick the relevant part.\n      Array<idx_vector> sidx (dim_vector (nd, 1));\n\n      for (int i = 0; i < nd; i++)\n        sidx(i) = idx_vector::make_range (bdims(i)/2, 1, adims(i));\n      c = c.index (sidx);\n    }\n\n  return c;\n}\n\n#define CONV_DEFS(TPREF, RPREF)                                         \\\n  TPREF ## NDArray                                                      \\\n  convn (const TPREF ## NDArray& a, const RPREF ## NDArray& b,          \\\n         convn_type ct)                                                 \\\n  {                                                                     \\\n    return convolve (a, b, ct);                                         \\\n  }                                                                     \\\n  TPREF ## Matrix                                                       \\\n  convn (const TPREF ## Matrix& a, const RPREF ## Matrix& b,            \\\n         convn_type ct)                                                 \\\n  {                                                                     \\\n    return convolve (a, b, ct);                                         \\\n  }                                                                     \\\n  TPREF ## Matrix                                                       \\\n  convn (const TPREF ## Matrix& a, const RPREF ## ColumnVector& c,      \\\n         const RPREF ## RowVector& r, convn_type ct)                    \\\n  {                                                                     \\\n    return convolve (a, c * r, ct);                                     \\\n  }\n\nCONV_DEFS (, )\nCONV_DEFS (Complex, )\nCONV_DEFS (Complex, Complex)\nCONV_DEFS (Float, Float)\nCONV_DEFS (FloatComplex, Float)\nCONV_DEFS (FloatComplex, FloatComplex)\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/oct-convn.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_convn_h)\n#define octave_oct_convn_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\n// The remaining includes can be removed when the global enum\n// declaration, the convert_enum function, and the deprecated functions\n// at the end of this file are removed.\n\n#include <cstdlib>\n#include \"dMatrix.h\"\n#include \"dNDArray.h\"\n#include \"CMatrix.h\"\n#include \"CNDArray.h\"\n#include \"fMatrix.h\"\n#include \"fNDArray.h\"\n#include \"fCMatrix.h\"\n#include \"fCNDArray.h\"\n\n// FIXME: Is there any sane way to move a global enum to a namespace and\n// tag the global one as deprecated when it is used as a parameter in\n// public functions that also need to be tagged as deprecated?\n\nenum convn_type\n{\n  convn_full,\n  convn_same,\n  convn_valid\n};\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nenum convn_type\n{\n  convn_full,\n  convn_same,\n  convn_valid\n};\n\n// double real X double real\n\nextern OCTAVE_API NDArray\nconvn (const NDArray& a, const NDArray& b, convn_type ct);\n\nextern OCTAVE_API Matrix\nconvn (const Matrix& a, const Matrix& b, convn_type ct);\n\nextern OCTAVE_API Matrix\nconvn (const Matrix& a, const ColumnVector& c, const RowVector& r,\n       convn_type ct);\n\n// double complex X double real\n\nextern OCTAVE_API ComplexNDArray\nconvn (const ComplexNDArray& a, const NDArray& b, convn_type ct);\n\nextern OCTAVE_API ComplexMatrix\nconvn (const ComplexMatrix& a, const Matrix& b, convn_type ct);\n\nextern OCTAVE_API ComplexMatrix\nconvn (const ComplexMatrix& a, const ColumnVector& c, const RowVector& r,\n       convn_type ct);\n\n// double complex X double complex\n\nextern OCTAVE_API ComplexNDArray\nconvn (const ComplexNDArray& a, const ComplexNDArray& b, convn_type ct);\n\nextern OCTAVE_API ComplexMatrix\nconvn (const ComplexMatrix& a, const ComplexMatrix& b, convn_type ct);\n\nextern OCTAVE_API ComplexMatrix\nconvn (const ComplexMatrix& a, const ComplexColumnVector& c,\n       const ComplexRowVector& r, convn_type ct);\n\n// float real X float real\n\nextern OCTAVE_API FloatNDArray\nconvn (const FloatNDArray& a, const FloatNDArray& b, convn_type ct);\n\nextern OCTAVE_API FloatMatrix\nconvn (const FloatMatrix& a, const FloatMatrix& b, convn_type ct);\n\nextern OCTAVE_API FloatMatrix\nconvn (const FloatMatrix& a, const FloatColumnVector& c,\n       const FloatRowVector& r, convn_type ct);\n\n// float complex X float real\n\nextern OCTAVE_API FloatComplexNDArray\nconvn (const FloatComplexNDArray& a, const FloatNDArray& b, convn_type ct);\n\nextern OCTAVE_API FloatComplexMatrix\nconvn (const FloatComplexMatrix& a, const FloatMatrix& b, convn_type ct);\n\nextern OCTAVE_API FloatComplexMatrix\nconvn (const FloatComplexMatrix& a, const FloatColumnVector& c,\n       const FloatRowVector& r, convn_type ct);\n\n// float complex X float complex\n\nextern OCTAVE_API FloatComplexNDArray\nconvn (const FloatComplexNDArray& a, const FloatComplexNDArray& b,\n       convn_type ct);\n\nextern OCTAVE_API FloatComplexMatrix\nconvn (const FloatComplexMatrix& a, const FloatComplexMatrix& b,\n       convn_type ct);\n\nextern OCTAVE_API FloatComplexMatrix\nconvn (const FloatComplexMatrix& a, const FloatComplexColumnVector& c,\n       const FloatComplexRowVector& r, convn_type ct);\n\nconvn_type convert_enum (::convn_type ct)\n{\n  switch (ct)\n    {\n    case ::convn_full:\n      return convn_full;\n\n    case ::convn_same:\n      return convn_same;\n\n    case ::convn_valid:\n      return convn_valid;\n\n    default:\n      abort ();\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/oct-fftw.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_FFTW3_H)\n#  include <fftw3.h>\n#endif\n\n#include \"oct-error.h\"\n#include \"oct-fftw.h\"\n#include \"oct-locbuf.h\"\n#include \"quit.h\"\n#include \"singleton-cleanup.h\"\n\n#if defined (HAVE_FFTW3_THREADS) || defined (HAVE_FFTW3F_THREADS)\n#  include \"nproc-wrapper.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#if defined (HAVE_FFTW)\n\nfftw_planner *fftw_planner::s_instance = nullptr;\n\n// Helper class to create and cache FFTW plans for both 1-D and\n// 2-D.  This implementation defaults to using FFTW_ESTIMATE to create\n// the plans, which in theory is suboptimal, but provides quite\n// reasonable performance in practice.\n\n// Also note that if FFTW_ESTIMATE is not used then the planner in FFTW3\n// will destroy the input and output arrays.  We must, therefore, create a\n// temporary input array with the same size and 16-byte alignment as\n// the original array when using a different planner strategy.\n// Note that we also use any wisdom that is available, either in a\n// FFTW3 system wide file or as supplied by the user.\n\n// FIXME: if we can ensure 16 byte alignment in Array<T>\n// (<T> *data) the FFTW3 can use SIMD instructions for further\n// acceleration.\n\n// Note that it is profitable to store the FFTW3 plans, for small FFTs.\n\nfftw_planner::fftw_planner ()\n  : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0),\n    m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1)\n{\n  m_plan[0] = m_plan[1] = nullptr;\n  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;\n  m_simd_align[0] = m_simd_align[1] = false;\n  m_inplace[0] = m_inplace[1] = false;\n  m_n[0] = m_n[1] = dim_vector ();\n\n#if defined (HAVE_FFTW3_THREADS)\n  int init_ret = fftw_init_threads ();\n  if (! init_ret)\n    (*current_liboctave_error_handler) (\"Error initializing FFTW threads\");\n\n  // Check number of processors available to the current process\n  m_nthreads =\n    octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT_OVERRIDABLE);\n\n  // Limit number of threads to 3 by default\n  // See: https://octave.discourse.group/t/3121\n  // This can be later changed with fftw (\"threads\", nthreads).\n  if (m_nthreads > 3)\n    m_nthreads = 3;\n\n  fftw_plan_with_nthreads (m_nthreads);\n#endif\n\n  // If we have a system wide wisdom file, import it.\n  fftw_import_system_wisdom ();\n}\n\nfftw_planner::~fftw_planner ()\n{\n  fftw_plan *plan_p;\n\n  plan_p = reinterpret_cast<fftw_plan *> (&m_rplan);\n  if (*plan_p)\n    fftw_destroy_plan (*plan_p);\n\n  plan_p = reinterpret_cast<fftw_plan *> (&m_plan[0]);\n  if (*plan_p)\n    fftw_destroy_plan (*plan_p);\n\n  plan_p = reinterpret_cast<fftw_plan *> (&m_plan[1]);\n  if (*plan_p)\n    fftw_destroy_plan (*plan_p);\n}\n\nbool\nfftw_planner::instance_ok ()\n{\n  bool retval = true;\n\n  if (! s_instance)\n    {\n      s_instance = new fftw_planner ();\n      singleton_cleanup_list::add (cleanup_instance);\n    }\n\n  return retval;\n}\n\nvoid\nfftw_planner::threads (int nt)\n{\n#if defined (HAVE_FFTW3_THREADS)\n  if (instance_ok () && nt != threads ())\n    {\n      s_instance->m_nthreads = nt;\n      fftw_plan_with_nthreads (nt);\n      // Clear the current plans.\n      s_instance->m_rplan = nullptr;\n      s_instance->m_plan[0] = s_instance->m_plan[1] = nullptr;\n    }\n#else\n  octave_unused_parameter (nt);\n\n  (*current_liboctave_warning_handler)\n    (\"unable to change number of threads without FFTW thread support\");\n#endif\n}\n\n#define CHECK_SIMD_ALIGNMENT(x)                         \\\n  (((reinterpret_cast<std::ptrdiff_t> (x)) & 0xF) == 0)\n\nvoid *\nfftw_planner::do_create_plan (int dir, const int rank,\n                              const dim_vector& dims,\n                              octave_idx_type howmany,\n                              octave_idx_type stride,\n                              octave_idx_type dist,\n                              const Complex *in, Complex *out)\n{\n  int which = (dir == FFTW_FORWARD) ? 0 : 1;\n  fftw_plan *cur_plan_p = reinterpret_cast<fftw_plan *> (&m_plan[which]);\n  bool create_new_plan = false;\n  bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out);\n  bool ioinplace = (in == out);\n\n  // Don't create a new plan if we have a non SIMD plan already but\n  // can do SIMD.  This prevents endlessly recreating plans if we\n  // change the alignment.\n\n  if (m_plan[which] == nullptr || m_d[which] != dist || m_s[which] != stride\n      || m_r[which] != rank || m_h[which] != howmany\n      || ioinplace != m_inplace[which]\n      || ((ioalign != m_simd_align[which]) ? ! ioalign : false))\n    create_new_plan = true;\n  else\n    {\n      // We still might not have the same shape of array.\n\n      for (int i = 0; i < rank; i++)\n        if (dims(i) != m_n[which](i))\n          {\n            create_new_plan = true;\n            break;\n          }\n    }\n\n  if (create_new_plan)\n    {\n      m_d[which] = dist;\n      m_s[which] = stride;\n      m_r[which] = rank;\n      m_h[which] = howmany;\n      m_simd_align[which] = ioalign;\n      m_inplace[which] = ioinplace;\n      m_n[which] = dims;\n\n      // Note reversal of dimensions for column major storage in FFTW.\n      octave_idx_type nn = 1;\n      OCTAVE_LOCAL_BUFFER (int, tmp, rank);\n\n      for (int i = 0, j = rank-1; i < rank; i++, j--)\n        {\n          tmp[i] = dims(j);\n          nn *= dims(j);\n        }\n\n      int plan_flags = 0;\n      bool plan_destroys_in = true;\n\n      switch (m_meth)\n        {\n        case UNKNOWN:\n        case ESTIMATE:\n          plan_flags |= FFTW_ESTIMATE;\n          plan_destroys_in = false;\n          break;\n        case MEASURE:\n          plan_flags |= FFTW_MEASURE;\n          break;\n        case PATIENT:\n          plan_flags |= FFTW_PATIENT;\n          break;\n        case EXHAUSTIVE:\n          plan_flags |= FFTW_EXHAUSTIVE;\n          break;\n        case HYBRID:\n          if (nn < 8193)\n            plan_flags |= FFTW_MEASURE;\n          else\n            {\n              plan_flags |= FFTW_ESTIMATE;\n              plan_destroys_in = false;\n            }\n          break;\n        }\n\n      if (ioalign)\n        plan_flags &= ~FFTW_UNALIGNED;\n      else\n        plan_flags |= FFTW_UNALIGNED;\n\n      if (*cur_plan_p)\n        fftw_destroy_plan (*cur_plan_p);\n\n      OCTAVE_SCOPED_BUFFER_ANCHOR (Complex, itmp);\n      itmp = const_cast<Complex *> (in);\n      Complex *otmp = out;\n\n      if (plan_destroys_in)\n        {\n          // Create matrix with the same size and 16-byte alignment as input\n          OCTAVE_SCOPED_BUFFER (Complex, itmp, nn * howmany + 32);\n          itmp = reinterpret_cast<Complex *>\n                 (((reinterpret_cast<std::ptrdiff_t> (itmp) + 15) & ~ 0xF)\n                  + ((reinterpret_cast<std::ptrdiff_t> (in)) & 0xF));\n\n          if (in == out)\n            otmp = itmp;\n        }\n\n      *cur_plan_p\n        = fftw_plan_many_dft (rank, tmp, howmany,\n                              reinterpret_cast<fftw_complex *> (itmp),\n                              nullptr, stride, dist,\n                              reinterpret_cast<fftw_complex *> (otmp),\n                              nullptr, stride, dist, dir, plan_flags);\n\n      if (*cur_plan_p == nullptr)\n        (*current_liboctave_error_handler) (\"Error creating FFTW plan\");\n    }\n\n  return *cur_plan_p;\n}\n\nvoid *\nfftw_planner::do_create_plan (const int rank, const dim_vector& dims,\n                              octave_idx_type howmany,\n                              octave_idx_type stride,\n                              octave_idx_type dist,\n                              const double *in, Complex *out)\n{\n  fftw_plan *cur_plan_p = reinterpret_cast<fftw_plan *> (&m_rplan);\n  bool create_new_plan = false;\n  bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out);\n\n  // Don't create a new plan if we have a non SIMD plan already but\n  // can do SIMD.  This prevents endlessly recreating plans if we\n  // change the alignment.\n\n  if (m_rplan == nullptr || m_rd != dist || m_rs != stride || m_rr != rank\n      || m_rh != howmany || ((ioalign != m_rsimd_align) ? ! ioalign : false))\n    create_new_plan = true;\n  else\n    {\n      // We still might not have the same shape of array.\n\n      for (int i = 0; i < rank; i++)\n        if (dims(i) != m_rn(i))\n          {\n            create_new_plan = true;\n            break;\n          }\n    }\n\n  if (create_new_plan)\n    {\n      m_rd = dist;\n      m_rs = stride;\n      m_rr = rank;\n      m_rh = howmany;\n      m_rsimd_align = ioalign;\n      m_rn = dims;\n\n      // Note reversal of dimensions for column major storage in FFTW.\n      octave_idx_type nn = 1;\n      OCTAVE_LOCAL_BUFFER (int, tmp, rank);\n\n      for (int i = 0, j = rank-1; i < rank; i++, j--)\n        {\n          tmp[i] = dims(j);\n          nn *= dims(j);\n        }\n\n      int plan_flags = 0;\n      bool plan_destroys_in = true;\n\n      switch (m_meth)\n        {\n        case UNKNOWN:\n        case ESTIMATE:\n          plan_flags |= FFTW_ESTIMATE;\n          plan_destroys_in = false;\n          break;\n        case MEASURE:\n          plan_flags |= FFTW_MEASURE;\n          break;\n        case PATIENT:\n          plan_flags |= FFTW_PATIENT;\n          break;\n        case EXHAUSTIVE:\n          plan_flags |= FFTW_EXHAUSTIVE;\n          break;\n        case HYBRID:\n          if (nn < 8193)\n            plan_flags |= FFTW_MEASURE;\n          else\n            {\n              plan_flags |= FFTW_ESTIMATE;\n              plan_destroys_in = false;\n            }\n          break;\n        }\n\n      if (ioalign)\n        plan_flags &= ~FFTW_UNALIGNED;\n      else\n        plan_flags |= FFTW_UNALIGNED;\n\n      if (*cur_plan_p)\n        fftw_destroy_plan (*cur_plan_p);\n\n      OCTAVE_SCOPED_BUFFER_ANCHOR (double, itmp);\n      itmp = const_cast<double *> (in);\n      Complex *otmp = out;\n\n      if (plan_destroys_in)\n        {\n          // Create matrix with the same size and 16-byte alignment as input\n          octave_idx_type in_place = reinterpret_cast<double *> (out) == in;\n          OCTAVE_SCOPED_BUFFER (double, itmp,\n                                nn * howmany * (in_place + 1) + 32);\n          itmp = reinterpret_cast<double *>\n                 (((reinterpret_cast<std::ptrdiff_t> (itmp) + 15) & ~ 0xF)\n                  + ((reinterpret_cast<std::ptrdiff_t> (in)) & 0xF));\n\n          if (in_place)\n            otmp = reinterpret_cast<Complex *> (itmp);\n        }\n\n      *cur_plan_p\n        = fftw_plan_many_dft_r2c (rank, tmp, howmany, itmp,\n                                  nullptr, stride, dist,\n                                  reinterpret_cast<fftw_complex *> (otmp),\n                                  nullptr, stride, dist, plan_flags);\n\n      if (*cur_plan_p == nullptr)\n        (*current_liboctave_error_handler) (\"Error creating FFTW plan\");\n    }\n\n  return *cur_plan_p;\n}\n\nfftw_planner::FftwMethod\nfftw_planner::do_method ()\n{\n  return m_meth;\n}\n\nfftw_planner::FftwMethod\nfftw_planner::do_method (FftwMethod _meth)\n{\n  FftwMethod ret = m_meth;\n  if (_meth == ESTIMATE || _meth == MEASURE\n      || _meth == PATIENT || _meth == EXHAUSTIVE\n      || _meth == HYBRID)\n    {\n      if (m_meth != _meth)\n        {\n          m_meth = _meth;\n          if (m_rplan)\n            fftw_destroy_plan (reinterpret_cast<fftw_plan> (m_rplan));\n          if (m_plan[0])\n            fftw_destroy_plan (reinterpret_cast<fftw_plan> (m_plan[0]));\n          if (m_plan[1])\n            fftw_destroy_plan (reinterpret_cast<fftw_plan> (m_plan[1]));\n          m_rplan = m_plan[0] = m_plan[1] = nullptr;\n        }\n    }\n  else\n    ret = UNKNOWN;\n  return ret;\n}\n\nfloat_fftw_planner *float_fftw_planner::s_instance = nullptr;\n\nfloat_fftw_planner::float_fftw_planner ()\n  : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0),\n    m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1)\n{\n  m_plan[0] = m_plan[1] = nullptr;\n  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;\n  m_simd_align[0] = m_simd_align[1] = false;\n  m_inplace[0] = m_inplace[1] = false;\n  m_n[0] = m_n[1] = dim_vector ();\n\n#if defined (HAVE_FFTW3F_THREADS)\n  int init_ret = fftwf_init_threads ();\n  if (! init_ret)\n    (*current_liboctave_error_handler) (\"Error initializing FFTW3F threads\");\n\n  // Use number of processors available to the current process\n  // This can be later changed with fftw (\"threads\", nthreads).\n  m_nthreads =\n    octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT_OVERRIDABLE);\n\n  fftwf_plan_with_nthreads (m_nthreads);\n#endif\n\n  // If we have a system wide wisdom file, import it.\n  fftwf_import_system_wisdom ();\n}\n\nfloat_fftw_planner::~float_fftw_planner ()\n{\n  fftwf_plan *plan_p;\n\n  plan_p = reinterpret_cast<fftwf_plan *> (&m_rplan);\n  if (*plan_p)\n    fftwf_destroy_plan (*plan_p);\n\n  plan_p = reinterpret_cast<fftwf_plan *> (&m_plan[0]);\n  if (*plan_p)\n    fftwf_destroy_plan (*plan_p);\n\n  plan_p = reinterpret_cast<fftwf_plan *> (&m_plan[1]);\n  if (*plan_p)\n    fftwf_destroy_plan (*plan_p);\n}\n\nbool\nfloat_fftw_planner::instance_ok ()\n{\n  bool retval = true;\n\n  if (! s_instance)\n    {\n      s_instance = new float_fftw_planner ();\n      singleton_cleanup_list::add (cleanup_instance);\n    }\n\n  return retval;\n}\n\nvoid\nfloat_fftw_planner::threads (int nt)\n{\n#if defined (HAVE_FFTW3F_THREADS)\n  if (instance_ok () && nt != threads ())\n    {\n      s_instance->m_nthreads = nt;\n      fftwf_plan_with_nthreads (nt);\n      // Clear the current plans.\n      s_instance->m_rplan = nullptr;\n      s_instance->m_plan[0] = s_instance->m_plan[1] = nullptr;\n    }\n#else\n  octave_unused_parameter (nt);\n\n  (*current_liboctave_warning_handler)\n    (\"unable to change number of threads without FFTW thread support\");\n#endif\n}\n\nvoid *\nfloat_fftw_planner::do_create_plan (int dir, const int rank,\n                                    const dim_vector& dims,\n                                    octave_idx_type howmany,\n                                    octave_idx_type stride,\n                                    octave_idx_type dist,\n                                    const FloatComplex *in,\n                                    FloatComplex *out)\n{\n  int which = (dir == FFTW_FORWARD) ? 0 : 1;\n  fftwf_plan *cur_plan_p = reinterpret_cast<fftwf_plan *> (&m_plan[which]);\n  bool create_new_plan = false;\n  bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out);\n  bool ioinplace = (in == out);\n\n  // Don't create a new plan if we have a non SIMD plan already but\n  // can do SIMD.  This prevents endlessly recreating plans if we\n  // change the alignment.\n\n  if (m_plan[which] == nullptr || m_d[which] != dist || m_s[which] != stride\n      || m_r[which] != rank || m_h[which] != howmany\n      || ioinplace != m_inplace[which]\n      || ((ioalign != m_simd_align[which]) ? ! ioalign : false))\n    create_new_plan = true;\n  else\n    {\n      // We still might not have the same shape of array.\n\n      for (int i = 0; i < rank; i++)\n        if (dims(i) != m_n[which](i))\n          {\n            create_new_plan = true;\n            break;\n          }\n    }\n\n  if (create_new_plan)\n    {\n      m_d[which] = dist;\n      m_s[which] = stride;\n      m_r[which] = rank;\n      m_h[which] = howmany;\n      m_simd_align[which] = ioalign;\n      m_inplace[which] = ioinplace;\n      m_n[which] = dims;\n\n      // Note reversal of dimensions for column major storage in FFTW.\n      octave_idx_type nn = 1;\n      OCTAVE_LOCAL_BUFFER (int, tmp, rank);\n\n      for (int i = 0, j = rank-1; i < rank; i++, j--)\n        {\n          tmp[i] = dims(j);\n          nn *= dims(j);\n        }\n\n      int plan_flags = 0;\n      bool plan_destroys_in = true;\n\n      switch (m_meth)\n        {\n        case UNKNOWN:\n        case ESTIMATE:\n          plan_flags |= FFTW_ESTIMATE;\n          plan_destroys_in = false;\n          break;\n        case MEASURE:\n          plan_flags |= FFTW_MEASURE;\n          break;\n        case PATIENT:\n          plan_flags |= FFTW_PATIENT;\n          break;\n        case EXHAUSTIVE:\n          plan_flags |= FFTW_EXHAUSTIVE;\n          break;\n        case HYBRID:\n          if (nn < 8193)\n            plan_flags |= FFTW_MEASURE;\n          else\n            {\n              plan_flags |= FFTW_ESTIMATE;\n              plan_destroys_in = false;\n            }\n          break;\n        }\n\n      if (ioalign)\n        plan_flags &= ~FFTW_UNALIGNED;\n      else\n        plan_flags |= FFTW_UNALIGNED;\n\n      if (*cur_plan_p)\n        fftwf_destroy_plan (*cur_plan_p);\n\n      OCTAVE_SCOPED_BUFFER_ANCHOR (FloatComplex, itmp);\n      itmp = const_cast<FloatComplex *> (in);\n      FloatComplex *otmp = out;\n\n      if (plan_destroys_in)\n        {\n          // Create matrix with the same size and 16-byte alignment as input\n          OCTAVE_SCOPED_BUFFER (FloatComplex, itmp, nn * howmany + 32);\n          itmp = reinterpret_cast<FloatComplex *>\n                 (((reinterpret_cast<std::ptrdiff_t> (itmp) + 15) & ~ 0xF)\n                  + ((reinterpret_cast<std::ptrdiff_t> (in)) & 0xF));\n\n          if (out == in)\n            otmp = itmp;\n        }\n\n      *cur_plan_p\n        = fftwf_plan_many_dft (rank, tmp, howmany,\n                               reinterpret_cast<fftwf_complex *> (itmp),\n                               nullptr, stride, dist,\n                               reinterpret_cast<fftwf_complex *> (otmp),\n                               nullptr, stride, dist, dir, plan_flags);\n\n      if (*cur_plan_p == nullptr)\n        (*current_liboctave_error_handler) (\"Error creating FFTW plan\");\n    }\n\n  return *cur_plan_p;\n}\n\nvoid *\nfloat_fftw_planner::do_create_plan (const int rank, const dim_vector& dims,\n                                    octave_idx_type howmany,\n                                    octave_idx_type stride,\n                                    octave_idx_type dist,\n                                    const float *in, FloatComplex *out)\n{\n  fftwf_plan *cur_plan_p = reinterpret_cast<fftwf_plan *> (&m_rplan);\n  bool create_new_plan = false;\n  bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out);\n\n  // Don't create a new plan if we have a non SIMD plan already but\n  // can do SIMD.  This prevents endlessly recreating plans if we\n  // change the alignment.\n\n  if (m_rplan == nullptr || m_rd != dist || m_rs != stride || m_rr != rank\n      || m_rh != howmany || ((ioalign != m_rsimd_align) ? ! ioalign : false))\n    create_new_plan = true;\n  else\n    {\n      // We still might not have the same shape of array.\n\n      for (int i = 0; i < rank; i++)\n        if (dims(i) != m_rn(i))\n          {\n            create_new_plan = true;\n            break;\n          }\n    }\n\n  if (create_new_plan)\n    {\n      m_rd = dist;\n      m_rs = stride;\n      m_rr = rank;\n      m_rh = howmany;\n      m_rsimd_align = ioalign;\n      m_rn = dims;\n\n      // Note reversal of dimensions for column major storage in FFTW.\n      octave_idx_type nn = 1;\n      OCTAVE_LOCAL_BUFFER (int, tmp, rank);\n\n      for (int i = 0, j = rank-1; i < rank; i++, j--)\n        {\n          tmp[i] = dims(j);\n          nn *= dims(j);\n        }\n\n      int plan_flags = 0;\n      bool plan_destroys_in = true;\n\n      switch (m_meth)\n        {\n        case UNKNOWN:\n        case ESTIMATE:\n          plan_flags |= FFTW_ESTIMATE;\n          plan_destroys_in = false;\n          break;\n        case MEASURE:\n          plan_flags |= FFTW_MEASURE;\n          break;\n        case PATIENT:\n          plan_flags |= FFTW_PATIENT;\n          break;\n        case EXHAUSTIVE:\n          plan_flags |= FFTW_EXHAUSTIVE;\n          break;\n        case HYBRID:\n          if (nn < 8193)\n            plan_flags |= FFTW_MEASURE;\n          else\n            {\n              plan_flags |= FFTW_ESTIMATE;\n              plan_destroys_in = false;\n            }\n          break;\n        }\n\n      if (ioalign)\n        plan_flags &= ~FFTW_UNALIGNED;\n      else\n        plan_flags |= FFTW_UNALIGNED;\n\n      if (*cur_plan_p)\n        fftwf_destroy_plan (*cur_plan_p);\n\n      OCTAVE_SCOPED_BUFFER_ANCHOR (float, itmp);\n      itmp = const_cast<float *> (in);\n      FloatComplex *otmp = out;\n\n      if (plan_destroys_in)\n        {\n          // Create matrix with the same size and 16-byte alignment as input\n          octave_idx_type in_place = reinterpret_cast<float *> (out) == in;\n          OCTAVE_SCOPED_BUFFER (float, itmp,\n                                nn * howmany * (in_place + 1) + 32);\n          itmp = reinterpret_cast<float *>\n                 (((reinterpret_cast<std::ptrdiff_t> (itmp) + 15) & ~ 0xF)\n                  + ((reinterpret_cast<std::ptrdiff_t> (in)) & 0xF));\n\n          if (in_place)\n            otmp = reinterpret_cast<FloatComplex *> (itmp);\n        }\n\n      *cur_plan_p\n        = fftwf_plan_many_dft_r2c (rank, tmp, howmany, itmp,\n                                   nullptr, stride, dist,\n                                   reinterpret_cast<fftwf_complex *> (otmp),\n                                   nullptr, stride, dist, plan_flags);\n\n      if (*cur_plan_p == nullptr)\n        (*current_liboctave_error_handler) (\"Error creating FFTW plan\");\n    }\n\n  return *cur_plan_p;\n}\n\nfloat_fftw_planner::FftwMethod\nfloat_fftw_planner::do_method ()\n{\n  return m_meth;\n}\n\nfloat_fftw_planner::FftwMethod\nfloat_fftw_planner::do_method (FftwMethod _meth)\n{\n  FftwMethod ret = m_meth;\n  if (_meth == ESTIMATE || _meth == MEASURE\n      || _meth == PATIENT || _meth == EXHAUSTIVE\n      || _meth == HYBRID)\n    {\n      if (m_meth != _meth)\n        {\n          m_meth = _meth;\n          if (m_rplan)\n            fftwf_destroy_plan (reinterpret_cast<fftwf_plan> (m_rplan));\n          if (m_plan[0])\n            fftwf_destroy_plan (reinterpret_cast<fftwf_plan> (m_plan[0]));\n          if (m_plan[1])\n            fftwf_destroy_plan (reinterpret_cast<fftwf_plan> (m_plan[1]));\n          m_rplan = m_plan[0] = m_plan[1] = nullptr;\n        }\n    }\n  else\n    ret = UNKNOWN;\n  return ret;\n}\n\ntemplate <typename T>\nstatic inline void\nconvert_packcomplex_1d (T *out, std::size_t nr, std::size_t nc,\n                        octave_idx_type stride, octave_idx_type dist)\n{\n  octave_quit ();\n\n  // Fill in the missing data.\n\n  for (std::size_t i = 0; i < nr; i++)\n    for (std::size_t j = nc/2+1; j < nc; j++)\n      out[j*stride + i*dist] = conj (out[(nc - j)*stride + i*dist]);\n\n  octave_quit ();\n}\n\ntemplate <typename T>\nstatic inline void\nconvert_packcomplex_Nd (T *out, const dim_vector& dv)\n{\n  std::size_t nc = dv(0);\n  std::size_t nr = dv(1);\n  std::size_t np = (dv.ndims () > 2 ? dv.numel () / nc / nr : 1);\n  std::size_t nrp = nr * np;\n  T *ptr1, *ptr2;\n\n  octave_quit ();\n\n  // Create space for the missing elements.\n\n  for (std::size_t i = 0; i < nrp; i++)\n    {\n      ptr1 = out + i * (nc/2 + 1) + nrp*((nc-1)/2);\n      ptr2 = out + i * nc;\n      for (std::size_t j = 0; j < nc/2+1; j++)\n        *ptr2++ = *ptr1++;\n    }\n\n  octave_quit ();\n\n  // Fill in the missing data for the rank = 2 case directly for speed.\n\n  for (std::size_t i = 0; i < np; i++)\n    {\n      for (std::size_t j = 1; j < nr; j++)\n        for (std::size_t k = nc/2+1; k < nc; k++)\n          out[k + (j + i*nr)*nc] = conj (out[nc - k + ((i+1)*nr - j)*nc]);\n\n      for (std::size_t j = nc/2+1; j < nc; j++)\n        out[j + i*nr*nc] = conj (out[(i*nr+1)*nc - j]);\n    }\n\n  octave_quit ();\n\n  // Now do the permutations needed for rank > 2 cases.\n\n  std::size_t jstart = dv(0) * dv(1);\n  std::size_t kstep = dv(0);\n  std::size_t nel = dv.numel ();\n\n  for (int inner = 2; inner < dv.ndims (); inner++)\n    {\n      std::size_t jmax = jstart * dv(inner);\n      for (std::size_t i = 0; i < nel; i+=jmax)\n        for (std::size_t j = jstart, jj = jmax-jstart; j < jj;\n             j+=jstart, jj-=jstart)\n          for (std::size_t k = 0; k < jstart; k+= kstep)\n            for (std::size_t l = nc/2+1; l < nc; l++)\n              {\n                T tmp = out[i+ j + k + l];\n                out[i + j + k + l] = out[i + jj + k + l];\n                out[i + jj + k + l] = tmp;\n              }\n      jstart = jmax;\n    }\n\n  octave_quit ();\n}\n\nint\nfftw::fft (const double *in, Complex *out, std::size_t npts,\n           std::size_t nsamples, octave_idx_type stride,\n           octave_idx_type dist)\n{\n  dist = (dist < 0 ? npts : dist);\n\n  dim_vector dv (npts, 1);\n  void *vplan = fftw_planner::create_plan (1, dv, nsamples,\n                stride, dist, in, out);\n  fftw_plan m_plan = reinterpret_cast<fftw_plan> (vplan);\n\n  fftw_execute_dft_r2c (m_plan, (const_cast<double *> (in)),\n                        reinterpret_cast<fftw_complex *> (out));\n\n  // Need to create other half of the transform.\n\n  convert_packcomplex_1d (out, nsamples, npts, stride, dist);\n\n  return 0;\n}\n\nint\nfftw::fft (const Complex *in, Complex *out, std::size_t npts,\n           std::size_t nsamples, octave_idx_type stride,\n           octave_idx_type dist)\n{\n  dist = (dist < 0 ? npts : dist);\n\n  dim_vector dv (npts, 1);\n  void *vplan = fftw_planner::create_plan (FFTW_FORWARD, 1, dv,\n                nsamples, stride,\n                dist, in, out);\n  fftw_plan m_plan = reinterpret_cast<fftw_plan> (vplan);\n\n  fftw_execute_dft (m_plan,\n                    reinterpret_cast<fftw_complex *> (const_cast<Complex *> (in)),\n                    reinterpret_cast<fftw_complex *> (out));\n\n  return 0;\n}\n\nint\nfftw::ifft (const Complex *in, Complex *out, std::size_t npts,\n            std::size_t nsamples, octave_idx_type stride,\n            octave_idx_type dist)\n{\n  dist = (dist < 0 ? npts : dist);\n\n  dim_vector dv (npts, 1);\n  void *vplan = fftw_planner::create_plan (FFTW_BACKWARD, 1, dv, nsamples,\n                stride, dist, in, out);\n  fftw_plan m_plan = reinterpret_cast<fftw_plan> (vplan);\n\n  fftw_execute_dft (m_plan,\n                    reinterpret_cast<fftw_complex *> (const_cast<Complex *> (in)),\n                    reinterpret_cast<fftw_complex *> (out));\n\n  const Complex scale = npts;\n  for (std::size_t j = 0; j < nsamples; j++)\n    for (std::size_t i = 0; i < npts; i++)\n      out[i*stride + j*dist] /= scale;\n\n  return 0;\n}\n\nint\nfftw::fftNd (const double *in, Complex *out, const int rank,\n             const dim_vector& dv)\n{\n  octave_idx_type dist = 1;\n  for (int i = 0; i < rank; i++)\n    dist *= dv(i);\n\n  // Fool with the position of the start of the output matrix, so that\n  // creating other half of the matrix won't cause cache problems.\n\n  octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2);\n\n  void *vplan = fftw_planner::create_plan (rank, dv, 1, 1, dist,\n                in, out + offset);\n  fftw_plan m_plan = reinterpret_cast<fftw_plan> (vplan);\n\n  fftw_execute_dft_r2c (m_plan, (const_cast<double *> (in)),\n                        reinterpret_cast<fftw_complex *> (out+ offset));\n\n  // Need to create other half of the transform.\n\n  convert_packcomplex_Nd (out, dv);\n\n  return 0;\n}\n\nint\nfftw::fftNd (const Complex *in, Complex *out, const int rank,\n             const dim_vector& dv)\n{\n  octave_idx_type dist = 1;\n  for (int i = 0; i < rank; i++)\n    dist *= dv(i);\n\n  void *vplan = fftw_planner::create_plan (FFTW_FORWARD, rank, dv,\n                1, 1, dist, in, out);\n  fftw_plan m_plan = reinterpret_cast<fftw_plan> (vplan);\n\n  fftw_execute_dft (m_plan,\n                    reinterpret_cast<fftw_complex *> (const_cast<Complex *> (in)),\n                    reinterpret_cast<fftw_complex *> (out));\n\n  return 0;\n}\n\nint\nfftw::ifftNd (const Complex *in, Complex *out, const int rank,\n              const dim_vector& dv)\n{\n  octave_idx_type dist = 1;\n  for (int i = 0; i < rank; i++)\n    dist *= dv(i);\n\n  void *vplan = fftw_planner::create_plan (FFTW_BACKWARD, rank, dv,\n                1, 1, dist, in, out);\n  fftw_plan m_plan = reinterpret_cast<fftw_plan> (vplan);\n\n  fftw_execute_dft (m_plan,\n                    reinterpret_cast<fftw_complex *> (const_cast<Complex *> (in)),\n                    reinterpret_cast<fftw_complex *> (out));\n\n  const std::size_t npts = dv.numel ();\n  const Complex scale = npts;\n  for (std::size_t i = 0; i < npts; i++)\n    out[i] /= scale;\n\n  return 0;\n}\n\nint\nfftw::fft (const float *in, FloatComplex *out, std::size_t npts,\n           std::size_t nsamples, octave_idx_type stride,\n           octave_idx_type dist)\n{\n  dist = (dist < 0 ? npts : dist);\n\n  dim_vector dv (npts, 1);\n  void *vplan = float_fftw_planner::create_plan (1, dv, nsamples, stride,\n                dist, in, out);\n  fftwf_plan m_plan = reinterpret_cast<fftwf_plan> (vplan);\n\n  fftwf_execute_dft_r2c (m_plan, (const_cast<float *> (in)),\n                         reinterpret_cast<fftwf_complex *> (out));\n\n  // Need to create other half of the transform.\n\n  convert_packcomplex_1d (out, nsamples, npts, stride, dist);\n\n  return 0;\n}\n\nint\nfftw::fft (const FloatComplex *in, FloatComplex *out, std::size_t npts,\n           std::size_t nsamples, octave_idx_type stride,\n           octave_idx_type dist)\n{\n  dist = (dist < 0 ? npts : dist);\n\n  dim_vector dv (npts, 1);\n  void *vplan = float_fftw_planner::create_plan (FFTW_FORWARD, 1, dv,\n                nsamples, stride, dist,\n                in, out);\n  fftwf_plan m_plan = reinterpret_cast<fftwf_plan> (vplan);\n\n  fftwf_execute_dft (m_plan,\n                     reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *> (in)),\n                     reinterpret_cast<fftwf_complex *> (out));\n\n  return 0;\n}\n\nint\nfftw::ifft (const FloatComplex *in, FloatComplex *out, std::size_t npts,\n            std::size_t nsamples, octave_idx_type stride,\n            octave_idx_type dist)\n{\n  dist = (dist < 0 ? npts : dist);\n\n  dim_vector dv (npts, 1);\n  void *vplan = float_fftw_planner::create_plan (FFTW_BACKWARD, 1, dv,\n                nsamples, stride, dist,\n                in, out);\n  fftwf_plan m_plan = reinterpret_cast<fftwf_plan> (vplan);\n\n  fftwf_execute_dft (m_plan,\n                     reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *> (in)),\n                     reinterpret_cast<fftwf_complex *> (out));\n\n  const FloatComplex scale = npts;\n  for (std::size_t j = 0; j < nsamples; j++)\n    for (std::size_t i = 0; i < npts; i++)\n      out[i*stride + j*dist] /= scale;\n\n  return 0;\n}\n\nint\nfftw::fftNd (const float *in, FloatComplex *out, const int rank,\n             const dim_vector& dv)\n{\n  octave_idx_type dist = 1;\n  for (int i = 0; i < rank; i++)\n    dist *= dv(i);\n\n  // Fool with the position of the start of the output matrix, so that\n  // creating other half of the matrix won't cause cache problems.\n\n  octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2);\n\n  void *vplan = float_fftw_planner::create_plan (rank, dv, 1, 1, dist,\n                in, out + offset);\n  fftwf_plan m_plan = reinterpret_cast<fftwf_plan> (vplan);\n\n  fftwf_execute_dft_r2c (m_plan, (const_cast<float *> (in)),\n                         reinterpret_cast<fftwf_complex *> (out+ offset));\n\n  // Need to create other half of the transform.\n\n  convert_packcomplex_Nd (out, dv);\n\n  return 0;\n}\n\nint\nfftw::fftNd (const FloatComplex *in, FloatComplex *out, const int rank,\n             const dim_vector& dv)\n{\n  octave_idx_type dist = 1;\n  for (int i = 0; i < rank; i++)\n    dist *= dv(i);\n\n  void *vplan = float_fftw_planner::create_plan (FFTW_FORWARD, rank, dv,\n                1, 1, dist, in, out);\n  fftwf_plan m_plan = reinterpret_cast<fftwf_plan> (vplan);\n\n  fftwf_execute_dft (m_plan,\n                     reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *> (in)),\n                     reinterpret_cast<fftwf_complex *> (out));\n\n  return 0;\n}\n\nint\nfftw::ifftNd (const FloatComplex *in, FloatComplex *out, const int rank,\n              const dim_vector& dv)\n{\n  octave_idx_type dist = 1;\n  for (int i = 0; i < rank; i++)\n    dist *= dv(i);\n\n  void *vplan = float_fftw_planner::create_plan (FFTW_BACKWARD, rank, dv,\n                1, 1, dist, in, out);\n  fftwf_plan m_plan = reinterpret_cast<fftwf_plan> (vplan);\n\n  fftwf_execute_dft (m_plan,\n                     reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *> (in)),\n                     reinterpret_cast<fftwf_complex *> (out));\n\n  const std::size_t npts = dv.numel ();\n  const FloatComplex scale = npts;\n  for (std::size_t i = 0; i < npts; i++)\n    out[i] /= scale;\n\n  return 0;\n}\n\n#endif\n\nstd::string\nfftw_version ()\n{\n#if defined (HAVE_FFTW)\n  return ::fftw_version;\n#else\n  return \"none\";\n#endif\n}\n\nstd::string\nfftwf_version ()\n{\n#if defined (HAVE_FFTW)\n  return ::fftwf_version;\n#else\n  return \"none\";\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/oct-fftw.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_fftw_h)\n#define octave_oct_fftw_h 1\n\n#include \"octave-config.h\"\n\n#include <cstddef>\n\n#include <string>\n\n#include \"dim-vector.h\"\n#include \"oct-cmplx.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTAVE_API fftw_planner\n{\nprotected:\n\n  fftw_planner ();\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (fftw_planner)\n\n  ~fftw_planner ();\n\n  enum FftwMethod\n  {\n    UNKNOWN = -1,\n    ESTIMATE,\n    MEASURE,\n    PATIENT,\n    EXHAUSTIVE,\n    HYBRID\n  };\n\n  static bool instance_ok ();\n\n  static void *\n  create_plan (int dir, const int rank, const dim_vector& dims,\n               octave_idx_type howmany, octave_idx_type stride,\n               octave_idx_type dist, const Complex *in,\n               Complex *out)\n  {\n    return instance_ok ()\n           ? s_instance->do_create_plan (dir, rank, dims, howmany, stride,\n                                         dist, in, out)\n           : nullptr;\n  }\n\n  static void *\n  create_plan (const int rank, const dim_vector& dims,\n               octave_idx_type howmany, octave_idx_type stride,\n               octave_idx_type dist, const double *in, Complex *out)\n  {\n    return instance_ok ()\n           ? s_instance->do_create_plan (rank, dims, howmany, stride, dist,\n                                         in, out)\n           : nullptr;\n  }\n\n  static FftwMethod method ()\n  {\n    static FftwMethod dummy;\n\n    return instance_ok () ? s_instance->do_method () : dummy;\n  }\n\n  static FftwMethod method (FftwMethod meth)\n  {\n    static FftwMethod dummy;\n\n    return instance_ok () ? s_instance->do_method (meth) : dummy;\n  }\n\n  static void threads (int nt);\n\n  static int threads ()\n  {\n    return instance_ok () ? s_instance->m_nthreads : 0;\n  }\n\nprivate:\n\n  static fftw_planner *s_instance;\n\n  static void cleanup_instance ()\n  { delete s_instance; s_instance = nullptr; }\n\n  void *\n  do_create_plan (int dir, const int rank, const dim_vector& dims,\n                  octave_idx_type howmany, octave_idx_type stride,\n                  octave_idx_type dist, const Complex *in,\n                  Complex *out);\n\n  void *\n  do_create_plan (const int rank, const dim_vector& dims,\n                  octave_idx_type howmany, octave_idx_type stride,\n                  octave_idx_type dist, const double *in, Complex *out);\n\n  FftwMethod do_method ();\n\n  FftwMethod do_method (FftwMethod meth);\n\n  FftwMethod m_meth;\n\n  // FIXME: perhaps this should be split into two classes?\n\n  // Plan for fft and ifft of complex values\n  void *m_plan[2];\n\n  // dist\n  octave_idx_type m_d[2];\n\n  // stride\n  octave_idx_type m_s[2];\n\n  // rank\n  int m_r[2];\n\n  // howmany\n  octave_idx_type m_h[2];\n\n  // dims\n  dim_vector m_n[2];\n\n  bool m_simd_align[2];\n  bool m_inplace[2];\n\n  // Plan for fft of real values\n  void *m_rplan;\n\n  // dist\n  octave_idx_type m_rd;\n\n  // stride\n  octave_idx_type m_rs;\n\n  // rank\n  int m_rr;\n\n  // howmany\n  octave_idx_type m_rh;\n\n  // dims\n  dim_vector m_rn;\n\n  bool m_rsimd_align;\n\n  // number of threads.  Always 1 unless compiled with multi-threading\n  // support.\n  int m_nthreads;\n};\n\nclass OCTAVE_API float_fftw_planner\n{\nprotected:\n\n  float_fftw_planner ();\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (float_fftw_planner)\n\n  ~float_fftw_planner ();\n\n  enum FftwMethod\n  {\n    UNKNOWN = -1,\n    ESTIMATE,\n    MEASURE,\n    PATIENT,\n    EXHAUSTIVE,\n    HYBRID\n  };\n\n  static bool instance_ok ();\n\n  static void *\n  create_plan (int dir, const int rank, const dim_vector& dims,\n               octave_idx_type howmany, octave_idx_type stride,\n               octave_idx_type dist, const FloatComplex *in,\n               FloatComplex *out)\n  {\n    return instance_ok ()\n           ? s_instance->do_create_plan (dir, rank, dims, howmany, stride,\n                                         dist, in, out)\n           : nullptr;\n  }\n\n  static void *\n  create_plan (const int rank, const dim_vector& dims,\n               octave_idx_type howmany, octave_idx_type stride,\n               octave_idx_type dist, const float *in, FloatComplex *out)\n  {\n    return instance_ok ()\n           ? s_instance->do_create_plan (rank, dims, howmany, stride, dist,\n                                         in, out)\n           : nullptr;\n  }\n\n  static FftwMethod method ()\n  {\n    static FftwMethod dummy;\n\n    return instance_ok () ? s_instance->do_method () : dummy;\n  }\n\n  static FftwMethod method (FftwMethod meth)\n  {\n    static FftwMethod dummy;\n\n    return instance_ok () ? s_instance->do_method (meth) : dummy;\n  }\n\n  static void threads (int nt);\n\n  static int threads ()\n  {\n    return instance_ok () ? s_instance->m_nthreads : 0;\n  }\n\nprivate:\n\n  static float_fftw_planner *s_instance;\n\n  static void cleanup_instance ()\n  { delete s_instance; s_instance = nullptr; }\n\n  void *\n  do_create_plan (int dir, const int rank, const dim_vector& dims,\n                  octave_idx_type howmany, octave_idx_type stride,\n                  octave_idx_type dist, const FloatComplex *in,\n                  FloatComplex *out);\n\n  void *\n  do_create_plan (const int rank, const dim_vector& dims,\n                  octave_idx_type howmany, octave_idx_type stride,\n                  octave_idx_type dist, const float *in, FloatComplex *out);\n\n  FftwMethod do_method ();\n\n  FftwMethod do_method (FftwMethod meth);\n\n  FftwMethod m_meth;\n\n  // FIXME: perhaps this should be split into two classes?\n\n  // Plan for fft and ifft of complex values\n  void *m_plan[2];\n\n  // dist\n  octave_idx_type m_d[2];\n\n  // stride\n  octave_idx_type m_s[2];\n\n  // rank\n  int m_r[2];\n\n  // howmany\n  octave_idx_type m_h[2];\n\n  // dims\n  dim_vector m_n[2];\n\n  bool m_simd_align[2];\n  bool m_inplace[2];\n\n  // Plan for fft of real values\n  void *m_rplan;\n\n  // dist\n  octave_idx_type m_rd;\n\n  // stride\n  octave_idx_type m_rs;\n\n  // rank\n  int m_rr;\n\n  // howmany\n  octave_idx_type m_rh;\n\n  // dims\n  dim_vector m_rn;\n\n  bool m_rsimd_align;\n\n  // number of threads.  Always 1 unless compiled with multi-threading\n  // support.\n  int m_nthreads;\n};\n\nclass OCTAVE_API fftw\n{\npublic:\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE_DELETE (fftw)\n\n  static int fft (const double *in, Complex *out, std::size_t npts,\n                  std::size_t nsamples = 1, octave_idx_type stride = 1,\n                  octave_idx_type dist = -1);\n  static int fft (const Complex *in, Complex *out, std::size_t npts,\n                  std::size_t nsamples = 1, octave_idx_type stride = 1,\n                  octave_idx_type dist = -1);\n  static int ifft (const Complex *in, Complex *out, std::size_t npts,\n                   std::size_t nsamples = 1, octave_idx_type stride = 1,\n                   octave_idx_type dist = -1);\n\n  static int fftNd (const double *, Complex *, const int, const dim_vector&);\n  static int fftNd (const Complex *, Complex *, const int,\n                    const dim_vector&);\n  static int ifftNd (const Complex *, Complex *, const int,\n                     const dim_vector&);\n\n  static int fft (const float *in, FloatComplex *out, std::size_t npts,\n                  std::size_t nsamples = 1, octave_idx_type stride = 1,\n                  octave_idx_type dist = -1);\n  static int fft (const FloatComplex *in, FloatComplex *out, std::size_t npts,\n                  std::size_t nsamples = 1, octave_idx_type stride = 1,\n                  octave_idx_type dist = -1);\n  static int ifft (const FloatComplex *in, FloatComplex *out, std::size_t npts,\n                   std::size_t nsamples = 1, octave_idx_type stride = 1,\n                   octave_idx_type dist = -1);\n\n  static int fftNd (const float *, FloatComplex *, const int,\n                    const dim_vector&);\n  static int fftNd (const FloatComplex *, FloatComplex *, const int,\n                    const dim_vector&);\n  static int ifftNd (const FloatComplex *, FloatComplex *, const int,\n                     const dim_vector&);\n};\n\nextern OCTAVE_API std::string fftw_version ();\nextern OCTAVE_API std::string fftwf_version ();\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/oct-norm.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <algorithm>\n#include <iostream>\n#include <limits>\n#include <type_traits>\n#include <vector>\n\n#include \"Array-oct.h\"\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n#include \"CRowVector.h\"\n#include \"CSparse.h\"\n#include \"MArray.h\"\n#include \"blas-proto.h\"\n#include \"dColVector.h\"\n#include \"dDiagMatrix.h\"\n#include \"dMatrix.h\"\n#include \"dRowVector.h\"\n#include \"dSparse.h\"\n#include \"f77-fcn.h\"\n#include \"fCColVector.h\"\n#include \"fCMatrix.h\"\n#include \"fCRowVector.h\"\n#include \"fColVector.h\"\n#include \"fDiagMatrix.h\"\n#include \"fMatrix.h\"\n#include \"fRowVector.h\"\n#include \"lapack-proto.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"mx-cm-s.h\"\n#include \"mx-fcm-fs.h\"\n#include \"mx-fs-fcm.h\"\n#include \"mx-s-cm.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n#include \"oct-norm.h\"\n#include \"quit.h\"\n#include \"svd.h\"\n\n#if defined (HAVE_ARPACK)\n#  include \"eigs-base.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// BLAS NRM2 wrappers for vector 2-norm\n\ninline double\nblas_nrm2 (octave_idx_type n, const double *x, octave_idx_type incx)\n{\n  F77_INT f77_n = to_f77_int (n);\n  F77_INT f77_incx = to_f77_int (incx);\n  F77_DBLE result;\n  F77_FUNC (xdnrm2, XDNRM2) (f77_n, x, f77_incx, result);\n  return result;\n}\n\ninline float\nblas_nrm2 (octave_idx_type n, const float *x, octave_idx_type incx)\n{\n  F77_INT f77_n = to_f77_int (n);\n  F77_INT f77_incx = to_f77_int (incx);\n  F77_REAL result;\n  F77_FUNC (xsnrm2, XSNRM2) (f77_n, x, f77_incx, result);\n  return result;\n}\n\ninline double\nblas_nrm2 (octave_idx_type n, const Complex *x, octave_idx_type incx)\n{\n  F77_INT f77_n = to_f77_int (n);\n  F77_INT f77_incx = to_f77_int (incx);\n  F77_DBLE result;\n  F77_FUNC (xdznrm2, XDZNRM2) (f77_n, F77_CONST_DBLE_CMPLX_ARG (x), f77_incx, result);\n  return result;\n}\n\ninline float\nblas_nrm2 (octave_idx_type n, const FloatComplex *x, octave_idx_type incx)\n{\n  F77_INT f77_n = to_f77_int (n);\n  F77_INT f77_incx = to_f77_int (incx);\n  F77_REAL result;\n  F77_FUNC (xscnrm2, XSCNRM2) (f77_n, F77_CONST_CMPLX_ARG (x), f77_incx, result);\n  return result;\n}\n\n// LAPACK LANGE wrappers for dense matrix norms.\n// norm_type: 'O'/'1' = 1-norm, 'I' = inf-norm, 'F' = Frobenius\n//\n// Note: LANGE mishandles Inf due to internal scaling (Inf/Inf = NaN).\n// We fix this by checking for Inf when LANGE returns NaN.\n\ntemplate <typename T, typename R>\ninline R\nlange_inf_fixup (R result, const T *data, octave_idx_type numel)\n{\n  // LANGE returned NaN - check if it should be Inf instead.\n  // If there's a genuine NaN in input, keep returning NaN.\n  // Only scan the matrix if LANGE returned NaN (no overhead otherwise).\n  if (math::isnan (result))\n    {\n      bool has_inf = false;\n      for (octave_idx_type i = 0; i < numel; i++)\n        {\n          if (math::isnan (data[i]))\n            return result;  // Genuine NaN takes precedence\n          if (math::isinf (data[i]))\n            has_inf = true;\n        }\n      if (has_inf)\n        return numeric_limits<R>::Inf ();\n    }\n  return result;\n}\n\ninline double\nlange (char norm_type, const Matrix& m)\n{\n  F77_INT mm = to_f77_int (m.rows ());\n  F77_INT nn = to_f77_int (m.cols ());\n  F77_INT lda = std::max (mm, static_cast<F77_INT> (1));\n\n  OCTAVE_LOCAL_BUFFER (double, work, mm);\n\n  F77_DBLE result;\n  F77_FUNC (xdlange, XDLANGE) (F77_CONST_CHAR_ARG (&norm_type), mm, nn,\n                               m.data (), lda, work, result\n                               F77_CHAR_ARG_LEN (1));\n  return lange_inf_fixup (result, m.data (), m.numel ());\n}\n\ninline float\nlange (char norm_type, const FloatMatrix& m)\n{\n  F77_INT mm = to_f77_int (m.rows ());\n  F77_INT nn = to_f77_int (m.cols ());\n  F77_INT lda = std::max (mm, static_cast<F77_INT> (1));\n\n  OCTAVE_LOCAL_BUFFER (float, work, mm);\n\n  F77_REAL result;\n  F77_FUNC (xslange, XSLANGE) (F77_CONST_CHAR_ARG (&norm_type), mm, nn,\n                               m.data (), lda, work, result\n                               F77_CHAR_ARG_LEN (1));\n  return lange_inf_fixup (result, m.data (), m.numel ());\n}\n\ninline double\nlange (char norm_type, const ComplexMatrix& m)\n{\n  F77_INT mm = to_f77_int (m.rows ());\n  F77_INT nn = to_f77_int (m.cols ());\n  F77_INT lda = std::max (mm, static_cast<F77_INT> (1));\n\n  OCTAVE_LOCAL_BUFFER (double, work, mm);\n\n  F77_DBLE result;\n  F77_FUNC (xzlange, XZLANGE) (F77_CONST_CHAR_ARG (&norm_type), mm, nn,\n                               F77_CONST_DBLE_CMPLX_ARG (m.data ()),\n                               lda, work, result\n                               F77_CHAR_ARG_LEN (1));\n  return lange_inf_fixup (result, m.data (), m.numel ());\n}\n\ninline float\nlange (char norm_type, const FloatComplexMatrix& m)\n{\n  F77_INT mm = to_f77_int (m.rows ());\n  F77_INT nn = to_f77_int (m.cols ());\n  F77_INT lda = std::max (mm, static_cast<F77_INT> (1));\n\n  OCTAVE_LOCAL_BUFFER (float, work, mm);\n\n  F77_REAL result;\n  F77_FUNC (xclange, XCLANGE) (F77_CONST_CHAR_ARG (&norm_type),\n                               mm, nn, F77_CONST_CMPLX_ARG (m.data ()),\n                               lda, work, result\n                               F77_CHAR_ARG_LEN (1));\n  return lange_inf_fixup (result, m.data (), m.numel ());\n}\n\n// Norm accumulators for various norms.\n// Reference: N. Higham, \"Estimating the Matrix p-Norm\",\n// Numer. Math., 62, pp. 539-555, 1992.\n//\n// For float types, we accumulate in double for better precision.\n// For double types, we use Hammarling scaling to avoid overflow/underflow.\n// Kahan compensation is NOT used since these accumulators are primarily\n// used in iterative methods where sqrt(eps) precision is sufficient.\n\n// Accumulator type: float promotes to double for better precision\ntemplate <typename R>\nusing accum_type = std::conditional_t<std::is_same_v<R, float>, double, R>;\n\n// norm accumulator for the p-norm\n// Uses Hammarling scaling to avoid overflow.\ntemplate <typename R>\nclass norm_accumulator_p\n{\npublic:\n  using AT = accum_type<R>;\n\n  norm_accumulator_p (R pp) : m_p (pp), m_scl (0), m_sum (1) { }\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (norm_accumulator_p)\n\n  template <typename U>\n  void accum (U val)\n  {\n    AT t = std::abs (val);\n    if (t != 0)\n      {\n        if (m_scl == t)\n          m_sum += 1;\n        else if (m_scl < t)\n          {\n            m_sum *= std::pow (m_scl / t, static_cast<AT> (m_p));\n            m_sum += 1;\n            m_scl = t;\n          }\n        else\n          m_sum += std::pow (t / m_scl, static_cast<AT> (m_p));\n      }\n  }\n\n  operator R ()\n  {\n    return static_cast<R> (m_scl * std::pow (m_sum, 1 / static_cast<AT> (m_p)));\n  }\n\nprivate:\n  R m_p;\n  AT m_scl, m_sum;\n};\n\n// norm accumulator for the minus p-pseudonorm\ntemplate <typename R>\nclass norm_accumulator_mp\n{\npublic:\n  using AT = accum_type<R>;\n\n  norm_accumulator_mp (R pp) : m_p (pp), m_scl (0), m_sum (1) { }\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (norm_accumulator_mp)\n\n  template <typename U>\n  void accum (U val)\n  {\n    AT t = 1 / std::abs (val);\n    if (m_scl == t)\n      m_sum += 1;\n    else if (m_scl < t)\n      {\n        m_sum *= std::pow (m_scl / t, static_cast<AT> (m_p));\n        m_sum += 1;\n        m_scl = t;\n      }\n    else if (t != 0)\n      m_sum += std::pow (t / m_scl, static_cast<AT> (m_p));\n  }\n\n  operator R ()\n  {\n    return static_cast<R> (m_scl * std::pow (m_sum, -1 / static_cast<AT> (m_p)));\n  }\n\nprivate:\n  R m_p;\n  AT m_scl, m_sum;\n};\n\n// norm accumulator for the 2-norm (euclidean)\n// Uses Hammarling scaling to avoid overflow.\ntemplate <typename R>\nclass norm_accumulator_2\n{\npublic:\n  using AT = accum_type<R>;\n\n  norm_accumulator_2 () : m_scl (0), m_sum (0) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_2)\n\n  void accum (R val)\n  {\n    AT t = std::abs (val);\n    if (t != 0)\n      {\n        if (m_scl == t)\n          m_sum += 1;\n        else if (m_scl < t)\n          {\n            AT r = m_scl / t;\n            m_sum *= r * r;\n            m_sum += 1;\n            m_scl = t;\n          }\n        else\n          {\n            AT r = t / m_scl;\n            m_sum += r * r;\n          }\n      }\n  }\n\n  void accum (std::complex<R> val)\n  {\n    accum (val.real ());\n    accum (val.imag ());\n  }\n\n  operator R ()\n  {\n    return static_cast<R> (m_scl * std::sqrt (m_sum));\n  }\n\nprivate:\n  AT m_scl, m_sum;\n};\n\n// norm accumulator for the 1-norm (city metric)\ntemplate <typename R>\nclass norm_accumulator_1\n{\npublic:\n  using AT = accum_type<R>;\n\n  norm_accumulator_1 () : m_sum (0) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_1)\n\n  template <typename U>\n  void accum (U val)\n  {\n    m_sum += std::abs (val);\n  }\n\n  operator R () { return static_cast<R> (m_sum); }\n\nprivate:\n  AT m_sum;\n};\n\n// norm accumulator for the inf-norm (max metric)\ntemplate <typename R>\nclass norm_accumulator_inf\n{\npublic:\n\n  norm_accumulator_inf () : m_max (0) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_inf)\n\n  template <typename U>\n  void accum (U val)\n  {\n    if (math::isnan (val))\n      m_max = numeric_limits<R>::NaN ();\n    else\n      m_max = std::max (m_max, std::abs (val));\n  }\n\n  operator R () { return m_max; }\n\nprivate:\n  R m_max;\n};\n\n// norm accumulator for the -inf pseudonorm (min abs value)\ntemplate <typename R>\nclass norm_accumulator_minf\n{\npublic:\n\n  norm_accumulator_minf () : m_min (numeric_limits<R>::Inf ()) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_minf)\n\n  template <typename U>\n  void accum (U val)\n  {\n    if (math::isnan (val))\n      m_min = numeric_limits<R>::NaN ();\n    else\n      m_min = std::min (m_min, std::abs (val));\n  }\n\n  operator R () { return m_min; }\n\nprivate:\n  R m_min;\n};\n\n// norm accumulator for the 0-pseudonorm (hamming distance)\ntemplate <typename R>\nclass norm_accumulator_0\n{\npublic:\n\n  norm_accumulator_0 () : m_num (0) { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_0)\n\n  template <typename U>\n  void accum (U val)\n  {\n    if (val != static_cast<U> (0)) ++m_num;\n  }\n\n  operator R () { return m_num; }\n\nprivate:\n  unsigned int m_num;\n};\n\n// OK, we're armed :) Now let's go for the fun\n\ntemplate <typename T, typename R, typename ACC>\ninline void\nvector_norm (const Array<T>& v, R& res, ACC acc)\n{\n  for (octave_idx_type i = 0; i < v.numel (); i++)\n    acc.accum (v(i));\n\n  res = acc;\n}\n\n// sparse version - only iterates over nonzero elements\ntemplate <typename T, typename R, typename ACC>\ninline void\nvector_norm (const MSparse<T>& v, R& res, ACC acc)\n{\n  octave_idx_type nnz = v.nnz ();\n  for (octave_idx_type i = 0; i < nnz; i++)\n    acc.accum (v.data (i));\n\n  res = acc;\n}\n\n// dense versions\ntemplate <typename T, typename R, typename ACC>\nvoid\ncolumn_norms (const MArray<T>& m, MArray<R>& res, ACC acc)\n{\n  res = MArray<R> (dim_vector (1, m.columns ()));\n  for (octave_idx_type j = 0; j < m.columns (); j++)\n    {\n      ACC accj = acc;\n      for (octave_idx_type i = 0; i < m.rows (); i++)\n        accj.accum (m(i, j));\n\n      res.xelem (j) = accj;\n    }\n}\n\ntemplate <typename T, typename R, typename ACC>\nvoid\nrow_norms (const MArray<T>& m, MArray<R>& res, ACC acc)\n{\n  res = MArray<R> (dim_vector (m.rows (), 1));\n  std::vector<ACC> acci (m.rows (), acc);\n  for (octave_idx_type j = 0; j < m.columns (); j++)\n    {\n      for (octave_idx_type i = 0; i < m.rows (); i++)\n        acci[i].accum (m(i, j));\n    }\n\n  for (octave_idx_type i = 0; i < m.rows (); i++)\n    res.xelem (i) = acci[i];\n}\n\n// sparse versions\ntemplate <typename T, typename R, typename ACC>\nvoid\ncolumn_norms (const MSparse<T>& m, MArray<R>& res, ACC acc)\n{\n  res = MArray<R> (dim_vector (1, m.columns ()));\n  for (octave_idx_type j = 0; j < m.columns (); j++)\n    {\n      ACC accj = acc;\n      for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++)\n        accj.accum (m.data (k));\n\n      res.xelem (j) = accj;\n    }\n}\n\ntemplate <typename T, typename R, typename ACC>\nvoid\nrow_norms (const MSparse<T>& m, MArray<R>& res, ACC acc)\n{\n  res = MArray<R> (dim_vector (m.rows (), 1));\n  std::vector<ACC> acci (m.rows (), acc);\n  for (octave_idx_type j = 0; j < m.columns (); j++)\n    {\n      for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++)\n        acci[m.ridx (k)].accum (m.data (k));\n    }\n\n  for (octave_idx_type i = 0; i < m.rows (); i++)\n    res.xelem (i) = acci[i];\n}\n\n// Dense vector 2-norm using BLAS NRM2\ntemplate <typename T, typename R>\ninline R\nvector_norm_2_blas (const MArray<T>& v)\n{\n  return blas_nrm2 (v.numel (), v.data (), 1);\n}\n\n// Dispatcher for dense arrays - use BLAS for 2-norm\ntemplate <typename T, typename R>\nR\nvector_norm (const MArray<T>& v, R p)\n{\n  R res;\n  if (p == 2)\n    res = vector_norm_2_blas<T, R> (v);\n  else if (p == 1)\n    vector_norm (v, res, norm_accumulator_1<R> ());\n  else if (math::isinf (p))\n    {\n      if (p > 0)\n        vector_norm (v, res, norm_accumulator_inf<R> ());\n      else\n        vector_norm (v, res, norm_accumulator_minf<R> ());\n    }\n  else if (p == 0)\n    vector_norm (v, res, norm_accumulator_0<R> ());\n  else if (p > 0)\n    vector_norm (v, res, norm_accumulator_p<R> (p));\n  else\n    vector_norm (v, res, norm_accumulator_mp<R> (p));\n  return res;\n}\n\n// Dispatcher for sparse arrays - accumulators only (no BLAS)\ntemplate <typename T, typename R>\nR\nvector_norm (const MSparse<T>& v, R p)\n{\n  R res;\n  if (p == 2)\n    vector_norm (v, res, norm_accumulator_2<R> ());\n  else if (p == 1)\n    vector_norm (v, res, norm_accumulator_1<R> ());\n  else if (math::isinf (p))\n    {\n      if (p > 0)\n        vector_norm (v, res, norm_accumulator_inf<R> ());\n      else\n        vector_norm (v, res, norm_accumulator_minf<R> ());\n    }\n  else if (p == 0)\n    vector_norm (v, res, norm_accumulator_0<R> ());\n  else if (p > 0)\n    vector_norm (v, res, norm_accumulator_p<R> (p));\n  else\n    vector_norm (v, res, norm_accumulator_mp<R> (p));\n  return res;\n}\n\n// Dispatchers for column/row norms (use accumulators)\n#define DEFINE_COLROW_DISPATCHER(FCN_NAME, ARG_TYPE, RES_TYPE)  \\\ntemplate <typename T, typename R>                               \\\nRES_TYPE FCN_NAME (const ARG_TYPE& v, R p)                      \\\n{                                                               \\\n  RES_TYPE res;                                                 \\\n  if (p == 2)                                                   \\\n    FCN_NAME (v, res, norm_accumulator_2<R> ());                \\\n  else if (p == 1)                                              \\\n    FCN_NAME (v, res, norm_accumulator_1<R> ());                \\\n  else if (math::isinf (p))                                     \\\n    {                                                           \\\n      if (p > 0)                                                \\\n        FCN_NAME (v, res, norm_accumulator_inf<R> ());          \\\n      else                                                      \\\n        FCN_NAME (v, res, norm_accumulator_minf<R> ());         \\\n    }                                                           \\\n  else if (p == 0)                                              \\\n    FCN_NAME (v, res, norm_accumulator_0<R> ());                \\\n  else if (p > 0)                                               \\\n    FCN_NAME (v, res, norm_accumulator_p<R> (p));               \\\n  else                                                          \\\n    FCN_NAME (v, res, norm_accumulator_mp<R> (p));              \\\n  return res;                                                   \\\n}\n\nDEFINE_COLROW_DISPATCHER (column_norms, MArray<T>, MArray<R>)\nDEFINE_COLROW_DISPATCHER (row_norms, MArray<T>, MArray<R>)\nDEFINE_COLROW_DISPATCHER (column_norms, MSparse<T>, MArray<R>)\nDEFINE_COLROW_DISPATCHER (row_norms, MSparse<T>, MArray<R>)\n\n// The approximate subproblem in Higham's method.  Find lambda and mu such\n// that norm ([lambda, mu], p) == 1 and norm (y*lambda + col*mu, p) is\n// maximized.\n// Real version.  As in Higham's paper.\ntemplate <typename ColVectorT, typename R>\nstatic void\nhigham_subp (const ColVectorT& y, const ColVectorT& col,\n             octave_idx_type nsamp, R p, R& lambda, R& mu)\n{\n  R nrm = 0;\n  for (octave_idx_type i = 0; i < nsamp; i++)\n    {\n      octave_quit ();\n      R fi = i * static_cast<R> (M_PI) / nsamp;\n      R lambda1 = cos (fi);\n      R mu1 = sin (fi);\n      R lmnr = std::pow (std::pow (std::abs (lambda1), p)\n                         + std::pow (std::abs (mu1), p), 1 / p);\n      lambda1 /= lmnr; mu1 /= lmnr;\n      R nrm1 = vector_norm (lambda1 * y + mu1 * col, p);\n      if (nrm1 > nrm)\n        {\n          lambda = lambda1;\n          mu = mu1;\n          nrm = nrm1;\n        }\n    }\n}\n\n// Complex version.  Higham's paper does not deal with complex case, so we\n// use a simple extension.  First, guess the magnitudes as in real version,\n// then try to rotate lambda to improve further.\ntemplate <typename ColVectorT, typename R>\nstatic void\nhigham_subp (const ColVectorT& y, const ColVectorT& col,\n             octave_idx_type nsamp, R p,\n             std::complex<R>& lambda, std::complex<R>& mu)\n{\n  typedef std::complex<R> CR;\n  R nrm = 0;\n  lambda = 1.0;\n  CR lamcu = lambda / std::abs (lambda);\n  // Probe magnitudes\n  for (octave_idx_type i = 0; i < nsamp; i++)\n    {\n      octave_quit ();\n      R fi = i * static_cast<R> (M_PI) / nsamp;\n      R lambda1 = cos (fi);\n      R mu1 = sin (fi);\n      R lmnr = std::pow (std::pow (std::abs (lambda1), p)\n                         + std::pow (std::abs (mu1), p), 1 / p);\n      lambda1 /= lmnr; mu1 /= lmnr;\n      R nrm1 = vector_norm (lambda1 * lamcu * y + mu1 * col, p);\n      if (nrm1 > nrm)\n        {\n          lambda = lambda1 * lamcu;\n          mu = mu1;\n          nrm = nrm1;\n        }\n    }\n  R lama = std::abs (lambda);\n  // Probe orientation\n  for (octave_idx_type i = 0; i < nsamp; i++)\n    {\n      octave_quit ();\n      R fi = i * static_cast<R> (M_PI) / nsamp;\n      lamcu = CR (cos (fi), sin (fi));\n      R nrm1 = vector_norm (lama * lamcu * y + mu * col, p);\n      if (nrm1 > nrm)\n        {\n          lambda = lama * lamcu;\n          nrm = nrm1;\n        }\n    }\n}\n\n// the p-dual element (should work for both real and complex)\ntemplate <typename T, typename R>\ninline T\nelem_dual_p (T x, R p)\n{\n  return math::signum (x) * std::pow (std::abs (x), p - 1);\n}\n\n// the VectorT is used for vectors, but actually it has to be\n// a Matrix type to allow all the operations.  For instance SparseMatrix\n// does not support multiplication with column/row vectors.\n// the dual vector\ntemplate <typename VectorT, typename R>\nVectorT\ndual_p (const VectorT& x, R p, R q)\n{\n  VectorT res (x.dims ());\n  for (octave_idx_type i = 0; i < x.numel (); i++)\n    res.xelem (i) = elem_dual_p (x(i), p);\n  return res / vector_norm (res, q);\n}\n\n// Higham's hybrid method\ntemplate <typename MatrixT, typename VectorT, typename R>\nR\nhigham (const MatrixT& m, R p, R tol, int maxiter,\n        VectorT& x)\n{\n  x.resize (m.columns (), 1);\n  // the OSE part\n  VectorT y (m.rows (), 1, 0), z (m.rows (), 1);\n  typedef typename VectorT::element_type RR;\n  RR lambda = 0;\n  RR mu = 1;\n  for (octave_idx_type k = 0; k < m.columns (); k++)\n    {\n      octave_quit ();\n      VectorT col (m.column (k));\n      if (k > 0)\n        higham_subp (y, col, 4*k, p, lambda, mu);\n      for (octave_idx_type i = 0; i < k; i++)\n        x(i) *= lambda;\n      x(k) = mu;\n      y = lambda * y + mu * col;\n    }\n\n  // the PM part\n  x = x / vector_norm (x, p);\n  R q = p / (p - 1);\n\n  R gamma = 0, gamma1;\n  int iter = 0;\n  while (iter < maxiter)\n    {\n      octave_quit ();\n      y = m * x;\n      gamma1 = gamma;\n      gamma = vector_norm (y, p);\n      z = dual_p (y, p, q);\n      z = z.hermitian ();\n      z = z * m;\n\n      if (iter > 0 && (vector_norm (z, q) <= gamma\n                       || (gamma - gamma1) <= tol * gamma))\n        break;\n\n      z = z.hermitian ();\n      x = dual_p (z, q, p);\n      iter++;\n    }\n\n  return gamma;\n}\n\n// derive column vector and SVD types\n\nconstexpr const char *p_less1_gripe = \"xnorm: p must be >= 1\";\n\n// Maximum number of iterations for iterative norm algorithms.\n// 256 seems to be a good value.  Eventually, we can provide a means to change\n// this constant from Octave.\nconstexpr int max_norm_iter = 256;\n\n// version with SVD for dense matrices, uses LAPACK LANGE for 1/Inf norms\ntemplate <typename MatrixT, typename VectorT, typename R>\nR\nsvd_matrix_norm (const MatrixT& m, R p, VectorT)\n{\n  R res = 0;\n  if (p == 2)\n    {\n      math::svd<MatrixT> fact (m, math::svd<MatrixT>::Type::sigma_only);\n      res = fact.singular_values () (0, 0);\n    }\n  else if (p == 1)\n    res = lange ('O', m);\n  else if (math::isinf (p) && p > 1)\n    res = lange ('I', m);\n  else if (p > 1)\n    {\n      VectorT x;\n      const R sqrteps = std::sqrt (std::numeric_limits<R>::epsilon ());\n      res = higham (m, p, sqrteps, max_norm_iter, x);\n    }\n  else\n    (*current_liboctave_error_handler) (\"%s\", p_less1_gripe);\n\n  return res;\n}\n\n// Helper for conjugate that works with real types (no-op for real)\ntemplate <typename T>\nconstexpr T safe_conj (T x)\n{\n  if constexpr (std::is_arithmetic_v<T>)\n    return x;\n  else\n    return std::conj (x);\n}\n\n// Helper for dot product (conjugate-linear in first argument)\ntemplate <typename VectorT>\nauto\nvector_dot (const VectorT& x, const VectorT& y)\n{\n  using T = typename VectorT::element_type;\n  T sum = T (0);\n  for (octave_idx_type i = 0; i < x.numel (); i++)\n    sum += safe_conj (x(i)) * y(i);\n  return sum;\n}\n\n// Power iteration for largest singular value (sparse 2-norm)\n// Computes sigma_max = sqrt(lambda_max(A'*A)) via power method on A'*A\n// This avoids forming A'*A explicitly by using two sparse matvecs per iteration\n// Used as fallback when ARPACK is not available.\ntemplate <typename MatrixT, typename VectorT, typename R>\nR\nsparse_2norm_power (const MatrixT& m, R tol, int maxiter, VectorT)\n{\n  octave_idx_type nc = m.columns ();\n  octave_idx_type nr = m.rows ();\n\n  if (nc == 0 || nr == 0)\n    return R (0);\n\n  // Work with smaller dimension for efficiency\n  const bool use_aat = (nr < nc);\n  octave_idx_type n = std::min (nr, nc);\n\n  // Initialize x = ones(n,1) normalized\n  VectorT x (n, 1, R (1) / std::sqrt (static_cast<R> (n)));\n  VectorT y (n, 1);\n\n  R lambda = 0, lambda_prev = 0;\n\n  for (int iter = 0; iter < maxiter; iter++)\n    {\n      octave_quit ();\n\n      // Compute y = (A'*A)*x or y = (A*A')*x via two sparse matvecs\n      if (use_aat)\n        {\n          // y = A * (A' * x) -- fewer ops when nr < nc\n          auto z = m.hermitian () * x;\n          y = m * z;\n        }\n      else\n        {\n          // y = A' * (A * x) -- fewer ops when nc <= nr\n          auto z = m * x;\n          y = m.hermitian () * z;\n        }\n\n      // Rayleigh quotient: lambda = x' * y\n      lambda_prev = lambda;\n      lambda = std::abs (vector_dot (x, y));\n\n      // Normalize y -> x for next iteration\n      const R norm_y = vector_norm (y, R (2));\n\n      if (norm_y == R (0))\n        return R (0);\n\n      x = y / norm_y;\n\n      // Check convergence\n      if (iter > 0 && std::abs (lambda - lambda_prev) <= tol * lambda)\n        break;\n    }\n\n  return std::sqrt (lambda);\n}\n\n#if defined (HAVE_ARPACK)\n\n// ARPACK-based sparse 2-norm using Implicitly Restarted Lanczos.\n// Builds augmented matrix [0, A; A', 0] whose eigenvalues are +-sigma_i.\n// More robust than power iteration for clustered singular values.\ndouble\nsparse_2norm_arpack (const SparseMatrix& m, double tol, int maxiter)\n{\n  octave_idx_type nc = m.cols ();\n  octave_idx_type nr = m.rows ();\n\n  if (nc == 0 || nr == 0)\n    return 0.0;\n\n  octave_quit ();\n\n  // Build augmented sparse matrix: [0, A; A', 0]\n  // Eigenvalues are +-sigma_i, so max |eigenvalue| = sigma_max\n  octave_idx_type n = nr + nc;\n  SparseMatrix aug (n, n);\n\n  // Insert A in upper-right block (rows 0..nr-1, cols nr..n-1)\n  aug = aug.insert (m, 0, nr);\n\n  octave_quit ();\n\n  // Insert A' in lower-left block (rows nr..n-1, cols 0..nr-1)\n  aug = aug.insert (m.transpose (), nr, 0);\n\n  octave_quit ();\n\n  // Use ARPACK to find largest magnitude eigenvalue\n  octave_idx_type k = 1;              // number of eigenvalues\n  octave_idx_type p = -1;             // auto-select basis size (will become max(2k,20))\n  octave_idx_type info = 0;           // start with random initial vector\n  Matrix eig_vec;\n  ColumnVector eig_val;\n  SparseMatrix B;                     // empty = standard eigenproblem\n  ColumnVector permB;\n  ColumnVector resid;                 // empty = random initial vector\n\n  EigsRealSymmetricMatrix (aug, std::string (\"LM\"), k, p, info,\n                           eig_vec, eig_val, B, permB, resid,\n                           std::cout, tol, false, false, 0, maxiter);\n\n  octave_quit ();\n\n  if (info < 0 || eig_val.numel () == 0)\n    return 0.0;  // ARPACK failed, caller should fall back\n\n  return std::abs (eig_val (0));\n}\n\n// Complex version\ndouble\nsparse_2norm_arpack (const SparseComplexMatrix& m, double tol, int maxiter)\n{\n  octave_idx_type nc = m.cols ();\n  octave_idx_type nr = m.rows ();\n\n  if (nc == 0 || nr == 0)\n    return 0.0;\n\n  octave_quit ();\n\n  // Build augmented sparse matrix: [0, A; A', 0] where A' is conjugate transpose\n  octave_idx_type n = nr + nc;\n  SparseComplexMatrix aug (n, n);\n\n  // Insert A in upper-right block\n  aug = aug.insert (m, 0, nr);\n\n  octave_quit ();\n\n  // Insert A' (hermitian = conjugate transpose) in lower-left block\n  aug = aug.insert (m.hermitian (), nr, 0);\n\n  octave_quit ();\n\n  // For complex matrices, the augmented matrix is Hermitian\n  octave_idx_type k = 1;\n  octave_idx_type p = -1;\n  octave_idx_type info = 0;\n  ComplexMatrix eig_vec;\n  ComplexColumnVector eig_val;\n  SparseComplexMatrix B;\n  ColumnVector permB;\n  ComplexColumnVector resid;\n\n  EigsComplexNonSymmetricMatrix (aug, std::string (\"LM\"), k, p, info,\n                                 eig_vec, eig_val, B, permB, resid,\n                                 std::cout, tol, false, false, 0, maxiter);\n\n  octave_quit ();\n\n  if (info < 0 || eig_val.numel () == 0)\n    return 0.0;\n\n  return std::abs (eig_val (0));\n}\n\n#endif  // HAVE_ARPACK\n\n// Unified sparse 2-norm: use ARPACK when available, fall back to power iteration\ntemplate <typename MatrixT, typename VectorT, typename R>\nR\nsparse_2norm (const MatrixT& m, R tol, int maxiter, VectorT)\n{\n#if defined (HAVE_ARPACK)\n  // Use ARPACK (Lanczos) - more accurate than power iteration\n  R res = sparse_2norm_arpack (m, tol, maxiter);\n  if (res > R (0))\n    return res;\n  // Fall through to power iteration if ARPACK failed\n#endif\n\n  return sparse_2norm_power (m, tol, maxiter, VectorT ());\n}\n\n// SVD-free version for sparse matrices\ntemplate <typename MatrixT, typename VectorT, typename R>\nR\nmatrix_norm (const MatrixT& m, R p, VectorT)\n{\n  R res = 0;\n  if (p == 1)\n    res = xcolnorms (m, static_cast<R> (1)).max ();\n  else if (math::isinf (p) && p > 1)\n    res = xrownorms (m, static_cast<R> (1)).max ();\n  else if (p == 2)\n    {\n      // Use ARPACK (Lanczos) or power iteration for 2-norm (spectral norm)\n      const R sqrteps = std::sqrt (std::numeric_limits<R>::epsilon ());\n      res = sparse_2norm (m, sqrteps, max_norm_iter, VectorT ());\n    }\n  else if (p > 1)\n    {\n      VectorT x;\n      const R sqrteps = std::sqrt (std::numeric_limits<R>::epsilon ());\n      res = higham (m, p, sqrteps, max_norm_iter, x);\n    }\n  else\n    (*current_liboctave_error_handler) (\"%s\", p_less1_gripe);\n\n  return res;\n}\n\n// and finally, here's what we've promised in the header file\n\n#define DEFINE_XNORM_FCNS(PREFIX, RTYPE)                              \\\nRTYPE xnorm (const PREFIX##ColumnVector& x, RTYPE p)                  \\\n{                                                                     \\\n  return vector_norm (x, p);                                          \\\n}                                                                     \\\nRTYPE xnorm (const PREFIX##RowVector& x, RTYPE p)                     \\\n{                                                                     \\\n  return vector_norm (x, p);                                          \\\n}                                                                     \\\nRTYPE xnorm (const PREFIX##Matrix& x, RTYPE p)                        \\\n{                                                                     \\\n  return svd_matrix_norm (x, p, PREFIX##Matrix ());                   \\\n}                                                                     \\\nRTYPE xfrobnorm (const PREFIX##Matrix& x)                             \\\n{                                                                     \\\n  return lange ('F', x);                                              \\\n}\n\nDEFINE_XNORM_FCNS(, double)\nDEFINE_XNORM_FCNS(Complex, double)\nDEFINE_XNORM_FCNS(Float, float)\nDEFINE_XNORM_FCNS(FloatComplex, float)\n\n// Sparse Frobenius norm - use accumulator over nonzeros\ntemplate <typename T, typename R>\ninline void array_norm_2 (const T *v, octave_idx_type n, R& res)\n{\n  norm_accumulator_2<R> acc;\n  for (octave_idx_type i = 0; i < n; i++)\n    acc.accum (v[i]);\n\n  res = acc;\n}\n\n#define DEFINE_XNORM_SPARSE_FCNS(PREFIX, RTYPE)               \\\nRTYPE xnorm (const Sparse##PREFIX##Matrix& x, RTYPE p)        \\\n{                                                             \\\n  return matrix_norm (x, p, PREFIX##Matrix ());               \\\n}                                                             \\\nRTYPE xfrobnorm (const Sparse##PREFIX##Matrix& x)             \\\n{                                                             \\\n  RTYPE res;                                                  \\\n  array_norm_2 (x.data (), x.nnz (), res);                    \\\n  return res;                                                 \\\n}\n\nDEFINE_XNORM_SPARSE_FCNS(, double)\nDEFINE_XNORM_SPARSE_FCNS(Complex, double)\n\n#define DEFINE_COLROW_NORM_FCNS(PREFIX, RPREFIX, RTYPE)       \\\nRPREFIX##RowVector                                            \\\nxcolnorms (const PREFIX##Matrix& m, RTYPE p)                  \\\n{                                                             \\\n  return column_norms (m, p);                                 \\\n}                                                             \\\nRPREFIX##ColumnVector                                         \\\nxrownorms (const PREFIX##Matrix& m, RTYPE p)                  \\\n{                                                             \\\n  return row_norms (m, p);                                    \\\n}                                                             \\\n\nDEFINE_COLROW_NORM_FCNS(, , double)\nDEFINE_COLROW_NORM_FCNS(Complex, , double)\nDEFINE_COLROW_NORM_FCNS(Float, Float, float)\nDEFINE_COLROW_NORM_FCNS(FloatComplex, Float, float)\n\nDEFINE_COLROW_NORM_FCNS(Sparse, , double)\nDEFINE_COLROW_NORM_FCNS(SparseComplex, , double)\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/oct-norm.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_norm_h)\n#define octave_oct_norm_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\n#include \"oct-cmplx.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTAVE_API double xnorm (const ColumnVector&, double p = 2);\nextern OCTAVE_API double xnorm (const RowVector&, double p = 2);\nextern OCTAVE_API double xnorm (const Matrix&, double p = 2);\nextern OCTAVE_API double xfrobnorm (const Matrix&);\n\nextern OCTAVE_API double xnorm (const ComplexColumnVector&, double p = 2);\nextern OCTAVE_API double xnorm (const ComplexRowVector&, double p = 2);\nextern OCTAVE_API double xnorm (const ComplexMatrix&, double p = 2);\nextern OCTAVE_API double xfrobnorm (const ComplexMatrix&);\n\nextern OCTAVE_API float xnorm (const FloatColumnVector&, float p = 2);\nextern OCTAVE_API float xnorm (const FloatRowVector&, float p = 2);\nextern OCTAVE_API float xnorm (const FloatMatrix&, float p = 2);\nextern OCTAVE_API float xfrobnorm (const FloatMatrix&);\n\nextern OCTAVE_API float xnorm (const FloatComplexColumnVector&, float p = 2);\nextern OCTAVE_API float xnorm (const FloatComplexRowVector&, float p = 2);\nextern OCTAVE_API float xnorm (const FloatComplexMatrix&, float p = 2);\nextern OCTAVE_API float xfrobnorm (const FloatComplexMatrix&);\n\nextern OCTAVE_API double xnorm (const SparseMatrix&, double p = 2);\nextern OCTAVE_API double xfrobnorm (const SparseMatrix&);\n\nextern OCTAVE_API double xnorm (const SparseComplexMatrix&, double p = 2);\nextern OCTAVE_API double xfrobnorm (const SparseComplexMatrix&);\n\nextern OCTAVE_API RowVector xcolnorms (const Matrix&, double p = 2);\nextern OCTAVE_API ColumnVector xrownorms (const Matrix&, double p = 2);\n\nextern OCTAVE_API RowVector xcolnorms (const ComplexMatrix&, double p = 2);\nextern OCTAVE_API ColumnVector xrownorms (const ComplexMatrix&, double p = 2);\n\nextern OCTAVE_API FloatRowVector xcolnorms (const FloatMatrix&, float p = 2);\nextern OCTAVE_API FloatColumnVector xrownorms (const FloatMatrix&, float p = 2);\n\nextern OCTAVE_API FloatRowVector xcolnorms (const FloatComplexMatrix&, float p = 2);\nextern OCTAVE_API FloatColumnVector xrownorms (const FloatComplexMatrix&, float p = 2);\n\nextern OCTAVE_API RowVector xcolnorms (const SparseMatrix&, double p = 2);\nextern OCTAVE_API ColumnVector xrownorms (const SparseMatrix&, double p = 2);\n\nextern OCTAVE_API RowVector xcolnorms (const SparseComplexMatrix&, double p = 2);\nextern OCTAVE_API ColumnVector xrownorms (const SparseComplexMatrix&, double p = 2);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/oct-rand.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdint>\n\n#include \"lo-ieee.h\"\n#include \"mach-info.h\"\n#include \"mappers.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-rand.h\"\n#include \"oct-time.h\"\n#include \"quit.h\"\n#include \"randgamma.h\"\n#include \"randmtzig.h\"\n#include \"randpoisson.h\"\n#include \"ranlib-proto.h\"\n#include \"singleton-cleanup.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nrand *rand::s_instance = nullptr;\n\nrand::rand ()\n  : m_current_distribution (uniform_dist), m_use_old_generators (false),\n    m_rand_states ()\n{\n  initialize_ranlib_generators ();\n\n  initialize_mersenne_twister ();\n}\n\nbool\nrand::instance_ok ()\n{\n  bool retval = true;\n\n  if (! s_instance)\n    {\n      s_instance = new rand ();\n      singleton_cleanup_list::add (cleanup_instance);\n    }\n\n  return retval;\n}\n\ndouble\nrand::do_seed ()\n{\n  union d2i { double d; int32_t i[2]; };\n  union d2i u;\n\n  mach_info::float_format ff = mach_info::native_float_format ();\n\n  switch (ff)\n    {\n    case mach_info::flt_fmt_ieee_big_endian:\n      F77_FUNC (getsd, GETSD) (u.i[1], u.i[0]);\n      break;\n\n    default:\n      F77_FUNC (getsd, GETSD) (u.i[0], u.i[1]);\n      break;\n    }\n\n  return u.d;\n}\n\nstatic int32_t\nforce_to_fit_range (int32_t i, int32_t lo, int32_t hi)\n{\n  liboctave_panic_unless (hi > lo && lo >= 0);\n\n  i = (i > 0 ? i : -i);\n\n  if (i < lo)\n    i = lo;\n  else if (i > hi)\n    i = i % hi;\n\n  return i;\n}\n\nvoid\nrand::do_seed (double s)\n{\n  m_use_old_generators = true;\n\n  int i0, i1;\n  union d2i { double d; int32_t i[2]; };\n  union d2i u;\n  u.d = s;\n\n  mach_info::float_format ff = mach_info::native_float_format ();\n\n  switch (ff)\n    {\n    case mach_info::flt_fmt_ieee_big_endian:\n      i1 = force_to_fit_range (u.i[0], 1, 2147483563);\n      i0 = force_to_fit_range (u.i[1], 1, 2147483399);\n      break;\n\n    default:\n      i0 = force_to_fit_range (u.i[0], 1, 2147483563);\n      i1 = force_to_fit_range (u.i[1], 1, 2147483399);\n      break;\n    }\n\n  F77_FUNC (setsd, SETSD) (i0, i1);\n}\n\nvoid\nrand::do_reset ()\n{\n  m_use_old_generators = true;\n  initialize_ranlib_generators ();\n}\n\nuint32NDArray\nrand::do_state (const std::string& d)\n{\n  return m_rand_states[d.empty () ? m_current_distribution : get_dist_id (d)];\n}\n\nvoid\nrand::do_state (const uint32NDArray& s, const std::string& d)\n{\n  m_use_old_generators = false;\n\n  int old_dist = m_current_distribution;\n\n  int new_dist = (d.empty () ? m_current_distribution : get_dist_id (d));\n\n  uint32NDArray saved_state;\n\n  if (old_dist != new_dist)\n    saved_state = get_internal_state ();\n\n  set_internal_state (s);\n\n  m_rand_states[new_dist] = get_internal_state ();\n\n  if (old_dist != new_dist)\n    m_rand_states[old_dist] = saved_state;\n}\n\nvoid\nrand::do_reset (const std::string& d)\n{\n  m_use_old_generators = false;\n\n  int old_dist = m_current_distribution;\n\n  int new_dist = (d.empty () ? m_current_distribution : get_dist_id (d));\n\n  uint32NDArray saved_state;\n\n  if (old_dist != new_dist)\n    saved_state = get_internal_state ();\n\n  init_mersenne_twister ();\n  m_rand_states[new_dist] = get_internal_state ();\n\n  if (old_dist != new_dist)\n    m_rand_states[old_dist] = saved_state;\n}\n\nstd::string\nrand::do_distribution ()\n{\n  std::string retval;\n\n  switch (m_current_distribution)\n    {\n    case uniform_dist:\n      retval = \"uniform\";\n      break;\n\n    case normal_dist:\n      retval = \"normal\";\n      break;\n\n    case expon_dist:\n      retval = \"exponential\";\n      break;\n\n    case poisson_dist:\n      retval = \"poisson\";\n      break;\n\n    case gamma_dist:\n      retval = \"gamma\";\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"rand: invalid distribution ID = %d\", m_current_distribution);\n      break;\n    }\n\n  return retval;\n}\n\nvoid\nrand::do_distribution (const std::string& d)\n{\n  int id = get_dist_id (d);\n\n  switch (id)\n    {\n    case uniform_dist:\n      rand::uniform_distribution ();\n      break;\n\n    case normal_dist:\n      rand::normal_distribution ();\n      break;\n\n    case expon_dist:\n      rand::exponential_distribution ();\n      break;\n\n    case poisson_dist:\n      rand::poisson_distribution ();\n      break;\n\n    case gamma_dist:\n      rand::gamma_distribution ();\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"rand: invalid distribution ID = %d\", id);\n      break;\n    }\n}\n\nvoid\nrand::do_uniform_distribution ()\n{\n  switch_to_generator (uniform_dist);\n\n  F77_FUNC (setcgn, SETCGN) (uniform_dist);\n}\n\nvoid\nrand::do_normal_distribution ()\n{\n  switch_to_generator (normal_dist);\n\n  F77_FUNC (setcgn, SETCGN) (normal_dist);\n}\n\nvoid\nrand::do_exponential_distribution ()\n{\n  switch_to_generator (expon_dist);\n\n  F77_FUNC (setcgn, SETCGN) (expon_dist);\n}\n\nvoid\nrand::do_poisson_distribution ()\n{\n  switch_to_generator (poisson_dist);\n\n  F77_FUNC (setcgn, SETCGN) (poisson_dist);\n}\n\nvoid\nrand::do_gamma_distribution ()\n{\n  switch_to_generator (gamma_dist);\n\n  F77_FUNC (setcgn, SETCGN) (gamma_dist);\n}\n\ntemplate <>\nOCTAVE_API double\nrand::uniform<double> ()\n{\n  double retval;\n\n  if (m_use_old_generators)\n    F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, retval);\n  else\n    retval = rand_uniform<double> ();\n\n  return retval;\n}\n\ntemplate <>\nOCTAVE_API double\nrand::normal<double> ()\n{\n  double retval;\n\n  if (m_use_old_generators)\n    F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, retval);\n  else\n    retval = rand_normal<double> ();\n\n  return retval;\n}\n\ntemplate <>\nOCTAVE_API double\nrand::exponential<double> ()\n{\n  double retval;\n\n  if (m_use_old_generators)\n    F77_FUNC (dgenexp, DGENEXP) (1.0, retval);\n  else\n    retval = rand_exponential<double> ();\n\n  return retval;\n}\n\ntemplate <>\nOCTAVE_API double\nrand::poisson<double> (double a)\n{\n  double retval;\n\n  if (m_use_old_generators)\n    {\n      if (a < 0.0 || ! math::isfinite (a))\n        retval = numeric_limits<double>::NaN ();\n      else\n        {\n          // workaround bug in ignpoi, by calling with different Mu\n          F77_FUNC (dignpoi, DIGNPOI) (a + 1, retval);\n          F77_FUNC (dignpoi, DIGNPOI) (a, retval);\n        }\n    }\n  else\n    retval = rand_poisson<double> (a);\n\n  return retval;\n}\n\ntemplate <>\nOCTAVE_API double\nrand::gamma<double> (double a)\n{\n  double retval;\n\n  if (m_use_old_generators)\n    {\n      if (a <= 0.0 || ! math::isfinite (a))\n        retval = numeric_limits<double>::NaN ();\n      else\n        F77_FUNC (dgengam, DGENGAM) (1.0, a, retval);\n    }\n  else\n    retval = rand_gamma<double> (a);\n\n  return retval;\n}\n\ntemplate <>\nOCTAVE_API float rand::uniform<float> ()\n{\n  float retval;\n\n  if (m_use_old_generators)\n    F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, retval);\n  else\n    retval = rand_uniform<float> ();\n\n  return retval;\n}\n\ntemplate <>\nOCTAVE_API float rand::normal<float> ()\n{\n  float retval;\n\n  if (m_use_old_generators)\n    F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, retval);\n  else\n    retval = rand_normal<float> ();\n\n  return retval;\n}\n\ntemplate <>\nOCTAVE_API float rand::exponential<float> ()\n{\n  float retval;\n\n  if (m_use_old_generators)\n    F77_FUNC (fgenexp, FGENEXP) (1.0f, retval);\n  else\n    retval = rand_exponential<float> ();\n\n  return retval;\n}\n\ntemplate <>\nOCTAVE_API float rand::poisson<float> (float a)\n{\n  float retval;\n\n  if (m_use_old_generators)\n    {\n      if (a < 0.0f || ! math::isfinite (a))\n        retval = numeric_limits<float>::NaN ();\n      else\n        {\n          // workaround bug in ignpoi, by calling with different Mu\n          F77_FUNC (fignpoi, FIGNPOI) (a + 1, retval);\n          F77_FUNC (fignpoi, FIGNPOI) (a, retval);\n        }\n    }\n  else\n    {\n      // Keep poisson distribution in double precision for accuracy\n      retval = rand_poisson<double> (a);\n    }\n\n  return retval;\n}\n\ntemplate <>\nOCTAVE_API float rand::gamma<float> (float a)\n{\n  float retval;\n\n  if (m_use_old_generators)\n    {\n      if (a <= 0.0f || ! math::isfinite (a))\n        retval = numeric_limits<float>::NaN ();\n      else\n        F77_FUNC (fgengam, FGENGAM) (1.0f, a, retval);\n    }\n  else\n    retval = rand_gamma<float> (a);\n\n  return retval;\n}\n\ntemplate <typename T>\nT\nrand::do_scalar (T a)\n{\n  T retval = 0;\n\n  switch (m_current_distribution)\n    {\n    case uniform_dist:\n      retval = uniform<T> ();\n      break;\n\n    case normal_dist:\n      retval = normal<T> ();\n      break;\n\n    case expon_dist:\n      retval = exponential<T> ();\n      break;\n\n    case poisson_dist:\n      retval = poisson<T> (a);\n      break;\n\n    case gamma_dist:\n      retval = gamma<T> (a);\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"rand: invalid distribution ID = %d\", m_current_distribution);\n      break;\n    }\n\n  if (! m_use_old_generators)\n    save_state ();\n\n  return retval;\n}\n\ntemplate OCTAVE_API double rand::do_scalar<double> (double);\ntemplate OCTAVE_API float rand::do_scalar<float> (float);\n\ntemplate <typename T>\nArray<T>\nrand::do_vector (octave_idx_type n, T a)\n{\n  Array<T> retval;\n\n  if (n > 0)\n    {\n      retval.clear (n, 1);\n\n      fill (retval.numel (), retval.rwdata (), a);\n    }\n  else if (n < 0)\n    (*current_liboctave_error_handler) (\"rand: invalid negative argument\");\n\n  return retval;\n}\n\ntemplate OCTAVE_API Array<double>\nrand::do_vector<double> (octave_idx_type, double);\ntemplate OCTAVE_API Array<float>\nrand::do_vector<float> (octave_idx_type, float);\n\nNDArray\nrand::do_nd_array (const dim_vector& dims, double a)\n{\n  NDArray retval;\n\n  if (! dims.all_zero ())\n    {\n      retval.clear (dims);\n\n      fill (retval.numel (), retval.rwdata (), a);\n    }\n\n  return retval;\n}\n\nFloatNDArray\nrand::do_float_nd_array (const dim_vector& dims, float a)\n{\n  FloatNDArray retval;\n\n  if (! dims.all_zero ())\n    {\n      retval.clear (dims);\n\n      fill (retval.numel (), retval.rwdata (), a);\n    }\n\n  return retval;\n}\n\n// Make the random number generator give us a different sequence every\n// time we start octave unless we specifically set the seed.  The\n// technique used below will cycle monthly, but it does seem to\n// work ok to give fairly different seeds each time Octave starts.\n\nvoid\nrand::initialize_ranlib_generators ()\n{\n  sys::localtime tm;\n  int stored_distribution = m_current_distribution;\n  F77_FUNC (setcgn, SETCGN) (uniform_dist);\n\n  int hour = tm.hour () + 1;\n  int minute = tm.min () + 1;\n  int second = tm.sec () + 1;\n\n  int32_t s0 = tm.mday () * hour * minute * second;\n  int32_t s1 = hour * minute * second;\n\n  s0 = force_to_fit_range (s0, 1, 2147483563);\n  s1 = force_to_fit_range (s1, 1, 2147483399);\n\n  F77_FUNC (setall, SETALL) (s0, s1);\n  F77_FUNC (setcgn, SETCGN) (stored_distribution);\n}\n\nvoid\nrand::initialize_mersenne_twister ()\n{\n  uint32NDArray s;\n\n  init_mersenne_twister ();\n  s = get_internal_state ();\n  m_rand_states[uniform_dist] = s;\n\n  init_mersenne_twister ();\n  s = get_internal_state ();\n  m_rand_states[normal_dist] = s;\n\n  init_mersenne_twister ();\n  s = get_internal_state ();\n  m_rand_states[expon_dist] = s;\n\n  init_mersenne_twister ();\n  s = get_internal_state ();\n  m_rand_states[poisson_dist] = s;\n\n  init_mersenne_twister ();\n  s = get_internal_state ();\n  m_rand_states[gamma_dist] = s;\n\n  // All of the initializations above have messed with the internal state.\n  // Restore the state of the currently selected distribution.\n  set_internal_state (m_rand_states[m_current_distribution]);\n}\n\nuint32NDArray\nrand::get_internal_state ()\n{\n  uint32NDArray s (dim_vector (MT_N + 1, 1));\n\n  get_mersenne_twister_state (reinterpret_cast<uint32_t *> (s.rwdata ()));\n\n  return s;\n}\n\nvoid\nrand::save_state ()\n{\n  m_rand_states[m_current_distribution] = get_internal_state ();\n}\n\nint\nrand::get_dist_id (const std::string& d)\n{\n  int retval = unknown_dist;\n\n  if (d == \"uniform\" || d == \"rand\")\n    retval = uniform_dist;\n  else if (d == \"normal\" || d == \"randn\")\n    retval = normal_dist;\n  else if (d == \"exponential\" || d == \"rande\")\n    retval = expon_dist;\n  else if (d == \"poisson\" || d == \"randp\")\n    retval = poisson_dist;\n  else if (d == \"gamma\" || d == \"randg\")\n    retval = gamma_dist;\n  else\n    (*current_liboctave_error_handler)\n      (\"rand: invalid distribution '%s'\", d.c_str ());\n\n  return retval;\n}\n\nvoid\nrand::set_internal_state (const uint32NDArray& s)\n{\n  octave_idx_type len = s.numel ();\n\n  const uint32_t *sdata = reinterpret_cast<const uint32_t *> (s.data ());\n\n  if (len == MT_N + 1 && sdata[MT_N] <= MT_N && sdata[MT_N] > 0)\n    set_mersenne_twister_state (sdata);\n  else\n    init_mersenne_twister (sdata, len);\n}\n\nvoid\nrand::switch_to_generator (int dist)\n{\n  if (dist != m_current_distribution)\n    {\n      m_current_distribution = dist;\n\n      set_internal_state (m_rand_states[dist]);\n    }\n}\n\nvoid\nrand::fill (octave_idx_type len, double *v, double a)\n{\n  if (len < 1)\n    return;\n\n  switch (m_current_distribution)\n    {\n    case uniform_dist:\n      if (m_use_old_generators)\n        std::generate_n (v, len, []() { double x; F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, x); return x; });\n      else\n        rand_uniform<double> (len, v);\n      break;\n\n    case normal_dist:\n      if (m_use_old_generators)\n        std::generate_n (v, len, []() { double x; F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, x); return x; });\n      else\n        rand_normal<double> (len, v);\n      break;\n\n    case expon_dist:\n      if (m_use_old_generators)\n        std::generate_n (v, len, []() { double x; F77_FUNC (dgenexp, DGENEXP) (1.0, x); return x; });\n      else\n        rand_exponential<double> (len, v);\n      break;\n\n    case poisson_dist:\n      if (m_use_old_generators)\n        {\n          if (a < 0.0 || ! math::isfinite (a))\n            std::fill_n (v, len, numeric_limits<double>::NaN ());\n          else\n            {\n              // workaround bug in ignpoi, by calling with different Mu\n              double tmp;\n              F77_FUNC (dignpoi, DIGNPOI) (a + 1, tmp);\n              std::generate_n (v, len, [a]() { double x; F77_FUNC (dignpoi, DIGNPOI) (a, x); return x; });\n            }\n        }\n      else\n        rand_poisson<double> (a, len, v);\n      break;\n\n    case gamma_dist:\n      if (m_use_old_generators)\n        {\n          if (a <= 0.0 || ! math::isfinite (a))\n            std::fill_n (v, len, numeric_limits<double>::NaN ());\n          else\n            std::generate_n (v, len, [a]() { double x; F77_FUNC (dgengam, DGENGAM) (1.0, a, x); return x; });\n        }\n      else\n        rand_gamma<double> (a, len, v);\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"rand: invalid distribution ID = %d\", m_current_distribution);\n      break;\n    }\n\n  save_state ();\n\n  return;\n}\n\nvoid\nrand::fill (octave_idx_type len, float *v, float a)\n{\n  if (len < 1)\n    return;\n\n  switch (m_current_distribution)\n    {\n    case uniform_dist:\n      if (m_use_old_generators)\n        std::generate_n (v, len, []() { float x; F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, x); return x; });\n      else\n        rand_uniform<float> (len, v);\n      break;\n\n    case normal_dist:\n      if (m_use_old_generators)\n        std::generate_n (v, len, []() { float x; F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, x); return x; });\n      else\n        rand_normal<float> (len, v);\n      break;\n\n    case expon_dist:\n      if (m_use_old_generators)\n        std::generate_n (v, len, []() { float x; F77_FUNC (fgenexp, FGENEXP) (1.0f, x); return x; });\n      else\n        rand_exponential<float> (len, v);\n      break;\n\n    case poisson_dist:\n      if (m_use_old_generators)\n        {\n          if (a < 0.0f || ! math::isfinite (a))\n            std::fill_n (v, len, numeric_limits<float>::NaN ());\n          else\n            {\n              // workaround bug in ignpoi, by calling with different Mu\n              float tmp;\n              F77_FUNC (fignpoi, FIGNPOI) (a + 1, tmp);\n              std::generate_n (v, len, [a]() { float x; F77_FUNC (fignpoi, FIGNPOI) (a, x); return x; });\n            }\n        }\n      else\n        rand_poisson<float> (a, len, v);\n      break;\n\n    case gamma_dist:\n      if (m_use_old_generators)\n        {\n          if (a <= 0.0f || ! math::isfinite (a))\n            std::fill_n (v, len, numeric_limits<float>::NaN ());\n          else\n            std::generate_n (v, len, [a]() { float x; F77_FUNC (fgengam, FGENGAM) (1.0f, a, x); return x; });\n        }\n      else\n        rand_gamma<float> (a, len, v);\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"rand: invalid distribution ID = %d\", m_current_distribution);\n      break;\n    }\n\n  save_state ();\n\n  return;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/oct-rand.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_rand_h)\n#define octave_oct_rand_h 1\n\n#include \"octave-config.h\"\n\n#include <map>\n#include <string>\n\n#include \"Array-oct.h\"\n#include \"dNDArray.h\"\n#include \"fNDArray.h\"\n#include \"lo-ieee.h\"\n#include \"uint32NDArray.h\"\n\n//class dim_vector;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTAVE_API rand\n{\nprotected:\n\n  OCTAVE_API rand ();\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (rand)\n\n  ~rand () = default;\n\n  static bool instance_ok ();\n\n  // Return the current seed.\n  static double seed ()\n  {\n    return (instance_ok ()\n            ? s_instance->do_seed () : numeric_limits<double>::NaN ());\n  }\n\n  // Set the seed.\n  static void seed (double s)\n  {\n    if (instance_ok ())\n      s_instance->do_seed (s);\n  }\n\n  // Reset the seed.\n  static void reset ()\n  {\n    if (instance_ok ())\n      s_instance->do_reset ();\n  }\n\n  // Return the current state.\n  static uint32NDArray state (const std::string& d = \"\")\n  {\n    return instance_ok () ? s_instance->do_state (d) : uint32NDArray ();\n  }\n\n  // Set the current state/\n  static void state (const uint32NDArray& s,\n                     const std::string& d = \"\")\n  {\n    if (instance_ok ())\n      s_instance->do_state (s, d);\n  }\n\n  // Reset the current state/\n  static void reset (const std::string& d)\n  {\n    if (instance_ok ())\n      s_instance->do_reset (d);\n  }\n\n  // Return the current distribution.\n  static std::string distribution ()\n  {\n    return instance_ok () ? s_instance->do_distribution () : \"\";\n  }\n\n  // Set the current distribution.  May be either \"uniform\" (the\n  // default), \"normal\", \"exponential\", \"poisson\", or \"gamma\".\n  static void distribution (const std::string& d)\n  {\n    if (instance_ok ())\n      s_instance->do_distribution (d);\n  }\n\n  static void uniform_distribution ()\n  {\n    if (instance_ok ())\n      s_instance->do_uniform_distribution ();\n  }\n\n  static void normal_distribution ()\n  {\n    if (instance_ok ())\n      s_instance->do_normal_distribution ();\n  }\n\n  static void exponential_distribution ()\n  {\n    if (instance_ok ())\n      s_instance->do_exponential_distribution ();\n  }\n\n  static void poisson_distribution ()\n  {\n    if (instance_ok ())\n      s_instance->do_poisson_distribution ();\n  }\n\n  static void gamma_distribution ()\n  {\n    if (instance_ok ())\n      s_instance->do_gamma_distribution ();\n  }\n\n  // Return the next number from the sequence.\n  static double scalar (double a = 1.0)\n  {\n    return (instance_ok ()\n            ? s_instance->do_scalar (a) : numeric_limits<double>::NaN ());\n  }\n\n  // Return the next number from the sequence.\n  static float float_scalar (float a = 1.0)\n  {\n    return (instance_ok ()\n            ? s_instance->do_scalar (a) : numeric_limits<float>::NaN ());\n  }\n\n  // Return an array of numbers from the sequence.\n  static Array<double> vector (octave_idx_type n, double a = 1.0)\n  {\n    return instance_ok () ? s_instance->do_vector (n, a) : Array<double> ();\n  }\n\n  // Return an array of numbers from the sequence.\n  static Array<float> float_vector (octave_idx_type n, float a = 1.0)\n  {\n    return instance_ok () ? s_instance->do_vector (n, a) : Array<float> ();\n  }\n\n  // Return an N-dimensional array of numbers from the sequence,\n  // filled in column major order.\n  static NDArray nd_array (const dim_vector& dims, double a = 1.0)\n  {\n    return instance_ok () ? s_instance->do_nd_array (dims, a) : NDArray ();\n  }\n\n  // Return an N-dimensional array of numbers from the sequence,\n  // filled in column major order.\n  static FloatNDArray float_nd_array (const dim_vector& dims, float a = 1.0)\n  {\n    return (instance_ok ()\n            ? s_instance->do_float_nd_array (dims, a) : FloatNDArray ());\n  }\n\nprivate:\n\n  static rand *s_instance;\n\n  static void cleanup_instance ()\n  { delete s_instance; s_instance = nullptr; }\n\n  enum\n  {\n    unknown_dist,\n    uniform_dist,\n    normal_dist,\n    expon_dist,\n    poisson_dist,\n    gamma_dist\n  };\n\n  // Current distribution of random numbers.\n  int m_current_distribution;\n\n  // If TRUE, use old RANLIB generators.  Otherwise, use Mersenne\n  // Twister generator.\n  bool m_use_old_generators;\n\n  // Saved MT states.\n  std::map<int, uint32NDArray> m_rand_states;\n\n  // Return the current seed.\n  OCTAVE_API double do_seed ();\n\n  // Set the seed.\n  OCTAVE_API void do_seed (double s);\n\n  // Reset the seed.\n  OCTAVE_API void do_reset ();\n\n  // Return the current state.\n  OCTAVE_API uint32NDArray do_state (const std::string& d);\n\n  // Set the current state/\n  OCTAVE_API void do_state (const uint32NDArray& s, const std::string& d);\n\n  // Reset the current state/\n  OCTAVE_API void do_reset (const std::string& d);\n\n  // Return the current distribution.\n  OCTAVE_API std::string do_distribution ();\n\n  // Set the current distribution.  May be either \"uniform\" (the\n  // default), \"normal\", \"exponential\", \"poisson\", or \"gamma\".\n  OCTAVE_API void do_distribution (const std::string& d);\n\n  OCTAVE_API void do_uniform_distribution ();\n\n  OCTAVE_API void do_normal_distribution ();\n\n  OCTAVE_API void do_exponential_distribution ();\n\n  OCTAVE_API void do_poisson_distribution ();\n\n  OCTAVE_API void do_gamma_distribution ();\n\n  // The following templates only make sense for double and float\n  // types.\n\n  template <typename T> OCTAVE_API T uniform ();\n\n  template <typename T> OCTAVE_API T normal ();\n\n  template <typename T> OCTAVE_API T exponential ();\n\n  template <typename T> OCTAVE_API T poisson (T a);\n\n  template <typename T> OCTAVE_API T gamma (T a);\n\n  // Return the next number from the sequence.\n  template <typename T> OCTAVE_API T do_scalar (T a = 1);\n\n  // Return an array of numbers from the sequence.\n  template <typename T> OCTAVE_API Array<T>\n  do_vector (octave_idx_type n, T a = 1);\n\n  // Return an N-dimensional array of numbers from the sequence,\n  // filled in column major order.\n  OCTAVE_API NDArray do_nd_array (const dim_vector& dims, double a = 1.);\n\n  // Return an N-dimensional array of numbers from the sequence,\n  // filled in column major order.\n  OCTAVE_API FloatNDArray\n  do_float_nd_array (const dim_vector& dims, float a = 1.);\n\n  // Some helper functions.\n\n  OCTAVE_API void initialize_ranlib_generators ();\n\n  OCTAVE_API void initialize_mersenne_twister ();\n\n  OCTAVE_API uint32NDArray get_internal_state ();\n\n  OCTAVE_API void save_state ();\n\n  OCTAVE_API int get_dist_id (const std::string& d);\n\n  OCTAVE_API void set_internal_state (const uint32NDArray& s);\n\n  OCTAVE_API void switch_to_generator (int dist);\n\n  OCTAVE_API void fill (octave_idx_type len, double *v, double a);\n\n  OCTAVE_API void fill (octave_idx_type len, float *v, float a);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/oct-specfun.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <algorithm>\n#include <limits>\n\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n#include \"CNDArray.h\"\n#include \"Faddeeva.hh\"\n#include \"amos-proto.h\"\n#include \"dMatrix.h\"\n#include \"dNDArray.h\"\n#include \"dRowVector.h\"\n#include \"f77-fcn.h\"\n#include \"fCColVector.h\"\n#include \"fCMatrix.h\"\n#include \"fCNDArray.h\"\n#include \"fMatrix.h\"\n#include \"fNDArray.h\"\n#include \"fRowVector.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-error.h\"\n#include \"oct-specfun.h\"\n#include \"slatec-proto.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\nstatic inline Complex\nbessel_return_value (const Complex& val, octave_idx_type ierr)\n{\n  static const Complex inf_val\n    = Complex (numeric_limits<double>::Inf (),\n               numeric_limits<double>::Inf ());\n\n  static const Complex nan_val\n    = Complex (numeric_limits<double>::NaN (),\n               numeric_limits<double>::NaN ());\n\n  Complex retval;\n\n  switch (ierr)\n    {\n    case 0:\n    case 3:\n    case 4:\n      retval = val;\n      break;\n\n    case 2:\n      retval = inf_val;\n      break;\n\n    default:\n      retval = nan_val;\n      break;\n    }\n\n  return retval;\n}\n\nstatic inline FloatComplex\nbessel_return_value (const FloatComplex& val, octave_idx_type ierr)\n{\n  static const FloatComplex inf_val\n    = FloatComplex (numeric_limits<float>::Inf (),\n                    numeric_limits<float>::Inf ());\n\n  static const FloatComplex nan_val\n    = FloatComplex (numeric_limits<float>::NaN (),\n                    numeric_limits<float>::NaN ());\n\n  FloatComplex retval;\n\n  switch (ierr)\n    {\n    case 0:\n    case 3:\n    case 4:\n      retval = val;\n      break;\n\n    case 2:\n      retval = inf_val;\n      break;\n\n    default:\n      retval = nan_val;\n      break;\n    }\n\n  return retval;\n}\n\nComplex\nairy (const Complex& z, bool deriv, bool scaled, octave_idx_type& ierr)\n{\n  double ar = 0.0;\n  double ai = 0.0;\n\n  double zr = z.real ();\n  double zi = z.imag ();\n\n  F77_INT id = (deriv ? 1 : 0);\n  F77_INT nz, t_ierr;\n  F77_INT sc = (scaled ? 2 : 1);\n\n  F77_FUNC (zairy, ZAIRY) (zr, zi, id, sc, ar, ai, nz, t_ierr);\n\n  ierr = t_ierr;\n\n  if (zi == 0.0 && (! scaled || zr >= 0.0))\n    ai = 0.0;\n\n  return bessel_return_value (Complex (ar, ai), ierr);\n}\n\nComplexMatrix\nairy (const ComplexMatrix& z, bool deriv, bool scaled,\n      Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = z.rows ();\n  octave_idx_type nc = z.cols ();\n\n  ComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = airy (z(i, j), deriv, scaled, ierr(i, j));\n\n  return retval;\n}\n\nComplexNDArray\nairy (const ComplexNDArray& z, bool deriv, bool scaled,\n      Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = z.dims ();\n  octave_idx_type nel = dv.numel ();\n  ComplexNDArray retval (dv);\n\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = airy (z(i), deriv, scaled, ierr(i));\n\n  return retval;\n}\n\nFloatComplex\nairy (const FloatComplex& z, bool deriv, bool scaled,\n      octave_idx_type& ierr)\n{\n  FloatComplex a;\n\n  F77_INT id = (deriv ? 1 : 0);\n  F77_INT nz, t_ierr;\n  F77_INT sc = (scaled ? 2 : 1);\n\n  F77_FUNC (cairy, CAIRY) (F77_CONST_CMPLX_ARG (&z), id, sc,\n                           F77_CMPLX_ARG (&a), nz, t_ierr);\n\n  ierr = t_ierr;\n\n  float ar = a.real ();\n  float ai = a.imag ();\n\n  if (z.imag () == 0.0 && (! scaled || z.real () >= 0.0))\n    ai = 0.0;\n\n  return bessel_return_value (FloatComplex (ar, ai), ierr);\n}\n\nFloatComplexMatrix\nairy (const FloatComplexMatrix& z, bool deriv, bool scaled,\n      Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = z.rows ();\n  octave_idx_type nc = z.cols ();\n\n  FloatComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = airy (z(i, j), deriv, scaled, ierr(i, j));\n\n  return retval;\n}\n\nFloatComplexNDArray\nairy (const FloatComplexNDArray& z, bool deriv, bool scaled,\n      Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = z.dims ();\n  octave_idx_type nel = dv.numel ();\n  FloatComplexNDArray retval (dv);\n\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = airy (z(i), deriv, scaled, ierr(i));\n\n  return retval;\n}\n\nstatic inline Complex\nzbesj (const Complex& z, double alpha, int kode, octave_idx_type& ierr);\n\nstatic inline Complex\nzbesy (const Complex& z, double alpha, int kode, octave_idx_type& ierr);\n\nstatic inline Complex\nzbesi (const Complex& z, double alpha, int kode, octave_idx_type& ierr);\n\nstatic inline Complex\nzbesk (const Complex& z, double alpha, int kode, octave_idx_type& ierr);\n\nstatic inline Complex\nzbesh1 (const Complex& z, double alpha, int kode, octave_idx_type& ierr);\n\nstatic inline Complex\nzbesh2 (const Complex& z, double alpha, int kode, octave_idx_type& ierr);\n\nstatic inline Complex\nzbesj (const Complex& z, double alpha, int kode, octave_idx_type& ierr)\n{\n  Complex retval;\n\n  if (alpha >= 0.0)\n    {\n      double yr = 0.0;\n      double yi = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      double zr = z.real ();\n      double zi = z.imag ();\n\n      F77_FUNC (zbesj, ZBESJ) (zr, zi, alpha, kode, 1, &yr, &yi, nz, t_ierr);\n\n      ierr = t_ierr;\n\n      if (zi == 0.0 && zr >= 0.0)\n        yi = 0.0;\n\n      retval = bessel_return_value (Complex (yr, yi), ierr);\n    }\n  else if (octave::math::is_integer (alpha))\n    {\n      // zbesy can overflow as z->0, and cause troubles for generic case below\n      alpha = -alpha;\n      Complex tmp = zbesj (z, alpha, kode, ierr);\n      if ((static_cast<long> (alpha)) & 1)\n        tmp = - tmp;\n      retval = bessel_return_value (tmp, ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      Complex tmp = cos (M_PI * alpha) * zbesj (z, alpha, kode, ierr);\n\n      if (ierr == 0 || ierr == 3)\n        {\n          tmp -= sin (M_PI * alpha) * zbesy (z, alpha, kode, ierr);\n\n          retval = bessel_return_value (tmp, ierr);\n        }\n      else\n        retval = Complex (numeric_limits<double>::NaN (),\n                          numeric_limits<double>::NaN ());\n    }\n\n  return retval;\n}\n\nstatic inline Complex\nzbesy (const Complex& z, double alpha, int kode, octave_idx_type& ierr)\n{\n  Complex retval;\n\n  if (alpha >= 0.0)\n    {\n      double yr = 0.0;\n      double yi = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      double wr, wi;\n\n      double zr = z.real ();\n      double zi = z.imag ();\n\n      ierr = 0;\n\n      if (zr == 0.0 && zi == 0.0)\n        {\n          yr = -numeric_limits<double>::Inf ();\n          yi = 0.0;\n        }\n      else\n        {\n          F77_FUNC (zbesy, ZBESY) (zr, zi, alpha, kode, 1, &yr, &yi, nz,\n                                   &wr, &wi, t_ierr);\n\n          ierr = t_ierr;\n\n          if (zi == 0.0 && zr >= 0.0)\n            yi = 0.0;\n        }\n\n      return bessel_return_value (Complex (yr, yi), ierr);\n    }\n  else if (octave::math::is_integer (alpha - 0.5))\n    {\n      // zbesy can overflow as z->0, and cause troubles for generic case below\n      alpha = -alpha;\n      Complex tmp = zbesj (z, alpha, kode, ierr);\n      if ((static_cast<long> (alpha - 0.5)) & 1)\n        tmp = - tmp;\n      retval = bessel_return_value (tmp, ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      Complex tmp = cos (M_PI * alpha) * zbesy (z, alpha, kode, ierr);\n\n      if (ierr == 0 || ierr == 3)\n        {\n          tmp += sin (M_PI * alpha) * zbesj (z, alpha, kode, ierr);\n\n          retval = bessel_return_value (tmp, ierr);\n        }\n      else\n        retval = Complex (numeric_limits<double>::NaN (),\n                          numeric_limits<double>::NaN ());\n    }\n\n  return retval;\n}\n\nstatic inline Complex\nzbesi (const Complex& z, double alpha, int kode, octave_idx_type& ierr)\n{\n  Complex retval;\n\n  if (alpha >= 0.0)\n    {\n      double yr = 0.0;\n      double yi = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      double zr = z.real ();\n      double zi = z.imag ();\n\n      F77_FUNC (zbesi, ZBESI) (zr, zi, alpha, kode, 1, &yr, &yi, nz, t_ierr);\n\n      ierr = t_ierr;\n\n      if (zi == 0.0 && zr >= 0.0)\n        yi = 0.0;\n\n      retval = bessel_return_value (Complex (yr, yi), ierr);\n    }\n  else if (octave::math::is_integer (alpha))\n    {\n      // zbesi can overflow as z->0, and cause troubles for generic case below\n      alpha = -alpha;\n      Complex tmp = zbesi (z, alpha, kode, ierr);\n      retval = bessel_return_value (tmp, ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      Complex tmp = zbesi (z, alpha, kode, ierr);\n\n      if (ierr == 0 || ierr == 3)\n        {\n          Complex tmp2 = (2.0 / M_PI) * sin (M_PI * alpha)\n                         * zbesk (z, alpha, kode, ierr);\n\n          if (kode == 2)\n            {\n              // Compensate for different scaling factor of besk.\n              tmp2 *= exp (-z - std::abs (z.real ()));\n            }\n\n          tmp += tmp2;\n\n          retval = bessel_return_value (tmp, ierr);\n        }\n      else\n        retval = Complex (numeric_limits<double>::NaN (),\n                          numeric_limits<double>::NaN ());\n    }\n\n  return retval;\n}\n\nstatic inline Complex\nzbesk (const Complex& z, double alpha, int kode, octave_idx_type& ierr)\n{\n  Complex retval;\n\n  if (alpha >= 0.0)\n    {\n      double yr = 0.0;\n      double yi = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      double zr = z.real ();\n      double zi = z.imag ();\n\n      ierr = 0;\n\n      if (zr == 0.0 && zi == 0.0)\n        {\n          yr = numeric_limits<double>::Inf ();\n          yi = 0.0;\n        }\n      else\n        {\n          F77_FUNC (zbesk, ZBESK) (zr, zi, alpha, kode, 1, &yr, &yi, nz,\n                                   t_ierr);\n\n          ierr = t_ierr;\n\n          if (zi == 0.0 && zr >= 0.0)\n            yi = 0.0;\n        }\n\n      retval = bessel_return_value (Complex (yr, yi), ierr);\n    }\n  else\n    {\n      Complex tmp = zbesk (z, -alpha, kode, ierr);\n\n      retval = bessel_return_value (tmp, ierr);\n    }\n\n  return retval;\n}\n\nstatic inline Complex\nzbesh1 (const Complex& z, double alpha, int kode, octave_idx_type& ierr)\n{\n  Complex retval;\n\n  if (alpha >= 0.0)\n    {\n      double yr = 0.0;\n      double yi = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      double zr = z.real ();\n      double zi = z.imag ();\n\n      F77_FUNC (zbesh, ZBESH) (zr, zi, alpha, kode, 1, 1, &yr, &yi, nz,\n                               t_ierr);\n\n      ierr = t_ierr;\n\n      retval = bessel_return_value (Complex (yr, yi), ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      static const Complex eye = Complex (0.0, 1.0);\n\n      Complex tmp = exp (M_PI * alpha * eye) * zbesh1 (z, alpha, kode, ierr);\n\n      retval = bessel_return_value (tmp, ierr);\n    }\n\n  return retval;\n}\n\nstatic inline Complex\nzbesh2 (const Complex& z, double alpha, int kode, octave_idx_type& ierr)\n{\n  Complex retval;\n\n  if (alpha >= 0.0)\n    {\n      double yr = 0.0;\n      double yi = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      double zr = z.real ();\n      double zi = z.imag ();\n\n      F77_FUNC (zbesh, ZBESH) (zr, zi, alpha, kode, 2, 1, &yr, &yi, nz,\n                               t_ierr);\n\n      ierr = t_ierr;\n\n      retval = bessel_return_value (Complex (yr, yi), ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      static const Complex eye = Complex (0.0, 1.0);\n\n      Complex tmp = exp (-M_PI * alpha * eye) * zbesh2 (z, alpha, kode, ierr);\n\n      retval = bessel_return_value (tmp, ierr);\n    }\n\n  return retval;\n}\n\ntypedef Complex (*dptr) (const Complex&, double, int, octave_idx_type&);\n\nstatic inline Complex\ndo_bessel (dptr f, const char *, double alpha, const Complex& x,\n           bool scaled, octave_idx_type& ierr)\n{\n  Complex retval;\n\n  retval = f (x, alpha, (scaled ? 2 : 1), ierr);\n\n  return retval;\n}\n\nstatic inline ComplexMatrix\ndo_bessel (dptr f, const char *, double alpha, const ComplexMatrix& x,\n           bool scaled, Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = x.rows ();\n  octave_idx_type nc = x.cols ();\n\n  ComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = f (x(i, j), alpha, (scaled ? 2 : 1), ierr(i, j));\n\n  return retval;\n}\n\nstatic inline ComplexMatrix\ndo_bessel (dptr f, const char *, const Matrix& alpha, const Complex& x,\n           bool scaled, Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = alpha.rows ();\n  octave_idx_type nc = alpha.cols ();\n\n  ComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = f (x, alpha(i, j), (scaled ? 2 : 1), ierr(i, j));\n\n  return retval;\n}\n\nstatic inline ComplexMatrix\ndo_bessel (dptr f, const char *fn, const Matrix& alpha,\n           const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr)\n{\n  ComplexMatrix retval;\n\n  octave_idx_type x_nr = x.rows ();\n  octave_idx_type x_nc = x.cols ();\n\n  octave_idx_type alpha_nr = alpha.rows ();\n  octave_idx_type alpha_nc = alpha.cols ();\n\n  if (x_nr != alpha_nr || x_nc != alpha_nc)\n    (*current_liboctave_error_handler)\n      (\"%s: the sizes of alpha and x must conform\", fn);\n\n  octave_idx_type nr = x_nr;\n  octave_idx_type nc = x_nc;\n\n  retval.resize (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = f (x(i, j), alpha(i, j), (scaled ? 2 : 1), ierr(i, j));\n\n  return retval;\n}\n\nstatic inline ComplexNDArray\ndo_bessel (dptr f, const char *, double alpha, const ComplexNDArray& x,\n           bool scaled, Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = x.dims ();\n  octave_idx_type nel = dv.numel ();\n  ComplexNDArray retval (dv);\n\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = f (x(i), alpha, (scaled ? 2 : 1), ierr(i));\n\n  return retval;\n}\n\nstatic inline ComplexNDArray\ndo_bessel (dptr f, const char *, const NDArray& alpha, const Complex& x,\n           bool scaled, Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = alpha.dims ();\n  octave_idx_type nel = dv.numel ();\n  ComplexNDArray retval (dv);\n\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = f (x, alpha(i), (scaled ? 2 : 1), ierr(i));\n\n  return retval;\n}\n\nstatic inline ComplexNDArray\ndo_bessel (dptr f, const char *fn, const NDArray& alpha,\n           const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = x.dims ();\n  ComplexNDArray retval;\n\n  if (dv != alpha.dims ())\n    (*current_liboctave_error_handler)\n      (\"%s: the sizes of alpha and x must conform\", fn);\n\n  octave_idx_type nel = dv.numel ();\n\n  retval.resize (dv);\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = f (x(i), alpha(i), (scaled ? 2 : 1), ierr(i));\n\n  return retval;\n}\n\nstatic inline ComplexMatrix\ndo_bessel (dptr f, const char *, const RowVector& alpha,\n           const ComplexColumnVector& x, bool scaled,\n           Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = x.numel ();\n  octave_idx_type nc = alpha.numel ();\n\n  ComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = f (x(i), alpha(j), (scaled ? 2 : 1), ierr(i, j));\n\n  return retval;\n}\n\n#define SS_BESSEL(name, fcn)                                            \\\n    Complex                                                             \\\n    name (double alpha, const Complex& x, bool scaled, octave_idx_type& ierr) \\\n    {                                                                   \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);            \\\n    }\n\n#define SM_BESSEL(name, fcn)                                    \\\n    ComplexMatrix                                               \\\n    name (double alpha, const ComplexMatrix& x, bool scaled,    \\\n          Array<octave_idx_type>& ierr)                         \\\n    {                                                           \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);    \\\n    }\n\n#define MS_BESSEL(name, fcn)                                    \\\n    ComplexMatrix                                               \\\n    name (const Matrix& alpha, const Complex& x, bool scaled,   \\\n          Array<octave_idx_type>& ierr)                         \\\n    {                                                           \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);    \\\n    }\n\n#define MM_BESSEL(name, fcn)                                            \\\n    ComplexMatrix                                                       \\\n    name (const Matrix& alpha, const ComplexMatrix& x, bool scaled,     \\\n          Array<octave_idx_type>& ierr)                                 \\\n    {                                                                   \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);            \\\n    }\n\n#define SN_BESSEL(name, fcn)                                    \\\n    ComplexNDArray                                              \\\n    name (double alpha, const ComplexNDArray& x, bool scaled,   \\\n          Array<octave_idx_type>& ierr)                         \\\n    {                                                           \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);    \\\n    }\n\n#define NS_BESSEL(name, fcn)                                    \\\n    ComplexNDArray                                              \\\n    name (const NDArray& alpha, const Complex& x, bool scaled,  \\\n          Array<octave_idx_type>& ierr)                         \\\n    {                                                           \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);    \\\n    }\n\n#define NN_BESSEL(name, fcn)                                            \\\n    ComplexNDArray                                                      \\\n    name (const NDArray& alpha, const ComplexNDArray& x, bool scaled,   \\\n          Array<octave_idx_type>& ierr)                                 \\\n    {                                                                   \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);            \\\n    }\n\n#define RC_BESSEL(name, fcn)                                            \\\n    ComplexMatrix                                                       \\\n    name (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, \\\n          Array<octave_idx_type>& ierr)                                 \\\n    {                                                                   \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);            \\\n    }\n\n#define ALL_BESSEL(name, fcn)                   \\\n    SS_BESSEL (name, fcn)                       \\\n    SM_BESSEL (name, fcn)                       \\\n    MS_BESSEL (name, fcn)                       \\\n    MM_BESSEL (name, fcn)                       \\\n    SN_BESSEL (name, fcn)                       \\\n    NS_BESSEL (name, fcn)                       \\\n    NN_BESSEL (name, fcn)                       \\\n    RC_BESSEL (name, fcn)\n\nALL_BESSEL (besselj, zbesj)\nALL_BESSEL (bessely, zbesy)\nALL_BESSEL (besseli, zbesi)\nALL_BESSEL (besselk, zbesk)\nALL_BESSEL (besselh1, zbesh1)\nALL_BESSEL (besselh2, zbesh2)\n\n#undef ALL_BESSEL\n#undef SS_BESSEL\n#undef SM_BESSEL\n#undef MS_BESSEL\n#undef MM_BESSEL\n#undef SN_BESSEL\n#undef NS_BESSEL\n#undef NN_BESSEL\n#undef RC_BESSEL\n\nstatic inline FloatComplex\ncbesj (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr);\n\nstatic inline FloatComplex\ncbesy (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr);\n\nstatic inline FloatComplex\ncbesi (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr);\n\nstatic inline FloatComplex\ncbesk (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr);\n\nstatic inline FloatComplex\ncbesh1 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr);\n\nstatic inline FloatComplex\ncbesh2 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr);\n\nstatic inline FloatComplex\ncbesj (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr)\n{\n  FloatComplex retval;\n\n  if (alpha >= 0.0)\n    {\n      FloatComplex y = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      F77_FUNC (cbesj, CBESJ) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1,\n                               F77_CMPLX_ARG (&y), nz, t_ierr);\n\n      ierr = t_ierr;\n\n      if (z.imag () == 0.0 && z.real () >= 0.0)\n        y = FloatComplex (y.real (), 0.0);\n\n      retval = bessel_return_value (y, ierr);\n    }\n  else if (octave::math::is_integer (alpha))\n    {\n      // zbesy can overflow as z->0, and cause troubles for generic case below\n      alpha = -alpha;\n      FloatComplex tmp = cbesj (z, alpha, kode, ierr);\n      if ((static_cast<long> (alpha)) & 1)\n        tmp = - tmp;\n      retval = bessel_return_value (tmp, ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      FloatComplex tmp = cosf (static_cast<float> (M_PI) * alpha)\n                         * cbesj (z, alpha, kode, ierr);\n\n      if (ierr == 0 || ierr == 3)\n        {\n          tmp -= sinf (static_cast<float> (M_PI) * alpha)\n                 * cbesy (z, alpha, kode, ierr);\n\n          retval = bessel_return_value (tmp, ierr);\n        }\n      else\n        retval = FloatComplex (numeric_limits<float>::NaN (),\n                               numeric_limits<float>::NaN ());\n    }\n\n  return retval;\n}\n\nstatic inline FloatComplex\ncbesy (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr)\n{\n  FloatComplex retval;\n\n  if (alpha >= 0.0)\n    {\n      FloatComplex y = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      FloatComplex w;\n\n      ierr = 0;\n\n      if (z.real () == 0.0 && z.imag () == 0.0)\n        {\n          y = FloatComplex (-numeric_limits<float>::Inf (), 0.0);\n        }\n      else\n        {\n          F77_FUNC (cbesy, CBESY) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1,\n                                   F77_CMPLX_ARG (&y), nz,\n                                   F77_CMPLX_ARG (&w), t_ierr);\n\n          ierr = t_ierr;\n\n          if (z.imag () == 0.0 && z.real () >= 0.0)\n            y = FloatComplex (y.real (), 0.0);\n        }\n\n      return bessel_return_value (y, ierr);\n    }\n  else if (octave::math::is_integer (alpha - 0.5))\n    {\n      // zbesy can overflow as z->0, and cause troubles for generic case below\n      alpha = -alpha;\n      FloatComplex tmp = cbesj (z, alpha, kode, ierr);\n      if ((static_cast<long> (alpha - 0.5)) & 1)\n        tmp = - tmp;\n      retval = bessel_return_value (tmp, ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      FloatComplex tmp = cosf (static_cast<float> (M_PI) * alpha)\n                         * cbesy (z, alpha, kode, ierr);\n\n      if (ierr == 0 || ierr == 3)\n        {\n          tmp += sinf (static_cast<float> (M_PI) * alpha)\n                 * cbesj (z, alpha, kode, ierr);\n\n          retval = bessel_return_value (tmp, ierr);\n        }\n      else\n        retval = FloatComplex (numeric_limits<float>::NaN (),\n                               numeric_limits<float>::NaN ());\n    }\n\n  return retval;\n}\n\nstatic inline FloatComplex\ncbesi (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr)\n{\n  FloatComplex retval;\n\n  if (alpha >= 0.0)\n    {\n      FloatComplex y = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      F77_FUNC (cbesi, CBESI) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1,\n                               F77_CMPLX_ARG (&y), nz, t_ierr);\n\n      ierr = t_ierr;\n\n      if (z.imag () == 0.0 && z.real () >= 0.0)\n        y = FloatComplex (y.real (), 0.0);\n\n      retval = bessel_return_value (y, ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      FloatComplex tmp = cbesi (z, alpha, kode, ierr);\n\n      if (ierr == 0 || ierr == 3)\n        {\n          FloatComplex tmp2 = static_cast<float> (2.0 / M_PI)\n                              * sinf (static_cast<float> (M_PI) * alpha)\n                              * cbesk (z, alpha, kode, ierr);\n\n          if (kode == 2)\n            {\n              // Compensate for different scaling factor of besk.\n              tmp2 *= exp (-z - std::abs (z.real ()));\n            }\n\n          tmp += tmp2;\n\n          retval = bessel_return_value (tmp, ierr);\n        }\n      else\n        retval = FloatComplex (numeric_limits<float>::NaN (),\n                               numeric_limits<float>::NaN ());\n    }\n\n  return retval;\n}\n\nstatic inline FloatComplex\ncbesk (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr)\n{\n  FloatComplex retval;\n\n  if (alpha >= 0.0)\n    {\n      FloatComplex y = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      ierr = 0;\n\n      if (z.real () == 0.0 && z.imag () == 0.0)\n        {\n          y = FloatComplex (numeric_limits<float>::Inf (), 0.0);\n        }\n      else\n        {\n          F77_FUNC (cbesk, CBESK) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1,\n                                   F77_CMPLX_ARG (&y), nz, t_ierr);\n\n          ierr = t_ierr;\n\n          if (z.imag () == 0.0 && z.real () >= 0.0)\n            y = FloatComplex (y.real (), 0.0);\n        }\n\n      retval = bessel_return_value (y, ierr);\n    }\n  else\n    {\n      FloatComplex tmp = cbesk (z, -alpha, kode, ierr);\n\n      retval = bessel_return_value (tmp, ierr);\n    }\n\n  return retval;\n}\n\nstatic inline FloatComplex\ncbesh1 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr)\n{\n  FloatComplex retval;\n\n  if (alpha >= 0.0)\n    {\n      FloatComplex y = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      F77_FUNC (cbesh, CBESH) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, 1,\n                               F77_CMPLX_ARG (&y), nz, t_ierr);\n\n      ierr = t_ierr;\n\n      retval = bessel_return_value (y, ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      static const FloatComplex eye = FloatComplex (0.0, 1.0);\n\n      FloatComplex tmp = exp (static_cast<float> (M_PI) * alpha * eye)\n                         * cbesh1 (z, alpha, kode, ierr);\n\n      retval = bessel_return_value (tmp, ierr);\n    }\n\n  return retval;\n}\n\nstatic inline FloatComplex\ncbesh2 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr)\n{\n  FloatComplex retval;\n\n  if (alpha >= 0.0)\n    {\n      FloatComplex y = 0.0;\n\n      F77_INT nz, t_ierr;\n\n      F77_FUNC (cbesh, CBESH) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 2, 1,\n                               F77_CMPLX_ARG (&y), nz, t_ierr);\n\n      ierr = t_ierr;\n\n      retval = bessel_return_value (y, ierr);\n    }\n  else\n    {\n      alpha = -alpha;\n\n      static const FloatComplex eye = FloatComplex (0.0, 1.0);\n\n      FloatComplex tmp = exp (-static_cast<float> (M_PI) * alpha * eye)\n                         * cbesh2 (z, alpha, kode, ierr);\n\n      retval = bessel_return_value (tmp, ierr);\n    }\n\n  return retval;\n}\n\ntypedef FloatComplex (*fptr) (const FloatComplex&, float, int,\n                              octave_idx_type&);\n\nstatic inline FloatComplex\ndo_bessel (fptr f, const char *, float alpha, const FloatComplex& x,\n           bool scaled, octave_idx_type& ierr)\n{\n  FloatComplex retval;\n\n  retval = f (x, alpha, (scaled ? 2 : 1), ierr);\n\n  return retval;\n}\n\nstatic inline FloatComplexMatrix\ndo_bessel (fptr f, const char *, float alpha, const FloatComplexMatrix& x,\n           bool scaled, Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = x.rows ();\n  octave_idx_type nc = x.cols ();\n\n  FloatComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = f (x(i, j), alpha, (scaled ? 2 : 1), ierr(i, j));\n\n  return retval;\n}\n\nstatic inline FloatComplexMatrix\ndo_bessel (fptr f, const char *, const FloatMatrix& alpha,\n           const FloatComplex& x,\n           bool scaled, Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = alpha.rows ();\n  octave_idx_type nc = alpha.cols ();\n\n  FloatComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = f (x, alpha(i, j), (scaled ? 2 : 1), ierr(i, j));\n\n  return retval;\n}\n\nstatic inline FloatComplexMatrix\ndo_bessel (fptr f, const char *fn, const FloatMatrix& alpha,\n           const FloatComplexMatrix& x, bool scaled,\n           Array<octave_idx_type>& ierr)\n{\n  FloatComplexMatrix retval;\n\n  octave_idx_type x_nr = x.rows ();\n  octave_idx_type x_nc = x.cols ();\n\n  octave_idx_type alpha_nr = alpha.rows ();\n  octave_idx_type alpha_nc = alpha.cols ();\n\n  if (x_nr != alpha_nr || x_nc != alpha_nc)\n    (*current_liboctave_error_handler)\n      (\"%s: the sizes of alpha and x must conform\", fn);\n\n  octave_idx_type nr = x_nr;\n  octave_idx_type nc = x_nc;\n\n  retval.resize (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = f (x(i, j), alpha(i, j), (scaled ? 2 : 1), ierr(i, j));\n\n  return retval;\n}\n\nstatic inline FloatComplexNDArray\ndo_bessel (fptr f, const char *, float alpha, const FloatComplexNDArray& x,\n           bool scaled, Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = x.dims ();\n  octave_idx_type nel = dv.numel ();\n  FloatComplexNDArray retval (dv);\n\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = f (x(i), alpha, (scaled ? 2 : 1), ierr(i));\n\n  return retval;\n}\n\nstatic inline FloatComplexNDArray\ndo_bessel (fptr f, const char *, const FloatNDArray& alpha,\n           const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = alpha.dims ();\n  octave_idx_type nel = dv.numel ();\n  FloatComplexNDArray retval (dv);\n\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = f (x, alpha(i), (scaled ? 2 : 1), ierr(i));\n\n  return retval;\n}\n\nstatic inline FloatComplexNDArray\ndo_bessel (fptr f, const char *fn, const FloatNDArray& alpha,\n           const FloatComplexNDArray& x, bool scaled,\n           Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = x.dims ();\n  FloatComplexNDArray retval;\n\n  if (dv != alpha.dims ())\n    (*current_liboctave_error_handler)\n      (\"%s: the sizes of alpha and x must conform\", fn);\n\n  octave_idx_type nel = dv.numel ();\n\n  retval.resize (dv);\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = f (x(i), alpha(i), (scaled ? 2 : 1), ierr(i));\n\n  return retval;\n}\n\nstatic inline FloatComplexMatrix\ndo_bessel (fptr f, const char *, const FloatRowVector& alpha,\n           const FloatComplexColumnVector& x, bool scaled,\n           Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = x.numel ();\n  octave_idx_type nc = alpha.numel ();\n\n  FloatComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = f (x(i), alpha(j), (scaled ? 2 : 1), ierr(i, j));\n\n  return retval;\n}\n\n#define SS_BESSEL(name, fcn)                                    \\\n    FloatComplex                                                \\\n    name (float alpha, const FloatComplex& x, bool scaled,      \\\n          octave_idx_type& ierr)                                \\\n    {                                                           \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);    \\\n    }\n\n#define SM_BESSEL(name, fcn)                                            \\\n    FloatComplexMatrix                                                  \\\n    name (float alpha, const FloatComplexMatrix& x, bool scaled,        \\\n          Array<octave_idx_type>& ierr)                                 \\\n    {                                                                   \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);            \\\n    }\n\n#define MS_BESSEL(name, fcn)                                            \\\n    FloatComplexMatrix                                                  \\\n    name (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, \\\n          Array<octave_idx_type>& ierr)                                 \\\n    {                                                                   \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);            \\\n    }\n\n#define MM_BESSEL(name, fcn)                                            \\\n    FloatComplexMatrix                                                  \\\n    name (const FloatMatrix& alpha, const FloatComplexMatrix& x,        \\\n          bool scaled, Array<octave_idx_type>& ierr)                    \\\n    {                                                                   \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);            \\\n    }\n\n#define SN_BESSEL(name, fcn)                                            \\\n    FloatComplexNDArray                                                 \\\n    name (float alpha, const FloatComplexNDArray& x, bool scaled,       \\\n          Array<octave_idx_type>& ierr)                                 \\\n    {                                                                   \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);            \\\n    }\n\n#define NS_BESSEL(name, fcn)                                    \\\n    FloatComplexNDArray                                         \\\n    name (const FloatNDArray& alpha, const FloatComplex& x,     \\\n          bool scaled, Array<octave_idx_type>& ierr)            \\\n    {                                                           \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);    \\\n    }\n\n#define NN_BESSEL(name, fcn)                                            \\\n    FloatComplexNDArray                                                 \\\n    name (const FloatNDArray& alpha, const FloatComplexNDArray& x,      \\\n          bool scaled, Array<octave_idx_type>& ierr)                    \\\n    {                                                                   \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);            \\\n    }\n\n#define RC_BESSEL(name, fcn)                                    \\\n    FloatComplexMatrix                                          \\\n    name (const FloatRowVector& alpha,                          \\\n          const FloatComplexColumnVector& x, bool scaled,       \\\n          Array<octave_idx_type>& ierr)                         \\\n    {                                                           \\\n      return do_bessel (fcn, #name, alpha, x, scaled, ierr);    \\\n    }\n\n#define ALL_BESSEL(name, fcn)                   \\\n    SS_BESSEL (name, fcn)                       \\\n    SM_BESSEL (name, fcn)                       \\\n    MS_BESSEL (name, fcn)                       \\\n    MM_BESSEL (name, fcn)                       \\\n    SN_BESSEL (name, fcn)                       \\\n    NS_BESSEL (name, fcn)                       \\\n    NN_BESSEL (name, fcn)                       \\\n    RC_BESSEL (name, fcn)\n\nALL_BESSEL (besselj, cbesj)\nALL_BESSEL (bessely, cbesy)\nALL_BESSEL (besseli, cbesi)\nALL_BESSEL (besselk, cbesk)\nALL_BESSEL (besselh1, cbesh1)\nALL_BESSEL (besselh2, cbesh2)\n\n#undef ALL_BESSEL\n#undef SS_BESSEL\n#undef SM_BESSEL\n#undef MS_BESSEL\n#undef MM_BESSEL\n#undef SN_BESSEL\n#undef NS_BESSEL\n#undef NN_BESSEL\n#undef RC_BESSEL\n\nComplex\nbiry (const Complex& z, bool deriv, bool scaled, octave_idx_type& ierr)\n{\n  double ar = 0.0;\n  double ai = 0.0;\n\n  double zr = z.real ();\n  double zi = z.imag ();\n\n  F77_INT id = (deriv ? 1 : 0);\n  F77_INT t_ierr;\n  F77_INT sc = (scaled ? 2 : 1);\n\n  F77_FUNC (zbiry, ZBIRY) (zr, zi, id, sc, ar, ai, t_ierr);\n\n  ierr = t_ierr;\n\n  if (zi == 0.0 && (! scaled || zr >= 0.0))\n    ai = 0.0;\n\n  return bessel_return_value (Complex (ar, ai), ierr);\n}\n\nComplexMatrix\nbiry (const ComplexMatrix& z, bool deriv, bool scaled,\n      Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = z.rows ();\n  octave_idx_type nc = z.cols ();\n\n  ComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = biry (z(i, j), deriv, scaled, ierr(i, j));\n\n  return retval;\n}\n\nComplexNDArray\nbiry (const ComplexNDArray& z, bool deriv, bool scaled,\n      Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = z.dims ();\n  octave_idx_type nel = dv.numel ();\n  ComplexNDArray retval (dv);\n\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = biry (z(i), deriv, scaled, ierr(i));\n\n  return retval;\n}\n\nFloatComplex\nbiry (const FloatComplex& z, bool deriv, bool scaled,\n      octave_idx_type& ierr)\n{\n  FloatComplex a;\n\n  F77_INT id = (deriv ? 1 : 0);\n  F77_INT t_ierr;\n  F77_INT sc = (scaled ? 2 : 1);\n\n  F77_FUNC (cbiry, CBIRY) (F77_CONST_CMPLX_ARG (&z), id, sc,\n                           F77_CMPLX_ARG (&a), t_ierr);\n\n  ierr = t_ierr;\n\n  float ar = a.real ();\n  float ai = a.imag ();\n\n  if (z.imag () == 0.0 && (! scaled || z.real () >= 0.0))\n    ai = 0.0;\n\n  return bessel_return_value (FloatComplex (ar, ai), ierr);\n}\n\nFloatComplexMatrix\nbiry (const FloatComplexMatrix& z, bool deriv, bool scaled,\n      Array<octave_idx_type>& ierr)\n{\n  octave_idx_type nr = z.rows ();\n  octave_idx_type nc = z.cols ();\n\n  FloatComplexMatrix retval (nr, nc);\n\n  ierr.resize (dim_vector (nr, nc));\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      retval(i, j) = biry (z(i, j), deriv, scaled, ierr(i, j));\n\n  return retval;\n}\n\nFloatComplexNDArray\nbiry (const FloatComplexNDArray& z, bool deriv, bool scaled,\n      Array<octave_idx_type>& ierr)\n{\n  const dim_vector& dv = z.dims ();\n  octave_idx_type nel = dv.numel ();\n  FloatComplexNDArray retval (dv);\n\n  ierr.resize (dv);\n\n  for (octave_idx_type i = 0; i < nel; i++)\n    retval(i) = biry (z(i), deriv, scaled, ierr(i));\n\n  return retval;\n}\n\n// Real and complex Dawson function (= scaled erfi) from Faddeeva package\ndouble\ndawson (double x) { return Faddeeva::Dawson (x); }\nfloat\ndawson (float x) { return Faddeeva::Dawson (x); }\n\nComplex\ndawson (const Complex& x)\n{\n  return Faddeeva::Dawson (x);\n}\n\nFloatComplex\ndawson (const FloatComplex& x)\n{\n  Complex xd (x.real (), x.imag ());\n  Complex ret;\n  ret = Faddeeva::Dawson (xd, std::numeric_limits<float>::epsilon ());\n  return FloatComplex (ret.real (), ret.imag ());\n}\n\nvoid\nellipj (double u, double m, double& sn, double& cn, double& dn, double& err)\n{\n  static const int Nmax = 16;\n  double m1, t=0, si_u, co_u, se_u, ta_u, b, c[Nmax], a[Nmax], phi;\n  int n, Nn, ii;\n\n  if (m < 0 || m > 1)\n    {\n      (*current_liboctave_warning_with_id_handler)\n        (\"Octave:ellipj-invalid-m\",\n         \"ellipj: invalid M value, required value 0 <= M <= 1\");\n\n      sn = cn = dn = lo_ieee_nan_value ();\n\n      return;\n    }\n\n  double sqrt_eps = std::sqrt (std::numeric_limits<double>::epsilon ());\n  if (m < sqrt_eps)\n    {\n      // For small m, (Abramowitz and Stegun, Section 16.13)\n      si_u = sin (u);\n      co_u = cos (u);\n      t = 0.25*m*(u - si_u*co_u);\n      sn = si_u - t * co_u;\n      cn = co_u + t * si_u;\n      dn = 1 - 0.5*m*si_u*si_u;\n    }\n  else if ((1 - m) < sqrt_eps)\n    {\n      // For m1 = (1-m) small (Abramowitz and Stegun, Section 16.15)\n      m1 = 1 - m;\n      si_u = sinh (u);\n      co_u = cosh (u);\n      ta_u = tanh (u);\n      se_u = 1/co_u;\n      sn = ta_u + 0.25*m1*(si_u*co_u - u)*se_u*se_u;\n      cn = se_u - 0.25*m1*(si_u*co_u - u)*ta_u*se_u;\n      dn = se_u + 0.25*m1*(si_u*co_u + u)*ta_u*se_u;\n    }\n  else\n    {\n      // Arithmetic-Geometric Mean (AGM) algorithm\n      //   (Abramowitz and Stegun, Section 16.4)\n      a[0] = 1;\n      b    = std::sqrt (1 - m);\n      c[0] = std::sqrt (m);\n      for (n = 1; n < Nmax; ++n)\n        {\n          a[n] = (a[n - 1] + b)/2;\n          c[n] = (a[n - 1] - b)/2;\n          b = std::sqrt (a[n - 1]*b);\n          if (c[n]/a[n] < std::numeric_limits<double>::epsilon ()) break;\n        }\n      if (n >= Nmax - 1)\n        {\n          err = 1;\n          return;\n        }\n      Nn = n;\n      for (ii = 1; n > 0; ii *= 2, --n) {}  // ii = pow(2,Nn)\n      phi = ii*a[Nn]*u;\n      for (n = Nn; n > 0; --n)\n        {\n          phi = (std::asin ((c[n]/a[n])* sin (phi)) + phi)/2;\n        }\n      sn = sin (phi);\n      cn = cos (phi);\n      dn = std::sqrt (1 - m*sn*sn);\n    }\n}\n\nvoid\nellipj (const Complex& u, double m, Complex& sn, Complex& cn, Complex& dn,\n        double& err)\n{\n  double m1 = 1 - m, ss1, cc1, dd1;\n\n  ellipj (u.imag (), m1, ss1, cc1, dd1, err);\n  if (u.real () == 0)\n    {\n      // u is pure imag: Jacoby imag. transf.\n      sn = Complex (0, ss1/cc1);\n      cn = 1/cc1;         //    cn.imag = 0;\n      dn = dd1/cc1;       //    dn.imag = 0;\n    }\n  else\n    {\n      // u is generic complex\n      double ss, cc, dd, ddd;\n\n      ellipj (u.real (), m, ss, cc, dd, err);\n      ddd = cc1*cc1 + m*ss*ss*ss1*ss1;\n      sn = Complex (ss*dd1/ddd, cc*dd*ss1*cc1/ddd);\n      cn = Complex (cc*cc1/ddd, -ss*dd*ss1*dd1/ddd);\n      dn = Complex (dd*cc1*dd1/ddd, -m*ss*cc*ss1/ddd);\n    }\n}\n\n// Complex error function from the Faddeeva package\nComplex\nerf (const Complex& x)\n{\n  return Faddeeva::erf (x);\n}\n\nFloatComplex\nerf (const FloatComplex& x)\n{\n  Complex xd (x.real (), x.imag ());\n  Complex ret = Faddeeva::erf (xd, std::numeric_limits<float>::epsilon ());\n  return FloatComplex (ret.real (), ret.imag ());\n}\n\n// Complex complementary error function from the Faddeeva package\nComplex\nerfc (const Complex& x)\n{\n  return Faddeeva::erfc (x);\n}\n\nFloatComplex\nerfc (const FloatComplex& x)\n{\n  Complex xd (x.real (), x.imag ());\n  Complex ret = Faddeeva::erfc (xd, std::numeric_limits<float>::epsilon ());\n  return FloatComplex (ret.real (), ret.imag ());\n}\n\n// The algorithm for erfcinv is an adaptation of the erfinv algorithm\n// above from P. J. Acklam.  It has been modified to run over the\n// different input domain of erfcinv.  See the notes for erfinv for an\n// explanation.\n\nstatic double\ndo_erfcinv (double x, bool refine)\n{\n  // Coefficients of rational approximation.\n  static const double a[] =\n  {\n    -2.806989788730439e+01,  1.562324844726888e+02,\n      -1.951109208597547e+02,  9.783370457507161e+01,\n      -2.168328665628878e+01,  1.772453852905383e+00\n    };\n  static const double b[] =\n  {\n    -5.447609879822406e+01,  1.615858368580409e+02,\n      -1.556989798598866e+02,  6.680131188771972e+01,\n      -1.328068155288572e+01\n    };\n  static const double c[] =\n  {\n    -5.504751339936943e-03, -2.279687217114118e-01,\n      -1.697592457770869e+00, -1.802933168781950e+00,\n      3.093354679843505e+00,  2.077595676404383e+00\n    };\n  static const double d[] =\n  {\n    7.784695709041462e-03,  3.224671290700398e-01,\n    2.445134137142996e+00,  3.754408661907416e+00\n  };\n\n  static const double spi2 = 8.862269254527579e-01; // sqrt(pi)/2.\n  static const double pbreak_lo = 0.04850;  // 1-pbreak\n  static const double pbreak_hi = 1.95150;  // 1+pbreak\n  double y;\n\n  // Select case.\n  if (x >= pbreak_lo && x <= pbreak_hi)\n    {\n      // Middle region.\n      const double q = 0.5*(1-x), r = q*q;\n      const double yn = (((((a[0]*r + a[1])*r + a[2])*r + a[3])*r + a[4])*r + a[5])*q;\n      const double yd = ((((b[0]*r + b[1])*r + b[2])*r + b[3])*r + b[4])*r + 1.0;\n      y = yn / yd;\n    }\n  else if (x > 0.0 && x < 2.0)\n    {\n      // Tail region.\n      const double q = (x < 1\n                        ? std::sqrt (-2*std::log (0.5*x))\n                        : std::sqrt (-2*std::log (0.5*(2-x))));\n\n      const double yn = ((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5];\n\n      const double yd = (((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0;\n\n      y = yn / yd;\n\n      if (x < pbreak_lo)\n        y = -y;\n    }\n  else if (x == 0.0)\n    return numeric_limits<double>::Inf ();\n  else if (x == 2.0)\n    return -numeric_limits<double>::Inf ();\n  else\n    return numeric_limits<double>::NaN ();\n\n  if (refine)\n    {\n      // One iteration of Halley's method gives full precision.\n      double u = (erf (y) - (1-x)) * spi2 * exp (y*y);\n      y -= u / (1 + y*u);\n    }\n\n  return y;\n}\n\ndouble\nerfcinv (double x)\n{\n  return do_erfcinv (x, true);\n}\n\nfloat\nerfcinv (float x)\n{\n  return do_erfcinv (x, false);\n}\n\n// Real and complex scaled complementary error function from Faddeeva pkg.\ndouble\nerfcx (double x) { return Faddeeva::erfcx (x); }\nfloat\nerfcx (float x) { return Faddeeva::erfcx (x); }\n\nComplex\nerfcx (const Complex& x)\n{\n  return Faddeeva::erfcx (x);\n}\n\nFloatComplex\nerfcx (const FloatComplex& x)\n{\n  Complex xd (x.real (), x.imag ());\n  Complex ret;\n  ret = Faddeeva::erfcx (xd, std::numeric_limits<float>::epsilon ());\n  return FloatComplex (ret.real (), ret.imag ());\n}\n\n// Real and complex imaginary error function from Faddeeva package\ndouble\nerfi (double x) { return Faddeeva::erfi (x); }\nfloat\nerfi (float x) { return Faddeeva::erfi (x); }\n\nComplex\nerfi (const Complex& x)\n{\n  return Faddeeva::erfi (x);\n}\n\nFloatComplex\nerfi (const FloatComplex& x)\n{\n  Complex xd (x.real (), x.imag ());\n  Complex ret = Faddeeva::erfi (xd, std::numeric_limits<float>::epsilon ());\n  return FloatComplex (ret.real (), ret.imag ());\n}\n\n// This algorithm is due to P. J. Acklam.\n//\n// See http://home.online.no/~pjacklam/notes/invnorm/\n//\n// The rational approximation has relative accuracy 1.15e-9 in the whole\n// region.  For doubles, it is refined by a single step of Halley's 3rd\n// order method.  For single precision, the accuracy is already OK, so\n// we skip it to get faster evaluation.\n\nstatic double\ndo_erfinv (double x, bool refine)\n{\n  // Coefficients of rational approximation.\n  static const double a[] =\n  {\n    -2.806989788730439e+01,  1.562324844726888e+02,\n      -1.951109208597547e+02,  9.783370457507161e+01,\n      -2.168328665628878e+01,  1.772453852905383e+00\n    };\n  static const double b[] =\n  {\n    -5.447609879822406e+01,  1.615858368580409e+02,\n      -1.556989798598866e+02,  6.680131188771972e+01,\n      -1.328068155288572e+01\n    };\n  static const double c[] =\n  {\n    -5.504751339936943e-03, -2.279687217114118e-01,\n      -1.697592457770869e+00, -1.802933168781950e+00,\n      3.093354679843505e+00,  2.077595676404383e+00\n    };\n  static const double d[] =\n  {\n    7.784695709041462e-03,  3.224671290700398e-01,\n    2.445134137142996e+00,  3.754408661907416e+00\n  };\n\n  static const double spi2 = 8.862269254527579e-01; // sqrt(pi)/2.\n  static const double pbreak = 0.95150;\n  double ax = fabs (x), y;\n\n  // Select case.\n  if (ax <= pbreak)\n    {\n      // Middle region.\n      const double q = 0.5 * x, r = q*q;\n      const double yn = (((((a[0]*r + a[1])*r + a[2])*r + a[3])*r + a[4])*r + a[5])*q;\n      const double yd = ((((b[0]*r + b[1])*r + b[2])*r + b[3])*r + b[4])*r + 1.0;\n      y = yn / yd;\n    }\n  else if (ax < 1.0)\n    {\n      // Tail region.\n      const double q = std::sqrt (-2*std::log (0.5*(1-ax)));\n      const double yn = ((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5];\n      const double yd = (((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0;\n      y = yn / yd * math::signum (-x);\n    }\n  else if (ax == 1.0)\n    return numeric_limits<double>::Inf () * math::signum (x);\n  else\n    return numeric_limits<double>::NaN ();\n\n  if (refine)\n    {\n      // One iteration of Halley's method gives full precision.\n      double u = (erf (y) - x) * spi2 * exp (y*y);\n      y -= u / (1 + y*u);\n    }\n\n  return y;\n}\n\ndouble\nerfinv (double x)\n{\n  return do_erfinv (x, true);\n}\n\nfloat\nerfinv (float x)\n{\n  return do_erfinv (x, false);\n}\n\nComplex\nexpm1 (const Complex& x)\n{\n  Complex retval;\n\n  if (std::abs (x) < 1)\n    {\n      double im = x.imag ();\n      double u = expm1 (x.real ());\n      double v = sin (im/2);\n      v = -2*v*v;\n      retval = Complex (u*v + u + v, (u+1) * sin (im));\n    }\n  else\n    retval = std::exp (x) - Complex (1);\n\n  return retval;\n}\n\nFloatComplex\nexpm1 (const FloatComplex& x)\n{\n  FloatComplex retval;\n\n  if (std::abs (x) < 1)\n    {\n      float im = x.imag ();\n      float u = expm1 (x.real ());\n      float v = sin (im/2);\n      v = -2*v*v;\n      retval = FloatComplex (u*v + u + v, (u+1) * sin (im));\n    }\n  else\n    retval = std::exp (x) - FloatComplex (1);\n\n  return retval;\n}\n\ndouble\ngamma (double x)\n{\n  double result;\n\n  // Special cases for (near) compatibility with Matlab instead of tgamma.\n  // Matlab does not have -0.\n\n  if (x == 0)\n    result = (math::negative_sign (x)\n              ? -numeric_limits<double>::Inf ()\n              : numeric_limits<double>::Inf ());\n  else if ((x < 0 && math::is_integer (x))\n           || math::isinf (x))\n    result = numeric_limits<double>::Inf ();\n  else if (math::isnan (x))\n    result = numeric_limits<double>::NaN ();\n  else\n    result = std::tgamma (x);\n\n  return result;\n}\n\nfloat\ngamma (float x)\n{\n  float result;\n\n  // Special cases for (near) compatibility with Matlab instead of tgamma.\n  // Matlab does not have -0.\n\n  if (x == 0)\n    result = (math::negative_sign (x)\n              ? -numeric_limits<float>::Inf ()\n              : numeric_limits<float>::Inf ());\n  else if ((x < 0 && math::is_integer (x))\n           || math::isinf (x))\n    result = numeric_limits<float>::Inf ();\n  else if (math::isnan (x))\n    result = numeric_limits<float>::NaN ();\n  else\n    result = std::tgammaf (x);\n\n  return result;\n}\n\nComplex\nlog1p (const Complex& x)\n{\n  Complex retval;\n\n  double r = x.real (), i = x.imag ();\n\n  if (fabs (r) < 0.5 && fabs (i) < 0.5)\n    {\n      double u = 2*r + r*r + i*i;\n      retval = Complex (log1p (u / (1+std::sqrt (u+1))),\n                        atan2 (i, 1 + r));\n    }\n  else\n    retval = std::log (Complex (1) + x);\n\n  return retval;\n}\n\nFloatComplex\nlog1p (const FloatComplex& x)\n{\n  FloatComplex retval;\n\n  float r = x.real (), i = x.imag ();\n\n  if (fabs (r) < 0.5 && fabs (i) < 0.5)\n    {\n      float u = 2*r + r*r + i*i;\n      retval = FloatComplex (log1p (u / (1+std::sqrt (u+1))),\n                             atan2 (i, 1 + r));\n    }\n  else\n    retval = std::log (FloatComplex (1) + x);\n\n  return retval;\n}\n\nstatic const double pi = 3.14159265358979323846;\n\ntemplate <typename T>\nstatic inline T\nxlog (const T& x)\n{\n  return log (x);\n}\n\ntemplate <>\ninline double\nxlog (const double& x)\n{\n  return std::log (x);\n}\n\ntemplate <>\ninline float\nxlog (const float& x)\n{\n  return std::log (x);\n}\n\ntemplate <typename T>\nstatic T\nlanczos_approximation_psi (const T zc)\n{\n  // Coefficients for C.Lanczos expansion of psi function from XLiFE++\n  // gammaFunctions psi_coef[k] = - (2k+1) * lg_coef[k] (see melina++\n  // gamma functions -1/12, 3/360,-5/1260, 7/1680,-9/1188,\n  // 11*691/360360,-13/156, 15*3617/122400, ? , ?\n  static const T dg_coeff[10] =\n  {\n    -0.83333333333333333e-1, 0.83333333333333333e-2,\n      -0.39682539682539683e-2, 0.41666666666666667e-2,\n      -0.75757575757575758e-2, 0.21092796092796093e-1,\n      -0.83333333333333333e-1, 0.4432598039215686,\n      -0.3053954330270122e+1,  0.125318899521531e+2\n    };\n\n  T overz2  = T (1.0) / (zc * zc);\n  T overz2k = overz2;\n\n  T p = 0;\n  for (octave_idx_type k = 0; k < 10; k++, overz2k *= overz2)\n    p += dg_coeff[k] * overz2k;\n  p += xlog (zc) - T (0.5) / zc;\n  return p;\n}\n\ntemplate <typename T>\nT\nxpsi (T z)\n{\n  static const double euler_mascheroni\n    = 0.577215664901532860606512090082402431042;\n\n  const bool is_int = (std::floor (z) == z);\n\n  T p = 0;\n  if (z <= 0)\n    {\n      // limits - zeros of the gamma function\n      if (is_int)\n        p = -numeric_limits<T>::Inf (); // Matlab returns -Inf for psi (0)\n      else\n        // Abramowitz and Stegun, page 259, eq 6.3.7\n        p = psi (1 - z) - (pi / tan (pi * z));\n    }\n  else if (is_int)\n    {\n      // Abramowitz and Stegun, page 258, eq 6.3.2\n      p = - euler_mascheroni;\n      for (octave_idx_type k = z - 1; k > 0; k--)\n        p += 1.0 / k;\n    }\n  else if (z - std::floor (z) == 0.5)\n    {\n      // Abramowitz and Stegun, page 258, eq 6.3.3 and 6.3.4\n      for (octave_idx_type k = z; k > 0; k--)\n        p += 1.0 / (2 * k - 1);\n\n      p = - euler_mascheroni - 2 * std::log (2) + 2 * (p);\n    }\n  else\n    {\n      // adapted from XLiFE++ gammaFunctions\n\n      T zc = z;\n      // Use formula for derivative of LogGamma(z)\n      if (z < 10)\n        {\n          const signed char n = 10 - z;\n          for (signed char k = n - 1; k >= 0; k--)\n            p -= 1.0 / (k + z);\n          zc += n;\n        }\n      p += lanczos_approximation_psi (zc);\n    }\n\n  return p;\n}\n\n// explicit instantiations\ndouble\npsi (double z) { return xpsi (z); }\nfloat\npsi (float z) { return xpsi (z); }\n\ntemplate <typename T>\nstd::complex<T>\nxpsi (const std::complex<T>& z)\n{\n  // adapted from XLiFE++ gammaFunctions\n\n  typedef typename std::complex<T>::value_type P;\n\n  P z_r  = z.real ();\n  P z_ra = z_r;\n\n  std::complex<T> dgam (0.0, 0.0);\n  if (z.imag () == 0)\n    dgam = std::complex<T> (psi (z_r), 0.0);\n  else if (z_r < 0)\n    dgam = psi (P (1.0) - z)- (P (pi) / tan (P (pi) * z));\n  else\n    {\n      // Use formula for derivative of LogGamma(z)\n      std::complex<T> z_m = z;\n      if (z_ra < 8)\n        {\n          unsigned char n = 8 - z_ra;\n          z_m = z + std::complex<T> (n, 0.0);\n\n          // Recurrence formula.  For | Re(z) | < 8, use recursively\n          //\n          //   DiGamma(z) = DiGamma(z+1) - 1/z\n          std::complex<T> z_p = z + P (n - 1);\n          for (unsigned char k = n; k > 0; k--, z_p -= 1.0)\n            dgam -= P (1.0) / z_p;\n        }\n\n      // for | Re(z) | > 8, use derivative of C.Lanczos expansion for\n      // LogGamma\n      //\n      //   psi(z) = log(z) - 1/(2z) - 1/12z^2 + 3/360z^4 - 5/1260z^6\n      //     + 7/1680z^8 - 9/1188z^10 + ...\n      //\n      // (Abramowitz&Stegun, page 259, formula 6.3.18\n      dgam += lanczos_approximation_psi (z_m);\n    }\n  return dgam;\n}\n\n// explicit instantiations\nComplex\npsi (const Complex& z) { return xpsi (z); }\nFloatComplex\npsi (const FloatComplex& z) { return xpsi (z); }\n\ntemplate <typename T>\nstatic inline void\nfortran_psifn (T z, octave_idx_type n, T& ans, octave_idx_type& ierr);\n\ntemplate <>\ninline void\nfortran_psifn<double> (double z, octave_idx_type n_arg,\n                       double& ans, octave_idx_type& ierr)\n{\n  F77_INT n = to_f77_int (n_arg);\n  F77_INT flag = 0;\n  F77_INT t_ierr;\n  F77_XFCN (dpsifn, DPSIFN, (z, n, 1, 1, ans, flag, t_ierr));\n  ierr = t_ierr;\n}\n\ntemplate <>\ninline void\nfortran_psifn<float> (float z, octave_idx_type n_arg,\n                      float& ans, octave_idx_type& ierr)\n{\n  F77_INT n = to_f77_int (n_arg);\n  F77_INT flag = 0;\n  F77_INT t_ierr;\n  F77_XFCN (psifn, PSIFN, (z, n, 1, 1, ans, flag, t_ierr));\n  ierr = t_ierr;\n}\n\ntemplate <typename T>\nT\nxpsi (octave_idx_type n, T z)\n{\n  T ans;\n  octave_idx_type ierr = 0;\n  fortran_psifn<T> (z, n, ans, ierr);\n  if (ierr == 0)\n    {\n      // Remember that psifn and dpsifn return scales values\n      // When n is 1: do nothing since ((-1)**(n+1)/gamma(n+1)) == 1\n      // When n is 0: change sign since ((-1)**(n+1)/gamma(n+1)) == -1\n      if (n > 1)\n        // FIXME: xgamma here is a killer for our precision since it grows\n        //        way too fast.\n        ans = ans / (std::pow (-1.0, n + 1) / gamma (double (n+1)));\n      else if (n == 0)\n        ans = -ans;\n    }\n  else if (ierr == 2)\n    ans = - numeric_limits<T>::Inf ();\n  else // we probably never get here\n    ans = numeric_limits<T>::NaN ();\n\n  return ans;\n}\n\ndouble\npsi (octave_idx_type n, double z) { return xpsi (n, z); }\nfloat\npsi (octave_idx_type n, float z) { return xpsi (n, z); }\n\nComplex\nrc_lgamma (double x)\n{\n  double result;\n\n#if defined (HAVE_LGAMMA_R)\n  int sgngam;\n  result = lgamma_r (x, &sgngam);\n#else\n  result = std::lgamma (x);\n  int sgngam = signgam;\n#endif\n\n  if (sgngam < 0 && std::isfinite (result))\n    return Complex (result, M_PI);\n  else\n    return result;\n}\n\nFloatComplex\nrc_lgamma (float x)\n{\n  float result;\n\n#if defined (HAVE_LGAMMAF_R)\n  int sgngam;\n  result = lgammaf_r (x, &sgngam);\n#else\n  result = std::lgammaf (x);\n  int sgngam = signgam;\n#endif\n\n  if (sgngam < 0 && std::isfinite (result))\n    return FloatComplex (result, M_PI);\n  else\n    return result;\n}\n\nComplex\nrc_log1p (double x)\n{\n  return (x < -1.0\n          ? Complex (std::log (-(1.0 + x)), M_PI)\n          : Complex (log1p (x)));\n}\n\nFloatComplex\nrc_log1p (float x)\n{\n  return (x < -1.0f\n          ? FloatComplex (std::log (-(1.0f + x)), M_PI)\n          : FloatComplex (log1p (x)));\n}\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/oct-specfun.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_specfun_h)\n#define octave_oct_specfun_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\n#include \"Array-oct.h\"\n#include \"oct-cmplx.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ninline double acosh (double x) { return std::acosh (x); }\ninline float acosh (float x) { return std::acoshf (x); }\ninline Complex acosh (const Complex& x) { return std::acosh (x); }\ninline FloatComplex acosh (const FloatComplex& x) { return std::acosh (x); }\n\nextern OCTAVE_API Complex airy (const Complex& z, bool deriv, bool scaled,\n                                octave_idx_type& ierr);\nextern OCTAVE_API ComplexMatrix airy (const ComplexMatrix& z, bool deriv,\n                                      bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray airy (const ComplexNDArray& z, bool deriv,\n                                       bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplex airy (const FloatComplex& z, bool deriv,\n                                     bool scaled, octave_idx_type& ierr);\nextern OCTAVE_API FloatComplexMatrix airy (const FloatComplexMatrix& z,\n                                           bool deriv, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray airy (const FloatComplexNDArray& z,\n                                            bool deriv, bool scaled, Array<octave_idx_type>& ierr);\n\ninline double asinh (double x) { return std::asinh (x); }\ninline float asinh (float x) { return std::asinhf (x); }\ninline Complex asinh (const Complex& x) { return std::asinh (x); }\ninline FloatComplex asinh (const FloatComplex& x) { return std::asinh (x); }\n\ninline double atanh (double x) { return std::atanh (x); }\ninline float atanh (float x) { return std::atanhf (x); }\ninline Complex atanh (const Complex& x) { return std::atanh (x); }\ninline FloatComplex atanh (const FloatComplex& x) { return std::atanh (x); }\n\nextern OCTAVE_API Complex besselj (double alpha, const Complex& x, bool scaled,\n                                   octave_idx_type& ierr);\nextern OCTAVE_API Complex bessely (double alpha, const Complex& x, bool scaled,\n                                   octave_idx_type& ierr);\nextern OCTAVE_API Complex besseli (double alpha, const Complex& x, bool scaled,\n                                   octave_idx_type& ierr);\nextern OCTAVE_API Complex besselk (double alpha, const Complex& x, bool scaled,\n                                   octave_idx_type& ierr);\nextern OCTAVE_API Complex besselh1 (double alpha, const Complex& x, bool scaled,\n                                    octave_idx_type& ierr);\nextern OCTAVE_API Complex besselh2 (double alpha, const Complex& x, bool scaled,\n                                    octave_idx_type& ierr);\n\nextern OCTAVE_API ComplexMatrix besselj (double alpha, const ComplexMatrix& x,\n                                         bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix bessely (double alpha, const ComplexMatrix& x,\n                                         bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besseli (double alpha, const ComplexMatrix& x,\n                                         bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselk (double alpha, const ComplexMatrix& x,\n                                         bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselh1 (double alpha, const ComplexMatrix& x,\n                                          bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselh2 (double alpha, const ComplexMatrix& x,\n                                          bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API ComplexMatrix besselj (const Matrix& alpha, const Complex& x,\n                                         bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix bessely (const Matrix& alpha, const Complex& x,\n                                         bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besseli (const Matrix& alpha, const Complex& x,\n                                         bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselk (const Matrix& alpha, const Complex& x,\n                                         bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselh1 (const Matrix& alpha, const Complex& x,\n                                          bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselh2 (const Matrix& alpha, const Complex& x,\n                                          bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API ComplexMatrix besselj (const Matrix& alpha,\n                                         const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix bessely (const Matrix& alpha,\n                                         const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besseli (const Matrix& alpha,\n                                         const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselk (const Matrix& alpha,\n                                         const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselh1 (const Matrix& alpha,\n                                          const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselh2 (const Matrix& alpha,\n                                          const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API ComplexNDArray besselj (double alpha, const ComplexNDArray& x,\n                                          bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray bessely (double alpha, const ComplexNDArray& x,\n                                          bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besseli (double alpha, const ComplexNDArray& x,\n                                          bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besselk (double alpha, const ComplexNDArray& x,\n                                          bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besselh1 (double alpha,\n                                           const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besselh2 (double alpha,\n                                           const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API ComplexNDArray besselj (const NDArray& alpha,\n                                          const Complex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray bessely (const NDArray& alpha,\n                                          const Complex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besseli (const NDArray& alpha,\n                                          const Complex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besselk (const NDArray& alpha,\n                                          const Complex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besselh1 (const NDArray& alpha,\n                                           const Complex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besselh2 (const NDArray& alpha,\n                                           const Complex& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API ComplexNDArray besselj (const NDArray& alpha,\n                                          const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray bessely (const NDArray& alpha,\n                                          const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besseli (const NDArray& alpha,\n                                          const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besselk (const NDArray& alpha,\n                                          const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besselh1 (const NDArray& alpha,\n                                           const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray besselh2 (const NDArray& alpha,\n                                           const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API ComplexMatrix besselj (const RowVector& alpha,\n                                         const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix bessely (const RowVector& alpha,\n                                         const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besseli (const RowVector& alpha,\n                                         const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselk (const RowVector& alpha,\n                                         const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselh1 (const RowVector& alpha,\n                                          const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexMatrix besselh2 (const RowVector& alpha,\n                                          const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API FloatComplex besselj (float alpha, const FloatComplex& x,\n                                        bool scaled, octave_idx_type& ierr);\nextern OCTAVE_API FloatComplex bessely (float alpha, const FloatComplex& x,\n                                        bool scaled, octave_idx_type& ierr);\nextern OCTAVE_API FloatComplex besseli (float alpha, const FloatComplex& x,\n                                        bool scaled, octave_idx_type& ierr);\nextern OCTAVE_API FloatComplex besselk (float alpha, const FloatComplex& x,\n                                        bool scaled, octave_idx_type& ierr);\nextern OCTAVE_API FloatComplex besselh1 (float alpha, const FloatComplex& x,\n                                         bool scaled, octave_idx_type& ierr);\nextern OCTAVE_API FloatComplex besselh2 (float alpha, const FloatComplex& x,\n                                         bool scaled, octave_idx_type& ierr);\n\nextern OCTAVE_API FloatComplexMatrix besselj (float alpha,\n                                              const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix bessely (float alpha,\n                                              const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besseli (float alpha,\n                                              const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselk (float alpha,\n                                              const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselh1 (float alpha,\n                                               const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselh2 (float alpha,\n                                               const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API FloatComplexMatrix besselj (const FloatMatrix& alpha,\n                                              const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix bessely (const FloatMatrix& alpha,\n                                              const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besseli (const FloatMatrix& alpha,\n                                              const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselk (const FloatMatrix& alpha,\n                                              const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselh1 (const FloatMatrix& alpha,\n                                               const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselh2 (const FloatMatrix& alpha,\n                                               const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API FloatComplexMatrix besselj (const FloatMatrix& alpha,\n                                              const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix bessely (const FloatMatrix& alpha,\n                                              const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besseli (const FloatMatrix& alpha,\n                                              const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselk (const FloatMatrix& alpha,\n                                              const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselh1 (const FloatMatrix& alpha,\n                                               const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselh2 (const FloatMatrix& alpha,\n                                               const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API FloatComplexNDArray besselj (float alpha,\n                                               const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray bessely (float alpha,\n                                               const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besseli (float alpha,\n                                               const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besselk (float alpha,\n                                               const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besselh1 (float alpha,\n                                                const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besselh2 (float alpha,\n                                                const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API FloatComplexNDArray besselj (const FloatNDArray& alpha,\n                                               const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray bessely (const FloatNDArray& alpha,\n                                               const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besseli (const FloatNDArray& alpha,\n                                               const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besselk (const FloatNDArray& alpha,\n                                               const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besselh1 (const FloatNDArray& alpha,\n                                                const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besselh2 (const FloatNDArray& alpha,\n                                                const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API FloatComplexNDArray besselj (const FloatNDArray& alpha,\n                                               const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray bessely (const FloatNDArray& alpha,\n                                               const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besseli (const FloatNDArray& alpha,\n                                               const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besselk (const FloatNDArray& alpha,\n                                               const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besselh1 (const FloatNDArray& alpha,\n                                                const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray besselh2 (const FloatNDArray& alpha,\n                                                const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API FloatComplexMatrix besselj (const FloatRowVector& alpha,\n                                              const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix bessely (const FloatRowVector& alpha,\n                                              const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besseli (const FloatRowVector& alpha,\n                                              const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselk (const FloatRowVector& alpha,\n                                              const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselh1 (const FloatRowVector& alpha,\n                                               const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexMatrix besselh2 (const FloatRowVector& alpha,\n                                               const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);\n\nextern OCTAVE_API Complex biry (const Complex& z, bool deriv, bool scaled,\n                                octave_idx_type& ierr);\nextern OCTAVE_API ComplexMatrix biry (const ComplexMatrix& z, bool deriv,\n                                      bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API ComplexNDArray biry (const ComplexNDArray& z, bool deriv,\n                                       bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplex biry (const FloatComplex& z, bool deriv,\n                                     bool scaled, octave_idx_type& ierr);\nextern OCTAVE_API FloatComplexMatrix biry (const FloatComplexMatrix& z,\n                                           bool deriv, bool scaled, Array<octave_idx_type>& ierr);\nextern OCTAVE_API FloatComplexNDArray biry (const FloatComplexNDArray& z,\n                                            bool deriv, bool scaled, Array<octave_idx_type>& ierr);\n\ninline double cbrt (double x) { return std::cbrt (x); }\ninline float cbrt (float x) { return std::cbrtf (x); }\n\nextern OCTAVE_API double dawson (double x);\nextern OCTAVE_API float dawson (float x);\nextern OCTAVE_API Complex dawson (const Complex& x);\nextern OCTAVE_API FloatComplex dawson (const FloatComplex& x);\n\nextern OCTAVE_API void ellipj (double u, double m, double& sn, double& cn,\n                               double& dn, double& err);\nextern OCTAVE_API void ellipj (const Complex& u, double m, Complex& sn,\n                               Complex& cn, Complex& dn, double& err);\n\ninline double erf (double x) { return std::erf (x); }\ninline float erf (float x) { return std::erff (x); }\nextern OCTAVE_API Complex erf (const Complex& x);\nextern OCTAVE_API FloatComplex erf (const FloatComplex& x);\n\ninline double erfc (double x) { return std::erfc (x); }\ninline float erfc (float x) { return std::erfcf (x); }\nextern OCTAVE_API Complex erfc (const Complex& x);\nextern OCTAVE_API FloatComplex erfc (const FloatComplex& x);\n\nextern OCTAVE_API double erfcinv (double x);\nextern OCTAVE_API float erfcinv (float x);\n\nextern OCTAVE_API double erfcx (double x);\nextern OCTAVE_API float erfcx (float x);\nextern OCTAVE_API Complex erfcx (const Complex& x);\nextern OCTAVE_API FloatComplex erfcx (const FloatComplex& x);\n\nextern OCTAVE_API double erfi (double x);\nextern OCTAVE_API float erfi (float x);\nextern OCTAVE_API Complex erfi (const Complex& x);\nextern OCTAVE_API FloatComplex erfi (const FloatComplex& x);\n\nextern OCTAVE_API double erfinv (double x);\nextern OCTAVE_API float erfinv (float x);\n\ninline double expm1 (double x) { return std::expm1 (x); }\ninline float expm1 (float x) { return std::expm1f (x); }\nextern OCTAVE_API Complex expm1 (const Complex& x);\nextern OCTAVE_API FloatComplex expm1 (const FloatComplex& x);\n\nextern OCTAVE_API double gamma (double x);\nextern OCTAVE_API float gamma (float x);\n\ninline double lgamma (double x) { return std::lgamma (x); }\ninline float lgamma (float x) { return std::lgammaf (x); }\n\ninline double log1p (double x) { return std::log1p (x); }\ninline float log1p (float x) { return std::log1pf (x); }\nextern OCTAVE_API Complex log1p (const Complex& x);\nextern OCTAVE_API FloatComplex log1p (const FloatComplex& x);\n\nextern OCTAVE_API double psi (double x);\nextern OCTAVE_API float psi (float x);\nextern OCTAVE_API Complex psi (const Complex& x);\nextern OCTAVE_API FloatComplex psi (const FloatComplex& x);\nextern OCTAVE_API double psi (octave_idx_type n, double z);\nextern OCTAVE_API float psi (octave_idx_type n, float z);\n\nextern OCTAVE_API Complex rc_lgamma (double x);\nextern OCTAVE_API FloatComplex rc_lgamma (float x);\n\nextern OCTAVE_API Complex rc_log1p (double x);\nextern OCTAVE_API FloatComplex rc_log1p (float x);\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/oct-spparms.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ostream>\n\n#include \"Array-oct.h\"\n#include \"lo-ieee.h\"\n#include \"oct-error.h\"\n#include \"oct-spparms.h\"\n#include \"singleton-cleanup.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nsparse_params *sparse_params::s_instance = nullptr;\n\nbool\nsparse_params::instance_ok ()\n{\n  bool retval = true;\n\n  if (! s_instance)\n    {\n      s_instance = new sparse_params ();\n      singleton_cleanup_list::add (cleanup_instance);\n    }\n\n  return retval;\n}\n\nvoid\nsparse_params::defaults ()\n{\n  if (instance_ok ())\n    s_instance->do_defaults ();\n}\n\nvoid\nsparse_params::tight ()\n{\n  if (instance_ok ())\n    s_instance->do_tight ();\n}\n\nstring_vector\nsparse_params::get_keys ()\n{\n  return instance_ok () ? s_instance->do_get_keys () : string_vector ();\n}\n\nColumnVector\nsparse_params::get_vals ()\n{\n  return instance_ok () ? s_instance->do_get_vals () : ColumnVector ();\n}\n\nbool\nsparse_params::set_vals (const Array<double>& vals)\n{\n  return instance_ok () ? s_instance->do_set_vals (vals) : false;\n}\n\nbool\nsparse_params::set_key (const std::string& key, const double& val)\n{\n  return instance_ok () ? s_instance->do_set_key (key, val) : false;\n}\n\ndouble\nsparse_params::get_key (const std::string& key)\n{\n  return (instance_ok ()\n          ? s_instance->do_get_key (key) : numeric_limits<double>::NaN ());\n}\n\ndouble\nsparse_params::get_bandden ()\n{\n  return instance_ok () ? s_instance->do_get_bandden () : 0.0;\n}\n\nvoid\nsparse_params::print_info (std::ostream& os, const std::string& prefix)\n{\n  if (instance_ok ())\n    s_instance->do_print_info (os, prefix);\n}\n\nvoid\nsparse_params::do_defaults ()\n{\n  m_params(0) = 0;      // spumoni\n  m_params(1) = 1;      // ths_rel\n  m_params(2) = 1;      // ths_abs\n  m_params(3) = 0;      // exact_d\n  m_params(4) = 3;      // supernd\n  m_params(5) = 3;      // rreduce\n  m_params(6) = 0.5;    // wh_frac\n  m_params(7) = 1;      // autommd\n  m_params(8) = 1;      // autoamd\n  m_params(9) = 0.1;    // piv_tol\n  m_params(10) = 0.5;   // bandden\n  m_params(11) = 1;     // umfpack\n  m_params(12) = 0.001; // sym_tol\n}\n\nvoid\nsparse_params::do_tight ()\n{\n  m_params(0) = 0;      // spumoni\n  m_params(1) = 1;      // ths_rel\n  m_params(2) = 0;      // ths_abs\n  m_params(3) = 1;      // exact_d\n  m_params(4) = 1;      // supernd\n  m_params(5) = 1;      // rreduce\n  m_params(6) = 0.5;    // wh_frac\n  m_params(7) = 1;      // autommd\n  m_params(8) = 1;      // autoamd\n  m_params(9) = 0.1;    // piv_tol\n  m_params(10) = 0.5;   // bandden\n  m_params(11) = 1;     // umfpack\n  m_params(12) = 0.001; // sym_tol\n}\n\nvoid\nsparse_params::init_keys ()\n{\n  m_keys(0) = \"spumoni\";\n  m_keys(1) = \"ths_rel\";\n  m_keys(2) = \"ths_abs\";\n  m_keys(3) = \"exact_d\";\n  m_keys(4) = \"supernd\";\n  m_keys(5) = \"rreduce\";\n  m_keys(6) = \"wh_frac\";\n  m_keys(7) = \"autommd\";\n  m_keys(8) = \"autoamd\";\n  m_keys(9) = \"piv_tol\";\n  m_keys(10) = \"bandden\";\n  m_keys(11) = \"umfpack\";\n  m_keys(12) = \"sym_tol\";\n}\n\ndouble\nsparse_params::do_get_bandden ()\n{\n  return m_params(10);\n}\n\nbool\nsparse_params::do_set_vals (const Array<double>& vals)\n{\n  octave_idx_type len = vals.numel ();\n\n  if (len > OCTAVE_SPARSE_CONTROLS_SIZE)\n    (*current_liboctave_error_handler)\n      (\"sparse_params::do_set_vals: too many values\");\n\n  for (int i = 0; i < len; i++)\n    m_params(i) = vals(i);\n\n  return true;\n}\n\nbool\nsparse_params::do_set_key (const std::string& key, const double& val)\n{\n  for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++)\n    {\n      if (m_keys (i) == key)\n        {\n          m_params(i) = val;\n          return true;\n        }\n    }\n\n  return false;\n}\n\ndouble\nsparse_params::do_get_key (const std::string& key)\n{\n  for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++)\n    {\n      if (m_keys (i) == key)\n        return m_params(i);\n    }\n\n  return numeric_limits<double>::NaN ();\n}\n\nvoid\nsparse_params::do_print_info (std::ostream& os,\n                              const std::string& prefix) const\n{\n  for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++)\n    os << prefix << m_keys(i) << \": \" << m_params(i) << \"\\n\";\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/oct-spparms.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_spparms_h)\n#define octave_oct_spparms_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\n#include \"Array-fwd.h\"\n#include \"str-vec.h\"\n#include \"dColVector.h\"\n\n#define OCTAVE_SPARSE_CONTROLS_SIZE 13\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTAVE_API sparse_params\n{\nprotected:\n\n  sparse_params ()\n    : m_params (OCTAVE_SPARSE_CONTROLS_SIZE),\n      m_keys (OCTAVE_SPARSE_CONTROLS_SIZE)\n  {\n    init_keys ();\n    do_defaults ();\n  }\n\npublic:\n\n  sparse_params (const sparse_params&) = default;\n\n  sparse_params& operator = (const sparse_params&) = default;\n\n  ~sparse_params () = default;\n\n  static bool instance_ok ();\n\n  static void defaults ();\n\n  static void tight ();\n\n  static string_vector get_keys ();\n\n  static ColumnVector get_vals ();\n\n  static bool set_vals (const Array<double>& vals);\n\n  static bool set_key (const std::string& key, const double& val);\n\n  static double get_key (const std::string& key);\n\n  static double get_bandden ();\n\n  static void print_info (std::ostream& os, const std::string& prefix);\n\nprivate:\n\n  ColumnVector m_params;\n\n  string_vector m_keys;\n\n  static sparse_params *s_instance;\n\n  static void cleanup_instance ()\n  {\n    delete s_instance;\n    s_instance = nullptr;\n  }\n\n  void do_defaults ();\n\n  void do_tight ();\n\n  string_vector do_get_keys () const { return m_keys; }\n\n  ColumnVector do_get_vals () const { return m_params; }\n\n  bool do_set_vals (const Array<double>& vals);\n\n  bool do_set_key (const std::string& key, const double& val);\n\n  double do_get_key (const std::string& key);\n\n  double do_get_bandden ();\n\n  void do_print_info (std::ostream& os, const std::string& prefix) const;\n\n  void init_keys ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/qr.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <vector>\n\n#include \"Array-oct.h\"\n#include \"CColVector.h\"\n#include \"CMatrix.h\"\n#include \"CRowVector.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"dRowVector.h\"\n#include \"fCColVector.h\"\n#include \"fCMatrix.h\"\n#include \"fCRowVector.h\"\n#include \"fColVector.h\"\n#include \"fMatrix.h\"\n#include \"fRowVector.h\"\n#include \"lapack-proto.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sort.h\"\n#include \"qr.h\"\n#include \"qrupdate-proto.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nqr<T>::qr (const T& q_arg, const T& r_arg)\n  : m_q (q_arg), m_r (r_arg)\n{\n  octave_idx_type q_nr = m_q.rows ();\n  octave_idx_type q_nc = m_q.cols ();\n\n  octave_idx_type r_nr = m_r.rows ();\n  octave_idx_type r_nc = m_r.cols ();\n\n  if (! (q_nc == r_nr && (q_nr == q_nc || (q_nr > q_nc && r_nr == r_nc))))\n    (*current_liboctave_error_handler) (\"QR dimensions mismatch\");\n}\n\ntemplate <typename T>\ntypename qr<T>::type\nqr<T>::get_type () const\n{\n  type retval;\n\n  if (! m_q.isempty () && m_q.issquare ())\n    retval = qr<T>::std;\n  else if (m_q.rows () > m_q.cols () && m_r.issquare ())\n    retval = qr<T>::economy;\n  else\n    retval = qr<T>::raw;\n\n  return retval;\n}\n\ntemplate <typename T>\nbool\nqr<T>::regular () const\n{\n  bool retval = true;\n\n  octave_idx_type k = std::min (m_r.rows (), m_r.cols ());\n\n  for (octave_idx_type i = 0; i < k; i++)\n    {\n      if (m_r(i, i) == ELT_T ())\n        {\n          retval = false;\n          break;\n        }\n    }\n\n  return retval;\n}\n\n#if ! defined (HAVE_QRUPDATE)\n\n// Replacement update methods.\n\nvoid\nwarn_qrupdate_once ()\n{\n  static bool warned = false;\n\n  if (! warned)\n    {\n      (*current_liboctave_warning_with_id_handler)\n        (\"Octave:missing-dependency\",\n         \"In this version of Octave, QR & Cholesky updating routines \"\n         \"simply update the matrix and recalculate factorizations.  \"\n         \"To use fast algorithms, link Octave with the qrupdate library.  \"\n         \"See <http://sourceforge.net/projects/qrupdate>.\");\n\n      warned = true;\n    }\n}\n\ntemplate <typename T>\nvoid\nqr<T>::update (const CV_T& u, const CV_T& v)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type m = m_q.rows ();\n  octave_idx_type n = m_r.cols ();\n\n  if (u.numel () != m || v.numel () != n)\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  init (m_q*m_r + T (u) * T (v).hermitian (), get_type ());\n}\n\ntemplate <typename T>\nvoid\nqr<T>::update (const T& u, const T& v)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type m = m_q.rows ();\n  octave_idx_type n = m_r.cols ();\n\n  if (u.rows () != m || v.rows () != n || u.cols () != v.cols ())\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  init (m_q*m_r + u * v.hermitian (), get_type ());\n}\n\ntemplate <typename T, typename CV_T>\nstatic\nT\ninsert_col (const T& a, octave_idx_type i, const CV_T& x)\n{\n  T retval (a.rows (), a.cols () + 1);\n  retval.assign (idx_vector::colon, idx_vector (0, i),\n                 a.index (idx_vector::colon, idx_vector (0, i)));\n  retval.assign (idx_vector::colon, idx_vector (i), x);\n  retval.assign (idx_vector::colon, idx_vector (i+1, retval.cols ()),\n                 a.index (idx_vector::colon, idx_vector (i, a.cols ())));\n  return retval;\n}\n\ntemplate <typename T, typename RV_T>\nstatic\nT\ninsert_row (const T& a, octave_idx_type i, const RV_T& x)\n{\n  T retval (a.rows () + 1, a.cols ());\n  retval.assign (idx_vector (0, i), idx_vector::colon,\n                 a.index (idx_vector (0, i), idx_vector::colon));\n  retval.assign (idx_vector (i), idx_vector::colon, x);\n  retval.assign (idx_vector (i+1, retval.rows ()), idx_vector::colon,\n                 a.index (idx_vector (i, a.rows ()), idx_vector::colon));\n  return retval;\n}\n\ntemplate <typename T>\nstatic\nT\ndelete_col (const T& a, octave_idx_type i)\n{\n  T retval = a;\n  retval.delete_elements (1, idx_vector (i));\n  return retval;\n}\n\ntemplate <typename T>\nstatic\nT\ndelete_row (const T& a, octave_idx_type i)\n{\n  T retval = a;\n  retval.delete_elements (0, idx_vector (i));\n  return retval;\n}\n\ntemplate <typename T>\nstatic\nT\nshift_cols (const T& a, octave_idx_type i, octave_idx_type j)\n{\n  octave_idx_type n = a.cols ();\n  Array<octave_idx_type> p (dim_vector (n, 1));\n  for (octave_idx_type k = 0; k < n; k++) p(k) = k;\n  if (i < j)\n    {\n      for (octave_idx_type k = i; k < j; k++) p(k) = k+1;\n      p(j) = i;\n    }\n  else if (j < i)\n    {\n      p(j) = i;\n      for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1;\n    }\n\n  return a.index (idx_vector::colon, idx_vector (p));\n}\n\ntemplate <typename T>\nvoid\nqr<T>::insert_col (const CV_T& u, octave_idx_type j)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type m = m_q.rows ();\n  octave_idx_type n = m_r.cols ();\n\n  if (u.numel () != m)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  init (math::insert_col (m_q*m_r, j, u), get_type ());\n}\n\ntemplate <typename T>\nvoid\nqr<T>::insert_col (const T& u, const Array<octave_idx_type>& j)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type m = m_q.rows ();\n  octave_idx_type n = m_r.cols ();\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);\n  octave_idx_type nj = js.numel ();\n  bool dups = false;\n  for (octave_idx_type i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  if (u.numel () != m || u.cols () != nj)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (nj > 0 && (js(0) < 0 || js(nj-1) > n))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      T a = m_q*m_r;\n      for (octave_idx_type i = 0; i < nj; i++)\n        a = math::insert_col (a, js(i), u.column (i));\n\n      init (a, get_type ());\n    }\n}\n\ntemplate <typename T>\nvoid\nqr<T>::delete_col (octave_idx_type j)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type n = m_r.cols ();\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  init (math::delete_col (m_q*m_r, j), get_type ());\n}\n\ntemplate <typename T>\nvoid\nqr<T>::delete_col (const Array<octave_idx_type>& j)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type n = m_r.cols ();\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);\n  octave_idx_type nj = js.numel ();\n  bool dups = false;\n  for (octave_idx_type i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      T a = m_q*m_r;\n      for (octave_idx_type i = 0; i < nj; i++)\n        a = math::delete_col (a, js(i));\n\n      init (a, get_type ());\n    }\n}\n\ntemplate <typename T>\nvoid\nqr<T>::insert_row (const RV_T& u, octave_idx_type j)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type m = m_r.rows ();\n  octave_idx_type n = m_r.cols ();\n\n  if (! m_q.issquare () || u.numel () != n)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > m)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  init (math::insert_row (m_q*m_r, j, u), get_type ());\n}\n\ntemplate <typename T>\nvoid\nqr<T>::delete_row (octave_idx_type j)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type m = m_r.rows ();\n\n  if (! m_q.issquare ())\n    (*current_liboctave_error_handler) (\"qrdelete: dimensions mismatch\");\n\n  if (j < 0 || j > m-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  init (math::delete_row (m_q*m_r, j), get_type ());\n}\n\ntemplate <typename T>\nvoid\nqr<T>::shift_cols (octave_idx_type i, octave_idx_type j)\n{\n  warn_qrupdate_once ();\n\n  octave_idx_type n = m_r.cols ();\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrshift: index out of range\");\n\n  init (math::shift_cols (m_q*m_r, i, j), get_type ());\n}\n\n#endif\n\n// Specializations.\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::form (octave_idx_type n_arg, Matrix& afact, double *tau,\n                  type qr_type)\n{\n  F77_INT n = to_f77_int (n_arg);\n  F77_INT m = to_f77_int (afact.rows ());\n  F77_INT min_mn = std::min (m, n);\n  F77_INT info;\n\n  if (qr_type == qr<Matrix>::raw)\n    {\n      for (F77_INT j = 0; j < min_mn; j++)\n        {\n          F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1);\n          for (F77_INT i = limit + 1; i < m; i++)\n            afact.elem (i, j) *= tau[j];\n        }\n\n      m_r = afact;\n    }\n  else\n    {\n      // Attempt to minimize copying.\n      if (m >= n)\n        {\n          // afact will become m_q.\n          m_q = afact;\n          F77_INT k = (qr_type == qr<Matrix>::economy ? n : m);\n          m_r = Matrix (k, n);\n          for (F77_INT j = 0; j < n; j++)\n            {\n              F77_INT i = 0;\n              for (; i <= j; i++)\n                m_r.xelem (i, j) = afact.xelem (i, j);\n              for (; i < k; i++)\n                m_r.xelem (i, j) = 0;\n            }\n          afact = Matrix (); // optimize memory\n        }\n      else\n        {\n          // afact will become m_r.\n          m_q = Matrix (m, m);\n          for (F77_INT j = 0; j < m; j++)\n            for (F77_INT i = j + 1; i < m; i++)\n              {\n                m_q.xelem (i, j) = afact.xelem (i, j);\n                afact.xelem (i, j) = 0;\n              }\n          m_r = afact;\n        }\n\n      if (m > 0)\n        {\n          F77_INT k = to_f77_int (m_q.cols ());\n          // workspace query.\n          double rlwork;\n          F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.rwdata (), m,\n                                     tau, &rlwork, -1, info));\n\n          // allocate buffer and do the job.\n          F77_INT lwork = static_cast<F77_INT> (rlwork);\n          lwork = std::max (lwork, static_cast<F77_INT> (1));\n          OCTAVE_LOCAL_BUFFER (double, work, lwork);\n          F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.rwdata (), m,\n                                     tau, work, lwork, info));\n        }\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::init (const Matrix& a, type qr_type)\n{\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n\n  F77_INT min_mn = (m < n ? m : n);\n  OCTAVE_LOCAL_BUFFER (double, tau, min_mn);\n\n  F77_INT info = 0;\n\n  Matrix afact = a;\n  if (m > n && qr_type == qr<Matrix>::std)\n    afact.resize (m, m);\n\n  if (m > 0)\n    {\n      // workspace query.\n      double rlwork;\n      F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.rwdata (), m, tau,\n                                 &rlwork, -1, info));\n\n      // allocate buffer and do the job.\n      F77_INT lwork = static_cast<F77_INT> (rlwork);\n      lwork = std::max (lwork, static_cast<F77_INT> (1));\n      OCTAVE_LOCAL_BUFFER (double, work, lwork);\n      F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.rwdata (), m, tau,\n                                 work, lwork, info));\n    }\n\n  form (n, afact, tau, qr_type);\n}\n\n#if defined (HAVE_QRUPDATE)\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::update (const ColumnVector& u, const ColumnVector& v)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  std::vector<double> utmp (u.data (), u.data () + u.numel ());\n  std::vector<double> vtmp (v.data (), v.data () + v.numel ());\n  OCTAVE_LOCAL_BUFFER (double, w, 2*k);\n  F77_XFCN (dqr1up, DQR1UP, (m, n, k, m_q.rwdata (), m,\n                             m_r.rwdata (), k, utmp.data (),\n                             vtmp.data (), w));\n}\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::update (const Matrix& u, const Matrix& v)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_rows = to_f77_int (u.rows ());\n  F77_INT u_cols = to_f77_int (u.cols ());\n\n  F77_INT v_rows = to_f77_int (v.rows ());\n  F77_INT v_cols = to_f77_int (v.cols ());\n\n  if (u_rows != m || v_rows != n || u_cols != v_cols)\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  OCTAVE_LOCAL_BUFFER (double, w, 2*k);\n  for (F77_INT i = 0; i < u_cols; i++)\n    {\n      std::vector<double> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      std::vector<double> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (dqr1up, DQR1UP, (m, n, k, m_q.rwdata (), m,\n                                 m_r.rwdata (), k, utmp.data (),\n                                 vtmp.data (), w));\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::insert_col (const ColumnVector& u, octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n\n  if (u_nel != m)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (k < m)\n    {\n      m_q.resize (m, k+1);\n      m_r.resize (k+1, n+1);\n    }\n  else\n    m_r.resize (k, n+1);\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  const std::vector<double> utmp (u.data (), u.data () + u.numel ());\n  OCTAVE_LOCAL_BUFFER (double, w, k);\n  F77_XFCN (dqrinc, DQRINC, (m, n, k, m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr, j + 1,\n                             utmp.data (), w));\n}\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::insert_col (const Matrix& u, const Array<octave_idx_type>& j)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);\n  F77_INT nj = to_f77_int (js.numel ());\n  bool dups = false;\n  for (F77_INT i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT u_cols = to_f77_int (u.cols ());\n\n  if (u_nel != m || u_cols != nj)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  F77_INT js_beg = to_f77_int (js(0));\n  F77_INT js_end = to_f77_int (js(nj-1));\n\n  if (nj > 0 && (js_beg < 0 || js_end > n))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      F77_INT kmax = std::min (k + nj, m);\n      if (k < m)\n        {\n          m_q.resize (m, kmax);\n          m_r.resize (kmax, n + nj);\n        }\n      else\n        m_r.resize (k, n + nj);\n\n      F77_INT ldq = to_f77_int (m_q.rows ());\n      F77_INT ldr = to_f77_int (m_r.rows ());\n\n      OCTAVE_LOCAL_BUFFER (double, w, kmax);\n      for (F77_INT i = 0; i < nj; i++)\n        {\n          F77_INT ii = i;\n          const std::vector<double> utmp (u.data () + jsi(i) * u.rows (), u.data () + (jsi(i) + 1) * u.rows ());\n          F77_INT js_elt = to_f77_int (js(ii));\n          F77_XFCN (dqrinc, DQRINC, (m, n + ii, std::min (kmax, k + ii),\n                                     m_q.rwdata (), ldq,\n                                     m_r.rwdata (), ldr, js_elt + 1,\n                                     utmp.data (), w));\n        }\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::delete_col (octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT k = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (double, w, k);\n  F77_XFCN (dqrdec, DQRDEC, (m, n, k, m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr, j + 1, w));\n\n  if (k < m)\n    {\n      m_q.resize (m, k-1);\n      m_r.resize (k-1, n-1);\n    }\n  else\n    m_r.resize (k, n-1);\n}\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::delete_col (const Array<octave_idx_type>& j)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);\n  F77_INT nj = to_f77_int (js.numel ());\n  bool dups = false;\n  for (F77_INT i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  F77_INT js_beg = to_f77_int (js(0));\n  F77_INT js_end = to_f77_int (js(nj-1));\n\n  if (nj > 0 && (js_beg > n-1 || js_end < 0))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      F77_INT ldq = to_f77_int (m_q.rows ());\n      F77_INT ldr = to_f77_int (m_r.rows ());\n\n      OCTAVE_LOCAL_BUFFER (double, w, k);\n      for (F77_INT i = 0; i < nj; i++)\n        {\n          F77_INT ii = i;\n          F77_INT js_elt = to_f77_int (js(ii));\n          F77_XFCN (dqrdec, DQRDEC, (m, n - ii, (k == m ? k : k - ii),\n                                     m_q.rwdata (), ldq,\n                                     m_r.rwdata (), ldr,\n                                     js_elt + 1, w));\n        }\n\n      if (k < m)\n        {\n          m_q.resize (m, k - nj);\n          m_r.resize (k - nj, n - nj);\n        }\n      else\n        m_r.resize (k, n - nj);\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::insert_row (const RowVector& u, octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = std::min (m, n);\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n\n  if (! m_q.issquare () || u_nel != n)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > m)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  m_q.resize (m + 1, m + 1);\n  m_r.resize (m + 1, n);\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  std::vector<double> utmp (u.data (), u.data () + u.numel ());\n  OCTAVE_LOCAL_BUFFER (double, w, k);\n  F77_XFCN (dqrinr, DQRINR, (m, n, m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr,\n                             j + 1, utmp.data (), w));\n\n}\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::delete_row (octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (! m_q.issquare ())\n    (*current_liboctave_error_handler) (\"qrdelete: dimensions mismatch\");\n\n  if (j < 0 || j > m-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (double, w, 2*m);\n  F77_XFCN (dqrder, DQRDER, (m, n, m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr, j + 1, w));\n\n  m_q.resize (m - 1, m - 1);\n  m_r.resize (m - 1, n);\n}\n\ntemplate <>\nOCTAVE_API void\nqr<Matrix>::shift_cols (octave_idx_type i_arg, octave_idx_type j_arg)\n{\n  F77_INT i = to_f77_int (i_arg);\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT k = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrshift: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (double, w, 2*k);\n  F77_XFCN (dqrshc, DQRSHC, (m, n, k,\n                             m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr,\n                             i + 1, j + 1, w));\n}\n\n#endif\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::form (octave_idx_type n_arg, FloatMatrix& afact,\n                       float *tau, type qr_type)\n{\n  F77_INT n = to_f77_int (n_arg);\n  F77_INT m = to_f77_int (afact.rows ());\n  F77_INT min_mn = std::min (m, n);\n  F77_INT info;\n\n  if (qr_type == qr<FloatMatrix>::raw)\n    {\n      for (F77_INT j = 0; j < min_mn; j++)\n        {\n          F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1);\n          for (F77_INT i = limit + 1; i < m; i++)\n            afact.elem (i, j) *= tau[j];\n        }\n\n      m_r = afact;\n    }\n  else\n    {\n      // Attempt to minimize copying.\n      if (m >= n)\n        {\n          // afact will become m_q.\n          m_q = afact;\n          F77_INT k = (qr_type == qr<FloatMatrix>::economy ? n : m);\n          m_r = FloatMatrix (k, n);\n          for (F77_INT j = 0; j < n; j++)\n            {\n              F77_INT i = 0;\n              for (; i <= j; i++)\n                m_r.xelem (i, j) = afact.xelem (i, j);\n              for (; i < k; i++)\n                m_r.xelem (i, j) = 0;\n            }\n          afact = FloatMatrix (); // optimize memory\n        }\n      else\n        {\n          // afact will become m_r.\n          m_q = FloatMatrix (m, m);\n          for (F77_INT j = 0; j < m; j++)\n            for (F77_INT i = j + 1; i < m; i++)\n              {\n                m_q.xelem (i, j) = afact.xelem (i, j);\n                afact.xelem (i, j) = 0;\n              }\n          m_r = afact;\n        }\n\n      if (m > 0)\n        {\n          F77_INT k = to_f77_int (m_q.cols ());\n          // workspace query.\n          float rlwork;\n          F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.rwdata (), m,\n                                     tau, &rlwork, -1, info));\n\n          // allocate buffer and do the job.\n          F77_INT lwork = static_cast<F77_INT> (rlwork);\n          lwork = std::max (lwork, static_cast<F77_INT> (1));\n          OCTAVE_LOCAL_BUFFER (float, work, lwork);\n          F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.rwdata (), m,\n                                     tau, work, lwork, info));\n        }\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::init (const FloatMatrix& a, type qr_type)\n{\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n\n  F77_INT min_mn = (m < n ? m : n);\n  OCTAVE_LOCAL_BUFFER (float, tau, min_mn);\n\n  F77_INT info = 0;\n\n  FloatMatrix afact = a;\n  if (m > n && qr_type == qr<FloatMatrix>::std)\n    afact.resize (m, m);\n\n  if (m > 0)\n    {\n      // workspace query.\n      float rlwork;\n      F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.rwdata (), m, tau,\n                                 &rlwork, -1, info));\n\n      // allocate buffer and do the job.\n      F77_INT lwork = static_cast<F77_INT> (rlwork);\n      lwork = std::max (lwork, static_cast<F77_INT> (1));\n      OCTAVE_LOCAL_BUFFER (float, work, lwork);\n      F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.rwdata (), m, tau,\n                                 work, lwork, info));\n    }\n\n  form (n, afact, tau, qr_type);\n}\n\n#if defined (HAVE_QRUPDATE)\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::update (const FloatColumnVector& u, const FloatColumnVector& v)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  std::vector<float> utmp (u.data (), u.data () + u.numel ());\n  std::vector<float> vtmp (v.data (), v.data () + v.numel ());\n  OCTAVE_LOCAL_BUFFER (float, w, 2*k);\n  F77_XFCN (sqr1up, SQR1UP, (m, n, k, m_q.rwdata (), m,\n                             m_r.rwdata (), k, utmp.data (),\n                             vtmp.data (), w));\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::update (const FloatMatrix& u, const FloatMatrix& v)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_rows = to_f77_int (u.rows ());\n  F77_INT u_cols = to_f77_int (u.cols ());\n\n  F77_INT v_rows = to_f77_int (v.rows ());\n  F77_INT v_cols = to_f77_int (v.cols ());\n\n  if (u_rows != m || v_rows != n || u_cols != v_cols)\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  OCTAVE_LOCAL_BUFFER (float, w, 2*k);\n  for (F77_INT i = 0; i < u_cols; i++)\n    {\n      std::vector<float> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      std::vector<float> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (sqr1up, SQR1UP, (m, n, k, m_q.rwdata (), m,\n                                 m_r.rwdata (), k, utmp.data (),\n                                 vtmp.data (), w));\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::insert_col (const FloatColumnVector& u,\n                             octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n\n  if (u_nel != m)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (k < m)\n    {\n      m_q.resize (m, k+1);\n      m_r.resize (k+1, n+1);\n    }\n  else\n    m_r.resize (k, n+1);\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  const std::vector<float> utmp (u.data (), u.data () + u.numel ());\n  OCTAVE_LOCAL_BUFFER (float, w, k);\n  F77_XFCN (sqrinc, SQRINC, (m, n, k, m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr, j + 1,\n                             utmp.data (), w));\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::insert_col (const FloatMatrix& u,\n                             const Array<octave_idx_type>& j)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);\n  F77_INT nj = to_f77_int (js.numel ());\n  bool dups = false;\n  for (F77_INT i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT u_cols = to_f77_int (u.cols ());\n\n  if (u_nel != m || u_cols != nj)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  F77_INT js_beg = to_f77_int (js(0));\n  F77_INT js_end = to_f77_int (js(nj-1));\n\n  if (nj > 0 && (js_beg < 0 || js_end > n))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      F77_INT kmax = std::min (k + nj, m);\n      if (k < m)\n        {\n          m_q.resize (m, kmax);\n          m_r.resize (kmax, n + nj);\n        }\n      else\n        m_r.resize (k, n + nj);\n\n      F77_INT ldq = to_f77_int (m_q.rows ());\n      F77_INT ldr = to_f77_int (m_r.rows ());\n\n      OCTAVE_LOCAL_BUFFER (float, w, kmax);\n      for (F77_INT i = 0; i < nj; i++)\n        {\n          F77_INT ii = i;\n          const std::vector<float> utmp (u.data () + jsi(i) * u.rows (), u.data () + (jsi(i) + 1) * u.rows ());\n          F77_INT js_elt = to_f77_int (js(ii));\n          F77_XFCN (sqrinc, SQRINC, (m, n + ii, std::min (kmax, k + ii),\n                                     m_q.rwdata (), ldq,\n                                     m_r.rwdata (), ldr, js_elt + 1,\n                                     utmp.data (), w));\n        }\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::delete_col (octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT k = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (float, w, k);\n  F77_XFCN (sqrdec, SQRDEC, (m, n, k, m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr, j + 1, w));\n\n  if (k < m)\n    {\n      m_q.resize (m, k-1);\n      m_r.resize (k-1, n-1);\n    }\n  else\n    m_r.resize (k, n-1);\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::delete_col (const Array<octave_idx_type>& j)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);\n  F77_INT nj = to_f77_int (js.numel ());\n  bool dups = false;\n  for (F77_INT i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  F77_INT js_beg = to_f77_int (js(0));\n  F77_INT js_end = to_f77_int (js(nj-1));\n\n  if (nj > 0 && (js_beg > n-1 || js_end < 0))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      F77_INT ldq = to_f77_int (m_q.rows ());\n      F77_INT ldr = to_f77_int (m_r.rows ());\n\n      OCTAVE_LOCAL_BUFFER (float, w, k);\n      for (F77_INT i = 0; i < nj; i++)\n        {\n          F77_INT ii = i;\n          F77_INT js_elt = to_f77_int (js(ii));\n          F77_XFCN (sqrdec, SQRDEC, (m, n - ii, (k == m ? k : k - ii),\n                                     m_q.rwdata (), ldq,\n                                     m_r.rwdata (), ldr,\n                                     js_elt + 1, w));\n        }\n\n      if (k < m)\n        {\n          m_q.resize (m, k - nj);\n          m_r.resize (k - nj, n - nj);\n        }\n      else\n        m_r.resize (k, n - nj);\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::insert_row (const FloatRowVector& u,\n                             octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = std::min (m, n);\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n\n  if (! m_q.issquare () || u_nel != n)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > m)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  m_q.resize (m + 1, m + 1);\n  m_r.resize (m + 1, n);\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  std::vector<float> utmp (u.data (), u.data () + u.numel ());\n  OCTAVE_LOCAL_BUFFER (float, w, k);\n  F77_XFCN (sqrinr, SQRINR, (m, n, m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr,\n                             j + 1, utmp.data (), w));\n\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::delete_row (octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (! m_q.issquare ())\n    (*current_liboctave_error_handler) (\"qrdelete: dimensions mismatch\");\n\n  if (j < 0 || j > m-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (float, w, 2*m);\n  F77_XFCN (sqrder, SQRDER, (m, n, m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr, j + 1,\n                             w));\n\n  m_q.resize (m - 1, m - 1);\n  m_r.resize (m - 1, n);\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatMatrix>::shift_cols (octave_idx_type i_arg, octave_idx_type j_arg)\n{\n  F77_INT i = to_f77_int (i_arg);\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT k = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrshift: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (float, w, 2*k);\n  F77_XFCN (sqrshc, SQRSHC, (m, n, k,\n                             m_q.rwdata (), ldq,\n                             m_r.rwdata (), ldr,\n                             i + 1, j + 1, w));\n}\n\n#endif\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::form (octave_idx_type n_arg, ComplexMatrix& afact,\n                         Complex *tau, type qr_type)\n{\n  F77_INT n = to_f77_int (n_arg);\n  F77_INT m = to_f77_int (afact.rows ());\n  F77_INT min_mn = std::min (m, n);\n  F77_INT info;\n\n  if (qr_type == qr<ComplexMatrix>::raw)\n    {\n      for (F77_INT j = 0; j < min_mn; j++)\n        {\n          F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1);\n          for (F77_INT i = limit + 1; i < m; i++)\n            afact.elem (i, j) *= tau[j];\n        }\n\n      m_r = afact;\n    }\n  else\n    {\n      // Attempt to minimize copying.\n      if (m >= n)\n        {\n          // afact will become m_q.\n          m_q = afact;\n          F77_INT k = (qr_type == qr<ComplexMatrix>::economy ? n : m);\n          m_r = ComplexMatrix (k, n);\n          for (F77_INT j = 0; j < n; j++)\n            {\n              F77_INT i = 0;\n              for (; i <= j; i++)\n                m_r.xelem (i, j) = afact.xelem (i, j);\n              for (; i < k; i++)\n                m_r.xelem (i, j) = 0;\n            }\n          afact = ComplexMatrix (); // optimize memory\n        }\n      else\n        {\n          // afact will become m_r.\n          m_q = ComplexMatrix (m, m);\n          for (F77_INT j = 0; j < m; j++)\n            for (F77_INT i = j + 1; i < m; i++)\n              {\n                m_q.xelem (i, j) = afact.xelem (i, j);\n                afact.xelem (i, j) = 0;\n              }\n          m_r = afact;\n        }\n\n      if (m > 0)\n        {\n          F77_INT k = to_f77_int (m_q.cols ());\n          // workspace query.\n          Complex clwork;\n          F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn,\n                                     F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                                     m, F77_DBLE_CMPLX_ARG (tau),\n                                     F77_DBLE_CMPLX_ARG (&clwork), -1,\n                                     info));\n\n          // allocate buffer and do the job.\n          F77_INT lwork = static_cast<F77_INT> (clwork.real ());\n          lwork = std::max (lwork, static_cast<F77_INT> (1));\n          OCTAVE_LOCAL_BUFFER (Complex, work, lwork);\n          F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn,\n                                     F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                                     m, F77_DBLE_CMPLX_ARG (tau),\n                                     F77_DBLE_CMPLX_ARG (work), lwork,\n                                     info));\n        }\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::init (const ComplexMatrix& a, type qr_type)\n{\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n\n  F77_INT min_mn = (m < n ? m : n);\n  OCTAVE_LOCAL_BUFFER (Complex, tau, min_mn);\n\n  F77_INT info = 0;\n\n  ComplexMatrix afact = a;\n  if (m > n && qr_type == qr<ComplexMatrix>::std)\n    afact.resize (m, m);\n\n  if (m > 0)\n    {\n      // workspace query.\n      Complex clwork;\n      F77_XFCN (zgeqrf, ZGEQRF, (m, n,\n                                 F77_DBLE_CMPLX_ARG (afact.rwdata ()),\n                                 m, F77_DBLE_CMPLX_ARG (tau),\n                                 F77_DBLE_CMPLX_ARG (&clwork), -1, info));\n\n      // allocate buffer and do the job.\n      F77_INT lwork = static_cast<F77_INT> (clwork.real ());\n      lwork = std::max (lwork, static_cast<F77_INT> (1));\n      OCTAVE_LOCAL_BUFFER (Complex, work, lwork);\n      F77_XFCN (zgeqrf, ZGEQRF, (m, n,\n                                 F77_DBLE_CMPLX_ARG (afact.rwdata ()),\n                                 m, F77_DBLE_CMPLX_ARG (tau),\n                                 F77_DBLE_CMPLX_ARG (work), lwork, info));\n    }\n\n  form (n, afact, tau, qr_type);\n}\n\n#if defined (HAVE_QRUPDATE)\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::update (const ComplexColumnVector& u,\n                           const ComplexColumnVector& v)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  std::vector<Complex> utmp (u.data (), u.data () + u.numel ());\n  std::vector<Complex> vtmp (v.data (), v.data () + v.numel ());\n  OCTAVE_LOCAL_BUFFER (Complex, w, k);\n  OCTAVE_LOCAL_BUFFER (double, rw, k);\n  F77_XFCN (zqr1up, ZQR1UP, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                             m, F77_DBLE_CMPLX_ARG (m_r.rwdata ()), k,\n                             F77_DBLE_CMPLX_ARG (utmp.data ()),\n                             F77_DBLE_CMPLX_ARG (vtmp.data ()),\n                             F77_DBLE_CMPLX_ARG (w), rw));\n}\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::update (const ComplexMatrix& u, const ComplexMatrix& v)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_rows = to_f77_int (u.rows ());\n  F77_INT u_cols = to_f77_int (u.cols ());\n\n  F77_INT v_rows = to_f77_int (v.rows ());\n  F77_INT v_cols = to_f77_int (v.cols ());\n\n  if (u_rows != m || v_rows != n || u_cols != v_cols)\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  OCTAVE_LOCAL_BUFFER (Complex, w, k);\n  OCTAVE_LOCAL_BUFFER (double, rw, k);\n  for (F77_INT i = 0; i < u_cols; i++)\n    {\n      std::vector<Complex> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      std::vector<Complex> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (zqr1up, ZQR1UP, (m, n, k,\n                                 F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                                 m, F77_DBLE_CMPLX_ARG (m_r.rwdata ()), k,\n                                 F77_DBLE_CMPLX_ARG (utmp.data ()),\n                                 F77_DBLE_CMPLX_ARG (vtmp.data ()),\n                                 F77_DBLE_CMPLX_ARG (w), rw));\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::insert_col (const ComplexColumnVector& u,\n                               octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n\n  if (u_nel != m)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (k < m)\n    {\n      m_q.resize (m, k+1);\n      m_r.resize (k+1, n+1);\n    }\n  else\n    m_r.resize (k, n+1);\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  const std::vector<Complex> utmp (u.data (), u.data () + u.numel ());\n  OCTAVE_LOCAL_BUFFER (double, rw, k);\n  F77_XFCN (zqrinc, ZQRINC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                             ldq, F77_DBLE_CMPLX_ARG (m_r.rwdata ()),\n                             ldr, j + 1,\n                             F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), rw));\n}\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::insert_col (const ComplexMatrix& u,\n                               const Array<octave_idx_type>& j)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);\n  F77_INT nj = to_f77_int (js.numel ());\n  bool dups = false;\n  for (F77_INT i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT u_cols = to_f77_int (u.cols ());\n\n  if (u_nel != m || u_cols != nj)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  F77_INT js_beg = to_f77_int (js(0));\n  F77_INT js_end = to_f77_int (js(nj-1));\n\n  if (nj > 0 && (js_beg < 0 || js_end > n))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      F77_INT kmax = std::min (k + nj, m);\n      if (k < m)\n        {\n          m_q.resize (m, kmax);\n          m_r.resize (kmax, n + nj);\n        }\n      else\n        m_r.resize (k, n + nj);\n\n      F77_INT ldq = to_f77_int (m_q.rows ());\n      F77_INT ldr = to_f77_int (m_r.rows ());\n\n      OCTAVE_LOCAL_BUFFER (double, rw, kmax);\n      for (F77_INT i = 0; i < nj; i++)\n        {\n          F77_INT ii = i;\n          const std::vector<Complex> utmp (u.data () + jsi(i) * u.rows (), u.data () + (jsi(i) + 1) * u.rows ());\n          F77_INT js_elt = to_f77_int (js(ii));\n          F77_XFCN (zqrinc, ZQRINC, (m, n + ii, std::min (kmax, k + ii),\n                                     F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                                     ldq,\n                                     F77_DBLE_CMPLX_ARG (m_r.rwdata ()),\n                                     ldr, js_elt + 1,\n                                     F77_CONST_DBLE_CMPLX_ARG (utmp.data ()),\n                                     rw));\n        }\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::delete_col (octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT k = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (double, rw, k);\n  F77_XFCN (zqrdec, ZQRDEC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                             ldq, F77_DBLE_CMPLX_ARG (m_r.rwdata ()),\n                             ldr, j + 1, rw));\n\n  if (k < m)\n    {\n      m_q.resize (m, k-1);\n      m_r.resize (k-1, n-1);\n    }\n  else\n    m_r.resize (k, n-1);\n}\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::delete_col (const Array<octave_idx_type>& j)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);\n  F77_INT nj = to_f77_int (js.numel ());\n  bool dups = false;\n  for (F77_INT i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  F77_INT js_beg = to_f77_int (js(0));\n  F77_INT js_end = to_f77_int (js(nj-1));\n\n  if (nj > 0 && (js_beg > n-1 || js_end < 0))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      F77_INT ldq = to_f77_int (m_q.rows ());\n      F77_INT ldr = to_f77_int (m_r.rows ());\n\n      OCTAVE_LOCAL_BUFFER (double, rw, k);\n      for (F77_INT i = 0; i < nj; i++)\n        {\n          F77_INT ii = i;\n          F77_INT js_elt = to_f77_int (js(ii));\n          F77_XFCN (zqrdec, ZQRDEC, (m, n - ii, (k == m ? k : k - ii),\n                                     F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                                     ldq,\n                                     F77_DBLE_CMPLX_ARG (m_r.rwdata ()),\n                                     ldr, js_elt + 1, rw));\n        }\n\n      if (k < m)\n        {\n          m_q.resize (m, k - nj);\n          m_r.resize (k - nj, n - nj);\n        }\n      else\n        m_r.resize (k, n - nj);\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::insert_row (const ComplexRowVector& u,\n                               octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = std::min (m, n);\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n\n  if (! m_q.issquare () || u_nel != n)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > m)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  m_q.resize (m + 1, m + 1);\n  m_r.resize (m + 1, n);\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  std::vector<Complex> utmp (u.data (), u.data () + u.numel ());\n  OCTAVE_LOCAL_BUFFER (double, rw, k);\n  F77_XFCN (zqrinr, ZQRINR, (m, n, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                             ldq, F77_DBLE_CMPLX_ARG (m_r.rwdata ()),\n                             ldr, j + 1,\n                             F77_DBLE_CMPLX_ARG (utmp.data ()), rw));\n\n}\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::delete_row (octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (! m_q.issquare ())\n    (*current_liboctave_error_handler) (\"qrdelete: dimensions mismatch\");\n\n  if (j < 0 || j > m-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (Complex, w, m);\n  OCTAVE_LOCAL_BUFFER (double, rw, m);\n  F77_XFCN (zqrder, ZQRDER, (m, n, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),\n                             ldq, F77_DBLE_CMPLX_ARG (m_r.rwdata ()),\n                             ldr, j + 1, F77_DBLE_CMPLX_ARG (w), rw));\n\n  m_q.resize (m - 1, m - 1);\n  m_r.resize (m - 1, n);\n}\n\ntemplate <>\nOCTAVE_API void\nqr<ComplexMatrix>::shift_cols (octave_idx_type i_arg,\n                               octave_idx_type j_arg)\n{\n  F77_INT i = to_f77_int (i_arg);\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT k = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrshift: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (Complex, w, k);\n  OCTAVE_LOCAL_BUFFER (double, rw, k);\n  F77_XFCN (zqrshc, ZQRSHC, (m, n, k,\n                             F77_DBLE_CMPLX_ARG (m_q.rwdata ()), ldq,\n                             F77_DBLE_CMPLX_ARG (m_r.rwdata ()), ldr,\n                             i + 1, j + 1, F77_DBLE_CMPLX_ARG (w), rw));\n}\n\n#endif\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::form (octave_idx_type n_arg, FloatComplexMatrix& afact,\n                              FloatComplex *tau, type qr_type)\n{\n  F77_INT n = to_f77_int (n_arg);\n  F77_INT m = to_f77_int (afact.rows ());\n  F77_INT min_mn = std::min (m, n);\n  F77_INT info;\n\n  if (qr_type == qr<FloatComplexMatrix>::raw)\n    {\n      for (F77_INT j = 0; j < min_mn; j++)\n        {\n          F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1);\n          for (F77_INT i = limit + 1; i < m; i++)\n            afact.elem (i, j) *= tau[j];\n        }\n\n      m_r = afact;\n    }\n  else\n    {\n      // Attempt to minimize copying.\n      if (m >= n)\n        {\n          // afact will become m_q.\n          m_q = afact;\n          F77_INT k = (qr_type == qr<FloatComplexMatrix>::economy ? n : m);\n          m_r = FloatComplexMatrix (k, n);\n          for (F77_INT j = 0; j < n; j++)\n            {\n              F77_INT i = 0;\n              for (; i <= j; i++)\n                m_r.xelem (i, j) = afact.xelem (i, j);\n              for (; i < k; i++)\n                m_r.xelem (i, j) = 0;\n            }\n          afact = FloatComplexMatrix (); // optimize memory\n        }\n      else\n        {\n          // afact will become m_r.\n          m_q = FloatComplexMatrix (m, m);\n          for (F77_INT j = 0; j < m; j++)\n            for (F77_INT i = j + 1; i < m; i++)\n              {\n                m_q.xelem (i, j) = afact.xelem (i, j);\n                afact.xelem (i, j) = 0;\n              }\n          m_r = afact;\n        }\n\n      if (m > 0)\n        {\n          F77_INT k = to_f77_int (m_q.cols ());\n          // workspace query.\n          FloatComplex clwork;\n          F77_XFCN (cungqr, CUNGQR, (m, k, min_mn,\n                                     F77_CMPLX_ARG (m_q.rwdata ()), m,\n                                     F77_CMPLX_ARG (tau),\n                                     F77_CMPLX_ARG (&clwork), -1, info));\n\n          // allocate buffer and do the job.\n          F77_INT lwork = static_cast<F77_INT> (clwork.real ());\n          lwork = std::max (lwork, static_cast<F77_INT> (1));\n          OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);\n          F77_XFCN (cungqr, CUNGQR, (m, k, min_mn,\n                                     F77_CMPLX_ARG (m_q.rwdata ()), m,\n                                     F77_CMPLX_ARG (tau),\n                                     F77_CMPLX_ARG (work), lwork, info));\n        }\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::init (const FloatComplexMatrix& a, type qr_type)\n{\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n\n  F77_INT min_mn = (m < n ? m : n);\n  OCTAVE_LOCAL_BUFFER (FloatComplex, tau, min_mn);\n\n  F77_INT info = 0;\n\n  FloatComplexMatrix afact = a;\n  if (m > n && qr_type == qr<FloatComplexMatrix>::std)\n    afact.resize (m, m);\n\n  if (m > 0)\n    {\n      // workspace query.\n      FloatComplex clwork;\n      F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.rwdata ()),\n                                 m, F77_CMPLX_ARG (tau),\n                                 F77_CMPLX_ARG (&clwork), -1, info));\n\n      // allocate buffer and do the job.\n      F77_INT lwork = static_cast<F77_INT> (clwork.real ());\n      lwork = std::max (lwork, static_cast<F77_INT> (1));\n      OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);\n      F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.rwdata ()),\n                                 m, F77_CMPLX_ARG (tau),\n                                 F77_CMPLX_ARG (work), lwork, info));\n    }\n\n  form (n, afact, tau, qr_type);\n}\n\n#if defined (HAVE_QRUPDATE)\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::update (const FloatComplexColumnVector& u,\n                                const FloatComplexColumnVector& v)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT v_nel = to_f77_int (v.numel ());\n\n  if (u_nel != m || v_nel != n)\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  std::vector<FloatComplex> utmp (u.data (), u.data () + u.numel ());\n  std::vector<FloatComplex> vtmp (v.data (), v.data () + v.numel ());\n  OCTAVE_LOCAL_BUFFER (FloatComplex, w, k);\n  OCTAVE_LOCAL_BUFFER (float, rw, k);\n  F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (m_q.rwdata ()),\n                             m, F77_CMPLX_ARG (m_r.rwdata ()), k,\n                             F77_CMPLX_ARG (utmp.data ()),\n                             F77_CMPLX_ARG (vtmp.data ()),\n                             F77_CMPLX_ARG (w), rw));\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::update (const FloatComplexMatrix& u,\n                                const FloatComplexMatrix& v)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_rows = to_f77_int (u.rows ());\n  F77_INT u_cols = to_f77_int (u.cols ());\n\n  F77_INT v_rows = to_f77_int (v.rows ());\n  F77_INT v_cols = to_f77_int (v.cols ());\n\n  if (u_rows != m || v_rows != n || u_cols != v_cols)\n    (*current_liboctave_error_handler) (\"qrupdate: dimensions mismatch\");\n\n  OCTAVE_LOCAL_BUFFER (FloatComplex, w, k);\n  OCTAVE_LOCAL_BUFFER (float, rw, k);\n  for (F77_INT i = 0; i < u_cols; i++)\n    {\n      std::vector<FloatComplex> utmp (u.data () + i * u.rows (), u.data () + (i + 1) * u.rows ());\n      std::vector<FloatComplex> vtmp (v.data () + i * v.rows (), v.data () + (i + 1) * v.rows ());\n      F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (m_q.rwdata ()),\n                                 m, F77_CMPLX_ARG (m_r.rwdata ()), k,\n                                 F77_CMPLX_ARG (utmp.data ()),\n                                 F77_CMPLX_ARG (vtmp.data ()),\n                                 F77_CMPLX_ARG (w), rw));\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::insert_col (const FloatComplexColumnVector& u,\n                                    octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n\n  if (u_nel != m)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > n)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (k < m)\n    {\n      m_q.resize (m, k+1);\n      m_r.resize (k+1, n+1);\n    }\n  else\n    m_r.resize (k, n+1);\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  const std::vector<FloatComplex> utmp (u.data (), u.data () + u.numel ());\n  OCTAVE_LOCAL_BUFFER (float, rw, k);\n  F77_XFCN (cqrinc, CQRINC, (m, n, k, F77_CMPLX_ARG (m_q.rwdata ()), ldq,\n                             F77_CMPLX_ARG (m_r.rwdata ()), ldr, j + 1,\n                             F77_CONST_CMPLX_ARG (utmp.data ()), rw));\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::insert_col (const FloatComplexMatrix& u,\n                                    const Array<octave_idx_type>& j)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);\n  F77_INT nj = to_f77_int (js.numel ());\n  bool dups = false;\n  for (F77_INT i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n  F77_INT u_cols = to_f77_int (u.cols ());\n\n  if (u_nel != m || u_cols != nj)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  F77_INT js_beg = to_f77_int (js(0));\n  F77_INT js_end = to_f77_int (js(nj-1));\n\n  if (nj > 0 && (js_beg < 0 || js_end > n))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      F77_INT kmax = std::min (k + nj, m);\n      if (k < m)\n        {\n          m_q.resize (m, kmax);\n          m_r.resize (kmax, n + nj);\n        }\n      else\n        m_r.resize (k, n + nj);\n\n      F77_INT ldq = to_f77_int (m_q.rows ());\n      F77_INT ldr = to_f77_int (m_r.rows ());\n\n      OCTAVE_LOCAL_BUFFER (float, rw, kmax);\n      for (F77_INT i = 0; i < nj; i++)\n        {\n          F77_INT ii = i;\n          const std::vector<FloatComplex> utmp (u.data () + jsi(i) * u.rows (), u.data () + (jsi(i) + 1) * u.rows ());\n          F77_INT js_elt = to_f77_int (js(ii));\n          F77_XFCN (cqrinc, CQRINC, (m, n + ii, std::min (kmax, k + ii),\n                                     F77_CMPLX_ARG (m_q.rwdata ()), ldq,\n                                     F77_CMPLX_ARG (m_r.rwdata ()), ldr,\n                                     js_elt + 1,\n                                     F77_CONST_CMPLX_ARG (utmp.data ()),\n                                     rw));\n        }\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::delete_col (octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT k = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (float, rw, k);\n  F77_XFCN (cqrdec, CQRDEC, (m, n, k, F77_CMPLX_ARG (m_q.rwdata ()), ldq,\n                             F77_CMPLX_ARG (m_r.rwdata ()), ldr, j + 1,\n                             rw));\n\n  if (k < m)\n    {\n      m_q.resize (m, k-1);\n      m_r.resize (k-1, n-1);\n    }\n  else\n    m_r.resize (k, n-1);\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::delete_col (const Array<octave_idx_type>& j)\n{\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = to_f77_int (m_q.cols ());\n\n  Array<octave_idx_type> jsi;\n  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);\n  F77_INT nj = to_f77_int (js.numel ());\n  bool dups = false;\n  for (F77_INT i = 0; i < nj - 1; i++)\n    dups = dups && js(i) == js(i+1);\n\n  if (dups)\n    (*current_liboctave_error_handler) (\"qrinsert: duplicate index detected\");\n\n  F77_INT js_beg = to_f77_int (js(0));\n  F77_INT js_end = to_f77_int (js(nj-1));\n\n  if (nj > 0 && (js_beg > n-1 || js_end < 0))\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  if (nj > 0)\n    {\n      F77_INT ldq = to_f77_int (m_q.rows ());\n      F77_INT ldr = to_f77_int (m_r.rows ());\n\n      OCTAVE_LOCAL_BUFFER (float, rw, k);\n      for (F77_INT i = 0; i < nj; i++)\n        {\n          F77_INT ii = i;\n          F77_INT js_elt = to_f77_int (js(ii));\n          F77_XFCN (cqrdec, CQRDEC, (m, n - ii, (k == m ? k : k - ii),\n                                     F77_CMPLX_ARG (m_q.rwdata ()), ldq,\n                                     F77_CMPLX_ARG (m_r.rwdata ()), ldr,\n                                     js_elt + 1, rw));\n        }\n\n      if (k < m)\n        {\n          m_q.resize (m, k - nj);\n          m_r.resize (k - nj, n - nj);\n        }\n      else\n        m_r.resize (k, n - nj);\n    }\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::insert_row (const FloatComplexRowVector& u,\n                                    octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n  F77_INT k = std::min (m, n);\n\n  F77_INT u_nel = to_f77_int (u.numel ());\n\n  if (! m_q.issquare () || u_nel != n)\n    (*current_liboctave_error_handler) (\"qrinsert: dimensions mismatch\");\n\n  if (j < 0 || j > m)\n    (*current_liboctave_error_handler) (\"qrinsert: index out of range\");\n\n  m_q.resize (m + 1, m + 1);\n  m_r.resize (m + 1, n);\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  std::vector<FloatComplex> utmp (u.data (), u.data () + u.numel ());\n  OCTAVE_LOCAL_BUFFER (float, rw, k);\n  F77_XFCN (cqrinr, CQRINR, (m, n, F77_CMPLX_ARG (m_q.rwdata ()), ldq,\n                             F77_CMPLX_ARG (m_r.rwdata ()), ldr,\n                             j + 1, F77_CMPLX_ARG (utmp.data ()),\n                             rw));\n\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::delete_row (octave_idx_type j_arg)\n{\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (! m_q.issquare ())\n    (*current_liboctave_error_handler) (\"qrdelete: dimensions mismatch\");\n\n  if (j < 0 || j > m-1)\n    (*current_liboctave_error_handler) (\"qrdelete: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (FloatComplex, w, m);\n  OCTAVE_LOCAL_BUFFER (float, rw, m);\n  F77_XFCN (cqrder, CQRDER, (m, n, F77_CMPLX_ARG (m_q.rwdata ()), ldq,\n                             F77_CMPLX_ARG (m_r.rwdata ()), ldr, j + 1,\n                             F77_CMPLX_ARG (w), rw));\n\n  m_q.resize (m - 1, m - 1);\n  m_r.resize (m - 1, n);\n}\n\ntemplate <>\nOCTAVE_API void\nqr<FloatComplexMatrix>::shift_cols (octave_idx_type i_arg,\n                                    octave_idx_type j_arg)\n{\n  F77_INT i = to_f77_int (i_arg);\n  F77_INT j = to_f77_int (j_arg);\n\n  F77_INT m = to_f77_int (m_q.rows ());\n  F77_INT k = to_f77_int (m_r.rows ());\n  F77_INT n = to_f77_int (m_r.cols ());\n\n  if (i < 0 || i > n-1 || j < 0 || j > n-1)\n    (*current_liboctave_error_handler) (\"qrshift: index out of range\");\n\n  F77_INT ldq = to_f77_int (m_q.rows ());\n  F77_INT ldr = to_f77_int (m_r.rows ());\n\n  OCTAVE_LOCAL_BUFFER (FloatComplex, w, k);\n  OCTAVE_LOCAL_BUFFER (float, rw, k);\n  F77_XFCN (cqrshc, CQRSHC, (m, n, k,\n                             F77_CMPLX_ARG (m_q.rwdata ()), ldq,\n                             F77_CMPLX_ARG (m_r.rwdata ()), ldr,\n                             i + 1, j + 1, F77_CMPLX_ARG (w), rw));\n}\n\n#endif\n\n// Instantiations we need.\n\ntemplate class qr<Matrix>;\n\ntemplate class qr<FloatMatrix>;\n\ntemplate class qr<ComplexMatrix>;\n\ntemplate class qr<FloatComplexMatrix>;\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/qr.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_qr_h)\n#define octave_qr_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-fwd.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nclass qr\n{\npublic:\n\n  typedef typename T::element_type ELT_T;\n  typedef typename T::row_vector_type RV_T;\n  typedef typename T::column_vector_type CV_T;\n\n  enum type\n  {\n    std,\n    raw,\n    economy\n  };\n\n  qr () : m_q (), m_r () { }\n\n  qr (const T& a, type qr_type = qr::std)\n    : m_q (), m_r ()\n  {\n    init (a, qr_type);\n  }\n\n  OCTAVE_API qr (const T& m_q, const T& m_r);\n\n  qr (const qr& a) : m_q (a.m_q), m_r (a.m_r) { }\n\n  qr& operator = (const qr& a)\n  {\n    if (this != &a)\n      {\n        m_q = a.m_q;\n        m_r = a.m_r;\n      }\n\n    return *this;\n  }\n\n  virtual ~qr () = default;\n\n  T Q () const { return m_q; }\n\n  T R () const { return m_r; }\n\n  OCTAVE_API type get_type () const;\n\n  OCTAVE_API bool regular () const;\n\n  OCTAVE_API void init (const T& a, type qr_type);\n\n  OCTAVE_API void update (const CV_T& u, const CV_T& v);\n\n  OCTAVE_API void update (const T& u, const T& v);\n\n  OCTAVE_API void insert_col (const CV_T& u, octave_idx_type j);\n\n  OCTAVE_API void insert_col (const T& u, const Array<octave_idx_type>& j);\n\n  OCTAVE_API void delete_col (octave_idx_type j);\n\n  OCTAVE_API void delete_col (const Array<octave_idx_type>& j);\n\n  OCTAVE_API void insert_row (const RV_T& u, octave_idx_type j);\n\n  OCTAVE_API void delete_row (octave_idx_type j);\n\n  OCTAVE_API void shift_cols (octave_idx_type i, octave_idx_type j);\n\nprotected:\n\n  T m_q;\n  T m_r;\n\n  OCTAVE_API void\n  form (octave_idx_type n, T& afact, ELT_T *tau, type qr_type);\n};\n\nextern OCTAVE_API void warn_qrupdate_once ();\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/qrp.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n\n#include \"Array-oct.h\"\n#include \"CMatrix.h\"\n#include \"MArray.h\"\n#include \"dMatrix.h\"\n#include \"dRowVector.h\"\n#include \"fCMatrix.h\"\n#include \"fMatrix.h\"\n#include \"fRowVector.h\"\n#include \"lapack-proto.h\"\n#include \"oct-locbuf.h\"\n#include \"qrp.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\n// Specialization.\n\ntemplate <>\nOCTAVE_API\nvoid\nqrp<Matrix>::init (const Matrix& a, type qr_type)\n{\n  liboctave_panic_if (qr_type == qr<Matrix>::raw);\n\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n\n  F77_INT min_mn = (m < n ? m : n);\n  OCTAVE_LOCAL_BUFFER (double, tau, min_mn);\n\n  F77_INT info = 0;\n\n  Matrix afact = a;\n  if (m > n && qr_type == qr<Matrix>::std)\n    afact.resize (m, m);\n\n  MArray<F77_INT> jpvt (dim_vector (n, 1), 0);\n\n  if (m > 0)\n    {\n      // workspace query.\n      double rlwork;\n      F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.rwdata (),\n                                 m, jpvt.rwdata (), tau,\n                                 &rlwork, -1, info));\n\n      // allocate buffer and do the job.\n      F77_INT lwork = static_cast<F77_INT> (rlwork);\n      lwork = std::max (lwork, static_cast<F77_INT> (1));\n      OCTAVE_LOCAL_BUFFER (double, work, lwork);\n\n      F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.rwdata (),\n                                 m, jpvt.rwdata (), tau,\n                                 work, lwork, info));\n    }\n  else\n    {\n      for (F77_INT i = 0; i < n; i++)\n        jpvt(i) = i+1;\n    }\n\n  // Form Permutation matrix (if economy is requested, return the\n  // indices only!)\n\n  jpvt -= static_cast<F77_INT> (1);\n  m_p = PermMatrix (jpvt, true);\n\n  form (n, afact, tau, qr_type);\n}\n\ntemplate <>\nOCTAVE_API\nqrp<Matrix>::qrp (const Matrix& a, type qr_type)\n  : qr<Matrix> (), m_p ()\n{\n  init (a, qr_type);\n}\n\ntemplate <>\nOCTAVE_API\nRowVector\nqrp<Matrix>::Pvec () const\n{\n  Array<double> pa (m_p.col_perm_vec ());\n  RowVector pv (MArray<double> (pa) + 1.0);\n  return pv;\n}\n\ntemplate <>\nOCTAVE_API\nvoid\nqrp<FloatMatrix>::init (const FloatMatrix& a, type qr_type)\n{\n  liboctave_panic_if (qr_type == qr<FloatMatrix>::raw);\n\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n\n  F77_INT min_mn = (m < n ? m : n);\n  OCTAVE_LOCAL_BUFFER (float, tau, min_mn);\n\n  F77_INT info = 0;\n\n  FloatMatrix afact = a;\n  if (m > n && qr_type == qr<FloatMatrix>::std)\n    afact.resize (m, m);\n\n  MArray<F77_INT> jpvt (dim_vector (n, 1), 0);\n\n  if (m > 0)\n    {\n      // workspace query.\n      float rlwork;\n      F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.rwdata (),\n                                 m, jpvt.rwdata (), tau,\n                                 &rlwork, -1, info));\n\n      // allocate buffer and do the job.\n      F77_INT lwork = static_cast<F77_INT> (rlwork);\n      lwork = std::max (lwork, static_cast<F77_INT> (1));\n      OCTAVE_LOCAL_BUFFER (float, work, lwork);\n\n      F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.rwdata (),\n                                 m, jpvt.rwdata (), tau,\n                                 work, lwork, info));\n    }\n  else\n    {\n      for (F77_INT i = 0; i < n; i++)\n        jpvt(i) = i+1;\n    }\n\n  // Form Permutation matrix (if economy is requested, return the\n  // indices only!)\n\n  jpvt -= static_cast<F77_INT> (1);\n  m_p = PermMatrix (jpvt, true);\n\n  form (n, afact, tau, qr_type);\n}\n\ntemplate <>\nOCTAVE_API\nqrp<FloatMatrix>::qrp (const FloatMatrix& a, type qr_type)\n  : qr<FloatMatrix> (), m_p ()\n{\n  init (a, qr_type);\n}\n\ntemplate <>\nOCTAVE_API\nFloatRowVector\nqrp<FloatMatrix>::Pvec () const\n{\n  Array<float> pa (m_p.col_perm_vec ());\n  FloatRowVector pv (MArray<float> (pa) + 1.0f);\n  return pv;\n}\n\ntemplate <>\nOCTAVE_API\nvoid\nqrp<ComplexMatrix>::init (const ComplexMatrix& a, type qr_type)\n{\n  liboctave_panic_if (qr_type == qr<ComplexMatrix>::raw);\n\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n\n  F77_INT min_mn = (m < n ? m : n);\n  OCTAVE_LOCAL_BUFFER (Complex, tau, min_mn);\n\n  F77_INT info = 0;\n\n  ComplexMatrix afact = a;\n  if (m > n && qr_type == qr<ComplexMatrix>::std)\n    afact.resize (m, m);\n\n  MArray<F77_INT> jpvt (dim_vector (n, 1), 0);\n\n  if (m > 0)\n    {\n      OCTAVE_LOCAL_BUFFER (double, rwork, 2*n);\n\n      // workspace query.\n      Complex clwork;\n      F77_XFCN (zgeqp3, ZGEQP3, (m, n,\n                                 F77_DBLE_CMPLX_ARG (afact.rwdata ()),\n                                 m, jpvt.rwdata (),\n                                 F77_DBLE_CMPLX_ARG (tau),\n                                 F77_DBLE_CMPLX_ARG (&clwork),\n                                 -1, rwork, info));\n\n      // allocate buffer and do the job.\n      F77_INT lwork = static_cast<F77_INT> (clwork.real ());\n      lwork = std::max (lwork, static_cast<F77_INT> (1));\n      OCTAVE_LOCAL_BUFFER (Complex, work, lwork);\n\n      F77_XFCN (zgeqp3, ZGEQP3, (m, n,\n                                 F77_DBLE_CMPLX_ARG (afact.rwdata ()),\n                                 m, jpvt.rwdata (),\n                                 F77_DBLE_CMPLX_ARG (tau),\n                                 F77_DBLE_CMPLX_ARG (work),\n                                 lwork, rwork, info));\n    }\n  else\n    {\n      for (F77_INT i = 0; i < n; i++)\n        jpvt(i) = i+1;\n    }\n\n  // Form Permutation matrix (if economy is requested, return the\n  // indices only!)\n\n  jpvt -= static_cast<F77_INT> (1);\n  m_p = PermMatrix (jpvt, true);\n\n  form (n, afact, tau, qr_type);\n}\n\ntemplate <>\nOCTAVE_API\nqrp<ComplexMatrix>::qrp (const ComplexMatrix& a, type qr_type)\n  : qr<ComplexMatrix> (), m_p ()\n{\n  init (a, qr_type);\n}\n\ntemplate <>\nOCTAVE_API\nRowVector\nqrp<ComplexMatrix>::Pvec () const\n{\n  Array<double> pa (m_p.col_perm_vec ());\n  RowVector pv (MArray<double> (pa) + 1.0);\n  return pv;\n}\n\ntemplate <>\nOCTAVE_API\nvoid\nqrp<FloatComplexMatrix>::init (const FloatComplexMatrix& a, type qr_type)\n{\n  liboctave_panic_if (qr_type == qr<FloatComplexMatrix>::raw);\n\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n\n  F77_INT min_mn = (m < n ? m : n);\n  OCTAVE_LOCAL_BUFFER (FloatComplex, tau, min_mn);\n\n  F77_INT info = 0;\n\n  FloatComplexMatrix afact = a;\n  if (m > n && qr_type == qr<FloatComplexMatrix>::std)\n    afact.resize (m, m);\n\n  MArray<F77_INT> jpvt (dim_vector (n, 1), 0);\n\n  if (m > 0)\n    {\n      OCTAVE_LOCAL_BUFFER (float, rwork, 2*n);\n\n      // workspace query.\n      FloatComplex clwork;\n      F77_XFCN (cgeqp3, CGEQP3, (m, n,\n                                 F77_CMPLX_ARG (afact.rwdata ()),\n                                 m, jpvt.rwdata (),\n                                 F77_CMPLX_ARG (tau),\n                                 F77_CMPLX_ARG (&clwork),\n                                 -1, rwork, info));\n\n      // allocate buffer and do the job.\n      F77_INT lwork = static_cast<F77_INT> (clwork.real ());\n      lwork = std::max (lwork, static_cast<F77_INT> (1));\n      OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);\n\n      F77_XFCN (cgeqp3, CGEQP3, (m, n,\n                                 F77_CMPLX_ARG (afact.rwdata ()),\n                                 m, jpvt.rwdata (),\n                                 F77_CMPLX_ARG (tau),\n                                 F77_CMPLX_ARG (work),\n                                 lwork, rwork, info));\n    }\n  else\n    {\n      for (F77_INT i = 0; i < n; i++)\n        jpvt(i) = i+1;\n    }\n\n  // Form Permutation matrix (if economy is requested, return the\n  // indices only!)\n\n  jpvt -= static_cast<F77_INT> (1);\n  m_p = PermMatrix (jpvt, true);\n\n  form (n, afact, tau, qr_type);\n}\n\ntemplate <>\nOCTAVE_API\nqrp<FloatComplexMatrix>::qrp (const FloatComplexMatrix& a, type qr_type)\n  : qr<FloatComplexMatrix> (), m_p ()\n{\n  init (a, qr_type);\n}\n\ntemplate <>\nOCTAVE_API\nFloatRowVector\nqrp<FloatComplexMatrix>::Pvec () const\n{\n  Array<float> pa (m_p.col_perm_vec ());\n  FloatRowVector pv (MArray<float> (pa) + 1.0f);\n  return pv;\n}\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/qrp.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_qrp_h)\n#define octave_qrp_h 1\n\n#include \"octave-config.h\"\n\n#include \"PermMatrix.h\"\n#include \"qr.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nclass qrp : public qr<T>\n{\npublic:\n\n  typedef typename T::real_row_vector_type RV_T;\n\n  typedef typename qr<T>::type type;\n\n  qrp () : qr<T> (), m_p () { }\n\n  OCTAVE_API qrp (const T&, type = qr<T>::std);\n\n  qrp (const qrp& a) : qr<T> (a), m_p (a.m_p) { }\n\n  qrp& operator = (const qrp& a)\n  {\n    if (this != &a)\n      {\n        qr<T>::operator = (a);\n        m_p = a.m_p;\n      }\n\n    return *this;\n  }\n\n  ~qrp () = default;\n\n  OCTAVE_API void init (const T&, type = qr<T>::std);\n\n  PermMatrix P () const { return m_p; }\n\n  OCTAVE_API RV_T Pvec () const;\n\nprivate:\n\n  PermMatrix m_p;\n};\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/qrupdate-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_qrupdate_proto_h)\n#define octave_qrupdate_proto_h 1\n\n#include \"octave-config.h\"\n\n#include \"f77-fcn.h\"\n\nextern \"C\"\n{\n\n#if defined (HAVE_QRUPDATE)\n\n  // CH1DN\n\n  F77_RET_T\n  F77_FUNC (cch1dn, CCH1DN) (const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             F77_REAL *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dch1dn, DCH1DN) (const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             F77_DBLE *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (sch1dn, SCH1DN) (const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             F77_REAL *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zch1dn, ZCH1DN) (const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             F77_DBLE *, F77_INT&);\n\n  // CH1UP\n\n  F77_RET_T\n  F77_FUNC (cch1up, CCH1UP) (const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (dch1up, DCH1UP) (const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (sch1up, SCH1UP) (const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zch1up, ZCH1UP) (const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *, F77_DBLE *);\n\n  // CHDEX\n\n  F77_RET_T\n  F77_FUNC (dchdex, DCHDEX) (const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (schdex, SCHDEX) (const F77_INT&, F77_REAL *,\n                             const F77_INT&, const F77_INT&,\n                             F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (cchdex, CCHDEX) (const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zchdex, ZCHDEX) (const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *);\n\n  // CHINX\n\n  F77_RET_T\n  F77_FUNC (cchinx, CCHINX) (const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, F77_REAL *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dchinx, DCHINX) (const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *, F77_DBLE *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (schinx, SCHINX) (const F77_INT&, F77_REAL *,\n                             const F77_INT&, const F77_INT&,\n                             F77_REAL *, F77_REAL *, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (zchinx, ZCHINX) (const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, F77_DBLE *, F77_INT&);\n\n  // CHSHX\n\n  F77_RET_T\n  F77_FUNC (cchshx, CCHSHX) (const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (dchshx, DCHSHX) (const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (schshx, SCHSHX) (const F77_INT&, F77_REAL *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zchshx, ZCHSHX) (const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *, F77_DBLE *);\n\n  // QR1UP\n\n  F77_RET_T\n  F77_FUNC (cqr1up, CQR1UP) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             F77_CMPLX *, F77_CMPLX *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (dqr1up, DQR1UP) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *, F77_DBLE *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (sqr1up, SQR1UP) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *, F77_REAL *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zqr1up, ZQR1UP) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             F77_DBLE_CMPLX *, F77_DBLE_CMPLX *, F77_DBLE *);\n\n  // QRDEC\n\n  F77_RET_T\n  F77_FUNC (cqrdec, CQRDEC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (dqrdec, DQRDEC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (sqrdec, SQRDEC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, const F77_INT&,\n                             F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zqrdec, ZQRDEC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE *);\n\n  // QRDER\n\n  F77_RET_T\n  F77_FUNC (cqrder, CQRDER) (const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (dqrder, DQRDER) (const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             const F77_INT&, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (sqrder, SQRDER) (const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             const F77_INT&, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zqrder, ZQRDER) (const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *, F77_DBLE *);\n\n  // QRINC\n\n  F77_RET_T\n  F77_FUNC (cqrinc, CQRINC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_CMPLX *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (dqrinc, DQRINC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (sqrinc, SQRINC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_REAL *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zqrinc, ZQRINC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_DBLE_CMPLX *, F77_DBLE *);\n\n  // QRINR\n\n  F77_RET_T\n  F77_FUNC (cqrinr, CQRINR) (const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             const F77_INT&, const F77_CMPLX *,\n                             F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (dqrinr, DQRINR) (const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             const F77_INT&, const F77_DBLE *,\n                             F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (sqrinr, SQRINR) (const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             const F77_INT&, const F77_REAL *,\n                             F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zqrinr, ZQRINR) (const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             const F77_INT&, const F77_DBLE_CMPLX *,\n                             F77_DBLE *);\n\n  // QRSHC\n\n  F77_RET_T\n  F77_FUNC (cqrshc, CQRSHC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, F77_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&,\n                             F77_CMPLX *, F77_REAL *);\n  F77_RET_T\n  F77_FUNC (dqrshc, DQRSHC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, F77_DBLE *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&,\n                             F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (sqrshc, SQRSHC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, F77_REAL *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&,\n                             F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zqrshc, ZQRSHC) (const F77_INT&, const F77_INT&,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, F77_DBLE_CMPLX *,\n                             const F77_INT&, const F77_INT&,\n                             const F77_INT&,\n                             F77_DBLE_CMPLX *, F77_DBLE *);\n\n#endif\n\n#if defined (HAVE_QRUPDATE_LUU)\n\n  // LU1UP\n\n  F77_RET_T\n  F77_FUNC (clu1up, CLU1UP) (const F77_INT&, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, const F77_INT&,\n                             F77_CMPLX *, F77_CMPLX *);\n\n  F77_RET_T\n  F77_FUNC (dlu1up, DLU1UP) (const F77_INT&, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, const F77_INT&,\n                             F77_DBLE *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (slu1up, SLU1UP) (const F77_INT&, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, const F77_INT&,\n                             F77_REAL *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zlu1up, ZLU1UP) (const F77_INT&, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, const F77_INT&,\n                             F77_DBLE_CMPLX *, F77_DBLE_CMPLX *);\n\n  // LUP1UP\n\n  F77_RET_T\n  F77_FUNC (clup1up, CLUP1UP) (const F77_INT&, const F77_INT&,\n                               F77_CMPLX *, const F77_INT&,\n                               F77_CMPLX *, const F77_INT&,\n                               F77_INT *, const F77_CMPLX *,\n                               const F77_CMPLX *, F77_CMPLX *);\n  F77_RET_T\n  F77_FUNC (dlup1up, DLUP1UP) (const F77_INT&, const F77_INT&,\n                               F77_DBLE *, const F77_INT&,\n                               F77_DBLE *, const F77_INT&,\n                               F77_INT *, const F77_DBLE *,\n                               const F77_DBLE *, F77_DBLE *);\n\n  F77_RET_T\n  F77_FUNC (slup1up, SLUP1UP) (const F77_INT&, const F77_INT&,\n                               F77_REAL *, const F77_INT&,\n                               F77_REAL *, const F77_INT&,\n                               F77_INT *, const F77_REAL *,\n                               const F77_REAL *, F77_REAL *);\n\n  F77_RET_T\n  F77_FUNC (zlup1up, ZLUP1UP) (const F77_INT&, const F77_INT&,\n                               F77_DBLE_CMPLX *, const F77_INT&,\n                               F77_DBLE_CMPLX *, const F77_INT&,\n                               F77_INT *, const F77_DBLE_CMPLX *,\n                               const F77_DBLE_CMPLX *, F77_DBLE_CMPLX *);\n\n#endif\n\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/randgamma.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/* Original version written by Paul Kienzle distributed as free\n   software in the in the public domain.  */\n\n/*\n\ndouble randg (a)\nvoid fill_randg (a,n,x)\n\nGenerate a series of standard gamma distributions.\n\nSee: G. Marsaglia and W. Tsang, \"A simple method for generating gamma\nvariables\", ACM Transactions on Mathematical Software, 26(3), pp. 363-372,\n2000.\n\nNeeds the following defines:\n* NAN: value to return for Not-A-Number\n* RUNI: uniform generator on (0,1)\n* RNOR: normal generator\n* REXP: exponential generator, or -log(RUNI) if one isn't available\n* INFINITE: function to test whether a value is infinite\n\nTest using:\n  mean = a\n  variance = a\n  skewness = 2/sqrt(a)\n  kurtosis = 3 + 6/sqrt(a)\n\nNote that randg can be used to generate many distributions:\n\ngamma(a,b) for a>0, b>0 (from R)\n  r = b*randg(a)\nbeta(a,b) for a>0, b>0\n  r1 = randg(a,1)\n  r = r1 / (r1 + randg(b,1))\nErlang(a,n)\n  r = a*randg(n)\nchisq(df) for df>0\n  r = 2*randg(df/2)\nt(df) for 0<df<inf (use randn if df is infinite)\n  r = randn () / sqrt(2*randg(df/2)/df)\nF(n1,n2) for 0<n1, 0<n2\n  r1 = 2*randg(n1/2)/n1 or 1 if n1 is infinite\n  r2 = 2*randg(n2/2)/n2 or 1 if n2 is infinite\n  r = r1 / r2\nnegative binonial (n, p) for n>0, 0<p<=1\n  r = randp((1-p)/p * randg(n))\n  (from R, citing Devroye(1986), Non-Uniform Random Variate Generation)\nnon-central chisq(df,L), for df>=0 and L>0 (use chisq if L=0)\n  r = randp(L/2)\n  r(r>0) = 2*randg(r(r>0))\n  r(df>0) += 2*randg(df(df>0)/2)\n  (from R, citing formula 29.5b-c in Johnson, Kotz, Balkrishnan(1995))\nDirichlet(a1,...,ak) for ai > 0\n  r = (randg(a1),...,randg(ak))\n  r = r / sum(r)\n  (from GSL, citing Law & Kelton(1991), Simulation Modeling and Analysis)\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"randgamma.h\"\n#include \"randmtzig.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T> void rand_gamma (T a, octave_idx_type n, T *r)\n{\n  octave_idx_type i;\n  /* If a < 1, start by generating gamma (1+a) */\n  const T d = (a < 1. ? 1.+a : a) - 1./3.;\n  const T c = 1./std::sqrt (9.*d);\n\n  /* Handle invalid cases */\n  if (a <= 0 || math::isinf (a))\n    {\n      for (i=0; i < n; i++)\n        r[i] = numeric_limits<T>::NaN ();\n      return;\n    }\n\n  for (i=0; i < n; i++)\n    {\n      T x, xsq, v, u;\n    restart:\n      x = rand_normal<T> ();\n      v = (1+c*x);\n      v *= (v*v);\n      if (v <= 0)\n        goto restart; /* rare, so don't bother moving up */\n      u = rand_uniform<T> ();\n      xsq = x*x;\n      if (u >= 1.-0.0331*xsq*xsq && std::log (u) >= 0.5*xsq + d*(1-v+std::log (v)))\n        goto restart;\n      r[i] = d*v;\n    }\n  if (a < 1)\n    {\n      /* Use gamma(a) = gamma(1+a)*U^(1/a) */\n      /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */\n      for (i = 0; i < n; i++)\n        r[i] *= exp (-rand_exponential<T> () / a);\n    }\n}\n\ntemplate OCTAVE_API void rand_gamma (double, octave_idx_type, double *);\ntemplate OCTAVE_API void rand_gamma (float, octave_idx_type, float *);\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/randgamma.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/* Original version written by Paul Kienzle distributed as free\n   software in the in the public domain.  */\n\n#if ! defined (octave_randgamma_h)\n#define octave_randgamma_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T>\nOCTAVE_API void\nrand_gamma (T a, octave_idx_type n, T *p);\n\ntemplate <typename T>\nT\nrand_gamma (T a)\n{\n  T retval;\n  rand_gamma (a, 1, &retval);\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/randmtzig.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n   A C-program for MT19937, with initialization improved 2002/2/10.\n   Coded by Takuji Nishimura and Makoto Matsumoto.\n   This is a faster version by taking Shawn Cokus's optimization,\n   Matthe Bellew's simplification, Isaku Wada's real version.\n   David Bateman added normal and exponential distributions following\n   Marsaglia and Tang's Ziggurat algorithm.\n\n   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,\n   Copyright (C) 2004, David Bateman\n   All rights reserved.\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions\n   are met:\n\n     1. Redistributions of source code must retain the above copyright\n        notice, this list of conditions and the following disclaimer.\n\n     2. Redistributions in binary form must reproduce the above copyright\n        notice, this list of conditions and the following disclaimer in the\n        documentation and/or other materials provided with the distribution.\n\n     3. The names of its contributors may not be used to endorse or promote\n        products derived from this software without specific prior written\n        permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER\n   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n   Any feedback is very welcome.\n   http://www.math.keio.ac.jp/matumoto/emt.html\n   email: matumoto@math.keio.ac.jp\n\n   * 2004-01-19 Paul Kienzle\n   * * comment out main\n   * add init_by_entropy, get_state, set_state\n   * * converted to allow compiling by C++ compiler\n   *\n   * 2004-01-25 David Bateman\n   * * Add Marsaglia and Tsang Ziggurat code\n   *\n   * 2004-07-13 Paul Kienzle\n   * * make into an independent library with some docs.\n   * * introduce new main and test code.\n   *\n   * 2004-07-28 Paul Kienzle & David Bateman\n   * * add -DALLBITS flag for 32 vs. 53 bits of randomness in mantissa\n   * * make the naming scheme more uniform\n   * * add -DHAVE_X86 for faster support of 53 bit mantissa on x86 arch.\n   *\n   * 2005-02-23 Paul Kienzle\n   * * fix -DHAVE_X86_32 flag and add -DUSE_X86_32=0|1 for explicit control\n   *\n   * 2006-04-01 David Bateman\n   * * convert for use in octave, declaring static functions only used\n   *   here and adding oct_ to functions visible externally\n   * * inverse sense of ALLBITS\n   *\n   * 2012-05-18 David Bateman\n   * * Remove randu64 and ALLBIT option\n   * * Add the single precision generators\n   */\n\n/*\n   === Build instructions ===\n\n   Compile with -DHAVE_GETTIMEOFDAY if the gettimeofday function is\n   available.  This is not necessary if your architecture has\n   /dev/urandom defined.\n\n   Uses implicit -Di386 or explicit -DHAVE_X86_32 to determine if CPU=x86.\n   You can force X86 behavior with -DUSE_X86_32=1, or suppress it with\n   -DUSE_X86_32=0. You should also consider -march=i686 or similar for\n   extra performance. Check whether -DUSE_X86_32=0 is faster on 64-bit\n   x86 architectures.\n\n   If you want to replace the Mersenne Twister with another\n   generator then redefine randi32 appropriately.\n\n   === Usage instructions ===\n   Before using any of the generators, initialize the state with one of\n   the init_mersenne_twister functions.\n\n   All generators share the same state vector.\n\n   === Mersenne Twister ===\n   random initial state:\n   void init_mersenne_twister ()\n\n   // 32-bit initial state:\n   void init_mersenne_twister (uint32_t s)\n\n   // m*32-bit initial state:\n   void init_mersenne_twister (uint32_t k[],int m)\n\n   // saves state in array:\n   void get_mersenne_twister_state (uint32_t save[MT_N+1])\n\n   // restores state from array\n   void set_mersenne_twister_state (uint32_t save[MT_N+1])\n\n   static uint32_t randmt ()               returns 32-bit unsigned int\n\n   === inline generators ===\n   static uint32_t randi32 ()   returns 32-bit unsigned int\n   static uint64_t randi53 ()   returns 53-bit unsigned int\n   static uint64_t randi54 ()   returns 54-bit unsigned int\n   static float randu24 ()      returns 24-bit uniform in (0,1)\n   static double randu53 ()     returns 53-bit uniform in (0,1)\n\n   double rand_uniform ()       returns M-bit uniform in (0,1)\n   double rand_normal ()        returns M-bit standard normal\n   double rand_exponential ()   returns N-bit standard exponential\n\n   === Array generators ===\n   void rand_uniform (octave_idx_type, double [])\n   void rand_normal (octave_idx_type, double [])\n   void rand_exponential (octave_idx_type, double [])\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <ctime>\n\n#include <algorithm>\n#include <random>\n\n#include \"oct-syscalls.h\"\n#include \"oct-time.h\"\n#include \"randmtzig.h\"\n\n/* FIXME: may want to suppress X86 if sizeof(long) > 4 */\n#if ! defined (USE_X86_32)\n#  if defined (i386) || defined (HAVE_X86_32)\n#    define USE_X86_32 1\n#  else\n#    define USE_X86_32 0\n#  endif\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n/* ===== Mersenne Twister 32-bit generator ===== */\n\n#define MT_M 397\n#define MATRIX_A 0x9908b0dfUL   /* constant vector a */\n#define UMASK 0x80000000UL /* most significant w-r bits */\n#define LMASK 0x7fffffffUL /* least significant r bits */\n#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )\n#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))\n\nstatic uint32_t *next;\nstatic uint32_t state[MT_N]; /* the array for the state vector  */\nstatic int left = 1;\nstatic int initf = 0;\nstatic int initt = 1;\nstatic int inittf = 1;\n\n/* initializes state[MT_N] with a seed */\nvoid\ninit_mersenne_twister (const uint32_t s)\n{\n  int j;\n  state[0] = s & 0xffffffffUL;\n  for (j = 1; j < MT_N; j++)\n    {\n      state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);\n      /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */\n      /* In the previous versions, MSBs of the seed affect   */\n      /* only MSBs of the array state[].                        */\n      /* 2002/01/09 modified by Makoto Matsumoto             */\n      state[j] &= 0xffffffffUL;  /* for >32 bit machines */\n    }\n  left = 1;\n  initf = 1;\n}\n\n/* initialize by an array with array-length */\n/* init_key is the array for initializing keys */\n/* key_length is its length */\nvoid\ninit_mersenne_twister (const uint32_t *init_key, const int key_length)\n{\n  int i, j, k;\n  init_mersenne_twister (19650218UL);\n  i = 1;\n  j = 0;\n  k = (MT_N > key_length ? MT_N : key_length);\n  for (; k; k--)\n    {\n      state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL))\n                 + init_key[j] + j; /* non linear */\n      state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */\n      i++;\n      j++;\n      if (i >= MT_N)\n        {\n          state[0] = state[MT_N-1];\n          i = 1;\n        }\n      if (j >= key_length)\n        j = 0;\n    }\n  for (k = MT_N - 1; k; k--)\n    {\n      state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL))\n                 - i; /* non linear */\n      state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */\n      i++;\n      if (i >= MT_N)\n        {\n          state[0] = state[MT_N-1];\n          i = 1;\n        }\n    }\n\n  state[0] = 0x80000000UL; /* MSB is 1; assuring nonzero initial array */\n  left = 1;\n  initf = 1;\n}\n\nvoid\ninit_mersenne_twister ()\n{\n  uint32_t entropy[MT_N];\n  int n = 0;\n\n  // Gather some entropy from various sources\n\n  sys::time now;\n\n  // Current time in seconds\n  if (n < MT_N)\n    entropy[n++] = now.unix_time ();\n\n  // CPU time used (usec)\n  if (n < MT_N)\n    entropy[n++] = clock ();\n\n  // Fractional part of current time\n  if (n < MT_N)\n    entropy[n++] = now.usec ();\n\n  // Include the PID to make sure that several processes reaching here at the\n  // same time use different random numbers.\n  if (n < MT_N)\n    entropy[n++] = sys::getpid ();\n\n  if (n < MT_N)\n    {\n      try\n        {\n          // The standard doesn't *guarantee* that random_device provides\n          // non-deterministic random numbers. So add entropy from this\n          // source last to make sure we gathered at least some entropy from\n          // the earlier sources.\n          std::random_device rd;\n          std::uniform_int_distribution<uint32_t> dist;\n          // Add 1024 bit of \"true\" entropy\n          int n_max = std::min (n + 32, MT_N);\n          while (n < n_max)\n            entropy[n++] = dist (rd);\n        }\n      catch (const std::exception&)\n        {\n          // Just ignore any exception and skip that source of entropy.\n        }\n    }\n\n  // Send all the entropy into the initial state vector\n  init_mersenne_twister (entropy, n);\n}\n\nvoid\nset_mersenne_twister_state (const uint32_t *save)\n{\n  std::copy_n (save, MT_N, state);\n  left = save[MT_N];\n  next = state + (MT_N - left + 1);\n}\n\nvoid\nget_mersenne_twister_state (uint32_t *save)\n{\n  std::copy_n (state, MT_N, save);\n  save[MT_N] = left;\n}\n\nstatic void\nnext_state ()\n{\n  uint32_t *p = state;\n  int j;\n\n  /* if init_by_int() has not been called, */\n  /* a default initial seed is used         */\n  /* if (initf==0) init_by_int(5489UL); */\n  /* Or better yet, a random seed! */\n  if (initf == 0)\n    init_mersenne_twister ();\n\n  left = MT_N;\n  next = state;\n\n  for (j = MT_N - MT_M + 1; --j; p++)\n    *p = p[MT_M] ^ TWIST(p[0], p[1]);\n\n  for (j = MT_M; --j; p++)\n    *p = p[MT_M-MT_N] ^ TWIST(p[0], p[1]);\n\n  *p = p[MT_M-MT_N] ^ TWIST(p[0], state[0]);\n}\n\n/* generates a random number on [0,0xffffffff]-interval */\nstatic uint32_t\nrandmt ()\n{\n  uint32_t y;\n\n  if (--left == 0)\n    next_state ();\n  y = *next++;\n\n  /* Tempering */\n  y ^= (y >> 11);\n  y ^= (y << 7) & 0x9d2c5680UL;\n  y ^= (y << 15) & 0xefc60000UL;\n  return (y ^ (y >> 18));\n}\n\n/* ===== Uniform generators ===== */\n\n/* Select which 32 bit generator to use */\n#define randi32 randmt\n\nstatic uint64_t\nrandi53 ()\n{\n  const uint32_t lo = randi32 ();\n  const uint32_t hi = randi32 () & 0x1FFFFF;\n#if defined (HAVE_X86_32)\n  uint64_t u;\n  uint32_t *p = (uint32_t *)&u;\n  p[0] = lo;\n  p[1] = hi;\n  return u;\n#else\n  return ((static_cast<uint64_t> (hi) << 32) | lo);\n#endif\n}\n\nstatic uint64_t\nrandi54 ()\n{\n  const uint32_t lo = randi32 ();\n  const uint32_t hi = randi32 () & 0x3FFFFF;\n#if defined (HAVE_X86_32)\n  uint64_t u;\n  uint32_t *p = static_cast<uint32_t *> (&u);\n  p[0] = lo;\n  p[1] = hi;\n  return u;\n#else\n  return ((static_cast<uint64_t> (hi) << 32) | lo);\n#endif\n}\n\n/* generates a random number on (0,1)-real-interval */\nstatic float\nrandu24 ()\n{\n  uint32_t i;\n\n  do\n    {\n      i = randi32 () & static_cast<uint32_t> (0xFFFFFF);\n    }\n  while (i == 0);\n\n  return i * (1.0f / 16777216.0f);\n}\n\n/* generates a random number on (0,1) with 53-bit resolution */\nstatic double\nrandu53 ()\n{\n  int32_t a, b;\n\n  do\n    {\n      a = randi32 () >> 5;\n      b = randi32 () >> 6;\n    }\n  while (a == 0 && b == 0);\n\n  return (a*67108864.0 + b) * (1.0/9007199254740992.0);\n}\n\n/* Determine mantissa for uniform doubles */\ntemplate <>\nOCTAVE_API double\nrand_uniform<double> ()\n{\n  return randu53 ();\n}\n\n/* Determine mantissa for uniform floats */\ntemplate <>\nOCTAVE_API float\nrand_uniform<float> ()\n{\n  return randu24 ();\n}\n\n/* ===== Ziggurat normal and exponential generators ===== */\n\n#define ZIGGURAT_TABLE_SIZE 256\n\n#define ZIGGURAT_NOR_R 3.6541528853610088\n#define ZIGGURAT_NOR_INV_R 0.27366123732975828\n#define NOR_SECTION_AREA 0.00492867323399\n\n#define ZIGGURAT_EXP_R 7.69711747013104972\n#define ZIGGURAT_EXP_INV_R 0.129918765548341586\n#define EXP_SECTION_AREA 0.0039496598225815571993\n\n#define ZIGINT uint64_t\n#define EMANTISSA 9007199254740992.0  /* 53 bit mantissa */\n#define ERANDI randi53() /* 53 bits for mantissa */\n#define NMANTISSA EMANTISSA\n#define NRANDI randi54() /* 53 bits for mantissa + 1 bit sign */\n#define RANDU randu53()\n\nstatic ZIGINT ki[ZIGGURAT_TABLE_SIZE];\nstatic double wi[ZIGGURAT_TABLE_SIZE], fi[ZIGGURAT_TABLE_SIZE];\nstatic ZIGINT ke[ZIGGURAT_TABLE_SIZE];\nstatic double we[ZIGGURAT_TABLE_SIZE], fe[ZIGGURAT_TABLE_SIZE];\n\n/*\n  This code is based on the paper Marsaglia and Tsang, \"The ziggurat method\n  for generating random variables\", Journ. Statistical Software. Code was\n  presented in this paper for a Ziggurat of 127 levels and using a 32 bit\n  integer random number generator. This version of the code, uses the\n  Mersenne Twister as the integer generator and uses 256 levels in the\n  Ziggurat. This has several advantages.\n\n  1) As Marsaglia and Tsang themselves states, the more levels the few\n  times the expensive tail algorithm must be called\n  2) The cycle time of the generator is determined by the integer\n  generator, thus the use of a Mersenne Twister for the core random\n  generator makes this cycle extremely long.\n  3) The license on the original code was unclear, thus rewriting the code\n  from the article means we are free of copyright issues.\n  4) Compile flag for full 53-bit random mantissa.\n\n  It should be stated that the authors made my life easier, by the fact that\n  the algorithm developed in the text of the article is for a 256 level\n  ziggurat, even if the code itself isn't...\n\n  One modification to the algorithm developed in the article, is that it is\n  assumed that 0 <= x < Inf, and \"unsigned long\"s are used, thus resulting in\n  terms like 2^32 in the code. As the normal distribution is defined between\n  -Inf < x < Inf, we effectively only have 31 bit integers plus a sign. Thus\n  in Marsaglia and Tsang, terms like 2^32 become 2^31. We use NMANTISSA for\n  this term.  The exponential distribution is one sided so we use the\n  full 32 bits.  We use EMANTISSA for this term.\n\n  It appears that I'm slightly slower than the code in the article, this\n  is partially due to a better generator of random integers than they\n  use. But might also be that the case of rapid return was optimized by\n  inlining the relevant code with a #define. As the basic Mersenne\n  Twister is only 25% faster than this code I suspect that the main\n  reason is just the use of the Mersenne Twister and not the inlining,\n  so I'm not going to try and optimize further.\n*/\n\nvoid\ncreate_ziggurat_tables ()\n{\n  int i;\n  double x, x1;\n\n  /* Ziggurat tables for the normal distribution */\n  x1 = ZIGGURAT_NOR_R;\n  wi[255] = x1 / NMANTISSA;\n  fi[255] = exp (-0.5 * x1 * x1);\n\n  /* Index zero is special for tail strip, where Marsaglia and Tsang\n   * defines this as\n   * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1,\n   * where v is the area of each strip of the ziggurat.\n   */\n  ki[0] = static_cast<ZIGINT> (x1 * fi[255] / NOR_SECTION_AREA * NMANTISSA);\n  wi[0] = NOR_SECTION_AREA / fi[255] / NMANTISSA;\n  fi[0] = 1.;\n\n  for (i = 254; i > 0; i--)\n    {\n      /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus\n       * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y))\n       */\n      x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + fi[i+1]));\n      ki[i+1] = static_cast<ZIGINT> (x / x1 * NMANTISSA);\n      wi[i] = x / NMANTISSA;\n      fi[i] = exp (-0.5 * x * x);\n      x1 = x;\n    }\n\n  ki[1] = 0;\n\n  /* Zigurrat tables for the exponential distribution */\n  x1 = ZIGGURAT_EXP_R;\n  we[255] = x1 / EMANTISSA;\n  fe[255] = exp (-x1);\n\n  /* Index zero is special for tail strip, where Marsaglia and Tsang\n   * defines this as\n   * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1,\n   * where v is the area of each strip of the ziggurat.\n   */\n  ke[0] = static_cast<ZIGINT> (x1 * fe[255] / EXP_SECTION_AREA * EMANTISSA);\n  we[0] = EXP_SECTION_AREA / fe[255] / EMANTISSA;\n  fe[0] = 1.;\n\n  for (i = 254; i > 0; i--)\n    {\n      /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus\n       * need inverse operator of y = exp(-x) -> x = -ln(y)\n       */\n      x = - std::log (EXP_SECTION_AREA / x1 + fe[i+1]);\n      ke[i+1] = static_cast<ZIGINT> (x / x1 * EMANTISSA);\n      we[i] = x / EMANTISSA;\n      fe[i] = exp (-x);\n      x1 = x;\n    }\n  ke[1] = 0;\n\n  initt = 0;\n}\n\n/*\n * Here is the guts of the algorithm. As Marsaglia and Tsang state the\n * algorithm in their paper\n *\n * 1) Calculate a random signed integer j and let i be the index\n *     provided by the rightmost 8-bits of j\n * 2) Set x = j * w_i. If j < k_i return x\n * 3) If i = 0, then return x from the tail\n * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x\n * 5) goto step 1\n *\n * Where f is the functional form of the distribution, which for a normal\n * distribution is exp(-0.5*x*x)\n */\n\n\ntemplate <>\nOCTAVE_API double\nrand_normal<double> ()\n{\n  if (initt)\n    create_ziggurat_tables ();\n\n  while (1)\n    {\n      /* The following code is specialized for 32-bit mantissa.\n       * Compared to the arbitrary mantissa code, there is a performance\n       * gain for 32-bits: PPC: 2%,  MIPS: 8%,  x86: 40%\n       * There is a bigger performance gain compared to using a full\n       * 53-bit mantissa:  PPC: 60%, MIPS: 65%, x86: 240%\n       * Of course, different compilers and operating systems may\n       * have something to do with this.\n       */\n# if defined (HAVE_X86_32)\n      /* 53-bit mantissa, 1-bit sign, x86 32-bit architecture */\n      double x;\n      int si, idx;\n      uint32_t lo, hi;\n      int64_t rabs;\n      uint32_t *p = (uint32_t *)&rabs;\n      lo = randi32 ();\n      idx = lo & 0xFF;\n      hi = randi32 ();\n      si = hi & UMASK;\n      p[0] = lo;\n      p[1] = hi & 0x1FFFFF;\n      x = ( si ? -rabs : rabs ) * wi[idx];\n# else\n      /* arbitrary mantissa (selected by NRANDI, with 1 bit for sign) */\n      const uint64_t r = NRANDI;\n      const int64_t rabs = r >> 1;\n      const int idx = static_cast<int> (rabs & 0xFF);\n      const double x = ( (r & 1) ? -rabs : rabs) * wi[idx];\n# endif\n      if (rabs < static_cast<int64_t> (ki[idx]))\n        return x;        /* 99.3% of the time we return here 1st try */\n      else if (idx == 0)\n        {\n          /* As stated in Marsaglia and Tsang\n           *\n           * For the normal tail, the method of Marsaglia[5] provides:\n           * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x,\n           * then return r+x. Except that r+x is always in the positive\n           * tail!!!! Any thing random might be used to determine the\n           * sign, but as we already have r we might as well use it\n           *\n           * [PAK] but not the bottom 8 bits, since they are all 0 here!\n           */\n          double xx, yy;\n          do\n            {\n              xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU);\n              yy = - std::log (RANDU);\n            }\n          while ( yy+yy <= xx*xx);\n          return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx);\n        }\n      else if ((fi[idx-1] - fi[idx]) * RANDU + fi[idx] < exp (-0.5*x*x))\n        return x;\n    }\n}\n\ntemplate <>\nOCTAVE_API double\nrand_exponential<double> ()\n{\n  if (initt)\n    create_ziggurat_tables ();\n\n  while (1)\n    {\n      ZIGINT ri = ERANDI;\n      const int idx = static_cast<int> (ri & 0xFF);\n      const double x = ri * we[idx];\n      if (ri < ke[idx])\n        return x;               /* 98.9% of the time we return here 1st try */\n      else if (idx == 0)\n        {\n          /* As stated in Marsaglia and Tsang\n           *\n           * For the exponential tail, the method of Marsaglia[5] provides:\n           * x = r - ln(U);\n           */\n          return ZIGGURAT_EXP_R - std::log (RANDU);\n        }\n      else if ((fe[idx-1] - fe[idx]) * RANDU + fe[idx] < exp (-x))\n        return x;\n    }\n}\n\ntemplate <> OCTAVE_API void rand_uniform<double> (octave_idx_type n, double *p)\n{\n  std::generate_n (p, n, []() { return rand_uniform<double> (); });\n}\n\ntemplate <> OCTAVE_API void rand_normal (octave_idx_type n, double *p)\n{\n  std::generate_n (p, n, []() { return rand_normal<double> (); });\n}\n\ntemplate <> OCTAVE_API void rand_exponential (octave_idx_type n, double *p)\n{\n  std::generate_n (p, n, []() { return rand_exponential<double> (); });\n}\n\n#undef ZIGINT\n#undef EMANTISSA\n#undef ERANDI\n#undef NMANTISSA\n#undef NRANDI\n#undef RANDU\n\n#define ZIGINT uint32_t\n#define EMANTISSA 4294967296.0 /* 32 bit mantissa */\n#define ERANDI randi32() /* 32 bits for mantissa */\n#define NMANTISSA 2147483648.0 /* 31 bit mantissa */\n#define NRANDI randi32() /* 31 bits for mantissa + 1 bit sign */\n#define RANDU randu24()\n\nstatic ZIGINT fki[ZIGGURAT_TABLE_SIZE];\nstatic float fwi[ZIGGURAT_TABLE_SIZE], ffi[ZIGGURAT_TABLE_SIZE];\nstatic ZIGINT fke[ZIGGURAT_TABLE_SIZE];\nstatic float fwe[ZIGGURAT_TABLE_SIZE], ffe[ZIGGURAT_TABLE_SIZE];\n\nstatic void\ncreate_ziggurat_float_tables ()\n{\n  int i;\n  float x, x1;\n\n  /* Ziggurat tables for the normal distribution */\n  x1 = ZIGGURAT_NOR_R;\n  fwi[255] = x1 / NMANTISSA;\n  ffi[255] = exp (-0.5 * x1 * x1);\n\n  /* Index zero is special for tail strip, where Marsaglia and Tsang\n   * defines this as\n   * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1,\n   * where v is the area of each strip of the ziggurat.\n   */\n  fki[0] = static_cast<ZIGINT> (x1 * ffi[255] / NOR_SECTION_AREA * NMANTISSA);\n  fwi[0] = NOR_SECTION_AREA / ffi[255] / NMANTISSA;\n  ffi[0] = 1.;\n\n  for (i = 254; i > 0; i--)\n    {\n      /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus\n       * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y))\n       */\n      x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + ffi[i+1]));\n      fki[i+1] = static_cast<ZIGINT> (x / x1 * NMANTISSA);\n      fwi[i] = x / NMANTISSA;\n      ffi[i] = exp (-0.5 * x * x);\n      x1 = x;\n    }\n\n  fki[1] = 0;\n\n  /* Zigurrat tables for the exponential distribution */\n  x1 = ZIGGURAT_EXP_R;\n  fwe[255] = x1 / EMANTISSA;\n  ffe[255] = exp (-x1);\n\n  /* Index zero is special for tail strip, where Marsaglia and Tsang\n   * defines this as\n   * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1,\n   * where v is the area of each strip of the ziggurat.\n   */\n  fke[0] = static_cast<ZIGINT> (x1 * ffe[255] / EXP_SECTION_AREA * EMANTISSA);\n  fwe[0] = EXP_SECTION_AREA / ffe[255] / EMANTISSA;\n  ffe[0] = 1.;\n\n  for (i = 254; i > 0; i--)\n    {\n      /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus\n       * need inverse operator of y = exp(-x) -> x = -ln(y)\n       */\n      x = - std::log (EXP_SECTION_AREA / x1 + ffe[i+1]);\n      fke[i+1] = static_cast<ZIGINT> (x / x1 * EMANTISSA);\n      fwe[i] = x / EMANTISSA;\n      ffe[i] = exp (-x);\n      x1 = x;\n    }\n  fke[1] = 0;\n\n  inittf = 0;\n}\n\n/*\n * Here is the guts of the algorithm. As Marsaglia and Tsang state the\n * algorithm in their paper\n *\n * 1) Calculate a random signed integer j and let i be the index\n *     provided by the rightmost 8-bits of j\n * 2) Set x = j * w_i. If j < k_i return x\n * 3) If i = 0, then return x from the tail\n * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x\n * 5) goto step 1\n *\n * Where f is the functional form of the distribution, which for a normal\n * distribution is exp(-0.5*x*x)\n */\n\ntemplate <>\nOCTAVE_API float\nrand_normal<float> ()\n{\n  if (inittf)\n    create_ziggurat_float_tables ();\n\n  while (1)\n    {\n      /* 32-bit mantissa */\n      const uint32_t r = randi32 ();\n      const uint32_t rabs = r & LMASK;\n      const int idx = static_cast<int> (r & 0xFF);\n      const float x = static_cast<int32_t> (r) * fwi[idx];\n      if (rabs < fki[idx])\n        return x;        /* 99.3% of the time we return here 1st try */\n      else if (idx == 0)\n        {\n          /* As stated in Marsaglia and Tsang\n           *\n           * For the normal tail, the method of Marsaglia[5] provides:\n           * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x,\n           * then return r+x. Except that r+x is always in the positive\n           * tail!!!! Any thing random might be used to determine the\n           * sign, but as we already have r we might as well use it\n           *\n           * [PAK] but not the bottom 8 bits, since they are all 0 here!\n           */\n          float xx, yy;\n          do\n            {\n              xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU);\n              yy = - std::log (RANDU);\n            }\n          while ( yy+yy <= xx*xx);\n          return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx);\n        }\n      else if ((ffi[idx-1] - ffi[idx]) * RANDU + ffi[idx] < exp (-0.5*x*x))\n        return x;\n    }\n}\n\ntemplate <>\nOCTAVE_API float\nrand_exponential<float> ()\n{\n  if (inittf)\n    create_ziggurat_float_tables ();\n\n  while (1)\n    {\n      ZIGINT ri = ERANDI;\n      const int idx = static_cast<int> (ri & 0xFF);\n      const float x = ri * fwe[idx];\n      if (ri < fke[idx])\n        return x;               /* 98.9% of the time we return here 1st try */\n      else if (idx == 0)\n        {\n          /* As stated in Marsaglia and Tsang\n           *\n           * For the exponential tail, the method of Marsaglia[5] provides:\n           * x = r - ln(U);\n           */\n          return ZIGGURAT_EXP_R - std::log (RANDU);\n        }\n      else if ((ffe[idx-1] - ffe[idx]) * RANDU + ffe[idx] < exp (-x))\n        return x;\n    }\n}\n\ntemplate <> OCTAVE_API void rand_uniform (octave_idx_type n, float *p)\n{\n  std::generate_n (p, n, []() { return rand_uniform<float> (); });\n}\n\ntemplate <> OCTAVE_API void rand_normal (octave_idx_type n, float *p)\n{\n  std::generate_n (p, n, []() { return rand_normal<float> (); });\n}\n\ntemplate <> OCTAVE_API void rand_exponential (octave_idx_type n, float *p)\n{\n  std::generate_n (p, n, []() { return rand_exponential<float> (); });\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/randmtzig.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n   A C-program for MT19937, with initialization improved 2002/2/10.\n   Coded by Takuji Nishimura and Makoto Matsumoto.\n   This is a faster version by taking Shawn Cokus's optimization,\n   Matthe Bellew's simplification, Isaku Wada's real version.\n   David Bateman added normal and exponential distributions following\n   Marsaglia and Tang's Ziggurat algorithm.\n\n   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,\n   Copyright (C) 2004, David Bateman\n   All rights reserved.\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions\n   are met:\n\n     1. Redistributions of source code must retain the above copyright\n        notice, this list of conditions and the following disclaimer.\n\n     2. Redistributions in binary form must reproduce the above copyright\n        notice, this list of conditions and the following disclaimer in the\n        documentation and/or other materials provided with the distribution.\n\n     3. The names of its contributors may not be used to endorse or promote\n        products derived from this software without specific prior written\n        permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER\n   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n*/\n\n#if ! defined (octave_randmtzig_h)\n#define octave_randmtzig_h 1\n\n#include \"octave-config.h\"\n\n#define MT_N 624\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Mersenne Twister.\n\nextern OCTAVE_API void init_mersenne_twister ();\nextern OCTAVE_API void init_mersenne_twister (const uint32_t seed);\nextern OCTAVE_API void init_mersenne_twister (const uint32_t *init_key,\n                                              const int key_length);\n\nextern OCTAVE_API void set_mersenne_twister_state (const uint32_t *save);\nextern OCTAVE_API void get_mersenne_twister_state (uint32_t *save);\n\ntemplate <typename T> OCTAVE_API T rand_uniform ();\ntemplate <typename T> OCTAVE_API T rand_normal ();\ntemplate <typename T> OCTAVE_API T rand_exponential ();\n\ntemplate <typename T> OCTAVE_API void rand_uniform (octave_idx_type n, T *p);\ntemplate <typename T> OCTAVE_API void rand_normal (octave_idx_type n, T *p);\ntemplate <typename T> OCTAVE_API void\nrand_exponential (octave_idx_type n, T *p);\n\ntemplate <> OCTAVE_API double rand_uniform<double> ();\ntemplate <> OCTAVE_API double rand_normal<double> ();\ntemplate <> OCTAVE_API double rand_exponential<double> ();\n\ntemplate <> OCTAVE_API float rand_uniform<float> ();\ntemplate <> OCTAVE_API float rand_normal<float> ();\ntemplate <> OCTAVE_API float rand_exponential<float> ();\n\ntemplate <> OCTAVE_API void\nrand_uniform<double> (octave_idx_type n, double *p);\n\ntemplate <> OCTAVE_API void\nrand_normal<double> (octave_idx_type n, double *p);\n\ntemplate <> OCTAVE_API void\nrand_exponential<double> (octave_idx_type n, double *p);\n\ntemplate <> OCTAVE_API void\nrand_uniform<float> (octave_idx_type n, float *p);\n\ntemplate <> OCTAVE_API void\nrand_normal<float> (octave_idx_type n, float *p);\n\ntemplate <> OCTAVE_API void\nrand_exponential<float> (octave_idx_type n, float *p);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/randpoisson.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/* Original version written by Paul Kienzle distributed as free\n   software in the in the public domain.  */\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <cstddef>\n\n#include \"f77-fcn.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"oct-error.h\"\n#include \"randmtzig.h\"\n#include \"randpoisson.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic double xlgamma (double x)\n{\n  return std::lgamma (x);\n}\n\n/* ---- pprsc.c from Stadloeber's winrand --- */\n\n/* flogfak(k) = ln(k!) */\nstatic double\nflogfak (double k)\n{\n#define C0  9.18938533204672742e-01\n#define C1  8.33333333333333333e-02\n#define C3 -2.77777777777777778e-03\n#define C5  7.93650793650793651e-04\n#define C7 -5.95238095238095238e-04\n\n  static double logfak[30L] =\n  {\n    0.00000000000000000,   0.00000000000000000,   0.69314718055994531,\n    1.79175946922805500,   3.17805383034794562,   4.78749174278204599,\n    6.57925121201010100,   8.52516136106541430,  10.60460290274525023,\n    12.80182748008146961,  15.10441257307551530,  17.50230784587388584,\n    19.98721449566188615,  22.55216385312342289,  25.19122118273868150,\n    27.89927138384089157,  30.67186010608067280,  33.50507345013688888,\n    36.39544520803305358,  39.33988418719949404,  42.33561646075348503,\n    45.38013889847690803,  48.47118135183522388,  51.60667556776437357,\n    54.78472939811231919,  58.00360522298051994,  61.26170176100200198,\n    64.55753862700633106,  67.88974313718153498,  71.25703896716800901\n  };\n\n  double r, rr;\n\n  if (k >= 30.0)\n    {\n      r  = 1.0 / k;\n      rr = r * r;\n      return ((k + 0.5)*std::log (k) - k + C0\n              + r*(C1 + rr*(C3 + rr*(C5 + rr*C7))));\n    }\n  else\n    return (logfak[static_cast<int> (k)]);\n}\n\n/******************************************************************\n *                                                                *\n * Poisson Distribution - Patchwork Rejection/Inversion           *\n *                                                                *\n ******************************************************************\n *                                                                *\n * For parameter my < 10, Tabulated Inversion is applied.         *\n * For my >= 10, Patchwork Rejection is employed:                 *\n * The area below the histogram function f(x) is rearranged in    *\n * its body by certain point reflections. Within a large center   *\n * interval variates are sampled efficiently by rejection from    *\n * uniform hats. Rectangular immediate acceptance regions speed   *\n * up the generation. The remaining tails are covered by          *\n * exponential functions.                                         *\n *                                                                *\n ******************************************************************\n *                                                                *\n * FUNCTION :   - pprsc samples a random number from the Poisson  *\n *                distribution with parameter my > 0.             *\n * REFERENCE :  - H. Zechner : Efficient sampling from            *\n *                continuous and discrete unimodal distributions, *\n *                Doctoral Dissertation, pp. 156, Technical       *\n *                University Graz, Austria, 1994.                 *\n * SUBPROGRAM : - drand(seed) ... (0,1)-Uniform generator with    *\n *                unsigned long integer *seed.                    *\n *                                                                *\n * Implemented by H. Zechner, January 1994                        *\n * Revised by F. Niederl, July 1994                               *\n *                                                                *\n ******************************************************************/\n\nstatic double\nf (double k, double l_nu, double c_pm)\n{\n  return exp (k * l_nu - flogfak (k) - c_pm);\n}\n\nstatic double\npprsc (double my)\n{\n  static double my_last = -1.0;\n  static double m, k2, k4, k1, k5;\n  static double dl, dr, r1, r2, r4, r5, ll, lr, l_my, c_pm,\n         f1, f2, f4, f5, p1, p2, p3, p4, p5, p6;\n  double        Dk, X, Y;\n  double        Ds, U, V, W;\n\n  if (my != my_last)\n    {\n      /* set-up           */\n      my_last = my;\n      /* approximate deviation of reflection points k2, k4 from my - 1/2 */\n      Ds = std::sqrt (my + 0.25);\n\n      /* mode m, reflection points k2 and k4, and points k1 and k5,      */\n      /* which delimit the centre region of h(x)                         */\n      m  = std::floor (my);\n      k2 = ceil (my - 0.5 - Ds);\n      k4 = std::floor (my - 0.5 + Ds);\n      k1 = k2 + k2 - m + 1L;\n      k5 = k4 + k4 - m;\n\n      /* range width of the critical left and right centre region        */\n      dl = (k2 - k1);\n      dr = (k5 - k4);\n\n      /* recurrence constants r(k)=p(k)/p(k-1) at k = k1, k2, k4+1, k5+1 */\n      r1 = my / k1;\n      r2 = my / k2;\n      r4 = my / (k4 + 1.0);\n      r5 = my / (k5 + 1.0);\n\n      /* reciprocal values of the scale parameters of exp. tail envelope */\n      ll =  std::log (r1);                        /* expon. tail left */\n      lr = -std::log (r5);                        /* expon. tail right*/\n\n      /* Poisson constants, necessary for computing function values f(k) */\n      l_my = std::log (my);\n      c_pm = m * l_my - flogfak (m);\n\n      /* function values f(k) = p(k)/p(m) at k = k2, k4, k1, k5          */\n      f2 = f (k2, l_my, c_pm);\n      f4 = f (k4, l_my, c_pm);\n      f1 = f (k1, l_my, c_pm);\n      f5 = f (k5, l_my, c_pm);\n\n      /* area of the two centre and the two exponential tail regions     */\n      /* area of the two immediate acceptance regions between k2, k4     */\n      p1 = f2 * (dl + 1.0);                            /* immed. left    */\n      p2 = f2 * dl         + p1;                       /* centre left    */\n      p3 = f4 * (dr + 1.0) + p2;                       /* immed. right   */\n      p4 = f4 * dr         + p3;                       /* centre right   */\n      p5 = f1 / ll         + p4;                       /* exp. tail left */\n      p6 = f5 / lr         + p5;                       /* exp. tail right*/\n    }\n\n  for (;;)\n    {\n      /* generate uniform number U -- U(0, p6)                           */\n      /* case distinction corresponding to U                             */\n      if ((U = rand_uniform<double> () * p6) < p2)\n        {\n          /* centre left      */\n\n          /* immediate acceptance region\n             R2 = [k2, m) *[0, f2),  X = k2, ... m -1 */\n          if ((V = U - p1) < 0.0)  return (k2 + std::floor (U/f2));\n          /* immediate acceptance region\n             R1 = [k1, k2)*[0, f1),  X = k1, ... k2-1 */\n          if ((W = V / dl) < f1 )  return (k1 + std::floor (V/f1));\n\n          /* computation of candidate X < k2, and its counterpart Y > k2 */\n          /* either squeeze-acceptance of X or acceptance-rejection of Y */\n          Dk = std::floor (dl * rand_uniform<double> ()) + 1.0;\n          if (W <= f2 - Dk * (f2 - f2/r2))\n            {\n              /* quick accept of  */\n              return (k2 - Dk);                      /* X = k2 - Dk      */\n            }\n          if ((V = f2 + f2 - W) < 1.0)\n            {\n              /* quick reject of Y*/\n              Y = k2 + Dk;\n              if (V <= f2 + Dk * (1.0 - f2)/(dl + 1.0))\n                {\n                  /* quick accept of  */\n                  return (Y);                        /* Y = k2 + Dk      */\n                }\n              if (V <= f (Y, l_my, c_pm))  return (Y); /* final accept of Y*/\n            }\n          X = k2 - Dk;\n        }\n      else if (U < p4)\n        {\n          /* centre right     */\n          /*  immediate acceptance region\n              R3 = [m, k4+1)*[0, f4), X = m, ... k4    */\n          if ((V = U - p3) < 0.0)  return (k4 - std::floor ((U - p2)/f4));\n          /* immediate acceptance region\n             R4 = [k4+1, k5+1)*[0, f5)                */\n          if ((W = V / dr) < f5 )  return (k5 - std::floor (V/f5));\n\n          /* computation of candidate X > k4, and its counterpart Y < k4 */\n          /* either squeeze-acceptance of X or acceptance-rejection of Y */\n          Dk = std::floor (dr * rand_uniform<double> ()) + 1.0;\n          if (W <= f4 - Dk * (f4 - f4*r4))\n            {\n              /* quick accept of  */\n              return (k4 + Dk);                      /* X = k4 + Dk      */\n            }\n          if ((V = f4 + f4 - W) < 1.0)\n            {\n              /* quick reject of Y*/\n              Y = k4 - Dk;\n              if (V <= f4 + Dk * (1.0 - f4)/ dr)\n                {\n                  /* quick accept of  */\n                  return (Y);                        /* Y = k4 - Dk      */\n                }\n              if (V <= f (Y, l_my, c_pm))  return (Y); /* final accept of Y*/\n            }\n          X = k4 + Dk;\n        }\n      else\n        {\n          W = rand_uniform<double> ();\n          if (U < p5)\n            {\n              /* expon. tail left */\n              Dk = std::floor (1.0 - std::log (W)/ll);\n              if ((X = k1 - Dk) < 0L)  continue;     /* 0 <= X <= k1 - 1 */\n              W *= (U - p4) * ll;                    /* W -- U(0, h(x))  */\n              if (W <= f1 - Dk * (f1 - f1/r1))\n                return (X);                          /* quick accept of X*/\n            }\n          else\n            {\n              /* expon. tail right*/\n              Dk = std::floor (1.0 - std::log (W)/lr);\n              X  = k5 + Dk;                          /* X >= k5 + 1      */\n              W *= (U - p5) * lr;                    /* W -- U(0, h(x))  */\n              if (W <= f5 - Dk * (f5 - f5*r5))\n                return (X);                          /* quick accept of X*/\n            }\n        }\n\n      /* acceptance-rejection test of candidate X from the original area */\n      /* test, whether  W <= f(k),    with  W = U*h(x)  and  U -- U(0, 1)*/\n      /* log f(X) = (X - m)*log(my) - log X! + log m!                    */\n      if (std::log (W) <= X * l_my - flogfak (X) - c_pm)  return (X);\n    }\n}\n/* ---- pprsc.c end ------ */\n\n/* The remainder of the file is by Paul Kienzle */\n\n/* Table size is predicated on the maximum value of lambda\n * we want to store in the table, and the maximum value of\n * returned by the uniform random number generator on [0,1).\n * With lambda==10 and u_max = 1 - 1/(2^32+1), we\n * have poisson_pdf(lambda,36) < 1-u_max.  If instead our\n * generator uses more bits of mantissa or returns a value\n * in the range [0,1], then for lambda==10 we need a table\n * size of 46 instead.  For long doubles, the table size\n * will need to be longer still.  */\n#define TABLESIZE 46\n\n/* Given uniform u, find x such that CDF(L,x)==u.  Return x. */\n\ntemplate <typename T>\nstatic void\npoisson_cdf_lookup (double lambda, T *p, std::size_t n)\n{\n  double t[TABLESIZE];\n\n  /* Precompute the table for the u up to and including 0.458.\n   * We will almost certainly need it. */\n  int intlambda = static_cast<int> (std::floor (lambda));\n  double P;\n  int tableidx;\n  std::size_t i = n;\n\n  t[0] = P = exp (-lambda);\n  for (tableidx = 1; tableidx <= intlambda; tableidx++)\n    {\n      P = P*lambda/static_cast<double> (tableidx);\n      t[tableidx] = t[tableidx-1] + P;\n    }\n\n  while (i-- > 0)\n    {\n      double u = rand_uniform<double> ();\n\n      /* If u > 0.458 we know we can jump to floor(lambda) before\n       * comparing (this observation is based on Stadlober's winrand\n       * code). For lambda >= 1, this will be a win.  Lambda < 1\n       * is already fast, so adding an extra comparison is not a\n       * problem. */\n      int k = (u > 0.458 ? intlambda : 0);\n\n      /* We aren't using a for loop here because when we find the\n       * right k we want to jump to the next iteration of the\n       * outer loop, and the continue statement will only work for\n       * the inner loop. */\n    nextk:\n      if (u <= t[k])\n        {\n          p[i] = static_cast<T> (k);\n          continue;\n        }\n      if (++k < tableidx)\n        goto nextk;\n\n      /* We only need high values of the table very rarely so we\n       * don't automatically compute the entire table. */\n      while (tableidx < TABLESIZE)\n        {\n          P = P*lambda/static_cast<double> (tableidx);\n          t[tableidx] = t[tableidx-1] + P;\n          /* Make sure we converge to 1.0 just in case u is uniform\n           * on [0,1] rather than [0,1). */\n          if (t[tableidx] == t[tableidx-1]) t[tableidx] = 1.0;\n          tableidx++;\n          if (u <= t[tableidx-1]) break;\n        }\n\n      /* We are assuming that the table size is big enough here.\n       * This should be true even if rand_uniform is returning values in\n       * the range [0,1] rather than [0,1). */\n      p[i] = static_cast<T> (tableidx-1);\n    }\n}\n\n/* From Press, et al., Numerical Recipes */\ntemplate <typename T>\nstatic void\npoisson_rejection (double lambda, T *p, std::size_t n)\n{\n  double sq = std::sqrt (2.0*lambda);\n  double alxm = std::log (lambda);\n  double g = lambda*alxm - xlgamma (lambda+1.0);\n  std::size_t i;\n\n  for (i = 0; i < n; i++)\n    {\n      double y, em, t;\n      do\n        {\n          do\n            {\n              y = tan (M_PI*rand_uniform<double> ());\n              em = sq * y + lambda;\n            }\n          while (em < 0.0);\n          em = std::floor (em);\n          t = 0.9*(1.0+y*y)* exp (em*alxm-flogfak (em)-g);\n        }\n      while (rand_uniform<double> () > t);\n      p[i] = em;\n    }\n}\n\n/* The cutoff of L <= 1e8 in the following two functions before using\n * the normal approximation is based on:\n *   > L=1e8; x=floor(linspace(0,2*L,1000));\n *   > max(abs(normal_pdf(x,L,L)-poisson_pdf(x,L)))\n *   ans = 1.1376e-28\n * For L=1e7, the max is around 1e-9, which is within the step size of\n * rand_uniform.  For L>1e10 the pprsc function breaks down, as I saw\n * from the histogram of a large sample, so 1e8 is both small enough\n * and large enough. */\n\n/* Generate a set of poisson numbers with the same distribution */\ntemplate <typename T>\nvoid\nrand_poisson (T L_arg, octave_idx_type n, T *p)\n{\n  double L = L_arg;\n  octave_idx_type i;\n  if (L < 0.0 || math::isinf (L))\n    {\n      for (i=0; i<n; i++)\n        p[i] = numeric_limits<T>::NaN ();\n    }\n  else if (L <= 10.0)\n    {\n      poisson_cdf_lookup<T> (L, p, n);\n    }\n  else if (L <= 1e8)\n    {\n      for (i=0; i<n; i++)\n        p[i] = pprsc (L);\n    }\n  else\n    {\n      /* normal approximation: from Phys. Rev. D, Vol. 50, p. 1284, 1994. */\n      const double sqrtL = std::sqrt (L);\n      for (i = 0; i < n; i++)\n        {\n          p[i] = std::floor (rand_normal<T> () * sqrtL + L + 0.5);\n          if (p[i] < 0.0)\n            p[i] = 0.0; /* will probably never happen */\n        }\n    }\n}\n\ntemplate void rand_poisson<double> (double, octave_idx_type, double *);\ntemplate void rand_poisson<float> (float, octave_idx_type, float *);\n\n/* Generate one poisson variate */\ntemplate <typename T>\nT\nrand_poisson (T L_arg)\n{\n  double L = L_arg;\n  T ret;\n  if (L < 0.0) ret = numeric_limits<T>::NaN ();\n  else if (L <= 12.0)\n    {\n      /* From Press, et al. Numerical recipes */\n      double g = exp (-L);\n      int em = -1;\n      double t = 1.0;\n      do\n        {\n          ++em;\n          t *= rand_uniform<T> ();\n        }\n      while (t > g);\n      ret = em;\n    }\n  else if (L <= 1e8)\n    {\n      /* numerical recipes */\n      poisson_rejection<T> (L, &ret, 1);\n    }\n  else if (math::isinf (L))\n    {\n      /* FIXME: R uses NaN, but the normal approximation suggests that\n       * limit should be Inf.  Which is correct? */\n      ret = numeric_limits<T>::NaN ();\n    }\n  else\n    {\n      /* normal approximation: from Phys. Rev. D, Vol. 50, p1284, 1994. */\n      ret = std::floor (rand_normal<T> () * std::sqrt (L) + L + 0.5);\n      if (ret < 0.0) ret = 0.0; /* will probably never happen */\n    }\n  return ret;\n}\n\ntemplate OCTAVE_API double rand_poisson<double> (double);\ntemplate OCTAVE_API float rand_poisson<float> (float);\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/randpoisson.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/* Original version written by Paul Kienzle distributed as free\n   software in the in the public domain.  */\n\n#if ! defined (octave_randpoisson_h)\n#define octave_randpoisson_h 1\n\n#include \"octave-config.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T> OCTAVE_API void rand_poisson (T L, octave_idx_type n, T *p);\n\ntemplate <typename T> OCTAVE_API T rand_poisson (T L);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/ranlib-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_ranlib_proto_h)\n#define octave_ranlib_proto_h 1\n\n#include \"octave-config.h\"\n\n#include \"f77-fcn.h\"\n\nextern \"C\"\n{\n  F77_RET_T\n  F77_FUNC (dgenexp, DGENEXP) (const F77_DBLE&, F77_DBLE&);\n\n  F77_RET_T\n  F77_FUNC (dgengam, DGENGAM) (const F77_DBLE&, const F77_DBLE&, F77_DBLE&);\n\n  F77_RET_T\n  F77_FUNC (dgennor, DGENNOR) (const F77_DBLE&, const F77_DBLE&, F77_DBLE&);\n\n  F77_RET_T\n  F77_FUNC (dgenunf, DGENUNF) (const F77_DBLE&, const F77_DBLE&, F77_DBLE&);\n\n  F77_RET_T\n  F77_FUNC (dignpoi, DIGNPOI) (const F77_DBLE&, F77_DBLE&);\n\n  F77_RET_T\n  F77_FUNC (fgenexp, FGENEXP) (const F77_REAL&, F77_REAL&);\n\n  F77_RET_T\n  F77_FUNC (fgengam, FGENGAM) (const F77_REAL&, const F77_REAL&, F77_REAL&);\n\n  F77_RET_T\n  F77_FUNC (fgennor, FGENNOR) (const F77_REAL&, const F77_REAL&, F77_REAL&);\n\n  F77_RET_T\n  F77_FUNC (fgenunf, FGENUNF) (const F77_REAL&, const F77_REAL&, F77_REAL&);\n\n  F77_RET_T\n  F77_FUNC (fignpoi, FIGNPOI) (const F77_REAL&, F77_REAL&);\n\n  F77_RET_T\n  F77_FUNC (getsd, GETSD) (F77_INT4&, F77_INT4&);\n\n  F77_RET_T\n  F77_FUNC (setall, SETALL) (const F77_INT4&, const F77_INT4&);\n\n  F77_RET_T\n  F77_FUNC (setcgn, SETCGN) (const F77_INT4&);\n\n  F77_RET_T\n  F77_FUNC (setsd, SETSD) (const F77_INT4&, const F77_INT4&);\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/schur.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"Array-oct.h\"\n#include \"CMatrix.h\"\n#include \"dMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"fMatrix.h\"\n#include \"lapack-proto.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"schur.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\n// For real types.\n\nstatic F77_INT\nselect_ana (const double& a, const double&)\n{\n  return (a < 0.0);\n}\n\nstatic F77_INT\nselect_dig (const double& a, const double& b)\n{\n  return (hypot (a, b) < 1.0);\n}\n\nstatic F77_INT\nselect_ana (const float& a, const float&)\n{\n  return (a < 0.0);\n}\n\nstatic F77_INT\nselect_dig (const float& a, const float& b)\n{\n  return (hypot (a, b) < 1.0);\n}\n\n// For complex types.\n\nstatic F77_INT\nselect_ana (const F77_DBLE_CMPLX& a_arg)\n{\n  const Complex a = reinterpret_cast<const Complex&> (a_arg);\n  return a.real () < 0.0;\n}\n\nstatic F77_INT\nselect_dig (const F77_DBLE_CMPLX& a_arg)\n{\n  const Complex& a = reinterpret_cast<const Complex&> (a_arg);\n  return (abs (a) < 1.0);\n}\n\nstatic F77_INT\nselect_ana (const F77_CMPLX& a_arg)\n{\n  const FloatComplex& a = reinterpret_cast<const FloatComplex&> (a_arg);\n  return a.real () < 0.0;\n}\n\nstatic F77_INT\nselect_dig (const F77_CMPLX& a_arg)\n{\n  const FloatComplex& a = reinterpret_cast<const FloatComplex&> (a_arg);\n  return (abs (a) < 1.0);\n}\n\ntemplate <>\nOCTAVE_API F77_INT\nschur<Matrix>::init (const Matrix& a, const std::string& ord,\n                     bool calc_unitary)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.cols ());\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"schur: requires square matrix\");\n\n  if (a_nr == 0)\n    {\n      m_schur_mat.clear ();\n      m_unitary_schur_mat.clear ();\n      return 0;\n    }\n\n  // Workspace requirements may need to be fixed if any of the\n  // following change.\n\n  char jobvs;\n  char sense = 'N';\n  char sort = 'N';\n\n  if (calc_unitary)\n    jobvs = 'V';\n  else\n    jobvs = 'N';\n\n  char ord_char = (ord.empty () ? 'U' : ord[0]);\n\n  if (ord_char == 'A' || ord_char == 'D'\n      || ord_char == 'a' || ord_char == 'd')\n    sort = 'S';\n\n  double_selector selector = nullptr;\n  if (ord_char == 'A' || ord_char == 'a')\n    selector = select_ana;\n  else if (ord_char == 'D' || ord_char == 'd')\n    selector = select_dig;\n\n  F77_INT n = a_nc;\n  F77_INT lwork = 8 * n;\n  F77_INT liwork = 1;\n  F77_INT info;\n  F77_INT sdim;\n  double rconde;\n  double rcondv;\n\n  m_schur_mat = a;\n\n  if (calc_unitary)\n    m_unitary_schur_mat.clear (n, n);\n\n  double *s = m_schur_mat.rwdata ();\n  double *q = m_unitary_schur_mat.rwdata ();\n\n  Array<double> wr (dim_vector (n, 1));\n  double *pwr = wr.rwdata ();\n\n  Array<double> wi (dim_vector (n, 1));\n  double *pwi = wi.rwdata ();\n\n  Array<double> work (dim_vector (lwork, 1));\n  double *pwork = work.rwdata ();\n\n  // BWORK is not referenced for the non-ordered Schur routine.\n  F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;\n  Array<F77_INT> bwork (dim_vector (ntmp, 1));\n  F77_INT *pbwork = bwork.rwdata ();\n\n  Array<F77_INT> iwork (dim_vector (liwork, 1));\n  F77_INT *piwork = iwork.rwdata ();\n\n  F77_XFCN (dgeesx, DGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),\n                             F77_CONST_CHAR_ARG2 (&sort, 1),\n                             selector,\n                             F77_CONST_CHAR_ARG2 (&sense, 1),\n                             n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv,\n                             pwork, lwork, piwork, liwork, pbwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API F77_INT\nschur<FloatMatrix>::init (const FloatMatrix& a, const std::string& ord,\n                          bool calc_unitary)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.cols ());\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"SCHUR requires square matrix\");\n\n  if (a_nr == 0)\n    {\n      m_schur_mat.clear ();\n      m_unitary_schur_mat.clear ();\n      return 0;\n    }\n\n  // Workspace requirements may need to be fixed if any of the\n  // following change.\n\n  char jobvs;\n  char sense = 'N';\n  char sort = 'N';\n\n  if (calc_unitary)\n    jobvs = 'V';\n  else\n    jobvs = 'N';\n\n  char ord_char = (ord.empty () ? 'U' : ord[0]);\n\n  if (ord_char == 'A' || ord_char == 'D'\n      || ord_char == 'a' || ord_char == 'd')\n    sort = 'S';\n\n  float_selector selector = nullptr;\n  if (ord_char == 'A' || ord_char == 'a')\n    selector = select_ana;\n  else if (ord_char == 'D' || ord_char == 'd')\n    selector = select_dig;\n\n  F77_INT n = a_nc;\n  F77_INT lwork = 8 * n;\n  F77_INT liwork = 1;\n  F77_INT info;\n  F77_INT sdim;\n  float rconde;\n  float rcondv;\n\n  m_schur_mat = a;\n\n  if (calc_unitary)\n    m_unitary_schur_mat.clear (n, n);\n\n  float *s = m_schur_mat.rwdata ();\n  float *q = m_unitary_schur_mat.rwdata ();\n\n  Array<float> wr (dim_vector (n, 1));\n  float *pwr = wr.rwdata ();\n\n  Array<float> wi (dim_vector (n, 1));\n  float *pwi = wi.rwdata ();\n\n  Array<float> work (dim_vector (lwork, 1));\n  float *pwork = work.rwdata ();\n\n  // BWORK is not referenced for the non-ordered Schur routine.\n  F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;\n  Array<F77_INT> bwork (dim_vector (ntmp, 1));\n  F77_INT *pbwork = bwork.rwdata ();\n\n  Array<F77_INT> iwork (dim_vector (liwork, 1));\n  F77_INT *piwork = iwork.rwdata ();\n\n  F77_XFCN (sgeesx, SGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),\n                             F77_CONST_CHAR_ARG2 (&sort, 1),\n                             selector,\n                             F77_CONST_CHAR_ARG2 (&sense, 1),\n                             n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv,\n                             pwork, lwork, piwork, liwork, pbwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API F77_INT\nschur<ComplexMatrix>::init (const ComplexMatrix& a, const std::string& ord,\n                            bool calc_unitary)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.cols ());\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"SCHUR requires square matrix\");\n\n  if (a_nr == 0)\n    {\n      m_schur_mat.clear ();\n      m_unitary_schur_mat.clear ();\n      return 0;\n    }\n\n  // Workspace requirements may need to be fixed if any of the\n  // following change.\n\n  char jobvs;\n  char sense = 'N';\n  char sort = 'N';\n\n  if (calc_unitary)\n    jobvs = 'V';\n  else\n    jobvs = 'N';\n\n  char ord_char = (ord.empty () ? 'U' : ord[0]);\n\n  if (ord_char == 'A' || ord_char == 'D'\n      || ord_char == 'a' || ord_char == 'd')\n    sort = 'S';\n\n  complex_selector selector = nullptr;\n  if (ord_char == 'A' || ord_char == 'a')\n    selector = select_ana;\n  else if (ord_char == 'D' || ord_char == 'd')\n    selector = select_dig;\n\n  F77_INT n = a_nc;\n  F77_INT lwork = 8 * n;\n  F77_INT info;\n  F77_INT sdim;\n  double rconde;\n  double rcondv;\n\n  m_schur_mat = a;\n  if (calc_unitary)\n    m_unitary_schur_mat.clear (n, n);\n\n  Complex *s = m_schur_mat.rwdata ();\n  Complex *q = m_unitary_schur_mat.rwdata ();\n\n  Array<double> rwork (dim_vector (n, 1));\n  double *prwork = rwork.rwdata ();\n\n  Array<Complex> w (dim_vector (n, 1));\n  Complex *pw = w.rwdata ();\n\n  Array<Complex> work (dim_vector (lwork, 1));\n  Complex *pwork = work.rwdata ();\n\n  // BWORK is not referenced for non-ordered Schur.\n  F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;\n  Array<F77_INT> bwork (dim_vector (ntmp, 1));\n  F77_INT *pbwork = bwork.rwdata ();\n\n  F77_XFCN (zgeesx, ZGEESX,\n            (F77_CONST_CHAR_ARG2 (&jobvs, 1),\n             F77_CONST_CHAR_ARG2 (&sort, 1),\n             selector,\n             F77_CONST_CHAR_ARG2 (&sense, 1),\n             n, F77_DBLE_CMPLX_ARG (s), n, sdim, F77_DBLE_CMPLX_ARG (pw),\n             F77_DBLE_CMPLX_ARG (q), n, rconde, rcondv,\n             F77_DBLE_CMPLX_ARG (pwork), lwork, prwork, pbwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API schur<ComplexMatrix>\nrsf2csf<ComplexMatrix, Matrix> (const Matrix& s_arg, const Matrix& u_arg)\n{\n  ComplexMatrix s (s_arg);\n  ComplexMatrix u (u_arg);\n\n  F77_INT n = to_f77_int (s.rows ());\n\n  if (s.columns () != n || u.rows () != n || u.columns () != n)\n    (*current_liboctave_error_handler)\n      (\"rsf2csf: inconsistent matrix dimensions\");\n\n  if (n > 0)\n    {\n      OCTAVE_LOCAL_BUFFER (double, c, n-1);\n      OCTAVE_LOCAL_BUFFER (double, sx, n-1);\n\n      F77_XFCN (zrsf2csf, ZRSF2CSF,\n                (n, F77_DBLE_CMPLX_ARG (s.rwdata ()),\n                 F77_DBLE_CMPLX_ARG (u.rwdata ()), c, sx));\n    }\n\n  return schur<ComplexMatrix> (s, u);\n}\n\ntemplate <>\nOCTAVE_API F77_INT\nschur<FloatComplexMatrix>::init (const FloatComplexMatrix& a,\n                                 const std::string& ord, bool calc_unitary)\n{\n  F77_INT a_nr = to_f77_int (a.rows ());\n  F77_INT a_nc = to_f77_int (a.cols ());\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler) (\"SCHUR requires square matrix\");\n\n  if (a_nr == 0)\n    {\n      m_schur_mat.clear ();\n      m_unitary_schur_mat.clear ();\n      return 0;\n    }\n\n  // Workspace requirements may need to be fixed if any of the\n  // following change.\n\n  char jobvs;\n  char sense = 'N';\n  char sort = 'N';\n\n  if (calc_unitary)\n    jobvs = 'V';\n  else\n    jobvs = 'N';\n\n  char ord_char = (ord.empty () ? 'U' : ord[0]);\n\n  if (ord_char == 'A' || ord_char == 'D'\n      || ord_char == 'a' || ord_char == 'd')\n    sort = 'S';\n\n  float_complex_selector selector = nullptr;\n  if (ord_char == 'A' || ord_char == 'a')\n    selector = select_ana;\n  else if (ord_char == 'D' || ord_char == 'd')\n    selector = select_dig;\n\n  F77_INT n = a_nc;\n  F77_INT lwork = 8 * n;\n  F77_INT info;\n  F77_INT sdim;\n  float rconde;\n  float rcondv;\n\n  m_schur_mat = a;\n  if (calc_unitary)\n    m_unitary_schur_mat.clear (n, n);\n\n  FloatComplex *s = m_schur_mat.rwdata ();\n  FloatComplex *q = m_unitary_schur_mat.rwdata ();\n\n  Array<float> rwork (dim_vector (n, 1));\n  float *prwork = rwork.rwdata ();\n\n  Array<FloatComplex> w (dim_vector (n, 1));\n  FloatComplex *pw = w.rwdata ();\n\n  Array<FloatComplex> work (dim_vector (lwork, 1));\n  FloatComplex *pwork = work.rwdata ();\n\n  // BWORK is not referenced for non-ordered Schur.\n  F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;\n  Array<F77_INT> bwork (dim_vector (ntmp, 1));\n  F77_INT *pbwork = bwork.rwdata ();\n\n  F77_XFCN (cgeesx, CGEESX,\n            (F77_CONST_CHAR_ARG2 (&jobvs, 1),\n             F77_CONST_CHAR_ARG2 (&sort, 1),\n             selector,\n             F77_CONST_CHAR_ARG2 (&sense, 1),\n             n, F77_CMPLX_ARG (s), n, sdim, F77_CMPLX_ARG (pw),\n             F77_CMPLX_ARG (q), n,\n             rconde, rcondv,\n             F77_CMPLX_ARG (pwork), lwork, prwork, pbwork, info\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)\n             F77_CHAR_ARG_LEN (1)));\n\n  return info;\n}\n\ntemplate <>\nOCTAVE_API schur<FloatComplexMatrix>\nrsf2csf<FloatComplexMatrix, FloatMatrix> (const FloatMatrix& s_arg,\n    const FloatMatrix& u_arg)\n{\n  FloatComplexMatrix s (s_arg);\n  FloatComplexMatrix u (u_arg);\n\n  F77_INT n = to_f77_int (s.rows ());\n\n  if (s.columns () != n || u.rows () != n || u.columns () != n)\n    (*current_liboctave_error_handler)\n      (\"rsf2csf: inconsistent matrix dimensions\");\n\n  if (n > 0)\n    {\n      OCTAVE_LOCAL_BUFFER (float, c, n-1);\n      OCTAVE_LOCAL_BUFFER (float, sx, n-1);\n\n      F77_XFCN (crsf2csf, CRSF2CSF,\n                (n, F77_CMPLX_ARG (s.rwdata ()),\n                 F77_CMPLX_ARG (u.rwdata ()), c, sx));\n    }\n\n  return schur<FloatComplexMatrix> (s, u);\n}\n\n// Instantiations we need.\n\ntemplate class schur<ComplexMatrix>;\n\ntemplate class schur<FloatComplexMatrix>;\n\ntemplate class schur<FloatMatrix>;\n\ntemplate class schur<Matrix>;\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/schur.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_schur_h)\n#define octave_schur_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n// FIXME: Don't really need these for compiling schur.h, but it messes\n// up compilation in liboctave/array if these are not present.\n#include \"CMatrix.h\"\n#include \"dMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"fMatrix.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nclass schur\n{\npublic:\n\n  schur () : m_schur_mat (), m_unitary_schur_mat () { }\n\n  schur (const T& a, const std::string& ord, bool calc_unitary = true)\n    : m_schur_mat (), m_unitary_schur_mat ()\n  {\n    init (a, ord, calc_unitary);\n  }\n\n  schur (const T& a, const std::string& ord, octave_f77_int_type& info,\n         bool calc_unitary = true)\n    : m_schur_mat (), m_unitary_schur_mat ()\n  {\n    info = init (a, ord, calc_unitary);\n  }\n\n  // This one should really be protected or private but we need it in\n  // rsf2csf and I don't see how to make that function a friend of\n  // this class.\n  schur (const T& s, const T& u) : m_schur_mat (s), m_unitary_schur_mat (u)\n  { }\n\n  schur (const schur& a)\n    : m_schur_mat (a.m_schur_mat),\n      m_unitary_schur_mat (a.m_unitary_schur_mat)\n  { }\n\n  schur& operator = (const schur& a)\n  {\n    if (this != &a)\n      {\n        m_schur_mat = a.m_schur_mat;\n        m_unitary_schur_mat = a.m_unitary_schur_mat;\n      }\n\n    return *this;\n  }\n\n  ~schur () = default;\n\n  T schur_matrix () const { return m_schur_mat; }\n\n  T unitary_schur_matrix () const { return m_unitary_schur_mat; }\n\nprotected:\n\nprivate:\n\n  T m_schur_mat;\n  T m_unitary_schur_mat;\n\n  OCTAVE_API octave_f77_int_type\n  init (const T& a, const std::string& ord, bool calc_unitary);\n};\n\ntemplate <typename RT, typename AT>\nextern OCTAVE_API schur<RT>\nrsf2csf (const AT& s, const AT& u);\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/slatec-proto.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_slatec_proto_h)\n#define octave_slatec_proto_h 1\n\n#include \"octave-config.h\"\n\n#include \"f77-fcn.h\"\n\nextern \"C\"\n{\n  // PCHIM\n\n  F77_RET_T\n  F77_FUNC (dpchim, DPCHIM) (const F77_INT& n, const F77_DBLE *x,\n                             const F77_DBLE *f, F77_DBLE *d,\n                             const F77_INT& incfd,\n                             F77_INT& ierr);\n\n  F77_RET_T\n  F77_FUNC (pchim, PCHIM) (const F77_INT& n, const F77_REAL *x,\n                           const F77_REAL *f, F77_REAL *d,\n                           const F77_INT& incfd,\n                           F77_INT& ierr);\n\n  // PSIFN\n\n  F77_RET_T\n  F77_FUNC (psifn, PSIFN) (const F77_REAL&, const F77_INT&,\n                           const F77_INT&, const F77_INT&,\n                           F77_REAL&, F77_INT&, F77_INT&);\n\n  F77_RET_T\n  F77_FUNC (dpsifn, DPSIFN) (const F77_DBLE&, const F77_INT&,\n                             const F77_INT&, const F77_INT&,\n                             F77_DBLE&, F77_INT&, F77_INT&);\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/sparse-chol.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstddef>\n\n#include \"CSparse.h\"\n#include \"MatrixType.h\"\n#include \"dRowVector.h\"\n#include \"dSparse.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-error.h\"\n#include \"oct-sparse.h\"\n#include \"oct-spparms.h\"\n#include \"quit.h\"\n#include \"sparse-chol.h\"\n#include \"sparse-util.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename chol_type>\nclass sparse_chol<chol_type>::sparse_chol_rep\n{\npublic:\n\n  sparse_chol_rep ()\n    : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0)\n#if defined (HAVE_CHOLMOD)\n    , m_L (nullptr), m_common ()\n#endif\n  { }\n\n  sparse_chol_rep (const chol_type& a, bool natural, bool force)\n    : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0)\n#if defined (HAVE_CHOLMOD)\n    , m_L (nullptr), m_common ()\n#endif\n  {\n    init (a, natural, force);\n  }\n\n  sparse_chol_rep (const chol_type& a, octave_idx_type& info,\n                   bool natural, bool force)\n    : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0)\n#if defined (HAVE_CHOLMOD)\n    , m_L (nullptr), m_common ()\n#endif\n  {\n    info = init (a, natural, force);\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (sparse_chol_rep)\n\n  ~sparse_chol_rep ()\n  {\n#if defined (HAVE_CHOLMOD)\n    if (m_L)\n      CHOLMOD_NAME (free_sparse) (&m_L, &m_common);\n\n    CHOLMOD_NAME(finish) (&m_common);\n#endif\n  }\n\n#if defined (HAVE_CHOLMOD)\n  cholmod_sparse * L () const\n  {\n    return m_L;\n  }\n\n  cholmod_common * cc () const\n  {\n    cholmod_common *ret = const_cast<cholmod_common *> (&m_common);\n    return ret;\n  }\n\n#endif\n\n  octave_idx_type P () const\n  {\n#if defined (HAVE_CHOLMOD)\n    return (m_minor_p == from_size_t (m_L->ncol) ? 0 : m_minor_p + 1);\n#else\n    return 0;\n#endif\n  }\n\n  RowVector perm () const { return m_perm + 1; }\n\n  SparseMatrix Q () const;\n\n  bool is_positive_definite () const { return m_is_pd; }\n\n  double rcond () const { return m_rcond; }\n\nprivate:\n\n  bool m_is_pd;\n\n  octave_idx_type m_minor_p;\n\n  RowVector m_perm;\n\n  double m_rcond;\n\n#if defined (HAVE_CHOLMOD)\n  cholmod_sparse *m_L;\n\n  cholmod_common m_common;\n\n  void drop_zeros (const cholmod_sparse *S);\n#endif\n\n  octave_idx_type init (const chol_type& a, bool natural, bool force);\n};\n\n#if defined (HAVE_CHOLMOD)\n\n// Can't use CHOLMOD_NAME(drop)(0.0, S, cm) because it doesn't treat\n// complex matrices.\n\ntemplate <typename chol_type>\nvoid\nsparse_chol<chol_type>::sparse_chol_rep::drop_zeros (const cholmod_sparse *S)\n{\n  if (! S)\n    return;\n\n  octave_idx_type *Sp = static_cast<octave_idx_type *> (S->p);\n  octave_idx_type *Si = static_cast<octave_idx_type *> (S->i);\n  chol_elt *Sx = static_cast<chol_elt *> (S->x);\n\n  octave_idx_type pdest = 0;\n  octave_idx_type ncol = S->ncol;\n\n  for (octave_idx_type k = 0; k < ncol; k++)\n    {\n      octave_idx_type p = Sp[k];\n      octave_idx_type pend = Sp[k+1];\n      Sp[k] = pdest;\n\n      for (; p < pend; p++)\n        {\n          chol_elt sik = Sx[p];\n\n          if (CHOLMOD_IS_NONZERO (sik))\n            {\n              if (p != pdest)\n                {\n                  Si[pdest] = Si[p];\n                  Sx[pdest] = sik;\n                }\n\n              pdest++;\n            }\n        }\n    }\n\n  Sp[ncol] = pdest;\n}\n\n// Must provide a specialization for this function.\ntemplate <typename T>\nint\nget_xtype ();\n\ntemplate <>\ninline int\nget_xtype<double> ()\n{\n  return CHOLMOD_REAL;\n}\n\ntemplate <>\ninline int\nget_xtype<Complex> ()\n{\n  return CHOLMOD_COMPLEX;\n}\n\n#endif\n\ntemplate <typename chol_type>\noctave_idx_type\nsparse_chol<chol_type>::sparse_chol_rep::init (const chol_type& a,\n    bool natural, bool force)\n{\n  octave_idx_type info = 0;\n\n#if defined (HAVE_CHOLMOD)\n\n  octave_idx_type a_nr = a.rows ();\n  octave_idx_type a_nc = a.cols ();\n\n  if (a_nr != a_nc)\n    (*current_liboctave_error_handler)\n      (\"sparse_chol requires square matrix\");\n\n  cholmod_common *cm = &m_common;\n\n  // Setup initial parameters\n\n  CHOLMOD_NAME(start) (cm);\n  cm->prefer_zomplex = false;\n\n  double spu = sparse_params::get_key (\"spumoni\");\n\n  if (spu == 0.)\n    {\n      cm->print = -1;\n      SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr);\n    }\n  else\n    {\n      cm->print = static_cast<int> (spu) + 2;\n      SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function,\n                               &SparseCholPrint);\n    }\n\n  cm->error_handler = &SparseCholError;\n\n  SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide,\n                            divcomplex);\n\n  SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);\n\n  cm->final_asis = false;\n  cm->final_super = false;\n  cm->final_ll = true;\n  cm->final_pack = true;\n  cm->final_monotonic = true;\n  cm->final_resymbol = false;\n\n  cholmod_sparse A;\n  cholmod_sparse *ac = &A;\n  double dummy;\n\n  ac->nrow = a_nr;\n  ac->ncol = a_nc;\n\n  ac->p = const_cast<octave_idx_type *> (a.cidx ());\n  ac->i = const_cast<octave_idx_type *> (a.ridx ());\n  ac->nzmax = a.nnz ();\n  ac->packed = true;\n  ac->sorted = true;\n  ac->nz = nullptr;\n#if defined (OCTAVE_ENABLE_64)\n  ac->itype = CHOLMOD_LONG;\n#else\n  ac->itype = CHOLMOD_INT;\n#endif\n  ac->dtype = CHOLMOD_DOUBLE;\n  ac->stype = 1;\n  ac->xtype = get_xtype<chol_elt> ();\n\n  if (a_nr < 1)\n    ac->x = &dummy;\n  else\n    ac->x = const_cast<chol_elt *> (a.data ());\n\n  // use natural ordering if no q output parameter\n  if (natural)\n    {\n      cm->nmethods = 1;\n      cm->method[0].ordering = CHOLMOD_NATURAL;\n      cm->postorder = false;\n    }\n\n  cholmod_factor *Lfactor = CHOLMOD_NAME(analyze) (ac, cm);\n  CHOLMOD_NAME(factorize) (ac, Lfactor, cm);\n\n  m_is_pd = cm->status == CHOLMOD_OK;\n  info = (m_is_pd ? 0 : cm->status);\n\n  if (m_is_pd || force)\n    {\n      m_rcond = CHOLMOD_NAME(rcond) (Lfactor, cm);\n\n      m_minor_p = Lfactor->minor;\n\n      m_L = CHOLMOD_NAME(factor_to_sparse) (Lfactor, cm);\n\n      if (m_minor_p > 0 && m_minor_p < a_nr)\n        {\n          std::size_t n1 = a_nr + 1;\n          m_L->p = CHOLMOD_NAME(realloc) (m_minor_p+1,\n                                          sizeof(octave_idx_type),\n                                          m_L->p, &n1, cm);\n\n          CHOLMOD_NAME(reallocate_sparse)\n          (static_cast<octave_idx_type *> (m_L->p)[m_minor_p],\n           m_L, cm);\n\n          m_L->ncol = m_minor_p;\n        }\n\n      drop_zeros (m_L);\n\n      if (! natural)\n        {\n          m_perm.resize (a_nr);\n          for (octave_idx_type i = 0; i < a_nr; i++)\n            m_perm(i) = static_cast<octave_idx_type *> (Lfactor->Perm)[i];\n        }\n    }\n\n  // NAME used to prefix statistics report from print_common\n  static char blank_name[] = \" \";\n\n  CHOLMOD_NAME(print_common) (blank_name, cm);\n  CHOLMOD_NAME(free_factor) (&Lfactor, cm);\n\n  return info;\n\n#else\n\n  octave_unused_parameter (a);\n  octave_unused_parameter (natural);\n  octave_unused_parameter (force);\n\n  (*current_liboctave_error_handler)\n    (\"support for CHOLMOD was unavailable or disabled when liboctave was built\");\n\n  return info;\n\n#endif\n}\n\ntemplate <typename chol_type>\nSparseMatrix\nsparse_chol<chol_type>::sparse_chol_rep::Q () const\n{\n#if defined (HAVE_CHOLMOD)\n\n  octave_idx_type n = m_L->nrow;\n  SparseMatrix p (n, n, n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    {\n      p.xcidx (i) = i;\n      p.xridx (i) = static_cast<octave_idx_type> (m_perm (i));\n      p.xdata (i) = 1;\n    }\n\n  p.xcidx (n) = n;\n\n  return p;\n\n#else\n\n  return SparseMatrix ();\n\n#endif\n}\n\ntemplate <typename chol_type>\nsparse_chol<chol_type>::sparse_chol ()\n  : m_rep (new typename sparse_chol<chol_type>::sparse_chol_rep ())\n{ }\n\ntemplate <typename chol_type>\nsparse_chol<chol_type>::sparse_chol (const chol_type& a, bool natural,\n                                     bool force)\n  : m_rep (new typename\n           sparse_chol<chol_type>::sparse_chol_rep (a, natural, force))\n{ }\n\ntemplate <typename chol_type>\nsparse_chol<chol_type>::sparse_chol (const chol_type& a,\n                                     octave_idx_type& info,\n                                     bool natural, bool force)\n  : m_rep (new typename\n           sparse_chol<chol_type>::sparse_chol_rep (a, info, natural, force))\n{ }\n\ntemplate <typename chol_type>\nsparse_chol<chol_type>::sparse_chol (const chol_type& a,\n                                     octave_idx_type& info,\n                                     bool natural)\n  : m_rep (new typename\n           sparse_chol<chol_type>::sparse_chol_rep (a, info, natural, false))\n{ }\n\ntemplate <typename chol_type>\nsparse_chol<chol_type>::sparse_chol (const chol_type& a,\n                                     octave_idx_type& info)\n  : m_rep (new typename\n           sparse_chol<chol_type>::sparse_chol_rep (a, info, false, false))\n{ }\n\ntemplate <typename chol_type>\nchol_type\nsparse_chol<chol_type>::L () const\n{\n#if defined (HAVE_CHOLMOD)\n\n  cholmod_sparse *m = m_rep->L ();\n\n  octave_idx_type nc = m->ncol;\n  octave_idx_type nnz\n    = from_suitesparse_long (CHOLMOD_NAME(nnz) (m, m_rep->cc ()));\n\n  chol_type ret (m->nrow, nc, nnz);\n\n  for (octave_idx_type j = 0; j < nc+1; j++)\n    ret.xcidx (j) = static_cast<octave_idx_type *> (m->p)[j];\n\n  for (octave_idx_type i = 0; i < nnz; i++)\n    {\n      ret.xridx (i) = static_cast<octave_idx_type *> (m->i)[i];\n      ret.xdata (i) = static_cast<chol_elt *> (m->x)[i];\n    }\n\n  return ret;\n\n#else\n\n  return chol_type ();\n\n#endif\n}\n\ntemplate <typename chol_type>\noctave_idx_type\nsparse_chol<chol_type>::P () const\n{\n  return m_rep->P ();\n}\n\ntemplate <typename chol_type>\nRowVector\nsparse_chol<chol_type>::perm () const\n{\n  return m_rep->perm ();\n}\n\ntemplate <typename chol_type>\nSparseMatrix\nsparse_chol<chol_type>::Q () const\n{\n  return m_rep->Q ();\n}\n\ntemplate <typename chol_type>\nbool\nsparse_chol<chol_type>::is_positive_definite () const\n{\n  return m_rep->is_positive_definite ();\n}\n\ntemplate <typename chol_type>\ndouble\nsparse_chol<chol_type>::rcond () const\n{\n  return m_rep->rcond ();\n}\n\ntemplate <typename chol_type>\nchol_type\nsparse_chol<chol_type>::inverse () const\n{\n  chol_type retval;\n\n#if defined (HAVE_CHOLMOD)\n\n  cholmod_sparse *m = m_rep->L ();\n  octave_idx_type n = m->ncol;\n  RowVector m_perm = m_rep->perm ();\n  double rcond2;\n  octave_idx_type info;\n  MatrixType mattype (MatrixType::Upper);\n  chol_type linv = L ().hermitian ().inverse (mattype, info, rcond2, 1, 0);\n\n  if (m_perm.numel () == n)\n    {\n      SparseMatrix Qc = Q ();\n\n      retval = Qc * linv * linv.hermitian () * Qc.transpose ();\n    }\n  else\n    retval = linv * linv.hermitian ();\n\n#endif\n\n  return retval;\n}\n\ntemplate <typename chol_type>\nchol_type\nchol2inv (const chol_type& r)\n{\n  octave_idx_type r_nr = r.rows ();\n  octave_idx_type r_nc = r.cols ();\n  chol_type retval;\n\n  if (r_nr != r_nc)\n    (*current_liboctave_error_handler) (\"U must be a square matrix\");\n\n  MatrixType mattype (r);\n  int typ = mattype.type (false);\n  double rcond;\n  octave_idx_type info;\n  chol_type rtra, multip;\n\n  if (typ == MatrixType::Upper)\n    {\n      rtra = r.transpose ();\n      multip = (rtra*r);\n    }\n  else if (typ == MatrixType::Lower)\n    {\n      rtra = r.transpose ();\n      multip = (r*rtra);\n    }\n  else\n    (*current_liboctave_error_handler) (\"U must be a triangular matrix\");\n\n  MatrixType mattypenew (multip);\n  retval = multip.inverse (mattypenew, info, rcond, true, false);\n  return retval;\n}\n\n// SparseComplexMatrix specialization (the value for the NATURAL\n// parameter in the sparse_chol<T>::sparse_chol_rep constructor is\n// different from the default).\n\ntemplate <>\nOCTAVE_API\nsparse_chol<SparseComplexMatrix>::sparse_chol (const SparseComplexMatrix& a,\n    octave_idx_type& info)\n  : m_rep (new sparse_chol<SparseComplexMatrix>::sparse_chol_rep (a, info,\n           true,\n           false))\n{ }\n\n// Instantiations we need.\n\ntemplate class OCTAVE_API sparse_chol<SparseMatrix>;\n\ntemplate class sparse_chol<SparseComplexMatrix>;\n\ntemplate OCTAVE_API SparseMatrix\nchol2inv<SparseMatrix> (const SparseMatrix& r);\n\ntemplate OCTAVE_API SparseComplexMatrix\nchol2inv<SparseComplexMatrix> (const SparseComplexMatrix& r);\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/sparse-chol.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_sparse_chol_h)\n#define octave_sparse_chol_h 1\n\n#include \"octave-config.h\"\n\n#include <memory>\n\n#include \"mx-fwd.h\"\n\n#include \"CSparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\n// If the sparse matrix classes become templated on the element type\n// (i.e., sparse_matrix<double>), then it might be best to make the\n// template parameter of this class also be the element type instead\n// of the matrix type.\n\ntemplate <typename chol_type>\nclass OCTAVE_API sparse_chol\n{\npublic:\n\n  sparse_chol ();\n\n  sparse_chol (const chol_type& a, bool natural, bool force);\n\n  sparse_chol (const chol_type& a, octave_idx_type& info,\n               bool natural, bool force);\n\n  sparse_chol (const chol_type& a, octave_idx_type& info, bool natural);\n\n  sparse_chol (const chol_type& a, octave_idx_type& info);\n\n  sparse_chol (const sparse_chol<chol_type>& a) = default;\n\n  virtual ~sparse_chol () = default;\n\n  sparse_chol<chol_type>&\n  operator = (const sparse_chol<chol_type>& a) = default;\n\n  chol_type L () const;\n\n  chol_type R () const { return L ().hermitian (); }\n\n  octave_idx_type P () const;\n\n  RowVector perm () const;\n\n  SparseMatrix Q () const;\n\n  bool is_positive_definite () const;\n\n  double rcond () const;\n\n  chol_type inverse () const;\n\nprotected:\n\n  typedef typename chol_type::element_type chol_elt;\n\n  class sparse_chol_rep;\n\nprivate:\n\n  std::shared_ptr<sparse_chol_rep> m_rep;\n};\n\ntemplate <typename chol_type>\nOCTAVE_API\nchol_type\nchol2inv (const chol_type& r);\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/sparse-dmsolve.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n\n#include \"CMatrix.h\"\n#include \"CSparse.h\"\n#include \"MArray.h\"\n#include \"MSparse.h\"\n#include \"MatrixType.h\"\n#include \"dSparse.h\"\n#include \"oct-error.h\"\n#include \"oct-inttypes-fwd.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sort.h\"\n#include \"oct-sparse.h\"\n#include \"quit.h\"\n#include \"sparse-dmsolve.h\"\n#include \"sparse-qr.h\"\n\ntemplate <typename T>\nstatic MSparse<T>\ndmsolve_extract (const MSparse<T>& A, const octave_idx_type *Pinv,\n                 const octave_idx_type *Q, octave_idx_type rst,\n                 octave_idx_type rend, octave_idx_type cst,\n                 octave_idx_type cend, octave_idx_type maxnz = -1,\n                 bool lazy = false)\n{\n  octave_idx_type nr = rend - rst;\n  octave_idx_type nc = cend - cst;\n\n  maxnz = (maxnz < 0 ? A.nnz () : maxnz);\n\n  octave_idx_type nz;\n\n  // Cast to uint64 to handle overflow in this multiplication\n  if (octave_uint64 (nr)*octave_uint64 (nc) < octave_uint64 (maxnz))\n    nz = nr*nc;\n  else\n    nz = maxnz;\n\n  MSparse<T> B (nr, nc, (nz < maxnz ? nz : maxnz));\n\n  // Some sparse functions can support lazy indexing (where elements\n  // in the row are in no particular order), even though octave in\n  // general can't.  For those functions that can using it is a big\n  // win here in terms of speed.\n\n  if (lazy)\n    {\n      nz = 0;\n\n      for (octave_idx_type j = cst ; j < cend ; j++)\n        {\n          octave_idx_type qq = (Q ? Q[j] : j);\n\n          B.xcidx (j - cst) = nz;\n\n          for (octave_idx_type p = A.cidx (qq) ; p < A.cidx (qq+1) ; p++)\n            {\n              octave_quit ();\n\n              octave_idx_type r = (Pinv ? Pinv[A.ridx (p)] : A.ridx (p));\n\n              if (r >= rst && r < rend)\n                {\n                  B.xdata (nz) = A.data (p);\n                  B.xridx (nz++) = r - rst;\n                }\n            }\n        }\n\n      B.xcidx (cend - cst) = nz;\n    }\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (T, X, rend - rst);\n\n      octave_sort<octave_idx_type> sort;\n      octave_idx_type *ri = B.xridx ();\n\n      nz = 0;\n\n      for (octave_idx_type j = cst ; j < cend ; j++)\n        {\n          octave_idx_type qq = (Q ? Q[j] : j);\n\n          B.xcidx (j - cst) = nz;\n\n          for (octave_idx_type p = A.cidx (qq) ; p < A.cidx (qq+1) ; p++)\n            {\n              octave_quit ();\n\n              octave_idx_type r = (Pinv ? Pinv[A.ridx (p)] : A.ridx (p));\n\n              if (r >= rst && r < rend)\n                {\n                  X[r-rst] = A.data (p);\n                  B.xridx (nz++) = r - rst;\n                }\n            }\n\n          sort.sort (ri + B.xcidx (j - cst), nz - B.xcidx (j - cst));\n\n          for (octave_idx_type p = B.cidx (j - cst); p < nz; p++)\n            B.xdata (p) = X[B.xridx (p)];\n        }\n\n      B.xcidx (cend - cst) = nz;\n    }\n\n  return B;\n}\n\ntemplate <typename T>\nstatic MArray<T>\ndmsolve_extract (const MArray<T>& m, const octave_idx_type *,\n                 const octave_idx_type *, octave_idx_type r1,\n                 octave_idx_type r2, octave_idx_type c1,\n                 octave_idx_type c2)\n{\n  r2 -= 1;\n  c2 -= 1;\n\n  if (r1 > r2)\n    std::swap (r1, r2);\n\n  if (c1 > c2)\n    std::swap (c1, c2);\n\n  octave_idx_type new_r = r2 - r1 + 1;\n  octave_idx_type new_c = c2 - c1 + 1;\n\n  MArray<T> result (dim_vector (new_r, new_c));\n\n  for (octave_idx_type j = 0; j < new_c; j++)\n    {\n      for (octave_idx_type i = 0; i < new_r; i++)\n        result.xelem (i, j) = m.elem (r1+i, c1+j);\n    }\n\n  return result;\n}\n\ntemplate <typename T>\nstatic void\ndmsolve_insert (MArray<T>& a, const MArray<T>& b, const octave_idx_type *Q,\n                octave_idx_type r, octave_idx_type c)\n{\n  T *ax = a.rwdata ();\n\n  const T *bx = b.data ();\n\n  octave_idx_type anr = a.rows ();\n\n  octave_idx_type nr = b.rows ();\n  octave_idx_type nc = b.cols ();\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      octave_idx_type aoff = (c + j) * anr;\n      octave_idx_type boff = j * nr;\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          octave_quit ();\n          ax[Q[r + i] + aoff] = bx[i + boff];\n        }\n    }\n}\n\ntemplate <typename T>\nstatic void\ndmsolve_insert (MSparse<T>& a, const MSparse<T>& b, const octave_idx_type *Q,\n                octave_idx_type r, octave_idx_type c)\n{\n  octave_idx_type b_rows = b.rows ();\n  octave_idx_type b_cols = b.cols ();\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  OCTAVE_LOCAL_BUFFER (octave_idx_type, Qinv, nr);\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    Qinv[Q[i]] = i;\n\n  // First count the number of elements in the final array\n  octave_idx_type nel = a.xcidx (c) + b.nnz ();\n\n  if (c + b_cols < nc)\n    nel += a.xcidx (nc) - a.xcidx (c + b_cols);\n\n  for (octave_idx_type i = c; i < c + b_cols; i++)\n    {\n      for (octave_idx_type j = a.xcidx (i); j < a.xcidx (i+1); j++)\n        {\n          if (Qinv[a.xridx (j)] < r || Qinv[a.xridx (j)] >= r + b_rows)\n            nel++;\n        }\n    }\n\n  OCTAVE_LOCAL_BUFFER (T, X, nr);\n\n  octave_sort<octave_idx_type> sort;\n\n  MSparse<T> tmp (a);\n\n  a = MSparse<T> (nr, nc, nel);\n\n  octave_idx_type *ri = a.xridx ();\n\n  for (octave_idx_type i = 0; i < tmp.cidx (c); i++)\n    {\n      a.xdata (i) = tmp.xdata (i);\n      a.xridx (i) = tmp.xridx (i);\n    }\n\n  for (octave_idx_type i = 0; i < c + 1; i++)\n    a.xcidx (i) = tmp.xcidx (i);\n\n  octave_idx_type ii = a.xcidx (c);\n\n  for (octave_idx_type i = c; i < c + b_cols; i++)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = tmp.xcidx (i); j < tmp.xcidx (i+1); j++)\n        {\n          if (Qinv[tmp.xridx (j)] < r ||  Qinv[tmp.xridx (j)] >= r + b_rows)\n            {\n              X[tmp.xridx (j)] = tmp.xdata (j);\n              a.xridx (ii++) = tmp.xridx (j);\n            }\n        }\n\n      octave_quit ();\n\n      for (octave_idx_type j = b.cidx (i-c); j < b.cidx (i-c+1); j++)\n        {\n          X[Q[r + b.ridx (j)]] = b.data (j);\n          a.xridx (ii++) = Q[r + b.ridx (j)];\n        }\n\n      sort.sort (ri + a.xcidx (i), ii - a.xcidx (i));\n\n      for (octave_idx_type p = a.xcidx (i); p < ii; p++)\n        a.xdata (p) = X[a.xridx (p)];\n\n      a.xcidx (i+1) = ii;\n    }\n\n  for (octave_idx_type i = c + b_cols; i < nc; i++)\n    {\n      for (octave_idx_type j = tmp.xcidx (i); j < tmp.cidx (i+1); j++)\n        {\n          a.xdata (ii) = tmp.xdata (j);\n          a.xridx (ii++) = tmp.xridx (j);\n        }\n\n      a.xcidx (i+1) = ii;\n    }\n}\n\ntemplate <typename T, typename RT>\nstatic void\ndmsolve_permute (MArray<RT>& a, const MArray<T>& b, const octave_idx_type *p)\n{\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  const T *Bx = b.data ();\n\n  a.resize (dim_vector (b_nr, b_nc));\n\n  RT *Btx = a.rwdata ();\n\n  for (octave_idx_type j = 0; j < b_nc; j++)\n    {\n      octave_idx_type off = j * b_nr;\n      for (octave_idx_type i = 0; i < b_nr; i++)\n        {\n          octave_quit ();\n          Btx[p[i] + off] = Bx[ i + off];\n        }\n    }\n}\n\ntemplate <typename T, typename RT>\nstatic void\ndmsolve_permute (MSparse<RT>& a, const MSparse<T>& b, const octave_idx_type *p)\n{\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nz = b.nnz ();\n\n  octave_idx_type nz = 0;\n\n  a = MSparse<RT> (b_nr, b_nc, b_nz);\n  octave_sort<octave_idx_type> sort;\n  octave_idx_type *ri = a.xridx ();\n\n  OCTAVE_LOCAL_BUFFER (RT, X, b_nr);\n\n  a.xcidx (0) = 0;\n\n  for (octave_idx_type j = 0; j < b_nc; j++)\n    {\n      for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)\n        {\n          octave_quit ();\n          octave_idx_type r = p[b.ridx (i)];\n          X[r] = b.data (i);\n          a.xridx (nz++) = p[b.ridx (i)];\n        }\n\n      sort.sort (ri + a.xcidx (j), nz - a.xcidx (j));\n\n      for (octave_idx_type i = a.cidx (j); i < nz; i++)\n        {\n          octave_quit ();\n          a.xdata (i) = X[a.xridx (i)];\n        }\n\n      a.xcidx (j+1) = nz;\n    }\n}\n\n#if defined (HAVE_CXSPARSE)\n\nstatic void\nsolve_singularity_warning (double)\n{\n  // Dummy singularity handler so that LU solver doesn't flag\n  // an error for numerically rank defficient matrices\n}\n\n#endif\n\ntemplate <typename RT, typename ST, typename T>\nRT\ndmsolve (const ST& a, const T& b, octave_idx_type& info)\n{\n  RT retval;\n\n#if defined (HAVE_CXSPARSE)\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  if (nr < 0 || nc < 0 || nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch in solution of minimum norm problem\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    retval = RT (nc, b_nc, 0.0);\n  else\n    {\n      octave_idx_type nnz_remaining = a.nnz ();\n\n      CXSPARSE_DNAME () csm;\n\n      csm.m = nr;\n      csm.n = nc;\n      csm.x = nullptr;\n      csm.nz = -1;\n      csm.nzmax = a.nnz ();\n\n      // Cast away const on A, with full knowledge that CSparse won't touch it.\n      // Prevents the methods below from making a copy of the data.\n      csm.p = const_cast<octave::suitesparse_integer *>\n                (octave::to_suitesparse_intptr (a.cidx ()));\n      csm.i = const_cast<octave::suitesparse_integer *>\n                (octave::to_suitesparse_intptr (a.ridx ()));\n\n      CXSPARSE_DNAME (d) *dm = CXSPARSE_DNAME(_dmperm) (&csm, 0);\n      octave_idx_type *p = octave::to_octave_idx_type_ptr (dm->p);\n      octave_idx_type *q = octave::to_octave_idx_type_ptr (dm->q);\n\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, pinv, nr);\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        pinv[p[i]] = i;\n\n      RT btmp;\n      dmsolve_permute (btmp, b, pinv);\n      info = 0;\n\n      retval.resize (nc, b_nc);\n\n      // Leading over-determined block\n      if (dm->rr[2] < nr && dm->cc[3] < nc)\n        {\n          ST m = dmsolve_extract (a, pinv, q, dm->rr[2], nr, dm->cc[3], nc,\n                                  nnz_remaining, true);\n          nnz_remaining -= m.nnz ();\n          RT mtmp = octave::math::qrsolve (m, dmsolve_extract (btmp,\n                                                               nullptr, nullptr,\n                                                               dm->rr[2], b_nr,\n                                                               0, b_nc),\n                                           info);\n          dmsolve_insert (retval, mtmp, q, dm->cc[3], 0);\n\n          if (dm->rr[2] > 0 && ! info)\n            {\n              m = dmsolve_extract (a, pinv, q, 0, dm->rr[2],\n                                   dm->cc[3], nc, nnz_remaining, true);\n              nnz_remaining -= m.nnz ();\n              RT ctmp = dmsolve_extract (btmp, nullptr, nullptr,\n                                         0, dm->rr[2], 0, b_nc);\n              btmp.insert (ctmp - m * mtmp, 0, 0);\n            }\n        }\n\n      // Structurally non-singular blocks\n      // FIXME: Should use fine Dulmange-Mendelsohn decomposition here.\n      if (dm->rr[1] < dm->rr[2] && dm->cc[2] < dm->cc[3] && ! info)\n        {\n          ST m = dmsolve_extract (a, pinv, q, dm->rr[1], dm->rr[2],\n                                  dm->cc[2], dm->cc[3], nnz_remaining, false);\n          nnz_remaining -= m.nnz ();\n          RT btmp2 = dmsolve_extract (btmp, nullptr, nullptr,\n                                      dm->rr[1], dm->rr[2],\n                                      0, b_nc);\n          double rcond = 0.0;\n          MatrixType mtyp (MatrixType::Full);\n          RT mtmp = m.solve (mtyp, btmp2, info, rcond,\n                             solve_singularity_warning, false);\n          if (info != 0)\n            {\n              info = 0;\n              mtmp = octave::math::qrsolve (m, btmp2, info);\n            }\n\n          dmsolve_insert (retval, mtmp, q, dm->cc[2], 0);\n          if (dm->rr[1] > 0 && ! info)\n            {\n              m = dmsolve_extract (a, pinv, q, 0, dm->rr[1], dm->cc[2],\n                                   dm->cc[3], nnz_remaining, true);\n              nnz_remaining -= m.nnz ();\n              RT ctmp = dmsolve_extract (btmp, nullptr, nullptr,\n                                         0, dm->rr[1], 0, b_nc);\n              btmp.insert (ctmp - m * mtmp, 0, 0);\n            }\n        }\n\n      // Trailing under-determined block\n      if (dm->rr[1] > 0 && dm->cc[2] > 0 && ! info)\n        {\n          ST m = dmsolve_extract (a, pinv, q, 0, dm->rr[1], 0,\n                                  dm->cc[2], nnz_remaining, true);\n          RT mtmp = octave::math::qrsolve (m, dmsolve_extract (btmp, nullptr,\n                                                               nullptr, 0,\n                                                               dm->rr[1], 0,\n                                                               b_nc),\n                                           info);\n          dmsolve_insert (retval, mtmp, q, 0, 0);\n        }\n\n      CXSPARSE_DNAME (_dfree) (dm);\n    }\n\n#else\n\n  octave_unused_parameter (a);\n  octave_unused_parameter (b);\n  octave_unused_parameter (info);\n\n  (*current_liboctave_error_handler)\n    (\"support for CXSparse was unavailable or disabled when liboctave was built\");\n\n#endif\n\n  return retval;\n}\n\n// Instantiations we need.\n\ntemplate OCTAVE_API ComplexMatrix\ndmsolve<ComplexMatrix, SparseComplexMatrix, Matrix>\n  (const SparseComplexMatrix&, const Matrix&, octave_idx_type&);\n\ntemplate OCTAVE_API SparseComplexMatrix\ndmsolve<SparseComplexMatrix, SparseComplexMatrix, SparseMatrix>\n  (const SparseComplexMatrix&, const SparseMatrix&, octave_idx_type&);\n\ntemplate OCTAVE_API ComplexMatrix\ndmsolve<ComplexMatrix, SparseComplexMatrix, ComplexMatrix>\n  (const SparseComplexMatrix&, const ComplexMatrix&, octave_idx_type&);\n\ntemplate OCTAVE_API SparseComplexMatrix\ndmsolve<SparseComplexMatrix, SparseComplexMatrix, SparseComplexMatrix>\n  (const SparseComplexMatrix&, const SparseComplexMatrix&, octave_idx_type&);\n\ntemplate OCTAVE_API Matrix\ndmsolve<Matrix, SparseMatrix, Matrix>\n  (const SparseMatrix&, const Matrix&, octave_idx_type&);\n\ntemplate OCTAVE_API SparseMatrix\ndmsolve<SparseMatrix, SparseMatrix, SparseMatrix>\n  (const SparseMatrix&, const SparseMatrix&, octave_idx_type&);\n\ntemplate OCTAVE_API ComplexMatrix\ndmsolve<ComplexMatrix, SparseMatrix, ComplexMatrix>\n  (const SparseMatrix&, const ComplexMatrix&, octave_idx_type&);\n\ntemplate OCTAVE_API SparseComplexMatrix\ndmsolve<SparseComplexMatrix, SparseMatrix, SparseComplexMatrix>\n  (const SparseMatrix&, const SparseComplexMatrix&, octave_idx_type&);\n"
  },
  {
    "path": "liboctave/numeric/sparse-dmsolve.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_sparse_dmsolve_h)\n#define octave_sparse_dmsolve_h 1\n\n#include \"octave-config.h\"\n\ntemplate <typename RT, typename ST, typename T>\nOCTAVE_API RT\ndmsolve (const ST& a, const T& b, octave_idx_type& info);\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/sparse-lu.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"CSparse.h\"\n#include \"PermMatrix.h\"\n#include \"dSparse.h\"\n#include \"mappers.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sparse.h\"\n#include \"oct-spparms.h\"\n#include \"sparse-lu.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\n// Wrappers for SuiteSparse (formerly UMFPACK) functions that have\n// different names depending on the sparse matrix data type.\n//\n// All of these functions must be specialized to forward to the correct\n// SuiteSparse functions.\n\ntemplate <typename T>\nvoid\numfpack_defaults (double *Control);\n\ntemplate <typename T>\nvoid\numfpack_free_numeric (void **Numeric);\n\ntemplate <typename T>\nvoid\numfpack_free_symbolic (void **Symbolic);\n\ntemplate <typename T>\noctave_idx_type\numfpack_get_lunz (octave_idx_type *lnz, octave_idx_type *unz,\n                  void *Numeric);\n\ntemplate <typename T>\noctave_idx_type\numfpack_get_numeric (octave_idx_type *Lp, octave_idx_type *Lj,\n                     T *Lx, // Or Lz_packed\n                     octave_idx_type *Up, octave_idx_type *Ui,\n                     T *Ux, // Or Uz_packed\n                     octave_idx_type *p, octave_idx_type *q,\n                     double *Dz_packed, octave_idx_type *do_recip,\n                     double *Rs, void *Numeric);\n\ntemplate <typename T>\noctave_idx_type\numfpack_numeric (const octave_idx_type *Ap, const octave_idx_type *Ai,\n                 const T *Ax, // Or Az_packed\n                 void *Symbolic, void **Numeric,\n                 const double *Control, double *Info);\n\ntemplate <typename T>\noctave_idx_type\numfpack_qsymbolic (octave_idx_type n_row, octave_idx_type n_col,\n                   const octave_idx_type *Ap, const octave_idx_type *Ai,\n                   const T *Ax, // Or Az_packed\n                   const octave_idx_type *Qinit, void **Symbolic,\n                   const double *Control, double *Info);\n\ntemplate <typename T>\nvoid\numfpack_report_control (const double *Control);\n\ntemplate <typename T>\nvoid\numfpack_report_info (const double *Control, const double *Info);\n\ntemplate <typename T>\nvoid\numfpack_report_matrix (octave_idx_type n_row, octave_idx_type n_col,\n                       const octave_idx_type *Ap,\n                       const octave_idx_type *Ai,\n                       const T *Ax, // Or Az_packed\n                       octave_idx_type col_form, const double *Control);\n\ntemplate <typename T>\nvoid\numfpack_report_numeric (void *Numeric, const double *Control);\n\ntemplate <typename T>\nvoid\numfpack_report_perm (octave_idx_type np, const octave_idx_type *Perm,\n                     const double *Control);\n\ntemplate <typename T>\nvoid\numfpack_report_status (double *Control, octave_idx_type status);\n\ntemplate <typename T>\nvoid\numfpack_report_symbolic (void *Symbolic, const double *Control);\n\n#if defined (HAVE_UMFPACK)\n\n// SparseMatrix Specialization.\n\ntemplate <>\ninline OCTAVE_API void\numfpack_defaults<double> (double *Control)\n{\n  UMFPACK_DNAME (defaults) (Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_free_numeric<double> (void **Numeric)\n{\n  UMFPACK_DNAME (free_numeric) (Numeric);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_free_symbolic<double> (void **Symbolic)\n{\n  UMFPACK_DNAME (free_symbolic) (Symbolic);\n}\n\ntemplate <>\ninline OCTAVE_API octave_idx_type\numfpack_get_lunz<double>\n(octave_idx_type *lnz, octave_idx_type *unz, void *Numeric)\n{\n  suitesparse_integer ignore1, ignore2, ignore3;\n\n  return UMFPACK_DNAME (get_lunz) (to_suitesparse_intptr (lnz),\n                                   to_suitesparse_intptr (unz),\n                                   &ignore1, &ignore2, &ignore3, Numeric);\n}\n\ntemplate <>\ninline OCTAVE_API octave_idx_type\numfpack_get_numeric<double>\n(octave_idx_type *Lp, octave_idx_type *Lj, double *Lx,\n octave_idx_type *Up, octave_idx_type *Ui, double *Ux,\n octave_idx_type *p, octave_idx_type *q, double *Dx,\n octave_idx_type *do_recip, double *Rs, void *Numeric)\n{\n  return UMFPACK_DNAME (get_numeric) (to_suitesparse_intptr (Lp),\n                                      to_suitesparse_intptr (Lj),\n                                      Lx, to_suitesparse_intptr (Up),\n                                      to_suitesparse_intptr (Ui), Ux,\n                                      to_suitesparse_intptr (p),\n                                      to_suitesparse_intptr (q), Dx,\n                                      to_suitesparse_intptr (do_recip),\n                                      Rs, Numeric);\n}\n\ntemplate <>\ninline OCTAVE_API octave_idx_type\numfpack_numeric<double>\n(const octave_idx_type *Ap, const octave_idx_type *Ai,\n const double *Ax, void *Symbolic, void **Numeric,\n const double *Control, double *Info)\n{\n  return UMFPACK_DNAME (numeric) (to_suitesparse_intptr (Ap),\n                                  to_suitesparse_intptr (Ai),\n                                  Ax, Symbolic, Numeric, Control, Info);\n}\n\ntemplate <>\ninline OCTAVE_API octave_idx_type\numfpack_qsymbolic<double>\n(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap,\n const octave_idx_type *Ai, const double *Ax,\n const octave_idx_type *Qinit, void **Symbolic,\n const double *Control, double *Info)\n{\n  return UMFPACK_DNAME (qsymbolic) (n_row, n_col,\n                                    to_suitesparse_intptr (Ap),\n                                    to_suitesparse_intptr (Ai), Ax,\n                                    to_suitesparse_intptr (Qinit),\n                                    Symbolic, Control, Info);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_control<double> (const double *Control)\n{\n  UMFPACK_DNAME (report_control) (Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_info<double> (const double *Control, const double *Info)\n{\n  UMFPACK_DNAME (report_info) (Control, Info);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_matrix<double>\n(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap,\n const octave_idx_type *Ai, const double *Ax, octave_idx_type col_form,\n const double *Control)\n{\n  UMFPACK_DNAME (report_matrix) (n_row, n_col,\n                                 to_suitesparse_intptr (Ap),\n                                 to_suitesparse_intptr (Ai), Ax,\n                                 col_form, Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_numeric<double> (void *Numeric, const double *Control)\n{\n  UMFPACK_DNAME (report_numeric) (Numeric, Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_perm<double>\n(octave_idx_type np, const octave_idx_type *Perm, const double *Control)\n{\n  UMFPACK_DNAME (report_perm) (np, to_suitesparse_intptr (Perm), Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_status<double> (double *Control, octave_idx_type status)\n{\n  UMFPACK_DNAME (report_status) (Control, status);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_symbolic<double> (void *Symbolic, const double *Control)\n{\n  UMFPACK_DNAME (report_symbolic) (Symbolic, Control);\n}\n\n// SparseComplexMatrix specialization.\n\ntemplate <>\ninline OCTAVE_API void\numfpack_defaults<Complex> (double *Control)\n{\n  UMFPACK_ZNAME (defaults) (Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_free_numeric<Complex> (void **Numeric)\n{\n  UMFPACK_ZNAME (free_numeric) (Numeric);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_free_symbolic<Complex> (void **Symbolic)\n{\n  UMFPACK_ZNAME (free_symbolic) (Symbolic);\n}\n\ntemplate <>\ninline OCTAVE_API octave_idx_type\numfpack_get_lunz<Complex>\n(octave_idx_type *lnz, octave_idx_type *unz, void *Numeric)\n{\n  suitesparse_integer ignore1, ignore2, ignore3;\n\n  return UMFPACK_ZNAME (get_lunz) (to_suitesparse_intptr (lnz),\n                                   to_suitesparse_intptr (unz),\n                                   &ignore1, &ignore2, &ignore3, Numeric);\n}\n\ntemplate <>\ninline OCTAVE_API octave_idx_type\numfpack_get_numeric<Complex>\n(octave_idx_type *Lp, octave_idx_type *Lj, Complex *Lz,\n octave_idx_type *Up, octave_idx_type *Ui, Complex *Uz,\n octave_idx_type *p, octave_idx_type *q, double *Dz,\n octave_idx_type *do_recip, double *Rs, void *Numeric)\n{\n  return UMFPACK_ZNAME (get_numeric) (to_suitesparse_intptr (Lp),\n                                      to_suitesparse_intptr (Lj),\n                                      reinterpret_cast<double *> (Lz),\n                                      nullptr, to_suitesparse_intptr (Up),\n                                      to_suitesparse_intptr (Ui),\n                                      reinterpret_cast<double *> (Uz),\n                                      nullptr, to_suitesparse_intptr (p),\n                                      to_suitesparse_intptr (q),\n                                      reinterpret_cast<double *> (Dz),\n                                      nullptr, to_suitesparse_intptr (do_recip),\n                                      Rs, Numeric);\n}\n\ntemplate <>\ninline OCTAVE_API octave_idx_type\numfpack_numeric<Complex>\n(const octave_idx_type *Ap, const octave_idx_type *Ai,\n const Complex *Az, void *Symbolic, void **Numeric,\n const double *Control, double *Info)\n{\n  return UMFPACK_ZNAME (numeric) (to_suitesparse_intptr (Ap),\n                                  to_suitesparse_intptr (Ai),\n                                  reinterpret_cast<const double *> (Az),\n                                  nullptr, Symbolic, Numeric, Control, Info);\n}\n\ntemplate <>\ninline OCTAVE_API octave_idx_type\numfpack_qsymbolic<Complex>\n(octave_idx_type n_row, octave_idx_type n_col,\n const octave_idx_type *Ap, const octave_idx_type *Ai,\n const Complex *Az, const octave_idx_type *Qinit,\n void **Symbolic, const double *Control, double *Info)\n{\n  return UMFPACK_ZNAME (qsymbolic) (n_row, n_col,\n                                    to_suitesparse_intptr (Ap),\n                                    to_suitesparse_intptr (Ai),\n                                    reinterpret_cast<const double *> (Az),\n                                    nullptr, to_suitesparse_intptr (Qinit),\n                                    Symbolic, Control, Info);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_control<Complex> (const double *Control)\n{\n  UMFPACK_ZNAME (report_control) (Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_info<Complex> (const double *Control, const double *Info)\n{\n  UMFPACK_ZNAME (report_info) (Control, Info);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_matrix<Complex>\n(octave_idx_type n_row, octave_idx_type n_col,\n const octave_idx_type *Ap, const octave_idx_type *Ai,\n const Complex *Az, octave_idx_type col_form, const double *Control)\n{\n  UMFPACK_ZNAME (report_matrix) (n_row, n_col,\n                                 to_suitesparse_intptr (Ap),\n                                 to_suitesparse_intptr (Ai),\n                                 reinterpret_cast<const double *> (Az),\n                                 nullptr, col_form, Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_numeric<Complex> (void *Numeric, const double *Control)\n{\n  UMFPACK_ZNAME (report_numeric) (Numeric, Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_perm<Complex>\n(octave_idx_type np, const octave_idx_type *Perm, const double *Control)\n{\n  UMFPACK_ZNAME (report_perm) (np, to_suitesparse_intptr (Perm), Control);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_status<Complex> (double *Control, octave_idx_type status)\n{\n  UMFPACK_ZNAME (report_status) (Control, status);\n}\n\ntemplate <>\ninline OCTAVE_API void\numfpack_report_symbolic<Complex> (void *Symbolic, const double *Control)\n{\n  UMFPACK_ZNAME (report_symbolic) (Symbolic, Control);\n}\n\n#endif\n\ntemplate <typename lu_type>\nsparse_lu<lu_type>::sparse_lu (const lu_type& a, const Matrix& piv_thres,\n                               bool scale)\n  : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q ()\n{\n#if defined (HAVE_UMFPACK)\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  // Setup the control parameters\n  Matrix Control (UMFPACK_CONTROL, 1);\n  double *control = Control.rwdata ();\n  umfpack_defaults<lu_elt_type> (control);\n\n  double tmp = sparse_params::get_key (\"spumoni\");\n  if (! math::isnan (tmp))\n    Control (UMFPACK_PRL) = tmp;\n\n  if (piv_thres.numel () == 2)\n    {\n      tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0));\n      if (! math::isnan (tmp))\n        Control (UMFPACK_PIVOT_TOLERANCE) = tmp;\n\n      tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1));\n      if (! math::isnan (tmp))\n        Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;\n    }\n  else\n    {\n      tmp = sparse_params::get_key (\"piv_tol\");\n      if (! math::isnan (tmp))\n        Control (UMFPACK_PIVOT_TOLERANCE) = tmp;\n\n      tmp = sparse_params::get_key (\"sym_tol\");\n      if (! math::isnan (tmp))\n        Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;\n    }\n\n  // Set whether we are allowed to modify Q or not\n  tmp = sparse_params::get_key (\"autoamd\");\n  if (! math::isnan (tmp))\n    Control (UMFPACK_FIXQ) = tmp;\n\n  // Turn-off UMFPACK scaling for LU\n  if (scale)\n    Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;\n  else\n    Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;\n\n  umfpack_report_control<lu_elt_type> (control);\n\n  const octave_idx_type *Ap = a.cidx ();\n  const octave_idx_type *Ai = a.ridx ();\n  const lu_elt_type *Ax = a.data ();\n\n  umfpack_report_matrix<lu_elt_type> (nr, nc, Ap, Ai, Ax,\n                                      static_cast<octave_idx_type> (1),\n                                      control);\n\n  void *Symbolic;\n  Matrix Info (1, UMFPACK_INFO);\n  double *info = Info.rwdata ();\n  int status = umfpack_qsymbolic<lu_elt_type> (nr, nc, Ap, Ai, Ax, nullptr,\n               &Symbolic, control, info);\n\n  if (status < 0)\n    {\n      umfpack_report_status<lu_elt_type> (control, status);\n      umfpack_report_info<lu_elt_type> (control, info);\n\n      umfpack_free_symbolic<lu_elt_type> (&Symbolic);\n\n      (*current_liboctave_error_handler)\n        (\"sparse_lu: symbolic factorization failed\");\n    }\n  else\n    {\n      umfpack_report_symbolic<lu_elt_type> (Symbolic, control);\n\n      void *Numeric;\n      status = umfpack_numeric<lu_elt_type> (Ap, Ai, Ax, Symbolic,\n                                             &Numeric, control, info);\n      umfpack_free_symbolic<lu_elt_type> (&Symbolic);\n\n      m_cond = Info (UMFPACK_RCOND);\n\n      if (status < 0)\n        {\n          umfpack_report_status<lu_elt_type> (control, status);\n          umfpack_report_info<lu_elt_type> (control, info);\n\n          umfpack_free_numeric<lu_elt_type> (&Numeric);\n\n          (*current_liboctave_error_handler)\n            (\"sparse_lu: numeric factorization failed\");\n        }\n      else\n        {\n          umfpack_report_numeric<lu_elt_type> (Numeric, control);\n\n          octave_idx_type lnz, unz;\n          status = umfpack_get_lunz<lu_elt_type> (&lnz, &unz, Numeric);\n\n          if (status < 0)\n            {\n              umfpack_report_status<lu_elt_type> (control, status);\n              umfpack_report_info<lu_elt_type> (control, info);\n\n              umfpack_free_numeric<lu_elt_type> (&Numeric);\n\n              (*current_liboctave_error_handler)\n                (\"sparse_lu: extracting LU factors failed\");\n            }\n          else\n            {\n              octave_idx_type n_inner = (nr < nc ? nr : nc);\n\n              if (lnz < 1)\n                m_L = lu_type (n_inner, nr,\n                               static_cast<octave_idx_type> (1));\n              else\n                m_L = lu_type (n_inner, nr, lnz);\n\n              octave_idx_type *Ltp = m_L.cidx ();\n              octave_idx_type *Ltj = m_L.ridx ();\n              lu_elt_type *Ltx = m_L.data ();\n\n              if (unz < 1)\n                m_U = lu_type (n_inner, nc,\n                               static_cast<octave_idx_type> (1));\n              else\n                m_U = lu_type (n_inner, nc, unz);\n\n              octave_idx_type *Up = m_U.cidx ();\n              octave_idx_type *Uj = m_U.ridx ();\n              lu_elt_type *Ux = m_U.data ();\n\n              m_R = SparseMatrix (nr, nr, nr);\n              for (octave_idx_type i = 0; i < nr; i++)\n                {\n                  m_R.xridx (i) = i;\n                  m_R.xcidx (i) = i;\n                }\n              m_R.xcidx (nr) = nr;\n              double *Rx = m_R.data ();\n\n              m_P.resize (dim_vector (nr, 1));\n              octave_idx_type *p = m_P.rwdata ();\n\n              m_Q.resize (dim_vector (nc, 1));\n              octave_idx_type *q = m_Q.rwdata ();\n\n              octave_idx_type do_recip;\n              status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx,\n                       Up, Uj, Ux,\n                       p, q, nullptr,\n                       &do_recip, Rx,\n                       Numeric);\n\n              umfpack_free_numeric<lu_elt_type> (&Numeric);\n\n              if (status < 0)\n                {\n                  umfpack_report_status<lu_elt_type> (control, status);\n\n                  (*current_liboctave_error_handler)\n                    (\"sparse_lu: extracting LU factors failed\");\n                }\n              else\n                {\n                  m_L = m_L.transpose ();\n\n                  if (do_recip)\n                    for (octave_idx_type i = 0; i < nr; i++)\n                      Rx[i] = 1.0 / Rx[i];\n\n                  umfpack_report_matrix<lu_elt_type> (nr, n_inner,\n                                                      m_L.cidx (),\n                                                      m_L.ridx (),\n                                                      m_L.data (),\n                                                      static_cast<octave_idx_type> (1),\n                                                      control);\n                  umfpack_report_matrix<lu_elt_type> (n_inner, nc,\n                                                      m_U.cidx (),\n                                                      m_U.ridx (),\n                                                      m_U.data (),\n                                                      static_cast<octave_idx_type> (1),\n                                                      control);\n                  umfpack_report_perm<lu_elt_type> (nr, p, control);\n                  umfpack_report_perm<lu_elt_type> (nc, q, control);\n                }\n\n              umfpack_report_info<lu_elt_type> (control, info);\n            }\n        }\n    }\n\n#else\n\n  octave_unused_parameter (a);\n  octave_unused_parameter (piv_thres);\n  octave_unused_parameter (scale);\n\n  (*current_liboctave_error_handler)\n    (\"support for UMFPACK was unavailable or disabled when liboctave was built\");\n\n#endif\n}\n\ntemplate <typename lu_type>\nsparse_lu<lu_type>::sparse_lu (const lu_type& a,\n                               const ColumnVector& Qinit,\n                               const Matrix& piv_thres, bool scale,\n                               bool FixedQ, double droptol,\n                               bool milu, bool udiag)\n  : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q ()\n{\n#if defined (HAVE_UMFPACK)\n\n  if (milu)\n    (*current_liboctave_error_handler)\n      (\"Modified incomplete LU not implemented\");\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  // Setup the control parameters\n  Matrix Control (UMFPACK_CONTROL, 1);\n  double *control = Control.rwdata ();\n  umfpack_defaults<lu_elt_type> (control);\n\n  double tmp = sparse_params::get_key (\"spumoni\");\n  if (! math::isnan (tmp))\n    Control (UMFPACK_PRL) = tmp;\n\n  if (piv_thres.numel () == 2)\n    {\n      tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0));\n      if (! math::isnan (tmp))\n        Control (UMFPACK_PIVOT_TOLERANCE) = tmp;\n      tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1));\n      if (! math::isnan (tmp))\n        Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;\n    }\n  else\n    {\n      tmp = sparse_params::get_key (\"piv_tol\");\n      if (! math::isnan (tmp))\n        Control (UMFPACK_PIVOT_TOLERANCE) = tmp;\n\n      tmp = sparse_params::get_key (\"sym_tol\");\n      if (! math::isnan (tmp))\n        Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;\n    }\n\n  if (droptol >= 0.)\n    Control (UMFPACK_DROPTOL) = droptol;\n\n  // Set whether we are allowed to modify Q or not\n  if (FixedQ)\n    Control (UMFPACK_FIXQ) = 1.0;\n  else\n    {\n      tmp = sparse_params::get_key (\"autoamd\");\n      if (! math::isnan (tmp))\n        Control (UMFPACK_FIXQ) = tmp;\n    }\n\n  // Turn-off UMFPACK scaling for LU\n  if (scale)\n    Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;\n  else\n    Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;\n\n  umfpack_report_control<lu_elt_type> (control);\n\n  const octave_idx_type *Ap = a.cidx ();\n  const octave_idx_type *Ai = a.ridx ();\n  const lu_elt_type *Ax = a.data ();\n\n  umfpack_report_matrix<lu_elt_type> (nr, nc, Ap, Ai, Ax,\n                                      static_cast<octave_idx_type> (1),\n                                      control);\n\n  void *Symbolic;\n  Matrix Info (1, UMFPACK_INFO);\n  double *info = Info.rwdata ();\n  int status;\n\n  // Null loop so that qinit is immediately deallocated when not needed\n  do\n    {\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, qinit, nc);\n\n      for (octave_idx_type i = 0; i < nc; i++)\n        qinit[i] = static_cast<octave_idx_type> (Qinit (i));\n\n      status = umfpack_qsymbolic<lu_elt_type> (nr, nc, Ap, Ai, Ax,\n               qinit, &Symbolic, control,\n               info);\n    }\n  while (0);\n\n  if (status < 0)\n    {\n      umfpack_report_status<lu_elt_type> (control, status);\n      umfpack_report_info<lu_elt_type> (control, info);\n\n      umfpack_free_symbolic<lu_elt_type> (&Symbolic);\n\n      (*current_liboctave_error_handler)\n        (\"sparse_lu: symbolic factorization failed\");\n    }\n  else\n    {\n      umfpack_report_symbolic<lu_elt_type> (Symbolic, control);\n\n      void *Numeric;\n      status = umfpack_numeric<lu_elt_type> (Ap, Ai, Ax, Symbolic,\n                                             &Numeric, control, info);\n      umfpack_free_symbolic<lu_elt_type> (&Symbolic);\n\n      m_cond = Info (UMFPACK_RCOND);\n\n      if (status < 0)\n        {\n          umfpack_report_status<lu_elt_type> (control, status);\n          umfpack_report_info<lu_elt_type> (control, info);\n\n          umfpack_free_numeric<lu_elt_type> (&Numeric);\n\n          (*current_liboctave_error_handler)\n            (\"sparse_lu: numeric factorization failed\");\n        }\n      else\n        {\n          umfpack_report_numeric<lu_elt_type> (Numeric, control);\n\n          octave_idx_type lnz, unz;\n          status = umfpack_get_lunz<lu_elt_type> (&lnz, &unz, Numeric);\n\n          if (status < 0)\n            {\n              umfpack_report_status<lu_elt_type> (control, status);\n              umfpack_report_info<lu_elt_type> (control, info);\n\n              umfpack_free_numeric<lu_elt_type> (&Numeric);\n\n              (*current_liboctave_error_handler)\n                (\"sparse_lu: extracting LU factors failed\");\n            }\n          else\n            {\n              octave_idx_type n_inner = (nr < nc ? nr : nc);\n\n              if (lnz < 1)\n                m_L = lu_type (n_inner, nr,\n                               static_cast<octave_idx_type> (1));\n              else\n                m_L = lu_type (n_inner, nr, lnz);\n\n              octave_idx_type *Ltp = m_L.cidx ();\n              octave_idx_type *Ltj = m_L.ridx ();\n              lu_elt_type *Ltx = m_L.data ();\n\n              if (unz < 1)\n                m_U = lu_type (n_inner, nc,\n                               static_cast<octave_idx_type> (1));\n              else\n                m_U = lu_type (n_inner, nc, unz);\n\n              octave_idx_type *Up = m_U.cidx ();\n              octave_idx_type *Uj = m_U.ridx ();\n              lu_elt_type *Ux = m_U.data ();\n\n              m_R = SparseMatrix (nr, nr, nr);\n              for (octave_idx_type i = 0; i < nr; i++)\n                {\n                  m_R.xridx (i) = i;\n                  m_R.xcidx (i) = i;\n                }\n              m_R.xcidx (nr) = nr;\n              double *Rx = m_R.data ();\n\n              m_P.resize (dim_vector (nr, 1));\n              octave_idx_type *p = m_P.rwdata ();\n\n              m_Q.resize (dim_vector (nc, 1));\n              octave_idx_type *q = m_Q.rwdata ();\n\n              octave_idx_type do_recip;\n              status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx,\n                       Up, Uj, Ux,\n                       p, q, nullptr,\n                       &do_recip,\n                       Rx, Numeric);\n\n              umfpack_free_numeric<lu_elt_type> (&Numeric);\n\n              if (status < 0)\n                {\n                  umfpack_report_status<lu_elt_type> (control, status);\n\n                  (*current_liboctave_error_handler)\n                    (\"sparse_lu: extracting LU factors failed\");\n                }\n              else\n                {\n                  m_L = m_L.transpose ();\n\n                  if (do_recip)\n                    for (octave_idx_type i = 0; i < nr; i++)\n                      Rx[i] = 1.0 / Rx[i];\n\n                  umfpack_report_matrix<lu_elt_type> (nr, n_inner,\n                                                      m_L.cidx (),\n                                                      m_L.ridx (),\n                                                      m_L.data (),\n                                                      static_cast<octave_idx_type> (1),\n                                                      control);\n                  umfpack_report_matrix<lu_elt_type> (n_inner, nc,\n                                                      m_U.cidx (),\n                                                      m_U.ridx (),\n                                                      m_U.data (),\n                                                      static_cast<octave_idx_type> (1),\n                                                      control);\n                  umfpack_report_perm<lu_elt_type> (nr, p, control);\n                  umfpack_report_perm<lu_elt_type> (nc, q, control);\n                }\n\n              umfpack_report_info<lu_elt_type> (control, info);\n            }\n        }\n    }\n\n  if (udiag)\n    (*current_liboctave_error_handler)\n      (\"Option udiag of incomplete LU not implemented\");\n\n#else\n\n  octave_unused_parameter (a);\n  octave_unused_parameter (Qinit);\n  octave_unused_parameter (piv_thres);\n  octave_unused_parameter (scale);\n  octave_unused_parameter (FixedQ);\n  octave_unused_parameter (droptol);\n  octave_unused_parameter (milu);\n  octave_unused_parameter (udiag);\n\n  (*current_liboctave_error_handler)\n    (\"support for UMFPACK was unavailable or disabled when liboctave was built\");\n\n#endif\n}\n\ntemplate <typename lu_type>\nlu_type\nsparse_lu<lu_type>::Y () const\n{\n  octave_idx_type nr = m_L.rows ();\n  octave_idx_type nz = m_L.cols ();\n  octave_idx_type nc = m_U.cols ();\n\n  lu_type Yout (nr, nc, m_L.nnz () + m_U.nnz () - (nr<nz?nr:nz));\n  octave_idx_type ii = 0;\n  Yout.xcidx (0) = 0;\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      for (octave_idx_type i = m_U.cidx (j); i < m_U.cidx (j + 1); i++)\n        {\n          Yout.xridx (ii) = m_U.ridx (i);\n          Yout.xdata (ii++) = m_U.data (i);\n        }\n\n      if (j < nz)\n        {\n          // Note the +1 skips the 1.0 on the diagonal\n          for (octave_idx_type i = m_L.cidx (j) + 1;\n               i < m_L.cidx (j +1); i++)\n            {\n              Yout.xridx (ii) = m_L.ridx (i);\n              Yout.xdata (ii++) = m_L.data (i);\n            }\n        }\n\n      Yout.xcidx (j + 1) = ii;\n    }\n\n  return Yout;\n}\n\ntemplate <typename lu_type>\nSparseMatrix\nsparse_lu<lu_type>::Pr () const\n{\n  octave_idx_type nr = m_L.rows ();\n\n  SparseMatrix Pout (nr, nr, nr);\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    {\n      Pout.cidx (i) = i;\n      Pout.ridx (m_P(i)) = i;\n      Pout.data (i) = 1;\n    }\n\n  Pout.cidx (nr) = nr;\n\n  return Pout;\n}\n\ntemplate <typename lu_type>\nColumnVector\nsparse_lu<lu_type>::Pr_vec () const\n{\n  octave_idx_type nr = m_L.rows ();\n\n  ColumnVector Pout (nr);\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    Pout.xelem (i) = static_cast<double> (m_P(i) + 1);\n\n  return Pout;\n}\n\ntemplate <typename lu_type>\nPermMatrix\nsparse_lu<lu_type>::Pr_mat () const\n{\n  return PermMatrix (m_P, false);\n}\n\ntemplate <typename lu_type>\nSparseMatrix\nsparse_lu<lu_type>::Pc () const\n{\n  octave_idx_type nc = m_U.cols ();\n\n  SparseMatrix Pout (nc, nc, nc);\n\n  for (octave_idx_type i = 0; i < nc; i++)\n    {\n      Pout.cidx (i) = i;\n      Pout.ridx (i) = m_Q(i);\n      Pout.data (i) = 1;\n    }\n\n  Pout.cidx (nc) = nc;\n\n  return Pout;\n}\n\ntemplate <typename lu_type>\nColumnVector\nsparse_lu<lu_type>::Pc_vec () const\n{\n  octave_idx_type nc = m_U.cols ();\n\n  ColumnVector Pout (nc);\n\n  for (octave_idx_type i = 0; i < nc; i++)\n    Pout.xelem (i) = static_cast<double> (m_Q(i) + 1);\n\n  return Pout;\n}\n\ntemplate <typename lu_type>\nPermMatrix\nsparse_lu<lu_type>::Pc_mat () const\n{\n  return PermMatrix (m_Q, true);\n}\n\n// Instantiations we need.\ntemplate class OCTAVE_API sparse_lu<SparseMatrix>;\n\ntemplate class OCTAVE_API sparse_lu<SparseComplexMatrix>;\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/sparse-lu.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_sparse_lu_h)\n#define octave_sparse_lu_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\n#include \"MArray.h\"\n#include \"dMatrix.h\"\n#include \"dSparse.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\n// If the sparse matrix classes become templated on the element type\n// (i.e., sparse_matrix<double>), then it might be best to make the\n// template parameter of this class also be the element type instead\n// of the matrix type.\n\ntemplate <typename lu_type>\nclass OCTAVE_API sparse_lu\n{\npublic:\n\n  typedef typename lu_type::element_type lu_elt_type;\n\n  sparse_lu ()\n    : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q () { }\n\n  OCTAVE_API\n  sparse_lu (const lu_type& a, const Matrix& piv_thres = Matrix (),\n             bool scale = false);\n\n  OCTAVE_API\n  sparse_lu (const lu_type& a, const ColumnVector& Qinit,\n             const Matrix& piv_thres, bool scale = false,\n             bool FixedQ = false, double droptol = -1.0,\n             bool milu = false, bool udiag = false);\n\n  sparse_lu (const sparse_lu& a)\n    : m_L (a.m_L), m_U (a.m_U), m_R (),\n      m_cond (a.m_cond), m_P (a.m_P), m_Q (a.m_Q)\n  { }\n\n  sparse_lu& operator = (const sparse_lu& a)\n  {\n    if (this != &a)\n      {\n        m_L = a.m_L;\n        m_U = a.m_U;\n        m_cond = a.m_cond;\n        m_P = a.m_P;\n        m_Q = a.m_Q;\n      }\n\n    return *this;\n  }\n\n  virtual ~sparse_lu () = default;\n\n  lu_type L () const { return m_L; }\n\n  lu_type U () const { return m_U; }\n\n  SparseMatrix R () const { return m_R; }\n\n  OCTAVE_API lu_type Y () const;\n\n  OCTAVE_API SparseMatrix Pc () const;\n\n  OCTAVE_API SparseMatrix Pr () const;\n\n  OCTAVE_API ColumnVector Pc_vec () const;\n\n  OCTAVE_API ColumnVector Pr_vec () const;\n\n  OCTAVE_API PermMatrix Pc_mat () const;\n\n  OCTAVE_API PermMatrix Pr_mat () const;\n\n  const octave_idx_type * row_perm () const { return m_P.data (); }\n\n  const octave_idx_type * col_perm () const { return m_Q.data (); }\n\n  double rcond () const { return m_cond; }\n\nprotected:\n\n  lu_type m_L;\n  lu_type m_U;\n  SparseMatrix m_R;\n\n  double m_cond;\n\n  MArray<octave_idx_type> m_P;\n  MArray<octave_idx_type> m_Q;\n};\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/sparse-qr.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"CMatrix.h\"\n#include \"CSparse.h\"\n#include \"MArray.h\"\n#include \"dColVector.h\"\n#include \"dMatrix.h\"\n#include \"dSparse.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sparse.h\"\n#include \"quit.h\"\n#include \"sparse-qr.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\n#if defined (HAVE_CXSPARSE)\ntemplate <typename SPARSE_T>\nclass cxsparse_types\n{ };\n\ntemplate <>\nclass cxsparse_types<SparseMatrix>\n{\npublic:\n  typedef CXSPARSE_DNAME (s) symbolic_type;\n  typedef CXSPARSE_DNAME (n) numeric_type;\n};\n\ntemplate <>\nclass cxsparse_types<SparseComplexMatrix>\n{\npublic:\n  typedef CXSPARSE_ZNAME (s) symbolic_type;\n  typedef CXSPARSE_ZNAME (n) numeric_type;\n};\n#endif\n\ntemplate <typename SPARSE_T>\nclass sparse_qr<SPARSE_T>::sparse_qr_rep\n{\npublic:\n\n  sparse_qr_rep (const SPARSE_T& a, int order);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (sparse_qr_rep)\n\n  ~sparse_qr_rep ();\n\n  bool ok () const\n  {\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n    return (m_H && m_Htau && m_HPinv && m_R && m_E);\n#elif defined (HAVE_CXSPARSE)\n    return (N && S);\n#else\n    return false;\n#endif\n  }\n\n  SPARSE_T V () const;\n\n  ColumnVector Pinv () const;\n\n  ColumnVector P () const;\n\n  ColumnVector E () const;\n\n  SPARSE_T R (bool econ) const;\n\n  typename SPARSE_T::dense_matrix_type\n  C (const typename SPARSE_T::dense_matrix_type& b, bool econ = false);\n\n  typename SPARSE_T::dense_matrix_type Q (bool econ = false);\n\n  octave_idx_type nrows;\n  octave_idx_type ncols;\n\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  template <typename RHS_T, typename RET_T>\n  RET_T solve (const RHS_T& b, octave_idx_type& info) const;\n\n#endif\n\n#if defined (HAVE_CXSPARSE)\n\n  typename cxsparse_types<SPARSE_T>::symbolic_type *S;\n  typename cxsparse_types<SPARSE_T>::numeric_type *N;\n\n#endif\n\n  template <typename RHS_T, typename RET_T>\n  RET_T tall_solve (const RHS_T& b, octave_idx_type& info);\n\n  template <typename RHS_T, typename RET_T>\n  RET_T wide_solve (const RHS_T& b, octave_idx_type& info) const;\n\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\nprivate:\n\n  cholmod_common m_cc;\n  cholmod_sparse *m_R;  // R factor\n                        // Column permutation for A.  Fill-reducing ordering.\n  SuiteSparse_long *m_E;\n  cholmod_sparse *m_H;  // Householder vectors\n  cholmod_dense *m_Htau;  // beta scalars\n  SuiteSparse_long *m_HPinv;\n\n#endif\n};\n\ntemplate <typename SPARSE_T>\nColumnVector\nsparse_qr<SPARSE_T>::sparse_qr_rep::Pinv () const\n{\n#if defined (HAVE_CXSPARSE)\n\n  ColumnVector ret (N->L->m);\n\n  for (octave_idx_type i = 0; i < N->L->m; i++)\n    ret.xelem (i) = S->pinv[i];\n\n  return ret;\n\n#else\n\n  return ColumnVector ();\n\n#endif\n}\n\ntemplate <typename SPARSE_T>\nColumnVector\nsparse_qr<SPARSE_T>::sparse_qr_rep::P () const\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  ColumnVector ret (nrows);\n\n  // FIXME: Is ret.xelem (m_HPinv[i]) = i + 1 correct?\n  for (octave_idx_type i = 0; i < nrows; i++)\n    ret.xelem (from_suitesparse_long (m_HPinv[i])) = i + 1;\n\n  return ret;\n\n#elif defined (HAVE_CXSPARSE)\n\n  ColumnVector ret (N->L->m);\n\n  for (octave_idx_type i = 0; i < N->L->m; i++)\n    ret.xelem (S->pinv[i]) = i;\n\n  return ret;\n\n#else\n\n  return ColumnVector ();\n\n#endif\n}\n\ntemplate <typename SPARSE_T>\nColumnVector\nsparse_qr<SPARSE_T>::sparse_qr_rep::E () const\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  ColumnVector ret (ncols);\n\n  if (m_E)\n    for (octave_idx_type i = 0; i < ncols; i++)\n      ret(i) = from_suitesparse_long (m_E[i]) + 1;\n  else\n    for (octave_idx_type i = 0; i < ncols; i++)\n      ret(i) = i + 1;\n\n  return ret;\n\n#elif defined (HAVE_CXSPARSE)\n\n  ColumnVector ret (ncols);\n\n  if (S->q)\n    for (octave_idx_type i = 0; i < ncols; i++)\n      ret(i) = from_suitesparse_long (S->q[i]) + 1;\n  else\n    for (octave_idx_type i = 0; i < ncols; i++)\n      ret(i) = i + 1;\n\n  return ret;\n\n#else\n\n  return ColumnVector ();\n\n#endif\n}\n\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n// Convert octave real sparse matrix to cholmod real sparse matrix.\n// Returns a \"shallow\" copy of a.\nstatic cholmod_sparse\nors2crs (const SparseMatrix& a)\n{\n  cholmod_sparse A;\n\n  octave_idx_type ncols = a.cols ();\n  octave_idx_type nnz = a.nnz ();\n\n  A.ncol = ncols;\n  A.nrow = a.rows ();\n  A.itype = CHOLMOD_LONG;\n  A.nzmax = nnz;\n  A.sorted = 0;\n  A.packed = 1;\n  A.stype = 0;\n  A.xtype = CHOLMOD_REAL;\n  A.dtype = CHOLMOD_DOUBLE;\n  A.nz = nullptr;\n  A.z = nullptr;\n\n#  if defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  A.p = reinterpret_cast<SuiteSparse_long *>\n        (const_cast<octave_idx_type *> (a.cidx ()));\n  A.i = reinterpret_cast<SuiteSparse_long *>\n        (const_cast<octave_idx_type *> (a.ridx ()));\n#  else\n  SuiteSparse_long *A_p;\n  A_p = new SuiteSparse_long[ncols+1];\n  for (octave_idx_type i = 0; i < ncols+1; i++)\n    A_p[i] = a.cidx (i);\n  A.p = A_p;\n\n  SuiteSparse_long *A_i;\n  A_i = new SuiteSparse_long[nnz];\n  for (octave_idx_type i = 0; i < nnz; i++)\n    A_i[i] = a.ridx (i);\n  A.i = A_i;\n#  endif\n\n  A.x = const_cast<double *> (a.data ());\n\n  return A;\n}\n\n// Convert octave complex sparse matrix to cholmod complex sparse matrix.\n// Returns a \"shallow\" copy of a.\nstatic cholmod_sparse\nocs2ccs (const SparseComplexMatrix& a)\n{\n  cholmod_sparse A;\n\n  octave_idx_type ncols = a.cols ();\n  octave_idx_type nnz = a.nnz ();\n\n  A.ncol = ncols;\n  A.nrow = a.rows ();\n  A.itype = CHOLMOD_LONG;\n  A.nzmax = nnz;\n  A.sorted = 0;\n  A.packed = 1;\n  A.stype = 0;\n  A.xtype = CHOLMOD_COMPLEX;\n  A.dtype = CHOLMOD_DOUBLE;\n  A.nz = nullptr;\n  A.z = nullptr;\n\n#  if defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  A.p = reinterpret_cast<SuiteSparse_long *>\n        (const_cast<octave_idx_type *> (a.cidx ()));\n  A.i = reinterpret_cast<SuiteSparse_long *>\n        (const_cast<octave_idx_type *> (a.ridx ()));\n#  else\n  SuiteSparse_long *A_p;\n  A_p = new SuiteSparse_long[ncols+1];\n  for (octave_idx_type i = 0; i < ncols+1; i++)\n    A_p[i] = a.cidx (i);\n  A.p = A_p;\n\n  SuiteSparse_long *A_i;\n  A_i = new SuiteSparse_long[nnz];\n  for (octave_idx_type i = 0; i < nnz; i++)\n    A_i[i] = a.ridx (i);\n  A.i = A_i;\n#  endif\n\n  A.x = const_cast<Complex *>\n        (reinterpret_cast<const Complex *> (a.data ()));\n\n  return A;\n}\n\n// Convert octave real dense matrix to cholmod complex dense matrix.\n// Returns a \"deep\" copy of a.\nstatic cholmod_dense *\nord2ccd (const MArray<double>& a, cholmod_common *cc1)\n{\n  cholmod_dense *A\n    = cholmod_l_allocate_dense (a.rows (), a.cols (), a.rows(),\n                                CHOLMOD_COMPLEX, cc1);\n\n  const double *a_x = a.data ();\n\n  Complex *A_x = reinterpret_cast<Complex *> (A->x);\n  for (octave_idx_type j = 0; j < a.cols() * a.rows() ; j++)\n    A_x[j] = Complex (a_x[j], 0.0);\n\n  return A;\n}\n\n// Convert octave real dense matrix to cholmod real dense matrix.\n// Returns a \"shallow\" copy of a.\nstatic cholmod_dense\nord2crd (const MArray<double>& a)\n{\n  cholmod_dense A;\n\n  A.ncol = a.cols ();\n  A.nrow = a.rows ();\n  A.nzmax = a.cols () * a.rows ();\n  A.xtype = CHOLMOD_REAL;\n  A.dtype = CHOLMOD_DOUBLE;\n  A.z = nullptr;\n  A.d = a.rows ();\n  A.x = const_cast<double *> (a.data ());\n\n  return A;\n}\n\n// Convert octave complex dense matrix to cholmod complex dense matrix.\n// Returns a \"shallow\" copy of a.\nstatic cholmod_dense\nocd2ccd (const ComplexMatrix& a)\n{\n  cholmod_dense A;\n\n  A.ncol = a.cols ();\n  A.nrow = a.rows ();\n  A.nzmax = a.cols () * a.rows ();\n  A.xtype = CHOLMOD_COMPLEX;\n  A.dtype = CHOLMOD_DOUBLE;\n  A.z = nullptr;\n  A.d = a.rows ();\n  A.x = const_cast<Complex *> (reinterpret_cast<const Complex *> (a.data ()));\n\n  return A;\n}\n\n// Convert cholmod real sparse matrix to octave real sparse matrix.\n// Returns a \"shallow\" copy of y.\nstatic SparseMatrix\ncrs2ors (cholmod_sparse *y, const cholmod_common *cc1)\n{\n  octave_idx_type nrow = from_size_t (y->nrow);\n  octave_idx_type ncol = from_size_t (y->ncol);\n  octave_idx_type nz\n    = from_suitesparse_long\n      (cholmod_l_nnz (y, const_cast<cholmod_common *> (cc1)));\n  SparseMatrix ret (nrow, ncol, nz);\n\n  SuiteSparse_long *y_p = reinterpret_cast<SuiteSparse_long *> (y->p);\n  for (octave_idx_type j = 0; j < ncol + 1; j++)\n    ret.xcidx (j) = from_suitesparse_long (y_p[j]);\n\n  SuiteSparse_long *y_i = reinterpret_cast<SuiteSparse_long *> (y->i);\n  double *y_x = reinterpret_cast<double *> (y->x);\n  for (octave_idx_type j = 0; j < nz; j++)\n    {\n      ret.xridx (j) = from_suitesparse_long (y_i[j]);\n      ret.xdata (j) = y_x[j];\n    }\n\n  return ret;\n}\n\n// Convert cholmod complex sparse matrix to octave complex sparse matrix.\n// Returns a \"deep\" copy of a.\nstatic SparseComplexMatrix\nccs2ocs (cholmod_sparse *a, cholmod_common *cc1)\n{\n  octave_idx_type nrow = from_size_t (a->nrow);\n  octave_idx_type ncol = from_size_t (a->ncol);\n  octave_idx_type nz = from_suitesparse_long (cholmod_l_nnz (a, cc1));\n  SparseComplexMatrix ret (nrow, ncol, nz);\n\n  SuiteSparse_long *a_p = reinterpret_cast<SuiteSparse_long *> (a->p);\n  for (octave_idx_type j = 0; j < ncol + 1; j++)\n    ret.xcidx(j) = from_suitesparse_long (a_p[j]);\n\n  SuiteSparse_long *a_i = reinterpret_cast<SuiteSparse_long *> (a->i);\n  Complex *a_x = reinterpret_cast<Complex *> (a->x);\n  for (octave_idx_type j = 0; j < nz; j++)\n    {\n      ret.xridx(j) = from_suitesparse_long (a_i[j]);\n      ret.xdata(j) = a_x[j];\n    }\n\n  return ret;\n}\n\n// Convert octave real sparse matrix to cholmod complex sparse matrix.\n// Returns a \"deep\" copy of a.\nstatic cholmod_sparse *\nors2ccs (const SparseMatrix& a, cholmod_common *cc)\n{\n  cholmod_sparse *A\n    = cholmod_l_allocate_sparse (a.rows (), a.cols (), a.nnz (), 0, 1, 0,\n                                 CHOLMOD_COMPLEX, cc);\n\n  octave_idx_type ncol = a.cols ();\n  SuiteSparse_long *A_p = reinterpret_cast<SuiteSparse_long *> (A->p);\n  for (octave_idx_type j = 0; j < ncol + 1; j++)\n    A_p[j] = a.cidx(j);\n\n  const double *a_x = a.data ();\n  Complex *A_x = reinterpret_cast<Complex *> (A->x);\n  SuiteSparse_long *A_i = reinterpret_cast<SuiteSparse_long *> (A->i);\n  for (octave_idx_type j = 0; j < a.nnz (); j++)\n    {\n      A_x[j] = Complex (a_x[j], 0.0);\n      A_i[j] = a.ridx(j);\n    }\n  return A;\n}\n\n#if defined (HAVE_CXSPARSE) && ! defined (OCTAVE_SUITESPARSE_INTEGER_MATCH)\nstatic suitesparse_integer\nsuitesparse_long_to_suitesparse_integer (SuiteSparse_long x)\n{\n  if (x < std::numeric_limits<suitesparse_integer>::min ()\n      || x > std::numeric_limits<suitesparse_integer>::max ())\n    (*current_liboctave_error_handler)\n      (\"integer dimension or index out of range for SuiteSparse's indexing type\");\n\n  return static_cast<suitesparse_integer> (x);\n}\n#endif\n\nstatic void\nspqr_error_handler (const cholmod_common *cc)\n{\n  if (cc->status >= 0)\n    return;\n\n  switch (cc->status)\n    {\n    case CHOLMOD_OUT_OF_MEMORY:\n      (*current_liboctave_error_handler)\n        (\"sparse_qr: sparse matrix QR factorization failed\"\n         \" - out of memory\");\n    case CHOLMOD_TOO_LARGE:\n      (*current_liboctave_error_handler)\n        (\"sparse_qr: sparse matrix QR factorization failed\"\n         \" - integer overflow occurred\");\n    default:\n      (*current_liboctave_error_handler)\n        (\"sparse_qr: sparse matrix QR factorization failed\"\n         \" - error %d\", cc->status);\n    }\n\n  // FIXME: Free memory?\n  // FIXME: Can cc-status > 0 (CHOLMOD_NOT_POSDEF, CHOLMOD_DSMALL) occur?\n}\n#endif\n\n// Specializations.\n\n// Real-valued matrices.\n\n// Arguments for parameter order (taken from SuiteSparseQR documentation).\n// 0: fixed ordering 0 (no permutation of columns)\n// 1: natural ordering 1 (only singleton columns are permuted to the left of\n//    the matrix)\n// 2: colamd\n// 3:\n// 4: CHOLMOD best-effort (COLAMD, METIS,...)\n// 5: AMD(a'*a)\n// 6: metis(a'*a)\n// 7: SuiteSparseQR default ordering\n// 8: try COLAMD, AMD, and METIS; pick best\n// 9: try COLAMD and AMD; pick best\n//FIXME: What is order = 3?\ntemplate <>\nsparse_qr<SparseMatrix>::sparse_qr_rep::sparse_qr_rep\n(const SparseMatrix& a, int order)\n  : nrows (a.rows ()), ncols (a.columns ())\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n  , m_cc (), m_R (nullptr), m_E (nullptr), m_H (nullptr), m_Htau (nullptr),\n    m_HPinv (nullptr)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr < 0 || nc < 0)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension with negative size\");\n\n  if (order < 0 || order > 9)\n    (*current_liboctave_error_handler)\n      (\"ordering %d is not supported by SPQR\", order);\n\n  cholmod_l_start (&m_cc);\n  cholmod_sparse A = ors2crs (a);\n\n  SuiteSparseQR<double> (order, static_cast<double> (SPQR_DEFAULT_TOL),\n                         static_cast<SuiteSparse_long> (A.nrow),\n                         &A, &m_R, &m_E, &m_H, &m_HPinv, &m_Htau, &m_cc);\n  spqr_error_handler (&m_cc);\n\n#  if ! defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.i);\n#  endif\n}\n\n#elif defined (HAVE_CXSPARSE)\n  , S (nullptr), N (nullptr)\n{\n  CXSPARSE_DNAME () A;\n\n  A.nzmax = a.nnz ();\n  A.m = nrows;\n  A.n = ncols;\n  // Cast away const on A, with full knowledge that CSparse won't touch it\n  // Prevents the methods below making a copy of the data.\n  A.p = const_cast<suitesparse_integer *>\n        (to_suitesparse_intptr (a.cidx ()));\n  A.i = const_cast<suitesparse_integer *>\n        (to_suitesparse_intptr (a.ridx ()));\n  A.x = const_cast<double *> (a.data ());\n  A.nz = -1;\n\n  S = CXSPARSE_DNAME (_sqr) (order, &A, 1);\n  N = CXSPARSE_DNAME (_qr) (&A, S);\n\n  if (! N)\n    (*current_liboctave_error_handler)\n      (\"sparse_qr: sparse matrix QR factorization filled\");\n\n}\n\n#else\n\n{\n  octave_unused_parameter (order);\n\n  (*current_liboctave_error_handler)\n    (\"sparse_qr: support for SPQR or CXSparse was unavailable or disabled when liboctave was built\");\n}\n\n#endif\n\ntemplate <>\nsparse_qr<SparseMatrix>::sparse_qr_rep::~sparse_qr_rep ()\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  cholmod_l_free_sparse (&m_R, &m_cc);\n  cholmod_l_free_sparse (&m_H, &m_cc);\n  cholmod_l_free_dense (&m_Htau, &m_cc);\n  free (m_E);  // FIXME: use cholmod_l_free\n  free (m_HPinv);\n  cholmod_l_finish (&m_cc);\n\n#elif defined (HAVE_CXSPARSE)\n\n  CXSPARSE_DNAME (_sfree) (S);\n  CXSPARSE_DNAME (_nfree) (N);\n\n#endif\n}\n\ntemplate <>\nSparseMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::V () const\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  return crs2ors (m_H, &m_cc);\n\n#elif defined (HAVE_CXSPARSE)\n\n  // Drop zeros from V and sort\n  // FIXME: Is the double transpose to sort necessary?\n\n  CXSPARSE_DNAME (_dropzeros) (N->L);\n  CXSPARSE_DNAME () *D = CXSPARSE_DNAME (_transpose) (N->L, 1);\n  CXSPARSE_DNAME (_spfree) (N->L);\n  N->L = CXSPARSE_DNAME (_transpose) (D, 1);\n  CXSPARSE_DNAME (_spfree) (D);\n\n  octave_idx_type nc = N->L->n;\n  octave_idx_type nz = N->L->p[nc];\n  SparseMatrix ret (N->L->m, nc, nz);\n\n  for (octave_idx_type j = 0; j < nc+1; j++)\n    ret.xcidx (j) = N->L->p[j];\n\n  for (octave_idx_type j = 0; j < nz; j++)\n    {\n      ret.xridx (j) = N->L->i[j];\n      ret.xdata (j) = N->L->x[j];\n    }\n\n  return ret;\n\n#else\n\n  return SparseMatrix ();\n\n#endif\n}\n\ntemplate <>\nSparseMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::R (bool econ) const\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  octave_idx_type nr = from_size_t (m_R->nrow);\n  octave_idx_type nc = from_size_t (m_R->ncol);\n  octave_idx_type nz\n    = from_suitesparse_long\n      (cholmod_l_nnz (m_R, const_cast<cholmod_common *> (&m_cc)));\n\n  // FIXME: Does this work if econ = true?\n  SparseMatrix ret ((econ ? (nc > nr ? nr : nc) : nr), nc, nz);\n  SuiteSparse_long *Rp = reinterpret_cast<SuiteSparse_long *> (m_R->p);\n  SuiteSparse_long *Ri = reinterpret_cast<SuiteSparse_long *> (m_R->i);\n\n  for (octave_idx_type j = 0; j < nc + 1; j++)\n    ret.xcidx (j) = from_suitesparse_long (Rp[j]);\n\n  for (octave_idx_type j = 0; j < nz; j++)\n    {\n      ret.xridx (j) = from_suitesparse_long (Ri[j]);\n      ret.xdata (j) = (reinterpret_cast<double *> (m_R->x))[j];\n    }\n\n  return ret;\n\n#elif defined (HAVE_CXSPARSE)\n\n  // Drop zeros from R and sort\n  // FIXME: Is the double transpose to sort necessary?\n\n  CXSPARSE_DNAME (_dropzeros) (N->U);\n  CXSPARSE_DNAME () *D = CXSPARSE_DNAME (_transpose) (N->U, 1);\n  CXSPARSE_DNAME (_spfree) (N->U);\n  N->U = CXSPARSE_DNAME (_transpose) (D, 1);\n  CXSPARSE_DNAME (_spfree) (D);\n\n  octave_idx_type nc = N->U->n;\n  octave_idx_type nz = N->U->p[nc];\n\n  SparseMatrix ret ((econ ? (nc > nrows ? nrows : nc) : nrows), nc, nz);\n\n  for (octave_idx_type j = 0; j < nc+1; j++)\n    ret.xcidx (j) = N->U->p[j];\n\n  for (octave_idx_type j = 0; j < nz; j++)\n    {\n      ret.xridx (j) = N->U->i[j];\n      ret.xdata (j) = N->U->x[j];\n    }\n\n  return ret;\n\n#else\n\n  octave_unused_parameter (econ);\n\n  return SparseMatrix ();\n\n#endif\n}\n\ntemplate <>\nMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::C (const Matrix& b, bool econ)\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n  octave_idx_type nr = (econ\n                        ? (ncols > nrows ? nrows : ncols)\n                        : nrows);\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n  Matrix ret (nr, b_nc);\n\n  if (nrows != b_nr)\n    (*current_liboctave_error_handler)\n      (\"sparse_qr: matrix dimension mismatch\");\n  else if (b_nc < 0 || b_nr < 0)\n    (*current_liboctave_error_handler)\n      (\"sparse_qr: matrix dimension with negative size\");\n\n  cholmod_dense *QTB;  // Q' * B\n  cholmod_dense B = ord2crd (b);\n\n  QTB = SuiteSparseQR_qmult<double> (SPQR_QTX, m_H, m_Htau, m_HPinv, &B,\n                                     &m_cc);\n  spqr_error_handler (&m_cc);\n\n  // copy QTB into ret\n  double *QTB_x = reinterpret_cast<double *> (QTB->x);\n  double *ret_vec = reinterpret_cast<double *> (ret.rwdata ());\n  for (octave_idx_type j = 0; j < b_nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      ret_vec[j * nr + i] = QTB_x[j * b_nr + i];\n\n  cholmod_l_free_dense (&QTB, &m_cc);\n\n  return ret;\n\n#elif defined (HAVE_CXSPARSE)\n\n  if (econ)\n    (*current_liboctave_error_handler)\n      (\"sparse-qr: economy mode with CXSparse not supported\");\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  octave_idx_type nc = N->L->n;\n  octave_idx_type nr = nrows;\n\n  const double *bvec = b.data ();\n\n  Matrix ret (b_nr, b_nc);\n  double *vec = ret.rwdata ();\n\n  if (nr < 0 || nc < 0 || nr != b_nr)\n    (*current_liboctave_error_handler) (\"matrix dimension mismatch\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    ret = Matrix (nc, b_nc, 0.0);\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (double, buf, S->m2);\n\n      for (octave_idx_type j = 0, idx = 0;\n           j < b_nc;\n           j++, idx += b_nr)\n        {\n          octave_quit ();\n\n          for (octave_idx_type i = nr; i < S->m2; i++)\n            buf[i] = 0.;\n\n          octave_idx_type nm = (nr < nc ? nr : nc);\n\n          CXSPARSE_DNAME (_ipvec) (S->pinv, bvec + idx, buf, b_nr);\n\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              octave_quit ();\n\n              CXSPARSE_DNAME (_happly) (N->L, i, N->B[i], buf);\n            }\n\n          for (octave_idx_type i = 0; i < b_nr; i++)\n            vec[i+idx] = buf[i];\n        }\n    }\n\n  return ret;\n\n#else\n\n  octave_unused_parameter (b);\n  octave_unused_parameter (econ);\n\n  return Matrix ();\n\n#endif\n}\n\ntemplate <>\nMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::Q (bool econ)\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  octave_idx_type nc = (econ\n                        ? (ncols > nrows ? nrows : ncols)\n                        : nrows);\n  Matrix ret (nrows, nc);\n  cholmod_dense *q;\n\n  // I is nrows x nrows identity matrix\n  cholmod_dense *I_mat\n    = cholmod_l_allocate_dense (nrows, nrows, nrows, CHOLMOD_REAL, &m_cc);\n\n  for (octave_idx_type i = 0; i < nrows * nrows; i++)\n    (reinterpret_cast<double *> (I_mat->x))[i] = 0.0;\n\n  for (octave_idx_type i = 0; i < nrows; i++)\n    (reinterpret_cast<double *> (I_mat->x))[i * nrows + i] = 1.0;\n\n  q = SuiteSparseQR_qmult<double> (SPQR_QX, m_H, m_Htau, m_HPinv, I_mat,\n                                   &m_cc);\n  spqr_error_handler (&m_cc);\n\n  double *q_x = reinterpret_cast<double *> (q->x);\n  double *ret_vec = const_cast<double *> (ret.rwdata ());\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nrows; i++)\n      ret_vec[j * nrows + i] = q_x[j * nrows + i];\n\n  cholmod_l_free_dense (&q, &m_cc);\n  cholmod_l_free_dense (&I_mat, &m_cc);\n\n  return ret;\n\n#elif defined (HAVE_CXSPARSE)\n\n  if (econ)\n    (*current_liboctave_error_handler)\n      (\"sparse-qr: economy mode with CXSparse not supported\");\n\n  octave_idx_type nc = N->L->n;\n  octave_idx_type nr = nrows;\n  Matrix ret (nr, nr);\n  double *ret_vec = ret.rwdata ();\n\n  if (nr < 0 || nc < 0)\n    (*current_liboctave_error_handler) (\"matrix dimension mismatch\");\n\n  if (nr == 0 || nc == 0)\n    ret = Matrix (nc, nr, 0.0);\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (double, bvec, nr + 1);\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        bvec[i] = 0.;\n\n      OCTAVE_LOCAL_BUFFER (double, buf, S->m2);\n\n      for (octave_idx_type j = 0, idx = 0; j < nr; j++, idx += nr)\n        {\n          octave_quit ();\n\n          bvec[j] = 1.0;\n          for (octave_idx_type i = nr; i < S->m2; i++)\n            buf[i] = 0.;\n\n          octave_idx_type nm = (nr < nc ? nr : nc);\n\n          CXSPARSE_DNAME (_ipvec) (S->pinv, bvec, buf, nr);\n\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              octave_quit ();\n\n              CXSPARSE_DNAME (_happly) (N->L, i, N->B[i], buf);\n            }\n\n          for (octave_idx_type i = 0; i < nr; i++)\n            ret_vec[i+idx] = buf[i];\n\n          bvec[j] = 0.0;\n        }\n    }\n\n  return ret.transpose ();\n\n#else\n\n  octave_unused_parameter (econ);\n\n  return Matrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::tall_solve<MArray<double>, Matrix>\n(const MArray<double>& b, octave_idx_type& info)\n{\n  info = -1;\n\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD) && defined (HAVE_CXSPARSE))\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n  Matrix x (ncols, b_nc);  // X = m_E'*(m_R\\(Q'*B))\n\n  if (nrows < 0 || ncols < 0 || b_nc < 0 || b_nr < 0)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension with negative size\");\n\n  if (nrows < 0 || ncols < 0 || nrows != b_nr)\n    (*current_liboctave_error_handler) (\"matrix dimension mismatch\");\n\n  cholmod_dense *QTB;  // Q' * B\n  cholmod_dense B = ord2crd (b);\n\n  // FIXME: Process b column by column as in the CXSPARSE version below.\n  // This avoids a large dense matrix Q' * B in memory.\n  QTB = SuiteSparseQR_qmult<double> (SPQR_QTX, m_H, m_Htau, m_HPinv, &B, &m_cc);\n\n  spqr_error_handler (&m_cc);\n\n  // convert m_R into CXSPARSE matrix R2\n  CXSPARSE_DNAME (_sparse) R2;\n  R2.n = ncols;\n  R2.m = ncols;\n  R2.nzmax = m_R->nzmax;\n  R2.x = reinterpret_cast<double *> (m_R->x);\n#  if defined (OCTAVE_SUITESPARSE_INTEGER_MATCH)\n  R2.p = reinterpret_cast<suitesparse_integer *> (m_R->p);\n  R2.i = reinterpret_cast<suitesparse_integer *> (m_R->i);\n#  else\n  suitesparse_integer *R2_p;\n  R2_p = new suitesparse_integer[ncols+1];\n  SuiteSparse_long *R_p = reinterpret_cast<SuiteSparse_long *> (m_R->p);\n  for (octave_idx_type i = 0; i < ncols+1; i++)\n    R2_p[i] = suitesparse_long_to_suitesparse_integer (R_p[i]);\n  R2.p = R2_p;\n\n  suitesparse_integer *R2_i;\n  octave_idx_type nnz = from_suitesparse_long (cholmod_l_nnz (m_R, &m_cc));\n  R2_i = new suitesparse_integer[nnz];\n  SuiteSparse_long *R_i = reinterpret_cast<SuiteSparse_long *> (m_R->i);\n  for (octave_idx_type i = 0; i < nnz; i++)\n    R2_i[i] =  suitesparse_long_to_suitesparse_integer (R_i[i]);\n  R2.i = R2_i;\n#  endif\n  R2.nz = -1;\n  double *x_vec = const_cast<double *> (x.rwdata ());\n  suitesparse_integer *E;\n#  if defined (OCTAVE_SUITESPARSE_INTEGER_MATCH)\n  E = reinterpret_cast<suitesparse_integer *> (m_E);\n#  else\n  E = new suitesparse_integer [ncols];\n  for (octave_idx_type i = 0; i < ncols; i++)\n    E[i] = suitesparse_long_to_suitesparse_integer (m_E[i]);\n#  endif\n  for (octave_idx_type j = 0; j < b_nc; j++)\n    {\n      // fill x(:,j)\n      // solve (m_R\\(Q'*B(:,j)) and store result in QTB(:,j)\n      CXSPARSE_DNAME (_usolve)\n      (&R2, &(reinterpret_cast<double *> (QTB->x)[j * b_nr]));\n      // x(:,j) = m_E' * (m_R\\(Q'*B(:,j))\n      CXSPARSE_DNAME (_ipvec)\n      (E, &(reinterpret_cast<double *> (QTB->x)[j * b_nr]),\n       &x_vec[j * ncols], ncols);\n    }\n\n#  if ! defined (OCTAVE_SUITESPARSE_INTEGER_MATCH)\n  delete [] R2_p;\n  delete [] R2_i;\n  delete [] E;\n#  endif\n  cholmod_l_free_dense (&QTB, &m_cc);\n\n  info = 0;\n\n  return x;\n\n#elif defined (HAVE_CXSPARSE)\n\n  octave_idx_type nr = nrows;\n  octave_idx_type nc = ncols;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  const double *bvec = b.data ();\n\n  Matrix x (nc, b_nc);\n  double *vec = x.rwdata ();\n\n  OCTAVE_LOCAL_BUFFER (double, buf, S->m2);\n\n  for (octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;\n       i++, idx+=nc, bidx+=b_nr)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_ipvec) (S->pinv, bvec + bidx, buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_usolve) (N->U, buf);\n      CXSPARSE_DNAME (_ipvec) (S->q, buf, vec + idx, nc);\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return Matrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::wide_solve<MArray<double>, Matrix>\n(const MArray<double>& b, octave_idx_type& info) const\n{\n  info = -1;\n#if defined (HAVE_CXSPARSE)\n\n  // These are swapped because the original matrix was transposed in\n  // sparse_qr<SparseMatrix>::solve.\n\n  octave_idx_type nr = ncols;\n  octave_idx_type nc = nrows;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  const double *bvec = b.data ();\n\n  Matrix x (nc, b_nc);\n  double *vec = x.rwdata ();\n\n  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);\n\n  OCTAVE_LOCAL_BUFFER (double, buf, nbuf);\n\n  for (octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;\n       i++, idx+=nc, bidx+=b_nr)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_pvec) (S->q, bvec + bidx, buf, nr);\n      CXSPARSE_DNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_pvec) (S->pinv, buf, vec + idx, nc);\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n  octave_unused_parameter (b);\n\n  return Matrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nSparseMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::tall_solve<SparseMatrix, SparseMatrix>\n(const SparseMatrix& b, octave_idx_type& info)\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  octave_idx_type nr = nrows;\n  octave_idx_type nc = ncols;\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  SparseMatrix x (nc, b_nc, b.nnz ());\n  x.xcidx (0) = 0;\n\n  octave_idx_type x_nz = b.nnz ();\n  octave_idx_type ii = 0;\n\n  OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, buf, S->m2);\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        Xx[j] = b.xelem (j, i);\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_usolve) (N->U, buf);\n      CXSPARSE_DNAME (_ipvec) (S->q, buf, Xx, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          double tmp = Xx[j];\n\n          if (tmp != 0.0)\n            {\n              if (ii == x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = x_nz * (b_nc - i) / b_nc;\n                  sz = (sz > 10 ? sz : 10) + x_nz;\n                  x.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              x.xdata (ii) = tmp;\n              x.xridx (ii++) = j;\n            }\n        }\n\n      x.xcidx (i+1) = ii;\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return SparseMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nSparseMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::wide_solve<SparseMatrix, SparseMatrix>\n(const SparseMatrix& b, octave_idx_type& info) const\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  // These are swapped because the original matrix was transposed in\n  // sparse_qr<SparseMatrix>::solve.\n\n  octave_idx_type nr = ncols;\n  octave_idx_type nc = nrows;\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  SparseMatrix x (nc, b_nc, b.nnz ());\n  x.xcidx (0) = 0;\n\n  octave_idx_type x_nz = b.nnz ();\n  octave_idx_type ii = 0;\n  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);\n\n  OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, buf, nbuf);\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        Xx[j] = b.xelem (j, i);\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr);\n      CXSPARSE_DNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xx, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          double tmp = Xx[j];\n\n          if (tmp != 0.0)\n            {\n              if (ii == x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = x_nz * (b_nc - i) / b_nc;\n                  sz = (sz > 10 ? sz : 10) + x_nz;\n                  x.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              x.xdata (ii) = tmp;\n              x.xridx (ii++) = j;\n            }\n        }\n\n      x.xcidx (i+1) = ii;\n    }\n\n  info = 0;\n\n  x.maybe_compress ();\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return SparseMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nComplexMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::tall_solve<MArray<Complex>, ComplexMatrix>\n(const MArray<Complex>& b, octave_idx_type& info)\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  octave_idx_type nr = nrows;\n  octave_idx_type nc = ncols;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  ComplexMatrix x (nc, b_nc);\n  Complex *vec = x.rwdata ();\n\n  OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, buf, S->m2);\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        {\n          Complex c = b.xelem (j, i);\n          Xx[j] = c.real ();\n          Xz[j] = c.imag ();\n        }\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_usolve) (N->U, buf);\n      CXSPARSE_DNAME (_ipvec) (S->q, buf, Xx, nc);\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_ipvec) (S->pinv, Xz, buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_usolve) (N->U, buf);\n      CXSPARSE_DNAME (_ipvec) (S->q, buf, Xz, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        vec[j+idx] = Complex (Xx[j], Xz[j]);\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return ComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nComplexMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::wide_solve<MArray<Complex>, ComplexMatrix>\n(const MArray<Complex>& b, octave_idx_type& info) const\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  // These are swapped because the original matrix was transposed in\n  // sparse_qr<SparseMatrix>::solve.\n\n  octave_idx_type nr = ncols;\n  octave_idx_type nc = nrows;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  ComplexMatrix x (nc, b_nc);\n  Complex *vec = x.rwdata ();\n\n  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);\n\n  OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, buf, nbuf);\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        {\n          Complex c = b.xelem (j, i);\n          Xx[j] = c.real ();\n          Xz[j] = c.imag ();\n        }\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr);\n      CXSPARSE_DNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xx, nc);\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_pvec) (S->q, Xz, buf, nr);\n      CXSPARSE_DNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xz, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        vec[j+idx] = Complex (Xx[j], Xz[j]);\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return ComplexMatrix ();\n\n#endif\n}\n\n// Complex-valued matrices.\n\ntemplate <>\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::sparse_qr_rep\n(const SparseComplexMatrix& a, int order)\n  : nrows (a.rows ()), ncols (a.columns ())\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n  , m_cc (), m_R (nullptr), m_E (nullptr), m_H (nullptr),\n    m_Htau (nullptr), m_HPinv (nullptr)\n{\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  if (nr < 0 || nc < 0)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension with negative size\");\n\n  if (order < 0 || order > 9)\n    (*current_liboctave_error_handler)\n      (\"ordering %d is not supported by SPQR\", order);\n\n  cholmod_l_start (&m_cc);\n  cholmod_sparse A = ocs2ccs (a);\n\n  SuiteSparseQR<Complex> (order, static_cast<double> (SPQR_DEFAULT_TOL),\n                          static_cast<SuiteSparse_long> (A.nrow),\n                          &A, &m_R, &m_E, &m_H,\n                          &m_HPinv, &m_Htau, &m_cc);\n  spqr_error_handler (&m_cc);\n\n#  if ! defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.i);\n#  endif\n}\n\n#elif defined (HAVE_CXSPARSE)\n  , S (nullptr), N (nullptr)\n{\n  CXSPARSE_ZNAME () A;\n\n  A.nzmax = a.nnz ();\n  A.m = nrows;\n  A.n = ncols;\n  // Cast away const on A, with full knowledge that CSparse won't touch it\n  // Prevents the methods below making a copy of the data.\n  A.p = const_cast<suitesparse_integer *>\n        (to_suitesparse_intptr (a.cidx ()));\n  A.i = const_cast<suitesparse_integer *>\n        (to_suitesparse_intptr (a.ridx ()));\n  A.x = const_cast<cs_complex_t *>\n        (reinterpret_cast<const cs_complex_t *> (a.data ()));\n  A.nz = -1;\n\n  S = CXSPARSE_ZNAME (_sqr) (order, &A, 1);\n  N = CXSPARSE_ZNAME (_qr) (&A, S);\n\n  if (! N)\n    (*current_liboctave_error_handler)\n      (\"sparse_qr: sparse matrix QR factorization filled\");\n\n}\n\n#else\n\n{\n  octave_unused_parameter (order);\n\n  (*current_liboctave_error_handler)\n    (\"sparse_qr: support for CXSparse was unavailable or disabled when liboctave was built\");\n}\n\n#endif\n\ntemplate <>\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::~sparse_qr_rep ()\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  cholmod_l_free_sparse (&m_R, &m_cc);\n  cholmod_l_free_sparse (&m_H, &m_cc);\n  cholmod_l_free_dense (&m_Htau, &m_cc);\n  free (m_E);  // FIXME: use cholmod_l_free\n  free (m_HPinv);\n  cholmod_l_finish (&m_cc);\n\n#elif defined (HAVE_CXSPARSE)\n\n  CXSPARSE_ZNAME (_sfree) (S);\n  CXSPARSE_ZNAME (_nfree) (N);\n\n#endif\n}\n\ntemplate <>\nSparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::V () const\n{\n#if defined (HAVE_CXSPARSE)\n  // Drop zeros from V and sort\n  // FIXME: Is the double transpose to sort necessary?\n\n  CXSPARSE_ZNAME (_dropzeros) (N->L);\n  CXSPARSE_ZNAME () *D = CXSPARSE_ZNAME (_transpose) (N->L, 1);\n  CXSPARSE_ZNAME (_spfree) (N->L);\n  N->L = CXSPARSE_ZNAME (_transpose) (D, 1);\n  CXSPARSE_ZNAME (_spfree) (D);\n\n  octave_idx_type nc = N->L->n;\n  octave_idx_type nz = N->L->p[nc];\n  SparseComplexMatrix ret (N->L->m, nc, nz);\n\n  for (octave_idx_type j = 0; j < nc+1; j++)\n    ret.xcidx (j) = N->L->p[j];\n\n  for (octave_idx_type j = 0; j < nz; j++)\n    {\n      ret.xridx (j) = N->L->i[j];\n      ret.xdata (j) = reinterpret_cast<Complex *> (N->L->x)[j];\n    }\n\n  return ret;\n\n#else\n\n  return SparseComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\nSparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::R (bool econ) const\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  octave_idx_type nr = from_size_t (m_R->nrow);\n  octave_idx_type nc = from_size_t (m_R->ncol);\n  octave_idx_type nz\n    = from_suitesparse_long\n      (cholmod_l_nnz (m_R, const_cast<cholmod_common *> (&m_cc)));\n\n  // FIXME: Does this work if econ = true?\n  SparseComplexMatrix ret ((econ ? (nc > nr ? nr : nc) : nr), nc, nz);\n  SuiteSparse_long *Rp = reinterpret_cast<SuiteSparse_long *> (m_R->p);\n  SuiteSparse_long *Ri = reinterpret_cast<SuiteSparse_long *> (m_R->i);\n\n  for (octave_idx_type j = 0; j < nc + 1; j++)\n    ret.xcidx (j) = from_suitesparse_long (Rp[j]);\n\n  for (octave_idx_type j = 0; j < nz; j++)\n    {\n      ret.xridx (j) = from_suitesparse_long (Ri[j]);\n      ret.xdata (j) = (reinterpret_cast<Complex *> (m_R->x))[j];\n    }\n\n  return ret;\n\n#elif defined (HAVE_CXSPARSE)\n\n  // Drop zeros from R and sort\n  // FIXME: Is the double transpose to sort necessary?\n\n  CXSPARSE_ZNAME (_dropzeros) (N->U);\n  CXSPARSE_ZNAME () *D = CXSPARSE_ZNAME (_transpose) (N->U, 1);\n  CXSPARSE_ZNAME (_spfree) (N->U);\n  N->U = CXSPARSE_ZNAME (_transpose) (D, 1);\n  CXSPARSE_ZNAME (_spfree) (D);\n\n  octave_idx_type nc = N->U->n;\n  octave_idx_type nz = N->U->p[nc];\n\n  SparseComplexMatrix ret ((econ ? (nc > nrows ? nrows : nc) : nrows),\n                           nc, nz);\n\n  for (octave_idx_type j = 0; j < nc+1; j++)\n    ret.xcidx (j) = N->U->p[j];\n\n  for (octave_idx_type j = 0; j < nz; j++)\n    {\n      ret.xridx (j) = N->U->i[j];\n      ret.xdata (j) = reinterpret_cast<Complex *> (N->U->x)[j];\n    }\n\n  return ret;\n\n#else\n\n  octave_unused_parameter (econ);\n\n  return SparseComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\nComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::C\n(const ComplexMatrix& b, bool econ)\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  // FIXME: not tested\n  octave_idx_type nr = (econ\n                        ? (ncols > nrows ? nrows : ncols)\n                        : nrows);\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n  ComplexMatrix ret (nr, b_nc);\n\n  if (nrows != b_nr)\n    (*current_liboctave_error_handler) (\"matrix dimension mismatch\");\n\n  if (b_nc < 0 || b_nr < 0)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension with negative size\");\n\n  cholmod_dense *QTB;  // Q' * B\n  cholmod_dense B = ocd2ccd (b);\n\n  QTB = SuiteSparseQR_qmult<Complex> (SPQR_QTX, m_H, m_Htau, m_HPinv, &B,\n                                      &m_cc);\n  spqr_error_handler (&m_cc);\n\n  // copy QTB into ret\n  Complex *QTB_x = reinterpret_cast<Complex *> (QTB->x);\n  Complex *ret_vec = reinterpret_cast<Complex *> (ret.rwdata ());\n  for (octave_idx_type j = 0; j < b_nc; j++)\n    for (octave_idx_type i = 0; i < nr; i++)\n      ret_vec[j * nr + i] = QTB_x[j * b_nr + i];\n\n  cholmod_l_free_dense (&QTB, &m_cc);\n\n  return ret;\n\n#elif defined (HAVE_CXSPARSE)\n\n  if (econ)\n    (*current_liboctave_error_handler)\n      (\"sparse-qr: economy mode with CXSparse not supported\");\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type nc = N->L->n;\n  octave_idx_type nr = nrows;\n  const cs_complex_t *bvec\n    = reinterpret_cast<const cs_complex_t *> (b.data ());\n  ComplexMatrix ret (b_nr, b_nc);\n  Complex *vec = ret.rwdata ();\n\n  if (nr < 0 || nc < 0 || nr != b_nr)\n    (*current_liboctave_error_handler) (\"matrix dimension mismatch\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    ret = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0));\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (Complex, buf, S->m2);\n\n      for (octave_idx_type j = 0, idx = 0;\n           j < b_nc;\n           j++, idx += b_nr)\n        {\n          octave_quit ();\n\n          octave_idx_type nm = (nr < nc ? nr : nc);\n\n          CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec + idx,\n                                   reinterpret_cast<cs_complex_t *> (buf),\n                                   b_nr);\n\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              octave_quit ();\n\n              CXSPARSE_ZNAME (_happly) (N->L, i, N->B[i],\n                                        reinterpret_cast<cs_complex_t *> (buf));\n            }\n\n          for (octave_idx_type i = 0; i < b_nr; i++)\n            vec[i+idx] = buf[i];\n        }\n    }\n\n  return ret;\n\n#else\n\n  octave_unused_parameter (b);\n  octave_unused_parameter (econ);\n\n  return ComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\nComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::Q (bool econ)\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  octave_idx_type nc = (econ\n                        ? (ncols > nrows ? nrows : ncols)\n                        : nrows);\n  ComplexMatrix ret (nrows, nc);\n  cholmod_dense *q;\n\n  // I is nrows x nrows identity matrix\n  cholmod_dense *I_mat\n    = reinterpret_cast<cholmod_dense *>\n      (cholmod_l_allocate_dense (nrows, nrows, nrows, CHOLMOD_COMPLEX, &m_cc));\n\n  for (octave_idx_type i = 0; i < nrows * nrows; i++)\n    (reinterpret_cast<Complex *> (I_mat->x))[i] = 0.0;\n\n  for (octave_idx_type i = 0; i < nrows; i++)\n    (reinterpret_cast<Complex *> (I_mat->x))[i * nrows + i] = 1.0;\n\n  q = SuiteSparseQR_qmult<Complex> (SPQR_QX, m_H, m_Htau, m_HPinv, I_mat,\n                                    &m_cc);\n  spqr_error_handler (&m_cc);\n\n  Complex *q_x = reinterpret_cast<Complex *> (q->x);\n  Complex *ret_vec = const_cast<Complex *> (ret.rwdata ());\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    for (octave_idx_type i = 0; i < nrows; i++)\n      ret_vec[j * nrows + i] = q_x[j * nrows + i];\n\n  cholmod_l_free_dense (&q, &m_cc);\n  cholmod_l_free_dense (&I_mat, &m_cc);\n\n  return ret;\n\n#elif defined (HAVE_CXSPARSE)\n\n  if (econ)\n    (*current_liboctave_error_handler)\n      (\"sparse-qr: economy mode with CXSparse not supported\");\n\n  octave_idx_type nc = N->L->n;\n  octave_idx_type nr = nrows;\n  ComplexMatrix ret (nr, nr);\n  Complex *vec = ret.rwdata ();\n\n  if (nr < 0 || nc < 0)\n    (*current_liboctave_error_handler) (\"matrix dimension mismatch\");\n\n  if (nr == 0 || nc == 0)\n    ret = ComplexMatrix (nc, nr, Complex (0.0, 0.0));\n  else\n    {\n      OCTAVE_LOCAL_BUFFER (cs_complex_t, bvec, nr);\n\n      for (octave_idx_type i = 0; i < nr; i++)\n        bvec[i] = 0.0;\n\n      OCTAVE_LOCAL_BUFFER (Complex, buf, S->m2);\n\n      for (octave_idx_type j = 0, idx = 0; j < nr; j++, idx+=nr)\n        {\n          octave_quit ();\n\n          bvec[j] = 1.0;\n\n          octave_idx_type nm = (nr < nc ? nr : nc);\n\n          CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec,\n                                   reinterpret_cast<cs_complex_t *> (buf),\n                                   nr);\n\n          for (octave_idx_type i = 0; i < nm; i++)\n            {\n              octave_quit ();\n\n              CXSPARSE_ZNAME (_happly) (N->L, i, N->B[i],\n                                        reinterpret_cast<cs_complex_t *> (buf));\n            }\n\n          for (octave_idx_type i = 0; i < nr; i++)\n            vec[i+idx] = buf[i];\n\n          bvec[j] = 0.0;\n        }\n    }\n\n  return ret.hermitian ();\n\n#else\n\n  octave_unused_parameter (econ);\n\n  return ComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nSparseComplexMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::tall_solve<SparseComplexMatrix,\n          SparseComplexMatrix>\n          (const SparseComplexMatrix& b, octave_idx_type& info)\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  octave_idx_type nr = nrows;\n  octave_idx_type nc = ncols;\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  SparseComplexMatrix x (nc, b_nc, b.nnz ());\n  x.xcidx (0) = 0;\n\n  octave_idx_type x_nz = b.nnz ();\n  octave_idx_type ii = 0;\n\n  OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, buf, S->m2);\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        {\n          Complex c = b.xelem (j, i);\n          Xx[j] = c.real ();\n          Xz[j] = c.imag ();\n        }\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_usolve) (N->U, buf);\n      CXSPARSE_DNAME (_ipvec) (S->q, buf, Xx, nc);\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_ipvec) (S->pinv, Xz, buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_usolve) (N->U, buf);\n      CXSPARSE_DNAME (_ipvec) (S->q, buf, Xz, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          Complex tmp = Complex (Xx[j], Xz[j]);\n\n          if (tmp != 0.0)\n            {\n              if (ii == x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = x_nz * (b_nc - i) / b_nc;\n                  sz = (sz > 10 ? sz : 10) + x_nz;\n                  x.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              x.xdata (ii) = tmp;\n              x.xridx (ii++) = j;\n            }\n        }\n\n      x.xcidx (i+1) = ii;\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return SparseComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nSparseComplexMatrix\nsparse_qr<SparseMatrix>::sparse_qr_rep::wide_solve<SparseComplexMatrix,\n          SparseComplexMatrix>\n          (const SparseComplexMatrix& b, octave_idx_type& info) const\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  // These are swapped because the original matrix was transposed in\n  // sparse_qr<SparseMatrix>::solve.\n\n  octave_idx_type nr = ncols;\n  octave_idx_type nc = nrows;\n\n  octave_idx_type b_nr = b.rows ();\n  octave_idx_type b_nc = b.cols ();\n\n  SparseComplexMatrix x (nc, b_nc, b.nnz ());\n  x.xcidx (0) = 0;\n\n  octave_idx_type x_nz = b.nnz ();\n  octave_idx_type ii = 0;\n  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);\n\n  OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (double, buf, nbuf);\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        {\n          Complex c = b.xelem (j, i);\n          Xx[j] = c.real ();\n          Xz[j] = c.imag ();\n        }\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr);\n      CXSPARSE_DNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xx, nc);\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.;\n\n      CXSPARSE_DNAME (_pvec) (S->q, Xz, buf, nr);\n      CXSPARSE_DNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xz, nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          Complex tmp = Complex (Xx[j], Xz[j]);\n\n          if (tmp != 0.0)\n            {\n              if (ii == x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = x_nz * (b_nc - i) / b_nc;\n                  sz = (sz > 10 ? sz : 10) + x_nz;\n                  x.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              x.xdata (ii) = tmp;\n              x.xridx (ii++) = j;\n            }\n        }\n\n      x.xcidx (i+1) = ii;\n    }\n\n  info = 0;\n\n  x.maybe_compress ();\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return SparseComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::tall_solve<MArray<double>,\n          ComplexMatrix>\n          (const MArray<double>& b, octave_idx_type& info)\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  octave_idx_type nr = nrows;\n  octave_idx_type nc = ncols;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  ComplexMatrix x (nc, b_nc);\n  cs_complex_t *vec = reinterpret_cast<cs_complex_t *> (x.rwdata ());\n\n  OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2);\n  OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        Xx[j] = b.xelem (j, i);\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.0;\n\n      CXSPARSE_ZNAME (_ipvec) (S->pinv,\n                               reinterpret_cast<cs_complex_t *> (Xx),\n                               buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_ZNAME (_usolve) (N->U, buf);\n      CXSPARSE_ZNAME (_ipvec) (S->q, buf, vec + idx, nc);\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return ComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::wide_solve<MArray<double>,\n          ComplexMatrix>\n          (const MArray<double>& b, octave_idx_type& info) const\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  // These are swapped because the original matrix was transposed in\n  // sparse_qr<SparseComplexMatrix>::solve.\n\n  octave_idx_type nr = ncols;\n  octave_idx_type nc = nrows;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  ComplexMatrix x (nc, b_nc);\n  cs_complex_t *vec = reinterpret_cast<cs_complex_t *> (x.rwdata ());\n\n  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);\n\n  OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf);\n  OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);\n  OCTAVE_LOCAL_BUFFER (double, B, nr);\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    B[i] = N->B[i];\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        Xx[j] = b.xelem (j, i);\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.0;\n\n      CXSPARSE_ZNAME (_pvec) (S->q, reinterpret_cast<cs_complex_t *> (Xx),\n                              buf, nr);\n      CXSPARSE_ZNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf);\n        }\n\n      CXSPARSE_ZNAME (_pvec) (S->pinv, buf, vec + idx, nc);\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return ComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nSparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::tall_solve<SparseMatrix,\n          SparseComplexMatrix>\n          (const SparseMatrix& b, octave_idx_type& info)\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  octave_idx_type nr = nrows;\n  octave_idx_type nc = ncols;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  SparseComplexMatrix x (nc, b_nc, b.nnz ());\n  x.xcidx (0) = 0;\n\n  octave_idx_type x_nz = b.nnz ();\n  octave_idx_type ii = 0;\n\n  OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2);\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        Xx[j] = b.xelem (j, i);\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.0;\n\n      CXSPARSE_ZNAME (_ipvec) (S->pinv,\n                               reinterpret_cast<cs_complex_t *> (Xx),\n                               buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_ZNAME (_usolve) (N->U, buf);\n      CXSPARSE_ZNAME (_ipvec) (S->q, buf,\n                               reinterpret_cast<cs_complex_t *> (Xx),\n                               nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          Complex tmp = Xx[j];\n\n          if (tmp != 0.0)\n            {\n              if (ii == x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = x_nz * (b_nc - i) / b_nc;\n                  sz = (sz > 10 ? sz : 10) + x_nz;\n                  x.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              x.xdata (ii) = tmp;\n              x.xridx (ii++) = j;\n            }\n        }\n\n      x.xcidx (i+1) = ii;\n    }\n\n  info = 0;\n\n  x.maybe_compress ();\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return SparseComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nSparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::wide_solve<SparseMatrix,\n          SparseComplexMatrix>\n          (const SparseMatrix& b, octave_idx_type& info) const\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  // These are swapped because the original matrix was transposed in\n  // sparse_qr<SparseComplexMatrix>::solve.\n\n  octave_idx_type nr = ncols;\n  octave_idx_type nc = nrows;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  SparseComplexMatrix x (nc, b_nc, b.nnz ());\n  x.xcidx (0) = 0;\n\n  octave_idx_type x_nz = b.nnz ();\n  octave_idx_type ii = 0;\n  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);\n\n  OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf);\n  OCTAVE_LOCAL_BUFFER (double, B, nr);\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    B[i] = N->B[i];\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        Xx[j] = b.xelem (j, i);\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.0;\n\n      CXSPARSE_ZNAME (_pvec) (S->q,\n                              reinterpret_cast<cs_complex_t *> (Xx),\n                              buf, nr);\n      CXSPARSE_ZNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf);\n        }\n\n      CXSPARSE_ZNAME (_pvec) (S->pinv, buf,\n                              reinterpret_cast<cs_complex_t *> (Xx),\n                              nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          Complex tmp = Xx[j];\n\n          if (tmp != 0.0)\n            {\n              if (ii == x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = x_nz * (b_nc - i) / b_nc;\n                  sz = (sz > 10 ? sz : 10) + x_nz;\n                  x.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              x.xdata (ii) = tmp;\n              x.xridx (ii++) = j;\n            }\n        }\n\n      x.xcidx (i+1) = ii;\n    }\n\n  info = 0;\n\n  x.maybe_compress ();\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return SparseComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::tall_solve<MArray<Complex>,\n          ComplexMatrix>\n          (const MArray<Complex>& b, octave_idx_type& info)\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  octave_idx_type nr = nrows;\n  octave_idx_type nc = ncols;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  const cs_complex_t *bvec = reinterpret_cast<const cs_complex_t *>\n                             (b.data ());\n\n  ComplexMatrix x (nc, b_nc);\n  cs_complex_t *vec = reinterpret_cast<cs_complex_t *>\n                      (x.rwdata ());\n\n  OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2);\n\n  for (octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;\n       i++, idx+=nc, bidx+=b_nr)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.0;\n\n      CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec + bidx, buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_ZNAME (_usolve) (N->U, buf);\n      CXSPARSE_ZNAME (_ipvec) (S->q, buf, vec + idx, nc);\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return ComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::wide_solve<MArray<Complex>,\n          ComplexMatrix>\n          (const MArray<Complex>& b, octave_idx_type& info) const\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  // These are swapped because the original matrix was transposed in\n  // sparse_qr<SparseComplexMatrix>::solve.\n\n  octave_idx_type nr = ncols;\n  octave_idx_type nc = nrows;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  const cs_complex_t *bvec = reinterpret_cast<const cs_complex_t *>\n                             (b.data ());\n\n  ComplexMatrix x (nc, b_nc);\n  cs_complex_t *vec = reinterpret_cast<cs_complex_t *> (x.rwdata ());\n\n  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);\n\n  OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf);\n  OCTAVE_LOCAL_BUFFER (double, B, nr);\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    B[i] = N->B[i];\n\n  for (octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;\n       i++, idx+=nc, bidx+=b_nr)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.0;\n\n      CXSPARSE_ZNAME (_pvec) (S->q, bvec + bidx, buf, nr);\n      CXSPARSE_ZNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf);\n        }\n\n      CXSPARSE_ZNAME (_pvec) (S->pinv, buf, vec + idx, nc);\n    }\n\n  info = 0;\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return ComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nSparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::tall_solve<SparseComplexMatrix,\n          SparseComplexMatrix>\n          (const SparseComplexMatrix& b, octave_idx_type& info)\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  octave_idx_type nr = nrows;\n  octave_idx_type nc = ncols;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  SparseComplexMatrix x (nc, b_nc, b.nnz ());\n  x.xcidx (0) = 0;\n\n  octave_idx_type x_nz = b.nnz ();\n  octave_idx_type ii = 0;\n\n  OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2);\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        Xx[j] = b.xelem (j, i);\n\n      for (octave_idx_type j = nr; j < S->m2; j++)\n        buf[j] = 0.0;\n\n      CXSPARSE_ZNAME (_ipvec) (S->pinv,\n                               reinterpret_cast<cs_complex_t *> (Xx),\n                               buf, nr);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf);\n        }\n\n      CXSPARSE_ZNAME (_usolve) (N->U, buf);\n      CXSPARSE_ZNAME (_ipvec) (S->q, buf,\n                               reinterpret_cast<cs_complex_t *> (Xx),\n                               nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          Complex tmp = Xx[j];\n\n          if (tmp != 0.0)\n            {\n              if (ii == x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = x_nz * (b_nc - i) / b_nc;\n                  sz = (sz > 10 ? sz : 10) + x_nz;\n                  x.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              x.xdata (ii) = tmp;\n              x.xridx (ii++) = j;\n            }\n        }\n\n      x.xcidx (i+1) = ii;\n    }\n\n  info = 0;\n\n  x.maybe_compress ();\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return SparseComplexMatrix ();\n\n#endif\n}\n\ntemplate <>\ntemplate <>\nSparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::sparse_qr_rep::wide_solve<SparseComplexMatrix,\n          SparseComplexMatrix>\n          (const SparseComplexMatrix& b, octave_idx_type& info) const\n{\n  info = -1;\n\n#if defined (HAVE_CXSPARSE)\n\n  // These are swapped because the original matrix was transposed in\n  // sparse_qr<SparseComplexMatrix>::solve.\n\n  octave_idx_type nr = ncols;\n  octave_idx_type nc = nrows;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  SparseComplexMatrix x (nc, b_nc, b.nnz ());\n  x.xcidx (0) = 0;\n\n  octave_idx_type x_nz = b.nnz ();\n  octave_idx_type ii = 0;\n  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);\n\n  OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc));\n  OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf);\n  OCTAVE_LOCAL_BUFFER (double, B, nr);\n\n  for (octave_idx_type i = 0; i < nr; i++)\n    B[i] = N->B[i];\n\n  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)\n    {\n      octave_quit ();\n\n      for (octave_idx_type j = 0; j < b_nr; j++)\n        Xx[j] = b.xelem (j, i);\n\n      for (octave_idx_type j = nr; j < nbuf; j++)\n        buf[j] = 0.0;\n\n      CXSPARSE_ZNAME (_pvec) (S->q, reinterpret_cast<cs_complex_t *> (Xx),\n                              buf, nr);\n      CXSPARSE_ZNAME (_utsolve) (N->U, buf);\n\n      for (octave_idx_type j = nr-1; j >= 0; j--)\n        {\n          octave_quit ();\n\n          CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf);\n        }\n\n      CXSPARSE_ZNAME (_pvec) (S->pinv, buf,\n                              reinterpret_cast<cs_complex_t *> (Xx), nc);\n\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          Complex tmp = Xx[j];\n\n          if (tmp != 0.0)\n            {\n              if (ii == x_nz)\n                {\n                  // Resize the sparse matrix\n                  octave_idx_type sz = x_nz * (b_nc - i) / b_nc;\n                  sz = (sz > 10 ? sz : 10) + x_nz;\n                  x.change_capacity (sz);\n                  x_nz = sz;\n                }\n\n              x.xdata (ii) = tmp;\n              x.xridx (ii++) = j;\n            }\n        }\n\n      x.xcidx (i+1) = ii;\n    }\n\n  info = 0;\n\n  x.maybe_compress ();\n\n  return x;\n\n#else\n\n  octave_unused_parameter (b);\n\n  return SparseComplexMatrix ();\n\n#endif\n}\n\ntemplate <typename SPARSE_T>\nsparse_qr<SPARSE_T>::sparse_qr ()\n  : m_rep (new sparse_qr_rep (SPARSE_T (), 0))\n{ }\n\ntemplate <typename SPARSE_T>\nsparse_qr<SPARSE_T>::sparse_qr (const SPARSE_T& a, int order)\n  : m_rep (new sparse_qr_rep (a, order))\n{ }\n\ntemplate <typename SPARSE_T>\nbool\nsparse_qr<SPARSE_T>::ok () const\n{\n  return m_rep->ok ();\n}\n\ntemplate <typename SPARSE_T>\nSPARSE_T\nsparse_qr<SPARSE_T>::V () const\n{\n  return m_rep->V ();\n}\n\ntemplate <typename SPARSE_T>\nColumnVector\nsparse_qr<SPARSE_T>::Pinv () const\n{\n  return m_rep->P ();\n}\n\ntemplate <typename SPARSE_T>\nColumnVector\nsparse_qr<SPARSE_T>::P () const\n{\n  return m_rep->P ();\n}\n\ntemplate <typename SPARSE_T>\nColumnVector\nsparse_qr<SPARSE_T>::E () const\n{\n  return m_rep->E();\n}\n\n\ntemplate <typename SPARSE_T>\nSparseMatrix\nsparse_qr<SPARSE_T>::E_MAT () const\n{\n  ColumnVector perm = m_rep->E ();\n  octave_idx_type nrows = perm.rows ();\n  SparseMatrix ret (nrows, nrows, nrows);\n  for (octave_idx_type i = 0; i < nrows; i++)\n    ret(perm(i) - 1, i) = 1.0;\n  return ret;\n}\n\n\ntemplate <typename SPARSE_T>\nSPARSE_T\nsparse_qr<SPARSE_T>::R (bool econ) const\n{\n  return m_rep->R (econ);\n}\n\ntemplate <typename SPARSE_T>\ntypename SPARSE_T::dense_matrix_type\nsparse_qr<SPARSE_T>::C (const typename SPARSE_T::dense_matrix_type& b,\n                        bool econ) const\n{\n  return m_rep->C (b, econ);\n}\n\ntemplate <typename SPARSE_T>\ntypename SPARSE_T::dense_matrix_type\nsparse_qr<SPARSE_T>::Q (bool econ) const\n{\n  return m_rep->Q (econ);\n}\n\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n//specializations of function min2norm_solve\ntemplate <>\ntemplate <>\nOCTAVE_API Matrix\nsparse_qr<SparseMatrix>::min2norm_solve<MArray<double>, Matrix>\n (const SparseMatrix& a, const MArray<double>& b, octave_idx_type& info, int order)\n{\n  info = -1;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type nc = a.cols ();\n  Matrix x (nc, b_nc);\n  cholmod_common cc;\n\n  cholmod_l_start (&cc);\n  cholmod_sparse A = ors2crs (a);\n  cholmod_dense B = ord2crd (b);\n  cholmod_dense *X;\n\n  X = SuiteSparseQR_min2norm<double> (order, SPQR_DEFAULT_TOL, &A, &B, &cc);\n  spqr_error_handler (&cc);\n\n  double *xdata = x.rwdata ();\n  for (octave_idx_type i = 0; i < nc * b_nc; i++)\n    xdata[i] = reinterpret_cast<double *> (X->x)[i];\n  info = 0;\n\n#  if ! defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.i);\n#  endif\n  cholmod_l_free_dense (&X, &cc);\n  cholmod_l_finish (&cc);\n\n  return x;\n}\n\ntemplate <>\ntemplate <>\nOCTAVE_API SparseMatrix\nsparse_qr<SparseMatrix>::min2norm_solve<SparseMatrix, SparseMatrix>\n (const SparseMatrix& a, const SparseMatrix& b, octave_idx_type& info, int order)\n{\n  info = -1;\n\n  SparseMatrix x;\n  cholmod_common cc;\n\n  cholmod_l_start (&cc);\n  cholmod_sparse A = ors2crs (a);\n  cholmod_sparse B = ors2crs (b);\n  cholmod_sparse *X;\n\n  X = SuiteSparseQR_min2norm<double> (order, SPQR_DEFAULT_TOL, &A, &B, &cc);\n  spqr_error_handler (&cc);\n\n  x = crs2ors (X, &cc);\n  info = 0;\n\n  #if ! defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.i);\n  delete [] reinterpret_cast<SuiteSparse_long *> (B.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (B.i);\n  #endif\n  cholmod_l_free_sparse (&X, &cc);\n  cholmod_l_finish (&cc);\n\n  return x;\n}\n\ntemplate <>\ntemplate <>\nOCTAVE_API ComplexMatrix\nsparse_qr<SparseMatrix>::min2norm_solve<MArray<Complex>, ComplexMatrix>\n (const SparseMatrix& a, const MArray<Complex>& b, octave_idx_type& info, int order)\n{\n  info = -1;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type nc = a.cols ();\n  ComplexMatrix x (nc, b_nc);\n  cholmod_common cc;\n\n  cholmod_l_start (&cc);\n  cholmod_sparse *A = ors2ccs (a, &cc);\n  cholmod_dense B = ocd2ccd (b);\n  cholmod_dense *X;\n\n  X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, A, &B, &cc);\n  spqr_error_handler (&cc);\n\n  Complex *xdata = x.rwdata ();\n  for (octave_idx_type i = 0; i < nc * b_nc; i++)\n    xdata[i] = reinterpret_cast<Complex *> (X->x)[i];\n  info = 0;\n\n  cholmod_l_free_sparse (&A, &cc);\n  cholmod_l_free_dense (&X, &cc);\n  cholmod_l_finish (&cc);\n\n  return x;\n}\n\ntemplate <>\ntemplate <>\nOCTAVE_API SparseComplexMatrix\nsparse_qr<SparseMatrix>::min2norm_solve<SparseComplexMatrix, SparseComplexMatrix>\n (const SparseMatrix& a, const SparseComplexMatrix& b, octave_idx_type& info, int order)\n{\n  info = -1;\n\n  cholmod_common cc;\n\n  cholmod_l_start (&cc);\n  cholmod_sparse *A = ors2ccs (a, &cc);\n  cholmod_sparse B = ocs2ccs (b);\n  cholmod_sparse *X;\n\n  X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, A, &B, &cc);\n  spqr_error_handler (&cc);\n\n  SparseComplexMatrix ret = ccs2ocs (X, &cc);\n  info = 0;\n\n#  if ! defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  delete [] reinterpret_cast<SuiteSparse_long *> (B.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (B.i);\n#  endif\n  cholmod_l_free_sparse (&A, &cc);\n  cholmod_l_free_sparse (&X, &cc);\n  cholmod_l_finish (&cc);\n\n  return ret;\n}\n\ntemplate <>\ntemplate <>\nOCTAVE_API ComplexMatrix\nsparse_qr<SparseComplexMatrix>::min2norm_solve<MArray<Complex>, ComplexMatrix>\n (const SparseComplexMatrix& a, const MArray<Complex>& b, octave_idx_type& info, int order)\n{\n  info = -1;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type nc = a.cols ();\n  ComplexMatrix x (nc, b_nc);\n  cholmod_common cc;\n\n  cholmod_l_start (&cc);\n  cholmod_sparse A = ocs2ccs (a);\n  cholmod_dense B = ocd2ccd (b);\n  cholmod_dense *X;\n\n  X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, &B, &cc);\n  spqr_error_handler (&cc);\n\n  Complex *xdata = x.rwdata ();\n  for (octave_idx_type i = 0; i < nc * b_nc; i++)\n    xdata[i] = reinterpret_cast<Complex *> (X->x)[i];\n  info = 0;\n\n#  if ! defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.i);\n#  endif\n  cholmod_l_free_dense (&X, &cc);\n  cholmod_l_finish (&cc);\n\n  return x;\n}\n\n// FIXME: 2024/01/07: This template specialization does not appear to be\n// reachable from current Octave code calling qrsolve from sparse-dmsolve.cc.\n// It remains because liboctave may be used by other C++ code besides the\n// Octave interpreter.\ntemplate <>\ntemplate <>\nOCTAVE_API ComplexMatrix\nsparse_qr<SparseComplexMatrix>::min2norm_solve<MArray<double>, ComplexMatrix>\n (const SparseComplexMatrix& a, const MArray<double>& b, octave_idx_type& info, int order)\n{\n  info = -1;\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type nc = a.cols ();\n  ComplexMatrix x (nc, b_nc);\n  cholmod_common cc;\n\n  cholmod_l_start (&cc);\n  cholmod_sparse A = ocs2ccs (a);\n  cholmod_dense *B = ord2ccd (b, &cc);\n  cholmod_dense *X;\n\n  X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, B, &cc);\n  spqr_error_handler (&cc);\n\n  Complex *xdata = x.rwdata ();\n  for (octave_idx_type i = 0; i < nc * b_nc; i++)\n    xdata[i] = reinterpret_cast<Complex *> (X->x)[i];\n  info = 0;\n\n#  if ! defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.i);\n#  endif\n  cholmod_l_free_dense (&B, &cc);\n  cholmod_l_free_dense (&X, &cc);\n  cholmod_l_finish (&cc);\n\n  return x;\n}\n\ntemplate <>\ntemplate <>\nOCTAVE_API SparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::min2norm_solve<SparseComplexMatrix, SparseComplexMatrix>\n (const SparseComplexMatrix& a, const SparseComplexMatrix& b, octave_idx_type& info, int order)\n{\n  info = -1;\n\n  cholmod_common cc;\n\n  cholmod_l_start (&cc);\n  cholmod_sparse A = ocs2ccs (a);\n  cholmod_sparse B = ocs2ccs (b);\n  cholmod_sparse *X;\n\n  X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, &B, &cc);\n  spqr_error_handler (&cc);\n\n  SparseComplexMatrix ret = ccs2ocs (X, &cc);\n  info = 0;\n\n#  if ! defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.i);\n  delete [] reinterpret_cast<SuiteSparse_long *> (B.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (B.i);\n#  endif\n  cholmod_l_free_sparse (&X, &cc);\n  cholmod_l_finish (&cc);\n\n  return ret;\n}\n\n// FIXME: 2024/01/07: This template specialization does not appear to be\n// reachable from current Octave code calling qrsolve from sparse-dmsolve.cc.\n// It remains because liboctave may be used by other C++ code besides the\n// Octave interpreter.\ntemplate <>\ntemplate <>\nOCTAVE_API SparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::min2norm_solve<SparseMatrix, SparseComplexMatrix>\n (const SparseComplexMatrix& a, const SparseMatrix& b, octave_idx_type& info, int order)\n{\n  info = -1;\n\n  cholmod_common cc;\n\n  cholmod_l_start (&cc);\n  cholmod_sparse A = ocs2ccs (a);\n  cholmod_sparse *B = ors2ccs (b, &cc);\n  cholmod_sparse *X;\n\n  X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, B, &cc);\n  spqr_error_handler (&cc);\n\n  SparseComplexMatrix ret = ccs2ocs (X, &cc);\n  info = 0;\n\n#  if ! defined (OCTAVE_SUITESPARSE_LONG_MATCH)\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.p);\n  delete [] reinterpret_cast<SuiteSparse_long *> (A.i);\n#  endif\n  cholmod_l_free_sparse (&B, &cc);\n  cholmod_l_free_sparse (&X, &cc);\n  cholmod_l_finish (&cc);\n\n  return ret;\n}\n#endif\n\n// FIXME: Why is the \"order\" of the QR calculation as used in the\n// CXSparse function sqr 3 for real matrices and 2 for complex?  These\n// values seem to be required but there was no explanation in David\n// Bateman's original code.\n\ntemplate <typename SPARSE_T>\nclass cxsparse_defaults\n{\npublic:\n  enum { order = -1 };\n};\n\ntemplate <>\nclass cxsparse_defaults<SparseMatrix>\n{\npublic:\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n  enum { order = SPQR_ORDERING_DEFAULT };\n#elif defined (HAVE_CXSPARSE)\n  enum { order = 3 };\n#endif\n};\n\ntemplate <>\nclass cxsparse_defaults<SparseComplexMatrix>\n{\npublic:\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n  enum { order = SPQR_ORDERING_DEFAULT };\n#elif defined (HAVE_CXSPARSE)\n  enum { order = 2 };\n#endif\n};\n\ntemplate <typename SPARSE_T>\ntemplate <typename RHS_T, typename RET_T>\nRET_T\nsparse_qr<SPARSE_T>::solve (const SPARSE_T& a, const RHS_T& b,\n                            octave_idx_type& info)\n{\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n\n  info = -1;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  int order = cxsparse_defaults<SPARSE_T>::order;\n\n  if (nr < 0 || nc < 0 || b_nc < 0 || b_nr < 0)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension with negative size\");\n\n  if ( nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch in solution of minimum norm problem\");\n\n  info = 0;\n\n  return min2norm_solve<RHS_T, RET_T> (a, b, info, order);\n\n#elif defined (HAVE_CXSPARSE)\n\n  info = -1;\n\n  octave_idx_type nr = a.rows ();\n  octave_idx_type nc = a.cols ();\n\n  octave_idx_type b_nc = b.cols ();\n  octave_idx_type b_nr = b.rows ();\n\n  int order = cxsparse_defaults<SPARSE_T>::order;\n\n  if (nr < 0 || nc < 0 || nr != b_nr)\n    (*current_liboctave_error_handler)\n      (\"matrix dimension mismatch in solution of minimum norm problem\");\n\n  if (nr == 0 || nc == 0 || b_nc == 0)\n    {\n      info = 0;\n\n      return RET_T (nc, b_nc, 0.0);\n    }\n  else if (nr >= nc)\n    {\n      sparse_qr<SPARSE_T> q (a, order);\n\n      return q.ok () ? q.tall_solve<RHS_T, RET_T> (b, info) : RET_T ();\n    }\n  else\n    {\n      sparse_qr<SPARSE_T> q (a.hermitian (), order);\n\n      return q.ok () ? q.wide_solve<RHS_T, RET_T> (b, info) : RET_T ();\n    }\n\n#else\n\n  octave_unused_parameter (a);\n  octave_unused_parameter (b);\n  octave_unused_parameter (info);\n\n  return RET_T ();\n\n#endif\n}\n\n//explicit instantiations of static member function solve\ntemplate\nOCTAVE_API Matrix\nsparse_qr<SparseMatrix>::solve<MArray<double>, Matrix>\n(const SparseMatrix& a, const MArray<double>& b, octave_idx_type& info);\n\ntemplate\nOCTAVE_API SparseMatrix\nsparse_qr<SparseMatrix>::solve<SparseMatrix, SparseMatrix>\n(const SparseMatrix& a, const SparseMatrix& b, octave_idx_type& info);\n\ntemplate\nOCTAVE_API ComplexMatrix\nsparse_qr<SparseMatrix>::solve<MArray<Complex>, ComplexMatrix>\n(const SparseMatrix& a, const MArray<Complex>& b, octave_idx_type& info);\n\ntemplate\nOCTAVE_API SparseComplexMatrix\nsparse_qr<SparseMatrix>::solve<SparseComplexMatrix, SparseComplexMatrix>\n(const SparseMatrix& a, const SparseComplexMatrix& b,\n octave_idx_type& info);\n\ntemplate\nOCTAVE_API ComplexMatrix\nsparse_qr<SparseComplexMatrix>::solve<MArray<Complex>, ComplexMatrix>\n(const SparseComplexMatrix& a, const MArray<Complex>& b,\n octave_idx_type& info);\n\ntemplate\nOCTAVE_API SparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::solve<\nSparseComplexMatrix, SparseComplexMatrix>\n(const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n octave_idx_type& info);\n\ntemplate\nOCTAVE_API ComplexMatrix\nsparse_qr<SparseComplexMatrix>::solve<MArray<double>, ComplexMatrix>\n(const SparseComplexMatrix& a, const MArray<double>& b,\n octave_idx_type& info);\n\ntemplate\nOCTAVE_API SparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::solve<SparseMatrix, SparseComplexMatrix>\n(const SparseComplexMatrix& a, const SparseMatrix& b,\n octave_idx_type& info);\n\n//explicit instantiations of member function E_MAT\ntemplate\nOCTAVE_API SparseMatrix\nsparse_qr<SparseMatrix>::E_MAT () const;\n\ntemplate\nOCTAVE_API SparseMatrix\nsparse_qr<SparseComplexMatrix>::E_MAT () const;\n\ntemplate <typename SPARSE_T>\ntemplate <typename RHS_T, typename RET_T>\nRET_T\nsparse_qr<SPARSE_T>::tall_solve (const RHS_T& b, octave_idx_type& info) const\n{\n  return m_rep->template tall_solve<RHS_T, RET_T> (b, info);\n}\n\ntemplate <typename SPARSE_T>\ntemplate <typename RHS_T, typename RET_T>\nRET_T\nsparse_qr<SPARSE_T>::wide_solve (const RHS_T& b, octave_idx_type& info) const\n{\n  return m_rep->template wide_solve<RHS_T, RET_T> (b, info);\n}\n\n// Explicitly instantiate all member functions\n\ntemplate OCTAVE_API sparse_qr<SparseMatrix>::sparse_qr ();\ntemplate OCTAVE_API\nsparse_qr<SparseMatrix>::sparse_qr (const SparseMatrix& a, int order);\ntemplate OCTAVE_API bool sparse_qr<SparseMatrix>::ok () const;\ntemplate OCTAVE_API ColumnVector sparse_qr<SparseMatrix>::E () const;\ntemplate OCTAVE_API SparseMatrix sparse_qr<SparseMatrix>::V () const;\ntemplate OCTAVE_API ColumnVector sparse_qr<SparseMatrix>::Pinv () const;\ntemplate OCTAVE_API ColumnVector sparse_qr<SparseMatrix>::P () const;\ntemplate OCTAVE_API SparseMatrix\nsparse_qr<SparseMatrix>::R (bool econ) const;\ntemplate OCTAVE_API Matrix\nsparse_qr<SparseMatrix>::C (const Matrix& b, bool econ) const;\ntemplate OCTAVE_API Matrix sparse_qr<SparseMatrix>::Q (bool econ) const;\n\ntemplate OCTAVE_API sparse_qr<SparseComplexMatrix>::sparse_qr ();\ntemplate OCTAVE_API\nsparse_qr<SparseComplexMatrix>::sparse_qr\n(const SparseComplexMatrix& a, int order);\ntemplate OCTAVE_API bool sparse_qr<SparseComplexMatrix>::ok () const;\ntemplate OCTAVE_API ColumnVector\nsparse_qr<SparseComplexMatrix>::E () const;\ntemplate OCTAVE_API SparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::V () const;\ntemplate OCTAVE_API ColumnVector\nsparse_qr<SparseComplexMatrix>::Pinv () const;\ntemplate OCTAVE_API ColumnVector\nsparse_qr<SparseComplexMatrix>::P () const;\ntemplate OCTAVE_API SparseComplexMatrix\nsparse_qr<SparseComplexMatrix>::R (bool econ) const;\ntemplate OCTAVE_API ComplexMatrix\nsparse_qr<SparseComplexMatrix>::C (const ComplexMatrix& b, bool econ) const;\ntemplate OCTAVE_API ComplexMatrix\nsparse_qr<SparseComplexMatrix>::Q (bool econ) const;\n\nMatrix\nqrsolve (const SparseMatrix& a, const MArray<double>& b,\n         octave_idx_type& info)\n{\n  return sparse_qr<SparseMatrix>::solve<MArray<double>, Matrix> (a, b,\n         info);\n}\n\nSparseMatrix\nqrsolve (const SparseMatrix& a, const SparseMatrix& b,\n         octave_idx_type& info)\n{\n  return sparse_qr<SparseMatrix>::solve<SparseMatrix, SparseMatrix> (a, b,\n         info);\n}\n\nComplexMatrix\nqrsolve (const SparseMatrix& a, const MArray<Complex>& b,\n         octave_idx_type& info)\n{\n  return sparse_qr<SparseMatrix>::solve<MArray<Complex>,\n         ComplexMatrix> (a, b, info);\n}\n\nSparseComplexMatrix\nqrsolve (const SparseMatrix& a, const SparseComplexMatrix& b,\n         octave_idx_type& info)\n{\n  return sparse_qr<SparseMatrix>::solve<SparseComplexMatrix,\n         SparseComplexMatrix> (a, b, info);\n}\n\nComplexMatrix\nqrsolve (const SparseComplexMatrix& a, const MArray<double>& b,\n         octave_idx_type& info)\n{\n  return sparse_qr<SparseComplexMatrix>::solve<MArray<double>,\n         ComplexMatrix> (a, b, info);\n}\n\nSparseComplexMatrix\nqrsolve (const SparseComplexMatrix& a, const SparseMatrix& b,\n         octave_idx_type& info)\n{\n  return sparse_qr<SparseComplexMatrix>::solve<SparseMatrix,\n         SparseComplexMatrix>\n         (a, b, info);\n}\n\nComplexMatrix\nqrsolve (const SparseComplexMatrix& a, const MArray<Complex>& b,\n         octave_idx_type& info)\n{\n  return sparse_qr<SparseComplexMatrix>::solve<MArray<Complex>,\n         ComplexMatrix> (a, b, info);\n}\n\nSparseComplexMatrix\nqrsolve (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n         octave_idx_type& info)\n{\n  return sparse_qr<SparseComplexMatrix>::solve<SparseComplexMatrix,\n         SparseComplexMatrix>\n         (a, b, info);\n}\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/sparse-qr.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_sparse_qr_h)\n#define octave_sparse_qr_h 1\n\n#include \"octave-config.h\"\n\n#include <memory>\n\n#include \"oct-cmplx.h\"\n#include \"MArray-fwd.h\"\n#include \"mx-fwd.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\n// If the sparse matrix classes become templated on the element type\n// (i.e., sparse_matrix<double>), then it might be best to make the\n// template parameter of this class also be the element type instead\n// of the matrix type.\n\ntemplate <typename SPARSE_T>\nclass sparse_qr\n{\npublic:\n\n  OCTAVE_API sparse_qr ();\n\n#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))\n  // order = 7 selects SPQR default ordering\n  OCTAVE_API sparse_qr (const SPARSE_T& a, int order = 7);\n#elif defined (HAVE_CXSPARSE)\n  // order = 3 selects CXSparse default ordering\n  OCTAVE_API sparse_qr (const SPARSE_T& a, int order = 3);\n#else\n  OCTAVE_API sparse_qr (const SPARSE_T& a, int order = 0);\n#endif\n\n  sparse_qr (const sparse_qr& a) = default;\n\n  ~sparse_qr () = default;\n\n  sparse_qr& operator = (const sparse_qr& a) = default;\n\n  OCTAVE_API bool ok () const;\n\n  OCTAVE_API ColumnVector E () const;\n\n  // constructs permutation matrix from permutation vector rep -> E()\n  OCTAVE_API SparseMatrix E_MAT () const;\n\n  OCTAVE_API SPARSE_T V () const;\n\n  OCTAVE_API ColumnVector Pinv () const;\n\n  OCTAVE_API ColumnVector P () const;\n\n  OCTAVE_API SPARSE_T R (bool econ = false) const;\n\n  OCTAVE_API typename SPARSE_T::dense_matrix_type\n  C (const typename SPARSE_T::dense_matrix_type& b, bool econ = false) const;\n\n  OCTAVE_API typename SPARSE_T::dense_matrix_type\n  Q (bool econ = false) const;\n\n  template <typename RHS_T, typename RET_T>\n  static OCTAVE_API RET_T\n  solve (const SPARSE_T& a, const RHS_T& b,\n         octave_idx_type& info);\n\nprivate:\n\n  template <typename RHS_T, typename RET_T>\n  static OCTAVE_API RET_T\n  min2norm_solve (const SPARSE_T& a, const RHS_T& b,\n                  octave_idx_type& info, int order);\n\n  template <typename RHS_T, typename RET_T>\n  OCTAVE_API RET_T\n  tall_solve (const RHS_T& b, octave_idx_type& info) const;\n\n  template <typename RHS_T, typename RET_T>\n  OCTAVE_API RET_T\n  wide_solve (const RHS_T& b, octave_idx_type& info) const;\n\n  //--------\n  class sparse_qr_rep;\n\n  std::shared_ptr<sparse_qr_rep> m_rep;\n};\n\n// extern instantiations with set visibility/export/import attribute\n\nextern template class OCTAVE_API sparse_qr<SparseMatrix>;\n\nextern template class OCTAVE_API sparse_qr<SparseComplexMatrix>;\n\n// Provide qrsolve for backward compatibility.\n\nextern OCTAVE_API Matrix\nqrsolve (const SparseMatrix& a, const MArray<double>& b,\n         octave_idx_type& info);\n\nextern OCTAVE_API SparseMatrix\nqrsolve (const SparseMatrix& a, const SparseMatrix& b,\n         octave_idx_type& info);\n\nextern OCTAVE_API ComplexMatrix\nqrsolve (const SparseMatrix& a, const MArray<Complex>& b,\n         octave_idx_type& info);\n\nextern OCTAVE_API SparseComplexMatrix\nqrsolve (const SparseMatrix& a, const SparseComplexMatrix& b,\n         octave_idx_type& info);\n\nextern OCTAVE_API ComplexMatrix\nqrsolve (const SparseComplexMatrix& a, const MArray<double>& b,\n         octave_idx_type& info);\n\nextern OCTAVE_API SparseComplexMatrix\nqrsolve (const SparseComplexMatrix& a, const SparseMatrix& b,\n         octave_idx_type& info);\n\nextern OCTAVE_API ComplexMatrix\nqrsolve (const SparseComplexMatrix& a, const MArray<Complex>& b,\n         octave_idx_type& info);\n\nextern OCTAVE_API SparseComplexMatrix\nqrsolve (const SparseComplexMatrix& a, const SparseComplexMatrix& b,\n         octave_idx_type& info);\n\ntypedef sparse_qr<SparseMatrix> SparseQR;\ntypedef sparse_qr<SparseComplexMatrix> SparseComplexQR;\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/numeric/svd.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <unordered_map>\n\n#include \"CMatrix.h\"\n#include \"dDiagMatrix.h\"\n#include \"dMatrix.h\"\n#include \"fCMatrix.h\"\n#include \"fDiagMatrix.h\"\n#include \"fMatrix.h\"\n#include \"lapack-proto.h\"\n#include \"oct-error.h\"\n#include \"svd.h\"\n\n// class to compute optimal work space size (lwork) for DGEJSV and SGEJSV\ntemplate<typename T>\nclass gejsv_lwork\n{\npublic:\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE_DELETE (gejsv_lwork)\n\n  // Unfortunately, dgejsv and sgejsv do not provide estimation of 'lwork'.\n  // Thus, we have to estimate it according to corresponding LAPACK\n  // documentation and related source codes (e.g., cgejsv).\n  // In LAPACKE (C interface to LAPACK), the memory handling code in\n  // LAPACKE_dgejsv() (lapacke_dgejsv.c, last visit 2019-02-17) uses\n  // the minimum required working space.  In contrast, here the optimal\n  // working space size is computed, at the cost of much longer code.\n\n  static F77_INT optimal (char& joba, char& jobu, char& jobv,\n                          F77_INT m, F77_INT n);\n\nprivate:\n  typedef typename T::element_type P;\n\n  // functions could be called from GEJSV\n  static F77_INT geqp3_lwork (F77_INT m, F77_INT n,\n                              P *a, F77_INT lda,\n                              F77_INT *jpvt, P *tau, P *work,\n                              F77_INT lwork, F77_INT& info);\n\n  static F77_INT geqrf_lwork (F77_INT m, F77_INT n,\n                              P *a, F77_INT lda,\n                              P *tau, P *work,\n                              F77_INT lwork, F77_INT& info);\n\n  static F77_INT gelqf_lwork (F77_INT m, F77_INT n,\n                              P *a, F77_INT lda,\n                              P *tau, P *work,\n                              F77_INT lwork, F77_INT& info);\n\n  static F77_INT ormlq_lwork (char& side, char& trans,\n                              F77_INT m, F77_INT n, F77_INT k,\n                              P *a, F77_INT lda,\n                              P *tau, P *c, F77_INT ldc,\n                              P *work, F77_INT lwork, F77_INT& info);\n\n  static F77_INT ormqr_lwork (char& side, char& trans,\n                              F77_INT m, F77_INT n, F77_INT k,\n                              P *a, F77_INT lda,\n                              P *tau, P *c, F77_INT ldc,\n                              P *work, F77_INT lwork, F77_INT& info);\n};\n\n#define GEJSV_REAL_QP3_LWORK(f, F)                              \\\n  F77_XFCN (f, F, (m, n, a, lda, jpvt, tau, work, lwork, info))\n\n#define GEJSV_REAL_QR_LWORK(f, F)                               \\\n  F77_XFCN (f, F, (m, n, a, lda, tau, work, lwork, info))\n\n#define GEJSV_REAL_ORM_LWORK(f, F)                              \\\n  F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&side,  1),             \\\n                   F77_CONST_CHAR_ARG2 (&trans, 1),             \\\n                   m, n, k, a, lda, tau,                        \\\n                   c, ldc, work, lwork, info                    \\\n                   F77_CHAR_ARG_LEN (1)                         \\\n                   F77_CHAR_ARG_LEN (1)))\n\n// For Matrix\ntemplate<>\nF77_INT\ngejsv_lwork<Matrix>::geqp3_lwork (F77_INT m, F77_INT n,\n                                  P *a, F77_INT lda,\n                                  F77_INT *jpvt, P *tau, P *work,\n                                  F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_QP3_LWORK (dgeqp3, DGEQP3);\n  return static_cast<F77_INT> (work[0]);\n}\n\ntemplate<>\nF77_INT\ngejsv_lwork<Matrix>::geqrf_lwork (F77_INT m, F77_INT n,\n                                  P *a, F77_INT lda,\n                                  P *tau, P *work,\n                                  F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_QR_LWORK (dgeqrf, DGEQRF);\n  return static_cast<F77_INT> (work[0]);\n}\n\ntemplate<>\nF77_INT\ngejsv_lwork<Matrix>::gelqf_lwork (F77_INT m, F77_INT n,\n                                  P *a, F77_INT lda,\n                                  P *tau, P *work,\n                                  F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_QR_LWORK (dgelqf, DGELQF);\n  return static_cast<F77_INT> (work[0]);\n}\n\ntemplate<>\nF77_INT\ngejsv_lwork<Matrix>::ormlq_lwork (char& side, char& trans,\n                                  F77_INT m, F77_INT n, F77_INT k,\n                                  P *a, F77_INT lda,\n                                  P *tau, P *c, F77_INT ldc,\n                                  P *work, F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_ORM_LWORK (dormlq, DORMLQ);\n  return static_cast<F77_INT> (work[0]);\n}\n\ntemplate<>\nF77_INT\ngejsv_lwork<Matrix>::ormqr_lwork (char& side, char& trans,\n                                  F77_INT m, F77_INT n, F77_INT k,\n                                  P *a, F77_INT lda,\n                                  P *tau, P *c, F77_INT ldc,\n                                  P *work, F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_ORM_LWORK (dormqr, DORMQR);\n  return static_cast<F77_INT> (work[0]);\n}\n\n// For FloatMatrix\ntemplate<>\nF77_INT\ngejsv_lwork<FloatMatrix>::geqp3_lwork (F77_INT m, F77_INT n,\n                                       P *a, F77_INT lda,\n                                       F77_INT *jpvt, P *tau, P *work,\n                                       F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_QP3_LWORK (sgeqp3, SGEQP3);\n  return static_cast<F77_INT> (work[0]);\n}\n\ntemplate<>\nF77_INT\ngejsv_lwork<FloatMatrix>::geqrf_lwork (F77_INT m, F77_INT n,\n                                       P *a, F77_INT lda,\n                                       P *tau, P *work,\n                                       F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_QR_LWORK (sgeqrf, SGEQRF);\n  return static_cast<F77_INT> (work[0]);\n}\n\ntemplate<>\nF77_INT\ngejsv_lwork<FloatMatrix>::gelqf_lwork (F77_INT m, F77_INT n,\n                                       P *a, F77_INT lda,\n                                       P *tau, P *work,\n                                       F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_QR_LWORK (sgelqf, SGELQF);\n  return static_cast<F77_INT> (work[0]);\n}\n\ntemplate<>\nF77_INT\ngejsv_lwork<FloatMatrix>::ormlq_lwork (char& side, char& trans,\n                                       F77_INT m, F77_INT n, F77_INT k,\n                                       P *a, F77_INT lda,\n                                       P *tau, P *c, F77_INT ldc,\n                                       P *work, F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_ORM_LWORK (sormlq, SORMLQ);\n  return static_cast<F77_INT> (work[0]);\n}\n\ntemplate<>\nF77_INT\ngejsv_lwork<FloatMatrix>::ormqr_lwork (char& side, char& trans,\n                                       F77_INT m, F77_INT n, F77_INT k,\n                                       P *a, F77_INT lda,\n                                       P *tau, P *c, F77_INT ldc,\n                                       P *work, F77_INT lwork, F77_INT& info)\n{\n  GEJSV_REAL_ORM_LWORK (sormqr, SORMQR);\n  return static_cast<F77_INT> (work[0]);\n}\n\n#undef GEJSV_REAL_QP3_LWORK\n#undef GEJSV_REAL_QR_LWORK\n#undef GEJSV_REAL_ORM_LWORK\n\ntemplate<typename T>\nF77_INT\ngejsv_lwork<T>::optimal (char& joba, char& jobu, char& jobv,\n                         F77_INT m, F77_INT n)\n{\n  F77_INT lwork = -1;\n  std::vector<P> work (2);  // dummy work space\n\n  // variables that mimic running environment of gejsv\n  F77_INT lda  = std::max<F77_INT> (m, 1);\n  F77_INT ierr = 0;\n  char side  = 'L';\n  char trans = 'N';\n  std::vector<P> mat_a (1);\n  P *a = mat_a.data ();    // dummy input matrix\n  std::vector<F77_INT> vec_jpvt = {0};\n  P *tau = work.data ();\n  P *u   = work.data ();\n  P *v   = work.data ();\n\n  bool need_lsvec = jobu == 'U' || jobu == 'F';\n  bool need_rsvec = jobv == 'V' || jobv == 'J';\n\n  F77_INT lw_pocon = 3 * n;  // for [s,d]pocon\n  F77_INT lw_geqp3 = geqp3_lwork (m, n, a, lda, vec_jpvt.data (),\n                                  tau, work.data (), -1, ierr);\n  F77_INT lw_geqrf = geqrf_lwork (m, n, a, lda,\n                                  tau, work.data (), -1, ierr);\n\n  if (! (need_lsvec || need_rsvec) )\n    {\n      // only SIGMA is needed\n      if (! (joba == 'E' || joba == 'G') )\n        lwork = std::max<F77_INT> ({2*m + n, n + lw_geqp3, n + lw_geqrf, 7});\n      else\n        lwork = std::max<F77_INT> ({2*m + n, n + lw_geqp3, n + lw_geqrf,\n                                    n + n*n + lw_pocon, 7});\n    }\n  else if (need_rsvec && ! need_lsvec)\n    {\n      // SIGMA and the right singular vectors are needed\n      F77_INT lw_gelqf = gelqf_lwork (n, n, a, lda,\n                                      tau, work.data (), -1, ierr);\n      trans = 'T';\n      F77_INT lw_ormlq = ormlq_lwork (side, trans, n, n, n, a, lda,\n                                      tau, v, n, work.data (), -1, ierr);\n      lwork = std::max<F77_INT> ({2*m + n, n + lw_geqp3, n + lw_pocon,\n                                  n + lw_gelqf, 2*n + lw_geqrf, n + lw_ormlq});\n    }\n  else if (need_lsvec && ! need_rsvec)\n    {\n      // SIGMA and the left singular vectors are needed\n      F77_INT n1 = (jobu == 'U') ? n : m;  // size of U is m x n1\n      F77_INT lw_ormqr = ormqr_lwork (side, trans, m, n1, n, a, lda,\n                                      tau, u, m, work.data (), -1, ierr);\n      lwork = std::max<F77_INT> ({2*m + n, n + lw_geqp3, n + lw_pocon,\n                                  2*n + lw_geqrf, n + lw_ormqr});\n    }\n  else  // full SVD is needed\n    {\n      if (jobv == 'V')\n        lwork = std::max (2*m + n, 6*n + 2*n*n);\n      else if (jobv == 'J')\n        lwork = std::max<F77_INT> ({2*m + n, 4*n + n*n, 2*n + n*n + 6});\n\n      F77_INT n1 = (jobu == 'U') ? n : m;  // size of U is m x n1\n      F77_INT lw_ormqr = ormqr_lwork (side, trans, m, n1, n, a, lda,\n                                      tau, u, m, work.data (), -1, ierr);\n      lwork = std::max (lwork, n + lw_ormqr);\n    }\n\n  return lwork;\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nT\nsvd<T>::left_singular_matrix () const\n{\n  if (m_type == svd::Type::sigma_only)\n    (*current_liboctave_error_handler)\n      (\"svd: U not computed because type == svd::sigma_only\");\n\n  return m_left_sm;\n}\n\ntemplate <typename T>\nT\nsvd<T>::right_singular_matrix () const\n{\n  if (m_type == svd::Type::sigma_only)\n    (*current_liboctave_error_handler)\n      (\"svd: V not computed because type == svd::sigma_only\");\n\n  return m_right_sm;\n}\n\n// GESVD specializations\n\n#define GESVD_REAL_STEP(f, F)                                   \\\n  F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1),              \\\n                   F77_CONST_CHAR_ARG2 (&jobv, 1),              \\\n                   m, n, tmp_data, m1, s_vec, u, m1, vt,        \\\n                   nrow_vt1, work.data (), lwork, info          \\\n                   F77_CHAR_ARG_LEN (1)                         \\\n                   F77_CHAR_ARG_LEN (1)))\n\n#define GESVD_COMPLEX_STEP(f, F, CMPLX_ARG)             \\\n  F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1),      \\\n                   F77_CONST_CHAR_ARG2 (&jobv, 1),      \\\n                   m, n, CMPLX_ARG (tmp_data),          \\\n                   m1, s_vec, CMPLX_ARG (u), m1,        \\\n                   CMPLX_ARG (vt), nrow_vt1,            \\\n                   CMPLX_ARG (work.data ()),            \\\n                   lwork, rwork.data (), info           \\\n                   F77_CHAR_ARG_LEN (1)                 \\\n                   F77_CHAR_ARG_LEN (1)))\n\n// DGESVD\ntemplate<>\nOCTAVE_API void\nsvd<Matrix>::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n,\n                    double *tmp_data, F77_INT m1, double *s_vec,\n                    double *u, double *vt, F77_INT nrow_vt1,\n                    std::vector<double>& work, F77_INT& lwork,\n                    F77_INT& info)\n{\n  GESVD_REAL_STEP (dgesvd, DGESVD);\n\n  lwork = static_cast<F77_INT> (work[0]);\n  work.resize (lwork);\n\n  GESVD_REAL_STEP (dgesvd, DGESVD);\n}\n\n// SGESVD\ntemplate<>\nOCTAVE_API void\nsvd<FloatMatrix>::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n,\n                         float *tmp_data, F77_INT m1, float *s_vec,\n                         float *u, float *vt, F77_INT nrow_vt1,\n                         std::vector<float>& work, F77_INT& lwork,\n                         F77_INT& info)\n{\n  GESVD_REAL_STEP (sgesvd, SGESVD);\n\n  lwork = static_cast<F77_INT> (work[0]);\n  work.resize (lwork);\n\n  GESVD_REAL_STEP (sgesvd, SGESVD);\n}\n\n// ZGESVD\ntemplate<>\nOCTAVE_API void\nsvd<ComplexMatrix>::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n,\n                           Complex *tmp_data, F77_INT m1, double *s_vec,\n                           Complex *u, Complex *vt, F77_INT nrow_vt1,\n                           std::vector<Complex>& work, F77_INT& lwork,\n                           F77_INT& info)\n{\n  std::vector<double> rwork (5 * std::max (m, n));\n\n  GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG);\n\n  lwork = static_cast<F77_INT> (work[0].real ());\n  work.resize (lwork);\n\n  GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG);\n}\n\n// CGESVD\ntemplate<>\nOCTAVE_API void\nsvd<FloatComplexMatrix>::gesvd (char& jobu, char& jobv, F77_INT m,\n                                F77_INT n, FloatComplex *tmp_data,\n                                F77_INT m1, float *s_vec, FloatComplex *u,\n                                FloatComplex *vt, F77_INT nrow_vt1,\n                                std::vector<FloatComplex>& work,\n                                F77_INT& lwork, F77_INT& info)\n{\n  std::vector<float> rwork (5 * std::max (m, n));\n\n  GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG);\n\n  lwork = static_cast<F77_INT> (work[0].real ());\n  work.resize (lwork);\n\n  GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG);\n}\n\n#undef GESVD_REAL_STEP\n#undef GESVD_COMPLEX_STEP\n\n// GESDD specializations\n\n#define GESDD_REAL_STEP(f, F)                                           \\\n    F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1),                    \\\n                     m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1,    \\\n                     work.data (), lwork, iwork, info                   \\\n                     F77_CHAR_ARG_LEN (1)))\n\n#define GESDD_COMPLEX_STEP(f, F, CMPLX_ARG)                     \\\n    F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), m, n,      \\\n                     CMPLX_ARG (tmp_data), m1,                  \\\n                     s_vec, CMPLX_ARG (u), m1,                  \\\n                     CMPLX_ARG (vt), nrow_vt1,                  \\\n                     CMPLX_ARG (work.data ()), lwork,           \\\n                     rwork.data (), iwork, info                 \\\n                     F77_CHAR_ARG_LEN (1)))\n\n// DGESDD\ntemplate<>\nOCTAVE_API void\nsvd<Matrix>::gesdd (char& jobz, F77_INT m, F77_INT n, double *tmp_data,\n                    F77_INT m1, double *s_vec, double *u, double *vt,\n                    F77_INT nrow_vt1, std::vector<double>& work,\n                    F77_INT& lwork, F77_INT *iwork, F77_INT& info)\n{\n  GESDD_REAL_STEP (dgesdd, DGESDD);\n\n  lwork = static_cast<F77_INT> (work[0]);\n  work.resize (lwork);\n\n  GESDD_REAL_STEP (dgesdd, DGESDD);\n}\n\n// SGESDD\ntemplate<>\nOCTAVE_API void\nsvd<FloatMatrix>::gesdd (char& jobz, F77_INT m, F77_INT n, float *tmp_data,\n                         F77_INT m1, float *s_vec, float *u, float *vt,\n                         F77_INT nrow_vt1, std::vector<float>& work,\n                         F77_INT& lwork, F77_INT *iwork, F77_INT& info)\n{\n  GESDD_REAL_STEP (sgesdd, SGESDD);\n\n  lwork = static_cast<F77_INT> (work[0]);\n  work.resize (lwork);\n\n  GESDD_REAL_STEP (sgesdd, SGESDD);\n}\n\n// ZGESDD\ntemplate<>\nOCTAVE_API void\nsvd<ComplexMatrix>::gesdd (char& jobz, F77_INT m, F77_INT n,\n                           Complex *tmp_data, F77_INT m1, double *s_vec,\n                           Complex *u, Complex *vt, F77_INT nrow_vt1,\n                           std::vector<Complex>& work, F77_INT& lwork,\n                           F77_INT *iwork, F77_INT& info)\n{\n\n  F77_INT min_mn = std::min (m, n);\n  F77_INT max_mn = std::max (m, n);\n\n  F77_INT lrwork;\n  if (jobz == 'N')\n    lrwork = 7*min_mn;\n  else\n    lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1);\n\n  std::vector<double> rwork (lrwork);\n\n  GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG);\n\n  lwork = static_cast<F77_INT> (work[0].real ());\n  work.resize (lwork);\n\n  GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG);\n}\n\n// CGESDD\ntemplate<>\nOCTAVE_API void\nsvd<FloatComplexMatrix>::gesdd (char& jobz, F77_INT m, F77_INT n,\n                                FloatComplex *tmp_data, F77_INT m1,\n                                float *s_vec, FloatComplex *u,\n                                FloatComplex *vt, F77_INT nrow_vt1,\n                                std::vector<FloatComplex>& work,\n                                F77_INT& lwork, F77_INT *iwork,\n                                F77_INT& info)\n{\n  F77_INT min_mn = std::min (m, n);\n  F77_INT max_mn = std::max (m, n);\n\n  F77_INT lrwork;\n  if (jobz == 'N')\n    lrwork = 7*min_mn;\n  else\n    lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1);\n  std::vector<float> rwork (lrwork);\n\n  GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG);\n\n  lwork = static_cast<F77_INT> (work[0].real ());\n  work.resize (lwork);\n\n  GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG);\n}\n\n#undef GESDD_REAL_STEP\n#undef GESDD_COMPLEX_STEP\n\n// GEJSV specializations\n\n#define GEJSV_REAL_STEP(f, F)                                         \\\n    F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1),                  \\\n                     F77_CONST_CHAR_ARG2 (&jobu, 1),                  \\\n                     F77_CONST_CHAR_ARG2 (&jobv, 1),                  \\\n                     F77_CONST_CHAR_ARG2 (&jobr, 1),                  \\\n                     F77_CONST_CHAR_ARG2 (&jobt, 1),                  \\\n                     F77_CONST_CHAR_ARG2 (&jobp, 1),                  \\\n                     m, n, tmp_data, m1, s_vec, u, m1, v, nrow_v1,    \\\n                     work.data (), lwork, iwork.data (), info         \\\n                     F77_CHAR_ARG_LEN (1)                             \\\n                     F77_CHAR_ARG_LEN (1)                             \\\n                     F77_CHAR_ARG_LEN (1)                             \\\n                     F77_CHAR_ARG_LEN (1)                             \\\n                     F77_CHAR_ARG_LEN (1)                             \\\n                     F77_CHAR_ARG_LEN (1)))\n\n#define GEJSV_COMPLEX_STEP(f, F, CMPLX_ARG)                       \\\n    F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1),              \\\n                     F77_CONST_CHAR_ARG2 (&jobu, 1),              \\\n                     F77_CONST_CHAR_ARG2 (&jobv, 1),              \\\n                     F77_CONST_CHAR_ARG2 (&jobr, 1),              \\\n                     F77_CONST_CHAR_ARG2 (&jobt, 1),              \\\n                     F77_CONST_CHAR_ARG2 (&jobp, 1),              \\\n                     m, n, CMPLX_ARG (tmp_data), m1,              \\\n                     s_vec, CMPLX_ARG (u), m1,                    \\\n                     CMPLX_ARG (v), nrow_v1,                      \\\n                     CMPLX_ARG (work.data ()), lwork,             \\\n                     rwork.data (), lrwork, iwork.data (), info   \\\n                     F77_CHAR_ARG_LEN (1)                         \\\n                     F77_CHAR_ARG_LEN (1)                         \\\n                     F77_CHAR_ARG_LEN (1)                         \\\n                     F77_CHAR_ARG_LEN (1)                         \\\n                     F77_CHAR_ARG_LEN (1)                         \\\n                     F77_CHAR_ARG_LEN (1)))\n\n// DGEJSV\ntemplate<>\nvoid\nsvd<Matrix>::gejsv (char& joba, char& jobu, char& jobv,\n                    char& jobr, char& jobt, char& jobp,\n                    F77_INT m, F77_INT n,\n                    P *tmp_data, F77_INT m1, DM_P *s_vec, P *u,\n                    P *v, F77_INT nrow_v1, std::vector<P>& work,\n                    F77_INT& lwork, std::vector<F77_INT>& iwork,\n                    F77_INT& info)\n{\n  lwork = gejsv_lwork<Matrix>::optimal (joba, jobu, jobv, m, n);\n  work.resize (lwork);\n\n  GEJSV_REAL_STEP (dgejsv, DGEJSV);\n}\n\n// SGEJSV\ntemplate<>\nvoid\nsvd<FloatMatrix>::gejsv (char& joba, char& jobu, char& jobv,\n                         char& jobr, char& jobt, char& jobp,\n                         F77_INT m, F77_INT n,\n                         P *tmp_data, F77_INT m1, DM_P *s_vec, P *u,\n                         P *v, F77_INT nrow_v1, std::vector<P>& work,\n                         F77_INT& lwork, std::vector<F77_INT>& iwork,\n                         F77_INT& info)\n{\n  lwork = gejsv_lwork<FloatMatrix>::optimal (joba, jobu, jobv, m, n);\n  work.resize (lwork);\n\n  GEJSV_REAL_STEP (sgejsv, SGEJSV);\n}\n\n// ZGEJSV\ntemplate<>\nvoid\nsvd<ComplexMatrix>::gejsv (char& joba, char& jobu, char& jobv,\n                           char& jobr, char& jobt, char& jobp,\n                           F77_INT m, F77_INT n,\n                           P *tmp_data, F77_INT m1, DM_P *s_vec, P *u,\n                           P *v, F77_INT nrow_v1, std::vector<P>& work,\n                           F77_INT& lwork, std::vector<F77_INT>& iwork,\n                           F77_INT& info)\n{\n  F77_INT lrwork = -1;          // work space size query\n  std::vector<double> rwork (1);\n  work.resize (2);\n\n  GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG);\n\n  lwork = static_cast<F77_INT> (work[0].real ());\n  work.resize (lwork);\n\n  lrwork = static_cast<F77_INT> (rwork[0]);\n  rwork.resize (lrwork);\n\n  F77_INT liwork = static_cast<F77_INT> (iwork[0]);\n  iwork.resize (liwork);\n\n  GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG);\n}\n\n// CGEJSV\ntemplate<>\nvoid\nsvd<FloatComplexMatrix>::gejsv (char& joba, char& jobu, char& jobv,\n                                char& jobr, char& jobt, char& jobp,\n                                F77_INT m, F77_INT n, P *tmp_data,\n                                F77_INT m1, DM_P *s_vec, P *u, P *v,\n                                F77_INT nrow_v1, std::vector<P>& work,\n                                F77_INT& lwork,\n                                std::vector<F77_INT>& iwork, F77_INT& info)\n{\n  F77_INT lrwork = -1;          // work space size query\n  std::vector<float> rwork (1);\n  work.resize (2);\n\n  GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG);\n\n  lwork = static_cast<F77_INT> (work[0].real ());\n  work.resize (lwork);\n\n  lrwork = static_cast<F77_INT> (rwork[0]);\n  rwork.resize (lrwork);\n\n  F77_INT liwork = static_cast<F77_INT> (iwork[0]);\n  iwork.resize (liwork);\n\n  GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG);\n}\n\n#undef GEJSV_REAL_STEP\n#undef GEJSV_COMPLEX_STEP\n\ntemplate<typename T>\nsvd<T>::svd (const T& a, svd::Type type, svd::Driver driver)\n  : m_type (type), m_driver (driver), m_left_sm (), m_sigma (),\n    m_right_sm ()\n{\n  F77_INT info;\n\n  F77_INT m = to_f77_int (a.rows ());\n  F77_INT n = to_f77_int (a.cols ());\n\n  if (m == 0 || n == 0)\n    {\n      switch (m_type)\n        {\n        case svd::Type::std:\n          m_left_sm = T (m, m, 0);\n          for (F77_INT i = 0; i < m; i++)\n            m_left_sm.xelem (i, i) = 1;\n          m_sigma = DM_T (m, n);\n          m_right_sm = T (n, n, 0);\n          for (F77_INT i = 0; i < n; i++)\n            m_right_sm.xelem (i, i) = 1;\n          break;\n\n        case svd::Type::economy:\n          m_left_sm = T (m, 0, 0);\n          m_sigma = DM_T (0, 0);\n          m_right_sm = T (n, 0, 0);\n          break;\n\n        case svd::Type::sigma_only:\n        default:\n          m_sigma = DM_T (0, 1);\n          break;\n        }\n      return;\n    }\n\n  T atmp = a;\n  P *tmp_data = atmp.rwdata ();\n\n  F77_INT min_mn = (m < n ? m : n);\n\n  char jobu = 'A';\n  char jobv = 'A';\n\n  F77_INT ncol_u = m;\n  F77_INT nrow_vt = n;\n  F77_INT nrow_s = m;\n  F77_INT ncol_s = n;\n\n  switch (m_type)\n    {\n    case svd::Type::economy:\n      jobu = jobv = 'S';\n      ncol_u = nrow_vt = nrow_s = ncol_s = min_mn;\n      break;\n\n    case svd::Type::sigma_only:\n\n      // Note: for this case, both jobu and jobv should be 'N', but there\n      // seems to be a bug in dgesvd from Lapack V2.0.  To demonstrate the\n      // bug, set both jobu and jobv to 'N' and find the singular values of\n      // [eye(3), eye(3)].  The result is [-sqrt(2), -sqrt(2), -sqrt(2)].\n      //\n      // For Lapack 3.0, this problem seems to be fixed.\n\n      jobu = jobv = 'N';\n      ncol_u = nrow_vt = 1;\n      break;\n\n    default:\n      break;\n    }\n\n  if (! (jobu == 'N' || jobu == 'O'))\n    m_left_sm.resize (m, ncol_u);\n\n  P *u = m_left_sm.rwdata ();\n\n  m_sigma.resize (nrow_s, ncol_s);\n  DM_P *s_vec = m_sigma.rwdata ();\n\n  if (! (jobv == 'N' || jobv == 'O'))\n    {\n      if (m_driver == svd::Driver::GEJSV)\n        m_right_sm.resize (n, nrow_vt);\n      else\n        m_right_sm.resize (nrow_vt, n);\n    }\n\n  P *vt = m_right_sm.rwdata ();\n\n  // Query _GESVD for the correct dimension of WORK.\n  F77_INT lwork = -1;\n  // FIXME: A variable-sized scratchpad is required for Fortran SVD routines.\n  // Octave calls LAPACK routines with lwork of -1 initially which causes\n  // LAPACK to calculate the size of the required scratchpad and return that\n  // value in the first entry of the \"work\" array.  The temporary buffer was\n  // grown to the desired size using std::vector::reserve().  However, this\n  // leads to undefined behavior outside the C++ specification.  To work around\n  // this (7/4//2025) all of the calls were changed to std::vector::resize().\n  // This is correct, but unnecessarily initializes all values of the array.\n  // The code should be re-architected to avoid this, possibly by moving\n  // this scratchpad memory out of this function and in to the lower-level\n  // routines where the memory is used.\n  std::vector<P> work (1);\n\n  const F77_INT f77_int_one = static_cast<F77_INT> (1);\n  F77_INT m1 = std::max (m, f77_int_one);\n  F77_INT nrow_vt1 = std::max (nrow_vt, f77_int_one);\n\n  if (m_driver == svd::Driver::GESVD)\n    gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1,\n           work, lwork, info);\n  else if (m_driver == svd::Driver::GESDD)\n    {\n      liboctave_panic_unless (jobu == jobv);\n      char jobz = jobu;\n\n      std::vector<F77_INT> iwork (8 * std::min (m, n));\n\n      gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1,\n             work, lwork, iwork.data (), info);\n    }\n  else if (m_driver == svd::Driver::GEJSV)\n    {\n      bool transposed = false;\n      if (n > m)\n        {\n          // GEJSV only accepts m >= n, thus we need to transpose here\n          transposed = true;\n\n          std::swap (m, n);\n          m1 = std::max (m, f77_int_one);\n          nrow_vt1 = std::max (n, f77_int_one);  // we have m > n\n          if (m_type == svd::Type::sigma_only)\n            nrow_vt1 = 1;\n          std::swap (jobu, jobv);\n\n          atmp = atmp.hermitian ();\n          tmp_data = atmp.rwdata ();\n\n          // Swap pointers of U and V.\n          u  = m_right_sm.rwdata ();\n          vt = m_left_sm.rwdata ();\n        }\n\n      // translate jobu and jobv from gesvd to gejsv.\n      std::unordered_map<char, std::string> job_svd2jsv;\n      job_svd2jsv['A'] = \"FJ\";\n      job_svd2jsv['S'] = \"UV\";\n      job_svd2jsv['O'] = \"WW\";\n      job_svd2jsv['N'] = \"NN\";\n      jobu = job_svd2jsv[jobu][0];\n      jobv = job_svd2jsv[jobv][1];\n\n      char joba = 'F';  // 'F': most conservative\n      char jobr = 'R';  // 'R' is recommended.\n      char jobt = 'N';  // or 'T', but that requires U and V appear together\n      char jobp = 'N';  // use 'P' if denormal is poorly implemented.\n\n      std::vector<F77_INT> iwork (std::max<F77_INT> (m + 3*n, 1));\n\n      gejsv (joba, jobu, jobv, jobr, jobt, jobp, m, n, tmp_data, m1,\n             s_vec, u, vt, nrow_vt1, work, lwork, iwork, info);\n\n      if (iwork[2] == 1)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:convergence\", \"svd: (driver: GEJSV) \"\n           \"Denormal occurred, possible loss of accuracy.\");\n\n      if (info < 0)\n        (*current_liboctave_error_handler)\n          (\"svd: (driver: GEJSV) Illegal argument at #%d\",\n           static_cast<int> (-info));\n      else if (info > 0)\n        (*current_liboctave_warning_with_id_handler)\n          (\"Octave:convergence\", \"svd: (driver: GEJSV) \"\n           \"Fail to converge within max sweeps, \"\n           \"possible inaccurate result.\");\n\n      if (transposed)  // put things that need to transpose back here\n        std::swap (m, n);\n    }\n  else\n    (*current_liboctave_error_handler) (\"svd: unknown driver\");\n\n  // LAPACK can return -0 which is a small problem (bug #55710).\n  for (octave_idx_type i = 0; i < m_sigma.diag_length (); i++)\n    {\n      if (! m_sigma.dgxelem (i))\n        m_sigma.dgxelem (i) = DM_P (0);\n    }\n\n  // GESVD and GESDD return VT instead of V, GEJSV return V.\n  if (! (jobv == 'N' || jobv == 'O') && (m_driver != svd::Driver::GEJSV))\n    m_right_sm = m_right_sm.hermitian ();\n}\n\n// Instantiations we need.\n\ntemplate class svd<Matrix>;\n\ntemplate class svd<FloatMatrix>;\n\ntemplate class svd<ComplexMatrix>;\n\ntemplate class svd<FloatComplexMatrix>;\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/numeric/svd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_svd_h)\n#define octave_svd_h 1\n\n#include \"octave-config.h\"\n\n#include <vector>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ntemplate <typename T>\nclass OCTAVE_API svd\n{\npublic:\n\n  typedef typename T::real_diag_matrix_type DM_T;\n\n  enum class Type\n  {\n    std,\n    economy,\n    sigma_only\n  };\n\n  enum class Driver\n  {\n    GESVD,\n    GESDD,\n    GEJSV\n  };\n\n  svd ()\n    : m_type (), m_driver (), m_left_sm (), m_sigma (), m_right_sm ()\n  { }\n\n  svd (const T& a, svd::Type type = svd::Type::std,\n       svd::Driver driver = svd::Driver::GESVD);\n\n  svd (const svd& a)\n    : m_type (a.m_type), m_driver (a.m_driver), m_left_sm (a.m_left_sm),\n      m_sigma (a.m_sigma), m_right_sm (a.m_right_sm)\n  { }\n\n  svd& operator = (const svd& a)\n  {\n    if (this != &a)\n      {\n        m_type = a.m_type;\n        m_left_sm = a.m_left_sm;\n        m_sigma = a.m_sigma;\n        m_right_sm = a.m_right_sm;\n        m_driver = a.m_driver;\n      }\n\n    return *this;\n  }\n\n  ~svd () = default;\n\n  T left_singular_matrix () const;\n\n  DM_T singular_values () const { return m_sigma; }\n\n  T right_singular_matrix () const;\n\nprivate:\n\n  typedef typename T::element_type P;\n  typedef typename DM_T::element_type DM_P;\n\n  svd::Type m_type;\n  svd::Driver m_driver;\n\n  T m_left_sm;\n  DM_T m_sigma;\n  T m_right_sm;\n\n  void gesvd (char& jobu, char& jobv, octave_f77_int_type m,\n              octave_f77_int_type n, P *tmp_data, octave_f77_int_type m1,\n              DM_P *s_vec, P *u, P *vt, octave_f77_int_type nrow_vt1,\n              std::vector<P>& work, octave_f77_int_type& lwork,\n              octave_f77_int_type& info);\n\n  void gesdd (char& jobz, octave_f77_int_type m, octave_f77_int_type n,\n              P *tmp_data, octave_f77_int_type m1, DM_P *s_vec, P *u,\n              P *vt, octave_f77_int_type nrow_vt1, std::vector<P>& work,\n              octave_f77_int_type& lwork, octave_f77_int_type *iwork,\n              octave_f77_int_type& info);\n\n  void gejsv (char& joba, char& jobu, char& jobv, char& jobr, char& jobt,\n              char& jobp, octave_f77_int_type m, octave_f77_int_type n,\n              P *tmp_data, octave_f77_int_type m1, DM_P *s_vec, P *u,\n              P *v, octave_f77_int_type nrow_v1, std::vector<P>& work,\n              octave_f77_int_type& lwork,\n              std::vector<octave_f77_int_type>& iwork,\n              octave_f77_int_type& info);\n};\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/octave.in.pc",
    "content": "Name: @PACKAGE_NAME@\nDescription: C++ interface to GNU Octave underlying library.\nURL: https://www.octave.org\nVersion: @PACKAGE_VERSION@\nRequires:\nRequires.private:\nLibs: -L@octlibdir@ @LIBOCTAVE@\nLibs.private: @LIBOCTAVE_LINK_DEPS@\nCflags: -I@octincludedir@/..\n"
  },
  {
    "path": "liboctave/operators/Sparse-diag-op-defs.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Sparse_diag_op_defs_h)\n#define octave_Sparse_diag_op_defs_h 1\n\n#include \"octave-config.h\"\n\n#include \"lo-array-errwarn.h\"\n\n// Matrix multiplication\n\ntemplate <typename RT, typename DM, typename SM>\nRT do_mul_dm_sm (const DM& d, const SM& a)\n{\n  const octave_idx_type nr = d.rows ();\n  const octave_idx_type nc = d.cols ();\n\n  const octave_idx_type a_nr = a.rows ();\n  const octave_idx_type a_nc = a.cols ();\n\n  if (nc != a_nr)\n    octave::err_nonconformant (\"operator *\", nr, nc, a_nr, a_nc);\n\n  RT r (nr, a_nc, a.nnz ());\n\n  octave_idx_type l = 0;\n\n  for (octave_idx_type j = 0; j < a_nc; j++)\n    {\n      r.xcidx (j) = l;\n      const octave_idx_type colend = a.cidx (j+1);\n      for (octave_idx_type k = a.cidx (j); k < colend; k++)\n        {\n          const octave_idx_type i = a.ridx (k);\n          if (i >= nr) break;\n          r.xdata (l) = d.dgelem (i) * a.data (k);\n          r.xridx (l) = i;\n          l++;\n        }\n    }\n\n  r.xcidx (a_nc) = l;\n\n  r.maybe_compress (true);\n  return r;\n}\n\ntemplate <typename RT, typename SM, typename DM>\nRT do_mul_sm_dm (const SM& a, const DM& d)\n{\n  const octave_idx_type nr = d.rows ();\n  const octave_idx_type nc = d.cols ();\n\n  const octave_idx_type a_nr = a.rows ();\n  const octave_idx_type a_nc = a.cols ();\n\n  if (nr != a_nc)\n    octave::err_nonconformant (\"operator *\", a_nr, a_nc, nr, nc);\n\n  const octave_idx_type mnc = (nc < a_nc ? nc: a_nc);\n  RT r (a_nr, nc, a.cidx (mnc));\n\n  for (octave_idx_type j = 0; j < mnc; ++j)\n    {\n      const typename DM::element_type s = d.dgelem (j);\n      const octave_idx_type colend = a.cidx (j+1);\n      r.xcidx (j) = a.cidx (j);\n      for (octave_idx_type k = a.cidx (j); k < colend; ++k)\n        {\n          r.xdata (k) = s * a.data (k);\n          r.xridx (k) = a.ridx (k);\n        }\n    }\n  for (octave_idx_type j = mnc; j <= nc; ++j)\n    r.xcidx (j) = a.cidx (mnc);\n\n  r.maybe_compress (true);\n  return r;\n}\n\n// FIXME: functors such as this should be gathered somewhere\ntemplate <typename T>\nstruct identity_val\n{\npublic:\n  typedef T argument_type;\n  typedef T result_type;\n  T operator () (const T x) { return x; }\n};\n\n// Matrix addition\n\ntemplate <typename RT, typename SM, typename DM, typename OpA, typename OpD>\nRT inner_do_add_sm_dm (const SM& a, const DM& d, OpA opa, OpD opd)\n{\n  using std::min;\n  const octave_idx_type nr = d.rows ();\n  const octave_idx_type nc = d.cols ();\n  const octave_idx_type n = min (nr, nc);\n\n  const octave_idx_type a_nr = a.rows ();\n  const octave_idx_type a_nc = a.cols ();\n\n  const octave_idx_type nz = a.nnz ();\n  RT r (a_nr, a_nc, nz + n);\n  octave_idx_type k = 0;\n\n  for (octave_idx_type j = 0; j < nc; ++j)\n    {\n      octave_quit ();\n      const octave_idx_type colend = a.cidx (j+1);\n      r.xcidx (j) = k;\n      octave_idx_type k_src = a.cidx (j), k_split;\n\n      for (k_split = k_src; k_split < colend; k_split++)\n        if (a.ridx (k_split) >= j)\n          break;\n\n      for (; k_src < k_split; k_src++, k++)\n        {\n          r.xridx (k) = a.ridx (k_src);\n          r.xdata (k) = opa (a.data (k_src));\n        }\n\n      if (k_src < colend && a.ridx (k_src) == j)\n        {\n          r.xridx (k) = j;\n          r.xdata (k) = opa (a.data (k_src)) + opd (d.dgelem (j));\n          k++; k_src++;\n        }\n      else\n        {\n          r.xridx (k) = j;\n          r.xdata (k) = opd (d.dgelem (j));\n          k++;\n        }\n\n      for (; k_src < colend; k_src++, k++)\n        {\n          r.xridx (k) = a.ridx (k_src);\n          r.xdata (k) = opa (a.data (k_src));\n        }\n\n    }\n  r.xcidx (nc) = k;\n\n  r.maybe_compress (true);\n  return r;\n}\n\ntemplate <typename RT, typename SM, typename DM, typename OpA, typename OpD>\nRT inner_do_add_row_sm_dm (const SM& a, const DM& d, OpA opa, OpD opd)\n{\n  const octave_idx_type nr = d.rows ();\n  const octave_idx_type nc = d.cols ();\n\n  const octave_idx_type nz = nr * nc;\n  RT r (nr, nc, nz);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      octave_quit ();\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          r.elem (i, j) = opa (a.elem (0, j));\n          if (i == j)\n            r.elem (i, j) = opa (a.elem (0, j)) + opd (d.dgelem (j));\n        }\n    }\n\n  r.maybe_compress (true);\n  return r;\n}\n\ntemplate <typename RT, typename SM, typename DM, typename OpA, typename OpD>\nRT inner_do_add_col_sm_dm (const SM& a, const DM& d, OpA opa, OpD opd)\n{\n  const octave_idx_type nr = d.rows ();\n  const octave_idx_type nc = d.cols ();\n\n  const octave_idx_type nz = nr * nc;\n  RT r (nr, nc, nz);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      octave_quit ();\n      for (octave_idx_type i = 0; i < nr; i++)\n        {\n          r.elem (i, j) = opa (a.elem (i, 0));\n          if (i == j)\n            r.elem (i, j) = opa (a.elem (i, 0)) + opd (d.dgelem (j));\n        }\n    }\n\n  r.maybe_compress (true);\n  return r;\n}\n\ntemplate <typename RT, typename DM, typename SM>\nRT do_add_dm_sm (const DM& d, const SM& a)\n{\n  if (a.rows () == d.rows () && a.cols () == d.cols ())\n    return inner_do_add_sm_dm<RT> (a, d,\n                                   identity_val<typename SM::element_type> (),\n                                   identity_val<typename DM::element_type> ());\n  else if (a.rows () == d.rows () && a.cols () == 1)\n    return inner_do_add_col_sm_dm<RT> (a, d,\n                                   identity_val<typename SM::element_type> (),\n                                   identity_val<typename DM::element_type> ());\n  else if (a.cols () == d.cols () && a.rows () == 1)\n    return inner_do_add_row_sm_dm<RT> (a, d,\n                                   identity_val<typename SM::element_type> (),\n                                   identity_val<typename DM::element_type> ());\n  else\n    octave::err_nonconformant (\"operator +\",\n                               d.rows (), d.cols (), a.rows (), a.cols ());\n}\n\ntemplate <typename RT, typename DM, typename SM>\nRT do_sub_dm_sm (const DM& d, const SM& a)\n{\n  if (a.rows () == d.rows () && a.cols () == d.cols ())\n    return inner_do_add_sm_dm<RT> (a, d,\n                                   std::negate<typename SM::element_type> (),\n                                   identity_val<typename DM::element_type> ());\n  else if (a.rows () == d.rows () && a.cols () == 1)\n    return inner_do_add_col_sm_dm<RT> (a, d,\n                                   std::negate<typename SM::element_type> (),\n                                   identity_val<typename DM::element_type> ());\n  else if (a.cols () == d.cols () && a.rows () == 1)\n    return inner_do_add_row_sm_dm<RT> (a, d,\n                                   std::negate<typename SM::element_type> (),\n                                   identity_val<typename DM::element_type> ());\n  else\n    octave::err_nonconformant (\"operator -\",\n                               d.rows (), d.cols (), a.rows (), a.cols ());\n}\n\ntemplate <typename RT, typename SM, typename DM>\nRT do_add_sm_dm (const SM& a, const DM& d)\n{\n  if (a.rows () == d.rows () && a.cols () == d.cols ())\n    return inner_do_add_sm_dm<RT> (a, d,\n                                   identity_val<typename SM::element_type> (),\n                                   identity_val<typename DM::element_type> ());\n  else if (a.rows () == d.rows () && a.cols () == 1)\n    return inner_do_add_col_sm_dm<RT> (a, d,\n                                   identity_val<typename SM::element_type> (),\n                                   identity_val<typename DM::element_type> ());\n  else if (a.cols () == d.cols () && a.rows () == 1)\n    return inner_do_add_row_sm_dm<RT> (a, d,\n                                   identity_val<typename SM::element_type> (),\n                                   identity_val<typename DM::element_type> ());\n  else\n    octave::err_nonconformant (\"operator +\",\n                               d.rows (), d.cols (), a.rows (), a.cols ());\n}\n\ntemplate <typename RT, typename SM, typename DM>\nRT do_sub_sm_dm (const SM& a, const DM& d)\n{\n  if (a.rows () == d.rows () && a.cols () == d.cols ())\n    return inner_do_add_sm_dm<RT> (a, d,\n                                   identity_val<typename SM::element_type> (),\n                                   std::negate<typename DM::element_type> ());\n  else if (a.rows () == d.rows () && a.cols () == 1)\n    return inner_do_add_col_sm_dm<RT> (a, d,\n                                   identity_val<typename SM::element_type> (),\n                                   std::negate<typename DM::element_type> ());\n  else if (a.cols () == d.cols () && a.rows () == 1)\n    return inner_do_add_row_sm_dm<RT> (a, d,\n                                   identity_val<typename SM::element_type> (),\n                                   std::negate<typename DM::element_type> ());\n  else\n    octave::err_nonconformant (\"operator -\",\n                               d.rows (), d.cols (), a.rows (), a.cols ());\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/Sparse-op-decls.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Sparse_op_decls_h)\n#define octave_Sparse_op_decls_h 1\n\n#include \"octave-config.h\"\n\n#include \"mx-fwd.h\"\n\n#define SPARSE_BIN_OP_DECL(R, OP, X, Y, API)    \\\n  extern API R OP (const X&, const Y&)\n\n#define SPARSE_CMP_OP_DECL(OP, X, Y, API)               \\\n  extern API SparseBoolMatrix OP (const X&, const Y&)\n\n#define SPARSE_BOOL_OP_DECL(OP, X, Y, API)              \\\n  extern API SparseBoolMatrix OP (const X&, const Y&)\n\n#define SPARSE_BOOL_OP1_DECL(OP, X, Y, API)             \\\n  extern API boolMatrix OP (const X&, const Y&)\n\n// sparse matrix by scalar operations.\n\n#define SPARSE_SMS_BIN_OP_DECLS(R1, R2, M, S, API)      \\\n  SPARSE_BIN_OP_DECL (R1, operator +, M, S, API);       \\\n  SPARSE_BIN_OP_DECL (R1, operator -, M, S, API);       \\\n  SPARSE_BIN_OP_DECL (R2, operator *, M, S, API);       \\\n  SPARSE_BIN_OP_DECL (R2, operator /, M, S, API);\n\n#define SPARSE_SMS_CMP_OP_DECLS(M, S, API)      \\\n  SPARSE_CMP_OP_DECL (mx_el_lt, M, S, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_le, M, S, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_ge, M, S, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_gt, M, S, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, M, S, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, M, S, API);\n\n#define SPARSE_SMS_EQNE_OP_DECLS(M, S, API)     \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, M, S, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, M, S, API);\n\n#define SPARSE_SMS_BOOL_OP_DECLS(M, S, API)     \\\n  SPARSE_BOOL_OP_DECL (mx_el_and, M, S, API);   \\\n  SPARSE_BOOL_OP1_DECL (mx_el_or, M, S, API);\n\n#define SPARSE_SMS_OP_DECLS(R1, R2, M, S, API)  \\\n  SPARSE_SMS_BIN_OP_DECLS (R1, R2, M, S, API)   \\\n  SPARSE_SMS_CMP_OP_DECLS (M, S, API)           \\\n  SPARSE_SMS_BOOL_OP_DECLS (M, S, API)\n\n// scalar by sparse matrix operations.\n\n#define SPARSE_SSM_BIN_OP_DECLS(R1, R2, S, M, API)      \\\n  SPARSE_BIN_OP_DECL (R1, operator +, S, M, API);       \\\n  SPARSE_BIN_OP_DECL (R1, operator -, S, M, API);       \\\n  SPARSE_BIN_OP_DECL (R2, operator *, S, M, API);       \\\n  SPARSE_BIN_OP_DECL (R1, operator /, S, M, API);\n\n#define SPARSE_SSM_CMP_OP_DECLS(S, M, API)      \\\n  SPARSE_CMP_OP_DECL (mx_el_lt, S, M, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_le, S, M, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_ge, S, M, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_gt, S, M, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, S, M, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, S, M, API);\n\n#define SPARSE_SSM_EQNE_OP_DECLS(S, M, API)     \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, S, M, API);     \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, S, M, API);\n\n#define SPARSE_SSM_BOOL_OP_DECLS(S, M, API)     \\\n  SPARSE_BOOL_OP_DECL (mx_el_and, S, M, API);   \\\n  SPARSE_BOOL_OP1_DECL (mx_el_or, S, M, API);\n\n#define SPARSE_SSM_OP_DECLS(R1, R2, S, M, API)  \\\n  SPARSE_SSM_BIN_OP_DECLS (R1, R2, S, M, API)   \\\n  SPARSE_SSM_CMP_OP_DECLS (S, M, API)           \\\n  SPARSE_SSM_BOOL_OP_DECLS (S, M, API)          \\\n\n// sparse matrix by sparse matrix operations.\n\n#define SPARSE_SMSM_BIN_OP_DECLS(R1, R2, M1, M2, API)   \\\n  SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API);     \\\n  SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API);     \\\n  SPARSE_BIN_OP_DECL (R2, product,    M1, M2, API);     \\\n  SPARSE_BIN_OP_DECL (R2, quotient,   M1, M2, API);\n\n#define SPARSE_SMSM_CMP_OP_DECLS(M1, M2, API)   \\\n  SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);\n\n#define SPARSE_SMSM_EQNE_OP_DECLS(M1, M2, API)  \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);\n\n#define SPARSE_SMSM_BOOL_OP_DECLS(M1, M2, API)  \\\n  SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \\\n  SPARSE_BOOL_OP_DECL (mx_el_or,  M1, M2, API);\n\n#define SPARSE_SMSM_OP_DECLS(R1, R2, M1, M2, API)       \\\n  SPARSE_SMSM_BIN_OP_DECLS (R1, R2, M1, M2, API)        \\\n  SPARSE_SMSM_CMP_OP_DECLS (M1, M2, API)                \\\n  SPARSE_SMSM_BOOL_OP_DECLS (M1, M2, API)\n\n// matrix by sparse matrix operations.\n\n#define SPARSE_MSM_BIN_OP_DECLS(R1, R2, M1, M2, API)    \\\n  SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API);     \\\n  SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API);     \\\n  SPARSE_BIN_OP_DECL (R2, product,    M1, M2, API);     \\\n  SPARSE_BIN_OP_DECL (R1, quotient,   M1, M2, API);\n\n#define SPARSE_MSM_CMP_OP_DECLS(M1, M2, API)    \\\n  SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);\n\n#define SPARSE_MSM_EQNE_OP_DECLS(M1, M2, API)   \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);\n\n#define SPARSE_MSM_BOOL_OP_DECLS(M1, M2, API)   \\\n  SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \\\n  SPARSE_BOOL_OP1_DECL (mx_el_or, M1, M2, API);\n\n#define SPARSE_MSM_OP_DECLS(R1, R2, M1, M2, API)        \\\n  SPARSE_MSM_BIN_OP_DECLS (R1, R2, M1, M2, API)         \\\n  SPARSE_MSM_CMP_OP_DECLS (M1, M2, API)                 \\\n  SPARSE_MSM_BOOL_OP_DECLS (M1, M2, API)\n\n// sparse matrix by matrix operations.\n\n#define SPARSE_SMM_BIN_OP_DECLS(R1, R2, M1, M2, API)    \\\n  SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API);     \\\n  SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API);     \\\n  SPARSE_BIN_OP_DECL (R2, product,    M1, M2, API);     \\\n  SPARSE_BIN_OP_DECL (R2, quotient,   M1, M2, API);\n\n#define SPARSE_SMM_CMP_OP_DECLS(M1, M2, API)    \\\n  SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);\n\n#define SPARSE_SMM_EQNE_OP_DECLS(M1, M2, API)   \\\n  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API);   \\\n  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);\n\n#define SPARSE_SMM_BOOL_OP_DECLS(M1, M2, API)   \\\n  SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \\\n  SPARSE_BOOL_OP1_DECL (mx_el_or, M1, M2, API);\n\n#define SPARSE_SMM_OP_DECLS(R1, R2, M1, M2, API)        \\\n  SPARSE_SMM_BIN_OP_DECLS (R1, R2, M1, M2, API)         \\\n  SPARSE_SMM_CMP_OP_DECLS (M1, M2, API)                 \\\n  SPARSE_SMM_BOOL_OP_DECLS (M1, M2, API)\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/Sparse-op-defs.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Sparse_op_defs_h)\n#define octave_Sparse_op_defs_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-util.h\"\n#include \"lo-array-errwarn.h\"\n#include \"mx-inlines.cc\"\n#include \"oct-locbuf.h\"\n\n// sparse matrix by scalar operations.\n\n#define SPARSE_SMS_BIN_OP_1(R, F, OP, M, S)                             \\\n  R                                                                     \\\n  F (const M& m, const S& s)                                            \\\n  {                                                                     \\\n    octave_idx_type nr = m.rows ();                                     \\\n    octave_idx_type nc = m.cols ();                                     \\\n                                                                        \\\n    R r (nr, nc, (0.0 OP s));                                           \\\n                                                                        \\\n    for (octave_idx_type j = 0; j < nc; j++)                            \\\n      for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)       \\\n        r.xelem (m.ridx (i), j) = m.data (i) OP s;                      \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMS_BIN_OP_2(R, F, OP, M, S)             \\\n  R                                                     \\\n  F (const M& m, const S& s)                            \\\n  {                                                     \\\n    octave_idx_type nr = m.rows ();                     \\\n    octave_idx_type nc = m.cols ();                     \\\n    octave_idx_type nz = m.nnz ();                      \\\n                                                        \\\n    R r (nr, nc, nz);                                   \\\n                                                        \\\n    for (octave_idx_type i = 0; i < nz; i++)            \\\n      {                                                 \\\n        r.xdata (i) = m.data (i) OP s;                  \\\n        r.xridx (i) = m.ridx (i);                       \\\n      }                                                 \\\n    for (octave_idx_type i = 0; i < nc + 1; i++)        \\\n      r.xcidx (i) = m.cidx (i);                         \\\n                                                        \\\n    r.maybe_compress (true);                            \\\n    return r;                                           \\\n  }\n\n#define SPARSE_SMS_BIN_OPS(R1, R2, M, S)        \\\n  SPARSE_SMS_BIN_OP_1 (R1, operator +, +, M, S) \\\n  SPARSE_SMS_BIN_OP_1 (R1, operator -, -, M, S) \\\n  SPARSE_SMS_BIN_OP_2 (R2, operator *, *, M, S) \\\n  SPARSE_SMS_BIN_OP_2 (R2, operator /, /, M, S)\n\n#define SPARSE_SMS_CMP_OP(F, OP, M, S)                                  \\\n  SparseBoolMatrix                                                      \\\n  F (const M& m, const S& s)                                            \\\n  {                                                                     \\\n    octave_idx_type nr = m.rows ();                                     \\\n    octave_idx_type nc = m.cols ();                                     \\\n    SparseBoolMatrix r;                                                 \\\n                                                                        \\\n    M::element_type m_zero = M::element_type ();                        \\\n                                                                        \\\n    if (m_zero OP s)                                                    \\\n      {                                                                 \\\n        r = SparseBoolMatrix (nr, nc, true);                            \\\n        for (octave_idx_type j = 0; j < nc; j++)                        \\\n          for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)   \\\n            if (! (m.data (i) OP s))                                    \\\n              r.data (m.ridx (i) + j * nr) = false;                     \\\n        r.maybe_compress (true);                                        \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        r = SparseBoolMatrix (nr, nc, m.nnz ());                        \\\n        r.cidx (0) = static_cast<octave_idx_type> (0);                  \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < nc; j++)                        \\\n          {                                                             \\\n            for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \\\n              if (m.data (i) OP s)                                      \\\n                {                                                       \\\n                  r.ridx (nel) = m.ridx (i);                            \\\n                  r.data (nel++) = true;                                \\\n                }                                                       \\\n            r.cidx (j + 1) = nel;                                       \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMS_CMP_OPS(M, S)                \\\n  SPARSE_SMS_CMP_OP (mx_el_lt, <,  M, S)        \\\n  SPARSE_SMS_CMP_OP (mx_el_le, <=, M, S)        \\\n  SPARSE_SMS_CMP_OP (mx_el_ge, >=, M, S)        \\\n  SPARSE_SMS_CMP_OP (mx_el_gt, >,  M, S)        \\\n  SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, S)        \\\n  SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, S)\n\n#define SPARSE_SMS_EQNE_OPS(M, S)               \\\n  SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, S)        \\\n  SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, S)\n\n#define SPARSE_SMS_BOOL_AND_OP(M, S)                                    \\\n  SparseBoolMatrix                                                      \\\n  mx_el_and (const M& m, const S& s)                                    \\\n  {                                                                     \\\n    octave_idx_type nr = m.rows ();                                     \\\n    octave_idx_type nc = m.cols ();                                     \\\n    SparseBoolMatrix r;                                                 \\\n                                                                        \\\n    M::element_type lhs_zero = M::element_type ();                      \\\n    S rhs_zero = S ();                                                  \\\n                                                                        \\\n    if (nr > 0 && nc > 0)                                               \\\n      {                                                                 \\\n        if (s != rhs_zero)                                              \\\n          {                                                             \\\n            r = SparseBoolMatrix (nr, nc, m.nnz ());                    \\\n            r.cidx (0) = static_cast<octave_idx_type> (0);              \\\n            octave_idx_type nel = 0;                                    \\\n            for (octave_idx_type j = 0; j < nc; j++)                    \\\n              {                                                         \\\n                for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \\\n                  if (m.data (i) != lhs_zero)                           \\\n                    {                                                   \\\n                      r.ridx (nel) = m.ridx (i);                        \\\n                      r.data (nel++) = true;                            \\\n                    }                                                   \\\n                r.cidx (j + 1) = nel;                                   \\\n              }                                                         \\\n            r.maybe_compress (false);                                   \\\n          }                                                             \\\n        else                                                            \\\n          r = SparseBoolMatrix (nr, nc);                                \\\n      }                                                                 \\\n    else                                                                \\\n      r = SparseBoolMatrix (nr, nc);                                    \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMS_BOOL_OR_OP(M, S)                                     \\\n  boolMatrix                                                            \\\n  mx_el_or (const M& m, const S& s)                                     \\\n  {                                                                     \\\n    octave_idx_type nr = m.rows ();                                     \\\n    octave_idx_type nc = m.cols ();                                     \\\n    boolMatrix r;                                                       \\\n                                                                        \\\n    M::element_type lhs_zero = M::element_type ();                      \\\n    S rhs_zero = S ();                                                  \\\n                                                                        \\\n    if (nr > 0 && nc > 0)                                               \\\n      {                                                                 \\\n        if (s != rhs_zero)                                              \\\n          r = boolMatrix (nr, nc, true);                                \\\n        else                                                            \\\n          {                                                             \\\n            r = boolMatrix (nr, nc, false);                             \\\n                                                                        \\\n            for (octave_idx_type j = 0; j < nc; j++)                    \\\n              for (octave_idx_type i = 0; i < nr; i++)                  \\\n                if (m.elem (i, j) != lhs_zero)                          \\\n                  r.elem (i, j) = true;                                 \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      r = boolMatrix (nr, nc, false);                                   \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMS_BOOL_OPS(M, S)               \\\n  SPARSE_SMS_BOOL_AND_OP (M, S)                 \\\n  SPARSE_SMS_BOOL_OR_OP  (M, S)\n\n// scalar by sparse matrix operations.\n\n#define SPARSE_SSM_BIN_OP_1(R, F, OP, S, M)                             \\\n  R                                                                     \\\n  F (const S& s, const M& m)                                            \\\n  {                                                                     \\\n    octave_idx_type nr = m.rows ();                                     \\\n    octave_idx_type nc = m.cols ();                                     \\\n                                                                        \\\n    R r (nr, nc, (s OP 0.0));                                           \\\n                                                                        \\\n    for (octave_idx_type j = 0; j < nc; j++)                            \\\n      for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)       \\\n        r.xelem (m.ridx (i), j) = s OP m.data (i);                      \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SSM_BIN_OP_2(R, F, OP, S, M)             \\\n  R                                                     \\\n  F (const S& s, const M& m)                            \\\n  {                                                     \\\n    octave_idx_type nr = m.rows ();                     \\\n    octave_idx_type nc = m.cols ();                     \\\n    octave_idx_type nz = m.nnz ();                      \\\n                                                        \\\n    R r (nr, nc, nz);                                   \\\n                                                        \\\n    for (octave_idx_type i = 0; i < nz; i++)            \\\n      {                                                 \\\n        r.xdata (i) = s OP m.data (i);                  \\\n        r.xridx (i) = m.ridx (i);                       \\\n      }                                                 \\\n    for (octave_idx_type i = 0; i < nc + 1; i++)        \\\n      r.xcidx (i) = m.cidx (i);                         \\\n                                                        \\\n    r.maybe_compress(true);                             \\\n    return r;                                           \\\n  }\n\n#define SPARSE_SSM_BIN_OPS(R1, R2, S, M)        \\\n  SPARSE_SSM_BIN_OP_1 (R1, operator +, +, S, M) \\\n  SPARSE_SSM_BIN_OP_1 (R1, operator -, -, S, M) \\\n  SPARSE_SSM_BIN_OP_2 (R2, operator *, *, S, M) \\\n  SPARSE_SSM_BIN_OP_1 (R1, operator /, /, S, M)\n\n#define SPARSE_SSM_CMP_OP(F, OP, S, M)                                  \\\n  SparseBoolMatrix                                                      \\\n  F (const S& s, const M& m)                                            \\\n  {                                                                     \\\n    octave_idx_type nr = m.rows ();                                     \\\n    octave_idx_type nc = m.cols ();                                     \\\n    SparseBoolMatrix r;                                                 \\\n                                                                        \\\n    M::element_type m_zero = M::element_type ();                        \\\n                                                                        \\\n    if (s OP m_zero)                                                    \\\n      {                                                                 \\\n        r = SparseBoolMatrix (nr, nc, true);                            \\\n        for (octave_idx_type j = 0; j < nc; j++)                        \\\n          for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)   \\\n            if (! (s OP m.data (i)))                                    \\\n              r.data (m.ridx (i) + j * nr) = false;                     \\\n        r.maybe_compress (true);                                        \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        r = SparseBoolMatrix (nr, nc, m.nnz ());                        \\\n        r.cidx (0) = static_cast<octave_idx_type> (0);                  \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < nc; j++)                        \\\n          {                                                             \\\n            for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \\\n              if (s OP m.data (i))                                      \\\n                {                                                       \\\n                  r.ridx (nel) = m.ridx (i);                            \\\n                  r.data (nel++) = true;                                \\\n                }                                                       \\\n            r.cidx (j + 1) = nel;                                       \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SSM_CMP_OPS(S, M)                \\\n  SPARSE_SSM_CMP_OP (mx_el_lt, <,  S, M)        \\\n  SPARSE_SSM_CMP_OP (mx_el_le, <=, S, M)        \\\n  SPARSE_SSM_CMP_OP (mx_el_ge, >=, S, M)        \\\n  SPARSE_SSM_CMP_OP (mx_el_gt, >,  S, M)        \\\n  SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, M)        \\\n  SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, M)\n\n#define SPARSE_SSM_EQNE_OPS(S, M)               \\\n  SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, M)        \\\n  SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, M)\n\n#define SPARSE_SSM_BOOL_AND_OP(S, M)                                    \\\n  SparseBoolMatrix                                                      \\\n  mx_el_and (const S& s, const M& m)                                    \\\n  {                                                                     \\\n    octave_idx_type nr = m.rows ();                                     \\\n    octave_idx_type nc = m.cols ();                                     \\\n    SparseBoolMatrix r;                                                 \\\n                                                                        \\\n    S lhs_zero = S ();                                                  \\\n    M::element_type rhs_zero = M::element_type ();                      \\\n                                                                        \\\n    if (nr > 0 && nc > 0)                                               \\\n      {                                                                 \\\n        if (s != lhs_zero)                                              \\\n          {                                                             \\\n            r = SparseBoolMatrix (nr, nc, m.nnz ());                    \\\n            r.cidx (0) = static_cast<octave_idx_type> (0);              \\\n            octave_idx_type nel = 0;                                    \\\n            for (octave_idx_type j = 0; j < nc; j++)                    \\\n              {                                                         \\\n                for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \\\n                  if (m.data (i) != rhs_zero)                           \\\n                    {                                                   \\\n                      r.ridx (nel) = m.ridx (i);                        \\\n                      r.data (nel++) = true;                            \\\n                    }                                                   \\\n                r.cidx (j + 1) = nel;                                   \\\n              }                                                         \\\n            r.maybe_compress (false);                                   \\\n          }                                                             \\\n        else                                                            \\\n          r = SparseBoolMatrix (nr, nc);                                \\\n      }                                                                 \\\n    else                                                                \\\n      r = SparseBoolMatrix (nr, nc);                                    \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SSM_BOOL_OR_OP(S, M)                                     \\\n  boolMatrix                                                            \\\n  mx_el_or (const S& s, const M& m)                                     \\\n  {                                                                     \\\n    octave_idx_type nr = m.rows ();                                     \\\n    octave_idx_type nc = m.cols ();                                     \\\n    boolMatrix r;                                                       \\\n                                                                        \\\n    S lhs_zero = S ();                                                  \\\n    M::element_type rhs_zero = M::element_type ();                      \\\n                                                                        \\\n    if (nr > 0 && nc > 0)                                               \\\n      {                                                                 \\\n        if (s != lhs_zero)                                              \\\n          r = boolMatrix (nr, nc, true);                                \\\n        else                                                            \\\n          {                                                             \\\n            r = boolMatrix (nr, nc, false);                             \\\n                                                                        \\\n            for (octave_idx_type j = 0; j < nc; j++)                    \\\n              for (octave_idx_type i = 0; i < nr; i++)                  \\\n                if (m.elem (i, j) != rhs_zero)                          \\\n                  r.elem (i, j) = true;                                 \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      r = boolMatrix (nr, nc, false);                                   \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SSM_BOOL_OPS(S, M)               \\\n  SPARSE_SSM_BOOL_AND_OP (S, M)                 \\\n  SPARSE_SSM_BOOL_OR_OP  (S, M)\n\n// sparse matrix by sparse matrix operations.\n\n#define SPARSE_SMSM_BIN_OP_1(R, F, OP, M1, M2)                          \\\n  R                                                                     \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    R r;                                                                \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    if (m1_nr == 1 && m1_nc == 1)                                       \\\n      {                                                                 \\\n        if (m1.elem (0,0) == 0.)                                        \\\n          r = OP R (m2);                                                \\\n        else                                                            \\\n          {                                                             \\\n            r = R (m2_nr, m2_nc, m1.data (0) OP 0.);                    \\\n                                                                        \\\n            for (octave_idx_type j = 0 ; j < m2_nc ; j++)               \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                octave_idx_type idxj = j * m2_nr;                       \\\n                for (octave_idx_type i = m2.cidx (j) ; i < m2.cidx (j+1) ; i++) \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                    r.data (idxj + m2.ridx (i)) = m1.data (0) OP m2.data (i);   \\\n                  }                                                     \\\n              }                                                         \\\n            r.maybe_compress ();                                        \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m2_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        if (m2.elem (0,0) == 0.)                                        \\\n          r = R (m1);                                                   \\\n        else                                                            \\\n          {                                                             \\\n            r = R (m1_nr, m1_nc, 0. OP m2.data (0));                    \\\n                                                                        \\\n            for (octave_idx_type j = 0 ; j < m1_nc ; j++)               \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                octave_idx_type idxj = j * m1_nr;                       \\\n                for (octave_idx_type i = m1.cidx (j) ; i < m1.cidx (j+1) ; i++) \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                    r.data (idxj + m1.ridx (i)) = m1.data (i) OP m2.data (0);   \\\n                  }                                                     \\\n              }                                                         \\\n            r.maybe_compress ();                                        \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                  \\\n      {                                                                 \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                 \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                  \\\n      {                                                                 \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                  \\\n      {                                                                 \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                 \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                  \\\n      {                                                                 \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \\\n      {                                                                 \\\n        r = R (m1_nr, m1_nc, (m1.nnz () + m2.nnz ()));                  \\\n                                                                        \\\n        octave_idx_type jx = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        for (octave_idx_type i = 0 ; i < m1_nc ; i++)                   \\\n          {                                                             \\\n            octave_idx_type ja = m1.cidx (i);                           \\\n            octave_idx_type ja_max = m1.cidx (i+1);                     \\\n            bool ja_lt_max = ja < ja_max;                               \\\n                                                                        \\\n            octave_idx_type jb = m2.cidx (i);                           \\\n            octave_idx_type jb_max = m2.cidx (i+1);                     \\\n            bool jb_lt_max = jb < jb_max;                               \\\n                                                                        \\\n            while (ja_lt_max || jb_lt_max)                              \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                if ((! jb_lt_max) ||                                    \\\n                    (ja_lt_max && (m1.ridx (ja) < m2.ridx (jb))))       \\\n                  {                                                     \\\n                    r.ridx (jx) = m1.ridx (ja);                         \\\n                    r.data (jx) = m1.data (ja) OP 0.;                   \\\n                    jx++;                                               \\\n                    ja++;                                               \\\n                    ja_lt_max= ja < ja_max;                             \\\n                  }                                                     \\\n                else if ((! ja_lt_max) ||                               \\\n                         (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja))))  \\\n                  {                                                     \\\n                    r.ridx (jx) = m2.ridx (jb);                         \\\n                    r.data (jx) = 0. OP m2.data (jb);                   \\\n                    jx++;                                               \\\n                    jb++;                                               \\\n                    jb_lt_max= jb < jb_max;                             \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    if ((m1.data (ja) OP m2.data (jb)) != 0.)           \\\n                      {                                                 \\\n                        r.data (jx) = m1.data (ja) OP m2.data (jb);     \\\n                        r.ridx (jx) = m1.ridx (ja);                     \\\n                        jx++;                                           \\\n                      }                                                 \\\n                    ja++;                                               \\\n                    ja_lt_max= ja < ja_max;                             \\\n                    jb++;                                               \\\n                    jb_lt_max= jb < jb_max;                             \\\n                  }                                                     \\\n              }                                                         \\\n            r.cidx (i+1) = jx;                                          \\\n          }                                                             \\\n                                                                        \\\n        r.maybe_compress ();                                            \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))              \\\n      {                                                                 \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);         \\\n        octave_idx_type rnnz = (m1_nc < m2_nc ? m1.nnz () * m2_nc + m2.nnz () : \\\n                                                m1.nnz () + m1_nc * m2.nnz ()); \\\n        r = R (m1_nr, r_nc, rnnz);                                      \\\n                                                                        \\\n        octave_idx_type jx = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        for (octave_idx_type i = 0 ; i < r_nc ; i++)                    \\\n          {                                                             \\\n            octave_idx_type ja;                                         \\\n            octave_idx_type ja_max;                                     \\\n            octave_idx_type jb;                                         \\\n            octave_idx_type jb_max;                                     \\\n            if (m1_nc == 1)                                             \\\n              {                                                         \\\n                ja = m1.cidx(0);                                        \\\n                ja_max = m1.cidx(1);                                    \\\n                jb = m2.cidx (i);                                       \\\n                jb_max = m2.cidx (i+1);                                 \\\n              }                                                         \\\n            else                                                        \\\n              {                                                         \\\n                ja = m1.cidx(i);                                        \\\n                ja_max = m1.cidx(i+1);                                  \\\n                jb = m2.cidx (0);                                       \\\n                jb_max = m2.cidx (1);                                   \\\n              }                                                         \\\n            bool ja_lt_max = ja < ja_max;                               \\\n            bool jb_lt_max = jb < jb_max;                               \\\n                                                                        \\\n            while (ja_lt_max || jb_lt_max)                              \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                if ((! jb_lt_max) ||                                    \\\n                    (ja_lt_max && (m1.ridx (ja) < m2.ridx (jb))))       \\\n                  {                                                     \\\n                    r.ridx (jx) = m1.ridx (ja);                         \\\n                    r.data (jx) = m1.data (ja) OP 0.;                   \\\n                    jx++;                                               \\\n                    ja++;                                               \\\n                    ja_lt_max = ja < ja_max;                            \\\n                  }                                                     \\\n                else if ((! ja_lt_max) ||                               \\\n                         (m2.ridx (jb) < m1.ridx (ja)))                 \\\n                  {                                                     \\\n                    r.ridx (jx) = m2.ridx (jb);                         \\\n                    r.data (jx) = 0. OP m2.data (jb);                   \\\n                    jx++;                                               \\\n                    jb++;                                               \\\n                    jb_lt_max = jb < jb_max;                            \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    if (m1.data (ja) OP m2.data (jb) != 0.)             \\\n                      {                                                 \\\n                        r.data (jx) = m1.data (ja) OP m2.data (jb);     \\\n                        r.ridx (jx) = m1.ridx (ja);                     \\\n                        jx++;                                           \\\n                      }                                                 \\\n                    ja++;                                               \\\n                    ja_lt_max = ja < ja_max;                            \\\n                    jb++;                                               \\\n                    jb_lt_max = jb < jb_max;                            \\\n                  }                                                     \\\n              }                                                         \\\n            r.cidx (i+1) = jx;                                          \\\n          }                                                             \\\n        r.maybe_compress ();                                            \\\n      }                                                                 \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))              \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else if (m1_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        r = R (m2_nr, m1_nc, (m1.nnz () * m2_nr + m2.nnz () * m1_nc));  \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            const Complex a_val = m1.elem (0, j);                       \\\n                                                                        \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                 \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                                                                        \\\n                const Complex b_val = m2.elem (i, 0);                   \\\n                const Complex val = a_val OP b_val;                     \\\n                                                                        \\\n                if (val != Complex ())                                  \\\n                  r.elem (i, j) = val;                                  \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress ();                                            \\\n      }                                                                 \\\n    else if (m1_nc == 1 && m2_nr == 1)                                  \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMSM_BIN_OP_2(R, F, OP, M1, M2)                            \\\n  R                                                                       \\\n  F (const M1& m1, const M2& m2)                                          \\\n  {                                                                       \\\n    R r;                                                                  \\\n    Complex nan = Complex (octave::numeric_limits<double>::NaN (),        \\\n                           octave::numeric_limits<double>::NaN ());       \\\n                                                                          \\\n    octave_idx_type m1_nr = m1.rows ();                                   \\\n    octave_idx_type m1_nc = m1.cols ();                                   \\\n                                                                          \\\n    octave_idx_type m2_nr = m2.rows ();                                   \\\n    octave_idx_type m2_nc = m2.cols ();                                   \\\n                                                                          \\\n    if (m1_nr == 1 && m1_nc == 1)                                         \\\n      {                                                                   \\\n        if (m1.elem (0, 0) == 0.0)                                        \\\n          r = R (m2_nr, m2_nc);                                           \\\n        else if (octave::math::isnan (m1.elem (0, 0)))                    \\\n          {                                                               \\\n            r = R (m2_nr, m2_nc, m2_nr * m2_nc);                          \\\n            for (octave_idx_type i = 0 ; i < r.numel () ; i++)            \\\n              r.elem(i) = nan;                                            \\\n          }                                                               \\\n        else if (octave::math::isinf (m1.elem (0, 0)))                    \\\n          {                                                               \\\n            r = R (m2_nr, m2_nc, m2_nr * m2_nc);                          \\\n                                                                          \\\n            for (octave_idx_type j = 0 ; j < m2_nc ; j++)                 \\\n              {                                                           \\\n                octave_quit ();                                           \\\n                for (octave_idx_type i = 0 ; i < m2_nr ; i++)             \\\n                  {                                                       \\\n                    if (m2.elem (i, j) == 0.0)                            \\\n                      r.elem (i, j) = nan;                                \\\n                    else                                                  \\\n                      r.elem (i, j) = m1.elem (0, 0) * m2.elem (i, j);    \\\n                  }                                                       \\\n              }                                                           \\\n            r.maybe_compress (true);                                      \\\n          }                                                               \\\n        else                                                              \\\n          {                                                               \\\n            r = R (m2);                                                   \\\n            octave_idx_type m2_nnz = m2.nnz ();                           \\\n                                                                          \\\n            for (octave_idx_type i = 0 ; i < m2_nnz ; i++)                \\\n              {                                                           \\\n                octave_quit ();                                           \\\n                r.data (i) = m1.data (0) OP r.data (i);                   \\\n              }                                                           \\\n            r.maybe_compress ();                                          \\\n          }                                                               \\\n      }                                                                   \\\n    else if (m2_nr == 1 && m2_nc == 1)                                    \\\n      {                                                                   \\\n        if (m2.elem (0, 0) == 0.0)                                        \\\n          r = R (m1_nr, m1_nc);                                           \\\n        else if (octave::math::isnan (m2.elem (0, 0)))                    \\\n          {                                                               \\\n            r = R (m1_nr, m1_nc, m1_nr * m1_nc);                          \\\n            for (octave_idx_type i = 0 ; i < r.numel () ; i++)            \\\n              r.elem(i) = nan;                                            \\\n          }                                                               \\\n        else if (octave::math::isinf (m2.elem (0, 0)))                    \\\n          {                                                               \\\n            r = R (m1_nr, m1_nc, m1_nr * m1_nc);                          \\\n                                                                          \\\n            for (octave_idx_type j = 0 ; j < m1_nc ; j++)                 \\\n              {                                                           \\\n                octave_quit ();                                           \\\n                for (octave_idx_type i = 0 ; i < m1_nr ; i++)             \\\n                  {                                                       \\\n                    if (m1.elem (i, j) == 0.0)                            \\\n                      r.elem (i, j) = nan;                                \\\n                    else                                                  \\\n                      r.elem (i, j) = m1.elem (i, j) * m2.elem (0, 0);    \\\n                  }                                                       \\\n              }                                                           \\\n            r.maybe_compress (true);                                      \\\n          }                                                               \\\n        else                                                              \\\n          {                                                               \\\n            r = R (m1);                                                   \\\n            octave_idx_type m1_nnz = m1.nnz ();                           \\\n                                                                          \\\n            for (octave_idx_type i = 0 ; i < m1_nnz ; i++)                \\\n              {                                                           \\\n                octave_quit ();                                           \\\n                r.data (i) = r.data (i) OP m2.data (0);                   \\\n              }                                                           \\\n            r.maybe_compress ();                                          \\\n          }                                                               \\\n      }                                                                   \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                    \\\n      {                                                                   \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                   \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                      \\\n        else                                                              \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);     \\\n      }                                                                   \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                    \\\n      {                                                                   \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                   \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                      \\\n        else                                                              \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);     \\\n      }                                                                   \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                    \\\n      {                                                                   \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                   \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                      \\\n        else                                                              \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);     \\\n      }                                                                   \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                    \\\n      {                                                                   \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                   \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                      \\\n        else                                                              \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);     \\\n      }                                                                   \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc &&                          \\\n             (m1.any_element_is_inf_or_nan () ||                          \\\n              m2.any_element_is_inf_or_nan ()))                           \\\n      {                                                                   \\\n        r = R (m1_nr, m1_nc, m1_nr * m1_nc);                              \\\n                                                                          \\\n        for (octave_idx_type j = 0 ; j < m1_nc ; j++)                     \\\n          {                                                               \\\n            octave_quit ();                                               \\\n            for (octave_idx_type i = 0 ; i < m1_nr ; i++)                 \\\n              r.elem (i, j) = m1.elem (i, j) * m2.elem (i, j);            \\\n          }                                                               \\\n        r.maybe_compress (true);                                          \\\n      }                                                                   \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                            \\\n      {                                                                   \\\n        r = R (m1_nr, m1_nc,                                              \\\n               (m1.nnz () > m2.nnz () ? m1.nnz () : m2.nnz ()));          \\\n                                                                          \\\n        octave_idx_type jx = 0;                                           \\\n        r.cidx (0) = 0;                                                   \\\n        for (octave_idx_type i = 0 ; i < m1_nc ; i++)                     \\\n          {                                                               \\\n            octave_idx_type ja = m1.cidx (i);                             \\\n            octave_idx_type ja_max = m1.cidx (i+1);                       \\\n            bool ja_lt_max = ja < ja_max;                                 \\\n                                                                          \\\n            octave_idx_type jb = m2.cidx (i);                             \\\n            octave_idx_type jb_max = m2.cidx (i+1);                       \\\n            bool jb_lt_max = jb < jb_max;                                 \\\n                                                                          \\\n            while (ja_lt_max || jb_lt_max)                                \\\n              {                                                           \\\n                octave_quit ();                                           \\\n                if ((! jb_lt_max) ||                                      \\\n                    (ja_lt_max && (m1.ridx (ja) < m2.ridx (jb))))         \\\n                  {                                                       \\\n                    ja++; ja_lt_max= ja < ja_max;                         \\\n                  }                                                       \\\n                else if ((! ja_lt_max) ||                                 \\\n                         (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja))))    \\\n                  {                                                       \\\n                    jb++; jb_lt_max= jb < jb_max;                         \\\n                  }                                                       \\\n                else                                                      \\\n                  {                                                       \\\n                    if ((m1.data (ja) OP m2.data (jb)) != 0.)             \\\n                      {                                                   \\\n                        r.data (jx) = m1.data (ja) OP m2.data (jb);       \\\n                        r.ridx (jx) = m1.ridx (ja);                       \\\n                        jx++;                                             \\\n                      }                                                   \\\n                    ja++; ja_lt_max= ja < ja_max;                         \\\n                    jb++; jb_lt_max= jb < jb_max;                         \\\n                  }                                                       \\\n              }                                                           \\\n            r.cidx (i+1) = jx;                                            \\\n          }                                                               \\\n                                                                          \\\n        r.maybe_compress ();                                              \\\n      }                                                                   \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1) &&              \\\n             (m1.any_element_is_inf_or_nan () ||                          \\\n              m2.any_element_is_inf_or_nan ()))                           \\\n      {                                                                   \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);           \\\n        r = R (m1_nr, r_nc, m1_nr * r_nc);                                \\\n                                                                          \\\n        if (m1_nc == 1)                                                   \\\n          {                                                               \\\n            for (octave_idx_type j = 0 ; j < r_nc ; j++)                  \\\n              {                                                           \\\n                octave_quit ();                                           \\\n                for (octave_idx_type i = 0 ; i < m1_nr ; i++)             \\\n                  r.elem (i, j) = m1.elem (i, 0) * m2.elem (i, j);        \\\n              }                                                           \\\n          }                                                               \\\n        else                                                              \\\n          {                                                               \\\n            for (octave_idx_type j = 0 ; j < r_nc ; j++)                  \\\n              {                                                           \\\n                octave_quit ();                                           \\\n                for (octave_idx_type i = 0 ; i < m1_nr ; i++)             \\\n                  r.elem (i, j) = m1.elem (i, j) * m2.elem (i, 0);        \\\n              }                                                           \\\n          }                                                               \\\n        r.maybe_compress (true);                                          \\\n      }                                                                   \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))                \\\n      {                                                                   \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);           \\\n        octave_idx_type rnnz = (m1_nc < m2_nc ?                           \\\n                                m1.nnz () * m2_nc + m2.nnz () :           \\\n                                m1.nnz () + m1_nc * m2.nnz ());           \\\n        r = R (m1_nr, r_nc, rnnz);                                        \\\n                                                                          \\\n        octave_idx_type jx = 0;                                           \\\n        r.cidx (0) = 0;                                                   \\\n        for (octave_idx_type i = 0 ; i < r_nc ; i++)                      \\\n          {                                                               \\\n            octave_idx_type ja;                                           \\\n            octave_idx_type ja_max;                                       \\\n            octave_idx_type jb;                                           \\\n            octave_idx_type jb_max;                                       \\\n            if (m1_nc == 1)                                               \\\n              {                                                           \\\n                ja = m1.cidx(0);                                          \\\n                ja_max = m1.cidx(1);                                      \\\n                jb = m2.cidx (i);                                         \\\n                jb_max = m2.cidx (i+1);                                   \\\n              }                                                           \\\n            else                                                          \\\n              {                                                           \\\n                ja = m1.cidx(i);                                          \\\n                ja_max = m1.cidx(i+1);                                    \\\n                jb = m2.cidx (0);                                         \\\n                jb_max = m2.cidx (1);                                     \\\n              }                                                           \\\n            bool ja_lt_max = ja < ja_max;                                 \\\n            bool jb_lt_max = jb < jb_max;                                 \\\n                                                                          \\\n            while (ja_lt_max || jb_lt_max)                                \\\n              {                                                           \\\n                octave_quit ();                                           \\\n                if ((! jb_lt_max) ||                                      \\\n                    (ja_lt_max && (m1.ridx (ja) < m2.ridx (jb))))         \\\n                  {                                                       \\\n                    ja++;                                                 \\\n                    ja_lt_max = ja < ja_max;                              \\\n                  }                                                       \\\n                else if ((! ja_lt_max) ||                                 \\\n                         (m2.ridx (jb) < m1.ridx (ja)))                   \\\n                  {                                                       \\\n                    jb++;                                                 \\\n                    jb_lt_max = jb < jb_max;                              \\\n                  }                                                       \\\n                else                                                      \\\n                  {                                                       \\\n                    if (m1.data (ja) OP m2.data (jb) != 0.)               \\\n                      {                                                   \\\n                        r.data (jx) = m1.data (ja) OP m2.data (jb);       \\\n                        r.ridx (jx) = m1.ridx (ja);                       \\\n                        jx++;                                             \\\n                      }                                                   \\\n                    ja++;                                                 \\\n                    ja_lt_max = ja < ja_max;                              \\\n                    jb++;                                                 \\\n                    jb_lt_max = jb < jb_max;                              \\\n                  }                                                       \\\n              }                                                           \\\n            r.cidx (i+1) = jx;                                            \\\n          }                                                               \\\n        r.maybe_compress ();                                              \\\n      }                                                                   \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))                \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();              \\\n    else if (m1_nr == 1 && m2_nc == 1 &&                                  \\\n             (m1.any_element_is_inf_or_nan () ||                          \\\n              m2.any_element_is_inf_or_nan ()))                           \\\n      {                                                                   \\\n        r = R (m2_nr, m1_nc, m2_nr * m1_nc);                              \\\n                                                                          \\\n        for (octave_idx_type j = 0 ; j < m1_nc ; j++)                     \\\n          {                                                               \\\n            octave_quit ();                                               \\\n            for (octave_idx_type i = 0 ; i < m2_nr ; i++)                 \\\n              r.elem (i, j) = m1.elem (0, j) * m2.elem (i, 0);            \\\n          }                                                               \\\n        r.maybe_compress (true);                                          \\\n      }                                                                   \\\n    else if (m1_nr == 1 && m2_nc == 1)                                    \\\n      {                                                                   \\\n        r = R (m2_nr, m1_nc, (m1.nnz () * m2_nr + m2.nnz () * m1_nc));    \\\n                                                                          \\\n        octave_idx_type jx = 0;                                           \\\n        r.cidx (0) = 0;                                                   \\\n        for (octave_idx_type i = 0 ; i < m1_nc ; i++)                     \\\n          {                                                               \\\n            octave_idx_type ja = m1.cidx (i);                             \\\n            octave_idx_type ja_max = m1.cidx (i+1);                       \\\n            bool ja_lt_max = ja < ja_max;                                 \\\n                                                                          \\\n            octave_idx_type jb = m2.cidx (0);                             \\\n            octave_idx_type jb_max = m2.cidx (1);                         \\\n            bool jb_lt_max = jb < jb_max;                                 \\\n                                                                          \\\n            while (ja_lt_max || jb_lt_max)                                \\\n              {                                                           \\\n                octave_quit ();                                           \\\n                if (! ja_lt_max && jb_lt_max)                             \\\n                  {                                                       \\\n                    jb++;                                                 \\\n                    jb_lt_max = jb < jb_max;                              \\\n                  }                                                       \\\n                else if (ja_lt_max && ! jb_lt_max)                        \\\n                  {                                                       \\\n                    ja_lt_max = false;                                    \\\n                  }                                                       \\\n                else if (ja_lt_max && jb_lt_max)                          \\\n                  {                                                       \\\n                    if ((m1.data (ja) OP m2.data (jb)) != 0.)             \\\n                      {                                                   \\\n                        r.data (jx) = m1.data (ja) OP m2.data (jb);       \\\n                        r.ridx (jx) = m2.ridx (jb);                       \\\n                        jx++;                                             \\\n                      }                                                   \\\n                    jb++;                                                 \\\n                    jb_lt_max = jb < jb_max;                              \\\n                    ja_lt_max = jb_lt_max;                                \\\n                  }                                                       \\\n              }                                                           \\\n            r.cidx (i+1) = jx;                                            \\\n          }                                                               \\\n        r.maybe_compress ();                                              \\\n      }                                                                   \\\n    else if (m1_nc == 1 && m2_nr == 1)                                    \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();              \\\n    else                                                                  \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);         \\\n                                                                          \\\n    return r;                                                             \\\n  }\n\n#define SPARSE_SMSM_BIN_OP_3(R, F, OP, M1, M2)                          \\\n  R                                                                     \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    R r;                                                                \\\n    Complex Zero = Complex ();                                          \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    if (m1_nr == 1 && m1_nc == 1)                                       \\\n      {                                                                 \\\n        if ((m1.elem (0,0) OP Zero) == Zero)                            \\\n          {                                                             \\\n            octave_idx_type m2_nnz = m2.nnz ();                         \\\n            r = R (m2);                                                 \\\n            for (octave_idx_type i = 0 ; i < m2_nnz ; i++)              \\\n              r.data (i) = m1.elem (0,0) OP r.data (i);                 \\\n            r.maybe_compress ();                                        \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            r = R (m2_nr, m2_nc, m1.elem (0,0) OP Zero);                \\\n            for (octave_idx_type j = 0 ; j < m2_nc ; j++)               \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                octave_idx_type idxj = j * m2_nr;                       \\\n                for (octave_idx_type i = m2.cidx (j) ; i < m2.cidx (j+1) ; i++) \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                    r.data (idxj + m2.ridx (i)) = m1.elem (0,0) OP m2.data (i); \\\n                  }                                                     \\\n              }                                                         \\\n            r.maybe_compress ();                                        \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m2_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        if ((Zero OP m1.elem (0,0)) == Zero)                            \\\n          {                                                             \\\n            octave_idx_type m1_nnz = m1.nnz ();                         \\\n            r = R (m1);                                                 \\\n            for (octave_idx_type i = 0 ; i < m1_nnz ; i++)              \\\n              r.data (i) = r.data (i) OP m2.elem (0,0);                 \\\n            r.maybe_compress ();                                        \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            r = R (m1_nr, m1_nc, Zero OP m2.elem (0,0));                \\\n            for (octave_idx_type j = 0 ; j < m1_nc ; j++)               \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                octave_idx_type idxj = j * m1_nr;                       \\\n                for (octave_idx_type i = m1.cidx (j) ; i < m1.cidx (j+1) ; i++) \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                    r.data (idxj + m1.ridx (i)) = m1.data (i) OP m2.elem (0,0); \\\n                  }                                                     \\\n              }                                                         \\\n            r.maybe_compress ();                                        \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                  \\\n      {                                                                 \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                 \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                  \\\n      {                                                                 \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                  \\\n      {                                                                 \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                 \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                  \\\n      {                                                                 \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \\\n      {                                                                 \\\n                                                                        \\\n        /* FIXME: Kludge... Always double/Complex, so Complex () */     \\\n        r = R (m1_nr, m1_nc, (Zero OP Zero));                           \\\n                                                                        \\\n        for (octave_idx_type i = 0 ; i < m1_nc ; i++)                   \\\n          {                                                             \\\n            octave_idx_type ja = m1.cidx (i);                           \\\n            octave_idx_type ja_max = m1.cidx (i+1);                     \\\n            bool ja_lt_max = ja < ja_max;                               \\\n                                                                        \\\n            octave_idx_type jb = m2.cidx (i);                           \\\n            octave_idx_type jb_max = m2.cidx (i+1);                     \\\n            bool jb_lt_max = jb < jb_max;                               \\\n                                                                        \\\n            while (ja_lt_max || jb_lt_max)                              \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                if ((! jb_lt_max) ||                                    \\\n                    (ja_lt_max && (m1.ridx (ja) < m2.ridx (jb))))       \\\n                  {                                                     \\\n                    /* keep those kludges coming */                     \\\n                    r.elem (m1.ridx (ja),i) = m1.data (ja) OP Zero;     \\\n                    ja++;                                               \\\n                    ja_lt_max= ja < ja_max;                             \\\n                  }                                                     \\\n                else if ((! ja_lt_max) ||                               \\\n                         (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja))))  \\\n                  {                                                     \\\n                    /* keep those kludges coming */                     \\\n                    r.elem (m2.ridx (jb),i) = Zero OP m2.data (jb);     \\\n                    jb++;                                               \\\n                    jb_lt_max= jb < jb_max;                             \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r.elem (m1.ridx (ja),i) = m1.data (ja) OP           \\\n                                              m2.data (jb);             \\\n                    ja++;                                               \\\n                    ja_lt_max= ja < ja_max;                             \\\n                    jb++;                                               \\\n                    jb_lt_max= jb < jb_max;                             \\\n                  }                                                     \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (true);                                        \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))              \\\n      {                                                                 \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);         \\\n        r = R (m1_nr, r_nc, (Zero / Zero));                             \\\n                                                                        \\\n        for (octave_idx_type i = 0 ; i < r_nc ; i++)                    \\\n          {                                                             \\\n            octave_idx_type ja;                                         \\\n            octave_idx_type ja_max;                                     \\\n            octave_idx_type jb;                                         \\\n            octave_idx_type jb_max;                                     \\\n            if (m1_nc == 1)                                             \\\n              {                                                         \\\n                ja = m1.cidx(0);                                        \\\n                ja_max = m1.cidx(1);                                    \\\n                jb = m2.cidx (i);                                       \\\n                jb_max = m2.cidx (i+1);                                 \\\n              }                                                         \\\n            else                                                        \\\n              {                                                         \\\n                ja = m1.cidx(i);                                        \\\n                ja_max = m1.cidx(i+1);                                  \\\n                jb = m2.cidx (0);                                       \\\n                jb_max = m2.cidx (1);                                   \\\n              }                                                         \\\n            bool ja_lt_max = ja < ja_max;                               \\\n            bool jb_lt_max = jb < jb_max;                               \\\n                                                                        \\\n            while (ja_lt_max || jb_lt_max)                              \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                if ((! jb_lt_max) ||                                    \\\n                     (ja_lt_max && (m1.ridx (ja) < m2.ridx (jb))))      \\\n                  {                                                     \\\n                    r.elem (m1.ridx (ja), i) = m1.data (ja) OP Zero;    \\\n                    ja++;                                               \\\n                    ja_lt_max = ja < ja_max;                            \\\n                  }                                                     \\\n                else if ((! ja_lt_max) ||                               \\\n                         (m2.ridx (jb) < m1.ridx (ja)))                 \\\n                  {                                                     \\\n                    r.elem (m2.ridx (jb), i) = Zero OP m2.data (jb);    \\\n                    jb++;                                               \\\n                    jb_lt_max = jb < jb_max;                            \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r.elem (m1.ridx (ja), i) = m1.data (ja) OP          \\\n                                               m2.data (jb);            \\\n                    ja++;                                               \\\n                    ja_lt_max = ja < ja_max;                            \\\n                    jb++;                                               \\\n                    jb_lt_max = jb < jb_max;                            \\\n                  }                                                     \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (true);                                        \\\n      }                                                                 \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))              \\\n      r = quotient (m1.transpose (), m2.transpose ()).transpose ();     \\\n    else if (m1_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        r = R (m2_nr, m1_nc, (m1_nc * m2_nr));                          \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            const Complex m1_val = m1.elem (0, j);                      \\\n                                                                        \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                 \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                                                                        \\\n                const Complex m2_val = m2.elem (i, 0);                  \\\n                const Complex val = m1_val OP m2_val;                   \\\n                                                                        \\\n                if (val != Zero || val != val)                          \\\n                  r.elem (i, j) = val;                                  \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (true);                                        \\\n      }                                                                 \\\n    else if (m1_nc == 1 && m2_nr == 1)                                  \\\n      r = quotient (m1.transpose (), m2.transpose ()).transpose ();     \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n// Note that SM ./ SM needs to take into account the NaN and Inf values\n// implied by the division by zero.\n// FIXME: Are the NaNs double(NaN) or Complex(NaN,Nan) in the complex case?\n#define SPARSE_SMSM_BIN_OPS(R1, R2, M1, M2)             \\\n  SPARSE_SMSM_BIN_OP_1 (R1, operator +,  +, M1, M2)     \\\n  SPARSE_SMSM_BIN_OP_1 (R1, operator -,  -, M1, M2)     \\\n  SPARSE_SMSM_BIN_OP_2 (R2, product,     *, M1, M2)     \\\n  SPARSE_SMSM_BIN_OP_3 (R2, quotient,    /, M1, M2)\n\n// FIXME: this macro duplicates the bodies of the template functions\n// defined in the SPARSE_SSM_CMP_OP and SPARSE_SMS_CMP_OP macros.\n\n#define SPARSE_SMSM_CMP_OP(F, OP, M1, M2)                               \\\n  SparseBoolMatrix                                                      \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    SparseBoolMatrix r;                                                 \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    M1::element_type Z1 = M1::element_type ();                          \\\n    M2::element_type Z2 = M2::element_type ();                          \\\n                                                                        \\\n    if (m1_nr == 1 && m1_nc == 1)                                       \\\n      {                                                                 \\\n        if (m1.elem (0,0) OP Z2)                                        \\\n          {                                                             \\\n            r = SparseBoolMatrix (m2_nr, m2_nc, true);                  \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              for (octave_idx_type i = m2.cidx (j); i < m2.cidx (j+1); i++)    \\\n                if (! (m1.elem (0,0) OP m2.data (i)))                   \\\n                  r.data (m2.ridx (i) + j * m2_nr) = false;             \\\n            r.maybe_compress (true);                                    \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            r = SparseBoolMatrix (m2_nr, m2_nc, m2.nnz ());             \\\n            r.cidx (0) = static_cast<octave_idx_type> (0);              \\\n            octave_idx_type nel = 0;                                    \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = m2.cidx (j); i < m2.cidx (j+1); i++)  \\\n                  if (m1.elem (0,0) OP m2.data (i))                     \\\n                    {                                                   \\\n                      r.ridx (nel) = m2.ridx (i);                       \\\n                      r.data (nel++) = true;                            \\\n                    }                                                   \\\n                r.cidx (j + 1) = nel;                                   \\\n              }                                                         \\\n            r.maybe_compress (false);                                   \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m2_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        if (Z1 OP m2.elem (0,0))                                        \\\n          {                                                             \\\n            r = SparseBoolMatrix (m1_nr, m1_nc, true);                  \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              for (octave_idx_type i = m1.cidx (j); i < m1.cidx (j+1); i++)    \\\n                if (! (m1.data (i) OP m2.elem (0,0)))                   \\\n                  r.data (m1.ridx (i) + j * m1_nr) = false;             \\\n            r.maybe_compress (true);                                    \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz ());             \\\n            r.cidx (0) = static_cast<octave_idx_type> (0);              \\\n            octave_idx_type nel = 0;                                    \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = m1.cidx (j); i < m1.cidx (j+1); i++)  \\\n                  if (m1.data (i) OP m2.elem (0,0))                     \\\n                    {                                                   \\\n                      r.ridx (nel) = m1.ridx (i);                       \\\n                      r.data (nel++) = true;                            \\\n                    }                                                   \\\n                r.cidx (j + 1) = nel;                                   \\\n              }                                                         \\\n            r.maybe_compress (false);                                   \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                  \\\n      {                                                                 \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                 \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                  \\\n      {                                                                 \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                  \\\n      {                                                                 \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                 \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                  \\\n      {                                                                 \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \\\n      {                                                                 \\\n        if (Z1 OP Z2)                                                   \\\n          {                                                             \\\n            r = SparseBoolMatrix (m1_nr, m1_nc, true);                  \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              {                                                         \\\n                octave_idx_type i1 = m1.cidx (j);                       \\\n                octave_idx_type e1 = m1.cidx (j+1);                     \\\n                octave_idx_type i2 = m2.cidx (j);                       \\\n                octave_idx_type e2 = m2.cidx (j+1);                     \\\n                while (i1 < e1 || i2 < e2)                              \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                                                                        \\\n                    if (i1 == e1 ||                                     \\\n                        (i2 < e2 && m1.ridx (i1) > m2.ridx (i2)))       \\\n                      {                                                 \\\n                        if (! (Z1 OP m2.data (i2)))                     \\\n                          r.data (m2.ridx (i2) + j * m1_nr) = false;    \\\n                        i2++;                                           \\\n                      }                                                 \\\n                    else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))   \\\n                      {                                                 \\\n                        if (! (m1.data (i1) OP Z2))                     \\\n                          r.data (m1.ridx (i1) + j * m1_nr) = false;    \\\n                        i1++;                                           \\\n                      }                                                 \\\n                    else                                                \\\n                      {                                                 \\\n                        if (! (m1.data (i1) OP m2.data (i2)))           \\\n                          r.data (m1.ridx (i1) + j * m1_nr) = false;    \\\n                        i1++;                                           \\\n                        i2++;                                           \\\n                      }                                                 \\\n                  }                                                     \\\n              }                                                         \\\n            r.maybe_compress (true);                                    \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ()); \\\n            r.cidx (0) = static_cast<octave_idx_type> (0);              \\\n            octave_idx_type nel = 0;                                    \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              {                                                         \\\n                octave_idx_type i1 = m1.cidx (j);                       \\\n                octave_idx_type e1 = m1.cidx (j+1);                     \\\n                octave_idx_type i2 = m2.cidx (j);                       \\\n                octave_idx_type e2 = m2.cidx (j+1);                     \\\n                while (i1 < e1 || i2 < e2)                              \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                                                                        \\\n                    if (i1 == e1 ||                                     \\\n                        (i2 < e2 && m1.ridx (i1) > m2.ridx (i2)))       \\\n                      {                                                 \\\n                        if (Z1 OP m2.data (i2))                         \\\n                          {                                             \\\n                            r.ridx (nel) = m2.ridx (i2);                \\\n                            r.data (nel++) = true;                      \\\n                          }                                             \\\n                        i2++;                                           \\\n                      }                                                 \\\n                    else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))   \\\n                      {                                                 \\\n                        if (m1.data (i1) OP Z2)                         \\\n                          {                                             \\\n                            r.ridx (nel) = m1.ridx (i1);                \\\n                            r.data (nel++) = true;                      \\\n                          }                                             \\\n                        i1++;                                           \\\n                      }                                                 \\\n                    else                                                \\\n                      {                                                 \\\n                        if (m1.data (i1) OP m2.data (i2))               \\\n                          {                                             \\\n                            r.ridx (nel) = m1.ridx (i1);                \\\n                            r.data (nel++) = true;                      \\\n                          }                                             \\\n                        i1++;                                           \\\n                        i2++;                                           \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j + 1) = nel;                                   \\\n              }                                                         \\\n            r.maybe_compress (false);                                   \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))              \\\n      {                                                                 \\\n        if (Z1 OP Z2)                                                   \\\n          {                                                             \\\n            octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);     \\\n            r = SparseBoolMatrix (m1_nr, r_nc, true);                   \\\n            for (octave_idx_type j = 0; j < r_nc; j++)                  \\\n              {                                                         \\\n                octave_idx_type i1;                                     \\\n                octave_idx_type e1;                                     \\\n                octave_idx_type i2;                                     \\\n                octave_idx_type e2;                                     \\\n                if (m1_nc == 1)                                         \\\n                  {                                                     \\\n                    i1 = m1.cidx(0);                                    \\\n                    e1 = m1.cidx(1);                                    \\\n                    i2 = m2.cidx (j);                                   \\\n                    e2 = m2.cidx (j+1);                                 \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    i1 = m1.cidx(j);                                    \\\n                    e1 = m1.cidx(j+1);                                  \\\n                    i2 = m2.cidx (0);                                   \\\n                    e2 = m2.cidx (1);                                   \\\n                  }                                                     \\\n                while (i1 < e1 || i2 < e2)                              \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                                                                        \\\n                    if (i1 == e1 ||                                     \\\n                        (i2 < e2 && m1.ridx (i1) > m2.ridx (i2)))       \\\n                      {                                                 \\\n                        if (! (Z1 OP m2.data (i2)))                     \\\n                          r.data (m2.ridx (i2) + j * m1_nr) = false;    \\\n                        i2++;                                           \\\n                      }                                                 \\\n                    else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))   \\\n                      {                                                 \\\n                        if (! (m1.data (i1) OP Z2))                     \\\n                          r.data (m1.ridx (i1) + j * m1_nr) = false;    \\\n                        i1++;                                           \\\n                      }                                                 \\\n                    else                                                \\\n                      {                                                 \\\n                        if (! (m1.data (i1) OP m2.data (i2)))           \\\n                          r.data (m1.ridx (i1) + j * m1_nr) = false;    \\\n                        i1++;                                           \\\n                        i2++;                                           \\\n                      }                                                 \\\n                  }                                                     \\\n              }                                                         \\\n            r.maybe_compress (true);                                    \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);     \\\n            octave_idx_type rnnz = (m1_nc < m2_nc ?                     \\\n                                    m1.nnz () * m2_nc + m2.nnz () :     \\\n                                    m1.nnz () + m1_nc * m2.nnz ());     \\\n            r = SparseBoolMatrix (m1_nr, r_nc, rnnz);                   \\\n                                                                        \\\n            r.cidx (0) = static_cast<octave_idx_type> (0);              \\\n            octave_idx_type nel = 0;                                    \\\n            for (octave_idx_type j = 0; j < r_nc; j++)                  \\\n              {                                                         \\\n                octave_idx_type i1;                                     \\\n                octave_idx_type e1;                                     \\\n                octave_idx_type i2;                                     \\\n                octave_idx_type e2;                                     \\\n                if (m1_nc == 1)                                         \\\n                  {                                                     \\\n                    i1 = m1.cidx(0);                                    \\\n                    e1 = m1.cidx(1);                                    \\\n                    i2 = m2.cidx (j);                                   \\\n                    e2 = m2.cidx (j+1);                                 \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    i1 = m1.cidx(j);                                    \\\n                    e1 = m1.cidx(j+1);                                  \\\n                    i2 = m2.cidx (0);                                   \\\n                    e2 = m2.cidx (1);                                   \\\n                  }                                                     \\\n                while (i1 < e1 || i2 < e2)                              \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                                                                        \\\n                    if (i1 == e1 ||                                     \\\n                        (i2 < e2 && m1.ridx (i1) > m2.ridx (i2)))       \\\n                      {                                                 \\\n                        if (Z1 OP m2.data (i2))                         \\\n                          {                                             \\\n                            r.ridx (nel) = m2.ridx (i2);                \\\n                            r.data (nel++) = true;                      \\\n                          }                                             \\\n                        i2++;                                           \\\n                      }                                                 \\\n                    else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))   \\\n                      {                                                 \\\n                        if (m1.data (i1) OP Z2)                         \\\n                          {                                             \\\n                            r.ridx (nel) = m1.ridx (i1);                \\\n                            r.data (nel++) = true;                      \\\n                          }                                             \\\n                        i1++;                                           \\\n                      }                                                 \\\n                    else                                                \\\n                      {                                                 \\\n                        if (m1.data (i1) OP m2.data (i2))               \\\n                          {                                             \\\n                            r.ridx (nel) = m1.ridx (i1);                \\\n                            r.data (nel++) = true;                      \\\n                          }                                             \\\n                        i1++;                                           \\\n                        i2++;                                           \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j + 1) = nel;                                   \\\n              }                                                         \\\n            r.maybe_compress (false);                                   \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))              \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else if (m1_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        if (Z1 OP Z2)                                                   \\\n          {                                                             \\\n            r = SparseBoolMatrix (m2_nr, m1_nc, true);                  \\\n                                                                        \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              {                                                         \\\n                const Complex m1_val = m1.elem (0, j);                  \\\n                                                                        \\\n                for (octave_idx_type i = 0; i < m2_nr; i++)             \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                                                                        \\\n                    const Complex m2_val = m2.elem (i, 0);              \\\n                                                                        \\\n                    if (! (m1_val OP m2_val))                           \\\n                      r.elem (i, j) = false;                            \\\n                  }                                                     \\\n              }                                                         \\\n            r.maybe_compress (true);                                    \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            octave_idx_type nz = m1.nnz () * m2_nr + m2.nnz () * m1_nc; \\\n            r = SparseBoolMatrix (m2_nr, m1_nc, nz);                    \\\n                                                                        \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              {                                                         \\\n                const Complex m1_val = m1.elem (0, j);                  \\\n                                                                        \\\n                for (octave_idx_type i = 0; i < m2_nr; i++)             \\\n                  {                                                     \\\n                    octave_quit ();                                     \\\n                                                                        \\\n                    const Complex m2_val = m2.elem (i, 0);              \\\n                                                                        \\\n                    if (m1_val OP m2_val)                               \\\n                      r.elem (i, j) = true;                             \\\n                  }                                                     \\\n              }                                                         \\\n            r.maybe_compress (false);                                   \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nc == 1 && m2_nr == 1)                                  \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMSM_CMP_OPS(M1, M2)             \\\n  SPARSE_SMSM_CMP_OP (mx_el_lt, <,  M1, M2)     \\\n  SPARSE_SMSM_CMP_OP (mx_el_le, <=, M1, M2)     \\\n  SPARSE_SMSM_CMP_OP (mx_el_ge, >=, M1, M2)     \\\n  SPARSE_SMSM_CMP_OP (mx_el_gt, >,  M1, M2)     \\\n  SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, M2)     \\\n  SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, M2)\n\n#define SPARSE_SMSM_EQNE_OPS(M1, M2)            \\\n  SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, M2)     \\\n  SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, M2)\n\n#define SPARSE_SMSM_BOOL_AND_OP(M1, M2)                                        \\\n  extern SparseBoolMatrix mx_el_and (const M1&, const M2::element_type&);      \\\n  extern SparseBoolMatrix mx_el_and (const M1::element_type&, const M2&);      \\\n  SparseBoolMatrix                                                             \\\n  mx_el_and (const M1& m1, const M2& m2)                                       \\\n  {                                                                            \\\n    SparseBoolMatrix r;                                                        \\\n                                                                               \\\n    octave_idx_type m1_nr = m1.rows ();                                        \\\n    octave_idx_type m1_nc = m1.cols ();                                        \\\n                                                                               \\\n    octave_idx_type m2_nr = m2.rows ();                                        \\\n    octave_idx_type m2_nc = m2.cols ();                                        \\\n                                                                               \\\n    M1::element_type lhs_zero = M1::element_type ();                           \\\n    M2::element_type rhs_zero = M2::element_type ();                           \\\n                                                                               \\\n    if (m1_nr == 1 && m1_nc == 1)                                              \\\n      return mx_el_and (m1.elem (0,0), m2);                                    \\\n    else if (m2_nr == 1 && m2_nc == 1)                                         \\\n      return mx_el_and (m1, m2.elem (0,0));                                    \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                         \\\n      {                                                                        \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                        \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                           \\\n        else                                                                   \\\n          octave::err_nonconformant (\"mx_el_and\", m1_nr, m1_nc, m2_nr, m2_nc); \\\n      }                                                                        \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                         \\\n      {                                                                        \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                        \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                           \\\n        else                                                                   \\\n          octave::err_nonconformant (\"mx_el_and\", m1_nr, m1_nc, m2_nr, m2_nc); \\\n      }                                                                        \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                         \\\n      {                                                                        \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                        \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                           \\\n        else                                                                   \\\n          octave::err_nonconformant (\"mx_el_and\", m1_nr, m1_nc, m2_nr, m2_nc); \\\n      }                                                                        \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                         \\\n      {                                                                        \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                        \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                           \\\n        else                                                                   \\\n          octave::err_nonconformant (\"mx_el_and\", m1_nr, m1_nc, m2_nr, m2_nc); \\\n      }                                                                        \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                                 \\\n      {                                                                        \\\n        r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ());            \\\n        r.cidx (0) = static_cast<octave_idx_type> (0);                         \\\n        octave_idx_type nel = 0;                                               \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                            \\\n          {                                                                    \\\n            octave_idx_type i1 = m1.cidx (j);                                  \\\n            octave_idx_type e1 = m1.cidx (j+1);                                \\\n            octave_idx_type i2 = m2.cidx (j);                                  \\\n            octave_idx_type e2 = m2.cidx (j+1);                                \\\n            while (i1 < e1 || i2 < e2)                                         \\\n              {                                                                \\\n                octave_quit ();                                                \\\n                                                                               \\\n                if (i1 == e1 ||                                                \\\n                    (i2 < e2 && m1.ridx (i1) > m2.ridx (i2)))                  \\\n                  i2++;                                                        \\\n                else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))              \\\n                  i1++;                                                        \\\n                else                                                           \\\n                  {                                                            \\\n                    if ((m1.data (i1) != lhs_zero) &&                          \\\n                        (m2.data (i2) != rhs_zero))                            \\\n                      {                                                        \\\n                        r.ridx (nel) = m1.ridx (i1);                           \\\n                        r.data (nel++) = true;                                 \\\n                      }                                                        \\\n                    i1++;                                                      \\\n                    i2++;                                                      \\\n                  }                                                            \\\n              }                                                                \\\n            r.cidx (j + 1) = nel;                                              \\\n          }                                                                    \\\n        r.maybe_compress (false);                                              \\\n      }                                                                        \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))                     \\\n      {                                                                        \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);                \\\n        octave_idx_type rnnz = (m1_nc < m2_nc ?                                \\\n                                m1.nnz () * m2_nc + m2.nnz () :                \\\n                                m1.nnz () + m1_nc * m2.nnz ());                \\\n        r = SparseBoolMatrix (m1_nr, r_nc, rnnz);                              \\\n                                                                               \\\n        r.cidx (0) = static_cast<octave_idx_type> (0);                         \\\n        octave_idx_type nel = 0;                                               \\\n        for (octave_idx_type j = 0; j < r_nc; j++)                             \\\n          {                                                                    \\\n            octave_idx_type i1;                                                \\\n            octave_idx_type e1;                                                \\\n            octave_idx_type i2;                                                \\\n            octave_idx_type e2;                                                \\\n            if (m1_nc == 1)                                                    \\\n              {                                                                \\\n                i1 = m1.cidx(0);                                               \\\n                e1 = m1.cidx(1);                                               \\\n                i2 = m2.cidx (j);                                              \\\n                e2 = m2.cidx (j+1);                                            \\\n              }                                                                \\\n            else                                                               \\\n              {                                                                \\\n                i1 = m1.cidx(j);                                               \\\n                e1 = m1.cidx(j+1);                                             \\\n                i2 = m2.cidx (0);                                              \\\n                e2 = m2.cidx (1);                                              \\\n              }                                                                \\\n            while (i1 < e1 || i2 < e2)                                         \\\n              {                                                                \\\n                octave_quit ();                                                \\\n                                                                               \\\n                if (i1 == e1 ||                                                \\\n                    (i2 < e2 && m1.ridx (i1) > m2.ridx (i2)))                  \\\n                  i2++;                                                        \\\n                else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))              \\\n                  i1++;                                                        \\\n                else                                                           \\\n                  {                                                            \\\n                    if ((m1.data (i1) != lhs_zero) &&                          \\\n                        (m2.data (i2) != rhs_zero))                            \\\n                      {                                                        \\\n                        r.ridx (nel) = m1.ridx (i1);                           \\\n                        r.data (nel++) = true;                                 \\\n                      }                                                        \\\n                    i1++;                                                      \\\n                    i2++;                                                      \\\n                  }                                                            \\\n              }                                                                \\\n            r.cidx (j + 1) = nel;                                              \\\n          }                                                                    \\\n        r.maybe_compress (false);                                              \\\n      }                                                                        \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))                     \\\n      r = mx_el_and (m1.transpose (), m2.transpose ()).transpose ();           \\\n    else if (m1_nr == 1 && m2_nc == 1)                                         \\\n      {                                                                        \\\n        /* Count num of nonzero elements */                                    \\\n        octave_idx_type nel = 0;                                               \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                            \\\n          for (octave_idx_type i = 0; i < m2_nr; i++)                          \\\n            if ((m1.elem (0, j) != lhs_zero) &&                                \\\n                (m2.elem (i, 0) != rhs_zero))                                  \\\n              nel++;                                                           \\\n                                                                               \\\n        r = SparseBoolMatrix (m2_nr, m1_nc, nel);                              \\\n                                                                               \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                            \\\n          {                                                                    \\\n            const bool m1_val = m1.elem (0, j) != lhs_zero;                    \\\n                                                                               \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                        \\\n              {                                                                \\\n                octave_quit ();                                                \\\n                                                                               \\\n                const bool m2_val = m2.elem (i, 0) != rhs_zero;                \\\n                                                                               \\\n                if (m1_val && m2_val)                                          \\\n                  r.elem (i, j) = true;                                        \\\n              }                                                                \\\n          }                                                                    \\\n        r.maybe_compress (true);                                               \\\n      }                                                                        \\\n    else if (m1_nc == 1 && m2_nr == 1)                                         \\\n      r = mx_el_and (m1.transpose (), m2.transpose ()).transpose ();           \\\n    else                                                                       \\\n      octave::err_nonconformant (\"mx_el_and\", m1_nr, m1_nc, m2_nr, m2_nc);     \\\n                                                                               \\\n    return r;                                                                  \\\n  }\n\n#define SPARSE_SMSM_BOOL_OR_OP(M1, M2)                                         \\\n  extern SparseBoolMatrix mx_el_or (const M1&, const M2&);                     \\\n  SparseBoolMatrix                                                             \\\n  mx_el_or (const M1& m1, const M2& m2)                                        \\\n  {                                                                            \\\n    SparseBoolMatrix r;                                                        \\\n                                                                               \\\n    octave_idx_type m1_nr = m1.rows ();                                        \\\n    octave_idx_type m1_nc = m1.cols ();                                        \\\n                                                                               \\\n    octave_idx_type m2_nr = m2.rows ();                                        \\\n    octave_idx_type m2_nc = m2.cols ();                                        \\\n                                                                               \\\n    M1::element_type lhs_zero = M1::element_type ();                           \\\n    M2::element_type rhs_zero = M2::element_type ();                           \\\n                                                                               \\\n    if (m1_nr == 1 && m1_nc == 1)                                              \\\n      {                                                                        \\\n        if (m2_nr > 0 && m2_nc > 0)                                            \\\n          {                                                                    \\\n            if (m1.elem(0, 0) != rhs_zero)                                     \\\n              r = SparseBoolMatrix (m2_nr, m2_nc, true);                       \\\n            else                                                               \\\n              {                                                                \\\n                r = SparseBoolMatrix (m2_nr, m2_nc, m2.nnz ());                \\\n                                                                               \\\n                for (octave_idx_type j = 0; j < m2_nc; j++)                    \\\n                  for (octave_idx_type i = 0; i < m2_nr; i++)                  \\\n                    if (m2.elem (i, j) != lhs_zero)                            \\\n                      r.elem (i, j) = true;                                    \\\n              }                                                                \\\n          }                                                                    \\\n        else                                                                   \\\n          r = SparseBoolMatrix (m2_nr, m2_nc);                                 \\\n        return r;                                                              \\\n      }                                                                        \\\n    else if (m2_nr == 1 && m2_nc == 1)                                         \\\n      {                                                                        \\\n        if (m1_nr > 0 && m1_nc > 0)                                            \\\n          {                                                                    \\\n            if (m2.elem(0, 0) != rhs_zero)                                     \\\n              r = SparseBoolMatrix (m1_nr, m1_nc, true);                       \\\n            else                                                               \\\n              {                                                                \\\n                r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz ());                \\\n                                                                               \\\n                for (octave_idx_type j = 0; j < m1_nc; j++)                    \\\n                  for (octave_idx_type i = 0; i < m1_nr; i++)                  \\\n                    if (m1.elem (i, j) != lhs_zero)                            \\\n                      r.elem (i, j) = true;                                    \\\n              }                                                                \\\n          }                                                                    \\\n        else                                                                   \\\n          r = SparseBoolMatrix (m1_nr, m1_nc);                                 \\\n        return r;                                                              \\\n      }                                                                        \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                         \\\n      {                                                                        \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                        \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                           \\\n        else                                                                   \\\n          octave::err_nonconformant (\"mx_el_or\", m1_nr, m1_nc, m2_nr, m2_nc);  \\\n      }                                                                        \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                         \\\n      {                                                                        \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                        \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                           \\\n        else                                                                   \\\n          octave::err_nonconformant (\"mx_el_or\", m1_nr, m1_nc, m2_nr, m2_nc);  \\\n      }                                                                        \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                         \\\n      {                                                                        \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                        \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                           \\\n        else                                                                   \\\n          octave::err_nonconformant (\"mx_el_or\", m1_nr, m1_nc, m2_nr, m2_nc);  \\\n      }                                                                        \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                         \\\n      {                                                                        \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                        \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                           \\\n        else                                                                   \\\n          octave::err_nonconformant (\"mx_el_or\", m1_nr, m1_nc, m2_nr, m2_nc);  \\\n      }                                                                        \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                                 \\\n      {                                                                        \\\n        r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ());            \\\n        r.cidx (0) = static_cast<octave_idx_type> (0);                         \\\n        octave_idx_type nel = 0;                                               \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                            \\\n          {                                                                    \\\n            octave_idx_type i1 = m1.cidx (j);                                  \\\n            octave_idx_type e1 = m1.cidx (j+1);                                \\\n            octave_idx_type i2 = m2.cidx (j);                                  \\\n            octave_idx_type e2 = m2.cidx (j+1);                                \\\n            while (i1 < e1 || i2 < e2)                                         \\\n              {                                                                \\\n                octave_quit ();                                                \\\n                                                                               \\\n                if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2)))      \\\n                  {                                                            \\\n                    if (m2.data (i2) != rhs_zero)                              \\\n                      {                                                        \\\n                        r.ridx (nel) = m2.ridx (i2);                           \\\n                        r.data (nel++) = true;                                 \\\n                      }                                                        \\\n                    i2++;                                                      \\\n                  }                                                            \\\n                else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))              \\\n                  {                                                            \\\n                    if (m1.data (i1) != lhs_zero)                              \\\n                      {                                                        \\\n                        r.ridx (nel) = m1.ridx (i1);                           \\\n                        r.data (nel++) = true;                                 \\\n                      }                                                        \\\n                    i1++;                                                      \\\n                  }                                                            \\\n                else                                                           \\\n                  {                                                            \\\n                    if (m1.data (i1) != lhs_zero || m2.data (i2) != rhs_zero)  \\\n                      {                                                        \\\n                        r.ridx (nel) = m1.ridx (i1);                           \\\n                        r.data (nel++) = true;                                 \\\n                      }                                                        \\\n                    i1++;                                                      \\\n                    i2++;                                                      \\\n                  }                                                            \\\n              }                                                                \\\n            r.cidx (j + 1) = nel;                                              \\\n          }                                                                    \\\n        r.maybe_compress (false);                                              \\\n      }                                                                        \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))                     \\\n      {                                                                        \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);                \\\n        octave_idx_type rnnz = (m1_nc < m2_nc ?                                \\\n                                m1.nnz () * m2_nc + m2.nnz () :                \\\n                                m1.nnz () + m1_nc * m2.nnz ());                \\\n        r = SparseBoolMatrix (m1_nr, r_nc, rnnz);                              \\\n                                                                               \\\n        r.cidx (0) = static_cast<octave_idx_type> (0);                         \\\n        octave_idx_type nel = 0;                                               \\\n        for (octave_idx_type j = 0; j < r_nc; j++)                             \\\n          {                                                                    \\\n            octave_idx_type i1;                                                \\\n            octave_idx_type e1;                                                \\\n            octave_idx_type i2;                                                \\\n            octave_idx_type e2;                                                \\\n            if (m1_nc == 1)                                                    \\\n              {                                                                \\\n                i1 = m1.cidx(0);                                               \\\n                e1 = m1.cidx(1);                                               \\\n                i2 = m2.cidx (j);                                              \\\n                e2 = m2.cidx (j+1);                                            \\\n              }                                                                \\\n            else                                                               \\\n              {                                                                \\\n                i1 = m1.cidx(j);                                               \\\n                e1 = m1.cidx(j+1);                                             \\\n                i2 = m2.cidx (0);                                              \\\n                e2 = m2.cidx (1);                                              \\\n              }                                                                \\\n            while (i1 < e1 || i2 < e2)                                         \\\n              {                                                                \\\n                octave_quit ();                                                \\\n                                                                               \\\n                if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2)))      \\\n                  {                                                            \\\n                    if (m2.data (i2) != rhs_zero)                              \\\n                      {                                                        \\\n                        r.ridx (nel) = m2.ridx (i2);                           \\\n                        r.data (nel++) = true;                                 \\\n                      }                                                        \\\n                    i2++;                                                      \\\n                  }                                                            \\\n                else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))              \\\n                  {                                                            \\\n                    if (m1.data (i1) != lhs_zero)                              \\\n                      {                                                        \\\n                        r.ridx (nel) = m1.ridx (i1);                           \\\n                        r.data (nel++) = true;                                 \\\n                      }                                                        \\\n                    i1++;                                                      \\\n                  }                                                            \\\n                else                                                           \\\n                  {                                                            \\\n                    if (m1.data (i1) != lhs_zero || m2.data (i2) != rhs_zero)  \\\n                      {                                                        \\\n                        r.ridx (nel) = m1.ridx (i1);                           \\\n                        r.data (nel++) = true;                                 \\\n                      }                                                        \\\n                    i1++;                                                      \\\n                    i2++;                                                      \\\n                  }                                                            \\\n              }                                                                \\\n            r.cidx (j + 1) = nel;                                              \\\n          }                                                                    \\\n        r.maybe_compress (false);                                              \\\n      }                                                                        \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))                     \\\n      r = mx_el_or (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else if (m1_nr == 1 && m2_nc == 1)                                         \\\n      {                                                                        \\\n        /* Count num of nonzero elements */                                    \\\n        octave_idx_type nel = 0;                                               \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                            \\\n          for (octave_idx_type i = 0; i < m2_nr; i++)                          \\\n            if ((m1.elem (0, j) != lhs_zero) ||                                \\\n                (m2.elem (i, 0) != rhs_zero))                                  \\\n              nel++;                                                           \\\n                                                                               \\\n        r = SparseBoolMatrix (m2_nr, m1_nc, nel);                              \\\n                                                                               \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                            \\\n          {                                                                    \\\n            const bool m1_val = m1.elem (0, j) != lhs_zero;                    \\\n                                                                               \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                        \\\n              {                                                                \\\n                octave_quit ();                                                \\\n                                                                               \\\n                const bool m2_val = m2.elem (i, 0) != rhs_zero;                \\\n                                                                               \\\n                if (m1_val || m2_val)                                          \\\n                  r.elem (i, j) = true;                                        \\\n              }                                                                \\\n          }                                                                    \\\n        r.maybe_compress (false);                                              \\\n      }                                                                        \\\n    else if (m1_nc == 1 && m2_nr == 1)                                         \\\n      r = mx_el_or (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else                                                                       \\\n      octave::err_nonconformant (\"mx_el_or\", m1_nr, m1_nc, m2_nr, m2_nc);      \\\n                                                                               \\\n    return r;                                                                  \\\n  }\n\n#define SPARSE_SMSM_BOOL_OPS(M1, M2)            \\\n  SPARSE_SMSM_BOOL_AND_OP (M1, M2)              \\\n  SPARSE_SMSM_BOOL_OR_OP (M1, M2)\n\n// matrix by sparse matrix operations.\n\n#define SPARSE_MSM_BIN_OP(R, F, OP, M1, M2)                             \\\n  R                                                                     \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    R r;                                                                \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    if (m2_nr == 1 && m2_nc == 1)                                       \\\n      r = R (m1 OP m2.elem (0,0));                                      \\\n    else if ((m1_nr == m2_nr && m1_nc == m2_nc) ||                      \\\n             (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1)) ||          \\\n             (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1)) ||          \\\n             (m1_nr == 1 && m2_nc == 1)                     ||          \\\n             (m1_nc == 1 && m2_nr == 1))                                \\\n      r = R (F (m1, m2.matrix_value ()));                               \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_MSM_BIN_OPS(R1, R2, M1, M2)            \\\n  SPARSE_MSM_BIN_OP (R1, operator +,  +, M1, M2)      \\\n  SPARSE_MSM_BIN_OP (R1, operator -,  -, M1, M2)      \\\n  SPARSE_MSM_BIN_OP (R2, product,     *, M1, M2)      \\\n  SPARSE_MSM_BIN_OP (R1, quotient,    /, M1, M2)\n\n#define SPARSE_MSM_CMP_OP(F, OP, M1, M2)                                \\\n  SparseBoolMatrix                                                      \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    SparseBoolMatrix r;                                                 \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    if (m2_nr == 1 && m2_nc == 1)                                       \\\n      r = SparseBoolMatrix (F (m1, m2.elem (0,0)));                     \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                  \\\n      {                                                                 \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                 \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                  \\\n      {                                                                 \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                  \\\n      {                                                                 \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                 \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                  \\\n      {                                                                 \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \\\n      {                                                                 \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m1_nr; i++)                   \\\n            if (m1.elem (i, j) OP m2.elem (i, j))                       \\\n              nel++;                                                    \\\n                                                                        \\\n        r = SparseBoolMatrix (m1_nr, m1_nc, nel);                       \\\n                                                                        \\\n        octave_idx_type ii = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m1_nr; i++)                 \\\n              {                                                         \\\n                bool el = m1.elem (i, j) OP m2.elem (i, j);             \\\n                if (el)                                                 \\\n                  {                                                     \\\n                    r.data (ii) = el;                                   \\\n                    r.ridx (ii++) = i;                                  \\\n                  }                                                     \\\n              }                                                         \\\n            r.cidx (j+1) = ii;                                          \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))              \\\n      {                                                                 \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);         \\\n                                                                        \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                if (m1.elem (i, 0) OP m2.elem (i, j))                   \\\n                  nel++;                                                \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                if (m1.elem (i, j) OP m2.elem (i, 0))                   \\\n                  nel++;                                                \\\n          }                                                             \\\n                                                                        \\\n        r = SparseBoolMatrix (m1_nr, r_nc, nel);                        \\\n                                                                        \\\n        octave_idx_type ii = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = 0; i < m1_nr; i++)             \\\n                  {                                                     \\\n                    bool el = m1.elem (i, 0) OP m2.elem (i, j);         \\\n                    if (el)                                             \\\n                      {                                                 \\\n                        r.data (ii) = el;                               \\\n                        r.ridx (ii++) = i;                              \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j+1) = ii;                                      \\\n              }                                                         \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = 0; i < m1_nr; i++)             \\\n                  {                                                     \\\n                    bool el = m1.elem (i, j) OP m2.elem (i, 0);         \\\n                    if (el)                                             \\\n                      {                                                 \\\n                        r.data (ii) = el;                               \\\n                        r.ridx (ii++) = i;                              \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j+1) = ii;                                      \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))              \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else if (m1_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m2_nr; i++)                   \\\n            if (m1.elem (0, j) OP m2.elem (i, 0))                       \\\n              nel++;                                                    \\\n                                                                        \\\n        r = SparseBoolMatrix (m2_nr, m1_nc, nel);                       \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            const Complex m1_val = m1.elem (0, j);                      \\\n                                                                        \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                 \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                                                                        \\\n                const Complex m2_val = m2.elem (i, 0);                  \\\n                                                                        \\\n                if (m1_val OP m2_val)                                   \\\n                  r.elem (i, j) = true;                                 \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    else if (m1_nc == 1 && m2_nr == 1)                                  \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_MSM_CMP_OPS(M1, M2)              \\\n  SPARSE_MSM_CMP_OP (mx_el_lt, <,  M1, M2)      \\\n  SPARSE_MSM_CMP_OP (mx_el_le, <=, M1, M2)      \\\n  SPARSE_MSM_CMP_OP (mx_el_ge, >=, M1, M2)      \\\n  SPARSE_MSM_CMP_OP (mx_el_gt, >,  M1, M2)      \\\n  SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, M2)      \\\n  SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, M2)\n\n#define SPARSE_MSM_EQNE_OPS(M1, M2)             \\\n  SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, M2)      \\\n  SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, M2)\n\n#define SPARSE_MSM_BOOL_AND_OP(F, OP, M1, M2)                           \\\n  SparseBoolMatrix                                                      \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    SparseBoolMatrix r;                                                 \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    M1::element_type lhs_zero = M1::element_type ();                    \\\n    M2::element_type rhs_zero = M2::element_type ();                    \\\n                                                                        \\\n    if (m2_nr == 1 && m2_nc == 1)                                       \\\n      r = SparseBoolMatrix (F (m1, m2.elem (0,0)));                     \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                  \\\n      {                                                                 \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                 \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                  \\\n      {                                                                 \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                  \\\n      {                                                                 \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                 \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                  \\\n      {                                                                 \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \\\n      {                                                                 \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m1_nr; i++)                   \\\n            if ((m1.elem (i, j) != lhs_zero) OP                         \\\n                (m2.elem (i, j) != rhs_zero))                           \\\n              nel++;                                                    \\\n                                                                        \\\n        r = SparseBoolMatrix (m1_nr, m1_nc, nel);                       \\\n                                                                        \\\n        octave_idx_type ii = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m1_nr; i++)                 \\\n              {                                                         \\\n                bool el = (m1.elem (i, j) != lhs_zero) OP               \\\n                          (m2.elem (i, j) != rhs_zero);                 \\\n                if (el)                                                 \\\n                  {                                                     \\\n                    r.data (ii) = el;                                   \\\n                    r.ridx (ii++) = i;                                  \\\n                  }                                                     \\\n              }                                                         \\\n            r.cidx (j+1) = ii;                                          \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))              \\\n      {                                                                 \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);         \\\n                                                                        \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                if ((m1.elem (i, 0) != lhs_zero) OP                     \\\n                    (m2.elem (i, j) != rhs_zero))                       \\\n                  nel++;                                                \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                if ((m1.elem (i, j) != lhs_zero) OP                     \\\n                    (m2.elem (i, 0) != rhs_zero))                       \\\n                  nel++;                                                \\\n          }                                                             \\\n                                                                        \\\n        r = SparseBoolMatrix (m1_nr, r_nc, nel);                        \\\n                                                                        \\\n        octave_idx_type ii = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = 0; i < m1_nr; i++)             \\\n                  {                                                     \\\n                    bool el = (m1.elem (i, 0) != lhs_zero) OP           \\\n                              (m2.elem (i, j) != rhs_zero);             \\\n                    if (el)                                             \\\n                      {                                                 \\\n                        r.data (ii) = el;                               \\\n                        r.ridx (ii++) = i;                              \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j+1) = ii;                                      \\\n              }                                                         \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = 0; i < m1_nr; i++)             \\\n                  {                                                     \\\n                    bool el = (m1.elem (i, j) != lhs_zero) OP           \\\n                              (m2.elem (i, 0) != rhs_zero);             \\\n                    if (el)                                             \\\n                      {                                                 \\\n                        r.data (ii) = el;                               \\\n                        r.ridx (ii++) = i;                              \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j+1) = ii;                                      \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))              \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else if (m1_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m2_nr; i++)                   \\\n            if ((m1.elem (0, j) != lhs_zero) OP                         \\\n                (m2.elem (i, 0) != rhs_zero))                           \\\n              nel++;                                                    \\\n                                                                        \\\n        r = SparseBoolMatrix (m2_nr, m1_nc, nel);                       \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            const bool m1_val = m1.elem (0, j) != lhs_zero;             \\\n                                                                        \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                 \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                                                                        \\\n                const bool m2_val = m2.elem (i, 0) != lhs_zero;         \\\n                                                                        \\\n                if (m1_val OP m2_val)                                   \\\n                  r.elem (i, j) = true;                                 \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    else if (m1_nc == 1 && m2_nr == 1)                                  \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_MSM_BOOL_OR_OP(F, OP, M1, M2)                            \\\n  boolMatrix                                                            \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    boolMatrix r;                                                       \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    M1::element_type lhs_zero = M1::element_type ();                    \\\n    M2::element_type rhs_zero = M2::element_type ();                    \\\n                                                                        \\\n    if (m2_nr == 1 && m2_nc == 1)                                       \\\n      r = boolMatrix (F (m1, m2.elem (0,0)));                           \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                  \\\n      {                                                                 \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                 \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                  \\\n      {                                                                 \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                  \\\n      {                                                                 \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                 \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                  \\\n      {                                                                 \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \\\n      {                                                                 \\\n        r = boolMatrix (m1_nr, m1_nc, false);                           \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m1_nr; i++)                   \\\n            {                                                           \\\n              bool el = (m1.elem (i, j) != lhs_zero) OP                 \\\n                        (m2.elem (i, j) != rhs_zero);                   \\\n              if (el)                                                   \\\n                r.elem (i, j) = el;                                     \\\n            }                                                           \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))              \\\n      {                                                                 \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);         \\\n                                                                        \\\n        r = boolMatrix (m1_nr, r_nc, false);                            \\\n                                                                        \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                {                                                       \\\n                  bool el = (m1.elem (i, 0) != lhs_zero) OP             \\\n                            (m2.elem (i, j) != rhs_zero);               \\\n                  if (el)                                               \\\n                    r.elem (i, j) = el;                                 \\\n                }                                                       \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                {                                                       \\\n                  bool el = (m1.elem (i, j) != lhs_zero) OP             \\\n                            (m2.elem (i, 0) != rhs_zero);               \\\n                  if (el)                                               \\\n                    r.elem (i, j) = el;                                 \\\n                }                                                       \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))              \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else if (m1_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        r = boolMatrix (m2_nr, m1_nc, false);                           \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            const bool m1_val = m1.elem (0, j) != lhs_zero;             \\\n                                                                        \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                 \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                                                                        \\\n                const bool m2_val = m2.elem (i, 0) != lhs_zero;         \\\n                                                                        \\\n                if (m1_val OP m2_val)                                   \\\n                  r.elem (i, j) = true;                                 \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nc == 1 && m2_nr == 1)                                  \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_MSM_BOOL_OPS(M1, M2)                 \\\n  SPARSE_MSM_BOOL_AND_OP (mx_el_and, &&, M1, M2)    \\\n  SPARSE_MSM_BOOL_OR_OP  (mx_el_or,  ||, M1, M2)\n\n// sparse matrix by matrix operations.\n\n#define SPARSE_SMM_BIN_OP(R, F, OP, M1, M2)                             \\\n  R                                                                     \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    R r;                                                                \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    if (m1_nr == 1 && m1_nc == 1)                                       \\\n      r = R (m1.elem (0,0) OP m2);                                      \\\n    else if ((m1_nr == m2_nr && m1_nc == m2_nc) ||                      \\\n             (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1)) ||          \\\n             (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1)) ||          \\\n             (m1_nr == 1 && m2_nc == 1)                     ||          \\\n             (m1_nc == 1 && m2_nr == 1))                                \\\n      r = R (F (m1.matrix_value (), m2));                               \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMM_BIN_OPS(R1, R2, M1, M2)            \\\n  SPARSE_SMM_BIN_OP (R1, operator +,  +, M1, M2)      \\\n  SPARSE_SMM_BIN_OP (R1, operator -,  -, M1, M2)      \\\n  SPARSE_SMM_BIN_OP (R2, product,     *, M1, M2)      \\\n  SPARSE_SMM_BIN_OP (R2, quotient,    /, M1, M2)\n\n#define SPARSE_SMM_CMP_OP(F, OP, M1, M2)                                \\\n  SparseBoolMatrix                                                      \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    SparseBoolMatrix r;                                                 \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    if (m1_nr == 1 && m1_nc == 1)                                       \\\n      r = SparseBoolMatrix (F (m1.elem (0,0), m2));                     \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                  \\\n      {                                                                 \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                 \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                  \\\n      {                                                                 \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                  \\\n      {                                                                 \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                 \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                  \\\n      {                                                                 \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \\\n      {                                                                 \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m1_nr; i++)                   \\\n            if (m1.elem (i, j) OP m2.elem (i, j))                       \\\n              nel++;                                                    \\\n                                                                        \\\n        r = SparseBoolMatrix (m1_nr, m1_nc, nel);                       \\\n                                                                        \\\n        octave_idx_type ii = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m1_nr; i++)                 \\\n              {                                                         \\\n                bool el = m1.elem (i, j) OP m2.elem (i, j);             \\\n                if (el)                                                 \\\n                  {                                                     \\\n                    r.data (ii) = el;                                   \\\n                    r.ridx (ii++) = i;                                  \\\n                  }                                                     \\\n              }                                                         \\\n            r.cidx (j+1) = ii;                                          \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))              \\\n      {                                                                 \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);         \\\n                                                                        \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                if (m1.elem (i, 0) OP m2.elem (i, j))                   \\\n                  nel++;                                                \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                if (m1.elem (i, j) OP m2.elem (i, 0))                   \\\n                  nel++;                                                \\\n          }                                                             \\\n                                                                        \\\n        r = SparseBoolMatrix (m1_nr, r_nc, nel);                        \\\n                                                                        \\\n        octave_idx_type ii = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = 0; i < m1_nr; i++)             \\\n                  {                                                     \\\n                    bool el = m1.elem (i, 0) OP m2.elem (i, j);         \\\n                    if (el)                                             \\\n                      {                                                 \\\n                        r.data (ii) = el;                               \\\n                        r.ridx (ii++) = i;                              \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j+1) = ii;                                      \\\n              }                                                         \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = 0; i < m1_nr; i++)             \\\n                  {                                                     \\\n                    bool el = m1.elem (i, j) OP m2.elem (i, 0);         \\\n                    if (el)                                             \\\n                      {                                                 \\\n                        r.data (ii) = el;                               \\\n                        r.ridx (ii++) = i;                              \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j+1) = ii;                                      \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))              \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else if (m1_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m2_nr; i++)                   \\\n            if (m1.elem (0, j) OP m2.elem (i, 0))                       \\\n              nel++;                                                    \\\n                                                                        \\\n        r = SparseBoolMatrix (m2_nr, m1_nc, nel);                       \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            const Complex m1_val = m1.elem (0, j);                      \\\n                                                                        \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                 \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                                                                        \\\n                const Complex m2_val = m2.elem (i, 0);                  \\\n                                                                        \\\n                if (m1_val OP m2_val)                                   \\\n                  r.elem (i, j) = true;                                 \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    else if (m1_nc == 1 && m2_nr == 1)                                  \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMM_CMP_OPS(M1, M2)              \\\n  SPARSE_SMM_CMP_OP (mx_el_lt, <,  M1, M2)      \\\n  SPARSE_SMM_CMP_OP (mx_el_le, <=, M1, M2)      \\\n  SPARSE_SMM_CMP_OP (mx_el_ge, >=, M1, M2)      \\\n  SPARSE_SMM_CMP_OP (mx_el_gt, >,  M1, M2)      \\\n  SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, M2)      \\\n  SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, M2)\n\n#define SPARSE_SMM_EQNE_OPS(M1, M2)             \\\n  SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, M2)      \\\n  SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, M2)\n\n#define SPARSE_SMM_BOOL_AND_OP(F, OP, M1, M2)                           \\\n  SparseBoolMatrix                                                      \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    SparseBoolMatrix r;                                                 \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    M1::element_type lhs_zero = M1::element_type ();                    \\\n    M2::element_type rhs_zero = M2::element_type ();                    \\\n                                                                        \\\n    if (m1_nr == 1 && m1_nc == 1)                                       \\\n      r = SparseBoolMatrix (F (m1.elem (0,0), m2));                     \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                  \\\n      {                                                                 \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                 \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                  \\\n      {                                                                 \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                  \\\n      {                                                                 \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                 \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                  \\\n      {                                                                 \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \\\n      {                                                                 \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m1_nr; i++)                   \\\n            if ((m1.elem (i, j) != lhs_zero) OP                         \\\n                (m2.elem (i, j) != rhs_zero))                           \\\n              nel++;                                                    \\\n                                                                        \\\n        r = SparseBoolMatrix (m1_nr, m1_nc, nel);                       \\\n                                                                        \\\n        octave_idx_type ii = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m1_nr; i++)                 \\\n              {                                                         \\\n                bool el = (m1.elem (i, j) != lhs_zero) OP               \\\n                          (m2.elem (i, j) != rhs_zero);                 \\\n                if (el)                                                 \\\n                  {                                                     \\\n                    r.data (ii) = el;                                   \\\n                    r.ridx (ii++) = i;                                  \\\n                  }                                                     \\\n              }                                                         \\\n            r.cidx (j+1) = ii;                                          \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))              \\\n      {                                                                 \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);         \\\n                                                                        \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                if ((m1.elem (i, 0) != lhs_zero) OP                     \\\n                    (m2.elem (i, j) != rhs_zero))                       \\\n                  nel++;                                                \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                if ((m1.elem (i, j) != lhs_zero) OP                     \\\n                    (m2.elem (i, 0) != rhs_zero))                       \\\n                  nel++;                                                \\\n          }                                                             \\\n                                                                        \\\n        r = SparseBoolMatrix (m1_nr, r_nc, nel);                        \\\n                                                                        \\\n        octave_idx_type ii = 0;                                         \\\n        r.cidx (0) = 0;                                                 \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = 0; i < m1_nr; i++)             \\\n                  {                                                     \\\n                    bool el = (m1.elem (i, 0) != lhs_zero) OP           \\\n                              (m2.elem (i, j) != rhs_zero);             \\\n                    if (el)                                             \\\n                      {                                                 \\\n                        r.data (ii) = el;                               \\\n                        r.ridx (ii++) = i;                              \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j+1) = ii;                                      \\\n              }                                                         \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              {                                                         \\\n                for (octave_idx_type i = 0; i < m1_nr; i++)             \\\n                  {                                                     \\\n                    bool el = (m1.elem (i, j) != lhs_zero) OP           \\\n                              (m2.elem (i, 0) != rhs_zero);             \\\n                    if (el)                                             \\\n                      {                                                 \\\n                        r.data (ii) = el;                               \\\n                        r.ridx (ii++) = i;                              \\\n                      }                                                 \\\n                  }                                                     \\\n                r.cidx (j+1) = ii;                                      \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))              \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else if (m1_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        /* Count num of nonzero elements */                             \\\n        octave_idx_type nel = 0;                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m2_nr; i++)                   \\\n            if ((m1.elem (0, j) != lhs_zero) OP                         \\\n                (m2.elem (i, 0) != rhs_zero))                           \\\n              nel++;                                                    \\\n                                                                        \\\n        r = SparseBoolMatrix (m2_nr, m1_nc, nel);                       \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            const bool m1_val = m1.elem (0, j) != lhs_zero;             \\\n                                                                        \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                 \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                                                                        \\\n                const bool m2_val = m2.elem (i, 0) != lhs_zero;         \\\n                                                                        \\\n                if (m1_val OP m2_val)                                   \\\n                  r.elem (i, j) = true;                                 \\\n              }                                                         \\\n          }                                                             \\\n        r.maybe_compress (false);                                       \\\n      }                                                                 \\\n    else if (m1_nc == 1 && m2_nr == 1)                                  \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMM_BOOL_OR_OP(F, OP, M1, M2)                            \\\n  boolMatrix                                                            \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    boolMatrix r;                                                       \\\n                                                                        \\\n    octave_idx_type m1_nr = m1.rows ();                                 \\\n    octave_idx_type m1_nc = m1.cols ();                                 \\\n                                                                        \\\n    octave_idx_type m2_nr = m2.rows ();                                 \\\n    octave_idx_type m2_nc = m2.cols ();                                 \\\n                                                                        \\\n    M1::element_type lhs_zero = M1::element_type ();                    \\\n    M2::element_type rhs_zero = M2::element_type ();                    \\\n                                                                        \\\n    if (m1_nr == 1 && m1_nc == 1)                                       \\\n      r = boolMatrix (F (m1.elem (0,0), m2));                           \\\n    else if (m1_nr == 0 && (m2_nr == 0 || m2_nr == 1))                  \\\n      {                                                                 \\\n        if (m1_nc == 1 || m2_nc == 1 || m1_nc == m2_nc)                 \\\n          r.resize (m1_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nc == 0 && (m2_nc == 0 || m2_nc == 1))                  \\\n      {                                                                 \\\n        if (m1_nr == 1 || m2_nr == 1 || m1_nr == m2_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m1_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nr == 0 && (m1_nr == 0 || m1_nr == 1))                  \\\n      {                                                                 \\\n        if (m2_nc == 1 || m1_nc == 1 || m2_nc == m1_nc)                 \\\n          r.resize (m2_nr, std::max (m1_nc, m2_nc));                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m2_nc == 0 && (m1_nc == 0 || m1_nc == 1))                  \\\n      {                                                                 \\\n        if (m2_nr == 1 || m1_nr == 1 || m2_nr == m1_nr)                 \\\n          r.resize (std::max (m1_nr, m2_nr), m2_nc);                    \\\n        else                                                            \\\n          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);   \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \\\n      {                                                                 \\\n        r = boolMatrix (m1_nr, m1_nc, false);                           \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          for (octave_idx_type i = 0; i < m1_nr; i++)                   \\\n            {                                                           \\\n              bool el = (m1.elem (i, j) != lhs_zero) OP                 \\\n                        (m2.elem (i, j) != rhs_zero);                   \\\n              if (el)                                                   \\\n                r.elem (i, j) = el;                                     \\\n            }                                                           \\\n      }                                                                 \\\n    else if (m1_nr == m2_nr && (m1_nc == 1 || m2_nc == 1))              \\\n      {                                                                 \\\n        octave_idx_type r_nc = (m1_nc < m2_nc ? m2_nc : m1_nc);         \\\n                                                                        \\\n        r = boolMatrix (m1_nr, r_nc, false);                            \\\n                                                                        \\\n        if (m1_nc == 1)                                                 \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m2_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                {                                                       \\\n                  bool el = (m1.elem (i, 0) != lhs_zero) OP             \\\n                            (m2.elem (i, j) != rhs_zero);               \\\n                  if (el)                                               \\\n                    r.elem (i, j) = el;                                 \\\n                }                                                       \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type j = 0; j < m1_nc; j++)                 \\\n              for (octave_idx_type i = 0; i < m1_nr; i++)               \\\n                {                                                       \\\n                  bool el = (m1.elem (i, j) != lhs_zero) OP             \\\n                            (m2.elem (i, 0) != rhs_zero);               \\\n                  if (el)                                               \\\n                    r.elem (i, j) = el;                                 \\\n                }                                                       \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nc == m2_nc && (m1_nr == 1 || m2_nr == 1))              \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else if (m1_nr == 1 && m2_nc == 1)                                  \\\n      {                                                                 \\\n        r = boolMatrix (m2_nr, m1_nc, false);                           \\\n                                                                        \\\n        for (octave_idx_type j = 0; j < m1_nc; j++)                     \\\n          {                                                             \\\n            const bool m1_val = m1.elem (0, j) != lhs_zero;             \\\n                                                                        \\\n            for (octave_idx_type i = 0; i < m2_nr; i++)                 \\\n              {                                                         \\\n                octave_quit ();                                         \\\n                                                                        \\\n                const bool m2_val = m2.elem (i, 0) != lhs_zero;         \\\n                                                                        \\\n                if (m1_val OP m2_val)                                   \\\n                  r.elem (i, j) = true;                                 \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    else if (m1_nc == 1 && m2_nr == 1)                                  \\\n      r = F (m1.transpose (), m2.transpose ()).transpose ();            \\\n    else                                                                \\\n      octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);       \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define SPARSE_SMM_BOOL_OPS(M1, M2)                 \\\n  SPARSE_SMM_BOOL_AND_OP (mx_el_and, &&, M1, M2)    \\\n  SPARSE_SMM_BOOL_OR_OP  (mx_el_or,  ||, M1, M2)\n\n// 'cumsum' and 'cumprod' specializations for sparse matrices\n\n#define SPARSE_CUMSUM(RET_TYPE, ELT_TYPE, FCN, NAN_EXPR, EXPR)                \\\n                                                                              \\\n  octave_idx_type nr = rows ();                                               \\\n  octave_idx_type nc = cols ();                                               \\\n                                                                              \\\n  RET_TYPE retval;                                                            \\\n                                                                              \\\n  if (nr > 0 && nc > 0)                                                       \\\n    {                                                                         \\\n      if ((nr == 1 && dim == -1) || dim == 1)                                 \\\n        /* Ugly!! Is there a better way? */                                   \\\n        retval = transpose (). FCN (0, nanflag) .transpose ();                \\\n      else                                                                    \\\n        {                                                                     \\\n          octave_idx_type nel = 0;                                            \\\n          for (octave_idx_type i = 0; i < nc; i++)                            \\\n            {                                                                 \\\n              ELT_TYPE t = ELT_TYPE ();                                       \\\n              for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)         \\\n                {                                                             \\\n                  t += data (j);                                              \\\n                  if (t != ELT_TYPE ())                                       \\\n                    {                                                         \\\n                      if (j == cidx (i+1) - 1)                                \\\n                        nel += nr - ridx (j);                                 \\\n                      else                                                    \\\n                        nel += ridx (j+1) - ridx (j);                         \\\n                    }                                                         \\\n                }                                                             \\\n            }                                                                 \\\n          retval = RET_TYPE (nr, nc, nel);                                    \\\n          retval.cidx (0) = 0;                                                \\\n          octave_idx_type ii = 0;                                             \\\n          if (nanflag)                                                        \\\n            {                                                                 \\\n              for (octave_idx_type i = 0; i < nc; i++)                        \\\n                {                                                             \\\n                  ELT_TYPE t = ELT_TYPE ();                                   \\\n                  for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)     \\\n                    {                                                         \\\n                      NAN_EXPR;                                               \\\n                      if (t != ELT_TYPE ())                                   \\\n                        {                                                     \\\n                          if (j == cidx (i+1) - 1)                            \\\n                            {                                                 \\\n                              for (octave_idx_type k = ridx (j); k < nr; k++) \\\n                                {                                             \\\n                                  retval.data (ii) = t;                       \\\n                                  retval.ridx (ii++) = k;                     \\\n                                }                                             \\\n                            }                                                 \\\n                          else                                                \\\n                            {                                                 \\\n                              for (octave_idx_type k = ridx (j);              \\\n                                   k < ridx (j+1); k++)                       \\\n                                {                                             \\\n                                  retval.data (ii) = t;                       \\\n                                  retval.ridx (ii++) = k;                     \\\n                                }                                             \\\n                            }                                                 \\\n                        }                                                     \\\n                    }                                                         \\\n                  retval.cidx (i+1) = ii;                                     \\\n                }                                                             \\\n            }                                                                 \\\n          else                                                                \\\n            {                                                                 \\\n              for (octave_idx_type i = 0; i < nc; i++)                        \\\n                {                                                             \\\n                  ELT_TYPE t = ELT_TYPE ();                                   \\\n                  for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)     \\\n                    {                                                         \\\n                      EXPR;                                                   \\\n                      if (t != ELT_TYPE ())                                   \\\n                        {                                                     \\\n                          if (j == cidx (i+1) - 1)                            \\\n                            {                                                 \\\n                              for (octave_idx_type k = ridx (j); k < nr; k++) \\\n                                {                                             \\\n                                  retval.data (ii) = t;                       \\\n                                  retval.ridx (ii++) = k;                     \\\n                                }                                             \\\n                            }                                                 \\\n                          else                                                \\\n                            {                                                 \\\n                              for (octave_idx_type k = ridx (j);              \\\n                                   k < ridx (j+1); k++)                       \\\n                                {                                             \\\n                                  retval.data (ii) = t;                       \\\n                                  retval.ridx (ii++) = k;                     \\\n                                }                                             \\\n                            }                                                 \\\n                        }                                                     \\\n                    }                                                         \\\n                  retval.cidx (i+1) = ii;                                     \\\n                }                                                             \\\n            }                                                                 \\\n        }                                                                     \\\n    }                                                                         \\\n  else                                                                        \\\n    retval = RET_TYPE (nr, nc);                                               \\\n                                                                              \\\n  return retval\n\n#define SPARSE_CUMPROD(RET_TYPE, ELT_TYPE, FCN)                             \\\n                                                                            \\\n  octave_idx_type nr = rows ();                                             \\\n  octave_idx_type nc = cols ();                                             \\\n                                                                            \\\n  RET_TYPE retval;                                                          \\\n                                                                            \\\n  if (nr > 0 && nc > 0)                                                     \\\n    {                                                                       \\\n      if ((nr == 1 && dim == -1) || dim == 1)                               \\\n        /* Ugly!! Is there a better way? */                                 \\\n        retval = transpose (). FCN (0, nanflag) .transpose ();              \\\n      else                                                                  \\\n        {                                                                   \\\n          octave_idx_type nel = 0;                                          \\\n          for (octave_idx_type i = 0; i < nc; i++)                          \\\n            {                                                               \\\n              octave_idx_type jj = 0;                                       \\\n              for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)       \\\n                {                                                           \\\n                  if (jj == ridx (j))                                       \\\n                    {                                                       \\\n                      nel++;                                                \\\n                      jj++;                                                 \\\n                    }                                                       \\\n                  else                                                      \\\n                    break;                                                  \\\n                }                                                           \\\n            }                                                               \\\n          retval = RET_TYPE (nr, nc, nel);                                  \\\n          retval.cidx (0) = 0;                                              \\\n          octave_idx_type ii = 0;                                           \\\n          if (nanflag)                                                      \\\n            {                                                               \\\n              for (octave_idx_type i = 0; i < nc; i++)                      \\\n                {                                                           \\\n                  ELT_TYPE t = ELT_TYPE (1.);                               \\\n                  octave_idx_type jj = 0;                                   \\\n                  for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)   \\\n                    {                                                       \\\n                      if (jj == ridx (j))                                   \\\n                        {                                                   \\\n                          if (! octave::math::isnan (data (j)))             \\\n                            t *= data (j);                                  \\\n                          retval.data (ii) = t;                             \\\n                          retval.ridx (ii++) = jj++;                        \\\n                        }                                                   \\\n                      else                                                  \\\n                        break;                                              \\\n                    }                                                       \\\n                  retval.cidx (i+1) = ii;                                   \\\n                }                                                           \\\n            }                                                               \\\n          else                                                              \\\n            {                                                               \\\n              for (octave_idx_type i = 0; i < nc; i++)                      \\\n                {                                                           \\\n                  ELT_TYPE t = ELT_TYPE (1.);                               \\\n                  octave_idx_type jj = 0;                                   \\\n                  for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)   \\\n                    {                                                       \\\n                      if (jj == ridx (j))                                   \\\n                        {                                                   \\\n                          t *= data (j);                                    \\\n                          retval.data (ii) = t;                             \\\n                          retval.ridx (ii++) = jj++;                        \\\n                        }                                                   \\\n                      else                                                  \\\n                        break;                                              \\\n                    }                                                       \\\n                  retval.cidx (i+1) = ii;                                   \\\n                }                                                           \\\n            }                                                               \\\n        }                                                                   \\\n    }                                                                       \\\n  else                                                                      \\\n    retval = RET_TYPE (nr, nc);                                             \\\n                                                                            \\\n  return retval\n\n// Reduction operations for sparse matrices ('prod', 'sum', and 'sumsq')\n\n#define SPARSE_SUMSQ_HEADER(RET_TYPE, EXPR)                              \\\n  if (rows () > 0 && cols () > 0 && dim > 1)                             \\\n    {                                                                    \\\n      RET_TYPE r = RET_TYPE (rows (), cols (), nnz ());                  \\\n      r.cidx (0) = static_cast<octave_idx_type> (0);                     \\\n      octave_idx_type nel = 0;                                           \\\n      for (octave_idx_type j = 0; j < cols (); j++)                      \\\n        {                                                                \\\n          for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)        \\\n            if (data (i) != 0.0)                                         \\\n              {                                                          \\\n                r.ridx (nel) = ridx (i);                                 \\\n                EXPR                                                     \\\n              }                                                          \\\n          r.cidx (j + 1) = nel;                                          \\\n        }                                                                \\\n      r.maybe_compress (false);                                          \\\n      return r;                                                          \\\n    }                                                                    \\\n  if (dim > 1)                                                           \\\n    return *this;\n\n#define SPARSE_BASE_REDUCTION_OP(RET_TYPE, EL_TYPE, ROW_EXPR, COL_EXPR,  \\\n                                 INIT_VAL, MT_RESULT)                    \\\n                                                                         \\\n  octave_idx_type nr = rows ();                                          \\\n  octave_idx_type nc = cols ();                                          \\\n                                                                         \\\n  RET_TYPE retval;                                                       \\\n                                                                         \\\n  if (nr > 0 && nc > 0)                                                  \\\n    {                                                                    \\\n      if ((nr == 1 && dim == -1) || dim == 1)                            \\\n        {                                                                \\\n          /* Define j here to allow fancy definition for prod method */  \\\n          octave_idx_type j = 0;                                         \\\n          OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nr);                        \\\n                                                                         \\\n          for (octave_idx_type i = 0; i < nr; i++)                       \\\n            tmp[i] = INIT_VAL;                                           \\\n          for (j = 0; j < nc; j++)                                       \\\n            {                                                            \\\n              for (octave_idx_type i = cidx (j); i < cidx (j + 1); i++)  \\\n                {                                                        \\\n                  ROW_EXPR;                                              \\\n                }                                                        \\\n            }                                                            \\\n          octave_idx_type nel = 0;                                       \\\n          for (octave_idx_type i = 0; i < nr; i++)                       \\\n            if (tmp[i] != EL_TYPE ())                                    \\\n              nel++;                                                     \\\n          retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), nel); \\\n          retval.cidx (0) = 0;                                           \\\n          retval.cidx (1) = nel;                                         \\\n          nel = 0;                                                       \\\n          for (octave_idx_type i = 0; i < nr; i++)                       \\\n            if (tmp[i] != EL_TYPE ())                                    \\\n              {                                                          \\\n                retval.data (nel) = tmp[i];                              \\\n                retval.ridx (nel++) = i;                                 \\\n              }                                                          \\\n        }                                                                \\\n      else                                                               \\\n        {                                                                \\\n          OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nc);                        \\\n                                                                         \\\n          for (octave_idx_type j = 0; j < nc; j++)                       \\\n            {                                                            \\\n              tmp[j] = INIT_VAL;                                         \\\n              for (octave_idx_type i = cidx (j); i < cidx (j + 1); i++)  \\\n                {                                                        \\\n                  COL_EXPR;                                              \\\n                }                                                        \\\n            }                                                            \\\n          octave_idx_type nel = 0;                                       \\\n          for (octave_idx_type i = 0; i < nc; i++)                       \\\n            if (tmp[i] != EL_TYPE ())                                    \\\n              nel++;                                                     \\\n          retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, nel); \\\n          retval.cidx (0) = 0;                                           \\\n          nel = 0;                                                       \\\n          for (octave_idx_type i = 0; i < nc; i++)                       \\\n            if (tmp[i] != EL_TYPE ())                                    \\\n              {                                                          \\\n                retval.data (nel) = tmp[i];                              \\\n                retval.ridx (nel++) = 0;                                 \\\n                retval.cidx (i+1) = retval.cidx (i) + 1;                 \\\n              }                                                          \\\n            else                                                         \\\n              retval.cidx (i+1) = retval.cidx (i);                       \\\n        }                                                                \\\n    }                                                                    \\\n  else if (nc == 0 && nr == 0 && dim == -1)                              \\\n    {                                                                    \\\n      if (MT_RESULT)                                                     \\\n        {                                                                \\\n          retval = RET_TYPE (static_cast<octave_idx_type> (1),           \\\n                             static_cast<octave_idx_type> (1),           \\\n                             static_cast<octave_idx_type> (1));          \\\n          retval.cidx (0) = 0;                                           \\\n          retval.cidx (1) = 1;                                           \\\n          retval.ridx (0) = 0;                                           \\\n          retval.data (0) = MT_RESULT;                                   \\\n        }                                                                \\\n      else                                                               \\\n        retval = RET_TYPE (static_cast<octave_idx_type> (1),             \\\n                           static_cast<octave_idx_type> (1),             \\\n                           static_cast<octave_idx_type> (0));            \\\n    }                                                                    \\\n  else if (nc == 0 && nr == 0 && dim == 0)                               \\\n        retval = RET_TYPE (static_cast<octave_idx_type> (1),             \\\n                           static_cast<octave_idx_type> (0),             \\\n                           static_cast<octave_idx_type> (0));            \\\n  else if (nc == 0 && nr == 0 && dim == 1)                               \\\n        retval = RET_TYPE (static_cast<octave_idx_type> (0),             \\\n                           static_cast<octave_idx_type> (1),             \\\n                           static_cast<octave_idx_type> (0));            \\\n  else if (nr == 0 && (dim == 0 || dim == -1))                           \\\n    {                                                                    \\\n      if (MT_RESULT)                                                     \\\n        {                                                                \\\n          retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, nc);  \\\n          retval.cidx (0) = 0;                                           \\\n          for (octave_idx_type i = 0; i < nc ; i++)                      \\\n            {                                                            \\\n              retval.ridx (i) = 0;                                       \\\n              retval.cidx (i+1) = i+1;                                   \\\n              retval.data (i) = MT_RESULT;                               \\\n            }                                                            \\\n        }                                                                \\\n      else                                                               \\\n        retval = RET_TYPE (static_cast<octave_idx_type> (1), nc,         \\\n                           static_cast<octave_idx_type> (0));            \\\n    }                                                                    \\\n  else if (nc == 0 && (dim == 1 || dim == -1))                           \\\n    {                                                                    \\\n      if (MT_RESULT)                                                     \\\n        {                                                                \\\n          retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), nr);  \\\n          retval.cidx (0) = 0;                                           \\\n          retval.cidx (1) = nr;                                          \\\n          for (octave_idx_type i = 0; i < nr; i++)                       \\\n            {                                                            \\\n              retval.ridx (i) = i;                                       \\\n              retval.data (i) = MT_RESULT;                               \\\n            }                                                            \\\n        }                                                                \\\n      else                                                               \\\n        retval = RET_TYPE (nr, static_cast<octave_idx_type> (1),         \\\n                           static_cast<octave_idx_type> (0));            \\\n    }                                                                    \\\n  else                                                                   \\\n    retval.resize (nr > 0, nc > 0);                                      \\\n                                                                         \\\n  return retval\n\n// High accuracy accumulator for sparse matrices ('xsum')\n\n#define SPARSE_XSUM_REDUCTION_OP(RET_TYPE, EL_TYPE)                      \\\n                                                                         \\\n  octave_idx_type nr = rows ();                                          \\\n  octave_idx_type nc = cols ();                                          \\\n                                                                         \\\n  EL_TYPE inf = std::numeric_limits<EL_TYPE>::infinity ();               \\\n                                                                         \\\n  RET_TYPE retval;                                                       \\\n                                                                         \\\n  if (nr > 0 && nc > 0)                                                  \\\n    {                                                                    \\\n      if ((nr == 1 && dim == -1) || dim == 1)                            \\\n        {                                                                \\\n          OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nr);                        \\\n                                                                         \\\n          for (octave_idx_type i = 0; i < nr; i++)                       \\\n            tmp[i] = 0.0;                                                \\\n          for (octave_idx_type i = 0; i < nr; i++)                       \\\n            {                                                            \\\n              EL_TYPE acc = 0.0;                                         \\\n              EL_TYPE err = 0.0;                                         \\\n              bool posinf = false;                                       \\\n              bool neginf = false;                                       \\\n              for (octave_idx_type j = 0; j < nc; j++)                   \\\n                {                                                        \\\n                  EL_TYPE d = elem (i, j);                               \\\n                  if (d == EL_TYPE ());                                  \\\n                  else if (nanflag && octave::math::isnan (d));          \\\n                  else if (! octave::math::isinf (d))                    \\\n                    twosum_accum (acc, err, d);                          \\\n                  else if (d > 0.0)                                      \\\n                    posinf = true;                                       \\\n                  else                                                   \\\n                    neginf = true;                                       \\\n                }                                                        \\\n              if (posinf && neginf)                                      \\\n                tmp[i] = NAN;                                            \\\n              else if (posinf)                                           \\\n                tmp[i] = acc + err + inf;                                \\\n              else if (neginf)                                           \\\n                tmp[i] = acc + err - inf;                                \\\n              else                                                       \\\n                tmp[i] = acc + err;                                      \\\n            }                                                            \\\n          octave_idx_type nel = 0;                                       \\\n          for (octave_idx_type i = 0; i < nr; i++)                       \\\n            if (tmp[i] != EL_TYPE ())                                    \\\n              nel++;                                                     \\\n          retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), nel); \\\n          retval.cidx (0) = 0;                                           \\\n          retval.cidx (1) = nel;                                         \\\n          nel = 0;                                                       \\\n          for (octave_idx_type i = 0; i < nr; i++)                       \\\n            if (tmp[i] != EL_TYPE ())                                    \\\n              {                                                          \\\n                retval.data (nel) = tmp[i];                              \\\n                retval.ridx (nel++) = i;                                 \\\n              }                                                          \\\n        }                                                                \\\n      else                                                               \\\n        {                                                                \\\n          OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nc);                        \\\n                                                                         \\\n          for (octave_idx_type j = 0; j < nc; j++)                       \\\n            {                                                            \\\n              EL_TYPE acc = 0.0;                                         \\\n              EL_TYPE err = 0.0;                                         \\\n              bool posinf = false;                                       \\\n              bool neginf = false;                                       \\\n              for (octave_idx_type i = 0; i < nr; i++)                   \\\n                {                                                        \\\n                  EL_TYPE d = elem (i, j);                               \\\n                  if (d == EL_TYPE ());                                  \\\n                  else if (nanflag && octave::math::isnan (d));          \\\n                  else if (! octave::math::isinf (d))                    \\\n                    twosum_accum (acc, err, d);                          \\\n                  else if (d > 0.0)                                      \\\n                    posinf = true;                                       \\\n                  else                                                   \\\n                    neginf = true;                                       \\\n                }                                                        \\\n              if (posinf && neginf)                                      \\\n                tmp[j] = NAN;                                            \\\n              else if (posinf)                                           \\\n                tmp[j] = acc + err + inf;                                \\\n              else if (neginf)                                           \\\n                tmp[j] = acc + err - inf;                                \\\n              else                                                       \\\n                tmp[j] = acc + err;                                      \\\n            }                                                            \\\n          octave_idx_type nel = 0;                                       \\\n          for (octave_idx_type i = 0; i < nc; i++)                       \\\n            if (tmp[i] != EL_TYPE ())                                    \\\n              nel++;                                                     \\\n          retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, nel); \\\n          retval.cidx (0) = 0;                                           \\\n          nel = 0;                                                       \\\n          for (octave_idx_type i = 0; i < nc; i++)                       \\\n            if (tmp[i] != EL_TYPE ())                                    \\\n              {                                                          \\\n                retval.data (nel) = tmp[i];                              \\\n                retval.ridx (nel++) = 0;                                 \\\n                retval.cidx (i+1) = retval.cidx (i) + 1;                 \\\n              }                                                          \\\n            else                                                         \\\n              retval.cidx (i+1) = retval.cidx (i);                       \\\n        }                                                                \\\n    }                                                                    \\\n  else if (nc == 0 && nr == 0 && dim == -1)                              \\\n    retval = RET_TYPE (static_cast<octave_idx_type> (1),                 \\\n                       static_cast<octave_idx_type> (1),                 \\\n                       static_cast<octave_idx_type> (0));                \\\n  else if (nc == 0 && nr == 0 && dim == 0)                               \\\n        retval = RET_TYPE (static_cast<octave_idx_type> (1),             \\\n                           static_cast<octave_idx_type> (0),             \\\n                           static_cast<octave_idx_type> (0));            \\\n  else if (nc == 0 && nr == 0 && dim == 1)                               \\\n        retval = RET_TYPE (static_cast<octave_idx_type> (0),             \\\n                           static_cast<octave_idx_type> (1),             \\\n                           static_cast<octave_idx_type> (0));            \\\n  else if (nr == 0 && (dim == 0 || dim == -1))                           \\\n    retval = RET_TYPE (static_cast<octave_idx_type> (1), nc,             \\\n                       static_cast<octave_idx_type> (0));                \\\n  else if (nc == 0 && (dim == 1 || dim == -1))                           \\\n    retval = RET_TYPE (nr, static_cast<octave_idx_type> (1),             \\\n                       static_cast<octave_idx_type> (0));                \\\n  else                                                                   \\\n    retval.resize (nr > 0, nc > 0);                                      \\\n                                                                         \\\n  return retval\n\n// Specializations for 'any' and 'all' functions\n\n#define SPARSE_ANY_ALL_HEADER                                            \\\n  if (rows () > 0 && cols () > 0 && dim > 1)                             \\\n    {                                                                    \\\n      SparseBoolMatrix r = SparseBoolMatrix (rows (), cols (), nnz ());  \\\n      r.cidx (0) = static_cast<octave_idx_type> (0);                     \\\n      octave_idx_type nel = 0;                                           \\\n      for (octave_idx_type j = 0; j < cols (); j++)                      \\\n        {                                                                \\\n          for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)        \\\n            if (data (i) != 0.0)                                         \\\n              {                                                          \\\n                r.ridx (nel) = ridx (i);                                 \\\n                r.data (nel++) = true;                                   \\\n              }                                                          \\\n          r.cidx (j + 1) = nel;                                          \\\n        }                                                                \\\n      r.maybe_compress (false);                                          \\\n      return r;                                                          \\\n    }\n\n// Don't break from this loop if the test succeeds because\n// we are looping over the rows and not the columns in the inner loop.\n#define SPARSE_ANY_ALL_OP_ROW_CODE(TEST_OP, TEST_TRUE_VAL)      \\\n  if (data (i) TEST_OP 0.0)                                     \\\n    tmp[ridx (i)] = TEST_TRUE_VAL;\n\n#define SPARSE_ANY_ALL_OP_COL_CODE(TEST_OP, TEST_TRUE_VAL)      \\\n  if (data (i) TEST_OP 0.0)                                     \\\n    {                                                           \\\n      tmp[j] = TEST_TRUE_VAL;                                   \\\n      break;                                                    \\\n    }\n\n#define SPARSE_ANY_ALL_OP(DIM, INIT_VAL, MT_RESULT, TEST_OP, TEST_TRUE_VAL)      \\\n  SPARSE_BASE_REDUCTION_OP (SparseBoolMatrix, char,                              \\\n                            SPARSE_ANY_ALL_OP_ROW_CODE (TEST_OP, TEST_TRUE_VAL), \\\n                            SPARSE_ANY_ALL_OP_COL_CODE (TEST_OP, TEST_TRUE_VAL), \\\n                            INIT_VAL, MT_RESULT)\n\n#define SPARSE_ALL_OP(DIM)                                                 \\\n  if ((rows () == 1 && dim == -1) || dim == 1)                             \\\n    return transpose (). all (0). transpose ();                            \\\n  else                                                                     \\\n    {                                                                      \\\n      SPARSE_ANY_ALL_OP (DIM, (cidx (j+1) - cidx (j) < nr ? false : true), \\\n                         true, ==, false);                                 \\\n    }\n\n#define SPARSE_ANY_OP(DIM) SPARSE_ANY_ALL_OP (DIM, false, false, !=, true)\n\n#define SPARSE_SPARSE_MUL(RET_TYPE, RET_EL_TYPE, EL_TYPE)               \\\n  octave_idx_type nr = m.rows ();                                       \\\n  octave_idx_type nc = m.cols ();                                       \\\n                                                                        \\\n  octave_idx_type a_nr = a.rows ();                                     \\\n  octave_idx_type a_nc = a.cols ();                                     \\\n                                                                        \\\n  if (nr == 1 && nc == 1)                                               \\\n    {                                                                   \\\n      RET_EL_TYPE s = m.elem (0,0);                                     \\\n      if (octave::math::isnan (s))                                      \\\n        {                                                               \\\n          RET_TYPE r (a_nr, a_nc, a_nr * a_nc);                         \\\n          for (octave_idx_type i = 0 ; i < r.numel () ; i++)            \\\n            r.elem(i) = octave::numeric_limits<EL_TYPE>::NaN ();        \\\n          return r;                                                     \\\n        }                                                               \\\n      if (octave::math::isinf (s))                                      \\\n        {                                                               \\\n          RET_TYPE r (a_nr, a_nc, a_nr * a_nc);                         \\\n          for (octave_idx_type j = 0 ; j < a_nc ; j++)                  \\\n            {                                                           \\\n              octave_quit ();                                           \\\n              for (octave_idx_type i = 0 ; i < a_nr ; i++)              \\\n                {                                                       \\\n                  if (a.elem (i, j) == 0.0)                             \\\n                    r.elem (i, j) = octave::numeric_limits<EL_TYPE>::NaN ();   \\\n                  else                                                  \\\n                    r.elem (i, j) = s * a.elem (i, j);                  \\\n                }                                                       \\\n            }                                                           \\\n          r.maybe_compress (true);                                      \\\n          return r;                                                     \\\n        }                                                               \\\n      octave_idx_type nz = a.nnz ();                                    \\\n      RET_TYPE r (a_nr, a_nc, nz);                                      \\\n                                                                        \\\n      for (octave_idx_type i = 0; i < nz; i++)                          \\\n        {                                                               \\\n          octave_quit ();                                               \\\n          r.data (i) = s * a.data (i);                                  \\\n          r.ridx (i) = a.ridx (i);                                      \\\n        }                                                               \\\n      for (octave_idx_type i = 0; i < a_nc + 1; i++)                    \\\n        {                                                               \\\n          octave_quit ();                                               \\\n          r.cidx (i) = a.cidx (i);                                      \\\n        }                                                               \\\n                                                                        \\\n      r.maybe_compress (true);                                          \\\n      return r;                                                         \\\n    }                                                                   \\\n  else if (a_nr == 1 && a_nc == 1)                                      \\\n    {                                                                   \\\n      RET_EL_TYPE s = a.elem (0,0);                                     \\\n      if (octave::math::isnan (s))                                      \\\n        {                                                               \\\n          RET_TYPE r (nr, nc, nr * nc);                                 \\\n          for (octave_idx_type i = 0 ; i < r.numel () ; i++)            \\\n            r.elem(i) = octave::numeric_limits<EL_TYPE>::NaN ();        \\\n          return r;                                                     \\\n        }                                                               \\\n      if (octave::math::isinf (s))                                      \\\n        {                                                               \\\n          RET_TYPE r (nr, nc, nr * nc);                                 \\\n          for (octave_idx_type j = 0 ; j < nc ; j++)                    \\\n            {                                                           \\\n              octave_quit ();                                           \\\n              for (octave_idx_type i = 0 ; i < nr ; i++)                \\\n                {                                                       \\\n                  if (m.elem (i, j) == 0.0)                             \\\n                    r.elem (i, j) = octave::numeric_limits<EL_TYPE>::NaN ();   \\\n                  else                                                  \\\n                    r.elem (i, j) = s * m.elem (i, j);                  \\\n                }                                                       \\\n            }                                                           \\\n          r.maybe_compress (true);                                      \\\n          return r;                                                     \\\n        }                                                               \\\n      octave_idx_type nz = m.nnz ();                                    \\\n      RET_TYPE r (nr, nc, nz);                                          \\\n                                                                        \\\n      for (octave_idx_type i = 0; i < nz; i++)                          \\\n        {                                                               \\\n          octave_quit ();                                               \\\n          r.data (i) = m.data (i) * s;                                  \\\n          r.ridx (i) = m.ridx (i);                                      \\\n        }                                                               \\\n      for (octave_idx_type i = 0; i < nc + 1; i++)                      \\\n        {                                                               \\\n          octave_quit ();                                               \\\n          r.cidx (i) = m.cidx (i);                                      \\\n        }                                                               \\\n                                                                        \\\n      r.maybe_compress (true);                                          \\\n      return r;                                                         \\\n    }                                                                   \\\n  else if (nc != a_nr)                                                  \\\n    octave::err_nonconformant (\"operator *\", nr, nc, a_nr, a_nc);       \\\n  else                                                                  \\\n    {                                                                   \\\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, w, nr);                     \\\n      RET_TYPE retval (nr, a_nc, static_cast<octave_idx_type> (0));     \\\n      for (octave_idx_type i = 0; i < nr; i++)                          \\\n        w[i] = 0;                                                       \\\n      retval.xcidx (0) = 0;                                             \\\n                                                                        \\\n      octave_idx_type nel = 0;                                          \\\n                                                                        \\\n      for (octave_idx_type i = 0; i < a_nc; i++)                        \\\n        {                                                               \\\n          for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++)   \\\n            {                                                           \\\n              octave_idx_type col = a.ridx (j);                         \\\n              for (octave_idx_type k = m.cidx (col) ; k < m.cidx (col+1); k++) \\\n                {                                                       \\\n                  if (w[m.ridx (k)] < i + 1)                            \\\n                    {                                                   \\\n                      w[m.ridx (k)] = i + 1;                            \\\n                      nel++;                                            \\\n                    }                                                   \\\n                  octave_quit ();                                       \\\n                }                                                       \\\n            }                                                           \\\n          retval.xcidx (i+1) = nel;                                     \\\n        }                                                               \\\n                                                                        \\\n      if (nel == 0)                                                     \\\n        return RET_TYPE (nr, a_nc);                                     \\\n      else                                                              \\\n        {                                                               \\\n          for (octave_idx_type i = 0; i < nr; i++)                      \\\n            w[i] = 0;                                                   \\\n                                                                        \\\n          OCTAVE_LOCAL_BUFFER (RET_EL_TYPE, Xcol, nr);                  \\\n                                                                        \\\n          retval.change_capacity (nel);                                 \\\n          /* The optimal break-point as estimated from simulations */   \\\n          /* Note that Mergesort is O(nz log(nz)) while searching */    \\\n          /* all values is O(nr), where nz here is nonzero per row */   \\\n          /* of length nr.  The test itself was then derived from */    \\\n          /* the simulation with random square matrices and the */      \\\n          /* observation of the number of nonzero elements in the */    \\\n          /* output matrix it was found that the breakpoints were */    \\\n          /*   nr: 500  1000  2000  5000 10000 */                       \\\n          /*   nz:   6    25    97   585  2202 */                       \\\n          /* The below is a simplication of the 'polyfit'-ed */         \\\n          /* parameters to these breakpoints */                         \\\n          octave_idx_type n_per_col = (a_nc > 43000 ? 43000 :           \\\n                                       (a_nc * a_nc) / 43000);          \\\n          octave_idx_type ii = 0;                                       \\\n          octave_idx_type *ri = retval.xridx ();                        \\\n          octave_sort<octave_idx_type> sort;                            \\\n                                                                        \\\n          for (octave_idx_type i = 0; i < a_nc ; i++)                   \\\n            {                                                           \\\n              if (retval.xcidx (i+1) - retval.xcidx (i) > n_per_col)    \\\n                {                                                       \\\n                  for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++)  \\\n                    {                                                   \\\n                      octave_idx_type col = a.ridx (j);                 \\\n                      EL_TYPE tmpval = a.data (j);                      \\\n                      for (octave_idx_type k = m.cidx (col) ;           \\\n                           k < m.cidx (col+1); k++)                     \\\n                        {                                               \\\n                          octave_quit ();                               \\\n                          octave_idx_type row = m.ridx (k);             \\\n                          if (w[row] < i + 1)                           \\\n                            {                                           \\\n                              w[row] = i + 1;                           \\\n                              Xcol[row] = tmpval * m.data (k);          \\\n                            }                                           \\\n                          else                                          \\\n                            Xcol[row] += tmpval * m.data (k);           \\\n                        }                                               \\\n                    }                                                   \\\n                  for (octave_idx_type k = 0; k < nr; k++)              \\\n                    if (w[k] == i + 1)                                  \\\n                      {                                                 \\\n                        retval.xdata (ii) = Xcol[k];                    \\\n                        retval.xridx (ii++) = k;                        \\\n                      }                                                 \\\n                }                                                       \\\n              else                                                      \\\n                {                                                       \\\n                  for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++)  \\\n                    {                                                   \\\n                      octave_idx_type col = a.ridx (j);                 \\\n                      EL_TYPE tmpval = a.data (j);                      \\\n                      for (octave_idx_type k = m.cidx (col) ;           \\\n                           k < m.cidx (col+1); k++)                     \\\n                        {                                               \\\n                          octave_quit ();                               \\\n                          octave_idx_type row = m.ridx (k);             \\\n                          if (w[row] < i + 1)                           \\\n                            {                                           \\\n                              w[row] = i + 1;                           \\\n                              retval.xridx (ii++) = row;                \\\n                              Xcol[row] = tmpval * m.data (k);          \\\n                            }                                           \\\n                          else                                          \\\n                            Xcol[row] += tmpval * m.data (k);           \\\n                        }                                               \\\n                    }                                                   \\\n                  sort.sort (ri + retval.xcidx (i), ii - retval.xcidx (i));    \\\n                  for (octave_idx_type k = retval.xcidx (i); k < ii; k++)      \\\n                    retval.xdata (k) = Xcol[retval.xridx (k)];          \\\n                }                                                       \\\n            }                                                           \\\n          retval.maybe_compress (true);                                 \\\n          return retval;                                                \\\n        }                                                               \\\n    }\n\n#define SPARSE_FULL_MUL(RET_TYPE, EL_TYPE)                              \\\n  octave_idx_type nr = m.rows ();                                       \\\n  octave_idx_type nc = m.cols ();                                       \\\n                                                                        \\\n  octave_idx_type a_nr = a.rows ();                                     \\\n  octave_idx_type a_nc = a.cols ();                                     \\\n                                                                        \\\n  if (nr == 1 && nc == 1)                                               \\\n    {                                                                   \\\n      RET_TYPE retval = m.elem (0,0) * a;                               \\\n      return retval;                                                    \\\n    }                                                                   \\\n  else if (nc != a_nr)                                                  \\\n    octave::err_nonconformant (\"operator *\", nr, nc, a_nr, a_nc);       \\\n  else                                                                  \\\n    {                                                                   \\\n      RET_TYPE::element_type zero = RET_TYPE::element_type ();          \\\n                                                                        \\\n      RET_TYPE retval (nr, a_nc, zero);                                 \\\n                                                                        \\\n      for (octave_idx_type i = 0; i < a_nc ; i++)                       \\\n        {                                                               \\\n          for (octave_idx_type j = 0; j < a_nr; j++)                    \\\n            {                                                           \\\n              octave_quit ();                                           \\\n                                                                        \\\n              EL_TYPE tmpval = a.elem (j,i);                            \\\n              for (octave_idx_type k = m.cidx (j) ; k < m.cidx (j+1); k++)     \\\n                retval.elem (m.ridx (k),i) += tmpval * m.data (k);      \\\n            }                                                           \\\n        }                                                               \\\n      return retval;                                                    \\\n    }\n\n#define SPARSE_FULL_TRANS_MUL(RET_TYPE, EL_TYPE, CONJ_OP)               \\\n  octave_idx_type nr = m.rows ();                                       \\\n  octave_idx_type nc = m.cols ();                                       \\\n                                                                        \\\n  octave_idx_type a_nr = a.rows ();                                     \\\n  octave_idx_type a_nc = a.cols ();                                     \\\n                                                                        \\\n  if (nr == 1 && nc == 1)                                               \\\n    {                                                                   \\\n      RET_TYPE retval = CONJ_OP (m.elem (0,0)) * a;                     \\\n      return retval;                                                    \\\n    }                                                                   \\\n  else if (nr != a_nr)                                                  \\\n    octave::err_nonconformant (\"operator *\", nc, nr, a_nr, a_nc);       \\\n  else                                                                  \\\n    {                                                                   \\\n      RET_TYPE retval (nc, a_nc);                                       \\\n                                                                        \\\n      for (octave_idx_type i = 0; i < a_nc ; i++)                       \\\n        {                                                               \\\n          for (octave_idx_type j = 0; j < nc; j++)                      \\\n            {                                                           \\\n              octave_quit ();                                           \\\n                                                                        \\\n              EL_TYPE acc = EL_TYPE ();                                 \\\n              for (octave_idx_type k = m.cidx (j) ; k < m.cidx (j+1); k++)     \\\n                acc += a.elem (m.ridx (k),i) * CONJ_OP (m.data (k));    \\\n              retval.xelem (j,i) = acc;                                 \\\n            }                                                           \\\n        }                                                               \\\n      return retval;                                                    \\\n    }\n\n#define FULL_SPARSE_MUL(RET_TYPE, EL_TYPE)                              \\\n  octave_idx_type nr = m.rows ();                                       \\\n  octave_idx_type nc = m.cols ();                                       \\\n                                                                        \\\n  octave_idx_type a_nr = a.rows ();                                     \\\n  octave_idx_type a_nc = a.cols ();                                     \\\n                                                                        \\\n  if (a_nr == 1 && a_nc == 1)                                           \\\n    {                                                                   \\\n      RET_TYPE retval = m * a.elem (0,0);                               \\\n      return retval;                                                    \\\n    }                                                                   \\\n  else if (nc != a_nr)                                                  \\\n    octave::err_nonconformant (\"operator *\", nr, nc, a_nr, a_nc);       \\\n  else                                                                  \\\n    {                                                                   \\\n      RET_TYPE::element_type zero = RET_TYPE::element_type ();          \\\n                                                                        \\\n      RET_TYPE retval (nr, a_nc, zero);                                 \\\n                                                                        \\\n      for (octave_idx_type i = 0; i < a_nc ; i++)                       \\\n        {                                                               \\\n          octave_quit ();                                               \\\n          for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++)   \\\n            {                                                           \\\n              octave_idx_type col = a.ridx (j);                         \\\n              EL_TYPE tmpval = a.data (j);                              \\\n                                                                        \\\n              for (octave_idx_type k = 0 ; k < nr; k++)                 \\\n                retval.xelem (k,i) += tmpval * m.elem (k,col);          \\\n            }                                                           \\\n        }                                                               \\\n      return retval;                                                    \\\n    }\n\n#define FULL_SPARSE_MUL_TRANS(RET_TYPE, EL_TYPE, CONJ_OP)               \\\n  octave_idx_type nr = m.rows ();                                       \\\n  octave_idx_type nc = m.cols ();                                       \\\n                                                                        \\\n  octave_idx_type a_nr = a.rows ();                                     \\\n  octave_idx_type a_nc = a.cols ();                                     \\\n                                                                        \\\n  if (a_nr == 1 && a_nc == 1)                                           \\\n    {                                                                   \\\n      RET_TYPE retval = m * CONJ_OP (a.elem (0,0));                     \\\n      return retval;                                                    \\\n    }                                                                   \\\n  else if (nc != a_nc)                                                  \\\n    octave::err_nonconformant (\"operator *\", nr, nc, a_nc, a_nr);       \\\n  else                                                                  \\\n    {                                                                   \\\n      RET_TYPE::element_type zero = RET_TYPE::element_type ();          \\\n                                                                        \\\n      RET_TYPE retval (nr, a_nr, zero);                                 \\\n                                                                        \\\n      for (octave_idx_type i = 0; i < a_nc ; i++)                       \\\n        {                                                               \\\n          octave_quit ();                                               \\\n          for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++)   \\\n            {                                                           \\\n              octave_idx_type col = a.ridx (j);                         \\\n              EL_TYPE tmpval = CONJ_OP (a.data (j));                    \\\n              for (octave_idx_type k = 0 ; k < nr; k++)                 \\\n                retval.xelem (k,col) += tmpval * m.elem (k,i);          \\\n            }                                                           \\\n        }                                                               \\\n      return retval;                                                    \\\n    }\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/Sparse-perm-op-defs.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_Sparse_perm_op_defs_h)\n#define octave_Sparse_perm_op_defs_h 1\n\n#include \"octave-config.h\"\n\n#include \"PermMatrix.h\"\n#include \"lo-array-errwarn.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sort.h\"\n#include \"quit.h\"\n\n// Matrix multiplication\n\ntemplate <typename SM>\nSM octinternal_do_mul_colpm_sm (const octave_idx_type *pcol, const SM& a)\n// Relabel the rows according to pcol.\n{\n  const octave_idx_type nr = a.rows ();\n  const octave_idx_type nc = a.cols ();\n  const octave_idx_type nent = a.nnz ();\n  SM r (nr, nc, nent);\n\n  octave_sort<octave_idx_type> sort;\n\n  for (octave_idx_type j = 0; j <= nc; ++j)\n    r.xcidx (j) = a.cidx (j);\n\n  for (octave_idx_type j = 0; j < nc; j++)\n    {\n      octave_quit ();\n\n      OCTAVE_LOCAL_BUFFER (octave_idx_type, sidx, r.xcidx (j+1) - r.xcidx (j));\n      for (octave_idx_type i = r.xcidx (j), ii = 0; i < r.xcidx (j+1); i++)\n        {\n          sidx[ii++]=i;\n          r.xridx (i) = pcol[a.ridx (i)];\n        }\n      sort.sort (r.xridx () + r.xcidx (j), sidx, r.xcidx (j+1) - r.xcidx (j));\n      for (octave_idx_type i = r.xcidx (j), ii = 0; i < r.xcidx (j+1); i++)\n        r.xdata (i) = a.data (sidx[ii++]);\n    }\n\n  return r;\n}\n\ntemplate <typename SM>\nSM octinternal_do_mul_pm_sm (const PermMatrix& p, const SM& a)\n{\n  const octave_idx_type nr = a.rows ();\n  if (p.cols () != nr)\n    octave::err_nonconformant (\"operator *\",\n                               p.rows (), p.cols (), a.rows (), a.cols ());\n\n  return octinternal_do_mul_colpm_sm (p.col_perm_vec ().data (), a);\n}\n\ntemplate <typename SM>\nSM octinternal_do_mul_sm_rowpm (const SM& a, const octave_idx_type *prow)\n// For a row permutation, iterate across the source a and stuff the\n// results into the correct destination column in r.\n{\n  const octave_idx_type nr = a.rows ();\n  const octave_idx_type nc = a.cols ();\n  const octave_idx_type nent = a.nnz ();\n  SM r (nr, nc, nent);\n\n  for (octave_idx_type j_src = 0; j_src < nc; ++j_src)\n    r.xcidx (prow[j_src]) = a.cidx (j_src+1) - a.cidx (j_src);\n  octave_idx_type k = 0;\n  for (octave_idx_type j = 0; j < nc; ++j)\n    {\n      const octave_idx_type tmp = r.xcidx (j);\n      r.xcidx (j) = k;\n      k += tmp;\n    }\n  r.xcidx (nc) = nent;\n\n  octave_idx_type k_src = 0;\n  for (octave_idx_type j_src = 0; j_src < nc; ++j_src)\n    {\n      octave_quit ();\n      const octave_idx_type j = prow[j_src];\n      const octave_idx_type kend_src = a.cidx (j_src + 1);\n      for (k = r.xcidx (j); k_src < kend_src; ++k, ++k_src)\n        {\n          r.xridx (k) = a.ridx (k_src);\n          r.xdata (k) = a.data (k_src);\n        }\n    }\n  liboctave_panic_unless (k_src == nent);\n\n  return r;\n}\n\ntemplate <typename SM>\nSM octinternal_do_mul_sm_colpm (const SM& a, const octave_idx_type *pcol)\n// For a column permutation, iterate across the destination r and pull\n// data from the correct column of a.\n{\n  const octave_idx_type nr = a.rows ();\n  const octave_idx_type nc = a.cols ();\n  const octave_idx_type nent = a.nnz ();\n  SM r (nr, nc, nent);\n\n  for (octave_idx_type j = 0; j < nc; ++j)\n    {\n      const octave_idx_type j_src = pcol[j];\n      r.xcidx (j+1) = r.xcidx (j) + (a.cidx (j_src+1) - a.cidx (j_src));\n    }\n  liboctave_panic_unless (r.xcidx (nc) == nent);\n\n  octave_idx_type k = 0;\n  for (octave_idx_type j = 0; j < nc; ++j)\n    {\n      octave_quit ();\n      const octave_idx_type j_src = pcol[j];\n      octave_idx_type k_src;\n      const octave_idx_type kend_src = a.cidx (j_src + 1);\n      for (k_src = a.cidx (j_src); k_src < kend_src; ++k_src, ++k)\n        {\n          r.xridx (k) = a.ridx (k_src);\n          r.xdata (k) = a.data (k_src);\n        }\n    }\n  liboctave_panic_unless (k == nent);\n\n  return r;\n}\n\ntemplate <typename SM>\nSM octinternal_do_mul_sm_pm (const SM& a, const PermMatrix& p)\n{\n  const octave_idx_type nc = a.cols ();\n  if (p.rows () != nc)\n    octave::err_nonconformant (\"operator *\",\n                               a.rows (), a.cols (), p.rows (), p.cols ());\n\n  return octinternal_do_mul_sm_colpm (a, p.col_perm_vec ().data ());\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/config-ops.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nset -e\n\nAWK=${AWK:-awk}\nSHELL=${SHELL:-/bin/sh}\n\nif [ $# -lt 3 ]; then\n  src_type=\"all\"\nelse\n  src_type=\"$3\"\nfi\n\nif [ $# -lt 2 ]; then\n  obj_type=\"all\"\nelse\n  obj_type=\"$2\"\nfi\n\nif [ $# -lt 1 ]; then\n  top_srcdir=\"../..\"\nelse\n  top_srcdir=\"$1\"\nfi\n\nmove_if_change=\"$top_srcdir/build-aux/move-if-change\"\n\nclean_varname=\"liboctave_MAINTAINERCLEANFILES\"\n\nliboctave_dir=\"$top_srcdir/liboctave/operators\"\n\nmk_ops=\"$liboctave_dir/mk-ops.awk\"\n\ncase \"$obj_type\" in\n  vx | all)\n    case \"$src_type\" in\n      inc | all)\n        fn=vx-op-inc.mk\n        VX_INC=$($AWK -f $mk_ops -v prefix=vx -v list_h_files=1 $liboctave_dir/vx-ops)\n        echo \"VX_OP_INC = $VX_INC\" > $liboctave_dir/$fn-t\n        echo \"$clean_varname += \\$(srcdir)/%reldir%/$fn\" >> $liboctave_dir/$fn-t\n        $SHELL $move_if_change $liboctave_dir/$fn-t $liboctave_dir/$fn\n      ;;\n    esac\n  ;;\nesac\n\ncase \"$obj_type\" in\n  vx | all)\n    case \"$src_type\" in\n      src | all)\n        fn=vx-op-src.mk\n        VX_SRC=$($AWK -f $mk_ops -v prefix=vx -v list_cc_files=1 $liboctave_dir/vx-ops)\n        echo \"VX_OP_SRC = $VX_SRC\" > $liboctave_dir/$fn-t\n        echo \"$clean_varname += \\$(srcdir)/%reldir%/$fn\" >> $liboctave_dir/$fn-t\n        $SHELL $move_if_change $liboctave_dir/$fn-t $liboctave_dir/$fn\n      ;;\n    esac\n  ;;\nesac\n\ncase \"$obj_type\" in\n  mx | all)\n    case \"$src_type\" in\n      inc | all)\n        fn=mx-op-inc.mk\n        MX_INC=$($AWK -f $mk_ops -v prefix=mx -v list_h_files=1 $liboctave_dir/mx-ops)\n        echo \"MX_OP_INC = $MX_INC\" > $liboctave_dir/$fn-t\n        echo \"$clean_varname += \\$(srcdir)/%reldir%/$fn\" >> $liboctave_dir/$fn-t\n        $SHELL $move_if_change $liboctave_dir/$fn-t $liboctave_dir/$fn\n      ;;\n    esac\n  ;;\nesac\n\ncase \"$obj_type\" in\n  mx | all)\n    case \"$src_type\" in\n      src | all)\n        fn=mx-op-src.mk\n        MX_SRC=$($AWK -f $mk_ops -v prefix=mx -v list_cc_files=1 $liboctave_dir/mx-ops)\n        echo \"MX_OP_SRC = $MX_SRC\" > $liboctave_dir/$fn-t\n        echo \"$clean_varname += \\$(srcdir)/%reldir%/$fn\" >> $liboctave_dir/$fn-t\n        $SHELL $move_if_change $liboctave_dir/$fn-t $liboctave_dir/$fn\n      ;;\n    esac\n  ;;\nesac\n\ncase \"$obj_type\" in\n  smx | all)\n    case \"$src_type\" in\n      inc | all)\n        fn=smx-op-inc.mk\n        SMX_INC=$($AWK -f $mk_ops -v prefix=smx -v list_h_files=1 $liboctave_dir/smx-ops)\n        echo \"SMX_OP_INC = $SMX_INC\" > $liboctave_dir/$fn-t\n        echo \"$clean_varname += \\$(srcdir)/%reldir%/$fn\" >> $liboctave_dir/$fn-t\n        $SHELL $move_if_change $liboctave_dir/$fn-t $liboctave_dir/$fn\n      ;;\n    esac\n  ;;\nesac\n\ncase \"$obj_type\" in\n  smx | all)\n    case \"$src_type\" in\n      src | all)\n        fn=smx-op-src.mk\n        SMX_SRC=$($AWK -f $mk_ops -v prefix=smx -v list_cc_files=1 $liboctave_dir/smx-ops)\n        echo \"SMX_OP_SRC = $SMX_SRC\" > $liboctave_dir/$fn-t\n        echo \"$clean_varname += \\$(srcdir)/%reldir%/$fn\" >> $liboctave_dir/$fn-t\n        $SHELL $move_if_change $liboctave_dir/$fn-t $liboctave_dir/$fn\n      ;;\n    esac\n  ;;\nesac\n"
  },
  {
    "path": "liboctave/operators/mk-ops.awk",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nBEGIN {\n  declare_types = 0;\n  generate_ops = 0;\n  op_class = \"\";\n  sparse = 0;\n  ntypes = 0;\n  make_inclusive_header = 0;\n  make_header = 0;\n  make_source = 0;\n\n  if (build_file)\n    {\n      if (build_file == \"mx-ops.h\" || build_file == \"smx-ops.h\" || build_file == \"vx-ops.h\")\n        {\n          make_inclusive_header = 1;\n\n          print \"// DO NOT EDIT -- generated by mk-ops.awk\";\n          tmp = build_file;\n          prefix = substr (tmp, 1, index (tmp, \"-\")-1);\n          gsub (/[\\.-]/, \"_\", tmp);\n          printf (\"#if ! defined (octave_%s)\\n\", tmp);\n          printf (\"#define octave_%s 1\\n\", tmp);\n          print \"#include \\\"octave-config.h\\\"\";\n        }\n      else\n        {\n          if (match (build_file, /\\.h$/))\n            {\n              make_header = 1;\n\n              tmp = substr (build_file, 1, length (build_file)-2);\n            }\n          else if (match (build_file, /\\.cc$/))\n            {\n              make_source = 1;\n\n              tmp = substr (build_file, 1, length (build_file)-3);\n            }\n\n          prefix = substr (tmp, 1, index (tmp, \"-\")-1);\n          tmp = substr (tmp, index (tmp, \"-\")+1);\n          lhs_arg = substr (tmp, 1, index (tmp, \"-\")-1);\n          rhs_arg = substr (tmp, index (tmp, \"-\")+1);\n        }\n    }\n}\n/^#/ {\n  if ($2 == \"types\")\n    declare_types = 1;\n  else if ($3 == \"operators\")\n    {\n      op_class = $2;\n      generate_ops = 1;\n      declare_types = 0;\n\n      if (op_class == \"vector\")\n        sparse = 0;\n      else if (op_class == \"full-matrix\")\n        sparse = 0;\n      else if (op_class == \"sparse-matrix\")\n        sparse = 1;\n      else\n        {\n          printf (\"unrecognized object type: %s\", op_class);\n          exit (1);\n        }\n    }\n  next;\n} {\n  if (declare_types)\n    {\n      ntypes++;\n\n      if (NF == 5 || NF == 6)\n        {\n          if (NF == 6)\n            core_type[ntypes] = $6;\n\n          fwd_decl_ok[ntypes] = $5 == \"YES\";\n          header[ntypes] = $4 == \"NONE\" ? \"\" : $4;\n          class[ntypes] = $3;\n          type[ntypes] = $2;\n          tag[ntypes] = $1;\n          rev_tag[$1] = ntypes;\n        }\n      else\n        printf (\"skipping line %d: %s\\n\", NR, $0);\n    }\n  else if (generate_ops)\n    {\n      if (NF >= 4 || (sparse && NF >= 5))\n        {\n          n = 0;\n\n          result_tag_1 = $(++n);\n          if (sparse)\n            result_tag_2 = $(++n);\n          lhs_tag = $(++n);\n          rhs_tag = $(++n);\n          op_type = $(++n);\n\n          bin_ops = index (op_type, \"B\") != 0;\n          cmp_ops = index (op_type, \"C\") != 0;\n          eqne_ops = index (op_type, \"E\") != 0;\n          bool_ops = index (op_type, \"L\") != 0;\n\n          k = 0\n          while (NF > n)\n            bool_headers[k++] = $(++n);\n\n          cc_file = sprintf (\"%s-%s-%s.cc\", prefix, lhs_tag, rhs_tag);\n          h_file = sprintf (\"%s-%s-%s.h\", prefix, lhs_tag, rhs_tag);\n\n          if (list_cc_files)\n            {\n              printf (\" liboctave/operators/%s\", cc_file);\n              next;\n            }\n\n          if (list_h_files)\n            {\n              printf (\" liboctave/operators/%s\", h_file);\n              next;\n            }\n\n          if (make_inclusive_header)\n            {\n              printf (\"#include \\\"%s\\\"\\n\", h_file);\n              next;\n            }\n\n          if (lhs_arg != lhs_tag || rhs_arg != rhs_tag)\n            next;\n\n          h_guard = sprintf (\"octave_%s_%s_%s_h\", prefix, lhs_tag, rhs_tag);\n\n          result_num_1 = rev_tag[result_tag_1];\n          if (sparse)\n            result_num_2 = rev_tag[result_tag_2];\n          lhs_num = rev_tag[lhs_tag];\n          rhs_num = rev_tag[rhs_tag];\n\n          result_type_1 = type[result_num_1];\n          if (sparse)\n            result_type_2 = type[result_num_2];\n          lhs_type = type[lhs_num];\n          rhs_type = type[rhs_num];\n\n          lhs_core_type = core_type[lhs_num];\n          rhs_core_type = core_type[rhs_num];\n\n          result_header_1 = header[result_num_1];\n          if (sparse)\n            result_header_2 = header[result_num_2];\n          lhs_header = header[lhs_num];\n          rhs_header = header[rhs_num];\n\n          lhs_class = class[lhs_num];\n          rhs_class = class[rhs_num];\n\n          if (make_header)\n            {\n              print \"// DO NOT EDIT -- generated by mk-ops.awk\";\n\n              printf (\"#if ! defined (%s)\\n\", h_guard);\n              printf (\"#define %s 1\\n\", h_guard);\n              print \"#include \\\"octave-config.h\\\"\";\n\n              if (result_header_1)\n                {\n                  if (result_fwd_decl_ok)\n                    printf (\"class %s\\n\", result_type_1);\n                  else\n                    printf (\"#include \\\"%s\\\"\\n\", result_header_1);\n                }\n\n              if (result_header_2 && ! (result_header_2 == result_header_1))\n                {\n                  if (result_fwd_decl_ok)\n                    printf (\"class %s\\n\", result_type_2);\n                  else\n                    printf (\"#include \\\"%s\\\"\\n\", result_header_2);\n                }\n\n              if (lhs_header && ! (lhs_header == result_header_1 || lhs_header == result_header_2))\n                {\n                  if (result_fwd_decl_ok)\n                    printf (\"class %s\\n\", lhs_type);\n                  else\n                    printf (\"#include \\\"%s\\\"\\n\", lhs_header);\n                }\n\n              if (rhs_header && ! (rhs_header == lhs_header || rhs_header == result_header_1 || rhs_header == result_header_2))\n                {\n                  if (result_fwd_decl_ok)\n                    printf (\"class %s\\n\", rhs_type);\n                  else\n                    printf (\"#include \\\"%s\\\"\\n\", rhs_header);\n                }\n\n              if (sparse)\n                {\n                  lhs_is_sparse = 0;\n                  rhs_is_sparse = 0;\n\n                  xlhs_tag = \"NONE\";\n                  xrhs_tag = \"NONE\";\n\n                  if (lhs_tag == \"sbm\")\n                    {\n                      lhs_is_sparse = 1;\n                      xlhs_tag = \"b\";\n                    }\n                  else if (lhs_tag == \"scm\")\n                    {\n                      lhs_is_sparse = 1;\n                      xlhs_tag = \"cs\";\n                    }\n                  else if (lhs_tag == \"sm\")\n                    {\n                      lhs_is_sparse = 1;\n                      xlhs_tag = \"s\";\n                    }\n                  else if (lhs_tag == \"bm\" || lhs_tag == \"cm\" || lhs_tag == \"m\")\n                    xlhs_tag = lhs_tag;\n\n                  if (rhs_tag == \"sbm\")\n                    {\n                      rhs_is_sparse = 1;\n                      xrhs_tag = \"b\";\n                    }\n                  else if (rhs_tag == \"scm\")\n                    {\n                      rhs_is_sparse = 1;\n                      xrhs_tag = \"cs\";\n                    }\n                  else if (rhs_tag == \"sm\")\n                    {\n                      rhs_is_sparse = 1;\n                      xrhs_tag = \"s\";\n                    }\n                  else if (rhs_tag == \"bm\" || rhs_tag == \"cm\" || rhs_tag == \"m\")\n                    xrhs_tag = rhs_tag;\n\n                  same_types = ((xlhs_tag == \"b\" && xrhs_tag == \"bm\") || (xlhs_tag == \"cs\" && xrhs_tag == \"cm\") || (xlhs_tag == \"s\" && xrhs_tag == \"m\") || (xlhs_tag == \"bm\" && xrhs_tag == \"b\") || (xlhs_tag == \"cm\" && xrhs_tag == \"cs\") || (xlhs_tag == \"m\" && xrhs_tag == \"s\"));\n\n                  if (! (same_types || (rhs_is_sparse && lhs_is_sparse) || xlhs_tag == \"NONE\" || xrhs_tag == \"NONE\"))\n                    {\n                      printf (\"#include \\\"mx-%s-%s.h\\\"\\n\", xlhs_tag, xrhs_tag);\n                      printf (\"#include \\\"mx-%s-%s.h\\\"\\n\", xrhs_tag, xlhs_tag);\n\n                      xxlhs_tag = xlhs_tag;\n                      xxrhs_tag = xrhs_tag;\n\n                      if (xxlhs_tag == \"cs\")\n                        xxlhs_tag = \"cm\";\n                      else if (xxlhs_tag == \"s\")\n                        xxlhs_tag = \"m\";\n                      else if (xxlhs_tag == \"b\")\n                        xxlhs_tag = \"NONE\";\n\n                      if (xxrhs_tag == \"cs\")\n                        xxrhs_tag = \"cm\";\n                      else if (xxrhs_tag == \"s\")\n                        xxrhs_tag = \"m\";\n                      else if (xxrhs_tag == \"b\")\n                        xxrhs_tag = \"NONE\";\n\n                      if (! (xxlhs_tag == \"NONE\" || xxrhs_tag == \"NONE\" || xxlhs_tag == xxrhs_tag))\n                        {\n                          printf (\"#include \\\"mx-%s-%s.h\\\"\\n\", xxlhs_tag, xxrhs_tag);\n                          printf (\"#include \\\"mx-%s-%s.h\\\"\\n\", xxrhs_tag, xxlhs_tag);\n                        }\n\n                      xxlhs_tag = xlhs_tag;\n                      xxrhs_tag = xrhs_tag;\n\n                      if (xxlhs_tag == \"m\")\n                        xxlhs_tag = \"nda\";\n                      else if (xxlhs_tag == \"cm\")\n                        xxlhs_tag = \"cnda\";\n                      else if (xxlhs_tag == \"bm\")\n                        xxlhs_tag = \"NONE\";\n\n                      if (xxrhs_tag == \"m\")\n                        xxrhs_tag = \"nda\";\n                      else if (xxrhs_tag == \"cm\")\n                        xxrhs_tag = \"cnda\";\n                      else if (xxrhs_tag == \"bm\")\n                        xxrhs_tag = \"NONE\";\n\n                      if (! (xxlhs_tag == \"NONE\" || xxrhs_tag == \"NONE\"))\n                        {\n                          printf (\"#include \\\"mx-%s-%s.h\\\"\\n\", xxlhs_tag, xxrhs_tag);\n                          printf (\"#include \\\"mx-%s-%s.h\\\"\\n\", xxrhs_tag, xxlhs_tag);\n                        }\n                    }\n\n                  printf (\"#include \\\"Sparse-op-defs.h\\\"\\n\");\n                }\n\n              if (bin_ops)\n                emit_bin_op_decls(sparse, lhs_class, rhs_class,\n                                  result_type_1, result_type_2,\n                                  lhs_type, rhs_type);\n\n              if (cmp_ops)\n                emit_cmp_op_decls(sparse, lhs_class, rhs_class,\n                                  lhs_type, rhs_type);\n\n              if (eqne_ops)\n                emit_eqne_op_decls(sparse, lhs_class, rhs_class,\n                                   lhs_type, rhs_type);\n\n              if (bool_ops)\n                emit_bool_op_decls(sparse, lhs_class, rhs_class,\n                                   lhs_type, rhs_type);\n\n              print \"#endif\";\n\n              exit (0);\n            }\n          else if (make_source)\n            {\n              print \"// DO NOT EDIT -- generated by mk-ops.awk\";\n\n              print \"#if defined (HAVE_CONFIG_H)\";\n              print \"#  include \\\"config.h\\\"\";\n              print \"#endif\";\n\n              print \"#include \\\"Array-util.h\\\"\";\n\n              printf (\"#include \\\"%s\\\"\\n\", h_file);\n\n              if (! sparse)\n                printf (\"#include \\\"mx-op-defs.h\\\"\\n\");\n\n              for (i in bool_headers)\n                {\n                  printf (\"#include \\\"%s\\\"\\n\", bool_headers[i]);\n                  delete bool_headers[i];\n                }\n\n              if (result_header_1)\n                printf (\"#include \\\"%s\\\"\\n\", result_header_1);\n\n              if (result_header_2 && ! (result_header_2 == result_header_1))\n                printf (\"#include \\\"%s\\\"\\n\", result_header_2);\n\n              if (lhs_header && ! (lhs_header == result_header_1 || lhs_header == result_header_2))\n                printf (\"#include \\\"%s\\\"\\n\", lhs_header);\n\n              if (rhs_header && ! (rhs_header == lhs_header || rhs_header == result_header_1 || rhs_header == result_header_2))\n                printf (\"#include \\\"%s\\\"\\n\", rhs_header);\n\n              if (bin_ops)\n                emit_bin_ops(sparse, lhs_class, rhs_class,\n                             result_type_1, result_type_2, lhs_type, rhs_type);\n\n              if (cmp_ops)\n                emit_cmp_ops(sparse, lhs_class, rhs_class, lhs_type, rhs_type);\n\n              if (eqne_ops)\n                emit_eqne_ops(sparse, lhs_class, rhs_class,\n                              lhs_type, rhs_type);\n\n              if (bool_ops)\n                emit_bool_ops(sparse, lhs_class, rhs_class,\n                              lhs_type, rhs_type);\n\n              exit (0);\n            }\n        }\n      else\n        printf (\"skipping line %d: %s\\n\", NR, $0);\n    }\n}\nEND {\n  if (make_inclusive_header)\n    print \"#endif\";\n}\n\nfunction emit_bin_op_decl (result_type, operator, lhs_type, rhs_type)\n{\n  if (operator != \"\")\n    printf (\"  extern OCTAVE_API %s %s (const %s&, const %s&);\\n\",\n            result_type, operator, lhs_type, rhs_type);\n}\n\nfunction emit_bin_op_decls_1 (result_type, lhs_type, rhs_type,\n                              add_op, sub_op, mul_op, div_op)\n{\n  emit_bin_op_decl(result_type, add_op, lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, sub_op, lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, mul_op, lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, div_op, lhs_type, rhs_type);\n}\n\nfunction emit_sparse_bin_op_decls_1 (result_type_1, result_type_2,\n                                     lhs_type, rhs_type,\n                                     add_op, sub_op, mul_op, div_op)\n{\n  emit_bin_op_decl(result_type_1, add_op, lhs_type, rhs_type);\n  emit_bin_op_decl(result_type_1, sub_op, lhs_type, rhs_type);\n  emit_bin_op_decl(result_type_2, mul_op, lhs_type, rhs_type);\n  emit_bin_op_decl(result_type_1, div_op, lhs_type, rhs_type);\n}\n\nfunction emit_sparse_bin_op_decls_2 (result_type_1, result_type_2,\n                                     lhs_type, rhs_type,\n                                     add_op, sub_op, mul_op, div_op)\n{\n  emit_bin_op_decl(result_type_1, add_op, lhs_type, rhs_type);\n  emit_bin_op_decl(result_type_1, sub_op, lhs_type, rhs_type);\n  emit_bin_op_decl(result_type_2, mul_op, lhs_type, rhs_type);\n  emit_bin_op_decl(result_type_2, div_op, lhs_type, rhs_type);\n}\n\nfunction emit_bin_op_decls (sparse, lhs_class, rhs_class,\n                            result_type_1, result_type_2,\n                            lhs_type, rhs_type)\n{\n  if (sparse)\n    {\n      if (lhs_class == \"S\" && rhs_class == \"SM\")\n        emit_sparse_bin_op_decls_1(result_type_1, result_type_2,\n                                   lhs_type, rhs_type,\n                                   \"operator +\", \"operator -\",\n                                   \"operator *\", \"operator /\");\n\n      else if (lhs_class == \"SM\" && rhs_class == \"S\")\n        emit_sparse_bin_op_decls_2(result_type_1, result_type_2,\n                                   lhs_type, rhs_type,\n                                   \"operator +\", \"operator -\",\n                                   \"operator *\", \"operator /\");\n\n      else if (lhs_class == \"M\" && rhs_class == \"SM\")\n        emit_sparse_bin_op_decls_1(result_type_1, result_type_2,\n                                   lhs_type, rhs_type,\n                                   \"operator +\", \"operator -\",\n                                   \"product\", \"quotient\");\n\n      else if ((lhs_class == \"SM\" && rhs_class == \"M\") \\\n               || (lhs_class == \"SM\" && rhs_class == \"SM\"))\n        emit_sparse_bin_op_decls_2(result_type_1, result_type_2,\n                                   lhs_type, rhs_type,\n                                   \"operator +\", \"operator -\",\n                                   \"product\", \"quotient\");\n    }\n  else\n    {\n      if ((lhs_class == \"M\" && rhs_class == \"S\") \\\n          || (lhs_class == \"ND\" && rhs_class == \"S\") \\\n          || (lhs_class == \"S\" \\\n              && (rhs_class == \"M\" || rhs_class == \"ND\" || rhs_class == \"V\")) \\\n          || (lhs_class == \"V\" && rhs_class == \"S\"))\n        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,\n                            \"operator +\", \"operator -\",\n                            \"operator *\", \"operator /\");\n\n      else if ((lhs_class == \"M\" && rhs_class == \"M\")      \\\n               || (lhs_class == \"ND\" && rhs_class == \"ND\") \\\n               || (lhs_class == \"V\" && rhs_class == \"V\"))\n        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,\n                            \"operator +\", \"operator -\",\n                            \"product\", \"quotient\");\n\n      else if ((lhs_class == \"DM\" && rhs_class == \"M\")  \\\n          || (lhs_class == \"M\" && rhs_class == \"DM\"))\n        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,\n                            \"operator +\", \"operator -\", \"operator *\", \"\");\n\n      else if (lhs_class == \"DM\" && rhs_class == \"DM\")\n        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,\n                            \"operator +\", \"operator -\", \"product\", \"\");\n\n      else if (lhs_class == \"DM\" && rhs_class == \"S\")\n        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,\n                            \"\", \"\", \"operator *\", \"operator /\");\n\n      else if ((lhs_class == \"M\" && rhs_class == \"PM\") \\\n               || (lhs_class == \"PM\" && rhs_class == \"M\") \\\n               || (lhs_class == \"S\" && rhs_class == \"DM\"))\n        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,\n                            \"\", \"\", \"operator *\", \"\");\n    }\n}\n\nfunction emit_cmp_op_decls_1(result_type, lhs_type, rhs_type)\n{\n  emit_bin_op_decl(result_type, \"mx_el_lt\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, \"mx_el_le\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, \"mx_el_ge\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, \"mx_el_gt\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, \"mx_el_eq\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, \"mx_el_ne\", lhs_type, rhs_type);\n}\n\nfunction emit_cmp_op_decls (sparse, lhs_class, rhs_class, lhs_type, rhs_type)\n{\n  if (sparse)\n    {\n      if ((lhs_class == \"M\" && rhs_class == \"SM\") \\\n          || (lhs_class == \"SM\" && (rhs_class == \"M\" || rhs_class == \"S\" || rhs_class == \"SM\")) \\\n          || (lhs_class == \"S\" && rhs_class == \"SM\"))\n        emit_cmp_op_decls_1(\"SparseBoolMatrix\", lhs_type, rhs_type);\n    }\n  else\n    {\n      if ((lhs_class == \"M\" && rhs_class == \"M\") \\\n          || (lhs_class == \"M\" && rhs_class == \"S\") \\\n          || (lhs_class == \"S\" && rhs_class == \"M\"))\n        emit_cmp_op_decls_1(\"boolMatrix\", lhs_type, rhs_type);\n      else if ((lhs_class == \"ND\" && rhs_class == \"ND\") \\\n               || (lhs_class == \"ND\" && rhs_class == \"S\") \\\n               || (lhs_class == \"S\" && rhs_class == \"ND\"))\n        emit_cmp_op_decls_1(\"boolNDArray\", lhs_type, rhs_type);\n    }\n}\n\nfunction emit_eqne_op_decls_1(result_type, lhs_type, rhs_type)\n{\n  emit_bin_op_decl(result_type, \"mx_el_eq\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, \"mx_el_ne\", lhs_type, rhs_type);\n}\n\nfunction emit_eqne_op_decls (sparse, lhs_class, rhs_class, lhs_type, rhs_type)\n{\n  if (sparse)\n    {\n      if ((lhs_class == \"M\" && rhs_class == \"SM\") \\\n          || (lhs_class == \"SM\" && rhs_class == \"M\"))\n        emit_eqne_op_decls_1(\"SparseBoolMatrix\", lhs_type, rhs_type);\n    }\n\n  ## No separate eqne ops for full-matrix or vector.\n}\n\nfunction emit_bool_op_decls_1 (result_type, lhs_type, rhs_type)\n{\n  emit_bin_op_decl(result_type, \"mx_el_and\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, \"mx_el_or\", lhs_type, rhs_type);\n}\n\nfunction emit_bool_op_decls_2 (result_type, lhs_type, rhs_type)\n{\n  emit_bin_op_decl(result_type, \"mx_el_not_and\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, \"mx_el_not_or\", lhs_type, rhs_type);\n}\n\nfunction emit_bool_op_decls_3 (result_type, lhs_type, rhs_type)\n{\n  emit_bin_op_decl(result_type, \"mx_el_and_not\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type, \"mx_el_or_not\", lhs_type, rhs_type);\n}\n\nfunction emit_bool_op_decls_4 (result_type_1, result_type_2, lhs_type, rhs_type)\n{\n  emit_bin_op_decl(result_type_1, \"mx_el_and\", lhs_type, rhs_type);\n  emit_bin_op_decl(result_type_2, \"mx_el_or\", lhs_type, rhs_type);\n}\n\nfunction emit_bool_op_decls (sparse, lhs_class, rhs_class, lhs_type, rhs_type)\n{\n  if (sparse)\n    {\n      if (lhs_class == \"SM\" && rhs_class == \"SM\")\n        emit_bool_op_decls_1(\"SparseBoolMatrix\", lhs_type, rhs_type);\n\n      else if ((lhs_class == \"SM\" && (rhs_class == \"S\" || rhs_class == \"M\")) \\\n               || ((lhs_class == \"S\" || lhs_class == \"M\") && rhs_class == \"SM\"))\n        emit_bool_op_decls_4(\"SparseBoolMatrix\", \"boolMatrix\", lhs_type, rhs_type);\n    }\n  else\n    {\n      if ((lhs_class == \"M\" && rhs_class == \"M\") \\\n          || (lhs_class == \"M\" && rhs_class == \"S\") \\\n          || (lhs_class == \"S\" && rhs_class == \"M\"))\n        emit_bool_op_decls_1(\"boolMatrix\", lhs_type, rhs_type);\n      else if (lhs_class == \"ND\" && rhs_class == \"S\")\n        {\n          emit_bool_op_decls_1(\"boolNDArray\", lhs_type, rhs_type);\n          emit_bool_op_decls_2(\"boolNDArray\", lhs_type, rhs_type);\n        }\n      else if (lhs_class == \"S\" && rhs_class == \"ND\")\n        {\n          emit_bool_op_decls_1(\"boolNDArray\", lhs_type, rhs_type);\n          emit_bool_op_decls_3(\"boolNDArray\", lhs_type, rhs_type);\n        }\n      else if (lhs_class == \"ND\" && rhs_class == \"ND\")\n        {\n          emit_bool_op_decls_1(\"boolNDArray\", lhs_type, rhs_type);\n          emit_bool_op_decls_2(\"boolNDArray\", lhs_type, rhs_type);\n          emit_bool_op_decls_3(\"boolNDArray\", lhs_type, rhs_type);\n        }\n    }\n}\n\nfunction emit_sparse_bin_ops (lhs_class, rhs_class, result_type_1,\n                              result_type_2, lhs_type, rhs_type)\n{\n  printf (\"SPARSE_%s%s_BIN_OPS (%s, %s, %s, %s)\\n\",\n          lhs_class, rhs_class, result_type_1,\n          result_type_2, lhs_type, rhs_type);\n}\n\nfunction emit_dm_bin_ops (lhs_class, rhs_class, result_type_1,\n                          lhs_type, rhs_type)\n{\n  printf (\"%s%s_BIN_OPS (%s, %s, %s)\\n\",\n          lhs_class, rhs_class, result_type_1, lhs_type, rhs_type);\n}\n\nfunction emit_mm_bin_op (result_t, op, lhs_t, rhs_t, fcn)\n{\n  printf (\"\\n\" \\\n          \"%s\\n\" \\\n          \"%s (const %s& m1, const %s& m2)\\n\" \\\n          \"{\\n\" \\\n          \"  return do_mm_binary_op<%s::element_type, %s::element_type, %s::element_type> (m1, m2, %s, %s, %s, \\\"%s\\\");\\n\" \\\n          \"}\\n\",\n          result_t, op, lhs_t, rhs_t, result_t, lhs_t, rhs_t,\n          fcn, fcn, fcn, op);\n}\n\nfunction emit_mm_bin_ops (result_t, lhs_t, rhs_t)\n{\n  emit_mm_bin_op(result_t, \"operator +\", lhs_t, rhs_t, \"mx_inline_add\");\n  emit_mm_bin_op(result_t, \"operator -\", lhs_t, rhs_t, \"mx_inline_sub\");\n  emit_mm_bin_op(result_t, \"product\", lhs_t, rhs_t, \"mx_inline_mul\");\n  emit_mm_bin_op(result_t, \"quotient\", lhs_t, rhs_t, \"mx_inline_div\");\n}\n\nfunction emit_bin_ops (sparse, lhs_class, rhs_class,\n                       result_type_1, result_type_2, lhs_type, rhs_type)\n{\n  if (sparse)\n    emit_sparse_bin_ops(lhs_class, rhs_class, result_type_1,\n                        result_type_2, lhs_type, rhs_type);\n else if ((lhs_class == \"DM\" && rhs_class == \"M\") \\\n          || (lhs_class == \"M\" && rhs_class == \"DM\"))\n    emit_dm_bin_ops(lhs_class, rhs_class, result_type_1,\n                    lhs_type, rhs_type);\n  else if (lhs_class == \"M\" && rhs_class == \"M\")\n    emit_mm_bin_ops(result_type_1, lhs_type, rhs_type);\n  else\n    printf (\"%s%s_BIN_OPS (%s, %s, %s)\\n\",\n            lhs_class, rhs_class, result_type_1, lhs_type, rhs_type);\n}\n\nfunction emit_cmp_ops (sparse, lhs_class, rhs_class, lhs_type, rhs_type)\n{\n  if (sparse)\n    printf (\"SPARSE_%s%s_CMP_OPS (%s, %s)\\n\",\n            lhs_class, rhs_class, lhs_type, rhs_type);\n  else\n    printf (\"%s%s_CMP_OPS (%s, %s)\\n\",\n            lhs_class, rhs_class, lhs_type, rhs_type);\n}\n\nfunction emit_eqne_ops (sparse, lhs_class, rhs_class, lhs_type, rhs_type)\n{\n  if (sparse)\n    printf (\"SPARSE_%s%s_EQNE_OPS (%s, %s)\\n\",\n            lhs_class, rhs_class, lhs_type, rhs_type);\n\n  ## No separate eqne ops for full-matrix or vector.\n}\n\nfunction emit_bool_ops (sparse, lhs_class, rhs_class, lhs_type, rhs_type)\n{\n  if (sparse)\n    printf (\"SPARSE_%s%s_BOOL_OPS (%s, %s)\\n\",\n            lhs_class, rhs_class, lhs_type, rhs_type);\n  else\n    printf (\"%s%s_BOOL_OPS (%s, %s)\\n\",\n            lhs_class, rhs_class, lhs_type, rhs_type);\n}\n"
  },
  {
    "path": "liboctave/operators/module.mk",
    "content": "include %reldir%/vx-op-inc.mk\ninclude %reldir%/mx-op-inc.mk\ninclude %reldir%/smx-op-inc.mk\n\ninclude %reldir%/vx-op-src.mk\ninclude %reldir%/mx-op-src.mk\ninclude %reldir%/smx-op-src.mk\n\nOP_MK_FILES := \\\n  $(srcdir)/%reldir%/vx-op-inc.mk \\\n  $(srcdir)/%reldir%/mx-op-inc.mk \\\n  $(srcdir)/%reldir%/smx-op-inc.mk \\\n  $(srcdir)/%reldir%/vx-op-src.mk \\\n  $(srcdir)/%reldir%/mx-op-src.mk \\\n  $(srcdir)/%reldir%/smx-op-src.mk\n\n$(OP_MK_FILES) : %.mk : $(srcdir)/%reldir%/config-ops.sh $(srcdir)/%reldir%/mk-ops.awk\n\t$(AM_V_GEN)$(SHELL) $(srcdir)/%reldir%/config-ops.sh $(top_srcdir) `echo $(*F) | $(SED) 's/-op-.*//'` `echo $(*F) | $(SED) 's/.*-op-//'`\n\n\nBUILT_LIBOCTAVE_OPERATORS_SOURCES = \\\n  $(MX_OP_SRC) \\\n  $(VX_OP_SRC) \\\n  $(SMX_OP_SRC)\n\nBUILT_LIBOCTAVE_OPERATORS_INC = \\\n  %reldir%/mx-ops.h \\\n  %reldir%/smx-ops.h \\\n  %reldir%/vx-ops.h \\\n  $(MX_OP_INC) \\\n  $(VX_OP_INC) \\\n  $(SMX_OP_INC)\n\nBUILT_LIBOCTAVE_OPERATORS_FILES = \\\n  $(BUILT_LIBOCTAVE_OPERATORS_SOURCES) \\\n  $(BUILT_LIBOCTAVE_OPERATORS_INC)\n\nBUILT_FULL_MATRIX_OPERATORS_FILES = \\\n  %reldir%/mx-ops.h \\\n  $(MX_OP_INC) \\\n  $(MX_OP_SRC)\n\nBUILT_SPARSE_MATRIX_OPERATORS_FILES = \\\n  %reldir%/smx-ops.h \\\n  $(SMX_OP_INC) \\\n  $(SMX_OP_SRC)\n\nBUILT_VECTOR_OPERATORS_FILES = \\\n  %reldir%/vx-ops.h \\\n  $(VX_OP_INC) \\\n  $(VX_OP_SRC)\n\nLIBOCTAVE_OPERATORS_INC = \\\n  %reldir%/mx-base.h \\\n  %reldir%/mx-defs.h \\\n  %reldir%/mx-ext.h \\\n  %reldir%/mx-op-decl.h \\\n  %reldir%/mx-op-defs.h \\\n  %reldir%/Sparse-diag-op-defs.h \\\n  %reldir%/Sparse-op-decls.h \\\n  %reldir%/Sparse-op-defs.h \\\n  %reldir%/Sparse-perm-op-defs.h\n\n## There are no distributed source files in this directory\nLIBOCTAVE_OPERATORS_SRC =\n\nLIBOCTAVE_TEMPLATE_SRC += \\\n  %reldir%/mx-inlines.cc\n\n## Special rules for sources which must be built before rest of compilation.\n\nOP_SRCDIR = $(srcdir)/%reldir%\n\ndefine run-mk-ops\n  rm -f $@-t $@ && \\\n  $(AWK) -f $(OP_SRCDIR)/mk-ops.awk -v build_file=$(notdir $@) $< > $@-t && \\\n  mv $@-t $@\nendef\n\n$(BUILT_FULL_MATRIX_OPERATORS_FILES): %reldir%/mx-ops %reldir%/mk-ops.awk\n\t$(AM_V_GEN)$(run-mk-ops)\n\n$(BUILT_SPARSE_MATRIX_OPERATORS_FILES): %reldir%/smx-ops %reldir%/mk-ops.awk\n\t$(AM_V_GEN)$(run-mk-ops)\n\n$(BUILT_VECTOR_OPERATORS_FILES): %reldir%/vx-ops %reldir%/mk-ops.awk\n\t$(AM_V_GEN)$(run-mk-ops)\n\nnoinst_LTLIBRARIES += %reldir%/liboperators.la\n\n%canon_reldir%_liboperators_la_SOURCES = $(LIBOCTAVE_OPERATORS_SRC)\n\nnodist_%canon_reldir%_liboperators_la_SOURCES = $(BUILT_LIBOCTAVE_OPERATORS_SOURCES)\n\n%canon_reldir%_liboperators_la_CPPFLAGS = $(liboctave_liboctave_la_CPPFLAGS)\n\nliboctave_liboctave_la_LIBADD += %reldir%/liboperators.la\n\nliboctave_EXTRA_DIST += \\\n  %reldir%/config-ops.sh \\\n  %reldir%/mk-ops.awk \\\n  %reldir%/mx-ops \\\n  %reldir%/smx-ops \\\n  %reldir%/vx-ops\n\nliboctave_CLEANFILES += \\\n  $(BUILT_LIBOCTAVE_OPERATORS_FILES)\n"
  },
  {
    "path": "liboctave/operators/mx-base.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mx_base_h)\n#define octave_mx_base_h 1\n\n#include \"octave-config.h\"\n\n// Matrix Type class\n\n#include \"MatrixType.h\"\n\n// Matrix classes.\n\n#include \"boolMatrix.h\"\n#include \"chMatrix.h\"\n#include \"dMatrix.h\"\n#include \"CMatrix.h\"\n#include \"fMatrix.h\"\n#include \"fCMatrix.h\"\n\n// Column Vector classes.\n\n#include \"dColVector.h\"\n#include \"CColVector.h\"\n#include \"fColVector.h\"\n#include \"fCColVector.h\"\n\n// Row Vector classes.\n\n#include \"dRowVector.h\"\n#include \"CRowVector.h\"\n#include \"fRowVector.h\"\n#include \"fCRowVector.h\"\n\n// Diagonal Matrix classes.\n\n#include \"dDiagMatrix.h\"\n#include \"CDiagMatrix.h\"\n#include \"fDiagMatrix.h\"\n#include \"fCDiagMatrix.h\"\n\n// Permutation matrix class\n#include \"PermMatrix.h\"\n\n// Sparse Matrix classes.\n\n#include \"boolSparse.h\"\n#include \"dSparse.h\"\n#include \"CSparse.h\"\n\n// N-D Array classes.\n\n#include \"boolNDArray.h\"\n#include \"chNDArray.h\"\n#include \"dNDArray.h\"\n#include \"CNDArray.h\"\n#include \"fNDArray.h\"\n#include \"fCNDArray.h\"\n\n#include \"int8NDArray.h\"\n#include \"int16NDArray.h\"\n#include \"int32NDArray.h\"\n#include \"int64NDArray.h\"\n\n#include \"uint8NDArray.h\"\n#include \"uint16NDArray.h\"\n#include \"uint32NDArray.h\"\n#include \"uint64NDArray.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/mx-defs.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mx_defs_h)\n#define octave_mx_defs_h 1\n\n#include \"octave-config.h\"\n\n// Classes we declare.\n\n#include \"mx-fwd.h\"\n\ntemplate <typename T> class aepbalance;\n\ntemplate <typename T> class gepbalance;\n\ntemplate <typename T> class chol;\n\nclass EIG;\n\ntemplate <typename T> class gsvd;\n\ntemplate <typename T> class hess;\n\ntemplate <typename T> class schur;\n\ntemplate <typename T> class svd;\n\ntemplate <typename T> class lu;\n\ntemplate <typename T> class qr;\n\ntemplate <typename T> class qrp;\n\n// Other data types we use but that don't always need to have full\n// declarations.\n\n#include \"oct-cmplx.h\"\n\n#if ! defined (MAPPER_FCN_TYPEDEFS)\n#  define MAPPER_FCN_TYPEDEFS 1\n\nenum blas_trans_type\n{\n  blas_no_trans = 'N',\n  blas_trans = 'T',\n  blas_conj_trans = 'C'\n};\n\ninline char\nget_blas_char (blas_trans_type transt)\n{\n  return static_cast<char> (transt);\n}\n\n#  endif\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/mx-ext.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1994-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mx_ext_h)\n#define octave_mx_ext_h 1\n\n#include \"octave-config.h\"\n\n// Result of a AEP Balance operation.\n\n#include \"aepbalance.h\"\n\n// Result of a GEP Balance operation.\n\n#include \"gepbalance.h\"\n\n// Result of a Determinant calculation.\n\n#include \"DET.h\"\n\n// Result of a Cholesky Factorization\n\n#include \"chol.h\"\n\n// Result of a Hessenberg Decomposition\n\n#include \"hess.h\"\n\n// Result of a Schur Decomposition\n\n#include \"schur.h\"\n\n// Result of a Singular Value Decomposition.\n\n#include \"svd.h\"\n\n// Result of an Eigenvalue computation.\n\n#include \"EIG.h\"\n\n// Result of a Generalized Singular Value Decomposition.\n\n#include \"gsvd.h\"\n\n\n// Result of an LU decomposition.\n\n#include \"lu.h\"\n\n// Result of a QR decomposition.\n\n#include \"qr.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/mx-inlines.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mx_inlines_h)\n#define octave_mx_inlines_h 1\n\n// This file should *not* include config.h.  It is only included in other C++\n// source files that should have included config.h before including this file.\n\n#include <cstddef>\n#include <cmath>\n\n#include <algorithm>\n#include <limits>\n\n#include \"Array-util.h\"\n#include \"Array-oct.h\"\n#include \"bsxfun.h\"\n#include \"oct-cmplx.h\"\n#include \"oct-inttypes-fwd.h\"\n#include \"oct-locbuf.h\"\n\n// Provides some commonly repeated, basic loop templates.\n\ntemplate <typename R, typename S>\ninline void\nmx_inline_fill (std::size_t n, R *r, S s)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = s;\n}\n\ntemplate <typename R, typename X>\ninline void\nmx_inline_uminus (std::size_t n, R *r, const X *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = -x[i];\n}\n\ntemplate <typename R>\ninline void\nmx_inline_uminus2 (std::size_t n, R *r)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = -r[i];\n}\n\ntemplate <typename X>\ninline void\nmx_inline_iszero (std::size_t n, bool *r, const X *x)\n{\n  const X zero = X ();\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = x[i] == zero;\n}\n\ntemplate <typename X>\ninline void\nmx_inline_notzero (std::size_t n, bool *r, const X *x)\n{\n  const X zero = X ();\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = x[i] != zero;\n}\n\n#define DEFMXBINOP(F, OP)                                       \\\n  template <typename R, typename X, typename Y>                 \\\n  inline void F (std::size_t n, R *r, const X *x, const Y *y)   \\\n  {                                                             \\\n    for (std::size_t i = 0; i < n; i++)                         \\\n      r[i] = x[i] OP y[i];                                      \\\n  }                                                             \\\n  template <typename R, typename X, typename Y>                 \\\n  inline void F (std::size_t n, R *r, const X *x, Y y)          \\\n  {                                                             \\\n    for (std::size_t i = 0; i < n; i++)                         \\\n      r[i] = x[i] OP y;                                         \\\n  }                                                             \\\n  template <typename R, typename X, typename Y>                 \\\n  inline void F (std::size_t n, R *r, X x, const Y *y)          \\\n  {                                                             \\\n    for (std::size_t i = 0; i < n; i++)                         \\\n      r[i] = x OP y[i];                                         \\\n  }\n\nDEFMXBINOP (mx_inline_add, +)\nDEFMXBINOP (mx_inline_sub, -)\nDEFMXBINOP (mx_inline_mul, *)\nDEFMXBINOP (mx_inline_div, /)\n\n#define DEFMXBINOPEQ(F, OP)                             \\\n  template <typename R, typename X>                     \\\n  inline void F (std::size_t n, R *r, const X *x)       \\\n  {                                                     \\\n    for (std::size_t i = 0; i < n; i++)                 \\\n      r[i] OP x[i];                                     \\\n  }                                                     \\\n  template <typename R, typename X>                     \\\n  inline void F (std::size_t n, R *r, X x)              \\\n  {                                                     \\\n    for (std::size_t i = 0; i < n; i++)                 \\\n      r[i] OP x;                                        \\\n  }\n\nDEFMXBINOPEQ (mx_inline_add2, +=)\nDEFMXBINOPEQ (mx_inline_sub2, -=)\nDEFMXBINOPEQ (mx_inline_mul2, *=)\nDEFMXBINOPEQ (mx_inline_div2, /=)\n\n#define DEFMXCMPOP(F, OP)                                               \\\n  template <typename X, typename Y>                                     \\\n  inline void F (std::size_t n, bool *r, const X *x, const Y *y)        \\\n  {                                                                     \\\n    for (std::size_t i = 0; i < n; i++)                                 \\\n      r[i] = x[i] OP y[i];                                              \\\n  }                                                                     \\\n  template <typename X, typename Y>                                     \\\n  inline void F (std::size_t n, bool *r, const X *x, Y y)               \\\n  {                                                                     \\\n    for (std::size_t i = 0; i < n; i++)                                 \\\n      r[i] = x[i] OP y;                                                 \\\n  }                                                                     \\\n  template <typename X, typename Y>                                     \\\n  inline void F (std::size_t n, bool *r, X x, const Y *y)               \\\n  {                                                                     \\\n    for (std::size_t i = 0; i < n; i++)                                 \\\n      r[i] = x OP y[i];                                                 \\\n  }\n\nDEFMXCMPOP (mx_inline_lt, <)\nDEFMXCMPOP (mx_inline_le, <=)\nDEFMXCMPOP (mx_inline_gt, >)\nDEFMXCMPOP (mx_inline_ge, >=)\nDEFMXCMPOP (mx_inline_eq, ==)\nDEFMXCMPOP (mx_inline_ne, !=)\n\n// Convert to logical value, for logical op purposes.\ntemplate <typename T>\ninline bool\nlogical_value (T x)\n{\n  return x;\n}\n\ntemplate <typename T>\ninline bool\nlogical_value (const std::complex<T>& x)\n{\n  return x.real () != 0 || x.imag () != 0;\n}\n\ntemplate <typename T>\ninline bool\nlogical_value (const octave_int<T>& x)\n{\n  return x.value ();\n}\n\ntemplate <typename X>\nvoid\nmx_inline_not (std::size_t n, bool *r, const X *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = ! logical_value (x[i]);\n}\n\ninline void\nmx_inline_not2 (std::size_t n, bool *r)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = ! r[i];\n}\n\n#define DEFMXBOOLOP(F, NOT1, OP, NOT2)                                  \\\n  template <typename X, typename Y>                                     \\\n  inline void F (std::size_t n, bool *r, const X *x, const Y *y)        \\\n  {                                                                     \\\n    for (std::size_t i = 0; i < n; i++)                                 \\\n      r[i] = ((NOT1 logical_value (x[i]))                               \\\n              OP (NOT2 logical_value (y[i])));                          \\\n  }                                                                     \\\n  template <typename X, typename Y>                                     \\\n  inline void F (std::size_t n, bool *r, const X *x, Y y)               \\\n  {                                                                     \\\n    const bool yy = (NOT2 logical_value (y));                           \\\n    for (std::size_t i = 0; i < n; i++)                                 \\\n      r[i] = (NOT1 logical_value (x[i])) OP yy;                         \\\n  }                                                                     \\\n  template <typename X, typename Y>                                     \\\n  inline void F (std::size_t n, bool *r, X x, const Y *y)               \\\n  {                                                                     \\\n    const bool xx = (NOT1 logical_value (x));                           \\\n    for (std::size_t i = 0; i < n; i++)                                 \\\n      r[i] = xx OP (NOT2 logical_value (y[i]));                         \\\n  }\n\nDEFMXBOOLOP (mx_inline_and, , &&, )\nDEFMXBOOLOP (mx_inline_or, , ||, )\nDEFMXBOOLOP (mx_inline_not_and, !, &&, )\nDEFMXBOOLOP (mx_inline_not_or, !, ||, )\nDEFMXBOOLOP (mx_inline_and_not, , &&, !)\nDEFMXBOOLOP (mx_inline_or_not, , ||, !)\n\ntemplate <typename X>\ninline void\nmx_inline_and2 (std::size_t n, bool *r, const X *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] &= logical_value (x[i]);\n}\n\ntemplate <typename X>\ninline void\nmx_inline_and2 (std::size_t n, bool *r, X x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] &= x;\n}\n\ntemplate <typename X>\ninline void\nmx_inline_or2 (std::size_t n, bool *r, const X *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] |= logical_value (x[i]);\n}\n\ntemplate <typename X>\ninline void\nmx_inline_or2 (std::size_t n, bool *r, X x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] |= x;\n}\n\ntemplate <typename T>\ninline bool\nmx_inline_any_nan (std::size_t n, const T *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    {\n      if (octave::math::isnan (x[i]))\n        return true;\n    }\n\n  return false;\n}\n\ntemplate <typename T>\ninline bool\nmx_inline_all_finite (std::size_t n, const T *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    {\n      if (! octave::math::isfinite (x[i]))\n        return false;\n    }\n\n  return true;\n}\n\ntemplate <typename T>\ninline bool\nmx_inline_any_negative (std::size_t n, const T *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    {\n      if (x[i] < 0)\n        return true;\n    }\n\n  return false;\n}\n\ntemplate <typename T>\ninline bool\nmx_inline_any_positive (std::size_t n, const T *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    {\n      if (x[i] > 0)\n        return true;\n    }\n\n  return false;\n}\n\ntemplate <typename T>\ninline bool\nmx_inline_all_real (std::size_t n, const std::complex<T> *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    {\n      if (x[i].imag () != 0)\n        return false;\n    }\n\n  return true;\n}\n\ntemplate <typename T>\ninline void\nmx_inline_real (std::size_t n, T *r, const std::complex<T> *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = x[i].real ();\n}\n\ntemplate <typename T>\ninline void\nmx_inline_imag (std::size_t n, T *r, const std::complex<T> *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = x[i].imag ();\n}\n\n\ntemplate <typename T>\ninline void\nmx_inline_xmin (std::size_t n, T *r, const T *x, const T *y)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::min (x[i], y[i]);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmin (std::size_t n, T *r, const T *x, const T *y, const bool nanflag)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::min (x[i], y[i], nanflag);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmin (std::size_t n, T *r, const T *x, const T *y,\n                const bool nanflag, const bool realabs)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::min (x[i], y[i], nanflag, realabs);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmin (std::size_t n, T *r, const T *x, T y)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::min (x[i], y);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmin (std::size_t n, T *r, const T *x, T y, const bool nanflag)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::min (x[i], y, nanflag);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmin (std::size_t n, T *r, const T *x, T y,\n                const bool nanflag, const bool realabs)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::min (x[i], y, nanflag, realabs);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmin (std::size_t n, T *r, T x, const T *y)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::min (x, y[i]);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmin (std::size_t n, T *r, T x, const T *y, const bool nanflag)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::min (x, y[i], nanflag);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmin (std::size_t n, T *r, T x, const T *y,\n                const bool nanflag, const bool realabs)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::min (x, y[i], nanflag, realabs);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmax (std::size_t n, T *r, const T *x, const T *y)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::max (x[i], y[i]);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmax (std::size_t n, T *r, const T *x, const T *y, const bool nanflag)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::max (x[i], y[i], nanflag);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmax (std::size_t n, T *r, const T *x, const T *y,\n                const bool nanflag, const bool realabs)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::max (x[i], y[i], nanflag, realabs);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmax (std::size_t n, T *r, const T *x, T y)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::max (x[i], y);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmax (std::size_t n, T *r, const T *x, T y, const bool nanflag)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::max (x[i], y, nanflag);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmax (std::size_t n, T *r, const T *x, T y,\n                const bool nanflag, const bool realabs)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::max (x[i], y, nanflag, realabs);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmax (std::size_t n, T *r, T x, const T *y)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::max (x, y[i]);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmax (std::size_t n, T *r, T x, const T *y, const bool nanflag)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::max (x, y[i], nanflag);\n}\n\ntemplate <typename T>\ninline void\nmx_inline_xmax (std::size_t n, T *r, T x, const T *y,\n                const bool nanflag, const bool realabs)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = octave::math::max (x, y[i], nanflag, realabs);\n}\n\n// FIXME: Is this comment correct anymore?  It seems like std::pow is chosen.\n// Let the compiler decide which pow to use, whichever best matches the\n// arguments provided.\n\ntemplate <typename R, typename X, typename Y>\ninline void\nmx_inline_pow (std::size_t n, R *r, const X *x, const Y *y)\n{\n  using std::pow;\n\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = pow (x[i], y[i]);\n}\n\ntemplate <typename R, typename X, typename Y>\ninline void\nmx_inline_pow (std::size_t n, R *r, const X *x, Y y)\n{\n  using std::pow;\n\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = pow (x[i], y);\n}\n\ntemplate <typename R, typename X, typename Y>\ninline void\nmx_inline_pow (std::size_t n, R *r, X x, const Y *y)\n{\n  using std::pow;\n\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = pow (x, y[i]);\n}\n\n// Arbitrary function appliers.\n// The function is a template parameter to enable inlining.\ntemplate <typename R, typename X, R fcn (X x)>\ninline void\nmx_inline_map (std::size_t n, R *r, const X *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = fcn (x[i]);\n}\n\ntemplate <typename R, typename X, R fcn (const X& x)>\ninline void\nmx_inline_map (std::size_t n, R *r, const X *x)\n{\n  for (std::size_t i = 0; i < n; i++)\n    r[i] = fcn (x[i]);\n}\n\n// Appliers.  Since these call the operation just once, we pass it as\n// a pointer, to allow the compiler reduce number of instances.\n\ntemplate <typename R, typename X>\ninline Array<R>\ndo_mx_unary_op (const Array<X>& x,\n                void (*op) (std::size_t, R *, const X *))\n{\n  Array<R> r (x.dims ());\n  op (r.numel (), r.rwdata (), x.data ());\n  return r;\n}\n\n// Shortcuts for applying mx_inline_map.\n\ntemplate <typename R, typename X, R fcn (X)>\ninline Array<R>\ndo_mx_unary_map (const Array<X>& x)\n{\n  return do_mx_unary_op<R, X> (x, mx_inline_map<R, X, fcn>);\n}\n\ntemplate <typename R, typename X, R fcn (const X&)>\ninline Array<R>\ndo_mx_unary_map (const Array<X>& x)\n{\n  return do_mx_unary_op<R, X> (x, mx_inline_map<R, X, fcn>);\n}\n\ntemplate <typename R>\ninline Array<R>&\ndo_mx_inplace_op (Array<R>& r,\n                  void (*op) (std::size_t, R *))\n{\n  op (r.numel (), r.rwdata ());\n  return r;\n}\n\ntemplate <typename R, typename X, typename Y>\ninline Array<R>\ndo_mm_binary_op (const Array<X>& x, const Array<Y>& y,\n                 void (*op) (std::size_t, R *, const X *, const Y *),\n                 void (*op1) (std::size_t, R *, X, const Y *),\n                 void (*op2) (std::size_t, R *, const X *, Y),\n                 const char *opname)\n{\n  const dim_vector& dx = x.dims ();\n  const dim_vector& dy = y.dims ();\n  if (dx == dy)\n    {\n      Array<R> r (dx);\n      op (r.numel (), r.rwdata (), x.data (), y.data ());\n      return r;\n    }\n  else if (is_valid_bsxfun (dx, dy))\n    {\n      return do_bsxfun_op (x, y, op, op1, op2);\n    }\n  else\n    octave::err_nonconformant (opname, dx, dy);\n}\n\ntemplate <typename R, typename X, typename Y>\ninline Array<R>\ndo_ms_binary_op (const Array<X>& x, const Y& y,\n                 void (*op) (std::size_t, R *, const X *, Y))\n{\n  Array<R> r (x.dims ());\n  op (r.numel (), r.rwdata (), x.data (), y);\n  return r;\n}\n\ntemplate <typename R, typename X, typename Y>\ninline Array<R>\ndo_sm_binary_op (const X& x, const Array<Y>& y,\n                 void (*op) (std::size_t, R *, X, const Y *))\n{\n  Array<R> r (y.dims ());\n  op (r.numel (), r.rwdata (), x, y.data ());\n  return r;\n}\n\n// These are required for min/max binary operations with extra\n// nanflag and realabs arguments\n\ntemplate <typename R, typename X, typename Y>\ninline Array<R>\ndo_mm_binary_op (const Array<X>& x, const Array<Y>& y, bool nanflag,\n                 void (*op) (std::size_t, R *, const X *, const Y *, bool),\n                 void (*op1) (std::size_t, R *, X, const Y *, bool),\n                 void (*op2) (std::size_t, R *, const X *, Y, bool),\n                 const char *opname)\n{\n  const dim_vector& dx = x.dims ();\n  const dim_vector& dy = y.dims ();\n  if (dx == dy)\n    {\n      Array<R> r (dx);\n      op (r.numel (), r.rwdata (), x.data (), y.data (), nanflag);\n      return r;\n    }\n  else if (is_valid_bsxfun (dx, dy))\n    {\n      return do_bsxfun1_op (x, y, nanflag, op, op1, op2);\n    }\n  else\n    octave::err_nonconformant (opname, dx, dy);\n}\n\ntemplate <typename R, typename X, typename Y>\ninline Array<R>\ndo_ms_binary_op (const Array<X>& x, const Y& y, bool nanflag,\n                 void (*op) (std::size_t, R *, const X *, Y, bool))\n{\n  Array<R> r (x.dims ());\n  op (r.numel (), r.rwdata (), x.data (), y, nanflag);\n  return r;\n}\n\ntemplate <typename R, typename X, typename Y>\ninline Array<R>\ndo_sm_binary_op (const X& x, const Array<Y>& y, bool nanflag,\n                 void (*op) (std::size_t, R *, X, const Y *, bool))\n{\n  Array<R> r (y.dims ());\n  op (r.numel (), r.rwdata (), x, y.data (), nanflag);\n  return r;\n}\n\ntemplate <typename R, typename X, typename Y>\ninline Array<R>\ndo_mm_binary_op (const Array<X>& x, const Array<Y>& y,\n                 bool nanflag, bool realabs,\n                 void (*op) (std::size_t, R *, const X *, const Y *,\n                             bool, bool),\n                 void (*op1) (std::size_t, R *, X, const Y *, bool, bool),\n                 void (*op2) (std::size_t, R *, const X *, Y, bool, bool),\n                 const char *opname)\n{\n  const dim_vector& dx = x.dims ();\n  const dim_vector& dy = y.dims ();\n  if (dx == dy)\n    {\n      Array<R> r (dx);\n      op (r.numel (), r.rwdata (), x.data (), y.data (), nanflag, realabs);\n      return r;\n    }\n  else if (is_valid_bsxfun (dx, dy))\n    {\n      return do_bsxfun2_op (x, y, nanflag, realabs, op, op1, op2);\n    }\n  else\n    octave::err_nonconformant (opname, dx, dy);\n}\n\ntemplate <typename R, typename X, typename Y>\ninline Array<R>\ndo_ms_binary_op (const Array<X>& x, const Y& y, bool nanflag, bool realabs,\n                 void (*op) (std::size_t, R *, const X *, Y, bool, bool))\n{\n  Array<R> r (x.dims ());\n  op (r.numel (), r.rwdata (), x.data (), y, nanflag, realabs);\n  return r;\n}\n\ntemplate <typename R, typename X, typename Y>\ninline Array<R>\ndo_sm_binary_op (const X& x, const Array<Y>& y, bool nanflag, bool realabs,\n                 void (*op) (std::size_t, R *, X, const Y *, bool, bool))\n{\n  Array<R> r (y.dims ());\n  op (r.numel (), r.rwdata (), x, y.data (), nanflag, realabs);\n  return r;\n}\n\ntemplate <typename R, typename X>\ninline Array<R>&\ndo_mm_inplace_op (Array<R>& r, const Array<X>& x,\n                  void (*op) (std::size_t, R *, const X *),\n                  void (*op1) (std::size_t, R *, X),\n                  const char *opname)\n{\n  const dim_vector& dr = r.dims ();\n  const dim_vector& dx = x.dims ();\n  if (dr == dx)\n    op (r.numel (), r.rwdata (), x.data ());\n  else if (is_valid_inplace_bsxfun (dr, dx))\n    do_inplace_bsxfun_op (r, x, op, op1);\n  else\n    octave::err_nonconformant (opname, dr, dx);\n\n  return r;\n}\n\ntemplate <typename R, typename X>\ninline Array<R>&\ndo_ms_inplace_op (Array<R>& r, const X& x,\n                  void (*op) (std::size_t, R *, X))\n{\n  op (r.numel (), r.rwdata (), x);\n  return r;\n}\n\ntemplate <typename T1, typename T2>\ninline bool\nmx_inline_equal (std::size_t n, const T1 *x, const T2 *y)\n{\n  for (std::size_t i = 0; i < n; i++)\n    if (x[i] != y[i])\n      return false;\n  return true;\n}\n\ntemplate <typename T>\ninline bool\ndo_mx_check (const Array<T>& a,\n             bool (*op) (std::size_t, const T *))\n{\n  return op (a.numel (), a.data ());\n}\n\n// NOTE: we don't use std::norm because it typically does some heavyweight\n// magic to avoid underflows, which we don't need here.\ntemplate <typename T>\ninline T\ncabsq (const std::complex<T>& c)\n{\n  return c.real () * c.real () + c.imag () * c.imag ();\n}\n\n// default.  works for integers and bool.\ntemplate <typename T>\ninline bool\nxis_true (T x)\n{\n  return x;\n}\n\ntemplate <typename T>\ninline bool\nxis_false (T x)\n{\n  return ! x;\n}\n\n// for octave_ints\ntemplate <typename T>\ninline bool\nxis_true (const octave_int<T>& x)\n{\n  return x.value ();\n}\n\ntemplate <typename T>\ninline bool\nxis_false (const octave_int<T>& x)\n{\n  return ! x.value ();\n}\n\n// for reals, we want to ignore NaNs.\ninline bool\nxis_true (double x)\n{\n  return ! octave::math::isnan (x) && x != 0.0;\n}\n\ninline bool\nxis_false (double x)\n{\n  return x == 0.0;\n}\n\ninline bool\nxis_true (float x)\n{\n  return ! octave::math::isnan (x) && x != 0.0f;\n}\n\ninline bool\nxis_false (float x)\n{\n  return x == 0.0f;\n}\n\n// Ditto for complex.\ninline bool\nxis_true (const Complex& x)\n{\n  return ! octave::math::isnan (x) && x != 0.0;\n}\n\ninline bool\nxis_false (const Complex& x)\n{\n  return x == 0.0;\n}\n\ninline bool\nxis_true (const FloatComplex& x)\n{\n  return ! octave::math::isnan (x) && x != 0.0f;\n}\n\ninline bool\nxis_false (const FloatComplex& x)\n{\n  return x == 0.0f;\n}\n\n#define OP_RED_SUM(ac, el) ac += el\n#define OP_RED_PROD(ac, el) ac *= el\n#define OP_RED_SUMSQ(ac, el) ac += ((el)*(el))\n#define OP_RED_SUMSQC(ac, el) ac += cabsq (el)\n\ninline void\nop_dble_prod (double& ac, float el)\n{\n  ac *= el;\n}\n\n// FIXME: guaranteed?\ninline void\nop_dble_prod (Complex& ac, const FloatComplex& el)\n{\n  ac *= el;\n}\n\ntemplate <typename T>\ninline void\nop_dble_prod (double& ac, const octave_int<T>& el)\n{\n  ac *= el.double_value ();\n}\n\ninline void\nop_dble_sum (double& ac, float el)\n{\n  ac += el;\n}\n\n// FIXME: guaranteed?\ninline void\nop_dble_sum (Complex& ac, const FloatComplex& el)\n{\n  ac += el;\n}\n\ntemplate <typename T>\ninline void\nop_dble_sum (double& ac, const octave_int<T>& el)\n{\n  ac += el.double_value ();\n}\n\n// The following two implement a simple short-circuiting.\n#define OP_RED_ANYC(ac, el)                     \\\n  if (xis_true (el))                            \\\n    {                                           \\\n      ac = true;                                \\\n      break;                                    \\\n    }                                           \\\n  else                                          \\\n    continue\n\n#define OP_RED_ALLC(ac, el)                     \\\n  if (xis_false (el))                           \\\n    {                                           \\\n      ac = false;                               \\\n      break;                                    \\\n    }                                           \\\n  else                                          \\\n    continue\n\n#define OP_RED_FCN(F, TSRC, TRES, OP, ZERO)     \\\n  template <typename T>                         \\\n  inline TRES                                   \\\n  F (const TSRC *v, octave_idx_type n)          \\\n  {                                             \\\n    TRES ac = ZERO;                             \\\n    for (octave_idx_type i = 0; i < n; i++)     \\\n      OP(ac, v[i]);                             \\\n    return ac;                                  \\\n  }\n\n#define PROMOTE_DOUBLE(T)                                       \\\n  typename subst_template_param<std::complex, T, double>::type\n\nOP_RED_FCN (mx_inline_sum, T, T, OP_RED_SUM, 0)\nOP_RED_FCN (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)\nOP_RED_FCN (mx_inline_count, bool, T, OP_RED_SUM, 0)\nOP_RED_FCN (mx_inline_prod, T, T, OP_RED_PROD, 1)\nOP_RED_FCN (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 1.0)\nOP_RED_FCN (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)\nOP_RED_FCN (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)\nOP_RED_FCN (mx_inline_dsumsq, T, PROMOTE_DOUBLE(T), OP_RED_SUMSQ, 0.0)\nOP_RED_FCN (mx_inline_dsumsq, std::complex<T>, PROMOTE_DOUBLE(T), OP_RED_SUMSQC, 0.0)\nOP_RED_FCN (mx_inline_any, T, bool, OP_RED_ANYC, false)\nOP_RED_FCN (mx_inline_all, T, bool, OP_RED_ALLC, true)\n\n#define OP_RED_NAN_FCN(F, TSRC, TRES, OP, ZERO)       \\\n  template <typename T>                               \\\n  inline TRES                                         \\\n  F (const TSRC *v, octave_idx_type n, bool nanflag)  \\\n  {                                                   \\\n    TRES ac = ZERO;                                   \\\n    if (nanflag)                                      \\\n      {                                               \\\n        for (octave_idx_type i = 0; i < n; i++)       \\\n          if (! octave::math::isnan (v[i]))           \\\n              OP(ac, v[i]);                           \\\n      }                                               \\\n    else                                              \\\n      {                                               \\\n        for (octave_idx_type i = 0; i < n; i++)       \\\n          OP(ac, v[i]);                               \\\n      }                                               \\\n    return ac;                                        \\\n  }\n\nOP_RED_NAN_FCN (mx_inline_sum, T, T, OP_RED_SUM, 0)\nOP_RED_NAN_FCN (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)\nOP_RED_NAN_FCN (mx_inline_prod, T, T, OP_RED_PROD, 1)\nOP_RED_NAN_FCN (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 1.0)\nOP_RED_NAN_FCN (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)\nOP_RED_NAN_FCN (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)\nOP_RED_NAN_FCN (mx_inline_dsumsq, T, PROMOTE_DOUBLE(T), OP_RED_SUMSQ, 0.0)\nOP_RED_NAN_FCN (mx_inline_dsumsq, std::complex<T>, PROMOTE_DOUBLE(T), OP_RED_SUMSQC, 0.0)\n\n#define OP_RED_FCN2(F, TSRC, TRES, OP, ZERO)                            \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n)      \\\n  {                                                                     \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      r[i] = ZERO;                                                      \\\n    for (octave_idx_type j = 0; j < n; j++)                             \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < m; i++)                         \\\n          OP(r[i], v[i]);                                               \\\n        v += m;                                                         \\\n      }                                                                 \\\n  }\n\nOP_RED_FCN2 (mx_inline_sum, T, T, OP_RED_SUM, 0)\nOP_RED_FCN2 (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)\nOP_RED_FCN2 (mx_inline_count, bool, T, OP_RED_SUM, 0)\nOP_RED_FCN2 (mx_inline_prod, T, T, OP_RED_PROD, 1)\nOP_RED_FCN2 (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 1.0)\nOP_RED_FCN2 (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)\nOP_RED_FCN2 (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)\nOP_RED_FCN2 (mx_inline_dsumsq, T, PROMOTE_DOUBLE(T), OP_RED_SUMSQ, 0.0)\nOP_RED_FCN2 (mx_inline_dsumsq, std::complex<T>, PROMOTE_DOUBLE(T), OP_RED_SUMSQC, 0.0)\n\n#define OP_RED_NAN_FCN2(F, TSRC, TRES, OP, ZERO)                        \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n,      \\\n     bool nanflag)                                                      \\\n  {                                                                     \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      r[i] = ZERO;                                                      \\\n                                                                        \\\n    if (nanflag)                                                        \\\n      {                                                                 \\\n        /* omitnan: skip NaN, result stays at identity if all NaN */    \\\n        for (octave_idx_type j = 0; j < n; j++)                         \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              if (! octave::math::isnan (v[i]))                         \\\n                OP(r[i], v[i]);                                         \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        /* includenan: NaN propagates naturally */                      \\\n        for (octave_idx_type j = 0; j < n; j++)                         \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              OP(r[i], v[i]);                                           \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_RED_NAN_FCN2 (mx_inline_sum, T, T, OP_RED_SUM, 0)\nOP_RED_NAN_FCN2 (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)\nOP_RED_NAN_FCN2 (mx_inline_prod, T, T, OP_RED_PROD, 1)\nOP_RED_NAN_FCN2 (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 1.0)\nOP_RED_NAN_FCN2 (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)\nOP_RED_NAN_FCN2 (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)\nOP_RED_NAN_FCN2 (mx_inline_dsumsq, T, PROMOTE_DOUBLE(T), OP_RED_SUMSQ, 0.0)\nOP_RED_NAN_FCN2 (mx_inline_dsumsq, std::complex<T>, PROMOTE_DOUBLE(T), OP_RED_SUMSQC, 0.0)\n\n#define OP_RED_ANYR(ac, el) ac |= xis_true (el)\n#define OP_RED_ALLR(ac, el) ac &= xis_true (el)\n\nOP_RED_FCN2 (mx_inline_any_r, T, bool, OP_RED_ANYR, false)\nOP_RED_FCN2 (mx_inline_all_r, T, bool, OP_RED_ALLR, true)\n\n// Using the general code for any/all would sacrifice short-circuiting.\n// OTOH, going by rows would sacrifice cache-coherence.  The following\n// algorithm will achieve both, at the cost of a temporary octave_idx_type\n// array.\n\n#define OP_ROW_SHORT_CIRCUIT(F, PRED, ZERO)                             \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, bool *r, octave_idx_type m, octave_idx_type n)         \\\n  {                                                                     \\\n    if (n <= 8)                                                         \\\n      return F ## _r (v, r, m, n);                                      \\\n                                                                        \\\n    /* FIXME: it may be sub-optimal to allocate the buffer here. */     \\\n    OCTAVE_LOCAL_BUFFER (octave_idx_type, iact, m);                     \\\n    for (octave_idx_type i = 0; i < m; i++) iact[i] = i;                \\\n    octave_idx_type nact = m;                                           \\\n    for (octave_idx_type j = 0; j < n; j++)                             \\\n      {                                                                 \\\n        octave_idx_type k = 0;                                          \\\n        for (octave_idx_type i = 0; i < nact; i++)                      \\\n          {                                                             \\\n            octave_idx_type ia = iact[i];                               \\\n            if (! PRED (v[ia]))                                         \\\n              iact[k++] = ia;                                           \\\n          }                                                             \\\n        nact = k;                                                       \\\n        v += m;                                                         \\\n      }                                                                 \\\n    for (octave_idx_type i = 0; i < m; i++) r[i] = ! ZERO;              \\\n    for (octave_idx_type i = 0; i < nact; i++) r[iact[i]] = ZERO;       \\\n  }\n\nOP_ROW_SHORT_CIRCUIT (mx_inline_any, xis_true, false)\nOP_ROW_SHORT_CIRCUIT (mx_inline_all, xis_false, true)\n\n#define OP_RED_FCNN(F, TSRC, TRES)              \\\n  template <typename T>                         \\\n  inline void                                   \\\n  F (const TSRC *v, TRES *r, octave_idx_type l, \\\n     octave_idx_type n, octave_idx_type u)      \\\n  {                                             \\\n    if (l == 1)                                 \\\n      {                                         \\\n        for (octave_idx_type i = 0; i < u; i++) \\\n          {                                     \\\n            r[i] = F<T> (v, n);                 \\\n            v += n;                             \\\n          }                                     \\\n      }                                         \\\n    else                                        \\\n      {                                         \\\n        for (octave_idx_type i = 0; i < u; i++) \\\n          {                                     \\\n            F (v, r, l, n);                     \\\n            v += l*n;                           \\\n            r += l;                             \\\n          }                                     \\\n      }                                         \\\n  }\n\nOP_RED_FCNN (mx_inline_sum, T, T)\nOP_RED_FCNN (mx_inline_dsum, T, PROMOTE_DOUBLE(T))\nOP_RED_FCNN (mx_inline_count, bool, T)\nOP_RED_FCNN (mx_inline_prod, T, T)\nOP_RED_FCNN (mx_inline_dprod, T, PROMOTE_DOUBLE(T))\nOP_RED_FCNN (mx_inline_sumsq, T, T)\nOP_RED_FCNN (mx_inline_sumsq, std::complex<T>, T)\nOP_RED_FCNN (mx_inline_dsumsq, T, PROMOTE_DOUBLE(T))\nOP_RED_FCNN (mx_inline_dsumsq, std::complex<T>, PROMOTE_DOUBLE(T))\nOP_RED_FCNN (mx_inline_any, T, bool)\nOP_RED_FCNN (mx_inline_all, T, bool)\n\n#define OP_RED_NAN_FCNN(F, TSRC, TRES)                   \\\n  template <typename T>                                  \\\n  inline void                                            \\\n  F (const TSRC *v, TRES *r, octave_idx_type l,          \\\n     octave_idx_type n, octave_idx_type u, bool nanflag) \\\n  {                                                      \\\n    if (l == 1)                                          \\\n      {                                                  \\\n        for (octave_idx_type i = 0; i < u; i++)          \\\n          {                                              \\\n            r[i] = F<T> (v, n, nanflag);                 \\\n            v += n;                                      \\\n          }                                              \\\n      }                                                  \\\n    else                                                 \\\n      {                                                  \\\n        for (octave_idx_type i = 0; i < u; i++)          \\\n          {                                              \\\n            F (v, r, l, n, nanflag);                     \\\n            v += l*n;                                    \\\n            r += l;                                      \\\n          }                                              \\\n      }                                                  \\\n  }\n\nOP_RED_NAN_FCNN (mx_inline_sum, T, T)\nOP_RED_NAN_FCNN (mx_inline_dsum, T, PROMOTE_DOUBLE(T))\nOP_RED_NAN_FCNN (mx_inline_prod, T, T)\nOP_RED_NAN_FCNN (mx_inline_dprod, T, PROMOTE_DOUBLE(T))\nOP_RED_NAN_FCNN (mx_inline_sumsq, T, T)\nOP_RED_NAN_FCNN (mx_inline_sumsq, std::complex<T>, T)\nOP_RED_NAN_FCNN (mx_inline_dsumsq, T, PROMOTE_DOUBLE(T))\nOP_RED_NAN_FCNN (mx_inline_dsumsq, std::complex<T>, PROMOTE_DOUBLE(T))\n\n#define OP_CUM_FCN(F, TSRC, TRES, OP)           \\\n  template <typename T>                         \\\n  inline void                                   \\\n  F (const TSRC *v, TRES *r, octave_idx_type n) \\\n  {                                             \\\n    if (n)                                      \\\n      {                                         \\\n        TRES t = r[0] = v[0];                   \\\n        for (octave_idx_type i = 1; i < n; i++) \\\n          r[i] = t = t OP v[i];                 \\\n      }                                         \\\n  }\n\nOP_CUM_FCN (mx_inline_cumsum, T, T, +)\nOP_CUM_FCN (mx_inline_cumprod, T, T, *)\nOP_CUM_FCN (mx_inline_cumcount, bool, T, +)\n\n#define OP_CUM_NAN_FCN(F, TSRC, TRES, OP, ZERO)               \\\n  template <typename T>                                       \\\n  inline void                                                 \\\n  F (const TSRC *v, TRES *r, octave_idx_type n, bool nanflag) \\\n  {                                                           \\\n    if (n)                                                    \\\n      {                                                       \\\n        if (nanflag)                                          \\\n          {                                                   \\\n            TRES z = ZERO;                                    \\\n            TRES t;                                           \\\n            if (octave::math::isnan (v[0]))                   \\\n              t = r[0] = z;                                   \\\n            else                                              \\\n              t = r[0] = v[0];                                \\\n            for (octave_idx_type i = 1; i < n; i++)           \\\n              {                                               \\\n                if (octave::math::isnan (v[i]))               \\\n                  r[i] = t = t OP z;                          \\\n                else                                          \\\n                  r[i] = t = t OP v[i];                       \\\n              }                                               \\\n          }                                                   \\\n        else                                                  \\\n          {                                                   \\\n            TRES t = r[0] = v[0];                             \\\n            for (octave_idx_type i = 1; i < n; i++)           \\\n              r[i] = t = t OP v[i];                           \\\n          }                                                   \\\n      }                                                       \\\n  }\n\nOP_CUM_NAN_FCN (mx_inline_cumsum, T, T, +, 0.0)\nOP_CUM_NAN_FCN (mx_inline_cumprod, T, T, *, 1.0)\n\n#define OP_CUM_FCN2(F, TSRC, TRES, OP)                                  \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n)      \\\n  {                                                                     \\\n    if (n)                                                              \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < m; i++)                         \\\n          r[i] = v[i];                                                  \\\n        const T *r0 = r;                                                \\\n        for (octave_idx_type j = 1; j < n; j++)                         \\\n          {                                                             \\\n            r += m; v += m;                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              r[i] = r0[i] OP v[i];                                     \\\n            r0 += m;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_CUM_FCN2 (mx_inline_cumsum, T, T, +)\nOP_CUM_FCN2 (mx_inline_cumprod, T, T, *)\nOP_CUM_FCN2 (mx_inline_cumcount, bool, T, +)\n\n#define OP_CUM_NAN_FCN2(F, TSRC, TRES, OP, ZERO)                        \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n,      \\\n     bool nanflag)                                                      \\\n  {                                                                     \\\n    if (n)                                                              \\\n      {                                                                 \\\n        if (nanflag)                                                    \\\n          {                                                             \\\n            TRES z = ZERO;                                              \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (v[i]))                         \\\n                  r[i] = z;                                             \\\n                else                                                    \\\n                  r[i] = v[i];                                          \\\n              }                                                         \\\n            const T *r0 = r;                                            \\\n            for (octave_idx_type j = 1; j < n; j++)                     \\\n              {                                                         \\\n                r += m; v += m;                                         \\\n                for (octave_idx_type i = 0; i < m; i++)                 \\\n                  {                                                     \\\n                    if (octave::math::isnan (v[i]))                     \\\n                      r[i] = r0[i] OP z;                                \\\n                    else                                                \\\n                      r[i] = r0[i] OP v[i];                             \\\n                  }                                                     \\\n                r0 += m;                                                \\\n              }                                                         \\\n          }                                                             \\\n        else                                                            \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              r[i] = v[i];                                              \\\n            const T *r0 = r;                                            \\\n            for (octave_idx_type j = 1; j < n; j++)                     \\\n              {                                                         \\\n                r += m; v += m;                                         \\\n                for (octave_idx_type i = 0; i < m; i++)                 \\\n                  r[i] = r0[i] OP v[i];                                 \\\n                r0 += m;                                                \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_CUM_NAN_FCN2 (mx_inline_cumsum, T, T, +, 0.0)\nOP_CUM_NAN_FCN2 (mx_inline_cumprod, T, T, *, 1.0)\n\n#define OP_CUM_FCNN(F, TSRC, TRES)              \\\n  template <typename T>                         \\\n  inline void                                   \\\n  F (const TSRC *v, TRES *r, octave_idx_type l, \\\n     octave_idx_type n, octave_idx_type u)      \\\n  {                                             \\\n    if (l == 1)                                 \\\n      {                                         \\\n        for (octave_idx_type i = 0; i < u; i++) \\\n          {                                     \\\n            F (v, r, n);                        \\\n            v += n;                             \\\n            r += n;                             \\\n          }                                     \\\n      }                                         \\\n    else                                        \\\n      {                                         \\\n        for (octave_idx_type i = 0; i < u; i++) \\\n          {                                     \\\n            F (v, r, l, n);                     \\\n            v += l*n;                           \\\n            r += l*n;                           \\\n          }                                     \\\n      }                                         \\\n  }\n\nOP_CUM_FCNN (mx_inline_cumsum, T, T)\nOP_CUM_FCNN (mx_inline_cumprod, T, T)\nOP_CUM_FCNN (mx_inline_cumcount, bool, T)\n\n#define OP_CUM_NAN_FCNN(F, TSRC, TRES)                   \\\n  template <typename T>                                  \\\n  inline void                                            \\\n  F (const TSRC *v, TRES *r, octave_idx_type l,          \\\n     octave_idx_type n, octave_idx_type u, bool nanflag) \\\n  {                                                      \\\n    if (l == 1)                                          \\\n      {                                                  \\\n        for (octave_idx_type i = 0; i < u; i++)          \\\n          {                                              \\\n            F (v, r, n, nanflag);                        \\\n            v += n;                                      \\\n            r += n;                                      \\\n          }                                              \\\n      }                                                  \\\n    else                                                 \\\n      {                                                  \\\n        for (octave_idx_type i = 0; i < u; i++)          \\\n          {                                              \\\n            F (v, r, l, n, nanflag);                     \\\n            v += l*n;                                    \\\n            r += l*n;                                    \\\n          }                                              \\\n      }                                                  \\\n  }\n\nOP_CUM_NAN_FCNN (mx_inline_cumsum, T, T)\nOP_CUM_NAN_FCNN (mx_inline_cumprod, T, T)\n\ntemplate <typename T>\ninline void\nmx_inline_flip (const T *v, T *r, octave_idx_type n)\n{\n  if (n)\n    {\n      for (octave_idx_type i = 0; i < n; i++)\n        r[i] = v[n-1-i];\n    }\n}\n\ntemplate <typename T>\ninline void\nmx_inline_flip (const T *v, T *r, octave_idx_type m, octave_idx_type n)\n{\n  if (n)\n    {\n      for (octave_idx_type j = 0; j < n; j++)\n        {\n          for (octave_idx_type i = 0; i < m; i++)\n            r[(n-1-j)*m+i] = v[j*m+i];\n        }\n    }\n}\n\ntemplate <typename T>\ninline void\nmx_inline_flip (const T *v, T *r, octave_idx_type l,\n                octave_idx_type n, octave_idx_type u)\n{\n  if (l == 1)\n    {\n      for (octave_idx_type i = 0; i < u; i++)\n        {\n          mx_inline_flip (v, r, n);\n          v += n;\n          r += n;\n        }\n    }\n  else\n    {\n      for (octave_idx_type i = 0; i < u; i++)\n        {\n          mx_inline_flip (v, r, l, n);\n          v += l*n;\n          r += l*n;\n        }\n    }\n}\n\n// Templated functions for Fmin and Fmax\n\n#define OP_MINMAX_FCN(F, OP)                                            \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type n, const bool nanflag,      \\\n          const bool realabs)                                           \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    if (! nanflag)                                                      \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < n; i++)                         \\\n          if (octave::math::isnan (v[i]))                               \\\n            {                                                           \\\n              *r = NAN;                                                 \\\n              return;                                                   \\\n            }                                                           \\\n      }                                                                 \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type i = 1;                                              \\\n    if (octave::math::isnan (tmp))                                      \\\n      {                                                                 \\\n        for (; i < n && octave::math::isnan (v[i]); i++) ;              \\\n        if (i < n)                                                      \\\n          tmp = v[i];                                                   \\\n      }                                                                 \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          if (v[i] OP tmp)                                              \\\n            tmp = v[i];                                                 \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (std::abs (v[i]) OP std::abs (tmp))                      \\\n              tmp = v[i];                                               \\\n            else if (std::abs (v[i]) == std::abs (tmp) && v[i] OP tmp)  \\\n              tmp = v[i];                                               \\\n          }                                                             \\\n      }                                                                 \\\n    *r = tmp;                                                           \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n,     \\\n          const bool nanflag, const bool realabs)                       \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    if (! nanflag)                                                      \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < n; i++)                         \\\n          if (octave::math::isnan (v[i]))                               \\\n            {                                                           \\\n              *r = NAN;                                                 \\\n              *ri = i;                                                  \\\n              return;                                                   \\\n            }                                                           \\\n      }                                                                 \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type tmpi = 0;                                           \\\n    octave_idx_type i = 1;                                              \\\n    if (octave::math::isnan (tmp))                                      \\\n      {                                                                 \\\n        for (; i < n && octave::math::isnan (v[i]); i++) ;              \\\n        if (i < n)                                                      \\\n          {                                                             \\\n            tmp = v[i];                                                 \\\n            tmpi = i;                                                   \\\n          }                                                             \\\n      }                                                                 \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          if (v[i] OP tmp)                                              \\\n            {                                                           \\\n              tmp = v[i];                                               \\\n              tmpi = i;                                                 \\\n            }                                                           \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (std::abs (v[i]) OP std::abs (tmp))                      \\\n              {                                                         \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n            else if (std::abs (v[i]) == std::abs (tmp) && v[i] OP tmp)  \\\n              {                                                         \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    *r = tmp;                                                           \\\n    *ri = tmpi;                                                         \\\n  }\n\nOP_MINMAX_FCN (mx_inline_min, <)\nOP_MINMAX_FCN (mx_inline_max, >)\n\n// Row reductions will be slightly complicated.  We will proceed with checks\n// for NaNs until we detect that no row will yield a NaN, in which case we\n// proceed to a faster code.\n\n#define OP_MINMAX_FCN2(F, OP)                                           \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type m, octave_idx_type n,            \\\n     const bool nanflag, const bool realabs)                            \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      {                                                                 \\\n        r[i] = v[i];                                                    \\\n      }                                                                 \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if ((octave::math::isnan (v[i]) ||                      \\\n                     octave::math::isnan (r[i])) && ! nanflag)          \\\n                  r[i] = NAN;                                           \\\n                else if (octave::math::isnan (v[i]));                   \\\n                else if (octave::math::isnan (r[i]) || v[i] OP r[i])    \\\n                  r[i] = v[i];                                          \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if ((octave::math::isnan (v[i]) ||                      \\\n                     octave::math::isnan (r[i])) && ! nanflag)          \\\n                  r[i] = NAN;                                           \\\n                else if (octave::math::isnan (v[i]));                   \\\n                else if (octave::math::isnan (r[i]) ||                  \\\n                         std::abs (v[i]) OP std::abs (r[i]))            \\\n                  r[i] = v[i];                                          \\\n                else if (std::abs (v[i]) == std::abs (r[i]) &&          \\\n                         v[i] OP r[i])                                  \\\n                  r[i] = v[i];                                          \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type m,          \\\n     octave_idx_type n, const bool nanflag, const bool realabs)         \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      {                                                                 \\\n        r[i] = v[i];                                                    \\\n        ri[i] = j;                                                      \\\n      }                                                                 \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r[i]) && ! nanflag);           \\\n                else if (octave::math::isnan (v[i]) && ! nanflag)       \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (octave::math::isnan (v[i]));                   \\\n                else if (octave::math::isnan (r[i]) || v[i] OP r[i])    \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r[i]) && ! nanflag);           \\\n                else if (octave::math::isnan (v[i]) && ! nanflag)       \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (octave::math::isnan (v[i]));                   \\\n                else if (octave::math::isnan (r[i]) ||                  \\\n                         std::abs (v[i]) OP std::abs (r[i]))            \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (std::abs (v[i]) == std::abs (r[i]) &&          \\\n                         v[i] OP r[i])                                  \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_MINMAX_FCN2 (mx_inline_min, <)\nOP_MINMAX_FCN2 (mx_inline_max, >)\n\n#define OP_MINMAX_FCNN(F)                                               \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type l, octave_idx_type n,            \\\n     octave_idx_type u, const bool nanflag, const bool realabs)         \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    if (l == 1)                                                         \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, n, nanflag, realabs);                              \\\n            v += n;                                                     \\\n            r++;                                                        \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, l, n, nanflag, realabs);                           \\\n            v += l*n;                                                   \\\n            r += l;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type l,          \\\n     octave_idx_type n, octave_idx_type u, const bool nanflag,          \\\n     const bool realabs)                                                \\\n  {                                                                     \\\n    if (! n) return;                                                    \\\n    if (l == 1)                                                         \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, ri, n, nanflag, realabs);                          \\\n            v += n;                                                     \\\n            r++;                                                        \\\n            ri++;                                                       \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, ri, l, n, nanflag, realabs);                       \\\n            v += l*n;                                                   \\\n            r += l;                                                     \\\n            ri += l;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_MINMAX_FCNN (mx_inline_min)\nOP_MINMAX_FCNN (mx_inline_max)\n\n// Special implementation for complex arrays, since we need comparisons\n// in both real and imaginary parts for MATLAB compatibility.\n\n#define OP_CMINMAX_FCN(F, OP)                                                  \\\n  template <typename T>                                                        \\\n  void F (const std::complex<T> *v, std::complex<T> *r,                        \\\n          octave_idx_type n, const bool nanflag, const bool realabs)           \\\n  {                                                                            \\\n    if (! n)                                                                   \\\n      return;                                                                  \\\n    if (! nanflag)                                                             \\\n      {                                                                        \\\n        for (octave_idx_type i = 0; i < n; i++)                                \\\n          if (octave::math::isnan (v[i]))                                      \\\n            {                                                                  \\\n              *r = NAN;                                                        \\\n              return;                                                          \\\n            }                                                                  \\\n      }                                                                        \\\n    std::complex<T> tmp = v[0];                                                \\\n    octave_idx_type i = 1;                                                     \\\n    if (octave::math::isnan (tmp))                                             \\\n      {                                                                        \\\n        for (; i < n && octave::math::isnan (v[i]); i++) ;                     \\\n        if (i < n)                                                             \\\n          tmp = v[i];                                                          \\\n      }                                                                        \\\n    if (realabs)                                                               \\\n      {                                                                        \\\n        for (; i < n; i++)                                                     \\\n          {                                                                    \\\n            if (v[i].real () OP tmp.real ())                                   \\\n              tmp = v[i];                                                      \\\n            else if (v[i].real () == tmp.real () &&                            \\\n                     v[i].imag () OP tmp.imag ())                              \\\n              tmp = v[i];                                                      \\\n          }                                                                    \\\n      }                                                                        \\\n    else                                                                       \\\n      {                                                                        \\\n        for (; i < n; i++)                                                     \\\n          {                                                                    \\\n            if (std::abs (v[i]) OP std::abs (tmp))                             \\\n              tmp = v[i];                                                      \\\n            else if (std::abs (v[i]) == std::abs (tmp) &&                      \\\n                     std::arg (v[i]) OP std::arg (tmp))                        \\\n              tmp = v[i];                                                      \\\n          }                                                                    \\\n      }                                                                        \\\n    *r = tmp;                                                                  \\\n  }                                                                            \\\n  template <typename T>                                                        \\\n  void F (const std::complex<T> *v, std::complex<T> *r,                        \\\n          octave_idx_type *ri, octave_idx_type n, const bool nanflag,          \\\n          const bool realabs)                                                  \\\n  {                                                                            \\\n    if (! n)                                                                   \\\n      return;                                                                  \\\n    if (! nanflag)                                                             \\\n      {                                                                        \\\n        for (octave_idx_type i = 0; i < n; i++)                                \\\n          if (octave::math::isnan (v[i]))                                      \\\n            {                                                                  \\\n              *r = NAN;                                                        \\\n              *ri = i;                                                         \\\n              return;                                                          \\\n            }                                                                  \\\n      }                                                                        \\\n    std::complex<T> tmp = v[0];                                                \\\n    octave_idx_type tmpi = 0;                                                  \\\n    octave_idx_type i = 1;                                                     \\\n    if (octave::math::isnan (tmp))                                             \\\n      {                                                                        \\\n        for (; i < n && octave::math::isnan (v[i]); i++) ;                     \\\n        if (i < n)                                                             \\\n          {                                                                    \\\n            tmp = v[i];                                                        \\\n            tmpi = i;                                                          \\\n          }                                                                    \\\n      }                                                                        \\\n    if (realabs)                                                               \\\n      {                                                                        \\\n        for (; i < n; i++)                                                     \\\n          {                                                                    \\\n            if (v[i].real () OP tmp.real ())                                   \\\n              {                                                                \\\n                tmp = v[i];                                                    \\\n                tmpi = i;                                                      \\\n              }                                                                \\\n            else if (v[i].real () == tmp.real () &&                            \\\n                     v[i].imag () OP tmp.imag ())                              \\\n              {                                                                \\\n                tmp = v[i];                                                    \\\n                tmpi = i;                                                      \\\n              }                                                                \\\n          }                                                                    \\\n      }                                                                        \\\n    else                                                                       \\\n      {                                                                        \\\n        for (; i < n; i++)                                                     \\\n          {                                                                    \\\n            if (std::abs (v[i]) OP std::abs (tmp))                             \\\n              {                                                                \\\n                tmp = v[i];                                                    \\\n                tmpi = i;                                                      \\\n              }                                                                \\\n            else if (std::abs (v[i]) == std::abs (tmp) &&                      \\\n                     std::arg (v[i]) OP std::arg (tmp))                        \\\n              {                                                                \\\n                tmp = v[i];                                                    \\\n                tmpi = i;                                                      \\\n              }                                                                \\\n          }                                                                    \\\n      }                                                                        \\\n    *r = tmp;                                                                  \\\n    *ri = tmpi;                                                                \\\n  }\n\nOP_CMINMAX_FCN (mx_inline_cmin, <)\nOP_CMINMAX_FCN (mx_inline_cmax, >)\n\n// Row reductions will be slightly complicated.  We will proceed with checks\n// for NaNs until we detect that no row will yield a NaN, in which case we\n// proceed to a faster code.\n\n#define OP_CMINMAX_FCN2(F, OP)                                                 \\\n  template <typename T>                                                        \\\n  inline void                                                                  \\\n  F (const std::complex<T> *v, std::complex<T> *r, octave_idx_type m,          \\\n     octave_idx_type n, const bool nanflag, const bool realabs)                \\\n  {                                                                            \\\n    if (! n)                                                                   \\\n      return;                                                                  \\\n    octave_idx_type j = 0;                                                     \\\n    for (octave_idx_type i = 0; i < m; i++)                                    \\\n      {                                                                        \\\n        r[i] = v[i];                                                           \\\n      }                                                                        \\\n    j++;                                                                       \\\n    v += m;                                                                    \\\n    if (realabs)                                                               \\\n      {                                                                        \\\n        while (j < n)                                                          \\\n          {                                                                    \\\n            for (octave_idx_type i = 0; i < m; i++)                            \\\n              {                                                                \\\n                if ((octave::math::isnan (v[i]) ||                             \\\n                     octave::math::isnan (r[i])) && ! nanflag)                 \\\n                  r[i] = NAN;                                                  \\\n                else if (octave::math::isnan (v[i]));                          \\\n                else if (octave::math::isnan (r[i]) ||                         \\\n                         v[i].real () OP r[i].real ())                         \\\n                  r[i] = v[i];                                                 \\\n                else if (v[i].real () == r[i].real () &&                       \\\n                         v[i].imag () OP r[i].imag ())                         \\\n                  r[i] = v[i];                                                 \\\n              }                                                                \\\n            j++;                                                               \\\n            v += m;                                                            \\\n          }                                                                    \\\n      }                                                                        \\\n    else                                                                       \\\n      {                                                                        \\\n        while (j < n)                                                          \\\n          {                                                                    \\\n            for (octave_idx_type i = 0; i < m; i++)                            \\\n              {                                                                \\\n                if ((octave::math::isnan (v[i]) ||                             \\\n                     octave::math::isnan (r[i])) && ! nanflag)                 \\\n                  r[i] = NAN;                                                  \\\n                else if (octave::math::isnan (v[i]));                          \\\n                else if (octave::math::isnan (r[i]) ||                         \\\n                         std::abs (v[i]) OP std::abs (r[i]))                   \\\n                  r[i] = v[i];                                                 \\\n                else if (std::abs (v[i]) == std::abs (r[i]) &&                 \\\n                         std::arg (v[i]) OP std::arg (r[i]))                   \\\n                  r[i] = v[i];                                                 \\\n              }                                                                \\\n            j++;                                                               \\\n            v += m;                                                            \\\n          }                                                                    \\\n      }                                                                        \\\n  }                                                                            \\\n  template <typename T>                                                        \\\n  inline void                                                                  \\\n  F (const std::complex<T> *v, std::complex<T> *r, octave_idx_type *ri,        \\\n     octave_idx_type m, octave_idx_type n, const bool nanflag,                 \\\n     const bool realabs)                                                       \\\n  {                                                                            \\\n    if (! n)                                                                   \\\n      return;                                                                  \\\n    octave_idx_type j = 0;                                                     \\\n    for (octave_idx_type i = 0; i < m; i++)                                    \\\n      {                                                                        \\\n        r[i] = v[i];                                                           \\\n        ri[i] = j;                                                             \\\n      }                                                                        \\\n    j++;                                                                       \\\n    v += m;                                                                    \\\n    if (realabs)                                                               \\\n      {                                                                        \\\n        while (j < n)                                                          \\\n          {                                                                    \\\n            for (octave_idx_type i = 0; i < m; i++)                            \\\n              {                                                                \\\n                if (octave::math::isnan (r[i]) && ! nanflag);                  \\\n                else if (octave::math::isnan (v[i]) && ! nanflag)              \\\n                  {                                                            \\\n                    r[i] = NAN;                                                \\\n                    ri[i] = j;                                                 \\\n                  }                                                            \\\n                else if (octave::math::isnan (v[i]));                          \\\n                else if (octave::math::isnan (r[i]) ||                         \\\n                         v[i].real () OP r[i].real ())                         \\\n                  {                                                            \\\n                    r[i] = v[i];                                               \\\n                    ri[i] = j;                                                 \\\n                  }                                                            \\\n                else if (v[i].real () == r[i].real () &&                       \\\n                         v[i].imag () OP r[i].imag ())                         \\\n                  {                                                            \\\n                    r[i] = v[i];                                               \\\n                    ri[i] = j;                                                 \\\n                  }                                                            \\\n              }                                                                \\\n            j++;                                                               \\\n            v += m;                                                            \\\n          }                                                                    \\\n      }                                                                        \\\n    else                                                                       \\\n      {                                                                        \\\n        while (j < n)                                                          \\\n          {                                                                    \\\n            for (octave_idx_type i = 0; i < m; i++)                            \\\n              {                                                                \\\n                if (octave::math::isnan (r[i]) && ! nanflag);                  \\\n                else if (octave::math::isnan (v[i]) && ! nanflag)              \\\n                  {                                                            \\\n                    r[i] = NAN;                                                \\\n                    ri[i] = j;                                                 \\\n                  }                                                            \\\n                else if (octave::math::isnan (v[i]));                          \\\n                else if (octave::math::isnan (r[i]) ||                         \\\n                         std::abs (v[i]) OP std::abs (r[i]))                   \\\n                  {                                                            \\\n                    r[i] = v[i];                                               \\\n                    ri[i] = j;                                                 \\\n                  }                                                            \\\n                else if (std::abs (v[i]) == std::abs (r[i]) &&                 \\\n                         std::arg (v[i]) OP std::arg (r[i]))                   \\\n                  {                                                            \\\n                    r[i] = v[i];                                               \\\n                    ri[i] = j;                                                 \\\n                  }                                                            \\\n              }                                                                \\\n            j++;                                                               \\\n            v += m;                                                            \\\n          }                                                                    \\\n      }                                                                        \\\n  }\n\nOP_CMINMAX_FCN2 (mx_inline_cmin, <)\nOP_CMINMAX_FCN2 (mx_inline_cmax, >)\n\n#define OP_CMINMAX_FCNN(F)                                                     \\\n  template <typename T>                                                        \\\n  inline void                                                                  \\\n  F (const T *v, T *r, octave_idx_type l, octave_idx_type n,                   \\\n     octave_idx_type u, const bool nanflag, const bool realabs)                \\\n  {                                                                            \\\n    if (! n)                                                                   \\\n      return;                                                                  \\\n    if (l == 1)                                                                \\\n      {                                                                        \\\n        for (octave_idx_type i = 0; i < u; i++)                                \\\n          {                                                                    \\\n            F (v, r, n, nanflag, realabs);                                     \\\n            v += n;                                                            \\\n            r++;                                                               \\\n          }                                                                    \\\n      }                                                                        \\\n    else                                                                       \\\n      {                                                                        \\\n        for (octave_idx_type i = 0; i < u; i++)                                \\\n          {                                                                    \\\n            F (v, r, l, n, nanflag, realabs);                                  \\\n            v += l*n;                                                          \\\n            r += l;                                                            \\\n          }                                                                    \\\n      }                                                                        \\\n  }                                                                            \\\n  template <typename T>                                                        \\\n  inline void                                                                  \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type l,                 \\\n     octave_idx_type n, octave_idx_type u, bool nanflag, bool realabs)         \\\n  {                                                                            \\\n    if (! n) return;                                                           \\\n    if (l == 1)                                                                \\\n      {                                                                        \\\n        for (octave_idx_type i = 0; i < u; i++)                                \\\n          {                                                                    \\\n            F (v, r, ri, n, nanflag, realabs);                                 \\\n            v += n;                                                            \\\n            r++;                                                               \\\n            ri++;                                                              \\\n          }                                                                    \\\n      }                                                                        \\\n    else                                                                       \\\n      {                                                                        \\\n        for (octave_idx_type i = 0; i < u; i++)                                \\\n          {                                                                    \\\n            F (v, r, ri, l, n, nanflag, realabs);                              \\\n            v += l*n;                                                          \\\n            r += l;                                                            \\\n            ri += l;                                                           \\\n          }                                                                    \\\n      }                                                                        \\\n  }\n\nOP_CMINMAX_FCNN (mx_inline_cmin)\nOP_CMINMAX_FCNN (mx_inline_cmax)\n\n// Faster implementation for int arrays, since they do not support\n// NaN values and real/abs comparison methods require specialized mapper.\n\n#define OP_INT_MINMAX_FCN(F, OP)                                        \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type n, const bool realabs)      \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type i = 1;                                              \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          if (v[i] OP tmp)                                              \\\n            tmp = v[i];                                                 \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (mappers_abs (v[i]) OP mappers_abs (tmp))                \\\n              tmp = v[i];                                               \\\n            else if (mappers_abs (v[i]) == mappers_abs (tmp) &&         \\\n                     v[i] OP tmp)                                       \\\n              tmp = v[i];                                               \\\n          }                                                             \\\n      }                                                                 \\\n    *r = tmp;                                                           \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n,     \\\n          const bool realabs)                                           \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type tmpi = 0;                                           \\\n    octave_idx_type i = 1;                                              \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          if (v[i] OP tmp)                                              \\\n            {                                                           \\\n              tmp = v[i];                                               \\\n              tmpi = i;                                                 \\\n            }                                                           \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (mappers_abs (v[i]) OP mappers_abs (tmp))                \\\n              {                                                         \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n            else if (mappers_abs (v[i]) == mappers_abs (tmp) &&         \\\n                     v[i] OP tmp)                                       \\\n              {                                                         \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    *r = tmp;                                                           \\\n    *ri = tmpi;                                                         \\\n  }\n\nOP_INT_MINMAX_FCN (mx_inline_intmin, <)\nOP_INT_MINMAX_FCN (mx_inline_intmax, >)\n\n#define OP_INT_MINMAX_FCN2(F, OP)                                       \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type m, octave_idx_type n,            \\\n     const bool realabs)                                                \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      {                                                                 \\\n        r[i] = v[i];                                                    \\\n      }                                                                 \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              if (v[i] OP r[i])                                         \\\n                r[i] = v[i];                                            \\\n            j++;                                                        \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (mappers_abs (v[i]) OP mappers_abs (r[i]))           \\\n                  r[i] = v[i];                                          \\\n                else if (mappers_abs (v[i]) == mappers_abs (r[i]) &&    \\\n                         v[i] OP r[i])                                  \\\n                  r[i] = v[i];                                          \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type m,          \\\n     octave_idx_type n, const bool realabs)                             \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      {                                                                 \\\n        r[i] = v[i];                                                    \\\n        ri[i] = j;                                                      \\\n      }                                                                 \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              if (v[i] OP r[i])                                         \\\n                {                                                       \\\n                  r[i] = v[i];                                          \\\n                  ri[i] = j;                                            \\\n                }                                                       \\\n            j++;                                                        \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (mappers_abs (v[i]) OP mappers_abs (r[i]))           \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                  else if (mappers_abs (v[i]) == mappers_abs (r[i]) &&  \\\n                           v[i] OP r[i])                                \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_INT_MINMAX_FCN2 (mx_inline_intmin, <)\nOP_INT_MINMAX_FCN2 (mx_inline_intmax, >)\n\n#define OP_INT_MINMAX_FCNN(F)                                           \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type l, octave_idx_type n,            \\\n     octave_idx_type u, const bool realabs)                             \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    if (l == 1)                                                         \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, n, realabs);                                       \\\n            v += n;                                                     \\\n            r++;                                                        \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, l, n, realabs);                                    \\\n            v += l*n;                                                   \\\n            r += l;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type l,          \\\n     octave_idx_type n, octave_idx_type u, const bool realabs)          \\\n  {                                                                     \\\n    if (! n) return;                                                    \\\n    if (l == 1)                                                         \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, ri, n, realabs);                                   \\\n            v += n;                                                     \\\n            r++;                                                        \\\n            ri++;                                                       \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, ri, l, n, realabs);                                \\\n            v += l*n;                                                   \\\n            r += l;                                                     \\\n            ri += l;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_INT_MINMAX_FCNN (mx_inline_intmin)\nOP_INT_MINMAX_FCNN (mx_inline_intmax)\n\n// Faster implementation for char arrays, since they do not support\n// NaN values and real/abs comparison methods do apply either.\n\n#define OP_CHMINMAX_FCN(F, OP)                                          \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type n)                          \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type i = 1;                                              \\\n    for (; i < n; i++)                                                  \\\n      if (v[i] OP tmp)                                                  \\\n        tmp = v[i];                                                     \\\n    *r = tmp;                                                           \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n)     \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type tmpi = 0;                                           \\\n    octave_idx_type i = 1;                                              \\\n    for (; i < n; i++)                                                  \\\n      if (v[i] OP tmp)                                                  \\\n        {                                                               \\\n          tmp = v[i];                                                   \\\n          tmpi = i;                                                     \\\n        }                                                               \\\n    *r = tmp;                                                           \\\n    *ri = tmpi;                                                         \\\n  }\n\nOP_CHMINMAX_FCN (mx_inline_chmin, <)\nOP_CHMINMAX_FCN (mx_inline_chmax, >)\n\n#define OP_CHMINMAX_FCN2(F, OP)                                         \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type m, octave_idx_type n)            \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    octave_idx_type j = 1;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      r[i] = v[i];                                                      \\\n    v += m;                                                             \\\n    while (j < n)                                                       \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < m; i++)                         \\\n          if (v[i] OP r[i])                                             \\\n            r[i] = v[i];                                                \\\n        j++;                                                            \\\n        v += m;                                                         \\\n      }                                                                 \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type *ri,                             \\\n     octave_idx_type m, octave_idx_type n)                              \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    octave_idx_type j = 1;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      {                                                                 \\\n        r[i] = v[i];                                                    \\\n        ri[i] = j;                                                      \\\n      }                                                                 \\\n    v += m;                                                             \\\n    while (j < n)                                                       \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < m; i++)                         \\\n          if (v[i] OP r[i])                                             \\\n            {                                                           \\\n              r[i] = v[i];                                              \\\n              ri[i] = j;                                                \\\n            }                                                           \\\n        j++;                                                            \\\n        v += m;                                                         \\\n      }                                                                 \\\n  }\n\nOP_CHMINMAX_FCN2 (mx_inline_chmin, <)\nOP_CHMINMAX_FCN2 (mx_inline_chmax, >)\n\n#define OP_CHMINMAX_FCNN(F)                                             \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type l,                               \\\n     octave_idx_type n,octave_idx_type u)                               \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    if (l == 1)                                                         \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, n);                                                \\\n            v += n;                                                     \\\n            r++;                                                        \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, l, n);                                             \\\n            v += l*n;                                                   \\\n            r += l;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type l,          \\\n     octave_idx_type n, octave_idx_type u)                              \\\n  {                                                                     \\\n    if (! n) return;                                                    \\\n    if (l == 1)                                                         \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, ri, n);                                            \\\n            v += n;                                                     \\\n            r++;                                                        \\\n            ri++;                                                       \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (octave_idx_type i = 0; i < u; i++)                         \\\n          {                                                             \\\n            F (v, r, ri, l, n);                                         \\\n            v += l*n;                                                   \\\n            r += l;                                                     \\\n            ri += l;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_CHMINMAX_FCNN (mx_inline_chmin)\nOP_CHMINMAX_FCNN (mx_inline_chmax)\n\n// Templated functions for Fcummin and Fcummax\n\n#define OP_CUMMINMAX_FCN(F, OP)                                         \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type n, const bool nanflag,      \\\n          const bool realabs)                                           \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type i = 1;                                              \\\n    octave_idx_type j = 0;                                              \\\n    if (octave::math::isnan (tmp) && ! nanflag)                         \\\n      {                                                                 \\\n        for (; j < n; j++)                                              \\\n          r[j] = NAN;                                                   \\\n        return;                                                         \\\n      }                                                                 \\\n    else if (octave::math::isnan (tmp))                                 \\\n      {                                                                 \\\n        for (; i < n && octave::math::isnan (v[i]); i++) ;              \\\n        for (; j < i; j++)                                              \\\n          r[j] = tmp;                                                   \\\n        if (i < n)                                                      \\\n          tmp = v[i];                                                   \\\n      }                                                                 \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (octave::math::isnan (v[i]) && ! nanflag)                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                for (; j < n; j++)                                      \\\n                  r[j] = NAN;                                           \\\n                return;                                                 \\\n              }                                                         \\\n            if (v[i] OP tmp)                                            \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                tmp = v[i];                                             \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (octave::math::isnan (v[i]) && ! nanflag)                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                for (; j < n; j++)                                      \\\n                  r[j] = NAN;                                           \\\n                return;                                                 \\\n              }                                                         \\\n            if (std::abs (v[i]) OP std::abs (tmp))                      \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                tmp = v[i];                                             \\\n              }                                                         \\\n            else if (std::abs (v[i]) == std::abs (tmp) && v[i] OP tmp)  \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                tmp = v[i];                                             \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    for (; j < i; j++)                                                  \\\n      r[j] = tmp;                                                       \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n,     \\\n          const bool nanflag, const bool realabs)                       \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type tmpi = 0;                                           \\\n    octave_idx_type i = 1;                                              \\\n    octave_idx_type j = 0;                                              \\\n    if (octave::math::isnan (tmp) && ! nanflag)                         \\\n      {                                                                 \\\n        for (; j < n; j++)                                              \\\n          {                                                             \\\n            r[j] = NAN;                                                 \\\n            ri[j] = tmpi;                                               \\\n          }                                                             \\\n        return;                                                         \\\n      }                                                                 \\\n    else if (octave::math::isnan (tmp))                                 \\\n      {                                                                 \\\n        for (; i < n && octave::math::isnan (v[i]); i++) ;              \\\n        for (; j < i; j++)                                              \\\n          {                                                             \\\n            r[j] = tmp;                                                 \\\n            ri[j] = tmpi;                                               \\\n          }                                                             \\\n        if (i < n)                                                      \\\n          {                                                             \\\n            tmp = v[i];                                                 \\\n            tmpi = i;                                                   \\\n          }                                                             \\\n      }                                                                 \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (octave::math::isnan (v[i]) && ! nanflag)                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                for (; j < n; j++)                                      \\\n                  {                                                     \\\n                    r[j] = NAN;                                         \\\n                    ri[j] = i;                                          \\\n                  }                                                     \\\n                return;                                                 \\\n              }                                                         \\\n            if (v[i] OP tmp)                                            \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (octave::math::isnan (v[i]) && ! nanflag)                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                for (; j < n; j++)                                      \\\n                  {                                                     \\\n                    r[j] = NAN;                                         \\\n                    ri[j] = i;                                          \\\n                  }                                                     \\\n                return;                                                 \\\n              }                                                         \\\n            if (std::abs (v[i]) OP std::abs (tmp))                      \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n            else if (std::abs (v[i]) == std::abs (tmp) && v[i] OP tmp)  \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    for (; j < i; j++)                                                  \\\n      {                                                                 \\\n        r[j] = tmp;                                                     \\\n        ri[j] = tmpi;                                                   \\\n      }                                                                 \\\n  }\n\nOP_CUMMINMAX_FCN (mx_inline_cummin, <)\nOP_CUMMINMAX_FCN (mx_inline_cummax, >)\n\n#define OP_CUMMINMAX_FCN2(F, OP)                                        \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type m, octave_idx_type n,            \\\n     const bool nanflag, const bool realabs)                            \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    const T *r0;                                                        \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      r[i] = v[i];                                                      \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    r0 = r;                                                             \\\n    r += m;                                                             \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (! nanflag && j < n)                                      \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (v[i]) ||                       \\\n                    octave::math::isnan (r0[i]))                        \\\n                  r[i] = NAN;                                           \\\n                else if (v[i] OP r0[i])                                 \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n        while (nanflag && j < n)                                        \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r0[i]) || v[i] OP r0[i])       \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (! nanflag && j < n)                                      \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (v[i]) ||                       \\\n                    octave::math::isnan (r0[i]))                        \\\n                  r[i] = NAN;                                           \\\n                else if (std::abs (v[i]) OP std::abs (r0[i]))           \\\n                  r[i] = v[i];                                          \\\n                else if (std::abs (v[i]) == std::abs (r0[i]) &&         \\\n                         v[i] OP r0[i])                                 \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n        while (nanflag && j < n)                                        \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r0[i]))                        \\\n                  r[i] = v[i];                                          \\\n                else if (std::abs (v[i]) OP std::abs (r0[i]))           \\\n                  r[i] = v[i];                                          \\\n                else if (std::abs (v[i]) == std::abs (r0[i]) &&         \\\n                         v[i] OP r0[i])                                 \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type m,          \\\n     octave_idx_type n, const bool nanflag, const bool realabs)         \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    const T *r0;                                                        \\\n    const octave_idx_type *r0i;                                         \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      {                                                                 \\\n        r[i] = v[i];                                                    \\\n        ri[i] = 0;                                                      \\\n      }                                                                 \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    r0 = r;                                                             \\\n    r += m;                                                             \\\n    r0i = ri;                                                           \\\n    ri += m;                                                            \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (! nanflag && j < n)                                      \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (v[i]) &&                       \\\n                    octave::math::isnan (r0[i]))                        \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n                else if (octave::math::isnan (v[i]))                    \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (v[i] OP r0[i])                                 \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n        while (nanflag && j < n)                                        \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r0[i]) &&                      \\\n                    octave::math::isnan (v[i]))                         \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n                else if (octave::math::isnan (r0[i]) || v[i] OP r0[i])  \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (! nanflag && j < n)                                      \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (v[i]) &&                       \\\n                    octave::math::isnan (r0[i]))                        \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n                else if (octave::math::isnan (v[i]))                    \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (std::abs (v[i]) OP std::abs (r0[i]))           \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (std::abs (v[i]) == std::abs (r0[i]) &&         \\\n                         v[i] OP r0[i])                                 \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n        while (nanflag && j < n)                                        \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r0[i]) &&                      \\\n                    octave::math::isnan (v[i]))                         \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n                if (octave::math::isnan (r0[i]))                        \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (std::abs (v[i]) OP std::abs (r0[i]))           \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (std::abs (v[i]) == std::abs (r0[i]) &&         \\\n                         v[i] OP r0[i])                                 \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_CUMMINMAX_FCN2 (mx_inline_cummin, <)\nOP_CUMMINMAX_FCN2 (mx_inline_cummax, >)\n\n#define OP_CUMMINMAX_FCNN(F)                                    \\\n  template <typename T>                                         \\\n  inline void                                                   \\\n  F (const T *v, T *r, octave_idx_type l, octave_idx_type n,    \\\n     octave_idx_type u, const bool nanflag, const bool realabs) \\\n  {                                                             \\\n    if (! n)                                                    \\\n      return;                                                   \\\n    if (l == 1)                                                 \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, n, nanflag, realabs);                      \\\n            v += n;                                             \\\n            r += n;                                             \\\n          }                                                     \\\n      }                                                         \\\n    else                                                        \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, l, n, nanflag, realabs);                   \\\n            v += l*n;                                           \\\n            r += l*n;                                           \\\n          }                                                     \\\n      }                                                         \\\n  }                                                             \\\n  template <typename T>                                         \\\n  inline void                                                   \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type l,  \\\n     octave_idx_type n, octave_idx_type u, const bool nanflag,  \\\n     const bool realabs)                                        \\\n  {                                                             \\\n    if (! n)                                                    \\\n      return;                                                   \\\n    if (l == 1)                                                 \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, ri, n, nanflag, realabs);                  \\\n            v += n;                                             \\\n            r += n;                                             \\\n            ri += n;                                            \\\n          }                                                     \\\n      }                                                         \\\n    else                                                        \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, ri, l, n, nanflag, realabs);               \\\n            v += l*n;                                           \\\n            r += l*n;                                           \\\n            ri += l*n;                                          \\\n          }                                                     \\\n      }                                                         \\\n  }\n\nOP_CUMMINMAX_FCNN (mx_inline_cummin)\nOP_CUMMINMAX_FCNN (mx_inline_cummax)\n\n// Special implementation for complex arrays, since we need comparisons\n// in both real and imaginary parts for MATLAB compatibility.\n\n#define OP_CCUMMINMAX_FCN(F, OP)                                        \\\n  template <typename T>                                                 \\\n  void F (const std::complex<T> *v, std::complex<T> *r,                 \\\n          octave_idx_type n, const bool nanflag, const bool realabs)    \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    std::complex<T> tmp = v[0];                                         \\\n    octave_idx_type i = 1;                                              \\\n    octave_idx_type j = 0;                                              \\\n    if (octave::math::isnan (tmp) && ! nanflag)                         \\\n      {                                                                 \\\n        for (; j < n; j++)                                              \\\n          r[j] = NAN;                                                   \\\n        return;                                                         \\\n      }                                                                 \\\n    else if (octave::math::isnan (tmp))                                 \\\n      {                                                                 \\\n        for (; i < n && octave::math::isnan (v[i]); i++) ;              \\\n        for (; j < i; j++)                                              \\\n          r[j] = tmp;                                                   \\\n        if (i < n)                                                      \\\n          tmp = v[i];                                                   \\\n      }                                                                 \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (octave::math::isnan (v[i]) && ! nanflag)                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                for (; j < n; j++)                                      \\\n                  r[j] = NAN;                                           \\\n                return;                                                 \\\n              }                                                         \\\n            if (v[i].real () OP tmp.real ())                            \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                tmp = v[i];                                             \\\n              }                                                         \\\n            else if (v[i].real () == tmp.real () &&                     \\\n                     v[i].imag () OP tmp.imag ())                       \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                tmp = v[i];                                             \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (octave::math::isnan (v[i]) && ! nanflag)                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                for (; j < n; j++)                                      \\\n                  r[j] = NAN;                                           \\\n                return;                                                 \\\n              }                                                         \\\n            if (std::abs (v[i]) OP std::abs (tmp))                      \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                tmp = v[i];                                             \\\n              }                                                         \\\n            else if (std::abs (v[i]) == std::abs (tmp) &&               \\\n                     std::arg (v[i]) OP std::arg (tmp))                 \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                tmp = v[i];                                             \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    for (; j < i; j++)                                                  \\\n      r[j] = tmp;                                                       \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  void F (const std::complex<T> *v, std::complex<T> *r,                 \\\n          octave_idx_type *ri, octave_idx_type n, const bool nanflag,   \\\n          const bool realabs)                                           \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    std::complex<T> tmp = v[0];                                         \\\n    octave_idx_type tmpi = 0;                                           \\\n    octave_idx_type i = 1;                                              \\\n    octave_idx_type j = 0;                                              \\\n    if (octave::math::isnan (tmp) && ! nanflag)                         \\\n      {                                                                 \\\n        for (; j < n; j++)                                              \\\n          {                                                             \\\n            r[j] = NAN;                                                 \\\n            ri[j] = tmpi;                                               \\\n          }                                                             \\\n        return;                                                         \\\n      }                                                                 \\\n    else if (octave::math::isnan (tmp))                                 \\\n      {                                                                 \\\n        for (; i < n && octave::math::isnan (v[i]); i++) ;              \\\n        for (; j < i; j++)                                              \\\n          {                                                             \\\n            r[j] = tmp;                                                 \\\n            ri[j] = tmpi;                                               \\\n          }                                                             \\\n        if (i < n)                                                      \\\n          {                                                             \\\n            tmp = v[i];                                                 \\\n            tmpi = i;                                                   \\\n          }                                                             \\\n      }                                                                 \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (octave::math::isnan (v[i]) && ! nanflag)                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                for (; j < n; j++)                                      \\\n                  {                                                     \\\n                    r[j] = NAN;                                         \\\n                    ri[j] = i;                                          \\\n                  }                                                     \\\n                return;                                                 \\\n              }                                                         \\\n            if (v[i].real () OP tmp.real ())                            \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n            else if (v[i].real () == tmp.real () &&                     \\\n                     v[i].imag () OP tmp.imag ())                       \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (octave::math::isnan (v[i]) && ! nanflag)                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                for (; j < n; j++)                                      \\\n                  {                                                     \\\n                    r[j] = NAN;                                         \\\n                    ri[j] = i;                                          \\\n                  }                                                     \\\n                return;                                                 \\\n              }                                                         \\\n            if (std::abs (v[i]) OP std::abs (tmp))                      \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n            else if (std::abs (v[i]) == std::abs (tmp) &&               \\\n                     std::arg (v[i]) OP std::arg (tmp))                 \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    for (; j < i; j++)                                                  \\\n      {                                                                 \\\n        r[j] = tmp;                                                     \\\n        ri[j] = tmpi;                                                   \\\n      }                                                                 \\\n  }\n\nOP_CCUMMINMAX_FCN (mx_inline_ccummin, <)\nOP_CCUMMINMAX_FCN (mx_inline_ccummax, >)\n\n#define OP_CCUMMINMAX_FCN2(F, OP)                                       \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const std::complex<T> *v, std::complex<T> *r, octave_idx_type m,   \\\n     octave_idx_type n, const bool nanflag, const bool realabs)         \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    const std::complex<T> *r0;                                          \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      r[i] = v[i];                                                      \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    r0 = r;                                                             \\\n    r += m;                                                             \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (! nanflag && j < n)                                      \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (v[i]) ||                       \\\n                    octave::math::isnan (r0[i]))                        \\\n                  r[i] = NAN;                                           \\\n                else if (v[i].real () OP r0[i].real ())                 \\\n                  r[i] = v[i];                                          \\\n                else if (v[i].real () == r0[i].real () &&               \\\n                         v[i].imag () OP r0[i].imag ())                 \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n        while (nanflag && j < n)                                        \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r0[i]))                        \\\n                  r[i] = v[i];                                          \\\n                else if (v[i].real () OP r0[i].real ())                 \\\n                  r[i] = v[i];                                          \\\n                else if (v[i].real () == r0[i].real () &&               \\\n                         v[i].imag () OP r0[i].imag ())                 \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (! nanflag && j < n)                                      \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (v[i]) ||                       \\\n                    octave::math::isnan (r0[i]))                        \\\n                  r[i] = NAN;                                           \\\n                else if (std::abs (v[i]) OP std::abs (r0[i]))           \\\n                  r[i] = v[i];                                          \\\n                else if (std::abs (v[i]) == std::abs (r0[i]) &&         \\\n                         std::arg (v[i]) OP std::arg (r0[i]))           \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n        while (nanflag && j < n)                                        \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r0[i]))                        \\\n                  r[i] = v[i];                                          \\\n                else if (std::abs (v[i]) OP std::abs (r0[i]))           \\\n                  r[i] = v[i];                                          \\\n                else if (std::abs (v[i]) == std::abs (r0[i])  &&        \\\n                         std::arg (v[i]) OP std::arg (r0[i]))           \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const std::complex<T> *v, std::complex<T> *r, octave_idx_type *ri, \\\n     octave_idx_type m, octave_idx_type n, const bool nanflag,          \\\n     const bool realabs)                                                \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    const std::complex<T> *r0;                                          \\\n    const octave_idx_type *r0i;                                         \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      {                                                                 \\\n        r[i] = v[i];                                                    \\\n        ri[i] = 0;                                                      \\\n      }                                                                 \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    r0 = r;                                                             \\\n    r += m;                                                             \\\n    r0i = ri;                                                           \\\n    ri += m;                                                            \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (! nanflag && j < n)                                      \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (v[i]) &&                       \\\n                    octave::math::isnan (r0[i]))                        \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n                else if (octave::math::isnan (v[i]))                    \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (v[i].real () OP r0[i].real ())                 \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (v[i].real () == r0[i].real () &&               \\\n                         v[i].imag () OP r0[i].imag ())                 \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n        while (nanflag && j < n)                                        \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r0[i]) &&                      \\\n                    octave::math::isnan (v[i]))                         \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n                else if (octave::math::isnan (r0[i]))                   \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (v[i].real () OP r0[i].real ())                 \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (v[i].real () == r0[i].real () &&               \\\n                         v[i].imag () OP r0[i].imag ())                 \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (! nanflag && j < n)                                      \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (v[i]) &&                       \\\n                    octave::math::isnan (r0[i]))                        \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n                else if (octave::math::isnan (v[i]))                    \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (std::abs (v[i]) OP std::abs (r0[i]))           \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (std::abs (v[i]) == std::abs (r0[i]) &&         \\\n                         std::arg (v[i]) OP std::arg (r0[i]))           \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n        while (nanflag && j < n)                                        \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (octave::math::isnan (r0[i]) &&                      \\\n                    octave::math::isnan (v[i]))                         \\\n                  {                                                     \\\n                    r[i] = NAN;                                         \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n                else if (octave::math::isnan (r0[i]))                   \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (std::abs (v[i]) OP std::abs (r0[i]))           \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (std::abs (v[i]) == std::abs (r0[i]) &&         \\\n                         std::arg (v[i]) OP std::arg (r0[i]))           \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_CCUMMINMAX_FCN2 (mx_inline_ccummin, <)\nOP_CCUMMINMAX_FCN2 (mx_inline_ccummax, >)\n\n#define OP_CCUMMINMAX_FCNN(F)                                   \\\n  template <typename T>                                         \\\n  inline void                                                   \\\n  F (const T *v, T *r, octave_idx_type l, octave_idx_type n,    \\\n     octave_idx_type u, const bool nanflag, const bool realabs) \\\n  {                                                             \\\n    if (! n)                                                    \\\n      return;                                                   \\\n    if (l == 1)                                                 \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, n, nanflag, realabs);                      \\\n            v += n;                                             \\\n            r += n;                                             \\\n          }                                                     \\\n      }                                                         \\\n    else                                                        \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, l, n, nanflag, realabs);                   \\\n            v += l*n;                                           \\\n            r += l*n;                                           \\\n          }                                                     \\\n      }                                                         \\\n  }                                                             \\\n  template <typename T>                                         \\\n  inline void                                                   \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type l,  \\\n     octave_idx_type n, octave_idx_type u, const bool nanflag,  \\\n     const bool realabs)                                        \\\n  {                                                             \\\n    if (! n)                                                    \\\n      return;                                                   \\\n    if (l == 1)                                                 \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, ri, n, nanflag, realabs);                  \\\n            v += n;                                             \\\n            r += n;                                             \\\n            ri += n;                                            \\\n          }                                                     \\\n      }                                                         \\\n    else                                                        \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, ri, l, n, nanflag, realabs);               \\\n            v += l*n;                                           \\\n            r += l*n;                                           \\\n            ri += l*n;                                          \\\n          }                                                     \\\n      }                                                         \\\n  }\n\nOP_CCUMMINMAX_FCNN (mx_inline_ccummin)\nOP_CCUMMINMAX_FCNN (mx_inline_ccummax)\n\n// Faster implementation for int arrays, since they do not support\n// NaN values and real/abs comparison methods require specialized mapper.\n\n#define OP_INT_CUMMINMAX_FCN(F, OP)                                     \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type n, const bool realabs)      \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type i = 1;                                              \\\n    octave_idx_type j = 0;                                              \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          if (v[i] OP tmp)                                              \\\n            {                                                           \\\n              for (; j < i; j++)                                        \\\n                r[j] = tmp;                                             \\\n              tmp = v[i];                                               \\\n            }                                                           \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (mappers_abs (v[i]) OP mappers_abs (tmp))                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                tmp = v[i];                                             \\\n              }                                                         \\\n            else if (mappers_abs (v[i]) == mappers_abs (tmp) &&         \\\n                     v[i] OP tmp)                                       \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  r[j] = tmp;                                           \\\n                tmp = v[i];                                             \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    for (; j < i; j++)                                                  \\\n      r[j] = tmp;                                                       \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n,     \\\n          const bool realabs)                                           \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    T tmp = v[0];                                                       \\\n    octave_idx_type tmpi = 0;                                           \\\n    octave_idx_type i = 1;                                              \\\n    octave_idx_type j = 0;                                              \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          if (v[i] OP tmp)                                              \\\n            {                                                           \\\n              for (; j < i; j++)                                        \\\n                {                                                       \\\n                  r[j] = tmp;                                           \\\n                  ri[j] = tmpi;                                         \\\n                }                                                       \\\n              tmp = v[i];                                               \\\n              tmpi = i;                                                 \\\n            }                                                           \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        for (; i < n; i++)                                              \\\n          {                                                             \\\n            if (mappers_abs (v[i]) OP mappers_abs (tmp))                \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n            else if (mappers_abs (v[i]) == mappers_abs (tmp) &&         \\\n                     v[i] OP tmp)                                       \\\n              {                                                         \\\n                for (; j < i; j++)                                      \\\n                  {                                                     \\\n                    r[j] = tmp;                                         \\\n                    ri[j] = tmpi;                                       \\\n                  }                                                     \\\n                tmp = v[i];                                             \\\n                tmpi = i;                                               \\\n              }                                                         \\\n          }                                                             \\\n      }                                                                 \\\n    for (; j < i; j++)                                                  \\\n      {                                                                 \\\n        r[j] = tmp;                                                     \\\n        ri[j] = tmpi;                                                   \\\n      }                                                                 \\\n  }\n\nOP_INT_CUMMINMAX_FCN (mx_inline_intcummin, <)\nOP_INT_CUMMINMAX_FCN (mx_inline_intcummax, >)\n\n#define OP_INT_CUMMINMAX_FCN2(F, OP)                                    \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type m, octave_idx_type n,            \\\n     const bool realabs)                                                \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    const T *r0;                                                        \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      {                                                                 \\\n        r[i] = v[i];                                                    \\\n      }                                                                 \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    r0 = r;                                                             \\\n    r += m;                                                             \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (v[i] OP r0[i])                                      \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (mappers_abs (v[i]) OP mappers_abs (r0[i]))          \\\n                  r[i] = v[i];                                          \\\n                else if (mappers_abs (v[i]) == mappers_abs (r0[i]) &&   \\\n                         v[i] OP r0[i])                                 \\\n                  r[i] = v[i];                                          \\\n                else                                                    \\\n                  r[i] = r0[i];                                         \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n          }                                                             \\\n      }                                                                 \\\n  }                                                                     \\\n  template <typename T>                                                 \\\n  inline void                                                           \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type m,          \\\n     octave_idx_type n, const bool realabs)                             \\\n  {                                                                     \\\n    if (! n)                                                            \\\n      return;                                                           \\\n    const T *r0;                                                        \\\n    const octave_idx_type *r0i;                                         \\\n    octave_idx_type j = 0;                                              \\\n    for (octave_idx_type i = 0; i < m; i++)                             \\\n      {                                                                 \\\n        r[i] = v[i]; ri[i] = 0;                                         \\\n      }                                                                 \\\n    j++;                                                                \\\n    v += m;                                                             \\\n    r0 = r;                                                             \\\n    r += m;                                                             \\\n    r0i = ri;                                                           \\\n    ri += m;                                                            \\\n    if (realabs)                                                        \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (v[i] OP r0[i])                                      \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        while (j < n)                                                   \\\n          {                                                             \\\n            for (octave_idx_type i = 0; i < m; i++)                     \\\n              {                                                         \\\n                if (mappers_abs (v[i]) OP mappers_abs (r0[i]))          \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else if (mappers_abs (v[i]) == mappers_abs (r0[i])      \\\n                         && v[i] OP r0[i])                              \\\n                  {                                                     \\\n                    r[i] = v[i];                                        \\\n                    ri[i] = j;                                          \\\n                  }                                                     \\\n                else                                                    \\\n                  {                                                     \\\n                    r[i] = r0[i];                                       \\\n                    ri[i] = r0i[i];                                     \\\n                  }                                                     \\\n              }                                                         \\\n            j++;                                                        \\\n            v += m;                                                     \\\n            r0 = r;                                                     \\\n            r += m;                                                     \\\n            r0i = ri;                                                   \\\n            ri += m;                                                    \\\n          }                                                             \\\n      }                                                                 \\\n  }\n\nOP_INT_CUMMINMAX_FCN2 (mx_inline_intcummin, <)\nOP_INT_CUMMINMAX_FCN2 (mx_inline_intcummax, >)\n\n#define OP_INT_CUMMINMAX_FCNN(F)                                \\\n  template <typename T>                                         \\\n  inline void                                                   \\\n  F (const T *v, T *r, octave_idx_type l, octave_idx_type n,    \\\n     octave_idx_type u, const bool realabs)                     \\\n  {                                                             \\\n    if (! n)                                                    \\\n      return;                                                   \\\n    if (l == 1)                                                 \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, n, realabs);                               \\\n            v += n;                                             \\\n            r += n;                                             \\\n          }                                                     \\\n      }                                                         \\\n    else                                                        \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, l, n, realabs);                            \\\n            v += l*n;                                           \\\n            r += l*n;                                           \\\n          }                                                     \\\n      }                                                         \\\n  }                                                             \\\n  template <typename T>                                         \\\n  inline void                                                   \\\n  F (const T *v, T *r, octave_idx_type *ri, octave_idx_type l,  \\\n     octave_idx_type n, octave_idx_type u, const bool realabs)  \\\n  {                                                             \\\n    if (! n)                                                    \\\n      return;                                                   \\\n    if (l == 1)                                                 \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, ri, n, realabs);                           \\\n            v += n;                                             \\\n            r += n;                                             \\\n            ri += n;                                            \\\n          }                                                     \\\n      }                                                         \\\n    else                                                        \\\n      {                                                         \\\n        for (octave_idx_type i = 0; i < u; i++)                 \\\n          {                                                     \\\n            F (v, r, ri, l, n, realabs);                        \\\n            v += l*n;                                           \\\n            r += l*n;                                           \\\n            ri += l*n;                                          \\\n          }                                                     \\\n      }                                                         \\\n  }\n\nOP_INT_CUMMINMAX_FCNN (mx_inline_intcummin)\nOP_INT_CUMMINMAX_FCNN (mx_inline_intcummax)\n\ntemplate <typename T>\nvoid mx_inline_diff (const T *v, T *r, octave_idx_type n,\n                     octave_idx_type order)\n{\n  switch (order)\n    {\n    case 1:\n      for (octave_idx_type i = 0; i < n-1; i++)\n        r[i] = v[i+1] - v[i];\n      break;\n    case 2:\n      if (n > 1)\n        {\n          T lst = v[1] - v[0];\n          for (octave_idx_type i = 0; i < n-2; i++)\n            {\n              T dif = v[i+2] - v[i+1];\n              r[i] = dif - lst;\n              lst = dif;\n            }\n        }\n      break;\n    default:\n      {\n        OCTAVE_LOCAL_BUFFER (T, buf, n-1);\n\n        for (octave_idx_type i = 0; i < n-1; i++)\n          buf[i] = v[i+1] - v[i];\n\n        for (octave_idx_type o = 2; o <= order; o++)\n          {\n            for (octave_idx_type i = 0; i < n-o; i++)\n              buf[i] = buf[i+1] - buf[i];\n          }\n\n        for (octave_idx_type i = 0; i < n-order; i++)\n          r[i] = buf[i];\n      }\n    }\n}\n\ntemplate <typename T>\nvoid\nmx_inline_diff (const T *v, T *r,\n                octave_idx_type m, octave_idx_type n,\n                octave_idx_type order)\n{\n  switch (order)\n    {\n    case 1:\n      for (octave_idx_type i = 0; i < m*(n-1); i++)\n        r[i] = v[i+m] - v[i];\n      break;\n    case 2:\n      for (octave_idx_type i = 0; i < n-2; i++)\n        {\n          for (octave_idx_type j = i*m; j < i*m+m; j++)\n            r[j] = (v[j+m+m] - v[j+m]) - (v[j+m] - v[j]);\n        }\n      break;\n    default:\n      {\n        OCTAVE_LOCAL_BUFFER (T, buf, n-1);\n\n        for (octave_idx_type j = 0; j < m; j++)\n          {\n            for (octave_idx_type i = 0; i < n-1; i++)\n              buf[i] = v[i*m+j+m] - v[i*m+j];\n\n            for (octave_idx_type o = 2; o <= order; o++)\n              {\n                for (octave_idx_type i = 0; i < n-o; i++)\n                  buf[i] = buf[i+1] - buf[i];\n              }\n\n            for (octave_idx_type i = 0; i < n-order; i++)\n              r[i*m+j] = buf[i];\n          }\n      }\n    }\n}\n\ntemplate <typename T>\ninline void\nmx_inline_diff (const T *v, T *r,\n                octave_idx_type l, octave_idx_type n, octave_idx_type u,\n                octave_idx_type order)\n{\n  if (! n) return;\n  if (l == 1)\n    {\n      for (octave_idx_type i = 0; i < u; i++)\n        {\n          mx_inline_diff (v, r, n, order);\n          v += n; r += n-order;\n        }\n    }\n  else\n    {\n      for (octave_idx_type i = 0; i < u; i++)\n        {\n          mx_inline_diff (v, r, l, n, order);\n          v += l*n;\n          r += l*(n-order);\n        }\n    }\n}\n\n// Assistant function\n\ninline void\nget_extent_triplet (const dim_vector& dims, int& dim,\n                    octave_idx_type& l, octave_idx_type& n,\n                    octave_idx_type& u)\n{\n  octave_idx_type ndims = dims.ndims ();\n  if (dim >= ndims)\n    {\n      l = dims.numel ();\n      n = 1;\n      u = 1;\n    }\n  else\n    {\n      if (dim < 0)\n        dim = dims.first_non_singleton ();\n\n      // calculate extent triplet.\n      l = 1, n = dims(dim), u = 1;\n      for (octave_idx_type i = 0; i < dim; i++)\n        l *= dims(i);\n      for (octave_idx_type i = dim + 1; i < ndims; i++)\n        u *= dims(i);\n    }\n}\n\n// For char and octave_int arrays\n\ntemplate <typename R, typename T>\ninline Array<R>\ndo_mx_red_op (const Array<T>& src, int dim,\n              void (*mx_red_op) (const T *, R *, octave_idx_type,\n                                 octave_idx_type, octave_idx_type))\n{\n  octave_idx_type l, n, u;\n  dim_vector dims = src.dims ();\n\n  // Handle 0x0 empty array\n  if (dims.ndims () == 2 && dims(0) == 0 && dims(1) == 0 && dim == -1)\n    dims(1) = 1;\n\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // Reduction operation reduces the array size.\n  if (dim < dims.ndims ()) dims(dim) = 1;\n  dims.chop_trailing_singletons ();\n\n  Array<R> ret (dims);\n  mx_red_op (src.data (), ret.rwdata (), l, n, u);\n\n  return ret;\n}\n\n// For double, float, and complex arrays\n\ntemplate <typename R, typename T>\ninline Array<R>\ndo_mx_red_op (const Array<T>& src, int dim, bool nanflag,\n              void (*mx_red_op) (const T *, R *, octave_idx_type,\n                                 octave_idx_type, octave_idx_type, bool))\n{\n  octave_idx_type l, n, u;\n  dim_vector dims = src.dims ();\n\n  // Handle 0x0 empty array\n  if (dims.ndims () == 2 && dims(0) == 0 && dims(1) == 0 && dim == -1)\n    dims(1) = 1;\n\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // Reduction operation reduces the array size.\n  if (dim < dims.ndims ()) dims(dim) = 1;\n  dims.chop_trailing_singletons ();\n\n  Array<R> ret (dims);\n  mx_red_op (src.data (), ret.rwdata (), l, n, u, nanflag);\n\n  return ret;\n}\n\ntemplate <typename R, typename T>\ninline Array<R>\ndo_mx_flip_op (const Array<T>& src, int dim,\n               void (*mx_flip_op) (const T *, R *, octave_idx_type,\n                                   octave_idx_type, octave_idx_type))\n{\n  octave_idx_type l, n, u;\n  const dim_vector& dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // Cumulative operation doesn't reduce the array size.\n  Array<R> ret (dims);\n  mx_flip_op (src.data (), ret.rwdata (), l, n, u);\n\n  return ret;\n}\n\ntemplate <typename R, typename T>\ninline Array<R>\ndo_mx_cum_op (const Array<T>& src, int dim,\n              void (*mx_cum_op) (const T *, R *, octave_idx_type,\n                                 octave_idx_type, octave_idx_type))\n{\n  octave_idx_type l, n, u;\n  const dim_vector& dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // Cumulative operation doesn't reduce the array size.\n  Array<R> ret (dims);\n  mx_cum_op (src.data (), ret.rwdata (), l, n, u);\n\n  return ret;\n}\n\ntemplate <typename R, typename T>\ninline Array<R>\ndo_mx_cum_op (const Array<T>& src, int dim, bool nanflag,\n              void (*mx_cum_op) (const T *, R *, octave_idx_type,\n                                 octave_idx_type, octave_idx_type, bool))\n{\n  octave_idx_type l, n, u;\n  const dim_vector& dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // Cumulative operation doesn't reduce the array size.\n  Array<R> ret (dims);\n  mx_cum_op (src.data (), ret.rwdata (), l, n, u, nanflag);\n\n  return ret;\n}\n\n// For double, float, and complex arrays\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_minmax_op (const Array<R>& src, int dim, bool nanflag, bool realabs,\n                 void (*mx_minmax_op) (const R *, R *, octave_idx_type,\n                                       octave_idx_type, octave_idx_type,\n                                       bool, bool))\n{\n  octave_idx_type l, n, u;\n  dim_vector dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // If the dimension is zero, we don't do anything.\n  if (dim < dims.ndims () && dims(dim) != 0) dims(dim) = 1;\n  dims.chop_trailing_singletons ();\n\n  Array<R> ret (dims);\n  mx_minmax_op (src.data (), ret.rwdata (), l, n, u, nanflag, realabs);\n\n  return ret;\n}\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_minmax_op (const Array<R>& src, Array<octave_idx_type>& idx, int dim,\n                 bool nanflag, bool realabs,\n                 void (*mx_minmax_op) (const R *, R *, octave_idx_type *,\n                                       octave_idx_type, octave_idx_type,\n                                       octave_idx_type, bool, bool))\n{\n  octave_idx_type l, n, u;\n  dim_vector dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // If the dimension is zero, we don't do anything.\n  if (dim < dims.ndims () && dims(dim) != 0) dims(dim) = 1;\n  dims.chop_trailing_singletons ();\n\n  Array<R> ret (dims);\n  if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);\n\n  mx_minmax_op (src.data (), ret.rwdata (), idx.rwdata (),\n                l, n, u, nanflag, realabs);\n\n  return ret;\n}\n\n// For octave_int arrays\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_minmax_op (const Array<R>& src, int dim, bool realabs,\n                 void (*mx_minmax_op) (const R *, R *, octave_idx_type,\n                                       octave_idx_type, octave_idx_type, bool))\n{\n  octave_idx_type l, n, u;\n  dim_vector dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // If the dimension is zero, we don't do anything.\n  if (dim < dims.ndims () && dims(dim) != 0) dims(dim) = 1;\n  dims.chop_trailing_singletons ();\n\n  Array<R> ret (dims);\n  mx_minmax_op (src.data (), ret.rwdata (), l, n, u, realabs);\n\n  return ret;\n}\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_minmax_op (const Array<R>& src, Array<octave_idx_type>& idx, int dim,\n                 bool realabs,\n                 void (*mx_minmax_op) (const R *, R *, octave_idx_type *,\n                                       octave_idx_type, octave_idx_type,\n                                       octave_idx_type, bool))\n{\n  octave_idx_type l, n, u;\n  dim_vector dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // If the dimension is zero, we don't do anything.\n  if (dim < dims.ndims () && dims(dim) != 0) dims(dim) = 1;\n  dims.chop_trailing_singletons ();\n\n  Array<R> ret (dims);\n  if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);\n\n  mx_minmax_op (src.data (), ret.rwdata (), idx.rwdata (), l, n, u, realabs);\n\n  return ret;\n}\n\n// For char arrays\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_minmax_op (const Array<R>& src, int dim,\n                 void (*mx_minmax_op) (const R *, R *, octave_idx_type,\n                                       octave_idx_type, octave_idx_type))\n{\n  octave_idx_type l, n, u;\n  dim_vector dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // If the dimension is zero, we don't do anything.\n  if (dim < dims.ndims () && dims(dim) != 0) dims(dim) = 1;\n  dims.chop_trailing_singletons ();\n\n  Array<R> ret (dims);\n  mx_minmax_op (src.data (), ret.rwdata (), l, n, u);\n\n  return ret;\n}\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_minmax_op (const Array<R>& src, Array<octave_idx_type>& idx, int dim,\n                 void (*mx_minmax_op) (const R *, R *, octave_idx_type *,\n                                       octave_idx_type, octave_idx_type,\n                                       octave_idx_type))\n{\n  octave_idx_type l, n, u;\n  dim_vector dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  // If the dimension is zero, we don't do anything.\n  if (dim < dims.ndims () && dims(dim) != 0) dims(dim) = 1;\n  dims.chop_trailing_singletons ();\n\n  Array<R> ret (dims);\n  if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);\n\n  mx_minmax_op (src.data (), ret.rwdata (), idx.rwdata (), l, n, u);\n\n  return ret;\n}\n\n// For double, float, and complex arrays\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_cumminmax_op (const Array<R>& src, int dim, bool nanflag, bool realabs,\n                    void (*mx_cumminmax_op) (const R *, R *, octave_idx_type,\n                                             octave_idx_type, octave_idx_type,\n                                             bool, bool))\n{\n  octave_idx_type l, n, u;\n  const dim_vector& dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  Array<R> ret (dims);\n  mx_cumminmax_op (src.data (), ret.rwdata (), l, n, u, nanflag, realabs);\n\n  return ret;\n}\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_cumminmax_op (const Array<R>& src, Array<octave_idx_type>& idx, int dim,\n                    bool nanflag, bool realabs,\n                    void (*mx_cumminmax_op) (const R *, R *, octave_idx_type *,\n                                             octave_idx_type, octave_idx_type,\n                                             octave_idx_type, bool, bool))\n{\n  octave_idx_type l, n, u;\n  const dim_vector& dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  Array<R> ret (dims);\n  if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);\n\n  mx_cumminmax_op (src.data (), ret.rwdata (), idx.rwdata (),\n                   l, n, u, nanflag, realabs);\n\n  return ret;\n}\n\n// For octave_int arrays\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_cumminmax_op (const Array<R>& src, int dim, bool realabs,\n                    void (*mx_cumminmax_op) (const R *, R *, octave_idx_type,\n                                             octave_idx_type, octave_idx_type,\n                                             bool))\n{\n  octave_idx_type l, n, u;\n  const dim_vector& dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  Array<R> ret (dims);\n  mx_cumminmax_op (src.data (), ret.rwdata (), l, n, u, realabs);\n\n  return ret;\n}\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_cumminmax_op (const Array<R>& src, Array<octave_idx_type>& idx, int dim,\n                    bool realabs,\n                    void (*mx_cumminmax_op) (const R *, R *, octave_idx_type *,\n                                             octave_idx_type, octave_idx_type,\n                                             octave_idx_type, bool))\n{\n  octave_idx_type l, n, u;\n  const dim_vector& dims = src.dims ();\n  get_extent_triplet (dims, dim, l, n, u);\n\n  Array<R> ret (dims);\n  if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);\n\n  mx_cumminmax_op (src.data (), ret.rwdata (), idx.rwdata (),\n                   l, n, u, realabs);\n\n  return ret;\n}\n\ntemplate <typename R>\ninline Array<R>\ndo_mx_diff_op (const Array<R>& src, int dim, octave_idx_type order,\n               void (*mx_diff_op) (const R *, R *,\n                                   octave_idx_type, octave_idx_type,\n                                   octave_idx_type, octave_idx_type))\n{\n  octave_idx_type l, n, u;\n  if (order <= 0)\n    return src;\n\n  dim_vector dims = src.dims ();\n\n  get_extent_triplet (dims, dim, l, n, u);\n  if (dim >= dims.ndims ())\n    dims.resize (dim+1, 1);\n\n  if (dims(dim) <= order)\n    {\n      dims(dim) = 0;\n      return Array<R> (dims);\n    }\n  else\n    {\n      dims(dim) -= order;\n    }\n\n  Array<R> ret (dims);\n  mx_diff_op (src.data (), ret.rwdata (), l, n, u, order);\n\n  return ret;\n}\n\n// Fast extra-precise summation.\n// Reference: T. Ogita, S. M. Rump, S. Oishi,\n// \"Accurate Sum And Dot Product\",\n// SIAM J. Sci. Computing, Vol. 26, 2005\n\n// Safe implementation (Standard API).\n// Handles overflows to infinity correctly to prevent NaN pollution in error term.\ntemplate <typename T>\ninline void\ntwosum_accum (T& s, T& e, const T& x)\n{\n  const T s1 = s + x;\n\n  // If sum becomes non-finite (overflow to +/-Inf), do NOT update the\n  // compensation term (avoids Inf-Inf -> NaN in e).\n  if (! octave::math::isfinite (s1))\n    {\n      s = s1;\n      e = T (0);\n      return;\n    }\n\n  const T t  = s1 - s;\n  const T e1 = (s - (s1 - t)) + (x - t);\n\n  s = s1;\n  e += e1;\n}\n\n// Overload with three arguments for vectors (Contiguous / Vector)\n// Used for column sums or simple vector reductions.\ntemplate <typename T>\ninline T\nmx_inline_xsum (const T *v, octave_idx_type n, bool nanflag)\n{\n  T s = 0, e = 0;\n  const T zero = 0;\n  bool posinf = false;\n  bool neginf = false;\n  bool seen_nan = false;\n\n  for (octave_idx_type i = 0; i < n; ++i)\n    {\n      const T val = v[i];\n\n      if (octave::math::isnan (val))\n        {\n          if (nanflag)           // omitnan\n            continue;\n          else                   // normal sum: NaN dominates everything\n            {\n              seen_nan = true;\n              break;\n            }\n        }\n\n      if (! octave::math::isinf (val))\n        twosum_accum (s, e, val);\n      else if (val > zero)\n        posinf = true;\n      else\n        neginf = true;\n    }\n\n  if (octave::math::isinf (s))\n    {\n      if (s > zero)\n        posinf = true;\n      else\n        neginf = true;\n    }\n\n  if (seen_nan)\n    return std::numeric_limits<T>::quiet_NaN ();\n\n  if (posinf && neginf)\n    return std::numeric_limits<T>::quiet_NaN ();\n  else if (posinf)\n    return std::numeric_limits<T>::infinity ();\n  else if (neginf)\n    return -std::numeric_limits<T>::infinity ();\n\n  return s + e;\n}\n\n// Overload with five arguments for matrices (strided)\ntemplate <typename T>\ninline void\nmx_inline_xsum (const T *v, T *r,\n                octave_idx_type l, octave_idx_type n, bool nanflag)\n{\n  const T zero = 0;\n\n  for (octave_idx_type i = 0; i < l; ++i)\n    {\n      T s = 0, e = 0;\n      bool posinf = false;\n      bool neginf = false;\n      bool seen_nan = false;\n\n      for (octave_idx_type j = 0; j < n; ++j)\n        {\n          const T val = v[i + j*l];\n\n          if (octave::math::isnan (val))\n            {\n              if (nanflag)          // omitnan\n                continue;\n              else\n                {\n                  seen_nan = true;\n                  break;\n                }\n            }\n\n          if (! octave::math::isinf (val))\n            twosum_accum (s, e, val);\n          else if (val > zero)\n            posinf = true;\n          else\n            neginf = true;\n        }\n\n      if (octave::math::isinf (s))\n        {\n          if (s > zero)\n            posinf = true;\n          else\n            neginf = true;\n        }\n\n      if (seen_nan || (posinf && neginf))\n        r[i] = std::numeric_limits<T>::quiet_NaN ();\n      else if (posinf)\n        r[i] = std::numeric_limits<T>::infinity ();\n      else if (neginf)\n        r[i] = -std::numeric_limits<T>::infinity ();\n      else\n        r[i] = s + e;\n    }\n}\n\nOP_RED_NAN_FCNN (mx_inline_xsum, T, T)\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/mx-op-decl.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mx_op_decl_h)\n#define octave_mx_op_decl_h 1\n\n#include \"octave-config.h\"\n\n#define BIN_OP_DECL(R, OP, X, Y, API)           \\\n  extern API R OP (const X&, const Y&)\n\n#include \"mx-fwd.h\"\n\n#define CMP_OP_DECL(OP, X, Y, API)              \\\n  extern API boolMatrix OP (const X&, const Y&)\n\n#define NDCMP_OP_DECL(OP, X, Y, API)                    \\\n  extern API boolNDArray OP (const X&, const Y&)\n\n#define BOOL_OP_DECL(OP, X, Y, API)             \\\n  extern API boolMatrix OP (const X&, const Y&)\n\n#define NDBOOL_OP_DECL(OP, X, Y, API)                   \\\n  extern API boolNDArray OP (const X&, const Y&)\n\n// vector by scalar operations.\n\n#define VS_BIN_OP_DECLS(R, V, S, API)           \\\n  BIN_OP_DECL (R, operator +, V, S, API);       \\\n  BIN_OP_DECL (R, operator -, V, S, API);       \\\n  BIN_OP_DECL (R, operator *, V, S, API);       \\\n  BIN_OP_DECL (R, operator /, V, S, API);\n\n#define VS_OP_DECLS(R, V, S, API)               \\\n  VS_BIN_OP_DECLS(R, V, S, API)\n\n// scalar by vector by operations.\n\n#define SV_BIN_OP_DECLS(R, S, V, API)           \\\n  BIN_OP_DECL (R, operator +, S, V, API);       \\\n  BIN_OP_DECL (R, operator -, S, V, API);       \\\n  BIN_OP_DECL (R, operator *, S, V, API);       \\\n  BIN_OP_DECL (R, operator /, S, V, API);\n\n#define SV_OP_DECLS(R, S, V, API)               \\\n  SV_BIN_OP_DECLS(R, S, V, API)\n\n// vector by vector operations.\n\n#define VV_BIN_OP_DECLS(R, V1, V2, API)         \\\n  BIN_OP_DECL (R, operator +, V1, V2, API);     \\\n  BIN_OP_DECL (R, operator -, V1, V2, API);     \\\n  BIN_OP_DECL (R, product,    V1, V2, API);     \\\n  BIN_OP_DECL (R, quotient,   V1, V2, API);\n\n#define VV_OP_DECLS(R, V1, V2, API)             \\\n  VV_BIN_OP_DECLS(R, V1, V2, API)\n\n// matrix by scalar operations.\n\n#define MS_BIN_OP_DECLS(R, M, S, API)           \\\n  BIN_OP_DECL (R, operator +, M, S, API);       \\\n  BIN_OP_DECL (R, operator -, M, S, API);       \\\n  BIN_OP_DECL (R, operator *, M, S, API);       \\\n  BIN_OP_DECL (R, operator /, M, S, API);\n\n#define MS_CMP_OP_DECLS(M, S, API)              \\\n  CMP_OP_DECL (mx_el_lt, M, S, API);            \\\n  CMP_OP_DECL (mx_el_le, M, S, API);            \\\n  CMP_OP_DECL (mx_el_ge, M, S, API);            \\\n  CMP_OP_DECL (mx_el_gt, M, S, API);            \\\n  CMP_OP_DECL (mx_el_eq, M, S, API);            \\\n  CMP_OP_DECL (mx_el_ne, M, S, API);\n\n#define MS_BOOL_OP_DECLS(M, S, API)             \\\n  BOOL_OP_DECL (mx_el_and, M, S, API);          \\\n  BOOL_OP_DECL (mx_el_or,  M, S, API);          \\\n\n#define MS_OP_DECLS(R, M, S, API)               \\\n  MS_BIN_OP_DECLS (R, M, S, API)                \\\n  MS_CMP_OP_DECLS (M, S, API)                   \\\n  MS_BOOL_OP_DECLS (M, S, API)                  \\\n\n// scalar by matrix operations.\n\n#define SM_BIN_OP_DECLS(R, S, M, API)           \\\n  BIN_OP_DECL (R, operator +, S, M, API);       \\\n  BIN_OP_DECL (R, operator -, S, M, API);       \\\n  BIN_OP_DECL (R, operator *, S, M, API);       \\\n  BIN_OP_DECL (R, operator /, S, M, API);\n\n#define SM_CMP_OP_DECLS(S, M, API)              \\\n  CMP_OP_DECL (mx_el_lt, S, M, API);            \\\n  CMP_OP_DECL (mx_el_le, S, M, API);            \\\n  CMP_OP_DECL (mx_el_ge, S, M, API);            \\\n  CMP_OP_DECL (mx_el_gt, S, M, API);            \\\n  CMP_OP_DECL (mx_el_eq, S, M, API);            \\\n  CMP_OP_DECL (mx_el_ne, S, M, API);\n\n#define SM_BOOL_OP_DECLS(S, M, API)             \\\n  BOOL_OP_DECL (mx_el_and, S, M, API);          \\\n  BOOL_OP_DECL (mx_el_or,  S, M, API);          \\\n\n#define SM_OP_DECLS(R, S, M, API)               \\\n  SM_BIN_OP_DECLS (R, S, M, API)                \\\n  SM_CMP_OP_DECLS (S, M, API)                   \\\n  SM_BOOL_OP_DECLS (S, M, API)                  \\\n\n// matrix by matrix operations.\n\n#define MM_BIN_OP_DECLS(R, M1, M2, API)         \\\n  BIN_OP_DECL (R, operator +, M1, M2, API);     \\\n  BIN_OP_DECL (R, operator -, M1, M2, API);     \\\n  BIN_OP_DECL (R, product,    M1, M2, API);     \\\n  BIN_OP_DECL (R, quotient,   M1, M2, API);\n\n#define MM_CMP_OP_DECLS(M1, M2, API)            \\\n  CMP_OP_DECL (mx_el_lt, M1, M2, API);          \\\n  CMP_OP_DECL (mx_el_le, M1, M2, API);          \\\n  CMP_OP_DECL (mx_el_ge, M1, M2, API);          \\\n  CMP_OP_DECL (mx_el_gt, M1, M2, API);          \\\n  CMP_OP_DECL (mx_el_eq, M1, M2, API);          \\\n  CMP_OP_DECL (mx_el_ne, M1, M2, API);\n\n#define MM_BOOL_OP_DECLS(M1, M2, API)           \\\n  BOOL_OP_DECL (mx_el_and, M1, M2, API);        \\\n  BOOL_OP_DECL (mx_el_or,  M1, M2, API);\n\n#define MM_OP_DECLS(R, M1, M2, API)             \\\n  MM_BIN_OP_DECLS (R, M1, M2, API)              \\\n  MM_CMP_OP_DECLS (M1, M2, API)                 \\\n  MM_BOOL_OP_DECLS (M1, M2, API)\n\n// N-D matrix by scalar operations.\n\n#define NDS_BIN_OP_DECLS(R, ND, S, API)         \\\n  BIN_OP_DECL (R, operator +, ND, S, API);      \\\n  BIN_OP_DECL (R, operator -, ND, S, API);      \\\n  BIN_OP_DECL (R, operator *, ND, S, API);      \\\n  BIN_OP_DECL (R, operator /, ND, S, API);\n\n#define NDS_CMP_OP_DECLS(ND, S, API)            \\\n  NDCMP_OP_DECL (mx_el_lt, ND, S, API);         \\\n  NDCMP_OP_DECL (mx_el_le, ND, S, API);         \\\n  NDCMP_OP_DECL (mx_el_ge, ND, S, API);         \\\n  NDCMP_OP_DECL (mx_el_gt, ND, S, API);         \\\n  NDCMP_OP_DECL (mx_el_eq, ND, S, API);         \\\n  NDCMP_OP_DECL (mx_el_ne, ND, S, API);\n\n#define NDS_BOOL_OP_DECLS(ND, S, API)           \\\n  NDBOOL_OP_DECL (mx_el_and, ND, S, API);       \\\n  NDBOOL_OP_DECL (mx_el_or,  ND, S, API);       \\\n  NDBOOL_OP_DECL (mx_el_not_and, ND, S, API);   \\\n  NDBOOL_OP_DECL (mx_el_not_or,  ND, S, API);\n\n#define NDS_OP_DECLS(R, ND, S, API)             \\\n  NDS_BIN_OP_DECLS (R, ND, S, API)              \\\n  NDS_CMP_OP_DECLS (ND, S, API)                 \\\n  NDS_BOOL_OP_DECLS (ND, S, API)\n\n// scalar by N-D matrix operations.\n\n#define SND_BIN_OP_DECLS(R, S, ND, API)         \\\n  BIN_OP_DECL (R, operator +, S, ND, API);      \\\n  BIN_OP_DECL (R, operator -, S, ND, API);      \\\n  BIN_OP_DECL (R, operator *, S, ND, API);      \\\n  BIN_OP_DECL (R, operator /, S, ND, API);\n\n#define SND_CMP_OP_DECLS(S, ND, API)            \\\n  NDCMP_OP_DECL (mx_el_lt, S, ND, API);         \\\n  NDCMP_OP_DECL (mx_el_le, S, ND, API);         \\\n  NDCMP_OP_DECL (mx_el_ge, S, ND, API);         \\\n  NDCMP_OP_DECL (mx_el_gt, S, ND, API);         \\\n  NDCMP_OP_DECL (mx_el_eq, S, ND, API);         \\\n  NDCMP_OP_DECL (mx_el_ne, S, ND, API);\n\n#define SND_BOOL_OP_DECLS(S, ND, API)           \\\n  NDBOOL_OP_DECL (mx_el_and, S, ND, API);       \\\n  NDBOOL_OP_DECL (mx_el_or,  S, ND, API);       \\\n  NDBOOL_OP_DECL (mx_el_and_not, S, ND, API);   \\\n  NDBOOL_OP_DECL (mx_el_or_not,  S, ND, API);\n\n#define SND_OP_DECLS(R, S, ND, API)             \\\n  SND_BIN_OP_DECLS (R, S, ND, API)              \\\n  SND_CMP_OP_DECLS (S, ND, API)                 \\\n  SND_BOOL_OP_DECLS (S, ND, API)\n\n// N-D matrix by N-D matrix operations.\n\n#define NDND_BIN_OP_DECLS(R, ND1, ND2, API)     \\\n  BIN_OP_DECL (R, operator +, ND1, ND2, API);   \\\n  BIN_OP_DECL (R, operator -, ND1, ND2, API);   \\\n  BIN_OP_DECL (R, product,    ND1, ND2, API);   \\\n  BIN_OP_DECL (R, quotient,   ND1, ND2, API);\n\n#define NDND_CMP_OP_DECLS(ND1, ND2, API)        \\\n  NDCMP_OP_DECL (mx_el_lt, ND1, ND2, API);      \\\n  NDCMP_OP_DECL (mx_el_le, ND1, ND2, API);      \\\n  NDCMP_OP_DECL (mx_el_ge, ND1, ND2, API);      \\\n  NDCMP_OP_DECL (mx_el_gt, ND1, ND2, API);      \\\n  NDCMP_OP_DECL (mx_el_eq, ND1, ND2, API);      \\\n  NDCMP_OP_DECL (mx_el_ne, ND1, ND2, API);\n\n#define NDND_BOOL_OP_DECLS(ND1, ND2, API)               \\\n  NDBOOL_OP_DECL (mx_el_and, ND1, ND2, API);            \\\n  NDBOOL_OP_DECL (mx_el_or,  ND1, ND2, API);            \\\n  NDBOOL_OP_DECL (mx_el_and_not, ND1, ND2, API);        \\\n  NDBOOL_OP_DECL (mx_el_or_not,  ND1, ND2, API);        \\\n  NDBOOL_OP_DECL (mx_el_not_and, ND1, ND2, API);        \\\n  NDBOOL_OP_DECL (mx_el_not_or,  ND1, ND2, API);\n\n#define NDND_OP_DECLS(R, ND1, ND2, API)         \\\n  NDND_BIN_OP_DECLS (R, ND1, ND2, API)          \\\n  NDND_CMP_OP_DECLS (ND1, ND2, API)             \\\n  NDND_BOOL_OP_DECLS (ND1, ND2, API)\n\n// scalar by diagonal matrix operations.\n\n#define SDM_BIN_OP_DECLS(R, S, DM, API)         \\\n  BIN_OP_DECL (R, operator *, S, DM, API);      \\\n\n#define SDM_OP_DECLS(R, S, DM, API)             \\\n  SDM_BIN_OP_DECLS(R, S, DM, API)\n\n// diagonal matrix by scalar operations.\n\n#define DMS_BIN_OP_DECLS(R, DM, S, API)         \\\n  BIN_OP_DECL (R, operator *, DM, S, API);      \\\n  BIN_OP_DECL (R, operator /, DM, S, API);\n\n#define DMS_OP_DECLS(R, DM, S, API)             \\\n  DMS_BIN_OP_DECLS(R, DM, S, API)\n\n// matrix by diagonal matrix operations.\n\n#define MDM_BIN_OP_DECLS(R, M, DM, API)         \\\n  BIN_OP_DECL (R, operator +, M, DM, API);      \\\n  BIN_OP_DECL (R, operator -, M, DM, API);      \\\n  BIN_OP_DECL (R, operator *, M, DM, API);\n\n#define MDM_OP_DECLS(R, M, DM, API)             \\\n  MDM_BIN_OP_DECLS(R, M, DM, API)\n\n// diagonal matrix by matrix operations.\n\n#define DMM_BIN_OP_DECLS(R, DM, M, API)         \\\n  BIN_OP_DECL (R, operator +, DM, M, API);      \\\n  BIN_OP_DECL (R, operator -, DM, M, API);      \\\n  BIN_OP_DECL (R, operator *, DM, M, API);\n\n#define DMM_OP_DECLS(R, DM, M, API)             \\\n  DMM_BIN_OP_DECLS(R, DM, M, API)\n\n// diagonal matrix by diagonal matrix operations.\n\n#define DMDM_BIN_OP_DECLS(R, DM1, DM2, API)     \\\n  BIN_OP_DECL (R, operator +, DM1, DM2, API);   \\\n  BIN_OP_DECL (R, operator -, DM1, DM2, API);   \\\n  BIN_OP_DECL (R, product, DM1, DM2, API);\n\n#define DMDM_OP_DECLS(R, DM1, DM2, API)         \\\n  DMDM_BIN_OP_DECLS (R, DM1, DM2, API)\n\n// scalar by N-D array min/max ops with optional nanflag and method arguments\n\n#define MINMAX_DECLS(T, S, API)                                               \\\n  extern API T min (S d, const T& m);                                         \\\n  extern API T min (const T& m, S d);                                         \\\n  extern API T min (const T& a, const T& b);                                  \\\n  extern API T max (S d, const T& m);                                         \\\n  extern API T max (const T& m, S d);                                         \\\n  extern API T max (const T& a, const T& b);                                  \\\n  extern API T min (S d, const T& m, const bool nanflag);                     \\\n  extern API T min (const T& m, S d, const bool nanflag);                     \\\n  extern API T min (const T& a, const T& b, const bool nanflag);              \\\n  extern API T max (S d, const T& m, const bool nanflag);                     \\\n  extern API T max (const T& m, S d, const bool nanflag);                     \\\n  extern API T max (const T& a, const T& b, const bool nanflag);              \\\n  extern API T min (S d, const T& m, const bool nanflag, const bool realabs); \\\n  extern API T min (const T& m, S d, const bool nanflag, const bool realabs); \\\n  extern API T min (const T& a, const T& b, const bool nanflag,               \\\n                    const bool realabs);                                      \\\n  extern API T max (S d, const T& m, const bool nanflag, const bool realabs); \\\n  extern API T max (const T& m, S d, const bool nanflag, const bool realabs); \\\n  extern API T max (const T& a, const T& b, const bool nanflag,               \\\n                    const bool realabs);\n\n// permutation matrix by matrix ops and vice versa\n\n#define PMM_BIN_OP_DECLS(R, PM, M, API)         \\\n  BIN_OP_DECL (R, operator *, PM, M, API);\n\n#define MPM_BIN_OP_DECLS(R, M, PM, API)         \\\n  BIN_OP_DECL (R, operator *, M, PM, API);\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/mx-op-defs.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mx_op_defs_h)\n#define octave_mx_op_defs_h 1\n\n#include \"octave-config.h\"\n\n#include \"lo-array-errwarn.h\"\n#include \"mx-op-decl.h\"\n#include \"mx-inlines.cc\"\n\n#define SNANCHK(s)                              \\\n  if (octave::math::isnan (s))                  \\\n    octave::err_nan_to_logical_conversion ()\n\n#define MNANCHK(m, MT)                          \\\n  if (do_mx_check (m, mx_inline_any_nan<MT>))   \\\n    octave::err_nan_to_logical_conversion ()\n\n// vector by scalar operations.\n\n#define VS_BIN_OP(R, F, OP, V, S)                                       \\\n  R                                                                     \\\n  F (const V& v, const S& s)                                            \\\n  {                                                                     \\\n    return do_ms_binary_op<R::element_type, V::element_type, S> (v, s, OP); \\\n  }\n\n#define VS_BIN_OPS(R, V, S)                             \\\n  VS_BIN_OP (R, operator +, mx_inline_add, V, S)        \\\n  VS_BIN_OP (R, operator -, mx_inline_sub, V, S)        \\\n  VS_BIN_OP (R, operator *, mx_inline_mul, V, S)        \\\n  VS_BIN_OP (R, operator /, mx_inline_div, V, S)\n\n// scalar by vector by operations.\n\n#define SV_BIN_OP(R, F, OP, S, V)                                       \\\n  R                                                                     \\\n  F (const S& s, const V& v)                                            \\\n  {                                                                     \\\n    return do_sm_binary_op<R::element_type, S, V::element_type> (s, v, OP); \\\n  }\n\n#define SV_BIN_OPS(R, S, V)                             \\\n  SV_BIN_OP (R, operator +, mx_inline_add, S, V)        \\\n  SV_BIN_OP (R, operator -, mx_inline_sub, S, V)        \\\n  SV_BIN_OP (R, operator *, mx_inline_mul, S, V)        \\\n  SV_BIN_OP (R, operator /, mx_inline_div, S, V)\n\n// vector by vector operations.\n\n#define VV_BIN_OP(R, F, OP, V1, V2)                                     \\\n  R                                                                     \\\n  F (const V1& v1, const V2& v2)                                        \\\n  {                                                                     \\\n    return do_mm_binary_op<R::element_type, V1::element_type, V2::element_type> (v1, v2, OP, OP, OP, #F); \\\n  }\n\n#define VV_BIN_OPS(R, V1, V2)                           \\\n  VV_BIN_OP (R, operator +, mx_inline_add, V1, V2)      \\\n  VV_BIN_OP (R, operator -, mx_inline_sub, V1, V2)      \\\n  VV_BIN_OP (R, product,    mx_inline_mul, V1, V2)      \\\n  VV_BIN_OP (R, quotient,   mx_inline_div, V1, V2)\n\n// matrix by scalar operations.\n\n#define MS_BIN_OP(R, OP, M, S, F)                                       \\\n  R                                                                     \\\n  OP (const M& m, const S& s)                                           \\\n  {                                                                     \\\n    return do_ms_binary_op<R::element_type, M::element_type, S> (m, s, F); \\\n  }\n\n#define MS_BIN_OPS(R, M, S)                             \\\n  MS_BIN_OP (R, operator +, M, S, mx_inline_add)        \\\n  MS_BIN_OP (R, operator -, M, S, mx_inline_sub)        \\\n  MS_BIN_OP (R, operator *, M, S, mx_inline_mul)        \\\n  MS_BIN_OP (R, operator /, M, S, mx_inline_div)\n\n#define MS_CMP_OP(F, OP, M, S)                                          \\\n  boolMatrix                                                            \\\n  F (const M& m, const S& s)                                            \\\n  {                                                                     \\\n    return do_ms_binary_op<bool, M::element_type, S> (m, s, OP);        \\\n  }\n\n#define MS_CMP_OPS(M, S)                        \\\n  MS_CMP_OP (mx_el_lt, mx_inline_lt, M, S)      \\\n  MS_CMP_OP (mx_el_le, mx_inline_le, M, S)      \\\n  MS_CMP_OP (mx_el_ge, mx_inline_ge, M, S)      \\\n  MS_CMP_OP (mx_el_gt, mx_inline_gt, M, S)      \\\n  MS_CMP_OP (mx_el_eq, mx_inline_eq, M, S)      \\\n  MS_CMP_OP (mx_el_ne, mx_inline_ne, M, S)\n\n#define MS_BOOL_OP(F, OP, M, S)                                         \\\n  boolMatrix                                                            \\\n  F (const M& m, const S& s)                                            \\\n  {                                                                     \\\n    MNANCHK (m, M::element_type);                                       \\\n    SNANCHK (s);                                                        \\\n    return do_ms_binary_op<bool, M::element_type, S> (m, s, OP);        \\\n  }\n\n#define MS_BOOL_OPS(M, S)                       \\\n  MS_BOOL_OP (mx_el_and, mx_inline_and, M, S)   \\\n  MS_BOOL_OP (mx_el_or,  mx_inline_or,  M, S)\n\n// scalar by matrix operations.\n\n#define SM_BIN_OP(R, OP, S, M, F)                                       \\\n  R                                                                     \\\n  OP (const S& s, const M& m)                                           \\\n  {                                                                     \\\n    return do_sm_binary_op<R::element_type, S, M::element_type> (s, m, F); \\\n  }\n\n#define SM_BIN_OPS(R, S, M)                             \\\n  SM_BIN_OP (R, operator +, S, M, mx_inline_add)        \\\n  SM_BIN_OP (R, operator -, S, M, mx_inline_sub)        \\\n  SM_BIN_OP (R, operator *, S, M, mx_inline_mul)        \\\n  SM_BIN_OP (R, operator /, S, M, mx_inline_div)\n\n#define SM_CMP_OP(F, OP, S, M)                                          \\\n  boolMatrix                                                            \\\n  F (const S& s, const M& m)                                            \\\n  {                                                                     \\\n    return do_sm_binary_op<bool, S, M::element_type> (s, m, OP);        \\\n  }\n\n#define SM_CMP_OPS(S, M)                        \\\n  SM_CMP_OP (mx_el_lt, mx_inline_lt, S, M)      \\\n  SM_CMP_OP (mx_el_le, mx_inline_le, S, M)      \\\n  SM_CMP_OP (mx_el_ge, mx_inline_ge, S, M)      \\\n  SM_CMP_OP (mx_el_gt, mx_inline_gt, S, M)      \\\n  SM_CMP_OP (mx_el_eq, mx_inline_eq, S, M)      \\\n  SM_CMP_OP (mx_el_ne, mx_inline_ne, S, M)\n\n#define SM_BOOL_OP(F, OP, S, M)                                         \\\n  boolMatrix                                                            \\\n  F (const S& s, const M& m)                                            \\\n  {                                                                     \\\n    SNANCHK (s);                                                        \\\n    MNANCHK (m, M::element_type);                                       \\\n    return do_sm_binary_op<bool, S, M::element_type> (s, m, OP);        \\\n  }\n\n#define SM_BOOL_OPS(S, M)                       \\\n  SM_BOOL_OP (mx_el_and, mx_inline_and, S, M)   \\\n  SM_BOOL_OP (mx_el_or,  mx_inline_or,  S, M)\n\n// matrix by matrix operations.\n\n#define MM_BIN_OP(R, OP, M1, M2, F)                                     \\\n  R                                                                     \\\n  OP (const M1& m1, const M2& m2)                                       \\\n  {                                                                     \\\n    return do_mm_binary_op<R::element_type, M1::element_type, M2::element_type> (m1, m2, F, F, F, #OP); \\\n  }\n\n#define MM_BIN_OPS(R, M1, M2)                           \\\n  MM_BIN_OP (R, operator +, M1, M2, mx_inline_add)      \\\n  MM_BIN_OP (R, operator -, M1, M2, mx_inline_sub)      \\\n  MM_BIN_OP (R, product,    M1, M2, mx_inline_mul)      \\\n  MM_BIN_OP (R, quotient,   M1, M2, mx_inline_div)\n\n#define MM_CMP_OP(F, OP, M1, M2)                                        \\\n  boolMatrix                                                            \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \\\n  }\n\n#define MM_CMP_OPS(M1, M2)                      \\\n  MM_CMP_OP (mx_el_lt, mx_inline_lt, M1, M2)    \\\n  MM_CMP_OP (mx_el_le, mx_inline_le, M1, M2)    \\\n  MM_CMP_OP (mx_el_ge, mx_inline_ge, M1, M2)    \\\n  MM_CMP_OP (mx_el_gt, mx_inline_gt, M1, M2)    \\\n  MM_CMP_OP (mx_el_eq, mx_inline_eq, M1, M2)    \\\n  MM_CMP_OP (mx_el_ne, mx_inline_ne, M1, M2)\n\n#define MM_BOOL_OP(F, OP, M1, M2)                                       \\\n  boolMatrix                                                            \\\n  F (const M1& m1, const M2& m2)                                        \\\n  {                                                                     \\\n    MNANCHK (m1, M1::element_type);                                     \\\n    MNANCHK (m2, M2::element_type);                                     \\\n    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \\\n  }\n\n#define MM_BOOL_OPS(M1, M2)                     \\\n  MM_BOOL_OP (mx_el_and, mx_inline_and, M1, M2) \\\n  MM_BOOL_OP (mx_el_or,  mx_inline_or,  M1, M2)\n\n// N-D matrix by scalar operations.\n\n#define NDS_BIN_OP(R, OP, ND, S, F)                                     \\\n  R                                                                     \\\n  OP (const ND& m, const S& s)                                          \\\n  {                                                                     \\\n    return do_ms_binary_op<R::element_type, ND::element_type, S> (m, s, F); \\\n  }\n\n#define NDS_BIN_OPS(R, ND, S)                           \\\n  NDS_BIN_OP (R, operator +, ND, S, mx_inline_add)      \\\n  NDS_BIN_OP (R, operator -, ND, S, mx_inline_sub)      \\\n  NDS_BIN_OP (R, operator *, ND, S, mx_inline_mul)      \\\n  NDS_BIN_OP (R, operator /, ND, S, mx_inline_div)\n\n#define NDS_CMP_OP(F, OP, ND, S)                                        \\\n  boolNDArray                                                           \\\n  F (const ND& m, const S& s)                                           \\\n  {                                                                     \\\n    return do_ms_binary_op<bool, ND::element_type, S> (m, s, OP);       \\\n  }\n\n#define NDS_CMP_OPS(ND, S)                      \\\n  NDS_CMP_OP (mx_el_lt, mx_inline_lt, ND, S)    \\\n  NDS_CMP_OP (mx_el_le, mx_inline_le, ND, S)    \\\n  NDS_CMP_OP (mx_el_ge, mx_inline_ge, ND, S)    \\\n  NDS_CMP_OP (mx_el_gt, mx_inline_gt, ND, S)    \\\n  NDS_CMP_OP (mx_el_eq, mx_inline_eq, ND, S)    \\\n  NDS_CMP_OP (mx_el_ne, mx_inline_ne, ND, S)\n\n#define NDS_BOOL_OP(F, OP, ND, S)                                       \\\n  boolNDArray                                                           \\\n  F (const ND& m, const S& s)                                           \\\n  {                                                                     \\\n    MNANCHK (m, ND::element_type);                                      \\\n    SNANCHK (s);                                                        \\\n    return do_ms_binary_op<bool, ND::element_type, S> (m, s, OP);       \\\n  }\n\n#define NDS_BOOL_OPS(ND, S)                             \\\n  NDS_BOOL_OP (mx_el_and,     mx_inline_and,     ND, S) \\\n  NDS_BOOL_OP (mx_el_or,      mx_inline_or,      ND, S) \\\n  NDS_BOOL_OP (mx_el_not_and, mx_inline_not_and, ND, S) \\\n  NDS_BOOL_OP (mx_el_not_or,  mx_inline_not_or,  ND, S) \\\n  NDS_BOOL_OP (mx_el_and_not, mx_inline_and_not, ND, S) \\\n  NDS_BOOL_OP (mx_el_or_not,  mx_inline_or_not,  ND, S)\n\n// scalar by N-D matrix operations.\n\n#define SND_BIN_OP(R, OP, S, ND, F)                                     \\\n  R                                                                     \\\n  OP (const S& s, const ND& m)                                          \\\n  {                                                                     \\\n    return do_sm_binary_op<R::element_type, S, ND::element_type> (s, m, F); \\\n  }\n\n#define SND_BIN_OPS(R, S, ND)                           \\\n  SND_BIN_OP (R, operator +, S, ND, mx_inline_add)      \\\n  SND_BIN_OP (R, operator -, S, ND, mx_inline_sub)      \\\n  SND_BIN_OP (R, operator *, S, ND, mx_inline_mul)      \\\n  SND_BIN_OP (R, operator /, S, ND, mx_inline_div)\n\n#define SND_CMP_OP(F, OP, S, ND)                                        \\\n  boolNDArray                                                           \\\n  F (const S& s, const ND& m)                                           \\\n  {                                                                     \\\n    return do_sm_binary_op<bool, S, ND::element_type> (s, m, OP);       \\\n  }\n\n#define SND_CMP_OPS(S, ND)                      \\\n  SND_CMP_OP (mx_el_lt, mx_inline_lt, S, ND)    \\\n  SND_CMP_OP (mx_el_le, mx_inline_le, S, ND)    \\\n  SND_CMP_OP (mx_el_ge, mx_inline_ge, S, ND)    \\\n  SND_CMP_OP (mx_el_gt, mx_inline_gt, S, ND)    \\\n  SND_CMP_OP (mx_el_eq, mx_inline_eq, S, ND)    \\\n  SND_CMP_OP (mx_el_ne, mx_inline_ne, S, ND)\n\n#define SND_BOOL_OP(F, OP, S, ND)                                       \\\n  boolNDArray                                                           \\\n  F (const S& s, const ND& m)                                           \\\n  {                                                                     \\\n    SNANCHK (s);                                                        \\\n    MNANCHK (m, ND::element_type);                                      \\\n    return do_sm_binary_op<bool, S, ND::element_type> (s, m, OP);       \\\n  }\n\n#define SND_BOOL_OPS(S, ND)                             \\\n  SND_BOOL_OP (mx_el_and,     mx_inline_and,     S, ND) \\\n  SND_BOOL_OP (mx_el_or,      mx_inline_or,      S, ND) \\\n  SND_BOOL_OP (mx_el_not_and, mx_inline_not_and, S, ND) \\\n  SND_BOOL_OP (mx_el_not_or,  mx_inline_not_or,  S, ND) \\\n  SND_BOOL_OP (mx_el_and_not, mx_inline_and_not, S, ND) \\\n  SND_BOOL_OP (mx_el_or_not,  mx_inline_or_not,  S, ND)\n\n// N-D matrix by N-D matrix operations.\n\n#define NDND_BIN_OP(R, OP, ND1, ND2, F)                                 \\\n  R                                                                     \\\n  OP (const ND1& m1, const ND2& m2)                                     \\\n  {                                                                     \\\n    return do_mm_binary_op<R::element_type, ND1::element_type, ND2::element_type> (m1, m2, F, F, F, #OP); \\\n  }\n\n#define NDND_BIN_OPS(R, ND1, ND2)                       \\\n  NDND_BIN_OP (R, operator +, ND1, ND2, mx_inline_add)  \\\n  NDND_BIN_OP (R, operator -, ND1, ND2, mx_inline_sub)  \\\n  NDND_BIN_OP (R, product,    ND1, ND2, mx_inline_mul)  \\\n  NDND_BIN_OP (R, quotient,   ND1, ND2, mx_inline_div)\n\n#define NDND_CMP_OP(F, OP, ND1, ND2)                                    \\\n  boolNDArray                                                           \\\n  F (const ND1& m1, const ND2& m2)                                      \\\n  {                                                                     \\\n    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \\\n  }\n\n#define NDND_CMP_OPS(ND1, ND2)                          \\\n  NDND_CMP_OP (mx_el_lt, mx_inline_lt, ND1, ND2)        \\\n  NDND_CMP_OP (mx_el_le, mx_inline_le, ND1, ND2)        \\\n  NDND_CMP_OP (mx_el_ge, mx_inline_ge, ND1, ND2)        \\\n  NDND_CMP_OP (mx_el_gt, mx_inline_gt, ND1, ND2)        \\\n  NDND_CMP_OP (mx_el_eq, mx_inline_eq, ND1, ND2)        \\\n  NDND_CMP_OP (mx_el_ne, mx_inline_ne, ND1, ND2)\n\n#define NDND_BOOL_OP(F, OP, ND1, ND2)                                   \\\n  boolNDArray                                                           \\\n  F (const ND1& m1, const ND2& m2)                                      \\\n  {                                                                     \\\n    MNANCHK (m1, ND1::element_type);                                    \\\n    MNANCHK (m2, ND2::element_type);                                    \\\n    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \\\n  }\n\n#define NDND_BOOL_OPS(ND1, ND2)                                 \\\n  NDND_BOOL_OP (mx_el_and,     mx_inline_and,     ND1, ND2)     \\\n  NDND_BOOL_OP (mx_el_or,      mx_inline_or,      ND1, ND2)     \\\n  NDND_BOOL_OP (mx_el_not_and, mx_inline_not_and, ND1, ND2)     \\\n  NDND_BOOL_OP (mx_el_not_or,  mx_inline_not_or,  ND1, ND2)     \\\n  NDND_BOOL_OP (mx_el_and_not, mx_inline_and_not, ND1, ND2)     \\\n  NDND_BOOL_OP (mx_el_or_not,  mx_inline_or_not,  ND1, ND2)\n\n// scalar by diagonal matrix operations.\n\n#define SDM_BIN_OP(R, OP, S, DM)                        \\\n  R                                                     \\\n  operator OP (const S& s, const DM& dm)                \\\n  {                                                     \\\n    R r (dm.rows (), dm.cols ());                       \\\n                                                        \\\n    for (octave_idx_type i = 0; i < dm.length (); i++)  \\\n      r.dgxelem (i) = s OP dm.dgelem (i);               \\\n                                                        \\\n    return r;                                           \\\n  }\n\n#define SDM_BIN_OPS(R, S, DM)                   \\\n  SDM_BIN_OP (R, *, S, DM)\n\n// diagonal matrix by scalar operations.\n\n#define DMS_BIN_OP(R, OP, DM, S)                        \\\n  R                                                     \\\n  operator OP (const DM& dm, const S& s)                \\\n  {                                                     \\\n    R r (dm.rows (), dm.cols ());                       \\\n                                                        \\\n    for (octave_idx_type i = 0; i < dm.length (); i++)  \\\n      r.dgxelem (i) = dm.dgelem (i) OP s;               \\\n                                                        \\\n    return r;                                           \\\n  }\n\n#define DMS_BIN_OPS(R, DM, S)                   \\\n  DMS_BIN_OP (R, *, DM, S)                      \\\n  DMS_BIN_OP (R, /, DM, S)\n\n// matrix by diagonal matrix operations.\n\n#define MDM_BIN_OP(R, OP, M, DM, OPEQ)                               \\\n  R                                                                  \\\n  OP (const M& m, const DM& dm)                                      \\\n  {                                                                  \\\n    R r;                                                             \\\n                                                                     \\\n    octave_idx_type m_nr = m.rows ();                                \\\n    octave_idx_type m_nc = m.cols ();                                \\\n                                                                     \\\n    octave_idx_type dm_nr = dm.rows ();                              \\\n    octave_idx_type dm_nc = dm.cols ();                              \\\n                                                                     \\\n    r.resize (m_nr, m_nc);                                           \\\n                                                                     \\\n    if (m_nr > 0 && m_nc > 0)                                        \\\n      {                                                              \\\n        if (m_nr == dm_nr && m_nc == dm_nc)                          \\\n          {                                                          \\\n            r = R (m);                                               \\\n                                                                     \\\n            octave_idx_type len = dm.length ();                      \\\n                                                                     \\\n            for (octave_idx_type i = 0; i < len; i++)                \\\n              r.elem (i, i) OPEQ dm.elem (i, i);                     \\\n          }                                                          \\\n        else if (m_nr == dm_nr && m_nc == 1)                         \\\n          {                                                          \\\n            r = R (dm_nr, dm_nc);                                    \\\n                                                                     \\\n            octave_idx_type len = dm.length ();                      \\\n                                                                     \\\n            for (octave_idx_type i = 0; i < len; i++)                \\\n              for (octave_idx_type j = 0; j < len; j++)              \\\n                {                                                    \\\n                  r.elem (i, j) = m.elem (i, 0);                     \\\n                  if (i == j)                                        \\\n                    r.elem (i, j) OPEQ dm.elem (i, i);               \\\n                }                                                    \\\n          }                                                          \\\n        else if (m_nc == dm_nc && m_nr == 1)                         \\\n          {                                                          \\\n            r = R (dm_nr, dm_nc);                                    \\\n                                                                     \\\n            octave_idx_type len = dm.length ();                      \\\n                                                                     \\\n            for (octave_idx_type i = 0; i < len; i++)                \\\n              for (octave_idx_type j = 0; j < len; j++)              \\\n                {                                                    \\\n                  r.elem (i, j) = m.elem (0, j);                     \\\n                  if (i == j)                                        \\\n                    r.elem (i, j) OPEQ dm.elem (i, i);               \\\n                }                                                    \\\n          }                                                          \\\n        else                                                         \\\n          octave::err_nonconformant (#OP, m_nr, m_nc, dm_nr, dm_nc); \\\n      }                                                              \\\n    else if (m_nr != dm_nr || m_nc != dm_nc)                         \\\n      octave::err_nonconformant (#OP, m_nr, m_nc, dm_nr, dm_nc);     \\\n                                                                     \\\n    return r;                                                        \\\n  }\n\n#define MDM_MULTIPLY_OP(R, M, DM)                                          \\\n  R                                                                        \\\n  operator * (const M& m, const DM& dm)                                    \\\n  {                                                                        \\\n    R r;                                                                   \\\n                                                                           \\\n    R::element_type r_zero = R::element_type ();                           \\\n                                                                           \\\n    octave_idx_type m_nr = m.rows ();                                      \\\n    octave_idx_type m_nc = m.cols ();                                      \\\n                                                                           \\\n    octave_idx_type dm_nr = dm.rows ();                                    \\\n    octave_idx_type dm_nc = dm.cols ();                                    \\\n                                                                           \\\n    if (m_nc != dm_nr)                                                     \\\n      octave::err_nonconformant (\"operator *\", m_nr, m_nc, dm_nr, dm_nc);  \\\n                                                                           \\\n    r = R (m_nr, dm_nc);                                                   \\\n    R::element_type *rd = r.rwdata ();                                     \\\n    const M::element_type *md = m.data ();                                 \\\n    const DM::element_type *dd = dm.data ();                               \\\n                                                                           \\\n    octave_idx_type len = dm.length ();                                    \\\n    for (octave_idx_type i = 0; i < len; i++)                              \\\n      {                                                                    \\\n        mx_inline_mul (m_nr, rd, md, dd[i]);                               \\\n        rd += m_nr; md += m_nr;                                            \\\n      }                                                                    \\\n    mx_inline_fill (m_nr * (dm_nc - len), rd, r_zero);                     \\\n                                                                           \\\n    return r;                                                              \\\n  }\n\n#define MDM_BIN_OPS(R, M, DM)                   \\\n  MDM_BIN_OP (R, operator +, M, DM, +=)         \\\n  MDM_BIN_OP (R, operator -, M, DM, -=)         \\\n  MDM_MULTIPLY_OP (R, M, DM)\n\n// diagonal matrix by matrix operations.\n\n#define DMM_BIN_OP(R, OP, DM, M, PREOP)                              \\\n  R                                                                  \\\n  OP (const DM& dm, const M& m)                                      \\\n  {                                                                  \\\n    R r;                                                             \\\n                                                                     \\\n    octave_idx_type dm_nr = dm.rows ();                              \\\n    octave_idx_type dm_nc = dm.cols ();                              \\\n                                                                     \\\n    octave_idx_type m_nr = m.rows ();                                \\\n    octave_idx_type m_nc = m.cols ();                                \\\n                                                                     \\\n    r.resize (m_nr, m_nc);                                           \\\n                                                                     \\\n    if (m_nr > 0 && m_nc > 0)                                        \\\n      {                                                              \\\n        if (m_nr == dm_nr && m_nc == dm_nc)                          \\\n          {                                                          \\\n            r = R (PREOP m);                                         \\\n                                                                     \\\n            octave_idx_type len = dm.length ();                      \\\n                                                                     \\\n            for (octave_idx_type i = 0; i < len; i++)                \\\n              r.elem (i, i) += dm.elem (i, i);                       \\\n          }                                                          \\\n        else if (m_nr == dm_nr && m_nc == 1)                         \\\n          {                                                          \\\n            r = R (dm_nr, dm_nc);                                    \\\n                                                                     \\\n            octave_idx_type len = dm.length ();                      \\\n                                                                     \\\n            for (octave_idx_type i = 0; i < len; i++)                \\\n              for (octave_idx_type j = 0; j < len; j++)              \\\n                {                                                    \\\n                  r.elem (i, j) = PREOP m.elem (i, 0);               \\\n                  if (i == j)                                        \\\n                    r.elem (i, j) += dm.elem (i, i);                 \\\n                }                                                    \\\n          }                                                          \\\n        else if (m_nc == dm_nc && m_nr == 1)                         \\\n          {                                                          \\\n            r = R (dm_nr, dm_nc);                                    \\\n                                                                     \\\n            octave_idx_type len = dm.length ();                      \\\n                                                                     \\\n            for (octave_idx_type i = 0; i < len; i++)                \\\n              for (octave_idx_type j = 0; j < len; j++)              \\\n                {                                                    \\\n                  r.elem (i, j) = PREOP m.elem (0, j);               \\\n                  if (i == j)                                        \\\n                    r.elem (i, j) += dm.elem (i, i);                 \\\n                }                                                    \\\n          }                                                          \\\n        else                                                         \\\n          octave::err_nonconformant (#OP, m_nr, m_nc, dm_nr, dm_nc); \\\n      }                                                              \\\n    else if (m_nr != dm_nr || m_nc != dm_nc)                         \\\n      octave::err_nonconformant (#OP, m_nr, m_nc, dm_nr, dm_nc);     \\\n                                                                     \\\n    return r;                                                        \\\n  }\n\n#define DMM_MULTIPLY_OP(R, DM, M)                                          \\\n  R                                                                        \\\n  operator * (const DM& dm, const M& m)                                    \\\n  {                                                                        \\\n    R r;                                                                   \\\n                                                                           \\\n    R::element_type r_zero = R::element_type ();                           \\\n                                                                           \\\n    octave_idx_type dm_nr = dm.rows ();                                    \\\n    octave_idx_type dm_nc = dm.cols ();                                    \\\n                                                                           \\\n    octave_idx_type m_nr = m.rows ();                                      \\\n    octave_idx_type m_nc = m.cols ();                                      \\\n                                                                           \\\n    if (dm_nc != m_nr)                                                     \\\n      octave::err_nonconformant (\"operator *\", dm_nr, dm_nc, m_nr, m_nc);  \\\n                                                                           \\\n    r = R (dm_nr, m_nc);                                                   \\\n    R::element_type *rd = r.rwdata ();                                     \\\n    const M::element_type *md = m.data ();                                 \\\n    const DM::element_type *dd = dm.data ();                               \\\n                                                                           \\\n    octave_idx_type len = dm.length ();                                    \\\n    for (octave_idx_type i = 0; i < m_nc; i++)                             \\\n      {                                                                    \\\n        mx_inline_mul (len, rd, md, dd);                                   \\\n        rd += len; md += m_nr;                                             \\\n        mx_inline_fill (dm_nr - len, rd, r_zero);                          \\\n        rd += dm_nr - len;                                                 \\\n      }                                                                    \\\n                                                                           \\\n    return r;                                                              \\\n  }\n\n#define DMM_BIN_OPS(R, DM, M)               \\\n  DMM_BIN_OP (R, operator +, DM, M,  )      \\\n  DMM_BIN_OP (R, operator -, DM, M, -)      \\\n  DMM_MULTIPLY_OP (R, DM, M)\n\n// diagonal matrix by diagonal matrix operations.\n\n#define DMDM_BIN_OP(R, OP, DM1, DM2, F)                                 \\\n  R                                                                     \\\n  OP (const DM1& dm1, const DM2& dm2)                                   \\\n  {                                                                     \\\n    R r;                                                                \\\n                                                                        \\\n    octave_idx_type dm1_nr = dm1.rows ();                               \\\n    octave_idx_type dm1_nc = dm1.cols ();                               \\\n                                                                        \\\n    octave_idx_type dm2_nr = dm2.rows ();                               \\\n    octave_idx_type dm2_nc = dm2.cols ();                               \\\n                                                                        \\\n    if (dm1_nr != dm2_nr || dm1_nc != dm2_nc)                           \\\n      octave::err_nonconformant (#OP, dm1_nr, dm1_nc, dm2_nr, dm2_nc);  \\\n                                                                        \\\n    r.resize (dm1_nr, dm1_nc);                                          \\\n                                                                        \\\n    if (dm1_nr > 0 && dm1_nc > 0)                                       \\\n      F (dm1.length (), r.rwdata (), dm1.data (), dm2.data ());         \\\n                                                                        \\\n    return r;                                                           \\\n  }\n\n#define DMDM_BIN_OPS(R, DM1, DM2)                       \\\n  DMDM_BIN_OP (R, operator +, DM1, DM2, mx_inline_add)  \\\n  DMDM_BIN_OP (R, operator -, DM1, DM2, mx_inline_sub)  \\\n  DMDM_BIN_OP (R, product,    DM1, DM2, mx_inline_mul)\n\n// scalar by N-D array min/max ops\n\n#define SND_MINMAX_FCN(FCN, T, S)                                       \\\n  T                                                                     \\\n  FCN (S d, const T& m)                                                 \\\n  {                                                                     \\\n    return do_sm_binary_op<T::element_type, S, T::element_type> (d, m, mx_inline_x##FCN); \\\n  }\n\n#define NDS_MINMAX_FCN(FCN, T, S)                                       \\\n  T                                                                     \\\n  FCN (const T& m, S d)                                                 \\\n  {                                                                     \\\n    return do_ms_binary_op<T::element_type, T::element_type, S> (m, d, mx_inline_x##FCN); \\\n  }\n\n#define NDND_MINMAX_FCN(FCN, T, S)                                      \\\n  T                                                                     \\\n  FCN (const T& a, const T& b)                                          \\\n  {                                                                     \\\n    return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, mx_inline_x##FCN, mx_inline_x##FCN, mx_inline_x##FCN, #FCN); \\\n  }\n\n// scalar by N-D array min/max ops with nanflag\n\n#define SND_MINMAX1_FCN(FCN, T, S)                                      \\\n  T                                                                     \\\n  FCN (S d, const T& m, const bool nanflag)                             \\\n  {                                                                     \\\n    return do_sm_binary_op<T::element_type, S, T::element_type> (d, m, nanflag, mx_inline_x##FCN); \\\n  }\n\n#define NDS_MINMAX1_FCN(FCN, T, S)                                      \\\n  T                                                                     \\\n  FCN (const T& m, S d, const bool nanflag)                             \\\n  {                                                                     \\\n    return do_ms_binary_op<T::element_type, T::element_type, S> (m, d, nanflag, mx_inline_x##FCN); \\\n  }\n\n#define NDND_MINMAX1_FCN(FCN, T, S)                                     \\\n  T                                                                     \\\n  FCN (const T& a, const T& b, const bool nanflag)                      \\\n  {                                                                     \\\n    return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, nanflag, mx_inline_x##FCN, mx_inline_x##FCN, mx_inline_x##FCN, #FCN); \\\n  }\n\n// scalar by N-D array min/max ops with nanflag and realabs\n\n#define SND_MINMAX2_FCN(FCN, T, S)                                      \\\n  T                                                                     \\\n  FCN (S d, const T& m, const bool nanflag, const bool realabs)         \\\n  {                                                                     \\\n    return do_sm_binary_op<T::element_type, S, T::element_type> (d, m, nanflag, realabs, mx_inline_x##FCN); \\\n  }\n\n#define NDS_MINMAX2_FCN(FCN, T, S)                                      \\\n  T                                                                     \\\n  FCN (const T& m, S d, const bool nanflag, const bool realabs)         \\\n  {                                                                     \\\n    return do_ms_binary_op<T::element_type, T::element_type, S> (m, d, nanflag, realabs, mx_inline_x##FCN); \\\n  }\n\n#define NDND_MINMAX2_FCN(FCN, T, S)                                     \\\n  T                                                                     \\\n  FCN (const T& a, const T& b, const bool nanflag, const bool realabs)  \\\n  {                                                                     \\\n    return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, nanflag, realabs, mx_inline_x##FCN, mx_inline_x##FCN, mx_inline_x##FCN, #FCN); \\\n  }\n\n#define MINMAX_FCNS(T, S)                    \\\n  SND_MINMAX_FCN (min, T, S)                 \\\n  NDS_MINMAX_FCN (min, T, S)                 \\\n  NDND_MINMAX_FCN (min, T, S)                \\\n  SND_MINMAX_FCN (max, T, S)                 \\\n  NDS_MINMAX_FCN (max, T, S)                 \\\n  NDND_MINMAX_FCN (max, T, S)                \\\n  SND_MINMAX1_FCN (min, T, S)                \\\n  NDS_MINMAX1_FCN (min, T, S)                \\\n  NDND_MINMAX1_FCN (min, T, S)               \\\n  SND_MINMAX1_FCN (max, T, S)                \\\n  NDS_MINMAX1_FCN (max, T, S)                \\\n  NDND_MINMAX1_FCN (max, T, S)               \\\n  SND_MINMAX2_FCN (min, T, S)                \\\n  NDS_MINMAX2_FCN (min, T, S)                \\\n  NDND_MINMAX2_FCN (min, T, S)               \\\n  SND_MINMAX2_FCN (max, T, S)                \\\n  NDS_MINMAX2_FCN (max, T, S)                \\\n  NDND_MINMAX2_FCN (max, T, S)\n\n// permutation matrix by matrix ops and vice versa\n\n#define PMM_MULTIPLY_OP(PM, M)                                          \\\n  M operator * (const PM& p, const M& x)                                \\\n  {                                                                     \\\n    octave_idx_type nr = x.rows ();                                     \\\n    octave_idx_type nc = x.columns ();                                  \\\n    M result;                                                           \\\n    if (p.columns () != nr)                                             \\\n      octave::err_nonconformant (\"operator *\", p.rows (), p.columns (), nr, nc); \\\n    else                                                                \\\n      {                                                                 \\\n        result = M (nr, nc);                                            \\\n        result.assign (p.col_perm_vec (), octave::idx_vector::colon, x);        \\\n      }                                                                 \\\n                                                                        \\\n    return result;                                                      \\\n  }\n\n#define MPM_MULTIPLY_OP(M, PM)                                          \\\n  M operator * (const M& x, const PM& p)                                \\\n  {                                                                     \\\n    octave_idx_type nr = x.rows ();                                     \\\n    octave_idx_type nc = x.columns ();                                  \\\n    M result;                                                           \\\n    if (p.rows () != nc)                                                \\\n      octave::err_nonconformant (\"operator *\", nr, nc, p.rows (), p.columns ()); \\\n                                                                        \\\n    result = x.index (octave::idx_vector::colon, p.col_perm_vec ());            \\\n                                                                        \\\n    return result;                                                      \\\n  }\n\n#define PMM_BIN_OPS(R, PM, M)                   \\\n  PMM_MULTIPLY_OP(PM, M);\n\n#define MPM_BIN_OPS(R, M, PM)                   \\\n  MPM_MULTIPLY_OP(M, PM);\n\n#define NDND_MAPPER_BODY(R, NAME)               \\\n  R retval (dims ());                           \\\n  octave_idx_type n = numel ();                 \\\n  for (octave_idx_type i = 0; i < n; i++)       \\\n    retval.xelem (i) = NAME (elem (i));         \\\n  return retval;\n\n#endif\n"
  },
  {
    "path": "liboctave/operators/mx-ops",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# NOTE: if this file changes, you must run bootstrap and configure to\n# rebuild the source file lists for Make.\n\n# types\n#\n# key typename object-type header fwd-decl-ok core-type\n#\n# object-type is one of\n#\n#   S:  scalar\n#   M:  matrix\n#   DM: diagonal matrix\n#   ND: N-D array\n#   FS:  scalar\n#   FM:  matrix\n#   FDM: diagonal matrix\n#   FND: N-D array\n#\n# core-type is only used for the octave_int types, and is the template\n# parameter: octave_int8 is octave_int<int8_t>\n#\nx NONE NONE NONE NO\nb bool S NONE NO\nbm boolMatrix ND boolMatrix.h YES\nbnda boolNDArray ND boolNDArray.h YES\ncdm ComplexDiagMatrix DM CDiagMatrix.h YES\ncm ComplexMatrix M CMatrix.h YES\ncnda ComplexNDArray ND CNDArray.h YES\ncs Complex S oct-cmplx.h NO\ndm DiagMatrix DM dDiagMatrix.h YES\nm Matrix M dMatrix.h YES\nnda NDArray ND dNDArray.h YES\ns double S NONE NO\nfcdm FloatComplexDiagMatrix DM fCDiagMatrix.h YES\nfcm FloatComplexMatrix M fCMatrix.h YES\nfcnda FloatComplexNDArray ND fCNDArray.h YES\nfcs FloatComplex S oct-cmplx.h NO\nfdm FloatDiagMatrix DM fDiagMatrix.h YES\nfm FloatMatrix M fMatrix.h YES\nfnda FloatNDArray ND fNDArray.h YES\nfs float S NONE NO\ni8 octave_int8 S oct-inttypes.h YES int8_t\nui8 octave_uint8 S oct-inttypes.h YES uint8_t\ni16 octave_int16 S oct-inttypes.h YES int16_t\nui16 octave_uint16 S oct-inttypes.h YES uint16_t\ni32 octave_int32 S oct-inttypes.h YES int32_t\nui32 octave_uint32 S oct-inttypes.h YES uint32_t\ni64 octave_int64 S oct-inttypes.h YES int64_t\nui64 octave_uint64 S oct-inttypes.h YES uint64_t\ni8nda int8NDArray ND int8NDArray.h YES int8_t\nui8nda uint8NDArray ND uint8NDArray.h YES uint8_t\ni16nda int16NDArray ND int16NDArray.h YES int16_t\nui16nda uint16NDArray ND uint16NDArray.h YES uint16_t\ni32nda int32NDArray ND int32NDArray.h YES int32_t\nui32nda uint32NDArray ND uint32NDArray.h YES uint32_t\ni64nda int64NDArray ND int64NDArray.h YES int64_t\nui64nda uint64NDArray ND uint64NDArray.h YES uint64_t\npm PermMatrix PM PermMatrix.h YES\n#\n# full-matrix operators\n#\n# result_t lhs_t rhs_t op-type headers ...\n#\n# op-type is one of\n#\n#   B: binary ops, + - * /\n#   C: comparison ops, < <= == != >= >\n#   L: logical ops, & |\n#\ncdm cdm dm B\ncdm dm cdm B\ncdm cs dm B\ncm cs m BCL boolMatrix.h\ncnda cs nda BCL boolMatrix.h boolNDArray.h\ncm cdm cm B\ncm cdm m B\ncdm cdm s B\ncm cm cdm B\ncm cm dm B\ncm cm m BCL boolMatrix.h\ncnda cnda nda BCL boolMatrix.h boolNDArray.h\ncm cm s BCL boolMatrix.h\ncnda cnda s BCL boolMatrix.h boolNDArray.h\ncdm dm cs B\ncm dm cm B\ncm m cs BCL boolMatrix.h\ncnda nda cs BCL boolMatrix.h boolNDArray.h\ncm m cdm B\ncm m cm BCL boolMatrix.h\ncnda nda cnda BCL boolMatrix.h boolNDArray.h\ncdm s cdm B\ncm s cm BCL boolMatrix.h\ncnda s cnda BCL boolMatrix.h boolNDArray.h\nm dm m B\nm m dm B\n#\nfcdm fcdm fdm B\nfcdm fdm fcdm B\nfcdm fcs fdm B\nfcm fcs fm BCL boolMatrix.h\nfcnda fcs fnda BCL boolMatrix.h boolNDArray.h\nfcm fcdm fcm B\nfcm fcdm fm B\nfcdm fcdm fs B\nfcm fcm fcdm B\nfcm fcm fdm B\nfcm fcm fm BCL boolMatrix.h\nfcnda fcnda fnda BCL boolMatrix.h boolNDArray.h\nfcm fcm fs BCL boolMatrix.h\nfcnda fcnda fs BCL boolMatrix.h boolNDArray.h\nfcdm fdm fcs B\nfcm fdm fcm B\nfcm fm fcs BCL boolMatrix.h\nfcnda fnda fcs BCL boolMatrix.h boolNDArray.h\nfcm fm fcdm B\nfcm fm fcm BCL boolMatrix.h\nfcnda fnda fcnda BCL boolMatrix.h boolNDArray.h\nfcdm fs fcdm B\nfcm fs fcm BCL boolMatrix.h\nfcnda fs fcnda BCL boolMatrix.h boolNDArray.h\nfm fdm fm B\nfm fm fdm B\n#\nm pm m B\nm m pm B\ncm pm cm B\ncm cm pm B\nfm pm fm B\nfm fm pm B\nfcm pm fcm B\nfcm fcm pm B\n#\ni8nda s i8nda BCL boolMatrix.h boolNDArray.h\ni8nda i8nda s BCL boolMatrix.h boolNDArray.h\nui8nda s ui8nda BCL boolMatrix.h boolNDArray.h\nui8nda ui8nda s BCL boolMatrix.h boolNDArray.h\ni16nda s i16nda BCL boolMatrix.h boolNDArray.h\ni16nda i16nda s BCL boolMatrix.h boolNDArray.h\nui16nda s ui16nda BCL boolMatrix.h boolNDArray.h\nui16nda ui16nda s BCL boolMatrix.h boolNDArray.h\ni32nda s i32nda BCL boolMatrix.h boolNDArray.h\ni32nda i32nda s BCL boolMatrix.h boolNDArray.h\nui32nda s ui32nda BCL boolMatrix.h boolNDArray.h\nui32nda ui32nda s BCL boolMatrix.h boolNDArray.h\ni64nda s i64nda BCL boolMatrix.h boolNDArray.h\ni64nda i64nda s BCL boolMatrix.h boolNDArray.h\nui64nda s ui64nda BCL boolMatrix.h boolNDArray.h\nui64nda ui64nda s BCL boolMatrix.h boolNDArray.h\ni8nda fs i8nda BCL boolMatrix.h boolNDArray.h\ni8nda i8nda fs BCL boolMatrix.h boolNDArray.h\nui8nda fs ui8nda BCL boolMatrix.h boolNDArray.h\nui8nda ui8nda fs BCL boolMatrix.h boolNDArray.h\ni16nda fs i16nda BCL boolMatrix.h boolNDArray.h\ni16nda i16nda fs BCL boolMatrix.h boolNDArray.h\nui16nda fs ui16nda BCL boolMatrix.h boolNDArray.h\nui16nda ui16nda fs BCL boolMatrix.h boolNDArray.h\ni32nda fs i32nda BCL boolMatrix.h boolNDArray.h\ni32nda i32nda fs BCL boolMatrix.h boolNDArray.h\nui32nda fs ui32nda BCL boolMatrix.h boolNDArray.h\nui32nda ui32nda fs BCL boolMatrix.h boolNDArray.h\ni64nda fs i64nda BCL boolMatrix.h boolNDArray.h\ni64nda i64nda fs BCL boolMatrix.h boolNDArray.h\nui64nda fs ui64nda BCL boolMatrix.h boolNDArray.h\nui64nda ui64nda fs BCL boolMatrix.h boolNDArray.h\n#\ni8nda nda i8 BCL boolMatrix.h boolNDArray.h\ni8nda i8 nda BCL boolMatrix.h boolNDArray.h\nui8nda nda ui8 BCL boolMatrix.h boolNDArray.h\nui8nda ui8 nda BCL boolMatrix.h boolNDArray.h\ni16nda nda i16 BCL boolMatrix.h boolNDArray.h\ni16nda i16 nda BCL boolMatrix.h boolNDArray.h\nui16nda nda ui16 BCL boolMatrix.h boolNDArray.h\nui16nda ui16 nda BCL boolMatrix.h boolNDArray.h\ni32nda nda i32 BCL boolMatrix.h boolNDArray.h\ni32nda i32 nda BCL boolMatrix.h boolNDArray.h\nui32nda nda ui32 BCL boolMatrix.h boolNDArray.h\nui32nda ui32 nda BCL boolMatrix.h boolNDArray.h\ni64nda nda i64 BCL boolMatrix.h boolNDArray.h\ni64nda i64 nda BCL boolMatrix.h boolNDArray.h\nui64nda nda ui64 BCL boolMatrix.h boolNDArray.h\nui64nda ui64 nda BCL boolMatrix.h boolNDArray.h\ni8nda fnda i8 BCL boolMatrix.h boolNDArray.h\ni8nda i8 fnda BCL boolMatrix.h boolNDArray.h\nui8nda fnda ui8 BCL boolMatrix.h boolNDArray.h\nui8nda ui8 fnda BCL boolMatrix.h boolNDArray.h\ni16nda fnda i16 BCL boolMatrix.h boolNDArray.h\ni16nda i16 fnda BCL boolMatrix.h boolNDArray.h\nui16nda fnda ui16 BCL boolMatrix.h boolNDArray.h\nui16nda ui16 fnda BCL boolMatrix.h boolNDArray.h\ni32nda fnda i32 BCL boolMatrix.h boolNDArray.h\ni32nda i32 fnda BCL boolMatrix.h boolNDArray.h\nui32nda fnda ui32 BCL boolMatrix.h boolNDArray.h\nui32nda ui32 fnda BCL boolMatrix.h boolNDArray.h\ni64nda fnda i64 BCL boolMatrix.h boolNDArray.h\ni64nda i64 fnda BCL boolMatrix.h boolNDArray.h\nui64nda fnda ui64 BCL boolMatrix.h boolNDArray.h\nui64nda ui64 fnda BCL boolMatrix.h boolNDArray.h\n#\ni8nda nda i8nda BCL boolMatrix.h boolNDArray.h\ni8nda i8nda nda BCL boolMatrix.h boolNDArray.h\nui8nda nda ui8nda BCL boolMatrix.h boolNDArray.h\nui8nda ui8nda nda BCL boolMatrix.h boolNDArray.h\ni16nda nda i16nda BCL boolMatrix.h boolNDArray.h\ni16nda i16nda nda BCL boolMatrix.h boolNDArray.h\nui16nda nda ui16nda BCL boolMatrix.h boolNDArray.h\nui16nda ui16nda nda BCL boolMatrix.h boolNDArray.h\ni32nda nda i32nda BCL boolMatrix.h boolNDArray.h\ni32nda i32nda nda BCL boolMatrix.h boolNDArray.h\nui32nda nda ui32nda BCL boolMatrix.h boolNDArray.h\nui32nda ui32nda nda BCL boolMatrix.h boolNDArray.h\ni64nda nda i64nda BCL boolMatrix.h boolNDArray.h\ni64nda i64nda nda BCL boolMatrix.h boolNDArray.h\nui64nda nda ui64nda BCL boolMatrix.h boolNDArray.h\nui64nda ui64nda nda BCL boolMatrix.h boolNDArray.h\ni8nda fnda i8nda BCL boolMatrix.h boolNDArray.h\ni8nda i8nda fnda BCL boolMatrix.h boolNDArray.h\nui8nda fnda ui8nda BCL boolMatrix.h boolNDArray.h\nui8nda ui8nda fnda BCL boolMatrix.h boolNDArray.h\ni16nda fnda i16nda BCL boolMatrix.h boolNDArray.h\ni16nda i16nda fnda BCL boolMatrix.h boolNDArray.h\nui16nda fnda ui16nda BCL boolMatrix.h boolNDArray.h\nui16nda ui16nda fnda BCL boolMatrix.h boolNDArray.h\ni32nda fnda i32nda BCL boolMatrix.h boolNDArray.h\ni32nda i32nda fnda BCL boolMatrix.h boolNDArray.h\nui32nda fnda ui32nda BCL boolMatrix.h boolNDArray.h\nui32nda ui32nda fnda BCL boolMatrix.h boolNDArray.h\ni64nda fnda i64nda BCL boolMatrix.h boolNDArray.h\ni64nda i64nda fnda BCL boolMatrix.h boolNDArray.h\nui64nda fnda ui64nda BCL boolMatrix.h boolNDArray.h\nui64nda ui64nda fnda BCL boolMatrix.h boolNDArray.h\n#\nx i8nda ui8 CL boolMatrix.h boolNDArray.h\nx i8nda i16 CL boolMatrix.h boolNDArray.h\nx i8nda ui16 CL boolMatrix.h boolNDArray.h\nx i8nda i32 CL boolMatrix.h boolNDArray.h\nx i8nda ui32 CL boolMatrix.h boolNDArray.h\nx i8nda i64 CL boolMatrix.h boolNDArray.h\nx i8nda ui64 CL boolMatrix.h boolNDArray.h\n#\nx i16nda i8 CL boolMatrix.h boolNDArray.h\nx i16nda ui8 CL boolMatrix.h boolNDArray.h\nx i16nda ui16 CL boolMatrix.h boolNDArray.h\nx i16nda i32 CL boolMatrix.h boolNDArray.h\nx i16nda ui32 CL boolMatrix.h boolNDArray.h\nx i16nda i64 CL boolMatrix.h boolNDArray.h\nx i16nda ui64 CL boolMatrix.h boolNDArray.h\n#\nx i32nda i8 CL boolMatrix.h boolNDArray.h\nx i32nda ui8 CL boolMatrix.h boolNDArray.h\nx i32nda i16 CL boolMatrix.h boolNDArray.h\nx i32nda ui16 CL boolMatrix.h boolNDArray.h\nx i32nda ui32 CL boolMatrix.h boolNDArray.h\nx i32nda i64 CL boolMatrix.h boolNDArray.h\nx i32nda ui64 CL boolMatrix.h boolNDArray.h\n#\nx i64nda i8 CL boolMatrix.h boolNDArray.h\nx i64nda ui8 CL boolMatrix.h boolNDArray.h\nx i64nda i16 CL boolMatrix.h boolNDArray.h\nx i64nda ui16 CL boolMatrix.h boolNDArray.h\nx i64nda i32 CL boolMatrix.h boolNDArray.h\nx i64nda ui32 CL boolMatrix.h boolNDArray.h\nx i64nda ui64 CL boolMatrix.h boolNDArray.h\n#\nx ui8nda i8 CL boolMatrix.h boolNDArray.h\nx ui8nda i16 CL boolMatrix.h boolNDArray.h\nx ui8nda ui16 CL boolMatrix.h boolNDArray.h\nx ui8nda i32 CL boolMatrix.h boolNDArray.h\nx ui8nda ui32 CL boolMatrix.h boolNDArray.h\nx ui8nda i64 CL boolMatrix.h boolNDArray.h\nx ui8nda ui64 CL boolMatrix.h boolNDArray.h\n#\nx ui16nda i8 CL boolMatrix.h boolNDArray.h\nx ui16nda ui8 CL boolMatrix.h boolNDArray.h\nx ui16nda i16 CL boolMatrix.h boolNDArray.h\nx ui16nda i32 CL boolMatrix.h boolNDArray.h\nx ui16nda ui32 CL boolMatrix.h boolNDArray.h\nx ui16nda i64 CL boolMatrix.h boolNDArray.h\nx ui16nda ui64 CL boolMatrix.h boolNDArray.h\n#\nx ui32nda i8 CL boolMatrix.h boolNDArray.h\nx ui32nda ui8 CL boolMatrix.h boolNDArray.h\nx ui32nda i16 CL boolMatrix.h boolNDArray.h\nx ui32nda ui16 CL boolMatrix.h boolNDArray.h\nx ui32nda i32 CL boolMatrix.h boolNDArray.h\nx ui32nda i64 CL boolMatrix.h boolNDArray.h\nx ui32nda ui64 CL boolMatrix.h boolNDArray.h\n#\nx ui64nda i8 CL boolMatrix.h boolNDArray.h\nx ui64nda ui8 CL boolMatrix.h boolNDArray.h\nx ui64nda i16 CL boolMatrix.h boolNDArray.h\nx ui64nda ui16 CL boolMatrix.h boolNDArray.h\nx ui64nda i32 CL boolMatrix.h boolNDArray.h\nx ui64nda ui32 CL boolMatrix.h boolNDArray.h\nx ui64nda i64 CL boolMatrix.h boolNDArray.h\n#\nx i8 ui8nda CL boolMatrix.h boolNDArray.h\nx i8 i16nda CL boolMatrix.h boolNDArray.h\nx i8 ui16nda CL boolMatrix.h boolNDArray.h\nx i8 i32nda CL boolMatrix.h boolNDArray.h\nx i8 ui32nda CL boolMatrix.h boolNDArray.h\nx i8 i64nda CL boolMatrix.h boolNDArray.h\nx i8 ui64nda CL boolMatrix.h boolNDArray.h\n#\nx i16 i8nda CL boolMatrix.h boolNDArray.h\nx i16 ui8nda CL boolMatrix.h boolNDArray.h\nx i16 ui16nda CL boolMatrix.h boolNDArray.h\nx i16 i32nda CL boolMatrix.h boolNDArray.h\nx i16 ui32nda CL boolMatrix.h boolNDArray.h\nx i16 i64nda CL boolMatrix.h boolNDArray.h\nx i16 ui64nda CL boolMatrix.h boolNDArray.h\n#\nx i32 i8nda CL boolMatrix.h boolNDArray.h\nx i32 ui8nda CL boolMatrix.h boolNDArray.h\nx i32 i16nda CL boolMatrix.h boolNDArray.h\nx i32 ui16nda CL boolMatrix.h boolNDArray.h\nx i32 ui32nda CL boolMatrix.h boolNDArray.h\nx i32 i64nda CL boolMatrix.h boolNDArray.h\nx i32 ui64nda CL boolMatrix.h boolNDArray.h\n#\nx i64 i8nda CL boolMatrix.h boolNDArray.h\nx i64 ui8nda CL boolMatrix.h boolNDArray.h\nx i64 i16nda CL boolMatrix.h boolNDArray.h\nx i64 ui16nda CL boolMatrix.h boolNDArray.h\nx i64 i32nda CL boolMatrix.h boolNDArray.h\nx i64 ui32nda CL boolMatrix.h boolNDArray.h\nx i64 ui64nda CL boolMatrix.h boolNDArray.h\n#\nx ui8 i8nda CL boolMatrix.h boolNDArray.h\nx ui8 i16nda CL boolMatrix.h boolNDArray.h\nx ui8 ui16nda CL boolMatrix.h boolNDArray.h\nx ui8 i32nda CL boolMatrix.h boolNDArray.h\nx ui8 ui32nda CL boolMatrix.h boolNDArray.h\nx ui8 i64nda CL boolMatrix.h boolNDArray.h\nx ui8 ui64nda CL boolMatrix.h boolNDArray.h\n#\nx ui16 i8nda CL boolMatrix.h boolNDArray.h\nx ui16 ui8nda CL boolMatrix.h boolNDArray.h\nx ui16 i16nda CL boolMatrix.h boolNDArray.h\nx ui16 i32nda CL boolMatrix.h boolNDArray.h\nx ui16 ui32nda CL boolMatrix.h boolNDArray.h\nx ui16 i64nda CL boolMatrix.h boolNDArray.h\nx ui16 ui64nda CL boolMatrix.h boolNDArray.h\n#\nx ui32 i8nda CL boolMatrix.h boolNDArray.h\nx ui32 ui8nda CL boolMatrix.h boolNDArray.h\nx ui32 i16nda CL boolMatrix.h boolNDArray.h\nx ui32 ui16nda CL boolMatrix.h boolNDArray.h\nx ui32 i32nda CL boolMatrix.h boolNDArray.h\nx ui32 i64nda CL boolMatrix.h boolNDArray.h\nx ui32 ui64nda CL boolMatrix.h boolNDArray.h\n#\nx ui64 i8nda CL boolMatrix.h boolNDArray.h\nx ui64 ui8nda CL boolMatrix.h boolNDArray.h\nx ui64 i16nda CL boolMatrix.h boolNDArray.h\nx ui64 ui16nda CL boolMatrix.h boolNDArray.h\nx ui64 i32nda CL boolMatrix.h boolNDArray.h\nx ui64 ui32nda CL boolMatrix.h boolNDArray.h\nx ui64 i64nda CL boolMatrix.h boolNDArray.h\n#\nx i8nda ui8nda CL boolMatrix.h boolNDArray.h\nx i8nda i16nda CL boolMatrix.h boolNDArray.h\nx i8nda ui16nda CL boolMatrix.h boolNDArray.h\nx i8nda i32nda CL boolMatrix.h boolNDArray.h\nx i8nda ui32nda CL boolMatrix.h boolNDArray.h\nx i8nda i64nda CL boolMatrix.h boolNDArray.h\nx i8nda ui64nda CL boolMatrix.h boolNDArray.h\n#\nx i16nda i8nda CL boolMatrix.h boolNDArray.h\nx i16nda ui8nda CL boolMatrix.h boolNDArray.h\nx i16nda ui16nda CL boolMatrix.h boolNDArray.h\nx i16nda i32nda CL boolMatrix.h boolNDArray.h\nx i16nda ui32nda CL boolMatrix.h boolNDArray.h\nx i16nda i64nda CL boolMatrix.h boolNDArray.h\nx i16nda ui64nda CL boolMatrix.h boolNDArray.h\n#\nx i32nda i8nda CL boolMatrix.h boolNDArray.h\nx i32nda ui8nda CL boolMatrix.h boolNDArray.h\nx i32nda i16nda CL boolMatrix.h boolNDArray.h\nx i32nda ui16nda CL boolMatrix.h boolNDArray.h\nx i32nda ui32nda CL boolMatrix.h boolNDArray.h\nx i32nda i64nda CL boolMatrix.h boolNDArray.h\nx i32nda ui64nda CL boolMatrix.h boolNDArray.h\n#\nx i64nda i8nda CL boolMatrix.h boolNDArray.h\nx i64nda ui8nda CL boolMatrix.h boolNDArray.h\nx i64nda i16nda CL boolMatrix.h boolNDArray.h\nx i64nda ui16nda CL boolMatrix.h boolNDArray.h\nx i64nda i32nda CL boolMatrix.h boolNDArray.h\nx i64nda ui32nda CL boolMatrix.h boolNDArray.h\nx i64nda ui64nda CL boolMatrix.h boolNDArray.h\n#\nx ui8nda i8nda CL boolMatrix.h boolNDArray.h\nx ui8nda i16nda CL boolMatrix.h boolNDArray.h\nx ui8nda ui16nda CL boolMatrix.h boolNDArray.h\nx ui8nda i32nda CL boolMatrix.h boolNDArray.h\nx ui8nda ui32nda CL boolMatrix.h boolNDArray.h\nx ui8nda i64nda CL boolMatrix.h boolNDArray.h\nx ui8nda ui64nda CL boolMatrix.h boolNDArray.h\n#\nx ui16nda i8nda CL boolMatrix.h boolNDArray.h\nx ui16nda ui8nda CL boolMatrix.h boolNDArray.h\nx ui16nda i16nda CL boolMatrix.h boolNDArray.h\nx ui16nda i32nda CL boolMatrix.h boolNDArray.h\nx ui16nda ui32nda CL boolMatrix.h boolNDArray.h\nx ui16nda i64nda CL boolMatrix.h boolNDArray.h\nx ui16nda ui64nda CL boolMatrix.h boolNDArray.h\n#\nx ui32nda i8nda CL boolMatrix.h boolNDArray.h\nx ui32nda ui8nda CL boolMatrix.h boolNDArray.h\nx ui32nda i16nda CL boolMatrix.h boolNDArray.h\nx ui32nda ui16nda CL boolMatrix.h boolNDArray.h\nx ui32nda i32nda CL boolMatrix.h boolNDArray.h\nx ui32nda i64nda CL boolMatrix.h boolNDArray.h\nx ui32nda ui64nda CL boolMatrix.h boolNDArray.h\n#\nx ui64nda i8nda CL boolMatrix.h boolNDArray.h\nx ui64nda ui8nda CL boolMatrix.h boolNDArray.h\nx ui64nda i16nda CL boolMatrix.h boolNDArray.h\nx ui64nda ui16nda CL boolMatrix.h boolNDArray.h\nx ui64nda i32nda CL boolMatrix.h boolNDArray.h\nx ui64nda ui32nda CL boolMatrix.h boolNDArray.h\nx ui64nda i64nda CL boolMatrix.h boolNDArray.h\n"
  },
  {
    "path": "liboctave/operators/smx-ops",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# NOTE: if this file changes, you must run bootstrap and configure to\n# rebuild the source file lists for Make.\n\n# types\n#\n# key typename object-type header fwd-decl-ok\n#\n#   S:  scalar\n#   M:  matrix\n#   DM: diagonal matrix\n#   ND: N-D array\n#   SM: sparse matrix\n#\nsm SparseMatrix SM dSparse.h YES\nscm SparseComplexMatrix SM CSparse.h YES\nsbm SparseBoolMatrix SM boolSparse.h YES\nb bool S NONE NO\nbm boolMatrix M boolMatrix.h YES\ns double S NONE NO\ncs Complex S oct-cmplx.h NO\nm Matrix M dMatrix.h YES\ncm ComplexMatrix M CMatrix.h YES\n#\n# sparse-matrix operators\n#\n# result_t_1 result_t_2 lhs_t rhs_t op-type headers ...\n#\n# op-type is one of\n#\n#   B: binary ops, + - * /\n#   C: comparison ops, < <= == != >= >\n#   E: == != (Only one of C or E can be used!!)\n#   L: logical ops, & |\n#\ncm scm sm cs BCL boolSparse.h\ncm scm cs sm BCL boolSparse.h\ncm scm scm s BCL boolSparse.h\ncm scm s scm BCL boolSparse.h\nscm scm scm sm BCL boolSparse.h\nscm scm sm scm BCL boolSparse.h\nm sm m sm BCL boolSparse.h\ncm scm m scm BCL boolSparse.h\ncm scm cm sm BCL boolSparse.h\ncm scm cm scm BCL boolSparse.h\nm sm sm m BCL boolSparse.h\ncm scm scm m BCL boolSparse.h\ncm scm sm cm BCL boolSparse.h\ncm scm scm cm BCL boolSparse.h\nbm sbm bm sbm EL\nbm sbm sbm bm EL\n"
  },
  {
    "path": "liboctave/operators/vx-ops",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# NOTE: if this file changes, you must run bootstrap and configure to\n# rebuild the source file lists for Make.\n\n# types\n#\n# key typename object-type header fwd-decl-ok scalar-zero\n#\n# object-type is one of\n#\n#   S:  scalar\n#   V:  vector\n#\nccv ComplexColumnVector V CColVector.h YES 0.0\ncrv ComplexRowVector V CRowVector.h YES 0.0\ncs Complex S oct-cmplx.h NO 0.0\ncv ColumnVector V dColVector.h YES 0.0\nrv RowVector V dRowVector.h YES 0.0\ns double S NONE NO 0.0\nfccv FloatComplexColumnVector V fCColVector.h YES 0.0\nfcrv FloatComplexRowVector V fCRowVector.h YES 0.0\nfcs FloatComplex S oct-cmplx.h NO 0.0\nfcv FloatColumnVector V fColVector.h YES 0.0\nfrv FloatRowVector V fRowVector.h YES 0.0\nfs float S NONE NO 0.0\n#\n# vector operators\n#\n# result_t lhs_t rhs_t op-type\n#\n# op-type is one of\n#\n#   B: binary ops, + - * /\n#   C: comparison ops, < <= == != >= >\n#   E: == != (Only one of C or E can be used!!)\n#   L: logical ops, & |\n#\n# though we are currently defining only binary ops for vectors.\n#\nccv ccv cv B\nccv ccv s B\ncrv crv rv B\ncrv crv s B\nccv cs cv B\ncrv cs rv B\nccv cv ccv B\nccv cv cs B\ncrv rv crv B\ncrv rv cs B\nccv s ccv B\ncrv s crv B\nfccv fccv fcv B\nfccv fccv fs B\nfcrv fcrv frv B\nfcrv fcrv fs B\nfccv fcs fcv B\nfcrv fcs frv B\nfccv fcv fccv B\nfccv fcv fcs B\nfcrv frv fcrv B\nfcrv frv fcs B\nfccv fs fccv B\nfcrv fs fcrv B\n"
  },
  {
    "path": "liboctave/system/child-list.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"child-list.h\"\n#include \"oct-syscalls.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid child_list::remove (pid_t pid)\n{\n  m_list.remove_if ([pid] (const child& oc) { return oc.m_pid == pid; });\n}\n\nvoid\nchild_list::child_list::insert (pid_t pid, child::child_event_handler f)\n{\n  m_list.push_back (child (pid, f));\n}\n\nvoid\nchild_list::reap ()\n{\n  // Mark the record for PID invalid.\n\n  for (auto& oc : m_list)\n    {\n      // The call to the child::child_event_handler might\n      // invalidate the iterator (for example, by calling\n      // child_list::remove), so we increment the iterator\n      // here.\n\n      if (oc.m_have_status)\n        {\n          oc.m_have_status = 0;\n\n          child::child_event_handler f = oc.m_handler;\n\n          if (f && f (oc.m_pid, oc.m_status))\n            oc.m_pid = -1;\n        }\n    }\n\n  // Remove PIDs that have completed above.\n  remove (-1);\n}\n\n// Wait on our children and record any changes in their status.\n\nbool\nchild_list::wait ()\n{\n  bool retval = false;\n\n  for (auto& oc : m_list)\n    {\n      pid_t pid = oc.m_pid;\n\n      if (pid > 0)\n        {\n          int status;\n\n          if (sys::waitpid (pid, &status, sys::wnohang ()) > 0)\n            {\n              oc.m_have_status = 1;\n\n              oc.m_status = status;\n\n              retval = true;\n\n              break;\n            }\n        }\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/child-list.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_child_list_h)\n#define octave_child_list_h 1\n\n#include \"octave-config.h\"\n\n#include <csignal>\n\n#include <list>\n\n#include <sys/types.h>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTAVE_API child\n{\npublic:\n\n  // Do whatever to handle event for child with PID (might not\n  // actually be dead, could just be stopped).  Return true if\n  // the list element corresponding to PID should be removed from\n  // list.  This function should not call any functions that modify\n  // the child_list.\n\n  typedef bool (*child_event_handler) (pid_t, int);\n\n  child (pid_t pid = -1, child_event_handler f = nullptr)\n    : m_pid (pid), m_handler (f), m_have_status (0), m_status (0)\n  { }\n\n  child (const child&) = default;\n\n  child& operator = (const child&) = default;\n\n  ~child () = default;\n\n  // The process ID of this child.\n  pid_t m_pid;\n\n  // The function we call if an event happens for this child.\n  child_event_handler m_handler;\n\n  // Nonzero if this child has stopped or terminated.\n  sig_atomic_t m_have_status;\n\n  // The m_status of this child; 0 if running, otherwise a m_status value\n  // from waitpid.\n  int m_status;\n};\n\nclass OCTAVE_API child_list\n{\npublic:\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (child_list)\n\n  void insert (pid_t pid, child::child_event_handler f);\n\n  void remove (pid_t pid);\n\n  void reap ();\n\n  bool wait ();\n\nprivate:\n\n  std::list<child> m_list;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/cmach-info.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_cmach_info_h)\n#define octave_cmach_info_h 1\n\n#warning 'header file \"cmach-info.h\" is deprecated, use \"mach-info.h\" instead'\n\n#include \"mach-info.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/system/dir-ops.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n#include <cstring>\n\n#include <list>\n#include <string>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include \"windows.h\"\n#endif\n\n#include \"dirent-wrappers.h\"\n\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"oct-error.h\"\n#include \"oct-sysdep.h\"\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nbool\ndir_entry::open (const std::string& n)\n{\n  if (! n.empty ())\n    m_name = n;\n\n  if (! m_name.empty ())\n    {\n      close ();\n\n      std::string fullname = sys::file_ops::tilde_expand (m_name);\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n      std::string msg;\n\n      if (sys::dir_exists (fullname, msg))\n        // Never dereference this pointer!\n        // We just need something that is non-null.\n        m_dir = reinterpret_cast<void *> (1);\n      else\n        {\n          m_dir = nullptr;\n          m_errmsg = msg;\n        }\n#else\n      m_dir = octave_opendir_wrapper (fullname.c_str ());\n\n      if (! m_dir)\n        m_errmsg = std::strerror (errno);\n#endif\n    }\n  else\n    m_errmsg = \"dir_entry::open: empty filename\";\n\n  return m_dir != nullptr;\n}\n\nstring_vector\ndir_entry::read ()\n{\n  string_vector retval;\n\n  if (ok ())\n    {\n      std::list<std::string> dirlist;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n      WIN32_FIND_DATAW find_file_data;\n      std::wstring pattern = u8_to_wstring (m_name + \"\\\\*\");\n      std::string file_name;\n\n      HANDLE h_find_file = FindFirstFileW (pattern.c_str (), &find_file_data);\n      if (h_find_file != INVALID_HANDLE_VALUE)\n        {\n          do\n            {\n              file_name = u8_from_wstring (find_file_data.cFileName);\n              dirlist.push_back (file_name);\n            }\n          while (FindNextFileW (h_find_file, &find_file_data));\n\n          FindClose (h_find_file);\n        }\n#else\n      char *fname;\n\n      while ((fname = octave_readdir_wrapper (m_dir)))\n        dirlist.push_back (fname);\n#endif\n\n      retval = string_vector (dirlist);\n    }\n\n  return retval;\n}\n\nbool\ndir_entry::close ()\n{\n  bool retval = true;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  m_dir = nullptr;\n#else\n  if (m_dir)\n    {\n      retval = (octave_closedir_wrapper (m_dir) == 0);\n\n      m_dir = nullptr;\n    }\n#endif\n\n  return retval;\n}\n\nunsigned int\ndir_entry::max_name_length ()\n{\n  return octave_name_max_wrapper ();\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/dir-ops.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dir_ops_h)\n#define octave_dir_ops_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nclass OCTAVE_API dir_entry\n{\n\n  // NOTE: This class cannot be used safely cross-platform (Windows) with\n  // non-ASCII characters in paths.\n  // Consider replacing the implementation using std::filesystem (C++ 17).\n  // In the meantime, consider using sys::get_dirlist instead.\n\npublic:\n\n  dir_entry (const std::string& n = \"\")\n    : m_name (n), m_dir (nullptr), m_fail (false), m_errmsg ()\n  {\n    if (! m_name.empty ())\n      open ();\n  }\n\n  dir_entry (const dir_entry& d)\n    : m_name (d.m_name), m_dir (d.m_dir), m_fail (d.m_fail),\n      m_errmsg (d.m_errmsg)\n  { }\n\n  dir_entry& operator = (const dir_entry& d)\n  {\n    if (this != &d)\n      {\n        m_name = d.m_name;\n        m_dir = d.m_dir;\n        m_fail = d.m_fail;\n        m_errmsg = d.m_errmsg;\n      }\n\n    return *this;\n  }\n\n  ~dir_entry () { close (); }\n\n  bool open (const std::string& = \"\");\n\n  string_vector read ();\n\n  bool close ();\n\n  bool ok () const { return m_dir && ! m_fail; }\n\n  operator bool () const { return ok (); }\n\n  std::string error () const { return ok () ? \"\" : m_errmsg; }\n\n  static unsigned int max_name_length ();\n\nprivate:\n\n  // Name of the directory.\n  std::string m_name;\n\n  // A pointer to the contents of the directory.  We use void here to\n  // avoid possible conflicts with the way some systems declare the\n  // type DIR.\n  void *m_dir;\n\n  // TRUE means the open for this directory failed.\n  bool m_fail;\n\n  // If a failure occurs, this contains the system error text.\n  std::string m_errmsg;\n};\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/file-ops.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <cctype>\n#  include <system_error>\n\n#  include <windows.h>\n#  include \"unwind-prot.h\"\n#else\n#  include \"canonicalize-file-name-wrapper.h\"\n#endif\n\n#include \"areadlink-wrapper.h\"\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"gen-tempname-wrapper.h\"\n#include \"oct-env.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-password.h\"\n#include \"oct-sysdep.h\"\n#include \"quit.h\"\n#include \"stat-wrappers.h\"\n#include \"str-vec.h\"\n#include \"unistd-wrappers.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// The following tilde-expansion code was stolen and adapted from\n// readline.\n\n// The default value of tilde_additional_prefixes.  This is set to\n// whitespace preceding a tilde so that simple programs which do not\n// perform any word separation get desired behavior.\nstatic const char *default_prefixes[] = { \" ~\", \"\\t~\", \":~\", nullptr };\n\n// The default value of tilde_additional_suffixes.  This is set to\n// whitespace or newline so that simple programs which do not perform\n// any word separation get desired behavior.\nstatic const char *default_suffixes[] = { \" \", \"\\n\", \":\", nullptr };\n\nstatic std::size_t\ntilde_find_prefix (const std::string& s, std::size_t& len)\n{\n  len = 0;\n\n  std::size_t s_len = s.length ();\n\n  if (s_len == 0 || s[0] == '~')\n    return 0;\n\n  string_vector prefixes = sys::file_ops::tilde_additional_prefixes;\n\n  if (! prefixes.empty ())\n    {\n      for (std::size_t i = 0; i < s_len; i++)\n        {\n          for (int j = 0; j < prefixes.numel (); j++)\n            {\n              std::size_t pfx_len = prefixes[j].length ();\n\n              if (prefixes[j] == s.substr (i, pfx_len))\n                {\n                  len = pfx_len - 1;\n                  return i + len;\n                }\n            }\n        }\n    }\n\n  return s_len;\n}\n\n// Find the end of a tilde expansion in S, and return the index\n// of the character which ends the tilde definition.\n\nstatic std::size_t\ntilde_find_suffix (const std::string& s)\n{\n  std::size_t s_len = s.length ();\n\n  string_vector suffixes = sys::file_ops::tilde_additional_suffixes;\n\n  std::size_t i = 0;\n\n  for ( ; i < s_len; i++)\n    {\n      if (sys::file_ops::is_dir_sep (s[i]))\n        break;\n\n      if (! suffixes.empty ())\n        {\n          for (int j = 0; j < suffixes.numel (); j++)\n            {\n              std::size_t sfx_len = suffixes[j].length ();\n\n              if (suffixes[j] == s.substr (i, sfx_len))\n                return i;\n            }\n        }\n    }\n\n  return i;\n}\n\n// Take FNAME and return the tilde prefix we want expanded.\n\nstatic std::string\nisolate_tilde_prefix (const std::string& fname)\n{\n  std::size_t f_len = fname.length ();\n\n  std::size_t len = 1;\n\n  while (len < f_len && ! sys::file_ops::is_dir_sep (fname[len]))\n    len++;\n\n  return fname.substr (1, len);\n}\n\n// Do the work of tilde expansion on FILENAME.  FILENAME starts with a\n// tilde.\n\nstatic std::string\ntilde_expand_word (const std::string& filename)\n{\n  std::size_t f_len = filename.length ();\n\n  if (f_len == 0 || filename[0] != '~')\n    return std::string (filename);\n\n  // A leading '~/' or a bare '~' is *always* translated to the value\n  // of $HOME or the home directory of the current user, regardless of\n  // any preexpansion hook.\n\n  if (f_len == 1 || sys::file_ops::is_dir_sep (filename[1]))\n    return sys::env::get_home_directory () + filename.substr (1);\n\n  std::string username = isolate_tilde_prefix (filename);\n\n  std::size_t user_len = username.length ();\n\n  std::string dirname;\n\n  if (sys::file_ops::tilde_expansion_preexpansion_hook)\n    {\n      std::string expansion\n        = sys::file_ops::tilde_expansion_preexpansion_hook (username);\n\n      if (! expansion.empty ())\n        return expansion + filename.substr (user_len+1);\n    }\n\n  // No preexpansion hook, or the preexpansion hook failed.  Look in the\n  // password database.\n\n  sys::password pw = sys::password::getpwnam (username);\n\n  if (! pw)\n    {\n      // If the calling program has a special syntax for expanding tildes,\n      // and we couldn't find a standard expansion, then let them try.\n\n      if (sys::file_ops::tilde_expansion_failure_hook)\n        {\n          std::string expansion\n            = sys::file_ops::tilde_expansion_failure_hook (username);\n\n          if (! expansion.empty ())\n            dirname = expansion + filename.substr (user_len+1);\n        }\n\n      // If we don't have a failure hook, or if the failure hook did not\n      // expand the tilde, return a copy of what we were passed.\n\n      if (dirname.empty ())\n        dirname = filename;\n    }\n  else\n    dirname = pw.dir () + filename.substr (user_len+1);\n\n  return dirname;\n}\n\nOCTAVE_BEGIN_NAMESPACE(sys)\nOCTAVE_BEGIN_NAMESPACE(file_ops)\n\nchar dev_sep_char ()\n{\n#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))\n  return ':';\n#else\n  return 0;\n#endif\n}\n\nchar\ndir_sep_char ()\n{\n#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))\n  return '\\\\';\n#else\n  return '/';\n#endif\n}\n\nstd::string\ndir_sep_str ()\n{\n#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))\n  return R\"(\\)\";\n#else\n  return \"/\";\n#endif\n}\n\nstd::string\ndir_sep_chars ()\n{\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)\n  return R\"(/\\)\";\n#else\n  return dir_sep_str ();\n#endif\n}\n\ntilde_expansion_hook tilde_expansion_preexpansion_hook = nullptr;\n\ntilde_expansion_hook tilde_expansion_failure_hook = nullptr;\n\nstring_vector tilde_additional_prefixes = default_prefixes;\n\nstring_vector tilde_additional_suffixes = default_suffixes;\n\nbool\nis_dev_sep (char c)\n{\n#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))\n  return c == dev_sep_char ();\n#else\n  octave_unused_parameter (c);\n\n  return false;\n#endif\n}\n\nbool\nis_dir_sep (char c)\n{\n  std::string tmp = dir_sep_chars ();\n  return tmp.find (c) != std::string::npos;\n}\n\nstd::string\ntilde_expand (const std::string& name)\n{\n  if (name.find ('~') == std::string::npos)\n    return std::string (name);\n  else\n    {\n      std::string result;\n\n      std::size_t name_len = name.length ();\n\n      // Scan through S expanding tildes as we come to them.\n\n      std::size_t pos = 0;\n\n      while (1)\n        {\n          if (pos > name_len)\n            break;\n\n          std::size_t len;\n\n          // Make START point to the tilde which starts the expansion.\n\n          std::size_t start = tilde_find_prefix (name.substr (pos), len);\n\n          result.append (name.substr (pos, start));\n\n          // Advance STRING to the starting tilde.\n\n          pos += start;\n\n          // Make FINI be the index of one after the last character of the\n          // username.\n\n          std::size_t fini = tilde_find_suffix (name.substr (pos));\n\n          // If both START and FINI are zero, we are all done.\n\n          if (! (start || fini))\n            break;\n\n          // Expand the entire tilde word, and copy it into RESULT.\n\n          std::string tilde_word = name.substr (pos, fini);\n\n          pos += fini;\n\n          std::string expansion = tilde_expand_word (tilde_word);\n\n          result.append (expansion);\n        }\n\n      return result;\n    }\n}\n\nstring_vector\ntilde_expand (const string_vector& names)\n{\n  int n = names.numel ();\n\n  string_vector retval (n);\n\n  for (int i = 0; i < n; i++)\n    retval[i] = tilde_expand (names[i]);\n\n  return retval;\n}\n\nstd::string\nconcat (const std::string& dir, const std::string& file)\n{\n  return dir.empty ()\n         ? file\n         : (is_dir_sep (dir.back ())\n            ? dir + file\n            : dir + dir_sep_char () + file);\n}\n\nstd::string\ndirname (const std::string& path)\n{\n  std::size_t ipos = path.find_last_of (dir_sep_chars ());\n\n  return (ipos != std::string::npos) ? path.substr (0, ipos) : \"\";\n}\n\nstd::string\ntail (const std::string& path)\n{\n  std::size_t ipos = path.find_last_of (dir_sep_chars ());\n\n  if (ipos != std::string::npos)\n    ipos++;\n  else\n    ipos = 0;\n\n  return path.substr (ipos);\n}\n\nstd::string\nnative_separator_path (const std::string& path)\n{\n  std::string retval;\n\n  if (dir_sep_char () == '/')\n    retval = path;\n  else\n    {\n      std::size_t n = path.length ();\n      for (std::size_t i = 0; i < n; i++)\n        {\n          if (path[i] == '/')\n            retval += dir_sep_char();\n          else\n            retval += path[i];\n        }\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(file_ops)\n\nint mkdir (const std::string& nm, mode_t md)\n{\n  std::string msg;\n  return mkdir (nm, md, msg);\n}\n\nint\nmkdir (const std::string& name, mode_t mode, std::string& msg)\n{\n  msg = \"\";\n\n  int status = octave_mkdir_wrapper (name.c_str (), mode);\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\nint\nrecursive_mkdir (const std::string& name, mode_t mode)\n{\n  std::string msg;\n  return recursive_mkdir (name, mode, msg);\n}\n\nint\nrecursive_mkdir (const std::string& name, mode_t mode, std::string& msg)\n{\n  int status;\n\n  // account for root in absolute directories\n#if defined (OCTAVE_USE_WINDOWS_API)\n  // root of current drive\n  std::size_t skip_root = 0;\n  if (name.size () > 1)\n    {\n      if (name[1] == ':')\n        // drive root (e.g., C:\\)\n        skip_root = 2;\n      else if (file_ops::is_dir_sep (name[0])\n               && file_ops::is_dir_sep (name[1]))\n        {\n          // UNC path root (e.g., \\\\SERVER\\share\\)\n          skip_root = name.find_first_of (file_ops::dir_sep_chars (), 2);\n          skip_root = name.find_first_of (file_ops::dir_sep_chars (),\n                                          skip_root + 1);\n        }\n    }\n\n  std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (),\n                                          skip_root + 1);\n#else\n  std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (), 1);\n#endif\n\n  // iterate over all componenents of NAME and make directories\n  while (delim != std::string::npos)\n    {\n      std::string base = name.substr (0, delim);\n      sys::file_stat fs (base);\n      if (! fs.is_dir ())\n        {\n          status = mkdir (base, mode, msg);\n          if (status < 0)\n            return status;\n        }\n      delim = name.find_first_of (file_ops::dir_sep_chars (), delim + 1);\n    }\n\n  // finally, create requested directory\n  return mkdir (name, mode, msg);\n}\n\nint\nmkfifo (const std::string& nm, mode_t md)\n{\n  std::string msg;\n  return mkfifo (nm, md, msg);\n}\n\nint\nmkfifo (const std::string& name, mode_t mode, std::string& msg)\n{\n  msg = \"\";\n\n  int status = octave_mkfifo_wrapper (name.c_str (), mode);\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\nint\nlink (const std::string& old_name, const std::string& new_name)\n{\n  std::string msg;\n  return link (old_name, new_name, msg);\n}\n\nint\nlink (const std::string& old_name, const std::string& new_name,\n      std::string& msg)\n{\n  msg = \"\";\n\n  int status = -1;\n\n  status = octave_link_wrapper (old_name.c_str (), new_name.c_str ());\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\nint\nsymlink (const std::string& old_name, const std::string& new_name)\n{\n  std::string msg;\n  return symlink (old_name, new_name, msg);\n}\n\nint\nsymlink (const std::string& old_name, const std::string& new_name,\n         std::string& msg)\n{\n  msg = \"\";\n\n  int status = -1;\n\n  status = octave_symlink_wrapper (old_name.c_str (), new_name.c_str ());\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\nint\nreadlink (const std::string& path, std::string& result)\n{\n  std::string msg;\n  return readlink (path, result, msg);\n}\n\nint\nreadlink (const std::string& path, std::string& result, std::string& msg)\n{\n  int status = -1;\n\n  msg = \"\";\n\n  char *buf = octave_areadlink_wrapper (path.c_str ());\n\n  if (! buf)\n    msg = std::strerror (errno);\n  else\n    {\n      result = buf;\n      ::free (buf);\n      status = 0;\n    }\n\n  return status;\n}\n\nint\nrename (const std::string& from, const std::string& to)\n{\n  std::string msg;\n  return rename (from, to, msg);\n}\n\nint\nrename (const std::string& from, const std::string& to,\n        std::string& msg)\n{\n  int status = -1;\n\n  msg = \"\";\n\n  // Do nothing if source and target are the same file.\n  if (same_file (to, from))\n    return 0;\n\n  // The behavior of std::rename with existing target is not defined by the\n  // standard.  Implementations differ vastly.  For Octave, use the following\n  // for the case that the target already exists:\n  // If the source and the target are regular files, overwrite the target.\n  // In other cases, fail.\n  if (file_exists (to))\n    {\n      if (file_exists (to, false) && file_exists (from, false))\n        {\n#if ! defined (OCTAVE_USE_WINDOWS_API)\n          unlink (to);\n#endif\n        }\n      else\n        {\n          msg = \"Target already exists.\";\n          return status;\n        }\n    }\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::wstring wfrom = u8_to_wstring (from);\n  std::wstring wto = u8_to_wstring (to);\n\n  DWORD from_attr = GetFileAttributesW (wfrom.c_str ());\n  DWORD to_attr = GetFileAttributesW (wto.c_str ());\n\n  if (from_attr == INVALID_FILE_ATTRIBUTES)\n    {\n      // from does not exist\n      const std::error_condition econd\n        = std::system_category ().default_error_condition (ERROR_FILE_NOT_FOUND);\n      msg = econd.message ();\n      return status;\n    }\n\n  if (from_attr & FILE_ATTRIBUTE_DIRECTORY)\n    {\n      // rename directory\n      if (to_attr != INVALID_FILE_ATTRIBUTES)\n        {\n          // target already exists\n          msg = \"Cannot replace with directory\";\n          return status;\n        }\n\n      if (MoveFileExW (wfrom.c_str (), wto.c_str (), 0))\n        return 0;\n\n      const std::error_condition econd\n        = std::system_category ().default_error_condition (GetLastError ());\n      msg = econd.message ();\n      return status;\n    }\n\n  // use MoveFileExW with MOVEFILE_REPLACE_EXISTING in a retry loop\n  // files might be locked by anti-virus, indexers, etc.\n\n  static const int max_retries = 10;\n\n  for (int attempt = 0; attempt < max_retries; ++attempt)\n    {\n      if (MoveFileExW (wfrom.c_str (), wto.c_str (), MOVEFILE_REPLACE_EXISTING))\n        return 0;\n\n      DWORD err = GetLastError ();\n\n      if (err != ERROR_SHARING_VIOLATION\n          && err != ERROR_ACCESS_DENIED\n          && err != ERROR_LOCK_VIOLATION\n          && err != ERROR_DRIVE_LOCKED)\n        {\n          // return if the error is not potentially transient\n          const std::error_condition econd\n            = std::system_category ().default_error_condition (err);\n          msg = econd.message ();\n          return status;\n        }\n\n      if (attempt + 1 < max_retries)\n        {\n          // wait before next try\n          Sleep (5);\n        }\n    }\n\n  const std::error_condition econd\n    = std::system_category ().default_error_condition (GetLastError ());\n  msg = econd.message ();\n\n#else\n  status = std::rename (from.c_str (), to.c_str ());\n\n  if (status < 0)\n    msg = std::strerror (errno);\n#endif\n\n  return status;\n}\n\nint\nrmdir (const std::string& name)\n{\n  std::string msg;\n  return rmdir (name, msg);\n}\n\nint\nrmdir (const std::string& name, std::string& msg)\n{\n  msg = \"\";\n\n  int status = -1;\n\n  status = octave_rmdir_wrapper (name.c_str ());\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\n// And a version that works recursively.\n\nint\nrecursive_rmdir (const std::string& name)\n{\n  std::string msg;\n  return recursive_rmdir (name, msg);\n}\n\nint\nrecursive_rmdir (const std::string& name, std::string& msg)\n{\n  msg = \"\";\n\n  int status = 0;\n\n  string_vector dirlist;\n\n  if (get_dirlist (name, dirlist, msg))\n    {\n      for (octave_idx_type i = 0; i < dirlist.numel (); i++)\n        {\n          octave_quit ();\n\n          std::string nm = dirlist[i];\n\n          // Skip current directory and parent.\n          if (nm == \".\" || nm == \"..\")\n            continue;\n\n          std::string fullnm = name + file_ops::dir_sep_str () + nm;\n\n          // Get info about the file.  Don't follow links.\n          file_stat fs (fullnm, false);\n\n          if (fs)\n            {\n              if (fs.is_dir ())\n                {\n                  status = recursive_rmdir (fullnm, msg);\n\n                  if (status < 0)\n                    break;\n                }\n              else\n                {\n                  status = unlink (fullnm, msg);\n\n                  if (status < 0)\n                    break;\n                }\n            }\n          else\n            {\n              msg = fs.error ();\n              break;\n            }\n        }\n\n      if (status >= 0)\n        status = rmdir (name, msg);\n    }\n  else\n    status = -1;\n\n  return status;\n}\n\nint\numask (mode_t mode)\n{\n  return octave_umask_wrapper (mode);\n}\n\nint\nunlink (const std::string& name)\n{\n  std::string msg;\n  return unlink (name, msg);\n}\n\nint\nunlink (const std::string& name, std::string& msg)\n{\n  msg = \"\";\n\n  int status = -1;\n\n  status = octave_unlink_wrapper (name.c_str ());\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\nstd::string\ntempnam (const std::string& dir, const std::string& pfx)\n{\n  std::string msg;\n  return tempnam (dir, pfx, msg);\n}\n\nstd::string\ntempnam (const std::string& dir, const std::string& pfx,\n         std::string& msg)\n{\n  msg = \"\";\n\n  std::string retval;\n\n  // get dir path to use for template\n  std::string templatename;\n  if (dir.empty ())\n    templatename = env::get_temp_directory ();\n  else if (! file_stat (dir, false).is_dir ())\n    templatename = env::get_temp_directory ();\n  else\n    templatename = dir;\n\n  // add dir sep char if it is not there\n  if (*templatename.rbegin () != file_ops::dir_sep_char ())\n    templatename += file_ops::dir_sep_char ();\n\n  if (pfx.empty ())\n    templatename += \"file\";\n  else\n    templatename += pfx;\n\n  // add the required XXXXXX for the template\n  templatename += \"XXXXXX\";\n\n  // create and copy template to char array for call to gen_tempname\n  OCTAVE_LOCAL_BUFFER (char, tname, templatename.length () + 1);\n\n  strcpy (tname, templatename.c_str ());\n\n  if (octave_gen_tempname_wrapper (tname) == -1)\n    msg = std::strerror (errno);\n  else\n    retval = tname;\n\n  return retval;\n}\n\nstd::string\ncanonicalize_file_name (const std::string& name)\n{\n  std::string msg;\n  return canonicalize_file_name (name, msg);\n}\n\nstd::string\ncanonicalize_file_name (const std::string& name, std::string& msg)\n{\n  msg = \"\";\n\n  std::string retval;\n\n  // FIXME: Consider replacing this with std::filesystem::canonical on all\n  // platforms once we allow using C++17.\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  // open file handle\n  std::wstring wname = u8_to_wstring (name);\n  HANDLE h_file = CreateFileW (wname.c_str (), GENERIC_READ,\n                               FILE_SHARE_READ, nullptr, OPEN_EXISTING,\n                               FILE_FLAG_BACKUP_SEMANTICS, nullptr);\n\n  // Might have been a symbolic link that points to a network share.\n  // It looks like opening a network share itself (not a file or folder\n  // *on* a share) might return an invalid handle.  As a workaround, try to\n  // open a handle to the symbolic link itself (and do not resolve it).\n  if (h_file == INVALID_HANDLE_VALUE)\n    h_file = CreateFileW (wname.c_str (), GENERIC_READ,\n                          FILE_SHARE_READ, nullptr, OPEN_EXISTING,\n                          FILE_FLAG_BACKUP_SEMANTICS\n                          | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);\n\n  if (h_file == INVALID_HANDLE_VALUE)\n    {\n      msg = \"Unable to open file \\\"\" + name + \"\\\"\";\n      return retval;\n    }\n\n  unwind_action close_file_handle (CloseHandle, h_file);\n\n  const std::size_t buf_size = 32767;\n  wchar_t buffer[buf_size] = L\"\";\n\n  // query canonical name\n  DWORD len = GetFinalPathNameByHandleW (h_file, buffer, buf_size,\n                                         FILE_NAME_NORMALIZED);\n  if (len >= buf_size)\n    {\n      msg = \"Error querying normalized name for \\\"\" + name + \"\\\"\";\n      return retval;\n    }\n\n  retval = u8_from_wstring (std::wstring (buffer, len));\n\n  // remove prefix\n  // \"Normal\" paths are prefixed by \"\\\\?\\\".\n  // UNC paths are prefixed by \"\\\\?\\UNC\\\".\n  if (retval.compare (0, 8, R\"(\\\\?\\UNC\\)\") == 0)\n    {\n      retval = retval.erase (2, 6);\n\n      // If the initial path looked like a mapped network drive, replace\n      // portion of path that corresponds to mapped root with drive root.\n      if (name.size () < 3 || name[1] != ':')\n        return retval;\n\n      // UNC path corresponding to original drive letter (mappped drive)\n      std::wstring orig_map = wname.substr (0, 3);\n      orig_map[2] = L'\\\\';\n      HANDLE h_map = CreateFileW (orig_map.c_str (), GENERIC_READ,\n                                  FILE_SHARE_READ, nullptr, OPEN_EXISTING,\n                                  FILE_FLAG_BACKUP_SEMANTICS\n                                  | FILE_FLAG_OPEN_REPARSE_POINT,\n                                  nullptr);\n\n      if (h_map == INVALID_HANDLE_VALUE)\n        // cannot determine common root\n        return retval;\n\n      unwind_action close_map_handle (CloseHandle, h_map);\n      len = GetFinalPathNameByHandleW (h_map, buffer, buf_size,\n                                       FILE_NAME_NORMALIZED);\n\n      std::string orig_root\n        = u8_from_wstring (std::wstring (buffer, len));\n\n      if (orig_root.compare (0, 8, R\"(\\\\?\\UNC\\)\"))\n        // root was not a mapped share\n        return retval;\n\n      orig_root = orig_root.erase (2, 6);\n      // trim trailing file separators from UNC path corresponding to root\n      std::string file_seps = file_ops::dir_sep_chars ();\n      while (file_seps.find (orig_root.back ()) != std::string::npos)\n        orig_root.pop_back ();\n\n      if (retval.compare (0, orig_root.size (), orig_root))\n        // start of UNC path doesn't match mapped drive root\n        return retval;\n\n      // file is on mapped share\n      size_t sep_pos = orig_root.size ();\n      if (sep_pos != retval.size ())\n        retval = retval.substr (sep_pos-2);\n      else\n        retval.resize (2);  // no file component\n      retval[0] = std::toupper (name[0]);\n      retval[1] = ':';\n    }\n  else if (retval.compare (0, 4, R\"(\\\\?\\)\") == 0)\n    retval = retval.erase (0, 4);\n#else\n  char *tmp = octave_canonicalize_file_name_wrapper (name.c_str ());\n\n  if (tmp)\n    {\n      retval = tmp;\n      free (tmp);\n    }\n\n  if (retval.empty ())\n    msg = std::strerror (errno);\n#endif\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/file-ops.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_file_ops_h)\n#define octave_file_ops_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include <sys/types.h>\n\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nOCTAVE_BEGIN_NAMESPACE(file_ops)\n\ntypedef std::string (*tilde_expansion_hook) (const std::string&);\n\n// If non-null, this contains the address of a function that the\n// application wants called before trying the standard tilde\n// expansions.  The function is called with the text sans tilde, and\n// returns a malloc()'ed string which is the expansion, or a NULL\n// pointer if the expansion fails.\n\nextern OCTAVE_API tilde_expansion_hook tilde_expansion_preexpansion_hook;\n\n// If non-null, this contains the address of a function to call if the\n// standard meaning for expanding a tilde fails.  The function is\n// called with the text (sans tilde, as in \"foo\"), and returns a\n// malloc()'ed string which is the expansion, or a NULL pointer if\n// there is no expansion.\n\nextern OCTAVE_API tilde_expansion_hook tilde_expansion_failure_hook;\n\n// When non-null, this is a NULL terminated array of strings which are\n// duplicates for a tilde prefix.  Bash uses this to expand '=~' and\n// ':~'.\n\nextern OCTAVE_API string_vector tilde_additional_prefixes;\n\n// When non-null, this is a NULL terminated array of strings which\n// match the end of a username, instead of just \"/\".  Bash sets this\n// to ':' and '=~'.\n\nextern OCTAVE_API string_vector tilde_additional_suffixes;\n\n// Find the start of a tilde expansion in S, and return the index\n// of the tilde which starts the expansion.  Place the length of the\n// text which identified this tilde starter in LEN, excluding the\n// tilde itself.\n\nextern OCTAVE_API char dev_sep_char ();\n\nextern OCTAVE_API bool is_dev_sep (char c);\n\nextern OCTAVE_API char dir_sep_char ();\n\nextern OCTAVE_API std::string dir_sep_str ();\n\nextern OCTAVE_API std::string dir_sep_chars ();\n\nextern OCTAVE_API bool is_dir_sep (char c);\n\n// If NAME has a leading ~ or ~user, Unix-style, expand it to the\n// user's home directory.  If no ~, or no <pwd.h>, just return NAME.\n\nextern OCTAVE_API std::string tilde_expand (const std::string&);\n\n// A vector version of the above.\n\nextern OCTAVE_API string_vector tilde_expand (const string_vector&);\n\nextern OCTAVE_API std::string concat (const std::string&, const std::string&);\n\n// Return the directory part of a filename or an empty string if\n// there is no directory component.  Does not check to see\n// whether the file exists or is a directory.\n\nextern OCTAVE_API std::string dirname (const std::string& path);\n\n// Return the tail member of a filename.\n\nextern OCTAVE_API std::string tail (const std::string& path);\n\n// Convert path from UNIX type separators to whatever is the\n// system separators.\n\nextern OCTAVE_API std::string\nnative_separator_path (const std::string& path);\n\nOCTAVE_END_NAMESPACE(file_ops)\n\nextern OCTAVE_API int\nmkdir (const std::string&, mode_t);\n\nextern OCTAVE_API int\nmkdir (const std::string&, mode_t, std::string&);\n\nextern OCTAVE_API int\nrecursive_mkdir (const std::string& name, mode_t mode);\n\nextern OCTAVE_API int\nrecursive_mkdir (const std::string& name, mode_t mode, std::string& msg);\n\nextern OCTAVE_API int\nmkfifo (const std::string&, mode_t);\n\nextern OCTAVE_API int\nmkfifo (const std::string&, mode_t, std::string&);\n\nextern OCTAVE_API int\nlink (const std::string&, const std::string&);\n\nextern OCTAVE_API int\nlink (const std::string&, const std::string&, std::string&);\n\nextern OCTAVE_API int\nsymlink (const std::string&, const std::string&);\n\nextern OCTAVE_API int\nsymlink (const std::string&, const std::string&, std::string&);\n\nextern OCTAVE_API int\nreadlink (const std::string&, std::string&);\n\nextern OCTAVE_API int\nreadlink (const std::string&, std::string&, std::string&);\n\nextern OCTAVE_API int\nrename (const std::string&, const std::string&);\n\nextern OCTAVE_API int\nrename (const std::string&, const std::string&, std::string&);\n\nextern OCTAVE_API int\nrmdir (const std::string&);\n\nextern OCTAVE_API int\nrmdir (const std::string&, std::string&);\n\nextern OCTAVE_API int\nrecursive_rmdir (const std::string&);\n\nextern OCTAVE_API int\nrecursive_rmdir (const std::string&, std::string&);\n\nextern OCTAVE_API int\numask (mode_t);\n\nextern OCTAVE_API int\nunlink (const std::string&);\n\nextern OCTAVE_API int\nunlink (const std::string&, std::string&);\n\nextern OCTAVE_API std::string\ntempnam (const std::string&, const std::string&);\n\nextern OCTAVE_API std::string\ntempnam (const std::string&, const std::string&, std::string&);\n\nextern OCTAVE_API std::string\ncanonicalize_file_name (const std::string&);\n\nextern OCTAVE_API std::string\ncanonicalize_file_name (const std::string&, std::string&);\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/file-stat.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ctime>\n#include <cerrno>\n#include <cstring>\n\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"stat-wrappers.h\"\n#include \"strmode-wrapper.h\"\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include \"oct-env.h\"\n#  include \"oct-regexp.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\n// FIXME: the is_* and mode_as_string functions are only valid\n// for initialized objects.  If called for an object that is not\n// initialized, they should throw an exception.\n\nbool\nbase_file_stat::is_blk () const\n{\n  return exists () && is_blk (m_mode);\n}\n\nbool\nbase_file_stat::is_chr () const\n{\n  return exists () && is_chr (m_mode);\n}\n\nbool\nbase_file_stat::is_dir () const\n{\n  return exists () && is_dir (m_mode);\n}\n\nbool\nbase_file_stat::is_fifo () const\n{\n  return exists () && is_fifo (m_mode);\n}\n\nbool\nbase_file_stat::is_lnk () const\n{\n  return exists () && is_lnk (m_mode);\n}\n\nbool\nbase_file_stat::is_reg () const\n{\n  return exists () && is_reg (m_mode);\n}\n\nbool\nbase_file_stat::is_sock () const\n{\n  return exists () && is_sock (m_mode);\n}\n\nbool\nbase_file_stat::is_blk (mode_t mode)\n{\n  return octave_is_blk_wrapper (mode);\n}\n\nbool\nbase_file_stat::is_chr (mode_t mode)\n{\n  return octave_is_chr_wrapper (mode);\n}\n\nbool\nbase_file_stat::is_dir (mode_t mode)\n{\n  return octave_is_dir_wrapper (mode);\n}\n\nbool\nbase_file_stat::is_fifo (mode_t mode)\n{\n  return octave_is_fifo_wrapper (mode);\n}\n\nbool\nbase_file_stat::is_lnk (mode_t mode)\n{\n  return octave_is_lnk_wrapper (mode);\n}\n\nbool\nbase_file_stat::is_reg (mode_t mode)\n{\n  return octave_is_reg_wrapper (mode);\n}\n\nbool\nbase_file_stat::is_sock (mode_t mode)\n{\n  return octave_is_sock_wrapper (mode);\n}\n\nbool\nbase_file_stat::have_struct_stat_st_rdev ()\n{\n  return ::octave_have_struct_stat_st_rdev ();\n}\n\nbool\nbase_file_stat::have_struct_stat_st_blksize ()\n{\n  return octave_have_struct_stat_st_blksize ();\n}\n\nbool\nbase_file_stat::have_struct_stat_st_blocks ()\n{\n  return octave_have_struct_stat_st_blocks ();\n}\n\nstd::string\nbase_file_stat::mode_as_string () const\n{\n  char buf[12];\n\n  octave_strmode_wrapper (m_mode, buf);\n\n  return std::string (buf);\n}\n\n// Has FILE been modified since TIME?  Returns 1 for yes, 0 for no,\n// and -1 for any error.\n\nint\nbase_file_stat::is_newer (const std::string& file,\n                          const sys::time& time)\n{\n  file_stat fs (file);\n\n  return fs ? fs.is_newer (time) : -1;\n}\n\n// Private stuff:\n\nfile_stat::file_stat (const std::string& n, bool fl)\n  : base_file_stat (), m_file_name (n), m_follow_links (fl)\n{\n  if (! m_file_name.empty ())\n    update_internal ();\n}\n\nfile_stat::~file_stat () { }\n\nvoid\nfile_stat::update_internal (bool force)\n{\n  if (! m_initialized || force)\n    {\n      m_initialized = false;\n      m_fail = false;\n\n      std::string full_file_name = sys::file_ops::tilde_expand (m_file_name);\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n      full_file_name = sys::env::make_absolute (full_file_name);\n\n      // Remove trailing slashes\n      while (full_file_name.length () > 1\n             && sys::file_ops::is_dir_sep (full_file_name.back ()))\n        full_file_name.pop_back ();\n\n      // If path is a root (like \"C:\" or \"\\\\SERVER\\share\"), add a\n      // trailing backslash.\n      // FIXME: This pattern does not match all possible UNC roots:\n      //        https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/62e862f4-2a51-452e-8eeb-dc4ff5ee33cc\n      static const regexp pat (R\"(^\\\\\\\\[\\w.-]+\\\\[\\w\\$-]+$)\");\n      if ((full_file_name.length () == 2 && full_file_name[1] == ':')\n          || (full_file_name.length () > 4  && full_file_name[0] == '\\\\'\n              && full_file_name[1] == '\\\\' && pat.is_match (full_file_name)))\n        full_file_name.push_back ('\\\\');\n#endif\n\n      const char *cname = full_file_name.c_str ();\n\n      time_t sys_atime, sys_mtime, sys_ctime;\n      long int atime_nsec, mtime_nsec, ctime_nsec;\n\n      int status\n        = (m_follow_links\n           ? octave_stat_wrapper (cname, &m_mode, &m_ino, &m_dev,\n                                  &m_nlink, &m_uid, &m_gid, &m_size,\n                                  &sys_atime, &atime_nsec, &sys_mtime,\n                                  &mtime_nsec, &sys_ctime, &ctime_nsec,\n                                  &m_rdev, &m_blksize, &m_blocks)\n           : octave_lstat_wrapper (cname, &m_mode, &m_ino, &m_dev,\n                                   &m_nlink, &m_uid, &m_gid, &m_size,\n                                   &sys_atime, &atime_nsec, &sys_mtime,\n                                   &mtime_nsec, &sys_ctime, &ctime_nsec,\n                                   &m_rdev, &m_blksize, &m_blocks));\n\n      if (status < 0)\n        {\n          m_fail = true;\n          m_errmsg = std::strerror (errno);\n        }\n      else\n        {\n          m_atime = sys::time (static_cast<OCTAVE_TIME_T> (sys_atime),\n                               atime_nsec/1000);\n          m_mtime = sys::time (static_cast<OCTAVE_TIME_T> (sys_mtime),\n                               mtime_nsec/1000);\n          m_ctime = sys::time (static_cast<OCTAVE_TIME_T> (sys_ctime),\n                               ctime_nsec/1000);\n        }\n\n      m_initialized = true;\n    }\n}\n\nvoid\nfile_fstat::update_internal (bool force)\n{\n  if (! m_initialized || force)\n    {\n      m_initialized = false;\n      m_fail = false;\n\n      time_t sys_atime, sys_mtime, sys_ctime;\n      long int atime_nsec, mtime_nsec, ctime_nsec;\n\n      int status\n        = octave_fstat_wrapper (m_fid, &m_mode, &m_ino, &m_dev,\n                                &m_nlink, &m_uid, &m_gid, &m_size,\n                                &sys_atime, &atime_nsec, &sys_mtime,\n                                &mtime_nsec, &sys_ctime, &ctime_nsec,\n                                &m_rdev, &m_blksize, &m_blocks);\n\n      if (status < 0)\n        {\n          m_fail = true;\n          m_errmsg = std::strerror (errno);\n        }\n      else\n        {\n          m_atime = sys::time (static_cast<OCTAVE_TIME_T> (sys_atime),\n                               atime_nsec/1000);\n          m_mtime = sys::time (static_cast<OCTAVE_TIME_T> (sys_mtime),\n                               mtime_nsec/1000);\n          m_ctime = sys::time (static_cast<OCTAVE_TIME_T> (sys_ctime),\n                               ctime_nsec/1000);\n        }\n\n      m_initialized = true;\n    }\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/file-stat.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_file_stat_h)\n#define octave_file_stat_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"oct-time.h\"\n\n#include <sys/types.h>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nclass OCTAVE_API base_file_stat\n{\npublic:\n\n  base_file_stat ()\n    : m_initialized (false), m_fail (false), m_errmsg (), m_mode (),\n      m_ino (), m_dev (), m_nlink (), m_uid (), m_gid (),\n      m_size (), m_atime (), m_mtime (), m_ctime (), m_rdev (),\n      m_blksize (), m_blocks () { }\n\n  base_file_stat (const base_file_stat& fs)\n    : m_initialized (fs.m_initialized), m_fail (fs.m_fail),\n      m_errmsg (fs.m_errmsg), m_mode (fs.m_mode), m_ino (fs.m_ino),\n      m_dev (fs.m_dev), m_nlink (fs.m_nlink), m_uid (fs.m_uid),\n      m_gid (fs.m_gid), m_size (fs.m_size), m_atime (fs.m_atime),\n      m_mtime (fs.m_mtime), m_ctime (fs.m_ctime), m_rdev (fs.m_rdev),\n      m_blksize (fs.m_blksize), m_blocks (fs.m_blocks) { }\n\n  base_file_stat& operator = (const base_file_stat& fs)\n  {\n    if (this != &fs)\n      {\n        m_initialized = fs.m_initialized;\n        m_fail = fs.m_fail;\n        m_errmsg = fs.m_errmsg;\n        m_mode = fs.m_mode;\n        m_ino = fs.m_ino;\n        m_dev = fs.m_dev;\n        m_nlink = fs.m_nlink;\n        m_uid = fs.m_uid;\n        m_gid = fs.m_gid;\n        m_size = fs.m_size;\n        m_atime = fs.m_atime;\n        m_mtime = fs.m_mtime;\n        m_ctime = fs.m_ctime;\n        m_rdev = fs.m_rdev;\n        m_blksize = fs.m_blksize;\n        m_blocks = fs.m_blocks;\n      }\n\n    return *this;\n  }\n\n  // The minimum difference in file time stamp values.\n  // FIXME: This value should come from the filesystem itself.\n  //        How can we get that info?\n  sys::time time_resolution () const\n  {\n    static sys::time resolution (1.0);\n    return resolution;\n  }\n\n  // File status and info.  The is_XXX functions will return false for\n  // file_stat objects that are not properly initialized.  The others\n  // should all return 0 (or the equivalent, for the given object)\n  // which is likely not meaningful.\n\n  bool is_blk () const;\n  bool is_chr () const;\n  bool is_dir () const;\n  bool is_fifo () const;\n  bool is_lnk () const;\n  bool is_reg () const;\n  bool is_sock () const;\n\n  static bool is_blk (mode_t mode);\n  static bool is_chr (mode_t mode);\n  static bool is_dir (mode_t mode);\n  static bool is_fifo (mode_t mode);\n  static bool is_lnk (mode_t mode);\n  static bool is_reg (mode_t mode);\n  static bool is_sock (mode_t mode);\n\n  static bool have_struct_stat_st_rdev ();\n  static bool have_struct_stat_st_blksize ();\n  static bool have_struct_stat_st_blocks ();\n\n  ino_t ino () const { return m_ino; }\n  dev_t dev () const { return m_dev; }\n\n  nlink_t nlink () const { return m_nlink; }\n\n  uid_t uid () const { return m_uid; }\n  gid_t gid () const { return m_gid; }\n\n  off_t size () const { return m_size; }\n\n  sys::time atime () const { return m_atime; }\n  sys::time mtime () const { return m_mtime; }\n  sys::time ctime () const { return m_ctime; }\n\n  dev_t rdev () const { return m_rdev; }\n\n  long blksize () const { return m_blksize; }\n  long blocks () const { return m_blocks; }\n\n  mode_t mode () const { return m_mode; }\n\n  std::string mode_as_string () const;\n\n  bool ok () const { return m_initialized && ! m_fail; }\n\n  operator bool () const { return ok (); }\n\n  bool exists () const { return ok (); }\n\n  std::string error () const { return ok () ? \"\" : m_errmsg; }\n\n  // Has the file referenced by this object been modified since TIME?\n  bool is_newer (const sys::time& time) const { return m_mtime > time; }\n\n  // It's nice to be able to hide the file_stat object if we don't\n  // really care about it.\n  static int is_newer (const std::string&, const sys::time&);\n\nprotected:\n\n  virtual ~base_file_stat () = default;\n\n  // TRUE means we have already called stat.\n  bool m_initialized;\n\n  // TRUE means the stat for this file failed.\n  bool m_fail;\n\n  // If a failure occurs, this contains the system error text.\n  std::string m_errmsg;\n\n  // file type and permissions\n  mode_t m_mode;\n\n  // serial number\n  ino_t m_ino;\n\n  // device number\n  dev_t m_dev;\n\n  // number of links\n  nlink_t m_nlink;\n\n  // user ID of owner\n  uid_t m_uid;\n\n  // group ID of owner\n  gid_t m_gid;\n\n  // size in bytes, for regular files\n  off_t m_size;\n\n  // time of last access\n  sys::time m_atime;\n\n  // time of last modification\n  sys::time m_mtime;\n\n  // time of last file status change\n  sys::time m_ctime;\n\n  // device number for special files\n  dev_t m_rdev;\n\n  // best I/O block size\n  long m_blksize;\n\n  // number of 512-byte blocks allocated\n  long m_blocks;\n};\n\nclass OCTAVE_API file_stat : public base_file_stat\n{\npublic:\n\n  // This constructor must remain defined in the cpp file rather than in\n  // the header file (bug #50234).\n  file_stat (const std::string& n = \"\", bool fl = true);\n\n  file_stat (const file_stat& fs)\n    : base_file_stat (fs), m_file_name (fs.m_file_name),\n      m_follow_links (fs.m_follow_links) { }\n\n  file_stat& operator = (const file_stat& fs)\n  {\n    if (this != &fs)\n      {\n        base_file_stat::operator = (fs);\n\n        m_file_name = fs.m_file_name;\n        m_follow_links = fs.m_follow_links;\n      }\n\n    return *this;\n  }\n\n  // This destructor must remain as an empty destructor defined in the\n  // cpp file rather than in the header file (bug #50234).\n  ~file_stat ();\n\n  void get_stats (bool force = false)\n  {\n    if (! m_initialized || force)\n      update_internal (force);\n  }\n\n  void get_stats (const std::string& n, bool force = false)\n  {\n    if (n != m_file_name || ! m_initialized || force)\n      {\n        m_initialized = false;\n\n        m_file_name = n;\n\n        update_internal (force);\n      }\n  }\n\nprivate:\n\n  // Name of the file.\n  std::string m_file_name;\n\n  // TRUE means follow symbolic links to the ultimate file (stat).\n  // FALSE means get information about the link itself (lstat).\n  bool m_follow_links;\n\n  void update_internal (bool force = false);\n};\n\nclass OCTAVE_API file_fstat : public base_file_stat\n{\npublic:\n\n  file_fstat () = delete;\n\n  file_fstat (int n) : base_file_stat (), m_fid (n)\n  {\n    update_internal ();\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (file_fstat)\n\n  void get_stats (bool force = false)\n  {\n    if (! m_initialized || force)\n      update_internal (force);\n  }\n\n  void get_stats (int n, bool force = false)\n  {\n    if (n != m_fid || ! m_initialized || force)\n      {\n        m_initialized = false;\n\n        m_fid = n;\n\n        update_internal (force);\n      }\n  }\n\nprivate:\n\n  // Open file descriptor.\n  int m_fid;\n\n  void update_internal (bool force = false);\n};\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/lo-sysdep.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_sysdep_h)\n#define octave_lo_sysdep_h 1\n\n#warning 'header file \"lo-sysdep.h\" is deprecated, use \"oct-sysdep.h\" instead'\n\n#include \"oct-sysdep.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/system/lo-sysinfo.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_sysinfo_h)\n#define octave_lo_sysinfo_h 1\n\n#warning 'header file \"lo-sysinfo.h\" is deprecated, use \"oct-sysinfo.h\" instead'\n\n#include \"oct-sysinfo.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/system/mach-info.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdint>\n\n#include \"f77-fcn.h\"\n#include \"mach-info.h\"\n#include \"oct-error.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(mach_info)\n\n// FIXME: Maybe this function should be declared in a header file?  Or\n// we should be obtaining values from C++ std::numeric_limits<double>?\n\nextern \"C\"\n{\n  extern double F77_FUNC (d1mach, D1MACH) (const F77_INT*);\n}\n\ntypedef union\n{\n  double d;\n  int32_t i[2];\n} equiv;\n\ntypedef struct\n{\n  int fp_fmt;\n  equiv fp_par[4];\n} float_params;\n\n#define INIT_FLT_PAR(fp, fmt, sm1, sm2, lrg1, lrg2, rt1, rt2, dv1, dv2) \\\n  do                                                                    \\\n    {                                                                   \\\n      fp.fp_fmt = (fmt);                                                \\\n      fp.fp_par[0].i[0] = (sm1);  fp.fp_par[0].i[1] = (sm2);            \\\n      fp.fp_par[1].i[0] = (lrg1); fp.fp_par[1].i[1] = (lrg2);           \\\n      fp.fp_par[2].i[0] = (rt1);  fp.fp_par[2].i[1] = (rt2);            \\\n      fp.fp_par[3].i[0] = (dv1);  fp.fp_par[3].i[1] = (dv2);            \\\n    }                                                                   \\\n  while (0)\n\nstatic int equiv_compare (const equiv *std, const equiv *v, int len)\n{\n  int i;\n  for (i = 0; i < len; i++)\n    if (v[i].i[0] != std[i].i[0] || v[i].i[1] != std[i].i[1])\n      return 0;\n  return 1;\n}\n\n// Determine whether floating point format appears to be IEEE little\n// endian (1), IEEE big endian (2) or unknown (0)\n// little endian, or 2 if it is IEEE big endian.\n\nstatic float_format get_float_format ()\n{\n  float_params fp[3];\n\n  INIT_FLT_PAR (fp[0], 1,\n                0,    1048576,\n                -1, 2146435071,\n                0, 1017118720,\n                0, 1018167296);\n\n  INIT_FLT_PAR (fp[1], 2,\n                1048576,  0,\n                2146435071, -1,\n                1017118720,  0,\n                1018167296,  0);\n\n  INIT_FLT_PAR (fp[2], 0,\n                0, 0,\n                0, 0,\n                0, 0,\n                0, 0);\n\n  equiv mach_fp_par[4];\n\n  F77_INT opt;\n\n  opt = 1;\n  mach_fp_par[0].d = F77_FUNC (d1mach, D1MACH) (&opt);\n\n  opt = 2;\n  mach_fp_par[1].d = F77_FUNC (d1mach, D1MACH) (&opt);\n\n  opt = 3;\n  mach_fp_par[2].d = F77_FUNC (d1mach, D1MACH) (&opt);\n\n  opt = 4;\n  mach_fp_par[3].d = F77_FUNC (d1mach, D1MACH) (&opt);\n\n  int float_params_id = 0;\n  int i = 0;\n  do\n    {\n      if (equiv_compare (fp[i].fp_par, mach_fp_par, 4))\n        {\n          float_params_id = fp[i].fp_fmt;\n          break;\n        }\n    }\n  while (fp[++i].fp_fmt != 0);\n\n  switch (float_params_id)\n    {\n    case 1:\n      return flt_fmt_ieee_little_endian;\n\n    case 2:\n      return flt_fmt_ieee_big_endian;\n\n    default:\n      return flt_fmt_unknown;\n    }\n}\n\nstatic int is_big_endian ()\n{\n  // Are we little or big endian?  From Harbison & Steele.\n\n  union\n  {\n    long l;\n    char c[sizeof (long)];\n  } u;\n\n  u.l = 1;\n\n  return (u.c[sizeof (long) - 1] == 1);\n}\n\nfloat_format\nnative_float_format ()\n{\n  static float_format fmt = get_float_format ();\n\n  return fmt;\n}\n\nbool\nwords_big_endian ()\n{\n  static bool big_endian = is_big_endian ();\n\n  return big_endian;\n}\n\nbool\nwords_little_endian ()\n{\n  static bool little_endian = ! is_big_endian ();\n\n  return little_endian;\n}\n\nbool\nnan_with_payload ()\n{\n#if defined (HAVE_QNAN_WITH_PAYLOAD)\n  return 1;\n#else\n  return 0;\n#endif\n}\n\nfloat_format\nstring_to_float_format (const std::string& s)\n{\n  float_format retval = flt_fmt_unknown;\n\n  if (s == \"native\" || s == \"n\")\n    retval = native_float_format ();\n  else if (s == \"ieee-be\" || s == \"b\")\n    retval = flt_fmt_ieee_big_endian;\n  else if (s == \"ieee-le\" || s == \"l\")\n    retval = flt_fmt_ieee_little_endian;\n  else if (s == \"unknown\")\n    retval = flt_fmt_unknown;\n  else\n    (*current_liboctave_error_handler)\n      (\"invalid architecture type specified\");\n\n  return retval;\n}\n\nstd::string\nfloat_format_as_string (float_format flt_fmt)\n{\n  std::string retval = \"unknown\";\n\n  switch (flt_fmt)\n    {\n    case flt_fmt_ieee_big_endian:\n      retval = \"ieee-be\";\n      break;\n\n    case flt_fmt_ieee_little_endian:\n      retval = \"ieee-le\";\n      break;\n\n    default:\n      break;\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(mach_info)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/mach-info.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mach_info_h)\n#define octave_mach_info_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(mach_info)\n\nenum float_format\n{\n  // If these values change, you must also change the values\n  // returned by octave_get_float_format.\n\n  flt_fmt_unknown = 0,\n  flt_fmt_ieee_little_endian = 1,\n  flt_fmt_ieee_big_endian = 2,\n};\n\nOCTAVE_API float_format native_float_format ();\n\nOCTAVE_API bool words_big_endian ();\n\nOCTAVE_API bool words_little_endian ();\n\nOCTAVE_API bool nan_with_payload ();\n\nOCTAVE_API float_format string_to_float_format (const std::string&);\n\nOCTAVE_API std::string float_format_as_string (float_format);\n\nOCTAVE_END_NAMESPACE(mach_info)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/module.mk",
    "content": "SYSTEM_INC = \\\n  %reldir%/child-list.h \\\n  %reldir%/dir-ops.h \\\n  %reldir%/file-ops.h \\\n  %reldir%/file-stat.h \\\n  %reldir%/lo-sysdep.h \\\n  %reldir%/lo-sysinfo.h \\\n  %reldir%/mach-info.h \\\n  %reldir%/oct-env.h \\\n  %reldir%/oct-group.h \\\n  %reldir%/oct-password.h \\\n  %reldir%/oct-syscalls.h \\\n  %reldir%/oct-sysdep.h \\\n  %reldir%/oct-sysinfo.h \\\n  %reldir%/oct-time.h \\\n  %reldir%/oct-uname.h\n\nSYSTEM_SRC = \\\n  %reldir%/child-list.cc \\\n  %reldir%/dir-ops.cc \\\n  %reldir%/file-ops.cc \\\n  %reldir%/file-stat.cc \\\n  %reldir%/mach-info.cc \\\n  %reldir%/oct-env.cc \\\n  %reldir%/oct-group.cc \\\n  %reldir%/oct-password.cc \\\n  %reldir%/oct-syscalls.cc \\\n  %reldir%/oct-sysdep.cc \\\n  %reldir%/oct-sysinfo.cc \\\n  %reldir%/oct-time.cc \\\n  %reldir%/oct-uname.cc\n\nnoinst_HEADERS += \\\n  %reldir%/cmach-info.h\n\nnoinst_LTLIBRARIES += %reldir%/libsystem.la\n\n%canon_reldir%_libsystem_la_SOURCES = $(SYSTEM_SRC)\n\n%canon_reldir%_libsystem_la_CPPFLAGS = $(liboctave_liboctave_la_CPPFLAGS)\n\nliboctave_liboctave_la_LIBADD += %reldir%/libsystem.la\n"
  },
  {
    "path": "liboctave/system/oct-env.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nThe functions listed below were adapted from a similar functions\nfrom GNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991\nFree Software Foundation, Inc.\n\n  octave::sys::env::do_absolute_pathname\n  octave::sys::env::do_base_pathname\n  octave::sys::env::do_chdir\n  octave::sys::env::do_getcwd\n  octave::sys::env::do_make_absolute\n  octave::sys::env::do_polite_directory_format\n  octave::sys::env::pathname_backup\n\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n#include <cstring>\n\n#include <string>\n\n#include \"file-ops.h\"\n#include \"lo-utils.h\"\n#include \"oct-env.h\"\n#include \"oct-error.h\"\n#include \"oct-password.h\"\n#include \"oct-syscalls.h\"\n#include \"oct-sysdep.h\"\n#include \"set-program-name-wrapper.h\"\n#include \"singleton-cleanup.h\"\n#include \"unistd-wrappers.h\"\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <windows.h>\n#  include <shlobj.h>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nenv::env ()\n  : m_follow_symbolic_links (true), m_verbatim_pwd (true),\n    m_current_directory (), m_prog_name (), m_prog_invocation_name (),\n    m_user_name (), m_host_name ()\n{\n  // Get a real value for the current directory.\n  do_getcwd ();\n\n  // Etc.\n  do_get_user_name ();\n\n  do_get_host_name ();\n}\n\nenv *env::s_instance = nullptr;\n\nbool\nenv::instance_ok ()\n{\n  bool retval = true;\n\n  if (! s_instance)\n    {\n      s_instance = new env ();\n      singleton_cleanup_list::add (cleanup_instance);\n    }\n\n  return retval;\n}\n\nstd::string\nenv::polite_directory_format (const std::string& name)\n{\n  return (instance_ok ())\n         ? s_instance->do_polite_directory_format (name) : \"\";\n}\n\nbool\nenv::absolute_pathname (const std::string& s)\n{\n  return (instance_ok ())\n         ? s_instance->do_absolute_pathname (s) : false;\n}\n\nbool\nenv::rooted_relative_pathname (const std::string& s)\n{\n  return (instance_ok ())\n         ? s_instance->do_rooted_relative_pathname (s) : false;\n}\n\nstd::string\nenv::base_pathname (const std::string& s)\n{\n  return (instance_ok ())\n         ? s_instance->do_base_pathname (s) : \"\";\n}\n\nstd::string\nenv::make_absolute (const std::string& s, const std::string& dot_path)\n{\n  return (instance_ok ())\n         ? s_instance->do_make_absolute (s, dot_path) : \"\";\n}\n\nstd::string\nenv::get_current_directory ()\n{\n  return (instance_ok ())\n         ? s_instance->do_getcwd () : \"\";\n}\n\nstd::string\nenv::get_home_directory ()\n{\n  return (instance_ok ())\n         ? s_instance->do_get_home_directory () : \"\";\n}\n\nstd::string\nenv::get_temp_directory ()\n{\n  return (instance_ok ())\n         ? s_instance->do_get_temp_directory () : \"\";\n}\n\nstd::string\nenv::get_user_config_directory ()\n{\n  return (instance_ok ())\n         ? s_instance->do_get_user_config_directory () : \"\";\n}\n\nstd::string\nenv::get_user_data_directory ()\n{\n  return (instance_ok ())\n         ? s_instance->do_get_user_data_directory () : \"\";\n}\n\nstd::string\nenv::get_program_name ()\n{\n  return (instance_ok ())\n         ? s_instance->m_prog_name : \"\";\n}\n\nstd::string\nenv::get_program_invocation_name ()\n{\n  return (instance_ok ())\n         ? s_instance->m_prog_invocation_name : \"\";\n}\n\nvoid\nenv::set_program_name (const std::string& s)\n{\n  if (instance_ok ())\n    s_instance->do_set_program_name (s);\n}\n\nstd::string\nenv::get_user_name ()\n{\n  return (instance_ok ())\n         ? s_instance->do_get_user_name () : \"\";\n}\n\nstd::string\nenv::get_host_name ()\n{\n  return (instance_ok ())\n         ? s_instance->do_get_host_name () : \"\";\n}\n\nstd::string\nenv::do_get_temp_directory () const\n{\n  std::string tempd = do_getenv (\"TMPDIR\");\n\n#if defined (__MINGW32__) || defined (_MSC_VER)\n\n  if (tempd.empty ())\n    tempd = do_getenv (\"TEMP\");\n\n  if (tempd.empty ())\n    tempd = do_getenv (\"TMP\");\n\n#if defined (P_tmpdir)\n  if (tempd.empty ())\n    tempd = P_tmpdir;\n#endif\n\n  // Some versions of MinGW and MSVC either don't define P_tmpdir, or\n  // define it to a single backslash.  In such cases just use C:\\temp.\n  if (tempd.empty () || tempd == R\"(\\)\")\n    tempd = R\"(c:\\temp)\";\n\n#else\n\n  if (tempd.empty ())\n    tempd = do_getenv (\"TMP\");\n\n#if defined (P_tmpdir)\n  if (tempd.empty ())\n    tempd = P_tmpdir;\n#else\n  if (tempd.empty ())\n    tempd = \"/tmp\";\n#endif\n\n#endif\n\n  return tempd;\n}\n\nstd::string\nenv::do_get_user_config_directory ()\n{\n  std::string cfg_dir;\n\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && defined (OCTAVE_USE_WINDOWS_API)\n  wchar_t path[MAX_PATH+1];\n  if (SHGetFolderPathW (nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY,\n                        nullptr, SHGFP_TYPE_CURRENT, path) == S_OK)\n    cfg_dir = u8_from_wstring (path);\n#else\n  cfg_dir = do_getenv (\"XDG_CONFIG_HOME\");\n#endif\n\n  if (cfg_dir.empty ())\n    cfg_dir = do_get_home_directory () + sys::file_ops::dir_sep_str ()\n              + \".config\";\n\n  return cfg_dir;\n}\n\nstd::string\nenv::do_get_user_data_directory ()\n{\n  std::string data_dir;\n\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && defined (OCTAVE_USE_WINDOWS_API)\n  wchar_t path[MAX_PATH+1];\n  if (SHGetFolderPathW (nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY,\n                        nullptr, SHGFP_TYPE_CURRENT, path) == S_OK)\n    data_dir = u8_from_wstring (path);\n#else\n  data_dir = do_getenv (\"XDG_DATA_HOME\");\n#endif\n\n  if (data_dir.empty ())\n    data_dir = do_get_home_directory () + sys::file_ops::dir_sep_str ()\n               + \".local\" + sys::file_ops::dir_sep_str () + \"share\";\n\n  return data_dir;\n}\n\n\n// FIXME: this leaves no way to distinguish between a\n// variable that is not set and one that is set to the empty string.\n// Is this a problem?\n\nstd::string\nenv::getenv (const std::string& name)\n{\n  return (instance_ok ())\n         ? s_instance->do_getenv (name) : \"\";\n}\n\nbool\nenv::isenv (const std::string& name)\n{\n  return isenv_wrapper (name);\n}\n\nvoid\nenv::putenv (const std::string& name, const std::string& value)\n{\n  putenv_wrapper (name, value);\n}\n\nbool\nenv::have_x11_display ()\n{\n  std::string display = getenv (\"DISPLAY\");\n\n  return ! display.empty ();\n}\n\nbool\nenv::chdir (const std::string& newdir)\n{\n  return (instance_ok ())\n         ? s_instance->do_chdir (newdir) : false;\n}\n\nvoid\nenv::do_set_program_name (const std::string& s)\n{\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n      // octave_set_program_name_wrapper returns a cleaned up\n      // version of the program name (stripping libtool's \"lt-\"\n      // prefix, for example).\n\n      // The string passed to gnulib's ::set_program_name function must\n      // exist for the duration of the program so allocate a copy here\n      // instead of passing S.c_str () which only exists as long as the\n      // string object S.\n\n      m_prog_invocation_name\n        = octave_set_program_name_wrapper (strsave (s.c_str ()));\n\n      std::size_t pos\n        = m_prog_invocation_name.find_last_of (sys::file_ops::dir_sep_chars ());\n\n      // Also keep a shortened version of the program name.\n      m_prog_name = (pos == std::string::npos\n                     ? m_prog_invocation_name\n                     : m_prog_invocation_name.substr (pos+1));\n\n      initialized = true;\n    }\n}\n\n// Return a pretty pathname.  If the first part of the pathname is the\n// same as $HOME, then replace that with '~'.\n\nstd::string\nenv::do_polite_directory_format (const std::string& name)\n{\n  std::string retval;\n\n  std::string home_dir = do_get_home_directory ();\n\n  std::size_t len = home_dir.length ();\n\n  if (len > 1 && home_dir == name.substr (0, len)\n      && (name.length () == len || sys::file_ops::is_dir_sep (name[len])))\n    {\n      retval = \"~\";\n      retval.append (name.substr (len));\n    }\n  else\n    retval = name;\n\n  return retval;\n}\n\nbool\nenv::do_absolute_pathname (const std::string& s) const\n{\n  std::size_t len = s.length ();\n\n  if (len == 0)\n    return false;\n\n  if (sys::file_ops::is_dir_sep (s[0]))\n    return true;\n\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)\n  if ((len == 2 && isalpha (s[0]) && s[1] == ':')\n      || (len > 2 && isalpha (s[0]) && s[1] == ':'\n          && sys::file_ops::is_dir_sep (s[2])))\n    return true;\n#endif\n\n  return false;\n}\n\nbool\nenv::do_rooted_relative_pathname (const std::string& s) const\n{\n  std::size_t len = s.length ();\n\n  if (len == 0)\n    return false;\n\n  if (len == 1 && s[0] == '.')\n    return true;\n\n  if (len > 1 && s[0] == '.' && sys::file_ops::is_dir_sep (s[1]))\n    return true;\n\n  if (len == 2 && s[0] == '.' && s[1] == '.')\n    return true;\n\n  if (len > 2 && s[0] == '.' && s[1] == '.'\n      && sys::file_ops::is_dir_sep (s[2]))\n    return true;\n\n  return false;\n}\n\n// Return the 'basename' of the pathname in STRING (the stuff after\n// the last directory separator).  If STRING is not a full pathname,\n// simply return it.\n\nstd::string\nenv::do_base_pathname (const std::string& s) const\n{\n  if (! (do_absolute_pathname (s) || do_rooted_relative_pathname (s)))\n    return s;\n\n  std::size_t pos = s.find_last_of (sys::file_ops::dir_sep_chars ());\n\n  if (pos == std::string::npos)\n    return s;\n  else\n    return s.substr (pos+1);\n}\n\n// Turn STRING (a pathname) into an absolute pathname, assuming that\n// DOT_PATH contains the symbolic location of the current directory.\n\nstd::string\nenv::do_make_absolute (const std::string& s,\n                       const std::string& dot_path) const\n{\n  if (dot_path.empty () || s.empty () || do_absolute_pathname (s))\n    return s;\n\n  // Optimization: every time Octave returns to the prompt it calls\n  // make_absolute_filename with '.' as argument.\n  if (s == \".\")\n    return dot_path;\n\n  std::string current_dir = dot_path;\n\n  if (! sys::file_ops::is_dir_sep (current_dir.back ()))\n    current_dir.append (sys::file_ops::dir_sep_str ());\n\n  std::size_t i = 0;\n  std::size_t slen = s.length ();\n\n  while (i < slen)\n    {\n      if (s[i] == '.')\n        {\n          if (i + 1 == slen)\n            break;\n\n          if (sys::file_ops::is_dir_sep (s[i+1]))\n            {\n              i += 2;\n              continue;\n            }\n\n          if (s[i+1] == '.'\n              && (i + 2 == slen\n                  || sys::file_ops::is_dir_sep (s[i+2])))\n            {\n              i += 2;\n              if (i != slen)\n                i++;\n\n              pathname_backup (current_dir, 1);\n\n              continue;\n            }\n        }\n\n      std::size_t sep_pos;\n      sep_pos = s.find_first_of (sys::file_ops::dir_sep_chars (), i);\n\n      if (sep_pos == std::string::npos)\n        {\n          current_dir.append (s, i, sep_pos-i);\n          break;\n        }\n      else if (sep_pos == i)\n        {\n          /* Two separators in a row, skip adding 2nd separator */\n          i++;\n        }\n      else\n        {\n          current_dir.append (s, i, sep_pos-i+1);\n          i = sep_pos + 1;\n        }\n    }\n\n  // Strip any trailing directory separator\n  if (sys::file_ops::is_dir_sep (current_dir.back ()))\n    current_dir.pop_back ();\n\n  return current_dir;\n}\n\n// Return a string which is the current working directory.\n\nstd::string\nenv::do_getcwd ()\n{\n  if (! m_follow_symbolic_links)\n    m_current_directory = \"\";\n\n  if (m_verbatim_pwd || m_current_directory.empty ())\n    m_current_directory = sys::getcwd ();\n\n  return m_current_directory;\n}\n\n// This value is not cached because it can change while Octave is\n// running.\n\nstd::string\nenv::do_get_home_directory ()\n{\n  std::string hd = do_getenv (\"HOME\");\n\n#if defined (__MINGW32__) || defined (_MSC_VER)\n  // Maybe we are started directly from cmd.exe.\n  if (hd.empty ())\n    {\n      std::string drv = do_getenv (\"HOMEDRIVE\");\n      if (drv.empty ())\n        hd = do_getenv (\"HOMEPATH\");\n      else\n        hd = drv + do_getenv (\"HOMEPATH\");\n    }\n#endif\n\n  if (hd.empty ())\n    {\n      sys::password pw = sys::password::getpwuid (sys::getuid ());\n\n      hd = (pw ? pw.dir () : std::string (sys::file_ops::dir_sep_str ()));\n    }\n\n  return hd;\n}\n\nstd::string\nenv::do_get_user_name ()\n{\n  if (m_user_name.empty ())\n    {\n      sys::password pw = sys::password::getpwuid (sys::getuid ());\n\n      m_user_name = (pw ? pw.name () : \"unknown\");\n    }\n\n  return m_user_name;\n}\n\nstd::string\nenv::do_get_host_name ()\n{\n  if (m_host_name.empty ())\n    {\n      char hostname[1024];\n\n      int status = octave_gethostname_wrapper (hostname, 1023);\n\n      m_host_name = (status < 0) ? \"unknown\" : hostname;\n    }\n\n  return m_host_name;\n}\n\nstd::string\nenv::do_getenv (const std::string& name) const\n{\n  return getenv_wrapper (name);\n}\n\n// Do the work of changing to the directory NEWDIR.\n// Handle symbolic link following, etc.\n\nbool\nenv::do_chdir (const std::string& newdir)\n{\n  bool retval = false;\n\n  std::string tmp;\n\n  if (m_follow_symbolic_links)\n    {\n      if (m_current_directory.empty ())\n        do_getcwd ();\n\n      if (m_current_directory.empty ())\n        tmp = newdir;\n      else\n        tmp = do_make_absolute (newdir, m_current_directory);\n\n      // Get rid of trailing directory separator.\n      if (tmp.length () > 1 && sys::file_ops::is_dir_sep (tmp.back ()))\n        tmp.pop_back ();\n\n      if (! sys::chdir (tmp))\n        {\n          m_current_directory = tmp;\n          retval = true;\n        }\n    }\n  else\n    retval = (! sys::chdir (newdir));\n\n  return retval;\n}\n\n// Remove the last N directories from PATH.\n\nvoid\nenv::pathname_backup (std::string& path, int n) const\n{\n  if (path.empty ())\n    return;\n\n  std::size_t i = path.length () - 1;\n\n  while (n--)\n    {\n      while (sys::file_ops::is_dir_sep (path[i]) && i > 0)\n        i--;\n\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)\n      // Don't strip file letter part.\n      if (i == 1 && path[i] == ':')\n        {\n          // Keep path separator if present.\n          i = std::min (i+2, path.length ());\n          break;\n        }\n#endif\n\n      while (! sys::file_ops::is_dir_sep (path[i]) && i > 0)\n        i--;\n\n      i++;\n    }\n\n  path.resize (i);\n}\n\nvoid\nenv::error (int err_num) const\n{\n  (*current_liboctave_error_handler) (\"%s\", std::strerror (err_num));\n}\n\nvoid\nenv::error (const std::string& s) const\n{\n  (*current_liboctave_error_handler) (\"%s\", s.c_str ());\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/oct-env.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_env_h)\n#define octave_oct_env_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nclass OCTAVE_API env\n{\nprotected:\n\n  env ();\n\npublic:\n\n  OCTAVE_DISABLE_COPY_MOVE (env)\n\n  ~env () = default;\n\n  static std::string polite_directory_format (const std::string& name);\n\n  static bool absolute_pathname (const std::string& s);\n\n  static bool rooted_relative_pathname (const std::string& s);\n\n  static std::string base_pathname (const std::string& s);\n\n  static std::string\n  make_absolute (const std::string& s,\n                 const std::string& dot_path = get_current_directory ());\n\n  static std::string get_current_directory ();\n\n  static std::string get_home_directory ();\n\n  static std::string get_temp_directory ();\n\n  static std::string get_user_config_directory ();\n\n  static std::string get_user_data_directory ();\n\n  static std::string get_program_name ();\n\n  static std::string get_program_invocation_name ();\n\n  static std::string get_user_name ();\n\n  static std::string get_host_name ();\n\n  static std::string getenv (const std::string& name);\n\n  static bool isenv (const std::string& name);\n\n  static void putenv (const std::string& name, const std::string& value);\n\n  static bool have_x11_display ();\n\n  static bool chdir (const std::string& newdir);\n\n  static void set_program_name (const std::string& s);\n\nprivate:\n\n  static bool instance_ok ();\n\n  std::string do_polite_directory_format (const std::string& name);\n\n  bool do_absolute_pathname (const std::string& s) const;\n\n  bool do_rooted_relative_pathname (const std::string& s) const;\n\n  std::string do_base_pathname (const std::string& s) const;\n\n  std::string do_make_absolute (const std::string& s,\n                                const std::string& dot_path) const;\n\n  std::string do_getcwd ();\n\n  std::string do_get_home_directory ();\n\n  std::string do_get_temp_directory () const;\n\n  std::string do_get_user_config_directory ();\n\n  std::string do_get_user_data_directory ();\n\n  std::string do_get_user_name ();\n\n  std::string do_get_host_name ();\n\n  std::string do_getenv (const std::string& name) const;\n\n  void do_putenv (const std::string& name, const std::string& value) const;\n\n  bool do_chdir (const std::string& newdir);\n\n  void do_set_program_name (const std::string& s);\n\n  void pathname_backup (std::string& path, int n) const;\n\n  void error (int) const;\n\n  void error (const std::string&) const;\n\n  // The real thing.\n  static env *s_instance;\n\n  static void cleanup_instance ()\n  { delete s_instance; s_instance = nullptr; }\n\n  // TRUE means follow symbolic links that point to directories just\n  // as if they are real directories.\n  bool m_follow_symbolic_links;\n\n  // TRUE means that pwd always give verbatim directory, regardless\n  // of symbolic link following.\n  bool m_verbatim_pwd;\n\n  // Where are we?\n  std::string m_current_directory;\n\n  // Etc.\n  std::string m_prog_name;\n\n  std::string m_prog_invocation_name;\n\n  std::string m_user_name;\n\n  std::string m_host_name;\n};\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/oct-group.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sys/types.h>\n\n#if defined (HAVE_GRP_H)\n#  include <grp.h>\n#endif\n\n#include \"oct-error.h\"\n#include \"oct-group.h\"\n#include \"str-vec.h\"\n\n#define NOT_SUPPORTED(nm)                       \\\n  nm \": not supported on this system\"\n\nOCTAVE_NORETURN static\nvoid\nerr_invalid ()\n{\n  (*current_liboctave_error_handler) (\"invalid group object\");\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nstd::string\ngroup::name () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_name;\n}\n\nstd::string\ngroup::passwd () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_passwd;\n}\n\ngid_t\ngroup::gid () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_gid;\n}\n\nstring_vector\ngroup::mem () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_mem;\n}\n\ngroup\ngroup::getgrent ()\n{\n  std::string msg;\n  return getgrent (msg);\n}\n\ngroup\ngroup::getgrent (std::string& msg)\n{\n#if defined (HAVE_GETGRENT)\n  msg = \"\";\n  return group (::getgrent (), msg);\n#else\n  msg = NOT_SUPPORTED (\"getgrent\");\n  return group ();\n#endif\n}\n\ngroup\ngroup::getgrgid (gid_t gid)\n{\n  std::string msg;\n  return getgrgid (gid, msg);\n}\n\ngroup\ngroup::getgrgid (gid_t gid, std::string& msg)\n{\n#if defined (HAVE_GETGRGID)\n  msg = \"\";\n  return group (::getgrgid (gid), msg);\n#else\n  octave_unused_parameter (gid);\n\n  msg = NOT_SUPPORTED (\"getgruid\");\n  return group ();\n#endif\n}\n\ngroup\ngroup::getgrnam (const std::string& nm)\n{\n  std::string msg;\n  return getgrnam (nm, msg);\n}\n\ngroup\ngroup::getgrnam (const std::string& nm, std::string& msg)\n{\n#if defined (HAVE_GETGRNAM)\n  msg = \"\";\n  return group (::getgrnam (nm.c_str ()), msg);\n#else\n  octave_unused_parameter (nm);\n\n  msg = NOT_SUPPORTED (\"getgrnam\");\n  return group ();\n#endif\n}\n\nint\ngroup::setgrent ()\n{\n  std::string msg;\n  return setgrent (msg);\n}\n\nint\ngroup::setgrent (std::string& msg)\n{\n#if defined (HAVE_SETGRENT)\n  msg = \"\";\n  ::setgrent ();\n  return 0;\n#else\n  msg = NOT_SUPPORTED (\"setgrent\");\n  return -1;\n#endif\n}\n\nint\ngroup::endgrent ()\n{\n  std::string msg;\n  return endgrent (msg);\n}\n\nint\ngroup::endgrent (std::string& msg)\n{\n#if defined (HAVE_ENDGRENT)\n  msg = \"\";\n  ::endgrent ();\n  return 0;\n#else\n  msg = NOT_SUPPORTED (\"endgrent\");\n  return -1;\n#endif\n}\n\ngroup::group (void *p, std::string& msg)\n  : m_name (), m_passwd (), m_gid (0), m_mem (), m_valid (false)\n{\n#if defined (HAVE_GRP_H)\n  msg = \"\";\n\n  if (p)\n    {\n      struct ::group *gr = static_cast<struct ::group *> (p);\n\n      m_name = gr->gr_name;\n\n#if defined (HAVE_GR_PASSWD)\n      m_passwd = gr->gr_passwd;\n#endif\n\n      m_gid = gr->gr_gid;\n\n      m_mem = string_vector (gr->gr_mem);\n\n      m_valid = true;\n    }\n#else\n  octave_unused_parameter (p);\n\n  msg = NOT_SUPPORTED (\"group functions\");\n#endif\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/oct-group.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_group_h)\n#define octave_oct_group_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include <sys/types.h>\n\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nclass OCTAVE_API group\n{\npublic:\n\n  group ()\n    : m_name (), m_passwd (), m_gid (0), m_mem (), m_valid (false)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (group)\n\n  std::string name () const;\n\n  std::string passwd () const;\n\n  gid_t gid () const;\n\n  string_vector mem () const;\n\n  bool ok () const { return m_valid; }\n\n  operator bool () const { return ok (); }\n\n  static group getgrent ();\n  static group getgrent (std::string& msg);\n\n  static group getgrgid (gid_t gid);\n  static group getgrgid (gid_t gid, std::string& msg);\n\n  static group getgrnam (const std::string& nm);\n  static group getgrnam (const std::string& nm, std::string& msg);\n\n  static int setgrent ();\n  static int setgrent (std::string& msg);\n\n  static int endgrent ();\n  static int endgrent (std::string& msg);\n\nprivate:\n\n  // The group name.\n  std::string m_name;\n\n  // The group password.\n  std::string m_passwd;\n\n  // The numeric group id.\n  gid_t m_gid;\n\n  // The members of the group;\n  string_vector m_mem;\n\n  // Flag that says whether we have been properly initialized.\n  bool m_valid;\n\n  // This is how we will create an group object from a pointer\n  // to a struct group.\n  group (void *p, std::string& msg);\n};\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/oct-password.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sys/types.h>\n\n#include \"oct-error.h\"\n#include \"oct-password.h\"\n#include \"pwd-wrappers.h\"\n\n#define NOT_SUPPORTED(nm)                       \\\n  nm \": not supported on this system\"\n\nOCTAVE_NORETURN static\nvoid\nerr_invalid ()\n{\n  (*current_liboctave_error_handler) (\"invalid password object\");\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nstd::string\npassword::name () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_name;\n}\n\nstd::string\npassword::passwd () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_passwd;\n}\n\nuid_t\npassword::uid () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_uid;\n}\n\ngid_t\npassword::gid () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_gid;\n}\n\nstd::string\npassword::gecos () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_gecos;\n}\n\nstd::string\npassword::dir () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_dir;\n}\n\nstd::string\npassword::shell () const\n{\n  if (! ok ())\n    err_invalid ();\n\n  return m_shell;\n}\n\npassword\npassword::getpwent ()\n{\n  std::string msg;\n  return getpwent (msg);\n}\n\npassword\npassword::getpwent (std::string& msg)\n{\n#if defined (HAVE_GETPWENT)\n  msg = \"\";\n  return password (octave_getpwent_wrapper (), msg);\n#else\n  msg = NOT_SUPPORTED (\"getpwent\");\n  return password ();\n#endif\n}\n\npassword\npassword::getpwuid (uid_t uid)\n{\n  std::string msg;\n  return getpwuid (uid, msg);\n}\n\npassword\npassword::getpwuid (uid_t uid, std::string& msg)\n{\n#if defined (HAVE_GETPWUID)\n  msg = \"\";\n  return password (octave_getpwuid_wrapper (uid), msg);\n#else\n  octave_unused_parameter (uid);\n\n  msg = NOT_SUPPORTED (\"getpwuid\");\n  return password ();\n#endif\n}\n\npassword\npassword::getpwnam (const std::string& nm)\n{\n  std::string msg;\n  return getpwnam (nm, msg);\n}\n\npassword\npassword::getpwnam (const std::string& nm, std::string& msg)\n{\n#if defined (HAVE_GETPWNAM)\n  msg = \"\";\n  return password (octave_getpwnam_wrapper (nm.c_str ()), msg);\n#else\n  octave_unused_parameter (nm);\n\n  msg = NOT_SUPPORTED (\"getpwnam\");\n  return password ();\n#endif\n}\n\nint\npassword::setpwent ()\n{\n  std::string msg;\n  return setpwent (msg);\n}\n\nint\npassword::setpwent (std::string& msg)\n{\n#if defined (HAVE_SETPWENT)\n  msg = \"\";\n  octave_setpwent_wrapper ();\n  return 0;\n#else\n  msg = NOT_SUPPORTED (\"setpwent\");\n  return -1;\n#endif\n}\n\nint\npassword::endpwent ()\n{\n  std::string msg;\n  return endpwent (msg);\n}\n\nint\npassword::endpwent (std::string& msg)\n{\n#if defined (HAVE_ENDPWENT)\n  msg = \"\";\n  octave_endpwent_wrapper ();\n  return 0;\n#else\n  msg = NOT_SUPPORTED (\"endpwent\");\n  return -1;\n#endif\n}\n\npassword::password (void *p, std::string& msg)\n  : m_name (), m_passwd (), m_uid (0), m_gid (0), m_gecos (),\n    m_dir (), m_shell (), m_valid (false)\n{\n#if defined (HAVE_PWD_H)\n  msg = \"\";\n\n  if (p)\n    {\n      struct octave_passwd_wrapper pw;\n      octave_from_passwd (static_cast<struct ::passwd *> (p), &pw);\n\n      m_name = pw.pw_name;\n      m_passwd = pw.pw_passwd;\n      m_uid = pw.pw_uid;\n      m_gid = pw.pw_gid;\n      m_gecos = pw.pw_gecos;\n      m_dir = pw.pw_dir;\n      m_shell = pw.pw_shell;\n\n      m_valid = true;\n    }\n#else\n  octave_unused_parameter (p);\n\n  msg = NOT_SUPPORTED (\"password functions\");\n#endif\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/oct-password.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_passwd_h)\n#define octave_oct_passwd_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include <sys/types.h>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nclass OCTAVE_API password\n{\npublic:\n\n  password ()\n    : m_name (), m_passwd (), m_uid (0), m_gid (0), m_gecos (),\n      m_dir (), m_shell (), m_valid (false)\n  { }\n\n  password (const password& pw)\n    : m_name (pw.m_name), m_passwd (pw.m_passwd),\n      m_uid (pw.m_uid), m_gid (pw.m_gid), m_gecos (pw.m_gecos),\n      m_dir (pw.m_dir), m_shell (pw.m_shell), m_valid (pw.m_valid)\n  { }\n\n  password& operator = (const password& pw)\n  {\n    if (this != &pw)\n      {\n        m_name = pw.m_name;\n        m_passwd = pw.m_passwd;\n        m_uid = pw.m_uid;\n        m_gid = pw.m_gid;\n        m_gecos = pw.m_gecos;\n        m_dir = pw.m_dir;\n        m_shell = pw.m_shell;\n        m_valid = pw.m_valid;\n      }\n\n    return *this;\n  }\n\n  ~password () = default;\n\n  std::string name () const;\n\n  std::string passwd () const;\n\n  uid_t uid () const;\n\n  gid_t gid () const;\n\n  std::string gecos () const;\n\n  std::string dir () const;\n\n  std::string shell () const;\n\n  bool ok () const { return m_valid; }\n\n  operator bool () const { return ok (); }\n\n  static password getpwent ();\n  static password getpwent (std::string& msg);\n\n  static password getpwuid (uid_t uid);\n  static password getpwuid (uid_t uid, std::string& msg);\n\n  static password getpwnam (const std::string& nm);\n  static password getpwnam (const std::string& nm, std::string& msg);\n\n  static int setpwent ();\n  static int setpwent (std::string& msg);\n\n  static int endpwent ();\n  static int endpwent (std::string& msg);\n\nprivate:\n\n  // User name.\n  std::string m_name;\n\n  // Encrypted password.\n  std::string m_passwd;\n\n  // Numeric user id.\n  uid_t m_uid;\n\n  // Numeric group id.\n  gid_t m_gid;\n\n  // Miscellaneous junk.\n  std::string m_gecos;\n\n  // Home directory.\n  std::string m_dir;\n\n  // Login shell.\n  std::string m_shell;\n\n  // Flag that says whether we have been properly initialized.\n  bool m_valid;\n\n  // This is how we will create a password object from a pointer\n  // to a struct passwd.\n  password (void *p, std::string& msg);\n};\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/oct-syscalls.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n#include <cstring>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <io.h>\n#else\n#  include <unistd.h>\n#endif\n\n#include \"fcntl-wrappers.h\"\n#include \"lo-utils.h\"\n#include \"oct-syscalls.h\"\n#include \"oct-sysdep.h\"\n#include \"octave-popen2.h\"\n#include \"signal-wrappers.h\"\n#include \"str-vec.h\"\n#include \"unistd-wrappers.h\"\n#include \"wait-wrappers.h\"\n\n#define NOT_SUPPORTED(nm)                       \\\n  nm \": not supported on this system\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nint\ndup (int old_fd)\n{\n  return octave_dup_wrapper (old_fd);\n}\n\nint\ndup2 (int old_fd, int new_fd)\n{\n  std::string msg;\n  return sys::dup2 (old_fd, new_fd, msg);\n}\n\nint\ndup2 (int old_fd, int new_fd, std::string& msg)\n{\n  msg = \"\";\n\n  int status = -1;\n\n  status = octave_dup2_wrapper (old_fd, new_fd);\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\nint\nexecvp (const std::string& file, const string_vector& argv)\n{\n  std::string msg;\n  return sys::execvp (file, argv, msg);\n}\n\nint\nexecvp (const std::string& file, const string_vector& args,\n        std::string& msg)\n{\n  msg = \"\";\n\n  char **argv = args.c_str_vec ();\n\n  int status = octave_execvp_wrapper (file.c_str (), argv);\n\n  string_vector::delete_c_str_vec (argv);\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\npid_t\nfork (std::string& msg)\n{\n  pid_t status = -1;\n\n  if (octave_have_fork ())\n    {\n      status = octave_fork_wrapper ();\n\n      if (status < 0)\n        msg = std::strerror (errno);\n    }\n  else\n    msg = NOT_SUPPORTED (\"fork\");\n\n  return status;\n}\n\npid_t\nvfork (std::string& msg)\n{\n  pid_t status = -1;\n\n  if (octave_have_vfork () || octave_have_fork ())\n    {\n      if (octave_have_vfork ())\n        status = octave_vfork_wrapper ();\n      else\n        status = octave_fork_wrapper ();\n\n      if (status < 0)\n        msg = std::strerror (errno);\n    }\n  else\n    msg = NOT_SUPPORTED (\"vfork\");\n\n  return status;\n}\n\npid_t\ngetpgrp (std::string& msg)\n{\n  pid_t status = octave_getpgrp_wrapper ();\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\npid_t\ngetpid ()\n{\n  return octave_getpid_wrapper ();\n}\n\npid_t\ngetppid ()\n{\n  return octave_getppid_wrapper ();\n}\n\ngid_t\ngetgid ()\n{\n  return octave_getgid_wrapper ();\n}\n\ngid_t\ngetegid ()\n{\n  return octave_getegid_wrapper ();\n}\n\nuid_t\ngetuid ()\n{\n  return octave_getuid_wrapper ();\n}\n\nuid_t\ngeteuid ()\n{\n  return octave_geteuid_wrapper ();\n}\n\nint\npipe (int *fildes)\n{\n  std::string msg;\n  return sys::pipe (fildes, msg);\n}\n\nint\npipe (int *fildes, std::string& msg)\n{\n  msg = \"\";\n\n  int status = -1;\n\n  status = octave_pipe_wrapper (fildes);\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\nint read (int fd, void *buf, size_t count)\n{\n  // This function is defined in <unistd.h> for POSIX and in <io.h> on Windows.\n  // Use this wrapper to avoid having to include headers conditionally in\n  // installed sources.\n  return ::read (fd, buf, count);\n}\n\nint close (int fd)\n{\n  return octave_close_wrapper (fd);\n}\n\npid_t\nwaitpid (pid_t pid, int *status, int options)\n{\n  std::string msg;\n  return sys::waitpid (pid, status, options, msg);\n}\n\npid_t\nwaitpid (pid_t pid, int *status, int options,\n         std::string& msg)\n{\n  pid_t retval = -1;\n  msg = \"\";\n\n  retval = octave_waitpid_wrapper (pid, status, options);\n\n  if (retval < 0)\n    msg = std::strerror (errno);\n\n  return retval;\n}\n\nint\nwcontinue ()\n{\n  return octave_wcontinue_wrapper ();\n}\n\nint\nwcoredump (int status)\n{\n  return octave_wcoredump_wrapper (status);\n}\n\nbool\nwifcontinued (int status)\n{\n  return octave_wifcontinued_wrapper (status);\n}\n\nbool\nwifexited (int status)\n{\n  return octave_wifexited_wrapper (status);\n}\n\nbool\nwifsignaled (int status)\n{\n  return octave_wifsignaled_wrapper (status);\n}\n\nbool\nwifstopped (int status)\n{\n  return octave_wifstopped_wrapper (status);\n}\n\nint\nwexitstatus (int status)\n{\n  return octave_wexitstatus_wrapper (status);\n}\n\nint\nwnohang ()\n{\n  return octave_wnohang_wrapper ();\n}\n\nint\nwstopsig (int status)\n{\n  return octave_wstopsig_wrapper (status);\n}\n\nint\nwtermsig (int status)\n{\n  return octave_wtermsig_wrapper (status);\n}\n\nint\nwuntraced ()\n{\n  return octave_wuntraced_wrapper ();\n}\n\nint\nkill (pid_t pid, int sig)\n{\n  std::string msg;\n  return sys::kill (pid, sig, msg);\n}\n\nint\nkill (pid_t pid, int sig, std::string& msg)\n{\n  msg = \"\";\n\n  int status = -1;\n\n  if (octave_have_kill ())\n    {\n      status = octave_kill_wrapper (pid, sig);\n\n      if (status < 0)\n        msg = std::strerror (errno);\n    }\n  else\n    msg = NOT_SUPPORTED (\"kill\");\n\n  return status;\n}\n\npid_t\npopen2 (const std::string& cmd, const string_vector& args,\n        bool sync_mode, int *fildes)\n{\n  std::string msg;\n  return sys::popen2 (cmd, args, sync_mode, fildes, msg);\n}\n\npid_t\npopen2 (const std::string& cmd, const string_vector& args,\n        bool sync_mode, int *fildes, std::string& msg)\n{\n  char **argv = args.c_str_vec ();\n  const char *errmsg;\n\n  pid_t pid = octave_popen2 (cmd.c_str (), argv, sync_mode, fildes, &errmsg);\n\n  string_vector::delete_c_str_vec (argv);\n\n  if (pid < 0)\n    msg = errmsg;\n\n  return pid;\n}\n\nint\nfcntl (int fd, int cmd, long arg)\n{\n  std::string msg;\n  return sys::fcntl (fd, cmd, arg, msg);\n}\n\nint\nfcntl (int fd, int cmd, long arg, std::string& msg)\n{\n  msg = \"\";\n\n  int status = -1;\n\n  status = octave_fcntl_wrapper (fd, cmd, arg);\n\n  if (status < 0)\n    msg = std::strerror (errno);\n\n  return status;\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/oct-syscalls.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_syscalls_h)\n#define octave_oct_syscalls_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdio>\n#include <functional>\n#include <string>\n\n#include \"unwind-prot.h\"\n\nclass string_vector;\n\n#include <sys/types.h>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nextern OCTAVE_API int dup (int old_fd);\n\nextern OCTAVE_API int dup2 (int, int);\nextern OCTAVE_API int dup2 (int, int, std::string&);\n\nextern OCTAVE_API int execvp (const std::string&, const string_vector&);\nextern OCTAVE_API int execvp (const std::string&, const string_vector&,\n                              std::string&);\n\nextern OCTAVE_API pid_t fork (std::string&);\n\nextern OCTAVE_API pid_t vfork (std::string&);\n\nextern OCTAVE_API pid_t getpgrp (std::string&);\n\nextern OCTAVE_API pid_t getpid ();\n\nextern OCTAVE_API pid_t getppid ();\n\nextern OCTAVE_API gid_t getgid ();\n\nextern OCTAVE_API gid_t getegid ();\n\nextern OCTAVE_API uid_t getuid ();\n\nextern OCTAVE_API uid_t geteuid ();\n\nextern OCTAVE_API int pipe (int *);\nextern OCTAVE_API int pipe (int *, std::string&);\n\nextern OCTAVE_API int read (int fd, void *buf, size_t count);\n\nextern OCTAVE_API int close (int fd);\n\nextern OCTAVE_API pid_t waitpid (pid_t, int *status, int);\nextern OCTAVE_API pid_t waitpid (pid_t, int *status, int, std::string&);\n\nextern OCTAVE_API int wcontinue ();\n\nextern OCTAVE_API int wcoredump (int status);\n\nextern OCTAVE_API bool wifcontinued (int status);\n\nextern OCTAVE_API bool wifexited (int status);\n\nextern OCTAVE_API bool wifsignaled (int status);\n\nextern OCTAVE_API bool wifstopped (int status);\n\nextern OCTAVE_API int wexitstatus (int status);\n\nextern OCTAVE_API int wnohang ();\n\nextern OCTAVE_API int wstopsig (int status);\n\nextern OCTAVE_API int wtermsig (int status);\n\nextern OCTAVE_API int wuntraced ();\n\nextern OCTAVE_API int kill (pid_t, int);\nextern OCTAVE_API int kill (pid_t, int, std::string&);\n\nextern OCTAVE_API pid_t\npopen2 (const std::string&, const string_vector&, bool, int *);\n\nextern OCTAVE_API pid_t\npopen2 (const std::string&, const string_vector&, bool, int *,\n        std::string&);\n\nextern OCTAVE_API int fcntl (int, int, long);\nextern OCTAVE_API int fcntl (int, int, long, std::string&);\n\ntemplate <typename F>\nauto capture_stderr (F fn, std::string& err_str)\n{\n  // create pipe\n  int fds[2];\n  if (pipe (fds) != 0)\n    return fn ();\n\n  octave::unwind_action close_read_pipe ([fds] () { close (fds[0]); });\n\n  int old_stderr;\n  std::invoke_result_t<F> result {};\n\n  {\n    // close the write end of pipe before reading from read end\n    octave::unwind_action close_write_pipe ([fds] () { close (fds[1]); });\n\n    // save old stderr\n    old_stderr = dup (fileno (stderr));\n    if (old_stderr < 0)\n      return fn ();\n\n    // redirect stderr to pipe\n    if (dup2 (fds[1], fileno (stderr)) < 0)\n      return fn ();\n\n    // restore stderr\n    octave::unwind_action restore_stderr (\n      [old_stderr] ()\n      { \n        fflush (stderr);\n        dup2 (old_stderr, fileno (stderr));\n        close (old_stderr);\n      });\n\n    // call function\n    if constexpr (std::is_void_v<std::invoke_result_t<F>>)\n      fn ();\n    else\n      result = fn ();\n  }\n\n  // read from pipe\n  fflush (stderr);\n  char buffer[4096];\n  for (;;)\n    {\n      int n = read (fds[0], buffer, sizeof (buffer));\n      if (n <= 0)\n        break;\n      err_str.append (buffer, n);\n    }\n\n  if constexpr (std::is_void_v<std::invoke_result_t<F>>)\n    return;\n  else\n    return result;\n}\n\ntemplate <typename F>\nauto capture_stderr (F fn)\n{\n  std::string err_str;\n\n  return capture_stderr (fn, err_str);\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/oct-sysdep.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n#include <locale>\n#include <codecvt>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <iostream>\n\n#  include <windows.h>\n#  include <wchar.h>\n#endif\n\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"localcharset-wrapper.h\"\n#include \"oct-error.h\"\n#include \"oct-sysdep.h\"\n#include \"setenv-wrapper.h\"\n#include \"uniconv-wrappers.h\"\n#include \"unistd-wrappers.h\"\n#include \"unsetenv-wrapper.h\"\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include \"filepos-wrappers.h\"\n#  include \"oct-hash.h\"\n#  include \"oct-locbuf.h\"\n#  include \"unwind-prot.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nint\nsystem (const std::string& cmd_str)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  // On Windows (non-Cygwin), child processes need to be created with a new\n  // console to avoid desynchronization of the console that is used by the\n  // command window widget of the GUI.\n\n  // Capture output using pipe.\n  HANDLE h_read;\n  HANDLE h_write;\n  SECURITY_ATTRIBUTES sa {};\n  sa.nLength = sizeof (sa);\n  sa.bInheritHandle = TRUE;  // child can inherit\n  sa.lpSecurityDescriptor = nullptr;\n\n  if (! CreatePipe (&h_read, &h_write, &sa, 0))\n    return GetLastError ();\n\n  // avoid inheriting read end of the pipe\n  SetHandleInformation (h_read, HANDLE_FLAG_INHERIT, 0);\n\n  // create process with new hidden console\n  std::wstring wcmd_str {L\"cmd.exe /C \\\"\"};\n  wcmd_str.append (u8_to_wstring (cmd_str));\n  wcmd_str.append (L\"\\\"\");\n  STARTUPINFOW si {};\n  si.cb = sizeof (si);\n  si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;\n  si.wShowWindow = SW_HIDE;  // avoid flashing black window\n  si.hStdOutput = h_write;\n  si.hStdError = h_write;\n  si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);\n  PROCESS_INFORMATION pi {};\n\n  BOOL ok = CreateProcessW (nullptr, &wcmd_str[0], nullptr, nullptr, TRUE,\n                            CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi);\n\n  CloseHandle (h_write);\n\n  if (! ok)\n    {\n      CloseHandle (h_read);\n      return GetLastError ();\n    }\n\n  // read from pipe (in chunks)\n  char buffer[4096];\n  DWORD bytes_read;\n  while (ReadFile (h_read, buffer, sizeof (buffer)-1, &bytes_read, nullptr)\n         && bytes_read > 0)\n    {\n      buffer[bytes_read] = '\\0';\n      std::cout << buffer;\n    }\n\n  WaitForSingleObject (pi.hProcess, INFINITE);\n\n  DWORD ret = 0;\n  GetExitCodeProcess (pi.hProcess, &ret);\n\n  CloseHandle (pi.hProcess);\n  CloseHandle (pi.hThread);\n  CloseHandle (h_read);\n\n  return ret;\n\n#else\n  return ::system (cmd_str.c_str ());\n#endif\n}\n\nstd::string\ngetcwd ()\n{\n  std::string retval;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  wchar_t *tmp = _wgetcwd (nullptr, 0);\n\n  if (! tmp)\n    (*current_liboctave_error_handler) (\"unable to find current directory\");\n\n  std::wstring tmp_wstr (tmp);\n  free (tmp);\n\n  std::string tmp_str = u8_from_wstring (tmp_wstr);\n\n  retval = tmp_str;\n\n#else\n  // Using octave_getcwd_wrapper ensures that we have a getcwd that\n  // will allocate a buffer as large as necessary if buf and size are\n  // both 0.\n\n  char *tmp = octave_getcwd_wrapper (nullptr, 0);\n\n  if (! tmp)\n    (*current_liboctave_error_handler) (\"unable to find current directory\");\n\n  retval = tmp;\n  free (tmp);\n#endif\n\n  return retval;\n}\n\nint\nchdir (const std::string& path_arg)\n{\n  std::string path = sys::file_ops::tilde_expand (path_arg);\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  if (path.length () == 2 && path[1] == ':')\n    path += '\\\\';\n#endif\n\n  return octave_chdir_wrapper (path.c_str ());\n}\n\nbool\nget_dirlist (const std::string& dirname, string_vector& dirlist,\n             std::string& msg)\n{\n  dirlist = \"\";\n  msg = \"\";\n#if defined (OCTAVE_USE_WINDOWS_API)\n  _WIN32_FIND_DATAW ffd;\n\n  std::string path_name (dirname);\n  if (path_name.empty ())\n    return true;\n\n  if (path_name.back () == '\\\\' || path_name.back () == '/')\n    path_name.push_back ('*');\n  else\n    path_name.append (R\"(\\*)\");\n\n  // Find first file in directory.\n  std::wstring wpath_name = u8_to_wstring (path_name);\n  HANDLE hFind = FindFirstFileW (wpath_name.c_str (), &ffd);\n  if (INVALID_HANDLE_VALUE == hFind)\n    {\n      DWORD errCode = GetLastError ();\n      char *errorText = nullptr;\n      FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM |\n                      FORMAT_MESSAGE_ALLOCATE_BUFFER |\n                      FORMAT_MESSAGE_IGNORE_INSERTS,\n                      nullptr, errCode,\n                      MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),\n                      reinterpret_cast<char *> (&errorText), 0, nullptr);\n      if (errorText != nullptr)\n        {\n          msg = std::string (errorText);\n          LocalFree (errorText);\n        }\n      return false;\n    }\n\n  std::list<std::string> dirlist_str;\n  do\n    dirlist_str.push_back (u8_from_wstring (ffd.cFileName));\n  while (FindNextFileW (hFind, &ffd) != 0);\n\n  FindClose(hFind);\n\n  dirlist = string_vector (dirlist_str);\n\n#else\n\n  dir_entry dir (dirname);\n\n  if (! dir)\n    {\n      msg = dir.error ();\n      return false;\n    }\n\n  dirlist = dir.read ();\n\n  dir.close ();\n#endif\n\n  return true;\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\nstatic bool\ncheck_fseek_ftell_workaround_needed (bool set_nonbuffered_mode)\n{\n  // To check whether the workaround is needed:\n  //\n  //   * Create a tmp file with LF line endings only.\n  //\n  //   * Open that file for reading in text mode.\n  //\n  //   * Read a line.\n  //\n  //   * Use ftello to record the position of the beginning of the\n  //     second line.\n  //\n  //   * Read and save the contents of the second line.\n  //\n  //   * Use fseeko to return to the saved position.\n  //\n  //   * Read the second line again and compare to the previously\n  //     saved text.\n  //\n  //   * If the lines are different, we need to set non-buffered\n  //     input mode for files opened in text mode.\n\n  std::string tmpname = sys::tempnam (\"\", \"oct-\");\n\n  if (tmpname.empty ())\n    {\n      (*current_liboctave_warning_handler)\n        (\"fseek/ftell bug check failed (tmp name creation)!\");\n      return false;\n    }\n\n  std::FILE *fptr = std::fopen (tmpname.c_str (), \"wb\");\n\n  if (! fptr)\n    {\n      (*current_liboctave_warning_handler)\n        (\"fseek/ftell bug check failed (opening tmp file for writing)!\");\n      return false;\n    }\n\n  fprintf (fptr, \"%s\", \"foo\\nbar\\nbaz\\n\");\n\n  std::fclose (fptr);\n\n  fptr = std::fopen (tmpname.c_str (), \"rt\");\n\n  if (! fptr)\n    {\n      (*current_liboctave_warning_handler)\n        (\"fseek/ftell bug check failed (opening tmp file for reading)!\");\n      return false;\n    }\n\n  unwind_action act ([fptr, tmpname] ()\n  {\n    std::fclose (fptr);\n    sys::unlink (tmpname);\n  });\n\n  if (set_nonbuffered_mode)\n    ::setvbuf (fptr, nullptr, _IONBF, 0);\n\n  while (true)\n    {\n      int c = fgetc (fptr);\n\n      if (c == EOF)\n        {\n          (*current_liboctave_warning_handler)\n            (\"fseek/ftell bug check failed (skipping first line)!\");\n          return false;\n        }\n\n      if (c == '\\n')\n        break;\n    }\n\n  off_t pos = octave_ftello_wrapper (fptr);\n\n  char buf1[8];\n  int i = 0;\n  while (true)\n    {\n      int c = fgetc (fptr);\n\n      if (c == EOF)\n        {\n          (*current_liboctave_warning_handler)\n            (\"fseek/ftell bug check failed (reading second line)!\");\n          return false;\n        }\n\n      if (c == '\\n')\n        break;\n\n      buf1[i++] = static_cast<char> (c);\n    }\n  buf1[i] = '\\0';\n\n  octave_fseeko_wrapper (fptr, pos, SEEK_SET);\n\n  char buf2[8];\n  i = 0;\n  while (true)\n    {\n      int c = fgetc (fptr);\n\n      if (c == EOF)\n        {\n          (*current_liboctave_warning_handler)\n            (\"fseek/ftell bug check failed (reading after repositioning)!\");\n          return false;\n        }\n\n      if (c == '\\n')\n        break;\n\n      buf2[i++] = static_cast<char> (c);\n    }\n  buf2[i] = '\\0';\n\n  return strcmp (buf1, buf2);\n}\n\nstatic std::string\nget_formatted_last_error ()\n{\n  std::string msg = \"\";\n\n  DWORD last_error = GetLastError ();\n\n  wchar_t *error_text = nullptr;\n  FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |\n                  FORMAT_MESSAGE_ALLOCATE_BUFFER |\n                  FORMAT_MESSAGE_IGNORE_INSERTS,\n                  nullptr, last_error,\n                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),\n                  reinterpret_cast<wchar_t *> (&error_text), 0, nullptr);\n\n  if (error_text != nullptr)\n    {\n      msg = u8_from_wstring (error_text);\n      LocalFree (error_text);\n    }\n  else\n    msg = \"Unknown error.\";\n\n  return msg;\n}\n#endif\n\nbool\nfile_exists (const std::string& filename, bool is_dir)\n{\n  // Check if a file with the given name exists on the file system.  If is_dir\n  // is true (the default), also return true if filename refers to a directory.\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::wstring w_fn = u8_to_wstring (filename);\n\n  DWORD f_attr = GetFileAttributesW (w_fn.c_str ());\n\n  return ((f_attr != INVALID_FILE_ATTRIBUTES)\n          && (is_dir || ! (f_attr & FILE_ATTRIBUTE_DIRECTORY)));\n\n#else\n  file_stat fs (filename);\n\n  return (fs && (is_dir || ! fs.is_dir ()));\n\n#endif\n}\n\nbool\nfile_exists (const std::string& filename, bool is_dir, std::string& msg)\n{\n  // Check if a file with the given name exists on the file system.  If is_dir\n  // is true (the default), also return true if filename refers to a directory.\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::wstring w_fn = u8_to_wstring (filename);\n\n  DWORD f_attr = GetFileAttributesW (w_fn.c_str ());\n\n  if (f_attr == INVALID_FILE_ATTRIBUTES)\n    msg = get_formatted_last_error ();\n\n  return ((f_attr != INVALID_FILE_ATTRIBUTES)\n          && (is_dir || ! (f_attr & FILE_ATTRIBUTE_DIRECTORY)));\n\n#else\n  file_stat fs (filename);\n\n  if (! fs)\n    msg = fs.error ();\n\n  return (fs && (is_dir || ! fs.is_dir ()));\n\n#endif\n}\n\nbool\ndir_exists (const std::string& dirname)\n{\n  // Check if a directory with the given name exists on the file system.\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::wstring w_dn = u8_to_wstring (dirname);\n\n  DWORD f_attr = GetFileAttributesW (w_dn.c_str ());\n\n  return ((f_attr != INVALID_FILE_ATTRIBUTES)\n          && (f_attr & FILE_ATTRIBUTE_DIRECTORY));\n\n#else\n  file_stat fs (dirname);\n\n  return (fs && fs.is_dir ());\n\n#endif\n}\n\nbool\ndir_exists (const std::string& dirname, std::string& msg)\n{\n  // Check if a directory with the given name exists on the file system.\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::wstring w_dn = u8_to_wstring (dirname);\n\n  DWORD f_attr = GetFileAttributesW (w_dn.c_str ());\n\n  if (f_attr == INVALID_FILE_ATTRIBUTES)\n    msg = get_formatted_last_error ();\n\n  return ((f_attr != INVALID_FILE_ATTRIBUTES)\n          && (f_attr & FILE_ATTRIBUTE_DIRECTORY));\n\n#else\n  file_stat fs (dirname);\n\n  if (! fs)\n    msg = fs.error ();\n\n  return (fs && fs.is_dir ());\n\n#endif\n}\n\n// Return TRUE if FILE1 and FILE2 refer to the same (physical) file.\n\nbool\nsame_file (const std::string& file1, const std::string& file2)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  // FIXME: When Octave switches to C++17, consider replacing this function\n  //        by https://en.cppreference.com/w/cpp/filesystem/equivalent.\n\n  bool retval = false;\n\n  std::wstring file1w = sys::u8_to_wstring (file1);\n  std::wstring file2w = sys::u8_to_wstring (file2);\n  const wchar_t *f1 = file1w.c_str ();\n  const wchar_t *f2 = file2w.c_str ();\n\n  bool f1_is_dir = GetFileAttributesW (f1) & FILE_ATTRIBUTE_DIRECTORY;\n  bool f2_is_dir = GetFileAttributesW (f2) & FILE_ATTRIBUTE_DIRECTORY;\n\n  // Windows native code\n  // Reference: http://msdn2.microsoft.com/en-us/library/aa363788.aspx\n\n  DWORD share = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;\n\n  HANDLE hfile1\n    = CreateFileW (f1, 0, share, 0, OPEN_EXISTING,\n                   f1_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);\n\n  if (hfile1 != INVALID_HANDLE_VALUE)\n    {\n      HANDLE hfile2\n        = CreateFileW (f2, 0, share, 0, OPEN_EXISTING,\n                       f2_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);\n\n      if (hfile2 != INVALID_HANDLE_VALUE)\n        {\n          BY_HANDLE_FILE_INFORMATION hfi1;\n          BY_HANDLE_FILE_INFORMATION hfi2;\n\n          if (GetFileInformationByHandle (hfile1, &hfi1)\n              && GetFileInformationByHandle (hfile2, &hfi2))\n            {\n              retval = (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber\n                        && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh\n                        && hfi1.nFileIndexLow == hfi2.nFileIndexLow\n                        && hfi1.nFileSizeHigh == hfi2.nFileSizeHigh\n                        && hfi1.nFileSizeLow == hfi2.nFileSizeLow\n                        && hfi1.ftLastWriteTime.dwLowDateTime\n                        == hfi2.ftLastWriteTime.dwLowDateTime\n                        && hfi1.ftLastWriteTime.dwHighDateTime\n                        == hfi2.ftLastWriteTime.dwHighDateTime);\n            }\n\n          CloseHandle (hfile2);\n        }\n\n      CloseHandle (hfile1);\n    }\n\n  return retval;\n\n#else\n\n  // POSIX Code\n\n  sys::file_stat fs_file1 (file1);\n  sys::file_stat fs_file2 (file2);\n\n  return (fs_file1 && fs_file2\n          && fs_file1.ino () == fs_file2.ino ()\n          && fs_file1.dev () == fs_file2.dev ());\n\n#endif\n}\n\nstd::FILE *\nfopen (const std::string& filename, const std::string& mode)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  std::wstring wfilename = u8_to_wstring (filename);\n  std::wstring wmode = u8_to_wstring (mode);\n\n  std::FILE *fptr = _wfopen (wfilename.c_str (), wmode.c_str ());\n\n  static bool fseek_ftell_bug_workaround_needed = false;\n  static bool fseek_ftell_bug_checked = false;\n\n  if (! fseek_ftell_bug_checked && mode.find ('t') != std::string::npos)\n    {\n      // FIXME: Is the following workaround needed for all files\n      // opened in text mode, or only for files opened for reading?\n\n      // Try to avoid fseek/ftell bug on Windows systems by setting\n      // non-buffered input mode for files opened in text mode, but\n      // only if it appears that the workaround is needed.  See\n      // Octave bug #58055.\n\n      // To check whether the workaround is needed:\n      //\n      //   * Create a tmp file with LF line endings only.\n      //\n      //   * Open that file for reading in text mode.\n      //\n      //   * Read a line.\n      //\n      //   * Use ftello to record the position of the beginning of\n      //     the second line.\n      //\n      //   * Read and save the contents of the second line.\n      //\n      //   * Use fseeko to return to the saved position.\n      //\n      //   * Read the second line again and compare to the\n      //     previously saved text.\n      //\n      //   * If the lines are different, we need to set non-buffered\n      //     input mode for files opened in text mode.\n      //\n      //   * To verify that the workaround solves the problem,\n      //     repeat the above test with non-buffered input mode.  If\n      //     that fails, warn that there may be trouble with\n      //     ftell/fseek when reading files opened in text mode.\n\n      if (check_fseek_ftell_workaround_needed (false))\n        {\n          if (check_fseek_ftell_workaround_needed (true))\n            (*current_liboctave_warning_handler)\n              (\"fseek/ftell may fail for files opened in text mode\");\n          else\n            fseek_ftell_bug_workaround_needed = true;\n        }\n\n      fseek_ftell_bug_checked = true;\n    }\n\n  if (fseek_ftell_bug_workaround_needed\n      && mode.find ('t') != std::string::npos)\n    ::setvbuf (fptr, nullptr, _IONBF, 0);\n\n  return fptr;\n\n#else\n  return std::fopen (filename.c_str (), mode.c_str ());\n#endif\n}\n\nstd::FILE *\nfopen_tmp (const std::string& name, const std::string& mode)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  // Append \"D\" to the mode string to indicate that this is a temporary\n  // file that should be deleted when the last open handle is closed.\n  std::string tmp_mode = mode + \"D\";\n\n  return std::fopen (name.c_str (), tmp_mode.c_str ());\n\n#else\n\n  std::FILE *fptr = std::fopen (name.c_str (), mode.c_str ());\n\n  // From gnulib: This relies on the Unix semantics that a file is not\n  // really removed until it is closed.\n  octave_unlink_wrapper (name.c_str ());\n\n  return fptr;\n\n#endif\n}\n\nstd::fstream\nfstream (const std::string& filename, const std::ios::openmode mode)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  std::wstring wfilename = u8_to_wstring (filename);\n\n  return std::fstream (wfilename.c_str (), mode);\n\n#else\n  return std::fstream (filename.c_str (), mode);\n#endif\n}\n\nstd::ifstream\nifstream (const std::string& filename, const std::ios::openmode mode)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  std::wstring wfilename = u8_to_wstring (filename);\n\n  return std::ifstream (wfilename.c_str (), mode);\n\n#else\n  return std::ifstream (filename.c_str (), mode);\n#endif\n}\n\nstd::ofstream\nofstream (const std::string& filename, const std::ios::openmode mode)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  std::wstring wfilename = u8_to_wstring (filename);\n\n  return std::ofstream (wfilename.c_str (), mode);\n\n#else\n  return std::ofstream (filename.c_str (), mode);\n#endif\n}\n\nvoid\nputenv_wrapper (const std::string& name, const std::string& value)\n{\n  // Short of extreme measures to track memory, altering the environment\n  // always leaks memory, but the saving grace is that the leaks are small.\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  // FIXME: The malloc leaks memory, but so would a call to setenv.\n\n  // As far as I can see there's no way to distinguish between the\n  // various errors; putenv doesn't have errno values.\n\n  if (name.find ('=') != std::string::npos)\n    (*current_liboctave_error_handler)\n      (\"putenv: name (%s) must not contain '='\", name.c_str());\n\n  std::string new_env = name + \"=\" + value;\n\n  std::wstring new_wenv = u8_to_wstring (new_env);\n\n  int len = (new_wenv.length () + 1) * sizeof (wchar_t);\n\n  wchar_t *new_item = static_cast<wchar_t *> (std::malloc (len));\n\n  wcscpy (new_item, new_wenv.c_str());\n\n  if (_wputenv (new_item) < 0)\n    (*current_liboctave_error_handler)\n      (\"putenv (%s) failed\", new_env.c_str());\n#else\n  // FIXME: Using setenv leaks memory, but so would using malloc and putenv.\n\n  if (octave_setenv_wrapper (name.c_str (), value.c_str (), 1) < 0)\n    (*current_liboctave_error_handler)\n      (\"setenv (%s, %s) failed with error %d\", name.c_str (), value.c_str (),\n       errno);\n#endif\n}\n\nstd::string\ngetenv_wrapper (const std::string& name)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::wstring wname = u8_to_wstring (name);\n  wchar_t *env = _wgetenv (wname.c_str ());\n  return env ? u8_from_wstring (env) : \"\";\n#else\n  char *env = ::getenv (name.c_str ());\n  return env ? env : \"\";\n#endif\n}\n\nint\nunsetenv_wrapper (const std::string& name)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  putenv_wrapper (name, \"\");\n\n  // Also remove variable from environment.\n  std::wstring wname = u8_to_wstring (name);\n  return (SetEnvironmentVariableW (wname.c_str (), nullptr) ? 0 : -1);\n#else\n  return octave_unsetenv_wrapper (name.c_str ());\n#endif\n}\n\nbool\nisenv_wrapper (const std::string& name)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::wstring wname = u8_to_wstring (name);\n  wchar_t *env = _wgetenv (wname.c_str ());\n#else\n  char *env = ::getenv (name.c_str ());\n#endif\n  return env != 0;\n}\n\nstd::wstring\nu8_to_wstring (const std::string& utf8_string)\n{\n  // convert multibyte UTF-8 string to wide character string\n  size_t srclen = utf8_string.length ();\n  const uint8_t *src = reinterpret_cast<const uint8_t *> (utf8_string.c_str ());\n\n  size_t length = 0;\n  char *wchar = octave_u8_conv_to_encoding (\"wchar_t\", src, srclen, &length);\n\n  if (! wchar)\n    return std::wstring ();\n\n  // memcpy to std::wstring to avoid potential memory alignment issues\n  std::wstring retval;\n  retval.resize (length / sizeof (wchar_t));\n  std::memcpy (retval.data (), wchar, length);\n  free (static_cast<void *> (wchar));\n\n  return retval;\n}\n\nstd::string\nu8_from_wstring (const std::wstring& wchar_string)\n{\n  // convert wide character string to multibyte UTF-8 string\n  size_t srclen = wchar_string.length () * sizeof (wchar_t);\n  const char *src = reinterpret_cast<const char *> (wchar_string.c_str ());\n\n  size_t length = 0;\n  char *mbchar = reinterpret_cast<char *>\n                 (octave_u8_conv_from_encoding (\"wchar_t\", src, srclen, &length));\n\n  std::string retval = \"\";\n  if (mbchar != nullptr)\n    {\n      retval = std::string (mbchar, length);\n      free (static_cast<void *> (mbchar));\n    }\n\n  return retval;\n}\n\n// At quite a few places in the code we are passing file names as\n// char arrays to external library functions.\n\n// When these functions try to locate the corresponding file on the\n// disc, they need to use the wide character API on Windows to\n// correctly open files with non-ASCII characters.\n\n// But they have no way of knowing which encoding we are using for\n// the passed string.  So they have no way of reliably converting to\n// a wchar_t array.  (I.e., there is no possible fix for these\n// functions with current C or C++.)\n\n// To solve the dilemma, the function \"get_ASCII_filename\" first\n// checks whether there are any non-ASCII characters in the passed\n// file name.  If there are not, it returns the original name.\n\n// Otherwise, it optionally tries to convert the file name to the locale\n// charset.\n\n// If the file name contains characters that cannot be converted to the\n// locale charset (or that step is skipped), it tries to obtain the short\n// file name (8.3 naming scheme) which only consists of ASCII characters\n// and are safe to pass.  However, short file names can be disabled for\n// performance reasons on the file system level with NTFS and they are not\n// stored on other file systems (e.g., ExFAT).  So there is no guarantee\n// that these exist.\n\n// If short file names are not stored, a hard link to the file is\n// created.  For this the path to the file is split at the deepest\n// possible level that doesn't contain non-ASCII characters.  At\n// that level a hidden folder is created that holds the hard links.\n// That means we need to have write access on that location.  A path\n// to that hard link is returned.\n\n// If the file system is FAT32, there are no hard links.  But FAT32\n// always stores short file names.  So we are safe.\n\n// ExFAT that is occasionally used on USB sticks and SD cards stores\n// neither short file names nor does it support hard links.  So for\n// exFAT with this function, there is (currently) no way to generate\n// a file name that is stripped from non-ASCII characters but still\n// is valid.\n\n// For Unixy systems, this function does nothing.\n\nstd::string\nget_ASCII_filename (const std::string& orig_file_name,\n                    const bool allow_locale)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  // Return file name that only contains ASCII characters that can\n  // be used to access the file orig_file_name.  The original file\n  // must exist in the file system before calling this function.\n  // This is useful for passing file names to functions that are not\n  // aware of the character encoding we are using.\n\n  // 0. Check whether filename contains non-ASCII (UTF-8) characters.\n\n  std::string::const_iterator first_non_ASCII\n    = std::find_if (orig_file_name.begin (), orig_file_name.end (),\n  [](char c) { return (c < 0 || c >= 128); });\n\n  if (first_non_ASCII == orig_file_name.end ())\n    return orig_file_name;\n\n  // 1. Optionally, check if all characters in the path can be successfully\n  // converted to the locale charset\n  if (allow_locale)\n    {\n      const char *locale = octave_locale_charset_wrapper ();\n      if (locale)\n        {\n          const uint8_t *name_u8 = reinterpret_cast<const uint8_t *>\n                                   (orig_file_name.c_str ());\n          std::size_t length = 0;\n          char *name_locale = octave_u8_conv_to_encoding_strict\n                              (locale, name_u8,\n                               orig_file_name.length () + 1, &length);\n          if (name_locale)\n            {\n              std::string file_name_locale (name_locale, length);\n              free (name_locale);\n              return file_name_locale;\n            }\n        }\n    }\n\n  // 2. Check if file system stores short filenames (might be ASCII-only).\n\n  std::wstring w_orig_file_name_str = u8_to_wstring (orig_file_name);\n  const wchar_t *w_orig_file_name = w_orig_file_name_str.c_str ();\n\n  // Get full path to file\n  wchar_t w_full_file_name[_MAX_PATH];\n  if (_wfullpath (w_full_file_name, w_orig_file_name, _MAX_PATH) == nullptr)\n    return orig_file_name;\n\n  std::wstring w_full_file_name_str = w_full_file_name;\n\n  // Get short filename (8.3) from UTF-16 filename.\n\n  long length = GetShortPathNameW (w_full_file_name, nullptr, 0);\n\n  if (length > 0)\n    {\n      // Dynamically allocate the correct size (terminating null char\n      // was included in length).\n\n      OCTAVE_LOCAL_BUFFER (wchar_t, w_short_file_name, length);\n      GetShortPathNameW (w_full_file_name, w_short_file_name, length);\n\n      std::wstring w_short_file_name_str\n        = std::wstring (w_short_file_name, length);\n\n      if (w_short_file_name_str.compare (0, length-1, w_full_file_name_str) != 0)\n        {\n          // Check whether short file name contains non-ASCII characters\n          std::string short_file_name\n            = u8_from_wstring (w_short_file_name_str);\n          first_non_ASCII\n            = std::find_if (short_file_name.begin (),\n                            short_file_name.end (),\n          [](char c) { return (c < 0 || c >= 128); });\n          if (first_non_ASCII == short_file_name.end ())\n            return short_file_name;\n        }\n    }\n\n  // 3. Create hard link with only-ASCII characters.\n  // Get longest possible part of path that only contains ASCII chars.\n\n  std::wstring::iterator w_first_non_ASCII\n    = std::find_if (w_full_file_name_str.begin (), w_full_file_name_str.end (),\n  [](wchar_t c) { return (c < 0 || c >= 128); });\n  std::wstring tmp_substr\n    = std::wstring (w_full_file_name_str.begin (), w_first_non_ASCII);\n\n  std::size_t pos\n    = tmp_substr.find_last_of (u8_to_wstring (file_ops::dir_sep_chars ()));\n\n  std::string par_dir\n    = u8_from_wstring (w_full_file_name_str.substr (0, pos+1));\n\n  // Create .oct_ascii directory.\n  // FIXME: We need to have write permission in this location.\n\n  std::string oct_ascii_dir = par_dir + \".oct_ascii\";\n  std::string test_dir = canonicalize_file_name (oct_ascii_dir);\n\n  if (test_dir.empty ())\n    {\n      std::string msg;\n      int status = sys::mkdir (oct_ascii_dir, 0777, msg);\n\n      if (status < 0)\n        return orig_file_name;\n\n      // Set hidden property.\n      SetFileAttributesA (oct_ascii_dir.c_str (), FILE_ATTRIBUTE_HIDDEN);\n    }\n\n  // Create file from hash of full filename.\n  std::string filename_hash\n    = (oct_ascii_dir + file_ops::dir_sep_str ()\n       + crypto::hash (\"SHA1\", orig_file_name));\n\n  // FIXME: This is just to check if the file exists.  Use a more efficient\n  // method.\n  std::string abs_filename_hash = canonicalize_file_name (filename_hash);\n\n  if (! abs_filename_hash.empty ())\n    sys::unlink (filename_hash);\n\n  // At this point, we know that we have only ASCII characters.\n  // So instead of converting, just copy the characters to std::wstring.\n  std::wstring w_filename_hash (filename_hash.begin (),\n                                filename_hash.end ());\n\n  if (CreateHardLinkW (w_filename_hash.c_str (), w_orig_file_name, nullptr))\n    return filename_hash;\n\n#else\n\n  octave_unused_parameter (allow_locale);\n\n#endif\n\n  return orig_file_name;\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/oct-sysdep.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_sysdep_h)\n#define octave_oct_sysdep_h 1\n\n#include \"octave-config.h\"\n\n#include <fstream>\n#include <string>\n\n#include <sys/types.h>\n\n#include \"lo-ieee.h\"\n\nclass string_vector;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nextern OCTAVE_API int system (const std::string& cmd_str);\n\nextern OCTAVE_API std::string getcwd ();\n\nextern OCTAVE_API int chdir (const std::string&);\n\nextern OCTAVE_API bool\nget_dirlist (const std::string& dirname, string_vector& dirlist,\n             std::string& msg);\n\nextern OCTAVE_API bool\nfile_exists (const std::string& filename, bool is_dir = true);\n\nextern OCTAVE_API bool\nfile_exists (const std::string& filename, bool is_dir, std::string& msg);\n\nextern OCTAVE_API bool dir_exists (const std::string& dirname);\n\nextern OCTAVE_API bool\ndir_exists (const std::string& dirname, std::string& msg);\n\nextern OCTAVE_API bool\nsame_file (const std::string& f, const std::string& g);\n\nextern OCTAVE_API std::FILE *\nfopen (const std::string& name, const std::string& mode);\n\nextern OCTAVE_API std::FILE *\nfopen_tmp (const std::string& name, const std::string& mode);\n\nextern OCTAVE_API std::fstream\nfstream (const std::string& name,\n         const std::ios::openmode mode = std::ios::in | std::ios::out);\n\nextern OCTAVE_API std::ifstream\nifstream (const std::string& name,\n          const std::ios::openmode mode = std::ios::in);\n\nextern OCTAVE_API std::ofstream\nofstream (const std::string& name,\n          const std::ios::openmode mode = std::ios::out);\n\nextern OCTAVE_API void\nputenv_wrapper (const std::string& name, const std::string& value);\n\nextern OCTAVE_API std::string getenv_wrapper (const std::string&);\n\nextern OCTAVE_API bool isenv_wrapper (const std::string&);\n\nextern OCTAVE_API int unsetenv_wrapper (const std::string&);\n\nextern OCTAVE_API std::wstring u8_to_wstring (const std::string&);\n\nextern OCTAVE_API std::string u8_from_wstring (const std::wstring&);\n\nextern OCTAVE_API std::string\nget_ASCII_filename (const std::string& long_file_name,\n                    const bool allow_locale = false);\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/oct-sysinfo.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sstream>\n#include <string>\n\n#include \"f77-fcn.h\"\n#include \"oct-shlib.h\"\n#include \"oct-sysinfo.h\"\n\n// Hack to stringize macro results.\n#define xSTRINGIZE(x) #x\n#define STRINGIZE(x) xSTRINGIZE(x)\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nstd::string blas_version ()\n{\n  dynamic_library dyn_libs (\"\");\n\n  if (! dyn_libs)\n    return \"unknown BLAS\";\n\n  std::string retval;\n\n  // Check for functions that are specific to certain BLAS implementations.\n\n  // FlexiBLAS\n  typedef void (*flexi_f_type) (int *, int *, int *);\n  flexi_f_type flexi_f_ptr = reinterpret_cast<flexi_f_type>\n                             (dyn_libs.search (\"flexiblas_get_version\"));\n\n  if (flexi_f_ptr)\n    {\n      int v_major = 0;\n      int v_minor = 0;\n      int v_patch = 0;\n      flexi_f_ptr (&v_major, &v_minor, &v_patch);\n\n      std::ostringstream s;\n      s << \"FlexiBLAS Version \"\n        << v_major << \".\" << v_minor << \".\" << v_patch;\n\n      retval = s.str ();\n    }\n\n  // OpenBLAS\n  typedef char *(*open_fcn_type) ();\n  open_fcn_type open_f_ptr = reinterpret_cast<open_fcn_type>\n                             (dyn_libs.search (\"openblas_get_config\"));\n\n  if (open_f_ptr)\n    {\n      if (! retval.empty ())\n        retval += \"\\n\";\n\n      retval += \"OpenBLAS (config: \" + std::string (open_f_ptr ()) + \")\";\n    }\n\n  // OpenBLAS with minimal extension functions included in the library\n  else if (dyn_libs.search (\"openblas_get_num_threads\"))\n    {\n      if (! retval.empty ())\n        retval += \"\\n\";\n\n      retval += \"OpenBLAS (config: unknown)\";\n    }\n\n  // GotoBLAS(2)\n  if (dyn_libs.search (\"gotoblas_profile_init\"))\n    {\n      if (! retval.empty ())\n        retval += \"\\n\";\n\n      retval += \"GotoBLAS(2)\";\n    }\n\n  // ATLAS\n  // FIXME: If we are really interested, we could use a pipe to\n  // redirect the output of \"ATL_buildinfo\".\n  if (dyn_libs.search (\"ATL_buildinfo\"))\n    {\n      if (! retval.empty ())\n        retval += \"\\n\";\n\n      retval += \"ATLAS\";\n    }\n\n  // ACML\n  typedef void (*acml_f_type) (int *, int *, int *);\n  acml_f_type acml_f_ptr = reinterpret_cast<acml_f_type>\n                           (dyn_libs.search (\"acmlversion\"));\n\n  if (acml_f_ptr)\n    {\n      int v_major = 0;\n      int v_minor = 0;\n      int v_patch = 0;\n      acml_f_ptr (&v_major, &v_minor, &v_patch);\n\n      std::ostringstream s;\n      s << \"ACML BLAS Version \"\n        << v_major << \".\" << v_minor << \".\" << v_patch;\n\n      if (! retval.empty ())\n        retval += \"\\n\";\n\n      retval += s.str ();\n    }\n\n  // Intel MKL\n  typedef void (*mkl_f_type) (char *, int);\n  mkl_f_type mkl_f_ptr = reinterpret_cast<mkl_f_type>\n                         (dyn_libs.search (\"mkl_get_version_string\"));\n\n  if (mkl_f_ptr)\n    {\n      char buf[198] = {};\n      // MKL overwrites buffer.  Read (LENGTH-1) bytes to keep '\\0' terminator.\n      mkl_f_ptr (buf, (198 - 1));\n\n      if (! retval.empty ())\n        retval += \"\\n\";\n\n      retval += std::string (buf);\n    }\n\n  // Otherwise\n  if (retval.empty ())\n    retval = \"unknown or reference BLAS\";\n\n  return retval;\n}\n\nstd::string\nlapack_version ()\n{\n  std::string retval = \"unknown LAPACK\";\n\n  dynamic_library dyn_libs (\"\");\n\n  if (! dyn_libs)\n    return retval;\n\n  // query LAPACK version\n  typedef F77_RET_T\n    (*ilaver_fcn_type) (const F77_INT&, const F77_INT&, const F77_INT&);\n  ilaver_fcn_type f_ptr = reinterpret_cast<ilaver_fcn_type>\n                          (dyn_libs.search (STRINGIZE (F77_FUNC (ilaver, ILAVER))));\n\n  if (f_ptr)\n    {\n      int v_major = 0;\n      int v_minor = 0;\n      int v_patch = 0;\n      f_ptr (v_major, v_minor, v_patch);\n\n      std::ostringstream s;\n      s << \"Linear Algebra PACKage Version \"\n        << v_major << \".\" << v_minor << \".\" << v_patch;\n\n      retval = s.str ();\n    }\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/oct-sysinfo.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_sysinfo_h)\n#define octave_oct_sysinfo_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nextern OCTAVE_API std::string blas_version ();\n\nextern OCTAVE_API std::string lapack_version ();\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/oct-time.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <ctime>\n\n#include <iomanip>\n#include <limits>\n#include <ostream>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <windows.h>\n#else\n#  include \"file-stat.h\"\n#endif\n\n#include \"lo-utils.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sysdep.h\"\n#include \"oct-time.h\"\n#include \"octave-preserve-stream-state.h\"\n#include \"strftime-wrapper.h\"\n#include \"strptime-wrapper.h\"\n#include \"time-wrappers.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\ntime::time (double d)\n  : m_ot_unix_time (static_cast<OCTAVE_TIME_T> (d)), m_ot_usec (0)\n{\n  double ip;\n  m_ot_usec = static_cast<int> (std::modf (d, &ip) * 1e6);\n}\n\ntime::time (const base_tm& tm)\n  : m_ot_unix_time (), m_ot_usec ()\n{\n  struct ::tm t;\n\n  t.tm_sec = tm.sec ();\n  t.tm_min = tm.min ();\n  t.tm_hour = tm.hour ();\n  t.tm_mday = tm.mday ();\n  t.tm_mon = tm.mon ();\n  t.tm_year = tm.year ();\n  t.tm_wday = tm.wday ();\n  t.tm_yday = tm.yday ();\n  t.tm_isdst = tm.isdst ();\n\n#if defined (HAVE_TM_GMTOFF)\n  t.tm_gmtoff = tm.gmtoff ();\n#endif\n\n#if defined (HAVE_STRUCT_TM_TM_ZONE)\n  std::string s = tm.zone ();\n  char *ps = strsave (s.c_str ());\n  t.tm_zone = ps;\n#endif\n\n  m_ot_unix_time = octave_mktime_wrapper (&t);\n\n#if defined (HAVE_STRUCT_TM_TM_ZONE)\n  delete [] ps;\n#endif\n\n  m_ot_usec = tm.usec ();\n}\n\nstd::string\ntime::ctime () const\n{\n  return localtime (*this).asctime ();\n}\n\nstd::ostream&\noperator << (std::ostream& os, const time& ot)\n{\n  preserve_stream_state stream_state (os);\n\n  os << ot.m_ot_unix_time << '.'\n     << std::setw (6) << std::setfill ('0') << ot.m_ot_usec;\n\n  return os;\n}\n\nvoid\ntime::stamp ()\n{\n  time_t ot_unix_time;\n  octave_gettimeofday_wrapper (&ot_unix_time, &m_ot_usec);\n  m_ot_unix_time = ot_unix_time;\n}\n\n// From the mktime() manual page:\n//\n//     The mktime() function converts a broken-down time structure,\n//     expressed as local time, to calendar time representation.\n//\n//     <snip>\n//\n//     If structure members are outside their legal interval, they\n//     will be normalized (so that, e.g., 40 October is changed into\n//     9 November).\n//\n// So, we no longer check limits here.\n\n#define DEFINE_SET_FIELD_FCN(type, f, lo, hi)   \\\n    base_tm&                                    \\\n    base_tm::f (type v)                         \\\n    {                                           \\\n      m_ ## f = v;                              \\\n                                                \\\n      return *this;                             \\\n    }\n\n#define DEFINE_SET_INT_FIELD_FCN(f, lo, hi)     \\\n    DEFINE_SET_FIELD_FCN (int, f, lo, hi)\n\nDEFINE_SET_INT_FIELD_FCN (usec, 0, 1000000)\nDEFINE_SET_INT_FIELD_FCN (sec, 0, 61)\nDEFINE_SET_INT_FIELD_FCN (min, 0, 59)\nDEFINE_SET_INT_FIELD_FCN (hour, 0, 23)\nDEFINE_SET_INT_FIELD_FCN (mday, 1, 31)\nDEFINE_SET_INT_FIELD_FCN (mon, 0, 11)\nDEFINE_SET_INT_FIELD_FCN (year, std::numeric_limits<int>::min (),\n                          std::numeric_limitd<int>::max ())\nDEFINE_SET_INT_FIELD_FCN (wday, 0, 6)\nDEFINE_SET_INT_FIELD_FCN (yday, 0, 365)\nDEFINE_SET_INT_FIELD_FCN (isdst, 0, 1)\nDEFINE_SET_FIELD_FCN (long, gmtoff, -86400, 0)\n\nbase_tm&\nbase_tm::zone (const std::string& s)\n{\n  m_zone = s;\n  return *this;\n}\n\n#if ! defined STRFTIME_BUF_INITIAL_SIZE\n#  define STRFTIME_BUF_INITIAL_SIZE 128\n#endif\n\nstd::string\nbase_tm::strftime (const std::string& fmt) const\n{\n  std::string retval;\n\n  if (! fmt.empty ())\n    {\n      struct ::tm t;\n\n      t.tm_sec = m_sec;\n      t.tm_min = m_min;\n      t.tm_hour = m_hour;\n      t.tm_mday = m_mday;\n      t.tm_mon = m_mon;\n      t.tm_year = m_year;\n      t.tm_wday = m_wday;\n      t.tm_yday = m_yday;\n      t.tm_isdst = m_isdst;\n\n#if defined (HAVE_TM_GMTOFF)\n      t.tm_gmtoff = m_gmtoff;\n#endif\n\n#if defined (HAVE_STRUCT_TM_TM_ZONE)\n      char *ps = strsave (m_zone.c_str ());\n      t.tm_zone = ps;\n#endif\n\n      const char *fmt_str = fmt.c_str ();\n\n      char *buf = nullptr;\n      std::size_t bufsize = STRFTIME_BUF_INITIAL_SIZE;\n      std::size_t chars_written = 0;\n\n      while (chars_written == 0)\n        {\n          delete [] buf;\n          buf = new char [bufsize];\n          buf[0] = '\\0';\n\n          chars_written\n            = octave_strftime_wrapper (buf, bufsize, fmt_str, &t);\n\n          bufsize *= 2;\n        }\n\n#if defined (HAVE_STRUCT_TM_TM_ZONE)\n      delete [] ps;\n#endif\n\n      retval = buf;\n\n      delete [] buf;\n    }\n\n  return retval;\n}\n\nvoid\nbase_tm::init (void *p)\n{\n  if (! p)\n    return;\n\n  struct ::tm *t = static_cast<struct ::tm *> (p);\n\n  m_sec = t->tm_sec;\n  m_min = t->tm_min;\n  m_hour = t->tm_hour;\n  m_mday = t->tm_mday;\n  m_mon = t->tm_mon;\n  m_year = t->tm_year;\n  m_wday = t->tm_wday;\n  m_yday = t->tm_yday;\n  m_isdst = t->tm_isdst;\n\n#if defined (HAVE_TM_GMTOFF)\n  m_gmtoff = t->tm_gmtoff;\n#elif defined (OCTAVE_USE_WINDOWS_API)\n  TIME_ZONE_INFORMATION tzi;\n\n  GetTimeZoneInformationForYear (m_year, nullptr, &tzi);\n\n  if (m_isdst)\n    m_gmtoff = -60 * (tzi.Bias + tzi.DaylightBias);\n  else\n    m_gmtoff = -60 * (tzi.Bias + tzi.StandardBias);\n#endif\n\n#if defined (HAVE_STRUCT_TM_TM_ZONE)\n  if (t->tm_zone)\n    m_zone = t->tm_zone;\n#elif defined (OCTAVE_USE_WINDOWS_API)\n  if (m_isdst)\n    m_zone = sys::u8_from_wstring (tzi.DaylightName);\n  else\n    m_zone = sys::u8_from_wstring (tzi.StandardName);\n#elif defined (HAVE_TZNAME)\n  if (t->tm_isdst == 0 || t->tm_isdst == 1)\n    m_zone = tzname[t->tm_isdst];\n#endif\n}\n\nvoid\nlocaltime::init (const time& ot)\n{\n  m_usec = ot.usec ();\n\n  time_t t = ot.unix_time ();\n\n  base_tm::init (std::localtime (&t));\n}\n\nvoid\ngmtime::init (const time& ot)\n{\n  m_usec = ot.usec ();\n\n  time_t t = ot.unix_time ();\n\n  base_tm::init (std::gmtime (&t));\n}\n\nvoid\nstrptime::init (const std::string& str, const std::string& fmt)\n{\n  struct ::tm t;\n\n  t.tm_sec = 0;\n  t.tm_min = 0;\n  t.tm_hour = 0;\n  t.tm_mday = 0;\n  t.tm_mon = -1;\n  t.tm_year = std::numeric_limits<int>::min ();\n  t.tm_wday = 0;\n  t.tm_yday = 0;\n  t.tm_isdst = 0;\n\n#if defined (HAVE_TM_GMTOFF)\n  t.tm_gmtoff = 0;\n#endif\n\n#if defined (HAVE_STRUCT_TM_TM_ZONE)\n  char *ps = strsave (\"\");\n  t.tm_zone = ps;\n#endif\n\n  const char *p = str.c_str ();\n\n  char *q = octave_strptime_wrapper (p, fmt.c_str (), &t);\n\n  // Fill in wday and yday, but only if mday is valid and the mon and year\n  // are filled in, avoiding issues with mktime and invalid dates.\n  if (t.tm_mday != 0 && t.tm_mon >= 0\n      && t.tm_year != std::numeric_limits<int>::min ())\n    {\n      t.tm_isdst = -1;\n      octave_mktime_wrapper (&t);\n    }\n\n  if (t.tm_mon < 0)\n    t.tm_mon = 0;\n\n  if (t.tm_year == std::numeric_limits<int>::min ())\n    t.tm_year = 0;\n\n  if (q)\n    m_nchars = q - p + 1;\n  else\n    m_nchars = 0;\n\n  base_tm::init (&t);\n\n#if defined (HAVE_STRUCT_TM_TM_ZONE)\n  delete [] ps;\n#endif\n}\n\nvoid\ncpu_time::stamp ()\n{\n  time_t usr_sec, sys_sec;\n  octave_cpu_time (&usr_sec, &sys_sec, &m_usr_usec, &m_sys_usec);\n  m_usr_sec = usr_sec;\n  m_sys_sec = sys_sec;\n}\n\nvoid\nresource_usage::stamp ()\n{\n  time_t usr_sec, sys_sec;\n  long usr_usec, sys_usec;\n\n  octave_getrusage_wrapper (&usr_sec, &sys_sec, &usr_usec,\n                            &sys_usec, &m_maxrss, &m_ixrss,\n                            &m_idrss, &m_isrss, &m_minflt,\n                            &m_majflt, &m_nswap, &m_inblock,\n                            &m_oublock, &m_msgsnd, &m_msgrcv,\n                            &m_nsignals, &m_nvcsw, &m_nivcsw);\n\n  m_cpu = cpu_time (usr_sec, sys_sec, usr_usec, sys_usec);\n}\n\nfile_time::file_time ()\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  FILETIME curr_file_time;\n  GetSystemTimeAsFileTime (&curr_file_time);\n  m_time\n    = (static_cast<OCTAVE_TIME_T> (curr_file_time.dwHighDateTime)) << 32\n      | (static_cast<OCTAVE_TIME_T> (curr_file_time.dwLowDateTime));\n#else\n  time_t ot_unix_time;\n  long ot_usec;\n  octave_gettimeofday_wrapper (&ot_unix_time, &ot_usec);\n  // Discard usec.  We are assuming a 1 second resolution anyway.\n  m_time = ot_unix_time;\n#endif\n}\n\nfile_time::file_time (const std::string& filename)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  std::wstring wfull_name = sys::u8_to_wstring (filename);\n  WIN32_FILE_ATTRIBUTE_DATA file_attributes;\n\n  if (! GetFileAttributesExW (wfull_name.c_str (), GetFileExInfoStandard,\n                              &file_attributes))\n    {\n      m_time = 0;\n      return;\n    }\n\n  FILETIME last_write_time = file_attributes.ftLastWriteTime;\n\n  m_time\n    = (static_cast<OCTAVE_TIME_T> (last_write_time.dwHighDateTime)) << 32\n      | (static_cast<OCTAVE_TIME_T> (last_write_time.dwLowDateTime));\n#else\n  file_stat fs = file_stat (filename);\n  m_time = fs.mtime ().unix_time ();\n#endif\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/oct-time.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_time_h)\n#define octave_oct_time_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <string>\n\n\nstatic inline double\nas_double (OCTAVE_TIME_T sec, long usec)\n{\n  // Unix time will be exactly representable as a double for more than\n  // 100 million years, so no worry there, and microseconds has a\n  // range of 0-1e6, so we are safe there as well.\n\n  return (static_cast<double> (sec) + static_cast<double> (usec) / 1.0e6);\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nclass base_tm;\n\nclass time\n{\npublic:\n\n  time ()\n    : m_ot_unix_time (0), m_ot_usec (0) { stamp (); }\n\n  time (OCTAVE_TIME_T t)\n    : m_ot_unix_time (t), m_ot_usec (0) { }\n\n  time (OCTAVE_TIME_T t, long us)\n    : m_ot_unix_time (t), m_ot_usec ()\n  {\n    long rem, extra;\n\n    if (us >= 0)\n      {\n        rem = us % 1000000;\n        extra = (us - rem) / 1000000;\n      }\n    else\n      {\n        us = -us;\n        rem = us % 1000000;\n        extra = - (1 + (us - rem) / 1000000);\n        rem = 1000000 - us % 1000000;\n      }\n\n    m_ot_usec = rem;\n    m_ot_unix_time += extra;\n  }\n\n  OCTAVE_API time (double d);\n\n  OCTAVE_API time (const base_tm& tm);\n\n  time (const time& ot)\n    : m_ot_unix_time (ot.m_ot_unix_time), m_ot_usec (ot.m_ot_usec) { }\n\n  time& operator = (const time& ot)\n  {\n    if (this != &ot)\n      {\n        m_ot_unix_time = ot.m_ot_unix_time;\n        m_ot_usec = ot.m_ot_usec;\n      }\n\n    return *this;\n  }\n\n  ~time () = default;\n\n  OCTAVE_API void stamp ();\n\n  double double_value () const\n  {\n    return as_double (m_ot_unix_time, m_ot_usec);\n  }\n\n  OCTAVE_TIME_T unix_time () const { return m_ot_unix_time; }\n\n  long usec () const { return m_ot_usec; }\n\n  OCTAVE_API std::string ctime () const;\n\n  friend OCTAVE_API std::ostream& operator << (std::ostream& os, const time& ot);\n\nprivate:\n\n  // Seconds since the epoch.\n  OCTAVE_TIME_T m_ot_unix_time;\n\n  // Additional microseconds.\n  long m_ot_usec;\n};\n\ninline bool\noperator == (const time& t1, const time& t2)\n{\n  return (t1.unix_time () == t2.unix_time () && t1.usec () == t2.usec ());\n}\n\ninline bool\noperator != (const time& t1, const time& t2)\n{\n  return ! (t1 == t2);\n}\n\ninline bool\noperator < (const time& t1, const time& t2)\n{\n  if (t1.unix_time () < t2.unix_time ())\n    return true;\n  else if (t1.unix_time () > t2.unix_time ())\n    return false;\n  else if (t1.usec () < t2.usec ())\n    return true;\n  else\n    return false;\n}\n\ninline bool\noperator <= (const time& t1, const time& t2)\n{\n  return (t1 < t2 || t1 == t2);\n}\n\ninline bool\noperator > (const time& t1, const time& t2)\n{\n  if (t1.unix_time () > t2.unix_time ())\n    return true;\n  else if (t1.unix_time () < t2.unix_time ())\n    return false;\n  else if (t1.usec () > t2.usec ())\n    return true;\n  else\n    return false;\n}\n\ninline bool\noperator >= (const time& t1, const time& t2)\n{\n  return (t1 > t2 || t1 == t2);\n}\n\ninline time\noperator + (const time& t1, const time& t2)\n{\n  return time (t1.unix_time () + t2.unix_time (),\n               t1.usec () + t2.usec ());\n}\n\nclass base_tm\n{\npublic:\n\n  base_tm ()\n    : m_usec (0), m_sec (0), m_min (0), m_hour (0),\n      m_mday (0), m_mon (0), m_year (0), m_wday (0),\n      m_yday (0), m_isdst (0), m_gmtoff (0), m_zone (\"unknown\")\n  { }\n\n  base_tm (const base_tm& tm)\n    : m_usec (tm.m_usec), m_sec (tm.m_sec), m_min (tm.m_min),\n      m_hour (tm.m_hour), m_mday (tm.m_mday), m_mon (tm.m_mon),\n      m_year (tm.m_year), m_wday (tm.m_wday), m_yday (tm.m_yday),\n      m_isdst (tm.m_isdst), m_gmtoff (tm.m_gmtoff), m_zone (tm.m_zone)\n  { }\n\n  base_tm& operator = (const base_tm& tm)\n  {\n    if (this != &tm)\n      {\n        m_usec = tm.m_usec;\n        m_sec = tm.m_sec;\n        m_min = tm.m_min;\n        m_hour = tm.m_hour;\n        m_mday = tm.m_mday;\n        m_mon = tm.m_mon;\n        m_year = tm.m_year;\n        m_wday = tm.m_wday;\n        m_yday = tm.m_yday;\n        m_isdst = tm.m_isdst;\n        m_gmtoff = tm.m_gmtoff;\n        m_zone = tm.m_zone;\n      }\n\n    return *this;\n  }\n\n  virtual ~base_tm () = default;\n\n  int usec () const { return m_usec; }\n  int sec () const { return m_sec; }\n  int min () const { return m_min; }\n  int hour () const { return m_hour; }\n  int mday () const { return m_mday; }\n  int mon () const { return m_mon; }\n  int year () const { return m_year; }\n  int wday () const { return m_wday; }\n  int yday () const { return m_yday; }\n  int isdst () const { return m_isdst; }\n  long gmtoff () const { return m_gmtoff; }\n  std::string zone () const { return m_zone; }\n\n  OCTAVE_API base_tm& usec (int v);\n  OCTAVE_API base_tm& sec (int v);\n  OCTAVE_API base_tm& min (int v);\n  OCTAVE_API base_tm& hour (int v);\n  OCTAVE_API base_tm& mday (int v);\n  OCTAVE_API base_tm& mon (int v);\n  OCTAVE_API base_tm& year (int v);\n  OCTAVE_API base_tm& wday (int v);\n  OCTAVE_API base_tm& yday (int v);\n  OCTAVE_API base_tm& isdst (int v);\n  OCTAVE_API base_tm& gmtoff (long v);\n  OCTAVE_API base_tm& zone (const std::string& s);\n\n  OCTAVE_API std::string strftime (const std::string& fmt) const;\n\n  std::string asctime () const\n  { return strftime (\"%a %b %d %H:%M:%S %Y\\n\"); }\n\nprotected:\n\n  // Microseconds after the second (0, 999999).\n  int m_usec;\n\n  // Seconds after the minute (0, 61).\n  int m_sec;\n\n  // Minutes after the hour (0, 59).\n  int m_min;\n\n  // Hours since midnight (0, 23).\n  int m_hour;\n\n  // Day of the month (1, 31).\n  int m_mday;\n\n  // Months since January (0, 11).\n  int m_mon;\n\n  // Years since 1900.\n  int m_year;\n\n  // Days since Sunday (0, 6).\n  int m_wday;\n\n  // Days since January 1 (0, 365).\n  int m_yday;\n\n  // Daylight saving time flag.\n  int m_isdst;\n\n  // Time zone.\n  long m_gmtoff;\n\n  // Time zone.\n  std::string m_zone;\n\n  OCTAVE_API void init (void *p);\n};\n\nclass localtime : public base_tm\n{\npublic:\n\n  localtime ()\n    : base_tm () { init (time ()); }\n\n  localtime (const time& ot)\n    : base_tm () { init (ot); }\n\n  localtime (const localtime& t)\n    : base_tm (t) { }\n\n  localtime& operator = (const localtime& t)\n  {\n    base_tm::operator = (t);\n    return *this;\n  }\n\n  ~localtime () = default;\n\nprivate:\n\n  OCTAVE_API void init (const time& ot);\n};\n\nclass gmtime : public base_tm\n{\npublic:\n\n  gmtime ()\n    : base_tm () { init (time ()); }\n\n  gmtime (const time& ot)\n    : base_tm () { init (ot); }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (gmtime)\n\nprivate:\n\n  OCTAVE_API void init (const time& ot);\n};\n\nclass strptime : public base_tm\n{\npublic:\n\n  strptime () = delete;\n\n  strptime (const std::string& str, const std::string& fmt)\n    : base_tm (), m_nchars (0)\n  {\n    init (str, fmt);\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (strptime)\n\n  int characters_converted () const { return m_nchars; }\n\nprivate:\n\n  int m_nchars;\n\n  OCTAVE_API void init (const std::string& str, const std::string& fmt);\n};\n\nclass cpu_time\n{\npublic:\n\n  friend class resource_usage;\n\n  cpu_time ()\n    : m_usr_sec (0), m_sys_sec (0), m_usr_usec (0), m_sys_usec (0)\n  {\n    stamp ();\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (cpu_time)\n\n  OCTAVE_API void stamp ();\n\n  double user () const\n  {\n    return as_double (m_usr_sec, m_usr_usec);\n  }\n\n  double system () const\n  {\n    return as_double (m_sys_sec, m_sys_usec);\n  }\n\n  OCTAVE_TIME_T user_sec () const { return m_usr_sec; }\n  long user_usec () const { return m_usr_usec; }\n\n  OCTAVE_TIME_T system_sec () const { return m_sys_sec; }\n  long system_usec () const { return m_sys_usec; }\n\nprivate:\n\n  OCTAVE_TIME_T m_usr_sec;\n  OCTAVE_TIME_T m_sys_sec;\n\n  long m_usr_usec;\n  long m_sys_usec;\n\n  cpu_time (OCTAVE_TIME_T usr_sec, OCTAVE_TIME_T sys_sec, long usr_usec, long sys_usec)\n    : m_usr_sec (usr_sec), m_sys_sec (sys_sec),\n      m_usr_usec (usr_usec), m_sys_usec (sys_usec)\n  { }\n};\n\nclass resource_usage\n{\npublic:\n\n  resource_usage ()\n    : m_cpu (), m_maxrss (0), m_ixrss (0), m_idrss (0),\n      m_isrss (0), m_minflt (0), m_majflt (0), m_nswap (0),\n      m_inblock (0), m_oublock (0), m_msgsnd (0), m_msgrcv (0),\n      m_nsignals (0), m_nvcsw (0), m_nivcsw (0)\n  {\n    stamp ();\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (resource_usage)\n\n  OCTAVE_API void stamp ();\n\n  cpu_time cpu () const { return m_cpu; }\n\n  long maxrss () const { return m_maxrss; }\n  long ixrss () const { return m_ixrss; }\n  long idrss () const { return m_idrss; }\n  long isrss () const { return m_isrss; }\n  long minflt () const { return m_minflt; }\n  long majflt () const { return m_majflt; }\n  long nswap () const { return m_nswap; }\n  long inblock () const { return m_inblock; }\n  long oublock () const { return m_oublock; }\n  long msgsnd () const { return m_msgsnd; }\n  long msgrcv () const { return m_msgrcv; }\n  long nsignals () const { return m_nsignals; }\n  long nvcsw () const { return m_nvcsw; }\n  long nivcsw () const { return m_nivcsw; }\n\nprivate:\n\n  cpu_time m_cpu;\n\n  long m_maxrss;\n  long m_ixrss;\n  long m_idrss;\n  long m_isrss;\n  long m_minflt;\n  long m_majflt;\n  long m_nswap;\n  long m_inblock;\n  long m_oublock;\n  long m_msgsnd;\n  long m_msgrcv;\n  long m_nsignals;\n  long m_nvcsw;\n  long m_nivcsw;\n};\n\n// class to handle file time efficiently on different platforms\n\nclass OCTAVE_API file_time\n{\npublic:\n\n  file_time ();\n\n  file_time (OCTAVE_TIME_T t)\n    : m_time (t)\n  { }\n\n  file_time (const std::string& filename);\n\n  file_time (const file_time& ot)\n  {\n    m_time = ot.time ();\n  }\n\n  file_time& operator = (const file_time& ot)\n  {\n    if (this != &ot)\n      m_time = ot.time ();\n\n    return *this;\n  }\n\n  ~file_time () = default;\n\n  inline static file_time time_resolution ()\n  {\n#if defined (OCTAVE_USE_WINDOWS_API)\n    // FAT file systems have 2 seconds resolution for the modification time.\n    static OCTAVE_TIME_T time_resolution = 20000000;\n#else\n    // Assume 1 second (see file_stat)\n    static OCTAVE_TIME_T time_resolution = 1;\n#endif\n    return time_resolution;\n  }\n\n  inline bool\n  operator == (const file_time& t2) const\n  {\n    return time () == t2.time ();\n  }\n\n  inline bool\n  operator != (const file_time& t2) const\n  {\n    return ! (*this == t2);\n  }\n\n  inline bool\n  operator < (const file_time& t2) const\n  {\n    return time () < t2.time ();\n  }\n\n  inline bool\n  operator <= (const file_time& t2) const\n  {\n    return (*this < t2 || *this == t2);\n  }\n\n  inline bool\n  operator > (const file_time& t2) const\n  {\n    return time () > t2.time ();\n  }\n\n  inline bool\n  operator >= (const file_time& t2) const\n  {\n    return (*this > t2 || *this == t2);\n  }\n\n  inline file_time\n  operator + (const file_time& t2) const\n  {\n    return file_time (time () + t2.time ());\n  }\n\n  inline file_time\n  operator + (const OCTAVE_TIME_T t2) const\n  {\n    return file_time (time () + t2);\n  }\n\n  OCTAVE_TIME_T time () const { return m_time; }\n\nprivate:\n\n  // The native file time type differs per platform.\n  // On POSIX, this is the number of 1 second intervals since the epoch.\n  // On Windows, this is the number of 100 ns intervals since a different epoch.\n  OCTAVE_TIME_T m_time;\n};\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/system/oct-uname.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n#include <cstring>\n\n#include \"oct-uname.h\"\n#include \"uname-wrapper.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nvoid\nuname::init ()\n{\n  char *sysname, *nodename, *release, *version, *machine;\n\n  m_errno = octave_uname_wrapper (&sysname, &nodename, &release,\n                                  &version, &machine);\n\n  if (m_errno < 0)\n    m_errmsg = std::strerror (errno);\n  else\n    {\n      m_sysname = sysname;\n      m_nodename = nodename;\n      m_release = release;\n      m_version = version;\n      m_machine = machine;\n      m_errmsg = \"\";\n    }\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/system/oct-uname.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_uname_h)\n#define octave_oct_uname_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nclass OCTAVE_API uname\n{\npublic:\n\n  uname ()\n    : m_sysname (\"unknown\"), m_nodename (\"unknown\"),\n      m_release (\"unknown\"), m_version (\"unknown\"),\n      m_machine (\"unknown\"),\n      m_errmsg (\"uname not supported on this system\"), m_errno (-1)\n  { init (); }\n\n  uname (const uname& unm)\n    : m_sysname (unm.m_sysname), m_nodename (unm.m_nodename),\n      m_release (unm.m_release), m_version (unm.m_version),\n      m_machine (unm.m_machine),\n      m_errmsg (unm.m_errmsg), m_errno (unm.m_errno)\n  { }\n\n  uname& operator = (const uname& unm)\n  {\n    if (this != &unm)\n      {\n        m_sysname = unm.m_sysname;\n        m_nodename = unm.m_nodename;\n        m_release = unm.m_release;\n        m_version = unm.m_version;\n        m_machine = unm.m_machine;\n\n        m_errmsg = unm.m_errmsg;\n        m_errno = unm.m_errno;\n      }\n\n    return *this;\n  }\n\n  ~uname () = default;\n\n  std::string sysname () const { return m_sysname; }\n  std::string nodename () const { return m_nodename; }\n  std::string release () const { return m_release; }\n  std::string version () const { return m_version; }\n  std::string machine () const { return m_machine; }\n\n  std::string message () const { return m_errmsg; }\n  int error () const { return m_errno; }\n\nprivate:\n\n  std::string m_sysname;\n  std::string m_nodename;\n  std::string m_release;\n  std::string m_version;\n  std::string m_machine;\n\n  std::string m_errmsg;\n  int m_errno;\n\n  void init ();\n};\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/action-container.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"action-container.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid action_container::run (std::size_t num)\n{\n  if (num > size ())\n    num = size ();\n\n  for (std::size_t i = 0; i < num; i++)\n    run_first ();\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/action-container.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_action_container_h)\n#define octave_action_container_h 1\n\n#include \"octave-config.h\"\n\n#include <atomic>\n#include <cstddef>\n#include <functional>\n\n// This class allows registering actions in a list for later\n// execution, either explicitly or when the container goes out of\n// scope.\n\n// FIXME: is there a better name for this class?\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(util)\n\ntemplate <typename T>\nstruct atomic_traits\n{\n  typedef T type;\n};\n\ntemplate <typename T>\nstruct atomic_traits<std::atomic<T>>\n{\n  typedef T type;\n};\n\nOCTAVE_END_NAMESPACE(util)\n\nclass action_container\n{\npublic:\n\n  // A generic unwind_protect element.  Knows how to run itself and\n  // discard itself.  Also, contains a pointer to the next element.\n  class elem\n  {\n  public:\n\n    friend class action_container;\n\n    elem () { }\n\n    OCTAVE_DISABLE_COPY_MOVE (elem)\n\n    virtual ~elem () = default;\n\n    virtual void run () { }\n  };\n\n  // An element that merely runs a void (*)() function.\n\n  class fcn_elem : public elem\n  {\n  public:\n\n    // FIXME: Do we need to apply std::forward to the arguments to\n    // std::bind here?\n\n    template <typename F, typename... Args>\n    fcn_elem (F&& fcn, Args&& ... args)\n      : m_fcn (std::bind (fcn, args...))\n    { }\n\n    void run () { m_fcn (); }\n\n  private:\n\n    std::function<void ()> m_fcn;\n  };\n\n  // An element that stores arbitrary variable, and restores it.\n\n  template <typename T>\n  class restore_var_elem : public elem\n  {\n  public:\n\n    restore_var_elem (T& ref, const T& val)\n      : m_ptr (&ref), m_val (val) { }\n\n    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (restore_var_elem)\n\n    ~restore_var_elem () = default;\n\n    void run () { *m_ptr = m_val; }\n\n  private:\n\n    T *m_ptr;\n    typename util::atomic_traits<T>::type m_val;\n  };\n\n  // Deletes a class allocated using new.\n\n  template <typename T>\n  class delete_ptr_elem : public elem\n  {\n  public:\n\n    delete_ptr_elem (T *ptr)\n      : m_ptr (ptr) { }\n\n    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (delete_ptr_elem)\n\n    ~delete_ptr_elem () = default;\n\n    void run () { delete m_ptr; }\n\n  private:\n\n    T *m_ptr;\n  };\n\n  action_container () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (action_container)\n\n  virtual ~action_container () = default;\n\n  template <typename F, typename... Args>\n  void add (F&& fcn, Args&& ... args)\n  {\n    add_action (new fcn_elem (std::forward<F> (fcn),\n                              std::forward<Args> (args)...));\n  }\n\n  // Use separate template types for function pointer parameter\n  // declarations and captured arguments so that differences in\n  // const are handled properly.\n\n  template <typename... Params, typename... Args>\n  void add_fcn (void (*fcn) (Params...), Args&& ... args)\n  {\n    add_action (new fcn_elem (fcn, std::forward<Args> (args)...));\n  }\n\n  template <typename T, typename... Params, typename... Args>\n  void add_method (T *obj, void (T::*method) (Params...), Args&& ... args)\n  {\n    add_action (new fcn_elem (method, obj, std::forward<Args> (args)...));\n  }\n\n  template <typename T, typename... Params, typename... Args>\n  void add_method (T& obj, void (T::*method) (Params...), Args&& ... args)\n  {\n    add_action (new fcn_elem (method, &obj, std::forward<Args> (args)...));\n  }\n\n  // Call to delete (T*).\n\n  template <typename T>\n  void add_delete (T *obj)\n  {\n    add_action (new delete_ptr_elem<T> (obj));\n  }\n\n  // Protect any variable.\n  template <typename T>\n  void protect_var (T& var)\n  {\n    add_action (new restore_var_elem<T> (var, var));\n  }\n\n  // Protect any variable, value given.\n  template <typename T>\n  void protect_var (T& var, const T& val)\n  {\n    add_action (new restore_var_elem<T> (var, val));\n  }\n\n  operator bool () const { return ! empty (); }\n\n  virtual void run_first () = 0;\n\n  OCTAVE_API void run (std::size_t num);\n\n  void run () { run (size ()); }\n\n  virtual void discard_first () = 0;\n\n  void discard (std::size_t num)\n  {\n    if (num > size ())\n      num = size ();\n\n    for (std::size_t i = 0; i < num; i++)\n      discard_first ();\n  }\n\n  void discard () { discard (size ()); }\n\n  virtual std::size_t size () const = 0;\n\n  bool empty () const { return size () == 0; }\n\nprotected:\n\n  virtual void add_action (elem *new_elem) = 0;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/base-list.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_base_list_h)\n#define octave_base_list_h 1\n\n#include \"octave-config.h\"\n\n#warning \"using <base-list.h> is discouraged - use <list> instead\"\n\n#include <cstdlib>\n\n#include <list>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename elt_type>\nclass base_list\n{\npublic:\n\n  typedef typename std::list<elt_type>::iterator iterator;\n  typedef typename std::list<elt_type>::const_iterator const_iterator;\n\n  typedef typename std::list<elt_type>::reverse_iterator reverse_iterator;\n  typedef typename std::list<elt_type>::const_reverse_iterator\n    const_reverse_iterator;\n\n  bool empty () const { return m_lst.empty (); }\n\n  std::size_t size () const { return m_lst.size (); }\n  std::size_t length () const { return size (); }\n\n  iterator erase (iterator pos) { return m_lst.erase (pos); }\n\n  template <typename P>\n  void remove_if (P pred)\n  {\n    m_lst.remove_if (pred);\n  }\n\n  void clear () { m_lst.clear (); }\n\n  iterator begin () { return iterator (m_lst.begin ()); }\n  const_iterator begin () const { return const_iterator (m_lst.begin ()); }\n\n  iterator end () { return iterator (m_lst.end ()); }\n  const_iterator end () const { return const_iterator (m_lst.end ()); }\n\n  reverse_iterator rbegin () { return reverse_iterator (m_lst.rbegin ()); }\n  const_reverse_iterator rbegin () const\n  { return const_reverse_iterator (m_lst.rbegin ()); }\n\n  reverse_iterator rend () { return reverse_iterator (m_lst.rend ()); }\n  const_reverse_iterator rend () const\n  { return const_reverse_iterator (m_lst.rend ()); }\n\n  elt_type& front () { return m_lst.front (); }\n  elt_type& back () { return m_lst.back (); }\n\n  const elt_type& front () const { return m_lst.front (); }\n  const elt_type& back () const { return m_lst.back (); }\n\n  void push_front (const elt_type& s) { m_lst.push_front (s); }\n  void push_back (const elt_type& s) { m_lst.push_back (s); }\n\n  void pop_front () { m_lst.pop_front (); }\n  void pop_back () { m_lst.pop_back (); }\n\n  // For backward compatibility.\n  void append (const elt_type& s) { m_lst.push_back (s); }\n\n  base_list () = default;\n\n  base_list (const std::list<elt_type>& l) : m_lst (l) { }\n\n  base_list (const base_list& bl) = default;\n\n  base_list& operator = (const base_list& bl) = default;\n\n  virtual ~base_list () = default;\n\nprotected:\n\n  std::list<elt_type> m_lst;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/blaswrap.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nWrapper for Apple libBLAS.dylib and libLAPACK.dylib\n\nAt least on the versions of OSX 10.6 so far (up and including 10.6.6)\nthese libraries are incompatible with 64 bit builds, as some functions\nin libBLAS.dylib are not conforming to F2C calling conventions, as\nthey should.  This breaks them in 64-bit builds on the x86_64\narchitecture.\n\nNewer gfortran compilers no longer default to the F2C calling\nconvention.  These wrappers map the F2C conformant functions in\nlibBLAS and libLAPACK to the native gfortran calling convention, so\nthat the libraries can be used with software built for x86_64\narchitecture.\n\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\" /* USE_BLASWRAP ? */\n#endif\n\n#if defined (USE_BLASWRAP)\n\n/*\n * vecLib is an Apple framework (collection of libraries) containing\n * libBLAS and libLAPACK.  The fortran stubs in these libraries are\n * (mostly, but not completely) in the F2C calling convention.\n * We access the libraries via the vecLib framework to make sure we\n * get the Apple versions, rather than some other blas/lapack with the\n * same name.\n */\n#if ! defined (VECLIB_FILE)\n#  define VECLIB_FILE \"/System/Library/Frameworks/vecLib.framework/Versions/A/vecLib\"\n#endif\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n/*\n * Since this is a wrapper for fortran functions,\n * we do not have prototypes for them.\n */\n#  pragma GCC diagnostic ignored \"-Wmissing-prototypes\"\n#endif\n\n#include <dlfcn.h>\n#include <stdlib.h>\n\n/*\n * Apple LAPACK follows F2C calling convention,\n * Convert to normal gfortran calling convention\n */\n\nstatic void (*f2c_blas_func[]) (void);   /* forward declaration for wrapper */\nstatic void (*f2c_lapack_func[]) (void); /* forward declaration for wrapper */\n\n/*\n * LAPACK Wrappers, only need to convert the return value from double to float\n */\n\ntypedef double (*F2C_CALL_0) (void);\ntypedef double (*F2C_CALL_1) (void *a1);\ntypedef double (*F2C_CALL_2) (void *a1, void *a2);\ntypedef double (*F2C_CALL_3) (void *a1, void *a2, void *a3);\ntypedef double (*F2C_CALL_4) (void *a1, void *a2, void *a3, void *a4);\ntypedef double (*F2C_CALL_5) (void *a1, void *a2, void *a3, void *a4, void *a5);\ntypedef double (*F2C_CALL_6) (void *a1, void *a2, void *a3, void *a4, void *a5,\n                              void *a6);\ntypedef double (*F2C_CALL_7) (void *a1, void *a2, void *a3, void *a4, void *a5,\n                              void *a6, void *a7);\ntypedef double (*F2C_CALL_8) (void *a1, void *a2, void *a3, void *a4, void *a5,\n                              void *a6, void *a7, void *a8);\n\n#define F2C_LAPACK_CALL_8(name) \\\n  float name (void *a1, void *a2, void *a3, void *a4, void *a5, void *a6, void *a7, void *a8) \\\n  {                                                                     \\\n    return ((F2C_CALL_8)f2c_lapack_func[f2c_ ## name]) (a1, a2, a3, a4, a5, a6, a7, a8); \\\n  }\n\n#define F2C_LAPACK_CALL_7(name) \\\n  float name (void *a1, void *a2, void *a3, void *a4, void *a5, void *a6, void *a7) \\\n  {                                                                     \\\n    return ((F2C_CALL_7)f2c_lapack_func[f2c_ ## name]) (a1, a2, a3, a4, a5, a6, a7); \\\n  }\n\n#define F2C_LAPACK_CALL_6(name) \\\n  float name (void *a1, void *a2, void *a3, void *a4, void *a5, void *a6) \\\n  {                                                                     \\\n    return ((F2C_CALL_6)f2c_lapack_func[f2c_ ## name]) (a1, a2, a3, a4, a5, a6); \\\n  }\n\n#define F2C_LAPACK_CALL_5(name) \\\n  float name (void *a1, void *a2, void *a3, void *a4, void *a5)         \\\n  {                                                                     \\\n    return ((F2C_CALL_5)f2c_lapack_func[f2c_ ## name]) (a1, a2, a3, a4, a5); \\\n  }\n\n#define F2C_LAPACK_CALL_4(name) \\\n  float name (void *a1, void *a2, void *a3, void *a4)                   \\\n  {                                                                     \\\n    return ((F2C_CALL_4)f2c_lapack_func[f2c_ ## name]) (a1, a2, a3, a4); \\\n  }\n\n#define F2C_LAPACK_CALL_3(name) \\\n  float name (void *a1, void *a2, void *a3)                          \\\n  {                                                                  \\\n    return ((F2C_CALL_3)f2c_lapack_func[f2c_ ## name]) (a1, a2, a3); \\\n  }\n\n#define F2C_LAPACK_CALL_2(name) \\\n  float name (void *a1, void *a2)                                \\\n  {                                                              \\\n    return ((F2C_CALL_2)f2c_lapack_func[f2c_ ## name]) (a1, a2); \\\n  }\n\n#define F2C_LAPACK_CALL_1(name) \\\n  float name (void *a1)                                      \\\n  {                                                          \\\n    return ((F2C_CALL_1)f2c_lapack_func[f2c_ ## name]) (a1); \\\n  }\n\n#define F2C_LAPACK_CALL_0(name) \\\n  float name (void)                                        \\\n  {                                                        \\\n    return ((F2C_CALL_0)f2c_lapack_func[f2c_ ## name]) (); \\\n  }\n\n#define F2C_LAPACK_CALL_NONE(name)\n\n#define F2C_LAPACK_CALL(name, args) F2C_LAPACK_CALL_ ## args (name)\n\n#define ENUM_ITEM(name, args)                   \\\n  f2c_ ## name,\n\n#define NAME_TO_STRING_CASE(name, args)         \\\n  case f2c_ ## name: return #name;\n\n#define DEFINE_LAPACK_ENUM(name, list)  \\\n  typedef enum {                        \\\n    list(ENUM_ITEM)                     \\\n  } name;                               \\\n  static const char*                    \\\n  f2c_ ## name ## _name (name n) {      \\\n    switch (n) {                        \\\n      list(NAME_TO_STRING_CASE)         \\\n    default: return \"\";                 \\\n    }                                   \\\n  }                                     \\\n  list(F2C_LAPACK_CALL)\n\n#define DEFINE_BLAS_ENUM(name, list)    \\\n  typedef enum {                        \\\n    list(ENUM_ITEM)                     \\\n  } name;                               \\\n  static const char*                    \\\n  f2c_ ## name ## _name(name n) {       \\\n    switch (n) {                        \\\n      list(NAME_TO_STRING_CASE)         \\\n    default: return \"\";                 \\\n    }                                   \\\n  }\n\n/*\n * Lapack functions (with argument count) that need the return value\n * converted from double to float\n */\n#define LAPACK_LIST(_)  \\\n  _(clangb_,7)          \\\n  _(clange_,6)          \\\n  _(clangt_,5)          \\\n  _(clanhb_,7)          \\\n  _(clanhe_,6)          \\\n  _(clanhp_,5)          \\\n  _(clanhs_,5)          \\\n  _(clanht_,4)          \\\n  _(clansb_,7)          \\\n  _(clansp_,5)          \\\n  _(clansy_,6)          \\\n  _(clantb_,8)          \\\n  _(clantp_,6)          \\\n  _(clantr_,8)          \\\n  _(scsum1_,3)          \\\n  _(second_,0)          \\\n  _(slamc3_,2)          \\\n  _(slamch_,1)          \\\n  _(slangb_,7)          \\\n  _(slange_,6)          \\\n  _(slangt_,5)          \\\n  _(slanhs_,5)          \\\n  _(slansb_,7)          \\\n  _(slansp_,5)          \\\n  _(slanst_,4)          \\\n  _(slansy_,6)          \\\n  _(slantb_,8)          \\\n  _(slantp_,6)          \\\n  _(slantr_,8)          \\\n  _(slapy2_,2)          \\\n  _(slapy3_,3)          \\\n  _(LAPACK_COUNT,NONE)\n\n/*\n * These need a bit more complex wrappers\n */\n#define BLAS_LIST(_)    \\\n  _(cdotu_,6)           \\\n  _(zdotu_,6)           \\\n  _(cdotc_,6)           \\\n  _(zdotc_,6)           \\\n  _(BLAS_COUNT,NONE)\n\nDEFINE_BLAS_ENUM(blas, BLAS_LIST)\n\nDEFINE_LAPACK_ENUM(lapack, LAPACK_LIST)\n\n/*\n * BLAS wrappers, F2C convention passes returned complex as an extra first\n * argument\n */\ntypedef struct { float r, i; } complex;\ntypedef struct { double r, i; } doublecomplex;\n\ntypedef void (*F2C_BLAS_CALL_6) (void *c, void *a1, void *a2, void *a3,\n                                 void *a4, void *a5);\n\n#define F2C_BLAS_CALL(type, name) \\\ntype name (void *a1, void *a2, void *a3, void *a4, void *a5) \\\n{ \\\n  type cplx; \\\n  ((F2C_BLAS_CALL_6)f2c_blas_func[f2c_ ## name]) (&cplx, a1, a2, a3, a4, a5); \\\n  return cplx; \\\n}\n\nF2C_BLAS_CALL(complex, cdotu_)\nF2C_BLAS_CALL(doublecomplex, zdotu_)\nF2C_BLAS_CALL(complex, cdotc_)\nF2C_BLAS_CALL(doublecomplex, zdotc_)\n\n/*\n * Function pointer arrays, indexed by the enums\n */\nstatic void (*f2c_blas_func[f2c_BLAS_COUNT]) (void) = { 0 };\nstatic void (*f2c_lapack_func[f2c_LAPACK_COUNT]) (void) = { 0 };\n\n/*\n * Initialization: This is called before main ().\n * Get the function pointers to the wrapped functions in Apple vecLib\n */\n\nstatic void * apple_vecLib = 0;\n\n__attribute__((constructor))\nstatic void initVecLibWrappers (void)\n{\n  apple_vecLib = dlopen (VECLIB_FILE, RTLD_LOCAL | RTLD_NOLOAD | RTLD_FIRST);\n  if (0 == apple_vecLib)\n    abort ();\n\n  int i;\n  for (i = 0; i < f2c_LAPACK_COUNT; i++)\n    if (0 == (f2c_lapack_func[i] = dlsym (apple_vecLib, f2c_lapack_name(i))))\n      abort ();\n  for (i = 0; i < f2c_BLAS_COUNT; i++)\n    if (0 == (f2c_blas_func[i] = dlsym (apple_vecLib, f2c_blas_name(i))))\n      abort ();\n}\n\n__attribute__((destructor))\nstatic void finiVecLibWrappers (void)\n{\n  if (apple_vecLib)\n    dlclose (apple_vecLib);\n  apple_vecLib = 0;\n}\n\n#endif /* USE_BLASWRAP */\n"
  },
  {
    "path": "liboctave/util/byte-swap.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_byte_swap_h)\n#define octave_byte_swap_h 1\n\n#include \"octave-config.h\"\n\nstatic inline void\nswap_bytes (void *ptr, unsigned int i, unsigned int j)\n{\n  char *t = static_cast<char *> (ptr);\n\n  char tmp = t[i];\n  t[i] = t[j];\n  t[j] = tmp;\n}\n\ntemplate <int n>\nvoid\nswap_bytes (void *ptr)\n{\n  for (int i = 0; i < n/2; i++)\n    swap_bytes (ptr, i, n-1-i);\n}\n\ntemplate <>\ninline void\nswap_bytes<1> (void *)\n{ }\n\ntemplate <>\ninline void\nswap_bytes<2> (void *ptr)\n{\n  swap_bytes (ptr, 0, 1);\n}\n\ntemplate <>\ninline void\nswap_bytes<4> (void *ptr)\n{\n  swap_bytes (ptr, 0, 3);\n  swap_bytes (ptr, 1, 2);\n}\n\ntemplate <>\ninline void\nswap_bytes<8> (void *ptr)\n{\n  swap_bytes (ptr, 0, 7);\n  swap_bytes (ptr, 1, 6);\n  swap_bytes (ptr, 2, 5);\n  swap_bytes (ptr, 3, 4);\n}\n\ntemplate <int n>\nvoid\nswap_bytes (void *ptr, int len)\n{\n  char *t = static_cast<char *> (ptr);\n\n  for (int i = 0; i < len; i++)\n    {\n      swap_bytes<n> (t);\n      t += n;\n    }\n}\n\ntemplate <>\ninline void\nswap_bytes<1> (void *, int)\n{ }\n\n#endif\n"
  },
  {
    "path": "liboctave/util/caseless-str.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_caseless_str_h)\n#define octave_caseless_str_h 1\n\n#include \"octave-config.h\"\n\n#include <cctype>\n#include <string>\n\nclass caseless_str : public std::string\n{\npublic:\n\n  typedef std::string::iterator iterator;\n  typedef std::string::const_iterator const_iterator;\n\n  caseless_str () = default;\n\n  caseless_str (const std::string& s) : std::string (s) { }\n  caseless_str (const char *s) : std::string (s) { }\n\n  caseless_str (const caseless_str&) = default;\n\n  caseless_str& operator = (const caseless_str&) = default;\n\n  ~caseless_str () = default;\n\n  bool operator < (const std::string& s) const\n  {\n    auto p1 = begin ();\n    auto p2 = s.begin ();\n\n    while (p1 != end () && p2 != s.end ())\n      {\n        char lp1 = std::tolower (*p1);\n        char lp2 = std::tolower (*p2);\n\n        if (lp1 > lp2)\n          return false;\n        if (lp1 < lp2)\n          return true;\n\n        p1++;\n        p2++;\n      }\n\n    if (length () >= s.length ())\n      return false;\n    else\n      return true;\n  }\n\n  // Case-insensitive comparison.\n  bool compare (const std::string& s, std::size_t limit = std::string::npos) const\n  {\n    auto p1 = begin ();\n    auto p2 = s.begin ();\n\n    std::size_t k = 0;\n\n    while (p1 != end () && p2 != s.end () && k++ < limit)\n      {\n        if (std::tolower (*p1) != std::tolower (*p2))\n          return false;\n\n        p1++;\n        p2++;\n      }\n\n    return (limit == std::string::npos) ? size () == s.size () : k == limit;\n  }\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/util/d1mach-tst.for",
    "content": "c Copyright (C) 1996-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      program main\n      integer i\n      double precision d1mach\n      double precision t1, t2\n      do 10 i = 1, 5\n        print *, d1mach (i)\n   10 continue\n      end\n"
  },
  {
    "path": "liboctave/util/d1mach.f",
    "content": "c Copyright (C) 1996-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      double precision function d1mach (i)\n      integer i\n      logical init\n      double precision dmach(5)\n      double precision dlamch\n      external dlamch\n      save init, dmach\n      data init /.false./\n      if (.not. init) then\n        dmach(1) = dlamch ('u')\n        dmach(2) = dlamch ('o')\n        dmach(3) = dlamch ('e')\n        dmach(4) = dlamch ('p')\n        dmach(5) = log10 (dlamch ('b'))\n        init = .true.\n      endif\n      if (i .lt. 1 .or. i .gt. 5) goto 999\n      d1mach = dmach(i)\n      return\n  999 write (*, 1999) i\n 1999 format (' d1mach - i out of bounds', i10)\n      call xstopx (' ')\n      d1mach = 0\n      end\n"
  },
  {
    "path": "liboctave/util/data-conv.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cctype>\n#include <cstdlib>\n\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"byte-swap.h\"\n#include \"data-conv.h\"\n#include \"lo-ieee.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n\n// FIXME: Almost all platform-dependent sizes such as \"short\" are now defined\n// to take fixed values (such as 2B).  This was instigated for Matlab\n// compatibility (bug #41672).  It means a lot of this code is probably\n// obsolete and could be pared down or removed entirely.\n\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\n#  define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q)                         \\\n  do                                                                    \\\n    {                                                                   \\\n      int sz = BITS / std::numeric_limits<unsigned char>::digits;       \\\n      if (sizeof (TQ char) == sz)                                       \\\n        VAL = oct_data_conv::dt_ ## Q ## char;                          \\\n      else if (sizeof (TQ short) == sz)                                 \\\n        VAL = oct_data_conv::dt_ ## Q ## short;                         \\\n      else if (sizeof (TQ int) == sz)                                   \\\n        VAL = oct_data_conv::dt_ ## Q ## int;                           \\\n      else if (sizeof (TQ long) == sz)                                  \\\n        VAL = oct_data_conv::dt_ ## Q ## long;                          \\\n      else if (sizeof (TQ long long) == sz)                             \\\n        VAL = oct_data_conv::dt_ ## Q ## longlong;                      \\\n      else                                                              \\\n        VAL = oct_data_conv::dt_unknown;                                \\\n    }                                                                   \\\n  while (0)\n#else\n#  define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q)                         \\\n  do                                                                    \\\n    {                                                                   \\\n      int sz = BITS / std::numeric_limits<unsigned char>::digits;       \\\n      if (sizeof (TQ char) == sz)                                       \\\n        VAL = oct_data_conv::dt_ ## Q ## char;                          \\\n      else if (sizeof (TQ short) == sz)                                 \\\n        VAL = oct_data_conv::dt_ ## Q ## short;                         \\\n      else if (sizeof (TQ int) == sz)                                   \\\n        VAL = oct_data_conv::dt_ ## Q ## int;                           \\\n      else if (sizeof (TQ long) == sz)                                  \\\n        VAL = oct_data_conv::dt_ ## Q ## long;                          \\\n      else                                                              \\\n        VAL = oct_data_conv::dt_unknown;                                \\\n    }                                                                   \\\n  while (0)\n#endif\n\n#define FIND_SIZED_FLOAT_TYPE(VAL, BITS)                                \\\n  do                                                                    \\\n    {                                                                   \\\n      int sz = BITS / std::numeric_limits<unsigned char>::digits;       \\\n      if (sizeof (float) == sz)                                         \\\n        VAL = oct_data_conv::dt_float;                                  \\\n      else if (sizeof (double) == sz)                                   \\\n        VAL = oct_data_conv::dt_double;                                 \\\n      else                                                              \\\n        VAL = oct_data_conv::dt_unknown;                                \\\n    }                                                                   \\\n  while (0)\n\n// I'm not sure it is worth the trouble, but let's use a lookup table\n// for the types that are supposed to be a specific number of bits\n// wide.  Given the macros above, this should work as long as\n// std::numeric_limits<unsigned char>::digits is a multiple of 8 and\n// there are types with the right sizes.\n//\n// The sized data type lookup table has the following format:\n//\n//                            bits\n//                    +----+----+----+----+\n//                    |  8 | 16 | 32 | 64 |\n//                    +----+----+----+----+\n//     signed integer |    |    |    |    |\n//                    +----+----+----+----+\n//   unsigned integer |    |    |    |    |\n//                    +----+----+----+----+\n//     floating point |    |    |    |    |\n//                    +----+----+----+----+\n//\n// So, the 0,3 element is supposed to contain the oct_data_conv enum\n// value corresponding to the correct native data type for a signed\n// 32-bit integer.\n\nstatic void\ninit_sized_type_lookup_table (oct_data_conv::data_type table[3][4])\n{\n  int bits = 8;\n\n  for (int i = 0; i < 4; i++)\n    {\n      FIND_SIZED_INT_TYPE (table[0][i], bits, , );\n\n      FIND_SIZED_INT_TYPE (table[1][i], bits, unsigned, u);\n\n      FIND_SIZED_FLOAT_TYPE (table[2][i], bits);\n\n      bits *= 2;\n    }\n}\n\nstatic std::string\nstrip_spaces (const std::string& str)\n{\n  std::size_t n = str.length ();\n\n  std::size_t k = 0;\n\n  std::string s (n, '\\0');\n\n  for (std::size_t i = 0; i < n; i++)\n    if (! isspace (str[i]))\n      s[k++] = tolower (str[i]);\n\n  s.resize (k);\n\n  return s;\n}\n\n#define GET_SIZED_INT_TYPE(T, U)                \\\n  do                                            \\\n    {                                           \\\n      switch (sizeof (T))                       \\\n        {                                       \\\n        case 1:                                 \\\n          retval = dt_ ## U ## int8;            \\\n          break;                                \\\n                                                \\\n        case 2:                                 \\\n          retval = dt_ ## U ## int16;           \\\n          break;                                \\\n                                                \\\n        case 4:                                 \\\n          retval = dt_ ## U ## int32;           \\\n          break;                                \\\n                                                \\\n        case 8:                                 \\\n          retval = dt_ ## U ## int64;           \\\n          break;                                \\\n                                                \\\n        default:                                \\\n          retval = dt_unknown;                  \\\n          break;                                \\\n        }                                       \\\n    }                                           \\\n  while (0)\n\nstd::size_t\noct_data_conv::data_type_size (data_type dt)\n{\n  std::size_t retval = -1;\n\n  switch (dt)\n    {\n    case oct_data_conv::dt_int8:\n      retval = sizeof (int8_t);\n      break;\n\n    case oct_data_conv::dt_uint8:\n      retval = sizeof (uint8_t);\n      break;\n\n    case oct_data_conv::dt_int16:\n      retval = sizeof (int16_t);\n      break;\n\n    case oct_data_conv::dt_uint16:\n      retval = sizeof (uint16_t);\n      break;\n\n    case oct_data_conv::dt_int32:\n      retval = sizeof (int32_t);\n      break;\n\n    case oct_data_conv::dt_uint32:\n      retval = sizeof (uint32_t);\n      break;\n\n    case oct_data_conv::dt_int64:\n      retval = sizeof (int64_t);\n      break;\n\n    case oct_data_conv::dt_uint64:\n      retval = sizeof (uint64_t);\n      break;\n\n    case oct_data_conv::dt_float:\n    case oct_data_conv::dt_single:\n      retval = sizeof (float);\n      break;\n\n    case oct_data_conv::dt_double:\n      retval = sizeof (double);\n      break;\n\n    case oct_data_conv::dt_char:\n      retval = sizeof (char);\n      break;\n\n    case oct_data_conv::dt_schar:\n      retval = sizeof (signed char);\n      break;\n\n    case oct_data_conv::dt_uchar:\n      retval = sizeof (unsigned char);\n      break;\n\n    case oct_data_conv::dt_short:\n      retval = sizeof (short);\n      break;\n\n    case oct_data_conv::dt_ushort:\n      retval = sizeof (unsigned short);\n      break;\n\n    case oct_data_conv::dt_int:\n      retval = sizeof (int);\n      break;\n\n    case oct_data_conv::dt_uint:\n      retval = sizeof (unsigned int);\n      break;\n\n    case oct_data_conv::dt_long:\n      retval = sizeof (long);\n      break;\n\n    case oct_data_conv::dt_ulong:\n      retval = sizeof (unsigned long);\n      break;\n\n    case oct_data_conv::dt_longlong:\n      retval = sizeof (long long);\n      break;\n\n    case oct_data_conv::dt_ulonglong:\n      retval = sizeof (unsigned long long);\n      break;\n\n    case oct_data_conv::dt_logical:\n      retval = sizeof (bool);\n      break;\n\n    case oct_data_conv::dt_unknown:\n    default:\n      (*current_liboctave_error_handler)\n        (\"oct_data_conv::data_type_size: unknown data type\");\n      break;\n    }\n\n  return retval;\n}\n\noct_data_conv::data_type\noct_data_conv::string_to_data_type (const std::string& str)\n{\n  data_type retval = dt_unknown;\n\n  static bool initialized = false;\n\n  static data_type sized_type_table[3][4];\n\n  if (! initialized)\n    {\n      init_sized_type_lookup_table (sized_type_table);\n\n      initialized = true;\n    }\n\n  std::string s = strip_spaces (str);\n\n  // Organized so most frequent precision appears first\n  if (s == \"uint8\")\n    retval = dt_uint8;\n  else if (s == \"double\" || s == \"float64\" || s == \"real*8\")\n    retval = dt_double;\n  else if (s == \"single\" || s == \"float\" || s == \"float32\" || s == \"real*4\")\n    retval = dt_single;\n  else if (s == \"char\" || s == \"char*1\")\n    retval = dt_char;\n  else if (s == \"int\")\n    retval = dt_int32;\n  else if (s == \"uchar\" || s == \"unsignedchar\")\n    retval = dt_uint8;\n  else if (s == \"schar\" || s == \"signedchar\")\n    retval = dt_int8;\n  else if (s == \"int8\" || s == \"integer*1\")\n    retval = dt_int8;\n  else if (s == \"int16\" || s == \"integer*2\")\n    retval = dt_int16;\n  else if (s == \"uint16\")\n    retval = dt_uint16;\n  else if (s == \"int32\" || s == \"integer*4\")\n    retval = dt_int32;\n  else if (s == \"uint32\")\n    retval = dt_uint32;\n  else if (s == \"int64\" || s == \"integer*8\")\n    retval = dt_int64;\n  else if (s == \"uint64\")\n    retval = dt_uint64;\n  else if (s == \"short\")\n    retval = dt_int16;\n  else if (s == \"ushort\" || s == \"unsignedshort\")\n    retval = dt_uint16;\n  else if (s == \"uint\" || s == \"unsignedint\")\n    retval = dt_uint32;\n  else if (s == \"long\")\n    retval = dt_int32;\n  else if (s == \"ulong\" || s == \"unsignedlong\")\n    retval = dt_uint32;\n  // FIXME: The following are undocumented precisions\n  else if (s == \"longlong\")\n    GET_SIZED_INT_TYPE (long long, );\n  else if (s == \"ulonglong\" || s == \"unsignedlonglong\")\n    GET_SIZED_INT_TYPE (unsigned long long, u);\n  else if (s == \"logical\")\n    retval = dt_logical;\n  else\n    (*current_liboctave_error_handler) (\"invalid data type specified\");\n\n  if (retval == dt_unknown)\n    (*current_liboctave_error_handler)\n      (\"unable to find matching native data type for %s\", s.c_str ());\n\n  return retval;\n}\n\nvoid\noct_data_conv::string_to_data_type (const std::string& str, int& block_size,\n                                    oct_data_conv::data_type& input_type,\n                                    oct_data_conv::data_type& output_type)\n{\n  block_size = 1;\n  input_type = dt_uchar;\n  output_type = dt_double;\n\n  bool input_is_output = false;\n\n  std::string s = strip_spaces (str);\n\n  std::size_t pos = 0;\n\n  if (s[0] == '*')\n    input_is_output = true;\n  else\n    {\n      std::size_t len = s.length ();\n\n      while (pos < len && isdigit (s[pos]))\n        pos++;\n\n      if (pos > 0)\n        {\n          if (s[pos] == '*')\n            {\n              try\n                {\n                  block_size = std::stoi (s);\n                  s = s.substr (pos+1);\n                }\n              catch (const std::invalid_argument&)\n                {\n                  (*current_liboctave_error_handler)\n                    (\"invalid repeat count in '%s'\", s.c_str ());\n                }\n              catch (const std::out_of_range&)\n                {\n                  (*current_liboctave_error_handler)\n                    (\"repeat count out of range in '%s'\", s.c_str ());\n                }\n            }\n          else\n            (*current_liboctave_error_handler)\n              (\"invalid repeat count in '%s'\", str.c_str ());\n        }\n    }\n\n  pos = s.find ('=');\n\n  if (pos != std::string::npos)\n    {\n      if (s[pos+1] == '>')\n        {\n          std::string s1;\n\n          if (input_is_output)\n            {\n              s1 = s.substr (1, pos-1);\n\n              (*current_liboctave_warning_with_id_handler)\n                (\"Octave:fread-precision-syntax\",\n                 \"warning: ignoring leading * in fread precision\");\n            }\n          else\n            s1 = s.substr (0, pos);\n\n          input_type = string_to_data_type (s1);\n          output_type = string_to_data_type (s.substr (pos+2));\n        }\n      else\n        (*current_liboctave_error_handler)\n          (\"fread: invalid precision specified\");\n    }\n  else\n    {\n      if (input_is_output)\n        s = s.substr (1);\n\n      input_type = string_to_data_type (s);\n\n      if (input_is_output)\n        output_type = input_type;\n    }\n}\n\nvoid\noct_data_conv::string_to_data_type (const std::string& str, int& block_size,\n                                    oct_data_conv::data_type& output_type)\n{\n  block_size = 1;\n  output_type = dt_double;\n\n  std::string s = strip_spaces (str);\n\n  std::size_t pos = 0;\n\n  std::size_t len = s.length ();\n\n  while (pos < len && isdigit (s[pos]))\n    pos++;\n\n  if (pos > 0)\n    {\n      if (s[pos] == '*')\n        {\n          try\n            {\n              block_size = std::stoi (s);\n              s = s.substr (pos+1);\n            }\n          catch (const std::invalid_argument&)\n            {\n              (*current_liboctave_error_handler)\n                (\"invalid repeat count in '%s'\", s.c_str ());\n            }\n          catch (const std::out_of_range&)\n            {\n              (*current_liboctave_error_handler)\n                (\"repeat count out of range in '%s'\", s.c_str ());\n            }\n        }\n      else\n        (*current_liboctave_error_handler)\n          (\"invalid repeat count in '%s'\", str.c_str ());\n    }\n\n  output_type = string_to_data_type (s);\n}\n\nstd::string\noct_data_conv::data_type_as_string (oct_data_conv::data_type dt)\n{\n  std::string retval;\n\n  switch (dt)\n    {\n    case oct_data_conv::dt_int8:\n      retval = \"int8\";\n      break;\n\n    case oct_data_conv::dt_uint8:\n      retval = \"uint8\";\n      break;\n\n    case oct_data_conv::dt_int16:\n      retval = \"int16\";\n      break;\n\n    case oct_data_conv::dt_uint16:\n      retval = \"uint16\";\n      break;\n\n    case oct_data_conv::dt_int32:\n      retval = \"int32\";\n      break;\n\n    case oct_data_conv::dt_uint32:\n      retval = \"uint32\";\n      break;\n\n    case oct_data_conv::dt_int64:\n      retval = \"int64\";\n      break;\n\n    case oct_data_conv::dt_uint64:\n      retval = \"uint64\";\n      break;\n\n    case oct_data_conv::dt_single:\n      retval = \"single\";\n      break;\n\n    case oct_data_conv::dt_double:\n      retval = \"double\";\n      break;\n\n    case oct_data_conv::dt_char:\n      retval = \"char\";\n      break;\n\n    case oct_data_conv::dt_schar:\n      retval = \"signed char\";\n      break;\n\n    case oct_data_conv::dt_uchar:\n      retval = \"unsigned char\";\n      break;\n\n    case oct_data_conv::dt_short:\n      retval = \"short\";\n      break;\n\n    case oct_data_conv::dt_ushort:\n      retval = \"unsigned short\";\n      break;\n\n    case oct_data_conv::dt_int:\n      retval = \"int\";\n      break;\n\n    case oct_data_conv::dt_uint:\n      retval = \"unsigned int\";\n      break;\n\n    case oct_data_conv::dt_long:\n      retval = \"long\";\n      break;\n\n    case oct_data_conv::dt_ulong:\n      retval = \"unsigned long\";\n      break;\n\n    case oct_data_conv::dt_longlong:\n      retval = \"long long\";\n      break;\n\n    case oct_data_conv::dt_ulonglong:\n      retval = \"unsigned long long\";\n      break;\n\n    case oct_data_conv::dt_float:\n      retval = \"float\";\n      break;\n\n    case oct_data_conv::dt_logical:\n      retval = \"logical\";\n      break;\n\n    case oct_data_conv::dt_unknown:\n    default:\n      retval = \"unknown\";\n      break;\n    }\n\n  return retval;\n}\n\n#define LS_DO_READ(TYPE, swap, data, size, len, stream)                 \\\n  do                                                                    \\\n    {                                                                   \\\n      if (len > 0)                                                      \\\n        {                                                               \\\n          OCTAVE_LOCAL_BUFFER (TYPE, ptr, len);                         \\\n          std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \\\n          do_read (stream, reinterpret_cast<char *> (ptr), n_bytes);    \\\n          if (! stream)                                                 \\\n            return;                                                     \\\n          if (swap)                                                     \\\n            swap_bytes< size > (ptr, len);                              \\\n          for (octave_idx_type i = 0; i < len; i++)                     \\\n            data[i] = ptr[i];                                           \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\n// Have to use copy here to avoid writing over data accessed via\n// Matrix::data ().\n\n#define LS_DO_WRITE(TYPE, data, size, len, stream)                      \\\n  do                                                                    \\\n    {                                                                   \\\n      char tmp_type = type;                                             \\\n      stream.write (&tmp_type, 1);                                      \\\n      if (len > 0)                                                      \\\n        {                                                               \\\n          OCTAVE_LOCAL_BUFFER (TYPE, ptr, len);                         \\\n          for (octave_idx_type i = 0; i < len; i++)                     \\\n            ptr[i] = static_cast<TYPE> (data[i]);                       \\\n          std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \\\n          do_write (stream, reinterpret_cast<const char *> (ptr), n_bytes); \\\n        }                                                               \\\n     }                                                                  \\\n  while (0)\n\n// Loading variables from files.\n\nOCTAVE_NORETURN static\nvoid\nerr_unrecognized_float_fmt ()\n{\n  (*current_liboctave_error_handler)\n    (\"unrecognized floating point format requested\");\n}\n\n// But first, some data conversion routines.\n\n// Currently, we only handle conversions for the IEEE types.  To fix\n// that, make more of the following routines work.\n\n// FIXME: assumes sizeof (Complex) == 8\n// FIXME: assumes sizeof (double) == 8\n// FIXME: assumes sizeof (float) == 4\n\nstatic void\nIEEE_big_double_to_IEEE_little_double (void *d, octave_idx_type len)\n{\n  swap_bytes<8> (d, len);\n}\n\nstatic void\nIEEE_big_float_to_IEEE_little_float (void *d, octave_idx_type len)\n{\n  swap_bytes<4> (d, len);\n}\n\nstatic void\nIEEE_little_double_to_IEEE_big_double (void *d, octave_idx_type len)\n{\n  swap_bytes<8> (d, len);\n}\n\nstatic void\nIEEE_little_float_to_IEEE_big_float (void *d, octave_idx_type len)\n{\n  swap_bytes<4> (d, len);\n}\n\nvoid\ndo_double_format_conversion (void *data, octave_idx_type len,\n                             octave::mach_info::float_format from_fmt,\n                             octave::mach_info::float_format to_fmt)\n{\n  switch (to_fmt)\n    {\n    case octave::mach_info::flt_fmt_ieee_little_endian:\n      switch (from_fmt)\n        {\n        case octave::mach_info::flt_fmt_ieee_little_endian:\n          break;\n\n        case octave::mach_info::flt_fmt_ieee_big_endian:\n          IEEE_big_double_to_IEEE_little_double (data, len);\n          break;\n\n        default:\n          err_unrecognized_float_fmt ();\n          break;\n        }\n      break;\n\n    case octave::mach_info::flt_fmt_ieee_big_endian:\n      switch (from_fmt)\n        {\n        case octave::mach_info::flt_fmt_ieee_little_endian:\n          IEEE_little_double_to_IEEE_big_double (data, len);\n          break;\n\n        case octave::mach_info::flt_fmt_ieee_big_endian:\n          break;\n\n        default:\n          err_unrecognized_float_fmt ();\n          break;\n        }\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"impossible state reached in file '%s' at line %d\",\n         __FILE__, __LINE__);\n      break;\n    }\n}\n\nvoid\ndo_float_format_conversion (void *data, octave_idx_type len,\n                            octave::mach_info::float_format from_fmt,\n                            octave::mach_info::float_format to_fmt)\n{\n  switch (to_fmt)\n    {\n    case octave::mach_info::flt_fmt_ieee_little_endian:\n      switch (from_fmt)\n        {\n        case octave::mach_info::flt_fmt_ieee_little_endian:\n          break;\n\n        case octave::mach_info::flt_fmt_ieee_big_endian:\n          IEEE_big_float_to_IEEE_little_float (data, len);\n          break;\n\n        default:\n          err_unrecognized_float_fmt ();\n          break;\n        }\n      break;\n\n    case octave::mach_info::flt_fmt_ieee_big_endian:\n      switch (from_fmt)\n        {\n        case octave::mach_info::flt_fmt_ieee_little_endian:\n          IEEE_little_float_to_IEEE_big_float (data, len);\n          break;\n\n        case octave::mach_info::flt_fmt_ieee_big_endian:\n          break;\n\n        default:\n          err_unrecognized_float_fmt ();\n          break;\n        }\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"impossible state reached in file '%s' at line %d\",\n         __FILE__, __LINE__);\n      break;\n    }\n}\n\nvoid\ndo_float_format_conversion (void *data, std::size_t sz, octave_idx_type len,\n                            octave::mach_info::float_format from_fmt,\n                            octave::mach_info::float_format to_fmt)\n{\n  switch (sz)\n    {\n    case sizeof (float):\n      do_float_format_conversion (data, len, from_fmt, to_fmt);\n      break;\n\n    case sizeof (double):\n      do_double_format_conversion (data, len, from_fmt, to_fmt);\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"impossible state reached in file '%s' at line %d\",\n         __FILE__, __LINE__);\n      break;\n    }\n}\n\nstatic void\ndo_read (std::istream& is, char *byte_data, std::streamsize n_bytes)\n{\n  // read large data in chunks of 64 MiB\n  constexpr std::streamsize chunk_size = 64 * 1024 * 1024;\n  for (std::streamsize offset = 0; offset < n_bytes; )\n    {\n      std::streamsize to_read = std::min (chunk_size, n_bytes - offset);\n      is.read (byte_data + offset, to_read);\n\n      if (! is)\n        return;\n\n      offset += to_read;\n    }\n}\nvoid\nread_doubles (std::istream& is, double *data, save_type type,\n              octave_idx_type len, bool swap,\n              octave::mach_info::float_format fmt)\n{\n  switch (type)\n    {\n    case LS_U_CHAR:\n      LS_DO_READ (uint8_t, swap, data, 1, len, is);\n      break;\n\n    case LS_U_SHORT:\n      LS_DO_READ (uint16_t, swap, data, 2, len, is);\n      break;\n\n    case LS_U_INT:\n      LS_DO_READ (uint32_t, swap, data, 4, len, is);\n      break;\n\n    case LS_CHAR:\n      LS_DO_READ (int8_t, swap, data, 1, len, is);\n      break;\n\n    case LS_SHORT:\n      LS_DO_READ (int16_t, swap, data, 2, len, is);\n      break;\n\n    case LS_INT:\n      LS_DO_READ (int32_t, swap, data, 4, len, is);\n      break;\n\n    case LS_FLOAT:\n      {\n        OCTAVE_LOCAL_BUFFER (float, ptr, len);\n        std::streamsize n_bytes = sizeof (float) * static_cast<std::streamsize> (len);\n        do_read (is, reinterpret_cast<char *> (ptr), n_bytes);\n        if (! is)\n          return;\n        do_float_format_conversion (ptr, len, fmt);\n        for (octave_idx_type i = 0; i < len; i++)\n          data[i] = ptr[i];\n      }\n      break;\n\n    case LS_DOUBLE: // No conversion necessary.\n      {\n        std::streamsize n_bytes = sizeof (double) * static_cast<std::streamsize> (len);\n        do_read (is, reinterpret_cast<char *> (data), n_bytes);\n        if (! is)\n          return;\n        do_double_format_conversion (data, len, fmt);\n        // FIXME: Potentially add conversion code for MIPS NA here, Bug #59830.\n        //\n        // for (int i = 0; i < len; i++)\n        //   data[i] = __lo_ieee_replace_MIPS_NA (data[i]);\n      }\n      break;\n\n    default:\n      is.clear (std::ios::failbit | is.rdstate ());\n      break;\n    }\n}\n\nvoid\nread_floats (std::istream& is, float *data, save_type type,\n             octave_idx_type len, bool swap,\n             octave::mach_info::float_format fmt)\n{\n  switch (type)\n    {\n    case LS_U_CHAR:\n      LS_DO_READ (uint8_t, swap, data, 1, len, is);\n      break;\n\n    case LS_U_SHORT:\n      LS_DO_READ (uint16_t, swap, data, 2, len, is);\n      break;\n\n    case LS_U_INT:\n      LS_DO_READ (uint32_t, swap, data, 4, len, is);\n      break;\n\n    case LS_CHAR:\n      LS_DO_READ (int8_t, swap, data, 1, len, is);\n      break;\n\n    case LS_SHORT:\n      LS_DO_READ (int16_t, swap, data, 2, len, is);\n      break;\n\n    case LS_INT:\n      LS_DO_READ (int32_t, swap, data, 4, len, is);\n      break;\n\n    case LS_FLOAT: // No conversion necessary.\n      {\n        std::streamsize n_bytes = sizeof (float) * static_cast<std::streamsize> (len);\n        do_read (is, reinterpret_cast<char *> (data), n_bytes);\n        if (! is)\n          return;\n        do_float_format_conversion (data, len, fmt);\n      }\n      break;\n\n    case LS_DOUBLE:\n      {\n        OCTAVE_LOCAL_BUFFER (double, ptr, len);\n        std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);\n        do_read (is, reinterpret_cast<char *> (ptr), n_bytes);\n        if (! is)\n          return;\n        do_double_format_conversion (ptr, len, fmt);\n        for (octave_idx_type i = 0; i < len; i++)\n          data[i] = ptr[i];\n      }\n      break;\n\n    default:\n      is.clear (std::ios::failbit | is.rdstate ());\n      break;\n    }\n}\n\nstatic void\ndo_write (std::ostream& os, const char *byte_data, std::streamsize n_bytes)\n{\n  // write large data in chunks of 64 MiB\n  constexpr std::streamsize chunk_size = 64 * 1024 * 1024;\n  for (std::streamsize written = 0; written < n_bytes; )\n    {\n      std::streamsize remaining = n_bytes - written;\n      std::streamsize to_write = std::min (chunk_size, remaining);\n      os.write (byte_data + written, to_write);\n      if (! os)\n        return;\n      written += to_write;\n    }\n}\n\nvoid\nwrite_doubles (std::ostream& os, const double *data, save_type type,\n               octave_idx_type len)\n{\n  switch (type)\n    {\n    case LS_U_CHAR:\n      LS_DO_WRITE (uint8_t, data, 1, len, os);\n      break;\n\n    case LS_U_SHORT:\n      LS_DO_WRITE (uint16_t, data, 2, len, os);\n      break;\n\n    case LS_U_INT:\n      LS_DO_WRITE (uint32_t, data, 4, len, os);\n      break;\n\n    case LS_CHAR:\n      LS_DO_WRITE (int8_t, data, 1, len, os);\n      break;\n\n    case LS_SHORT:\n      LS_DO_WRITE (int16_t, data, 2, len, os);\n      break;\n\n    case LS_INT:\n      LS_DO_WRITE (int32_t, data, 4, len, os);\n      break;\n\n    case LS_FLOAT:\n      LS_DO_WRITE (float, data, 4, len, os);\n      break;\n\n    case LS_DOUBLE: // No conversion necessary.\n      {\n        char tmp_type = static_cast<char> (type);\n        os.write (&tmp_type, 1);\n\n        std::streamsize n_bytes = sizeof (double) * static_cast<std::streamsize> (len);\n        do_write (os, reinterpret_cast<const char *> (data), n_bytes);\n      }\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"unrecognized data format requested\");\n      break;\n    }\n}\n\nvoid\nwrite_floats (std::ostream& os, const float *data, save_type type,\n              octave_idx_type len)\n{\n  switch (type)\n    {\n    case LS_U_CHAR:\n      LS_DO_WRITE (uint8_t, data, 1, len, os);\n      break;\n\n    case LS_U_SHORT:\n      LS_DO_WRITE (uint16_t, data, 2, len, os);\n      break;\n\n    case LS_U_INT:\n      LS_DO_WRITE (uint32_t, data, 4, len, os);\n      break;\n\n    case LS_CHAR:\n      LS_DO_WRITE (int8_t, data, 1, len, os);\n      break;\n\n    case LS_SHORT:\n      LS_DO_WRITE (int16_t, data, 2, len, os);\n      break;\n\n    case LS_INT:\n      LS_DO_WRITE (int32_t, data, 4, len, os);\n      break;\n\n    case LS_FLOAT: // No conversion necessary.\n      {\n        char tmp_type = static_cast<char> (type);\n        os.write (&tmp_type, 1);\n        std::streamsize n_bytes = sizeof (float) * static_cast<std::streamsize> (len);\n        do_write (os, reinterpret_cast<const char *> (data), n_bytes);\n      }\n      break;\n\n    case LS_DOUBLE:\n      LS_DO_WRITE (double, data, 8, len, os);\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"unrecognized data format requested\");\n      break;\n    }\n}\n"
  },
  {
    "path": "liboctave/util/data-conv.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_data_conv_h)\n#define octave_data_conv_h 1\n\n#include \"octave-config.h\"\n\n#include \"mach-info.h\"\n#include \"oct-inttypes-fwd.h\"\n\nclass OCTAVE_API oct_data_conv\n{\npublic:\n\n  enum data_type\n  {\n    dt_int8      =  0,\n    dt_uint8     =  1,\n    dt_int16     =  2,\n    dt_uint16    =  3,\n    dt_int32     =  4,\n    dt_uint32    =  5,\n    dt_int64     =  6,\n    dt_uint64    =  7,\n    dt_single    =  8,\n    dt_double    =  9,\n    dt_char      = 10,\n    dt_schar     = 11,\n    dt_uchar     = 12,\n    dt_logical   = 13,\n    dt_short     = 14,\n    dt_ushort    = 15,\n    dt_int       = 16,\n    dt_uint      = 17,\n    dt_long      = 18,\n    dt_ulong     = 19,\n    dt_longlong  = 20,\n    dt_ulonglong = 21,\n    dt_float     = 22,\n    dt_unknown   = 23 // Must be last, have largest value!\n  };\n\n  static std::size_t data_type_size (data_type dt);\n\n  static data_type string_to_data_type (const std::string& s);\n\n  static void string_to_data_type (const std::string& s, int& block_size,\n                                   data_type& input_type,\n                                   data_type& output_type);\n\n  static void string_to_data_type (const std::string& s, int& block_size,\n                                   data_type& output_type);\n\n  static std::string data_type_as_string (data_type dt);\n};\n\n// Add new entries to the end of this enum, otherwise Octave will not\n// be able to read binary data files stored in Octave's binary data\n// format that were created with previous versions of Octave.\n\nenum save_type\n{\n  LS_U_CHAR  = 0,\n  LS_U_SHORT = 1,\n  LS_U_INT   = 2,\n  LS_CHAR    = 3,\n  LS_SHORT   = 4,\n  LS_INT     = 5,\n  LS_FLOAT   = 6,\n  LS_DOUBLE  = 7,\n  LS_U_LONG  = 8,\n  LS_LONG    = 9\n};\n\nextern OCTAVE_API void\ndo_double_format_conversion (void *data, octave_idx_type len,\n                             octave::mach_info::float_format from_fmt,\n                             octave::mach_info::float_format to_fmt\n                             = octave::mach_info::native_float_format ());\n\nextern OCTAVE_API void\ndo_float_format_conversion (void *data, octave_idx_type len,\n                            octave::mach_info::float_format from_fmt,\n                            octave::mach_info::float_format to_fmt\n                            = octave::mach_info::native_float_format ());\n\nextern OCTAVE_API void\ndo_float_format_conversion (void *data, std::size_t sz, octave_idx_type len,\n                            octave::mach_info::float_format from_fmt,\n                            octave::mach_info::float_format to_fmt\n                            = octave::mach_info::native_float_format ());\n\nextern OCTAVE_API void\nread_doubles (std::istream& is, double *data, save_type type,\n              octave_idx_type len, bool swap, octave::mach_info::float_format fmt);\n\nextern OCTAVE_API void\nwrite_doubles (std::ostream& os, const double *data, save_type type,\n               octave_idx_type len);\n\nextern OCTAVE_API void\nread_floats (std::istream& is, float *data, save_type type,\n             octave_idx_type len, bool swap, octave::mach_info::float_format fmt);\n\nextern OCTAVE_API void\nwrite_floats (std::ostream& os, const float *data, save_type type,\n              octave_idx_type len);\n\ntemplate <typename T>\ninline bool\nis_equivalent_type (oct_data_conv::data_type)\n{\n  return false;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<int8_t> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_int8;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<int16_t> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_int16;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<int32_t> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_int32;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<int64_t> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_int64;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<uint8_t> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_uint8;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<uint16_t> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_uint16;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<uint32_t> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_uint32;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<uint64_t> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_uint64;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<octave_int8> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_int8;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<octave_int16> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_int16;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<octave_int32> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_int32;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<octave_int64> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_int64;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<octave_uint8> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_uint8;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<octave_uint16> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_uint16;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<octave_uint32> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_uint32;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<octave_uint64> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_uint64;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<double> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_double;\n}\n\ntemplate <>\ninline bool\nis_equivalent_type<float> (oct_data_conv::data_type t)\n{\n  return t == oct_data_conv::dt_single || t == oct_data_conv::dt_float;\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/util/f77-dummy-main.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cassert>\n\n// Dummy Fortran main declaration, needed in order to link to some\n// Fortran libraries.  See the AC_F77_DUMMY_MAIN macro documentation.\n// This function should never be called.\n\n#if defined (F77_DUMMY_MAIN)\n\nextern \"C\"\nint\nF77_DUMMY_MAIN (void)\n{\n  assert (0);\n\n  return 1;\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/util/f77-fcn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n#include <cstring>\n\n#include \"f77-fcn.h\"\n#include \"oct-error.h\"\n#include \"quit.h\"\n\n/* All the STOP statements in the Fortran routines have been replaced\n   with a call to XSTOPX.\n\n   XSTOPX calls the liboctave error handler.  In the Octave interpreter\n   we set this to a function that throws an exception and transfers\n   control to the enclosing try/catch block.  That is typically at the\n   top-level REPL.  */\n\nF77_RET_T\nF77_FUNC (xstopx, XSTOPX) (F77_CONST_CHAR_ARG_DEF (s_arg, len)\n                           F77_CHAR_ARG_LEN_DEF (len))\n{\n  const char *s = F77_CHAR_ARG_USE (s_arg);\n  size_t slen = F77_CHAR_ARG_LEN_USE (s_arg, len);\n\n  /* Skip printing message if it is just a single blank character.  */\n  if (! (s && slen > 0 && ! (slen == 1 && *s == ' ')))\n    {\n      s = \"unknown error in fortran subroutine\";\n      slen = strlen (s);\n    }\n\n  (*current_liboctave_error_handler) (\"%.*s\", static_cast<int> (slen), s);\n\n  F77_NORETURN (0)\n}\n"
  },
  {
    "path": "liboctave/util/f77-fcn.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_f77_fcn_h)\n#define octave_f77_fcn_h 1\n\n#include \"octave-config.h\"\n\n#include \"oct-error.h\"\n#include \"quit.h\"\n\n#if defined (__cplusplus)\n#  include <cstddef>\n#  include <limits>\nusing std::size_t;\nextern \"C\" {\n#else\n#  include <stddef.h>\n#endif\n\n/* This macro is obsolete.  */\n\n#define F77_XFCN(f, F, args)                    \\\n  F77_FUNC (f, F) args\n\n#if ! defined (F77_FCN)\n#  define F77_FCN(f, F) F77_FUNC (f, F)\n#endif\n\n/*\n\nThe following macros are used for handling Fortran <-> C calling\nconventions.  They are defined below for three different types of\nsystems, Cray (possibly now obsolete), Visual Fortran, and gfortran.\nNote that we don't attempt to handle Fortran functions, we always use\nsubroutine wrappers for them and pass the return value as an extra\nargument.\n\nUse these macros to pass character strings from C to Fortran:\n\n  F77_CHAR_ARG(x)\n  F77_CONST_CHAR_ARG(x)\n  F77_CXX_STRING_ARG(x)\n  F77_CHAR_ARG_LEN(l)\n  F77_CHAR_ARG_DECL\n  F77_CONST_CHAR_ARG_DECL\n  F77_CHAR_ARG_LEN_DECL\n\nUse these macros to write C-language functions that accept\nFortran-style character strings:\n\n  F77_CHAR_ARG_DEF(s, len)\n  F77_CONST_CHAR_ARG_DEF(s, len)\n  F77_CHAR_ARG_LEN_DEF(len)\n  F77_CHAR_ARG_USE(s)\n  F77_CHAR_ARG_LEN_USE(s, len)\n\nUse these macros for C++ code\n\n  F77_INT         Equivalent to Fortran INTEGER type\n  F77_INT4        Equivalent to Fortran INTEGER*4 type\n  F77_DBLE        Equivalent to Fortran DOUBLE PRECISION type\n  F77_REAL        Equivalent to Fortran REAL type\n  F77_CMPLX       Equivalent to Fortran COMPLEX type\n  F77_DBLE_CMPLX  Equivalent to Fortran DOUBLE COMPLEX type\n  F77_LOGICAL     Equivalent to Fortran LOGICAL type\n  F77_RET_T       Return type of a C++ function that acts like a\n                  Fortran subroutine.\n\nUse these macros to return from C-language functions that are supposed\nto act like Fortran subroutines.  F77_NORETURN is intended to be used\nas the last statement of such a function that has been tagged with a\n\"noreturn\" attribute.  If the compiler supports the \"noreturn\"\nattribute or if F77_RET_T is void, then it should expand to nothing so\nthat we avoid warnings about functions tagged as \"noreturn\"\ncontaining a return statement.  Otherwise, it should expand to a\nstatement that returns the given value so that we avoid warnings about\nnot returning a value from a function declared to return something.\n\n  F77_RETURN(retval)\n  F77_NORETURN(retval)\n\n*/\n\n#if defined (F77_USES_CRAY_CALLING_CONVENTION)\n\n#include <fortran.h>\n\n/* Use these macros to pass character strings from C to Fortran.  Cray\n   Fortran uses a descriptor structure to pass a pointer to the string\n   and the length in a single argument.  */\n\n#define F77_CHAR_ARG(x) octave_make_cray_ftn_ch_dsc (x, strlen (x))\n#define F77_CONST_CHAR_ARG(x)                           \\\n  octave_make_cray_const_ftn_ch_dsc (x, strlen (x))\n#define F77_CHAR_ARG2(x, l) octave_make_cray_ftn_ch_dsc (x, l)\n#define F77_CONST_CHAR_ARG2(x, l) octave_make_cray_const_ftn_ch_dsc (x, l)\n#define F77_CXX_STRING_ARG(x)                                   \\\n  octave_make_cray_const_ftn_ch_dsc (x.c_str (), x.length ())\n#define F77_CHAR_ARG_LEN(l)\n#define F77_CHAR_ARG_LEN_TYPE\n#define F77_CHAR_ARG_LEN_DECL\n#define F77_CHAR_ARG_DECL octave_cray_ftn_ch_dsc\n#define F77_CONST_CHAR_ARG_DECL octave_cray_ftn_ch_dsc\n\n/* Use these macros to write C-language functions that accept\n   Fortran-style character strings.  */\n#define F77_CHAR_ARG_DEF(s, len) octave_cray_ftn_ch_dsc s\n#define F77_CONST_CHAR_ARG_DEF(s, len) octave_cray_ftn_ch_dsc s\n#define F77_CHAR_ARG_LEN_DEF(len)\n#define F77_CHAR_ARG_USE(s) s.ptr\n#define F77_CHAR_ARG_LEN_USE(s, len) (s.mask.len >> 3)\n\n#define F77_RET_T int\n\n/* Use these macros to return from C-language functions that are\n   supposed to act like Fortran subroutines.  F77_NORETURN is intended\n   to be used as the last statement of such a function that has been\n   tagged with a \"noreturn\" attribute.  */\n\n#define F77_RETURN(retval) return retval;\n#if defined (HAVE_OCTAVE_NORETURN_ATTR)\n#  define F77_NORETURN(retval)\n#else\n#  define F77_NORETURN(retval) return retval;\n#endif\n\n/* FIXME: These should work for SV1 or Y-MP systems but will\n          need to be changed for others.  */\n\ntypedef union\n  {\n  const char *const_ptr;\n  char *ptr;\n  struct\n  {\n    unsigned off : 6;\n    unsigned len : 26;\n    unsigned add : 32;\n  } mask;\n} octave_cray_descriptor;\n\ntypedef void *octave_cray_ftn_ch_dsc;\n\n#if defined (__cplusplus)\n#  define OCTAVE_F77_FCN_INLINE inline\n#else\n#  define OCTAVE_F77_FCN_INLINE\n#endif\n\nstatic OCTAVE_F77_FCN_INLINE octave_cray_ftn_ch_dsc\noctave_make_cray_ftn_ch_dsc (char *ptr_arg, unsigned long len_arg)\n{\n  octave_cray_descriptor desc;\n  desc.ptr = ptr_arg;\n  desc.mask.len = len_arg << 3;\n  return *((octave_cray_ftn_ch_dsc *) &desc);\n}\n\nstatic OCTAVE_F77_FCN_INLINE octave_cray_ftn_ch_dsc\noctave_make_cray_const_ftn_ch_dsc (const char *ptr_arg, unsigned long len_arg)\n{\n  octave_cray_descriptor desc;\n  desc.const_ptr = ptr_arg;\n  desc.mask.len = len_arg << 3;\n  return *((octave_cray_ftn_ch_dsc *) &desc);\n}\n\n#undef OCTAVE_F77_FCN_INLINE\n\n#elif defined (F77_USES_VISUAL_FORTRAN_CALLING_CONVENTION)\n\n/* Use these macros to pass character strings from C to Fortran.\n   Visual Fortran inserts the length after each character string\n   argument.  */\n\n#define F77_CHAR_ARG(x) x, strlen (x)\n#define F77_CONST_CHAR_ARG(x) F77_CHAR_ARG (x)\n#define F77_CHAR_ARG2(x, l) x, l\n#define F77_CONST_CHAR_ARG2(x, l) F77_CHAR_ARG2 (x, l)\n#define F77_CXX_STRING_ARG(x) F77_CONST_CHAR_ARG2 (x.c_str (), x.length ())\n#define F77_CHAR_ARG_LEN(l)\n#define F77_CHAR_ARG_LEN_TYPE int\n#define F77_CHAR_ARG_LEN_DECL\n#define F77_CHAR_ARG_DECL char *, F77_CHAR_ARG_LEN_TYPE\n#define F77_CONST_CHAR_ARG_DECL const char *, F77_CHAR_ARG_LEN_TYPE\n\n#define F77_CHAR_ARG_DEF(s, len) char *s, F77_CHAR_ARG_LEN_TYPE len\n#define F77_CONST_CHAR_ARG_DEF(s, len) const char *s, F77_CHAR_ARG_LEN_TYPE len\n#define F77_CHAR_ARG_LEN_DEF(len)\n#define F77_CHAR_ARG_USE(s) s\n#define F77_CHAR_ARG_LEN_USE(s, len) len\n\n#define F77_RET_T void\n\n#define F77_RETURN(retval) return;\n#define F77_NORETURN(retval)\n\n#elif defined (F77_USES_GFORTRAN_CALLING_CONVENTION)\n\n/* Use these macros to pass character strings from C to Fortran.\n   gfortran appends length arguments for assumed size character\n   strings to the and ignores others.\n\n   FIXME: I don't think we correctly handle the case of mixing some\n   fixed-length and some assumed-length character string arguments as\n   we don't handle each case separately, so it seems there could be\n   mismatch?  However, I don't think we currently have to handle this\n   case in Octave.  */\n\n#define F77_CHAR_ARG(x) x\n#define F77_CONST_CHAR_ARG(x) F77_CHAR_ARG (x)\n#define F77_CHAR_ARG2(x, l) x\n#define F77_CONST_CHAR_ARG2(x, l) F77_CHAR_ARG2 (x, l)\n#define F77_CXX_STRING_ARG(x) F77_CONST_CHAR_ARG2 (x.c_str (), x.length ())\n#define F77_CHAR_ARG_LEN(l) , l\n#if defined (__GNUC__) && __GNUC__ >= 8\n#  define F77_CHAR_ARG_LEN_TYPE size_t\n#else\n#  define F77_CHAR_ARG_LEN_TYPE int\n#endif\n#define F77_CHAR_ARG_LEN_DECL , F77_CHAR_ARG_LEN_TYPE\n#define F77_CHAR_ARG_DECL char *\n#define F77_CONST_CHAR_ARG_DECL const char *\n\n#define F77_CHAR_ARG_DEF(s, len) char *s\n#define F77_CONST_CHAR_ARG_DEF(s, len) const char *s\n#define F77_CHAR_ARG_LEN_DEF(len) , F77_CHAR_ARG_LEN_TYPE len\n#define F77_CHAR_ARG_USE(s) s\n#define F77_CHAR_ARG_LEN_USE(s, len) len\n\n#define F77_RET_T void\n\n#define F77_RETURN(retval) return;\n#if defined (HAVE_OCTAVE_NORETURN_ATTR)\n#  define F77_NORETURN(retval)\n#else\n#  define F77_NORETURN(retval) return retval;\n#endif\n\n#elif defined (F77_USES_F2C_CALLING_CONVENTION)\n\n/* Assume f2c-compatible calling convention.  */\n\n/* Use these macros to pass character strings from C to Fortran.  f2c\n   appends all length arguments at the end of the parameter list.  */\n\n#define F77_CHAR_ARG(x) x\n#define F77_CONST_CHAR_ARG(x) F77_CHAR_ARG (x)\n#define F77_CHAR_ARG2(x, l) x\n#define F77_CONST_CHAR_ARG2(x, l) F77_CHAR_ARG2 (x, l)\n#define F77_CXX_STRING_ARG(x) F77_CONST_CHAR_ARG2 (x.c_str (), x.length ())\n#define F77_CHAR_ARG_LEN(l) , l\n#define F77_CHAR_ARG_LEN_TYPE long\n#define F77_CHAR_ARG_LEN_DECL , F77_CHAR_ARG_LEN_TYPE\n#define F77_CHAR_ARG_DECL char *\n#define F77_CONST_CHAR_ARG_DECL const char *\n\n#define F77_CHAR_ARG_DEF(s, len) char *s\n#define F77_CONST_CHAR_ARG_DEF(s, len) const char *s\n#define F77_CHAR_ARG_LEN_DEF(len) , F77_CHAR_ARG_LEN_TYPE len\n#define F77_CHAR_ARG_USE(s) s\n#define F77_CHAR_ARG_LEN_USE(s, len) len\n\n#define F77_RET_T int\n\n#define F77_RETURN(retval) return retval;\n#if defined (HAVE_OCTAVE_NORETURN_ATTR)\n#  define F77_NORETURN(retval)\n#else\n#  define F77_NORETURN(retval) return retval;\n#endif\n\n#else\n\n#error \"unknown C++ to Fortran calling convention\"\n\n#endif\n\ntypedef double F77_DBLE;\ntypedef float F77_REAL;\ntypedef double _Complex F77_DBLE_CMPLX;\ntypedef float _Complex F77_CMPLX;\ntypedef octave_f77_int_type F77_INT;\ntypedef int32_t F77_INT4;\ntypedef octave_f77_int_type F77_LOGICAL;\n\n#define F77_CMPLX_ARG(x)                        \\\n  reinterpret_cast<float _Complex *> (x)\n\n#define F77_CONST_CMPLX_ARG(x)                  \\\n  reinterpret_cast<const float _Complex *> (x)\n\n#define F77_DBLE_CMPLX_ARG(x)                   \\\n  reinterpret_cast<double _Complex *> (x)\n\n#define F77_CONST_DBLE_CMPLX_ARG(x)             \\\n  reinterpret_cast<const double _Complex *> (x)\n\n/* Build a C string local variable CS from the Fortran string parameter S\n   declared as F77_CHAR_ARG_DEF(s, len) or F77_CONST_CHAR_ARG_DEF(s, len).\n   The string will be cleaned up at the end of the current block.\n   Needs to include <cstring> and <vector>.  */\n\n#define F77_CSTRING(s, len, cs)                                         \\\n  OCTAVE_LOCAL_BUFFER (char, cs, F77_CHAR_ARG_LEN_USE (s, len) + 1);    \\\n  memcpy (cs, F77_CHAR_ARG_USE (s), F77_CHAR_ARG_LEN_USE (s, len));     \\\n  cs[F77_CHAR_ARG_LEN_USE(s, len)] = '\\0'\n\nOCTAVE_NORETURN OCTAVE_API extern\nF77_RET_T\nF77_FUNC (xstopx, XSTOPX) (F77_CONST_CHAR_ARG_DECL\n                           F77_CHAR_ARG_LEN_DECL);\n\n#if defined (__cplusplus)\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ninline F77_INT\nto_f77_int (octave_idx_type x)\n{\n  if (x < std::numeric_limits<F77_INT>::min ()\n      || x > std::numeric_limits<F77_INT>::max ())\n    (*current_liboctave_error_handler)\n      (\"integer dimension or index out of range for Fortran INTEGER type\");\n\n  return static_cast<F77_INT> (x);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/util/file-info.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <deque>\n#include <fstream>\n\n#include \"file-info.h\"\n#include \"file-stat.h\"\n#include \"oct-error.h\"\n#include \"oct-sysdep.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstd::string file_info::get_line (std::size_t line) const\n{\n  std::string retval;\n\n  if (line == 0)\n    return retval;\n\n  if (line < m_offsets.size ())\n    {\n      std::size_t bol = m_offsets[line-1];\n      std::size_t eol = m_offsets[line];\n\n      while (eol > 0 && eol > bol\n             && (m_file_buf[eol-1] == '\\n' || m_file_buf[eol-1] == '\\r'))\n        eol--;\n\n      retval = m_file_buf.substr (bol, eol - bol);\n    }\n\n  return retval;\n}\n\nstd::deque<std::string>\nfile_info::get_lines (std::size_t line, std::size_t num_lines) const\n{\n  std::deque<std::string> retval;\n\n  for (std::size_t i = line; i < line+num_lines; i++)\n    retval.push_back (get_line (i));\n\n  return retval;\n}\n\n// Read entire file called fname and return the contents as a string\n\nstd::string\nfile_info::snarf_file (const std::string& fname)\n{\n  std::string retval;\n\n  sys::file_stat fs (fname);\n\n  if (! fs)\n    (*current_liboctave_error_handler) (\"no such file, '%s'\", fname.c_str ());\n\n  std::size_t sz = fs.size ();\n\n  std::ifstream file = sys::ifstream (fname.c_str (),\n                                      std::ios::in | std::ios::binary);\n\n  if (file)\n    {\n      std::string buf (sz+1, 0);\n\n      file.read (&buf[0], sz+1);\n\n      if (! file.eof ())\n        (*current_liboctave_error_handler)\n          (\"error reading file %s\", fname.c_str ());\n\n      // Expected to read the entire file.\n      retval = buf;\n    }\n\n  return retval;\n}\n\nstd::vector<std::size_t>\nfile_info::get_line_offsets (const std::string& buf)\n{\n  std::deque<std::size_t> tmp_offsets;\n\n  tmp_offsets.push_back (0);\n\n  std::size_t len = buf.length ();\n\n  for (std::size_t i = 0; i < len; i++)\n    {\n      char c = buf[i];\n\n      if (c == '\\r' && ++i < len)\n        {\n          c = buf[i];\n\n          if (c == '\\n')\n            tmp_offsets.push_back (i+1);\n          else\n            tmp_offsets.push_back (i);\n        }\n      else if (c == '\\n')\n        tmp_offsets.push_back (i+1);\n    }\n\n  tmp_offsets.push_back (len-1);\n\n  std::size_t n = tmp_offsets.size ();\n\n  std::vector<std::size_t> retval (n);\n  std::size_t i = 0;\n  for (auto& elt : tmp_offsets)\n    retval[i++] = elt;\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/file-info.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2001-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_file_info_h)\n#define octave_file_info_h 1\n\n#include \"octave-config.h\"\n\n#include <deque>\n#include <map>\n#include <string>\n#include <vector>\n\n#include \"oct-time.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass file_info\n{\npublic:\n\n  file_info ()\n    : m_file_buf (), m_offsets (), m_timestamp (static_cast<OCTAVE_TIME_T> (0))\n  { }\n\n  file_info (const std::string& text, const sys::time& timestamp)\n    : m_file_buf (text), m_offsets (get_line_offsets (m_file_buf)),\n      m_timestamp (timestamp)\n  { }\n\n  file_info (const std::string& fname)\n    : m_file_buf (snarf_file (fname)),\n      m_offsets (get_line_offsets (m_file_buf)),\n      m_timestamp ()\n  { }\n\n  file_info (const file_info&) = default;\n\n  file_info& operator = (const file_info&) = default;\n\n  ~file_info () = default;\n\n  OCTAVE_API std::string get_line (std::size_t line) const;\n\n  OCTAVE_API std::deque<std::string>\n  get_lines (std::size_t line, std::size_t num_lines) const;\n\n  std::size_t num_lines () const { return m_offsets.size (); }\n\n  std::string text () const { return m_file_buf; }\n\n  std::vector<std::size_t> line_offsets () const { return m_offsets; }\n\n  sys::time timestamp () const { return m_timestamp; }\n\n  std::size_t size () const { return m_file_buf.length (); }\n\nprivate:\n\n  // File contents as a string.\n  std::string m_file_buf;\n\n  // Offsets to line beginnings.\n  std::vector<std::size_t> m_offsets;\n\n  sys::time m_timestamp;\n\n  // Read entire file called fname and return the contents as a string\n  static OCTAVE_API std::string snarf_file (const std::string& fname);\n\n  static OCTAVE_API std::vector<std::size_t>\n  get_line_offsets (const std::string& buf);\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/glob-match.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"glob-match.h\"\n#include \"oct-glob.h\"\n#include \"glob-wrappers.h\"\n\nbool\nglob_match::match (const std::string& str) const\n{\n  return octave::sys::fnmatch (m_pat, str, m_fnmatch_flags);\n}\n\nstring_vector\nglob_match::glob () const\n{\n  return octave::sys::glob (m_pat);\n}\n\nint\nglob_match::opts_to_fnmatch_flags (unsigned int xopts) const\n{\n  int retval = 0;\n\n  if (xopts & pathname)\n    retval |= octave_fnm_pathname_wrapper ();\n\n  if (xopts & noescape)\n    retval |= octave_fnm_noescape_wrapper ();\n\n  if (xopts & period)\n    retval |= octave_fnm_period_wrapper ();\n\n  return retval;\n}\n\nsymbol_match::symbol_match (const std::string& pattern)\n{\n  m_pat = pattern;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  m_glob = nullptr;\n#else\n  m_glob = std::unique_ptr<glob_match> {new glob_match {pattern}};\n#endif\n}\n\nsymbol_match::symbol_match (const symbol_match& in)\n{\n  m_pat = in.m_pat;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  m_glob = nullptr;\n#else\n  m_glob = std::unique_ptr<glob_match> {new glob_match {m_pat}};\n#endif\n}\n\nbool\nsymbol_match::match (const std::string& sym)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  // gnulib's fnmatch replacement is slow on Windows.\n  // We don't need full POSIX compatibility to match symbol patterns.\n  // Glob patterns with '*' or '?' should be good enough.\n  // We also do not need to worry about multi-byte characters because symbols\n  // are ASCII-only.\n  octave_idx_type pat_len = m_pat.length ();\n  octave_idx_type pat_idx = 0;\n  octave_idx_type pat_wildc_idx = -1;\n  octave_idx_type sym_len = sym.length ();\n  octave_idx_type sym_idx = 0;\n  octave_idx_type sym_wildc_idx = 0;\n\n  while (sym_idx < sym_len)\n    {\n      if (pat_idx < pat_len\n          && (m_pat[pat_idx] == '?' || m_pat[pat_idx] == sym[sym_idx]))\n        {\n          // match to '?' or exact match\n          pat_idx++;\n          sym_idx++;\n        }\n      else if (pat_idx < pat_len && m_pat[pat_idx] == '*')\n        {\n          // remember position in pattern and symbol\n          pat_wildc_idx = pat_idx;\n          sym_wildc_idx = sym_idx;\n          pat_idx++;\n        }\n      else if (pat_wildc_idx != -1)\n        {\n          // no match but previous wildcard '*'\n          // revert pat_idx to previous position\n          pat_idx = pat_wildc_idx + 1;\n          // but proceed to next character in symbol and try to match again\n          sym_wildc_idx++;\n          sym_idx = sym_wildc_idx;\n        }\n      else\n        // no exact match and no wildcard\n        return false;\n    }\n\n  // consume potentially trailing '*' in pattern\n  while (pat_idx < pat_len && m_pat[pat_idx] == '*')\n    pat_idx++;\n\n  // check for remaining (unmatched) characters in pattern\n  return pat_idx == pat_len;\n\n#else\n\n  return m_glob->match (sym);\n\n#endif\n}\n\n"
  },
  {
    "path": "liboctave/util/glob-match.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_glob_match_h)\n#define octave_glob_match_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"Array-oct.h\"\n#include \"str-vec.h\"\n\nclass OCTAVE_API glob_match\n{\npublic:\n\n  enum opts\n  {\n    pathname = 1,  // No wildcard can ever match '/'.\n    noescape = 2,  // Backslashes don't quote special chars.\n    period = 4     // Leading '.' is matched only explicitly.\n  };\n\n  glob_match (const std::string& p,\n              unsigned int xopts = pathname | noescape | period)\n    : m_pat (p), m_fnmatch_flags (opts_to_fnmatch_flags (xopts))\n  { }\n\n  glob_match (const string_vector& p = string_vector (),\n              unsigned int xopts = pathname | noescape | period)\n    : m_pat (p), m_fnmatch_flags (opts_to_fnmatch_flags (xopts))\n  { }\n\n  glob_match (const glob_match& gm) = default;\n\n  glob_match& operator = (const glob_match& gm) = default;\n\n  ~glob_match () = default;\n\n  void set_pattern (const std::string& p) { m_pat = p; }\n\n  void set_pattern (const string_vector& p) { m_pat = p; }\n\n  bool match (const std::string& str) const;\n\n  Array<bool> match (const string_vector& str) const\n  {\n    int n = str.numel ();\n\n    Array<bool> retval (dim_vector (n, 1));\n\n    for (int i = 0; i < n; i++)\n      retval(i) = match (str[i]);\n\n    return retval;\n  }\n\n  // We forward to glob_internal here to avoid problems with gnulib's\n  // glob.h defining glob to be rpl_glob.\n\n  string_vector glob () const;\n\nprivate:\n\n  // Globbing pattern(s).\n  string_vector m_pat;\n\n  // Option flags.\n  int m_fnmatch_flags;\n\n  int opts_to_fnmatch_flags (unsigned int xopts) const;\n};\n\nclass OCTAVE_API symbol_match\n{\n\n// This class is meant to provide a performant implementation for symbol\n// matching on all platforms.  For Windows, that is done by manually\n// implementing matching rules for '*' and '?' wildcards.  On other platforms,\n// the matching is deferred to `fnmatch`.  That means that the matching rules\n// differ depending on the platform.  To write cross-platform compatible code\n// with this class, do not use [] groups or ranges, named character classes,\n// collating symbols, or equivalence class expressions.\n\npublic:\n\n  symbol_match (const std::string& pattern);\n\n  symbol_match (const symbol_match&);\n\n  symbol_match& operator = (const symbol_match& in)\n  {\n    if (this == &in)\n      return *this;\n\n    m_pat = in.m_pat;\n\n    if (m_glob)\n      m_glob->set_pattern (m_pat);\n\n    return *this;\n  }\n\n  ~symbol_match () = default;\n\n  void set_pattern (const std::string& p)\n  {\n    m_pat = p;\n\n    if (m_glob)\n      m_glob->set_pattern (m_pat);\n  }\n\n  bool match (const std::string& sym);\n\nprivate:\n\n  std::string m_pat;\n\n  std::unique_ptr<glob_match> m_glob;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/util/i1mach.f",
    "content": "c Copyright (C) 1996-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      integer function i1mach (i)\n      integer i, imach(16)\n      logical init\n      double precision dlamch\n      real slamch\n      external dlamch, slamch\n      save imach, init\n      data imach / 5, 6, 0, 6, 32, 4, 2, 31, 2147483647,\n     $     2, 0, 0, 0, 0, 0, 0 /\n      data init /.false./\n      if (.not. init) then\n        imach(11) = slamch ('n')\n        imach(12) = slamch ('m')\n        imach(13) = slamch ('l')\n        imach(14) = dlamch ('n')\n        imach(15) = dlamch ('m')\n        imach(16) = dlamch ('l')\n        init = .true.\n      endif\n      if (i .lt. 1 .or. i .gt. 16) goto 999\n      i1mach = imach(i)\n      return\n  999 write (*, 1999) i\n 1999 format (' i1mach - i out of bounds', i10)\n      call xstopx (' ')\n      i1mach = 0\n      end\n"
  },
  {
    "path": "liboctave/util/kpse.cc",
    "content": "// This file is not compiled to a separate object file.\n// It is included in pathsearch.cc.\n\n//////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1991-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n//  Look up a filename in a path.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cerrno>\n#include <cstdlib>\n\n#include <string>\n\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"kpse.h\"\n#include \"oct-env.h\"\n#include \"oct-password.h\"\n#include \"oct-sysdep.h\"\n#include \"oct-time.h\"\n#include \"pathsearch.h\"\n#include \"unistd-wrappers.h\"\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  define WIN32_LEAN_AND_MEAN 1\n#  include <windows.h>\n#endif\n\n// Define the characters which separate components of filenames and\n// environment variable paths.\n#define IS_DEVICE_SEP(ch) octave::sys::file_ops::is_dev_sep (ch)\n#define NAME_BEGINS_WITH_DEVICE(name)                   \\\n   (name.length () > 0 && IS_DEVICE_SEP ((name)[1]))\n\n#define DIR_SEP_STRING octave::sys::file_ops::dir_sep_str ()\n#define IS_DIR_SEP(ch) octave::sys::file_ops::is_dir_sep (ch)\n\n#define ENV_SEP octave::directory_path::path_sep_char ()\n#define ENV_SEP_STRING octave::directory_path::path_sep_str ()\n#define IS_ENV_SEP(ch) octave::directory_path::is_path_sep (ch)\n\n// Define to 1 to enable debugging\n#define OCTAVE_KPSE_DEBUG 0\n\n\nvoid\nkpse_path_iterator::set_end ()\n{\n  m_e = m_b + 1;\n\n  if (m_e == m_len)\n    ;  // OK, we have found the last element.\n  else if (m_e > m_len)\n    m_b = m_e = std::string::npos;\n  else\n    {\n      // Find the next colon not enclosed by braces (or the end of the path).\n      while (m_e < m_len && ! octave::directory_path::is_path_sep (m_path[m_e]))\n        m_e++;\n    }\n}\n\nvoid\nkpse_path_iterator::next ()\n{\n  m_b = m_e + 1;\n\n  // Skip any consecutive colons.\n  while (m_b < m_len && octave::directory_path::is_path_sep (m_path[m_b]))\n    m_b++;\n\n  if (m_b >= m_len)\n    m_b = m_e = std::string::npos;\n  else\n    set_end ();\n}\n\n/* Truncate any too-long components in NAME, returning the result.\n   It's too bad this is necessary.  See comments in readable.c for why.  */\nstatic std::string\nkpse_truncate_filename (const std::string& name)\n{\n  unsigned c_len = 0;        // Length of current component.\n  unsigned ret_len = 0;      // Length of constructed result.\n\n  std::string ret = name;\n\n  std::size_t m_len = name.length ();\n\n  for (std::size_t i = 0; i < m_len; i++)\n    {\n      if (IS_DIR_SEP (name[i]) || IS_DEVICE_SEP (name[i]))\n        {\n          // At a directory delimiter, reset component length.\n          c_len = 0;\n        }\n      else if (c_len > octave::sys::dir_entry::max_name_length ())\n        {\n          // If past the max for a component, ignore this character.\n          continue;\n        }\n\n      // Copy this character.\n      ret[ret_len++] = name[i];\n      c_len++;\n    }\n\n  ret.resize (ret_len);\n\n  return ret;\n}\n\n/* If access can read FN, run stat (assigning to stat buffer ST) and check that\n   fn is not a directory.  Don't check for just being a regular file, as it is\n   potentially useful to read FIFO's or some kinds of devices.  */\n\nstatic inline bool\nREADABLE (const std::string& fn)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  std::wstring w_fn = octave::sys::u8_to_wstring (fn);\n\n  DWORD f_attr = GetFileAttributesW (w_fn.c_str ());\n\n  return (f_attr != 0xFFFFFFFF && ! (f_attr & FILE_ATTRIBUTE_DIRECTORY));\n\n#else\n\n  bool retval = false;\n\n  const char *t = fn.c_str ();\n\n  if (octave_access_wrapper (t, octave_access_r_ok ()) == 0)\n    {\n      octave::sys::file_stat fs (fn);\n\n      retval = fs && ! fs.is_dir ();\n    }\n\n  return retval;\n\n#endif\n}\n\n/* POSIX invented the brain-damage of not necessarily truncating filename\n   components; the system's behavior is defined by the value of the symbol\n   _POSIX_NO_TRUNC, but you can't change it dynamically!\n\n   Generic const return warning.  See extend-fname.c.  */\n\nstatic std::string\nkpse_readable_file (const std::string& name)\n{\n  std::string ret;\n\n  if (READABLE (name))\n    {\n      ret = name;\n\n#if defined (ENAMETOOLONG)\n    }\n  else if (errno == ENAMETOOLONG)\n    {\n      ret = kpse_truncate_filename (name);\n\n      /* Perhaps some other error will occur with the truncated name,\n         so let's call access again.  */\n\n      if (! READABLE (ret))\n        {\n          // Failed.\n          ret = \"\";\n        }\n#endif\n\n    }\n  else\n    {\n      // Some other error.\n      if (errno == EACCES)\n        {\n          // Maybe warn them if permissions are bad.\n          perror (name.c_str ());\n        }\n\n      ret = \"\";\n    }\n\n  return ret;\n}\n\nstatic bool\nkpse_absolute_p (const std::string& filename, int relative_ok)\n{\n  return (octave::sys::env::absolute_pathname (filename)\n          || (relative_ok\n              && octave::sys::env::rooted_relative_pathname (filename)));\n}\n\n/* The very first search is for texmf.cnf, called when someone tries to\n   initialize the TFM path or whatever.  init_path calls kpse_cnf_get which\n   calls kpse_all_path_search to find all the texmf.cnf's.  We need to do\n   various special things in this case, since we obviously don't yet have the\n   configuration files when we're searching for the configuration files.  */\nstatic bool first_search = true;\n\n#if OCTAVE_KPSE_DEBUG\n// This function is called after every search.\nstatic void\nlog_search (const std::list<std::string>& filenames)\n{\n  for (const auto& filename : filenames)\n    {\n      octave::sys::time now;\n      std::cerr << now.unix_time () << ' ' << filename << std::endl;\n    }\n}\n#endif\n\n/* Concatenate each element in DIRS with NAME (assume each ends with a /, to\n   save time).  If SEARCH_ALL is false, return the first readable regular file.\n   Else continue to search for more.  In any case, if none, return a list\n   containing just NULL.\n\n   We keep a single buffer for the potential filenames and reallocate only when\n   necessary.  I'm not sure it's noticeably faster, but it does seem cleaner.\n   (We do waste a bit of space in the return value, though, since we don't\n   shrink it to the final size returned.)  */\n\nstatic std::list<std::string>\ndir_search (const std::string& dir, const std::string& name,\n            bool search_all)\n{\n  std::list<std::string> ret;\n\n  std::string potential = dir + name;\n\n  std::string tmp = kpse_readable_file (potential);\n\n  if (! tmp.empty ())\n    {\n      ret.push_back (potential);\n\n      if (! search_all)\n        return ret;\n    }\n\n  return ret;\n}\n\n/* This is called when NAME is absolute or explicitly relative; if it's\n   readable, return (a list containing) it; otherwise, return NULL.  */\n\nstatic std::list<std::string>\nabsolute_search (const std::string& name)\n{\n  std::list<std::string> ret_list;\n  std::string found = kpse_readable_file (name);\n\n  /* Add 'found' to the return list even if it's null; that tells\n     the caller we didn't find anything.  */\n  ret_list.push_back (found);\n\n  return ret_list;\n}\n\n/* This is the hard case -- look for NAME in PATH.  If ALL is false,\n   return the first file found.  Otherwise, search all elements of PATH.  */\n\nstatic std::list<std::string>\npath_search (const std::string& path, const std::string& name, bool all)\n{\n  std::list<std::string> ret_list;\n  bool done = false;\n\n  for (kpse_path_iterator pi (path); ! done && pi != std::string::npos; pi++)\n    {\n      std::string elt = *pi;\n\n      std::list<std::string> found;\n\n      // Do not touch the device if present\n      if (NAME_BEGINS_WITH_DEVICE (elt))\n        {\n          while (elt.length () > 3\n                 && IS_DIR_SEP (elt[2]) && IS_DIR_SEP (elt[3]))\n            {\n              elt[2] = elt[1];\n              elt[1] = elt[0];\n              elt = elt.substr (1);\n            }\n        }\n#if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \\\n     && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))\n      else\n        {\n          // We never want to search the whole disk.\n          while (elt.length () > 1\n                 && IS_DIR_SEP (elt[0]) && IS_DIR_SEP (elt[1]))\n            elt = elt.substr (1);\n        }\n#endif\n\n      // Our caller (search), also tests first_search, and does the resetting.\n      if (first_search)\n        found = std::list<std::string> ();\n\n      // Search the filesystem.\n      if (found.empty ())\n        {\n          std::string dir = kpse_element_dir (elt);\n\n          if (! dir.empty ())\n            found = dir_search (dir, name, all);\n        }\n\n      // Did we find anything anywhere?\n      if (! found.empty ())\n        {\n          if (all)\n            ret_list.splice (ret_list.end (), found);\n          else\n            {\n              ret_list.push_back (found.front ());\n              done = true;\n            }\n        }\n    }\n\n  return ret_list;\n}\n\n/* If NAME has a leading ~ or ~user, Unix-style, expand it to the user's home\n   directory, and return a new malloced string.  If no ~, or no <pwd.h>, just\n   return NAME.  */\n\nstatic std::string\nkpse_tilde_expand (const std::string& name)\n{\n  std::string expansion;\n\n  // If no leading tilde, do nothing.\n  if (name.empty () || name[0] != '~')\n    {\n      expansion = name;\n\n      /* If a bare tilde, return the home directory or '.'.  (Very unlikely\n         that the directory name will do anyone any good, but ...  */\n    }\n  else if (name.length () == 1)\n    {\n      expansion = octave::sys::env::get_home_directory ();\n\n      if (expansion.empty ())\n        expansion = \".\";\n\n      /* If '~/', remove any trailing / or replace leading // in $HOME.\n         Should really check for doubled intermediate slashes, too.  */\n    }\n  else if (IS_DIR_SEP (name[1]))\n    {\n      unsigned c = 1;\n      std::string home = octave::sys::env::get_home_directory ();\n\n      if (home.empty ())\n        home = \".\";\n\n      std::size_t home_len = home.length ();\n\n#if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \\\n     && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))\n      // handle leading \"//\"\n      if (home_len > 1 && IS_DIR_SEP (home[0]) && IS_DIR_SEP (home[1]))\n        home = home.substr (1);\n#endif\n\n      // omit '/' after '~'\n      if (IS_DIR_SEP (home[home_len - 1]))\n        c++;\n\n      expansion = home + name.substr (c);\n    }\n  else\n    /* If \"~user\" or \"~user/\", look up user in the passwd database\n       (but OS/2 doesn't have this concept).  */\n#if defined (HAVE_PWD_H)\n    {\n      unsigned c = 2;\n\n      // find user name\n      while (name.length () > c && ! IS_DIR_SEP (name[c]))\n        c++;\n\n      std::string user = name.substr (1, c-1);\n\n      /* We only need the cast here for (deficient) systems\n         which do not declare 'getpwnam' in <pwd.h>.  */\n      octave::sys::password p = octave::sys::password::getpwnam (user);\n\n      // If no such user, just use '.'.\n      std::string home = (p ? p.dir () : \".\");\n\n      if (home.empty ())\n        home = \".\";\n\n#  if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \\\n       && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))\n      // handle leading \"//\"\n      if (home.length () > 1 && IS_DIR_SEP (home[0]) && IS_DIR_SEP (home[1]))\n        home = home.substr (1);\n#  endif\n\n      // If HOME ends in '/', omit the '/' after ~user.\n      if (name.length () > c && IS_DIR_SEP (home.back ()))\n        c++;\n\n      expansion = (name.length () > c ? home : home + name.substr (c));\n    }\n#else   // not HAVE_PWD_H\n  expansion = name;\n#endif  // HAVE_PWD_H\n\n  return expansion;\n}\n\n/* Search PATH for ORIGINAL_NAME.  If ALL is false, or ORIGINAL_NAME is\n   absolute_p, check ORIGINAL_NAME itself.  Otherwise, look at each element of\n   PATH for the first readable ORIGINAL_NAME.\n\n   Always return a list; if no files are found, the list will contain just\n   NULL.  If ALL is true, the list will be terminated with NULL.  */\n\nstatic std::list<std::string>\nsearch (const std::string& path, const std::string& original_name, bool all)\n{\n  std::list<std::string> ret_list;\n  bool absolute_p;\n\n  // Make a leading ~ count as an absolute filename.\n  std::string name = kpse_tilde_expand (original_name);\n\n  /* If the first name is absolute or explicitly relative,\n     no need to consider PATH at all.  */\n  absolute_p = kpse_absolute_p (name, true);\n\n#if OCTAVE_KPSE_DEBUG\n  std::cerr << \"kpse: start search (file=\" << name\n            << \", find_all=\" << all << \", path=\" << path << \").\" << std::endl;\n#endif\n\n  // Find the file(s).\n  ret_list = (absolute_p ? absolute_search (name)\n                         : path_search (path, name, all));\n\n  /* The very first search is for texmf.cnf.  We can't log that, since\n     we want to allow setting TEXMFLOG in texmf.cnf.  */\n  if (first_search)\n    {\n      first_search = false;\n    }\n#if OCTAVE_KPSE_DEBUG\n  else\n    {\n      // Record the filenames we found.\n      std::cerr << \"kpse: search (\" << original_name << \") =>\";\n      log_search (ret_list);\n      std::cerr << std::endl;\n    }\n#endif\n\n  return ret_list;\n}\n\n/* Search PATH for the first NAME.  */\n\n/* Perform tilde expansion on NAME.  If the result is an absolute or explicitly\n   relative filename, check whether it is a readable (regular) file.\n\n   Otherwise, look in each of the directories specified in PATH (also do tilde\n   and variable expansion on elements in PATH).\n\n   The caller must expand PATH.  This is because it makes more sense to do this\n   once, in advance, instead of for every search using it.\n\n   In any case, return the complete filename if found, otherwise NULL.  */\n\nstd::string\nkpse_path_search (const std::string& path, const std::string& name)\n{\n  std::list<std::string> ret_list = search (path, name, false);\n\n  return ret_list.empty () ? \"\" : ret_list.front ();\n}\n\n/* Like 'kpse_path_search' with MUST_EXIST true, but return a list of\n   all the filenames (or NULL if none), instead of taking the first.  */\n\nstd::list<std::string>\nkpse_all_path_search (const std::string& path, const std::string& name)\n{\n  return search (path, name, true);\n}\n\n/* This is the hard case -- look in each element of PATH for each element of\n   NAMES.  If ALL is false, return the first file found.  Otherwise, search all\n   elements of PATH.  */\n\nstd::list<std::string>\npath_find_first_of (const std::string& path,\n                    const std::list<std::string>& names, bool all)\n{\n  std::list<std::string> ret_list;\n  bool done = false;\n\n  for (kpse_path_iterator pi (path); ! done && pi != std::string::npos; pi++)\n    {\n      std::string elt = *pi;\n\n      std::string dir;\n      std::list<std::string> found;\n\n      // Do not touch the device if present\n      if (NAME_BEGINS_WITH_DEVICE (elt))\n        {\n          while (elt.length () > 3\n                 && IS_DIR_SEP (elt[2]) && IS_DIR_SEP (elt[3]))\n            {\n              elt[2] = elt[1];\n              elt[1] = elt[0];\n              elt = elt.substr (1);\n            }\n        }\n#if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \\\n     && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))\n      else\n        {\n          // We never want to search the whole disk.\n          while (elt.length () > 1\n                 && IS_DIR_SEP (elt[0]) && IS_DIR_SEP (elt[1]))\n            elt = elt.substr (1);\n        }\n#endif\n\n      // We have to search one directory at a time.\n      dir = kpse_element_dir (elt);\n\n      if (! dir.empty ())\n        {\n          for (auto it = names.cbegin (); it != names.cend () && ! done; it++)\n            {\n              std::string name = *it;\n\n              /* Our caller (find_first_of), also tests first_search,\n                 and does the resetting.  */\n              if (first_search)\n                found = std::list<std::string> ();\n\n              // Search the filesystem.\n              if (found.empty ())\n                found = dir_search (dir, name, all);\n\n              // Did we find anything anywhere?\n              if (! found.empty ())\n                {\n                  if (all)\n                    ret_list.splice (ret_list.end (), found);\n                  else\n                    {\n                      ret_list.push_back (found.front ());\n                      done = true;\n                    }\n                }\n            }\n        }\n    }\n\n  return ret_list;\n}\n\nstatic std::list<std::string>\nfind_first_of (const std::string& path, const std::list<std::string>& names,\n               bool all)\n{\n  std::list<std::string> ret_list;\n\n#if OCTAVE_KPSE_DEBUG\n  std::cerr << \"kpse: start find_first_of (\";\n\n  for (auto p = names.cbegin (); p != names.cend (); p++)\n    {\n      if (p == names.cbegin ())\n        std::cerr << *p;\n      else\n        std::cerr << \", \" << *p;\n    }\n\n  std::cerr << \"), path=\" << path << '.' << std::endl;\n#endif\n\n  for (const auto& name : names)\n    {\n      if (kpse_absolute_p (name, true))\n        {\n          /* If the name is absolute or explicitly relative, no need to\n             consider PATH at all.  If we find something, then we are done.  */\n          ret_list = absolute_search (name);\n\n          if (! ret_list.empty ())\n            return ret_list;\n        }\n    }\n\n  // Find the file.\n  ret_list = path_find_first_of (path, names, all);\n\n  /* The very first search is for texmf.cnf.  We can't log that, since\n     we want to allow setting TEXMFLOG in texmf.cnf.  */\n  if (first_search)\n    {\n      first_search = false;\n    }\n#if OCTAVE_KPSE_DEBUG\n  else\n    {\n      /* Record the filenames we found, if desired.  And wrap them in a\n         debugging line if we're doing that.  */\n      std::cerr << \"kpse: find_first_of (\";\n\n      for (auto p = names.cbegin (); p != names.cend (); p++)\n        {\n          if (p == names.cbegin ())\n            std::cerr << *p;\n          else\n            std::cerr << \", \" << *p;\n        }\n\n      std::cerr << \") =>\";\n\n      log_search (ret_list);\n\n      std::cerr << std::endl;\n    }\n#endif\n\n  return ret_list;\n}\n\n/* Search each element of PATH for each element in the list of NAMES.\n   Return the first one found.  */\n\nstd::string\nkpse_path_find_first_of (const std::string& path,\n                         const std::list<std::string>& names)\n{\n  std::list<std::string> ret_list = find_first_of (path, names, false);\n\n  return ret_list.empty () ? \"\" : ret_list.front ();\n}\n\n/* Search each element of PATH for each element of NAMES and return a\n   list containing everything found, in the order found.  */\n\n/* Like 'kpse_path_find_first_of' with MUST_EXIST true, but return a\n   list of all the filenames (or NULL if none), instead of taking the\n   first.  */\n\nstd::list<std::string>\nkpse_all_path_find_first_of (const std::string& path,\n                             const std::list<std::string>& names)\n{\n  return find_first_of (path, names, true);\n}\n\n/* Perform tilde expansion on each element of the path, and include\n   canonical directory names for only the actually existing\n   directories in the result.  */\n\nstd::string\nkpse_path_expand (const std::string& path)\n{\n  std::string ret;\n  unsigned len = 0;\n\n  // Now expand each of the path elements, printing the results\n  for (kpse_path_iterator pi (path); pi != std::string::npos; pi++)\n    {\n      std::string elt = kpse_tilde_expand (*pi);\n\n      std::string dir;\n\n      // Do not touch the device if present\n      if (NAME_BEGINS_WITH_DEVICE (elt))\n        {\n          while (elt.length () > 3\n                 && IS_DIR_SEP (elt[2]) && IS_DIR_SEP (elt[3]))\n            {\n              elt[2] = elt[1];\n              elt[1] = elt[0];\n              elt = elt.substr (1);\n            }\n        }\n#if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \\\n     && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))\n      else\n        {\n          // We never want to search the whole disk.\n          while (elt.length () > 1\n                 && IS_DIR_SEP (elt[0]) && IS_DIR_SEP (elt[1]))\n            elt = elt.substr (1);\n        }\n#endif\n\n      /* Search the disk for all dirs in the component specified.\n         Be faster to check the database, but this is more reliable.  */\n      dir = kpse_element_dir (elt);\n\n      std::size_t dirlen = dir.length ();\n\n      if (dirlen > 0)\n        {\n          ret += dir;\n          len += dirlen;\n\n          // Retain trailing slash if that's the root directory.\n          if (dirlen == 1\n              || (dirlen == 3 && NAME_BEGINS_WITH_DEVICE (dir)\n                  && IS_DIR_SEP (dir[2])))\n            {\n              ret += ENV_SEP_STRING;\n              len++;\n            }\n\n          ret[len-1] = ENV_SEP;\n        }\n    }\n\n  if (! ret.empty ())\n    ret.pop_back ();\n\n  return ret;\n}\n\n/* braces.c -- code for doing word expansion in curly braces.\n   Taken from bash 1.14.5.  [And subsequently modified for kpatshea.]\n\n   Copyright (C) 1987,1991 Free Software Foundation, Inc.  */\n\n#define brace_whitespace(c) (! (c) || (c) == ' ' || (c) == '\\t' || (c) == '\\n')\n\n/* Basic idea:\n\n   Segregate the text into 3 sections: preamble (stuff before an open brace),\n   postamble (stuff after the matching close brace) and amble (stuff after\n   preamble, and before postamble).  Expand amble, and then tack on the\n   expansions to preamble.  Expand postamble, and tack on the expansions to the\n   result so far.  */\n\n/* Return a new array of strings which is the result of appending each string\n   in ARR2 to each string in ARR1.  The resultant array is len (arr1) * len\n   (arr2) long.  For convenience, ARR1 (and its contents) are free ()'ed.  ARR1\n   can be NULL, in that case, a new version of ARR2 is returned.  */\n\nstatic std::list<std::string>\narray_concat (const std::list<std::string>& arr1,\n              const std::list<std::string>& arr2)\n{\n  std::list<std::string> result;\n\n  if (arr1.empty ())\n    result = arr2;\n  else if (arr2.empty ())\n    result = arr1;\n  else\n    {\n      for (const auto& elt_2 : arr2)\n        for (const auto& elt_1 : arr1)\n          result.push_back (elt_1 + elt_2);\n    }\n\n  return result;\n}\n\nstatic int brace_gobbler (const std::string&, int&, int);\nstatic std::list<std::string> expand_amble (const std::string&);\n\n// Return an array of strings; the brace expansion of TEXT.\nstatic std::list<std::string>\nbrace_expand (const std::string& text)\n{\n  // Find the text of the preamble.\n  int i = 0;\n  int c = brace_gobbler (text, i, '{');\n\n  std::string preamble = text.substr (0, i);\n\n  std::list<std::string> result (1, preamble);\n\n  if (c == '{')\n    {\n      // Find the amble.  This is the stuff inside this set of braces.\n      int start = ++i;\n      c = brace_gobbler (text, i, '}');\n\n      // What if there isn't a matching close brace?\n      if (! c)\n        {\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:pathsearch-syntax\",\n             \"%s: Unmatched {\", text.c_str ());\n\n          result = std::list<std::string> (1, text);\n        }\n      else\n        {\n          std::string amble = text.substr (start, i-start);\n          result = array_concat (result, expand_amble (amble));\n\n          std::string postamble = text.substr (i+1);\n          result = array_concat (result, brace_expand (postamble));\n        }\n    }\n\n  return result;\n}\n\n// The character which is used to separate arguments.\nstatic int brace_arg_separator = ',';\n\n/* Expand the text found inside of braces.  We simply try to split the text at\n   BRACE_ARG_SEPARATORs into separate strings.  We then brace expand each slot\n   which needs it, until there are no more slots which need it.  */\nstatic std::list<std::string>\nexpand_amble (const std::string& text)\n{\n  std::list<std::string> result;\n\n  std::size_t text_len = text.length ();\n  std::size_t start;\n  int i, c;\n\n  for (start = 0, i = 0, c = 1; c && start < text_len; start = ++i)\n    {\n      int i0 = i;\n      int c0 = brace_gobbler (text, i0, brace_arg_separator);\n      int i1 = i;\n      int c1 = brace_gobbler (text, i1, ENV_SEP);\n      c = c0 | c1;\n      i = (i0 < i1 ? i0 : i1);\n\n      std::string tem = text.substr (start, i-start);\n\n      std::list<std::string> partial = brace_expand (tem);\n\n      if (result.empty ())\n        result = partial;\n      else\n        result.splice (result.end (), partial);\n    }\n\n  return result;\n}\n\n/* Start at INDEX, and skip characters in TEXT.  Set INDEX to the\n   index of the character matching SATISFY.  This understands about\n   quoting.  Return the character that caused us to stop searching;\n   this is either the same as SATISFY, or 0.  */\nstatic int\nbrace_gobbler (const std::string& text, int& indx, int satisfy)\n{\n  int c = 0;\n  int level = 0;\n  int quoted = 0;\n  int pass_next = 0;\n\n  std::size_t text_len = text.length ();\n\n  std::size_t i = indx;\n\n  for (; i < text_len; i++)\n    {\n      c = text[i];\n\n      if (pass_next)\n        {\n          pass_next = 0;\n          continue;\n        }\n\n      /* A backslash escapes the next character.  This allows backslash to\n         escape the quote character in a double-quoted string.  */\n      if (c == '\\\\' && (quoted == 0 || quoted == '\"' || quoted == '`'))\n        {\n          pass_next = 1;\n          continue;\n        }\n\n      if (quoted)\n        {\n          if (c == quoted)\n            quoted = 0;\n          continue;\n        }\n\n      if (c == '\"' || c == '\\'' || c == '`')\n        {\n          quoted = c;\n          continue;\n        }\n\n      if (c == satisfy && ! level && ! quoted)\n        {\n          /* We ignore an open brace surrounded by whitespace, and also an open\n             brace followed immediately by a close brace, that was preceded\n             with whitespace.  */\n          if (c == '{'\n              && ((i == 0 || brace_whitespace (text[i-1]))\n                  && (i+1 < text_len\n                      && (brace_whitespace (text[i+1]) || text[i+1] == '}'))))\n            continue;\n          /* If this is being compiled as part of bash, ignore the '{'\n             in a '${ }' construct.  */\n          if ((c != '{') || i == 0 || (text[i-1] != '$'))\n            break;\n        }\n\n      if (c == '{')\n        level++;\n      else if (c == '}' && level)\n        level--;\n    }\n\n  indx = i;\n  c = (c == satisfy) ? c : 0;\n  return c;\n}\n\n/* Given a path element ELT, return a the element with a trailing slash or an\n   empty string if the element is not a directory.\n\n   It's up to the caller to expand ELT.  This is because this routine is most\n   likely only useful to be called from 'kpse_path_search', which has already\n   assumed expansion has been done.  */\n\nstd::string\nkpse_element_dir (const std::string& elt)\n{\n  std::string ret;\n\n  // If given nothing, return nothing.\n  if (elt.empty ())\n    return ret;\n\n  if (octave::sys::dir_exists (elt))\n    {\n      ret = elt;\n\n      char last_char = ret.back ();\n\n      if (! (IS_DIR_SEP (last_char) || IS_DEVICE_SEP (last_char)))\n        ret += DIR_SEP_STRING;\n    }\n\n  return ret;\n}\n"
  },
  {
    "path": "liboctave/util/kpse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_kpse_h)\n#define octave_kpse_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n\n// A way to step through a path, extracting one directory name at a\n// time.\n\nclass kpse_path_iterator\n{\npublic:\n\n  kpse_path_iterator () = delete;\n\n  kpse_path_iterator (const std::string& p)\n    : m_path (p), m_b (0), m_e (0), m_len (m_path.length ())\n  {\n    set_end ();\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE_CTOR (kpse_path_iterator)\n  OCTAVE_DISABLE_COPY_MOVE_ASGN (kpse_path_iterator)\n\n  ~kpse_path_iterator () = default;\n\n  kpse_path_iterator operator ++ (int)\n  {\n    kpse_path_iterator retval (*this);\n    next ();\n    return retval;\n  }\n\n  std::string operator * () { return m_path.substr (m_b, m_e-m_b); }\n\n  bool operator != (const std::size_t sz) { return m_b != sz; }\n\nprivate:\n\n  const std::string& m_path;\n  std::size_t m_b;\n  std::size_t m_e;\n  std::size_t m_len;\n\n  void set_end ();\n  void next ();\n};\n\nextern unsigned int kpse_debug;\n\nextern std::list<std::string>\nkpse_all_path_search (const std::string& path, const std::string& name);\n\nextern std::list<std::string>\nkpse_all_path_find_first_of (const std::string& path,\n                             const std::list<std::string>& names);\n\nextern std::string\nkpse_element_dir (const std::string& elt);\n\nextern std::list<std::string>\nkpse_all_path_search (const std::string& path, const std::string& name);\n\nextern std::string\nkpse_path_expand (const std::string& path);\n\nextern std::string\nkpse_path_find_first_of (const std::string& path,\n                         const std::list<std::string>& names);\n\nextern std::string\nkpse_path_search (const std::string& path, const std::string& name);\n\n#endif\n"
  },
  {
    "path": "liboctave/util/lo-array-errwarn.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n\n#include <limits>\n#include <sstream>\n\n#include \"lo-array-errwarn.h\"\n#include \"oct-error.h\"\n\nstatic constexpr octave_idx_type IDX_MAX = dim_vector::dim_max ();\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Text constants used to shorten code below.\n\nstatic const char *error_id_nonconformant_args\n  = \"Octave:nonconformant-args\";\n\nstatic const char *error_id_index_out_of_bounds\n  = \"Octave:index-out-of-bounds\";\n\nstatic const char *error_id_invalid_index = \"Octave:invalid-index\";\n\nstatic const char *warning_id_nearly_singular_matrix\n  = \"Octave:nearly-singular-matrix\";\n\nstatic const char *warning_id_singular_matrix = \"Octave:singular-matrix\";\n\nvoid\nerr_nan_to_logical_conversion ()\n{\n  (*current_liboctave_error_handler)\n    (\"invalid conversion from NaN to logical\");\n}\n\nvoid\nerr_nan_to_character_conversion ()\n{\n  (*current_liboctave_error_handler)\n    (\"invalid conversion from NaN to character\");\n}\n\nvoid\nerr_nonconformant (const char *op,\n                   octave_idx_type op1_len, octave_idx_type op2_len)\n{\n  const char *err_id = error_id_nonconformant_args;\n\n  (*current_liboctave_error_with_id_handler)\n    (err_id, \"%s: nonconformant arguments (op1 len: %\" OCTAVE_IDX_TYPE_FORMAT\n     \", op2 len: % \" OCTAVE_IDX_TYPE_FORMAT \")\",\n     op, op1_len, op2_len);\n}\n\nvoid\nerr_nonconformant (const char *op,\n                   octave_idx_type op1_nr, octave_idx_type op1_nc,\n                   octave_idx_type op2_nr, octave_idx_type op2_nc)\n{\n  const char *err_id = error_id_nonconformant_args;\n\n  (*current_liboctave_error_with_id_handler)\n    (err_id, \"%s: nonconformant arguments \"\n     \"(op1 is %\" OCTAVE_IDX_TYPE_FORMAT \"x%\" OCTAVE_IDX_TYPE_FORMAT \", \"\n     \"op2 is %\" OCTAVE_IDX_TYPE_FORMAT\"x%\" OCTAVE_IDX_TYPE_FORMAT \")\",\n     op, op1_nr, op1_nc, op2_nr, op2_nc);\n}\n\nvoid\nerr_nonconformant (const char *op,\n                   const dim_vector& op1_dims, const dim_vector& op2_dims)\n{\n  const char *err_id = error_id_nonconformant_args;\n\n  std::string op1_dims_str = op1_dims.str ();\n  std::string op2_dims_str = op2_dims.str ();\n\n  (*current_liboctave_error_with_id_handler)\n    (err_id, \"%s: nonconformant arguments (op1 is %s, op2 is %s)\",\n     op, op1_dims_str.c_str (), op2_dims_str.c_str ());\n}\n\nvoid\nerr_del_index_out_of_range (bool is1d, octave_idx_type idx,\n                            octave_idx_type ext)\n{\n  const char *err_id = error_id_index_out_of_bounds;\n\n  (*current_liboctave_error_with_id_handler)\n    (err_id, \"A(%s) = []: index out of bounds: value %\" OCTAVE_IDX_TYPE_FORMAT\n     \" out of bound %\" OCTAVE_IDX_TYPE_FORMAT,\n     is1d ? \"I\" : \"..,I,..\", idx, ext);\n}\n\n// Show the expression that caused the error, e.g.,  \"A(-1,_)\",\n// \"A(0+1i)\", \"A(_,3)\".  Show how many indices come before/after the\n// offending one, e.g., (<error>), (<error>,_), or (_,<error>,...[x5]...)\n\nstd::string\nindex_exception::expression () const\n{\n  std::ostringstream buf;\n\n  if (m_var.empty () || m_var == \"<unknown>\")\n    buf << \"index \";\n  else\n    buf << m_var;\n\n  bool show_parens = m_dim > 0;\n\n  if (show_parens)\n    {\n      if (m_dim < 5)\n        {\n          buf << '(';\n\n          for (octave_idx_type i = 1; i < m_dim; i++)\n            buf << \"_,\";\n        }\n      else\n        buf << \"(...[x\" << m_dim - 1 << \"]...\";\n    }\n\n  buf << m_index;\n\n  if (show_parens)\n    {\n      if (m_nd - m_dim < 5)\n        {\n          for (octave_idx_type i = 0; i < m_nd - m_dim; i++)\n            buf << \",_\";\n\n          if (m_nd >= m_dim)\n            buf << ')';\n        }\n      else\n        buf << \"...[x\" << m_nd - m_dim << \"]...)\";\n    }\n\n  return buf.str ();\n}\n\nclass invalid_index : public index_exception\n{\npublic:\n\n  invalid_index (const std::string& value, octave_idx_type ndim,\n                 octave_idx_type dimen)\n    : index_exception (value, ndim, dimen)\n  {\n    // Virtual, but the one we want to call is defined in this class.\n    update_message ();\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE (invalid_index)\n\n  void update_message ()\n  {\n    static std::string exp\n      = std::to_string (std::numeric_limits<octave_idx_type>::digits);\n\n    set_message (expression ()\n                 + \": subscripts must be either integers 1 to (2^\" + exp\n                 + \")-1 or logicals\");\n  }\n\n  // ID of error to throw\n  const char * err_id () const\n  {\n    return error_id_invalid_index;\n  }\n\n  index_exception * dup ()\n  {\n    invalid_index *retval = new invalid_index {*this};\n    retval->set_identifier (retval->err_id ());\n    return retval;\n  }\n};\n\n// Complain if an index is negative, fractional, or too big.\n\nvoid\nerr_invalid_index (const std::string& idx, octave_idx_type nd,\n                   octave_idx_type dim, const std::string&)\n{\n  invalid_index e (idx, nd, dim);\n\n  throw e;\n}\n\nvoid\nerr_invalid_index (double n, octave_idx_type nd, octave_idx_type dim,\n                   const std::string& var)\n{\n  std::ostringstream buf;\n  buf << n + 1;\n\n  if (! std::isnan (n))\n    {\n      // if n not an integer, but would be printed as one, show diff\n      double nearest = std::floor (n + 1.5);\n      if (n + 1 != nearest && (buf.str ().find ('.') == std::string::npos))\n        buf << std::showpos << (n + 1 - nearest);\n    }\n\n  err_invalid_index (buf.str (), nd, dim, var);\n}\n\nvoid\nerr_invalid_index (octave_idx_type n, octave_idx_type nd,\n                   octave_idx_type dim, const std::string& var)\n{\n  if (n == IDX_MAX + 1)\n    err_invalid_index\n      (std::to_string\n         (static_cast<std::make_unsigned_t<octave_idx_type>> (n) + 1),\n       nd, dim, var);\n  else\n    err_invalid_index (std::to_string (n + 1), nd, dim, var);\n}\n\nvoid\nerr_invalid_index (uint64_t n, octave_idx_type nd,\n                   octave_idx_type dim, const std::string& var)\n{\n  err_invalid_index (std::to_string (n + 1), nd, dim, var);\n}\n\n// Complain for read access beyond the bounds of an array.\n\nclass out_of_range : public index_exception\n{\npublic:\n\n  out_of_range (const std::string& value, octave_idx_type nd,\n                octave_idx_type dim, octave_idx_type ext,\n                const dim_vector& size)\n    : index_exception (value, nd, dim), m_size (size), m_extent (ext)\n  {\n    // Virtual, but the one we want to call is defined in this class.\n    update_message ();\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE (out_of_range)\n\n  void update_message ()\n  {\n    set_message (expression () + \": out of bound \"\n                 + std::to_string (m_extent)\n                 + \" (dimensions are \" + m_size.str ('x') + \")\");\n  }\n\n  // ID of error to throw.\n  const char * err_id () const\n  {\n    return error_id_index_out_of_bounds;\n  }\n\n  index_exception * dup ()\n  {\n    out_of_range *retval = new out_of_range {*this};\n    retval->set_identifier (retval->err_id ());\n    return retval;\n  }\n\nprivate:\n\n  // Dimension of object being accessed.\n  dim_vector m_size;\n\n  // Length of dimension being accessed.\n  octave_idx_type m_extent;\n};\n\n// Complain of an index that is out of range\nvoid\nerr_index_out_of_range (int nd, int dim, octave_idx_type idx,\n                        octave_idx_type ext, const dim_vector& dv)\n{\n  throw out_of_range (std::to_string (idx), nd, dim, ext, dv);\n}\n\nvoid\nerr_invalid_resize ()\n{\n  (*current_liboctave_error_with_id_handler)\n    (\"Octave:invalid-resize\",\n     \"Invalid resizing operation or ambiguous assignment to an out-of-bounds array element\");\n}\n\nvoid\nwarn_singular_matrix (double rcond)\n{\n  if (rcond == 0.0)\n    {\n      (*current_liboctave_warning_with_id_handler)\n        (warning_id_singular_matrix,\n         \"matrix singular to machine precision\");\n    }\n  else\n    {\n      (*current_liboctave_warning_with_id_handler)\n        (warning_id_nearly_singular_matrix,\n         \"matrix singular to machine precision, rcond = %g\", rcond);\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n/* Tests in test/index.tst */\n"
  },
  {
    "path": "liboctave/util/lo-array-errwarn.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_array_errwarn_h)\n#define octave_lo_array_errwarn_h 1\n\n#include \"octave-config.h\"\n\n#include \"dim-vector.h\"\n#include \"quit.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Exception thrown by err_invalid_index\n// This is thrown when the invalid index is detected, at which point nd and dim\n// are usually not known.  It is caught at the place they are known, where a\n// new err_invalid_index is called.\n//\n// Typically, this should be caught after any call to\n// octave_value_list::index_vector()\n\nclass OCTAVE_EXCEPTION_API index_exception : public execution_exception\n{\npublic:\n\n  index_exception () = delete;\n\n  index_exception (const std::string& index, octave_idx_type nd = 0,\n                   octave_idx_type dim = -1, const char *var = \"\")\n    : m_index (index), m_nd (nd), m_dim (dim), m_var (var)\n  {\n    set_message (expression ());\n  }\n\n  OCTAVE_DEFAULT_COPY_MOVE (index_exception)\n\n  ~index_exception () = default;\n\n  // ID of error to throw.\n  virtual const char * err_id () const = 0;\n\n  // By default, update message to show the erroneous index expression.\n  virtual void update_message () { set_message (expression ()); }\n\n  // Position of error: dimension in error, and number of dimensions.\n  void set_pos (octave_idx_type nd_arg, octave_idx_type dim_arg)\n  {\n    m_nd = nd_arg;\n    m_dim = dim_arg;\n\n    update_message ();\n  }\n\n  void set_pos_if_unset (octave_idx_type nd_arg, octave_idx_type dim_arg)\n  {\n    if (m_nd == 0)\n      {\n        m_nd  = nd_arg;\n        m_dim = dim_arg;\n\n        update_message ();\n      }\n  }\n\n  // Name of variable being indexed.  eye(2)(1,1) gives \"<unknown>\".\n  void set_var (const std::string& var_arg = \"\")\n  {\n    m_var = var_arg;\n\n    update_message ();\n  }\n\n  // Return a newly allocated copy of the index_exception object.\n  virtual index_exception * dup () = 0;\n\nprivate:\n\n  // Value of invalid index.\n  std::string m_index;\n\nprotected:\n\n  // Show what's wrong, e.g., A(-1,_), A(0+1i).\n  OCTAVE_API std::string expression () const;\n\n  // Number of dimensions of indexed object.\n  octave_idx_type m_nd;\n\n  // Dimension number in which invalid index occurred.\n  octave_idx_type m_dim;\n\n  // Name of variable being indexed.\n  std::string m_var;\n};\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_nan_to_logical_conversion ();\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_nan_to_character_conversion ();\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_nonconformant (const char *op, octave_idx_type op1_len,\n                   octave_idx_type op2_len);\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_nonconformant (const char *op,\n                   octave_idx_type op1_nr, octave_idx_type op1_nc,\n                   octave_idx_type op2_nr, octave_idx_type op2_nc);\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_nonconformant (const char *op,\n                   const dim_vector& op1_dims, const dim_vector& op2_dims);\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_index_out_of_range (int ndims, int dim, octave_idx_type idx,\n                        octave_idx_type ext, const dim_vector& dv);\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_del_index_out_of_range (bool is1d, octave_idx_type iext,\n                            octave_idx_type ext);\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_invalid_index (double n, octave_idx_type nd = 0,\n                   octave_idx_type dim = 0,\n                   const std::string& var = \"\");\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_invalid_index (octave_idx_type n, octave_idx_type nd = 0,\n                   octave_idx_type dim = 0,\n                   const std::string& var = \"\");\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_invalid_index (uint64_t n, octave_idx_type nd = 0,\n                   octave_idx_type dim = 0,\n                   const std::string& var = \"\");\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_invalid_index (const std::string& idx, octave_idx_type nd = 0,\n                   octave_idx_type dim = 0,\n                   const std::string& var = \"\");\n\nOCTAVE_NORETURN extern OCTAVE_API void\nerr_invalid_resize ();\n\nextern OCTAVE_API void\nwarn_singular_matrix (double rcond = 0.0);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/lo-error.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_error_h)\n#define octave_lo_error_h 1\n\n#warning 'header file \"lo-error.h\" is deprecated, use \"oct-error.h\" instead'\n\n#include \"oct-error.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/util/lo-hash.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_hash_h)\n#define octave_lo_hash_h 1\n\n#warning 'header file \"lo-hash.h\" is deprecated, use \"oct-hash.h\" instead'\n\n#include \"oct-hash.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/util/lo-ieee.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cmath>\n#include <limits>\n\n#include \"lo-ieee.h\"\n#include \"mach-info.h\"\n#include \"oct-error.h\"\n\nstatic double lo_inf;\nstatic double lo_nan;\nstatic double lo_na;\n\nstatic float lo_float_inf;\nstatic float lo_float_nan;\nstatic float lo_float_na;\n\nstatic int lo_ieee_hw;\nstatic int lo_ieee_lw;\n\n#if defined (HAVE_IEEE754_QNAN)\n  #define LO_IEEE_NA_HW 0x7FF840F4\n#else\n  #define LO_IEEE_NA_HW 0x7FF040F4\n#endif\n#define LO_IEEE_NA_LW 0x40000000\n#define LO_IEEE_NA_FLOAT 0x7FC207A2\n\nint\n__lo_ieee_is_NA (double x)\n{\n  lo_ieee_double t;\n  t.value = x;\n  return (std::isnan (x) && t.word[lo_ieee_hw] == LO_IEEE_NA_HW\n          && t.word[lo_ieee_lw] == LO_IEEE_NA_LW) ? 1 : 0;\n}\n\ndouble\nlo_ieee_inf_value ()\n{\n  octave_ieee_init ();\n\n  return lo_inf;\n}\n\ndouble\nlo_ieee_na_value ()\n{\n  octave_ieee_init ();\n\n  return lo_na;\n}\n\ndouble\nlo_ieee_nan_value ()\n{\n  octave_ieee_init ();\n\n  return lo_nan;\n}\n\nint\n__lo_ieee_float_is_NA (float x)\n{\n  lo_ieee_float t;\n  t.value = x;\n  return (std::isnan (x) && (t.word == LO_IEEE_NA_FLOAT)) ? 1 : 0;\n}\n\nfloat\nlo_ieee_float_inf_value ()\n{\n  octave_ieee_init ();\n\n  return lo_float_inf;\n}\n\nfloat\nlo_ieee_float_na_value ()\n{\n  octave_ieee_init ();\n\n  return lo_float_na;\n}\n\nfloat\nlo_ieee_float_nan_value ()\n{\n  octave_ieee_init ();\n\n  return lo_float_nan;\n}\n\nvoid\noctave_ieee_init ()\n{\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n      octave::mach_info::float_format ff = octave::mach_info::native_float_format ();\n\n      switch (ff)\n        {\n        case octave::mach_info::flt_fmt_ieee_big_endian:\n        case octave::mach_info::flt_fmt_ieee_little_endian:\n          {\n            lo_nan = std::numeric_limits<double>::quiet_NaN ();\n            lo_inf = std::numeric_limits<double>::infinity ();\n\n            lo_float_nan = std::numeric_limits<float>::quiet_NaN ();\n            lo_float_inf = std::numeric_limits<float>::infinity ();\n\n            // The following is patterned after code in R.\n\n            if (ff == octave::mach_info::flt_fmt_ieee_big_endian)\n              {\n                lo_ieee_hw = 0;\n                lo_ieee_lw = 1;\n              }\n            else\n              {\n                lo_ieee_hw = 1;\n                lo_ieee_lw = 0;\n              }\n\n            lo_ieee_double t;\n            t.word[lo_ieee_hw] = LO_IEEE_NA_HW;\n            t.word[lo_ieee_lw] = LO_IEEE_NA_LW;\n\n            lo_na = t.value;\n\n            lo_ieee_float tf;\n            tf.word = LO_IEEE_NA_FLOAT;\n\n            lo_float_na = tf.value;\n          }\n          break;\n\n        default:\n          // If the format is unknown, then you will probably not have a\n          // useful system, so we will abort here.  Anyone wishing to\n          // experiment with building Octave on a system without IEEE\n          // floating point should be capable of removing this check and\n          // the configure test.\n          //\n          // If the error handler returns, then we'll abort.\n\n          (*current_liboctave_error_handler)\n            (\"lo_ieee_init: floating point format is not IEEE!  Maybe DLAMCH is miscompiled, or you are using some strange system without IEEE floating point math?\");\n\n          abort ();\n        }\n\n      initialized = true;\n    }\n}\n"
  },
  {
    "path": "liboctave/util/lo-ieee.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_ieee_h)\n#define octave_lo_ieee_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\n#  include <cmath>\n\nextern \"C\" {\n#else\n#  include <math.h>\n#endif\n\n/*  Octave's idea of infinity.  */\n#define octave_Inf (lo_ieee_inf_value ())\n\n/* Octave's idea of a missing value.  */\n#define octave_NA (lo_ieee_na_value ())\n\n/* Octave's idea of not a number.  */\n#define octave_NaN (lo_ieee_nan_value ())\n\n/*  Octave's idea of infinity.  */\n#define octave_Float_Inf (lo_ieee_float_inf_value ())\n\n/* Octave's idea of a missing value.  */\n#define octave_Float_NA (lo_ieee_float_na_value ())\n\n/* Octave's idea of not a number.  */\n#define octave_Float_NaN (lo_ieee_float_nan_value ())\n\n/* FIXME: This code assumes that a double has twice the\n          number of bits as an int */\n\ntypedef union\n  {\n  double value;\n  unsigned int word[2];\n} lo_ieee_double;\n\ntypedef union\n  {\n  float value;\n  unsigned int word;\n} lo_ieee_float;\n\nextern OCTAVE_API void octave_ieee_init (void);\n\nextern OCTAVE_API int __lo_ieee_is_NA (double);\n\nextern OCTAVE_API double lo_ieee_inf_value (void);\nextern OCTAVE_API double lo_ieee_na_value (void);\nextern OCTAVE_API double lo_ieee_nan_value (void);\n\nextern OCTAVE_API int __lo_ieee_float_is_NA (float);\n\nextern OCTAVE_API float lo_ieee_float_inf_value (void);\nextern OCTAVE_API float lo_ieee_float_na_value (void);\nextern OCTAVE_API float lo_ieee_float_nan_value (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#define lo_ieee_isnan(x)                                \\\n  (sizeof (x) == sizeof (float)                         \\\n   ? __lo_ieee_float_isnan (x) : __lo_ieee_isnan (x))\n\n#define lo_ieee_isfinite(x)                                   \\\n  (sizeof (x) == sizeof (float)                               \\\n   ? __lo_ieee_float_isfinite (x) : __lo_ieee_isfinite (x))\n\n#define lo_ieee_isinf(x)                                \\\n  (sizeof (x) == sizeof (float)                         \\\n   ? __lo_ieee_float_isinf (x) : __lo_ieee_isinf (x))\n\n#define lo_ieee_is_NA(x)                                \\\n  (sizeof (x) == sizeof (float)                         \\\n   ? __lo_ieee_float_is_NA (x) : __lo_ieee_is_NA (x))\n\n#define lo_ieee_signbit(x)                                      \\\n  (sizeof (x) == sizeof (float)                                 \\\n   ? __lo_ieee_float_signbit (x) : __lo_ieee_signbit (x))\n\n#if defined (__cplusplus)\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ntemplate <typename T>\nstruct numeric_limits\n{\npublic:\n  static T NA () { return static_cast<T> (0); }\n  static T NaN () { return static_cast<T> (0); }\n  static T Inf () { return static_cast<T> (0); }\n};\n\ntemplate <>\nstruct numeric_limits<double>\n{\npublic:\n  static double NA () { return octave_NA; }\n  static double NaN () { return octave_NaN; }\n  static double Inf () { return octave_Inf; }\n};\n\ntemplate <>\nstruct numeric_limits<float>\n{\npublic:\n  static float NA () { return octave_Float_NA; }\n  static float NaN () { return octave_Float_NaN; }\n  static float Inf () { return octave_Float_Inf; }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/util/lo-regexp.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_regexp_h)\n#define octave_lo_regexp_h 1\n\n#warning 'header file \"lo-regexp.h\" is deprecated, use \"oct-regexp.h\" instead'\n\n#include \"oct-regexp.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/util/lo-traits.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_traits_h)\n#define octave_lo_traits_h 1\n\n#warning 'header file \"lo-traits.h\" is deprecated, use \"oct-traits.h\" instead'\n\n#include \"oct-traits.h\"\n\n#endif\n"
  },
  {
    "path": "liboctave/util/lo-utils.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n#include <cstring>\n\n#include <complex>\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <string>\n\n#include \"quit.h\"\n\n#include \"intprops-wrappers.h\"\n#include \"lo-ieee.h\"\n#include \"lo-utils.h\"\n#include \"mappers.h\"\n#include \"oct-error.h\"\n#include \"oct-inttypes.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nbool is_int_or_inf_or_nan (double x)\n{\n  return math::isnan (x) || math::is_integer (x);\n}\n\nbool\ntoo_large_for_float (double x)\n{\n  return (math::isfinite (x)\n          && fabs (x) > std::numeric_limits<float>::max ());\n}\n\nbool\ntoo_large_for_float (const Complex& x)\n{\n  return (too_large_for_float (x.real ())\n          || too_large_for_float (x.imag ()));\n}\n\nbool\nis_int_or_inf_or_nan (float x)\n{\n  return math::isnan (x) || math::is_integer (x);\n}\n\n// Save a string.\n\nchar *\nstrsave (const char *s)\n{\n  if (! s)\n    return nullptr;\n\n  int len = strlen (s);\n  char *tmp = new char [len+1];\n  tmp = strcpy (tmp, s);\n  return tmp;\n}\n\nstd::string\nfgets (FILE *f)\n{\n  bool eof;\n  return fgets (f, eof);\n}\n\nstd::string\nfgets (FILE *f, bool& eof)\n{\n  eof = false;\n\n  std::string retval;\n\n  int grow_size = 1024;\n  int max_size = grow_size;\n\n  char *buf = static_cast<char *> (std::malloc (max_size));\n  if (! buf)\n    (*current_liboctave_error_handler) (\"octave_fgets: unable to malloc %d bytes\", max_size);\n\n  char *bufptr = buf;\n  int len = 0;\n\n  do\n    {\n      if (std::fgets (bufptr, grow_size, f))\n        {\n          len = strlen (bufptr);\n\n          if (len == grow_size - 1)\n            {\n              int tmp = bufptr - buf + grow_size - 1;\n              grow_size *= 2;\n              max_size += grow_size;\n              auto tmpbuf = static_cast<char *> (std::realloc (buf, max_size));\n              if (! tmpbuf)\n                {\n                  free (buf);\n                  (*current_liboctave_error_handler) (\"octave_fgets: unable to realloc %d bytes\", max_size);\n                }\n              buf = tmpbuf;\n              bufptr = buf + tmp;\n\n              if (*(bufptr-1) == '\\n')\n                {\n                  *bufptr = '\\0';\n                  retval = buf;\n                }\n            }\n          else if (bufptr[len-1] != '\\n')\n            {\n              bufptr[len++] = '\\n';\n              bufptr[len] = '\\0';\n              retval = buf;\n            }\n          else\n            retval = buf;\n        }\n      else\n        {\n          if (len == 0)\n            {\n              eof = true;\n\n              free (buf);\n\n              buf = nullptr;\n            }\n\n          break;\n        }\n    }\n  while (retval.empty ());\n\n  free (buf);\n\n  octave_quit ();\n\n  return retval;\n}\n\nstd::string\nfgetl (FILE *f)\n{\n  bool eof;\n  return fgetl (f, eof);\n}\n\nstd::string\nfgetl (FILE *f, bool& eof)\n{\n  std::string retval = fgets (f, eof);\n\n  if (! retval.empty () && retval.back () == '\\n')\n    retval.pop_back ();\n\n  return retval;\n}\n\ntemplate <typename T>\nT\nread_value (std::istream& is)\n{\n  T retval;\n  is >> retval;\n  return retval;\n}\n\ntemplate OCTAVE_API bool read_value<bool> (std::istream& is);\ntemplate OCTAVE_API octave_int8 read_value<octave_int8> (std::istream& is);\ntemplate OCTAVE_API octave_int16 read_value<octave_int16> (std::istream& is);\ntemplate OCTAVE_API octave_int32 read_value<octave_int32> (std::istream& is);\ntemplate OCTAVE_API octave_int64 read_value<octave_int64> (std::istream& is);\ntemplate OCTAVE_API octave_uint8 read_value<octave_uint8> (std::istream& is);\ntemplate OCTAVE_API octave_uint16 read_value<octave_uint16> (std::istream& is);\ntemplate OCTAVE_API octave_uint32 read_value<octave_uint32> (std::istream& is);\ntemplate OCTAVE_API octave_uint64 read_value<octave_uint64> (std::istream& is);\n\n// Note that the caller is responsible for repositioning the stream on\n// failure.\n\ntemplate <typename T>\nT\nread_inf_nan_na (std::istream& is, char c0)\n{\n  T val = 0.0;\n\n  switch (c0)\n    {\n    case 'i': case 'I':\n      {\n        char c1 = is.get ();\n        if (c1 == 'n' || c1 == 'N')\n          {\n            char c2 = is.get ();\n            if (c2 == 'f' || c2 == 'F')\n              {\n                val = std::numeric_limits<T>::infinity ();\n                is.peek ();  // Potentially set EOF bit\n              }\n            else\n              is.setstate (std::ios::failbit);\n          }\n        else\n          is.setstate (std::ios::failbit);\n      }\n      break;\n\n    case 'n': case 'N':\n      {\n        char c1 = is.get ();\n        if (c1 == 'a' || c1 == 'A')\n          {\n            char c2 = is.get ();\n            if (c2 == 'n' || c2 == 'N')\n              val = std::numeric_limits<T>::quiet_NaN ();\n            else\n              {\n                val = numeric_limits<T>::NA ();\n                is.putback (c2);\n                is.clear (is.rdstate () & ~std::ios::failbit);\n              }\n            is.peek ();  // Potentially set EOF bit\n          }\n        else\n          is.setstate (std::ios::failbit);\n      }\n      break;\n\n    default:\n      (*current_liboctave_error_handler)\n        (\"read_inf_nan_na: invalid character '%c'\", c0);\n    }\n\n  return val;\n}\n\n// Read a double value.  Discard any sign on NaN and NA.\n\ntemplate <typename T>\ndouble\nread_fp_value (std::istream& is)\n{\n  T val = 0.0;\n\n  // FIXME: resetting stream position is likely to fail unless we are\n  //        reading from a file.\n  std::streampos pos = is.tellg ();\n\n  is >> std::ws;  // skip through whitespace and advance stream pointer\n\n  bool neg = false;\n  char c1 = is.get ();\n  switch (c1)\n    {\n    case '-':\n      neg = true;\n      OCTAVE_FALLTHROUGH;\n\n    case '+':\n      {\n        char c2 = 0;\n        c2 = is.get ();\n        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')\n          val = read_inf_nan_na<T> (is, c2);\n        else if (isspace (c2))\n          is.setstate (std::ios::failbit);\n        else\n          {\n            is.putback (c2);\n            is >> val;\n          }\n\n        if (neg && ! math::isnan (val) && ! is.fail ())\n          val = -val;\n      }\n      break;\n\n    case 'i': case 'I':\n    case 'n': case 'N':\n      val = read_inf_nan_na<T> (is, c1);\n      break;\n\n    default:\n      is.putback (c1);\n      is >> val;\n      break;\n    }\n\n  std::ios::iostate status = is.rdstate ();\n  if (status & std::ios::failbit)\n    {\n      // Convert MAX_VAL returned by C++ streams for very large numbers to Inf\n      if (val == std::numeric_limits<T>::max ())\n        {\n          if (neg)\n            val = -std::numeric_limits<T>::infinity ();\n          else\n            val = std::numeric_limits<T>::infinity ();\n          is.clear (status & ~std::ios::failbit);\n        }\n      else\n        {\n          // True error.\n          // Reset stream to original position, clear eof bit, pass status on.\n          is.clear ();\n          is.seekg (pos);\n          is.setstate (status & ~std::ios_base::eofbit);\n        }\n    }\n\n  return val;\n}\n\ntemplate <typename T>\nstd::complex<T>\nread_cx_fp_value (std::istream& is)\n{\n  T re = 0.0;\n  T im = 0.0;\n\n  std::complex<T> cx = 0.0;\n\n  char ch = ' ';\n\n  while (isspace (ch))\n    ch = is.get ();\n\n  if (ch == '(')\n    {\n      re = read_value<T> (is);\n      ch = is.get ();\n\n      if (ch == ',')\n        {\n          im = read_value<T> (is);\n          ch = is.get ();\n\n          if (ch == ')')\n            cx = std::complex<T> (re, im);\n          else\n            is.setstate (std::ios::failbit);\n        }\n      else if (ch == ')')\n        cx = re;\n      else\n        is.setstate (std::ios::failbit);\n    }\n  else\n    {\n      is.putback (ch);\n      cx = read_value<T> (is);\n    }\n\n  return cx;\n}\n\n// FIXME: Could we use traits and enable_if to avoid duplication in the\n// following specializations?\n\ntemplate <> OCTAVE_API double read_value (std::istream& is)\n{\n  return read_fp_value<double> (is);\n}\n\ntemplate <> OCTAVE_API Complex read_value (std::istream& is)\n{\n  return read_cx_fp_value<double> (is);\n}\n\ntemplate <> OCTAVE_API float read_value (std::istream& is)\n{\n  return read_fp_value<float> (is);\n}\n\ntemplate <> OCTAVE_API FloatComplex read_value (std::istream& is)\n{\n  return read_cx_fp_value<float> (is);\n}\n\ntemplate <typename T>\nvoid\nwrite_value (std::ostream& os, const T& value)\n{\n  os << value;\n}\n\ntemplate OCTAVE_API void\nwrite_value<bool> (std::ostream& os, const bool& value);\ntemplate OCTAVE_API void\nwrite_value<octave_int8> (std::ostream& os, const octave_int8& value);\ntemplate OCTAVE_API void\nwrite_value<octave_int16> (std::ostream& os, const octave_int16& value);\ntemplate OCTAVE_API void\nwrite_value<octave_int32> (std::ostream& os, const octave_int32& value);\ntemplate OCTAVE_API void\nwrite_value<octave_int64> (std::ostream& os, const octave_int64& value);\ntemplate OCTAVE_API void\nwrite_value<octave_uint8> (std::ostream& os, const octave_uint8& value);\ntemplate OCTAVE_API void\nwrite_value<octave_uint16> (std::ostream& os, const octave_uint16& value);\ntemplate OCTAVE_API void\nwrite_value<octave_uint32> (std::ostream& os, const octave_uint32& value);\ntemplate OCTAVE_API void\nwrite_value<octave_uint64> (std::ostream& os, const octave_uint64& value);\n\n// Note: precision is supposed to be managed outside of this function by\n// setting stream parameters.\n\ntemplate <>\nOCTAVE_API void\nwrite_value (std::ostream& os, const double& value)\n{\n  if (lo_ieee_is_NA (value))\n    os << \"NA\";\n  else if (math::isnan (value))\n    os << \"NaN\";\n  else if (math::isinf (value))\n    os << (value < 0 ? \"-Inf\" : \"Inf\");\n  else\n    os << value;\n}\n\ntemplate <>\nOCTAVE_API void\nwrite_value (std::ostream& os, const Complex& value)\n{\n  os << '(';\n  write_value<double> (os, real (value));\n  os << ',';\n  write_value<double> (os, imag (value));\n  os << ')';\n}\n\n// Note: precision is supposed to be managed outside of this function by\n// setting stream parameters.\n\ntemplate <>\nOCTAVE_API void\nwrite_value (std::ostream& os, const float& value)\n{\n  if (lo_ieee_is_NA (value))\n    os << \"NA\";\n  else if (math::isnan (value))\n    os << \"NaN\";\n  else if (math::isinf (value))\n    os << (value < 0 ? \"-Inf\" : \"Inf\");\n  else\n    os << value;\n}\n\ntemplate <>\nOCTAVE_API void\nwrite_value (std::ostream& os, const FloatComplex& value)\n{\n  os << '(';\n  write_value<float> (os, real (value));\n  os << ',';\n  write_value<float> (os, imag (value));\n  os << ')';\n}\n\nOCTAVE_BEGIN_NAMESPACE(math)\n\nbool\nint_multiply_overflow (int a, int b, int *r)\n{\n  return octave_i_multiply_overflow_wrapper (a, b, r);\n}\n\nbool\nint_multiply_overflow (long int a, long int b, long int *r)\n{\n  return octave_li_multiply_overflow_wrapper (a, b, r);\n}\n\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\nbool\nint_multiply_overflow (long long int a, long long int b, long long int *r)\n{\n  return octave_lli_multiply_overflow_wrapper (a, b, r);\n}\n#endif\n\nbool\nint_multiply_overflow (unsigned int a, unsigned int b, unsigned int *r)\n{\n  return octave_ui_multiply_overflow_wrapper (a, b, r);\n}\n\nbool\nint_multiply_overflow (unsigned long int a, unsigned long int b,\n                       unsigned long int *r)\n{\n  return octave_uli_multiply_overflow_wrapper (a, b, r);\n}\n\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\nbool\nint_multiply_overflow (unsigned long long int a, unsigned long long int b,\n                       unsigned long long int *r)\n{\n  return octave_ulli_multiply_overflow_wrapper (a, b, r);\n}\n#endif\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/lo-utils.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_lo_utils_h)\n#define octave_lo_utils_h 1\n\n#include \"octave-config.h\"\n\n#include <cstdio>\n\n#include <iosfwd>\n#include <string>\n\n#include \"oct-cmplx.h\"\n#include \"quit.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Generic any/all test functionality with arbitrary predicate.\n\ntemplate <typename F, typename T, bool zero>\nbool\nany_all_test (F fcn, const T *m, octave_idx_type len)\n{\n  octave_idx_type i;\n\n  for (i = 0; i < len - 3; i += 4)\n    {\n      octave_quit ();\n\n      if (fcn (m[i]) != zero\n          || fcn (m[i+1]) != zero\n          || fcn (m[i+2]) != zero\n          || fcn (m[i+3]) != zero)\n        return ! zero;\n    }\n\n  octave_quit ();\n\n  for (; i < len; i++)\n    if (fcn (m[i]) != zero)\n      return ! zero;\n\n  return zero;\n}\n\nextern OCTAVE_API bool xis_int_or_inf_or_nan (double x);\n\ntemplate <typename T>\nbool is_one_or_zero (const T& x)\n{\n  return x == T (0) || x == T (1);\n}\n\ntemplate <typename T>\nbool is_zero (const T& x)\n{\n  return x == T (0);\n}\n\nextern OCTAVE_API bool too_large_for_float (double x);\n\nextern OCTAVE_API bool too_large_for_float (const Complex&  x);\n\nextern OCTAVE_API bool is_int_or_inf_or_nan (float x);\nextern OCTAVE_API bool too_large_for_float (float x);\n\nextern OCTAVE_API char * strsave (const char *);\n\nextern OCTAVE_API std::string fgets (std::FILE *);\nextern OCTAVE_API std::string fgetl (std::FILE *);\n\nextern OCTAVE_API std::string fgets (std::FILE *, bool& eof);\nextern OCTAVE_API std::string fgetl (std::FILE *, bool& eof);\n\ntemplate <typename T> OCTAVE_API T read_value (std::istream& is);\n\ntemplate <> OCTAVE_API double read_value (std::istream& is);\ntemplate <> OCTAVE_API Complex read_value (std::istream& is);\ntemplate <> OCTAVE_API float read_value (std::istream& is);\ntemplate <> OCTAVE_API FloatComplex read_value (std::istream& is);\n\ntemplate <typename T> OCTAVE_API void write_value (std::ostream& os, const T& value);\n\ntemplate <> OCTAVE_API void write_value (std::ostream& os, const double& value);\ntemplate <> OCTAVE_API void write_value (std::ostream& os, const Complex& value);\ntemplate <> OCTAVE_API void write_value (std::ostream& os, const float& value);\ntemplate <> OCTAVE_API void write_value (std::ostream& os, const FloatComplex& value);\n\nOCTAVE_BEGIN_NAMESPACE(math)\n\nextern OCTAVE_API bool int_multiply_overflow (int a, int b, int *r);\n\nextern OCTAVE_API bool\nint_multiply_overflow (long int a, long int b, long int *r);\n\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\nextern OCTAVE_API bool\nint_multiply_overflow (long long int a, long long int b, long long int *r);\n#endif\n\nextern OCTAVE_API bool\nint_multiply_overflow (unsigned int a, unsigned int b, unsigned int *r);\n\nextern OCTAVE_API bool\nint_multiply_overflow (unsigned long int a, unsigned long int b,\n                       unsigned long int *r);\n\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\nextern OCTAVE_API bool\nint_multiply_overflow (unsigned long long int a, unsigned long long int b,\n                       unsigned long long int *r);\n#endif\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/module.mk",
    "content": "UTIL_INC = \\\n  %reldir%/action-container.h \\\n  %reldir%/base-list.h \\\n  %reldir%/byte-swap.h \\\n  %reldir%/caseless-str.h \\\n  %reldir%/data-conv.h \\\n  %reldir%/file-info.h \\\n  %reldir%/glob-match.h \\\n  %reldir%/lo-array-errwarn.h \\\n  %reldir%/lo-hash.h \\\n  %reldir%/lo-ieee.h \\\n  %reldir%/lo-regexp.h \\\n  %reldir%/lo-traits.h \\\n  %reldir%/lo-utils.h \\\n  %reldir%/f77-fcn.h \\\n  %reldir%/lo-error.h \\\n  %reldir%/octave-preserve-stream-state.h \\\n  %reldir%/quit.h \\\n  %reldir%/oct-base64.h \\\n  %reldir%/oct-binmap.h \\\n  %reldir%/oct-cmplx.h \\\n  %reldir%/oct-error.h \\\n  %reldir%/oct-glob.h \\\n  %reldir%/oct-hash.h \\\n  %reldir%/oct-inttypes-fwd.h \\\n  %reldir%/oct-inttypes.h \\\n  %reldir%/oct-locbuf.h \\\n  %reldir%/oct-mutex.h \\\n  %reldir%/oct-regexp.h \\\n  %reldir%/oct-refcount.h \\\n  %reldir%/oct-shlib.h \\\n  %reldir%/oct-sort.h \\\n  %reldir%/oct-string.h \\\n  %reldir%/oct-traits.h \\\n  %reldir%/pathsearch.h \\\n  %reldir%/singleton-cleanup.h \\\n  %reldir%/sparse-util.h \\\n  %reldir%/str-vec.h \\\n  %reldir%/unwind-prot.h \\\n  %reldir%/url-transfer.h\n\nNOINSTALL_UTIL_INC = \\\n  %reldir%/kpse.h \\\n  %reldir%/oct-sparse.h\n\nUTIL_F77_SRC = \\\n  %reldir%/d1mach.f \\\n  %reldir%/i1mach.f \\\n  %reldir%/r1mach.f\n\nUTIL_C_SRC = \\\n  %reldir%/blaswrap.c\n\nUTIL_SRC = \\\n  %reldir%/action-container.cc \\\n  %reldir%/data-conv.cc \\\n  %reldir%/f77-dummy-main.cc \\\n  %reldir%/f77-fcn.cc \\\n  %reldir%/file-info.cc \\\n  %reldir%/glob-match.cc \\\n  %reldir%/kpse.cc \\\n  %reldir%/lo-array-errwarn.cc \\\n  %reldir%/lo-ieee.cc \\\n  %reldir%/lo-utils.cc \\\n  %reldir%/quit.cc \\\n  %reldir%/oct-base64.cc \\\n  %reldir%/oct-cmplx.cc \\\n  %reldir%/oct-error.cc \\\n  %reldir%/oct-glob.cc \\\n  %reldir%/oct-hash.cc \\\n  %reldir%/oct-inttypes.cc \\\n  %reldir%/oct-mutex.cc \\\n  %reldir%/oct-regexp.cc \\\n  %reldir%/oct-shlib.cc \\\n  %reldir%/oct-sparse.cc \\\n  %reldir%/oct-string.cc \\\n  %reldir%/pathsearch.cc \\\n  %reldir%/singleton-cleanup.cc \\\n  %reldir%/sparse-util.cc \\\n  %reldir%/str-vec.cc \\\n  %reldir%/unwind-prot.cc \\\n  %reldir%/url-transfer.cc \\\n  $(UTIL_F77_SRC) \\\n  $(UTIL_C_SRC) \\\n  $(NOINSTALL_UTIL_INC)\n\nliboctave_EXTRA_DIST += \\\n  %reldir%/d1mach-tst.for\n\nLIBOCTAVE_TEMPLATE_SRC += \\\n  %reldir%/oct-sort.cc\n\nnoinst_LTLIBRARIES += %reldir%/libutil.la\n\n%canon_reldir%_libutil_la_SOURCES = $(UTIL_SRC)\n\n%canon_reldir%_libutil_la_CPPFLAGS = \\\n  $(liboctave_liboctave_la_CPPFLAGS) \\\n  $(CURL_CPPFLAGS) \\\n  $(PCRE_CPPFLAGS) \\\n  $(SPARSE_XCPPFLAGS)\n\n%canon_reldir%_libutil_la_FFLAGS = $(F77_INTEGER_8_FLAG)\n\nliboctave_liboctave_la_LIBADD += %reldir%/libutil.la\n"
  },
  {
    "path": "liboctave/util/oct-base64.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n\n#include \"Array-oct.h\"\n#include \"base64-wrappers.h\"\n#include \"oct-base64.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nbool\nbase64_encode (const char *inc, const std::size_t inlen, char **out)\n{\n  bool ret = false;\n\n  std::ptrdiff_t outlen = octave_base64_encode_alloc_wrapper (inc, inlen, out);\n\n  if (! out)\n    {\n      if (outlen == 0 && inlen != 0)\n        (*current_liboctave_error_handler)\n          (\"base64_encode: input array too large\");\n      else\n        (*current_liboctave_error_handler)\n          (\"base64_encode: memory allocation error\");\n    }\n  else\n    ret = true;\n\n  return ret;\n}\n\nArray<double>\nbase64_decode (const std::string& str)\n{\n  Array<double> retval;\n\n  double *out;\n  std::ptrdiff_t outlen;\n\n  bool ok\n    = octave_base64_decode_alloc_wrapper (str.data (), str.length (),\n                                          reinterpret_cast<char **> (&out),\n                                          &outlen);\n\n  if (! ok)\n    (*current_liboctave_error_handler)\n      (\"base64_decode: input was not valid base64\");\n\n  if (! out)\n    (*current_liboctave_error_handler)\n      (\"base64_decode: memory allocation error\");\n\n  if ((outlen % (sizeof (double) / sizeof (char))) != 0)\n    {\n      ::free (out);\n      (*current_liboctave_error_handler)\n        (\"base64_decode: incorrect input size\");\n    }\n  else\n    {\n      octave_idx_type len = (outlen * sizeof (char)) / sizeof (double);\n      retval.resize (dim_vector (1, len));\n      std::copy (out, out + len, retval.rwdata ());\n      ::free (out);\n    }\n\n  return retval;\n}\n\nintNDArray<octave_uint8>\nbase64_decode_bytes (const std::string& str)\n{\n  intNDArray<octave_uint8> retval;\n\n  char *out;\n  std::ptrdiff_t outlen;\n\n  bool ok\n    = octave_base64_decode_alloc_wrapper (str.data (), str.length (),\n                                          &out, &outlen);\n\n  if (! ok)\n    (*current_liboctave_error_handler)\n      (\"base64_decode: input was not valid base64\");\n\n  if (! out)\n    (*current_liboctave_error_handler)\n      (\"base64_decode: memory allocation error\");\n\n  retval.resize (dim_vector (1, outlen));\n  std::copy (out, out + outlen, retval.rwdata ());\n  ::free (out);\n\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/oct-base64.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_base64_h)\n#define octave_oct_base64_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\n#include \"Array-fwd.h\"\n#include \"intNDArray.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nextern OCTAVE_API bool\nbase64_encode (const char *inc, const std::size_t inlen, char **out);\n\nextern OCTAVE_API Array<double>\nbase64_decode (const std::string& str);\n\nextern OCTAVE_API intNDArray<octave_uint8>\nbase64_decode_bytes (const std::string& str);\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-binmap.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_binmap_h)\n#define octave_oct_binmap_h 1\n\n#include \"octave-config.h\"\n\n#include \"Array-oct.h\"\n#include \"Sparse.h\"\n#include \"Array-util.h\"\n\n#include \"bsxfun.h\"\n\n// This source file implements a general binary mapping function for arrays.\n// The syntax is binmap<type> (a, b, f,[name]).\n// type denotes the expected return type of the operation.\n// a, b, should be one of the 6 combinations:\n//\n// Array-Array\n// Array-scalar\n// scalar-Array\n// Sparse-Sparse\n// Sparse-scalar\n// scalar-Sparse\n//\n// If both operands are nonscalar, name must be supplied.  It is used\n// as the base for error message when operands are nonconforming.\n//\n// The operation needs not be homogeneous, i.e., a, b and the result\n// may be of distinct types.  f can have any of the four signatures:\n//\n// U f (T, R)\n// U f (const T&, R)\n// U f (T, const R&)\n// U f (const T&, const R&)\n//\n// Additionally, f can be an arbitrary functor object.\n//\n// octave_quit() is called at appropriate places, hence the operation\n// is breakable.\n\n// The following template wrappers are provided for automatic bsxfun\n// calls (see the function signature for do_bsxfun_op).\n\ntemplate <typename R, typename X, typename Y, typename F>\nclass bsxfun_wrapper\n{\nprivate:\n\n  static F s_fcn;\n\npublic:\n\n  static void\n  set_f (const F& f_in)\n  {\n    s_fcn = f_in;\n  }\n\n  static void\n  op_mm (std::size_t n, R *r, const X *x, const Y *y)\n  {\n    for (std::size_t i = 0; i < n; i++)\n      r[i] = s_fcn (x[i], y[i]);\n  }\n\n  static void\n  op_sm (std::size_t n, R *r, X x, const Y *y)\n  {\n    for (std::size_t i = 0; i < n; i++)\n      r[i] = s_fcn (x, y[i]);\n  }\n\n  static void\n  op_ms (std::size_t n, R *r, const X *x, Y y)\n  {\n    for (std::size_t i = 0; i < n; i++)\n      r[i] = s_fcn (x[i], y);\n  }\n};\n\n// Static init\ntemplate <typename R, typename X, typename Y, typename F>\nF bsxfun_wrapper<R, X, Y, F>::s_fcn;\n\n// scalar-Array\ntemplate <typename U, typename T, typename R, typename F>\nArray<U>\nbinmap (const T& x, const Array<R>& ya, F fcn)\n{\n  octave_idx_type len = ya.numel ();\n\n  const R *y = ya.data ();\n\n  Array<U> result (ya.dims ());\n  U *p = result.rwdata ();\n\n  octave_idx_type i;\n  for (i = 0; i < len - 3; i += 4)\n    {\n      octave_quit ();\n\n      p[i] = fcn (x, y[i]);\n      p[i+1] = fcn (x, y[i+1]);\n      p[i+2] = fcn (x, y[i+2]);\n      p[i+3] = fcn (x, y[i+3]);\n    }\n\n  octave_quit ();\n\n  for (; i < len; i++)\n    p[i] = fcn (x, y[i]);\n\n  return result;\n}\n\n// Array-scalar\ntemplate <typename U, typename T, typename R, typename F>\nArray<U>\nbinmap (const Array<T>& xa, const R& y, F fcn)\n{\n  octave_idx_type len = xa.numel ();\n\n  const R *x = xa.data ();\n\n  Array<U> result (xa.dims ());\n  U *p = result.rwdata ();\n\n  octave_idx_type i;\n  for (i = 0; i < len - 3; i += 4)\n    {\n      octave_quit ();\n\n      p[i] = fcn (x[i], y);\n      p[i+1] = fcn (x[i+1], y);\n      p[i+2] = fcn (x[i+2], y);\n      p[i+3] = fcn (x[i+3], y);\n    }\n\n  octave_quit ();\n\n  for (; i < len; i++)\n    p[i] = fcn (x[i], y);\n\n  return result;\n}\n\n// Array-Array (treats singletons as scalars)\ntemplate <typename U, typename T, typename R, typename F>\nArray<U>\nbinmap (const Array<T>& xa, const Array<R>& ya, F fcn, const char *name)\n{\n  const dim_vector& xad = xa.dims ();\n  const dim_vector& yad = ya.dims ();\n  if (xa.numel () == 1)\n    return binmap<U, T, R, F> (xa(0), ya, fcn);\n  else if (ya.numel () == 1)\n    return binmap<U, T, R, F> (xa, ya(0), fcn);\n  else if (xad != yad)\n    {\n      if (! is_valid_bsxfun (xad, yad))\n        octave::err_nonconformant (name, xad, yad);\n\n      bsxfun_wrapper<U, T, R, F>::set_f(fcn);\n      return do_bsxfun_op (xa, ya,\n                           bsxfun_wrapper<U, T, R, F>::op_mm,\n                           bsxfun_wrapper<U, T, R, F>::op_sm,\n                           bsxfun_wrapper<U, T, R, F>::op_ms);\n    }\n\n  octave_idx_type len = xa.numel ();\n\n  const T *x = xa.data ();\n  const T *y = ya.data ();\n\n  Array<U> result (xa.dims ());\n  U *p = result.rwdata ();\n\n  octave_idx_type i;\n  for (i = 0; i < len - 3; i += 4)\n    {\n      octave_quit ();\n\n      p[i] = fcn (x[i], y[i]);\n      p[i+1] = fcn (x[i+1], y[i+1]);\n      p[i+2] = fcn (x[i+2], y[i+2]);\n      p[i+3] = fcn (x[i+3], y[i+3]);\n    }\n\n  octave_quit ();\n\n  for (; i < len; i++)\n    p[i] = fcn (x[i], y[i]);\n\n  return result;\n}\n\n// scalar-Sparse\ntemplate <typename U, typename T, typename R, typename F>\nSparse<U>\nbinmap (const T& x, const Sparse<R>& ys, F fcn)\n{\n  R yzero = R ();\n  U fz = fcn (x, yzero);\n\n  if (fz == U ())  // Sparsity preserving fcn\n    {\n      octave_idx_type nz = ys.nnz ();\n      Sparse<U> retval (ys.rows (), ys.cols (), nz);\n      std::copy (ys.ridx (), ys.ridx () + nz, retval.ridx ());\n      std::copy (ys.cidx (), ys.cidx () + ys.cols () + 1, retval.cidx ());\n\n      for (octave_idx_type i = 0; i < nz; i++)\n        {\n          octave_quit ();\n          retval.xdata (i) = fcn (x, ys.data (i));\n        }\n\n      octave_quit ();\n      retval.maybe_compress (true);\n      return retval;\n    }\n  else\n    return Sparse<U> (binmap<U, T, R, F> (x, ys.array_value (), fcn));\n}\n\n// Sparse-scalar\ntemplate <typename U, typename T, typename R, typename F>\nSparse<U>\nbinmap (const Sparse<T>& xs, const R& y, F fcn)\n{\n  T xzero = T ();\n  U fz = fcn (xzero, y);\n\n  if (fz == U ())  // Sparsity preserving fcn\n    {\n      octave_idx_type nz = xs.nnz ();\n      Sparse<U> retval (xs.rows (), xs.cols (), nz);\n      std::copy (xs.ridx (), xs.ridx () + nz, retval.ridx ());\n      std::copy (xs.cidx (), xs.cidx () + xs.cols () + 1, retval.cidx ());\n\n      for (octave_idx_type i = 0; i < nz; i++)\n        {\n          octave_quit ();\n          retval.xdata (i) = fcn (xs.data (i), y);\n        }\n\n      octave_quit ();\n      retval.maybe_compress (true);\n      return retval;\n    }\n  else\n    return Sparse<U> (binmap<U, T, R, F> (xs.array_value (), y, fcn));\n}\n\n// Sparse-Sparse (treats singletons as scalars)\ntemplate <typename U, typename T, typename R, typename F>\nSparse<U>\nbinmap (const Sparse<T>& xs, const Sparse<R>& ys, F fcn, const char *name)\n{\n  if (xs.rows () == 1 && xs.cols () == 1)\n    return binmap<U, T, R, F> (xs(0, 0), ys, fcn);\n  else if (ys.rows () == 1 && ys.cols () == 1)\n    return binmap<U, T, R, F> (xs, ys(0, 0), fcn);\n  else if (xs.dims () != ys.dims ())\n    octave::err_nonconformant (name, xs.dims (), ys.dims ());\n\n  T xzero = T ();\n  R yzero = R ();\n  U fz = fcn (xzero, yzero);\n\n  if (fz == U ())\n    {\n      // Sparsity-preserving function.  Do it efficiently.\n      octave_idx_type nr = xs.rows ();\n      octave_idx_type nc = xs.cols ();\n      Sparse<T> retval (nr, nc, xs.nnz () + ys.nnz ());\n\n      octave_idx_type nz = 0;\n      for (octave_idx_type j = 0; j < nc; j++)\n        {\n          octave_quit ();\n\n          octave_idx_type jx = xs.cidx (j);\n          octave_idx_type jx_max = xs.cidx (j+1);\n          bool jx_lt_max = jx < jx_max;\n\n          octave_idx_type jy = ys.cidx (j);\n          octave_idx_type jy_max = ys.cidx (j+1);\n          bool jy_lt_max = jy < jy_max;\n\n          while (jx_lt_max || jy_lt_max)\n            {\n              if (! jy_lt_max\n                  || (jx_lt_max && (xs.ridx (jx) < ys.ridx (jy))))\n                {\n                  retval.xridx (nz) = xs.ridx (jx);\n                  retval.xdata (nz) = fcn (xs.data (jx), yzero);\n                  jx++;\n                  jx_lt_max = jx < jx_max;\n                }\n              else if (! jx_lt_max\n                       || (jy_lt_max && (ys.ridx (jy) < xs.ridx (jx))))\n                {\n                  retval.xridx (nz) = ys.ridx (jy);\n                  retval.xdata (nz) = fcn (xzero, ys.data (jy));\n                  jy++;\n                  jy_lt_max = jy < jy_max;\n                }\n              else\n                {\n                  retval.xridx (nz) = xs.ridx (jx);\n                  retval.xdata (nz) = fcn (xs.data (jx), ys.data (jy));\n                  jx++;\n                  jx_lt_max = jx < jx_max;\n                  jy++;\n                  jy_lt_max = jy < jy_max;\n                }\n              nz++;\n            }\n          retval.xcidx (j+1) = nz;\n        }\n\n      retval.maybe_compress (true);\n      return retval;\n    }\n  else\n    return Sparse<U> (binmap<U, T, R, F> (xs.array_value (), ys.array_value (),\n                                          fcn, name));\n}\n\n// Overloads for function pointers.\n\n// Signature (T, R)\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, R),\n        const char *name)\n{ return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const T& x, const Array<R>& ya, U (*fcn) (T, R))\n{ return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const Array<T>& xa, const R& y, U (*fcn) (T, R))\n{ return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, R),\n        const char *name)\n{ return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, R))\n{ return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, R))\n{ return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }\n\n// Signature (const T&, const R&)\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, const R&),\n        const char *name)\n{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, const R&))\n{ return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, const R&))\n{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, const R&),\n        const char *name)\n{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, const R&))\n{ return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, const R&))\n{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }\n\n// Signature (const T&, R)\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, R),\n        const char *name)\n{ return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, R))\n{ return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, R))\n{ return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, R),\n        const char *name)\n{ return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, R))\n{ return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, R))\n{ return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }\n\n// Signature (T, const R&)\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, const R&),\n        const char *name)\n{ return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const T& x, const Array<R>& ya, U (*fcn) (T, const R&))\n{ return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Array<U>\nbinmap (const Array<T>& xa, const R& y, U (*fcn) (T, const R&))\n{ return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, const R&),\n        const char *name)\n{ return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, const R&))\n{ return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }\n\ntemplate <typename U, typename T, typename R>\ninline Sparse<U>\nbinmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, const R&))\n{ return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-cmplx.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <complex>\n\n// For complex-complex and complex-real comparisons, Octave uses the following\n// ordering: compare absolute values first; if they match, compare phase\n// angles.  This is partially inconsistent with M*b, which compares complex\n// numbers only by their real parts; OTOH, it uses the same definition for\n// max/min and sort.  The abs/arg comparison is definitely more useful (the\n// other one is emulated rather trivially), so let's be consistent and use that\n// all over.\n\n// The standard C library function arg() returns [-pi,pi], which creates a\n// non-unique representation for numbers along the negative real axis branch\n// cut.  Change this to principal value (-pi,pi] by mapping -pi to pi.\n\n// General templated code for all (double, float) complex operators\n#define DEF_COMPLEXR_COMP(OP, OPS)                                           \\\n   template <typename T>                                                     \\\n   bool operator OP (const std::complex<T>& a, const std::complex<T>& b)     \\\n   {                                                                         \\\n     const T ax = std::abs (a);                                              \\\n     const T bx = std::abs (b);                                              \\\n     if (ax == bx)                                                           \\\n       {                                                                     \\\n         const T ay = std::arg (a);                                          \\\n         const T by = std::arg (b);                                          \\\n         if (ay == static_cast<T> (-M_PI))                                   \\\n           {                                                                 \\\n             if (by != static_cast<T> (-M_PI))                               \\\n               return static_cast<T> (M_PI) OP by;                           \\\n           }                                                                 \\\n         else if (by == static_cast<T> (-M_PI))                              \\\n           {                                                                 \\\n             return ay OP static_cast<T> (M_PI);                             \\\n           }                                                                 \\\n         return ay OP by;                                                    \\\n       }                                                                     \\\n     else                                                                    \\\n       return ax OPS bx;                                                     \\\n   }                                                                         \\\n   template <typename T>                                                     \\\n   bool operator OP (const std::complex<T>& a, T b)                          \\\n   {                                                                         \\\n     const T ax = std::abs (a);                                              \\\n     const T bx = std::abs (b);                                              \\\n     if (ax == bx)                                                           \\\n       {                                                                     \\\n         const T ay = std::arg (a);                                          \\\n         if (ay == static_cast<T> (-M_PI))                                   \\\n           return static_cast<T> (M_PI) OP 0;                                \\\n         return ay OP 0;                                                     \\\n       }                                                                     \\\n     else                                                                    \\\n       return ax OPS bx;                                                     \\\n   }                                                                         \\\n   template <typename T>                                                     \\\n   bool operator OP (T a, const std::complex<T>& b)                          \\\n   {                                                                         \\\n     const T ax = std::abs (a);                                              \\\n     const T bx = std::abs (b);                                              \\\n     if (ax == bx)                                                           \\\n       {                                                                     \\\n         const T by = std::arg (b);                                          \\\n         if (by == static_cast<T> (-M_PI))                                   \\\n           return 0 OP static_cast<T> (M_PI);                                \\\n         return 0 OP by;                                                     \\\n       }                                                                     \\\n     else                                                                    \\\n       return ax OPS bx;                                                     \\\n   }\n\n#if defined (__APPLE__)\n   // Apple specializations\n\n   // FIXME: Apple's math library chooses to return a different value for\n   // std::arg with floats than the constant static_cast<float> (M_PI).\n   // Work around this obtuse behavior by providing the constant A_PI which\n   // is Apple's definition of the constant PI for float variables.\n   // The template code for doubles is the same as that for UNIX platforms.\n   // Use C++ template specialization to add specific functions for float\n   // values that make use of A_PI.\n\n   // Apple version of PI in single precision\n#  define A_PI 3.1415925025939941f\n\n#  define INST_SPECIAL_COMPLEXR_COMP(OP, OPS)                                \\\n     template <> OCTAVE_API                                                  \\\n     bool operator OP<float> (const std::complex<float>& a,                  \\\n                              const std::complex<float>& b)                  \\\n     {                                                                       \\\n       const float ax = std::abs (a);                                        \\\n       const float bx = std::abs (b);                                        \\\n       if (ax == bx)                                                         \\\n         {                                                                   \\\n           const float ay = std::arg (a);                                    \\\n           const float by = std::arg (b);                                    \\\n           if (ay == -A_PI)                                                  \\\n             {                                                               \\\n               if (by != -A_PI)                                              \\\n                 return static_cast<float> (M_PI) OP by;                     \\\n             }                                                               \\\n           else if (by == -A_PI)                                             \\\n             {                                                               \\\n               return ay OP static_cast<float> (M_PI);                       \\\n             }                                                               \\\n           return ay OP by;                                                  \\\n         }                                                                   \\\n       else                                                                  \\\n         return ax OPS bx;                                                   \\\n     }                                                                       \\\n     template <> OCTAVE_API                                                  \\\n     bool operator OP<float> (const std::complex<float>& a, float b)         \\\n     {                                                                       \\\n       const float ax = std::abs (a);                                        \\\n       const float bx = std::abs (b);                                        \\\n       if (ax == bx)                                                         \\\n         {                                                                   \\\n           const float ay = std::arg (a);                                    \\\n           if (ay == -A_PI)                                                  \\\n             return static_cast<float> (M_PI) OP 0;                          \\\n           return ay OP 0;                                                   \\\n         }                                                                   \\\n       else                                                                  \\\n         return ax OPS bx;                                                   \\\n     }                                                                       \\\n     template <> OCTAVE_API                                                  \\\n     bool operator OP<float> (float a, const std::complex<float>& b)         \\\n     {                                                                       \\\n       const float ax = std::abs (a);                                        \\\n       const float bx = std::abs (b);                                        \\\n       if (ax == bx)                                                         \\\n         {                                                                   \\\n           const float by = std::arg (b);                                    \\\n           if (by == -A_PI)                                                  \\\n             return 0 OP static_cast<float> (M_PI);                          \\\n           return 0 OP by;                                                   \\\n         }                                                                   \\\n       else                                                                  \\\n         return ax OPS bx;                                                   \\\n     }\n\n#endif\n\nDEF_COMPLEXR_COMP (>, >)\nDEF_COMPLEXR_COMP (<, <)\nDEF_COMPLEXR_COMP (>=, >)\nDEF_COMPLEXR_COMP (<=, <)\n\n\n// Instantiate templates\n\n# define INST_COMPLEXR_COMP(OP, T)                                           \\\n    template OCTAVE_API bool operator OP (const std::complex<T>& a,          \\\n                                          const std::complex<T>& b);         \\\n    template OCTAVE_API bool operator OP (const std::complex<T>& a, T b);    \\\n    template OCTAVE_API bool operator OP (T a, const std::complex<T>& b);\n\nINST_COMPLEXR_COMP (>, double)\nINST_COMPLEXR_COMP (<, double)\nINST_COMPLEXR_COMP (>=, double)\nINST_COMPLEXR_COMP (<=, double)\n\n#if defined (__APPLE__)\nINST_SPECIAL_COMPLEXR_COMP (>, >)\nINST_SPECIAL_COMPLEXR_COMP (<, <)\nINST_SPECIAL_COMPLEXR_COMP (>=, >)\nINST_SPECIAL_COMPLEXR_COMP (<=, <)\n#else\nINST_COMPLEXR_COMP (>, float)\nINST_COMPLEXR_COMP (<, float)\nINST_COMPLEXR_COMP (>=, float)\nINST_COMPLEXR_COMP (<=, float)\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-cmplx.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1995-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_cmplx_h)\n#define octave_oct_cmplx_h 1\n\n#include \"octave-config.h\"\n\n#include <complex>\n\ntypedef std::complex<double> Complex;\ntypedef std::complex<float> FloatComplex;\n\n// template declaration\n# define DECL_COMPLEXR_COMP(OP)                                               \\\n    template <typename T> bool operator OP (const std::complex<T>& a,         \\\n                                            const std::complex<T>& b);        \\\n    template <typename T> bool operator OP (const std::complex<T>& a, T b);   \\\n    template <typename T> bool operator OP (T a, const std::complex<T>& b);\n\nDECL_COMPLEXR_COMP(>)\nDECL_COMPLEXR_COMP(<)\nDECL_COMPLEXR_COMP(>=)\nDECL_COMPLEXR_COMP(<=)\n\n// extern template instantiations\n# define EXT_INST_COMPLEXR_COMP(OP, T)                                       \\\n    extern template OCTAVE_API                                               \\\n    bool operator OP (const std::complex<T>& a, const std::complex<T>& b);   \\\n    extern template OCTAVE_API                                               \\\n    bool operator OP (const std::complex<T>& a, T b);                        \\\n    extern template OCTAVE_API                                               \\\n    bool operator OP (T a, const std::complex<T>& b);\n\nEXT_INST_COMPLEXR_COMP(>, double)\nEXT_INST_COMPLEXR_COMP(>, float)\nEXT_INST_COMPLEXR_COMP(<, double)\nEXT_INST_COMPLEXR_COMP(<, float)\nEXT_INST_COMPLEXR_COMP(>=, double)\nEXT_INST_COMPLEXR_COMP(>=, float)\nEXT_INST_COMPLEXR_COMP(<=, double)\nEXT_INST_COMPLEXR_COMP(<=, float)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-error.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdarg>\n#include <cstdio>\n#include <cstdlib>\n\n#include \"oct-error.h\"\n\n/* Having this file in this directory is a kluge to avoid unresolved\n   symbol errors when creating shared versions of liboctave. */\n\n/* Pointer to the current error handling function. */\nOCTAVE_NORETURN liboctave_error_handler\n  current_liboctave_error_handler = liboctave_fatal;\n\n/* Pointer to the current error_with_id handling function. */\nOCTAVE_NORETURN liboctave_error_with_id_handler\n  current_liboctave_error_with_id_handler = liboctave_fatal_with_id;\n\n/* Pointer to the current warning handler. */\nliboctave_warning_handler\n  current_liboctave_warning_handler = liboctave_warning;\n\n/* Pointer to the current warning_with_id handler. */\nliboctave_warning_with_id_handler\n  current_liboctave_warning_with_id_handler = liboctave_warning_with_id;\n\nstatic void\nverror (const char *name, const char *fmt, va_list args)\n{\n  if (name)\n    fprintf (stderr, \"%s: \", name);\n\n  vfprintf (stderr, fmt, args);\n  fprintf (stderr, \"\\n\");\n  fflush (stderr);\n}\n\nvoid\nset_liboctave_error_handler (OCTAVE_NORETURN liboctave_error_handler f)\n{\n  if (f)\n    current_liboctave_error_handler = f;\n  else\n    current_liboctave_error_handler = liboctave_fatal;\n}\n\nvoid\nset_liboctave_error_with_id_handler (OCTAVE_NORETURN\n                                     liboctave_error_with_id_handler f)\n{\n  if (f)\n    current_liboctave_error_with_id_handler = f;\n  else\n    current_liboctave_error_with_id_handler = liboctave_fatal_with_id;\n}\n\nvoid\nset_liboctave_warning_handler (liboctave_warning_handler f)\n{\n  if (f)\n    current_liboctave_warning_handler = f;\n  else\n    current_liboctave_warning_handler = liboctave_warning;\n}\n\nvoid\nset_liboctave_warning_with_id_handler (liboctave_warning_with_id_handler f)\n{\n  if (f)\n    current_liboctave_warning_with_id_handler = f;\n  else\n    current_liboctave_warning_with_id_handler = liboctave_warning_with_id;\n}\n\nvoid\nliboctave_fatal (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  verror (\"fatal\", fmt, args);\n  va_end (args);\n\n  exit (EXIT_FAILURE);\n}\n\nvoid\nliboctave_fatal_with_id (const char *id, const char *fmt, ...)\n{\n  octave_unused_parameter (id);\n\n  va_list args;\n  va_start (args, fmt);\n  verror (\"fatal\", fmt, args);\n  va_end (args);\n\n  exit (EXIT_FAILURE);\n}\n\nvoid\nliboctave_warning (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  verror (\"warning\", fmt, args);\n  va_end (args);\n}\n\nvoid\nliboctave_warning_with_id (const char *id, const char *fmt, ...)\n{\n  octave_unused_parameter (id);\n\n  va_list args;\n  va_start (args, fmt);\n  verror (\"warning\", fmt, args);\n  va_end (args);\n}\n"
  },
  {
    "path": "liboctave/util/oct-error.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_error_h)\n#define octave_oct_error_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nOCTAVE_NORETURN extern OCTAVE_API void\nliboctave_fatal (const char *fmt, ...);\n\nOCTAVE_NORETURN extern OCTAVE_API void\nliboctave_fatal_with_id (const char *id, const char *fmt, ...);\n\nextern OCTAVE_API void\nliboctave_warning (const char *fmt, ...);\n\nextern OCTAVE_API void\nliboctave_warning_with_id (const char *id, const char *fmt, ...);\n\ntypedef void (*liboctave_error_handler) (const char *, ...);\n\ntypedef void (*liboctave_error_with_id_handler) (const char *, const char *, ...);\n\ntypedef void (*liboctave_warning_handler) (const char *, ...);\n\ntypedef void (*liboctave_warning_with_id_handler) (const char *, const char *, ...);\n\n/* Would be nice to make these pointers private, but we want to share\n   them among all the liboctave classes. */\nOCTAVE_FORMAT_PRINTF (1, 2)\nOCTAVE_NORETURN extern OCTAVE_API liboctave_error_handler\n  current_liboctave_error_handler;\n\nOCTAVE_FORMAT_PRINTF (2, 3)\nOCTAVE_NORETURN extern OCTAVE_API liboctave_error_with_id_handler\n  current_liboctave_error_with_id_handler;\n\nOCTAVE_FORMAT_PRINTF (1, 2)\nextern OCTAVE_API liboctave_warning_handler current_liboctave_warning_handler;\n\nOCTAVE_FORMAT_PRINTF (2, 3)\nextern OCTAVE_API liboctave_warning_with_id_handler\n  current_liboctave_warning_with_id_handler;\n\nextern OCTAVE_API void\nset_liboctave_error_handler (OCTAVE_NORETURN liboctave_error_handler f);\n\nextern OCTAVE_API void\nset_liboctave_error_with_id_handler (OCTAVE_NORETURN liboctave_error_with_id_handler f);\n\nextern OCTAVE_API void\nset_liboctave_warning_handler (liboctave_warning_handler f);\n\nextern OCTAVE_API void\nset_liboctave_warning_with_id_handler (liboctave_warning_with_id_handler f);\n\n// To allow the __FILE__ and __LINE__ macros to work as expected, the\n// liboctave_panic_impossible, liboctave_panic_if, and\n// liboctave_panic_unless symbols must be defined as macros.\n\n#if defined (NDEBUG)\n\n#  define liboctave_panic_impossible() do { } while (0)\n\n#  define liboctave_panic_if(cond) do { } while (0)\n\n#  define liboctave_panic_unless(cond) do { } while (0)\n\n#else\n\n#  define liboctave_panic_impossible() (*current_liboctave_error_handler) (\"impossible state reached in file '%s' at line %d\", __FILE__, __LINE__)\n\n#  define liboctave_panic_if(cond) do { if (cond) liboctave_panic_impossible (); } while (0)\n\n#  define liboctave_panic_unless(cond) liboctave_panic_if (! (cond))\n\n#endif\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-glob.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"glob-wrappers.h\"\n\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"oct-glob.h\"\n#include \"oct-sysdep.h\"\n#include \"unwind-prot.h\"\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <windows.h>\n#  include <shlwapi.h>\n#  include <wchar.h>\n#endif\n\n// These functions are defined here and not in glob_match.cc so that we\n// can include the glob.h file from gnulib, which defines glob to\n// be rpl_glob.  If we include glob.h in glob_match.cc, then it\n// transforms the glob_match::glob function to be glob_match::rpl_glob,\n// which is not what we want...\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nbool\nfnmatch (const string_vector& pat, const std::string& str, int fnm_flags)\n{\n  int npat = pat.numel ();\n\n  const char *cstr = str.c_str ();\n\n  for (int i = 0; i < npat; i++)\n    if (octave_fnmatch_wrapper (pat(i).c_str (), cstr, fnm_flags)\n        != octave_fnm_nomatch_wrapper ())\n      return true;\n\n  return false;\n}\n\nstring_vector\nglob (const string_vector& pat)\n{\n  string_vector retval;\n\n  int npat = pat.numel ();\n\n  int k = 0;\n\n  void *glob_info = octave_create_glob_info_struct ();\n\n  unwind_action cleanup_glob_info_struct\n  ([glob_info] () { octave_destroy_glob_info_struct (glob_info); });\n\n  for (int i = 0; i < npat; i++)\n    {\n      std::string xpat = pat(i);\n\n      if (! xpat.empty ())\n        {\n#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)           \\\n     && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))\n          std::replace (xpat.begin (), xpat.end (), '\\\\', '/');\n#endif\n\n          int err = octave_glob_wrapper (xpat.c_str (),\n                                         octave_glob_nosort_wrapper (),\n                                         glob_info);\n\n          if (! err)\n            {\n              int n = octave_glob_num_matches (glob_info);\n\n              const char *const *matches\n                = octave_glob_match_list (glob_info);\n\n              // FIXME: we shouldn't have to check to see if\n              // a single match exists, but it seems that glob() won't\n              // check for us unless the pattern contains globbing\n              // characters.  Hmm.\n\n              if (n > 1\n                  || (n == 1\n                      && sys::file_exists (std::string (matches[0]))))\n                {\n                  retval.resize (k+n);\n\n                  for (int j = 0; j < n; j++)\n                    {\n                      std::string tmp = matches[j];\n\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)    \\\n  && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)\n                      std::replace (tmp.begin (), tmp.end (), '/', '\\\\');\n#endif\n\n                      retval[k++] = tmp;\n                    }\n                }\n\n              octave_globfree_wrapper (glob_info);\n            }\n        }\n    }\n\n  return retval.sort ();\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\nstatic void\nfind_files (std::list<std::string>& dirlist, const std::string& dir,\n            const std::string& pat, std::string& file)\n{\n  // remove leading file separators\n  bool is_file_empty = file.empty ();\n  while (! file.empty () && sys::file_ops::is_dir_sep (file[0]))\n    file = file.substr (1, std::string::npos);\n\n  bool is_trailing_file_sep = ! is_file_empty && file.empty ();\n\n  if (! pat.compare (\".\") || ! pat.compare (\"..\"))\n    {\n      // shortcut for trivial patterns that would expand to a folder name\n\n      // get next component of path (or file name)\n      std::size_t sep_pos\n        = file.find_first_of (sys::file_ops::dir_sep_chars ());\n      std::string pat_str = file.substr (0, sep_pos);\n      std::string file_str = (sep_pos != std::string::npos)\n                             ? file.substr (sep_pos) : \"\";\n\n      // Original pattern ends with \".\" or \"..\". Take it as we have it.\n      if (pat_str.empty ())\n        {\n          if (is_trailing_file_sep)\n            pat_str = sys::file_ops::dir_sep_char ();\n          dirlist.push_back (sys::file_ops::concat (dir, pat) + pat_str);\n          return;\n        }\n\n      // call this function recursively with next path component in PAT\n      find_files (dirlist, sys::file_ops::concat (dir, pat),\n                  pat_str, file_str);\n      return;\n    }\n\n  // find first file in directory that matches pattern in PAT\n  std::wstring wpat = u8_to_wstring (sys::file_ops::concat (dir, pat));\n  _WIN32_FIND_DATAW ffd;\n  HANDLE h_find = FindFirstFileW (wpat.c_str (), &ffd);\n  // ignore any error\n  if (h_find == INVALID_HANDLE_VALUE)\n    return;\n\n  unwind_action close_h_find ([h_find] () { FindClose (h_find); });\n\n  // find all files that match pattern\n  do\n    {\n      // must be directory if pattern continues\n      if (! (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\n          && (! file.empty () || is_trailing_file_sep))\n        continue;\n\n      std::string found_dir = u8_from_wstring (ffd.cFileName);\n\n      if (file.empty ())\n        {\n          // Don't include \".\" and \"..\" in matches.\n          if (found_dir.compare (\".\") && found_dir.compare (\"..\"))\n            {\n              if (is_trailing_file_sep)\n                found_dir += sys::file_ops::dir_sep_char ();\n              dirlist.push_back (sys::file_ops::concat (dir, found_dir));\n            }\n        }\n      else\n        {\n          // get next component of path (or file name)\n          std::size_t sep_pos\n            = file.find_first_of (sys::file_ops::dir_sep_chars ());\n          std::string pat_str = file.substr (0, sep_pos);\n          std::string file_str = (sep_pos != std::string::npos)\n                                 ? file.substr (sep_pos) : \"\";\n\n          // call this function recursively with next path component in PAT\n          find_files (dirlist, sys::file_ops::concat (dir, found_dir),\n                      pat_str, file_str);\n        }\n    }\n  while (FindNextFileW (h_find, &ffd) != 0);\n}\n\n#endif\n\n// Glob like Windows \"dir\".  Treat only * and ? as wildcards,\n// and \"*.*\" matches filenames even if they do not contain \".\".\nstring_vector\nwindows_glob (const string_vector& pat)\n{\n  string_vector retval;\n\n  int npat = pat.numel ();\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  std::list<std::string> dirlist;\n\n  for (int i = 0; i < npat; i++)\n    {\n      std::string xpat = pat(i);\n      if (xpat.empty ())\n        continue;\n\n      std::string dir = \"\";\n\n      // separate component until first file separator\n      std::size_t sep_pos\n        = xpat.find_first_of (sys::file_ops::dir_sep_chars ());\n\n      // handle UNC paths\n      if (sep_pos == 0 && xpat.length () > 1\n          && sys::file_ops::is_dir_sep (xpat[1]))\n        {\n          // start pattern with a file, i.e., \"\\\\SERVER\\share\\file\"\n          sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (), 2);\n          if (sep_pos != std::string::npos)\n            sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (),\n                                          sep_pos + 1);\n          if (sep_pos != std::string::npos)\n            {\n              dir = xpat.substr(0, sep_pos);\n              xpat = xpat.substr (sep_pos+1);\n              sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars ());\n            }\n        }\n\n      std::string file = (sep_pos != std::string::npos)\n                         ? xpat.substr (sep_pos) : \"\";\n      xpat = xpat.substr (0, sep_pos);\n\n      if ((sep_pos == 2 || xpat.length () == 2) && xpat[1] == ':')\n        {\n          // include disc root with first file or folder\n\n          // remove leading file separators in path without disc root\n          while (file.length () > 1 && sys::file_ops::is_dir_sep (file[0]))\n            file = file.substr (1, std::string::npos);\n\n          sep_pos = file.find_first_of (sys::file_ops::dir_sep_chars ());\n          dir = xpat;\n          xpat = file.substr (0, sep_pos);\n          file = (sep_pos != std::string::npos)\n                 ? file.substr (sep_pos) : \"\";\n          if (xpat.empty ())\n            {\n              // don't glob if input is only disc root\n              std::wstring wpat = u8_to_wstring (pat(i));\n              if (PathFileExistsW (wpat.c_str ()))\n                {\n                  if (sys::file_ops::is_dir_sep (pat(i).back ()))\n                    dirlist.push_back (dir +\n                                       sys::file_ops::dir_sep_char ());\n                  else\n                    dirlist.push_back (dir);\n                }\n              continue;\n            }\n        }\n\n      find_files (dirlist, dir, xpat, file);\n    }\n\n  retval = string_vector (dirlist);\n\n#else\n\n  int k = 0;\n\n  void *glob_info = octave_create_glob_info_struct ();\n\n  unwind_action cleanup_glob_info_struct ([glob_info] () { octave_destroy_glob_info_struct (glob_info); });\n\n  for (int i = 0; i < npat; i++)\n    {\n      std::string xpat = pat(i);\n\n      if (! xpat.empty ())\n        {\n          std::string escaped;\n          escaped.reserve (xpat.length ());\n\n          for (std::size_t j = 0; j < xpat.length (); j++)\n            {\n#  if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)           \\\n       && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))\n              if (xpat[j] == '\\\\')\n                escaped += '/';\n              else\n#  endif\n                {\n                  if (xpat[j] == ']' || xpat[j] == '[')\n                    escaped += '\\\\';\n\n                  escaped += xpat[j];\n                }\n            }\n\n          // Replace trailing \"*.*\" by \"*\".\n          int len = escaped.length ();\n          if (len >= 3 && escaped.substr (len - 3) == \"*.*\")\n            escaped = escaped.substr (0, len - 2);\n\n          int err = octave_glob_wrapper (escaped.c_str (),\n                                         octave_glob_nosort_wrapper (),\n                                         glob_info);\n\n          if (! err)\n            {\n              int n = octave_glob_num_matches (glob_info);\n\n              const char *const *matches\n                = octave_glob_match_list (glob_info);\n\n              // FIXME: we shouldn't have to check to see if\n              // a single match exists, but it seems that glob() won't\n              // check for us unless the pattern contains globbing\n              // characters.  Hmm.\n\n              if (n > 1\n                  || (n == 1\n                      && sys::file_exists (std::string (matches[0]))))\n                {\n                  retval.resize (k + n);\n\n                  for (int j = 0; j < n; j++)\n                    {\n                      std::string tmp = matches[j];\n\n                      std::string unescaped;\n                      unescaped.reserve (tmp.length ());\n\n                      for (std::size_t m = 0; m < tmp.length (); m++)\n                        {\n#  if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)           \\\n     && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))\n                          if (tmp[m] == '/')\n                            unescaped += '\\\\';\n                          else\n#  endif\n                            {\n                              if (tmp[m] == '\\\\'\n                                  && ++m == tmp.length ())\n                                break;\n\n                              unescaped += tmp[m];\n                            }\n                        }\n\n                      retval[k++] = unescaped;\n                    }\n                }\n\n              octave_globfree_wrapper (glob_info);\n            }\n        }\n    }\n#endif\n\n  return retval.sort ();\n}\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/oct-glob.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2010-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_glob_h)\n#define octave_oct_glob_h 1\n\n#include \"octave-config.h\"\n\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(sys)\n\nextern OCTAVE_API bool\nfnmatch (const string_vector& pat, const std::string& str,\n         int fnmatch_flags);\n\nextern OCTAVE_API string_vector\nglob (const string_vector&);\n\nextern OCTAVE_API string_vector\nwindows_glob (const string_vector&);\n\nOCTAVE_END_NAMESPACE(sys)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-hash.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <algorithm>\n#include <iomanip>\n#include <sstream>\n#include <string>\n\n#include \"hash-wrappers.h\"\n#include \"oct-error.h\"\n#include \"oct-hash.h\"\n#include \"oct-locbuf.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(crypto)\n\nstd::string\nhash (hash_fptr hash_fcn, const std::string& str, int result_buf_len)\n{\n  OCTAVE_LOCAL_BUFFER (unsigned char, result_buf, result_buf_len);\n\n  hash_fcn (str.data (), str.length (), result_buf);\n\n  std::ostringstream buf;\n\n  for (int i = 0; i < result_buf_len; i++)\n    buf << std::hex << std::setw (2) << std::setfill ('0')\n        << (result_buf[i] & 0xFF);\n\n  return buf.str ();\n}\n\nint md2_digest_size () { return octave_md2_digest_size (); }\nint md4_digest_size () { return octave_md4_digest_size (); }\nint md5_digest_size () { return octave_md5_digest_size (); }\nint sha1_digest_size () { return octave_sha1_digest_size (); }\nint sha224_digest_size () { return octave_sha224_digest_size (); }\nint sha256_digest_size () { return octave_sha256_digest_size (); }\nint sha384_digest_size () { return octave_sha384_digest_size (); }\nint sha512_digest_size () { return octave_sha512_digest_size (); }\n\nstd::string\nmd2_hash (const std::string& str)\n{\n  return hash (octave_md2_buffer_wrapper, str, md2_digest_size ());\n}\n\nstd::string\nmd4_hash (const std::string& str)\n{\n  return hash (octave_md4_buffer_wrapper, str, md4_digest_size ());\n}\n\nstd::string\nmd5_hash (const std::string& str)\n{\n  return hash (octave_md5_buffer_wrapper, str, md5_digest_size ());\n}\n\nstd::string\nsha1_hash (const std::string& str)\n{\n  return hash (octave_sha1_buffer_wrapper, str, sha1_digest_size ());\n}\n\nstd::string\nsha224_hash (const std::string& str)\n{\n  return hash (octave_sha224_buffer_wrapper, str, sha224_digest_size ());\n}\n\nstd::string\nsha256_hash (const std::string& str)\n{\n  return hash (octave_sha256_buffer_wrapper, str, sha256_digest_size ());\n}\n\nstd::string\nsha384_hash (const std::string& str)\n{\n  return hash (octave_sha384_buffer_wrapper, str, sha384_digest_size ());\n}\n\nstd::string\nsha512_hash (const std::string& str)\n{\n  return hash (octave_sha512_buffer_wrapper, str, sha512_digest_size ());\n}\n\nstd::string\nhash (const std::string& hash_type, const std::string& str)\n{\n  std::string ht = hash_type;\n\n  std::transform (ht.begin (), ht.end (), ht.begin (), ::toupper);\n\n  if (ht == \"MD2\")\n    return md2_hash (str);\n  else if (ht == \"MD4\")\n    return md4_hash (str);\n  else if (ht == \"MD5\")\n    return md5_hash (str);\n  else if (ht == \"SHA1\")\n    return sha1_hash (str);\n  else if (ht == \"SHA224\")\n    return sha224_hash (str);\n  else if (ht == \"SHA256\")\n    return sha256_hash (str);\n  else if (ht == \"SHA384\")\n    return sha384_hash (str);\n  else if (ht == \"SHA512\")\n    return sha512_hash (str);\n  else\n    (*current_liboctave_error_handler)\n      (\"hash function '%s' not supported\", hash_type.c_str ());\n}\n\nOCTAVE_END_NAMESPACE(crypto)\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/oct-hash.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_hash_h)\n#define octave_oct_hash_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(crypto)\n\ntypedef void *(hash_fptr) (const char *buffer, std::size_t len, void *res);\n\nOCTAVE_API std::string\nhash (hash_fptr hash_fcn, const std::string& str, int result_buf_len);\n\nOCTAVE_API int md2_digest_size ();\nOCTAVE_API int md4_digest_size ();\nOCTAVE_API int md5_digest_size ();\nOCTAVE_API int sha1_digest_size ();\nOCTAVE_API int sha224_digest_size ();\nOCTAVE_API int sha256_digest_size ();\nOCTAVE_API int sha384_digest_size ();\nOCTAVE_API int sha512_digest_size ();\n\nOCTAVE_API std::string md2_hash (const std::string& str);\nOCTAVE_API std::string md4_hash (const std::string& str);\nOCTAVE_API std::string md5_hash (const std::string& str);\nOCTAVE_API std::string sha1_hash (const std::string& str);\nOCTAVE_API std::string sha224_hash (const std::string& str);\nOCTAVE_API std::string sha256_hash (const std::string& str);\nOCTAVE_API std::string sha384_hash (const std::string& str);\nOCTAVE_API std::string sha512_hash (const std::string& str);\n\nOCTAVE_API std::string\nhash (const std::string& hash_type, const std::string& str);\n\nOCTAVE_END_NAMESPACE(crypto)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-inttypes-fwd.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_inttypes_fwd_h)\n#define octave_oct_inttypes_fwd_h 1\n\n#include \"octave-config.h\"\n\ntemplate <typename T> class OCTAVE_TEMPLATE_API octave_int;\n\ntypedef octave_int<int8_t> octave_int8;\ntypedef octave_int<int16_t> octave_int16;\ntypedef octave_int<int32_t> octave_int32;\ntypedef octave_int<int64_t> octave_int64;\n\ntypedef octave_int<uint8_t> octave_uint8;\ntypedef octave_int<uint16_t> octave_uint16;\ntypedef octave_int<uint32_t> octave_uint32;\ntypedef octave_int<uint64_t> octave_uint64;\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-inttypes.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"fpucw-wrappers.h\"\n#include \"oct-error.h\"\n#include \"oct-inttypes.h\"\n\ntemplate <typename T>\nconst octave_int<T> octave_int<T>::s_zero (static_cast<T> (0));\n\ntemplate <typename T>\nconst octave_int<T> octave_int<T>::s_one (static_cast<T> (1));\n\n// Define type names.\n\n#define DEFINE_OCTAVE_INT_TYPENAME(TYPE, TYPENAME)              \\\n  template <>                                                   \\\n  OCTAVE_API const char *                                       \\\n  octave_int<TYPE>::type_name () { return TYPENAME; }\n\nDEFINE_OCTAVE_INT_TYPENAME (int8_t, \"int8\")\nDEFINE_OCTAVE_INT_TYPENAME (int16_t, \"int16\")\nDEFINE_OCTAVE_INT_TYPENAME (int32_t, \"int32\")\nDEFINE_OCTAVE_INT_TYPENAME (int64_t, \"int64\")\nDEFINE_OCTAVE_INT_TYPENAME (uint8_t, \"uint8\")\nDEFINE_OCTAVE_INT_TYPENAME (uint16_t, \"uint16\")\nDEFINE_OCTAVE_INT_TYPENAME (uint32_t, \"uint32\")\nDEFINE_OCTAVE_INT_TYPENAME (uint64_t, \"uint64\")\n\ntemplate <class T>\ntemplate <class S>\nT\noctave_int_base<T>::convert_real (const S& value)\n{\n  // Compute proper thresholds.\n  static const S thmin = compute_threshold (static_cast<S> (min_val ()),\n                                            min_val ());\n  static const S thmax = compute_threshold (static_cast<S> (max_val ()),\n                                            max_val ());\n  if (octave::math::isnan (value))\n    return static_cast<T> (0);\n  else if (value < thmin)\n    return min_val ();\n  else if (value > thmax)\n    return max_val ();\n  else\n    {\n      S rvalue = octave::math::round (value);\n      return static_cast<T> (rvalue);\n    }\n}\n\n#define INSTANTIATE_CONVERT_REAL_1(T, S)        \\\n  template                                      \\\n  OCTAVE_API                                    \\\n  T                                             \\\n  octave_int_base<T>::convert_real (const S&)\n\n#define INSTANTIATE_CONVERT_REAL(S)             \\\n  INSTANTIATE_CONVERT_REAL_1 (int8_t, S);       \\\n  INSTANTIATE_CONVERT_REAL_1 (uint8_t, S);      \\\n  INSTANTIATE_CONVERT_REAL_1 (int16_t, S);      \\\n  INSTANTIATE_CONVERT_REAL_1 (uint16_t, S);     \\\n  INSTANTIATE_CONVERT_REAL_1 (int32_t, S);      \\\n  INSTANTIATE_CONVERT_REAL_1 (uint32_t, S);     \\\n  INSTANTIATE_CONVERT_REAL_1 (int64_t, S);      \\\n  INSTANTIATE_CONVERT_REAL_1 (uint64_t, S)\n\nINSTANTIATE_CONVERT_REAL (double);\nINSTANTIATE_CONVERT_REAL (float);\n#if defined (OCTAVE_INT_USE_LONG_DOUBLE)\nINSTANTIATE_CONVERT_REAL (long double);\n#endif\n\n#if defined (OCTAVE_INT_USE_LONG_DOUBLE)\n\n#  if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)\n\n#    define DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES(T)       \\\n  template <typename xop>                                       \\\n  bool                                                          \\\n  octave_int_cmp_op::external_mop (double x, T y)               \\\n  {                                                             \\\n    unsigned int oldcw = octave_begin_long_double_rounding ();  \\\n                                                                \\\n    bool retval = xop::op (static_cast<long double> (x),        \\\n                           static_cast<long double> (y));       \\\n                                                                \\\n    octave_end_long_double_rounding (oldcw);                    \\\n                                                                \\\n    return retval;                                              \\\n  }                                                             \\\n                                                                \\\n  template <typename xop>                                       \\\n  bool                                                          \\\n  octave_int_cmp_op::external_mop (T x, double y)               \\\n  {                                                             \\\n    unsigned int oldcw = octave_begin_long_double_rounding ();  \\\n                                                                \\\n    bool retval = xop::op (static_cast<long double> (x),        \\\n                           static_cast<long double> (y));       \\\n                                                                \\\n    octave_end_long_double_rounding (oldcw);                    \\\n                                                                \\\n    return retval;                                              \\\n  }\n\nDEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES (int64_t)\nDEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES (uint64_t)\n\n#    define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(OP, T)           \\\n  template OCTAVE_API bool                                              \\\n  octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (double, T);   \\\n                                                                        \\\n  template OCTAVE_API bool                                              \\\n  octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (T, double)\n\n#    define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS(T)      \\\n  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (lt, T);           \\\n  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (le, T);           \\\n  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (gt, T);           \\\n  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (ge, T);           \\\n  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (eq, T);           \\\n  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (ne, T)\n\nINSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS (int64_t);\nINSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS (uint64_t);\n\nuint64_t\noctave_external_uint64_uint64_mul (uint64_t x, uint64_t y)\n{\n  unsigned int oldcw = octave_begin_long_double_rounding ();\n\n  uint64_t retval = octave_int_arith_base<uint64_t, false>::mul_internal (x, y);\n\n  octave_end_long_double_rounding (oldcw);\n\n  return retval;\n}\n\nint64_t\noctave_external_int64_int64_mul (int64_t x, int64_t y)\n{\n  unsigned int oldcw = octave_begin_long_double_rounding ();\n\n  int64_t retval = octave_int_arith_base<int64_t, true>::mul_internal (x, y);\n\n  octave_end_long_double_rounding (oldcw);\n\n  return retval;\n}\n\n// Note that if we return long double it is apparently possible for\n// truncation to happen at the point of storing the result in retval,\n// which can happen after we end long double rounding.  Attempt to avoid\n// that problem by storing the full precision temporary value in the\n// integer value before we end the long double rounding mode.\n// Similarly, the conversion from the 64-bit integer type to long double\n// must also occur in long double rounding mode.\n\n#    define DEFINE_OCTAVE_LONG_DOUBLE_OP(T, OP, NAME)           \\\n  T                                                             \\\n  external_double_ ## T ## _ ## NAME (double x, T y)            \\\n  {                                                             \\\n    unsigned int oldcw = octave_begin_long_double_rounding ();  \\\n                                                                \\\n    T retval = T (x OP static_cast<long double> (y.value ()));  \\\n                                                                \\\n    octave_end_long_double_rounding (oldcw);                    \\\n                                                                \\\n    return retval;                                              \\\n  }                                                             \\\n                                                                \\\n  T                                                             \\\n  external_ ## T ## _double_ ## NAME (T x, double y)            \\\n  {                                                             \\\n    unsigned int oldcw = octave_begin_long_double_rounding ();  \\\n                                                                \\\n    T retval = T (static_cast<long double> (x.value ()) OP y);  \\\n                                                                \\\n    octave_end_long_double_rounding (oldcw);                    \\\n                                                                \\\n    return retval;                                              \\\n  }\n\n#    define DEFINE_OCTAVE_LONG_DOUBLE_OPS(T)    \\\n  DEFINE_OCTAVE_LONG_DOUBLE_OP (T, +, add);     \\\n  DEFINE_OCTAVE_LONG_DOUBLE_OP (T, -, sub);     \\\n  DEFINE_OCTAVE_LONG_DOUBLE_OP (T, *, mul);     \\\n  DEFINE_OCTAVE_LONG_DOUBLE_OP (T, /, div)\n\nDEFINE_OCTAVE_LONG_DOUBLE_OPS (octave_int64);\nDEFINE_OCTAVE_LONG_DOUBLE_OPS (octave_uint64);\n\n#  endif\n\n#else\n\n// Define comparison operators\n\ntemplate <typename xop>\nbool\noctave_int_cmp_op::emulate_mop (uint64_t x, double y)\n{\n  // The following cast changes the value to 2^64 (which is outside the range\n  // of `uint64_t`).  Take care to handle this correctly (e.g., don't cast back\n  // to `uint64_t`)!\n  static const double xxup\n    = static_cast<double> (std::numeric_limits<uint64_t>::max ());\n  // This converts to the nearest double.  Unless there's an equality, the\n  // result is clear.\n  double xx = x;\n  if (xx != y)\n    return xop::op (xx, y);\n  else\n    {\n      // If equality occurred we compare as integers.\n      if (xx == xxup)\n        return xop::gtval;\n      else\n        return xop::op (x, static_cast<uint64_t> (xx));\n    }\n}\n\ntemplate <typename xop>\nbool\noctave_int_cmp_op::emulate_mop (int64_t x, double y)\n{\n  // The following cast changes the value to 2^63 (which is outside the range\n  // of `int64_t`).  Take care to handle this correctly (e.g., don't cast back\n  // to `int64_t`)!  The same applies to the lower limit on systems using one's\n  // complement.\n  static const double xxup\n    = static_cast<double> (std::numeric_limits<int64_t>::max ());\n  static const double xxlo\n    = static_cast<double> (std::numeric_limits<int64_t>::min ());\n  // This converts to the nearest double.  Unless there's an equality, the\n  // result is clear.\n  double xx = x;\n  if (xx != y)\n    return xop::op (xx, y);\n  else\n    {\n      // If equality occurred we compare as integers.\n      if (xx == xxup)\n        return xop::gtval;\n      else if (xx == xxlo)\n        return xop::ltval;\n      else\n        return xop::op (x, static_cast<int64_t> (xx));\n    }\n\n}\n\n// We define double-int operations by reverting the operator\n\n// A trait class reverting the operator\ntemplate <typename xop>\nclass rev_op\n{\npublic:\n  typedef xop op;\n};\n\n#define DEFINE_REVERTED_OPERATOR(OP1, OP2)      \\\n  template <>                                   \\\n  class rev_op<octave_int_cmp_op::OP1>          \\\n  {                                             \\\n  public:                                       \\\n    typedef octave_int_cmp_op::OP2 op;          \\\n  }\n\nDEFINE_REVERTED_OPERATOR (lt, gt);\nDEFINE_REVERTED_OPERATOR (gt, lt);\nDEFINE_REVERTED_OPERATOR (le, ge);\nDEFINE_REVERTED_OPERATOR (ge, le);\n\ntemplate <typename xop>\nbool\noctave_int_cmp_op::emulate_mop (double x, uint64_t y)\n{\n  typedef typename rev_op<xop>::op rop;\n  return mop<rop> (y, x);\n}\n\ntemplate <typename xop>\nbool\noctave_int_cmp_op::emulate_mop (double x, int64_t y)\n{\n  typedef typename rev_op<xop>::op rop;\n  return mop<rop> (y, x);\n}\n\n// Define handlers for (u)int64 multiplication.\n\ntemplate <>\nuint64_t\noctave_int_arith_base<uint64_t, false>::mul_internal (uint64_t x, uint64_t y)\n{\n  // Get upper words\n  uint64_t ux = x >> 32;\n  uint64_t uy = y >> 32;\n  uint64_t res;\n  if (ux)\n    {\n      if (uy)\n        goto overflow;\n      else\n        {\n          uint64_t ly = static_cast<uint32_t> (y);\n          uint64_t uxly = ux*ly;\n          if (uxly >> 32)\n            goto overflow;\n          uxly <<= 32;  // never overflows\n          uint64_t lx = static_cast<uint32_t> (x);\n          uint64_t lxly = lx*ly;\n          res = add (uxly, lxly);\n        }\n    }\n  else if (uy)\n    {\n      uint64_t lx = static_cast<uint32_t> (x);\n      uint64_t uylx = uy*lx;\n      if (uylx >> 32)\n        goto overflow;\n      uylx <<= 32;  // never overflows\n      uint64_t ly = static_cast<uint32_t> (y);\n      uint64_t lylx = ly*lx;\n      res = add (uylx, lylx);\n    }\n  else\n    {\n      uint64_t lx = static_cast<uint32_t> (x);\n      uint64_t ly = static_cast<uint32_t> (y);\n      res = lx*ly;\n    }\n\n  return res;\n\noverflow:\n  return max_val ();\n}\n\ntemplate <>\nint64_t\noctave_int_arith_base<int64_t, true>::mul_internal (int64_t x, int64_t y)\n{\n  // The signed case is far worse.  The problem is that even if neither\n  // integer fits into signed 32-bit range, the result may still be OK.\n  // Uh oh.\n\n  // Essentially, what we do is compute sign, multiply absolute values\n  // (as above) and impose the sign.\n\n  // But first, avoid overflow in computation of abs (min_val ()).\n\n  if (x == min_val ())\n    return y == 0 ? 0 : (y < 0 ? max_val () : min_val ());\n\n  if (y == min_val ())\n    return x == 0 ? 0 : (x < 0 ? max_val () : min_val ());\n\n  uint64_t usx = octave_int_abs (x);\n  uint64_t usy = octave_int_abs (y);\n  bool positive = (x < 0) == (y < 0);\n\n  // Get upper words\n  uint64_t ux = usx >> 32;\n  uint64_t uy = usy >> 32;\n  uint64_t res;\n  if (ux)\n    {\n      if (uy)\n        goto overflow;\n      else\n        {\n          uint64_t ly = static_cast<uint32_t> (usy);\n          uint64_t uxly = ux*ly;\n          if (uxly >> 32)\n            goto overflow;\n          uxly <<= 32;  // never overflows\n          uint64_t lx = static_cast<uint32_t> (usx);\n          uint64_t lxly = lx*ly;\n          res = uxly + lxly;\n          if (res < uxly)\n            goto overflow;\n        }\n    }\n  else if (uy)\n    {\n      uint64_t lx = static_cast<uint32_t> (usx);\n      uint64_t uylx = uy*lx;\n      if (uylx >> 32)\n        goto overflow;\n      uylx <<= 32;  // never overflows\n      uint64_t ly = static_cast<uint32_t> (usy);\n      uint64_t lylx = ly*lx;\n      res = uylx + lylx;\n      if (res < uylx)\n        goto overflow;\n    }\n  else\n    {\n      uint64_t lx = static_cast<uint32_t> (usx);\n      uint64_t ly = static_cast<uint32_t> (usy);\n      res = lx*ly;\n    }\n\n  if (positive)\n    {\n      if (res > static_cast<uint64_t> (max_val ()))\n        return max_val ();\n      else\n        return static_cast<int64_t> (res);\n    }\n  else\n    {\n      if (res > static_cast<uint64_t> (min_val ()))\n        return min_val ();\n      else\n        return -static_cast<int64_t> (res);\n    }\n\noverflow:\n  return positive ? max_val () : min_val ();\n\n}\n\ntemplate <>\nOCTAVE_API octave_uint64\noperator + (const octave_uint64& x, const double& y)\n{\n  return (y < 0) ? x - octave_uint64 (-y) : x + octave_uint64 (y);\n}\n\ntemplate <>\nOCTAVE_API octave_uint64\noperator + (const double& x, const octave_uint64& y)\n{\n  return y + x;\n}\n\ntemplate <>\nOCTAVE_API octave_int64\noperator + (const octave_int64& x, const double& y)\n{\n  // The following cast changes the value to 2^63 (which is outside the range\n  // of `int64_t`).\n  if (fabs (y) < static_cast<double> (octave_int64::max ()))\n    return x + octave_int64 (y);\n  else\n    {\n      // If the number is within the int64 range (the most common case,\n      // probably), the above will work as expected.  If not, it's more\n      // complicated - as long as y is within _twice_ the signed range, the\n      // result may still be an integer.  An instance of such an operation is\n      // 3*2^62 + (1+intmin ('int64')) that should yield int64 (2^62) + 1.\n      // So what we do is to try to convert y/2 and add it twice.  Note that\n      // if y/2 overflows, the result must overflow as well, and that y/2\n      // cannot be a fractional number.\n      octave_int64 y2 (y / 2);\n      return (x + y2) + y2;\n    }\n}\n\ntemplate <>\nOCTAVE_API octave_int64\noperator + (const double& x, const octave_int64& y)\n{\n  return y + x;\n}\n\ntemplate <>\nOCTAVE_API octave_uint64\noperator - (const octave_uint64& x, const double& y)\n{\n  return x + (-y);\n}\n\ntemplate <>\nOCTAVE_API octave_uint64\noperator - (const double& x, const octave_uint64& y)\n{\n  // The following cast changes the value to 2^64 (which is outside the range\n  // of `uint64_t`).\n  if (x < static_cast<double> (octave_uint64::max ()))\n    return octave_uint64 (x) - y;\n  else\n    {\n      // Again a trick to get the corner cases right.  Things like\n      // 3^2^63 - intmax ('uint64') should produce the correct result, i.e.,\n      // int64 (2^63) + 1.\n      const double p2_64 = std::pow (2.0, 64);\n      if (y.bool_value ())\n        {\n          const uint64_t p2_64my = (~y.value ()) + 1; // Equals 2^64 - y\n          return octave_uint64 (x - p2_64) + octave_uint64 (p2_64my);\n        }\n      else\n        return octave_uint64 (p2_64);\n    }\n}\n\ntemplate <>\nOCTAVE_API octave_int64\noperator - (const octave_int64& x, const double& y)\n{\n  return x + (-y);\n}\n\ntemplate <>\nOCTAVE_API octave_int64\noperator - (const double& x, const octave_int64& y)\n{\n  static constexpr bool twosc = (std::numeric_limits<int64_t>::min ()\n                                 < -std::numeric_limits<int64_t>::max ());\n  // In case of symmetric integers (not two's complement), this will probably\n  // be eliminated at compile time.\n  if (twosc && y.value () == std::numeric_limits<int64_t>::min ())\n    return octave_int64 (x + std::pow (2.0, 63));\n  else\n    return x + (-y);\n}\n\n// NOTE:\n// Emulated mixed multiplications are tricky due to possible precision loss.\n// Here, after sorting out common cases for speed, we follow the strategy\n// of converting the double number into the form sign * 64-bit integer *\n// 2^exponent, multiply the 64-bit integers to get a 128-bit number, split that\n// number into 32-bit words and form 4 double-valued summands (none of which\n// loses precision), then convert these into integers and sum them.  Though it\n// is not immediately obvious, this should work even w.r.t. rounding (none of\n// the summands lose precision).\n\n// Multiplies two unsigned 64-bit ints to get a 128-bit number represented\n// as four 32-bit words.\nstatic void\numul128 (uint64_t x, uint64_t y, uint32_t w[4])\n{\n  uint64_t lx = static_cast<uint32_t> (x);\n  uint64_t ux = x >> 32;\n  uint64_t ly = static_cast<uint32_t> (y);\n  uint64_t uy = y >> 32;\n  uint64_t a = lx * ly;\n  w[0] = a; a >>= 32;\n  uint64_t uxly = ux*ly;\n  uint64_t uylx = uy*lx;\n  a += static_cast<uint32_t> (uxly); uxly >>= 32;\n  a += static_cast<uint32_t> (uylx); uylx >>= 32;\n  w[1] = a; a >>= 32;\n  uint64_t uxuy = ux * uy;\n  a += uxly; a += uylx; a += uxuy;\n  w[2] = a; a >>= 32;\n  w[3] = a;\n}\n\n// Splits a double into bool sign, unsigned 64-bit mantissa and int exponent\nstatic void\ndblesplit (double x, bool& sign, uint64_t& mtis, int& exp)\n{\n  sign = x < 0; x = fabs (x);\n  x = octave::math::frexp (x, &exp);\n  exp -= 52;\n  mtis = static_cast<uint64_t> (ldexp (x, 52));\n}\n\n// Gets a double number from a\n// 32-bit unsigned integer mantissa, exponent, and sign.\nstatic double\ndbleget (bool sign, uint32_t mtis, int exp)\n{\n  double x = ldexp (static_cast<double> (mtis), exp);\n  return sign ? -x : x;\n}\n\ntemplate <>\nOCTAVE_API octave_uint64\noperator * (const octave_uint64& x, const double& y)\n{\n  // The following cast changes the value to 2^64 (which is outside the range\n  // of `uint64_t`).\n  if (y >= 0 && y < static_cast<double> (octave_uint64::max ())\n      && y == octave::math::fix (y))\n    return x * octave_uint64 (static_cast<uint64_t> (y));\n  else if (y == 0.5)\n    return x / octave_uint64 (static_cast<uint64_t> (2));\n  else if (y < 0 || octave::math::isnan (y) || octave::math::isinf (y))\n    return octave_uint64 (x.value () * y);\n  else\n    {\n      bool sign;\n      uint64_t my;\n      int e;\n      dblesplit (y, sign, my, e);\n      uint32_t w[4];\n      umul128 (x.value (), my, w);\n      octave_uint64 res = octave_uint64::s_zero;\n      for (short i = 0; i < 4; i++)\n        {\n          res += octave_uint64 (dbleget (sign, w[i], e));\n          e += 32;\n        }\n      return res;\n    }\n}\n\ntemplate <>\nOCTAVE_API octave_uint64\noperator * (const double& x, const octave_uint64& y)\n{\n  return y * x;\n}\n\ntemplate <>\nOCTAVE_API octave_int64\noperator * (const octave_int64& x, const double& y)\n{\n  // The following cast changes the value to 2^63 (which is outside the range\n  // of `int64_t`).\n  if (fabs (y) < static_cast<double> (octave_int64::max ())\n      && y == octave::math::fix (y))\n    return x * octave_int64 (static_cast<int64_t> (y));\n  else if (fabs (y) == 0.5)\n    return x / octave_int64 (static_cast<uint64_t> (4*y));\n  else if (octave::math::isnan (y) || octave::math::isinf (y))\n    return octave_int64 (x.value () * y);\n  else\n    {\n      bool sign;\n      uint64_t my;\n      int e;\n      dblesplit (y, sign, my, e);\n      uint32_t w[4];\n      sign = (sign != (x.value () < 0));\n      umul128 (octave_int_abs (x.value ()), my, w);\n      octave_int64 res = octave_int64::s_zero;\n      for (short i = 0; i < 4; i++)\n        {\n          res += octave_int64 (dbleget (sign, w[i], e));\n          e += 32;\n        }\n      return res;\n    }\n}\n\ntemplate <>\nOCTAVE_API octave_int64\noperator * (const double& x, const octave_int64& y)\n{\n  return y * x;\n}\n\ntemplate <>\nOCTAVE_API octave_uint64\noperator / (const double& x, const octave_uint64& y)\n{\n  return octave_uint64 (x / static_cast<double> (y));\n}\n\ntemplate <>\nOCTAVE_API octave_int64\noperator / (const double& x, const octave_int64& y)\n{\n  return octave_int64 (x / static_cast<double> (y));\n}\n\ntemplate <>\nOCTAVE_API octave_uint64\noperator / (const octave_uint64& x, const double& y)\n{\n  // The following cast changes the value to 2^64 (which is outside the range\n  // of `uint64_t`).\n  if (y >= 0 && y < static_cast<double> (octave_uint64::max ())\n      && y == octave::math::fix (y))\n    return x / octave_uint64 (y);\n  else\n    return x * (1.0/y);\n}\n\ntemplate <>\nOCTAVE_API octave_int64\noperator / (const octave_int64& x, const double& y)\n{\n  // The following cast changes the value to 2^63 (which is outside the range\n  // of `int64_t`).\n  if (fabs (y) < static_cast<double> (octave_int64::max ())\n      && y == octave::math::fix (y))\n    return x / octave_int64 (y);\n  else\n    return x * (1.0/y);\n}\n\n#define INSTANTIATE_INT64_DOUBLE_CMP_OP0(OP, T1, T2)                    \\\n  template OCTAVE_API bool                                              \\\n  octave_int_cmp_op::emulate_mop<octave_int_cmp_op::OP> (T1 x, T2 y)\n\n#define INSTANTIATE_INT64_DOUBLE_CMP_OP(OP)                     \\\n  INSTANTIATE_INT64_DOUBLE_CMP_OP0 (OP, double, int64_t);       \\\n  INSTANTIATE_INT64_DOUBLE_CMP_OP0 (OP, double, uint64_t);      \\\n  INSTANTIATE_INT64_DOUBLE_CMP_OP0 (OP, int64_t, double);       \\\n  INSTANTIATE_INT64_DOUBLE_CMP_OP0 (OP, uint64_t, double)\n\nINSTANTIATE_INT64_DOUBLE_CMP_OP (lt);\nINSTANTIATE_INT64_DOUBLE_CMP_OP (le);\nINSTANTIATE_INT64_DOUBLE_CMP_OP (gt);\nINSTANTIATE_INT64_DOUBLE_CMP_OP (ge);\nINSTANTIATE_INT64_DOUBLE_CMP_OP (eq);\nINSTANTIATE_INT64_DOUBLE_CMP_OP (ne);\n\n#endif\n\ntemplate <typename T>\noctave_int<T>\npow (const octave_int<T>& a, const octave_int<T>& b)\n{\n  octave_int<T> retval;\n\n  const octave_int<T> zero = octave_int<T>::s_zero;\n  const octave_int<T> one = octave_int<T>::s_one;\n\n  if (b == zero || a == one)\n    retval = one;\n  else if (b < zero)\n    {\n      if (a == -one)\n        retval = (b.value () % 2) ? a : one;\n      else\n        retval = zero;\n    }\n  else\n    {\n      octave_int<T> a_val = a;\n      T b_val = b; // no need to do saturation on b\n\n      retval = a;\n\n      b_val -= 1;\n\n      while (b_val != 0)\n        {\n          if (b_val & 1)\n            retval = retval * a_val;\n\n          b_val = b_val >> 1;\n\n          if (b_val)\n            a_val = a_val * a_val;\n        }\n    }\n\n  return retval;\n}\n\ntemplate <typename T>\noctave_int<T>\npow (const double& a, const octave_int<T>& b)\n{ return octave_int<T> (std::pow (a, b.double_value ())); }\n\ntemplate <typename T>\noctave_int<T>\npow (const octave_int<T>& a, const double& b)\n{\n  return ((b >= 0 && b < std::numeric_limits<T>::digits\n           && b == octave::math::fix (b))\n          ? pow (a, octave_int<T> (static_cast<T> (b)))\n          : octave_int<T> (std::pow (a.double_value (), b)));\n}\n\ntemplate <typename T>\noctave_int<T>\npow (const float& a, const octave_int<T>& b)\n{ return octave_int<T> (std::pow (a, b.float_value ())); }\n\ntemplate <typename T>\noctave_int<T>\npow (const octave_int<T>& a, const float& b)\n{\n  return ((b >= 0 && b < std::numeric_limits<T>::digits\n           && b == octave::math::fix (b))\n          ? pow (a, octave_int<T> (static_cast<T> (b)))\n          : octave_int<T> (std::pow (a.double_value (),\n                                     static_cast<double> (b))));\n}\n\n// FIXME: Do we really need a differently named single-precision function\n//        integer power function here instead of an overloaded one?\ntemplate <typename T>\noctave_int<T>\npowf (const float& a, const octave_int<T>& b)\n{ return octave_int<T> (pow (a, b.float_value ())); }\n\ntemplate <typename T>\noctave_int<T>\npowf (const octave_int<T>& a, const float& b)\n{\n  return ((b >= 0 && b < std::numeric_limits<T>::digits\n           && b == octave::math::fix (b))\n          ? pow (a, octave_int<T> (static_cast<T> (b)))\n          : octave_int<T> (std::pow (a.double_value (),\n                                     static_cast<double> (b))));\n}\n\n#define INSTANTIATE_INTTYPE(T)                                          \\\n  template class octave_int<T>;                                         \\\n                                                                        \\\n  template OCTAVE_API octave_int<T>                                     \\\n  pow (const octave_int<T>&, const octave_int<T>&);                     \\\n                                                                        \\\n  template OCTAVE_API octave_int<T>                                     \\\n  pow (const double&, const octave_int<T>&);                            \\\n                                                                        \\\n  template OCTAVE_API octave_int<T>                                     \\\n  pow (const octave_int<T>&, const double&);                            \\\n                                                                        \\\n  template OCTAVE_API octave_int<T>                                     \\\n  pow (const float&, const octave_int<T>&);                             \\\n                                                                        \\\n  template OCTAVE_API octave_int<T>                                     \\\n  pow (const octave_int<T>&, const float&);                             \\\n                                                                        \\\n  template OCTAVE_API octave_int<T>                                     \\\n  powf (const float&, const octave_int<T>&);                            \\\n                                                                        \\\n  template OCTAVE_API octave_int<T>                                     \\\n  powf (const octave_int<T>&, const float&);                            \\\n                                                                        \\\n  template OCTAVE_API octave_int<T>                                     \\\n  bitshift (const octave_int<T>&, int, const octave_int<T>&);\n\nINSTANTIATE_INTTYPE (int8_t);\nINSTANTIATE_INTTYPE (int16_t);\nINSTANTIATE_INTTYPE (int32_t);\nINSTANTIATE_INTTYPE (int64_t);\n\nINSTANTIATE_INTTYPE (uint8_t);\nINSTANTIATE_INTTYPE (uint16_t);\nINSTANTIATE_INTTYPE (uint32_t);\nINSTANTIATE_INTTYPE (uint64_t);\n\n/*\n\n%!assert (intmax (\"int64\") / intmin (\"int64\"), int64 (-1))\n%!assert (intmin (\"int64\") / int64 (-1), intmax (\"int64\"))\n%!assert (int64 (2^63), intmax (\"int64\"))\n%!assert (uint64 (2^64), intmax (\"uint64\"))\n%!test\n%! a = 1.9*2^61; b = uint64 (a); b++; assert (b > a);\n%!test\n%! a = -1.9*2^61; b = int64 (a); b++; assert (b > a);\n%!test\n%! a = int64 (-2^60) + 2; assert (1.25*a == (5*a)/4);\n%!test\n%! a = uint64 (2^61) + 2; assert (1.25*a == (5*a)/4);\n%!assert (int32 (2^31+0.5), intmax (\"int32\"))\n%!assert (int32 (-2^31-0.5), intmin (\"int32\"))\n%!assert ((int64 (2^62)+1)^1, int64 (2^62)+1)\n%!assert ((int64 (2^30)+1)^2, int64 (2^60+2^31) + 1)\n\n%!assert <54382> (uint8 (char (128)), uint8 (128))\n%!assert <54382> (uint8 (char (255)), uint8 (255))\n%!assert <54382> (int8 (char (128)), int8 (128))\n%!assert <54382> (int8 (char (255)), int8 (255))\n\n%!assert <54382> (uint16 (char (128)), uint16 (128))\n%!assert <54382> (uint16 (char (255)), uint16 (255))\n%!assert <54382> (int16 (char (128)), int16 (128))\n%!assert <54382> (int16 (char (255)), int16 (255))\n\n%!assert <54382> (uint32 (char (128)), uint32 (128))\n%!assert <54382> (uint32 (char (255)), uint32 (255))\n%!assert <54382> (int32 (char (128)), int32 (128))\n%!assert <54382> (int32 (char (255)), int32 (255))\n\n%!assert <54382> (uint64 (char (128)), uint64 (128))\n%!assert <54382> (uint64 (char (255)), uint64 (255))\n%!assert <54382> (int64 (char (128)), int64 (128))\n%!assert <54382> (int64 (char (255)), int64 (255))\n*/\n"
  },
  {
    "path": "liboctave/util/oct-inttypes.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2004-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_inttypes_h)\n#define octave_oct_inttypes_h 1\n\n#include \"octave-config.h\"\n\n#include <cmath>\n#include <cstdlib>\n\n#include <iosfwd>\n#include <limits>\n#include <type_traits>\n\n#include \"mappers.h\"\n#include \"oct-inttypes-fwd.h\"\n\n#if defined (OCTAVE_INT_USE_LONG_DOUBLE)\n\nOCTAVE_BEGIN_NAMESPACE(octave)\nOCTAVE_BEGIN_NAMESPACE(math)\n\ninline long double round (long double x)\n{\n  return std::roundl (x);\n}\n\ninline long double isnan (long double x)\n{\n  return isnan (static_cast<double> (x));\n}\n\nOCTAVE_END_NAMESPACE(math)\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n\n// FIXME: we define this by our own because some compilers, such as\n// MSVC, do not provide std::abs (int64_t) and std::abs (uint64_t).  In\n// the future, it should go away in favor of std::abs.\n\ntemplate <typename T>\ninline T\noctave_int_abs (T x)\n{\n  return (x >= 0 ? x : -x);\n}\n\n// Query for an integer type of certain sizeof, and signedness.\n\ntemplate <int qsize, bool qsigned>\nstruct query_integer_type\n{\npublic:\n\n  static const bool registered = false;\n\n  // Void shall result in a compile-time error if we attempt to use it\n  // in computations.\n\n  typedef void type;\n};\n\n#define OCTAVE_REGISTER_INT_TYPE(TYPE)                                  \\\n  template <>                                                           \\\n  class query_integer_type<sizeof (TYPE),                               \\\n                           std::numeric_limits<TYPE>::is_signed>        \\\n  {                                                                     \\\n  public:                                                               \\\n                                                                        \\\n    static const bool registered = true;                                \\\n                                                                        \\\n    typedef TYPE type;                                                  \\\n  }\n\n// No two registered integers can share sizeof and signedness.\nOCTAVE_REGISTER_INT_TYPE (int8_t);\nOCTAVE_REGISTER_INT_TYPE (uint8_t);\nOCTAVE_REGISTER_INT_TYPE (int16_t);\nOCTAVE_REGISTER_INT_TYPE (uint16_t);\nOCTAVE_REGISTER_INT_TYPE (int32_t);\nOCTAVE_REGISTER_INT_TYPE (uint32_t);\nOCTAVE_REGISTER_INT_TYPE (int64_t);\nOCTAVE_REGISTER_INT_TYPE (uint64_t);\n\n#undef OCTAVE_REGISTER_INT_TYPE\n\n// Handles non-homogeneous integer comparisons.  Avoids doing useless tests.\n\nclass octave_int_cmp_op\n{\n  // This determines a suitable promotion type for T1 when meeting T2\n  // in a binary relation.  If promotion to int or T2 is safe, it is\n  // used.  Otherwise, the signedness of T1 is preserved and it is\n  // widened if T2 is wider.  Notice that if this is applied to both\n  // types, they must end up with equal size.\n\n  template <typename T1, typename T2>\n  class prom\n  {\n    // Promote to int?\n    static constexpr bool s_pint = (sizeof (T1) < sizeof (int)\n                                    && sizeof (T2) < sizeof (int));\n\n    static constexpr bool s_t1sig = std::numeric_limits<T1>::is_signed;\n    static constexpr bool s_t2sig = std::numeric_limits<T2>::is_signed;\n\n    static constexpr bool s_psig\n      = (s_pint || (sizeof (T2) > sizeof (T1) && s_t2sig) || s_t1sig);\n\n    static constexpr int s_psize\n      = (s_pint\n         ? sizeof (int)\n         : (sizeof (T2) > sizeof (T1) ? sizeof (T2) : sizeof (T1)));\n  public:\n\n    typedef typename query_integer_type<s_psize, s_psig>::type type;\n  };\n\n  // Implements comparisons between two types of equal size but\n  // possibly different signedness.\n\n  template <typename xop, int size>\n  class uiop\n  {\n    typedef typename query_integer_type<size, false>::type utype;\n    typedef typename query_integer_type<size, true>::type stype;\n\n  public:\n\n    static bool op (utype x, utype y)\n    {\n      return xop::op (x, y);\n    }\n\n    static bool op (stype x, stype y)\n    {\n      return xop::op (x, y);\n    }\n\n    static bool op (stype x, utype y)\n    {\n      return (x < 0) ? xop::ltval : xop::op (static_cast<utype> (x), y);\n    }\n\n    static bool op (utype x, stype y)\n    {\n      return (y < 0) ? xop::gtval : xop::op (x, static_cast<utype> (y));\n    }\n  };\n\npublic:\n\n  // Rationale: Comparators have a single static method, rel(), that\n  // returns the result of the binary relation.  They also have two\n  // static boolean fields: ltval, gtval determine the value of x OP y\n  // if x < y, x > y, respectively.\n\n#define OCTAVE_REGISTER_INT_CMP_OP(NM, OP)              \\\n  class NM                                              \\\n  {                                                     \\\n  public:                                               \\\n                                                        \\\n    static constexpr bool ltval = (0 OP 1);             \\\n    static constexpr bool gtval = (1 OP 0);             \\\n                                                        \\\n    template <typename T>                               \\\n    static bool op (T x, T y) { return x OP y; }        \\\n  }\n\n  OCTAVE_REGISTER_INT_CMP_OP (lt, <);\n  OCTAVE_REGISTER_INT_CMP_OP (le, <=);\n  OCTAVE_REGISTER_INT_CMP_OP (gt, >);\n  OCTAVE_REGISTER_INT_CMP_OP (ge, >=);\n  OCTAVE_REGISTER_INT_CMP_OP (eq, ==);\n  OCTAVE_REGISTER_INT_CMP_OP (ne, !=);\n\n#undef OCTAVE_REGISTER_INT_CMP_OP\n\n  // We also provide two special relations: ct, yielding always true,\n  // and cf, yielding always false.\n\n#define OCTAVE_REGISTER_INT_CONST_OP(NM, VALUE) \\\n  class NM                                      \\\n  {                                             \\\n  public:                                       \\\n                                                \\\n    static constexpr bool ltval = VALUE;        \\\n    static constexpr bool gtval = VALUE;        \\\n                                                \\\n    template <typename T>                       \\\n      static bool op (T, T) { return VALUE; }   \\\n  }\n\n  OCTAVE_REGISTER_INT_CONST_OP (ct, true);\n  OCTAVE_REGISTER_INT_CONST_OP (cf, false);\n\n#undef OCTAVE_REGISTER_INT_CONST_OP\n\n  // Universal comparison operation.\n\n  template <typename xop, typename T1, typename T2>\n  static bool\n  op (T1 x, T2 y)\n  {\n    typedef typename prom<T1, T2>::type PT1;\n    typedef typename prom<T2, T1>::type PT2;\n\n    return uiop<xop, sizeof (PT1)>::op (static_cast<PT1> (x),\n                                        static_cast<PT2> (y));\n  }\n\npublic:\n\n  // Mixed comparisons.\n\n  template <typename xop, typename T>\n  static bool mop (T x, double y)\n  {\n    return xop::op (static_cast<double> (x), y);\n  }\n\n  template <typename xop, typename T>\n  static bool mop (double x, T y)\n  {\n    return xop::op (x, static_cast<double> (y));\n  }\n\n#if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)\n\n#  define OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_CMP_OPS(T)    \\\n  template <typename xop>                                       \\\n  static OCTAVE_API bool external_mop (double, T);              \\\n                                                                \\\n  template <typename xop>                                       \\\n  static OCTAVE_API bool external_mop (T, double)\n\n  OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_CMP_OPS (int64_t);\n  OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_CMP_OPS (uint64_t);\n\n#endif\n\n  // Typecasting to doubles won't work properly for 64-bit integers --\n  // they lose precision.  If we have long doubles, use them...\n\n#if defined (OCTAVE_INT_USE_LONG_DOUBLE)\n\n#  if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)\n\n#    define OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP(T)     \\\n  template <typename xop>                               \\\n  static bool mop (double x, T y)                       \\\n  {                                                     \\\n    return external_mop<xop> (x, y);                    \\\n  }                                                     \\\n                                                        \\\n  template <typename xop>                               \\\n  static bool mop (T x, double y)                       \\\n  {                                                     \\\n    return external_mop<xop> (x, y);                    \\\n  }\n\n#  else\n\n#    define OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP(T)     \\\n  template <typename xop>                               \\\n  static bool mop (double x, T y)                       \\\n  {                                                     \\\n    return xop::op (static_cast<long double> (x),       \\\n                    static_cast<long double> (y));      \\\n  }                                                     \\\n                                                        \\\n  template <typename xop>                               \\\n  static bool mop (T x, double y)                       \\\n  {                                                     \\\n    return xop::op (static_cast<long double> (x),       \\\n                    static_cast<long double> (y));      \\\n  }\n\n#  endif\n\n#else\n\n  // ... otherwise, use external handlers\n\n  // FIXME: We could declare directly the mop methods as external, but\n  // we can't do this because bugs in gcc (<= 4.3) prevent explicit\n  // instantiations later in that case.\n\n#  define OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP(T)       \\\n  template <typename xop>                               \\\n  static OCTAVE_API bool emulate_mop (double, T);       \\\n                                                        \\\n  template <typename xop>                               \\\n  static bool mop (double x, T y)                       \\\n  {                                                     \\\n    return emulate_mop<xop> (x, y);                     \\\n  }                                                     \\\n                                                        \\\n  template <typename xop>                               \\\n  static OCTAVE_API bool emulate_mop (T, double);       \\\n                                                        \\\n  template <typename xop>                               \\\n  static bool mop (T x, double y)                       \\\n  {                                                     \\\n    return emulate_mop<xop> (x, y);                     \\\n  }\n\n#endif\n\n  OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP (int64_t)\n  OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP (uint64_t)\n\n#undef OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP\n};\n\n// Base integer class.  No data, just conversion methods and exception\n// flags.\n\ntemplate <typename T>\nclass octave_int_base\n{\npublic:\n\n  static T min_val () { return std::numeric_limits<T>::min (); }\n  static T max_val () { return std::numeric_limits<T>::max (); }\n\n  // Convert integer value.\n\n  template <typename S>\n  static T truncate_int (const S& value)\n  {\n    // An exhaustive test whether the max and/or min check can be\n    // omitted.\n\n    static constexpr bool t_is_signed = std::numeric_limits<T>::is_signed;\n    static constexpr bool s_is_signed = std::numeric_limits<S>::is_signed;\n\n    static constexpr int t_size = sizeof (T);\n    static constexpr int s_size = sizeof (S);\n\n    static constexpr bool omit_chk_min\n      = (! s_is_signed || (t_is_signed && t_size >= s_size));\n\n    static constexpr bool omit_chk_max\n      = (t_size > s_size\n         || (t_size == s_size && (! t_is_signed || s_is_signed)));\n\n    // If the check can be omitted, substitute constant false\n    // relation.\n\n    typedef octave_int_cmp_op::cf cf;\n    typedef octave_int_cmp_op::lt lt;\n    typedef octave_int_cmp_op::gt gt;\n    typedef typename std::conditional_t<omit_chk_min, cf, lt> chk_min;\n    typedef typename std::conditional_t<omit_chk_max, cf, gt> chk_max;\n\n    // Efficiency of the following depends on inlining and dead code\n    // elimination, but that should be a piece of cake for most\n    // compilers.\n\n    if (chk_min::op (value, static_cast<S> (min_val ())))\n      return min_val ();\n    else if (chk_max::op (value, static_cast<S> (max_val ())))\n      return max_val ();\n    else\n      return static_cast<T> (value);\n  }\n\nprivate:\n\n  // Compute a real-valued threshold for a max/min check.\n\n  template <typename S>\n  static S compute_threshold (S val, T orig_val)\n  {\n    // Fool optimizations (maybe redundant).\n\n    val = octave::math::round (val);\n\n    // If val is even, but orig_val is odd, we're one unit off.\n\n    if (orig_val % 2 && octave::math::is_integer (val / 2))\n      // FIXME: is this always correct?\n      val *= (static_cast<S> (1) - (std::numeric_limits<S>::epsilon () / 2));\n\n    return val;\n  }\n\npublic:\n\n  // Convert a real number (check NaN and non-int).\n\n  template <typename S>\n  static OCTAVE_API T convert_real (const S& value);\n};\n\n// Saturated (homogeneous) integer arithmetics.  The signed and\n// unsigned implementations are significantly different, so we\n// implement another layer and completely specialize.  Arithmetics\n// inherits from octave_int_base so that it can use its exceptions and\n// truncation functions.\n\ntemplate <typename T, bool is_signed>\nclass octave_int_arith_base\n{ };\n\n// Unsigned arithmetics.  C++ standard requires it to be modular, so\n// the overflows can be handled efficiently and reliably.\n\ntemplate <typename T>\nclass octave_int_arith_base<T, false> : octave_int_base<T>\n{\npublic:\n\n  static T abs (T x) { return x; }\n\n  static T signum (T x) { return x ? static_cast<T> (1) : static_cast<T> (0); }\n\n  // Shifts do not overflow.\n\n  static T rshift (T x, int n) { return x >> n; }\n\n  static T lshift (T x, int n) { return x << n; }\n\n  static T minus (T) { return static_cast<T> (0); }\n\n  // The overflow behavior for unsigned integers is guaranteed by\n  // C and C++, so the following should always work.\n\n  static T add (T x, T y)\n  {\n    T u = x + y;\n\n    if (u < x)\n      u = octave_int_base<T>::max_val ();\n\n    return u;\n  }\n\n  static T sub (T x, T y)\n  {\n    T u = x - y;\n\n    if (u > x)\n      u = 0;\n\n    return u;\n  }\n\n  // Multiplication is done using promotion to wider integer type.  If\n  // there is no suitable promotion type, this operation *MUST* be\n  // specialized.\n\n  static T mul (T x, T y) { return mul_internal (x, y); }\n\n  static T mul_internal (T x, T y)\n  {\n    // Promotion type for multiplication (if exists).\n\n    typedef typename query_integer_type<2* sizeof (T), false>::type mptype;\n\n    return octave_int_base<T>::truncate_int (static_cast<mptype> (x)\n           * static_cast<mptype> (y));\n  }\n\n  // Division with rounding to nearest.  Note that / and % are\n  // probably computed by a single instruction.\n\n  static T div (T x, T y)\n  {\n    if (y != 0)\n      {\n        T z = x / y;\n        T w = x % y;\n\n        if (w >= y-w)\n          z += 1;\n\n        return z;\n      }\n    else\n      return x ? octave_int_base<T>::max_val () : 0;\n  }\n\n  // Remainder.\n\n  static T rem (T x, T y) { return y != 0 ? x % y : 0; }\n\n  // Modulus.  Note the weird y = 0 case for Matlab compatibility.\n\n  static T mod (T x, T y) { return y != 0 ? x % y : x; }\n};\n\n#if defined (OCTAVE_INT_USE_LONG_DOUBLE)\n\n// Handle 64-bit multiply using long double.\n\n#  if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)\n\nextern OCTAVE_API uint64_t\noctave_external_uint64_uint64_mul (uint64_t, uint64_t);\n\n#  endif\n\ntemplate <>\ninline uint64_t\noctave_int_arith_base<uint64_t, false>::mul_internal (uint64_t x, uint64_t y)\n{\n  uint64_t retval;\n\n  long double p = static_cast<long double> (x) * static_cast<long double> (y);\n\n  if (p > static_cast<long double> (octave_int_base<uint64_t>::max_val ()))\n    retval = octave_int_base<uint64_t>::max_val ();\n  else\n    retval = static_cast<uint64_t> (p);\n\n  return retval;\n}\n\ntemplate <>\ninline uint64_t\noctave_int_arith_base<uint64_t, false>::mul (uint64_t x, uint64_t y)\n{\n#  if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)\n  return octave_external_uint64_uint64_mul (x, y);\n#  else\n  return mul_internal (x, y);\n#  endif\n}\n\n#else\n\n// Special handler for 64-bit integer multiply.\n\ntemplate <>\nOCTAVE_API uint64_t\noctave_int_arith_base<uint64_t, false>::mul_internal (uint64_t, uint64_t);\n\n#endif\n\ntemplate <typename T>\nclass octave_int_arith_base<T, true> : octave_int_base<T>\n{\n  // The corresponding unsigned type.\n  typedef typename query_integer_type<sizeof (T), false>::type UT;\n\npublic:\n\n  // Returns 1 for negative number, 0 otherwise.\n\n  static T __signbit (T x) { return (x < 0) ? 1 : 0; }\n\n  static T abs (T x)\n  {\n    // -INT_MAX is safe because C++ actually allows only three\n    // implementations of integers: sign & magnitude, ones complement\n    // and twos complement.  The first test will, with modest\n    // optimizations, evaluate at compile time, and maybe eliminate\n    // the branch completely.\n\n    return ((octave_int_base<T>::min_val () < -octave_int_base<T>::max_val ()\n             && x == octave_int_base<T>::min_val ())\n            ? octave_int_base<T>::max_val ()\n            : ((x < 0) ? -x : x));\n  }\n\n  static T signum (T x)\n  {\n    // With modest optimizations, this will compile without a jump.\n\n    return ((x > 0) ? 1 : 0) - __signbit (x);\n  }\n\n  // FIXME: we do not have an authority what signed shifts should\n  // exactly do, so we define them the easy way.  Note that Matlab\n  // does not define signed shifts.\n\n  static T rshift (T x, int n) { return x >> n; }\n\n  static T lshift (T x, int n) { return x << n; }\n\n  // Minus has problems similar to abs.\n\n  static T minus (T x)\n  {\n    return ((octave_int_base<T>::min_val () < -octave_int_base<T>::max_val ()\n             && x == octave_int_base<T>::min_val ())\n            ? octave_int_base<T>::max_val ()\n            : -x);\n  }\n\n  static T add (T x, T y)\n  {\n    // Avoid anything that may overflow.\n\n    return (y < 0\n            ? (x < octave_int_base<T>::min_val () - y\n               ? octave_int_base<T>::min_val ()\n               : x + y)\n            : (x > octave_int_base<T>::max_val () - y\n               ? octave_int_base<T>::max_val ()\n               : x + y));\n  }\n\n  static T sub (T x, T y)\n  {\n    // Avoid anything that may overflow.\n\n    return (y < 0\n            ? (x > octave_int_base<T>::max_val () + y\n               ? octave_int_base<T>::max_val ()\n               : x - y)\n            : (x < octave_int_base<T>::min_val () + y\n               ? octave_int_base<T>::min_val ()\n               : x - y));\n  }\n\n  // Multiplication is done using promotion to wider integer type.  If\n  // there is no suitable promotion type, this operation *MUST* be\n  // specialized.\n\n  static T mul (T x, T y) { return mul_internal (x, y); }\n\n  static T mul_internal (T x, T y)\n  {\n    // Promotion type for multiplication (if exists).\n\n    typedef typename query_integer_type<2* sizeof (T), true>::type mptype;\n\n    return octave_int_base<T>::truncate_int (static_cast<mptype> (x)\n           * static_cast<mptype> (y));\n  }\n\n  // Division.\n\n  static T div (T x, T y)\n  {\n    T z;\n\n    if (y == 0)\n      {\n        if (x < 0)\n          z = octave_int_base<T>::min_val ();\n        else if (x != 0)\n          z = octave_int_base<T>::max_val ();\n        else\n          z = 0;\n      }\n    else if (y < 0)\n      {\n        // This is a special case that overflows as well.\n        if (y == -1 && x == octave_int_base<T>::min_val ())\n          z = octave_int_base<T>::max_val ();\n        else\n          {\n            z = x / y;\n            // Can't overflow, but std::abs (x) can!\n            T w = -octave_int_abs (x % y);\n            if (w <= y - w)\n              z -= 1 - (__signbit (x) << 1);\n          }\n      }\n    else\n      {\n        z = x / y;\n\n        // FIXME: this is a workaround due to MSVC's absence of\n        // std::abs (int64_t).  The call to octave_int_abs can't\n        // overflow, but std::abs (x) can!\n        T w = octave_int_abs (x % y);\n\n        if (w >= y - w)\n          z += 1 - (__signbit (x) << 1);\n      }\n    return z;\n  }\n\n  // Remainder.\n\n  static T rem (T x, T y)\n  {\n    return y != 0 ? x % y : 0;\n  }\n\n  // Modulus.  Note the weird y = 0 case for Matlab compatibility.\n\n  static T mod (T x, T y)\n  {\n    if (y != 0)\n      {\n        T r = x % y;\n        return (r == 0) ? 0 : (((r < 0) != (y < 0)) ? r + y : r);\n      }\n    else\n      return x;\n  }\n};\n\n#if defined (OCTAVE_INT_USE_LONG_DOUBLE)\n\n// Handle 64-bit multiply using long double\n\n#  if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)\n\nextern OCTAVE_API int64_t\noctave_external_int64_int64_mul (int64_t, int64_t);\n\n#  endif\n\ntemplate <>\ninline int64_t\noctave_int_arith_base<int64_t, true>::mul_internal (int64_t x, int64_t y)\n{\n  int64_t retval;\n\n  long double p = static_cast<long double> (x) * static_cast<long double> (y);\n\n  if (p > static_cast<long double> (octave_int_base<int64_t>::max_val ()))\n    retval = octave_int_base<int64_t>::max_val ();\n  else if (p < static_cast<long double> (octave_int_base<int64_t>::min_val ()))\n    retval = octave_int_base<int64_t>::min_val ();\n  else\n    retval = static_cast<int64_t> (p);\n\n  return retval;\n}\n\ntemplate <>\ninline int64_t\noctave_int_arith_base<int64_t, true>::mul (int64_t x, int64_t y)\n{\n#  if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)\n  return octave_external_int64_int64_mul (x, y);\n#  else\n  return mul_internal (x, y);\n#  endif\n}\n\n#else\n\n// Special handler for 64-bit integer multiply.\n\ntemplate <>\nOCTAVE_API int64_t\noctave_int_arith_base<int64_t, true>::mul_internal (int64_t, int64_t);\n\n#endif\n\n// This class simply selects the proper arithmetics.\ntemplate <typename T>\nclass octave_int_arith\n  : public octave_int_arith_base<T, std::numeric_limits<T>::is_signed>\n{ };\n\ntemplate <typename T>\nclass OCTAVE_TEMPLATE_API octave_int : public octave_int_base<T>\n{\npublic:\n\n  typedef T val_type;\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int () : m_ival () { }\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int (T i) : m_ival (i) { }\n\n#if defined (OCTAVE_HAVE_OVERLOAD_CHAR_INT8_TYPES)\n\n  // Always treat characters as unsigned.\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int (char c)\n    : m_ival (octave_int_base<T>::truncate_int (static_cast<unsigned char> (c)))\n  { }\n\n#endif\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int (double d)\n    : m_ival (octave_int_base<T>::convert_real (d)) { }\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int (float d)\n    : m_ival (octave_int_base<T>::convert_real (d)) { }\n\n#if defined (OCTAVE_INT_USE_LONG_DOUBLE)\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int (long double d)\n    : m_ival (octave_int_base<T>::convert_real (d)) { }\n\n#endif\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int (bool b) : m_ival (b) { }\n\n  template <typename U>\n  OCTAVE_OVERRIDABLE_FUNC_API\n  octave_int (const U& i)\n    : m_ival(octave_int_base<T>::truncate_int (i)) { }\n\n  template <typename U>\n  OCTAVE_OVERRIDABLE_FUNC_API\n  octave_int (const octave_int<U>& i)\n    : m_ival (octave_int_base<T>::truncate_int (i.value ())) { }\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int (const octave_int<T>&) = default;\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int&\n  operator = (const octave_int<T>&) = default;\n\n  OCTAVE_OVERRIDABLE_FUNC_API ~octave_int () = default;\n\n  OCTAVE_OVERRIDABLE_FUNC_API T value () const { return m_ival; }\n\n  OCTAVE_OVERRIDABLE_FUNC_API const unsigned char * iptr () const\n  {\n    return reinterpret_cast<const unsigned char *> (& m_ival);\n  }\n\n  OCTAVE_OVERRIDABLE_FUNC_API bool operator ! () const { return ! m_ival; }\n\n  OCTAVE_OVERRIDABLE_FUNC_API bool bool_value () const\n  { return static_cast<bool> (value ()); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API char char_value () const\n  { return static_cast<char> (value ()); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API double double_value () const\n  { return static_cast<double> (value ()); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API float float_value () const\n  { return static_cast<float> (value ()); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API operator T () const { return value (); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int<T> operator + () const\n  { return *this; }\n\n  // unary operators & mappers\n#define OCTAVE_INT_UN_OP(OPNAME, NAME)          \\\n  inline octave_int<T>                          \\\n  OPNAME () const                               \\\n  {                                             \\\n    return octave_int_arith<T>::NAME (m_ival);  \\\n  }\n\n  OCTAVE_INT_UN_OP (operator -, minus)\n  OCTAVE_INT_UN_OP (abs, abs)\n  OCTAVE_INT_UN_OP (signum, signum)\n\n#undef OCTAVE_INT_UN_OP\n\n  OCTAVE_OVERRIDABLE_FUNC_API octave_int<T> operator ~ () const\n  {\n    T bitinv = ~ m_ival;\n    return bitinv;\n  }\n\n  // Homogeneous binary integer operations.\n#define OCTAVE_INT_BIN_OP(OP, NAME, ARGT)               \\\n  inline octave_int<T>                                  \\\n  operator OP (const ARGT& y) const                     \\\n  {                                                     \\\n    return octave_int_arith<T>::NAME (m_ival, y);       \\\n  }                                                     \\\n                                                        \\\n  inline octave_int<T>&                                 \\\n  operator OP##= (const ARGT& y)                        \\\n  {                                                     \\\n    m_ival = octave_int_arith<T>::NAME (m_ival, y);     \\\n    return *this;                                       \\\n  }\n\n  OCTAVE_INT_BIN_OP (+, add, octave_int<T>)\n  OCTAVE_INT_BIN_OP (-, sub, octave_int<T>)\n  OCTAVE_INT_BIN_OP (*, mul, octave_int<T>)\n  OCTAVE_INT_BIN_OP (/, div, octave_int<T>)\n  OCTAVE_INT_BIN_OP (%, rem, octave_int<T>)\n  OCTAVE_INT_BIN_OP (<<, lshift, int)\n  OCTAVE_INT_BIN_OP (>>, rshift, int)\n\n#undef OCTAVE_INT_BIN_OP\n\n  OCTAVE_OVERRIDABLE_FUNC_API static octave_int<T> min ()\n  { return std::numeric_limits<T>::min (); }\n  OCTAVE_OVERRIDABLE_FUNC_API static octave_int<T> max ()\n  { return std::numeric_limits<T>::max (); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API static int nbits ()\n  { return std::numeric_limits<T>::digits; }\n\n  OCTAVE_OVERRIDABLE_FUNC_API static int byte_size () { return sizeof (T); }\n\n  OCTAVE_OVERRIDABLE_FUNC_API static const OCTAVE_API char * type_name ();\n\n  // The following are provided for convenience.\n  static const octave_int s_zero, s_one;\n\nprivate:\n\n  T m_ival;\n};\n\ntemplate <typename T>\ninline octave_int<T>\nrem (const octave_int<T>& x, const octave_int<T>& y)\n{\n  return octave_int_arith<T>::rem (x.value (), y.value ());\n}\n\ntemplate <typename T>\ninline octave_int<T>\nmod (const octave_int<T>& x, const octave_int<T>& y)\n{\n  return octave_int_arith<T>::mod (x.value (), y.value ());\n}\n\n// FIXME: can/should any of these be inline?\n\ntemplate <typename T>\nextern OCTAVE_API octave_int<T>\npow (const octave_int<T>&, const octave_int<T>&);\n\ntemplate <typename T>\nextern OCTAVE_API octave_int<T>\npow (const double& a, const octave_int<T>& b);\n\ntemplate <typename T>\nextern OCTAVE_API octave_int<T>\npow (const octave_int<T>& a, const double& b);\n\ntemplate <typename T>\nextern OCTAVE_API octave_int<T>\npow (const float& a, const octave_int<T>& b);\n\ntemplate <typename T>\nextern OCTAVE_API octave_int<T>\npow (const octave_int<T>& a, const float& b);\n\n// FIXME: Do we really need a differently named single-precision\n//        function integer power function here instead of an overloaded\n//        one?\n\ntemplate <typename T>\nextern OCTAVE_API octave_int<T>\npowf (const float& a, const octave_int<T>& b);\n\ntemplate <typename T>\nextern OCTAVE_API octave_int<T>\npowf (const octave_int<T>& a, const float& b);\n\n// Binary relations\n\n#define OCTAVE_INT_CMP_OP(OP, NAME)                                     \\\n  template <typename T1, typename T2>                                   \\\n  inline bool                                                           \\\n  operator OP (const octave_int<T1>& x, const octave_int<T2>& y)        \\\n  {                                                                     \\\n    return octave_int_cmp_op::op<octave_int_cmp_op::NAME, T1, T2> (x.value (), y.value ()); \\\n  }\n\nOCTAVE_INT_CMP_OP (<, lt)\nOCTAVE_INT_CMP_OP (<=, le)\nOCTAVE_INT_CMP_OP (>, gt)\nOCTAVE_INT_CMP_OP (>=, ge)\nOCTAVE_INT_CMP_OP (==, eq)\nOCTAVE_INT_CMP_OP (!=, ne)\n\n#undef OCTAVE_INT_CMP_OP\n\ntemplate <typename T>\ninline std::ostream&\noperator << (std::ostream& os, const octave_int<T>& ival)\n{\n  os << ival.value ();\n  return os;\n}\n\ntemplate <typename T>\ninline std::istream&\noperator >> (std::istream& is, octave_int<T>& ival)\n{\n  T tmp = 0;\n  is >> tmp;\n  ival = tmp;\n  return is;\n}\n\n// We need to specialise for char and unsigned char because\n// std::operator<< and std::operator>> are overloaded to input and\n// output the ASCII character values instead of a representation of\n// their numerical value (e.g., os << char(10) outputs a space instead\n// of outputting the characters '1' and '0')\n\ntemplate <>\ninline std::ostream&\noperator << (std::ostream& os, const octave_int<int8_t>& ival)\n{\n  os << static_cast<int> (ival.value ());\n\n  return os;\n}\n\ntemplate <>\ninline std::ostream&\noperator << (std::ostream& os, const octave_int<uint8_t>& ival)\n{\n  os << static_cast<unsigned int> (ival.value ());\n\n  return os;\n}\n\ntemplate <>\ninline std::istream&\noperator >> (std::istream& is, octave_int<int8_t>& ival)\n{\n  int tmp = 0;\n  is >> tmp;\n  ival = static_cast<int8_t> (tmp);\n\n  return is;\n}\n\ntemplate <>\ninline std::istream&\noperator >> (std::istream& is, octave_int<uint8_t>& ival)\n{\n  unsigned int tmp = 0;\n  is >> tmp;\n  ival = static_cast<uint8_t> (tmp);\n\n  return is;\n}\n\n// Bitwise operations\n\n#define OCTAVE_INT_BITCMP_OP(OP)                                \\\n  template <typename T>                                         \\\n  octave_int<T>                                                 \\\n  operator OP (const octave_int<T>& x, const octave_int<T>& y)  \\\n  {                                                             \\\n    return x.value () OP y.value ();                            \\\n  }\n\nOCTAVE_INT_BITCMP_OP (&)\nOCTAVE_INT_BITCMP_OP (|)\nOCTAVE_INT_BITCMP_OP (^)\n\n#undef OCTAVE_INT_BITCMP_OP\n\n// General bit shift.\ntemplate <typename T>\noctave_int<T>\nbitshift (const octave_int<T>& a, int n,\n          const octave_int<T>& mask = std::numeric_limits<T>::max ())\n{\n  if (n > 0)\n    return (a << n) & mask;\n  else if (n < 0)\n    return (a >> -n) & mask;\n  else\n    return a & mask;\n}\n\n#if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)\n\n#  define OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP(T, OP)     \\\n  extern OCTAVE_API T                                           \\\n  external_double_ ## T ## _ ## OP (double x, T y);             \\\n                                                                \\\n  extern OCTAVE_API T                                           \\\n  external_ ## T ## _double_ ## OP (T x, double y)\n\n#  define OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS(T)        \\\n  OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, add);          \\\n  OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, sub);          \\\n  OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, mul);          \\\n  OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, div)\n\nOCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS (octave_int64);\nOCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS (octave_uint64);\n\n#endif\n\n#define OCTAVE_INT_DOUBLE_BIN_OP0(OP)                           \\\n  template <typename T>                                         \\\n  inline octave_int<T>                                          \\\n  operator OP (const octave_int<T>& x, const double& y)         \\\n  {                                                             \\\n    return octave_int<T> (static_cast<double> (x) OP y);        \\\n  }                                                             \\\n                                                                \\\n  template <typename T>                                         \\\n  inline octave_int<T>                                          \\\n  operator OP (const double& x, const octave_int<T>& y)         \\\n  {                                                             \\\n    return octave_int<T> (x OP static_cast<double> (y));        \\\n  }\n\n#if defined (OCTAVE_INT_USE_LONG_DOUBLE)\n\n// Handle mixed op using long double.\n\n#  if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)\n\n#    define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME)                  \\\n  OCTAVE_INT_DOUBLE_BIN_OP0(OP)                                 \\\n                                                                \\\n  template <>                                                   \\\n  inline octave_int64                                           \\\n  operator OP (const double& x, const octave_int64& y)          \\\n  {                                                             \\\n    return external_double_octave_int64_ ## NAME (x, y);        \\\n  }                                                             \\\n                                                                \\\n  template <>                                                   \\\n  inline octave_uint64                                          \\\n  operator OP (const double& x, const octave_uint64& y)         \\\n  {                                                             \\\n    return external_double_octave_uint64_ ## NAME (x, y);       \\\n  }                                                             \\\n                                                                \\\n  template <>                                                   \\\n  inline octave_int64                                           \\\n  operator OP (const octave_int64& x, const double& y)          \\\n  {                                                             \\\n    return external_octave_int64_double_ ## NAME (x, y);        \\\n  }                                                             \\\n                                                                \\\n  template <>                                                   \\\n  inline octave_uint64                                          \\\n  operator OP (const octave_uint64& x, const double& y)         \\\n  {                                                             \\\n    return external_octave_uint64_double_ ## NAME (x, y);       \\\n  }\n\n#  else\n\n#    define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME)                          \\\n  OCTAVE_INT_DOUBLE_BIN_OP0(OP)                                         \\\n                                                                        \\\n  template <>                                                           \\\n  inline octave_int64                                                   \\\n  operator OP (const double& x, const octave_int64& y)                  \\\n  {                                                                     \\\n    return octave_int64 (x OP static_cast<long double> (y.value ()));   \\\n  }                                                                     \\\n                                                                        \\\n  template <>                                                           \\\n  inline octave_uint64                                                  \\\n  operator OP (const double& x, const octave_uint64& y)                 \\\n  {                                                                     \\\n    return octave_uint64 (x OP static_cast<long double> (y.value ()));  \\\n  }                                                                     \\\n                                                                        \\\n  template <>                                                           \\\n  inline octave_int64                                                   \\\n  operator OP (const octave_int64& x, const double& y)                  \\\n  {                                                                     \\\n    return octave_int64 (static_cast<long double> (x.value ()) OP y);   \\\n  }                                                                     \\\n                                                                        \\\n  template <>                                                           \\\n  inline octave_uint64                                                  \\\n  operator OP (const octave_uint64& x, const double& y)                 \\\n  {                                                                     \\\n    return octave_uint64 (static_cast<long double> (x.value ()) OP y);  \\\n  }\n\n#  endif\n\n#else\n\n// External handlers.\n\n#  define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME)            \\\n  OCTAVE_INT_DOUBLE_BIN_OP0(OP)                         \\\n                                                        \\\n  template <>                                           \\\n  OCTAVE_API octave_int64                               \\\n  operator OP (const double&, const octave_int64&);     \\\n                                                        \\\n  template <>                                           \\\n  OCTAVE_API octave_uint64                              \\\n  operator OP (const double&, const octave_uint64&);    \\\n                                                        \\\n  template <>                                           \\\n  OCTAVE_API octave_int64                               \\\n  operator OP (const octave_int64&, const double&);     \\\n                                                        \\\n  template <>                                           \\\n  OCTAVE_API octave_uint64                              \\\n  operator OP (const octave_uint64&, const double&);\n\n#endif\n\nOCTAVE_INT_DOUBLE_BIN_OP (+, add)\nOCTAVE_INT_DOUBLE_BIN_OP (-, sub)\nOCTAVE_INT_DOUBLE_BIN_OP (*, mul)\nOCTAVE_INT_DOUBLE_BIN_OP (/, div)\n\n#undef OCTAVE_INT_DOUBLE_BIN_OP0\n#undef OCTAVE_INT_DOUBLE_BIN_OP\n#undef OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP\n#undef OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS\n\n#define OCTAVE_INT_DOUBLE_CMP_OP(OP, NAME)                              \\\n  template <typename T>                                                 \\\n  inline bool                                                           \\\n  operator OP (const octave_int<T>& x, const double& y)                 \\\n  {                                                                     \\\n    return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x.value (), y); \\\n  }                                                                     \\\n                                                                        \\\n  template <typename T>                                                 \\\n  inline bool                                                           \\\n  operator OP (const double& x, const octave_int<T>& y)                 \\\n  {                                                                     \\\n    return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x, y.value ()); \\\n  }\n\nOCTAVE_INT_DOUBLE_CMP_OP (<, lt)\nOCTAVE_INT_DOUBLE_CMP_OP (<=, le)\nOCTAVE_INT_DOUBLE_CMP_OP (>=, ge)\nOCTAVE_INT_DOUBLE_CMP_OP (>, gt)\nOCTAVE_INT_DOUBLE_CMP_OP (==, eq)\nOCTAVE_INT_DOUBLE_CMP_OP (!=, ne)\n\n#undef OCTAVE_INT_DOUBLE_CMP_OP\n\n// Floats are handled by simply converting to doubles.\n\n#define OCTAVE_INT_FLOAT_BIN_OP(OP)             \\\n  template <typename T>                         \\\n  inline octave_int<T>                          \\\n  operator OP (const octave_int<T>& x, float y) \\\n  {                                             \\\n    return x OP static_cast<double> (y);        \\\n  }                                             \\\n                                                \\\n  template <typename T>                         \\\n  inline octave_int<T>                          \\\n  operator OP (float x, const octave_int<T>& y) \\\n  {                                             \\\n    return static_cast<double> (x) OP y;        \\\n  }\n\nOCTAVE_INT_FLOAT_BIN_OP (+)\nOCTAVE_INT_FLOAT_BIN_OP (-)\nOCTAVE_INT_FLOAT_BIN_OP (*)\nOCTAVE_INT_FLOAT_BIN_OP (/)\n\n#undef OCTAVE_INT_FLOAT_BIN_OP\n\n#define OCTAVE_INT_FLOAT_CMP_OP(OP) \\\n  template <typename T>                                 \\\n  inline bool                                           \\\n  operator OP (const octave_int<T>& x, const float& y)  \\\n  {                                                     \\\n    return x OP static_cast<double> (y);                \\\n  }                                                     \\\n                                                        \\\n  template <typename T>                                 \\\n  bool                                                  \\\n  operator OP (const float& x, const octave_int<T>& y)  \\\n  {                                                     \\\n    return static_cast<double> (x) OP y;                \\\n  }\n\nOCTAVE_INT_FLOAT_CMP_OP (<)\nOCTAVE_INT_FLOAT_CMP_OP (<=)\nOCTAVE_INT_FLOAT_CMP_OP (>=)\nOCTAVE_INT_FLOAT_CMP_OP (>)\nOCTAVE_INT_FLOAT_CMP_OP (==)\nOCTAVE_INT_FLOAT_CMP_OP (!=)\n\n#undef OCTAVE_INT_FLOAT_CMP_OP\n\ntemplate <typename T>\noctave_int<T>\nxmax (const octave_int<T>& x, const octave_int<T>& y)\n{\n  const T xv = x.value ();\n  const T yv = y.value ();\n\n  return octave_int<T> (xv >= yv ? xv : yv);\n}\n\ntemplate <typename T>\noctave_int<T>\nxmin (const octave_int<T>& x, const octave_int<T>& y)\n{\n  const T xv = x.value ();\n  const T yv = y.value ();\n\n  return octave_int<T> (xv <= yv ? xv : yv);\n}\n\n// Ints are handled by converting to octave_int type.\n\n#define OCTAVE_INT_IDX_TYPE_BIN_OP(OP)                          \\\n  template <typename T>                                         \\\n  inline octave_int<T>                                          \\\n  operator OP (const octave_int<T>& x, octave_idx_type y)       \\\n  {                                                             \\\n    return x OP octave_int<T> (y);                              \\\n  }                                                             \\\n                                                                \\\n  template <typename T>                                         \\\n  inline octave_int<T>                                          \\\n  operator OP (octave_idx_type x, const octave_int<T>& y)       \\\n  {                                                             \\\n    return octave_int<T> (x) OP y;                              \\\n  }\n\nOCTAVE_INT_IDX_TYPE_BIN_OP (+)\nOCTAVE_INT_IDX_TYPE_BIN_OP (-)\nOCTAVE_INT_IDX_TYPE_BIN_OP (*)\nOCTAVE_INT_IDX_TYPE_BIN_OP (/)\n\n#undef OCTAVE_INT_IDX_TYPE_BIN_OP\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-locbuf.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_locbuf_h)\n#define octave_oct_locbuf_h 1\n\n#include \"octave-config.h\"\n\n#include <cstddef>\n\n#include <algorithm>\n#include <memory>\n\n#if __cplusplus >= 201402L\n\n#define OCTAVE_LOCAL_BUFFER(T, buf, size)                               \\\n  auto octave_local_buffer_ ## buf = std::make_unique<T []> (size);     \\\n  T *buf = octave_local_buffer_ ## buf.get ()\n\n#else\n\n#define OCTAVE_LOCAL_BUFFER(T, buf, size)                               \\\n  std::unique_ptr<T []> octave_local_buffer_ ## buf { new T [size] };   \\\n  T *buf = octave_local_buffer_ ## buf.get ()\n\n#endif\n\n#define OCTAVE_LOCAL_BUFFER_INIT(T, buf, size, value)                   \\\n  OCTAVE_LOCAL_BUFFER (T, buf, size);                                   \\\n  std::fill_n (buf, size, value)\n\n// The following two macros can be used in a pair if the scope of the buffer\n// should be larger than the scope in which the buffer is created.\n\n#define OCTAVE_SCOPED_BUFFER_ANCHOR(T, buf)                             \\\n  std::unique_ptr<T []> octave_local_buffer_ ## buf;                    \\\n  T *buf\n\n#if __cplusplus >= 201402L\n\n#define OCTAVE_SCOPED_BUFFER(T, buf, size)                              \\\n  octave_local_buffer_ ## buf = std::make_unique<T []> (size);          \\\n  buf = octave_local_buffer_ ## buf.get ()\n\n#else\n\n#define OCTAVE_SCOPED_BUFFER(T, buf, size)                              \\\n  octave_local_buffer_ ## buf = std::unique_ptr<T []> (new T [size]);   \\\n  buf = octave_local_buffer_ ## buf.get ()\n\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-mutex.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-error.h\"\n#include \"oct-mutex.h\"\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <windows.h>\n#elif defined (HAVE_PTHREAD_H)\n#  include <pthread.h>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\nbase_mutex::lock ()\n{\n  (*current_liboctave_error_handler) (\"mutex not supported on this platform\");\n}\n\nvoid\nbase_mutex::unlock ()\n{\n  (*current_liboctave_error_handler) (\"mutex not supported on this platform\");\n}\n\nbool\nbase_mutex::try_lock ()\n{\n  (*current_liboctave_error_handler) (\"mutex not supported on this platform\");\n\n  return false;\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\nclass w32_mutex : public base_mutex\n{\npublic:\n  w32_mutex ()\n    : base_mutex ()\n  {\n    InitializeCriticalSection (&cs);\n  }\n\n  ~w32_mutex ()\n  {\n    DeleteCriticalSection (&cs);\n  }\n\n  void lock ()\n  {\n    EnterCriticalSection (&cs);\n  }\n\n  void unlock ()\n  {\n    LeaveCriticalSection (&cs);\n  }\n\n  bool try_lock ()\n  {\n    return (TryEnterCriticalSection (&cs) != 0);\n  }\n\nprivate:\n  CRITICAL_SECTION cs;\n};\n\nstatic DWORD thread_id = 0;\n\nvoid\nthread::init ()\n{\n  thread_id = GetCurrentThreadId ();\n}\n\nbool\nthread::is_thread ()\n{\n  return (GetCurrentThreadId () == thread_id);\n}\n\n#elif defined (HAVE_PTHREAD_H)\n\nclass pthread_mutex : public base_mutex\n{\npublic:\n\n  pthread_mutex ()\n    : base_mutex (), m_pm ()\n  {\n    pthread_mutexattr_t attr;\n\n    pthread_mutexattr_init (&attr);\n    pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);\n    pthread_mutex_init (&m_pm, &attr);\n    pthread_mutexattr_destroy (&attr);\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (pthread_mutex)\n\n  ~pthread_mutex ()\n  {\n    pthread_mutex_destroy (&m_pm);\n  }\n\n  void lock ()\n  {\n    pthread_mutex_lock (&m_pm);\n  }\n\n  void unlock ()\n  {\n    pthread_mutex_unlock (&m_pm);\n  }\n\n  bool try_lock ()\n  {\n    return (pthread_mutex_trylock (&m_pm) == 0);\n  }\n\nprivate:\n  pthread_mutex_t m_pm;\n};\n\nstatic pthread_t thread_id = 0;\n\nvoid\nthread::init ()\n{\n  thread_id = pthread_self ();\n}\n\nbool\nthread::is_thread ()\n{\n  return (pthread_equal (thread_id, pthread_self ()) != 0);\n}\n\n#endif\n\nstatic base_mutex *\ninit_rep ()\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  return new w32_mutex ();\n#elif defined (HAVE_PTHREAD_H)\n  return new pthread_mutex ();\n#else\n  return new base_mutex ();\n#endif\n}\n\nmutex::mutex () : m_rep (init_rep ()) { }\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/oct-mutex.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_mutex_h)\n#define octave_oct_mutex_h 1\n\n#include \"octave-config.h\"\n\n#include <memory>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass mutex;\n\nclass OCTAVE_API base_mutex\n{\npublic:\n  friend class mutex;\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (base_mutex)\n\n  virtual ~base_mutex () = default;\n\n  virtual void lock ();\n\n  virtual void unlock ();\n\n  virtual bool try_lock ();\n};\n\nclass OCTAVE_API mutex\n{\npublic:\n  mutex ();\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (mutex)\n\n  void lock ()\n  {\n    m_rep->lock ();\n  }\n\n  void unlock ()\n  {\n    m_rep->unlock ();\n  }\n\n  bool try_lock ()\n  {\n    return m_rep->try_lock ();\n  }\n\nprotected:\n  std::shared_ptr<base_mutex> m_rep;\n};\n\nclass OCTAVE_API autolock\n{\npublic:\n  autolock (const mutex& m, bool block = true)\n    : m_mutex (m), m_lock_result (false)\n  {\n    if (block)\n      {\n        m_mutex.lock ();\n        m_lock_result = true;\n      }\n    else\n      m_lock_result = m_mutex.try_lock ();\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (autolock)\n\n  ~autolock ()\n  {\n    if (m_lock_result)\n      m_mutex.unlock ();\n  }\n\n  bool ok () const { return m_lock_result; }\n\n  operator bool () const { return ok (); }\n\nprivate:\n\n  mutex m_mutex;\n\n  bool m_lock_result;\n};\n\n\nclass OCTAVE_API thread\n{\npublic:\n\n  static void init ();\n\n  static bool is_thread ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-refcount.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_refcount_h)\n#define octave_oct_refcount_h 1\n\n#include \"octave-config.h\"\n\n#include <atomic>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Encapsulates a reference counter.\n\ntemplate <typename T>\nclass refcount\n{\npublic:\n\n  typedef T count_type;\n\n  refcount (count_type initial_count)\n    : m_count (initial_count)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (refcount)\n\n  ~refcount () = default;\n\n  // Increment/Decrement.  int is postfix.\n  count_type operator++ ()\n  {\n    return ++m_count;\n  }\n\n  count_type operator++ (int)\n  {\n    return m_count++;\n  }\n\n  count_type operator-- ()\n  {\n    return --m_count;\n  }\n\n  count_type operator-- (int)\n  {\n    return m_count--;\n  }\n\n  count_type value () const\n  {\n    return m_count.load ();\n  }\n\n  operator count_type () const\n  {\n    return value ();\n  }\n\nprivate:\n\n  std::atomic<T> m_count;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-regexp.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <list>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#if defined (HAVE_PCRE2)\n#  define PCRE2_CODE_UNIT_WIDTH 8\n#  if defined (HAVE_PCRE2_H)\n#    include <pcre2.h>\n#  elif defined (HAVE_PCRE2_PCRE2_H)\n#    include <pcre2/pcre2.h>\n#  endif\n#elif defined (HAVE_PCRE)\n#  if defined (HAVE_PCRE_H)\n#    include <pcre.h>\n#  elif defined (HAVE_PCRE_PCRE_H)\n#    include <pcre/pcre.h>\n#  endif\n#endif\n\n#include \"Matrix.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-regexp.h\"\n#include \"quit.h\"\n#include \"str-vec.h\"\n#include \"unistr-wrappers.h\"\n#include \"unwind-prot.h\"\n\n#if defined (HAVE_PCRE2)\ntypedef pcre2_code octave_pcre_code;\ntypedef PCRE2_SIZE OCTAVE_PCRE_SIZE;\nvoid (*octave_pcre_code_free) (octave_pcre_code *) = pcre2_code_free;\n#  define OCTAVE_PCRE_CASELESS PCRE2_CASELESS\n#  define OCTAVE_PCRE_DOTALL PCRE2_DOTALL\n#  define OCTAVE_PCRE_MULTILINE PCRE2_MULTILINE\n#  define OCTAVE_PCRE_EXTENDED PCRE2_EXTENDED\n#  define OCTAVE_PCRE_UTF PCRE2_UTF\n#  define OCTAVE_PCRE_INFO_CAPTURECOUNT PCRE2_INFO_CAPTURECOUNT\n#  define OCTAVE_PCRE_INFO_NAMECOUNT PCRE2_INFO_NAMECOUNT\n#  define OCTAVE_PCRE_INFO_NAMEENTRYSIZE PCRE2_INFO_NAMEENTRYSIZE\n#  define OCTAVE_PCRE_INFO_NAMETABLE PCRE2_INFO_NAMETABLE\n#elif defined (HAVE_PCRE)\ntypedef pcre octave_pcre_code;\ntypedef int OCTAVE_PCRE_SIZE;\nvoid (*octave_pcre_code_free) (void *) = pcre_free;\n#  define OCTAVE_PCRE_CASELESS PCRE_CASELESS\n#  define OCTAVE_PCRE_DOTALL PCRE_DOTALL\n#  define OCTAVE_PCRE_MULTILINE PCRE_MULTILINE\n#  define OCTAVE_PCRE_EXTENDED PCRE_EXTENDED\n#  define OCTAVE_PCRE_UTF PCRE_UTF8\n#  define OCTAVE_PCRE_INFO_CAPTURECOUNT PCRE_INFO_CAPTURECOUNT\n#  define OCTAVE_PCRE_INFO_NAMECOUNT PCRE_INFO_NAMECOUNT\n#  define OCTAVE_PCRE_INFO_NAMEENTRYSIZE PCRE_INFO_NAMEENTRYSIZE\n#  define OCTAVE_PCRE_INFO_NAMETABLE PCRE_INFO_NAMETABLE\n#else\n#  error \"PCRE2 or PCRE library is required to build Octave\"\n#endif\n\nstatic inline int\noctave_pcre_pattern_info (const octave_pcre_code *code, int what, void *where)\n{\n#if defined (HAVE_PCRE2)\n  return pcre2_pattern_info (code, what, where);\n#else\n  return pcre_fullinfo (code, nullptr, what, where);\n#endif\n}\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n// Define the maximum number of retries for a pattern\n// that possibly results in an infinite recursion.\n#define PCRE_MATCHLIMIT_MAX 10\n\n// FIXME: should this be configurable?\n#define MAXLOOKBEHIND 10\n\nstatic bool lookbehind_warned = false;\n\n// FIXME: don't bother collecting and composing return values\n//        the user doesn't want.\n\nvoid\nregexp::free ()\n{\n  octave_pcre_code_free (static_cast<octave_pcre_code *> (m_code));\n}\n\nvoid\nregexp::compile_internal ()\n{\n  // If we had a previously compiled pattern, release it.\n  free ();\n\n  std::size_t max_length = MAXLOOKBEHIND;\n\n  std::size_t pos = 0;\n  std::size_t new_pos;\n  int inames = 0;\n  std::ostringstream buf;\n\n  while ((new_pos = m_pattern.find (\"(?\", pos)) != std::string::npos)\n    {\n      std::size_t tmp_pos;\n      if (m_pattern.size () > new_pos + 2\n          && m_pattern.at (new_pos + 2) == '<'\n          && ! (m_pattern.size () > new_pos + 3\n                && (m_pattern.at (new_pos + 3) == '='\n                    || m_pattern.at (new_pos + 3) == '!'))\n          && (tmp_pos = m_pattern.find_first_of ('>', new_pos))\n          != std::string::npos\n          && m_pattern.find_first_of (')', tmp_pos) != std::string::npos)\n        {\n          // The syntax of named tokens in pcre is \"(?P<name>...)\" while\n          // we need a syntax \"(?<name>...)\", so fix that here.  Also an\n          // expression like\n          // \"(?<first>\\w+)\\s+(?<last>\\w+)|(?<last>\\w+),\\s+(?<first>\\w+)\"\n          // should be perfectly legal, while pcre does not allow the same\n          // named token name on both sides of the alternative.  Also fix\n          // that here by replacing name tokens by dummy names, and dealing\n          // with the dummy names later.\n\n          std::string tmp_name\n            = m_pattern.substr (new_pos+3, tmp_pos-new_pos-3);\n\n          bool found = false;\n\n          for (int i = 0; i < m_names; i++)\n            {\n              if (m_named_pats(i) == tmp_name)\n                {\n                  m_named_idx.resize (dim_vector (inames+1, 1));\n                  m_named_idx(inames) = i;\n                  found = true;\n                  break;\n                }\n            }\n\n          if (! found)\n            {\n              m_named_idx.resize (dim_vector (inames+1, 1));\n              m_named_idx(inames) = m_names;\n              m_named_pats.append (tmp_name);\n              m_names++;\n            }\n\n          if (new_pos > pos)\n            buf << m_pattern.substr (pos, new_pos-pos);\n          if (inames < 10)\n            buf << \"(?P<n00\" << inames++;\n          else if (inames < 100)\n            buf << \"(?P<n0\" << inames++;\n          else\n            buf << \"(?P<n\" << inames++;\n\n          pos = tmp_pos;\n        }\n      else if (m_pattern.size () > new_pos + 2\n               && m_pattern.at (new_pos + 2) == '<')\n        {\n          // Find lookbehind operators of arbitrary length (ie like\n          // \"(?<=[a-z]*)\") and replace with a maximum length operator\n          // as PCRE can not yet handle arbitrary length lookahead\n          // operators.  Use the string length as the maximum length to\n          // avoid issues.\n\n          int brackets = 1;\n          std::size_t tmp_pos1 = new_pos + 2;\n          std::size_t tmp_pos2 = tmp_pos1;\n\n          while (tmp_pos1 < m_pattern.length () && brackets > 0)\n            {\n              char ch = m_pattern.at (tmp_pos1);\n\n              if (ch == '(')\n                brackets++;\n              else if (ch == ')')\n                {\n                  if (brackets > 1)\n                    tmp_pos2 = tmp_pos1;\n\n                  brackets--;\n                }\n\n              tmp_pos1++;\n            }\n\n          if (brackets != 0)\n            {\n              buf << m_pattern.substr (pos, new_pos - pos) << \"(?\";\n              pos = new_pos + 2;\n            }\n          else\n            {\n              std::size_t tmp_pos3 = m_pattern.find_first_of (\"*+\", tmp_pos2);\n\n              if (tmp_pos3 != std::string::npos && tmp_pos3 < tmp_pos1)\n                {\n                  if (! lookbehind_warned)\n                    {\n                      lookbehind_warned = true;\n                      (*current_liboctave_warning_with_id_handler)\n                        (\"Octave:regexp-lookbehind-limit\",\n                         \"%s: arbitrary length lookbehind patterns are only supported up to length %d\",\n                         m_who.c_str (), MAXLOOKBEHIND);\n                    }\n\n                  buf << m_pattern.substr (pos, new_pos - pos) << '(';\n\n                  std::size_t i;\n\n                  if (m_pattern.at (tmp_pos3) == '*')\n                    i = 0;\n                  else\n                    i = 1;\n\n                  for (; i < max_length + 1; i++)\n                    {\n                      buf << m_pattern.substr (new_pos, tmp_pos3 - new_pos)\n                          << '{' << i << '}';\n                      buf << m_pattern.substr (tmp_pos3 + 1,\n                                               tmp_pos1 - tmp_pos3 - 1);\n                      if (i != max_length)\n                        buf << '|';\n                    }\n                  buf << ')';\n                }\n              else\n                buf << m_pattern.substr (pos, tmp_pos1 - pos);\n\n              pos = tmp_pos1;\n            }\n        }\n      else\n        {\n          buf << m_pattern.substr (pos, new_pos - pos) << \"(?\";\n          pos = new_pos + 2;\n        }\n\n    }\n\n  buf << m_pattern.substr (pos);\n\n  // Replace NULLs with escape sequence because conversion function c_str()\n  // will terminate string early at embedded NULLs.\n  std::string buf_str = buf.str ();\n  while ((pos = buf_str.find ('\\0')) != std::string::npos)\n    buf_str.replace (pos, 1, \"\\\\000\");\n\n  int pcre_options\n    = (  (m_options.case_insensitive () ? OCTAVE_PCRE_CASELESS : 0)\n         | (m_options.dotexceptnewline () ? 0 : OCTAVE_PCRE_DOTALL)\n         | (m_options.lineanchors () ? OCTAVE_PCRE_MULTILINE : 0)\n         | (m_options.freespacing () ? OCTAVE_PCRE_EXTENDED : 0)\n         | OCTAVE_PCRE_UTF);\n\n#if defined (HAVE_PCRE2)\n  PCRE2_SIZE erroffset;\n  int errnumber;\n\n  m_code = pcre2_compile (reinterpret_cast<PCRE2_SPTR> (buf_str.c_str ()),\n                          PCRE2_ZERO_TERMINATED, pcre_options,\n                          &errnumber, &erroffset, nullptr);\n\n  if (! m_code)\n    {\n      // PCRE docs say:\n      //\n      //   If the buffer is too small, the message is truncated (but\n      //   still with a trailing zero), and the negative error code\n      //   PCRE2_ERROR_NOMEMORY is returned.  None of the messages are\n      //   very long; a buffer size of 120 code units is ample.\n      //\n      // so we assume that 256 will be large enough to avoid truncated\n      // messages.\n\n      PCRE2_UCHAR err [256];\n      pcre2_get_error_message (errnumber, err, sizeof (err));\n      (*current_liboctave_error_handler)\n        (\"%s: %s at position %zu of expression\", m_who.c_str (), err,\n         erroffset);\n    }\n#else\n  const char *err;\n  int erroffset;\n\n  m_code = pcre_compile (buf_str.c_str (), pcre_options,\n                         &err, &erroffset, nullptr);\n\n  if (! m_code)\n    (*current_liboctave_error_handler)\n      (\"%s: %s at position %d of expression\", m_who.c_str (), err, erroffset);\n#endif\n}\n\nregexp::match_data\nregexp::match (const std::string& buffer) const\n{\n  // check if input is valid utf-8\n  const uint8_t *buf_str = reinterpret_cast<const uint8_t *> (buffer.c_str ());\n  if (octave_u8_check_wrapper (buf_str, buffer.length ()))\n    (*current_liboctave_error_handler)\n      (\"%s: the input string is invalid UTF-8\", m_who.c_str ());\n\n  regexp::match_data retval;\n\n  std::list<regexp::match_element> lst;\n\n  int subpatterns;\n  int namecount;\n  int nameentrysize;\n  char *nametable;\n  std::size_t idx = 0;\n\n  octave_pcre_code *re = static_cast<octave_pcre_code *> (m_code);\n\n  octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_CAPTURECOUNT, &subpatterns);\n  octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_NAMECOUNT, &namecount);\n  octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_NAMEENTRYSIZE, &nameentrysize);\n  octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_NAMETABLE, &nametable);\n\n#if defined (HAVE_PCRE)\n  OCTAVE_LOCAL_BUFFER (OCTAVE_PCRE_SIZE, ovector, (subpatterns+1)*3);\n#endif\n\n  OCTAVE_LOCAL_BUFFER (int, nidx, namecount);\n\n  for (int i = 0; i < namecount; i++)\n    {\n      // Index of subpattern in first two bytes of name (MSB first).\n      // Extract index.\n      nidx[i] = (static_cast<int> (nametable[i*nameentrysize])) << 8\n                | static_cast<int> (nametable[i*nameentrysize+1]);\n    }\n\n  while (true)\n    {\n      octave_quit ();\n\n#if defined (HAVE_PCRE2)\n      pcre2_match_data *tmp_match_data\n        = pcre2_match_data_create_from_pattern (re, nullptr);\n\n      unwind_action cleanup_match_data ([tmp_match_data] () { pcre2_match_data_free (tmp_match_data); });\n\n      int matches = pcre2_match (re, reinterpret_cast<PCRE2_SPTR> (buffer.c_str ()),\n                                 buffer.length (), idx,\n                                 PCRE2_NO_UTF_CHECK | (idx ? PCRE2_NOTBOL : 0),\n                                 tmp_match_data, nullptr);\n\n      if (matches < 0 && matches != PCRE2_ERROR_NOMATCH)\n        (*current_liboctave_error_handler)\n          (\"%s: internal error calling pcre2_match; \"\n           \"error code from pcre2_match is %i\", m_who.c_str (), matches);\n\n      if (matches == PCRE2_ERROR_NOMATCH)\n        break;\n\n      OCTAVE_PCRE_SIZE *ovector = pcre2_get_ovector_pointer (tmp_match_data);\n#else\n      int matches = pcre_exec (re, nullptr, buffer.c_str (),\n                               buffer.length (), idx,\n                               PCRE_NO_UTF8_CHECK | (idx ? PCRE_NOTBOL : 0),\n                               ovector, (subpatterns+1)*3);\n\n      if (matches == PCRE_ERROR_MATCHLIMIT)\n        {\n          // Try harder; start with default value for MATCH_LIMIT\n          // and increase it.\n          (*current_liboctave_warning_with_id_handler)\n            (\"Octave:regexp-match-limit\",\n             \"your pattern caused PCRE to hit its MATCH_LIMIT; trying harder now, but this will be slow\");\n\n          pcre_extra pe;\n\n          pcre_config (PCRE_CONFIG_MATCH_LIMIT,\n                       static_cast<void *> (&pe.match_limit));\n\n          pe.flags = PCRE_EXTRA_MATCH_LIMIT;\n\n          int i = 0;\n          while (matches == PCRE_ERROR_MATCHLIMIT\n                 && i++ < PCRE_MATCHLIMIT_MAX)\n            {\n              octave_quit ();\n\n              pe.match_limit *= 10;\n              matches = pcre_exec (re, &pe, buffer.c_str (),\n                                   buffer.length (), idx,\n                                   PCRE_NO_UTF8_CHECK\n                                   | (idx ? PCRE_NOTBOL : 0),\n                                   ovector, (subpatterns+1)*3);\n            }\n        }\n\n      if (matches < 0 && matches != PCRE_ERROR_NOMATCH)\n        (*current_liboctave_error_handler)\n          (\"%s: internal error calling pcre_exec; \"\n           \"error code from pcre_exec is %i\", m_who.c_str (), matches);\n\n      if (matches == PCRE_ERROR_NOMATCH)\n        break;\n#endif\n      if (ovector[0] >= ovector[1] && ! m_options.emptymatch ())\n        {\n          // Zero length match.  Skip to next char.\n          idx = ovector[0] + 1;\n          if (idx < buffer.length ())\n            continue;\n          else\n            break;\n        }\n      else\n        {\n          int pos_match = 0;\n          Matrix token_extents (matches-1, 2);\n\n          for (int i = 1; i < matches; i++)\n            {\n#if defined (HAVE_PCRE2)\n              if (ovector[2*i] != PCRE2_SIZE_MAX\n#else\n              if (ovector[2*i] >= 0\n#endif\n                  && ovector[2*i+1] > 0\n                  && (i == 1 || ovector[2*i] != ovector[2*i-2]\n                      || ovector[2*i-1] != ovector[2*i+1]))\n                {\n                  token_extents(pos_match, 0) = double (ovector[2*i]+1);\n                  token_extents(pos_match++, 1) = double (ovector[2*i+1]);\n                }\n            }\n\n          token_extents.resize (pos_match, 2);\n\n          OCTAVE_PCRE_SIZE start = ovector[0] + 1;\n          OCTAVE_PCRE_SIZE end = ovector[1];\n\n#if defined (HAVE_PCRE2)\n          // Must use explicit length constructor as match can contain '\\0'.\n          std::string match_string = std::string (buffer.c_str() + start - 1,\n                                                  end - start + 1);\n#else\n          const char **listptr;\n          int status = pcre_get_substring_list (buffer.c_str (), ovector,\n                                                matches, &listptr);\n\n          if (status == PCRE_ERROR_NOMEMORY)\n            (*current_liboctave_error_handler)\n              (\"%s: cannot allocate memory in pcre_get_substring_list\",\n               m_who.c_str ());\n\n          // Must use explicit length constructor as match can contain '\\0'.\n          std::string match_string = std::string (*listptr, end - start + 1);\n#endif\n\n          string_vector tokens (pos_match);\n          string_vector named_tokens (m_names);\n#if ! defined (HAVE_PCRE2)\n          int pos_offset = 0;\n#endif\n          pos_match = 0;\n\n          for (int i = 1; i < matches; i++)\n            {\n#if defined (HAVE_PCRE2)\n              if (ovector[2*i] != PCRE2_SIZE_MAX\n#else\n              if (ovector[2*i] >= 0\n#endif\n                  && ovector[2*i+1] > 0)\n                {\n                  if (i == 1 || ovector[2*i] != ovector[2*i-2]\n                      || ovector[2*i-1] != ovector[2*i+1])\n                    {\n                      if (namecount > 0)\n                        {\n                          // FIXME: Should probably do this with a map()\n                          //        rather than a linear search.  However,\n                          //        the number of captured, named expressions\n                          //        is usually pretty small (< 4)\n                          for (int j = 0; j < namecount; j++)\n                            {\n                              if (nidx[j] == i)\n                                {\n                                  std::size_t len = ovector[2*i+1] - ovector[2*i];\n                                  named_tokens(m_named_idx(j))\n#if defined (HAVE_PCRE2)\n                                    = std::string (buffer.c_str () + ovector[2*i], len);\n#else\n                                    = std::string (*(listptr+i-pos_offset), len);\n#endif\n                                  break;\n                                }\n                            }\n                        }\n\n                      std::size_t len = ovector[2*i+1] - ovector[2*i];\n#if defined (HAVE_PCRE2)\n                      tokens(pos_match++) = std::string (buffer.c_str() + ovector[2*i], len);\n#else\n                      tokens(pos_match++) = std::string (*(listptr+i), len);\n#endif\n                    }\n#if ! defined (HAVE_PCRE2)\n                  else\n                    pos_offset++;\n#endif\n                }\n            }\n\n#if ! defined (HAVE_PCRE2)\n          pcre_free_substring_list (listptr);\n#endif\n\n          // FIXME: MATCH_ELEMENT uses double values for these,\n          // presumably because that is what the Octave interpreter\n          // uses.  Should we check that the values don't exceed\n          // flintmax here?  It seems unlikely that it would happen,\n          // but...\n\n          double dstart = static_cast<double> (start);\n          double dend = static_cast<double> (end);\n\n          regexp::match_element new_elem (named_tokens, tokens, match_string,\n                                          token_extents,\n                                          dstart, dend);\n\n          lst.push_back (new_elem);\n\n          if (ovector[1] <= ovector[0])\n            {\n              // Zero length match.  Skip to next char.\n              idx = ovector[0] + 1;\n              if (idx <= buffer.length ())\n                continue;\n            }\n          else\n            idx = ovector[1];\n\n          if (m_options.once () || idx >= buffer.length ())\n            break;\n        }\n    }\n\n  retval = regexp::match_data (lst, m_named_pats);\n\n  return retval;\n}\n\nbool\nregexp::is_match (const std::string& buffer) const\n{\n  regexp::match_data rx_lst = match (buffer);\n\n  return rx_lst.size () > 0;\n}\n\nArray<bool>\nregexp::is_match (const string_vector& buffer) const\n{\n  octave_idx_type len = buffer.numel ();\n\n  Array<bool> retval (dim_vector (len, 1));\n\n  for (octave_idx_type i = 0; i < buffer.numel (); i++)\n    retval(i) = is_match (buffer(i));\n\n  return retval;\n}\n\n// Declare rep_token_t used in processing replacement string\nstruct rep_token_t\n{\n  std::size_t pos;\n  int num;\n};\n\nstd::string\nregexp::replace (const std::string& buffer,\n                 const std::string& replacement) const\n{\n  std::string retval;\n\n  const regexp::match_data rx_lst = match (buffer);\n\n  std::size_t num_matches = rx_lst.size ();\n\n  if (num_matches == 0)\n    {\n      retval = buffer;\n      return retval;\n    }\n\n  // Identify replacement tokens; build a vector of group numbers in\n  // the replacement string so that we can quickly calculate the size\n  // of the replacement.\n\n  // FIXME: All code assumes that only 10 tokens ($0-$9) exist.\n  //        $11 represents $1 followed by the character '1' rather than\n  //        the eleventh capture buffer.\n\n  std::string repstr = replacement;\n  std::vector<rep_token_t> tokens;\n  tokens.reserve (5);  // Reserve memory for 5 pattern replacements\n\n  for (std::size_t i=0; i < repstr.size (); i++)\n    {\n      if (repstr[i] == '\\\\')\n        {\n          if (i < repstr.size () - 1 && repstr[i+1] == '$')\n            {\n              repstr.erase (i, 1); // erase backslash\n              i++;                 // skip over '$'\n              continue;\n            }\n          if (i < repstr.size () - 1 && repstr[i+1] == '\\\\')\n            {\n              repstr.erase (i, 1); // erase 1st backslash\n              continue;\n            }\n        }\n      else if (repstr[i] == '$')\n        {\n          if (i < repstr.size () - 1 && isdigit (repstr[i+1]))\n            {\n              rep_token_t tmp_token;\n\n              tmp_token.pos = i;\n              tmp_token.num = repstr[i+1]-'0';\n              tokens.push_back (tmp_token);\n            }\n        }\n    }\n\n  std::string rep;\n  int num_tokens = tokens.size ();\n\n  if (num_tokens > 0)\n    {\n      // Determine replacement length\n      const std::size_t replen = repstr.size () - 2*num_tokens;\n      int delta = 0;\n      auto p = rx_lst.begin ();\n      for (std::size_t i = 0; i < num_matches; i++)\n        {\n          octave_quit ();\n\n          double start = p->start ();\n          double end = p->end ();\n\n          const Matrix pairs (p->token_extents ());\n          std::size_t pairlen = 0;\n          for (int j = 0; j < num_tokens; j++)\n            {\n              if (tokens[j].num == 0)\n                pairlen += static_cast<std::size_t> (end - start + 1);\n              else if (tokens[j].num <= pairs.rows ())\n                pairlen += static_cast<std::size_t> (pairs(tokens[j].num-1, 1)\n                                                     - pairs(tokens[j].num-1, 0)\n                                                     + 1);\n            }\n          delta += (static_cast<int> (replen + pairlen)\n                    - static_cast<int> (end - start + 1));\n          p++;\n        }\n\n      // Build replacement string\n      rep.reserve (buffer.size () + delta);\n      std::size_t from = 0;\n      p = rx_lst.begin ();\n      for (std::size_t i = 0; i < num_matches; i++)\n        {\n          octave_quit ();\n\n          double start = p->start ();\n          double end = p->end ();\n\n          const Matrix pairs (p->token_extents ());\n          rep.append (&buffer[from], static_cast<std::size_t> (start - 1 - from));\n          from = static_cast<std::size_t> (end);\n\n          std::size_t cur_pos = 0;\n\n          for (int j = 0; j < num_tokens; j++)\n            {\n              rep.append (&repstr[cur_pos], (tokens[j].pos) - cur_pos);\n              cur_pos = tokens[j].pos+2;\n\n              int k = tokens[j].num;\n              if (k == 0)\n                {\n                  // replace with entire match\n                  rep.append (&buffer[static_cast<std::size_t> (end - 1)],\n                              static_cast<std::size_t> (end - start + 1));\n                }\n              else if (k <= pairs.rows ())\n                {\n                  // replace with group capture\n                  rep.append (&buffer[static_cast<std::size_t> (pairs(k-1, 0)-1)],\n                              static_cast<std::size_t> (pairs(k-1, 1)\n                                                        - pairs(k-1, 0) + 1));\n                }\n              else\n                {\n                  // replace with nothing\n                }\n            }\n          if (cur_pos < repstr.size ())\n            rep.append (&repstr[cur_pos], repstr.size () - cur_pos);\n\n          p++;\n        }\n      rep.append (&buffer[from], buffer.size () - from);\n    }\n  else\n    {\n      // Determine repstr length\n      const std::size_t replen = repstr.size ();\n      int delta = 0;\n      auto p = rx_lst.begin ();\n      for (std::size_t i = 0; i < num_matches; i++)\n        {\n          octave_quit ();\n\n          delta += static_cast<int> (replen)\n                   - static_cast<int> (p->end () - p->start () + 1);\n          p++;\n        }\n\n      // Build replacement string\n      rep.reserve (buffer.size () + delta);\n      std::size_t from = 0;\n      p = rx_lst.begin ();\n      for (std::size_t i = 0; i < num_matches; i++)\n        {\n          octave_quit ();\n\n          rep.append (&buffer[from],\n                      static_cast<std::size_t> (p->start () - 1 - from));\n          from = static_cast<std::size_t> (p->end ());\n          rep.append (repstr);\n          p++;\n        }\n      rep.append (&buffer[from], buffer.size () - from);\n    }\n\n  retval = rep;\n  return retval;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/oct-regexp.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_regexp_h)\n#define octave_oct_regexp_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <sstream>\n#include <string>\n\n#include \"Array-oct.h\"\n#include \"Matrix.h\"\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTAVE_API regexp\n{\npublic:\n\n  class opts;\n  class match_data;\n\n  regexp (const std::string& pat = \"\",\n          const regexp::opts& opt = regexp::opts (),\n          const std::string& w = \"regexp\")\n    : m_pattern (pat), m_options (opt), m_code (nullptr), m_named_pats (),\n      m_names (0), m_named_idx (), m_who (w)\n  {\n    compile_internal ();\n  }\n\n  regexp (const regexp&) = default;\n\n  regexp& operator = (const regexp& rx) = default;\n\n  ~regexp () { free (); }\n\n  void compile (const std::string& pat,\n                const regexp::opts& opt = regexp::opts ())\n  {\n    m_pattern = pat;\n    m_options = opt;\n    compile_internal ();\n  }\n\n  match_data match (const std::string& buffer) const;\n\n  bool is_match (const std::string& buffer) const;\n\n  Array<bool> is_match (const string_vector& buffer) const;\n\n  std::string replace (const std::string& buffer,\n                       const std::string& replacement) const;\n\n  static match_data\n  match (const std::string& pat, const std::string& buffer,\n         const regexp::opts& opt = regexp::opts (),\n         const std::string& who = \"regexp\")\n  {\n    regexp rx (pat, opt, who);\n\n    return rx.match (buffer);\n  }\n\n  static bool\n  is_match (const std::string& pat, const std::string& buffer,\n            const regexp::opts& opt = regexp::opts (),\n            const std::string& who = \"regexp\")\n  {\n    regexp rx (pat, opt, who);\n\n    return rx.is_match (buffer);\n  }\n\n  static Array<bool>\n  is_match (const std::string& pat, const string_vector& buffer,\n            const regexp::opts& opt = regexp::opts (),\n            const std::string& who = \"regexp\")\n  {\n    regexp rx (pat, opt, who);\n\n    return rx.is_match (buffer);\n  }\n\n  static std::string\n  replace (const std::string& pat, const std::string& buffer,\n           const std::string& replacement,\n           const regexp::opts& opt = regexp::opts (),\n           const std::string& who = \"regexp\")\n  {\n    regexp rx (pat, opt, who);\n\n    return rx.replace (buffer, replacement);\n  }\n\n  class opts\n  {\n  public:\n\n    opts ()\n      : m_case_insensitive (false), m_dotexceptnewline (false),\n        m_emptymatch (false), m_freespacing (false), m_lineanchors (false),\n        m_once (false) { }\n\n    opts (const opts&) = default;\n\n    opts& operator = (const opts&) = default;\n\n    ~opts () = default;\n\n    void case_insensitive (bool val) { m_case_insensitive = val; }\n    void dotexceptnewline (bool val) { m_dotexceptnewline = val; }\n    void emptymatch (bool val) { m_emptymatch = val; }\n    void freespacing (bool val) { m_freespacing = val; }\n    void lineanchors (bool val) { m_lineanchors = val; }\n    void once (bool val) { m_once = val; }\n\n    bool case_insensitive () const { return m_case_insensitive; }\n    bool dotexceptnewline () const { return m_dotexceptnewline; }\n    bool emptymatch () const { return m_emptymatch; }\n    bool freespacing () const { return m_freespacing; }\n    bool lineanchors () const { return m_lineanchors; }\n    bool once () const { return m_once; }\n\n  private:\n\n    bool m_case_insensitive;\n    bool m_dotexceptnewline;\n    bool m_emptymatch;\n    bool m_freespacing;\n    bool m_lineanchors;\n    bool m_once;\n  };\n\n  class match_element\n  {\n  public:\n\n    match_element () = delete;\n\n    match_element (const string_vector& nt, const string_vector& t,\n                   const std::string& ms, const Matrix& te,\n                   double s, double e)\n      : m_match_string (ms), m_named_tokens (nt), m_tokens (t),\n        m_token_extents (te), m_start (s), m_end (e)\n    { }\n\n    OCTAVE_DEFAULT_COPY_MOVE_DELETE (match_element)\n\n    std::string match_string () const { return m_match_string; }\n    string_vector named_tokens () const { return m_named_tokens; }\n    string_vector tokens () const { return m_tokens; }\n    Matrix token_extents () const { return m_token_extents; }\n    double start () const { return m_start; }\n    double end () const { return m_end; }\n\n  private:\n\n    std::string m_match_string;\n    string_vector m_named_tokens;\n    string_vector m_tokens;\n    Matrix m_token_extents;\n\n    // FIXME: Are these values declared as double because that's what\n    // Octave interpreter functions will store?  Should they be int or\n    // size_t instead?\n    double m_start;\n    double m_end;\n  };\n\n  class match_data : public std::list<match_element>\n  {\n  public:\n\n    match_data ()\n      : std::list<match_element> (), m_named_pats ()\n    { }\n\n    match_data (const std::list<match_element>& l, const string_vector& np)\n      : std::list<match_element> (l), m_named_pats (np)\n    { }\n\n    OCTAVE_DEFAULT_COPY_MOVE_DELETE (match_data)\n\n    string_vector named_patterns () const { return m_named_pats; }\n\n  private:\n\n    string_vector m_named_pats;\n  };\n\nprivate:\n\n  // The pattern we've been asked to match.\n  std::string m_pattern;\n\n  opts m_options;\n\n  // Internal data describing the regular expression.\n  void *m_code;\n\n  string_vector m_named_pats;\n  int m_names;\n  Array<int> m_named_idx;\n  std::string m_who;\n\n  void free ();\n\n  void compile_internal ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-shlib.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <list>\n#include <map>\n\nextern \"C\"\n{\n#if defined (HAVE_DLOPEN_API)\n#  if defined (HAVE_DLFCN_H)\n#    include <dlfcn.h>\n#  else\n  extern void * dlopen (const char *, int);\n  extern const char * dlerror ();\n  extern void * dlsym (void *, const char *);\n  extern int dlclose (void *);\n#  endif\n#elif defined (HAVE_LOADLIBRARY_API)\n#  define WIN32_LEAN_AND_MEAN 1\n#  include <windows.h>\n#  include <psapi.h>\n#endif\n}\n\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"oct-error.h\"\n#include \"oct-shlib.h\"\n#include \"str-vec.h\"\n\n#if defined (HAVE_LOADLIBRARY_API)\n#  include \"oct-sysdep.h\"\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstd::list<dynamic_library> possibly_unreferenced_dynamic_libraries;\n\nvoid\ndynamic_library::delete_later ()\n{\n  possibly_unreferenced_dynamic_libraries.push_back (*this);\n}\n\nint\nrelease_unreferenced_dynamic_libraries ()\n{\n  possibly_unreferenced_dynamic_libraries.clear ();\n\n  return 0;\n}\n\ndynamic_library::dynlib_rep::dynlib_rep (const std::string& f)\n  : m_count (1), m_fcn_names (), m_file (f), m_time_loaded (),\n    m_search_all_loaded (false)\n{\n  instances ()[f] = this;\n\n  if (is_out_of_date ())\n    (*current_liboctave_warning_with_id_handler)\n      (\"Octave:future-time-stamp\",\n       \"time stamp for file '%s' is in the future\", m_file.c_str ());\n}\n\nbool\ndynamic_library::dynlib_rep::is_out_of_date () const\n{\n  sys::file_stat fs (m_file);\n  return (fs && fs.is_newer (m_time_loaded));\n}\n\nvoid\ndynamic_library::dynlib_rep::fake_reload ()\n{\n  // We can't actually reload the library, but we'll pretend we did.\n  sys::file_stat fs (m_file);\n  if (fs && fs.is_newer (m_time_loaded))\n    {\n      m_time_loaded = fs.mtime ();\n\n      (*current_liboctave_warning_with_id_handler)\n        (\"Octave:library-reload\",\n         \"library %s not reloaded due to existing references\", m_file.c_str ());\n    }\n}\n\ndynamic_library::dynlib_rep *\ndynamic_library::dynlib_rep::get_instance (const std::string& f, bool fake)\n{\n  dynlib_rep *retval = nullptr;\n  std::map<std::string, dynlib_rep *>::iterator p = instances ().find (f);\n  if (p != instances ().end ())\n    {\n      retval = p->second;\n      retval->m_count++;\n      if (fake)\n        retval->fake_reload ();\n    }\n  else\n    retval = new_instance (f);\n\n  return retval;\n}\n\nstd::list<std::string>\ndynamic_library::dynlib_rep::function_names () const\n{\n  std::list<std::string> retval;\n\n  for (const auto& p : m_fcn_names)\n    retval.push_back (p.first);\n\n  return retval;\n}\n\nvoid\ndynamic_library::dynlib_rep::add_fcn_name (const std::string& name)\n{\n  auto p = m_fcn_names.find (name);\n\n  if (p == m_fcn_names.end ())\n    m_fcn_names[name] = 1;\n  else\n    ++(p->second);\n}\n\nbool\ndynamic_library::dynlib_rep::remove_fcn_name (const std::string& fcn_name)\n{\n  bool retval = false;\n\n  auto p = m_fcn_names.find (fcn_name);\n\n  if (p != m_fcn_names.end () && --(p->second) == 0)\n    {\n      m_fcn_names.erase (fcn_name);\n      retval = true;\n    }\n\n  return retval;\n}\n\nstd::map<std::string, dynamic_library::dynlib_rep *>&\ndynamic_library::dynlib_rep::instances ()\n{\n  // FIXME: This map is intentionally heap-allocated and never deleted to avoid\n  // UBSAN issues.  Also see bug #53156 and the similar pattern in\n  // ov-typeinfo.cc.  This creates a small memory leak that is reclaimed by the\n  // OS at process exit.\n  //\n  // This \"leaky singleton\" pattern is necessary because:\n  // 1. s_nil_rep is a file-scope static whose destructor calls instances()\n  // 2. possibly_unreferenced_dynamic_libraries may hold dynamic_library\n  //    objects whose destructors also call instances()\n  // 3. We cannot guarantee the map outlives all these other statics\n  //\n  // By never destroying the map, we ensure it is always valid during shutdown.\n\n  static auto *s_instances = new std::map<std::string, dynlib_rep *> ();\n  return *s_instances;\n}\n\ndynamic_library::dynlib_rep dynamic_library::s_nil_rep;\n\n#if defined (HAVE_DLOPEN_API)\n\nclass octave_dlopen_shlib : public dynamic_library::dynlib_rep\n{\npublic:\n\n  octave_dlopen_shlib (const std::string& f);\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (octave_dlopen_shlib)\n\n  ~octave_dlopen_shlib ();\n\n  void * search (const std::string& name,\n                const dynamic_library::name_mangler& mangler\n                = dynamic_library::name_mangler ());\n\n  // FIXME: this is possibly redundant because failure to open a library will\n  // normally throw an exception, avoiding the construction of an invalid\n  // library.  Leave it here for possible future use.\n\n  bool is_open () const\n  {\n    return (m_search_all_loaded || m_library != nullptr);\n  }\n\nprivate:\n\n  void *m_library;\n};\n\noctave_dlopen_shlib::octave_dlopen_shlib (const std::string& f)\n  : dynamic_library::dynlib_rep (f), m_library (nullptr)\n{\n  int flags = 0;\n\n  // Use RTLD_NOW to resolve all symbols before dlopen returns.\n  // By using this option, dlopen will detect errors and Octave\n  // won't exit if there are unresolved symbols in the file we are\n  // loading, and we may even get a useful diagnostic.\n#  if defined (RTLD_NOW)\n  flags |= RTLD_NOW;\n#  endif\n\n  // Use RTLD_GLOBAL to export symbols from loaded objects so they are\n  // available to other subsequently loaded libraries.\n#  if defined (RTLD_GLOBAL)\n  flags |= RTLD_GLOBAL;\n#  endif\n\n  if (m_file.empty ())\n    {\n      m_search_all_loaded = true;\n      return;\n    }\n\n  m_library = dlopen (m_file.c_str (), flags);\n\n  if (! m_library)\n    {\n      const char *msg = dlerror ();\n\n      if (msg)\n        (*current_liboctave_error_handler)\n          (\"%s: failed to load\\nIncompatible version or missing dependency?\"\n           \"\\n%s\", m_file.c_str (), msg);\n      else\n        (*current_liboctave_error_handler)\n          (\"%s: failed to load\\nIncompatible version or missing dependency?\",\n           m_file.c_str ());\n    }\n}\n\noctave_dlopen_shlib::~octave_dlopen_shlib ()\n{\n  if (m_library)\n    dlclose (m_library);\n}\n\nvoid *\noctave_dlopen_shlib::search (const std::string& name,\n                             const dynamic_library::name_mangler& mangler)\n{\n  void *function = nullptr;\n\n  if (! is_open ())\n    (*current_liboctave_error_handler)\n      (\"shared library %s is not open\", m_file.c_str ());\n\n  std::string sym_name = name;\n\n  if (mangler)\n    sym_name = mangler (name);\n\n  if (m_search_all_loaded)\n    function = dlsym (RTLD_DEFAULT, sym_name.c_str ());\n  else\n    function = dlsym (m_library, sym_name.c_str ());\n\n  return function;\n}\n\n#elif defined (HAVE_LOADLIBRARY_API)\n\nclass octave_w32_shlib: public dynamic_library::dynlib_rep\n{\npublic:\n\n  octave_w32_shlib (const std::string& f);\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_w32_shlib)\n\n  ~octave_w32_shlib ();\n\n  void * search (const std::string& name,\n                const dynamic_library::name_mangler& mangler\n                = dynamic_library::name_mangler ());\n\n  void * global_search (const std::string& sym_name);\n\n  bool is_open () const\n  {\n    return (m_search_all_loaded || m_handle != nullptr);\n  }\n\nprivate:\n\n  HINSTANCE m_handle;\n};\n\noctave_w32_shlib::octave_w32_shlib (const std::string& f)\n  : dynamic_library::dynlib_rep (f), m_handle (nullptr)\n{\n  if (f.empty())\n    {\n      m_search_all_loaded = true;\n      return;\n    }\n\n  std::string dir = sys::file_ops::dirname (f);\n  std::wstring wdir = sys::u8_to_wstring (dir);\n  SetDllDirectoryW (dir.empty ()\n                    ? nullptr : wdir.c_str ());\n\n  std::wstring wfile = sys::u8_to_wstring (m_file);\n  m_handle = LoadLibraryW (wfile.c_str ());\n\n  SetDllDirectoryW (nullptr);\n\n  if (! m_handle)\n    {\n      DWORD last_error = GetLastError ();\n\n      wchar_t *error_text = nullptr;\n      FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |\n                      FORMAT_MESSAGE_ALLOCATE_BUFFER |\n                      FORMAT_MESSAGE_IGNORE_INSERTS,\n                      nullptr, last_error,\n                      MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),\n                      reinterpret_cast<wchar_t *> (&error_text), 0, nullptr);\n\n      std::ostringstream err_str;\n      err_str << \"opening the library '\" << m_file << \"' failed (error \"\n              << last_error << \"): \";\n      if (error_text != nullptr)\n        {\n          err_str << sys::u8_from_wstring (error_text);\n          LocalFree (error_text);\n        }\n      else\n        err_str << \"Unknown error.\";\n\n      (*current_liboctave_error_handler) (\"%s\", err_str.str ().c_str ());\n    }\n}\n\noctave_w32_shlib::~octave_w32_shlib ()\n{\n  if (m_handle)\n    FreeLibrary (m_handle);\n}\n\nvoid *\noctave_w32_shlib::global_search (const std::string& sym_name)\n{\n  void *function = nullptr;\n\n  HANDLE proc = GetCurrentProcess ();\n\n  if (! proc)\n    (*current_liboctave_error_handler)\n      (\"Unable to get handle to own process.\");\n\n  std::size_t lib_num = 64;\n  std::size_t size_lib = sizeof (HMODULE);\n  HMODULE *h_libs;\n  DWORD bytes_all_libs;\n  bool got_libs;\n\n  // Get a list of all the libraries in own process.\n  h_libs = static_cast<HMODULE *> (malloc (size_lib*lib_num));\n  got_libs = EnumProcessModules (proc, h_libs, size_lib*lib_num,\n                                 &bytes_all_libs);\n  int ii = 0;\n  while (((size_lib*lib_num) < bytes_all_libs) && ii++ < 3)\n    {\n      lib_num = bytes_all_libs / size_lib;\n      h_libs = static_cast<HMODULE *> (realloc (h_libs, bytes_all_libs));\n      got_libs = EnumProcessModules (proc, h_libs, bytes_all_libs,\n                                     &bytes_all_libs);\n    }\n\n  if (got_libs)\n    {\n      for (std::size_t i = 0; i < (bytes_all_libs / size_lib); i++)\n        {\n          // Check for function in library.\n          function = reinterpret_cast<void *>\n                     (GetProcAddress (h_libs[i], sym_name.c_str ()));\n\n          if (function)\n            break;\n        }\n    }\n\n  // Release the handle to the process.\n  CloseHandle (proc);\n\n  return function;\n}\n\nvoid *\noctave_w32_shlib::search (const std::string& name,\n                          const dynamic_library::name_mangler& mangler)\n{\n  void *function = nullptr;\n\n  if (! m_search_all_loaded && ! is_open ())\n    (*current_liboctave_error_handler)\n      (\"shared library %s is not open\", m_file.c_str ());\n\n  std::string sym_name = name;\n\n  if (mangler)\n    sym_name = mangler (name);\n\n  if (m_search_all_loaded)\n    function = global_search (sym_name);\n  else\n    function = reinterpret_cast<void *> (GetProcAddress (m_handle,\n                                         sym_name.c_str ()));\n\n  return function;\n}\n\n#endif\n\ndynamic_library::dynlib_rep *\ndynamic_library::dynlib_rep::new_instance (const std::string& f)\n{\n#if defined (HAVE_DLOPEN_API)\n  return new octave_dlopen_shlib (f);\n#elif defined (HAVE_LOADLIBRARY_API)\n  return new octave_w32_shlib (f);\n#else\n  (*current_liboctave_error_handler)\n    (\"support for dynamically loaded libraries was unavailable or disabled when liboctave was built\");\n#endif\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/oct-shlib.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1999-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_shlib_h)\n#define octave_oct_shlib_h 1\n\n#include \"octave-config.h\"\n\n#include <functional>\n#include <list>\n#include <map>\n#include <string>\n\n#include \"oct-time.h\"\n#include \"oct-refcount.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass dynamic_library\n{\npublic: // FIXME: make this class private?\n\n  typedef std::function<std::string (const std::string&)> name_mangler;\n\n  class dynlib_rep\n  {\n  public:\n\n    dynlib_rep ()\n      : m_count (1), m_fcn_names (), m_file (), m_time_loaded (OCTAVE_TIME_T ()),\n        m_search_all_loaded (false)\n    { }\n\n    OCTAVE_DISABLE_COPY_MOVE (dynlib_rep)\n\n  protected:\n\n    OCTAVE_API\n    dynlib_rep (const std::string& f);\n\n  public:\n\n    virtual ~dynlib_rep ()\n    {\n      instances ().erase (m_file);\n    }\n\n    virtual bool is_open () const\n    { return false; }\n\n    virtual void * search (const std::string&,\n                          const name_mangler& = name_mangler ())\n    { return nullptr; }\n\n    OCTAVE_API bool is_out_of_date () const;\n\n    // This method will be overridden conditionally.\n    static OCTAVE_API dynlib_rep * new_instance (const std::string& f);\n\n    static OCTAVE_API dynlib_rep * get_instance (const std::string& f, bool fake);\n\n    sys::time time_loaded () const\n    { return m_time_loaded; }\n\n    std::string file_name () const\n    { return m_file; }\n\n    std::size_t num_fcn_names () const { return m_fcn_names.size (); }\n\n    OCTAVE_API std::list<std::string> function_names () const;\n\n    OCTAVE_API void add_fcn_name (const std::string&);\n\n    OCTAVE_API bool remove_fcn_name (const std::string&);\n\n    void clear_fcn_names () { m_fcn_names.clear (); }\n\n  public:\n\n    refcount<octave_idx_type> m_count;\n\n  protected:\n\n    OCTAVE_API void fake_reload ();\n\n    // Accessor for the instances map.  Uses a heap-allocated \"leaky singleton\"\n    // to avoid static destruction order issues at exit.  See bug #53156 and\n    // the similar pattern in ov-typeinfo.cc.\n    static OCTAVE_API std::map<std::string, dynlib_rep *>& instances ();\n\n    // Set of hooked function names.\n    typedef std::map<std::string, std::size_t>::iterator fcn_names_iterator;\n    typedef std::map<std::string, std::size_t>::const_iterator fcn_names_const_iterator;\n\n    std::map<std::string, std::size_t> m_fcn_names;\n    std::string m_file;\n    sys::time m_time_loaded;\n    bool m_search_all_loaded;\n  };\n\nprivate:\n\n  static OCTAVE_API dynlib_rep s_nil_rep;\n\npublic:\n\n  dynamic_library () : m_rep (&s_nil_rep) { m_rep->m_count++; }\n\n  dynamic_library (const std::string& f, bool fake = true)\n    : m_rep (dynlib_rep::get_instance (f, fake)) { }\n\n  ~dynamic_library ()\n  {\n    if (--m_rep->m_count == 0 && m_rep != &s_nil_rep)\n      delete m_rep;\n  }\n\n  OCTAVE_API void delete_later ();\n\n  dynamic_library (const dynamic_library& sl)\n    : m_rep (sl.m_rep)\n  {\n    m_rep->m_count++;\n  }\n\n  dynamic_library& operator = (const dynamic_library& sl)\n  {\n    if (m_rep != sl.m_rep)\n      {\n        if (--m_rep->m_count == 0 && m_rep != &s_nil_rep)\n          delete m_rep;\n\n        m_rep = sl.m_rep;\n        m_rep->m_count++;\n      }\n\n    return *this;\n  }\n\n  bool operator == (const dynamic_library& sl) const\n  { return (m_rep == sl.m_rep); }\n\n  operator bool () const { return m_rep->is_open (); }\n\n  void open (const std::string& f)\n  { *this = dynamic_library (f); }\n\n  std::list<std::string> close ()\n  {\n    std::list<std::string> removed_fcns = m_rep->function_names ();\n\n    m_rep->clear_fcn_names ();\n\n    *this = dynamic_library ();\n\n    return removed_fcns;\n  }\n\n  void * search (const std::string& nm,\n                const name_mangler& mangler = name_mangler ()) const\n  {\n    void *f = m_rep->search (nm, mangler);\n    if (f)\n      m_rep->add_fcn_name (nm);\n\n    return f;\n  }\n\n  void add (const std::string& name)\n  { m_rep->add_fcn_name (name); }\n\n  bool remove (const std::string& name)\n  { return m_rep->remove_fcn_name (name); }\n\n  std::size_t number_of_functions_loaded () const\n  { return m_rep->num_fcn_names (); }\n\n  bool is_out_of_date () const\n  { return m_rep->is_out_of_date (); }\n\n  std::string file_name () const\n  { return m_rep->file_name (); }\n\n  sys::time time_loaded () const\n  { return m_rep->time_loaded (); }\n\nprivate:\n\n  dynlib_rep *m_rep;\n};\n\n// FIXME: Currently must return int so that it may be used as an\n// event_hook function.\n\nOCTAVE_API int release_unreferenced_dynamic_libraries ();\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-sort.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n// Code stolen in large part from Python's, listobject.c, which itself had\n// no license header.  However, thanks to Tim Peters for the parts of the\n// code I ripped-off.\n//\n// As required in the Python license the short description of the changes\n// made are\n//\n// * convert the sorting code in listobject.cc into a generic class,\n//   replacing PyObject* with the type of the class T.\n//\n// * replaced usages of malloc, free, memcpy and memmove by standard C++\n//   new [], delete [] and std::copy and std::copy_backward.  Note that replacing\n//   memmove by std::copy is possible if the destination starts before the source.\n//   If not, std::copy_backward needs to be used.\n//\n// * templatize comparison operator in most methods, provide possible dispatch\n//\n// * duplicate methods to avoid by-the-way indexed sorting\n//\n// * add methods for verifying sortedness of array\n//\n// * row sorting via breadth-first tree subsorting\n//\n// * binary lookup and sequential binary lookup optimized for dense downsampling.\n//\n// * NOTE: the memory management routines rely on the fact that delete [] silently\n//   ignores null pointers.  Don't gripe about the missing checks - they're there.\n//\n//\n// The Python license is\n//\n//   PSF LICENSE AGREEMENT FOR PYTHON 2.3\n//   --------------------------------------\n//\n//   1. This LICENSE AGREEMENT is between the Python Software Foundation\n//   (\"PSF\"), and the Individual or Organization (\"Licensee\") accessing and\n//   otherwise using Python 2.3 software in source or binary form and its\n//   associated documentation.\n//\n//   2. Subject to the terms and conditions of this License Agreement, PSF\n//   hereby grants Licensee a nonexclusive, royalty-free, world-wide\n//   license to reproduce, analyze, test, perform and/or display publicly,\n//   prepare derivative works, distribute, and otherwise use Python 2.3\n//   alone or in any derivative version, provided, however, that PSF's\n//   License Agreement and PSF's notice of copyright, i.e., \"Copyright (c)\n//   2001, 2002, 2003 Python Software Foundation; All Rights Reserved\" are\n//   retained in Python 2.3 alone or in any derivative version prepared by\n//   Licensee.\n//\n//   3. In the event Licensee prepares a derivative work that is based on\n//   or incorporates Python 2.3 or any part thereof, and wants to make\n//   the derivative work available to others as provided herein, then\n//   Licensee hereby agrees to include in any such work a brief summary of\n//   the changes made to Python 2.3.\n//\n//   4. PSF is making Python 2.3 available to Licensee on an \"AS IS\"\n//   basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\n//   IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND\n//   DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\n//   FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.3 WILL NOT\n//   INFRINGE ANY THIRD PARTY RIGHTS.\n//\n//   5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON\n//   2.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS\n//   A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.3,\n//   OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\n//\n//   6. This License Agreement will automatically terminate upon a material\n//   breach of its terms and conditions.\n//\n//   7. Nothing in this License Agreement shall be deemed to create any\n//   relationship of agency, partnership, or joint venture between PSF and\n//   Licensee.  This License Agreement does not grant permission to use PSF\n//   trademarks or trade name in a trademark sense to endorse or promote\n//   products or services of Licensee, or any third party.\n//\n//   8. By copying, installing or otherwise using Python 2.3, Licensee\n//   agrees to be bound by the terms and conditions of this License\n//   Agreement.\n//\n////////////////////////////////////////////////////////////////////////\n\n// This file should not include config.h.  It is only included in other\n// C++ source files that should have included config.h before including\n// this file.\n\n#include <algorithm>\n#include <cstring>\n#include <stack>\n\n#include \"mappers.h\"\n#include \"oct-error.h\"\n#include \"oct-locbuf.h\"\n#include \"oct-sort.h\"\n#include \"quit.h\"\n\ntemplate <typename T>\noctave_sort<T>::octave_sort () :\n  m_compare (ascending_compare), m_ms (nullptr)\n{ }\n\ntemplate <typename T>\noctave_sort<T>::octave_sort (const compare_fcn_type& comp)\n  : m_compare (comp), m_ms (nullptr)\n{ }\n\ntemplate <typename T>\noctave_sort<T>::~octave_sort ()\n{\n  delete m_ms;\n}\n\ntemplate <typename T>\nvoid\noctave_sort<T>::set_compare (sortmode mode)\n{\n  if (mode == ASCENDING)\n    m_compare = ascending_compare;\n  else if (mode == DESCENDING)\n    m_compare = descending_compare;\n  else\n    m_compare = compare_fcn_type ();\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nvoid\noctave_sort<T>::binarysort (T *data, octave_idx_type nel,\n                            octave_idx_type start, Comp comp)\n{\n  if (start == 0)\n    ++start;\n\n  for (; start < nel; ++start)\n    {\n      /* set l to where *start belongs */\n      octave_idx_type l = 0;\n      octave_idx_type r = start;\n      T pivot = data[start];\n      /* Invariants:\n       * pivot >= all in [lo, l).\n       * pivot  < all in [r, start).\n       * The second is vacuously true at the start.\n       */\n      do\n        {\n          octave_idx_type p = l + ((r - l) >> 1);\n          if (comp (pivot, data[p]))\n            r = p;\n          else\n            l = p+1;\n        }\n      while (l < r);\n      /* The invariants still hold, so pivot >= all in [lo, l) and\n         pivot < all in [l, start), so pivot belongs at l.  Note\n         that if there are elements equal to pivot, l points to the\n         first slot after them -- that's why this sort is stable.\n         Slide over to make room.\n         Caution: using memmove is much slower under MSVC 5;\n         we're not usually moving many slots. */\n      // NOTE: using swap and going upwards appears to be faster.\n      for (octave_idx_type p = l; p < start; p++)\n        std::swap (pivot, data[p]);\n      data[start] = pivot;\n    }\n\n  return;\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nvoid\noctave_sort<T>::binarysort (T *data, octave_idx_type *idx, octave_idx_type nel,\n                            octave_idx_type start, Comp comp)\n{\n  if (start == 0)\n    ++start;\n\n  for (; start < nel; ++start)\n    {\n      /* set l to where *start belongs */\n      octave_idx_type l = 0;\n      octave_idx_type r = start;\n      T pivot = data[start];\n      /* Invariants:\n       * pivot >= all in [lo, l).\n       * pivot  < all in [r, start).\n       * The second is vacuously true at the start.\n       */\n      do\n        {\n          octave_idx_type p = l + ((r - l) >> 1);\n          if (comp (pivot, data[p]))\n            r = p;\n          else\n            l = p+1;\n        }\n      while (l < r);\n      /* The invariants still hold, so pivot >= all in [lo, l) and\n         pivot < all in [l, start), so pivot belongs at l.  Note\n         that if there are elements equal to pivot, l points to the\n         first slot after them -- that's why this sort is stable.\n         Slide over to make room.\n         Caution: using memmove is much slower under MSVC 5;\n         we're not usually moving many slots. */\n      // NOTE: using swap and going upwards appears to be faster.\n      for (octave_idx_type p = l; p < start; p++)\n        std::swap (pivot, data[p]);\n      data[start] = pivot;\n      octave_idx_type ipivot = idx[start];\n      for (octave_idx_type p = l; p < start; p++)\n        std::swap (ipivot, idx[p]);\n      idx[start] = ipivot;\n    }\n\n  return;\n}\n\n/*\nReturn the length of the run beginning at lo, in the slice [lo, hi).  lo < hi\nis required on entry.  \"A run\" is the longest ascending sequence, with\n\n    lo[0] <= lo[1] <= lo[2] <= ...\n\nor the longest descending sequence, with\n\n    lo[0] > lo[1] > lo[2] > ...\n\nDESCENDING is set to false in the former case, or to true in the latter.\nFor its intended use in a stable mergesort, the strictness of the defn of\n\"descending\" is needed so that the caller can safely reverse a descending\nsequence without violating stability (strict > ensures there are no equal\nelements to get out of order).\n\nReturns -1 in case of error.\n*/\ntemplate <typename T>\ntemplate <typename Comp>\noctave_idx_type\noctave_sort<T>::count_run (T *lo, octave_idx_type nel, bool& descending,\n                           Comp comp)\n{\n  octave_idx_type n;\n  T *hi = lo + nel;\n\n  descending = false;\n  ++lo;\n  if (lo == hi)\n    return 1;\n\n  n = 2;\n\n  if (comp (*lo, *(lo-1)))\n    {\n      descending = true;\n      for (lo = lo+1; lo < hi; ++lo, ++n)\n        {\n          if (comp (*lo, *(lo-1)))\n            ;\n          else\n            break;\n        }\n    }\n  else\n    {\n      for (lo = lo+1; lo < hi; ++lo, ++n)\n        {\n          if (comp (*lo, *(lo-1)))\n            break;\n        }\n    }\n\n  return n;\n}\n\n/*\nLocate the proper position of key in a sorted vector; if the vector contains\nan element equal to key, return the position immediately to the left of\nthe leftmost equal element.  [gallop_right() does the same except returns\nthe position to the right of the rightmost equal element (if any).]\n\n\"a\" is a sorted vector with n elements, starting at a[0].  n must be > 0.\n\n\"hint\" is an index at which to begin the search, 0 <= hint < n.  The closer\nhint is to the final result, the faster this runs.\n\nThe return value is the int k in 0..n such that\n\n    a[k-1] < key <= a[k]\n\npretending that *(a-1) is minus infinity and a[n] is plus infinity.  IOW,\nkey belongs at index k; or, IOW, the first k elements of a should precede\nkey, and the last n-k should follow key.\n\nReturns -1 on error.  See listsort.txt for info on the method.\n*/\ntemplate <typename T>\ntemplate <typename Comp>\noctave_idx_type\noctave_sort<T>::gallop_left (T key, T *a, octave_idx_type n,\n                             octave_idx_type hint,\n                             Comp comp)\n{\n  octave_idx_type ofs;\n  octave_idx_type lastofs;\n  octave_idx_type k;\n\n  a += hint;\n  lastofs = 0;\n  ofs = 1;\n  if (comp (*a, key))\n    {\n      /* a[hint] < key -- gallop right, until\n       * a[hint + lastofs] < key <= a[hint + ofs]\n       */\n      const octave_idx_type maxofs = n - hint;  /* &a[n-1] is highest */\n      while (ofs < maxofs)\n        {\n          if (comp (a[ofs], key))\n            {\n              lastofs = ofs;\n              ofs = (ofs << 1) + 1;\n              if (ofs <= 0)     /* int overflow */\n                ofs = maxofs;\n            }\n          else  /* key <= a[hint + ofs] */\n            break;\n        }\n      if (ofs > maxofs)\n        ofs = maxofs;\n      /* Translate back to offsets relative to &a[0]. */\n      lastofs += hint;\n      ofs += hint;\n    }\n  else\n    {\n      /* key <= a[hint] -- gallop left, until\n       * a[hint - ofs] < key <= a[hint - lastofs]\n       */\n      const octave_idx_type maxofs = hint + 1;  /* &a[0] is lowest */\n      while (ofs < maxofs)\n        {\n          if (comp (*(a-ofs), key))\n            break;\n          /* key <= a[hint - ofs] */\n          lastofs = ofs;\n          ofs = (ofs << 1) + 1;\n          if (ofs <= 0) /* int overflow */\n            ofs = maxofs;\n        }\n      if (ofs > maxofs)\n        ofs = maxofs;\n      /* Translate back to positive offsets relative to &a[0]. */\n      k = lastofs;\n      lastofs = hint - ofs;\n      ofs = hint - k;\n    }\n  a -= hint;\n\n  /* Now a[lastofs] < key <= a[ofs], so key belongs somewhere to the\n   * right of lastofs but no farther right than ofs.  Do a binary\n   * search, with invariant a[lastofs-1] < key <= a[ofs].\n   */\n  ++lastofs;\n  while (lastofs < ofs)\n    {\n      octave_idx_type m = lastofs + ((ofs - lastofs) >> 1);\n\n      if (comp (a[m], key))\n        lastofs = m+1;  /* a[m] < key */\n      else\n        ofs = m;        /* key <= a[m] */\n    }\n\n  return ofs;\n}\n\n/*\nExactly like gallop_left(), except that if key already exists in a[0:n],\nfinds the position immediately to the right of the rightmost equal value.\n\nThe return value is the int k in 0..n such that\n\n    a[k-1] <= key < a[k]\n\nor -1 if error.\n\nThe code duplication is massive, but this is enough different given that\nwe're sticking to \"<\" comparisons that it's much harder to follow if\nwritten as one routine with yet another \"left or right?\" flag.\n*/\ntemplate <typename T>\ntemplate <typename Comp>\noctave_idx_type\noctave_sort<T>::gallop_right (T key, T *a, octave_idx_type n,\n                              octave_idx_type hint,\n                              Comp comp)\n{\n  octave_idx_type ofs;\n  octave_idx_type lastofs;\n  octave_idx_type k;\n\n  a += hint;\n  lastofs = 0;\n  ofs = 1;\n  if (comp (key, *a))\n    {\n      /* key < a[hint] -- gallop left, until\n       * a[hint - ofs] <= key < a[hint - lastofs]\n       */\n      const octave_idx_type maxofs = hint + 1;  /* &a[0] is lowest */\n      while (ofs < maxofs)\n        {\n          if (comp (key, *(a-ofs)))\n            {\n              lastofs = ofs;\n              ofs = (ofs << 1) + 1;\n              if (ofs <= 0)     /* int overflow */\n                ofs = maxofs;\n            }\n          else  /* a[hint - ofs] <= key */\n            break;\n        }\n      if (ofs > maxofs)\n        ofs = maxofs;\n      /* Translate back to positive offsets relative to &a[0]. */\n      k = lastofs;\n      lastofs = hint - ofs;\n      ofs = hint - k;\n    }\n  else\n    {\n      /* a[hint] <= key -- gallop right, until\n       * a[hint + lastofs] <= key < a[hint + ofs]\n       */\n      const octave_idx_type maxofs = n - hint;  /* &a[n-1] is highest */\n      while (ofs < maxofs)\n        {\n          if (comp (key, a[ofs]))\n            break;\n          /* a[hint + ofs] <= key */\n          lastofs = ofs;\n          ofs = (ofs << 1) + 1;\n          if (ofs <= 0) /* int overflow */\n            ofs = maxofs;\n        }\n      if (ofs > maxofs)\n        ofs = maxofs;\n      /* Translate back to offsets relative to &a[0]. */\n      lastofs += hint;\n      ofs += hint;\n    }\n  a -= hint;\n\n  /* Now a[lastofs] <= key < a[ofs], so key belongs somewhere to the\n   * right of lastofs but no farther right than ofs.  Do a binary\n   * search, with invariant a[lastofs-1] <= key < a[ofs].\n   */\n  ++lastofs;\n  while (lastofs < ofs)\n    {\n      octave_idx_type m = lastofs + ((ofs - lastofs) >> 1);\n\n      if (comp (key, a[m]))\n        ofs = m;        /* key < a[m] */\n      else\n        lastofs = m+1;  /* a[m] <= key */\n    }\n\n  return ofs;\n}\n\nstatic inline octave_idx_type\nroundupsize (std::size_t n)\n{\n  unsigned int nbits = 3;\n  std::size_t n2 = n >> 8;\n\n  /* Round up:\n   * If n <       256, to a multiple of        8.\n   * If n <      2048, to a multiple of       64.\n   * If n <     16384, to a multiple of      512.\n   * If n <    131072, to a multiple of     4096.\n   * If n <   1048576, to a multiple of    32768.\n   * If n <   8388608, to a multiple of   262144.\n   * If n <  67108864, to a multiple of  2097152.\n   * If n < 536870912, to a multiple of 16777216.\n   * ...\n   * If n < 2**(5+3*i), to a multiple of 2**(3*i).\n   *\n   * This over-allocates proportional to the list size, making room\n   * for additional growth.  The over-allocation is mild, but is\n   * enough to give linear-time amortized behavior over a long\n   * sequence of appends() in the presence of a poorly-performing\n   * system realloc() (which is a reality, e.g., across all flavors\n   * of Windows, with Win9x behavior being particularly bad -- and\n   * we've still got address space fragmentation problems on Win9x\n   * even with this scheme, although it requires much longer lists to\n   * provoke them than it used to).\n   */\n  while (n2)\n    {\n      n2 >>= 3;\n      nbits += 3;\n    }\n\n  std::size_t multiplier = static_cast<std::size_t> (1) << nbits;\n  std::size_t new_size = (n >> nbits) + 1;\n\n  if (new_size\n      > static_cast<std::size_t> (std::numeric_limits<octave_idx_type>::max ())\n        / multiplier)\n    (*current_liboctave_error_handler)\n      (\"unable to allocate sufficient memory for sort\");\n\n  new_size *= multiplier;\n  return static_cast<octave_idx_type> (new_size);\n}\n\n/* Ensure enough temp memory for 'need' array slots is available.\n * Returns 0 on success and -1 if the memory can't be gotten.\n */\ntemplate <typename T>\nvoid\noctave_sort<T>::MergeState::getmem (octave_idx_type need)\n{\n  if (need <= m_alloced)\n    return;\n\n  need = roundupsize (need);\n  /* Don't realloc!  That can cost cycles to copy the old data, but\n   * we don't care what's in the block.\n   */\n  delete [] m_a;\n  delete [] m_ia; // Must do this or fool possible next getmemi.\n  m_a = new T [need];\n  m_alloced = need;\n\n}\n\ntemplate <typename T>\nvoid\noctave_sort<T>::MergeState::getmemi (octave_idx_type need)\n{\n  if (m_a && m_ia && need <= m_alloced)\n    return;\n\n  need = roundupsize (need);\n  /* Don't realloc!  That can cost cycles to copy the old data, but\n   * we don't care what's in the block.\n   */\n  delete [] m_a;\n  delete [] m_ia;\n\n  m_a = new T [need];\n  m_ia = new octave_idx_type [need];\n  m_alloced = need;\n}\n\n/* Merge the na elements starting at pa with the nb elements starting at pb\n * in a stable way, in-place.  na and nb must be > 0, and pa + na == pb.\n * Must also have that *pb < *pa, that pa[na-1] belongs at the end of the\n * merge, and should have na <= nb.  See listsort.txt for more info.\n * Return 0 if successful, -1 if error.\n */\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_lo (T *pa, octave_idx_type na,\n                          T *pb, octave_idx_type nb,\n                          Comp comp)\n{\n  octave_idx_type k;\n  T *dest;\n  int result = -1;      /* guilty until proved innocent */\n  octave_idx_type min_gallop = m_ms->m_min_gallop;\n\n  m_ms->getmem (na);\n\n  std::copy (pa, pa + na, m_ms->m_a);\n  dest = pa;\n  pa = m_ms->m_a;\n\n  *dest++ = *pb++;\n  --nb;\n  if (nb == 0)\n    goto Succeed;\n  if (na == 1)\n    goto CopyB;\n\n  for (;;)\n    {\n      octave_idx_type acount = 0;       /* # of times A won in a row */\n      octave_idx_type bcount = 0;       /* # of times B won in a row */\n\n      /* Do the straightforward thing until (if ever) one run\n       * appears to win consistently.\n       */\n      for (;;)\n        {\n\n          // FIXME: these loops are candidates for further optimizations.\n          // Rather than testing everything in each cycle, it may be more\n          // efficient to do it in hunks.\n          if (comp (*pb, *pa))\n            {\n              *dest++ = *pb++;\n              ++bcount;\n              acount = 0;\n              --nb;\n              if (nb == 0)\n                goto Succeed;\n              if (bcount >= min_gallop)\n                break;\n            }\n          else\n            {\n              *dest++ = *pa++;\n              ++acount;\n              bcount = 0;\n              --na;\n              if (na == 1)\n                goto CopyB;\n              if (acount >= min_gallop)\n                break;\n            }\n        }\n\n      /* One run is winning so consistently that galloping may\n       * be a huge win.  So try that, and continue galloping until\n       * (if ever) neither run appears to be winning consistently\n       * anymore.\n       */\n      ++min_gallop;\n      do\n        {\n          min_gallop -= (min_gallop > 1);\n          m_ms->m_min_gallop = min_gallop;\n          k = gallop_right (*pb, pa, na, 0, comp);\n          acount = k;\n          if (k)\n            {\n              if (k < 0)\n                goto Fail;\n              dest = std::copy (pa, pa + k, dest);\n              pa += k;\n              na -= k;\n              if (na == 1)\n                goto CopyB;\n              /* na==0 is impossible now if the comparison\n               * function is consistent, but we can't assume\n               * that it is.\n               */\n              if (na == 0)\n                goto Succeed;\n            }\n          *dest++ = *pb++;\n          --nb;\n          if (nb == 0)\n            goto Succeed;\n\n          k = gallop_left (*pa, pb, nb, 0, comp);\n          bcount = k;\n          if (k)\n            {\n              if (k < 0)\n                goto Fail;\n              dest = std::copy (pb, pb + k, dest);\n              pb += k;\n              nb -= k;\n              if (nb == 0)\n                goto Succeed;\n            }\n          *dest++ = *pa++;\n          --na;\n          if (na == 1)\n            goto CopyB;\n        }\n      while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);\n\n      ++min_gallop;     /* penalize it for leaving galloping mode */\n      m_ms->m_min_gallop = min_gallop;\n    }\n\nSucceed:\n  result = 0;\n\nFail:\n  if (na)\n    std::copy (pa, pa + na, dest);\n  return result;\n\nCopyB:\n  /* The last element of pa belongs at the end of the merge. */\n  std::copy (pb, pb + nb, dest);\n  dest[nb] = *pa;\n\n  return 0;\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_lo (T *pa, octave_idx_type *ipa, octave_idx_type na,\n                          T *pb, octave_idx_type *ipb, octave_idx_type nb,\n                          Comp comp)\n{\n  octave_idx_type k;\n  T *dest;\n  octave_idx_type *idest;\n  int result = -1;      /* guilty until proved innocent */\n  octave_idx_type min_gallop = m_ms->m_min_gallop;\n\n  m_ms->getmemi (na);\n\n  std::copy (pa, pa + na, m_ms->m_a);\n  std::copy (ipa, ipa + na, m_ms->m_ia);\n  dest = pa; idest = ipa;\n  pa = m_ms->m_a; ipa = m_ms->m_ia;\n\n  *dest++ = *pb++; *idest++ = *ipb++;\n  --nb;\n  if (nb == 0)\n    goto Succeed;\n  if (na == 1)\n    goto CopyB;\n\n  for (;;)\n    {\n      octave_idx_type acount = 0;       /* # of times A won in a row */\n      octave_idx_type bcount = 0;       /* # of times B won in a row */\n\n      /* Do the straightforward thing until (if ever) one run\n       * appears to win consistently.\n       */\n      for (;;)\n        {\n\n          if (comp (*pb, *pa))\n            {\n              *dest++ = *pb++; *idest++ = *ipb++;\n              ++bcount;\n              acount = 0;\n              --nb;\n              if (nb == 0)\n                goto Succeed;\n              if (bcount >= min_gallop)\n                break;\n            }\n          else\n            {\n              *dest++ = *pa++; *idest++ = *ipa++;\n              ++acount;\n              bcount = 0;\n              --na;\n              if (na == 1)\n                goto CopyB;\n              if (acount >= min_gallop)\n                break;\n            }\n        }\n\n      /* One run is winning so consistently that galloping may\n       * be a huge win.  So try that, and continue galloping until\n       * (if ever) neither run appears to be winning consistently\n       * anymore.\n       */\n      ++min_gallop;\n      do\n        {\n          min_gallop -= (min_gallop > 1);\n          m_ms->m_min_gallop = min_gallop;\n          k = gallop_right (*pb, pa, na, 0, comp);\n          acount = k;\n          if (k)\n            {\n              if (k < 0)\n                goto Fail;\n              dest = std::copy (pa, pa + k, dest);\n              idest = std::copy (ipa, ipa + k, idest);\n              pa += k; ipa += k;\n              na -= k;\n              if (na == 1)\n                goto CopyB;\n              /* na==0 is impossible now if the comparison\n               * function is consistent, but we can't assume\n               * that it is.\n               */\n              if (na == 0)\n                goto Succeed;\n            }\n          *dest++ = *pb++; *idest++ = *ipb++;\n          --nb;\n          if (nb == 0)\n            goto Succeed;\n\n          k = gallop_left (*pa, pb, nb, 0, comp);\n          bcount = k;\n          if (k)\n            {\n              if (k < 0)\n                goto Fail;\n              dest = std::copy (pb, pb + k, dest);\n              idest = std::copy (ipb, ipb + k, idest);\n              pb += k; ipb += k;\n              nb -= k;\n              if (nb == 0)\n                goto Succeed;\n            }\n          *dest++ = *pa++; *idest++ = *ipa++;\n          --na;\n          if (na == 1)\n            goto CopyB;\n        }\n      while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);\n\n      ++min_gallop;     /* penalize it for leaving galloping mode */\n      m_ms->m_min_gallop = min_gallop;\n    }\n\nSucceed:\n  result = 0;\n\nFail:\n  if (na)\n    {\n      std::copy (pa, pa + na, dest);\n      std::copy (ipa, ipa + na, idest);\n    }\n  return result;\n\nCopyB:\n  /* The last element of pa belongs at the end of the merge. */\n  std::copy (pb, pb + nb, dest);\n  std::copy (ipb, ipb + nb, idest);\n  dest[nb] = *pa;\n  idest[nb] = *ipa;\n\n  return 0;\n}\n\n/* Merge the na elements starting at pa with the nb elements starting at pb\n * in a stable way, in-place.  na and nb must be > 0, and pa + na == pb.\n * Must also have that *pb < *pa, that pa[na-1] belongs at the end of the\n * merge, and should have na >= nb.  See listsort.txt for more info.\n * Return 0 if successful, -1 if error.\n */\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_hi (T *pa, octave_idx_type na,\n                          T *pb, octave_idx_type nb,\n                          Comp comp)\n{\n  octave_idx_type k;\n  T *dest;\n  int result = -1;      /* guilty until proved innocent */\n  T *basea, *baseb;\n  octave_idx_type min_gallop = m_ms->m_min_gallop;\n\n  m_ms->getmem (nb);\n\n  dest = pb + nb - 1;\n  std::copy (pb, pb + nb, m_ms->m_a);\n  basea = pa;\n  baseb = m_ms->m_a;\n  pb = m_ms->m_a + nb - 1;\n  pa += na - 1;\n\n  *dest-- = *pa--;\n  --na;\n  if (na == 0)\n    goto Succeed;\n  if (nb == 1)\n    goto CopyA;\n\n  for (;;)\n    {\n      octave_idx_type acount = 0;       /* # of times A won in a row */\n      octave_idx_type bcount = 0;       /* # of times B won in a row */\n\n      /* Do the straightforward thing until (if ever) one run\n       * appears to win consistently.\n       */\n      for (;;)\n        {\n          if (comp (*pb, *pa))\n            {\n              *dest-- = *pa--;\n              ++acount;\n              bcount = 0;\n              --na;\n              if (na == 0)\n                goto Succeed;\n              if (acount >= min_gallop)\n                break;\n            }\n          else\n            {\n              *dest-- = *pb--;\n              ++bcount;\n              acount = 0;\n              --nb;\n              if (nb == 1)\n                goto CopyA;\n              if (bcount >= min_gallop)\n                break;\n            }\n        }\n\n      /* One run is winning so consistently that galloping may\n       * be a huge win.  So try that, and continue galloping until\n       * (if ever) neither run appears to be winning consistently\n       * anymore.\n       */\n      ++min_gallop;\n      do\n        {\n          min_gallop -= (min_gallop > 1);\n          m_ms->m_min_gallop = min_gallop;\n          k = gallop_right (*pb, basea, na, na-1, comp);\n          if (k < 0)\n            goto Fail;\n          k = na - k;\n          acount = k;\n          if (k)\n            {\n              dest = std::copy_backward (pa+1 - k, pa+1, dest+1) - 1;\n              pa -= k;\n              na -= k;\n              if (na == 0)\n                goto Succeed;\n            }\n          *dest-- = *pb--;\n          --nb;\n          if (nb == 1)\n            goto CopyA;\n\n          k = gallop_left (*pa, baseb, nb, nb-1, comp);\n          if (k < 0)\n            goto Fail;\n          k = nb - k;\n          bcount = k;\n          if (k)\n            {\n              dest -= k;\n              pb -= k;\n              std::copy (pb+1, pb+1 + k, dest+1);\n              nb -= k;\n              if (nb == 1)\n                goto CopyA;\n              /* nb==0 is impossible now if the comparison\n               * function is consistent, but we can't assume\n               * that it is.\n               */\n              if (nb == 0)\n                goto Succeed;\n            }\n          *dest-- = *pa--;\n          --na;\n          if (na == 0)\n            goto Succeed;\n        }\n      while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);\n      ++min_gallop;     /* penalize it for leaving galloping mode */\n      m_ms->m_min_gallop = min_gallop;\n    }\n\nSucceed:\n  result = 0;\n\nFail:\n  if (nb)\n    std::copy (baseb, baseb + nb, dest-(nb-1));\n  return result;\n\nCopyA:\n  /* The first element of pb belongs at the front of the merge. */\n  dest = std::copy_backward (pa+1 - na, pa+1, dest+1) - 1;\n  pa -= na;\n  *dest = *pb;\n\n  return 0;\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_hi (T *pa, octave_idx_type *ipa, octave_idx_type na,\n                          T *pb, octave_idx_type *ipb, octave_idx_type nb,\n                          Comp comp)\n{\n  octave_idx_type k;\n  T *dest;\n  octave_idx_type *idest;\n  int result = -1;      /* guilty until proved innocent */\n  T *basea, *baseb;\n  octave_idx_type *ibaseb;\n  octave_idx_type min_gallop = m_ms->m_min_gallop;\n\n  m_ms->getmemi (nb);\n\n  dest = pb + nb - 1;\n  idest = ipb + nb - 1;\n  std::copy (pb, pb + nb, m_ms->m_a);\n  std::copy (ipb, ipb + nb, m_ms->m_ia);\n  basea = pa;\n  baseb = m_ms->m_a; ibaseb = m_ms->m_ia;\n  pb = m_ms->m_a + nb - 1; ipb = m_ms->m_ia + nb - 1;\n  pa += na - 1; ipa += na - 1;\n\n  *dest-- = *pa--; *idest-- = *ipa--;\n  --na;\n  if (na == 0)\n    goto Succeed;\n  if (nb == 1)\n    goto CopyA;\n\n  for (;;)\n    {\n      octave_idx_type acount = 0;       /* # of times A won in a row */\n      octave_idx_type bcount = 0;       /* # of times B won in a row */\n\n      /* Do the straightforward thing until (if ever) one run\n       * appears to win consistently.\n       */\n      for (;;)\n        {\n          if (comp (*pb, *pa))\n            {\n              *dest-- = *pa--; *idest-- = *ipa--;\n              ++acount;\n              bcount = 0;\n              --na;\n              if (na == 0)\n                goto Succeed;\n              if (acount >= min_gallop)\n                break;\n            }\n          else\n            {\n              *dest-- = *pb--; *idest-- = *ipb--;\n              ++bcount;\n              acount = 0;\n              --nb;\n              if (nb == 1)\n                goto CopyA;\n              if (bcount >= min_gallop)\n                break;\n            }\n        }\n\n      /* One run is winning so consistently that galloping may\n       * be a huge win.  So try that, and continue galloping until\n       * (if ever) neither run appears to be winning consistently\n       * anymore.\n       */\n      ++min_gallop;\n      do\n        {\n          min_gallop -= (min_gallop > 1);\n          m_ms->m_min_gallop = min_gallop;\n          k = gallop_right (*pb, basea, na, na-1, comp);\n          if (k < 0)\n            goto Fail;\n          k = na - k;\n          acount = k;\n          if (k)\n            {\n              dest = std::copy_backward (pa+1 - k, pa+1, dest+1) - 1;\n              idest = std::copy_backward (ipa+1 - k, ipa+1, idest+1) - 1;\n              pa -= k; ipa -= k;\n              na -= k;\n              if (na == 0)\n                goto Succeed;\n            }\n          *dest-- = *pb--; *idest-- = *ipb--;\n          --nb;\n          if (nb == 1)\n            goto CopyA;\n\n          k = gallop_left (*pa, baseb, nb, nb-1, comp);\n          if (k < 0)\n            goto Fail;\n          k = nb - k;\n          bcount = k;\n          if (k)\n            {\n              dest -= k; idest -= k;\n              pb -= k; ipb -= k;\n              std::copy (pb+1, pb+1 + k, dest+1);\n              std::copy (ipb+1, ipb+1 + k, idest+1);\n              nb -= k;\n              if (nb == 1)\n                goto CopyA;\n              /* nb==0 is impossible now if the comparison\n               * function is consistent, but we can't assume\n               * that it is.\n               */\n              if (nb == 0)\n                goto Succeed;\n            }\n          *dest-- = *pa--; *idest-- = *ipa--;\n          --na;\n          if (na == 0)\n            goto Succeed;\n        }\n      while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);\n      ++min_gallop;     /* penalize it for leaving galloping mode */\n      m_ms->m_min_gallop = min_gallop;\n    }\n\nSucceed:\n  result = 0;\n\nFail:\n  if (nb)\n    {\n      std::copy (baseb, baseb + nb, dest-(nb-1));\n      std::copy (ibaseb, ibaseb + nb, idest-(nb-1));\n    }\n  return result;\n\nCopyA:\n  /* The first element of pb belongs at the front of the merge. */\n  dest = std::copy_backward (pa+1 - na, pa+1, dest+1) - 1;\n  idest = std::copy_backward (ipa+1 - na, ipa+1, idest+1) - 1;\n  pa -= na; ipa -= na;\n  *dest = *pb; *idest = *ipb;\n\n  return 0;\n}\n\n/* Merge the two runs at stack indices i and i+1.\n * Returns 0 on success, -1 on error.\n */\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_at (octave_idx_type i, T *data,\n                          Comp comp)\n{\n  T *pa, *pb;\n  octave_idx_type na, nb;\n  octave_idx_type k;\n\n  pa = data + m_ms->m_pending[i].m_base;\n  na = m_ms->m_pending[i].m_len;\n  pb = data + m_ms->m_pending[i+1].m_base;\n  nb = m_ms->m_pending[i+1].m_len;\n\n  /* Record the length of the combined runs; if i is the 3rd-last\n   * run now, also slide over the last run (which isn't involved\n   * in this merge).  The current run i+1 goes away in any case.\n   */\n  m_ms->m_pending[i].m_len = na + nb;\n  if (i == m_ms->m_n - 3)\n    m_ms->m_pending[i+1] = m_ms->m_pending[i+2];\n  m_ms->m_n--;\n\n  /* Where does b start in a?  Elements in a before that can be\n   * ignored (already in place).\n   */\n  k = gallop_right (*pb, pa, na, 0, comp);\n  if (k < 0)\n    return -1;\n  pa += k;\n  na -= k;\n  if (na == 0)\n    return 0;\n\n  /* Where does a end in b?  Elements in b after that can be\n   * ignored (already in place).\n   */\n  nb = gallop_left (pa[na-1], pb, nb, nb-1, comp);\n  if (nb <= 0)\n    return nb;\n\n  /* Merge what remains of the runs, using a temp array with\n   * min (na, nb) elements.\n   */\n  if (na <= nb)\n    return merge_lo (pa, na, pb, nb, comp);\n  else\n    return merge_hi (pa, na, pb, nb, comp);\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_at (octave_idx_type i, T *data, octave_idx_type *idx,\n                          Comp comp)\n{\n  T *pa, *pb;\n  octave_idx_type *ipa, *ipb;\n  octave_idx_type na, nb;\n  octave_idx_type k;\n\n  pa = data + m_ms->m_pending[i].m_base;\n  ipa = idx + m_ms->m_pending[i].m_base;\n  na = m_ms->m_pending[i].m_len;\n  pb = data + m_ms->m_pending[i+1].m_base;\n  ipb = idx + m_ms->m_pending[i+1].m_base;\n  nb = m_ms->m_pending[i+1].m_len;\n\n  /* Record the length of the combined runs; if i is the 3rd-last\n   * run now, also slide over the last run (which isn't involved\n   * in this merge).  The current run i+1 goes away in any case.\n   */\n  m_ms->m_pending[i].m_len = na + nb;\n  if (i == m_ms->m_n - 3)\n    m_ms->m_pending[i+1] = m_ms->m_pending[i+2];\n  m_ms->m_n--;\n\n  /* Where does b start in a?  Elements in a before that can be\n   * ignored (already in place).\n   */\n  k = gallop_right (*pb, pa, na, 0, comp);\n  if (k < 0)\n    return -1;\n  pa += k; ipa += k;\n  na -= k;\n  if (na == 0)\n    return 0;\n\n  /* Where does a end in b?  Elements in b after that can be\n   * ignored (already in place).\n   */\n  nb = gallop_left (pa[na-1], pb, nb, nb-1, comp);\n  if (nb <= 0)\n    return nb;\n\n  /* Merge what remains of the runs, using a temp array with\n   * min (na, nb) elements.\n   */\n  if (na <= nb)\n    return merge_lo (pa, ipa, na, pb, ipb, nb, comp);\n  else\n    return merge_hi (pa, ipa, na, pb, ipb, nb, comp);\n}\n\n/* Examine the stack of runs waiting to be merged, merging adjacent runs\n * until the stack invariants are re-established:\n *\n * 1. len[-3] > len[-2] + len[-1]\n * 2. len[-2] > len[-1]\n *\n * See listsort.txt for more info.\n *\n * Returns 0 on success, -1 on error.\n */\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_collapse (T *data, Comp comp)\n{\n  struct s_slice *p = m_ms->m_pending;\n\n  while (m_ms->m_n > 1)\n    {\n      octave_idx_type n = m_ms->m_n - 2;\n      if (n > 0 && p[n-1].m_len <= p[n].m_len + p[n+1].m_len)\n        {\n          if (p[n-1].m_len < p[n+1].m_len)\n            --n;\n          if (merge_at (n, data, comp) < 0)\n            return -1;\n        }\n      else if (p[n].m_len <= p[n+1].m_len)\n        {\n          if (merge_at (n, data, comp) < 0)\n            return -1;\n        }\n      else\n        break;\n    }\n\n  return 0;\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_collapse (T *data, octave_idx_type *idx, Comp comp)\n{\n  struct s_slice *p = m_ms->m_pending;\n\n  while (m_ms->m_n > 1)\n    {\n      octave_idx_type n = m_ms->m_n - 2;\n      if (n > 0 && p[n-1].m_len <= p[n].m_len + p[n+1].m_len)\n        {\n          if (p[n-1].m_len < p[n+1].m_len)\n            --n;\n          if (merge_at (n, data, idx, comp) < 0)\n            return -1;\n        }\n      else if (p[n].m_len <= p[n+1].m_len)\n        {\n          if (merge_at (n, data, idx, comp) < 0)\n            return -1;\n        }\n      else\n        break;\n    }\n\n  return 0;\n}\n\n/* Regardless of invariants, merge all runs on the stack until only one\n * remains.  This is used at the end of the mergesort.\n *\n * Returns 0 on success, -1 on error.\n */\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_force_collapse (T *data, Comp comp)\n{\n  struct s_slice *p = m_ms->m_pending;\n\n  while (m_ms->m_n > 1)\n    {\n      octave_idx_type n = m_ms->m_n - 2;\n      if (n > 0 && p[n-1].m_len < p[n+1].m_len)\n        --n;\n      if (merge_at (n, data, comp) < 0)\n        return -1;\n    }\n\n  return 0;\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nint\noctave_sort<T>::merge_force_collapse (T *data, octave_idx_type *idx, Comp comp)\n{\n  struct s_slice *p = m_ms->m_pending;\n\n  while (m_ms->m_n > 1)\n    {\n      octave_idx_type n = m_ms->m_n - 2;\n      if (n > 0 && p[n-1].m_len < p[n+1].m_len)\n        --n;\n      if (merge_at (n, data, idx, comp) < 0)\n        return -1;\n    }\n\n  return 0;\n}\n\n/* Compute a good value for the minimum run length; natural runs shorter\n * than this are boosted artificially via binary insertion.\n *\n * If n < 64, return n (it's too small to bother with fancy stuff).\n * Else if n is an exact power of 2, return 32.\n * Else return an int k, 32 <= k <= 64, such that n/k is close to, but\n * strictly less than, an exact power of 2.\n *\n * See listsort.txt for more info.\n */\ntemplate <typename T>\noctave_idx_type\noctave_sort<T>::merge_compute_minrun (octave_idx_type n)\n{\n  octave_idx_type r = 0;        /* becomes 1 if any 1 bits are shifted off */\n\n  while (n >= 64)\n    {\n      r |= n & 1;\n      n >>= 1;\n    }\n\n  return n + r;\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nvoid\noctave_sort<T>::sort (T *data, octave_idx_type nel, Comp comp)\n{\n  /* Re-initialize the Mergestate as this might be the second time called */\n  if (! m_ms) m_ms = new MergeState;\n\n  m_ms->reset ();\n  m_ms->getmem (MERGESTATE_TEMP_SIZE);\n\n  if (nel > 1)\n    {\n      octave_idx_type nremaining = nel;\n      octave_idx_type lo = 0;\n\n      /* March over the array once, left to right, finding natural runs,\n       * and extending short natural runs to minrun elements.\n       */\n      octave_idx_type minrun = merge_compute_minrun (nremaining);\n      do\n        {\n          bool descending;\n          octave_idx_type n;\n\n          /* Identify next run. */\n          n = count_run (data + lo, nremaining, descending, comp);\n          if (n < 0)\n            return;\n          if (descending)\n            std::reverse (data + lo, data + lo + n);\n          /* If short, extend to min (minrun, nremaining). */\n          if (n < minrun)\n            {\n              const octave_idx_type force = (nremaining <= minrun ? nremaining\n                                                                  : minrun);\n              binarysort (data + lo, force, n, comp);\n              n = force;\n            }\n          /* Push run onto m_pending-runs stack, and maybe merge. */\n          liboctave_panic_unless (m_ms->m_n < MAX_MERGE_PENDING);\n          m_ms->m_pending[m_ms->m_n].m_base = lo;\n          m_ms->m_pending[m_ms->m_n].m_len = n;\n          m_ms->m_n++;\n          if (merge_collapse (data, comp) < 0)\n            return;\n          /* Advance to find next run. */\n          lo += n;\n          nremaining -= n;\n        }\n      while (nremaining);\n\n      merge_force_collapse (data, comp);\n    }\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nvoid\noctave_sort<T>::sort (T *data, octave_idx_type *idx, octave_idx_type nel,\n                      Comp comp)\n{\n  /* Re-initialize the Mergestate as this might be the second time called */\n  if (! m_ms) m_ms = new MergeState;\n\n  m_ms->reset ();\n  m_ms->getmemi (MERGESTATE_TEMP_SIZE);\n\n  if (nel > 1)\n    {\n      octave_idx_type nremaining = nel;\n      octave_idx_type lo = 0;\n\n      /* March over the array once, left to right, finding natural runs,\n       * and extending short natural runs to minrun elements.\n       */\n      octave_idx_type minrun = merge_compute_minrun (nremaining);\n      do\n        {\n          bool descending;\n          octave_idx_type n;\n\n          /* Identify next run. */\n          n = count_run (data + lo, nremaining, descending, comp);\n          if (n < 0)\n            return;\n          if (descending)\n            {\n              std::reverse (data + lo, data + lo + n);\n              std::reverse (idx + lo, idx + lo + n);\n            }\n          /* If short, extend to min (minrun, nremaining). */\n          if (n < minrun)\n            {\n              const octave_idx_type force = (nremaining <= minrun ? nremaining\n                                                                  : minrun);\n              binarysort (data + lo, idx + lo, force, n, comp);\n              n = force;\n            }\n          /* Push run onto m_pending-runs stack, and maybe merge. */\n          liboctave_panic_unless (m_ms->m_n < MAX_MERGE_PENDING);\n          m_ms->m_pending[m_ms->m_n].m_base = lo;\n          m_ms->m_pending[m_ms->m_n].m_len = n;\n          m_ms->m_n++;\n          if (merge_collapse (data, idx, comp) < 0)\n            return;\n          /* Advance to find next run. */\n          lo += n;\n          nremaining -= n;\n        }\n      while (nremaining);\n\n      merge_force_collapse (data, idx, comp);\n    }\n}\n\ntemplate <typename T>\nusing compare_fcn_ptr = bool (*) (typename ref_param<T>::type,\n                                  typename ref_param<T>::type);\n\ntemplate <typename T>\nvoid\noctave_sort<T>::sort (T *data, octave_idx_type nel)\n{\n#if defined (INLINE_ASCENDING_SORT)\n  if (*m_compare.template target<compare_fcn_ptr<T>> () == ascending_compare)\n    sort (data, nel, std::less<T> ());\n  else\n#endif\n#if defined (INLINE_DESCENDING_SORT)\n    if (*m_compare.template target<compare_fcn_ptr<T>> () == descending_compare)\n      sort (data, nel, std::greater<T> ());\n    else\n#endif\n      if (m_compare)\n        sort (data, nel, m_compare);\n}\n\ntemplate <typename T>\nvoid\noctave_sort<T>::sort (T *data, octave_idx_type *idx, octave_idx_type nel)\n{\n#if defined (INLINE_ASCENDING_SORT)\n  if (*m_compare.template target<compare_fcn_ptr<T>> () == ascending_compare)\n    sort (data, idx, nel, std::less<T> ());\n  else\n#endif\n#if defined (INLINE_DESCENDING_SORT)\n    if (*m_compare.template target<compare_fcn_ptr<T>> () == descending_compare)\n      sort (data, idx, nel, std::greater<T> ());\n    else\n#endif\n      if (m_compare)\n        sort (data, idx, nel, m_compare);\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nbool\noctave_sort<T>::issorted (const T *data, octave_idx_type nel, Comp comp)\n{\n  const T *end = data + nel;\n  if (data != end)\n    {\n      const T *next = data;\n      while (++next != end)\n        {\n          if (comp (*next, *data))\n            break;\n          data = next;\n        }\n      data = next;\n    }\n\n  return data == end;\n}\n\ntemplate <typename T>\nbool\noctave_sort<T>::issorted (const T *data, octave_idx_type nel)\n{\n  bool retval = false;\n#if defined (INLINE_ASCENDING_SORT)\n  if (*m_compare.template target<compare_fcn_ptr<T>> () == ascending_compare)\n    retval = issorted (data, nel, std::less<T> ());\n  else\n#endif\n#if defined (INLINE_DESCENDING_SORT)\n    if (*m_compare.template target<compare_fcn_ptr<T>> () == descending_compare)\n      retval = issorted (data, nel, std::greater<T> ());\n    else\n#endif\n      if (m_compare)\n        retval = issorted (data, nel, m_compare);\n\n  return retval;\n}\n\nstruct sortrows_run_t\n{\npublic:\n  sortrows_run_t (octave_idx_type c, octave_idx_type o, octave_idx_type n)\n    : col (c), ofs (o), nel (n) { }\n  //--------\n  octave_idx_type col, ofs, nel;\n};\n\ntemplate <typename T>\ntemplate <typename Comp>\nvoid\noctave_sort<T>::sort_rows (const T *data, octave_idx_type *idx,\n                           octave_idx_type rows, octave_idx_type cols,\n                           Comp comp)\n{\n  OCTAVE_LOCAL_BUFFER (T, buf, rows);\n  for (octave_idx_type i = 0; i < rows; i++)\n    idx[i] = i;\n\n  if (cols == 0 || rows <= 1)\n    return;\n\n  // This is a breadth-first traversal.\n  typedef sortrows_run_t run_t;\n  std::stack<run_t> runs;\n\n  runs.push (run_t (0, 0, rows));\n\n  while (! runs.empty ())\n    {\n      octave_idx_type col = runs.top ().col;\n      octave_idx_type ofs = runs.top ().ofs;\n      octave_idx_type nel = runs.top ().nel;\n      runs.pop ();\n      liboctave_panic_unless (nel > 1);\n\n      T *lbuf = buf + ofs;\n      const T *ldata = data + rows*col;\n      octave_idx_type *lidx = idx + ofs;\n\n      // Gather.\n      for (octave_idx_type i = 0; i < nel; i++)\n        lbuf[i] = ldata[lidx[i]];\n\n      // Sort.\n      sort (lbuf, lidx, nel, comp);\n\n      // Identify constant runs and schedule subsorts.\n      if (col < cols-1)\n        {\n          octave_idx_type lst = 0;\n          for (octave_idx_type i = 0; i < nel; i++)\n            {\n              if (comp (lbuf[lst], lbuf[i]))\n                {\n                  if (i > lst + 1)\n                    runs.push (run_t (col+1, ofs + lst, i - lst));\n                  lst = i;\n                }\n            }\n          if (nel > lst + 1)\n            runs.push (run_t (col+1, ofs + lst, nel - lst));\n        }\n    }\n}\n\ntemplate <typename T>\nvoid\noctave_sort<T>::sort_rows (const T *data, octave_idx_type *idx,\n                           octave_idx_type rows, octave_idx_type cols)\n{\n#if defined (INLINE_ASCENDING_SORT)\n  if (*m_compare.template target<compare_fcn_ptr<T>> () == ascending_compare)\n    sort_rows (data, idx, rows, cols, std::less<T> ());\n  else\n#endif\n#if defined (INLINE_DESCENDING_SORT)\n    if (*m_compare.template target<compare_fcn_ptr<T>> () == descending_compare)\n      sort_rows (data, idx, rows, cols, std::greater<T> ());\n    else\n#endif\n      if (m_compare)\n        sort_rows (data, idx, rows, cols, m_compare);\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nbool\noctave_sort<T>::is_sorted_rows (const T *data, octave_idx_type rows,\n                                octave_idx_type cols, Comp comp)\n{\n  if (rows <= 1 || cols == 0)\n    return true;\n\n  // This is a breadth-first traversal.\n  const T *lastrow = data + rows*(cols - 1);\n  typedef std::pair<const T *, octave_idx_type> run_t;\n  std::stack<run_t> runs;\n\n  bool sorted = true;\n  runs.push (run_t (data, rows));\n  while (sorted && ! runs.empty ())\n    {\n      const T *lo = runs.top ().first;\n      octave_idx_type n = runs.top ().second;\n      runs.pop ();\n      if (lo < lastrow)\n        {\n          // Not the final column.\n          liboctave_panic_unless (n > 1);\n          const T *hi = lo + n;\n          const T *lst = lo;\n          for (lo++; lo < hi; lo++)\n            {\n              if (comp (*lst, *lo))\n                {\n                  if (lo > lst + 1)\n                    runs.push (run_t (lst + rows, lo - lst));\n                  lst = lo;\n                }\n              else if (comp (*lo, *lst))\n                break;\n\n            }\n          if (lo == hi)\n            {\n              if (lo > lst + 1)\n                runs.push (run_t (lst + rows, lo - lst));\n            }\n          else\n            {\n              sorted = false;\n              break;\n            }\n        }\n      else\n        // The final column - use fast code.\n        sorted = issorted (lo, n, comp);\n    }\n\n  return sorted;\n}\n\ntemplate <typename T>\nbool\noctave_sort<T>::is_sorted_rows (const T *data, octave_idx_type rows,\n                                octave_idx_type cols)\n{\n  bool retval = false;\n#if defined (INLINE_ASCENDING_SORT)\n  if (*m_compare.template target<compare_fcn_ptr<T>> () == ascending_compare)\n    retval = is_sorted_rows (data, rows, cols, std::less<T> ());\n  else\n#endif\n#if defined (INLINE_DESCENDING_SORT)\n    if (*m_compare.template target<compare_fcn_ptr<T>> () == descending_compare)\n      retval = is_sorted_rows (data, rows, cols, std::greater<T> ());\n    else\n#endif\n      if (m_compare)\n        retval = is_sorted_rows (data, rows, cols, m_compare);\n\n  return retval;\n}\n\n// The simple binary lookup.\n\ntemplate <typename T>\ntemplate <typename Comp>\noctave_idx_type\noctave_sort<T>::lookup (const T *data, octave_idx_type nel,\n                        const T& value, Comp comp)\n{\n  octave_idx_type lo = 0;\n  octave_idx_type hi = nel;\n\n  while (lo < hi)\n    {\n      octave_idx_type mid = lo + ((hi-lo) >> 1);\n      if (comp (value, data[mid]))\n        hi = mid;\n      else\n        lo = mid + 1;\n    }\n\n  return lo;\n}\n\ntemplate <typename T>\noctave_idx_type\noctave_sort<T>::lookup (const T *data, octave_idx_type nel,\n                        const T& value)\n{\n  octave_idx_type retval = 0;\n#if defined (INLINE_ASCENDING_SORT)\n  if (*m_compare.template target<compare_fcn_ptr<T>> () == ascending_compare)\n    retval = lookup (data, nel, value, std::less<T> ());\n  else\n#endif\n#if defined (INLINE_DESCENDING_SORT)\n    if (*m_compare.template target<compare_fcn_ptr<T>> () == descending_compare)\n      retval = lookup (data, nel, value, std::greater<T> ());\n    else\n#endif\n      if (m_compare)\n        retval = lookup (data, nel, value, m_compare);\n\n  return retval;\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nvoid\noctave_sort<T>::lookup (const T *data, octave_idx_type nel,\n                        const T *values, octave_idx_type nvalues,\n                        octave_idx_type *idx, Comp comp)\n{\n  // Use a sequence of binary lookups.\n  // FIXME: Can this be sped up generally?  The sorted merge case is dealt with\n  // elsewhere.\n  for (octave_idx_type j = 0; j < nvalues; j++)\n    idx[j] = lookup (data, nel, values[j], comp);\n}\n\ntemplate <typename T>\nvoid\noctave_sort<T>::lookup (const T *data, octave_idx_type nel,\n                        const T *values, octave_idx_type nvalues,\n                        octave_idx_type *idx)\n{\n#if defined (INLINE_ASCENDING_SORT)\n  if (*m_compare.template target<compare_fcn_ptr<T>> () == ascending_compare)\n    lookup (data, nel, values, nvalues, idx, std::less<T> ());\n  else\n#endif\n#if defined (INLINE_DESCENDING_SORT)\n    if (*m_compare.template target<compare_fcn_ptr<T>> () == descending_compare)\n      lookup (data, nel, values, nvalues, idx, std::greater<T> ());\n    else\n#endif\n      if (m_compare)\n        lookup (data, nel, values, nvalues, idx, m_compare);\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nvoid\noctave_sort<T>::lookup_sorted (const T *data, octave_idx_type nel,\n                               const T *values, octave_idx_type nvalues,\n                               octave_idx_type *idx, bool rev, Comp comp)\n{\n  if (rev)\n    {\n      octave_idx_type i = 0;\n      octave_idx_type j = nvalues - 1;\n\n      if (nvalues > 0 && nel > 0)\n        {\n          while (true)\n            {\n              if (comp (values[j], data[i]))\n                {\n                  idx[j] = i;\n                  if (--j < 0)\n                    break;\n                }\n              else if (++i == nel)\n                break;\n            }\n        }\n\n      for (; j >= 0; j--)\n        idx[j] = i;\n    }\n  else\n    {\n      octave_idx_type i = 0;\n      octave_idx_type j = 0;\n\n      if (nvalues > 0 && nel > 0)\n        {\n          while (true)\n            {\n              if (comp (values[j], data[i]))\n                {\n                  idx[j] = i;\n                  if (++j == nvalues)\n                    break;\n                }\n              else if (++i == nel)\n                break;\n            }\n        }\n\n      for (; j != nvalues; j++)\n        idx[j] = i;\n    }\n}\n\ntemplate <typename T>\nvoid\noctave_sort<T>::lookup_sorted (const T *data, octave_idx_type nel,\n                               const T *values, octave_idx_type nvalues,\n                               octave_idx_type *idx, bool rev)\n{\n#if defined (INLINE_ASCENDING_SORT)\n  if (*m_compare.template target<compare_fcn_ptr<T>> () == ascending_compare)\n    lookup_sorted (data, nel, values, nvalues, idx, rev, std::less<T> ());\n  else\n#endif\n#if defined (INLINE_DESCENDING_SORT)\n    if (*m_compare.template target<compare_fcn_ptr<T>> () == descending_compare)\n      lookup_sorted (data, nel, values, nvalues, idx, rev, std::greater<T> ());\n    else\n#endif\n      if (m_compare)\n        lookup_sorted (data, nel, values, nvalues, idx, rev, m_compare);\n}\n\ntemplate <typename T>\ntemplate <typename Comp>\nvoid\noctave_sort<T>::nth_element (T *data, octave_idx_type nel,\n                             octave_idx_type lo, octave_idx_type up,\n                             Comp comp)\n{\n  // Simply wrap the STL algorithms.\n  // FIXME: this will fail if we attempt to inline <,> for Complex.\n  if (up == lo+1)\n    std::nth_element (data, data + lo, data + nel, comp);\n  else if (lo == 0)\n    std::partial_sort (data, data + up, data + nel, comp);\n  else\n    {\n      std::nth_element (data, data + lo, data + nel, comp);\n      if (up == lo + 2)\n        {\n          // Finding two subsequent elements.\n          std::swap (data[lo+1],\n                     *std::min_element (data + lo + 1, data + nel, comp));\n        }\n      else\n        std::partial_sort (data + lo + 1, data + up, data + nel, comp);\n    }\n}\n\ntemplate <typename T>\nvoid\noctave_sort<T>::nth_element (T *data, octave_idx_type nel,\n                             octave_idx_type lo, octave_idx_type up)\n{\n  if (up < 0)\n    up = lo + 1;\n\n#if defined (INLINE_ASCENDING_SORT)\n  if (*m_compare.template target<compare_fcn_ptr<T>> () == ascending_compare)\n    nth_element (data, nel, lo, up, std::less<T> ());\n  else\n#endif\n#if defined (INLINE_DESCENDING_SORT)\n    if (*m_compare.template target<compare_fcn_ptr<T>> () == descending_compare)\n      nth_element (data, nel, lo, up, std::greater<T> ());\n    else\n#endif\n      if (m_compare)\n        nth_element (data, nel, lo, up, m_compare);\n}\n\ntemplate <typename T>\nbool\noctave_sort<T>::ascending_compare (typename ref_param<T>::type x,\n                                   typename ref_param<T>::type y)\n{\n  return x < y;\n}\n\ntemplate <typename T>\nbool\noctave_sort<T>::descending_compare (typename ref_param<T>::type x,\n                                    typename ref_param<T>::type y)\n{\n  return x > y;\n}\n"
  },
  {
    "path": "liboctave/util/oct-sort.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2003-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n// Code stolen in large part from Python's, listobject.c, which itself had\n// no license header.  However, thanks to Tim Peters for the parts of the\n// code I ripped-off.\n//\n// As required in the Python license the short description of the changes\n// made are\n//\n// * convert the sorting code in listobject.cc into a generic class,\n//   replacing PyObject* with the type of the class T.\n//\n// The Python license is\n//\n//   PSF LICENSE AGREEMENT FOR PYTHON 2.3\n//   --------------------------------------\n//\n//   1. This LICENSE AGREEMENT is between the Python Software Foundation\n//   (\"PSF\"), and the Individual or Organization (\"Licensee\") accessing and\n//   otherwise using Python 2.3 software in source or binary form and its\n//   associated documentation.\n//\n//   2. Subject to the terms and conditions of this License Agreement, PSF\n//   hereby grants Licensee a nonexclusive, royalty-free, world-wide\n//   license to reproduce, analyze, test, perform and/or display publicly,\n//   prepare derivative works, distribute, and otherwise use Python 2.3\n//   alone or in any derivative version, provided, however, that PSF's\n//   License Agreement and PSF's notice of copyright, i.e., \"Copyright (c)\n//   2001, 2002, 2003 Python Software Foundation; All Rights Reserved\" are\n//   retained in Python 2.3 alone or in any derivative version prepared by\n//   Licensee.\n//\n//   3. In the event Licensee prepares a derivative work that is based on\n//   or incorporates Python 2.3 or any part thereof, and wants to make\n//   the derivative work available to others as provided herein, then\n//   Licensee hereby agrees to include in any such work a brief summary of\n//   the changes made to Python 2.3.\n//\n//   4. PSF is making Python 2.3 available to Licensee on an \"AS IS\"\n//   basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\n//   IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND\n//   DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\n//   FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.3 WILL NOT\n//   INFRINGE ANY THIRD PARTY RIGHTS.\n//\n//   5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON\n//   2.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS\n//   A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.3,\n//   OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\n//\n//   6. This License Agreement will automatically terminate upon a material\n//   breach of its terms and conditions.\n//\n//   7. Nothing in this License Agreement shall be deemed to create any\n//   relationship of agency, partnership, or joint venture between PSF and\n//   Licensee.  This License Agreement does not grant permission to use PSF\n//   trademarks or trade name in a trademark sense to endorse or promote\n//   products or services of Licensee, or any third party.\n//\n//   8. By copying, installing or otherwise using Python 2.3, Licensee\n//   agrees to be bound by the terms and conditions of this License\n//   Agreement.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_sort_h)\n#define octave_oct_sort_h 1\n\n#include \"octave-config.h\"\n\n#include <functional>\n\n#include \"oct-traits.h\"\n\n// Enum for type of sort function\nenum sortmode { UNSORTED = 0, ASCENDING, DESCENDING };\n\ntemplate <typename T>\nclass OCTAVE_TEMPLATE_API octave_sort\n{\npublic:\n\n  typedef std::function<bool (typename ref_param<T>::type,\n                              typename ref_param<T>::type)> compare_fcn_type;\n\n  octave_sort ();\n\n  octave_sort (const compare_fcn_type&);\n\n  OCTAVE_DISABLE_COPY_MOVE (octave_sort)\n\n  ~octave_sort ();\n\n  void set_compare (const compare_fcn_type& comp) { m_compare = comp; }\n\n  void set_compare (sortmode mode);\n\n  // Sort an array in-place.\n  void sort (T *data, octave_idx_type nel);\n\n  // Ditto, but also permute the passed indices (may not be valid indices).\n  void sort (T *data, octave_idx_type *idx, octave_idx_type nel);\n\n  // Check whether an array is sorted.\n  bool issorted (const T *data, octave_idx_type nel);\n\n  // Sort a matrix by rows, return a permutation\n  // vector.\n  void sort_rows (const T *data, octave_idx_type *idx,\n                  octave_idx_type rows, octave_idx_type cols);\n\n  // Determine whether a matrix (as a contiguous block) is sorted by rows.\n  bool is_sorted_rows (const T *data,\n                       octave_idx_type rows, octave_idx_type cols);\n\n  // Do a binary lookup in a sorted array.\n  octave_idx_type lookup (const T *data, octave_idx_type nel,\n                          const T& value);\n\n  // Ditto, but for an array.\n  void lookup (const T *data, octave_idx_type nel,\n               const T *values, octave_idx_type nvalues,\n               octave_idx_type *idx);\n\n  // A linear merge of two sorted tables.  rev indicates the second table is\n  // in reverse order.\n  void lookup_sorted (const T *data, octave_idx_type nel,\n                      const T *values, octave_idx_type nvalues,\n                      octave_idx_type *idx, bool rev = false);\n\n  // Rearranges the array so that the elements with indices\n  // lo..up-1 are in their correct place.\n  void nth_element (T *data, octave_idx_type nel,\n                    octave_idx_type lo, octave_idx_type up = -1);\n\n  static bool ascending_compare (typename ref_param<T>::type,\n                                 typename ref_param<T>::type);\n\n  static bool descending_compare (typename ref_param<T>::type,\n                                  typename ref_param<T>::type);\n\nprivate:\n\n  // The maximum number of entries in a MergeState's pending-runs stack.\n  // This is enough to sort arrays of size up to about\n  //     32 * phi ** MAX_MERGE_PENDING\n  // where phi ~= 1.618.  85 is ridiculously large enough, good for an array\n  // with 2^64 elements.\n  static const int MAX_MERGE_PENDING = 85;\n\n  // When we get into galloping mode, we stay there until both runs win less\n  // often than MIN_GALLOP consecutive times.  See listsort.txt for more info.\n  static const int MIN_GALLOP = 7;\n\n  // Avoid malloc for small temp arrays.\n  static const int MERGESTATE_TEMP_SIZE = 1024;\n\n  // One MergeState exists on the stack per invocation of mergesort.\n  // It's just a convenient way to pass state around among the helper\n  // functions.\n  //\n  // DGB: This isn't needed with mergesort in a class, but it doesn't\n  // slow things up, and it is likely to make my life easier for any\n  // potential backporting of changes in the Python code.\n\n  struct s_slice\n  {\n    octave_idx_type m_base, m_len;\n  };\n\n  struct MergeState\n  {\n  public:\n\n    MergeState ()\n      : m_min_gallop (), m_a (nullptr), m_ia (nullptr), m_alloced (0), m_n (0)\n    { reset (); }\n\n    OCTAVE_DISABLE_COPY_MOVE (MergeState)\n\n    ~MergeState ()\n    { delete [] m_a; delete [] m_ia; }\n\n    void reset ()\n    { m_min_gallop = MIN_GALLOP; m_n = 0; }\n\n    void getmem (octave_idx_type need);\n\n    void getmemi (octave_idx_type need);\n\n    //--------\n\n    // This controls when we get *into* galloping mode.  It's initialized to\n    // MIN_GALLOP.  merge_lo and merge_hi tend to nudge it higher for random\n    // data, and lower for highly structured data.\n    octave_idx_type m_min_gallop;\n\n    // 'a' is temp storage to help with merges.  It contains room for\n    // alloced entries.\n    T *m_a;               // may point to temparray below\n    octave_idx_type *m_ia;\n    octave_idx_type m_alloced;\n\n    // A stack of n pending runs yet to be merged.  Run #i starts at address\n    // base[i] and extends for len[i] elements.  It's always true (so long as\n    // the indices are in bounds) that\n    //\n    //   pending[i].base + pending[i].len == pending[i+1].base\n    //\n    // so we could cut the storage for this, but it's a minor amount,\n    // and keeping all the info explicit simplifies the code.\n    octave_idx_type m_n;\n    struct s_slice m_pending[MAX_MERGE_PENDING];\n  };\n\n  compare_fcn_type m_compare;\n\n  MergeState *m_ms;\n\n  template <typename Comp>\n  void binarysort (T *data, octave_idx_type nel,\n                   octave_idx_type start, Comp comp);\n\n  template <typename Comp>\n  void binarysort (T *data, octave_idx_type *idx, octave_idx_type nel,\n                   octave_idx_type start, Comp comp);\n\n  template <typename Comp>\n  octave_idx_type count_run (T *lo, octave_idx_type n, bool& descending,\n                             Comp comp);\n\n  template <typename Comp>\n  octave_idx_type gallop_left (T key, T *a, octave_idx_type n,\n                               octave_idx_type hint, Comp comp);\n\n  template <typename Comp>\n  octave_idx_type gallop_right (T key, T *a, octave_idx_type n,\n                                octave_idx_type hint, Comp comp);\n\n  template <typename Comp>\n  int merge_lo (T *pa, octave_idx_type na,\n                T *pb, octave_idx_type nb,\n                Comp comp);\n\n  template <typename Comp>\n  int merge_lo (T *pa, octave_idx_type *ipa, octave_idx_type na,\n                T *pb, octave_idx_type *ipb, octave_idx_type nb,\n                Comp comp);\n\n  template <typename Comp>\n  int merge_hi (T *pa, octave_idx_type na,\n                T *pb, octave_idx_type nb,\n                Comp comp);\n\n  template <typename Comp>\n  int merge_hi (T *pa, octave_idx_type *ipa, octave_idx_type na,\n                T *pb, octave_idx_type *ipb, octave_idx_type nb,\n                Comp comp);\n\n  template <typename Comp>\n  int merge_at (octave_idx_type i, T *data, Comp comp);\n\n  template <typename Comp>\n  int merge_at (octave_idx_type i, T *data, octave_idx_type *idx, Comp comp);\n\n  template <typename Comp>\n  int merge_collapse (T *data, Comp comp);\n\n  template <typename Comp>\n  int merge_collapse (T *data, octave_idx_type *idx, Comp comp);\n\n  template <typename Comp>\n  int merge_force_collapse (T *data, Comp comp);\n\n  template <typename Comp>\n  int merge_force_collapse (T *data, octave_idx_type *idx, Comp comp);\n\n  octave_idx_type merge_compute_minrun (octave_idx_type n);\n\n  template <typename Comp>\n  void sort (T *data, octave_idx_type nel, Comp comp);\n\n  template <typename Comp>\n  void sort (T *data, octave_idx_type *idx, octave_idx_type nel, Comp comp);\n\n  template <typename Comp>\n  bool issorted (const T *data, octave_idx_type nel, Comp comp);\n\n  template <typename Comp>\n  void sort_rows (const T *data, octave_idx_type *idx,\n                  octave_idx_type rows, octave_idx_type cols,\n                  Comp comp);\n\n  template <typename Comp>\n  bool is_sorted_rows (const T *data, octave_idx_type rows,\n                       octave_idx_type cols, Comp comp);\n\n  template <typename Comp>\n  octave_idx_type lookup (const T *data, octave_idx_type nel,\n                          const T& value, Comp comp);\n\n  template <typename Comp>\n  void lookup (const T *data, octave_idx_type nel,\n               const T *values, octave_idx_type nvalues,\n               octave_idx_type *idx, Comp comp);\n\n  template <typename Comp>\n  void lookup_sorted (const T *data, octave_idx_type nel,\n                      const T *values, octave_idx_type nvalues,\n                      octave_idx_type *idx, bool rev, Comp comp);\n\n  template <typename Comp>\n  void nth_element (T *data, octave_idx_type nel,\n                    octave_idx_type lo, octave_idx_type up,\n                    Comp comp);\n};\n\ntemplate <typename T>\nclass OCTAVE_TEMPLATE_API vec_index\n{\npublic:\n  T m_vec;\n  octave_idx_type m_indx;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-sparse.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-error.h\"\n#include \"oct-sparse.h\"\n\n#if (defined (HAVE_AMD) || defined (HAVE_CCOLAMD)               \\\n     || defined (HAVE_CHOLMOD) || defined (HAVE_COLAMD)         \\\n     || defined (HAVE_CXSPARSE) || defined (HAVE_UMFPACK))\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstatic inline void\ncheck_suitesparse_integer_size ()\n{\n  // FIXME: maybe it would be better to make this a configure check and\n  // disable suitesparse if it fails?\n\n  if (sizeof (suitesparse_integer) != sizeof (octave_idx_type))\n    (*current_liboctave_error_handler)\n      (\"size of suitesparse integer does not match octave_idx_type!\");\n}\n\nsuitesparse_integer *\nto_suitesparse_intptr (octave_idx_type *i)\n{\n  check_suitesparse_integer_size ();\n\n  return reinterpret_cast<suitesparse_integer *> (i);\n}\n\nconst suitesparse_integer *\nto_suitesparse_intptr (const octave_idx_type *i)\n{\n  check_suitesparse_integer_size ();\n\n  return reinterpret_cast<const suitesparse_integer *> (i);\n}\n\noctave_idx_type *\nto_octave_idx_type_ptr (suitesparse_integer *i)\n{\n  check_suitesparse_integer_size ();\n\n  return reinterpret_cast<octave_idx_type *> (i);\n}\n\nconst octave_idx_type *\nto_octave_idx_type_ptr (const suitesparse_integer *i)\n{\n  check_suitesparse_integer_size ();\n\n  return reinterpret_cast<const octave_idx_type *> (i);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-sparse.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2005-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_sparse_h)\n#define octave_oct_sparse_h 1\n\n#include \"octave-config.h\"\n\n#include <limits>\n\n#if defined (HAVE_CHOLMOD)\n#  include \"dSparse.h\"\n#  include \"CSparse.h\"\n#endif\n\n#if defined (HAVE_SUITESPARSE_AMD_H)\n#  include <suitesparse/amd.h>\n#elif defined (HAVE_AMD_AMD_H)\n#  include <amd/amd.h>\n#elif defined (HAVE_AMD_H)\n#  include <amd.h>\n#endif\n\n#if defined (HAVE_SUITESPARSE_CCOLAMD_H)\n#  include <suitesparse/ccolamd.h>\n#elif defined (HAVE_CCOLAMD_CCOLAMD_H)\n#  include <ccolamd/ccolamd.h>\n#elif defined (HAVE_CCOLAMD_H)\n#  include <ccolamd.h>\n#endif\n\n#if defined (HAVE_SUITESPARSE_CHOLMOD_H)\n#  include <suitesparse/cholmod.h>\n#elif defined (HAVE_CHOLMOD_CHOLMOD_H)\n#  include <cholmod/cholmod.h>\n#elif defined (HAVE_CHOLMOD_H)\n#  include <cholmod.h>\n#endif\n\n#if defined (HAVE_SUITESPARSE_COLAMD_H)\n#  include <suitesparse/colamd.h>\n#elif defined (HAVE_COLAMD_COLAMD_H)\n#  include <colamd/colamd.h>\n#elif defined (HAVE_COLAMD_H)\n#  include <colamd.h>\n#endif\n\n#if defined (HAVE_SUITESPARSE_CS_H)\n#  include <suitesparse/cs.h>\n#elif defined (HAVE_CXSPARSE_CS_H)\n#  include <cxsparse/cs.h>\n#elif defined (HAVE_CS_H)\n#  include <cs.h>\n#endif\n\n#if defined (HAVE_SUITESPARSE_UMFPACK_H)\n#  include <suitesparse/umfpack.h>\n#elif defined (HAVE_UMFPACK_UMFPACK_H)\n#  include <umfpack/umfpack.h>\n#elif defined (HAVE_UMFPACK_H)\n#  include <umfpack.h>\n#endif\n\n#if defined (HAVE_SUITESPARSE_SUITESPARSEQR_HPP)\n#  include <suitesparse/SuiteSparseQR.hpp>\n#elif defined (HAVE_SUITESPARSEQR_HPP)\n#  include <SuiteSparseQR.hpp>\n#endif\n\n// Cope with API differences between SuiteSparse versions\n\n#if defined (SUITESPARSE_VERSION)\n#  if (SUITESPARSE_VERSION >= SUITESPARSE_VER_CODE (7, 0))\n#    define SUITESPARSE_NAME(name) SuiteSparse_ ## name\n#    define SUITESPARSE_SET_FCN(name) SuiteSparse_config_ ## name ## _set\n#    define SUITESPARSE_ASSIGN_FPTR(f_name, f_var, f_assign) \\\n       SUITESPARSE_SET_FCN(f_name) (f_assign)\n#    define SUITESPARSE_ASSIGN_FPTR2(f_name, f_var, f_assign) \\\n       SUITESPARSE_SET_FCN(f_name) (SUITESPARSE_NAME (f_assign))\n#  elif (SUITESPARSE_VERSION >= SUITESPARSE_VER_CODE (4, 3))\n#    define SUITESPARSE_NAME(name) SuiteSparse_ ## name\n#    define SUITESPARSE_ASSIGN_FPTR(f_name, f_var, f_assign) \\\n       (SuiteSparse_config.f_name = f_assign)\n#    define SUITESPARSE_ASSIGN_FPTR2(f_name, f_var, f_assign) \\\n       (SuiteSparse_config.f_name = SUITESPARSE_NAME (f_assign))\n#  else\n#    define SUITESPARSE_ASSIGN_FPTR(f_name, f_var, f_assign) \\\n       (f_var = f_assign)\n#    define SUITESPARSE_ASSIGN_FPTR2(f_name, f_var, f_assign) \\\n       (f_var = CHOLMOD_NAME (f_assign))\n#  endif\n#endif\n\n// Function names depend on integer type.\n\n#if defined (HAVE_AMD)\n#  if defined (OCTAVE_ENABLE_64)\n#    define AMD_NAME(name) amd_l ## name\n#  else\n#    define AMD_NAME(name) amd ## name\n#  endif\n#endif\n\n#if defined (HAVE_CCOLAMD)\n#  if defined (OCTAVE_ENABLE_64)\n#    define CCOLAMD_NAME(name) ccolamd_l ## name\n#    define CSYMAMD_NAME(name) csymamd_l ## name\n#  else\n#    define CCOLAMD_NAME(name) ccolamd ## name\n#    define CSYMAMD_NAME(name) csymamd ## name\n#  endif\n#endif\n\n#if defined (HAVE_CHOLMOD)\n#  if defined (OCTAVE_ENABLE_64)\n#    define CHOLMOD_NAME(name) cholmod_l_ ## name\n#  else\n#    define CHOLMOD_NAME(name) cholmod_ ## name\n#  endif\n#endif\n\n#if defined (HAVE_COLAMD)\n#  if defined (OCTAVE_ENABLE_64)\n#    define COLAMD_NAME(name) colamd_l ## name\n#    define SYMAMD_NAME(name) symamd_l ## name\n#  else\n#    define COLAMD_NAME(name) colamd ## name\n#    define SYMAMD_NAME(name) symamd ## name\n#  endif\n#endif\n\n#if defined (HAVE_CXSPARSE)\n#  if defined (OCTAVE_ENABLE_64)\n#    define CXSPARSE_DNAME(name) cs_dl ## name\n#    define CXSPARSE_ZNAME(name) cs_cl ## name\n#  else\n#    define CXSPARSE_DNAME(name) cs_di ## name\n#    define CXSPARSE_ZNAME(name) cs_ci ## name\n#  endif\n#endif\n\n#if defined (HAVE_UMFPACK)\n#  if defined (OCTAVE_ENABLE_64)\n#    define UMFPACK_DNAME(name) umfpack_dl_ ## name\n#    define UMFPACK_ZNAME(name) umfpack_zl_ ## name\n#  else\n#    define UMFPACK_DNAME(name) umfpack_di_ ## name\n#    define UMFPACK_ZNAME(name) umfpack_zi_ ## name\n#  endif\n#endif\n\n#if (defined (HAVE_AMD) || defined (HAVE_CCOLAMD)               \\\n     || defined (HAVE_CHOLMOD) || defined (HAVE_COLAMD)         \\\n     || defined (HAVE_CXSPARSE) || defined (HAVE_SPQR)          \\\n     || defined (HAVE_UMFPACK))\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n#  if defined (OCTAVE_ENABLE_64)\ntypedef SuiteSparse_long suitesparse_integer;\n#  else\ntypedef int suitesparse_integer;\n#  endif\n\nextern OCTAVE_API suitesparse_integer *\nto_suitesparse_intptr (octave_idx_type *i);\n\nextern const OCTAVE_API suitesparse_integer *\nto_suitesparse_intptr (const octave_idx_type *i);\n\nextern OCTAVE_API octave_idx_type *\nto_octave_idx_type_ptr (suitesparse_integer *i);\n\nextern const OCTAVE_API octave_idx_type *\nto_octave_idx_type_ptr (const suitesparse_integer *i);\n\ninline octave_idx_type\nfrom_suitesparse_long (SuiteSparse_long x)\n{\n  if (x < std::numeric_limits<octave_idx_type>::min ()\n      || x > std::numeric_limits<octave_idx_type>::max ())\n    (*current_liboctave_error_handler)\n      (\"integer dimension or index out of range for Octave's indexing type\");\n\n  return static_cast<octave_idx_type> (x);\n}\n\ninline octave_idx_type\nfrom_size_t (std::size_t x)\n{\n  // std::size_t is guaranteed to be unsigned\n  if (x > std::numeric_limits<octave_idx_type>::max ())\n    (*current_liboctave_error_handler)\n      (\"integer dimension or index out of range for Octave's index type\");\n\n  return static_cast<octave_idx_type> (x);\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-string.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-string.h\"\n\n#include <algorithm>\n#include <cctype>\n#include <cstring>\n#if defined (OCTAVE_HAVE_STD_FROM_CHARS_DOUBLE)\n#  include <charconv>\n#endif\n#include <iomanip>\n#include <string>\n#include <unordered_set>\n\n#if defined (OCTAVE_HAVE_FAST_FLOAT)\n#  include <fast_float/fast_float.h>\n#endif\n\n#include \"Array-oct.h\"\n#include \"iconv-wrappers.h\"\n#include \"lo-ieee.h\"\n#include \"mappers.h\"\n#include \"oct-locbuf.h\"\n#include \"uniconv-wrappers.h\"\n#include \"unistr-wrappers.h\"\n#include \"unwind-prot.h\"\n\ntemplate <typename T>\nstatic bool\nstr_data_cmp (const typename T::value_type *a, const typename T::value_type *b,\n              const typename T::size_type n)\n{\n  for (typename T::size_type i = 0; i < n; ++i)\n    if (a[i] != b[i])\n      return false;\n  return true;\n}\n\ntemplate <typename T>\nstatic bool\nstr_data_cmpi (const typename T::value_type *a, const typename T::value_type *b,\n               const typename T::size_type n)\n{\n  for (typename T::size_type i = 0; i < n; ++i)\n    if (std::tolower (a[i]) != std::tolower (b[i]))\n      return false;\n  return true;\n}\n\n\n// Templates to handle std::basic_string, std::vector, Array, and char*.\ntemplate <typename T>\ntypename T::size_type\nnumel (const T& str)\n{\n  return str.size ();\n}\n\ntemplate <>\noctave_idx_type\nnumel (const Array<char>& str)\n{\n  return str.numel ();\n}\n\ntemplate <typename T>\ntypename T::size_type\nstrlen (const typename T::value_type *str)\n{\n  return std::strlen (str);\n}\n\ntemplate <typename T>\nbool\nsizes_cmp (const T& str_a, const T& str_b)\n{\n  return str_a.size () == str_b.size ();\n}\n\ntemplate <>\nbool\nsizes_cmp (const Array<char>& str_a, const Array<char>& str_b)\n{\n  return str_a.dims () == str_b.dims ();\n}\n\ntemplate <typename T>\nbool\nsizes_cmp (const T& str_a, const typename T::value_type *str_b)\n{\n  return str_a.size () == strlen<T> (str_b);\n}\n\ntemplate <>\nbool\nsizes_cmp (const Array<char>& str_a, const char *str_b)\n{\n  return (str_a.isvector () && str_a.rows () == 1\n          && str_a.numel () == strlen<Array<char>> (str_b));\n}\n\n\ntemplate<typename T>\nbool\noctave::string::strcmp (const T& str_a, const T& str_b)\n{\n  return (sizes_cmp (str_a, str_b)\n          && str_data_cmp<T> (str_a.data (), str_b.data (), numel (str_a)));\n}\n\ntemplate<typename T>\nbool\noctave::string::strcmp (const T& str_a, const typename T::value_type *str_b)\n{\n  return (sizes_cmp (str_a, str_b)\n          && str_data_cmp<T> (str_a.data (), str_b, numel (str_a)));\n}\n\n\ntemplate<typename T>\nbool\noctave::string::strcmpi (const T& str_a, const T& str_b)\n{\n  return (sizes_cmp (str_a, str_b)\n          && str_data_cmpi<T> (str_a.data (), str_b.data (), numel (str_a)));\n}\n\ntemplate<typename T>\nbool\noctave::string::strcmpi (const T& str_a, const typename T::value_type *str_b)\n{\n  return (sizes_cmp (str_a, str_b)\n          && str_data_cmpi<T> (str_a.data (), str_b, numel (str_a)));\n}\n\n\ntemplate<typename T>\nbool\noctave::string::strncmp (const T& str_a, const T& str_b,\n                         const typename T::size_type n)\n{\n  typename T::size_type neff;\n  auto len_a = numel (str_a);\n  auto len_b = numel (str_b);\n  neff = std::min (std::max (len_a, len_b), n);\n\n  return (len_a >= neff && len_b >= neff\n          && str_data_cmp<T> (str_a.data (), str_b.data (), neff));\n}\n\ntemplate<typename T>\nbool\noctave::string::strncmp (const T& str_a, const typename T::value_type *str_b,\n                         const typename T::size_type n)\n{\n  typename T::size_type neff;\n  auto len_a = numel (str_a);\n  auto len_b = strlen<T> (str_b);\n  neff = std::min (std::max (len_a, len_b), n);\n\n  return (len_a >= neff && len_b >= neff\n          && str_data_cmp<T> (str_a.data (), str_b, neff));\n}\n\n\ntemplate<typename T>\nbool\noctave::string::strncmpi (const T& str_a, const T& str_b,\n                          const typename T::size_type n)\n{\n  typename T::size_type neff;\n  auto len_a = numel (str_a);\n  auto len_b = numel (str_b);\n  neff = std::min (std::max (len_a, len_b), n);\n\n  return (len_a >= neff && len_b >= neff\n          && str_data_cmpi<T> (str_a.data (), str_b.data (), neff));\n}\n\ntemplate<typename T>\nbool\noctave::string::strncmpi (const T& str_a, const typename T::value_type *str_b,\n                          const typename T::size_type n)\n{\n  typename T::size_type neff;\n  auto len_a = numel (str_a);\n  auto len_b = strlen<T> (str_b);\n  neff = std::min (std::max (len_a, len_b), n);\n\n  return (len_a >= neff && len_b >= neff\n          && str_data_cmpi<T> (str_a.data (), str_b, neff));\n}\n\n\n// Instantiations we need\n#define INSTANTIATE_OCTAVE_STRING(T, API)                                     \\\n  template API bool octave::string::strcmp<T> (const T&, const T&);           \\\n  template API bool                                                           \\\n  octave::string::strcmp<T> (const T&, const typename T::value_type*);        \\\n  template API bool octave::string::strcmpi<T> (const T&, const T&);          \\\n  template API bool                                                           \\\n  octave::string::strcmpi<T> (const T&, const typename T::value_type*);       \\\n  template API bool                                                           \\\n  octave::string::strncmp<T> (const T&, const T&,                             \\\n                              const typename T::size_type);                   \\\n  template API bool                                                           \\\n  octave::string::strncmp<T> (const T&, const typename T::value_type*,        \\\n                              const typename T::size_type);                   \\\n  template API bool                                                           \\\n  octave::string::strncmpi<T> (const T&, const T&,                            \\\n                               const typename T::size_type n);                \\\n  template API bool                                                           \\\n  octave::string::strncmpi<T> (const T&, const typename T::value_type*,       \\\n                               const typename T::size_type);\n\n// We could also instantiate std::vector<char> but would it be\n// useful for anyone?\nINSTANTIATE_OCTAVE_STRING(std::string, OCTAVE_API)\nINSTANTIATE_OCTAVE_STRING(Array<char>, OCTAVE_API)\n\n#undef INSTANTIATE_OCTAVE_STRING\n\nstatic inline bool\nis_imag_unit (int c)\n{ return c == 'i' || c == 'j'; }\n\nstatic double\nsingle_num (std::istringstream& is)\n{\n  double num = 0.0;\n\n  // Get the remaining string from current position\n  std::string str;\n  std::streampos start_pos = is.tellg ();\n  std::getline (is, str);\n\n  const char *first = str.data ();\n  const char *last = first + str.size ();\n\n  // Skip leading whitespace\n  while (first != last && std::isspace (static_cast<unsigned char> (*first)))\n    ++first;\n\n  if (first == last)\n    {\n      is.seekg (start_pos);\n      is.setstate (std::ios::failbit);\n      return num;\n    }\n\n  // Special check for \"NA\" value (not handled by from_chars)\n  if (first + 2 <= last && first[0] == 'N' && first[1] == 'A' &&\n      (first + 2 == last || std::isspace (static_cast<unsigned char> (first[2]))))\n    {\n      num = octave_NA;\n      is.seekg (start_pos + static_cast<std::streamoff> (first - str.data () + 2));\n      return num;\n    }\n\n  // Use from_chars for all other numbers (including Inf, -Inf, NaN)\n#if defined (OCTAVE_HAVE_STD_FROM_CHARS_DOUBLE)\n  auto [ptr, ec] = std::from_chars (first, last, num);\n#elif defined (OCTAVE_HAVE_FAST_FLOAT)\n  auto [ptr, ec] = fast_float::from_chars (first, last, num);\n#else\n#  error \"Cannot convert string to floating-point number.  This should be unreachable.\"\n#endif\n\n  if (ec == std::errc {})\n    {\n      // Successfully parsed a number\n      std::streamoff chars_consumed = static_cast<std::streamoff> (ptr - str.data ());\n      is.seekg (start_pos + chars_consumed);\n\n      // Check if we are at EOF after consuming the number\n      if (ptr == last)\n        is.seekg (0, std::ios::end);\n    }\n  else\n    {\n      // Parse failed\n      switch (ec)\n        {\n        case std::errc::invalid_argument:\n          // No valid number could be parsed\n          is.seekg (start_pos);\n          is.setstate (std::ios::failbit);\n          break;\n        case std::errc::result_out_of_range:\n          // Number is out of range for double\n          // Determine sign and set to appropriate infinity\n          {\n            // Check for negative sign\n            const char* p = first;\n            while (p < ptr && std::isspace (static_cast<unsigned char> (*p)))\n              ++p;\n\n            if (p < ptr && *p == '-')\n              num = -octave::numeric_limits<double>::Inf ();\n            else\n              num = octave::numeric_limits<double>::Inf ();\n\n            std::streamoff chars_consumed = static_cast<std::streamoff> (ptr - str.data ());\n            is.seekg (start_pos + chars_consumed);\n          }\n          break;\n\n        default:\n          // Unexpected error\n          is.seekg (start_pos);\n          is.setstate (std::ios::failbit);\n          break;\n        }\n    }\n  return num;\n}\n\nstatic std::istringstream&\nextract_num (std::istringstream& is, double& num, bool& imag, bool& have_sign)\n{\n  have_sign = imag = false;\n\n  char c = is.peek ();\n\n  // Skip leading spaces.\n  while (isspace (c))\n    {\n      is.get ();\n      c = is.peek ();\n    }\n\n  bool negative = false;\n\n  // Accept leading sign.\n  if (c == '+' || c == '-')\n    {\n      have_sign = true;\n      negative = c == '-';\n      is.get ();\n      c = is.peek ();\n    }\n\n  // Skip spaces after sign.\n  while (isspace (c))\n    {\n      is.get ();\n      c = is.peek ();\n    }\n\n  // Imaginary number (i*num or just i), or maybe 'inf'.\n  if (c == 'i')\n    {\n      // possible infinity.\n      is.get ();\n      c = is.peek ();\n\n      if (is.eof ())\n        {\n          // just 'i' and string is finished.  Return immediately.\n          imag = true;\n          num = (negative ? -1.0 : 1.0);\n          return is;\n        }\n      else\n        {\n          if (std::tolower (c) != 'n')\n            imag = true;\n          is.unget ();\n        }\n    }\n  else if (c == 'j')\n    imag = true;\n\n  // It's i*num or just i\n  if (imag)\n    {\n      is.get ();\n      c = is.peek ();\n      // Skip spaces after imaginary unit.\n      while (isspace (c))\n        {\n          is.get ();\n          c = is.peek ();\n        }\n\n      if (c == '*')\n        {\n          // Multiplier follows, we extract it as a number.\n          is.get ();\n          num = single_num (is);\n          if (is.good ())\n            c = is.peek ();\n        }\n      else\n        num = 1.0;\n    }\n  else\n    {\n      // It's num, num*i, or numi.\n      num = single_num (is);\n      if (is.good ())\n        {\n          c = is.peek ();\n\n          // Skip spaces after number.\n          while (isspace (c))\n            {\n              is.get ();\n              c = is.peek ();\n            }\n\n          if (c == '*')\n            {\n              is.get ();\n              c = is.peek ();\n\n              // Skip spaces after operator.\n              while (isspace (c))\n                {\n                  is.get ();\n                  c = is.peek ();\n                }\n\n              if (is_imag_unit (c))\n                {\n                  imag = true;\n                  is.get ();\n                  c = is.peek ();\n                }\n              else\n                is.setstate (std::ios::failbit); // indicate read has failed.\n            }\n          else if (is_imag_unit (c))\n            {\n              imag = true;\n              is.get ();\n              c = is.peek ();\n            }\n        }\n    }\n\n  if (is.good ())\n    {\n      // Skip trailing spaces.\n      while (isspace (c))\n        {\n          is.get ();\n          c = is.peek ();\n        }\n    }\n\n  if (negative)\n    num = -num;\n\n  return is;\n}\n\nstatic inline void\nset_component (Complex& c, double num, bool imag)\n{\n#if defined (HAVE_CXX_COMPLEX_SETTERS)\n  if (imag)\n    c.imag (num);\n  else\n    c.real (num);\n#elif defined (HAVE_CXX_COMPLEX_REFERENCE_ACCESSORS)\n  if (imag)\n    c.imag () = num;\n  else\n    c.real () = num;\n#else\n  if (imag)\n    c = Complex (c.real (), num);\n  else\n    c = Complex (num, c.imag ());\n#endif\n}\n\nComplex\noctave::string::str2double (const std::string& str_arg)\n{\n  Complex val (0.0, 0.0);\n\n  std::string str = str_arg;\n\n  // FIXME: removing all commas doesn't allow actual parsing.\n  //        Example: \"1,23.45\" is wrong, but passes Octave.\n  str.erase (std::remove (str.begin (), str.end(), ','), str.end ());\n  std::istringstream is (str);\n\n  double num;\n  bool i1, i2, s1, s2;\n\n  if (is.eof ())\n    val = octave::numeric_limits<double>::NaN ();\n  else if (! extract_num (is, num, i1, s1))\n    val = octave::numeric_limits<double>::NaN ();\n  else\n    {\n      set_component (val, num, i1);\n\n      if (! is.eof ())\n        {\n          if (! extract_num (is, num, i2, s2) || i1 == i2 || ! s2)\n            val = octave::numeric_limits<double>::NaN ();\n          else\n            set_component (val, num, i2);\n        }\n    }\n\n  return val;\n}\n\nbool\noctave::string::any_non_ascii_chars (const std::string &s)\n{\n  for (unsigned char c : s)\n    if (c & 0x80)\n      return true;\n\n  return false;\n}\n\nstd::string\noctave::string::u8_to_encoding (const std::string& who,\n                                const std::string& u8_string,\n                                const std::string& encoding)\n{\n  const uint8_t *src = reinterpret_cast<const uint8_t *>\n                       (u8_string.c_str ());\n  std::size_t srclen = u8_string.length ();\n\n  std::size_t length;\n  char *native_str = octave_u8_conv_to_encoding (encoding.c_str (), src,\n                                                 srclen, &length);\n\n  if (! native_str)\n    {\n      if (errno == ENOSYS)\n        (*current_liboctave_error_handler)\n          (\"%s: iconv() is not supported.  Installing GNU libiconv and then \"\n           \"re-compiling Octave could fix this.\", who.c_str ());\n      else\n        (*current_liboctave_error_handler)\n          (\"%s: converting from UTF-8 to codepage '%s' failed: %s\",\n           who.c_str (), encoding.c_str (), std::strerror (errno));\n    }\n\n  octave::unwind_action free_native_str ([native_str] () { ::free (native_str); });\n\n  std::string retval = std::string (native_str, length);\n\n  return retval;\n}\n\nstd::string\noctave::string::u8_from_encoding (const std::string& who,\n                                  const std::string& native_string,\n                                  const std::string& encoding)\n{\n  const char *src = native_string.c_str ();\n  std::size_t srclen = native_string.length ();\n\n  std::size_t length;\n  uint8_t *utf8_str = octave_u8_conv_from_encoding (encoding.c_str (), src,\n                                                    srclen, &length);\n  if (! utf8_str)\n    {\n      if (errno == ENOSYS)\n        (*current_liboctave_error_handler)\n          (\"%s: iconv() is not supported.  Installing GNU libiconv and then \"\n           \"re-compiling Octave could fix this.\", who.c_str ());\n      else\n        (*current_liboctave_error_handler)\n          (\"%s: converting from codepage '%s' to UTF-8 failed: %s\",\n           who.c_str (), encoding.c_str (), std::strerror (errno));\n    }\n\n  octave::unwind_action free_utf8_str ([utf8_str] () { ::free (utf8_str); });\n\n  std::string retval = std::string (reinterpret_cast<char *> (utf8_str), length);\n\n  return retval;\n}\n\nunsigned int\noctave::string::u8_validate (const std::string& who,\n                             std::string& in_str,\n                             const octave::string::u8_fallback_type type)\n{\n  std::string out_str;\n\n  unsigned int num_replacements = 0;\n  const char *in_chr = in_str.c_str ();\n  const char *inv_utf8 = in_chr;\n  const char *const in_end = in_chr + in_str.length ();\n  while (inv_utf8 && in_chr < in_end)\n    {\n      inv_utf8 = reinterpret_cast<const char *>\n          (octave_u8_check_wrapper (reinterpret_cast<const uint8_t *> (in_chr),\n                                    in_end - in_chr));\n\n      if (inv_utf8 == nullptr)\n        out_str.append (in_chr, in_end - in_chr);\n      else\n        {\n          num_replacements++;\n          out_str.append (in_chr, inv_utf8 - in_chr);\n          in_chr = inv_utf8 + 1;\n\n          if (type == U8_REPLACEMENT_CHAR)\n            out_str.append (\"\\xef\\xbf\\xbd\");\n          else if (type == U8_ISO_8859_1)\n            {\n              std::string fallback = \"iso-8859-1\";\n              std::size_t lengthp;\n              uint8_t *val_utf8 = octave_u8_conv_from_encoding\n                                    (fallback.c_str (), inv_utf8, 1, &lengthp);\n\n              if (! val_utf8)\n                (*current_liboctave_error_handler)\n                  (\"%s: converting from codepage '%s' to UTF-8 failed: %s\",\n                   who.c_str (), fallback.c_str (), std::strerror (errno));\n\n              octave::unwind_action free_val_utf8 ([val_utf8] () { ::free (val_utf8); });\n\n              out_str.append (reinterpret_cast<const char *> (val_utf8),\n                              lengthp);\n            }\n        }\n    }\n\n  in_str = out_str;\n  return num_replacements;\n}\n\nstd::string\noctave::string::u16_to_encoding (const std::string& who,\n                                 const std::u16string& u16_string,\n                                 const std::string& encoding)\n{\n  const uint16_t *src = reinterpret_cast<const uint16_t *>\n                        (u16_string.c_str ());\n  std::size_t srclen = u16_string.length ();\n\n  std::size_t length;\n  char *native_str = octave_u16_conv_to_encoding (encoding.c_str (), src,\n                                                  srclen, &length);\n\n  if (! native_str)\n    {\n      if (errno == ENOSYS)\n        (*current_liboctave_error_handler)\n          (\"%s: iconv() is not supported.  Installing GNU libiconv and then \"\n           \"re-compiling Octave could fix this.\", who.c_str ());\n      else\n        (*current_liboctave_error_handler)\n          (\"%s: converting from UTF-16 to codepage '%s' failed: %s\",\n           who.c_str (), encoding.c_str (), std::strerror (errno));\n    }\n\n  octave::unwind_action free_native_str ([native_str] () { ::free (native_str); });\n\n  std::string retval = std::string (native_str, length);\n\n  return retval;\n}\n\nstd::vector<std::string>\noctave::string::get_encoding_list ()\n{\n  static std::vector<std::string> encoding_list;\n\n  if (encoding_list.empty ())\n    {\n#if defined (HAVE_ICONVLIST)\n      // get number of supported encodings\n      std::size_t count = 0;\n      octave_iconvlist_wrapper (\n        [] (unsigned int num, const char * const *, void *data) -> int\n          {\n            std::size_t *count_ptr = static_cast<std::size_t *> (data);\n            *count_ptr = num;\n            return 0;\n          },\n        &count);\n\n      if (count == static_cast<size_t> (-1))\n        {\n          encoding_list.push_back (\"UTF-8\");\n          return encoding_list;\n        }\n\n#  if defined (HAVE_ICONV_CANONICALIZE)\n      // use unordered_set to skip canonicalized aliases\n      std::unordered_set<std::string> encoding_set;\n      encoding_set.reserve (count);\n\n      // populate vector with name of encodings\n      octave_iconvlist_wrapper (\n        [] (unsigned int num, const char * const *names, void *data) -> int\n          {\n            std::unordered_set<std::string> *encoding_set_ptr\n              = static_cast<std::unordered_set<std::string> *> (data);\n            for (std::size_t i = 0; i < num; i++)\n              {\n                const char *canonicalized_enc\n                  = octave_iconv_canonicalize_wrapper (names[i]);\n                encoding_set_ptr->insert (canonicalized_enc);\n              }\n            return 0;\n          },\n        &encoding_set);\n\n      encoding_list.assign (encoding_set.begin (), encoding_set.end ());\n#  endif\n\n#else\n      // Use hardcoded list of encodings as a fallback for platforms without\n      // iconvlist (or another way of programmatically querrying a list of\n      // supported encodings).\n      // This list is inspired by the encodings supported by Geany.\n      encoding_list\n        = {\"ISO-8859-1\",\n           \"ISO-8859-2\",\n           \"ISO-8859-3\",\n           \"ISO-8859-4\",\n           \"ISO-8859-5\",\n           \"ISO-8859-6\",\n           \"ISO-8859-7\",\n           \"ISO-8859-8\",\n           \"ISO-8859-9\",\n           \"ISO-8859-10\",\n           \"ISO-8859-13\",\n           \"ISO-8859-14\",\n           \"ISO-8859-15\",\n           \"ISO-8859-16\",\n\n           \"UTF-7\",\n           \"UTF-8\",\n           \"UTF-16LE\",\n           \"UTF-16BE\",\n           \"UTF-32LE\",\n           \"UTF-32BE\",\n           \"UCS-2LE\",\n           \"UCS-2BE\",\n\n           \"ARMSCII-8\",\n           \"BIG5\",\n           \"BIG5-HKSCS\",\n           \"CP866\",\n\n           \"EUC-JP\",\n           \"EUC-KR\",\n           \"EUC-TW\",\n\n           \"GB18030\",\n           \"GB_2312-80\",\n           \"GBK\",\n           \"HZ\",\n\n           \"IBM850\",\n           \"IBM852\",\n           \"IBM855\",\n           \"IBM857\",\n           \"IBM862\",\n           \"IBM864\",\n\n           \"ISO-2022-JP\",\n           \"ISO-2022-KR\",\n           \"JOHAB\",\n           \"KOI8-R\",\n           \"KOI8-U\",\n\n           \"SHIFT_JIS\",\n           \"TCVN\",\n           \"TIS-620\",\n           \"UHC\",\n           \"VISCII\",\n\n           \"CP1250\",\n           \"CP1251\",\n           \"CP1252\",\n           \"CP1253\",\n           \"CP1254\",\n           \"CP1255\",\n           \"CP1256\",\n           \"CP1257\",\n           \"CP1258\",\n\n           \"CP932\"\n           };\n\n      // FIXME: Should we check whether those are actually valid encoding\n      // identifiers?\n#endif\n\n      // sort list of encodings\n      std::sort (encoding_list.begin (), encoding_list.end ());\n    }\n\n  return encoding_list;\n}\n\ntypedef octave::string::codecvt_u8::InternT InternT;\ntypedef octave::string::codecvt_u8::ExternT ExternT;\ntypedef octave::string::codecvt_u8::StateT StateT;\n\ntypename std::codecvt<InternT, ExternT, StateT>::result\noctave::string::codecvt_u8::do_out\n  (StateT& /* state */,\n   const InternT* from, const InternT* from_end, const InternT*& from_next,\n   ExternT* to, ExternT* to_end, ExternT*& to_next) const\n{\n  to_next = to;\n  if (from_end <= from)\n    {\n      from_next = from_end;\n      return std::codecvt<InternT, ExternT, StateT>::noconv;\n    }\n\n  // Check if buffer ends in a complete UTF-8 surrogate.\n  // FIXME: If this is the last call before a stream is closed, we should\n  //        convert trailing bytes even if they look incomplete.\n  //        How can we detect that?\n  std::size_t pop_end = 0;\n  if ((*(from_end-1) & 0b10000000) == 0b10000000)\n    {\n      // The last byte is part of a surrogate.  Check if it is complete.\n\n      // number of bytes of the surrogate in the buffer\n      std::size_t num_bytes_in_buf = 1;\n      // Find initial byte of surrogate\n      while (((*(from_end-num_bytes_in_buf) & 0b11000000) != 0b11000000)\n             && (num_bytes_in_buf < 4)\n             && (from_end-num_bytes_in_buf > from))\n        num_bytes_in_buf++;\n\n      // If the start of the surrogate is not in the buffer, we need to\n      // continue with the invalid UTF-8 sequence to avoid an infinite loop.\n      // Check if we found an initial byte and if there are enough bytes in the\n      // buffer to complete the surrogate.\n      if ((((*(from_end-num_bytes_in_buf) & 0b11100000) == 0b11000000)\n           && (num_bytes_in_buf < 2))  // incomplete 2-byte surrogate\n          || (((*(from_end-num_bytes_in_buf) & 0b11110000) == 0b11100000)\n              && (num_bytes_in_buf < 3))  // incomplete 3-byte surrogate\n          || (((*(from_end-num_bytes_in_buf) & 0b11111000) == 0b11110000)\n              && (num_bytes_in_buf < 4)))  // incomplete 4-byte surrogate\n        pop_end = num_bytes_in_buf;\n    }\n  from_next = from_end - pop_end;\n\n  std::size_t srclen = (from_end-from-pop_end) * sizeof (InternT);\n  std::size_t length = (to_end-to) * sizeof (ExternT);\n  if (srclen < 1 || length < 1)\n    return std::codecvt<InternT, ExternT, StateT>::partial;\n\n  // Convert from UTF-8 to output encoding\n  const uint8_t *u8_str = reinterpret_cast<const uint8_t *> (from);\n  char *enc_str = octave_u8_conv_to_encoding (m_enc.c_str (), u8_str, srclen,\n                                              &length);\n\n  if (length < 1)\n    return std::codecvt<InternT, ExternT, StateT>::partial;\n\n  size_t max = (to_end - to) * sizeof (ExternT);\n  // FIXME: If the output encoding is a multibyte or variable byte encoding,\n  //        we should ensure that we don't cut off a \"partial\" surrogate from\n  //        the output.\n  //        Can this ever happen?\n  if (length < max)\n    max = length;\n\n  // copy conversion result to output\n  std::copy_n (enc_str, max, to);\n  ::free (enc_str);\n\n  from_next = from + srclen;\n  to_next = to + max;\n\n  return ((pop_end > 0 || max < length)\n          ? std::codecvt<InternT, ExternT, StateT>::partial\n          : std::codecvt<InternT, ExternT, StateT>::ok);\n}\n\ntypename std::codecvt<InternT, ExternT, StateT>::result\noctave::string::codecvt_u8::do_in\n  (StateT& /* state */,\n   const ExternT* from, const ExternT* from_end, const ExternT*& from_next,\n   InternT* to, InternT* to_end, InternT*& to_next) const\n{\n  // Convert from input encoding to UTF-8\n  std::size_t srclen = (from_end-from) * sizeof (ExternT);\n  std::size_t lengthp = (to_end-to) * sizeof (InternT);\n  const char *enc_str = reinterpret_cast<const char *> (from);\n  uint8_t *u8_str = octave_u8_conv_from_encoding (m_enc.c_str (),\n                                                  enc_str, srclen, &lengthp);\n\n  std::size_t max = to_end - to;\n  if (lengthp < max)\n    max = lengthp;\n\n  // copy conversion result to output\n  std::copy_n (u8_str, max, to);\n  ::free (u8_str);\n\n  from_next = from + srclen;\n  to_next = to + max;\n\n  return std::codecvt<InternT, ExternT, StateT>::ok;\n}\n\nint octave::string::codecvt_u8::do_length\n  (StateT& /* state */, const ExternT *src, const ExternT *end,\n   std::size_t max) const\n{\n  // return number of external characters that produce MAX internal ones\n  std::size_t srclen = end-src;\n  OCTAVE_LOCAL_BUFFER (std::size_t, offsets, srclen);\n  std::size_t lengthp = max;\n  octave_u8_conv_from_encoding_offsets (m_enc.c_str (), src, srclen, offsets,\n                                        &lengthp);\n  std::size_t ext_char;\n  for (ext_char = 0; ext_char < srclen; ext_char++)\n    {\n      if (offsets[ext_char] != static_cast<size_t> (-1)\n          && offsets[ext_char] >= max)\n        break;\n    }\n\n  return ext_char;\n}\n\n\ntemplate <typename T>\nstd::string\nrational_approx (T val, int len)\n{\n  std::string s;\n\n  if (len <= 0)\n    len = 10;\n\n  static constexpr T out_of_range_top\n    = static_cast<T> (std::numeric_limits<int>::max ()) + 1.0;\n  static constexpr T out_of_range_bottom\n    = static_cast<T> (std::numeric_limits<int>::min ()) - 1.0;\n\n  if (octave::math::isinf (val))\n    {\n      if (val > 0)\n        s = \"1/0\";\n      else\n        s = \"-1/0\";\n    }\n  else if (octave::math::isnan (val))\n    s = \"0/0\";\n  else if (val <= out_of_range_bottom || val >= out_of_range_top\n           || octave::math::is_integer (val))\n    {\n      std::ostringstream buf;\n      buf.flags (std::ios::fixed);\n      buf << std::setprecision (0) << octave::math::round (val);\n      s = buf.str ();\n    }\n  else\n    {\n      T lastn = 1;\n      T lastd = 0;\n      T n = octave::math::round (val);\n      T d = 1;\n      T frac = val - n;\n\n      std::ostringstream init_buf;\n      init_buf.flags (std::ios::fixed);\n      init_buf << std::setprecision (0) << static_cast<int> (n);\n      s = init_buf.str ();\n\n      while (true)\n        {\n          T flip = 1 / frac;\n          T step = octave::math::round (flip);\n          T nextn = n;\n          T nextd = d;\n\n          // Have we converged to 1/intmax ?\n          if (std::abs (flip) > out_of_range_top)\n            {\n              lastn = n;\n              lastd = d;\n              break;\n            }\n\n          frac = flip - step;\n          n = step * n + lastn;\n          d = step * d + lastd;\n          lastn = nextn;\n          lastd = nextd;\n\n          if (std::abs (n) >= out_of_range_top\n              || std::abs (d) >= out_of_range_top)\n            break;\n\n          std::ostringstream buf;\n          buf.flags (std::ios::fixed);\n          buf << std::setprecision (0) << static_cast<int> (n)\n              << '/' << static_cast<int> (d);\n\n          if (n < 0 && d < 0)\n            {\n              // Double negative, string can be two characters longer.\n              if (buf.str ().length () > static_cast<unsigned int> (len + 2))\n                break;\n            }\n          else\n            {\n              if (buf.str ().length () > static_cast<unsigned int> (len))\n                break;\n            }\n\n          s = buf.str ();\n        }\n\n      if (lastd < 0)\n        {\n          // Move negative sign from denominator to numerator\n          lastd = - lastd;\n          lastn = - lastn;\n          std::ostringstream buf;\n          buf.flags (std::ios::fixed);\n          buf << std::setprecision (0) << static_cast<int> (lastn)\n              << '/' << static_cast<int> (lastd);\n          s = buf.str ();\n        }\n    }\n\n  return s;\n}\n\n// instantiate the template for float and double\ntemplate OCTAVE_API std::string rational_approx<float> (float val, int len);\ntemplate OCTAVE_API std::string rational_approx<double> (double val, int len);\n"
  },
  {
    "path": "liboctave/util/oct-string.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_string_h)\n#define octave_oct_string_h 1\n\n#include \"octave-config.h\"\n\n#include <locale>\n#include <vector>\n\n#include \"oct-cmplx.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\n//! Octave string utility functions.\n//!\n//! This functions provide a C++ interface to most string functions\n//! available in the Octave interpreter.\n//!\n//! Specializations for Array may consider its dimensions in addition\n//! to the actual string contents.\n//!\n//! @attention\n//! Octave's string comparison functions return true when strings are\n//! are equal, just the opposite of the corresponding C library functions.\n//! In addition, Octave's function only return bool and do not check\n//! lexicographical order.\n\nOCTAVE_BEGIN_NAMESPACE(string)\n\n//! True if strings are the same.\n//!\n//! ## Specialization for Array<char>\n//!\n//! When comparing whole Array of chars, the actual Array dimensions\n//! are significant.  A column vector and row vector with the same\n//! char array, will still return false.\n\ntemplate <typename T>\nOCTAVE_API bool\nstrcmp (const T& str_a, const T& str_b);\n\n//! True if string is the same as character sequence.\n//!\n//! Compares a string to the null-terminated character sequence\n//! beginning at the character pointed to by str_b.\n//!\n//! ## Specialization for Array<char>\n//!\n//! For purposes of comparison of dimensions, the character sequence\n//! is considered to be a row vector.\n\ntemplate <typename T>\nOCTAVE_API bool\nstrcmp (const T& str_a, const typename T::value_type *str_b);\n\n//! True if strings are the same, ignoring case.\n//!\n//! ## Specialization for Array<char>\n//!\n//! When comparing whole Array of chars, the actual Array dimensions\n//! are significant.  A column vector and row vector with the same\n//! char array, will still return false.\n\ntemplate <typename T>\nOCTAVE_API bool\nstrcmpi (const T& str_a, const T& str_b);\n\n//! True if string is the same as character sequence, ignoring case.\n//!\n//! ## Specialization for Array<char>\n//!\n//! For purposes of comparison of dimensions, the character sequence\n//! is considered to be a row vector.\n\ntemplate <typename T>\nOCTAVE_API bool\nstrcmpi (const T& str_a, const typename T::value_type *str_b);\n\n//! True if the first N characters are the same.\n//!\n//! ## Specialization for Array<char>\n//!\n//! The comparison is done in the first N characters, the actual\n//! dimensions of the Array are irrelevant.  A row vector and\n//! a column vector of the same still return true.\n\ntemplate <typename T>\nOCTAVE_API bool\nstrncmp (const T& str_a, const T& str_b,\n         const typename T::size_type n);\n\n//! True if the first N characters are the same.\ntemplate <typename T>\nOCTAVE_API bool\nstrncmp (const T& str_a, const typename T::value_type *str_b,\n         const typename T::size_type n);\n\n//! True if the first N characters are the same, ignoring case.\n//!\n//! ## Specialization for Array<char>\n//!\n//! The comparison is done in the first N characters, the actual\n//! dimensions of the Array are irrelevant.  A row vector and\n//! a column vector of the same still return true.\n\ntemplate <typename T>\nOCTAVE_API bool\nstrncmpi (const T& str_a, const T& str_b,\n          const typename T::size_type n);\n\n//! True if the first N characters are the same, ignoring case.\ntemplate <typename T>\nOCTAVE_API bool\nstrncmpi (const T& str_a, const typename T::value_type *str_b,\n          const typename T::size_type n);\n\nextern OCTAVE_API Complex\nstr2double (const std::string& str_arg);\n\n//! True if any of the characters is outside the range of ASCII\nextern OCTAVE_API bool\nany_non_ascii_chars (const std::string &s);\n\nextern OCTAVE_API std::string\nu8_to_encoding (const std::string& who, const std::string& u8_string,\n                const std::string& encoding);\n\nextern OCTAVE_API std::string\nu8_from_encoding (const std::string& who, const std::string& native_string,\n                  const std::string& encoding);\n\nenum u8_fallback_type\n{\n  U8_REPLACEMENT_CHAR,\n  U8_ISO_8859_1\n};\n\nextern OCTAVE_API unsigned int\nu8_validate (const std::string& who, std::string& in_string,\n             const u8_fallback_type type = U8_REPLACEMENT_CHAR);\n\nextern OCTAVE_API std::string\nu16_to_encoding (const std::string& who, const std::u16string& u16_string,\n                 const std::string& encoding);\n\nextern OCTAVE_API std::vector<std::string>\nget_encoding_list ();\n\ntemplate<class Facet>\nstruct deletable_facet : Facet\n{\n  deletable_facet () = delete;\n\n  template<class ...Args>\n  deletable_facet (Args&& ...args)\n    : Facet (std::forward<Args> (args)...)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (deletable_facet)\n};\n\nclass OCTAVE_API codecvt_u8 : public std::codecvt<char, char, std::mbstate_t>\n{\npublic:\n\n  codecvt_u8 (const std::string& enc)\n    : m_enc (enc)\n  { }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (codecvt_u8)\n\n  virtual ~codecvt_u8 () { }\n\n  typedef char InternT;\n  typedef char ExternT;\n  typedef std::mbstate_t StateT;\n\nprivate:\n\n  OCTAVE_API\n  typename std::codecvt<InternT, ExternT, StateT>::result\n  do_out (StateT& state,\n          const InternT *from, const InternT *from_end, const InternT *&from_next,\n          ExternT *to, ExternT *to_end, ExternT *&to_next) const;\n\n  OCTAVE_API\n  typename std::codecvt<InternT, ExternT, StateT>::result\n  do_in (StateT& state,\n         const ExternT *from, const ExternT *from_end, const ExternT *&from_next,\n         InternT *to, InternT *to_end, InternT *&to_next) const;\n\n  typename std::codecvt<InternT, ExternT, StateT>::result\n  do_unshift (StateT& /* state */, ExternT *to, ExternT * /* to_end */,\n              ExternT *&to_next) const\n  {\n    // FIXME: What is the correct thing to unshift?\n    // Just reset?\n    to_next = to;\n\n    return std::codecvt<InternT, ExternT, StateT>::ok;\n  }\n\n  int do_encoding () const throw ()\n  {\n    // return 0 because UTF-8 encoding is variable length\n    return 0;\n  }\n\n  bool do_always_noconv () const throw ()\n  {\n    // return false to indicate non-identity conversion\n    return false;\n  }\n\n  OCTAVE_API int\n  do_length (StateT& state, const ExternT *src, const ExternT *end,\n             std::size_t max) const;\n\n  int do_max_length() const throw ()\n  {\n    // For UTF-8, a maximum of 4 bytes are needed for one character.\n    return 4;\n  }\n\n  std::string m_enc;\n\n};\n\nOCTAVE_END_NAMESPACE(string)\nOCTAVE_END_NAMESPACE(octave)\n\ntemplate <typename T>\nextern OCTAVE_API std::string\nrational_approx (T val, int len);\n\n#endif\n"
  },
  {
    "path": "liboctave/util/oct-traits.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2009-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_oct_traits_h)\n#define octave_oct_traits_h 1\n\n#include \"octave-config.h\"\n\n#include <type_traits>\n\n// Ideas for these classes taken from C++ Templates, The Complete\n// Guide by David Vandevoorde and Nicolai M. Josuttis, Addison-Wesley, \n// 2003.\n\n// Select a type based on the value of a constant expression.\n\ntemplate <bool cond, typename T1, typename T2>\nclass\nOCTAVE_DEPRECATED (12, \"if_then_else<cond, T1, T2>::result is obsolete, use std::conditional_t<cond, T1, T2>\")\nif_then_else\n{\npublic:\n\n  typedef std::conditional_t<cond, T1, T2> result;\n};\n\n// Determine whether two types are equal.\ntemplate <typename T1, typename T2>\nstruct equal_types : std::false_type {};\n\ntemplate <typename T>\nstruct equal_types<T, T> : std::true_type {};\n\n// Determine whether a type is an instance of a template.\n\ntemplate <template <typename> class Template, typename T>\nstruct is_instance : std::false_type {};\n\ntemplate <template <typename> class Template, typename T>\nstruct is_instance<Template, Template<T>> : std::true_type {};\n\n// Determine whether a template parameter is a class type.\n\ntemplate <typename T1>\nclass is_class_type\n{\nprivate:\n\n  typedef char one;\n  typedef struct { char c[2]; } two;\n\n  // Classes can have pointers to members.\n  template <typename T2> static one is_class_type_test (int T2::*);\n\n  // Catch everything else.\n  template <typename T2> static two is_class_type_test (...);\n\npublic:\n\n  enum { yes = sizeof (is_class_type_test<T1> (0)) == 1 };\n  enum { no = ! yes };\n};\n\n// Define typename ref_param<T>::type as T const& if T is a class\n// type.  Otherwise, define it to be T.\n\ntemplate <typename T>\nclass ref_param\n{\npublic:\n\n  typedef typename std::conditional_t<is_class_type<T>::no, T, T const&> type;\n};\n\n// Will turn TemplatedClass<T> to T, leave T otherwise.\n// Useful for stripping wrapper classes, like octave_int.\n\ntemplate <template <typename> class TemplatedClass, typename T>\nclass strip_template_param\n{\npublic:\n  typedef T type;\n};\n\ntemplate <template <typename> class TemplatedClass, typename T>\nclass strip_template_param<TemplatedClass, TemplatedClass<T>>\n{\npublic:\n  typedef T type;\n};\n\n// Will turn TemplatedClass<T> to TemplatedClass<S>, T to S otherwise.\n// Useful for generic promotions.\n\ntemplate <template <typename> class TemplatedClass, typename T, typename S>\nclass subst_template_param\n{\npublic:\n  typedef S type;\n};\n\ntemplate <template <typename> class TemplatedClass, typename T, typename S>\nclass subst_template_param<TemplatedClass, TemplatedClass<T>, S>\n{\npublic:\n  typedef TemplatedClass<S> type;\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/util/octave-preserve-stream-state.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_octave_preserve_stream_state_h)\n#define octave_octave_preserve_stream_state_h 1\n\n#include \"octave-config.h\"\n\n#include <ios>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass preserve_stream_state\n{\npublic:\n\n  preserve_stream_state () = delete;\n\n  preserve_stream_state (std::ios& s)\n    : m_stream (s), m_oflags (s.flags ()), m_oprecision (s.precision ()),\n      m_owidth (s.width ()), m_ofill (s.fill ())\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_CTOR (preserve_stream_state)\n  OCTAVE_DISABLE_COPY_MOVE_ASGN (preserve_stream_state)\n\n  ~preserve_stream_state ()\n  {\n    m_stream.flags (m_oflags);\n    m_stream.precision (m_oprecision);\n    m_stream.width (m_owidth);\n    m_stream.fill (m_ofill);\n  }\n\nprivate:\n\n  std::ios& m_stream;\n  std::ios::fmtflags m_oflags;\n  std::streamsize m_oprecision;\n  int m_owidth;\n  char m_ofill;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/pathsearch.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"kpse.h\"\n#include \"lo-utils.h\"\n#include \"oct-env.h\"\n#include \"oct-error.h\"\n#include \"pathsearch.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\ndirectory_path::directory_path (const std::string& s)\n  : m_orig_path (s), m_initialized (false), m_expanded_path (),\n    m_path_elements ()\n{\n  if (! m_orig_path.empty ())\n    init ();\n}\n\nstd::list<std::string>\ndirectory_path::elements ()\n{\n  return m_initialized ? m_path_elements : std::list<std::string> ();\n}\n\nstd::list<std::string>\ndirectory_path::all_directories ()\n{\n  std::list<std::string> retval;\n\n  if (m_initialized)\n    {\n      for (const auto& elt : m_path_elements)\n        {\n          std::string elt_dir = kpse_element_dir (elt);\n\n          if (! elt_dir.empty ())\n            retval.push_back (elt_dir);\n        }\n    }\n\n  return retval;\n}\n\nstd::string\ndirectory_path::find_first (const std::string& nm)\n{\n  return m_initialized ? kpse_path_search (m_expanded_path, nm) : \"\";\n}\n\nstd::list<std::string>\ndirectory_path::find_all (const std::string& nm)\n{\n  return (m_initialized\n          ? kpse_all_path_search (m_expanded_path, nm)\n          : std::list<std::string> ());\n}\n\nstd::string\ndirectory_path::find_first_of (const std::list<std::string>& names)\n{\n  return (m_initialized\n          ? kpse_path_find_first_of (m_expanded_path, names) : \"\");\n}\n\nstd::list<std::string>\ndirectory_path::find_all_first_of (const std::list<std::string>& names)\n{\n  return (m_initialized\n          ? kpse_all_path_find_first_of (m_expanded_path, names)\n          : std::list<std::string> ());\n}\n\nvoid\ndirectory_path::init ()\n{\n  m_expanded_path = kpse_path_expand (m_orig_path);\n\n  for (kpse_path_iterator pi (m_expanded_path); pi != std::string::npos; pi++)\n    m_path_elements.push_back (*pi);\n\n  m_initialized = true;\n}\n\nchar\ndirectory_path::path_sep_char ()\n{\n  return SEPCHAR;\n}\n\nstd::string\ndirectory_path::path_sep_str ()\n{\n  return SEPCHAR_STR;\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/pathsearch.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pathsearch_h)\n#define octave_pathsearch_h 1\n\n#include \"octave-config.h\"\n\n#include <list>\n#include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTAVE_API directory_path\n{\npublic:\n\n  directory_path (const std::string& s = \"\");\n\n  directory_path (const directory_path&) = default;\n\n  directory_path& operator = (const directory_path&) = default;\n\n  ~directory_path () = default;\n\n  void set (const std::string& s)\n  {\n    m_initialized = false;\n    m_orig_path = s;\n    init ();\n  }\n\n  std::list<std::string> elements ();\n\n  std::list<std::string> all_directories ();\n\n  std::string find_first (const std::string&);\n\n  std::string find (const std::string& nm) { return find_first (nm); }\n\n  std::list<std::string> find_all (const std::string&);\n\n  std::string find_first_of (const std::list<std::string>& names);\n\n  std::list<std::string>\n  find_all_first_of (const std::list<std::string>& names);\n\n  void rehash ()\n  {\n    m_initialized = false;\n    init ();\n  }\n\n  static char path_sep_char ();\n\n  // static void path_sep_char (char c);\n\n  static std::string path_sep_str ();\n\n  static bool is_path_sep (char c) { return c == path_sep_char (); }\n\nprivate:\n\n  // The colon separated list that we were given.\n  std::string m_orig_path;\n\n  // TRUE means we've unpacked the path p.\n  bool m_initialized;\n\n  // A version of the colon separate list on which we have performed\n  // tilde, variable, and possibly default path expansion.\n  std::string m_expanded_path;\n\n  // The elements of the list.\n  std::list<std::string> m_path_elements;\n\n  void init ();\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/quit.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <atomic>\n#include <cstring>\n\n#include <ostream>\n#include <sstream>\n\n#include \"quit.h\"\n\nstd::atomic<int> octave_interrupt_state {0};\n\nstd::atomic<bool> octave_signal_caught {false};\n\nvoid (*octave_signal_hook) () = nullptr;\nvoid (*octave_interrupt_hook) () = nullptr;\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstd::string execution_exception::stack_trace () const\n{\n  std::size_t nframes = m_stack_info.size ();\n\n  if (nframes == 0)\n    return std::string ();\n\n  std::ostringstream buf;\n\n  buf << \"error: called from\\n\";\n\n  for (const auto& frm : m_stack_info)\n    {\n      buf << \"    \" << frm.fcn_name ();\n\n      int line = frm.line ();\n\n      if (line > 0)\n        {\n          buf << \" at line \" << line;\n\n          int column = frm.column ();\n\n          if (column > 0)\n            buf << \" column \" << column;\n        }\n\n      buf << \"\\n\";\n    }\n\n  return buf.str ();\n}\n\nvoid\nexecution_exception::display (std::ostream& os) const\n{\n  if (! m_message.empty ())\n    {\n      os << m_err_type << \": \" << m_message;\n\n      if (m_message.back () != '\\n')\n        {\n          os << \"\\n\";\n\n          std::string st = stack_trace ();\n\n          if (! st.empty ())\n            os << st;\n        }\n    }\n}\n\nOCTAVE_END_NAMESPACE(octave)\n\nextern \"C\" OCTAVE_API void\noctave_quit_c (void)\n{\n  octave_quit ();\n}\n\nvoid\noctave_handle_signal ()\n{\n  if (octave_signal_hook)\n    octave_signal_hook ();\n\n  int curr_interrupt_state = octave_interrupt_state.load ();\n\n  while (curr_interrupt_state > 0 &&\n         ! octave_interrupt_state.compare_exchange_weak (curr_interrupt_state, -1))\n    ;\n\n  if (curr_interrupt_state > 0)\n    throw octave::interrupt_exception ();\n}\n"
  },
  {
    "path": "liboctave/util/quit.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2002-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_quit_h)\n#define octave_quit_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\n#  include <atomic>\n#  include <iosfwd>\n#  include <list>\n#  include <stdexcept>\n#  include <string>\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass frame_info\n{\npublic:\n\n  frame_info () = default;\n\n  frame_info (const std::string& file_name, const std::string& fcn_name,\n              int line, int column)\n    : m_file_name (file_name), m_fcn_name (fcn_name), m_line (line),\n      m_column (column)\n  { }\n\n  frame_info (const frame_info&) = default;\n\n  frame_info& operator = (const frame_info&) = default;\n\n  ~frame_info () = default;\n\n  std::string file_name () const { return m_file_name; }\n\n  std::string fcn_name () const { return m_fcn_name; }\n\n  int line () const { return m_line; }\n\n  int column () const { return m_column; }\n\nprivate:\n\n  std::string m_file_name;\n\n  std::string m_fcn_name;\n\n  int m_line;\n\n  int m_column;\n};\n\ninline bool operator == (const frame_info& a, const frame_info& b)\n{\n  return (a.file_name () == b.file_name ()\n          && a.fcn_name () == b.fcn_name ()\n          && a.line () == b.line ()\n          && a.column () == b.column ());\n}\n\nclass OCTAVE_EXCEPTION_API execution_exception : public std::runtime_error\n{\npublic:\n\n  typedef std::list<frame_info> stack_info_type;\n\n  execution_exception (const std::string& err_type = \"error\",\n                       const std::string& id = \"\",\n                       const std::string& message = \"unspecified error\",\n                       const stack_info_type& stack_info = stack_info_type ())\n    : runtime_error (message), m_err_type (err_type), m_id (id),\n      m_message (message), m_stack_info (stack_info)\n  { }\n\n  execution_exception (const execution_exception&) = default;\n\n  execution_exception& operator = (const execution_exception&) = default;\n\n  ~execution_exception () = default;\n\n  void set_err_type (const std::string& et)\n  {\n    m_err_type = et;\n  }\n\n  std::string err_type () const { return m_err_type; }\n\n  virtual std::string stack_trace () const;\n\n  void set_identifier (const std::string& id)\n  {\n    m_id = id;\n  }\n\n  virtual std::string identifier () const { return m_id; }\n\n  void set_message (const std::string& msg)\n  {\n    m_message = msg;\n  }\n\n  std::string message () const { return m_message; }\n\n  // Provided for std::exception interface.\n  const char * what () const noexcept { return m_message.c_str (); }\n\n  virtual stack_info_type stack_info () const\n  {\n    return m_stack_info;\n  }\n\n  void set_stack_info (const stack_info_type& stack_info)\n  {\n    m_stack_info = stack_info;\n  }\n\n  virtual void display (std::ostream& os) const;\n\nprivate:\n\n  std::string m_err_type;\n\n  std::string m_id;\n\n  std::string m_message;\n\n  stack_info_type m_stack_info;\n};\n\nclass OCTAVE_EXCEPTION_API exit_exception : public std::exception\n{\npublic:\n\n  exit_exception (int exit_status = 0, bool safe_to_return = false)\n    : std::exception (), m_exit_status (exit_status),\n      m_safe_to_return (safe_to_return)\n  { }\n\n  OCTAVE_DEFAULT_COPY_MOVE_DELETE (exit_exception)\n\n  const char * what () const noexcept { return \"exit exception\"; }\n\n  int exit_status () const { return m_exit_status; }\n\n  bool safe_to_return () const { return m_safe_to_return; }\n\nprivate:\n\n  int m_exit_status;\n\n  bool m_safe_to_return;\n};\n\nclass OCTAVE_EXCEPTION_API interrupt_exception : public std::exception\n{\npublic:\n\n  interrupt_exception () = default;\n\n  interrupt_exception (const interrupt_exception&) = default;\n\n  interrupt_exception& operator = (const interrupt_exception&) = default;\n\n  ~interrupt_exception () = default;\n\n  const char * what () const noexcept { return \"interrupt exception\"; }\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\nextern \"C\" {\n\n#endif\n\n// The following enum values are deprecated and will eventually be\n// removed from Octave, but there seems to be no universally good way\n// to tag them with an attribute that will generate a warning.\n\n  enum\n  octave_exception\n  {\n    octave_no_exception = 0,\n    octave_exec_exception = 1,\n    octave_alloc_exception = 3,\n    octave_quit_exception = 4\n  };\n\n  /*\n    > 0: interrupt pending\n      0: no interrupt pending\n    < 0: handling interrupt\n  */\n\n#if defined (__cplusplus)\n\n  extern OCTAVE_API std::atomic<int> octave_interrupt_state;\n\n  extern OCTAVE_API std::atomic<bool> octave_signal_caught;\n\n#endif\n\n  extern OCTAVE_API void octave_handle_signal (void);\n\n#if defined (__cplusplus)\n\n  inline void octave_quit ()\n  {\n    bool expected = true;\n\n    if (octave_signal_caught.compare_exchange_strong (expected, false))\n      octave_handle_signal ();\n  }\n\n#define OCTAVE_QUIT octave_quit ()\n\n#else\n\n  extern OCTAVE_API void octave_quit_c (void);\n#define OCTAVE_QUIT octave_quit_c ()\n\n#endif\n\n  /* The following macros are obsolete.  Interrupting immediately by\n     calling siglongjmp or similar from a signal handler is asking for\n     trouble.  Rather than remove them, however, please leave them in\n     place so that old code that uses them will continue to compile.  They\n     are defined to create a dummy do-while block to match the previous\n     definitions.  */\n\n#define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE     \\\n  do                                                    \\\n    {\n\n#define END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE       \\\n    }                                                   \\\n  while (0)\n\n#if defined (__cplusplus)\n\n  /* Likewise, these are obsolete.  They are defined to create a\n     dummy scope to match the previous versions that created a try-catch\n     block.  */\n\n#define BEGIN_INTERRUPT_WITH_EXCEPTIONS         \\\n  {\n\n#define END_INTERRUPT_WITH_EXCEPTIONS           \\\n  }\n\n#endif\n\n#if defined (__cplusplus)\n}\n\n/* These should only be declared for C++ code, and should also be\n   outside of any extern \"C\" block.  */\n\nextern OCTAVE_API void (*octave_signal_hook) ();\nextern OCTAVE_API void (*octave_interrupt_hook) ();\n\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/util/r1mach.f",
    "content": "c Copyright (C) 1993-2026 The Octave Project Developers\nc\nc See the file COPYRIGHT.md in the top-level directory of this\nc distribution or <https://octave.org/copyright/>.\nc\nc This file is part of Octave.\nc\nc Octave is free software: you can redistribute it and/or modify it\nc under the terms of the GNU General Public License as published by\nc the Free Software Foundation, either version 3 of the License, or\nc (at your option) any later version.\nc\nc Octave is distributed in the hope that it will be useful, but\nc WITHOUT ANY WARRANTY; without even the implied warranty of\nc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nc GNU General Public License for more details.\nc\nc You should have received a copy of the GNU General Public License\nc along with Octave; see the file COPYING.  If not, see\nc <https://www.gnu.org/licenses/>.\nc\n      real function r1mach (i)\n      integer i\n      logical init\n      real rmach(5)\n      real slamch\n      external slamch\n      save init, rmach\n      data init /.false./\n      if (.not. init) then\n        rmach(1) = slamch ('u')\n        rmach(2) = slamch ('o')\n        rmach(3) = slamch ('e')\n        rmach(4) = slamch ('p')\n        rmach(5) = log10 (slamch ('b'))\n        init = .true.\n      endif\n      if (i .lt. 1 .or. i .gt. 5) goto 999\n      r1mach = rmach(i)\n      return\n  999 write (*, 1999) i\n 1999 format (' r1mach - i out of bounds', i10)\n      call xstopx (' ')\n      r1mach = 0\n      end\n"
  },
  {
    "path": "liboctave/util/singleton-cleanup.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-error.h\"\n#include \"singleton-cleanup.h\"\n\nsingleton_cleanup_list *singleton_cleanup_list::s_instance = nullptr;\n\nsingleton_cleanup_list::~singleton_cleanup_list ()\n{\n  for (fptr fcn : m_fcn_list)\n    {\n      fcn ();\n    }\n}\n\nbool\nsingleton_cleanup_list::instance_ok ()\n{\n  bool retval = true;\n\n  if (! s_instance)\n    s_instance = new singleton_cleanup_list ();\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/util/singleton-cleanup.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2011-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_singleton_cleanup_h)\n#define octave_singleton_cleanup_h 1\n\n#include \"octave-config.h\"\n\n#include <set>\n\nclass OCTAVE_API singleton_cleanup_list\n{\nprotected:\n\n  singleton_cleanup_list () : m_fcn_list () { }\n\npublic:\n\n  typedef void (*fptr) ();\n\n  OCTAVE_DISABLE_COPY_MOVE (singleton_cleanup_list)\n\n  ~singleton_cleanup_list ();\n\n  static void add (fptr f)\n  {\n    if (instance_ok ())\n      s_instance->do_add (f);\n  }\n\n  static void cleanup ()\n  {\n    delete s_instance;\n    s_instance = nullptr;\n  }\n\nprivate:\n\n  static singleton_cleanup_list *s_instance;\n\n  static bool instance_ok ();\n\n  static void cleanup_instance ()\n  {\n    delete s_instance;\n    s_instance = nullptr;\n  }\n\n  std::set<fptr> m_fcn_list;\n\n  void do_add (fptr f)\n  {\n    m_fcn_list.insert (f);\n  }\n};\n\n#endif\n"
  },
  {
    "path": "liboctave/util/sparse-util.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdarg>\n#include <cstdio>\n\n#include \"oct-error.h\"\n#include \"oct-sparse.h\"\n#include \"sparse-util.h\"\n\nstatic inline void\nsparse_chol_error_internal (int status, const char *file,\n                            int line, const char *message)\n{\n#if defined (HAVE_CHOLMOD)\n\n  // Ignore CHOLMOD_NOT_POSDEF, since we handle that in Fchol as an\n  // error or exit status.\n  if (status != CHOLMOD_NOT_POSDEF)\n    (*current_liboctave_warning_with_id_handler)\n      (\"Octave:cholmod-message\", \"warning %i, at line %i in file %s: %s\",\n       status, line, file, message);\n\n#else\n\n  octave_unused_parameter (status);\n  octave_unused_parameter (file);\n  octave_unused_parameter (line);\n  octave_unused_parameter (message);\n\n#endif\n}\n\n// FIXME: this overload is here due to API change in SuiteSparse (3.1 -> 3.2)\n\nvoid\nSparseCholError (int status, char *file, int line, char *message)\n{\n  sparse_chol_error_internal (status, file, line, message);\n}\n\nvoid\nSparseCholError (int status, const char *file, int line, const char *message)\n{\n  sparse_chol_error_internal (status, file, line, message);\n}\n\nint\nSparseCholPrint (const char *fmt, ...)\n{\n  va_list args;\n  va_start (args, fmt);\n  int ret = std::vfprintf (stderr, fmt, args);\n  std::fflush (stderr);\n  va_end (args);\n  return ret;\n}\n\nbool\nsparse_indices_ok (octave_idx_type *r, octave_idx_type *c,\n                   octave_idx_type nrows, octave_idx_type ncols,\n                   octave_idx_type nnz)\n{\n  if (nnz > 0)\n    {\n      if (c[0] != 0)\n        (*current_liboctave_error_handler)\n          (\"invalid sparse matrix: cidx[0] must be zero\");\n\n      octave_idx_type jold = 0;\n\n      for (octave_idx_type j = 1; j < ncols+1; j++)\n        {\n          if (c[j] < c[j-1])\n            (*current_liboctave_error_handler)\n              (\"invalid sparse matrix: cidx elements must appear in ascending order\");\n\n          if (c[j] > nnz)\n            (*current_liboctave_error_handler)\n              (\"invalid sparse matrix: cidx[%\" OCTAVE_IDX_TYPE_FORMAT \"] = \"\n               \"%\" OCTAVE_IDX_TYPE_FORMAT \" exceeds number of nonzero elements\",\n               j, c[j]+1);\n\n          if (c[j] != jold)\n            {\n              for (octave_idx_type i = jold+1; i < c[j]; i++)\n                {\n                  if (r[i] < r[i-1])\n                    (*current_liboctave_error_handler)\n                      (\"invalid sparse matrix: ridx elements must appear \"\n                       \"in ascending order for each column\");\n\n                  if (r[i] >= nrows)\n                    (*current_liboctave_error_handler)\n                      (\"invalid sparse matrix: ridx[%\" OCTAVE_IDX_TYPE_FORMAT\n                       \"] = %\" OCTAVE_IDX_TYPE_FORMAT \" out of range\",\n                       i, r[i]+1);\n                }\n\n              jold = c[j];\n            }\n        }\n    }\n\n  return true;\n}\n"
  },
  {
    "path": "liboctave/util/sparse-util.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1998-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_sparse_util_h)\n#define octave_sparse_util_h 1\n\n#include \"octave-config.h\"\n\n// The next two functions don't do anything unless CHOLMOD is available\n\n// FIXME: This overload is here due to API change in SuiteSparse (3.1 -> 3.2)\nextern OCTAVE_API void\nSparseCholError (int status, char *file, int line, char *message);\n\nextern OCTAVE_API void\nSparseCholError (int status, const char *file, int line, const char *message);\n\nextern OCTAVE_API int\nSparseCholPrint (const char *fmt, ...);\n\nextern OCTAVE_API bool\nsparse_indices_ok (octave_idx_type *r, octave_idx_type *c,\n                   octave_idx_type nrows, octave_idx_type ncols,\n                   octave_idx_type nnz);\n\n#endif\n"
  },
  {
    "path": "liboctave/util/str-vec.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n/*\n\nThe function string_vector::list_in_columns was adapted from a similar\nfunction distributed in the GNU file utilities, copyright (C) 85, 88,\n90, 91, 95, 1996 Free Software Foundation, Inc.\n\n*/\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <ostream>\n#include <string>\n\n#include \"lo-utils.h\"\n#include \"str-vec.h\"\n\n// Create a string vector from a NULL terminated list of C strings.\n\nstring_vector::string_vector (const char * const *s)\n  : m_data ()\n{\n  octave_idx_type n = 0;\n\n  if (s)\n    {\n      const char * const *t = s;\n\n      while (*t++)\n        n++;\n    }\n\n  resize (n);\n\n  for (octave_idx_type i = 0; i < n; i++)\n    elem (i) = s[i];\n}\n\n// Create a string vector from up to N C strings.  Assumes that N is\n// nonnegative.\n\nstring_vector::string_vector (const char * const *s, octave_idx_type n)\n  : m_data (dim_vector (n, 1))\n{\n  for (octave_idx_type i = 0; i < n; i++)\n    elem (i) = s[i];\n}\n\nstring_vector&\nstring_vector::sort (bool make_uniq)\n{\n  // Don't use Array<std::string>::sort () to allow sorting in place.\n  octave_sort<std::string> lsort;\n  lsort.sort (m_data.rwdata (), numel ());\n\n  if (make_uniq)\n    uniq ();\n\n  return *this;\n}\nstring_vector&\nstring_vector::uniq ()\n{\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      octave_idx_type k = 0;\n\n      for (octave_idx_type i = 1; i < len; i++)\n        if (elem (i) != elem (k))\n          if (++k != i)\n            elem (k) = elem (i);\n\n      if (len != ++k)\n        resize (k);\n    }\n\n  return *this;\n}\n\nstring_vector&\nstring_vector::append (const std::string& s)\n{\n  octave_idx_type len = numel ();\n\n  resize (len + 1);\n\n  elem (len) = s;\n\n  return *this;\n}\n\nstring_vector&\nstring_vector::append (const string_vector& sv)\n{\n  octave_idx_type len = numel ();\n  octave_idx_type sv_len = sv.numel ();\n  octave_idx_type new_len = len + sv_len;\n\n  resize (new_len);\n\n  for (octave_idx_type i = 0; i < sv_len; i++)\n    elem (len + i) = sv[i];\n\n  return *this;\n}\n\nstd::string\nstring_vector::join (const std::string& sep) const\n{\n  std::string retval;\n\n  octave_idx_type len = numel ();\n\n  if (len > 0)\n    {\n      octave_idx_type i;\n\n      for (i = 0; i < len - 1; i++)\n        retval += elem (i) + sep;\n\n      retval += elem (i);\n    }\n\n  return retval;\n}\n\nchar **\nstring_vector::c_str_vec () const\n{\n  octave_idx_type len = numel ();\n\n  char **retval = new char * [len + 1];\n\n  retval[len] = nullptr;\n\n  for (octave_idx_type i = 0; i < len; i++)\n    retval[i] = octave::strsave (elem (i).c_str ());\n\n  return retval;\n}\n\nstd::list<std::string>\nstring_vector::std_list () const\n{\n  octave_idx_type len = numel ();\n\n  std::list<std::string> retval;\n\n  for (octave_idx_type i = 0; i < len; i++)\n    retval.push_back (elem (i));\n\n  return retval;\n}\n\nvoid\nstring_vector::delete_c_str_vec (const char * const *v)\n{\n  if (! v)\n    return;\n\n  const char * const *p = v;\n\n  while (*p)\n    delete [] *p++;\n\n  delete [] v;\n}\n\n// Format a list in neat columns.\n\nstd::ostream&\nstring_vector::list_in_columns (std::ostream& os, int width,\n                                const std::string& prefix) const\n{\n  // Compute the maximum name length.\n\n  octave_idx_type max_name_length = 0;\n  octave_idx_type total_names = numel ();\n\n  if (total_names == 0)\n    {\n      // List empty, remember to end output with a newline.\n\n      os << \"\\n\";\n      return os;\n    }\n\n  for (octave_idx_type i = 0; i < total_names; i++)\n    {\n      octave_idx_type name_length = elem (i).length ();\n      if (name_length > max_name_length)\n        max_name_length = name_length;\n    }\n\n  // Allow at least two spaces between names.\n\n  max_name_length += 2;\n\n  // Calculate the maximum number of columns that will fit.\n\n  octave_idx_type line_length = (width <= 0 ? 80 : width) - prefix.length ();\n\n  octave_idx_type nc = line_length / max_name_length;\n  if (nc == 0)\n    nc = 1;\n\n  // Calculate the number of rows that will be in each column except\n  // possibly for a short column on the right.\n\n  octave_idx_type nr = total_names / nc + (total_names % nc != 0);\n\n  octave_idx_type count;\n  for (octave_idx_type row = 0; row < nr; row++)\n    {\n      count = row;\n\n      // Print the next row.\n\n      os << prefix;\n\n      while (1)\n        {\n          std::string nm = elem (count);\n\n          os << nm;\n          octave_idx_type name_length = nm.length ();\n\n          count += nr;\n          if (count >= total_names)\n            break;\n\n          octave_idx_type spaces_to_pad = max_name_length - name_length;\n          for (octave_idx_type i = 0; i < spaces_to_pad; i++)\n            os << ' ';\n        }\n      os << \"\\n\";\n    }\n\n  return os;\n}\n"
  },
  {
    "path": "liboctave/util/str-vec.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1996-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_str_vec_h)\n#define octave_str_vec_h 1\n\n#include \"octave-config.h\"\n\n#include <iosfwd>\n#include <list>\n#include <string>\n\n#include \"Array-oct.h\"\n\nclass OCTAVE_API string_vector\n{\npublic:\n\n  string_vector () = default;\n\n  explicit string_vector (octave_idx_type n) : m_data (dim_vector (n, 1)) { }\n\n  string_vector (const char *s) : m_data (dim_vector (1, 1), s) { }\n\n  string_vector (const std::string& s) : m_data (dim_vector (1, 1), s) { }\n\n  string_vector (const string_vector&) = default;\n\n  string_vector (string_vector&&) = default;\n\n  //! Constructor for STL containers of std::string.\n  //!\n  //! Templated constructor for any template class with std::string as the\n  //! first parameter, and begin, end, and size methods, i.e., a class with\n  //! similar interface as the STL containers.\n\n  template<template <typename...> class String_Container, typename... Other>\n  string_vector (const String_Container<std::string, Other...>& lst);\n\n  string_vector (const Array<std::string>& s)\n    : m_data (s.as_column ()) { }\n\n  string_vector (const char * const *s);\n\n  string_vector (const char * const *s, octave_idx_type n);\n\n  string_vector& operator = (const string_vector&) = default;\n\n  string_vector& operator = (string_vector&&) = default;\n\n  ~string_vector () = default;\n\n  bool empty () const { return numel () == 0; }\n\n  octave_idx_type max_length () const\n  {\n    octave_idx_type n = numel ();\n    octave_idx_type longest = 0;\n\n    for (octave_idx_type i = 0; i < n; i++)\n      {\n        octave_idx_type tmp = elem (i).length ();\n\n        if (tmp > longest)\n          longest = tmp;\n      }\n\n    return longest;\n  }\n\n  void resize (octave_idx_type n, const std::string& rfv = \"\")\n  {\n    m_data.resize (dim_vector (n, 1), rfv);\n  }\n\n  octave_idx_type numel () const { return m_data.numel (); }\n\n  bool isempty () const { return m_data.isempty (); }\n\n  std::string& elem (octave_idx_type i) { return m_data.elem (i); }\n\n  std::string elem (octave_idx_type i) const { return m_data.elem (i); }\n\n  std::string& xelem (octave_idx_type i) { return m_data.xelem (i); }\n\n  std::string xelem (octave_idx_type i) const { return m_data.xelem (i); }\n\n  std::string& operator[] (octave_idx_type i) { return elem (i); }\n\n  std::string operator[] (octave_idx_type i) const { return elem (i); }\n\n  std::string& operator () (octave_idx_type i) { return elem (i); }\n\n  std::string operator () (octave_idx_type i) const { return elem (i); }\n\n  string_vector& sort (bool make_uniq = false);\n\n  string_vector& uniq ();\n\n  string_vector& append (const std::string& s);\n\n  string_vector& append (const string_vector& sv);\n\n  std::string join (const std::string& sep = \"\") const;\n\n  char ** c_str_vec () const;\n\n  std::list<std::string> std_list () const;\n\n  static void delete_c_str_vec (const char * const*);\n\n  std::ostream&\n  list_in_columns (std::ostream&, int width = 0,\n                   const std::string& prefix = \"\") const;\n\n  string_vector linear_slice (octave_idx_type lo, octave_idx_type up) const\n  {\n    return string_vector (m_data.linear_slice (lo, up));\n  }\n\n  template <typename U, typename F> Array<U> map (F fcn) const\n  {\n    return m_data.map<U> (fcn);\n  }\n\nprivate:\n\n  Array<std::string> m_data;\n};\n\n\ntemplate<template <typename...> class String_Container, typename... Other>\nstring_vector::string_vector (const String_Container<std::string, Other...>&\n                              lst)\n  : m_data ()\n{\n  resize (lst.size ());\n\n  octave_idx_type i = 0;\n  for (const std::string& s : lst)\n    elem (i++) = s;\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/util/unwind-prot.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"oct-error.h\"\n#include \"unwind-prot.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nvoid\nunwind_protect_safe::warn_unhandled_exception () const\n{\n  (*current_liboctave_warning_handler)\n    (\"unhandled exception in unwind_protect_safe handler.  \"\n     \"It is a bug in Octave for this to happen.  \"\n     \"Please help improve Octave by reporting it.\");\n}\n\nvoid\nunwind_action_safe::warn_unhandled_exception () const\n{\n  (*current_liboctave_warning_handler)\n    (\"unhandled exception in unwind_action_safe handler.  \"\n     \"It is a bug in Octave for this to happen.  \"\n     \"Please help improve Octave by reporting it.\");\n}\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/unwind-prot.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_unwind_prot_h)\n#define octave_unwind_prot_h 1\n\n#include \"octave-config.h\"\n\n#include <cstddef>\n\n#include <stack>\n#include <memory>\n\n#include \"action-container.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nclass OCTAVE_API unwind_protect : public action_container\n{\npublic:\n\n  unwind_protect () : m_lifo () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (unwind_protect)\n\n  // Destructor should not raise an exception, so all actions\n  // registered should be exception-safe.  If you're not sure, see\n  // unwind_protect_safe.\n\n  ~unwind_protect () { run (); }\n\n  operator bool () const { return ! empty (); }\n\n  void run_first ()\n  {\n    if (! empty ())\n      {\n        // No leak on exception!\n        std::unique_ptr<elem> ptr (m_lifo.top ());\n        m_lifo.pop ();\n        ptr->run ();\n      }\n  }\n\n  void discard_first ()\n  {\n    if (! empty ())\n      {\n        elem *ptr = m_lifo.top ();\n        m_lifo.pop ();\n        delete ptr;\n      }\n  }\n\n  std::size_t size () const { return m_lifo.size (); }\n\nprotected:\n\n  virtual void add_action (elem *new_elem)\n  {\n    m_lifo.push (new_elem);\n  }\n\n  std::stack<elem *> m_lifo;\n};\n\n// Like unwind_protect, but this one will guard against the possibility\n// of seeing an exception (or interrupt) in the cleanup actions.\n// Not that we can do much about it, but at least we won't crash.\n\nclass OCTAVE_API unwind_protect_safe : public unwind_protect\n{\nprivate:\n\n  void warn_unhandled_exception () const;\n\npublic:\n\n  unwind_protect_safe () : unwind_protect () { }\n\n  OCTAVE_DISABLE_COPY_MOVE (unwind_protect_safe)\n\n  ~unwind_protect_safe ()\n  {\n    while (! empty ())\n      {\n        try\n          {\n            run_first ();\n          }\n        catch (...) // Yes, the black hole.  Remember we're in a destructor.\n          {\n            warn_unhandled_exception ();\n          }\n      }\n  }\n};\n\n// In most cases, the following are preferred for efficiency.  Some\n// cases may require the flexibility of the general unwind_protect\n// mechanism defined above.\n\n// Perform action at end of the current scope when unwind_action\n// object destructor is called.\n//\n// For example:\n//\n//   void fcn (int val) { ... }\n//\n// ...\n//\n//   {\n//     int val = 42;\n//\n//     // template parameters, std::bind and std::function provide\n//     // flexibility in calling forms (function pointer or lambda):\n//\n//     unwind_action act1 (fcn, val);\n//     unwind_action act2 ([val] () { fcn (val); });\n//   }\n//\n// NOTE: Don't forget to provide a name for the unwind_action\n// variable.  If you write\n//\n//   unwind_action /* NO NAME! */ (...);\n//\n// then the destructor for the temporary anonymous object will be\n// called immediately after the object is constructed instead of at\n// the end of the current scope.\n\nclass OCTAVE_API unwind_action\n{\npublic:\n\n  unwind_action () : m_fcn () { }\n\n  // FIXME: Do we need to apply std::forward to the arguments to\n  // std::bind here?\n\n  template <typename F, typename... Args>\n  unwind_action (F&& fcn, Args&& ... args)\n    : m_fcn (std::bind (fcn, args...))\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (unwind_action)\n\n  ~unwind_action () { run (); }\n\n  // FIXME: Do we need to apply std::forward to the arguments to\n  // std::bind here?\n\n  template <typename F, typename... Args>\n  void set (F&& fcn, Args&& ... args)\n  {\n    m_fcn = std::bind (fcn, args...);\n  }\n\n  void set () { m_fcn = nullptr; }\n\n  // Alias for set() which is clearer about programmer intention.\n  void discard () { set (); }\n\n  void run ()\n  {\n    if (m_fcn)\n      m_fcn ();\n\n    // Invalidate so action won't run again when object is deleted.\n    discard ();\n  }\n\nprivate:\n\n  std::function<void ()> m_fcn;\n};\n\n// Like unwind_action, but this one will guard against the possibility\n// of seeing an exception (or interrupt) in the cleanup actions.\n// Not that we can do much about it, but at least we won't crash.\n\nclass OCTAVE_API unwind_action_safe\n{\nprivate:\n\n  void warn_unhandled_exception () const;\n\npublic:\n\n  unwind_action_safe () : m_fcn () { }\n\n  // FIXME: Do we need to apply std::forward to the arguments to\n  // std::bind here?\n\n  template <typename F, typename... Args>\n  unwind_action_safe (F&& fcn, Args&& ... args)\n    : m_fcn (std::bind (fcn, args...))\n  { }\n\n  OCTAVE_DISABLE_COPY_MOVE (unwind_action_safe)\n\n  ~unwind_action_safe () { run (); }\n\n  // FIXME: Do we need to apply std::forward to the arguments to\n  // std::bind here?\n\n  template <typename F, typename... Args>\n  void set (F&& fcn, Args&& ... args)\n  {\n    m_fcn = std::bind (fcn, args...);\n  }\n\n  void set () { m_fcn = nullptr; }\n\n  // Alias for set() which is clearer about programmer intention.\n  void discard () { set (); }\n\n  void run ()\n  {\n    try\n      {\n        if (m_fcn)\n          m_fcn ();\n      }\n    catch (...) // Yes, the black hole.  Remember we're in a destructor.\n      {\n        warn_unhandled_exception ();\n      }\n\n    // Invalidate so action won't run again when object is deleted.\n    discard ();\n  }\n\nprivate:\n\n  std::function<void ()> m_fcn;\n};\n\n// Reset a variable value at the end of the current scope when\n// unwind_protect_var object destructor is called.\n//\n// For example:\n//\n//   {\n//     int x = 42;\n//     unwind_protect_var<int> upv (x);  // X will be reset at end of scope\n//     x = 13;                           // Set temporary value.\n//   }\n//\n// Temporary value may be set at construction:\n//\n//   {\n//     int x = ...;\n//     unwind_protect_var<int> upv (x, 13);  // X will be reset.\n//                                           // temporary value is 13.\n//   }\n//\n// NOTE: Don't forget to provide a name for the unwind_protect_var\n// variable.  If you write\n//\n//   unwind_protect_var<type> /* NO NAME! */ (...);\n//\n// then the destructor for the temporary anonymous object will be\n// called immediately after the object is constructed instead of at\n// the end of the current scope.\n//\n// FIXME: Once we are able to use C++17, class template argument\n// deduction will allow us to omit the explicit template type from the\n// constructor expression:\n//\n//   unwind_protect_var upv (...);\n\ntemplate <typename T>\nclass unwind_protect_var\n{\npublic:\n\n  // Ensure that the value referenced by REF will be reset when this\n  // unwind_protect_var object goes out of scope.\n\n  explicit unwind_protect_var (T& ref)\n    : m_ref (ref), m_val (ref)\n  { }\n\n  // Set the value referenced by REF to NEW_VAL and ensure that it\n  // will be reset to its original value when this\n  // unwind_protect_var object goes out of scope.\n\n  unwind_protect_var (T& ref, const T& new_val)\n    : m_ref (ref), m_val (ref)\n  {\n    m_ref = new_val;\n  }\n\n  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (unwind_protect_var)\n\n  ~unwind_protect_var ()\n  {\n    m_ref = m_val;\n  }\n\nprivate:\n\n  T& m_ref;\n  T m_val;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/util/url-transfer.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <fstream>\n#include <iostream>\n\n#include \"dir-ops.h\"\n#include \"file-ops.h\"\n#include \"file-stat.h\"\n#include \"oct-env.h\"\n#include \"oct-sysdep.h\"\n#include \"unwind-prot.h\"\n#include \"url-transfer.h\"\n#include \"version.h\"\n\n#if defined (HAVE_CURL)\n#  include <curl/curl.h>\n#  include <curl/easy.h>\n#endif\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nbase_url_transfer::base_url_transfer ()\n  : m_host_or_url (), m_valid (false), m_ftp (false),\n    m_ascii_mode (false), m_ok (true), m_errmsg (),\n    m_curr_istream (&std::cin), m_curr_ostream (&std::cout)\n{ }\n\nbase_url_transfer::base_url_transfer (const std::string& host,\n                                      const std::string& /* user_arg */,\n                                      const std::string& /* passwd */,\n                                      std::ostream& os)\n  : m_host_or_url (host), m_valid (false), m_ftp (true),\n    m_ascii_mode (false), m_ok (true), m_errmsg (),\n    m_curr_istream (&std::cin), m_curr_ostream (&os)\n{ }\n\nbase_url_transfer::base_url_transfer (const std::string& url,\n                                      std::ostream& os)\n  : m_host_or_url (url), m_valid (false), m_ftp (false),\n    m_ascii_mode (false), m_ok (true), m_errmsg (),\n    m_curr_istream (&std::cin), m_curr_ostream (&os)\n{ }\n\nvoid\nbase_url_transfer::mget_directory (const std::string& directory,\n                                   const std::string& target)\n{\n  std::string sep = sys::file_ops::dir_sep_str ();\n\n  if (! sys::dir_exists (directory))\n    {\n      std::string msg;\n      int status = sys::mkdir (directory, 0777, msg);\n\n      if (status < 0)\n        {\n          m_ok = false;\n          m_errmsg = \"__ftp_mget__: can not create directory '\"\n                     + target + sep + directory + \"': \" + msg;\n          return;\n        }\n    }\n\n  cwd (directory);\n\n  if (good ())\n    {\n      unwind_action_safe reset_path (&base_url_transfer::cwd, this, \"..\");\n\n      string_vector sv = list ();\n\n      for (octave_idx_type i = 0; i < sv.numel (); i++)\n        {\n          OCTAVE_TIME_T ftime;\n          bool fisdir;\n          double fsize;\n\n          get_fileinfo (sv(i), fsize, ftime, fisdir);\n\n          if (fisdir)\n            mget_directory (sv(i), target + directory + sep);\n          else\n            {\n              std::string realfile = target + directory + sep + sv(i);\n\n              std::ofstream ofile =\n                sys::ofstream (realfile.c_str (),\n                               std::ios::out | std::ios::binary);\n\n              if (! ofile.is_open ())\n                {\n                  m_ok = false;\n                  m_errmsg = \"__ftp_mget__: unable to open file\";\n                  break;\n                }\n              int(*unlink_fptr)(const std::string&) = sys::unlink;\n              unwind_action_safe delete_file (unlink_fptr, realfile);\n\n              get (sv(i), ofile);\n\n              ofile.close ();\n\n              if (good ())\n                delete_file.discard ();\n            }\n\n          if (! good ())\n            break;\n        }\n    }\n}\n\nstring_vector\nbase_url_transfer::mput_directory (const std::string& base,\n                                   const std::string& directory)\n{\n  string_vector file_list;\n\n  std::string realdir\n    = (base.empty ()\n       ? directory : base + sys::file_ops::dir_sep_str () + directory);\n\n  mkdir (directory);\n\n  if (! good ())\n    return file_list;\n\n  cwd (directory);\n\n  if (good ())\n    {\n      unwind_action_safe reset_path (&base_url_transfer::cwd, this, \"..\");\n\n      string_vector files;\n      std::string msg;\n\n      if (sys::get_dirlist (realdir, files, msg))\n        for (octave_idx_type i = 0; i < files.numel (); i++)\n          {\n            std::string file = files (i);\n\n            if (file == \".\" || file == \"..\")\n              continue;\n\n            std::string realfile\n              = realdir + sys::file_ops::dir_sep_str () + file;\n\n            if (! sys::file_exists (realfile))\n              {\n                m_ok = false;\n                m_errmsg = \"__ftp__mput: file '\" + realfile\n                           + \"' does not exist\";\n                break;\n              }\n\n            if (sys::dir_exists (realfile))\n              {\n                file_list.append (mput_directory (realdir, file));\n\n                if (! good ())\n                  break;\n              }\n            else\n              {\n                // FIXME: Does ascii mode need to be flagged here?\n                std::ifstream ifile =\n                  sys::ifstream (realfile.c_str (),\n                                 std::ios::in | std::ios::binary);\n\n                if (! ifile.is_open ())\n                  {\n                    m_ok = false;\n                    m_errmsg = \"__ftp_mput__: unable to open file '\"\n                               + realfile + \"'\";\n                    break;\n                  }\n\n                put (file, ifile);\n\n                ifile.close ();\n\n                if (! good ())\n                  break;\n\n                file_list.append (realfile);\n              }\n          }\n      else\n        {\n          m_ok = false;\n          m_errmsg = \"__ftp_mput__: can not read the directory '\"\n                     + realdir + \"'\";\n        }\n    }\n\n  return file_list;\n}\n\n#if defined (HAVE_CURL)\n\nstatic int\nwrite_data (void *buffer, std::size_t size, std::size_t nmemb, void *streamp)\n{\n  std::ostream& stream = *(static_cast<std::ostream *> (streamp));\n  stream.write (static_cast<const char *> (buffer), size*nmemb);\n  return (stream.fail () ? 0 : size * nmemb);\n}\n\nstatic int\nread_data (void *buffer, std::size_t size, std::size_t nmemb, void *streamp)\n{\n  std::istream& stream = *(static_cast<std::istream *> (streamp));\n  stream.read (static_cast<char *> (buffer), size*nmemb);\n  if (stream.eof ())\n    return stream.gcount ();\n  else\n    return (stream.fail () ? 0 : size * nmemb);\n}\n\nstatic std::size_t\nthrow_away (void *, std::size_t size, std::size_t nmemb, void *)\n{\n  return static_cast<std::size_t> (size * nmemb);\n}\n\n// I'd love to rewrite this as a private method of the url_transfer\n// class, but you can't pass the va_list from the wrapper SETOPT to\n// the curl_easy_setopt function.\n#define SETOPT(option, parameter)                                       \\\n  do                                                                    \\\n    {                                                                   \\\n      CURLcode res = curl_easy_setopt (m_curl, option, parameter);      \\\n      if (res != CURLE_OK)                                              \\\n        {                                                               \\\n          m_ok = false;                                                 \\\n          m_errmsg = curl_easy_strerror (res);                          \\\n          return;                                                       \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\n// Same as above but with a return value.\n#define SETOPTR(option, parameter)                                      \\\n  do                                                                    \\\n    {                                                                   \\\n      CURLcode res = curl_easy_setopt (m_curl, option, parameter);      \\\n      if (res != CURLE_OK)                                              \\\n        {                                                               \\\n          m_ok = false;                                                 \\\n          m_errmsg = curl_easy_strerror (res);                          \\\n          return retval;                                                \\\n        }                                                               \\\n    }                                                                   \\\n  while (0)\n\nclass curl_transfer : public base_url_transfer\n{\npublic:\n\n  curl_transfer ()\n    : base_url_transfer (), m_curl (curl_easy_init ()), m_errnum (), m_url (),\n      m_userpwd ()\n  {\n    if (m_curl)\n      m_valid = true;\n    else\n      m_errmsg = \"can not create curl object\";\n  }\n\n  curl_transfer (const std::string& host, const std::string& user_arg,\n                 const std::string& passwd, std::ostream& os)\n    : base_url_transfer (host, user_arg, passwd, os),\n      m_curl (curl_easy_init ()), m_errnum (), m_url (), m_userpwd ()\n  {\n    if (m_curl)\n      m_valid = true;\n    else\n      {\n        m_errmsg = \"can not create curl object\";\n        return;\n      }\n\n    init (user_arg, passwd, std::cin, os);\n\n    m_url = \"ftp://\" + host;\n    SETOPT (CURLOPT_URL, m_url.c_str ());\n\n    // Set up the link, with no transfer.\n    perform ();\n  }\n\n  curl_transfer (const std::string& url_str, std::ostream& os)\n    : base_url_transfer (url_str, os), m_curl (curl_easy_init ()),\n      m_errnum (), m_url (), m_userpwd ()\n  {\n    if (m_curl)\n      m_valid = true;\n    else\n      {\n        m_errmsg = \"can not create curl object\";\n        return;\n      }\n\n    init (\"\", \"\", std::cin, os);\n\n    std::string cainfo = sys::env::getenv (\"CURLOPT_CAINFO\");\n    if (! cainfo.empty ())\n      SETOPT (CURLOPT_CAINFO, cainfo.c_str ());\n\n    std::string capath = sys::env::getenv (\"CURLOPT_CAPATH\");\n    if (! capath.empty ())\n      SETOPT (CURLOPT_CAPATH, capath.c_str ());\n\n    SETOPT (CURLOPT_NOBODY, 0);\n\n    // Restore the default HTTP request method to GET after setting\n    // NOBODY to true (in the init method) and back to false (above).\n    // This is needed for backward compatibility with versions of\n    // libcurl < 7.18.2.\n    SETOPT (CURLOPT_HTTPGET, 1);\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (curl_transfer)\n\n  ~curl_transfer ()\n  {\n    if (m_curl)\n      curl_easy_cleanup (m_curl);\n  }\n\n  void perform ()\n  {\n    m_errnum = curl_easy_perform (m_curl);\n\n    if (m_errnum != CURLE_OK)\n      {\n        m_ok = false;\n        m_errmsg = curl_easy_strerror (m_errnum);\n      }\n  }\n\n  std::string lasterror () const\n  {\n    return std::string (curl_easy_strerror (m_errnum));\n  }\n\n  std::ostream& set_ostream (std::ostream& os)\n  {\n    std::ostream& retval = *m_curr_ostream;\n    m_curr_ostream = &os;\n    SETOPTR (CURLOPT_WRITEDATA, static_cast<void *> (m_curr_ostream));\n    return retval;\n  }\n\n  std::istream& set_istream (std::istream& is)\n  {\n    std::istream& retval = *m_curr_istream;\n    m_curr_istream = &is;\n    SETOPTR (CURLOPT_READDATA, static_cast<void *> (m_curr_istream));\n    return retval;\n  }\n\n  void ascii ()\n  {\n    m_ascii_mode = true;\n    SETOPT (CURLOPT_TRANSFERTEXT, 1);\n  }\n\n  void binary ()\n  {\n    m_ascii_mode = false;\n    SETOPT (CURLOPT_TRANSFERTEXT, 0);\n  }\n\n  void cwd (const std::string& path)\n  {\n    ftp_file_or_dir_action (path, \"cwd\");\n  }\n\n  void del (const std::string& file)\n  {\n    ftp_file_or_dir_action (file, \"dele\");\n  }\n\n  void rmdir (const std::string& path)\n  {\n    ftp_file_or_dir_action (path, \"rmd\");\n  }\n\n  void mkdir (const std::string& path)\n  {\n    ftp_file_or_dir_action (path, \"mkd\");\n  }\n\n  void rename (const std::string& oldname, const std::string& newname)\n  {\n    struct curl_slist *slist = nullptr;\n\n    unwind_action cleanup_slist ([slist] () { curl_slist_free_all (slist); });\n\n    std::string cmd = \"rnfr \" + oldname;\n    slist = curl_slist_append (slist, cmd.c_str ());\n    cmd = \"rnto \" + newname;\n    slist = curl_slist_append (slist, cmd.c_str ());\n    SETOPT (CURLOPT_POSTQUOTE, slist);\n\n    perform ();\n    if (! good ())\n      return;\n\n    SETOPT (CURLOPT_POSTQUOTE, 0);\n  }\n\n  void put (const std::string& file, std::istream& is)\n  {\n    m_url = \"ftp://\" + m_host_or_url + '/' + file;\n    SETOPT (CURLOPT_URL, m_url.c_str ());\n    SETOPT (CURLOPT_UPLOAD, 1);\n    SETOPT (CURLOPT_NOBODY, 0);\n    std::istream& old_is = set_istream (is);\n\n    perform ();\n    if (! good ())\n      return;\n\n    set_istream (old_is);\n    SETOPT (CURLOPT_NOBODY, 1);\n    SETOPT (CURLOPT_UPLOAD, 0);\n    m_url = \"ftp://\" + m_host_or_url;\n    SETOPT (CURLOPT_URL, m_url.c_str ());\n  }\n\n  void get (const std::string& file, std::ostream& os)\n  {\n    m_url = \"ftp://\" + m_host_or_url + '/' + file;\n    SETOPT (CURLOPT_URL, m_url.c_str ());\n    SETOPT (CURLOPT_NOBODY, 0);\n    std::ostream& old_os = set_ostream (os);\n\n    perform ();\n    if (! good ())\n      return;\n\n    set_ostream (old_os);\n    SETOPT (CURLOPT_NOBODY, 1);\n    m_url = \"ftp://\" + m_host_or_url;\n    SETOPT (CURLOPT_URL, m_url.c_str ());\n  }\n\n  void dir ()\n  {\n    m_url = \"ftp://\" + m_host_or_url + '/';\n    SETOPT (CURLOPT_URL, m_url.c_str ());\n    SETOPT (CURLOPT_NOBODY, 0);\n\n    perform ();\n    if (! good ())\n      return;\n\n    SETOPT (CURLOPT_NOBODY, 1);\n    m_url = \"ftp://\" + m_host_or_url;\n    SETOPT (CURLOPT_URL, m_url.c_str ());\n  }\n\n  string_vector list ()\n  {\n    string_vector retval;\n\n    std::ostringstream buf;\n    m_url = \"ftp://\" + m_host_or_url + '/';\n    SETOPTR (CURLOPT_WRITEDATA, static_cast<void *> (&buf));\n    SETOPTR (CURLOPT_URL, m_url.c_str ());\n    SETOPTR (CURLOPT_DIRLISTONLY, 1);\n    SETOPTR (CURLOPT_NOBODY, 0);\n\n    perform ();\n    if (! good ())\n      return retval;\n\n    SETOPTR (CURLOPT_NOBODY, 1);\n    m_url = \"ftp://\" + m_host_or_url;\n    SETOPTR (CURLOPT_WRITEDATA, static_cast<void *> (m_curr_ostream));\n    SETOPTR (CURLOPT_DIRLISTONLY, 0);\n    SETOPTR (CURLOPT_URL, m_url.c_str ());\n\n    // Count number of directory entries\n    std::string str = buf.str ();\n    octave_idx_type n = 0;\n    std::size_t pos = 0;\n    while (true)\n      {\n        pos = str.find_first_of ('\\n', pos);\n        if (pos == std::string::npos)\n          break;\n        pos++;\n        n++;\n      }\n    retval.resize (n);\n    pos = 0;\n    for (octave_idx_type i = 0; i < n; i++)\n      {\n        std::size_t newpos = str.find_first_of ('\\n', pos);\n        if (newpos == std::string::npos)\n          break;\n\n        std::string name = str.substr (pos, newpos - pos);\n        // remove trailing \\r if there is one\n        if (name.length () > 0 && name.back () == '\\r')\n          name.pop_back ();\n\n        retval(i) = name;\n        pos = newpos + 1;\n      }\n\n    return retval;\n  }\n\n  void get_fileinfo (const std::string& filename, double& filesize,\n                     OCTAVE_TIME_T& filetime, bool& fileisdir)\n  {\n    std::string path = pwd ();\n\n    m_url = \"ftp://\" + m_host_or_url + '/' + path + '/' + filename;\n    SETOPT (CURLOPT_URL, m_url.c_str ());\n    SETOPT (CURLOPT_FILETIME, 1);\n    SETOPT (CURLOPT_HEADERFUNCTION, throw_away);\n    SETOPT (CURLOPT_WRITEFUNCTION, throw_away);\n\n    // FIXME\n    // The MDTM command fails for a directory on the servers I tested\n    // so this is a means of testing for directories.  It also means\n    // I can't get the date of directories!\n\n    perform ();\n    if (! good ())\n      {\n        fileisdir = true;\n        filetime = -1;\n        filesize = 0;\n\n        return;\n      }\n\n    fileisdir = false;\n    OCTAVE_TIME_T ft;\n    curl_easy_getinfo (m_curl, CURLINFO_FILETIME, &ft);\n    filetime = ft;\n    double fs;\n    curl_easy_getinfo (m_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &fs);\n    filesize = fs;\n\n    SETOPT (CURLOPT_WRITEFUNCTION, write_data);\n    SETOPT (CURLOPT_HEADERFUNCTION, 0);\n    SETOPT (CURLOPT_FILETIME, 0);\n    m_url = \"ftp://\" + m_host_or_url;\n    SETOPT (CURLOPT_URL, m_url.c_str ());\n\n    // The MDTM command seems to reset the path to the root with the\n    // servers I tested with, so cd again into the correct path.  Make\n    // the path absolute so that this will work even with servers that\n    // don't end up in the root after an MDTM command.\n    cwd ('/' + path);\n  }\n\n  std::string pwd ()\n  {\n    std::string retval;\n\n    struct curl_slist *slist = nullptr;\n\n    unwind_action cleanup_slist ([slist] () { curl_slist_free_all (slist); });\n\n    slist = curl_slist_append (slist, \"pwd\");\n    SETOPTR (CURLOPT_POSTQUOTE, slist);\n    SETOPTR (CURLOPT_HEADERFUNCTION, write_data);\n\n    std::ostringstream buf;\n    SETOPTR (CURLOPT_WRITEHEADER, static_cast<void *> (&buf));\n\n    perform ();\n    if (! good ())\n      return retval;\n\n    retval = buf.str ();\n\n    // Can I assume that the path is always in \"\" on the last line\n    std::size_t pos2 = retval.rfind ('\"');\n    std::size_t pos1 = retval.rfind ('\"', pos2 - 1);\n    retval = retval.substr (pos1 + 1, pos2 - pos1 - 1);\n\n    SETOPTR (CURLOPT_HEADERFUNCTION, 0);\n    SETOPTR (CURLOPT_WRITEHEADER, 0);\n    SETOPTR (CURLOPT_POSTQUOTE, 0);\n\n    return retval;\n  }\n\n  void http_get (const Array<std::string>& param)\n  {\n    http_action (param, \"get\");\n  }\n\n  void http_post (const Array<std::string>& param)\n  {\n    http_action (param, \"post\");\n  }\n\n  void http_action (const Array<std::string>& param, const std::string& action)\n  {\n    m_url = m_host_or_url;\n\n    std::string query_string;\n\n    query_string = form_query_string (param);\n\n    if (action.empty () || action == \"get\")\n      {\n        if (! query_string.empty ())\n          m_url += '?' + query_string;\n\n        SETOPT (CURLOPT_URL, m_url.c_str ());\n      }\n    else if (action == \"post\" || action == \"put\" || action == \"delete\")\n      {\n        SETOPT (CURLOPT_POSTFIELDS, query_string.c_str ());\n\n        if (action == \"put\")\n          {\n            SETOPT (CURLOPT_CUSTOMREQUEST, \"PUT\");\n          }\n\n        if (action == \"delete\")\n          {\n            SETOPT (CURLOPT_CUSTOMREQUEST, \"DELETE\");\n          }\n\n        SETOPT (CURLOPT_URL, m_url.c_str ());\n      }\n    else\n      {\n        m_ok = false;\n        m_errmsg = \"curl_transfer: unknown http action\";\n      }\n\n    if (m_ok)\n      perform ();\n  }\n\n  void cookie_jar (const std::string& filename)\n  {\n    SETOPT (CURLOPT_COOKIEJAR, filename.c_str ());\n\n    SETOPT (CURLOPT_COOKIEFILE, filename.c_str ());\n  }\n\n  // Sets the header fields in a transfer.  Input should be in the form\n  // of an array of strings with pairs of keys and values together\n  void set_header_fields (const Array<std::string>& param)\n  {\n    struct curl_slist *slist = nullptr;\n\n    unwind_action cleanup_slist ([slist] () { curl_slist_free_all (slist); });\n\n    if (param.numel () >= 2)\n      {\n        for (int i = 0; i < param.numel (); i += 2)\n          {\n            std::string header = param(i) + \": \" + param(i+1);\n\n            slist = curl_slist_append (slist, header.c_str ());\n          }\n\n        SETOPT (CURLOPT_HTTPHEADER, slist);\n      }\n  }\n\n  // Sets and sends the form data associated with a transfer.\n  // Input should be an array of strings with each pair of strings\n  // corresponding to the fieldname and it's value.\n  // To attach a file, you should use 'file' as the fieldname with the\n  // path of the file as its value.\n  void form_data_post (const Array<std::string>& param)\n  {\n    curl_mime *mime = nullptr;\n    curl_mimepart *part = nullptr;\n\n    SETOPT (CURLOPT_URL, m_host_or_url.c_str ());\n\n    unwind_action cleanup_mime ([mime] () { curl_mime_free (mime); });\n\n    if (param.numel () >= 2)\n      {\n        for (int i = 0; i < param.numel (); i += 2)\n          {\n            std::string name = param(i);\n            std::string data = param(i+1);\n\n            part = curl_mime_addpart (mime);\n            curl_mime_name (part, name.c_str ());\n            if (name == \"file\")\n              curl_mime_filedata (part, data.c_str ());\n            else\n              curl_mime_data (part, data.c_str (), CURL_ZERO_TERMINATED);\n          }\n\n        SETOPT (CURLOPT_MIMEPOST, mime);\n      }\n\n    perform ();\n  }\n\n  // Sets the various options specified by weboptions object.\n  void set_weboptions (const struct weboptions& options)\n  {\n    set_header_fields (options.HeaderFields);\n\n    SETOPT (CURLOPT_TIMEOUT_MS, options.Timeout);\n    SETOPT (CURLOPT_CONNECTTIMEOUT_MS, options.Timeout);\n\n    if (! options.UserAgent.empty ())\n      SETOPT (CURLOPT_USERAGENT, options.UserAgent.c_str ());\n\n    if (! options.Username.empty ())\n      {\n        if (! options.Password.empty ())\n          {\n            std::string tmp = options.Username + \":\" + options.Password;\n            SETOPT (CURLOPT_USERPWD, tmp.c_str ());\n          }\n        else\n          {\n            std::string tmp = options.Username + \":\";\n            SETOPT (CURLOPT_USERPWD, tmp.c_str ());\n          }\n      }\n\n    // FIXME: Implement missing options for MATLAB compatibility.\n    /*************************************************************\n    if (! options.ContentReader.empty ())\n      { }\n\n    if (! options.ArrayFormat.empty ())\n      { }\n\n    if (! options.CertificateFilename.empty ())\n      { }\n\n    *************************************************************/\n  }\n\nprivate:\n\n  // Pointer to cURL object.\n  CURL *m_curl;\n\n  // cURL error code.\n  CURLcode m_errnum;\n\n  // The cURL library changed the curl_easy_setopt call to make an\n  // internal copy of string parameters in version 7.17.0.  Prior\n  // versions only held a pointer to a string provided by the caller\n  // that must persist for the lifetime of the CURL handle.\n  //\n  // The associated API did not change, only the behavior of the library\n  // implementing the function call.\n  //\n  // To be compatible with any version of cURL, the caller must keep a\n  // copy of all string parameters associated with a CURL handle until\n  // the handle is released.  The curl_handle::curl_handle_rep class\n  // contains the pointer to the CURL handle and so is the best\n  // candidate for storing the strings as well. (bug #36717)\n  std::string m_url;\n  std::string m_userpwd;\n\n  void init (const std::string& user, const std::string& passwd,\n             std::istream& is, std::ostream& os)\n  {\n    // No data transfer by default\n    SETOPT (CURLOPT_NOBODY, 1);\n\n    // Set the username and password\n    m_userpwd = user;\n    if (! passwd.empty ())\n      m_userpwd += ':' + passwd;\n    if (! m_userpwd.empty ())\n      SETOPT (CURLOPT_USERPWD, m_userpwd.c_str ());\n\n    // Define our callback to get called when there's data to be written.\n    SETOPT (CURLOPT_WRITEFUNCTION, write_data);\n\n    // Set a pointer to our struct to pass to the callback.\n    SETOPT (CURLOPT_WRITEDATA, static_cast<void *> (&os));\n\n    // Define our callback to get called when there's data to be read\n    SETOPT (CURLOPT_READFUNCTION, read_data);\n\n    // Set a pointer to our struct to pass to the callback.\n    SETOPT (CURLOPT_READDATA, static_cast<void *> (&is));\n\n    // Follow redirects.\n    SETOPT (CURLOPT_FOLLOWLOCATION, true);\n\n    // Don't use EPSV since connecting to sites that don't support it\n    // will hang for some time (3 minutes?) before moving on to try PASV\n    // instead.\n    SETOPT (CURLOPT_FTP_USE_EPSV, false);\n\n    // Set the user agent for the curl request\n    // Needed by mediaWiki API.\n    curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);\n    const char *lib_ver = data->version;\n    std::string user_agent\n    (\"GNU Octave/\"\n     + std::string (OCTAVE_VERSION)\n     + \" (https://www.octave.org/) libcurl/\"\n     + std::string (lib_ver));\n\n    SETOPT (CURLOPT_USERAGENT, user_agent.c_str ());\n\n    SETOPT (CURLOPT_NOPROGRESS, true);\n    SETOPT (CURLOPT_FAILONERROR, true);\n\n    SETOPT (CURLOPT_POSTQUOTE, 0);\n    SETOPT (CURLOPT_QUOTE, 0);\n  }\n\n  std::string form_query_string (const Array<std::string>& param)\n  {\n    std::ostringstream query;\n\n    if (param.numel () >= 2)\n      for (int i = 0; i < param.numel (); i += 2)\n        {\n          std::string name = param(i);\n          std::string text = param(i+1);\n\n          // Encode strings.\n          char *enc_name = curl_easy_escape (m_curl, name.c_str (),\n                                             name.length ());\n          char *enc_text = curl_easy_escape (m_curl, text.c_str (),\n                                             text.length ());\n\n          query << enc_name << '=' << enc_text;\n\n          curl_free (enc_name);\n          curl_free (enc_text);\n\n          if (i < param.numel ()-2)\n            query << '&';\n        }\n\n    query.flush ();\n\n    return query.str ();\n  }\n\n  void ftp_file_or_dir_action (const std::string& file_or_dir,\n                               const std::string& action)\n  {\n    struct curl_slist *slist = nullptr;\n\n    unwind_action cleanup_slist ([slist] () { curl_slist_free_all (slist); });\n\n    std::string cmd = action + ' ' + file_or_dir;\n\n    slist = curl_slist_append (slist, cmd.c_str ());\n\n    SETOPT (CURLOPT_POSTQUOTE, slist);\n\n    perform ();\n\n    if (! good ())\n      return;\n\n    SETOPT (CURLOPT_POSTQUOTE, 0);\n  }\n};\n\n#undef SETOPT\n\n#endif\n\n#if defined (HAVE_CURL)\n#  define REP_CLASS curl_transfer\n#else\n#  define REP_CLASS base_url_transfer\n#endif\n\nurl_transfer::url_transfer () : m_rep (new REP_CLASS ())\n{ }\n\nurl_transfer::url_transfer (const std::string& host, const std::string& user,\n                            const std::string& passwd, std::ostream& os)\n  : m_rep (new REP_CLASS (host, user, passwd, os))\n{ }\n\nurl_transfer::url_transfer (const std::string& url, std::ostream& os)\n  : m_rep (new REP_CLASS (url, os))\n{ }\n\n#undef REP_CLASS\n\nOCTAVE_END_NAMESPACE(octave)\n"
  },
  {
    "path": "liboctave/util/url-transfer.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2006-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_url_transfer_h)\n#define octave_url_transfer_h 1\n\n#include \"octave-config.h\"\n\n#include <istream>\n#include <memory>\n#include <ostream>\n#include <string>\n\n#include \"Array-fwd.h\"\n#include \"str-vec.h\"\n\nOCTAVE_BEGIN_NAMESPACE(octave)\n\nstruct weboptions\n{\n  std::string CharacterEncoding;\n  std::string UserAgent;\n  long Timeout;\n  std::string Username;\n  std::string Password;\n  std::string ContentReader;\n  std::string RequestMethod;\n  std::string ArrayFormat;\n  Array<std::string> HeaderFields;\n  std::string CertificateFilename;\n};\n\nclass OCTAVE_API base_url_transfer\n{\npublic:\n\n  friend class url_transfer;\n\n  base_url_transfer ();\n\n  base_url_transfer (const std::string& host,\n                     const std::string& /* user_arg */,\n                     const std::string& /* passwd */,\n                     std::ostream& os);\n\n  base_url_transfer (const std::string& url, std::ostream& os);\n\n  OCTAVE_DISABLE_COPY_MOVE (base_url_transfer)\n\n  virtual ~base_url_transfer () = default;\n\n  bool is_valid () const { return m_valid; }\n\n  bool good () const { return m_valid && m_ok; }\n\n  virtual void perform () { }\n\n  virtual std::string lasterror () const { return m_errmsg; }\n\n  virtual std::ostream& set_ostream (std::ostream& /* os */)\n  {\n    return *m_curr_ostream;\n  }\n\n  virtual std::istream& set_istream (std::istream& /* is */)\n  {\n    return *m_curr_istream;\n  }\n\n  virtual void ascii () { }\n\n  virtual void binary () { }\n\n  bool is_ascii () const { return m_ascii_mode; }\n\n  bool is_binary () const { return ! m_ascii_mode; }\n\n  virtual void cwd (const std::string& /* path */) { }\n\n  virtual void del (const std::string& /* file */) { }\n\n  virtual void rmdir (const std::string& /* path */) { }\n\n  virtual void mkdir (const std::string& /* path */) { }\n\n  virtual void rename (const std::string& /* oldname */,\n                       const std::string& /* newname */) { }\n\n  virtual void put (const std::string& /* file */,\n                    std::istream& /* is */) { }\n\n  virtual void get (const std::string& /* file */,\n                    std::ostream& /* os */) { }\n\n  void mget_directory (const std::string& directory,\n                       const std::string& target);\n\n  string_vector mput_directory (const std::string& base,\n                                const std::string& directory);\n\n  virtual void dir () { }\n\n  virtual string_vector list () { return string_vector (); }\n\n  virtual void get_fileinfo (const std::string& /* filename */,\n                             double& /* filesize */,\n                             OCTAVE_TIME_T& /* filetime */,\n                             bool& /* fileisdir */) { }\n\n  virtual std::string pwd () { return \"\"; }\n\n  virtual void http_get (const Array<std::string>& /* param */) { }\n\n  virtual void http_post (const Array<std::string>& /* param */) { }\n\n  virtual void http_action (const Array<std::string>& /* param */,\n                            const std::string& /* action */) { }\n\n  virtual void cookie_jar (const std::string& /* filename */) { }\n\n  virtual void set_header_fields (const Array<std::string>& /* param */) { }\n\n  virtual void form_data_post (const Array<std::string>& /* param */) { }\n\n  virtual void set_weboptions (const struct weboptions& /* param */) { }\n\nprotected:\n\n  // Host for ftp transfers or full URL for http requests.\n  std::string m_host_or_url;\n  bool m_valid;\n  bool m_ftp;\n  bool m_ascii_mode;\n  bool m_ok;\n  std::string m_errmsg;\n  std::istream *m_curr_istream;\n  std::ostream *m_curr_ostream;\n};\n\nclass OCTAVE_API url_transfer\n{\npublic:\n\n  url_transfer ();\n\n  url_transfer (const std::string& host, const std::string& user,\n                const std::string& passwd, std::ostream& os);\n\n  url_transfer (const std::string& url, std::ostream& os);\n\n  url_transfer (const url_transfer&) = default;\n\n  url_transfer& operator = (const url_transfer&) = default;\n\n  ~url_transfer () = default;\n\n  bool is_valid () const { return m_rep->is_valid (); }\n\n  bool good () const { return m_rep->good (); }\n\n  std::string lasterror () const { return m_rep->lasterror (); }\n\n  std::ostream& set_ostream (std::ostream& os)\n  {\n    return m_rep->set_ostream (os);\n  }\n\n  std::istream& set_istream (std::istream& is)\n  {\n    return m_rep->set_istream (is);\n  }\n\n  void ascii () { m_rep->ascii (); }\n\n  void binary () { m_rep->binary (); }\n\n  bool is_ascii () const { return m_rep->is_ascii (); }\n\n  bool is_binary () const { return m_rep->is_binary (); }\n\n  void cwd (const std::string& path) { m_rep->cwd (path); }\n\n  void del (const std::string& file) { m_rep->del (file); }\n\n  void rmdir (const std::string& path) { m_rep->rmdir (path); }\n\n  void mkdir (const std::string& path) { m_rep->mkdir (path); }\n\n  void rename (const std::string& oldname, const std::string& newname)\n  {\n    m_rep->rename (oldname, newname);\n  }\n\n  void put (const std::string& file, std::istream& is)\n  {\n    m_rep->put (file, is);\n  }\n\n  void get (const std::string& file, std::ostream& os)\n  {\n    m_rep->get (file, os);\n  }\n\n  void mget_directory (const std::string& directory,\n                       const std::string& target)\n  {\n    m_rep->mget_directory (directory, target);\n  }\n\n  string_vector mput_directory (const std::string& base,\n                                const std::string& directory)\n  {\n    return m_rep->mput_directory (base, directory);\n  }\n\n  void dir () { m_rep->dir (); }\n\n  string_vector list () { return m_rep->list (); }\n\n  void get_fileinfo (const std::string& filename, double& filesize,\n                     OCTAVE_TIME_T& filetime, bool& fileisdir)\n  {\n    m_rep->get_fileinfo (filename, filesize, filetime, fileisdir);\n  }\n\n  std::string pwd () { return m_rep->pwd (); }\n\n  void http_get (const Array<std::string>& param)\n  {\n    m_rep->http_get (param);\n  }\n\n  void http_post (const Array<std::string>& param)\n  {\n    m_rep->http_post (param);\n  }\n\n  void http_action (const Array<std::string>& param,\n                    const std::string& action)\n  {\n    m_rep->http_action (param, action);\n  }\n\n  void cookie_jar (const std::string& filename)\n  {\n    m_rep->cookie_jar (filename);\n  }\n\n  void set_header_fields (const Array<std::string>& param)\n  {\n    m_rep->set_header_fields (param);\n  }\n\n  void form_data_post (const Array<std::string>& param)\n  {\n    m_rep->form_data_post (param);\n  }\n\n  void set_weboptions (const struct weboptions& param)\n  {\n    m_rep->set_weboptions (param);\n  }\n\nprivate:\n\n  std::shared_ptr<base_url_transfer> m_rep;\n};\n\nOCTAVE_END_NAMESPACE(octave)\n\n#endif\n"
  },
  {
    "path": "liboctave/version.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2013-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n\n#include \"version.h\"\n\nstatic std::string\nformat_url (bool html, const std::string& url)\n{\n  if (html)\n    return R\"(<a href=\")\" + url + R\"(\">)\" + url + \"</a>\";\n  else\n    return \"<\" + url + \">\";\n}\n\nstd::string\noctave_www_statement (bool html)\n{\n  return \"Home page:            \"\n         + format_url (html, \"https://octave.org\");\n}\n\nstd::string\noctave_bugs_statement (bool html)\n{\n  return \"Support resources:    \"\n         + format_url (html, \"https://octave.org/support\");\n}\n\nstd::string\noctave_contrib_statement (bool html)\n{\n  return \"Improve Octave:       \"\n         + format_url (html, \"https://octave.org/get-involved\");\n}\n\nstd::string\noctave_name_version_copyright (bool html)\n{\n  // The GNU coding standards say that the first line printed by --version\n  // should place the version number following the last space on the line.\n  std::string br = (html ? \"<br>\\n\" : \"\\n\");\n\n  return \"GNU Octave (\" OCTAVE_CANONICAL_HOST_TYPE \") version \" OCTAVE_VERSION + br\n         + OCTAVE_COPYRIGHT;\n}\n\nstd::string\noctave_name_version_copyright_license (bool html)\n{\n  std::string br = (html ? \"<br>\\n\" : \"\\n\");\n\n  return octave_name_version_copyright (html) + br\n         + \"License GPLv3+: GNU GPL version 3 or later \"\n         + format_url (html, \"https://gnu.org/licenses/gpl.html\");\n}\n\nstatic std::string\noctave_warranty_statement (bool html, const std::string& extra_info = \"\")\n{\n  std::string br = (html ? \"\\n\" : \"\\n\");\n\n  return \"There is NO WARRANTY, to the extent permitted by law.\"\n         + extra_info;\n}\n\nstd::string\noctave_name_version_copyright_license_copying_warranty\n  (bool html, const std::string& extra_info)\n{\n  std::string br = (html ? \"<br>\\n\" : \"\\n\");\n  std::string sep = (html ? \"\\n</p>\\n<p>\\n\" : \"\\n\\n\");\n\n  return octave_name_version_copyright_license (html)\n         + sep\n         + \"This is free software; see the source code for copying conditions.\" + br\n         + octave_warranty_statement (html, extra_info) ;\n}\n\nstd::string\noctave_name_version_copyright_license_copying_warranty_bugs\n  (bool html, const std::string& extra_info)\n{\n  std::string sep = (html ? \"\\n</p>\\n<p>\\n\" : \"\\n\");\n  std::string msg =\n    (html ? \"<p>\\n\" : \"\")\n    + octave_name_version_copyright_license_copying_warranty (html, extra_info)\n    + (html ? \"\" : \"\\n\")               + sep\n    + octave_www_statement (html)      + sep\n    + octave_bugs_statement (html)     + sep\n    + octave_contrib_statement (html)  + sep\n    + (html ? \"\\n</p>\" : \"\");\n\n  return msg;\n}\n\nstd::string\noctave_startup_message (bool html)\n{\n  std::string msg\n    = octave_name_version_copyright_license_copying_warranty_bugs\n        (html, \"  For details, type 'warranty'.\");\n\n  msg += (html ? \"<p>\\n\" : \"\\n\");\n  msg += \"For changes from previous versions, type 'news'.\";\n  msg += (html ? \"\\n</p>\" : \"\");\n\n  return msg;\n}\n"
  },
  {
    "path": "liboctave/version.in.h",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1992-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_version_h)\n#define octave_version_h 1\n\n#include \"octave-config.h\"\n\n#define OCTAVE_VERSION %OCTAVE_VERSION%\n\n#define OCTAVE_MAJOR_VERSION %OCTAVE_MAJOR_VERSION%\n\n#define OCTAVE_MINOR_VERSION %OCTAVE_MINOR_VERSION%\n\n#define OCTAVE_PATCH_VERSION %OCTAVE_PATCH_VERSION%\n\n// The \"API version\" is used as a way of checking that interfaces in the\n// liboctave and libinterp libraries haven't changed in a backwardly\n// incompatible way when loading .oct files.  A better way to do that is\n// with library versioning, but not all systems support that.\n// NOTE: This macro will be removed in a future version of Octave.  If\n// you insist on checking for features using a version number, use the\n// OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, and\n// OCTAVE_PATCH_VERSION macros instead.\n#define OCTAVE_API_VERSION %OCTAVE_API_VERSION%\n\n#define OCTAVE_RELEASE_DATE %OCTAVE_RELEASE_DATE%\n\n#define OCTAVE_CANONICAL_HOST_TYPE %OCTAVE_CANONICAL_HOST_TYPE%\n\n#define OCTAVE_COPYRIGHT %OCTAVE_COPYRIGHT%\n\n#include <string>\n\nextern OCTAVE_API std::string octave_www_statement (bool html = false);\n\nextern OCTAVE_API std::string octave_contrib_statement (bool html = false);\n\nextern OCTAVE_API std::string octave_bugs_statement (bool html = false);\n\nextern OCTAVE_API std::string octave_name_version_copyright (bool html = false);\n\nextern OCTAVE_API std::string\noctave_name_version_copyright_license_copying_warranty\n  (bool html = false, const std::string& extra_info = \"\");\n\nextern OCTAVE_API std::string\noctave_name_version_copyright_license_copying_warranty_bugs\n  (bool html = false, const std::string& extra_info = \"\");\n\nextern OCTAVE_API std::string octave_startup_message (bool html = false);\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/_Exit-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// _Exit is provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"stdlib.h\"\n\n#include \"_Exit-wrapper.h\"\n\nvoid\noctave__Exit_wrapper (int status)\n{\n  _Exit (status);\n}\n"
  },
  {
    "path": "liboctave/wrappers/_Exit-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave__Exit_wrapper_h)\n#define octave__Exit_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API void \noctave__Exit_wrapper (int status);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/areadlink-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// areadlink is provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"areadlink.h\"\n\n#include \"areadlink-wrapper.h\"\n\n// Returns pointer to allocated storage.\n\nchar *\noctave_areadlink_wrapper (const char *name)\n{\n  return areadlink (name);\n}\n"
  },
  {
    "path": "liboctave/wrappers/areadlink-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_areadlink_wrapper_h)\n#define octave_areadlink_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API char * octave_areadlink_wrapper (const char *name);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/async-system-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// areadlink is provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n#  include <stdlib.h>\n#  include <string.h>\n#  define WIN32_LEAN_AND_MEAN 1\n#  include <windows.h>\n#else\n#  include <sys/types.h>\n#  include <unistd.h>\n#endif\n\n#include \"async-system-wrapper.h\"\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include \"uniconv-wrappers.h\"\n#endif\n\npid_t\noctave_async_system_wrapper (const char *cmd)\n{\n  int retval = -1;\n\n  if (! cmd)\n    return retval;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  STARTUPINFOW si;\n  PROCESS_INFORMATION pi;\n\n  ZeroMemory (&si, sizeof (si));\n  ZeroMemory (&pi, sizeof (pi));\n\n  wchar_t *xcmd = u8_to_wchar (cmd);\n\n  if (! CreateProcessW (NULL, xcmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))\n    retval = -1;\n  else\n    {\n      retval = pi.dwProcessId;\n\n      CloseHandle (pi.hProcess);\n      CloseHandle (pi.hThread);\n    }\n\n  free (xcmd);\n\n#else\n\n  pid_t pid = fork ();\n\n  if (pid == 0)\n    execl (SHELL_PATH, \"sh\", \"-c\", cmd, (char *) (0));\n  else\n    retval = pid;\n\n#endif\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/wrappers/async-system-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_async_system_wrapper_h)\n#define octave_async_system_wrapper_h 1\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API pid_t octave_async_system_wrapper (const char *cmd);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/base64-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// The base64 functions are provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"base64.h\"\n\n#include \"base64-wrappers.h\"\n\nptrdiff_t\noctave_base64_encode_alloc_wrapper (const char *in, ptrdiff_t inlen, char **out)\n{\n  return base64_encode_alloc (in, inlen, out);\n}\n\nbool\noctave_base64_decode_alloc_wrapper (const char *in, ptrdiff_t inlen,\n                                    char **out, ptrdiff_t *outlen)\n{\n  return base64_decode_alloc (in, inlen, out, outlen);\n}\n"
  },
  {
    "path": "liboctave/wrappers/base64-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_base64_wrappers_h)\n#define octave_base64_wrappers_h 1\n\n#if defined (__cplusplus)\n#  include <cstddef>\n#else\n#  include <stdbool.h>\n#  include <stddef.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API ptrdiff_t\noctave_base64_encode_alloc_wrapper (const char *in, ptrdiff_t inlen, char **out);\n\nextern OCTAVE_API bool\noctave_base64_decode_alloc_wrapper (const char *in, ptrdiff_t inlen,\n                                    char **out, ptrdiff_t *outlen);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/canonicalize-file-name-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// canonicalize_file_name may be provided by gnulib.  We don't include\n// gnulib headers directly in Octave's C++ source files to avoid\n// problems that may be caused by the way that gnulib overrides standard\n// library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdlib.h>\n\n#include \"canonicalize-file-name-wrapper.h\"\n\nchar *\noctave_canonicalize_file_name_wrapper (const char *name)\n{\n  return canonicalize_file_name (name);\n}\n"
  },
  {
    "path": "liboctave/wrappers/canonicalize-file-name-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_canonicalize_file_name_wrapper_h)\n#define octave_canonicalize_file_name_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API char *\noctave_canonicalize_file_name_wrapper (const char *name);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/cxx-signal-helpers.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sys/types.h>\n#include <csignal>\n#include <cstdlib>\n#include <cstring>\n\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n#  include <windows.h>\n#else\n#  include <pthread.h>\n#endif\n\n#include \"signal-wrappers.h\"\n\n#if ! defined (__WIN32__) || defined (__CYGWIN__)\n\n// The following pattern often used in C code to initialize a static\n// variable could possibly cause trouble in multi-threaded code:\n//\n//   TYPE * get_var () {\n//     static bool initialized = false;\n//     static TYPE *var;\n//     if (! initialized) {\n//       var = ...;\n//       initialized = true;\n//     }\n//     return var;\n//   }\n//\n// Changing this code to\n//\n//   static TYPE *var = init_var ();\n//\n// doesn't work in C because the static variable can't be initialized by\n// a function call.  So we have to do this job in C++.  To avoid calling\n// new, initialize sigset_t rather than a pointer to allocated storage.\n\nstatic sigset_t\ninit_async_signals ()\n{\n  sigset_t sigmask;\n\n  sigemptyset (&sigmask);\n\n  // The signals listed here should match the list of signals that\n  // we handle in the signal handler thread.\n\n  // Interrupt signals.\n\n#if defined (SIGINT)\n  sigaddset (&sigmask, SIGINT);\n#endif\n\n#if defined (SIGBREAK)\n  sigaddset (&sigmask, SIGBREAK);\n#endif\n\n  // Termination signals.\n\n#if defined (SIGHUP)\n  sigaddset (&sigmask, SIGHUP);\n#endif\n\n#if defined (SIGQUIT)\n  sigaddset (&sigmask, SIGQUIT);\n#endif\n\n#if defined (SIGTERM)\n  sigaddset (&sigmask, SIGTERM);\n#endif\n\n  // Alarm signals.\n\n#if defined (SIGALRM)\n  sigaddset (&sigmask, SIGALRM);\n#endif\n\n#if defined (SIGVTALRM)\n  sigaddset (&sigmask, SIGVTALRM);\n#endif\n\n  // I/O signals.\n\n#if defined (SIGLOST)\n  sigaddset (&sigmask, SIGLOST);\n#endif\n\n#if defined (SIGPIPE)\n  sigaddset (&sigmask, SIGPIPE);\n#endif\n\n  // Job control signals.\n\n#if defined (SIGCHLD)\n  sigaddset (&sigmask, SIGCHLD);\n#endif\n\n#if defined (SIGCLD)\n  sigaddset (&sigmask, SIGCLD);\n#endif\n\n  // Resource limit signals.\n\n#if defined (SIGXCPU)\n  sigaddset (&sigmask, SIGXCPU);\n#endif\n\n#if defined (SIGXFSZ)\n  sigaddset (&sigmask, SIGXFSZ);\n#endif\n\n  return sigmask;\n}\n\n// Initialized once, is const so we never write to it again and it can\n// be accessed by multiple threads without locking.\n\nstatic const sigset_t async_signals = init_async_signals ();\n\n#endif\n\nvoid\noctave_block_async_signals ()\n{\n#if ! defined (__WIN32__) || defined (__CYGWIN__)\n  pthread_sigmask (SIG_BLOCK, &async_signals, 0);\n#endif\n}\n\nvoid\noctave_unblock_async_signals ()\n{\n#if ! defined (__WIN32__) || defined (__CYGWIN__)\n  pthread_sigmask (SIG_UNBLOCK, &async_signals, 0);\n#endif\n}\n\n#if ! defined (__WIN32__) || defined (__CYGWIN__)\n\nstatic void *\nsignal_watcher (void *arg)\n{\n  octave_sig_handler *handler = reinterpret_cast<octave_sig_handler *> (arg);\n\n  octave_unblock_async_signals ();\n\n  while (1)\n    {\n      int sig_caught;\n\n      if (sigwait (&async_signals, &sig_caught))\n        {\n          // FIXME: what else should we do?\n          abort ();\n        }\n\n      // Let handler have complete control over what to do.\n      (*handler) (sig_caught);\n    }\n}\n\n#endif\n\nvoid\noctave_create_interrupt_watcher_thread (octave_sig_handler *handler)\n{\n#if ! defined (__WIN32__)\n  pthread_t sighandler_thread_id;\n\n  if (pthread_create (&sighandler_thread_id, 0, signal_watcher,\n                      reinterpret_cast<void *> (handler)))\n    {\n      // FIXME: what else should we do?\n      abort ();\n    }\n#else\n  octave_unblock_async_signals ();\n\n  octave_unused_parameter (handler);\n#endif\n}\n"
  },
  {
    "path": "liboctave/wrappers/dirent-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <dirent.h>\n\n#include \"dirent-wrappers.h\"\n\nvoid *\noctave_opendir_wrapper (const char *dname)\n{\n  return opendir (dname);\n}\n\nchar *\noctave_readdir_wrapper (void *dir)\n{\n  struct dirent *d_ent = readdir ((DIR *) dir);\n\n  return d_ent ? d_ent->d_name : 0;\n}\n\nvoid\noctave_rewinddir_wrapper (void *dir)\n{\n  rewinddir ((DIR *) dir);\n}\n\nint\noctave_closedir_wrapper (void *dir)\n{\n  return closedir ((DIR *) dir);\n}\n\n// Define NAME_MAX, the maximum length of a single component in a\n// filename.  No such limit may exist, or may vary depending on the\n// filesystem.  This value should be avoided for creating character\n// strings and used only to truncate given file names to this length if\n// attempts to get info about the file fail with errno == ENAMETOOLONG.\n\n// Most likely the system will truncate filenames if it is not POSIX,\n// and so we can use the BSD value here.\n\n#if ! defined (_POSIX_NAME_MAX)\n#  define _POSIX_NAME_MAX 255\n#endif\n\n#if ! defined (NAME_MAX)\n#  define NAME_MAX _POSIX_NAME_MAX\n#endif\n\nunsigned int\noctave_name_max_wrapper (void)\n{\n  return NAME_MAX;\n}\n"
  },
  {
    "path": "liboctave/wrappers/dirent-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_dirent_wrappers_h)\n#define octave_dirent_wrappers_h 1\n\n#if ! defined (__cplusplus)\n#  include <stdbool.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API void * octave_opendir_wrapper (const char *dname);\n\nextern OCTAVE_API char * octave_readdir_wrapper (void *dir);\n\nextern OCTAVE_API void octave_rewinddir_wrapper (void *dir);\n\nextern OCTAVE_API int octave_closedir_wrapper (void *dir);\n\nextern OCTAVE_API unsigned int octave_name_max_wrapper (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/fcntl-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <fcntl.h>\n\n#include \"fcntl-wrappers.h\"\n\nint\noctave_fcntl_wrapper (int fd, int cmd, int arg)\n{\n  return fcntl (fd, cmd, arg);\n}\n\nint\noctave_open_wrapper (const char *nm, int flags, mode_t mode)\n{\n  return open (nm, flags, mode);\n}\n\nint\noctave_f_dupfd_wrapper (void)\n{\n#if defined (F_DUPFD)\n  return F_DUPFD;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_f_getfd_wrapper (void)\n{\n#if defined (F_GETFD)\n  return F_GETFD;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_f_getfl_wrapper (void)\n{\n#if defined (F_GETFL)\n  return F_GETFL;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_f_setfd_wrapper (void)\n{\n#if defined (F_SETFD)\n  return F_SETFD;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_f_setfl_wrapper (void)\n{\n#if defined (F_SETFL)\n  return F_SETFL;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_append_wrapper (void)\n{\n#if defined (O_APPEND)\n  return O_APPEND;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_async_wrapper (void)\n{\n#if defined (O_ASYNC)\n  return O_ASYNC;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_creat_wrapper (void)\n{\n#if defined (O_CREAT)\n  return O_CREAT;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_excl_wrapper (void)\n{\n#if defined (O_EXCL)\n  return O_EXCL;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_nonblock_wrapper (void)\n{\n#if defined (O_NONBLOCK)\n  return O_NONBLOCK;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_rdonly_wrapper (void)\n{\n#if defined (O_RDONLY)\n  return O_RDONLY;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_rdwr_wrapper (void)\n{\n#if defined (O_RDWR)\n  return O_RDWR;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_sync_wrapper (void)\n{\n#if defined (O_SYNC)\n  return O_SYNC;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_trunc_wrapper (void)\n{\n#if defined (O_TRUNC)\n  return O_TRUNC;\n#else\n  return -1;\n#endif\n}\n\nint\noctave_o_wronly_wrapper (void)\n{\n#if defined (O_WRONLY)\n  return O_WRONLY;\n#else\n  return -1;\n#endif\n}\n"
  },
  {
    "path": "liboctave/wrappers/fcntl-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fcntl_wrappers_h)\n#define octave_fcntl_wrappers_h 1\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int octave_fcntl_wrapper (int fd, int cmd, int arg);\n\nextern OCTAVE_API int\noctave_open_wrapper (const char *nm, int flags, mode_t mode);\n\nextern OCTAVE_API int octave_f_dupfd_wrapper (void);\n\nextern OCTAVE_API int octave_f_getfd_wrapper (void);\n\nextern OCTAVE_API int octave_f_getfl_wrapper (void);\n\nextern OCTAVE_API int octave_f_setfd_wrapper (void);\n\nextern OCTAVE_API int octave_f_setfl_wrapper (void);\n\nextern OCTAVE_API int octave_o_append_wrapper (void);\n\nextern OCTAVE_API int octave_o_async_wrapper (void);\n\nextern OCTAVE_API int octave_o_creat_wrapper (void);\n\nextern OCTAVE_API int octave_o_excl_wrapper (void);\n\nextern OCTAVE_API int octave_o_nonblock_wrapper (void);\n\nextern OCTAVE_API int octave_o_rdonly_wrapper (void);\n\nextern OCTAVE_API int octave_o_rdwr_wrapper (void);\n\nextern OCTAVE_API int octave_o_sync_wrapper (void);\n\nextern OCTAVE_API int octave_o_trunc_wrapper (void);\n\nextern OCTAVE_API int octave_o_wronly_wrapper (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/filepos-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// ftello and fseeko may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdio.h>\n\n#include \"filepos-wrappers.h\"\n\nint\noctave_fseeko_wrapper (FILE *fp, off_t offset, int whence)\n{\n  return fseeko (fp, offset, whence);\n}\n\noff_t\noctave_ftello_wrapper (FILE *fp)\n{\n  return ftello (fp);\n}\n"
  },
  {
    "path": "liboctave/wrappers/filepos-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_filepos_wrappers_h)\n#define octave_filepos_wrappers_h 1\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\n#  include <cstdio>\n#else\n#  include <stdio.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int\noctave_fseeko_wrapper (FILE *fp, off_t offset, int whence);\n\nextern OCTAVE_API off_t octave_ftello_wrapper (FILE *fp);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/fpucw-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// The fpucw macros are provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_FPU_CONTROL_H)\n#  include <fpu_control.h>\n#endif\n\n#include \"fpucw.h\"\n\n#include \"fpucw-wrappers.h\"\n\n#if ! defined (_FPU_DEFAULT)\n#  if defined __i386__ || defined __x86_64__\n#    define _FPU_DEFAULT 0x037f\n#  else\n#    define _FPU_DEFAULT 0\n#  endif\n#endif\n\nvoid\noctave_set_default_fpucw (void)\n{\n  fpucw_t cw = GET_FPUCW ();\n\n  if (cw != _FPU_DEFAULT)\n    SET_FPUCW (_FPU_DEFAULT);\n}\n\n// OLDCW is the name used by the fpucw.h macros and gnulib doesn't give\n// us a choice.  We are also assuming that fpucw_t is unsigned, and no\n// wider than an int.\n\nunsigned int\noctave_begin_long_double_rounding (void)\n{\n  // Don't use DECL_LONG_DOUBLE_ROUNDING here because on some systems,\n  // it is defined to be empty.\n\n  fpucw_t oldcw = 0;\n\n  BEGIN_LONG_DOUBLE_ROUNDING ();\n\n  return oldcw;\n}\n\nvoid\noctave_end_long_double_rounding (unsigned int oldcw)\n{\n  END_LONG_DOUBLE_ROUNDING ();\n\n  // It might be unused.\n  octave_unused_parameter (oldcw);\n}\n"
  },
  {
    "path": "liboctave/wrappers/fpucw-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_fpucw_wrappers_h)\n#define octave_fpucw_wrappers_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API void octave_set_default_fpucw (void);\n\n// unsigned int must match the actual type of fpucw_t.\n\nextern OCTAVE_API unsigned int octave_begin_long_double_rounding (void);\n\nextern OCTAVE_API void octave_end_long_double_rounding (unsigned int);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/gen-tempname-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// gen_tempname is provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"tempname.h\"\n\n#include \"gen-tempname-wrapper.h\"\n\nint\noctave_gen_tempname_wrapper (char *tmpl)\n{\n  return gen_tempname (tmpl, 0, 0, GT_NOCREATE);\n}\n"
  },
  {
    "path": "liboctave/wrappers/gen-tempname-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_gen_tempname_wrapper_h)\n#define octave_gen_tempname_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int octave_gen_tempname_wrapper (char *tmpl);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/getopt-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// getopt_long may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdlib.h>\n\n#include <getopt.h>\n\n#include \"getopt-wrapper.h\"\n\nstatic struct option *\nmake_option_struct (const struct octave_getopt_options *opts)\n{\n  const struct octave_getopt_options *p = opts;\n  struct option *retval = 0, *q = 0;\n\n  int n = 0;\n  while (p->name)\n    {\n      n++;\n      p++;\n    }\n\n  retval = (struct option *) malloc ((n+1) * sizeof (struct option));\n\n  // If we don't have enough memory even to start Octave\n  // then we might as well quit now.\n  if (! retval)\n    abort ();\n\n  p = opts;\n  q = retval;\n  while (p->name)\n    {\n      q->name = p->name;\n\n      switch (p->has_arg)\n        {\n        case octave_required_arg:\n          q->has_arg = required_argument;\n          break;\n\n        case octave_optional_arg:\n          q->has_arg = optional_argument;\n          break;\n\n        default:\n          q->has_arg = no_argument;\n          break;\n        }\n\n      q->flag = p->flag;\n\n      q->val = p->val;\n\n      q++;\n      p++;\n    }\n\n  q->name = 0;\n  q->has_arg = 0;\n  q->flag = 0;\n  q->val = 0;\n\n  return retval;\n}\n\nint\noctave_getopt_long_wrapper (int argc, char **argv,\n                            const char *shortopts,\n                            const struct octave_getopt_options *longopts,\n                            int *longind)\n{\n  struct option *lopts = make_option_struct (longopts);\n\n  int retval = getopt_long (argc, argv, shortopts, lopts, longind);\n\n  free (lopts);\n\n  return retval;\n}\n\nchar *\noctave_optarg_wrapper (void)\n{\n  return optarg;\n}\n\nint\noctave_optind_wrapper (void)\n{\n  return optind;\n}\n\nint\noctave_get_opterr_wrapper (void)\n{\n  return opterr;\n}\n\nint\noctave_set_opterr_wrapper (int val)\n{\n  int retval = opterr;\n\n  opterr = val;\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/wrappers/getopt-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_getopt_wrapper_h)\n#define octave_getopt_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nstruct octave_getopt_options\n{\n  const char *name;\n  int has_arg;\n  int *flag;\n  int val;\n};\n\n#define octave_no_arg 0\n#define octave_required_arg 1\n#define octave_optional_arg 2\n\nextern OCTAVE_API int\noctave_getopt_long_wrapper (int argc, char **argv,\n                            const char *shortopts,\n                            const struct octave_getopt_options *longopts,\n                            int *longind);\n\nextern OCTAVE_API char * octave_optarg_wrapper (void);\n\nextern OCTAVE_API int octave_optind_wrapper (void);\n\nextern OCTAVE_API int octave_get_opterr_wrapper (void);\nextern OCTAVE_API int octave_set_opterr_wrapper (int val);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/glob-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdlib.h>\n\n#include <fnmatch.h>\n#include <glob.h>\n\n#include \"glob-wrappers.h\"\n\nvoid *\noctave_create_glob_info_struct (void)\n{\n  return malloc (sizeof (glob_t));\n}\n\n// Does not call globfree.\nvoid\noctave_destroy_glob_info_struct (void *glob_info)\n{\n  free (glob_info);\n}\n\nint\noctave_glob_wrapper (const char *pattern, int flags, void *glob_info)\n{\n  return glob (pattern, flags, 0, glob_info);\n}\n\nint\noctave_glob_num_matches (void *glob_info)\n{\n  return glob_info ? ((glob_t *) glob_info)->gl_pathc : 0;\n}\n\nchar **\noctave_glob_match_list (void *glob_info)\n{\n  return glob_info ? ((glob_t *) glob_info)->gl_pathv : 0;\n}\n\nvoid\noctave_globfree_wrapper (void *glob_info)\n{\n  globfree ((glob_t *) glob_info);\n}\n\nint\noctave_glob_nosort_wrapper (void)\n{\n  return GLOB_NOSORT;\n}\n\nint\noctave_fnmatch_wrapper (const char *pattern, const char *name, int flags)\n{\n  return fnmatch (pattern, name, flags);\n}\n\nint\noctave_fnm_nomatch_wrapper (void)\n{\n  return FNM_NOMATCH;\n}\n\nint\noctave_fnm_pathname_wrapper (void)\n{\n  return FNM_PATHNAME;\n}\n\nint\noctave_fnm_noescape_wrapper (void)\n{\n  return FNM_NOESCAPE;\n}\n\nint\noctave_fnm_period_wrapper (void)\n{\n  return FNM_PERIOD;\n}\n"
  },
  {
    "path": "liboctave/wrappers/glob-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_glob_wrappers_h)\n#define octave_glob_wrappers_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API void * octave_create_glob_info_struct (void);\n\n// Does not call globfree.\nextern OCTAVE_API void octave_destroy_glob_info_struct (void *glob_info);\n\n// We don't need the error function pointer that the system glob\n// function allows.\nextern OCTAVE_API int\noctave_glob_wrapper (const char *pattern, int flags, void *glob_info);\n\nextern OCTAVE_API int octave_glob_num_matches (void *glob_info);\n\nextern OCTAVE_API char ** octave_glob_match_list (void *glob_info);\n\nextern OCTAVE_API void octave_globfree_wrapper (void *glob_info);\n\nextern OCTAVE_API int octave_glob_nosort_wrapper (void);\n\nextern OCTAVE_API int\noctave_fnmatch_wrapper (const char *pattern, const char *name, int flags);\n\nextern OCTAVE_API int octave_fnm_nomatch_wrapper (void);\n\nextern OCTAVE_API int octave_fnm_pathname_wrapper (void);\n\nextern OCTAVE_API int octave_fnm_noescape_wrapper (void);\n\nextern OCTAVE_API int octave_fnm_period_wrapper (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/hash-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// The hash functions are provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"md2.h\"\n#include \"md4.h\"\n\n// Silence invalid warnings in gnulib\n// FIXME: This was fixed upstream in gnulib on 2026-02-12.\n// The following ifdef can be deleted after a gnulib update.\n#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wcast-qual\"\n#endif\n\n#include \"md5.h\"\n#include \"sha1.h\"\n#include \"sha256.h\"\n#include \"sha512.h\"\n\n// FIXME: This was fixed upstream in gnulib on 2026-02-12.\n// The following ifdef can be deleted after a gnulib update.\n#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC\n#  pragma GCC diagnostic pop\n#endif\n\n#include \"hash-wrappers.h\"\n\nint octave_md2_digest_size (void) { return MD2_DIGEST_SIZE; }\nint octave_md4_digest_size (void) { return MD4_DIGEST_SIZE; }\nint octave_md5_digest_size (void) { return MD5_DIGEST_SIZE; }\nint octave_sha1_digest_size (void) { return SHA1_DIGEST_SIZE; }\nint octave_sha224_digest_size (void) { return SHA224_DIGEST_SIZE; }\nint octave_sha256_digest_size (void) { return SHA256_DIGEST_SIZE; }\nint octave_sha384_digest_size (void) { return SHA384_DIGEST_SIZE; }\nint octave_sha512_digest_size (void) { return SHA512_DIGEST_SIZE; }\n\nvoid *\noctave_md2_buffer_wrapper (const char *buf, size_t len, void *res)\n{\n  return md2_buffer (buf, len, res);\n}\n\nvoid *\noctave_md4_buffer_wrapper (const char *buf, size_t len, void *res)\n{\n  return md4_buffer (buf, len, res);\n}\n\nvoid *\noctave_md5_buffer_wrapper (const char *buf, size_t len, void *res)\n{\n  return md5_buffer (buf, len, res);\n}\n\nvoid *\noctave_sha1_buffer_wrapper (const char *buf, size_t len, void *res)\n{\n  return sha1_buffer (buf, len, res);\n}\n\nvoid *\noctave_sha224_buffer_wrapper (const char *buf, size_t len, void *res)\n{\n  return sha224_buffer (buf, len, res);\n}\n\nvoid *\noctave_sha256_buffer_wrapper (const char *buf, size_t len, void *res)\n{\n  return sha256_buffer (buf, len, res);\n}\n\nvoid *\noctave_sha384_buffer_wrapper (const char *buf, size_t len, void *res)\n{\n  return sha384_buffer (buf, len, res);\n}\n\nvoid *\noctave_sha512_buffer_wrapper (const char *buf, size_t len, void *res)\n{\n  return sha512_buffer (buf, len, res);\n}\n"
  },
  {
    "path": "liboctave/wrappers/hash-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_hash_wrappers_h)\n#define octave_hash_wrappers_h 1\n\n#if defined (__cplusplus)\n#  include <cstddef>\n#else\n#  include <stddef.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int octave_md2_digest_size (void);\nextern OCTAVE_API int octave_md4_digest_size (void);\nextern OCTAVE_API int octave_md5_digest_size (void);\nextern OCTAVE_API int octave_sha1_digest_size (void);\nextern OCTAVE_API int octave_sha224_digest_size (void);\nextern OCTAVE_API int octave_sha256_digest_size (void);\nextern OCTAVE_API int octave_sha384_digest_size (void);\nextern OCTAVE_API int octave_sha512_digest_size (void);\n\nextern OCTAVE_API void *\noctave_md2_buffer_wrapper (const char *buf, size_t len, void *res);\n\nextern OCTAVE_API void *\noctave_md4_buffer_wrapper (const char *buf, size_t len, void *res);\n\nextern OCTAVE_API void *\noctave_md5_buffer_wrapper (const char *buf, size_t len, void *res);\n\nextern OCTAVE_API void *\noctave_sha1_buffer_wrapper (const char *buf, size_t len, void *res);\n\nextern OCTAVE_API void *\noctave_sha224_buffer_wrapper (const char *buf, size_t len, void *res);\n\nextern OCTAVE_API void *\noctave_sha256_buffer_wrapper (const char *buf, size_t len, void *res);\n\nextern OCTAVE_API void *\noctave_sha384_buffer_wrapper (const char *buf, size_t len, void *res);\n\nextern OCTAVE_API void *\noctave_sha512_buffer_wrapper (const char *buf, size_t len, void *res);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/iconv-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"iconv.h\"\n\n#include \"iconv-wrappers.h\"\n\nvoid *\noctave_iconv_open_wrapper (const char *tocode, const char *fromcode)\n{\n  return (void *) iconv_open (tocode, fromcode);\n}\n\nint\noctave_iconv_close_wrapper (void *cd)\n{\n  return iconv_close ((iconv_t) cd);\n}\n\nvoid\noctave_iconvlist_wrapper (int (*do_one) (unsigned int namescount,\n                                         const char * const *names,\n                                         void *data),\n                          void *data)\n{\n#if defined (HAVE_ICONVLIST)\n  iconvlist (do_one, data);\n#else\n  octave_unused_parameter (do_one);\n  octave_unused_parameter (data);\n#endif\n\n  return;\n}\n\nconst char *\noctave_iconv_canonicalize_wrapper (const char *name)\n{\n#if defined (HAVE_ICONV_CANONICALIZE)\n  return iconv_canonicalize (name);\n#else\n  return name;\n#endif\n}\n"
  },
  {
    "path": "liboctave/wrappers/iconv-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_iconv_wrappers_h)\n#define octave_iconv_wrappers_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API void *\noctave_iconv_open_wrapper (const char *tocode, const char *fromcode);\n\nextern OCTAVE_API int octave_iconv_close_wrapper (void *cd);\n\nextern OCTAVE_API void\noctave_iconvlist_wrapper (int (*do_one) (unsigned int namescount,\n                                         const char * const *names,\n                                         void *data),\n                          void *data);\n\nextern OCTAVE_API const char *\noctave_iconv_canonicalize_wrapper (const char *name);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/intprops-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"intprops.h\"\n\n#include \"intprops-wrappers.h\"\n\n// The *_OVERFLOW macros are provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n#  pragma GCC diagnostic ignored \"-Wsign-compare\"\n#  pragma GCC diagnostic ignored \"-Wtype-limits\"\n#endif\n\nint\noctave_i_multiply_overflow_wrapper (int a, int b, int *r)\n{\n  return INT_MULTIPLY_WRAPV (a, b, r);\n}\n\nint\noctave_li_multiply_overflow_wrapper (long int a, long int b, long int *r)\n{\n  return INT_MULTIPLY_WRAPV (a, b, r);\n}\n\n#if defined (OCTAVE_HAVE_LONG_LONG_INT)\nint\noctave_lli_multiply_overflow_wrapper (long long int a, long long int b,\n                                      long long int *r)\n{\n  return INT_MULTIPLY_WRAPV (a, b, r);\n}\n#endif\n\nint\noctave_ui_multiply_overflow_wrapper (unsigned int a, unsigned int b,\n                                     unsigned int *r)\n{\n  return INT_MULTIPLY_WRAPV (a, b, r);\n}\n\nint\noctave_uli_multiply_overflow_wrapper (unsigned long int a, unsigned long int b,\n                                      unsigned long int *r)\n{\n  return INT_MULTIPLY_WRAPV (a, b, r);\n}\n\n#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\nint\noctave_ulli_multiply_overflow_wrapper (unsigned long long int a,\n                                       unsigned long long int b,\n                                       unsigned long long int *r)\n{\n  return INT_MULTIPLY_WRAPV (a, b, r);\n}\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/intprops-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2020-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_localcharset_wrapper_h)\n#define octave_localcharset_wrapper_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n// These functions return 1 if the operation between the input arguments would\n// overflow.\n\nextern OCTAVE_API int\noctave_i_multiply_overflow_wrapper (int a, int b, int *r);\n\nextern OCTAVE_API int\noctave_li_multiply_overflow_wrapper (long int a, long int b, long int *r);\n\n#  if defined (OCTAVE_HAVE_LONG_LONG_INT)\nextern OCTAVE_API int\noctave_lli_multiply_overflow_wrapper (long long int a, long long int b,\n                                      long long int *r);\n#  endif\n\nextern OCTAVE_API int\noctave_ui_multiply_overflow_wrapper (unsigned int a, unsigned int b,\n                                     unsigned int *r);\n\nextern OCTAVE_API int\noctave_uli_multiply_overflow_wrapper (unsigned long int a, unsigned long int b,\n                                      unsigned long int *r);\n\n#  if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)\nextern OCTAVE_API int\noctave_ulli_multiply_overflow_wrapper (unsigned long long int a,\n                                       unsigned long long int b,\n                                       unsigned long long int *r);\n#  endif\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/localcharset-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"localcharset.h\"\n\n#include \"localcharset-wrapper.h\"\n\n// The locale_charset function is provided by gnulib.  We don't include\n// gnulib headers directly in Octave's C++ source files to avoid\n// problems that may be caused by the way that gnulib overrides standard\n// library functions.\n\nconst char *\noctave_locale_charset_wrapper (void)\n{\n  return locale_charset ();\n}\n"
  },
  {
    "path": "liboctave/wrappers/localcharset-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_localcharset_wrapper_h)\n#define octave_localcharset_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API const char * octave_locale_charset_wrapper (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/math-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <math.h>\n\n#include \"math-wrappers.h\"\n\ndouble\noctave_frexp_wrapper (double x, int *expptr)\n{\n  return frexp (x, expptr);\n}\n\nfloat\noctave_frexpf_wrapper (float x, int *expptr)\n{\n  return frexpf (x, expptr);\n}\n"
  },
  {
    "path": "liboctave/wrappers/math-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_math_wrappers_h)\n#define octave_math_wrappers_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API double octave_frexp_wrapper (double x, int *expptr);\n\nextern OCTAVE_API float octave_frexpf_wrapper (float x, int *expptr);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/mkostemp-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// mkostemp may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <fcntl.h>\n#include <stdlib.h>\n\n#include \"mkostemp-wrapper.h\"\n\nint\noctave_mkostemp_wrapper (char *tmpl)\n{\n  return mkostemp (tmpl, O_BINARY);\n}\n"
  },
  {
    "path": "liboctave/wrappers/mkostemp-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mkostemp_wrapper_h)\n#define octave_mkostemp_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int octave_mkostemp_wrapper (char *tmpl);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/mkostemps-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// mkostemp may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <fcntl.h>\n#include <stdlib.h>\n\n#include \"mkostemps-wrapper.h\"\n\nint\noctave_mkostemps_wrapper (char *tmpl, int suffixlen)\n{\n  return mkostemps (tmpl, suffixlen, O_BINARY);\n}\n"
  },
  {
    "path": "liboctave/wrappers/mkostemps-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_mkostemps_wrapper_h)\n#define octave_mkostemps_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int octave_mkostemps_wrapper (char *tmpl, int suffixlen);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/module.mk",
    "content": "NOINSTALL_WRAPPERS_INC = \\\n  %reldir%/_Exit-wrapper.h \\\n  %reldir%/areadlink-wrapper.h \\\n  %reldir%/async-system-wrapper.h \\\n  %reldir%/base64-wrappers.h \\\n  %reldir%/canonicalize-file-name-wrapper.h \\\n  %reldir%/dirent-wrappers.h \\\n  %reldir%/fcntl-wrappers.h \\\n  %reldir%/filepos-wrappers.h \\\n  %reldir%/fpucw-wrappers.h \\\n  %reldir%/gen-tempname-wrapper.h \\\n  %reldir%/getopt-wrapper.h \\\n  %reldir%/glob-wrappers.h \\\n  %reldir%/hash-wrappers.h \\\n  %reldir%/iconv-wrappers.h \\\n  %reldir%/intprops-wrappers.h \\\n  %reldir%/localcharset-wrapper.h \\\n  %reldir%/math-wrappers.h \\\n  %reldir%/mkostemp-wrapper.h \\\n  %reldir%/mkostemps-wrapper.h \\\n  %reldir%/nanosleep-wrapper.h \\\n  %reldir%/nproc-wrapper.h \\\n  %reldir%/octave-popen2.h \\\n  %reldir%/pwd-wrappers.h \\\n  %reldir%/select-wrappers.h \\\n  %reldir%/set-program-name-wrapper.h \\\n  %reldir%/setenv-wrapper.h \\\n  %reldir%/signal-wrappers.h \\\n  %reldir%/stat-wrappers.h \\\n  %reldir%/strcase-wrappers.h \\\n  %reldir%/strdup-wrapper.h \\\n  %reldir%/strftime-wrapper.h \\\n  %reldir%/strmode-wrapper.h \\\n  %reldir%/strptime-wrapper.h \\\n  %reldir%/time-wrappers.h \\\n  %reldir%/uname-wrapper.h \\\n  %reldir%/unicase-wrappers.h \\\n  %reldir%/uniconv-wrappers.h \\\n  %reldir%/unictype-wrappers.h \\\n  %reldir%/unistd-wrappers.h \\\n  %reldir%/unistr-wrappers.h \\\n  %reldir%/unsetenv-wrapper.h \\\n  %reldir%/vasprintf-wrapper.h \\\n  %reldir%/wait-for-input.h \\\n  %reldir%/wait-wrappers.h\n\nWRAPPERS_SRC = \\\n  %reldir%/_Exit-wrapper.c \\\n  %reldir%/areadlink-wrapper.c \\\n  %reldir%/async-system-wrapper.c \\\n  %reldir%/base64-wrappers.c \\\n  %reldir%/canonicalize-file-name-wrapper.c \\\n  %reldir%/cxx-signal-helpers.cc \\\n  %reldir%/dirent-wrappers.c \\\n  %reldir%/fcntl-wrappers.c \\\n  %reldir%/filepos-wrappers.c \\\n  %reldir%/fpucw-wrappers.c \\\n  %reldir%/gen-tempname-wrapper.c \\\n  %reldir%/getopt-wrapper.c \\\n  %reldir%/glob-wrappers.c \\\n  %reldir%/hash-wrappers.c \\\n  %reldir%/iconv-wrappers.c \\\n  %reldir%/intprops-wrappers.c \\\n  %reldir%/localcharset-wrapper.c \\\n  %reldir%/math-wrappers.c \\\n  %reldir%/mkostemp-wrapper.c \\\n  %reldir%/mkostemps-wrapper.c \\\n  %reldir%/nanosleep-wrapper.c \\\n  %reldir%/nproc-wrapper.c \\\n  %reldir%/octave-popen2.c \\\n  %reldir%/pwd-wrappers.c \\\n  %reldir%/select-wrappers.c \\\n  %reldir%/set-program-name-wrapper.c \\\n  %reldir%/setenv-wrapper.c \\\n  %reldir%/signal-wrappers.c \\\n  %reldir%/stat-wrappers.c \\\n  %reldir%/strcase-wrappers.c \\\n  %reldir%/strdup-wrapper.c \\\n  %reldir%/strftime-wrapper.c \\\n  %reldir%/strmode-wrapper.c \\\n  %reldir%/strptime-wrapper.c \\\n  %reldir%/time-wrappers.c \\\n  %reldir%/uname-wrapper.c \\\n  %reldir%/unicase-wrappers.c \\\n  %reldir%/uniconv-wrappers.c \\\n  %reldir%/unictype-wrappers.c \\\n  %reldir%/unistd-wrappers.c \\\n  %reldir%/unistr-wrappers.c \\\n  %reldir%/unsetenv-wrapper.c \\\n  %reldir%/vasprintf-wrapper.c \\\n  %reldir%/wait-for-input.c \\\n  %reldir%/wait-wrappers.c \\\n  $(NOINSTALL_WRAPPERS_INC)\n\nnoinst_LTLIBRARIES += %reldir%/libwrappers.la\n\n%canon_reldir%_libwrappers_la_SOURCES = $(WRAPPERS_SRC)\n\n%canon_reldir%_libwrappers_la_CPPFLAGS = \\\n  @OCTAVE_DLL_DEFS@ \\\n  @EXTERNAL_DLL_DEFS@ \\\n  -Ilibgnu -I$(srcdir)/libgnu\n\nliboctave_liboctave_la_LIBADD += %reldir%/libwrappers.la\n\nliboctave_liboctave_la_LDFLAGS += $(GNULIB_LINK_DEPS)\n"
  },
  {
    "path": "liboctave/wrappers/nanosleep-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// nanosleep may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <time.h>\n\n#include \"nanosleep-wrapper.h\"\n\nint\noctave_nanosleep_wrapper (const struct timespec *requested,\n                          struct timespec *remaining)\n{\n  return nanosleep (requested, remaining);\n}\n"
  },
  {
    "path": "liboctave/wrappers/nanosleep-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_nanosleep_wrapper_h)\n#define octave_nanosleep_wrapper_h 1\n\n#if defined (__cplusplus)\n#  include <ctime>\n#else\n#  include <time.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int\noctave_nanosleep_wrapper (const struct timespec *requested,\n                          struct timespec *remaining);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/nproc-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// num_processors is provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"nproc.h\"\n\n#include \"nproc-wrapper.h\"\n\nunsigned long int\noctave_num_processors_wrapper (enum octave_nproc_query octave_query)\n{\n  enum nproc_query query = NPROC_CURRENT;\n\n  switch (octave_query)\n    {\n    case OCTAVE_NPROC_ALL:\n      query = NPROC_ALL;\n      break;\n\n    case OCTAVE_NPROC_CURRENT:\n      query = NPROC_CURRENT;\n      break;\n\n    case OCTAVE_NPROC_CURRENT_OVERRIDABLE:\n      query = NPROC_CURRENT_OVERRIDABLE;\n      break;\n    }\n\n  return num_processors (query);\n}\n"
  },
  {
    "path": "liboctave/wrappers/nproc-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_nproc_wrapper_h)\n#define octave_nproc_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nenum octave_nproc_query\n{\n  OCTAVE_NPROC_ALL,\n  OCTAVE_NPROC_CURRENT,\n  OCTAVE_NPROC_CURRENT_OVERRIDABLE\n};\n\nextern OCTAVE_API unsigned long int\noctave_num_processors_wrapper (enum octave_nproc_query);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/octave-popen2.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// It makes more sense to define octave_popen2 with the wrapper\n// functions than it does to try to provide wrappers for all the\n// individual functions and macros that it uses and that may be provided\n// by gnulib.  We don't include gnulib headers directly in Octave's C++\n// source files to avoid problems that may be caused by the way that\n// gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n#  include <fcntl.h>\n#  include <io.h>\n#  define WIN32_LEAN_AND_MEAN 1\n#  include <windows.h>\n\n#  include \"uniconv-wrappers.h\"\n#else\n#  include <errno.h>\n#  include <fcntl.h>\n#  include <sys/types.h>\n#  include <sys/wait.h>\n#  include <unistd.h>\n#endif\n\n#include \"octave-popen2.h\"\n\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n\nstatic char *\nmake_command_string (const char *cmd, char *const *args)\n{\n  char *const *argp;\n  size_t cmd_len;\n  char *command;\n  size_t arg_len;\n\n  // Count command length, quotes, and terminating NUL character.\n  cmd_len = strlen (cmd) + 3;\n\n  // Count argument length, space, and quotes.\n  // Ignore first arg as it is the command.\n  argp = args;\n  while (*++argp)\n    cmd_len += strlen (*argp) + 3;\n\n  command = (char *) malloc (cmd_len);\n\n  // double-quote command\n  sprintf (command, \"\\\"%s\\\"\", cmd);\n\n  argp = args;\n  cmd_len = strlen (cmd) + 2;\n  while (*++argp)\n    {\n      // append double-quoted argument separated by space to command buffer\n      command[cmd_len++] = ' ';\n      command[cmd_len++] = '\"';\n      arg_len = strlen (*argp);\n      memcpy (command + cmd_len, *argp, arg_len);\n      cmd_len += arg_len;\n      command[cmd_len++] = '\"';\n    }\n  command[cmd_len] = 0;\n\n  return command;\n}\n\npid_t\noctave_popen2 (const char *cmd, char *const *args, bool sync_mode,\n               int *fildes, const char **errmsg)\n{\n  pid_t pid;\n\n  char *command;\n  bool status;\n\n  PROCESS_INFORMATION pi;\n  STARTUPINFO si;\n\n  HANDLE hProcess = GetCurrentProcess ();\n  HANDLE childRead, childWrite, parentRead, parentWrite;\n  DWORD pipeMode;\n\n  ZeroMemory (&pi, sizeof (pi));\n  ZeroMemory (&si, sizeof (si));\n  si.cb = sizeof (si);\n\n  if (! CreatePipe (&childRead, &parentWrite, 0, 0)\n      || ! DuplicateHandle (hProcess, childRead, hProcess, &childRead,\n                            0, TRUE,\n                            DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))\n    {\n      *errmsg = \"popen2: pipe creation failed\";\n      return -1;\n    }\n\n  if (! CreatePipe (&parentRead, &childWrite, 0, 0)\n      || ! DuplicateHandle (hProcess, childWrite, hProcess, &childWrite,\n                            0, TRUE,\n                            DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))\n    {\n      *errmsg = \"popen2: pipe creation failed\";\n      return -1;\n    }\n\n  if (! sync_mode)\n    {\n      pipeMode = PIPE_NOWAIT;\n      SetNamedPipeHandleState (parentRead, &pipeMode, 0, 0);\n    }\n\n  fildes[1] = _open_osfhandle ((intptr_t) parentRead, _O_RDONLY | _O_BINARY);\n  fildes[0] = _open_osfhandle ((intptr_t) parentWrite, _O_WRONLY | _O_BINARY);\n\n  si.dwFlags |= STARTF_USESTDHANDLES;\n\n  si.hStdInput = childRead;\n  si.hStdOutput = childWrite;\n  si.hStdError = GetStdHandle (STD_ERROR_HANDLE);\n\n  command = make_command_string (cmd, args);\n\n  wchar_t *wcmd = u8_to_wchar (command);\n\n  free (command);\n\n  status = CreateProcessW (NULL, wcmd, NULL, NULL, TRUE, CREATE_NO_WINDOW,\n                           NULL, NULL, &si, &pi);\n\n  free (wcmd);\n\n  if (! status)\n    {\n      *errmsg = \"popen2: process creation failed\";\n      return -1;\n    }\n\n  pid = pi.dwProcessId;\n\n  CloseHandle (childRead);\n  CloseHandle (childWrite);\n\n  CloseHandle (pi.hProcess);\n  CloseHandle (pi.hThread);\n\n  return pid;\n}\n\n#else\n\n// Magic value used to indicate child failed back to parent process\n#define OCTAVE_CHILD_FAILURE 129\n\npid_t\noctave_popen2 (const char *cmd, char *const *args, bool sync_mode,\n               int *fildes, const char **errmsg)\n{\n  pid_t pid;\n\n  int child_stdin[2], child_stdout[2];\n\n  if (pipe (child_stdin) < 0)\n    {\n      *errmsg = strerror (errno);\n      return -1;\n    }\n\n  if (pipe (child_stdout) < 0)\n    {\n      close (child_stdin[0]);\n      close (child_stdin[1]);\n\n      *errmsg = strerror (errno);\n      return -1;\n    }\n\n  pid = fork ();\n\n  if (pid == 0)\n    {\n      // Child process\n\n      close (child_stdin[1]);\n      close (child_stdout[0]);\n\n      if (dup2 (child_stdin[0], STDIN_FILENO) >= 0)\n        {\n          close (child_stdin[0]);\n\n          if (dup2 (child_stdout[1], STDOUT_FILENO) >= 0)\n            {\n              close (child_stdout[1]);\n\n              if (execvp (cmd, args) < 0)\n                perror (\"error: popen2 (child)\");\n            }\n          else\n            perror (\"error: popen2 (child)\");\n        }\n      else\n        perror (\"error: popen2 (child)\");\n\n      _Exit (OCTAVE_CHILD_FAILURE);  \n    }\n  else if (pid > 0)\n    {\n      // Parent process\n\n      close (child_stdin[0]);\n      close (child_stdout[1]);\n\n#if defined (F_SETFL) && defined (O_NONBLOCK)\n      if (! sync_mode && fcntl (child_stdout[0], F_SETFL, O_NONBLOCK) < 0)\n        {\n          *errmsg = strerror (errno);\n          return -1;\n        }\n      else\n#endif\n        {\n          fildes[0] = child_stdin[1];\n          fildes[1] = child_stdout[0];\n\n          // Sanity check that child process hasn't already aborted.\n          // Note: Maybe use nanosleep() as usleep() is deprecated/removed\n          // after 2008?\n          usleep (5e3);  // wait for 5 milliseconds\n          int wstatus;\n          pid_t tst_pid = waitpid (pid, &wstatus, WNOHANG);\n          if (tst_pid == -1)\n            {\n              // Error with waitpid ()\n              *errmsg = strerror (errno);\n              return -1;\n            }\n          else if (tst_pid != 0)\n            {\n              // Child has already changed state, probably bad, but verify\n              if (WIFEXITED(wstatus)\n                  && WEXITSTATUS(wstatus) == OCTAVE_CHILD_FAILURE)\n                {\n                  *errmsg = \"popen2 (parent): failure in child process\";\n                  return -1;\n                }\n            }\n\n          return pid;\n        }\n    }\n\n  // Reaching this code means fork() was unsuccessful\n  *errmsg = strerror (errno);\n  return -1;\n}\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/octave-popen2.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_octave_popen2_h)\n#define octave_octave_popen2_h 1\n\n#if ! defined (__cplusplus)\n#  include <stdbool.h>\n#endif\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API pid_t\noctave_popen2 (const char *cmd, char *const *args, bool sync_mode,\n               int *fildes, const char **errmsg);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/pwd-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2023-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// pwd.h might set some preprocessor definitions that replace Octave functions\n// in compilation units where it is included.  Use these wrappers to avoid that.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#if defined (HAVE_PWD_H)\n#  include <pwd.h>\n#endif\n\n#include \"pwd-wrappers.h\"\n\nstruct passwd *octave_getpwent_wrapper (void)\n{\n#if defined HAVE_GETPWENT\n  return getpwent ();\n#else\n  return NULL;\n#endif\n}\n\nstruct passwd *octave_getpwuid_wrapper (uid_t uid)\n{\n#if defined (HAVE_GETPWUID)\n  return getpwuid (uid);\n#else\n  octave_unused_parameter (uid);\n\n  return NULL;\n#endif\n}\n\nstruct passwd *octave_getpwnam_wrapper (const char *nam)\n{\n#if defined (HAVE_GETPWNAM)\n  return getpwnam (nam);\n#else\n  octave_unused_parameter (nam);\n\n  return NULL;\n#endif\n}\n\nvoid octave_setpwent_wrapper (void)\n{\n#if defined (HAVE_SETPWENT)\n  setpwent ();\n#endif\n  return;\n}\n\nvoid octave_endpwent_wrapper (void)\n{\n#if defined (HAVE_ENDPWENT)\n  endpwent ();\n#endif\n  return;\n}\n\nvoid octave_from_passwd (const struct passwd *pw,\n                         struct octave_passwd_wrapper *oct_pw)\n{\n#if defined (HAVE_PWD_H)\n  oct_pw->pw_name = pw->pw_name;\n  oct_pw->pw_passwd = pw->pw_passwd;\n  oct_pw->pw_uid = pw->pw_uid;\n  oct_pw->pw_gid = pw->pw_gid;\n  oct_pw->pw_gecos = pw->pw_gecos;\n  oct_pw->pw_dir = pw->pw_dir;\n  oct_pw->pw_shell = pw->pw_shell;\n#else\n  octave_unused_parameter (pw);\n  octave_unused_parameter (oct_pw);\n#endif\n  return;\n}\n"
  },
  {
    "path": "liboctave/wrappers/pwd-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2023-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_pwd_wrappers_h)\n#define octave_pwd_wrappers_h 1\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nstruct passwd;\n\n// We can't include <pwd.h> without the risk of overwriting function names\n// with preprocessor deinitions.  Define a struct that can hold the needed\n// fields, and use a function to convert from struct passwd to it.\nstruct octave_passwd_wrapper\n{\n  char *pw_name;\n  char *pw_passwd;\n  uid_t pw_uid;\n  gid_t pw_gid;\n  char *pw_gecos;\n  char *pw_dir;\n  char *pw_shell;\n};\n\nextern OCTAVE_API struct passwd * octave_getpwent_wrapper (void);\n\nextern OCTAVE_API struct passwd * octave_getpwuid_wrapper (uid_t uid);\n\nextern OCTAVE_API struct passwd * octave_getpwnam_wrapper (const char *nam);\n\nextern OCTAVE_API void octave_setpwent_wrapper (void);\n\nextern OCTAVE_API void octave_endpwent_wrapper (void);\n\nextern OCTAVE_API void octave_endpwent_wrapper (void);\n\nextern OCTAVE_API void\noctave_from_passwd (const struct passwd *pw,\n                    struct octave_passwd_wrapper *oct_pw);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/select-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sys/select.h>\n\n#include \"select-wrappers.h\"\n\nint\noctave_select (int nfds, /* fd_set *restrict */ void *restrict readfds,\n               /* fd_set *restrict */ void *restrict writefds,\n               /* fd_set *restrict */ void *restrict errorfds,\n               /* struct timeval * */ void *timeout)\n{\n  return select (nfds, (fd_set *restrict) readfds, (fd_set *restrict) writefds,\n                 (fd_set *restrict) errorfds, (struct timeval *) timeout);\n}\n\nvoid\noctave_fd_set (int fd, /* fd_set * */ void *set)\n{\n  FD_SET (fd, (fd_set *) set);\n}\n\nvoid\noctave_fd_clr (int fd, /* fd_set * */ void *set)\n{\n  FD_CLR (fd, (fd_set *) set);\n}\n\nint\noctave_fd_isset (int fd, /* fd_set * */ void *set)\n{\n  return FD_ISSET (fd, (fd_set *) set);\n}\n\nvoid\noctave_fd_zero (/* fd_set * */ void *set)\n{\n  FD_ZERO ((fd_set *) set);\n}\n"
  },
  {
    "path": "liboctave/wrappers/select-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2024-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_wait_for_input_h)\n#define octave_wait_for_input_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n// We'd need to include gnulib headers for the 'fd_set', 'struct timeval'\n// types.  Use 'void *' or 'int' in the wrapper interfaces instead.\n\nextern OCTAVE_API int\noctave_select (int nfds, /* fd_set *restrict */ void *restrict readfds,\n               /* fd_set *restrict */ void *restrict writefds,\n               /* fd_set *restrict */ void *restrict errorfds,\n               /* struct timeval * */ void *timeout);\n\nextern OCTAVE_API void\noctave_fd_set (int fd, /* fd_set * */ void *set);\n\nextern OCTAVE_API void\noctave_fd_clr (int fd, /* fd_set * */ void *set);\n\nextern OCTAVE_API int\noctave_fd_isset (int fd, /* fd_set * */ void *set);\n\nextern OCTAVE_API void\noctave_fd_zero (/* fd_set * */ void *set);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/set-program-name-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// set_program_name is provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"progname.h\"\n\n#include \"set-program-name-wrapper.h\"\n\nconst char *\noctave_set_program_name_wrapper (const char *pname)\n{\n  set_program_name (pname);\n\n  // Let gnulib strip off things like the \"lt-\" prefix from libtool.\n  return program_name;\n}\n"
  },
  {
    "path": "liboctave/wrappers/set-program-name-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_set_program_name_wrapper_h)\n#define octave_set_program_name_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API const char *\noctave_set_program_name_wrapper (const char *pname);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/setenv-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// unsetenv may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdlib.h>\n\n#include \"setenv-wrapper.h\"\n\nint\noctave_setenv_wrapper (const char *envname, const char *envval, int overwrite)\n{\n  return setenv (envname, envval, overwrite);\n}\n"
  },
  {
    "path": "liboctave/wrappers/setenv-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2025-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_setenv_wrapper_h)\n#define octave_setenv_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int\noctave_setenv_wrapper (const char *envname, const char *envval, int overwrite);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/signal-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sys/types.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n#  include <windows.h>\n#else\n#  include <pthread.h>\n#endif\n\n#include \"signal-wrappers.h\"\n\nint\noctave_kill_wrapper (pid_t pid, int signum)\n{\n#if defined (HAVE_KILL)\n  return kill (pid, signum);\n#elif defined (HAVE_RAISE)\n  octave_unused_parameter (pid);\n\n  return raise (signum);\n#else\n  octave_unused_parameter (pid);\n  octave_unused_parameter (signum);\n\n  return -1;\n#endif\n}\n\nchar *\noctave_strsignal_wrapper (int signum)\n{\n  return strsignal (signum);\n}\n\nbool\noctave_have_kill (void)\n{\n#if defined (HAVE_KILL)\n  return true;\n#else\n  return false;\n#endif\n}\n\nbool\noctave_get_sig_number (const char *signame, int *signum)\n{\n  *signum = -1;\n\n  // FIXME: this should probably use a perfect hash function.\n\n  if (! strcmp (signame, \"SIGINT\"))\n    {\n#if defined (SIGINT)\n      *signum = SIGINT;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGBREAK\"))\n    {\n#if defined (SIGBREAK)\n      *signum = SIGBREAK;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGABRT\"))\n    {\n#if defined (SIGABRT)\n      *signum = SIGABRT;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGALRM\"))\n    {\n#if defined (SIGALRM)\n      *signum = SIGALRM;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGBUS\"))\n    {\n#if defined (SIGBUS)\n      *signum = SIGBUS;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGCHLD\"))\n    {\n#if defined (SIGCHLD)\n      *signum = SIGCHLD;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGCLD\"))\n    {\n#if defined (SIGCLD)\n      *signum = SIGCLD;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGCONT\"))\n    {\n#if defined (SIGCONT)\n      *signum = SIGCONT;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGEMT\"))\n    {\n#if defined (SIGEMT)\n      *signum = SIGEMT;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGFPE\"))\n    {\n#if defined (SIGFPE)\n      *signum = SIGFPE;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGHUP\"))\n    {\n#if defined (SIGHUP)\n      *signum = SIGHUP;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGILL\"))\n    {\n#if defined (SIGILL)\n      *signum = SIGILL;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGINFO\"))\n    {\n#if defined (SIGINFO)\n      *signum = SIGINFO;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGIOT\"))\n    {\n#if defined (SIGIOT)\n      *signum = SIGIOT;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGKILL\"))\n    {\n#if defined (SIGKILL)\n      *signum = SIGKILL;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGLOST\"))\n    {\n#if defined (SIGLOST)\n      *signum = SIGLOST;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGPIPE\"))\n    {\n#if defined (SIGPIPE)\n      *signum = SIGPIPE;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGPOLL\"))\n    {\n#if defined (SIGPOLL)\n      *signum = SIGPOLL;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGPROF\"))\n    {\n#if defined (SIGPROF)\n      *signum = SIGPROF;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGPWR\"))\n    {\n#if defined (SIGPWR)\n      *signum = SIGPWR;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGQUIT\"))\n    {\n#if defined (SIGQUIT)\n      *signum = SIGQUIT;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGSEGV\"))\n    {\n#if defined (SIGSEGV)\n      *signum = SIGSEGV;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGSTOP\"))\n    {\n#if defined (SIGSTOP)\n      *signum = SIGSTOP;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGSYS\"))\n    {\n#if defined (SIGSYS)\n      *signum = SIGSYS;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGTERM\"))\n    {\n#if defined (SIGTERM)\n      *signum = SIGTERM;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGTRAP\"))\n    {\n#if defined (SIGTRAP)\n      *signum = SIGTRAP;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGTSTP\"))\n    {\n#if defined (SIGTSTP)\n      *signum = SIGTSTP;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGTTIN\"))\n    {\n#if defined (SIGTTIN)\n      *signum = SIGTTIN;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGTTOU\"))\n    {\n#if defined (SIGTTOU)\n      *signum = SIGTTOU;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGURG\"))\n    {\n#if defined (SIGURG)\n      *signum = SIGURG;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGUSR1\"))\n    {\n#if defined (SIGUSR1)\n      *signum = SIGUSR1;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGUSR2\"))\n    {\n#if defined (SIGUSR2)\n      *signum = SIGUSR2;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGVTALRM\"))\n    {\n#if defined (SIGVTALRM)\n      *signum = SIGVTALRM;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGIO\"))\n    {\n#if defined (SIGIO)\n      *signum = SIGIO;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGWINCH\"))\n    {\n#if defined (SIGWINCH)\n      *signum = SIGWINCH;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGXCPU\"))\n    {\n#if defined (SIGXCPU)\n      *signum = SIGXCPU;\n      return true;\n#endif\n    }\n  else if (! strcmp (signame, \"SIGXFSZ\"))\n    {\n#if defined (SIGXFSZ)\n      *signum = SIGXFSZ;\n      return true;\n#endif\n    }\n\n  return false;\n}\n\noctave_sig_handler *\noctave_set_signal_handler_internal (int sig, octave_sig_handler *handler,\n                                    bool restart_syscalls)\n{\n  struct sigaction act, oact;\n\n  act.sa_handler = handler;\n  act.sa_flags = 0;\n\n#if defined (SIGALRM)\n  if (sig == SIGALRM)\n    {\n#  if defined (SA_INTERRUPT)\n      act.sa_flags |= SA_INTERRUPT;\n#  endif\n    }\n#endif\n#if defined (SA_RESTART)\n#  if defined (SIGALRM)\n  else\n#  endif\n  // FIXME: Do we also need to explicitly disable SA_RESTART?\n  if (restart_syscalls)\n    act.sa_flags |= SA_RESTART;\n#endif\n\n  sigemptyset (&act.sa_mask);\n  sigemptyset (&oact.sa_mask);\n\n  sigaction (sig, &act, &oact);\n\n  return oact.sa_handler;\n}\n\noctave_sig_handler *\noctave_set_signal_handler_by_name (const char *signame,\n                                   octave_sig_handler *handler,\n                                   bool restart_syscalls)\n{\n  int sig;\n\n  return (octave_get_sig_number (signame, &sig)\n          ? octave_set_signal_handler_internal (sig, handler, restart_syscalls)\n          : 0);\n}\n\noctave_sig_handler *\noctave_set_default_signal_handler (int sig)\n{\n  return octave_set_signal_handler_internal (sig, SIG_DFL, true);\n}\n\noctave_sig_handler *\noctave_set_default_signal_handler_by_name (const char *signame)\n{\n  return octave_set_signal_handler_by_name (signame, SIG_DFL, true);\n}\n\nint\noctave_num_signals (void)\n{\n  return NSIG;\n}\n\ntypedef struct\n{\n  sigset_t nvar;\n  sigset_t ovar;\n} sigset_info;\n\nvoid *\noctave_block_child (void)\n{\n#if defined (SIGCHLD) || defined (SIGCLD)\n\n  sigset_info *context = (sigset_info *) malloc (sizeof (sigset_info));\n\n  if (context)\n    {\n      sigemptyset (&(context->ovar));\n      sigemptyset (&(context->nvar));\n#if defined (SIGCHLD)\n      sigaddset (&(context->nvar), SIGCHLD);\n#endif\n#if defined (SIGCLD)\n      sigaddset (&(context->nvar), SIGCLD);\n#endif\n      sigprocmask (SIG_BLOCK, &(context->nvar), &(context->ovar));\n    }\n\n  return context;\n\n#else\n\n  return 0;\n\n#endif\n}\n\nvoid\noctave_unblock_child (void *context_arg)\n{\n  if (context_arg)\n    {\n      sigset_info *context = (sigset_info *) context_arg;\n\n      sigprocmask (SIG_SETMASK, &(context->ovar), 0);\n\n      free (context);\n    }\n}\n\nstatic void\nblock_or_unblock_signal (int how, int sig)\n{\n#if ! defined (__WIN32__) || defined (__CYGWIN__)\n\n  // Blocking/unblocking signals at thread level is only supported\n  // on platform with fully compliant POSIX threads.  This is not\n  // supported on Win32.  Moreover, we have to make sure that SIGINT\n  // handler is not installed before calling AllocConsole: installing\n  // a SIGINT handler internally calls SetConsoleCtrlHandler, which\n  // must be called after AllocConsole to be effective.\n\n  sigset_t signal_mask;\n\n  sigemptyset (&signal_mask);\n\n  sigaddset (&signal_mask, sig);\n\n  pthread_sigmask (how, &signal_mask, 0);\n\n#else\n\n  octave_unused_parameter (how);\n  octave_unused_parameter (sig);\n\n#endif\n}\n\nvoid\noctave_block_interrupt_signal (void)\n{\n  block_or_unblock_signal (SIG_BLOCK, SIGINT);\n\n#if defined (SIGBREAK)\n  block_or_unblock_signal (SIG_BLOCK, SIGBREAK);\n#endif\n}\n\nvoid\noctave_unblock_interrupt_signal (void)\n{\n  block_or_unblock_signal (SIG_UNBLOCK, SIGINT);\n\n#if defined (SIGBREAK)\n  block_or_unblock_signal (SIG_UNBLOCK, SIGBREAK);\n#endif\n}\n\nstatic void\nblock_or_unblock_signal_by_name (int how, const char *signame)\n{\n  int sig;\n\n  if (octave_get_sig_number (signame, &sig))\n    block_or_unblock_signal (how, sig);\n}\n\nvoid\noctave_block_signal_by_name (const char *signame)\n{\n  block_or_unblock_signal_by_name (SIG_BLOCK, signame);\n}\n\nvoid\noctave_unblock_signal_by_name (const char *signame)\n{\n  block_or_unblock_signal_by_name (SIG_UNBLOCK, signame);\n}\n\n/* Allow us to save the signal mask and then restore it to the most\n   recently saved value.  This is necessary when using the POSIX signal\n   handling interface on some systems calling longjmp out of the signal\n   handler to get to the top level on an interrupt doesn't restore the\n   original signal mask.  Alternatively, we could use\n   sigsetjmp/siglongjmp, but saving and restoring the signal mask\n   ourselves works ok and seems simpler just now.  */\n\nstatic sigset_t octave_signal_mask;\n\nvoid\noctave_save_signal_mask (void)\n{\n  sigprocmask (0, 0, &octave_signal_mask);\n}\n\nvoid\noctave_restore_signal_mask (void)\n{\n  sigprocmask (SIG_SETMASK, &octave_signal_mask, 0);\n}\n\nvoid *\noctave_alloc_signal_mask (void)\n{\n  return malloc (sizeof (sigset_t));\n}\n\nvoid\noctave_free_signal_mask (void *mask)\n{\n  free (mask);\n}\n\nvoid\noctave_get_signal_mask (void *mask)\n{\n  sigprocmask (0, 0, mask);\n}\n\nvoid\noctave_set_signal_mask (void *mask)\n{\n  sigprocmask (SIG_SETMASK, (sigset_t *) mask, 0);\n}\n\nint\noctave_raise_wrapper (int signum)\n{\n  return raise (signum);\n}\n\n#if ! defined (__WIN32__)\nstatic void\nprint_sigset (FILE *of, const char *prefix, const sigset_t *sigset)\n{\n  int sig;\n  int cnt = 0;\n\n  for (sig = 1; sig < NSIG; sig++)\n    {\n      if (sigismember (sigset, sig))\n        {\n          cnt++;\n          fprintf (of, \"%ld: %s%d (%s)\\n\", (long int) pthread_self (),\n                   prefix, sig, strsignal (sig));\n        }\n    }\n\n  if (cnt == 0)\n    fprintf (of, \"%ld: %s<empty signal set>\\n\", (long int) pthread_self (),\n             prefix);\n}\n\nstatic int\nprint_sigmask (FILE *of, const char *msg)\n{\n  sigset_t sigmask;\n\n  if (msg)\n    fprintf (of, \"%s\", msg);\n\n  if (pthread_sigmask (SIG_BLOCK, NULL, &sigmask) == -1)\n    return -1;\n\n  print_sigset (of, \"\\t\\t\", &sigmask);\n\n  return 0;\n}\n#endif\n\nvoid\noctave_show_sigmask (const char *msg)\n{\n#if ! defined (__WIN32__)\n  if (! msg)\n    msg = \"signal mask\\n\";\n\n  print_sigmask (stderr, msg);\n#else\n  octave_unused_parameter (msg);\n\n  fputs (\"no signal mask on Windows systems\\n\", stderr);\n#endif\n}\n"
  },
  {
    "path": "liboctave/wrappers/signal-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_signal_wrappers_h)\n#define octave_signal_wrappers_h 1\n\n#if ! defined (__cplusplus)\n#  include <stdbool.h>\n#endif\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\ntypedef void octave_sig_handler (int);\n\nextern OCTAVE_API int octave_kill_wrapper (pid_t pid, int signum);\n\nextern OCTAVE_API char * octave_strsignal_wrapper (int signum);\n\nextern OCTAVE_API bool octave_have_kill (void);\n\nextern OCTAVE_API bool octave_get_sig_number (const char *signame, int *signum);\n\nextern OCTAVE_API octave_sig_handler *\noctave_set_signal_handler_internal (int sig, octave_sig_handler *handler,\n                                    bool restart_syscalls);\n\nextern OCTAVE_API octave_sig_handler *\noctave_set_signal_handler_by_name (const char *signame,\n                                   octave_sig_handler *handler,\n                                   bool restart_syscalls);\n\nextern OCTAVE_API octave_sig_handler *\noctave_set_default_signal_handler (int sig);\n\nextern OCTAVE_API octave_sig_handler *\noctave_set_default_signal_handler_by_name (const char *signame);\n\nextern OCTAVE_API int octave_num_signals (void);\n\nextern OCTAVE_API void * octave_block_child (void);\n\nextern OCTAVE_API void octave_unblock_child (void *context);\n\nextern OCTAVE_API void octave_block_interrupt_signal (void);\n\nextern OCTAVE_API void octave_unblock_interrupt_signal (void);\n\nextern OCTAVE_API void octave_block_signal_by_name (const char *signame);\n\nextern OCTAVE_API void octave_unblock_signal_by_name (const char *signame);\n\nextern OCTAVE_API void octave_save_signal_mask (void);\n\nextern OCTAVE_API void octave_restore_signal_mask (void);\n\nextern OCTAVE_API void * octave_alloc_signal_mask (void);\n\nextern OCTAVE_API void octave_free_signal_mask (void *mask);\n\nextern OCTAVE_API void octave_get_signal_mask (void *mask);\n\nextern OCTAVE_API void octave_set_signal_mask (void *mask);\n\nextern OCTAVE_API int octave_raise_wrapper (int signum);\n\n// This function can be useful for debugging.\n\nextern OCTAVE_API void octave_show_sigmask (const char *);\n\n// The next three functions are defined in cxx-signal-helpers.cc.\n\nextern OCTAVE_API void\noctave_create_interrupt_watcher_thread (octave_sig_handler *handler);\n\nextern OCTAVE_API void octave_block_async_signals (void);\n\nextern OCTAVE_API void octave_unblock_async_signals (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/stat-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <time.h>\n\n#include <sys/types.h>\n#include <sys/stat.h>\n\n// Silence compiler warning if stat doesn't support nanosecond-precision\n// time stamps (e.g., on Windows).\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#endif\n\n#include \"stat-time.h\"\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n#  pragma GCC diagnostic pop\n#endif\n\n#include \"stat-wrappers.h\"\n#include \"uniconv-wrappers.h\"\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <windows.h>\n#  include <wchar.h>\n#endif\n\nint\noctave_mkdir_wrapper (const char *name, mode_t mode)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  wchar_t *wname = u8_to_wchar (name);\n  int status = _wmkdir (wname);\n  free ((void *) wname);\n  octave_unused_parameter (mode);\n  return status;\n#else\n  return mkdir (name, mode);\n#endif\n}\n\nint\noctave_mkfifo_wrapper (const char *name, mode_t mode)\n{\n  return mkfifo (name, mode);\n}\n\nint\noctave_umask_wrapper (mode_t mode)\n{\n  return umask (mode);\n}\n\nstatic inline void\nassign_stat_fields (struct stat *buf, mode_t *mode, ino_t *ino,\n                    dev_t *dev, nlink_t *nlink, uid_t *uid,\n                    gid_t *gid, off_t *size, time_t *atime,\n                    long int *atime_nsec, time_t *mtime, long int *mtime_nsec,\n                    time_t *ctime, long int *ctime_nsec, dev_t *rdev,\n                    long *blksize, long *blocks)\n{\n  *mode = buf->st_mode;\n  *ino = buf->st_ino;\n  *dev = buf->st_dev;\n  *nlink = buf->st_nlink;\n  *uid = buf->st_uid;\n  *gid = buf->st_gid;\n  *size = buf->st_size;\n  *atime = buf->st_atime;\n  *atime_nsec = get_stat_atime_ns (buf);\n  *mtime = buf->st_mtime;\n  *mtime_nsec = get_stat_mtime_ns (buf);\n  *ctime = buf->st_ctime;\n  *ctime_nsec = get_stat_ctime_ns (buf);\n\n#if defined (HAVE_STRUCT_STAT_ST_RDEV)\n  *rdev = buf->st_rdev;\n#else\n  *rdev = 0;\n#endif\n\n#if defined (HAVE_STRUCT_STAT_ST_BLKSIZE)\n  *blksize = buf->st_blksize;\n#else\n  *blksize = 0;\n#endif\n\n#if defined (HAVE_STRUCT_STAT_ST_BLOCKS)\n  *blocks = buf->st_blocks;\n#else\n  *blocks = 0;\n#endif\n}\n\nint\noctave_stat_wrapper (const char *fname, mode_t *mode, ino_t *ino,\n                     dev_t *dev, nlink_t *nlink, uid_t *uid,\n                     gid_t *gid, off_t *size, time_t *atime,\n                     long int *atime_nsec, time_t *mtime, long int *mtime_nsec,\n                     time_t *ctime, long int *ctime_nsec, dev_t *rdev,\n                     long *blksize, long *blocks)\n{\n  struct stat buf;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  wchar_t *wfname = u8_to_wchar (fname);\n  int status = _wstati64 (wfname, &buf);\n  free ((void *) wfname);\n#else\n  int status = stat (fname, &buf);\n#endif\n\n  assign_stat_fields (&buf, mode, ino, dev, nlink, uid, gid, size,\n                      atime, atime_nsec, mtime, mtime_nsec, ctime, ctime_nsec,\n                      rdev, blksize, blocks);\n\n  return status;\n}\n\nint\noctave_lstat_wrapper (const char *lname, mode_t *mode, ino_t *ino,\n                      dev_t *dev, nlink_t *nlink, uid_t *uid,\n                      gid_t *gid, off_t *size, time_t *atime,\n                      long int *atime_nsec, time_t *mtime, long int *mtime_nsec,\n                      time_t *ctime, long int *ctime_nsec, dev_t *rdev,\n                      long *blksize, long *blocks)\n{\n  struct stat buf;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  // Windows doesn't have an lstat.  Use stat instead\n  wchar_t *wlname = u8_to_wchar (lname);\n  int status = _wstati64 (wlname, &buf);\n  free ((void *) wlname);\n#else\n  int status = lstat (lname, &buf);\n#endif\n\n  assign_stat_fields (&buf, mode, ino, dev, nlink, uid, gid, size,\n                      atime, atime_nsec, mtime, mtime_nsec, ctime, ctime_nsec,\n                      rdev, blksize, blocks);\n\n  return status;\n}\n\nint\noctave_fstat_wrapper (int fid, mode_t *mode, ino_t *ino,\n                      dev_t *dev, nlink_t *nlink, uid_t *uid,\n                      gid_t *gid, off_t *size, time_t *atime,\n                      long int *atime_nsec, time_t *mtime, long int *mtime_nsec,\n                      time_t *ctime, long int *ctime_nsec, dev_t *rdev,\n                      long *blksize, long *blocks)\n{\n  struct stat buf;\n\n  int status = fstat (fid, &buf);\n\n  assign_stat_fields (&buf, mode, ino, dev, nlink, uid, gid, size,\n                      atime, atime_nsec, mtime, mtime_nsec, ctime, ctime_nsec,\n                      rdev, blksize, blocks);\n\n  return status;\n}\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n// Disable the unused parameter warning for the following wrapper functions.\n// The <sys/stat.h> header provided by gnulib may define some of the S_IS*\n// macros to expand to a constant and ignore the parameter.\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#endif\n\nbool\noctave_is_blk_wrapper (mode_t mode)\n{\n#if defined (S_ISBLK)\n  return S_ISBLK (mode);\n#else\n  return false;\n#endif\n}\n\nbool\noctave_is_chr_wrapper (mode_t mode)\n{\n#if defined (S_ISCHR)\n  return S_ISCHR (mode);\n#else\n  return false;\n#endif\n}\n\nbool\noctave_is_dir_wrapper (mode_t mode)\n{\n#if defined (S_ISDIR)\n  return S_ISDIR (mode);\n#else\n  return false;\n#endif\n}\n\nbool\noctave_is_fifo_wrapper (mode_t mode)\n{\n#if defined (S_ISFIFO)\n  return S_ISFIFO (mode);\n#else\n  return false;\n#endif\n}\n\nbool\noctave_is_lnk_wrapper (mode_t mode)\n{\n#if defined (S_ISLNK)\n  return S_ISLNK (mode);\n#else\n  return false;\n#endif\n}\n\nbool\noctave_is_reg_wrapper (mode_t mode)\n{\n#if defined (S_ISREG)\n  return S_ISREG (mode);\n#else\n  return false;\n#endif\n}\n\nbool\noctave_is_sock_wrapper (mode_t mode)\n{\n#if defined (S_ISSOCK)\n  return S_ISSOCK (mode);\n#else\n  return false;\n#endif\n}\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n// Restore prevailing warning state for remainder of the file.\n#  pragma GCC diagnostic pop\n#endif\n\nbool\noctave_have_struct_stat_st_rdev (void)\n{\n#if defined (HAVE_STRUCT_STAT_ST_RDEV)\n  return true;\n#else\n  return false;\n#endif\n}\n\nbool\noctave_have_struct_stat_st_blksize (void)\n{\n#if defined (HAVE_STRUCT_STAT_ST_BLKSIZE)\n  return true;\n#else\n  return false;\n#endif\n}\n\nbool\noctave_have_struct_stat_st_blocks (void)\n{\n#if defined (HAVE_STRUCT_STAT_ST_BLOCKS)\n  return true;\n#else\n  return false;\n#endif\n}\n"
  },
  {
    "path": "liboctave/wrappers/stat-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_stat_wrappers_h)\n#define octave_stat_wrappers_h 1\n\n#if defined (__cplusplus)\n#  include <ctime>\n#else\n#  include <stdbool.h>\n#  include <time.h>\n#endif\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int octave_mkdir_wrapper (const char *name, mode_t mode);\n\nextern OCTAVE_API int octave_mkfifo_wrapper (const char *name, mode_t mode);\n\nextern OCTAVE_API int octave_umask_wrapper (mode_t mode);\n\nextern OCTAVE_API int\noctave_stat_wrapper (const char *fname, mode_t *mode, ino_t *ino,\n                     dev_t *dev, nlink_t *nlink, uid_t *uid,\n                     gid_t *gid, off_t *size, time_t *atime,\n                     long int *atime_nsec, time_t *mtime, long int *mtime_nsec,\n                     time_t *ctime, long int *ctime_nsec, dev_t *rdev,\n                     long *blksize, long *blocks);\n\nextern OCTAVE_API int\noctave_lstat_wrapper (const char *lname, mode_t *mode, ino_t *ino,\n                      dev_t *dev, nlink_t *nlink, uid_t *uid,\n                      gid_t *gid, off_t *size, time_t *atime,\n                      long int *atime_nsec, time_t *mtime, long int *mtime_nsec,\n                      time_t *ctime, long int *ctime_nsec, dev_t *rdev,\n                      long *blksize, long *blocks);\n\nextern OCTAVE_API int\noctave_fstat_wrapper (int fid, mode_t *mode, ino_t *ino,\n                      dev_t *dev, nlink_t *nlink, uid_t *uid,\n                      gid_t *gid, off_t *size, time_t *atime,\n                      long int *atime_nsec, time_t *mtime, long int *mtime_nsec,\n                      time_t *ctime, long int *ctime_nsec, dev_t *rdev,\n                      long *blksize, long *blocks);\n\nextern OCTAVE_API bool octave_is_blk_wrapper (mode_t mode);\nextern OCTAVE_API bool octave_is_chr_wrapper (mode_t mode);\nextern OCTAVE_API bool octave_is_dir_wrapper (mode_t mode);\nextern OCTAVE_API bool octave_is_fifo_wrapper (mode_t mode);\nextern OCTAVE_API bool octave_is_lnk_wrapper (mode_t mode);\nextern OCTAVE_API bool octave_is_reg_wrapper (mode_t mode);\nextern OCTAVE_API bool octave_is_sock_wrapper (mode_t mode);\n\nextern OCTAVE_API bool octave_have_struct_stat_st_rdev (void);\nextern OCTAVE_API bool octave_have_struct_stat_st_blksize (void);\nextern OCTAVE_API bool octave_have_struct_stat_st_blocks (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/strcase-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2022-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <strings.h>\n\n#include \"strcase-wrappers.h\"\n\nOCTAVE_API int\noctave_strcasecmp (const char *s1, const char *s2)\n{\n  return strcasecmp (s1, s2);\n}\n\nOCTAVE_API int\noctave_strncasecmp (const char *s1, const char *s2, size_t n)\n{\n  return strncasecmp (s1, s2, n);\n}\n"
  },
  {
    "path": "liboctave/wrappers/strcase-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2022-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_strcase_wrappers_h)\n#define octave_strcase_wrappers_h 1\n\n#include \"octave-config.h\"\n\n#if defined (__cplusplus)\n#include <cstddef>\nusing std::size_t;\nextern \"C\" {\n#else\n#include <stddef.h>\n#endif\n\nOCTAVE_API int\noctave_strcasecmp (const char *s1, const char *s2);\n\nOCTAVE_API int\noctave_strncasecmp (const char *s1, const char *s2, size_t n);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/strdup-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// strdup may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include \"strdup-wrapper.h\"\n\nchar *\noctave_strdup_wrapper (const char *str)\n{\n  return strdup (str);\n}\n"
  },
  {
    "path": "liboctave/wrappers/strdup-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_strdup_wrapper_h)\n#define octave_strdup_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API char * octave_strdup_wrapper (const char *str);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/strftime-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// nstrftime is provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <time.h>\n\n#include \"strftime.h\"\n\n#include \"strftime-wrapper.h\"\n\nsize_t\noctave_strftime_wrapper (char *buf, size_t len, const char *fmt,\n                         const struct tm *t)\n{\n  return nstrftime (buf, len, fmt, t, NULL, 0);\n}\n"
  },
  {
    "path": "liboctave/wrappers/strftime-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_strftime_wrapper_h)\n#define octave_strftime_wrapper_h 1\n\n#if defined (__cplusplus)\n#  include <cstddef>\n#  include <ctime>\n#else\n#  include <stddef.h>\n#  include <time.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API size_t\noctave_strftime_wrapper (char *buf, size_t len, const char *fmt,\n                         const struct tm *t);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/strmode-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// strmode may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"filemode.h\"\n\n#include \"strmode-wrapper.h\"\n\nvoid\noctave_strmode_wrapper (mode_t mode, char *buffer)\n{\n  strmode (mode, buffer);\n}\n"
  },
  {
    "path": "liboctave/wrappers/strmode-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_strmode_wrapper_h)\n#define octave_strmode_wrapper_h 1\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n// Expects a buffer with at least 12 characters.\n\nextern OCTAVE_API void octave_strmode_wrapper (mode_t mode, char *buffer);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/strptime-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// strptime may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <time.h>\n\n#include \"strptime-wrapper.h\"\n\nchar *\noctave_strptime_wrapper (const char *p, const char *fmt, struct tm *t)\n{\n  return strptime (p, fmt, t);\n}\n"
  },
  {
    "path": "liboctave/wrappers/strptime-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_strptime_wrapper_h)\n#define octave_strptime_wrapper_h 1\n\n#if defined (__cplusplus)\n#  include <ctime>\n#else\n#  include <time.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API char *\noctave_strptime_wrapper (const char *p, const char *fmt, struct tm *t);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/time-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sys/resource.h>\n#include <sys/time.h>\n#include <sys/times.h>\n\n#include \"time-wrappers.h\"\n\nint\noctave_gettimeofday_wrapper (time_t *sec, long *usec)\n{\n  struct timeval tv;\n\n  int status = gettimeofday (&tv, NULL);\n\n  if (status < 0)\n    {\n      *sec = 0;\n      *usec = 0;\n    }\n  else\n    {\n      *sec = tv.tv_sec;\n      *usec = tv.tv_usec;\n    }\n\n  return status;\n}\n\nint\noctave_cpu_time (time_t *usr_sec, time_t *sys_sec,\n                 long *usr_usec, long *sys_usec)\n{\n  struct rusage ru;\n\n  int status = getrusage (RUSAGE_SELF, &ru);\n\n  if (status < 0)\n    {\n      *usr_sec = 0;\n      *sys_sec = 0;\n\n      *usr_usec = 0;\n      *sys_usec = 0;\n    }\n  else\n    {\n      *usr_sec = ru.ru_utime.tv_sec;\n      *usr_usec = ru.ru_utime.tv_usec;\n\n      *sys_sec = ru.ru_stime.tv_sec;\n      *sys_usec = ru.ru_stime.tv_usec;\n    }\n\n  return status;\n}\n\nint\noctave_getrusage_wrapper (time_t *usr_sec, time_t *sys_sec,\n                          long *usr_usec, long *sys_usec,\n                          long *maxrss, long *ixrss, long *idrss,\n                          long *isrss, long *minflt, long *majflt,\n                          long *nswap, long *inblock, long *oublock,\n                          long *msgsnd, long *msgrcv, long *nsignals,\n                          long *nvcsw, long *nivcsw)\n{\n  struct rusage ru;\n\n  int status = getrusage (RUSAGE_SELF, &ru);\n\n  if (status < 0)\n    {\n      *usr_sec = 0;\n      *usr_usec = 0;\n\n      *sys_sec = 0;\n      *sys_usec = 0;\n\n      *maxrss = 0;\n      *ixrss = 0;\n      *idrss = 0;\n      *isrss = 0;\n      *minflt = 0;\n      *majflt = 0;\n      *nswap = 0;\n      *inblock = 0;\n      *oublock = 0;\n      *msgsnd = 0;\n      *msgrcv = 0;\n      *nsignals = 0;\n      *nvcsw = 0;\n      *nivcsw = 0;\n    }\n  else\n    {\n      *usr_sec = ru.ru_utime.tv_sec;\n      *usr_usec = ru.ru_utime.tv_usec;\n\n      *sys_sec = ru.ru_stime.tv_sec;\n      *sys_usec = ru.ru_stime.tv_usec;\n\n      *maxrss = ru.ru_maxrss;\n      *ixrss = ru.ru_ixrss;\n      *idrss = ru.ru_idrss;\n      *isrss = ru.ru_isrss;\n      *minflt = ru.ru_minflt;\n      *majflt = ru.ru_majflt;\n      *nswap = ru.ru_nswap;\n      *inblock = ru.ru_inblock;\n      *oublock = ru.ru_oublock;\n      *msgsnd = ru.ru_msgsnd;\n      *msgrcv = ru.ru_msgrcv;\n      *nsignals = ru.ru_nsignals;\n      *nvcsw = ru.ru_nvcsw;\n      *nivcsw = ru.ru_nivcsw;\n    }\n\n  return status;\n}\n\ntime_t\noctave_mktime_wrapper (struct tm *tp)\n{\n  return mktime (tp);\n}\n\n// Avoid the risk of gnulib overriding anything above by placing this underneath the above fns\n#include \"gethrxtime.h\"\n\nlong long\noctave_gettime_ns_wrapper (void)\n{\n  return gethrxtime ();\n}\n"
  },
  {
    "path": "liboctave/wrappers/time-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_time_wrappers_h)\n#define octave_time_wrappers_h 1\n\n#if defined (__cplusplus)\n#  include <ctime>\n#else\n#  include <time.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API long long\noctave_gettime_ns_wrapper (void);\n\nextern OCTAVE_API int octave_gettimeofday_wrapper (time_t *sec, long *usec);\n\nextern OCTAVE_API int\noctave_cpu_time (time_t *usr_sec, time_t *sys_sec,\n                 long *usr_usec, long *sys_usec);\n\nextern OCTAVE_API int\noctave_getrusage_wrapper (time_t *usr_sec, time_t *sys_sec,\n                          long *usr_usec, long *sys_usec,\n                          long *maxrss, long *ixrss, long *idrss,\n                          long *isrss, long *minflt, long *majflt,\n                          long *nswap, long *inblock, long *oublock,\n                          long *msgsnd, long *msgrcv, long *nsignals,\n                          long *nvcsw, long *nivcsw);\n\nextern OCTAVE_API time_t\noctave_mktime_wrapper (struct tm *tp);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/uname-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// uname may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sys/utsname.h>\n\n#include \"uname-wrapper.h\"\n\n// Returns pointers to static storage.\n\nint\noctave_uname_wrapper (char **sysname, char **nodename,\n                      char **release, char **version, char **machine)\n{\n  static struct utsname unm;\n\n  int err = uname (&unm);\n\n  if (err < 0)\n    {\n      *sysname = 0;\n      *nodename = 0;\n      *release = 0;\n      *version = 0;\n      *machine = 0;\n    }\n  else\n    {\n      *sysname = unm.sysname;\n      *nodename = unm.nodename;\n      *release = unm.release;\n      *version = unm.version;\n      *machine = unm.machine;\n    }\n\n  return err;\n}\n"
  },
  {
    "path": "liboctave/wrappers/uname-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_uname_wrapper_h)\n#define octave_uname_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int\noctave_uname_wrapper (char **sysname, char **nodename,\n                      char **release, char **version, char **machine);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/unicase-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"unicase.h\"\n\n#include \"unicase-wrappers.h\"\n\nuint8_t *\noctave_u8_tolower_wrapper (const uint8_t *s, size_t n,\n                           const char *iso639_language,\n                           uint8_t *resultbuf, size_t *lengthp)\n{\n  return u8_tolower (s, n, iso639_language, NULL, resultbuf, lengthp);\n}\n\nuint8_t *\noctave_u8_toupper_wrapper (const uint8_t *s, size_t n,\n                           const char *iso639_language,\n                           uint8_t *resultbuf, size_t *lengthp)\n{\n  return u8_toupper (s, n, iso639_language, NULL, resultbuf, lengthp);\n}\n"
  },
  {
    "path": "liboctave/wrappers/unicase-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_unicase_wrappers_h)\n#define octave_unicase_wrappers_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API uint8_t *\noctave_u8_tolower_wrapper (const uint8_t *s, size_t n,\n                           const char *iso639_language,\n                           uint8_t *resultbuf, size_t *lengthp);\n\nextern OCTAVE_API uint8_t *\noctave_u8_toupper_wrapper (const uint8_t *s, size_t n,\n                           const char *iso639_language,\n                           uint8_t *resultbuf, size_t *lengthp);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/uniconv-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// The conversion functions are provided by gnulib.  We don't include\n// gnulib headers directly in Octave's C++ source files to avoid\n// problems that may be caused by the way that gnulib overrides standard\n// library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <wchar.h>\n\n#include \"uniconv.h\"\n\n#include \"uniconv-wrappers.h\"\n\nuint8_t *\noctave_u8_conv_from_encoding (const char *fromcode, const char *src,\n                              size_t srclen, size_t *lengthp)\n{\n  return u8_conv_from_encoding (fromcode, iconveh_question_mark,\n                                src, srclen, NULL, NULL, lengthp);\n}\n\nstatic char *\noctave_u8_conv_to_encoding_intern (const char *tocode,\n                                   enum iconv_ilseq_handler handler,\n                                   const uint8_t *src, size_t srclen,\n                                   size_t *offsets, size_t *lengthp)\n{\n  // FIXME: It looks like the input to u8_conv_to_encoding must be at least\n  //        four bytes and zero-terminated to work correctly.  Zero-pad input.\n  //        Should this be fixed in gnulib or iconv instead?\n  size_t minlen = 4;\n  size_t padlen = (srclen+1 > minlen ? srclen+1 : minlen);\n\n  // Take surrogate size into account for UTF-16 and UTF-32 output encodings.\n  // That is necessary to correctly remove the padding after the encoding\n  // conversion.\n  // FIXME: Are there other encodings that we should support for which the\n  //        \"encoding surrogate\" size is different from one byte?\n  size_t surrogate_size = 1;\n  if (strlen (tocode) > 5)\n    {\n      if ((tocode[0] == 'u' || tocode[0] == 'U')\n          && (tocode[1] == 't' || tocode[1] == 'T')\n          && (tocode[2] == 'f' || tocode[2] == 'F')\n          && tocode[3] == '-')\n        {\n          if (tocode[4] == '1' && tocode[5] == '6')\n            surrogate_size = 2;\n          else if (tocode[4] == '3' && tocode[5] == '2')\n            surrogate_size = 4;\n        }\n    }\n\n  uint8_t *u8_str = (uint8_t *) malloc (padlen);\n  memcpy (u8_str, src, srclen);\n  for (size_t i_pad = 0; i_pad < padlen-srclen; i_pad++)\n    u8_str[srclen+i_pad] = 0;\n  const uint8_t *cu8_str = u8_str;\n\n  // Convert from UTF-8 to output encoding\n  char *ret = u8_conv_to_encoding (tocode, handler, cu8_str, padlen,\n                                   offsets, NULL, lengthp);\n\n  free ((void *) u8_str);\n\n  // FIXME: This assumes that \"\\0\" is converted to one \"encoding surrogate\".\n  //        This might not be true for some exotic output encodings (like\n  //        UTF-7?).\n  *lengthp = (*lengthp <= (padlen-srclen) * surrogate_size\n              ? 0\n              : *lengthp - (padlen-srclen) * surrogate_size);\n\n  return ret;\n}\n\nchar *\noctave_u8_conv_to_encoding (const char *tocode, const uint8_t *src,\n                            size_t srclen, size_t *lengthp)\n{\n  return octave_u8_conv_to_encoding_intern (tocode, iconveh_question_mark,\n                                            src, srclen, NULL, lengthp);\n}\n\nchar *\noctave_u8_conv_to_encoding_strict (const char *tocode, const uint8_t *src,\n                                   size_t srclen, size_t *lengthp)\n{\n  return octave_u8_conv_to_encoding_intern (tocode, iconveh_error,\n                                            src, srclen, NULL, lengthp);\n}\n\nuint16_t *\noctave_u16_conv_from_encoding (const char *fromcode, const char *src,\n                               size_t srclen, size_t *lengthp)\n{\n  return u16_conv_from_encoding (fromcode, iconveh_question_mark,\n                                 src, srclen, NULL, NULL, lengthp);\n}\n\nuint16_t *\noctave_u16_conv_from_encoding_strict (const char *fromcode, const char *src,\n                                      size_t srclen, size_t *lengthp)\n{\n  return u16_conv_from_encoding (fromcode, iconveh_error,\n                                 src, srclen, NULL, NULL, lengthp);\n}\n\nchar *\noctave_u16_conv_to_encoding (const char *tocode, const uint16_t *src,\n                             size_t srclen, size_t *lengthp)\n{\n  return u16_conv_to_encoding (tocode, iconveh_question_mark,\n                               src, srclen, NULL, NULL, lengthp);\n}\n\nchar *\noctave_u16_conv_to_encoding_strict (const char *tocode, const uint16_t *src,\n                                    size_t srclen, size_t *lengthp)\n{\n  return u16_conv_to_encoding (tocode, iconveh_error,\n                               src, srclen, NULL, NULL, lengthp);\n}\n\nchar *\noctave_u32_conv_to_encoding_strict (const char *tocode, const uint32_t *src,\n                                    size_t srclen, size_t *lengthp)\n{\n  return u32_conv_to_encoding (tocode, iconveh_error,\n                               src, srclen, NULL, NULL, lengthp);\n}\n\nuint8_t *\noctave_u8_conv_from_encoding_offsets\n  (const char *fromcode, const char *src, size_t srclen,\n   size_t *offsets, size_t *lengthp)\n{\n  return u8_conv_from_encoding (fromcode, iconveh_question_mark,\n                                src, srclen, offsets, NULL, lengthp);\n}\n\nchar *\noctave_u8_conv_to_encoding_offsets\n  (const char *tocode, const uint8_t *src, size_t srclen,\n   size_t *offsets, size_t *lengthp)\n{\n  return octave_u8_conv_to_encoding_intern (tocode, iconveh_question_mark,\n                                            src, srclen, offsets, lengthp);\n}\n\nchar *\nu8_from_wchar (const wchar_t *wc)\n{\n  // Convert wide char array to multibyte UTF-8 char array\n  // The memory at the returned pointer must be freed after use.\n\n  size_t srclen = wcslen (wc) * sizeof (wchar_t);\n  const char *src = (const char *) wc;\n\n  size_t length = 0;\n  uint8_t *mbchar = u8_conv_from_encoding (\"wchar_t\", iconveh_question_mark,\n                                           src, srclen, NULL, NULL, &length);\n\n  // result might not be 0 terminated\n  char *retval = malloc (length + 1);\n  if (retval)\n    {\n      memcpy (retval, mbchar, length);\n      free ((void *) mbchar);\n      retval[length] = 0; // 0 terminate string\n    }\n  else\n    free ((void *) mbchar);\n\n  return retval;\n}\n\nwchar_t *\nu8_to_wchar (const char *u8)\n{\n  // Convert multibyte UTF-8 char array to wide char array\n  // The memory at the returned pointer must be freed after use.\n\n  size_t srclen = strlen (u8);\n  const uint8_t *src = (const uint8_t *) u8;\n\n  size_t length = 0;\n\n  char *wchar = u8_conv_to_encoding (\"wchar_t\", iconveh_question_mark,\n                                     src, srclen, NULL, NULL, &length);\n  // result might not be 0 terminated\n  wchar_t *retval = malloc (length + 1 * sizeof (wchar_t));\n  if (retval)\n    {\n      memcpy (retval, wchar, length);\n      free ((void *) wchar);\n      retval[length / sizeof (wchar_t)] = 0; // 0 terminate string\n    }\n\n  else\n    free ((void *) wchar);\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/wrappers/uniconv-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_uniconv_wrappers_h)\n#define octave_uniconv_wrappers_h 1\n\n#if defined (__cplusplus)\n#  include <cstddef>\n#  include <cstdint>\n#else\n#  include <stddef.h>\n#  include <stdint.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n// Since we omit arguments we don't care about in Octave, these aren't\n// named with the _wrapper suffix.\n\nextern OCTAVE_API uint8_t *\noctave_u8_conv_from_encoding (const char *fromcode, const char *src,\n                              size_t srclen, size_t *lengthp);\n\nextern OCTAVE_API char *\noctave_u8_conv_to_encoding (const char *tocode, const uint8_t *src,\n                            size_t srclen, size_t *lengthp);\n\nextern OCTAVE_API char *\noctave_u8_conv_to_encoding_strict (const char *tocode, const uint8_t *src,\n                                   size_t srclen, size_t *lengthp);\n\nextern OCTAVE_API uint16_t *\noctave_u16_conv_from_encoding (const char *fromcode, const char *src,\n                               size_t srclen, size_t *lengthp);\n\nextern OCTAVE_API uint16_t *\noctave_u16_conv_from_encoding_strict (const char *fromcode, const char *src,\n                                      size_t srclen, size_t *lengthp);\n\nextern OCTAVE_API char *\noctave_u16_conv_to_encoding (const char *tocode, const uint16_t *src,\n                             size_t srclen, size_t *lengthp);\n\nextern OCTAVE_API char *\noctave_u16_conv_to_encoding_strict (const char *tocode, const uint16_t *src,\n                                    size_t srclen, size_t *lengthp);\n\nextern OCTAVE_API char *\noctave_u32_conv_to_encoding_strict (const char *tocode, const uint32_t *src,\n                                    size_t srclen, size_t *lengthp);\n\nextern OCTAVE_API uint8_t *\noctave_u8_conv_from_encoding_offsets\n  (const char *fromcode, const char *src, size_t srclen,\n   size_t *offsets, size_t *lengthp);\n\nextern OCTAVE_API char *\noctave_u8_conv_to_encoding_offsets\n  (const char *tocode, const uint8_t *src, size_t srclen,\n   size_t *offsets, size_t *lengthp);\n\nextern OCTAVE_API char * u8_from_wchar (const wchar_t *wc);\n\nextern OCTAVE_API wchar_t * u8_to_wchar (const char *u8_char);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/unictype-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"unictype.h\"\n\n#include \"unictype-wrappers.h\"\n\nbool\noctave_uc_is_alnum_wrapper (ucs4_t uc)\n{\n  return uc_is_alnum (uc);\n}\n\nbool\noctave_uc_is_alpha_wrapper (ucs4_t uc)\n{\n  return uc_is_alpha (uc);\n}\n\nbool\noctave_uc_is_blank_wrapper (ucs4_t uc)\n{\n  return uc_is_blank (uc);\n}\n\nbool\noctave_uc_is_cntrl_wrapper (ucs4_t uc)\n{\n  return uc_is_cntrl (uc);\n}\n\nbool\noctave_uc_is_digit_wrapper (ucs4_t uc)\n{\n  return uc_is_digit (uc);\n}\n\nbool\noctave_uc_is_graph_wrapper (ucs4_t uc)\n{\n  return uc_is_graph (uc);\n}\n\nbool\noctave_uc_is_lower_wrapper (ucs4_t uc)\n{\n  return uc_is_lower (uc);\n}\n\nbool\noctave_uc_is_print_wrapper (ucs4_t uc)\n{\n  return uc_is_print (uc);\n}\n\nbool\noctave_uc_is_punct_wrapper (ucs4_t uc)\n{\n  return uc_is_punct (uc);\n}\n\nbool\noctave_uc_is_space_wrapper (ucs4_t uc)\n{\n  return uc_is_space (uc);\n}\n\nbool\noctave_uc_is_upper_wrapper (ucs4_t uc)\n{\n  return uc_is_upper (uc);\n}\n\nbool\noctave_uc_is_xdigit_wrapper (ucs4_t uc)\n{\n  return uc_is_xdigit (uc);\n}\n"
  },
  {
    "path": "liboctave/wrappers/unictype-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_unictype_wrappers_h)\n#define octave_unictype_wrappers_h 1\n\ntypedef uint32_t ucs4_t;\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API bool octave_uc_is_alnum_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_alpha_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_blank_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_cntrl_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_digit_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_graph_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_lower_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_print_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_punct_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_space_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_upper_wrapper (ucs4_t uc);\n\nextern OCTAVE_API bool octave_uc_is_xdigit_wrapper (ucs4_t uc);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/unistd-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdio.h>\n\n#include <sys/types.h>\n#include <unistd.h>\n\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n#  include <process.h>\n#endif\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <windows.h>\n#  include <wchar.h>\n#endif\n\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n#  include \"windows-spawn.h\"\n#endif\n\n#include \"uniconv-wrappers.h\"\n#include \"unistd-wrappers.h\"\n\nint\noctave_access_f_ok (void)\n{\n  return F_OK;\n}\n\nint\noctave_access_r_ok (void)\n{\n  return R_OK;\n}\n\nint\noctave_access_w_ok (void)\n{\n  return W_OK;\n}\n\nint\noctave_access_x_ok (void)\n{\n  return X_OK;\n}\n\nint\noctave_access_wrapper (const char *nm, int mode)\n{\n  return access (nm, mode);\n}\n\nint\noctave_chdir_wrapper (const char *nm)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  wchar_t *wnm = u8_to_wchar (nm);\n  int status = _wchdir (wnm);\n  free ((void *) wnm);\n  return status;\n#else\n  return chdir (nm);\n#endif\n}\n\nint\noctave_close_wrapper (int fd)\n{\n  return close (fd);\n}\n\nconst char *\noctave_ctermid_wrapper (void)\n{\n#if defined (HAVE_CTERMID)\n  return ctermid (0);\n#else\n  return \"/dev/tty\";\n#endif\n}\n\nint\noctave_dup_wrapper (int old_fd)\n{\n  return dup (old_fd);\n}\n\nint\noctave_dup2_wrapper (int fd1, int fd2)\n{\n  return dup2 (fd1, fd2);\n}\n\nint\noctave_execv_wrapper (const char *file, char *const *argv)\n{\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n\n  char *argv_mem_to_free;\n  const char **sanitized_argv = prepare_spawn ((const char * const *) argv,\n                                               &argv_mem_to_free);\n\n#  if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\n\n  // count number of arguments\n  size_t argc;\n  for (argc = 0; sanitized_argv[argc] != NULL; argc++)\n    ;\n\n  wchar_t *wfile = u8_to_wchar (file);\n  const wchar_t **wargv = malloc ((argc + 1) * sizeof (wchar_t *));\n\n  // convert multibyte UTF-8 strings to wide character strings\n  for (size_t i_arg = 0; i_arg < argc; i_arg++)\n    wargv[i_arg] = u8_to_wchar (sanitized_argv[i_arg]);\n\n  wargv[argc] = NULL;\n\n  free (sanitized_argv);\n  free (argv_mem_to_free);\n\n  int status = _wspawnv (P_WAIT, wfile, wargv+1);\n\n  // This happens when the spawned child process terminates.\n\n  free (wfile);\n  const wchar_t **wp = wargv;\n  // Casting away the const in the loop is ok here.\n  while (*wp)\n    free ((wchar_t *) *wp++);\n  free (wargv);\n\n#  else\n\n  int status = spawnv (P_OVERLAY, file, sanitized_argv);\n\n  // This only happens if spawnv fails.\n\n  free (sanitized_argv);\n  free (argv_mem_to_free);\n\n#  endif\n\n  return status;\n\n#else\n\n  return execv (file, argv);\n\n#endif\n}\n\nint\noctave_execvp_wrapper (const char *file, char *const *argv)\n{\n  return execvp (file, argv);\n}\n\npid_t\noctave_fork_wrapper (void)\n{\n#if defined (HAVE_FORK)\n  return fork ();\n#else\n  return -1;\n#endif\n}\n\nint\noctave_ftruncate_wrapper (int fd, off_t sz)\n{\n  return ftruncate (fd, sz);\n}\n\nchar *\noctave_getcwd_wrapper (char *nm, size_t len)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  wchar_t *tmp = _wgetcwd (NULL, 0);\n  char *retval = NULL;\n\n  if (! tmp)\n    return retval;\n\n  retval = u8_from_wchar (tmp);\n  if (! nm)\n    return retval;\n  else\n    {\n      if (strlen (retval) > len)\n        return NULL;\n\n      memcpy (nm, retval, len);\n      free (retval);\n      return nm;\n    }\n#else\n  return getcwd (nm, len);\n#endif\n}\n\ngid_t\noctave_getegid_wrapper (void)\n{\n#if defined (HAVE_GETEGID)\n  return getegid ();\n#else\n  return -1;\n#endif\n}\n\nuid_t\noctave_geteuid_wrapper (void)\n{\n#if defined (HAVE_GETEUID)\n  return geteuid ();\n#else\n  return -1;\n#endif\n}\n\ngid_t\noctave_getgid_wrapper (void)\n{\n#if defined (HAVE_GETGID)\n  return getgid ();\n#else\n  return -1;\n#endif\n}\n\nint\noctave_gethostname_wrapper (char *nm, size_t len)\n{\n  return gethostname (nm, len);\n}\n\npid_t\noctave_getpgrp_wrapper (void)\n{\n#if defined (HAVE_GETPGRP)\n  return getpgrp ();\n#else\n  return -1;\n#endif\n}\n\npid_t\noctave_getpid_wrapper (void)\n{\n#if defined (HAVE_GETPID)\n  return getpid ();\n#else\n  return -1;\n#endif\n}\n\npid_t\noctave_getppid_wrapper (void)\n{\n#if defined (HAVE_GETPPID)\n  return getppid ();\n#else\n  return -1;\n#endif\n}\n\nuid_t\noctave_getuid_wrapper (void)\n{\n#if defined (HAVE_GETUID)\n  return getuid ();\n#else\n  return -1;\n#endif\n}\n\nint\noctave_isatty_wrapper (int fd)\n{\n  return isatty (fd);\n}\n\nint\noctave_link_wrapper (const char *nm1, const char *nm2)\n{\n  return link (nm1, nm2);\n}\n\nint\noctave_pipe_wrapper (int *fd)\n{\n  return pipe (fd);\n}\n\nint\noctave_rmdir_wrapper (const char *nm)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  wchar_t *wnm = u8_to_wchar (nm);\n  int status = _wrmdir (wnm);\n  free ((void *) wnm);\n  return status;\n#else\n  return rmdir (nm);\n#endif\n}\n\npid_t\noctave_setsid_wrapper (void)\n{\n#if defined (HAVE_SETSID)\n  return setsid ();\n#else\n  return -1;\n#endif\n}\n\nint\noctave_stdin_fileno (void)\n{\n  return STDIN_FILENO;\n}\n\nint\noctave_stdout_fileno (void)\n{\n  return STDOUT_FILENO;\n}\n\nint\noctave_stderr_fileno (void)\n{\n  return STDERR_FILENO;\n}\n\nint\noctave_symlink_wrapper (const char *nm1, const char *nm2)\n{\n  return symlink (nm1, nm2);\n}\n\nint\noctave_unlink_wrapper (const char *nm)\n{\n#if defined (OCTAVE_USE_WINDOWS_API)\n  wchar_t *wnm = u8_to_wchar (nm);\n\n  // _wunlink fails on files with the read-only flag set.  Try to un-set it.\n  DWORD file_attributes = GetFileAttributesW (wnm);\n  if (file_attributes != INVALID_FILE_ATTRIBUTES\n      && file_attributes & FILE_ATTRIBUTE_READONLY)\n    SetFileAttributesW (wnm, file_attributes & ~FILE_ATTRIBUTE_READONLY);\n\n  int status = _wunlink (wnm);\n  free ((void *) wnm);\n\n  return status;\n#else\n  return unlink (nm);\n#endif\n}\n\npid_t\noctave_vfork_wrapper (void)\n{\n#if defined (HAVE_VFORK)\n  return vfork ();\n#else\n  return -1;\n#endif\n}\n\nbool\noctave_have_fork (void)\n{\n#if defined (HAVE_FORK)\n  return true;\n#else\n  return false;\n#endif\n}\n\nbool\noctave_have_vfork (void)\n{\n#if defined (HAVE_VFORK)\n  return true;\n#else\n  return false;\n#endif\n}\n"
  },
  {
    "path": "liboctave/wrappers/unistd-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_unistd_wrappers_h)\n#define octave_unistd_wrappers_h 1\n\n#if ! defined (__cplusplus)\n#  include <stdbool.h>\n#endif\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int octave_access_f_ok (void);\n\nextern OCTAVE_API int octave_access_r_ok (void);\n\nextern OCTAVE_API int octave_access_w_ok (void);\n\nextern OCTAVE_API int octave_access_x_ok (void);\n\nextern OCTAVE_API int octave_access_wrapper (const char *nm, int mode);\n\nextern OCTAVE_API int octave_chdir_wrapper (const char *nm);\n\nextern OCTAVE_API int octave_close_wrapper (int fd);\n\nextern OCTAVE_API const char * octave_ctermid_wrapper (void);\n\nextern OCTAVE_API int octave_dup_wrapper (int old_fd);\n\nextern OCTAVE_API int octave_dup2_wrapper (int fd1, int fd2);\n\nextern OCTAVE_API int octave_execv_wrapper (const char *file, char *const *argv);\n\nextern OCTAVE_API int octave_execvp_wrapper (const char *file, char *const *argv);\n\nextern OCTAVE_API pid_t octave_fork_wrapper (void);\n\nextern OCTAVE_API int octave_ftruncate_wrapper (int fd, off_t sz);\n\nextern OCTAVE_API char * octave_getcwd_wrapper (char *nm, size_t len);\n\nextern OCTAVE_API gid_t octave_getegid_wrapper (void);\n\nextern OCTAVE_API uid_t octave_geteuid_wrapper (void);\n\nextern OCTAVE_API gid_t octave_getgid_wrapper (void);\n\nextern OCTAVE_API int octave_gethostname_wrapper (char *nm, size_t len);\n\nextern OCTAVE_API pid_t octave_getpgrp_wrapper (void);\n\nextern OCTAVE_API pid_t octave_getpid_wrapper (void);\n\nextern OCTAVE_API pid_t octave_getppid_wrapper (void);\n\nextern OCTAVE_API uid_t octave_getuid_wrapper (void);\n\nextern OCTAVE_API int octave_isatty_wrapper (int fd);\n\nextern OCTAVE_API int octave_link_wrapper (const char *nm1, const char *nm2);\n\nextern OCTAVE_API int octave_pipe_wrapper (int *fd);\n\nextern OCTAVE_API int octave_rmdir_wrapper (const char *nm);\n\nextern OCTAVE_API pid_t octave_setsid_wrapper (void);\n\nextern OCTAVE_API int octave_stdin_fileno (void);\n\nextern OCTAVE_API int octave_stdout_fileno (void);\n\nextern OCTAVE_API int octave_stderr_fileno (void);\n\nextern OCTAVE_API int octave_symlink_wrapper (const char *nm1, const char *nm2);\n\nextern OCTAVE_API int octave_unlink_wrapper (const char *nm);\n\nextern OCTAVE_API pid_t octave_vfork_wrapper (void);\n\nextern OCTAVE_API bool octave_have_fork (void);\n\nextern OCTAVE_API bool octave_have_vfork (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/unistr-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"unistr.h\"\n\n#include \"unistr-wrappers.h\"\n\nconst uint8_t *\noctave_u8_check_wrapper (const uint8_t *src, size_t n)\n{\n// Silence invalid warning in gnulib\n#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wcast-qual\"\n#endif\n  return u8_check (src, n);\n#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC\n#  pragma GCC diagnostic pop\n#endif\n}\n\nsize_t\noctave_u8_mbsnlen_wrapper (const uint8_t *src, size_t n)\n{\n  return u8_mbsnlen (src, n);\n}\n\nint\noctave_u8_strmblen_wrapper (const uint8_t *src)\n{\n  return u8_strmblen (src);\n}\n\nint\noctave_u8_strmbtouc_wrapper (uint32_t *puc, const uint8_t *src)\n{\n  return u8_strmbtouc (puc, src);\n}\n\nuint8_t *\noctave_u16_to_u8_wrapper (const uint16_t *src, size_t src_len,\n                          uint8_t *result_buf, size_t *lengthp)\n{\n  return u16_to_u8 (src, src_len, result_buf, lengthp);\n}\n\nuint8_t *\noctave_u32_to_u8_wrapper (const uint32_t *src, size_t src_len,\n                          uint8_t *result_buf, size_t *lengthp)\n{\n  return u32_to_u8 (src, src_len, result_buf, lengthp);\n}\n\nuint16_t *\noctave_u8_to_u16_wrapper (const uint8_t *src, size_t src_len,\n                          uint16_t *result_buf, size_t *lengthp)\n{\n  return u8_to_u16 (src, src_len, result_buf, lengthp);\n}\n\nuint32_t *\noctave_u8_to_u32_wrapper (const uint8_t *src, size_t src_len,\n                          uint32_t *result_buf, size_t *lengthp)\n{\n  return u8_to_u32 (src, src_len, result_buf, lengthp);\n}\n"
  },
  {
    "path": "liboctave/wrappers/unistr-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2018-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_unistr_wrappers_h)\n#define octave_unistr_wrappers_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API const uint8_t *\noctave_u8_check_wrapper (const uint8_t *src, size_t n);\n\nextern OCTAVE_API int octave_u8_strmblen_wrapper (const uint8_t *src);\n\nextern OCTAVE_API size_t\noctave_u8_mbsnlen_wrapper (const uint8_t *src, size_t n);\n\nextern OCTAVE_API int\noctave_u8_strmbtouc_wrapper (uint32_t *puc, const uint8_t *src);\n\nextern OCTAVE_API uint8_t *\noctave_u16_to_u8_wrapper (const uint16_t *src, size_t src_len,\n                          uint8_t *result_buf, size_t *lengthp);\n\nextern OCTAVE_API uint8_t *\noctave_u32_to_u8_wrapper (const uint32_t *src, size_t src_len,\n                          uint8_t *result_buf, size_t *lengthp);\n\nextern OCTAVE_API uint16_t *\noctave_u8_to_u16_wrapper (const uint8_t *src, size_t src_len,\n                          uint16_t *result_buf, size_t *lengthp);\n\nextern OCTAVE_API uint32_t *\noctave_u8_to_u32_wrapper (const uint8_t *src, size_t src_len,\n                          uint32_t *result_buf, size_t *lengthp);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/unsetenv-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// unsetenv may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdlib.h>\n\n#include \"unsetenv-wrapper.h\"\n\nint\noctave_unsetenv_wrapper (const char *name)\n{\n  return unsetenv (name);\n}\n"
  },
  {
    "path": "liboctave/wrappers/unsetenv-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_unsetenv_wrapper_h)\n#define octave_unsetenv_wrapper_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int octave_unsetenv_wrapper (const char *name);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/vasprintf-wrapper.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// vasprintf may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdio.h>\n\n#include \"vasprintf-wrapper.h\"\n\nint\noctave_vasprintf_wrapper (char **buf, const char *fmt, va_list args)\n{\n  return vasprintf (buf, fmt, args);\n}\n"
  },
  {
    "path": "liboctave/wrappers/vasprintf-wrapper.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_vasprintf_wrapper_h)\n#define octave_vasprintf_wrapper_h 1\n\n#if defined (__cplusplus)\n#  include <cstdarg>\n#else\n#  include <stdarg.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int\noctave_vasprintf_wrapper (char **buf, const char *fmt, va_list args);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/wait-for-input.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// select may be provided by gnulib.  We don't include gnulib headers\n// directly in Octave's C++ source files to avoid problems that may be\n// caused by the way that gnulib overrides standard library functions.\n\n// We don't need select directly, we just need to use it to wait for\n// input on an open file descriptor.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sys/select.h>\n\n#include \"wait-for-input.h\"\n\nint\noctave_wait_for_input (int fid)\n{\n  int retval = -1;\n\n#if defined (HAVE_SELECT)\n  if (fid >= 0)\n    {\n      fd_set set;\n\n      FD_ZERO (&set);\n      FD_SET (fid, &set);\n\n      retval = select (FD_SETSIZE, &set, 0, 0, 0);\n    }\n#else\n  octave_unused_parameter (fid);\n\n  retval = 1;\n#endif\n\n  return retval;\n}\n"
  },
  {
    "path": "liboctave/wrappers/wait-for-input.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_wait_for_input_h)\n#define octave_wait_for_input_h 1\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API int octave_wait_for_input (int fid);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/wait-wrappers.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions may be provided by gnulib.  We don't include gnulib\n// headers directly in Octave's C++ source files to avoid problems that\n// may be caused by the way that gnulib overrides standard library\n// functions.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <sys/types.h>\n#include <sys/wait.h>\n\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n#  include <windows.h>\n#endif\n\n#include \"wait-wrappers.h\"\n\n#if ! defined (WCONTINUE)\n#  define WCONTINUE 0\n#endif\n\n#if ! defined (WNOHANG)\n#  define WNOHANG 0\n#endif\n\n#if ! defined (WUNTRACED)\n#  define WUNTRACED 0\n#endif\n\n#if ! defined (WIFCONTINUED)\n#  define WIFCONTINUED(x) false\n#endif\n\npid_t\noctave_waitpid_wrapper (pid_t pid, int *statusp, int options)\n{\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n  // gnulib's waitpid replacement currently uses _cwait, which\n  // apparently only works with console applications.\n  // Implement our own wrapper using win32 API functions.\n\n  octave_unused_parameter (options);\n\n  pid_t retval = -1;\n  DWORD status = 0;\n\n  HANDLE hProcess = OpenProcess (PROCESS_QUERY_INFORMATION | SYNCHRONIZE,\n                                 false, pid);\n\n  if (! hProcess)\n    return retval;\n\n  if (WaitForSingleObject (hProcess, INFINITE) != WAIT_OBJECT_0)\n    {\n      CloseHandle (hProcess);\n      return retval;\n    }\n\n  if (! GetExitCodeProcess (hProcess, &status))\n    {\n      CloseHandle (hProcess);\n      return retval;\n    }\n\n  CloseHandle (hProcess);\n\n  if (statusp)\n    *statusp = status;\n\n  retval = pid;\n\n  return retval;\n\n#else\n  return waitpid (pid, statusp, options);\n#endif\n}\n\nint\noctave_wcontinue_wrapper (void)\n{\n  return WCONTINUE;\n}\n\nint\noctave_wnohang_wrapper (void)\n{\n  return WNOHANG;\n}\n\nint\noctave_wuntraced_wrapper (void)\n{\n  return WUNTRACED;\n}\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n// Disable the unused parameter warning for the following wrapper functions.\n// The <sys/wait.h> header provided by gnulib may define some of the W*\n// macros to expand to a constant and ignore the parameter.\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#endif\n\nint\noctave_wcoredump_wrapper (int status)\n{\n  return WCOREDUMP (status);\n}\n\nint\noctave_wexitstatus_wrapper (int status)\n{\n  return WEXITSTATUS (status);\n}\n\nbool\noctave_wifcontinued_wrapper (int status)\n{\n  return WIFCONTINUED (status);\n}\n\nbool\noctave_wifexited_wrapper (int status)\n{\n  return WIFEXITED (status);\n}\n\nbool\noctave_wifsignaled_wrapper (int status)\n{\n  return WIFSIGNALED (status);\n}\n\nbool\noctave_wifstopped_wrapper (int status)\n{\n  return WIFSTOPPED (status);\n}\n\nint\noctave_wstopsig_wrapper (int status)\n{\n  return WSTOPSIG (status);\n}\n\nint\noctave_wtermsig_wrapper (int status)\n{\n  return WTERMSIG (status);\n}\n\n#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)\n// Restore prevailing warning state for remainder of the file.\n#  pragma GCC diagnostic pop\n#endif\n"
  },
  {
    "path": "liboctave/wrappers/wait-wrappers.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_wait_wrappers_h)\n#define octave_wait_wrappers_h 1\n\n#if ! defined (__cplusplus)\n#  include <stdbool.h>\n#endif\n\n#include <sys/types.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nextern OCTAVE_API pid_t\noctave_waitpid_wrapper (pid_t pid, int *statusp, int options);\n\nextern OCTAVE_API int octave_wcontinue_wrapper (void);\n\nextern OCTAVE_API int octave_wcoredump_wrapper (int status);\n\nextern OCTAVE_API bool octave_wifcontinued_wrapper (int status);\n\nextern OCTAVE_API bool octave_wifexited_wrapper (int status);\n\nextern OCTAVE_API bool octave_wifsignaled_wrapper (int status);\n\nextern OCTAVE_API bool octave_wifstopped_wrapper (int status);\n\nextern OCTAVE_API int octave_wexitstatus_wrapper (int status);\n\nextern OCTAVE_API int octave_wnohang_wrapper (void);\n\nextern OCTAVE_API int octave_wstopsig_wrapper (int status);\n\nextern OCTAVE_API int octave_wtermsig_wrapper (int status);\n\nextern OCTAVE_API int octave_wuntraced_wrapper (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "m4/acinclude.m4",
    "content": "dnl acinclude.m4 -- extra macros for configuring Octave\ndnl\ndnl --------------------------------------------------------------------\ndnl\ndnl Copyright (C) 1995-2026 The Octave Project Developers\ndnl\ndnl See the file COPYRIGHT.md in the top-level directory of this\ndnl distribution or <https://octave.org/copyright/>.\ndnl\ndnl This file is part of Octave.\ndnl\ndnl Octave is free software: you can redistribute it and/or modify it\ndnl under the terms of the GNU General Public License as published by\ndnl the Free Software Foundation, either version 3 of the License, or\ndnl (at your option) any later version.\ndnl\ndnl Octave is distributed in the hope that it will be useful, but\ndnl WITHOUT ANY WARRANTY; without even the implied warranty of\ndnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\ndnl GNU General Public License for more details.\ndnl\ndnl You should have received a copy of the GNU General Public License\ndnl along with Octave; see the file COPYING.  If not, see\ndnl <https://www.gnu.org/licenses/>.\ndnl\ndnl --------------------------------------------------------------------\ndnl\ndnl Alphabetical list of macros in the OCTAVE_ namespace\ndnl\ndnl\ndnl Figure out the hardware-vendor-os info.\ndnl\nAC_DEFUN([OCTAVE_CANONICAL_HOST], [\n  AC_CANONICAL_HOST\n  if test -z \"$host\"; then\n    host=unknown-unknown-unknown\n    AC_MSG_WARN([configuring Octave for unknown system type])\n  fi\n  canonical_host_type=$host\n  AC_SUBST(canonical_host_type)\n  if test -z \"$host_cpu\"; then\n    host_cpu=unknown\n  fi\n  if test -z \"$host_vendor\"; then\n    host_vendor=unknown\n  fi\n  if test -z \"$host_os\"; then\n    host_os=unknown\n  fi\n])\ndnl\ndnl Check if the Carbon Framework defines CGDisplayBitsPerPixel.\ndnl\nAC_DEFUN([OCTAVE_CARBON_CGDISPLAYBITSPERPIXEL], [\n  AC_CACHE_CHECK([whether CGDisplayBitsPerPixel is defined in the Carbon Framework],\n    [octave_cv_func_carbon_cgdisplaybitsperpixel],\n    [AC_LANG_PUSH(C++)\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <Carbon/Carbon.h>\n        ]], [[\n        CGDirectDisplayID display = CGMainDisplayID ();\n        size_t depth = CGDisplayBitsPerPixel (display);\n      ]])],\n      octave_cv_func_carbon_cgdisplaybitsperpixel=yes,\n      octave_cv_func_carbon_cgdisplaybitsperpixel=no)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_carbon_cgdisplaybitsperpixel = yes; then\n    AC_DEFINE(HAVE_CARBON_CGDISPLAYBITSPERPIXEL, 1,\n      [Define to 1 if Carbon Framework has CGDisplayBitsPerPixel.])\n  fi\n])\ndnl\ndnl Check if C compiler handles FLAG command line option.  If two\ndnl arguments are specified, execute the second arg as shell commands.\ndnl Otherwise, add FLAG to CFLAGS if the compiler accepts the flag.\ndnl\nAC_DEFUN([OCTAVE_CC_FLAG], [\n  ac_safe=`echo \"$1\" | $SED 'y% ./+-:=%___p___%'`\n  AC_MSG_CHECKING([whether ${CC-cc} accepts $1])\n  AC_CACHE_VAL([octave_cv_cc_flag_$ac_safe],\n    [AC_LANG_PUSH(C)\n    ac_octave_save_CFLAGS=\"$CFLAGS\"\n    CFLAGS=\"$CFLAGS $1\"\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],\n      [eval \"octave_cv_cc_flag_$ac_safe=yes\"],\n      [eval \"octave_cv_cc_flag_$ac_safe=no\"])\n    CFLAGS=\"$ac_octave_save_CFLAGS\"\n    AC_LANG_POP(C)\n  ])\n  if eval \"test \\\"`echo '$octave_cv_cc_flag_'$ac_safe`\\\" = yes\"; then\n    AC_MSG_RESULT([yes])\n    ifelse([$2], ,\n      [CFLAGS=\"$CFLAGS $1\"\n      AC_MSG_RESULT([adding $1 to CFLAGS])], [$2])\n  else\n    AC_MSG_RESULT([no])\n    ifelse([$3], , , [$3])\n  fi\n])\ndnl\ndnl Check if pthread stack size accounts for thread-local storage.\ndnl\ndnl This program should succeed if the pthread library allocates memory\ndnl for thread-local (__thread) variables independently of the\ndnl requested thread stack size.\ndnl\ndnl It will fail if (as in the current version of glibc) the storage\ndnl for thread-local variables is subtracted from the memory allocated\ndnl for the thread stack.  (This can cause problems for Java and for\ndnl other libraries.)\ndnl\ndnl This bug is tracked in glibc at:\ndnl https://sourceware.org/bugzilla/show_bug.cgi?id=11787\ndnl\nAC_DEFUN([OCTAVE_CHECK_BROKEN_PTHREAD_STACKSIZE], [\n  AC_CACHE_CHECK([whether pthread stack size does not account for thread-local storage],\n    [octave_cv_broken_pthread_stacksize],\n    [AC_LANG_PUSH(C)\n    AC_RUN_IFELSE([AC_LANG_PROGRAM([[\n#include <stdio.h>\n#include <string.h>\n#include <pthread.h>\n\nstatic char __thread data[100 * 1024];\n\nstatic void * threadfunc(void *arg)\n{\n    return data;\n}\n      ]], [[\n  pthread_attr_t attr;\n  pthread_t thread;\n  int errnum;\n\n  pthread_attr_init (&attr);\n  errnum = pthread_attr_setstacksize (&attr, 64 * 1024);\n  if (errnum != 0)\n  {\n    fprintf (stderr, \"pthread_attr_setstacksize: %s\\n\", strerror(errnum));\n    return 1;\n  }\n  errnum = pthread_create (&thread, &attr, &threadfunc, NULL);\n  if (errnum != 0)\n  {\n    fprintf (stderr, \"pthread_create: %s\\n\", strerror(errnum));\n    return 1;\n  }\n  errnum = pthread_join (thread, NULL);\n  if (errnum != 0)\n  {\n    fprintf (stderr, \"pthread_join: %s\\n\", strerror(errnum));\n    return 1;\n  }\n\n  pthread_attr_destroy (&attr);\n  return 0;\n    ]])],\n    octave_cv_broken_pthread_stacksize=no,\n    octave_cv_broken_pthread_stacksize=yes,\n    octave_cv_broken_pthread_stacksize=no)\n    AC_LANG_POP(C)\n  ])\n  if test $octave_cv_broken_pthread_stacksize = yes; then\n    AC_DEFINE(HAVE_BROKEN_PTHREAD_STACKSIZE, 1,\n      [Define to 1 if pthread stack size does not account for thread-local storage.])\n  fi\n])\ndnl\ndnl Check for BSD or Apple libc library.\ndnl\nAC_DEFUN([OCTAVE_BSD_LIBC], [\n  AC_CACHE_CHECK([whether using C library from BSD or Apple],\n    [octave_cv_bsd_libc], [\n    AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <sys/sysctl.h>]])], [\n      AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <linux/sysctl.h>]])],\n        octave_cv_bsd_libc=no,\n        octave_cv_bsd_libc=yes)\n      ],\n      octave_cv_bsd_libc=no)\n  ])\n  if test $octave_cv_bsd_libc = yes; then\n    AC_DEFINE(HAVE_BSD_LIBC, 1,\n      [Define to 1 if BSD or Apple libc is used])\n  fi\n])\ndnl\ndnl Check for LLVM or Apple libc++ library.\ndnl\nAC_DEFUN([OCTAVE_LLVM_LIBCXX], [\n  AC_CACHE_CHECK([whether using STL from LLVM or Apple],\n    [octave_cv_llvm_libcxx],\n    [AC_LANG_PUSH(C++)\n    AC_RUN_IFELSE([AC_LANG_PROGRAM([[\n        // Include any header from the STL\n        #include <iostream>\n        ]], [[\n        #if defined (_LIBCPP_VERSION)\n          return (0);\n        #else\n          return (1);\n        #endif\n      ]])],\n      octave_cv_llvm_libcxx=yes,\n      octave_cv_llvm_libcxx=no,\n      octave_cv_llvm_libcxx=no)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_llvm_libcxx = yes; then\n    AC_DEFINE(HAVE_LLVM_LIBCXX, 1,\n      [Define to 1 if linking to LLVM or Apple libc++.])\n  fi\n])\ndnl\ndnl Check whether std::pmr::polymorphic_allocator is available.\ndnl\nAC_DEFUN([OCTAVE_CHECK_STD_PMR_POLYMORPHIC_ALLOCATOR], [\n  AC_CACHE_CHECK([whether std::pmr::polymorphic_allocator is available],\n    [octave_cv_std_pmr_polymorphic_allocator],\n    [AC_LANG_PUSH(C++)\n    AC_RUN_IFELSE([AC_LANG_PROGRAM([[\n      #include <cstdlib>\n      #include <memory_resource>\n      #include <vector>\n      class mx_memory_resource : public std::pmr::memory_resource\n      {\n      private:\n        void * do_allocate (std::size_t bytes, size_t /*alignment*/)\n        {\n          void *ptr = std::malloc (bytes);\n          if (! ptr)\n            throw std::bad_alloc ();\n            return ptr;\n        }\n        void do_deallocate (void* ptr, std::size_t /*bytes*/,\n                            std::size_t /*alignment*/)\n        {\n          std::free (ptr);\n        }\n        bool do_is_equal (const std::pmr::memory_resource& other) const noexcept\n        {\n          return this == dynamic_cast<const mx_memory_resource *> (&other);\n          return true;\n        }\n      };\n      mx_memory_resource the_mx_memory_resource;\n    ]], [[\n      std::pmr::vector<int> my_int_vec { &the_mx_memory_resource };\n    ]])],\n    octave_cv_std_pmr_polymorphic_allocator=yes,\n    octave_cv_std_pmr_polymorphic_allocator=no,\n    [## On macOS, we need to run an executable to check if polymorphic\n    ## allocators are working.\n    ## When cross-compiling to that target, the following test might succeed\n    ## even if polymorphic allocators are not actually implemented. In that\n    ## case, users would need to manually configure with\n    ## `--disable-std-pmr-polymorphic-allocator`.\n    ## When cross-compiling to any other target, the following test should be\n    ## giving accurate results.\n\n    ## FIXME: Is there a way to not repeat the same code from above?\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n      #include <cstdlib>\n      #include <memory_resource>\n      #include <vector>\n      class mx_memory_resource : public std::pmr::memory_resource\n      {\n      private:\n        void * do_allocate (std::size_t bytes, size_t /*alignment*/)\n        {\n          void *ptr = std::malloc (bytes);\n          if (! ptr)\n            throw std::bad_alloc ();\n            return ptr;\n        }\n        void do_deallocate (void* ptr, std::size_t /*bytes*/,\n                            std::size_t /*alignment*/)\n        {\n          std::free (ptr);\n        }\n        bool do_is_equal (const std::pmr::memory_resource& other) const noexcept\n        {\n          return this == dynamic_cast<const mx_memory_resource *> (&other);\n          return true;\n        }\n      };\n      mx_memory_resource the_mx_memory_resource;\n    ]], [[\n      std::pmr::vector<int> my_int_vec { &the_mx_memory_resource };\n    ]])],\n    octave_cv_std_pmr_polymorphic_allocator=yes,\n    octave_cv_std_pmr_polymorphic_allocator=no)])\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_std_pmr_polymorphic_allocator = yes; then\n    AC_DEFINE(OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR, 1,\n      [Define to 1 if std::pmr::polymorphic_allocator is available.])\n    HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR=\"yes\"\n  else\n    HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR=\"no\"\n  fi\n])\ndnl\ndnl Check whether CXSparse is version 2.2 or later\ndnl FIXME: This test uses a version number.  It potentially could\ndnl        be re-written to actually call a function, but is it worth it?\ndnl\nAC_DEFUN([OCTAVE_CHECK_CXSPARSE_VERSION_OK], [\n  AC_CACHE_CHECK([whether CXSparse is version 2.2 or later],\n    [octave_cv_cxsparse_version_ok],\n    [ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    CPPFLAGS=\"$CXSPARSE_CPPFLAGS $CPPFLAGS\"\n    AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[\n        #if defined (HAVE_SUITESPARSE_CS_H)\n        #include <suitesparse/cs.h>\n        #elif defined (HAVE_CXSPARSE_CS_H)\n        #include <cxsparse/cs.h>\n        #elif defined (HAVE_CS_H)\n        #include <cs.h>\n        #endif\n        ]], [[\n        #if (defined (HAVE_CXSPARSE) \\\n             && (! defined (CS_VER) \\\n                 || CS_VER < 2 \\\n                 || (CS_VER == 2 && CS_SUBVER < 2)))\n        #error \"Octave requires CXSparse version 2.2 or later\"\n        #endif\n        ]])],\n      octave_cv_cxsparse_version_ok=yes,\n      octave_cv_cxsparse_version_ok=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n  ])\n  if test $octave_cv_cxsparse_version_ok = yes; then\n    AC_DEFINE(HAVE_CXSPARSE_VERSION_OK, 1,\n      [Define to 1 if CXSparse is version 2.2 or later.])\n  fi\n])\ndnl\ndnl Check whether the FFTW library supports multi-threading.  This macro\ndnl should be called once per FFTW precision passing in the library\ndnl variant (e.g., \"fftw3\") and a function in the thread support API\ndnl (e.g., \"fftw_plan_with_nthreads\").  Depending on how FFTW was built,\ndnl the thread functions could be compiled into the main FFTW library or\ndnl could be a separate add-on library that is passed to the linker\ndnl ahead of the main FFTW library.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FFTW_THREADS], [\n  ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n  ac_octave_save_LDFLAGS=\"$LDFLAGS\"\n  ac_octave_save_LIBS=\"$LIBS\"\n  CPPFLAGS=\"$m4_toupper([$1])_CPPFLAGS $CPPFLAGS\"\n  LDFLAGS=\"$m4_toupper([$1])_LDFLAGS $LDFLAGS\"\n  LIBS=\"$m4_toupper([$1])_LIBS $LIBS\"\n  AC_CACHE_CHECK([for $1 multi-threading support],\n    [octave_cv_[$1]_threads_lib],\n    [AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n      #include <fftw3.h>\n      ]], [[\n      $2 (2);\n      ]])],\n      [octave_cv_[$1]_threads_lib=yes],\n      [LIBS=\"-l[$1]_threads $LIBS\"\n      AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n        #include <fftw3.h>\n        ]], [[\n        $2 (2);\n        ]])],\n        [octave_cv_[$1]_threads_lib=\"-l[$1]_threads\"],\n        [octave_cv_[$1]_threads_lib=no])\n    ])\n  ])\n  case $octave_cv_[$1]_threads_lib in\n    -l*)\n      m4_toupper([$1])_LIBS=\"$octave_cv_[$1]_threads_lib $m4_toupper([$1])_LIBS\"\n      ;;\n    no)\n      AC_MSG_WARN([No $1 multi-threading support found.])\n      AC_MSG_WARN([The single-threaded library will be used instead.])\n      ;;\n  esac\n  if test $octave_cv_[$1]_threads_lib != no; then\n    AC_DEFINE([HAVE_]m4_toupper([$1])[_THREADS], 1,\n      [Define to 1 if ]m4_toupper([$1])[ has multi-threading support.])\n  fi\n  CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n  LDFLAGS=\"$ac_octave_save_LDFLAGS\"\n  LIBS=\"$ac_octave_save_LIBS\"\n])\ndnl\ndnl OCTAVE_CHECK_FORTRAN_SYMBOL_AND_CALLING_CONVENTIONS\ndnl\ndnl Set variables related to Fortran symbol names (append underscore,\ndnl use uppercase names, etc.) and calling convention (mostly used for\ndnl determining how character strings are passed).\ndnl\nAC_DEFUN([OCTAVE_CHECK_FORTRAN_SYMBOL_AND_CALLING_CONVENTIONS], [\n  F77_TOLOWER=yes\n  F77_APPEND_UNDERSCORE=yes\n  F77_APPEND_EXTRA_UNDERSCORE=yes\n\n  case $ac_cv_f77_mangling in\n    \"upper case\") F77_TOLOWER=no ;;\n  esac\n  case $ac_cv_f77_mangling in\n    \"no underscore\") F77_APPEND_UNDERSCORE=no ;;\n  esac\n  case $ac_cv_f77_mangling in\n    \"no extra underscore\") F77_APPEND_EXTRA_UNDERSCORE=no ;;\n  esac\n\n  case $canonical_host_type in\n    i[[3456789]]86-*-*)\n      if test $ac_cv_f77_compiler_gnu = yes; then\n        OCTAVE_F77_FLAG([-mieee-fp])\n      fi\n    ;;\n    alpha*-*-*)\n      if test $ac_cv_f77_compiler_gnu = yes; then\n        OCTAVE_F77_FLAG([-mieee])\n      else\n        OCTAVE_F77_FLAG([-ieee])\n        OCTAVE_F77_FLAG([-fpe1])\n      fi\n    ;;\n    powerpc-apple-machten*)\n      FFLAGS=\n    ;;\n  esac\n\n  if test $ac_cv_f77_compiler_gnu = yes; then\n    FORTRAN_CALLING_CONVENTION=gfortran\n  else\n    FORTRAN_CALLING_CONVENTION=unknown\n  fi\n  AC_ARG_ENABLE([fortran-calling-convention],\n    [AS_HELP_STRING([--enable-fortran-calling-convention=OPTION],\n      [Select C++ to Fortran calling convention.  \"gfortran\" should be detected automatically.  Other options are \"cray\", \"visual-fortran\", or \"f2c\".])],\n    [FORTRAN_CALLING_CONVENTION=\"$enableval\"], [])\n\n  case $FORTRAN_CALLING_CONVENTION in\n    gfortran)\n      AC_DEFINE(F77_USES_GFORTRAN_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the gfortran calling convention.])\n    ;;\n    cray)\n      AC_DEFINE(F77_USES_CRAY_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the Cray Fortran calling convention.])\n    ;;\n    visual-fortran)\n      AC_DEFINE(F77_USES_VISUAL_FORTRAN_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the Visual Fortran calling convention.])\n    ;;\n    f2c)\n      AC_DEFINE(F77_USES_F2C_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the f2c calling convention.])\n    ;;\n    *)\n      AC_MSG_ERROR([to build Octave, the C++ to Fortran calling convention must be known.])\n    ;;\n  esac\n\n  if test -n \"$FFLAGS\"; then\n    AC_MSG_NOTICE([defining FFLAGS to be $FFLAGS])\n  fi\n\n  AC_SUBST(F77_TOLOWER)\n  AC_SUBST(F77_APPEND_UNDERSCORE)\n  AC_SUBST(F77_APPEND_EXTRA_UNDERSCORE)\n])\ndnl\ndnl Check if function gluTessCallback is called with \"(...)\".\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_GLUTESSCALLBACK_THREEDOTS], [\n  AC_CACHE_CHECK([whether gluTessCallback is called with \"(...)\"],\n    [octave_cv_func_glutesscallback_threedots],\n    [AC_LANG_PUSH(C++)\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #if defined (HAVE_GL_GLU_H)\n        # include <GL/glu.h>\n        #elif defined HAVE_OPENGL_GLU_H || defined HAVE_FRAMEWORK_OPENGL\n        # include <OpenGL/glu.h>\n        #endif\n        ]], [[\n        GLvoid (*func)(...);\n        gluTessCallback(0, 0, func);\n        ]])],\n      octave_cv_func_glutesscallback_threedots=yes,\n      octave_cv_func_glutesscallback_threedots=no)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_glutesscallback_threedots = yes; then\n    AC_DEFINE(HAVE_GLUTESSCALLBACK_THREEDOTS, 1,\n      [Define to 1 if gluTessCallback is called with (...).])\n  fi\n])\ndnl\ndnl Check whether the Qt class QList has a constructor that accepts\ndnl a pair of iterators.  This constructor was introduced in Qt 5.14.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 5.13 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_QFONTMETRICS_HORIZONTAL_ADVANCE], [\n  AC_CACHE_CHECK([for QFontMetrics::horizontalAdvance function],\n    [octave_cv_func_qfontmetrics_horizontal_advance],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QFont>\n        #include <QFontMetrics>\n        #include <QString>\n        ]], [[\n        QFont font;\n        QFontMetrics fm (font);\n        fm.horizontalAdvance ('x');\n        fm.horizontalAdvance (QString (\"string\"));\n        ]])],\n      octave_cv_func_qfontmetrics_horizontal_advance=yes,\n      octave_cv_func_qfontmetrics_horizontal_advance=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_qfontmetrics_horizontal_advance = yes; then\n    AC_DEFINE(HAVE_QFONTMETRICS_HORIZONTAL_ADVANCE, 1,\n      [Define to 1 if you have the `QFontMetrics::horizontalAdvance' function.])\n  fi\n])\ndnl\ndnl Check whether the Qt class QHelpEngine has the documentsForIdentifier\ndnl function.  This member function was introduced in Qt 5.15.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 5.14 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_QHELPENGINE_DOCUMENTSFORIDENTIFIER], [\n  AC_CACHE_CHECK([for QHelpEngine::documentsForIdentifier in <QHelpEngine>],\n    [octave_cv_func_qhelpengine_documentsforidentifier],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QHelpEngine>\n        #include <QHelpLink>\n        #include <QList>\n        #include <QString>\n        #include <QUrl>\n        ]], [[\n        QString collection_file;\n        QHelpEngine eng (collection_file);\n        QString id;\n        eng.documentsForIdentifier (id);\n        ]])],\n      octave_cv_func_qhelpengine_documentsforidentifier=yes,\n      octave_cv_func_qhelpengine_documentsforidentifier=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_qhelpengine_documentsforidentifier = yes; then\n    AC_DEFINE(HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER, 1,\n      [Define to 1 if you have the `QHelpEngine::documentsForIdentifier' member function.])\n  fi\n])\ndnl\ndnl Check whether the Qt QHelpSearchQueryWidget class has the searchInput\ndnl member function.  This function was introduced in Qt 5.9.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 5.8 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_QHELPSEARCHQUERYWIDGET_SEARCHINPUT], [\n  AC_CACHE_CHECK([for QHelpSearchQueryWidget::searchInput],\n    [octave_cv_func_qhelpsearchquerywidget_searchinput],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QHelpSearchQueryWidget>\n        #include <QString>\n        ]], [[\n        QHelpSearchQueryWidget *query_widget = new QHelpSearchQueryWidget ();\n        QString search_input = query_widget->searchInput ();\n        ]])],\n      octave_cv_func_qhelpsearchquerywidget_searchinput=yes,\n      octave_cv_func_qhelpsearchquerywidget_searchinput=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_qhelpsearchquerywidget_searchinput = yes; then\n    AC_DEFINE(HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT, 1,\n      [Define to 1 if you have the `QHelpSearchQueryWidget::searchInput' member function.])\n  fi\n])\ndnl\ndnl Check whether the Qt class QList has a constructor that accepts\ndnl a pair of iterators.  This constructor was introduced in Qt 5.14.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 5.13 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_QLIST_ITERATOR_CONSTRUCTOR], [\n  AC_CACHE_CHECK([for QList<T>::QList (iterator, iterator) constructor],\n    [octave_cv_func_qlist_iterator_constructor],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QList>\n        ]], [[\n        QList<int> lst_one;\n        QList<int> lst_two (lst_one.begin (), lst_one.end ());\n        ]])],\n      octave_cv_func_qlist_iterator_constructor=yes,\n      octave_cv_func_qlist_iterator_constructor=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_qlist_iterator_constructor = yes; then\n    AC_DEFINE(HAVE_QLIST_ITERATOR_CONSTRUCTOR, 1,\n      [Define to 1 if you have the `QList<T>::QList (iterator, iterator)' constructor.])\n  fi\n])\ndnl\ndnl Check whether the Qt class QWheelEvent has the position member function.\ndnl This member function was introduced in Qt 5.14.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 5.13 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_QWHEELEVENT_POSITION], [\n  AC_CACHE_CHECK([for QWheelEvent::position in <QWheelEvent>],\n    [octave_cv_func_qwheelevent_position],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QWheelEvent>\n        void foo (const QWheelEvent& ev)\n        {\n          ev.position ();\n        };\n        ]])],\n      octave_cv_func_qwheelevent_position=yes,\n      octave_cv_func_qwheelevent_position=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_qwheelevent_position = yes; then\n    AC_DEFINE(HAVE_QWHEELEVENT_POSITION, 1,\n      [Define to 1 if you have the `QWheelEvent::position' member function.])\n  fi\n])\ndnl\ndnl Check whether the Qt method QPainter::setRenderHint accepts the\ndnl QPainter::LosslessImageRendering flag.  This flag was introduced in\ndnl Qt 5.13.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 5.12 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_QPAINTER_SETRENDERHINT_LOSSLESS], [\n  AC_CACHE_CHECK([for QPainter::LosslessImageRendering flag],\n    [octave_cv_func_qpainter_setrenderhint_lossless],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QPainter>\n        ]], [[\n        QPainter painter;\n        painter.setRenderHint (QPainter::LosslessImageRendering);\n        ]])],\n      octave_cv_func_qpainter_setrenderhint_lossless=yes,\n      octave_cv_func_qpainter_setrenderhint_lossless=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_qpainter_setrenderhint_lossless = yes; then\n    AC_DEFINE(HAVE_QPAINTER_RENDERHINT_LOSSLESS, 1,\n      [Define to 1 if you have the `QPainter::LosslessImageRendering' flag.])\n  fi\n])\ndnl\ndnl Check whether the Qt methods QColor::getRgbF and QColor::getHslF\ndnl use float types as their arguments.  The type of the arguments\ndnl changed from qreal to float in Qt6.\ndnl\ndnl FIXME: Delete this check when we drop support for any version of Qt5.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_QCOLOR_FLOAT_TYPE], [\n  AC_CACHE_CHECK([for QColor::getRgbF and QColor::getHslF with float arguments],\n    [octave_cv_func_qcolor_float_type],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QColor>\n        ]], [[\n        QColor color;\n        float r, g, b, h, s, l, a;\n        color.getRgbF (&r, &g, &b);\n        color.getHslF (&h, &s, &l, &a);\n        ]])],\n      octave_cv_func_qcolor_float_type=yes,\n      octave_cv_func_qcolor_float_type=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_qcolor_float_type = yes; then\n    AC_DEFINE(HAVE_QCOLOR_FLOAT_TYPE, 1,\n      [Define to 1 if QColor::getRgbF and QColor::getHslF use float type arguments.])\n  fi\n])\ndnl\ndnl Check whether Qt provides a QStringView class.  This class was first\ndnl introduced in Qt 5.10 and finally replaced QStringRef in Qt6.\ndnl\ndnl FIXME: Delete this check when we drop support for Qt 5.9 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_CLASS_QSTRINGVIEW], [\n  AC_CACHE_CHECK([for class QStringView],\n    [octave_cv_class_qstringview],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QStringView>\n        ]], [[\n        QStringView qstrv {};\n        ]])],\n      octave_cv_class_qstringview=yes,\n      octave_cv_class_qstringview=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_class_qstringview = yes; then\n    AC_DEFINE(HAVE_QSTRINGVIEW, 1,\n      [Define to 1 if Qt provides the class QStringView.])\n  fi\n])\ndnl\ndnl Check whether the Qt class QTextStream has the setEncoding function.\ndnl This function was introduced replacing QTextStream::setCodec in Qt6.\ndnl\ndnl FIXME: Delete this check when we drop support for any version of Qt5.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_QTEXTSTREAM_SETENCODING], [\n  AC_CACHE_CHECK([for QTextStream::setEncoding],\n    [octave_cv_func_qtextstream_setencoding],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QStringConverter>\n        #include <QTextStream>\n        ]], [[\n        QTextStream textstream;\n        textstream.setEncoding (QStringConverter::Utf8);\n        ]])],\n      octave_cv_func_qtextstream_setencoding=yes,\n      octave_cv_func_qtextstream_setencoding=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_qtextstream_setencoding = yes; then\n    AC_DEFINE(HAVE_QTEXTSTREAM_SETENCODING, 1,\n      [Define to 1 if you have the `QTextStream::setEncoding' member function.])\n  fi\n])\ndnl\ndnl Check whether the Qt namespace contains a member Key_micro.  This\ndnl value was introduced in Qt 6.7.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 6.6 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_ENUM_QT_KEY_MICRO], [\n  AC_CACHE_CHECK([for Qt::Key_micro enum value],\n    [octave_cv_enum_qt_key_micro],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <Qt>\n        ]], [[\n        Qt::Key key = Qt::Key_micro;\n        ]])],\n      octave_cv_enum_qt_key_micro=yes,\n      octave_cv_enum_qt_key_micro=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_enum_qt_key_micro = yes; then\n    AC_DEFINE(HAVE_QT_KEY_MICRO, 1,\n      [Define to 1 if you have the `Qt::Key_micro' enum value.])\n  fi\n])\ndnl\ndnl Check whether the Qt class QCheckBox has the checkStateChanged\ndnl signal.  This signal was introduced in Qt 6.7.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 6.6 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_SIGNAL_QCHECKBOX_CHECKSTATECHANGED], [\n  AC_CACHE_CHECK([for QCheckBox::checkStateChanged signal],\n    [octave_cv_signal_qcheckbox_checkstatechanged],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QCheckBox>\n        ]], [[\n        QCheckBox checkbox;\n        QObject::connect (&checkbox, &QCheckBox::checkStateChanged,\n                          [] (Qt::CheckState) {});\n        ]])],\n      octave_cv_signal_qcheckbox_checkstatechanged=yes,\n      octave_cv_signal_qcheckbox_checkstatechanged=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_signal_qcheckbox_checkstatechanged = yes; then\n    AC_DEFINE(HAVE_QCHECKBOX_CHECKSTATECHANGED, 1,\n      [Define to 1 if you have the `QCheckBox::checkStateChanged' signal.])\n  fi\n])\ndnl\ndnl Check whether the Qt class QColor has the fromString member function.\ndnl This member function was introduced in Qt 6.4.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 6.3 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_FUNC_QCOLOR_FROMSTRING], [\n  AC_CACHE_CHECK([for QColor::fromString],\n    [octave_cv_func_qcolor_fromstring],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QColor>\n        ]], [[\n        QColor color;\n        color.fromString (\"green\");\n        ]])],\n      octave_cv_func_qcolor_fromstring=yes,\n      octave_cv_func_qcolor_fromstring=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_func_qcolor_fromstring = yes; then\n    AC_DEFINE(HAVE_QCOLOR_FROMSTRING, 1,\n      [Define to 1 if you have the `QColor::fromString' member function.])\n  fi\n])\ndnl\ndnl Check whether HDF5 library has version 1.6 API functions.\ndnl\nAC_DEFUN([OCTAVE_CHECK_HDF5_HAS_VER_16_API], [\n  AC_CACHE_CHECK([whether HDF5 library has enforced version 1.6 API],\n    [octave_cv_hdf5_has_ver_16_api],\n    [AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n      #include <hdf5.h>\n      ]], [[\n      H5Eset_auto (0, 0);\n      ]])],\n      octave_cv_hdf5_has_ver_16_api=yes,\n      octave_cv_hdf5_has_ver_16_api=no)\n  ])\n  if test $octave_cv_hdf5_has_ver_16_api != yes; then\n    AC_DEFINE(HAVE_HDF5_18, 1, [Define to 1 if >=HDF5-1.8 is available.])\n  fi\n])\ndnl\ndnl Check whether HDF5 library has UTF-8 file API.\ndnl\nAC_DEFUN([OCTAVE_CHECK_HDF5_HAS_UTF8_API], [\n  AC_CACHE_CHECK([whether HDF5 library has UTF-8 file API],\n    [octave_cv_hdf5_has_utf8_api],\n    [case $host_os in\n      msdosmsvc | mingw*)\n        AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n          #include <stddef.h>\n          const wchar_t *H5_get_utf16_str(const char *s);\n          ]], [[\n          H5_get_utf16_str (\"\");\n          ]])],\n          octave_cv_hdf5_has_utf8_api=yes,\n          octave_cv_hdf5_has_utf8_api=no)\n      ;;\n      *)\n        ## Assume yes on all other platforms\n        octave_cv_hdf5_has_utf8_api=yes\n      ;;\n     esac\n    ])\n  if test $octave_cv_hdf5_has_utf8_api = yes; then\n    AC_DEFINE(HAVE_HDF5_UTF8, 1, [Define to 1 if HDF5 has UTF-8 file API.])\n  fi\n])\ndnl\ndnl Usage:\ndnl OCTAVE_CHECK_LIB(LIBRARY, DOC-NAME, WARN-MSG, HEADER, FUNC,\ndnl                  LANG, DOC-STRING, EXTRA-CHECK, PKG-CONFIG-NAME,\ndnl                  REQUIRED)\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB], [\n  AC_ARG_WITH([m4_tolower($1)-includedir],\n    [AS_HELP_STRING([--with-m4_tolower($1)-includedir=DIR],\n      [look for $2 include files in DIR])],\n    [m4_toupper(patsubst([$1], [-], [_]))_CPPFLAGS=\"-I$withval\"])\n  AC_SUBST(m4_toupper(patsubst([$1], [-], [_]))_CPPFLAGS)\n\n  AC_ARG_WITH([m4_tolower($1)-libdir],\n    [AS_HELP_STRING([--with-m4_tolower($1)-libdir=DIR],\n      [look for $2 libraries in DIR])],\n    [m4_toupper(patsubst([$1], [-], [_]))_LDFLAGS=\"-L$withval\"])\n  AC_SUBST(m4_toupper(patsubst([$1], [-], [_]))_LDFLAGS)\n\n  AC_ARG_WITH([m4_tolower($1)],\n    [ifelse([$#], 10,\n       [m4_ifblank([$7],\n         [AS_HELP_STRING([--with-m4_tolower($1)=<lib>], [use $2 library <lib>])],\n         [AS_HELP_STRING([--with-m4_tolower($1)], [$7])])],\n       [m4_ifblank([$7],\n         [AS_HELP_STRING([--without-m4_tolower($1)], [don't use $2 library])],\n         [AS_HELP_STRING([--without-m4_tolower($1)], [$7])])])],\n    [with_]patsubst([$1], [-], [_])=$withval, [with_]patsubst([$1], [-], [_])=yes)\n\n  [ac_octave_]patsubst([$1], [-], [_])_pkg_check=no\n  m4_toupper(patsubst([$1], [-], [_]))_LIBS=\n  [warn_]patsubst([$1], [-], [_])=\"$3\"\n  case $[with_]patsubst([$1], [-], [_]) in\n    no)\n      ifelse([$#], 10,\n        [AC_MSG_ERROR([--without-m4_tolower($1) specified but $2 is required.])],\n        [[warn_]patsubst([$1], [-], [_])=\"\"\n         m4_toupper(patsubst([$1], [-], [_]))_LIBS=])\n    ;;\n    yes | \"\")\n      [ac_octave_]patsubst([$1], [-], [_])_pkg_check=yes\n      m4_toupper(patsubst([$1], [-], [_]))_LIBS=\"-l$1\"\n    ;;\n    -* | */* | *.a | *.so | *.so.* | *.o)\n      m4_toupper(patsubst([$1], [-], [_]))_LIBS=\"$[with_]patsubst([$1], [-], [_])\"\n    ;;\n    *)\n      m4_toupper(patsubst([$1], [-], [_]))_LIBS=\"-l$[with_]patsubst([$1], [-], [_])\"\n    ;;\n  esac\n\n  if test $[ac_octave_]patsubst([$1], [-], [_])_pkg_check = yes; then\n    PKG_CHECK_EXISTS(m4_default([$9], [$1]), [\n      if test -z \"$m4_toupper(patsubst([$1], [-], [_]))_CPPFLAGS\"; then\n        m4_toupper(patsubst([$1], [-], [_]))_CPPFLAGS=\"$($PKG_CONFIG --cflags m4_default([$9], [$1]) | $SED -e 's/^ *$//')\"\n      fi\n      if test -z \"$m4_toupper(patsubst([$1], [-], [_]))_LDFLAGS\"; then\n        m4_toupper(patsubst([$1], [-], [_]))_LDFLAGS=\"$($PKG_CONFIG --libs-only-L m4_default([$9], [$1]) | $SED -e 's/^ *$//')\"\n      fi\n      m4_toupper(patsubst([$1], [-], [_]))_LIBS=\"$($PKG_CONFIG --libs-only-l --libs-only-other m4_default([$9], [$1]) | $SED -e 's/^ *$//')\"\n    ])\n  fi\n\n  if test -n \"$m4_toupper(patsubst([$1], [-], [_]))_LIBS\"; then\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_LDFLAGS=\"$LDFLAGS\"\n    ac_octave_save_LIBS=\"$LIBS\"\n    CPPFLAGS=\"$m4_toupper(patsubst([$1], [-], [_]))_CPPFLAGS $CPPFLAGS\"\n    LDFLAGS=\"$m4_toupper(patsubst([$1], [-], [_]))_LDFLAGS $LDFLAGS\"\n    LIBS=\"$m4_toupper(patsubst([$1], [-], [_]))_LIBS $LIBS\"\n    m4_ifnblank([$6], [AC_LANG_PUSH($6)])\n    [ac_octave_]patsubst([$1], [-], [_])_check_for_lib=no\n    m4_ifblank([$4], [[ac_octave_]patsubst([$1], [-], [_])_check_for_lib=yes],\n               [AC_CHECK_HEADERS([$4], [[ac_octave_]patsubst([$1], [-], [_])_check_for_lib=yes; break])])\n    if test $[ac_octave_]patsubst([$1], [-], [_])_check_for_lib = yes; then\n      AC_CACHE_CHECK([for $5 in $m4_toupper(patsubst([$1], [-], [_]))_LIBS],\n        [[octave_cv_lib_]patsubst([$1], [-], [_])],\n        [AC_LINK_IFELSE([AC_LANG_CALL([], [$5])],\n          [[octave_cv_lib_]patsubst([$1], [-], [_])=yes], [[octave_cv_lib_]patsubst([$1], [-], [_])=no])\n      ])\n      if test \"$[octave_cv_lib_]patsubst([$1], [-], [_])\" = yes; then\n        m4_ifblank([$8], [\n          [warn_]patsubst([$1], [-], [_])=\n          AC_DEFINE([HAVE_]m4_toupper(patsubst([$1], [-], [_])), 1,\n            [Define to 1 if $2 is available.])], [$8])\n      else\n        m4_toupper(patsubst([$1], [-], [_]))_LIBS=\n      fi\n    else\n      [octave_cv_lib_]patsubst([$1], [-], [_])=no\n      m4_toupper(patsubst([$1], [-], [_]))_LIBS=\n    fi\n    m4_ifnblank([$6], [AC_LANG_POP($6)])\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    LDFLAGS=\"$ac_octave_save_LDFLAGS\"\n    LIBS=\"$ac_octave_save_LIBS\"\n  else\n    [octave_cv_lib_]patsubst([$1], [-], [_])=no\n  fi\n\n  ifelse([$#], 10, [\n    if test $[octave_cv_lib_]patsubst([$1], [-], [_]) = no; then\n      AC_MSG_ERROR([to build Octave, you must have the $2 library and header files installed])\n    fi])\n  AC_SUBST(m4_toupper(patsubst([$1], [-], [_]))_LIBS)\n  if test -n \"$[warn_]patsubst([$1], [-], [_])\"; then\n    OCTAVE_CONFIGURE_WARNING([[warn_]patsubst([$1], [-], [_])])\n  fi\n])\ndnl\ndnl Check whether ARPACK works (does not crash).\ndnl\ndnl Using a pure Fortran program doesn't seem to crash when linked\ndnl with the buggy ARPACK library, but the C++ program does.  Maybe it\ndnl is the memory allocation that exposes the bug and using statically\ndnl allocated arrays in Fortran does not?\ndnl\ndnl FIXME: it would be nice to avoid the duplication of F77 macros\ndnl and typedefs here and in the f77-fcn.h header file.  Also, the\ndnl definition of the character handling macros are not right for\ndnl all systems (but should work on most modern systems in use today).\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_ARPACK_OK_1], [\n  AC_CACHE_CHECK([whether the arpack library works],\n    [octave_cv_lib_arpack_ok_1],\n    [AC_LANG_PUSH(C++)\n    AC_RUN_IFELSE([AC_LANG_PROGRAM([[\n\n#include <cfloat>\n#include <cstdint>\n\ntypedef int F77_RET_T;\n\n#define F77_CHAR_ARG2(x, l) x\n#define F77_CONST_CHAR_ARG2(x, l) F77_CHAR_ARG2 (x, l)\n\n#define F77_CHAR_ARG_LEN(l) , l\n\n#define F77_CONST_CHAR_ARG_DECL const char *\n#define F77_CHAR_ARG_LEN_DECL , long\n\n#define F77_INT $OCTAVE_F77_INT_TYPE\n#define F77_DBLE double\n\nextern \"C\"\n{\n  F77_RET_T\n  F77_FUNC (dnaupd, DNAUPD) (F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT&, const F77_DBLE&,\n                             F77_DBLE*, const F77_INT&, F77_DBLE*,\n                             const F77_INT&, F77_INT*,\n                             F77_INT*, F77_DBLE*, F77_DBLE*,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dneupd, DNEUPD) (const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT*, F77_DBLE*, F77_DBLE*,\n                             F77_DBLE*, const F77_INT&, const F77_DBLE&,\n                             const F77_DBLE&, F77_DBLE*,\n                             F77_CONST_CHAR_ARG_DECL,\n                             const F77_INT&,\n                             F77_CONST_CHAR_ARG_DECL,\n                             F77_INT&, const F77_DBLE&, F77_DBLE*,\n                             const F77_INT&, F77_DBLE*,\n                             const F77_INT&, F77_INT*,\n                             F77_INT*, F77_DBLE*, F77_DBLE*,\n                             const F77_INT&, F77_INT&\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL\n                             F77_CHAR_ARG_LEN_DECL);\n\n  F77_RET_T\n  F77_FUNC (dgemv, DGEMV) (F77_CONST_CHAR_ARG_DECL,\n                           const F77_INT&, const F77_INT&,\n                           const F77_DBLE&, const F77_DBLE*,\n                           const F77_INT&, const F77_DBLE*,\n                           const F77_INT&, const F77_DBLE&,\n                           F77_DBLE*, const F77_INT&\n                           F77_CHAR_ARG_LEN_DECL);\n}\n\nvoid\ndoit (void)\n{\n  // Based on function EigsRealNonSymmetricMatrix from liboctave/eigs-base.cc.\n\n  // Problem matrix.  See bug #31479.\n  F77_INT n = 4;\n  double *m = new double [n * n];\n  m[0] = 1, m[4] = 0, m[8]  = 0, m[12] = -1;\n  m[1] = 0, m[5] = 1, m[9]  = 0, m[13] =  0;\n  m[2] = 0, m[6] = 0, m[10] = 1, m[14] =  0;\n  m[3] = 0, m[7] = 0, m[11] = 2, m[15] =  1;\n\n  double *resid = new double [4];\n\n  resid[0] = 0.960966;\n  resid[1] = 0.741195;\n  resid[2] = 0.150143;\n  resid[3] = 0.868067;\n\n  F77_INT *ip = new F77_INT [11];\n\n  ip[0] = 1;   // ishift\n  ip[1] = 0;   // ip[1] not referenced\n  ip[2] = 300; // mxiter, maximum number of iterations\n  ip[3] = 1;   // NB blocksize in recurrence\n  ip[4] = 0;   // nconv, number of Ritz values that satisfy convergence\n  ip[5] = 0;   // ip[5] not referenced\n  ip[6] = 1;   // mode\n  ip[7] = 0;   // ip[7] to ip[10] are return values\n  ip[8] = 0;\n  ip[9] = 0;\n  ip[10] = 0;\n\n  F77_INT *ipntr = new F77_INT [14];\n\n  F77_INT k = 1;\n  F77_INT p = 3;\n  F77_INT lwork = 3 * p * (p + 2);\n\n  double *v = new double [n * (p + 1)];\n  double *workl = new double [lwork + 1];\n  double *workd = new double [3 * n + 1];\n\n  F77_INT ido = 0;\n  F77_INT info = 0;\n\n  double tol = DBL_EPSILON;\n\n  do\n    {\n      F77_FUNC (dnaupd, DNAUPD) (ido, F77_CONST_CHAR_ARG2 (\"I\", 1),\n                                 n, F77_CONST_CHAR_ARG2 (\"LM\", 2),\n                                 k, tol, resid, p, v, n, ip, ipntr,\n                                 workd, workl, lwork, info\n                                 F77_CHAR_ARG_LEN (1)\n                                 F77_CHAR_ARG_LEN (2));\n\n      if (ido == -1 || ido == 1 || ido == 2)\n        {\n          double *x = workd + ipntr[0] - 1;\n          double *y = workd + ipntr[1] - 1;\n\n          F77_FUNC (dgemv, DGEMV) (F77_CONST_CHAR_ARG2 (\"N\", 1),\n                                   n, n, 1.0, m, n, x, 1, 0.0, y, 1\n                                   F77_CHAR_ARG_LEN (1));\n        }\n      else\n        {\n          if (info < 0)\n            return;  // Error\n\n          break;\n        }\n    }\n  while (1);\n\n  F77_INT *sel = new F77_INT [p];\n\n  // In Octave, the dimensions of dr and di are k+1, but k+2 avoids segfault\n  double *dr = new double [k + 1];\n  double *di = new double [k + 1];\n  double *workev = new double [3 * p];\n\n  for (F77_INT i = 0; i < k + 1; i++)\n    dr[i] = di[i] = 0.0;\n\n  F77_INT rvec = 1;\n\n  double sigmar = 0.0;\n  double sigmai = 0.0;\n\n  // In Octave, this is n*(k+1), but n*(k+2) avoids segfault\n  double *z = new double [n * (k + 1)];\n\n  F77_FUNC (dneupd, DNEUPD) (rvec, F77_CONST_CHAR_ARG2 (\"A\", 1),\n                             sel, dr, di, z, n, sigmar, sigmai, workev,\n                             F77_CONST_CHAR_ARG2 (\"I\", 1), n,\n                             F77_CONST_CHAR_ARG2 (\"LM\", 2), k, tol,\n                             resid, p, v, n, ip, ipntr, workd,\n                             workl, lwork, info\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (1)\n                             F77_CHAR_ARG_LEN (2));\n}\n\n]], [[\n\n  for (int i = 0; i < 10; i++)\n    doit ();\n\n    ]])],\n    octave_cv_lib_arpack_ok_1=yes,\n    octave_cv_lib_arpack_ok_1=no,\n    octave_cv_lib_arpack_ok_1=yes)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_lib_arpack_ok_1 = yes; then\n    $1\n    :\n  else\n    $2\n    :\n  fi\n])\ndnl\ndnl Check whether ARPACK is buggy (it doesn't crash, but gets wrong answers).\ndnl\ndnl ARPACK versions < 3.3.0 have a bug which results in different eigenvalues\ndnl being calculated depending on whether eigenvectors are also requested.\ndnl See bug #52425.\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_ARPACK_OK_2], [\n  AC_CACHE_CHECK([whether the arpack library is free of bugs],\n    [octave_cv_lib_arpack_ok_2],\n    [save_FFLAGS=\"$FFLAGS\"\n    FFLAGS=\"$FFLAGS $F77_INTEGER_8_FLAG\"\n    AC_LANG_PUSH(Fortran 77)\n    AC_RUN_IFELSE([[\n      program bug_52425\nc\n      integer          maxn, maxnev, maxncv, ldv\n      parameter       (maxn=256, maxnev=10, maxncv=25,\n     $                 ldv=maxn )\nc\n      Double precision\n     &                 v(ldv,maxncv), workl(maxncv*(maxncv+8)),\n     &                 workd(3*maxn), d(maxncv,2), resid(maxn),\n     &                 ax(maxn)\n      logical          select(maxncv)\n      integer          iparam(11), ipntr(11)\nc\n      character        bmat*1, which*2\n      integer          ido, n, nev, ncv, lworkl, info, ierr, j,\n     &                 nx, nconv, maxitr, mode, ishfts\n      logical          rvec\n      Double precision\n     &                 tol, sigma\nc\n      Double precision\n     &                 zero\n      parameter        (zero = 0.0D+0)\nc\n      Double precision\n     &                 dnrm2\n      external         dnrm2, daxpy\nc\n      intrinsic        abs\nc\n      n = 20\n      nev =  4\n      ncv =  20\n      bmat = 'I'\n      which = 'BE'\nc\n      lworkl = ncv*(ncv+8)\n      tol = zero\n      info = 1\n      do j = 1,n\n         resid (j) = 1.0d0\n      end do\n      ido = 0\nc\n      ishfts = 1\n      maxitr = 300\n      mode   = 1\nc\n      iparam(1) = ishfts\n      iparam(3) = maxitr\n      iparam(7) = mode\nc\n 10   continue\nc\n         call dsaupd ( ido, bmat, n, which, nev, tol, resid,\n     &                 ncv, v, ldv, iparam, ipntr, workd, workl,\n     &                 lworkl, info )\nc\n         if (ido .eq. -1 .or. ido .eq. 1) then\n            call av (n, workd(ipntr(1)), workd(ipntr(2)))\n            go to 10\n         end if\nc\n      if ( info .lt. 0 ) then\n          stop 1\n      else\n         rvec = .false.\nc\n         call dseupd ( rvec, 'All', select, d, v, ldv, sigma,\n     &        bmat, n, which, nev, tol, resid, ncv, v, ldv,\n     &        iparam, ipntr, workd, workl, lworkl, ierr )\nc\n         if ( ierr .ne. 0) then\n             stop 1\n         else\n             nconv =  iparam(5)\n             do 20 j=1, nconv\n                call av(n, v(1,j), ax)\n                call daxpy(n, -d(j,1), v(1,j), 1, ax, 1)\n                d(j,2) = dnrm2(n, ax, 1)\n                d(j,2) = d(j,2) / abs(d(j,1))\nc\n 20          continue\nc\nc            | Litmus test: return 1 or 0 based on returned eigenvalue\nc\n             if (abs(d(1,1) - 2.0810) > 1.0d-4) then\n                stop 1\n             else\n                stop 0\n             end if\n         end if\n      end if\nc\n      end\nc\n      subroutine av (n, v, w)\n      integer           n, j\n      Double precision v(n), w(n)\nc\n      w(1) = 4*v(1) + v(3)\n      w(2) = 4*v(2) + v(4)\n      do 10 j = 3, n - 2\n         w(j) = v(j-2) + 4*v(j) + v(j+2)\n 10   continue\n      w(n-1) = v(n-3) + 4 * v(n-1)\n      w(n) = v(n-2) + 4 * v(n)\n      return\n      end\n    ]],\n    octave_cv_lib_arpack_ok_2=yes,\n    octave_cv_lib_arpack_ok_2=no,\n    octave_cv_lib_arpack_ok_2=yes)\n    ## Restore FFLAGS.\n    FFLAGS=\"$save_FFLAGS\"\n    AC_LANG_POP(Fortran 77)\n  ])\n  if test $octave_cv_lib_arpack_ok_2 = yes; then\n    $1\n    :\n  else\n    $2\n    :\n  fi\n])\ndnl\ndnl Check whether GLPK provides the latest API functions required\ndnl for the glpk function. The glp_iptcp structure was introduced\ndnl in GLPK version 4.38.\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_GLPK_OK], [\n  AC_CACHE_CHECK([whether the glpk library has glp_interior(glp_prob*, glp_iptcp*)],\n    [octave_cv_lib_glpk_ok],\n    [AC_LANG_PUSH(C++)\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n        extern \"C\"\n        {\n        #if defined (HAVE_GLPK_GLPK_H)\n        #include <glpk/glpk.h>\n        #else\n        #include <glpk.h>\n        #endif\n        }\n        ]], [[\n        glp_prob *lp = glp_create_prob ();\n        glp_iptcp iptcp;\n        glp_init_iptcp (&iptcp);\n        int retval = glp_interior (lp, &iptcp);\n        ]])],\n      octave_cv_lib_glpk_ok=yes,\n      octave_cv_lib_glpk_ok=no)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_lib_glpk_ok = yes; then\n    $1\n    :\n  else\n    $2\n    :\n  fi\n])\ndnl\ndnl Check whether iconv provides the function iconvlist.\ndnl\nAC_DEFUN([OCTAVE_CHECK_ICONVLIST], [\n  AC_CACHE_CHECK([whether the function iconvlist is available],\n    [octave_cv_iconvlist],\n    [ac_octave_save_LIBS=\"$LIBS\"\n    LIBS=\"$LIBICONV $LIBS\"\n    AC_LANG_PUSH(C++)\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n        #if HAVE_ICONV\n        extern \"C\"\n        {\n        #  include <iconv.h>\n        }\n        #endif\n        ]], [[\n        iconvlist (\n           [] (unsigned int, const char * const *, void *) -> int\n             {\n               return 0;\n             },\n           nullptr);\n        ]])],\n      octave_cv_iconvlist=yes,\n      octave_cv_iconvlist=no)\n    AC_LANG_POP(C++)\n    LIBS=\"$ac_octave_save_LIBS\"\n  ])\n  if test $octave_cv_iconvlist = yes; then\n    AC_DEFINE(HAVE_ICONVLIST, 1, [Define to 1 if iconvlist is available.])\n  fi\n])\ndnl\ndnl Check whether iconv provides the function iconv_canonicalize.\ndnl\nAC_DEFUN([OCTAVE_CHECK_ICONV_CANONICALIZE], [\n  AC_CACHE_CHECK([whether the function iconv_canonicalize is available],\n    [octave_cv_iconv_canonicalize],\n    [ac_octave_save_LIBS=\"$LIBS\"\n    LIBS=\"$LIBICONV $LIBS\"\n    AC_LANG_PUSH(C++)\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n        #if HAVE_ICONV\n        extern \"C\"\n        {\n        #  include <iconv.h>\n        }\n        #endif\n        ]], [[\n        iconv_canonicalize (\"UTF-8\");\n        ]])],\n      octave_cv_iconv_canonicalize=yes,\n      octave_cv_iconv_canonicalize=no)\n    AC_LANG_POP(C++)\n    LIBS=\"$ac_octave_save_LIBS\"\n  ])\n  if test $octave_cv_iconv_canonicalize = yes; then\n    AC_DEFINE(HAVE_ICONV_CANONICALIZE, 1,\n      [Define to 1 if iconv_canonicalize is available.])\n  fi\n])\ndnl\ndnl Check whether using HDF5 DLL under Windows.  This is done by\ndnl testing for a data symbol in the HDF5 library, which would\ndnl require the definition of _HDF5USEDL_ under MSVC compiler.\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_HDF5_DLL], [\n  AC_CACHE_CHECK([if _HDF5USEDLL_ needs to be defined],\n    [octave_cv_lib_hdf5_dll],\n    [AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n        #include <hdf5.h>\n        ]], [[\n        hid_t x = H5T_NATIVE_DOUBLE;\n        return x\n      ]])],\n      [octave_cv_lib_hdf5_dll=no],\n      [save_CFLAGS=\"$CFLAGS\"\n      CFLAGS=\"$CFLAGS -DWIN32 -D_HDF5USEDLL_\"\n      ac_octave_save_LIBS=\"$LIBS\"\n      LIBS=\"$HDF5_LIBS $LIBS\"\n      AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n          #include <hdf5.h>\n          ]], [[\n          hid_t x = H5T_NATIVE_DOUBLE;\n          return x\n        ]])],\n        octave_cv_lib_hdf5_dll=yes,\n        octave_cv_lib_hdf5_dll=no)\n      CFLAGS=\"$save_CFLAGS\"\n      LIBS=\"$ac_octave_save_LIBS\"\n    ])\n  ])\n  if test $octave_cv_lib_hdf5_dll = yes; then\n    AC_DEFINE(_HDF5USEDLL_, 1, [Define to 1 if using HDF5 dll (Win32).])\n  fi\n])\ndnl\ndnl Check for OpenGL.  If found, define OPENGL_LIBS.\ndnl\ndnl FIXME: The following tests should probably check for the\ndnl libraries separately.\ndnl\ndnl FIXME: Should we allow a way to specify a directory for OpenGL\ndnl libraries and header files?\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_OPENGL], [\n  OPENGL_LIBS=\n\n  ## On MacOSX systems the OpenGL framework can be used\n  OCTAVE_HAVE_FRAMEWORK(OpenGL, [[\n    #include <OpenGL/gl.h>\n    #include <OpenGL/glu.h>\n    ]], [[\n    GLint par; glGetIntegerv (GL_VIEWPORT, &par);\n    ]],\n    have_framework_opengl=yes, have_framework_opengl=no)\n\n  if test $have_framework_opengl = yes; then\n    AC_DEFINE(HAVE_FRAMEWORK_OPENGL, 1,\n      [Define to 1 if framework OPENGL is available.])\n    OPENGL_LIBS=\"-framework OpenGL\"\n    AC_MSG_NOTICE([adding -framework OpenGL to OPENGL_LIBS])\n    OCTAVE_CHECK_FUNC_GLUTESSCALLBACK_THREEDOTS\n  else\n    case $canonical_host_type in\n      *-*-mingw32* | *-*-msdosmsvc)\n        AC_CHECK_HEADERS([windows.h])\n      ;;\n    esac\n    have_opengl_incs=no\n    AC_CHECK_HEADERS([GL/gl.h OpenGL/gl.h],\n      [AC_CHECK_HEADERS([GL/glu.h OpenGL/glu.h],\n        [have_opengl_incs=yes; break], [], [\n#if defined (HAVE_WINDOWS_H)\n#include <windows.h>\n#endif\n      ])\n      break\n      ], [], [\n#if defined (HAVE_WINDOWS_H)\n# include <windows.h>\n#endif\n    ])\n\n    if test $have_opengl_incs = yes; then\n      AC_CHECK_HEADERS([GL/glext.h OpenGL/glext.h], [], [], [\n#if defined (HAVE_WINDOWS_H)\n# include <windows.h>\n#endif\n#if defined (HAVE_GL_GL_H)\n# include <GL/gl.h>\n#elif defined (HAVE_OPENGL_GL_H)\n# include <OpenGL/gl.h>\n#endif\n      ])\n      case $canonical_host_type in\n        *-*-mingw32* | *-*-msdosmsvc)\n          ac_octave_save_LIBS=\"$LIBS\"\n          LIBS=\"$LIBS -lopengl32\"\n          AC_MSG_CHECKING([for glEnable in -lopengl32])\n          AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n            #if HAVE_WINDOWS_H\n            # include <windows.h>\n            #endif\n            #if defined (HAVE_GL_GL_H)\n            # include <GL/gl.h>\n            #elif defined (HAVE_OPENGL_GL_H)\n            # include <OpenGL/gl.h>\n            #endif\n            ]], [[\n            glEnable(GL_SMOOTH);\n            ]])], [OPENGL_LIBS=\"-lopengl32 -lglu32\"])\n\n          LIBS=\"$ac_octave_save_LIBS\"\n          if test -n \"$OPENGL_LIBS\"; then\n            AC_MSG_RESULT([yes])\n          else\n            AC_MSG_RESULT([no])\n          fi\n          ;;\n        *)\n          ## Non-Mac, Non-Windows systems use this check\n          AC_CHECK_LIB([GL], [glEnable], [OPENGL_LIBS=\"-lGL -lGLU\"])\n          ;;\n      esac\n    fi\n  fi\n  AC_SUBST(OPENGL_LIBS)\n  if test -n \"$OPENGL_LIBS\"; then\n    AC_DEFINE(HAVE_OPENGL, 1, [Define to 1 if OpenGL is available.])\n\n    save_LIBS=\"$LIBS\"\n    LIBS=\"$LIBS $OPENGL_LIBS\"\n    AC_CACHE_CHECK([for glBlendFuncSeparate],\n      [octave_cv_func_glblendfuncseparate],[\n      AC_LANG_PUSH(C++)\n      AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n#if defined (HAVE_WINDOWS_H)\n# include <windows.h>\n#endif\n#if defined (HAVE_GL_GL_H)\n# include <GL/gl.h>\n#elif defined (HAVE_OPENGL_GL_H)\n# include <OpenGL/gl.h>\n#endif\n#if defined (HAVE_GL_GLEXT_H)\n#  include <GL/glext.h>\n#elif defined (HAVE_OPENGL_GLEXT_H) || defined (HAVE_FRAMEWORK_OPENGL)\n#  include <OpenGL/glext.h>\n#endif\n        ]], [[\n        GLenum sfactor=0;\n        GLenum dfactor=0;\n        GLenum salpha=0;\n        GLenum dalpha=0;\n        glBlendFuncSeparate (sfactor, dfactor, salpha, dalpha);\n        ]])],\n        octave_cv_func_glblendfuncseparate=yes,\n        octave_cv_func_glblendfuncseparate=no)\n      AC_LANG_POP(C++)\n      ])\n    if test $octave_cv_func_glblendfuncseparate = yes; then\n      AC_DEFINE(HAVE_GLBLENDFUNCSEPARATE, 1, [Define to 1 if glBlendFuncSeparate can be used directly.])\n    else\n      AC_CACHE_CHECK([for glBlendFuncSeparate with GL_GLEXT_PROTOTYPES],\n        [octave_cv_func_glblendfuncseparate_as_ext],[\n        AC_LANG_PUSH(C++)\n        AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n#define GL_GLEXT_PROTOTYPES 1\n#if defined (HAVE_WINDOWS_H)\n# include <windows.h>\n#endif\n#if defined (HAVE_GL_GL_H)\n# include <GL/gl.h>\n#elif defined (HAVE_OPENGL_GL_H)\n# include <OpenGL/gl.h>\n#endif\n#if defined (HAVE_GL_GLEXT_H)\n#  include <GL/glext.h>\n#elif defined (HAVE_OPENGL_GLEXT_H) || defined (HAVE_FRAMEWORK_OPENGL)\n#  include <OpenGL/glext.h>\n#endif\n          ]], [[\n          GLenum sfactor=0;\n          GLenum dfactor=0;\n          GLenum salpha=0;\n          GLenum dalpha=0;\n          glBlendFuncSeparate (sfactor, dfactor, salpha, dalpha);\n          ]])],\n          octave_cv_func_glblendfuncseparate_as_ext=yes,\n          octave_cv_func_glblendfuncseparate_as_ext=no)\n        ])\n      if test $octave_cv_func_glblendfuncseparate_as_ext = yes; then\n        AC_DEFINE(HAVE_GLBLENDFUNCSEPARATE, 1, [Define to 1 if glBlendFuncSeparate can be used directly.])\n        AC_DEFINE(GL_GLEXT_PROTOTYPES, 1, [Define to 1 to enable OpenGL extensions in headers.])\n      fi\n    fi\n    LIBS=\"$save_LIBS\"\n  fi\n])\ndnl\ndnl Check whether PCRE is compiled with --enable-utf.\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_PCRE_OK], [\n  AC_CACHE_CHECK([whether PCRE library was compiled with UTF support],\n    [octave_cv_lib_pcre_ok],\n    [AC_LANG_PUSH(C++)\n    AC_RUN_IFELSE([AC_LANG_PROGRAM([[\n        #include <cstdio>\n        #if defined (HAVE_PCRE_H)\n        #  include <pcre.h>\n        #elif defined (HAVE_PCRE_PCRE_H)\n        #  include <pcre/pcre.h>\n        #endif\n        ]], [[\n        const char *pattern = \"test\";\n        const char *err;\n        int erroffset;\n        pcre *data = pcre_compile (pattern, PCRE_UTF8, &err, &erroffset, nullptr);\n        return (! data);\n      ]])],\n      octave_cv_lib_pcre_ok=yes,\n      octave_cv_lib_pcre_ok=no,\n      octave_cv_lib_pcre_ok=yes)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_lib_pcre_ok = yes; then\n    $1\n    :\n  else\n    $2\n    :\n  fi\n])\ndnl\ndnl Check whether PCRE2 is compiled with --enable-utf.\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_PCRE2_OK], [\n  AC_CACHE_CHECK([whether PCRE2 library was compiled with UTF support],\n    [octave_cv_lib_pcre2_ok],\n    [AC_LANG_PUSH(C++)\n    AC_RUN_IFELSE([AC_LANG_PROGRAM([[\n        #include <cstdio>\n        #define PCRE2_CODE_UNIT_WIDTH 8\n        #if defined (HAVE_PCRE2_H)\n        #  include <pcre2.h>\n        #elif defined (HAVE_PCRE2_PCRE2_H)\n        #  include <pcre2/pcre2.h>\n        #endif\n        ]], [[\n        const char *pattern = \"test\";\n        int err;\n        PCRE2_SIZE erroffset;\n        pcre2_code *data = pcre2_compile ((PCRE2_SPTR) pattern, PCRE2_ZERO_TERMINATED, PCRE2_UTF, &err, &erroffset, nullptr);\n        return (! data);\n      ]])],\n      octave_cv_lib_pcre2_ok=yes,\n      octave_cv_lib_pcre2_ok=no,\n      octave_cv_lib_pcre2_ok=yes)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_lib_pcre2_ok = yes; then\n    $1\n    :\n  else\n    $2\n    :\n  fi\n])\ndnl\ndnl Check whether Qhull works (does not crash).\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_QHULL_OK], [\n  AC_CACHE_CHECK([whether the qhull_r library works],\n    [octave_cv_lib_qhull_r_ok],\n    [AC_RUN_IFELSE([AC_LANG_PROGRAM([[\n        #include <stdio.h>\n        #if defined (HAVE_LIBQHULL_R_LIBQHULL_R_H)\n        # include <libqhull_r/libqhull_r.h>\n        # include <libqhull_r/qset_r.h>\n        # include <libqhull_r/geom_r.h>\n        # include <libqhull_r/poly_r.h>\n        # include <libqhull_r/io_r.h>\n        #elif defined (HAVE_LIBQHULL_R_H)\n        # include <libqhull_r.h>\n        # include <qset_r.h>\n        # include <geom_r.h>\n        # include <poly_r.h>\n        # include <io_r.h>\n        #endif\n        #if defined (NEED_QHULL_R_VERSION)\n          char *qh_version = \"version\";\n        #endif\n        ]], [[\n        int dim = 2;\n        int n = 4;\n        coordT points[8] = { -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5 };\n        boolT ismalloc = 0;\n        qhT context = { };\n        qhT* qh = &context;\n        return qh_new_qhull (qh, dim, n, points, ismalloc, \"qhull \", 0, stderr);\n      ]])],\n      octave_cv_lib_qhull_r_ok=yes,\n      octave_cv_lib_qhull_r_ok=no,\n      octave_cv_lib_qhull_r_ok=yes)\n  ])\n  if test $octave_cv_lib_qhull_r_ok = yes; then\n    $1\n    :\n  else\n    $2\n    :\n  fi\n])\ndnl\ndnl Check whether sndfile library is modern enough to include things like Ogg\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_SNDFILE_OK], [\n  AC_CACHE_CHECK([whether sndfile library is modern enough],\n    [octave_cv_lib_sndfile_ok],\n    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <sndfile.h>\n        ]], [[\n        int x = SF_FORMAT_OGG;\n      ]])],\n      octave_cv_lib_sndfile_ok=yes,\n      octave_cv_lib_sndfile_ok=no)\n  ])\n  if test $octave_cv_lib_sndfile_ok = yes; then\n    $1\n    :\n  else\n    $2\n    :\n  fi\n])\n\ndnl\ndnl Check for support of some specific formats in sndfile library\ndnl\nAC_DEFUN([OCTAVE_CHECK_LIB_SNDFILE_FORMATS], [\n  AC_CACHE_CHECK([whether sndfile library supports mp3],\n    [octave_cv_lib_sndfile_format_mp3],\n    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <sndfile.h>\n        ]], [[\n        int x = SF_FORMAT_MPEG;\n      ]])],\n      octave_cv_lib_sndfile_format_mp3=yes,\n      octave_cv_lib_sndfile_format_mp3=no)\n  ])\n  if test $octave_cv_lib_sndfile_format_mp3 = yes; then\n    AC_DEFINE(HAVE_LIB_SNDFILE_FORMAT_MP3, 1,\n      [Define to 1 if libsndfile supports mp3.])\n  fi\n])\ndnl\ndnl Check whether new API is used with QHelpIndexWidget.\ndnl Under new API, QHelpIndexWidget emits documentActivates.\ndnl Under old API, QHelpIndexWidget emits linkActivated.\ndnl New structure/signal API was introduced in Qt 5.15.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 5.14 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_NEW_QHELPINDEXWIDGET_API], [\n  AC_CACHE_CHECK([for new QHelpIndexWidget API],\n    [octave_cv_new_qhelpindexwidget_api],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QHelpLink>\n        ]], [[\n        QHelpLink link;\n        ]])],\n      octave_cv_new_qhelpindexwidget_api=yes,\n      octave_cv_new_qhelpindexwidget_api=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_new_qhelpindexwidget_api = yes; then\n    AC_DEFINE(HAVE_NEW_QHELPINDEXWIDGET_API, 1,\n      [Define to 1 if using new QHelpIndexWidget API.])\n  fi\n])\ndnl\ndnl Check for the Qhull version.\ndnl\nAC_DEFUN([OCTAVE_CHECK_QHULL_VERSION], [\n  AC_CACHE_CHECK([for qh_version in $QHULL_R_LIBS],\n    [octave_cv_lib_qhull_r_version],\n    [AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n        #include <stdio.h>\n        #if defined (HAVE_LIBQHULL_R_LIBQHULL_R_H)\n        # include <libqhull_r/libqhull_r.h>\n        # include <libqhull_r/qset_r.h>\n        # include <libqhull_r/geom_r.h>\n        # include <libqhull_r/poly_r.h>\n        # include <libqhull_r/io_r.h>\n        #elif defined (HAVE_LIBQHULL_R_H)\n        # include <libqhull_r.h>\n        # include <qset_r.h>\n        # include <geom_r.h>\n        # include <poly_r.h>\n        # include <io_r.h>\n        #endif\n        ]], [[\n        const char *tmp = qh_version;\n      ]])],\n      octave_cv_lib_qhull_r_version=yes, octave_cv_lib_qhull_r_version=no)\n  ])\n  if test $octave_cv_lib_qhull_r_version = no; then\n    AC_DEFINE(NEED_QHULL_R_VERSION, 1,\n      [Define to 1 if the Qhull library needs a qh_version variable defined.])\n  fi\n])\ndnl\ndnl Check whether the Qt class QRegion has the iterators and related\ndnl functions introduced in Qt 5.8.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 5.7 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_QREGION_ITERATORS], [\n  AC_CACHE_CHECK([for QRegion iterators and related functions],\n    [octave_cv_qregion_iterators],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <QRegion>\n        ]], [[\n        QRegion region;\n        QRegion::const_iterator it;\n        it = region.begin ();\n        it = region.end ();\n        it = region.cbegin ();\n        it = region.cend ();\n        QRegion::const_reverse_iterator rit;\n        rit = region.rbegin ();\n        rit = region.rend ();\n        rit = region.crbegin ();\n        rit = region.crend ();\n        ]])],\n      octave_cv_qregion_iterators=yes,\n      octave_cv_qregion_iterators=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_qregion_iterators = yes; then\n    AC_DEFINE(HAVE_QREGION_ITERATORS, 1,\n      [Define to 1 if you have the `QFontMetrics::horizontalAdvance' function.])\n  fi\n])\ndnl\ndnl Check whether we have QScintilla for the given Qt VERSION.\ndnl\nAC_DEFUN([OCTAVE_CHECK_QSCINTILLA], [\n  qt_version=\"$1\";\n  use_qscintilla=no\n  warn_qscintilla=\"\"\n\n  ## Check for Qt libraries\n  case \"$qt_version\" in\n    5)\n      octave_qscintilla_libnames=\"qscintilla2-qt5 qscintilla2_qt5 qt5scintilla2\"\n    ;;\n    6)\n      octave_qscintilla_libnames=\"qscintilla2-qt6 qscintilla2_qt6 qt6scintilla2\"\n    ;;\n    *)\n      AC_MSG_ERROR([Unrecognized Qt version $qt_version])\n    ;;\n  esac\n\n  if test $build_qt_gui = yes && test $check_qscintilla = yes; then\n\n    ## Check for QScintilla library which is used in the Qt GUI editor.\n    AC_CACHE_CHECK([for the QScintilla library for Qt $qt_version],\n      [octave_cv_lib_qscintilla],\n      [save_CPPFLAGS=\"$CPPFLAGS\"\n      save_CXXFLAGS=\"$CXXFLAGS\"\n      save_LDFLAGS=\"$LDFLAGS\"\n      ac_octave_save_LIBS=\"$LIBS\"\n      CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n      CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n      LDFLAGS=\"$QT_LDFLAGS $LDFLAGS\"\n      AC_LANG_PUSH(C++)\n      for octave_qscintilla_try in $octave_qscintilla_libnames; do\n        LIBS=\"$QT_LIBS -l$octave_qscintilla_try\"\n        AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n          #include <Qsci/qsciapis.h>\n          #include <Qsci/qscilexercpp.h>\n          ]], [[\n          QsciLexer *lexer = new QsciLexerCPP ();\n          QsciAPIs *lexer_apis = new QsciAPIs (lexer);\n          ]])],\n          octave_cv_lib_qscintilla=\"-l$octave_qscintilla_try\",\n          octave_cv_lib_qscintilla=no)\n        if test $octave_cv_lib_qscintilla != no; then\n          break\n        fi\n      done\n      CPPFLAGS=\"$save_CPPFLAGS\"\n      CXXFLAGS=\"$save_CXXFLAGS\"\n      LDFLAGS=\"$save_LDFLAGS\"\n      LIBS=\"$ac_octave_save_LIBS\"\n      AC_LANG_POP([C++])\n    ])\n\n    if test $octave_cv_lib_qscintilla = no; then\n      warn_qscintilla=\"QScintilla library not found; disabling built-in Qt GUI editor\"\n    else\n      ## Let's assume QScintilla library is at the same location as\n      ## other regular Qt libraries.\n      QT_LIBS=\"$QT_LIBS $octave_cv_lib_qscintilla\"\n      OCTAVE_CHECK_QSCINTILLA_VERSION\n      AC_DEFINE(HAVE_QSCINTILLA, 1,\n        [Define to 1 if the QScintilla library and header files are available.])\n\n      save_CPPFLAGS=\"$CPPFLAGS\"\n      save_CXXFLAGS=\"$CXXFLAGS\"\n      CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n      CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n      AC_LANG_PUSH(C++)\n      AC_CHECK_HEADERS([Qsci/qscilexeroctave.h Qsci/qscilexermatlab.h])\n      AC_LANG_POP(C++)\n      CPPFLAGS=\"$save_CPPFLAGS\"\n      CXXFLAGS=\"$save_CXXFLAGS\"\n\n      use_qscintilla=yes\n    fi\n  fi\n])\ndnl\ndnl Check whether QScintilla has version 2.6.0 or later\ndnl FIXME: This test uses a version number.  It potentially could\ndnl        be re-written to actually call the function, but is it worth it?\ndnl\nAC_DEFUN([OCTAVE_CHECK_QSCINTILLA_VERSION], [\n  AC_CACHE_CHECK([whether QScintilla has version 2.6.0 or later],\n    [octave_cv_version_2_6_0],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[\n        #include <Qsci/qsciglobal.h>\n        ]], [[\n        #if QSCINTILLA_VERSION < 0x020600\n        #error Old FindFirst function found.\n        #endif\n        ]])],\n      octave_cv_version_2_6_0=yes,\n      octave_cv_version_2_6_0=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_version_2_6_0 = yes; then\n    AC_DEFINE(HAVE_QSCI_VERSION_2_6_0, 1,\n      [Define to 1 if QScintilla is of Version 2.6.0 or later.])\n  fi\n])\ndnl\ndnl OCTAVE_CHECK_QT\ndnl\nAC_DEFUN([OCTAVE_CHECK_QT], [\n  octave_qt_versions=\"$1\"\n\n  build_qt_gui=no\n  use_qscintilla=no\n  win32_terminal=no\n\n  for ver in $octave_qt_versions; do\n    OCTAVE_CHECK_QT_VERSION([$ver])\n    if test $build_qt_gui = yes; then\n      have_qt_version=$ver\n      break\n    elif test -n \"$QT_MODULES_AVAILABLE\"; then\n      ## If some modules were found for $ver, then warn about possible\n      ## incomplete or broken Qt installation instead of checking for\n      ## next version in the list.  Don't attempt a similar check for\n      ## tools here because Qt5 and Qt6 tools may be installed with\n      ## the same name so determining whether there is a mix of versions\n      ## will require more work than just looking which tools are installed.\n      warn_qt_modules=\"Your installation of Qt version $ver appears incomplete or broken in some way.  Fix that or use --with-qt=VER to use another version.\"\n      break\n    fi\n  done\n\n  if test $build_qt_gui = yes; then\n    BUILD_QT_SUMMARY_MSG=\"yes (version: $have_qt_version)\"\n    if test x\"$have_qt_version\" = x5; then\n      AC_DEFINE(HAVE_QT5, 1, [Define to 1 if using Qt version 5.])\n    fi\n    if test x\"$have_qt_version\" = x6; then\n      AC_DEFINE(HAVE_QT6, 1, [Define to 1 if using Qt version 6.])\n    fi\n  else\n    if test -n \"$QT_MODULES_MISSING\" || test -n \"$QT_TOOLS_MISSING\"; then\n      qt_missing=`echo $QT_MODULES_MISSING$QT_TOOLS_MISSING | sed 's/  *$//'`\n      BUILD_QT_SUMMARY_MSG=\"no (missing:$qt_missing)\"\n    else\n      BUILD_QT_SUMMARY_MSG=\"no\"\n    fi\n    if test -n \"$warn_qt_modules\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qt_modules])\n    fi\n    if test -n \"$warn_qt_cxx17\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qt_cxx17])\n    fi\n    if test -n \"$warn_qt_libraries\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qt_libraries])\n    fi\n    if test -n \"$warn_qt_version\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qt_version])\n    fi\n    if test -n \"$warn_qt_tools\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qt_tools])\n    fi\n    if test -n \"$warn_qt_setvbuf\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qt_setvbuf])\n    fi\n    if test -n \"$warn_qt_lib_fcns\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qt_lib_fcns])\n    fi\n    if test -n \"$warn_qt_abstract_item_model\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qt_abstract_item_model])\n    fi\n    if test -n \"$warn_qt_opengl\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qt_opengl])\n    fi\n    if test -n \"$warn_qscintilla\"; then\n      OCTAVE_CONFIGURE_WARNING([warn_qscintilla])\n    fi\n  fi\n\n  AM_CONDITIONAL([AMCOND_BUILD_QT_GUI], [test $build_qt_gui = yes])\n  AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA], [test $use_qscintilla = yes])\n  AM_CONDITIONAL([WIN32_TERMINAL], [test $win32_terminal = yes])\n])\ndnl\ndnl Check whether the Qt::ImCursorRectangle enum value exists.\ndnl It replaces the Qt::ImMicroFocus enum value that was deprecated\ndnl in Qt 5.14.\ndnl\nAC_DEFUN([OCTAVE_CHECK_QT_IMCURSORRECTANGLE_ENUM_VALUE], [\n  AC_CACHE_CHECK([for Qt::ImCursorRectangle enum value],\n    [octave_cv_qt_imcursorrectangle_enum_value],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <Qt>\n        ]], [[\n        Qt::InputMethodQuery method_query = Qt::ImCursorRectangle;\n        ]])],\n      octave_cv_qt_imcursorrectangle_enum_value=yes,\n      octave_cv_qt_imcursorrectangle_enum_value=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_qt_imcursorrectangle_enum_value = yes; then\n    AC_DEFINE(HAVE_QT_IMCURSORRECTANGLE_ENUM_VALUE, 1,\n      [Define to 1 if you have the `Qt::ImCursorRectangle' enum value.])\n  fi\n])\ndnl\ndnl Check whether the Qt::SplitBehavior enum exists and has\ndnl Qt::KeepEmptyParts and Qt::SkipEmptyParts members.  This enum\ndnl was introduced or modified in Qt 5.14.\ndnl\ndnl FIXME: Delete this entirely when we drop support for Qt 5.13 or older.\ndnl\nAC_DEFUN([OCTAVE_CHECK_QT_SPLITBEHAVIOR_ENUM], [\n  AC_CACHE_CHECK([for Qt::SplitBehavior enum],\n    [octave_cv_qt_splitbehavior_enum],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    CXXFLAGS=\"$CXXPICFLAG $CXXFLAGS\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <Qt>\n        ]], [[\n        Qt::SplitBehavior sb_keep = Qt::KeepEmptyParts;\n        Qt::SplitBehavior sb_skip = Qt::SkipEmptyParts;\n        ]])],\n      octave_cv_qt_splitbehavior_enum=yes,\n      octave_cv_qt_splitbehavior_enum=no)\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_qt_splitbehavior_enum = yes; then\n    AC_DEFINE(HAVE_QT_SPLITBEHAVIOR_ENUM, 1,\n      [Define to 1 if you have the `Qt::SplitBehavior' enum.])\n  fi\n])\ndnl\ndnl OCTAVE_CHECK_QT_TOOL(TOOL)\ndnl\nAC_DEFUN([OCTAVE_CHECK_QT_TOOL], [\n  AC_CHECK_TOOLS(m4_toupper([$1])_QTVER, [$1-qt$qt_version])\n  if test -z \"$m4_toupper([$1])_QTVER\"; then\n    AC_PATH_TOOL(m4_toupper([$1]), [$1], [],\n                 [$QT_HOST_LIBEXECS$PATH_SEPARATOR$QT_HOST_BINS$PATH_SEPARATOR])\n    if test -z \"$m4_toupper([$1])\"; then\n      AC_CHECK_TOOLS(m4_toupper([$1]), [$1])\n    fi\n    if test -n \"$m4_toupper([$1])\"; then\n      if test -n \"$QTCHOOSER\"; then\n        m4_toupper([$1])FLAGS=\"-qt=$qt_version\"\n      fi\n      QT_TOOLS_AVAILABLE=\"$QT_TOOLS_AVAILABLE $1\"\n    else\n      QT_TOOLS_MISSING=\"$QT_TOOLS_MISSING $1\"\n    fi\n  else\n    m4_toupper([$1])=\"$m4_toupper([$1])_QTVER\"\n    QT_TOOLS_AVAILABLE=\"$QT_TOOLS_AVAILABLE $1\"\n  fi\n])\ndnl\ndnl Check whether Qt VERSION is present, supports QScintilla,\ndnl and will work for Octave.\ndnl\ndnl OCTAVE_CHECK_QT_VERSION(VERSION)\ndnl\nAC_DEFUN([OCTAVE_CHECK_QT_VERSION], [AC_MSG_CHECKING([Qt version $1])\n\n  qt_version=\"$1\";\n\n  build_qt_gui=yes\n  win32_terminal=no\n\n  warn_qt_libraries=\"\"\n  warn_qt_version=\"\"\n  warn_qt_tools=\"\"\n  warn_qt_setvbuf=\"\"\n  warn_qt_lib_fcns=\"\"\n  warn_qt_abstract_item_model=\"\"\n  warn_qt_opengl=\"\"\n\n  if test $build_qt_gui = yes; then\n    ## Check for Qt libraries\n    case \"$qt_version\" in\n      5)\n        QT_MODULES=\"Qt5Core Qt5Gui Qt5Help Qt5Network Qt5OpenGL Qt5PrintSupport Qt5Widgets Qt5Xml\"\n      ;;\n      6)\n        QT_MODULES=\"Qt6Core Qt6Gui Qt6Help Qt6Network Qt6OpenGL Qt6OpenGLWidgets Qt6PrintSupport Qt6Widgets Qt6Xml\"\n        case $host_os in\n          mingw* | msdosmsvc*)\n          ;;\n          *)\n            # FIXME: Remove Qt6Core5Compat when we no longer rely on classes that\n            #        have been removed in Qt6:\n            #        https://www.qt.io/blog/porting-from-qt-5-to-qt-6-using-qt5compat-library\n            #        It is still needed for the terminal implementation in\n            #        libgui/qterminal/libqterminal/unix\n            QT_MODULES=\"$QT_MODULES Qt6Core5Compat\"\n          ;;\n        esac\n      ;;\n      *)\n        AC_MSG_ERROR([Unrecognized Qt version $qt_version])\n      ;;\n    esac\n  fi\n\n  if test $build_qt_gui = yes \\\n      && test -n \"$QT_CPPFLAGS\" \\\n      && test -n \"$QT_LIBS\"; then\n    ## Don't use pkg-config but assume the provided flags are correct\n    ## and match the --with-qt value.\n    AC_MSG_WARN(\"Using provided values for QT_CPPFLAGS, QT_LIBS, and QT_LDFLAGS for Qt$qt_version\")\n  else\n    if test $build_qt_gui = yes; then\n      ## Use this check to get info in the log file.\n      PKG_CHECK_MODULES(QT, [$QT_MODULES],\n        [],\n        [build_qt_gui=no\n         warn_qt_libraries=\"Qt libraries not found; disabling Qt GUI\"])\n\n      ## Check the modules again individually to get lists of modules that\n      ## are available and/or missing\n      QT_MODULES_AVAILABLE=\n      QT_MODULES_MISSING=\n      for qt_mod in $QT_MODULES; do\n        if $PKG_CONFIG --exists $qt_mod; then\n          QT_MODULES_AVAILABLE=\"$QT_MODULES_AVAILABLE $qt_mod\"\n        else\n          QT_MODULES_MISSING=\"$QT_MODULES_MISSING $qt_mod\"\n        fi\n      done\n    fi\n\n    if test $build_qt_gui = yes; then\n      ## Retrieve Qt compilation and linker flags\n      QT_CPPFLAGS=\"$($PKG_CONFIG --cflags $QT_MODULES | $SED -e 's/^ *$//')\"\n      QT_LDFLAGS=\"$($PKG_CONFIG --libs-only-L $QT_MODULES | $SED -e 's/^ *$//')\"\n      QT_LIBS=\"$($PKG_CONFIG --libs-only-l --libs-only-other $QT_MODULES | $SED -e 's/^ *$//')\"\n\n      case $host_os in\n        *darwin*)\n          ## Qt might be installed in framework\n          ac_octave_QT_LIBS_only_l=\"$($PKG_CONFIG --libs-only-l $QT_MODULES | $SED -e 's/^ *$//')\"\n          if test -z \"$ac_octave_QT_LIBS_only_l\"; then\n            QT_LDFLAGS=\"`$PKG_CONFIG --libs-only-other $QT_MODULES | tr ' ' '\\n' | $GREP -e '-F' | uniq | tr '\\n' ' '`\"\n            QT_LIBS=\"`$PKG_CONFIG --libs-only-other $QT_MODULES | tr ' ' '\\n' | $GREP -v -e '-F' | uniq | tr '\\n' ' '`\"\n          fi\n        ;;\n      esac\n    fi\n  fi\n\n  QT_TOOLS_AVAILABLE=\n  QT_TOOLS_MISSING=\n\n  if test $build_qt_gui = yes; then\n    case \"$qt_version\" in\n      5)\n        AC_CHECK_TOOLS(QTCHOOSER, [qtchooser])\n      ;;\n      6)\n        ac_octave_save_QT_HOST_LIBEXECS=\"$QT_HOST_LIBEXECS\"\n        if test -z \"$QT_HOST_LIBEXECS\"; then\n          AC_CHECK_TOOLS(QTPATHS6, [qtpaths6 qtpaths-qt6])\n          if test -n \"$QTPATHS6\"; then\n            QT_HOST_LIBEXECS=\"`$QTPATHS6 --query QT_HOST_LIBEXECS`\"\n          fi\n        fi\n        if test -z \"$QT_HOST_LIBEXECS\"; then\n          AC_CHECK_TOOLS(QMAKE6, [qmake6 qmake-qt6])\n          if test -n \"$QMAKE6\"; then\n            QT_HOST_LIBEXECS=\"`$QMAKE6 -query QT_HOST_LIBEXECS`\"\n          fi\n        fi\n        if test -n \"$QT_HOST_LIBEXECS\"; then\n          case $host_os in\n            mingw*)\n              AC_CHECK_TOOL(CYGPATH, [cygpath])\n              if test -n \"$CYGPATH\"; then\n                QT_HOST_LIBEXECS=\"`$CYGPATH -u $QT_HOST_LIBEXECS`\"\n              fi\n            ;;\n          esac\n        fi\n        ac_octave_save_QT_HOST_BINS=\"$QT_HOST_BINS\"\n        if test -z \"$QT_HOST_BINS\"; then\n          AC_CHECK_TOOLS(QTPATHS6, [qtpaths6 qtpaths-qt6])\n          if test -n \"$QTPATHS6\"; then\n            QT_HOST_BINS=\"`$QTPATHS6 --query QT_HOST_BINS`\"\n          fi\n        fi\n        if test -z \"$QT_HOST_BINS\"; then\n          AC_CHECK_TOOLS(QMAKE6, [qmake6 qmake-qt6])\n          if test -n \"$QMAKE6\"; then\n            QT_HOST_BINS=\"`$QMAKE6 -query QT_HOST_BINS`\"\n          fi\n        fi\n        if test -n \"$QT_HOST_BINS\"; then\n          case $host_os in\n            mingw*)\n              AC_CHECK_TOOL(CYGPATH, [cygpath])\n              if test -n \"$CYGPATH\"; then\n                QT_HOST_BINS=\"`$CYGPATH -u $QT_HOST_BINS`\"\n              fi\n            ;;\n          esac\n        fi\n      ;;\n    esac\n\n    OCTAVE_CHECK_QT_TOOL([moc])\n    OCTAVE_CHECK_QT_TOOL([uic])\n    OCTAVE_CHECK_QT_TOOL([rcc])\n    OCTAVE_CHECK_QT_TOOL([lrelease])\n    OCTAVE_CHECK_QT_TOOL([qhelpgenerator])\n    case \"$qt_version\" in\n      5)\n        OCTAVE_CHECK_QT_TOOL([qcollectiongenerator])\n      ;;\n      6)\n        QCOLLECTIONGENERATOR=\"$QHELPGENERATOR\"\n      ;;\n    esac\n\n    if test -n \"$QT_TOOLS_MISSING\"; then\n      warn_qt_tools=\"one or more of the Qt utilities moc, uic, rcc, lrelease, qcollectiongenerator, and qhelpgenerator not found; disabling Qt GUI\"\n      build_qt_gui=no\n      MOC_QTVER=\n      UIC_QTVER=\n      RCC_QTVER=\n      LRELEASE_QTVER=\n      QCOLLECTIONGENERATOR_QTVER=\n      QHELPGENERATOR_QTVER=\n      MOCFLAGS=\n      UICFLAGS=\n      RCCFLAGS=\n      LRELEASEFLAGS=\n      QCOLLECTIONGENERATORFLAGS=\n      QHELPGENERATORFLAGS=\n      QT_HOST_LIBEXECS=\"$ac_octave_save_QT_HOST_LIBEXECS\"\n      QT_HOST_BINS=\"$ac_octave_save_QT_HOST_BINS\"\n      $as_unset ac_cv_prog_MOC_QTVER\n      $as_unset ac_cv_prog_ac_ct_MOC_QTVER\n      $as_unset ac_cv_prog_UIC_QTVER\n      $as_unset ac_cv_prog_ac_ct_UIC_QTVER\n      $as_unset ac_cv_prog_RCC_QTVER\n      $as_unset ac_cv_prog_ac_ct_RCC_QTVER\n      $as_unset ac_cv_prog_LRELEASE_QTVER\n      $as_unset ac_cv_prog_ac_ct_LRELEASE_QTVER\n      $as_unset ac_cv_prog_QCOLLECTIONGENERATOR_QTVER\n      $as_unset ac_cv_prog_ac_ct_QCOLLECTIONGENERATOR_QTVER\n      $as_unset ac_cv_prog_QHELPGENERATOR_QTVER\n      $as_unset ac_cv_prog_ac_ct_QHELPGENERATOR_QTVER\n    fi\n  fi\n\n  if test $build_qt_gui = yes; then\n    case $host_os in\n      mingw* | msdosmsvc*)\n        AC_CHECK_FUNCS([setvbuf], [win32_terminal=yes],\n          [build_qt_gui=no\n           warn_qt_setvbuf=\"setvbuf not found; disabling Qt GUI\"])\n      ;;\n      *)\n        AC_CHECK_HEADERS([pty.h libutil.h util.h])\n        AC_SEARCH_LIBS([openpty], [util],\n          [AC_DEFINE(HAVE_OPENPTY, 1, [Define to 1 if openpty exists])])\n        AC_CHECK_FUNCS([chmod chown ftruncate mmap munmap], [],\n          [build_qt_gui=no\n           warn_qt_lib_fcns=\"At least one of chmod, chown, ftruncate, mmap, and munmap not found; disabling Qt GUI\"])\n      ;;\n    esac\n  fi\n\n  if test $build_qt_gui = yes; then\n    ## We have what we need to build the Qt GUI.  The remaining\n    ## checks below are for optional features related to the Qt GUI.\n\n    AC_DEFINE(HAVE_QT, 1,\n      [Define to 1 if Qt is available, with all required functions, libraries, developer header files, and utilities.])\n\n    AC_LANG_PUSH(C++)\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    CPPFLAGS=\"$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS\"\n    AC_CHECK_HEADERS([QStandardPaths QtVersionChecks])\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    AC_LANG_POP(C++)\n\n    ## We don't need to unset cache variables for any of the remaining\n    ## tests if they fail because we have already decided that the Qt\n    ## version that we are testing now will be the one used.\n\n    OCTAVE_CHECK_FUNC_QFONTMETRICS_HORIZONTAL_ADVANCE\n    OCTAVE_CHECK_FUNC_QHELPSEARCHQUERYWIDGET_SEARCHINPUT\n    OCTAVE_CHECK_NEW_QHELPINDEXWIDGET_API\n    OCTAVE_CHECK_FUNC_QLIST_ITERATOR_CONSTRUCTOR\n    OCTAVE_CHECK_FUNC_QHELPENGINE_DOCUMENTSFORIDENTIFIER\n    OCTAVE_CHECK_FUNC_QWHEELEVENT_POSITION\n    OCTAVE_CHECK_FUNC_QPAINTER_SETRENDERHINT_LOSSLESS\n    OCTAVE_CHECK_FUNC_QCOLOR_FLOAT_TYPE\n    OCTAVE_CHECK_CLASS_QSTRINGVIEW\n    OCTAVE_CHECK_FUNC_QTEXTSTREAM_SETENCODING\n    OCTAVE_CHECK_ENUM_QT_KEY_MICRO\n    OCTAVE_CHECK_SIGNAL_QCHECKBOX_CHECKSTATECHANGED\n    OCTAVE_CHECK_FUNC_QCOLOR_FROMSTRING\n\n    OCTAVE_CHECK_QREGION_ITERATORS\n    OCTAVE_CHECK_QT_IMCURSORRECTANGLE_ENUM_VALUE\n    OCTAVE_CHECK_QT_SPLITBEHAVIOR_ENUM\n\n    OCTAVE_CHECK_QSCINTILLA([$qt_version])\n\n  fi\n\n  if test $build_qt_gui = no; then\n    QT_CPPFLAGS=\n    QT_LDFLAGS=\n    QT_LIBS=\n  fi\n\n\n  AC_SUBST(MOCFLAGS)\n  AC_SUBST(UICFLAGS)\n  AC_SUBST(RCCFLAGS)\n  AC_SUBST(LRELEASEFLAGS)\n  AC_SUBST(QCOLLECTIONGENERATORFLAGS)\n  AC_SUBST(QHELPGENERATORFLAGS)\n  AC_SUBST(QT_CPPFLAGS)\n  AC_SUBST(QT_LDFLAGS)\n  AC_SUBST(QT_LIBS)\n])\ndnl\ndnl Check if the default Fortran INTEGER is 64 bits wide.\ndnl If cross-compiling, assume 4 bytes unless the cache value\ndnl is already set.\ndnl\nAC_DEFUN([OCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER], [\n  AC_CACHE_CHECK([default size of Fortran INTEGER],\n    [octave_cv_sizeof_fortran_integer],\n    [ac_octave_save_FFLAGS=\"$FFLAGS\"\n     FFLAGS=\"$FFLAGS $F77_INTEGER_8_FLAG\"\n     AC_LANG_PUSH(Fortran 77)\n     AC_RUN_IFELSE([AC_LANG_PROGRAM(,[[\n      integer*8 n8\n      integer n\nc Generate -2**33 + 1.\n      n8 = 2\n      n8 = -4 * (n8 ** 30)\n      n8 = n8 + 1\nc Convert to default integer type.  If the values are no longer equal,\nc assume the default integer size is 32-bits.\n      n = n8\n      if (n .ne. n8) stop 1\n       ]])],\n       octave_cv_sizeof_fortran_integer=8,\n       octave_cv_sizeof_fortran_integer=4,\n       octave_cv_sizeof_fortran_integer=4)\n     AC_LANG_POP(Fortran 77)\n     FFLAGS=\"$ac_octave_save_FFLAGS\"\n  ])\n])\ndnl\ndnl Check for library that exports SUNContext_Create.\ndnl\nAC_DEFUN([OCTAVE_CHECK_SUNDIALS_SUNCONTEXT_CREATE], [\n  ac_octave_save_LIBS=$LIBS\n  LIBS=\"$SUNDIALS_IDA_LIBS $SUNDIALS_NVECSERIAL_LIBS $LIBS\"\n  dnl Check for SUNContext_Create without linking to libsundials_core.\n  dnl That should succeed for SUNDIALS version 6.\n  AC_CHECK_FUNC([SUNContext_Create])\n  LIBS=\"$ac_octave_save_LIBS\"\n  if test \"x$ac_cv_func_SUNContext_Create\" != xyes; then\n    ## SUNDIALS version 7 exports SUNContext_Create from libsundials_core\n    ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_octave_save_LDFLAGS=\"$LDFLAGS\"\n    ac_octave_save_LIBS=\"$LIBS\"\n    LIBS=\"$SUNDIALS_CORE_LIBS $LIBS\"\n    LDFLAGS=\"$SUNDIALS_CORE_LDFLAGS $LDFLAGS\"\n    CPPFLAGS=\"$SUNDIALS_CORE_CPPFLAGS $CPPFLAGS\"\n    ## Unset cache variable from previous check\n    unset ac_cv_func_SUNContext_Create\n    OCTAVE_CHECK_LIB(sundials_core, [SUNDIALS core], [],\n      [sundials_core.h sundials/sundials_core.h], [SUNContext_Create],\n      [], [])\n    CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n    LDFLAGS=\"$ac_octave_save_LDFLAGS\"\n    LIBS=\"$ac_octave_save_LIBS\"\n  fi\n  if test \"x$ac_cv_func_SUNContext_Create\" = xyes \\\n    || test \"x$octave_cv_lib_sundials_core\" = xyes; then\n    ## SUNDIALS prior to version 6 does not need SUNContext_Create\n    AC_DEFINE(HAVE_SUNDIALS_SUNCONTEXT, 1,\n      [Define to 1 if SUNDIALS API uses a SUNContext object.])\n  fi\n])\ndnl\ndnl Check whether SUNDIALS libraries provide a compatible interface.\ndnl The current recommended interface was introduced in SUNDIALS version 4.\ndnl The deprecated interface that Octave currently works to be compatible with\ndnl was introduced in SUNDIALS version 3.\ndnl\nAC_DEFUN([OCTAVE_CHECK_SUNDIALS_COMPATIBLE_API], [\n  ac_octave_save_LIBS=$LIBS\n  LIBS=\"$SUNDIALS_IDA_LIBS $SUNDIALS_NVECSERIAL_LIBS $LIBS\"\n  dnl Current API functions present in SUNDIALS version 4\n  AC_CHECK_FUNCS([IDASetJacFn IDASetLinearSolver SUNLinSol_Dense SUNSparseMatrix_Reallocate])\n  dnl FIXME: The purpose of the following tests is to detect the deprecated\n  dnl API from SUNDIALS version 3, which should only be used if the current\n  dnl API tests above failed. For now, always test for ida_direct.h.\n  AC_CHECK_HEADERS([ida/ida_direct.h ida_direct.h])\n  dnl Each of these is a deprecated analog to the functions listed above.\n  AC_CHECK_FUNCS([IDADlsSetJacFn IDADlsSetLinearSolver SUNDenseLinearSolver])\n  LIBS=$ac_octave_save_LIBS\n  AC_MSG_CHECKING([whether SUNDIALS API provides the necessary functions])\n  if test \"x$ac_cv_func_IDASetJacFn\" = xyes \\\n     && test \"x$ac_cv_func_IDASetLinearSolver\" = xyes \\\n     && test \"x$ac_cv_func_SUNLinSol_Dense\" = xyes; then\n    octave_have_sundials_compatible_api=yes\n  elif test \"x$ac_cv_func_IDADlsSetJacFn\" = xyes \\\n     && test \"x$ac_cv_func_IDADlsSetLinearSolver\" = xyes \\\n     && test \"x$ac_cv_func_SUNDenseLinearSolver\" = xyes; then\n    octave_have_sundials_compatible_api=yes\n  else\n    octave_have_sundials_compatible_api=no\n  fi\n  AC_MSG_RESULT([$octave_have_sundials_compatible_api])\n  if test $octave_have_sundials_compatible_api = no; then\n    warn_sundials_disabled=\"SUNDIALS libraries do not provide an API that is compatible with Octave.  The solvers ode15i and ode15s will be disabled.\"\n    OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])\n  fi\n])\ndnl\ndnl Check whether SUNDIALS IDA uses sunrealtype.\ndnl\nAC_DEFUN([OCTAVE_CHECK_SUNDIALS_SUNREALTYPE], [\n  AC_CACHE_CHECK([whether SUNDIALS IDA uses sunrealtype],\n    [octave_cv_sundials_has_sunrealtype],\n    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #if defined (HAVE_IDA_IDA_H)\n        #  include <ida/ida.h>\n        #elif defined (HAVE_IDA_H)\n        #  include <ida.h>\n        #endif\n        ]], [[\n        sunrealtype test;\n      ]])],\n      octave_cv_sundials_has_sunrealtype=yes,\n      octave_cv_sundials_has_sunrealtype=no)\n  ])\n  if test $octave_cv_sundials_has_sunrealtype = no; then\n    OCTAVE_SUNREALTYPE=realtype\n  else\n    OCTAVE_SUNREALTYPE=sunrealtype\n  fi\n  AC_SUBST(OCTAVE_SUNREALTYPE)\n  AC_DEFINE_UNQUOTED(OCTAVE_SUNREALTYPE, [$OCTAVE_SUNREALTYPE],\n    [Define to the type used for real numbers by SUNDIALS.])\n])\ndnl\ndnl Check whether SUNDIALS IDA library is configured with double\ndnl precision realtype.\ndnl\nAC_DEFUN([OCTAVE_CHECK_SUNDIALS_SIZEOF_REALTYPE], [\n  AC_CACHE_CHECK([whether SUNDIALS IDA is configured with double precision realtype],\n    [octave_cv_sundials_realtype_is_double],\n    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #if defined (HAVE_IDA_IDA_H)\n        #  include <ida/ida.h>\n        #elif defined (HAVE_IDA_H)\n        #  include <ida.h>\n        #endif\n        #include <assert.h>\n        ]], [[\n        static_assert (sizeof (OCTAVE_SUNREALTYPE) == sizeof (double),\n                       \"SUNDIALS is not configured for double precision\");\n      ]])],\n      octave_cv_sundials_realtype_is_double=yes,\n      octave_cv_sundials_realtype_is_double=no)\n  ])\n  if test $octave_cv_sundials_realtype_is_double = no; then\n    warn_sundials_disabled=\"SUNDIALS IDA library not configured with double precision realtype.  The solvers ode15i and ode15s will be disabled.\"\n    OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])\n  fi\n])\ndnl\ndnl Check whether SUNDIALS IDA library has the SUNLINSOL_DENSE linear solver.\ndnl\nAC_DEFUN([OCTAVE_CHECK_SUNDIALS_SUNLINSOL_DENSE], [\n  AC_CHECK_HEADERS([sunlinsol/sunlinsol_dense.h],\n      octave_cv_sundials_sunlinsol_dense=yes,\n      octave_cv_sundials_sunlinsol_dense=no)\n    ])\n  if test $octave_cv_sundials_sunlinsol_dense = yes; then\n    AC_DEFINE(HAVE_SUNDIALS_SUNLINSOL_DENSE, 1,\n      [Define to 1 if SUNDIALS IDA includes the SUNLINSOL_DENSE linear solver.])\n  else\n    warn_sundials_disabled=\"SUNDIALS IDA library does not include the SUNLINSOL_DENSE linear solver.  The solvers ode15i and ode15s will be disabled.\"\n    OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])\n  fi\n])\ndnl\ndnl Check whether SUNDIALS IDA library is configured with SUNLINSOL_KLU\ndnl enabled.\ndnl\nAC_DEFUN([OCTAVE_CHECK_SUNDIALS_SUNLINSOL_KLU], [\n  ## Including <sunlinsol/sunlinsol_klu.h> may depend on including klu.h\n  ## first.  The check for \"klu.h\" needs to have been performed before here.\n  AC_CHECK_HEADERS([sunlinsol/sunlinsol_klu.h], [], [],\n    [#if defined (HAVE_KLU_H)\n     #  include <klu.h>\n     #elif defined (HAVE_KLU_KLU_H)\n     #  include <klu/klu.h>\n     #elif defined (HAVE_SUITESPARSE_KLU_H)\n     #  include <suitesparse/klu.h>\n     #endif\n    ])\n  ## Check for library that exports SUNContext_Create\n  OCTAVE_CHECK_SUNDIALS_SUNCONTEXT_CREATE\n  ## Check for current KLU function name first.\n  ac_octave_save_CPPFLAGS=\"$CPPFLAGS\"\n  ac_octave_save_LDFLAGS=\"$LDFLAGS\"\n  ac_octave_save_LIBS=\"$LIBS\"\n  CPPFLAGS=\"$SUNDIALS_CORE_CPPFLAGS $CPPFLAGS\"\n  LDFLAGS=\"$SUNDIALS_CORE_LDFLAGS $LDFLAGS\"\n  LIBS=\"$SUNDIALS_CORE_LIBS $LIBS\"\n  OCTAVE_CHECK_LIB(sundials_sunlinsolklu, SUNLINSOL_KLU, [],\n    [], [SUNLinSol_KLU], [],\n    [don't use SUNDIALS SUNLINSOL_KLU library, disable ode15i and ode15s sparse Jacobian],\n    [AC_CHECK_FUNCS([SUNLinSol_KLU])\n     AC_CACHE_CHECK([whether compiling a program that calls SUNLinSol_KLU works],\n      [octave_cv_sundials_sunlinsol_klu],\n      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n         #if defined (HAVE_IDA_IDA_H)\n         #  include <ida/ida.h>\n         #elif defined (HAVE_IDA_H)\n         #  include <ida.h>\n         #endif\n         #if defined (HAVE_KLU_H)\n         #include <klu.h>\n         #endif\n         #if defined (HAVE_KLU_KLU_H)\n         #include <klu/klu.h>\n         #endif\n         #if defined (HAVE_SUITESPARSE_KLU_H)\n         #include <suitesparse/klu.h>\n         #endif\n         #if defined (HAVE_SUNLINSOL_SUNLINSOL_KLU_H)\n         #include <sunlinsol/sunlinsol_klu.h>\n         #endif\n         ]], [[\n         #if defined (HAVE_SUNDIALS_SUNCONTEXT)\n         #  if ! defined (SUN_COMM_NULL)\n         #    define SUN_COMM_NULL NULL\n         #  endif\n           SUNContext *sunContext;\n           if (SUNContext_Create (SUN_COMM_NULL, sunContext) < 0)\n             1/0;  // provoke an error\n           SUNLinSol_KLU (0, 0, *sunContext);\n           SUNContext_Free (sunContext);\n         #else\n           SUNLinSol_KLU (0, 0);\n         #endif\n      ]])],\n      octave_cv_sundials_sunlinsol_klu=yes,\n      octave_cv_sundials_sunlinsol_klu=no)\n    ])])\n  if test \"x$octave_cv_sundials_sunlinsol_klu\" = xno; then\n    ## Check for deprecated KLU function name second.\n    OCTAVE_CHECK_LIB(sundials_sunlinsolklu, SUNLINSOL_KLU, [],\n      [], [SUNKLU], [],\n      [don't use SUNDIALS SUNLINSOL_KLU library, disable ode15i and ode15s sparse Jacobian],\n      [AC_CHECK_FUNCS([SUNKLU])\n       AC_CACHE_CHECK([whether compiling a program that calls SUNKLU works],\n        [octave_cv_sundials_sunlinsol_klu],\n        [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n           #if defined (HAVE_IDA_IDA_H)\n           #  include <ida/ida.h>\n           #elif defined (HAVE_IDA_H)\n           #  include <ida.h>\n           #endif\n           #if defined (HAVE_KLU_H)\n           #include <klu.h>\n           #endif\n           #if defined (HAVE_KLU_KLU_H)\n           #include <klu/klu.h>\n           #endif\n           #if defined (HAVE_SUITESPARSE_KLU_H)\n           #include <suitesparse/klu.h>\n           #endif\n           #if defined (HAVE_SUNLINSOL_SUNLINSOL_KLU_H)\n           #include <sunlinsol/sunlinsol_klu.h>\n           #endif\n           ]], [[\n           SUNKLU (0, 0);\n        ]])],\n        octave_cv_sundials_sunlinsol_klu=yes,\n        octave_cv_sundials_sunlinsol_klu=no)\n      ])])\n  fi\n  if test \"x$ac_cv_header_sunlinsol_sunlinsol_klu_h\" = xyes \\\n     && test \"x$octave_cv_sundials_sunlinsol_klu\" = xyes; then\n    AC_DEFINE(HAVE_SUNDIALS_SUNLINSOL_KLU, 1,\n      [Define to 1 if SUNDIALS IDA is configured with SUNLINSOL_KLU enabled.])\n  else\n    warn_sundials_sunlinsol_klu=\"SUNDIALS IDA library not configured with SUNLINSOL_KLU or sunlinsol_klu.h is not usable.  The solvers ode15i and ode15s will not support the sparse Jacobian feature.\"\n    OCTAVE_CONFIGURE_WARNING([warn_sundials_sunlinsol_klu])\n  fi\n  CPPFLAGS=\"$ac_octave_save_CPPFLAGS\"\n  LDFLAGS=\"$ac_octave_save_LDFLAGS\"\n  LIBS=\"$ac_octave_save_LIBS\"\n])\ndnl\ndnl Like AC_CONFIG_FILES, but don't touch the output file if it already\ndnl exists and hasn't changed.\ndnl\nAC_DEFUN([OCTAVE_CONFIG_MOVE_IF_CHANGE_FILES], [\n  m4_foreach_w([elt], [$1], [\n    AC_CONFIG_FILES(elt[-tmp:]patsubst(elt, [.sh$], [.in.sh]))\n    AC_CONFIG_COMMANDS(elt,\n    [$SHELL $srcdir/build-aux/move-if-change ]elt[-tmp ]elt)])])\ndnl\ndnl Add warning to final summary.\ndnl\nAC_DEFUN([OCTAVE_CONFIGURE_WARNING], [\n  AC_MSG_WARN([$][$1])\n  m4_set_add([summary_warning_list], [$1])\n])\ndnl\ndnl Print final summary.\ndnl\nAC_DEFUN([OCTAVE_CONFIGURE_WARNING_SUMMARY], [\n  m4_set_foreach([summary_warning_list], [elt], [\n    if test -n \"[$]elt\"; then\n      AC_MSG_WARN([$]elt)\n      warn_msg_printed=true\n    fi])\n])\ndnl\ndnl Check if the C++ library has the bit_and, bit_or, and bit_xor\ndnl templates defined.\ndnl\nAC_DEFUN([OCTAVE_CXX_BITWISE_OP_TEMPLATES], [\n  AC_CACHE_CHECK([whether bit_and, bit_or, bit_xor are defined in the C++ library],\n    [octave_cv_cxx_bitwise_op_templates],\n    [AC_LANG_PUSH(C++)\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <functional>\n        ]], [[\n        int x = 0;\n        int y = 1;\n        int z1 = std::bit_and<int>() (x, y);\n        int z2 = std::bit_or<int>() (x, y);\n        int z3 = std::bit_xor<int>() (x, y);\n      ]])],\n      octave_cv_cxx_bitwise_op_templates=yes,\n      octave_cv_cxx_bitwise_op_templates=no)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_cxx_bitwise_op_templates = yes; then\n    AC_DEFINE(HAVE_CXX_BITWISE_OP_TEMPLATES, 1,\n      [Define to 1 if C++ library has templated bitwise operators.])\n  fi\n])\ndnl\ndnl Check if the C++ library has functions to access real and imaginary\ndnl parts of complex numbers independently via references.\ndnl\nAC_DEFUN([OCTAVE_CXX_COMPLEX_REFERENCE_ACCESSORS], [\n  AC_CACHE_CHECK([whether complex class can reference components independently],\n    [octave_cv_cxx_complex_reference_accessors],\n    [AC_LANG_PUSH(C++)\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <complex>\n        ]], [[\n        std::complex<double> x;\n        x.real () = 1.0;\n        x.imag () = 1.0;\n      ]])],\n      octave_cv_cxx_complex_reference_accessors=yes,\n      octave_cv_cxx_complex_reference_accessors=no)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_cxx_complex_reference_accessors = yes; then\n    AC_DEFINE(HAVE_CXX_COMPLEX_REFERENCE_ACCESSORS, 1,\n      [Define to 1 if C++ complex class has T& real () and T& imag () methods.])\n  fi\n])\ndnl\ndnl Check if the C++ library has functions to set real and imaginary\ndnl parts of complex numbers independently.\ndnl\nAC_DEFUN([OCTAVE_CXX_COMPLEX_SETTERS], [\n  AC_CACHE_CHECK([whether complex class can set components independently],\n    [octave_cv_cxx_complex_setters],\n    [AC_LANG_PUSH(C++)\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n        #include <complex>\n        ]], [[\n        std::complex<double> x;\n        x.real (1.0);\n        x.imag (2.0);\n      ]])],\n      octave_cv_cxx_complex_setters=yes, octave_cv_cxx_complex_setters=no)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_cxx_complex_setters = yes; then\n    AC_DEFINE(HAVE_CXX_COMPLEX_SETTERS, 1,\n      [Define to 1 if C++ complex class has void real (T) and void imag (T) methods.])\n  fi\n])\ndnl\ndnl Check if the compiler supports dynamic auto arrays.\ndnl\nAC_DEFUN([OCTAVE_CXX_DYNAMIC_AUTO_ARRAYS], [\n  AC_CACHE_CHECK([whether C++ supports dynamic auto arrays],\n    [octave_cv_cxx_dynamic_auto_arrays],\n    [AC_LANG_PUSH(C++)\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[\n        void test(char *);\n        int length();\n        char x[length()];\n        test(x);\n      ]])],\n      octave_cv_cxx_dynamic_auto_arrays=yes,\n      octave_cv_cxx_dynamic_auto_arrays=no)\n    AC_LANG_POP(C++)\n  ])\n  if test $octave_cv_cxx_dynamic_auto_arrays = yes; then\n    AC_DEFINE(HAVE_DYNAMIC_AUTO_ARRAYS, 1,\n      [Define to 1 if C++ supports dynamic auto arrays.])\n  fi\n])\ndnl\ndnl Check if C++ compiler handles FLAG command line option.  If two\ndnl arguments are specified, execute the second arg as shell commands.\ndnl Otherwise, add FLAG to CXXFLAGS if the compiler accepts the flag.\ndnl\nAC_DEFUN([OCTAVE_CXX_FLAG], [\n  ac_safe=`echo \"$1\" | $SED 'y%./+-:=%__p___%'`\n  AC_MSG_CHECKING([whether ${CXX-g++} accepts $1])\n  AC_CACHE_VAL([octave_cv_cxx_flag_$ac_safe],\n    [AC_LANG_PUSH(C++)\n    ac_octave_save_CXXFLAGS=\"$CXXFLAGS\"\n    CXXFLAGS=\"$CXXFLAGS $1\"\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],\n      eval \"octave_cv_cxx_flag_$ac_safe=yes\",\n      eval \"octave_cv_cxx_flag_$ac_safe=no\")\n    CXXFLAGS=\"$ac_octave_save_CXXFLAGS\"\n    AC_LANG_POP(C++)\n  ])\n  if eval \"test \\\"`echo '$octave_cv_cxx_flag_'$ac_safe`\\\" = yes\"; then\n    AC_MSG_RESULT([yes])\n    ifelse([$2], ,\n      [CXXFLAGS=\"$CXXFLAGS $1\"\n      AC_MSG_RESULT([adding $1 to CXXFLAGS])], [$2])\n  else\n    AC_MSG_RESULT([no])\n    ifelse([$3], , , [$3])\n  fi\n])\ndnl\ndnl OCTAVE_DEFINE_MKOCTFILE_DYNAMIC_LINK_OPTIONS\ndnl\ndnl Requires the following variables to already be set:\ndnl\ndnl   AR\ndnl   CFLAGS\ndnl   CXX\ndnl   CXXFLAGS\ndnl   EXEEXT\ndnl   GCC\ndnl   GREP\ndnl   GXX\ndnl   LDFLAGS\ndnl   ac_cv_f77_compiler_gnu\ndnl   canonical_host_type\ndnl   have_msvc\ndnl\nAC_DEFUN_ONCE([OCTAVE_DEFINE_MKOCTFILE_DYNAMIC_LINK_OPTIONS], [\n  ### Set system-dependent options for building shared libraries.\n  ### These are used by mkoctfile to create dynamically loadable\n  ### .oct and .mex files.  It would be great if we could somehow\n  ### use libtool to get this information.\n\n  CPICFLAG=-fPIC\n  CXXPICFLAG=-fPIC\n  FPICFLAG=-fPIC\n  SH_LDFLAGS=-shared\n  DL_LDFLAGS=\"${SH_LDFLAGS}\"\n  MKOCTFILE_DL_LDFLAGS=\"${DL_LDFLAGS}\"\n  NO_OCT_FILE_STRIP=false\n  TEMPLATE_AR=\"${AR}\"\n  TEMPLATE_ARFLAGS=\"${ARFLAGS}\"\n  library_path_var=LD_LIBRARY_PATH\n  ldpreloadsep=\" \"\n  case $canonical_host_type in\n    *-*-386bsd* | *-*-netbsd*)\n      SH_LDFLAGS=-Bshareable\n    ;;\n    *-*-openbsd*)\n      SH_LDFLAGS=\"-shared -fPIC\"\n    ;;\n    *-*-freebsd*)\n      SH_LDFLAGS=\"-shared -Wl,-x\"\n    ;;\n    alpha*-dec-osf*)\n      CPICFLAG=\n      CXXPICFLAG=\n      FPICFLAG=\n      SH_LDFLAGS=\"-shared -Wl,-expect_unresolved -Wl,'*'\"\n    ;;\n    *-*-darwin*)\n      DL_LDFLAGS=\"-bundle -undefined dynamic_lookup -bind_at_load\"\n      MKOCTFILE_DL_LDFLAGS=\"-bundle -undefined dynamic_lookup -bind_at_load\"\n      SH_LDFLAGS=\"-dynamiclib -single_module\"\n      case $canonical_host_type in\n        powerpc-*)\n          CXXPICFLAG=\n          CPICFLAG=\n          FPICFLAG=\n        ;;\n      esac\n      NO_OCT_FILE_STRIP=true\n      library_path_var=DYLD_LIBRARY_PATH\n    ;;\n    *-*-cygwin*)\n      CPICFLAG=\n      CXXPICFLAG=\n      FPICFLAG=\n      DL_LDFLAGS=\"-shared -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc\"\n      SH_LDFLAGS=\"-shared -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-auto-image-base\"\n      ldpreloadsep=\":\"\n    ;;\n    *-*-mingw*)\n      if test $have_msvc = yes; then\n        DL_LDFLAGS=\"-shared\"\n        CPICFLAG=\n        CXXPICFLAG=\n        FPICFLAG=\n        SH_LDFLAGS=\"-shared\"\n        if test -n \"`echo $CFLAGS | $GREP -e '-g'`\" || test -n \"`echo $CXXFLAGS | $GREP -e '-g'`\"; then\n          DL_LDFLAGS=\"$DL_LDFLAGS -g\"\n          SH_LDFLAGS=\"$SH_LDFLAGS -g\"\n        fi\n        NO_OCT_FILE_STRIP=true\n        library_path_var=PATH\n      else\n        CPICFLAG=\n        CXXPICFLAG=\n        FPICFLAG=\n        DL_LDFLAGS=\"-shared -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc\"\n        SH_LDFLAGS=\"-shared -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-auto-image-base\"\n        library_path_var=PATH\n      fi\n    ;;\n    *-*-msdosmsvc)\n      DL_LDFLAGS=\"-shared\"\n      CPICFLAG=\n      CXXPICFLAG=\n      FPICFLAG=\n      SH_LDFLAGS=\"-shared\"\n      if test -n \"`echo $CFLAGS | $GREP -e '-g'`\" || test -n \"`echo $CXXFLAGS | $GREP -e '-g'`\"; then\n        DL_LDFLAGS=\"$DL_LDFLAGS -g\"\n        SH_LDFLAGS=\"$SH_LDFLAGS -g\"\n      fi\n      NO_OCT_FILE_STRIP=true\n      library_path_var=PATH\n    ;;\n    *-*-linux* | *-*-gnu*)\n      MKOCTFILE_DL_LDFLAGS=\"-shared -Wl,-Bsymbolic\"\n    ;;\n    i[[3456]]86-*-sco3.2v5*)\n      SH_LDFLAGS=-G\n    ;;\n    rs6000-ibm-aix* | powerpc-ibm-aix*)\n      CPICFLAG=\n      CXXPICFLAG=\n      FPICFLAG=\n      library_path_var=LIBPATH\n    ;;\n    hppa*-hp-hpux*)\n      if test $ac_cv_f77_compiler_gnu = yes; then\n        FPICFLAG=-fPIC\n      else\n        FPICFLAG=+Z\n      fi\n      SH_LDFLAGS=\"-shared -fPIC\"\n      library_path_var=SHLIB_PATH\n    ;;\n    ia64*-hp-hpux*)\n      if test $ac_cv_f77_compiler_gnu = yes; then\n        FPICFLAG=-fPIC\n      else\n        FPICFLAG=+Z\n      fi\n      SH_LDFLAGS=\"-shared -fPIC\"\n    ;;\n    *-sgi-*)\n      CPICFLAG=\n      CXXPICFLAG=\n      FPICFLAG=\n    ;;\n    sparc-sun-sunos4*)\n      if test $ac_cv_f77_compiler_gnu = yes; then\n        FPICFLAG=-fPIC\n      else\n        FPICFLAG=-PIC\n      fi\n      SH_LDFLAGS=\"-assert nodefinitions\"\n    ;;\n    sparc-sun-solaris2* | i386-pc-solaris2*)\n      if test $ac_cv_f77_compiler_gnu = yes; then\n        FPICFLAG=-fPIC\n      else\n        FPICFLAG=-KPIC\n      fi\n      if test \"$GCC\" = yes; then\n        CPICFLAG=-fPIC\n      else\n        CPICFLAG=-KPIC\n      fi\n      if test \"$GXX\" = yes; then\n        CXXPICFLAG=-fPIC\n        SH_LDFLAGS=-shared\n      else\n        CXXPICFLAG=-KPIC\n        SH_LDFLAGS=-G\n      fi\n      ## Template closures in archive libraries need a different mechanism.\n      if test \"$GXX\" != yes; then\n        TEMPLATE_AR=\"${CXX}\"\n        TEMPLATE_ARFLAGS=\"-xar -o\"\n      fi\n    ;;\n  esac\n\n  AC_MSG_NOTICE([defining FPICFLAG to be $FPICFLAG])\n  AC_MSG_NOTICE([defining CPICFLAG to be $CPICFLAG])\n  AC_MSG_NOTICE([defining CXXPICFLAG to be $CXXPICFLAG])\n  AC_MSG_NOTICE([defining SH_LDFLAGS to be $SH_LDFLAGS])\n  AC_MSG_NOTICE([defining DL_LDFLAGS to be $DL_LDFLAGS])\n  AC_MSG_NOTICE([defining MKOCTFILE_DL_LDFLAGS to be $MKOCTFILE_DL_LDFLAGS])\n  AC_MSG_NOTICE([defining NO_OCT_FILE_STRIP to be $NO_OCT_FILE_STRIP])\n  AC_MSG_NOTICE([defining TEMPLATE_AR to be $TEMPLATE_AR])\n  AC_MSG_NOTICE([defining TEMPLATE_ARFLAGS to be $TEMPLATE_ARFLAGS])\n  AC_MSG_NOTICE([defining library_path_var to be $library_path_var])\n  AC_SUBST(FPICFLAG)\n  AC_SUBST(CPICFLAG)\n  AC_SUBST(CXXPICFLAG)\n  AC_SUBST(SH_LDFLAGS)\n  AC_SUBST(DL_LDFLAGS)\n  AC_SUBST(MKOCTFILE_DL_LDFLAGS)\n  AC_SUBST(NO_OCT_FILE_STRIP)\n  AC_SUBST(TEMPLATE_AR)\n  AC_SUBST(TEMPLATE_ARFLAGS)\n  AC_SUBST(library_path_var)\n  AC_SUBST(ldpreloadsep)\n  AM_SUBST_NOTMAKE(ldpreloadsep)\n])\ndnl\ndnl Allow the user disable support for command line editing using GNU\ndnl readline.\ndnl\nAC_DEFUN([OCTAVE_ENABLE_READLINE], [\n  USE_READLINE=yes\n  AC_ARG_ENABLE([readline],\n    [AS_HELP_STRING([--disable-readline],\n      [do not use readline library])],\n    [if test \"$enableval\" = no; then\n       USE_READLINE=no\n       warn_readline=\"command editing and history features require GNU Readline\"\n     fi])\n  if test $USE_READLINE = yes; then\n    gl_FUNC_READLINE\n    if test \"$gl_cv_lib_readline\" != no; then\n      AC_DEFINE(USE_READLINE, 1, [Define to 1 to use the readline library.])\n    else\n      AC_MSG_WARN([I need GNU Readline 4.2 or later])\n      AC_MSG_ERROR([this is fatal unless you specify --disable-readline])\n    fi\n  fi\n])\ndnl\ndnl Check if Fortran compiler handles FLAG command line option.  If\ndnl two arguments are specified, execute the second arg as shell\ndnl commands.  Otherwise, add FLAG to FFLAGS if the compiler accepts\ndnl the flag.\ndnl\nAC_DEFUN([OCTAVE_F77_FLAG], [\n  ac_safe=`echo \"$1\" | $SED 'y%./+-:=%__p___%'`\n  AC_MSG_CHECKING([whether ${F77-g77} accepts $1])\n  AC_CACHE_VAL([octave_cv_f77_flag_$ac_safe], [\n    AC_LANG_PUSH(Fortran 77)\n    ac_octave_save_FFLAGS=\"$FFLAGS\"\n    FFLAGS=\"$FFLAGS $1\"\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],\n      eval \"octave_cv_f77_flag_$ac_safe=yes\",\n      eval \"octave_cv_f77_flag_$ac_safe=no\")\n    FFLAGS=\"$ac_octave_save_FFLAGS\"\n    AC_LANG_POP(Fortran 77)\n  ])\n  if eval \"test \\\"`echo '$octave_cv_f77_flag_'$ac_safe`\\\" = yes\"; then\n    AC_MSG_RESULT([yes])\n    ifelse([$2], ,\n      [FFLAGS=\"$FFLAGS $1\"\n      AC_MSG_RESULT([adding $1 to FFLAGS])], [$2])\n  else\n    AC_MSG_RESULT([no])\n    ifelse([$3], , , [$3])\n  fi\n])\ndnl\ndnl Check to see if the compiler and the linker can handle the flags\ndnl \"-framework $1\" for the given prologue $2 and the given body $3 of\ndnl a source file.  Arguments 2 and 3 optionally can also be empty.\ndnl Add options (lower case letters $1) \"--with-framework-$1\" and\ndnl \"--without-framework-$1\".  If this test is successful then perform\ndnl $4, otherwise do $5.\ndnl\nAC_DEFUN([OCTAVE_HAVE_FRAMEWORK], [\n  AC_MSG_CHECKING([whether ${LD-ld} accepts -framework $1])\n  AC_CACHE_VAL([octave_cv_framework_$1],\n    [ac_octave_save_LDFLAGS=\"$LDFLAGS\"\n    LDFLAGS=\"$LDFLAGS -framework $1\"\n    AC_LANG_PUSH(C++)\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([$2], [$3])],\n      eval \"octave_cv_framework_$1=yes\",\n      eval \"octave_cv_framework_$1=no\")\n    AC_LANG_POP(C++)\n    LDFLAGS=\"$ac_octave_save_LDFLAGS\"\n  ])\n  if test \"$octave_cv_framework_$1\" = yes; then\n    AC_MSG_RESULT([yes])\n    AC_ARG_WITH(framework-m4_tolower($1),\n      [AS_HELP_STRING([--without-framework-m4_tolower($1)],\n        [don't use framework $1])],\n         with_have_framework=$withval, with_have_framework=yes)\n    if test \"$with_have_framework\" = yes; then\n      [$4]\n      :\n    else\n      AC_MSG_NOTICE([framework rejected by --without-framework-m4_tolower($1)])\n      [$5]\n    fi\n  else\n    AC_MSG_RESULT([no])\n    [$5]\n  fi\n])\ndnl\ndnl Check for IEEE 754 data format.\ndnl\nAC_DEFUN([OCTAVE_IEEE754_DATA_FORMAT], [\n  AC_MSG_CHECKING([for IEEE 754 data format])\n  AC_CACHE_VAL([octave_cv_ieee754_data_format],\n    [AC_RUN_IFELSE([AC_LANG_SOURCE([[\n        int\n        main (void)\n        {\n          typedef union { unsigned char c[8]; double d; } ieeebytes;\n\n          ieeebytes l = {0x1c, 0xbc, 0x6e, 0xf2, 0x54, 0x8b, 0x11, 0x43};\n          ieeebytes b = {0x43, 0x11, 0x8b, 0x54, 0xf2, 0x6e, 0xbc, 0x1c};\n\n          return l.d != 1234567891234567.0 && b.d != 1234567891234567.0;\n        }\n      ]])],\n      octave_cv_ieee754_data_format=yes,\n      octave_cv_ieee754_data_format=no,\n      octave_cv_ieee754_data_format=yes)\n  ])\n  if test \"$cross_compiling\" = yes; then\n    AC_MSG_RESULT([$octave_cv_ieee754_data_format assumed for cross compilation])\n  else\n    AC_MSG_RESULT([$octave_cv_ieee754_data_format])\n  fi\n  if test $octave_cv_ieee754_data_format = yes; then\n    AC_DEFINE(HAVE_IEEE754_DATA_FORMAT, 1,\n      [Define to 1 if your system uses IEEE 754 data format.])\n  else\n    ## If the format is unknown, then you will probably not have a\n    ## useful system, so we will abort here.  Anyone wishing to\n    ## experiment with building Octave on a system without IEEE\n    ## floating point should be capable of removing this check and\n    ## the one in the octave_ieee_init function in liboctave/lo-ieee.cc.\n    AC_MSG_ERROR([IEEE 754 data format required for building Octave])\n  fi\n])\ndnl\ndnl Check if MIPS processor is target and quiet signalling NaN value is\ndnl opposite of IEEE 754-2008 standard used by all other architectures.\ndnl\nAC_DEFUN([OCTAVE_IEEE754_QNAN], [\n  AC_CACHE_CHECK([whether quiet NaN values are conformant to IEEE 754-2008],\n    [octave_cv_ieee754_qnan],\n    [AC_LANG_PUSH(C)\n    AC_RUN_IFELSE([AC_LANG_PROGRAM([[\n        #include <math.h>\n        #include <stdint.h>\n        #include <string.h>\n        ]], [[\n        /* The MSB of the mantissa of quiet NaN values is set to 1 according\n         * to IEEE 754-2008.  That is not the case for some architectures,\n         * e.g., MIPS.  */\n        double qNaN = NAN;  // quiet NaN\n        uint64_t bits;\n        memcpy (&bits, &qNaN, sizeof (qNaN));\n        if (bits & (1ULL << 51))\n          /* quiet NaN conformant to IEEE 754-2008 */\n          return 0;\n        else\n          /* quiet NaN not conformant to IEEE 754-2008 */\n          return 1;\n      ]])],\n      octave_cv_ieee754_qnan=yes,\n      octave_cv_ieee754_qnan=no,\n      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n          ]], [[\n          /* When cross-compiling, only test whether MIPS is the target\n           * architecture.\n           * FIXME: Add more conditions as needed.  */\n          #if defined (__mips__) || defined (mips) || defined (__mips) || defined (__MIPS__)\n          #  error \"quiet NaN on MIPS is not conformant to IEEE 754-2008\"\n          #endif\n        ]])],\n        octave_cv_ieee754_qnan=yes,\n        octave_cv_ieee754_qnan=no)\n    ])\n    AC_LANG_POP(C)\n  ])\n  if test $octave_cv_ieee754_qnan = yes; then\n    AC_DEFINE(HAVE_IEEE754_QNAN, 1,\n      [Define to 1 if quiet NaN values are encoded according to IEEE 754-2008.])\n  fi\n])\ndnl\ndnl Check if the payload of quiet NaN values is retained on arithmetic\ndnl operations.  That is needed for consistent NA handling.\ndnl\nAC_DEFUN([OCTAVE_QNAN_WITH_PAYLOAD], [\n  AC_CACHE_CHECK([whether quiet NaN values retain payload on arithmetic operations],\n    [octave_cv_qnan_with_payload],\n    [AC_LANG_PUSH(C)\n    AC_RUN_IFELSE([AC_LANG_PROGRAM([[\n        #include <math.h>\n        #include <stdint.h>\n        #include <string.h>\n        ]], [[\n        /* Quiet NaNs retain the \"payload\" (i.e., the value of the mantissa)\n         * when performing arithmetic operations.  That is not the case for\n         * some architectures, e.g., RISC-V.  */\n\n        #if defined (HAVE_IEEE754_QNAN)\n        #  define LO_IEEE_NA_HW 0x7FF840F4\n        #else\n        #  define LO_IEEE_NA_HW 0x7FF040F4\n        #endif\n        #define LO_IEEE_NA_LW 0x40000000\n        uint32_t word_NA[2];\n        volatile double oct_NA;\n        uint64_t bits_NA;\n        uint64_t bits_NA_1;\n\n        /* Check whether platform is Big Endian */\n        union\n        {\n          long l;\n          char c[sizeof (long)];\n        } u;\n        u.l = 1;\n\n        /* value used as NA in Octave */\n        if (u.c[sizeof (long) - 1] == 1)\n          {\n            /* Big Endian */\n            word_NA[0] = LO_IEEE_NA_HW;\n            word_NA[1] = LO_IEEE_NA_LW;\n          }\n        else\n          {\n            /* Little Endian */\n            word_NA[1] = LO_IEEE_NA_HW;\n            word_NA[0] = LO_IEEE_NA_LW;\n          }\n\n        memcpy ((void *) &oct_NA, &word_NA, sizeof (oct_NA));\n\n        memcpy (&bits_NA, (const void *) &oct_NA, sizeof (oct_NA));\n        oct_NA += 1.0;\n        memcpy (&bits_NA_1, (const void *) &oct_NA, sizeof (oct_NA));\n        if (bits_NA == bits_NA_1)\n          /* payload of quiet NaN was retained */\n          return 0;\n        else\n          /* payload of quiet NaN was not retained */\n          return 1;\n      ]])],\n      octave_cv_qnan_with_payload=yes,\n      octave_cv_qnan_with_payload=no,\n      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n          ]], [[\n          /* When cross-compiling, only test whether the target architecture is\n           * RISC-V.\n           * FIXME: Add more conditions as needed.  */\n          #if defined(__riscv)\n          #  error \"quiet NaN values do not retain the payload on arithmetic operations\"\n          #endif\n        ]])],\n        octave_cv_qnan_with_payload=yes,\n        octave_cv_qnan_with_payload=no)\n    ])\n    AC_LANG_POP(C)\n  ])\n  if test $octave_cv_qnan_with_payload = yes; then\n    AC_DEFINE(HAVE_QNAN_WITH_PAYLOAD, 1,\n      [Define to 1 if quiet NaN values retain their payload on arithmetic operations.])\n  fi\n])\ndnl\ndnl Check for ar.\ndnl\nAC_DEFUN([OCTAVE_PROG_AR], [\n  if test -z \"$AR\"; then\n    AR=ar\n  fi\n  AC_SUBST(AR)\n\n  if test -z \"$ARFLAGS\"; then\n    ARFLAGS=\"cr\"\n  fi\n  AC_SUBST(ARFLAGS)\n\n  dnl FIXME: Remove when libtool updated (placed 4/15/2017).\n  dnl This silences the following unnecessary warning during compile:\n  dnl ar: `u' modifier ignored since `D' is the default (see `U')\n  if test -z \"$AR_FLAGS\"; then\n    AR_FLAGS=\"$ARFLAGS\"\n  fi\n])\ndnl\ndnl Check for bison.\ndnl\nAC_DEFUN([OCTAVE_PROG_BISON], [\n  dnl FIXME: What is our actual required minimum version for Bison?\n  gl_PROG_BISON([BISON], [3.0])\n  WARN_BISONFLAGS=\n\n  case \"`$BISON --version`\" in\n    *bison*) tmp_have_bison=yes ;;\n    *) tmp_have_bison=no ;;\n  esac\n\n  if test $tmp_have_bison = yes; then\n    WARN_BISONFLAGS=\"-Wno-yacc\"\n\n    AC_CACHE_CHECK([syntax of bison api.prefix (or name-prefix) declaration],\n                   [octave_cv_bison_api_prefix_decl_style], [\n      style=\"api name\"\n      quote=\"quote brace\"\n      for s in $style; do\n        for q in $quote; do\n          if test $s = \"api\"; then\n            if test $q = \"quote\"; then\n              def='%define api.prefix \"foo_\"'\n            else\n              def='%define api.prefix {foo_}'\n            fi\n          else\n            if test $q = \"quote\"; then\n              def='%name-prefix=\"foo_\"'\n            else\n              def='%name-prefix {foo_}'\n            fi\n          fi\n          cat << EOF > conftest.yy\n$def\n%start input\n%%\ninput:;\n%%\nEOF\n          ## Older versions of bison only warn and exit with success.\n          octave_bison_output=`$BISON $WARN_BISONFLAGS conftest.yy 2>&1`\n          ac_status=$?\n          if test $ac_status -eq 0 && test -z \"$octave_bison_output\"; then\n            octave_cv_bison_api_prefix_decl_style=\"$s $q\"\n            break\n          fi\n        done\n        if test -n \"$octave_cv_bison_api_prefix_decl_style\"; then\n          break\n        fi\n      done\n      rm -f conftest.yy y.tab.h y.tab.c\n      ])\n\n    AC_CACHE_CHECK([whether api.prefix applies to yysymbol_kind_t],\n                   [octave_cv_bison_api_prefix_applies_to_yysymbol_kind_t], [\n      [case \"$octave_cv_bison_api_prefix_decl_style\" in\n        \"api brace\")\n          def='%define api.prefix {PREFIX_}'\n        ;;\n        \"api quote\")\n          def='%define api.prefix \"PREFIX_\"'\n        ;;\n        \"name brace\")\n          def='%define name-prefix {PREFIX_}'\n        ;;\n        \"name quote\")\n          def='%define name-prefix \"PREFIX_\"'\n        ;;\n      esac]\n      cat << EOF > conftest.yy\n$def\n%start input\n%%\ninput:;\n%%\nEOF\n      ## Older versions of bison only warn and exit with success.\n      $BISON $WARN_BISONFLAGS --defines --output conftest.cc conftest.yy\n      if grep PREFIX_symbol_kind_t conftest.cc > /dev/null; then\n        octave_cv_bison_api_prefix_applies_to_yysymbol_kind_t=yes\n      else\n        octave_cv_bison_api_prefix_applies_to_yysymbol_kind_t=no\n      fi\n      rm -f conftest.yy y.tab.h conftest.cc\n      ])\n  fi\n\n  if test -z \"$octave_cv_bison_api_prefix_decl_style\" \\\n    || test \"$octave_cv_bison_api_prefix_decl_style\" != \"api brace\"; then\n    tmp_have_bison=no\n    warn_bison_api_prefix_decl_style=\"\n\nI wasn't able to find a suitable style for declaring the api prefix\nin a bison input file so I'm disabling bison.  We expect bison to\nunderstand the '%define api.prefix { PREFIX }' syntax.\n\"\n    OCTAVE_CONFIGURE_WARNING([warn_bison_api_prefix_decl_style])\n  fi\n\n  if test $tmp_have_bison = no; then\n    BISON='${top_srcdir}/build-aux/missing bison'\n    warn_bison=\"\n\nI didn't find bison, or the version of bison that I found does not\nsupport all the features that are required, but it's only a problem\nif you need to reconstruct parse.cc, which is the case if you're\nbuilding from VCS sources.\n\"\n    OCTAVE_CONFIGURE_WARNING([warn_bison])\n\n  fi\n  if test \"$octave_cv_bison_api_prefix_applies_to_yysymbol_kind_t\" = no; then\n    OCTAVE_PARSER_CPPFLAGS=\"-Dyysymbol_kind_t=octave_symbol_kind_t\"\n    OCTAVE_TEX_PARSER_CPPFLAGS=\"-Dyysymbol_kind_t=octave_tex_symbol_kind_t\"\n  fi\n  AC_SUBST(OCTAVE_PARSER_CPPFLAGS)\n  AC_SUBST(OCTAVE_TEX_PARSER_CPPFLAGS)\n])\ndnl\ndnl Find find program.\ndnl\n## Prefer GNU find if found.\nAN_MAKEVAR([FIND],  [OCTAVE_PROG_FIND])\nAN_PROGRAM([gfind], [OCTAVE_PROG_FIND])\nAN_PROGRAM([find],  [OCTAVE_PROG_FIND])\nAC_DEFUN([OCTAVE_PROG_FIND], [\n  AC_CHECK_PROGS(FIND, [gfind find])\n])\ndnl\ndnl Check for flex.\ndnl\nAC_DEFUN([OCTAVE_PROG_FLEX], [\n  ## For now, don't define LEXLIB to be -lfl -- we don't use anything in\n  ## it, and it might not be installed.\n  ##\n  ## Also make sure that we generate an interactive scanner if we are\n  ## using flex.\ndnl We declare %noyywrap in the lexer files so we use the noyywrap\ndnl option here to skip the search for that function.\n  AC_PROG_LEX([noyywrap])\n  case \"`$LEX --version`\" in\n    *flex*)\n      LFLAGS=\"-I\"\n      AC_MSG_RESULT([defining LFLAGS to be $LFLAGS])\n      LEXLIB=\n    ;;\n    *)\n      LEX='${top_srcdir}/build-aux/missing flex'\n      warn_flex=\"\n\nI didn't find flex, but it's only a problem if you need to reconstruct\nlex.cc, which is the case if you're building from VCS sources.\n\"\n      OCTAVE_CONFIGURE_WARNING([warn_flex])\n    ;;\n  esac\n  AC_SUBST(LFLAGS)\n])\ndnl\ndnl Check for ghostscript.\ndnl\nAC_DEFUN([OCTAVE_PROG_GHOSTSCRIPT], [\n  case \"$canonical_host_type\" in\n    *-*-mingw* | *-*-msdosmsvc)\n      ac_octave_gs_names=\"gs gswin32c gswin64c mgs\"\n    ;;\n    *)\n      ac_octave_gs_names=\"gs\"\n    ;;\n  esac\n  AC_CHECK_PROGS(GHOSTSCRIPT, [$ac_octave_gs_names])\n  if test -z \"$GHOSTSCRIPT\"; then\n    GHOSTSCRIPT='${top_srcdir}/build-aux/missing gs'\n    warn_ghostscript=\"\n\nI didn't find ghostscript, so reconstructing figures for the manual\nwill fail, and saving graphics in some output formats will fail when\nusing Octave\n\"\n    OCTAVE_CONFIGURE_WARNING([warn_ghostscript])\n  fi\n  AC_SUBST(GHOSTSCRIPT)\n])\ndnl\ndnl Check for gnuplot.\ndnl\nAC_DEFUN([OCTAVE_PROG_GNUPLOT], [\n  ac_octave_gp_names=\"gnuplot\"\n  ac_octave_gp_default=\"gnuplot\"\n  if test \"$cross_compiling\" = yes; then\n    GNUPLOT=\"$ac_octave_gp_default\"\n    GNUPLOT_BINARY=$GNUPLOT\n    AC_MSG_RESULT([assuming $GNUPLOT exists on $canonical_host_type host])\n  else\n    AC_CHECK_PROGS(GNUPLOT, [$ac_octave_gp_names])\n    GNUPLOT_BINARY=$GNUPLOT\n    if test -z \"$GNUPLOT\"; then\n      GNUPLOT=\"$ac_octave_gp_default\"\n      GNUPLOT_BINARY=\"\"\n      warn_gnuplot=\"\n\ngnuplot not found.  It isn't necessary to have gnuplot installed, but\nwithout native graphics or gnuplot you won't be able to use any of\nOctave's plotting commands.\n\"\n      OCTAVE_CONFIGURE_WARNING([warn_gnuplot])\n    fi\n  fi\n  AC_SUBST(GNUPLOT)\n])\ndnl\ndnl Check for gperf.\ndnl\nAC_DEFUN([OCTAVE_PROG_GPERF], [\n  AC_CHECK_PROG(GPERF, gperf, gperf, [])\n  if test -z \"$GPERF\"; then\n    GPERF='${top_srcdir}/build-aux/missing gperf'\n    warn_gperf=\"\n\nI didn't find gperf, but it's only a problem if you need to\nreconstruct oct-gperf.h\n\"\n    OCTAVE_CONFIGURE_WARNING([warn_gperf])\n    GPERF='${top_srcdir}/build-aux/missing gperf'\n  fi\n  AC_SUBST(GPERF)\n])\ndnl\ndnl Find icotool program.\ndnl\nAC_DEFUN([OCTAVE_PROG_ICOTOOL], [\n  AC_CHECK_PROG(ICOTOOL, icotool, icotool, [])\n  if test -z \"$ICOTOOL\"; then\n    ICOTOOL='${top_srcdir}/build-aux/missing icotool'\n    warn_icotool=\"\n\nI didn't find icotool, but it's only a problem if you need to\nreconstruct octave-logo.ico, which is the case if you're building from\nVCS sources.\n\"\n    OCTAVE_CONFIGURE_WARNING([warn_icotool])\n  fi\n  AC_SUBST(ICOTOOL)\n])\ndnl\ndnl Check for makeinfo.\ndnl\nAC_DEFUN([OCTAVE_PROG_MAKEINFO], [\n  dnl use MKINFO, not MAKEINFO, for variable name because Automake\n  dnl automatically defines a value for MAKEINFO even when it does not\n  dnl exist which will then fool the 'test -z' line.\n  AC_CHECK_PROG(MKINFO, makeinfo, makeinfo, [])\n  if test -z \"$MKINFO\"; then\n    warn_makeinfo=\"\n\nI didn't find makeinfo, which is required for reading documentation.\nYou may install a copy later for Octave to use.\n\"\n    OCTAVE_CONFIGURE_WARNING([warn_makeinfo])\n  fi\n  dnl If we have a GNU makeinfo program, see if it supports the @sortas command\n  dnl for defining a custom sort key for an index entry.\n  if test -n \"$MKINFO\"; then\n    AC_CACHE_CHECK([for makeinfo support for @sortas command],\n      [octave_cv_makeinfo_sortas_command],\n      [cat << EOF > conftest.texi\n\\input texinfo\n@node Top\n@top Document\n@menu\n* Chapter::\n* Index::\n@end menu\n@node Chapter\n@chapter Chapter\n@cindex @sortas{a} foo\n@node Index\n@unnumbered Index\n@printindex cp\n@bye\nEOF\n        if $MKINFO --no-warn conftest.texi 2>/dev/null; then\n          octave_cv_makeinfo_sortas_command=yes\n        else\n          octave_cv_makeinfo_sortas_command=no\n        fi\n        rm -f conftest.info conftest.texi\n    ])\n    if test $octave_cv_makeinfo_sortas_command = no; then\n      warn_makeinfo=\"\n\nI wasn't able to find a version of GNU makeinfo that supports the\n@sortas command, but it's only a problem if you need to build the\nmanual, which is the case if you're building from VCS sources.\n\"\n      OCTAVE_CONFIGURE_WARNING([warn_makeinfo])\n    fi\n  fi\n])\ndnl\ndnl What pager should we use?\ndnl\nAC_DEFUN([OCTAVE_PROG_PAGER], [\n  if test \"$cross_compiling\" = yes; then\n    DEFAULT_PAGER=less\n    AC_MSG_RESULT([assuming $DEFAULT_PAGER exists on $canonical_host_type host])\n    AC_SUBST(DEFAULT_PAGER)\n  else\n    ac_octave_possible_pagers=\"less more page pg\"\n    case \"$canonical_host_type\" in\n      *-*-cygwin* | *-*-mingw32* | *-*-msdosmsvc)\n        ac_octave_possible_pagers=\"$ac_octave_possible_pagers more.com\"\n      ;;\n    esac\n\n    AC_CHECK_PROGS(DEFAULT_PAGER, [$ac_octave_possible_pagers], [])\n    if test -z \"$DEFAULT_PAGER\"; then\n      warn_less=\"I couldn't find \\`less', \\`more', \\`page', or \\`pg'\"\n      OCTAVE_CONFIGURE_WARNING([warn_less])\n    fi\n  fi\n])\ndnl\ndnl Find Perl program.\ndnl\nAC_DEFUN([OCTAVE_PROG_PERL], [\n  AC_CHECK_PROG(PERL, perl, perl, [])\n  AC_SUBST(PERL)\n])\ndnl\ndnl Find Python program.\ndnl\nAC_DEFUN([OCTAVE_PROG_PYTHON], [\n  AC_CHECK_PROGS(PYTHON, [python3 python], python, [])\n  AC_SUBST(PYTHON)\n])\ndnl\ndnl Find rsvg-convert program.\ndnl\nAC_DEFUN([OCTAVE_PROG_RSVG_CONVERT], [\n  AC_CHECK_PROG(RSVG_CONVERT, rsvg-convert, rsvg-convert, [])\n  if test -z \"$RSVG_CONVERT\"; then\n    RSVG_CONVERT='${top_srcdir}/build-aux/missing rsvg-convert'\n    warn_rsvg_convert=\"\n\nI didn't find rsvg-convert, but it's only a problem if you need to\nreconstruct octave-logo-*.png, which is the case if you're building\nfrom VCS sources.\n\"\n    OCTAVE_CONFIGURE_WARNING([warn_rsvg_convert])\n  fi\n  AC_SUBST(RSVG_CONVERT)\n])\ndnl\ndnl Find sed program.\ndnl\n# Check for a fully-functional sed program, that truncates\n# as few characters as possible and that supports \"\\(X\\|Y\\)\"\n# style regular expression alternation.  Prefer GNU sed if found.\nAC_DEFUN([OCTAVE_PROG_SED], [\n  AC_MSG_CHECKING([for a usable sed])\n  if test -z \"$SED\"; then\n    AC_CACHE_VAL([octave_cv_prog_sed],\n      [# Loop through the user's path and search for sed and gsed.\n      # Next, test potential sed programs in list for truncation.\n      _AS_PATH_WALK([$PATH],\n        [for ac_prog in sed gsed; do\n          for ac_exec_ext in '' $ac_executable_extensions; do\n            if AS_EXECUTABLE_P([\"$as_dir/$ac_prog$ac_exec_ext\"]); then\n              _sed_list=\"$_sed_list $as_dir/$ac_prog$ac_exec_ext\"\n            fi\n          done\n        done\n      ])\n      AS_TMPDIR(sed)\n      _max=0\n      _count=0\n      # Add /usr/xpg4/bin/sed as it is typically found on Solaris\n      # along with /bin/sed that truncates output.\n      for _sed in $_sed_list /usr/xpg4/bin/sed; do\n        test ! -f ${_sed} && break\n        cat /dev/null > \"$tmp/sed.in\"\n        _count=0\n        echo $ECHO_N \"0123456789$ECHO_C\" >\"$tmp/sed.in\"\n        # Check for GNU sed and select it if it is found.\n        if \"${_sed}\" --version 2>&1 < /dev/null | $EGREP '(GNU)' > /dev/null; then\n          octave_cv_prog_sed=${_sed}\n          break;\n        fi\n        # Reject if RE alternation is not handled.\n        if test \"`echo 'this and that' | ${_sed} -n 's/\\(this\\|that\\).*$/\\1/p'`\" != \"this\"; then\n          continue;\n        fi\n        while true; do\n          cat \"$tmp/sed.in\" \"$tmp/sed.in\" >\"$tmp/sed.tmp\"\n          mv \"$tmp/sed.tmp\" \"$tmp/sed.in\"\n          cp \"$tmp/sed.in\" \"$tmp/sed.nl\"\n          echo >>\"$tmp/sed.nl\"\n          ${_sed} -e 's/a$//' < \"$tmp/sed.nl\" >\"$tmp/sed.out\" || break\n          cmp -s \"$tmp/sed.out\" \"$tmp/sed.nl\" || break\n          # 10000 chars as input seems more than enough\n          test $_count -gt 10 && break\n          _count=`expr $_count + 1`\n          if test $_count -gt $_max; then\n            _max=$_count\n            octave_cv_prog_sed=$_sed\n          fi\n        done\n      done\n      rm -rf \"$tmp\"\n    ])\n    SED=$octave_cv_prog_sed\n    if test -z \"$SED\"; then\n      AC_MSG_ERROR([no usable version of sed found])\n    fi\n  fi\n  AC_SUBST(SED)\n  AC_MSG_RESULT([$SED])\n])\ndnl\ndnl Check for options that can be passed to tar to make archives reproducible.\ndnl\nAC_DEFUN([OCTAVE_PROG_TAR_REPRODUCIBLE], [\n  AC_CACHE_CHECK([for options to make reproducible archives with GNU tar],\n    [octave_cv_tar_flags],\n    [octave_cv_tar_flags=\n    dnl This uses Automake's logic for finding GNU tar under various names\n    for octave_tar in tar gnutar gtar :; do\n      $octave_tar --version >/dev/null 2>&1 && break\n    done\n    dnl If we have a valid GNU tar program, see if it supports sets of options\n    if test x\"$octave_tar\" != x:; then\n      echo > conftest.txt\n      for octave_tar_flag in --owner=0 --group=0 --numeric-owner --sort=name; do\n        $octave_tar -cf conftest.tar $octave_cv_tar_flags $octave_tar_flag conftest.txt 2>/dev/null\n        if test $? -eq 0; then\n          octave_cv_tar_flags=\"${octave_cv_tar_flags:+$octave_cv_tar_flags }$octave_tar_flag\"\n        fi\n      done\n      rm -f conftest.tar conftest.txt\n    fi\n  ])\n  REPRODUCIBLE_TAR_FLAGS=\"$octave_cv_tar_flags\"\n  AC_SUBST(REPRODUCIBLE_TAR_FLAGS)\n])\ndnl\ndnl Check for texi2dvi.\ndnl\nAC_DEFUN([OCTAVE_PROG_TEXI2DVI], [\n  AC_CHECK_PROG(TEXI2DVI, texi2dvi, texi2dvi, [])\n  if test -z \"$TEXI2DVI\"; then\n    TEXI2DVI='${top_srcdir}/build-aux/missing texi2dvi'\n    warn_texi2dvi=\"\n\nI didn't find texi2dvi, but it's only a problem if you need to\nreconstruct the DVI version of the manual\n\"\n    OCTAVE_CONFIGURE_WARNING([warn_texi2dvi])\n  fi\n  AC_SUBST(TEXI2DVI)\n])\ndnl\ndnl Check for texi2pdf.\ndnl\nAC_DEFUN([OCTAVE_PROG_TEXI2PDF], [\n  AC_REQUIRE([OCTAVE_PROG_TEXI2DVI])\n  AC_CHECK_PROG(TEXI2PDF, texi2pdf, texi2pdf, [])\n  if test -z \"$TEXI2PDF\"; then\n    ac_octave_texi2pdf_missing=yes;\n    if test -n \"$TEXI2DVI\"; then\n      TEXI2PDF=\"$TEXI2DVI --pdf\"\n      ac_octave_texi2pdf_missing=no;\n    fi\n  else\n    ac_octave_texi2pdf_missing=no;\n  fi\n  if test $ac_octave_texi2pdf_missing = yes; then\n    TEXI2PDF='${top_srcdir}/build-aux/missing texi2pdf'\n    warn_texi2pdf=\"\n\nI didn't find texi2pdf, but it's only a problem if you need to\nreconstruct the PDF version of the manual\n\"\n    OCTAVE_CONFIGURE_WARNING([warn_texi2pdf])\n  fi\n  AC_SUBST(TEXI2PDF)\n])\ndnl\ndnl Set default value for a variable and substitute it.\ndnl\nAC_DEFUN([OCTAVE_SET_DEFAULT], [\n  ifelse($#, 2, [: ${$1=$2}\n])dnl\n  AC_MSG_RESULT([defining $1 to be $$1])\n  AC_SUBST($1)\n])\ndnl\ndnl Check whether integer types that are used for indexing in SuiteSparse match.\ndnl\nAC_DEFUN([OCTAVE_CHECK_SUITESPARSE_SIZEOF_IDX_TYPES], [\n  if test -n \"$SPQR_LIBS\" && test -n \"$CHOLMOD_LIBS\"; then\n    save_CPPFLAGS=\"$CPPFLAGS\"\n    CPPFLAGS=\"$CHOLMOD_CPPFLAGS $CPPFLAGS\"\n\n    AC_CACHE_CHECK([whether SuiteSparse_long and octave_idx_type have same size],\n      [octave_cv_suitesparse_long_match],\n      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n          #if defined (HAVE_SUITESPARSE_CHOLMOD_H)\n          #  include <suitesparse/cholmod.h>\n          #elif defined (HAVE_CHOLMOD_CHOLMOD_H)\n          #  include <cholmod/cholmod.h>\n          #elif defined (HAVE_CHOLMOD_H)\n          #  include <cholmod.h>\n          #endif\n          #include <assert.h>\n          ]], [[\n          static_assert (sizeof (SuiteSparse_long) == sizeof (OCTAVE_IDX_TYPE),\n                         \"SuiteSparse_long does not match size of octave_idx_type\");\n        ]])],\n        octave_cv_suitesparse_long_match=yes,\n        octave_cv_suitesparse_long_match=no)\n    ])\n    if test $octave_cv_suitesparse_long_match = yes; then\n      AC_DEFINE(OCTAVE_SUITESPARSE_LONG_MATCH, 1,\n        [Define to 1 if SuiteSparse_long and octave_idx_type have same size.])\n    fi\n\n    if test -n \"$CXSPARSE_LIBS\"; then\n      AC_CACHE_CHECK([whether SuiteSparse_long and suitesparse_integer have same size],\n        [octave_cv_suitesparse_integer_match],\n        [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n            #if defined (HAVE_SUITESPARSE_CHOLMOD_H)\n            #  include <suitesparse/cholmod.h>\n            #elif defined (HAVE_CHOLMOD_CHOLMOD_H)\n            #  include <cholmod/cholmod.h>\n            #elif defined (HAVE_CHOLMOD_H)\n            #  include <cholmod.h>\n            #endif\n            #include <assert.h>\n            ]], [[\n            #  if defined (OCTAVE_ENABLE_64)\n            typedef SuiteSparse_long suitesparse_integer;\n            #  else\n            typedef int suitesparse_integer;\n            #  endif\n            static_assert (sizeof (SuiteSparse_long) == sizeof (suitesparse_integer),\n                           \"SuiteSparse_long does not match size of suitesparse_integer\");\n          ]])],\n          octave_cv_suitesparse_integer_match=yes,\n          octave_cv_suitesparse_integer_match=no)\n      ])\n      if test $octave_cv_suitesparse_integer_match = yes; then\n        AC_DEFINE(OCTAVE_SUITESPARSE_INTEGER_MATCH, 1,\n          [Define to 1 if SuiteSparse_long and suitesparse_integer have same size.])\n      fi\n    fi\n\n    CPPFLAGS=\"$save_CPPFLAGS\"\n  fi\n])\ndnl\ndnl Check for UMFPACK separately split complex matrix and RHS.\ndnl\ndnl Macro assumes that the check for umfpack has already been performed.\ndnl\nAC_DEFUN([OCTAVE_UMFPACK_SEPARATE_SPLIT], [\n  AC_MSG_CHECKING([for UMFPACK separate complex matrix and rhs split])\n  AC_CACHE_VAL([octave_cv_umfpack_separate_split],\n    [AC_RUN_IFELSE([AC_LANG_SOURCE([[\n        #include <stdint.h>\n        #include <stdlib.h>\n        #include <math.h>\n        #if defined (HAVE_SUITESPARSE_UMFPACK_H)\n        # include <suitesparse/umfpack.h>\n        #elif defined (HAVE_UMFPACK_UMFPACK_H)\n        # include <umfpack/umfpack.h>\n        #elif defined (HAVE_UMFPACK_H)\n        # include <umfpack.h>\n        #endif\n        #if defined (OCTAVE_ENABLE_64)\n        typedef uint64_t idx_type;\n        #define UMFPACK_NAME(name) umfpack_zl_ ## name\n        #else\n        typedef int idx_type;\n        #define UMFPACK_NAME(name) umfpack_zi_ ## name\n        #endif\n        idx_type n = 5;\n        idx_type Ap[] = {0, 2, 5, 9, 10, 12};\n        idx_type Ai[]  = {0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4};\n        double Ax[] = {2., 0., 3., 0., 3., 0., -1., 0., 4., 0., 4., 0.,\n                      -3., 0., 1., 0., 2., 0., 2., 0., 6., 0., 1., 0.};\n        double br[] = {8., 45., -3., 3., 19.};\n        double bi[] = {0., 0., 0., 0., 0.};\n        int main (void)\n        {\n          double *null = (double *) NULL ;\n          double *x = (double *)malloc (2 * n * sizeof(double));\n          idx_type i ;\n          void *Symbolic, *Numeric ;\n          (void) UMFPACK_NAME (symbolic) (n, n, Ap, Ai, Ax, null, &Symbolic, null, null) ;\n          (void) UMFPACK_NAME (numeric) (Ap, Ai, Ax, null, Symbolic, &Numeric, null, null) ;\n          UMFPACK_NAME (free_symbolic) (&Symbolic) ;\n          (void) UMFPACK_NAME (solve) (0, Ap, Ai, Ax, null, x, null, br, bi,\n                                   Numeric, null, null) ;\n          UMFPACK_NAME (free_numeric) (&Numeric) ;\n          for (i = 0; i < n; i++, x+=2)\n            if (fabs (*x - i - 1.) > 1.e-13)\n              return (1);\n          return (0) ;\n        }\n      ]])],\n      octave_cv_umfpack_separate_split=yes,\n      octave_cv_umfpack_separate_split=no,\n      octave_cv_umfpack_separate_split=yes)\n  ])\n  if test \"$cross_compiling\" = yes; then\n    AC_MSG_RESULT([$octave_cv_umfpack_separate_split assumed for cross compilation])\n  else\n    AC_MSG_RESULT([$octave_cv_umfpack_separate_split])\n  fi\n  if test $octave_cv_umfpack_separate_split = yes; then\n    AC_DEFINE(UMFPACK_SEPARATE_SPLIT, 1,\n      [Define to 1 if the UMFPACK Complex solver allows matrix and RHS to be split independently.])\n  fi\n])\n"
  },
  {
    "path": "m4/ax_blas.m4",
    "content": "# ===========================================================================\n#         https://www.gnu.org/software/autoconf-archive/ax_blas.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_BLAS([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])\n#\n# DESCRIPTION\n#\n#   This macro looks for a library that implements the BLAS linear-algebra\n#   interface (see http://www.netlib.org/blas/). On success, it sets the\n#   BLAS_LIBS output variable to hold the requisite library linkages.\n#\n#   To link with BLAS, you should link with:\n#\n#     $BLAS_LIBS $LIBS $FLIBS\n#\n#   in that order. FLIBS is the output variable of the\n#   AC_F77_LIBRARY_LDFLAGS macro (called if necessary by AX_BLAS), and is\n#   sometimes necessary in order to link with F77 libraries. Users will also\n#   need to use AC_F77_DUMMY_MAIN (see the autoconf manual), for the same\n#   reason.\n#\n#   Many libraries are searched for, from ATLAS to CXML to ESSL. The user\n#   may also use --with-blas=<lib> in order to use some specific BLAS\n#   library <lib>. In order to link successfully, however, be aware that you\n#   will probably need to use the same Fortran compiler (which can be set\n#   via the F77 env. var.) as was used to compile the BLAS library.\n#\n#   ACTION-IF-FOUND is a list of shell commands to run if a BLAS library is\n#   found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it is\n#   not found. If ACTION-IF-FOUND is not specified, the default action will\n#   define HAVE_BLAS.\n#\n# LICENSE\n#\n#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>\n#   Copyright (c) 2019 Geoffrey M. Oxberry <goxberry@gmail.com>\n#\n#   This program is free software: you can redistribute it and/or modify it\n#   under the terms of the GNU General Public License as published by the\n#   Free Software Foundation, either version 3 of the License, or (at your\n#   option) any later version.\n#\n#   This program is distributed in the hope that it will be useful, but\n#   WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n#   Public License for more details.\n#\n#   You should have received a copy of the GNU General Public License along\n#   with this program. If not, see <https://www.gnu.org/licenses/>.\n#\n#   As a special exception, the respective Autoconf Macro's copyright owner\n#   gives unlimited permission to copy, distribute and modify the configure\n#   scripts that are the output of Autoconf when processing the Macro. You\n#   need not follow the terms of the GNU General Public License when using\n#   or distributing such scripts, even though portions of the text of the\n#   Macro appear in them. The GNU General Public License (GPL) does govern\n#   all other use of the material that constitutes the Autoconf Macro.\n#\n#   This special exception to the GPL applies to versions of the Autoconf\n#   Macro released by the Autoconf Archive. When you make and distribute a\n#   modified version of the Autoconf Macro, you may extend this special\n#   exception to the GPL to apply to your modified version as well.\n\n#serial 21\n\nAU_ALIAS([ACX_BLAS], [AX_BLAS])\nAC_DEFUN([AX_BLAS], [\nAC_PREREQ([2.55])\nAC_REQUIRE([AC_F77_LIBRARY_LDFLAGS])\nAC_REQUIRE([AC_CANONICAL_HOST])\nax_blas_ok=no\n\nAC_ARG_WITH(blas,\n\t[AS_HELP_STRING([--with-blas=<lib>], [use BLAS library <lib>])])\ncase $with_blas in\n\tyes | \"\") ;;\n\tno) ax_blas_ok=disable ;;\n\t-* | */* | *.a | *.so | *.so.* | *.dylib | *.dylib.* | *.o)\n\t\tBLAS_LIBS=\"$with_blas\"\n\t;;\n\t*) BLAS_LIBS=\"-l$with_blas\" ;;\nesac\n\n# Get fortran linker names of BLAS functions to check for.\nAC_F77_FUNC(sgemm)\nAC_F77_FUNC(dgemm)\n\nax_blas_save_LIBS=\"$LIBS\"\nLIBS=\"$LIBS $FLIBS\"\n\n# First, check BLAS_LIBS environment variable\nif test $ax_blas_ok = no; then\nif test \"x$BLAS_LIBS\" != x; then\n\tsave_LIBS=\"$LIBS\"; LIBS=\"$BLAS_LIBS $LIBS\"\n\tAC_MSG_CHECKING([for $sgemm in $BLAS_LIBS])\n\tAC_LINK_IFELSE([AC_LANG_CALL([], [$sgemm])], [ax_blas_ok=yes], [BLAS_LIBS=\"\"])\n\tAC_MSG_RESULT($ax_blas_ok)\n\tLIBS=\"$save_LIBS\"\nfi\nfi\n\n# BLAS linked to by default?  (happens on some supercomputers)\nif test $ax_blas_ok = no; then\n\tsave_LIBS=\"$LIBS\"; LIBS=\"$LIBS\"\n\tAC_MSG_CHECKING([if $sgemm is being linked in already])\n\tAC_LINK_IFELSE([AC_LANG_CALL([], [$sgemm])], [ax_blas_ok=yes])\n\tAC_MSG_RESULT($ax_blas_ok)\n\tLIBS=\"$save_LIBS\"\nfi\n\n# BLAS linked to by flexiblas? (Default on FC33+ and RHEL9+)\n\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(flexiblas, $sgemm, [ax_blas_ok=yes\n\t\t\t                BLAS_LIBS=\"-lflexiblas\"])\nfi\n\n# BLAS in OpenBLAS library? (http://xianyi.github.com/OpenBLAS/)\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(openblas, $sgemm, [ax_blas_ok=yes\n\t\t\t                BLAS_LIBS=\"-lopenblas\"])\nfi\n\n# BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(atlas, ATL_xerbla,\n\t\t[AC_CHECK_LIB(f77blas, $sgemm,\n\t\t[AC_CHECK_LIB(cblas, cblas_dgemm,\n\t\t\t[ax_blas_ok=yes\n\t\t\t BLAS_LIBS=\"-lcblas -lf77blas -latlas\"],\n\t\t\t[], [-lf77blas -latlas])],\n\t\t\t[], [-latlas])])\nfi\n\n# BLAS in PhiPACK libraries? (requires generic BLAS lib, too)\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(blas, $sgemm,\n\t\t[AC_CHECK_LIB(dgemm, $dgemm,\n\t\t[AC_CHECK_LIB(sgemm, $sgemm,\n\t\t\t[ax_blas_ok=yes; BLAS_LIBS=\"-lsgemm -ldgemm -lblas\"],\n\t\t\t[], [-lblas])],\n\t\t\t[], [-lblas])])\nfi\n\n# BLAS in Intel MKL library?\nif test $ax_blas_ok = no; then\n\t# MKL for gfortran\n\tif test x\"$ac_cv_fc_compiler_gnu\" = xyes; then\n\t\t# 64 bit\n\t\tif test $host_cpu = x86_64; then\n\t\t\tAC_CHECK_LIB(mkl_gf_lp64, $sgemm,\n\t\t\t[ax_blas_ok=yes;BLAS_LIBS=\"-lmkl_gf_lp64 -lmkl_sequential -lmkl_core -lpthread\"],,\n\t\t\t[-lmkl_gf_lp64 -lmkl_sequential -lmkl_core -lpthread])\n\t\t# 32 bit\n\t\telif test $host_cpu = i686; then\n\t\t\tAC_CHECK_LIB(mkl_gf, $sgemm,\n\t\t\t\t[ax_blas_ok=yes;BLAS_LIBS=\"-lmkl_gf -lmkl_sequential -lmkl_core -lpthread\"],,\n\t\t\t\t[-lmkl_gf -lmkl_sequential -lmkl_core -lpthread])\n\t\tfi\n\t# MKL for other compilers (Intel, PGI, ...?)\n\telse\n\t\t# 64-bit\n\t\tif test $host_cpu = x86_64; then\n\t\t\tAC_CHECK_LIB(mkl_intel_lp64, $sgemm,\n\t\t\t\t[ax_blas_ok=yes;BLAS_LIBS=\"-lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread\"],,\n\t\t\t\t[-lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread])\n\t\t# 32-bit\n\t\telif test $host_cpu = i686; then\n\t\t\tAC_CHECK_LIB(mkl_intel, $sgemm,\n\t\t\t\t[ax_blas_ok=yes;BLAS_LIBS=\"-lmkl_intel -lmkl_sequential -lmkl_core -lpthread\"],,\n\t\t\t\t[-lmkl_intel -lmkl_sequential -lmkl_core -lpthread])\n\t\tfi\n\tfi\nfi\n# Old versions of MKL\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(mkl, $sgemm, [ax_blas_ok=yes;BLAS_LIBS=\"-lmkl -lguide -lpthread\"],,[-lguide -lpthread])\nfi\n\n# BLAS in Apple vecLib library?\nif test $ax_blas_ok = no; then\n\tsave_LIBS=\"$LIBS\"; LIBS=\"-framework Accelerate $LIBS\"\n\tAC_MSG_CHECKING([for $sgemm in -framework Accelerate])\n\tAC_LINK_IFELSE([AC_LANG_CALL([], [$sgemm])], [ax_blas_ok=yes;BLAS_LIBS=\"-framework Accelerate\"])\n\tAC_MSG_RESULT($ax_blas_ok)\n\tLIBS=\"$save_LIBS\"\nfi\n\n# BLAS in Alpha CXML library?\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(cxml, $sgemm, [ax_blas_ok=yes;BLAS_LIBS=\"-lcxml\"])\nfi\n\n# BLAS in Alpha DXML library? (now called CXML, see above)\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(dxml, $sgemm, [ax_blas_ok=yes;BLAS_LIBS=\"-ldxml\"])\nfi\n\n# BLAS in Sun Performance library?\nif test $ax_blas_ok = no; then\n\tif test \"x$GCC\" != xyes; then # only works with Sun CC\n\t\tAC_CHECK_LIB(sunmath, acosp,\n\t\t\t[AC_CHECK_LIB(sunperf, $sgemm,\n\t\t\t\t[BLAS_LIBS=\"-xlic_lib=sunperf -lsunmath\"\n                                 ax_blas_ok=yes],[],[-lsunmath])])\n\tfi\nfi\n\n# BLAS in SCSL library?  (SGI/Cray Scientific Library)\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(scs, $sgemm, [ax_blas_ok=yes; BLAS_LIBS=\"-lscs\"])\nfi\n\n# BLAS in SGIMATH library?\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(complib.sgimath, $sgemm,\n\t\t     [ax_blas_ok=yes; BLAS_LIBS=\"-lcomplib.sgimath\"])\nfi\n\n# BLAS in IBM ESSL library? (requires generic BLAS lib, too)\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(blas, $sgemm,\n\t\t[AC_CHECK_LIB(essl, $sgemm,\n\t\t\t[ax_blas_ok=yes; BLAS_LIBS=\"-lessl -lblas\"],\n\t\t\t[], [-lblas $FLIBS])])\nfi\n\n# Generic BLAS library?\nif test $ax_blas_ok = no; then\n\tAC_CHECK_LIB(blas, $sgemm, [ax_blas_ok=yes; BLAS_LIBS=\"-lblas\"])\nfi\n\nAC_SUBST(BLAS_LIBS)\n\nLIBS=\"$ax_blas_save_LIBS\"\n\n# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:\nif test x\"$ax_blas_ok\" = xyes; then\n        ifelse([$1],,AC_DEFINE(HAVE_BLAS,1,[Define if you have a BLAS library.]),[$1])\n        :\nelse\n        ax_blas_ok=no\n        $2\nfi\n])dnl AX_BLAS\n"
  },
  {
    "path": "m4/ax_compare_version.m4",
    "content": "# ===========================================================================\n#    https://www.gnu.org/software/autoconf-archive/ax_compare_version.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE])\n#\n# DESCRIPTION\n#\n#   This macro compares two version strings. Due to the various number of\n#   minor-version numbers that can exist, and the fact that string\n#   comparisons are not compatible with numeric comparisons, this is not\n#   necessarily trivial to do in a autoconf script. This macro makes doing\n#   these comparisons easy.\n#\n#   The six basic comparisons are available, as well as checking equality\n#   limited to a certain number of minor-version levels.\n#\n#   The operator OP determines what type of comparison to do, and can be one\n#   of:\n#\n#    eq  - equal (test A == B)\n#    ne  - not equal (test A != B)\n#    le  - less than or equal (test A <= B)\n#    ge  - greater than or equal (test A >= B)\n#    lt  - less than (test A < B)\n#    gt  - greater than (test A > B)\n#\n#   Additionally, the eq and ne operator can have a number after it to limit\n#   the test to that number of minor versions.\n#\n#    eq0 - equal up to the length of the shorter version\n#    ne0 - not equal up to the length of the shorter version\n#    eqN - equal up to N sub-version levels\n#    neN - not equal up to N sub-version levels\n#\n#   When the condition is true, shell commands ACTION-IF-TRUE are run,\n#   otherwise shell commands ACTION-IF-FALSE are run. The environment\n#   variable 'ax_compare_version' is always set to either 'true' or 'false'\n#   as well.\n#\n#   Examples:\n#\n#     AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8])\n#     AX_COMPARE_VERSION([3.15],[lt],[3.15.8])\n#\n#   would both be true.\n#\n#     AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8])\n#     AX_COMPARE_VERSION([3.15],[gt],[3.15.8])\n#\n#   would both be false.\n#\n#     AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8])\n#\n#   would be true because it is only comparing two minor versions.\n#\n#     AX_COMPARE_VERSION([3.15.7],[eq0],[3.15])\n#\n#   would be true because it is only comparing the lesser number of minor\n#   versions of the two values.\n#\n#   Note: The characters that separate the version numbers do not matter. An\n#   empty string is the same as version 0. OP is evaluated by autoconf, not\n#   configure, so must be a string, not a variable.\n#\n#   The author would like to acknowledge Guido Draheim whose advice about\n#   the m4_case and m4_ifvaln functions make this macro only include the\n#   portions necessary to perform the specific comparison specified by the\n#   OP argument in the final configure script.\n#\n# LICENSE\n#\n#   Copyright (c) 2008 Tim Toolan <toolan@ele.uri.edu>\n#\n#   Copying and distribution of this file, with or without modification, are\n#   permitted in any medium without royalty provided the copyright notice\n#   and this notice are preserved. This file is offered as-is, without any\n#   warranty.\n\n#serial 13\n\ndnl #########################################################################\nAC_DEFUN([AX_COMPARE_VERSION], [\n  AC_REQUIRE([AC_PROG_AWK])\n\n  # Used to indicate true or false condition\n  ax_compare_version=false\n\n  # Convert the two version strings to be compared into a format that\n  # allows a simple string comparison.  The end result is that a version\n  # string of the form 1.12.5-r617 will be converted to the form\n  # 0001001200050617.  In other words, each number is zero padded to four\n  # digits, and non digits are removed.\n  AS_VAR_PUSHDEF([A],[ax_compare_version_A])\n  A=`echo \"$1\" | sed -e 's/\\([[0-9]]*\\)/Z\\1Z/g' \\\n                     -e 's/Z\\([[0-9]]\\)Z/Z0\\1Z/g' \\\n                     -e 's/Z\\([[0-9]][[0-9]]\\)Z/Z0\\1Z/g' \\\n                     -e 's/Z\\([[0-9]][[0-9]][[0-9]]\\)Z/Z0\\1Z/g' \\\n                     -e 's/[[^0-9]]//g'`\n\n  AS_VAR_PUSHDEF([B],[ax_compare_version_B])\n  B=`echo \"$3\" | sed -e 's/\\([[0-9]]*\\)/Z\\1Z/g' \\\n                     -e 's/Z\\([[0-9]]\\)Z/Z0\\1Z/g' \\\n                     -e 's/Z\\([[0-9]][[0-9]]\\)Z/Z0\\1Z/g' \\\n                     -e 's/Z\\([[0-9]][[0-9]][[0-9]]\\)Z/Z0\\1Z/g' \\\n                     -e 's/[[^0-9]]//g'`\n\n  dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary\n  dnl # then the first line is used to determine if the condition is true.\n  dnl # The sed right after the echo is to remove any indented white space.\n  m4_case(m4_tolower($2),\n  [lt],[\n    ax_compare_version=`echo \"x$A\nx$B\" | sed 's/^ *//' | sort -r | sed \"s/x${A}/false/;s/x${B}/true/;1q\"`\n  ],\n  [gt],[\n    ax_compare_version=`echo \"x$A\nx$B\" | sed 's/^ *//' | sort | sed \"s/x${A}/false/;s/x${B}/true/;1q\"`\n  ],\n  [le],[\n    ax_compare_version=`echo \"x$A\nx$B\" | sed 's/^ *//' | sort | sed \"s/x${A}/true/;s/x${B}/false/;1q\"`\n  ],\n  [ge],[\n    ax_compare_version=`echo \"x$A\nx$B\" | sed 's/^ *//' | sort -r | sed \"s/x${A}/true/;s/x${B}/false/;1q\"`\n  ],[\n    dnl Split the operator from the subversion count if present.\n    m4_bmatch(m4_substr($2,2),\n    [0],[\n      # A count of zero means use the length of the shorter version.\n      # Determine the number of characters in A and B.\n      ax_compare_version_len_A=`echo \"$A\" | $AWK '{print(length)}'`\n      ax_compare_version_len_B=`echo \"$B\" | $AWK '{print(length)}'`\n\n      # Set A to no more than B's length and B to no more than A's length.\n      A=`echo \"$A\" | sed \"s/\\(.\\{$ax_compare_version_len_B\\}\\).*/\\1/\"`\n      B=`echo \"$B\" | sed \"s/\\(.\\{$ax_compare_version_len_A\\}\\).*/\\1/\"`\n    ],\n    [[0-9]+],[\n      # A count greater than zero means use only that many subversions\n      A=`echo \"$A\" | sed \"s/\\(\\([[0-9]]\\{4\\}\\)\\{m4_substr($2,2)\\}\\).*/\\1/\"`\n      B=`echo \"$B\" | sed \"s/\\(\\([[0-9]]\\{4\\}\\)\\{m4_substr($2,2)\\}\\).*/\\1/\"`\n    ],\n    [.+],[\n      AC_WARNING(\n        [invalid OP numeric parameter: $2])\n    ],[])\n\n    # Pad zeros at end of numbers to make same length.\n    ax_compare_version_tmp_A=\"$A`echo $B | sed 's/./0/g'`\"\n    B=\"$B`echo $A | sed 's/./0/g'`\"\n    A=\"$ax_compare_version_tmp_A\"\n\n    # Check for equality or inequality as necessary.\n    m4_case(m4_tolower(m4_substr($2,0,2)),\n    [eq],[\n      test \"x$A\" = \"x$B\" && ax_compare_version=true\n    ],\n    [ne],[\n      test \"x$A\" != \"x$B\" && ax_compare_version=true\n    ],[\n      AC_WARNING([invalid OP parameter: $2])\n    ])\n  ])\n\n  AS_VAR_POPDEF([A])dnl\n  AS_VAR_POPDEF([B])dnl\n\n  dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.\n  if test \"$ax_compare_version\" = \"true\" ; then\n    m4_ifvaln([$4],[$4],[:])dnl\n    m4_ifvaln([$5],[else $5])dnl\n  fi\n]) dnl AX_COMPARE_VERSION\n"
  },
  {
    "path": "m4/ax_cxx_compile_stdcxx.m4",
    "content": "# ===========================================================================\n#  https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])\n#\n# DESCRIPTION\n#\n#   Check for baseline language coverage in the compiler for the specified\n#   version of the C++ standard.  If necessary, add switches to CXX and\n#   CXXCPP to enable support.  VERSION may be '11', '14', '17', '20', or\n#   '23' for the respective C++ standard version.\n#\n#   The second argument, if specified, indicates whether you insist on an\n#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.\n#   -std=c++11).  If neither is specified, you get whatever works, with\n#   preference for no added switch, and then for an extended mode.\n#\n#   The third argument, if specified 'mandatory' or if left unspecified,\n#   indicates that baseline support for the specified C++ standard is\n#   required and that the macro should error out if no mode with that\n#   support is found.  If specified 'optional', then configuration proceeds\n#   regardless, after defining HAVE_CXX${VERSION} if and only if a\n#   supporting mode is found.\n#\n# LICENSE\n#\n#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>\n#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>\n#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>\n#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>\n#   Copyright (c) 2015 Paul Norman <penorman@mac.com>\n#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>\n#   Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>\n#   Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>\n#   Copyright (c) 2020 Jason Merrill <jason@redhat.com>\n#   Copyright (c) 2021, 2024 Jörn Heusipp <osmanx@problemloesungsmaschine.de>\n#   Copyright (c) 2015, 2022, 2023, 2024 Olly Betts\n#\n#   Copying and distribution of this file, with or without modification, are\n#   permitted in any medium without royalty provided the copyright notice\n#   and this notice are preserved.  This file is offered as-is, without any\n#   warranty.\n\n#serial 25\n\ndnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro\ndnl  (serial version number 13).\n\nAC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl\n  m4_if([$1], [11], [ax_cxx_compile_alternatives=\"11 0x\"],\n        [$1], [14], [ax_cxx_compile_alternatives=\"14 1y\"],\n        [$1], [17], [ax_cxx_compile_alternatives=\"17 1z\"],\n        [$1], [20], [ax_cxx_compile_alternatives=\"20\"],\n        [$1], [23], [ax_cxx_compile_alternatives=\"23\"],\n        [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl\n  m4_if([$2], [], [],\n        [$2], [ext], [],\n        [$2], [noext], [],\n        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl\n  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],\n        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],\n        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],\n        [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])\n  AC_LANG_PUSH([C++])dnl\n  ac_success=no\n\n  m4_if([$2], [], [dnl\n    AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,\n\t\t   ax_cv_cxx_compile_cxx$1,\n      [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],\n        [ax_cv_cxx_compile_cxx$1=yes],\n        [ax_cv_cxx_compile_cxx$1=no])])\n    if test x$ax_cv_cxx_compile_cxx$1 = xyes; then\n      ac_success=yes\n    fi])\n\n  m4_if([$2], [noext], [], [dnl\n  if test x$ac_success = xno; then\n    for alternative in ${ax_cxx_compile_alternatives}; do\n      switch=\"-std=gnu++${alternative}\"\n      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])\n      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,\n                     $cachevar,\n        [ac_save_CXX=\"$CXX\"\n         CXX=\"$CXX $switch\"\n         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],\n          [eval $cachevar=yes],\n          [eval $cachevar=no])\n         CXX=\"$ac_save_CXX\"])\n      if eval test x\\$$cachevar = xyes; then\n        CXX=\"$CXX $switch\"\n        if test -n \"$CXXCPP\" ; then\n          CXXCPP=\"$CXXCPP $switch\"\n        fi\n        ac_success=yes\n        break\n      fi\n    done\n  fi])\n\n  m4_if([$2], [ext], [], [dnl\n  if test x$ac_success = xno; then\n    dnl HP's aCC needs +std=c++11 according to:\n    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf\n    dnl Cray's crayCC needs \"-h std=c++11\"\n    dnl MSVC needs -std:c++NN for C++17 and later (default is C++14)\n    for alternative in ${ax_cxx_compile_alternatives}; do\n      for switch in -std=c++${alternative} +std=c++${alternative} \"-h std=c++${alternative}\" MSVC; do\n        if test x\"$switch\" = xMSVC; then\n          dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide\n          dnl with -std=c++17.  We suffix the cache variable name with _MSVC to\n          dnl avoid this.\n          switch=-std:c++${alternative}\n          cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC])\n        else\n          cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])\n        fi\n        AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,\n                       $cachevar,\n          [ac_save_CXX=\"$CXX\"\n           CXX=\"$CXX $switch\"\n           AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],\n            [eval $cachevar=yes],\n            [eval $cachevar=no])\n           CXX=\"$ac_save_CXX\"])\n        if eval test x\\$$cachevar = xyes; then\n          CXX=\"$CXX $switch\"\n          if test -n \"$CXXCPP\" ; then\n            CXXCPP=\"$CXXCPP $switch\"\n          fi\n          ac_success=yes\n          break\n        fi\n      done\n      if test x$ac_success = xyes; then\n        break\n      fi\n    done\n  fi])\n  AC_LANG_POP([C++])\n  if test x$ax_cxx_compile_cxx$1_required = xtrue; then\n    if test x$ac_success = xno; then\n      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])\n    fi\n  fi\n  if test x$ac_success = xno; then\n    HAVE_CXX$1=0\n    AC_MSG_NOTICE([No compiler with C++$1 support was found])\n  else\n    HAVE_CXX$1=1\n    AC_DEFINE(HAVE_CXX$1,1,\n              [define if the compiler supports basic C++$1 syntax])\n  fi\n  AC_SUBST(HAVE_CXX$1)\n])\n\n\ndnl  Test body for checking C++11 support\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],\n  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11]\n)\n\ndnl  Test body for checking C++14 support\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],\n  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14]\n)\n\ndnl  Test body for checking C++17 support\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],\n  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_17]\n)\n\ndnl  Test body for checking C++20 support\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_20],\n  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_17\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_20]\n)\n\ndnl  Test body for checking C++23 support\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_23],\n  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_17\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_20\n   _AX_CXX_COMPILE_STDCXX_testbody_new_in_23]\n)\n\n\ndnl  Tests for new features in C++11\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[\n\n// If the compiler admits that it is not ready for C++11, why torture it?\n// Hopefully, this will speed up the test.\n\n#ifndef __cplusplus\n\n#error \"This is not a C++ compiler\"\n\n// MSVC always sets __cplusplus to 199711L in older versions; newer versions\n// only set it correctly if /Zc:__cplusplus is specified as well as a\n// /std:c++NN switch:\n//\n// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/\n//\n// The value __cplusplus ought to have is available in _MSVC_LANG since\n// Visual Studio 2015 Update 3:\n//\n// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros\n//\n// This was also the first MSVC version to support C++14 so we can't use the\n// value of either __cplusplus or _MSVC_LANG to quickly rule out MSVC having\n// C++11 or C++14 support, but we can check _MSVC_LANG for C++17 and later.\n#elif __cplusplus < 201103L && !defined _MSC_VER\n\n#error \"This is not a C++11 compiler\"\n\n#else\n\nnamespace cxx11\n{\n\n  namespace test_static_assert\n  {\n\n    template <typename T>\n    struct check\n    {\n      static_assert(sizeof(int) <= sizeof(T), \"not big enough\");\n    };\n\n  }\n\n  namespace test_final_override\n  {\n\n    struct Base\n    {\n      virtual ~Base() {}\n      virtual void f() {}\n    };\n\n    struct Derived : public Base\n    {\n      virtual ~Derived() override {}\n      virtual void f() override {}\n    };\n\n  }\n\n  namespace test_double_right_angle_brackets\n  {\n\n    template < typename T >\n    struct check {};\n\n    typedef check<void> single_type;\n    typedef check<check<void>> double_type;\n    typedef check<check<check<void>>> triple_type;\n    typedef check<check<check<check<void>>>> quadruple_type;\n\n  }\n\n  namespace test_decltype\n  {\n\n    int\n    f()\n    {\n      int a = 1;\n      decltype(a) b = 2;\n      return a + b;\n    }\n\n  }\n\n  namespace test_type_deduction\n  {\n\n    template < typename T1, typename T2 >\n    struct is_same\n    {\n      static const bool value = false;\n    };\n\n    template < typename T >\n    struct is_same<T, T>\n    {\n      static const bool value = true;\n    };\n\n    template < typename T1, typename T2 >\n    auto\n    add(T1 a1, T2 a2) -> decltype(a1 + a2)\n    {\n      return a1 + a2;\n    }\n\n    int\n    test(const int c, volatile int v)\n    {\n      static_assert(is_same<int, decltype(0)>::value == true, \"\");\n      static_assert(is_same<int, decltype(c)>::value == false, \"\");\n      static_assert(is_same<int, decltype(v)>::value == false, \"\");\n      auto ac = c;\n      auto av = v;\n      auto sumi = ac + av + 'x';\n      auto sumf = ac + av + 1.0;\n      static_assert(is_same<int, decltype(ac)>::value == true, \"\");\n      static_assert(is_same<int, decltype(av)>::value == true, \"\");\n      static_assert(is_same<int, decltype(sumi)>::value == true, \"\");\n      static_assert(is_same<int, decltype(sumf)>::value == false, \"\");\n      static_assert(is_same<int, decltype(add(c, v))>::value == true, \"\");\n      return (sumf > 0.0) ? sumi : add(c, v);\n    }\n\n  }\n\n  namespace test_noexcept\n  {\n\n    int f() { return 0; }\n    int g() noexcept { return 0; }\n\n    static_assert(noexcept(f()) == false, \"\");\n    static_assert(noexcept(g()) == true, \"\");\n\n  }\n\n  namespace test_constexpr\n  {\n\n    template < typename CharT >\n    unsigned long constexpr\n    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept\n    {\n      return *s ? strlen_c_r(s + 1, acc + 1) : acc;\n    }\n\n    template < typename CharT >\n    unsigned long constexpr\n    strlen_c(const CharT *const s) noexcept\n    {\n      return strlen_c_r(s, 0UL);\n    }\n\n    static_assert(strlen_c(\"\") == 0UL, \"\");\n    static_assert(strlen_c(\"1\") == 1UL, \"\");\n    static_assert(strlen_c(\"example\") == 7UL, \"\");\n    static_assert(strlen_c(\"another\\0example\") == 7UL, \"\");\n\n  }\n\n  namespace test_rvalue_references\n  {\n\n    template < int N >\n    struct answer\n    {\n      static constexpr int value = N;\n    };\n\n    answer<1> f(int&)       { return answer<1>(); }\n    answer<2> f(const int&) { return answer<2>(); }\n    answer<3> f(int&&)      { return answer<3>(); }\n\n    void\n    test()\n    {\n      int i = 0;\n      const int c = 0;\n      static_assert(decltype(f(i))::value == 1, \"\");\n      static_assert(decltype(f(c))::value == 2, \"\");\n      static_assert(decltype(f(0))::value == 3, \"\");\n    }\n\n  }\n\n  namespace test_uniform_initialization\n  {\n\n    struct test\n    {\n      static const int zero {};\n      static const int one {1};\n    };\n\n    static_assert(test::zero == 0, \"\");\n    static_assert(test::one == 1, \"\");\n\n  }\n\n  namespace test_lambdas\n  {\n\n    void\n    test1()\n    {\n      auto lambda1 = [](){};\n      auto lambda2 = lambda1;\n      lambda1();\n      lambda2();\n    }\n\n    int\n    test2()\n    {\n      auto a = [](int i, int j){ return i + j; }(1, 2);\n      auto b = []() -> int { return '0'; }();\n      auto c = [=](){ return a + b; }();\n      auto d = [&](){ return c; }();\n      auto e = [a, &b](int x) mutable {\n        const auto identity = [](int y){ return y; };\n        for (auto i = 0; i < a; ++i)\n          a += b--;\n        return x + identity(a + b);\n      }(0);\n      return a + b + c + d + e;\n    }\n\n    int\n    test3()\n    {\n      const auto nullary = [](){ return 0; };\n      const auto unary = [](int x){ return x; };\n      using nullary_t = decltype(nullary);\n      using unary_t = decltype(unary);\n      const auto higher1st = [](nullary_t f){ return f(); };\n      const auto higher2nd = [unary](nullary_t f1){\n        return [unary, f1](unary_t f2){ return f2(unary(f1())); };\n      };\n      return higher1st(nullary) + higher2nd(nullary)(unary);\n    }\n\n  }\n\n  namespace test_variadic_templates\n  {\n\n    template <int...>\n    struct sum;\n\n    template <int N0, int... N1toN>\n    struct sum<N0, N1toN...>\n    {\n      static constexpr auto value = N0 + sum<N1toN...>::value;\n    };\n\n    template <>\n    struct sum<>\n    {\n      static constexpr auto value = 0;\n    };\n\n    static_assert(sum<>::value == 0, \"\");\n    static_assert(sum<1>::value == 1, \"\");\n    static_assert(sum<23>::value == 23, \"\");\n    static_assert(sum<1, 2>::value == 3, \"\");\n    static_assert(sum<5, 5, 11>::value == 21, \"\");\n    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, \"\");\n\n  }\n\n  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae\n  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function\n  // because of this.\n  namespace test_template_alias_sfinae\n  {\n\n    struct foo {};\n\n    template<typename T>\n    using member = typename T::member_type;\n\n    template<typename T>\n    void func(...) {}\n\n    template<typename T>\n    void func(member<T>*) {}\n\n    void test();\n\n    void test() { func<foo>(0); }\n\n  }\n\n}  // namespace cxx11\n\n#endif  // __cplusplus >= 201103L\n\n]])\n\n\ndnl  Tests for new features in C++14\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[\n\n// If the compiler admits that it is not ready for C++14, why torture it?\n// Hopefully, this will speed up the test.\n\n#ifndef __cplusplus\n\n#error \"This is not a C++ compiler\"\n\n#elif __cplusplus < 201402L && !defined _MSC_VER\n\n#error \"This is not a C++14 compiler\"\n\n#else\n\nnamespace cxx14\n{\n\n  namespace test_polymorphic_lambdas\n  {\n\n    int\n    test()\n    {\n      const auto lambda = [](auto&&... args){\n        const auto istiny = [](auto x){\n          return (sizeof(x) == 1UL) ? 1 : 0;\n        };\n        const int aretiny[] = { istiny(args)... };\n        return aretiny[0];\n      };\n      return lambda(1, 1L, 1.0f, '1');\n    }\n\n  }\n\n  namespace test_binary_literals\n  {\n\n    constexpr auto ivii = 0b0000000000101010;\n    static_assert(ivii == 42, \"wrong value\");\n\n  }\n\n  namespace test_generalized_constexpr\n  {\n\n    template < typename CharT >\n    constexpr unsigned long\n    strlen_c(const CharT *const s) noexcept\n    {\n      auto length = 0UL;\n      for (auto p = s; *p; ++p)\n        ++length;\n      return length;\n    }\n\n    static_assert(strlen_c(\"\") == 0UL, \"\");\n    static_assert(strlen_c(\"x\") == 1UL, \"\");\n    static_assert(strlen_c(\"test\") == 4UL, \"\");\n    static_assert(strlen_c(\"another\\0test\") == 7UL, \"\");\n\n  }\n\n  namespace test_lambda_init_capture\n  {\n\n    int\n    test()\n    {\n      auto x = 0;\n      const auto lambda1 = [a = x](int b){ return a + b; };\n      const auto lambda2 = [a = lambda1(x)](){ return a; };\n      return lambda2();\n    }\n\n  }\n\n  namespace test_digit_separators\n  {\n\n    constexpr auto ten_million = 100'000'000;\n    static_assert(ten_million == 100000000, \"\");\n\n  }\n\n  namespace test_return_type_deduction\n  {\n\n    auto f(int& x) { return x; }\n    decltype(auto) g(int& x) { return x; }\n\n    template < typename T1, typename T2 >\n    struct is_same\n    {\n      static constexpr auto value = false;\n    };\n\n    template < typename T >\n    struct is_same<T, T>\n    {\n      static constexpr auto value = true;\n    };\n\n    int\n    test()\n    {\n      auto x = 0;\n      static_assert(is_same<int, decltype(f(x))>::value, \"\");\n      static_assert(is_same<int&, decltype(g(x))>::value, \"\");\n      return x;\n    }\n\n  }\n\n}  // namespace cxx14\n\n#endif  // __cplusplus >= 201402L\n\n]])\n\n\ndnl  Tests for new features in C++17\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[\n\n// If the compiler admits that it is not ready for C++17, why torture it?\n// Hopefully, this will speed up the test.\n\n#ifndef __cplusplus\n\n#error \"This is not a C++ compiler\"\n\n#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L\n\n#error \"This is not a C++17 compiler\"\n\n#else\n\n#include <initializer_list>\n#include <utility>\n#include <type_traits>\n\nnamespace cxx17\n{\n\n  namespace test_constexpr_lambdas\n  {\n\n    constexpr int foo = [](){return 42;}();\n\n  }\n\n  namespace test::nested_namespace::definitions\n  {\n\n  }\n\n  namespace test_fold_expression\n  {\n\n    template<typename... Args>\n    int multiply(Args... args)\n    {\n      return (args * ... * 1);\n    }\n\n    template<typename... Args>\n    bool all(Args... args)\n    {\n      return (args && ...);\n    }\n\n  }\n\n  namespace test_extended_static_assert\n  {\n\n    static_assert (true);\n\n  }\n\n  namespace test_auto_brace_init_list\n  {\n\n    auto foo = {5};\n    auto bar {5};\n\n    static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);\n    static_assert(std::is_same<int, decltype(bar)>::value);\n  }\n\n  namespace test_typename_in_template_template_parameter\n  {\n\n    template<template<typename> typename X> struct D;\n\n  }\n\n  namespace test_fallthrough_nodiscard_maybe_unused_attributes\n  {\n\n    int f1()\n    {\n      return 42;\n    }\n\n    [[nodiscard]] int f2()\n    {\n      [[maybe_unused]] auto unused = f1();\n\n      switch (f1())\n      {\n      case 17:\n        f1();\n        [[fallthrough]];\n      case 42:\n        f1();\n      }\n      return f1();\n    }\n\n  }\n\n  namespace test_extended_aggregate_initialization\n  {\n\n    struct base1\n    {\n      int b1, b2 = 42;\n    };\n\n    struct base2\n    {\n      base2() {\n        b3 = 42;\n      }\n      int b3;\n    };\n\n    struct derived : base1, base2\n    {\n        int d;\n    };\n\n    derived d1 {{1, 2}, {}, 4};  // full initialization\n    derived d2 {{}, {}, 4};      // value-initialized bases\n\n  }\n\n  namespace test_general_range_based_for_loop\n  {\n\n    struct iter\n    {\n      int i;\n\n      int& operator* ()\n      {\n        return i;\n      }\n\n      const int& operator* () const\n      {\n        return i;\n      }\n\n      iter& operator++()\n      {\n        ++i;\n        return *this;\n      }\n    };\n\n    struct sentinel\n    {\n      int i;\n    };\n\n    bool operator== (const iter& i, const sentinel& s)\n    {\n      return i.i == s.i;\n    }\n\n    bool operator!= (const iter& i, const sentinel& s)\n    {\n      return !(i == s);\n    }\n\n    struct range\n    {\n      iter begin() const\n      {\n        return {0};\n      }\n\n      sentinel end() const\n      {\n        return {5};\n      }\n    };\n\n    void f()\n    {\n      range r {};\n\n      for (auto i : r)\n      {\n        [[maybe_unused]] auto v = i;\n      }\n    }\n\n  }\n\n  namespace test_lambda_capture_asterisk_this_by_value\n  {\n\n    struct t\n    {\n      int i;\n      int foo()\n      {\n        return [*this]()\n        {\n          return i;\n        }();\n      }\n    };\n\n  }\n\n  namespace test_enum_class_construction\n  {\n\n    enum class byte : unsigned char\n    {};\n\n    byte foo {42};\n\n  }\n\n  namespace test_constexpr_if\n  {\n\n    template <bool cond>\n    int f ()\n    {\n      if constexpr(cond)\n      {\n        return 13;\n      }\n      else\n      {\n        return 42;\n      }\n    }\n\n  }\n\n  namespace test_selection_statement_with_initializer\n  {\n\n    int f()\n    {\n      return 13;\n    }\n\n    int f2()\n    {\n      if (auto i = f(); i > 0)\n      {\n        return 3;\n      }\n\n      switch (auto i = f(); i + 4)\n      {\n      case 17:\n        return 2;\n\n      default:\n        return 1;\n      }\n    }\n\n  }\n\n  namespace test_template_argument_deduction_for_class_templates\n  {\n\n    template <typename T1, typename T2>\n    struct pair\n    {\n      pair (T1 p1, T2 p2)\n        : m1 {p1},\n          m2 {p2}\n      {}\n\n      T1 m1;\n      T2 m2;\n    };\n\n    void f()\n    {\n      [[maybe_unused]] auto p = pair{13, 42u};\n    }\n\n  }\n\n  namespace test_non_type_auto_template_parameters\n  {\n\n    template <auto n>\n    struct B\n    {};\n\n    B<5> b1;\n    B<'a'> b2;\n\n  }\n\n  namespace test_structured_bindings\n  {\n\n    int arr[2] = { 1, 2 };\n    std::pair<int, int> pr = { 1, 2 };\n\n    auto f1() -> int(&)[2]\n    {\n      return arr;\n    }\n\n    auto f2() -> std::pair<int, int>&\n    {\n      return pr;\n    }\n\n    struct S\n    {\n      int x1 : 2;\n      volatile double y1;\n    };\n\n    S f3()\n    {\n      return {};\n    }\n\n    auto [ x1, y1 ] = f1();\n    auto& [ xr1, yr1 ] = f1();\n    auto [ x2, y2 ] = f2();\n    auto& [ xr2, yr2 ] = f2();\n    const auto [ x3, y3 ] = f3();\n\n  }\n\n  namespace test_exception_spec_type_system\n  {\n\n    struct Good {};\n    struct Bad {};\n\n    void g1() noexcept;\n    void g2();\n\n    template<typename T>\n    Bad\n    f(T*, T*);\n\n    template<typename T1, typename T2>\n    Good\n    f(T1*, T2*);\n\n    static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);\n\n  }\n\n  namespace test_inline_variables\n  {\n\n    template<class T> void f(T)\n    {}\n\n    template<class T> inline T g(T)\n    {\n      return T{};\n    }\n\n    template<> inline void f<>(int)\n    {}\n\n    template<> int g<>(int)\n    {\n      return 5;\n    }\n\n  }\n\n}  // namespace cxx17\n\n#endif  // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L\n\n]])\n\n\ndnl  Tests for new features in C++20\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[\n\n#ifndef __cplusplus\n\n#error \"This is not a C++ compiler\"\n\n#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L\n\n#error \"This is not a C++20 compiler\"\n\n#else\n\n#include <version>\n\nnamespace cxx20\n{\n\n// As C++20 supports feature test macros in the standard, there is no\n// immediate need to actually test for feature availability on the\n// Autoconf side.\n\n}  // namespace cxx20\n\n#endif  // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L\n\n]])\n\n\ndnl  Tests for new features in C++23\n\nm4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_23], [[\n\n#ifndef __cplusplus\n\n#error \"This is not a C++ compiler\"\n\n#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L\n\n#error \"This is not a C++23 compiler\"\n\n#else\n\n#include <version>\n\nnamespace cxx23\n{\n\n// As C++23 supports feature test macros in the standard, there is no\n// immediate need to actually test for feature availability on the\n// Autoconf side.\n\n}  // namespace cxx23\n\n#endif  // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L\n\n]])\n"
  },
  {
    "path": "m4/ax_lapack.m4",
    "content": "# ===========================================================================\n#        https://www.gnu.org/software/autoconf-archive/ax_lapack.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_LAPACK([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])\n#\n# DESCRIPTION\n#\n#   This macro looks for a library that implements the LAPACK linear-algebra\n#   interface (see http://www.netlib.org/lapack/). On success, it sets the\n#   LAPACK_LIBS output variable to hold the requisite library linkages.\n#\n#   To link with LAPACK, you should link with:\n#\n#     $LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS\n#\n#   in that order. BLAS_LIBS is the output variable of the AX_BLAS macro,\n#   called automatically. FLIBS is the output variable of the\n#   AC_F77_LIBRARY_LDFLAGS macro (called if necessary by AX_BLAS), and is\n#   sometimes necessary in order to link with F77 libraries. Users will also\n#   need to use AC_F77_DUMMY_MAIN (see the autoconf manual), for the same\n#   reason.\n#\n#   The user may also use --with-lapack=<lib> in order to use some specific\n#   LAPACK library <lib>. In order to link successfully, however, be aware\n#   that you will probably need to use the same Fortran compiler (which can\n#   be set via the F77 env. var.) as was used to compile the LAPACK and BLAS\n#   libraries.\n#\n#   ACTION-IF-FOUND is a list of shell commands to run if a LAPACK library\n#   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it\n#   is not found. If ACTION-IF-FOUND is not specified, the default action\n#   will define HAVE_LAPACK.\n#\n# LICENSE\n#\n#   Copyright (c) 2009 Steven G. Johnson <stevenj@alum.mit.edu>\n#   Copyright (c) 2019 Geoffrey M. Oxberry <goxberry@gmail.com>\n#\n#   This program is free software: you can redistribute it and/or modify it\n#   under the terms of the GNU General Public License as published by the\n#   Free Software Foundation, either version 3 of the License, or (at your\n#   option) any later version.\n#\n#   This program is distributed in the hope that it will be useful, but\n#   WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n#   Public License for more details.\n#\n#   You should have received a copy of the GNU General Public License along\n#   with this program. If not, see <https://www.gnu.org/licenses/>.\n#\n#   As a special exception, the respective Autoconf Macro's copyright owner\n#   gives unlimited permission to copy, distribute and modify the configure\n#   scripts that are the output of Autoconf when processing the Macro. You\n#   need not follow the terms of the GNU General Public License when using\n#   or distributing such scripts, even though portions of the text of the\n#   Macro appear in them. The GNU General Public License (GPL) does govern\n#   all other use of the material that constitutes the Autoconf Macro.\n#\n#   This special exception to the GPL applies to versions of the Autoconf\n#   Macro released by the Autoconf Archive. When you make and distribute a\n#   modified version of the Autoconf Macro, you may extend this special\n#   exception to the GPL to apply to your modified version as well.\n\n#serial 10\n\nAU_ALIAS([ACX_LAPACK], [AX_LAPACK])\nAC_DEFUN([AX_LAPACK], [\nAC_REQUIRE([AX_BLAS])\nax_lapack_ok=no\n\nAC_ARG_WITH(lapack,\n        [AS_HELP_STRING([--with-lapack=<lib>], [use LAPACK library <lib>])])\ncase $with_lapack in\n        yes | \"\") ;;\n        no) ax_lapack_ok=disable ;;\n        -* | */* | *.a | *.so | *.so.* | *.dylib | *.dylib.* | *.o)\n                 LAPACK_LIBS=\"$with_lapack\"\n        ;;\n        *) LAPACK_LIBS=\"-l$with_lapack\" ;;\nesac\n\n# Get fortran linker name of LAPACK function to check for.\nAC_F77_FUNC(cheev)\n\n# We cannot use LAPACK if BLAS is not found\nif test \"x$ax_blas_ok\" != xyes; then\n        ax_lapack_ok=noblas\n        LAPACK_LIBS=\"\"\nfi\n\n# First, check LAPACK_LIBS environment variable\nif test \"x$LAPACK_LIBS\" != x; then\n        save_LIBS=\"$LIBS\"; LIBS=\"$LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS\"\n        AC_MSG_CHECKING([for $cheev in $LAPACK_LIBS])\n        AC_LINK_IFELSE([AC_LANG_CALL([], [$cheev])], [ax_lapack_ok=yes], [LAPACK_LIBS=\"\"])\n        AC_MSG_RESULT($ax_lapack_ok)\n        LIBS=\"$save_LIBS\"\n        if test $ax_lapack_ok = no; then\n                LAPACK_LIBS=\"\"\n        fi\nfi\n\n# LAPACK linked to by default?  (is sometimes included in BLAS lib)\nif test $ax_lapack_ok = no; then\n        save_LIBS=\"$LIBS\"; LIBS=\"$LIBS $BLAS_LIBS $FLIBS\"\n        AC_CHECK_FUNC($cheev, [ax_lapack_ok=yes])\n        LIBS=\"$save_LIBS\"\nfi\n\n# Generic LAPACK library?\nfor lapack in lapack lapack_rs6k; do\n        if test $ax_lapack_ok = no; then\n                save_LIBS=\"$LIBS\"; LIBS=\"$BLAS_LIBS $LIBS\"\n                AC_CHECK_LIB($lapack, $cheev,\n                    [ax_lapack_ok=yes; LAPACK_LIBS=\"-l$lapack\"], [], [$FLIBS])\n                LIBS=\"$save_LIBS\"\n        fi\ndone\n\nAC_SUBST(LAPACK_LIBS)\n\n# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:\nif test x\"$ax_lapack_ok\" = xyes; then\n        ifelse([$1],,AC_DEFINE(HAVE_LAPACK,1,[Define if you have LAPACK library.]),[$1])\n        :\nelse\n        ax_lapack_ok=no\n        $2\nfi\n])dnl AX_LAPACK\n"
  },
  {
    "path": "m4/ax_openmp.m4",
    "content": "# ===========================================================================\n#        https://www.gnu.org/software/autoconf-archive/ax_openmp.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_OPENMP([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])\n#\n# DESCRIPTION\n#\n#   This macro tries to find out how to compile programs that use OpenMP a\n#   standard API and set of compiler directives for parallel programming\n#   (see http://www-unix.mcs/)\n#\n#   On success, it sets the OPENMP_CFLAGS/OPENMP_CXXFLAGS/OPENMP_F77FLAGS\n#   output variable to the flag (e.g. -omp) used both to compile *and* link\n#   OpenMP programs in the current language.\n#\n#   NOTE: You are assumed to not only compile your program with these flags,\n#   but also link it with them as well.\n#\n#   If you want to compile everything with OpenMP, you should set:\n#\n#     CFLAGS=\"$CFLAGS $OPENMP_CFLAGS\"\n#     #OR#  CXXFLAGS=\"$CXXFLAGS $OPENMP_CXXFLAGS\"\n#     #OR#  FFLAGS=\"$FFLAGS $OPENMP_FFLAGS\"\n#\n#   (depending on the selected language).\n#\n#   The user can override the default choice by setting the corresponding\n#   environment variable (e.g. OPENMP_CFLAGS).\n#\n#   ACTION-IF-FOUND is a list of shell commands to run if an OpenMP flag is\n#   found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it is\n#   not found. If ACTION-IF-FOUND is not specified, the default action will\n#   define HAVE_OPENMP.\n#\n# LICENSE\n#\n#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>\n#   Copyright (c) 2015 John W. Peterson <jwpeterson@gmail.com>\n#   Copyright (c) 2016 Nick R. Papior <nickpapior@gmail.com>\n#\n#   This program is free software: you can redistribute it and/or modify it\n#   under the terms of the GNU General Public License as published by the\n#   Free Software Foundation, either version 3 of the License, or (at your\n#   option) any later version.\n#\n#   This program is distributed in the hope that it will be useful, but\n#   WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n#   Public License for more details.\n#\n#   You should have received a copy of the GNU General Public License along\n#   with this program. If not, see <https://www.gnu.org/licenses/>.\n#\n#   As a special exception, the respective Autoconf Macro's copyright owner\n#   gives unlimited permission to copy, distribute and modify the configure\n#   scripts that are the output of Autoconf when processing the Macro. You\n#   need not follow the terms of the GNU General Public License when using\n#   or distributing such scripts, even though portions of the text of the\n#   Macro appear in them. The GNU General Public License (GPL) does govern\n#   all other use of the material that constitutes the Autoconf Macro.\n#\n#   This special exception to the GPL applies to versions of the Autoconf\n#   Macro released by the Autoconf Archive. When you make and distribute a\n#   modified version of the Autoconf Macro, you may extend this special\n#   exception to the GPL to apply to your modified version as well.\n\n#serial 14\n\nAC_DEFUN([AX_OPENMP], [\nAC_PREREQ([2.69]) dnl for _AC_LANG_PREFIX\n\nAC_CACHE_CHECK([for OpenMP flag of _AC_LANG compiler], ax_cv_[]_AC_LANG_ABBREV[]_openmp, [save[]_AC_LANG_PREFIX[]FLAGS=$[]_AC_LANG_PREFIX[]FLAGS\nax_cv_[]_AC_LANG_ABBREV[]_openmp=unknown\n# Flags to try:  -fopenmp (gcc), -mp (SGI & PGI),\n#                -qopenmp (icc>=15), -openmp (icc),\n#                -xopenmp (Sun), -omp (Tru64),\n#                -qsmp=omp (AIX),\n#                none\nax_openmp_flags=\"-fopenmp -openmp -qopenmp -mp -xopenmp -omp -qsmp=omp none\"\nif test \"x$OPENMP_[]_AC_LANG_PREFIX[]FLAGS\" != x; then\n  ax_openmp_flags=\"$OPENMP_[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flags\"\nfi\nfor ax_openmp_flag in $ax_openmp_flags; do\n  case $ax_openmp_flag in\n    none) []_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[] ;;\n    *) []_AC_LANG_PREFIX[]FLAGS=\"$save[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flag\" ;;\n  esac\n  AC_LINK_IFELSE([AC_LANG_SOURCE([[\n@%:@include <omp.h>\n\nstatic void\nparallel_fill(int * data, int n)\n{\n  int i;\n@%:@pragma omp parallel for\n  for (i = 0; i < n; ++i)\n    data[i] = i;\n}\n\nint\nmain(void)\n{\n  int arr[100000];\n  omp_set_num_threads(2);\n  parallel_fill(arr, 100000);\n  return 0;\n}\n]])],[ax_cv_[]_AC_LANG_ABBREV[]_openmp=$ax_openmp_flag; break],[])\ndone\n[]_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[]FLAGS\n])\nif test \"x$ax_cv_[]_AC_LANG_ABBREV[]_openmp\" = \"xunknown\"; then\n  m4_default([$2],:)\nelse\n  if test \"x$ax_cv_[]_AC_LANG_ABBREV[]_openmp\" != \"xnone\"; then\n    OPENMP_[]_AC_LANG_PREFIX[]FLAGS=$ax_cv_[]_AC_LANG_ABBREV[]_openmp\n  fi\n  m4_default([$1], [AC_DEFINE(HAVE_OPENMP,1,[Define if OpenMP is enabled])])\nfi\n])dnl AX_OPENMP\n"
  },
  {
    "path": "m4/ax_pthread.m4",
    "content": "# ===========================================================================\n#        https://www.gnu.org/software/autoconf-archive/ax_pthread.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])\n#\n# DESCRIPTION\n#\n#   This macro figures out how to build C programs using POSIX threads. It\n#   sets the PTHREAD_LIBS output variable to the threads library and linker\n#   flags, and the PTHREAD_CFLAGS output variable to any special C compiler\n#   flags that are needed. (The user can also force certain compiler\n#   flags/libs to be tested by setting these environment variables.)\n#\n#   Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is\n#   needed for multi-threaded programs (defaults to the value of CC\n#   respectively CXX otherwise). (This is necessary on e.g. AIX to use the\n#   special cc_r/CC_r compiler alias.)\n#\n#   NOTE: You are assumed to not only compile your program with these flags,\n#   but also to link with them as well. For example, you might link with\n#   $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS\n#   $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS\n#\n#   If you are only building threaded programs, you may wish to use these\n#   variables in your default LIBS, CFLAGS, and CC:\n#\n#     LIBS=\"$PTHREAD_LIBS $LIBS\"\n#     CFLAGS=\"$CFLAGS $PTHREAD_CFLAGS\"\n#     CXXFLAGS=\"$CXXFLAGS $PTHREAD_CFLAGS\"\n#     CC=\"$PTHREAD_CC\"\n#     CXX=\"$PTHREAD_CXX\"\n#\n#   In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant\n#   has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to\n#   that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).\n#\n#   Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the\n#   PTHREAD_PRIO_INHERIT symbol is defined when compiling with\n#   PTHREAD_CFLAGS.\n#\n#   ACTION-IF-FOUND is a list of shell commands to run if a threads library\n#   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it\n#   is not found. If ACTION-IF-FOUND is not specified, the default action\n#   will define HAVE_PTHREAD.\n#\n#   Please let the authors know if this macro fails on any platform, or if\n#   you have any other suggestions or comments. This macro was based on work\n#   by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help\n#   from M. Frigo), as well as ac_pthread and hb_pthread macros posted by\n#   Alejandro Forero Cuervo to the autoconf macro repository. We are also\n#   grateful for the helpful feedback of numerous users.\n#\n#   Updated for Autoconf 2.68 by Daniel Richard G.\n#\n# LICENSE\n#\n#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>\n#   Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>\n#   Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>\n#\n#   This program is free software: you can redistribute it and/or modify it\n#   under the terms of the GNU General Public License as published by the\n#   Free Software Foundation, either version 3 of the License, or (at your\n#   option) any later version.\n#\n#   This program is distributed in the hope that it will be useful, but\n#   WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n#   Public License for more details.\n#\n#   You should have received a copy of the GNU General Public License along\n#   with this program. If not, see <https://www.gnu.org/licenses/>.\n#\n#   As a special exception, the respective Autoconf Macro's copyright owner\n#   gives unlimited permission to copy, distribute and modify the configure\n#   scripts that are the output of Autoconf when processing the Macro. You\n#   need not follow the terms of the GNU General Public License when using\n#   or distributing such scripts, even though portions of the text of the\n#   Macro appear in them. The GNU General Public License (GPL) does govern\n#   all other use of the material that constitutes the Autoconf Macro.\n#\n#   This special exception to the GPL applies to versions of the Autoconf\n#   Macro released by the Autoconf Archive. When you make and distribute a\n#   modified version of the Autoconf Macro, you may extend this special\n#   exception to the GPL to apply to your modified version as well.\n\n#serial 31\n\nAU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])\nAC_DEFUN([AX_PTHREAD], [\nAC_REQUIRE([AC_CANONICAL_HOST])\nAC_REQUIRE([AC_PROG_CC])\nAC_REQUIRE([AC_PROG_SED])\nAC_LANG_PUSH([C])\nax_pthread_ok=no\n\n# We used to check for pthread.h first, but this fails if pthread.h\n# requires special compiler flags (e.g. on Tru64 or Sequent).\n# It gets checked for in the link test anyway.\n\n# First of all, check if the user has set any of the PTHREAD_LIBS,\n# etcetera environment variables, and if threads linking works using\n# them:\nif test \"x$PTHREAD_CFLAGS$PTHREAD_LIBS\" != \"x\"; then\n        ax_pthread_save_CC=\"$CC\"\n        ax_pthread_save_CFLAGS=\"$CFLAGS\"\n        ax_pthread_save_LIBS=\"$LIBS\"\n        AS_IF([test \"x$PTHREAD_CC\" != \"x\"], [CC=\"$PTHREAD_CC\"])\n        AS_IF([test \"x$PTHREAD_CXX\" != \"x\"], [CXX=\"$PTHREAD_CXX\"])\n        CFLAGS=\"$CFLAGS $PTHREAD_CFLAGS\"\n        LIBS=\"$PTHREAD_LIBS $LIBS\"\n        AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])\n        AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])\n        AC_MSG_RESULT([$ax_pthread_ok])\n        if test \"x$ax_pthread_ok\" = \"xno\"; then\n                PTHREAD_LIBS=\"\"\n                PTHREAD_CFLAGS=\"\"\n        fi\n        CC=\"$ax_pthread_save_CC\"\n        CFLAGS=\"$ax_pthread_save_CFLAGS\"\n        LIBS=\"$ax_pthread_save_LIBS\"\nfi\n\n# We must check for the threads library under a number of different\n# names; the ordering is very important because some systems\n# (e.g. DEC) have both -lpthread and -lpthreads, where one of the\n# libraries is broken (non-POSIX).\n\n# Create a list of thread flags to try. Items with a \",\" contain both\n# C compiler flags (before \",\") and linker flags (after \",\"). Other items\n# starting with a \"-\" are C compiler flags, and remaining items are\n# library names, except for \"none\" which indicates that we try without\n# any flags at all, and \"pthread-config\" which is a program returning\n# the flags for the Pth emulation library.\n\nax_pthread_flags=\"pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config\"\n\n# The ordering *is* (sometimes) important.  Some notes on the\n# individual items follow:\n\n# pthreads: AIX (must check this before -lpthread)\n# none: in case threads are in libc; should be tried before -Kthread and\n#       other compiler flags to prevent continual compiler warnings\n# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)\n# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64\n#           (Note: HP C rejects this with \"bad form for `-t' option\")\n# -pthreads: Solaris/gcc (Note: HP C also rejects)\n# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it\n#      doesn't hurt to check since this sometimes defines pthreads and\n#      -D_REENTRANT too), HP C (must be checked before -lpthread, which\n#      is present but should not be used directly; and before -mthreads,\n#      because the compiler interprets this as \"-mt\" + \"-hreads\")\n# -mthreads: Mingw32/gcc, Lynx/gcc\n# pthread: Linux, etcetera\n# --thread-safe: KAI C++\n# pthread-config: use pthread-config program (for GNU Pth library)\n\ncase $host_os in\n\n        freebsd*)\n\n        # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)\n        # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)\n\n        ax_pthread_flags=\"-kthread lthread $ax_pthread_flags\"\n        ;;\n\n        hpux*)\n\n        # From the cc(1) man page: \"[-mt] Sets various -D flags to enable\n        # multi-threading and also sets -lpthread.\"\n\n        ax_pthread_flags=\"-mt -pthread pthread $ax_pthread_flags\"\n        ;;\n\n        openedition*)\n\n        # IBM z/OS requires a feature-test macro to be defined in order to\n        # enable POSIX threads at all, so give the user a hint if this is\n        # not set. (We don't define these ourselves, as they can affect\n        # other portions of the system API in unpredictable ways.)\n\n        AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],\n            [\n#            if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)\n             AX_PTHREAD_ZOS_MISSING\n#            endif\n            ],\n            [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])\n        ;;\n\n        solaris*)\n\n        # On Solaris (at least, for some versions), libc contains stubbed\n        # (non-functional) versions of the pthreads routines, so link-based\n        # tests will erroneously succeed. (N.B.: The stubs are missing\n        # pthread_cleanup_push, or rather a function called by this macro,\n        # so we could check for that, but who knows whether they'll stub\n        # that too in a future libc.)  So we'll check first for the\n        # standard Solaris way of linking pthreads (-mt -lpthread).\n\n        ax_pthread_flags=\"-mt,-lpthread pthread $ax_pthread_flags\"\n        ;;\nesac\n\n# Are we compiling with Clang?\n\nAC_CACHE_CHECK([whether $CC is Clang],\n    [ax_cv_PTHREAD_CLANG],\n    [ax_cv_PTHREAD_CLANG=no\n     # Note that Autoconf sets GCC=yes for Clang as well as GCC\n     if test \"x$GCC\" = \"xyes\"; then\n        AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],\n            [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */\n#            if defined(__clang__) && defined(__llvm__)\n             AX_PTHREAD_CC_IS_CLANG\n#            endif\n            ],\n            [ax_cv_PTHREAD_CLANG=yes])\n     fi\n    ])\nax_pthread_clang=\"$ax_cv_PTHREAD_CLANG\"\n\n\n# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)\n\n# Note that for GCC and Clang -pthread generally implies -lpthread,\n# except when -nostdlib is passed.\n# This is problematic using libtool to build C++ shared libraries with pthread:\n# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460\n# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333\n# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555\n# To solve this, first try -pthread together with -lpthread for GCC\n\nAS_IF([test \"x$GCC\" = \"xyes\"],\n      [ax_pthread_flags=\"-pthread,-lpthread -pthread -pthreads $ax_pthread_flags\"])\n\n# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first\n\nAS_IF([test \"x$ax_pthread_clang\" = \"xyes\"],\n      [ax_pthread_flags=\"-pthread,-lpthread -pthread\"])\n\n\n# The presence of a feature test macro requesting re-entrant function\n# definitions is, on some systems, a strong hint that pthreads support is\n# correctly enabled\n\ncase $host_os in\n        darwin* | hpux* | linux* | osf* | solaris*)\n        ax_pthread_check_macro=\"_REENTRANT\"\n        ;;\n\n        aix*)\n        ax_pthread_check_macro=\"_THREAD_SAFE\"\n        ;;\n\n        *)\n        ax_pthread_check_macro=\"--\"\n        ;;\nesac\nAS_IF([test \"x$ax_pthread_check_macro\" = \"x--\"],\n      [ax_pthread_check_cond=0],\n      [ax_pthread_check_cond=\"!defined($ax_pthread_check_macro)\"])\n\n\nif test \"x$ax_pthread_ok\" = \"xno\"; then\nfor ax_pthread_try_flag in $ax_pthread_flags; do\n\n        case $ax_pthread_try_flag in\n                none)\n                AC_MSG_CHECKING([whether pthreads work without any flags])\n                ;;\n\n                *,*)\n                PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed \"s/^\\(.*\\),\\(.*\\)$/\\1/\"`\n                PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed \"s/^\\(.*\\),\\(.*\\)$/\\2/\"`\n                AC_MSG_CHECKING([whether pthreads work with \"$PTHREAD_CFLAGS\" and \"$PTHREAD_LIBS\"])\n                ;;\n\n                -*)\n                AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])\n                PTHREAD_CFLAGS=\"$ax_pthread_try_flag\"\n                ;;\n\n                pthread-config)\n                AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])\n                AS_IF([test \"x$ax_pthread_config\" = \"xno\"], [continue])\n                PTHREAD_CFLAGS=\"`pthread-config --cflags`\"\n                PTHREAD_LIBS=\"`pthread-config --ldflags` `pthread-config --libs`\"\n                ;;\n\n                *)\n                AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])\n                PTHREAD_LIBS=\"-l$ax_pthread_try_flag\"\n                ;;\n        esac\n\n        ax_pthread_save_CFLAGS=\"$CFLAGS\"\n        ax_pthread_save_LIBS=\"$LIBS\"\n        CFLAGS=\"$CFLAGS $PTHREAD_CFLAGS\"\n        LIBS=\"$PTHREAD_LIBS $LIBS\"\n\n        # Check for various functions.  We must include pthread.h,\n        # since some functions may be macros.  (On the Sequent, we\n        # need a special flag -Kthread to make this header compile.)\n        # We check for pthread_join because it is in -lpthread on IRIX\n        # while pthread_create is in libc.  We check for pthread_attr_init\n        # due to DEC craziness with -lpthreads.  We check for\n        # pthread_cleanup_push because it is one of the few pthread\n        # functions on Solaris that doesn't have a non-functional libc stub.\n        # We try pthread_create on general principles.\n\n        AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>\n#                       if $ax_pthread_check_cond\n#                        error \"$ax_pthread_check_macro must be defined\"\n#                       endif\n                        static void *some_global = NULL;\n                        static void routine(void *a)\n                          {\n                             /* To avoid any unused-parameter or\n                                unused-but-set-parameter warning.  */\n                             some_global = a;\n                          }\n                        static void *start_routine(void *a) { return a; }],\n                       [pthread_t th; pthread_attr_t attr;\n                        pthread_create(&th, 0, start_routine, 0);\n                        pthread_join(th, 0);\n                        pthread_attr_init(&attr);\n                        pthread_cleanup_push(routine, 0);\n                        pthread_cleanup_pop(0) /* ; */])],\n            [ax_pthread_ok=yes],\n            [])\n\n        CFLAGS=\"$ax_pthread_save_CFLAGS\"\n        LIBS=\"$ax_pthread_save_LIBS\"\n\n        AC_MSG_RESULT([$ax_pthread_ok])\n        AS_IF([test \"x$ax_pthread_ok\" = \"xyes\"], [break])\n\n        PTHREAD_LIBS=\"\"\n        PTHREAD_CFLAGS=\"\"\ndone\nfi\n\n\n# Clang needs special handling, because older versions handle the -pthread\n# option in a rather... idiosyncratic way\n\nif test \"x$ax_pthread_clang\" = \"xyes\"; then\n\n        # Clang takes -pthread; it has never supported any other flag\n\n        # (Note 1: This will need to be revisited if a system that Clang\n        # supports has POSIX threads in a separate library.  This tends not\n        # to be the way of modern systems, but it's conceivable.)\n\n        # (Note 2: On some systems, notably Darwin, -pthread is not needed\n        # to get POSIX threads support; the API is always present and\n        # active.  We could reasonably leave PTHREAD_CFLAGS empty.  But\n        # -pthread does define _REENTRANT, and while the Darwin headers\n        # ignore this macro, third-party headers might not.)\n\n        # However, older versions of Clang make a point of warning the user\n        # that, in an invocation where only linking and no compilation is\n        # taking place, the -pthread option has no effect (\"argument unused\n        # during compilation\").  They expect -pthread to be passed in only\n        # when source code is being compiled.\n        #\n        # Problem is, this is at odds with the way Automake and most other\n        # C build frameworks function, which is that the same flags used in\n        # compilation (CFLAGS) are also used in linking.  Many systems\n        # supported by AX_PTHREAD require exactly this for POSIX threads\n        # support, and in fact it is often not straightforward to specify a\n        # flag that is used only in the compilation phase and not in\n        # linking.  Such a scenario is extremely rare in practice.\n        #\n        # Even though use of the -pthread flag in linking would only print\n        # a warning, this can be a nuisance for well-run software projects\n        # that build with -Werror.  So if the active version of Clang has\n        # this misfeature, we search for an option to squash it.\n\n        AC_CACHE_CHECK([whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread],\n            [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],\n            [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown\n             # Create an alternate version of $ac_link that compiles and\n             # links in two steps (.c -> .o, .o -> exe) instead of one\n             # (.c -> exe), because the warning occurs only in the second\n             # step\n             ax_pthread_save_ac_link=\"$ac_link\"\n             ax_pthread_sed='s/conftest\\.\\$ac_ext/conftest.$ac_objext/g'\n             ax_pthread_link_step=`AS_ECHO([\"$ac_link\"]) | sed \"$ax_pthread_sed\"`\n             ax_pthread_2step_ac_link=\"($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)\"\n             ax_pthread_save_CFLAGS=\"$CFLAGS\"\n             for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do\n                AS_IF([test \"x$ax_pthread_try\" = \"xunknown\"], [break])\n                CFLAGS=\"-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS\"\n                ac_link=\"$ax_pthread_save_ac_link\"\n                AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],\n                    [ac_link=\"$ax_pthread_2step_ac_link\"\n                     AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],\n                         [break])\n                    ])\n             done\n             ac_link=\"$ax_pthread_save_ac_link\"\n             CFLAGS=\"$ax_pthread_save_CFLAGS\"\n             AS_IF([test \"x$ax_pthread_try\" = \"x\"], [ax_pthread_try=no])\n             ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=\"$ax_pthread_try\"\n            ])\n\n        case \"$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG\" in\n                no | unknown) ;;\n                *) PTHREAD_CFLAGS=\"$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS\" ;;\n        esac\n\nfi # $ax_pthread_clang = yes\n\n\n\n# Various other checks:\nif test \"x$ax_pthread_ok\" = \"xyes\"; then\n        ax_pthread_save_CFLAGS=\"$CFLAGS\"\n        ax_pthread_save_LIBS=\"$LIBS\"\n        CFLAGS=\"$CFLAGS $PTHREAD_CFLAGS\"\n        LIBS=\"$PTHREAD_LIBS $LIBS\"\n\n        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.\n        AC_CACHE_CHECK([for joinable pthread attribute],\n            [ax_cv_PTHREAD_JOINABLE_ATTR],\n            [ax_cv_PTHREAD_JOINABLE_ATTR=unknown\n             for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do\n                 AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],\n                                                 [int attr = $ax_pthread_attr; return attr /* ; */])],\n                                [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],\n                                [])\n             done\n            ])\n        AS_IF([test \"x$ax_cv_PTHREAD_JOINABLE_ATTR\" != \"xunknown\" && \\\n               test \"x$ax_cv_PTHREAD_JOINABLE_ATTR\" != \"xPTHREAD_CREATE_JOINABLE\" && \\\n               test \"x$ax_pthread_joinable_attr_defined\" != \"xyes\"],\n              [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],\n                                  [$ax_cv_PTHREAD_JOINABLE_ATTR],\n                                  [Define to necessary symbol if this constant\n                                   uses a non-standard name on your system.])\n               ax_pthread_joinable_attr_defined=yes\n              ])\n\n        AC_CACHE_CHECK([whether more special flags are required for pthreads],\n            [ax_cv_PTHREAD_SPECIAL_FLAGS],\n            [ax_cv_PTHREAD_SPECIAL_FLAGS=no\n             case $host_os in\n             solaris*)\n             ax_cv_PTHREAD_SPECIAL_FLAGS=\"-D_POSIX_PTHREAD_SEMANTICS\"\n             ;;\n             esac\n            ])\n        AS_IF([test \"x$ax_cv_PTHREAD_SPECIAL_FLAGS\" != \"xno\" && \\\n               test \"x$ax_pthread_special_flags_added\" != \"xyes\"],\n              [PTHREAD_CFLAGS=\"$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS\"\n               ax_pthread_special_flags_added=yes])\n\n        AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],\n            [ax_cv_PTHREAD_PRIO_INHERIT],\n            [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],\n                                             [[int i = PTHREAD_PRIO_INHERIT;\n                                               return i;]])],\n                            [ax_cv_PTHREAD_PRIO_INHERIT=yes],\n                            [ax_cv_PTHREAD_PRIO_INHERIT=no])\n            ])\n        AS_IF([test \"x$ax_cv_PTHREAD_PRIO_INHERIT\" = \"xyes\" && \\\n               test \"x$ax_pthread_prio_inherit_defined\" != \"xyes\"],\n              [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])\n               ax_pthread_prio_inherit_defined=yes\n              ])\n\n        CFLAGS=\"$ax_pthread_save_CFLAGS\"\n        LIBS=\"$ax_pthread_save_LIBS\"\n\n        # More AIX lossage: compile with *_r variant\n        if test \"x$GCC\" != \"xyes\"; then\n            case $host_os in\n                aix*)\n                AS_CASE([\"x/$CC\"],\n                    [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],\n                    [#handle absolute path differently from PATH based program lookup\n                     AS_CASE([\"x$CC\"],\n                         [x/*],\n                         [\n\t\t\t   AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC=\"${CC}_r\"])\n\t\t\t   AS_IF([test \"x${CXX}\" != \"x\"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX=\"${CXX}_r\"])])\n\t\t\t ],\n                         [\n\t\t\t   AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])\n\t\t\t   AS_IF([test \"x${CXX}\" != \"x\"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])\n\t\t\t ]\n                     )\n                    ])\n                ;;\n            esac\n        fi\nfi\n\ntest -n \"$PTHREAD_CC\" || PTHREAD_CC=\"$CC\"\ntest -n \"$PTHREAD_CXX\" || PTHREAD_CXX=\"$CXX\"\n\nAC_SUBST([PTHREAD_LIBS])\nAC_SUBST([PTHREAD_CFLAGS])\nAC_SUBST([PTHREAD_CC])\nAC_SUBST([PTHREAD_CXX])\n\n# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:\nif test \"x$ax_pthread_ok\" = \"xyes\"; then\n        ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])\n        :\nelse\n        ax_pthread_ok=no\n        $2\nfi\nAC_LANG_POP\n])dnl AX_PTHREAD\n"
  },
  {
    "path": "m4/module.mk",
    "content": "EXTRA_DIST += \\\n  %reldir%/module.mk \\\n  %reldir%/ax_blas.m4 \\\n  %reldir%/ax_compare_version.m4 \\\n  %reldir%/ax_cxx_compile_stdcxx.m4 \\\n  %reldir%/ax_lapack.m4 \\\n  %reldir%/ax_openmp.m4 \\\n  %reldir%/ax_pthread.m4 \\\n  %reldir%/gnulib-cache.m4 \\\n  %reldir%/libtool.m4 \\\n  %reldir%/ltoptions.m4 \\\n  %reldir%/ltsugar.m4 \\\n  %reldir%/ltversion.m4 \\\n  %reldir%/lt~obsolete.m4 \\\n  %reldir%/octave_blas.m4 \\\n  %reldir%/pkg.m4\n"
  },
  {
    "path": "m4/octave_blas.m4",
    "content": "dnl --------------------------------------------------------------------\ndnl\ndnl Copyright (C) 2022-2026 The Octave Project Developers\ndnl\ndnl See the file COPYRIGHT.md in the top-level directory of this\ndnl distribution or <https://octave.org/copyright/>.\ndnl\ndnl This file is part of Octave.\ndnl\ndnl Octave is free software: you can redistribute it and/or modify it\ndnl under the terms of the GNU General Public License as published by\ndnl the Free Software Foundation, either version 3 of the License, or\ndnl (at your option) any later version.\ndnl\ndnl Octave is distributed in the hope that it will be useful, but\ndnl WITHOUT ANY WARRANTY; without even the implied warranty of\ndnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\ndnl GNU General Public License for more details.\ndnl\ndnl You should have received a copy of the GNU General Public License\ndnl along with Octave; see the file COPYING.  If not, see\ndnl <https://www.gnu.org/licenses/>.\ndnl\ndnl --------------------------------------------------------------------\ndnl\ndnl Check for BLAS library and, if valid, determine integer size of library\ndnl\nAC_DEFUN([OCTAVE_BLAS], [\n  AC_PREREQ(2.50)\n  dnl Call reference macro to find BLAS library\n  AX_BLAS\n\n  if test \"$cross_compiling\" = yes ; then\n    dnl Assume BLAS library exists when cross compiling\n    ax_blas_ok=yes\n    AC_MSG_CHECKING([BLAS can be called from Fortran])\n    AC_MSG_RESULT([yes assumed for cross compilation])\n    dnl Assume generic 4-byte BLAS library if not specified\n    AC_MSG_CHECKING([BLAS library integer size])\n    if test -z \"$ax_cv_blas_integer_size\" ; then\n      ax_cv_blas_integer_size=4\n    fi\n    AC_MSG_RESULT([$ax_cv_blas_integer_size assumed for cross compilation])\n  elif test $ax_blas_ok = yes; then\n    ac_octave_save_LIBS=\"$LIBS\"\n    LIBS=\"$BLAS_LIBS $LIBS\"\n    AC_LANG_PUSH(Fortran 77)\n    # Check if BLAS functions with single precision return value work\n    # correctly\n    AC_CACHE_CHECK([whether BLAS functions with single precision return value work correctly],\n      [octave_cv_working_blas_single_precision],\n      [AC_RUN_IFELSE([AC_LANG_PROGRAM(,[[\n      implicit none\n      real d\n      real x(2), y(2)\n      real sdot\n\n      data x /1.0, 2.0/\n      data y /3.0, 4.0/\n\n      d = sdot (2, x, 1, y, 1)\n*     print *, 'result: ', d\n\nc Some implementations of BLAS (e.g., the one from Apple Accelerate)\nc erroneously return a *double*-precision floating point value for functions\nc that should be returning a single-precision floating point value.\nc Check if the result for SDOT is correct if we (correctly) assume that it\nc returns a single-precision floating point value.\n\n      if (d .ne. 11.0) then\n        stop 1\n      endif\n\n        ]])],\n        octave_cv_working_blas_single_precision=yes,\n        octave_cv_working_blas_single_precision=no)\n      ])\n    if test \"$octave_cv_working_blas_single_precision\" != yes; then\n      AC_MSG_ERROR([The function SDOT does not work correctly with the selected BLAS library. Use a different implementation of BLAS.])\n    fi\n\n    ## Check BLAS library integer size.\n    ## If it does not appear to be 8 bytes, we assume it is 4 bytes.\n    ## FIXME: this may fail with options like -ftrapping-math.\n    AC_CACHE_CHECK([BLAS library integer size],\n      [ax_cv_blas_integer_size],\n      [AC_RUN_IFELSE([AC_LANG_PROGRAM(,[[\n      integer*8 two, n\n      integer*4 n2(2)\n      double precision d, a(1), b(1), ddot\n      equivalence (n, n2)\n\n      a(1) = 1.0\n      b(1) = 1.0\n\nc Generate 2**32 + 1 in an 8-byte integer.  Whether we have a big\nc endian or little endian system, both 4-byte words of this value\nc should be 1.\n\n      two = 2\n      n = (two ** 32) + 1\n\nc Check that our expectation about the type conversions are correct.\n\n      if (n2(1) .ne. 1 .or. n2(2) .ne. 1) then\n        print *, 'invalid assumption about integer type conversion'\n        stop 2\n      endif\n\n*     print *, n, n2(1), n2(2)\n*     print *, a(1), b(1)\n\nc DDOT will either see 1 or a large value for N.  Since INCX and INCY\nc are both 0, we will never increment the index, so A and B only need to\nc have a single element.  If N is interpreted as 1 (BLAS compiled with\nc 4-byte integers) then the result will be 1.  If N is interpreted as a\nc large value (BLAS compiled with 8-byte integers) then the result will\nc be the summation a(1)*b(1) 2^32+1 times.  This will also take some\nc time to compute, but at least for now it is the unusual case so we are\nc much more likely to exit quickly after detecting that the BLAS library\nc was compiled with 4-byte integers.\n\n      d = ddot (n, a, 0, b, 0)\n\n*     print *, a(1), b(1), d\n\nc Success (0 exit status) means we detected BLAS compiled with\nc 8-byte integers.\n\n      if (d .eq. 1.0) then\n        stop 1\n      endif\n\n        ]])],\n        ax_cv_blas_integer_size=8,\n        ax_cv_blas_integer_size=4)\n      ])\n\n  AC_LANG_POP(Fortran 77)\n  LIBS=\"$ac_octave_save_LIBS\"\nfi\n\n])\n"
  },
  {
    "path": "m4/pkg.m4",
    "content": "# pkg.m4 - Macros to locate and use pkg-config.   -*- Autoconf -*-\n# serial 14 (pkgconf)\n\ndnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.\ndnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>\ndnl\ndnl This program is free software; you can redistribute it and/or modify\ndnl it under the terms of the GNU General Public License as published by\ndnl the Free Software Foundation; either version 2 of the License, or\ndnl (at your option) any later version.\ndnl\ndnl This program is distributed in the hope that it will be useful, but\ndnl WITHOUT ANY WARRANTY; without even the implied warranty of\ndnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\ndnl General Public License for more details.\ndnl\ndnl You should have received a copy of the GNU General Public License\ndnl along with this program; if not, see <https://www.gnu.org/licenses/>.\ndnl\ndnl As a special exception to the GNU General Public License, if you\ndnl distribute this file as part of a program that contains a\ndnl configuration script generated by Autoconf, you may include it under\ndnl the same distribution terms that you use for the rest of that\ndnl program.\n\ndnl PKG_PREREQ(MIN-VERSION)\ndnl -----------------------\ndnl Since: 0.29\ndnl\ndnl Verify that the version of the pkg-config macros are at least\ndnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's\ndnl installed version of pkg-config, this checks the developer's version\ndnl of pkg.m4 when generating configure.\ndnl\ndnl To ensure that this macro is defined, also add:\ndnl m4_ifndef([PKG_PREREQ],\ndnl     [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])\ndnl\ndnl See the \"Since\" comment for each macro you use to see what version\ndnl of the macros you require.\nm4_defun([PKG_PREREQ],\n[m4_define([PKG_MACROS_VERSION], [0.29.2])\nm4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,\n    [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])\n])dnl PKG_PREREQ\n\ndnl PKG_PROG_PKG_CONFIG([MIN-VERSION])\ndnl ----------------------------------\ndnl Since: 0.16\ndnl\ndnl Search for the pkg-config tool and set the PKG_CONFIG variable to\ndnl first found in the path. Checks that the version of pkg-config found\ndnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is\ndnl used since that's the first version where most current features of\ndnl pkg-config existed.\nAC_DEFUN([PKG_PROG_PKG_CONFIG],\n[m4_pattern_forbid([^_?PKG_[A-Z_]+$])\nm4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])\nm4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])\nAC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])\nAC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])\nAC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])\n\nif test \"x$ac_cv_env_PKG_CONFIG_set\" != \"xset\"; then\n\tAC_PATH_TOOL([PKG_CONFIG], [pkg-config])\nfi\nif test -n \"$PKG_CONFIG\"; then\n\t_pkg_min_version=m4_default([$1], [0.9.0])\n\tAC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])\n\tif $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then\n\t\tAC_MSG_RESULT([yes])\n\telse\n\t\tAC_MSG_RESULT([no])\n\t\tPKG_CONFIG=\"\"\n\tfi\nfi[]dnl\n])dnl PKG_PROG_PKG_CONFIG\n\ndnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])\ndnl -------------------------------------------------------------------\ndnl Since: 0.18\ndnl\ndnl Check to see whether a particular set of modules exists. Similar to\ndnl PKG_CHECK_MODULES(), but does not set variables or print errors.\ndnl\ndnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])\ndnl only at the first occurrence in configure.ac, so if the first place\ndnl it's called might be skipped (such as if it is within an \"if\", you\ndnl have to call PKG_CHECK_EXISTS manually\nAC_DEFUN([PKG_CHECK_EXISTS],\n[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl\nif test -n \"$PKG_CONFIG\" && \\\n    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors \"$1\"]); then\n  m4_default([$2], [:])\nm4_ifvaln([$3], [else\n  $3])dnl\nfi])\n\ndnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])\ndnl ---------------------------------------------\ndnl Internal wrapper calling pkg-config via PKG_CONFIG and setting\ndnl pkg_failed based on the result.\nm4_define([_PKG_CONFIG],\n[if test -n \"$$1\"; then\n    pkg_cv_[]$1=\"$$1\"\n elif test -n \"$PKG_CONFIG\"; then\n    PKG_CHECK_EXISTS([$3],\n                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 \"$3\" 2>/dev/null`\n\t\t      test \"x$?\" != \"x0\" && pkg_failed=yes ],\n\t\t     [pkg_failed=yes])\n else\n    pkg_failed=untried\nfi[]dnl\n])dnl _PKG_CONFIG\n\ndnl _PKG_SHORT_ERRORS_SUPPORTED\ndnl ---------------------------\ndnl Internal check to see if pkg-config supports short errors.\nAC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],\n[AC_REQUIRE([PKG_PROG_PKG_CONFIG])\nif $PKG_CONFIG --atleast-pkgconfig-version 0.20; then\n        _pkg_short_errors_supported=yes\nelse\n        _pkg_short_errors_supported=no\nfi[]dnl\n])dnl _PKG_SHORT_ERRORS_SUPPORTED\n\n\ndnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],\ndnl   [ACTION-IF-NOT-FOUND])\ndnl --------------------------------------------------------------\ndnl Since: 0.4.0\ndnl\ndnl Note that if there is a possibility the first call to\ndnl PKG_CHECK_MODULES might not happen, you should be sure to include an\ndnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac\nAC_DEFUN([PKG_CHECK_MODULES],\n[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl\nAC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl\nAC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl\n\npkg_failed=no\nAC_MSG_CHECKING([for $2])\n\n_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])\n_PKG_CONFIG([$1][_LIBS], [libs], [$2])\n\nm4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS\nand $1[]_LIBS to avoid the need to call pkg-config.\nSee the pkg-config man page for more details.])\n\nif test $pkg_failed = yes; then\n        AC_MSG_RESULT([no])\n        _PKG_SHORT_ERRORS_SUPPORTED\n        if test $_pkg_short_errors_supported = yes; then\n                $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs \"$2\" 2>&1`\n        else\n                $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs \"$2\" 2>&1`\n        fi\n        # Put the nasty error message in config.log where it belongs\n        echo \"$$1[]_PKG_ERRORS\" >&AS_MESSAGE_LOG_FD\n\n        m4_default([$4], [AC_MSG_ERROR(\n[Package requirements ($2) were not met:\n\n$$1_PKG_ERRORS\n\nConsider adjusting the PKG_CONFIG_PATH environment variable if you\ninstalled software in a non-standard prefix.\n\n_PKG_TEXT])[]dnl\n        ])\nelif test $pkg_failed = untried; then\n        AC_MSG_RESULT([no])\n        m4_default([$4], [AC_MSG_FAILURE(\n[The pkg-config script could not be found or is too old.  Make sure it\nis in your PATH or set the PKG_CONFIG environment variable to the full\npath to pkg-config.\n\n_PKG_TEXT\n\nTo get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl\n        ])\nelse\n        $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS\n        $1[]_LIBS=$pkg_cv_[]$1[]_LIBS\n        AC_MSG_RESULT([yes])\n        $3\nfi[]dnl\n])dnl PKG_CHECK_MODULES\n\n\ndnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],\ndnl   [ACTION-IF-NOT-FOUND])\ndnl ---------------------------------------------------------------------\ndnl Since: 0.29\ndnl\ndnl Checks for existence of MODULES and gathers its build flags with\ndnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags\ndnl and VARIABLE-PREFIX_LIBS from --libs.\ndnl\ndnl Note that if there is a possibility the first call to\ndnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to\ndnl include an explicit call to PKG_PROG_PKG_CONFIG in your\ndnl configure.ac.\nAC_DEFUN([PKG_CHECK_MODULES_STATIC],\n[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl\n_save_PKG_CONFIG=$PKG_CONFIG\nPKG_CONFIG=\"$PKG_CONFIG --static\"\nPKG_CHECK_MODULES($@)\nPKG_CONFIG=$_save_PKG_CONFIG[]dnl\n])dnl PKG_CHECK_MODULES_STATIC\n\n\ndnl PKG_INSTALLDIR([DIRECTORY])\ndnl -------------------------\ndnl Since: 0.27\ndnl\ndnl Substitutes the variable pkgconfigdir as the location where a module\ndnl should install pkg-config .pc files. By default the directory is\ndnl $libdir/pkgconfig, but the default can be changed by passing\ndnl DIRECTORY. The user can override through the --with-pkgconfigdir\ndnl parameter.\nAC_DEFUN([PKG_INSTALLDIR],\n[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])\nm4_pushdef([pkg_description],\n    [pkg-config installation directory @<:@]pkg_default[@:>@])\nAC_ARG_WITH([pkgconfigdir],\n    [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,\n    [with_pkgconfigdir=]pkg_default)\nAC_SUBST([pkgconfigdir], [$with_pkgconfigdir])\nm4_popdef([pkg_default])\nm4_popdef([pkg_description])\n])dnl PKG_INSTALLDIR\n\n\ndnl PKG_NOARCH_INSTALLDIR([DIRECTORY])\ndnl --------------------------------\ndnl Since: 0.27\ndnl\ndnl Substitutes the variable noarch_pkgconfigdir as the location where a\ndnl module should install arch-independent pkg-config .pc files. By\ndnl default the directory is $datadir/pkgconfig, but the default can be\ndnl changed by passing DIRECTORY. The user can override through the\ndnl --with-noarch-pkgconfigdir parameter.\nAC_DEFUN([PKG_NOARCH_INSTALLDIR],\n[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])\nm4_pushdef([pkg_description],\n    [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])\nAC_ARG_WITH([noarch-pkgconfigdir],\n    [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,\n    [with_noarch_pkgconfigdir=]pkg_default)\nAC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])\nm4_popdef([pkg_default])\nm4_popdef([pkg_description])\n])dnl PKG_NOARCH_INSTALLDIR\n\n\ndnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,\ndnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])\ndnl -------------------------------------------\ndnl Since: 0.28\ndnl\ndnl Retrieves the value of the pkg-config variable for the given module.\nAC_DEFUN([PKG_CHECK_VAR],\n[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl\nAC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl\n\n_PKG_CONFIG([$1], [variable=\"][$3][\"], [$2])\nAS_VAR_COPY([$1], [pkg_cv_][$1])\n\nAS_VAR_IF([$1], [\"\"], [$5], [$4])dnl\n])dnl PKG_CHECK_VAR\n\ndnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,\ndnl   [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],\ndnl   [DESCRIPTION], [DEFAULT])\ndnl ------------------------------------------\ndnl\ndnl Prepare a \"--with-\" configure option using the lowercase\ndnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and\ndnl PKG_CHECK_MODULES in a single macro.\nAC_DEFUN([PKG_WITH_MODULES],\n[\nm4_pushdef([with_arg], m4_tolower([$1]))\n\nm4_pushdef([description],\n           [m4_default([$5], [build with ]with_arg[ support])])\n\nm4_pushdef([def_arg], [m4_default([$6], [auto])])\nm4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])\nm4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])\n\nm4_case(def_arg,\n            [yes],[m4_pushdef([with_without], [--without-]with_arg)],\n            [m4_pushdef([with_without],[--with-]with_arg)])\n\nAC_ARG_WITH(with_arg,\n     AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,\n    [AS_TR_SH([with_]with_arg)=def_arg])\n\nAS_CASE([$AS_TR_SH([with_]with_arg)],\n            [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],\n            [auto],[PKG_CHECK_MODULES([$1],[$2],\n                                        [m4_n([def_action_if_found]) $3],\n                                        [m4_n([def_action_if_not_found]) $4])])\n\nm4_popdef([with_arg])\nm4_popdef([description])\nm4_popdef([def_arg])\n\n])dnl PKG_WITH_MODULES\n\ndnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,\ndnl   [DESCRIPTION], [DEFAULT])\ndnl -----------------------------------------------\ndnl\ndnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES\ndnl check._[VARIABLE-PREFIX] is exported as make variable.\nAC_DEFUN([PKG_HAVE_WITH_MODULES],\n[\nPKG_WITH_MODULES([$1],[$2],,,[$3],[$4])\n\nAM_CONDITIONAL([HAVE_][$1],\n               [test \"$AS_TR_SH([with_]m4_tolower([$1]))\" = \"yes\"])\n])dnl PKG_HAVE_WITH_MODULES\n\ndnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,\ndnl   [DESCRIPTION], [DEFAULT])\ndnl ------------------------------------------------------\ndnl\ndnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after\ndnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make\ndnl and preprocessor variable.\nAC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],\n[\nPKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])\n\nAS_IF([test \"$AS_TR_SH([with_]m4_tolower([$1]))\" = \"yes\"],\n        [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])\n])dnl PKG_HAVE_DEFINE_WITH_MODULES\n"
  },
  {
    "path": "oct-conf-post-private.in.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (HAVE_DEV_T)\ntypedef short dev_t;\n#endif\n\n#if ! defined (HAVE_INO_T)\ntypedef unsigned long ino_t;\n#endif\n\n#if defined (_MSC_VER)\n#  define __WIN32__ 1\n#  define WIN32 1\n   /* missing parameters in macros */\n#  pragma warning (disable: 4003)\n   /* missing implementations in template instantiation */\n#  pragma warning (disable: 4996)\n   /* deprecated function names (FIXME: ???) */\n#  pragma warning (disable: 4661)\n#endif\n\n#if defined (__APPLE__) && defined (__MACH__)\n#  define OCTAVE_USE_OS_X_API 1\n#endif\n\n/* Silence deprecated API warning from Apple OS > 10.14 */\n#if defined (__APPLE__) && defined (__MACH__) && defined (HAVE_OPENGL)\n#  define GL_SILENCE_DEPRECATION 1\n#endif\n\n/* Define to 1 if we expect to have <windows.h>, Sleep, etc. */\n#if defined (__WIN32__) && ! defined (__CYGWIN__)\n#  define OCTAVE_USE_WINDOWS_API 1\n#endif\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  define OCTAVE_HAVE_WINDOWS_FILESYSTEM 1\n#elif defined (__CYGWIN__)\n#  define OCTAVE_HAVE_WINDOWS_FILESYSTEM 1\n#  define OCTAVE_HAVE_POSIX_FILESYSTEM 1\n#else\n#  define OCTAVE_HAVE_POSIX_FILESYSTEM 1\n#endif\n\n/* sigsetjmp is a macro, not a function. */\n#if defined (sigsetjmp) && defined (HAVE_SIGLONGJMP)\n#  define OCTAVE_HAVE_SIG_JUMP 1\n#endif\n\n/* To be able to use long doubles for 64-bit mixed arithmetics, we need\n   them at least 80 bits wide and we need roundl declared in math.h.\n   FIXME: Maybe substitute this by a more precise check in the future?  */\n#if (SIZEOF_LONG_DOUBLE >= 10) && defined (HAVE_ROUNDL)\n#  define OCTAVE_INT_USE_LONG_DOUBLE\n#  if (SIZEOF_LONG_DOUBLE < 16                                          \\\n       && (defined __i386__ || defined __x86_64__) && defined __GNUC__)\n#    define OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED 1\n#  endif\n#endif\n\n#if defined (HAVE_LLVM_LIBCXX)\n/* The stream encoding facet from libc++ is stricter than libstdc++ when\n   it comes to reverting the stream.  Disable encoding conversion for file\n   streams with libc++.\n   FIXME: Maybe use a more specific test.  */\n#  define OCTAVE_HAVE_STRICT_ENCODING_FACET 1\n#endif\n\n/* Make all .oct file interpreter functions and methods static.  */\n#define OCTAVE_USE_STATIC_DEFUN\n\n/* This macro is intended to be used only to enable inline functions or\n   typedefs that provide access to symbols that have been moved to the\n   octave namespace.  It may be temporarily useful to define this macro\n   when moving a symbol to the octave namespace but it should not be\n   defined when building released versions of Octave, as building those\n   should not require deprecated symbols.  It is defined in\n   octave-config.h, so users of Octave may continue to access symbols\n   using the deprecated names.  */\n/* #undef OCTAVE_PROVIDE_DEPRECATED_SYMBOLS */\n\n/* Tag indicating Octave's autoconf-generated config.h has been\n   included.  This symbol is provided because autoconf-generated\n   config.h files do not define a multiple-inclusion guard.  See also\n   the notes at the top of the generated octave-config.h file.  */\n\n#define OCTAVE_AUTOCONFIG_H_INCLUDED 1\n"
  },
  {
    "path": "oct-conf-post-public.in.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 1993-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (__cplusplus)\n#  include <cinttypes>\n#else\n#  include <inttypes.h>\n#endif\n\n#define OCTAVE_BEGIN_NAMESPACE(name) namespace name {\n#define OCTAVE_END_NAMESPACE(name) }\n\n#define OCTAVE_DEPRECATED(ver, msg) [[deprecated(\"[\" #ver \"]: \" msg)]]\n#define HAVE_OCTAVE_DEPRECATED_ATTR 1\n\n/* FIXME: Since C++17 the standard defines the attribute [[noreturn]].\n   However, g++ and clang++ differ on where the attribute should appear making\n   it impossible at the moment (2026-02-15) to support both compilers.\n   There may be similar issues with other compilers, but this has not been\n   tested.  Uncomment the following line and remove the specific test for\n   GCC/Clang compilers when and if a solution is found. */\n\n//#define OCTAVE_NORETURN [[noreturn]]\n\n// Use GCC/Clang specific attribute syntax rather than C++ standard\n#if defined (__GNUC__)\n#  define OCTAVE_NORETURN __attribute__ ((__noreturn__))\n#  define HAVE_OCTAVE_NORETURN_ATTR 1\n#else\n#  define OCTAVE_NORETURN\n#endif\n\n#define OCTAVE_UNUSED [[maybe_unused]]\n#define HAVE_OCTAVE_UNUSED_ATTR 1\n\n#if ! defined (OCTAVE_FALLTHROUGH)\n#  define OCTAVE_FALLTHROUGH [[fallthrough]]\n#endif\n\n// Branch hint macros for use in if condititions.\n#if defined (__GNUC__)\n   // The following attributes are used with GCC/Clang compilers.\n#  define OCTAVE_LIKELY(x) __builtin_expect (!!(x), 1)\n#  define OCTAVE_UNLIKELY(x) __builtin_expect (!!(x), 0)\n#else\n#  define OCTAVE_LIKELY(x) !!(x)\n#  define OCTAVE_UNLIKELY(x) !!(x)\n#endif\n\n#if defined (__MINGW32__)\n  /* MinGW requires special handling due to different format specifiers\n     on different platforms.  The macro __MINGW_PRINTF_FORMAT maps to\n     either gnu_printf or ms_printf depending on where we are compiling\n     to avoid warnings on format specifiers that are legal.\n     See: https://bugzilla.mozilla.org/show_bug.cgi?id=1331349 */\n#  if defined (__cplusplus)\n#    include <cstdio>\n#  else\n#    include <stdio.h>\n#  endif\n\n#  define OCTAVE_FORMAT_PRINTF(stringIndex, firstToCheck) \\\n     __attribute__ ((format (__MINGW_PRINTF_FORMAT, stringIndex, firstToCheck)))\n\n#  define HAVE_OCTAVE_FORMAT_PRINTF_ATTR 1\n#elif defined (__GNUC__)\n   // The following attributes are used with GCC/Clang compilers.\n#  define OCTAVE_FORMAT_PRINTF(index, first) \\\n     __attribute__ ((__format__(printf, index, first)))\n\n#  define HAVE_OCTAVE_FORMAT_PRINTF_ATTR 1\n#else\n#  define OCTAVE_FORMAT_PRINTF(index, first)\n\n/* #  undef HAVE_OCTAVE_FORMAT_PRINTF_ATTR */\n#endif\n\n#if defined (__cplusplus)\ntemplate <typename T>\nstatic inline void\noctave_unused_parameter (const T&)\n{ }\n#else\n#  define octave_unused_parameter(param) (void) param;\n#endif\n\n#if defined (OCTAVE_ENABLE_LIB_VISIBILITY_FLAGS)\n#  if defined (_WIN32) || defined (__CYGWIN__)\n#    if defined (__GNUC__)\n       // GCC\n#      define OCTAVE_EXPORT __attribute__ ((dllexport))\n#      define OCTAVE_IMPORT __attribute__ ((dllimport))\n#    else\n       // MSVC\n#      define OCTAVE_EXPORT __declspec(dllexport)\n#      define OCTAVE_IMPORT __declspec(dllimport)\n#    endif\n#  else\n     // All other platforms.\n#    define OCTAVE_EXPORT __attribute__ ((visibility (\"default\")))\n#    define OCTAVE_IMPORT\n#  endif\n#else\n#  define OCTAVE_EXPORT\n#  define OCTAVE_IMPORT\n#endif\n\n// API macros for liboctave\n#if defined (OCTAVE_DLL)\n#  define OCTAVE_API OCTAVE_EXPORT\n#  define OCTAVE_EXCEPTION_API OCTAVE_EXPORT\n#  if defined (_WIN32) || defined (__CYGWIN__)\n#    define OCTAVE_TEMPLATE_API\n#    define OCTAVE_OVERRIDABLE_FUNC_API OCTAVE_EXPORT\n#  else\n#    define OCTAVE_TEMPLATE_API OCTAVE_EXPORT\n#    define OCTAVE_OVERRIDABLE_FUNC_API\n#  endif\n#else\n#  define OCTAVE_API OCTAVE_IMPORT\n#  if defined (_WIN32) || defined (__CYGWIN__)\n#    define OCTAVE_EXCEPTION_API OCTAVE_IMPORT\n#  else\n#    define OCTAVE_EXCEPTION_API OCTAVE_EXPORT\n#  endif\n#  define OCTAVE_TEMPLATE_API\n#  define OCTAVE_OVERRIDABLE_FUNC_API\n#endif\n\n// API macros for liboctinterp\n#if defined (OCTINTERP_DLL)\n#  define OCTINTERP_API OCTAVE_EXPORT\n#  define OCTINTERP_EXCEPTION_API OCTAVE_EXPORT\n#  if defined (_WIN32) || defined (__CYGWIN__)\n#    define OCTINTERP_TEMPLATE_API\n#    define OCTINTERP_OVERRIDABLE_FUNC_API OCTAVE_EXPORT\n#  else\n#    define OCTINTERP_TEMPLATE_API OCTAVE_EXPORT\n#    define OCTINTERP_OVERRIDABLE_FUNC_API\n#  endif\n#else\n#  define OCTINTERP_API OCTAVE_IMPORT\n#  if defined (_WIN32) || defined (__CYGWIN__)\n#    define OCTINTERP_EXCEPTION_API OCTAVE_IMPORT\n#  else\n#    define OCTINTERP_EXCEPTION_API OCTAVE_EXPORT\n#  endif\n#  define OCTINTERP_TEMPLATE_API\n#  define OCTINTERP_OVERRIDABLE_FUNC_API\n#endif\n\n// API macros for liboctmex\n#if defined (OCTMEX_DLL)\n#  define OCTMEX_API OCTAVE_EXPORT\n#  define OCTMEX_EXCEPTION_API OCTAVE_EXPORT\n#  if defined (_WIN32) || defined (__CYGWIN__)\n#    define OCTMEX_TEMPLATE_API\n#    define OCTMEX_OVERRIDABLE_FUNC_API OCTAVE_EXPORT\n#  else\n#    define OCTMEX_TEMPLATE_API OCTAVE_EXPORT\n#    define OCTMEX_OVERRIDABLE_FUNC_API\n#  endif\n#else\n#  define OCTMEX_API OCTAVE_IMPORT\n#  if defined (_WIN32) || defined (__CYGWIN__)\n#    define OCTMEX_EXCEPTION_API OCTAVE_IMPORT\n#  else\n#    define OCTMEX_EXCEPTION_API OCTAVE_EXPORT\n#  endif\n#  define OCTMEX_TEMPLATE_API\n#  define OCTMEX_OVERRIDABLE_FUNC_API\n#endif\n\n// API macros for libgui\n#if defined (OCTGUI_DLL)\n#  define OCTGUI_API OCTAVE_EXPORT\n#  define OCTGUI_EXCEPTION_API OCTAVE_EXPORT\n#  if defined (_WIN32) || defined (__CYGWIN__)\n#    define OCTGUI_TEMPLATE_API\n#    define OCTGUI_OVERRIDABLE_FUNC_API OCTAVE_EXPORT\n#  else\n#    define OCTGUI_TEMPLATE_API OCTAVE_EXPORT\n#    define OCTGUI_OVERRIDABLE_FUNC_API\n#  endif\n#else\n#  define OCTGUI_API OCTAVE_IMPORT\n#  if defined (_WIN32) || defined (__CYGWIN__)\n#    define OCTGUI_EXCEPTION_API OCTAVE_IMPORT\n#  else\n#    define OCTGUI_EXCEPTION_API OCTAVE_EXPORT\n#  endif\n#  define OCTGUI_TEMPLATE_API\n#  define OCTGUI_OVERRIDABLE_FUNC_API\n#endif\n\n// API macros for the Array<T> template class\n#if (defined (OCTAVE_DLL) || defined (OCTINTERP_DLL))\n   // export symbols when building liboctave or liboctinterp\n#  define OCTARRAY_API OCTAVE_EXPORT\n#else\n   /* Allow downstream projects to set visibility attributes when\n      instantiating the Array<T> template class with new types.\n      For that, OCTARRAY_API must be defined to the appropriate attribute\n      before including \"octave/oct.h\" in translation units that instantiate\n      the Array<T> template with a new type. */\n#  if ! defined (OCTARRAY_API)\n     // default is no visibility attributes\n#    define OCTARRAY_API\n#  endif\n#endif\n#if defined (_WIN32) || defined (__CYGWIN__)\n#  define OCTARRAY_TEMPLATE_API\n#  define OCTARRAY_OVERRIDABLE_FUNC_API OCTARRAY_API\n#else\n#  define OCTARRAY_TEMPLATE_API OCTARRAY_API\n#  define OCTARRAY_OVERRIDABLE_FUNC_API\n#endif\n\n#if defined (OCTAVE_ENABLE_64)\n#  define OCTAVE_IDX_TYPE_FORMAT PRId64\n#else\n#  define OCTAVE_IDX_TYPE_FORMAT PRId32\n#endif\n\n#if OCTAVE_SIZEOF_F77_INT_TYPE == 8\n#  define OCTAVE_F77_INT_TYPE_FORMAT PRId64\n#else\n#  define OCTAVE_F77_INT_TYPE_FORMAT PRId32\n#endif\n\n#define OCTAVE_HAVE_F77_INT_TYPE 1\n\n// time type in API is always 64 bits wide\n#define OCTAVE_TIME_T int64_t\n\n#if defined (__cplusplus) && ! defined (OCTAVE_THREAD_LOCAL)\n#  define OCTAVE_THREAD_LOCAL\n#endif\n\n#if defined (__cplusplus)\n#  define OCTAVE_DISABLE_COPY(X)                \\\n  X (const X&) = delete;                        \\\n  X& operator = (const X&) = delete;\n\n#  define OCTAVE_DISABLE_MOVE(X)                \\\n  X (X&&) = delete;                             \\\n  X (const X&&) = delete;                       \\\n  X& operator = (X&&) = delete;                 \\\n  X& operator = (const X&&) = delete;\n\n#  define OCTAVE_DISABLE_COPY_MOVE(X)           \\\n  OCTAVE_DISABLE_COPY (X)                       \\\n  OCTAVE_DISABLE_MOVE (X)\n\n#  define OCTAVE_DISABLE_COPY_MOVE_ASGN(X)      \\\n  X& operator = (const X&) = delete;            \\\n  X& operator = (X&&) = delete;                 \\\n  X& operator = (const X&&) = delete;\n\n#  define OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE(X) \\\n  X () = delete;                                \\\n  OCTAVE_DISABLE_COPY (X)                       \\\n  OCTAVE_DISABLE_MOVE (X)\n\n#  define OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE_DELETE(X)  \\\n  X () = delete;                                        \\\n  OCTAVE_DISABLE_COPY (X)                               \\\n  OCTAVE_DISABLE_MOVE (X)                               \\\n  ~X () = delete;\n\n#  define OCTAVE_DEFAULT_COPY(X)                \\\n  X (const X&) = default;                       \\\n  X& operator = (const X&) = default;\n\n#  define OCTAVE_DEFAULT_MOVE(X)                \\\n  X (X&&) = default;                            \\\n  X& operator = (X&&) = default;\n\n#  define OCTAVE_DEFAULT_COPY_MOVE(X)           \\\n  OCTAVE_DEFAULT_COPY (X)                       \\\n  OCTAVE_DEFAULT_MOVE (X)\n\n#  define OCTAVE_DEFAULT_COPY_MOVE_CTOR(X)      \\\n  X (const X&) = default;                       \\\n  X (X&&) = default;\n\n#  define OCTAVE_DEFAULT_CONSTRUCT_COPY(X)      \\\n  X () = default;                               \\\n  OCTAVE_DEFAULT_COPY (X)\n\n#  define OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE(X) \\\n  X () = default;                               \\\n  OCTAVE_DEFAULT_COPY_MOVE (X)\n\n#  define OCTAVE_DEFAULT_COPY_DELETE(X)         \\\n  OCTAVE_DEFAULT_COPY (X)                       \\\n  ~X () = default;\n\n#  define OCTAVE_DEFAULT_COPY_MOVE_DELETE(X)    \\\n  OCTAVE_DEFAULT_COPY_MOVE (X)                  \\\n  ~X () = default;\n\n#  define OCTAVE_DEFAULT_CONSTRUCT_DELETE(X)    \\\n  X () = default;                               \\\n  ~X () = default;\n\n#  define OCTAVE_DEFAULT_CONSTRUCT_COPY_DELETE(X)       \\\n  OCTAVE_DEFAULT_CONSTRUCT_DELETE (X)                   \\\n  OCTAVE_DEFAULT_COPY (X)                               \\\n\n#  define OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE(X)  \\\n  OCTAVE_DEFAULT_CONSTRUCT_DELETE (X)                   \\\n  OCTAVE_DEFAULT_COPY_MOVE (X)\n\n#endif\n\ntypedef OCTAVE_IDX_TYPE octave_idx_type;\ntypedef OCTAVE_F77_INT_TYPE octave_f77_int_type;\n\n// Backward compatibility\n\n#if defined (OCTAVE_ENABLE_64)\n#  define USE_64_BIT_IDX_T 1\n#endif\n\n#if defined (OCTAVE_ENABLE_OPENMP)\n#  define HAVE_OPENMP 1\n#endif\n"
  },
  {
    "path": "octave.doap",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Project xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n         xmlns:foaf=\"http://xmlns.com/foaf/0.1/\"\n         xmlns=\"http://usefulinc.com/ns/doap#\">\n\n  <name>GNU Octave</name>\n  <shortname>octave</shortname>\n\n  <shortdesc>Interactive programming environment for numerical computations</shortdesc>\n  <shortdesc xml:lang=\"ca\">Entorn de programació interactiva per a càlculs numèrics</shortdesc>\n  <shortdesc xml:lang=\"de\">Interaktive Programmierumgebung für numerische Berechnungen</shortdesc>\n  <shortdesc xml:lang=\"es\">Entorno de programación interactiva para cálculos numéricos</shortdesc>\n  <shortdesc xml:lang=\"fr\">Environnement de programmation interactif pour le calcul numérique</shortdesc>\n  <shortdesc xml:lang=\"hu\">Interaktív programozási környezet számszerű számításokhoz</shortdesc>\n  <shortdesc xml:lang=\"it\">Ambiente di programmazione interattivo per il calcolo numerico</shortdesc>\n  <shortdesc xml:lang=\"ja\">数値計算のための対話的なプログラミング環境</shortdesc>\n  <shortdesc xml:lang=\"nl\">Interactieve programmeeromgeving voor numerieke berekeningen</shortdesc>\n  <shortdesc xml:lang=\"pt\">Ambiente de programação interativo para computação numérica</shortdesc>\n  <shortdesc xml:lang=\"zh\">数值计算交互式编程环境</shortdesc>\n\n  <description>\n    GNU Octave is a high-level interpreted language, primarily intended for\n    numerical computations. It provides capabilities for the numerical\n    solution of linear and nonlinear problems, and for performing other\n    numerical experiments. It also provides extensive graphics capabilities\n    for data visualization and manipulation. Octave is normally used through\n    its interactive command line interface, but it can also be used to write\n    non-interactive programs. The Octave language is quite similar to\n    Matlab so that most programs are easily portable.\n  </description>\n  <description xml:lang=\"de\">\n    GNU Octave ist eine höhere, interpretierte Programmiersprache, die\n    hauptsächlich für numerische Berechnungen gedacht ist. Sie bietet\n    Funktionen für die numerische Lösung linearer und nichtlinearer Probleme\n    und für die Durchführung anderer numerischer Experimente. Darüber hinaus\n    bietet es umfangreiche Grafikfunktionen zur Datenvisualisierung und\n    -manipulation. Octave wird normalerweise mittels einer interaktiven\n    Befehlszeile verwendet, kann aber auch zum Schreiben nicht interaktiver\n    Programme verwendet werden. Die Octave-Programmiersprache ist sehr\n    ähnlich zu Matlab, so dass die meisten Programme leicht übertragbar sind.\n  </description>\n  <description xml:lang=\"es\">\n    GNU Octave es un lenguaje interpretado de alto nivel, destinado\n    principalmente a cálculos numéricos. Dispone capacidades para\n    la solución numérica de problemas lineales y no lineales, y para\n    realizar otros experimentos numéricos. También proporciona amplias\n    funcionalidades gráficas para la visualización y manipulación de datos.\n    Octave se usa normalmente a través de su interfaz de línea de comandos\n    interactiva, pero también se puede usar para escribir programas no\n    interactivos. El lenguaje Octave es muy similar a Matlab,\n    por lo que la mayoría de los programas son fáciles de portar.\n  </description>\n  <description xml:lang=\"fr\">\n    GNU Octave est un langage de programmation interprété, destiné\n    principalement au calcul numérique. Il fournit des fonctionnalités\n    pour la résolution de problèmes linéaires et non-linéaires, et pour toutes\n    sortes d'expériences numériques.  Il s'accompagne d'un système complet\n    de visualisation et de manipulation des données. Octave s’utilise\n    généralement via son environnement en lignes de commandes interactif,\n    mais il peut aussi être utilisé pour écrire des programmes non\n    interactifs. Le langage Octave est très similaire à Matlab de telle sorte\n    que les programmes Matlab sont très faciles à porter sous Octave.\n  </description>\n  <description xml:lang=\"hu\">\n    A GNU Octave egy magas szintű értelmezett nyelv, elsősorban numerikus\n    számításokhoz. Képességeket biztosít a lineáris és nemlineáris problémák\n    numerikus megoldására, valamint egyéb numerikus kísérletek elvégzésére.\n    Ezenkívül kiterjedt grafikus képességeket biztosít az adatok\n    megjelenítéséhez és manipulálásához. Az Octave-t általában az interaktív\n    parancssori felületen keresztül használják, de nem interaktív programok\n    írására is használható. Az Octave nyelv nagyon hasonló a Matlabhoz, így\n    a legtöbb program könnyen hordozható.\n  </description>\n  <description xml:lang=\"nl\">\n    GNU Octave is een geínterpreteerde programmeertaal bedoeld voor numerieke\n    berekeningen. Het biedt mogelijkheden voor het numeriek oplossen van\n    lineaire en niet-lineaire problemen en andere numerieke experimenten. Ook\n    biedt het uitgebreide mogelijkheden for grafische visualisatie en\n    -manipulatie van data. Octave wordt meestal gebruikt door middel van zijn\n    interactieve opdrachtregelinterface (terminal) maar kan ook gebruikt\n    worden voor het schrijven van niet-interactieve programma's. Octave's taal\n    lijkt zeer veel op die van Matlab zodat de meeste Matlabcode simpel te\n    draaien is in Octave.\n  </description>\n\n  <homepage rdf:resource=\"https://www.octave.org\" />\n  <license rdf:resource=\"https://www.gnu.org/licenses/gpl-3.0.txt\" />\n  <bug-database rdf:resource=\"https://savannah.gnu.org/bugs/?group=octave\" />\n  <download-page rdf:resource=\"https://ftp.gnu.org/gnu/octave/\" />\n  <mailing-list rdf:resource=\"https://lists.gnu.org/mailman/listinfo/help-octave\" />\n  <wiki rdf:resource=\"https://wiki.octave.org\" />\n\n  <programming-language>C++</programming-language>\n\n  <maintainer>\n    <foaf:Person>\n      <foaf:name>John W. Eaton</foaf:name>\n      <foaf:mbox rdf:resource=\"mailto:jwe@octave.org\" />\n    </foaf:Person>\n  </maintainer>\n\n  <repository>\n    <HgRepository>\n      <browse rdf:resource=\"https://hg.savannah.gnu.org/hgweb/octave\"/>\n      <location rdf:resource=\"https://hg.savannah.gnu.org/hgweb/octave\"/>\n    </HgRepository>\n  </repository>\n\n</Project>\n"
  },
  {
    "path": "run-octave.in",
    "content": "#! /bin/sh\n##\n## run-octave -- run Octave in the build tree.\n##\n########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n: ${AWK=%AWK%}\n: ${FIND=%FIND%}\n: ${SED=%SED%}\n: ${ADDRESS_SANITIZER_ENABLED=\"%ADDRESS_SANITIZER_ENABLED%\"}\n: ${ADDRESS_SANITIZER_OPTIONS=\"%ADDRESS_SANITIZER_OPTIONS%\"}\n\n# FIXME: is there a better way to handle the possibility of spaces\n#        in these names?\n\ntop_srcdir='%abs_top_srcdir%'\nbuilddir='%builddir%'\n\nd1=\"$top_srcdir/scripts\"\nd2=\"$builddir/scripts\"\nd3=\"$builddir/libinterp\"\nd4=\"$top_srcdir/examples/data\"\nd5=\"$builddir/libgui/graphics\"\n\nd1_list=`$FIND \"$d1\" -type d -a ! \\( \\( -name private -o -name '@*' -o -name '+*' -o -name '.deps' -o -name '.libs' \\) -a -prune \\) -exec echo '{}' ';' | $SED 's/$/:/'`\nd2_list=`$FIND \"$d2\" -type d -a ! \\( \\( -name private -o -name '@*' -o -name '+*' -o -name '.deps' -o -name '.libs' \\) -a -prune \\) -exec echo '{}' ';' | $SED 's/$/:/'`\nd3_list=`$FIND \"$d3\" -type d -a ! \\( \\( -name private -o -name '@*' -o -name '+*' -o -name '.deps' -o -name '.libs' \\) -a -prune \\) -exec echo '{}' ';' | $SED 's/$/:/'`\nd4_list=`$FIND \"$d4\" -type d -exec echo '{}' ';' | $SED 's/$/:/'`\n\nd1_path=`echo \"$d1_list\" | $AWK '{ t = (s $0); s = t; } END { sub (/:$/, \"\", s); print s; }'`\nd2_path=`echo \"$d2_list\" | $AWK '{ t = (s $0); s = t; } END { sub (/:$/, \"\", s); print s; }'`\nd3_path=`echo \"$d3_list\" | $AWK '{ t = (s $0); s = t; } END { sub (/:$/, \"\", s); print s; }'`\nd4_path=`echo \"$d4_list\" | $AWK '{ t = (s $0); s = t; } END { sub (/:$/, \"\", s); print s; }'`\n\noctave_executable=\"$builddir/src/octave\"\n\nLOADPATH=\"$d1_path:$d2_path:$d3_path:$d4_path:$d5\"\nIMAGEPATH=\".:$top_srcdir/scripts/image\"\nDOCFILE=\"$builddir/doc/interpreter/doc-cache\"\nBUILT_IN_DOCSTRINGS_FILE=\"$builddir/libinterp/DOCSTRINGS\"\nTEXIMACROSFILE=\"$top_srcdir/doc/interpreter/macros.texi\"\nINFOFILE=\"$builddir/doc/interpreter/octave.info\"\nOCTAVE_QTHELP_COLLECTION=\"$builddir/doc/interpreter/octave_interpreter.qhc\"\n\n## Checking for string equality below with prepended x's in order to\n## handle problems with empty strings.\nwhile [ $# -gt 0 ]; do\n  if [ \"x$1\" = \"x-g\" ]; then\n    driver=\"gdb --args\"\n    shift\n  elif [ \"x$1\" = \"x-gud\" ]; then\n    ## Frontends for gdb (e.g., Emacs's GUD mode) need --annotate=3\n    driver=\"gdb --annotate=3 --args\"\n    shift\n  elif [ \"x$1\" = \"x-gud2\" ]; then\n    ## The latest version of gud needs -i=mi.  There isn't a good way to check\n    ## this at configure time, so we just add a gud2 flag\n    driver=\"gdb -i=mi --args\"\n    shift\n  elif [ \"x$1\" = \"x-valgrind\" ]; then\n    driver=\"valgrind --tool=memcheck\"\n    shift\n  elif [ \"x$1\" = \"x-callgrind\" ]; then\n    driver=\"valgrind --tool=callgrind\"\n    shift\n  elif [ \"x$1\" = \"x-strace\" ]; then\n    driver=\"strace -o octave.trace\"\n    shift\n  elif [ \"x$1\" = \"x-cli\" ]; then\n    octave_executable=\"$builddir/src/octave-cli\"\n    shift\n  elif [ \"x$1\" = \"x-disable-asan\" ]; then\n    disable_asan=yes\n    shift\n  else\n    break\n  fi\ndone\n\n## Documentation files may exist in the current (build) directory\n## or in the source directory when building from a release.\nif ! [ -e $DOCFILE ]; then\n  DOCFILE=\"$top_srcdir/doc/interpreter/doc-cache\"\nfi\nif ! [ -e $BUILT_IN_DOCSTRINGS_FILE ]; then\n  BUILT_IN_DOCSTRINGS_FILE=\"$top_srcdir/libinterp/DOCSTRINGS\"\nfi\nif ! [ -e $INFOFILE ]; then\n  INFOFILE=\"$top_srcdir/doc/interpreter/octave.info\"\nfi\nif ! [ -e $OCTAVE_QTHELP_COLLECTION ]; then\n  OCTAVE_QTHELP_COLLECTION=\"$top_srcdir/doc/interpreter/octave_interpreter.qhc\"\nfi\n\n## We set OCTAVE_ARCHLIBDIR so that the wrapper program can find the\n## octave-gui program in the build tree.  That will fail if we ever\n## need Octave to find other things in ARCHLIBDIR that are not built\n## in the $builddir/src directory.\n\nOCTAVE_ARCHLIBDIR=\"$builddir/src\"; export OCTAVE_ARCHLIBDIR\nOCTAVE_BINDIR=\"$builddir/src\"; export OCTAVE_BINDIR\nOCTAVE_FONTS_DIR=\"$top_srcdir/etc/fonts\"; export OCTAVE_FONTS_DIR\nOCTAVE_JAVA_DIR=\"$builddir/scripts/java\"; export OCTAVE_JAVA_DIR\nOCTAVE_LOCALE_DIR=\"$builddir/libgui/languages\"; export OCTAVE_LOCALE_DIR\n## QTHELP location has been set above\nexport OCTAVE_QTHELP_COLLECTION\nOCTAVE_SITE_INITFILE=\"$top_srcdir/scripts/startup/site-rcfile\"; export OCTAVE_SITE_INITFILE\nOCTAVE_VERSION_INITFILE=\"$top_srcdir/scripts/startup/version-rcfile\"; export OCTAVE_VERSION_INITFILE\n\nif [ \"$ADDRESS_SANITIZER_ENABLED\" = yes ]; then\n  if [ \"$disable_asan\" = yes ]; then\n    ## Is there a better way to do this so that we don't fill /tmp\n    ## with junk files?  Using /dev/null won't work because asan\n    ## appends the process ID to the file name.\n    ASAN_OPTIONS=\"leak_check_at_exit=0:log_path=/tmp/oct-asan-log:verbosity=0\"\n  else\n    ASAN_OPTIONS=\"$ADDRESS_SANITIZER_OPTIONS\"\n  fi\n  export ASAN_OPTIONS\nfi\n\nexec $builddir/libtool --mode=execute $driver \\\n  \"$octave_executable\" --no-init-path --path=\"$LOADPATH\" \\\n  --image-path=\"$IMAGEPATH\" --doc-cache-file=\"$DOCFILE\" \\\n  --built-in-docstrings-file=\"$BUILT_IN_DOCSTRINGS_FILE\" \\\n  --texi-macros-file=\"$TEXIMACROSFILE\" --info-file=\"$INFOFILE\" \"$@\"\n"
  },
  {
    "path": "scripts/+containers/Map.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nclassdef Map < handle\n\n  ## -*- texinfo -*-\n  ## @deftypefn  {} {@var{m} =} containers.Map ()\n  ## @deftypefnx {} {@var{m} =} containers.Map (@var{keys}, @var{vals})\n  ## @deftypefnx {} {@var{m} =} containers.Map (@var{keys}, @var{vals}, @qcode{\"UniformValues\"}, @var{is_uniform})\n  ## @deftypefnx {} {@var{m} =} containers.Map (@qcode{\"KeyType\"}, @var{kt}, @qcode{\"ValueType\"}, @var{vt})\n  ##\n  ## Create an object of the containers.Map class that stores a list of\n  ## key/value pairs.\n  ##\n  ## @var{keys} is an array of @emph{unique} keys for the map.  The keys can be\n  ## numeric scalars or strings.  The type for numeric keys may be one of\n  ## @qcode{\"double\"}, @qcode{\"single\"}, @qcode{\"int32\"}, @qcode{\"uint32\"},\n  ## @qcode{\"int64\"}, or @qcode{\"uint64\"}.  Other numeric or logical keys will\n  ## be converted to @qcode{\"double\"}.  A single string key may be entered as\n  ## is.  Multiple string keys are entered as a cell array of strings.\n  ##\n  ## @var{vals} is an array of values for the map with the @emph{same} number\n  ## of elements as @var{keys}.\n  ##\n  ## When called with no input arguments, a default map is created with strings\n  ## as the key type and @qcode{\"any\"} as the value type.\n  ##\n  ## The @qcode{\"UniformValues\"} option specifies whether the values of the map\n  ## must be strictly of the same type.  If @var{is_uniform} is true, any\n  ## values which would be added to the map are first validated to ensure they\n  ## are of the correct type.\n  ##\n  ## When called with @qcode{\"KeyType\"} and @qcode{\"ValueType\"} arguments,\n  ## create an empty map with the specified types.  The inputs @var{kt} and\n  ## @var{vt} are the types for the keys and values of the map, respectively.\n  ## Allowed values for @var{kt} are @qcode{\"char\"}, @qcode{\"double\"},\n  ## @qcode{\"single\"}, @qcode{\"int32\"}, @qcode{\"uint32\"}, @qcode{\"int64\"},\n  ## @qcode{\"uint64\"}.  Allowed values for @var{vt} are @qcode{\"any\"},\n  ## @qcode{\"char\"}, @qcode{\"double\"}, @qcode{\"single\"}, @qcode{\"int32\"},\n  ## @qcode{\"uint32\"}, @qcode{\"int64\"}, @qcode{\"uint64\"}, @qcode{\"logical\"}.\n  ##\n  ## The return value @var{m} is an object of the containers.Map class.\n  ## @seealso{struct}\n  ## @end deftypefn\n\n  properties (GetAccess = public, SetAccess = private)\n\n    ## -*- texinfo -*-\n    ## @deftypefn {} {@var{type} =} Map.KeyType ()\n    ## Return the key type.\n    ##\n    ## Possible values for @var{type} are @qcode{\"char\"}, @qcode{\"double\"},\n    ## @qcode{\"single\"}, @qcode{\"int32\"}, @qcode{\"uint32\"}, @qcode{\"int64\"},\n    ## @qcode{\"uint64\"}.\n    ## @end deftypefn\n\n    KeyType   = \"char\";\n\n    ## -*- texinfo -*-\n    ## @deftypefn {} {@var{type} =} Map.ValueType ()\n    ## Return the value type.\n    ##\n    ## Possible values for @var{type} are @qcode{\"any\"}, @qcode{\"char\"},\n    ## @qcode{\"double\"}, @qcode{\"single\"}, @qcode{\"int32\"}, @qcode{\"uint32\"},\n    ## @qcode{\"int64\"}, @qcode{\"uint64\"}, @qcode{\"logical\"}.\n    ## @end deftypefn\n\n    ValueType = \"any\";\n\n  endproperties\n\n  properties (Dependent, SetAccess = protected)\n\n    ## -*- texinfo -*-\n    ## @deftypefn {} {@var{n} =} Map.Count ()\n    ## Return the number of key/value pairs in the map, as a uint64.\n    ## @end deftypefn\n\n    Count = 0;\n\n  endproperties\n\n  properties (private)\n    map = struct ();\n\n    numeric_keys = false;\n  endproperties\n\n  methods (Access = public)\n\n    function this = Map (varargin)\n\n      if (nargin == 0)\n        ## Empty object with \"char\" key type and \"any\" value type.\n      elseif (nargin == 2 || (nargin == 4\n                              && strcmpi (varargin{3}, \"UniformValues\")))\n        ## Get Map keys\n        keys = varargin{1};\n        if (! iscell (keys))\n          if (isnumeric (keys) || islogical (keys))\n            keys = num2cell (keys);\n          else\n            keys = { keys };\n          endif\n        endif\n        keys = keys(:);  # Use Nx1 column vector to simplify calls to all()\n\n        ## Get Map values\n        vals = varargin{2};\n        if (! iscell (vals))\n          if ((isnumeric (vals) || islogical (vals)) && ! isscalar (keys))\n            vals = num2cell (vals);\n          else\n            vals = { vals };\n          endif\n        endif\n        vals = vals(:);\n        if (numel (keys) != numel (vals))\n          error (\"containers.Map: the number of keys and values must match\");\n        endif\n\n        ## Determine KeyType\n        kt = unique (cellfun ('class', keys, \"UniformOutput\", false));\n        if (numel (kt) == 1)\n          ## Single key type--most common case\n          if (strcmp (kt{1}, \"char\"))\n            ## String is most common key type\n          else\n            if (! all (cellfun (\"isreal\", keys)\n                       & (cellfun (\"numel\", keys) == 1)))\n              error (\"containers.Map: keys must be real scalar numeric values or char vectors\");\n            endif\n            if (any (strcmp (kt{1},\n                             {\"logical\", \"int8\", \"uint8\", \"int16\", \"uint16\"})))\n              kt = { \"double\" };\n            endif\n          endif\n          this.KeyType = char (kt);\n        else\n          ## Multiple key types\n          if (! all (ismember (kt, {\"double\", \"single\", \"int8\", \"uint8\", ...\n                                    \"int16\", \"uint16\", \"int32\", \"uint32\", ...\n                                    \"int64\", \"uint64\", \"logical\"})))\n            error (\"containers.Map: when using multiple key types, all types must be numeric\");\n          else\n            warning (\"containers.Map: all keys will be converted to double\");\n            this.KeyType = \"double\";\n          endif\n        endif\n\n        ## Determine ValueType\n        vt = unique (cellfun ('class', vals, \"UniformOutput\", false));\n        if (numel (vt) == 1\n            && (ischar (vals{1})\n                || ((isnumeric (vals{1}) || islogical (vals{1}))\n                    && all (cellfun ('numel', vals) == 1))))\n          this.ValueType = vt{1};\n        else\n          this.ValueType = \"any\";\n        endif\n\n        ## Process UniformValues option\n        if (nargin == 4)\n          UniformValues = varargin{4};\n          if (! isscalar (UniformValues)\n              || ! (islogical (UniformValues) || isnumeric (UniformValues)))\n            error (\"containers.Map: 'UniformValues' must be a logical scalar\");\n          endif\n\n          if (UniformValues)\n            if (numel (vt) > 1\n                || (strcmp (this.ValueType, \"any\") && isreal (vals{1})))\n              error (\"containers.Map: when 'UniformValues' is true, all values must be scalars of the same data type\");\n            endif\n          else\n            this.ValueType = \"any\";\n          endif\n        endif\n\n        ## Check type of keys and values, and define numeric_keys\n        check_types (this);\n\n        ## Flatten char keys\n        if (! this.numeric_keys)\n          keys = cellfun (@(x) x(:).', keys, 'UniformOutput', false);\n        endif\n\n        ## Sort keys (faster than call to sort_keys once encoded)\n        if (this.numeric_keys)\n          [~, I] = sort (cell2mat (keys));\n        else\n          [~, I] = sort (keys);\n        endif\n        keys = keys(I);\n        vals = vals(I);\n        ## Convert keys to char vectors\n        keys = encode_keys (this, keys);\n        ## Fill in the Map\n        this.map = cell2struct (vals, keys);\n      elseif (nargin == 4)\n        for i = [1, 3]\n          switch (lower (varargin{i}))\n            case \"keytype\"\n              this.KeyType = varargin{i+1};\n            case \"valuetype\"\n              this.ValueType = varargin{i+1};\n            otherwise\n              error (\"containers.Map: missing parameter name 'KeyType' or 'ValueType'\");\n          endswitch\n        endfor\n        check_types (this);\n      else\n        error (\"containers.Map: incorrect number of inputs specified\");\n      endif\n\n    endfunction\n\n    function keySet = keys (this)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {@var{keys} =} Map.keys ()\n      ## Return a sorted list of all keys of the map as a cell vector.\n      ## @end deftypefn\n\n      keySet = fieldnames (this.map).';  # compatibility requires row vector\n      keySet = decode_keys (this, keySet);\n\n    endfunction\n\n    function valueSet = values (this, keySet)\n\n      ## -*- texinfo -*-\n      ## @deftypefn  {} {@var{val} =} Map.values ()\n      ## @deftypefnx {} {@var{val} =} Map.values (@var{keySet})\n      ## Return the list of all values stored in the map as a cell vector.\n      ##\n      ## If @var{keySet}, a cell array of keys is provided, the corresponding\n      ## values will be returned.\n      ## @end deftypefn\n\n      if (nargin == 1)\n        valueSet = struct2cell (this.map).';\n      else\n        if (! iscell (keySet))\n          error (\"containers.Map: input argument 'keySet' must be a cell\");\n        endif\n        if (! this.numeric_keys)\n          ## Flatten char keys\n          keySet = cellfun (@(x) x(:).', keySet, 'UniformOutput', false);\n        endif\n        enckeySet = encode_keys (this, keySet);\n        valueSet = cell (size (keySet));\n        for i = 1:numel (valueSet)\n          try\n            valueSet{i} = this.map.(enckeySet{i});\n          catch\n            error (\"containers.Map: key <%s> does not exist\",\n                   strtrim (disp (keySet{i})));\n          end_try_catch\n        endfor\n      endif\n\n    endfunction\n\n    function tf = isKey (this, keySet)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {@var{mask} =} Map.isKey (@var{keySet})\n      ## Return a logical array which is true where the elements of\n      ## @var{keySet} are keys of the map and false otherwise.\n      ##\n      ## @var{keySet} is a cell array of keys.  If a single key is being\n      ## checked, it can be entered directly as a scalar value or a char\n      ## vector.\n      ## @end deftypefn\n\n      if (! iscell (keySet))\n        if (isnumeric (keySet) || islogical (keySet))\n          keySet = num2cell (keySet);\n        else\n          keySet = { keySet };\n        endif\n      endif\n      tf = false (size (keySet));\n      in = cellfun (\"isnumeric\", keySet) | cellfun (\"islogical\", keySet);\n      if (! this.numeric_keys)\n        in = ! in;\n        ## Flatten char keys\n        keySet = cellfun (@(x) x(:).', keySet, 'UniformOutput', false);\n      endif\n      keySet = encode_keys (this, keySet(in));\n      tf(in) = isfield (this.map, keySet);\n\n    endfunction\n\n    function this = remove (this, keySet)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {} Map.remove (@var{keySet})\n      ## @deftypefn {} {@var{newMap) =} Map.remove (@var{keySet})\n      ## Remove the list of key/value pairs specified by a cell array of keys\n      ## @var{keySet} from the map.\n      ##\n      ## @var{keySet}) can also be a scalar value or a string when specifying a\n      ## single key.\n      ## @end deftypefn\n\n      if (! iscell (keySet))\n        if (isnumeric (keySet) || islogical (keySet))\n          keySet = num2cell (keySet);\n        else\n          keySet = { keySet };\n        endif\n      endif\n      in = cellfun (\"isnumeric\", keySet) | cellfun (\"islogical\", keySet);\n      if (! this.numeric_keys)\n        in = ! in;\n        ## Flatten char keys\n        keySet = cellfun (@(x) x(:).', keySet, 'UniformOutput', false);\n      endif\n      keySet = encode_keys (this, keySet(in));\n      in = isfield (this.map, keySet);\n      this.map = rmfield (this.map, keySet(in));\n\n    endfunction\n\n    function varargout = size (this, n)\n\n      ## -*- texinfo -*-\n      ## @deftypefn  {} {@var{l} =} Map.size (@var{n})\n      ## @deftypefnx {} {@var{sz} =} Map.size ()\n      ## @deftypefnx {} {@var{dim_1}, @dots{}, @var{dim_n} =} Map.size ()\n      ## If @var{n} is 1, return the number of key/value pairs in the map,\n      ## otherwise return 1.\n      ##\n      ## Without input arguments, return vector @code{[@var{l}, 1]} where\n      ## @var{l} is the number of key/value pairs in the map.\n      ##\n      ## With multiple outputs, return @code{[@var{l}, @dots{}, 1]}.\n      ## @end deftypefn\n\n      c = length (this);\n      if (nargin == 1)\n        if (nargout <= 1)\n          varargout = { [c 1] };\n        else\n          varargout{1} = c;\n          [varargout{2:nargout}] = deal (1);\n        endif\n      else\n        if (n == 1)\n          varargout = { c };\n        else\n          varargout = { 1 };\n        endif\n      endif\n\n    endfunction\n\n    function len = length (this)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {@var{n} =} Map.length ()\n      ## Return the number of key/value pairs in the map.\n      ## @end deftypefn\n\n      len = double (this.Count);\n\n    endfunction\n\n    function tf = isempty (this)\n      tf = (this.Count == 0);\n    endfunction\n\n    function count = get.Count (this)\n      count = uint64 (numfields (this.map));\n    endfunction\n\n    function varargout = subsref (this, s)\n\n      switch (s(1).type)\n        case \".\"\n          switch (s(1).subs)\n            case \"keys\"\n              sref = keys (this);\n            case \"values\"\n              if (numel (s) > 1\n                  && strcmp (s(2).type, \"()\") && ! isempty (s(2).subs))\n                sref = values (this, s(2).subs{1});\n                s(1) = [];\n              else\n                sref = values (this);\n              endif\n            case \"size\"\n              sref = size (this);\n            case \"length\"\n              sref = length (this);\n            case \"isempty\"\n              sref = isempty (this);\n            case \"Count\"\n              sref = this.Count;\n            case \"KeyType\"\n              sref = this.KeyType;\n            case \"ValueType\"\n              sref = this.ValueType;\n            case {\"isKey\", \"remove\"}\n              if (numel (s) < 2 || numel (s(2).subs) != 1)\n                error (\"containers.Map: input argument 'KeySet' is missing\");\n              endif\n              sref = feval (s(1).subs, this, s(2).subs{1});\n              s(1) = [];\n            otherwise\n              error (\"containers.Map: unknown property '%s'\", s(1).subs);\n          endswitch\n          if (numel (s) > 1 && strcmp (s(2).type, \"()\") && isempty (s(2).subs))\n            s(1) = [];\n          endif\n        case \"()\"\n          if (isempty (s(1).subs))\n            error (\"containers.Map: no key specified\");\n          endif\n          key = s(1).subs{1};\n          if ((! this.numeric_keys && ! ischar (key))\n              || (this.numeric_keys && (! (isnumeric (key) || islogical (key))\n                                        || ! isscalar (key))))\n            error (\"containers.Map: specified key type does not match the type of this container\");\n          endif\n          if (ischar (key))\n            key = key(:).';\n          endif\n          enckey = encode_keys (this, key);\n          if (! isfield (this.map, enckey))\n            error (\"containers.Map: specified key <%s> does not exist\",\n                   strtrim (disp (key)));\n          endif\n          sref = this.map.(enckey);\n        otherwise\n          error (\"containers.Map: only '()' indexing is supported\");\n      endswitch\n      if (numel (s) > 1)\n        [varargout{1:nargout}] = subsref (sref, s(2:end));\n      else\n        varargout = {sref};\n      endif\n\n    endfunction\n\n    function this = subsasgn (this, s, val)\n\n      if (numel (s) > 1)\n        error (\"containers.Map: only one level of indexing is supported\");\n      endif\n      switch (s(1).type)\n        case \".\"\n          error (\"containers.Map: properties are read-only\");\n        case \"()\"\n          key = s(1).subs{1};\n          if ((! this.numeric_keys && ! ischar (key))\n              || (this.numeric_keys && (! (isnumeric (key) || islogical (key))\n                                        || ! isscalar (key))))\n            error (\"containers.Map: specified key type does not match the type of this container\");\n          endif\n          if (! strcmp (this.ValueType, \"any\"))\n            if ((strcmp (this.ValueType, \"char\") && ! ischar (val))\n                || (! strcmp (this.ValueType, \"char\")\n                    && (! (isnumeric (val) || islogical (val))\n                        || ! isscalar (val))))\n              error (\"containers.Map: specified value type does not match the type of this container\");\n            endif\n            val = feval (this.ValueType, val);\n          endif\n          if (ischar (key))\n            key = key(:).';\n          endif\n          key = encode_keys (this, key);\n          if (isfield (this.map, key))\n            this.map.(key) = val;\n          else\n            this.map.(key) = val;\n            this = sort_keys (this);\n          endif\n        case \"{}\"\n          error (\"containers.Map: only '()' indexing is supported for assigning values\");\n      endswitch\n\n    endfunction\n\n    function n = numArgumentsFromSubscript (this, ~, ~)\n      n = numel (this);\n    endfunction\n\n    function newobj = horzcat (varargin)\n      warning (\"Octave:language-extension\",\n               \"containers.Map: horizontal concatenation is an Octave-only feature\");\n      newobj = vertcat (varargin{:});\n    endfunction\n\n    function newobj = vertcat (varargin)\n\n      ## When concatenating maps, the data type of all values must be\n      ## consistent with the ValueType of the leftmost map.\n      keySet = cell (1, 0);\n      keyTypes = cell (1, 0);\n      for i = 1:numel (varargin)\n        keySet = [keySet, keys(varargin{i})];\n        keyTypes = [keyTypes, varargin{i}.KeyType];\n      endfor\n      if (numel (unique (keyTypes)) != 1)\n        if (any (strcmp (keyTypes, \"char\")))\n          error (\"containers.Map: cannot concatenate maps with numeric and string keys\");\n        endif\n        keySet = cellfun (@(x) feval (keyTypes{1}, x), keySet, \"UniformOutput\", false);\n      endif\n      valueSet = cell (1, 0);\n      for i = 1:numel (varargin)\n        valueSet = [valueSet, values(varargin{i})];\n      endfor\n      newobj = containers.Map (keySet, valueSet);\n\n    endfunction\n\n    function disp (this)\n      printf (\"  containers.Map object with properties:\\n\\n\");\n      printf ([\"    Count     : %d\\n\" ...\n               \"    KeyType   : %s\\n\" ...\n               \"    ValueType : %s\\n\\n\"],\n               this.Count, this.KeyType, this.ValueType);\n    endfunction\n\n  endmethods\n\n  methods (Access = private)\n\n    ## All keys are encoded as strings.\n    ## For numeric keys, this requires conversion.\n    function keys = encode_keys (this, keys)\n\n      if (iscellstr (keys) || ischar (keys))\n        return;\n      endif\n      cell_input = iscell (keys);\n      if (cell_input)\n        orig_sz = size (keys);\n        if (! all (cellfun (\"isclass\", keys, this.KeyType)))\n          ## Convert input set to KeyType.  This is rarely necessary.\n          keys = cellfun (@(x) feval (this.KeyType, x), keys);\n        else\n          keys = cell2mat (keys);\n        endif\n      elseif (! isa (keys, this.KeyType))\n        keys = feval (this.KeyType, keys);\n      endif\n      keys = num2hex (keys);  # Force to char matrix with single logical column\n      if (cell_input)\n        keys = reshape (cellstr (keys), orig_sz);\n      endif\n\n    endfunction\n\n    function keys = decode_keys (this, keys)\n      if (this.numeric_keys)\n        keys = hex2num (keys, this.KeyType);\n        ## This always returns a 1xN list of keys ignoring input shape\n        keys = mat2cell (keys(:).', 1, ones (1, numel (keys)));\n      endif\n    endfunction\n\n    function this = sort_keys (this)\n\n      keySet = keys (this);\n      if (this.numeric_keys)\n        [~, p] = sort (cell2mat (keySet));\n      else\n        [~, p] = sort (keySet);\n      endif\n      this.map = orderfields (this.map, p);\n\n    endfunction\n\n    function check_types (this)\n\n      switch (this.KeyType)\n        case {\"char\"}\n          this.numeric_keys = false;\n        case {\"double\", \"single\", \"int32\", \"uint32\", \"int64\", \"uint64\"}\n          this.numeric_keys = true;\n        otherwise\n          error (\"containers.Map: unsupported KeyType\");\n      endswitch\n\n      if (! any (strcmp (this.ValueType, {\"any\"; \"char\"; \"logical\";\n                                          \"double\"; \"single\";\n                                          \"int8\"; \"uint8\"; \"int16\"; \"uint16\";\n                                          \"int32\"; \"uint32\";\n                                          \"int64\"; \"uint64\"})))\n        error (\"containers.Map: unsupported ValueType\");\n      endif\n\n    endfunction\n\n  endmethods\n\nendclassdef\n\n\n## Test empty Map\n%!test\n%! m = containers.Map ();\n%! assert (m.Count, uint64 (0));\n%! assert (length (m), 0);\n%! assert (rows (m), 0);\n%! assert (columns (m), 1);\n%! assert (isempty (m));\n%! assert (isempty (keys (m)));\n%! assert (isempty (values (m)));\n%! assert (isKey (m, \"Octave\"), false);\n%! assert (isKey (m, 42), false);\n%! assert (isKey (m, {\"Octave\", 42}), [false, false]);\n%! assert (isKey (m, {\"Octave\"; 42}), [false; false]);\n\n## Test string keys\n%!test\n%! key = {\"One\", \"Two\", \"Three\", \"Four\"};\n%! val = [1, 2, 3, 4];\n%! m = containers.Map (key, val);\n%! assert (m.KeyType, \"char\");\n%! assert (m.ValueType, \"double\");\n%! assert (m.Count, uint64 (4));\n%! assert (iscell (keys (m)));\n%! assert (iscell (values (m)));\n%! assert (size (keys (m)), [1, 4]);\n%! assert (size (values (m)), [1, 4]);\n%! assert (m(\"Two\"), 2);\n%! m(\"Five\") = 5;\n%! key2 = {\"Six\", \"Seven\", \"Eight\"};\n%! val2 = [6, 7, 8];\n%! m2 = containers.Map (key2, val2);\n%! m = [m; m2];\n%! assert (m.Count, uint64 (8));\n%! k = keys (m);\n%! assert (isempty (setdiff (k, [key, \"Five\", key2])));\n%! v = values (m, {\"Three\", \"Four\"; \"Five\", \"Six\"});\n%! assert (v, {3, 4; 5, 6});\n%! remove (m, {\"Three\", \"Four\"});\n%! k = keys (m);\n%! assert (numel (k), 6);\n%! assert (m.isKey({\"One\", \"Four\"; \"Ten\", \"Five\"}), [true,false; false,true]);\n\n## Test empty char array as key\n%!test <*67255>\n%! m = containers.Map ('', 3);\n%! assert (m(''), 3);\n\n## Test multi-row char array keys\n%!test <*67283>\n%! k1 = char (\"key\", \"one\");\n%! k2 = char (\"key\", \"two\");\n%! k3 = char (\"key\", \"three\");\n%! m = containers.Map ({k1, k2}, {1, 2});\n%! m(k3) = 3;\n%! assert (m(k1), 1);\n%! assert (m.values ({k1, k3}), {1, 3});\n%! m.remove ({k1, k3});\n%! assert (m(k2), 2);\n%! assert (m.isKey ({k1, k2, k3}), [false, true, false]);\n\n## Test numeric keys\n%!test\n%! key = [1, 2, 3, 4];\n%! val = {\"One\", \"Two\", \"Three\", \"Four\"};\n%! m = containers.Map (key, val);\n%! assert (m.KeyType, \"double\");\n%! assert (m.ValueType, \"char\");\n%! assert (iscell (keys (m)));\n%! assert (iscell (values (m)));\n%! assert (size (keys (m)), [1, 4]);\n%! assert (size (values (m)), [1, 4]);\n%! assert (m(2), \"Two\");\n%! m(5) = \"Five\";\n%! key2 = [6, 7, 8];\n%! val2 = {\"Six\", \"Seven\", \"Eight\"};\n%! m2 = containers.Map (key2, val2);\n%! m = [m; m2];\n%! assert (m.Count, uint64 (8));\n%! k = keys (m);\n%! assert (isempty (setdiff (cell2mat (k), [key, 5, key2])));\n%! v = values (m, {3, 4; 5, 6});\n%! assert (v, {\"Three\", \"Four\"; \"Five\", \"Six\"});\n%! remove (m, {3, 4});\n%! k = keys (m);\n%! assert (numel (k), 6);\n%! assert (m.isKey({1, 4; 10, 5}), [true,false; false,true]);\n\n## Test that nonscalar objects force ValueType to \"any\"\n%!test\n%! key = [2, 3, 4];\n%! val = {eye(2), eye(3), eye(4)};\n%! m = containers.Map (key, val);\n%! assert (m(3), eye (3));\n%! assert (m(2)(2,2), 1);\n%! assert (m.KeyType, \"double\");\n%! assert (m.ValueType, \"any\");\n%! key = [2, 3, 4];\n%! val = {2, 3, [4 5]};\n%! m = containers.Map (key, val);\n%! assert (m.KeyType, \"double\");\n%! assert (m.ValueType, \"any\");\n\n## Test that mixed object types force ValueType to \"any\"\n%!test\n%! key = [2, 3, 4];\n%! val = {double(1), single(2), uint8(3)};\n%! m = containers.Map (key, val);\n%! assert (m.KeyType, \"double\");\n%! assert (m.ValueType, \"any\");\n%! assert (class (m(4)), \"uint8\");\n%! assert (class (m(3)), \"single\");\n\n## Test that non-numeric, non-char object types force ValueType to \"any\"\n%!test\n%! key = {\"a\", \"b\"};\n%! val = {struct(), struct()};\n%! m = containers.Map (key, val);\n%! assert (m.ValueType, \"any\");\n%! m = containers.Map (key, val, \"UniformValues\", true);\n%! assert (m.ValueType, \"any\");\n%! m = containers.Map (key, {1, 2i});\n%! assert (m.ValueType, \"double\");\n\n## Test \"UniformValues\" input\n%!test\n%! key = {\"one\", \"two\", \"three\"};\n%! val = {1, 2, 3};\n%! m = containers.Map (key, val, \"UniformValues\",false);\n%! assert (m.ValueType, \"any\");\n%! m(\"four\") = \"GNU\";\n%! assert (values (m), {\"GNU\", 1, 3, 2});\n\n## Test 4-input form of Map\n%!test\n%! m = containers.Map (\"KeyType\",\"char\", \"ValueType\",\"int32\");\n%! assert (m.KeyType, \"char\");\n%! assert (m.ValueType, \"int32\");\n%! assert (m.Count, uint64 (0));\n%! assert (isempty (m));\n\n## Test all allowable key types\n%!test\n%! key = [2, 3, 4];\n%! val = {2, 3, 4};\n%! types = {\"double\", \"single\", \"int32\", \"uint32\", \"int64\", \"uint64\"};\n%! for type = types\n%!   type = type{1};\n%!   k = feval (type, key);\n%!   m = containers.Map (k, val);\n%!   assert (m.KeyType, type);\n%!   assert (isa (keys (m){1}, type));\n%! endfor\n%! assert (all (isKey (m, keys (m))));\n\n## Test that other numeric key types are converted to double\n%!test\n%! key = [0, 1];\n%! val = {1, 2};\n%! types = {\"logical\", \"int8\", \"uint8\", \"int16\", \"uint16\"};\n%! for type = types\n%!   type = type{1};\n%!   k = feval (type, key);\n%!   m = containers.Map (k, val);\n%!   assert (m.KeyType, \"double\");\n%!   assert (isa (keys (m){1}, \"double\"));\n%! endfor\n%! assert (all (isKey (m, keys (m))));\n\n## Test removal of keys\n%!test\n%! m = containers.Map ({\"a\",\"b\",\"c\"}, {1,2,3});\n%! assert (m.isKey (\"a\"), true);\n%! assert (m.isKey ({\"a\",\"d\"}), [true, false]);\n%! m.remove (\"a\");\n%! m.remove ({\"b\",\"c\"});\n%! assert (isempty (m));\n\n## Ensure that exact key values are preserved.\n%!test\n%! keytypes = {\"int32\", \"int64\", \"uint32\", \"uint64\"};\n%! for keytype = keytypes\n%!   keytype = keytype{1};\n%!   key = intmax (keytype);\n%!   m = containers.Map (key, pi);\n%!   assert (m.isKey (key));\n%!   assert (m.keys (), {key});\n%!   key = intmin (keytype);\n%!   m = containers.Map (key, pi);\n%!   assert (m.isKey (key));\n%!   assert (m.keys (), {key});\n%! endfor\n%! keytypes = {\"double\", \"single\"};\n%! for i = 1:numel (keytypes)\n%!   keytype = keytypes{i};\n%!   key = realmax (keytype);\n%!   m = containers.Map (key, pi);\n%!   assert (m.isKey (key));\n%!   assert (m.keys (), {key});\n%!   key = realmin (keytype);\n%!   m = containers.Map (key, pi);\n%!   assert (m.isKey (key));\n%!   assert (m.keys (), {key});\n%!   key = -realmax (keytype);\n%!   m = containers.Map (key, pi);\n%!   assert (m.isKey (key));\n%!   assert (m.keys (), {key});\n%! endfor\n\n## Test using mixed numerical keys (subsref)\n%!test <*56594>\n%! key = [1, 2, 3];\n%! val = {\"One\", \"Two\", \"Three\"};\n%! types = {\"double\", \"single\", \"int32\", \"uint32\", \"int64\", \"uint64\", ...\n%!          \"int8\", \"uint8\", \"int16\", \"uint16\"};\n%! for type1 = types\n%!   type = type1{1};\n%!   k = feval (type, key);\n%!   m = containers.Map (k, val);\n%!   for type2 = [types, \"logical\"]\n%!     type = type2{1};\n%!     k = feval (type, key(1));\n%!     assert (m(k), \"One\");\n%!   endfor\n%! endfor\n\n## Test using mixed numerical keys (subsasgn)\n%!test <*56594>\n%! key = [1, 2, 3];\n%! val = {\"One\", \"Two\", \"Three\"};\n%! m = containers.Map (key, val);\n%! m (uint32 (1)) = \"Four\";\n%! assert (m.Count, uint64 (3));\n%! assert (keys (m), {1, 2, 3});\n%! assert (m(1), \"Four\");\n%! assert (m(uint16 (1)), \"Four\");\n\n## Test sort order of keys and values\n%!test\n%! key = {\"d\",\"a\",\"b\"};\n%! m = containers.Map (key, 1:numel (key));\n%! assert (keys (m), sort (key));\n%! assert (values (m), {2, 3, 1});\n%! m(\"c\") = 4;\n%! assert (keys (m), sort ([key, \"c\"]));\n%! assert (values (m), {2, 3, 4, 1});\n%! key = [Inf, 2, 0, -Inf, -1];\n%! m = containers.Map (key, 1:numel (key));\n%! assert (keys (m), num2cell (sort (key)));\n%! assert (values (m), {4, 5, 3, 2, 1});\n%! m(-2) = 6;\n%! assert (keys (m), num2cell (sort ([key, -2])));\n%! assert (values (m), {4, 6, 5, 3, 2, 1});\n\n## Test horizontal concatenation\n%!test\n%! m1 = containers.Map (\"b\", 2);\n%! m2 = containers.Map (\"a\", 1);\n%! m3 = [m1, m2];\n%! k = keys (m3);\n%! assert (numel (k), 2);\n%! assert (k, {\"a\", \"b\"});\n%! m1 = containers.Map (1, 1);\n%! m2 = containers.Map (single ([2, 3]), {2, 3});\n%! m3 = [m1, m2];\n%! assert (m3.KeyType, \"double\");\n%! assert (keys (m3), {1, 2, 3});\n%! m3 = [m2, m1];\n%! assert (m3.KeyType, \"single\");\n\n## Test subsref calls\n%!test <*59607>\n%! months = {'Jan', 'Feb', 'Mar', 'Apr'};\n%! vals = [10, 11, 12, 13];\n%! M = containers.Map (months, vals);\n%! keys = {'Jan', 'Feb'};\n%! assert (M.values, values (M));\n%! assert (M.values (), values (M));\n%! assert (M.values (keys), {10, 11});\n%! assert (M.values (keys)(2), {11});\n%! assert (M.values (keys){2}, 11);\n%!test\n%! months = {'Jan', 'Feb', 'Mar', 'Apr'};\n%! vals = [10, 11, 12, 13];\n%! M = containers.Map (months, vals);\n%! keys = {'Jan', 'FooBar', 'Feb'};\n%! assert (M.isKey (keys)(2:end), [false, true]);\n\n## Test subsref calls will multiple outputs\n%!test <*67426>\n%! M = containers.Map ('first', struct ('dat', {111, 222}));\n%! [a, b] = M('first').dat;\n%! assert ([a, b], [111, 222])\n%!test <*67426>\n%! M = containers.Map ('first', {{111, 222}});\n%! [a, b] = M('first') {:};\n%! assert ([a, b], [111, 222])\n%!test <*67426>\n%! M = containers.Map ({'first', 'second'}, {111, 222});\n%! [a,b] = M.values () {:};\n%! assert ([a, b], [111, 222])\n\n## Test input validation\n%!error containers.Map (1,2,3)\n%!error containers.Map (1,2,3,4,5)\n%!error <the number of keys and values must match> containers.Map ([], 1)\n%!error <number of keys and values must match> containers.Map (1, {2, 3})\n%!error <keys must be real .* values> containers.Map ({{1}}, 2)\n%!error <keys must be .* scalar .* values> containers.Map ({magic(3)}, 2)\n%!warning <keys .* converted to double>\n%! containers.Map ({1,int8(2)}, {3,4});\n%!error <when using multiple key types, all types must be numeric>\n%! containers.Map ({1, {2}}, {3,4})\n%!error <'UniformValues' must be a logical scalar>\n%! containers.Map (1,2, 'UniformValues', ones (2,2))\n%!error <'UniformValues' must be a logical scalar>\n%! containers.Map (1,2, 'UniformValues', {true})\n%!error <all values must be scalars of the same data type>\n%! containers.Map ({1,2}, {3, uint32(4)}, \"UniformValues\", true)\n%!error <missing parameter name 'KeyType'>\n%! containers.Map (\"keytype\", \"char\", \"vtype\", \"any\")\n%!error <'keySet' must be a cell>\n%! m = containers.Map ();\n%! values (m, 1);\n%#!error <key .foobar. does not exist>\n%! m = containers.Map ();\n%! values (m, \"foobar\");\n%!error <input argument 'KeySet' is missing>\n%! m = containers.Map ();\n%! m.isKey (1,2);\n%!error <unknown property 'foobar'>\n%! m = containers.Map ();\n%! m.foobar;\n%!error <key type does not match the type of this container>\n%! m = containers.Map (\"a\", 1);\n%! m(1);\n%!error <specified key .b. does not exist>\n%! m = containers.Map (\"a\", 1);\n%! m(\"b\");\n%!test\n%! [old_fmt, old_spacing] = format ();\n%! unwind_protect\n%!   format short;\n%!   m = containers.Map (1, 1);\n%!   fail (\"m(2)\", \"specified key <2> does not exist\");\n%! unwind_protect_cleanup\n%!   format (old_fmt);\n%!   format (old_spacing);\n%! end_unwind_protect\n%!error <only '\\(\\)' indexing is supported>\n%! m = containers.Map (\"a\", 1);\n%! m{1};\n%!error <unsupported KeyType>\n%! m1 = containers.Map (\"KeyType\", \"cell\", \"ValueType\", \"any\");\n%!error <unsupported ValueType>\n%! m1 = containers.Map (\"KeyType\", \"char\", \"ValueType\", \"cell\");\n%!error\n%! m1 = containers.Map (1, 1);\n%! m2 = containers.Map (\"a\", 2);\n%! m3 = [m1, m2];\n"
  },
  {
    "path": "scripts/+containers/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/Map.m\n\n%canon_reldir%dir = $(fcnfiledir)/+containers\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/+matlab/+lang/MemoizedFunction.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nclassdef MemoizedFunction < handle\n\n  properties (GetAccess = public, SetAccess = private)\n    Function = [];\n  endproperties\n\n  properties (Access = public)\n    Enabled = true;\n    CacheSize = 10;\n  endproperties\n\n  properties (Access = private, Hidden = true)\n    Cache;\n  endproperties\n\n  methods (Access = public)\n\n    function this = MemoizedFunction (fcn_handle)\n      if (! isa (fcn_handle, \"function_handle\"))\n        error (\"matlab.lang.MemoizedFunction: FCN_HANDLE must be a function handle\");\n      endif\n      this.Function = fcn_handle;\n      this.Cache = init_cache ();\n    endfunction\n\n    function varargout = subsref (this, s)\n\n      switch (s(1).type)\n\n        case \".\"\n          switch (s(1).subs)\n            case \"Function\"\n              varargout{1} = this.Function;\n            case \"Enabled\"\n              varargout{1} = this.Enabled;\n            case \"CacheSize\"\n              varargout{1} = this.CacheSize;\n            case \"clearCache\"\n              clearCache (this);\n              varargout = {};\n            case \"stats\"\n              varargout{1} = stats (this);\n            otherwise\n              error (\"matlab.lang.MemoizedFunction: unknown property '%s'\", ...\n                     s(1).subs);\n          endswitch\n\n        case \"()\"\n          n_out = ifelse (nargout == 0, 1, nargout);\n          if (! this.Enabled)\n            [varargout{1:n_out}] = feval (this.Function, s(1).subs{:});\n          else\n            cache_idx = [];\n            for i = 1:numel (this.Cache.Inputs)\n              if (isequaln (this.Cache.Inputs{i}, s(1).subs) ...\n                  && isequal (this.Cache.Nargout(i), nargout))\n                cache_idx = i;\n                break;\n              endif\n            endfor\n            if (! isempty (cache_idx))\n              [varargout{1:n_out}] = deal (this.Cache.Outputs{cache_idx}{:});\n              this.Cache.TotalHits += 1;\n              this.Cache.HitCount(cache_idx) += 1;\n            else\n              [varargout{1:n_out}] = feval (this.Function, s(1).subs{:});\n              n = numel (this.Cache.Inputs) + 1;\n              if (n > this.CacheSize)\n                this.Cache.Inputs(1)   = [];\n                this.Cache.Nargout(1)  = [];\n                this.Cache.Outputs(1)  = [];\n                this.Cache.HitCount(1) = [];\n                n -= 1;  # FIFO\n              endif\n              this.Cache.Inputs{n}   = s(1).subs;\n              this.Cache.Nargout(n)  = nargout;\n              this.Cache.Outputs{n}  = varargout;\n              this.Cache.HitCount(n) = 0;\n              this.Cache.TotalMisses += 1;\n            endif\n          endif\n\n        otherwise\n          error (\"matlab.lang.MemoizedFunction: only '()' indexing is supported\");\n\n      endswitch\n\n      if (numel (s) > 1)\n        varargout{1} = subsref (varargout{1}, s(2:end));\n      endif\n\n    endfunction\n\n    function this = subsasgn (this, s, val)\n\n      if (numel (s) > 1)\n        error (\"matlab.lang.MemoizedFunction: only one level of indexing is supported\");\n      endif\n\n      switch (s(1).type)\n\n        case \".\"\n          switch (s(1).subs)\n            case \"Function\"\n              error (\"matlab.lang.MemoizedFunction: property Function is read-only\");\n\n            case \"Enabled\"\n              if (! isscalar (val) || ! (isnumeric (val) || islogical (val)) ...\n                  || ! isfinite (val))\n                error (\"matlab.lang.MemoizedFunction: Enabled must be a logical scalar\");\n              endif\n              this.Enabled = logical (val);\n\n            case \"CacheSize\"\n              if (! isscalar (val) || ! isnumeric (val) || ! isfinite (val) ...\n                  || val < 1 || fix (val) != val)\n                error (\"matlab.lang.MemoizedFunction: CacheSize must be a positive integer scalar\");\n              endif\n              this.CacheSize = double (val);\n              n = numel(this.Cache.Inputs) - this.CacheSize;\n              if (n > 0)\n                this.Cache.Inputs(1:n)   = [];\n                this.Cache.Nargout(1:n)  = [];\n                this.Cache.Outputs(1:n)  = [];\n                this.Cache.HitCount(1:n) = [];\n              endif\n\n            otherwise\n              error (\"matlab.lang.MemoizedFunction: unknown property '%s'\", ...\n                     s(1).subs);\n          endswitch\n\n        otherwise\n          error (\"matlab.lang.MemoizedFunction: only '.' indexing is supported for assigning values\");\n\n      endswitch\n\n    endfunction\n\n    function clearCache (this)\n      this.Cache = init_cache ();\n    endfunction\n\n    function s = stats (this)\n\n      if (isempty (this.Cache.Inputs))\n        CacheHitRatePercent   = 0;\n        CacheOccupancyPercent = 0;\n        MostHitCachedInput    = [];\n      else\n        CacheHitRatePercent   = 100 * (this.Cache.TotalHits /\n                                (this.Cache.TotalHits + this.Cache.TotalMisses));\n        CacheOccupancyPercent = 100 * (numel (this.Cache.Inputs)\n                                       / this.CacheSize);\n        [~, i] = max (this.Cache.HitCount);\n        MostHitCachedInput    = struct (\"Hits\", this.Cache.HitCount(i),\n                                        \"Input\", {this.Cache.Inputs{i}});\n      endif\n      s = struct (\n        \"Cache\",                 this.Cache,\n        \"MostHitCachedInput\",    MostHitCachedInput,\n        \"CacheHitRatePercent\",   CacheHitRatePercent,\n        \"CacheOccupancyPercent\", CacheOccupancyPercent);\n\n    endfunction\n\n    function newobj = horzcat (varargin)\n      error (\"matlab.lang.MemoizedFunction: concatenation is not allowed\");\n    endfunction\n\n    function newobj = vertcat (varargin)\n      error (\"matlab.lang.MemoizedFunction: concatenation is not allowed\");\n    endfunction\n\n  endmethods\n\nendclassdef\n\nfunction cache = init_cache ()\n\n  cache = struct (\"Inputs\",      {{}},\n                  \"Nargout\",     [],\n                  \"Outputs\",     {{}},\n                  \"HitCount\",    [],\n                  \"TotalHits\",   0,\n                  \"TotalMisses\", 0);\n\nendfunction\n"
  },
  {
    "path": "scripts/+matlab/+lang/makeUniqueStrings.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{uniqstr} =} matlab.lang.makeUniqueStrings (@var{str})\n## @deftypefnx {} {@var{uniqstr} =} matlab.lang.makeUniqueStrings (@var{str}, @var{ex})\n## @deftypefnx {} {@var{uniqstr} =} matlab.lang.makeUniqueStrings (@var{str}, @var{ex}, @var{maxlength})\n## @deftypefnx {} {[@var{uniqstr}, @var{ismodified}] =} matlab.lang.makeUniqueStrings (@dots{})\n##\n## Construct a list of unique strings from a list of strings.\n##\n## The input @var{str} must be a string or a cell array of strings.\n## The output @var{uniqstr} will be of the same type.\n##\n## The algorithm makes two strings unique by appending an underscore\n## (@qcode{\"_\"} and a numeric count to the second string.\n##\n## If @var{ex} is a string or a cell array of strings, @var{uniqstr} will\n## contain elements that are unique between themselves and with respect to\n## @var{ex}.\n##\n## If @var{ex} is an index array or a logical array for @var{str} then it\n## selects the subset of @var{str} that are made unique.  Unselected elements\n## are not modified.\n##\n## The optional input @var{maxlength} specifies the maximum length of any\n## string in @var{uniqstr}.  If an input string cannot be made unique without\n## exceeding @var{maxlength} an error is emitted.\n##\n## The optional output @var{ismodified} is a logical array indicating whether\n## each element in @var{str} was modified to make it unique.\n##\n## @seealso{unique, matlab.lang.makeValidName}\n## @end deftypefn\n\nfunction [uniqstr, ismodified] = makeUniqueStrings (str, ex = {}, maxlength = Inf)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  ##  Validate first input\n  if (! ischar (str) && ! iscellstr (str))\n    error (\"makeUniqueStrings: STR must be a string or cellstr\");\n  endif\n\n  convert2char = ischar (str);\n  uniqstr = cellstr (str);\n  sz = size (uniqstr);\n  uniqstr = uniqstr(:)';\n\n  ## Initialize array of strings to exclude\n  excludedstrings = {};\n\n  ## Validate optional exclusion list input\n  if (nargin > 1)\n    if (ischar (ex) || iscellstr (ex))\n      excludedstrings = cellstr (ex);\n    elseif (islogical (ex))\n      if (numel (ex) != numel (uniqstr))\n        error (\"makeUniqueStrings: STR and EX logical array must have the same length\");\n      endif\n      excludedstrings = uniqstr(! ex);\n      uniqstr = uniqstr(ex);\n    elseif (isnumeric (ex))\n      if (! isindex (ex, numel (uniqstr)))\n        error (\"makeUniqueStrings: invalid array of indices EX\");\n      endif\n      excludedstrings = uniqstr(setdiff (1:numel (uniqstr), ex));\n      uniqstr = uniqstr(ex);\n    else\n      error (\"makeUniqueStrings: invalid input\");\n    endif\n    excludedstrings = excludedstrings(:)';\n  endif\n\n  ## Validate optional maxlength input\n  if (nargin > 2)\n    if (! isindex (maxlength))\n      error (\"makeUniqueStrings: MAXLENGTH must be a positive integer\");\n    endif\n  endif\n  chk_length = ! isinf (maxlength);\n\n  ismodified = false (size (uniqstr));\n  if (chk_length)\n    ## Truncate output strings\n    ismodified = (cellfun ('length', uniqstr) > maxlength);\n    uniqstr(ismodified) = cellindexmat (uniqstr(ismodified), 1:maxlength);\n  endif\n\n  ## Make unique strings\n  ## FIXME: lots of call to ismember are slow.\n  [~, I, J] = unique (uniqstr, \"first\");\n  for i = 1:numel (I)\n    R = ! ismember (uniqstr{I(i)}, excludedstrings);\n    K = find (J == J(I(i)));\n    n = 1 + ceil (log10 (numel (K)));\n\n    if (! chk_length)\n      sub = uniqstr{K(1)};\n    else\n      if (length (uniqstr{K(1)}) + n > maxlength)\n        if (n >= maxlength)\n          error (\"makeUniqueStrings: cannot create unique elements within MAXLENGTH\");\n        endif\n        sub = uniqstr{K(1)}(1:maxlength-n);\n      else\n        sub = uniqstr{K(1)};\n      endif\n    endif\n\n    for k = (1 + R):numel (K)\n      while (true)\n        N = k - R;\n        proposal = [sub sprintf(\"_%d\", N)];\n        if (! ismember (proposal, [excludedstrings, uniqstr(I(i+1:end))]))\n          uniqstr{K(k)} = proposal;\n          break;\n        else\n          R--;  # i.e., increments N\n        endif\n      endwhile\n      ismodified(K(k)) |= true;\n    endfor\n  endfor\n\n  ## Return outputs with correct type and size\n  if (convert2char)\n    uniqstr = char (uniqstr);\n    if (isempty (uniqstr))\n      uniqstr = char ();\n    endif\n  else\n    if (isnumeric (ex) || islogical (ex))\n      tmp = uniqstr;\n      uniqstr = cell (1, prod (sz));\n      uniqstr(ex) = tmp;\n      if (isnumeric (ex))\n        uniqstr(setdiff (1:prod (sz), ex)) = excludedstrings;\n      else\n        uniqstr(! ex) = excludedstrings;\n      endif\n      tmp = ismodified;\n      ismodified = false (sz);\n      ismodified(ex) = tmp;\n    endif\n    uniqstr = reshape (uniqstr, sz);\n  endif\n\nendfunction\n\n\n## Test first input\n%!test\n%! assert (matlab.lang.makeUniqueStrings (\"a\"), \"a\");\n%! assert (matlab.lang.makeUniqueStrings ({\"a\",\"b\",\"c\"}), {\"a\",\"b\",\"c\"});\n%! assert (matlab.lang.makeUniqueStrings (''), '');\n%! assert (matlab.lang.makeUniqueStrings ({}), {});\n\n## Test exclusion list\n%!test\n%! str = {\"jwe\", \"Marco\", \"Rik\", \"jwe\", \"Kai\", \"jwe\", \"Torsten\"};\n%! uniqstr = matlab.lang.makeUniqueStrings (str);\n%! assert (uniqstr,\n%!         {\"jwe\", \"Marco\", \"Rik\", \"jwe_1\", \"Kai\", \"jwe_2\", \"Torsten\"});\n%! uniqstr = matlab.lang.makeUniqueStrings (str, \"Rik\");\n%! assert (uniqstr,\n%!         {\"jwe\", \"Marco\", \"Rik_1\", \"jwe_1\", \"Kai\", \"jwe_2\", \"Torsten\"});\n%! [uniqstr, m] = matlab.lang.makeUniqueStrings (str, {\"Kai\", \"Rik\"});\n%! assert (uniqstr,\n%!         {\"jwe\", \"Marco\", \"Rik_1\", \"jwe_1\", \"Kai_1\", \"jwe_2\", \"Torsten\"});\n%! assert (m, logical ([0 0 1 1 1 1 0]));\n\n## Test index array\n%!test\n%! str = {\"a\", \"a\", \"a\", \"b\", \"a\", \"b\"};\n%! uniqstr = matlab.lang.makeUniqueStrings (str, 1:4);\n%! assert (uniqstr, {\"a_1\", \"a_2\", \"a_3\", \"b_1\", \"a\", \"b\"});\n%! str(end+1) = \"a\";\n%! [uniqstr, m] = matlab.lang.makeUniqueStrings (str, 1:4);\n%! assert (uniqstr, {\"a_1\", \"a_2\", \"a_3\", \"b_1\", \"a\", \"b\", \"a\"});\n%! assert (m ,logical ([1 1 1 1 0 0 0]));\n\n## Test logical array\n%!test\n%! str = {\"a\", \"a\", \"a\", \"b\", \"a\", \"b\"};\n%! [uniqstr, m] = matlab.lang.makeUniqueStrings (str, logical ([1 1 1 1 0 0]));\n%! assert (uniqstr, {\"a_1\", \"a_2\", \"a_3\", \"b_1\", \"a\", \"b\"});\n%! assert (m, logical ([1 1 1 1 0 0]));\n\n## Test maxlength\n%!test\n%! str = {\"maxlength\", \"maxlength\", \"maxlength\", \"maxlength\"};\n%! [uniqstr, m] = matlab.lang.makeUniqueStrings (str, 1:3, 5);\n%! assert (uniqstr, {\"maxle\", \"max_1\", \"max_2\", \"maxlength\"});\n%! assert (m, logical ([1 1 1 0]));\n%!error <cannot create unique elements within MAXLENGTH>\n%! matlab.lang.makeUniqueStrings (repmat ({\"a\"}, 1, 10), {}, 2);\n\n%!test\n%! assert (matlab.lang.makeUniqueStrings (\"a\", {\"a\"}), \"a_1\");\n%! assert (matlab.lang.makeUniqueStrings (\"a\", {\"a\",\"a_1\"}), \"a_2\");\n%! uniqstr = matlab.lang.makeUniqueStrings ({\"a\",\"a\",\"a\",\"a_6\",\"a\"},\n%!                                          {\"a\",\"a_3\"});\n%! assert (uniqstr, {\"a_1\",\"a_2\",\"a_4\",\"a_6\",\"a_5\"});\n\n## Test input validation\n%!error <Invalid call> matlab.lang.makeUniqueStrings ()\n%!error <STR must be a string or cellstr> matlab.lang.makeUniqueStrings (1)\n%!error <STR and EX logical array must have the same length>\n%! matlab.lang.makeUniqueStrings (\"a\", [true false]);\n%!error <invalid array of indices EX> matlab.lang.makeUniqueStrings (\"a\", 2)\n%!error <MAXLENGTH must be a positive integer>\n%! matlab.lang.makeUniqueStrings (\"a\", {}, pi);\n"
  },
  {
    "path": "scripts/+matlab/+lang/makeValidName.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{varname} =} matlab.lang.makeValidName (@var{str})\n## @deftypefnx {} {@var{varname} =} matlab.lang.makeValidName (@dots{}, @qcode{\"ReplacementStyle\"}, @var{rs})\n## @deftypefnx {} {@var{varname} =} matlab.lang.makeValidName (@dots{}, @qcode{\"Prefix\"}, @var{pfx})\n## @deftypefnx {} {[@var{varname}, @var{ismodified}] =} matlab.lang.makeValidName (@dots{})\n##\n## Create valid variable name @var{varname} from @var{str}.\n##\n## The input @var{str} must be a string or a cell array of strings.\n## The output @var{varname} will be of the same type.\n##\n## A valid variable name is a sequence of letters, digits, and underscores that\n## does not begin with a digit.\n##\n## The @qcode{\"ReplacementStyle\"} option specifies how invalid characters\n## are handled.  Acceptable values are\n##\n## @table @asis\n## @item @qcode{\"underscore\"} (default)\n## Replace all invalid characters with an underscore (@qcode{\"_\"}).\n##\n## @item @qcode{\"delete\"}\n## Remove any invalid character.\n##\n## @item @qcode{\"hex\"}\n## Replace all invalid characters with their hexadecimal representation.\n## @end table\n##\n## Whitespace characters are always removed @strong{prior} to the application\n## of the @qcode{\"ReplacementStyle\"}.  Lowercase letters following a whitespace\n## will be changed to uppercase.\n##\n## The @qcode{\"Prefix\"} option specifies the string @var{pfx} to add as a\n## prefix to the input if it begins with a digit.  @var{pfx} must be a valid\n## variable name itself.  The default prefix is @qcode{\"x\"}.\n##\n## The optional output @var{ismodified} is a logical array indicating whether\n## the respective element in @var{str} was a valid name or not.\n##\n## @seealso{iskeyword, isvarname, matlab.lang.makeUniqueStrings}\n## @end deftypefn\n\nfunction [varname, ismodified] = makeValidName (varargin)\n\n  [varname, ismodified] = __make_valid_name__ (varargin{:});\n\nendfunction\n\n\n## Test char vector input\n%!test\n%! varname = matlab.lang.makeValidName (\"octave\");\n%! assert (varname, \"octave\");\n\n## Test cellstr input\n%!test\n%! varname = matlab.lang.makeValidName ({\"gnu\", \"octave\"});\n%! assert (varname, {\"gnu\", \"octave\"});\n\n## Test default flags\n%!test\n%! str = {\"Octave\", \"3d plot\", \"GNU/Octave\", \"laplace_*\"};\n%! varname = matlab.lang.makeValidName (str);\n%! assert (varname, {\"Octave\", \"x3dPlot\", \"GNU_Octave\", \"laplace__\"});\n\n## Test ReplacementStyle flag\n%!test\n%! str = {\"Octave\", \"3d plot\", \"GNU/Octave\", \"laplace_*\"};\n%! varname = matlab.lang.makeValidName (str, \"ReplacementStyle\", \"underscore\");\n%! assert (varname, {\"Octave\", \"x3dPlot\", \"GNU_Octave\", \"laplace__\"});\n%! varname = matlab.lang.makeValidName (str, \"ReplacementStyle\", \"hex\");\n%! assert (varname, {\"Octave\", \"x3dPlot\", \"GNU0x2FOctave\", \"laplace_0x2A\"});\n%! varname = matlab.lang.makeValidName (str, \"ReplacementStyle\", \"delete\");\n%! assert (varname, {\"Octave\", \"x3dPlot\", \"GNUOctave\", \"laplace_\"});\n\n## Test Prefix flag\n%!test\n%! assert (matlab.lang.makeValidName ({\"\", \" \"}), {\"x\", \"x\"});\n%! str = {\"Octave\", \"3d plot\", \"GNU/Octave\", \"laplace_*\"};\n%! varname = matlab.lang.makeValidName (str, \"prefix\", \"oct_\");\n%! assert (varname, {\"Octave\", \"oct_3dPlot\", \"GNU_Octave\", \"laplace__\"});\n\n## Test second output\n%!test\n%! str = {\"Octave\", \"3d plot\", \"GNU/Octave\", \"laplace_*\"};\n%! [varname, modified] = matlab.lang.makeValidName (str);\n%! assert (modified, [false, true, true, true]);\n\n## Test whitespace followed by a lowercase letter\n%!test\n%! varname = matlab.lang.makeValidName (\"gnu octave\");\n%! assert (varname, \"gnuOctave\");\n%! varname = matlab.lang.makeValidName (\" octave  \");\n%! assert (varname, \"octave\");\n\n## Check for keywords\n%!assert (matlab.lang.makeValidName (\"for\"), \"xFor\")\n%!assert (matlab.lang.makeValidName (\"For\"), \"For\")\n%!error matlab.lang.makeValidName (\"for\", \"Prefix\", \"for\")\n\n## Test input validation\n%!error <Invalid call> matlab.lang.makeValidName ()\n%!error <STR must be a string or cellstr> matlab.lang.makeValidName (42)\n%!error <options must occur in pairs> matlab.lang.makeValidName (\"a\", \"opt1\")\n%!error <option argument must be a string>\n%! matlab.lang.makeValidName (\"a\", 1, 2)\n%!error <'ReplacementStyle' value must be a string>\n%! matlab.lang.makeValidName (\"a\", \"ReplacementStyle\", 1);\n%!error <invalid 'ReplacementStyle' value 'foobar'>\n%! matlab.lang.makeValidName (\"a\", \"ReplacementStyle\", \"foobar\");\n%!error <invalid 'Prefix' value '1_'>\n%! matlab.lang.makeValidName (\"a\", \"Prefix\", \"1_\");\n%!error <unknown property 'foobar'>\n%! matlab.lang.makeValidName (\"a\", \"foobar\", 1);\n"
  },
  {
    "path": "scripts/+matlab/+lang/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/makeUniqueStrings.m \\\n  %reldir%/makeValidName.m \\\n  %reldir%/MemoizedFunction.m\n\n%canon_reldir%dir = $(fcnfiledir)/+matlab/+lang\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/+matlab/+net/base64decode.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{out_vec} =} matlab.net.base64decode (@var{b64_str})\n##\n## Convert base64 encoded @var{b64_str} to uint8 vector @var{out_vec}.\n##\n## The input @var{b64_str} must be a string vector.\n## The output @var{out_vec} will be a uint8 vector that is decoded\n## according to RFC 4648.\n##\n## @seealso{matlab.net.base64encode, base64_decode, base64_encode,\n## native2unicode}\n## @end deftypefn\n\nfunction out_vec = base64decode (b64_str)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  if (! isvector (b64_str) || ! ischar (b64_str))\n    error (\"base64decode: B64_STR must be a base64 encoded character vector\");\n  endif\n\n  out_vec = uint8 (__base64_decode_bytes__ (b64_str));\n\nendfunction\n\n\n## Test char vector input\n%!assert (matlab.net.base64decode (\"AQ==\"), uint8 (1))\n%!assert (matlab.net.base64decode (\"/w==\"), uint8 (255))\n%!assert (matlab.net.base64decode (\"AQID\"), uint8 (1:3))\n%!assert (matlab.net.base64decode (\"YQ==\"), uint8 (\"a\"))\n%!assert (matlab.net.base64decode (\"YWJjZGVmZw==\"), uint8 (\"abcdefg\"))\n\n## Test input validation\n%!error <Invalid call> matlab.net.base64decode ()\n%!error <character vector> matlab.net.base64decode (pi)\n%!error <character vector> matlab.net.base64decode ({1,2})\n%!error <character vector> matlab.net.base64decode ([1,2;3,4])\n"
  },
  {
    "path": "scripts/+matlab/+net/base64encode.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{b64_str} =} matlab.net.base64encode (@var{in})\n##\n## Convert @var{in} to a base64 encoded string @var{b64_str}.\n##\n## The input @var{in} can be a string or numeric vector.\n## The output @var{b64_str} will be encoded according to RFC 4648.\n##\n## @seealso{matlab.net.base64decode, base64_decode, base64_encode,\n## unicode2native}\n## @end deftypefn\n\nfunction b64_str = base64encode (in)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  if (! isvector (in) || ! (isnumeric (in) || ischar (in)))\n    error (\"base64encode: IN must be a numeric or character vector\");\n  endif\n\n  if (any (in != round (in)))\n    error (\"base64encode: IN must consist of integers\");\n  endif\n\n  b64_str = base64_encode (uint8 (in));\n\nendfunction\n\n\n## Test char vector input\n%!assert (matlab.net.base64encode (1), \"AQ==\")\n%!assert (matlab.net.base64encode (255), \"/w==\")\n%!assert (matlab.net.base64encode (1:3), \"AQID\")\n%!assert (matlab.net.base64encode (\"a\"), \"YQ==\")\n%!assert (matlab.net.base64encode (\"abcdefg\"), \"YWJjZGVmZw==\")\n\n## Test input validation\n%!error <Invalid call> matlab.net.base64encode ()\n%!error <numeric or character vector> matlab.net.base64encode ({1,2})\n%!error <numeric or character vector> matlab.net.base64encode ([1,2;3,4])\n%!error <consist of integers> matlab.net.base64encode (pi)\n"
  },
  {
    "path": "scripts/+matlab/+net/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/base64decode.m \\\n  %reldir%/base64encode.m\n\n%canon_reldir%dir = $(fcnfiledir)/+matlab/+net\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/@ftp/ascii.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} ascii (@var{f})\n## Set the FTP connection @var{f} to use ASCII mode for transfers.\n##\n## ASCII mode is only appropriate for text files as it will convert the\n## remote host's newline representation to the local host's newline\n## representation.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n## @seealso{@ftp/binary, @ftp/ftp}\n## @end deftypefn\n\nfunction ascii (f)\n  __ftp_ascii__ (f.curlhandle);\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/binary.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} binary (@var{f})\n## Set the FTP connection @var{f} to use binary mode for transfers.\n##\n## In binary mode there is no conversion of newlines from the remote\n## representation to the local representation.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n## @seealso{@ftp/ascii, @ftp/ftp}\n## @end deftypefn\n\nfunction binary (f)\n  __ftp_binary__ (f.curlhandle);\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/cd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{cwd} =} cd (@var{f})\n## @deftypefnx {} {} cd (@var{f}, @var{path})\n## @deftypefnx {} {@var{new_cwd} =} cd (@var{f}, @var{path})\n## Get or set the remote directory on the FTP connection @var{f}.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n##\n## If @var{path} is not specified, return the remote current working\n## directory.  Otherwise, set the remote directory to @var{path} and return\n## the new remote working directory.\n##\n## If the directory does not exist, an error message is printed and the\n## working directory is not changed.\n## @seealso{@ftp/dir, @ftp/ftp}\n## @end deftypefn\n\nfunction path = cd (f, path)\n\n  if (nargin == 2)\n    __ftp_cwd__ (f.curlhandle, path);\n  endif\n\n  path = __ftp_pwd__ (f.curlhandle);\n\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/close.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} close (@var{f})\n## Close the FTP connection represented by the FTP object @var{f}.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n## @seealso{@ftp/ftp}\n## @end deftypefn\n\nfunction close (f)\n  __ftp_close__ (f.curlhandle);\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/delete.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} delete (@var{f}, @var{file})\n## Delete the remote file @var{file} over the FTP connection @var{f}.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n## @seealso{@ftp/rmdir, @ftp/rename, @ftp/ftp}\n## @end deftypefn\n\nfunction delete (f, file)\n  __ftp_delete__ (f.curlhandle, file);\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/dir.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} dir (@var{f})\n## @deftypefnx {} {@var{lst} =} dir (@var{f})\n## List the current directory in verbose form for the FTP connection @var{f}.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n##\n## If the optional output @var{lst} is requested return a struct array\n## with one entry per file with the fields @code{name}, @code{date},\n## @code{bytes}, @code{isdir}, @code{datenum}.\n## @seealso{@ftp/cd, @ftp/mkdir, @ftp/rmdir, @ftp/ftp}\n## @end deftypefn\n\nfunction lst = dir (f)\n  if (nargout == 0)\n    __ftp_dir__ (f.curlhandle);\n  else\n    lst = __ftp_dir__ (f.curlhandle);\n  endif\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/disp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nfunction disp (obj)\n\n  printf (\"  FTP object\\n\");\n  printf (\"    host: %s\\n\", obj.host);\n  printf (\"    user: %s\\n\", obj.username);\n  printf (\"     dir: %s\\n\", __ftp_pwd__ (obj.curlhandle));\n  printf (\"    mode: %s\\n\", __ftp_mode__ (obj.curlhandle));\n\nendfunction\n"
  },
  {
    "path": "scripts/@ftp/ftp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{f} =} ftp (@var{host})\n## @deftypefnx {} {@var{f} =} ftp (@var{host}, @var{username}, @var{password})\n## Connect to the FTP server @var{host} with @var{username} and @var{password}.\n##\n## If @var{username} and @var{password} are not specified, user\n## @qcode{\"anonymous\"} with no password is used.  The returned FTP object\n## @var{f} represents the established FTP connection.\n##\n## The list of actions for an FTP object are shown below.  All functions\n## require an FTP object as the first argument.\n##\n## @multitable @columnfractions 0.15 0.8\n## @headitem Method @tab Description\n## @item ascii @tab Set transfer type to ascii\n## @item binary @tab Set transfer type to binary\n## @item cd @tab Change remote working directory\n## @item close @tab Close FTP connection\n## @item delete @tab Delete remote file\n## @item dir @tab List remote directory contents\n## @item mget @tab Download remote files\n## @item mkdir @tab Create remote directory\n## @item mput @tab Upload local files\n## @item rename @tab Rename remote file or directory\n## @item rmdir @tab Remove remote directory\n## @end multitable\n##\n## @seealso{@ftp/ascii, @ftp/binary, @ftp/cd, @ftp/close, @ftp/delete,\n## @ftp/dir, @ftp/mget, @ftp/mkdir, @ftp/mput, @ftp/rename, @ftp/rmdir}\n## @end deftypefn\n\nfunction obj = ftp (host = \"\", username = \"anonymous\", password = \"\")\n\n  if (nargin == 1 && isa (host, \"ftp\"))\n    obj = host;   # Copy constructor\n  else\n    p.host = host;\n    p.username = username;\n    p.password = password;\n    p.curlhandle = tempname (\"ftp-\");\n    if (nargin > 0)\n      p.curlhandle = __ftp__ (host, username, password);\n    endif\n    obj = class (p, \"ftp\");\n  endif\n\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/loadobj.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## @deftypefn {} {@var{b} =} loadobj (@var{a})\n## Method of a class to manipulate an object after loading it from a file.\n##\n## The function @code{loadobj} is called when the object @var{a} is loaded\n## using the @code{load} function.  An example of the use of @code{saveobj}\n## might be to add fields to an object that don't make sense to be saved.\n##\n## @seealso{saveobj, class}\n## @end deftypefn\n\nfunction b = loadobj (a)\n\n  b = a;\n  if (isfield (b, \"jobject\"))\n    b = rmfield (b, \"jobject\");\n  endif\n  b.curlhandle = __ftp__ (b.host, b.username, b.password);\n  if (isfield (b, \"dir\"))\n    if (! isempty (b.dir))\n      __ftp_cwd__ (b.curlhandle, b.dir);\n    endif\n    b = rmfield (b, \"dir\");\n  elseif (isfield (b, \"remotePwd\"))\n    ## FIXME: Can we read Matlab java stringBuffer objects?\n    warning (\"@ftp/loadobj: can not change remote directory in loaded FTP object\");\n    b = rmfield (b, \"remotePwd\");\n  endif\n\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/mget.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} mget (@var{f}, @var{file})\n## @deftypefnx {} {} mget (@var{f}, @var{dir})\n## @deftypefnx {} {} mget (@var{f}, @var{remote_name}, @var{target})\n## Download a remote file @var{file} or directory @var{dir} to the local\n## directory on the FTP connection @var{f}.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n##\n## The arguments @var{file} and @var{dir} can include wildcards and any\n## files or directories on the remote server that match will be downloaded.\n##\n## If a third string argument @var{target} is given, then it must indicate\n## the path to the local destination directory.  @var{target} may be a\n## relative or absolute path.\n## @seealso{@ftp/mput, @ftp/ftp}\n## @end deftypefn\n\nfunction mget (f, file, target = \"\")\n  __ftp_mget__ (f.curlhandle, file, target);\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/mkdir.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mkdir (@var{f}, @var{path})\n## Create the remote directory @var{path}, over the FTP connection @var{f}.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n## @seealso{@ftp/rmdir, @ftp/ftp}\n## @end deftypefn\n\nfunction mkdir (f, path)\n  __ftp_mkdir__ (f.curlhandle, path);\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/module.mk",
    "content": "## Automake fails to process \"include %reldir%/module.mk\" in the directory\n## above.  All of the commands which would normally be in this file were\n## manually placed in scripts/module.mk to avoid using the \"include\" directive.\n##\n## This is an Automake bug.  Automake has switched to a Perl backend which uses\n## the following pattern to detect a path:\n##\n## my $PATH_PATTERN = '(\\w|[+/.-])+';\n##\n## This pattern only includes alphanumeric, '_', and [+/.-], but not \"@\".\n"
  },
  {
    "path": "scripts/@ftp/mput.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} mput (@var{f}, @var{file})\n## @deftypefnx {} {@var{file_list} =} mput (@var{f}, @var{file})\n## Upload the local file @var{file} into the current remote directory on the\n## FTP connection @var{f}.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n##\n## The argument @var{file} is passed through the @code{glob} function and any\n## files that match the wildcards in @var{file} will be uploaded.\n##\n## The optional output argument @var{file_list} contains a cell array of\n## strings with the names of the uploaded files.\n## @seealso{@ftp/mget, @ftp/mkdir, @ftp/ftp}\n## @end deftypefn\n\nfunction retval = mput (f, file)\n  if (nargout == 0)\n    __ftp_mput__ (f.curlhandle, file);\n  else\n    retval = __ftp_mput__ (f.curlhandle, file);\n  endif\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/rename.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} rename (@var{f}, @var{oldname}, @var{newname})\n## Rename or move the remote file or directory @var{oldname} to @var{newname},\n## over the FTP connection @var{f}.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n## @seealso{@ftp/delete, @ftp/rmdir, @ftp/ftp}\n## @end deftypefn\n\nfunction rename (f, oldname, newname)\n  __ftp_rename__ (f.curlhandle, oldname, newname);\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/rmdir.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} rmdir (@var{f}, @var{path})\n## Remove the remote directory @var{path}, over the FTP connection @var{f}.\n##\n## @var{f} is an FTP object returned by the @code{ftp} function.\n## @seealso{@ftp/delete, @ftp/mkdir, @ftp/rename, @ftp/ftp}\n## @end deftypefn\n\nfunction rmdir (f, path)\n  __ftp_rmdir__ (f.curlhandle, path);\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/@ftp/saveobj.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{b} =} saveobj (@var{a})\n## Method of a class to manipulate an object prior to saving it to a file.\n##\n## The function @code{saveobj} is called when the object @var{a} is saved\n## using the @code{save} function.  An example of the use of @code{saveobj}\n## might be to remove fields of the object that don't make sense to be saved\n## or it might be used to ensure that certain fields of the object are\n## initialized before the object is saved.\n##\n## @seealso{loadobj, class}\n## @end deftypefn\n\nfunction b = saveobj (a)\n  b = a;\n  b = rmfield (b, \"curlhandle\");\n  b.dir = __ftp_pwd__ (a.curlhandle);\nendfunction\n\n\n## No test possible for interactive function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/audio/@audioplayer/__get_properties__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{props} =} __get_properties__ (@var{player})\n## Return a struct containing all named properties of the audioplayer object\n## @var{player}.\n## @seealso{@audioplayer/get, @audioplayer/set, @audioplayer/audioplayer}\n## @end deftypefn\n\nfunction props = __get_properties__ (player)\n\n  hplayer = struct (player).player;\n\n  props = struct (\"BitsPerSample\",\n                  __player_get_nbits__ (hplayer),\n\n                  \"CurrentSample\",\n                  __player_get_sample_number__ (hplayer),\n\n                  \"DeviceID\",\n                  __player_get_id__ (hplayer),\n\n                  \"NumberOfChannels\",\n                  __player_get_channels__ (hplayer),\n\n                  \"Running\",\n                  ifelse (__player_isplaying__ (hplayer), \"on\", \"off\"),\n\n                  \"SampleRate\",\n                  __player_get_fs__ (hplayer),\n\n                  \"TotalSamples\",\n                  __player_get_total_samples__ (hplayer),\n\n                  \"Tag\",\n                  __player_get_tag__ (hplayer),\n\n                  \"Type\",\n                  \"audioplayer\",\n\n                  \"UserData\",\n                  __player_get_userdata__ (hplayer));\n\nendfunction\n"
  },
  {
    "path": "scripts/audio/@audioplayer/audioplayer.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{player} =} audioplayer (@var{y}, @var{fs})\n## @deftypefnx {} {@var{player} =} audioplayer (@var{y}, @var{fs}, @var{nbits})\n## @deftypefnx {} {@var{player} =} audioplayer (@var{y}, @var{fs}, @var{nbits}, @var{id})\n## @deftypefnx {} {@var{player} =} audioplayer (@var{recorder})\n## @deftypefnx {} {@var{player} =} audioplayer (@var{recorder}, @var{id})\n## Create an audioplayer object that will play back data @var{y} at sample\n## rate @var{fs}.\n##\n## The signal @var{y} can be a vector (mono audio) or a two-dimensional array\n## (multi-channel audio).\n##\n## The optional arguments @var{nbits} and @var{id} specify the number of bits\n## per sample and player device ID, respectively.  Device IDs may be found\n## using the @code{audiodevinfo} function.\n##\n## Given an audiorecorder object @var{recorder}, use the data from the object\n## to initialize the player.\n##\n## The list of actions for an audioplayer object are shown below.  All\n## methods require an audioplayer object as the first argument.\n##\n## @multitable @columnfractions 0.2 0.75\n## @headitem Method @tab Description\n## @item get @tab Read audioplayer property values\n## @item isplaying @tab Return true if audioplayer is playing\n## @item pause @tab Pause audioplayer playback\n## @item play @tab Play audio stored in audioplayer object w/o blocking\n## @item playblocking @tab Play audio stored in audioplayer object\n## @item resume @tab Resume playback after pause\n## @item set @tab Write audioplayer property values\n## @item stop @tab Stop playback\n## @end multitable\n##\n## Example\n##\n## Create an audioplayer object that will play back one second of white noise\n## at 44100 sample rate using 8 bits per sample.\n##\n## @example\n## @group\n## y = 0.25 * randn (2, 44100);\n## player = audioplayer (y, 44100, 8);\n## play (player);\n## @end group\n## @end example\n## @seealso{@audioplayer/get, @audioplayer/isplaying, @audioplayer/pause,\n## @audioplayer/play, @audioplayer/playblocking, @audioplayer/resume,\n## @audioplayer/set, @audioplayer/stop, audiodevinfo,\n## @audiorecorder/audiorecorder, sound, soundsc}\n## @end deftypefn\n\nfunction player = audioplayer (varargin)\n\n  if (nargin < 1 || nargin > 4)\n    print_usage ();\n  endif\n\n  if (isa (varargin{1}, \"audiorecorder\"))\n    if (nargin == 1)\n      player = getplayer (varargin{1});\n    elseif (nargin == 2)\n      recorder = varargin{1};\n      data = getaudiodata (recorder);\n      player = audioplayer (data,\n                            get (recorder, \"SampleRate\"),\n                            get (recorder, \"BitsPerSample\"),\n                            varargin{2});\n    else\n      print_usage ();\n    endif\n  else\n    ## FIXME: There is incomplete input validation in internal C++ function.\n    ##        All validation should occur here in m-file.\n    if (isempty (varargin{1}))\n      error (\"audioplayer: Y must be non-empty numeric data\");\n    endif\n    player.player = __player_audioplayer__ (varargin{:});\n    player = class (player, \"audioplayer\");\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Generate 2 seconds of white noise and play it back with a pause\n%! fs = 44100;\n%! audio = 0.25 * randn (2, 2*fs);\n%! player = audioplayer (audio, fs);\n%! play (player);\n%! pause (1);\n%! pause (player);\n%! pause (1);\n%! resume (player);\n%! pause (1);\n%! stop (player);\n\n## Tests of audioplayer must not actually play anything.\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! mono = 0.25 * randn (1, 44100);\n%! stereo = 0.25 * randn (2, 44100);\n%! fs = 44100;\n%! player1 = audioplayer (mono, fs);\n%! player2 = audioplayer (stereo, fs);\n%! assert (player1.NumberOfChannels, 1);\n%! assert (player2.NumberOfChannels, 2);\n%! assert (player1.SampleRate, 44100);\n%! assert (player2.SampleRate, 44100);\n%! assert (player1.TotalSamples, 44100);\n%! assert (player2.TotalSamples, 44100);\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! audio = randn (8000, 1);\n%! fs = 44100;\n%! player = audioplayer (audio, fs, 16);\n%! assert (player.NumberOfChannels, 1);\n%! assert (player.SampleRate, 44100);\n%! assert (player.BitsPerSample, 16);\n\n## Verify input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! ## Verify nbits option only accepts 8, 16, 24\n%! fail (\"audioplayer (1, 8e3, 9)\", \"NBITS must be 8, 16, or 24\");\n%! fail (\"audioplayer (1, 8e3, 32)\", \"NBITS must be 8, 16, or 24\");\n%! player = audioplayer (1, 8e3, 8);\n%! player = audioplayer (1, 8e3, 16);\n%! player = audioplayer (1, 8e3, 24);\n\n%!error <Y must be non-empty numeric data> audioplayer ([])\n"
  },
  {
    "path": "scripts/audio/@audioplayer/disp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} disp (@var{player})\n## Display the properties of the audioplayer object @var{player}.\n## @seealso{@audioplayer/audioplayer}\n## @end deftypefn\n\nfunction disp (player)\n\n  printf (\"audioplayer object with properties:\\n\\n\");\n  for [val, prop] = __get_properties__ (player)\n    printf (\"  %s = \", prop), disp (val);\n  endfor\n\nendfunction\n\n\n## No tests possible/needed for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audioplayer/get.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{value} =} get (@var{player}, @var{name})\n## @deftypefnx {} {@var{values} =} get (@var{player}, @lbracechar{}@var{name1}, @var{name2}, @dots{}@rbracechar{})\n## @deftypefnx {} {@var{values} =} get (@var{player})\n## Return the @var{value} of the property identified by @var{name}.\n##\n## If @var{name} is a cell array return the values of the properties\n## identified by the elements of the cell array.  Given only the player\n## object, return a scalar structure with values for all properties of\n## @var{player}.  The field names of the structure correspond to the property\n## names.\n## @seealso{@audioplayer/set, @audioplayer/audioplayer}\n## @end deftypefn\n\nfunction value = get (player, name)\n\n  properties = __get_properties__ (player);\n\n  if (nargin == 1)\n    value = properties;\n  elseif (nargin == 2)\n    pnames = name;\n    if (ischar (pnames))\n      value = getproperty (properties, pnames);\n    elseif (iscellstr (pnames))\n      value = cell (size (pnames));\n      for i = 1:numel (pnames)\n        value{i} = getproperty (properties, pnames{i});\n      endfor\n    else\n      error (\"@audioplayer/get: NAME must be a string or cell array of strings\");\n    endif\n  endif\n\nendfunction\n\nfunction value = getproperty (properties, pname)\n\n  persistent valid_props;\n  if (isempty (valid_props))\n    valid_props = { \"BitsPerSample\", \"CurrentSample\", \"DeviceID\", ...\n                    \"NumberOfChannels\", \"Running\", \"SampleRate\", ...\n                    \"TotalSamples\", \"Tag\", \"Type\", \"UserData\" };\n  endif\n\n  idx = find (strcmpi (pname, valid_props), 1);\n  if (isempty (idx))\n    error ('@audioplayer/get: \"%s\" is not a valid property name', pname);\n  endif\n\n  value = properties.(valid_props{idx});\n\nendfunction\n\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! props = get (player);\n%! assert (fieldnames (props), {\"BitsPerSample\"; \"CurrentSample\"; \"DeviceID\";\n%!         \"NumberOfChannels\"; \"Running\"; \"SampleRate\"; \"TotalSamples\"; \"Tag\";\n%!         \"Type\"; \"UserData\"});\n%! value = get (player, \"Running\");\n%! assert (value, \"off\");\n%! value = get (player, \"ruNNIng\");  # test case insensitivity\n%! assert (value, \"off\");\n%! values = get (player, {\"SampleRate\", \"BitsPerSample\", \"TotalSamples\"});\n%! assert (values, {44100, 8, 2});\n\n## Test input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! fail (\"get (player, 1)\", \"NAME must be a string\");\n%! fail ('get (player, \"foobar\")', '\"foobar\" is not a valid property');\n"
  },
  {
    "path": "scripts/audio/@audioplayer/isplaying.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isplaying (@var{player})\n## Return true if the audioplayer object @var{player} is currently playing back\n## audio and false otherwise.\n## @seealso{@audioplayer/pause, @audioplayer/audioplayer}\n## @end deftypefn\n\nfunction tf = isplaying (player)\n\n  tf = __player_isplaying__ (struct (player).player);\n\nendfunction\n\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! assert (isplaying (player), false);\n"
  },
  {
    "path": "scripts/audio/@audioplayer/pause.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} pause (@var{player})\n## Pause playback of audioplayer @var{player}.\n## @seealso{@audioplayer/resume, @audioplayer/stop, @audioplayer/audioplayer}\n## @end deftypefn\n\nfunction pause (player)\n\n  __player_pause__ (struct (player).player);\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audioplayer/play.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} play (@var{player})\n## @deftypefnx {} {} play (@var{player}, @var{start})\n## @deftypefnx {} {} play (@var{player}, [@var{start}, @var{end}])\n## Play audio stored in the audioplayer object @var{player} without blocking.\n##\n## If the optional argument @var{start} is provided, begin playing\n## @var{start} samples in to the recording.\n##\n## If the optional argument @var{end} is provided, stop playing at\n## @var{end} samples into the recording.\n## @seealso{@audioplayer/playblocking, @audioplayer/pause, @audioplayer/stop,\n## @audioplayer/audioplayer}\n## @end deftypefn\n\nfunction play (player, length)\n\n  hplayer = struct (player).player;\n\n  if (nargin == 1)\n    __player_play__ (hplayer);\n  else\n    __player_play__ (hplayer, length);\n  endif\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audioplayer/playblocking.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} playblocking (@var{player})\n## @deftypefnx {} {} playblocking (@var{player}, @var{start})\n## @deftypefnx {} {} playblocking (@var{player}, [@var{start}, @var{end}])\n## Play audio stored in the audioplayer object @var{player} with blocking\n## (synchronous I/O).\n##\n## If the optional argument @var{start} is provided, begin playing\n## @var{start} samples into the recording.\n##\n## If the optional argument @var{end} is provided, stop playing at\n## @var{end} samples into the recording.\n## @seealso{@audioplayer/play, @audioplayer/pause, @audioplayer/stop,\n## @audioplayer/audioplayer}\n## @end deftypefn\n\nfunction playblocking (player, start)\n\n  if (nargin == 1)\n    __player_playblocking__ (struct (player).player);\n  else\n    __player_playblocking__ (struct (player).player, start);\n  endif\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audioplayer/resume.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} resume (@var{player})\n## Resume playback for the paused audioplayer object @var{player}.\n## @seealso{@audioplayer/pause, @audioplayer/stop, @audioplayer/audioplayer}\n## @end deftypefn\n\nfunction resume (player)\n\n  __player_resume__ (struct (player).player);\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audioplayer/set.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} set (@var{player}, @var{name}, @var{value})\n## @deftypefnx {} {} set (@var{player}, @var{name_cell}, @var{value_cell})\n## @deftypefnx {} {} set (@var{player}, @var{properties_struct})\n## @deftypefnx {} {@var{properties} =} set (@var{player})\n## Set the value of property specified by @var{name} to a given @var{value}.\n##\n## If @var{name} and @var{value} are cell arrays, set each property to the\n## corresponding value.  Given a structure of properties with fields\n## corresponding to property names, set the value of those properties to the\n## corresponding field values.  Given only an audioplayer object, return a\n## structure of configurable properties (i.e., writeable properties).\n## @seealso{@audioplayer/get, @audioplayer/audioplayer}\n## @end deftypefn\n\nfunction properties = set (player, varargin)\n\n  if (nargin > 3)\n    print_usage ();\n  endif\n\n  hplayer = struct (player).player;\n\n  if (nargin == 1)\n    properties = struct (\"SampleRate\", {{}}, \"Tag\", {{}}, \"UserData\", {{}});\n  elseif (nargin == 2)\n    for [value, property] = varargin{1}\n      setproperty (hplayer, property, value);\n    endfor\n  elseif (nargin == 3)\n    if (iscell (varargin{1}))\n      index = 1;\n      for property = varargin{1}\n        setproperty (hplayer, char (property), varargin{2}{index});\n        index += 1;\n      endfor\n    else\n      setproperty (hplayer, varargin{1}, varargin{2});\n    endif\n  endif\n\nendfunction\n\nfunction setproperty (player, property, value)\n\n  switch (lower (property))\n    case \"samplerate\"\n      __player_set_fs__ (player, value);\n    case \"tag\"\n      __player_set_tag__ (player, value);\n    case \"userdata\"\n      __player_set_userdata__ (player, value);\n    otherwise\n      error ('@audioplayer/set: \"%s\" is not a valid property name or is read-only', property);\n  endswitch\n\nendfunction\n\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! set (player, \"SampleRate\", 8800);\n%! set (player, \"Tag\", \"mytag\");\n%! ## Also test case insensitivity\n%! set (player, \"USERdata\", [1, 2; 3, 4]);\n%! assert (player.SampleRate, 8800);\n%! assert (player.Tag, \"mytag\");\n%! assert (player.UserData, [1, 2; 3, 4]);\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! set (player, {\"SampleRate\", \"Tag\", \"UserData\"},\n%!              {8800, \"mytag\", [1, 2; 3, 4]});\n%! assert (player.SampleRate, 8800);\n%! assert (player.Tag, \"mytag\");\n%! assert (player.UserData, [1, 2; 3, 4]);\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! props = set (player);\n%! props.SampleRate = 8800;\n%! props.Tag = \"mytag\";\n%! props.UserData = [1, 2; 3, 4];\n%! set (player, props);\n%! assert (player.SampleRate, 8800);\n%! assert (player.Tag, \"mytag\");\n%! assert (player.UserData, [1, 2; 3, 4]);\n\n## Test input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! fail ('set (player, \"foobar\", 1)', \"not a valid property name\");\n%! fail ('set (player, \"Running\", 1)', \"is read-only\");\n"
  },
  {
    "path": "scripts/audio/@audioplayer/stop.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} stop (@var{player})\n## Stop playback of the audioplayer @var{player} and reset relevant variables\n## to their initial values.\n## @seealso{@audioplayer/pause, @audioplayer/resume, @audioplayer/audioplayer}\n## @end deftypefn\n\nfunction stop (player)\n\n  __player_stop__ (struct (player).player);\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audioplayer/subsasgn.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{value} =} subsasgn (@var{player}, @var{idx}, @var{rhs})\n## Perform subscripted assignment on the audio player object @var{player}.\n##\n## Assign the value of @var{rhs} to the player property named by @var{idx}.\n## @seealso{@audioplayer/audioplayer}\n## @end deftypefn\n\nfunction value = subsasgn (player, idx, rhs)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (isempty (idx))\n    error (\"audioplayer: missing index\");\n  endif\n\n  if (strcmp (idx(1).type, \".\"))\n    field = idx.subs;\n    set (player, field, rhs);\n    value = player;\n  else\n    error (\"@audioplayer/subsasgn: invalid subscript type\");\n  endif\n\nendfunction\n\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! player.Tag = \"mytag\";\n%! assert (get (player, \"Tag\"), \"mytag\");\n\n## Test input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! fail (\"player(1).Tag = 5\", \"invalid subscript type\");\n%! fail (\"player{1}.Tag = 5\", \"invalid subscript type\");\n"
  },
  {
    "path": "scripts/audio/@audioplayer/subsref.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{value} =} subsref (@var{player}, @var{idx})\n## Perform subscripted selection on the audio player object @var{player}.\n##\n## Return the player property value named by @var{idx}.\n## @seealso{@audioplayer/audioplayer}\n## @end deftypefn\n\nfunction value = subsref (player, idx)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (isempty (idx))\n    error (\"@audioplayer/subsref: missing index\");\n  endif\n\n  if (strcmp (idx(1).type, \".\"))\n    field = idx.subs;\n    value = get (player, field);\n  else\n    error (\"@audioplayer/subsref: invalid subscript type\");\n  endif\n\nendfunction\n\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! set (player, \"Tag\", \"mytag\");\n%! assert (player.Tag, \"mytag\");\n\n## Test input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0\n%! player = audioplayer ([-1, 1], 44100, 8);\n%! fail (\"player(1).Tag\", \"invalid subscript type\");\n%! fail (\"player{1}.Tag\", \"invalid subscript type\");\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/__get_properties__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{props} =} __get_properties__ (@var{recorder})\n## Return a struct containing all named properties of the recorder object\n## @var{recorder}.\n## @seealso{@audiorecorder/get, @audiorecorder/set,\n## @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction props = __get_properties__ (recorder)\n\n  hrecorder = struct (recorder).recorder;\n\n  props = struct (\"BitsPerSample\",\n                  __recorder_get_nbits__ (hrecorder),\n\n                  \"CurrentSample\",\n                  __recorder_get_sample_number__ (hrecorder),\n\n                  \"DeviceID\",\n                  __recorder_get_id__ (hrecorder),\n\n                  \"NumberOfChannels\",\n                  __recorder_get_channels__ (hrecorder),\n\n                  \"Running\",\n                  ifelse (__recorder_isrecording__ (hrecorder), \"on\", \"off\"),\n\n                  \"SampleRate\",\n                  __recorder_get_fs__ (hrecorder),\n\n                  \"TotalSamples\",\n                  __recorder_get_total_samples__ (hrecorder),\n\n                  \"Tag\",\n                  __recorder_get_tag__ (hrecorder),\n\n                  \"Type\",\n                  \"audiorecorder\",\n\n                  \"UserData\",\n                  __recorder_get_userdata__ (hrecorder));\n\nendfunction\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/audiorecorder.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{recorder} =} audiorecorder ()\n## @deftypefnx {} {@var{recorder} =} audiorecorder (@var{fs}, @var{nbits}, @var{nchannels})\n## @deftypefnx {} {@var{recorder} =} audiorecorder (@var{fs}, @var{nbits}, @var{nchannels}, @var{id})\n## Create an audiorecorder object recording 8-bit mono audio at 8000 Hz\n## sample rate.\n##\n## The optional arguments @var{fs}, @var{nbits}, @var{nchannels}, and @var{id}\n## specify the sample rate, number of bits per sample, number of channels, and\n## recording device ID, respectively.  Device IDs may be found using the\n## @code{audiodevinfo} function.\n##\n## The list of actions for an audiorecorder object are shown below.  All\n## methods require an audiorecorder object as the first argument.\n##\n## @multitable @columnfractions 0.22 0.73\n## @headitem Method @tab Description\n## @item get @tab Read audiorecorder property values\n## @item getaudiodata @tab Return audio data as a numeric matrix\n## @item getplayer @tab Return audioplayer loaded with data from audiorecorder\n## @item isrecording @tab Return true if audiorecorder is recording\n## @item pause @tab Pause recording\n## @item play @tab Play audio stored in audiorecorder object\n## @item record @tab Record audio in audiorecorder object w/o blocking\n## @item recordblocking @tab Record audio in audiorecorder object\n## @item resume @tab Resume recording after pause\n## @item set @tab Write audiorecorder property values\n## @item stop @tab Stop recording\n## @end multitable\n##\n## @seealso{@audiorecorder/get, @audiorecorder/getaudiodata,\n## @audiorecorder/getplayer, @audiorecorder/isrecording,\n## @audiorecorder/pause, @audiorecorder/play, @audiorecorder/record,\n## @audiorecorder/recordblocking, @audioplayer/resume, @audiorecorder/set,\n## @audiorecorder/stop, audiodevinfo, @audioplayer/audioplayer, record}\n## @end deftypefn\n\nfunction recorder = audiorecorder (varargin)\n\n  if (! (nargin == 0 || nargin == 3 || nargin == 4))\n    print_usage ();\n  endif\n\n  ## FIXME: No input validation in internal C++ function.\n  ##        It should occur here.\n  recorder.recorder = __recorder_audiorecorder__ (varargin{:});\n  recorder = class (recorder, \"audiorecorder\");\n\nendfunction\n\n\n%!demo\n%! ## Record 1 second of audio and play it back in two ways\n%! recorder = audiorecorder (44100, 16, 2);\n%! record (recorder, 1);\n%! pause (2);\n%! player1 = audioplayer (recorder);\n%! player2 = getplayer (recorder);\n%! play (player1);\n%! pause (2);\n%! play (player2);\n%! pause (2);\n%! stop (player1);\n%! stop (player2);\n\n## Tests of audiorecorder must not actually record anything.\n\n## Test input validation\n%!error <Invalid call> audiorecorder (1)\n%!error <Invalid call> audiorecorder (1, 8)\n%!error <Invalid call> audiorecorder (1, 8, 2, -1, 5)\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/disp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} disp (@var{recorder})\n## Display the properties of the audiorecorder object @var{recorder}.\n## @seealso{@audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction disp (recorder)\n\n  printf (\"audiorecorder object with properties:\\n\\n\");\n  for [val, prop] = __get_properties__ (recorder)\n    printf (\"  %s = \", prop), disp (val);\n  endfor\n\nendfunction\n\n\n## No tests possible/needed for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/get.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{value} =} get (@var{recorder}, @var{name})\n## @deftypefnx {} {@var{values} =} get (@var{recorder}, @lbracechar{}@var{name1}, @var{name2}, @dots{}@rbracechar{})\n## @deftypefnx {} {@var{values} =} get (@var{recorder})\n## Return the @var{value} of the property identified by @var{name}.\n##\n## If @var{name} is a cell array return the values of the properties\n## identified by the elements of the cell array.  Given only the recorder\n## object, return a scalar structure with values for all properties of\n## @var{recorder}.  The field names of the structure correspond to the property\n## names.\n## @seealso{@audiorecorder/set, @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction value = get (recorder, name)\n\n  properties = __get_properties__ (recorder);\n\n  if (nargin == 1)\n    value = properties;\n  elseif (nargin == 2)\n    pnames = name;\n    if (ischar (pnames))\n      value = getproperty (properties, pnames);\n    elseif (iscellstr (pnames))\n      value = cell (size (pnames));\n      for i = 1:numel (pnames)\n        value{i} = getproperty (properties, pnames{i});\n      endfor\n    else\n      error (\"@audiorecorder/get: NAME must be a string or cell array of strings\");\n    endif\n  endif\n\nendfunction\n\nfunction value = getproperty (properties, pname)\n\n  persistent valid_props;\n  if (isempty (valid_props))\n    valid_props = { \"BitsPerSample\", \"CurrentSample\", \"DeviceID\", ...\n                    \"NumberOfChannels\", \"Running\", \"SampleRate\", ...\n                    \"TotalSamples\", \"Tag\", \"Type\", \"UserData\" };\n  endif\n\n  idx = find (strcmpi (pname, valid_props), 1);\n  if (isempty (idx))\n    error ('@audiorecorder/get: \"%s\" is not a valid property name', pname);\n  endif\n\n  value = properties.(valid_props{idx});\n\nendfunction\n\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 16, 2);\n%! props = get (recorder);\n%! assert (fieldnames (props), {\"BitsPerSample\"; \"CurrentSample\"; \"DeviceID\";\n%!         \"NumberOfChannels\"; \"Running\"; \"SampleRate\"; \"TotalSamples\"; \"Tag\";\n%!         \"Type\"; \"UserData\"});\n%! value = get (recorder, \"Running\");\n%! assert (value, \"off\");\n%! values = get (recorder, {\"SampleRate\", \"BitsPerSample\", \"NumberOfChannels\"});\n%! assert (values, {44100, 16, 2});\n\n## Test input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 16, 2);\n%! fail (\"get (recorder, 1)\", \"NAME must be a string\");\n%! fail ('get (recorder, \"foobar\")', '\"foobar\" is not a valid property');\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/getaudiodata.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{data} =} getaudiodata (@var{recorder})\n## @deftypefnx {} {@var{data} =} getaudiodata (@var{recorder}, @var{datatype})\n## Return audio data from audiorecorder object @var{recorder} as a double\n## matrix with values between -1.0 and 1.0 and with as many columns as there\n## are channels in @var{recorder}.\n##\n## Given the optional argument @var{datatype}, convert the recorded data\n## to the specified type, which may be one of @qcode{\"double\"},\n## @qcode{\"single\"}, @qcode{\"int16\"}, @qcode{\"int8\"} or @qcode{\"uint8\"}.\n## @seealso{@audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction data = getaudiodata (recorder, datatype)\n\n  hrecorder = struct (recorder).recorder;\n\n  if (nargin == 1)\n    data = __recorder_getaudiodata__ (hrecorder);\n  else\n    data = __recorder_getaudiodata__ (hrecorder);\n    switch (datatype)\n      case \"double\"\n        ## Do nothing, data is already of type double\n      case \"single\"\n        data = single (data);\n      case \"int16\"\n        data = int16 (data * (2.0 ^ 15));\n      case \"int8\"\n        data = int8 (data * (2.0 ^ 7));\n      case \"uint8\"\n        data = uint8 ((data + 1.0) * 0.5 * (2.0 ^ 8 - 1));\n      otherwise\n        error ('@audiorecorder/getaudiodata: invalid DATATYPE \"%s\"', datatype);\n    endswitch\n  endif\n\n  if (get (recorder, \"NumberOfChannels\") == 2)\n    data = data.';\n  else\n    data = data(1,:).';\n  endif\n\nendfunction\n\n\n## Tests of audiorecorder must not actually record anything.\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 16, 2);\n%! data = getaudiodata (recorder);\n%! assert (isa (data, \"double\"));\n%! data = getaudiodata (recorder, \"double\");\n%! assert (isa (data, \"double\"));\n%! data = getaudiodata (recorder, \"single\");\n%! assert (isa (data, \"single\"));\n%! data = getaudiodata (recorder, \"int16\");\n%! assert (isa (data, \"int16\"));\n%! data = getaudiodata (recorder, \"int8\");\n%! assert (isa (data, \"int8\"));\n%! data = getaudiodata (recorder, \"uint8\");\n%! assert (isa (data, \"uint8\"));\n%! assert (size (data)(1), recorder.TotalSamples);\n%! assert (size (data)(2), 2);\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 8, 1);\n%! data = getaudiodata (recorder);\n%! assert (size (data)(1), recorder.TotalSamples);\n%! assert (size (data)(2), 1);\n\n## Test input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 16, 2);\n%! fail (\"getaudiodata (recorder, 'foobar')\", \"invalid DATATYPE\");\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/getplayer.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{player} =} getplayer (@var{recorder})\n## Return an audioplayer object with data recorded by the audiorecorder object\n## @var{recorder}.\n## @seealso{@audioplayer/audioplayer, @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction player = getplayer (recorder)\n\n  data = getaudiodata (recorder);\n  player = audioplayer (data,\n                        get (recorder, \"SampleRate\"),\n                        get (recorder, \"BitsPerSample\"));\n\nendfunction\n\n\n## FIXME: Uncomment when audioplayer constructor supports null data\n%!#testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%!# recorder = audiorecorder (44100, 16, 2);\n%!# player = getplayer (recorder);\n%!# assert (isa (player, \"audioplayer\"));\n%!# assert (player.SampleRate, 44100);\n%!# assert (player.BitsPerSample, 16);\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/isrecording.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isrecording (@var{recorder})\n## Return true if the audiorecorder object @var{recorder} is currently\n## recording audio and false otherwise.\n## @seealso{@audiorecorder/pause, @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction tf = isrecording (recorder)\n\n  tf = __recorder_isrecording__ (struct (recorder).recorder);\n\nendfunction\n\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 16, 2);\n%! assert (isrecording (recorder), false);\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/pause.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} pause (@var{recorder})\n## Pause recording for audiorecorder @var{recorder}.\n## @seealso{@audiorecorder/resume, @audiorecorder/stop,\n## @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction pause (recorder)\n\n  __recorder_pause__ (struct (recorder).recorder);\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/play.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{player} =} play (@var{recorder})\n## @deftypefnx {} {@var{player} =} play (@var{recorder}, @var{start})\n## @deftypefnx {} {@var{player} =} play (@var{recorder}, [@var{start}, @var{end}])\n## Play the audio recorded in @var{recorder} without blocking and return a\n## corresponding audioplayer object.\n##\n## If the optional argument @var{start} is provided, begin playing\n## @var{start} seconds into the recording.\n##\n## If the optional argument @var{end} is provided, stop playing at\n## @var{end} seconds into the recording.\n## @seealso{@audiorecorder/getplayer, @audioplayer/audioplayer,\n## @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction player = play (recorder, start)\n\n  data = getaudiodata (recorder);\n  player = audioplayer (data,\n                        get (recorder, \"SampleRate\"),\n                        get (recorder, \"BitsPerSample\"));\n\n  if (nargin == 1)\n    play (player);\n  else\n    play (player, start);\n  endif\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/record.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} record (@var{recorder})\n## @deftypefnx {} {} record (@var{recorder}, @var{length})\n## Record audio without blocking using the audiorecorder object\n## @var{recorder} until paused or stopped by the @var{pause} or @var{stop}\n## methods.\n##\n## Given the optional argument @var{length}, record for @var{length} seconds.\n## @seealso{@audiorecorder/recordblocking, @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction record (recorder, length)\n\n  hrecorder = struct (recorder).recorder;\n\n  if (nargin == 1)\n    __recorder_record__ (hrecorder);\n  else\n    __recorder_record__ (hrecorder, length);\n  endif\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/recordblocking.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} recordblocking (@var{recorder}, @var{length})\n## Record audio with blocking (synchronous I/O).\n##\n## The length of the recording in seconds (@var{length}) must be specified.\n## @seealso{@audiorecorder/record, @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction recordblocking (recorder, length)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  __recorder_recordblocking__ (struct (recorder).recorder, length);\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/resume.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} resume (@var{recorder})\n## Resume recording with the paused audiorecorder object @var{recorder}.\n## @seealso{@audiorecorder/pause, @audiorecorder/stop,\n## @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction resume (recorder)\n\n  __recorder_resume__ (struct (recorder).recorder);\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/set.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} set (@var{recorder}, @var{name}, @var{value})\n## @deftypefnx {} {} set (@var{recorder}, @var{name_cell}, @var{value_cell})\n## @deftypefnx {} {} set (@var{recorder}, @var{properties_struct})\n## @deftypefnx {} {@var{properties} =} set (@var{recorder})\n## Set the value of property specified by @var{name} to a given @var{value}.\n##\n## If @var{name} and @var{value} are cell arrays, set each property to a\n## corresponding value.  Given a structure of properties with fields\n## corresponding to property names, set the value of those properties to the\n## corresponding field values.  Given only a recorder object, return a\n## structure of configurable properties (i.e., writeable properties).\n## @seealso{@audiorecorder/get, @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction properties = set (recorder, varargin)\n\n  if (nargin > 3)\n    print_usage ();\n  endif\n\n  hrecorder = struct (recorder).recorder;\n\n  if (nargin == 1)\n    properties = struct (\"SampleRate\", {{}}, \"Tag\", {{}}, \"UserData\", {{}});\n\n  elseif (nargin == 2)\n    for [value, property] = varargin{1}\n      setproperty (hrecorder, property, value);\n    endfor\n\n  elseif (nargin == 3)\n    if (iscell (varargin{1}))\n      index = 1;\n      for property = varargin{1}\n        setproperty (hrecorder, char (property), varargin{2}{index});\n        index += 1;\n      endfor\n    else\n      setproperty (hrecorder, varargin{1}, varargin{2});\n    endif\n  endif\n\nendfunction\n\nfunction setproperty (recorder, property, value)\n\n  switch (lower (property))\n    case \"samplerate\"\n      __recorder_set_fs__ (recorder, value);\n    case \"tag\"\n      __recorder_set_tag__ (recorder, value);\n    case \"userdata\"\n      __recorder_set_userdata__ (recorder, value);\n    otherwise\n      error ('@audiorecorder/set: \"%s\" is not a valid property name or is read-only', property);\n  endswitch\n\nendfunction\n\n\n## Tests of audiorecorder must not actually record anything.\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder ();\n%! set (recorder, \"SampleRate\", 8800);\n%! set (recorder, \"Tag\", \"mytag\");\n%! ## Also test case insensitivity\n%! set (recorder, \"USERdata\", [1, 2; 3, 4]);\n%! assert (recorder.SampleRate, 8800);\n%! assert (recorder.Tag, \"mytag\");\n%! assert (recorder.UserData, [1, 2; 3, 4]);\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder ();\n%! set (recorder, {\"SampleRate\", \"Tag\", \"UserData\"},\n%!                {8800, \"mytag\", [1, 2; 3, 4]});\n%! assert (recorder.SampleRate, 8800);\n%! assert (recorder.Tag, \"mytag\");\n%! assert (recorder.UserData, [1, 2; 3, 4]);\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder ();\n%! props = set (recorder);\n%! props.SampleRate = 8800;\n%! props.Tag = \"mytag\";\n%! props.UserData = [1, 2; 3, 4];\n%! set (recorder, props);\n%! assert (recorder.SampleRate, 8800);\n%! assert (recorder.Tag, \"mytag\");\n%! assert (recorder.UserData, [1, 2; 3, 4]);\n\n## Test input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder ();\n%! fail ('set (recorder, \"foobar\", 1)', \"not a valid property name\");\n%! fail ('set (recorder, \"Running\", 1)', \"is read-only\");\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/stop.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} stop (@var{recorder})\n## Stop recording with audiorecorder object @var{recorder} and clean up any\n## audio streams.\n## @seealso{@audiorecorder/pause, @audiorecorder/resume,\n## @audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction stop (recorder)\n\n  __recorder_stop__ (struct (recorder).recorder);\n\nendfunction\n\n\n## No tests possible for this function\n%!assert (1)\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/subsasgn.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{value} =} subsasgn (@var{recorder}, @var{idx}, @var{rhs})\n## Perform subscripted assignment on the audio recorder object @var{recorder}.\n##\n## Assign the value of @var{rhs} to the recorder property named by @var{idx}.\n## @seealso{@audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction recorder = subsasgn (recorder, idx, rhs)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (isempty (idx))\n    error (\"@audiorecorder/subsasgn: missing index\");\n  endif\n\n  if (strcmp (idx(1).type, \".\"))\n    field = idx.subs;\n    set (recorder, field, rhs);\n  else\n    error (\"@audiorecorder/subsasgn: invalid subscript type\");\n  endif\n\nendfunction\n\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 16, 2);\n%! recorder.Tag = \"mytag\";\n%! assert (get (recorder, \"Tag\"), \"mytag\");\n\n## Test input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 16, 2);\n%! fail (\"recorder(1).Tag = 5\", \"invalid subscript type\");\n%! fail (\"recorder{1}.Tag = 5\", \"invalid subscript type\");\n"
  },
  {
    "path": "scripts/audio/@audiorecorder/subsref.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{value} =} subsref (@var{recorder}, @var{idx})\n## Perform subscripted selection on the audio recorder object @var{recorder}.\n##\n## Return the recorder property value named by @var{idx}.\n## @seealso{@audiorecorder/audiorecorder}\n## @end deftypefn\n\nfunction value = subsref (recorder, idx)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (isempty (idx))\n    error (\"@audiorecorder/subsref: missing index\");\n  endif\n\n  if (strcmp (idx(1).type, \".\"))\n    field = idx.subs;\n    value = get (recorder, field);\n  else\n    error (\"@audiorecorder/subsref: invalid subscript type\");\n  endif\n\nendfunction\n\n\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 16, 2);\n%! set (recorder, \"Tag\", \"mytag\");\n%! assert (recorder.Tag, \"mytag\");\n\n## Test input validation\n%!testif HAVE_PORTAUDIO; audiodevinfo (1) > 0\n%! recorder = audiorecorder (44100, 16, 2);\n%! fail (\"recorder(1).Tag\", \"invalid subscript type\");\n%! fail (\"recorder{1}.Tag\", \"invalid subscript type\");\n"
  },
  {
    "path": "scripts/audio/lin2mu.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} lin2mu (@var{x})\n## @deftypefnx {} {@var{y} =} lin2mu (@var{x}, @var{n})\n## Convert audio data from linear to mu-law.\n##\n## Linear values use floating point values in the range -1 @leq{} @var{x}\n## @leq{} 1 if @var{n} is 0 (default), or @var{n}-bit signed integers if @var{n}\n## is 8 or 16.  Mu-law values are 8-bit unsigned integers in the range\n## 0 @leq{} @var{y} @leq{} 255.\n## @seealso{mu2lin}\n## @end deftypefn\n\nfunction y = lin2mu (x, n = 0)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Convert to floating point integers per Matlab.\n  x = double (x);\n\n  if (nargin == 2)\n    if (! isscalar (n) && ! isreal (n)\n        || (n != 0 && n != 8 && n != 16))\n      error (\"lin2mu: N must be either 0, 8, or 16\");\n    elseif (isempty (n))\n      n = 0;\n    endif\n  endif\n\n  ## Transform real and n-bit format to 16-bit.\n  if (n == 0)\n    ## [-1,1] -> [-32768, 32768]\n    x *= 32768;\n  elseif (n != 16)\n    x *= 256;\n  endif\n\n  ## Determine sign of x, set sign(0) = 1.\n  sig = sign (x) + (x == 0);\n\n  ## Take absolute value of x, but force it to be smaller than 32636;\n  ## add bias.\n  x = min (abs (x), 32635) + 132;\n\n  ## Find exponent and fraction of binary representation.\n  [f, e] = log2 (x);\n\n  y = 64 * sig - 16 * e - fix (32 * f) + 335;\n\nendfunction\n\n\n## Test functionality\n%!test\n%! x = -1:1;\n%! y = x';\n%! assert (lin2mu (x), (lin2mu (y))');\n%! assert (lin2mu (x), [0, 255, 128]);\n\n%!assert (lin2mu ([0, 1, NaN, inf, -inf], 8), [255, 231, NaN, 128, 0])\n%!assert (lin2mu ([]), [])\n%!assert (lin2mu (0), 255)\n%!assert (lin2mu (0, 0), 255)\n%!assert (lin2mu (0, 8), 255)\n%!assert (lin2mu (0, 16), 255)\n%!assert (lin2mu (2, 8), 219)\n%!assert (lin2mu (3, []), 128)\n%!assert (lin2mu (3, 16), 255)\n%!assert (lin2mu (repmat (-0.23, 1, 1000), 0), repmat (34, 1, 1000))\n%!assert (lin2mu (ones (2, 2), 0), repmat (128, 2))\n\n## Test input validation\n%!error <Invalid call> lin2mu ()\n%!error <N must be either 0, 8, or 16> lin2mu (1, 2)\n%!error <N must be either 0, 8, or 16> lin2mu (1, [1,2])\n%!error <N must be either 0, 8, or 16> lin2mu (1, ones (1, 2))\n%!error <invalid conversion> lin2mu ({2:5})\n"
  },
  {
    "path": "scripts/audio/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/@audioplayer \\\n  %reldir%/@audiorecorder\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/lin2mu.m \\\n  %reldir%/mu2lin.m \\\n  %reldir%/record.m \\\n  %reldir%/sound.m \\\n  %reldir%/soundsc.m\n\n%canon_reldir%_@audioplayer_FCN_FILES = \\\n  %reldir%/@audioplayer/__get_properties__.m \\\n  %reldir%/@audioplayer/audioplayer.m \\\n  %reldir%/@audioplayer/disp.m \\\n  %reldir%/@audioplayer/get.m \\\n  %reldir%/@audioplayer/isplaying.m \\\n  %reldir%/@audioplayer/pause.m  \\\n  %reldir%/@audioplayer/play.m \\\n  %reldir%/@audioplayer/playblocking.m \\\n  %reldir%/@audioplayer/resume.m \\\n  %reldir%/@audioplayer/set.m \\\n  %reldir%/@audioplayer/stop.m \\\n  %reldir%/@audioplayer/subsasgn.m \\\n  %reldir%/@audioplayer/subsref.m\n\n%canon_reldir%_@audiorecorder_FCN_FILES = \\\n  %reldir%/@audiorecorder/__get_properties__.m \\\n  %reldir%/@audiorecorder/audiorecorder.m \\\n  %reldir%/@audiorecorder/disp.m \\\n  %reldir%/@audiorecorder/get.m \\\n  %reldir%/@audiorecorder/getaudiodata.m \\\n  %reldir%/@audiorecorder/getplayer.m \\\n  %reldir%/@audiorecorder/isrecording.m \\\n  %reldir%/@audiorecorder/pause.m \\\n  %reldir%/@audiorecorder/play.m \\\n  %reldir%/@audiorecorder/record.m \\\n  %reldir%/@audiorecorder/recordblocking.m \\\n  %reldir%/@audiorecorder/resume.m \\\n  %reldir%/@audiorecorder/set.m \\\n  %reldir%/@audiorecorder/stop.m \\\n  %reldir%/@audiorecorder/subsasgn.m \\\n  %reldir%/@audiorecorder/subsref.m\n\n%canon_reldir%dir = $(fcnfiledir)/audio\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_@audioplayerdir = $(fcnfiledir)/audio/@audioplayer\n\n%canon_reldir%_@audioplayer_DATA = $(%canon_reldir%_@audioplayer_FCN_FILES)\n\n%canon_reldir%_@audiorecorderdir = $(fcnfiledir)/audio/@audiorecorder\n\n%canon_reldir%_@audiorecorder_DATA = $(%canon_reldir%_@audiorecorder_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_@audioplayer_FCN_FILES) \\\n  $(%canon_reldir%_@audiorecorder_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/audio/mu2lin.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} mu2lin (@var{x})\n## @deftypefnx {} {@var{y} =} mu2lin (@var{x}, @var{n})\n## Convert audio data from mu-law to linear.\n##\n## Mu-law values are 8-bit unsigned integers in the range 0 @leq{} @var{y}\n## @leq{} 255.  Linear values use floating point values in the range\n## -@var{linmax} @leq{} @var{x} @var{linmax} (where\n## @code{@var{linmax} = 32124/32768 =~ 0.98}) when @var{n} is zero (default).\n## If @var{n} is 8 or 16 then @var{n}-bit signed integers are used instead.\n##\n## Programming Note: @code{mu2lin} maps maximum mu-law inputs to values\n## slightly below the maximum ([-0.98, +0.98]) representable with a linear\n## scale.  Because of this, @code{mu2lin (lin2mu (@var{x}))} might not\n## reproduce the original input.\n## @seealso{lin2mu}\n## @end deftypefn\n\nfunction y = mu2lin (x, n = 0)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 2)\n    if (! isscalar (n) && ! isreal (n)\n        || (n != 0 && n != 8 && n != 16))\n      error (\"lin2mu: N must be either 0, 8, or 16\");\n    elseif (isempty (n))\n      n = 0;\n    endif\n  endif\n\n  ulaw = [32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, ...\n          23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, ...\n          15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, ...\n          11900, 11388, 10876, 10364,  9852,  9340,  8828,  8316, ...\n           7932,  7676,  7420,  7164,  6908,  6652,  6396,  6140, ...\n           5884,  5628,  5372,  5116,  4860,  4604,  4348,  4092, ...\n           3900,  3772,  3644,  3516,  3388,  3260,  3132,  3004, ...\n           2876,  2748,  2620,  2492,  2364,  2236,  2108,  1980, ...\n           1884,  1820,  1756,  1692,  1628,  1564,  1500,  1436, ...\n           1372,  1308,  1244,  1180,  1116,  1052,   988,   924, ...\n            876,   844,   812,   780,   748,   716,   684,   652, ...\n            620,   588,   556,   524,   492,   460,   428,   396, ...\n            372,   356,   340,   324,   308,   292,   276,   260, ...\n            244,   228,   212,   196,   180,   164,   148,   132, ...\n            120,   112,   104,    96,    88,    80,    72,    64, ...\n             56,    48,    40,    32,    24,    16,     8,     0 ];\n\n  ulaw = [ -ulaw, ulaw ];\n\n  ## Set the shape of y to that of x overwrites the contents of y with\n  ## ulaw of x.\n  y = x;\n  y(:) = ulaw(x + 1);\n\n  ## Convert to real or 8-bit.\n  if (n == 0)\n    ## [ -32768, 32767 ] -> [ -1, 1)\n    y /= 32768;\n  elseif (n == 8)\n    ld = max (abs (y(:)));\n    if (ld < 16384 && ld > 0)\n      sc = 64 / ld;\n    else\n      sc = 1 / 256;\n    endif\n    y = fix (y * sc);\n  endif\n\nendfunction\n\n\n## Test functionality\n%!shared linmax\n%! linmax = 32124 / 32768;\n\n%!test\n%! x = [0, 128, 255];\n%! y = x';\n%! assert (mu2lin (x), (mu2lin (y))');\n%! assert (mu2lin (x), [-linmax, +linmax, 0]);\n\n%!assert (mu2lin ([]), [])\n%!assert (mu2lin (255), 0)\n%!assert (mu2lin (255, 0), 0)\n%!assert (mu2lin (255, 8), 0)\n%!assert (mu2lin (255, 16), 0)\n%!assert (mu2lin (128, []), linmax)\n%!assert (mu2lin (128, 8), 125)\n%!assert (mu2lin (128, 16), 32124)\n%!assert (mu2lin (zeros (1, 1000), 0), repmat (-linmax, 1, 1000))\n%!assert (mu2lin (255*ones (2, 2), 0), zeros (2, 2))\n\n## Test input validation\n%!error <Invalid call> mu2lin ()\n%!error <N must be either 0, 8, or 16> mu2lin (1, 2)\n%!error <N must be either 0, 8, or 16> mu2lin (1, [1,2])\n%!error <N must be either 0, 8, or 16> mu2lin (1, ones (1, 2))\n%!error mu2lin ({2:5})\n"
  },
  {
    "path": "scripts/audio/record.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{data} =} record (@var{sec})\n## @deftypefnx {} {@var{data} =} record (@var{sec}, @var{fs})\n## Record @var{sec} seconds of audio from the system's default audio input at\n## a sampling rate of 8000 samples per second.\n##\n## If the optional argument @var{fs} is given, it specifies the sampling rate\n## for recording.\n##\n## For more control over audio recording, use the @code{audiorecorder} class.\n## @seealso{@audiorecorder/audiorecorder, sound, soundsc}\n## @end deftypefn\n\nfunction data = record (sec, fs = 8000)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (sec) && sec >= 0))\n    error (\"record: recording duration SEC must be a non-negative number\");\n  endif\n\n  if (! (isscalar (fs) && fs > 0))\n    error (\"record: sample rate FS must be a positive number\");\n  endif\n\n  data = [];\n\n  if (sec > 0)\n    rec = audiorecorder (fs, 16, 1);\n\n    recordblocking (rec, sec);\n\n    data = getaudiodata (rec);\n  endif\n\nendfunction\n\n\n## Tests of record must not actually record anything.\n%!assert (isempty (record (0)))\n\n## Test input validation\n%!error <SEC must be a non-negative number> record (ones (2,2))\n%!error <SEC must be a non-negative number> record (-1)\n%!error <FS must be a positive number> record (1, ones (2,2))\n%!error <FS must be a positive number> record (1, -1)\n"
  },
  {
    "path": "scripts/audio/sound.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} sound (@var{y})\n## @deftypefnx {} {} sound (@var{y}, @var{fs})\n## @deftypefnx {} {} sound (@var{y}, @var{fs}, @var{nbits})\n## Play audio data @var{y} at sample rate @var{fs} to the default audio\n## device.\n##\n## The audio signal @var{y} can be a vector or a two-column array representing\n## mono or stereo audio, respectively.\n##\n## If @var{fs} is not given, a default sample rate of 8000 samples per second\n## is used.\n##\n## The optional argument @var{nbits} specifies the bit depth to play to the\n## audio device and defaults to 8 bits.\n##\n## For more control over audio playback, use the @code{audioplayer} class.\n## @seealso{soundsc, @audioplayer/audioplayer, record}\n## @end deftypefn\n\nfunction sound (y, fs, nbits)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin < 2 || isempty (fs))\n    fs = 8000;\n  elseif (! (isscalar (fs) && fs > 0))\n    error (\"sound: sample rate FS must be a positive number\");\n  endif\n\n  if (nargin < 3 || isempty (nbits))\n    nbits = 8;\n  elseif (! (isscalar (nbits) && (nbits == 8 || nbits == 16 || nbits == 24)))\n    error (\"sound: bit depth NBITS must be 8, 16, or 24\");\n  endif\n\n  play = audioplayer (y, fs, nbits);\n\n  playblocking (play);\n\nendfunction\n\n\n## Tests of sound must not actually play anything.\n\n## Test input validation\n%!error <Invalid call> sound ()\n%!error <FS must be a positive number> sound (1, ones (2,2))\n%!error <FS must be a positive number> sound (1, -1)\n%!error <NBITS must be 8, 16, or 24> sound (1, [], 2)\n"
  },
  {
    "path": "scripts/audio/soundsc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} soundsc (@var{y})\n## @deftypefnx {} {} soundsc (@var{y}, @var{fs})\n## @deftypefnx {} {} soundsc (@var{y}, @var{fs}, @var{nbits})\n## @deftypefnx {} {} soundsc (@dots{}, [@var{ymin}, @var{ymax}])\n## Scale the audio data @var{y} and play it at sample rate @var{fs} to the\n## default audio device.\n##\n## The audio signal @var{y} can be a vector or a two-column array representing\n## mono or stereo audio, respectively.\n##\n## If @var{fs} is not given, a default sample rate of 8000 samples per second\n## is used.\n##\n## The optional argument @var{nbits} specifies the bit depth to play to the\n## audio device and defaults to 8 bits.\n##\n## By default, @var{y} is automatically normalized to the range [-1, 1].  If\n## the range [@var{ymin}, @var{ymax}] is given, then elements of @var{y}\n## that fall within the range @var{ymin} @leq{} @var{y} @leq{} @var{ymax}\n## are scaled to the range [-1, 1] instead.\n##\n## For more control over audio playback, use the @code{audioplayer} class.\n## @seealso{sound, @audioplayer/audioplayer, record}\n## @end deftypefn\n\nfunction soundsc (y, fs, nbits, yrange = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin < 2 || isempty (fs))\n    fs = 8000;\n  elseif (nargin == 2 && numel (fs) > 1)\n    yrange = fs;\n    fs = 8000;\n  elseif (! (isscalar (fs) && fs > 0))\n    error (\"soundsc: sample rate FS must be a positive number\");\n  endif\n\n  if (nargin < 3 || isempty (nbits))\n    nbits = 8;\n  elseif (nargin == 3 && numel (nbits) > 1)\n    yrange = nbits;\n    nbits = 8;\n  elseif (! (isscalar (nbits) && (nbits == 8 || nbits == 16 || nbits == 24)))\n    error (\"soundsc: bit depth NBITS must be 8, 16, or 24\");\n  endif\n\n  if (isreal (yrange) && (numel (yrange) == 2) && (yrange(1) <= yrange(2)))\n    ymin = yrange(1);\n    ymax = yrange(2);\n  elseif (isempty (yrange))\n    ymin = min (y(:));\n    ymax = max (y(:));\n  else\n    error (\"soundsc: audio range must be a 2-element [YMIN, YMAX] vector\");\n  endif\n\n  ymin = double (ymin);\n  ymax = double (ymax);\n  ymedian = (ymax + ymin) / 2;\n  yscale = 2 / (ymax - ymin);\n\n  y = (double (y) - ymedian) .* yscale;\n\n  play = audioplayer (y, fs, nbits);\n\n  playblocking (play);\n\nendfunction\n\n\n## Tests of soundsc must not actually play anything.\n## Test input validation\n%!error <Invalid call> soundsc ()\n%!error <FS must be a positive number> soundsc (1, ones (2,2), 8)\n%!error <FS must be a positive number> soundsc (1, -1)\n%!error <NBITS must be 8, 16, or 24> soundsc (1, [], 2)\n%!error <range must be a 2-element .* vector> soundsc (1, [2 1])\n%!error <range must be a 2-element .* vector> soundsc (1, [1 2 3])\n%!error <range must be a 2-element .* vector> soundsc (1, 8000, [2 1])\n%!error <range must be a 2-element .* vector> soundsc (1, 8000, [1 2 3])\n%!error <range must be a 2-element .* vector> soundsc (1, 8000, 8, [2 1])\n%!error <range must be a 2-element .* vector> soundsc (1, 8000, 8, [1 2 3])\n"
  },
  {
    "path": "scripts/deprecated/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/deprecated/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config\n\n%canon_reldir%dir = $(fcnfiledir)/deprecated\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/elfun/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/elfun/acosd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} acosd (@var{x})\n## Compute the inverse cosine in degrees for each element of @var{x}.\n## @seealso{cosd, acos}\n## @end deftypefn\n\nfunction y = acosd (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = acos (x) .* 180 ./ pi;\n\nendfunction\n\n\n%!assert (acosd (0:0.1:1), 180/pi * acos (0:0.1:1), -10*eps)\n\n%!error <Invalid call> acosd ()\n"
  },
  {
    "path": "scripts/elfun/acot.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} acot (@var{x})\n## Compute the inverse cotangent in radians for each element of @var{x}.\n## @seealso{cot, acotd}\n## @end deftypefn\n\nfunction y = acot (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = atan (1 ./ x);\n\nendfunction\n\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! x = [rt3, 1, rt3/3, 0, -rt3/3, -1, -rt3];\n%! v = [pi/6, pi/4, pi/3, pi/2, -pi/3, -pi/4, -pi/6];\n%! assert (acot (x), v, sqrt (eps));\n\n%!error <Invalid call> acot ()\n"
  },
  {
    "path": "scripts/elfun/acotd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} acotd (@var{x})\n## Compute the inverse cotangent in degrees for each element of @var{x}.\n## @seealso{cotd, acot}\n## @end deftypefn\n\nfunction y = acotd (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = atand (1 ./ x);\n\nendfunction\n\n\n%!assert (acotd (0:10:90), 180/pi * acot (0:10:90), -10*eps)\n\n%!error <Invalid call> acotd ()\n"
  },
  {
    "path": "scripts/elfun/acoth.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} acoth (@var{x})\n## Compute the inverse hyperbolic cotangent of each element of @var{x}.\n## @seealso{coth}\n## @end deftypefn\n\nfunction y = acoth (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = atanh (1 ./ x);\n\nendfunction\n\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! v = -i*[pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6];\n%! x = i*[rt3, 1, rt3/3, -rt3/3, -1, -rt3];\n%! assert (acoth (x), v, sqrt (eps));\n\n%!error <Invalid call> acoth ()\n"
  },
  {
    "path": "scripts/elfun/acsc.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} acsc (@var{x})\n## Compute the inverse cosecant in radians for each element of @var{x}.\n## @seealso{csc, acscd}\n## @end deftypefn\n\nfunction y = acsc (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = asin (1 ./ x);\n\nendfunction\n\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! v = [pi/6, pi/4, pi/3, pi/2, pi/3, pi/4, pi/6];\n%! x = [2, rt2, 2*rt3/3, 1, 2*rt3/3, rt2, 2];\n%! assert (acsc (x), v, sqrt (eps));\n\n%!error <Invalid call> acsc ()\n"
  },
  {
    "path": "scripts/elfun/acscd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} acscd (@var{x})\n## Compute the inverse cosecant in degrees for each element of @var{x}.\n## @seealso{cscd, acsc}\n## @end deftypefn\n\nfunction y = acscd (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = acsc (x) .* 180 ./ pi;\n\nendfunction\n\n\n%!assert (acscd (0:10:90), 180/pi * acsc (0:10:90), -10*eps)\n\n%!error <Invalid call> acscd ()\n"
  },
  {
    "path": "scripts/elfun/acsch.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} acsch (@var{x})\n## Compute the inverse hyperbolic cosecant of each element of @var{x}.\n## @seealso{csch}\n## @end deftypefn\n\nfunction y = acsch (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = asinh (1 ./ x);\n\nendfunction\n\n\n%!test\n%! v = [pi/2*i, -pi/2*i];\n%! x = [-i, i];\n%! assert (acsch (x), v, sqrt (eps));\n\n%!error <Invalid call> acsch ()\n"
  },
  {
    "path": "scripts/elfun/asec.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} asec (@var{x})\n## Compute the inverse secant in radians for each element of @var{x}.\n## @seealso{sec, asecd}\n## @end deftypefn\n\nfunction y = asec (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = acos (1 ./ x);\n\nendfunction\n\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! v = [0, pi/6, pi/4, pi/3, 2*pi/3, 3*pi/4, 5*pi/6, pi];\n%! x = [1, 2*rt3/3, rt2, 2, -2, -rt2, -2*rt3/3, -1];\n%! assert (asec (x), v, sqrt (eps));\n\n%!error <Invalid call> asec ()\n"
  },
  {
    "path": "scripts/elfun/asecd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} asecd (@var{x})\n## Compute the inverse secant in degrees for each element of @var{x}.\n## @seealso{secd, asec}\n## @end deftypefn\n\nfunction y = asecd (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = asec (x) .* 180 ./ pi;\n\nendfunction\n\n\n%!assert (asecd (0:10:90), 180/pi * asec (0:10:90), -10*eps)\n\n%!error <Invalid call> asecd ()\n"
  },
  {
    "path": "scripts/elfun/asech.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} asech (@var{x})\n## Compute the inverse hyperbolic secant of each element of @var{x}.\n## @seealso{sech}\n## @end deftypefn\n\nfunction y = asech (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = acosh (1 ./ x);\n\nendfunction\n\n\n%!test\n%! v = [0, pi*i];\n%! x = [1, -1];\n%! assert (asech (x), v, sqrt (eps));\n\n%!error <Invalid call> asech ()\n"
  },
  {
    "path": "scripts/elfun/asind.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} asind (@var{x})\n## Compute the inverse sine in degrees for each element of @var{x}.\n## @seealso{sind, asin}\n## @end deftypefn\n\nfunction y = asind (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = asin (x) .* 180 ./ pi;\n\nendfunction\n\n\n%!assert (asind (0:0.1:1), 180/pi * asin (0:0.1:1), -10*eps)\n\n%!error <Invalid call> asind ()\n"
  },
  {
    "path": "scripts/elfun/atan2d.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{d} =} atan2d (@var{y}, @var{x})\n## Compute atan (@var{y} / @var{x}) in degrees for corresponding elements\n## from @var{y} and @var{x}.\n## @seealso{tand, atan2}\n## @end deftypefn\n\nfunction d = atan2d (y, x)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  d = 180 ./ pi .* atan2 (y, x);\n\nendfunction\n\n\n%!assert (atan2d (-1:.1:1, 1:-.1:-1),\n%!        180/pi * atan2 (-1:.1:1, 1:-.1:-1), -10*eps)\n\n%!error <Invalid call> atan2d ()\n%!error <Invalid call> atan2d (1)\n"
  },
  {
    "path": "scripts/elfun/atand.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} atand (@var{x})\n## Compute the inverse tangent in degrees for each element of @var{x}.\n## @seealso{tand, atan}\n## @end deftypefn\n\nfunction y = atand (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 180 ./ pi .* atan (x);\n\nendfunction\n\n\n%!assert (atand (0:10:90), 180/pi * atan (0:10:90), -10*eps)\n\n%!error <Invalid call> atand ()\n"
  },
  {
    "path": "scripts/elfun/cosd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} cosd (@var{x})\n## Compute the cosine for each element of @var{x} in degrees.\n##\n## The function is more accurate than @code{cos} for large values of @var{x}\n## and for multiples of 90 degrees (@code{@var{x} = 90 + 180*n} with n an\n## integer) where @code{cosd} returns 0 rather than a small value on the order\n## of eps.\n## @seealso{acosd, cos}\n## @end deftypefn\n\nfunction y = cosd (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x))\n    error (\"cosd: X must be numeric\");\n  endif\n\n  ## Advance phase by 90 degrees to transform sin to cos and use sind().\n  y = sind (x + 90);\n\nendfunction\n\n\n%!assert (cosd (10:20:360), cos ([10:20:360] * pi/180), 5*eps)\n%!assert (cosd ([-270, -90, 90, 270]) == 0)\n%!assert (cosd ([-360, -180, 0, 180, 360]), [1, -1, 1, -1, 1])\n%!assert (cosd ([-Inf, NaN, +Inf, 0]), [NaN, NaN, NaN, 1])\n%!assert (cosd (+23) == cosd (-23))\n%!assert (cosd (1e6), 0.17364817766693033, 5*eps)\n%!assert (cosd (90 + 180i), -i*sinh (pi))\n%!assert (cosd (1e6 + 180i), 2.01292156189451577 + 11.3732880565446539i, -eps)\n\n%!error <Invalid call> cosd ()\n%!error <X must be numeric> cosd (\"abc\")\n"
  },
  {
    "path": "scripts/elfun/cospi.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} cospi (@var{x})\n## Compute cosine (@var{x} * pi) for each element of @var{x} accurately.\n##\n## The ordinary @code{cos} function uses IEEE@tie{}754 floating point numbers\n## and may produce results that are very close (within a few eps) of the\n## correct value, but which are not exact.  The @code{cospi} function is more\n## accurate and returns 0 exactly for half-integer values of @var{x} (e.g.,\n## @dots{}, -3/2, -1/2, 1/2, 3/2, @dots{}), and +1/-1 for integer values.\n##\n## Example @*\n## comparison of @code{cos} and @code{cospi} for half-integer values of @var{x}\n##\n## @example\n## @group\n## cos ([-3/2, -1/2, 1/2, 3/2] * pi)\n## @xresult{}\n##      -1.8370e-16   6.1232e-17   6.1232e-17  -1.8370e-16\n##\n## cospi ([-3/2, -1/2, 1/2, 3/2])\n## @xresult{}\n##        0   0   0   0\n## @end group\n## @end example\n##\n## @seealso{sinpi, cos}\n## @end deftypefn\n\nfunction y = cospi (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Advance phase by pi/2 so that algorithm from sinpi can be used.\n  ## Wrap integer multiples so that new domain is [-1, 1).\n  x = mod (x - 0.5, 2) - 1;\n\n  ## Integer multiples of pi must be exactly zero.\n  x(x == -1) = 0;\n\n  y = sin (x * pi);\n\nendfunction\n\n\n%!assert (cospi ([-3/2, -1/2, 1/2, 3/2]) == 0)\n%!assert (cospi ([-2, -1, 0, 1, 2]), [1, -1, 1, -1, 1])\n%!assert (cospi (100 + [0.1:0.1:0.9]), cos ([0.1:0.1:0.9]*pi), 2*eps (100))\n\n%!error <Invalid call> cospi ()\n"
  },
  {
    "path": "scripts/elfun/cot.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} cot (@var{x})\n## Compute the cotangent for each element of @var{x} in radians.\n## @seealso{acot, cotd, coth}\n## @end deftypefn\n\nfunction y = cot (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 1 ./ tan (x);\n\nendfunction\n\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! x = [pi/6, pi/4, pi/3, pi/2, 2*pi/3, 3*pi/4, 5*pi/6];\n%! v = [rt3, 1, rt3/3, 0, -rt3/3, -1, -rt3];\n%! assert (cot (x), v, sqrt (eps));\n\n%!error <Invalid call> cot ()\n"
  },
  {
    "path": "scripts/elfun/cotd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} cotd (@var{x})\n## Compute the cotangent for each element of @var{x} in degrees.\n## @seealso{acotd, cot}\n## @end deftypefn\n\nfunction y = cotd (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 1 ./ tand (x);\n\nendfunction\n\n\n%!assert (cotd (10:10:80), cot (pi*[10:10:80]/180), -10*eps)\n%!assert (cotd ([0, 180, 360]) == Inf)\n%!assert (cotd ([90, 270]) == 0)\n\n%!error <Invalid call> cotd ()\n"
  },
  {
    "path": "scripts/elfun/coth.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} coth (@var{x})\n## Compute the hyperbolic cotangent of each element of @var{x}.\n## @seealso{acoth}\n## @end deftypefn\n\nfunction y = coth (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 1 ./ tanh (x);\n\nendfunction\n\n\n%!test\n%! x = [pi/2*i, 3*pi/2*i];\n%! v = [0, 0];\n%! assert (coth (x), v, sqrt (eps));\n\n%!error <Invalid call> coth ()\n"
  },
  {
    "path": "scripts/elfun/csc.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} csc (@var{x})\n## Compute the cosecant for each element of @var{x} in radians.\n## @seealso{acsc, cscd, csch}\n## @end deftypefn\n\nfunction y = csc (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 1 ./ sin (x);\n\nendfunction\n\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! x = [pi/6, pi/4, pi/3, pi/2, 2*pi/3, 3*pi/4, 5*pi/6];\n%! v = [2, rt2, 2*rt3/3, 1, 2*rt3/3, rt2, 2];\n%! assert (csc (x), v, sqrt (eps));\n\n%!error <Invalid call> csc ()\n"
  },
  {
    "path": "scripts/elfun/cscd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} cscd (@var{x})\n## Compute the cosecant for each element of @var{x} in degrees.\n## @seealso{acscd, csc}\n## @end deftypefn\n\nfunction y = cscd (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 1 ./ sind (x);\n\nendfunction\n\n\n%!assert (cscd (10:10:90), csc (pi*[10:10:90]/180), -10*eps)\n%!assert (cscd ([0, 180, 360]) == Inf)\n%!assert (cscd ([90, 270]) != Inf)\n\n%!error <Invalid call> cscd ()\n"
  },
  {
    "path": "scripts/elfun/csch.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} csch (@var{x})\n## Compute the hyperbolic cosecant of each element of @var{x}.\n## @seealso{acsch}\n## @end deftypefn\n\nfunction y = csch (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 1 ./ sinh (x);\n\nendfunction\n\n\n%!test\n%! x = [pi/2*i, 3*pi/2*i];\n%! v = [-i, i];\n%! assert (csch (x), v, sqrt (eps));\n\n%!error <Invalid call> csch ()\n"
  },
  {
    "path": "scripts/elfun/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/acosd.m \\\n  %reldir%/acot.m \\\n  %reldir%/acotd.m \\\n  %reldir%/acoth.m \\\n  %reldir%/acsc.m \\\n  %reldir%/acscd.m \\\n  %reldir%/acsch.m \\\n  %reldir%/asec.m \\\n  %reldir%/asecd.m \\\n  %reldir%/asech.m \\\n  %reldir%/asind.m \\\n  %reldir%/atan2d.m \\\n  %reldir%/atand.m \\\n  %reldir%/cosd.m \\\n  %reldir%/cospi.m \\\n  %reldir%/cot.m \\\n  %reldir%/cotd.m \\\n  %reldir%/coth.m \\\n  %reldir%/csc.m \\\n  %reldir%/cscd.m \\\n  %reldir%/csch.m \\\n  %reldir%/sec.m \\\n  %reldir%/secd.m \\\n  %reldir%/sech.m \\\n  %reldir%/sind.m \\\n  %reldir%/sinpi.m \\\n  %reldir%/tand.m\n\n%canon_reldir%dir = $(fcnfiledir)/elfun\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/elfun/sec.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} sec (@var{x})\n## Compute the secant for each element of @var{x} in radians.\n## @seealso{asec, secd, sech}\n## @end deftypefn\n\nfunction y = sec (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 1 ./ cos (x);\n\nendfunction\n\n\n%!test\n%! rt2 = sqrt (2);\n%! rt3 = sqrt (3);\n%! x = [0, pi/6, pi/4, pi/3, 2*pi/3, 3*pi/4, 5*pi/6, pi];\n%! v = [1, 2*rt3/3, rt2, 2, -2, -rt2, -2*rt3/3, -1];\n%! assert (sec (x), v, sqrt (eps));\n\n%!error <Invalid call> sec ()\n"
  },
  {
    "path": "scripts/elfun/secd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} secd (@var{x})\n## Compute the secant for each element of @var{x} in degrees.\n## @seealso{asecd, sec}\n## @end deftypefn\n\nfunction y = secd (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 1 ./ cosd (x);\n\nendfunction\n\n\n%!assert (secd (0:10:80), sec (pi*[0:10:80]/180), -10*eps)\n%!assert (secd ([0, 180, 360]) != Inf)\n%!assert (secd ([90, 270]) == Inf)\n\n%!error <Invalid call> secd ()\n"
  },
  {
    "path": "scripts/elfun/sech.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} sech (@var{x})\n## Compute the hyperbolic secant of each element of @var{x}.\n## @seealso{asech}\n## @end deftypefn\n\nfunction y = sech (x)\n\nif (nargin < 1)\n    print_usage ();\n  endif\n\n  y = 1 ./ cosh (x);\n\nendfunction\n\n\n%!test\n%! x = [0, pi*i];\n%! v = [1, -1];\n%! assert (sech (x), v, sqrt (eps));\n\n%!error <Invalid call> sech ()\n"
  },
  {
    "path": "scripts/elfun/sind.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} sind (@var{x})\n## Compute the sine for each element of @var{x} in degrees.\n##\n## The function is more accurate than @code{sin} for large values of @var{x}\n## and for multiples of 180 degrees (@code{@var{x}/180} is an integer) where\n## @code{sind} returns 0 rather than a small value on the order of eps.\n## @seealso{asind, sin}\n## @end deftypefn\n\nfunction y = sind (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x))\n    error (\"sind: X must be numeric\");\n  endif\n\n  x_iscomplex = iscomplex (x);\n  if (x_iscomplex)\n    xi = imag (x);\n  endif\n  x = real (x);\n\n  ## Wrap multiples so that new domain is [-180, 180)\n  x = mod (x-180, 360) - 180;\n\n  if (x_iscomplex)\n    y = sin (complex (x, xi) / 180 * pi);\n    ## Integer multiples of pi must be exactly zero\n    y(x == -180) = complex (0, imag (y(x == -180)));\n  else\n    y = sin (x / 180 * pi);\n    ## Integer multiples of pi must be exactly zero\n    y(x == -180) = 0;\n  endif\n\nendfunction\n\n\n%!assert (sind (10:20:360), sin ([10:20:360] * pi/180), 5*eps)\n%!assert (sind ([-360, -180, 0, 180, 360]) == 0)\n%!assert (sind ([-270, -90, 90, 270]), [1, -1, 1, -1])\n%!assert (sind ([-Inf, NaN, +Inf, 0]), [NaN, NaN, NaN, 0])\n%!assert (sind (+23) == -sind (-23))\n%!assert (sind (1e6), -0.984807753012208, 5*eps)\n%!assert (sind (180 + 180i), -i*sinh (pi))\n%!assert (sind (1e6 + 180i), -11.415845458288851 + 2.0054175437381652i, 5*eps)\n\n%!error <Invalid call> sind ()\n%!error <X must be numeric> sind (\"abc\")\n"
  },
  {
    "path": "scripts/elfun/sinpi.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} sinpi (@var{x})\n## Compute sine (@var{x} * pi) for each element of @var{x} accurately.\n##\n## The ordinary @code{sin} function uses IEEE@tie{}754 floating point numbers\n## and may produce results that are very close (within a few eps) of the\n## correct value, but which are not exact.  The @code{sinpi} function is more\n## accurate and returns 0 exactly for integer values of @var{x} and +1/-1 for\n## half-integer values (e.g., @dots{}, -3/2, -1/2, 1/2, 3/2, @dots{}).\n##\n## Example @*\n## comparison of @code{sin} and @code{sinpi} for integer values of @var{x}\n##\n## @example\n## @group\n## sin ([0, 1, 2, 3] * pi)\n## @xresult{}\n##      0   1.2246e-16  -2.4493e-16   3.6739e-16\n##\n## sinpi ([0, 1, 2, 3])\n## @xresult{}\n##        0   0   0   0\n## @end group\n## @end example\n##\n## @seealso{cospi, sin}\n## @end deftypefn\n\nfunction y = sinpi (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Wrap integer multiples so that new domain is [-1, 1)\n  x = mod (x-1, 2) - 1;\n\n  ## Integer multiples of pi must be exactly zero\n  x(x == -1) = 0;\n\n  y = sin (x * pi);\n\nendfunction\n\n\n%!assert (sinpi ([-1, -2, 0, 1, 2]) == 0)\n%!assert (sinpi ([-3/2, -1/2, 1/2, 3/2]), [1, -1, 1, -1])\n%!assert (sinpi (100 + [0.1:0.1:0.9]), sin ([0.1:0.1:0.9]*pi), 2*eps (100))\n\n%!error <Invalid call> sinpi ()\n"
  },
  {
    "path": "scripts/elfun/tand.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} tand (@var{x})\n## Compute the tangent for each element of @var{x} in degrees.\n##\n## Returns zero for elements where @code{@var{x}/180} is an integer and\n## @code{Inf} for elements where @code{(@var{x}-90)/180} is an integer.\n## @seealso{atand, tan}\n## @end deftypefn\n\nfunction y = tand (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  I0 = x / 180;\n  I90 = (x-90) / 180;\n  y = tan (I0 .* pi);\n  y(I0 == fix (I0) & isfinite (I0)) = 0;\n  y(I90 == fix (I90) & isfinite (I90)) = Inf;\n\nendfunction\n\n\n%!assert (tand (10:10:80), tan (pi*[10:10:80]/180), -10*eps)\n%!assert (tand ([0, 180, 360]) == 0)\n%!assert (tand ([90, 270]) == Inf)\n\n%!error <Invalid call> tand ()\n"
  },
  {
    "path": "scripts/general/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/general/accumarray.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{A} =} accumarray (@var{subs}, @var{vals})\n## @deftypefnx {} {@var{A} =} accumarray (@var{subs}, @var{vals}, @var{sz})\n## @deftypefnx {} {@var{A} =} accumarray (@var{subs}, @var{vals}, @var{sz}, @var{fcn})\n## @deftypefnx {} {@var{A} =} accumarray (@var{subs}, @var{vals}, @var{sz}, @var{fcn}, @var{fillval})\n## @deftypefnx {} {@var{A} =} accumarray (@var{subs}, @var{vals}, @var{sz}, @var{fcn}, @var{fillval}, @var{issparse})\n##\n## Create an array by accumulating the elements of a vector into the\n## positions defined by their subscripts.\n##\n## The subscripts are defined by the rows of the matrix @var{subs} and the\n## values by @var{vals}.  Each row of @var{subs} corresponds to one of the\n## values in @var{vals}.  If @var{vals} is a scalar, it will be used for each\n## of the row of @var{subs}.  If @var{subs} is a cell array of vectors, all\n## vectors must be of the same length, and the subscripts in the @var{k}th\n## vector must correspond to the @var{k}th dimension of the result.\n##\n## The size of the matrix will be determined by the subscripts\n## themselves.  However, if @var{sz} is defined it determines the matrix\n## size.  The length of @var{sz} must correspond to the number of columns\n## in @var{subs}.  An exception is if @var{subs} has only one column, in\n## which case @var{sz} may be the dimensions of a vector and the\n## subscripts of @var{subs} are taken as the indices into it.\n##\n## The default action of @code{accumarray} is to sum the elements with\n## the same subscripts.  This behavior can be modified by defining the\n## @var{fcn} function.  This should be a function or function handle\n## that accepts a column vector and returns a scalar.  The result of the\n## function should not depend on the order of the subscripts.\n##\n## The elements of the returned array that have no subscripts associated\n## with them are set to zero.  Defining @var{fillval} to some other value\n## allows these values to be defined.  This behavior changes, however,\n## for certain values of @var{fcn}.  If @var{fcn} is @code{@@min}\n## (respectively, @code{@@max}) then the result will be filled with the\n## minimum (respectively, maximum) integer if @var{vals} is of integral\n## type, logical false (respectively, logical true) if @var{vals} is of\n## logical type, zero if @var{fillval} is zero and all values are\n## non-positive (respectively, non-negative), and NaN otherwise.\n##\n## By default @code{accumarray} returns a full matrix.  If\n## @var{issparse} is logically true, then a sparse matrix is returned\n## instead.\n##\n## The following @code{accumarray} example constructs a frequency table\n## that in the first column counts how many occurrences each number in\n## the second column has, taken from the vector @var{x}.  Note the usage\n## of @code{unique}  for assigning to all repeated elements of @var{x}\n## the same index (@pxref{XREFunique,,@code{unique}}).\n##\n## @example\n## @group\n## @var{x} = [91, 92, 90, 92, 90, 89, 91, 89, 90, 100, 100, 100];\n## [@var{u}, ~, @var{j}] = unique (@var{x});\n## [accumarray(@var{j}', 1), @var{u}']\n##   @xresult{}  2    89\n##       3    90\n##       2    91\n##       2    92\n##       3   100\n## @end group\n## @end example\n##\n## Another example, where the result is a multi-dimensional 3-D array and\n## the default value (zero) appears in the output:\n##\n## @example\n## @group\n## accumarray ([1, 1, 1;\n##              2, 1, 2;\n##              2, 3, 2;\n##              2, 1, 2;\n##              2, 3, 2], 101:105)\n## @xresult{} ans(:,:,1) = [101, 0, 0; 0, 0, 0]\n## @xresult{} ans(:,:,2) = [0, 0, 0; 206, 0, 208]\n## @end group\n## @end example\n##\n## The sparse option can be used as an alternative to the @code{sparse}\n## constructor (@pxref{XREFsparse,,@code{sparse}}).  Thus\n##\n## @example\n## sparse (@var{i}, @var{j}, @var{sv})\n## @end example\n##\n## @noindent\n## can be written with @code{accumarray} as\n##\n## @example\n## accumarray ([@var{i}, @var{j}], @var{sv}', [], [], 0, true)\n## @end example\n##\n## @noindent\n## For repeated indices, @code{sparse} adds the corresponding value.  To\n## take the minimum instead, use @code{min} as an accumulator function:\n##\n## @example\n## accumarray ([@var{i}, @var{j}], @var{sv}', [], @@min, 0, true)\n## @end example\n##\n## The complexity of accumarray in general for the non-sparse case is\n## generally O(M+N), where N is the number of subscripts and M is the\n## maximum subscript (linearized in multi-dimensional case).  If\n## @var{fcn} is one of @code{@@sum} (default), @code{@@max},\n## @code{@@min} or @code{@@(x) @{x@}}, an optimized code path is used.\n## Note that for general reduction function the interpreter overhead can\n## play a major part and it may be more efficient to do multiple\n## accumarray calls and compute the results in a vectorized manner.\n##\n## @seealso{accumdim, unique, sparse}\n## @end deftypefn\n\nfunction A = accumarray (subs, vals, sz = [], fcn = [], fillval = [], issparse = [])\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  lenvals = length (vals);\n\n  if (iscell (subs))\n    subs = cellfun ('vec', subs, \"uniformoutput\", false);\n    ndims = numel (subs);\n    if (ndims == 1)\n      subs = subs{1};\n    endif\n\n    lensubs = cellfun ('length', subs);\n\n    if (any (lensubs != lensubs(1)) || (lenvals > 1 && lenvals != lensubs(1)))\n      error (\"accumarray: dimension mismatch\");\n    endif\n\n  else\n    ndims = columns (subs);\n    if (lenvals > 1 && lenvals != rows (subs))\n      error (\"accumarray: dimension mismatch\");\n    endif\n  endif\n\n  if (isempty (fcn))\n    fcn = @sum;\n  elseif (! is_function_handle (fcn))\n    error (\"accumarray: FCN must be a function handle\");\n  endif\n\n  if (isempty (fillval))\n    fillval = 0;\n  endif\n\n  if (isempty (issparse))\n    issparse = false;\n  endif\n\n  if (issparse)\n\n    ## Sparse case.\n    ## Avoid linearizing the subscripts, because it could overflow.\n\n    if (fillval != 0)\n      error (\"accumarray: FILLVAL must be zero in the sparse case\");\n    endif\n\n    ## Ensure subscripts are a two-column matrix.\n    if (iscell (subs))\n      subs = [subs{:}];\n    endif\n\n    ## Validate dimensions.\n    if (ndims == 1)\n      subs(:,2) = 1;\n    elseif (ndims != 2)\n      error (\"accumarray: in the sparse case, needs 1 or 2 subscripts\");\n    endif\n\n    if (isnumeric (vals) || islogical (vals))\n      vals = double (vals);\n    else\n      error (\"accumarray: in the sparse case, values must be numeric or logical\");\n    endif\n\n    if (fcn != @sum)\n\n      ## Reduce values.  This is not needed if we're about to sum them,\n      ## because \"sparse\" can do that.\n\n      ## Sort indices.\n      [subs, idx] = sortrows (subs);\n      n = rows (subs);\n      ## Identify runs.\n      jdx = find (any (diff (subs, 1, 1), 2));\n      jdx = [jdx; n];\n\n      vals = cellfun (fcn, mat2cell (vals(:)(idx), diff ([0; jdx])));\n      subs = subs(jdx, :);\n      mode = \"unique\";\n    else\n      mode = \"sum\";\n    endif\n\n    ## Form the sparse matrix.\n    if (isempty (sz))\n      A = sparse (subs(:,1), subs(:,2), vals, mode);\n    elseif (length (sz) == 2)\n\n      ## Row vector case\n      if (sz(1) == 1)\n        [i, j] = deal (subs(:,2), subs(:,1));\n      else\n        [i, j] = deal (subs(:,1), subs(:,2));\n      endif\n      A = sparse (i, j, vals, sz(1), sz(2), mode);\n    else\n      error (\"accumarray: dimensions mismatch\");\n    endif\n\n  else\n\n    ## Linearize subscripts.\n    if (ndims > 1)\n      if (isempty (sz))\n        if (iscell (subs))\n          sz = cellfun (\"max\", subs);\n        else\n          sz = max (subs, [], 1);\n        endif\n      elseif (ndims != length (sz))\n        error (\"accumarray: dimensions mismatch\");\n      endif\n\n      ## Convert multi-dimensional subscripts.\n      if (isnumeric (subs))\n        subs = num2cell (subs, 1);\n      endif\n      subs = sub2ind (sz, subs{:}); # creates index cache\n    elseif (! isempty (sz) && length (sz) < 2)\n      error (\"accumarray: needs at least 2 dimensions\");\n    elseif (! isindex (subs)) # creates index cache\n      error (\"accumarray: indices must be positive integers\");\n    endif\n\n\n    ## Some built-in reductions handled efficiently.\n\n    if (fcn == @sum)\n      ## Fast summation.\n      if (isempty (sz))\n        A = __accumarray_sum__ (subs, vals);\n      else\n        A = __accumarray_sum__ (subs, vals, prod (sz));\n        ## set proper shape.\n        A = reshape (A, sz);\n      endif\n\n      ## we fill in nonzero fill value.\n      if (fillval != 0)\n        mask = true (size (A));\n        mask(subs) = false;\n        A(mask) = fillval;\n      endif\n    elseif (fcn == @max)\n      ## Fast maximization.\n\n      if (isinteger (vals))\n        zero = intmin (vals);\n      elseif (islogical (vals))\n        zero = false;\n      elseif (fillval == 0 && all (vals(:) >= 0))\n        ## This is a common case - fillval is zero, all numbers\n        ## nonegative.\n        zero = 0;\n      else\n        zero = NaN; # Neutral value.\n      endif\n\n      if (isempty (sz))\n        A = __accumarray_max__ (subs, vals, zero);\n      else\n        A = __accumarray_max__ (subs, vals, zero, prod (sz));\n        A = reshape (A, sz);\n      endif\n\n      if (fillval != zero && ! (isnan (fillval) || isnan (zero)))\n        mask = true (size (A));\n        mask(subs) = false;\n        A(mask) = fillval;\n      endif\n    elseif (fcn == @min)\n      ## Fast minimization.\n\n      if (isinteger (vals))\n        zero = intmax (vals);\n      elseif (islogical (vals))\n        zero = true;\n      elseif (fillval == 0 && all (vals(:) <= 0))\n        ## This is a common case - fillval is zero, all numbers\n        ## non-positive.\n        zero = 0;\n      else\n        zero = NaN; # Neutral value.\n      endif\n\n      if (isempty (sz))\n        A = __accumarray_min__ (subs, vals, zero);\n      else\n        A = __accumarray_min__ (subs, vals, zero, prod (sz));\n        A = reshape (A, sz);\n      endif\n\n      if (fillval != zero && ! (isnan (fillval) || isnan (zero)))\n        mask = true (size (A));\n        mask(subs) = false;\n        A(mask) = fillval;\n      endif\n    else\n\n      ## The general case.  Reduce values.\n      n = rows (subs);\n      if (numel (vals) == 1)\n        vals = vals(ones (1, n), 1);\n      else\n        vals = vals(:);\n      endif\n\n      ## Sort indices.\n      [subs, idx] = sort (subs);\n      ## Identify runs.\n      jdx = find (subs(1:n-1) != subs(2:n));\n      if (n != 0) # bug #47287\n        jdx = [jdx; n];\n      endif\n      vals = mat2cell (vals(idx), diff ([0; jdx]));\n      ## Optimize the case when function is @(x) {x}, i.e., we just want\n      ## to collect the values to cells.\n      persistent simple_cell_str = func2str (@(x) {x});\n      if (! strcmp (func2str (fcn), simple_cell_str))\n        vals = cellfun (fcn, vals);\n      endif\n\n      subs = subs(jdx);\n\n      if (isempty (sz))\n        sz = max (subs);\n        ## If subs is empty, sz will be too, and length will be 0, hence \"<= 1\"\n        if (length (sz) <= 1)\n          sz(2) = 1;\n        endif\n      endif\n\n      ## Construct matrix of fillvals.\n      if (iscell (vals))\n        A = cell (sz);\n      elseif (fillval == 0)\n        A = zeros (sz, class (vals));\n      else\n        A = repmat (fillval, sz);\n      endif\n\n      ## Set the reduced values.\n      A(subs) = vals;\n    endif\n  endif\n\nendfunction\n\n\n%!assert (accumarray ([1; 2; 4; 2; 4], 101:105), [101; 206; 0; 208])\n%!assert (accumarray ([1 1 1; 2 1 2; 2 3 2; 2 1 2; 2 3 2], 101:105),\n%!                    cat (3, [101 0 0; 0 0 0], [0 0 0; 206 0 208]))\n\n%!assert (accumarray ([1 1 1; 2 1 2; 2 3 2; 2 1 2; 2 3 2], 101:105, [], @(x) sin (sum (x))),\n%!        sin (cat (3, [101,0,0;0,0,0],[0,0,0;206,0,208])))\n\n%!assert (accumarray ({[1 3 3 2 3 1 2 2 3 3 1 2], [3 4 2 1 4 3 4 2 2 4 3 4], [1 1 2 2 1 1 2 1 1 1 2 2]}, 101:112),\n%!        cat (3, [0 0 207 0; 0 108 0 0; 0 109 0 317], [0 0 111 0; 104 0 0 219; 0 103 0 0]))\n\n%!assert (accumarray ([1 1; 2 1; 2 3; 2 1; 2 3], 101:105, [2 4], @max, NaN),\n%!        [101 NaN NaN NaN; 104 NaN 105 NaN])\n\n%!assert (accumarray ([1 1; 2 1; 2 3; 2 1; 2 3], 101:105, [], @prod),\n%!        [101 0 0; 10608 0 10815])\n%!assert (accumarray ([1 1; 2 1; 2 3; 2 1; 2 3], 101:105, [2 4], @prod, 0, true),\n%!        sparse ([1 2 2], [1 1 3], [101 10608 10815], 2, 4))\n%!assert (accumarray ([1 1; 2 1; 2 3; 2 1; 2 3], 1, [2 4]), [1 0 0 0; 2 0 2 0])\n%!assert (accumarray ([1 1; 2 1; 2 3; 2 1; 2 3], 101:105, [2 4], @(x) length (x) > 1),\n%!        [false false false false; true false true false])\n\n%!assert (accumarray ([1; 2], [3; 4], [2, 1], @min, [], 0), [3; 4])\n%!assert (accumarray ([1; 2], [3; 4], [2, 1], @min, [], 1), sparse ([3; 4]))\n%!assert (accumarray ([1; 2], [3; 4], [1, 2], @min, [], 0), [3, 4])\n%!assert (accumarray ([1; 2], [3; 4], [1, 2], @min, [], 1), sparse ([3, 4]))\n\n%!test\n%! A = accumarray ([1 1; 2 1; 2 3; 2 1; 2 3], 101:105, [2,4], @(x) {x});\n%! assert (A{2},[102; 104]);\n\n%!test\n%! subs = ceil (rand (2000, 3)*10);\n%! vals = rand (2000, 1);\n%! assert (accumarray (subs, vals, [], @max),\n%!         accumarray (subs, vals, [], @(x) max (x)));\n\n%!test\n%! subs = ceil (rand (2000, 1)*100);\n%! vals = rand (2000, 1);\n%! assert (accumarray (subs, vals, [100, 1], @min, NaN),\n%!         accumarray (subs, vals, [100, 1], @(x) min (x), NaN));\n\n%!test\n%! subs = ceil (rand (2000, 2)*30);\n%! subsc = num2cell (subs, 1);\n%! vals = rand (2000, 1);\n%! assert (accumarray (subsc, vals, [], [], 0, true),\n%!         accumarray (subs, vals, [], [], 0, true));\n\n%!test\n%! subs = ceil (rand (2000, 3)*10);\n%! subsc = num2cell (subs, 1);\n%! vals = rand (2000, 1);\n%! assert (accumarray (subsc, vals, [], @max),\n%!         accumarray (subs, vals, [], @max));\n\n%!error accumarray (1:5)\n%!error accumarray ([1,2,3],1:2)\n\n## Handle empty arrays\n%!test <*47287>\n%! ## min, max, and sum are special cases within accumarray so test them.\n%! funcs = {@(x) length (x) > 1, @min, @max, @sum};\n%! for idx = 1:numel (funcs)\n%!   assert (accumarray (zeros (0, 1), [], [0 1] , funcs{idx}), zeros (0, 1));\n%!   assert (accumarray (zeros (0, 1), [], [1 0] , funcs{idx}), zeros (1, 0));\n%!   assert (accumarray (zeros (0, 1), [], [] , funcs{idx}), zeros (0, 1));\n%! endfor\n\n## Matlab returns an array of doubles even though FCN returns cells.  In\n## Octave, we do not have that bug, at least for this case.\n%!assert (accumarray (zeros (0, 1), [], [0 1] , @(x) {x}), cell (0, 1))\n\n%!error <FCN must be a function handle>\n%! accumarray ([1; 2; 3], [1; 2; 3], [3 1], '@(x) {x}')\n"
  },
  {
    "path": "scripts/general/accumdim.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{A} =} accumdim (@var{subs}, @var{vals})\n## @deftypefnx {} {@var{A} =} accumdim (@var{subs}, @var{vals}, @var{dim})\n## @deftypefnx {} {@var{A} =} accumdim (@var{subs}, @var{vals}, @var{dim}, @var{n})\n## @deftypefnx {} {@var{A} =} accumdim (@var{subs}, @var{vals}, @var{dim}, @var{n}, @var{fcn})\n## @deftypefnx {} {@var{A} =} accumdim (@var{subs}, @var{vals}, @var{dim}, @var{n}, @var{fcn}, @var{fillval})\n## Create an array by accumulating the slices of an array into the\n## positions defined by their subscripts along a specified dimension.\n##\n## The subscripts are defined by the index vector @var{subs}.\n## The dimension is specified by @var{dim}.  If not given, it defaults\n## to the first non-singleton dimension.  The length of @var{subs} must\n## be equal to @code{size (@var{vals}, @var{dim})}.\n##\n## The extent of the result matrix in the working dimension will be\n## determined by the subscripts themselves.  However, if @var{n} is\n## defined it determines this extent.\n##\n## The default action of @code{accumdim} is to sum the subarrays with the\n## same subscripts.  This behavior can be modified by defining the\n## @var{fcn} function.  This should be a function or function handle\n## that accepts an array and a dimension, and reduces the array along\n## this dimension.  As a special exception, the built-in @code{min} and\n## @code{max} functions can be used directly, and @code{accumdim}\n## accounts for the middle empty argument that is used in their calling.\n##\n## The slices of the returned array that have no subscripts associated\n## with them are set to zero.  Defining @var{fillval} to some other\n## value allows these values to be defined.\n##\n## An example of the use of @code{accumdim} is:\n##\n## @example\n## @group\n## accumdim ([1, 2, 1, 2, 1], [ 7, -10,   4;\n##                             -5, -12,   8;\n##                            -12,   2,   8;\n##                            -10,   9,  -3;\n##                             -5,  -3, -13])\n## @xresult{} [-10,-11,-1;-15,-3,5]\n## @end group\n## @end example\n##\n## @seealso{accumarray}\n## @end deftypefn\n\nfunction A = accumdim (subs, vals, dim, n = 0, fcn = [], fillval = 0)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (isempty (fillval))\n    fillval = 0;\n  endif\n\n  if (! isvector (subs))\n    error (\"accumdim: SUBS must be a subscript vector\");\n  elseif (! isindex (subs)) # creates index cache\n    error (\"accumdim: indices must be positive integers\");\n  else\n    m = max (subs);\n    if (n == 0 || isempty (n))\n      n = m;\n    elseif (n < m)\n      error (\"accumdim: N index out of range\");\n    endif\n  endif\n\n  sz = size (vals);\n\n  if (nargin < 3)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  elseif (! isindex (dim))\n    error (\"accumdim: DIM must be a valid dimension\");\n  elseif (dim > length (sz))\n    sz(end+1:dim) = 1;\n  endif\n  sz(dim) = n;\n\n  if (length (subs) != size (vals, dim))\n    error (\"accumdim: dimension mismatch\");\n  endif\n\n  if (isempty (fcn) || fcn == @sum)\n    ## Fast summation case.\n    A = __accumdim_sum__ (subs, vals, dim, n);\n\n    ## Fill in nonzero fill value\n    if (fillval != 0)\n      mask = true (n, 1);\n      mask(subs) = false;\n      subsc = {':'}(ones (1, length (sz)));\n      subsc{dim} = mask;\n      A(subsc{:}) = fillval;\n    endif\n    return;\n  endif\n\n  ## The general case.\n  ns = length (subs);\n  ## Sort indices.\n  [subs, idx] = sort (subs(:));\n  ## Identify runs.\n  jdx = find (subs(1:ns-1) != subs(2:ns));\n  jdx = [jdx; ns];\n  ## Collect common slices.\n  szc = num2cell (sz);\n  szc{dim} = diff ([0; jdx]);\n  subsc = {':'}(ones (1, length (sz)));\n  subsc{dim} = idx;\n  vals = mat2cell (vals(subsc{:}), szc{:});\n  ## Apply reductions.  Special case min, max.\n  if (fcn == @min || fcn == @max)\n    vals = cellfun (fcn, vals, {[]}, {dim}, \"uniformoutput\", false);\n  else\n    vals = cellfun (fcn, vals, {dim}, \"uniformoutput\", false);\n  endif\n  subs = subs(jdx);\n\n  ## Concatenate reduced slices.\n  vals = cat (dim, vals{:});\n\n  ## Construct matrix of fillvals.\n  if (fillval == 0)\n    A = zeros (sz, class (vals));\n  else\n    A = repmat (fillval, sz);\n  endif\n\n  ## Set the reduced values.\n  subsc{dim} = subs;\n  A(subsc{:}) = vals;\n\nendfunction\n\n\n## Test accumdim vs. accumarray\n%!shared a\n%! a = rand (5, 5, 5);\n\n%!assert (accumdim ([1;3;1;3;3], a)(:,2,3), accumarray ([1;3;1;3;3], a(:,2,3)))\n%!assert (accumdim ([2;3;2;2;2], a, 2, 4)(4,:,2),\n%!        accumarray ([2;3;2;2;2], a(4,:,2), [1,4]))\n%!assert (accumdim ([2;3;2;1;2], a, 3, 3, @min)(1,5,:),\n%!        accumarray ([2;3;2;1;2], a(1,5,:), [1,1,3], @min))\n%!assert (accumdim ([1;3;2;2;1], a, 2, 3, @median)(4,:,5),\n%!        accumarray ([1;3;2;2;1], a(4,:,5), [1,3], @median))\n\n## Test fillval\n%!assert (accumdim ([1;3;1;3;3], a)(2,:,:), zeros (1,5,5))\n%!assert (accumdim ([1;3;1;3;3], a, 1, 4)([2 4],:,:), zeros (2,5,5))\n%!assert (accumdim ([1;3;1;3;3], a, 1, 4, [], pi)([2 4],:,:), pi (2,5,5))\n\n## Test input validation\n%!error <Invalid call> accumdim ()\n%!error <Invalid call> accumdim (1)\n%!error <SUBS must be a subscript vector> accumdim (ones (2,2), ones (2,2))\n%!error <indices must be positive integers> accumdim ([-1 1], ones (2,2))\n%!error <N index out of range> accumdim ([1 2], ones (2,2), 1, 1)\n%!error <dimension mismatch> accumdim ([1], ones (2,2))\n"
  },
  {
    "path": "scripts/general/bincoeff.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{b} =} bincoeff (@var{n}, @var{k})\n## Return the binomial coefficient of @var{n} and @var{k}.\n##\n## The binomial coefficient is defined as\n## @tex\n## $$\n##  {n \\choose k} = {n (n-1) (n-2) \\cdots (n-k+1) \\over k!}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##  /   \\\n##  | n |    n (n-1) (n-2) @dots{} (n-k+1)\n##  |   |  = -------------------------\n##  | k |               k!\n##  \\   /\n## @end group\n## @end example\n##\n## @end ifnottex\n## For example:\n##\n## @example\n## @group\n## bincoeff (5, 2)\n##    @xresult{} 10\n## @end group\n## @end example\n##\n## In most cases, the @code{nchoosek} function is faster for small\n## scalar integer arguments.  It also warns about loss of precision for\n## big arguments.\n##\n## @seealso{nchoosek}\n## @end deftypefn\n\nfunction b = bincoeff (n, k)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  [retval, n, k] = common_size (n, k);\n  if (retval > 0)\n    error (\"bincoeff: N and K must be of common size or scalars\");\n  endif\n\n  if (iscomplex (n) || iscomplex (k))\n    error (\"bincoeff: N and K must not be complex\");\n  endif\n\n  b = zeros (size (n));\n\n  ok = (k >= 0) & (k == fix (k)) & (! isnan (n));\n  b(! ok) = NaN;\n\n  n_int = (n == fix (n));\n  idx = n_int & (n < 0) & ok;\n  b(idx) = (-1) .^ k(idx) .* exp (gammaln (abs (n(idx)) + k(idx))\n                                  - gammaln (k(idx) + 1)\n                                  - gammaln (abs (n(idx))));\n\n  idx = (n >= k) & ok;\n  b(idx) = exp (gammaln (n(idx) + 1)\n                - gammaln (k(idx) + 1)\n                - gammaln (n(idx) - k(idx) + 1));\n\n  idx = (! n_int) & (n < k) & ok;\n  b(idx) = (1/pi) * exp (gammaln (n(idx) + 1)\n                         - gammaln (k(idx) + 1)\n                         + gammaln (k(idx) - n(idx))\n                         + log (sin (pi * (n(idx) - k(idx) + 1))));\n\n  ## Clean up rounding errors.\n  b(n_int) = round (b(n_int));\n\n  idx = ! n_int;\n  b(idx) = real (b(idx));\n\nendfunction\n\n\n%!assert (bincoeff (4, 2), 6)\n%!assert (bincoeff (2, 4), 0)\n%!assert (bincoeff (-4, 2), 10)\n%!assert (bincoeff (5, 2), 10)\n%!assert (bincoeff (50, 6), 15890700)\n%!assert (bincoeff (0.4, 2), -.12, 8*eps)\n\n%!assert (bincoeff ([4 NaN 4], [-1, 2, 2.5]), NaN (1, 3))\n\n## Test input validation\n%!error <Invalid call> bincoeff ()\n%!error <Invalid call> bincoeff (1)\n%!error bincoeff (ones (3), ones (2))\n%!error bincoeff (ones (2), ones (3))\n"
  },
  {
    "path": "scripts/general/bitcmp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{C} =} bitcmp (@var{A}, @var{k})\n## Return the @var{k}-bit complement of integers in @var{A}.\n##\n## If @var{k} is omitted @code{k = log2 (flintmax) + 1} is assumed.\n##\n## @example\n## @group\n## bitcmp (7,4)\n##   @xresult{} 8\n## dec2bin (11)\n##   @xresult{} 1011\n## dec2bin (bitcmp (11, 6))\n##   @xresult{} 110100\n## @end group\n## @end example\n##\n## @seealso{bitand, bitor, bitxor, bitset, bitget, bitcmp, bitshift, flintmax}\n## @end deftypefn\n\n## Liberally based on the version by Kai Habel from Octave Forge\n\nfunction C = bitcmp (A, k)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 2 && (! isscalar (k) || (floor (k) != k)))\n    error (\"bitcmp: K must be a scalar integer\");\n  endif\n\n  if (isa (A, \"double\"))\n    bmax = flintmax - 1;\n    amax = ceil (log2 (bmax));\n  elseif (isa (A, \"single\"))\n    bmax = flintmax (\"single\") - 1;\n    amax = ceil (log2 (bmax));\n  elseif (isinteger (A))\n    amax = sizeof (ones (1, class (A))) * 8;\n    bmax = bitpack (true (amax, 1), class (A));\n  else\n    error (\"bitcmp: invalid class %s\", class (A));\n  endif\n\n  if (nargin == 1 || k == amax)\n    C = bitxor (A, bmax);\n  else\n    m = double (k);\n    if (any (m < 1) || any (m > amax))\n      error (\"bitcmp: K must be in the range [1,%d]\", amax);\n    endif\n    mask = bitshift (bmax, k - amax);\n    C = bitxor (bitand (A, mask), mask);\n  endif\n\nendfunction\n\n\n%!test\n%! Amax = 53;\n%! Bmax = flintmax - 1;\n%! A = bitshift (Bmax,-2);\n%! assert (bitcmp (A,Amax),bitor (bitshift (1,Amax-1), bitshift (1,Amax-2)));\n%! assert (bitcmp (A,Amax-1), bitshift (1,Amax-2));\n%! assert (bitcmp (A,Amax-2), 0);\n%!test\n%! Amax = 24;\n%! Bmax = flintmax (\"single\") - 1;\n%! A = bitshift (Bmax,-2);\n%! assert (bitcmp (A,Amax),\n%!         bitor (bitshift (single (1),Amax-1), bitshift (single (1),Amax-2)));\n%! assert (bitcmp (A,Amax-1), bitshift (single (1),Amax-2));\n%! assert (bitcmp (A,Amax-2), single (0));\n%!test\n%! Amax = 8;\n%! Bmax = intmax (\"uint8\");\n%! A = bitshift (Bmax,-2);\n%! assert (bitcmp (A,Amax),\n%!         bitor (bitshift (uint8 (1),Amax-1), bitshift (uint8 (1),Amax-2)));\n%! assert (bitcmp (A,Amax-1), bitshift (uint8 (1),Amax-2));\n%! assert (bitcmp (A,Amax-2), uint8 (0));\n%!test\n%! Amax = 16;\n%! Bmax = intmax (\"uint16\");\n%! A = bitshift (Bmax,-2);\n%! assert (bitcmp (A,Amax),\n%!         bitor (bitshift (uint16 (1),Amax-1), bitshift (uint16 (1),Amax-2)));\n%! assert (bitcmp (A,Amax-1), bitshift (uint16 (1),Amax-2));\n%! assert (bitcmp (A,Amax-2), uint16 (0));\n%!test\n%! Amax = 32;\n%! Bmax = intmax (\"uint32\");\n%! A = bitshift (Bmax,-2);\n%! assert (bitcmp (A,Amax),\n%!         bitor (bitshift (uint32 (1),Amax-1), bitshift (uint32 (1),Amax-2)));\n%! assert (bitcmp (A,Amax-1), bitshift (uint32 (1),Amax-2));\n%! assert (bitcmp (A,Amax-2), uint32 (0));\n%!test\n%! Amax = 64;\n%! Bmax = intmax (\"uint64\");\n%! A = bitshift (Bmax,-2);\n%! assert (bitcmp (A,Amax),\n%!         bitor (bitshift (uint64 (1),Amax-1), bitshift (uint64 (1),Amax-2)));\n%! assert (bitcmp (A,Amax-1), bitshift (uint64 (1),Amax-2));\n%! assert (bitcmp (A,Amax-2), uint64 (0));\n\n## Do not forget signed integers\n%!assert (bitcmp (int8 (127)), int8 (-128)) # [1 1 1 1 1 1 1 0]\n%!assert (bitcmp (int8 (1)), int8 (-2))     # [1 0 0 0 0 0 0 0]\n%!assert (bitcmp (int8 (0)), int8 (-1))     # [0 0 0 0 0 0 0 0]\n%!assert (bitcmp (int8 (8)), int8 (-9))     # [0 0 0 1 0 0 0 0]\n"
  },
  {
    "path": "scripts/general/bitget.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{b} =} bitget (@var{A}, @var{n})\n## Return the bit value at position(s) @var{n} of the unsigned integers in\n## @var{A}.\n##\n## The least significant bit is @var{n} = 1.\n##\n## @example\n## @group\n## bitget (100, 8:-1:1)\n## @xresult{} 0  1  1  0  0  1  0  0\n## @end group\n## @end example\n## @seealso{bitand, bitor, bitxor, bitset, bitcmp, bitshift, intmax, flintmax}\n## @end deftypefn\n\n## Liberally based of the version by Kai Habel from Octave Forge\n\nfunction b = bitget (A, n)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (isa (A, \"double\"))\n    Amax = ceil (log2 (flintmax));\n    _conv = @double;\n  elseif (isa (A, \"single\"))\n    Amax = ceil (log2 (flintmax (\"single\")));\n    _conv = @single;\n  else\n    if (isa (A, \"uint8\"))\n      Amax = 8;\n      _conv = @uint8;\n    elseif (isa (A, \"uint16\"))\n      Amax = 16;\n      _conv = @uint16;\n    elseif (isa (A, \"uint32\"))\n      Amax = 32;\n      _conv = @uint32;\n    elseif (isa (A, \"uint64\"))\n      Amax = 64;\n      _conv = @uint64;\n    ## Temporary fix for bug #67592 for Octave 11.\n    ## Use unsigned integers in algorithm.\n    elseif (isa (A, \"int8\"))\n      Amax = 8;\n      _conv = @uint8;\n      A = typecast (A, 'uint8');\n    elseif (isa (A, \"int16\"))\n      Amax = 16;\n      _conv = @uint16;\n      A = typecast (A, 'uint16');\n    elseif (isa (A, \"int32\"))\n      Amax = 32;\n      _conv = @uint32;\n      A = typecast (A, 'uint32');\n    elseif (isa (A, \"int64\"))\n      Amax = 64;\n      _conv = @uint64;\n      A = typecast (A, 'uint64');\n    else\n      error (\"bitget: invalid class %s\", class (A));\n    endif\n  endif\n\n  m = double (n(:));\n  if (any (m < 1) || any (m > Amax))\n    error (\"bitget: N must be in the range [1,%d]\", Amax);\n  endif\n\n  b = bitand (A, bitshift (_conv (1), uint8 (n) - uint8 (1))) != _conv (0);\n\nendfunction\n\n\n%!test\n%! assert (bitget ([4, 14], [3, 3]), logical ([1, 1]));\n%! assert (bitget (single ([4, 14]), [3, 3]), logical ([1, 1]));\n%! pfx = {\"\", \"u\"};\n%! for i = 1:2\n%!   for prec = [8, 16, 32, 64]\n%!     fcn = str2func (sprintf (\"%sint%d\", pfx{i}, prec));\n%!     assert (bitget (fcn ([4, 14]), [3, 3]), logical ([1, 1]));\n%!   endfor\n%! endfor\n\n%!test <*67592>\n%! x = intmin ('int8');\n%! b = bitget (x, 8:-1:1);\n%! assert (b, logical ([1 0 0 0 0 0 0 0]));\n\n## Test input validation\n%!error <Invalid call> bitget ()\n%!error <Invalid call> bitget (1)\n%!error <invalid class> bitget (\"char\", 1)\n%!error <N must be in the range \\[1,53\\]> bitget (0, 0)\n%!error <N must be in the range \\[1,53\\]> bitget (0, 55)\n%!error <N must be in the range \\[1,24\\]> bitget (single (0), 0)\n%!error <N must be in the range \\[1,24\\]> bitget (single (0), 26)\n%!error <N must be in the range \\[1,8\\]> bitget (int8 (0), 9)\n%!error <N must be in the range \\[1,8\\]> bitget (uint8 (0), 9)\n%!error <N must be in the range \\[1,16\\]> bitget (int16 (0), 17)\n%!error <N must be in the range \\[1,16\\]> bitget (uint16 (0), 17)\n%!error <N must be in the range \\[1,32\\]> bitget (int32 (0), 33)\n%!error <N must be in the range \\[1,32\\]> bitget (uint32 (0), 33)\n%!error <N must be in the range \\[1,64\\]> bitget (int64 (0), 65)\n%!error <N must be in the range \\[1,64\\]> bitget (uint64 (0), 65)\n"
  },
  {
    "path": "scripts/general/bitset.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} bitset (@var{A}, @var{n})\n## @deftypefnx {} {@var{B} =} bitset (@var{A}, @var{n}, @var{val})\n## Set or reset bit(s) at position @var{n} of the unsigned integers in @var{A}.\n##\n## The least significant bit is @var{n} = 1.  @w{@var{val} = 0}@ resets bits\n## and @w{@var{val} = 1}@ sets bits.  If no @var{val} is specified it\n## defaults to 1 (set bit).  All inputs must be the same size or scalars.\n##\n## Example 1: Set multiple bits\n##\n## @example\n## @group\n## x = bitset (1, 3:5)\n##   @xresult{} x =\n##\n##    5    9   17\n##\n## dec2bin (x)\n##   @xresult{}\n##      00101\n##      01001\n##      10001\n## @end group\n## @end example\n##\n## Example 2: Reset and set bits\n##\n## @example\n## @group\n## x = bitset ([15 14], 1, [0 1])\n##   @xresult{} x =\n##\n##    14    15\n## @end group\n## @end example\n## @seealso{bitand, bitor, bitxor, bitget, bitcmp, bitshift, intmax, flintmax}\n## @end deftypefn\n\nfunction B = bitset (A, n, val = true)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (any (A(:) < 0))\n    error (\"bitset: A must be >= 0\");\n  endif\n\n  [size_err, A, n, val] = common_size (A, n, val);\n  if (size_err)\n    error (\"bitset: A, N, and VAL must be the same size or scalar\");\n  endif\n\n  ## Special case of empty input\n  if (isempty (A))\n    B = [];\n    return;\n  endif\n\n  sz = size (A);\n  cls = class (A);\n\n  if (isfloat (A) && isreal (A))\n    Bmax = flintmax (cls);\n    Amax = ceil (log2 (Bmax));\n  elseif (isinteger (A))\n    Bmax = intmax (cls);\n    Amax = ceil (log2 (Bmax));\n  else\n    error (\"bitset: invalid class %s\", cls);\n  endif\n\n  if (any (n(:) < 1) || any (n(:) > Amax))\n    error (\"bitset: N must be in the range [1,%d]\", Amax);\n  endif\n\n  mask = bitshift (cast (1, cls), uint8 (n) - uint8 (1));\n\n  on = logical (val);\n  off = ! on;\n\n  if (isscalar (mask))\n    onmask = mask;\n    offmask = mask;\n  else\n    onmask = mask(on);\n    offmask = mask(off);\n  endif\n\n  B = zeros (sz, cls);\n  B(on) = bitor (A(on), onmask);\n  B(off) = bitand (A(off), bitcmp (offmask));\n\nendfunction\n\n\n%!test\n%! assert (bitset ([0, 10], [3, 3]), [4, 14]);\n%! assert (bitset (single ([0, 10]), [3, 3]), single ([4, 14]));\n%! pfx = {\"\", \"u\"};\n%! for i = 1:2\n%!   for prec = [8, 16, 32, 64]\n%!     fcn = str2func (sprintf (\"%sint%d\", pfx{i}, prec));\n%!     assert (bitset (fcn ([0, 10]), [3, 3]), fcn ([4, 14]));\n%!   endfor\n%! endfor\n\n## Special case of empty input\n%!assert (bitset ([], 1), [])\n\n%!assert <*36458> (bitset (uint8 ([1, 2;3 4]), 1, [0 1; 0 1]),\n%!                 uint8 ([0, 3; 2 5]))\n\n%!assert (bitset (1:5, 1), [1, 3, 3, 5, 5])\n%!assert (bitset (1:5, 1, [1, 1, 1, 1, 1]), [1, 3, 3, 5, 5])\n%!assert <*54110> (bitset (1:5, 1, 1), [1, 3, 3, 5, 5])\n%!assert (bitset (1:5, 1, [1, 1, 1, 1, 0]), [1, 3, 3, 5, 4])\n\n## Test input validation\n%!error <Invalid call> bitset ()\n%!error <Invalid call> bitset (1)\n%!error <A must be .= 0> bitset (-1, 2)\n%!error <must be the same size or scalar> bitset ([1 2], [1 2 3])\n%!error <must be the same size or scalar> bitset (1, [1 2], [1 2 3])\n%!error <invalid class char> bitset (\"1\", 2)\n%!error <N must be in the range \\[1,53\\]> bitset (0, 0)\n%!error <N must be in the range \\[1,53\\]> bitset (0, 55)\n%!error <N must be in the range \\[1,24\\]> bitset (single (0), 0)\n%!error <N must be in the range \\[1,24\\]> bitset (single (0), 26)\n%!error <N must be in the range \\[1,7\\]> bitset (int8 (0), 0)\n%!error <N must be in the range \\[1,7\\]> bitset (int8 (0), 9)\n%!error <N must be in the range \\[1,8\\]> bitset (uint8 (0), 9)\n%!error <N must be in the range \\[1,15\\]> bitset (int16 (0), 17)\n%!error <N must be in the range \\[1,16\\]> bitset (uint16 (0), 17)\n%!error <N must be in the range \\[1,31\\]> bitset (int32 (0), 33)\n%!error <N must be in the range \\[1,32\\]> bitset (uint32 (0), 33)\n%!error <N must be in the range \\[1,63\\]> bitset (int64 (0), 65)\n%!error <N must be in the range \\[1,64\\]> bitset (uint64 (0), 65)\n"
  },
  {
    "path": "scripts/general/blkdiag.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{M} =} blkdiag (@var{A}, @var{B}, @var{C}, @dots{})\n## Build a block diagonal matrix from @var{A}, @var{B}, @var{C}, @enddots{}\n##\n## All arguments must be numeric and either two-dimensional matrices or\n## scalars.  If any argument is of type sparse, the output will also be sparse.\n## @seealso{diag, horzcat, vertcat, sparse}\n## @end deftypefn\n\nfunction M = blkdiag (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! all (cellfun (\"isnumeric\", varargin)))\n    error (\"blkdiag: all arguments must be numeric\");\n  endif\n\n  ## Note: trailing singletons are automatically (correctly) ignored.\n  if (! all (cellfun (\"ndims\", varargin) == 2))\n    error (\"blkdiag: all arguments must be two-dimensional matrices\");\n  endif\n\n  ## 'size' is an option for cellfun, but it's a bit different from\n  ## calling size directly which is required here.\n  tmp = cell2mat (cellfun (@size, varargin', \"uniformoutput\", false));\n  csz = cumsum ([0 0; tmp], 1);\n\n  if (any (cellfun (\"issparse\", varargin)))\n    M = sparse (csz(end,1), csz(end,2));\n  else\n    M = zeros (csz(end,:));\n  endif\n\n  for p = 1:nargin\n    vp = varargin{p};\n    if (! isempty (vp))\n      M((csz(p,1)+1):csz(p+1,1),(csz(p,2)+1):csz(p+1,2)) = vp;\n    endif\n  endfor\n\nendfunction\n\n\n## regular tests\n%!assert (blkdiag (1,ones (2),1), [1,0,0,0;0,1,1,0;0,1,1,0;0,0,0,1])\n%!assert (blkdiag ([1,2],[3,4],[5,6]), [1,2,0,0,0,0;0,0,3,4,0,0;0,0,0,0,5,6])\n%!assert (blkdiag ([1,2],[3;4],[5,6]),\n%!        [1,2,0,0,0;0,0,3,0,0;0,0,4,0,0;0,0,0,5,6])\n%!assert (blkdiag ([1,2;3,4],[5,6,7]), [1,2,0,0,0;3,4,0,0,0;0,0,5,6,7])\n## tests involving empty matrices\n%!assert (blkdiag ([],[],[]), [])\n%!assert (blkdiag ([],[1,2;3,4],[],5,[]), [1,2,0;3,4,0;0,0,5])\n%!assert (blkdiag (zeros (1,0,1),[1,2,3],1,0,5,zeros (0,1,1)),\n%!        [0,0,0,0,0,0,0;1,2,3,0,0,0,0;0,0,0,1,0,0,0;0,0,0,0,0,0,0;0,0,0,0,0,5,0])\n## tests involving sparse matrices\n%!assert (blkdiag (sparse ([1,2;3,4]),[5,6;7,8]),\n%!        sparse ([1,2,0,0;3,4,0,0;0,0,5,6;0,0,7,8]))\n%!assert (blkdiag (sparse ([1,2;3,4]),[5,6]),\n%!        sparse ([1,2,0,0;3,4,0,0;0,0,5,6]))\n## sanity checks\n%!test\n%! A = rand (round (rand (1, 2) * 10));\n%! assert (blkdiag (A), A);\n"
  },
  {
    "path": "scripts/general/cart2pol.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{theta}, @var{r}] =} cart2pol (@var{x}, @var{y})\n## @deftypefnx {} {[@var{theta}, @var{r}, @var{z}] =} cart2pol (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {[@var{theta}, @var{r}] =} cart2pol (@var{C})\n## @deftypefnx {} {[@var{theta}, @var{r}, @var{z}] =} cart2pol (@var{C})\n##\n## Transform Cartesian coordinates to polar or cylindrical coordinates.\n##\n## The inputs @var{x}, @var{y} (, and @var{z}) must be the same shape, or\n## scalar.  If called with a single matrix argument then each row of @var{C}\n## represents the Cartesian coordinate pair (@var{x}, @var{y}) or triplet\n## (@var{x}, @var{y}, @var{z}).\n##\n## The outputs @var{theta}, @var{r} (, and @var{z}) match the shape of the\n## inputs.  For a matrix input @var{C} the outputs will be column vectors with\n## rows corresponding to the rows of the input matrix.\n##\n## @var{theta} describes the angle relative to the positive x-axis measured in\n## the xy-plane.\n##\n## @var{r} is the distance to the z-axis @w{(0, 0, z)}.\n##\n## @var{z}, if present, is unchanged by the transformation.\n##\n## The coordinate transformation is computed using:\n## @tex\n## $$ \\theta = \\arctan \\left ( {y \\over x} \\right ) $$\n## $$ r = \\sqrt{x^2 + y^2} $$\n## $$ z = z $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## @var{theta} = arctan (@var{y} / @var{x})\n## @var{r} = sqrt (@var{x}^2 + @var{y}^2)\n## @var{z} = @var{z}\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @seealso{pol2cart, cart2sph, sph2cart}\n## @end deftypefn\n\nfunction [theta, r, z] = cart2pol (x, y, z = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    if (! (isnumeric (x) && ismatrix (x)))\n      error (\"cart2pol: matrix input must be 2-D numeric array\");\n    endif\n    if (isvector (x))\n      n = numel (x);\n      if (n != 2 && n != 3)\n        error (\"cart2pol: matrix input must be a 2- or 3-element vector or a 2- or 3-column array\");\n      endif\n      if (n == 3)\n        z = x(3);\n      endif\n      y = x(2);\n      x = x(1);\n    else\n      ncols = columns (x);\n      if (ncols != 2 && ncols != 3)\n        error (\"cart2pol: matrix input must be a 2- or 3-element vector or a 2- or 3-column array\");\n      endif\n\n      if (ncols == 3)\n        z = x(:,3);\n      endif\n      y = x(:,2);\n      x = x(:,1);\n    endif\n\n  elseif (nargin == 2)\n    if (! (isnumeric (x) && isnumeric (y)))\n      error (\"cart2pol: X, Y must be numeric arrays or scalars\");\n    endif\n    [err, x, y] = common_size (x, y);\n    if (err)\n      error (\"cart2pol: X, Y must be the same size or scalars\");\n    endif\n\n  elseif (nargin == 3)\n    if (! (isnumeric (x) && isnumeric (y) && isnumeric (z)))\n      error (\"cart2pol: X, Y, Z must be numeric arrays or scalars\");\n    endif\n    [err, x, y, z] = common_size (x, y, z);\n    if (err)\n      error (\"cart2pol: X, Y, Z must be the same size or scalars\");\n    endif\n  endif\n\n  theta = atan2 (y, x);\n  r = sqrt (x .^ 2 + y .^ 2);\n\nendfunction\n\n\n%!test\n%! x = [0, 1, 2];\n%! y = 0;\n%! [t, r] = cart2pol (x, y);\n%! assert (t, [0, 0, 0]);\n%! assert (r, x);\n\n%!test\n%! x = [0, 1, 2];\n%! y = [0, 1, 2];\n%! [t, r] = cart2pol (x, y);\n%! assert (t, [0, pi/4, pi/4], eps);\n%! assert (r, sqrt (2)*[0, 1, 2], eps);\n\n%!test\n%! x = [0, 1, 2]';\n%! y = [0, 1, 2]';\n%! [t, r] = cart2pol (x, y);\n%! assert (t, [0; pi/4; pi/4], eps);\n%! assert (r, sqrt (2)*[0; 1; 2], eps);\n\n%!test\n%! x = [0, 1, 2];\n%! y = [0, 1, 2];\n%! z = [0, 1, 2];\n%! [t, r, z2] = cart2pol (x, y, z);\n%! assert (t, [0, pi/4, pi/4], sqrt (eps));\n%! assert (r, sqrt (2)*[0, 1, 2], sqrt (eps));\n%! assert (z2, z);\n\n%!test\n%! x = [0, 1, 2];\n%! y = 0;\n%! z = 0;\n%! [t, r, z2] = cart2pol (x, y, z);\n%! assert (t, [0, 0, 0], eps);\n%! assert (r, x, eps);\n%! assert (z2, [0, 0, 0]);\n\n%!test\n%! x = 0;\n%! y = [0, 1, 2];\n%! z = 0;\n%! [t, r, z2] = cart2pol (x, y, z);\n%! assert (t, [0, 1, 1]*pi/2, eps);\n%! assert (r, y, eps);\n%! assert (z2, [0, 0, 0]);\n\n%!test\n%! x = 0;\n%! y = 0;\n%! z = [0, 1, 2];\n%! [t, r, z2] = cart2pol (x, y, z);\n%! assert (t, [0, 0, 0]);\n%! assert (r, [0, 0, 0]);\n%! assert (z2, z);\n\n%!test\n%! C = [0, 0; 1, 1; 2, 2];\n%! [t, r] = cart2pol (C);\n%! assert (t, [0; 1; 1]*pi/4, eps);\n%! assert (r, [0; 1; 2]*sqrt(2), eps);\n\n%!test\n%! C = [0, 0, 0; 1, 1, 1; 2, 2, 2];\n%! [t, r, z] = cart2pol (C);\n%! assert (t, [0; 1; 1]*pi/4, eps);\n%! assert (r, [0; 1; 2]*sqrt(2), eps);\n%! assert (z, [0; 1; 2]);\n\n%!test\n%! C = [0, 0, 0; 1, 1, 1; 2, 2, 2;1, 1, 1];\n%! [t, r, z] = cart2pol (C);\n%! assert (t, [0; 1; 1; 1]*pi/4, eps);\n%! assert (r, [0; 1; 2; 1]*sqrt(2), eps);\n%! assert (z, [0; 1; 2; 1]);\n\n%!test\n%! x = zeros (1, 1, 1, 2);\n%! x(1, 1, 1, 2) = sqrt (2);\n%! y = x;\n%! [t, r] = cart2pol (x, y);\n%! T = zeros (1, 1, 1, 2);\n%! T(1, 1, 1, 2) = pi/4;\n%! R = zeros (1, 1, 1, 2);\n%! R(1, 1, 1, 2) = 2;\n%! assert (t, T, eps);\n%! assert (r, R, eps);\n\n%!test\n%! [x, y, Z] = meshgrid ([0, 1], [0, 1], [0, 1]);\n%! [t, r, z] = cart2pol (x, y, Z);\n%! T(:, :, 1) = [0, 0; pi/2, pi/4];\n%! T(:, :, 2) = T(:, :, 1);\n%! R = sqrt (x.^2 + y.^2);\n%! assert (t, T, eps);\n%! assert (r, R, eps);\n%! assert (z, Z);\n\n## Test input validation\n%!error <Invalid call> cart2pol ()\n%!error cart2pol (1,2,3,4)\n%!error <matrix input must be 2-D numeric array> cart2pol ({1,2,3})\n%!error <matrix input must be 2-D numeric array> cart2pol (ones (3,3,2))\n%!error <matrix input must be a 2- or 3-element> cart2pol ([1])\n%!error <matrix input must be a 2- or 3-element> cart2pol ([1,2,3,4])\n%!error <must be numeric arrays or scalars> cart2pol ({1,2,3}, [1,2,3])\n%!error <must be numeric arrays or scalars> cart2pol ([1,2,3], {1,2,3})\n%!error <must be the same size or scalars> cart2pol (ones (3,3,3), ones (3,2,3))\n%!error <must be the same size or scalars> cart2pol ([1; 1], [2, 2])\n%!error <must be the same size or scalars> cart2pol ([1; 1], [2, 2], [3, 3])\n%!error <must be numeric arrays or scalars> cart2pol ({1,2,3}, [1,2,3], [1,2,3])\n%!error <must be numeric arrays or scalars> cart2pol ([1,2,3], {1,2,3}, [1,2,3])\n%!error <must be numeric arrays or scalars> cart2pol ([1,2,3], [1,2,3], {1,2,3})\n%!error <must be the same size or scalars> cart2pol (ones (3,3,3), 1, ones (3,2,3))\n%!error <must be the same size or scalars> cart2pol (ones (3,3,3), ones (3,2,3), 1)\n"
  },
  {
    "path": "scripts/general/cart2sph.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{theta}, @var{phi}, @var{r}] =} cart2sph (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {[@var{theta}, @var{phi}, @var{r}] =} cart2sph (@var{C})\n## Transform Cartesian coordinates to spherical coordinates.\n##\n## The inputs @var{x}, @var{y}, and @var{z} must be the same shape, or scalar.\n## If called with a single matrix argument then each row of @var{C} must\n## represent a Cartesian coordinate triplet (@var{x}, @var{y}, @var{z}).\n##\n## The outputs @var{theta}, @var{phi}, @var{r} match the shape of the inputs.\n## For a matrix input @var{C} the outputs will be column vectors with rows\n## corresponding to the rows of the input matrix.\n##\n## @var{theta} describes the azimuth angle relative to the positive x-axis\n## measured in the xy-plane.\n##\n## @var{phi} is the elevation angle measured relative to the xy-plane.\n##\n## @var{r} is the distance to the origin @w{(0, 0, 0)}.\n##\n## The coordinate transformation is computed using:\n## @tex\n## $$ \\theta = \\arctan \\left ({y \\over x} \\right ) $$\n## $$ \\phi = \\arctan \\left ( {z \\over {\\sqrt{x^2+y^2}}} \\right ) $$\n## $$ r = \\sqrt{x^2 + y^2 + z^2} $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## @var{theta} = arctan (@var{y} / @var{x})\n## @var{phi} = arctan (@var{z} / sqrt (@var{x}^2 + @var{y}^2))\n## @var{r} = sqrt (@var{x}^2 + @var{y}^2 + @var{z}^2)\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @seealso{sph2cart, cart2pol, pol2cart}\n## @end deftypefn\n\nfunction [theta, phi, r] = cart2sph (x, y, z)\n\n  if (nargin != 1 && nargin != 3)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    if (! (isnumeric (x) && ismatrix (x)))\n      error (\"cart2sph: matrix input C must be a 2-D numeric array\");\n    elseif (columns (x) != 3 && numel (x) != 3)\n      error (\"cart2sph: matrix input C must be a 3-element vector or 3-column array\");\n    endif\n\n    if (numel (x) == 3)\n      z = x(3);\n      y = x(2);\n      x = x(1);\n    else\n      z = x(:,3);\n      y = x(:,2);\n      x = x(:,1);\n    endif\n\n  else\n    if (! (isnumeric (x) && isnumeric (y) && isnumeric (z)))\n      error (\"cart2sph: X, Y, Z must be numeric arrays or scalars\");\n    endif\n    [err, x, y, z] = common_size (x, y, z);\n    if (err)\n      error (\"cart2sph: X, Y, Z must be the same size or scalars\");\n    endif\n  endif\n\n  theta = atan2 (y, x);\n  phi = atan2 (z, sqrt (x .^ 2 + y .^ 2));\n  r = sqrt (x .^ 2 + y .^ 2 + z .^ 2);\n\nendfunction\n\n\n%!test\n%! x = [0, 1, 2];\n%! y = [0, 1, 2];\n%! z = [0, 1, 2];\n%! [t, p, r] = cart2sph (x, y, z);\n%! assert (t, [0, pi/4, pi/4], eps);\n%! assert (p, [0, 1, 1]*atan (sqrt (0.5)), eps);\n%! assert (r, [0, 1, 2]*sqrt (3), eps);\n\n%!test\n%! x = [0; 1; 2];\n%! y = [0; 1; 2];\n%! z = [0; 1; 2];\n%! [t, p, r] = cart2sph (x, y, z);\n%! assert (t, [0; pi/4; pi/4], eps);\n%! assert (p, [0; 1; 1] * atan (sqrt (0.5)), eps);\n%! assert (r, [0; 1; 2] * sqrt (3), eps);\n\n%!test\n%! x = 0;\n%! y = [0, 1, 2];\n%! z = [0, 1, 2];\n%! [t, p, r] = cart2sph (x, y, z);\n%! assert (t, [0, 1, 1] * pi/2, eps);\n%! assert (p, [0, 1, 1] * pi/4, eps);\n%! assert (r, [0, 1, 2] * sqrt (2), eps);\n\n%!test\n%! x = [0, 1, 2];\n%! y = 0;\n%! z = [0, 1, 2];\n%! [t, p, r] = cart2sph (x, y, z);\n%! assert (t, [0, 0, 0]);\n%! assert (p, [0, 1, 1] * pi/4, eps);\n%! assert (r, [0, 1, 2] * sqrt (2), eps);\n\n%!test\n%! x = [0, 1, 2];\n%! y = [0, 1, 2];\n%! z = 0;\n%! [t, p, r] = cart2sph (x, y, z);\n%! assert (t, [0, 1, 1] * pi/4, eps);\n%! assert (p, [0, 0, 0]);\n%! assert (r, [0, 1, 2] * sqrt (2), eps);\n\n%!test\n%! x = 0;\n%! y = 0;\n%! z = [0, 1, 2];\n%! [t, p, r] = cart2sph (x, y, z);\n%! assert (t, [0, 0, 0]);\n%! assert (p, [0, 1, 1] * pi/2, eps);\n%! assert (r, [0, 1, 2]);\n\n%!test\n%! C = [0, 0, 0; 1, 0, 1; 2, 0, 2];\n%! [t, p, r] = cart2sph (C);\n%! assert (t, [0; 0; 0]);\n%! assert (p, [0; 1; 1] * pi/4, eps);\n%! assert (r, [0; 1; 2] * sqrt (2), eps);\n\n%!test\n%! C = [0, 0, 0; 1, 0, 1; 2, 0, 2; 1, 0, 1];\n%! [t, p, r] = cart2sph (C);\n%! assert (t, [0; 0; 0; 0]);\n%! assert (p, [0; 1; 1; 1] * pi/4, eps);\n%! assert (r, [0; 1; 2; 1] * sqrt (2), eps);\n\n%!test\n%! [x, y, z] = meshgrid ([0, 1], [0, 1], [0, 1]);\n%! [t, p, r] = cart2sph (x, y, z);\n%! T(:, :, 1) = [0, 0; pi/2, pi/4];\n%! T(:, :, 2) = T(:, :, 1);\n%! P(:, :, 1) = zeros (2, 2);\n%! P(:, :, 2) = [pi/2, pi/4; pi/4, acos(sqrt(2/3))];\n%! R = sqrt (x .^ 2 + y .^ 2 + z .^ 2);\n%! assert (t, T, eps);\n%! assert (p, P, eps);\n%! assert (r, R, eps);\n\n## Test input validation\n%!error <Invalid call> cart2sph ()\n%!error <Invalid call> cart2sph (1,2)\n%!error <matrix input C must be a 2-D numeric array> cart2sph ({1,2,3})\n%!error <matrix input C must be a 2-D numeric array> cart2sph (ones (3,3,2))\n%!error <matrix input C must be a 3-element> cart2sph ([1,2,3,4])\n%!error <matrix input C must be a 3-element> cart2sph ([1,2,3,4; 1,2,3,4; 1,2,3,4])\n%!error <must be numeric arrays or scalars> cart2sph ({1,2,3}, [1,2,3], [1,2,3])\n%!error <must be numeric arrays or scalars> cart2sph ([1,2,3], {1,2,3}, [1,2,3])\n%!error <must be numeric arrays or scalars> cart2sph ([1,2,3], [1,2,3], {1,2,3})\n%!error <must be the same size or scalars> cart2sph ([1,2,3], [1,2,3], [1,2,3]')\n%!error <must be the same size or scalars> cart2sph (ones (3,3,3), 1, ones (3,2,3))\n%!error <must be the same size or scalars> cart2sph (ones (3,3,3), ones (3,2,3), 1)\n"
  },
  {
    "path": "scripts/general/cell2mat.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{m} =} cell2mat (@var{c})\n## Convert the cell array @var{c} into a matrix by concatenating all\n## elements of @var{c} into a hyperrectangle.\n##\n## Elements of @var{c} must be numeric, logical, or char matrices; or cell\n## arrays; or structs; and @code{cat} must be able to concatenate them\n## together.\n## @seealso{mat2cell, num2cell}\n## @end deftypefn\n\nfunction m = cell2mat (c)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isempty (c))\n    m = zeros (size (c));\n  else\n    if (! iscell (c))\n      error (\"cell2mat: C must be a cell array\");\n    endif\n\n    ## Check first for valid matrix types\n    valid = cellfun (\"isnumeric\", c);\n    valid = cellfun (\"islogical\", c(! valid));\n    valid = cellfun (\"isclass\", c(! valid), \"char\");\n    if (! all (valid(:)))\n      valid = cellfun (\"isclass\", c, \"cell\");\n      if (! all (valid(:)))\n        valid = cellfun (\"isclass\", c, \"struct\");\n        if (! all (valid(:)))\n          error (\"cell2mat: wrong type elements or mixed cells, structs, and matrices\");\n        endif\n      endif\n    endif\n\n    sz = size (c);\n    if (all (cellfun (\"numel\", c)(:) == 1))\n      ## Special case of all scalars\n      m = reshape (cat (1, c{:}), sz);\n    else\n      ## The goal is to minimize the total number of cat() calls.\n      ## The dimensions can be concatenated along in arbitrary order.\n      ## The numbers of concatenations are:\n      ## n / d1\n      ## n / (d1 * d2)\n      ## n / (d1 * d2 * d3)\n      ## etc.\n      ## This is minimized if d1 >= d2 >= d3...\n\n      nd = ndims (c);\n      [~, isz] = sort (sz, \"descend\");\n      for idim = isz\n        if (sz(idim) == 1)\n          continue;\n        endif\n        xdim = [1:idim-1, idim+1:nd];\n        cc = num2cell (c, xdim);\n        c = cellfun (\"cat\", {idim}, cc{:}, \"uniformoutput\", false);\n      endfor\n      m = c{1};\n\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! C = {[1], [2 3 4]; [5; 9], [6 7 8; 10 11 12]};\n%! cell2mat (C)\n\n%!assert (cell2mat ({}), [])\n%!assert (cell2mat ([]), [])\n%!assert (cell2mat (cell (2,0)), zeros (2,0))\n%!test\n%! C = {[1], [2 3 4]; [5; 9], [6 7 8; 10 11 12]};\n%! D = C; D(:,:,2) = C;\n%! E = [1 2 3 4; 5 6 7 8; 9 10 11 12];\n%! F = E; F(:,:,2) = E;\n%! assert (cell2mat (C), E);\n%! assert (cell2mat (D), F);\n%!test\n%! m = rand (10) + i * rand (10);\n%! c = mat2cell (m, [1 2 3 4], [4 3 2 1]);\n%! assert (cell2mat (c), m);\n%!test\n%! m = int8 (256*rand (4, 5, 6, 7, 8));\n%! c = mat2cell (m, [1 2 1], [1 2 2], [3 1 1 1], [4 1 2], [3 1 4]);\n%! assert (cell2mat (c), m);\n%!test\n%! m = {1, 2, 3};\n%! assert (cell2mat (mat2cell (m, 1, [1 1 1])), m);\n\n## cell2mat from cell into another cell\n%!assert (cell2mat ({{\"foo\", \"bar\", \"qux\"}}), {\"foo\", \"bar\", \"qux\"})\n%!assert (cell2mat ({{\"foo\"}, {\"bar\", \"qux\"}}), {\"foo\", \"bar\", \"qux\"})\n%!assert (cell2mat ({{\"foo\"}; {\"bar\"; \"qux\"}}), {\"foo\"; \"bar\"; \"qux\"})\n%!assert (cell2mat ({{\"foo\", \"lol\"}; {\"bar\", \"qux\"}}),\n%!        {\"foo\", \"lol\"; \"bar\", \"qux\"})\n\n## cell2mat cell strings\n%!assert (cell2mat ({\"foo\", \"lol\"; \"bar\", \"qux\"}),\n%!        reshape (\"fboaorlqoulx\", [2 6]))\n\n%!error <Invalid call> cell2mat ()\n%!error <C must be a cell array> cell2mat ([1,2])\n%!error <mixed cells, structs, and matrices> cell2mat ({[1], struct()})\n%!error <mixed cells, structs, and matrices> cell2mat ({[1], {1}})\n%!error <mixed cells, structs, and matrices> cell2mat ({struct(), {1}})\n%!error <dimension mismatch> cell2mat ({{\"foo\"}; {\"bar\", \"qux\"}})\n%!error <dimension mismatch> cell2mat ({\"foox\", \"lol\"; \"bar\", \"qux\"})\n"
  },
  {
    "path": "scripts/general/celldisp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} celldisp (@var{c})\n## @deftypefnx {} {} celldisp (@var{c}, @var{name})\n## Recursively display the contents of a cell array.\n##\n## By default the values are displayed with the name of the variable @var{c}.\n## However, this name can be replaced with the variable @var{name}.  For\n## example:\n##\n## @example\n## @group\n## c = @{1, 2, @{31, 32@}@};\n## celldisp (c, \"b\")\n##    @xresult{}\n##       b@{1@} =\n##        1\n##       b@{2@} =\n##        2\n##       b@{3@}@{1@} =\n##        31\n##       b@{3@}@{2@} =\n##        32\n## @end group\n## @end example\n##\n## @seealso{disp}\n## @end deftypefn\n\n## This is ugly, but seems to be what Matlab does..\n\nfunction celldisp (c, name)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! iscell (c))\n    error (\"celldisp: C must be a cell array\");\n  endif\n\n  if (nargin == 1)\n    name = inputname (1);\n  endif\n\n  for i = 1: numel (c)\n    if (iscell (c{i}))\n      celldisp (c{i}, sprintf (\"%s{%s}\", name, indices (size (c), i)));\n    else\n      disp (sprintf (\"%s{%s} = \\n\", name, indices (size (c), i)));\n      disp (c{i});\n      disp (\"\");\n    endif\n  endfor\n\nendfunction\n\nfunction s = indices (dv, i)\n\n  if (sum (dv != 1) > 1)\n    c = cell (size (dv));\n    [c{:}] = ind2sub (dv, i);\n    s = sprintf (\"%i,\", c{:});\n    s(end) = [];\n  else\n    s = sprintf (\"%i\", i);\n  endif\n\nendfunction\n\n\n%!demo\n%! c = {1, 2, {31, 32}};\n%! celldisp (c, \"b\")\n\n## Test input validation\n%!error <Invalid call> celldisp ()\n%!error celldisp ({}, \"name\", 1)\n%!error <C must be a cell array> celldisp (1)\n"
  },
  {
    "path": "scripts/general/circshift.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} circshift (@var{x}, @var{n})\n## @deftypefnx {} {@var{y} =} circshift (@var{x}, @var{n}, @var{dim})\n## Circularly shift the values of the array @var{x}.\n##\n## @var{n} must be a vector of integers no longer than the number of dimensions\n## in @var{x}.  The values of @var{n} can be either positive or negative, which\n## determines the direction in which the values of @var{x} are shifted.  If an\n## element of @var{n} is zero, then the corresponding dimension of @var{x} will\n## not be shifted.  If @var{n} is a scalar and no @var{dim} is specified then\n## the shift is applied to the first non-singular dimension.\n##\n## If a scalar @var{dim} is given then operate along the specified dimension.\n## In this case @var{n} must be a scalar as well.\n##\n## Examples:\n##\n## @example\n## x = [1, 2, 3;\n##      4, 5, 6;\n##      7, 8, 9];\n## ## positive shift on rows (1st non-singular dim)\n## circshift (x, 1)\n##   @xresult{}\n##        7   8   9\n##        1   2   3\n##        4   5   6\n## ## negative shift on rows (1st non-singular dim)\n## circshift (x, -2)\n##   @xresult{}\n##        7   8   9\n##        1   2   3\n##        4   5   6\n## ## no shift of rows, shift columns by 1 (2nd dimension)\n## circshift (x, [0,1])\n##   @xresult{}\n##        3   1   2\n##        6   4   5\n##        9   7   8\n## ## shift columns (2nd dimension)\n## circshift (x, 1, 2)\n##   @xresult{}\n##        3   1   2\n##        6   4   5\n##        9   7   8\n## @end example\n## @seealso{permute, ipermute, shiftdim}\n## @end deftypefn\n\nfunction y = circshift (x, n, dim)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (isempty (x))\n    y = x;\n    return;\n  endif\n\n  nd = ndims (x);\n  sz = size (x);\n\n  if (nargin == 2)\n    if (isscalar (n))\n      ## Find the first non-singleton dimension.\n      (dim = find (sz > 1, 1)) || (dim = 1);\n      n = [zeros(1, dim-1), n];\n    endif\n  elseif (nargin == 3)\n    if ( ! isscalar (n))\n      error (\"circshift: N must be a scalar when DIM is also specified\");\n    endif\n    n = [zeros(1, dim-1), n];\n  endif\n\n  if (! isvector (n) || length (n) > nd)\n    error (\"circshift: N must be a vector, no longer than the number of dimensions in X\");\n  elseif (any (n != fix (n)))\n    error (\"circshift: all values of N must be integers\");\n  endif\n\n  idx = repmat ({':'}, 1, nd);\n  for i = 1:length (n)\n    b = n(i);\n    d = sz(i);\n    if (b > 0)\n      b = rem (b, d);\n      idx{i} = [d-b+1:d, 1:d-b];\n    elseif (b < 0)\n      b = rem (abs (b), d);\n      idx{i} = [b+1:d, 1:b];\n    endif\n  endfor\n\n  y = x(idx{:});\n\nendfunction\n\n\n%!shared x\n%! x = [1, 2, 3; 4, 5, 6; 7, 8, 9];\n\n%!assert (circshift (x, 1), [7, 8, 9; 1, 2, 3; 4, 5, 6])\n%!assert (circshift (x, -2), [7, 8, 9; 1, 2, 3; 4, 5, 6])\n%!assert (circshift (x, [0, 1]), [3, 1, 2; 6, 4, 5; 9, 7, 8])\n%!assert (circshift ([], 1), [])\n\n%!assert (circshift (eye (3), 1), circshift (eye (3), 1))\n%!assert (circshift (eye (3), 1), [0,0,1;1,0,0;0,1,0])\n\n%!assert (circshift (x, -2, 1), [7, 8, 9; 1, 2, 3; 4, 5, 6])\n%!assert (circshift (x, 1, 2), [3, 1, 2; 6, 4, 5; 9, 7, 8])\n\n%!test <*53178> assert (circshift (1:4, 1), [4 1 2 3])\n%!test <*53178> assert (circshift (1:4, 1, 1), 1:4)\n\n## Test input validation\n%!error <Invalid call> circshift ()\n%!error <Invalid call> circshift (1)\n%!error <N must be a scalar> circshift (1, [2 3], 4)\n%!error <N must be a vector> circshift (1, ones (2,2))\n%!error <no longer than the number of dimensions in X> circshift (1, [1 2 3])\n%!error <all values of N must be integers> circshift (1, 1.5)\n"
  },
  {
    "path": "scripts/general/common_size.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{err}, @var{yi}, @dots{}] =} common_size (@var{xi}, @dots{})\n## Determine if all input arguments are either scalar or of common size.\n##\n## If true, @var{err} is zero, and @var{yi} is a matrix of the common size\n## with all entries equal to @var{xi} if this is a scalar or @var{xi}\n## otherwise.  If the inputs cannot be brought to a common size, @var{err} is\n## 1, and @var{yi} is @var{xi}.  For example:\n##\n## @example\n## @group\n## [err, a, b] = common_size ([1 2; 3 4], 5)\n##      @xresult{} err = 0\n##      @xresult{} a = [ 1, 2; 3, 4 ]\n##      @xresult{} b = [ 5, 5; 5, 5 ]\n## @end group\n## @end example\n##\n## @noindent\n## This is useful for implementing functions where arguments can either be\n## scalars or of common size.\n## @seealso{size, size_equal, numel, ndims}\n## @end deftypefn\n\nfunction [err, varargout] = common_size (varargin)\n\n  if (nargin < 2)\n    error (\"common_size: only makes sense if nargin >= 2\");\n  endif\n\n  ## Find array args\n  array = cellfun (\"numel\", varargin) != 1;\n  aridx = find (array, 1);\n\n  if (isempty (aridx))\n    ## All inputs are scalars\n    err = 0;\n    varargout = varargin;\n  else\n    sz_eq = cellfun (\"size_equal\", varargin, varargin(aridx));\n    if (any (! sz_eq & array))\n      err = 1;\n      varargout = varargin;\n    else\n      err = 0;\n      if (nargout > 1)\n        varargout = varargin;\n        if (any (array))\n          scalar = ! array;\n          dims = size (varargin{aridx});\n          subs = arrayfun (@ones, 1, dims, \"uniformoutput\", false);\n          varargout(scalar) = cellindexmat (varargin(scalar), subs{:});\n        endif\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! m = [1,2;3,4];\n%! [err, a, b, c] = common_size (m, 3, 5);\n%! assert (err, 0);\n%! assert (a, m);\n%! assert (b, [3,3;3,3]);\n%! assert (c, [5,5;5,5]);\n\n%!test\n%! m = [1,2;3,4];\n%! [err, a, b, c] = common_size (m, [], 5);\n%! assert (err, 1);\n%! assert (a, m);\n%! assert (b, []);\n%! assert (c, 5);\n\n## Test input validation\n%!error <only makes sense if nargin .= 2> common_size ()\n%!error <only makes sense if nargin .= 2> common_size (1)\n"
  },
  {
    "path": "scripts/general/cplxpair.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{zsort} =} cplxpair (@var{z})\n## @deftypefnx {} {@var{zsort} =} cplxpair (@var{z}, @var{tol})\n## @deftypefnx {} {@var{zsort} =} cplxpair (@var{z}, @var{tol}, @var{dim})\n## Sort the numbers @var{z} into complex conjugate pairs ordered by increasing\n## real part.\n##\n## The negative imaginary complex numbers are placed first within each pair.\n## All real numbers (those with\n## @code{abs (imag (@var{z})) / abs (@var{z}) < @var{tol}}) are placed after\n## the complex pairs.\n##\n## @var{tol} is a weighting factor in the range [0, 1) which determines the\n## tolerance of the matching.  The default value is @code{100 * eps} and the\n## resulting tolerance for a given complex pair is\n## @code{@var{tol} * abs (@var{z}(i)))}.\n##\n## By default the complex pairs are sorted along the first non-singleton\n## dimension of @var{z}.  If @var{dim} is specified, then the complex pairs are\n## sorted along this dimension.\n##\n## Signal an error if some complex numbers could not be paired.  Signal an\n## error if all complex numbers are not exact conjugates (to within @var{tol}).\n## Note that there is no defined order for pairs with identical real parts but\n## differing imaginary parts.\n## @c Set example in small font to prevent overfull line\n##\n## @smallexample\n## cplxpair (exp (2i*pi*[0:4]'/5)) == exp (2i*pi*[3; 2; 4; 1; 0]/5)\n## @end smallexample\n## @end deftypefn\n\n## 2006-05-12 David Bateman - Modified for NDArrays\n\nfunction zsort = cplxpair (z, tol, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isempty (z))\n    zsort = zeros (size (z));\n    return;\n  endif\n\n  cls = ifelse (isa (z, \"single\"), \"single\", \"double\");\n  if (nargin < 2 || isempty (tol))\n    tol = 100*eps (cls);\n  elseif (! isscalar (tol) || tol < 0 || tol >= 1)\n    error (\"cplxpair: TOL must be a scalar number in the range 0 <= TOL < 1\");\n  endif\n\n  nd = ndims (z);\n  if (nargin < 3)\n    ## Find the first singleton dimension.\n    sz = size (z);\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  else\n    dim = floor (dim);\n    if (dim < 1 || dim > nd)\n      error (\"cplxpair: invalid dimension DIM\");\n    endif\n  endif\n\n  ## Move dimension to analyze to first position, and convert to a 2-D matrix.\n  perm = [dim:nd, 1:dim-1];\n  z = permute (z, perm);\n  sz = size (z);\n  n = sz(1);\n  m = prod (sz) / n;\n  z = reshape (z, n, m);\n\n  ## Sort the sequence in terms of increasing real values.\n  [~, idx] = sort (real (z), 1);\n  z = z(idx + n * ones (n, 1) * [0:m-1]);\n\n  ## Put the purely real values at the end of the returned list.\n  [idxi, idxj] = find (abs (imag (z)) ./ (abs (z) + realmin (cls)) <= tol);\n  ## Force values detected to be real within tolerance to actually be real.\n  z(idxi + n*(idxj-1)) = real (z(idxi + n*(idxj-1)));\n  q = sparse (idxi, idxj, 1, n, m);\n  nr = sum (q, 1);\n  [~, idx] = sort (q, 1);\n  midx = idx + rows (idx) * ones (rows (idx), 1) * [0:columns(idx)-1];\n  z = z(midx);\n  zsort = z;\n\n  ## For each remaining z, place the value and its conjugate at the start of\n  ## the returned list, and remove them from further consideration.\n  for j = 1:m\n    p = n - nr(j);\n    for i = 1:2:p\n      if (i+1 > p)\n        error (\"cplxpair: could not pair all complex numbers\");\n      endif\n      [v, idx] = min (abs (z(i+1:p,j) - conj (z(i,j))));\n      if (v >= tol * abs (z(i,j)))\n        error (\"cplxpair: could not pair all complex numbers\");\n      endif\n      ## For pairs, select the one with positive imaginary part and use it and\n      ## it's conjugate, but list the negative imaginary pair first.\n      if (imag (z(i,j)) > 0)\n        zsort([i, i+1],j) = [conj(z(i,j)), z(i,j)];\n      else\n        zsort([i, i+1],j) = [conj(z(idx+i,j)), z(idx+i,j)];\n      endif\n      z(idx+i,j) = z(i+1,j);\n    endfor\n  endfor\n\n  ## Reshape the output matrix.\n  zsort = ipermute (reshape (zsort, sz), perm);\n\nendfunction\n\n\n%!demo\n%! [ cplxpair(exp(2i*pi*[0:4]'/5)), exp(2i*pi*[3; 2; 4; 1; 0]/5) ]\n\n%!assert (isempty (cplxpair ([])))\n%!assert (cplxpair (1), 1)\n%!assert (cplxpair ([1+1i, 1-1i]), [1-1i, 1+1i])\n%!assert (cplxpair ([1+1i, 1+1i, 1, 1-1i, 1-1i, 2]), ...\n%!                  [1-1i, 1+1i, 1-1i, 1+1i, 1, 2])\n%!assert (cplxpair ([1+1i; 1+1i; 1; 1-1i; 1-1i; 2]), ...\n%!                  [1-1i; 1+1i; 1-1i; 1+1i; 1; 2])\n%!assert (cplxpair ([0, 1, 2]), [0, 1, 2])\n\n%!shared z,y\n%! z = exp (2i*pi*[4; 3; 5; 2; 6; 1; 0]/7);\n%! z(2) = conj (z(1));\n%! z(4) = conj (z(3));\n%! z(6) = conj (z(5));\n%!assert (cplxpair (z(randperm (7))), z)\n%!assert (cplxpair (z(randperm (7))), z)\n%!assert (cplxpair (z(randperm (7))), z)\n%!assert (cplxpair ([z(randperm (7)), z(randperm (7))]), [z,z])\n%!assert (cplxpair ([z(randperm (7)), z(randperm (7))],[],1), [z,z])\n%!assert (cplxpair ([z(randperm (7)).'; z(randperm (7)).'],[],2), [z.';z.'])\n%! y = [ -1-1i; -1+1i;-3; -2; 1; 2; 3];\n%!assert (cplxpair ([z(randperm (7)), y(randperm (7))]), [z,y])\n%!assert (cplxpair ([z(randperm (7)), y(randperm (7)),z(randperm (7))]),\n%!        [z,y,z])\n\n## Test tolerance\n%!assert (cplxpair ([2000 * (1+eps) + 4j; 2000 * (1-eps) - 4j]),\n%!        [(2000 - 4j); (2000 + 4j)], 100*eps(200))\n%!error <could not pair>\n%! cplxpair ([2000 * (1+eps) + 4j; 2000 * (1-eps) - 4j], 0);\n%!error <could not pair>\n%! cplxpair ([2e6 + j; 2e6 - j; 1e-9 * (1 + j); 1e-9 * (1 - 2j)]);\n\n## Test input validation\n%!error <Invalid call> cplxpair ()\n%!error <cplxpair: TOL must be .* scalar number> cplxpair (1, ones (2,2))\n%!error <cplxpair: TOL must be .* in the range 0 <= TOL < 1> cplxpair (1, -1)\n%!error <cplxpair: TOL must be .* in the range 0 <= TOL < 1> cplxpair (1, -1)\n%!error <invalid dimension DIM> cplxpair (1, [], 3)\n"
  },
  {
    "path": "scripts/general/cumtrapz.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} cumtrapz (@var{y})\n## @deftypefnx {} {@var{q} =} cumtrapz (@var{x}, @var{y})\n## @deftypefnx {} {@var{q} =} cumtrapz (@dots{}, @var{dim})\n## Cumulative numerical integration of points @var{y} using the trapezoidal\n## method.\n##\n## @w{@code{cumtrapz (@var{y})}}@ computes the cumulative integral of @var{y}\n## along the first non-singleton dimension.  Where @code{trapz} reports only\n## the overall integral sum, @code{cumtrapz} reports the current partial sum\n## value at each point of @var{y}.\n##\n## When the argument @var{x} is omitted an equally spaced @var{x} vector with\n## unit spacing (1) is assumed.  @code{cumtrapz (@var{x}, @var{y})} evaluates\n## the integral with respect to the spacing in @var{x} and the values in\n## @var{y}.  This is useful if the points in @var{y} have been sampled\n## unevenly.\n##\n## If the optional @var{dim} argument is given, operate along this dimension.\n##\n## Application Note: If @var{x} is not specified then unit spacing will be\n## used.  To scale the integral to the correct value you must multiply by the\n## actual spacing value (deltaX).\n## @seealso{trapz, cumsum}\n## @end deftypefn\n\nfunction z = cumtrapz (x, y, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  have_xy = have_dim = false;\n\n  if (nargin == 3)\n    have_xy = true;\n    have_dim = true;\n  elseif (nargin == 2)\n    if (isscalar (y) && ! isscalar (x))\n      have_dim = true;\n      dim = y;\n    else\n      have_xy = true;\n    endif\n  endif\n\n  if (have_xy)\n    nd = ndims (y);\n    sz = size (y);\n  else\n    nd = ndims (x);\n    sz = size (x);\n  endif\n\n  if (! have_dim)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  else\n    if (!(isscalar (dim) && dim == fix (dim))\n        || !(1 <= dim && dim <= nd))\n      error (\"trapz: DIM must be an integer and a valid dimension\");\n    endif\n  endif\n\n  n = sz(dim);\n  idx1 = idx2 = {':'}(ones (nd, 1));  # repmat ({':'}, [nd, 1]), but faster\n  idx1{dim} = 2 : n;\n  idx2{dim} = 1 : (n - 1);\n\n  if (! have_xy)\n    z = 0.5 * cumsum (x(idx1{:}) + x(idx2{:}), dim);\n  elseif (isscalar (x))\n    z = x * 0.5 * cumsum (y(idx1{:}) + y(idx2{:}), dim);\n  elseif (isvector (x))\n    if (length (x) != n)\n      error (\"cumtrapz: length of X and length of Y along DIM must match\");\n    endif\n      ## Reshape vector to point along dimension DIM\n      shape = ones (nd, 1);\n      shape(dim) = n;\n      x = reshape (x, shape);\n      z = 0.5 * cumsum (diff (x) .* (y(idx1{:}) + y(idx2{:})), dim);\n  else\n    if (! size_equal (x, y))\n      error (\"cumtrapz: X and Y must have same shape\");\n    endif\n    z = 0.5 * cumsum (diff (x, 1, dim) .* (y(idx1{:}) + y(idx2{:})), dim);\n  endif\n\n  sz(dim) = 1;\n  z = cat (dim, zeros (sz), z);\n\nendfunction\n\n\n%!shared x1, x2, y\n%! x1 = [1:5];\n%! x2 = [2:2:10];\n%! y = [1:5];\n%!\n%!assert (cumtrapz (y), [0, 1.5, 4, 7.5, 12])\n%!assert (cumtrapz (y'), [0, 1.5, 4, 7.5, 12]')\n%!assert (cumtrapz (1, y), [0, 1.5, 4, 7.5, 12])\n%!assert (cumtrapz (2, y), [0, 3, 8, 15, 24])\n%!assert (cumtrapz (x1, y),[0, 1.5, 4, 7.5, 12])\n%!assert (cumtrapz (x2, y),[0, 3, 8, 15, 24])\n%!assert (cumtrapz (2, y, 2), [0, 3, 8, 15, 24])\n%!assert (cumtrapz (x2, y, 2), [0, 3, 8, 15, 24])\n%!assert (cumtrapz (y, 1), [0, 0, 0, 0, 0])\n%!assert (cumtrapz (2, y, 1), [0, 0, 0, 0, 0])\n%!assert (cumtrapz (y', 2), [0, 0, 0, 0, 0]')\n\n%!shared x1, x2, y\n%! x1 = [0,0,0;2,2,2];\n%! x2 = [0,2,4;0,2,4];\n%! y = [1,2,3;4,5,6];\n%!\n%!assert (cumtrapz (y), [0,0,0;2.5,3.5,4.5])\n%!assert (cumtrapz (x1, y), [0,0,0;5,7,9])\n%!assert (cumtrapz (y, 1), [0,0,0;2.5,3.5,4.5])\n%!assert (cumtrapz (x1, y, 1), [0,0,0;5,7,9])\n%!assert (cumtrapz (y, 2), [0,1.5,4;0,4.5,10])\n%!assert (cumtrapz (x2, y, 2), [0,3,8;0,9,20])\n\n## Test ND-array implementation\n%!shared x1,x2,y\n%! x1 = 1:3;\n%! x2 = reshape ([0,2,4;0,2,4], [1 2 3]);\n%! y = reshape ([1,2,3;4,5,6], [1 2 3]);\n%!\n%!assert (cumtrapz (y,3), reshape ([0,1.5,4;0,4.5,10],[1 2 3]))\n%!assert (cumtrapz (x1,y,3), reshape ([0,1.5,4;0,4.5,10],[1 2 3]))\n%!assert (cumtrapz (x2,y,3), reshape ([0,3,8;0,9,20],[1 2 3]))\n\n## Test input validation\n%!error <Invalid call> cumtrapz ()\n%!error <DIM must be an integer> cumtrapz (1, 2, [1 2])\n%!error <DIM must be an integer> cumtrapz (1, 2, 1.5)\n%!error <DIM must be .* a valid dimension> cumtrapz (1, 2, 0)\n%!error <length of X and length of Y.*must match> cumtrapz ([1 2], [1 2 3])\n%!error <X and Y must have same shape> cumtrapz (ones (2,3), ones (2,4))\n"
  },
  {
    "path": "scripts/general/curl.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{cx}, @var{cy}, @var{cz}, @var{v}] =} curl (@var{x}, @var{y}, @var{z}, @var{fx}, @var{fy}, @var{fz})\n## @deftypefnx {} {[@var{cz}, @var{v}] =} curl (@var{x}, @var{y}, @var{fx}, @var{fy})\n## @deftypefnx {} {[@dots{}] =} curl (@var{fx}, @var{fy}, @var{fz})\n## @deftypefnx {} {[@dots{}] =} curl (@var{fx}, @var{fy})\n## @deftypefnx {} {@var{v} =} curl (@dots{})\n## Calculate curl of vector field given by the arrays @var{fx}, @var{fy}, and\n## @var{fz} or @var{fx}, @var{fy} respectively.\n## @tex\n## $$ {\\rm curl \\ {\\bf F}}(x,y,z) \\equiv \\nabla \\times {\\rm \\bf F} = \\left( \\frac{\\partial{F_z}}{\\partial{y}} - \\frac{\\partial{F_y}}{\\partial{z}}, \\frac{\\partial{F_x}}{\\partial{z}} - \\frac{\\partial{F_z}}{\\partial{x}}, \\frac{\\partial{F_y}}{\\partial{x}} - \\frac{\\partial{F_x}}{\\partial{y}} \\right)$$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##                   / d         d       d         d       d         d     \\\n## curl F(x,y,z)  =  | -- Fz  -  -- Fy,  -- Fx  -  -- Fz,  -- Fy  -  -- Fx |\n##                   \\ dy        dz      dz        dx      dx        dy    /\n## @end group\n## @end example\n##\n## @end ifnottex\n## The coordinates of the vector field can be given by the arguments @var{x},\n## @var{y}, @var{z} or @var{x}, @var{y} respectively.  @var{v} calculates the\n## scalar component of the angular velocity vector in direction of the z-axis\n## for two-dimensional input.  For three-dimensional input the scalar\n## rotation is calculated at each grid point in direction of the vector field\n## at that point.\n## @seealso{divergence, gradient, del2, cross}\n## @end deftypefn\n\nfunction varargout = curl (varargin)\n\n  fidx = 1;\n  if (nargin == 2)\n    sz = size (varargin{fidx});\n    dx = (1:sz(2))(:);\n    dy = (1:sz(1))(:);\n  elseif (nargin == 3)\n    sz = size (varargin{fidx});\n    dx = (1:sz(2))(:);\n    dy = (1:sz(1))(:);\n    dz = (1:sz(3))(:);\n  elseif (nargin == 4)\n    fidx = 3;\n    dx = varargin{1}(1,:);\n    dy = varargin{2}(:,1);\n  elseif (nargin == 6)\n    fidx = 4;\n    dx = varargin{1}(1,:,1)(:);\n    dy = varargin{2}(:,1,1)(:);\n    dz = varargin{3}(1,1,:)(:);\n  else\n    print_usage ();\n  endif\n\n  if (nargin == 4 || nargin == 2)\n    if (! size_equal (varargin{fidx}, varargin{fidx + 1}))\n      error (\"curl: size of X and Y must match\");\n    elseif (ndims (varargin{fidx}) != 2)\n      error (\"curl: X and Y must be 2-D matrices\");\n    elseif ((length (dx) != columns (varargin{fidx}))\n         || (length (dy) != rows (varargin{fidx})))\n      error (\"curl: size of dx and dy must match the respective dimension of X and Y\");\n    endif\n\n    dFx_dy = gradient (varargin{fidx}.', dy, dx).';\n    dFy_dx = gradient (varargin{fidx + 1}, dx, dy);\n    rot_z = dFy_dx - dFx_dy;\n    av = rot_z / 2;\n    if (nargout == 0 || nargout == 1)\n      varargout{1} = av;\n    else\n      varargout{1} = rot_z;\n      varargout{2} = av;\n    endif\n\n  elseif (nargin == 6 || nargin == 3)\n    if (! size_equal (varargin{fidx}, varargin{fidx + 1}, varargin{fidx + 2}))\n      error (\"curl: size of X, Y, and Z must match\");\n    elseif (ndims (varargin{fidx}) != 3)\n      error (\"curl: X, Y, and Z must be 2-D matrices\");\n    elseif ((length (dx) != size (varargin{fidx}, 2))\n         || (length (dy) != size (varargin{fidx}, 1))\n         || (length (dz) != size (varargin{fidx}, 3)))\n      error (\"curl: size of dx, dy, and dz must match the respective dimesion of X, Y, and Z\");\n    endif\n\n    [~, dFx_dy, dFx_dz] = gradient (varargin{fidx}, dx, dy, dz);\n    [dFy_dx, ~, dFy_dz] = gradient (varargin{fidx + 1}, dx, dy, dz);\n    [dFz_dx, dFz_dy] = gradient (varargin{fidx + 2}, dx, dy, dz);\n    rot_x = dFz_dy - dFy_dz;\n    rot_y = dFx_dz - dFz_dx;\n    rot_z = dFy_dx - dFx_dy;\n    l = sqrt(varargin{fidx}.^2 + varargin{fidx + 1}.^2 + varargin{fidx + 2}.^2);\n    av = (rot_x .* varargin{fidx} +\n          rot_y .* varargin{fidx + 1} +\n          rot_z .* varargin{fidx + 2}) ./ (2 * l);\n\n    if (nargout == 0 || nargout == 1)\n      varargout{1} = av;\n    else\n      varargout{1} = rot_x;\n      varargout{2} = rot_y;\n      varargout{3} = rot_z;\n      varargout{4} = av;\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! [X,Y] = meshgrid (-20:20,-22:22);\n%! av = curl (2*(X-Y), Y);\n%! assert (all (av(:) == 1));\n%! [cz,av] = curl (2*(X-Y), Y);\n%! assert (all (cz(:) == 2));\n%! assert (all (av(:) == 1));\n%! [cz,av] = curl (X/2, Y/2, 2*(X-Y), Y);\n%! assert (all (cz(:) == 4));\n%! assert (all (av(:) == 2));\n%! assert (size_equal (X,Y,cz,av));\n"
  },
  {
    "path": "scripts/general/dblquad.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} dblquad (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb})\n## @deftypefnx {} {@var{q} =} dblquad (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{tol})\n## @deftypefnx {} {@var{q} =} dblquad (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{tol}, @var{quadf})\n## @deftypefnx {} {@var{q} =} dblquad (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{tol}, @var{quadf}, @dots{})\n## Numerically evaluate the double integral of @var{f}.\n##\n## @var{f} is a function handle, inline function, or string containing the name\n## of the function to evaluate.  The function @var{f} must have the form\n## @math{z = f(x,y)} where @var{x} is a vector and @var{y} is a scalar.  It\n## should return a vector of the same length and orientation as @var{x}.\n##\n## @var{xa}, @var{ya} and @var{xb}, @var{yb} are the lower and upper limits of\n## integration for x and y respectively.  The underlying integrator determines\n## whether infinite bounds are accepted.\n##\n## The optional argument @var{tol} defines the absolute tolerance used to\n## integrate each sub-integral.  The default value is 1e-6.\n##\n## The optional argument @var{quadf} specifies which underlying integrator\n## function to use.  Any choice but @code{quad} is available and the default\n## is @code{quadcc}.\n##\n## Additional arguments, are passed directly to @var{f}.  To use the default\n## value for @var{tol} or @var{quadf} one may pass @qcode{':'} or an empty\n## matrix ([]).\n## @seealso{integral2, integral3, triplequad, quad, quadv, quadl, quadgk,\n##          quadcc, trapz}\n## @end deftypefn\n\nfunction q = dblquad (f, xa, xb, ya, yb, tol = 1e-6, quadf = @quadcc, varargin)\n\n  if (nargin < 5)\n    print_usage ();\n  endif\n  if (isempty (tol))\n    tol = 1e-6;\n  endif\n  if (isempty (quadf))\n    quadf = @quadcc;\n  endif\n\n  inner = @__dblquad_inner__;\n  if (ischar (f))\n    f = @(x,y) feval (f, x, y, varargin{:});\n    varargin = {};\n  endif\n\n  q = feval (quadf, @(y) inner (y, f, xa, xb, tol, quadf,\n                                varargin{:}), ya, yb, tol);\n\nendfunction\n\nfunction q = __dblquad_inner__ (y, f, xa, xb, tol, quadf, varargin)\n  q = zeros (size (y));\n  for i = 1 : length (y)\n    q(i) = feval (quadf, @(x) f(x, y(i), varargin{:}), xa, xb, tol);\n  endfor\nendfunction\n\n\n## Nasty integrand to show quadcc off\n%!assert (dblquad (@(x,y) 1 ./ (x+y), 0, 1, 0, 1), 2*log (2), 1e-6)\n\n%!assert (dblquad (@(x,y) exp (-x.^2 - y.^2) , -1, 1, -1, 1, 1e-6, @quadgk),\n%!        pi * erf (1).^2, 1e-6)\n%!assert (dblquad (@(x,y) exp (-x.^2 - y.^2) , -1, 1, -1, 1, 1e-6, @quadl),\n%!        pi * erf (1).^2, 1e-6)\n%!assert (dblquad (@(x,y) exp (-x.^2 - y.^2) , -1, 1, -1, 1, 1e-6, @quadv),\n%!        pi * erf (1).^2, 1e-6)\n"
  },
  {
    "path": "scripts/general/deal.m",
    "content": "########################################################################\n##\n## Copyright (C) 1998-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{r1}, @var{r2}, @dots{}, @var{rn}] =} deal (@var{a})\n## @deftypefnx {} {[@var{r1}, @var{r2}, @dots{}, @var{rn}] =} deal (@var{a1}, @var{a2}, @dots{}, @var{an})\n##\n## Copy the input parameters into the corresponding output parameters.\n##\n## If only a single input parameter is supplied, its value is copied to each\n## of the outputs.\n##\n## For example,\n##\n## @example\n## [a, b, c] = deal (x, y, z);\n## @end example\n##\n## @noindent\n## is equivalent to\n##\n## @example\n## @group\n## a = x;\n## b = y;\n## c = z;\n## @end group\n## @end example\n##\n## @noindent\n## and\n##\n## @example\n## [a, b, c] = deal (x);\n## @end example\n##\n## @noindent\n## is equivalent to\n##\n## @example\n## a = b = c = x;\n## @end example\n##\n## Programming Note: @code{deal} is often used with comma-separated lists\n## derived from cell arrays or structures.  This is unnecessary as the\n## interpreter can perform the same action without the overhead of a function\n## call.  For example:\n##\n## @example\n## @group\n## c = @{[1 2], \"Three\", 4@};\n## [x, y, z] = c@{:@}\n## @xresult{}\n##    x =\n##\n##       1   2\n##\n##    y = Three\n##    z =  4\n## @end group\n## @end example\n## @seealso{cell2struct, struct2cell, repmat}\n## @end deftypefn\n\nfunction varargout = deal (varargin)\n\n  if (nargin == 0)\n    print_usage ();\n  elseif (nargin == 1 || nargin == nargout)\n    varargout(1:nargout) = varargin;\n  else\n    error (\"deal: nargin > 1 and nargin != nargout\");\n  endif\n\nendfunction\n\n\n%!test\n%! [a,b] = deal (1,2);\n%! assert (a, 1);\n%! assert (b, 2);\n%!test\n%! [a,b] = deal (1);\n%! assert (a, 1);\n%! assert (b, 1);\n\n## Test input validation\n%!error <Invalid call> deal ()\n%!error <nargin . 1 and nargin != nargout> y = deal (1, 2)\n"
  },
  {
    "path": "scripts/general/deg2rad.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{rad} =} deg2rad (@var{deg})\n##\n## Convert degrees to radians.\n##\n## The input @var{deg} must be a scalar, vector, or N-dimensional array of\n## double or single floating point values.  @var{deg} may be complex in which\n## case the real and imaginary components are converted separately.\n##\n## The output @var{rad} is the same size and shape as @var{deg} with degrees\n## converted to radians using the conversion constant @code{pi/180}.\n##\n## Example:\n##\n## @example\n## @group\n## deg2rad ([0, 90, 180, 270, 360])\n##   @xresult{}  0.00000   1.57080   3.14159   4.71239   6.28319\n## @end group\n## @end example\n## @seealso{rad2deg}\n## @end deftypefn\n\nfunction rad = deg2rad (deg)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isfloat (deg))\n    error (\"deg2rad: DEG must be a floating point class (double or single)\");\n  endif\n\n  rad = deg * (pi / 180);\n\nendfunction\n\n\n%!assert (deg2rad (0), 0)\n%!assert (deg2rad (90), pi/2)\n%!assert (deg2rad (180), pi)\n%!assert (deg2rad ([0, 90, 180, 270, 360]), pi*[0, 1/2, 1, 3/2, 2])\n\n## Test input validation\n%!error <Invalid call> deg2rad ()\n%!error <DEG must be a floating point class> deg2rad (uint8 (1))\n%!error <DEG must be a floating point class> deg2rad (\"A\")\n"
  },
  {
    "path": "scripts/general/del2.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{L} =} del2 (@var{M})\n## @deftypefnx {} {@var{L} =} del2 (@var{M}, @var{h})\n## @deftypefnx {} {@var{L} =} del2 (@var{M}, @var{dx}, @var{dy}, @dots{})\n##\n## Calculate the discrete Laplace\n## @tex\n## operator $( \\nabla^2 )$.\n## @end tex\n## @ifnottex\n## operator.\n## @end ifnottex\n##\n## For a 2-dimensional matrix @math{M(x, y)} this is defined as\n## @tex\n## $$L = {1 \\over 4} \\left( \\frac{\\partial^2 M}{\\partial{x}^2} + \\frac{\\partial^2 M}{\\partial{y}^2} \\right)$$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##       1    / d^2            d^2         \\\n## L  = --- * | ---  M(x,y) +  ---  M(x,y) |\n##       4    \\ dx^2           dy^2        /\n## @end group\n## @end example\n##\n## @end ifnottex\n## For N-dimensional arrays the sum in parentheses is expanded to include\n## second derivatives over the additional higher dimensions.\n##\n## The spacing between evaluation points may be defined by @var{h}, which is a\n## scalar defining the equidistant spacing in all dimensions.  Alternatively,\n## the spacing in each dimension may be defined separately by @var{dx},\n## @var{dy}, etc.  A scalar spacing argument defines equidistant spacing,\n## whereas a vector argument can be used to specify variable spacing.  The\n## length of the spacing vectors must match the respective dimension of\n## @var{M}.  The default spacing value is 1.\n##\n## Dimensions with fewer than 3 data points are skipped.  Boundary points are\n## calculated from the linear extrapolation of interior points.\n##\n## Example: Second derivative of 2*x^3\n##\n## @example\n## @group\n## f = @@(x) 2*x.^3;\n## dd = @@(x) 12*x;\n## x = 1:6;\n## L = 4*del2 (f(x));\n## assert (L, dd (x));\n## @end group\n## @end example\n##\n## @seealso{gradient, diff}\n## @end deftypefn\n\nfunction L = del2 (M, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  nd = ndims (M);\n  sz = size (M);\n  dx = cell (1, nd);\n  if (nargin == 1)\n    for i = 1 : nd\n      dx(i) = ones (sz(i), 1);\n    endfor\n  elseif (nargin == 2 && isscalar (varargin{1}))\n    h = varargin{1};\n    for i = 1 : nd\n      dx(i) = h * ones (sz(i), 1);\n    endfor\n  elseif (numel (varargin) <= nd)\n    ndx = numel (varargin);\n    varargin(ndx+1:nd) = 1;   # Fill missing dims with 1.\n    ## Reverse dx{1} and dx{2} as the X-dim is the 2nd dim of a meshgrid array\n    varargin([1, 2]) = varargin([2, 1]);\n    for i = 1 : nd\n      arg = varargin{i};\n      if (isscalar (arg))\n        dx(i) = arg * ones (sz(i), 1);\n      elseif (isvector (arg))\n        if (length (arg) != sz(i))\n          error (\"del2: number of elements in spacing vector %d does not match dimension %d of M\", i, i);\n        endif\n        dx(i) = diff (varargin{i})(:);\n      else\n        error (\"del2: spacing element %d must be a scalar or vector\", i);\n      endif\n    endfor\n  else\n    print_usage ();\n  endif\n\n  idx = cell (1, nd);\n  idx(:) = \":\";\n\n  L = zeros (sz);\n  for i = 1 : nd\n    if (sz(i) >= 3)\n      DD = zeros (sz);\n      idx1 = idx2 = idx3 = idx;\n\n      ## interior points\n      idx1{i} = 1 : sz(i) - 2;\n      idx2{i} = 2 : sz(i) - 1;\n      idx3{i} = 3 : sz(i);\n      szi = sz;\n      szi(i) = 1;\n\n      h1 = repmat (shiftdim (dx{i}(1 : sz(i) - 2), 1 - i), szi);\n      h2 = repmat (shiftdim (dx{i}(2 : sz(i) - 1), 1 - i), szi);\n      DD(idx2{:}) = ((M(idx1{:}) - M(idx2{:})) ./ h1 + ...\n                     (M(idx3{:}) - M(idx2{:})) ./ h2) ./ (h1 + h2);\n\n      ## left and right boundary\n      if (sz(i) == 3)\n        DD(idx1{:}) = DD(idx3{:}) = DD(idx2{:});\n      else\n        idx1{i} = 1;\n        idx2{i} = 2;\n        idx3{i} = 3;\n        DD(idx1{:}) = (dx{i}(1) + dx{i}(2)) / dx{i}(2) * DD(idx2{:}) - ...\n            dx{i}(1) / dx{i}(2) * DD(idx3{:});\n\n        idx1{i} = sz(i);\n        idx2{i} = sz(i) - 1;\n        idx3{i} = sz(i) - 2;\n        DD(idx1{:}) = (dx{i}(sz(i) - 1) + dx{i}(sz(i) - 2)) / ...\n            dx{i}(sz(i) - 2) * DD(idx2{:}) - ...\n            dx{i}(sz(i) - 1) / dx{i}(sz(i) - 2) * DD(idx3{:});\n      endif\n\n      L += DD;\n    endif\n  endfor\n\n  L ./= nd;\n\nendfunction\n\n\n## 3x3 constant test\n%!test\n%! a = ones (3,3);\n%! b = del2 (a);\n%! assert (b(:,1), [0.00;0.00;0.00]);\n%! assert (b(:,2), [0.00;0.00;0.00]);\n%! assert (b(:,3), [0.00;0.00;0.00]);\n\n## 3x3 planar test\n%!test\n%! a = [1,2,3;2,3,4;3,4,5];\n%! b = del2 (a);\n%! assert (b(:,1), [0.00;0.00;0.00]);\n%! assert (b(:,2), [0.00;0.00;0.00]);\n%! assert (b(:,3), [0.00;0.00;0.00]);\n\n## 3x3 corner test\n%!test\n%! a = zeros (3,3);\n%! a(1,1) = 1.0;\n%! b = 2*del2 (a);\n%! assert (b(:,1), [1.00;0.50;0.50]);\n%! assert (b(:,2), [0.50;0.00;0.00]);\n%! assert (b(:,3), [0.50;0.00;0.00]);\n%! assert (b, flipud (2*del2 (flipud (a))));\n%! assert (b, fliplr (2*del2 (fliplr (a))));\n%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a))))));\n\n## 3x3 boundary test\n%!test\n%! a = zeros (3,3);\n%! a(2,1)=1.0;\n%! b = 2*del2 (a);\n%! assert (b(:,1), [-1.00;-0.50;-1.00]);\n%! assert (b(:,2), [0.00;0.50;0.00]);\n%! assert (b(:,3), [0.00;0.50;0.00]);\n%! assert (b, flipud (2*del2 (flipud (a))));\n%! assert (b, fliplr (2*del2 (fliplr (a))));\n%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a))))));\n\n## 3x3 center test\n%!test\n%! a = zeros (3,3);\n%! a(2,2) = 1.0;\n%! b = del2 (a);\n%! assert (b(:,1), [0.00;-0.50;0.00]);\n%! assert (b(:,2), [-0.50;-1.00;-0.50]);\n%! assert (b(:,3), [0.00;-0.50;0.00]);\n\n## 4x4 constant test\n%!test\n%! a = ones (4,4);\n%! b = del2 (a);\n%! assert (b(:,1), [0.00;0.00;0.00;0.00]);\n%! assert (b(:,2), [0.00;0.00;0.00;0.00]);\n%! assert (b(:,3), [0.00;0.00;0.00;0.00]);\n%! assert (b(:,4), [0.00;0.00;0.00;0.00]);\n\n## 4x4 planar test\n%!test\n%! a = [1,2,3,4;2,3,4,5;3,4,5,6;4,5,6,7];\n%! b = del2 (a);\n%! assert (b(:,1), [0.00;0.00;0.00;0.00]);\n%! assert (b(:,2), [0.00;0.00;0.00;0.00]);\n%! assert (b(:,3), [0.00;0.00;0.00;0.00]);\n%! assert (b(:,4), [0.00;0.00;0.00;0.00]);\n\n## 4x4 corner test\n%!test\n%! a = zeros (4,4);\n%! a(1,1) = 1.0;\n%! b = 2*del2 (a);\n%! assert (b(:,1), [2.00;0.50;0.00;-0.50]);\n%! assert (b(:,2), [0.50;0.00;0.00;0.00]);\n%! assert (b(:,3), [0.00;0.00;0.00;0.00]);\n%! assert (b(:,4), [-0.50;0.00;0.00;0.00]);\n%! assert (b, flipud (2*del2 (flipud (a))));\n%! assert (b, fliplr (2*del2 (fliplr (a))));\n%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a))))));\n\n## 9x9 center test\n%!test\n%! a = zeros (9,9);\n%! a(5,5) = 1.0;\n%! b = 2*del2 (a);\n%! assert (b(:,1), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]);\n%! assert (b(:,2), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]);\n%! assert (b(:,3), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]);\n%! assert (b(:,4), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]);\n%! assert (b(:,5), [0.00;0.00;0.00;0.50;-2.00;0.50;0.00;0.00;0.00]);\n%! assert (b(:,6), b(:,4));\n%! assert (b(:,7), b(:,3));\n%! assert (b(:,8), b(:,2));\n%! assert (b(:,9), b(:,1));\n\n## 9x9 boundary test\n%!test\n%! a = zeros (9,9);\n%! a(1,5) = 1.0;\n%! b = 2*del2 (a);\n%! assert (b(1,:), [0.00,0.00,0.00,0.50,0.00,0.50,0.00,0.00,0.00]);\n%! assert (b(2,:), [0.00,0.00,0.00,0.00,0.50,0.00,0.00,0.00,0.00]);\n%! assert (b(3:9,:), zeros (7,9));\n%! a(1,5) = 0.0;\n%! a(5,1) = 1.0;\n%! b = 2*del2 (a);\n%! assert (b(:,1), [0.00;0.00;0.00;0.50;0.00;0.50;0.00;0.00;0.00]);\n%! assert (b(:,2), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]);\n%! assert (b(:,3:9), zeros (9,7));\n\n## 9x9 dh center test\n%!test\n%! a = zeros (9,9);\n%! a(5,5) = 1.0;\n%! b = 8*del2 (a,2);\n%! assert (b(:,1:3), zeros (9,3));\n%! assert (b(:,4), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]);\n%! assert (b(:,5), [0.00;0.00;0.00;0.50;-2.00;0.50;0.00;0.00;0.00]);\n%! assert (b(:,6), b(:,4));\n%! assert (b(:,7:9), zeros (9,3));\n\n## 9x9 dx test\n%!test\n%! a = zeros (9,9);\n%! a(5,5) = 1.0;\n%! b = 4*del2 (a,2,1);\n%! assert (b(1:3,:), zeros (3,9));\n%! assert (b(4,:), [0.00;0.00;0.00;0.00;1.00;0.00;0.00;0.00;0.00]');\n%! assert (b(5,:), [0.00;0.00;0.00;0.25;-2.5;0.25;0.00;0.00;0.00]');\n%! assert (b(6,:), b(4,:));\n%! assert (b(7:9,:), zeros (3,9));\n\n## 9x9 dy test\n%!test\n%! a = zeros (9,9);\n%! a(5,5) = 1.0;\n%! b = 4*del2 (a,1,2);\n%! assert (b(:,1:3), zeros (9,3));\n%! assert (b(:,4), [0.00;0.00;0.00;0.00;1.00;0.00;0.00;0.00;0.00]);\n%! assert (b(:,5), [0.00;0.00;0.00;0.25;-2.5;0.25;0.00;0.00;0.00]);\n%! assert (b(:,6), b(:,4));\n%! assert (b(:,7:9), zeros (9,3));\n\n## 3-D test\n%!test\n%! a = zeros (9,9,9);\n%! a(5,5,5) = 1.0;\n%! b = 8*3*del2 (a,2);\n%! assert (b(:,:,1:3), zeros (9,9,3));\n%! assert (b(:,1:3,:), zeros (9,3,9));\n%! assert (b(1:3,:,:), zeros (3,9,9));\n%! assert (b(4:5,4,4), [0.0,0.0]');\n%! assert (b(5,5,4), 1.00);\n%! assert (b(4,4,5), 0.00);\n%! assert (b(5,4,5), 1.00);\n%! assert (b(5,5,5),-6.00);\n%! assert (b, flip (b,1));\n%! assert (b, flip (b,2));\n%! assert (b, flip (b,3));\n\n%!test <*51728>\n%! x = linspace (-2*pi, 2*pi);\n%! U = cos (x);\n%! L = 4*del2 (U, x);\n\n## Test input validation\n%!error <Invalid call> del2 ()\n%!error <Invalid call> del2 (1, 1, 2, 3)\n%!error <in spacing vector 1> del2 (1, 2, [1 1])\n%!error <in spacing vector 2> del2 (1, [1 1], 2)\n%!error <must be a scalar or vector> del2 (1, ones (2,2), 2)\n"
  },
  {
    "path": "scripts/general/divergence.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{div} =} divergence (@var{x}, @var{y}, @var{z}, @var{fx}, @var{fy}, @var{fz})\n## @deftypefnx {} {@var{div} =} divergence (@var{fx}, @var{fy}, @var{fz})\n## @deftypefnx {} {@var{div} =} divergence (@var{x}, @var{y}, @var{fx}, @var{fy})\n## @deftypefnx {} {@var{div} =} divergence (@var{fx}, @var{fy})\n## Calculate divergence of a vector field given by the arrays @var{fx},\n## @var{fy}, and @var{fz} or @var{fx}, @var{fy} respectively.\n## @tex\n## $$\n## {\\rm div \\ {\\bf F}}(x,y,z) \\equiv \\nabla \\cdot {\\rm \\bf F} = \\frac{\\partial F_x}{\\partial x} + \\frac{\\partial F_y}{\\partial y} + \\frac{\\partial F_z}{\\partial z}\n## $$\n##\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##                   d               d               d\n## div F(x,y,z)  =   -- F(x,y,z)  +  -- F(x,y,z)  +  -- F(x,y,z)\n##                   dx              dy              dz\n## @end group\n## @end example\n##\n## @end ifnottex\n## The coordinates of the vector field can be given by the arguments @var{x},\n## @var{y}, @var{z} or @var{x}, @var{y} respectively.\n##\n## @seealso{curl, gradient, del2, dot}\n## @end deftypefn\n\nfunction retval = divergence (varargin)\n\n  fidx = 1;\n  if (nargin == 2)\n    sz = size (varargin{fidx});\n    dx = (1:sz(2))(:);\n    dy = (1:sz(1))(:);\n  elseif (nargin == 3)\n    sz = size (varargin{fidx});\n    dx = 1:sz(2);\n    dy = 1:sz(1);\n    dz = 1:sz(3);\n  elseif (nargin == 4)\n    fidx = 3;\n    dx = varargin{1}(1,:);\n    dy = varargin{2}(:,1);\n  elseif (nargin == 6)\n    fidx = 4;\n    dx = varargin{1}(1,:,1)(:);\n    dy = varargin{2}(:,1,1)(:);\n    dz = varargin{3}(1,1,:)(:);\n  else\n    print_usage ();\n  endif\n\n  if (nargin == 4 || nargin == 2)\n    if (! size_equal (varargin{fidx},varargin{fidx + 1}))\n      error (\"divergence: size of X and Y must match\");\n    elseif (ndims (varargin{fidx}) != 2)\n      error (\"divergence: X and Y must be 2-D matrices\");\n    elseif (length (dx) != columns (varargin{fidx})\n            || length (dy) != rows (varargin{fidx}))\n      error (\"divergence: size of dx and dy must match the respective dimension of X and Y\");\n    endif\n\n    retval = gradient (varargin{fidx}, dx, dy);\n    retval += gradient (varargin{fidx + 1}.', dy, dx).';\n\n  elseif (nargin == 6 || nargin == 3)\n    if (! size_equal (varargin{fidx},varargin{fidx + 1},varargin{fidx + 2}))\n      error (\"divergence: size of X, Y, and Z must match\");\n    elseif (ndims (varargin{fidx}) != 3)\n      error (\"divergence: X, Y, and Z must be 2-D matrices\");\n    elseif ((length (dx) != size (varargin{fidx}, 2))\n         || (length (dy) != size (varargin{fidx}, 1))\n         || (length (dz) != size (varargin{fidx}, 3)))\n      error (\"divergence: size of dx, dy, and dz must match the respective dimesion of X, Y, and Z\");\n    endif\n\n    ## x-direction\n    retval = gradient (varargin{fidx}, dx, dy, dz);\n    ## y-direction\n    retval += shiftdim (gradient (shiftdim (varargin{fidx + 1}, 2), dy), 1);\n    ## z-direction\n    retval += shiftdim (gradient (shiftdim (varargin{fidx + 2}, 1), dz), 2);\n  endif\n\nendfunction\n\n\n%!test\n%! [X,Y] = meshgrid (-20:20,-22:22);\n%! div = divergence (X-Y,Y);\n%! assert (all (div(:) == 2));\n%! assert (size_equal (X,Y,div));\n"
  },
  {
    "path": "scripts/general/flip.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} flip (@var{A})\n## @deftypefnx {} {@var{B} =} flip (@var{A}, @var{dim})\n## Return a copy of array @var{A} flipped across dimension @var{dim}.\n##\n## If @var{dim} is unspecified it defaults to the first non-singleton\n## dimension.\n##\n## Examples:\n##\n## @example\n## ## row vector\n## flip ([1  2  3  4])\n##       @xresult{}  4  3  2  1\n##\n## ## column vector\n## flip ([1; 2; 3; 4])\n##       @xresult{}  4\n##           3\n##           2\n##           1\n##\n## ## 2-D matrix along dimension 1\n## flip ([1 2; 3 4])\n##       @xresult{}  3  4\n##           1  2\n##\n## ## 2-D matrix along dimension 2\n## flip ([1 2; 3 4], 2)\n##       @xresult{}  2  1\n##           4  3\n## @end example\n##\n## @seealso{fliplr, flipud, rot90, rotdim, permute, transpose}\n## @end deftypefn\n\nfunction B = flip (A, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  nd = ndims (A);\n  sz = size (A);\n  if (nargin == 1)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  elseif (! (isscalar (dim) && isindex (dim)))\n    error (\"flip: DIM must be a positive integer\");\n  endif\n\n  idx(1:max(nd, dim)) = {':'};\n  idx{dim} = size (A, dim):-1:1;\n  B = A(idx{:});\n\nendfunction\n\n\n%!assert (flip ([1 2; 3 4], 2), [2 1; 4 3])\n%!assert (flip ([1 2; 3 4], 3), [1 2; 3 4])\n\n## Test defaults\n%!assert (flip ([1 2 3 4]), [4 3 2 1])\n%!assert (flip ([1 2 3 4].'), [4 3 2 1].')\n%!assert (flip ([1 2; 3 4]), flip ([1 2 ; 3 4], 1))\n\n## Test NDArrays\n%!test\n%! a(1:2,1:2,1) = [1 2; 3 4];\n%! a(1:2,1:2,2) = [5 6; 7 8];\n%! b(1:2,1:2,1) = [5 6; 7 8];\n%! b(1:2,1:2,2) = [1 2; 3 4];\n%! assert (flip (a, 3), b);\n\n%!test\n%! a = b = zeros (2, 2, 1, 2);\n%! a(1:2,1:2,:,1) = [1 2; 3 4];\n%! a(1:2,1:2,:,2) = [5 6; 7 8];\n%! b(1:2,1:2,:,1) = [5 6; 7 8];\n%! b(1:2,1:2,:,2) = [1 2; 3 4];\n%! assert (flip (a, 3), a);\n%! assert (flip (a, 4), b);\n%! assert (flip (a, 5), a);\n\n%!error <Invalid call> flip ()\n%!error <DIM must be a positive integer> flip (magic (3), -1)\n"
  },
  {
    "path": "scripts/general/fliplr.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{B} =} fliplr (@var{A})\n## Flip array left to right.\n##\n## Return a copy of @var{A} with the order of the columns reversed.  In other\n## words, @var{A} is flipped left-to-right about a vertical axis.  For example:\n##\n## @example\n## @group\n## fliplr ([1, 2; 3, 4])\n##      @xresult{}  2  1\n##          4  3\n## @end group\n## @end example\n##\n## @seealso{flipud, flip, rot90, rotdim}\n## @end deftypefn\n\nfunction B = fliplr (A)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  B = flip (A, 2);\n\nendfunction\n\n\n%!assert (fliplr ([1, 2; 3, 4]), [2, 1; 4, 3])\n%!assert (fliplr ([1, 2; 3, 4; 5, 6]), [2, 1; 4, 3; 6, 5])\n%!assert (fliplr ([1, 2, 3; 4, 5, 6]), [3, 2, 1; 6, 5, 4])\n%!assert (fliplr ([1 2 3].'), [1 2 3].')\n\n## Test NDArrays\n%!test\n%! a(:,:,1) = [ 1  2;  3  4;  5  6];\n%! a(:,:,2) = [ 7  8;  9 10; 11 12];\n%! b(:,:,1) = [ 2  1;  4  3;  6  5];\n%! b(:,:,2) = [ 8  7; 10  9; 12 11];\n%! assert (fliplr (a), b);\n\n## Test NDArray with singleton dimensions\n%!test\n%! a(:,:,:,1) = [ 1  2;  3  4;  5  6];\n%! a(:,:,:,2) = [ 7  8;  9 10; 11 12];\n%! b(:,:,:,1) = [ 2  1;  4  3;  6  5];\n%! b(:,:,:,2) = [ 8  7; 10  9; 12 11];\n%! assert (fliplr (a), b);\n\n## Test for 1 row, i.e., returns the same\n%!test\n%! a(:,1,:,1) = [ 1  2  3  4];\n%! a(:,1,:,2) = [ 5  6  7  8];\n%! assert (fliplr (a), a);\n\n## Test input validation\n%!error <Invalid call> fliplr ()\n"
  },
  {
    "path": "scripts/general/flipud.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{B} =} flipud (@var{A})\n## Flip array upside down.\n##\n## Return a copy of @var{A} with the order of the rows reversed.  In other\n## words, @var{A} is flipped upside-down about a horizontal axis.  For example:\n##\n## @example\n## @group\n## flipud ([1, 2; 3, 4])\n##      @xresult{}  3  4\n##          1  2\n## @end group\n## @end example\n##\n## @seealso{fliplr, flip, rot90, rotdim}\n## @end deftypefn\n\nfunction B = flipud (A)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n  B = flip (A, 1);\n\nendfunction\n\n\n%!assert (flipud ([1, 2; 3, 4]), [3, 4; 1, 2])\n%!assert (flipud ([1, 2; 3, 4; 5, 6]), [5, 6; 3, 4; 1, 2])\n%!assert (flipud ([1, 2, 3; 4, 5, 6]), [4, 5, 6; 1, 2, 3])\n%!assert (flipud ([1 2 3]), [1 2 3])\n\n## Test NDArrays\n%!test\n%! a(:,:,1) = [ 1  2  3;  4  5  6];\n%! a(:,:,2) = [ 7  8  9; 10 11 12];\n%! b(:,:,1) = [ 4  5  6;  1  2  3];\n%! b(:,:,2) = [10 11 12;  7  8  9];\n%! assert (flipud (a), b);\n\n## Test NDArray with singleton dimensions\n%!test\n%! a(:,:,:,1) = [ 1  2  3;  4  5  6];\n%! a(:,:,:,2) = [ 7  8  9; 10 11 12];\n%! b(:,:,:,1) = [ 4  5  6;  1  2  3];\n%! b(:,:,:,2) = [10 11 12;  7  8  9];\n%! assert (flipud (a), b);\n\n## Test for 1 row, i.e., returns the same\n%!test\n%! a(1,:,:,1) = [ 1  2  3  4];\n%! a(1,:,:,2) = [ 5  6  7  8];\n%! assert (flipud (a), a);\n\n%!error <Invalid call> flipud ()\n"
  },
  {
    "path": "scripts/general/gradient.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{dx} =} gradient (@var{m})\n## @deftypefnx {} {[@var{dx}, @var{dy}, @var{dz}, @dots{}] =} gradient (@var{m})\n## @deftypefnx {} {[@dots{}] =} gradient (@var{m}, @var{s})\n## @deftypefnx {} {[@dots{}] =} gradient (@var{m}, @var{sx}, @var{sy}, @var{sz}, @dots{})\n## @deftypefnx {} {[@dots{}] =} gradient (@var{f}, @var{x0})\n## @deftypefnx {} {[@dots{}] =} gradient (@var{f}, @var{x0}, @var{s})\n## @deftypefnx {} {[@dots{}] =} gradient (@var{f}, @var{x0}, @var{sx}, @var{sy}, @dots{})\n##\n## Calculate the gradient of sampled data or a function.\n## @tex\n## $$\n## {\\rm grad} \\ F(x,y,z) \\equiv \\nabla F = \\frac{\\partial F_x}{\\partial x} \\hat{i} + \\frac{\\partial F_y}{\\partial y} \\hat{j} + \\frac{\\partial F_z}{\\partial z} \\hat{k}\n## $$\n## @end tex\n## @ifnottex\n##\n## @group\n## @verbatim\n##                   d                d                 d\n## grad F(x,y,z)  =  -- F(x,y,z) i  + -- F(x,y,z) j  +  -- F(x,y,z) k\n##                   dx               dy                dz\n## @end verbatim\n## @end group\n##\n## @end ifnottex\n##\n## If @var{m} is a vector, calculate the one-dimensional numerical gradient of\n## @var{m}.  If @var{m} is a matrix the gradient is calculated for each\n## dimension.  The return argument(s) are the estimated partial derivatives\n## for each dimension at the specified sample points.\n##\n## The default spacing of between data points is 1.  A constant spacing between\n## points can be specified with the @var{s} parameter.  If @var{s} is a scalar,\n## the single spacing value is used for all dimensions.  Otherwise, separate\n## values of the spacing can be supplied by the @var{sx}, @dots{} arguments.\n## Scalar values specify an equidistant spacing.  Vector values for the\n## @var{sx}, @dots{} arguments specify the coordinate for that dimension.  The\n## length must match the respective dimension of @var{m}.\n##\n## If the first argument @var{f} is a function handle, the gradient of the\n## function is calculated for the points in @var{x0}.  As with sampled data,\n## the spacing values between the points from which the gradient is estimated\n## can be set via the @var{s} or @var{dx}, @var{dy}, @dots{} arguments.  By\n## default a spacing of 1 is used, however this is normally overly large unless\n## the function is very slowly varying, and it is often necessary to specify a\n## smaller sample spacing.\n##\n## Example: numerical gradient of @code{cos} (analytically = @code{-sin})\n##\n## @example\n## @group\n## gradient (@@cos, pi/2, .1)\n## @xresult{} -0.9983\n## -sin (pi/2)\n## @xresult{} -1\n## @end group\n## @end example\n##\n## Programming Notes:\n## The value for interior data points is approximated using the central\n## difference.\n##\n## @example\n## y'(i) = 1/2 * (y(i+1) - y(i-1)).\n## @end example\n##\n## At boundary points a linear extrapolation is applied.\n##\n## @example\n## y'(1) = y(2) - y(1).\n## @end example\n##\n## @seealso{diff, del2}\n## @end deftypefn\n\nfunction varargout = gradient (m, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  nargout_with_ans = max (1,nargout);\n  if (isnumeric (m))\n    if (! isfloat (m))\n      error (\"gradient: M must be a floating point vector or array\");\n    endif\n    [varargout{1:nargout_with_ans}] = matrix_gradient (m, varargin{:});\n  elseif (is_function_handle (m))\n    [varargout{1:nargout_with_ans}] = handle_gradient (m, varargin{:});\n  elseif (ischar (m))\n    [varargout{1:nargout_with_ans}] = handle_gradient (str2func (m), ...\n                                                       varargin{:});\n  else\n    error (\"gradient: first input must be an array or a function\");\n  endif\n\nendfunction\n\nfunction varargout = matrix_gradient (m, varargin)\n\n  transposed = false;\n  if (isvector (m))\n    ## make a row vector.\n    transposed = (columns (m) == 1);\n    m = m(:).';\n  endif\n\n  nd = ndims (m);\n  sz = size (m);\n  if (length (sz) > 1)\n    tmp = sz(1); sz(1) = sz(2); sz(2) = tmp;\n  endif\n\n  if (nargin > 2 && nargin != nd + 1)\n    print_usage (\"gradient\");\n  endif\n\n  ## cell d stores a spacing vector for each dimension\n  d = cell (1, nd);\n  if (nargin == 1)\n    ## no spacing given - assume 1.0 for all dimensions\n    for i = 1:nd\n      d{i} = ones (sz(i) - 1, 1);\n    endfor\n  elseif (nargin == 2)\n    if (isscalar (varargin{1}))\n      ## single scalar value for all dimensions\n      for i = 1:nd\n        d{i} = varargin{1} * ones (sz(i) - 1, 1);\n      endfor\n    else\n      ## vector for one-dimensional derivative\n      d{1} = diff (varargin{1}(:));\n    endif\n  else\n    ## have spacing value for each dimension\n    if (length (varargin) != nd)\n      error (\"gradient: dimensions and number of spacing values do not match\");\n    endif\n    for i = 1:nd\n      if (isscalar (varargin{i}))\n        d{i} = varargin{i} * ones (sz(i) - 1, 1);\n      else\n        d{i} = diff (varargin{i}(:));\n      endif\n    endfor\n  endif\n\n  m = shiftdim (m, 1);\n  for i = 1:min (nd, nargout)\n    mr = rows (m);\n    mc = numel (m) / mr;\n    Y = zeros (size (m), class (m));\n\n    if (mr > 1)\n      ## Top and bottom boundary.\n      Y(1,:) = diff (m(1:2, :)) / d{i}(1);\n      Y(mr,:) = diff (m(mr-1:mr, :) / d{i}(mr - 1));\n    endif\n\n    if (mr > 2)\n      ## Interior points.\n      Y(2:mr-1,:) = ((m(3:mr,:) - m(1:mr-2,:))\n          ./ kron (d{i}(1:mr-2) + d{i}(2:mr-1), ones (1, mc)));\n    endif\n\n    ## turn multi-dimensional matrix in a way, that gradient\n    ## along x-direction is calculated first then y, z, ...\n\n    if (i == 1)\n      varargout{i} = shiftdim (Y, nd - 1);\n      m = shiftdim (m, nd - 1);\n    elseif (i == 2)\n      varargout{i} = Y;\n      m = shiftdim (m, 2);\n    else\n      varargout{i} = shiftdim (Y, nd - i + 1);\n      m = shiftdim (m, 1);\n    endif\n  endfor\n\n  if (transposed)\n    varargout{1} = varargout{1}.';\n  endif\n\nendfunction\n\nfunction varargout = handle_gradient (f, p0, varargin)\n\n  ## Input checking\n  p0_size = size (p0);\n\n  if (numel (p0_size) != 2)\n    error (\"gradient: the second input argument should either be a vector or a matrix\");\n  endif\n\n  if (any (p0_size == 1))\n    p0 = p0(:);\n    dim = 1;\n    num_points = numel (p0);\n  else\n    num_points = p0_size (1);\n    dim = p0_size (2);\n  endif\n\n  if (length (varargin) == 0)\n    delta = 1;\n  elseif (length (varargin) == 1 || length (varargin) == dim)\n    try\n      delta = [varargin{:}];\n    catch\n      error (\"gradient: spacing parameters must be scalars or a vector\");\n    end_try_catch\n  else\n    error (\"gradient: incorrect number of spacing parameters\");\n  endif\n\n  if (isscalar (delta))\n    delta = repmat (delta, 1, dim);\n  elseif (! isvector (delta))\n    error (\"gradient: spacing values must be scalars or a vector\");\n  endif\n\n  ## Calculate the gradient\n  p0 = mat2cell (p0, num_points, ones (1, dim));\n  varargout = cell (1, dim);\n  for d = 1:dim\n    s = delta(d);\n    df_dx = (f (p0{1:d-1}, p0{d}+s, p0{d+1:end})\n           - f (p0{1:d-1}, p0{d}-s, p0{d+1:end})) ./ (2*s);\n    if (dim == 1)\n      varargout{d} = reshape (df_dx, p0_size);\n    else\n      varargout{d} = df_dx;\n    endif\n  endfor\n\nendfunction\n\n\n%!test\n%! data = [1, 2, 4, 2];\n%! dx = gradient (data);\n%! dx2 = gradient (data, 0.25);\n%! dx3 = gradient (data, [0.25, 0.5, 1, 3]);\n%! assert (dx, [1, 3/2, 0, -2]);\n%! assert (dx2, [4, 6, 0, -8]);\n%! assert (dx3, [4, 4, 0, -1]);\n%! assert (size_equal (data, dx));\n\n%!test\n%! [Y,X,Z,U] = ndgrid (2:2:8,1:5,4:4:12,3:5:30);\n%! [dX,dY,dZ,dU] = gradient (X);\n%! assert (all (dX(:) == 1));\n%! assert (all (dY(:) == 0));\n%! assert (all (dZ(:) == 0));\n%! assert (all (dU(:) == 0));\n%! [dX,dY,dZ,dU] = gradient (Y);\n%! assert (all (dX(:) == 0));\n%! assert (all (dY(:) == 2));\n%! assert (all (dZ(:) == 0));\n%! assert (all (dU(:) == 0));\n%! [dX,dY,dZ,dU] = gradient (Z);\n%! assert (all (dX(:) == 0));\n%! assert (all (dY(:) == 0));\n%! assert (all (dZ(:) == 4));\n%! assert (all (dU(:) == 0));\n%! [dX,dY,dZ,dU] = gradient (U);\n%! assert (all (dX(:) == 0));\n%! assert (all (dY(:) == 0));\n%! assert (all (dZ(:) == 0));\n%! assert (all (dU(:) == 5));\n%! assert (size_equal (dX, dY, dZ, dU, X, Y, Z, U));\n%! [dX,dY,dZ,dU] = gradient (U, 5.0);\n%! assert (all (dU(:) == 1));\n%! [dX,dY,dZ,dU] = gradient (U, 1.0, 2.0, 3.0, 2.5);\n%! assert (all (dU(:) == 2));\n\n%!test\n%! [Y,X,Z,U] = ndgrid (2:2:8,1:5,4:4:12,3:5:30);\n%! [dX,dY,dZ,dU] = gradient (X+j*X);\n%! assert (all (dX(:) == 1+1j));\n%! assert (all (dY(:) == 0));\n%! assert (all (dZ(:) == 0));\n%! assert (all (dU(:) == 0));\n%! [dX,dY,dZ,dU] = gradient (Y-j*Y);\n%! assert (all (dX(:) == 0));\n%! assert (all (dY(:) == 2-j*2));\n%! assert (all (dZ(:) == 0));\n%! assert (all (dU(:) == 0));\n%! [dX,dY,dZ,dU] = gradient (Z+j*1);\n%! assert (all (dX(:) == 0));\n%! assert (all (dY(:) == 0));\n%! assert (all (dZ(:) == 4));\n%! assert (all (dU(:) == 0));\n%! [dX,dY,dZ,dU] = gradient (U-j*1);\n%! assert (all (dX(:) == 0));\n%! assert (all (dY(:) == 0));\n%! assert (all (dZ(:) == 0));\n%! assert (all (dU(:) == 5));\n%! assert (size_equal (dX, dY, dZ, dU, X, Y, Z, U));\n%! [dX,dY,dZ,dU] = gradient (U, 5.0);\n%! assert (all (dU(:) == 1));\n%! [dX,dY,dZ,dU] = gradient (U, 1.0, 2.0, 3.0, 2.5);\n%! assert (all (dU(:) == 2));\n\n%!test\n%! x = 0:10;\n%! f = @cos;\n%! df_dx = @(x) -sin (x);\n%! assert (gradient (f, x), df_dx (x), 0.2);\n%! assert (gradient (f, x, 0.5), df_dx (x), 0.1);\n\n%!test\n%! xy = reshape (1:10, 5, 2);\n%! f = @(x,y) sin (x) .* cos (y);\n%! df_dx = @(x, y) cos (x) .* cos (y);\n%! df_dy = @(x, y) -sin (x) .* sin (y);\n%! [dx, dy] = gradient (f, xy);\n%! assert (dx, df_dx (xy (:, 1), xy (:, 2)), 0.1);\n%! assert (dy, df_dy (xy (:, 1), xy (:, 2)), 0.1);\n\n## Test input validation\n%!error <Invalid call> gradient ()\n%!error <M must be a floating point vector or array> gradient (int8 ([1 2 3]))\n"
  },
  {
    "path": "scripts/general/idivide.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{C} =} idivide (@var{A}, @var{B}, @var{op})\n## Integer division with different rounding rules.\n##\n## The standard behavior of integer division such as @code{@var{A} ./ @var{B}}\n## is to round the result to the nearest integer.  This is not always the\n## desired behavior and @code{idivide} permits integer element-by-element\n## division to be performed with different treatment for the fractional\n## part of the division as determined by the @var{op} flag.  @var{op} is\n## a string with one of the values:\n##\n## @table @asis\n## @item @qcode{\"fix\"}\n## Calculate @code{@var{A} ./ @var{B}} with the fractional part rounded\n## towards zero.\n##\n## @item @qcode{\"round\"}\n## Calculate @code{@var{A} ./ @var{B}} with the fractional part rounded\n## towards the nearest integer.\n##\n## @item @qcode{\"floor\"}\n## Calculate @code{@var{A} ./ @var{B}} with the fractional part rounded\n## towards negative infinity.\n##\n## @item @qcode{\"ceil\"}\n## Calculate @code{@var{A} ./ @var{B}} with the fractional part rounded\n## towards positive infinity.\n## @end table\n##\n## @noindent\n## If @var{op} is not given it defaults to @qcode{\"fix\"}.\n## An example demonstrating these rounding rules is\n##\n## @example\n## @group\n## idivide (int8 ([-3, 3]), int8 (4), \"fix\")\n##   @xresult{}   0   0\n## idivide (int8 ([-3, 3]), int8 (4), \"round\")\n##   @xresult{}  -1   1\n## idivide (int8 ([-3, 3]), int8 (4), \"floor\")\n##   @xresult{}  -1   0\n## idivide (int8 ([-3, 3]), int8 (4), \"ceil\")\n##   @xresult{}   0   1\n## @end group\n## @end example\n##\n## @seealso{ceil, floor, fix, round, ldivide, rdivide}\n## @end deftypefn\n\nfunction C = idivide (A, B, op)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (nargin == 2)\n    op = \"fix\";\n  else\n    op = lower (op);\n  endif\n\n  if (! isinteger (A) && ! isinteger (B))\n    error (\"idivide: at least one input (A or B) must be an integer type\");\n  elseif (isinteger (A) && isinteger (B) && ! strcmp (class (A), class (B)))\n    error (\"idivide: integer type of A (%s) must match integer type of B (%s)\",\n           class (A), class (B));\n  endif\n\n  C = A ./ B;\n  if (strcmp (op, \"fix\"))\n    ## The following is an optimized version of `C -= (C .* B > A) .* sign (B)`.\n    if (isscalar (B))\n      if (B > 0)\n        C -= (C * B > A);\n      else\n        C += (C * B > A);\n      endif\n    else\n      y_sel = (B > 0);\n      if (isscalar (A))\n        C(y_sel) -= (C(y_sel) .* B(y_sel) > A);\n        y_sel = ! y_sel;\n        C(y_sel) += (C(y_sel) .* B(y_sel) > A);\n      else\n        C(y_sel) -= (C(y_sel) .* B(y_sel) > A(y_sel));\n        y_sel = ! y_sel;\n        C(y_sel) += (C(y_sel) .* B(y_sel) > A(y_sel));\n      endif\n    endif\n  elseif (strcmp (op, \"round\"))\n    return;\n  elseif (strcmp (op, \"floor\"))\n    ## The following is an optimized version of `C -= (C .* abs (B) > sign (B) .* A)`.\n    if (isscalar (B))\n      if (B > 0)\n        C -= (C * B > A);\n      else\n        C -= (C * B < A);\n      endif\n    else\n      y_sel = (B > 0);\n      if (isscalar (A))\n        C(y_sel) -= (C(y_sel) .* B(y_sel) > A);\n        y_sel = ! y_sel;\n        C(y_sel) -= (C(y_sel) .* B(y_sel) < A);\n      else\n        C(y_sel) -= (C(y_sel) .* B(y_sel) > A(y_sel));\n        y_sel = ! y_sel;\n        C(y_sel) -= (C(y_sel) .* B(y_sel) < A(y_sel));\n      endif\n    endif\n  elseif (strcmp (op, \"ceil\"))\n    ## The following is an optimized version of `C += (C .* abs (B) < sign (B) .* A)`.\n    if (isscalar (B))\n      if (B > 0)\n        C += (C * B < A);\n      else\n        C += (C * B > A);\n      endif\n    else\n      y_sel = (B > 0);\n      if (isscalar (A))\n        C(y_sel) += (C(y_sel) .* B(y_sel) < A);\n        y_sel = ! y_sel;\n        C(y_sel) += (C(y_sel) .* B(y_sel) > A);\n      else\n        C(y_sel) += (C(y_sel) .* B(y_sel) < A(y_sel));\n        y_sel = ! y_sel;\n        C(y_sel) += (C(y_sel) .* B(y_sel) > A(y_sel));\n      endif\n    endif\n  else\n    error ('idivide: unrecognized rounding type \"%s\"', op);\n  endif\n\nendfunction\n\n\n%!shared a, af, b, bf\n%! a = int8 (3);\n%! af = 3;\n%! b = int8 ([-4, 4]);\n%! bf = [-4, 4];\n\n%!assert (idivide (a, b), int8 ([0, 0]))\n%!assert (idivide (a, b, \"floor\"), int8 ([-1, 0]))\n%!assert (idivide (a, b, \"ceil\"), int8 ([0, 1]))\n%!assert (idivide (a, b, \"round\"), int8 ([-1, 1]))\n\n%!assert (idivide (af, b), int8 ([0, 0]))\n%!assert (idivide (af, b, \"floor\"), int8 ([-1, 0]))\n%!assert (idivide (af, b, \"ceil\"), int8 ([0, 1]))\n%!assert (idivide (af, b, \"round\"), int8 ([-1, 1]))\n\n%!assert (idivide (a, bf), int8 ([0, 0]))\n%!assert (idivide (a, bf, \"floor\"), int8 ([-1, 0]))\n%!assert (idivide (a, bf, \"ceil\"), int8 ([0, 1]))\n%!assert (idivide (a, bf, \"round\"), int8 ([-1, 1]))\n\n%!shared c, d\n%! c = int64 (4e16);\n%! d = int64 ([-2e8, 2e8]);\n\n%!assert <*61319> (idivide (c, d + int64 (1)), d + int64 ([-1, -1]))\n%!assert <*61319> (idivide (c, d + int64 (1), \"floor\"), d + int64 ([-2, -1]))\n%!assert <*61319> (idivide (c, d + int64 (1), \"ceil\"), d + int64 ([-1, 0]))\n%!assert <*61319> (idivide (c, d + int64 (1), \"round\"), d + int64 ([-1, -1]))\n\n%!assert <*61319> (idivide (c + int64 (1), d), d)\n%!assert <*61319> (idivide (c + int64 (1), d, \"floor\"), d + int64 ([-1, 0]))\n%!assert <*61319> (idivide (c + int64 (1), d, \"ceil\"), d + int64 ([0, 1]))\n%!assert <*61319> (idivide (c + int64 (1), d, \"round\"), d)\n\n## Test input validation\n%!error idivide (uint8 (1))\n%!error idivide (uint8 (1), 2, 3)\n%!error <at least one input> idivide (1, 2)\n%!error <at least one input> idivide ({1}, 2)\n%!error <A \\(int8\\) must match.* B \\(uint8\\)> idivide (int8 (1), uint8 (2))\n%!error <unrecognized rounding type \"foo\"> idivide (int8 (1), 2, \"foo\")\n"
  },
  {
    "path": "scripts/general/int2str.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{str} =} int2str (@var{n})\n## Convert an integer (or array of integers) to a string (or a character\n## array).\n##\n## @example\n## @group\n## int2str (123)\n##   @xresult{} 123\n##\n## s = int2str ([1, 2, 3; 4, 5, 6])\n##   @xresult{} s =\n##         1  2  3\n##         4  5  6\n##\n## whos s\n##   @xresult{} Variables in the current scope:\n##         Attr Name        Size                     Bytes  Class\n##         ==== ====        ====                     =====  =====\n##              s           2x7                         14  char\n##      Total is 14 elements using 14 bytes\n## @end group\n## @end example\n##\n## This function is not very flexible.  For better control over the\n## results, use @code{sprintf} (@pxref{Formatted Output}).\n##\n## Programming Notes:\n##\n## Non-integers are rounded to integers before display.  Only the real part\n## of complex numbers is displayed.\n##\n## @seealso{sprintf, num2str, mat2str}\n## @end deftypefn\n\nfunction str = int2str (n)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! (isnumeric (n) || islogical (n) || ischar (n)))\n    error (\"int2str: N must be a numeric, logical, or character array\");\n  endif\n\n  if (ischar (n))\n    str = n;\n    return;\n  elseif (isempty (n))\n    str = \"\";\n    return;\n  endif\n\n  n = round (real (n));\n\n  ## Set up a suitable format string while ignoring Inf/NaN entries\n  nan_inf = ! isfinite (n(:));\n  ndgt = floor (log10 (max (abs (n(! nan_inf)))));\n  if (isempty (ndgt) || ndgt == -Inf)\n    ndgt = 0;  # All Inf or all zero array\n  endif\n\n  ndgt += 3;\n  if (any (nan_inf))\n    ndgt = max (ndgt, 5);\n  endif\n\n  ## FIXME: Integers should be masked to show only 16 significant digits\n  fmt = sprintf (\"%%%d.0f\", ndgt);\n\n  nd = ndims (n);\n  nc = columns (n) * (nd - 1);    # N-D arrays are expanded in columns\n  n  = permute (n, [2, 3:nd, 1]);\n  fmt = [repmat(fmt, 1, nc), \"\\n\"];\n  strtmp = sprintf (fmt, n);\n  str = strtrim (char (ostrsplit (strtmp, \"\\n\", true)));\n\nendfunction\n\n\n%!assert (int2str (123), \"123\")\n%!assert (int2str (-123), \"-123\")\n%!assert (int2str (1.2), \"1\")\n%!assert (int2str (1.6), \"2\")\n%!assert (int2str ([1, 2, 3; 4, 5, 6]), [\"1  2  3\";\"4  5  6\"])\n%!assert (int2str ([]), \"\")\n\n%!error <Invalid call> int2str ()\n%!error <N must be a numeric> int2str ({1})\n"
  },
  {
    "path": "scripts/general/integral.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} integral (@var{f}, @var{a}, @var{b})\n## @deftypefnx {} {@var{q} =} integral (@var{f}, @var{a}, @var{b}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {[@var{q}, @var{err}] =} integral (@dots{})\n##\n## Numerically evaluate the integral of @var{f} from @var{a} to @var{b} using\n## adaptive quadrature.\n##\n## @code{integral} is a wrapper for @code{quadcc} (general real-valued, scalar\n## integrands and limits), and @code{quadgk} (integrals with specified\n## integration paths and array-valued integrands) that is intended to provide\n## @sc{matlab} compatibility.  More control of the numerical integration may be\n## achievable by calling the various quadrature functions directly.\n##\n## @var{f} is a function handle, inline function, or string containing the name\n## of the function to evaluate.  The function @var{f} must be vectorized and\n## return a vector of output values when given a vector of input values.\n##\n## @var{a} and @var{b} are the lower and upper limits of integration.  Either\n## or both limits may be infinite or contain weak end singularities.  If either\n## or both limits are complex, @code{integral} will perform a straight line\n## path integral.  Alternatively, a complex domain path can be specified using\n## the @qcode{\"Waypoints\"} option (see below).\n##\n## Additional optional parameters can be specified using\n## @qcode{\"@var{property}\", @var{value}} pairs.  Valid properties are:\n##\n## @table @code\n## @item Waypoints\n## Specifies points to be used in defining subintervals of the quadrature\n## algorithm, or if @var{a}, @var{b}, or @var{waypoints} are complex then\n## the quadrature is calculated as a contour integral along a piecewise\n## continuous path.  For more detail, @pxref{XREFquadgk,,@code{quadgk}}.\n##\n## @item ArrayValued\n## @code{integral} expects @var{f} to return a scalar value unless\n## @var{arrayvalued} is specified as true.  This option will cause\n## @code{integral} to perform the integration over the entire array and return\n## @var{q} with the same dimensions as returned by @var{f}.  For more detail\n## @pxref{XREFquadgk,,@code{quadgk}}.\n##\n## @item AbsTol\n## Define the absolute error tolerance for the quadrature.  The default\n## absolute tolerance is 1e-10 (1e-5 for single).\n##\n## @item RelTol\n## Define the relative error tolerance for the quadrature.  The default\n## relative tolerance is 1e-6 (1e-4 for single).\n## @end table\n##\n## The optional output @var{err} contains the absolute error estimate used by\n## the called integrator.\n##\n## Adaptive quadrature is used to minimize the estimate of error until the\n## following is satisfied:\n## @tex\n## $$error \\leq \\max \\left( AbsTol, RelTol\\cdot\\vert q\\vert \\right)$$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##   @var{error} <= max (@var{AbsTol}, @var{RelTol}*|@var{q}|).\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## Known @sc{matlab} incompatibilities:\n##\n## @enumerate\n## @item\n## If tolerances are left unspecified, and any integration limits or waypoints\n## are of type @code{single}, then Octave's integral functions automatically\n## reduce the default absolute and relative error tolerances as specified\n## above.  If tighter tolerances are desired they must be specified.\n## @sc{matlab} leaves the tighter tolerances appropriate for @code{double}\n## inputs in place regardless of the class of the integration limits.\n## @end enumerate\n##\n## @seealso{integral2, integral3, quad, quadgk, quadv, quadl, quadcc, trapz,\n##          dblquad, triplequad}\n## @end deftypefn\n\nfunction [q, err] = integral (f, a, b, varargin)\n\n  if (nargin < 3 || (mod (nargin, 2) == 0))\n    print_usage ();\n  endif\n\n  error_flag = (nargout == 2);\n\n  ## quadcc can't handle complex limits or integrands, but quadgk can.\n  ## Check for simple cases of complex limits and integrand.\n  f_is_complex = false;\n  if (iscomplex (a) || iscomplex (b))\n    f_is_complex = true;\n  elseif (iscomplex (feval (f, a)) || iscomplex (feval (f, b)))\n    f_is_complex = true;\n  endif\n\n  if (nargin == 3)\n    ## Pass the simplest case directly to general integrator.\n    ## Let quadcc function handle input checks on function and limits.\n    if (! f_is_complex)\n      try\n        if (error_flag)\n          [q, err] = quadcc (f, a, b);\n        else\n          q = quadcc (f, a, b);\n        endif\n      catch quaderror\n        if (strcmp (quaderror.message,\n                \"quadcc: integrand F must return a single, real-valued vector\"))\n          if (error_flag)\n            [q, err] = quadgk (f, a, b);\n          else\n            q = quadgk (f, a, b);\n          endif\n        else\n          error (quaderror.message);\n        endif\n      end_try_catch\n\n    else\n      ## Complex-valued integral\n      if (error_flag)\n        [q, err] = quadgk (f, a, b);\n      else\n        q = quadgk (f, a, b);\n      endif\n    endif\n\n  else\n    ## Parse options to determine how to call integrator.\n    abstol = [];\n    reltol = [];\n    waypoints = [];\n    arrayvalued = false;\n    use_quadgk = false;\n\n    idx = 1;\n    while (idx < nargin - 3)\n      prop = varargin{idx++};\n      if (! ischar (prop))\n        error (\"integral: property PROP must be a string\");\n      endif\n\n      switch (lower (prop))\n        case \"reltol\"\n          reltol = varargin{idx++};\n        case \"abstol\"\n          abstol = varargin{idx++};\n        case \"waypoints\"\n          waypoints = varargin{idx++}(:);\n          use_quadgk = true;\n        case \"arrayvalued\"\n          arrayvalued = varargin{idx++};\n          use_quadgk = true;\n        otherwise\n          error (\"integral: unknown property '%s'\", prop);\n      endswitch\n    endwhile\n\n    issingle = (isa (a, \"single\") || isa (b, \"single\")\n                || isa (waypoints, \"single\"));\n\n    if (isempty (abstol))\n      abstol = ifelse (issingle, 1e-5, 1e-10);\n    endif\n    if (isempty (reltol))\n      reltol = ifelse (issingle, 1e-4, 1e-6);\n    endif\n\n    if (use_quadgk)\n      ## Array valued functions or waypoint definitions require quadgk\n      ## no need to test for complex components\n      if (error_flag)\n        [q, err] = quadgk (f, a, b, \"AbsTol\", abstol, \"RelTol\", reltol,\n                            \"WayPoints\", waypoints, \"ArrayValued\", arrayvalued);\n      else\n        q = quadgk (f, a, b, \"AbsTol\", abstol, \"RelTol\", reltol,\n                            \"WayPoints\", waypoints, \"ArrayValued\", arrayvalued);\n      endif\n\n    else\n      ## otherwise try quadcc first, switch to quadgk if complex test fails\n      if (! f_is_complex)\n        try\n          if (error_flag)\n            [q, err] = quadcc (f, a, b, [abstol, reltol]);\n          else\n            q = quadcc (f, a, b, [abstol, reltol]);\n          endif\n        catch quaderror\n          if (strcmp (quaderror.message,\n                \"quadcc: integrand F must return a single, real-valued vector\"))\n            if (error_flag)\n              [q, err] = quadgk (f, a, b, \"AbsTol\", abstol, \"RelTol\", reltol);\n            else\n              q = quadgk (f, a, b, \"AbsTol\", abstol, \"RelTol\", reltol);\n            endif\n          else\n            error (quaderror.message);\n          endif\n        end_try_catch\n      else\n        ## Complex-valued integral\n        if (error_flag)\n          [q, err] = quadgk (f, a, b, \"AbsTol\", abstol, \"RelTol\", reltol);\n        else\n          q = quadgk (f, a, b, \"AbsTol\", abstol, \"RelTol\", reltol);\n        endif\n      endif\n    endif\n  endif\n\nendfunction\n\n\n## Matlab compatibility tests\n%!test\n%! f = @(x) exp (-x.^2) .* log (x).^2;\n%! emgamma = 0.57721566490153286;\n%! exact = (sqrt (pi)*(8*log (2)^2+8*emgamma*log (2)+pi^2+2*emgamma^2))/16;\n%! assert (integral (f, 0, Inf), exact, -1e-6);\n%! assert (integral (f, 0, Inf, \"RelTol\", 1e-12), exact, -1e-12);\n\n%!test  # with parameter\n%! f = @(x, c) 1 ./ (x.^3 - 2*x - c);\n%! assert (integral (@(x) f(x,5), 0, 2), -0.4605015338467329, 1e-10);\n\n%!test  # with tolerances\n%! f = @(x) log (x);\n%! assert (integral (@(x) f(x), 0, 1, \"AbsTol\", 1e-6), -1, 1e-6);\n\n%!test  # waypoints\n%! f = @(x) 1./(2.*x-1);\n%! assert (integral (f, 0, 0, \"Waypoints\", [1+1i, 1-1i]), -pi*1i, 1e-10);\n\n%!test  # an array-valued function\n%! f = @(x) sin ((1:5)*x);\n%! assert (integral (f, 0, 1, \"ArrayValued\", true), 1./[1:5]-cos(1:5)./[1:5],\n%!         1e-10);\n\n%!test  # test single input/output\n%! assert (integral (@sin, 0, 1), cos (0)-cos (1), 1e-10);\n%! assert (class (integral (@sin, single (0), 1)), \"single\");\n%! assert (class (integral (@sin, 0, single (1))), \"single\");\n%! assert (class (integral (@sin, single (0), single (1))), \"single\");\n%! assert (integral (@sin, 0, 1, \"Waypoints\", 0.5), cos (0)-cos (1), 1e-10);\n%! assert (class (integral (@sin, 0, 1, \"Waypoints\", single (0.5))), \"single\");\n%! assert (class (integral (@sin, single (0), 1, \"Waypoints\", 0.5)), \"single\");\n%! assert (class (integral (@sin, 0, single (1), \"Waypoints\", 0.5)), \"single\");\n\n%!test  # test complex argument handling\n%! f = @(x) round (exp (i*x));\n%! assert (integral (f, 0, pi), quadgk (f, 0, pi), eps);\n%! assert (integral (f, -1, 1), 2, 5*eps);\n%! assert (integral (@sin, -i, i), 0, eps);\n%! assert (1.5 * integral (@sqrt, -1, 0), i, eps);\n\n%!test\n%! f = @(x) x.^5 .* exp (-x) .* sin (x);\n%! assert (integral (f, 0, inf, \"RelTol\", 1e-8, \"AbsTol\", 1e-12), -15, -1e-8);\n\n## tests from quadcc\n%!assert (integral (@sin, -pi, pi), 0, 1e-10)\n%!assert (integral (inline (\"sin\"), -pi, pi), 0, 1e-10)\n%!assert (integral (\"sin\", -pi, pi), 0, 1e-10)\n%!assert (integral (@sin, -pi, 0), -2, 1e-10)\n%!assert (integral (@sin, 0, pi), 2, 1e-10)\n%!assert (integral (@(x) 1./(sqrt (x).*(x+1)), 0, Inf), pi, -1e-6)\n%!assert (integral (@(x) 1./(sqrt (x).*(x+1)), 0, Inf,\n%!                  \"AbsTol\", 0, \"RelTol\", 1e-8),\n%!        pi, -1e-8)\n%!assert (integral (@(x) exp (-x .^ 2), -Inf, Inf), sqrt (pi), 1e-10)\n%!assert (integral (@(x) exp (-x .^ 2), -Inf, 0), sqrt (pi)/2, 1e-10)\n\n## tests from quadgk\n%!assert (integral (@sin,-pi,pi, \"WayPoints\",0, \"AbsTol\",1e-6, \"RelTol\",1e-3),\n%!        0, 1e-6)\n%!assert (integral (@(x) abs (1 - x.^2), 0, 2, \"Waypoints\", 1), 2, 1e-10)\n%!assert (integral (@(z) log (z),1+1i,1+1i, \"WayPoints\", [1-1i, -1,-1i, -1+1i]),\n%!        complex (0, pi), 1e-10)\n\n## Test vector-valued functions\n%!assert (integral (@(x) [(sin (x)), (sin (2*x))], 0, pi, \"ArrayValued\", 1),\n%!        [2, 0], 1e-10)\n\n## Test matrix-valued functions\n%!assert (integral (@(x) [x,x,x; x,exp(x),x; x,x,x], 0, 1, \"ArrayValued\", 1),\n%!                    [0.5,0.5,0.5; 0.5,(exp (1) - 1),0.5; 0.5,0.5,0.5], 1e-10);\n\n## Test combined parameters\n%!assert (integral (@(x) [sin(x), cos(x)], 0, pi, \"ArrayValued\", 1,\n%!                   \"Waypoints\", [0.5]), [2, 0], 2*eps);\n\n## Test 2nd output\n%!test <*62412>\n%! [~, err] = integral (@(x) ones (size (x)), 0, 1);  # quadcc\n%! assert (err, 0, 5*eps);  # err ~3e-16\n%! [~, err] = integral (@(x) ones (size (x)), 0, 1, \"waypoints\", 1);  # quadgk\n%! assert (err, 0, 1000*eps);  # err ~7e-14\n%! [~, err] = integral (@(x) ones (size (x)), 0, 1, \"arrayvalued\", true);  # quadgk\n%! assert (err, 0, 1000*eps);  # err ~7e-14\n\n## Test input validation\n%!error integral (@sin)\n%!error integral (@sin, 0)\n%!error integral (@sin, 0, 1, 1e-6, true, 4)\n%!error integral (@sin, 0, 1, \"DummyArg\")\n%!error <property PROP must be a string> integral (@sin, 0, 1, 2, 3)\n%!error <unknown property 'foo'> integral (@sin, 0, 1, \"foo\", 3)\n%!error integral (@sin, 0, 1, \"AbsTol\", ones (2,2))\n%!error integral (@sin, 0, 1, \"AbsTol\", -1)\n%!error integral (@sin, 0, 1, \"RelTol\", ones (2,2))\n%!error integral (@sin, 0, 1, \"RelTol\", -1)\n"
  },
  {
    "path": "scripts/general/integral2.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} integral2 (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb})\n## @deftypefnx {} {@var{q} =} integral2 (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {[@var{q}, @var{err}] =} integral2 (@dots{})\n##\n## Numerically evaluate the two-dimensional integral of @var{f} using adaptive\n## quadrature over the two-dimensional domain defined by @var{xa}, @var{xb},\n## @var{ya}, @var{yb} (scalars may be finite or infinite).  Additionally,\n## @var{ya} and @var{yb} may be scalar functions of @var{x}, allowing for\n## integration over non-rectangular domains.\n##\n## @var{f} is a function handle, inline function, or string containing the\n## name of the function to evaluate.  The function @var{f} must be of the form\n## @math{z = f(x,y)}, and all operations must be vectorized such that @var{x}\n## and @var{y} accept array inputs and return array outputs of the same size.\n## (It can be assumed that @var{x} and @var{y} will either be same-size arrays\n## or one will be a scalar.)  The underlying integrators will input arrays of\n## integration points into @var{f} and/or use internal vector expansions to\n## speed computation that can produce unpredictable results if @var{f} is not\n## restricted to elementwise operations.  For integrands where this is\n## unavoidable, the @qcode(\"Vectorized\") option described below may produce\n## more reliable results.\n##\n## Additional optional parameters can be specified using\n## @qcode{\"@var{property}\", @var{value}} pairs.  Valid properties are:\n##\n## @table @code\n## @item AbsTol\n## Define the absolute error tolerance for the quadrature.  The default\n## value is 1e-10 (1e-5 for single).\n##\n## @item RelTol\n## Define the relative error tolerance for the quadrature.  The default\n## value is 1e-6 (1e-4 for single).\n##\n## @item Method\n## Specify the two-dimensional integration method to be used, with valid\n## options being @qcode{\"auto\"} (default), @qcode{\"tiled\"}, or\n## @qcode{\"iterated\"}.  When using @qcode{\"auto\"}, Octave will choose the\n## @qcode{\"tiled\"} method unless any of the integration limits are infinite.\n##\n## @item Vectorized\n## Enable or disable vectorized integration.  A value of @code{false} forces\n## Octave to use only scalar inputs when calling the integrand, which enables\n## integrands @math{f(x,y)} that have not been vectorized or only accept\n## scalar values of @var{x} or @var{y}.  The default value is @code{true}.\n## Note that this is achieved by wrapping @math{f(x,y)} with the function\n## @code{arrayfun}, which may significantly decrease computation speed.\n## @end table\n##\n## Adaptive quadrature is used to minimize the estimate of error until the\n## following is satisfied:\n## @tex\n## $$error \\leq \\max \\left( AbsTol, RelTol\\cdot\\vert q\\vert \\right)$$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##         @var{error} <= max (@var{AbsTol}, @var{RelTol}*|@var{q}|)\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @var{err} is an approximate bound on the error in the integral\n## @code{abs (@var{q} - @var{I})}, where @var{I} is the exact value of the\n## integral.\n##\n## Example 1 : integrate a rectangular region in x-y plane\n##\n## @example\n## @group\n## @var{f} = @@(@var{x},@var{y}) 2*ones (size (@var{x}));\n## @var{q} = integral2 (@var{f}, 0, 1, 0, 1)\n##   @xresult{} @var{q} =  2\n## @end group\n## @end example\n##\n## The result is a volume, which for this constant-value integrand, is just\n## @w{@code{@var{Length} * @var{Width} * @var{Height}}}.\n##\n## Example 2 : integrate a triangular region in x-y plane\n##\n## @example\n## @group\n## @var{f} = @@(@var{x},@var{y}) 2*ones (size (@var{x}));\n## @var{ymax} = @@(@var{x}) 1 - @var{x};\n## @var{q} = integral2 (@var{f}, 0, 1, 0, @var{ymax})\n##   @xresult{} @var{q} =  1\n## @end group\n## @end example\n##\n## The result is a volume, which for this constant-value integrand\n## @w{@math{@var{f} = 2}}, is the Triangle Area x Height or\n## @w{@code{1/2 * @var{Base} * @var{Width} * @var{Height}}}.\n##\n## Example 3 : integrate a non-vectorized function over a square region\n##\n## @example\n## @group\n## @var{f} = @@(@var{x},@var{y}) sinc (@var{x}) * sinc (@var{y}));\n## @var{q} = integral2 (@var{f}, -1, 1, -1, 1)\n##   @xresult{} @var{q} =  12.328  (incorrect)\n## @var{q} = integral2 (@var{f}, -1, 1, -1, 1, \"Vectorized\", false)\n##   @xresult{} @var{q} =  1.390 (correct)\n## @var{f} = @@(@var{x},@var{y}) sinc (@var{x}) .* sinc (@var{y});\n## @var{q} = integral2 (@var{f}, -1, 1, -1, 1)\n##   @xresult{} @var{q} =  1.390  (correct)\n## @end group\n## @end example\n##\n## The first result is incorrect as the non-elementwise operator between the\n## sinc functions in @var{f} create unintended matrix multiplications between\n## the internal integration arrays used by @code{integral2}.  In the second\n## result, setting @qcode{\"Vectorized\"} to false forces @code{integral2} to\n## perform scalar internal operations to compute the integral, resulting in\n## the correct numerical result at the cost of about a 20x increase in\n## computation time.  In the third result, vectorizing the integrand @var{f}\n## using the elementwise multiplication operator gets the correct result\n## without increasing computation time.\n##\n## Programming Notes: If there are singularities within the integration region\n## it is best to split the integral and place the singularities on the\n## boundary.\n##\n## Known @sc{matlab} incompatibility: If tolerances are left unspecified, and\n## any integration limits are of type @code{single}, then Octave's integral\n## functions automatically reduce the default absolute and relative error\n## tolerances as specified above.  If tighter tolerances are desired they\n## must be specified.  @sc{matlab} leaves the tighter tolerances appropriate\n## for @code{double} inputs in place regardless of the class of the\n## integration limits.\n##\n## Reference: @nospell{L.F. Shampine},\n## \"@sc{matlab} program for quadrature in 2D\",\n## @cite{Applied Mathematics and Computation}, @w{Vol.@: 1},\n## @w{pp.@: 266}--274, 2008.\n##\n## @seealso{quad2d, dblquad, integral, quad, quadgk, quadv, quadl, quadcc,\n##          trapz, integral3, triplequad}\n## @end deftypefn\n\nfunction [q, err] = integral2 (f, xa, xb, ya, yb, varargin)\n\n  if (nargin < 5 || mod (nargin, 2) == 0)\n    print_usage ();\n  endif\n\n  if (! is_function_handle (f))\n    print_usage ();\n  endif\n\n  if (! (isreal (xa) && isscalar (xa) && isreal (xb) && isscalar (xb)))\n    print_usage ();\n  endif\n\n  ## Check for single or double limits to set appropriate default tolerance.\n  issingle = (isa ([xa, xb], \"single\")\n              || (! is_function_handle (ya) && isa (ya, \"single\"))\n              || (! is_function_handle (yb) && isa (yb, \"single\")));\n\n  ## Set defaults, update with any specified parameters.\n  if (issingle)\n    abstol = 1e-5;\n    reltol = 1e-4;\n  else\n    abstol = 1e-10;\n    reltol = 1e-6;\n  endif\n\n  method = \"auto\";\n  idx = 1;\n  while (idx < nargin - 5)\n    prop = varargin{idx++};\n    if (! ischar (prop))\n      error (\"integral2: property PROP must be a string\");\n    endif\n\n    switch (lower (prop))\n      case \"abstol\"\n        abstol = varargin{idx++};\n        if (! (isnumeric (abstol) && isscalar (abstol) && abstol >= 0))\n          error (\"integral2: AbsTol value must be a numeric scalar >= 0\");\n        endif\n\n      case \"reltol\"\n        reltol = varargin{idx++};\n        if (! (isnumeric (reltol) && isscalar (reltol) && reltol >= 0))\n          error (\"integral2: RelTol value must be a numeric scalar >= 0\");\n        endif\n\n      case \"method\"\n        method = lower (varargin{idx++});\n        if (! any (strcmp (method, {\"auto\", \"iterated\", \"tiled\"})))\n          error (\"integral2 : unrecognized method '%s'\", method);\n        endif\n\n      case \"vectorized\"\n        vectorized = varargin{idx++};\n        if (! (isscalar (vectorized) && isreal (vectorized)))\n          error ('integral2: Vectorized must be a logical value');\n        endif\n        if (! vectorized)\n          f = @(x, y) arrayfun (f, x, y);\n        endif\n\n      otherwise\n        error (\"integral2: unknown property '%s'\", prop);\n\n    endswitch\n  endwhile\n\n  if (strcmp (method, \"auto\"))\n    if (isinf (xa) || isinf (xb)\n        || (! is_function_handle (ya) && isinf (ya))\n        || (! is_function_handle (yb) && isinf (yb)))\n      method = \"iterated\";\n    else\n      method = \"tiled\";\n    endif\n  endif\n\n  ## check upper and lower bounds of y\n  if (! is_function_handle (ya))\n    if (! (isreal (ya) && isscalar (ya)))\n      error (\"integral2: YA must be a real scalar or a function\");\n    endif\n    ya = @(x) ya * ones (rows (x), columns (x));\n  endif\n  if (! is_function_handle (yb))\n    if (! (isreal (yb) && isscalar (yb)))\n      error (\"integral2: YB must be a real scalar or a function\");\n    endif\n    yb = @(x) yb * ones (rows (x), columns (x));\n  endif\n\n  if (strcmp (method, \"iterated\"))\n    q = outer_iterated (f, xa, xb, ya, yb, abstol, reltol);\n\n    if (nargout == 2)\n      warning ('integral2: \"iterated\" method can not return estimated error');\n      err = 0;\n    endif\n  else\n    [q, err] = quad2d (f, xa, xb, ya, yb, \"AbsTol\", abstol, \"RelTol\", reltol);\n  endif\n\nendfunction\n\nfunction q = outer_iterated (f, xa, xb, ya, yb, abstol, reltol)\n  finner_iter = @(x) inner_iterated (x, f, ya, yb, abstol, reltol);\n  q = quadcc (finner_iter, xa, xb, [abstol, reltol]);\nendfunction\n\nfunction q = inner_iterated (x, f, ya, yb, abstol, reltol)\n  q = zeros (size (x));\n  for i = 1 : length (x)\n    q(i) = quadcc (@(y) f(x(i), y), ya(x(i)), yb(x(i)), [abstol, reltol]);\n  endfor\nendfunction\n\n\n## method tests\n%!shared f\n%! f = @(x, y) x .* y;\n\n%!assert (integral2 (f, 0, 1, 0, 1), 0.25, 1e-10)\n%!assert (integral2 (f, 0, 1, 0, 1, \"method\", \"tiled\"), 0.25, 1e-10)\n%!assert (integral2 (f, 0, 1, 0, 1, \"method\", \"iterated\"), 0.25, 1e-10)\n%!assert (integral2 (f, 0, 1, 0, 1, \"method\", \"auto\"), 0.25, 1e-10)\n\n## vectorized = false test\n%!test\n%! f = @(x, y) x * y;\n%!assert (integral2 (f, 0, 1, 0, 1, \"vectorized\", false), 0.25, 1e-10)\n\n## tolerance tests\n%!test\n%! f = @(x, y) 9 * x.^2 + 15 * y.^2;\n%!assert (integral2 (f, 0, 5, -5, 0, \"AbsTol\", 1e-9), 5000, 1e-9)\n%!assert (integral2 (f, 0, 5, -5, 0, \"RelTol\", 1e-5), 5000, -1e-5)\n%!assert (integral2 (f, 0, 5, -5, 0, \"RelTol\", 1e-6, \"AbsTol\", 1e-9),\n%!        5000, 1e-9)\n\n## tests from dblquad\n%!test\n%! f = @(x, y) 1 ./ (x+y);\n%!assert (integral2 (f, 0, 1, 0, 1, \"AbsTol\", 1e-7), 2*log (2), 1e-7)\n%!assert (integral2 (f, 0, 1, 0, 1, \"RelTol\", 1e-5), 2*log (2), -1e-5)\n%!assert (integral2 (f, 0, 1, 0, 1, \"AbsTol\", 1e-8, \"RelTol\", 1e-6),\n%!        2*log (2), -1e-6)\n%!assert (integral2 (f, 0, 1, 0, @(x) 1 - x), 1, -1e-6)\n\n%!assert (integral2 (@(x, y) exp (-x.^2 - y.^2) , -1, 1, -1, 1),\n%!        pi * erf (1).^2, 1e-10)\n\n%!assert (integral2 (@plus, 1, 2, 3, 4), 5, 1e-10)\n\n## tests from dblquad w/method specified\n%!assert (integral2 (f, 0, 1, 0, 1, \"AbsTol\", 1e-7, \"method\", \"iterated\"),\n%!        2*log (2), 1e-7)\n%!assert (integral2 (f, 0, 1, 0, 1, \"RelTol\", 1e-5, \"method\", \"iterated\"),\n%!        2*log (2), -1e-5)\n%!assert (integral2 (f, 0, 1, 0, 1, \"AbsTol\", 1e-8, \"RelTol\", 1e-6,\n%!                                  \"Method\", \"iterated\"),\n%!        2*log (2), -1e-6)\n%!assert (integral2 (f, 0, 1, 0, @(x) 1 - x, \"Method\", \"iterated\"), 1, -1e-6)\n%!assert (integral2 (@(x, y) exp (-x.^2 - y.^2) , -1, 1, -1, 1,\n%!                                                \"Method\", \"iterated\"),\n%!        pi * erf (1).^2, 1e-10)\n\n%!assert (integral2 (@plus, 1, 2, 3, 4, \"method\", \"iterated\"), 5, 1e-10)\n\n## Test input validation\n%!error <Invalid call> integral2 ()\n%!error <Invalid call> integral2 (@plus)\n%!error <Invalid call> integral2 (@plus, 1)\n%!error <Invalid call> integral2 (@plus, 1, 2)\n%!error <Invalid call> integral2 (@plus, 1, 2, 3)\n%!error <Invalid call> integral2 (@plus, 1, 2, 3, 4, \"foo\")\n%!error integral2 (0, 1, 2, 3, 4)          # f must be function handle\n%!error integral2 (@plus, 1i, 2, 3, 4)     # real limits\n%!error integral2 (@plus, 1, 2i, 3, 4)     # real limits\n%!error integral2 (@plus, [1 1], 2, 3, 4)  # scalar limits\n%!error integral2 (@plus, 1, [2 2], 3, 4)  # scalar limits\n%!error <property PROP must be a string> integral2 (@plus,1,2,3,4,99, \"bar\")\n%!error <AbsTol value must be a numeric>\n%! integral2 (@plus,1,2,3,4, \"AbsTol\", \"foo\");\n%!error <AbsTol value must be a .* scalar>\n%! integral2 (@plus, 1, 2, 3, 4, \"AbsTol\", [1, 2]);\n%!error <AbsTol value must be.* .= 0> integral2 (@plus,1,2,3,4, \"AbsTol\", -1)\n%!error <RelTol value must be a numeric>\n%! integral2 (@plus, 1, 2, 3, 4, \"RelTol\", \"foo\");\n%!error <RelTol value must be a .* scalar>\n%! integral2 (@plus, 1, 2, 3, 4, \"RelTol\", [1, 2]);\n%!error <RelTol value must be.* .= 0> integral2 (@plus,1,2,3,4, \"RelTol\", -1)\n%!error <unrecognized method 'foo'> integral2 (@plus,1,2,3,4, \"method\", \"foo\")\n%!error <Vectorized must be a logical value>\n%! integral2 (@plus,1,2,3,4, \"Vectorized\", [0 1]);\n%!error <Vectorized must be a logical value>\n%! integral2 (@plus,1,2,3,4, \"Vectorized\", {true});\n%!error <unknown property 'foo'>  integral2 (@plus, 1, 2, 3, 4, \"foo\", \"bar\")\n%!error <YA must be a real scalar> integral2 (@plus, 1, 2, 3i, 4)\n%!error <YA must be a real scalar> integral2 (@plus, 1, 2, [3 3], 4)\n%!error <YB must be a real scalar> integral2 (@plus, 1, 2, 3, 4i)\n%!error <YB must be a real scalar> integral2 (@plus, 1, 2, 3, [4 4])\n%!warning <\"iterated\" method can not return estimated error>\n%! [q, err] = integral2 (@plus, 0, 0, 0, 0, \"method\", \"iterated\");\n"
  },
  {
    "path": "scripts/general/integral3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} integral3 (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{za}, @var{zb})\n## @deftypefnx {} {@var{q} =} integral3 (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{za}, @var{zb}, @var{prop}, @var{val}, @dots{})\n##\n## Numerically evaluate the three-dimensional integral of @var{f} using\n## adaptive quadrature over the three-dimensional domain defined by\n## @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{za}, @var{zb} (scalars may\n## be finite or infinite).  Additionally, @var{ya} and @var{yb} may be\n## scalar functions of @var{x} and @var{za}, and @var{zb} maybe be scalar\n## functions of @var{x} and @var{y}, allowing for integration over\n## non-rectangular domains.\n##\n## @var{f} is a function handle, inline function, or string containing the\n## name of the function to evaluate.  The function @var{f} must be of the form\n## @math{z = f(x,y,z)}, and all operations must be vectorized such that\n## @var{x}, @var{y}, and @var{z} accept array inputs and return array outputs\n## of the same size.  (It can be assumed that @var{x}, @var{y}, and @var{z}\n## will either be same-size arrays or scalars.)  The underlying integrators\n## will input arrays of integration points into @var{f} and/or use internal\n## vector expansions to speed computation that can produce unpredictable\n## results if @var{f} is not restricted to elementwise operations.  For\n## integrands where this is unavoidable, the @qcode(\"Vectorized\") option\n## described below may produce more reliable results.\n##\n## Additional optional parameters can be specified using\n## @qcode{\"@var{property}\", @var{value}} pairs.  Valid properties are:\n##\n## @table @code\n## @item AbsTol\n## Define the absolute error tolerance for the quadrature.  The default\n## value is 1e-10 (1e-5 for single).\n##\n## @item RelTol\n## Define the relative error tolerance for the quadrature.  The default\n## value is 1e-6 (1e-4 for single).\n##\n## @item Method\n## Specify the two-dimensional integration method to be used, with valid\n## options being @qcode{\"auto\"} (default), @qcode{\"tiled\"}, or\n## @qcode{\"iterated\"}.  When using @qcode{\"auto\"}, Octave will choose the\n## @qcode{\"tiled\"} method unless any of the integration limits are infinite.\n##\n## @item Vectorized\n## Enable or disable vectorized integration.  A value of @code{false} forces\n## Octave to use only scalar inputs when calling the integrand, which enables\n## integrands @math{f(x,y,z)} that have not been vectorized or only accept\n## scalar values of @var{x}, @var{y}, or @var{z}.  The default value is\n## @code{true}.  Note that this is achieved by wrapping @math{f(x,y,z)} with\n## the function @code{arrayfun}, which may significantly decrease computation\n## speed.\n## @end table\n##\n## Adaptive quadrature is used to minimize the estimate of error until the\n## following is satisfied:\n## @tex\n## $$error \\leq \\max \\left( AbsTol, RelTol\\cdot\\vert q\\vert \\right)$$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##         @var{error} <= max (@var{AbsTol}, @var{RelTol}*|@var{q}|)\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @var{err} is an approximate bound on the error in the integral\n## @code{abs (@var{q} - @var{I})}, where @var{I} is the exact value of the\n## integral.\n##\n## Example 1 : integrate over a rectangular volume\n##\n## @example\n## @group\n## @var{f} = @@(@var{x},@var{y},@var{z}) ones (size (@var{x}));\n## @var{q} = integral3 (@var{f}, 0, 1, 0, 1, 0, 1)\n##   @xresult{} @var{q} =  1.00000\n## @end group\n## @end example\n##\n## For this constant-value integrand, the result is a volume which is just\n## @code{@var{Length} * @var{Width} * @var{Height}}.\n##\n## Example 2 : integrate over a spherical volume\n##\n## @example\n## @group\n## @var{f} = @@(@var{x},@var{y}) ones (size (@var{x}));\n## @var{ymax} = @@(@var{x}) sqrt (1 - @var{x}.^2);\n## @var{zmax} = @@(@var{x},@var{y}) sqrt (1 - @var{x}.^2 - @var{y}.^2);\n## @var{q} = integral3 (@var{f}, 0, 1, 0, @var{ymax}, 0, @var{zmax})\n##   @xresult{} @var{q} =  0.52360\n## @end group\n## @end example\n##\n## For this constant-value integrand, the result is a volume which is 1/8th\n## of a unit sphere or @code{1/8 * 4/3 * pi}.\n##\n## Example 3 : integrate a non-vectorized function over a cubic volume\n##\n## @example\n## @group\n## @var{f} = @@(@var{x},@var{y}) sinc (@var{x}) * sinc (@var{y}), * sinc (@var{z});\n## @var{q} = integral3 (@var{f}, -1, 1, -1, 1, -1, 1)\n##   @xresult{} @var{q} =  14.535  (incorrect)\n## @var{q} = integral3 (@var{f}, -1, 1, -1, 1, -1, 1, \"Vectorized\", false)\n##   @xresult{} @var{q} =  1.6388 (correct)\n## @var{f} = @@(@var{x},@var{y},@var{z}) sinc (@var{x}) .* sinc (@var{y}), .* sinc (@var{z});\n## @var{q} = integral3 (@var{f}, -1, 1, -1, 1, -1, 1)\n##   @xresult{} @var{q} =  1.6388  (correct)\n## @end group\n## @end example\n##\n## The first result is incorrect as the non-elementwise operator between the\n## sinc functions in @var{f} create unintended matrix multiplications between\n## the internal integration arrays used by @code{integral3}.  In the second\n## result, setting @qcode{\"Vectorized\"} to false forces @code{integral3} to\n## perform scalar internal operations to compute the integral, resulting in\n## the correct numerical result at the cost of about a 30x increase in\n## computation time.  In the third result, vectorizing the integrand @var{f}\n## using the elementwise multiplication operator gets the correct result\n## without increasing computation time.\n##\n## Programming Notes: If there are singularities within the integration region\n## it is best to split the integral and place the singularities on the\n## boundary.\n##\n## Known @sc{matlab} incompatibility: If tolerances are left unspecified, and\n## any integration limits are of type @code{single}, then Octave's integral\n## functions automatically reduce the default absolute and relative error\n## tolerances as specified above.  If tighter tolerances are desired they\n## must be specified.  @sc{matlab} leaves the tighter tolerances appropriate\n## for @code{double} inputs in place regardless of the class of the\n## integration limits.\n##\n## Reference: @nospell{L.F. Shampine},\n## \"@sc{matlab} program for quadrature in 2D\",\n## @cite{Applied Mathematics and Computation}, @w{Vol.@: 1},\n## @w{pp.@: 266}--274, 2008.\n##\n## @seealso{triplequad, integral, quad, quadgk, quadv, quadl,\n##          quadcc, trapz, integral2, quad2d, dblquad}\n## @end deftypefn\n\nfunction q = integral3 (f, xa, xb, ya, yb, za, zb, varargin)\n\n  if (nargin < 7 || mod (nargin, 2) == 0)\n    print_usage ();\n  endif\n\n  if (! is_function_handle (f))\n    print_usage ();\n  endif\n\n  if (! (isreal (xa) && isscalar (xa) && isreal (xb) && isscalar (xb)))\n    print_usage ();\n  endif\n\n  ## Check for single or double limits to set appropriate default tolerance.\n  issingle = (isa ([xa, xb], \"single\")\n              || (! is_function_handle (ya) && isa (ya, \"single\"))\n              || (! is_function_handle (yb) && isa (yb, \"single\"))\n              || (! is_function_handle (za) && isa (za, \"single\"))\n              || (! is_function_handle (zb) && isa (zb, \"single\")));\n\n  ## Communicate to downstream quadrature routines that at least one limit of\n  ## integration was of single type by casting xa, xb to single.\n  if (issingle)\n    xa = single (xa);\n    xb = single (xb);\n  endif\n\n  ## Set default tolerances, and then update with any specified parameters.\n  if (issingle)\n    abstol = 1e-5;\n    reltol = 1e-4;\n  else\n    abstol = 1e-10;\n    reltol = 1e-6;\n  endif\n\n  method = \"auto\";\n  vectorized = true;\n  idx = 1;\n  while (idx < nargin - 7)\n    prop = varargin{idx++};\n    if (! ischar (prop))\n      error (\"integral3: property PROP must be a string\");\n    endif\n\n    switch (lower (prop))\n      case \"abstol\"\n        abstol = varargin{idx++};\n        if (! (isnumeric (abstol) && isscalar (abstol) && abstol >= 0))\n          error (\"integral3: AbsTol value must be a numeric scalar >= 0\");\n        endif\n\n      case \"reltol\"\n        reltol = varargin{idx++};\n        if (! (isnumeric (reltol) && isscalar (reltol) && reltol >= 0))\n          error (\"integral3: RelTol value must be a numeric scalar >= 0\");\n        endif\n\n      case \"method\"\n        method = lower (varargin{idx++});\n        if (! any (strcmp (method, {\"auto\", \"iterated\", \"tiled\"})))\n          error (\"integral3 : unrecognized method '%s'\", method);\n        endif\n\n      case \"vectorized\"\n        vectorized = varargin{idx++};\n        if (! (isscalar (vectorized) && isreal (vectorized)))\n          error ('integral3: Vectorized must be a logical value');\n        endif\n\n      otherwise\n        error (\"integral3: unknown property '%s'\", prop);\n\n    endswitch\n  endwhile\n\n  if (strcmp (method, \"auto\"))\n    if (isinf (xa) || isinf (xb)\n        || (! is_function_handle (ya) && isinf (ya))\n        || (! is_function_handle (yb) && isinf (yb))\n        || (! is_function_handle (za) && isinf (za))\n        || (! is_function_handle (zb) && isinf (zb)))\n      method = \"iterated\";\n    else\n      method = \"tiled\";\n    endif\n  endif\n\n  ## check upper and lower bounds of y\n  if (! is_function_handle (ya))\n    if (! (isreal (ya) && isscalar (ya)))\n      error (\"integral3: YA must be a real scalar or a function\");\n    endif\n    ya = @(x) ya * ones (size (x));\n  endif\n  if (! is_function_handle (yb))\n    if (! (isreal (yb) && isscalar (yb)))\n      error (\"integral3: YB must be a real scalar or a function\");\n    endif\n    yb = @(x) yb * ones (size (x));\n  endif\n\n  ## check upper and lower bounds of z\n  if (! is_function_handle (za))\n    if (! (isreal (za) && isscalar (za)))\n      error (\"integral3: ZA must be a real scalar or a function\");\n    endif\n    za = @(x, y) za * ones (size (y));\n  endif\n  if (! is_function_handle (zb))\n    if (! (isreal (zb) && isscalar (zb)))\n      error (\"integral3: ZB must be a real scalar or a function\");\n    endif\n    zb = @(x, y) zb * ones (size (y));\n  endif\n\n  finner = @(x) inner (x, f, ya, yb, za, zb, vectorized, method, abstol, reltol);\n  q = quadcc (finner, xa, xb, [abstol, reltol]);\n\nendfunction\n\nfunction q = inner (x, f, ya, yb, za, zb, vectorized, method, abstol, reltol)\n\n  q = zeros (size (x));\n  for i = 1 : length (x)\n    za2 = @(y) za(x(i), y);\n    zb2 = @(y) zb(x(i), y);\n    f2 = @(y, z) f(x(i), y, z);\n    if (! vectorized)\n      f2 = @(y, z) arrayfun (f2, y, z);\n    endif\n    if (strcmp (method, \"iterated\"))\n      finner_iter = @(y) inner_iterated (y, f2, za2, zb2, abstol, reltol);\n      q(i) = quadcc (finner_iter, ya(x(i)), yb(x(i)), [abstol, reltol]);\n    else\n      q(i) = quad2d (f2, ya(x(i)), yb(x(i)), za2, zb2,\n                     \"AbsTol\", abstol, \"RelTol\", reltol);\n    endif\n  endfor\n\nendfunction\n\nfunction q = inner_iterated (y, f2, za2, zb2, abstol, reltol)\n  q = zeros (size (y));\n  for i = 1 : length (y)\n    q(i) = quadcc (@(z) f2(y(i), z), za2(y(i)), zb2(y(i)), [abstol, reltol]);\n  endfor\nendfunction\n\n\n## method tests\n%!shared f\n%! f = @(x, y, z) x .* y .* z;\n\n%!assert (integral3 (f, 0, 1, 0, 1, 0, 1), 0.125, 1e-10)\n%!assert (integral3 (f, 0, 1, 0, 1, 0, 1, \"method\", \"tiled\"), 0.125, 1e-10)\n%!assert (integral3 (f, 0, 1, 0, 1, 0, 1, \"method\", \"iterated\"), 0.125, 1e-10)\n%!assert (integral3 (f, 0, 1, 0, 1, 0, 1, \"method\", \"auto\"), 0.125, 1e-10)\n\n## vectorized = false test\n%!test\n%! f = @(x, y, z) x * y * z;\n%! assert (integral3 (f, 0, 1, 0, 1, 0, 1, \"vectorized\", false), 0.125, 1e-10);\n\n## tolerance tests\n%!test\n%! f = @(x, y, z) 2 * x.^2 + 3 * y.^2 + 4 * z.^2;\n%!assert (integral3 (f, 0, 5, -5, 0, 0, 5, \"AbsTol\", 1e-9), 9375, 1e-9)\n%!assert (integral3 (f, 0, 5, -5, 0, 0, 5, \"RelTol\", 1e-5), 9375, -1e-5)\n%!assert (integral3 (f, 0, 5, -5, 0, 0, 5, \"RelTol\", 1e-6, \"AbsTol\", 1e-9),\n%!        9375, 1e-9)\n\n## non-rectangular region\n## This test is too slow with \"iterated\" method\n%!test\n%! f = @(x,y,z) 1 ./ (x + y + z);\n%! ymax = @(x) 1 - x;\n%! zmax = @(x, y) 1 - x - y;\n%! assert (integral3 (f, 0, 1, 0, ymax, 0, zmax, \"method\", \"tiled\"),\n%!         0.25, 1e-6);\n\n## Test input validation\n%!error integral3\n%!error integral3 (@plus)\n%!error integral3 (@plus, 1)\n%!error integral3 (@plus, 1, 2)\n%!error integral3 (@plus, 1, 2, 3)\n%!error integral3 (@plus, 1, 2, 3, 4)\n%!error integral3 (@plus, 1, 2, 3, 4, 5)\n%!error integral3 (@plus, 1, 2, 3, 4, 5, 6, \"foo\")\n%!error integral3 (0, 1, 2, 3, 4, 5, 6)          # f must be a function handle\n%!error integral3 (@plus, 1i, 2, 3, 4, 5, 6)     # real limits\n%!error integral3 (@plus, 1, 2i, 3, 4, 5, 6)     # real limits\n%!error integral3 (@plus, [1 1], 2, 3, 4, 5, 6)  # scalar limits\n%!error integral3 (@plus, 1, [2 2], 3, 4, 5, 6)  # scalar limits\n%!error <property PROP must be a string>\n%! integral3 (@plus, 1, 2, 3, 4, 5, 6, 99, \"bar\");\n%!error <AbsTol value must be a numeric>\n%! integral3 (@plus, 1, 2, 3, 4, 5, 6, \"AbsTol\", \"foo\");\n%!error <AbsTol value must be a .* scalar>\n%! integral3 (@plus, 1, 2, 3, 4, 5, 6, \"AbsTol\", [1, 2]);\n%!error <AbsTol value must be.* .= 0>\n%! integral3 (@plus, 1, 2, 3, 4, 5, 6, \"AbsTol\", -1);\n%!error <RelTol value must be a numeric>\n%! integral3 (@plus, 1, 2, 3, 4, 5, 6, \"RelTol\", \"foo\");\n%!error <RelTol value must be a .* scalar>\n%! integral3 (@plus, 1, 2, 3, 4, 5, 6, \"RelTol\", [1, 2]);\n%!error <RelTol value must be.* .= 0>\n%! integral3 (@plus, 1, 2, 3, 4, 5, 6, \"RelTol\", -1);\n%!error <unrecognized method 'foo'>\n%! integral3 (@plus,1,2,3,4,5,6, \"method\", \"foo\");\n%!error <Vectorized must be a logical value>\n%! integral3 (@plus,1,2,3,4,5,6, \"Vectorized\", [0 1]);\n%!error <Vectorized must be a logical value>\n%! integral3 (@plus,1,2,3,4,5,6, \"Vectorized\", {true});\n%!error <unknown property 'foo'>\n%! integral3 (@plus, 1, 2, 3, 4, 6, 6, \"foo\", \"bar\");\n%!error <YA must be a real scalar> integral3 (@plus, 1, 2, 3i, 4, 5, 6)\n%!error <YA must be a real scalar> integral3 (@plus, 1, 2, [3 3], 4, 5, 6)\n%!error <YB must be a real scalar> integral3 (@plus, 1, 2, 3, 4i, 5, 6)\n%!error <YB must be a real scalar> integral3 (@plus, 1, 2, 3, [4 4], 5, 6)\n%!error <ZA must be a real scalar> integral3 (@plus, 1, 2, 3, 4, 5i, 6)\n%!error <ZA must be a real scalar> integral3 (@plus, 1, 2, 3, 4, [5 5], 6)\n%!error <ZB must be a real scalar> integral3 (@plus, 1, 2, 3, 4, 5, 6i)\n%!error <ZB must be a real scalar> integral3 (@plus, 1, 2, 3, 4, 5, [6 6])\n"
  },
  {
    "path": "scripts/general/interp1.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{yi} =} interp1 (@var{x}, @var{y}, @var{xi})\n## @deftypefnx {} {@var{yi} =} interp1 (@var{y}, @var{xi})\n## @deftypefnx {} {@var{yi} =} interp1 (@dots{}, @var{method})\n## @deftypefnx {} {@var{yi} =} interp1 (@dots{}, @var{extrap})\n## @deftypefnx {} {@var{yi} =} interp1 (@dots{}, \"left\")\n## @deftypefnx {} {@var{yi} =} interp1 (@dots{}, \"right\")\n## @deftypefnx {} {@var{pp} =} interp1 (@dots{}, \"pp\")\n##\n## One-dimensional interpolation.\n##\n## Interpolate input data to determine the value of @var{yi} at the points\n## @var{xi}.  If not specified, @var{x} is taken to be the indices of @var{y}\n## (@code{1:length (@var{y})}).  If @var{y} is a matrix or an N-dimensional\n## array, the interpolation is performed on each column of @var{y}.\n##\n## The interpolation @var{method} is one of:\n##\n## @table @asis\n## @item @qcode{\"nearest\"}\n## Return the nearest neighbor.\n##\n## @item @qcode{\"previous\"}\n## Return the previous neighbor.\n##\n## @item @qcode{\"next\"}\n## Return the next neighbor.\n##\n## @item @qcode{\"linear\"} (default)\n## Linear interpolation from nearest neighbors.\n##\n## @item @qcode{\"pchip\"}\n## Piecewise cubic Hermite interpolating polynomial---shape-preserving\n## interpolation with smooth first derivative.\n##\n## @item @qcode{\"cubic\"}\n## Cubic interpolation (same as @qcode{\"pchip\"}).\n##\n## @item @qcode{\"spline\"}\n## Cubic spline interpolation---smooth first and second derivatives\n## throughout the curve.\n## @end table\n##\n## Adding '*' to the start of any method above forces @code{interp1}\n## to assume that @var{x} is uniformly spaced, and only @code{@var{x}(1)}\n## and @code{@var{x}(2)} are referenced.  This is usually faster,\n## and is never slower.  The default method is @qcode{\"linear\"}.\n##\n## If @var{extrap} is the string @qcode{\"extrap\"}, then extrapolate values\n## beyond the endpoints using the current @var{method}.  If @var{extrap} is a\n## number, then replace values beyond the endpoints with that number.  When\n## unspecified, @var{extrap} defaults to @code{NA}.\n##\n## If the string argument @qcode{\"pp\"} is specified, then @var{xi} should not\n## be supplied and @code{interp1} returns a piecewise polynomial object.  This\n## object can later be used with @code{ppval} to evaluate the interpolation.\n## There is an equivalence, such that @code{ppval (interp1 (@var{x},\n## @var{y}, @var{method}, @qcode{\"pp\"}), @var{xi}) == interp1 (@var{x},\n## @var{y}, @var{xi}, @var{method}, @qcode{\"extrap\"})}.\n##\n## Duplicate points in @var{x} specify a discontinuous interpolant.  There\n## may be at most 2 consecutive points with the same value.\n## If @var{x} is increasing, the default discontinuous interpolant is\n## right-continuous.  If @var{x} is decreasing, the default discontinuous\n## interpolant is left-continuous.\n## The continuity condition of the interpolant may be specified by using\n## the options @qcode{\"left\"} or @qcode{\"right\"} to select a left-continuous\n## or right-continuous interpolant, respectively.\n## Discontinuous interpolation is only allowed for @qcode{\"nearest\"} and\n## @qcode{\"linear\"} methods; in all other cases, the @var{x}-values must be\n## unique.\n##\n## An example of the use of @code{interp1} is\n##\n## @example\n## @group\n## xf = [0:0.05:10];\n## yf = sin (2*pi*xf/5);\n## xp = [0:10];\n## yp = sin (2*pi*xp/5);\n## lin = interp1 (xp, yp, xf);\n## near = interp1 (xp, yp, xf, \"nearest\");\n## pch = interp1 (xp, yp, xf, \"pchip\");\n## spl = interp1 (xp, yp, xf, \"spline\");\n## plot (xf,yf,\"r\", xf,near,\"g\", xf,lin,\"b\", xf,pch,\"c\", xf,spl,\"m\",\n##       xp,yp,\"r*\");\n## legend (\"original\", \"nearest\", \"linear\", \"pchip\", \"spline\");\n## @end group\n## @end example\n##\n## @seealso{pchip, spline, interpft, interp2, interp3, interpn}\n## @end deftypefn\n\nfunction yi = interp1 (x, y, varargin)\n\n  if (nargin < 2 || nargin > 6)\n    print_usage ();\n  endif\n\n  method = \"linear\";\n  extrap = [];\n  xi = [];\n  ispp = false;\n  have_xi = false;\n  rightcontinuous = NaN;\n\n  if (nargin > 2)\n    for i_arg = 1:length (varargin)\n      arg = varargin{i_arg};\n      if (ischar (arg))\n        arg = lower (arg);\n        switch (arg)\n          case \"extrap\"\n            extrap = \"extrap\";\n          case \"pp\"\n            ispp = true;\n          case {\"right\", \"-right\"}\n            rightcontinuous = true;\n          case {\"left\", \"-left\"}\n            rightcontinuous = false;\n          otherwise\n            method = arg;\n        endswitch\n      else\n        if (i_arg == 1)\n          xi = arg;\n          have_xi = true;\n        else\n          extrap = arg;\n        endif\n      endif\n    endfor\n  endif\n\n  if (! have_xi && ! ispp)\n    xi = y;\n    y = x;\n    if (isvector (y))\n      x = 1:numel (y);\n    else\n      x = 1:rows (y);\n    endif\n  endif\n\n  if (isempty (extrap))\n    if (iscomplex (y))\n      extrap = NA + 1i*NA;\n    else\n      extrap = NA;\n    endif\n  endif\n\n  ## reshape matrices for convenience\n  x = x(:);\n  nx = rows (x);\n  szx = size (xi);\n  if (isvector (y))\n    y = y(:);\n  endif\n\n  szy = size (y);\n  y = y(:,:);\n  [ny, nc] = size (y);\n  xi = xi(:);\n\n  ## determine sizes\n  if (nx < 2 || ny < 2)\n    error (\"interp1: minimum of 2 points required in each dimension\");\n  endif\n\n  ## check whether x is sorted; sort if not.\n  if (! issorted (x, \"either\"))\n    [x, p] = sort (x);\n    y = y(p,:);\n  endif\n\n  if (any (strcmp (method, {\"previous\", \"*previous\", \"next\", \"*next\"})))\n    rightcontinuous = NaN; # needed for these methods to work\n  endif\n\n  if (isnan (rightcontinuous))\n    ## If not specified, set the continuity condition\n    if (x(end) < x(1))\n      rightcontinuous = false;\n    else\n      rightcontinuous = true;\n    endif\n  elseif ((rightcontinuous && (x(end) < x(1)))\n          || (! rightcontinuous && (x(end) > x(1))))\n    ## Switch between left-continuous and right-continuous\n    x = flipud (x);\n    y = flipud (y);\n  endif\n\n  ## Because of the way mkpp works, it's easiest to implement \"next\"\n  ## by running \"previous\" with vectors flipped.\n  if (strcmp (method, \"next\"))\n    x = flipud (x);\n    y = flipud (y);\n    method = \"previous\";\n  elseif (strcmp (method, \"*next\"))\n    x = flipud (x);\n    y = flipud (y);\n    method = \"*previous\";\n  endif\n\n  starmethod = method(1) == \"*\";\n\n  if (starmethod)\n    dx = x(2) - x(1);\n  else\n    jumps = x(1:end-1) == x(2:end);\n    have_jumps = any (jumps);\n    if (have_jumps)\n      if (strcmp (method, \"linear\") || strcmp (method, (\"nearest\")))\n        if (any (jumps(1:nx-2) & jumps(2:nx-1)))\n          warning (\"interp1: multiple discontinuities at the same X value\");\n        endif\n      else\n        error (\"interp1: discontinuities not supported for METHOD '%s'\",\n                                                                   method);\n      endif\n    endif\n  endif\n\n  ## Proceed with interpolating by all methods.\n  switch (method)\n\n    case \"nearest\"\n      pp = mkpp ([x(1); (x(1:nx-1)+x(2:nx))/2; x(nx)],\n                 shiftdim (y, 1), szy(2:end));\n      pp.orient = \"first\";\n\n      if (ispp)\n        yi = pp;\n      else\n        yi = ppval (pp, reshape (xi, szx));\n      endif\n\n    case \"*nearest\"\n      pp = mkpp ([x(1), x(1)+[0.5:(nx-1)]*dx, x(nx)],\n                 shiftdim (y, 1), szy(2:end));\n      pp.orient = \"first\";\n\n      if (ispp)\n        yi = pp;\n      else\n        yi = ppval (pp, reshape (xi, szx));\n      endif\n\n    case \"previous\"\n      pp = mkpp ([x(1:nx); 2*x(nx)-x(nx-1)],\n                 shiftdim (y, 1), szy(2:end));\n      pp.orient = \"first\";\n\n      if (ispp)\n        yi = pp;\n      else\n        yi = ppval (pp, reshape (xi, szx));\n      endif\n\n    case \"*previous\"\n      pp = mkpp (x(1)+[0:nx]*dx,\n                 shiftdim (y, 1), szy(2:end));\n      pp.orient = \"first\";\n\n      if (ispp)\n        yi = pp;\n      else\n        yi = ppval (pp, reshape (xi, szx));\n      endif\n\n    case \"linear\"\n\n      xx = x;\n      nxx = nx;\n      yy = y;\n      dy = diff (yy);\n      if (have_jumps)\n        ## Omit zero-size intervals.\n        xx(jumps) = [];\n        nxx = rows (xx);\n        yy(jumps, :) = [];\n        dy(jumps, :) = [];\n      endif\n\n      dx = diff (xx);\n      dx = repmat (dx, [1 size(dy)(2:end)]);\n\n      coefs = [(dy./dx).', yy(1:nxx-1, :).'];\n\n      pp = mkpp (xx, coefs, szy(2:end));\n      pp.orient = \"first\";\n\n      if (ispp)\n        yi = pp;\n      else\n        yi = ppval (pp, reshape (xi, szx));\n      endif\n\n    case \"*linear\"\n      dy = diff (y);\n      coefs = [(dy/dx).'(:), y(1:nx-1, :).'(:)];\n      pp = mkpp (x, coefs, szy(2:end));\n      pp.orient = \"first\";\n\n      if (ispp)\n        yi = pp;\n      else\n        yi = ppval (pp, reshape (xi, szx));\n      endif\n\n    case {\"pchip\", \"*pchip\", \"cubic\", \"*cubic\"}\n      if (nx == 2 || starmethod)\n        x = linspace (x(1), x(nx), ny);\n      endif\n\n      if (ispp)\n        y = shiftdim (reshape (y, szy), 1);\n        yi = pchip (x, y);\n        yi.orient = \"first\";\n      else\n        y = shiftdim (y, 1);\n        yi = pchip (x, y, reshape (xi, szx));\n        if (! isvector (y))\n          yi = shiftdim (yi, 1);\n        endif\n      endif\n\n    case {\"spline\", \"*spline\"}\n      if (nx == 2 || starmethod)\n        x = linspace (x(1), x(nx), ny);\n      endif\n\n      if (ispp)\n        y = shiftdim (reshape (y, szy), 1);\n        yi = spline (x, y);\n        yi.orient = \"first\";\n      else\n        y = shiftdim (y, 1);\n        yi = spline (x, y, reshape (xi, szx));\n        if (! isvector (y))\n          yi = shiftdim (yi, 1);\n        endif\n      endif\n\n    otherwise\n      error (\"interp1: invalid METHOD '%s'\", method);\n\n  endswitch\n\n  if (! ispp && isnumeric (extrap))\n    ## determine which values are out of range and set them to extrap,\n    ## unless extrap == \"extrap\".\n    minx = min (x(1), x(nx));\n    maxx = max (x(1), x(nx));\n\n    xi = reshape (xi, szx);\n    outliers = (xi < minx) | ! (xi <= maxx);  # this even catches NaNs\n    if (size_equal (outliers, yi))\n      yi(outliers) = extrap;\n      yi = reshape (yi, szx);\n    elseif (! isscalar (yi))\n      yi(outliers, :) = extrap;\n    else\n      warning (\"interp1: Unreachable state.  Please submit data that produced this warning to bugs.octave.org\");\n      yi(outliers.') = extrap;\n    endif\n\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! xf = 0:0.05:10;  yf = sin (2*pi*xf/5);\n%! xp = 0:10;       yp = sin (2*pi*xp/5);\n%! lin = interp1 (xp,yp,xf, 'linear');\n%! spl = interp1 (xp,yp,xf, 'spline');\n%! pch = interp1 (xp,yp,xf, 'pchip');\n%! near= interp1 (xp,yp,xf, 'nearest');\n%! plot (xf,yf,'r',xf,near,'g',xf,lin,'b',xf,pch,'c',xf,spl,'m',xp,yp,'r*');\n%! legend ('original', 'nearest', 'linear', 'pchip', 'spline');\n%! title ('Interpolation of continuous function sin (x) w/various methods');\n%! %--------------------------------------------------------\n%! % confirm that interpolated function matches the original\n\n%!demo\n%! clf;\n%! xf = 0:0.05:10;  yf = sin (2*pi*xf/5);\n%! xp = 0:10;       yp = sin (2*pi*xp/5);\n%! lin = interp1 (xp,yp,xf, '*linear');\n%! spl = interp1 (xp,yp,xf, '*spline');\n%! pch = interp1 (xp,yp,xf, '*pchip');\n%! near= interp1 (xp,yp,xf, '*nearest');\n%! plot (xf,yf,'r',xf,near,'g',xf,lin,'b',xf,pch,'c',xf,spl,'m',xp,yp,'r*');\n%! legend ('*original', '*nearest', '*linear', '*pchip', '*spline');\n%! title ('Interpolation of continuous function sin (x) w/various *methods');\n%! %--------------------------------------------------------\n%! % confirm that interpolated function matches the original\n\n%!demo\n%! clf;\n%! fstep = @(x) x > 1;\n%! xf = 0:0.05:2;  yf = fstep (xf);\n%! xp = linspace (0,2,10);  yp = fstep (xp);\n%! pch = interp1 (xp,yp,xf, 'pchip');\n%! spl = interp1 (xp,yp,xf, 'spline');\n%! plot (xf,yf,'r',xf,pch,'b',xf,spl,'m',xp,yp,'r*');\n%! title ({'Interpolation of step function with discontinuity at x==1', ...\n%!         'Note: \"pchip\" is shape-preserving, \"spline\" (continuous 1st, 2nd derivatives) is not'});\n%! legend ('original', 'pchip', 'spline');\n\n%!demo\n%! clf;\n%! t = 0 : 0.3 : pi; dt = t(2)-t(1);\n%! n = length (t); k = 100; dti = dt*n/k;\n%! ti = t(1) + [0 : k-1]*dti;\n%! y = sin (4*t + 0.3) .* cos (3*t - 0.1);\n%! ddys = diff (diff (interp1 (t,y,ti, 'spline'))./dti)./dti;\n%! ddyp = diff (diff (interp1 (t,y,ti, 'pchip')) ./dti)./dti;\n%! ddyc = diff (diff (interp1 (t,y,ti, 'cubic')) ./dti)./dti;\n%! plot (ti(2:end-1),ddys,'b*', ti(2:end-1),ddyp,'c^', ti(2:end-1),ddyc,'g+');\n%! title ({'Second derivative of interpolated \"sin (4*t + 0.3) .* cos (3*t - 0.1)\"', ...\n%!         'Note: \"spline\" has continuous 2nd derivative, others do not'});\n%! legend ('spline', 'pchip', 'cubic');\n\n%!demo\n%! clf;\n%! xf = 0:0.05:10;                yf = sin (2*pi*xf/5) - (xf >= 5);\n%! xp = [0:.5:4.5,4.99,5:.5:10];  yp = sin (2*pi*xp/5) - (xp >= 5);\n%! lin = interp1 (xp,yp,xf, 'linear');\n%! near= interp1 (xp,yp,xf, 'nearest');\n%! plot (xf,yf,'r', xf,near,'g', xf,lin,'b', xp,yp,'r*');\n%! legend ('original', 'nearest', 'linear');\n%! %--------------------------------------------------------\n%! % confirm that interpolated function matches the original\n\n%!demo\n%! clf;\n%! x = 0:0.5:3;\n%! x1 = [3 2 2 1];\n%! x2 = [1 2 2 3];\n%! y1 = [1 1 0 0];\n%! y2 = [0 0 1 1];\n%! h = plot (x, interp1 (x1, y1, x), 'b', x1, y1, 'sb');\n%! hold on\n%! g = plot (x, interp1 (x2, y2, x), 'r', x2, y2, '*r');\n%! axis ([0.5 3.5 -0.5 1.5]);\n%! legend ([h(1), g(1)], {'left-continuous', 'right-continuous'}, ...\n%!         'location', 'northwest')\n%! legend boxoff\n%! %--------------------------------------------------------\n%! % red curve is left-continuous and blue is right-continuous at x = 2\n\n## FIXME: add test for N-D arguments here\n\n## For each type of interpolated test, confirm that the interpolated\n## value at the knots match the values at the knots.  Points away\n## from the knots are requested, but only \"nearest\" and \"linear\"\n## confirm they are the correct values.\n\n%!shared xp, yp, xi, style\n%! xp = 0:2:10;\n%! yp = sin (2*pi*xp/5);\n%! xi = [-1, 0, 2.2, 4, 6.6, 10, 11];\n\n## The following BLOCK/ENDBLOCK section is repeated for each style\n##    nearest, previous, next, linear, cubic, spline, pchip\n## The test for ppval of cubic has looser tolerance, but otherwise\n## the tests are identical.\n## Note that the block checks style and *style; if you add more tests\n## be sure to add them to both sections of each block.  One test,\n## style vs. *style, occurs only in the first section.\n## There is an ENDBLOCKTEST after the final block\n\n%!test style = \"nearest\";\n## BLOCK\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!error interp1 (1,1,1, style)\n%!assert (interp1 (xp,[yp',yp'],xi,style),\n%!        interp1 (xp,[yp',yp'],xi,[\"*\",style]),100*eps)\n%!test style = [\"*\",style];\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!assert (interp1 (yp, xi, style, 0), ...\n%!        interp1 (1:numel (yp), yp, xi, style, 0), 10*eps)\n%!error interp1 (1,1,1, style)\n## ENDBLOCK\n\n%!test style = \"previous\";\n## BLOCK\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n## This test is expected to fail, so commented out.\n## \"previous\" and \"next\" options are not symmetric w.r.t to flipping xp,yp\n%!#assert (interp1 (xp,yp,xi,style),...\n%!#        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!error interp1 (1,1,1, style)\n%!assert (interp1 (xp,[yp',yp'],xi,style),\n%!        interp1 (xp,[yp',yp'],xi,[\"*\",style]),100*eps)\n%!test style = [\"*\",style];\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!#assert (interp1 (xp,yp,xi,style),...\n%!#        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!assert (interp1 (yp, xi, style, 0), ...\n%!        interp1 (1:numel (yp), yp, xi, style, 0), 10*eps)\n%!error interp1 (1,1,1, style)\n## ENDBLOCK\n\n%!test style = \"next\";\n## BLOCK\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!#assert (interp1 (xp,yp,xi,style),...\n%!#        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!error interp1 (1,1,1, style)\n%!assert (interp1 (xp,[yp',yp'],xi,style),\n%!        interp1 (xp,[yp',yp'],xi,[\"*\",style]),100*eps)\n%!test style = [\"*\",style];\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!#assert (interp1 (xp,yp,xi,style),...\n%!#        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!assert (interp1 (yp, xi, style, 0), ...\n%!        interp1 (1:numel (yp), yp, xi, style, 0), 10*eps)\n%!error interp1 (1,1,1, style)\n## ENDBLOCK\n\n%!test style = \"linear\";\n## BLOCK\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!error interp1 (1,1,1, style)\n%!assert (interp1 (xp,[yp',yp'],xi,style),\n%!        interp1 (xp,[yp',yp'],xi,[\"*\",style]),100*eps)\n%!test style = ['*',style];\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!assert (interp1 (yp, xi, style, 0), ...\n%!        interp1 (1:numel (yp), yp, xi, style, 0), 10*eps)\n%!assert (interp1 ([1 2 2 3], [1 2 3 4], 2), 3)\n%!assert (interp1 ([3 2 2 1], [4 3 2 1], 2), 2)\n%!error interp1 (1,1,1, style)\n## ENDBLOCK\n\n%!test style = \"cubic\";\n## BLOCK\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),100*eps)\n%!error interp1 (1,1,1, style)\n%!assert (interp1 (xp,[yp',yp'],xi,style),\n%!        interp1 (xp,[yp',yp'],xi,[\"*\",style]),100*eps)\n%!test style = [\"*\",style];\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),100*eps)\n%!assert (interp1 (yp, xi, style, 0), ...\n%!        interp1 (1:numel (yp), yp, xi, style, 0), 10*eps)\n%!error interp1 (1,1,1, style)\n## ENDBLOCK\n\n%!test style = \"pchip\";\n## BLOCK\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!error interp1 (1,1,1, style)\n%!assert (interp1 (xp,[yp',yp'],xi,style),\n%!        interp1 (xp,[yp',yp'],xi,[\"*\",style]),100*eps)\n%!test style = [\"*\",style];\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!assert (interp1 (yp, xi, style, 0), ...\n%!        interp1 (1:numel (yp), yp, xi, style, 0), 10*eps)\n%!error interp1 (1,1,1, style)\n## ENDBLOCK\n\n%!test style = \"spline\";\n## BLOCK\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!error interp1 (1,1,1, style)\n%!assert (interp1 (xp,[yp',yp'],xi,style),\n%!        interp1 (xp,[yp',yp'],xi,[\"*\",style]),100*eps)\n%!test style = [\"*\",style];\n%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])\n%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)\n%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)\n%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)\n%!assert (isempty (interp1 (xp',yp',[],style)))\n%!assert (isempty (interp1 (xp,yp,[],style)))\n%!assert (interp1 (xp,[yp',yp'],xi(:),style),...\n%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])\n%!assert <*61903> ...\n%!  (interp1 (xp, yp + 1i * yp.^2, xi, style),...\n%!   interp1 (xp,yp,xi,style) + 1i * interp1 (xp,yp.^2,xi,style))\n%!assert (interp1 (xp,yp,xi,style),...\n%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)\n%!assert (ppval (interp1 (xp,yp,style,\"pp\"),xi),\n%!        interp1 (xp,yp,xi,style,\"extrap\"),10*eps)\n%!assert (interp1 (yp, xi, style, 0), ...\n%!        interp1 (1:numel (yp), yp, xi, style, 0), 10*eps)\n%!error interp1 (1,1,1, style)\n## ENDBLOCK\n## ENDBLOCKTEST\n\n## test extrapolation\n%!assert (interp1 ([1:5],[3:2:11],[0,6],\"linear\",\"extrap\"), [1, 13], eps)\n%!assert (interp1 ([1:5],[3:2:11],[0,6],\"nearest\",\"extrap\"), [3, 11], eps)\n%!assert (interp1 ([1:5],[3:2:11],[0,6],\"previous\",\"extrap\"), [3, 11], eps)\n%!assert (interp1 ([1:5],[3:2:11],[0,6],\"next\",\"extrap\"), [3, 11], eps)\n%!assert (interp1 (xp, yp, [-1, max(xp)+1],\"linear\",5), [5, 5])\n%!assert (interp1 ([0,1],[1,0],[0.1,0.9;0.2,1.1]), [0.9 0.1; 0.8 NA], eps)\n%!assert (interp1 ([0,1],[1,0],[0.1,0.9;0.2,1]), [0.9 0.1; 0.8 0], eps)\n\n## Basic sanity checks\n%!assert (interp1 (1:2,1:2,1.4,\"nearest\"), 1)\n%!assert (interp1 (1:2,1:2,1.6,\"previous\"), 1)\n%!assert (interp1 (1:2,1:2,1.4,\"next\"), 2)\n%!assert (interp1 (1:2,1:2,1.4,\"linear\"), 1.4)\n%!assert (interp1 (1:4,1:4,1.4,\"cubic\"), 1.4)\n%!assert (interp1 (1:2,1:2,1.1,\"spline\"), 1.1)\n%!assert (interp1 (1:3,1:3,1.4,\"spline\"), 1.4)\n\n%!assert (interp1 (1:2:4,1:2:4,1.4,\"*nearest\"), 1)\n%!assert (interp1 (1:2:4,1:2:4,2.2,\"*previous\"), 1)\n%!assert (interp1 (1:2:4,1:2:4,1.4,\"*next\"), 3)\n%!assert (interp1 (1:2:4,1:2:4,[0,1,1.4,3,4],\"*linear\"), [NA,1,1.4,3,NA])\n%!assert (interp1 (1:2:8,1:2:8,1.4,\"*cubic\"), 1.4)\n%!assert (interp1 (1:2,1:2,1.3, \"*spline\"), 1.3)\n%!assert (interp1 (1:2:6,1:2:6,1.4,\"*spline\"), 1.4)\n\n%!assert (interp1 ([3,2,1],[3,2,2],2.5), 2.5)\n\n%!assert (interp1 ([4,4,3,2,0],[0,1,4,2,1],[1.5,4,4.5], \"linear\"), [1.75,1,NA])\n%!assert (interp1 (0:4, 2.5), 1.5)\n\n## Left and Right discontinuities\n%!assert (interp1 ([1,2,2,3,4],[0,1,4,2,1],[-1,1.5,2,2.5,3.5], \"linear\", \"extrap\", \"right\"), [-2,0.5,4,3,1.5])\n%!assert (interp1 ([1,2,2,3,4],[0,1,4,2,1],[-1,1.5,2,2.5,3.5], \"linear\", \"extrap\", \"left\"), [-2,0.5,1,3,1.5])\n\n## Test input validation\n%!error <Invalid call> interp1 ()\n%!error <Invalid call> interp1 (1)\n%!error <Invalid call> interp1 (1,2,3,4,5,6,7)\n%!error <minimum of 2 points required> interp1 (1,1,1, \"linear\")\n%!error <minimum of 2 points required> interp1 (1,1,1, \"*nearest\")\n%!error <minimum of 2 points required> interp1 (1,1,1, \"*linear\")\n%!error <minimum of 2 points required> interp1 (1,1,1, \"previous\")\n%!error <minimum of 2 points required> interp1 (1,1,1, \"*previous\")\n%!warning <multiple discontinuities> interp1 ([1 1 1 2], [1 2 3 4], 1);\n%!error <discontinuities not supported> interp1 ([1 1],[1 2],1, \"next\")\n%!error <discontinuities not supported> interp1 ([1 1],[1 2],1, \"pchip\")\n%!error <discontinuities not supported> interp1 ([1 1],[1 2],1, \"cubic\")\n%!error <discontinuities not supported> interp1 ([1 1],[1 2],1, \"spline\")\n%!error <invalid METHOD 'invalid'> interp1 (1:2,1:2,1, \"invalid\")\n"
  },
  {
    "path": "scripts/general/interp2.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{zi} =} interp2 (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi})\n## @deftypefnx {} {@var{zi} =} interp2 (@var{z}, @var{xi}, @var{yi})\n## @deftypefnx {} {@var{zi} =} interp2 (@var{z}, @var{n})\n## @deftypefnx {} {@var{zi} =} interp2 (@var{z})\n## @deftypefnx {} {@var{zi} =} interp2 (@dots{}, @var{method})\n## @deftypefnx {} {@var{zi} =} interp2 (@dots{}, @var{method}, @var{extrap})\n##\n## Two-dimensional interpolation.\n##\n## Interpolate numeric reference data @var{x}, @var{y}, @var{z} to determine\n## @var{zi} at the coordinates @var{xi}, @var{yi}.  The reference data\n## @var{x}, @var{y} can be matrices, as returned by @code{meshgrid}, in which\n## case the sizes of @var{x}, @var{y}, and @var{z} must be equal.  If @var{x},\n## @var{y} are vectors describing a grid then\n## @w{@code{length (@var{x}) == columns (@var{z})}}@ and\n## @w{@code{length (@var{y}) == rows (@var{z})}}.  In either case the input\n## data must be strictly monotonic.\n##\n## If called without @var{x}, @var{y}, and just a single reference data matrix\n## @var{z}, the 2-D region\n## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})} is assumed.\n## This saves memory if the grid is regular and the distance between points is\n## not important.\n##\n## If called with a single reference data matrix @var{z} and a refinement\n## value @var{n}, then perform interpolation over a grid where each original\n## interval has been recursively subdivided @var{n} times.  This results in\n## @code{2^@var{n}-1} additional points for every interval in the original\n## grid.  If @var{n} is omitted a value of 1 is used.  As an example, the\n## interval [0,1] with @code{@var{n}==2} results in a refined interval with\n## points at [0, 1/4, 1/2, 3/4, 1].\n##\n## The interpolation @var{method} is one of:\n##\n## @table @asis\n## @item @qcode{\"nearest\"}\n## Return the nearest neighbor.\n##\n## @item @qcode{\"linear\"} (default)\n## Linear interpolation from nearest neighbors.\n##\n## @item @qcode{\"pchip\"}\n## Piecewise cubic Hermite interpolating polynomial---shape-preserving\n## interpolation with smooth first derivative.\n##\n## @item @qcode{\"cubic\"}\n## Cubic interpolation using a convolution kernel function---third order\n## method with smooth first derivative.\n##\n## @item @qcode{\"spline\"}\n## Cubic spline interpolation---smooth first and second derivatives\n## throughout the curve.\n## @end table\n##\n## @var{extrap} is a scalar number.  It replaces values beyond the endpoints\n## with @var{extrap}.  Note that if @var{extrap} is used, @var{method} must\n## be specified as well.  If @var{extrap} is omitted and the @var{method} is\n## @qcode{\"spline\"}, then the extrapolated values of the @qcode{\"spline\"} are\n## used.  Otherwise the default @var{extrap} value for any other @var{method}\n## is @qcode{\"NA\"}.\n## @seealso{interp1, interp3, interpn, meshgrid}\n## @end deftypefn\n\nfunction ZI = interp2 (varargin)\n\n  narginchk (1, 7);\n  nargs = nargin;\n\n  Z = X = Y = XI = YI = n = [];\n  method = \"linear\";\n  extrap = [];\n\n  ## Check for method and extrap\n  if (nargs > 1 && ischar (varargin{end-1}))\n    if (! isnumeric (varargin{end}) || ! isscalar (varargin{end}))\n      error (\"interp2: EXTRAP must be a numeric scalar\");\n    endif\n    extrap = varargin{end};\n    method = varargin{end-1};\n    nargs -= 2;\n  elseif (ischar (varargin{end}))\n    method = varargin{end};\n    nargs -= 1;\n  endif\n  if (method(1) == \"*\")\n    warning (\"interp2: ignoring unsupported '*' flag to METHOD\");\n    method(1) = [];\n  endif\n  method = validatestring (method, ...\n                           {\"nearest\", \"linear\", \"pchip\", \"cubic\", \"spline\"});\n\n  ## Read numeric input\n  switch (nargs)\n    case 1\n      Z = varargin{1};\n      n = 1;\n    case 2\n      [Z, n] = deal (varargin{1:nargs});\n    case 3\n      [Z, XI, YI] = deal (varargin{1:nargs});\n    case 5\n      [X, Y, Z, XI, YI] = deal (varargin{1:nargs});\n    otherwise\n      print_usage ();\n  endswitch\n\n  ## Type checking\n  if (! isnumeric (Z) || isvector (Z) || ! ismatrix (Z))\n    error (\"interp2: Z must be a numeric 2-D matrix\");\n  endif\n  if (! isempty (n) && ! (isscalar (n) && n >= 0 && n == fix (n)))\n    error (\"interp2: N must be an integer >= 0\");\n  endif\n\n  ## Define X, Y, XI, YI if needed\n  [zr, zc] = size (Z);\n  if (isempty (X))\n    X = 1:zc;\n    Y = 1:zr;\n  endif\n  if (! isnumeric (X) || ! isnumeric (Y))\n    error (\"interp2: X, Y must be numeric matrices\");\n  endif\n  if (! isempty (n))\n    ## Calculate the interleaved input vectors.\n    p = 2^n;\n    XI = (p:p*zc)/p;\n    YI = (p:p*zr).'/p;\n  endif\n  if (! isnumeric (XI) || ! isnumeric (YI))\n    error (\"interp2: XI, YI must be numeric\");\n  endif\n\n  if (isvector (X) && isvector (Y))\n    X = X(:);  Y = Y(:);\n  elseif (size_equal (X, Y))\n    X = X(1,:).';  Y = Y(:,1);\n  else\n    error (\"interp2: X and Y must be matrices of equal size\");\n  endif\n  if (columns (Z) != length (X) || rows (Z) != length (Y))\n    error (\"interp2: X and Y size must match the dimensions of Z\");\n  endif\n  dx = diff (X);\n  if (all (dx < 0))\n    X = flipud (X);\n    Z = fliplr (Z);\n  elseif (any (dx <= 0))\n    error (\"interp2: X must be strictly monotonic\");\n  endif\n  dy = diff (Y);\n  if (all (dy < 0))\n    Y = flipud (Y);\n    Z = flipud (Z);\n  elseif (any (dy <= 0))\n    error (\"interp2: Y must be strictly monotonic\");\n  endif\n\n  if (strcmp (method, \"cubic\") && (rows (Z) < 3 || columns (Z) < 3))\n    warning ([\"interp2: cubic requires at least 3 points in each \" ...\n              \"dimension.  Falling back to linear interpolation.\"]);\n    method = \"linear\";\n  endif\n\n  if (any (strcmp (method, {\"nearest\", \"linear\", \"pchip\"})))\n\n    ## If Xi and Yi are vectors of different orientation build a grid\n    if ((isrow (XI) && iscolumn (YI)) || (iscolumn (XI) && isrow (YI)))\n      [XI, YI] = meshgrid (XI, YI);\n    elseif (! size_equal (XI, YI))\n      error (\"interp2: XI and YI must be matrices of equal size\");\n    endif\n\n    ## if XI, YI are vectors, X and Y should share their orientation.\n    if (isrow (XI))\n      if (rows (X) != 1)\n        X = X.';\n      endif\n      if (rows (Y) != 1)\n        Y = Y.';\n      endif\n    elseif (iscolumn (XI))\n      if (columns (X) != 1)\n        X = X.';\n      endif\n      if (columns (Y) != 1)\n        Y = Y.';\n      endif\n    endif\n\n    xidx = lookup (X, XI, \"lr\");\n    yidx = lookup (Y, YI, \"lr\");\n\n    if (strcmp (method, \"linear\"))\n      ## each quad satisfies the equation z(x,y)=a+b*x+c*y+d*xy\n      ##\n      ## a-b\n      ## | |\n      ## c-d\n      a = Z(1:(zr - 1), 1:(zc - 1));\n      b = Z(1:(zr - 1), 2:zc) - a;\n      c = Z(2:zr, 1:(zc - 1)) - a;\n      d = Z(2:zr, 2:zc) - a - b - c;\n\n      ## scale XI, YI values to a 1-spaced grid\n      Xsc = (XI - X(xidx)) ./ (diff (X)(xidx));\n      Ysc = (YI - Y(yidx)) ./ (diff (Y)(yidx));\n\n      ## Get 2-D index.\n      idx = sub2ind (size (a), yidx, xidx);\n      ## Dispose of the 1-D indices at this point to save memory.\n      clear xidx yidx;\n\n      ## Apply plane equation\n      ## Handle case where idx and coefficients are both vectors and resulting\n      ## coeff(idx) follows orientation of coeff, rather than that of idx.\n      forient = @(x) reshape (x, size (idx));\n      ZI =   forient (a(idx))        ...\n           + forient (b(idx)) .* Xsc ...\n           + forient (c(idx)) .* Ysc ...\n           + forient (d(idx)) .* Xsc.*Ysc;\n\n    elseif (strcmp (method, \"nearest\"))\n      ii = (XI - X(xidx) >= X(xidx + 1) - XI);\n      jj = (YI - Y(yidx) >= Y(yidx + 1) - YI);\n      idx = sub2ind (size (Z), yidx+jj, xidx+ii);\n      ZI = Z(idx);\n\n    elseif (strcmp (method, \"pchip\"))\n\n      if (length (X) < 2 || length (Y) < 2)\n        error (\"interp2: pchip requires at least 2 points in each dimension\");\n      endif\n\n      ## first order derivatives\n      DX = __pchip_deriv__ (X, Z, 2);\n      DY = __pchip_deriv__ (Y, Z, 1);\n      ## Compute mixed derivatives row-wise and column-wise.  Use the average.\n      DXY = (__pchip_deriv__ (X, DY, 2) + __pchip_deriv__ (Y, DX, 1)) / 2;\n\n      ## do the bicubic interpolation\n      hx = diff (X); hx = hx(xidx);\n      hy = diff (Y); hy = hy(yidx);\n\n      tx = (XI - X(xidx)) ./ hx;\n      ty = (YI - Y(yidx)) ./ hy;\n\n      ## construct the cubic hermite base functions in x, y\n\n      ## formulas:\n      ## b{1,1} =    ( 2*t.^3 - 3*t.^2     + 1);\n      ## b{2,1} = h.*(   t.^3 - 2*t.^2 + t    );\n      ## b{1,2} =    (-2*t.^3 + 3*t.^2        );\n      ## b{2,2} = h.*(   t.^3 -   t.^2        );\n\n      ## optimized equivalents of the above:\n      t1 = tx.^2;\n      t2 = tx.*t1 - t1;\n      xb{2,2} = hx.*t2;\n      t1 = t2 - t1;\n      xb{2,1} = hx.*(t1 + tx);\n      t2 += t1;\n      xb{1,2} = -t2;\n      xb{1,1} = t2 + 1;\n\n      t1 = ty.^2;\n      t2 = ty.*t1 - t1;\n      yb{2,2} = hy.*t2;\n      t1 = t2 - t1;\n      yb{2,1} = hy.*(t1 + ty);\n      t2 += t1;\n      yb{1,2} = -t2;\n      yb{1,1} = t2 + 1;\n\n      ZI = zeros (size (XI));\n      for ix = 1:2\n        for iy = 1:2\n          zidx = sub2ind (size (Z), yidx+(iy-1), xidx+(ix-1));\n          ZI += xb{1,ix} .* yb{1,iy} .*   Z(zidx);\n          ZI += xb{2,ix} .* yb{1,iy} .*  DX(zidx);\n          ZI += xb{1,ix} .* yb{2,iy} .*  DY(zidx);\n          ZI += xb{2,ix} .* yb{2,iy} .* DXY(zidx);\n        endfor\n      endfor\n\n    endif\n\n  else  # cubic or spline methods\n\n    ## Check dimensions of XI and YI\n    if (isvector (XI) && isvector (YI) && ! size_equal (XI, YI))\n      XI = XI(:).';  YI = YI(:);\n    elseif (! size_equal (XI, YI))\n      error (\"interp2: XI and YI must be matrices of equal size\");\n    endif\n\n    if (strcmp (method, \"spline\"))\n      if (isgriddata (XI) && isgriddata (YI.'))\n        ZI = __splinen__ ({Y, X}, Z, {YI(:,1), XI(1,:)}, extrap, \"spline\");\n      else\n        error (\"interp2: XI, YI must have uniform spacing ('meshgrid' format)\");\n      endif\n      return;  # spline doesn't use extrapolation value (MATLAB compatibility)\n    elseif (strcmp (method, \"cubic\"))\n      ## reduce to vectors if interpolation points are a meshgrid\n      if (size_equal (XI, YI) && all (all (XI(1, :) == XI & YI(:, 1) == YI)))\n        XI = XI(1, :);\n        YI = YI(:, 1);\n      endif\n\n      ## make X a row vector\n      X = X.';\n\n      ## quadratic padding + additional zeros for the special case of copying\n      ## the last line (like x=1:5, xi=5, requires to have indices 6 and 7)\n      row_1 = 3*Z(1, :, :) - 3*Z(2, :, :) + Z(3, :, :);\n      row_end = 3*Z(end, :, :) - 3*Z(end-1, :, :) + Z(end-2, :, :);\n      ZI = [3*row_1(:, 1, :) - 3*row_1(:, 2, :) + row_1(:, 3, :), ...\n            row_1, ...\n            3*row_1(:, end, :) - 3*row_1(:, end-1, :) + row_1(:, end-2, :), ...\n            0;\n            #\n            3*Z(:, 1, :) - 3*Z(:, 2, :) + Z(:, 3, :), ...\n            Z, ...\n            3*Z(:, end, :) - 3*Z(:, end-1, :) + Z(:, end-2, :), ...\n            zeros(rows (Z), 1, size (Z, 3));\n            #\n            3*row_end(:, 1, :) - 3*row_end(:, 2, :) + row_end(:, 3, :), ...\n            row_end, ...\n            3*row_end(:, end, :) - 3*row_end(:, end-1, :) + row_end(:, end-2, :), ...\n            0;\n            zeros(1, columns (Z) + 3, size (Z, 3))];\n\n      ## interpolate\n      if (isrow (XI) && iscolumn (YI))\n        ZI = conv_interp_vec (ZI, Y, YI, @cubic, [-2, 2], 1);\n        ZI = conv_interp_vec (ZI, X, XI, @cubic, [-2, 2], 2);\n      else\n        ZI = conv_interp_pairs (ZI, X, Y, XI, YI, @cubic, [-2, 2]);\n      endif\n    endif\n  endif\n\n  ## extrapolation 'extrap'\n  if (isempty (extrap))\n    if (iscomplex (Z))\n      extrap = complex (NA, NA);\n    else\n      extrap = NA;\n    endif\n  endif\n\n  if (X(1) < X(end))\n    if (Y(1) < Y(end))\n      ZI(XI < X(1,1) | XI > X(end) | YI < Y(1,1) | YI > Y(end)) = extrap;\n    else\n      ZI(XI < X(1) | XI > X(end) | YI < Y(end) | YI > Y(1)) = extrap;\n    endif\n  else\n    if (Y(1) < Y(end))\n      ZI(XI < X(end) | XI > X(1) | YI < Y(1) | YI > Y(end)) = extrap;\n    else\n      ZI(XI < X(1,end) | XI > X(1) | YI < Y(end) | YI > Y(1)) = extrap;\n    endif\n  endif\n\nendfunction\n\nfunction b = isgriddata (X)\n  d1 = diff (X, 1, 1);\n  b = ! any (d1(:) != 0);\nendfunction\n\n## cubic convolution kernel with a = -0.5 for MATLAB compatibility.\nfunction w = cubic (h)\n\n  absh = abs (h);\n  absh01 = absh <= 1;\n  absh12 = absh <= 2 & ! absh01;\n  absh_sqr = absh .* absh;\n  absh_cube = absh_sqr .* absh;\n  w = ...  # for |h| <= 1\n      (1.5 * absh_cube - 2.5 * absh_sqr + 1) .* absh01 ...\n      ...  # for 1 < |h| <= 2\n      + (-0.5 * absh_cube + 2.5 * absh_sqr - 4 * absh + 2) .* absh12;\n\nendfunction\n\n## bicubic interpolation of full matrix in one direction with vector\nfunction out = conv_interp_vec (Z, XY, XIYI, kernel, kernel_bounds, axis)\n\n  ## allocate output\n  out_shape = size (Z);\n  out_shape(axis) = length (XIYI);\n  out = zeros (out_shape);\n\n  ## get indexes and distances h\n  spread = abs (XY(1) - XY(2));\n  idx = lookup (XY, XIYI, \"l\");\n  h = (XIYI - XY(idx)) / spread;\n  idx += -kernel_bounds(1) - 1;  # apply padding for indexes\n\n  ## interpolate\n  for shift = kernel_bounds(1)+1 : kernel_bounds(2)\n    if (axis == 1)\n      out += Z(idx + shift, :) .* kernel (shift - h);\n    else\n      out += Z(:, idx + shift) .* kernel (shift - h);\n    endif\n  endfor\n\nendfunction\n\n## bicubic interpolation of arbitrary XI-YI-pairs\nfunction out = conv_interp_pairs (Z, X, Y, XI, YI, kernel, kernel_bounds)\n\n  spread_x = abs (X(1, 1) - X(1, 2));\n  spread_y = abs (Y(1, 1) - Y(2, 1));\n  idx_x = lookup (X, XI, \"l\");\n  idx_y = lookup (Y, YI, \"l\");\n  h_x = (XI - reshape (X(idx_x), size (idx_x))) / spread_x;\n  h_y = (YI - reshape (Y(idx_y), size (idx_y))) / spread_y;\n\n  ## adjust indexes for padding\n  idx_x += -kernel_bounds(1) - 1;\n  idx_y += -kernel_bounds(1) - 1;\n\n  shifts = kernel_bounds(1)+1 : kernel_bounds(2);\n  [SX(1,1,:,:), SY(1,1,:,:)] = meshgrid (shifts, shifts);\n  pixels = Z(sub2ind (size (Z), idx_y + SY, idx_x + SX));\n  kernel_y = kernel (reshape (shifts, 1, 1, [], 1) - h_y);\n  kernel_x = kernel (reshape (shifts, 1, 1, 1, []) - h_x);\n  out_x = sum (pixels .* kernel_x, 4);\n  out = sum (out_x .* kernel_y, 3);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! A = [13,-1,12;5,4,3;1,6,2];\n%! x = [0,1,4];  y = [10,11,12];\n%! xi = linspace (min (x), max (x), 17);\n%! yi = linspace (min (y), max (y), 26).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"linear\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x,y,A] = peaks (10);\n%! x = x(1,:).';  y = y(:,1);\n%! xi = linspace (min (x), max (x), 41);\n%! yi = linspace (min (y), max (y), 41).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"linear\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! A = [13,-1,12;5,4,3;1,6,2];\n%! x = [0,1,4];  y = [10,11,12];\n%! xi = linspace (min (x), max (x), 17);\n%! yi = linspace (min (y), max (y), 26).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"nearest\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x,y,A] = peaks (10);\n%! x = x(1,:).';  y = y(:,1);\n%! xi = linspace (min (x), max (x), 41);\n%! yi = linspace (min (y), max (y), 41).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"nearest\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! A = [13,-1,12;5,4,3;1,6,2];\n%! x = [0,1,2];  y = [10,11,12];\n%! xi = linspace (min (x), max (x), 17);\n%! yi = linspace (min (y), max (y), 26).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"pchip\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x,y,A] = peaks (10);\n%! x = x(1,:).';  y = y(:,1);\n%! xi = linspace (min (x), max (x), 41);\n%! yi = linspace (min (y), max (y), 41).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"pchip\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! A = [13,-1,12;5,4,3;1,6,2];\n%! x = [0,1,2];  y = [10,11,12];\n%! xi = linspace (min (x), max (x), 17);\n%! yi = linspace (min (y), max (y), 26).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"cubic\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x,y,A] = peaks (10);\n%! x = x(1,:).';  y = y(:,1);\n%! xi = linspace (min (x), max (x), 41);\n%! yi = linspace (min (y), max (y), 41).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"cubic\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! A = [13,-1,12;5,4,3;1,6,2];\n%! x = [0,1,2];  y = [10,11,12];\n%! xi = linspace (min (x), max (x), 17);\n%! yi = linspace (min (y), max (y), 26).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"spline\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x,y,A] = peaks (10);\n%! x = x(1,:).';  y = y(:,1);\n%! xi = linspace (min (x), max (x), 41);\n%! yi = linspace (min (y), max (y), 41).';\n%! mesh (xi,yi,interp2 (x,y,A,xi,yi, \"spline\"));\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x,y,A,\"b*\"); hold off;\n\n%!shared x, y, orig, xi, yi, expected\n%!test  # simple test\n%! x = [1,2,3];\n%! y = [4,5,6,7];\n%! [X, Y] = meshgrid (x, y);\n%! orig = X.^2 + Y.^3;\n%! xi = [0.8, 1.2, 2.0, 1.5];\n%! yi = [6.2, 4.0, 5.0, 7.1].';\n%!\n%! # check nearest neighbor\n%! expected = ...\n%!   [NA, 217, 220, 220;\n%!    NA,  65,  68,  68;\n%!    NA, 126, 129, 129;\n%!    NA,  NA,  NA,  NA];\n%! result = interp2 (x, y, orig, xi, yi, \"nearest\");\n%! assert (result, expected);\n%!\n%! # check invariance of translation\n%! result = interp2 (x+3, y-7, orig, xi+3, yi-7, \"nearest\");\n%! assert (result, expected);\n%!\n%! # check invariance of scaling\n%! result = interp2 (x*3, y*(-7), orig, xi*3, yi*(-7), \"nearest\");\n%! assert (result, expected);\n%!\n%! # check interpolation with index pairs\n%! result = interp2 (x, y, orig, xi(2:4), yi(1:3).', \"nearest\");\n%! assert (result, expected(sub2ind(size(expected), 1:3, 2:4)));\n%!\n%! # check bilinear interpolation\n%! expected = ...\n%!   [NA, 243,     245.4,   243.9;\n%!    NA,  65.6,    68,      66.5;\n%!    NA, 126.6,   129,     127.5;\n%!    NA,  NA,      NA,      NA];\n%! result = interp2 (x, y, orig, xi, yi);\n%! assert (result, expected, 1000*eps);\n%!\n%! # check invariance of translation\n%! result = interp2 (x+3, y-7, orig, xi+3, yi-7);\n%! assert (result, expected, 1000*eps);\n%!\n%! # check invariance of scaling\n%! result = interp2 (x*3, y*(-7), orig, xi*3, yi*(-7));\n%! assert (result, expected, 1000*eps);\n%!\n%! # check interpolation with index pairs\n%! result = interp2 (x, y, orig, xi(2:4), yi(1:3).');\n%! assert (result, expected(sub2ind(size(expected), 1:3, 2:4)), 1000*eps);\n%!\n%! # check spline interpolation\n%! expected = ...\n%!   [238.968,  239.768,  242.328,  240.578;\n%!     64.64,    65.44,    68,       66.25;\n%!    125.64,   126.44,   129,      127.25;\n%!    358.551,  359.351,  361.911,  360.161];\n%! result = interp2 (x, y, orig, xi, yi, \"spline\");\n%! assert (result, expected, 1000*eps);\n%!\n%! # check invariance of translation\n%! result = interp2 (x+3, y-7, orig, xi+3, yi-7, \"spline\");\n%! assert (result, expected, 1000*eps);\n%!\n%! # check invariance of scaling\n%! result = interp2 (x*3, y*(-7), orig, xi*3, yi*(-7), \"spline\");\n%! assert (result, expected, 1000*eps);\n%!\n%!test <62133>\n%! # FIXME: spline interpolation does not support index pairs, Matlab does.\n%! result = interp2 (x, y, orig, xi(2:4), yi(1:3).', \"spline\");\n%! assert (result, expected(sub2ind(size(expected), 1:3, 2:4)), 1000*eps);\n%!\n%!test <*61754>\n%! # check bicubic interpolation\n%! expected = ...\n%!   [NA, 239.96,  242.52,  240.77;\n%!    NA,  65.44,   68,      66.25;\n%!    NA, 126.44,  129,     127.25;\n%!    NA,  NA,      NA,      NA];\n%! result = interp2 (x, y, orig, xi, yi, \"cubic\");\n%! assert (result, expected, 10000*eps);\n%!\n%! # check invariance of translation\n%! result = interp2 (x+3, y-7, orig, xi+3, yi-7, \"cubic\");\n%! assert (result, expected, 10000*eps);\n%!\n%! # check invariance of scaling\n%! result = interp2 (x*3, y*(-7), orig, xi*3, yi*(-7), \"cubic\");\n%! assert (result, expected, 10000*eps);\n%!\n%! # check interpolation with index pairs\n%! result = interp2 (x, y, orig, xi(2:4), yi(1:3).', \"cubic\");\n%! assert (result, expected(sub2ind(size(expected), 1:3, 2:4)), 10000*eps);\n\n## Test that interpolating a complex matrix is equivalent to interpolating its\n## real and imaginary parts separately.\n%!test <*61863>\n%! xi = [2.5, 3.5];\n%! yi = [0.5, 1.5].';\n%! orig = rand (4, 3) + 1i * rand (4, 3);\n%! for method = {\"nearest\", \"linear\", \"pchip\", \"cubic\", \"spline\"}\n%!   interp_complex = interp2 (orig, xi, yi, method{1});\n%!   interp_real = interp2 (real (orig), xi, yi, method{1});\n%!   interp_imag = interp2 (imag (orig), xi, yi, method{1});\n%!   assert (real (interp_complex), interp_real);\n%!   assert (imag (interp_complex), interp_imag);\n%! endfor\n\n%!test  # 2^n refinement form\n%! x = [1,2,3];\n%! y = [4,5,6,7];\n%! [X, Y] = meshgrid (x, y);\n%! orig = X.^2 + Y.^3;\n%! xi = [1:0.25:3];  yi = [4:0.25:7].';\n%! expected = interp2 (x,y,orig, xi, yi);\n%! result = interp2 (orig, 2);\n%!\n%! assert (result, expected, 10*eps);\n\n%!test  # matrix slice\n%! A = eye (4);\n%! assert (interp2 (A,[1:4],[1:4]), [1,1,1,1]);\n\n%!test  # non-gridded XI,YI\n%! A = eye (4);\n%! assert (interp2 (A,[1,2;3,4],[1,3;2,4]), [1,0;0,1]);\n\n%!test  # for values outside of boundaries\n%! x = [1,2,3];\n%! y = [4,5,6,7];\n%! [X, Y] = meshgrid (x,y);\n%! orig = X.^2 + Y.^3;\n%! xi = [0,4];\n%! yi = [3,8].';\n%! assert (interp2 (x,y,orig, xi, yi), [NA,NA;NA,NA]);\n%! assert (interp2 (x,y,orig, xi, yi,\"linear\", 0), [0,0;0,0]);\n%! assert (interp2 (x,y,orig, xi, yi,\"linear\", 2), [2,2;2,2]);\n%! assert (interp2 (x,y,orig, xi, yi,\"spline\", 2), [2,2;2,2]);\n%! assert (interp2 (x,y,orig, xi, yi,\"linear\", 0+1i), [0+1i,0+1i;0+1i,0+1i]);\n%! assert (interp2 (x,y,orig, xi, yi,\"spline\"), [27,43;512,528]);\n%! assert (interp2 (x,y,orig, xi, yi,\"cubic\"), [NA,NA;NA,NA]);\n%! assert (interp2 (x,y,orig, xi, yi,\"cubic\", 2), [2,2;2,2]);\n\n%!test  # for values at boundaries\n%! A = [1,2;3,4];\n%! x = [0,1];\n%! y = [2,3].';\n%! assert (interp2 (x,y,A,x,y,\"linear\"), A);\n%! assert (interp2 (x,y,A,x,y,\"nearest\"), A);\n\n%!test  # for Matlab-compatible rounding for 'nearest'\n%! X = meshgrid (1:4);\n%! assert (interp2 (X, 2.5, 2.5, \"nearest\"), 3);\n\n## re-order monotonically decreasing\n%!assert <*41838> (interp2 ([1 2 3], [3 2 1], magic (3), 2.5, 3), 3.5)\n%!assert <*41838> (interp2 ([3 2 1], [1 2 3], magic (3), 1.5, 1), 3.5)\n\n## Linear interpretation with vector XI doesn't lead to matrix output\n%!assert <*49506> (interp2 ([2 3], [2 3 4], [1 2; 3 4; 5 6], [2 3], 3, \"linear\"), [3 4])\n\n%!shared z, zout, tol\n%! z = [1 3 5; 3 5 7; 5 7 9];\n%! zout = [1 2 3 4 5; 2 3 4 5 6; 3 4 5 6 7; 4 5 6 7 8; 5 6 7 8 9];\n%! tol = 2 * eps;\n%!\n%!assert (interp2 (z), zout, tol)\n%!assert (interp2 (z, \"linear\"), zout, tol)\n%!assert (interp2 (z, \"pchip\"), zout, tol)\n%!assert (interp2 (z, \"cubic\"), zout, tol)\n%!assert (interp2 (z, \"spline\"), zout, tol)\n%!assert (interp2 (z, [2 3 1], [2 2 2].', \"linear\"),\n%!        repmat ([5, 7, 3], [3, 1]), tol)\n%!assert (interp2 (z, [2 3 1], [2 2 2].', \"pchip\"),\n%!        repmat ([5, 7, 3], [3, 1]), tol)\n%!assert (interp2 (z, [2 3 1], [2 2 2].', \"cubic\"),\n%!        repmat ([5, 7, 3], [3, 1]), tol)\n%!assert (interp2 (z, [2 3 1], [2 2 2].', \"spline\"),\n%!        repmat ([5, 7, 3], [3, 1]), tol)\n%!assert (interp2 (z, [2 3 1], [2 2 2], \"linear\"), [5 7 3], tol)\n%!assert (interp2 (z, [2 3 1], [2 2 2], \"pchip\"), [5 7 3], tol)\n%!assert (interp2 (z, [2 3 1], [2 2 2], \"cubic\"), [5 7 3], tol)\n%!assert (interp2 (z, [2 3 1], [2 2 2], \"spline\"), [5 7 3], tol)\n%!assert (interp2 (z, [3; 3; 3], [2; 3; 1], \"linear\"), [7; 9; 5], tol)\n%!assert (interp2 (z, [3; 3; 3], [2; 3; 1], \"pchip\"), [7; 9; 5], tol)\n%!assert (interp2 (z, [3; 3; 3], [2; 3; 1], \"cubic\"), [7; 9; 5], tol)\n%!test <62132>\n%! # FIXME: single column yields single row with spline interpolation (numbers are correct)\n%! assert (interp2 (z, [3; 3; 3], [2; 3; 1], \"spline\"), [7; 9; 5], tol);\n\n## Test input validation\n%!error interp2 (1, 1, 1, 1, 1, 2)    # only 5 numeric inputs\n%!error interp2 (1, 1, 1, 1, 1, 2, 2) # only 5 numeric inputs\n%!error <Z must be a numeric 2-D matrix> interp2 ({1})\n%!error <Z must be a numeric 2-D matrix> interp2 (true)\n%!error <Z must be a numeric 2-D matrix> interp2 (1:10)\n%!error <Z must be a numeric 2-D matrix> interp2 ([1:10].')\n%!error <Z must be a numeric 2-D matrix> interp2 (1,1,1)\n%!error <Z must be a numeric 2-D matrix> interp2 (ones (2,2,2))\n%!error <N must be an integer .= 0> interp2 (ones (2), ones (2))\n%!error <N must be an integer .= 0> interp2 (ones (2), -1)\n%!error <N must be an integer .= 0> interp2 (ones (2), 1.5)\n%!warning <ignoring unsupported '\\*' flag> interp2 (rand (3,3), 1, \"*linear\");\n%!error <EXTRAP must be a numeric scalar> interp2 (1, 1, 1, 1, 1, \"linear\", {1})\n%!error <EXTRAP must be a numeric scalar> interp2 (1, 1, 1, 1, 1, \"linear\", ones (2,2))\n%!error <EXTRAP must be a numeric scalar> interp2 (1, 1, 1, 1, 1, \"linear\", \"abc\")\n%!error <EXTRAP must be a numeric scalar> interp2 (1, 1, 1, 1, 1, \"linear\", \"extrap\")\n%!error <X, Y must be numeric matrices> interp2 ({1}, 1, ones (2), 1, 1)\n%!error <X, Y must be numeric matrices> interp2 (1, {1}, ones (2), 1, 1)\n%!error <XI, YI must be numeric> interp2 (1, 1, ones (2), {1}, 1)\n%!error <XI, YI must be numeric> interp2 (1, 1, ones (2), 1, {1})\n%!error <X and Y must be matrices of equal size> interp2 (ones (2,2), 1, ones (2), 1, 1)\n%!error <X and Y must be matrices of equal size> interp2 (ones (2,2), ones (2,3), ones (2), 1, 1)\n%!error <X and Y size must match the dimensions of Z> interp2 (1:3, 1:3, ones (3,2), 1, 1)\n%!error <X and Y size must match the dimensions of Z> interp2 (1:2, 1:2, ones (3,2), 1, 1)\n%!error <X must be strictly monotonic> interp2 ([1 0 2], 1:3, ones (3,3), 1, 1)\n%!error <Y must be strictly monotonic> interp2 (1:3, [1 0 2], ones (3,3), 1, 1)\n%!warning <cubic requires at least 3 points in each dimension.> interp2 (eye(2), 1.5, 1.5, \"cubic\");\n%!error <XI and YI must be matrices of equal size> interp2 (1:2, 1:2, ones (2), ones (2,2), 1)\n%!error <XI and YI must be matrices of equal size> interp2 (1:2, 1:2, ones (2), 1, ones (2,2))\n%!error <XI, YI must have uniform spacing> interp2 (1:2, 1:2, ones (2), [1 2 4], [1 2 3], \"spline\")\n%!error <XI, YI must have uniform spacing> interp2 (1:2, 1:2, ones (2), [1 2 3], [1 2 4], \"spline\")\n%!error interp2 (1, 1, 1, 1, 1, \"foobar\")\n"
  },
  {
    "path": "scripts/general/interp3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{vi} =} interp3 (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi})\n## @deftypefnx {} {@var{vi} =} interp3 (@var{v}, @var{xi}, @var{yi}, @var{zi})\n## @deftypefnx {} {@var{vi} =} interp3 (@var{v}, @var{n})\n## @deftypefnx {} {@var{vi} =} interp3 (@var{v})\n## @deftypefnx {} {@var{vi} =} interp3 (@dots{}, @var{method})\n## @deftypefnx {} {@var{vi} =} interp3 (@dots{}, @var{method}, @var{extrapval})\n##\n## Three-dimensional interpolation.\n##\n## Interpolate numeric reference data @var{x}, @var{y}, @var{z}, @var{v} to\n## determine @var{vi} at the coordinates @var{xi}, @var{yi}, @var{zi}.  The\n## reference data @var{x}, @var{y}, @var{z} can be matrices, as returned by\n## @code{meshgrid}, in which case the sizes of @var{x}, @var{y}, @var{z}, and\n## @var{v} must be equal.  If @var{x}, @var{y}, @var{z} are vectors describing\n## a cubic grid then @code{length (@var{x}) == columns (@var{v})},\n## @code{length (@var{y}) == rows (@var{v})}, and\n## @code{length (@var{z}) == size (@var{v}, 3)}.  In either case the input\n## data must be strictly monotonic.\n##\n## If called without @var{x}, @var{y}, @var{z}, and just a single reference\n## data matrix @var{v}, the 3-D region\n## @code{@var{x} = 1:columns (@var{v}), @var{y} = 1:rows (@var{v}),\n## @var{z} = 1:size (@var{v}, 3)} is assumed.\n## This saves memory if the grid is regular and the distance between points is\n## not important.\n##\n## If called with a single reference data matrix @var{v} and a refinement\n## value @var{n}, then perform interpolation over a 3-D grid where each\n## original interval has been recursively subdivided @var{n} times.  This\n## results in @code{2^@var{n}-1} additional points for every interval in the\n## original grid.  If @var{n} is omitted a value of 1 is used.  As an\n## example, the interval [0,1] with @code{@var{n}==2} results in a refined\n## interval with points at [0, 1/4, 1/2, 3/4, 1].\n##\n## The interpolation @var{method} is one of:\n##\n## @table @asis\n## @item @qcode{\"nearest\"}\n## Return the nearest neighbor.\n##\n## @item @qcode{\"linear\"} (default)\n## Linear interpolation from nearest neighbors.\n##\n## @item @qcode{\"cubic\"}\n## Piecewise cubic Hermite interpolating polynomial---shape-preserving\n## interpolation with smooth first derivative (not implemented yet).\n##\n## @item @qcode{\"spline\"}\n## Cubic spline interpolation---smooth first and second derivatives\n## throughout the curve.\n## @end table\n##\n## @var{extrapval} is a scalar number.  It replaces values beyond the endpoints\n## with @var{extrapval}.  Note that if @var{extrapval} is used, @var{method}\n## must be specified as well.  If @var{extrapval} is omitted and the\n## @var{method} is @qcode{\"spline\"}, then the extrapolated values of the\n## @qcode{\"spline\"} are used.  Otherwise the default @var{extrapval} value for\n## any other @var{method} is @qcode{\"NA\"}.\n## @seealso{interp1, interp2, interpn, meshgrid}\n## @end deftypefn\n\n## FIXME: Need to add support for 'cubic' method (maybe change interpn).\n\nfunction vi = interp3 (varargin)\n\n  narginchk (1,9);\n\n  method = \"linear\";\n  extrapval = [];\n  nargs = nargin;\n\n  if (! isnumeric (varargin{1}))\n    error (\"interp3: input reference arrays must be numeric\");\n  endif\n\n  if (nargs > 1 && ischar (varargin{end-1}))\n    if (! isnumeric (varargin{end}) || ! isscalar (varargin{end}))\n      error (\"interp3: EXTRAPVAL must be a numeric scalar\");\n    endif\n    extrapval = varargin{end};\n    method = varargin{end-1};\n    nargs -= 2;\n  elseif (ischar (varargin{end}))\n    method = varargin{end};\n    nargs -= 1;\n  endif\n\n  if (method(1) == \"*\")\n    warning (\"interp3: ignoring unsupported '*' flag to METHOD\");\n    method(1) = [];\n  endif\n  method = validatestring (method, {\"nearest\", \"linear\", \"cubic\", \"spline\"});\n\n  if (nargs < 3)\n    ## Calling form interp3 (v) OR interp3 (v, n)\n    v = varargin{1};\n    if (ndims (v) != 3)\n      error (\"interp3: V must be a 3-D array of values\");\n    endif\n    n = varargin(2:nargs);\n    v = permute (v, [2, 1, 3]);\n    if (isempty (extrapval))\n      vi = interpn (v, n{:}, method);\n    else\n      vi = interpn (v, n{:}, method, extrapval);\n    endif\n\n  elseif (nargs == 4 && ! isvector (varargin{1}))\n    ## Calling form interp3 (v, xi, yi, zi)\n    v = varargin{1};\n    if (ndims (v) != 3)\n      error (\"interp3: V must be a 3-D array of values\");\n    endif\n    xi = varargin(2:4);\n    if (any (! cellfun ('isvector', xi)))\n      ## Meshgridded values rather than vectors\n      if (! size_equal (xi{:}))\n        error (\"interp3: XI, YI, and ZI dimensions must be equal\");\n      endif\n      for i = 1 : 3\n        xi{i} = permute (xi{i}, [2, 1, 3]);\n      endfor\n    endif\n    v = permute (v, [2, 1, 3]);\n    if (isempty (extrapval))\n      vi = interpn (v, xi{:}, method);\n    else\n      vi = interpn (v, xi{:}, method, extrapval);\n    endif\n\n  elseif (nargs == 7)\n    ## Calling form interp3 (x, y, z, v, xi, yi, zi)\n    v = varargin{4};\n    if (ndims (v) != 3)\n      error (\"interp3: V must be a 3-D array of values\");\n    endif\n    x = varargin(1:3);\n    if (any (! cellfun ('isvector', x)))\n      ## Meshgridded values rather than vectors\n      if (! size_equal (x{:}, v))\n        error (\"interp3: X, Y, Z, and V dimensions must be equal\");\n      endif\n      for i = 1 : 3\n        x{i} = permute (x{i}, [2, 1, 3]);\n      endfor\n    endif\n    xi = varargin(5:7);\n    if (any (! cellfun ('isvector', xi)))\n      ## Meshgridded values rather than vectors\n      if (! size_equal (xi{:}))\n        error (\"interp3: XI, YI, and ZI dimensions must be equal\");\n      endif\n      for i = 1 : 3\n        xi{i} = permute (xi{i}, [2, 1, 3]);\n      endfor\n    endif\n    v = permute (v, [2, 1, 3]);\n    if (isempty (extrapval))\n      vi = interpn (x{:}, v, xi{:}, method);\n    else\n      vi = interpn (x{:}, v, xi{:}, method, extrapval);\n    endif\n\n  else\n    error (\"interp3: wrong number or incorrectly formatted input arguments\");\n  endif\n\n  if (! isvector (vi))\n    vi = ipermute (vi, [2, 1, 3]);\n  endif\n\nendfunction\n\n\n## FIXME: Need some demo blocks here to show off the function like interp2.m.\n\n%!test  # basic test\n%! x = y = z = -1:1;  y = y + 2;\n%! f = @(x,y,z) x.^2 - y - z.^2;\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! v = f (xx,yy,zz);\n%! xi = yi = zi = -1:0.5:1;  yi = yi + 2.1;\n%! [xxi, yyi, zzi] = meshgrid (xi, yi, zi);\n%! vi = interp3 (x, y, z, v, xxi, yyi, zzi);\n%! [xxi, yyi, zzi] = ndgrid (yi, xi, zi);\n%! vi2 = interpn (y, x, z, v, xxi, yyi, zzi);\n%! assert (vi, vi2, 10*eps);\n\n%!test  # meshgridded xi, yi, zi\n%! x = z = 1:2;  y = 1:3;\n%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];\n%! xi = zi = .6:1.6;  yi = 1;\n%! [xxi3, yyi3, zzi3] = meshgrid (xi, yi, zi);\n%! [xxi, yyi, zzi] = ndgrid (yi, xi, zi);\n%! vi = interp3 (x, y, z, v, xxi3, yyi3, zzi3, \"nearest\");\n%! vi2 = interpn (y, x, z, v, xxi, yyi, zzi, \"nearest\");\n%! assert (vi, vi2);\n\n%!test  # vector xi, yi, zi\n%! x = z = 1:2;  y = 1:3;\n%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];\n%! xi = zi = .6:1.6;  yi = 1;\n%! vi = interp3 (x, y, z, v, xi, yi, zi, \"nearest\");\n%! vi2 = interpn (y, x, z, v, yi, xi, zi, \"nearest\");\n%! assert (vi, vi2);\n\n%!test  # vector xi+1 with extrap value\n%! x = z = 1:2;  y = 1:3;\n%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];\n%! xi = zi = .6:1.6;  yi = 1;\n%! vi = interp3 (x, y, z, v, xi+1, yi, zi, \"nearest\", 3);\n%! vi2 = interpn (y, x, z, v, yi, xi+1, zi, \"nearest\", 3);\n%! assert (vi, vi2);\n\n%!test  # input value matrix--no x,y,z\n%! x = z = 1:2;  y = 1:3;\n%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];\n%! xi = zi = .6:1.6;  yi = 1;\n%! vi = interp3 (v, xi, yi, zi, \"nearest\");\n%! vi2 = interpn (v, yi, xi, zi, \"nearest\");\n%! assert (vi, vi2);\n\n%!test  # input value matrix--no x,y,z, with extrap value\n%! x = z = 1:2;  y = 1:3;\n%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];\n%! xi = zi = .6:1.6;  yi = 1;\n%! vi = interp3 (v, xi, yi, zi, \"nearest\", 3);\n%! vi2 = interpn (v, yi, xi, zi, \"nearest\", 3);\n%! assert (vi, vi2);\n\n%!test  # extrapolation\n%! X = [0,0.5,1];  Y=X;  Z=X;\n%! V = zeros (3,3,3);\n%! V(:,:,1) = [1 3 5; 3 5 7; 5 7 9];\n%! V(:,:,2) = V(:,:,1) + 2;\n%! V(:,:,3) = V(:,:,2) + 2;\n%! tol = 10 * eps;\n%! x = y = z = [-0.1,0,0.1];\n%! assert (interp3 (X,Y,Z,V,x,y,z,\"spline\"), [-0.2, 1.0, 2.2], tol);\n%! assert (interp3 (X,Y,Z,V,x,y,z,\"linear\"), [NA, 1.0, 2.2], tol);\n%! assert (interp3 (X,Y,Z,V,x,y,z,\"spline\", 0), [0, 1.0, 2.2], tol);\n%! assert (interp3 (X,Y,Z,V,x,y,z,\"linear\", 0), [0, 1.0, 2.2], tol);\n\n%!shared z, zout, tol\n%! z = zeros (3, 3, 3);\n%! zout = zeros (5, 5, 5);\n%! z(:,:,1) = [1 3 5; 3 5 7; 5 7 9];\n%! z(:,:,2) = z(:,:,1) + 2;\n%! z(:,:,3) = z(:,:,2) + 2;\n%! for n = 1:5\n%!   zout(:,:,n) = [1 2 3 4 5;\n%!                  2 3 4 5 6;\n%!                  3 4 5 6 7;\n%!                  4 5 6 7 8;\n%!                  5 6 7 8 9] + (n-1);\n%! endfor\n%! tol = 10 * eps;\n%!\n%!assert (interp3 (z), zout, tol)\n%!assert (interp3 (z, \"linear\"), zout, tol)\n%!assert (interp3 (z, \"spline\"), zout, tol)\n\n%!test <*57450>\n%! [x, y, z] = meshgrid (1:10);\n%! v = x;\n%! xi = yi = zi = linspace (1, 10, 20).';\n%! vi = interp3 (x, y, z, v, xi, yi, zi);\n%! assert (size (vi), [20, 1]);\n\n## Test input validation\n%!error <not enough input arguments> interp3 ()\n%!error <input reference arrays must be numeric> interp3 ({1})\n%!error <input reference arrays must be numeric> interp3 (true)\n%!error <input reference arrays must be numeric> interp3 (struct())\n%!error <EXTRAPVAL must be a numeric scalar> interp3 (1,2,3,4,1,2,3,\"linear\", {1})\n%!error <EXTRAPVAL must be a numeric scalar> interp3 (1,2,3,4,1,2,3,\"linear\", ones (2,2))\n%!warning <ignoring unsupported '\\*' flag> interp3 (rand (3,3,3), 1, \"*linear\");\n%!error <V must be a 3-D array> interp3 (ones (2,2))\n%!error <V must be a 3-D array> interp3 (ones (2,2), 1,1,1)\n%!error <XI, YI, and ZI dimensions must be equal> interp3 (ones (2,2,2), 1,1, ones (2,2))\n%!error <V must be a 3-D array> interp3 (1:2, 1:2, 1:2, ones (2,2), 1,1,1)\n%!error <X, Y, Z, and V dimensions must be equal> interp3 (ones (1,2,2), ones (2,2,2), ones (2,2,2), ones (2,2,2), 1,1,1)\n%!error <XI, YI, and ZI dimensions must be equal> interp3 (1:2, 1:2, 1:2, rand (2,2,2), 1,1, ones (2,2))\n%!error <wrong number .* input arguments> interp3 (1:2, 1:2, 1:2)\n"
  },
  {
    "path": "scripts/general/interpft.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} interpft (@var{x}, @var{n})\n## @deftypefnx {} {@var{y} =} interpft (@var{x}, @var{n}, @var{dim})\n##\n## Fourier interpolation.\n##\n## If @var{x} is a vector then @var{x} is resampled with @var{n} points.  The\n## data in @var{x} is assumed to be equispaced.  If @var{x} is a matrix or an\n## N-dimensional array, the interpolation is performed on each column of\n## @var{x}.\n##\n## If @var{dim} is specified, then interpolate along the dimension @var{dim}.\n##\n## @code{interpft} assumes that the interpolated function is periodic, and so\n## assumptions are made about the endpoints of the interpolation.\n## @seealso{interp1}\n## @end deftypefn\n\nfunction y = interpft (x, n, dim)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (isscalar (n) && n == fix (n)))\n    error (\"interpft: N must be a scalar integer\");\n  endif\n\n  if (nargin == 2)\n    if (isrow (x))\n      dim = 2;\n    else\n      dim = 1;\n    endif\n  endif\n\n  nd = ndims (x);\n\n  if (dim < 1 || dim > nd)\n    error (\"interpft: invalid dimension DIM\");\n  endif\n\n  perm = [dim:nd, 1:(dim-1)];\n  x = permute (x, perm);\n  m = rows (x);\n\n  inc = ceil (m/n);\n  xfft = fft (x) / m;\n  k = ceil (m / 2);\n  sz = size (x);\n  sz(1) = n * inc - m;\n\n  idx = repmat ({':'}, nd, 1);\n  idx{1} = 1:k;\n  y = cat (1, xfft(idx{:}), zeros (sz));\n  idx{1} = k+1:m;\n  y = cat (1, y, xfft(idx{:}));\n\n  ## When m is an even number of rows, the FFT has a single Nyquist bin.\n  ## If zero-padded above, distribute the value of the Nyquist bin evenly\n  ## between the new corresponding positive and negative frequency bins.\n  if (sz(1) > 0 && k == m/2)\n    idx{1} = n * inc - k + 1;\n    tmp = y(idx{:}) / 2;\n    y(idx{:}) = tmp;\n    idx{1} = k + 1;\n    y(idx{:}) = tmp;\n  endif\n\n  y = n * ifft (y);\n\n  if (inc != 1)\n    sz(1) = n;\n    y = inc * reshape (y(1:inc:end), sz);\n  endif\n\n  y = ipermute (y, perm);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! t = 0 : 0.3 : pi;  dt = t(2)-t(1);\n%! n = length (t);  k = 100;\n%! ti = t(1) + [0 : k-1]*dt*n/k;\n%! y = sin (4*t + 0.3) .* cos (3*t - 0.1);\n%! yp = sin (4*ti + 0.3) .* cos (3*ti - 0.1);\n%! plot (ti, yp, 'g', ti, interp1 (t, y, ti, \"spline\"), 'b', ...\n%!       ti, interpft (y, k), 'c', t, y, \"r+\");\n%! legend (\"sin (4t+0.3)cos (3t-0.1)\", \"spline\", \"interpft\", \"data\");\n\n%!shared n,y\n%! x = [0:10]';  y = sin(x);  n = length (x);\n%!testif HAVE_FFTW\n%! assert (interpft (y, n), y, 20*eps);\n%!testif HAVE_FFTW\n%! assert (interpft (y', n), y', 20*eps);\n%!testif HAVE_FFTW\n%! assert (interpft ([y,y],n), [y,y], 20*eps);\n\n## Test case with complex input\n%!testif HAVE_FFTW <*39566>\n%! x = (1 + j) * [1:4]';\n%! y = ifft ([15 + 15*j; -6; -1.5 - 1.5*j; 0; -1.5 - 1.5*j; -6*j]);\n%! assert (interpft (x, 6), y, 10*eps);\n\n## Test for correct spectral symmetry with even/odd lengths\n%!testif HAVE_FFTW\n%! assert (max (abs (imag (interpft ([1:8], 20)))), 0, 20*eps);\n%!testif HAVE_FFTW\n%! assert (max (abs (imag (interpft ([1:8], 21)))), 0, 21*eps);\n%!testif HAVE_FFTW\n%! assert (max (abs (imag (interpft ([1:9], 20)))), 0, 20*eps);\n%!testif HAVE_FFTW\n%! assert (max (abs (imag (interpft ([1:9], 21)))), 0, 21*eps);\n\n## Test input validation\n%!error <Invalid call> interpft ()\n%!error <Invalid call> interpft (1)\n%!error <N must be a scalar integer> interpft (1,[2,2])\n%!error <N must be a scalar integer> interpft (1,2.1)\n%!error <invalid dimension DIM> interpft (1,2,0)\n%!error <invalid dimension DIM> interpft (1,2,3)\n"
  },
  {
    "path": "scripts/general/interpn.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{vi} =} interpn (@var{x1}, @var{x2}, @dots{}, @var{v}, @var{y1}, @var{y2}, @dots{})\n## @deftypefnx {} {@var{vi} =} interpn (@var{v}, @var{y1}, @var{y2}, @dots{})\n## @deftypefnx {} {@var{vi} =} interpn (@var{v}, @var{m})\n## @deftypefnx {} {@var{vi} =} interpn (@var{v})\n## @deftypefnx {} {@var{vi} =} interpn (@dots{}, @var{method})\n## @deftypefnx {} {@var{vi} =} interpn (@dots{}, @var{method}, @var{extrapval})\n##\n## Perform @var{n}-dimensional interpolation, where @var{n} is at least two.\n##\n## Each element of the @var{n}-dimensional numeric array @var{v} represents a\n## value at a location given by the parameters @var{x1}, @var{x2}, @dots{},\n## @var{xn}.  The parameters @var{x1}, @var{x2}, @dots{}, @var{xn} are either\n## @var{n}-dimensional arrays of the same size as the array @var{v} in\n## the @qcode{\"ndgrid\"} format or vectors.\n##\n## The parameters @var{y1}, @var{y2}, @dots{}, @var{yn} represent the points at\n## which the array @var{vi} is interpolated.  They can be vectors of the same\n## length and orientation in which case they are interpreted as coordinates of\n## scattered points.  If they are vectors of differing orientation or length,\n## they are used to form a grid in @qcode{\"ndgrid\"} format.  They can also be\n## @var{n}-dimensional arrays of equal size.\n##\n## If @var{x1}, @dots{}, @var{xn} are omitted, they are assumed to be\n## @code{x1 = 1 : size (@var{v}, 1)}, etc.  If @var{m} is specified, then\n## the interpolation adds a point half way between each of the interpolation\n## points.  This process is performed @var{m} times.  If only @var{v} is\n## specified, then @var{m} is assumed to be @code{1}.\n##\n## The interpolation @var{method} is one of:\n##\n## @table @asis\n## @item @qcode{\"nearest\"}\n## Return the nearest neighbor.\n##\n## @item @qcode{\"linear\"} (default)\n## Linear interpolation from nearest neighbors.\n##\n## @item @qcode{\"pchip\"}\n## Piecewise cubic Hermite interpolating polynomial---shape-preserving\n## interpolation with smooth first derivative (not implemented yet).\n##\n## @item @qcode{\"cubic\"}\n## Cubic interpolation (same as @qcode{\"pchip\"} [not implemented yet]).\n##\n## @item @qcode{\"spline\"}\n## Cubic spline interpolation---smooth first and second derivatives\n## throughout the curve.\n## @end table\n##\n## The default method is @qcode{\"linear\"}.\n##\n## @var{extrapval} is a scalar number.  It replaces values beyond the endpoints\n## with @var{extrapval}.  Note that if @var{extrapval} is used, @var{method}\n## must be specified as well.  If @var{extrapval} is omitted and the\n## @var{method} is @qcode{\"spline\"}, then the extrapolated values of the\n## @qcode{\"spline\"} are used.  Otherwise the default @var{extrapval} value for\n## any other @var{method} is @code{NA}.\n## @seealso{interp1, interp2, interp3, spline, ndgrid}\n## @end deftypefn\n\nfunction vi = interpn (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (varargin{1}))\n    error (\"interpn: input reference arrays must be numeric\");\n  endif\n\n  method = \"linear\";\n  extrapval = [];\n  nargs = nargin;\n\n  ## Find and validate EXTRAPVAL and/or METHOD inputs\n  if (nargs > 1 && ischar (varargin{end-1}))\n    if (! isnumeric (varargin{end}) || ! isscalar (varargin{end}))\n      error (\"interpn: EXTRAPVAL must be a numeric scalar\");\n    endif\n    extrapval = varargin{end};\n    method = varargin{end-1};\n    nargs -= 2;\n  elseif (ischar (varargin{end}))\n    method = varargin{end};\n    nargs -= 1;\n  endif\n\n  if (method(1) == \"*\")\n    warning (\"interpn: ignoring unsupported '*' flag to METHOD\");\n    method(1) = [];\n  endif\n  method = validatestring (method,\n                           {\"nearest\", \"linear\", \"pchip\", \"cubic\", \"spline\"},\n                           \"interpn\");\n\n  if (nargs <= 2)\n    ## Calling form interpn (V, ...)\n    v = varargin{1};\n    m = 1;\n    if (nargs == 2)\n      m = varargin{2};\n      if (! (isnumeric (m) && isscalar (m) && m == fix (m)))\n        print_usage ();\n      endif\n    endif\n    sz = size (v);\n    nd = ndims (v);\n    x = cell (1, nd);\n    y = cell (1, nd);\n    for i = 1 : nd\n      x{i} = 1 : sz(i);\n      y{i} = 1 : (1 / (2 ^ m)) : sz(i);\n    endfor\n    y{1} = y{1}.';\n    [y{:}] = ndgrid (y{:});\n  elseif (! isvector (varargin{1}) && nargs == (ndims (varargin{1}) + 1))\n    ## Calling form interpn (V, Y1, Y2, ...)\n    v = varargin{1};\n    sz = size (v);\n    nd = ndims (v);\n    x = cell (1, nd);\n    y = varargin(2 : nargs);\n    for i = 1 : nd\n      x{i} = 1 : sz(i);\n    endfor\n  elseif (rem (nargs, 2) == 1\n          && nargs == (2 * ndims (varargin{ceil (nargs / 2)})) + 1)\n    ## Calling form interpn (X1, X2, ..., V, Y1, Y2, ...)\n    nv = ceil (nargs / 2);\n    v = varargin{nv};\n    sz = size (v);\n    nd = ndims (v);\n    x = varargin(1 : (nv - 1));\n    y = varargin((nv + 1) : nargs);\n  else\n    error (\"interpn: wrong number or incorrectly formatted input arguments\");\n  endif\n\n  if (any (! cellfun (\"isvector\", x)))\n    for i = 1 : nd\n      if (! size_equal (x{i}, v))\n        error (\"interpn: incorrect dimensions for input X%d\", i);\n      endif\n      idx(1 : nd) = {1};\n      idx(i) = \":\";\n      x{i} = x{i}(idx{:})(:);\n    endfor\n  endif\n\n  all_vectors = all (cellfun (\"isvector\", y));\n  same_size = size_equal (y{:});\n  if (all_vectors && ! same_size)\n    [y{:}] = ndgrid (y{:});\n  endif\n\n  if (! strcmp (method, \"spline\") && isempty (extrapval))\n    if (iscomplex (v))\n      extrapval = NA + 1i*NA;\n    else\n      extrapval = NA;\n    endif\n  endif\n\n  if (strcmp (method, \"linear\"))\n    vi = __lin_interpn__ (x{:}, v, y{:});\n    vi(isna (vi)) = extrapval;\n  elseif (strcmp (method, \"nearest\"))\n    ## FIXME: This seems overly complicated.  Is there a way to simplify\n    ## all the code after the call to lookup (which should be fast)?\n    ## Could Qhull be used for quick nearest neighbor calculation?\n    yshape = size (y{1});\n    yidx = cell (1, nd);\n    ## Find rough nearest index using lookup function [O(log2 (N)].\n    for i = 1 : nd\n      y{i} = y{i}(:);\n      yidx{i} = lookup (x{i}, y{i}, \"lr\");\n    endfor\n    ## Single comparison to next largest index to see which is closer.\n    idx = cell (1,nd);\n    for i = 1 : nd\n      idx{i} = yidx{i} ...\n               + (y{i} - x{i}(yidx{i})(:) >= x{i}(yidx{i} + 1)(:) - y{i});\n    endfor\n    vi = v(sub2ind (sz, idx{:}));\n    ## Apply EXTRAPVAL to points outside original volume.\n    idx = false (prod (yshape), 1);\n    for i = 1 : nd\n      idx |= y{i} < min (x{i}(:)) | y{i} > max (x{i}(:));\n    endfor\n    vi(idx) = extrapval;\n    vi = reshape (vi, yshape);\n  elseif (strcmp (method, \"spline\"))\n    if (any (! cellfun (\"isvector\", y)))\n      ysz = size (y{1});\n      for i = 1 : nd\n        if (any (size (y{i}) != ysz))\n          error (\"interpn: incorrect dimensions for input Y%d\", i);\n        endif\n        idx(1 : nd) = {1};\n        idx(i) = \":\";\n        y{i} = y{i}(idx{:});\n      endfor\n    endif\n\n    vi = __splinen__ (x, v, y, extrapval, \"interpn\");\n\n    if (size_equal (y{:}))\n      ly = length (y{1});\n      idx = cell (1, ly);\n      q = cell (1, nd);\n      for i = 1 : ly\n        q(:) = i;\n        idx{i} = q;\n      endfor\n      vi = vi(cellfun (@(x) sub2ind (size (vi), x{:}), idx));\n      vi = reshape (vi, size (y{1}));\n    endif\n  elseif (strcmp (method, \"pchip\"))\n    error (\"interpn: pchip interpolation not yet implemented\");\n  elseif (strcmp (method, \"cubic\"))\n    error (\"interpn: cubic interpolation not yet implemented\");\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! A = [13,-1,12;5,4,3;1,6,2];\n%! x = [0,1,4];  y = [10,11,12];\n%! xi = linspace (min (x), max (x), 17);\n%! yi = linspace (min (y), max (y), 26)';\n%! mesh (xi, yi, interpn (x,y,A.',xi,yi, \"linear\").');\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x(:),y(:),A(:),\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! A = [13,-1,12;5,4,3;1,6,2];\n%! x = [0,1,4];  y = [10,11,12];\n%! xi = linspace (min (x), max (x), 17);\n%! yi = linspace (min (y), max (y), 26)';\n%! mesh (xi, yi, interpn (x,y,A.',xi,yi, \"nearest\").');\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x(:),y(:),A(:),\"b*\"); hold off;\n\n%!#demo  # FIXME: Uncomment when support for \"cubic\" has been added\n%! clf;\n%! colormap (\"default\");\n%! A = [13,-1,12;5,4,3;1,6,2];\n%! x = [0,1,2];  y = [10,11,12];\n%! xi = linspace (min (x), max (x), 17);\n%! yi = linspace (min (y), max (y), 26)';\n%! mesh (xi, yi, interpn (x,y,A.',xi,yi, \"cubic\").');\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x(:),y(:),A(:),\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! A = [13,-1,12;5,4,3;1,6,2];\n%! x = [0,1,2];  y = [10,11,12];\n%! xi = linspace (min (x), max (x), 17);\n%! yi = linspace (min (y), max (y), 26)';\n%! mesh (xi, yi, interpn (x,y,A.',xi,yi, \"spline\").');\n%! [x,y] = meshgrid (x,y);\n%! hold on; plot3 (x(:),y(:),A(:),\"b*\"); hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! x = y = z = -1:1;\n%! f = @(x,y,z) x.^2 - y - z.^2;\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! v = f (xx,yy,zz);\n%! xi = yi = zi = -1:0.1:1;\n%! [xxi, yyi, zzi] = ndgrid (xi, yi, zi);\n%! vi = interpn (x, y, z, v, xxi, yyi, zzi, \"spline\");\n%! mesh (yi, zi, squeeze (vi(1,:,:)));\n\n%!test\n%! [x,y,z] = ndgrid (0:2);\n%! f = x + y + z;\n%! assert (interpn (x,y,z,f,[.5 1.5],[.5 1.5],[.5 1.5]), [1.5, 4.5]);\n%! assert (interpn (x,y,z,f,[.51 1.51],[.51 1.51],[.51 1.51],\"nearest\"),\n%!         [3, 6]);\n%! assert (interpn (x,y,z,f,[.5 1.5],[.5 1.5],[.5 1.5],\"spline\"), [1.5, 4.5]);\n%! assert (interpn (x,y,z,f,x,y,z), f);\n%! assert (interpn (x,y,z,f,x,y,z,\"nearest\"), f);\n%! assert (interpn (x,y,z,f,x,y,z,\"spline\"), f);\n\n%!test\n%! [x, y, z] = ndgrid (0:2, 1:4, 2:6);\n%! f = x + y + z;\n%! xi = [0.5 1.0 1.5];  yi = [1.5 2.0 2.5 3.5];  zi = [2.5 3.5 4.0 5.0 5.5];\n%! fi = interpn (x, y, z, f, xi, yi, zi);\n%! [xi, yi, zi] = ndgrid (xi, yi, zi);\n%! assert (fi, xi + yi + zi);\n\n%!test\n%! xi = 0:2;  yi = 1:4;  zi = 2:6;\n%! [x, y, z] = ndgrid (xi, yi, zi);\n%! f = x + y + z;\n%! fi = interpn (x, y, z, f, xi, yi, zi, \"nearest\");\n%! assert (fi, x + y + z);\n\n%!test\n%! [x,y,z] = ndgrid (0:2);\n%! f = x.^2 + y.^2 + z.^2;\n%! assert (interpn (x,y,-z,f,1.5,1.5,-1.5), 7.5);\n\n%!test  # for Matlab-compatible rounding for \"nearest\"\n%! x = meshgrid (1:4);\n%! assert (interpn (x, 2.5, 2.5, \"nearest\"), 3);\n\n%!test\n%! z = zeros (3, 3, 3);\n%! zout = zeros (5, 5, 5);\n%! z(:,:,1) = [1 3 5; 3 5 7; 5 7 9];\n%! z(:,:,2) = z(:,:,1) + 2;\n%! z(:,:,3) = z(:,:,2) + 2;\n%! for n = 1:5\n%!   zout(:,:,n) = [1 2 3 4 5;\n%!                  2 3 4 5 6;\n%!                  3 4 5 6 7;\n%!                  4 5 6 7 8;\n%!                  5 6 7 8 9] + (n-1);\n%! endfor\n%! tol = 10*eps;\n%! assert (interpn (z), zout, tol);\n%! assert (interpn (z, \"linear\"), zout, tol);\n%! assert (interpn (z, \"spline\"), zout, tol);\n\n## Test that interpolating a complex matrix is equivalent to interpolating its\n## real and imaginary parts separately.\n%!testif HAVE_QNAN_WITH_PAYLOAD <*61907>\n%! yi = [0.5, 1.5]';\n%! xi = [2.5, 3.5];\n%! zi = [2.25, 4.75];\n%! rand (\"state\", 1340640850);\n%! v = rand (4, 3, 5) + 1i * rand (4, 3, 5);\n%! for method = {\"nearest\", \"linear\", \"spline\"}\n%!   vi_complex = interpn (v, yi, xi, zi, method{1});\n%!   vi_real = interpn (real (v), yi, xi, zi, method{1});\n%!   vi_imag = interpn (imag (v), yi, xi, zi, method{1});\n%!   assert (real (vi_complex), vi_real, 2*eps);\n%!   assert (imag (vi_complex), vi_imag, 2*eps);\n%! endfor\n\n## Duplicate from above.  Only for test statistics\n%!testif ; ! __have_feature__ (\"QNAN_WITH_PAYLOAD\") <59830>\n%! yi = [0.5, 1.5]';\n%! xi = [2.5, 3.5];\n%! zi = [2.25, 4.75];\n%! rand (\"state\", 1340640850);\n%! v = rand (4, 3, 5) + 1i * rand (4, 3, 5);\n%! for method = {\"nearest\", \"linear\", \"spline\"}\n%!   vi_complex = interpn (v, yi, xi, zi, method{1});\n%!   vi_real = interpn (real (v), yi, xi, zi, method{1});\n%!   vi_imag = interpn (imag (v), yi, xi, zi, method{1});\n%!   assert (real (vi_complex), vi_real, 2*eps);\n%!   assert (imag (vi_complex), vi_imag, 2*eps);\n%! endfor\n\n## Test input validation\n%!error <Invalid call> interpn ()\n%!error <input reference arrays must be numeric> interpn (\"foobar\")\n%!error <input reference arrays must be numeric> interpn ({1})\n%!error <input reference arrays must be numeric> interpn (true)\n%!error <EXTRAPVAL must be a numeric scalar> interpn (1, \"linear\", {1})\n%!error <EXTRAPVAL must be a numeric scalar> interpn (1, \"linear\", [1, 2])\n%!warning <ignoring unsupported '\\*' flag> interpn (rand (3,3), 1, \"*linear\");\n%!error <'foobar' does not match any of> interpn (1, \"foobar\")\n%!error <wrong number or incorrectly formatted input arguments>\n%! interpn (1, 2, 3, 4);\n%!error <incorrect dimensions for input X1>\n%! interpn ([1,2], ones (2,2), magic (3), [1,2], [1,2])\n%!error <incorrect dimensions for input X2>\n%! interpn (ones (3,3), ones (2,2), magic (3), [1,2], [1,2])\n%!error <incorrect dimensions for input Y2>\n%! interpn ([1,2], [1,2], magic (3), [1,2], ones (2,2), \"spline\")\n%!error <pchip interpolation not yet implemented> interpn ([1,2], \"pchip\")\n%!error <cubic interpolation not yet implemented> interpn ([1,2], \"cubic\")\n"
  },
  {
    "path": "scripts/general/isequal.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isequal (@var{x1}, @var{x2}, @dots{})\n## Return true if all of @var{x1}, @var{x2}, @dots{} are equal.\n## @seealso{isequaln}\n## @end deftypefn\n\n## Algorithm:\n##\n## 1. Verify the class of x.\n##    a. All objects are of the same class\n##    b. All objects are of a generic \"numeric\" class which includes\n##       numeric, logical, and character arrays\n## 2. Verify size of all objects match.\n## 3. Convert objects to struct, and then compare as stated below.\n## 4. For each argument after x, compare it for equality with x:\n##    a. char       compare each member with strcmp\n##    b. numeric    compare each member with '==' with sparsity regarded\n##    c. struct     compare number of fieldnames, value of fieldnames,\n##                  and then each field with isequal (recursive)\n##    d. cellstr    compare each cellstr member with strcmp\n##    e. cell       compare each member with isequal (recursive)\n##    f. fcn_handle compare using overloaded \"eq\" operator\n\nfunction tf = isequal (x, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  nvarargin = nargin - 1;\n  two_args = (nvarargin == 1);  # Optimization for base case of just 2 args\n\n  if (two_args)\n    y = varargin{1};  # alias y to second input for comparison\n  endif\n\n  ############################################################\n  ## Generic tests for equality\n\n  ## All arguments must either be of the same class,\n  ##  or they must be \"numeric\" values.\n  if (two_args)\n    tf = (strcmp (class (x), class (y))\n          || ((isreal (x) || iscomplex (x)) && (isreal (y) || iscomplex (y))));\n  else\n    tf = (all (cellfun (\"isclass\", varargin, class (x)))\n          || ((isreal (x) || iscomplex (x))\n              && all (cellfun (\"isreal\", varargin)\n                      | cellfun (\"isnumeric\", varargin))));\n  endif\n\n  ## Test that everything is the same size (which also tests dimensions)\n  if (tf)\n    tf = size_equal (x, varargin{:});\n  endif\n\n  ## From here on, compare any objects as if they were structures.\n  if (tf && isobject (x))\n    ## Locally suppress class-to-struct warning.  We know what we are doing.\n    warning (\"off\", \"Octave:classdef-to-struct\", \"local\");\n    x = builtin (\"struct\", x);\n    if (two_args)\n      clear y;  # break link to existing variable\n      varargin(1) = builtin (\"struct\", varargin{1});\n      y = varargin{1};  # re-alias y to second input\n    else\n      for i = 1:nvarargin\n        varargin(i) = builtin (\"struct\", varargin{i});\n      endfor\n    endif\n  endif\n\n  ############################################################\n  ## Check individual classes.\n\n  if (tf)\n    if (two_args)\n\n      if (ischar (x) && ischar (y))\n        ## char type.  Optimization, strcmp is ~35% faster than '==' operator.\n        tf = strcmp (x, y);\n\n      elseif (isreal (x) || iscomplex (x))\n        if (issparse (x))\n          ## sparse types.\n          [xi, xj, xv] = find (x);\n          [yi, yj, yv] = find (y);\n          tf = (length (xi) == length (yi)) && all (xi == yi) ...\n              && all (xj == yj) && all (xv == yv);\n        else\n          ## general \"numeric\" type.  Use '==' operator.\n          m = (x == y);\n          tf = all (m(:));\n        endif\n\n      elseif (isstruct (x))\n        ## struct type.  Compare # of fields, fieldnames, then field values.\n\n        ## Test number of fields are equal.\n        tf = (numfields (x) == numfields (y));\n\n        ## Test that all the field names are equal.\n        if (tf)\n          s_fnm_x = sort (fieldnames (x));\n          tf = all (strcmp (s_fnm_x, sort (fieldnames (y))));\n        endif\n\n        ## Test that all field values are equal.  Slow because of recursion.\n        if (tf)\n          if (isscalar (x))\n            for fldnm = s_fnm_x.'\n              tf = isequal (x.(fldnm{1}), y.(fldnm{1}));\n              if (! tf)\n                break;\n              endif\n            endfor\n          else\n            ## struct arrays have to have the contents of each field wrapped\n            ## in a cell since it expands to a collection of values.\n            for fldnm = s_fnm_x.'\n              tf = isequal ({x.(fldnm{1})}, {y.(fldnm{1})});\n              if (! tf)\n                break;\n              endif\n            endfor\n          endif\n        endif\n\n      elseif (iscellstr (x) && iscellstr (y))\n        ## cellstr type.  Optimization over cell type by using strcmp.\n        ## FIXME: It would be faster to use strcmp on whole cellstr arrays,\n        ## but bug #51412 needs to be fixed.  Instead, time/space trade-off.\n        ## Convert to char (space) for faster processing with strcmp (time).\n        tf = strcmp (char (x), char (y));\n\n      elseif (iscell (x))\n        ## cell type.  Check that each element of a cell is equal.  Slow.\n        n = numel (x);\n        idx = 1;\n        while (tf && idx <= n)\n          tf = isequal (x{idx}, y{idx});\n          idx += 1;\n        endwhile\n\n      elseif (is_function_handle (x))\n        ## function type.  Use '==' operator which is overloaded.\n        tf = (x == y);\n\n      elseif (isjava (x))\n        try\n          tf = x.equals (y);\n        catch\n          error ('isequal: Java object does not implement \"equals\" function');\n        end_try_catch\n\n      else\n        error (\"isequal: Impossible to reach code.  File a bug report.\");\n\n      endif\n\n    else  # More than two args.  This is going to be slower in general.\n\n      if (ischar (x) && all (cellfun (\"isclass\", varargin, \"char\")))\n        ## char type.  Optimization, strcmp is ~35% faster than '==' operator.\n        idx = 1;\n        while (tf && idx <= nvarargin)\n          tf = strcmp (x, varargin{idx});\n          idx += 1;\n        endwhile\n\n      elseif (isreal (x) || iscomplex (x))\n\n        if (issparse (x))\n          ## sparse types.\n\n          idx = 1;\n          [xi, xj, xv] = find (x);\n          while (tf && idx <= nvarargin)\n            y = varargin{idx};\n            [yi, yj, yv] = find (y);\n            tf = (length (xi) == length (yi)) && all (xi == yi) ...\n                 && all (xj == yj) && all (xv == yv);\n\n            idx += 1;\n          endwhile\n\n        else\n          ## general \"numeric\" type.  Use '==' operator.\n\n          idx = 1;\n          while (tf && idx <= nvarargin)\n            y = varargin{idx};\n            m = (x == y);\n            tf = all (m(:));\n\n            idx += 1;\n          endwhile\n\n        endif\n\n      elseif (isstruct (x))\n        ## struct type.  Compare # of fields, fieldnames, then field values.\n\n        ## Test number of fields are equal.\n        fnm_x = fieldnames (x);\n        n = numel (fnm_x);\n        fnm_v = cellfun (\"fieldnames\", varargin, \"uniformoutput\", false);\n        tf = all (n == cellfun (\"numel\", fnm_v));\n\n        ## Test that all the field names are equal.\n        if (tf)\n          fnm_x = sort (fnm_x);\n          idx = 1;\n          while (tf && idx <= nvarargin)\n            ## Allow the fieldnames to be in a different order.\n            tf = all (strcmp (fnm_x, sort (fnm_v{idx})));\n            idx += 1;\n          endwhile\n        endif\n\n        ## Test that all field values are equal.  Slow because of recursion.\n        if (tf)\n          args = cell (1, 1 + nvarargin);\n          if (isscalar (x))\n            for fldnm = fnm_x.'\n              args{1} = x.(fldnm{1});\n              for argn = 1:nvarargin\n                args{argn+1} = varargin{argn}.(fldnm{1});\n              endfor\n\n              tf = isequal (args{:});\n\n              if (! tf)\n                break;\n              endif\n            endfor\n          else\n            ## struct arrays have to have the contents of each field wrapped\n            ## in a cell since it expands to a collection of values.\n            for fldnm = fnm_x.'\n              args{1} = { x.(fldnm{1}) };\n              for argn = 1:nvarargin\n                args{argn+1} = { varargin{argn}.(fldnm{1}) };\n              endfor\n\n              tf = isequal (args{:});\n\n              if (! tf)\n                break;\n              endif\n            endfor\n          endif\n        endif\n\n      elseif (iscellstr (x) && all (cellfun ('iscellstr', varargin)))\n        ## cellstr type.  Optimization over cell type by using strcmp.\n        ## FIXME: It would be faster to use strcmp on whole cellstr arrays,\n        ## but bug #51412 needs to be fixed.  Instead, time/space trade-off.\n        ## Convert to char (space) for faster processing with strcmp (time).\n        idx = 1;\n        x = char (x);\n        while (tf && idx <= nvarargin)\n          tf = strcmp (x, char (varargin{idx}));\n          idx += 1;\n        endwhile\n\n      elseif (iscell (x))\n        ## cell type.  Check that each element of a cell is equal.  Slow.\n        n = numel (x);\n        args = cell (1, 1 + nvarargin);\n        idx = 1;\n        while (tf && idx <= n)\n          args(1) = x{idx};\n          args(2:end) = [cellindexmat(varargin, idx){:}];\n\n          tf = isequal (args{:});\n\n          idx += 1;\n        endwhile\n\n      elseif (is_function_handle (x))\n        ## function type.  Use '==' operator which is overloaded.\n        tf = all (cellfun (\"eq\", {x}, varargin));\n\n      else\n        error (\"isequal: Impossible to reach code.  File a bug report.\");\n\n      endif\n\n    endif\n  endif\n\n  tf = full (tf);  # Always return full logical value for Matlab compatibility.\n\nendfunction\n\n\n## test empty input\n%!assert (isequal ([], []), true)\n%!assert (isequal ([], 1), false)\n%!assert (isequal ([], [], 1), false)\n%!assert (isequal ([], 1, []), false)\n%!assert (isequal (1, [], []), false)\n\n## test size and shape\n%!assert (isequal ([1,2,3,4], [1,2,3,4]), true)\n%!assert (isequal ([1;2;3;4], [1;2;3;4]), true)\n%!assert (isequal ([1,2,3,4], [1;2;3;4]), false)\n%!assert (isequal ([1,2,3,4], [1,2;3,4]), false)\n%!assert (isequal ([1,2,3,4], [1,3;2,4]), false)\n%!assert (isequal ([1,2,3,4], [1,2,3,4], [1,2,3,4]), true)\n%!assert (isequal ([1;2;3;4], [1;2;3;4], [1;2;3;4]), true)\n%!assert (isequal ([1,2,3,4], [1,2,3,4], [1;2;3;4]), false)\n%!assert (isequal ([1,2,3,4], [1,2,3,4], [1,2;3,4]), false)\n%!assert (isequal ([1,2,3,4], [1,2,3,4], [1,3;2,4]), false)\n\n## General tests\n%!test\n%! A = 1:8;\n%! B = reshape (A, 2, 2, 2);\n%! assert (isequal (A, B), false);\n%! assert (isequal (A, A, B), false);\n%!test\n%! A = reshape (1:8, 2, 2, 2);\n%! B = A;\n%! assert (isequal (A, B), true);\n%! assert (isequal (A, A, B), true);\n%!test\n%! A = reshape (1:8, 2, 4);\n%! B = reshape (A, 2, 2, 2);\n%! assert (isequal (A, B), false);\n%! assert (isequal (A, A, B), false);\n\n## test characters and strings\n%!assert (isequal ('a', \"a\"), true)\n%!assert (isequal ('a', 'a', \"a\"), true)\n%!assert (isequal (\"abab\", [\"a\", \"b\", \"a\", \"b\"]), true)\n%!assert (isequal (\"abab\", \"abab\", [\"a\", \"b\", \"a\", \"b\"]), true)\n%!assert (isequal ([\"a\",\"b\",\"c\",\"d\"], [\"a\",\"b\",\"c\",\"d\"]), true)\n%!assert (isequal ([\"a\",\"b\",\"c\",\"d\"], [\"a\",\"b\",\"c\",\"d\"], [\"a\",\"b\",\"c\",\"d\"]),\n%!        true)\n%!assert (isequal ([\"test   \";\"strings\"], [\"test   \";\"strings\"]), true)\n%!assert (isequal ([\"test   \";\"strings\"], [\"test   \";\"strings\"],\n%!                 [\"test   \";\"strings\"]), true)\n%!assert (isequal ([\"a\",\"b\",\"c\",\"d\"], [\"a\";\"b\";\"c\";\"d\"]), false)\n%!assert (isequal ([\"a\",\"b\",\"c\",\"d\"], [\"a\",\"b\",\"c\",\"d\"], [\"a\";\"b\";\"c\";\"d\"]),\n%!        false)\n\n## test all numeric built-in primitives\n%!assert (isequal (false, 0))\n%!assert (isequal (char (0), 0))\n%!assert (isequal (false, logical (0), char (0),\n%!                 int8 (0), int16 (0), int32 (0), int64 (0),\n%!                 uint8 (0), uint16 (0), uint32 (0), uint64 (0),\n%!                 double (0), single (0),\n%!                 double (complex (0,0)), single (complex (0,0)),\n%!                 sparse (false), sparse (logical (0)),\n%!                 sparse (double (0)), sparse (single (0)),\n%!                 sparse (double (complex (0,0))),\n%!                 sparse (single (complex (0,0)))),\n%!        true)\n%!assert (isequal (true, logical (1), char (1),\n%!                 int8 (1), int16 (1), int32 (1), int64 (1),\n%!                 uint8 (1), uint16 (1), uint32 (1), uint64 (1),\n%!                 double (1), single (1),\n%!                 double (complex (1,0)), single (complex (1,0)),\n%!                 sparse (true), sparse (logical (1)),\n%!                 sparse (double (1)), sparse (single (1)),\n%!                 sparse (double (complex (1,0))),\n%!                 sparse (single (complex (1,0)))),\n%!        true)\n\n## test structures\n%!assert (isequal (struct ([]), struct ([])), true)\n%!assert (isequal (struct ([]), struct ([]), struct ([])), true)\n%!assert (isequal (struct (\"a\",1), struct (\"a\",1)), true)\n%!assert (isequal (struct (\"a\",1), struct (\"a\",1), struct (\"a\",1)), true)\n%!assert (isequal (struct (\"a\",1), struct (\"a\",2)), false)\n%!assert (isequal (struct (\"a\",1), struct (\"a\",1), struct (\"a\",2)), false)\n%!assert (isequal (struct (\"a\",1), struct (\"a\",1,\"b\",2)), false)\n%!assert (isequal (struct (\"a\",1), struct (\"a\",1),struct (\"a\",1,\"b\",2)), false)\n%!assert (isequal (struct (\"a\",1), struct (\"b\",1)), false)\n%!assert (isequal (struct (\"a\",1), struct (\"a\",1), struct (\"b\",1)), false)\n%!assert (isequal (struct (\"a\",1,\"b\",2), struct (\"a\",1,\"b\",2)), true)\n%!assert (isequal (struct (\"a\",1,\"b\",2), struct (\"a\",1,\"b\",2),\n%!                 struct (\"a\",1,\"b\",2)), true)\n%!assert (isequal (struct (\"a\",1,\"b\",2), struct (\"b\",2,\"a\",1)), true)\n%!assert (isequal (struct (\"a\",1,\"b\",2), struct (\"a\",1,\"b\",2),\n%!                 struct (\"b\",2,\"a\",1)), true)\n%!assert (isequal (struct (\"a\",\"abc\",\"b\",2), struct (\"a\",\"abc\",\"b\",2)), true)\n%!assert (isequal (struct (\"a\",\"abc\",\"b\",2), struct (\"a\",\"abc\",\"b\",2),\n%!                 struct (\"a\",\"abc\",\"b\",2)), true)\n\n## recursive structure\n%!test\n%! x.a = \"a1\";\n%! x.b.a = \"ba1\";\n%! x.b.b = \"bb1\";\n%! assert (isequal (x, x), true);\n%! assert (isequal (x, x, x), true);\n%! y = x;\n%! y.b.b = \"bb2\";\n%! assert (isequal (x, y), false);\n%! assert (isequal (x, x, y), false);\n%! y = x;\n%! y.b = rmfield (y.b, \"b\");\n%! y.b.b.a = \"bba1\";\n%! assert (isequal (x, y), false);\n%! assert (isequal (x, x, y), false);\n\n## struct array\n%!test\n%! x(1).a = 'A';\n%! x(2).a = magic (3);\n%! assert (isequal (x, x), true);\n%! assert (isequal (x, x, x), true);\n%! y = x;\n%! y(2).a = { magic(3) };\n%! assert (isequal (x, y), false);\n%! assert (isequal (x, x, y), false);\n\n## test cellstr\n%!assert (isequal (cell (1,1), cell (1,1)), true)\n%!assert (isequal (cell (1,1), cell (1,2)), false)\n%!assert (isequal ({\"a\",\"b\";\"c\",\"d\"}, {\"a\",\"b\";\"c\",\"d\"}), true)\n%!assert (isequal ({\"a\",\"b\";\"c\",\"d\"}, {\"a\",\"b\";\"c\",\"d\"}, {\"a\",\"b\";\"c\",\"d\"}),\n%!                 true)\n%!assert (isequal ({\"a\",\"b\",\"c\",\"d\"}, {\"a\";\"b\";\"c\";\"d\"}), false)\n%!assert (isequal ({\"a\",\"b\",\"c\",\"d\"}, {\"a\",\"b\",\"c\",\"d\"}, {\"a\";\"b\";\"c\";\"d\"}),\n%!        false)\n%!assert (isequal ([\"a\",\"b\",\"c\",\"d\"], {\"a\",\"b\",\"c\",\"d\"}), false)\n%!assert (isequal ([\"a\",\"b\",\"c\",\"d\"], [\"a\",\"b\",\"c\",\"d\"], {\"a\",\"b\",\"c\",\"d\"}),\n%!        false)\n%!test\n%! x = { [\"ab\"; \"cd\"] ; [\"ef\"; \"gh\"] };\n%! assert (isequal (x, x), true);\n%! assert (isequal (x, x, x), true);\n%! y = x;\n%! y(2) = [\"ef\"; \"gH\"];\n%! assert (isequal (x, y), false);\n%! assert (isequal (x, x, y), false);\n\n## test cells\n%!assert (isequal (cell (1,1), cell (1,1)), true)\n%!assert (isequal (cell (1,1), cell (1,1), cell (1,1)), true)\n%!assert (isequal (cell (1,1), cell (1,2)), false)\n%!assert (isequal (cell (1,1), cell (1,1), cell (1,2)), false)\n%!assert (isequal ({\"a\",1}, {\"a\",1}), true)\n%!assert (isequal ({\"a\",1}, {\"a\",1}, {\"a\",1}), true)\n%!assert (isequal ({\"a\",1}, {\"a\",2}), false)\n%!assert (isequal ({\"a\",1}, {\"a\",1}, {\"a\",2}), false)\n%!assert (isequal ({\"a\",1}, {\"b\",1}), false)\n%!assert (isequal ({\"a\",1}, {\"a\",1}, {\"b\",1}), false)\n%!assert (isequal ({\"a\",1,\"b\",2}, {\"a\",1,\"b\",2}), true)\n%!assert (isequal ({\"a\",1,\"b\",2}, {\"a\",1,\"b\",2}, {\"a\",1,\"b\",2}), true)\n%!assert (isequal ({\"a\",1,\"b\",2}, {\"b\",2,\"a\",1}), false)\n%!assert (isequal ({\"a\",1,\"b\",2}, {\"a\",1,\"b\",2}, {\"b\",2,\"a\",1}), false)\n%!assert (isequal ({\"a\",\"abc\",\"b\",2}, {\"a\",\"abc\",\"b\",2}), true)\n%!assert (isequal ({\"a\",\"abc\",\"b\",2}, {\"a\",\"abc\",\"b\",2}, {\"a\",\"abc\",\"b\",2}),\n%!                 true)\n\n## recursive cell\n%!test\n%! x = cell (1,3);\n%! x{1} = {[1], [1 2]};\n%! x{2} = true;\n%! x{3} = {{\"hello\"}, {\"world\"}};\n%! assert (isequal (x, x));\n%! y = x;\n%! y{3}{1}{1} = \"goodbye\";\n%! assert (isequal (x, y), false);\n\n## test function_handle\n%!test\n%! fcn = @(x) x.^2;\n%! assert (isequal (fcn, fcn), true);\n%! assert (isequal (fcn, fcn, fcn), true);\n%! assert (isequal (fcn, @(x) x.^2), false);\n%! assert (isequal (fcn, fcn, @(x) x.^2), false);\n%! assert (isequal (@(x) x.^2, fcn), false);\n%! assert (isequal (@(x) x.^2, @(x) x.^2, fcn), false);\n\n## test for sparse matrices\n%!shared A, Z\n%!  A = sprand (2^31, 1000, 2^(-31));\n%!  Z = sparse (2^31, 1000);\n%!assert (isequal (sparse ([]), []), true)\n%!assert (isequal (sparse ([]), sparse ([]), []), true)\n%!assert (isequal ([], sparse ([])), true)\n%!assert (isequal ([], [], sparse ([])), true)\n%!assert (isequal (sparse (0,1), sparse (0,1)), true)\n%!assert (isequal (sparse (0,1), sparse (0,1), sparse (0,1)), true)\n%!assert (isequal (sparse (0,1), zeros (0,1)), true)\n%!assert (isequal (sparse (0,1), sparse (0,1), zeros (0,1)), true)\n%!assert (isequal (sparse (2,2), sparse (2,2)), true)\n%!assert (isequal (sparse (2,2), sparse (2,2), sparse (2,2)), true)\n%!assert (isequal (zeros (2,2), sparse (2,2)), true)\n%!assert (isequal (zeros (2,2), zeros (2,2), sparse (2,2)), true)\n%!assert (isequal (speye (1), eye (1)), true)\n%!assert (isequal (speye (1), speye (1), eye (1)), true)\n%!assert (isequal (eye (300), speye (300)), true)\n%!assert (isequal (eye (300), eye (300), speye (300)), true)\n%!assert (isequal (sparse (0,1), sparse (1,0)), false)\n%!assert (isequal (sparse (0,1), sparse (0,1), sparse (1,0)), false)\n%!assert (isequal (Z, Z), true)\n%!assert (isequal (A, A), true)\n%!assert (isequal (A, Z), false)\n%!assert (isequal (Z, Z, Z), true)\n%!assert (isequal (A, A, A), true)\n%!assert (isequal (A, Z, A), false)\n\n## test NaN\n%!assert (isequal (NaN, NaN), false)\n%!assert (isequal (NaN, NaN, NaN), false)\n%!assert (isequal (NaN, Inf), false)\n%!assert (isequal (NaN, Inf, Inf), false)\n%!assert (isequal (NaN, 1.0), false)\n%!assert (isequal (NaN, 1.0, 1.0), false)\n%!assert (isequal ([1,2,NaN,4], [1,2,NaN,4]), false)\n%!assert (isequal ([1,2,NaN,4], [1,2,NaN,4], [1,2,NaN,4]), false)\n%!assert (isequal (struct (\"a\",NaN,\"b\",2), struct (\"a\",NaN,\"b\",2)), false)\n%!assert (isequal (struct (\"a\",NaN,\"b\",2), struct (\"a\",NaN,\"b\",2),\n%!                 struct (\"a\",NaN,\"b\",2)), false)\n\n## Matlab compatibility\n%!assert (isequal (sparse (1), sparse (1)), true)\n%!assert (isequal (sparse (1), sparse (1)), sparse (1), true)\n\n## Java objects\n%!testif HAVE_JAVA; usejava (\"jvm\")  <*62930>\n%! int1 = javaObject (\"java.lang.Integer\", 1.0);\n%! int2 = javaObject (\"java.lang.Integer\", 2.0);\n%! assert (isequal (int1, int1));\n%! assert (! isequal (int1, 1.0));\n%! assert (! isequal (int1, int2));\n\n## test input validation\n%!error <Invalid call> isequal ()\n%!error <Invalid call> isequal (1)\n"
  },
  {
    "path": "scripts/general/isequaln.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isequaln (@var{x1}, @var{x2}, @dots{})\n## Return true if all of @var{x1}, @var{x2}, @dots{} are equal under the\n## additional assumption that NaN == NaN (no comparison of NaN placeholders\n## in dataset).\n## @seealso{isequal}\n## @end deftypefn\n\n## Algorithm:\n##\n## 1. Verify the class of x.\n##    a. All objects are of the same class\n##    b. All objects are of a generic \"numeric\" class which includes\n##       numeric, logical, and character arrays\n## 2. Verify size of all objects match.\n## 3. Convert objects to struct, and then compare as stated below.\n## 4. For each argument after x, compare it for equality with x:\n##    a. char       compare each member with strcmp\n##    b. numeric    compare each member with '==', and assume NaN == NaN\n##    c. struct     compare number of fieldnames, value of fieldnames,\n##                  and then each field with isequaln (recursive)\n##    d. cellstr    compare each cellstr member with strcmp\n##    e. cell       compare each member with isequaln (recursive)\n##    f. fcn_handle compare using overloaded \"eq\" operator\n\nfunction tf = isequaln (x, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  nvarargin = nargin - 1;\n  two_args = (nvarargin == 1);  # Optimization for base case of just 2 args\n\n  if (two_args)\n    y = varargin{1};  # alias y to second input for comparison\n  endif\n\n  ############################################################\n  ## Generic tests for equality\n\n  ## All arguments must either be of the same class,\n  ##  or they must be \"numeric\" values.\n  if (two_args)\n    tf = (strcmp (class (x), class (y))\n          || ((isreal (x) || iscomplex (x)) && (isreal (y) || iscomplex (y))));\n  else\n    tf = (all (cellfun (\"isclass\", varargin, class (x)))\n          || ((isreal (x) || iscomplex (x))\n              && all (cellfun (\"isreal\", varargin)\n                      | cellfun (\"isnumeric\", varargin))));\n  endif\n\n  ## Test that everything is the same size (which also tests dimensions)\n  if (tf)\n    tf = size_equal (x, varargin{:});\n  endif\n\n  ## From here on, compare any objects as if they were structures.\n  if (tf && isobject (x))\n    ## Locally suppress class-to-struct warning.  We know what we are doing.\n    warning (\"off\", \"Octave:classdef-to-struct\", \"local\");\n    x = builtin (\"struct\", x);\n    if (two_args)\n      clear y;  # break link to existing variable\n      varargin(1) = builtin (\"struct\", varargin{1});\n      y = varargin{1};  # re-alias y to second input\n    else\n      for i = 1:nvarargin\n        varargin(i) = builtin (\"struct\", varargin{i});\n      endfor\n    endif\n  endif\n\n  ############################################################\n  ## Check individual classes.\n\n  if (tf)\n    if (two_args)\n\n      if (ischar (x) && ischar (y))\n        ## char type.  Optimization, strcmp is ~35% faster than '==' operator.\n        tf = strcmp (x, y);\n\n      elseif (isreal (x) || iscomplex (x))\n        ## general \"numeric\" type.  Use '==' operator.\n        m = (x == y);\n        tf = all (m(:));\n\n        if (! tf && isfloat (x) && isfloat (y))\n          tf = isnan (x(! m)) && isnan (y(! m));\n        endif\n\n      elseif (isstruct (x))\n        ## struct type.  Compare # of fields, fieldnames, then field values.\n\n        ## Test number of fields are equal.\n        tf = (numfields (x) == numfields (y));\n\n        ## Test that all the field names are equal.\n        if (tf)\n          s_fnm_x = sort (fieldnames (x));\n          tf = all (strcmp (s_fnm_x, sort (fieldnames (y))));\n        endif\n\n        ## Test that all field values are equal.  Slow because of recursion.\n        if (tf)\n          if (isscalar (x))\n            for fldnm = s_fnm_x.'\n              tf = isequaln (x.(fldnm{1}), y.(fldnm{1}));\n              if (! tf)\n                break;\n              endif\n            endfor\n          else\n            ## struct arrays have to have the contents of each field wrapped\n            ## in a cell since it expands to a collection of values.\n            for fldnm = s_fnm_x.'\n              tf = isequaln ({x.(fldnm{1})}, {y.(fldnm{1})});\n              if (! tf)\n                break;\n              endif\n            endfor\n          endif\n        endif\n\n      elseif (iscellstr (x) && iscellstr (y))\n        ## cellstr type.  Optimization over cell type by using strcmp.\n        ## FIXME: It would be faster to use strcmp on whole cellstr arrays,\n        ## but bug #51412 needs to be fixed.  Instead, time/space trade-off.\n        ## Convert to char (space) for faster processing with strcmp (time).\n        tf = strcmp (char (x), char (y));\n\n      elseif (iscell (x))\n        ## cell type.  Check that each element of a cell is equal.  Slow.\n        n = numel (x);\n        idx = 1;\n        while (tf && idx <= n)\n          tf = isequaln (x{idx}, y{idx});\n          idx += 1;\n        endwhile\n\n      elseif (is_function_handle (x))\n        ## function type.  Use '==' operator which is overloaded.\n        tf = (x == y);\n\n      else\n        error (\"isequaln: Impossible to reach code.  File a bug report.\");\n\n      endif\n\n    else  # More than two args.  This is going to be slower in general.\n\n      if (ischar (x) && all (cellfun (\"isclass\", varargin, \"char\")))\n        ## char type.  Optimization, strcmp is ~35% faster than '==' operator.\n        idx = 1;\n        while (tf && idx <= nvarargin)\n          tf = strcmp (x, varargin{idx});\n          idx += 1;\n        endwhile\n\n      elseif (isreal (x) || iscomplex (x))\n        ## general \"numeric\" type.  Use '==' operator.\n\n        idx = 1;\n        while (tf && idx <= nvarargin)\n          y = varargin{idx};\n          m = (x == y);\n          tf = all (m(:));\n\n          if (! tf && isfloat (x) && isfloat (y))\n            tf = isnan (x(! m)) && isnan (y(! m));\n          endif\n\n          idx += 1;\n        endwhile\n\n      elseif (isstruct (x))\n        ## struct type.  Compare # of fields, fieldnames, then field values.\n\n        ## Test number of fields are equal.\n        fnm_x = fieldnames (x);\n        n = numel (fnm_x);\n        fnm_v = cellfun (\"fieldnames\", varargin, \"uniformoutput\", false);\n        tf = all (n == cellfun (\"numel\", fnm_v));\n\n        ## Test that all the field names are equal.\n        if (tf)\n          fnm_x = sort (fnm_x);\n          idx = 1;\n          while (tf && idx <= nvarargin)\n            ## Allow the fieldnames to be in a different order.\n            tf = all (strcmp (fnm_x, sort (fnm_v{idx})));\n            idx += 1;\n          endwhile\n        endif\n\n        ## Test that all field values are equal.  Slow because of recursion.\n        if (tf)\n          args = cell (1, 1 + nvarargin);\n          if (isscalar (x))\n            for fldnm = fnm_x.'\n              args{1} = x.(fldnm{1});\n              for argn = 1:nvarargin\n                args{argn+1} = varargin{argn}.(fldnm{1});\n              endfor\n\n              tf = isequaln (args{:});\n\n              if (! tf)\n                break;\n              endif\n            endfor\n          else\n            ## struct arrays have to have the contents of each field wrapped\n            ## in a cell since it expands to a collection of values.\n            for fldnm = fnm_x.'\n              args{1} = { x.(fldnm{1}) };\n              for argn = 1:nvarargin\n                args{argn+1} = { varargin{argn}.(fldnm{1}) };\n              endfor\n\n              tf = isequaln (args{:});\n\n              if (! tf)\n                break;\n              endif\n            endfor\n          endif\n        endif\n\n      elseif (iscellstr (x) && all (cellfun ('iscellstr', varargin)))\n        ## cellstr type.  Optimization over cell type by using strcmp.\n        ## FIXME: It would be faster to use strcmp on whole cellstr arrays,\n        ## but bug #51412 needs to be fixed.  Instead, time/space trade-off.\n        ## Convert to char (space) for faster processing with strcmp (time).\n        idx = 1;\n        x = char (x);\n        while (tf && idx <= nvarargin)\n          tf = strcmp (x, char (varargin{idx}));\n          idx += 1;\n        endwhile\n\n      elseif (iscell (x))\n        ## cell type.  Check that each element of a cell is equal.  Slow.\n        n = numel (x);\n        args = cell (1, 1 + nvarargin);\n        idx = 1;\n        while (tf && idx <= n)\n          args(1) = x{idx};\n          args(2:end) = [cellindexmat(varargin, idx){:}];\n\n          tf = isequaln (args{:});\n\n          idx += 1;\n        endwhile\n\n      elseif (is_function_handle (x))\n        ## function type.  Use '==' operator which is overloaded.\n        tf = all (cellfun (\"eq\", {x}, varargin));\n\n      else\n        error (\"isequaln: Impossible to reach code.  File a bug report.\");\n\n      endif\n\n    endif\n  endif\n\n  tf = full (tf);  # Always return full logical value for Matlab compatibility.\n\nendfunction\n\n\n## test for equality\n%!assert (isequaln (1,1), true)\n%!assert (isequaln (1,1,1), true)\n%!assert (isequaln ({1,2,NaN,4}, {1,2,NaN,4}), true)\n%!assert (isequaln ({1,2,NaN,4}, {1,2,NaN,4}, {1,2,NaN,4}), true)\n%!assert (isequaln ([1,2,NaN,4], [1,2,NaN,4]), true)\n%!assert (isequaln ([1,2,NaN,4], [1,2,NaN,4], [1,2,NaN,4]), true)\n## test for inequality\n%!assert (isequaln (1,2), false)\n%!assert (isequaln (1,1,2), false)\n%!assert (isequaln ([1,2,NaN,4], [1,NaN,3,4]), false)\n%!assert (isequaln ([1,2,NaN,4], [1,2,NaN,4], [1,NaN,3,4]), false)\n%!assert (isequaln ([1,2,NaN,4], [1,2,3,4]), false)\n%!assert (isequaln ([1,2,NaN,4], [1,2,NaN,4], [1,2,3,4]), false)\n## test for equality (struct)\n%!shared st\n%! st = struct (\"a\",NaN,\"b\",2);\n%!assert (isequaln (st, st), true)\n%!assert (isequaln (st, st, st), true)\n\n## Input validation\n%!error <Invalid call> isequaln ()\n%!error <Invalid call> isequaln (1)\n"
  },
  {
    "path": "scripts/general/isuniform.m",
    "content": "########################################################################\n##\n## Copyright (C) 2023-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} isuniform (@var{v})\n## @deftypefnx {} {[@var{tf}, @var{delta}] =} isuniform (@var{v})\n## Return true if the real vector @var{v} is uniformly spaced and false\n## otherwise.\n##\n## A vector is uniform if the mean difference (@var{delta}) between all\n## elements is the same to within a tolerance of\n## @w{@code{4 * eps (max (abs (@var{v})))}}.\n##\n## The optional output @var{delta} is the uniform difference between elements.\n## If the vector is not uniform then @var{delta} is @code{NaN}.  @var{delta}\n## is of the same class as @var{v} for floating point inputs and of class\n## double for integer, logical, and character inputs.\n##\n## Programming Notes: The output is always false for the special cases of an\n## empty input or a scalar input.  If any element is @code{NaN} then the output\n## is false.  If @var{delta} is smaller than the calculated relative tolerance\n## then an absolute tolerance of @code{eps} is used.\n##\n## @seealso{linspace, colon}\n## @end deftypefn\n\nfunction [tf, delta] = isuniform (v)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  if (! (isreal (v) && (isvector (v) || isempty (v))))\n    error (\"isuniform: V must be a real vector\");\n  endif\n\n  if (! isfloat (v))\n    v = double (v);  # char, logical, integer inputs converted to double\n  endif\n\n  ## Handle special corner cases\n  if (isempty (v) || isscalar (v))\n    tf = false;\n    delta = NaN (class (v));\n    return;\n  endif\n\n  ## Compare mean delta to individual deltas with a tolerance\n  d = diff (v, 1);\n  delta = mean (d);\n  if (isnan (delta))\n    tf = false;\n  else\n    tol = 4 * eps (max (abs (v)));\n    if (delta < tol)\n      ## Switch to absolute tolerance for very small delta\n      tol = eps (class (v));\n    endif\n    tf = ! any (abs (d - delta) > tol);\n    if (! tf)\n      delta = NaN (class (v));\n    endif\n  endif\n\nendfunction\n\n\n%!assert (isuniform ([]), false)                  # empty input\n%!assert (isuniform (zeros (1,2,0,4)), false)     # empty input\n%!assert (isuniform (1), false)                   # scalar input\n%!assert (isuniform (1:5), true)\n%!assert (isuniform (int8 (1:3:10)), true)\n%!assert (isuniform ([false false false]), true)\n%!assert (isuniform (['A', 'C', 'E']), true)\n\n## Test return class of step\n%!test\n%! [tf, delta] = isuniform (single (10:-1.5:1));\n%! assert (tf, true);\n%! assert (delta, single (-1.5));\n%! [tf, delta] = isuniform (single ([1 2 5 6]));\n%! assert (tf, false);\n%! assert (delta, single (NaN));\n\n%!test\n%! [tf, delta] = isuniform (int8 (1:3:15));\n%! assert (tf, true);\n%! assert (delta, double (3));\n%! [tf, delta] = isuniform (int8 ([1 2 5 6]));\n%! assert (tf, false);\n%! assert (delta, double (NaN));\n\n## Test for small delta smaller than tolerance\n%!test\n%! v = 1:eps:(1+8*eps);\n%! [tf, delta] = isuniform (v);\n%! assert (tf, true);\n%! assert (delta, eps);\n%! v(3) -= 2*eps;\n%! [tf, delta] = isuniform (v);\n%! assert (tf, false);\n%! assert (delta, NaN);\n\n## test input validation\n%!error <Invalid call> isuniform ()\n%!error <V must be a real vector> isuniform ({1, 2, 3})\n%!error <V must be a real vector> isuniform (magic (3))\n"
  },
  {
    "path": "scripts/general/logspace.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} logspace (@var{a}, @var{b})\n## @deftypefnx {} {@var{y} =} logspace (@var{a}, @var{b}, @var{n})\n## @deftypefnx {} {@var{y} =} logspace (@var{a}, pi)\n## @deftypefnx {} {@var{y} =} logspace (@var{a}, pi, @var{n})\n## Return a row vector with @var{n} elements logarithmically spaced from\n## @tex\n## $10^{a}$ to $10^{b}$.\n## @end tex\n## @ifnottex\n## 10^@var{a} to 10^@var{b}.\n## @end ifnottex\n##\n## If the number of elements @var{n} is unspecified it defaults to 50.\n##\n## If @var{b} is equal to\n## @tex\n## $\\pi$,\n## @end tex\n## @ifnottex\n## pi,\n## @end ifnottex\n## the points are between\n## @tex\n## $10^{a}$ and $\\pi$,\n## @end tex\n## @ifnottex\n## 10^@var{a} and pi,\n## @end ifnottex\n## @emph{not}\n## @tex\n## $10^{a}$ and $10^{\\pi}$,\n## @end tex\n## @ifnottex\n## 10^@var{a} and 10^pi,\n## @end ifnottex\n## which is useful in digital signal processing.\n##\n## Programming Notes: For compatibility with @sc{matlab}, return the right-hand\n## side of the range\n## @tex\n## ($10^{b}$)\n## @end tex\n## @ifnottex\n## (10^@var{b})\n## @end ifnottex\n## when a single value (@var{n} = 1) is requested.\n## If @var{n} is not an integer then @code{floor (@var{n})} is used to round\n## the number of elements.  If @var{n} is zero or negative then an empty 1x0\n## matrix is returned.\n## @seealso{linspace}\n## @end deftypefn\n\nfunction y = logspace (a, b, n = 50)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (isscalar (a) && isscalar (b) && isscalar (n)))\n    error (\"logspace: arguments A, B, and N must be scalars\");\n  endif\n\n  npoints = fix (n);\n\n  if (b == pi)\n    b = log10 (pi);\n  endif\n\n  y = 10 .^ (linspace (a, b, npoints));\n\nendfunction\n\n\n%!test\n%! x1 = logspace (1, 2);\n%! x2 = logspace (1, 2, 10.1);\n%! x3 = logspace (1, -2, 10);\n%! x4 = logspace (1, pi, 10);\n%! assert (size (x1) == [1, 50]);\n%! assert (abs (x1(1) - 10) < eps);\n%! assert (abs (x1(50) - 100) < eps);\n%! assert (size (x2) == [1, 10]);\n%! assert (abs (x2(1) - 10) < eps);\n%! assert (abs (x2(10) - 100) < eps);\n%! assert (size (x3) == [1, 10]);\n%! assert (abs (x3(1) - 10) < eps);\n%! assert (abs (x3(10) - 0.01) < eps);\n%! assert (size (x4) == [1, 10]);\n%! assert (abs (x4(1) - 10) < eps);\n%! assert (abs (x4(10) - pi) < sqrt (eps));\n\n## Edge cases\n%!assert (logspace (Inf, Inf, 3), [Inf, Inf, Inf])\n%!assert (logspace (-Inf, Inf, 3), [0, 1, Inf])\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! assert (logspace (Inf + 1i, Inf + 1i, 3),\n%!         repmat (complex (-Inf,Inf), [1, 3]))\n%!testif HAVE_LLVM_LIBCXX  <55538>\n%! assert (logspace (Inf + 1i, Inf + 1i, 3),\n%!         repmat (complex (-Inf,Inf), [1, 3]))\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! assert (logspace (-Inf + 1i, Inf + 1i, 3),\n%!         [0, NaN + NaN * 1i, complex(-Inf, Inf)])\n%!testif HAVE_LLVM_LIBCXX  <55538>\n%! assert (logspace (-Inf + 1i, Inf + 1i, 3),\n%!         [0, NaN + NaN * 1i, complex(-Inf, Inf)])\n## Octave prefers to return NaN which indicates failure of algorithm.\n## Tests can be re-instated if full Matlab-compatibility is coded.\n%!#assert (logspace (0, Inf, 3), [1, Inf, Inf])\n%!#assert (logspace (0, -Inf, 3), [1, 0, 0])\n%!assert (logspace (Inf, -Inf, 3), [Inf, 1, 0])\n%!assert (logspace (-Inf, 0, 3), [0, NaN, 1])\n%!assert (logspace (Inf, 0, 3), [Inf, NaN, 1])\n\n## Test input validation\n%!error <Invalid call> logspace ()\n%!error logspace ([1, 2; 3, 4], 5, 6)\n%!error logspace (1, [1, 2; 3, 4], 6)\n%!error logspace (1, 2, [1, 2; 3, 4])\n"
  },
  {
    "path": "scripts/general/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__splinen__.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/accumarray.m \\\n  %reldir%/accumdim.m \\\n  %reldir%/bincoeff.m \\\n  %reldir%/bitcmp.m \\\n  %reldir%/bitget.m \\\n  %reldir%/bitset.m \\\n  %reldir%/blkdiag.m \\\n  %reldir%/cart2pol.m \\\n  %reldir%/cart2sph.m \\\n  %reldir%/cell2mat.m \\\n  %reldir%/celldisp.m \\\n  %reldir%/circshift.m \\\n  %reldir%/common_size.m \\\n  %reldir%/cplxpair.m \\\n  %reldir%/cumtrapz.m \\\n  %reldir%/curl.m \\\n  %reldir%/dblquad.m \\\n  %reldir%/deal.m \\\n  %reldir%/deg2rad.m \\\n  %reldir%/del2.m \\\n  %reldir%/divergence.m \\\n  %reldir%/flip.m \\\n  %reldir%/fliplr.m \\\n  %reldir%/flipud.m \\\n  %reldir%/gradient.m \\\n  %reldir%/idivide.m \\\n  %reldir%/int2str.m \\\n  %reldir%/integral.m \\\n  %reldir%/integral2.m \\\n  %reldir%/integral3.m \\\n  %reldir%/interp1.m \\\n  %reldir%/interp2.m \\\n  %reldir%/interp3.m \\\n  %reldir%/interpft.m \\\n  %reldir%/interpn.m \\\n  %reldir%/isequal.m \\\n  %reldir%/isequaln.m \\\n  %reldir%/isuniform.m \\\n  %reldir%/logspace.m \\\n  %reldir%/nextpow2.m \\\n  %reldir%/num2str.m \\\n  %reldir%/pagectranspose.m \\\n  %reldir%/pagetranspose.m \\\n  %reldir%/pol2cart.m \\\n  %reldir%/polyarea.m \\\n  %reldir%/postpad.m \\\n  %reldir%/prepad.m \\\n  %reldir%/quad2d.m \\\n  %reldir%/quadgk.m \\\n  %reldir%/quadl.m \\\n  %reldir%/quadv.m \\\n  %reldir%/rad2deg.m \\\n  %reldir%/rat.m \\\n  %reldir%/repelem.m \\\n  %reldir%/repmat.m \\\n  %reldir%/rescale.m \\\n  %reldir%/rng.m \\\n  %reldir%/rot90.m \\\n  %reldir%/rotdim.m \\\n  %reldir%/shiftdim.m \\\n  %reldir%/sortrows.m \\\n  %reldir%/sph2cart.m \\\n  %reldir%/structfun.m \\\n  %reldir%/subsindex.m \\\n  %reldir%/trapz.m \\\n  %reldir%/triplequad.m \\\n  %reldir%/xor.m\n\n%canon_reldir%dir = $(fcnfiledir)/general\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/general/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/general/nextpow2.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{n} =} nextpow2 (@var{x})\n## Compute the exponent of the next power of two not smaller than the input.\n##\n## For each element in the input array @var{x}, return the smallest integer\n## @var{n} such that\n## @tex\n## $2^n \\ge |x|$.\n## @end tex\n## @ifnottex\n## @code{2^@var{n} @geq{} abs (@var{x})}.\n## @end ifnottex\n## For input elements equal to zero, return zero.\n##\n## @seealso{pow2, log2}\n## @end deftypefn\n\nfunction n = nextpow2 (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x))\n    error (\"nextpow2: X must be numeric\");\n  elseif (! isreal (x))\n    error (\"nextpow2: X must be real\");\n  endif\n\n  [f, n] = log2 (abs (x));\n  n(f == 0.5)--;\n\n  if (isfloat (x))\n    idx_nan = isnan (x);\n    n(idx_nan) = x(idx_nan);\n    n(isinf (x)) = Inf;\n  else\n    n = cast (n, class (x));\n    if (intmax (x) > flintmax ())\n      n((2 .^ n) < abs (x))++;\n    endif\n  endif\n\nendfunction\n\n\n%!assert (nextpow2 (16), 4)\n%!assert (nextpow2 (17), 5)\n%!assert (nextpow2 (31), 5)\n%!assert (nextpow2 (-16), 4)\n%!assert (nextpow2 (-17), 5)\n%!assert (nextpow2 (-31), 5)\n%!assert (nextpow2 (1:17), [0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 4 5])\n%!assert <*62947> (nextpow2 (0.5), -1)\n%!assert <*62947> (nextpow2 (0.6), 0)\n## Special cases\n%!assert (nextpow2 (0), 0)\n%!assert (nextpow2 (1), 0)\n%!assert (nextpow2 (Inf), Inf)\n%!assert (nextpow2 (-Inf), Inf)\n%!assert (nextpow2 (NaN), NaN)\n%!assert (nextpow2 (NA), NA)\n%!assert (nextpow2 ([1, Inf, 3, -Inf, 9, NaN, NA]), ...\n%!                  [0, Inf, 2,  Inf, 4, NaN, NA])\n\n%!test\n%! p = (-1074:1023).';\n%! x = 2 .^ p;\n%! x = [x, x + eps(x)];\n%! x = [x, -x];\n%! n = nextpow2 (x);\n%! assert (n(:, 1), p);\n%! assert (n(:, 3), p);\n%! assert (n(:, 2), p + 1);\n%! assert (n(:, 4), p + 1);\n\n%!assert (nextpow2 (realmax ()), 1024)\n%!assert (nextpow2 (-realmax ()), 1024)\n\n%!test\n%! p = single (-149:127).';\n%! x = 2 .^ p;\n%! x = [x, x + eps(x)];\n%! x = [x, -x];\n%! n = nextpow2 (x);\n%! assert (n(:, 1), p);\n%! assert (n(:, 3), p);\n%! assert (n(:, 2), p + 1);\n%! assert (n(:, 4), p + 1);\n\n%!assert (nextpow2 (realmax ('single')), single (128))\n%!assert (nextpow2 (-realmax ('single')), single (128))\n\n%!test\n%! p = int32 (0:30).';\n%! x = 2 .^ p;\n%! x = [x, x + 1];\n%! x = [x, -x];\n%! n = nextpow2 (x);\n%! assert (n(:, 1), p);\n%! assert (n(:, 3), p);\n%! assert (n(:, 2), p + 1);\n%! assert (n(:, 4), p + 1);\n\n%!assert (nextpow2 (int32 (0)), int32 (0))\n%!assert (nextpow2 (intmin ('int32')), int32 (31))\n%!assert (nextpow2 (intmax ('int32')), int32 (31))\n\n%!assert (nextpow2 (uint32 (0)), uint32 (0))\n%!assert (nextpow2 (intmax ('uint32')), uint32 (32))\n\n%!test\n%! p = int64 (0:62).';\n%! x = 2 .^ p;\n%! x = [x, x + 1];\n%! x = [x, -x];\n%! n = nextpow2 (x);\n%! assert (n(:, 1), p);\n%! assert (n(:, 3), p);\n%! assert (n(:, 2), p + 1);\n%! assert (n(:, 4), p + 1);\n\n%!assert (nextpow2 (int64 (0)), int64 (0))\n%!assert (nextpow2 (intmin ('int64')), int64 (63))\n%!assert (nextpow2 (intmax ('int64')), int64 (63))\n\n%!assert (nextpow2 (uint64 (0)), uint64 (0))\n%!assert (nextpow2 (intmax ('uint64')), uint64 (64))\n\n## Test input validation\n%!error <Invalid call> nextpow2 ()\n%!error <X must be numeric> nextpow2 (\"t\")\n%!error <X must be real> nextpow2 (1 + 2i)\n"
  },
  {
    "path": "scripts/general/num2str.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{str} =} num2str (@var{x})\n## @deftypefnx {} {@var{str} =} num2str (@var{x}, @var{precision})\n## @deftypefnx {} {@var{str} =} num2str (@var{x}, @var{format})\n## Convert a number (or array) to a string (or a character array).\n##\n## The optional second argument may either give the number of significant\n## digits (@var{precision}) to be used in the output or a format template\n## string (@var{format}) as in @code{sprintf} (@pxref{Formatted Output}).\n## @code{num2str} can also process complex numbers.\n##\n## Examples:\n##\n## @example\n## num2str (123.456)\n##   @xresult{} 123.456\n##\n## num2str (123.456, 4)\n##   @xresult{} 123.5\n##\n## s = num2str ([1, 1.34; 3, 3.56], \"%5.1f\")\n##   @xresult{} s =\n##        1.0  1.3\n##        3.0  3.6\n## whos s\n##   @xresult{} Variables in the current scope:\n##         Attr Name        Size                     Bytes  Class\n##         ==== ====        ====                     =====  =====\n##              s           2x8                         16  char\n##      Total is 16 elements using 16 bytes\n##\n## num2str (1.234 + 27.3i)\n##   @xresult{} 1.234+27.3i\n## @end example\n##\n## The @code{num2str} function is not very flexible.  For better control\n## over the results, use @code{sprintf} (@pxref{Formatted Output}).\n##\n## Programming Notes:\n##\n## For @sc{matlab} compatibility, leading spaces are stripped before returning\n## the string.\n##\n## Integers larger than @code{flintmax} may not be displayed correctly.\n##\n## For complex @var{x}, the format string may only contain one output\n## conversion specification and nothing else.  Otherwise, results will be\n## unpredictable.\n##\n## Any optional @var{format} specified by the programmer is used without\n## modification.  This is in contrast to @sc{matlab} which tampers with the\n## @var{format} based on internal heuristics.\n## @seealso{sprintf, int2str, mat2str}\n## @end deftypefn\n\nfunction str = num2str (x, arg)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! (isnumeric (x) || islogical (x) || ischar (x)))\n    error (\"num2str: X must be a numeric, logical, or character array\");\n  endif\n\n  if (ischar (x))\n    str = x;\n  elseif (isempty (x))\n    str = \"\";\n  elseif (isreal (x))\n    if (nargin == 2)\n      if (ischar (arg))\n        fmt = arg;\n      elseif (isnumeric (arg) && isscalar (arg) && arg >= 0 && arg == fix (arg))\n        if (isfloat (x))\n          fmt = sprintf (\"%%%d.%dg\", arg+7, arg);\n        else\n          fmt = sprintf (\"%%%dd\", arg);\n        endif\n      else\n        error (\"num2str: PRECISION must be a scalar integer >= 0\");\n      endif\n    else\n      if (isnumeric (x))\n        ## Set up a suitable format string while ignoring Inf/NaN entries\n        valid = isfinite (x(:));\n        ndgt = floor (log10 (max (abs (x(valid)))));\n        if (isempty (ndgt) || ndgt == -Inf)\n          ndgt = 0;  # All Inf or all zero array\n        endif\n\n        if (ndgt > 15 || any (x(valid) != fix (x(valid))))\n          ## Floating point input\n          ndgt = max (ndgt + 5, 5);   # Keep at least 5 significant digits\n          ndgt = min (ndgt, 16);      # Cap significant digits at 16\n          fmt = sprintf (\"%%%d.%dg\", ndgt+7, ndgt);\n        else\n          ## Integer input\n          ndgt += 3;\n          if (any (! valid))\n            ndgt = max (ndgt, 5);     # Allow space for Inf/NaN\n          endif\n          if (isfloat (x))\n            fmt = sprintf (\"%%%d.0f\", ndgt);\n          else\n            fmt = sprintf (\"%%%dd\", ndgt);\n          endif\n        endif\n      else\n        ## Logical input\n        fmt = \"%3d\";\n      endif\n    endif\n    ## FIXME: Remove when Matlab strings are implemented in Octave.\n    warning ('off', 'Octave:mixed-string-concat', 'local');\n    fmt = do_string_escapes (fmt);  # required now that '\\n' is interpreted.\n    nd = ndims (x);\n    nc = columns (x) * (nd - 1);    # N-D arrays are expanded in columns\n    x  = permute (x, [2, 3:nd, 1]);\n    if (! (sum (strrep (fmt, \"%%\", \"\") == \"%\") > 1\n           || any (strcmp (fmt, {\"%s\", \"%c\"}))))\n      fmt = [deblank(repmat (fmt, 1, nc)), \"\\n\"];\n    endif\n    strtmp = sprintf (fmt, x);\n    str = strtrim (char (ostrsplit (strtmp, \"\\n\", true)));\n  else   # Complex matrix input\n    if (nargin == 2)\n      if (ischar (arg))\n        fmt = [deblank(arg) \"%-+\" arg(2:end) \"i\"];\n      elseif (isnumeric (arg) && isscalar (arg) && arg >= 0 && arg == fix (arg))\n        fmt = sprintf (\"%%%d.%dg%%-+%d.%dgi\", arg+7, arg, arg+7, arg);\n      else\n        error (\"num2str: PRECISION must be a scalar integer >= 0\");\n      endif\n    else\n      ## Set up a suitable format string while ignoring Inf/NaN entries\n      valid_real = isfinite (real (x(:)));\n      valid_imag = isfinite (imag (x(:)));\n      ndgt = floor (log10 (max (max (abs (real (x(valid_real)))),\n                                max (abs (imag (x(valid_imag)))))));\n      if (isempty (ndgt) || ndgt == -Inf)\n        ndgt = 0;  # All Inf or all zero array\n      endif\n\n      if (any (x(valid_real & valid_imag) != fix (x(valid_real & valid_imag))))\n        ## Floating point input\n        ndgt = max (ndgt + 5, 5);   # Keep at least 5 significant digits\n        ndgt = min (ndgt, 16);      # Cap significant digits at 16\n        fmt = sprintf (\"%%%d.%dg%%-+%d.%dgi\", ndgt+7, ndgt, ndgt+7, ndgt);\n      else\n        ## Integer input\n        ndgt += 3;\n        ## FIXME: Integers must be masked to show only 16 significant digits\n        ##        See test case for bug #36133 below\n        fmt = sprintf (\"%%%d.0f%%-+%d.0fi\", ndgt, ndgt);\n      endif\n    endif\n\n    ## Manipulate the complex value to have real values in the odd\n    ## columns and imaginary values in the even columns.\n    nd = ndims (x);\n    nc = columns (x);\n    idx = repmat ({':'}, nd, 1);\n    perm(1:2:2*nc) = 1:nc;\n    perm(2:2:2*nc) = nc + (1:nc);\n    idx{2} = perm;\n    x = horzcat (real (x), imag (x));\n    x = x(idx{:});\n\n    fmt = [deblank(repmat(fmt, 1, nc * (nd - 1))), \"\\n\"];\n    tmp = sprintf (fmt, permute (x, [2, 3:nd, 1]));\n\n    ## Put the \"i\"'s where they are supposed to be.\n    tmp = regexprep (tmp, \" +i\\n\", \"i\\n\");\n    tmp = regexprep (tmp, \"( +)i\", \"i$1\");\n\n    str = strtrim (char (ostrsplit (tmp(1:end-1), \"\\n\")));\n  endif\n\nendfunction\n\n\n## Basic tests\n%!assert (num2str (123), \"123\")\n%!assert (num2str (1.23), \"1.23\")\n%!assert (num2str (123.456, 4), \"123.5\")\n%!assert (num2str ([1, 1.34; 3, 3.56], \"%5.1f\"), [\"1.0  1.3\"; \"3.0  3.6\"])\n%!assert (num2str (1.234 + 27.3i), \"1.234+27.3i\")\n%!assert (num2str ([true false true]), \"1  0  1\")\n\n## Exceptional values\n%!assert (num2str (19440606), \"19440606\")\n%!assert (num2str (2^33), \"8589934592\")\n%!assert (num2str (-2^33), \"-8589934592\")\n%!assert (num2str (2^33+1i), \"8589934592+1i\")\n%!assert (num2str (-2^33+1i), \"-8589934592+1i\")\n%!assert (num2str ([0 0 0]), \"0  0  0\")\n%!assert (num2str (inf), \"Inf\")\n%!assert (num2str ([inf -inf]), \"Inf -Inf\")\n%!assert (num2str ([inf NaN -inf]), \"Inf  NaN -Inf\")\n%!assert (num2str ([complex(Inf,0), complex(0,-Inf)]), \"Inf+0i   0-Infi\")\n%!assert (num2str (complex (Inf,1)), \"Inf+1i\")\n%!assert (num2str (complex (1,Inf)), \"1+Infi\")\n%!assert (num2str (nan), \"NaN\")\n%!assert (num2str (complex (NaN, 1)), \"NaN+1i\")\n%!assert (num2str (complex (1, NaN)), \"1+NaNi\")\n%!assert (num2str (NA), \"NA\")\n%!assert (num2str (complex (NA, 1)), \"NA+1i\")\n%!assert (num2str (complex (1, NA)), \"1+NAi\")\n%!assert (num2str (int64 (-flintmax ()) - 1), \"-9007199254740993\")\n%!assert (num2str (int64 (-flintmax ()) - 1, 18), \"-9007199254740993\")\n\n## ND-arrays are concatenated in columns\n%!shared m, x\n%! m = magic (3);\n%! x = cat (3, m, -m);\n\n## real case\n%!test <*46770>\n%! y = num2str (x);\n%! assert (rows (y) == 3);\n%! assert (y, [\"8  1  6 -8 -1 -6\"\n%!             \"3  5  7 -3 -5 -7\"\n%!             \"4  9  2 -4 -9 -2\"]);\n\n## complex case\n%!test <*46770>\n%! x(1,1,2) = -8+2i;\n%! y = num2str (x);\n%! assert (rows (y) == 3);\n%! assert (y, [\"8+0i   1+0i   6+0i  -8+2i  -1+0i  -6+0i\"\n%!             \"3+0i   5+0i   7+0i  -3+0i  -5+0i  -7+0i\"\n%!             \"4+0i   9+0i   2+0i  -4+0i  -9+0i  -2+0i\"]);\n\n## Clear shared variables\n%!shared\n\n## Integers greater than 1e15 should switch to exponential notation\n%!assert <*36133> (num2str (1e15), \"1000000000000000\")\n%!assert <*36133> (num2str (1e16), \"1e+16\")\n## Even exact integers in IEEE notation should use exponential notation\n%!assert <*36133> (num2str (2^512), \"1.34078079299426e+154\")\n## Mixed integer/floating point arrays\n%!assert <*36133> (num2str ([2.1, 1e23, pi]),\n%!                 \"2.1  9.999999999999999e+22      3.141592653589793\")\n\n## Large integers should not switch sign when printed due to overflow\n%!assert <*36121> (num2str (2.4e9, 15), \"2400000000\")\n\n## Test for extra rows generated from newlines in format\n%!assert <*44864> (rows (num2str (magic (3), \"%3d %3d %3d\\n\")), 3)\n\n## Test that string conversion of numeric objects results in characters\n## if the numbers are within range for ASCII.\n%!assert <*45174> (num2str ([65 66 67], \"%s\"), \"ABC\")\n\n## Test input validation\n%!error <Invalid call> num2str ()\n%!error <X must be a numeric> num2str ({1})\n%!error <PRECISION must be a scalar integer .= 0> num2str (1, {1})\n%!error <PRECISION must be a scalar integer .= 0> num2str (1, ones (2))\n%!error <PRECISION must be a scalar integer .= 0> num2str (1, -1)\n%!error <PRECISION must be a scalar integer .= 0> num2str (1, 1.5)\n%!error <PRECISION must be a scalar integer .= 0> num2str (1+1i, {1})\n%!error <PRECISION must be a scalar integer .= 0> num2str (1+1i, ones (2))\n%!error <PRECISION must be a scalar integer .= 0> num2str (1+1i, -1)\n%!error <PRECISION must be a scalar integer .= 0> num2str (1+1i, 1.5)\n"
  },
  {
    "path": "scripts/general/pagectranspose.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} pagectranspose (@var{A})\n## Return the page-wise complex conjugate transpose of the N-dimensional array\n## @var{A}.\n##\n## This is equivalent to @tcode{@var{A}(:,:, @var{k})'} for each page @var{k}.\n##\n## @seealso{pagetranspose, ctranspose, permute}\n## @end deftypefn\n\nfunction B = pagectranspose (A)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  B = permute (conj (A), [2, 1, 3:ndims(A)]);\n\nendfunction\n\n\n%!test\n%! A = reshape (1:8, [2, 2, 2]);\n%! B = pagectranspose (A);\n%! assert (B, cat (3, [1,2;3,4], [5,6;7,8]));\n\n%!test\n%! A = reshape ((1:8)*i, [2, 2, 2]);\n%! B = pagectranspose (A);\n%! assert (B, -i * cat (3, [1,2;3,4], [5,6;7,8]));\n\n## Test input validation\n%!error <Invalid call> pagectranspose ()\n"
  },
  {
    "path": "scripts/general/pagetranspose.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{B} =} pagetranspose (@var{A})\n## Return the page-wise transpose of the N-dimensional array @var{A}.\n##\n## This is equivalent to @tcode{@var{A}(:,:, @var{k}).@:'} for each page\n## @var{k}.\n##\n## @seealso{pagectranspose, transpose, permute}\n## @end deftypefn\n\nfunction B = pagetranspose (A)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  B = permute (A, [2, 1, 3:ndims(A)]);\n\nendfunction\n\n\n%!test\n%! A = reshape (1:8, [2, 2, 2]);\n%! B = pagetranspose (A);\n%! assert (B, cat (3, [1,2;3,4], [5,6;7,8]));\n\n%!test\n%! A = reshape ((1:8)*i, [2, 2, 2]);\n%! B = pagetranspose (A);\n%! assert (B, i * cat (3, [1,2;3,4], [5,6;7,8]));\n\n## Test input validation\n%!error <Invalid call> pagetranspose ()\n"
  },
  {
    "path": "scripts/general/pol2cart.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{x}, @var{y}] =} pol2cart (@var{theta}, @var{r})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} pol2cart (@var{theta}, @var{r}, @var{z})\n## @deftypefnx {} {[@var{x}, @var{y}] =} pol2cart (@var{P})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} pol2cart (@var{P})\n## Transform polar or cylindrical coordinates to Cartesian coordinates.\n##\n## The inputs @var{theta}, @var{r}, (and @var{z}) must be the same shape, or\n## scalar.  If called with a single matrix argument then each row of @var{P}\n## represents the polar coordinate pair (@var{theta}, @var{r}) or the\n## cylindrical triplet (@var{theta}, @var{r}, @var{z}).\n##\n## The outputs @var{x}, @var{y} (, and @var{z}) match the shape of the inputs.\n## For a matrix input @var{P} the outputs will be column vectors with rows\n## corresponding to the rows of the input matrix.\n##\n## @var{theta} describes the angle relative to the positive x-axis measured in\n## the xy-plane.\n##\n## @var{r} is the distance to the z-axis @w{(0, 0, z)}.\n##\n## @var{z}, if present, is unchanged by the transformation.\n##\n## The coordinate transformation is computed using:\n## @tex\n## $$ x = r \\cos \\theta $$\n## $$ y = r \\sin \\theta $$\n## $$ z = z $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## @var{x} = @var{r} * cos (@var{theta})\n## @var{y} = @var{r} * sin (@var{theta})\n## @var{z} = @var{z}\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @seealso{cart2pol, sph2cart, cart2sph}\n## @end deftypefn\n\nfunction [x, y, z] = pol2cart (theta, r, z = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    if (! (isnumeric (theta) && ismatrix (theta)))\n      error (\"cart2pol: matrix input P must be 2-D numeric array\");\n    endif\n    if (isvector (theta))\n      n = numel (theta);\n      if (n != 2 && n != 3)\n        error (\"cart2pol: matrix input must be a 2- or 3-element vector or a 2- or 3-column array\");\n      endif\n      if (n == 3)\n        z = theta(3);\n      endif\n      r = theta(2);\n      theta = theta(1);\n\n    else\n      ncols = columns (theta);\n      if (ncols != 2 && ncols != 3)\n        error (\"cart2pol: matrix input must be a 2- or 3-element vector or a 2- or 3-column array\");\n      endif\n\n      if (ncols == 3)\n        z = theta(:,3);\n      endif\n      r = theta(:,2);\n      theta = theta(:,1);\n    endif\n\n  elseif (nargin == 2)\n    if (! (isnumeric (theta) && isnumeric (r)))\n      error (\"pol2cart: THETA, R must be numeric arrays or scalars\");\n    endif\n    [err, theta, r] = common_size (theta, r);\n    if (err)\n      error (\"pol2cart: THETA, R must be the same size or scalars\");\n    endif\n\n  elseif (nargin == 3)\n    if (! (isnumeric (theta) && isnumeric (r) && isnumeric (z)))\n      error (\"pol2cart: THETA, R, Z must be numeric arrays or scalars\");\n    endif\n    [err, theta, r, z] = common_size (theta, r, z);\n    if (err)\n      error (\"pol2cart: THETA, R, Z must be the same size or scalars\");\n    endif\n  endif\n\n  x = r .* cos (theta);\n  y = r .* sin (theta);\n\nendfunction\n\n\n%!test\n%! t = [0, 0.5, 1] * pi;\n%! r = 1;\n%! [x, y] = pol2cart (t, r);\n%! assert (x, [1, 0, -1], eps);\n%! assert (y, [0, 1,  0], eps);\n\n%!test\n%! t = [0, 1, 1] * pi/4;\n%! r = sqrt (2) * [0, 1, 2];\n%! [x, y] = pol2cart (t, r);\n%! assert (x, [0, 1, 2], 2*eps);\n%! assert (y, [0, 1, 2], 2*eps);\n\n%!test\n%! t = [0, 1, 1] * pi/4;\n%! r = sqrt (2) * [0, 1, 2];\n%! z = [0, 1, 2];\n%! [x, y, z2] = pol2cart (t, r, z);\n%! assert (x, [0, 1, 2], 2*eps);\n%! assert (y, [0, 1, 2], 2*eps);\n%! assert (z2, z);\n\n%!test\n%! t = [0; 1; 1] * pi/4;\n%! r = sqrt (2) * [0; 1; 2];\n%! z = [0; 1; 2];\n%! [x, y, z2] = pol2cart (t, r, z);\n%! assert (x, [0; 1; 2], 2*eps);\n%! assert (y, [0; 1; 2], 2*eps);\n%! assert (z2, z);\n\n\n%!test\n%! t = 0;\n%! r = [0, 1, 2];\n%! z = [0, 1, 2];\n%! [x, y, z2] = pol2cart (t, r, z);\n%! assert (x, [0, 1, 2], eps);\n%! assert (y, [0, 0, 0], eps);\n%! assert (z2, z);\n\n%!test\n%! t = [1, 1, 1]*pi/4;\n%! r = 1;\n%! z = [0, 1, 2];\n%! [x, y, z2] = pol2cart (t, r, z);\n%! assert (x, [1, 1, 1] / sqrt (2), eps);\n%! assert (y, [1, 1, 1] / sqrt (2), eps);\n%! assert (z2, z);\n\n%!test\n%! t = 0;\n%! r = [1, 2, 3];\n%! z = 1;\n%! [x, y, z2] = pol2cart (t, r, z);\n%! assert (x, [1, 2, 3], eps);\n%! assert (y, [0, 0, 0] / sqrt (2), eps);\n%! assert (z2, [1, 1, 1]);\n\n%!test\n%! P = [0, 0; pi/4, sqrt(2); pi/4, 2*sqrt(2)];\n%! [x, y] = pol2cart(P);\n%! assert (x, [0; 1; 2], 2*eps);\n%! assert (y, [0; 1; 2], 2*eps);\n\n%!test\n%! P = [0, 0, 0; pi/4, sqrt(2), 1; pi/4, 2*sqrt(2), 2];\n%! [x, y, z] = pol2cart(P);\n%! assert (x, [0; 1; 2], 2*eps);\n%! assert (y, [0; 1; 2], 2*eps);\n%! assert (z, P(:,3), 2*eps);\n\n%!test\n%! P = [0, 0, 0; pi/4, sqrt(2), 1; pi/4, 2*sqrt(2), 2; 0, 0, 0];\n%! [x, y, z] = pol2cart(P);\n%! assert (x, [0; 1; 2; 0], 2*eps);\n%! assert (y, [0; 1; 2; 0], 2*eps);\n%! assert (z, P(:,3), 2*eps);\n\n%!test\n%! r = ones (1, 1, 1, 2);\n%! r(1, 1, 1, 2) = 2;\n%! t = pi/2 * r;\n%! [x, y] = pol2cart (t, r);\n%! X = zeros (1, 1, 1, 2);\n%! X(1, 1, 1, 2) = -2;\n%! Y = zeros (1, 1, 1, 2);\n%! Y(1, 1, 1, 1) = 1;\n%! assert (x, X, 2*eps);\n%! assert (y, Y, 2*eps);\n\n%!test\n%! [t, r, Z] = meshgrid ([0, pi/2], [1, 2], [0, 1]);\n%! [x, y, z] = pol2cart (t, r, Z);\n%! X = zeros (2, 2, 2);\n%! X(:, 1, 1) = [1; 2];\n%! X(:, 1, 2) = [1; 2];\n%! Y = zeros (2, 2, 2);\n%! Y(:, 2, 1) = [1; 2];\n%! Y(:, 2, 2) = [1; 2];\n%! assert (x, X, eps);\n%! assert (y, Y, eps);\n%! assert (z, Z);\n\n## Test input validation\n%!error <Invalid call> pol2cart ()\n%!error <matrix input P must be 2-D numeric array> pol2cart ({1,2,3})\n%!error <matrix input P must be 2-D numeric array> pol2cart (ones (3,3,2))\n%!error <matrix input must be a 2- or 3-element> pol2cart ([1])\n%!error <matrix input must be a 2- or 3-element> pol2cart ([1,2,3,4])\n%!error <must be numeric arrays or scalars> pol2cart ({1,2,3}, [1,2,3])\n%!error <must be numeric arrays or scalars> pol2cart ([1,2,3], {1,2,3})\n%!error <must be the same size or scalars> pol2cart (ones (3,3,3), ones (3,2,3))\n%!error <must be the same size or scalars> pol2cart ([1; 1], [2, 2])\n%!error <must be the same size or scalars> pol2cart ([1; 1], [2, 2], [3, 3])\n%!error <must be numeric arrays or scalars> pol2cart ({1,2,3}, [1,2,3], [1,2,3])\n%!error <must be numeric arrays or scalars> pol2cart ([1,2,3], {1,2,3}, [1,2,3])\n%!error <must be numeric arrays or scalars> pol2cart ([1,2,3], [1,2,3], {1,2,3})\n%!error <must be the same size or scalars> pol2cart (ones (3,3,3), 1, ones (3,2,3))\n%!error <must be the same size or scalars> pol2cart (ones (3,3,3), ones (3,2,3), 1)\n"
  },
  {
    "path": "scripts/general/polyarea.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{a} =} polyarea (@var{x}, @var{y})\n## @deftypefnx {} {@var{a} =} polyarea (@var{x}, @var{y}, @var{dim})\n##\n## Determine area of a polygon by triangle method.\n##\n## The variables @var{x} and @var{y} define the vertex pairs, and must\n## therefore have the same shape.  They can be either vectors or arrays.  If\n## they are arrays then the columns of @var{x} and @var{y} are treated\n## separately and an area returned for each.\n##\n## If the optional @var{dim} argument is given, then @code{polyarea} works\n## along this dimension of the arrays @var{x} and @var{y}.\n##\n## @end deftypefn\n\n## FIXME: Add moments for centroid, etc.\n##\n## Bugs and limitations:\n##        Probably ought to be an optional check to make sure that\n##        traversing the vertices doesn't make any sides cross\n##        (Is simple closed curve the technical definition of this?).\n\nfunction a = polyarea (x, y, dim)\n\n  if (nargin < 2)\n    print_usage ();\n  elseif (! size_equal (x, y))\n    error (\"polyarea: X and Y must have the same shape\");\n  endif\n\n  if (nargin == 2)\n    a = abs (sum (x .* (circshift (y, -1) - circshift (y, 1)))) / 2;\n  else\n    a = abs (sum (x .* (circshift (y, -1, dim) - circshift (y, 1, dim)), dim)) / 2;\n  endif\n\nendfunction\n\n\n%!shared x, y\n%! x = [1;1;3;3;1];\n%! y = [1;3;3;1;1];\n%!assert (polyarea (x,y), 4, eps)\n%!assert (polyarea ([x,x],[y,y]), [4,4], eps)\n%!assert (polyarea ([x,x],[y,y],1), [4,4], eps)\n%!assert (polyarea ([x,x]',[y,y]',2), [4;4], eps)\n"
  },
  {
    "path": "scripts/general/postpad.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} postpad (@var{A}, @var{l})\n## @deftypefnx {} {@var{B} =} postpad (@var{A}, @var{l}, @var{c})\n## @deftypefnx {} {@var{B} =} postpad (@var{A}, @var{l}, @var{c}, @var{dim})\n## Append the scalar value @var{c} to the vector @var{A} until it is of length\n## @var{l}.  If @var{c} is not given, a value of 0 is used.\n##\n## If @code{length (@var{A}) > @var{l}}, elements from the end of @var{A} are\n## removed until a vector of length @var{l} is obtained.\n##\n## If @var{A} is a matrix, elements are appended or removed from each row.\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n##\n## If @var{dim} is larger than the dimensions of @var{A}, the result will have\n## @var{dim} dimensions.\n## @seealso{prepad, cat, resize}\n## @end deftypefn\n\nfunction B = postpad (A, l, c, dim)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (nargin < 3 || isempty (c))\n    c = 0;\n  else\n    if (! isscalar (c))\n      error (\"postpad: third argument must be empty or a scalar\");\n    endif\n  endif\n\n  nd = ndims (A);\n  sz = size (A);\n  if (nargin < 4)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  else\n    if (!(isscalar (dim) && dim == fix (dim) && dim >= 1))\n      error (\"postpad: DIM must be an integer and a valid dimension\");\n    endif\n  endif\n\n  if (! isscalar (l) || l < 0)\n    error (\"postpad: second argument must be a positive scaler\");\n  endif\n\n  if (dim > nd)\n    sz(nd+1:dim) = 1;\n  endif\n\n  d = sz(dim);\n\n  if (d == l)\n    ## This optimization makes sense because the function is used to match\n    ## the length between two vectors not knowing a priori is larger, and\n    ## allow for:\n    ##    ml = max (numel (v1), numel (v2));\n    ##    v1 = postpad (v1, ml);\n    ##    v2 = postpad (v2, ml);\n    B = A;\n  elseif (d >= l)\n    idx = repmat ({':'}, nd, 1);\n    idx{dim} = 1:l;\n    B = A(idx{:});\n  else\n    sz(dim) = l - d;\n    B = cat (dim, A, c(ones (sz)));\n  endif\n\nendfunction\n\n\n%!assert (postpad ([1,2], 4), [1,2,0,0])\n%!assert (postpad ([1;2], 4), [1;2;0;0])\n%!assert (postpad ([1,2], 4, 2), [1,2,2,2])\n%!assert (postpad ([1;2], 4, 2), [1;2;2;2])\n%!assert (postpad ([1,2], 2, 2, 1), [1,2;2,2])\n%!assert (postpad ([1;2], 2, 2, 3), reshape ([1;2;2;2], 2, 1, 2))\n%!assert (postpad ([1,2], 2, 2, 3), reshape ([1,2,2,2], 1, 2, 2))\n\n%!assert (postpad ([1 2], 2), [1 2])\n%!assert (postpad ([1; 2], 2), [1; 2])\n%!assert (postpad ([1; 2], 2, 3, 2), [1 3; 2 3])\n\n%! ## Test with string concatenation\n%!assert <*44162> (postpad (\"Octave\", 16, \"x\"), \"Octavexxxxxxxxxx\")\n%!assert (postpad (\"Octave\", 4), \"Octa\")\n\n%!error <Invalid call> postpad ()\n%!error <Invalid call> postpad (1)\n"
  },
  {
    "path": "scripts/general/prepad.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} prepad (@var{A}, @var{l})\n## @deftypefnx {} {@var{B} =} prepad (@var{A}, @var{l}, @var{c})\n## @deftypefnx {} {@var{B} =} prepad (@var{A}, @var{l}, @var{c}, @var{dim})\n## Prepend the scalar value @var{c} to the vector @var{A} until it is of length\n## @var{l}.  If @var{c} is not given, a value of 0 is used.\n##\n## If @code{length (@var{A}) > @var{l}}, elements from the beginning of @var{A}\n## are removed until a vector of length @var{l} is obtained.\n##\n## If @var{A} is a matrix, elements are prepended or removed from each row.\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n##\n## If @var{dim} is larger than the dimensions of @var{A}, the result will have\n## @var{dim} dimensions.\n## @seealso{postpad, cat, resize}\n## @end deftypefn\n\nfunction B = prepad (A, l, c, dim)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (nargin < 3 || isempty (c))\n    c = 0;\n  else\n    if (! isscalar (c))\n      error (\"prepad: pad value C must be empty or a scalar\");\n    endif\n  endif\n\n  nd = ndims (A);\n  sz = size (A);\n  if (nargin < 4)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  else\n    if (!(isscalar (dim) && dim == fix (dim) && dim >= 1))\n      error (\"prepad: DIM must be an integer and a valid dimension\");\n    endif\n  endif\n\n  if (! isscalar (l) || l < 0)\n    error (\"prepad: length L must be a positive scalar\");\n  endif\n\n  if (dim > nd)\n    sz(nd+1:dim) = 1;\n  endif\n\n  d = sz(dim);\n\n  if (d == l)\n    ## This optimization makes sense because the function is used to match\n    ## the length between two vectors not knowing a priori is larger, and\n    ## allow for:\n    ##    ml = max (numel (v1), numel (v2));\n    ##    v1 = prepad (v1, ml);\n    ##    v2 = prepad (v2, ml);\n    B = A;\n  elseif (d >= l)\n    idx = repmat ({':'}, nd, 1);\n    idx{dim} = d-l+1:d;\n    B = A(idx{:});\n  else\n    sz(dim) = l - d;\n    B = cat (dim, c(ones (sz)), A);\n  endif\n\nendfunction\n\n\n%!assert (prepad ([1,2], 4), [0,0,1,2])\n%!assert (prepad ([1;2], 4), [0;0;1;2])\n\n%!assert (prepad ([1,2], 4, 2), [2,2,1,2])\n%!assert (prepad ([1;2], 4, 2), [2;2;1;2])\n\n%!assert (prepad ([1 2], 2), [1 2])\n%!assert (prepad ([1; 2], 2), [1; 2])\n%!assert (prepad ([1; 2], 2, 3, 2), [3 1; 3 2])\n\n%!assert (prepad ([1,2], 2, 2, 1), [2,2;1,2])\n\n%!assert (prepad ([1,2], 2, 2, 3), reshape ([2,2,1,2], 1, 2, 2))\n%!assert (prepad ([1;2], 2, 2, 3), reshape ([2;2;1;2], 2, 1, 2))\n\n%! ## Test with string concatenation\n%!assert <*44162> (prepad (\"Octave\", 16, \"x\"), \"xxxxxxxxxxOctave\")\n%!assert (prepad (\"Octave\", 4), \"tave\")\n\n## FIXME: We need tests for multi-dimensional arrays.\n\n%!error <Invalid call> prepad ()\n%!error <Invalid call> prepad (1)\n%!error <C must be empty or a scalar> prepad ([1,2], 2, ones (2))\n%!error <DIM must be an integer> prepad ([1,2], 2, 2, ones (3))\n%!error <DIM must be an integer> prepad ([1,2], 2, 2, 1.1)\n%!error <L must be a positive scalar> prepad ([1,2], ones (2))\n%!error <L must be a positive scalar> prepad ([1,2], -1)\n"
  },
  {
    "path": "scripts/general/private/__splinen__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{yi} =} __splinen__ (@var{x}, @var{y}, @var{xi}, @var{extrapval}, @var{f})\n## Undocumented internal function.\n## @end deftypefn\n\n## FIXME: Allow arbitrary grids.\n\nfunction yi = __splinen__ (x, y, xi, extrapval, f)\n\n  ## N-D function to check whether any object in cell array is *not* a vector.\n  isnotvec = @(x) cellfun (\"numel\", x) != cellfun (\"length\", x);\n  if (! iscell (x) || length (x) < ndims (y) || any (isnotvec (x))\n      || ! iscell (xi) || length (xi) < ndims (y) || any (isnotvec (xi)))\n    error (\"__splinen__: %s: non-gridded data or dimensions inconsistent\", f);\n  endif\n\n  yi = y;\n  for i = length (x):-1:1\n    yi = permute (spline (x{i}, yi, xi{i}(:)), [length(x),1:length(x)-1]);\n  endfor\n\n  if (! isempty (extrapval))\n    [xi{:}] = ndgrid (cellfun (@(x) x(:), xi, \"uniformoutput\", false){:});\n    idx = false (size (xi{1}));\n    for i = 1 : length (x)\n      idx |= xi{i} < min (x{i}(:)) | xi{i} > max (x{i}(:));\n    endfor\n    yi(idx) = extrapval;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/general/quad2d.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} quad2d (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb})\n## @deftypefnx {} {@var{q} =} quad2d (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {[@var{q}, @var{err}, @var{iter}] =} quad2d (@dots{})\n##\n## Numerically evaluate the two-dimensional integral of @var{f} using adaptive\n## quadrature over the two-dimensional domain defined by @var{xa}, @var{xb},\n## @var{ya}, @var{yb} using tiled integration.  Additionally, @var{ya} and\n## @var{yb} may be scalar functions of @var{x}, allowing for the integration\n## over non-rectangular domains.\n##\n## @var{f} is a function handle, inline function, or string containing the\n## name of the function to evaluate.  The function @var{f} must be of the form\n## @math{z = f(x,y)}, and all operations must be vectorized such that @var{x}\n## and @var{y} accept array inputs and return array outputs of the same size.\n## (It can be assumed that @var{x} and @var{y} will either be same-size arrays\n## or one will be a scalar.)  The underlying integrators will input arrays of\n## integration points into @var{f} and/or use internal vector expansions to\n## speed computation that can produce unpredictable results if @var{f} is not\n## restricted to elementwise operations.  For integrands where this is\n## unavoidable, the @qcode(\"Vectorized\") option described below may produce\n## more reliable results.\n##\n## Additional optional parameters can be specified using\n## @qcode{\"@var{property}\", @var{value}} pairs.  Valid properties are:\n##\n## @table @code\n## @item AbsTol\n## Define the absolute error tolerance for the quadrature.  The default\n## value is 1e-10 (1e-5 for single).\n##\n## @item RelTol\n## Define the relative error tolerance for the quadrature.  The default\n## value is 1e-6 (1e-4 for single).\n##\n## @item MaxFunEvals\n## The maximum number of function calls to the vectorized function @var{f}.\n## The default value is 5000.\n##\n## @item Singular\n## Enable/disable transforms to weaken singularities on the edge of the\n## integration domain.  The default value is @var{true}.\n##\n## @item Vectorized\n## Enable or disable vectorized integration.  A value of @code{false} forces\n## Octave to use only scalar inputs when calling the integrand, which enables\n## integrands @math{f(x,y)} that have not been vectorized or only accept\n## scalar values of @var{x} or @var{y}.  The default value is @code{true}.\n## Note that this is achieved by wrapping @math{f(x,y)} with the function\n## @code{arrayfun}, which may significantly decrease computation speed.\n##\n## @item FailurePlot\n## If @code{quad2d} fails to converge to the desired error tolerance before\n## MaxFunEvals is reached, a plot of the areas that still need refinement\n## is created.  The default value is @var{false}.\n## @end table\n##\n## Adaptive quadrature is used to minimize the estimate of error until the\n## following is satisfied:\n## @tex\n## $$error \\leq \\max \\left( AbsTol, RelTol\\cdot\\vert q\\vert \\right)$$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##         @var{error} <= max (@var{AbsTol}, @var{RelTol}*|@var{q}|)\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## The optional output @var{err} is an approximate bound on the error in the\n## integral @code{abs (@var{q} - @var{I})}, where @var{I} is the exact value\n## of the integral.  The optional output @var{iter} is the number of vectorized\n## function calls to the function @var{f} that were used.\n##\n## Example 1 : integrate a rectangular region in x-y plane\n##\n## @example\n## @group\n## @var{f} = @@(@var{x},@var{y}) 2*ones (size (@var{x}));\n## @var{q} = quad2d (@var{f}, 0, 1, 0, 1)\n##   @xresult{} @var{q} =  2\n## @end group\n## @end example\n##\n## The result is a volume, which for this constant-value integrand, is just\n## @code{@var{Length} * @var{Width} * @var{Height}}.\n##\n## Example 2 : integrate a triangular region in x-y plane\n##\n## @example\n## @group\n## @var{f} = @@(@var{x},@var{y}) 2*ones (size (@var{x}));\n## @var{ymax} = @@(@var{x}) 1 - @var{x};\n## @var{q} = quad2d (@var{f}, 0, 1, 0, @var{ymax})\n##   @xresult{} @var{q} =  1\n## @end group\n## @end example\n##\n## The result is a volume, which for this constant-value integrand\n## @w{@math{@var{f} = 2}}, is the Triangle Area x Height or\n## @w{@code{1/2 * @var{Base} * @var{Width} * @var{Height}}}.\n##\n## Example 3 : integrate a non-vectorized function over a square region\n##\n## @example\n## @group\n## @var{f} = @@(@var{x},@var{y}) sinc (@var{x}) * sinc (@var{y}));\n## @var{q} = quad2d (@var{f}, -1, 1, -1, 1)\n##   @xresult{} @var{q} =  12.328  (incorrect)\n## @var{q} = quad2d (@var{f}, -1, 1, -1, 1, \"Vectorized\", false)\n##   @xresult{} @var{q} =  1.390 (correct)\n## @var{f} = @@(@var{x},@var{y}) sinc (@var{x}) .* sinc (@var{y});\n## @var{q} = quad2d (@var{f}, -1, 1, -1, 1)\n##   @xresult{} @var{q} =  1.390  (correct)\n## @end group\n## @end example\n##\n## The first result is incorrect as the non-elementwise operator between the\n## sinc functions in @var{f} create unintended matrix multiplications between\n## the internal integration arrays used by @code{quad2d}.  In the second\n## result, setting @qcode{\"Vectorized\"} to false forces @code{quad2d} to\n## perform scalar internal operations to compute the integral, resulting in\n## the correct numerical result at the cost of about a 20x increase in\n## computation time.  In the third result, vectorizing the integrand @var{f}\n## using the elementwise multiplication operator gets the correct result\n## without increasing computation time.\n##\n## Programming Notes: If there are singularities within the integration region\n## it is best to split the integral and place the singularities on the\n## boundary.\n##\n## Known @sc{matlab} incompatibility: If tolerances are left unspecified, and\n## any integration limits are of type @code{single}, then Octave's integral\n## functions automatically reduce the default absolute and relative error\n## tolerances as specified above.  If tighter tolerances are desired they\n## must be specified.  @sc{matlab} leaves the tighter tolerances appropriate\n## for @code{double} inputs in place regardless of the class of the\n## integration limits.\n##\n## Reference: @nospell{L.F. Shampine},\n## \"@sc{matlab} program for quadrature in 2D\",\n## @cite{Applied Mathematics and Computation}, @w{Vol.@: 1},\n## @w{pp.@: 266}--274, 2008.\n##\n## @seealso{integral2, dblquad, integral, quad, quadgk, quadv, quadl, quadcc,\n##          trapz, integral3, triplequad}\n## @end deftypefn\n\nfunction [q, err, iter] = quad2d (f, xa, xb, ya, yb, varargin)\n\n  if (nargin < 5 || mod (nargin, 2) == 0)\n    print_usage ();\n  endif\n\n  if (ischar (f))\n    ## Convert function given as a string to a function handle\n    f = @(x) feval (f, x);\n  elseif (! is_function_handle (f))\n    print_usage ();\n  endif\n\n  if (! (isreal (xa) && isscalar (xa) && isreal (xb) && isscalar (xb)))\n    print_usage ();\n  endif\n\n  ## Check for single or double limits to set appropriate default tolerance.\n  issingle = (isa ([xa, xb], \"single\")\n              || (! is_function_handle (ya) && isa (ya, \"single\"))\n              || (! is_function_handle (yb) && isa (yb, \"single\")));\n\n  ## Set defaults, update with any specified parameters.\n  if (issingle)\n    abstol = 1e-5;\n    reltol = 1e-4;\n  else\n    abstol = 1e-10;\n    reltol = 1e-6;\n  endif\n\n  vectorized = true;\n  singular = true;\n  idx = 1;\n  maxiter = 5000;\n  failureplot = false;\n\n  while (idx < nargin - 5)\n    prop = varargin{idx++};\n    if (! ischar (prop))\n      error (\"quad2d: property PROP must be a string\");\n    endif\n\n    switch (lower (prop))\n      case \"abstol\"\n        abstol = varargin{idx++};\n        if (! (isnumeric (abstol) && isscalar (abstol) && abstol >= 0))\n          error (\"quad2d: AbsTol value must be a numeric scalar >= 0\");\n        endif\n\n      case \"reltol\"\n        reltol = varargin{idx++};\n        if (! (isnumeric (reltol) && isscalar (reltol) && reltol >= 0))\n          error (\"quad2d: RelTol value must be a numeric scalar >= 0\");\n        endif\n\n      case \"maxfunevals\"\n        maxiter = varargin{idx++};\n        if (! (isnumeric (maxiter) && isscalar (maxiter)\n               && fix (maxiter) == maxiter && maxiter >= 1))\n          error (\"quad2d: MaxFunEvals value must be a scalar integer >= 1\");\n        endif\n\n      case \"singular\"\n        singular = varargin{idx++};\n        if (! (isscalar (singular) && isreal (singular)))\n          error (\"quad2d: Singular must be a logical value\");\n        endif\n\n      case \"vectorized\"\n        vectorized = varargin{idx++};\n        if (! (isscalar (vectorized) && isreal (vectorized)))\n          error (\"quad2d: Vectorized must be a logical value\");\n        endif\n\n      case \"failureplot\"\n        failureplot = varargin{idx++};\n        if (! (isscalar (failureplot) && isreal (failureplot)))\n          error (\"quad2d: FailurePlot must be a logical value\");\n        endif\n\n      otherwise\n        error (\"quad2d: unknown property '%s'\", prop);\n\n    endswitch\n  endwhile\n\n  if (! vectorized)\n    f = @(x, y) arrayfun (f, x, y);\n  endif\n\n  ## check upper and lower bounds of y\n  if (! is_function_handle (ya))\n    if (! (isreal (ya) && isscalar (ya)))\n      error (\"quad2d: YA must be a real scalar or a function\");\n    endif\n    ya = @(x) ya * ones (rows (x), columns (x));\n  endif\n  if (! is_function_handle (yb))\n    if (! (isreal (yb) && isscalar (yb)))\n      error (\"quad2d: YB must be a real scalar or a function\");\n    endif\n    yb = @(x) yb * ones (rows (x), columns (x));\n  endif\n\n  iter = 0;\n  qaccept = 0;\n  qerraccept = 0;\n\n  if (singular)\n    ## Shampine suggests using the singularity weakening transform\n    ## suggested by Havie.\n    ##   \\int_a^b f(x) dx = \\int_0^pi f (g(t)) (dx / dt) dt\n    ## where\n    ##   g(t) = ((a - b) * cos(t) + (a + b)) / 2\n    ##   dx = - (a - b) * sin(t) / 2 dt\n    ## Now our integral is\n    ##   \\int_a^b \\int_0^1 f(x,y) dydx\n    ## as we already substitute for \"y\", so\n    ##   gx(tx) = ((a - b) * cos(tx) + (a + b)) / 2\n    ##   gy(ty) = (1 - cos(ty)) / 2\n    ##   dydx = (b - a) * sin(tx) * sin(ty) / 4 dtydtx\n\n    xtrans = @(tx) ((xa - xb) .* cos (tx) + (xa + xb)) ./ 2;\n    ytrans = @(ty) (1 - cos (ty)) ./ 2;\n    ztrans = @(tx, ty) (xb - xa) .* sin (tx) .* sin (ty) ./ 4;\n    area = pi ^ 2;\n\n    ## Initialize tile list\n    tilelist(1) = struct (\"xa\", 0, \"xb\", pi, \"ya\", 0, \"yb\", pi, ...\n                          \"q\", 0, \"qerr\", Inf);\n  else\n    xtrans = @(tx) tx;\n    ytrans = @(ty) ty;\n    ztrans = @(tx, ty)  1;\n    area = (xb - xa);\n\n    ## Initialize tile list\n    tilelist(1) = struct (\"xa\", xa, \"xb\", xb, \"ya\", 0, \"yb\", 1, ...\n                          \"q\", 0, \"qerr\", Inf);\n  endif\n\n  while (length (tilelist) > 0 && iter < maxiter)\n    ## Get tile with the largest error\n    [~, idx] = max ([tilelist.qerr]);\n    tile = tilelist(idx);\n    tilelist(idx) = [];\n\n    ## Subdivide the tile into 4 subtiles\n    iter += 4;\n    tiles(4) = struct (\"xa\", tile.xa, \"xb\", tile.xa + (tile.xb - tile.xa) / 2,\n                       \"ya\", tile.ya, \"yb\", tile.ya + (tile.yb - tile.ya) / 2,\n                       \"q\", 0, \"qerr\", 0);\n    tiles(3) = struct (\"xa\", tile.xa, \"xb\", tile.xa + (tile.xb - tile.xa) / 2,\n                       \"ya\", tile.ya + (tile.yb - tile.ya) / 2, \"yb\", tile.yb,\n                       \"q\", 0, \"qerr\", 0);\n    tiles(2) = struct (\"xa\", tile.xa + (tile.xb - tile.xa) / 2, \"xb\", tile.xb,\n                       \"ya\", tile.ya, \"yb\", tile.ya + (tile.yb - tile.ya) / 2,\n                       \"q\", 0, \"qerr\", 0);\n    tiles(1) = struct (\"xa\", tile.xa + (tile.xb - tile.xa) / 2, \"xb\", tile.xb,\n                       \"ya\", tile.ya + (tile.yb - tile.ya) / 2, \"yb\", tile.yb,\n                       \"q\", 0, \"qerr\", 0);\n\n    ## Perform the quadrature of 4 subtiles\n    for i = 1:4\n      [tiles(i).q, tiles(i).qerr] = ...\n        tensorproduct (f, ya, yb, tiles(i), xtrans, ytrans, ztrans, singular);\n    endfor\n\n    q = qaccept + sum ([[tilelist.q], tiles.q]);\n    err = qerraccept + sum ([[tilelist.qerr], tiles.qerr]);\n    tol = max (abstol, reltol .* abs (q));\n\n    ## Shampine suggests taking a margin of a factor of 8 for\n    ## the local tolerance.  That, and the fact that we are subdividing\n    ## into 4 tiles, means we divide by 32 at this point.\n    localtol = tol * ([tile.xb] - [tile.xa]) * ([tile.yb] - [tile.ya]) ...\n               / area / 32;\n\n    ## If global tolerance is met, return.\n    if (err < tol)\n      break;\n    endif\n\n    ## Accept the tiles meeting the tolerance, and add the others back to\n    ## the list of tiles to treat.\n    idx = find ([tiles.qerr] < localtol);\n    qaccept += sum ([tiles(idx).q]);\n    qerraccept += sum ([tiles(idx).qerr]);\n    tiles(idx) = [];\n    tilelist = [tilelist, tiles];\n  endwhile\n\n  ## Verify convergence\n  if (iter >= maxiter)\n    if (err > max (abstol, reltol .* abs (q)))\n      warning ([\"quad2d: \" ...\n                \"Maximum number of sub-tiles reached without convergence\"]);\n    else\n      warning ([\"quad2d: \" ...\n                \"Maximum number of sub-tiles reached, accuracy may be low\"]);\n    endif\n    if (failureplot)\n      newplot ();\n      title (\"quad2d : Areas needing refinement\");\n      for tile = tilelist\n        xaa = xtrans(tile.xa);\n        xbb = xtrans(tile.xb);\n        y1 = ya(xaa) + ytrans(tile.ya) * (yb(xaa) - ya(xaa));\n        y2 = ya(xaa) + ytrans(tile.yb) * (yb(xaa) - ya(xaa));\n        y3 = ya(xbb) + ytrans(tile.yb) * (yb(xbb) - ya(xbb));\n        y4 = ya(xbb) + ytrans(tile.ya) * (yb(xbb) - ya(xbb));\n        patch ([xaa, xaa, xbb, xbb, xaa], [y1, y2, y3, y4, y1], \"b\");\n      endfor\n    endif\n  endif\n\nendfunction\n\nfunction [q, qerr] = tensorproduct (f, ya, yb, tile, xtrans, ytrans, ztrans, singular)\n\n  ## The Shampine TwoD paper proposes using a G3,K7 rule in a tensor product.\n  ## I couldn't find a tabulated abscissas and weights of a G3,K7 rule publicly\n  ## available, so use a G7,K15 rule from Octave's implementation of quadgk.\n\n  persistent abscissa = [-0.9914553711208126e+00, -0.9491079123427585e+00, ...\n                         -0.8648644233597691e+00, -0.7415311855993944e+00, ...\n                         -0.5860872354676911e+00, -0.4058451513773972e+00, ...\n                         -0.2077849550078985e+00,  0.0000000000000000e+00, ...\n                          0.2077849550078985e+00,  0.4058451513773972e+00, ...\n                          0.5860872354676911e+00,  0.7415311855993944e+00, ...\n                          0.8648644233597691e+00,  0.9491079123427585e+00, ...\n                          0.9914553711208126e+00];\n\n  persistent weights15 = [0.2293532201052922e-01,  0.6309209262997855e-01, ...\n                          0.1047900103222502e+00,  0.1406532597155259e+00, ...\n                          0.1690047266392679e+00,  0.1903505780647854e+00, ...\n                          0.2044329400752989e+00,  0.2094821410847278e+00, ...\n                          0.2044329400752989e+00,  0.1903505780647854e+00, ...\n                          0.1690047266392679e+00,  0.1406532597155259e+00, ...\n                          0.1047900103222502e+00,  0.6309209262997855e-01, ...\n                          0.2293532201052922e-01];\n\n  persistent weights7  = [0.0, ...\n                          0.1294849661688697e+00, 0.0, ...\n                          0.2797053914892767e+00, 0.0, ...\n                          0.3818300505051889e+00, 0.0, ...\n                          0.4179591836734694e+00, 0.0, ...\n                          0.3818300505051889e+00, 0.0, ...\n                          0.2797053914892767e+00, 0.0, ...\n                          0.1294849661688697e+00, 0.0];\n\n  xaa = tile.xa;\n  xbb = tile.xb;\n  yaa = tile.ya;\n  ybb = tile.yb;\n\n  tx = ((xbb - xaa) * abscissa + xaa + xbb) / 2;\n  x = xtrans(tx);\n  ty = (abscissa' * (ybb - yaa)  + yaa + ybb) / 2;\n  y = ones (15, 1) * ya(x) + ytrans(ty) * (yb(x) - ya(x));\n\n  xhalfwidth = (xbb - xaa ) / 2;\n  yhalfwidth = ones (15, 1) * (yb(x) - ya(x)) .* (ybb - yaa) ./ 2;\n\n  x = ones (15, 1) * x;\n  tx = ones (15,1) * tx;\n  ty = ty * ones (1, 15);\n\n  z = yhalfwidth .* f (x, y) .* ztrans(tx, ty) .* xhalfwidth;\n  q = weights15 * (weights15 * z).';\n  qerr = abs (weights7 * (weights7 * z).' - q);\n\nendfunction\n\n\n%!shared f\n%! f = @(x, y) x .* y;\n%!assert (quad2d (f, 0, 1, 0, 1), 0.25, 1e-10)\n\n%!test\n%! f = @(x, y) 9 * x.^2 + 15 * y.^2;\n%!assert (quad2d (f, 0, 5, -5, 0, \"AbsTol\", 1e-9), 5000, 1e-9)\n%!assert (quad2d (f, 0, 5, -5, 0, \"RelTol\", 1e-6), 5000, -1e-6)\n%!assert (quad2d (f, 0, 5, -5, 0, \"RelTol\", 1e-6, \"AbsTol\", 1e-9), 5000, 1e-9)\n\n## tests from dblquad\n%!test\n%! f = @(x, y) 1 ./ (x+y);\n%!assert (quad2d (f, 0, 1, 0, 1, \"AbsTol\", 1e-7), 2*log (2), 1e-7)\n%!assert (quad2d (f, 0, 1, 0, 1, \"RelTol\", 1e-5), 2*log (2), -1e-5)\n%!assert (quad2d (f, 0, 1, 0, 1, \"AbsTol\", 1e-8, \"RelTol\", 1e-6),\n%!        2*log (2), -1e-6)\n%!assert (quad2d (f, 0, 1, 0, @(x) 1 - x), 1, -1e-6)\n%!assert (quad2d (f, 0, 1, 0, @(x) 1 - x, \"Singular\", true), 1, -1e-6)\n\n%!assert (quad2d (@(x, y) exp (-x.^2 - y.^2) , -1, 1, -1, 1),\n%!        pi * erf (1).^2, 1e-10)\n\n%!assert (quad2d (@plus, 1, 2, 3, 4), 5, 1e-10)\n\n%!assert <*62972> (quad2d (@(x,y) 1i*ones (size (x)), 0,1,0,1), 1i)\n\n## Test input validation\n%!error <Invalid call> quad2d ()\n%!error <Invalid call> quad2d (@plus)\n%!error <Invalid call> quad2d (@plus, 1)\n%!error <Invalid call> quad2d (@plus, 1, 2)\n%!error <Invalid call> quad2d (@plus, 1, 2, 3)\n%!error <Invalid call> quad2d (@plus, 1, 2, 3, 4, \"foo\")\n%!error quad2d (0, 1, 2, 3, 4)          # f must be function handle\n%!error quad2d (@plus, 1i, 2, 3, 4)     # real limits\n%!error quad2d (@plus, 1, 2i, 3, 4)     # real limits\n%!error quad2d (@plus, [1 1], 2, 3, 4)  # scalar limits\n%!error quad2d (@plus, 1, [2 2], 3, 4)  # scalar limits\n%!error <property PROP must be a string> quad2d (@plus, 1, 2, 3, 4, 99, \"bar\")\n%!error <AbsTol value must be a numeric> quad2d (@plus, 1, 2, 3, 4, \"AbsTol\", \"foo\")\n%!error <AbsTol value must be a .* scalar> quad2d (@plus, 1, 2, 3, 4, \"AbsTol\", [1, 2])\n%!error <AbsTol value must be.* .= 0> quad2d (@plus, 1, 2, 3, 4, \"AbsTol\", -1)\n%!error <RelTol value must be a numeric> quad2d (@plus, 1, 2, 3, 4, \"RelTol\", \"foo\")\n%!error <RelTol value must be a .* scalar> quad2d (@plus, 1, 2, 3, 4, \"RelTol\", [1, 2])\n%!error <RelTol value must be.* .= 0> quad2d (@plus, 1, 2, 3, 4, \"RelTol\", -1)\n%!error <MaxFunEvals value must be a scalar integer>\n%! quad2d (@plus,1,2,3,4, \"MaxFunEvals\", {1});\n%!error <MaxFunEvals value must be a scalar integer>\n%! quad2d (@plus,1,2,3,4, \"MaxFunEvals\", [1 1]);\n%!error <MaxFunEvals value must be a scalar integer>\n%! quad2d (@plus,1,2,3,4, \"MaxFunEvals\", 1.5);\n%!error <MaxFunEvals value must be a scalar integer .= 1>\n%! quad2d (@plus,1,2,3,4, \"MaxFunEvals\", -1);\n%!error <Singular must be a logical value>\n%! quad2d (@plus,1,2,3,4, \"Singular\", [0 1]);\n%!error <Singular must be a logical value>\n%! quad2d (@plus,1,2,3,4, \"Singular\", {true});\n%!error <Vectorized must be a logical value>\n%! quad2d (@plus,1,2,3,4, \"Vectorized\", [0 1]);\n%!error <Vectorized must be a logical value>\n%! quad2d (@plus,1,2,3,4, \"Vectorized\", {true});\n%!error <FailurePlot must be a logical value>\n%! quad2d (@plus,1,2,3,4, \"FailurePlot\", [0 1]);\n%!error <FailurePlot must be a logical value>\n%! quad2d (@plus,1,2,3,4, \"FailurePlot\", {true});\n%!error <unknown property 'foo'>  quad2d (@plus, 1, 2, 3, 4, \"foo\", \"bar\")\n%!error <YA must be a real scalar> quad2d (@plus, 1, 2, 3i, 4)\n%!error <YA must be a real scalar> quad2d (@plus, 1, 2, [3 3], 4)\n%!error <YB must be a real scalar> quad2d (@plus, 1, 2, 3, 4i)\n%!error <YB must be a real scalar> quad2d (@plus, 1, 2, 3, [4 4])\n%!warning <Maximum number of> quad2d (@plus, 1, 2, 3, 4, \"MaxFunEvals\", 1);\n"
  },
  {
    "path": "scripts/general/quadgk.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} quadgk (@var{f}, @var{a}, @var{b})\n## @deftypefnx {} {@var{q} =} quadgk (@var{f}, @var{a}, @var{b}, @var{abstol})\n## @deftypefnx {} {@var{q} =} quadgk (@var{f}, @var{a}, @var{b}, @var{abstol}, @var{trace})\n## @deftypefnx {} {@var{q} =} quadgk (@var{f}, @var{a}, @var{b}, \"@var{prop}\", @var{val}, @dots{})\n## @deftypefnx {} {[@var{q}, @var{err}] =} quadgk (@dots{})\n##\n## Numerically evaluate the integral of @var{f} from @var{a} to @var{b}\n## using adaptive @nospell{Gauss-Kronrod} quadrature.\n##\n## @var{f} is a function handle, inline function, or string containing the name\n## of the function to evaluate.  The function @var{f} must be vectorized and\n## return a vector of output values when given a vector of input values (See\n## property @qcode{\"ArrayValued\"} for an exception to this rule).\n##\n## @var{a} and @var{b} are the lower and upper limits of integration.  Either\n## or both limits may be infinite or contain weak end singularities.  Variable\n## transformation will be used to treat any infinite intervals and weaken the\n## singularities.  For example:\n##\n## @example\n## quadgk (@@(x) 1 ./ (sqrt (x) .* (x + 1)), 0, Inf)\n## @end example\n##\n## @noindent\n## Note that the formulation of the integrand uses the element-by-element\n## operator @code{./} and all user functions to @code{quadgk} should do the\n## same.\n##\n## The optional argument @var{abstol} defines the absolute tolerance used to\n## stop the integration procedure.  The default value is 1e-10 (1e-5 for\n## single).\n##\n## The algorithm used by @code{quadgk} involves subdividing the integration\n## interval and evaluating each subinterval.  If @var{trace} is true then after\n## computing each of these partial integrals display: (1) the number of\n## subintervals at this step, (2) the current estimate of the error @var{err},\n## (3) the current estimate for the integral @var{q}.\n##\n## The behavior of the algorithm can be configured by passing arguments to\n## @code{quadgk} as pairs @qcode{\"@var{prop}\", @var{val}}.  Valid properties\n## are\n##\n## @table @code\n## @item AbsTol\n## Define the absolute error tolerance for the quadrature.  The default\n## absolute tolerance is 1e-10 (1e-5 for single).\n##\n## @item RelTol\n## Define the relative error tolerance for the quadrature.  The default\n## relative tolerance is 1e-6 (1e-4 for single).\n##\n## @item ArrayValued\n## When set to true, the function @var{f} produces an array output for a scalar\n## input.  The default is false which requires that @var{f} produce an output\n## that is the same size as the input.  For example,\n##\n## @example\n## quadgk (@@(x) x .^ (1:5), 0, 2, \"ArrayValued\", 1)\n## @end example\n##\n## @noindent\n## will integrate @code{[x.^1, x.^2, x.^3, x.^4, x.^5]} in one function call\n## rather than having to repeatedly define a single anonymous function and\n## use a normal invocation of @code{quadgk}.\n##\n## @item WayPoints\n## Specify points which will become endpoints for subintervals in the\n## algorithm which can result in significantly improved estimation of the error\n## in the integral, faster computation, or both.  It can be useful to specify\n## more subintervals around a region where the integrand is rapidly changing or\n## to flag locations where there is a discontinuity in the first derivative\n## of the function.  For example, the signum function has a discontinuity at\n## @code{x == 0} and by specifying a waypoint\n##\n## @example\n## quadgk (@@(x) sign (x), -0.5, 1, \"Waypoints\", [0])\n## @end example\n##\n## @noindent\n## the error bound is reduced from 4e-7 to 1e-13.\n##\n## If the function has @strong{singularities} within the region of integration\n## those should not be addressed with waypoints.  Instead, the overall integral\n## should be decomposed into a sum of several smaller integrals such that the\n## singularity occurs as one of the bounds of integration in the call to\n## @code{quadgk}.\n##\n## If any of the waypoints are complex then contour integration is performed as\n## documented below.\n##\n## @item MaxIntervalCount\n## @code{quadgk} initially subdivides the interval on which to perform the\n## quadrature into 10 intervals or, if WayPoints are given, at each waypoint.\n## Subintervals that have an unacceptable error are subdivided and\n## re-evaluated.  If the number of subintervals exceeds 650 subintervals at any\n## point then a poor convergence is signaled and the current estimate of the\n## integral is returned.  The property @qcode{\"MaxIntervalCount\"} can be used\n## to alter the number of subintervals that can exist before exiting.\n##\n## @item Trace\n## If logically true @code{quadgk} prints information on the convergence of the\n## quadrature at each iteration.\n## @end table\n##\n## If any of @var{a}, @var{b}, or @var{waypoints} is complex then the\n## quadrature is treated as a contour integral along a piecewise linear\n## path defined by\n## @code{[@var{a}, @var{waypoints}(1), @var{waypoints}(2), @dots{}, @var{b}]}.\n## In this case the integral is assumed to have no edge singularities.  For\n## example,\n##\n## @example\n## @group\n## quadgk (@@(z) log (z), 1+1i, 1+1i, \"WayPoints\",\n##         [-1+1i, -1-1i, +1-1i])\n## @end group\n## @end example\n##\n## @noindent\n## integrates @code{log (z)} along the square defined by\n## @code{[1+1i, -1+1i, -1-1i, +1-1i]}.\n##\n## The result of the integration is returned in @var{q}.\n##\n## @var{err} is an approximate bound on the error in the integral\n## @w{@code{abs (@var{q} - @var{I})}}, where @var{I} is the exact value of the\n## integral.  If the adaptive integration did not converge, the value of\n## @var{err} will be larger than the requested tolerance.  If only a single\n## output is requested then a warning will be emitted when the requested\n## tolerance is not met.  If the second output @var{err} is requested then no\n## warning is issued and it is the responsibility of the programmer to inspect\n## and determine whether the results are satisfactory.\n##\n## Reference: @nospell{L.F. Shampine},\n## \"Vectorized adaptive quadrature in @sc{matlab}\",\n## @cite{Journal of Computational and Applied Mathematics}, @w{Vol.@: 211},\n## @w{Issue 2}, @w{pp.@: 131}--140, Feb 2008.\n##\n## @seealso{quad, quadv, quadl, quadcc, trapz, dblquad, triplequad, integral,\n##          integral2, integral3}\n## @end deftypefn\n\nfunction [q, err] = quadgk (f, a, b, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  abstol = [];\n  reltol = [];\n  waypoints = [];\n  maxint = 650;\n  arrayvalued = false;\n  trace = false;\n\n  ## Parse options if present.\n  if (nargin > 3)\n    if (! ischar (varargin{1}))\n      if (! isempty (varargin{1}))\n        abstol = varargin{1};\n        reltol = 0;\n      endif\n      if (nargin > 4)\n        trace = varargin{2};\n      endif\n      if (nargin > 5)\n        error (\"quadgk: can not pass additional arguments to user function\");\n      endif\n    else\n      if (mod (nargin - 3, 2) != 0)\n        error (\"quadgk: property/value options must occur in pairs\");\n      endif\n\n      idx = 1;\n      while (idx < nargin - 3)\n        if (! ischar (varargin{idx}))\n          error (\"quadgk: property PROP must be a string\");\n        endif\n        prop = varargin{idx++};\n        switch (lower (prop))\n          case \"reltol\"\n            reltol = varargin{idx++};\n          case \"abstol\"\n            abstol = varargin{idx++};\n          case \"waypoints\"\n            waypoints = varargin{idx++}(:);\n          case \"maxintervalcount\"\n            maxint = varargin{idx++};\n          case \"arrayvalued\"\n            arrayvalued = varargin{idx++};\n          case \"trace\"\n            trace = varargin{idx++};\n          otherwise\n            error (\"quadgk: unknown property '%s'\", prop);\n        endswitch\n      endwhile\n    endif\n  endif\n\n  reverse = 1;\n  contour = iscomplex (a) || iscomplex (b) || iscomplex (waypoints);\n  if ((b < a) && ! contour)\n    ## Reverse integration\n    [b, a] = deal (a, b);\n    waypoints = sort (waypoints(waypoints > a & waypoints < b));\n    reverse = -1;\n  endif\n\n  issingle = (isa (a, \"single\") || isa (b, \"single\")\n              || isa (waypoints, \"single\"));\n\n  if (isempty (abstol))\n    abstol = ifelse (issingle, 1e-5, 1e-10);\n  elseif (! isscalar (abstol) || abstol < 0)\n    error (\"quadgk: ABSTOL must be a scalar >=0\");\n  endif\n\n  if (isempty (reltol))\n    reltol = ifelse (issingle, 1e-4, 1e-6);\n  elseif (! isscalar (reltol) || reltol < 0)\n    error (\"quadgk: RELTOL must be a scalar >=0\");\n  endif\n\n  ## FIXME: No validation of inputs MaxIntervalCount, Waypoints, ArrayValued,\n  ##        Trace.\n\n  ## Convert function given as a string to a function handle\n  if (ischar (f))\n    f = @(x) feval (f, x);\n  endif\n\n  ## Use variable substitution to weaken endpoint singularities and\n  ## to perform integration with endpoints at infinity.\n  ## No transform for contour integrals.\n  if (contour)\n    ## contour integral, no transform\n    subs = [a; waypoints; b];\n    h = sum (abs (diff (subs)));\n    trans = @(t) t;\n    ## Ensure f is always vectorized even if specified as, e.g., f = @(x) 1;\n    f = @(t) f (t) + 0*t;\n  elseif (isinf (a) && isinf (b))\n    ## Standard infinite to finite integral transformation.\n    ##   \\int_{-\\infinity_^\\infinity f(x) dx = \\int_-1^1 f (g(t)) g'(t) dt\n    ## where\n    ##   g(t)  = t / (1 - t^2)\n    ##   g'(t) =  (1 + t^2) / (1 - t^2) ^ 2\n    ## waypoint transform is then\n    ##   t =  (2 * g(t)) ./ (1 + sqrt(1 + 4 * g(t) .^ 2))\n    if (! isempty (waypoints))\n      trans = @(x) (2 * x) ./ (1 + sqrt (1 + 4 * x .^ 2));\n      subs = [-1; trans(waypoints); 1];\n    else\n      subs = linspace (-1, 1, 11)';\n    endif\n    h = 2;\n    trans = @(t) t ./ (1 - t.^2);\n    f = @(t) f (t ./ (1 - t .^ 2)) .* (1 + t .^ 2) ./ ((1 - t .^ 2) .^ 2);\n  elseif (isinf (a))\n    ## Formula defined in Shampine paper as two separate steps.\n    ## One to weaken singularity at finite end, then a second to transform to\n    ## a finite interval.  The singularity weakening transform is\n    ##   \\int_{-\\infinity}^b f(x) dx =\n    ##               - \\int_{-\\infinity}^0 f (b - t^2) 2 t dt\n    ## (note minus sign) and the finite interval transform is\n    ##   \\int_{-\\infinity}^0 f(b - t^2)  2 t dt =\n    ##                  \\int_{-1}^0 f (b - g(s) ^ 2) 2 g(s) g'(s) ds\n    ## where\n    ##   g(s)  = s / (1 + s)\n    ##   g'(s) = 1 / (1 + s) ^ 2\n    ## waypoint transform is then\n    ##   t = sqrt (b - x)\n    ##   s =  - t / (t + 1)\n    if (! isempty (waypoints))\n      tmp = sqrt (b - waypoints);\n      trans = @(x) - x ./ (x + 1);\n      subs = [-1; trans(tmp); 0];\n    else\n      subs = linspace (-1, 0, 11)';\n    endif\n    h = 1;\n    trans = @(t) b - (t ./ (1 + t)).^2;\n    f = @(s) - 2 * s .* f (b -  (s ./ (1 + s)) .^ 2) ./ ((1 + s) .^ 3);\n  elseif (isinf (b))\n    ## Formula defined in Shampine paper as two separate steps.\n    ## One to weaken singularity at finite end, then a second to transform to\n    ## a finite interval.  The singularity weakening transform is\n    ##   \\int_a^\\infinity f(x) dx = \\int_0^\\infinity f (a + t^2) 2 t dt\n    ## and the finite interval transform is\n    ##  \\int_0^\\infinity f(a + t^2)  2 t dt =\n    ##           \\int_0^1 f (a + g(s) ^ 2) 2 g(s) g'(s) ds\n    ## where\n    ##   g(s)  = s / (1 - s)\n    ##   g'(s) = 1 / (1 - s) ^ 2\n    ## waypoint transform is then\n    ##   t = sqrt (x - a)\n    ##   s = t / (t + 1)\n    if (! isempty (waypoints))\n      tmp = sqrt (waypoints - a);\n      trans = @(x) x ./ (x + 1);\n      subs = [0; trans(tmp); 1];\n    else\n      subs = linspace (0, 1, 11)';\n    endif\n    h = 1;\n    trans = @(t) a + (t ./ (1 - t)).^2;\n    f = @(s) 2 * s .* f (a +  (s ./ (1 - s)) .^ 2) ./ ((1 - s) .^ 3);\n  else\n    ## Davis, Rabinowitz, \"Methods of Numerical Integration\" p441 2ed.\n    ## Presented in section 5 of the Shampine paper as\n    ##   g(t) = ((b - a) / 2) * (t / 2 * (3 - t^2)) + (b + a) / 2\n    ##   g'(t) = ((b-a)/4) * (3 - 3t^2);\n    ## waypoint transform can then be found by solving for t with\n    ## Maxima (solve (c + 3*t -  3^3, t);).  This gives 3 roots, two of\n    ## which are complex for values between a and b and so can be ignored.\n    ## The third is\n    ##  c = (-4*x + 2*(b+a)) / (b-a);\n    ##  k = ((sqrt(c^2 - 4) + c)/2)^(1/3);\n    ##  t = (sqrt(3)* 1i * (1 - k^2) - (1 + k^2)) / 2 / k;\n    if (! isempty (waypoints))\n      trans = @__quadgk_finite_waypoint__;\n      subs = [-1; trans(waypoints, a, b); 1];\n    else\n      subs = linspace (-1, 1, 11)';\n    endif\n    h = 2;\n    trans = @(t) ((b - a) ./ 4) * t .* (3 - t.^2) + (b + a) ./ 2;\n    f = @(t) f((b - a) ./ 4 .* t .* (3 - t.^2) + (b + a) ./ 2) .* ...\n         3 .* (b - a) ./ 4 .* (1 - t.^2);\n  endif\n\n  ## Split interval into at least 10 subinterval with a 15 point\n  ## Gauss-Kronrod rule giving a minimum of 150 function evaluations.\n  while (numel (subs) < 11)\n    subs = [subs.' ; subs(1:end-1).' + diff(subs.') ./ 2, NaN](:)(1:end-1);\n  endwhile\n  subs = [subs(1:end-1), subs(2:end)];\n\n  warn_id = \"Octave:quadgk:warning-termination\";\n\n  if (! arrayvalued)\n    ## Initial evaluation of the integrand on the subintervals.\n    [q_subs, q_errs] = __quadgk_eval__ (f, subs, trans);\n    q0 = sum (q_subs);\n    err0 = sum (q_errs);\n\n    first = true;\n    while (true)\n      ## Quit if any evaluations are not finite (Inf or NaN).\n      if (any (! isfinite (q_subs)))\n        warning (warn_id, \"quadgk: non-finite integrand encountered\");\n        q = q0;\n        err = err0;\n        break;\n      endif\n\n      tol = max (abstol, reltol .* abs (q0));\n\n      ## If the global error estimate is met then exit.\n      if (err0 <= tol)\n        q = q0;\n        err = err0;\n        break;\n      endif\n\n      ## Accept the subintervals that meet the convergence criteria.\n      idx = find (abs (q_errs) < tol .* abs (diff (subs, 1, 2)) ./ h);\n      if (first)\n        q = sum (q_subs(idx));\n        err = sum (q_errs(idx));\n        first = false;\n      else\n        q0 = q + sum (q_subs);\n        err0 = err + sum (q_errs);\n        q += sum (q_subs(idx));\n        err += sum (q_errs(idx));\n      endif\n      subs(idx,:) = [];\n\n      ## If no remaining subintervals then exit.\n      if (isempty (subs))\n        break;\n      endif\n\n      if (trace)\n        disp ([rows(subs), err, q0]);\n      endif\n\n      ## Split remaining subintervals in two\n      mid = (subs(:,1) + subs(:,2)) ./ 2;\n      subs = [subs(:,1), mid; mid, subs(:,2)];\n\n      ## If the maximum subinterval count is met, then\n      ## accept remaining subinterval and exit.\n      if (rows (subs) > maxint)\n        warning (warn_id, \"quadgk: maximum interval count (%d) exceeded\", maxint);\n        q += sum (q_subs);\n        err += sum (q_errs);\n        break;\n      endif\n\n      ## Evaluation of the integrand on the remaining subintervals\n      [q_subs, q_errs] = __quadgk_eval__ (f, subs, trans);\n    endwhile\n\n    if (nargout < 2 && err > max (abstol, reltol * abs (q)))\n      warning (warn_id,\n               \"quadgk: Error tolerance not met.  Estimated error %g\", err);\n    endif\n\n    ## Reverse integral if necessary.\n    q = reverse * q;\n\n  else\n    ## f is array-valued\n    sz = size (f (subs(1)));\n\n    ## Initial evaluation of the integrand on the subintervals\n    [q_subs, q_errs] = __quadgk_eval_array__ (f, subs, trans, prod (sz));\n    q0 = sum (q_subs, 1);\n    err0 = sum (q_errs, 1);\n\n    first = true;\n    while (true)\n      ## Quit if any evaluations are not finite (Inf or NaN).\n      if (any (! isfinite (q_subs)(:)))\n        warning (warn_id, \"quadgk: non-finite integrand encountered\");\n        q = q0;\n        err = err0;\n        break;\n      endif\n\n      tol = max (abstol, reltol .* abs (q0));\n\n      ## If the global error estimate is met then exit\n      if (err0 <= tol)\n        q = q0;\n        err = err0;\n        break;\n      endif\n\n      ## Accept subintervals that meet the convergence criteria in all entries.\n      idx = find (all (abs (q_errs) < tol .* abs (diff (subs, 1, 2)) ./ h, 2));\n      if (first)\n        q = sum (q_subs(idx,:), 1);\n        err = sum (q_errs(idx,:), 1);\n        first = false;\n      else\n        q0 = q + sum (q_subs, 1);\n        err0 = err + sum (q_errs, 1);\n        q += sum (q_subs(idx,:), 1);\n        err += sum (q_errs(idx,:), 1);\n      endif\n      subs(idx,:) = [];\n\n      ## If no remaining subintervals exit\n      if (isempty (subs))\n        break;\n      endif\n\n      if (trace)\n        disp ([rows(subs), err(1, 1), q0(1, 1)]); # print only first entry\n      endif\n\n      ## Split remaining subintervals in two\n      mid = (subs(:,1) + subs(:,2)) ./ 2;\n      subs = [subs(:,1), mid; mid, subs(:,2)];\n\n      ## If the maximum subinterval count is met accept remaining subinterval\n      ## and exit\n      if (rows (subs) > maxint)\n        warning (warn_id, \"quadgk: maximum interval count (%d) exceeded\", maxint);\n        q += sum (q_subs, 1);\n        err += sum (q_errs, 1);\n        break;\n      endif\n\n      ## Evaluation of the integrand on the remaining subintervals\n      [q_subs, q_errs] = __quadgk_eval_array__ (f, subs, trans, prod (sz));\n    endwhile\n\n    i = find (err > max (abstol, reltol * abs (q)), 1);\n    if (nargout < 2 && length (i) > 0)\n      ## like ind2sub, only as vector.\n      j = mod (floor ((i-1)./cumprod ([1 sz(1:end-1)])),sz)+1;\n      s = [\"(\" sprintf(\"%d,\",j)(1:end-1) \")\"];\n      warning (warn_id,\n               \"quadgk: Error tolerance not met.  First entry at index %s with estimated error %g\", s, err(i));\n    endif\n\n    q = reverse * reshape (q, sz);\n    err = reshape (err, sz);\n  endif\n\nendfunction\n\nfunction [q, err] = __quadgk_eval__ (f, subs, trans)\n\n  ## A (15,7) point pair of Gauss-Kronrod quadrature rules.\n  ## The abscissa and weights are copied directly from dqk15w.f from quadpack.\n\n  persistent abscissa = [-0.9914553711208126e+00, -0.9491079123427585e+00, ...\n                         -0.8648644233597691e+00, -0.7415311855993944e+00, ...\n                         -0.5860872354676911e+00, -0.4058451513773972e+00, ...\n                         -0.2077849550078985e+00,  0.0000000000000000e+00, ...\n                          0.2077849550078985e+00,  0.4058451513773972e+00, ...\n                          0.5860872354676911e+00,  0.7415311855993944e+00, ...\n                          0.8648644233597691e+00,  0.9491079123427585e+00, ...\n                          0.9914553711208126e+00];\n\n  persistent weights15 = ...\n      diag ([0.2293532201052922e-01,  0.6309209262997855e-01, ...\n             0.1047900103222502e+00,  0.1406532597155259e+00, ...\n             0.1690047266392679e+00,  0.1903505780647854e+00, ...\n             0.2044329400752989e+00,  0.2094821410847278e+00, ...\n             0.2044329400752989e+00,  0.1903505780647854e+00, ...\n             0.1690047266392679e+00,  0.1406532597155259e+00, ...\n             0.1047900103222502e+00,  0.6309209262997855e-01, ...\n             0.2293532201052922e-01]);\n\n  persistent weights7 = ...\n      diag ([0.1294849661688697e+00,  0.2797053914892767e+00, ...\n             0.3818300505051889e+00,  0.4179591836734694e+00, ...\n             0.3818300505051889e+00,  0.2797053914892767e+00, ...\n             0.1294849661688697e+00]);\n\n  halfwidth = diff (subs, 1, 2) ./ 2;\n  center = sum (subs, 2) ./ 2;\n  t = (halfwidth * abscissa) + center;\n  x = trans ([t(:,1), t(:,end)]);\n\n  y = reshape (f (t(:)), size (t));\n\n  ## This is faster than using bsxfun as the * operator can use a\n  ## single BLAS call, rather than rows (sub) calls to the @times function.\n  q = sum (y * weights15, 2) .* halfwidth;\n  err = abs (sum (y(:,2:2:end) * weights7, 2) .* halfwidth - q);\n\nendfunction\n\nfunction [q, err] = __quadgk_eval_array__ (f, subs, trans, nel)\n\n  ## A (15,7) point pair of Gauss-Kronrod quadrature rules.\n  ## The abscissa and weights are copied directly from dqk15w.f from quadpack.\n\n  persistent abscissa = [-0.9914553711208126e+00, -0.9491079123427585e+00, ...\n                         -0.8648644233597691e+00, -0.7415311855993944e+00, ...\n                         -0.5860872354676911e+00, -0.4058451513773972e+00, ...\n                         -0.2077849550078985e+00,  0.0000000000000000e+00, ...\n                          0.2077849550078985e+00,  0.4058451513773972e+00, ...\n                          0.5860872354676911e+00,  0.7415311855993944e+00, ...\n                          0.8648644233597691e+00,  0.9491079123427585e+00, ...\n                          0.9914553711208126e+00];\n\n  persistent weights15 = ...\n            [0.2293532201052922e-01,  0.6309209262997855e-01, ...\n             0.1047900103222502e+00,  0.1406532597155259e+00, ...\n             0.1690047266392679e+00,  0.1903505780647854e+00, ...\n             0.2044329400752989e+00,  0.2094821410847278e+00, ...\n             0.2044329400752989e+00,  0.1903505780647854e+00, ...\n             0.1690047266392679e+00,  0.1406532597155259e+00, ...\n             0.1047900103222502e+00,  0.6309209262997855e-01, ...\n             0.2293532201052922e-01];\n\n  persistent weights7 = ...\n            [0.1294849661688697e+00,  0.2797053914892767e+00, ...\n             0.3818300505051889e+00,  0.4179591836734694e+00, ...\n             0.3818300505051889e+00,  0.2797053914892767e+00, ...\n             0.1294849661688697e+00];\n\n  halfwidth = diff (subs, 1, 2) ./ 2;\n  center = sum (subs, 2) ./ 2;\n  t = (halfwidth * abscissa) + center;\n  x = trans ([t(:,1), t(:,end)]);\n\n  y = zeros (nel, columns (t), rows (t));\n  for i = 1:rows (t)\n    for j = 1:columns (t)\n      y(:,j,i) = f (t(i,j))(:);\n    endfor\n  endfor\n  y = permute (y, [2 3 1]);\n\n  q = reshape (weights15 * y(:,:), [rows(t), nel]) .* halfwidth;\n  err = abs (reshape (weights7 * y(2:2:end,:), rows (t), nel) .* halfwidth - q);\n\nendfunction\n\nfunction t = __quadgk_finite_waypoint__ (x, a, b)\n  c = (-4 .* x + 2.* (b + a)) ./ (b - a);\n  k = ((sqrt (c .^ 2 - 4) + c) ./ 2) .^ (1/3);\n  t = real ((sqrt (3) .* 1i * (1 - k .^ 2) - (1 + k .^ 2)) ./ 2 ./ k);\nendfunction\n\n\n%!assert (quadgk (@sin,-pi,pi), 0, 1e-10)\n%!test\n%! warning (\"off\", \"Octave:legacy-function\", \"local\");\n%! assert (quadgk (inline (\"sin\"), -pi, pi), 0, 1e-10);\n%!assert (quadgk (\"sin\",-pi,pi), 0, 1e-10)\n%!assert (quadgk (@sin,-pi,pi, \"WayPoints\", 0, \"MaxIntervalCount\", 100,\n%!                \"RelTol\", 1e-3, \"AbsTol\", 1e-6, \"trace\", false), 0, 1e-6)\n%!assert (quadgk (@sin,-pi,pi, 1e-6, false), 0, 1e-6)\n%!assert <*51867> (quadgk (@(x) x, 0, 0), 0, 0)\n\n%!assert (quadgk (@sin,-pi,0), -2, 1e-10)\n%!assert (quadgk (@sin,0,pi), 2, 1e-10)\n%!assert (quadgk (@(x) 1./sqrt (x),0,1), 2, 1e-10)\n%!assert (quadgk (@(x) abs (1 - x.^2),0,2, \"Waypoints\", 1), 2, 1e-10)\n%!assert (quadgk (@(x) 1./(sqrt (x) .* (x+1)),0,Inf), pi, 1e-10)\n%!assert <*57614> (quadgk (@(z) exp (z)./z, 1, 1,\n%!                        \"Waypoints\", [1+i, -1+i, -1-i, 1-i]),\n%!                 complex (0, 2*pi), 1e-10)\n%!assert <*57614> (quadgk (@(z) exp (z)./z, 1, 1,\n%!                        \"Waypoints\", [1-i, -1-i, -1+i, 1+i]),\n%!                 complex (0, -2*pi), 1e-10)\n%!assert (quadgk (@(z) log (z),1+1i,1+1i, \"WayPoints\", [1-1i, -1,-1i, -1+1i]),\n%!        complex (0, pi), 1e-10)\n%!assert (quadgk (@(x) exp (-x .^ 2),-Inf,Inf), sqrt (pi), -1e-6)\n%!assert (quadgk (@(x) exp (-x .^ 2),-Inf,0), sqrt (pi)/2, -1e-6)\n%!test\n%! f = @(x) x .^ 5 .* exp (-x) .* sin (x);\n%! assert (quadgk (f, 0, Inf, \"RelTol\", 1e-8, \"AbsTol\", 1e-12), -15, -1e-8);\n\n## Test vector-valued functions\n%!assert (quadgk (@(x) [(sin (x)), (sin (2 * x))], 0, pi, \"arrayvalued\", 1),\n%!        [2, 0], 1e-6)\n\n## Test matrix-valued functions\n%!assert (quadgk (@(x) [ x,x,x; x,1./sqrt(x),x; x,x,x ], 0, 1, \"arrayvalued\",1),\n%!        [0.5,0.5,0.5; 0.5,2,0.5; 0.5,0.5,0.5], 15*1e-6);\n\n## Bug #62412\n%!warning <Error tolerance not met>\n%! f = @(t) -1 ./ t.^1.1;\n%! quadgk (f, 1, Inf);\n\n## Test input validation\n%!error quadgk (@sin)\n%!error quadgk (@sin, 0)\n%!error <can not pass additional arguments> quadgk (@sin, 0, 1, 1e-6, true, 4)\n%!error <options must occur in pairs> quadgk (@sin, 0, 1, \"DummyArg\")\n%!error <PROP must be a string> quadgk (@sin, 0, 1, \"AbsTol\", 1e-6, 2, 3)\n%!error <unknown property 'foo'> quadgk (@sin, 0, 1, \"foo\", 3)\n%!error <ABSTOL must be a scalar> quadgk (@sin, 0, 1, ones (2,2))\n%!error <ABSTOL must be a scalar .=0> quadgk (@sin, 0, 1, -1)\n%!error <RELTOL must be a scalar> quadgk (@sin, 0, 1, \"RelTol\", ones (2,2))\n%!error <RELTOL must be a scalar> quadgk (@sin, 0, 1, \"RelTol\", -1)\n"
  },
  {
    "path": "scripts/general/quadl.m",
    "content": "########################################################################\n##\n## Copyright (C) 1998-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} quadl (@var{f}, @var{a}, @var{b})\n## @deftypefnx {} {@var{q} =} quadl (@var{f}, @var{a}, @var{b}, @var{tol})\n## @deftypefnx {} {@var{q} =} quadl (@var{f}, @var{a}, @var{b}, @var{tol}, @var{trace})\n## @deftypefnx {} {@var{q} =} quadl (@var{f}, @var{a}, @var{b}, @var{tol}, @var{trace}, @var{p1}, @var{p2}, @dots{})\n## @deftypefnx {} {[@var{q}, @var{nfev}] =} quadl (@dots{})\n##\n## Numerically evaluate the integral of @var{f} from @var{a} to @var{b} using\n## an adaptive @nospell{Lobatto} rule.\n##\n## @var{f} is a function handle, inline function, or string containing the name\n## of the function to evaluate.  The function @var{f} must be vectorized and\n## return a vector of output values when given a vector of input values.\n##\n## @var{a} and @var{b} are the lower and upper limits of integration.  Both\n## limits must be finite.\n##\n## The optional argument @var{tol} defines the absolute tolerance with which\n## to perform the integration.  The default value is 1e-6.\n##\n## The algorithm used by @code{quadl} involves recursively subdividing the\n## integration interval.  If @var{trace} is defined then for each subinterval\n## display: (1) the total number of function evaluations, (2) the left end of\n## the subinterval, (3) the length of the subinterval, (4) the approximation of\n## the integral over the subinterval.\n##\n## Additional arguments @var{p1}, etc., are passed directly to the function\n## @var{f}.  To use default values for @var{tol} and @var{trace}, one may pass\n## empty matrices ([]).\n##\n## The result of the integration is returned in @var{q}.\n##\n## The optional output @var{nfev} indicates the total number of function\n## evaluations performed.\n##\n## Reference: @nospell{W. Gander and W. Gautschi}, @cite{Adaptive Quadrature -\n## Revisited}, BIT @w{Vol.@: 40}, @w{No.@: 1}, March 2000, @w{pp.@: 84}--101.\n## @url{https://www.inf.ethz.ch/personal/gander/}\n## @seealso{quad, quadv, quadgk, quadcc, trapz, dblquad, triplequad, integral,\n##          integral2, integral3}\n## @end deftypefn\n\n## Original Author: Walter Gautschi\n## Date: 08/03/98\n## Reference: Gander, Computermathematik, Birkhaeuser, 1992.\n\n## 2003-08-05 Shai Ayal\n##   * permission from author to release as GPL\n\nfunction [q, nfev] = quadl (f, a, b, tol = [], trace = false, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  if (isa (a, \"single\") || isa (b, \"single\"))\n    eps = eps (\"single\");\n  else\n    eps = eps (\"double\");\n  endif\n  if (isempty (tol))\n    tol = 1e-6;\n  elseif (! isscalar (tol) || tol < 0)\n    error (\"quadl: TOL must be a scalar >=0\");\n  elseif (tol < eps)\n    warning (\"quadl: TOL specified is smaller than machine precision, using %g\",\n                                                                           tol);\n    tol = eps;\n  endif\n  if (isempty (trace))\n    trace = false;\n  endif\n\n  y = feval (f, [a, b], varargin{:});\n  nfev = 1;\n\n  fa = y(1);\n  fb = y(2);\n\n  h = b - a;\n\n  [q, nfev, hmin] = adaptlobstp (f, a, b, fa, fb, Inf, nfev, abs (h),\n                                 tol, trace, varargin{:});\n\n  if (nfev > 10_000)\n    warning (\"quadl: maximum iteration count reached -- possible singular integral\");\n  elseif (any (! isfinite (q(:))))\n    warning (\"quadl: infinite or NaN function evaluations were returned\");\n  elseif (hmin < (b - a) * eps)\n    warning (\"quadl: minimum step size reached -- possible singular integral\");\n  endif\n\nendfunction\n\nfunction [q, nfev, hmin] = adaptlobstp (f, a, b, fa, fb, q0, nfev, hmin,\n                                        tol, trace, varargin)\n\n  persistent alpha = sqrt (2/3);\n  persistent beta = 1 / sqrt (5);\n\n  if (nfev > 10_000)\n    q = q0;\n    return;\n  endif\n\n  h = (b - a) / 2;\n  m = (a + b) / 2;\n  mll = m - alpha*h;\n  ml  = m - beta*h;\n  mr  = m + beta*h;\n  mrr = m + alpha*h;\n  x = [mll, ml, m, mr, mrr];\n  y = feval (f, x, varargin{:});\n  nfev += 1;\n  fmll = y(1);\n  fml  = y(2);\n  fm   = y(3);\n  fmr  = y(4);\n  fmrr = y(5);\n  i2 = (h/6)*(fa + fb + 5*(fml+fmr));\n  i1 = (h/1470)*(77*(fa+fb) + 432*(fmll+fmrr) + 625*(fml+fmr) + 672*fm);\n\n  if (abs (b - a) < hmin)\n    hmin = abs (b - a);\n  endif\n\n  if (trace)\n    disp ([nfev, a, b-a, i1]);\n  endif\n\n  ## Force at least one adaptive step (nfev > 2 test).\n  if ((abs (i1-i2) < tol || mll <= a || b <= mrr) && nfev > 2)\n    q = i1;\n  else\n    q = zeros (6, 1, class (x));\n    [q(1), nfev, hmin] = adaptlobstp (f, a  , mll, fa  , fmll, q0/6, nfev, hmin,\n                                      tol, trace, varargin{:});\n    [q(2), nfev, hmin] = adaptlobstp (f, mll, ml , fmll, fml , q0/6, nfev, hmin,\n                                      tol, trace, varargin{:});\n    [q(3), nfev, hmin] = adaptlobstp (f, ml , m  , fml , fm  , q0/6, nfev, hmin,\n                                      tol, trace, varargin{:});\n    [q(4), nfev, hmin] = adaptlobstp (f, m  , mr , fm  , fmr , q0/6, nfev, hmin,\n                                      tol, trace, varargin{:});\n    [q(5), nfev, hmin] = adaptlobstp (f, mr , mrr, fmr , fmrr, q0/6, nfev, hmin,\n                                      tol, trace, varargin{:});\n    [q(6), nfev, hmin] = adaptlobstp (f, mrr, b  , fmrr, fb  , q0/6, nfev, hmin,\n                                      tol, trace, varargin{:});\n    q = sum (q);\n  endif\n\nendfunction\n\n\n## basic functionality\n%!assert (quadl (@(x) sin (x), 0, pi), 2, 1e-6)\n\n## the values here are very high so it may be unavoidable that this fails\n%!assert (quadl (@(x) sin (3*x).*cosh (x).*sinh (x),10,15, 1e-3),\n%!        2.588424538641647e+10, 1e-3)\n\n## extra parameters\n%!assert (quadl (@(x,a,b) sin (a + b*x), 0, 1, [], [], 2, 3),\n%!        cos (2)/3 - cos (5)/3, 1e-6)\n\n## test different tolerances.\n%!test\n%! [q, nfev1] = quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.5, []);\n%! assert (q, (60 + sin (4) - sin (64))/12, 0.5);\n%! [q, nfev2] = quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.1, []);\n%! assert (q, (60 + sin (4) - sin (64))/12, 0.1);\n%! assert (nfev2 > nfev1);\n\n%!test  # test single input/output\n%! assert (class (quadl (@sin, 0, 1)), \"double\");\n%! assert (class (quadl (@sin, single (0), 1)), \"single\");\n%! assert (class (quadl (@sin, 0, single (1))), \"single\");\n\n## Test input validation\n%!error <Invalid call> quadl ()\n%!error <Invalid call> quadl (@sin)\n%!error <Invalid call> quadl (@sin,1)\n%!error <TOL must be a scalar> quadl (@sin,0,1, ones (2,2))\n%!error <TOL must be .* .=0> quadl (@sin,0,1, -1)\n"
  },
  {
    "path": "scripts/general/quadv.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} quadv (@var{f}, @var{a}, @var{b})\n## @deftypefnx {} {@var{q} =} quadv (@var{f}, @var{a}, @var{b}, @var{tol})\n## @deftypefnx {} {@var{q} =} quadv (@var{f}, @var{a}, @var{b}, @var{tol}, @var{trace})\n## @deftypefnx {} {@var{q} =} quadv (@var{f}, @var{a}, @var{b}, @var{tol}, @var{trace}, @var{p1}, @var{p2}, @dots{})\n## @deftypefnx {} {[@var{q}, @var{nfev}] =} quadv (@dots{})\n##\n## Numerically evaluate the integral of @var{f} from @var{a} to @var{b}\n## using an adaptive Simpson's rule.\n##\n## @var{f} is a function handle, inline function, or string containing the name\n## of the function to evaluate.  @code{quadv} is a vectorized version of\n## @code{quad} and the function defined by @var{f} must accept a scalar or\n## vector as input and return a scalar, vector, or array as output.\n##\n## @var{a} and @var{b} are the lower and upper limits of integration.  Both\n## limits must be finite.\n##\n## The optional argument @var{tol} defines the absolute tolerance used to stop\n## the adaptation procedure.  The default value is 1e-6.\n##\n## The algorithm used by @code{quadv} involves recursively subdividing the\n## integration interval and applying Simpson's rule on each subinterval.\n## If @var{trace} is true then after computing each of these partial\n## integrals display: (1) the total number of function evaluations,\n## (2) the left end of the subinterval, (3) the length of the subinterval,\n## (4) the approximation of the integral over the subinterval.\n##\n## Additional arguments @var{p1}, etc., are passed directly to the function\n## @var{f}.  To use default values for @var{tol} and @var{trace}, one may pass\n## empty matrices ([]).\n##\n## The result of the integration is returned in @var{q}.\n##\n## The optional output @var{nfev} indicates the total number of function\n## evaluations performed.\n##\n## Note: @code{quadv} is written in Octave's scripting language and can be\n## used recursively in @code{dblquad} and @code{triplequad}, unlike the\n## @code{quad} function.\n## @seealso{quad, quadl, quadgk, quadcc, trapz, dblquad, triplequad, integral,\n##          integral2, integral3}\n## @end deftypefn\n\n## Algorithm: See https://en.wikipedia.org/wiki/Adaptive_Simpson%27s_method\n## for basic explanation.  See NOTEs and FIXME for Octave modifications.\n\nfunction [q, nfev] = quadv (f, a, b, tol = [], trace = false, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  if (isa (a, \"single\") || isa (b, \"single\"))\n    eps = eps (\"single\");\n  else\n    eps = eps (\"double\");\n  endif\n  if (isempty (tol))\n    tol = 1e-6;\n  elseif (! isscalar (tol) || tol < 0)\n    error (\"quadv: TOL must be a scalar >=0\");\n  endif\n\n  if (trace)\n    ## Print column headers once above trace display.\n    printf (\"  nfev          a            (b - a)         q_interval\\n\");\n  endif\n\n  ## NOTE: Split the interval into 3 parts which avoids problems with periodic\n  ## functions when a, b, and (a + b)/2 fall on boundaries such as 0, 2*pi.\n  ## For compatibility with Matlab, split in to two equal size regions on the\n  ## left and right, and one larger central region.\n  alpha = 0.27158;   # factor for region 1 & region 3 size (~27%)\n  b1 = a + alpha * (b - a);\n  b2 = b - alpha * (b - a);\n  c1 = (a + b1) / 2;\n  c2 = (a + b)  / 2;\n  c3 = (b2 + b) / 2;\n\n  fa  = feval (f, a,  varargin{:});\n  fc1 = feval (f, c1, varargin{:});\n  fb1 = feval (f, b1, varargin{:});\n  fc2 = feval (f, c2, varargin{:});\n  fb2 = feval (f, b2, varargin{:});\n  fc3 = feval (f, c3, varargin{:});\n  fb  = feval (f, b,  varargin{:});\n  nfev = 7;\n\n  ## NOTE: If there are edge singularities, move edge point by eps*(b-a) as\n  ## discussed in Shampine paper used to implement quadgk.\n  if (any (isinf (fa(:))))\n    fa = feval (f, a + eps * (b-a), varargin{:});\n    nfev++;\n  endif\n  if (any (isinf (fb(:))))\n    fb = feval (f, b - eps * (b-a), varargin{:});\n    nfev++;\n  endif\n\n  ## Region 1\n  h = (b1 - a);\n  q1 = h / 6 * (fa + 4*fc1 + fb1);\n\n  [q1, nfev, hmin1] = simpsonstp (f, a, b1, c1, fa, fb1, fc1, q1, tol,\n                                  nfev, abs (h), trace, varargin{:});\n\n  ## Region 2\n  h = (b2 - b1);\n  q2 = h / 6 * (fb1 + 4*fc2 + fb2);\n\n  [q2, nfev, hmin2] = simpsonstp (f, b1, b2, c2, fb1, fb2, fc2, q2, tol,\n                                  nfev, abs (h), trace, varargin{:});\n\n  ## Region 3\n  h = (b - b2);\n  q3 = h / 6 * (fb2 + 4*fc3 + fb);\n\n  [q3, nfev, hmin3] = simpsonstp (f, b2, b, c3, fb2, fb, fc3, q3, tol,\n                                  nfev, abs (h), trace, varargin{:});\n\n  ## Total integral over all 3 regions and verify results\n  q = q1 + q2 + q3;\n\n  hmin = min ([hmin1, hmin2, hmin3]);\n\n  if (nfev > 10_000)\n    warning (\"quadv: maximum iteration count reached -- possible singular integral\");\n  elseif (any (! isfinite (q(:))))\n    warning (\"quadv: infinite or NaN function evaluations were returned\");\n  elseif (hmin < (b - a) * eps)\n    warning (\"quadv: minimum step size reached -- possible singular integral\");\n  endif\n\nendfunction\n\nfunction [q, nfev, hmin] = simpsonstp (f, a, b, c, fa, fb, fc, q0, tol,\n                                       nfev, hmin, trace, varargin)\n\n  if (nfev > 10_000)   # stop endless recursion\n    q = q0;\n    return;\n  endif\n\n  d = (a + c) / 2;\n  e = (c + b) / 2;\n  fd = feval (f, d, varargin{:});\n  fe = feval (f, e, varargin{:});\n  nfev += 2;\n  q1 = (c - a) / 6 * (fa + 4*fd + fc);\n  q2 = (b - c) / 6 * (fc + 4*fe + fb);\n  q = q1 + q2;\n\n  if (abs (a - c) < hmin)\n    hmin = abs (a - c);\n  endif\n\n  delta = q - q0;   # error term between new estimate and old estimate\n\n  if (trace)\n    printf (\"%5d   %#14.11g   %16.10e   %-16.11g\\n\",\n            nfev,  a,         b-a,      q + delta/15);\n  endif\n\n  ## NOTE: Not vectorizing q-q0 in the norm provides a more rigid criterion\n  ##       for matrix-valued functions.\n  if (norm (delta, Inf) > 15*tol)\n    ## FIXME: To keep sum of sub-interval integrands within overall tolerance\n    ## each bisection interval should use tol/2.  However, Matlab does not\n    ## do this, and it would also profoundly increase the number of function\n    ## evaluations required.\n    [q1, nfev, hmin] = simpsonstp (f, a, c, d, fa, fc, fd, q1, tol,\n                                   nfev, hmin, trace, varargin{:});\n    [q2, nfev, hmin] = simpsonstp (f, c, b, e, fc, fb, fe, q2, tol,\n                                   nfev, hmin, trace, varargin{:});\n    q = q1 + q2;\n  else\n    q += delta / 15;   # NOTE: Richardson extrapolation correction\n  endif\n\nendfunction\n\n\n%!assert (quadv (@sin, 0, 2*pi), 0, 1e-6)\n%!assert (quadv (@sin, 0, pi), 2, 1e-6)\n\n## Test weak singularities at the edge\n%!assert (quadv (@(x) 1 ./ sqrt (x), 0, 1), 2, 15*1e-6)\n\n## Test vector-valued functions\n%!assert (quadv (@(x) [(sin (x)), (sin (2 * x))], 0, pi), [2, 0], 1e-6)\n\n## Test matrix-valued functions\n%!assert (quadv (@(x) [ x,x,x; x,1./sqrt(x),x; x,x,x ], 0, 1),\n%!        [0.5,0.5,0.5; 0.5,2,0.5; 0.5,0.5,0.5], 15*1e-6);\n\n## Test periodic function\n%!assert <*57603> (quadv (@(t) sin (t) .^ 2, 0, 8*pi), 4*pi, 1e-6)\n\n## Test input validation\n%!error <Invalid call> quadv ()\n%!error <Invalid call> quadv (@sin)\n%!error <Invalid call> quadv (@sin,1)\n%!error <TOL must be a scalar> quadv (@sin,0,1, ones (2,2))\n%!error <TOL must be .* .=0> quadv (@sin,0,1, -1)\n"
  },
  {
    "path": "scripts/general/rad2deg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{deg} =} rad2deg (@var{rad})\n##\n## Convert radians to degrees.\n##\n## The input @var{rad} must be a scalar, vector, or N-dimensional array of\n## double or single floating point values.  @var{rad} may be complex in which\n## case the real and imaginary components are converted separately.\n##\n## The output @var{deg} is the same size and shape as @var{rad} with radians\n## converted to degrees using the conversion constant @code{180/pi}.\n##\n## Example:\n##\n## @example\n## @group\n## rad2deg ([0, pi/2, pi, 3/2*pi, 2*pi])\n##   @xresult{}  0    90   180   270   360\n## @end group\n## @end example\n## @seealso{deg2rad}\n## @end deftypefn\n\nfunction deg = rad2deg (rad)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isfloat (rad))\n    error (\"rad2deg: RAD must be a floating point class (double or single)\");\n  endif\n\n  deg = rad * (180/pi);\n\nendfunction\n\n\n%!assert (rad2deg (0), 0)\n%!assert (rad2deg (pi/2), 90)\n%!assert (rad2deg (pi), 180)\n%!assert (rad2deg (pi*[0, 1/2, 1, 3/2, 2]), [0, 90, 180, 270, 360])\n\n## Test input validation\n%!error <Invalid call> rad2deg ()\n%!error <RAD must be a floating point class> rad2deg (uint8 (1))\n%!error <RAD must be a floating point class> rad2deg (\"A\")\n"
  },
  {
    "path": "scripts/general/rat.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{s} =} rat (@var{x})\n## @deftypefnx {} {@var{s} =} rat (@var{x}, @var{tol})\n## @deftypefnx {} {[@var{n}, @var{d}] =} rat (@dots{})\n##\n## Find a rational approximation of @var{x} to within the tolerance defined by\n## @var{tol}.\n##\n## If unspecified, the default tolerance is @code{1e-6 * norm (@var{x}(:), 1)}.\n##\n## When called with one output argument, return a string containing a\n## continued fraction expansion (multiple terms).\n##\n## When called with two output arguments, return numeric matrices for the\n## numerator and denominator of a fractional representation of @var{x} such\n## that @code{@var{x} = @var{n} ./ @var{d}}.\n##\n## For example:\n##\n## @example\n## @group\n## s = rat (pi)\n## @xresult{} s = 3 + 1/(7 + 1/16)\n##\n## [n, d] = rat (pi)\n## @xresult{} n =  355\n## @xresult{} d =  113\n##\n## n / d - pi\n## @xresult{} 2.6676e-07\n## @end group\n## @end example\n##\n## Complex inputs are similar:\n##\n## @example\n## @group\n## s = rat (0.5 + i * pi)\n## @xresult{} s = complex (1 + 1/(-2), 3 + 1/(7 + 1/16))\n##\n## [n, d] = rat (0.5 + i * pi)\n## @xresult{} n =  113 + 710i\n## @xresult{} d =  226\n##\n## n / d - (0.5 + i * pi)\n## @xresult{} 0 + 2.6676e-07i\n## @end group\n## @end example\n##\n## Programming Notes:\n##\n## 1. With one output @code{rat} produces a string which is a continued\n## fraction expansion.  To produce a string which is a simple fraction\n## (one numerator, one denominator) use @code{rats}.\n##\n## 2. The string output produced by @code{rat} can be passed to @code{eval}\n## to get back the original input up to the tolerance used.\n##\n## @seealso{rats, format}\n## @end deftypefn\n\nfunction [n, d] = rat (x, tol)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isfloat (x))\n    error (\"rat: X must be a single or double array\");\n  endif\n\n  if (iscomplex (x))\n    if (nargout == 2)  # return numerator and denominator\n      if (nargin == 2)\n        [nr, dr] = rat (real (x), tol);\n        [ni, di] = rat (imag (x), tol);\n      else\n        [nr, dr] = rat (real (x));\n        [ni, di] = rat (imag (x));\n      endif\n\n      ## For inputs with inf, the output is set to 1/0 or -1/0.\n      ## Override that to +inf/1 or -inf/1.\n      ii = (dr == 0 & nr > 0); dr(ii) = 1; nr(ii) = +inf;\n      ii = (dr == 0 & nr < 0); dr(ii) = 1; nr(ii) = -inf;\n      ii = (di == 0 & ni > 0); di(ii) = 1; ni(ii) = +inf;\n      ii = (di == 0 & ni < 0); di(ii) = 1; ni(ii) = -inf;\n\n      d = lcm (dr, di);  # now this should always be nonzero\n      n = complex (nr .* (d ./ dr), ni .* (d ./ di));\n    elseif (nargout <= 1)  # string output\n      if (nargin == 2)\n        realstr = rat (real (x), tol);\n        imagstr = rat (imag (x), tol);\n      else\n        realstr = rat (real (x));\n        imagstr = rat (imag (x));\n      endif\n\n      nn = rows (realstr);\n      start  = repmat (\"complex (\", nn, 1);\n      mid    = repmat (\", \",        nn, 1);\n      finish = repmat (\")\",         nn, 1);\n      n = [start, realstr, mid, imagstr, finish];\n    endif\n    return;\n  endif\n\n  y = x(:);\n\n  ## Replace Inf with 0 while calculating ratios.\n  inf_idx = isinf (x);\n  y(inf_idx(:)) = 0;\n\n  if (nargin == 1)\n    ## default norm\n    tol = 1e-6 * norm (y, 1);\n  else\n    if (! (isscalar (tol) && isnumeric (tol) && tol >= 0))\n      error (\"rat: TOL must be a numeric scalar >= 0\");\n    endif\n  endif\n\n  ## First step in the approximation is the integer portion\n\n  ## First element in the continued fraction.\n  n = round (y);\n  d = ones (size (y));\n  frac = y - n;\n  lastn = ones (size (y));\n  lastd = zeros (size (y));\n\n  nsz = numel (y);\n  steps = zeros ([nsz, 0]);\n\n  ## Grab new factors until all continued fractions converge.\n  while (1)\n    ## Determine which fractions have not yet converged.\n    idx = find (y != 0 & abs (y - n./d) >= tol);\n    if (isempty (idx))\n      if (isempty (steps))\n        steps = NaN (nsz, 1);\n      endif\n      break;\n    endif\n\n    ## Grab the next step in the continued fraction.\n    flip = 1 ./ frac(idx);\n    ## Next element in the continued fraction.\n    step = round (flip);\n\n    if (nargout < 2)\n      tsteps = NaN (nsz, 1);\n      tsteps(idx) = step;\n      steps = [steps, tsteps];\n    endif\n\n    frac(idx) = flip - step;\n\n    ## Update the numerator/denominator.\n    savedn = n;\n    savedd = d;\n    n(idx) = n(idx).*step + lastn(idx);\n    d(idx) = d(idx).*step + lastd(idx);\n    lastn = savedn;\n    lastd = savedd;\n  endwhile\n\n  if (nargout <= 1)\n    ## string output\n    n = \"\";\n    nsteps = columns (steps);\n    ## Loop over all values in array\n    for i = 1:nsz\n\n      if (inf_idx(i))\n        s = ifelse (x(i) > 0, \"Inf\", \"-Inf\");\n      elseif (y(i) == 0)\n        s = \"0\";\n      else\n        ## Create partial fraction expansion of one value\n        s = [int2str(y(i)), \" \"];\n        j = 1;\n\n        while (true)\n          step = steps(i, j++);\n          if (isnan (step))\n            break;\n          endif\n          if (j > nsteps || isnan (steps(i, j)))\n            if (step < 0)\n              s = [s(1:end-1), \" + 1/(\", int2str(step), \")\"];\n            else\n              s = [s(1:end-1), \" + 1/\", int2str(step)];\n            endif\n            break;\n          else\n            s = [s(1:end-1), \" + 1/(\", int2str(step), \")\"];\n          endif\n        endwhile\n        s = [s, repmat(\")\", 1, j-2)];\n      endif\n\n      ## Append result to output\n      n_nc = columns (n);\n      s_nc = columns (s);\n      if (n_nc > s_nc)\n        s(:, s_nc+1:n_nc) = \" \";\n      elseif (s_nc > n_nc && n_nc != 0)\n        n(:, n_nc+1:s_nc) = \" \";\n      endif\n      n = cat (1, n, s);\n    endfor\n  else\n    ## numerator, denominator output\n\n    ## Move the minus sign to the numerator.\n    n .*= sign (d);\n    d = abs (d);\n\n    ## Return the same shape as the input.\n    n = reshape (n, size (x));\n    d = reshape (d, size (x));\n\n    ## Use 1/0 for Inf.\n    n(inf_idx) = sign (x(inf_idx));\n    d(inf_idx) = 0;\n  endif\n\nendfunction\n\n\n%!assert (rat (pi), \"3 + 1/(7 + 1/16)\")\n%!assert (rat (pi, 1e-2), \"3 + 1/7\")\n## Test exceptional values\n%!assert (rat (0), \"0\")\n%!assert (rat (Inf), \"Inf\")\n%!assert (rat (-Inf), \"-Inf\")\n\n%!test\n%! [n, d] = rat ([0.5, 0.3, 1/3]);\n%! assert (n, [1, 3, 1]);\n%! assert (d, [2, 10, 3]);\n## Test exceptional values\n%!test\n%! [n, d] = rat ([Inf, 0, -Inf]);\n%! assert (n, [1, 0, -1]);\n%! assert (d, [0, 1, 0]);\n\n## Test complex scalar input\n%!test <*55198>\n%! assert (rat (complex (0.5, pi)), \"complex (1 + 1/(-2), 3 + 1/(7 + 1/16))\");\n%! [n, d] = rat (complex (0.5, pi));\n%! assert (n, 113 + 710*i);\n%! assert (d, 226);\n\n## Test complex vector input in all four quadrants\n%!test <*55198>\n%! theta = 72 * (1:4);\n%! x = cosd (theta) + i * sind (theta);\n%! [n, d] = rat (x);\n%! assert (n, [274195+843885i, -39955+29029i, -39955-29029i, 274195-843885i]);\n%! assert (d, [887313, 49387, 49387, 887313]);\n%! assert (all (abs (n ./ d - x) <= 2e-6));\n%! str = rat (x);\n%! assert (str(1, :), \"complex (0 + 1/(3 + 1/(4 + 1/(4 + 1/(4 + 1/4)))), 1 + 1/(-20 + 1/(-2 + 1/(-3 + 1/(-6)))))\");\n%! assert (str(2, :), \"complex (-1 + 1/(5 + 1/(4 + 1/(4 + 1/4)))       , 1 + 1/(-2 + 1/(-2 + 1/(-3 + 1/8)))    )\");\n%! assert (str(3, :), \"complex (-1 + 1/(5 + 1/(4 + 1/(4 + 1/4)))       , -1 + 1/(2 + 1/(2 + 1/(3 + 1/(-8))))   )\");\n%! assert (str(4, :), \"complex (0 + 1/(3 + 1/(4 + 1/(4 + 1/(4 + 1/4)))), -1 + 1/(20 + 1/(2 + 1/(3 + 1/6)))     )\");\n\n## Test complex exceptional inputs\n%!test <*55198>\n%! assert (rat (complex (inf, 0)), \"complex (Inf, 0)\");\n%! assert (rat (complex (0, inf)), \"complex (0, Inf)\");\n%! assert (rat (complex (-inf, 0)), \"complex (-Inf, 0)\");\n%! assert (rat (complex (0, -inf)), \"complex (0, -Inf)\");\n%! assert (rat (complex (nan, 0)), \"complex (NaN , 0)\");\n%! assert (rat (complex (0, nan)), \"complex (0, NaN )\");\n\n%!test <*55198>\n%! [n, d] = rat (complex (inf, 0));\n%! assert (n, complex (inf, 0));\n%! assert (d, 1);\n%! [n, d] = rat (complex (0, inf));\n%! assert (n, complex (0, inf));\n%! assert (d, 1);\n%! [n, d] = rat (complex (-inf, 0));\n%! assert (n, complex (-inf, 0));\n%! assert (d, 1);\n%! [n, d] = rat (complex (0, -inf));\n%! assert (n, complex (0, -inf));\n%! assert (d, 1);\n%! [n, d] = rat (complex (NaN, 0));\n%! assert (n, complex (NaN, 0));\n%! assert (d, 1);\n%! [n, d] = rat (complex (0, NaN));\n%! assert (n, complex (0, NaN));\n%! assert (d, 1);\n\n## Test eval with complex inputs\n%!test <*55198>\n%! x = complex (0.5, pi);\n%! assert (eval (rat (x)), x, 1e-6 * norm (x, 1));\n\n## Test eval with inf*i\n%!test <*55198>\n%! x = complex (0, inf);\n%! assert (eval (rat (x)), x, 1e-6 * norm (x, 1));\n\n%!assert <*43374> (eval (rat (0.75)), [0.75])\n\n## Test input validation\n%!error <Invalid call> rat ()\n%!error <X must be a single or double array> rat (int8 (3))\n%!error <TOL must be a numeric scalar> rat (1, \"a\")\n%!error <TOL must be a numeric scalar> rat (1, [1 2])\n%!error <TOL must be a numeric scalar .* 0> rat (1, -1)\n"
  },
  {
    "path": "scripts/general/repelem.m",
    "content": "########################################################################\n##\n## Copyright (C) 2015-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{xxx} =} repelem (@var{x}, @var{R})\n## @deftypefnx {} {@var{xxx} =} repelem (@var{x}, @var{R_1}, @dots{}, @var{R_n})\n## Construct an array of repeated elements from @var{x} and repeat instructions\n## @var{R_1}, @enddots{}\n##\n## @var{x} must be a scalar, vector, or N-dimensional array.\n##\n## A repeat instruction @var{R_j} must either be a scalar or a vector.  If the\n## instruction is a scalar then each component of @var{x} in dimension @var{j}\n## is repeated @var{R_j} times.  If the instruction is a vector then it must\n## have the same number of elements as the corresponding dimension @var{j} of\n## @var{x}.  In this case, the @var{k}th component of dimension @var{j} is\n## repeated @code{@var{R_j}(@var{k})} times.\n##\n## If @var{x} is a scalar or vector then @code{repelem} may be called with just\n## a single repeat instruction @var{R} and @code{repelem} will return a vector\n## with the same orientation as the input.\n##\n## If @var{x} is a matrix then at least two @var{R_j}s must be specified.\n##\n## Note: Using @code{repelem} with a vector @var{x} and a vector for @var{R_j}\n## is equivalent to Run Length Decoding.\n##\n## Examples:\n##\n## @example\n## @group\n## A = [1 2 3 4 5];\n## B = [2 1 0 1 2];\n## repelem (A, B)\n##   @xresult{}   1   1   2   4   5   5\n## @end group\n## @end example\n##\n## @example\n## @group\n## A = magic (3)\n##   @xresult{} A =\n##        8   1   6\n##        3   5   7\n##        4   9   2\n## B1 = [1 2 3];\n## B2 = 2;\n## repelem (A, B1, B2)\n##   @xresult{}     8   8   1   1   6   6\n##          3   3   5   5   7   7\n##          3   3   5   5   7   7\n##          4   4   9   9   2   2\n##          4   4   9   9   2   2\n##          4   4   9   9   2   2\n## @end group\n## @end example\n##\n## More @var{R_j} may be specified than the number of dimensions of @var{x}.\n## Any excess @var{R_j} must be scalars (because @var{x}'s size in those\n## dimensions is only 1), and @var{x} will be replicated in those dimensions\n## accordingly.\n##\n## @example\n## @group\n## A = [1 2 3 4 5];\n## B1 = 2;\n## B2 = [2 1 3 0 2];\n## B3 = 3;\n## repelem (A, B1, B2, B3)\n##   @xresult{}    ans(:,:,1) =\n##            1   1   2   3   3   3   5   5\n##            1   1   2   3   3   3   5   5\n##\n##         ans(:,:,2) =\n##\n##            1   1   2   3   3   3   5   5\n##            1   1   2   3   3   3   5   5\n##\n##         ans(:,:,3) =\n##            1   1   2   3   3   3   5   5\n##            1   1   2   3   3   3   5   5\n## @end group\n## @end example\n##\n## @var{R_j} must be specified in order.  A placeholder of 1 may be used for\n## dimensions which do not need replication.\n##\n## @example\n## @group\n## repelem ([-1, 0; 0, 1], 1, 2, 1, 2)\n##   @xresult{}  ans(:,:,1,1) =\n##         -1  -1   0   0\n##          0   0   1   1\n##\n##       ans(:,:,1,2) =\n##         -1  -1   0   0\n##          0   0   1   1\n## @end group\n## @end example\n##\n## If fewer @var{R_j} are given than the number of dimensions in @var{x},\n## @code{repelem} will assume @var{R_j} is 1 for those dimensions.\n##\n## @example\n## A = cat (3, [-1 0; 0 1], [-1 0; 0 1])\n##   @xresult{}  ans(:,:,1) =\n##         -1   0\n##          0   1\n##\n##       ans(:,:,2) =\n##         -1   0\n##          0   1\n##\n## repelem (A,2,3)\n##   @xresult{}  ans(:,:,1) =\n##         -1  -1  -1   0   0   0\n##         -1  -1  -1   0   0   0\n##          0   0   0   1   1   1\n##          0   0   0   1   1   1\n##\n##       ans(:,:,2) =\n##         -1  -1  -1   0   0   0\n##         -1  -1  -1   0   0   0\n##          0   0   0   1   1   1\n##          0   0   0   1   1   1\n## @end example\n##\n## @code{repelem} preserves the class of @var{x}, and works with strings,\n## cell arrays, NA, and NAN inputs.  If any @var{R_j} is 0 the output will\n## be an empty array.\n##\n## @example\n## @group\n## repelem (\"Octave\", 2, 3)\n##   @xresult{}    OOOccctttaaavvveee\n##         OOOccctttaaavvveee\n##\n## repelem ([1 2 3; 1 2 3], 2, 0)\n##   @xresult{}    [](4x0)\n## @end group\n## @end example\n##\n## @seealso{cat, kron, repmat}\n## @end deftypefn\n\n## Author: Markus Bergholz <markuman@gmail.com>\n## Author: Nicholas R. Jankowski <jankowski.nicholas@gmail.com>\n\n## As a U.S. government employee, Nicholas R. Jankowski makes no claim\n## of copyright.\n\n## The prepareIdx routine is Copyright (C) 2015 Peter John Acklam\n## <pjacklam@gmail.com>, used with permission.\n\nfunction retval = repelem (x, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n\n  elseif (nargin == 2)\n\n    R = varargin{1};\n\n    if (isscalar (R))\n\n      if (! isvector (x))\n        error ([\"repelem: %dD Array requires %d or more input \" ...\n                \"arguments, but only %d given\"], ...\n               ndims (x), ndims (x) + 1, nargin);\n      endif\n\n      if (isrow (x))\n        ## element values repeated R times in a scalar or row vector\n        retval = x(ones (R, 1), :)(:).';\n      else\n        ## element values repeated R times in a col vector\n        retval = x.'(ones (R, 1), :)(:);\n      endif\n\n    elseif (isvector (x) && isvector (R))\n\n      ## vector x with vector repeat.\n      if (numel (R) != numel (x))\n        error ([\"repelem: R1 must either be scalar or have the same \" ...\n                \"number of elements as the vector to be replicated\"]);\n      endif\n\n      ## Basic run-length decoding in function prepareIdx returns\n      ## idx2 as a row vector of element indices in the right positions.\n      idx2 = prepareIdx (R);\n      ## Fill with element values, direction matches element.\n      retval = x(idx2);\n\n    else # catch any arrays passed to x or varargin with nargin==2\n      error ([\"repelem: when called with only two inputs they must be \" ...\n              \"either scalars or vectors, not %s and %s.\"],\n             typeinfo (x), typeinfo (R));\n    endif\n\n  elseif (nargin == 3)  # special optimized case for 2-D (matrices)\n\n    ## Input Validation\n    xsz = size (x);\n    vector_r = ! (cellfun ('numel', varargin) == 1);\n\n    ## 1. Check that all varargin are either scalars or vectors, not arrays.\n    ##    isvector returns true for scalars so one test captures both inputs.\n    if (! (isvector (varargin{1}) && (isvector (varargin{2}))))\n      error (\"repelem: R1 and R2 must be scalars or vectors\");\n\n    ## 2. check that any repeat vectors have the right length.\n    elseif (any (cellfun ('numel', varargin(vector_r)) != xsz(vector_r)))\n      error ([\"repelem: R_j vectors must have the same number of elements \" ...\n              \"as the size of dimension j of X\"]);\n    endif\n\n    ## Create index arrays to pass to element.\n    ## (It is no slower to call prepareIdx than to check and do scalars\n    ## directly.)\n    idx1 = prepareIdx (varargin{1}, xsz(1));\n    idx2 = prepareIdx (varargin{2}, xsz(2));\n\n    if (issparse (x))\n      retval = x(idx1, idx2);\n    else\n      ## The \":\" at the end takes care of any x dimensions > 2.\n      retval = x(idx1, idx2, :);\n    endif\n\n  else  # (nargin > 3)\n\n    ## Input Validation\n    xsz = size (x);\n    n_xdims = numel (xsz);\n    vector_r = ! (cellfun ('numel', varargin) == 1);\n\n    ## 1. Check that all repeats are scalars or vectors\n    ##    (isvector gives true for scalars);\n    if (! all (cellfun ('isvector', varargin(vector_r))))\n      error (\"repelem: R_j must all be scalars or vectors\");\n\n    ## 2. Catch any vectors thrown at trailing singletons,\n    ##    which should only have scalars;\n    elseif (find (vector_r, 1, \"last\") > n_xdims)\n      error (\"repelem: R_j for trailing singleton dimensions must be scalar\");\n\n    ## 3. Check that the ones that are vectors have the right length.\n    elseif (any (cellfun ('numel', varargin(vector_r)) != xsz(vector_r)))\n      error ([\"repelem: R_j vectors must have the same number of elements \" ...\n              \"as the size of dimension j of X\"]);\n\n    endif\n\n    n_rpts = nargin - 1;\n    dims_with_vectors_and_scalars = min (n_xdims, n_rpts);\n\n    ## Preallocate idx which will contain index array to be put into element.\n    idx = cell (1, n_rpts);\n\n    ## Use prepareIdx() to fill indices for dimensions that could be\n    ## a scalar or a vector.\n    for i = 1 : dims_with_vectors_and_scalars\n      idx(i) = prepareIdx (varargin{i}, xsz(i));\n    endfor\n\n    ## If there are more varargin inputs than x dimensions, then input tests\n    ## have verified that they are just scalars, so add [1 1 1 1 1 ... 1] to\n    ## those dims to perform concatenation along those dims.\n    if (n_rpts > n_xdims)\n      for i = n_xdims + (1 : (n_rpts - n_xdims))\n        idx(i) = ones (1, varargin{i});\n      endfor\n    endif\n\n    ## Use completed idx to specify repetition of x values in all dimensions.\n    ## The trailing \":\" will take care of cases where n_xdims > n_rpts.\n    retval = x(idx{:}, :);\n\n  endif\n\nendfunction\n\n## Return a row vector of indices prepared for replicating.\nfunction idx = prepareIdx (v, n)\n\n  if (isscalar (v))\n    ## will always return row vector\n    idx = [1:n](ones (v, 1), :)(:).';\n\n  else\n    ## This works for a row or column vector.\n\n    ## Get ending position for each element item.\n    idx_temp = cumsum (v);\n\n    ## Set starting position of each element to 1.\n    idx(idx_temp + 1) = 1;\n\n    ## Set starting position of each element to 1.\n    idx(1) = 1;\n\n    ## Row vector with proper length for output\n    idx = idx(1:idx_temp(end));\n\n    ## with prepared index\n    idx = (find (v != 0))(cumsum (idx));\n\n  endif\n\nendfunction\n\n\n## tests for help examples\n%!assert (repelem ([1 2 3 4 5], [2 1 0 1 2]), [1 1 2 4 5 5])\n%!assert (repelem (magic(3), [1 2 3],2), ...\n%!  [8 8 1 1 6 6;3 3 5 5 7 7;3 3 5 5 7 7;4 4 9 9 2 2;4 4 9 9 2 2;4 4 9 9 2 2])\n%!assert (repelem ([1 2 3 4 5],2,[2 1 3 0 2],3),repmat([1 1 2 3 3 3 5 5],2,1,3))\n%!assert (repelem ([-1 0;0 1],1,2,1,2), repmat([-1 -1 0 0; 0 0 1 1],1,1,1,2))\n%!assert (repelem (cat(3,[-1 0 ; 0 1],[-1 0 ; 0 1]),2,3), ...\n%!  repmat([-1 -1 -1 0 0 0;-1 -1 -1 0 0 0;0 0 0 1 1 1;0 0 0 1 1 1],1,1,2))\n%!assert (repelem (\"Octave\", 2,3), [\"OOOccctttaaavvveee\";\"OOOccctttaaavvveee\"])\n\n## test complex vectors are not Hermitian conjugated\n%!assert (repelem ([i, -i], 2), [i, i, -i, -i])\n%!assert (repelem ([i; -i], 2), [i; i; -i; -i])\n\n## nargin == 2 tests\n%!assert (repelem (2, 6), [2 2 2 2 2 2])\n%!assert (repelem ([-1 0 1], 2), [-1 -1 0 0 1 1])\n%!assert (repelem ([-1 0 1]', 2), [-1; -1; 0; 0; 1; 1])\n%!assert (repelem ([-1 0 1], [1 2 1]), [-1 0 0 1])\n%!assert (repelem ([-1 0 1]', [1 2 1]), [-1; 0; 0; 1])\n%!assert (repelem ([1 2 3 4 5]', [2 1 0 1 2]), [1 1 2 4 5 5]')\n\n## nargin == 3 tests\n%!assert (repelem ([1 0;0 -1], 2, 3),\n%!       [1 1 1 0 0 0;1 1 1 0 0 0;0 0 0 -1 -1 -1;0 0 0 -1 -1 -1])\n%!assert (repelem ([1 0; 0 -1], 1,[3 2]), [1 1 1 0 0;0 0 0 -1 -1])\n%!assert (repelem ([1 0; 0 -1], 2,[3 2]),\n%!        [1 1 1 0 0;1 1 1 0 0;0 0 0 -1 -1;0 0 0 -1 -1])\n%!assert (repelem (cat(3,[1 0; 0 -1],[1 0;0 -1]), 1,[3 2]),\n%!        repmat([1 1 1 0 0 ; 0 0 0 -1 -1],1,1,2))\n%!assert (repelem ([1 0; 0 -1], [3 2], 1), [1 0;1 0;1 0;0 -1;0 -1])\n%!assert (repelem ([1 0; 0 -1], [3 2], 2),\n%!        [1 1 0 0;1 1 0 0;1 1 0 0;0 0 -1 -1;0 0 -1 -1])\n%!assert (repelem ([1 0; 0 -1], [2 3] ,[3 2]),\n%!        [1 1 1 0 0;1 1 1 0 0;0 0 0 -1 -1;0 0 0 -1 -1;0 0 0 -1 -1])\n%!assert (repelem (cat(3,[1 1 1 0;0 1 0 0],[1 1 1 1;0 0 0 1],[1 0 0 1;1 1 0 1]),\n%!                2, 3),\n%!        cat (3,[1 1 1 1 1 1 1 1 1 0 0 0\n%!                1 1 1 1 1 1 1 1 1 0 0 0\n%!                0 0 0 1 1 1 0 0 0 0 0 0\n%!                0 0 0 1 1 1 0 0 0 0 0 0],\n%!               [1 1 1 1 1 1 1 1 1 1 1 1\n%!                1 1 1 1 1 1 1 1 1 1 1 1\n%!                0 0 0 0 0 0 0 0 0 1 1 1\n%!                0 0 0 0 0 0 0 0 0 1 1 1],\n%!               [1 1 1 0 0 0 0 0 0 1 1 1\n%!                1 1 1 0 0 0 0 0 0 1 1 1\n%!                1 1 1 1 1 1 0 0 0 1 1 1\n%!                1 1 1 1 1 1 0 0 0 1 1 1]))\n%!assert (repelem (cat(3,[1 1 1 0;0 1 0 0],[1 1 1 1;0 0 0 1],[1 0 0 1;1 1 0 1]),\n%!                2, [3 3 3 3]), ...\n%!        cat (3,[1 1 1 1 1 1 1 1 1 0 0 0\n%!                1 1 1 1 1 1 1 1 1 0 0 0\n%!                0 0 0 1 1 1 0 0 0 0 0 0\n%!                0 0 0 1 1 1 0 0 0 0 0 0], ...\n%!               [1 1 1 1 1 1 1 1 1 1 1 1\n%!                1 1 1 1 1 1 1 1 1 1 1 1\n%!                0 0 0 0 0 0 0 0 0 1 1 1\n%!                0 0 0 0 0 0 0 0 0 1 1 1], ...\n%!               [1 1 1 0 0 0 0 0 0 1 1 1\n%!                1 1 1 0 0 0 0 0 0 1 1 1\n%!                1 1 1 1 1 1 0 0 0 1 1 1\n%!                1 1 1 1 1 1 0 0 0 1 1 1]));\n%!assert (repelem ([1 2 3 4 5], 2,[2 1 2 0 2]), [1 1 2 3 3 5 5;1 1 2 3 3 5 5])\n%\n## nargin > 3 tests\n%!assert (repelem ([1 0;0 -1], 2, 3, 4), ...\n%!        cat(3,[1 1 1 0 0 0;1 1 1 0 0 0;0 0 0 -1 -1 -1;0 0 0 -1 -1 -1], ...\n%!              [1 1 1 0 0 0;1 1 1 0 0 0;0 0 0 -1 -1 -1;0 0 0 -1 -1 -1], ...\n%!              [1 1 1 0 0 0;1 1 1 0 0 0;0 0 0 -1 -1 -1;0 0 0 -1 -1 -1], ...\n%!              [1 1 1 0 0 0;1 1 1 0 0 0;0 0 0 -1 -1 -1;0 0 0 -1 -1 -1]))\n%!assert (repelem (repmat([-1 0;0 1],1,1,2,3),2,2,2), ...\n%!        repmat([-1 -1 0 0;-1 -1 0 0;0 0 1 1; 0 0 1 1],1,1,4,3))\n%!assert (repelem (repmat([-1 0;0 1],1,1,2,3),[2 2],[2 2],2), ...\n%!        repmat([-1 -1 0 0;-1 -1 0 0;0 0 1 1; 0 0 1 1],1,1,4,3))\n%!assert (repelem (repmat([-1 0;0 1],1,1,2,3),2,2,2,2,2), ...\n%!        repmat([-1 -1 0 0;-1 -1 0 0;0 0 1 1; 0 0 1 1],1,1,4,6,2))\n%!assert (repelem ([1,0,-1;-1,0,1],[2 3],[2 3 4],2), ...\n%!        cat (3,[ 1  1 0 0 0 -1 -1 -1 -1\n%!                 1  1 0 0 0 -1 -1 -1 -1\n%!                -1 -1 0 0 0  1  1  1  1\n%!                -1 -1 0 0 0  1  1  1  1\n%!                -1 -1 0 0 0  1  1  1  1], ...\n%!               [ 1  1 0 0 0 -1 -1 -1 -1\n%!                 1  1 0 0 0 -1 -1 -1 -1\n%!                -1 -1 0 0 0  1  1  1  1\n%!                -1 -1 0 0 0  1  1  1  1\n%!                -1 -1 0 0 0  1  1  1  1]));\n%!assert (repelem ([1 2 3;4 5 6],[0 2],2,2), repmat([4 4 5 5 6 6],2,1,2))\n\n## test with structures\n%!test\n%! a(2).x = 1;\n%! a(2).y = 2;\n%! a(1).x = 3;\n%! a(1).y = 4;\n%! b = repelem (a, 2, [1 3]);\n%! assert (size (b) == [2, 4]);\n%! assert ([b.y], [4 4 2 2 2 2 2 2]);\n\n## test with cell arrays\n%!test\n%! assert (repelem ({-1 0 1},  2), {-1 -1 0 0 1 1});\n%! assert (repelem ({-1 0 1}', 2), {-1; -1; 0; 0; 1; 1;});\n%! assert (repelem ({1 0;0 -1}, 2, 3),\n%!         {1 1 1 0 0 0;1 1 1 0 0 0;0 0 0 -1 -1 -1;0 0 0 -1 -1 -1});\n\n%!test <*54275>\n%! assert (repelem (11:13, [1 3 0]), [11 12 12 12]);\n\n%!test <*59705>\n%! xs = sparse (magic (3));\n%! assert (repelem (xs, 1, 2), ...\n%!         sparse ([8,8,1,1,6,6; 3,3,5,5,7,7; 4,4,9,9,2,2]));\n\n## nargin <= 1 error tests\n%!error <Invalid call> repelem ()\n%!error <Invalid call> repelem (1)\n%!error repelem (5,[])\n%!error repelem ([1 2 3 3 2 1])\n%!error repelem ([1 2 3; 3 2 1])\n\n## nargin == 2 error tests\n%!error repelem ([1 2 3; 3 2 1],[])\n%!error repelem ([1 2 3; 3 2 1],2)\n%!error repelem ([1 2 3; 3 2 1],2)\n%!error repelem ([1 2 3; 3 2 1],[1 2 3])\n%!error repelem ([1 2 3; 3 2 1],[1 2 3]')\n%!error repelem ([1 2 3; 3 2 1],[1 2 2 1])\n%!error repelem ([1 2 3; 3 2 1],[1 2 3;4 5 6])\n%!error repelem ([1 2 3 4 5],[1 2 3 4 5;1 2 3 4 5])\n\n## nargin == 3 error tests\n%!error repelem ([1 2 3; 3 2 1], 1, [1 2;1 2])\n%!error repelem ([1 2 3; 3 2 1], 1, [1 2])\n%!error repelem ([1 2 3; 3 2 1], 2, [])\n%!error repelem ([1 2 3; 3 2 1], [1 2 3], [1 2 3])\n%!error repelem ([1 2 3; 3 2 1], [1 2 3], [1 2 3 4])\n%!error repelem ([1 2 3; 3 2 1], [1 2], [1 2 3 4])\n\n## nargin > 3 error tests\n%!error repelem ([1 2 3; 3 2 1], 1, [1 2;1 2],1,2,3)\n%!error repelem ([1 2 3; 3 2 1], [],1,2,3)\n%!error repelem ([1 2 3; 3 2 1], [1 2], [1 2 3],1,2,[1 2;1 2])\n%!error repelem ([1 2 3; 3 2 1], [1 2 3], [1 2 3],1,2)\n%!error repelem ([1 2 3; 3 2 1], [1 2], [1 2 3 4],1,2)\n"
  },
  {
    "path": "scripts/general/repmat.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} repmat (@var{A}, @var{m})\n## @deftypefnx {} {@var{B} =} repmat (@var{A}, @var{m}, @var{n})\n## @deftypefnx {} {@var{B} =} repmat (@var{A}, @var{m}, @var{n}, @var{p} @dots{})\n## @deftypefnx {} {@var{B} =} repmat (@var{A}, [@var{m} @var{n}])\n## @deftypefnx {} {@var{B} =} repmat (@var{A}, [@var{m} @var{n} @var{p} @dots{}])\n## Repeat matrix or N-D array.\n##\n## Form a block matrix of size @var{m} by @var{n}, with a copy of matrix\n## @var{A} as each element.\n##\n## If @var{n} is not specified, form an @var{m} by @var{m} block matrix.  For\n## copying along more than two dimensions, specify the number of times to copy\n## across each dimension @var{m}, @var{n}, @var{p}, @dots{}, in a vector in the\n## second argument.\n##\n## @seealso{bsxfun, kron, repelems}\n## @end deftypefn\n\nfunction B = repmat (A, m, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (nargin == 3)\n    n = varargin{1};\n    if (! isempty (m) && isempty (n))\n      m = m(:).';\n      n = 1;\n    elseif (isempty (m) && ! isempty (n))\n      m = n(:).';\n      n = 1;\n    elseif (isempty (m) && isempty (n))\n      m = n = 1;\n    else\n      if (all (size (m) > 1))\n        m = m(:,1);\n        if (numel (m) < 3)\n          n = n(end);\n        else\n          n = [];\n        endif\n      endif\n      if (all (size (n) > 1))\n        n = n(:,1);\n      endif\n      m = m(:).';\n      n = n(:).';\n    endif\n  else\n    if (nargin > 3)\n      ## input check for m and varargin\n      if (isscalar (m) && all (cellfun (\"numel\", varargin) == 1))\n        m = [m varargin{:}];\n        n = [];\n      else\n        error (\"repmat: all input arguments must be scalar\");\n      endif\n    elseif (isempty (m))\n      m = n = 1;\n    elseif (isscalar (m))\n      n = m;\n    elseif (ndims (m) > 2)\n      error (\"repmat: M has more than 2 dimensions\");\n    elseif (all (size (m) > 1))\n      m = m(:,1).';\n      n = [];\n    else\n      m = m(:).';\n      n = [];\n    endif\n  endif\n  idx = [m, n];\n\n  if (all (idx < 0))\n    error (\"repmat: invalid dimensions\");\n  else\n    idx = max (idx, 0);\n  endif\n\n  if (numel (A) == 1)\n    ## optimize the scalar fill case.\n    if (any (idx == 0))\n      B = resize (A, idx);\n    else\n      B(1:prod (idx)) = A;\n      B = reshape (B, idx);\n    endif\n  elseif (ndims (A) == 2 && length (idx) < 3)\n    if (issparse (A))\n      B = kron (ones (idx), A);\n    else\n      ## indexing is now faster, so we use it rather than kron.\n      m = rows (A); n = columns (A);\n      p = idx(1); q = idx(2);\n      B = reshape (A, m, 1, n, 1);\n      B = B(:, ones (1, p), :, ones (1, q));\n      B = reshape (B, m*p, n*q);\n    endif\n  else\n    aidx = size (A);\n    ## ensure matching size\n    idx(end+1:length (aidx)) = 1;\n    aidx(end+1:length (idx)) = 1;\n    ## create subscript array\n    cidx = cell (2, length (aidx));\n    for i = 1:length (aidx)\n      cidx{1,i} = ':';\n      cidx{2,i} = ones (1, idx (i));\n    endfor\n    aaidx = aidx;\n    ## add singleton dims\n    aaidx(2,:) = 1;\n    A = reshape (A, aaidx(:));\n    B = reshape (A (cidx{:}), idx .* aidx);\n  endif\n\nendfunction\n\n\n## Tests for ML compatibility\n%!shared x\n%! x = [1 2 3];\n%!assert (repmat (x, [3, 1]), repmat (x, 3, []))\n%!assert (repmat (x, [3, 1]), repmat (x, [], 3))\n%!assert (repmat (x, [1, 3]), repmat (x, [], [1, 3]))\n%!assert (repmat (x, [1, 3]), repmat (x, [1, 3], []))\n%!assert (repmat (x, [1 3]), repmat (x, [1 3; 3 3]))\n%!assert (repmat (x, [1 1 2]), repmat (x, [1 1; 1 3; 2 1]))\n%!assert (repmat (x, [1 3; 1 3], [1; 3]), repmat (x, [1 1 3]))\n%!assert (repmat (x, [1 1], 4), repmat (x, [1 3; 1 3], [1; 4]))\n%!assert (repmat (x, [1 1], 4), repmat (x, [1 3; 1 3], [1 2; 3 4]))\n%!assert (repmat (x, [1 1], 4), repmat (x, [1 1 4]))\n%!assert (repmat (x, [1 1], 4), repmat (x, 1, [1 4]))\n\n## Test various methods of providing size parameters\n%!shared x\n%! x = [1 2;3 4];\n%!assert (repmat (x, [1 1]), repmat (x, 1))\n%!assert (repmat (x, [3 3]), repmat (x, 3))\n%!assert (repmat (x, [1 1]), repmat (x, 1, 1))\n%!assert (repmat (x, [1 3]), repmat (x, 1, 3))\n%!assert (repmat (x, [3 1]), repmat (x, 3, 1))\n%!assert (repmat (x, [3 3]), repmat (x, 3, 3))\n%!assert (repmat (pi, [1,2,3,4]), repmat (pi, 1,2,3,4))\n\n## Tests for numel==1 case:\n%!shared x, r\n%! x = [ 65 ];\n%! r = kron (ones (2,2), x);\n%!assert (r, repmat (x, [2 2]))\n%!assert (char (r), repmat (char (x), [2 2]))\n%!assert (int8 (r), repmat (int8 (x), [2 2]))\n\n## Tests for ndims==2 case:\n%!shared x, r\n%! x = [ 65 66 67 ];\n%! r = kron (ones (2,2), x);\n%!assert (r, repmat (x, [2 2]))\n%!assert (char (r), repmat (char (x), [2 2]))\n%!assert (int8 (r), repmat (int8 (x), [2 2]))\n\n## Tests for dim>2 case:\n%!shared x, r\n%! x = [ 65 66 67 ];\n%! r = kron (ones (2,2), x);\n%! r(:,:,2) = r(:,:,1);\n%!assert (r, repmat (x, [2 2 2]))\n%!assert (char (r), repmat (char (x), [2 2 2]))\n%!assert (int8 (r), repmat (int8 (x), [2 2 2]))\n\n## Test that sparsity is kept\n%!assert (sparse (4,4), repmat (sparse (2,2),[2 2]))\n\n%!assert (size (repmat (\".\", -1, 1)), [0, 1])\n%!assert (size (repmat (\".\", 1, -1)), [1, 0])\n\n%!assert (size (repmat (1, [1, 0])), [1, 0])\n%!assert (size (repmat (1, [5, 0])), [5, 0])\n%!assert (size (repmat (1, [0, 1])), [0, 1])\n%!assert (size (repmat (1, [0, 5])), [0, 5])\n\n%!assert (size (repmat (ones (0, 3), [2 3])), [0 9])\n%!assert (size (repmat (ones (0, 0, 3), [2 3])), [0 0 3])\n\n%!shared x\n%! x = struct (\"a\", [], \"b\", []);\n%!assert (size (repmat (x, [1, 0])), [1, 0])\n%!assert (size (repmat (x, [5, 0])), [5, 0])\n%!assert (size (repmat (x, [0, 1])), [0, 1])\n%!assert (size (repmat (x, [0, 5])), [0, 5])\n\n%!assert (size (repmat ({1}, [1, 0])), [1, 0])\n%!assert (size (repmat ({1}, [5, 0])), [5, 0])\n%!assert (size (repmat ({1}, [0, 1])), [0, 1])\n%!assert (size (repmat ({1}, [0, 5])), [0, 5])\n\n%!error size (repmat (\".\", -1, -1))\n"
  },
  {
    "path": "scripts/general/rescale.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} rescale (@var{A})\n## @deftypefnx {} {@var{B} =} rescale (@var{A}, @var{l}, @var{u})\n## @deftypefnx {} {@var{B} =} rescale (@dots{}, \"inputmin\", @var{inmin})\n## @deftypefnx {} {@var{B} =} rescale (@dots{}, \"inputmax\", @var{inmax})\n## Scale matrix elements to a specified range of values.\n##\n## When called with a single matrix argument @var{A}, rescale elements to\n## occupy the interval [0, 1].\n##\n## The optional inputs @code{[@var{l}, @var{u}]} will scale @var{A} to the\n## interval with lower bound @var{l} and upper bound @var{u}.\n##\n## The optional input @qcode{\"inputmin\"} replaces all elements less than\n## the specified value @var{inmin} with @var{inmin}.  Similarly, the optional\n## input @qcode{\"inputmax\"} replaces all elements greater than the specified\n## value @var{inmax} with @var{inmax}.  If unspecified the minimum and maximum\n## are taken from the data itself (@w{@code{@var{inmin} = min (A(:))}}@ and\n## @w{@code{@var{inmax} = max (A(:))}}).\n##\n## Programming Notes:\n## The applied formula is\n## @tex\n## $$B = l + {A - inmin \\over inmax - inmin} \\cdot (u - l)$$\n## @end tex\n## @ifnottex\n## @var{B} = @var{l} + ((@var{A} - @var{inmin}) ./ (@var{inmax} - @var{inmin}))\n## .* (@var{u} - @var{l})\n## @end ifnottex\n##\n## The class of the output matrix @var{B} is single if the input @var{A} is\n## single, but otherwise is of class double for inputs which are of double,\n## integer, or logical type.\n##\n## @seealso{bounds, min, max}\n## @end deftypefn\n\nfunction B = rescale (A, varargin)\n\n  if (! any (nargin == [1,3,5,7]))\n    print_usage ();\n  endif\n\n  ## Verify A input.\n  if (! (isnumeric (A) || islogical (A)))\n    error (\"rescale: A must be a numeric or logical matrix\");\n  endif\n  ## Use class double for integers and logical types\n  if (! isa (A, \"single\"))\n    A = double (A);\n  endif\n\n  l = 0;  u = 1;\n\n  ## If 2nd and 3rd argument are numeric, set non-default interval [l, u].\n  if (nargin > 1 && isnumeric (varargin{1}))\n    if (! isnumeric (varargin{2}))\n      error (\"rescale: upper bound U must be numeric\");\n    endif\n    l = varargin{1};  u = varargin{2};\n    varargin(1:2) = [];\n    if (any ((l > u)(:)))\n      error (\"rescale: lower bound L must be smaller than upper bound U\");\n    endif\n    ## FIXME: Need input validation for cases where l or u is not a scalar\n  endif\n\n  truncate_range = false;\n\n  ## Check for named argument \"inputmin\".\n  inminidx = find (strcmpi (varargin, \"inputmin\"), 1, \"last\");\n  if (! isempty (inminidx))\n    if (! isnumeric (varargin{inminidx + 1}))\n      error (\"rescale: INMIN must be numeric\");\n    endif\n    inmin = varargin{inminidx + 1};\n    varargin(inminidx:inminidx + 1) = [];\n    truncate_range = true;\n  else\n    inmin = min (A(:));\n  endif\n\n  ## Check for named argument \"inputmax\".\n  inmaxidx = find (strcmpi (varargin, \"inputmax\"), 1, \"last\");\n  if (! isempty (inmaxidx))\n    if (! isnumeric (varargin{inmaxidx + 1}))\n      error (\"rescale: INMAX must be numeric\");\n    endif\n    inmax = varargin{inmaxidx + 1};\n    varargin(inmaxidx:inmaxidx + 1) = [];\n    truncate_range = true;\n  else\n    inmax = max (A(:));\n  endif\n\n  ## Verify all options were processed\n  if (! isempty (varargin))\n    error (\"rescale: invalid option(s)\");\n  endif\n\n  ## Rescale A to interval [l,u] in range interval [inmin, inmax].\n  range = inmax - inmin;\n  range(range == 0) = 1;  # Avoid division by 0 resulting in NaN\n  B = l + (A - inmin) ./ range .* (u - l);\n  if (truncate_range)\n    B(A < inmin) = l;\n    B(A > inmax) = u;\n  endif\n\nendfunction\n\n\n%!assert (rescale ([]), [])\n%!assert (rescale ([0]), [0])\n%!assert (rescale ([1]), [0])\n%!assert (rescale (0:5), (0:5)/5)\n\n## Test [l,u] input\n%!assert (rescale (1:4, 3, 9), [3,5,7,9])\n%!test\n%! A = repmat ([1:3]', [1, 3]);\n%! B = rescale (A, [1, 2, 3], 5);\n%! assert (B, [1, 2, 3; 3, 3.5, 4; 5, 5, 5]);\n%!test\n%! A = repmat ([1:3]', [1, 3]);\n%! B = rescale (A, [1; 2; 3], 5);\n%! assert (B, [1, 1, 1; 3.5, 3.5, 3.5; 5, 5, 5]);\n\n## Test property/value options\n%!assert (rescale (0:6, \"inputmin\", 1, \"inputmax\", 5), [0,0,0.25,0.5,0.75,1,1])\n\n## Test class of returned output\n%!assert (class (rescale (single ([0, 5]))), \"single\")\n%!assert (class (rescale (double ([0, 5]))), \"double\")\n%!assert (class (rescale (int8 ([0, 5]))), \"double\")\n%!assert (class (rescale (logical ([0, 1]))), \"double\")\n\n## Test input validation\n%!error <Invalid call> rescale ()\n%!error <Invalid call> rescale (1, 2)\n%!error <Invalid call> rescale (1, 2, 3, 4)\n%!error <Invalid call> rescale (1, 2, 3, 4, 5, 6)\n%!error <Invalid call> rescale (1, 2, 3, 4, 5, 6, 7, 8)\n%!error <A must be a numeric or logical matrix> rescale (\"abc\")\n%!error <A must be a numeric or logical matrix> rescale ({ [1] })\n%!error <U must be numeric> rescale (1, 0, \"A\")\n%!error <L must be smaller than .* U> rescale (1, 2, 0)\n## FIXME: Need BIST tests here when input validation has been added for\n##        l and u not being scalar.\n%!error <INMIN must be numeric> rescale (1, \"inputmin\", \"abc\")\n%!error <INMAX must be numeric> rescale (1, \"inputmax\", \"abc\")\n%!error <invalid option> rescale (1, \"foobar\", 1)\n"
  },
  {
    "path": "scripts/general/rng.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} rng (@var{seed})\n## @deftypefnx {} {} rng (@var{seed}, \"@var{generator}\")\n## @deftypefnx {} {} rng (\"shuffle\")\n## @deftypefnx {} {} rng (\"shuffle\", \"@var{generator}\")\n## @deftypefnx {} {} rng (\"default\")\n## @deftypefnx {} {@var{s} =} rng ()\n## @deftypefnx {} {} rng (@var{s})\n## @deftypefnx {} {@var{s} =} rng (@dots{})\n## Set or query the seed of the random number generator used by @code{rand} and\n## @code{randn}.\n##\n## The input @var{seed} is a scalar numeric value used to initialize the state\n## vector of the random number generator.\n##\n## The optional string @var{generator} specifies the type of random number\n## generator to be used.  Its value can be @qcode{\"twister\"},\n## @qcode{\"v5uniform\"}, or @qcode{\"v5normal\"}.  The @qcode{\"twister\"} keyword\n## is described below.  @qcode{\"v5uniform\"} and @qcode{\"v5normal\"} refer to\n## older versions of Octave that used to use a different random number\n## generator.\n##\n## The state or seed of the random number generator can be reset to a new\n## random value using the @qcode{\"shuffle\"} keyword.\n##\n## The random number generator can be reset to default values using the\n## @qcode{\"default\"} keyword.  The default values are to use the Mersenne\n## Twister generator with a seed of 0.\n##\n## The optional return value @var{s} contains the state of the random number\n## generator at the time the function is called (i.e., before it might be\n## modified according to the input arguments).  It is encoded as a structure\n## variable with three fields: @qcode{\"Type\"}, @qcode{\"Seed\"}, and\n## @qcode{\"State\"}.  The random number generator can be restored to the state\n## @var{s} using @code{rng (@var{s})}.  This is useful when the identical\n## sequence of pseudo-random numbers is required for an algorithm.\n##\n## By default, and with the @qcode{\"twister\"} option, pseudo-random sequences\n## are computed using the Mersenne Twister with a period of @math{2^{19937}-1}\n## (See @nospell{M. Matsumoto and T. Nishimura},\n## \"Mersenne Twister: A 623-dimensionally equidistributed uniform pseudorandom\n## number generator\",\n## @cite{@nospell{ACM Trans.@: on Modeling and Computer Simulation}},\n## @w{Vol.@: 8}, @w{No.@: 1}, @w{pp.@: 3}--30, January 1998,\n## @url{http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html}).\n## Do @strong{not} use for cryptography without securely hashing several\n## returned values together, otherwise the generator state can be learned after\n## reading 624 consecutive values.\n##\n## @seealso{rand, randn}\n## @end deftypefn\n\nfunction s = rng (varargin)\n\n  if (nargin > 2)\n    print_usage ();\n  endif\n\n  ## Store current settings of random number generator\n  ## FIXME: there doesn't seem to be a way to query the type of generator\n  ##        currently used in Octave - assume \"twister\".\n  ## FIXME: there doesn't seem to be a way to query the seed initialization\n  ##        value - use \"Not applicable\".\n  ## FIXME: rand and randn use different generators - storing both states.\n  ## For older Matlab generators (v4, v5), the settings are stored like this:\n  ##   struct (\"Type\",\"Legacy\", \"Seed\", \"Not applicable\", \"State\",{[],[],...})\n\n  ## Type is the generator name.\n  ## Seed is the initial seed value.\n  ## State is a structure describing internal state of the generator.\n  srng = struct (\"Type\", \"twister\",\n                 \"Seed\", \"Not applicable\",\n                 \"State\", {{rand(\"state\"), randn(\"state\")}});\n\n  if (nargin == 0)\n    s = srng;\n    return;\n  endif\n\n  arg1 = varargin{1};\n  if (isscalar (arg1) && isnumeric (arg1) && isreal (arg1) && arg1 >= 0)\n    s_rand = s_randn = arg1;\n    generator = check_generator (varargin(2:end));\n\n  elseif (ischar (arg1) && strcmpi (arg1, \"shuffle\"))\n    ## Seed the random number generator based on the current time\n    s_rand = s_randn = \"reset\";  # or sum (1000*clock)\n    generator = check_generator (varargin(2:end));\n\n  elseif (ischar (arg1) && strcmpi (arg1, \"default\") && nargin == 1)\n    generator = \"twister\";\n    s_rand = s_randn = 0;  # FIXME: In Matlab, seed 0 corresponds to 5489\n\n  elseif (isstruct (arg1) && isscalar (arg1) && nargin == 1)\n    if (numfields (arg1) != 3\n        || ! all (isfield (arg1, {\"Type\", \"Seed\", \"State\"})))\n      error ('rng: input structure requires \"Type\", \"Seed\", \"State\" fields\"');\n    endif\n    ## Only the internal state \"State\" and generator type \"Type\" are needed\n    generator = arg1.Type;\n    if (iscell (arg1.State))\n      [s_rand, s_randn] = deal (arg1.State{:});\n    else\n      s_rand = s_randn = arg1.State;\n    endif\n\n  else\n    print_usage ();\n  endif\n\n  ## Set the type of random number generator and seed it\n  if (isempty (generator))\n    generator = srng.Type;\n  endif\n  switch (generator)\n    case \"twister\"\n      rand (\"state\", s_rand);\n      randn (\"state\", s_randn);\n\n    case \"legacy\"\n      rand (\"seed\", s_rand);\n      randn (\"seed\", s_randn);\n\n    case \"v5uniform\"\n      rand (\"seed\", s_rand);\n\n    case \"v5normal\"\n      randn (\"seed\", s_randn);\n\n    otherwise\n      error ('rng: invalid GENERATOR: \"%s\"', generator);\n\n  endswitch\n\n  if (nargout > 0)\n    s = srng;\n  endif\n\nendfunction\n\n\nfunction gen = check_generator (val)\n\n  if (isempty (val))\n    gen = \"\";\n    return;\n  elseif (! iscellstr (val))\n    error (\"rng: GENERATOR must be a string\");\n  endif\n\n  gen = lower (char (val));\n  if (any (strcmp (gen, {\"simdtwister\", \"combrecursive\", \"philox\", \"threefry\", \"multfibonacci\", \"v4\"})))\n    error ('rng: random number generator \"%s\" is not available in Octave', gen);\n  elseif (! any (strcmp (gen, {\"twister\", \"v5uniform\", \"v5normal\"})))\n    error ('rng: unknown random number generator \"%s\"', gen);\n  endif\n\nendfunction\n\n\n%!test\n%! state = rng ();\n%! unwind_protect\n%!   rng (42);\n%!   ru1 = rand ();\n%!   rn1 = randn ();\n%!   rng (42);\n%!   ru2 = rand ();\n%!   rn2 = randn ();\n%!   assert (ru2, ru1);\n%!   assert (rn2, rn1);\n%!   s1 = rng ();\n%!   s2 = rng (42);\n%!   assert (isequal (s1, s2));\n%!   ru1 = rand ();\n%!   rn1 = randn ();\n%!   s3 = rng (42);\n%!   ru2 = rand ();\n%!   rn2 = randn ();\n%!   assert (ru2, ru1);\n%!   assert (rn2, rn1);\n%! unwind_protect_cleanup\n%!   rng (state);\n%! end_unwind_protect\n\n%!test\n%! state = rng ();\n%! unwind_protect\n%!   rng (42, \"twister\");\n%!   ru1 = rand ();\n%!   rn1 = randn ();\n%!   rng (42, \"twister\");\n%!   ru2 = rand ();\n%!   rn2 = randn ();\n%!   assert (ru2, ru1);\n%!   assert (rn2, rn1);\n%!   s1 = rng ();\n%!   s2 = rng (42, \"twister\");\n%!   assert (isequal (s1, s2));\n%!   ru1 = rand ();\n%!   rn1 = randn ();\n%!   s3 = rng (42, \"twister\");\n%!   ru2 = rand ();\n%!   rn2 = randn ();\n%!   assert (ru2, ru1);\n%!   assert (rn2, rn1);\n%! unwind_protect_cleanup\n%!   rng (state);\n%! end_unwind_protect\n\n%!test\n%! state = rng ();\n%! unwind_protect\n%!   rng (\"shuffle\");\n%!   rng (\"shuffle\", \"twister\");\n%!   s = rng (\"shuffle\");\n%!   assert (! isequal (s, rng (\"shuffle\")));\n%!   s = rng (\"shuffle\", \"twister\");\n%!   assert (! isequal (s, rng (\"shuffle\", \"twister\")));\n%! unwind_protect_cleanup\n%!   rng (state);\n%! end_unwind_protect\n\n%!test\n%! state = rng ();\n%! unwind_protect\n%!   rng (\"default\");\n%!   ru1 = rand ();\n%!   rn1 = randn ();\n%!   rng (0, \"twister\");\n%!   ru2 = rand ();\n%!   rn2 = randn ();\n%!   assert (ru2, ru1);\n%!   assert (rn2, rn1);\n%!   rng (0, \"twister\");\n%!   s = rng (\"default\");\n%!   assert (isequal (s, rng ()));\n%! unwind_protect_cleanup\n%!   rng (state);\n%! end_unwind_protect\n\n%!test\n%! state = rng ();\n%! unwind_protect\n%!   s = rng ();\n%!   ru1 = rand ();\n%!   rn1 = randn ();\n%!   rng (s);\n%!   ru2 = rand ();\n%!   rn2 = randn ();\n%!   assert (ru2, ru1);\n%!   assert (rn2, rn1);\n%!   rng (42);  rand (1,2);  x = rand (1,2);\n%!   rng (42);  rand (1,2);  s = rng ();  y = rand (1,2);\n%!   assert (x, y);\n%!   rng (s);  z = rand (1,2);\n%!   assert (x, z);\n%!   s1 = rng ();\n%!   s2 = rng (s1);\n%!   assert (isequal (s1, s2));\n%! unwind_protect_cleanup\n%!   rng (state);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> rng (1, 2, 3)\n%!error <Invalid call> rng (eye (2))\n%!error <Invalid call> rng ({})\n%!error <Invalid call> rng (2i)\n%!error <Invalid call> rng (-2)\n%!error <Invalid call> rng (\"foobar\")\n%!error <Invalid call> rng (\"default\", \"twister\")\n%!error <Invalid call> rng (struct (\"Seed\", {1, 2}))\n%!error <Invalid call> rng (struct (\"Type\",[],\"State\",[],\"Seed\",[]), \"twister\")\n%!error <input structure requires \"Type\"> rng (struct ())\n%!error <input structure requires \"Type\">\n%! rng (struct (\"Type1\",[],\"State\",[],\"Seed\",[]));\n%!error <GENERATOR must be a string> rng (0, struct ())\n%!error <\"philox\" is not available in Octave> rng (0, \"philox\")\n%!error <GENERATOR must be a string> rng (\"shuffle\", struct ())\n%!error <unknown random number generator \"foobar\"> rng (\"shuffle\", \"foobar\")\n"
  },
  {
    "path": "scripts/general/rot90.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} rot90 (@var{A})\n## @deftypefnx {} {@var{B} =} rot90 (@var{A}, @var{k})\n## Rotate array by 90 degree increments.\n##\n## Return a copy of @var{A} with the elements rotated counterclockwise in\n## 90-degree increments.\n##\n## The second argument is optional, and specifies how many 90-degree rotations\n## are to be applied (the default value is 1).  Negative values of @var{k}\n## rotate the matrix in a clockwise direction.\n## For example,\n##\n## @example\n## @group\n## rot90 ([1, 2; 3, 4], -1)\n##     @xresult{}  3  1\n##         4  2\n## @end group\n## @end example\n##\n## @noindent\n## rotates the given matrix clockwise by 90 degrees.  The following are all\n## equivalent statements:\n##\n## @example\n## @group\n## rot90 ([1, 2; 3, 4], -1)\n## rot90 ([1, 2; 3, 4], 3)\n## rot90 ([1, 2; 3, 4], 7)\n## @end group\n## @end example\n##\n## The rotation is always performed on the plane of the first two dimensions,\n## i.e., rows and columns.  To perform a rotation on any other plane, use\n## @code{rotdim}.\n##\n## @seealso{rotdim, fliplr, flipud, flip}\n## @end deftypefn\n\nfunction B = rot90 (A, k = 1)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (k) && isreal (k) && k == fix (k)))\n    error (\"rot90: K must be a single real integer\");\n  endif\n\n  k = mod (k, 4);\n  nd = ndims (A);\n\n  if (k == 0)\n    B = A;\n  elseif (k == 1)\n    B = flipud (permute (A, [2 1 3:1:nd]));\n  elseif (k == 2)\n    idx(1:nd) = {':'};\n    idx{1} = rows (A):-1:1;\n    idx{2} = columns (A):-1:1;\n    B = A(idx{:});\n  elseif (k == 3)\n    B = permute (flipud (A), [2 1 3:1:nd]);\n  else\n    error (\"rot90: internal error!\");\n  endif\n\nendfunction\n\n\n%!test\n%! x1 = [1, 2; 3, 4];\n%! x2 = [2, 4; 1, 3];\n%! x3 = [4, 3; 2, 1];\n%! x4 = [3, 1; 4, 2];\n%!\n%! assert (rot90 (x1), x2);\n%! assert (rot90 (x1, 2), x3);\n%! assert (rot90 (x1, 3), x4);\n%! assert (rot90 (x1, 4), x1);\n%! assert (rot90 (x1, 5), x2);\n%! assert (rot90 (x1, -1), x4);\n\n## Test NDArrays\n%!test\n%! a(1:2,1:2,1) = [1 2; 3 4];\n%! a(1:2,1:2,2) = [5 6; 7 8];\n%! b(1:2,1:2,1) = [2 4; 1 3];\n%! b(1:2,1:2,2) = [6 8; 5 7];\n%! assert (rot90 (a, 1), b);\n%! assert (rot90 (a, 2), rot90 (b, 1));\n%! assert (rot90 (a, 3), rot90 (b, 2));\n\n%!test\n%! a = b = zeros (2, 2, 1, 2);\n%! a(1:2,1:2,:,1) = [1 2; 3 4];\n%! a(1:2,1:2,:,2) = [5 6; 7 8];\n%! b(1:2,1:2,:,1) = [2 4; 1 3];\n%! b(1:2,1:2,:,2) = [6 8; 5 7];\n%! assert (rot90 (a, 1), b);\n%! assert (rot90 (a, 2), rot90 (b, 1));\n%! assert (rot90 (a, 3), rot90 (b, 2));\n\n## With non-square matrices\n%!test\n%! a = zeros (3, 2, 1, 2);\n%! b = zeros (2, 3, 1, 2);\n%! a(1:2,1:3,:,1) = [ 1  2  3;  4  5  6];\n%! a(1:2,1:3,:,2) = [ 7  8  9; 10 11 12];\n%! b(1:3,1:2,:,1) = [ 3  6;  2  5;  1  4];\n%! b(1:3,1:2,:,2) = [ 9 12;  8 11;  7 10];\n%! assert (rot90 (a, 1), b);\n%! assert (rot90 (a, 2), rot90 (b, 1));\n%! assert (rot90 (a, 3), rot90 (b, 2));\n\n## Test input validation\n%!error <Invalid call> rot90 ()\n%!error rot90 (1, ones (2))\n%!error rot90 (1, 1.5)\n%!error rot90 (1, 1+i)\n"
  },
  {
    "path": "scripts/general/rotdim.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} rotdim (@var{A})\n## @deftypefnx {} {@var{B} =} rotdim (@var{A}, @var{n})\n## @deftypefnx {} {@var{B} =} rotdim (@var{A}, @var{n}, @var{plane})\n## Return a copy of @var{A} with the elements rotated counterclockwise in\n## 90-degree increments.\n##\n## The second argument @var{n} is optional, and specifies how many 90-degree\n## rotations are to be applied (the default value is 1).  Negative values of\n## @var{n} rotate the matrix in a clockwise direction.\n##\n## The third argument is also optional and defines the plane of the rotation.\n## If present, @var{plane} is a two element vector containing two different\n## valid dimensions of the matrix.  When @var{plane} is not given the first two\n## non-singleton dimensions are used.\n##\n## For example,\n##\n## @example\n## @group\n## rotdim ([1, 2; 3, 4], -1, [1, 2])\n##      @xresult{}  3  1\n##          4  2\n## @end group\n## @end example\n##\n## @noindent\n## rotates the given matrix clockwise by 90 degrees.  The following are all\n## equivalent statements:\n##\n## @example\n## @group\n## rotdim ([1, 2; 3, 4], -1, [1, 2])\n## rotdim ([1, 2; 3, 4], 3, [1, 2])\n## rotdim ([1, 2; 3, 4], 7, [1, 2])\n## @end group\n## @end example\n## @seealso{rot90, fliplr, flipud, flip}\n## @end deftypefn\n\nfunction B = rotdim (A, n, plane)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin > 1 && ! isempty (n))\n    if (! isscalar (n) || ! isreal (n) || fix (n) != n)\n      error (\"rotdim: N must be a scalar integer\");\n    endif\n  else\n    n = 1;\n  endif\n\n  nd = ndims (A);\n  sz = size (A);\n  if (nargin < 3)\n    if (nd > 2)\n      ## Find the first two non-singleton dimension.\n      plane = [];\n      dim = 0;\n      while (dim < nd)\n        dim += 1;\n        if (sz (dim) != 1)\n          plane = [plane, dim];\n          if (length (plane) == 2)\n            break;\n          endif\n        endif\n      endwhile\n      if (length (plane) < 1)\n        plane = [1, 2];\n      elseif (length (plane) < 2)\n        plane = [1, plane];\n      endif\n    else\n      plane = [1, 2];\n    endif\n  else\n    if (! (isvector (plane) && length (plane) == 2\n           && all (plane == fix (plane)) && all (plane > 0)\n           && all (plane < (nd + 1)) && plane(1) != plane(2)))\n      error (\"rotdim: PLANE must be a 2-element integer vector defining a valid plane\");\n    endif\n  endif\n\n  n = rem (n, 4);\n  if (n < 0)\n    n += 4;\n  endif\n  if (n == 0)\n    B = A;\n  elseif (n == 2)\n    B = flip (flip (A, plane(1)), plane(2));\n  elseif (n == 1 || n == 3)\n    perm = 1:nd;\n    perm(plane(1)) = plane(2);\n    perm(plane(2)) = plane(1);\n    B = permute (A, perm);\n    if (n == 1)\n      B = flip (B, min (plane));\n    else\n      B = flip (B, max (plane));\n    endif\n  endif\n\nendfunction\n\n\n%!shared r, rr\n%! r = [1,2,3];  rr = [3,2,1];\n%!assert (rotdim (r, 0), r)\n%!assert (rotdim (r, 1), rr')\n%!assert (rotdim (r, 2), rr)\n%!assert (rotdim (r, 3), r')\n%!assert (rotdim (r, 3), rotdim (r, -1))\n%!assert (rotdim (r, 1), rotdim (r))\n\n%!shared c, cr\n%! c = [1;2;3];  cr = [3;2;1];\n%!assert (rotdim (c, 0), c)\n%!assert (rotdim (c, 1), c')\n%!assert (rotdim (c, 2), cr)\n%!assert (rotdim (c, 3), cr')\n%!assert (rotdim (c, 3), rotdim (c, -1))\n%!assert (rotdim (c, 1), rotdim (c))\n\n%!shared m\n%! m = [1,2;3,4];\n%!assert (rotdim (m, 0), m)\n%!assert (rotdim (m, 1), [2,4;1,3])\n%!assert (rotdim (m, 2), [4,3;2,1])\n%!assert (rotdim (m, 3), [3,1;4,2])\n%!assert (rotdim (m, 3), rotdim (m, -1))\n%!assert (rotdim (m, 1), rotdim (m))\n\n## FIXME: We need tests for multi-dimensional arrays\n##        and different values of PLANE.\n\n%!error <Invalid call> rotdim ()\n"
  },
  {
    "path": "scripts/general/shiftdim.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} shiftdim (@var{x}, @var{n})\n## @deftypefnx {} {[@var{y}, @var{ns}] =} shiftdim (@var{x})\n## Shift the dimensions of @var{x} by @var{n}, where @var{n} must be\n## an integer scalar.\n##\n## When @var{n} is positive, the dimensions of @var{x} are shifted to the left,\n## with the leading dimensions circulated to the end.  If @var{n} is negative,\n## then the dimensions of @var{x} are shifted to the right, with @var{n}\n## leading singleton dimensions added.\n##\n## Called with a single argument, @code{shiftdim}, removes the leading\n## singleton dimensions, returning the number of dimensions removed in the\n## second output argument @var{ns}.\n##\n## For example:\n##\n## @example\n## @group\n## x = ones (1, 2, 3);\n## size (shiftdim (x, -1))\n##   @xresult{}   1   1   2   3\n## size (shiftdim (x, 1))\n##   @xresult{}   2   3\n## [b, ns] = shiftdim (x)\n##   @xresult{} b =\n##         1   1   1\n##         1   1   1\n##   @xresult{} ns = 1\n## @end group\n## @end example\n## @seealso{reshape, permute, ipermute, circshift, squeeze}\n## @end deftypefn\n\nfunction [y, ns]  = shiftdim (x, n)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  nd = ndims (x);\n  orig_dims = size (x);\n\n  if (nargin == 1)\n    ## Find the first non-singleton dimension.\n    (n = find (orig_dims != 1, 1) - 1) || (n = nd);\n  elseif (! (isscalar (n) && n == fix (n)))\n    error (\"shiftdim: N must be a scalar integer\");\n  endif\n\n  if (n >= nd)\n    n = rem (n, nd);\n  endif\n\n  if (n < 0)\n    singleton_dims = ones (1, -n);\n    y = reshape (x, [singleton_dims, orig_dims]);\n  elseif (n > 0)\n    ## We need permute here instead of reshape to shift values in a\n    ## compatible way.\n    y = permute (x, [n+1:nd 1:n]);\n  else\n    y = x;\n  endif\n\n  ns = n;\n\nendfunction\n\n\n%!test\n%! x = rand (1, 1, 4, 2);\n%! [y, ns] = shiftdim (x);\n%! assert (size (y), [4 2]);\n%! assert (ns, 2);\n%! assert (shiftdim (y, -2), x);\n%! assert (size (shiftdim (x, 2)), [4 2]);\n\n%!assert (size (shiftdim (rand (0, 1, 2))), [0 1 2])\n\n## Test input validation\n%!error <Invalid call> shiftdim ()\n%!error shiftdim (1, ones (2))\n%!error shiftdim (1, 1.5)\n"
  },
  {
    "path": "scripts/general/sortrows.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{s}, @var{i}] =} sortrows (@var{A})\n## @deftypefnx {} {[@var{s}, @var{i}] =} sortrows (@var{A}, @var{c})\n## Sort the rows of the matrix @var{A} according to the order of the columns\n## specified in @var{c}.\n##\n## By default (@var{c} omitted, or a particular column unspecified in @var{c})\n## an ascending sort order is used.  However, if elements of @var{c} are\n## negative then the corresponding column is sorted in descending order.  If\n## the elements of @var{A} are strings then a lexicographical sort is used.\n##\n## Example: sort by column 2 in descending order, then 3 in ascending order\n##\n## @example\n## @group\n## x = [ 7, 1, 4;\n##       8, 3, 5;\n##       9, 3, 6 ];\n## sortrows (x, [-2, 3])\n##    @xresult{} 8  3  5\n##       9  3  6\n##       7  1  4\n## @end group\n## @end example\n##\n## @seealso{sort}\n## @end deftypefn\n\nfunction [s, i] = sortrows (A, c)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 2)\n    if (! (isnumeric (c) && isvector (c)))\n      error (\"sortrows: C must be a numeric vector\");\n    elseif (any (c == 0) || any (abs (c) > columns (A)))\n      error (\"sortrows: all elements of C must be in the range [1, columns (A)]\");\n    endif\n  endif\n\n  default_mode = \"ascend\";\n  reverse_mode = \"descend\";\n\n  if (issparse (A) || iscell (A))\n    ## FIXME: Eliminate this case once __sort_rows_idx__ is fixed to\n    ##        handle sparse matrices.\n    if (nargin == 1)\n      i = sort_rows_idx_generic (default_mode, reverse_mode, A);\n    else\n      i = sort_rows_idx_generic (default_mode, reverse_mode, A, c);\n    endif\n  elseif (nargin == 1)\n    i = __sort_rows_idx__ (A, default_mode);\n  elseif (all (c > 0))\n    i = __sort_rows_idx__ (A(:,c), default_mode);\n  elseif (all (c < 0))\n    i = __sort_rows_idx__ (A(:,-c), reverse_mode);\n  else\n    ## Otherwise, fall back to the old algorithm.\n    i = sort_rows_idx_generic (default_mode, reverse_mode, A, c);\n  endif\n\n  s = A(i,:);\n\nendfunction\n\nfunction i = sort_rows_idx_generic (default_mode, reverse_mode, m, c)\n\n  if (nargin == 3)\n    indices = [1:columns(m)]';\n    mode(1:columns(m)) = {default_mode};\n  else\n    for j = 1:length (c)\n      if (c(j) < 0)\n        mode{j} = reverse_mode;\n      else\n        mode{j} = default_mode;\n      endif\n    endfor\n    indices = abs (c(:));\n  endif\n\n  ## Since sort is 'stable' the order of identical elements will be\n  ## preserved, so by traversing the sort indices in reverse order we\n  ## will make sure that identical elements in index i are subsorted by\n  ## index j.\n  indices = flipud (indices);\n  mode = flipud (mode');\n  i = [1:rows(m)]';\n  for j = 1:length (indices)\n    M = m(i, indices(j));\n    if (iscell (M) && ! iscellstr (M))\n      M = cell2mat (M);\n    endif\n    [~, idx] = sort (M, mode{j});\n    i = i(idx);\n  endfor\n\nendfunction\n\n\n%!test\n%! m = [1, 1; 1, 2; 3, 6; 2, 7];\n%! c = [1, -2];\n%! [x, idx] = sortrows (m, c);\n%! [sx, sidx] = sortrows (sparse (m), c);\n%! assert (x, [1, 2; 1, 1; 2, 7; 3, 6]);\n%! assert (idx, [2; 1; 4; 3]);\n%! assert (issparse (sx));\n%! assert (x, full (sx));\n%! assert (idx, sidx);\n\n%!test\n%! m = [1, 0, 0, 4];\n%! c = 1;\n%! [x, idx] = sortrows (m, c);\n%! [sx, sidx] = sortrows (sparse (m), c);\n%! assert (x, m);\n%! assert (idx, 1);\n%! assert (issparse (sx));\n%! assert (x, full (sx));\n%! assert (idx, sidx);\n\n%!test <*42523>\n%! C = {1, 2, \"filename1\";\n%!      3, 4, \"filename2\";\n%!      5, 6, \"filename3\"};\n%! C2 = sortrows (C, -1);\n%! assert (C2, flipud (C));\n\n## Test input validation\n%!error <Invalid call> sortrows ()\n%!error sortrows (1, \"ascend\")\n%!error sortrows (1, ones (2,2))\n%!error sortrows (1, 0)\n%!error sortrows (1, 2)\n"
  },
  {
    "path": "scripts/general/sph2cart.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{x}, @var{y}, @var{z}] =} sph2cart (@var{theta}, @var{phi}, @var{r})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} sph2cart (@var{S})\n## Transform spherical coordinates to Cartesian coordinates.\n##\n## The inputs @var{theta}, @var{phi}, and @var{r} must be the same shape, or\n## scalar.  If called with a single matrix argument then each row of @var{S}\n## must represent a spherical coordinate triplet (@var{theta}, @var{phi},\n## @var{r}).\n##\n## The outputs @var{x}, @var{y}, @var{z} match the shape of the inputs.  For a\n## matrix input @var{S} the outputs are column vectors with rows corresponding\n## to the rows of the input matrix.\n##\n## @var{theta} describes the azimuth angle relative to the positive x-axis\n## measured in the xy-plane.\n##\n## @var{phi} is the elevation angle measured relative to the xy-plane.\n##\n## @var{r} is the distance to the origin @w{(0, 0, 0)}.\n##\n## The coordinate transformation is computed using:\n## @tex\n## $$ x = r \\cos \\phi  \\cos \\theta $$\n## $$ y = r \\cos \\phi  \\sin \\theta $$\n## $$ z = r \\sin \\phi $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## @var{x} = r * cos (@var{phi}) * cos (@var{theta})\n## @var{y} = r * cos (@var{phi}) * sin (@var{theta})\n## @var{z} = r * sin (@var{phi})\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @seealso{cart2sph, pol2cart, cart2pol}\n## @end deftypefn\n\nfunction [x, y, z] = sph2cart (theta, phi, r)\n\n  if (nargin != 1 && nargin != 3)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    if (! (isnumeric (theta) && ismatrix (theta)))\n      error (\"sph2cart: matrix input must be a 2-D numeric array\");\n    endif\n    if (columns (theta) != 3 && numel (theta) != 3)\n      error (\"sph2cart: matrix input must be a 3-element vector or 3-column array\");\n    endif\n\n    if (numel (theta) == 3)\n      r = theta(3);\n      phi = theta(2);\n      theta = theta(1);\n    else\n      r = theta(:,3);\n      phi = theta(:,2);\n      theta = theta(:,1);\n    endif\n\n  else\n    if (! (isnumeric (theta) && isnumeric (phi) && isnumeric (r)))\n      error (\"sph2cart: THETA, PHI, R must be numeric arrays or scalars\");\n    endif\n    [err, theta, phi, r] = common_size (theta, phi, r);\n    if (err)\n      error (\"sph2cart: THETA, PHI, R must be the same size or scalars\");\n    endif\n  endif\n\n  x = r .* cos (phi) .* cos (theta);\n  y = r .* cos (phi) .* sin (theta);\n  z = r .* sin (phi);\n\nendfunction\n\n\n%!test\n%! t = [0, 0, 0];\n%! p = [0, 0, 0];\n%! r = [0, 1, 2];\n%! [x, y, z] = sph2cart (t, p, r);\n%! assert (x, r);\n%! assert (y, [0, 0, 0]);\n%! assert (z, [0, 0, 0]);\n\n%!test\n%! t = [0; 0; 0];\n%! p = [0; 0; 0];\n%! r = [0; 1; 2];\n%! [x, y, z] = sph2cart (t, p, r);\n%! assert (x, [0; 1; 2]);\n%! assert (y, [0; 0; 0]);\n%! assert (z, [0; 0; 0]);\n\n%!test\n%! t = 0;\n%! p = [0, 0, 0];\n%! r = [0, 1, 2];\n%! [x, y, z] = sph2cart (t, p, r);\n%! assert (x, [0, 1, 2]);\n%! assert (y, [0, 0, 0]);\n%! assert (z, [0, 0, 0]);\n\n%!test\n%! t = [0, 0, 0];\n%! p = 0;\n%! r = [0, 1, 2];\n%! [x, y, z] = sph2cart (t, p, r);\n%! assert (x, r);\n%! assert (y, [0, 0, 0]);\n%! assert (z, [0, 0, 0]);\n\n%!test\n%! t = [0, 0.5, 1]*pi;\n%! p = [0, 0, 0];\n%! r = 1;\n%! [x, y, z] = sph2cart (t, p, r);\n%! assert (x, [1, 0, -1], eps);\n%! assert (y, [0, 1, 0], eps);\n%! assert (z, [0, 0, 0], eps);\n\n%!test\n%! [x, y, z] = sph2cart ([0 0 0], 0, 1);\n%! assert (x, [1, 1, 1], eps);\n%! assert (y, [0, 0, 0], eps);\n%! assert (z, [0, 0, 0], eps);\n\n%!test\n%! S = [ 0, 0, 1; 0.5*pi, 0, 1; pi, 0, 1];\n%! [x, y, z] = sph2cart (S);\n%! assert (x, [1; 0; -1], eps);\n%! assert (y, [0; 1; 0], eps);\n%! assert (z, [0; 0; 0], eps);\n\n%!test\n%! S = [ 0, 0, 1; 0.5*pi, 0, 1; pi, 0, 1; pi, pi, 1];\n%! [x, y, z] = sph2cart (S);\n%! assert (x, [1; 0; -1; 1], eps);\n%! assert (y, [0; 1; 0; 0], eps);\n%! assert (z, [0; 0; 0; 0], eps);\n\n\n%!test\n%! [t, p, r] = meshgrid ([0, pi/2], [0, pi/2], [0, 1]);\n%! [x, y, z] = sph2cart (t, p, r);\n%! X = zeros (2, 2, 2);\n%! X(1, 1, 2) = 1;\n%! Y = zeros (2, 2, 2);\n%! Y(1, 2, 2) = 1;\n%! Z = zeros (2, 2, 2);\n%! Z(2, :, 2) = [1 1];\n%! assert (x, X, eps);\n%! assert (y, Y, eps);\n%! assert (z, Z);\n\n## Test input validation\n%!error <Invalid call> sph2cart ()\n%!error <Invalid call> sph2cart (1,2)\n%!error <matrix input must be a 2-D numeric array> sph2cart ({1,2,3})\n%!error <matrix input must be a 2-D numeric array> sph2cart (ones (3,3,2))\n%!error <matrix input must be a 3-element> sph2cart ([1,2,3,4])\n%!error <matrix input must be a 3-element> sph2cart ([1,2,3,4; 1,2,3,4; 1,2,3,4])\n%!error <must be numeric arrays or scalars> sph2cart ({1,2,3}, [1,2,3], [1,2,3])\n%!error <must be numeric arrays or scalars> sph2cart ([1,2,3], {1,2,3}, [1,2,3])\n%!error <must be numeric arrays or scalars> sph2cart ([1,2,3], [1,2,3], {1,2,3})\n%!error <must be the same size or scalars> sph2cart ([1,2,3], [1,2,3], [1,2,3]')\n%!error <must be the same size or scalars> sph2cart (ones (3,3,3), 1, ones (3,2,3))\n%!error <must be the same size or scalars> sph2cart (ones (3,3,3), ones (3,2,3), 1)\n"
  },
  {
    "path": "scripts/general/structfun.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{A} =} structfun (@var{fcn}, @var{S})\n## @deftypefnx {} {@var{A} =} structfun (@dots{}, \"ErrorHandler\", @var{errfcn})\n## @deftypefnx {} {@var{A} =} structfun (@dots{}, \"UniformOutput\", @var{val})\n## @deftypefnx {} {[@var{A}, @var{B}, @dots{}] =} structfun (@dots{})\n##\n## Evaluate the function named @var{name} on the fields of the structure\n## @var{S}.  The fields of @var{S} are passed to the function @var{fcn}\n## individually.\n##\n## @code{structfun} accepts an arbitrary function @var{fcn} in the form of an\n## inline function, function handle, or the name of a function (in a character\n## string).  In the case of a character string argument, the function must\n## accept a single argument named @var{x}, and it must return a string value.\n## If the function returns more than one argument, they are returned as\n## separate output variables.\n##\n## If the parameter @qcode{\"UniformOutput\"} is set to true (the default), then\n## the function must return a single element which will be concatenated into\n## the return value.  If @qcode{\"UniformOutput\"} is false, the outputs are\n## placed into a structure with the same fieldnames as the input structure.\n##\n## @example\n## @group\n## s.name1 = \"John Smith\";\n## s.name2 = \"Jill Jones\";\n## structfun (@@(x) regexp (x, '(\\w+)$', \"matches\")@{1@}, s,\n##            \"UniformOutput\", false)\n##   @xresult{} scalar structure containing the fields:\n##        name1 = Smith\n##        name2 = Jones\n## @end group\n## @end example\n##\n## Given the parameter @qcode{\"ErrorHandler\"}, @var{errfcn} defines a function\n## to call in case @var{fcn} generates an error.  The form of the function is\n##\n## @example\n## function [@dots{}] = errfcn (@var{se}, @dots{})\n## @end example\n##\n## @noindent\n## where there is an additional input argument to @var{errfcn} relative to\n## @var{fcn}, given by @nospell{@var{se}}.  This is a structure with the\n## elements @qcode{\"identifier\"}, @qcode{\"message\"} and @qcode{\"index\"},\n## giving respectively the error identifier, the error message, and the index\n## into the input arguments of the element that caused the error.  For an\n## example on how to use an error handler, @pxref{XREFcellfun,,@code{cellfun}}.\n##\n## @seealso{cellfun, arrayfun, spfun}\n## @end deftypefn\n\nfunction varargout = structfun (fcn, S, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  nargs = length (varargin);\n\n  recognized_opts = {\"UniformOutput\", \"ErrorHandler\"};\n  uo_str = recognized_opts{1};\n\n  uniform_output = true;\n\n  while (nargs >= 2)\n    opt_match = strcmpi (varargin{nargs-1}, recognized_opts);\n    if (opt_match(1))\n      uniform_output = varargin{nargs};\n    endif\n    if (any (opt_match))\n      nargs -= 2;\n    else\n      break;\n    endif\n  endwhile\n\n  if (nargs > 0)\n    error (\"structfun: invalid options\");\n  endif\n\n  varargout_defined = true;\n\n  if (nargout == 0)\n    ## ANS should not normally be defined here, but just in case someone\n    ## changes the code above so that it could be...\n    clear (\"ans\");\n    cellfun (fcn, struct2cell (S), varargin{:});\n    if (exist (\"ans\", \"var\"))\n      varargout = {ans};\n    else\n      varargout_defined = false;\n    endif\n  else\n    varargout = cell (max ([nargout, 1]), 1);\n    [varargout{:}] = cellfun (fcn, struct2cell (S), varargin{:});\n  endif\n\n  if (! uniform_output && varargout_defined)\n    varargout = cellfun (\"cell2struct\", varargout, {fieldnames(S)}, {1}, ...\n                         uo_str, false);\n  endif\n\nendfunction\n\n\n%!test\n%! s.name1 = \"John Smith\";\n%! s.name2 = \"Jill Jones\";\n%! l.name1 = \"Smith\";\n%! l.name2 = \"Jones\";\n%! o = structfun (@(x) regexp (x, '(\\w+)$', \"matches\"){1}, s,\n%!                \"UniformOutput\", false);\n%! assert (o, l);\n\n%!function [a, b] = __twoouts (x)\n%!  a = x + x;\n%!  b = x * x;\n%!endfunction\n\n%!test\n%! s = struct (\"a\", {1, 2, 3}, \"b\", {4, 5, 6});\n%! c(1:2, 1, 1) = [2; 8];\n%! c(1:2, 1, 2) = [4; 10];\n%! c(1:2, 1, 3) = [6; 12];\n%! d(1:2, 1, 1) = [1; 16];\n%! d(1:2, 1, 2) = [4; 25];\n%! d(1:2, 1, 3) = [9; 36];\n%! [aa, bb] = structfun (@__twoouts, s);\n%! assert (aa, c);\n%! assert (bb, d);\n\n%!test\n%! s = struct (\"a\", {1, 2, 3}, \"b\", {4, 5, 6});\n%! c = struct (\"a\", {2, 4, 6}, \"b\", {8, 10, 12});\n%! d = struct (\"a\", {1, 4, 9}, \"b\", {16, 25, 36});\n%! [aa, bb] = structfun (@__twoouts, s, \"UniformOutput\", false);\n%! assert (aa, c);\n%! assert (bb, d);\n\n%!function __zeroout(x)\n%!endfunction;\n\n%!test <66617>\n%! s.a = 3;\n%! clear (\"ans\");\n%! structfun (@__zeroout, s);\n%! assert (! exist (\"ans\", \"var\"));\n\n%!test <66617>\n%! s.a = 3;\n%! clear (\"ans\");\n%! structfun (@__zeroout, s, \"UniformOutput\", false);\n%! assert (! exist (\"ans\", \"var\"));\n\n%!test <66617>\n%! s = struct (\"a\", 1, \"b\", 4);\n%! clear (\"ans\");\n%! structfun (@deal, s);\n%! assert (! exist (\"ans\", \"var\"));\n\n%!test\n%! s = struct (\"a\", 1, \"b\", 4);\n%! a = structfun (@deal, s);\n%! assert (a, [1; 4]);\n\n%!test\n%! s = struct (\"a\", 1, \"b\", 4);\n%! [a, b] = structfun (@deal, s);\n%! assert ([a, b], [1, 1; 4, 4]);\n\n%!test <66617>\n%! s = struct ();\n%! clear (\"ans\");\n%! structfun (@(z) z, s);\n%! assert (! exist (\"ans\", \"var\"));\n\n%!test <66617>\n%! s = struct;\n%! y = structfun (@(z) z, s);\n%! assert (y, zeros (0, 1));\n"
  },
  {
    "path": "scripts/general/subsindex.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{idx} =} subsindex (@var{obj})\n## Convert an object to an index vector.\n##\n## When @var{obj} is a class object defined with a class constructor, then\n## @code{subsindex} is the overloading method that allows the conversion of\n## this class object to a valid indexing vector.  It is important to note that\n## @code{subsindex} must return a zero-based real integer vector of the class\n## @qcode{\"double\"}.  For example, if the class constructor were\n##\n## @example\n## @group\n## function obj = myclass (a)\n##   obj = class (struct (\"a\", a), \"myclass\");\n## endfunction\n## @end group\n## @end example\n##\n## @noindent\n## then the @code{subsindex} function\n##\n## @example\n## @group\n## function idx = subsindex (obj)\n##   idx = double (obj.a) - 1.0;\n## endfunction\n## @end group\n## @end example\n##\n## @noindent\n## could be used as follows\n##\n## @example\n## @group\n## a = myclass (1:4);\n## b = 1:10;\n## b(a)\n## @xresult{} 1  2  3  4\n## @end group\n## @end example\n##\n## @seealso{class, subsref, subsasgn}\n## @end deftypefn\n\nfunction idx = subsindex (obj)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Only way to get here is if subsindex has not been overloaded by a class.\n  error ('subsindex: not defined for class \"%s\"', class (obj));\n\nendfunction\n\n\n%!error <not defined for class \"double\"> subsindex (1)\n\n## Test input validation\n%!error <Invalid call> subsindex ()\n"
  },
  {
    "path": "scripts/general/trapz.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} trapz (@var{y})\n## @deftypefnx {} {@var{q} =} trapz (@var{x}, @var{y})\n## @deftypefnx {} {@var{q} =} trapz (@dots{}, @var{dim})\n##\n## Numerically evaluate the integral of points @var{y} using the trapezoidal\n## method.\n##\n## @w{@code{trapz (@var{y})}}@ computes the integral of @var{y} along the first\n## non-singleton dimension.  When the argument @var{x} is omitted an equally\n## spaced @var{x} vector with unit spacing (1) is assumed.\n## @code{trapz (@var{x}, @var{y})} evaluates the integral with respect to the\n## spacing in @var{x} and the values in @var{y}.  This is useful if the points\n## in @var{y} have been sampled unevenly.\n##\n## If the optional @var{dim} argument is given, operate along this dimension.\n##\n## Application Note: If @var{x} is not specified then unit spacing will be\n## used.  To scale the integral to the correct value you must multiply by the\n## actual spacing value (deltaX).  As an example, the integral of @math{x^3}\n## over the range [0, 1] is @math{x^4/4} or 0.25.  The following code uses\n## @code{trapz} to calculate the integral in three different ways.\n##\n## @example\n## @group\n## x = 0:0.1:1;\n## y = x.^3;\n## ## No scaling\n## q = trapz (y)\n##   @xresult{} q = 2.5250\n## ## Approximation to integral by scaling\n## q * 0.1\n##   @xresult{} 0.25250\n## ## Same result by specifying @var{x}\n## trapz (x, y)\n##   @xresult{} 0.25250\n## @end group\n## @end example\n##\n## @seealso{cumtrapz}\n## @end deftypefn\n\nfunction z = trapz (x, y, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  have_xy = have_dim = false;\n\n  if (nargin == 3)\n    have_xy = true;\n    have_dim = true;\n  elseif (nargin == 2)\n    if (isscalar (y) && ! isscalar (x))\n      have_dim = true;\n      dim = y;\n    else\n      have_xy = true;\n    endif\n  endif\n\n  if (have_xy)\n    nd = ndims (y);\n    sz = size (y);\n  else\n    nd = ndims (x);\n    sz = size (x);\n  endif\n\n  if (! have_dim)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  else\n    if (!(isscalar (dim) && dim == fix (dim))\n        || !(1 <= dim && dim <= nd))\n      error (\"trapz: DIM must be an integer and a valid dimension\");\n    endif\n  endif\n\n  n = sz(dim);\n  idx1 = idx2 = {':'}(ones (nd, 1));  # repmat ({':'}, [nd, 1]), but faster\n  idx1{dim} = 2 : n;\n  idx2{dim} = 1 : (n - 1);\n\n  if (! have_xy)\n    z = 0.5 * sum (x(idx1{:}) + x(idx2{:}), dim);\n  elseif (isscalar (x))\n    z = x * 0.5 * sum (y(idx1{:}) + y(idx2{:}), dim);\n  elseif (isvector (x))\n    if (length (x) != n)\n      error (\"trapz: length of X and length of Y along DIM must match\");\n    endif\n    ## Reshape spacing vector x to point along dimension DIM\n    shape = ones (nd, 1);\n    shape(dim) = n;\n    x = reshape (x, shape);\n    z = 0.5 * sum (diff (x) .* (y(idx1{:}) + y(idx2{:})), dim);\n  else\n    if (! size_equal (x, y))\n      error (\"trapz: X and Y must have same shape\");\n    endif\n    z = 0.5 * sum (diff (x, 1, dim) .* (y(idx1{:}) + y(idx2{:})), dim);\n  endif\n\nendfunction\n\n\n%!assert (trapz (1:5), 12)\n%!assert (trapz (1, 1:5), 12)\n%!assert (trapz (0.5, 1:5), 6)\n%!assert (trapz ([1:5], [1:5]), 12)\n%!assert (trapz ([1:5], [1:5]'), 12)\n%!assert (trapz ([1:5]', [1:5]'), 12)\n%!assert (trapz ([1:5]', [1:5]), 12)\n%!assert (trapz (0:0.5:2,1:5), 6)\n%!assert (trapz ([1:5;1:5].', 1), [12, 12])\n%!assert (trapz ([1:5;1:5], 2), [12; 12])\n%!assert (trapz (repmat (reshape (1:5,1,1,5),2,2), 3), [12 12; 12 12])\n%!assert (trapz ([0:0.5:2;1:5].', [1:5;1:5].', 1), [6, 12])\n%!assert (trapz ([0:0.5:2;1:5], [1:5;1:5], 2), [6; 12])\n%!assert (trapz (repmat (reshape ([0:0.5:2],1,1,5),2,2), ...\n%!               repmat (reshape (1:5,1,1,5),2,2), 3), [6 6; 6 6])\n%!assert (trapz (0:0.5:2, [(1:5)', (1:5)']), [6, 6])\n%!assert (trapz (0:0.5:2, [(1:5); (1:5)], 2), [6; 6])\n%!assert (trapz (0:0.5:2, repmat (reshape (1:5,1,1,5),2,2),3), [6 6; 6 6])\n%!assert <*54277> (trapz (ones (1,3), 1), zeros (1,3))\n%!assert <*54277> (trapz (ones (3,1), 2), zeros (3,1))\n\n## Test input validation\n%!error <Invalid call> trapz ()\n%!error <DIM must be an integer> trapz (1, 2, [1 2])\n%!error <DIM must be an integer> trapz (1, 2, 1.5)\n%!error <DIM must be .* a valid dimension> trapz (1, 2, 0)\n%!error <length of X and length of Y.*must match> trapz ([1 2], [1 2 3])\n%!error <X and Y must have same shape> trapz (ones (2,3), ones (2,4))\n"
  },
  {
    "path": "scripts/general/triplequad.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} triplequad (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{za}, @var{zb})\n## @deftypefnx {} {@var{q} =} triplequad (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{za}, @var{zb}, @var{tol})\n## @deftypefnx {} {@var{q} =} triplequad (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{za}, @var{zb}, @var{tol}, @var{quadf})\n## @deftypefnx {} {@var{q} =} triplequad (@var{f}, @var{xa}, @var{xb}, @var{ya}, @var{yb}, @var{za}, @var{zb}, @var{tol}, @var{quadf}, @dots{})\n## Numerically evaluate the triple integral of @var{f}.\n##\n## @var{f} is a function handle, inline function, or string containing the name\n## of the function to evaluate.  The function @var{f} must have the form\n## @math{w = f(x,y,z)} where either @var{x} or @var{y} is a vector and the\n## remaining inputs are scalars.  It should return a vector of the same length\n## and orientation as @var{x} or @var{y}.\n##\n## @var{xa}, @var{ya}, @var{za} and @var{xb}, @var{yb}, @var{zb} are the lower\n## and upper limits of integration for x, y, and z respectively.  The\n## underlying integrator determines whether infinite bounds are accepted.\n##\n## The optional argument @var{tol} defines the absolute tolerance used to\n## integrate each sub-integral.  The default value is 1e-6.\n##\n## The optional argument @var{quadf} specifies which underlying integrator\n## function to use.  Any choice but @code{quad} is available and the default\n## is @code{quadcc}.\n##\n## Additional arguments, are passed directly to @var{f}.  To use the default\n## value for @var{tol} or @var{quadf} one may pass @qcode{':'} or an empty\n## matrix ([]).\n## @seealso{integral3, integral2, dblquad, quad, quadv, quadl, quadgk, quadcc,\n##          trapz}\n## @end deftypefn\n\nfunction q = triplequad (f, xa, xb, ya, yb, za, zb, tol = 1e-6, quadf = @quadcc, varargin)\n\n  if (nargin < 7)\n    print_usage ();\n  endif\n\n  ## Allow use of empty matrix ([]) to indicate default\n  if (isempty (tol))\n    tol = 1e-6;\n  endif\n  if (isempty (quadf))\n    quadf = @quadcc;\n  endif\n\n  inner = @__triplequad_inner__;\n  if (ischar (f))\n    f = @(x,y,z) feval (f, x, y, z, varargin{:});\n    varargin = {};\n  endif\n\n  q = dblquad (@(y, z) inner (y, z, f, xa, xb, tol, quadf, varargin{:}), ...\n               ya, yb, za, zb, tol);\n\nendfunction\n\nfunction q = __triplequad_inner__ (y, z, f, xa, xb, tol, quadf, varargin)\n  q = zeros (size (y));\n  for i = 1 : length (y)\n    q(i) = feval (quadf, @(x) f (x, y(i), z, varargin{:}), xa, xb, tol);\n  endfor\nendfunction\n\n\n%!assert (triplequad (@(x,y,z) exp (-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [], @quadcc), pi^(3/2) * erf (1).^3, 1e-6)\n\n## These tests are too expensive to run normally (~30 sec each).  Disable them\n%!#assert (triplequad (@(x,y,z) exp (-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [], @quadgk), pi^(3/2) * erf (1).^3, 1e-6)\n%!#assert (triplequad (@(x,y,z) exp (-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [], @quadl), pi^(3/2) * erf (1).^3, 1e-6)\n%!#assert (triplequad (@(x,y,z) exp (-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [], @quadv), pi^(3/2) * erf (1).^3, 1e-6)\n"
  },
  {
    "path": "scripts/general/xor.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{z} =} xor (@var{x}, @var{y})\n## @deftypefnx {} {@var{z} =} xor (@var{x1}, @var{x2}, @dots{})\n## Return the @dfn{exclusive or} of @var{x} and @var{y}.\n##\n## For boolean expressions @var{x} and @var{y},\n## @code{xor (@var{x}, @var{y})} is true if and only if one of @var{x} or\n## @var{y} is true.  Otherwise, if @var{x} and @var{y} are both true or both\n## false, @code{xor} returns false.\n##\n## The truth table for the xor operation is\n##\n## @multitable @columnfractions 0.41 .044 .06 .042 0.42\n## @item @tab @var{x} @tab @var{y} @tab @var{z} @tab\n## @item @tab - @tab - @tab - @tab\n## @item @tab 0 @tab 0 @tab 0 @tab\n## @item @tab 1 @tab 0 @tab 1 @tab\n## @item @tab 0 @tab 1 @tab 1 @tab\n## @item @tab 1 @tab 1 @tab 0 @tab\n## @end multitable\n##\n## If more than two arguments are given the xor operation is applied\n## cumulatively from left to right:\n##\n## @example\n## (@dots{}((x1 XOR x2) XOR x3) XOR @dots{})\n## @end example\n##\n## @seealso{and, or, not}\n## @end deftypefn\n\nfunction z = xor (x, y, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  z = __xor__ (x, y);\n\n  ## Slow expansion to multiple arguments.\n  ## Probably okay number of elements will be small.\n  if (! isempty (varargin))\n    for i = 1:numel (varargin)\n      z = __xor__ (z, varargin{i});\n    endfor\n  endif\n\nendfunction\n\nfunction z = __xor__ (x, y)\n\n  if (isscalar (x) || isscalar (y) || size_equal (x, y))\n    ## Typecast to logicals is necessary for other numeric types.\n    z = logical (x) != logical (y);\n  else\n    try\n      z = bsxfun (@xor, x, y);\n    catch\n      error (\"xor: X and Y must be of compatible size or scalars\");\n    end_try_catch\n  endif\n\nendfunction\n\n\n%!assert (xor ([1, 1, 0, 0], [0, 1, 0, 1]), logical ([1, 0, 0, 1]))\n%!assert (xor ([i, i, 0, 0], [1, 0, 1, 0]), logical ([0, 1, 1, 0]))\n\n%!assert (xor (eye (2), fliplr (eye (2))), true (2))\n%!assert (xor (speye (2), fliplr (speye (2))), sparse (true (2)))\n\n## Test XOR reduction\n%!assert (xor ([1 0], [1 1], [0 0]), logical ([0 1]))\n\n## Test input validation\n%!error <Invalid call> xor ()\n%!error <Invalid call> xor (1)\n%!error <X and Y must be of compatible size> xor (ones (3,2), ones (2,3))\n"
  },
  {
    "path": "scripts/geometry/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/geometry/convhull.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{H} =} convhull (@var{x}, @var{y})\n## @deftypefnx {} {@var{H} =} convhull (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {@var{H} =} convhull (@var{x})\n## @deftypefnx {} {@var{H} =} convhull (@dots{}, @var{options})\n## @deftypefnx {} {[@var{H}, @var{V}] =} convhull (@dots{})\n## Compute the convex hull of a 2-D or 3-D set of points.\n##\n## The hull @var{H} is a linear index vector into the original set of points\n## that specifies which points form the enclosing hull.  For 2-D inputs only,\n## the output is ordered in a counterclockwise manner around the hull.\n##\n## The input @var{x} may also be a matrix with two or three columns where the\n## first column contains x-data, the second y-data, and the optional third\n## column contains z-data.\n##\n## An optional final argument, which must be a string or cell array of strings,\n## contains options passed to the underlying qhull command.\n## See the documentation for the Qhull library for details\n## @url{http://www.qhull.org/html/qh-quick.htm#options}.\n## The default option is @code{@{\"Qt\"@}}.\n##\n## If @var{options} is not present or @code{[]} then the default arguments are\n## used.  Otherwise, @var{options} replaces the default argument list.\n## To append user options to the defaults it is necessary to repeat the\n## default arguments in @var{options}.  Use a null string to pass no arguments.\n##\n## If the second output @var{V} is requested the volume of the enclosing\n## convex hull is calculated.\n##\n## @seealso{convhulln, delaunay, voronoi}\n## @end deftypefn\n\nfunction [H, V] = convhull (varargin)\n\n  if (nargin < 1 || nargin > 4)\n    print_usage ();\n  endif\n\n  z = [];\n  options = [];\n\n  switch (nargin)\n\n    case 1\n      if (! ismatrix (varargin{1})\n          || (columns (varargin{1}) != 2 && columns (varargin{1}) != 3))\n          error (\"convhull: X must be a matrix with 2 or 3 columns\");\n      else\n        x = varargin{1}(:,1);\n        y = varargin{1}(:,2);\n        if (columns (varargin{1}) == 3)\n          z = varargin{1}(:,3);\n        endif\n      endif\n\n    case 2\n      if (isnumeric (varargin{2}))\n        x = varargin{1};\n        y = varargin{2};\n      elseif (! (ischar (varargin{2}) || iscellstr (varargin{2})))\n        error (\"convhull: OPTIONS must be a string or cell array of strings\");\n      else\n        options = varargin{2};\n        ncols = columns (varargin{1});\n\n        if (! ismatrix (varargin{1}) || (ncols != 2 && ncols != 3))\n          error (\"convhull: X must be a matrix with 2 or 3 columns\");\n        else\n          x = varargin{1}(:,1);\n          y = varargin{1}(:,2);\n          if (ncols == 3)\n            z = varargin{1}(:,3);\n          endif\n        endif\n      endif\n\n    case 3\n      if (isnumeric (varargin{3}))\n        x = varargin{1};\n        y = varargin{2};\n        z = varargin{3};\n      elseif (! (ischar (varargin{3}) || iscellstr (varargin{3})))\n        error (\"convhull: OPTIONS must be a string or cell array of strings\");\n      else\n        x = varargin{1};\n        y = varargin{2};\n        options = varargin{3};\n      endif\n\n    case 4\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      options = varargin{4};\n\n      if (! (ischar (options) || iscellstr (options)))\n        error (\"convhull: OPTIONS must be a string or cell array of strings\");\n      endif\n\n  endswitch\n\n  if (isempty (z))\n    x = x(:);  y = y(:);\n    if (! size_equal (x, y))\n      error (\"convhull: X and Y must be the same size\");\n    endif\n    if (nargout > 1)\n      [Htmp, V] = convhulln ([x, y], options);\n    else\n      Htmp = convhulln ([x, y], options);\n    endif\n  else\n    x = x(:);  y = y(:);  z = z(:);\n    if (! size_equal (x, y, z))\n      error (\"convhull: X, Y, and Z must be the same size\");\n    endif\n    if (nargout > 1)\n      [H, V] = convhulln ([x, y, z], options);\n    else\n      H = convhulln ([x, y, z], options);\n    endif\n  endif\n\n  if (isempty (z))\n    ## Order 2-D convex hull in a counterclockwise manner.\n    n = rows (Htmp);\n    Htmp = Htmp.'(:);\n    H = zeros (n + 1, 1);\n\n    H(1) = Htmp(1);\n    next_pt = Htmp(2);\n    Htmp(2) = 0;\n    for k = 2:n\n      next_idx = find (Htmp == next_pt);\n      H(k) = Htmp(next_idx);\n\n      if (rem (next_idx, 2) == 0)\n        next_pt =  Htmp(next_idx - 1);\n         Htmp(next_idx - 1) = 0;\n      else\n        next_pt = Htmp(next_idx + 1);\n         Htmp(next_idx + 1) = 0;\n      endif\n    endfor\n\n    H(n + 1) = H(1);\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = -3:0.05:3;\n%! y = abs (sin (x));\n%! k = convhull (x, y);\n%! plot (x(k),y(k),\"r-;convex hull;\", x,y,\"b+;points;\");\n%! axis ([-3.05, 3.05, -0.05, 1.05]);\n\n%!testif HAVE_QHULL\n%! x = -3:0.5:3;\n%! y = abs (sin (x));\n%! assert (convhull (x, y), [1;7;13;12;11;10;4;3;2;1]);\n\n%!testif HAVE_QHULL\n%! [~, V] = convhull ([0,2,2,0], [0,0,1,1]);\n%! assert (V == 2);\n\n## Input validation tests\n%!error <Invalid call> convhull ()\n%!error <Invalid call> convhull (1,2,3,4,5)\n%!error <X must be a matrix with 2 or 3 columns> convhull (ones (2,4))\n%!error <OPTIONS must be a string or cell array> convhull (ones (2,2), struct ())\n%!error <X must be a matrix with 2 or 3 columns> convhull (ones (2,4), \"\")\n%!error <OPTIONS must be a string or cell array> convhull (ones (2,2), ones (2,2), struct ())\n%!error <OPTIONS must be a string or cell array> convhull (ones (2,2), ones (2,2), ones (2,2), struct ())\n%!error <X and Y must be the same size> convhull (1, [1 2])\n%!error <X, Y, and Z must be the same size> convhull (1, [1 2], [1 2])\n"
  },
  {
    "path": "scripts/geometry/delaunay.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tri} =} delaunay (@var{x}, @var{y})\n## @deftypefnx {} {@var{tetr} =} delaunay (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {@var{tri} =} delaunay (@var{x})\n## @deftypefnx {} {@var{tri} =} delaunay (@dots{}, @var{options})\n## Compute the Delaunay triangulation for a 2-D or 3-D set of points.\n##\n## For 2-D sets, the return value @var{tri} is a set of triangles which\n## satisfies the Delaunay circum-circle criterion, i.e., no data point from\n## [@var{x}, @var{y}] is within the circum-circle of the defining triangle.\n## The set of triangles @var{tri} is a matrix of size [n, 3].  Each row defines\n## a triangle and the three columns are the three vertices of the triangle.\n## The value of @code{@var{tri}(i,j)} is an index into @var{x} and @var{y} for\n## the location of the j-th vertex of the i-th triangle.\n##\n## For 3-D sets, the return value @var{tetr} is a set of tetrahedrons which\n## satisfies the Delaunay circum-circle criterion, i.e., no data point from\n## [@var{x}, @var{y}, @var{z}] is within the circum-circle of the defining\n## tetrahedron.  The set of tetrahedrons is a matrix of size [n, 4].  Each row\n## defines a tetrahedron and the four columns are the four vertices of the\n## tetrahedron.  The value of @code{@var{tetr}(i,j)} is an index into @var{x},\n## @var{y}, @var{z} for the location of the j-th vertex of the i-th\n## tetrahedron.\n##\n## The input @var{x} may also be a matrix with two or three columns where the\n## first column contains x-data, the second y-data, and the optional third\n## column contains z-data.\n##\n## An optional final argument, which must be a string or cell array of strings,\n## contains options passed to the underlying qhull command.\n## See the documentation for the Qhull library for details\n## @url{http://www.qhull.org/html/qh-quick.htm#options}.\n## The default options are @code{@{\"Qt\", \"Qbb\", \"Qc\"@}}.\n## If Qhull fails for 2-D input the triangulation is attempted again with\n## the options @code{@{\"Qt\", \"Qbb\", \"Qc\", \"Qz\"@}} which may result in\n## reduced accuracy.\n##\n## If @var{options} is not present or @code{[]} then the default arguments are\n## used.  Otherwise, @var{options} replaces the default argument list.\n## To append user options to the defaults it is necessary to repeat the\n## default arguments in @var{options}.  Use a null string to pass no arguments.\n##\n## @example\n## @group\n## x = rand (1, 10);\n## y = rand (1, 10);\n## tri = delaunay (x, y);\n## triplot (tri, x, y);\n## hold on;\n## plot (x, y, \"r*\");\n## axis ([0,1,0,1]);\n## @end group\n## @end example\n## @seealso{delaunayn, convhull, voronoi, triplot, trimesh, tetramesh, trisurf}\n## @end deftypefn\n\nfunction tri = delaunay (varargin)\n\n  if (nargin < 1 || nargin > 4)\n    print_usage ();\n  endif\n\n  z = [];\n  options = [];\n\n  switch (nargin)\n\n    case 1\n      if (! ismatrix (varargin{1})\n          || (columns (varargin{1}) != 2 && columns (varargin{1}) != 3))\n          error (\"delaunay: X must be a matrix with 2 or 3 columns\");\n      else\n        x = varargin{1}(:,1);\n        y = varargin{1}(:,2);\n        if (columns (varargin{1}) == 3)\n          z = varargin{1}(:,3);\n        endif\n      endif\n\n    case 2\n      if (isnumeric (varargin{2}))\n        x = varargin{1};\n        y = varargin{2};\n      elseif (! (ischar (varargin{2}) || iscellstr (varargin{2})))\n        error (\"delaunay: OPTIONS must be a string or cell array of strings\");\n      else\n        options = varargin{2};\n        ncols = columns (varargin{1});\n\n        if (! ismatrix (varargin{1}) || (ncols != 2 && ncols != 3))\n          error (\"delaunay: X must be a matrix with 2 or 3 columns\");\n        else\n          x = varargin{1}(:,1);\n          y = varargin{1}(:,2);\n          if (ncols == 3)\n            z = varargin{1}(:,3);\n          endif\n        endif\n      endif\n\n    case 3\n      if (isnumeric (varargin{3}))\n        x = varargin{1};\n        y = varargin{2};\n        z = varargin{3};\n      elseif (! (ischar (varargin{3}) || iscellstr (varargin{3})))\n        error (\"delaunay: OPTIONS must be a string or cell array of strings\");\n      else\n        x = varargin{1};\n        y = varargin{2};\n        options = varargin{3};\n      endif\n\n    case 4\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      options = varargin{4};\n\n      if (! (ischar (options) || iscellstr (options)))\n        error (\"delaunay: OPTIONS must be a string or cell array of strings\");\n      endif\n\n  endswitch\n\n  if (isempty (z))\n    x = x(:);  y = y(:);\n    if (! size_equal (x, y))\n      error (\"delaunay: X and Y must be the same size\");\n    endif\n    tri = delaunayn ([x, y], options);\n  else\n    x = x(:);  y = y(:);  z = z(:);\n    if (! size_equal (x, y, z))\n      error (\"delaunay: X, Y, and Z must be the same size\");\n    endif\n    tri = delaunayn ([x, y, z], options);\n  endif\n\nendfunction\n\n\n%!demo\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 1);\n%! x = rand (1,10);\n%! y = rand (1,10);\n%! tri = delaunay (x,y);\n%! clf;\n%! triplot (tri, x, y);\n%! hold on;\n%! plot (x, y, \"r*\");\n%! axis ([0,1,0,1]);\n\n%!testif HAVE_QHULL\n%! x = [-1, 0, 1, 0];\n%! y = [0, 1, 0, -1];\n%! assert (sortrows (sort (delaunay (x, y), 2)), [1,2,4;2,3,4]);\n\n%!testif HAVE_QHULL\n%! x = [-1, 0, 1, 0];\n%! y = [0, 1, 0, -1];\n%! mat = [x(:), y(:)];\n%! assert (sortrows (sort (delaunay (mat), 2)), [1,2,4;2,3,4]);\n\n%!testif HAVE_QHULL\n%! x = [-1, 0, 1, 0, 0];\n%! y = [0, 1, 0, -1, 0];\n%! assert (sortrows (sort (delaunay (x, y), 2)), [1,2,5;1,4,5;2,3,5;3,4,5]);\n\n%!testif HAVE_QHULL\n%! x = [-1, 0; 0, 1; 1, 0; 0, -1; 0, 0];\n%! assert (sortrows (sort (delaunay (x), 2)), [1,2,5;1,4,5;2,3,5;3,4,5]);\n\n%!testif HAVE_QHULL\n%! x = [1 5 2; 5 6 7];\n%! y = [5 7 8; 1 2 3];\n%! assert (sortrows (sort (delaunay (x, y), 2)), [1,2,4;1,3,4;1,3,5;3,4,6]);\n\n## Test 3-D input\n%!testif HAVE_QHULL\n%! x = [-1, -1, 1, 0, -1]; y = [-1, 1, 1, 0, -1]; z = [0, 0, 0, 1, 1];\n%! assert (sortrows (sort (delaunay (x, y, z), 2)), [1,2,3,4;1,2,4,5]);\n\n## Input validation tests\n%!error <Invalid call> delaunay ()\n%!error <Invalid call> delaunay (1,2,3,4,5)\n%!error <X must be a matrix with 2 or 3 columns> delaunay (ones (2,4))\n%!error <OPTIONS must be a string or cell array> delaunay (ones (2,2), struct ())\n%!error <X must be a matrix with 2 or 3 columns> delaunay (ones (2,4), \"\")\n%!error <OPTIONS must be a string or cell array> delaunay (ones (2,2), ones (2,2), struct ())\n%!error <OPTIONS must be a string or cell array> delaunay (ones (2,2), ones (2,2), ones (2,2), struct ())\n%!error <X and Y must be the same size> delaunay (1, [1 2])\n%!error <X, Y, and Z must be the same size> delaunay (1, [1 2], [1 2])\n"
  },
  {
    "path": "scripts/geometry/delaunayn.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{T} =} delaunayn (@var{pts})\n## @deftypefnx {} {@var{T} =} delaunayn (@var{pts}, @var{options})\n## Compute the Delaunay triangulation for an N-dimensional set of points.\n##\n## The Delaunay triangulation is a tessellation of the convex hull of a set of\n## points such that no N-sphere defined by the N-triangles contains any other\n## points from the set.\n##\n## The input matrix @var{pts} of size [n, dim] contains n points in a space of\n## dimension dim.  The return matrix @var{T} has size [m, dim+1].  Each row of\n## @var{T} contains a set of indices back into the original set of points\n## @var{pts} which describes a simplex of dimension dim.  For example, a 2-D\n## simplex is a triangle and 3-D simplex is a tetrahedron.\n##\n## An optional second argument, which must be a string or cell array of\n## strings, contains options passed to the underlying qhull command.  See the\n## documentation for the Qhull library for details\n## @url{http://www.qhull.org/html/qh-quick.htm#options}.\n## The default options depend on the dimension of the input:\n##\n## @itemize\n## @item 2-D and 3-D: @var{options} = @code{@{\"Qt\", \"Qbb\", \"Qc\"@}}\n##\n## @item 4-D and higher: @var{options} = @code{@{\"Qt\", \"Qbb\", \"Qc\", \"Qx\"@}}\n## @end itemize\n##\n## If Qhull fails for 2-D input the triangulation is attempted again with\n## the options @code{@{\"Qt\", \"Qbb\", \"Qc\", \"Qz\"@}} which may result in\n## reduced accuracy.\n##\n## If @var{options} is not present or @code{[]} then the default arguments are\n## used.  Otherwise, @var{options} replaces the default argument list.\n## To append user options to the defaults it is necessary to repeat the\n## default arguments in @var{options}.  Use a null string to pass no arguments.\n##\n## @seealso{delaunay, convhulln, voronoin, trimesh, tetramesh}\n## @end deftypefn\n\nfunction T = delaunayn (pts, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## NOTE: varargin options input validation is performed in __delaunayn__\n  if ((! isnumeric (pts)) || (ndims (pts) > 2))\n    error (\"delaunayn: PTS must be a 2-dimensional numeric array\");\n  endif\n  ## QHull library will segfault if input contains Inf or NaN (bug #67315)\n  if (any (! isfinite (pts(:))))\n    error (\"delaunayn: PTS must not contain Inf or NaN values\");\n  endif\n\n  ## Perform delaunay calculation using either default or specified options\n  if (isempty (varargin) || isempty (varargin{1}))\n    try\n      T = __delaunayn__ (pts);\n    catch err\n      if (columns (pts) <= 2)\n        T = __delaunayn__ (pts, \"Qt Qbb Qc Qz\");\n      else\n        rethrow (err);\n      endif\n    end_try_catch\n  else\n    T = __delaunayn__ (pts, varargin{:});\n  endif\n\n  ## Avoid erroneous calculations due to integer truncation.  See bug #64658.\n  ## FIXME: Large integer values in excess of flintmax can lose precision\n  ##        when converting from (u)int64 to double.  Consider modifying\n  ##        simplex checking to account for large integer math to avoid this\n  ##        problem.\n  if (isinteger (pts))\n    if (any (abs (pts(:)) > flintmax ('double')))\n      warning ([\"delaunayn: conversion of large integer values to \", ...\n                \"double, potential loss of precision may result in \" ...\n                \"erroneous triangulations.\"]);\n    endif\n    pts = double (pts);\n  endif\n\n  ## Begin check for and removal of trivial simplices\n  if (! isequal (T, 0))  # skip trivial simplex check if no simplexes\n\n    if (isa (pts, \"single\"))\n      tol = 1e3 * eps (\"single\");\n    else\n      tol = 1e3 * eps;\n    endif\n\n    ## Try to remove the ~zero volume simplices.  The volume of the i-th simplex\n    ## is given by abs(det(pts(T(i,2:end),:)-pts(T(i,1),:)))/factorial(ndim+1)\n    ## (reference http://en.wikipedia.org/wiki/Simplex).  Any simplex with a\n    ## relative volume less than some arbitrary criteria is rejected.  The\n    ## criteria we use is the volume of a simplex corresponding to an\n    ## orthogonal simplex (rectangle, rectangular prism, etc.) with edge lengths\n    ## equal to the common-origin edge lengths of the original simplex.  If the\n    ## relative volume is 1e3*eps then the simplex is rejected.  Note division\n    ## of the two volumes means that the factor factorial(ndim+1) is dropped\n    ## from volume calculations.\n\n    [nt, nd] = size (T);  # nt = simplex count, nd = # of simplex points\n    dim = nd - 1;\n\n    ## Calculate common origin edge vectors for each simplex (p2-p1,p3-p1,...)\n    ## Store in 3-D array such that:\n    ## rows = nt simplexes, cols = coordinates, pages = simplex edges\n    edge_vecs =  permute (reshape (pts(T(:, 2:nd), :).', [dim, nt, dim]), ...\n                          [2, 1, 3]) - pts(T(:, 1), :, ones (1, 1, dim));\n\n    ## Calculate orthogonal simplex volumes for comparison\n    orthog_simplex_vols = sqrt (prod (sumsq (edge_vecs, 2), 3));\n\n    ## Calculate simplex volumes according to problem dimension\n    if (nd == 3)\n      ## 2-D: area = cross product of triangle edge vectors\n      vol = edge_vecs(:,1,1) .* edge_vecs(:,2,2) ...\n            - edge_vecs(:,1,2) .* edge_vecs(:,2,1);\n\n    elseif (nd == 4)\n      ## 3-D: vol = scalar triple product [a.(b x c)]\n      vol = edge_vecs(:,1,1) .* ...\n              (edge_vecs(:,2,2) .* edge_vecs(:,3,3) - ...\n                edge_vecs(:,3,2) .* edge_vecs(:,2,3)) ...\n            - edge_vecs(:,2,1) .* ...\n              (edge_vecs(:,1,2) .* edge_vecs(:,3,3) - ...\n                edge_vecs(:,3,2) .* edge_vecs(:,1,3)) ...\n            + edge_vecs(:,3,1) .* ...\n              (edge_vecs(:,1,2) .* edge_vecs(:,2,3) - ...\n                edge_vecs(:,2,2) .* edge_vecs(:,1,3));\n\n    else\n      ## 1-D and >= 4-D: simplex 'volume' proportional to det|edge_vecs|\n\n      ## FIXME: Vectorize this for N-D inputs without excessive memory impact\n      ## over __delaunayn__ itself, or move simplex checking into __delaunayn__;\n      ## perhaps with an optimized page-wise determinant.\n      ## See bug #60818 for speed/memory improvement attempts and concerns.\n      vol = zeros (nt, 1);\n\n      ## Reshape so det can operate in dim 1&2\n      edge_vecs = permute (edge_vecs, [3, 2, 1]);\n\n      ## Calculate determinant for arbitrary problem dimension\n      for ii = 1:nt\n        vol(ii) = det (edge_vecs(:, :, ii));\n      endfor\n    endif\n\n    ## Mark simplices with relative volume < tol for removal\n    idx = (abs ((vol) ./ orthog_simplex_vols)) < tol;\n\n    ## Remove trivially small simplexes from T\n    T(idx, :) = [];\n\n    ## Ensure CCW node order for consistent outward normal (bug #53397)\n    ## simplest method of maintaining positive unit normal direction is to\n    ## reverse order of two nodes; this preserves 'nice' monotonic descending\n    ## node 1 ordering.  Currently ignores 1-D cases for compatibility.\n    if (dim > 1 && any (negvol = (vol(! idx) < 0)))\n      T(negvol, [2, 3]) = T(negvol, [3, 2]);\n    endif\n\n  endif\n\nendfunction\n\n\n## Test 1-D input\n%!testif HAVE_QHULL\n%! assert (sortrows (sort (delaunayn ([1;2]), 2)), [1, 2]);\n%! assert (sortrows (sort (delaunayn ([1;2;3]), 2)), [1, 2; 2, 3]);\n\n## Test 2-D input\n%!testif HAVE_QHULL\n%! x = [-1, 0; 0, 1; 1, 0; 0, -1; 0, 0];\n%! assert (sortrows (sort (delaunayn (x), 2)), [1,2,5;1,4,5;2,3,5;3,4,5]);\n\n## Test 3-D input\n%!testif HAVE_QHULL\n%! x = [-1, -1, 1, 0, -1]; y = [-1, 1, 1, 0, -1]; z = [0, 0, 0, 1, 1];\n%! assert (sortrows (sort (delaunayn ([x(:) y(:) z(:)]), 2)),\n%!         [1,2,3,4;1,2,4,5]);\n\n## 3-D test with trivial simplex removal\n%!testif HAVE_QHULL\n%! x = [0 0 0; 0 0 1; 0 1 0; 1 0 0; 0 1 1; 1 0 1; 1 1 0; 1 1 1; 0.5 0.5 0.5];\n%! T = sortrows (sort (delaunayn (x), 2));\n%! assert (rows (T), 12);\n\n## 4-D single simplex test\n%!testif HAVE_QHULL\n%! x = [0 0 0 0; 1 0 0 0; 1 1 0 0; 0 0 1 0; 0 0 0 1];\n%! T = sort (delaunayn (x), 2);\n%! assert (T, [1 2 3 4 5]);\n\n## 4-D two simplices test\n%!testif HAVE_QHULL\n%! x = [0 0 0 0; 1 0 0 0; 1 1 0 0; 0 0 1 0; 0 0 0 1; 0 0 0 2];\n%! T = sortrows (sort (delaunayn (x), 2));\n%! assert (rows (T), 2);\n%! assert (T, [1 2 3 4 5; 2 3 4 5 6]);\n\n## Test negative simplex produce positive normals\n## 2-D test\n%!testif HAVE_QHULL <*53397>\n%! x = [-1, 0; 0, 1; 1, 0; 0, -1; 0, 0];\n%! y = delaunayn (x);\n%! edges = permute (reshape (x(y(:, 2:end), :).', [2, 4, 2]), [2, 1, 3]) - ...\n%!         x(y(:, 1), :, ones (1, 1, 2));\n%! vol = edges(:,1,1) .* edges(:,2,2) - edges(:,1,2) .* edges(:,2,1);\n%! assert (all (vol >= 0));\n\n## 3-D test\n%!testif HAVE_QHULL <*53397>\n%! x = [[-1, -1, 1, 0, -1]',[-1, 1, 1, 0, -1]',[0, 0, 0, 1, 1]'];\n%! y = delaunayn (x);\n%! edges = permute (reshape (x(y(:, 2:end), :).', [3, 2, 3]), [2, 1, 3]) - ...\n%!         x(y(:, 1), :, ones (1, 1, 3));\n%! vol = edges(:,1,1) .* ...\n%!            (edges(:,2,2) .* edges(:,3,3) - edges(:,3,2) .* edges(:,2,3)) ...\n%!       - edges(:,2,1) .* ...\n%!            (edges(:,1,2) .* edges(:,3,3) - edges(:,3,2) .* edges(:,1,3)) ...\n%!       + edges(:,3,1) .* ...\n%!            (edges(:,1,2) .* edges(:,2,3) - edges(:,2,2) .* edges(:,1,3));\n%! assert (all (vol >= 0));\n\n## Avoid integer input erroneous volume truncation\n%!testif HAVE_QHULL <*64658>\n%! pts = [0 0 0; 0 0 10; 0 10 0; 0 10 10; 10 0 0; ...\n%!              10 0 10; 10 10 0; 10 10 10; 5 5 5];\n%! assert (isempty (delaunayn (int32 (pts))), false);\n%! assert (delaunayn (pts), delaunayn (int32 (pts)));\n\n## Input validation tests\n%!error <Invalid call> delaunayn ()\n%!error <PTS must be .* numeric array> delaunayn (\"abc\")\n%!error <PTS must be .* numeric array> delaunayn ({1})\n%!error <PTS must be .* numeric array> delaunayn (true)\n%!error <PTS must be a 2-dimensional .* array> delaunayn (ones (3,3,3))\n%!error <PTS must not contain Inf> delaunayn ([1, Inf, 3])\n%!error <PTS must not contain .* NaN> delaunayn ([1, NaN, 3])\n"
  },
  {
    "path": "scripts/geometry/dsearchn.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{idx} =} dsearchn (@var{x}, @var{tri}, @var{xi})\n## @deftypefnx {} {@var{idx} =} dsearchn (@var{x}, @var{tri}, @var{xi}, @var{outval})\n## @deftypefnx {} {@var{idx} =} dsearchn (@var{x}, @var{xi})\n## @deftypefnx {} {[@var{idx}, @var{d}] =} dsearchn (@dots{})\n## Return the index @var{idx} of the closest point in @var{x} to the elements\n## @var{xi}.\n##\n## If @var{outval} is supplied, then the values of @var{xi} that are not\n## contained within one of the simplices @var{tri} are set to @var{outval}.\n## Generally, @var{tri} is returned from @code{delaunayn (@var{x})}.\n##\n## The optional output @var{d} contains a column vector of distances between\n## the query points @var{xi} and the nearest simplex points @var{x}.\n##\n## Compatibility note: The @code{dsearchn} algorithm only uses the input\n## @var{tri} when @var{outdim} is specified to determine if any points lie\n## outside of the triangulation region.  For compatibility, @var{tri} is\n## accepted as an input even when @var{outdim} is not specified, but it is not\n## used or checked to be a valid triangulation, and providing it will not\n## affect either the output @var{idx} or the calculation efficiency.\n##\n## @seealso{tsearchn, delaunayn}\n## @end deftypefn\n\nfunction [idx, d] = dsearchn (x, tri, xi, outval)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (nargin == 2)\n    [idx, d] = __dsearchn__ (x, tri);\n  else\n    [idx, d] = __dsearchn__ (x, xi);\n    if (nargin == 4)\n      idx2 = isnan (tsearchn (x, tri, xi));\n      idx(idx2) = outval;\n      d(idx2) = outval;\n    endif\n  endif\n\nendfunction\n\n\n%!shared x, tri\n%! x = [-1,-1;-1,1;1,-1];\n%! tri = [1,2,3];\n%!assert (dsearchn (x,tri,[1,1/3]), 3)\n%!assert (dsearchn (x,tri,[1,1/3],NaN), NaN)\n%!assert (dsearchn (x,tri,[1,1/3],NA), NA)\n%!assert (dsearchn (x,tri,[1/3,1]), 2)\n%!assert (dsearchn (x,tri,[1/3,1],NaN), NaN)\n%!assert (dsearchn (x,tri,[1/3,1],NA), NA)\n"
  },
  {
    "path": "scripts/geometry/griddata.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{zi} =} griddata (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi})\n## @deftypefnx {} {@var{zi} =} griddata (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi}, @var{method})\n## @deftypefnx {} {[@var{xi}, @var{yi}, @var{zi}] =} griddata (@dots{})\n## @deftypefnx {} {@var{vi} =} griddata (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi})\n## @deftypefnx {} {@var{vi} =} griddata (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi}, @var{method})\n## @deftypefnx {} {@var{vi} =} griddata (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi}, @var{method}, @var{options})\n##\n## Interpolate irregular 2-D and 3-D source data at specified points.\n##\n## For 2-D interpolation, the inputs @var{x} and @var{y} define the points\n## where the function @code{@var{z} = f (@var{x}, @var{y})} is evaluated.\n## The inputs @var{x}, @var{y}, @var{z} are either vectors of the same length,\n## or the unequal vectors @var{x}, @var{y} are expanded to a 2-D grid with\n## @code{meshgrid} and @var{z} is a 2-D matrix matching the resulting size of\n## the X-Y grid.\n##\n## The interpolation points are (@var{xi}, @var{yi}).  If either @var{xi} or\n## @var{y} is a row vector and the other is a column vector, then\n## @code{meshgrid (@var{xi}, @var{yi})} will be used to create a mesh of\n## interpolation points.\n##\n## For 3-D interpolation, the inputs @var{x}, @var{y}, and @var{z} define the\n## points where the function @code{@var{v} = f (@var{x}, @var{y}, @var{z})}\n## is evaluated.  The inputs @var{x}, @var{y}, @var{z} are either vectors of\n## the same length, or if they are of unequal length, then they are expanded to\n## a 3-D grid with @code{meshgrid}.  The size of the input @var{v} must match\n## the size of the original data, either as a vector or a matrix.\n##\n## The outputs @var{zi} (for 2-D) or @var{vi} (for 3-D) will contain the\n## interpolated values of @var{z} or @var{v}, respectively, with the output\n## size matching that of the interpolation points.\n##\n## The optional input interpolation @var{method} can be @qcode{\"nearest\"},\n## @qcode{\"linear\"}, or for 2-D data @qcode{\"v4\"}.  When the method is\n## @qcode{\"nearest\"}, the output @var{vi} will be the closest point in the\n## original data (@var{x}, @var{y}, @var{z}) to the query point (@var{xi},\n## @var{yi}, @var{zi}).  When the method is @qcode{\"linear\"}, the output\n## @var{vi} will be a linear interpolation between the two closest points in\n## the original source data in each dimension.  For 2-D cases only, the\n## @qcode{\"v4\"} method is also available which implements a biharmonic spline\n## interpolation.  If @var{method} is omitted or empty, it defaults to\n## @qcode{\"linear\"}.\n##\n## For 3-D interpolation, the optional argument @var{options} is passed\n## directly to Qhull when computing the Delaunay triangulation used for\n## interpolation.  For more information on the defaults and how to pass\n## different values, @pxref{XREFdelaunayn,,@code{delaunayn}}.\n##\n## Programming Notes: If the input is complex the real and imaginary parts\n## are interpolated separately.  Interpolation is normally based on a\n## Delaunay triangulation.  Any query values outside the convex hull of the\n## input points will return @code{NaN}.  However, the @qcode{\"v4\"} method does\n## not use the triangulation and will return values outside the original data\n## (extrapolation).\n## @seealso{griddata3, griddatan, delaunay}\n## @end deftypefn\n\nfunction [rx, ry, rz] = griddata (x, y, z, varargin)\n\n  if (nargin < 5)\n    print_usage ();\n  endif\n\n  if (nargin > 6)\n    ## Current 2-D implementation has nargin max = 6, since no triangulation\n    ## options are passed to the 2-D algorithm.\n    ## 3-D algorithm requires nargin >=7.\n\n    if (nargout > 1)\n      error (\"griddata: only one output argument valid for 3-D interpolation\");\n    endif\n    rx = griddata3 (x, y, z, varargin{:});\n\n  else\n    ## for nargin 5 or 6, assign varargin terms to variables for 2-D algorithm\n    xi = varargin{1};\n    yi = varargin{2};\n\n    ## Meshgrid if x and y are vectors but z is matrix\n    if (isvector (x) && isvector (y) && all ([numel(y), numel(x)] == size (z)))\n      [x, y] = meshgrid (x, y);\n    endif\n\n    if (isvector (x) && isvector (y) && isvector (z))\n      if (! isequal (length (x), length (y), length (z)))\n        error (\"griddata: X, Y, and Z must be vectors of the same length\");\n      endif\n    elseif (! size_equal (x, y, z))\n      error (\"griddata: lengths of X, Y must match the columns and rows of Z\");\n    endif\n\n    ## Meshgrid xi and yi if one is a row vector and the other is a column\n    ## vector, but not if they are vectors with the same orientation.\n    if ((isrow (xi) && iscolumn (yi)) || (iscolumn (xi) && isrow (yi)))\n      [xi, yi] = meshgrid (xi, yi);\n    else\n      ## Ensure vector and matrix query point inputs are identically sized.\n      if (! size_equal (xi, yi))\n        error (\"griddata: XI and YI must be vectors or matrices of same size\");\n      endif\n    endif\n\n    if (nargin == 6)\n      method = varargin{3};\n      if (isempty (method))\n        method = \"linear\";\n      elseif (! ischar (method))\n        error (\"griddata: METHOD must be a string\");\n      else\n        method = lower (method);\n      endif\n\n      if (any (strcmp (method, {\"linear\", \"nearest\", \"v4\"})))\n        ## Do nothing, these are implemented methods\n      elseif (any (strcmp (method, {\"cubic\", \"natural\"})))\n        ## FIXME: implement missing interpolation methods.\n        error ('griddata: \"%s\" interpolation not yet implemented', method);\n      else\n        error ('griddata: unknown interpolation METHOD: \"%s\"', method);\n      endif\n    else\n      method = \"linear\";\n    endif\n\n    x = x(:);\n    y = y(:);\n    z = z(:);\n\n    ## Triangulate data.\n    if (! strcmp (method, \"v4\"))\n      tri = delaunay (x, y);\n    endif\n    zi = NaN (size (xi));\n\n    if (strcmp (method, \"linear\"))\n      ## Search for every point the enclosing triangle.\n      tri_list = tsearch (x, y, tri, xi(:), yi(:));\n\n      ## Only keep the points within triangles.\n      valid = ! isnan (tri_list);\n      tri_list = tri_list(valid);\n      nr_t = rows (tri_list);\n\n      tri = tri(tri_list,:);\n\n      ## Assign x,y,z for each point of triangle.\n      x1 = x(tri(:,1));\n      x2 = x(tri(:,2));\n      x3 = x(tri(:,3));\n\n      y1 = y(tri(:,1));\n      y2 = y(tri(:,2));\n      y3 = y(tri(:,3));\n\n      z1 = z(tri(:,1));\n      z2 = z(tri(:,2));\n      z3 = z(tri(:,3));\n\n      ## Calculate norm vector.\n      N = cross ([x2-x1, y2-y1, z2-z1], [x3-x1, y3-y1, z3-z1], 2);\n\n      ## Normalize.\n      N = diag (norm (N, \"rows\")) \\ N;\n\n      ## Calculate D of plane equation: Ax+By+Cz+D = 0\n      D = -(N(:,1) .* x1 + N(:,2) .* y1 + N(:,3) .* z1);\n\n      ## Calculate zi by solving plane equation for xi, yi.\n      zi(valid) = -(N(:,1).*xi(:)(valid) + N(:,2).*yi(:)(valid) + D) ./ N(:,3);\n\n    elseif (strcmp (method, \"nearest\"))\n      ## Search index of nearest point.\n      idx = dsearchn ([x(:), y(:)], tri, [xi(:), yi(:)]);\n      valid = ! isnan (idx);\n      zi(valid) = z(idx(valid));\n\n    elseif (strcmp (method, \"v4\"))\n      ## Use Biharmonic Spline Interpolation Green's Function method.\n      ## Compatible with Matlab v4 interpolation method, based on\n      ## D. Sandwell 1987 and Deng & Tang 2011.\n\n      ## The free space Green Function which solves the two-dimensional\n      ## Biharmonic PDE\n      ##\n      ## Delta(Delta(G(X))) = delta(X)\n      ##\n      ## for a point source yields\n      ##\n      ## G(X) = |X|^2 * (ln|X|-1) / (8 * pi)\n      ##\n      ## An N-point Biharmonic Interpolation at the point X is given by\n      ##\n      ## z(X) = sum_j_N (alpha_j * G(X-Xj))\n      ##      = sum_j_N (alpha_j * G(rj))\n      ##\n      ## in which the coefficients alpha_j are the unknowns.  rj is the\n      ## Euclidean distance between X and Xj.\n      ## From N datapoints {zi, Xi} an equation system can be formed:\n      ##\n      ## zi(Xi) = sum_j_N (alpha_j * G(Xi-Xj))\n      ##        = sum_j_N (alpha_j * G(rij))\n      ##\n      ## Its inverse yields the unknowns alpha_j.\n\n      ## Step1: Solve for weight coefficients alpha_j depending on the\n      ## Euclidean distances and the training data set {x,y,z}\n      r = sqrt ((x - x.').^2 + (y - y.').^2);  # size N^2\n      D = (r.^2) .* (log (r) - 1);\n      D(isnan (D)) = 0;  # Fix Green Function for r=0\n      alpha_j = D \\ z;\n\n      ## Step2 - Use alphas and Green's functions to get interpolated points.\n      ## Use dim3 projection for vectorized calculation to avoid loops.\n      ## Memory usage is proportional to Ni x N.\n      ## FIXME: if this approach is too memory intensive, revert portion to loop\n      x = permute (x, [3, 2, 1]);\n      y = permute (y, [3, 2, 1]);\n      alpha_j = permute (alpha_j, [3, 2, 1]);\n      r_i = sqrt ((xi - x).^2 + (yi - y).^2);  # size Ni x N\n      Di = (r_i.^2) .* (log (r_i) - 1);\n      Di(isnan (Di)) = 0;  # Fix Green's Function for r==0\n      zi = sum (Di .* alpha_j, 3);\n\n    endif\n\n    if (nargout > 1)\n      rx = xi;\n      ry = yi;\n      rz = zi;\n    else\n      rx = zi;\n    endif\n\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! x = 2*rand (100,1) - 1;\n%! y = 2*rand (size (x)) - 1;\n%! z = sin (2*(x.^2 + y.^2));\n%! [xx,yy] = meshgrid (linspace (-1, 1, 32));\n%! zz = griddata (x,y,z,xx,yy);\n%! mesh (xx, yy, zz);\n%! title (\"non-uniform grid sampled at 100 points\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! x = 2*rand (1000,1) - 1;\n%! y = 2*rand (size (x)) - 1;\n%! z = sin (2*(x.^2 + y.^2));\n%! [xx,yy] = meshgrid (linspace (-1, 1, 32));\n%! zz = griddata (x,y,z,xx,yy);\n%! mesh (xx, yy, zz);\n%! title ({\"non-uniform grid sampled at 1,000 points\",\n%!         'method = \"linear\"'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! x = 2*rand (1000,1) - 1;\n%! y = 2*rand (size (x)) - 1;\n%! z = sin (2*(x.^2 + y.^2));\n%! [xx,yy] = meshgrid (linspace (-1, 1, 32));\n%! zz = griddata (x,y,z,xx,yy,\"nearest\");\n%! mesh (xx, yy, zz);\n%! title ({\"non-uniform grid sampled at 1,000 points\",\n%!         'method = \"nearest neighbor\"'});\n\n%!testif HAVE_QHULL\n%! [xx, yy] = meshgrid (linspace (-1, 1, 32));\n%! x = xx(:);\n%! x = x + 10*(2*round (rand (size (x))) - 1) * eps;\n%! y = yy(:);\n%! y = y + 10*(2*round (rand (size (y))) - 1) * eps;\n%! z = sin (2*(x.^2 + y.^2));\n%! zz = griddata (x,y,z,xx,yy, \"linear\");\n%! zz2 = sin (2*(xx.^2 + yy.^2));\n%! zz2(isnan (zz)) = NaN;\n%! assert (zz, zz2, 100*eps);\n\n%!testif HAVE_QHULL\n%! [xx, yy] = meshgrid (linspace (-1, 1, 5));\n%! x = xx(:);\n%! x = x + 10*(2*round (rand (size (x))) - 1) * eps;\n%! y = yy(:);\n%! y = y + 10*(2*round (rand (size (y))) - 1) * eps;\n%! z = 2*(x.^2 + y.^2);\n%! zz = griddata (x,y,z,xx,yy, \"v4\");\n%! zz2 = 2*(xx.^2 + yy.^2);\n%! zz2(isnan (zz)) = NaN;\n%! assert (zz, zz2, 100*eps);\n\n%!testif HAVE_QHULL\n%! [xx, yy] = meshgrid (linspace (-1, 1, 5));\n%! x = xx(:);\n%! x = x + 10*(2*round (rand (size (x))) - 1) * eps;\n%! y = yy(:);\n%! y = y + 10*(2*round (rand (size (y))) - 1) * eps;\n%! z = 2*(x.^2 + y.^2);\n%! zz = griddata (x,y,z,xx,yy, \"nearest\");\n%! zz2 = 2*(xx.^2 + yy.^2);\n%! zz2(isnan (zz)) = NaN;\n%! assert (zz, zz2, 100*eps);\n\n%!testif HAVE_QHULL <*65146> # Ensure correct output for 3-point queries.\n%! xi = [1 2 3];\n%! a = griddata (xi, xi, xi .* xi', xi, xi, \"linear\");\n%! assert (a, [1, 4, 9], 10*eps);\n%! a = griddata (xi, xi, xi .* xi', xi', xi', \"linear\");\n%! assert (a, [1, 4, 9]', 10*eps);\n%! a = griddata (xi, xi, xi .* xi', [xi; xi], [xi; xi], \"linear\");\n%! assert (a, [1, 4, 9; 1, 4, 9], 10*eps);\n\n## Verify output orientation for various input vector shape combinations\n%!testif HAVE_QHULL <*65134>\n%! x = [1:10];\n%! y = [1:10];\n%! z = x .* y';\n%! xi = [1, 5, 10];\n%! yi = [1, 5];\n%! [xx, yy, vv] = griddata (x, y, z, xi, xi, 'nearest'); # Row, Row\n%! assert (xx, xi);\n%! assert (yy, xi);\n%! assert (size (vv), [1, 3]);\n%! [xx, yy, vv] = griddata (x, y, z, xi', xi', 'nearest'); # Col, Col\n%! assert (xx, xi');\n%! assert (yy, xi');\n%! assert (size (vv), [3, 1]);\n%! [xx, yy, vv] = griddata (x, y, z, xi, yi', 'nearest'); # Row, Col\n%! assert (xx, [xi; xi]);\n%! assert (yy, [yi', yi', yi']);\n%! assert (vv, [1, 5, 10; 5, 25, 50]);\n%! [xx, yy, vv] = griddata (x, y, z, xi', yi, 'nearest'); # Col, Row\n%! assert (xx, [xi; xi]);\n%! assert (yy, [yi', yi', yi']);\n%! assert (vv, [1, 5, 10; 5, 25, 50]);\n\n## Test input validation\n%!error <Invalid call> griddata ()\n%!error <Invalid call> griddata (1)\n%!error <Invalid call> griddata (1,2)\n%!error <Invalid call> griddata (1,2,3)\n%!error <Invalid call> griddata (1,2,3,4)\n%!error <only one output argument> [xi,yi] = griddata (1,2,3,4,5,6,7)\n%!error <vectors of the same length> griddata (1:4, 1:3, 1:3, 1:3, 1:3)\n%!error <vectors of the same length> griddata (1:3, 1:4, 1:3, 1:3, 1:3)\n%!error <vectors of the same length> griddata (1:3, 1:3, 1:4, 1:3, 1:3)\n%!error <the columns and rows of Z> griddata (1:4, 1:3, ones (4,4), 1:3, 1:3)\n%!error <the columns and rows of Z> griddata (1:4, 1:3, ones (3,5), 1:3, 1:3)\n%!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, 1:4, 1:3)\n%!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, 1:3, 1:4)\n%!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, [1:4]', [1:3]')\n%!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, [1:3]', [1:4]')\n%!error <METHOD must be a string> griddata (1,2,3,4,5, {\"linear\"})\n%!error <\"cubic\" .* not yet implemented> griddata (1,2,3,4,5, \"cubic\")\n%!error <\"natural\" .* not yet implemented> griddata (1,2,3,4,5, \"natural\")\n%!error <unknown interpolation METHOD: \"foobar\"> griddata (1,2,3,4,5, \"foobar\")\n"
  },
  {
    "path": "scripts/geometry/griddata3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{vi} =} griddata3 (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi})\n## @deftypefnx {} {@var{vi} =} griddata3 (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi}, @var{method})\n## @deftypefnx {} {@var{vi} =} griddata3 (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi}, @var{method}, @var{options})\n##\n## Interpolate irregular 3-D source data at specified points.\n##\n## The inputs @var{x}, @var{y}, and @var{z} define the points where the\n## function @code{@var{v} = f (@var{x}, @var{y}, @var{z})} is evaluated.  The\n## inputs @var{x}, @var{y}, @var{z} are either vectors of the same length, or\n## if they are of unequal length, then they are expanded to a 3-D grid with\n## @code{meshgrid}.  The size of the input @var{v} must match the size of the\n## original data, either as a vector or a matrix.\n##\n## The interpolation points are specified by @var{xi}, @var{yi}, @var{zi}.\n##\n## The optional input interpolation @var{method} can be @qcode{\"nearest\"} or\n## @qcode{\"linear\"}.  When the method is @qcode{\"nearest\"}, the output @var{vi}\n## will be the closest point in the original data (@var{x}, @var{y}, @var{z})\n## to the query point (@var{xi}, @var{yi}, @var{zi}).  When the method is\n## @qcode{\"linear\"}, the output @var{vi} will be a linear interpolation between\n## the two closest points in the original source data in each dimension.\n## If @var{method} is omitted or empty, it defaults to @qcode{\"linear\"}.\n##\n## The optional argument @var{options} is passed directly to Qhull when\n## computing the Delaunay triangulation used for interpolation.  See\n## @code{delaunayn} for information on the defaults and how to pass different\n## values.\n##\n## Programming Notes: If the input is complex the real and imaginary parts\n## are interpolated separately.  Interpolation is based on a Delaunay\n## triangulation and any query values outside the convex hull of the input\n## points will return @code{NaN}.\n## @seealso{griddata, griddatan, delaunayn}\n## @end deftypefn\n\nfunction vi = griddata3 (x, y, z, v, xi, yi, zi, method = \"linear\", varargin)\n\n  if (nargin < 7)\n    print_usage ();\n  endif\n\n  if (isvector (x) && isvector (y) && isvector (z) && isvector (v))\n    if (! isequal (length (x), length (y), length (z), length (v)))\n      error (\"griddata: X, Y, Z, and V must be vectors of the same length\");\n    endif\n  elseif (! size_equal (x, y, z, v))\n    error (\"griddata: X, Y, Z, and V must have equal sizes\");\n  endif\n\n  ## meshgrid xi, yi and zi if they are vectors unless\n  ## they are vectors of the same length.\n  if (isvector (xi) && isvector (yi) && isvector (zi))\n    if (! isequal (length (xi), length (yi), length (zi)))\n      [xi, yi, zi] = meshgrid (xi, yi, zi);\n    else\n      ## Otherwise, convert to column vectors\n      xi = xi(:);\n      yi = yi(:);\n      zi = zi(:);\n    endif\n  endif\n\n  if (! size_equal (xi, yi, zi))\n    error (\"griddata3: XI, YI, and ZI must be vectors or matrices of the same size\");\n  endif\n\n  vi = griddatan ([x(:), y(:), z(:)], v(:), [xi(:), yi(:), zi(:)], method, ...\n                  varargin{:});\n  vi = reshape (vi, size (xi));\n\nendfunction\n\n\n%!testif HAVE_QHULL\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 0);\n%! x = 2 * rand (1000, 1) - 1;\n%! y = 2 * rand (1000, 1) - 1;\n%! z = 2 * rand (1000, 1) - 1;\n%! v = x.^2 + y.^2 + z.^2;\n%! [xi, yi, zi] = meshgrid (-0.8:0.2:0.8);\n%! vi = griddata3 (x, y, z, v, xi, yi, zi, \"linear\");\n%! vv = vi - xi.^2 - yi.^2 - zi.^2;\n%! assert (max (abs (vv(:))), 0, 0.1);\n\n%!testif HAVE_QHULL\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 0);\n%! x = 2 * rand (1000, 1) - 1;\n%! y = 2 * rand (1000, 1) - 1;\n%! z = 2 * rand (1000, 1) - 1;\n%! v = x.^2 + y.^2 + z.^2;\n%! [xi, yi, zi] = meshgrid (-0.8:0.2:0.8);\n%! vi = griddata3 (x, y, z, v, xi, yi, zi, \"nearest\");\n%! vv = vi - xi.^2 - yi.^2 - zi.^2;\n%! assert (max (abs (vv(:))), 0.385, 0.1);\n\n## FIXME: Ideally, there should be BIST tests for input validation.\n## However, this function is deprecated in Matlab and it probably isn't worth\n## the coding time to work on a function that will be removed soon.\n"
  },
  {
    "path": "scripts/geometry/griddatan.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{yi} =} griddatan (@var{x}, @var{y}, @var{xi})\n## @deftypefnx {} {@var{yi} =} griddatan (@var{x}, @var{y}, @var{xi}, @var{method})\n## @deftypefnx {} {@var{yi} =} griddatan (@var{x}, @var{y}, @var{xi}, @var{method}, @var{options})\n##\n## Interpolate irregular source data @var{x}, @var{y} at points specified by\n## @var{xi}.\n##\n## The input @var{x} is an MxN matrix representing M points in an N-dimensional\n## space.  The input @var{y} is a single-valued column vector (Mx1)\n## representing a function evaluated at the points @var{x}, i.e.,\n## @code{@var{y} = fcn (@var{x})}.  The input @var{xi} is a list of points\n## for which the function output @var{yi} should be approximated through\n## interpolation.  @var{xi} must have the same number of columns (@var{N})\n## as @var{x} so that the dimensionality matches.\n##\n## The optional input interpolation @var{method} can be @qcode{\"nearest\"} or\n## @qcode{\"linear\"}.  When the method is @qcode{\"nearest\"}, the output @var{yi}\n## will be the closest point in the original data @var{x} to the query point\n## @var{xi}.  When the method is @qcode{\"linear\"}, the output @var{yi} will\n## be a linear interpolation between the two closest points in the original\n## source data.  If @var{method} is omitted or empty, it defaults to\n## @qcode{\"linear\"}.\n##\n## The optional argument @var{options} is passed directly to Qhull when\n## computing the Delaunay triangulation used for interpolation.  See\n## @code{delaunayn} for information on the defaults and how to pass different\n## values.\n##\n## Example\n##\n## @example\n## @group\n## ## Evaluate sombrero() function at irregular data points\n## x = 16*gallery (\"uniformdata\", [200,1], 1) - 8;\n## y = 16*gallery (\"uniformdata\", [200,1], 11) - 8;\n## z = sin (sqrt (x.^2 + y.^2)) ./ sqrt (x.^2 + y.^2);\n## ## Create a regular grid and interpolate data\n## [xi, yi] = ndgrid (linspace (-8, 8, 50));\n## zi = griddatan ([x, y], z, [xi(:), yi(:)]);\n## zi = reshape (zi, size (xi));\n## ## Plot results\n## clf ();\n## plot3 (x, y, z, \"or\");\n## hold on\n## surf (xi, yi, zi);\n## legend (\"Original Data\", \"Interpolated Data\");\n## @end group\n## @end example\n##\n## Programming Notes: If the input is complex the real and imaginary parts\n## are interpolated separately.  Interpolation is based on a Delaunay\n## triangulation and any query values outside the convex hull of the input\n## points will return @code{NaN}.  For 2-D and 3-D data additional\n## interpolation methods are available by using the @code{griddata} function.\n## @seealso{griddata, griddata3, delaunayn}\n## @end deftypefn\n\nfunction yi = griddatan (x, y, xi, method = \"linear\", varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  [m, n] = size (x);\n  [mi, ni] = size (xi);\n\n  if (m < n + 1)\n    error (\"griddatan: number of points in X (rows of X) must be greater than dimensionality of data + 1 (columns of X + 1)\");\n  endif\n  if (! iscolumn (y) || rows (y) != m)\n    error (\"griddatan: Y must be a column vector with the same number of points (rows) as X\");\n  endif\n  if (n != ni)\n    error (\"griddatan: dimension of query data XI (columns) must match X\");\n  endif\n\n  if (nargin > 3)\n    if (isempty (method))\n      method = \"linear\";\n    elseif (! ischar (method))\n      error (\"griddatan: METHOD must be a string\");\n    else\n      method = lower (method);\n    endif\n\n    if (strcmp (method, \"linear\") || strcmp (method, \"nearest\"))\n      ## Do nothing, these are implemented methods\n    elseif (strcmp (method, \"v4\"))\n      error ('griddatan: \"%s\" METHOD is available for 2-D inputs by using \"griddata\"', method);\n\n    elseif (any (strcmp (method, {\"cubic\", \"natural\"})))\n      ## FIXME: Remove when griddata.m supports these methods.\n      error ('griddatan: \"%s\" interpolation METHOD not yet implemented', method);\n\n    else\n      error ('griddatan: unknown interpolation METHOD: \"%s\"', method);\n    endif\n\n  endif\n\n  ## triangulate data\n  tri = delaunayn (x, varargin{:});\n\n  yi = NaN (mi, 1);\n\n  if (strcmp (method, \"linear\"))\n    ## search for every point the enclosing triangle\n    [tri_list, bary_list] = tsearchn (x, tri, xi);\n\n    ## only keep the points within triangles.\n    valid = ! isnan (tri_list);\n    tri_list = tri_list(valid);\n    bary_list = bary_list(valid, :);\n    nr_t = rows (tri_list);\n\n    ## Use barycentric coordinate of point to calculate yi\n    if (isscalar (tri_list))\n      ## Special case required by orientation rules for vector/vector index.\n      yi(valid) = sum (y(tri(tri_list,:)).' .* bary_list, 2);\n    else\n      yi(valid) = sum (y(tri(tri_list,:)) .* bary_list, 2);\n    endif\n\n  else\n    ## search index of nearest point\n    idx = dsearchn (x, tri, xi);\n    valid = ! isnan (idx);\n    yi(valid) = y(idx(valid));\n\n  endif\n\nendfunction\n\n\n%!testif HAVE_QHULL\n%! [xx,yy] = meshgrid (linspace (-1,1,32));\n%! xi = [xx(:), yy(:)];\n%! x = 2*rand (100,2) - 1;\n%! x = [x;1,1;1,-1;-1,-1;-1,1];\n%! y = sin (2 * sum (x.^2,2));\n%! zz = griddatan (x,y,xi, \"linear\");\n%! zz2 = griddata (x(:,1),x(:,2),y,xi(:,1),xi(:,2), \"linear\");\n%! assert (zz, zz2, 1e-10);\n\n%!testif HAVE_QHULL\n%! [xx,yy] = meshgrid (linspace (-1,1,32));\n%! xi = [xx(:), yy(:)];\n%! x = 2*rand (100,2) - 1;\n%! x = [x;1,1;1,-1;-1,-1;-1,1];\n%! y = sin (2*sum (x.^2,2));\n%! zz = griddatan (x,y,xi, \"nearest\");\n%! zz2 = griddata (x(:,1),x(:,2),y,xi(:,1),xi(:,2), \"nearest\");\n%! assert (zz, zz2, 1e-10);\n\n%!testif HAVE_QHULL <*56515>\n%! x = [ 0, 0; 1, 1; 0, 1; 1, 0 ];\n%! y = [ 1; 2; 3; 4 ];\n%! xi = [ .5, .5 ];\n%! yi = griddatan (x, y, xi);\n\n## Test input validation\n%!error <Invalid call> griddatan ()\n%!error <Invalid call> griddatan (1)\n%!error <Invalid call> griddatan (1,2)\n%!error <number of points in X> griddatan (1,2,3)\n%!error <Y must be a column vector> griddatan ([1;2],[3,4], 1)\n%!error <Y must .* same number of points .* as X> griddatan ([1;2],[3;4;5], 1)\n%!error <dimension of .* XI .* must match X> griddatan ([1;2],[3;4], [1, 2])\n%!error <METHOD must be a string> griddatan ([1;2],[3;4], 1, 5)\n%!error <\"v4\" METHOD is available for 2-D> griddatan ([1;2],[3;4], 1, \"v4\")\n%!error <\"cubic\" .* not yet implemented> griddatan ([1;2],[3;4], 1, \"cubic\")\n%!error <\"natural\" .* not yet implemented> griddatan ([1;2],[3;4], 1, \"natural\")\n%!error <unknown .* METHOD: \"foobar\"> griddatan ([1;2],[3;4], 1, \"foobar\")\n"
  },
  {
    "path": "scripts/geometry/inpolygon.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{in} =} inpolygon (@var{x}, @var{y}, @var{xv}, @var{yv})\n## @deftypefnx {} {[@var{in}, @var{on}] =} inpolygon (@var{x}, @var{y}, @var{xv}, @var{yv})\n##\n## For a polygon defined by vertex points @code{(@var{xv}, @var{yv})}, return\n## true if the points @code{(@var{x}, @var{y})} are inside (or on the boundary)\n## of the polygon; Otherwise, return false.\n##\n## The input variables @var{x} and @var{y}, must have the same dimension.\n##\n## The optional output @var{on} returns true if the points are exactly on the\n## polygon edge, and false otherwise.\n## @seealso{delaunay}\n## @end deftypefn\n\n## Algorithm: The method for determining if a point is in a polygon is based on\n## the PnPoly algorithm from Prof W. Randolph Franklin,\n## (Rensselaer Polytechnic Institute, Troy NY), originally written in 1970.\n## URL: http://wrfranklin.org/pnpoly\n\nfunction [in, on] = inpolygon (x, y, xv, yv)\n\n  if (nargin != 4)\n    print_usage ();\n  endif\n\n  if (! (isreal (x) && isreal (y) && isnumeric (x) && isnumeric (y)\n         && size_equal (x, y)))\n    error (\"inpolygon: X and Y must be real arrays of the same size\");\n  elseif (! (isreal (xv) && isreal (yv) && isvector (xv) && isvector (yv)\n             && size_equal (xv, yv)))\n    error (\"inpolygon: XV and YV must be real vectors of the same size\");\n  endif\n\n  npol = length (xv);\n\n  in = on = false (size (x));\n\n  j = npol;\n  for i = 1 : npol\n    delta_xv = xv(j) - xv(i);\n    delta_yv = yv(j) - yv(i);\n    ## distance = [distance from (x,y) to edge] * length(edge)\n    distance = delta_xv .* (y - yv(i)) - (x - xv(i)) .* delta_yv;\n\n    ## is y between the y-values of edge i,j AND (x,y) on the left of the edge?\n    idx1 = (((yv(i) <= y & y < yv(j)) | (yv(j) <= y & y < yv(i)))\n            & 0 < distance.*delta_yv);\n    in(idx1) = ! in(idx1);\n\n    ## Check if (x,y) are actually on the boundary of the polygon.\n    idx2 = (((yv(i) <= y & y <= yv(j)) | (yv(j) <= y & y <= yv(i)))\n            & ((xv(i) <= x & x <= xv(j)) | (xv(j) <= x & x <= xv(i)))\n            & (0 == distance | ! delta_xv));\n    on(idx2) = true;\n\n    j = i;\n  endfor\n\n  ## Matlab definition include both in polygon and on polygon points.\n  in |= on;\n\nendfunction\n\n\n%!demo\n%! xv = [ 0.05840, 0.48375, 0.69356, 1.47478, 1.32158, ...\n%!        1.94545, 2.16477, 1.87639, 1.18218, 0.27615, ...\n%!        0.05840 ];\n%! yv = [ 0.60628, 0.04728, 0.50000, 0.50000, 0.02015, ...\n%!        0.18161, 0.78850, 1.13589, 1.33781, 1.04650, ...\n%!        0.60628 ];\n%! xa = [0:0.1:2.3];\n%! ya = [0:0.1:1.4];\n%! [x,y] = meshgrid (xa, ya);\n%! [in,on] = inpolygon (x, y, xv, yv);\n%! inside = in & ! on;\n%!\n%! clf;\n%! plot (xv, yv);\n%! hold on;\n%! plot (x(inside), y(inside), \"og\");\n%! plot (x(! in), y(! in), \"sm\");\n%! plot (x(on), y(on), \"^b\");\n%! hold off;\n%! disp (\"Green circles are inside polygon, magenta squares are outside,\");\n%! disp (\"and blue triangles are on the boundary.\");\n\n%!demo\n%!  xv = [ 0.05840, 0.48375, 0.69356, 1.47478, 1.32158, ...\n%!         1.94545, 2.16477, 1.87639, 1.18218, 0.27615, ...\n%!         0.05840, 0.73295, 1.28913, 1.74221, 1.16023, ...\n%!         0.73295, 0.05840 ];\n%!  yv = [ 0.60628, 0.04728, 0.50000, 0.50000, 0.02015, ...\n%!         0.18161, 0.78850, 1.13589, 1.33781, 1.04650, ...\n%!         0.60628, 0.82096, 0.67155, 0.96114, 1.14833, ...\n%!         0.82096, 0.60628];\n%! xa = [0:0.1:2.3];\n%! ya = [0:0.1:1.4];\n%! [x, y] = meshgrid (xa, ya);\n%! [in, on] = inpolygon (x, y, xv, yv);\n%! inside = in & ! on;\n%!\n%! clf;\n%! plot (xv, yv);\n%! hold on;\n%! plot (x(inside), y(inside), \"og\");\n%! plot (x(! in), y(! in), \"sm\");\n%! plot (x(on), y(on), \"^b\");\n%! hold off;\n%! disp (\"Green circles are inside polygon, magenta squares are outside,\");\n%! disp (\"and blue triangles are on the boundary.\");\n\n%!test\n%! [in, on] = inpolygon ([1, 0, 2], [1, 0, 0], [-1, -1, 1, 1], [-1, 1, 1, -1]);\n%! assert (in, [true, true, false]);\n%! assert (on, [true, false, false]);\n\n## 3-D array input\n%!test\n%! x = zeros (2, 2, 2);\n%! x(1, 1, 1) = 1;\n%! x(2, 2, 2) = 2;\n%! y = zeros (2, 2, 2);\n%! y(1, 1, 1) = 1;\n%! y(2, 2, 2) = -1;\n%! [in, on] = inpolygon (x, y, [-1, -1, 1, 1], [-1, 1, 1, -1]);\n%! IN = true (2, 2, 2);\n%! IN(2, 2, 2) = false;\n%! ON = false (2, 2, 2);\n%! ON(1, 1, 1) = true;\n%! assert (in, IN);\n%! assert (on, ON);\n\n## Test input validation\n%!error <Invalid call> inpolygon ()\n%!error <Invalid call> inpolygon (1, 2)\n%!error <Invalid call> inpolygon (1, 2, 3)\n%!error <X and Y must be real> inpolygon (1i, 1, [3, 4], [5, 6])\n%!error <X and Y must be real> inpolygon (1, {1}, [3, 4], [5, 6])\n%!error <X and Y must be .* the same size> inpolygon (1, [1,2], [3, 4], [5, 6])\n%!error <X and Y must be .* the same size> inpolygon (1, ones (1,1,2), [3, 4], [5, 6])\n%!error <XV and YV must be real vectors> inpolygon (1, 1, [3i, 4], [5, 6])\n%!error <XV and YV must be real vectors> inpolygon (1, 1, [3, 4], {5, 6})\n%!error <XV and YV must .* the same size> inpolygon ([1,2], [3, 4], [5, 6], 1)\n"
  },
  {
    "path": "scripts/geometry/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/convhull.m \\\n  %reldir%/delaunay.m \\\n  %reldir%/delaunayn.m \\\n  %reldir%/dsearchn.m \\\n  %reldir%/griddata.m \\\n  %reldir%/griddata3.m \\\n  %reldir%/griddatan.m \\\n  %reldir%/inpolygon.m \\\n  %reldir%/rectint.m \\\n  %reldir%/rotx.m \\\n  %reldir%/roty.m \\\n  %reldir%/rotz.m \\\n  %reldir%/tsearchn.m \\\n  %reldir%/voronoi.m \\\n  %reldir%/voronoin.m\n\n%canon_reldir%dir = $(fcnfiledir)/geometry\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/geometry/rectint.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{area} =} rectint (@var{a}, @var{b})\n## Compute area or volume of intersection of rectangles or N-D boxes.\n##\n## Compute the area of intersection of rectangles in @var{a} and rectangles in\n## @var{b}.  N-dimensional boxes are supported in which case the volume, or\n## hypervolume is computed according to the number of dimensions.\n##\n## 2-dimensional rectangles are defined as @code{[xpos ypos width height]}\n## where xpos and ypos are the position of the bottom left corner.  Higher\n## dimensions are supported where the coordinates for the minimum value of each\n## dimension follow the length of the box in that dimension, e.g.,\n## @code{[xpos ypos zpos kpos @dots{} width height depth k_length @dots{}]}.\n##\n## Each row of @var{a} and @var{b} define a rectangle, and if both define\n## multiple rectangles, then the output, @var{area}, is a matrix where the i-th\n## row corresponds to the i-th row of a and the j-th column corresponds to the\n## j-th row of b.\n##\n## @seealso{polyarea}\n## @end deftypefn\n\nfunction dists = rectint (a, b)\n\n  if (nargin != 2)\n    print_usage ();\n  elseif (columns (a) != columns (b))\n    error (\"rectint: A and B must have same number of columns\");\n  elseif (ndims (a) > 2)\n    error (\"rectint: A and B must be 2-D arrays\");\n  elseif (mod (columns (a), 2))\n    error (\"rectint: number of columns of A and B must be a multiple of two\");\n  endif\n\n  nd = columns (a) / 2;\n  na = rows (a);\n  nb = rows (b);\n\n  a_start = a(:,1:nd);\n  b_start = b(:,1:nd);\n\n  a_end = a_start + a(:,nd+1:end);\n  b_end = b_start + b(:,nd+1:end);\n\n  a_start = reshape (a_start, [na 1 nd]);\n  b_start = reshape (b_start, [1 nb nd]);\n\n  a_end   = reshape (a_end,   [na 1 nd]);\n  b_end   = reshape (b_end,   [1 nb nd]);\n\n  ## We get a 3-D matrix where each dimension is in the 3rd dimension\n  dists = bsxfun (@min , a_end, b_end) - bsxfun (@max, a_start, b_start);\n  dists(dists < 0) = 0;\n  dists = prod (dists, 3);\n\nendfunction\n\n\n## Exactly overlapping\n%!assert (rectint ([0 0 1 1], [0 0 1 1]), 1)\n## rect2 completely enclosed by rect1\n%!assert (rectint ([-1 -1 3 3], [0 0 1 1]), 1)\n## rect1 completely enclosed by rect2\n%!assert (rectint ([0 0 1 1], [-1 -1 3 3]), 1)\n## rect1 right and top in rect2\n%!assert (rectint ([-1 -1 1.5 1.5], [0 0 1 1]), 0.25)\n## rect2 right and top in rect1\n%!assert (rectint ([0 0 1 1], [-1 -1 1.5 1.5]), 0.25)\n## no overlap - shared corner\n%!assert (rectint ([0 0 1 1], [1 1 2 2]), 0)\n## no overlap - shared edge\n%!assert (rectint ([0 0 1 1], [0 1 2 2]), 0)\n## Correct orientation of output\n%!assert (rectint ([0 0 1 1;0.5 0.5 1 1;-1 -1 2 2], [1 1 2 2]), [0;0.25;0])\n%!assert (rectint ([1 1 2 2], [0 0 1 1;0.5 0.5 1 1;-1 -1 2 2]), [0 0.25 0])\n\n%!assert <*44904> (rectint ([0 0 5 5], [6 6 5 5]), 0)\n%!assert <*44904> (rectint ([0 0 5 5], [0 6 5 5]), 0)\n%!assert <*44904> (rectint ([0 0 5 5], [6 0 5 5]), 0)\n%!assert <*44904> (rectint ([0 0 0 5 5 5], [0 0 6 5 5 5]), 0)\n\n## Test volumes\n%!shared r1, r2, r3, r4, r5\n%! r1 = [  5   3 0  7   5 2];\n%! r2 = [  2   5 0  4   2 2];\n%! r3 = [ 10   7 0 10   3 2];\n%! r4 = [ 10  -5 0  5   7 2];\n%! r5 = [-10   0 0 40  11 2];\n\n%!assert (rectint (r5, r1), 70)\n%!assert (rectint (r5, r4), 20)\n%!assert (rectint (r5, [r1; r2; r3; r4]), [70 16 60 20])\n\n## Test multiple volumes in both A and B\n%!assert (rectint ([r2; r5], [r1; r3; r4]), [4 0 0; 70 60 20])\n"
  },
  {
    "path": "scripts/geometry/rotx.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{T} =} rotx (@var{angle})\n##\n## @code{rotx} returns the 3x3 transformation matrix corresponding to an active\n## rotation of a vector about the x-axis by the specified @var{angle}, given in\n## degrees, where a positive angle corresponds to a counterclockwise\n## rotation when viewing the y-z plane from the positive x side.\n##\n## The form of the transformation matrix is:\n## @tex\n## $$\n## T = \\left[\\matrix{ 1 & 0 & 0 \\cr\n##                    0 & \\cos(angle) & -\\sin(angle)\\cr\n##                    0 & \\sin(angle) & \\cos(angle)}\\right].\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##      | 1      0           0      |\n##  T = | 0  cos(@var{angle}) -sin(@var{angle}) |\n##      | 0  sin(@var{angle})  cos(@var{angle}) |\n## @end group\n## @end example\n## @end ifnottex\n##\n## This rotation matrix is intended to be used as a left-multiplying matrix\n## when acting on a column vector, using the notation\n## @code{@var{v} = @var{T}*@var{u}}.\n## For example, a vector, @var{u}, pointing along the positive y-axis, rotated\n## 90-degrees about the x-axis, will result in a vector pointing along the\n## positive z-axis:\n##\n## @example\n## @group\n## >> u = [0 1 0]'\n## u =\n##    0\n##    1\n##    0\n##\n## >> T = rotx (90)\n## T =\n##    1.00000   0.00000   0.00000\n##    0.00000   0.00000  -1.00000\n##    0.00000   1.00000   0.00000\n##\n## >> v = T*u\n## v =\n##    0.00000\n##    0.00000\n##    1.00000\n## @end group\n## @end example\n##\n## @seealso{roty, rotz}\n## @end deftypefn\n\nfunction T = rotx (angle)\n\n  if (nargin < 1 || ! isscalar (angle))\n    print_usage ();\n  endif\n\n  angle *= pi / 180;\n\n  s = sin (angle);\n  c = cos (angle);\n\n  T = [1 0 0; 0 c -s; 0 s c];\n\nendfunction\n\n\n## Function output tests\n%!assert (rotx (0), [1 0 0; 0 1 0; 0 0 1])\n%!assert (rotx (45), [1, 0, 0; [0; 0],[(sqrt(2)/2).*[1 -1; 1 1]]], 1e-12)\n%!assert (rotx (90), [1 0 0; 0 0 -1; 0 1 0], 1e-12)\n%!assert (rotx (180), [1 0 0; 0 -1 0; 0 0 -1], 1e-12)\n\n## Test input validation\n%!error <Invalid call> rotx ()\n%!error <Invalid call> rotx ([1 2 3])\n"
  },
  {
    "path": "scripts/geometry/roty.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{T} =} roty (@var{angle})\n##\n## @code{roty} returns the 3x3 transformation matrix corresponding to an active\n## rotation of a vector about the y-axis by the specified @var{angle}, given in\n## degrees, where a positive angle corresponds to a counterclockwise\n## rotation when viewing the z-x plane from the positive y side.\n##\n## The form of the transformation matrix is:\n## @tex\n## $$\n## T = \\left[\\matrix{ \\cos(angle) & 0 & \\sin(angle) \\cr\n##                    0 & 1 & 0 \\cr\n##                    -\\sin(angle) & 0 & \\cos(angle)}\\right].\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##      |  cos(@var{angle})  0  sin(@var{angle}) |\n##  T = |      0       1      0      |\n##      | -sin(@var{angle})  0  cos(@var{angle}) |\n## @end group\n## @end example\n## @end ifnottex\n##\n## This rotation matrix is intended to be used as a left-multiplying matrix\n## when acting on a column vector, using the notation\n## @code{@var{v} = @var{T}*@var{u}}.\n## For example, a vector, @var{u}, pointing along the positive z-axis, rotated\n## 90-degrees about the y-axis, will result in a vector pointing along the\n## positive x-axis:\n##\n## @example\n## @group\n##   >> u = [0 0 1]'\n##    u =\n##       0\n##       0\n##       1\n##\n##    >> T = roty (90)\n##    T =\n##       0.00000   0.00000   1.00000\n##       0.00000   1.00000   0.00000\n##      -1.00000   0.00000   0.00000\n##\n##    >> v = T*u\n##    v =\n##       1.00000\n##       0.00000\n##       0.00000\n## @end group\n## @end example\n##\n## @seealso{rotx, rotz}\n## @end deftypefn\n\nfunction T = roty (angle)\n\n  if (nargin < 1 || ! isscalar (angle))\n    print_usage ();\n  endif\n\n  angle *= pi / 180;\n\n  s = sin (angle);\n  c = cos (angle);\n\n  T = [c 0 s; 0 1 0; -s 0 c];\n\nendfunction\n\n\n## Function output tests\n%!assert (roty (0), [1 0 0; 0 1 0; 0 0 1])\n%!assert (roty (45), [sqrt(2) 0 sqrt(2); 0 2 0; -sqrt(2) 0 sqrt(2)]./2, 1e-12)\n%!assert (roty (90), [0 0 1; 0 1 0; -1 0 0], 1e-12)\n%!assert (roty (180), [-1 0 0; 0 1 0; 0 0 -1], 1e-12)\n\n## Test input validation\n%!error <Invalid call> roty ()\n%!error <Invalid call> roty ([1 2 3])\n"
  },
  {
    "path": "scripts/geometry/rotz.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{T} =} rotz (@var{angle})\n##\n## @code{rotz} returns the 3x3 transformation matrix corresponding to an active\n## rotation of a vector about the z-axis by the specified @var{angle}, given in\n## degrees, where a positive angle corresponds to a counterclockwise\n## rotation when viewing the x-y plane from the positive z side.\n##\n## The form of the transformation matrix is:\n## @tex\n## $$\n## T = \\left[\\matrix{ \\cos(angle) & -\\sin(angle) & 0 \\cr\n##                    \\sin(angle) & \\cos(angle) & 0 \\cr\n##                    0 & 0 & 1}\\right].\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##      | cos(@var{angle}) -sin(@var{angle}) 0 |\n##  T = | sin(@var{angle})  cos(@var{angle}) 0 |\n##      |     0           0      1 |\n## @end group\n## @end example\n## @end ifnottex\n##\n## This rotation matrix is intended to be used as a left-multiplying matrix\n## when acting on a column vector, using the notation\n## @code{@var{v} = @var{T}*@var{u}}.\n## For example, a vector, @var{u}, pointing along the positive x-axis, rotated\n## 90-degrees about the z-axis, will result in a vector pointing along the\n## positive y-axis:\n##\n## @example\n## @group\n##   >> u = [1 0 0]'\n##    u =\n##       1\n##       0\n##       0\n##\n##    >> T = rotz (90)\n##    T =\n##       0.00000  -1.00000   0.00000\n##       1.00000   0.00000   0.00000\n##       0.00000   0.00000   1.00000\n##\n##    >> v = T*u\n##    v =\n##       0.00000\n##       1.00000\n##       0.00000\n## @end group\n## @end example\n##\n## @seealso{rotx, roty}\n## @end deftypefn\n\nfunction T = rotz (angle)\n\n  if (nargin < 1 || ! isscalar (angle))\n    print_usage ();\n  endif\n\n  angle = angle * pi / 180;\n\n  s = sin (angle);\n  c = cos (angle);\n\n  T = [c -s 0; s c 0; 0 0 1];\n\nendfunction\n\n\n## Function output tests\n%!assert (rotz (0), [1 0 0; 0 1 0; 0 0 1])\n%!assert (rotz (45), [(sqrt(2)/2).*[1 -1; 1 1] ,[0; 0]; 0, 0, 1], 1e-12)\n%!assert (rotz (90), [0 -1 0; 1 0 0; 0 0 1], 1e-12)\n%!assert (rotz (180), [-1 0 0; 0 -1 0; 0 0 1], 1e-12)\n\n## Test input validation\n%!error <Invalid call> rotz ()\n%!error <Invalid call> rotz ([1 2 3])\n"
  },
  {
    "path": "scripts/geometry/tsearchn.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{idx} =} tsearchn (@var{x}, @var{t}, @var{xi})\n## @deftypefnx {} {[@var{idx}, @var{p}] =} tsearchn (@var{x}, @var{t}, @var{xi})\n## Find the simplexes enclosing the given points.\n##\n## @code{tsearchn} is typically used with @code{delaunayn}:\n## @code{@var{t} = delaunayn (@var{x})} returns a set of simplexes @code{t},\n## then @code{tsearchn} returns the row index of @var{t} containing each point\n## of @var{xi}.  For points outside the convex hull, @var{idx} is NaN.\n##\n## If requested, @code{tsearchn} also returns the barycentric coordinates\n## @var{p} of the enclosing simplexes.\n##\n## @seealso{tsearch, dsearchn, delaunayn}\n## @end deftypefn\n\nfunction [idx, p] = tsearchn (x, t, xi)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (columns (x) != columns (xi))\n    error (\"tsearchn: number of columns of X and XI must match\");\n  endif\n\n  if (max (t(:)) > rows (x))\n    error (\"tsearchn: triangulation T must not access points outside X\");\n  endif\n\n  if (nargout <= 1 && columns (x) == 2)  # pass to the faster tsearch.cc\n    idx = tsearch (x(:,1), x(:,2), t, xi(:,1), xi(:,2));\n    return;\n  endif\n\n  nt = rows (t);\n  [m, n] = size (x);\n  mi = rows (xi);\n  idx = NaN (mi, 1);\n  p = NaN (mi, n + 1);\n  ni = [1:mi].';\n\n  for i = 1 : nt  # each simplex in turn\n\n    T = x(t(i, :), :);  # T is the current simplex\n    P = xi(ni, :);      # P is the set of points left to calculate\n\n    ## Convert to barycentric coords: these are used to express a point P\n    ## as    P = Beta * T\n    ## where T is a simplex.\n    ##\n    ## If 0 <= Beta <= 1, then the linear combination is also convex,\n    ## and the point P is inside the simplex T, otherwise it is outside.\n    ## Since the equation system is underdetermined, we apply the constraint\n    ## sum (Beta) == 1  to make it unique up to scaling.\n    ##\n    ## Note that the code below is vectorized over P, one point per row.\n\n    b = (P - T(end,:)) / (T(1:end-1,:) - T(end,:));\n    b(:, end+1) = 1 - sum (b, 2);\n\n    ## The points xi are inside the current simplex if\n    ## (all (b >= 0) && all (b <= 1)).  As sum (b,2) == 1, we only need to\n    ## test all(b>=0).\n    inside = all (b >= -1e-12, 2);  # -1e-12 instead of 0 for rounding errors\n    idx(ni(inside)) = i;\n    p(ni(inside), :) = b(inside, :);\n    ni = ni(! inside);\n  endfor\n\nendfunction\n\n\n%!shared x, tri\n%! x = [-1,-1;-1,1;1,-1];\n%! tri = [1, 2, 3];\n%!test\n%! [idx, p] = tsearchn (x,tri,[-1,-1]);\n%! assert (idx, 1);\n%! assert (p, [1,0,0], 1e-12);\n%!test\n%! [idx, p] = tsearchn (x,tri,[-1,1]);\n%! assert (idx, 1);\n%! assert (p, [0,1,0], 1e-12);\n%!test\n%! [idx, p] = tsearchn (x,tri,[1,-1]);\n%! assert (idx, 1);\n%! assert (p, [0,0,1], 1e-12);\n%!test\n%! [idx, p] = tsearchn (x,tri,[-1/3,-1/3]);\n%! assert (idx, 1);\n%! assert (p, [1/3,1/3,1/3], 1e-12);\n%!test\n%! [idx, p] = tsearchn (x,tri,[1,1]);\n%! assert (idx, NaN);\n%! assert (p, [NaN, NaN, NaN]);\n\n## Test input validation\n%!error <Invalid call> tsearchn ()\n%!error <Invalid call> tsearchn (1)\n%!error <Invalid call> tsearchn (1, 2)\n%!error <number of columns of X and XI must match> tsearchn ([1,2], 3, 4)\n%!error <T must not access points outside X> tsearchn (1, 2, 3)\n"
  },
  {
    "path": "scripts/geometry/voronoi.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} voronoi (@var{x}, @var{y})\n## @deftypefnx {} {} voronoi (@var{x}, @var{y}, @var{options})\n## @deftypefnx {} {} voronoi (@dots{}, \"linespec\")\n## @deftypefnx {} {} voronoi (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} voronoi (@dots{})\n## @deftypefnx {} {[@var{vx}, @var{vy}] =} voronoi (@dots{})\n## Plot the Voronoi diagram of points @code{(@var{x}, @var{y})}.\n##\n## The Voronoi facets with points at infinity are not drawn.\n##\n## The @var{options} argument, which must be a string or cell array of strings,\n## contains options passed to the underlying qhull command.\n## See the documentation for the Qhull library for details\n## @url{http://www.qhull.org/html/qh-quick.htm#options}.\n##\n## If @qcode{\"linespec\"} is given it is used to set the color and line style of\n## the plot.\n##\n## If an axes graphics handle @var{hax} is supplied then the Voronoi diagram is\n## drawn on the specified axes rather than in a new figure.\n##\n## If a single output argument is requested then the Voronoi diagram will be\n## plotted and a graphics handle @var{h} to the plot is returned.\n##\n## [@var{vx}, @var{vy}] = voronoi (@dots{}) returns the Voronoi vertices\n## instead of plotting the diagram.\n##\n## @example\n## @group\n## x = rand (10, 1);\n## y = rand (size (x));\n## h = convhull (x, y);\n## [vx, vy] = voronoi (x, y);\n## plot (vx, vy, \"-b\", x, y, \"o\", x(h), y(h), \"-g\");\n## legend (\"\", \"points\", \"hull\");\n## @end group\n## @end example\n##\n## @seealso{voronoin, delaunay, convhull}\n## @end deftypefn\n\nfunction [vx, vy] = voronoi (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  narg = 1;\n  hax = NaN;\n  if (isscalar (varargin{1}) && ishghandle (varargin{1}))\n    hax = varargin{1};\n    if (! isaxes (hax))\n      error (\"voronoi: HAX argument must be an axes object\");\n    endif\n    narg += 1;\n  endif\n\n  if (nargin < 1 + narg || nargin > 3 + narg)\n    print_usage ();\n  endif\n\n  x = varargin{narg++};\n  y = varargin{narg++};\n\n  opts = {};\n  if (narg <= nargin)\n    if (iscell (varargin{narg}))\n      opts = varargin(narg++);\n    elseif (isnumeric (varargin{narg}))\n      ## Accept, but ignore, the triangulation\n      narg += 1;\n    endif\n  endif\n\n  linespec = {\"b\"};\n  if (narg <= nargin && ischar (varargin{narg}))\n    linespec = varargin(narg);\n  endif\n\n  if (! isvector (x) || ! isvector (y) || numel (x) != numel (y))\n    error (\"voronoi: X and Y must be vectors of the same length\");\n  elseif (numel (x) < 2)\n    error (\"voronoi: minimum of 2 points required\");\n  endif\n  x = x(:);\n  y = y(:);\n\n  ## Add box to approximate rays to infinity.  For Voronoi diagrams the\n  ## box should be close to the points themselves.  To make the job of\n  ## finding the exterior edges easier it should be bigger than the area\n  ## enclosed by the points themselves.\n  ## NOTE: Octave uses a factor of 2 although we don't have an mathematical\n  ## justification for that.\n\n  xmin = min (x);\n  xmax = max (x);\n  ymin = min (y);\n  ymax = max (y);\n  ## Factor for size of bounding box\n  scale = 2;\n  xdelta = xmax - xmin;\n  ydelta = ymax - ymin;\n  xbox = [xmin - scale * xdelta; xmin - scale * xdelta;\n          xmax + scale * xdelta; xmax + scale * xdelta];\n  ybox = [ymin - scale * ydelta; ymax + scale * ydelta;\n          ymax + scale * ydelta; ymin - scale * ydelta];\n\n  [p, c, infi] = __voronoi__ (\"voronoi\", [[x; xbox], [y; ybox]], opts{:});\n\n  ## Build list of edges from points in facet.\n  c = c(! infi).';\n  edges = zeros (2, 0);\n  for i = 1:numel (c)\n    facet = c{i};\n    if (isempty (facet))\n      continue;\n    endif\n    edges = [edges, [facet; [facet(end), facet(1:end-1)]]];\n  endfor\n\n  ## Keep only the unique edges of the Voronoi diagram\n  edges = sortrows (sort (edges).').';\n  edges = edges(:, [any(diff(edges, 1, 2)), true]);\n\n  if (numel (x) > 2)\n    ## Eliminate the edges of the diagram representing the box.\n    ## Exclude points outside a certain radius from the center of distribution.\n    ## FIXME: Factor should be at least 1.0.  Octave uses 1.1 for margin.\n    ## There is no theoretical justification for this choice.\n    ctr = [(xmax + xmin)/2 , (ymax + ymin)/2];\n    radius = 1.1 * sumsq ([xmin, ymin] - ctr);\n    dist = sumsq (p - ctr, 2);\n\n    p_inside = (1:rows (p))(dist < radius);\n    edge_inside = any (ismember (edges, p_inside));\n    edges = edges(:, edge_inside);\n  else\n    ## look for the edge between the two given points\n    for edge = edges\n      if (det ([[[1;1],p(edge,1:2)];1,x(1),y(1)])\n          * det ([[[1;1],p(edge,1:2)];1,x(2),y(2)]) < 0)\n        edges = edge;\n        break;\n      endif\n    endfor\n    ## Use larger plot limits to make it more likely single bisector is shown.\n    xdelta = ydelta = max (xdelta, ydelta);\n  endif\n\n  ## Get points of the diagram\n  Vvx = reshape (p(edges, 1), size (edges));\n  Vvy = reshape (p(edges, 2), size (edges));\n\n  if (nargout < 2)\n    if (isnan (hax))\n      hax = gca ();\n    endif\n    h = plot (hax, Vvx, Vvy, linespec{:}, x, y, '+');\n    lim = [xmin, xmax, ymin, ymax];\n    axis (lim + 0.1 * [[-1, 1] * xdelta, [-1, 1] * ydelta]);\n    if (nargout == 1)\n      vx = h;\n    endif\n  else\n    vx = Vvx;\n    vy = Vvy;\n  endif\n\nendfunction\n\n\n%!demo\n%! voronoi (rand (10,1), rand (10,1));\n\n%!testif HAVE_QHULL\n%! phi = linspace (-pi, 3/4*pi, 8);\n%! [x,y] = pol2cart (phi, 1);\n%! [vx,vy] = voronoi (x,y);\n%! assert (vx(2,:), zeros (1, columns (vx)), eps);\n%! assert (vy(2,:), zeros (1, columns (vy)), eps);\n\n%!testif HAVE_QHULL <*40996>\n%! ## Special case of just 2 points\n%! x = [0 1];  y = [1 0];\n%! [vx, vy] = voronoi (x,y);\n%! assert (vx, [-0.7; 1.7], eps);\n%! assert (vy, [-0.7; 1.7], eps);\n\n%!testif HAVE_QHULL <*38295>\n%! x = [1,2,3];  y = [2,3,1];\n%! [vx, vy] = voronoi (x,y);\n%! assert (columns (vx), 3);\n\n%!testif HAVE_QHULL <*37270>\n%! ## Duplicate points can cause an internal error\n%! x = [1,2,3, 3];  y = [2,3,1, 1];\n%! [vx, vy] = voronoi (x,y);\n\n\n## Input validation tests\n%!error <Invalid call> voronoi ()\n%!error voronoi (ones (3,1))\n%!error voronoi (ones (3,1), ones (3,1), \"invalid1\", \"invalid2\", \"invalid3\")\n%!error <HAX argument must be an axes object> voronoi (0, ones (3,1), ones (3,1))\n%!error <X and Y must be vectors of the same length> voronoi (ones (3,1), ones (4,1))\n%!error <minimum of 2 points required> voronoi (2.5, 3.5)\n"
  },
  {
    "path": "scripts/geometry/voronoin.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{C}, @var{F}] =} voronoin (@var{pts})\n## @deftypefnx {} {[@var{C}, @var{F}] =} voronoin (@var{pts}, @var{options})\n## Compute N-dimensional Voronoi facets.\n##\n## The input matrix @var{pts} of size [n, dim] contains n points in a space of\n## dimension dim.\n##\n## @var{C} contains the points of the Voronoi facets.  The list @var{F}\n## contains, for each facet, the indices of the Voronoi points.\n##\n## An optional second argument, which must be a string or cell array of\n## strings, contains options passed to the underlying qhull command.  See the\n## documentation for the Qhull library for details\n## @url{http://www.qhull.org/html/qh-quick.htm#options}.\n##\n## The default options depend on the dimension of the input:\n##\n## @itemize\n## @item 2-D and 3-D: @var{options} = @code{@{\"Qbb\"@}}\n##\n## @item 4-D and higher: @var{options} = @code{@{\"Qbb\", \"Qx\"@}}\n## @end itemize\n##\n## If @var{options} is not present or @code{[]} then the default arguments are\n## used.  Otherwise, @var{options} replaces the default argument list.\n## To append user options to the defaults it is necessary to repeat the\n## default arguments in @var{options}.  Use a null string to pass no arguments.\n##\n## @seealso{voronoi, convhulln, delaunayn}\n## @end deftypefn\n\nfunction [C, F] = voronoin (pts, options)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  [np, dim] = size (pts);\n\n  if (np <= dim)\n    error (\"voronoin: number of points must be greater than their dimension\");\n  endif\n\n  caller = \"voronoin\";\n\n  if (nargin == 1)\n    [C, F] = __voronoi__ (caller, pts);\n  else\n    [C, F] = __voronoi__ (caller, pts, options);\n  endif\n\nendfunction\n\n\n## FIXME: Need functional tests\n\n%!error <Invalid call> voronoin ()\n%!error <number of points must be greater than their dimension> voronoin ([1 2])\n"
  },
  {
    "path": "scripts/gui/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/gui/dialog.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} dialog ()\n## @deftypefnx {} {@var{h} =} dialog (\"@var{property}\", @var{value}, @dots{})\n##\n## Create an empty modal dialog window to which other uicontrols can be added.\n##\n## The dialog box is a figure object with properties as recommended for a\n## dialog box.\n##\n## The default properties differing from a figure are:\n##\n## @table @asis\n## @item buttondownfcn\n## @code{if isempty (allchild(gcbf)), close (gcbf), endif}\n##\n## @item colormap\n## []\n##\n## @item color\n## defaultuicontrolbackgroundcolor\n##\n## @item dockcontrols\n## off\n##\n## @item handlevisibility\n## callback\n##\n## @item integerhandle\n## off\n##\n## @item inverthardcopy\n## off\n##\n## @item menubar\n## none\n##\n## @item numbertitle\n## off\n##\n## @item paperpositionmode\n## auto\n##\n## @item resize\n## off\n##\n## @item windowstyle\n## modal\n##\n## @end table\n##\n##\n## Multiple property-value pairs may be specified for the dialog object, but\n## they must appear in pairs.  The full list of properties is documented at\n## @ref{Figure Properties}.\n##\n## The return value @var{h} is a graphics handle to the created figure.\n##\n## Example:\n##\n## @example\n## @group\n## ## create an empty dialog window titled \"Dialog Example\"\n## h = dialog (\"name\", \"Dialog Example\");\n##\n## ## create a button (default style)\n## b = uicontrol (h, \"string\", \"OK\",\n##                   \"position\", [10 10 150 40],\n##                   \"callback\", \"delete (gcf)\");\n##\n## ## wait for dialog to resume or close\n## uiwait (h);\n## @end group\n## @end example\n##\n## @seealso{errordlg, msgbox, questdlg, warndlg, figure, uiwait}\n## @end deftypefn\n\nfunction h = dialog (varargin)\n\n  h = figure ( ...\n    \"buttondownfcn\", \"if isempty (allchild (gcbf)), close (gcbf), endif\",\n    \"color\", get (0,\"defaultuicontrolbackgroundcolor\"),\n    \"colormap\", [],\n    \"dockcontrols\", \"off\",\n    \"handlevisibility\", \"callback\",\n    \"integerhandle\", \"off\",\n    \"inverthardcopy\", \"off\",\n    \"menubar\", \"none\",\n    \"numbertitle\", \"off\",\n    \"paperpositionmode\", \"auto\",\n    \"resize\", \"off\",\n    \"toolbar\", \"none\",\n    \"windowstyle\", \"modal\",\n    varargin{:});\n\nendfunction\n\n## No BIST tests.  This function just dispatches to figure().\n%!assert (1)\n"
  },
  {
    "path": "scripts/gui/errordlg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} errordlg ()\n## @deftypefnx {} {} errordlg (@var{msg})\n## @deftypefnx {} {} errordlg (@var{msg}, @var{title})\n## @deftypefnx {} {} errordlg (@var{msg}, @var{title}, @var{opt})\n## @deftypefnx {} {@var{h} =} errordlg (@dots{})\n## Display an error dialog box with error message @var{msg} and caption\n## @var{title}.\n##\n## The default error message is @qcode{\"This is the default error string.@:\"}\n## and the default caption is @qcode{\"Error Dialog\"}.\n##\n## The error message may have multiple lines separated by newline characters\n## (\"\\n\"), or it may be a cellstr array with one element for each line.\n##\n## The third optional argument @var{opt} controls the behavior of the dialog.\n## For details, @pxref{XREFmsgbox,,@code{msgbox}}.\n##\n## The return value @var{h} is a handle to the figure object used for\n## building the dialog.\n##\n## Examples:\n##\n## @example\n## @group\n## errordlg (\"Some fancy error occurred.\");\n## errordlg (\"Some fancy error\\nwith two lines.\");\n## errordlg (@{\"Some fancy error\", \"with two lines.\"@});\n## errordlg (\"Some fancy error occurred.\", \"Fancy caption\");\n## @end group\n## @end example\n##\n## @seealso{helpdlg, warndlg, msgbox, inputdlg, listdlg, questdlg}\n## @end deftypefn\n\nfunction h = errordlg (varargin)\n\n  msg = \"This is the default error.\";\n  tit = \"Error Dialog\";\n  opt = \"non-modal\";\n\n  nargs = numel (varargin);\n\n  if (nargs > 3)\n    print_usage ();\n  elseif (nargs == 1)\n    msg = varargin{1};\n  elseif (nargs == 2)\n    msg = varargin{1};\n    tit = varargin{2};\n  elseif (nargs == 3)\n    msg = varargin{1};\n    tit = varargin{2};\n    opt = varargin{3};\n  endif\n\n  htmp = msgbox (msg, tit, \"error\", opt);\n\n  if (nargout)\n    h = htmp;\n  endif\n\nendfunction\n\n## No BIST tests.  This function just dispatches to msgbox().\n%!assert (1)\n"
  },
  {
    "path": "scripts/gui/getappdata.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{value} =} getappdata (@var{h}, @var{name})\n## @deftypefnx {} {@var{appdata} =} getappdata (@var{h})\n## Return the @var{value} of the application data @var{name} for the graphics\n## object with handle @var{h}.\n##\n## @var{h} may also be a vector of graphics handles.  If no second argument\n## @var{name} is given then @code{getappdata} returns a structure,\n## @var{appdata}, whose fields correspond to the appdata properties.\n##\n## @seealso{setappdata, isappdata, rmappdata, guidata, get, set, getpref,\n## setpref}\n## @end deftypefn\n\nfunction value = getappdata (h, name)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! all (ishghandle (h(:))))\n    error (\"getappdata: H must be a scalar or vector of graphic handles\");\n  endif\n\n  if (nargin == 2)\n    if (! ischar (name))\n      error (\"getappdata: NAME must be a string\");\n    endif\n\n    value = cell (numel (h), 1);\n    for i = 1:numel (h)\n      try\n        value{i} = (get (h(i), \"__appdata__\")).(name);\n      end_try_catch\n    endfor\n\n    if (i == 1)\n      value = value{1};\n    endif\n\n  else  # nargin == 1\n    if (numel (h) != 1)\n      error (\"getappdata: Only one handle H may be used when fetching appdata\");\n    endif\n\n    value = get (h, \"__appdata__\");\n    if (isempty (value))\n      value = struct ();\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! unwind_protect\n%!   setappdata (0, \"%data1%\", ones (3), \"%data2%\", \"hello world\");\n%!   assert (getappdata (0, \"%data1%\"), ones (3));\n%!   assert (getappdata (0, \"%data2%\"), \"hello world\");\n%!   appdata = getappdata (0);\n%!   name1 = \"%data1%\";  name2 = \"%data2%\";\n%!   assert (appdata.(name1), ones (3));\n%!   assert (appdata.(name2), \"hello world\");\n%! unwind_protect_cleanup\n%!   rmappdata (0, \"%data1%\", \"%data2%\");\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> getappdata ()\n%!error <H must be a scalar .* graphic handle> getappdata (-1, \"hello\")\n%!error <NAME must be a string> getappdata (0, 1)\n%!error <Only one handle H may be used when fetching appdata> getappdata ([0 0])\n"
  },
  {
    "path": "scripts/gui/getpixelposition.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{pos} =} getpixelposition (@var{h})\n## @deftypefnx {} {@var{pos} =} getpixelposition (@var{h}, @var{rel_to_fig})\n## Return the position of a user interface component in pixel units.\n##\n## The first argument @var{h} must be a handle to a valid graphics object of\n## type uibuttongroup, uicontrol, uipanel, uitable, axes, or figure.  For other\n## object types, the function returns zeros.\n##\n## By default, the position is returned relative to the object's parent.\n## If the second argument @var{rel_to_fig} is logically true, the position\n## is computed relative to the enclosing figure object.\n##\n## The return value @var{pos} is a 4-element vector with values\n## @code{[lower_left_X, lower_left_Y, width, height]}.\n##\n## @seealso{get}\n## @end deftypefn\n\nfunction pos = getpixelposition (h, rel_to_fig = false)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (h) && ishghandle (h)))\n    error (\"getpixelposition: H must be a scalar graphics handle\");\n  endif\n\n  if (! any (strcmp (get (h, \"type\"),\n                     {\"uibuttongroup\", \"uicontrol\", \"uitable\", \"uipanel\", ...\n                      \"axes\", \"figure\"})))\n    pos = zeros (1, 4);\n    return;\n  endif\n\n  pos = __get_position__ (h, \"pixels\");\n\n  if (rel_to_fig && ! isfigure (h))\n    hpar = get (h, \"parent\");\n    while (! isfigure (hpar))\n      pos(1:2) += __get_position__ (hpar, \"pixels\")(1:2);\n      hpar = get (hpar, \"parent\");\n    endwhile\n  endif\n\nendfunction\n\n\n%!demo\n%! clf ();\n%! hax = axes (\"position\", [0.25 0.25 0.5 0.5]);\n%! pos = getpixelposition (hax);\n%! han = annotation (\"rectangle\");\n%! set (han, \"units\", \"pixels\", \"position\", pos, \"color\", \"r\");\n\n%!demo\n%! hf = clf ();\n%! hbg = uibuttongroup (hf, \"position\", [0.2 0.7 0.2 0.2]);\n%! hb1 = uicontrol (hbg, \"style\", \"radiobutton\", ...\n%!                       \"string\", \"Choice 1\", ...\n%!                       \"units\", \"normalized\", ...\n%!                       \"position\", [0.01 0.5 0.98 0.5]);\n%! hb2 = uicontrol (hbg, \"style\", \"radiobutton\", ...\n%!                       \"string\", \"Choice 2\", ...\n%!                       \"units\", \"normalized\", ...\n%!                       \"position\", [0.01 0 0.98 0.5]);\n%! pos = getpixelposition (hbg);\n%! han = annotation (\"rectangle\");\n%! set (han, \"units\", \"pixels\", \"position\", pos, \"color\", \"r\");\n\n\n%!test\n%! pos = [0 0 400 400];\n%! hf = figure (\"visible\", \"off\", \"menubar\", \"none\", \"position\", pos);\n%! unwind_protect\n%!   hp = uipanel (hf, \"position\", [0.5 0.5 0.5 0.5]);\n%!   hax = axes (hp, \"position\", [0.5 0.5 0.5 0.5]);\n%!   assert (getpixelposition (hax), [100 100 100 100], 2);\n%!   assert (getpixelposition (hax, true), [300 300 100 100], 2);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Compatibility: return zeros for root figure\n%! assert (getpixelposition (groot), zeros (1, 4));\n\n%!test\n%! ## Compatibility: return the same for figures regardless of rel_to_fig\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   assert (getpixelposition (hf), getpixelposition (hf, true));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> getpixelposition ()\n%!error <H must be a scalar> getpixelposition ([1, 2])\n%!error <H must be a .* graphics handle> getpixelposition (-1)\n"
  },
  {
    "path": "scripts/gui/guidata.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{data} =} guidata (@var{h})\n## @deftypefnx {} {} guidata (@var{h}, @var{data})\n## Query or set user-custom GUI data.\n##\n## The GUI data is stored in the figure handle @var{h}.  If @var{h} is not a\n## figure handle then it's parent figure will be used for storage.\n##\n## @var{data} must be a single object which means it is usually preferable\n## for it to be a data container such as a cell array or struct so that\n## additional data items can be added easily.\n##\n## @seealso{getappdata, setappdata, get, set, getpref, setpref}\n## @end deftypefn\n\nfunction dataout = guidata (h, data)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ishghandle (h))\n    error (\"guidata: H must be a valid object handle\");\n  endif\n  h = ancestor (h, \"figure\");\n  if (isempty (h))\n    error (\"guidata: no ancestor figure of H found\");\n  endif\n\n  if (nargin == 1)\n    dataout = get (h, \"__guidata__\");\n  else\n    set (h, \"__guidata__\", data);\n    if (nargout == 1)\n      dataout = data;\n    endif\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> guidata ()\n%!error <H must be a valid object handle> guidata ({1})\n%!error <no ancestor figure of H found> guidata (0)\n"
  },
  {
    "path": "scripts/gui/guihandles.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hdata} =} guihandles (@var{h})\n## @deftypefnx {} {@var{hdata} =} guihandles\n## Return a structure of object handles for the figure associated with\n## handle @var{h}.\n##\n## If no handle is specified the current figure returned by @code{gcf} is used.\n##\n## The fieldname for each entry of @var{hdata} is taken from the @qcode{\"tag\"}\n## property of the graphic object.  If the tag is empty then the handle is not\n## returned.  If there are multiple graphic objects with the same tag then\n## the entry in @var{hdata} will be a vector of handles.  @code{guihandles}\n## includes all possible handles, including those for\n## which @qcode{\"HandleVisibility\"} is @qcode{\"off\"}.\n## @seealso{guidata, findobj, findall, allchild}\n## @end deftypefn\n\nfunction hdata = guihandles (h)\n\n  if (nargin == 1)\n    if (! ishghandle (h))\n      error (\"guidata: H must be a valid object handle\");\n    endif\n    h = ancestor (h, \"figure\");\n    if (isempty (h))\n      error (\"guidata: no ancestor figure of H found\");\n    endif\n  else\n    h = gcf ();\n  endif\n\n  hdata = __make_guihandles_struct__ (h, []);\n\nendfunction\n\nfunction hdata = __make_guihandles_struct__ (h, hdata)\n\n  tag = get (h, \"tag\");\n  if (! isempty (tag))\n    if (isfield (hdata, tag))\n      hdata.(tag) = [hdata.(tag), h];\n    else\n      try\n        hdata.(tag) = h;\n      catch\n      end_try_catch\n    endif\n  endif\n\n  kids = allchild (h);\n  for hkid = kids'\n    hdata = __make_guihandles_struct__ (hkid, hdata);\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/helpdlg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} helpdlg ()\n## @deftypefnx {} {} helpdlg (@var{msg})\n## @deftypefnx {} {} helpdlg (@var{msg}, @var{title})\n## @deftypefnx {} {@var{h} =} helpdlg (@dots{})\n## Display a help dialog box with help message @var{msg} and caption\n## @var{title}.\n##\n## The default help message is @qcode{\"This is the default help string.@:\"}\n## and the default caption is @qcode{\"Help Dialog\"}.\n##\n## The help message may have multiple lines separated by newline characters\n## (\"\\n\"), or it may be a cellstr array with one element for each line.\n##\n## The return value @var{h} is a handle to the figure object used for\n## building the dialog.\n##\n## Examples:\n##\n## @example\n## @group\n## helpdlg (\"Some helpful text for the user.\");\n## helpdlg (\"Some helpful text\\nwith two lines.\");\n## helpdlg (@{\"Some helpful text\", \"with two lines.\"@});\n## helpdlg (\"Some helpful text for the user.\", \"Fancy caption\");\n## @end group\n## @end example\n##\n## @seealso{errordlg, warndlg, msgbox, inputdlg, listdlg, questdlg}\n## @end deftypefn\n\nfunction h = helpdlg (varargin)\n\n  msg = \"This is the default help.\";\n  tit = \"Help Dialog\";\n  opt = \"non-modal\";\n\n  nargs = numel (varargin);\n\n  if (nargs > 2)\n    print_usage ();\n  elseif (nargs == 1)\n    msg = varargin{1};\n  elseif (nargs == 2)\n    msg = varargin{1};\n    tit = varargin{2};\n  endif\n\n  htmp = msgbox (msg, tit, \"help\", opt);\n\n  if (nargout)\n    h = htmp;\n  endif\n\nendfunction\n\n## No BIST tests.  This function just dispatches to msgbox().\n%!assert (1)\n"
  },
  {
    "path": "scripts/gui/inputdlg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{cstr} =} inputdlg (@var{prompt})\n## @deftypefnx {} {@var{cstr} =} inputdlg (@var{prompt}, @var{title})\n## @deftypefnx {} {@var{cstr} =} inputdlg (@var{prompt}, @var{title}, @var{rowscols})\n## @deftypefnx {} {@var{cstr} =} inputdlg (@var{prompt}, @var{title}, @var{rowscols}, @var{defaults})\n## @deftypefnx {} {@var{cstr} =} inputdlg (@var{prompt}, @var{title}, @var{rowscols}, @var{defaults}, @var{options})\n## Return user input from a multi-textfield dialog box.\n##\n## Inputs:\n##\n## @table @var\n## @item prompt\n## A cell array with strings labeling each text field.  This input is required.\n##\n## @item title\n## String to use for the caption of the dialog.  The default is\n## @qcode{\"Input Dialog\"}.\n##\n## @item rowscols\n## Specifies the size of the text fields and can take four forms:\n##\n## @enumerate\n## @item a scalar value which defines the number of rows used for each text\n## field.\n##\n## @item a row or column vector with the number of elements matching the number\n## of prompts.  Each element defines the number of rows used for the\n## corresponding text field.\n##\n## @item a 1x2 row vector which defines the number of rows and the number of\n## columns used for all text fields.\n##\n## @item an Mx2 matrix which defines the individual number of rows and columns\n## used for each text field.  In the matrix, each row describes a single text\n## field.  The first column specifies the number of input rows to use and the\n## second column specifies the text field width.\n## @end enumerate\n##\n## @item defaults\n## A list of default values to place in each text field.  It must be a cell\n## array of strings with the same size as @var{prompt}.\n##\n## @item options\n## Not supported, only for @sc{matlab} compatibility.\n## @end table\n##\n## Output:\n## The output is a cell array of strings with each element being the text that\n## was entered by the user.  An empty cell array is returned if the dialog was\n## closed by the Cancel button.\n##\n## Example:\n##\n## @example\n## @group\n## prompt = @{\"Width\", \"Height\", \"Depth\"@};\n## defaults = @{\"1.10\", \"2.20\", \"3.30\"@};\n## rowscols = [1,10; 2,20; 3,30];\n## dims = inputdlg (prompt, \"Enter Box Dimensions\", ...\n##                  rowscols, defaults);\n## @end group\n## @end example\n##\n## @seealso{errordlg, helpdlg, listdlg, msgbox, questdlg, warndlg}\n## @end deftypefn\n\nfunction cstr = inputdlg (prompt, varargin)\n\n  if (nargin < 1 || nargin > 5)\n    print_usage ();\n  endif\n\n  if (iscell (prompt))\n    ## Silently extract only char elements\n    prompt = prompt(cellfun (\"isclass\", prompt, \"char\"));\n  elseif (ischar (prompt))\n    prompt = {prompt};\n  else\n    error (\"inputdlg: PROMPT must be a character string or cellstr array\");\n  endif\n\n  title = \"Input Dialog\";\n  if (nargin > 1)\n    if (! ischar (varargin{1}))\n      error (\"inputdlg: TITLE must be a character string\");\n    endif\n    title = varargin{1};\n  endif\n\n  linespec = 1;\n  if (nargin > 2)\n    linespec = varargin{2};\n    if (! isnumeric (linespec))\n      error (\"inputdlg: ROWSCOLS must be numeric\");\n    endif\n  endif\n\n  defaults = cellstr (cell (size (prompt)));\n  if (nargin > 3)\n    if (numel (varargin{3}) != numel (prompt))\n      error (\"inputdlg: number of DEFAULT items must match number of PROMPT items\");\n    endif\n    defaults = varargin{3};\n  endif\n\n  if (nargin > 4)\n    warning (\"inputdlg: 5th 'options' argument ignored\");\n  endif\n\n  ## specification of text field sizes as in Matlab\n  ## Matlab requires a matrix for linespec, not a cell array...\n  ## rc = [1,10; 2,20; 3,30];\n  ##     c1  c2\n  ## r1  1   10   first  text field is 1x10\n  ## r2  2   20   second text field is 2x20\n  ## r3  3   30   third  text field is 3x30\n\n  if (isscalar (linespec))\n    ## only scalar value setting Height for all prompts\n    rowscols = zeros (numel (prompt), 2);\n    rowscols(:,1) = linespec;\n    rowscols(:,2) = 25;\n  elseif (isrow (linespec) && columns (linespec) == 2)\n    ## One HxW specification for all prompts\n    rowscols = repmat (linespec, numel (prompt), 1);\n  elseif (ismatrix (linespec))\n    if (rows (linespec) == columns (prompt) && columns (linespec) == 2)\n      ## (rows x columns) match, copy array linespec\n      rowscols = linespec;\n    elseif (isvector (linespec))\n      if (numel (linespec) != numel (prompt))\n        error (\"inputdlg: ROWSCOLS vector does not match size of PROMPT\");\n      endif\n      ## rows from column vector linespec, columns are set to default\n      rowscols = zeros (numel (prompt), 2);\n      rowscols(:,1) = linespec(:);\n      rowscols(:,2) = 25;\n    else\n      error (\"inputdlg: ROWSCOLS matrix does not match size of PROMPT\");\n    endif\n  else\n    error (\"inputdlg: invalid form of ROWSCOLS argument\");\n  endif\n  rowscols = ceil (rowscols);\n\n  ## convert numeric values in defaults cell array to strings\n  defs = cellfun ('num2str', defaults, \"UniformOutput\", false);\n\n  if (! __event_manager_have_dialogs__ ())\n    error (\"inputdlg is not available in this version of Octave\");\n  endif\n\n  cstr = __event_manager_input_dialog__ (prompt, title, rowscols, defs);\n\nendfunction\n\n\n%!demo\n%! disp ('- test inputdlg with prompt and caption only.');\n%! prompt = {'Width', 'Height', 'Depth'};\n%! dims = inputdlg (prompt, 'Enter Box Dimensions');\n%! if (isempty (dims))\n%!   helpdlg ('Canceled by user', 'Information');\n%! else\n%!   volume  = str2num (dims{1}) * str2num (dims{2}) * str2num (dims{3});\n%!   surface = 2 * (str2num (dims{1}) * str2num (dims{2}) + ...\n%!                  str2num (dims{2}) * str2num (dims{3}) + ...\n%!                  str2num (dims{1}) * str2num (dims{3}));\n%!   helpdlg (sprintf ('Results:\\nVolume = %.3f\\nSurface = %.3f', ...\n%!                     volume, surface), 'Box Dimensions');\n%! endif\n\n%!demo\n%! disp ('- test inputdlg with prescribed scalar (2 lines per text field) and defaults.');\n%! prompt = {'Width', 'Height', 'Depth'};\n%! default = {'1.1', '2.2', '3.3'};\n%! rc = 2;\n%! dims = inputdlg (prompt, 'Enter Box Dimensions', rc, default);\n%! if (isempty (dims))\n%!   helpdlg ('Canceled by user', 'Information');\n%! else\n%!   volume  = str2num (dims{1}) * str2num (dims{2}) * str2num (dims{3});\n%!   surface = 2 * (str2num (dims{1}) * str2num (dims{2}) + ...\n%!                  str2num (dims{2}) * str2num (dims{3}) + ...\n%!                  str2num (dims{1}) * str2num (dims{3}));\n%!    helpdlg (sprintf ('Results:\\nVolume = %.3f\\nSurface = %.3f', ...\n%!                      volume, surface), 'Box Dimensions');\n%! endif\n\n%!demo\n%! disp ('- test inputdlg with prescribed vector [1,2,3] for # of lines per text field and defaults.');\n%! prompt = {'Width', 'Height', 'Depth'};\n%! default = {'1.10', '2.10', '3.10'};\n%! rc = [1,2,3];  # NOTE: must be an array\n%! dims = inputdlg (prompt, 'Enter Box Dimensions', rc, default);\n%! if (isempty (dims))\n%!   helpdlg ('Canceled by user', 'Information');\n%! else\n%!   volume  = str2num (dims{1}) * str2num (dims{2}) * str2num (dims{3});\n%!   surface = 2 * (str2num (dims{1}) * str2num (dims{2}) + ...\n%!                  str2num (dims{2}) * str2num (dims{3}) + ...\n%!                  str2num (dims{1}) * str2num (dims{3}));\n%!   helpdlg (sprintf ('Results:\\nVolume = %.3f\\nSurface = %.3f', ...\n%!                     volume, surface), 'Box Dimensions');\n%! endif\n\n%!demo\n%! disp ('- test inputdlg with prescribed row by column sizes and defaults.');\n%! prompt = {'Width', 'Height', 'Depth'};\n%! default = {'1.10', '2.20', '3.30'};\n%! rc = [1,10; 2,20; 3,30];  # NOTE: must be an array\n%! dims = inputdlg (prompt, 'Enter Box Dimensions', rc, default);\n%! if (isempty (dims))\n%!   helpdlg ('Canceled by user', 'Information');\n%! else\n%!   volume  = str2num (dims{1}) * str2num (dims{2}) * str2num (dims{3});\n%!   surface = 2 * (str2num (dims{1}) * str2num (dims{2}) + ...\n%!                  str2num (dims{2}) * str2num (dims{3}) + ...\n%!                  str2num (dims{1}) * str2num (dims{3}));\n%!   helpdlg (sprintf ('Results:\\nVolume = %.3f\\nSurface = %.3f', ...\n%!                     volume, surface), 'Box Dimensions');\n%! endif\n\n%!demo\n%! disp ('- test inputdlg with vector for a single item.');\n%! prompt = {'enter x value'};\n%! default = {1};\n%! answer = inputdlg (prompt, 'Enter value', [1 10], default);\n%! if (isempty (answer))\n%!   helpdlg ('Canceled by user', 'Information');\n%! else\n%!   helpdlg (sprintf ('answer = %d', str2num (answer{1})), 'answer');\n%! endif\n\n%!error <Invalid call> inputdlg ()\n%!error <Invalid call> inputdlg (1, 2, 3, 4, 5, 6)\n%!error <PROMPT must be a character string> inputdlg (1)\n%!error <TITLE must be a character string> inputdlg (\"msg\", 1)\n%!error <ROWSCOLS must be numeric> inputdlg (\"msg\", \"title\", \"1\")\n%!error <number of DEFAULT items must match number of PROMPT items>\n%!  inputdlg (\"prompt\", \"title\", 1, {'1', '2'})\n%!error <ROWSCOLS vector does not match size of PROMPT>\n%! inputdlg ({\"a1\", \"a2\"}, \"title\", [1, 2, 3]);\n%!error <ROWSCOLS matrix does not match size of PROMPT>\n%! inputdlg ({\"a1\", \"a2\"}, \"title\", [1, 2, 3; 4, 5, 6]);\n%!error <invalid form of ROWSCOLS argument>\n%! inputdlg ({\"a1\", \"a2\"}, \"title\", ones (2,2,2));\n"
  },
  {
    "path": "scripts/gui/isappdata.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{valid} =} isappdata (@var{h}, @var{name})\n## Return true if the named application data, @var{name}, exists for the\n## graphics object with handle @var{h}.\n##\n## @var{h} may also be a vector of graphics handles.\n## @seealso{getappdata, setappdata, rmappdata, guidata, get, set, getpref,\n## setpref}\n## @end deftypefn\n\nfunction valid = isappdata (h, name)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! all (ishghandle (h(:))))\n    error (\"isappdata: H must be a scalar or vector of graphic handles\");\n  elseif (! ischar (name))\n    error (\"isappdata: NAME must be a string\");\n  endif\n\n  valid = false (size (h));\n  for i = 1:numel (h)\n    appdata = get (h(i), \"__appdata__\");\n    if (isfield (appdata, name))\n      valid(i) = true;\n    endif\n  endfor\n\nendfunction\n\n\n%!test\n%! unwind_protect\n%!   setappdata (0, \"%hello%\", \"world\");\n%!   assert (isappdata (0, \"%hello%\"), true);\n%!   assert (isappdata ([0 0], \"%hello%\"), [true, true]);\n%!   assert (isappdata (0, \"%foobar%\"), false);\n%! unwind_protect_cleanup\n%!   rmappdata (0, \"%hello%\");\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> isappdata ()\n%!error <H must be a scalar .* graphic handle> isappdata (-1, \"hello\")\n%!error <NAME must be a string> isappdata (0, 1)\n"
  },
  {
    "path": "scripts/gui/listdlg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{sel}, @var{ok}] =} listdlg (@var{key}, @var{value}, @dots{})\n## Return user inputs from a list dialog box in a vector of selection indices\n## (@var{sel}) and a flag indicating how the user closed the dialog box\n## (@var{ok}).\n##\n## The indices in @var{sel} are 1-based.\n##\n## The value of @var{ok} is 1 if the user closed the box with the OK button,\n## otherwise it is 0 and @var{sel} is empty.\n##\n## Input arguments are specified in form of @var{key}, @var{value} pairs.\n## The @qcode{\"ListString\"} argument pair @strong{must} be specified.\n##\n## Valid @var{key} and @var{value} pairs are:\n##\n## @table @asis\n## @item @qcode{\"ListString\"}\n## a cell array of strings specifying the items to list in the dialog.\n##\n## @item @qcode{\"SelectionMode\"}\n## can be either @qcode{\"Single\"} (only one item may be selected at a time) or\n## @qcode{\"Multiple\"} (default).\n##\n## @item @qcode{\"ListSize\"}\n## a two-element vector @code{[@var{width}, @var{height}]} specifying the size\n## of the list field in pixels.  The default is [160, 300].\n##\n## @item @qcode{\"InitialValue\"}\n## a vector containing 1-based indices of elements which will be pre-selected\n## when the list dialog is first displayed.\n## The default is 1 (first item).\n##\n## @item @qcode{\"Name\"}\n## a string to be used as the dialog caption.  Default is \"\".\n##\n## @item @qcode{\"PromptString\"}\n## a cell array of strings to be displayed above the list of items.\n## Default is @{@}.\n##\n## @item @qcode{\"OKString\"}\n## a string used to label the OK button.  Default is @qcode{\"OK\"}.\n##\n## @item @qcode{\"CancelString\"}\n## a string used to label the Cancel button.  Default is @qcode{\"Cancel\"}.\n## @end table\n##\n## Example:\n##\n## @example\n## @group\n## my_options = @{\"An item\", \"another\", \"yet another\"@};\n## [sel, ok] = listdlg (\"ListString\", my_options,\n##                      \"SelectionMode\", \"Multiple\");\n## if (ok == 1)\n##   disp (\"You selected:\");\n##   for i = 1:numel (sel)\n##     disp (sprintf (\"\\t%s\", my_options@{sel(i)@}));\n##   endfor\n## else\n##   disp (\"You cancelled.\");\n## endif\n## @end group\n## @end example\n##\n## @seealso{menu, errordlg, helpdlg, inputdlg, msgbox, questdlg, warndlg}\n## @end deftypefn\n\nfunction [sel, ok] = listdlg (varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (mod (nargin, 2) != 0)\n    error (\"listdlg: KEY/VALUE inputs must occur in pairs\");\n  endif\n\n  listcell = {\"\"};\n  selmode = \"multiple\";\n  listsize = [160, 300];\n  initialvalue = 1;\n  name = \"\";\n  prompt = {};\n  okstring = \"OK\";\n  cancelstring = \"Cancel\";\n\n  ## handle key, value pairs\n  for i = 1:2:nargin-1\n    if (strcmpi (varargin{i}, \"ListString\"))\n      listcell = varargin{i+1};\n    elseif (strcmpi (varargin{i}, \"SelectionMode\"))\n      selmode = lower (varargin{i+1});\n    elseif (strcmpi (varargin{i}, \"ListSize\"))\n      listsize = varargin{i+1};\n    elseif (strcmpi (varargin{i}, \"InitialValue\"))\n      initialvalue = varargin{i+1};\n    elseif (strcmpi (varargin{i}, \"Name\"))\n      name = varargin{i+1};\n    elseif (strcmpi (varargin{i}, \"PromptString\"))\n      prompt = varargin{i+1};\n    elseif (strcmpi (varargin{i}, \"OKString\"))\n      okstring = varargin{i+1};\n    elseif (strcmpi (varargin{i}, \"CancelString\"))\n      cancelstring = varargin{i+1};\n    else\n      error (\"listdlg: invalid KEY <%s>\", varargin{i});\n    endif\n  endfor\n\n  if (isempty (listcell))\n    error ('listdlg: \"ListString\" property must not be empty');\n  endif\n\n  ## make sure listcell strings are a cell array\n  if (! iscell (listcell))\n    listcell = {listcell};\n  elseif (iscellstr (listcell{1}))\n    listcell = listcell{1};\n  endif\n\n  ## make sure prompt strings are a cell array\n  if (! iscell (prompt))\n    prompt = {prompt};\n  endif\n\n  ## validate selection mode\n  if (! strcmp (selmode, \"multiple\") && ! strcmp (selmode, \"single\"))\n    error ('listdlg: \"SelectionMode\" must be \"single\" or \"multiple\"');\n  endif\n\n  if (! __event_manager_have_dialogs__ ())\n    error (\"listdlg is not available in this version of Octave\");\n  endif\n\n  [sel, ok] = __event_manager_list_dialog__ (listcell, selmode, listsize,\n                                             initialvalue, name, prompt,\n                                             okstring, cancelstring);\n\nendfunction\n\n\n%!demo\n%! disp ('- test listdlg with \"SelectionMode\"=\"single\".  No caption, no prompt.');\n%! itemlist = {\"An item\", \"another\", \"yet another\"};\n%! s = listdlg (\"ListString\", itemlist, \"SelectionMode\", \"Single\");\n%! imax = numel (s);\n%! for i=1:1:imax\n%!   disp ([\"Selection #\", num2str(i), \": \", itemlist{s(i)}]);\n%! endfor\n\n%!demo\n%! disp ('- test listdlg with \"SelectionMode\"=\"multiple\" and pre-selection.  Has caption and two prompt lines.');\n%! itemlist = {\"An item\", \"another\", \"yet another\"};\n%! s = listdlg (\"ListString\", itemlist, ...\n%!              \"SelectionMode\", \"Multiple\", ...\n%!              \"Name\", \"Selection Dialog\", ...\n%!              \"InitialValue\", [1,2,3],\n%!              \"PromptString\", {\"Select <b>an</b> item...\",\n%!                               \"...or <b>multiple</b> items\"});\n%! imax = numel (s);\n%! for i=1:1:imax\n%!   disp ([\"Selection #\", num2str(i), \": \", itemlist{s(i)}]);\n%! endfor\n\n%!demo\n%! disp (\"- test listdlg with ListSize.\");\n%! itemlist = {\"Neutron\", \"Electron\", \"Quark\", \"Proton\", \"Neutrino\"};\n%! s = listdlg (\"ListString\", itemlist,\n%!              \"Name\", \"Bits and Pieces\",\n%!              \"ListSize\", [200 75]);\n%! imax = numel (s);\n%! for i=1:1:imax\n%!   disp ([\"Selection #\", num2str(i), \": \", itemlist{s(i)}]);\n%! endfor\n\n## Test input validation\n%!error <Invalid call> listdlg ()\n%!error <Invalid call> listdlg (1)\n%!error listdlg (\"SelectionMode\")\n%!error <must occur in pairs> listdlg (\"SelectionMode\", \"multiple\", \"Name\")\n%!error <invalid KEY .FooBar.> listdlg (\"FooBar\", 1)\n%!error <\"ListString\" property must not be empty> listdlg (\"ListString\", {})\n%!error <\"SelectionMode\" must be \"single\" or \"multiple\">\n%! listdlg (\"ListString\", {\"A\"}, \"SelectionMode\", \"foobar\");\n"
  },
  {
    "path": "scripts/gui/listfonts.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {fonts =} listfonts ()\n## @deftypefnx {} {fonts =} listfonts (@var{h})\n## List system fonts.\n##\n## If a handle to a graphics object @var{h} is provided, also include the\n## font from the object's @qcode{\"FontName\"} property in the list.\n##\n## Programming Note: On systems that don't use FontConfig natively (all but\n## Linux), the font cache is built when Octave is installed.  You will need to\n## run @code{system (\"fc-cache -fv\")} manually after installing new fonts.\n##\n## @seealso{uisetfont, text, axes, uicontrol}\n## @end deftypefn\n\nfunction fonts = listfonts (h)\n\n  if (nargin == 1 && (! ishghandle (h) || ! isprop (h, \"fontname\")))\n    error (['listfonts: H must be a handle to a graphics object ', ...\n            'with a \"fontname\" property']);\n  endif\n\n  persistent sysfonts = get_fonts ();\n  fonts = sysfonts;\n\n  if (nargin == 1 && ! isempty (h))\n    font = get (h, \"fontname\");\n    if (! strcmp (font, \"*\"))\n      fonts = unique ([fonts font]);\n    endif\n  endif\n\nendfunction\n\nfunction fonts = get_fonts ()\n\n  fontfiles = __get_system_fonts__ ();\n\n  fonts = unique ({fontfiles.family, \"FreeSans\"});\n\nendfunction\n\n\n## Test input validation\n%!error listfonts (0, 0)\n%!error <H must be a handle to a graphics object with a \"fontname\" property>\n%! s = listfonts (0);\n%!error <H must be a handle to a graphics object>\n%! s = listfonts (struct ());\n"
  },
  {
    "path": "scripts/gui/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__file_filter__.m \\\n  %reldir%/private/__fltk_file_filter__.m \\\n  %reldir%/private/__get_funcname__.m \\\n  %reldir%/private/__is_function__.m \\\n  %reldir%/private/__ok_cancel_dlg__.m \\\n  %reldir%/private/__uigetdir_fltk__.m \\\n  %reldir%/private/__uigetfile_fltk__.m \\\n  %reldir%/private/__uiobject_split_args__.m \\\n  %reldir%/private/__uiputfile_fltk__.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/dialog.m \\\n  %reldir%/errordlg.m \\\n  %reldir%/getappdata.m \\\n  %reldir%/getpixelposition.m \\\n  %reldir%/guidata.m \\\n  %reldir%/guihandles.m \\\n  %reldir%/helpdlg.m \\\n  %reldir%/inputdlg.m \\\n  %reldir%/isappdata.m \\\n  %reldir%/listfonts.m \\\n  %reldir%/listdlg.m \\\n  %reldir%/movegui.m \\\n  %reldir%/msgbox.m \\\n  %reldir%/questdlg.m \\\n  %reldir%/rmappdata.m \\\n  %reldir%/setappdata.m \\\n  %reldir%/uibuttongroup.m \\\n  %reldir%/uicontextmenu.m \\\n  %reldir%/uicontrol.m \\\n  %reldir%/uigetdir.m \\\n  %reldir%/uigetfile.m \\\n  %reldir%/uifigure.m \\\n  %reldir%/uimenu.m \\\n  %reldir%/uipanel.m \\\n  %reldir%/uipushtool.m \\\n  %reldir%/uiputfile.m \\\n  %reldir%/uiresume.m \\\n  %reldir%/uisetfont.m \\\n  %reldir%/uitable.m \\\n  %reldir%/uitoggletool.m \\\n  %reldir%/uitoolbar.m \\\n  %reldir%/uiwait.m \\\n  %reldir%/waitbar.m \\\n  %reldir%/waitforbuttonpress.m \\\n  %reldir%/warndlg.m\n\n%canon_reldir%dir = $(fcnfiledir)/gui\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/gui/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/gui/movegui.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n## your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the filename COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} movegui\n## @deftypefnx {} {} movegui (@var{h})\n## @deftypefnx {} {} movegui (@var{pos})\n## @deftypefnx {} {} movegui (@var{h}, @var{pos})\n## @deftypefnx {} {} movegui (@var{h}, @var{event})\n## @deftypefnx {} {} movegui (@var{h}, @var{event}, @var{pos})\n## Move a figure specified by figure handle @var{h} to a position on the screen\n## defined by @var{pos}.\n##\n## @var{h} is a figure handle, or a handle to a graphics object.  In the latter\n## case, its parent figure will be used.  If unspecified, @var{h} will be\n## set to the handle of the relevant figure if a callback is being executed\n## (@code{gcbf}), otherwise it will be set to the handle of the current figure\n## (@code{gcf}).\n##\n## @var{pos} is either a two-value numeric vector or a string.  If @var{pos} is\n## numeric then it must be of the form @code{[h, v]} specifying the horizontal\n## and vertical offsets of the figure with respect to the screen.  A positive\n## value indicates the offset between the left (or bottom for the vertical\n## component) of the screen, and the left (or bottom) of the figure.  A\n## negative value indicates the offset between the right (or top) of the screen\n## and the right (or top) of the figure.\n##\n## Possible values for @var{pos} as a string are\n##\n## @table @code\n## @item north\n## Top center of the screen.\n##\n## @item south\n## Bottom center of the screen.\n##\n## @item east\n## Right center of the screen.\n##\n## @item west\n## Left center of the screen.\n##\n## @item northeast\n## Top right of the screen.\n##\n## @item northwest\n## Top left of the screen.\n##\n## @item southeast\n## Bottom right of the screen.\n##\n## @item southwest\n## Bottom left of the screen.\n##\n## @item center\n## Center of the screen.\n##\n## @item onscreen (default)\n## The figure will be minimally moved to be entirely visible on the screen,\n## with a 30 pixel extra padding from the sides of the screen.  This is the\n## default value if none is provided.\n## @end table\n##\n## @var{event} contains event data that will be ignored.  This construct\n## facilitates a call to movegui from a callback.\n##\n## @end deftypefn\n\nfunction movegui (varargin)\n\n  if (nargin > 3)\n    print_usage ();\n  endif\n\n  ## Default values for input arguments\n  h = [];\n  pos = \"onscreen\";\n\n  ## Get input arguments\n  if (nargin == 3)\n    h = varargin{1};\n    pos = varargin{3};\n  elseif (nargin == 2)\n    h = varargin{1};\n    pos = varargin{2};\n  elseif (nargin == 1)\n    if (ishghandle (varargin{1}) && isscalar (varargin{1}))\n      h = varargin{1};\n    else\n      pos = varargin{1};\n    endif\n  endif\n\n  ## Check figure handle\n  if (isempty (h))\n    h = gcbf ();\n    if (isempty (h))\n      h = gcf ();\n    endif\n  elseif (ishghandle (h))\n    h = ancestor (h, \"figure\");\n  else\n    error (\"movegui: H must be a graphics handle\");\n  endif\n\n  ## Get current position in pixels\n  units_fig = get (h, \"units\");\n  set (h, \"units\", \"pixels\");\n  fpos = get (h, \"position\");  # OuterPosition seems unreliable\n  set (h, \"units\", units_fig);\n\n  ## Get screen size in pixels\n  units_groot = get (groot (), \"units\");\n  set (groot (), \"units\", \"pixels\");\n  screen_size = get (groot (), \"ScreenSize\");\n  set (groot (), \"units\", units_groot);\n\n  ## Set default figure and screen border sizes [left, top, right, bottom]\n  f = [0, 90, 0, 30];\n  s = [0,  0, 0, 30];\n\n  ## Make sure figure is not larger than screen\n  fpos(1) = max (fpos(1), 1);\n  fpos(2) = max (fpos(2), 1);\n  fpos(3) = min (fpos(3), screen_size(3));\n  fpos(4) = min (fpos(4), screen_size(4));\n\n  ## Standard figure coordinates\n  ## left, middle, right\n  x = [s(1)+f(1), (screen_size(3)-fpos(3))/2, screen_size(3)-fpos(3)-s(3)-f(3)];\n  ## bottom, middle top\n  y = [s(4)+f(4), (screen_size(4)-fpos(4))/2, screen_size(4)-fpos(4)-s(2)-f(2)];\n\n  ## Compute new position\n  if (isnumeric (pos) && isreal (pos) && numel (pos) == 2)\n    fpos(1) = ifelse (pos(1) >= 0, pos(1), pos(1) + x(3));\n    fpos(2) = ifelse (pos(2) >= 0, pos(2), pos(2) + y(3));\n  elseif (ischar (pos))\n    switch (lower (pos))\n      case \"north\"\n        fpos(1:2) = [x(2), y(3)];\n      case \"south\"\n        fpos(1:2) = [x(2), y(1)];\n      case \"east\"\n        fpos(1:2) = [x(3), y(2)];\n      case \"west\"\n        fpos(1:2) = [x(1), y(2)];\n      case \"northeast\"\n        fpos(1:2) = [x(3), y(3)];\n      case \"northwest\"\n        fpos(1:2) = [x(1), y(3)];\n      case \"southeast\"\n        fpos(1:2) = [x(3), y(1)];\n      case \"southwest\"\n        fpos(1:2) = [x(1), y(1)];\n      case \"center\"\n        fpos(1:2) = [x(2), y(2)];\n      case \"onscreen\"\n        if (fpos(1) > x(3))\n          fpos(1) = x(3) - 30;\n        endif\n        if (fpos(2) > y(3))\n          fpos(2) = y(3) - 30;\n        endif\n        fpos(1) = max (fpos(1), 30);\n        fpos(2) = max (fpos(2), 30);\n      otherwise\n        error (\"movegui: invalid position\");\n    endswitch\n  elseif (nargin == 2 && ! isempty (gcbo))\n    ## Ignore event data (from callback)\n    movegui (h);\n    return;\n  else\n    error (\"movegui: invalid position\");\n  endif\n\n  ## Move figure\n  set (h, \"units\", \"pixels\", \"position\", fpos);\n  set (h, \"units\", units_fig);\n\nendfunction\n\n\n## FIXME: This test does not verify the results, only that the function\n##        can be invoked by different methods.\n%!test\n%! unwind_protect\n%!   h = figure (\"visible\", \"off\");\n%!   pos = {[10 10], [10 -10], [-10 10], [-10 -10], [10 10]',...\n%!     \"north\", \"east\", \"south\", \"west\", ...\n%!     \"northwest\", \"northeast\", \"southeast\", \"southwest\", ...\n%!     \"center\", \"onscreen\"};\n%!   for i = 1:numel (pos)\n%!     movegui (h, pos{i});\n%!     movegui (pos{i});\n%!     movegui (h, struct (\"evt\", []), pos{i});\n%!   endfor\n%!   movegui ();\n%!   movegui (h);\n%! unwind_protect_cleanup\n%!   close (h);\n%! end_unwind_protect\n\n## Test input validation\n%!error movegui (1,2,3,4)\n%!error <H must be a graphics handle> movegui (-1, [1,1])\n%!error <invalid position>\n%! unwind_protect\n%!   h = figure (\"visible\", \"off\");\n%!   movegui (h, \"foobar\");\n%! unwind_protect_cleanup\n%!   close (h);\n%! end_unwind_protect\n%!error <invalid position>\n%! unwind_protect\n%!   h = figure (\"visible\", \"off\");\n%!   movegui (h, [1, 2, 3]);\n%! unwind_protect_cleanup\n%!   close (h);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/gui/msgbox.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} msgbox (@var{msg})\n## @deftypefnx {} {@var{h} =} msgbox (@var{msg}, @var{title})\n## @deftypefnx {} {@var{h} =} msgbox (@var{msg}, @var{title}, @var{icon})\n## @deftypefnx {} {@var{h} =} msgbox (@var{msg}, @var{title}, \"custom\", @var{cdata})\n## @deftypefnx {} {@var{h} =} msgbox (@var{msg}, @var{title}, \"custom\", @var{cdata}, @var{colormap})\n## @deftypefnx {} {@var{h} =} msgbox (@dots{}, @var{opt})\n## Display @var{msg} using a message dialog box.\n##\n## The message may have multiple lines separated by newline characters (\"\\n\"),\n## or it may be a cellstr array with one element for each line.\n##\n## The optional input @var{title} (character string) can be used to decorate\n## the dialog caption.\n##\n## The optional argument @var{icon} selects a dialog icon.\n## It can be one of @qcode{\"none\"} (default), @qcode{\"error\"}, @qcode{\"help\"},\n## @qcode{\"warn\"}, or @qcode{\"custom\"}.  The latter must be followed by an\n## image array @var{cdata}, and for indexed images the associated colormap.\n##\n## The final optional argument @var{opt} controls the behavior of the dialog.\n## If @var{opt} is a string, it may be one of\n##\n## @table @asis\n## @item @qcode{\"non-modal\"} (default)\n## The dialog is normal.\n##\n## @item @qcode{\"modal\"}\n## If any dialogs already exist with the same title, the most recent is reused\n## and all others are closed.  The dialog is displayed @qcode{\"modal\"} which\n## means it prevents users from interacting with any other GUI element until\n## the dialog has been closed.\n##\n## @item @qcode{\"replace\"}\n## If any dialogs already exist with the same title, the most recent is reused\n## and all others are closed.  The resulting dialog is set @qcode{\"non-modal\"}.\n## @end table\n##\n## If @var{opt} is a structure, it must contain fields @qcode{\"WindowStyle\"}\n## and @qcode{\"Interpreter\"}:\n##\n## @table @asis\n## @item @qcode{\"WindowStyle\"}\n## The value must be @qcode{\"non-modal\"}, @qcode{\"modal\"}, or\n## @qcode{\"replace\"}.  See above.\n##\n## @item @qcode{\"Interpreter\"}\n## Controls the @qcode{\"interpreter\"} property of the text object used for\n## displaying the message.  The value must be @qcode{\"tex\"} (default),\n## @qcode{\"none\"}, or @qcode{\"latex\"}.\n## @end table\n##\n## The return value @var{h} is a handle to the figure object used for building\n## the dialog.\n##\n## Examples:\n##\n## @example\n## @group\n## msgbox (\"Some message for the user.\");\n## msgbox (\"Some message\\nwith two lines.\");\n## msgbox (@{\"Some message\", \"with two lines.\"@});\n## msgbox (\"Some message for the user.\", \"Fancy caption\");\n##\n## ## A message dialog box with error icon\n## msgbox (\"Some message for the user.\", \"Fancy caption\", \"error\");\n## @end group\n## @end example\n##\n## @seealso{errordlg, helpdlg, inputdlg, listdlg, questdlg, warndlg}\n## @end deftypefn\n\nfunction retval = msgbox (msg, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (msg) && ! iscellstr (msg))\n    error (\"msgbox: MSG must be a string or cell array of strings\");\n  endif\n\n  nargs = numel (varargin);\n  tit = \"\";\n  icon = \"none\";\n  windowstyle = \"non-modal\";\n  interpreter = \"tex\";\n\n  if (nargs > 0)\n    ## Check for option argument in last position\n    if (isstruct (varargin{nargs}))\n      opts = varargin{nargs};\n      if (isfield (opts, \"WindowStyle\"))\n        windowstyle = opts.WindowStyle;\n      endif\n      if (isfield (opts, \"Interpreter\"))\n        interpreter = opts.Interpreter;\n      endif\n\n      if (! any (strcmp (windowstyle, {\"non-modal\", \"modal\", \"replace\"})))\n        error ('msgbox: invalid value \"%s\" for WindowStyle', windowstyle);\n      endif\n      nargs -= 1;\n\n    elseif (any (strcmp (varargin{nargs}, {\"non-modal\", \"modal\", \"replace\"})))\n      windowstyle = varargin{nargs};\n      nargs -= 1;\n    endif\n  endif\n\n  if (nargs > 0)\n    tit = varargin{1};\n    if (! ischar (tit))\n      error (\"msgbox: TITLE must be a string\");\n    endif\n    if (nargs > 1)\n      icon = varargin{2};\n      if (! any (strcmp (icon, {\"help\", \"warn\", \"error\", \"none\", \"custom\"})))\n        if (ischar (icon))\n          error ('msgbox: invalid value \"%s\" for ICON', icon);\n        else\n          error (\"msgbox: ICON must be a string\");\n        endif\n      elseif (strcmp (icon, \"custom\"))\n        if (nargs < 3)\n          error ('msgbox: missing data for \"custom\" icon');\n        endif\n        icon = struct (\"cdata\", varargin{3}, \"colormap\", []);\n        if (! isnumeric (icon.cdata))\n          error ('msgbox: invalid data for \"custom\" icon');\n        elseif (! ismatrix (icon.cdata)\n                && (ndims (icon.cdata) != 3 || size (icon.cdata, 3) != 3))\n          error ('msgbox: invalid data for \"custom\" icon');\n        elseif (ismatrix (icon.cdata) && nargs == 4)\n          icon.colormap = varargin{4};\n        elseif (nargs > 3)\n          print_usage ();\n        endif\n      elseif (nargs > 2)\n        print_usage ();\n      endif\n    endif\n  endif\n\n  ## Window behavior and text interpreter\n  if (strcmp (windowstyle, \"non-modal\"))\n    windowstyle = \"normal\";\n  endif\n\n  ## Make a GUI element or print to console\n  if (__event_manager_have_dialogs__ ())\n    retval = __msgbox__ (msg, tit, icon, windowstyle, interpreter);\n  else\n    if (iscellstr (msg))\n      msg = strjoin (msg, \"\\n\");\n    endif\n    if (isstruct (icon))\n      icon = \"custom\";\n    endif\n    disp (sprintf (\"\\n%s:\\t%s\\n\\t%s\\n\",\n                   upper (icon), tit, strrep (msg, \"\\n\", \"\\n\\t\")));\n    retval = 1;\n  endif\n\nendfunction\n\nfunction hf = __msgbox__ (msg, tit, icon, windowstyle, interpreter)\n\n  ## Prepare graphics objects\n  hf = [];\n  if (strcmp (windowstyle, \"replace\") || strcmp (windowstyle, \"modal\"))\n    hf = findall (groot, \"tag\", \"__dialog__\", \"-and\", \"name\", tit);\n  endif\n  if (strcmp (windowstyle, \"replace\"))\n    windowstyle = \"normal\";\n  endif\n\n  if (! isempty (hf))\n    if (numel (hf) > 1)\n      close (hf(2:end));\n    endif\n    hf = hf(1);\n    set (hf, \"visible\", \"off\", \"windowstyle\", \"normal\");\n  else\n    hf = dialog (\"visible\", \"off\", \"name\", tit, \"tag\", \"__dialog__\", ...\n                 \"windowstyle\", \"normal\");\n    if (! strcmp (graphics_toolkit (), \"qt\"))\n      graphics_toolkit (hf, \"qt\");\n    endif\n  endif\n\n  hp = uipanel (hf);\n\n  hax = axes (\"parent\", hp, \"visible\", \"off\", \"units\", \"pixels\", ...\n              \"ydir\", \"reverse\");\n\n  ht = text (\"parent\", hax, \"string\", msg, \"units\", \"pixels\", ...\n             \"fontsize\", 14, \"interpreter\", interpreter);\n\n  ## Hold default icons data in a persistent variable\n  persistent cdata = struct (\"help\", [], \"warn\", [], \"error\", []);\n\n  icon_name = \"custom\";\n  if (ischar (icon))\n    icon_name = icon;\n    icon = struct (\"cdata\", [], \"colormap\", []);\n    if (isfield (cdata, icon_name))\n      if (! isempty (cdata.(icon_name)))\n        icon.cdata = cdata.(icon_name);\n      else\n        if (strcmp (icon_name, \"help\"))\n          icon_name = \"information\";\n        elseif (strcmp (icon_name, \"warn\"))\n          icon_name = \"warning\";\n        endif\n        tmp = __event_manager_named_icon__ ([\"dialog-\" icon_name]);\n        ## Fake transparency until the opengl renderer handles it:\n        ## RGB data from Qt are premultiplied, we only need to add the\n        ## background part\n        alpha = tmp(:,:,4);\n        tmp(:,:,4) = [];\n        backgnd = get (hp, \"backgroundcolor\");\n        tmp(:,:,1) += backgnd(1) * (255-alpha);\n        tmp(:,:,2) += backgnd(2) * (255-alpha);\n        tmp(:,:,3) += backgnd(3) * (255-alpha);\n        icon.cdata = tmp;\n        cdata.(icon_name) = tmp;\n\n      endif\n    endif\n  endif\n\n  ## Compute bbox in pixels\n  ax_sz = [200 60];\n  ax_margin = 12;\n  txt_margin = 20;\n  button_margin = 40;\n\n  extent = get (ht, \"extent\");\n  extent(3) += txt_margin;\n\n  im_sz = size (icon.cdata);\n\n  if (! isempty (icon.cdata))\n    extent(3) += im_sz(2);\n    extent(4) = max (extent(4), im_sz(1));\n  endif\n\n  ax_sz = max ([ax_sz; extent(3:4)+2*ax_margin]);\n\n  ## Align text left when there is an icon\n  text_offset = txt_margin;\n  if (! isempty (icon.cdata))\n    if (! isempty (icon.colormap))\n      set (hax, \"colormap\", icon.colormap)\n    endif\n    image (\"parent\", hax, \"cdata\", icon.cdata, \"cdatamapping\", \"direct\", ...\n           \"xdata\", [1 im_sz(2)], \"ydata\", [-(im_sz(1)-1)/2 (im_sz(1)-1)/2]);\n    text_offset = im_sz(2) + txt_margin;\n  endif\n\n  ## Set objects position\n  wd = ax_sz(1);\n  hg = ax_sz(2) + button_margin;\n  center = get (0, \"screensize\")(3:4) / 2;\n\n  set (hf, \"position\", [center(1)-wd/2 center(2)-hg/2 wd hg]);\n\n  set (hax, \"position\", [0 button_margin ax_sz], ...\n       \"xlim\", [1 ax_sz(1)]-ax_margin, \"ylim\", [-ax_sz(2)/2 ax_sz(2)/2], ...\n       \"units\", \"normalized\");\n\n  set (ht, \"units\", \"data\", \"position\", [text_offset 0 0]);\n\n  hui = uicontrol (\"string\", \"OK\",\n                   \"callback\", @cb_callback,\n                   \"keypressfcn\", @cb_keypress,\n                   \"position\", [ax_sz(1)/2-40 ax_margin 80 28], \"parent\", hp);\n\n  uicontrol (hui);  # Set keyboard focus on the uicontrol\n\n  set (hf, \"windowstyle\", windowstyle, \"visible\", \"on\");\n\nendfunction\n\n## Callback when button clicked (close window)\nfunction cb_callback (~, ~)\n  close (gcbf ());\nendfunction\n\n## Callback when key typed (close window on activation of button)\nfunction cb_keypress (~, ev)\n  if (any (strcmp (ev.Key, {\"enter\", \"return\", \"escape\", \"space\"})))\n    close (gcbf ());\n  endif\nendfunction\n\n\n%!demo\n%! msgbox (\"A bare dialog\");\n\n%!demo\n%! msgbox (\"An informative string\", \"Documentation\", \"help\");\n\n%!demo\n%! msgbox (\"Something the user should hear about before continuing\", ...\n%!         \"Take care!\", \"warn\");\n\n%!demo\n%! msgbox (\"A critical message for the user\", \"Error\", \"error\");\n\n%!demo\n%! msgbox ({\"The default interpreter is 'tex':\", ...\n%!          '\\Delta_{1-2} = r_2 - r_1'}, \"Documentation\", \"help\");\n\n%!demo\n%! msgbox ({\"Help dialog with uninterpreted string:\", ...\n%!          '\\Delta_{1-2} = r_2 - r_1'}, \"Documentation\", \"help\", ...\n%!          struct (\"Interpreter\", \"none\", \"WindowStyle\", \"non-modal\"));\n\n%!demo\n%! msgbox ({\"This dialog has replaced all the previously open dialogs\", ...\n%!          \"that had the same title ('Documentation').\"}, \"Documentation\", ...\n%!         \"warn\", \"replace\");\n\n%!demo\n%! msgbox (\"Custom dialog with a random 32-by-32-by-3 RGB icon.\", ...\n%!         \"Dialog Title\", \"custom\", rand (32, 32, 3));\n\n%!demo\n%! cdata = get (0, \"factoryimagecdata\");\n%! msgbox ({\"Custom dialog with the default Octave image.\", ...\n%!          \"The image is indexed into the 'copper' colormap\"}, ...\n%!         \"Dialog Title\", \"custom\", cdata, copper (64));\n\n## Test input validation\n%!error <Invalid call> msgbox ()\n%!error <MSG must be a string or cell array of strings> msgbox (1)\n%!error <invalid value \"foobar\" for WindowStyle>\n%! msgbox (\"msg\", struct (\"WindowStyle\", \"foobar\"))\n%!error <TITLE must be a string> msgbox (\"msg\", 1)\n%!error <invalid value \"foobar\" for ICON> msgbox (\"msg\", \"title\", \"foobar\")\n%!error <ICON must be a string> msgbox (\"msg\", \"title\", {1})\n%!error <missing data for \"custom\" icon> msgbox (\"msg\", \"title\", \"custom\")\n%!error <invalid data for \"custom\" icon>\n%! msgbox (\"msg\", \"title\", \"custom\", {{1}})\n%!error <Invalid call to msgbox> msgbox (\"msg\", \"title\", \"custom\", 1, 2, 3)\n%!error <Invalid call to msgbox> msgbox (\"msg\", \"title\", \"help\", \"1\")\n"
  },
  {
    "path": "scripts/gui/private/__file_filter__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[retval, defname, defdir] =} __file_filter__ (@var{caller}, @var{file_filter})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [retval, defname, defdir] = __file_filter__ (caller, file_filter)\n\n  retval = {};\n  defname = \"\";\n  defdir = \"\";\n\n  if (nargin == 1 || isempty (file_filter))\n    ## Do nothing, and just add default pattern.\n  elseif (iscell (file_filter))\n    [r, c] = size (file_filter);\n    if (c != 1 && c != 2)\n      error (\"%s: invalid filter specification\", caller);\n    endif\n    if (c == 1)\n      retval = cell (r, 2);\n      for i = 1:r\n        retval{i, 1} = file_filter{i};\n        retval{i, 2} = __default_filtername__ (file_filter{i});\n      endfor\n    else\n      retval = file_filter;\n      for i = 1:r\n        if (isempty (retval{i, 2}))\n          retval{i, 2} = __default_filtername__ (retval{i, 1});\n        endif\n      endfor\n    endif\n  elseif (ischar (file_filter))\n    [defdir, fname, fext] = fileparts (file_filter);\n    if (! strcmp (fname, \"*\"))\n      defname = [fname, fext];\n    endif\n    if (! isempty (fext))\n      fext = [\"*\" fext];\n      retval = {fext, __default_filtername__(fext)};\n    endif\n  endif\n\n  ## Delete any \"*.*\" pattern, and add \"* All Files\"\n  if (! isempty (retval))\n    retval(strcmp (retval(1,:), \"*.*\"), :) = [];\n  endif\n  retval(end+1,:) = {\"*\", __default_filtername__(\"*\")};\n\nendfunction\n\nfunction name = __default_filtername__ (filterext)\n\n  name = \"\";\n\n  switch (filterext)\n    case \"*\"\n      name = \"All Files\";\n    case \"*.m\"\n      name = \"Octave Source Files\";\n    case \"*.c\"\n      name = \"C Source Files\";\n    case {\"*.cc\", \"*.cp\", \"*.cpp\", \"*.CPP\", \"*.cxx\", \"*.c++\" \"*.C\"}\n      name = \"C++ Source Files\";\n    case \"*.oct\"\n      name = \"Octave Compiled Files\";\n  endswitch\n\n  if (isempty (name))\n    extlist = ostrsplit (filterext, \";\");\n    extlist = strrep (extlist, \"*.\", \"\");\n    extlist = upper (extlist);\n    extlist(end+1, :) = repmat ({\",\"}, 1, length (extlist));\n    extlist = strcat (extlist{:});\n    extlist = extlist(1:end-1);\n    name = strcat (extlist, \"-Files\");\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/private/__fltk_file_filter__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{filterspec} =} __fltk_file_filter__ (@var{file_filter})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction retval = __fltk_file_filter__ (file_filter)\n\n  retval = \"\";\n  [r, c] = size (file_filter);\n  if ((c == 0) || (c > 2))\n    error (\"file FILTER cell must have 1 or 2 columns\");\n  endif\n  fltk_str = \"\";\n  for idx = 1 : r\n\n    curr_ext = file_filter{idx, 1};\n    curr_ext = ostrsplit (curr_ext, \";\");\n\n    if (length (curr_ext) > 1)\n      curr_ext = strrep (curr_ext, '*.', ',');\n      curr_ext = strcat (curr_ext{:})(2 : end);\n      curr_ext = strcat (\"*.{\", curr_ext, \"}\");\n    else\n      curr_ext = curr_ext{:};\n    endif\n\n    curr_desc = strcat (curr_ext(3:end), \"-Files\");\n\n    if (c == 2)\n      curr_desc = file_filter{idx, 2};\n      curr_desc = strrep (curr_desc, '(', '<');\n      curr_desc = strrep (curr_desc, ')', '>');\n    endif\n\n    if (length (fltk_str) > 0)\n      fltk_str = strcat (fltk_str, \"\\t\", curr_desc, \" (\", curr_ext, \")\");\n    else\n      fltk_str = strcat (curr_desc, \" (\", curr_ext, \")\");\n    endif\n\n  endfor\n  retval = fltk_str;\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/private/__get_funcname__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{funcname} =} __get_funcname__ (@var{basename})\n## Internal function.\n##\n## Build function name for the current graphics toolkit according to the schema\n## __[basename]_[graphics_toolkit]__, use fltk as default.\n## @end deftypefn\n\nfunction funcname = __get_funcname__ (basename)\n\n  if (! __event_manager_enabled__ () || ! __event_manager_have_dialogs__ ())\n    tk = graphics_toolkit ();\n    funcname = [ \"__\" basename \"_\" tk \"__\"];\n    if (numel (tk) > 0 && ! strcmp (tk, \"fltk\")\n        && ! __is_function__ (funcname))\n      warning (\"%s: no implementation for toolkit '%s', using 'fltk' instead\",\n               basename, tk);\n    endif\n    funcname = [\"__\" basename \"_fltk__\"];\n  else\n    funcname = \"\";\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/private/__is_function__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} __is_function__ (@var{fcn})\n## Return true if @var{fcn} is an m-file function, @file{.oct} or @file{.mex}\n## function, or a built-in function.\n## @end deftypefn\n\nfunction tf = __is_function__ (fcn)\n\n  existval = exist (fcn);\n  tf = (existval == 2 || existval == 3 || existval == 5);\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/private/__ok_cancel_dlg__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{hf}, @var{hok}, @var{hcancel}] =} __ok_cancel_dlg__ (@var{dlg_title})\n## Undocumented internal function.\n## @seealso{}\n## @end deftypefn\n\nfunction [hf, hok, hcancel, hpanel] = __ok_cancel_dlg__ (dlg_title, varargin)\n\n  hf = dialog (\"name\", dlg_title, varargin{:});\n  setappdata (hf, \"__ok_cancel_btn__\", \"cancel\");\n\n  hpanel = uipanel (hf, \"units\", \"pixels\", \"bordertype\", \"none\");\n\n  hok = uicontrol (hf, \"style\", \"pushbutton\", \"string\", \"Ok\");\n\n  hcancel = uicontrol (hf, \"style\", \"pushbutton\", \"string\", \"Cancel\");\n\n  cb_fix_button_position (hf, [], hcancel, hok, hpanel);\n  set (hf, \"sizechangedfcn\", {@cb_fix_button_position, hcancel, hok, hpanel});\n\nendfunction\n\nfunction cb_fix_button_position (hf, evt, hcancel, hok, hpanel)\n\n  persistent margin = 20;\n  persistent hgt = 30;\n  persistent wd = 70;\n\n  units = get (hf, \"units\");\n  unwind_protect\n    set (hf, \"units\", \"pixels\");\n    pos = get (hf, \"position\");\n    set (hok, \"position\",\n         [(pos(3) - 2 * margin - 2 * wd), margin, wd, hgt]);\n    set (hcancel, \"position\",\n         [(pos(3) - margin - wd), margin, wd, hgt]);\n    set (hpanel, \"position\", [0 60 pos(3) pos(4)-60]);\n  unwind_protect_cleanup\n    set (hf, \"units\", units);\n  end_unwind_protect\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/private/__uigetdir_fltk__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{dirname} =} __uigetdir_fltk__ (@var{start_path}, @var{dialog_title})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction dirname = __uigetdir_fltk__ (start_path, dialog_title)\n\n  if (exist (\"__fltk_uigetfile__\") != 3)\n    error (\"uigetdir: fltk graphics toolkit required\");\n  endif\n\n  dirname = __fltk_uigetfile__ (\"\", dialog_title, start_path, \"dir\");\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/private/__uigetfile_fltk__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} __uigetfile_fltk__ (@var{filters}, @var{title}, @var{defval}, @var{multiselect}, @var{defdir})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [retval, retpath, retindex] = __uigetfile_fltk__ (filters, title, defval, multiselect, defdir)\n\n  if (exist (\"__fltk_uigetfile__\") != 3)\n    error (\"uigetfile: fltk graphics toolkit required\");\n  endif\n\n  filters = __fltk_file_filter__ (filters);\n  if (length (defdir) > 0)\n    defval = fullfile (defdir, defval);\n  endif\n  [retval, retpath, retindex] = ...\n    __fltk_uigetfile__ (filters, title, defval, multiselect);\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/private/__uiobject_split_args__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{p}, @var{args}] =} __uiobject_split_args__ (@var{who}, @var{in_args}, @var{parent_type}, @var{use_gcf})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [parent, args] = __uiobject_split_args__ (who, in_args, parent_type = {}, use_gcf = 1)\n\n  parent = [];\n  args = {};\n  offset = 1;\n\n  if (! isempty (in_args))\n    if (ishghandle (in_args{1}))\n      parent = in_args{1};\n      offset = 2;\n    elseif (! ischar (in_args{1}) && ! isstruct (in_args{1}))\n      error (\"%s: invalid parent handle\", who);\n    endif\n\n    args = in_args(offset:end);\n  endif\n\n  if (! isempty (args))\n    i = find (strcmpi (args(1:2:end), \"parent\"), 1, \"first\");\n    if (! isempty (i) && numel (args) >= 2*i)\n      parent = args{2*i};\n      if (! ishghandle (parent))\n        error (\"%s: invalid parent handle\", who);\n      endif\n      args((2*i-1):2*i) = [];\n    endif\n  endif\n\n  if (! isempty (parent))\n    if (! isempty (parent_type)\n        && isempty (find (strcmpi (get (parent, \"type\"), parent_type))))\n      error (\"%s: invalid parent, the parent type must be: %s\", ...\n             who, sprintf (\"%s, \", parent_type{:})(1:end-2));\n    endif\n  elseif (use_gcf)\n    parent = gcf ();\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/private/__uiputfile_fltk__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} __uiputfile_fltk__ (@var{filters}, @var{title}, @var{defval}, @var{position}, @var{tag}, @var{defdir})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [retval, retpath, retindex] = __uiputfile_fltk__ (filters, title, defval, tag, defdir)\n\n  if (exist (\"__fltk_uigetfile__\") != 3)\n    error (\"uiputfile: fltk graphics toolkit required\");\n  endif\n\n  filters = __fltk_file_filter__ (filters);\n  if (length (defdir) > 0)\n    defval = fullfile (defdir, defval);\n  endif\n  [retval, retpath, retindex] = ...\n    __fltk_uigetfile__ (filters, title, defval, tag);\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/questdlg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{btn} =} questdlg (@var{msg})\n## @deftypefnx {} {@var{btn} =} questdlg (@var{msg}, @var{title})\n## @deftypefnx {} {@var{btn} =} questdlg (@var{msg}, @var{title}, @var{default})\n## @deftypefnx {} {@var{btn} =} questdlg (@var{msg}, @var{title}, @var{btn1}, @var{btn2}, @var{default})\n## @deftypefnx {} {@var{btn} =} questdlg (@var{msg}, @var{title}, @var{btn1}, @var{btn2}, @var{btn3}, @var{default})\n## Display @var{msg} using a question dialog box and return the caption of\n## the activated button.\n##\n## The message may have multiple lines separated by newline characters (\"\\n\"),\n## or it may be a cellstr array with one element for each line.\n##\n## The optional @var{title} (character string) can be used to specify the\n## dialog caption.  It defaults to @qcode{\"Question Dialog\"}.\n##\n## The dialog may contain two or three buttons which will all close the dialog.\n##\n## The string @var{default} identifies the default button, which is activated\n## by pressing the @key{ENTER} key.  It must match one of the strings given\n## in @var{btn1}, @var{btn2}, or @var{btn3}.\n##\n## If only @var{msg} and @var{title} are specified, three buttons with the\n## default captions @qcode{\"Yes\"}, @qcode{\"No\"}, and @qcode{\"Cancel\"} are used.\n##\n## If only two button captions, @var{btn1} and @var{btn2}, are specified the\n## dialog will have only these two buttons.\n##\n## Examples:\n##\n## @example\n## @group\n## btn = questdlg (\"Close Octave?\", \"Some fancy title\", ...\n##                 \"Yes\", \"No\", \"No\");\n## if (strcmp (btn, \"Yes\"))\n##   exit ();\n## endif\n## @end group\n## @end example\n##\n## @seealso{errordlg, helpdlg, inputdlg, listdlg, msgbox, warndlg}\n## @end deftypefn\n\nfunction btn = questdlg (msg, title = \"Question Dialog\", varargin)\n\n  if (nargin < 1 || nargin > 6)\n    print_usage ();\n  endif\n\n  if (! ischar (msg))\n    if (! iscell (msg))\n      error (\"questdlg: MSG must be a character string or cellstr array\");\n    endif\n\n    msg = sprintf (\"%s\\n\", msg{:});\n    msg(end) = \"\";\n  endif\n\n  if (! ischar (title))\n    error (\"questdlg: TITLE must be a character string\");\n  endif\n\n  options{1} = \"Yes\";      # button1\n  options{2} = \"No\";       # button2\n  options{3} = \"Cancel\";   # button3\n  options{4} = \"Yes\";      # default\n\n  defbtn_error_msg = \"questdlg: DEFAULT must match one of the button options\";\n\n  switch (numel (varargin))\n    case 0\n      ## use default default\n\n    case 1\n      ## default button string\n      options{4} = varargin{1};  # default\n      if (! any (strcmp (options{4}, options(1:3))))\n        error (defbtn_error_msg);\n      endif\n\n    case 3\n      ## two buttons and default button string\n      options{1} = varargin{1};  # button1\n      options{2} = \"\";           # not used, no middle button\n      options{3} = varargin{2};  # button3\n      options{4} = varargin{3};  # default\n      if (! any (strcmp (options{4}, options([1 3]))))\n        error (defbtn_error_msg);\n      endif\n\n    case 4\n      ## three buttons and default button string\n      options{1} = varargin{1};  # button1\n      options{2} = varargin{2};  # button2\n      options{3} = varargin{3};  # button3\n      options{4} = varargin{4};  # default\n      if (! any (strcmp (options{4}, options(1:3))))\n        error (defbtn_error_msg);\n      endif\n\n  endswitch\n\n  if (__event_manager_have_dialogs__ ())\n    btn = __event_manager_question_dialog__ (msg, title, options{1}, options{2},\n                                             options{3}, options{4});\n  else\n    error (\"questdlg is not available in this version of Octave\");\n  endif\n\nendfunction\n\n\n%!demo\n%! disp ('- test questdlg with two buttons');\n%! a = questdlg ('Would you like some free money?',...\n%!               '$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $',...\n%!               'No', 'Cancel', 'Cancel');\n%! if (strcmp (a, 'No'))\n%!   msgbox ('Suit yourself.', 'Message Box');\n%! endif\n\n%!demo\n%! disp ('- test questdlg with message and title only.');\n%! a = 'Yes';\n%! c = 0;\n%! while (strcmp (a, 'Yes') && ! c)\n%!   a = questdlg ('Close this Question Dialog?', 'Reductio Ad Absurdum');\n%!   if (strcmp (a, 'Yes'))\n%!     q = 'Are you sure?';\n%!     while (strcmp (a, 'Yes'))\n%!       a = questdlg (q, 'Reductio Ad Absurdum');\n%!       word = ' really';\n%!       i = strfind (q, word);\n%!       if (isempty (i))\n%!         i = strfind (q, ' sure');\n%!         q = [q '!'];\n%!       else\n%!         word = [word ','];\n%!       endif\n%!       q = [q(1:i-1) word q(i:end)];\n%!     endwhile\n%!   endif\n%!   if (strcmp (a, 'Cancel'))\n%!     uiwait (warndlg ('Answer \"Yes\" or \"No\".', 'Warning Dialog'));\n%!     c = 1;\n%!   endif\n%! endwhile\n%! msgbox ('Whew!');\n\n%!demo\n%! disp ('- test questdlg with five inputs');\n%! ans = questdlg ('Are you ready Steve?', 'Brian', 'No', 'Uh huh', 'Uh huh');\n%! if (! strcmp (ans, 'No'))\n%!   ans = questdlg ('Andy?', 'Brian', 'No', 'Yeah', 'Yeah');\n%!   if (! strcmp (ans, 'No'))\n%!     ans = questdlg ('Mick?', 'Brian', 'No', 'Okay', 'Okay');\n%!     if (! strcmp (ans, 'No'))\n%!       ans = msgbox (\"Well all right, fellas.    \\n\\n     Let''s GO!!!!!\",...\n%!                     'Ballroom Blitz', 'none');\n%!     endif\n%!   endif\n%! endif\n\n## Test input validation\n%!error <Invalid call> questdlg ()\n%!error <Invalid call> questdlg (1,2,3,4,5,6,7)\n%!error <MSG must be a character string or cellstr array> questdlg (1)\n%!error <TITLE must be a character string> questdlg (\"msg\", 1)\n%!error <DEFAULT must match one of the button> questdlg (\"msg\", \"title\", \"ABC\")\n%!error <DEFAULT must match one of the button>\n%! questdlg (\"msg\", \"title\", \"btn1\", \"btn2\", \"ABC\");\n%!error <DEFAULT must match one of the button>\n%! questdlg (\"msg\", \"title\", \"btn1\", \"btn2\", \"btn3\", \"ABC\");\n"
  },
  {
    "path": "scripts/gui/rmappdata.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} rmappdata (@var{h}, @var{name})\n## @deftypefnx {} {} rmappdata (@var{h}, @var{name1}, @var{name2}, @dots{})\n## Delete the application data @var{name} from the graphics object with handle\n## @var{h}.\n##\n## @var{h} may also be a vector of graphics handles.  Multiple application data\n## names may be supplied to delete several properties at once.\n##\n## @seealso{setappdata, getappdata, isappdata}\n## @end deftypefn\n\nfunction rmappdata (h, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  h = h(:).';\n  if (! all (ishghandle (h)))\n    error (\"rmappdata: H must be a scalar or vector of graphic handles\");\n  elseif (! iscellstr (varargin))\n    error (\"rmappdata: NAME must be a string\");\n  endif\n\n  for hg = h\n    if (isprop (hg, \"__appdata__\"))\n      appdata = get (hg, \"__appdata__\");\n      vld = isfield (appdata, varargin);\n      if (! all (vld))\n        ## FIXME: Should we bother to error out?  Or just silently continue?\n        missing = varargin{find (! vld, 1)};\n        error (\"rmappdata: appdata '%s' is not present\", missing);\n      endif\n      appdata = rmfield (appdata, varargin);\n      set (hg, \"__appdata__\", appdata);\n    endif\n  endfor\n\nendfunction\n\n\n%!test\n%! setappdata (0, \"%hello%\", \"world\");\n%! rmappdata (0, \"%hello%\");\n%! assert (isappdata (0, \"%hello%\"), false);\n\n%!test\n%! setappdata (0, \"%data1%\", ones (3));\n%! setappdata (0, \"%data2%\", {\"hello\", \"world\"});\n%! rmappdata (0, \"%data1%\", \"%data2%\");\n%! assert (isappdata (0, \"%data1%\"), false);\n%! assert (isappdata (0, \"%data2%\"), false);\n\n## Test input validation\n%!error <Invalid call> rmappdata ()\n%!error <Invalid call> rmappdata (1)\n%!error <H must be a scalar .* graphic handle> rmappdata (-1, \"hello\")\n%!error <NAME must be a string> rmappdata (0, 1)\n%!error <appdata 'foobar' is not present> rmappdata (0, \"foobar\")\n"
  },
  {
    "path": "scripts/gui/setappdata.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} setappdata (@var{h}, @var{name}, @var{value})\n## @deftypefnx {} {} setappdata (@var{h}, @var{name1}, @var{value1}, @var{name2}, @var{value2}, @dots{})\n## @deftypefnx {} {} setappdata (@var{h}, @{@var{name1}, @var{name2}, @dots{}@}, @{@var{value1}, @var{value2}, @dots{}@})\n## Set the application data @var{name} to @var{value} for the graphics object\n## with handle @var{h}.\n##\n## @var{h} may also be a vector of graphics handles.  If the application data\n## with the specified @var{name} does not exist, it is created.\n##\n## Multiple @var{name}/@var{value} pairs can be specified.  Alternatively, a\n## cell array of @var{names} and a corresponding cell array of @var{values} can\n## be specified.  For details on obtaining a list of valid application data\n## properties, @pxref{XREFgetappdata,,@code{getappdata}}.\n##\n## @seealso{getappdata, isappdata, rmappdata, guidata, get, set, getpref,\n## setpref}\n## @end deftypefn\n\nfunction setappdata (h, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  h = h(:).';\n  if (! all (ishghandle (h)))\n    error (\"setappdata: H must be a scalar or vector of graphic handles\");\n  elseif (mod (numel (varargin), 2) != 0)\n    error (\"setappdata: NAME/VALUE arguments must occur in pairs\");\n  endif\n\n  if (iscellstr (varargin{1}))\n    if (nargin != 3)\n      error (\"setappdata: only 3 arguments possible when NAME is a cellstr\");\n    elseif (! iscell (varargin{2}))\n      varargin{2} = varargin(2);  # convert to cell\n    endif\n    names = varargin{1};\n    values = varargin{2};\n    n_names = numel (names);\n    n_value = numel (values);\n    if (n_value == 1 && n_names > 1)\n      values = repmat (values, [1, n_names]);\n    elseif (n_names != n_value)\n      error (\"setappdata: number of NAME and VALUE arguments must match\");\n    endif\n    varargin = cell (1, 2*numel (names));\n    varargin(1:2:end) = names;\n    varargin(2:2:end) = values;\n\n  elseif (! all (cellfun (\"isclass\", varargin(1:2:end), \"char\")))\n    error (\"setappdata: NAME must be a string or cellstr\");\n  endif\n\n  for hg = h\n    appdata = get (hg, \"__appdata__\");\n\n    ## Slow, but not likely to be that many elements in loop\n    for narg = 1:2:numel (varargin)\n      appdata.(varargin{narg}) = varargin{narg+1};\n    endfor\n\n    set (hg, \"__appdata__\", appdata);\n  endfor\n\nendfunction\n\n\n%!test\n%! unwind_protect\n%!   setappdata (0, \"%hello%\", \"world\");\n%!   assert (isappdata (0, \"%hello%\"), true);\n%!   assert (getappdata (0, \"%hello%\"), \"world\");\n%! unwind_protect_cleanup\n%!   rmappdata (0, \"%hello%\");\n%! end_unwind_protect\n\n%!test\n%! unwind_protect\n%!   setappdata (0, \"%data1%\", ones (3), \"%data2%\", \"hello world\");\n%!   assert (getappdata (0, \"%data1%\"), ones (3));\n%!   assert (getappdata (0, \"%data2%\"), \"hello world\");\n%!   setappdata (0, \"%data1%\", zeros (3));\n%!   assert (getappdata (0, \"%data1%\"), zeros (3));\n%! unwind_protect_cleanup\n%!   rmappdata (0, \"%data1%\", \"%data2%\");\n%! end_unwind_protect\n\n%!test\n%! unwind_protect\n%!   setappdata (0, {\"%data1%\", \"%data2%\"}, {ones(3), \"hello world\"});\n%!   assert (getappdata (0, \"%data1%\"), ones (3));\n%!   assert (getappdata (0, \"%data2%\"), \"hello world\");\n%!   setappdata (0, \"%data1%\", zeros (3));\n%!   assert (getappdata (0, \"%data1%\"), zeros (3));\n%!   rmappdata (0, \"%data1%\", \"%data2%\");\n%!   setappdata (0, {\"%data1%\", \"%data2%\"}, pi);\n%!   assert (getappdata (0, \"%data1%\"), pi);\n%!   assert (getappdata (0, \"%data2%\"), pi);\n%! unwind_protect_cleanup\n%!   rmappdata (0, \"%data1%\", \"%data2%\");\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> setappdata ()\n%!error <Invalid call> setappdata (0)\n%!error <Invalid call> setappdata (0, \"name\")\n%!error <H must be a scalar .* graphic handle> setappdata (-1, \"foo\", \"bar\")\n%!error <NAME/VALUE arguments must occur in pairs> setappdata (0, \"1\", 2, \"3\")\n%!error <only 3 arguments possible> setappdata (0, {\"1\"}, 2, \"3\", 4)\n%!error <number of NAME and VALUE arguments must match>\n%! setappdata (0, {\"1\", \"2\"}, {2, 3, 4})\n%!error <NAME must be a string> setappdata (0, 1, 2)\n"
  },
  {
    "path": "scripts/gui/uibuttongroup.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hui} =} uibuttongroup ()\n## @deftypefnx {} {@var{hui} =} uibuttongroup (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{hui} =} uibuttongroup (@var{parent})\n## @deftypefnx {} {@var{hui} =} uibuttongroup (@var{parent}, @var{property}, @var{value}, @dots{})\n## @c FIXME: 3rd form is not documented by Matlab nor implemented in Octave.\n## @c        Should it be removed?  (1/9/2022).\n## @deftypefnx {} {} uibuttongroup (@var{h})\n##\n## Create a uibuttongroup object and return a handle to it.\n##\n## A uibuttongroup is used to group uicontrol objects.\n##\n## If @var{parent} is omitted then a uibuttongroup for the current figure is\n## created.  If no figure is available, a new figure is created first.\n##\n## If @var{parent} is given then a uibuttongroup relative to @var{parent} is\n## created.\n##\n## Any provided property value pairs will override the default values of the\n## created uibuttongroup object.\n##\n## The full list of properties is documented at @ref{Uibuttongroup Properties}.\n##\n## Examples:\n##\n## @example\n## @group\n## ## Create figure and panel on it\n## f = figure;\n## ## Create a button group\n## gp = uibuttongroup (f, \"Position\", [ 0 0.5 1 1])\n## ## Create a buttons in the group\n## b1 = uicontrol (gp, \"style\", \"radiobutton\", ...\n##                 \"string\", \"Choice 1\", ...\n##                 \"Position\", [ 10 150 100 50 ]);\n## b2 = uicontrol (gp, \"style\", \"radiobutton\", ...\n##                 \"string\", \"Choice 2\", ...\n##                 \"Position\", [ 10 50 100 30 ]);\n## ## Create a button not in the group\n## b3 = uicontrol (f, \"style\", \"radiobutton\", ...\n##                 \"string\", \"Not in the group\", ...\n##                 \"Position\", [ 10 50 100 50 ]);\n## @end group\n## @end example\n##\n## When called with a single argument @var{h} which is a handle to an existing\n## uibuttongroup object, switch the focus to the specified uibuttongroup.  This\n## functionality is not currently implemented.\n## @seealso{figure, uipanel}\n## @end deftypefn\n\nfunction hui = uibuttongroup (varargin)\n\n  if (nargin == 1 && isgraphics (varargin{1}, \"uibuttongroup\"))\n    warning (\"uibuttongroup: focusing not implemented yet\");\n    return;\n  endif\n\n  [h, args] = __uiobject_split_args__ (\"uibuttongroup\", varargin,\n                                       {\"figure\", \"uipanel\", \"uibuttongroup\"});\n  hui = __go_uibuttongroup__ (h, args{:});\n\nendfunction\n\n\n%!demo\n%! f = clf ();\n%! gp = uibuttongroup (f, \"position\", [0 0.5 1 0.5], ...\n%!                     \"selectionchangedfcn\", ...\n%!                     @(h, e) fprintf (\"Selection changed: %s\\n\", get (e.NewValue, \"string\")));\n%! b1 = uicontrol (gp, \"style\", \"radiobutton\", ...\n%!                     \"string\", \"Choice 1\", ...\n%!                     \"units\", \"normalized\", ...\n%!                     \"position\", [0.01 0.5 0.98 0.5]);\n%! b2 = uicontrol (gp, \"style\", \"radiobutton\", ...\n%!                     \"string\", \"Choice 2\", ...\n%!                     \"units\", \"normalized\", ...\n%!                     \"position\", [0.01 0 0.98 0.5]);\n%! b3 = uicontrol (f, \"style\", \"radiobutton\", ...\n%!                    \"string\", \"Not in the group\", ...\n%!                    \"units\", \"normalized\", ...\n%!                    \"position\", [ 0.01 0 0.98 0.5 ]);\n%! fprintf (\"Current selected: %s\\n\", get (get (gp, \"selectedobject\"), \"string\"));\n%! pause (0.5);\n%! disp (\"Select b2\");\n%! set (gp, \"selectedobject\", b2);\n%! fprintf (\"Current selected: %s\\n\", get (get (gp, \"selectedobject\"), \"string\"));\n%! pause (0.5);\n%! disp (\"Select None\");\n%! set (gp, \"selectedobject\", []);\n%! pause (0.1);\n%! fprintf (\"Current selected: %s\\n\", get (get (gp, \"selectedobject\"), \"string\"));\n\n## Test mutual selection logic for radiobuttons\n## FIXME: commented out until a test can be found that doesn't rely on\n##        long values for pause() which still can occasionally fail.\n%!#test <*55230>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   bg = uibuttongroup (hf);\n%!   b1 = uicontrol (bg, \"style\", \"radiobutton\", \"units\", \"normalized\", ...\n%!                       \"position\", [0, 0, 1, 0.5]);\n%!   b2 = uicontrol (bg, \"style\", \"radiobutton\", \"units\", \"normalized\", ...\n%!                       \"position\", [0, 0.5, 1, 0.5]);\n%!   assert (get (bg, \"selectedobject\"), b1);\n%!   assert (get (b1, \"value\"), 1);\n%!   assert (get (b2, \"value\"), 0);\n%!   ## select radiobutton 2\n%!   set (bg, \"selectedobject\", b2);\n%!   pause (0.5);\n%!   assert (get (b1, \"value\"), 0);\n%!   assert (get (b2, \"value\"), 1);\n%!   ## set radiobutton 1\n%!   set (b1, \"value\", 1);\n%!   pause (0.5);\n%!   assert (get (bg, \"selectedobject\"), b1);\n%!   assert (get (b1, \"value\"), 1);\n%!   assert (get (b2, \"value\"), 0);\n%!   ## unset all radiobuttons\n%!   set (bg, \"selectedobject\", []);\n%!   pause (0.5);\n%!   assert (get (b1, \"value\"), 0);\n%!   assert (get (b2, \"value\"), 0);\n%!   ## change style of selected button\n%!   set (b1, \"value\", 1);\n%!   pause (0.5);\n%!   assert (get (bg, \"selectedobject\"), b1);\n%!   set (b1, \"style\", \"pushbutton\");\n%!   pause (0.5);\n%!   assert (get (bg, \"selectedobject\"), []);\n%!   ## add new button\n%!   b3 = uicontrol (bg, \"style\", \"togglebutton\");\n%!   pause (0.5);\n%!   assert (get (bg, \"selectedobject\"), b3);\n%!   assert (get (b2, \"value\"), 0);\n%!   assert (get (b3, \"value\"), 1);\n%!   ## remove selected button\n%!   delete (b3);\n%!   pause (0.5);\n%!   assert (get (bg, \"selectedobject\"), []);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test mutual selection logic for togglebuttons\n## FIXME: commented out until a test can be found that doesn't rely on\n##        long values for pause() which still can occasionally fail.\n%!#test <*55230>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   bg = uibuttongroup (hf);\n%!   b1 = uicontrol (bg, \"style\", \"togglebutton\", \"units\", \"normalized\", ...\n%!                       \"position\", [0, 0, 1, 0.5]);\n%!   b2 = uicontrol (bg, \"style\", \"togglebutton\", \"units\", \"normalized\", ...\n%!                       \"position\", [0, 0.5, 1, 0.5]);\n%!   assert (get (bg, \"selectedobject\"), b1);\n%!   assert (get (b1, \"value\"), 1);\n%!   assert (get (b2, \"value\"), 0);\n%!   ## select togglebutton 2\n%!   set (bg, \"selectedobject\", b2);\n%!   pause (0.5);\n%!   assert (get (b1, \"value\"), 0);\n%!   assert (get (b2, \"value\"), 1);\n%!   ## set togglebutton 1\n%!   set (b1, \"value\", 1);\n%!   pause (0.5);\n%!   assert (get (bg, \"selectedobject\"), b1);\n%!   assert (get (b1, \"value\"), 1);\n%!   assert (get (b2, \"value\"), 0);\n%!   ## unset all togglebuttons\n%!   set (bg, \"selectedobject\", []);\n%!   pause (0.5);\n%!   assert (get (b1, \"value\"), 0);\n%!   assert (get (b2, \"value\"), 0);\n%!   ## change style of selected button\n%!   set (b1, \"value\", 1);\n%!   pause (0.5);\n%!   assert (get (bg, \"selectedobject\"), b1);\n%!   set (b1, \"style\", \"pushbutton\");\n%!   assert (get (bg, \"selectedobject\"), []);\n%!   ## add new button\n%!   b3 = uicontrol (bg, \"style\", \"togglebutton\");\n%!   pause (0.5);\n%!   assert (get (bg, \"selectedobject\"), b3);\n%!   assert (get (b2, \"value\"), 0);\n%!   assert (get (b3, \"value\"), 1);\n%!   ## remove selected button\n%!   delete (b3);\n%!   pause (0.5);\n%!   assert (get (bg, \"selectedobject\"), []);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/gui/uicontextmenu.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hui} =} uicontextmenu (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{hui} =} uicontextmenu (@var{h}, @var{property}, @var{value}, @dots{})\n##\n## Create a uicontextmenu object and return a handle to it.\n##\n## If @var{h} is omitted then a uicontextmenu for the current figure is\n## created.  If no figure is available, a new figure is created first.\n##\n## If @var{h} is given then a uicontextmenu relative to @var{h} is created.\n##\n## Any provided property value pairs will override the default values of the\n## created uicontextmenu object.\n##\n## The full list of properties is documented at @ref{Uicontextmenu Properties}.\n##\n## Examples:\n##\n## @example\n## @group\n## ## create figure and uicontextmenu\n## f = figure ();\n## c = uicontextmenu (f);\n##\n## ## create menus in the context menu\n## m1 = uimenu (\"parent\", c, \"label\", \"Menu item 1\", ...\n##              \"callback\", \"disp('menu item 1')\");\n## m2 = uimenu (\"parent\", c, \"label\", \"Menu item 2\", ...\n##              \"callback\", \"disp('menu item 2')\");\n##\n## ## set the context menu for the figure\n## set (f, \"uicontextmenu\", c);\n## @end group\n## @end example\n## @seealso{figure, uimenu}\n## @end deftypefn\n\nfunction hui = uicontextmenu (varargin)\n\n  [h, args] = __uiobject_split_args__ (\"uicontextmenu\", varargin, {\"figure\"});\n  hui = __go_uicontextmenu__ (h, args{:});\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/uicontrol.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hui} =} uicontrol ()\n## @deftypefnx {} {@var{hui} =} uicontrol (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{hui} =} uicontrol (@var{parent})\n## @deftypefnx {} {@var{hui} =} uicontrol (@var{parent}, @var{property}, @var{value}, @dots{})\n## @deftypefnx {} {} uicontrol (@var{h})\n##\n## Create a uicontrol object and return a handle to it.\n##\n## A uicontrol object is used to create simple interactive controls such as\n## push buttons, checkboxes, edit and list controls.\n##\n## If @var{parent} is omitted then a uicontrol for the current figure is\n## created.  If no figure is available, a new figure is created first.\n##\n## If @var{parent} is given then a uicontrol relative to @var{parent} is\n## created.\n##\n## Any provided property value pairs will override the default values of the\n## created uicontrol object.\n##\n## The full list of properties is documented at @ref{Uicontrol Properties}.\n##\n## The type of uicontrol created is specified by the @var{style} property.  If\n## no style property is provided, a push button will be created.\n##\n## Valid styles for uicontrol are:\n##\n## @table @asis\n## @item @qcode{\"checkbox\"}\n## Create a checkbox control that allows user on/off selection.\n##\n## @item @qcode{\"edit\"}\n## Create an edit control that allows user input of single or multiple lines\n## of text.\n##\n## @item @qcode{\"listbox\"}\n## Create a listbox control that displays a list of items and allows user\n## selection of single or multiple items.\n##\n## @item @qcode{\"popupmenu\"}\n## Create a popupmenu control that displays a list of options that can be\n## selected when the user clicks on the control.\n##\n## @item @qcode{\"pushbutton\"}\n## Create a push button control that allows user to press to cause an action.\n##\n## @item @qcode{\"radiobutton\"}\n## Create a radio button control intended to be used for mutually exclusive\n## input in a group of radiobutton controls.\n##\n## @item @qcode{\"slider\"}\n## Create a slider control that allows user selection from a range of values\n## by sliding knob on the control.\n##\n## @item @qcode{\"text\"}\n## Create a static text control to display single or multiple lines of text.\n##\n## @item @qcode{\"togglebutton\"}\n## Create a toggle button control that appears like a push button but allows\n## the user to select between two states.\n##\n## @end table\n##\n## Note: For the @qcode{\"edit\"} and @qcode{\"listbox\"} styles, the single or\n## multiple line/selection behavior is determined by the @qcode{\"Min\"} and\n## @qcode{\"Max\"} properties, permitting multiple lines/selections when the\n## values are set such that @w{@code{Max - Min > 1}}.\n##\n## Examples:\n##\n## @example\n## @group\n## ## Create figure and panel on it\n## f = figure;\n## ## Create a button (default style)\n## b1 = uicontrol (f, \"string\", \"A Button\", ...\n##                    \"position\", [10 10 150 40]);\n## ## Create an edit control\n## e1 = uicontrol (f, \"style\", \"edit\", \"string\", \"editable text\", ...\n##                    \"position\", [10 60 300 40]);\n## ## Create a checkbox\n## c1 = uicontrol (f, \"style\", \"checkbox\", \"string\", \"a checkbox\", ...\n##                    \"position\", [10 120 150 40]);\n## @end group\n## @end example\n##\n## When called with a single argument @var{h} which is a handle to an existing\n## uicontrol object, switch the keyboard focus to the specified\n## uicontrol.  As a result, the uicontrol object will receive keyboard\n## events that can be processed using the @qcode{\"keypressfcn\"} callback.\n## @seealso{figure, uipanel}\n## @end deftypefn\n\nfunction hui = uicontrol (varargin)\n\n  if (nargin == 1 && isgraphics (varargin{1}, \"uicontrol\"))\n    set (varargin{1}, \"__focus__\", \"on\");\n    return;\n  endif\n\n  [h, args] = __uiobject_split_args__ (\"uicontrol\", varargin,\n                                       {\"figure\", \"uipanel\", \"uibuttongroup\"});\n\n  ## Validate style\n  idx = find (strcmpi (args(1:2:end), \"style\"), 1, \"last\");\n  if (! isempty (idx) && 2*idx <= numel (args))\n    if (strcmpi (args{2*idx}, \"frame\"))\n      warning (\"Octave:unimplemented-matlab-functionality\",\n               'uicontrol: \"frame\" style is not implemented.  Use uipanel() or uibuttongroup() instead');\n    endif\n  endif\n\n  htmp = __go_uicontrol__ (h, args{:});\n\n  if (nargout > 0)\n    hui = htmp;\n  endif\n\nendfunction\n\n\n%!warning <\"frame\" style is not implemented>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = uicontrol (hf, \"string\", \"Hello World\", \"Style\", \"frame\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/gui/uifigure.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} uifigure ()\n## @deftypefnx {} {@var{h} =} uifigure (\"@var{property}\", @var{value}, @dots{})\n## Create a new figure window for applications.\n##\n## Multiple property-value pairs may be specified for the figure object, but\n## they must occur in pairs.\n##\n## The return value @var{h} is a graphics handle to the created figure object.\n##\n## Programming Note: The full list of properties is documented at\n## @ref{Figure Properties}.  This function differs from @code{figure} in that\n## the created figure is optimized for application development, rather than\n## plotting.  This means features such as menubars and toolbars are turned off.\n## This is not perfect replacement for the @sc{matlab} uifigure object as the\n## properties @qcode{\"AutoResizeChildren\"}, @qcode{\"Icon\"}, and\n## @qcode{\"Scrollable\"} are not implemented.\n## @seealso{uipanel, uibuttongroup}\n## @end deftypefn\n\n## FIXME: This is not a perfect replica of a Matlab uifigure object because\n## some ordinary figure object properties are exposed (e.g., the \"PaperXXX\"\n## properties).  In addition, the following properties are missing:\n## \"AutoResizeChildren\", \"Icon\", \"Scrollable\".\n\nfunction h = uifigure (varargin)\n\n  if (rem (nargin, 2) != 0)\n    error (\"uifigure: PROPERTY/VALUE parameters must occur in pairs\");\n  endif\n\n  strfcn = @(s) any (strcmpi (s, {'AutoResizeChildren', 'Icon', 'Scrollable'}));\n  idx = cellfun (strfcn, varargin (1:2:end));\n  if (any (idx))\n    idx = repelem (idx, 2);\n    props = varargin(idx);  # save special props for applying later\n    varargin(idx) = [];     # remove special props from varargin\n  else\n    props = {};\n  endif\n\n  h = __go_figure__ (NaN, \"handlevisibility\", \"off\",\n                          \"numbertitle\", \"off\", \"integerhandle\", \"off\",\n                          \"menubar\", \"none\", \"toolbar\", \"none\",\n                          varargin{:});\n\n  ## Add uifigure-specific properties on top of regular figure graphics object\n  ## FIXME: There is no implementation behind these properties.\n  addproperty (\"AutoResizeChildren\", h, \"boolean\", \"on\");\n  addproperty (\"Icon\", h, \"data\", []);\n  addproperty (\"Scrollable\", h, \"boolean\", \"off\");\n\n  ## Set values for special properties added above\n  if (! isempty (props))\n    set (h, props{:});\n  endif\n\nendfunction\n\n\n%!test\n%! hf = uifigure (\"visible\", \"off\", \"Icon\", magic (3));\n%! unwind_protect\n%!   assert (isfigure (hf));\n%!   assert (get (hf, {\"numbertitle\", \"menubar\", \"icon\", \"scrollable\"}),\n%!                    {\"off\", \"none\", magic(3), \"off\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <parameters must occur in pairs> uifigure (\"PROP1\")\n"
  },
  {
    "path": "scripts/gui/uigetdir.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{dirname} =} uigetdir ()\n## @deftypefnx {} {@var{dirname} =} uigetdir (@var{init_path})\n## @deftypefnx {} {@var{dirname} =} uigetdir (@var{init_path}, @var{dialog_name})\n## Open a GUI dialog for selecting a directory.\n##\n## If @var{init_path} is not given the current working directory is used.\n##\n## @var{dialog_name} may be used to customize the dialog title.\n##\n## The output @var{dirname} is a character string with the name of the selected\n## directory.  However, if the @samp{Cancel} button is clicked the output is of\n## type double with the value @code{0}.\n## @seealso{uigetfile, uiputfile}\n## @end deftypefn\n\nfunction dirname = uigetdir (init_path = pwd, dialog_name = \"Select Directory to Open\")\n\n  if (! ischar (init_path) || ! ischar (dialog_name))\n    error (\"uigetdir: INIT_PATH and DIALOG_NAME must be string arguments\");\n  endif\n\n  if (! isfolder (init_path))\n    init_path = fileparts (init_path);\n  endif\n\n  if (__event_manager_have_dialogs__ ())\n    file_filter = cell (0, 2);\n    default_file_name = \"\";\n    dialog_mode = \"dir\";\n\n    [filename, dirname, filterindex] ...\n      = __event_manager_file_dialog__ (file_filter, dialog_name,\n                                       default_file_name, dialog_mode,\n                                       init_path);\n  else\n    funcname = __get_funcname__ (mfilename ());\n    dirname = feval (funcname, init_path, dialog_name);\n  endif\n\nendfunction\n\n\n%!demo\n%! uigetdir (pwd, 'Select Directory');\n\n## Remove from test statistics.  No real tests possible.\n%!assert (1)\n"
  },
  {
    "path": "scripts/gui/uigetfile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} uigetfile ()\n## @deftypefnx {} {[@dots{}] =} uigetfile (@var{flt})\n## @deftypefnx {} {[@dots{}] =} uigetfile (@var{flt}, @var{dialog_name})\n## @deftypefnx {} {[@dots{}] =} uigetfile (@var{flt}, @var{dialog_name}, @var{default_file})\n## @deftypefnx {} {[@dots{}] =} uigetfile (@dots{}, \"MultiSelect\", @var{mode})\n##\n## Open a GUI dialog for selecting a file and return the filename @var{fname},\n## the path to this file @var{fpath}, and the filter index @var{fltidx}.\n##\n## @var{flt} contains a (list of) file filter string(s) in one of the following\n## formats:\n##\n## @table @asis\n## @item @qcode{\"/path/to/filename.ext\"}\n## If a filename is given then the file extension is extracted and used as\n## filter.  In addition, the path is selected as current path in the dialog and\n## the filename is selected as default file.\n## Example: @code{uigetfile (\"myfcn.m\")}\n##\n## @item A single file extension @qcode{\"*.ext\"}\n## Example: @code{uigetfile (\"*.ext\")}\n##\n## @item A 2-column cell array\n## containing a file extension in the first column and a brief description in\n## the second column.  Example:\n## @code{uigetfile (@{\"*.ext\", \"My Description\";\"*.xyz\", \"XYZ-Format\"@})}\n##\n## The filter string can also contain a semicolon separated list of filter\n## extensions.  Example:\n## @code{uigetfile (@{\"*.gif;*.png;*.jpg\", \"Supported Picture Formats\"@})}\n##\n## @item A directory name or path name\n## If the folder name of path name contains a trailing file separator, the\n## contents of that folder will be displayed.  If no trailing file separator\n## is present the parent directory is listed.  The substring to the right of\n## the rightmost file separator (if any) will be interpreted as a file or\n## directory name and if that file or directory exists it will be highlighted.\n## If the path name or directory name is entirely or partly nonexistent, the\n## current working directory will be displayed.\n## No filter will be active.\n## @end table\n##\n## @var{dialog_name} can be used to customize the dialog title.\n##\n## If @var{default_file} is given then it will be selected in the GUI dialog.\n## If, in addition, a path is given it is also used as current path.\n##\n## Two or more files can be selected when setting the @qcode{\"MultiSelect\"} key\n## to @qcode{\"on\"}.  In that case, @var{fname} is a cell array containing the\n## files.\n##\n## The outputs @var{fname} and @var{fpath} are strings returning the chosen\n## name and path, respectively.  However, if the @samp{Cancel} button is\n## clicked the outputs are of type double with a value of @code{0}.\n## @var{fltidx} is the index in the list of filter extensions @var{flt} that\n## was selected.\n##\n## @seealso{uiputfile, uigetdir}\n## @end deftypefn\n\nfunction [retfile, retpath, retindex] = uigetfile (varargin)\n\n  if (nargin > 7)\n    error (\"uigetfile: number of input arguments must be less than eight\");\n  endif\n\n  ## Preset default values\n  outargs = {cell(0, 2),         # File Filter\n             \"Open File\",        # Dialog Title\n             \"\",                 # Default filename\n             \"off\",              # MultiSelect on/off\n             pwd};               # Default directory\n\n  idx1 = idx2 = [];\n  has_opts = false;\n  if (nargin > 0)\n    idx1 = find (strcmpi (varargin, \"multiselect\"), 1);\n    idx2 = find (strcmpi (varargin, \"position\"), 1);\n    if (idx1 || idx2)\n      has_opts = true;\n    endif\n  endif\n\n  if (! isempty (idx2))\n    ## FIXME: Remove handling the \"position\" property completely in Octave 9\n    warning (['uigetfile: The \"position\" argument is deprecated and will ', ...\n              \"be ignored.  Consider removing it from the function call.\"]);\n  endif\n\n  optidx = min ([idx1, nargin+1]);\n\n  args = varargin(1:optidx-1);\n\n  len = numel (args);\n  if (len > 0)\n    [outargs{1}, outargs{3}, defdir] = __file_filter__ (\"uigetfile\", args{1});\n    if (! isempty (defdir))\n      outargs{5} = defdir;\n    endif\n  else\n    outargs{1} = __file_filter__ (\"uigetfile\", outargs{1});\n  endif\n\n  if (len > 1)\n    if (ischar (args{2}))\n      if (! isempty (args{2}))\n        outargs{2} = args{2};\n      endif\n    elseif (! isempty (args{2}))\n      print_usage ();\n    endif\n  endif\n\n  if (len > 2)\n    if (ischar (args{3}))\n      if (isfolder (args{3}))\n        fdir = args{3};\n        fname = fext = \"\";\n      else\n        [fdir, fname, fext] = fileparts (varargin{3});\n      endif\n      if (! isempty (fdir))\n        outargs{5} = fdir;\n      endif\n      if (! isempty (fname) || ! isempty (fext))\n        outargs{3} = [fname fext];\n      endif\n    elseif (! isempty (args{3}))\n      print_usage ();\n    endif\n  endif\n\n  if (has_opts)\n    ## string arguments (\"position\" or \"multiselect\")\n\n    ## check for even number of remaining arguments, prop/value pair(s)\n    if (rem (nargin - optidx + 1, 2))\n      error (\"uigetfile: PROPERTY/VALUE arguments must occur in pairs\");\n    endif\n\n    for i = optidx : 2 : nargin\n      prop = varargin{i};\n      val = varargin{i + 1};\n      if (strcmpi (prop, \"position\"))\n        ## FIXME: Remove handling this option in Octave 9.\n      elseif (strcmpi (prop, \"multiselect\"))\n        if (! ischar (val))\n          error ('uigetfile: MultiSelect value must be a string (\"on\"/\"off\")');\n        endif\n        outargs{4} = lower (val);\n      else\n        error (\"uigetfile: unknown argument '%s'\", prop);\n      endif\n    endfor\n  endif\n\n  if (__event_manager_have_dialogs__ ())\n    [retfile, retpath, retindex] = __event_manager_file_dialog__ (outargs{:});\n  else\n    funcname = __get_funcname__ (mfilename ());\n    [retfile, retpath, retindex] = feval (funcname, outargs{:});\n  endif\n\nendfunction\n\n\n%!demo\n%! uigetfile ({'*.gif;*.png;*.jpg', 'Supported Picture Formats'});\n\n## Remove from test statistics.  No real tests possible.\n%!assert (1)\n"
  },
  {
    "path": "scripts/gui/uimenu.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hui} =} uimenu (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{hui} =} uimenu (@var{h}, @var{property}, @var{value}, @dots{})\n## Create a uimenu object and return a handle to it.\n##\n## If @var{h} is omitted then a top-level menu for the current figure is\n## created.  If @var{h} is given then a submenu relative to @var{h} is created.\n##\n## uimenu objects have the following specific properties:\n##\n## @table @asis\n## @item @qcode{\"accelerator\"}\n## A string containing the key, together with CTRL, to execute this\n## menu entry (e.g., @qcode{\"x\"} for CTRL+x).\n##\n## @item @qcode{\"checked\"}\n## Can be set @qcode{\"on\"} or @qcode{\"off\"}.  Sets a mark at this menu entry.\n##\n## @item @qcode{\"enable\"}\n## Can be set @qcode{\"on\"} or @qcode{\"off\"}.  If disabled then the menu entry\n## cannot be selected and is grayed out.\n##\n## @item @qcode{\"foregroundcolor\"}\n## A color value for the text of the menu entry.\n##\n## @item @qcode{\"menuselectedfcn\"}\n## The function called when this menu entry is executed.  It can be either a\n## function string (e.g., @qcode{\"@nospell{myfcn}\"}), a function handle (e.g.,\n## @@@nospell{myfcn}) or a cell array containing the function handle and\n## arguments for the callback function (e.g., @{@@@nospell{myfcn}, arg1,\n## arg2@}).\n##\n## @item @qcode{\"position\"}\n## A scalar value containing the relative menu position.  The first position\n## has value 1 and will be either the left or top depending on the orientation\n## of the uimenu.\n##\n## @item @qcode{\"separator\"}\n## Can be set @qcode{\"on\"} or @qcode{\"off\"}.  If enabled, a separator\n## line is drawn above the current position.  This property is ignored for\n## top-level entries.\n##\n## @item @qcode{\"text\"}\n## A string containing the text for this menu entry.  A @qcode{\"&\"}-symbol\n## can be used to mark the @qcode{\"accelerator\"} character (e.g.,\n## @nospell{@qcode{\"E&xit\"}}).\n##\n## @end table\n##\n## The full list of properties is documented at @ref{Uimenu Properties}.\n##\n## Examples:\n##\n## @example\n## @group\n## f = uimenu (\"text\", \"&File\", \"accelerator\", \"f\");\n## e = uimenu (\"text\", \"&Edit\", \"accelerator\", \"e\");\n## uimenu (f, \"text\", \"Close\", \"accelerator\", \"q\", ...\n##            \"menuselectedfcn\", \"close (gcf)\");\n## uimenu (e, \"text\", \"Toggle &Grid\", \"accelerator\", \"g\", ...\n##            \"menuselectedfcn\", \"grid (gca)\");\n## @end group\n## @end example\n## @seealso{figure}\n## @end deftypefn\n\nfunction hui = uimenu (varargin)\n\n  [h, args] = __uiobject_split_args__ (\"uimenu\", varargin,\n                                       {\"figure\", \"uicontextmenu\", \"uimenu\"});\n\n  htmp = __go_uimenu__ (h, args{:});\n\n  if (nargout > 0)\n    hui = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! surfl (peaks);\n%! colormap (copper (64));\n%! shading ('interp');\n%! f = uimenu ('text', '&File', 'accelerator', 'f');\n%! e = uimenu ('text', '&Edit', 'accelerator', 'e');\n%! uimenu (f, 'text', 'Close', 'accelerator', 'q', ...\n%!            'menuselectedfcn', 'close (gcf)');\n%! uimenu (e, 'text', 'Toggle &Grid', 'accelerator', 'g', ...\n%!            'menuselectedfcn', 'grid (gca)');\n\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! toolkit = graphics_toolkit (\"qt\");\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ui = uimenu (\"text\", \"mytext\");\n%!   assert (findobj (hf, \"type\", \"uimenu\"), ui);\n%!   assert (get (ui, \"text\"), \"mytext\");\n%!   assert (get (ui, \"checked\"), \"off\");\n%!   assert (get (ui, \"separator\"), \"off\");\n%!   assert (get (ui, \"enable\"), \"on\");\n%!   assert (get (ui, \"position\"), 4);\n%! unwind_protect_cleanup\n%!   close (hf);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n## check for top level menus file and edit\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! toolkit = graphics_toolkit (\"qt\");\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   uif = findall (hf, \"text\", \"&file\");\n%!   assert (ishghandle (uif));\n%!   uie = findall (hf, \"text\", \"&edit\");\n%!   assert (ishghandle (uie));\n%! unwind_protect_cleanup\n%!   close (hf);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! toolkit = graphics_toolkit (\"qt\");\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   uie = findall (hf, \"text\", \"&edit\");\n%!   myui = uimenu (uie, \"text\", \"mytext\");\n%!   assert (ancestor (myui, \"uimenu\", \"toplevel\"), uie);\n%! unwind_protect_cleanup\n%!   close (hf);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/gui/uipanel.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hui} =} uipanel ()\n## @deftypefnx {} {@var{hui} =} uipanel (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{hui} =} uipanel (@var{parent})\n## @deftypefnx {} {@var{hui} =} uipanel (@var{parent}, @var{property}, @var{value}, @dots{})\n##\n## Create a uipanel object.\n##\n## uipanels are used as containers to group other uicontrol objects.\n##\n## If @var{parent} is omitted then a uipanel for the current figure is\n## created.  If no figure is available, a new figure is created first.\n##\n## If @var{parent} is given then a uipanel relative to @var{parent} is created.\n##\n## Any provided property value pairs will override the default values of the\n## created uipanel object.\n##\n## The full list of properties is documented at @ref{Uipanel Properties}.\n##\n## The optional return value @var{hui} is a graphics handle to the created\n## uipanel object.\n##\n## Examples:\n##\n## @example\n## @group\n## ## create figure and panel on it\n## f = figure;\n## p = uipanel (\"title\", \"Panel Title\", \"position\", [.25 .25 .5 .5]);\n##\n## ## add two buttons to the panel\n## b1 = uicontrol (\"parent\", p, \"string\", \"A Button\", ...\n##                 \"position\", [18 10 150 36]);\n## b2 = uicontrol (\"parent\", p, \"string\", \"Another Button\", ...\n##                 \"position\",[18 60 150 36]);\n##\n## @end group\n## @end example\n## @seealso{figure, uicontrol}\n## @end deftypefn\n\nfunction hui = uipanel (varargin)\n\n  [h, args] = __uiobject_split_args__ (\"uipanel\", varargin,\n                                       {\"figure\", \"uipanel\", \"uibuttongroup\"});\n  htmp = __go_uipanel__ (h, args{:});\n\n  if (nargout > 0)\n    hui = htmp;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/uipushtool.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hui} =} uipushtool ()\n## @deftypefnx {} {@var{hui} =} uipushtool (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{hui} =} uipushtool (@var{parent})\n## @deftypefnx {} {@var{hui} =} uipushtool (@var{parent}, @var{property}, @var{value}, @dots{})\n##\n## Create a uipushtool object.\n##\n## uipushtools are buttons that appear on a figure toolbar.  The button is\n## created with a border that is shown when the user hovers over the button.\n## An image can be set using the cdata property.\n##\n## If @var{parent} is omitted then a uipushtool for the current figure is\n## created.  If no figure is available, a new figure is created first.  If a\n## figure is available, but does not contain a uitoolbar, a uitoolbar will be\n## created.\n##\n## If @var{parent} is given then a uipushtool is created on the @var{parent}\n## uitoolbar.\n##\n## Any provided property value pairs will override the default values of the\n## created uipushtool object.\n##\n## The full list of properties is documented at @ref{Uipushtool Properties}.\n##\n## The optional return value @var{hui} is a graphics handle to the created\n## uipushtool object.\n##\n## Examples:\n##\n## @example\n## @group\n## % create figure without a default toolbar\n## f = figure (\"toolbar\", \"none\");\n## % create empty toolbar\n## t = uitoolbar (f);\n## % create a 19x19x3 black square\n## img=zeros(19,19,3);\n## % add pushtool button to toolbar\n## b = uipushtool (t, \"cdata\", img);\n## @end group\n## @end example\n## @seealso{figure, uitoolbar, uitoggletool}\n## @end deftypefn\n\nfunction hui = uipushtool (varargin)\n\n  [h, args] = __uiobject_split_args__ (\"uipushtool\", varargin,\n                                       {\"uitoolbar\"}, 0);\n  if (isempty (h))\n    h = findobj (gcf, \"-depth\", 1, \"type\", \"uitoolbar\");\n    if (isempty (h))\n      h = uitoolbar ();\n    else\n      h = h(1);\n    endif\n  endif\n\n  htmp = __go_uipushtool__ (h, args{:});\n\n  if (nargout > 0)\n    hui = htmp;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/uiputfile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} uiputfile ()\n## @deftypefnx {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} uiputfile (@var{flt})\n## @deftypefnx {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} uiputfile (@var{flt}, @var{dialog_name})\n## @deftypefnx {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} uiputfile (@var{flt}, @var{dialog_name}, @var{default_file})\n## Open a GUI dialog for selecting a file.\n##\n## @var{flt} contains a (list of) file filter string(s) in one of the following\n## formats:\n##\n## @table @asis\n## @item @qcode{\"/path/to/filename.ext\"}\n## If a filename is given the file extension is extracted and used as filter.\n## In addition the path is selected as current path in the dialog and the\n## filename is selected as default file.  Example:\n## @code{uiputfile (\"myfcn.m\")}\n##\n## @item @qcode{\"*.ext\"}\n## A single file extension.\n## Example: @code{uiputfile (\"*.ext\")}\n##\n## @item @code{@{\"*.ext\", \"My Description\"@}}\n## A 2-column cell array containing the file extension in the 1st column and\n## a brief description in the 2nd column.  Example:\n## @code{uiputfile (@{\"*.ext\",\"My Description\";\"*.xyz\", \"XYZ-Format\"@})}\n## @end table\n##\n## The filter string can also contain a semicolon separated list of filter\n## extensions.  Example:\n## @code{uiputfile (@{\"*.gif;*.png;*.jpg\", \"Supported Picture Formats\"@})}\n##\n## @var{dialog_name} can be used to customize the dialog title.\n## If @var{default_file} is given it is preselected in the GUI dialog.\n## If, in addition, a path is given it is also used as current path.\n##\n## @var{fname} and @var{fpath} return the chosen name and path, respectively.\n## @var{fltidx} is the index in the list of filter extensions @var{flt} that\n## was selected.\n##\n## @seealso{uigetfile, uigetdir}\n## @end deftypefn\n\nfunction [retfile, retpath, retindex] = uiputfile (varargin)\n\n  if (nargin > 3)\n    print_usage ();\n  endif\n\n  ## Preset default values\n  outargs = {cell(0, 2),     # File Filter\n             \"Save File\",    # Dialog Title\n             \"\",             # Default filename\n             \"create\",\n             pwd};           # Default directory\n\n  if (nargin > 0)\n    [outargs{1}, outargs{3}, defdir] = __file_filter__ (\"uiputfile\",\n                                                        varargin{1});\n    if (! isempty (defdir))\n      outargs{5} = defdir;\n    endif\n  else\n    outargs{1} = __file_filter__ (\"uiputfile\", outargs{1});\n  endif\n\n  if (nargin > 1)\n    if (ischar (varargin{2}))\n      outargs{2} = varargin{2};\n    elseif (! isempty (varargin{2}))\n      print_usage ();\n    endif\n  endif\n\n  if (nargin > 2)\n    if (ischar (varargin{3}))\n      if (isfolder (varargin{3}))\n        fdir = varargin{3};\n        fname = fext = \"\";\n      else\n        [fdir, fname, fext] = fileparts (varargin{3});\n      endif\n      if (! isempty (fdir))\n        outargs{5} = fdir;\n      endif\n      if (! isempty (fname) || ! isempty (fext))\n        outargs{3} = [fname fext];\n      endif\n    elseif (! isempty (varargin{3}))\n      print_usage ();\n    endif\n  endif\n\n  if (__event_manager_have_dialogs__ ())\n    [retfile, retpath, retindex] = __event_manager_file_dialog__ (outargs{:});\n  else\n    funcname = __get_funcname__ (mfilename ());\n    [retfile, retpath, retindex] = feval (funcname, outargs{:});\n  endif\n\n  ## Append extension to the name if it isn't already added.\n  if (ischar (retfile))\n    [~, ~, ext] = fileparts (retfile);\n    if (isempty (ext))\n      ext = outargs{1}{retindex};\n      ext = strrep (ext, \"*\", \"\");\n      if (! strcmp (ext, '.'))\n        [~, ~, ext] = fileparts (ext);  # paranoid checking of extension\n        retfile = [retfile ext];\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! uiputfile ({'*.gif;*.png;*.jpg', 'Supported Picture Formats'});\n\n## Remove from test statistics.  No real tests possible.\n%!assert (1)\n"
  },
  {
    "path": "scripts/gui/uiresume.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} uiresume (@var{h})\n## Resume program execution suspended with @code{uiwait}.\n##\n## The handle @var{h} must be the same as the on specified in @code{uiwait}.\n## If the handle is invalid or there is no @code{uiwait} call pending for the\n## figure with handle @var{h}, this function does nothing.\n## @seealso{uiwait}\n## @end deftypefn\n\nfunction uiresume (h)\n\n  if (nargin < 1)\n    h = gcf ();\n  endif\n\n  if (! isfigure (h))\n    error (\"uiresume: invalid figure handle H\");\n  endif\n\n  try\n    uiwait_state = get (h, \"__uiwait_state__\");\n    if (strcmp (uiwait_state, \"active\"))\n      set (h, \"__uiwait_state__\", \"triggered\");\n    endif\n  catch\n    ## Ignore exception\n  end_try_catch\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/uisetfont.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} { } uisetfont ()\n## @deftypefnx {} { } uisetfont (@var{h})\n## @deftypefnx {} { } uisetfont (@var{fontstruct})\n## @deftypefnx {} { } uisetfont (@dots{}, @var{title})\n## @deftypefnx {} {@var{fontstruct} =} uisetfont (@dots{})\n## Open a font selection dialog.\n##\n## If the first argument is a handle to a text, axes, or uicontrol object,\n## pressing the OK button will change the font properties of the object.\n##\n## The first argument may also be a structure with fields @code{FontName},\n## @code{FontWeight}, @code{FontAngle}, @code{FontUnits}, and @code{FontSize},\n## indicating the initially selected font.\n##\n## The title of the dialog window can be specified by using the last argument\n## @var{title}.\n##\n## If an output argument @var{fontstruct} is requested, the selected font\n## structure is returned.  Otherwise, the font information is displayed\n## onscreen.\n##\n## Programming Note: On systems that don't use FontConfig natively (all but\n## Linux), the font cache is built when Octave is installed.  You will need to\n## run @code{system (\"fc-cache -fv\")} manually after installing new fonts.\n##\n## @seealso{listfonts, text, axes, uicontrol}\n## @end deftypefn\n\nfunction varargout = uisetfont (varargin)\n\n  persistent sysfonts = build_fontstruct ();\n  persistent fontfields = {\"FontName\", \"FontWeight\", \"FontAngle\", ...\n                           \"FontUnits\", \"FontSize\"};\n\n  do_display = true;\n  h = [];\n  fontstruct = [];\n  ttl = \"Font\";\n  nargin = numel (varargin);\n\n  ## Input checking\n  if (nargin > 2)\n    print_usage ();\n  elseif (nargin == 0)\n    ## Do nothing\n  elseif (ishghandle (varargin{1}))\n\n    h = varargin{1};\n    typ = get (h, \"type\");\n    if (! any (strcmp (typ, {\"axes\", \"text\", \"uicontrol\"})))\n      error (\"Octave:uisetfont:bad-object\",\n             \"uisetfont: H must be a handle to an axes, text, or uicontrol object\");\n    endif\n    nargin--;\n    varargin(1) = [];\n    do_display = false;\n\n  elseif (isstruct (varargin{1}))\n\n    fontstruct = varargin{1};\n    fields = fieldnames (fontstruct);\n    if (isempty (fields)\n        || ! all (cellfun (@(s) any (strcmp (s, fontfields)), fields)))\n      error (\"Octave:uisetfont:bad-fontstruct\",\n             \"uisetfont: FONTSTRUCT structure must have fields %s\",\n             strjoin (fontfields, \", \"));\n    endif\n    nargin--;\n    varargin(1) = [];\n\n  endif\n\n  ## Trailing TITLE argument\n  if (nargin == 1)\n    ttl = varargin{1};\n    if (! (ischar (ttl) && isrow (ttl)))\n      error (\"Octave:uisetfont:bad-title\",\n             \"uisetfont: TITLE must be a character vector\");\n    endif\n  elseif (nargin == 2)\n    print_usage ();\n  endif\n\n  ## Populate fontstruct\n  persistent defstruct = [];\n  if (isempty (defstruct))\n    factory_fields = strcat (\"factorytext\", lower (fontfields));\n    values = get (0, factory_fields);\n    defstruct = struct ([fontfields; values]{:});\n  endif\n\n  if (isempty (fontstruct))\n    if (isempty (h))\n      fontstruct = defstruct;\n    else\n      values = get (h, fontfields);\n      fontstruct = struct ([fontfields; values]{:});\n      names = {sysfonts.name};\n      if (! any (strcmpi (fontstruct.FontName, {sysfonts.name})))\n        warning (\"Octave:uisefont:unknown-font\",\n                 \"uisetfont: unknown font %s\", fontstruct.FontName);\n        fontstruct = defstruct;\n      endif\n    endif\n  endif\n\n  ## Sample string\n  persistent str = {\"Portez ce vieux whisky\";\n                    \"au juge blond qui fume\";\n                    \"0123456789\";\n                 ['\\alpha, \\beta, \\gamma, \\delta, \\epsilon, \\zeta, \\eta, ' ...\n                  '\\theta, \\vartheta, \\iota, \\kappa, \\lambda, \\mu, \\nu, '];\n                 ['\\xi, \\o, \\pi, \\varpi, \\rho, \\sigma, \\varsigma, \\tau, ' ...\n                  '\\upsilon, \\phi, \\chi, \\psi, \\omega']};\n\n  ## Run the dialog\n  warning (\"off\", \"Octave:missing-glyph\", \"local\");\n  warning (\"off\", \"Octave:substituted-glyph\", \"local\");\n  hf = run_fontdialog (sysfonts, h, fontstruct, ttl, str);\n\n  ## Now wait for a button to be pressed or the figure to be closed\n  uiwait (hf);\n\n  fontstruct = [];\n  if (ishghandle (hf))\n    fontstruct = getappdata (hf, \"__uisetfont_struct__\");\n    if (! isempty (h) && ! isempty (fontstruct))\n      set (h, fontstruct);\n    endif\n    close (hf);\n  endif\n\n  if (nargout > 0)\n    varargout{1} = fontstruct;\n  elseif (do_display && ! isempty (fontstruct))\n    disp (fontstruct);\n  endif\n\nendfunction\n\nfunction fonts = build_fontstruct ()\n\n  fontfiles = __get_system_fonts__ ();\n  families = unique ({fontfiles.family});\n\n  fonts(numel (families)+1) = struct (\"name\", \"\",\n                                      \"has_regular\", false,\n                                      \"has_bold\", false,\n                                      \"has_italic\", false,\n                                      \"has_bold_italic\", false);\n\n  fonts(1) = struct (\"name\", \"*\",\n                     \"has_regular\", true,\n                     \"has_bold\", true,\n                     \"has_italic\", true,\n                     \"has_bold_italic\", true);\n\n  for i = 1:numel (families)\n    ii = i + 1;\n    fonts(ii).name = families{i};\n    idx = strcmp ({fontfiles.family}, families{i});\n\n    isbold = strcmp ({fontfiles(idx).weight}, \"bold\");\n    isitalic = strcmp ({fontfiles(idx).angle}, \"italic\");\n\n    fonts(ii).has_regular = any (! isbold & ! isitalic);\n    fonts(ii).has_bold = any (isbold & ! isitalic);\n    fonts(ii).has_italic = any (isitalic & ! isbold);\n    fonts(ii).has_bold_italic = any (isbold & isitalic);\n  endfor\n\nendfunction\n\nfunction hf = run_fontdialog (sysfonts, hobj, fontstruct, ttl, str)\n\n  [hf, hok, hcancel, hp] = __ok_cancel_dlg__ (ttl,\n                                              \"position\", [200 200 400 400],\n                                              \"windowstyle\", \"modal\",\n                                              \"resize\", \"on\");\n\n  ## List controls\n  htmp = uipanel (hp, \"title\", \"Font Name\",\n                      \"units\", \"normalized\", \"position\", [0.04 0.35 0.5 0.6]);\n  hnames = uicontrol (htmp, \"style\", \"listbox\", \"string\", {sysfonts.name},\n                            \"units\", \"normalized\",\n                            \"position\", [0.02 0.01 0.96 .95]);\n\n  htmp = uipanel (hp, \"title\", \"Style\",\n                      \"units\", \"normalized\", \"position\", [0.56 0.35 0.25 0.6]);\n  hstyle = uicontrol (htmp, \"style\", \"listbox\",\n                      \"units\", \"normalized\",\n                      \"position\", [0.02 0.01 0.96 .95]);\n\n  htmp = uipanel (hp, \"title\", \"Size\",\n                      \"units\", \"normalized\", \"position\", [0.83 0.35 0.13 0.6]);\n  hsize = uicontrol (htmp, \"style\", \"listbox\",\n                           \"string\", arrayfun (@num2str, (8:30), \"uni\", false),\n                           \"units\", \"normalized\",\n                           \"position\", [0.02 0.01 0.96 .95]);\n\n  fcn = @(h) set (hstyle, \"string\",\n                          getstylestring (sysfonts(get (h, \"value\"))));\n  set (hnames, \"callback\", fcn);\n\n  ## Axes to display samples\n  htmp = uipanel (hp, \"title\", \"Sample\",\n                      \"units\", \"normalized\", \"position\", [0.04 0 0.92 0.33]);\n  hax = axes (\"parent\", htmp, \"visible\", \"off\", \"units\", \"normalized\",\n              \"position\", [0 0 1 0.95], \"xlim\", [0 1], \"ylim\", [0 1]);\n  ht = text (hax, 0.5, 0.5, str, \"horizontalalignment\", \"center\");\n\n  hlists = [hnames, hstyle, hsize];\n\n  ## Update text and uicontrol objects according to the input fontstruct\n  struct_to_lists (fontstruct, sysfonts, hlists);\n  set (ht, fontstruct);\n\n  ## Setup callbacks\n  set (hlists, \"callback\", {@cb_list_value_changed, hlists, ht, sysfonts});\n\n  set (hok, \"callback\", {@cb_button, hlists, \"ok\"});\n  set (hcancel, \"callback\", {@cb_button, hlists, \"cancel\"});\n\n  ## Give focus to the OK button\n  uicontrol (hok);\n\nendfunction\n\nfunction str = getstylestring (fontitem)\n\n  styles = {\"Plain\", \"Bold\", \"Italic\", \"Bold Italic\"};\n  if (fontitem.has_bold_italic)\n    str = styles;\n  elseif (fontitem.has_bold && fontitem.has_italic)\n    str = styles(1:3);\n  elseif (fontitem.has_bold)\n    str = styles(1:2);\n  elseif (fontitem.has_italic)\n    str = styles(1:2:3);\n  else\n    str = styles{1};\n  endif\n\nendfunction\n\nfunction fontstruct = struct_from_lists (hlists)\n\n  name = get (hlists(1), \"string\");\n  if (iscell (name))\n    name = name{get(hlists(1), \"value\")};\n  endif\n\n  szstr = get (hlists(3), \"string\");\n  sz = str2num (szstr{get(hlists(3), \"value\")});\n\n  fontstruct = struct (\"FontName\", name, \"FontWeight\", \"normal\",\n                       \"FontAngle\", \"normal\", \"FontUnits\", \"points\",\n                       \"FontSize\", sz);\n\n  style = get (hlists(2), \"string\");\n  if (iscell (style))\n    style = style{get(hlists(2), \"value\")};\n  endif\n\n  if (strcmp (style, \"Bold\"))\n    fontstruct.FontWeight = \"bold\";\n  elseif (strcmp (style, \"Bold Italic\"))\n    fontstruct.FontWeight = \"bold\";\n    fontstruct.FontAngle = \"italic\";\n  elseif (strcmp (style, \"Italic\"))\n    fontstruct.FontAngle = \"italic\";\n  endif\n\nendfunction\n\nfunction struct_to_lists (fontstruct, sysfonts, hlists)\n\n  ## Match font name\n  names = get (hlists(1), \"string\");\n  idx = find (strcmpi (fontstruct.FontName, names));\n  if (isempty (idx))\n    idx = 1;\n  endif\n  set (hlists(1), \"value\", idx);\n  styles = getstylestring (sysfonts(idx));\n  set (hlists(2), \"string\", styles);\n\n  ## Match style\n  style = \"Plain\";\n  if (strcmp (fontstruct.FontWeight, \"bold\")\n      && strcmp (fontstruct.FontAngle, \"italic\"))\n    style = \"Bold Italic\";\n  elseif (strcmp (fontstruct.FontWeight, \"bold\"))\n    style = \"Bold\";\n  elseif (strcmp (fontstruct.FontAngle, \"italic\"))\n    style = \"Italic\";\n  endif\n\n  idx = find (strcmpi (style, styles));\n  if (isempty (idx))\n    idx = 1;\n  endif\n  set (hlists(2), \"value\", idx);\n\n  ## Match size\n  szs = (8:30);\n  idx = find (round (fontstruct.FontSize) == szs);\n  if (isempty (idx))\n    idx = 1;\n  endif\n  set (hlists(3), \"value\", idx);\n\nendfunction\n\nfunction cb_button (h, ~, hlists, role)\n\n  fontstruct = [];\n  if (strcmp (role, \"ok\"))\n    fontstruct = struct_from_lists (hlists);\n  endif\n\n  setappdata (gcbf (), \"__uisetfont_struct__\", fontstruct);\n  uiresume (gcbf ());\n\nendfunction\n\nfunction cb_list_value_changed (h, ~, hlists, htext, sysfonts)\n\n  if (h == hlists(1))\n    set (hlists(2), \"string\", getstylestring (sysfonts(get (h, \"value\"))),\n                    \"value\", 1);\n  endif\n  fontstruct = struct_from_lists (hlists);\n  set (htext, fontstruct);\n\nendfunction\n\n\n## Test input validation\n%!testif HAVE_FONTCONFIG\n%! fail (\"uisetfont (1, 2, 3)\", \"Invalid call\");\n%!testif HAVE_FONTCONFIG\n%! fail (\"uisetfont (110, struct ())\", \"Invalid call\");\n%!testif HAVE_FONTCONFIG\n%! fail (\"uisetfont (groot ())\", \"H must be a handle to an axes\");\n%!testif HAVE_FONTCONFIG\n%! fail (\"uisetfont (struct ())\", \"FONTSTRUCT .* must have fields FontName,.*\");\n%!testif HAVE_FONTCONFIG\n%! fail (\"uisetfont ({'Title'})\", \"TITLE must be a character vector\");\n"
  },
  {
    "path": "scripts/gui/uitable.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hui} =} uitable (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{hui} =} uitable (@var{parent}, @var{property}, @var{value}, @dots{})\n## Create a uitable object and return a handle to it.\n##\n## A uitable object is used to show tables of data in a figure window.\n##\n## If @var{parent} is omitted then a uitable for the current figure is\n## created.  If no figure is available, a new figure is created first.\n##\n## If @var{parent} is given then a uitable relative to @var{parent} is\n## created.\n##\n## Any provided property value pairs will override the default values of the\n## created uitable object.\n##\n## The full list of properties is documented at @ref{Uitable Properties}.\n##\n## Examples:\n##\n## @smallexample\n## @group\n## ## Create figure and place a table on it\n## f = figure ();\n## m = magic (8);\n## t = uitable (f, \"Data\", m, \"ColumnWidth\", @{ 40 @});\n## @end group\n##\n## @group\n## ## Create a table with labeled rows and columns\n## f = figure ();\n## d = reshape (1:9, [3, 3]);\n## row_names = @{ \"Row1\", \"Row2\", \"Row3\" @};\n## col_names = @{ \"Col1\", \"Col2\", \"Col3\" @};\n## t = uitable (f, \"Data\", d, ...\n##              \"RowName\", row_names, \"ColumnName\", col_names);\n##\n## p = get (t, \"Position\");\n## e = get (t, \"Extent\");\n## p(3:4) = e(3:4);\n## set (t, \"Position\", p);\n## @end group\n##\n## ## Long demo with callbacks\n## function uitable_demo ()\n##   f = figure (\"Name\", \"uitable Demo\", \"Menu\", \"none\", ...\n##               \"Position\", [10 10 1000 680]);\n##\n##   ## A basic example\n##   d = @{ \"char\"   , \"A string\";\n##         \"double\" , 12.3456789;\n##         \"complex\", 1+2i;\n##         \"bool\"   , true;\n##         \"single\" , single(12.3456789);\n##         \"int8\"   , int8(-128);\n##         \"uint8\"  , uint8(128);\n##         \"int16\"  , int16(-32768);\n##         \"uint16\" , uint16(32768);\n##         \"int32\"  , int32(-2147483648);\n##         \"uint32\" , uint32(2147483648);\n##         \"int64\"  , int64(-2147483649);\n##         \"uint64\" , uint64(2147843649)@};\n##\n##   popup_options = @{\"A\", \"B\", \"C\", \"D\", \"E\"@};\n##\n##   columnformat_options = @{ \"[]\", \"char\", \"pop-up\", \"numeric\", ...\n##                            \"short\", \"short e\", \"short eng\", ...\n##                            \"short g\", \"long\", \"long e\", ...\n##                            \"long eng\", \"long g\", \"bank\", \"+\", ...\n##                            \"rat\", \"logical\"@};\n##   columnformat_values = columnformat_options;\n##   columnformat_values@{1@} = \"\";\n##   columnformat_values@{3@} = popup_options;\n##\n##   default_data = repmat (d(:,2), 1, columns (columnformat_options));\n##   b_add = uicontrol (f, \"Position\", [285 630 600 50], ...\n##             \"UserData\", [rows(d), 1], ...\n##             \"Style\", \"pushbutton\", ...\n##             \"String\", \"Set data at selected point to selected datatype\");\n##\n##   l_type_table = uicontrol (f, \"Position\", [ 0 603 120 25 ], ...\n##       \"String\", \"Datatype Table:\", ...\n##       \"Style\", \"text\");\n##   t_type_table = uitable (f, \"Position\", [ 0 530 1000 70 ], ...\n##       \"Data\", transpose (d(:, 2)), ...\n##       \"ColumnName\", transpose (d(:, 1)), ...\n##       \"RowName\", \"Value\", ...\n##       \"CellSelectionCallback\", ...\n##            @@(x, y) set (b_add, \"UserData\", y.Indices ));\n##\n##   l_point_table = uicontrol (f, \"Position\", [ 0 640 60 25 ], ...\n##       \"String\", \"Point:\", ...\n##       \"Style\", \"text\");\n##   t_point_table = uitable (f, \"Position\", [ 80 630 160 42 ], ...\n##       \"RowName\", [], ...\n##       \"ColumnName\", @{\"x\", \"y\"@}, ...\n##       \"Data\", [ 1, 1 ], ...\n##       \"ColumnEditable\", true);\n##\n##   l_editable_table = uicontrol (f, \"Position\", [ 0 502 200 25 ], ...\n##       \"Style\", \"text\", ...\n##       \"String\", \"Set Data Columns Editable:\");\n##   t_editable_table = ...\n##     uitable (f, \"Position\", [ 0 434 1000 65 ], ...\n##                 \"Data\", repmat (false, 1, columns (default_data)), ...\n##                 \"ColumnEditable\", true);\n##\n##   l_format_table = uicontrol (f, \"Position\", [ 0 406 200 25 ], ...\n##       \"Style\", \"text\", ...\n##       \"String\", \"Set Data Column Format:\");\n##   t_format_table = ...\n##     uitable (f, \"Position\", [ 0 338 1000 65 ], ...\n##                 \"Data\", columnformat_options, ...\n##                 \"ColumnEditable\", true, ...\n##                 \"ColumnFormat\", arrayfun (@@(x) @{columnformat_options@}, ...\n##                                           1:columns (columnformat_options)));\n##\n##   l_data_table = uicontrol (f, \"Style\", \"text\", ...\n##                                \"String\", \"Data:\", ...\n##                                \"Position\", [ 0 310 60 25 ]);\n##   t_data_table = uitable (f, \"Position\", [ 0 15 1000 290 ], ...\n##       \"Data\", default_data, ...\n##       \"ColumnFormat\", columnformat_values);\n##\n##   set (t_format_table, ...\n##        \"CellEditCallback\", ...\n##        @@(x, y) update_column_format (y.NewData, y.Indices, ...\n##                                       t_data_table, popup_options));\n##   set (t_point_table, \"CellEditCallback\", ...\n##        @@(x, y) validate_point_table (x, y, t_data_table));\n##   set (t_editable_table, \"CellEditCallback\", ...\n##        @@(x,y) set (t_data_table, ...\n##                     \"ColumnEditable\", get (t_editable_table, \"Data\")));\n##   set (b_add, ...\n##        \"Callback\", @@(x, y) update_data (b_add, t_point_table, ...\n##                                          t_type_table, t_data_table));\n##   set (t_data_table, \"CellSelectionCallback\", ...\n##        @@(x, y) update_point_table (y.Indices, t_point_table));\n## endfunction\n##\n## @group\n## function validate_point_table (h, dat, t_data_table)\n##   if (! (dat.NewData > 0 && ...\n##     dat.NewData < size (get (t_data_table, \"Data\"), dat.Indices(1, 1)) + 1))\n##\n##     d = get (h, \"Data\");\n##     d(dat.Indices) = 1;\n##     set (h, \"Data\", d);\n##   endif\n## endfunction\n## @end group\n##\n## @group\n## function update_column_format (format, indices, t_data_table, ...\n##                                popup_options)\n##   cf = get (t_data_table, \"ColumnFormat\");\n##   if (strcmp (format, \"[]\"))\n##     format = \"\";\n##   elseif (strcmp (format, \"pop-up\"))\n##     format = popup_options;\n##   endif\n##   cf@{indices(1,2)@} = format;\n##   set (t_data_table, \"ColumnFormat\", cf);\n## endfunction\n## @end group\n##\n## @group\n## function update_point_table (indices, t_point_table)\n##   if (isempty (indices))\n##     indices = [1, 1];\n##   endif\n##   set (t_point_table, \"Data\", indices(1,:));\n## endfunction\n## @end group\n##\n## @group\n## function update_data (b_add, t_point_table, t_type_table, ...\n##                       t_data_table)\n##   indices = get (b_add, \"UserData\");\n##   if (isempty (indices))\n##     indices = [1, 1];\n##   endif\n##   d = get (t_data_table, \"Data\");\n##   t_type_table_data = get (t_type_table, \"Data\");\n##   p = get (t_point_table, \"Data\");\n##   d(p(1,2), p(1,1)) = t_type_table_data(indices(1,2));\n##   set (t_data_table, \"Data\", d);\n## endfunction\n## @end group\n## @end smallexample\n##\n## @seealso{figure, uicontrol}\n## @end deftypefn\n\nfunction hui = uitable (varargin)\n\n  [h, args] = __uiobject_split_args__ (\"uitable\", varargin, ...\n                                       {\"figure\", \"uipanel\", \"uibuttongroup\"});\n  htmp = __go_uitable__ (h, args{:});\n\n  if (nargout > 0)\n    hui = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Create figure and place a table on it\n%! f = clf ();\n%! m = magic (8);\n%! t = uitable (f, \"Data\", m, \"ColumnWidth\", {50}, ...\n%!              \"Units\", \"normalized\", \"Position\", [0.1 0.1 0.8 0.8]);\n\n%!demo\n%! ## Create figure and place an editable table on it\n%! f = clf ();\n%! m = magic (8);\n%! t = uitable (f, \"Data\", m, \"ColumnWidth\", {50}, \"ColumnEditable\", true, ...\n%!              \"Units\", \"normalized\", \"Position\", [0.1 0.1 0.8 0.8]);\n\n%!demo\n%! ## Create figure and table, but change the format to rational_approx\n%! f = clf ();\n%! m = magic (8) / 64;\n%! t = uitable (f, \"Data\", m, \"ColumnWidth\", {50}, ...\n%!              \"ColumnFormat\", repmat ({\"rat\"}, 1, 8), ...\n%!              \"Units\", \"normalized\", \"Position\", [0.1 0.1 0.8 0.8]);\n\n%!demo\n%! cf = {\"char\", \"char\", {\"A\", \"B\", \"C\"}, \"numeric\", \"short\", \"short e\", ...\n%!      \"short eng\", \"short g\", \"long\", \"long e\", \"long eng\", \"long g\", ...\n%!      \"bank\", \"+\", \"rat\", \"logical\"};\n%! cn = cf;\n%! cn{1} = \"type\";\n%! cn{3} = \"pop-up\";\n%!\n%! d = {\"double\", 0.0000123456789;\n%!      \"double\", 0.000123456789;\n%!      \"double\", 0.00123456789;\n%!      \"double\", 0.0123456789;\n%!      \"double\", 0.123456789;\n%!      \"double\", 12;\n%!      \"double\", 1.23456789;\n%!      \"double\", 12.3456789;\n%!      \"double\", 123.456789;\n%!      \"double\", 1234.56789;\n%!      \"complex\", 0.0000123456789 + 12.3456789i;\n%!      \"complex\", 0.000123456789 + 12.3456789i;\n%!      \"complex\", 0.00123456789 + 12.3456789i;\n%!      \"complex\", 0.0123456789 + 12.3456789i;\n%!      \"complex\", 0.123456789 + 12.3456789i;\n%!      \"complex\", 1.23456789 + 12.3456789i;\n%!      \"complex\", 12.3456789 + 12.3456789i;\n%!      \"complex\", 123.456789 + 12.3456789i;\n%!      \"complex\", 1234.56789 + 12.3456789i;\n%!      \"bool\", true;\n%!      \"bool\", false;\n%!      \"single\", single(0.0000123456789);\n%!      \"single\", single(1.23456789);\n%!      \"single\", single(1234.56789);\n%!      \"int8\", int8(127);\n%!      \"int8\", int8(0);\n%!      \"int8\", int8(-126);\n%!      \"int16\", int16(32767);\n%!      \"int16\", int16(0);\n%!      \"int16\", int16(-32768);\n%!      \"int32\", int32(2147483647);\n%!      \"int32\", int32(0);\n%!      \"int32\", int32(-2147483647);\n%!      \"int64\", int64(9223372036854775807);\n%!      \"int64\", int64(0);\n%!      \"int64\", int64(-9223372036854775807);\n%!      \"uint8\", uint8(127);\n%!      \"uint8\", uint8(0);\n%!      \"uint8\", uint8(255);\n%!      \"uint16\", uint16(32767);\n%!      \"uint16\", uint16(0);\n%!      \"uint16\", uint16(65535);\n%!      \"uint32\", uint32(2147483647);\n%!      \"uint32\", uint32(0);\n%!      \"uint32\", uint32(4294967295);\n%!      \"uint64\", uint64(9223372036854775807);\n%!      \"uint64\", uint64(0);\n%!      \"uint64\", uint64(18446744073709551615);\n%!      \"char\", \"a string\"};\n%!\n%! ws = {\"auto\", 140};\n%! widths = cell (1, columns (cf));\n%! widths(1,1) = ws(1,1);\n%! widths(1,2:end) = repmat (ws(:,2), [1, columns(cf) - 1]);\n%!\n%! data = cell (rows (d), columns (cf));\n%!\n%! data(:,1) = d(:,1);\n%!\n%! data(:, 2:end) = repmat (d(:,2), [1, columns(cf) - 1]);\n%!\n%! t = uitable (\"Data\", data,\n%!              \"ColumnFormat\", cf,\n%!              \"ColumnWidth\", widths,\n%!              \"ColumnName\", cn,\n%!              \"ColumnEditable\", true,\n%!              \"Units\", \"Normalized\",\n%!              \"Position\", [0 0 1 1]);\n"
  },
  {
    "path": "scripts/gui/uitoggletool.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hui} =} uitoggletool ()\n## @deftypefnx {} {@var{hui} =} uitoggletool (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{hui} =} uitoggletool (@var{parent})\n## @deftypefnx {} {@var{hui} =} uitoggletool (@var{parent}, @var{property}, @var{value}, @dots{})\n##\n## Create a uitoggletool object.\n##\n## uitoggletool are togglebuttons that appear on a figure toolbar.  The\n## button is created with a border that is shown when the user hovers over\n## the button.  An image can be set using the cdata property.\n##\n## If @var{parent} is omitted then a uitoggletool for the current figure is\n## created.  If no figure is available, a new figure is created first.  If a\n## figure is available, but does not contain a uitoolbar, a uitoolbar will be\n## created.\n##\n## If @var{parent} is given then a uitoggletool is created on the\n## @var{parent} uitoolbar.\n##\n## Any provided property value pairs will override the default values of the\n## created uitoggletool object.\n##\n## The full list of properties is documented at @ref{Uitoggletool Properties}.\n##\n## The optional return value @var{hui} is a graphics handle to the created\n## uitoggletool object.\n##\n## Examples:\n##\n## @example\n## @group\n## % create figure without a default toolbar\n## f = figure (\"toolbar\", \"none\");\n## % create empty toolbar\n## t = uitoolbar (f);\n## % create a 19x19x3 black square\n## img=zeros(19,19,3);\n## % add uitoggletool button to toolbar\n## b = uitoggletool (t, \"cdata\", img);\n## @end group\n## @end example\n## @seealso{figure, uitoolbar, uipushtool}\n## @end deftypefn\n\nfunction hui = uitoggletool (varargin)\n\n  [h, args] = __uiobject_split_args__ (\"uitoggletool\", varargin,\n                                       {\"uitoolbar\"}, 0);\n  if (isempty (h))\n    h = findobj (gcf, \"-depth\", 1, \"type\", \"uitoolbar\");\n    if (isempty (h))\n      h = uitoolbar ();\n    else\n      h = h(1);\n    endif\n  endif\n\n  htmp = __go_uitoggletool__ (h, args{:});\n\n  if (nargout > 0)\n    hui = htmp;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/uitoolbar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hui} =} uitoolbar ()\n## @deftypefnx {} {@var{hui} =} uitoolbar (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{hui} =} uitoolbar (@var{parent})\n## @deftypefnx {} {@var{hui} =} uitoolbar (@var{parent}, @var{property}, @var{value}, @dots{})\n##\n## Create a uitoolbar object.  A uitoolbar displays uitoggletool and uipushtool\n## buttons.\n##\n## If @var{parent} is omitted then a uitoolbar for the current figure is\n## created.  If no figure is available, a new figure is created first.\n##\n## If @var{parent} is given then a uitoolbar relative to @var{parent} is\n## created.\n##\n## Any provided property value pairs will override the default values of the\n## created uitoolbar object.\n##\n## The full list of properties is documented at @ref{Uitoolbar Properties}.\n##\n## The optional return value @var{hui} is a graphics handle to the created\n## uitoolbar object.\n##\n## Examples:\n##\n## @example\n## @group\n## % create figure without a default toolbar\n## f = figure (\"toolbar\", \"none\");\n## % create empty toolbar\n## t = uitoolbar (f);\n## @end group\n## @end example\n## @seealso{figure, uitoggletool, uipushtool}\n## @end deftypefn\n\nfunction hui = uitoolbar (varargin)\n\n  [h, args] = __uiobject_split_args__ (\"uitoolbar\", varargin, {\"figure\"});\n\n  htmp = __go_uitoolbar__ (h, args{:});\n\n  if (nargout > 0)\n    hui = htmp;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/uiwait.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} uiwait\n## @deftypefnx {} {} uiwait (@var{h})\n## @deftypefnx {} {} uiwait (@var{h}, @var{timeout})\n## Suspend program execution until the figure with handle @var{h} is deleted\n## or @code{uiresume} is called.\n##\n## When no figure handle is specified this function uses the current figure.\n## If the figure handle is invalid or there is no current figure, this\n## functions returns immediately.\n##\n## When specified, @var{timeout} defines the number of seconds to wait\n## for the figure deletion or the @code{uiresume} call.  The timeout value\n## must be at least 1.  If a smaller value is specified, a warning is issued\n## and a timeout value of 1 is used instead.  If a non-integer value is\n## specified, it is truncated towards 0.  If @var{timeout} is not specified,\n## the program execution is suspended indefinitely.\n## @seealso{uiresume, waitfor}\n## @end deftypefn\n\nfunction uiwait (varargin)\n\n  h = [];\n  timeout = [];\n\n  if (nargin == 0)\n    h = get (0, \"currentfigure\");\n  else\n    h = varargin{1};\n    if (! isfigure (h))\n      error (\"uiwait: invalid figure handle H\");\n    endif\n    if (nargin > 1)\n      timeout = varargin{2};\n    endif\n  endif\n\n  if (! isempty (h))\n    unwind_protect\n      try\n        addproperty (\"__uiwait_state__\", h, \"radio\", \"none|{active}|triggered\");\n      catch\n        if (! strcmp (get (h, \"__uiwait_state__\"), \"none\"))\n          error (\"uiwait: an active uiwait call for this figure already exists\");\n        endif\n        set (h, \"__uiwait_state__\", \"active\");\n      end_try_catch\n      waitfor_args = {h, \"__uiwait_state__\", \"triggered\"};\n      if (! isempty (timeout))\n        waitfor_args(end+1:end+2) = {\"timeout\", timeout};\n      endif\n      waitfor (waitfor_args{:});\n    unwind_protect_cleanup\n      if (ishghandle (h) && isprop (h, \"__uiwait_state__\"))\n        set (h, \"__uiwait_state__\", \"none\");\n      endif\n    end_unwind_protect\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/waitbar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} waitbar (@var{frac})\n## @deftypefnx {} {@var{h} =} waitbar (@var{frac}, @var{msg})\n## @deftypefnx {} {@var{h} =} waitbar (@dots{}, \"createcancelbtn\", @var{fcn}, @dots{})\n## @deftypefnx {} {@var{h} =} waitbar (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} waitbar (@var{frac})\n## @deftypefnx {} {} waitbar (@var{frac}, @var{h})\n## @deftypefnx {} {} waitbar (@var{frac}, @var{h}, @var{msg})\n## Return a handle @var{h} to a new progress indicator (\"waitbar\") object.\n##\n## The waitbar is filled to fraction @var{frac} which must be in the range\n## [0, 1].\n##\n## The optional message @var{msg} is centered and displayed above the waitbar.\n##\n## A cancel button can be added to the bottom of the waitbar using the\n## @qcode{\"createcancelbtn\"} property of waitbar figures.  The action to be\n## executed when the user presses the button is specified using a string or\n## function handle @var{fcn}.\n##\n## The appearance of the waitbar figure window can be configured by passing\n## @var{prop}/@var{val} pairs to the function.  The full list of properties is\n## documented at @ref{Figure Properties}.\n##\n## When called with a single input the current waitbar, if it exists, is\n## updated to the new value @var{frac}.  If there are multiple outstanding\n## waitbars they can be updated individually by passing the handle @var{h}\n## of the specific waitbar to modify.\n##\n## @seealso{delete}\n## @end deftypefn\n\nfunction h = waitbar (varargin)\n\n  persistent curr_waitbar;\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  frac = varargin{1};\n  varargin(1) = [];\n\n  if (! (isnumeric (frac) && isscalar (frac) && frac >= 0 && frac <= 1))\n    error (\"waitbar: FRAC must be between 0 and 1\");\n  endif\n\n  ## Use existing waitbar if it still points to a valid graphics handle.\n  if (nargin == 1 && ishghandle (curr_waitbar))\n    hf = curr_waitbar;\n  else\n    hf = false;\n  endif\n\n  if (! isempty (varargin) && isnumeric (varargin{1}))\n    hf = varargin{1};\n    varargin(1) = [];\n    if (! isfigure (hf) || ! strcmp (get (hf, \"tag\"), \"waitbar\"))\n      error (\"waitbar: H must be a handle to a waitbar object\");\n    endif\n  endif\n\n  msg = false;\n\n  if (! isempty (varargin))\n    msg = varargin{1};\n    varargin(1) = [];\n    if (! (ischar (msg) || iscellstr (msg)))\n      error (\"waitbar: MSG must be a character string or cell array of strings\");\n    endif\n  endif\n\n  if (rem (numel (varargin), 2) != 0)\n    error (\"waitbar: invalid number of property/value pairs\");\n  endif\n\n  if (hf)\n    gd = get (hf, \"__guidata__\");\n    ## Get the cached handles.\n    ax = gd(1);\n    hp = gd(2);\n\n    set (hp, \"xdata\", [0; frac; frac; 0]);\n\n    if (ischar (msg) || iscellstr (msg))\n      th = get (ax, \"title\");\n      curr_msg = get (th, \"string\");\n      ## graphics handles always store data as column vectors\n      if (iscellstr (msg))\n        msg = msg(:);\n      endif\n      cmp = strcmp (msg, curr_msg);\n      if (! all (cmp(:)))\n        set (th, \"string\", msg);\n      endif\n    endif\n  else\n    ## Save and restore current figure\n    cf = get (0, \"currentfigure\");\n\n    hf = figure (\"units\", \"pixels\",\n                 \"position\", [250, 500, 400, 100],\n                 \"numbertitle\", \"off\",\n                 \"menubar\", \"none\", \"toolbar\", \"none\",\n                 \"integerhandle\", \"off\",\n                 \"handlevisibility\", \"callback\",\n                 \"tag\", \"waitbar\");\n\n    ax = axes (\"parent\", hf,\n               \"xtick\", [], \"ytick\", [],\n               \"xlim\", [0, 1], \"ylim\", [0, 1],\n               \"position\", [0.1, 0.3, 0.8, 0.2]);\n\n    ## Add createcancelbtn property\n    addproperty (\"createcancelbtn\", hf, \"figurebuttondownfcn\");\n    ## FIXME: Can't add listener because of bug #55963.\n    ## addlistener (hf, \"createcancelbtn\", {@updatecancelbutton, ax});\n\n    if (! isempty (varargin))\n      set (hf, varargin{:});\n    endif\n\n    ## Add listener and create cancel button only after setting properties\n    ## which could change \"createcancelbtn\" property (bug #55963).\n    addlistener (hf, \"createcancelbtn\", {@updatecancelbutton, ax});\n    if (any (strcmp (\"createcancelbtn\", varargin)))\n      updatecancelbutton (hf, [], ax);\n    endif\n\n    hp = patch (ax, [0; frac; frac; 0], [0; 0; 1; 1], [0, 0.35, 0.75]);\n\n    ## Cache the axes and patch handles.\n    set (hf, \"__guidata__\", [ax, hp]);\n\n    if (! (ischar (msg) || iscellstr (msg)))\n      msg = \"Please wait...\";\n    endif\n    title (ax, msg);\n\n    set (0, \"currentfigure\", cf);\n  endif\n\n  drawnow ();\n\n  if (nargout > 0)\n    h = hf;\n  endif\n\n  ## If there were no errors, update current waitbar.\n  curr_waitbar = hf;\n\nendfunction\n\nfunction updatecancelbutton (hf, ~, hax)\n\n  if (! strcmp (get (hf, \"__graphics_toolkit__\"), \"qt\"))\n    return;\n  endif\n\n  hbtn = findobj (hf, \"type\", \"uicontrol\", \"-and\", \"style\", \"pushbutton\");\n  cb = get (hf, \"createcancelbtn\");\n  if (! isempty (cb))\n    if (isempty (hbtn))\n      units = get (hax, \"units\");\n      fpos = get (hf, \"position\");\n      set (hax, \"units\", \"pixels\");\n      apos = get (hax, \"position\");\n\n      fpos(2) -= 40;\n      fpos(4) += 40;\n      apos(2) += 40;\n      set (hf, \"position\", fpos);\n      set (hax, \"position\", apos, \"units\", units);\n\n      hbtn = uicontrol (hf, \"style\", \"pushbutton\", \"string\", \"Cancel\", ...\n                            \"position\", [fpos(3)-100, 10, 60, 25], ...\n                            \"callback\", cb);\n    else\n      set (hbtn, \"callback\", cb);\n    endif\n  elseif (! isempty (hbtn))\n    delete (hbtn);\n    units = get (hax, \"units\");\n    fpos = get (hf, \"position\");\n    set (hax, \"units\", \"pixels\");\n    apos = get (hax, \"position\");\n\n    fpos(2) += 40;\n    fpos(4) -= 40;\n    apos(2) -= 40;\n    set (hf, \"position\", fpos);\n    set (hax, \"position\", apos, \"units\", units);\n  endif\n\nendfunction\n\n\n%!demo\n%! h = waitbar (0, '0.00%');\n%! for i = 0:0.01:1\n%!   waitbar (i, h, sprintf ('%.2f%%', 100*i));\n%!   if (strcmp (graphics_toolkit (), \"qt\"))\n%!     pause (0.01);\n%!   endif\n%! endfor\n%! close (h);\n\n%!demo\n%! h = waitbar (0, 'please wait...');\n%! for i = 0:0.01:0.6\n%!   waitbar (i);\n%!   if (strcmp (graphics_toolkit (), \"qt\"))\n%!     pause (0.01);\n%!   endif\n%! endfor\n%! i = 0.3;\n%! waitbar (i, h, 'don''t you hate taking a step backward?');\n%! pause (0.5);\n%! for i = i:0.005:0.7\n%!   waitbar (i, h);\n%!   if (strcmp (graphics_toolkit (), \"qt\"))\n%!     pause (0.01);\n%!   endif\n%! endfor\n%! waitbar (i, h, 'or stalling?');\n%! pause (1);\n%! for i = i:0.003:0.85\n%!   waitbar (i, h, 'just a little longer now');\n%!   if (strcmp (graphics_toolkit (), \"qt\"))\n%!     pause (0.01);\n%!   endif\n%! endfor\n%! for i = i:0.001:1\n%!   waitbar (i, h, 'please don''t be impatient');\n%!   if (strcmp (graphics_toolkit (), \"qt\"))\n%!     pause (0.01);\n%!   endif\n%! endfor\n%! close (h);\n\n%!demo\n%! h1 = waitbar (0, 'Waitbar #1');\n%! h2 = waitbar (0, 'Waitbar #2');\n%! h2pos = get (h2, 'position');\n%! h2pos(1) = h2pos(1) + (h2pos(3) + 50);\n%! set (h2, 'position', h2pos);\n%! pause (0.5);\n%! for i = 1:4\n%!   waitbar (i/4, h1);\n%!   pause (0.5);\n%!   waitbar (i/4, h2);\n%!   pause (0.5);\n%! endfor\n%! pause (0.5);\n%! close (h1);\n%! close (h2);\n\n%!demo\n%! clf ();\n%! niter = 7;\n%! l = 1;\n%! xx = [0 l];\n%! yy = [0 0];\n%! hli = plot (xx, yy);\n%! pos1 = get (gcf, \"position\");\n%!\n%! disp (\"Push the <cancel> button to stop the process.\");\n%! hf = waitbar (0,\"0\",\"Name\",\"Building Koch curve ...\",...\n%!               \"createcancelbtn\", \"setappdata (gcbf,'interrupt', true)\");\n%!\n%! pos2 = get (hf, \"position\");\n%! set (hf, \"position\", [pos1(1)+(pos1(3)-pos2(3))/2, pos1(2)+pos1(4), pos2(3:4)]);\n%!\n%! for ii = 1:niter\n%!   ## Check cancel request\n%!   if (! ishghandle (hf))\n%!     break;\n%!   elseif (getappdata (hf, \"interrupt\"))\n%!     delete (hf);\n%!     break;\n%!   else\n%!     waitbar (ii/niter, hf, sprintf (\"Step %d/%d\", ii, niter));\n%!   endif\n%!\n%!   ## Increasingly lengthy computation\n%!   l /= 3;\n%!   theta = angle (complex (diff (xx), diff (yy)));\n%!\n%!   xy = @(th, x0, y0) [cos(th) -sin(th) x0\n%!                       sin(th) cos(th) y0] * [0 l l*3/2      2*l;\n%!                                              0 0 l*(3)^.5/2 0;\n%!                                              1 1 1          1];\n%!   tmp = arrayfun (xy, theta, xx(1:end-1), yy(1:end-1),\n%!                   \"uniformoutput\", false);\n%!\n%!   tmp = cell2mat (tmp);\n%!   xx = [tmp(1,:) xx(end)];\n%!   yy = [tmp(2,:) yy(end)];\n%!   set (hli, \"xdata\", xx, \"ydata\", yy);\n%!   drawnow ();\n%!   pause (0.75);\n%! endfor\n%!\n%! if (ishghandle (hf))\n%!   delete (hf);\n%! endif\n\n## Test input validation\n%!error <FRAC must be between 0 and 1> waitbar (-0.5)\n%!error <FRAC must be between 0 and 1> waitbar (1.5)\n%!error <MSG must be a character string> waitbar (0.5, struct ())\n%!error <invalid number of property/value pairs> waitbar (0.5, \"msg\", \"Name\")\n"
  },
  {
    "path": "scripts/gui/waitforbuttonpress.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{b} =} waitforbuttonpress ()\n## Wait for mouse click or key press over the current figure window.\n##\n## The return value of @var{b} is 0 if a mouse button was pressed or 1 if a\n## key was pressed.\n## @seealso{waitfor, ginput, kbhit}\n## @end deftypefn\n\n## The original version of this code bore the copyright\n## Author: Petr Mikulik\n## License: public domain\n\nfunction b = waitforbuttonpress ()\n\n  [x, y, k] = ginput (1);\n\n  if (nargout == 1)\n    if (k <= 5)\n      b = 0;\n    else\n      b = 1;\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/gui/warndlg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} warndlg ()\n## @deftypefnx {} {} warndlg (@var{msg})\n## @deftypefnx {} {} warndlg (@var{msg}, @var{title})\n## @deftypefnx {} {} warndlg (@var{msg}, @var{title}, @var{opt})\n## @deftypefnx {} {@var{h} =} warndlg (@dots{})\n## Display a warning dialog box with warning message @var{msg} and caption\n## @var{title}.\n##\n## The default warning message is\n## @qcode{\"This is the default warning string.@:\"} and the default caption is\n## @qcode{\"Warning Dialog\"}.\n##\n## The warning message may have multiple lines separated by newline characters\n## (\"\\n\"), or it may be a cellstr array with one element for each line.\n##\n## The third optional argument @var{opt} controls the behavior of the dialog.\n## For details, @pxref{XREFmsgbox,,@code{msgbox}}.\n##\n## The return value @var{h} is a handle to the figure object used for\n## building the dialog.\n##\n## Examples:\n##\n## @example\n## @group\n## warndlg (\"Some warning text for the user.\");\n## warndlg (\"Some warning text\\nwith two lines.\");\n## warndlg (@{\"Some warning text\", \"with two lines.\"@});\n## warndlg (\"Some warning text for the user.\", \"Fancy caption\");\n## @end group\n## @end example\n##\n## @seealso{errordlg, helpdlg, msgbox, inputdlg, listdlg, questdlg}\n## @end deftypefn\n\nfunction h = warndlg (varargin)\n\n  msg = \"This is the default warning.\";\n  tit = \"Warning Dialog\";\n  opt = \"non-modal\";\n\n  nargs = numel (varargin);\n\n  if (nargs > 3)\n    print_usage ();\n  elseif (nargs == 1)\n    msg = varargin{1};\n  elseif (nargs == 2)\n    msg = varargin{1};\n    tit = varargin{2};\n  elseif (nargs == 3)\n    msg = varargin{1};\n    tit = varargin{2};\n    opt = varargin{3};\n  endif\n\n  htmp = msgbox (msg, tit, \"warn\", opt);\n\n  if (nargout)\n    h = htmp;\n  endif\n\nendfunction\n\n## No BIST tests.  This function just dispatches to msgbox().\n%!assert (1)\n"
  },
  {
    "path": "scripts/help/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/help/__gripe_missing_component__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} __gripe_missing_component__ (@var{caller}, @var{component})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction __gripe_missing_component__ (caller, component)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  msg = \"\";\n  fcn = missing_component_hook ();\n\n  ftype = exist (fcn);\n  if (ftype == 2 || ftype == 3 || ftype == 5 || ftype == 103)\n    msg = feval (fcn, component);\n  endif\n\n  if (isempty (msg))\n    switch (component)\n      case \"info-file\"\n        msg = \"unable to find the Octave info manual, Octave installation is incomplete\";\n      case \"mkoctfile\"\n        msg = \"unable to find the mkoctfile command, Octave installation is incomplete\";\n      case \"octave\"\n        msg = \"unable to find the octave executable, Octave installation is incomplete\";\n      case \"octave-config\"\n        msg = \"unable to find the octave-config command, Octave installation is incomplete\";\n      otherwise\n        msg = ['unable to find required Octave component \"' component '\"'];\n    endswitch\n  endif\n\n  error (\"%s: %s\\n\", caller, msg);\n\nendfunction\n\n\n## NOTE: Tests cannot rely on the exact error strings shown above because we\n##       specifically allow these messages to be overridden by\n##       missing_component_hook.  The prefix is all we can be sure of.\n%!error <abc: .*> __gripe_missing_component__ (\"abc\", \"info-file\")\n%!error <abc: .*> __gripe_missing_component__ (\"abc\", \"octave\")\n%!error <abc: .*> __gripe_missing_component__ (\"abc\", \"octave-config\")\n%!error <abc: .*> __gripe_missing_component__ (\"abc\", \"xyz\")\n\n%!error <Invalid call> __gripe_missing_component__ ()\n%!error <Invalid call> __gripe_missing_component__ (\"fcn\")\n"
  },
  {
    "path": "scripts/help/__makeinfo__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type})\n## @deftypefnx {} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type}, @var{fsee_also})\n## Undocumented internal function.\n## @end deftypefn\n\n## Run @code{makeinfo} on a given text.\n##\n## The string @var{text} is run through the @code{__makeinfo__} program\n## to generate output in various formats.  This string must contain valid\n## Texinfo formatted text.\n##\n## The @var{output_type} selects the format of the output.  This can be either\n## @t{\"html\"}, @t{\"texinfo\"}, or @t{\"plain text\"}.  By default this is\n## @t{\"plain text\"}.  If @var{output_type} is @t{\"texinfo\"}, the @t{@@seealso}\n## macro is expanded, but otherwise the text is unaltered.\n##\n## If the optional argument @var{see_also} is present, it is used to expand the\n## Octave specific @t{@@seealso} macro.  This argument must be a function\n## handle, that accepts a cell array of strings as input argument (each\n## elements of the array corresponds to the arguments to the @t{@@seealso}\n## macro), and return the expanded string.  If this argument is not given, the\n## @t{@@seealso} macro will be expanded to the text\n##\n## @example\n## See also: arg1, arg2, ...\n## @end example\n##\n## @noindent\n## for @t{\"plain text\"} output, and\n##\n## @example\n## See also: @@ref@{arg1@}, @@ref@{arg2@}, ...\n## @end example\n##\n## @noindent\n## otherwise.\n##\n## The optional output argument @var{status} contains the exit status of the\n## @code{makeinfo} program as returned by @code{system}.\n\nfunction [retval, status] = __makeinfo__ (text, output_type = \"plain text\", fsee_also)\n\n  ## Check input\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (text))\n    error (\"__makeinfo__: first input argument must be a string\");\n  endif\n\n  if (! ischar (output_type))\n    error (\"__makeinfo__: second input argument must be a string\");\n  endif\n\n  ## NOTE: The 3rd argument is used by Octave Forge function\n  ##       generate_package_html, not by core Octave.  This functionality\n  ##       can only be removed when that function has been updated.\n  if (nargin < 3)\n    if (strcmpi (output_type, \"plain text\"))\n      fsee_also = @(T) [\"\\nSee also:\", sprintf(\" %s,\", T{:})(1:end-1), \"\\n\"];\n    else\n      fsee_also = @(T) [\"\\nSee also:\", sprintf(\" @ref{%s},\", T{:})(1:end-1), \"\\n\"];\n    endif\n  endif\n\n  if (! is_function_handle (fsee_also))\n    error (\"__makeinfo__: third input argument must be a function handle\");\n  endif\n\n  ## Formatting in m-files has an extra space at the beginning of every line.\n  ## Remove these unwanted spaces if present.  First text char is \"\\n\" delim.\n  if (text(2) == \" \")\n    text = strrep (text, \"\\n \", \"\\n\");\n  endif\n  ## Texinfo crashes if @end tex does not appear first on the line.\n  text = regexprep (text, '^ +@end tex', '@end tex', 'lineanchors');\n  ## Replace @seealso with Octave specific @xseealso macro.\n  ## Also escape '@' to '@@' for Texinfo, unless '@\\' pattern used.\n  [s, e] = regexp (text, '@seealso{(?:[^}]|@\\\\})+}');\n  cum_rep = 0;\n  for (i_match = 1:numel (s))\n    esc_text = regexprep (text(((s(i_match)+8:e(i_match))+i_match-1)+cum_rep), '@(?!\\\\)', '@@');\n    text = [text(1:s(i_match)+i_match+cum_rep-1), 'xseealso', esc_text, ...\n            text(e(i_match)+1+i_match+cum_rep-1:end)];\n    cum_rep += numel (esc_text) - (e(i_match)-(s(i_match)+8)+1);\n  endfor\n\n  ## We don't want *ref macros to clutter plain text output with \"Note ...\"\n  if (strcmp (output_type, \"plain text\"))\n    text = regexprep (text, '@ref{(?:[^}]*?),?(?:XREF)?([^,}]+)}', '$1');\n    text = regexprep (text, '@xref{(?:[^}]*?),?(?:XREF)?([^,}]+)}', 'See $1');\n    text = regexprep (text, '@pxref{(?:[^}]*?),?(?:XREF)?([^,}]+)}', 'see $1');\n  endif\n\n  file = texi_macros_file ();\n  fid = fopen (file, \"r\");\n  if (fid < 0)\n    error (\"unable to open %s for reading\", file);\n  else\n    macros_text = fread (fid, Inf, \"*char\")';\n    text = [macros_text text];\n  endif\n  fclose (fid);\n\n  if (strcmpi (output_type, \"texinfo\"))\n    status = 0;\n    retval = text;\n    return;\n  endif\n\n  ## Create the final TeXinfo input string\n  text = sprintf (\"\\\\input texinfo\\n\\n%s\\n\\n@bye\\n\", text);\n\n  unwind_protect\n    ## Write Texinfo to tmp file\n    template = \"octave-help-XXXXXX\";\n    [fid, name] = mkstemp (fullfile (tempdir, template), true);\n    if (fid < 0)\n      error (\"__makeinfo__: could not create temporary file\");\n    endif\n    fprintf (fid, \"%s\", text);\n    fclose (fid);\n\n    ## Take action depending on output type\n    switch (lower (output_type))\n      case \"plain text\"\n        cmd = sprintf ('%s --no-headers --no-warn --no-validate --plaintext --fill-column=80 -c exampleindent=2 --output=- \"%s\"',\n                       makeinfo_program (), name);\n      case \"html\"\n        cmd = sprintf ('%s --no-headers --no-warn --no-validate --html --output=- \"%s\"',\n                       makeinfo_program (), name);\n      otherwise\n        error (\"__makeinfo__: unsupported output type: '%s'\", output_type);\n    endswitch\n\n    ## Call makeinfo\n    [status, retval] = system (cmd);\n\n    ## On error, retry with force to ensure user gets *something*\n    if (status)\n      cmd = regexprep (cmd, '--output=', '--force --output=', 'once');\n      [status_force, retval] = system (cmd);\n      ## original return value usually more useful\n      if (status_force)\n        status = status_force;\n      endif\n    endif\n\n    ## Clean up extra newlines generated by makeinfo\n    if (strcmpi (output_type, \"plain text\"))\n      if (numel (retval) > 2 && retval(end-1:end) == \"\\n\\n\")\n        retval = retval(1:end-2);\n      endif\n    endif\n\n    ## Clean up start of @deftypefn expansion which includes extra ':'\n    retval = regexprep (retval, '^ -- : +', ' -- ', \"lineanchors\");\n\n  unwind_protect_cleanup\n    if (exist (name, \"file\"))\n      delete (name);\n    endif\n  end_unwind_protect\n\nendfunction\n\n\n## No test needed for internal helper function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/help/__unimplemented__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{txt} =} __unimplemented__ (@var{fcn})\n## Return specific help text for the unimplemented function @var{fcn}.\n##\n## This is usually a suggestion for an existing compatible function to use in\n## place of @var{fcn}.\n##\n## This function is not called by users, but by the Octave interpreter when it\n## fails to recognize an input string as a valid function name.  See\n## @code{missing_function_hook} for using a different handler for this event.\n## @seealso{missing_function_hook}\n## @end deftypefn\n\nfunction txt = __unimplemented__ (fcn)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  print_contribute_msg = true;\n\n  ## Some smarter cases, add more as needed.\n  switch (fcn)\n    case {\"avifile\", \"aviinfo\", \"aviread\"}\n      txt = [\"Basic video file support is provided in the video package.  \", ...\n             \"See @url{https://packages.octave.org/video/}.\"];\n\n    case \"funm\"\n      txt = [\"@code{funm} is not currently part of core Octave.  \", ...\n             \"See the linear-algebra package at \", ...\n             \"@url{https://packages.octave.org/linear-algebra/}.\"];\n      print_contribute_msg = false;\n\n    case \"griddedInterpolant\"\n      txt = [\"@code{griddedInterpolant} is not implemented.  \", ...\n             \"Consider using @code{griddata}.\"];\n\n    case \"linprog\"\n      txt = [\"Octave does not currently provide @code{linprog}.  \", ...\n             \"Linear programming problems may be solved using @code{glpk}.  \", ...\n             \"Try @code{help glpk} for more info.\"];\n\n    case \"matlabrc\"\n      txt = [\"@file{matlabrc} is not implemented.  \", ...\n             \"Octave uses the file @file{.octaverc} instead.\"];\n      print_contribute_msg = false;\n\n    case {\"ode113\", \"ode23t\", \"ode23tb\"}\n      txt = [\"Octave provides @code{lsode}, and @code{ode15i}, \", ...\n             \"@code{ode15s}, @code{ode23}, @code{ode23s}, @code{ode45}\", ...\n             \"for solving differential equations.  For more information\", ...\n             \"try @code{help lsode} or @code{help ode45}.  \", ...\n             \"Further specialized ODE solvers are provided by the odepkg \", ...\n             \"package.  See @url{https://wiki.octave.org/Odepkg}.\"];\n\n    case \"polarplot\"\n      txt = [\"@code{polarplot} is not implemented.  \", ...\n             \"Consider using @code{polar}.\"];\n\n    case \"startup\"\n      txt = [\"@file{startup.m} is a user startup and configuration script.\", ...\n             \"  Try @code{doc startup} for more information.\"];\n      print_contribute_msg = false;\n\n    case {\"xlsread\", \"xlsfinfo\", \"xlswrite\", \"wk1read\", \"wk1finfo\", \"wk1write\"}\n      txt = [\"Functions for spreadsheet style I/O \", ...\n             \"(.xls .xlsx .sxc .ods .dbf .wk1 etc.) \" , ...\n             \"are provided in the io package.  \", ...\n             \"See @url{https://packages.octave.org/io/}.\"];\n      print_contribute_msg = false;\n\n    ## control system\n    case {\"absorbDelay\", \"allmargin\", \"append\", \"augstate\", \"balreal\", ...\n          \"balred\", \"balredOptions\", \"bdschur\", \"bode\", ...\n          \"bodemag\", \"bodeoptions\", \"bodeplot\", \"c2d\", \"c2dOptions\", ...\n          \"canon\", \"care\", \"chgFreqUnit\", \"chgTimeUnit\", \"connect\", ...\n          \"connectOptions\", \"covar\", \"ctrb\", \"ctrbf\", \"ctrlpref\", \"d2c\", ...\n          \"d2cOptions\", \"d2d\", \"d2dOptions\", \"damp\", \"dare\", \"db2mag\", ...\n          \"dcgain\", \"delay2z\", \"delayss\", \"dlqr\", \"dlyap\", \"dlyapchol\", ...\n          \"drss\", \"dsort\", \"dss\", \"dssdata\", \"esort\", \"estim\", \"evalfr\", ...\n          \"feedback\", \"filt\", \"frd\", \"frdata\", \"freqresp\", \"gcare\", \"gdare\", ...\n          \"genfrd\", \"genmat\", \"gensig\", \"genss\", \"get\", \"getBlockValue\", ...\n          \"getDelayModel\", \"getGainCrossover\", \"getIOTransfer\", ...\n          \"getLFTModel\", \"getLoopTransfer\", \"getNominal\", \"getoptions\", ...\n          \"getPeakGain\", \"getSwitches\", \"getValue\", \"gram\", \"hasdelay\", ...\n          \"hasInternalDelay\", \"hsvd\", \"hsvdOptions\", \"hsvoptions\", ...\n          \"hsvplot\", \"imp2exp\", \"impulse\", \"impulseplot\", \"initial\", ...\n          \"initialplot\", \"iopzmap\", \"iopzplot\", \"isct\", \"isdt\", ...\n          \"isfinite\", \"isParametric\", \"isproper\", \"isreal\", \"issiso\", ...\n          \"isstable\", \"isstatic\", \"kalman\", \"kalmd\", \"lft\", \"loopswitch\", ...\n          \"lqg\", \"lqgreg\", \"lqgtrack\", \"lqi\", \"lqr\", \"lqrd\", \"lqry\", \"lsim\", ...\n          \"lsiminfo\", \"lsimplot\", \"ltiview\", \"lyap\", \"lyapchol\", \"mag2db\", ...\n          \"margin\", \"minreal\", \"modred\", \"modsep\", \"nblocks\", \"ndims\", ...\n          \"ngrid\", \"nichols\", \"nicholsoptions\", \"nicholsplot\", \"nmodels\", ...\n          \"norm\", \"nyquist\", \"nyquistoptions\", \"nyquistplot\", \"obsv\", ...\n          \"obsvf\", \"order\", \"pade\", \"parallel\", \"permute\", \"pid\", \"piddata\", ...\n          \"pidstd\", \"pidstddata\", \"pidtool\", \"pidtune\", \"pidtuneOptions\", ...\n          \"place\", \"pole\", \"prescale\", \"pzmap\", \"pzoptions\", \"pzplot\", ...\n          \"realp\", \"reg\", \"replaceBlock\", \"repsys\", \"reshape\", \"rlocus\", ...\n          \"rlocusplot\", \"rss\", \"series\", \"set\", \"setBlockValue\", ...\n          \"setDelayModel\", \"setoptions\", \"setValue\", \"sgrid\", ...\n          \"showBlockValue\", \"showTunable\", \"sigma\", \"sigmaoptions\", ...\n          \"sigmaplot\", \"sisoinit\", \"sisotool\", \"sminreal\", \"ss\", ...\n          \"ss2ss\", \"ssdata\", \"stabsep\", \"stabsepOptions\", \"stack\", \"step\", ...\n          \"stepDataOptions\", \"stepinfo\", \"stepplot\", \"sumblk\", \"tf\", ...\n          \"tfdata\", \"thiran\", \"timeoptions\", \"totaldelay\", \"tzero\", ...\n          \"updateSystem\", \"upsample\", \"xperm\", \"zero\", \"zgrid\", \"zpk\", ...\n          \"zpkdata\"}\n      txt = check_package (fcn, \"control\", ...\n                           {\"frd\", \"iddata\", \"lti\", \"ss\", \"tf\", \"poly\"});\n      print_contribute_msg = false;\n\n    ## communications\n    case {\"algdeintrlv\", \"algintrlv\", \"alignsignals\", \"amdemod\", \"ammod\", ...\n          \"arithdeco\", \"arithenco\", \"awgn\", \"bchdec\", \"bchenc\", ...\n          \"bchgenpoly\", \"bchnumerr\", \"berawgn\", \"bercoding\", \"berconfint\", ...\n          \"berfading\", \"berfit\", \"bersync\", \"bertool\", \"bi2de\", \"bin2gray\", ...\n          \"biterr\", \"bsc\", \"cma\", \"commscope\", \"compand\", \"convdeintrlv\", ...\n          \"convenc\", \"convintrlv\", \"convmtx\", \"cosets\", \"cyclgen\", ...\n          \"cyclpoly\", \"de2bi\", \"decode\", \"deintrlv\", \"dfe\", \"dftmtx\", ...\n          \"distspec\", \"doppler\", \"dpcmdeco\", \"dpcmenco\", \"dpcmopt\", ...\n          \"dpskdemod\", \"dpskmod\", \"dvbs2ldpc\", \"encode\", \"equalize\", ...\n          \"eyediagram\", \"EyeScope\", \"finddelay\", \"fmdemod\", \"fmmod\", ...\n          \"fskdemod\", \"fskmod\", \"gaussdesign\", \"gen2par\", \"genqamdemod\", ...\n          \"genqammod\", \"gf\", \"gfadd\", \"gfconv\", \"gfcosets\", \"gfdeconv\", ...\n          \"gfdiv\", \"gffilter\", \"gflineq\", \"gfminpol\", \"gfmul\", \"gfpretty\", ...\n          \"gfprimck\", \"gfprimdf\", \"gfprimfd\", \"gfrank\", \"gfrepcov\", ...\n          \"gfroots\", \"gfsub\", \"gftable\", \"gftrunc\", \"gftuple\", \"gfweight\", ...\n          \"gray2bin\", \"hammgen\", \"heldeintrlv\", \"helintrlv\", ...\n          \"helscandeintrlv\", \"helscanintrlv\", \"huffmandeco\", \"huffmandict\", ...\n          \"huffmanenco\", \"intdump\", \"intrlv\", \"iscatastrophic\", ...\n          \"isprimitive\", \"istrellis\", \"legacychannelsim\", \"lineareq\", ...\n          \"lloyds\", \"lms\", \"lteZadoffChuSeq\", \"marcumq\", ...\n          \"mask2shift\", \"matdeintrlv\", \"matintrlv\", \"minpol\", \"mldivide\", ...\n          \"mlseeq\", \"modnorm\", \"muxdeintrlv\", \"muxintrlv\", \"noisebw\", ...\n          \"normlms\", \"oct2dec\", \"oqpskdemod\", \"oqpskmod\", \"pamdemod\", ...\n          \"pammod\", \"pmdemod\", \"pmmod\", \"poly2trellis\", \"primpoly\", ...\n          \"pskdemod\", \"pskmod\", \"qamdemod\", \"qammod\", \"qfunc\", \"qfuncinv\", ...\n          \"quantiz\", \"randdeintrlv\", \"randerr\", \"randintrlv\", \"randsrc\", ...\n          \"rayleighchan\", \"rcosdesign\", \"rectpulse\", \"reset\", \"ricianchan\", ...\n          \"rls\", \"rsdec\", \"rsenc\", \"rsgenpoly\", \"rsgenpolycoeffs\", ...\n          \"scatterplot\", \"sdrexamples\", \"sdrfgensysace\", \"sdrfroot\", ...\n          \"sdrinfo\", \"sdrload\", \"sdrsetup\", \"semianalytic\", \"shift2mask\", ...\n          \"signlms\", \"ssbdemod\", \"ssbmod\", \"stdchan\", ...\n          \"supportPackageInstaller\", \"symerr\", \"syndtable\", \"varlms\", ...\n          \"vec2mat\", \"vitdec\", \"wgn\"}\n      txt = check_package (fcn, \"communications\");\n      print_contribute_msg = false;\n\n    ## dataypes\n    case {\"array2table\", \"caldays\", \"calendarDuration\", \"calmonths\", ...\n          \"calquarters\", \"calweeks\", \"calyears\", \"categorical\", ...\n          \"cell2table\", \"convertCharsToStrings\", \"convertStringsToChars\", ...\n          \"csv2table\", \"datetime\", \"days\", \"duration\", \"hours\", ...\n          \"iscalendarduration\", \"iscategorical\", \"isdatetime\", \"isduration\", ...\n          \"isnat\", \"istable\", \"keyHash\", \"keyMatch\", \"milliseconds\", ...\n          \"minutes\", \"missing\", \"NaT\", \"seconds\", \"string\", \"struct2table\", ...\n          \"table\", \"vartype\", \"years\"}\n      txt = check_package (fcn, \"datatypes\");\n      print_contribute_msg = false;\n\n    ## dicom\n    case {\"addContour\", \"convertToInfo\", \"dicomanon\", \"dicomBrowser\", ...\n          \"dicomCollection\", \"dicomContours\", \"dicomdict\", \"dicomdisp\", ...\n          \"dicominfo\", \"dicomlookup\", \"dicomread\", \"dicomreadVolume\", ...\n          \"dicomuid\", \"dicomwrite\", \"deleteContour\", ...\n          \"images.dicom.decodeUID\", \"images.dicom.parseDICOMDIR\", \"isdicom\", ...\n          \"plotContour\"}\n      txt = check_package (fcn, \"dicom\");\n      print_contribute_msg = false;\n\n    ## financial\n    case {\"abs2active\", \"accrfrac\", \"acrubond\", \"acrudisc\", \"active2abs\", ...\n          \"addEquality\", \"addGroupRatio\", \"addGroups\", \"addInequality\", ...\n          \"adline\", \"adosc\", \"amortize\", \"annurate\", \"annuterm\", ...\n          \"arith2geom\", \"ascii2fts\", \"beytbill\", \"binprice\", \"blkimpv\", ...\n          \"blkprice\", \"blsdelta\", \"blsgamma\", \"blsimpv\", \"blslambda\", ...\n          \"blsprice\", \"blsrho\", \"blstheta\", \"blsvega\", \"bndconvp\", ...\n          \"bndconvy\", \"bnddurp\", \"bnddury\", \"bndkrdur\", \"bndprice\", ...\n          \"bndspread\", \"bndtotalreturn\", \"bndyield\", \"bolling\", \"bollinger\", ...\n          \"boxcox\", \"busdate\", \"busdays\", \"candle\", \"cdai\", \"cdprice\", ...\n          \"cdyield\", \"cfamounts\", \"cfbyzero\", \"cfconv\", \"cfdates\", \"cfdur\", ...\n          \"cfplot\", \"cfport\", \"cfprice\", \"cfspread\", \"cftimes\", \"cfyield\", ...\n          \"chaikosc\", \"chaikvolat\", \"chartfts\", \"checkFeasibility\", ...\n          \"chfield\", \"convert2sur\", ...\n          \"convertto\", \"corr2cov\", \"cov2corr\", \"cpncount\", \"cpndaten\", ...\n          \"cpndatenq\", \"cpndatep\", \"cpndaysp\", \"cpnpersz\", \"createholidays\", ...\n          \"cumsum\", \"cur2frac\", \"cur2str\", \"date2time\", \"dateaxis\", ...\n          \"datedisp\", \"datefind\", \"datemnth\", \"datewrkdy\", \"day\", \"days360\", ...\n          \"days360e\", \"days360isda\", \"days360psa\", \"days365\", \"daysact\", ...\n          \"daysadd\", \"daysdif\", \"dec2thirtytwo\", \"depfixdb\", \"depgendb\", ...\n          \"deprdv\", \"depsoyd\", \"depstln\", \"diff\", \"disc2zero\", \"discrate\", ...\n          \"ecmmvnrfish\", \"ecmmvnrmle\", \"ecmmvnrobj\", \"ecmmvnrstd\", ...\n          \"ecmnfish\", \"ecmnhess\", \"ecmninit\", \"ecmnmle\", \"ecmnobj\", ...\n          \"ecmnstd\", \"effrr\", \"elpm\", \"emaxdrawdown\", \"end\", \"eomdate\", ...\n          \"estimateAssetMoments\", \"estimateBounds\", ...\n          \"estimateFrontier\", ...\n          \"estimateFrontierByReturn\", ...\n          \"estimateFrontierByRisk\", ...\n          \"estimateFrontierLimits\", ...\n          \"estimateMaxSharpeRatio\", \"estimatePortMoments\", ...\n          \"estimatePortReturn\", ...\n          \"estimatePortRisk\", ...\n          \"estimatePortStd\", \"estimatePortVaR\", ...\n          \"estimateScenarioMoments\", \"ewstats\", ...\n          \"exp\", \"extfield\", \"fbusdate\", \"fetch\", \"fieldnames\", \"fillts\", ...\n          \"fints\", \"floatdiscmargin\", \"floatmargin\", \"fpctkd\", \"frac2cur\", ...\n          \"freqnum\", \"freqstr\", \"frontcon\", \"frontier\", \"fts2ascii\", ...\n          \"fts2mat\", \"ftsbound\", \"ftsgui\", \"ftsinfo\", \"ftstool\", \"ftsuniq\", ...\n          \"fvdisc\", \"fvfix\", \"fvvar\", \"fwd2zero\", \"geom2arith\", ...\n          \"getAssetMoments\", \"getBounds\", ...\n          \"getBudget\", ...\n          \"getCosts\", \"getEquality\", ...\n          \"getGroupRatio\", \"getGroups\", ...\n          \"getInequality\", ...\n          \"getnameidx\", \"getOneWayTurnover\", ...\n          \"getScenarios\", ...\n          \"hhigh\", \"highlow\", \"holdings2weights\", ...\n          \"holidays\", \"horzcat\", \"hour\", \"inforatio\", \"irr\", \"isbusday\", ...\n          \"iscompatible\", \"isfield\", \"issorted\", \"kagi\", \"lagts\", ...\n          \"lbusdate\", \"leadts\", \"length\", \"linebreak\", \"llow\", ...\n          \"log10\", \"log2\", \"lpm\", \"lweekdate\", \"m2xdate\", \"macd\", ...\n          \"maxdrawdown\", \"medprice\", \"merge\", \"minus\", \"minute\", \"mirr\", ...\n          \"month\", \"months\", \"movavg\", \"mrdivide\", \"mtimes\", \"mvnrfish\", ...\n          \"mvnrmle\", \"mvnrobj\", \"mvnrstd\", \"negvolidx\", ...\n          \"nomrr\", \"nweekdate\", \"nyseclosures\", \"onbalvol\", \"opprofit\", ...\n          \"payadv\", \"payodd\", \"payper\", \"payuni\", \"pcalims\", \"pcgcomp\", ...\n          \"pcglims\", \"pcpval\", \"peravg\", \"periodicreturns\", \"plotFrontier\", ...\n          \"plus\", \"pointfig\", \"portalloc\", ...\n          \"portalpha\", \"portcons\", \"Portfolio\", \"PortfolioCVaR\", ...\n          \"PortfolioMAD\", \"portopt\", \"portrand\", \"portror\", \"portsim\", ...\n          \"portstats\", \"portvar\", \"portvrisk\", \"posvolidx\", \"power\", ...\n          \"prbyzero\", \"prcroc\", \"prdisc\", \"priceandvol\", \"prmat\", \"prtbill\", ...\n          \"pvfix\", \"pvtrend\", \"pvvar\", \"pyld2zero\", \"rdivide\", \"renko\", ...\n          \"resamplets\", \"ret2tick\", \"rmfield\", \"rsindex\", \"selectreturn\", ...\n          \"setAssetList\", \"setAssetMoments\", ...\n          \"setBounds\", \"setBudget\", ...\n          \"setCosts\", ...\n          \"setDefaultConstraints\", ...\n          \"setEquality\", ...\n          \"setGroupRatio\", ...\n          \"setGroups\", \"setInequality\", ...\n          \"setInitPort\", ...\n          \"setOneWayTurnover\", ...\n          \"setProbabilityLevel\", \"setScenarios\", ...\n          \"setSolver\", ...\n          \"setTurnover\", \"sharpe\", ...\n          \"simulateNormalScenariosByData\", ...\n          \"simulateNormalScenariosByMoments\", ...\n          \"smoothts\", \"sortfts\", ...\n          \"spctkd\", \"stochosc\", \"subsasgn\", \"subsref\", \"targetreturn\", ...\n          \"taxedrr\", \"tbilldisc2yield\", \"tbillprice\", \"tbillrepo\", ...\n          \"tbillval01\", \"tbillyield\", \"tbillyield2disc\", \"tbl2bond\", ...\n          \"thirdwednesday\", \"thirtytwo2dec\", \"tick2ret\", \"time2date\", ...\n          \"times\", \"toannual\", \"todaily\", \"today\", \"todecimal\", \"tomonthly\", ...\n          \"toquarterly\", \"toquoted\", \"tosemi\", \"totalreturnprice\", ...\n          \"toweekly\", \"tr2bonds\", \"transprob\", \"transprobbytotals\", ...\n          \"transprobfromthresholds\", \"transprobgrouptotals\", ...\n          \"transprobprep\", \"transprobtothresholds\", \"tsaccel\", \"tsmom\", ...\n          \"tsmovavg\", \"typprice\", \"ugarch\", \"ugarchllf\", \"ugarchpred\", ...\n          \"ugarchsim\", \"uicalendar\", \"uminus\", \"uplus\", \"vertcat\", ...\n          \"volarea\", \"volroc\", \"wclose\", \"weeknum\", \"weights2holdings\", ...\n          \"willad\", \"willpctr\", \"wrkdydif\", \"x2mdate\", \"xirr\", \"year\", ...\n          \"yeardays\", \"yearfrac\", \"ylddisc\", \"yldmat\", \"yldtbill\", ...\n          \"zbtprice\", \"zbtyield\", \"zero2disc\", \"zero2fwd\", \"zero2pyld\"}\n      txt = check_package (fcn, \"financial\", {\"diffusion\", \"drift\", \"sde\"});\n      print_contribute_msg = false;\n\n    ## image\n    case {\"activecontour\", \"adapthisteq\", \"affine2d\", \"affine3d\", ...\n          \"analyze75info\", \"analyze75read\", \"applycform\", \"applylut\", ...\n          \"axes2pix\", \"bestblk\", \"blockproc\", \"bwarea\", \"bwareaopen\", ...\n          \"bwboundaries\", \"bwconncomp\", \"bwconvhull\", \"bwdist\", ...\n          \"bwdistgeodesic\", \"bweuler\", \"bwhitmiss\", \"bwlabel\", \"bwlabeln\", ...\n          \"bwlookup\", \"bwmorph\", \"bwpack\", \"bwperim\", \"bwselect\", ...\n          \"bwtraceboundary\", \"bwulterode\", \"bwunpack\", \"checkerboard\", ...\n          \"col2im\", \"colfilt\", \"conndef\", \"convmtx2\", \"corner\", ...\n          \"cornermetric\", \"corr2\", \"cp2tform\", \"cpcorr\", \"cpselect\", ...\n          \"cpstruct2pairs\", \"dct2\", \"dctmtx\", \"deconvblind\", \"deconvlucy\", ...\n          \"deconvreg\", \"deconvwnr\", \"decorrstretch\", \"demosaic\", ...\n          \"edge\", \"edgetaper\", \"entropy\", \"entropyfilt\", \"fan2para\", ...\n          \"fanbeam\", \"findbounds\", \"fitgeotrans\", \"fliptform\", \"freqz2\", ...\n          \"fsamp2\", \"fspecial\", \"ftrans2\", \"fwind1\", \"fwind2\", \"getheight\", ...\n          \"getimage\", \"getimagemodel\", \"getline\", \"getneighbors\", ...\n          \"getnhood\", \"getpts\", \"getrect\", \"getsequence\", \"graycomatrix\", ...\n          \"graycoprops\", \"graydist\", \"grayslice\", \"graythresh\", \"hdrread\", ...\n          \"hdrwrite\", \"histeq\", \"hough\", \"houghlines\", \"houghpeaks\", ...\n          \"iccfind\", \"iccread\", \"iccroot\", \"iccwrite\", \"idct2\", \"ifanbeam\", ...\n          \"im2bw\", \"im2col\", \"im2double\", \"im2int16\", \"im2java2d\", ...\n          \"im2single\", \"im2uint16\", \"im2uint8\", \"imabsdiff\", \"imadd\", ...\n          \"imadjust\", \"ImageAdapter\", \"imageinfo\", \"imapplymatrix\", ...\n          \"imapprox\", \"imattributes\", \"imbothat\", \"imclearborder\", ...\n          \"imclose\", \"imcolormaptool\", \"imcomplement\", \"imcontour\", ...\n          \"imcontrast\", \"imcrop\", \"imdilate\", \"imdisplayrange\", ...\n          \"imdistline\", \"imdivide\", \"imellipse\", \"imerode\", \"imextendedmax\", ...\n          \"imextendedmin\", \"imfill\", \"imfilter\", \"imfindcircles\", ...\n          \"imfreehand\", \"imfuse\", \"imgca\", \"imgcf\", \"imgetfile\", ...\n          \"imgradient\", \"imgradientxy\", \"imhandles\", \"imhist\", ...\n          \"imhistmatch\", \"imhmax\", \"imhmin\", \"imimposemin\", \"imlincomb\", ...\n          \"imline\", \"immagbox\", \"immovie\", \"immultiply\", \"imnoise\", ...\n          \"imopen\", \"imoverview\", \"imoverviewpanel\", \"impixel\", ...\n          \"impixelinfo\", \"impixelinfoval\", \"impixelregion\", ...\n          \"impixelregionpanel\", \"implay\", \"impoint\", \"impoly\", \"improfile\", ...\n          \"impyramid\", \"imquantize\", \"imreconstruct\", \"imrect\", \"imref2d\", ...\n          \"imref3d\", \"imregconfig\", \"imregionalmax\", \"imregionalmin\", ...\n          \"imregister\", \"imregtform\", \"imresize\", \"imroi\", \"imrotate\", ...\n          \"imsave\", \"imscrollpanel\", \"imsharpen\", \"imshowpair\", ...\n          \"imsubtract\", \"imtool\", \"imtophat\", \"imtransform\", \"imwarp\", ...\n          \"interfileinfo\", \"interfileread\", \"intlut\", \"iptaddcallback\", ...\n          \"iptcheckconn\", \"iptcheckhandle\", \"iptgetapi\", ...\n          \"iptGetPointerBehavior\", \"iptgetpref\", \"ipticondir\", ...\n          \"iptPointerManager\", \"iptprefs\", \"iptremovecallback\", ...\n          \"iptSetPointerBehavior\", \"iptsetpref\", \"iptwindowalign\", \"iradon\", ...\n          \"isflat\", \"isicc\", \"isrset\", \"lab2double\", \"lab2uint16\", ...\n          \"lab2uint8\", \"label2rgb\", \"labelmatrix\", \"makecform\", ...\n          \"makeConstrainToRectFcn\", \"makehdr\", \"makelut\", \"makeresampler\", ...\n          \"maketform\", \"mat2gray\", \"mean2\", \"medfilt2\", \"montage\", ...\n          \"multithresh\", \"nitfinfo\", \"nitfread\", \"nlfilter\", \"normxcorr2\", ...\n          \"openrset\", \"ordfilt2\", \"otf2psf\", \"padarray\", \"para2fan\", ...\n          \"phantom\", \"poly2mask\", \"projective2d\", \"psf2otf\", \"qtdecomp\", ...\n          \"qtgetblk\", \"qtsetblk\", \"radon\", \"rangefilt\", \"reflect\", ...\n          \"regionprops\", \"rgb2gray\", \"rgb2ycbcr\", \"roicolor\", \"roifill\", ...\n          \"roifilt2\", \"roipoly\", \"rsetwrite\", \"std2\", \"stdfilt\", \"strel\", ...\n          \"stretchlim\", \"subimage\", \"tformarray\", \"tformfwd\", \"tforminv\", ...\n          \"tonemap\", \"translate\", \"truesize\", \"viscircles\", \"warp\", ...\n          \"watershed\", \"whitepoint\", \"wiener2\", \"xyz2double\", \"xyz2uint16\", ...\n          \"ycbcr2rgb\"}\n      txt = check_package (fcn, \"image\", {\"imref2d\", \"imref3d\", \"strel\"});\n      print_contribute_msg = false;\n\n    ## signal\n    case {\"ac2poly\", \"ac2rc\", \"angle\", \"arburg\", \"arcov\", \"armcov\", ...\n          \"aryule\", \"bandpower\", \"barthannwin\", \"besselap\", \"besself\", ...\n          \"bilinear\", \"bitrevorder\", \"blackmanharris\", \"bohmanwin\", ...\n          \"buffer\", \"buttap\", \"butter\", \"buttord\", \"cceps\", \"cconv\", ...\n          \"cell2sos\", \"cfirpm\", \"cheb1ap\", \"cheb1ord\", \"cheb2ap\", ...\n          \"cheb2ord\", \"chebwin\", \"cheby1\", \"cheby2\", \"chirp\", \"convmtx\", ...\n          \"corrmtx\", \"cpsd\", \"czt\", \"db\", \"db2mag\", \"db2pow\", \"dct\", ...\n          \"decimate\", \"demod\", \"design\", \"designmethods\", \"designopts\", ...\n          \"dfilt\", \"dftmtx\", \"digitrevorder\", \"diric\", \"downsample\", \"dpss\", ...\n          \"dpssclear\", \"dpssdir\", \"dpssload\", \"dspdata\", \"dspfwiz\", ...\n          \"dutycycle\", \"ellip\", \"ellipap\", \"ellipord\", \"enbw\", \"equiripple\", ...\n          \"falltime\", \"fdatool\", \"fdesign\", \"filt2block\", \"filterbuilder\", ...\n          \"filternorm\", \"filtfilt\", \"filtic\", \"filtord\", \"findpeaks\", ...\n          \"fir1\", \"fir2\", \"fircls\", \"fircls1\", \"firls\", \"firpm\", \"firpmord\", ...\n          \"firrcos\", \"firtype\", \"flattopwin\", \"freqs\", \"freqsamp\", \"fvtool\", ...\n          \"fwht\", \"gauspuls\", \"gaussdesign\", \"gaussfir\", \"gausswin\", ...\n          \"gmonopuls\", \"goertzel\", \"grpdelay\", \"hann\", \"hilbert\", \"icceps\", ...\n          \"idct\", \"ifwht\", \"impinvar\", \"impz\", \"impzlength\", \"interp\", ...\n          \"intfilt\", \"invfreqs\", \"invfreqz\", \"is2rc\", \"isallpass\", ...\n          \"islinphase\", \"ismaxphase\", \"isminphase\", \"isstable\", \"kaiser\", ...\n          \"kaiserord\", \"kaiserwin\", \"lar2rc\", \"latc2tf\", \"latcfilt\", ...\n          \"levinson\", \"lp2bp\", \"lp2bs\", \"lp2hp\", \"lp2lp\", \"lpc\", \"lsf2poly\", ...\n          \"mag2db\", \"marcumq\", \"maxflat\", \"medfilt1\", \"midcross\", ...\n          \"modulate\", \"mscohere\", \"nuttallwin\", \"overshoot\", \"parzenwin\", ...\n          \"pburg\", \"pcov\", \"peak2peak\", \"peak2rms\", \"peig\", \"phasedelay\", ...\n          \"phasez\", \"pmcov\", \"pmtm\", \"pmusic\", \"poly2ac\", \"poly2lsf\", ...\n          \"poly2rc\", \"polyscale\", \"polystab\", \"pow2db\", \"prony\", ...\n          \"pulseperiod\", \"pulsesep\", \"pulsewidth\", \"pulstran\", \"pwelch\", ...\n          \"pyulear\", \"rc2ac\", \"rc2is\", \"rc2lar\", \"rc2poly\", \"rceps\", ...\n          \"rcosdesign\", \"realizemdl\", \"rectpuls\", \"rectwin\", \"resample\", ...\n          \"residuez\", \"risetime\", \"rlevinson\", \"rms\", \"rooteig\", ...\n          \"rootmusic\", \"rssq\", \"sawtooth\", \"schurrc\", \"seqperiod\", ...\n          \"setspecs\", \"settlingtime\", \"sfdr\", \"sgolay\", \"sgolayfilt\", ...\n          \"shiftdata\", \"sigwin\", \"sinad\", \"slewrate\", \"snr\", \"sos2cell\", ...\n          \"sos2ss\", \"sos2tf\", \"sos2zp\", \"sosfilt\", \"spectrogram\", ...\n          \"spectrum\", \"sptool\", \"square\", \"ss2sos\", \"ss2tf\", \"ss2zp\", ...\n          \"statelevels\", \"stepz\", \"stmcb\", \"strips\", \"taylorwin\", \"tf2latc\", ...\n          \"tf2sos\", \"tf2ss\", \"tf2zp\", \"tf2zpk\", \"tfestimate\", \"thd\", \"toi\", ...\n          \"triang\", \"tripuls\", \"tukeywin\", \"udecode\", \"uencode\", ...\n          \"undershoot\", \"unshiftdata\", \"upfirdn\", \"upsample\", ...\n          \"validstructures\", \"vco\", \"window\", \"wintool\", \"wvtool\", \"xcorr\", ...\n          \"xcorr2\", \"xcov\", \"yulewalk\", \"zerophase\", \"zp2sos\", \"zp2ss\", ...\n          \"zp2tf\", \"zplane\"}\n      txt = check_package (fcn, \"signal\");\n      print_contribute_msg = false;\n\n    ## statistics\n    case {\"adtest\", \"anova1\", \"anova2\", \"anovan\", \"bar3\", \"bar3h\", ...\n           \"bartlett_test\", \"barttest\", \"betacdf\", \"BetaDistribution\", ...\n           \"betafit\", \"betainv\", \"betalike\", \"betapdf\", \"betarnd\", ...\n           \"betastat\", \"binocdf\", \"binofit\", \"binoinv\", \"binolike\", ...\n           \"BinomialDistribution\", \"binopdf\", \"binornd\", \"binostat\", ...\n           \"binotest\", \"BirnbaumSaundersDistribution\", \"bisacdf\", ...\n           \"bisafit\", \"bisainv\", \"bisalike\", \"bisapdf\", \"bisarnd\", ...\n           \"bisastat\", \"boxplot\", \"burrcdf\", \"BurrDistribution\", \"burrfit\", ...\n           \"burrinv\", \"burrlike\", \"burrpdf\", \"burrrnd\", \"burrstat\", ...\n           \"bvncdf\", \"bvtcdf\", \"CalinskiHarabaszEvaluation\", \"canoncorr\", ...\n           \"cauchycdf\", \"cauchyinv\", \"cauchypdf\", \"cauchyrnd\", \"cdf\", ...\n           \"cdfcalc\", \"cdfplot\", \"chi2cdf\", \"chi2gof\", \"chi2inv\", ...\n           \"chi2pdf\", \"chi2rnd\", \"chi2stat\", \"chi2test\", \"cholcov\", ...\n           \"cl_multinom\", \"ClassificationDiscriminant\", ...\n           \"ClassificationGAM\", \"ClassificationKNN\", ...\n           \"ClassificationNeuralNetwork\", \"ClassificationPartitionedModel\", ...\n           \"ClassificationSVM\", \"cluster\", \"ClusterCriterion\", ...\n           \"clusterdata\", \"cmdscale\", \"combnk\", ...\n           \"CompactClassificationDiscriminant\", \"CompactClassificationGAM\", ...\n           \"CompactClassificationNeuralNetwork\", \"CompactClassificationSVM\", ...\n           \"confusionchart\", \"confusionmat\", \"ConfusionMatrixChart\", ...\n           \"cophenet\", \"copulacdf\", \"copulapdf\", \"copularnd\", ...\n           \"correlation_test\", \"createns\", \"crosstab\", \"crossval\", ...\n           \"cvpartition\", \"datasample\", \"DaviesBouldinEvaluation\", \"dcov\", ...\n           \"dendrogram\", \"ecdf\", \"editDistance\", \"einstein\", \"evalclusters\", ...\n           \"evcdf\", \"evfit\", \"evinv\", \"evlike\", \"evpdf\", \"evrnd\", \"evstat\", ...\n           \"ExhaustiveSearcher\", \"expcdf\", \"expfit\", \"expinv\", \"explike\", ...\n           \"ExponentialDistribution\", \"exppdf\", \"exprnd\", \"expstat\", ...\n           \"ExtremeValueDistribution\", \"factoran\", \"fcdf\", \"fcnnpredict\", ...\n           \"fcnntrain\", \"ff2n\", \"fillmissing\", \"finv\", \"fishertest\", ...\n           \"fitcdiscr\", \"fitcgam\", \"fitcnet\", \"fitcsvm\", \"fitdist\", ...\n           \"fitgmdist\", \"fitlm\", \"fitrgam\", \"fpdf\", \"friedman\", \"frnd\", ...\n           \"fstat\", \"fullfact\", \"gamcdf\", \"gamfit\", \"gaminv\", \"gamlike\", ...\n           \"GammaDistribution\", \"gampdf\", \"gamrnd\", \"gamstat\", ...\n           \"GapEvaluation\", \"GeneralizedExtremeValueDistribution\", ...\n           \"GeneralizedParetoDistribution\", \"geocdf\", \"geofit\", \"geoinv\", ...\n           \"geomean\", \"geopdf\", \"geornd\", \"geostat\", \"gevcdf\", \"gevfit\", ...\n           \"gevfit_lmom\", \"gevinv\", \"gevlike\", \"gevpdf\", \"gevrnd\", ...\n           \"gevstat\", \"glmfit\", \"glmval\", \"gpcdf\", \"gpfit\", \"gpinv\", ...\n           \"gplike\", \"gppdf\", \"gprnd\", \"gpstat\", \"grp2idx\", \"grpstats\", ...\n           \"gscatter\", \"gumbelcdf\", \"gumbelfit\", \"gumbelinv\", \"gumbellike\", ...\n           \"gumbelpdf\", \"gumbelrnd\", \"HalfNormalDistribution\", \"harmmean\", ...\n           \"hist3\", \"histfit\", \"hmmestimate\", \"hmmgenerate\", \"hmmviterbi\", ...\n           \"hncdf\", \"hnfit\", \"hninv\", \"hnlike\", \"hnpdf\", \"hnrnd\", \"hnstat\", ...\n           \"hnswSearcher\", \"hotelling_t2test\", \"hotelling_t2test2\", ...\n           \"hygecdf\", \"hygeinv\", \"hygepdf\", \"hygernd\", \"hygestat\", \"icdf\", ...\n           \"inconsistent\", \"InverseGaussianDistribution\", \"invgcdf\", ...\n           \"invgfit\", \"invginv\", \"invglike\", \"invgpdf\", \"invgrnd\", ...\n           \"invgstat\", \"ismissing\", \"isoutlier\", \"iwishpdf\", \"iwishrnd\", ...\n           \"jackknife\", \"jsucdf\", \"jsupdf\", \"KDTreeSearcher\", \"kmeans\", ...\n           \"knnsearch\", \"kruskalwallis\", \"kstest\", \"kstest2\", \"laplacecdf\", ...\n           \"laplaceinv\", \"laplacepdf\", \"laplacernd\", \"levene_test\", ...\n           \"libsvmread\", \"libsvmwrite\", \"linkage\", \"loadmodel\", \"logicdf\", ...\n           \"logifit\", \"logiinv\", \"logilike\", \"logipdf\", \"logirnd\", ...\n           \"logistat\", \"logistic_regression\", \"LogisticDistribution\", ...\n           \"logit\", \"loglcdf\", \"loglfit\", \"loglinv\", \"logllike\", ...\n           \"LoglogisticDistribution\", \"loglpdf\", \"loglrnd\", \"loglstat\", ...\n           \"logncdf\", \"lognfit\", \"logninv\", \"lognlike\", ...\n           \"LognormalDistribution\", \"lognpdf\", \"lognrnd\", \"lognstat\", ...\n           \"LoguniformDistribution\", \"mahal\", \"makedist\", \"makima\", ...\n           \"manova1\", \"manovacluster\", \"mcnemar_test\", \"mhsample\", \"mle\", ...\n           \"mnpdf\", \"mnrfit\", \"mnrnd\", \"monotone_smooth\", \"multcompare\", ...\n           \"MultinomialDistribution\", \"multiway\", \"mvncdf\", \"mvnpdf\", ...\n           \"mvnrnd\", \"mvtcdf\", \"mvtcdfqmc\", \"mvtpdf\", \"mvtrnd\", \"nakacdf\", ...\n           \"nakafit\", \"NakagamiDistribution\", \"nakainv\", \"nakalike\", ...\n           \"nakapdf\", \"nakarnd\", \"nakastat\", \"nanmax\", \"nanmean\", \"nanmin\", ...\n           \"nansum\", \"nbincdf\", \"nbinfit\", \"nbininv\", \"nbinlike\", \"nbinpdf\", ...\n           \"nbinrnd\", \"nbinstat\", \"ncfcdf\", \"ncfinv\", \"ncfpdf\", \"ncfrnd\", ...\n           \"ncfstat\", \"nctcdf\", \"nctinv\", \"nctpdf\", \"nctrnd\", \"nctstat\", ...\n           \"ncx2cdf\", \"ncx2inv\", \"ncx2pdf\", \"ncx2rnd\", \"ncx2stat\", ...\n           \"NegativeBinomialDistribution\", \"NormalDistribution\", ...\n           \"normalise_distribution\", \"normcdf\", \"normfit\", \"norminv\", ...\n           \"normlike\", \"normpdf\", \"normplot\", \"normrnd\", \"normstat\", ...\n           \"optimalleaforder\", \"pca\", \"pcacov\", \"pcares\", \"pdf\", \"pdist\", ...\n           \"pdist2\", \"PiecewiseLinearDistribution\", \"plcdf\", \"plinv\", ...\n           \"plpdf\", \"plrnd\", \"plsregress\", \"plstat\", \"poisscdf\", ...\n           \"poissfit\", \"poissinv\", \"poisslike\", \"PoissonDistribution\", ...\n           \"poisspdf\", \"poissrnd\", \"poisstat\", \"ppplot\", \"princomp\", ...\n           \"probit\", \"procrustes\", \"qqplot\", \"random\", \"rangesearch\", ...\n           \"ranksum\", \"raylcdf\", \"RayleighDistribution\", \"raylfit\", ...\n           \"raylinv\", \"rayllike\", \"raylpdf\", \"raylrnd\", \"raylstat\", ...\n           \"regress\", \"regress_gp\", \"regression_ftest\", \"regression_ttest\", ...\n           \"RegressionGAM\", \"ricecdf\", \"ricefit\", \"riceinv\", \"ricelike\", ...\n           \"ricepdf\", \"ricernd\", \"ricestat\", \"RicianDistribution\", \"ridge\", ...\n           \"rmmissing\", \"runstest\", \"sampsizepwr\", \"sigma_pts\", \"signrank\", ...\n           \"signtest\", \"silhouette\", \"SilhouetteEvaluation\", \"slicesample\", ...\n           \"squareform\", \"standardizeMissing\", \"stepwisefit\", \"svmpredict\", ...\n           \"svmtrain\", \"tabulate\", \"tcdf\", \"tiedrank\", \"tinv\", ...\n           \"tLocationScaleDistribution\", \"tlscdf\", \"tlsfit\", \"tlsinv\", ...\n           \"tlslike\", \"tlspdf\", \"tlsrnd\", \"tlsstat\", \"tpdf\", ...\n           \"TriangularDistribution\", \"tricdf\", \"triinv\", \"trimmean\", ...\n           \"tripdf\", \"trirnd\", \"tristat\", \"trnd\", \"tstat\", \"ttest\", ...\n           \"ttest2\", \"unidcdf\", \"unidfit\", \"unidinv\", \"unidpdf\", \"unidrnd\", ...\n           \"unidstat\", \"unifcdf\", \"unifinv\", \"unifit\", ...\n           \"UniformDistribution\", \"unifpdf\", \"unifrnd\", \"unifstat\", ...\n           \"vartest\", \"vartest2\", \"vartestn\", \"violin\", \"vmcdf\", \"vminv\", ...\n           \"vmpdf\", \"vmrnd\", \"wblcdf\", \"wblfit\", \"wblinv\", \"wbllike\", ...\n           \"wblpdf\", \"wblplot\", \"wblrnd\", \"wblstat\", \"WeibullDistribution\", ...\n           \"wienrnd\", \"wishpdf\", \"wishrnd\", \"x2fx\", \"ztest\", \"ztest2\"}\n      txt = check_package (fcn, \"statistics\");\n      print_contribute_msg = false;\n\n    ## symbolic\n    case {\"argnames\", \"bernoulli\", \"catalan\", \"charpoly\", \"chebyshevT\", ...\n          \"chebyshevU\", \"children\", \"coshint\", \"cosint\", \"dawson\", ...\n          \"digits\", \"dilog\", \"dirac\", \"divisors\", \"dsolve\", \"ei\", ...\n          \"ellipticCE\", \"ellipticCK\", \"ellipticCPi\", \"ellipticE\", ...\n          \"ellipticF\", \"ellipticK\", \"ellipticPi\", \"euler\", \"eulergamma\", ...\n          \"expand\", \"finverse\", \"formula\", \"fresnelc\", \"fresnels\", ...\n          \"funtool\", \"gegenbauerC\", \"harmonic\", \"heaviside\", \"hermiteH\", ...\n          \"hypergeom\", \"igamma\", \"jacobiP\", \"kroneckerDelta\", \"kummerU\", ...\n          \"laguerreL\", \"legendreP\", \"logint\", \"minpoly\", \"pochhammer\", ...\n          \"poles\", \"poly2sym\", \"polylog\", \"pretty\", \"quorem\", ...\n          \"rectangularPulse\", \"signIm\", \"simplify\", \"sinhint\", \"sinint\", ...\n          \"solve\", \"ssinint\", \"sym\", \"sym2poly\", \"symfun\", \"sympref\", ...\n          \"syms\", \"symvar\", \"triangularPulse\", \"vpa\", \"vpasolve\", ...\n          \"whittakerM\", \"whittakerW\", \"zeta\"}\n      txt = check_package (fcn, \"symbolic\", ...\n                           {\"double\", \"logical\", \"sym\", \"symfun\"});\n      print_contribute_msg = false;\n\n    ## optim(ization)\n    case {\"bintprog\", \"color\", \"fgoalattain\", \"fmincon\", \"fminimax\", ...\n          \"fminsearch\", \"fseminf\", \"fzmult\", \"gangstr\", \"ktrlink\", ...\n          \"linprog\", \"lsqcurvefit\", \"lsqlin\", \"lsqnonlin\", \"optimoptions\", ...\n          \"optimtool\", \"quadprog\"}\n      txt = check_package (fcn, \"optim\");\n      print_contribute_msg = false;\n\n    otherwise\n      ## Not in any package, check against list of core Matlab functions\n      if (ismember (fcn, missing_functions ()))\n        txt = sprintf (\"The @code{%s} function is not yet implemented in Octave.\", fcn);\n      else\n        txt = \"\";\n      endif\n\n  endswitch\n\n  if (txt)\n    if (print_contribute_msg)\n      txt = [txt, \"\\n\\n@noindent\\nPlease read \", ...\n             \"@url{https://www.octave.org/missing.html} to learn how \", ...\n             \"you can contribute missing functionality.\"];\n    endif\n    txt = __makeinfo__ (txt, \"plain text\");\n  endif\n\n  if (nargout == 0)\n    error (\"Octave:missing-function\", \"%s\\n\", txt);\n  endif\n\nendfunction\n\nfunction txt = check_package (fcn, name, classes = {})\n\n  txt = sprintf (strcat (\"The '%s' function belongs to the '%s' package\", ...\n                         \" indexed in Octave Packages at @url{https://\", ...\n                         \"packages.octave.org}\"), fcn, name);\n\n  [~, status] = pkg (\"describe\", name);\n  switch (lower (status{1}))\n\n    case \"loaded\",\n      for i = 1:numel (classes)\n        cls = classes{i};\n        try\n          meths = methods (cls);\n        catch\n          meths = {};\n        end_try_catch\n        if (any (strcmp (fcn, meths)))\n          txt = sprintf ([\"@code{%s} is a method of class @code{%s}; \", ...\n                          \"it must be called by prepending '%s/' \", ...\n                          \"to the method name (type @code{help @@%s/%s}).\"],\n                         fcn, cls, cls, cls, fcn);\n          return;\n        endif\n      endfor\n      ## FIXME: This code is probably unreachable if package contains the list\n      ## of implemented functions, rather than the list from Matlab.\n      txt = sprintf (\"%s but has not yet been implemented.\", txt);\n\n    case \"not loaded\",\n      txt = sprintf ([\"%s which you have installed, but not loaded.  \", ...\n                      \"To load the package, type @w{@code{pkg load %s}}@ \", ...\n                      \"from the Octave prompt.\"], txt, name);\n\n    otherwise\n      ## this includes \"not installed\" and anything else if pkg changes\n      ## the output of describe.\n      txt = sprintf (\"%s which seems not to be installed on your system.\", txt);\n\n  endswitch\n\nendfunction\n\nfunction rlist = missing_functions ()\n\n  persistent list = {\n  \"addboundary\",\n  \"addcats\",\n  \"addCause\",\n  \"addedge\",\n  \"addmulti\",\n  \"addnode\",\n  \"addpoints\",\n  \"addRequired\",\n  \"addsample\",\n  \"addsampletocollection\",\n  \"addts\",\n  \"adjacency\",\n  \"align\",\n  \"alim\",\n  \"alpha\",\n  \"alphamap\",\n  \"alphaShape\",\n  \"alphaSpectrum\",\n  \"alphaTriangulation\",\n  \"animatedline\",\n  \"animatedLine\",\n  \"append\",\n  \"array2timetable\",\n  \"barycentricToCartesian\",\n  \"bctree\",\n  \"bench\",\n  \"between\",\n  \"bfsearch\",\n  \"bicgstabl\",\n  \"biconncomp\",\n  \"binary\",\n  \"binscatter\",\n  \"bitnot\",\n  \"boundary\",\n  \"boundaryFacets\",\n  \"boundingbox\",\n  \"brush\",\n  \"builddocsearchdb\",\n  \"bvp4c\",\n  \"bvp5c\",\n  \"bvpget\",\n  \"bvpinit\",\n  \"bvpset\",\n  \"bvpxtend\",\n  \"caldiff\",\n  \"calllib\",\n  \"callSoapService\",\n  \"camdolly\",\n  \"cameratoolbar\",\n  \"campan\",\n  \"camproj\",\n  \"cartesianToBarycentric\",\n  \"cartToBary\",\n  \"categories\",\n  \"cdf2rdf\",\n  \"cdfepoch\",\n  \"cdfinfo\",\n  \"cdflib\",\n  \"cdfread\",\n  \"cdfwrite\",\n  \"cellplot\",\n  \"centrality\",\n  \"centroid\",\n  \"checkcode\",\n  \"checkin\",\n  \"checkout\",\n  \"circumcenter\",\n  \"circumcenters\",\n  \"classUnderlying\",\n  \"clearCache\",\n  \"clearpoints\",\n  \"clipboard\",\n  \"clone\",\n  \"cmopts\",\n  \"collapse\",\n  \"colordef\",\n  \"colormapeditor\",\n  \"compose\",\n  \"condensation\",\n  \"coneplot\",\n  \"conncomp\",\n  \"contains\",\n  \"contourslice\",\n  \"convexHull\",\n  \"copyHDU\",\n  \"count\",\n  \"countcats\",\n  \"countEachLabel\",\n  \"createClassFromWsdl\",\n  \"createFile\",\n  \"createImg\",\n  \"createSoapMessage\",\n  \"createTbl\",\n  \"criticalAlpha\",\n  \"customverctrl\",\n  \"daqread\",\n  \"datacursormode\",\n  \"datastore\",\n  \"datatipinfo\",\n  \"dateshift\",\n  \"day\",\n  \"dbmex\",\n  \"dde23\",\n  \"ddeget\",\n  \"ddensd\",\n  \"ddesd\",\n  \"ddeset\",\n  \"decomposition\",\n  \"degree\",\n  \"delaunayTriangulation\",\n  \"deleteCol\",\n  \"deleteFile\",\n  \"deleteHDU\",\n  \"deleteKey\",\n  \"deleteproperty\",\n  \"deleteRecord\",\n  \"deleteRows\",\n  \"delevent\",\n  \"DelimitedTextImportOptions\",\n  \"delsample\",\n  \"delsamplefromcollection\",\n  \"depdir\",\n  \"depfun\",\n  \"details\",\n  \"detectImportOptions\",\n  \"deval\",\n  \"dfsearch\",\n  \"digraph\",\n  \"discretize\",\n  \"dissect\",\n  \"distances\",\n  \"docsearch\",\n  \"dragrect\",\n  \"duration\",\n  \"dynamicprops\",\n  \"echodemo\",\n  \"edgeAttachments\",\n  \"edges\",\n  \"empty\",\n  \"enableservice\",\n  \"enumeration\",\n  \"eraseBetween\",\n  \"eventlisteners\",\n  \"events\",\n  \"exceltime\",\n  \"Execute\",\n  \"export2wsdlg\",\n  \"exportsetupdlg\",\n  \"extractAfter\",\n  \"extractBefore\",\n  \"extractBetween\",\n  \"faceNormal\",\n  \"faceNormals\",\n  \"fcontour\",\n  \"featureEdges\",\n  \"Feval\",\n  \"fewerbins\",\n  \"figurepalette\",\n  \"FileDatastore\",\n  \"filemarker\",\n  \"fileMode\",\n  \"fileName\",\n  \"filloutliers\",\n  \"fimplicit\",\n  \"fimplicit3\",\n  \"findedge\",\n  \"findgroups\",\n  \"findnode\",\n  \"findprop\",\n  \"fitsdisp\",\n  \"fitsinfo\",\n  \"fitsread\",\n  \"fitswrite\",\n  \"FixedWidthImportOptions\",\n  \"flipedge\",\n  \"flow\",\n  \"fmesh\",\n  \"fplot3\",\n  \"freeBoundary\",\n  \"freqspace\",\n  \"fsurf\",\n  \"FunctionTestCase\",\n  \"functiontests\",\n  \"funm\",\n  \"gather\",\n  \"gcmr\",\n  \"geobubble\",\n  \"geolimits\",\n  \"getabstime\",\n  \"getAColParms\",\n  \"getaudiodata\",\n  \"getBColParms\",\n  \"GetCharArray\",\n  \"getColName\",\n  \"getColType\",\n  \"getConstantValue\",\n  \"getdatasamples\",\n  \"getdatasamplesize\",\n  \"getEqColType\",\n  \"getFileFormats\",\n  \"GetFullMatrix\",\n  \"getHdrSpace\",\n  \"getHDUnum\",\n  \"getHDUtype\",\n  \"getImgSize\",\n  \"getImgType\",\n  \"getinterpmethod\",\n  \"getnext\",\n  \"getNumCols\",\n  \"getNumHDUs\",\n  \"getNumInputs\",\n  \"getNumOutputs\",\n  \"getNumRows\",\n  \"getOpenFiles\",\n  \"getpoints\",\n  \"getProfiles\",\n  \"getqualitydesc\",\n  \"getReport\",\n  \"getsamples\",\n  \"getsampleusingtime\",\n  \"gettimeseriesnames\",\n  \"gettsafteratevent\",\n  \"gettsafterevent\",\n  \"gettsatevent\",\n  \"gettsbeforeatevent\",\n  \"gettsbeforeevent\",\n  \"gettsbetweenevents\",\n  \"GetVariable\",\n  \"getvaropts\",\n  \"getVersion\",\n  \"GetWorkspaceData\",\n  \"gobjects\",\n  \"graph\",\n  \"GraphPlot\",\n  \"graymon\",\n  \"griddedInterpolant\",\n  \"guide\",\n  \"h5create\",\n  \"h5disp\",\n  \"h5info\",\n  \"h5read\",\n  \"h5readatt\",\n  \"h5write\",\n  \"h5writeatt\",\n  \"handle\",\n  \"hasdata\",\n  \"hasFrame\",\n  \"hasnext\",\n  \"hdf5info\",\n  \"hdf5read\",\n  \"hdf5write\",\n  \"hdfan\",\n  \"hdfdf24\",\n  \"hdfdfr8\",\n  \"hdfh\",\n  \"hdfhd\",\n  \"hdfhe\",\n  \"hdfhx\",\n  \"hdfinfo\",\n  \"hdfml\",\n  \"hdfpt\",\n  \"hdfread\",\n  \"hdftool\",\n  \"hdfv\",\n  \"hdfvf\",\n  \"hdfvh\",\n  \"hdfvs\",\n  \"head\",\n  \"heatmap\",\n  \"helpbrowser\",\n  \"helpdesk\",\n  \"helpwin\",\n  \"hgexport\",\n  \"hgsetget\",\n  \"highlight\",\n  \"histcounts\",\n  \"histcounts2\",\n  \"histogram\",\n  \"histogram2\",\n  \"hms\",\n  \"holes\",\n  \"hour\",\n  \"idealfilter\",\n  \"im2java\",\n  \"ImageDatastore\",\n  \"imapprox\",\n  \"imgCompress\",\n  \"import\",\n  \"imresize\",\n  \"incenter\",\n  \"incenters\",\n  \"incidence\",\n  \"indegree\",\n  \"inmem\",\n  \"innerjoin\",\n  \"inOutStatus\",\n  \"insertAfter\",\n  \"insertATbl\",\n  \"insertBefore\",\n  \"insertBTbl\",\n  \"insertCol\",\n  \"insertImg\",\n  \"insertRows\",\n  \"inShape\",\n  \"inspect\",\n  \"instrcallback\",\n  \"instrfind\",\n  \"instrfindall\",\n  \"interfaces\",\n  \"interp1q\",\n  \"interpstreamspeed\",\n  \"invoke\",\n  \"isaUnderlying\",\n  \"isbetween\",\n  \"iscategory\",\n  \"ischange\",\n  \"iscom\",\n  \"isCompressedImg\",\n  \"isConnected\",\n  \"isdag\",\n  \"isdst\",\n  \"isEdge\",\n  \"isenum\",\n  \"isevent\",\n  \"ishole\",\n  \"isIllConditioned\",\n  \"isinterface\",\n  \"isinterior\",\n  \"isInterior\",\n  \"isisomorphic\",\n  \"islocalmax\",\n  \"islocalmin\",\n  \"isLocked\",\n  \"isomorphism\",\n  \"isordinal\",\n  \"isprotected\",\n  \"isregular\",\n  \"issimplified\",\n  \"issortedrows\",\n  \"isStringScalar\",\n  \"istall\",\n  \"istimetable\",\n  \"isundefined\",\n  \"isvalid\",\n  \"isweekend\",\n  \"javaMethodEDT\",\n  \"javaObjectEDT\",\n  \"join\",\n  \"juliandate\",\n  \"labeledge\",\n  \"labelnode\",\n  \"lag\",\n  \"laplacian\",\n  \"last\",\n  \"layout\",\n  \"ldl\",\n  \"libfunctions\",\n  \"libfunctionsview\",\n  \"libisloaded\",\n  \"libpointer\",\n  \"libstruct\",\n  \"linkdata\",\n  \"loadlibrary\",\n  \"lsqminnorm\",\n  \"lsqr\",\n  \"makehgtform\",\n  \"mapreduce\",\n  \"mapreducer\",\n  \"matfile\",\n  \"maxflow\",\n  \"MaximizeCommandWindow\",\n  \"maxk\",\n  \"memmapfile\",\n  \"MemoizedFunction\",\n  \"mergecats\",\n  \"meta.abstractDetails\",\n  \"meta.DynamicProperty\",\n  \"meta.EnumeratedValue\",\n  \"meta.MetaData\",\n  \"methodsview\",\n  \"MException\",\n  \"milliseconds\",\n  \"MinimizeCommandWindow\",\n  \"mink\",\n  \"minres\",\n  \"minspantree\",\n  \"minute\",\n  \"mlint\",\n  \"mlintrpt\",\n  \"mmfileinfo\",\n  \"month\",\n  \"morebins\",\n  \"movAbsHDU\",\n  \"move\",\n  \"movie2avi\",\n  \"movNamHDU\",\n  \"movRelHDU\",\n  \"mput\",\n  \"multibandread\",\n  \"multibandwrite\",\n  \"nccreate\",\n  \"ncdisp\",\n  \"ncinfo\",\n  \"ncread\",\n  \"ncreadatt\",\n  \"ncwrite\",\n  \"ncwriteatt\",\n  \"ncwriteschema\",\n  \"nearest\",\n  \"nearestNeighbor\",\n  \"neighbors\",\n  \"netcdf\",\n  \"noanimate\",\n  \"notebook\",\n  \"notify\",\n  \"nsidedpoly\",\n  \"num2ruler\",\n  \"numArgumentsFromSubscript\",\n  \"numboundaries\",\n  \"numedges\",\n  \"numnodes\",\n  \"numpartitions\",\n  \"numRegions\",\n  \"numsides\",\n  \"ode113\",\n  \"ode23t\",\n  \"ode23tb\",\n  \"odextend\",\n  \"openFile\",\n  \"opengl\",\n  \"outdegree\",\n  \"outerjoin\",\n  \"pad\",\n  \"pagesetupdlg\",\n  \"parse\",\n  \"parseSoapResponse\",\n  \"partition\",\n  \"parula\",\n  \"path2rc\",\n  \"pathtool\",\n  \"pcode\",\n  \"pdepe\",\n  \"pdeval\",\n  \"perimeter\",\n  \"plotbrowser\",\n  \"plotedit\",\n  \"plottools\",\n  \"pointLocation\",\n  \"polaraxes\",\n  \"polarhistogram\",\n  \"polarplot\",\n  \"polarscatter\",\n  \"polybuffer\",\n  \"polyshape\",\n  \"posixtime\",\n  \"predecessors\",\n  \"preview\",\n  \"printdlg\",\n  \"printopt\",\n  \"printpreview\",\n  \"profsave\",\n  \"propedit\",\n  \"propertyeditor\",\n  \"PutCharArray\",\n  \"PutFullMatrix\",\n  \"PutWorkspaceData\",\n  \"pyargs\",\n  \"pyversion\",\n  \"quarter\",\n  \"Quit\",\n  \"RandStream\",\n  \"rbbox\",\n  \"readall\",\n  \"readasync\",\n  \"readATblHdr\",\n  \"readBTblHdr\",\n  \"readCard\",\n  \"readCol\",\n  \"readFrame\",\n  \"readimage\",\n  \"readImg\",\n  \"readKey\",\n  \"readKeyCmplx\",\n  \"readKeyDbl\",\n  \"readKeyLongLong\",\n  \"readKeyLongStr\",\n  \"readKeyUnit\",\n  \"readRecord\",\n  \"readtable\",\n  \"recordblocking\",\n  \"regions\",\n  \"registerevent\",\n  \"regmatlabserver\",\n  \"release\",\n  \"Remove\",\n  \"RemoveAll\",\n  \"removecats\",\n  \"removets\",\n  \"renamecats\",\n  \"reordercats\",\n  \"reordernodes\",\n  \"replace\",\n  \"replaceBetween\",\n  \"resample\",\n  \"retime\",\n  \"reverse\",\n  \"rlim\",\n  \"rmboundary\",\n  \"rmedge\",\n  \"rmholes\",\n  \"rmnode\",\n  \"rmslivers\",\n  \"rowfun\",\n  \"rtickangle\",\n  \"rtickformat\",\n  \"rticklabels\",\n  \"ruler2num\",\n  \"runperf\",\n  \"scale\",\n  \"scatteredInterpolant\",\n  \"scroll\",\n  \"second\",\n  \"selectmoveresize\",\n  \"sendmail\",\n  \"serial\",\n  \"serialbreak\",\n  \"seriallist\",\n  \"setabstime\",\n  \"setBscale\",\n  \"setcats\",\n  \"setCompressionType\",\n  \"setHCompScale\",\n  \"setHCompSmooth\",\n  \"setinterpmethod\",\n  \"setpixelposition\",\n  \"setTileDim\",\n  \"settimeseriesnames\",\n  \"setTscale\",\n  \"setuniformtime\",\n  \"setvaropts\",\n  \"setvartype\",\n  \"sheetnames\",\n  \"shortestpath\",\n  \"shortestpathtree\",\n  \"showplottool\",\n  \"shuffle\",\n  \"simplify\",\n  \"smoothdata\",\n  \"snapnow\",\n  \"sortboundaries\",\n  \"sortregions\",\n  \"sortx\",\n  \"sorty\",\n  \"split\",\n  \"splitapply\",\n  \"splitEachLabel\",\n  \"splitlines\",\n  \"SpreadsheetDatastore\",\n  \"SpreadsheetImportOptions\",\n  \"ss2tf\",\n  \"stack\",\n  \"standardizeMissing\",\n  \"stats\",\n  \"step\",\n  \"stopasync\",\n  \"str2mat\",\n  \"streamparticles\",\n  \"streamslice\",\n  \"string\",\n  \"strings\",\n  \"strip\",\n  \"strlength\",\n  \"struct2table\",\n  \"subgraph\",\n  \"subtract\",\n  \"subvolume\",\n  \"successors\",\n  \"summary\",\n  \"superclasses\",\n  \"support\",\n  \"supportPackageInstaller\",\n  \"surf2patch\",\n  \"surfaceArea\",\n  \"symmlq\",\n  \"synchronize\",\n  \"syntax\",\n  \"table2timetable\",\n  \"TabularTextDatastore\",\n  \"tail\",\n  \"tall\",\n  \"TallDatastore\",\n  \"tallrng\",\n  \"targetupdater\",\n  \"tcpclient\",\n  \"Test\",\n  \"TestResult\",\n  \"testsuite\",\n  \"texlabel\",\n  \"textwrap\",\n  \"tfqmr\",\n  \"thetalim\",\n  \"thetatickformat\",\n  \"thetaticklabels\",\n  \"throw\",\n  \"throwAsCaller\",\n  \"Tiff\",\n  \"timeit\",\n  \"timeofday\",\n  \"timer\",\n  \"timerange\",\n  \"timeseries\",\n  \"timetable\",\n  \"timetable2table\",\n  \"timezones\",\n  \"todatenum\",\n  \"toolboxdir\",\n  \"topkrows\",\n  \"toposort\",\n  \"transclosure\",\n  \"translate\",\n  \"transreduction\",\n  \"triangulation\",\n  \"TriRep\",\n  \"TriScatteredInterp\",\n  \"tscollection\",\n  \"tzoffset\",\n  \"uialert\",\n  \"uiaxes\",\n  \"uibutton\",\n  \"uicheckbox\",\n  \"uiconfirm\",\n  \"uidropdown\",\n  \"uieditfield\",\n  \"uigauge\",\n  \"uigetpref\",\n  \"uiimport\",\n  \"uiknob\",\n  \"uilabel\",\n  \"uilamp\",\n  \"uilistbox\",\n  \"uiopen\",\n  \"uiradiobutton\",\n  \"uisave\",\n  \"uisetcolor\",\n  \"uisetpref\",\n  \"uislider\",\n  \"uispinner\",\n  \"uistack\",\n  \"uiswitch\",\n  \"uitab\",\n  \"uitabgroup\",\n  \"uitextarea\",\n  \"uitogglebutton\",\n  \"uitree\",\n  \"uitreenode\",\n  \"undocheckout\",\n  \"unloadlibrary\",\n  \"unmesh\",\n  \"unregisterallevents\",\n  \"unregisterevent\",\n  \"unstack\",\n  \"upgradePreviouslyInstalledSupportPackages\",\n  \"userpath\",\n  \"ValueIterator\",\n  \"varfun\",\n  \"verctrl\",\n  \"vertexAttachments\",\n  \"vertexNormal\",\n  \"VideoReader\",\n  \"VideoWriter\",\n  \"viewmtx\",\n  \"visdiff\",\n  \"volume\",\n  \"volumebounds\",\n  \"voronoiDiagram\",\n  \"websave\",\n  \"week\",\n  \"whatsnew\",\n  \"winopen\",\n  \"withtol\",\n  \"wordcloud\",\n  \"write\",\n  \"writeChecksum\",\n  \"writeCol\",\n  \"writeComment\",\n  \"writeDate\",\n  \"writeHistory\",\n  \"writeImg\",\n  \"writeKey\",\n  \"writeKeyUnit\",\n  \"writetable\",\n  \"writeVideo\",\n  \"xmlread\",\n  \"xmlwrite\",\n  \"xslt\",\n  \"xtickformat\",\n  \"year\",\n  \"ymd\",\n  \"ytickformat\",\n  \"yyaxis\",\n  \"yyyymmdd\",\n  \"ztickformat\",\n  };\n\n  rlist = list;\n\nendfunction\n\n\n%!test\n%! str = __unimplemented__ (\"no_name_function\");\n%! assert (isempty (str));\n\n%!test\n%! str = __unimplemented__ (\"matlabrc\");\n%! assert (regexp (str, \".matlabrc. is not implemented\\.  Octave uses the file .\\.octaverc..instead\\.\"));\n\n%!test\n%! str = __unimplemented__ (\"MException\");\n%! assert (regexp (str, \"The .MException. function is not yet implemented in Octave\"));\n"
  },
  {
    "path": "scripts/help/ans.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @defvr {Automatic Variable} ans\n## The most recently computed result that was not explicitly assigned to a\n## variable.\n##\n## For example, after the expression\n##\n## @example\n## 3^2 + 4^2\n## @end example\n##\n## @noindent\n## is evaluated, the value returned by @code{ans} is 25.\n## @end defvr\n\n\n## Mark file as being tested.  No real test needed for a documentation .m file\n%!assert (1)\n"
  },
  {
    "path": "scripts/help/bessel.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{J}, @var{ierr}] =} besselj (@var{alpha}, @var{x}, @var{opt})\n## @deftypefnx {} {[@var{Y}, @var{ierr}] =} bessely (@var{alpha}, @var{x}, @var{opt})\n## @deftypefnx {} {[@var{I}, @var{ierr}] =} besseli (@var{alpha}, @var{x}, @var{opt})\n## @deftypefnx {} {[@var{K}, @var{ierr}] =} besselk (@var{alpha}, @var{x}, @var{opt})\n## @deftypefnx {} {[@var{H}, @var{ierr}] =} besselh (@var{alpha}, @var{k}, @var{x}, @var{opt})\n## Compute Bessel or Hankel functions of various kinds.\n##\n## All functions begin with the prefix @qcode{\"bessel\"}.  The list of\n## functions is:\n##\n## @table @code\n## @item besselj\n## Bessel functions of the first kind.  If the argument @var{opt} is supplied,\n## the result is multiplied by @code{exp (-abs (imag (x)))}.\n##\n## @item bessely\n## Bessel functions of the second kind.  If the argument @var{opt} is supplied,\n## the result is multiplied by @w{@code{exp (-abs (imag (x)))}}.\n##\n## @item besseli\n## Modified Bessel functions of the first kind.  If the argument @var{opt} is\n## supplied, the result is multiplied by @w{@code{exp (-abs (real (x)))}}.\n##\n## @item besselk\n## Modified Bessel functions of the second kind.  If the argument @var{opt} is\n## supplied, the result is multiplied by @w{@code{exp (x)}}.\n##\n## @item besselh\n## Compute Hankel functions of the first (@var{k} = 1) or second (@var{k} = 2)\n## kind.  If the argument @var{opt} is supplied, the result is multiplied by\n## @w{@code{exp (-I*@var{x})}}@ for @var{k} = 1 or\n## @w{@code{exp (I*@var{x})}}@ for @var{k} = 2.\n## @end table\n##\n## If @var{alpha} is a scalar, the result is the same size as @var{x}.  If\n## @var{x} is a scalar, the result is the same size as @var{alpha}.  If\n## @var{alpha} is a row vector and @var{x} is a column vector, the result is\n## a matrix with @code{length (@var{x})} rows and @code{length\n## (@var{alpha})} columns.  Otherwise, @var{alpha} and @var{x} must conform\n## and the result will be the same size.\n##\n## The order of the Bessel function @var{alpha} must be real.  The points for\n## evaluation @var{x} may be complex.\n##\n## If requested, @var{ierr} contains the following status information and is\n## the same size as the result.\n##\n## @enumerate 0\n## @item\n## Normal return.\n##\n## @item\n## Input error, return @code{NaN}.\n##\n## @item\n## Overflow, return @code{Inf}.\n##\n## @item\n## Loss of significance by argument reduction results in less than half of\n## machine accuracy.\n##\n## @item\n## Loss of significance by argument reduction, output may be inaccurate.\n##\n## @item\n## Error---no computation, algorithm termination condition not met, return\n## @code{NaN}.\n## @end enumerate\n##\n## @seealso{besselj, bessely, besseli, besselk, besselh}\n## @end deftypefn\n\nfunction bessel ()\n  error (\"bessel: you must use besselj, bessely, besseli, besselk, or besselh\\n\");\nendfunction\n\n\n%!error <you must use besselj, ...> bessel ()\n"
  },
  {
    "path": "scripts/help/debug.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} debug ()\n## Summary of debugging commands.\n##\n## For more information on each command and available options use\n## @code{help CMD}.\n##\n## The debugging commands available in Octave are\n##\n## @table @code\n## @item dbstop\n## Add a breakpoint.\n##\n## @item dbclear\n## Remove a breakpoint.\n##\n## @item dbstatus\n## List all breakpoints.\n##\n## @item dbwhere\n## Report the current file and line number where execution is stopped.\n##\n## @item dbtype\n## Display the code of the function being debugged, enumerating\n## the line numbers.\n##\n## @item dblist\n## List 10 lines of code centered around the line number where execution is\n## stopped.\n##\n## @item  dbstep\n## @itemx dbnext\n## Execute (step) one or more lines, follow execution into (step into) a\n## function call, or execute until the end of a function (step out), and\n## re-enter debug mode.\n##\n## @item dbcont\n## Continue normal code execution from the debug prompt.\n##\n## @item dbquit\n## Quit debugging mode immediately and return to the main prompt.\n##\n## @item dbstack\n## Print a backtrace of the execution stack.\n##\n## @item dbup\n## Move up the execution stack.\n##\n## @item dbdown\n## Move down the execution stack.\n##\n## @item keyboard\n## Force entry into debug mode from an m-file.\n##\n## @item debug_on_error\n## Configure whether Octave enters debug mode when it encounters an error.\n##\n## @item debug_on_warning\n## Configure whether Octave enters debug mode when it encounters a warning.\n##\n## @item debug_on_interrupt\n## Configure whether Octave enters debug mode when it encounters an interrupt.\n##\n## @item isdebugmode\n## Return true if in debug mode.\n## @end table\n##\n## @noindent\n## When Octave encounters a breakpoint, or other reason to enter debug mode,\n## the prompt changes to @qcode{\"debug>\"}.  The workspace of the function\n## where the breakpoint was encountered becomes available and any Octave\n## command that is valid in that workspace context may be executed.\n##\n## @seealso{dbstop, dbclear, dbstatus, dbwhere, dbtype, dbcont, dbquit,\n## dbstack, dbup, dbdown, keyboard, debug_on_error, debug_on_warning,\n## debug_on_interrupt, isdebugmode}\n## @end deftypefn\n\nfunction debug ()\n  help (\"debug\");\nendfunction\n\n\n## Mark file as being tested.  No real test needed for a documentation .m file\n%!assert (1)\n"
  },
  {
    "path": "scripts/help/doc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} doc @var{function_name}\n## @deftypefnx {} {} doc\n## Display documentation for the function @var{function_name} directly from an\n## online version of the printed manual, using the GNU Info browser.\n##\n## If invoked without an argument, the manual is shown from the beginning.\n##\n## For example, the command @kbd{doc rand} starts the GNU Info browser at the\n## @code{rand} node in the online version of the manual.\n##\n## Once the GNU Info browser is running, help for using it is available using\n## the command @kbd{C-h}.\n## @seealso{help}\n## @end deftypefn\n\nfunction retval = doc (function_name)\n\n  if (nargin == 1)\n    if (! ischar (function_name))\n      error (\"doc: FUNCTION_NAME must be a string\");\n    endif\n    ftype = exist (function_name);\n  else\n    function_name = \"\";\n    ftype = 0;\n  endif\n\n  ## Give event manager the first shot.\n\n  status = ! __event_manager_show_documentation__ (function_name);\n\n  if (status)\n\n    if (ftype == 2 || ftype == 3)\n      ffile = which (function_name);\n    else\n      ffile = \"\";\n    endif\n\n    if (isempty (ffile))\n      info_dir = __octave_config_info__ (\"infodir\");\n    else\n      info_dir = fileparts (ffile);\n    endif\n\n    ## Determine if a file called doc.info exist in the same\n    ## directory as the function.\n    info_file_name = fullfile (info_dir, \"doc.info\");\n\n    [~, err] = stat (info_file_name);\n\n    if (err < 0)\n      info_file_name = info_file ();\n\n      if (! exist (info_file_name, \"file\")\n          && ! exist ([info_file_name \".gz\"], \"file\")\n          && ! exist ([info_file_name \".bz2\"], \"file\"))\n        __gripe_missing_component__ (\"doc\", \"info-file\");\n      endif\n    endif\n\n    ## FIXME: Don't change the order of the arguments below because\n    ## the info-emacs-info script currently expects --directory DIR as\n    ## the third and fourth arguments.  Someone should fix that.\n    cmd = sprintf ('\"%s\" --file \"%s\" --directory \"%s\"',\n                   info_program (), info_file_name, info_dir);\n\n    have_fname = ! isempty (function_name);\n\n    if (have_fname)\n      status = system (sprintf ('%s --index-search \"%s\"', cmd, function_name));\n    endif\n\n    if (! (have_fname && status == 0))\n      status = system (cmd);\n      if (status == 127)\n        warning (\"doc: unable to find info program '%s'\", info_program ());\n      endif\n    endif\n\n  endif\n\n  if (nargout > 0)\n    retval = status;\n  endif\n\nendfunction\n\n\n%!testif ENABLE_DOCS\n%! ifile = info_file ();\n%! if (exist (ifile) != 2 && exist (sprintf (\"%s.gz\", ifile)) != 2)\n%!   error (\"Info file %s or %s.gz does not exist!\", ifile, ifile);\n%! endif\n"
  },
  {
    "path": "scripts/help/doc_cache_create.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} doc_cache_create (@var{out_file}, @var{directory})\n## @deftypefnx {} {} doc_cache_create (@var{out_file})\n## @deftypefnx {} {} doc_cache_create ()\n## Generate documentation cache for all functions in @var{directory}.\n##\n## A documentation cache is generated for all functions in @var{directory}\n## which may be a single string or a cell array of strings.  The cache is used\n## to speed up the function @code{lookfor}.\n##\n## The cache is saved in the file @var{out_file} which defaults to the value\n## @file{doc-cache} if not given.\n##\n## If no directory is given (or it is the empty matrix), a cache for built-in\n## functions, operators, and keywords is generated.\n##\n## @seealso{doc_cache_file, lookfor, path}\n## @end deftypefn\n\nfunction doc_cache_create (out_file = \"doc-cache\", directory = [])\n\n  ## Check input\n  if (! ischar (out_file))\n    print_usage ();\n  endif\n\n  ## Generate cache\n  if (isempty (directory))\n    cache = gen_builtin_cache ();\n  elseif (iscell (directory))\n    if (all (cellfun (\"isclass\", directory, \"char\")))\n      cache = gen_doc_cache_in_dir (directory);\n    else\n      error (\"doc_cache_create: cell must contain only strings\");\n    endif\n  elseif (ischar (directory))\n     cache = gen_doc_cache_in_dir (directory);\n  else\n     error (\"doc_cache_create: second input argument must be a string or a cell of strings\");\n  endif\n\n  ## Save cache\n  if (! isempty (cache))\n     save_header_format_string ([\"# doc-cache created by Octave \" OCTAVE_VERSION], \"local\");\n     save (\"-text\", out_file, \"cache\");\n  endif\n\nendfunction\n\nfunction [text, first_sentence, status] = handle_function (f, text, format)\n\n  first_sentence = \"\";\n  ## Skip internal functions starting with \"__\"\n  if (strncmp (f, \"__\", 2))\n    status = 1;\n    return;\n  endif\n\n  ## Take action depending on help text format\n  switch (lower (format))\n    case \"plain text\"\n      status = 0;\n    case \"texinfo\"\n      [text, status] = __makeinfo__ (text, \"plain text\");\n    case \"html\"\n      [text, status] = strip_html_tags (text);\n    otherwise\n      status = 1;\n  endswitch\n\n  ## Did we get the help text?\n  if (status != 0 || isempty (text))\n    warning (\"doc_cache_create: unusable help text found in file '%s'\", f);\n    return;\n  endif\n\n  ## Get first sentence of help text\n  first_sentence = get_first_help_sentence (f);\n\nendfunction\n\nfunction cache = create_cache (list)\n\n  cache = {};\n\n  ## For each function:\n  for n = 1:length (list)\n    f = list{n};\n\n    ## Get help text\n    [text, format] = get_help_text (f);\n\n    [text, first_sentence, status] = handle_function (f, text, format);\n\n    ## Did we get the help text?\n    if (status != 0)\n      continue;\n    endif\n\n    ## Store the help text\n    cache(1, end+1) = f;\n    cache(2, end) = text;\n    cache(3, end) = first_sentence;\n  endfor\n\nendfunction\n\nfunction cache = gen_doc_cache_in_dir (directory)\n\n  ## If 'directory' is not in the current path, add it so we search it\n  dir_in_path = ismember (directory, ostrsplit (path (), pathsep ()));\n\n  ## dirs not in path\n  if (! iscell (directory))\n    directory = {directory};\n  endif\n  dirs_notpath = {directory{! dir_in_path}};\n\n  ## add them\n  if (! isempty (dirs_notpath))\n    addpath (dirs_notpath{:});\n  endif\n\n  ## create cache\n  f_lsfcn = @(dir) create_cache (__list_functions__ (dir));\n  cache = cellfun (f_lsfcn, directory, \"UniformOutput\", false);\n\n  ## concatenate results\n  cache = [cache{:}];\n\n  ## remove dirs from path\n  if (! isempty (dirs_notpath))\n    rmpath (dirs_notpath{:});\n  endif\n\nendfunction\n\nfunction cache = gen_builtin_cache ()\n\n  operators = __operators__ ();\n  keywords = __keywords__ ();\n  builtins = __builtins__ ();\n  list = {operators{:}, keywords{:}, builtins{:}};\n\n  cache = create_cache (list);\n\nendfunction\n\n\n## No true tests desirable for this function.\n## Test input validation\n%!error doc_cache_create (1)\n"
  },
  {
    "path": "scripts/help/error_ids.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @cindex error ids\n##\n## @table @code\n## @item Octave:bad-alloc\n## Indicates that memory couldn't be allocated.\n##\n## @item Octave:invalid-context\n## Indicates the error was generated by an operation that cannot be executed in\n## the scope from which it was called.  For example, the function\n## @code{print_usage ()} when called from the Octave prompt raises this error.\n##\n## @item Octave:invalid-fun-call\n## Indicates that a function was called in an incorrect way, e.g., wrong number\n## of input arguments.\n##\n## @item Octave:invalid-indexing\n## Indicates that a data-type was indexed incorrectly, e.g., real-value index\n## for arrays, nonexistent field of a structure.\n##\n## @item Octave:invalid-input-arg\n## Indicates that a function was called with invalid input arguments.\n##\n## @item Octave:parse-error\n## The interpreter failed to parse (read) specified code.\n##\n## @item Octave:undefined-function\n## Indicates a call to a function that is not defined.  The function may exist\n## but Octave is unable to find it in the search path.\n##\n## @end table\n##\n\nfunction error_ids ()\n  help (\"error_ids\");\nendfunction\n\n\n## Mark file as being tested.  No real test needed for a documentation .m file\n%!assert (1)\n"
  },
  {
    "path": "scripts/help/get_first_help_sentence.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{text} =} get_first_help_sentence (@var{name})\n## @deftypefnx {} {@var{text} =} get_first_help_sentence (@var{name}, @var{max_len})\n## @deftypefnx {} {[@var{text}, @var{status}] =} get_first_help_sentence (@dots{})\n## Return the first sentence of a function's help text.\n##\n## The first sentence is defined as the text after the function declaration\n## until either the first period (\".\") or the first appearance of two\n## consecutive newlines (\"\\n\\n\").  The text is truncated to a maximum length of\n## @var{max_len}, which defaults to 80.  If the text must be truncated the last\n## three characters of the text are replaced with @qcode{\"...\"} to indicate\n## that more text was available.\n##\n## The optional output argument @var{status} returns the status reported by\n## @code{makeinfo}.  If only one output argument is requested, and @var{status}\n## is nonzero, a warning is displayed.\n##\n## As an example, the first sentence of this help text is\n##\n## @example\n## @group\n## get_first_help_sentence (\"get_first_help_sentence\")\n## @print{} ans = Return the first sentence of a function's help text.\n## @end group\n## @end example\n## @end deftypefn\n\nfunction [text, status] = get_first_help_sentence (name, max_len = 80)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (name))\n    error (\"get_first_help_sentence: NAME must be a string\");\n  endif\n\n  if (! isnumeric (max_len) || max_len <= 0 || max_len != fix (max_len))\n    error (\"get_first_help_sentence: MAX_LEN must be positive integer\");\n  endif\n\n  ## First, we get the raw help text\n  [help_text, format] = get_help_text (name);\n\n  ## Then, we take action depending on the format\n  switch (lower (format))\n    case \"plain text\"\n      [text, status] = first_sentence_plain_text (help_text, max_len);\n    case \"texinfo\"\n      [text, status] = first_sentence_texinfo (help_text, max_len);\n    case \"html\"\n      [text, status] = first_sentence_html (help_text, max_len);\n    case \"not documented\"\n      error (\"get_first_help_sentence: '%s' is not documented\\n\", name);\n    case \"not found\"\n      error (\"get_first_help_sentence: '%s' not found\\n\", name);\n    otherwise\n      error (\"get_first_help_sentence: internal error: unsupported help text format: '%s'\\n\", format);\n  endswitch\n\n  if (nargout <= 1 && status != 0)\n    warning (\"get_first_help_sentence: couldn't run makeinfo on '%s'\", name);\n  endif\n\nendfunction\n\n# This function extracts a snippet of an UTF-8 encoded string\nfunction out_text = extract_first_codepoints (in_text, count)\n  out_text = in_text(1 : find (unicode_idx (in_text) == count, 1, 'last'));\nendfunction\n\n## This function extracts the first sentence from a plain text help text\nfunction [text, status] = first_sentence_plain_text (help_text, max_len)\n\n  ## Extract first line by searching for a period followed by whitespace\n  ## followed by a capital letter (Nearly the same rule as Texinfo).\n  period_idx = regexp (help_text, '\\.\\s+(?:[A-Z]|\\n)', \"once\");\n  ## ... or a double end-of-line (we subtract 1 because we are not interested\n  ## in capturing the first newline).\n  line_end_idx = regexp (help_text, \"\\n\\n\", \"once\") - 1;\n  help_len = length (help_text);\n  min_idx = min ([period_idx, line_end_idx, help_len]);\n  if (min_idx < max_len)\n    text = extract_first_codepoints (help_text, min_idx);\n  else\n    if (max_len > 3)\n      text = extract_first_codepoints (help_text, max_len-3);\n      text = [text, \"...\"];\n    else\n      text = extract_first_codepoints (help_text, max_len);\n    endif\n  endif\n\n  status = 0;\n\nendfunction\n\n## This function extracts the first sentence from a Texinfo help text.\n## The function works by removing @def* from the texinfo text.  After this, we\n## render the text to plain text using makeinfo, and then extract the first\n## line.\nfunction [text, status] = first_sentence_texinfo (help_text, max_len)\n\n  ## Lines ending with \"@\\n\" are continuation lines, so they should be\n  ## concatenated with the following line.\n  help_text = strrep (help_text, \"@\\n\", \" \");\n\n  ## Find, and remove, lines that start with @def.  This should remove things\n  ## such as @deftypefn, @deftypefnx, @defvar, etc.\n  keep = true (size (help_text));\n  def_idx = strfind (help_text, \"@def\");\n  if (! isempty (def_idx))\n    endl_idx = find (help_text == \"\\n\");\n    for k = 1:length (def_idx)\n      endl = endl_idx(find (endl_idx > def_idx(k), 1));\n      if (isempty (endl))\n        endl = numel (keep);\n      endif\n      keep(def_idx(k):endl) = false;\n    endfor\n\n    ## Remove the @end ... that corresponds to the @def we removed above\n    def1 = def_idx(1);\n    space_idx = find (help_text == \" \");\n    space_idx = space_idx(find (space_idx > def1, 1));\n    bracket_idx = find (help_text == \"{\" | help_text == \"}\");\n    bracket_idx = bracket_idx(find (bracket_idx > def1, 1));\n    if (isempty (space_idx) && isempty (bracket_idx))\n      error (\"get_first_help_sentence: couldn't parse texinfo\");\n    endif\n    sep_idx = min (space_idx, bracket_idx);\n    def_type = help_text(def1+1:sep_idx-1);\n\n    end_idx = strfind (help_text, sprintf (\"@end %s\", def_type));\n    if (isempty (end_idx))\n      error (\"get_first_help_sentence: couldn't parse texinfo\");\n    endif\n    keep(end_idx(1):end) = false;\n\n    help_text = help_text(keep);\n  endif\n\n  ## Run makeinfo to generate plain text\n  [help_text, status] = __makeinfo__ (help_text, \"plain text\");\n\n  ## Extract first line with plain text method.\n  text = first_sentence_plain_text (help_text, max_len);\n\nendfunction\n\n## This function extracts the first sentence from a html help text.\n## The function simply removes the tags and treats the text as plain text.\nfunction [text, status] = first_sentence_html (help_text, max_len)\n\n  ## Strip tags\n  [help_text, status] = strip_html_tags (help_text);\n\n  ## Extract first line with plain text method.\n  text = first_sentence_plain_text (help_text, max_len);\n\nendfunction\n\n\n%!assert (regexp (get_first_help_sentence ('get_first_help_sentence'), ...\n%!                \"Return the first sentence of a function.s help text\\.\"))\n\n%!assert (get_first_help_sentence ('get_first_help_sentence', 28), ...\n%!        \"Return the first sentence...\")\n\n## Test input validation\n%!error <Invalid call> get_first_help_sentence ()\n%!error <NAME must be a string> get_first_help_sentence (1)\n%!error <MAX_LEN must be positive integer> get_first_help_sentence (\"ls\", \"a\")\n%!error <MAX_LEN must be positive integer> get_first_help_sentence (\"ls\", 0)\n%!error <MAX_LEN must be positive integer> get_first_help_sentence (\"ls\", 80.1)\n"
  },
  {
    "path": "scripts/help/help.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} help @var{name}\n## @deftypefnx {} {} help --list\n## @deftypefnx {} {} help .\n## @deftypefnx {} {} help\n## @deftypefnx {} {@var{help_text} =} help (@dots{})\n## Display the help text for @var{name}.\n##\n## For example, the command @kbd{help help} prints a short message describing\n## the @code{help} command.\n##\n## Given the single argument @code{--list}, list all operators, keywords,\n## built-in functions, and loadable functions available in the current session\n## of Octave.\n##\n## Given the single argument @code{.}, list all operators available in the\n## current session of Octave.\n##\n## If invoked without any arguments, @code{help} displays instructions on how\n## to access help from the command line.\n##\n## The help command can provide information about most operators, but\n## @var{name} must be enclosed by single or double quotes to prevent\n## the Octave interpreter from acting on @var{name}.  For example,\n## @code{help \"+\"} displays help on the addition operator.\n## @seealso{doc, lookfor, which, info}\n## @end deftypefn\n\nfunction retval = help (name)\n\n  if (nargin == 0)\n\n    text = \"\\n\\\n  For help with individual commands and functions type\\n\\\n\\n\\\n    help NAME\\n\\\n\\n\\\n  (replace NAME with the name of the command or function you would\\n\\\n  like to learn more about; for an operator, enclose \\\"NAME\\\" in quotes).\\n\\\n\\n\\\n  For a more detailed introduction to GNU Octave, consult the manual.\\n\\\n  The manual may be read from the prompt by typing\\n\\\n\\n\\\n    doc\\n\\\n\\n\\\n  GNU Octave is supported and developed by its user community.\\n\\\n  For more information visit https://www.octave.org.\\n\\n\";\n\n    if (nargout == 0)\n      puts (text);\n    else\n      retval = text;\n    endif\n\n  elseif (nargin == 1 && ischar (name))\n\n    if (strcmp (name, \"--list\"))\n      list = do_list_functions ();\n      if (nargout == 0)\n        printf (\"%s\", list);\n      else\n        retval = list;\n      endif\n      return;\n    endif\n\n    if (strcmp (name, \".\"))\n      list = do_list_operators ();\n      if (nargout == 0)\n        printf (\"%s\", list);\n      else\n        retval = list;\n      endif\n      return;\n    endif\n\n    ## Get help text\n    [text, format] = get_help_text (name);\n\n    ## Take action depending on help text format\n    switch (lower (format))\n      case \"plain text\"\n        status = 0;\n      case \"texinfo\"\n        [text, status] = __makeinfo__ (text, \"plain text\");\n      case \"html\"\n        [text, status] = strip_html_tags (text);\n      case \"not documented\"\n        error (\"help: '%s' is not documented\\n\", name);\n      case \"not found\"\n        do_contents (name);\n        return;\n      otherwise\n        error (\"help: internal error: unsupported help text format: '%s'\\n\", format);\n    endswitch\n\n    ## Print text\n    if (status != 0)\n      warning (\"help: Texinfo formatting filter exited abnormally; raw Texinfo source of help text follows...\\n\");\n    endif\n\n    if (nargout == 0)\n      if (! any (strcmp (name, {'./', '.\\', '...'})))\n        evalin (\"caller\", ['which (\"' undo_string_escapes(name) '\")']);\n      endif\n      printf (\"\\n%s\\n%s\", text, __additional_help_message__ ());\n    else\n      retval = text;\n    endif\n\n  else\n    error (\"help: invalid input\\n\");\n  endif\n\nendfunction\n\nfunction retval = do_list_operators ()\n  retval = sprintf (\"*** operators:\\n\\n%s\\n%s\\n\\n\",\n                    list_in_columns (__operators__ ()),\n                    [\"To obtain help on an operator, type\\n\"...\n                     \"      help \\\"NAME\\\"   or   help 'NAME'\"]);\nendfunction\n\nfunction retval = do_list_functions ()\n\n  operators = do_list_operators ();\n\n  keywords = sprintf (\"*** keywords:\\n\\n%s\\n\\n\",\n                      list_in_columns (__keywords__ ()));\n\n  builtins = sprintf (\"*** builtins:\\n\\n%s\\n\\n\",\n                      list_in_columns (__builtins__ ()));\n\n  dirs = ostrsplit (path, pathsep);\n  flist = \"\";\n  for i = 2:numel (dirs)\n    files = sort ({dir(fullfile (dirs{i}, \"*.m\")).name, ...\n                   dir(fullfile (dirs{i}, \"*.oct\")).name, ...\n                   dir(fullfile (dirs{i}, \"*.mex\")).name});\n\n    if (! isempty (files))\n      flist = sprintf (\"%s*** functions in %s:\\n\\n%s\\n\\n\",\n                       flist, dirs{i}, list_in_columns (files));\n    endif\n  endfor\n\n  retval = [operators, keywords, builtins, flist];\n\nendfunction\n\nfunction do_contents (name)\n\n  found = false;\n\n  dlist = dir_in_loadpath (name, \"all\");\n\n  for i = 1:numel (dlist)\n    fname = make_absolute_filename (fullfile (dlist{i}, \"Contents.m\"));\n\n    [text, format] = get_help_text_from_file (fname);\n\n    ## Take action depending on help text format\n    switch (lower (format))\n      case \"plain text\"\n        status = 0;\n      case \"texinfo\"\n        [text, status] = __makeinfo__ (text, \"plain text\");\n      case \"html\"\n        [text, status] = strip_html_tags (text);\n    endswitch\n\n    if (! isempty (text))\n      found = true;\n      ## Print text.\n      if (status != 0)\n        warning (\"help: Texinfo formatting filter exited abnormally; raw Texinfo source of help text follows...\\n\");\n      endif\n      printf (\"%s:\\n\\n%s\\n\", fname, text);\n    endif\n\n  endfor\n\n  if (found)\n    puts (__additional_help_message__ ());\n  else\n    msg = feval (missing_function_hook, name);\n\n    if (isempty (msg))\n      msg = sprintf (\"'%s' not found\", name);\n    endif\n\n    error (\"help: %s\\n\", msg);\n  endif\n\nendfunction\n\n\n%!assert (! isempty (strfind (help (\"ls\"), \"List directory contents\")))\n%!assert (! isempty (strfind (help (\".\"), \"||\")))\n\n## Test input validation\n%!error <invalid input> help (42)\n%!error <called with too many inputs> help (\"abc\", \"def\")\n%!error <'_! UNLIKELY_FCN! _' not found> help (\"_! UNLIKELY_FCN! _\")\n"
  },
  {
    "path": "scripts/help/lookfor.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} lookfor @var{str}\n## @deftypefnx {} {} lookfor -all @var{str}\n## @deftypefnx {} {[@var{fcn}, @var{help1str}] =} lookfor (@var{str})\n## @deftypefnx {} {[@var{fcn}, @var{help1str}] =} lookfor (\"-all\", @var{str})\n## Search for the string @var{str} in the documentation of all functions in the\n## current function search path.\n##\n## By default, @code{lookfor} looks for @var{str} in just the first sentence of\n## the help string for each function found.  The entire help text of each\n## function can be searched by using the @qcode{\"-all\"} argument.  All searches\n## are case insensitive.\n##\n## When called with no output arguments, @code{lookfor} prints the list of\n## matching functions to the terminal.  Otherwise, the output argument\n## @var{fcns} contains the function names and @var{help1str} contains the first\n## sentence from the help string of each function.\n##\n## Programming Note: The ability of @code{lookfor} to correctly identify the\n## first sentence of the help text is dependent on the format of the function's\n## help.  All Octave core functions are correctly formatted, but the same can\n## not be guaranteed for external packages and user-supplied functions.\n## Therefore, the use of the @qcode{\"-all\"} argument may be necessary to find\n## related functions that are not a part of Octave.\n##\n## The speed of lookup is greatly enhanced by having a cached documentation\n## file.  For more information,\n## @pxref{XREFdoc_cache_create,,@code{doc_cache_create}}.\n## @seealso{help, doc, which, path, doc_cache_create}\n## @end deftypefn\n\nfunction [fcn, help1str] = lookfor (str, arg2)\n\n  if (strcmpi (str, \"-all\"))\n    ## The difference between using '-all' and not is which part of the caches\n    ## we search.  The cache is organized such that row\n    ## 1) contains the function name\n    ## 2) contains the full help text\n    ## 3) contains the first sentence of the help text.\n    str = arg2;\n    search_type = 2;  # search the second row (full help text)\n  else\n    search_type = 3;  # search the third column (first help sentence)\n  endif\n  str = lower (str);  # Compare is case insensitive\n\n  ## Search functions, operators, and keywords that come with Octave\n  cache_file = doc_cache_file ();\n  if (exist (cache_file, \"file\"))\n    [fcnlist, help_text] = search_cache (str, cache_file, search_type);\n    had_core_cache = true;\n  else\n    fcnlist = help_text = {};\n    had_core_cache = false;\n  endif\n\n  ## Search functions in new path dirs.\n  orig_path = ostrsplit (__pathorig__ (), pathsep ());\n\n  ## ditto for path.\n  new_path = ostrsplit (path (), pathsep ());\n\n  ## remove directories already covered by orig_path.\n  if (had_core_cache)\n    new_path = setdiff (new_path, orig_path);\n  endif\n\n  for n = 1:numel (new_path)\n    fcndir = new_path{n};\n    cache_file = fullfile (fcndir, \"doc-cache\");\n    if (exist (cache_file, \"file\"))\n      ## We have a cache in the directory, then read it and search it!\n      [fcns, htext] = search_cache (str, cache_file, search_type);\n      fcnlist(end+1:end+length (fcns)) = fcns;\n      help_text(end+1:end+length (htext)) = htext;\n\n    else\n      ## We don't have a cache.  Search files.\n      for fcn_in_fcndir = (__list_functions__ (fcndir)).'\n        fn = fcn_in_fcndir{1};\n\n        ## Skip files that start with \"__\"\n        if (strncmp (fn, \"__\", 2))\n          continue;\n        endif\n\n        status = 0;\n\n        ## Extract first sentence\n        try\n          warn_state = warning ();\n          unwind_protect\n            warning (\"off\");\n            first_sentence = get_first_help_sentence (fn, 1024);\n          unwind_protect_cleanup\n            warning (warn_state);\n          end_unwind_protect\n        catch\n          status = 1;\n        end_try_catch\n\n        if (status)\n          ## Error getting first help sentence\n        elseif (search_type == 3)\n          ## only search the first sentence of the help text\n          text = first_sentence;\n        elseif (search_type == 2)\n          ## search entire help text\n          try\n            warn_state = warning ();\n            unwind_protect\n              warning (\"off\");\n              [text, fmt] = get_help_text (fn);\n              switch (lower (fmt))\n                case \"plain text\"\n                  status = 0;\n                case \"texinfo\"\n                  [text, status] = __makeinfo__ (text, \"plain text\");\n                case \"html\"\n                  [text, status] = strip_html_tags (text);\n                otherwise\n                  status = 1;\n              endswitch\n            unwind_protect_cleanup\n              warning (warn_state);\n            end_unwind_protect\n          catch\n            status = 1;\n          end_try_catch\n        endif\n\n        ## Search the help text\n        if (status == 0 && strfind (lower (text), str))\n          fcnlist(end+1) = fn;\n          help_text(end+1) = first_sentence;\n        endif\n      endfor\n    endif\n  endfor\n\n  if (nargout == 0)\n    ## Print the results (FIXME: it would be nice to break at word boundaries)\n    indent = 20;\n    term_width = (terminal_size ())(2);\n    desc_width = term_width - indent - 2;\n    indent_space = blanks (indent);\n    for k = 1:length (fcnlist)\n      f = fcnlist{k};\n      f(end+1:indent-1) = \" \";\n      puts ([f \" \"]);\n      lf = length (f);\n      desc = strtrim (strrep (help_text{k}, \"\\n\", \" \"));\n      ldesc = length (desc);\n      printf (\"%s\\n\", desc(1:min (ldesc, desc_width - (lf - indent))));\n      for start = (desc_width - (lf - indent) + 1):desc_width:ldesc\n        stop = min (start + desc_width, ldesc);\n        printf (\"%s%s\\n\", indent_space, strtrim (desc (start:stop)));\n      endfor\n    endfor\n  else\n    ## Return the results instead of displaying them\n    fcn = fcnlist;\n    help1str = help_text;\n  endif\n\nendfunction\n\nfunction [fcns, help_texts] = search_cache (str, cache_file, search_type)\n\n  load (cache_file);\n\n  if (isempty (cache))\n    fcns = help_texts = {};\n  else\n    t1 = strfind (lower (cache(1, :)), str);\n    t2 = strfind (lower (cache(search_type, :)), str);\n    cache_idx = find (! (cellfun (\"isempty\", t1) & cellfun (\"isempty\", t2)));\n    fcns = cache(1, cache_idx);\n    help_texts = cache(3, cache_idx);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/help/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__additional_help_message__.m \\\n  %reldir%/private/__strip_html_tags__.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/__gripe_missing_component__.m \\\n  %reldir%/__makeinfo__.m \\\n  %reldir%/__unimplemented__.m \\\n  %reldir%/ans.m \\\n  %reldir%/bessel.m \\\n  %reldir%/debug.m \\\n  %reldir%/doc.m \\\n  %reldir%/doc_cache_create.m \\\n  %reldir%/error_ids.m \\\n  %reldir%/get_first_help_sentence.m \\\n  %reldir%/help.m \\\n  %reldir%/lookfor.m \\\n  %reldir%/print_usage.m \\\n  %reldir%/slash.m \\\n  %reldir%/type.m \\\n  %reldir%/warning_ids.m \\\n  %reldir%/which.m\n\n%canon_reldir%dir = $(fcnfiledir)/help\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/help/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/help/print_usage.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} print_usage ()\n## @deftypefnx {} {} print_usage (@var{name})\n## Print the usage message for the function @var{name}.\n##\n## When called with no input arguments the @code{print_usage} function displays\n## the usage message of the currently executing function.\n## @seealso{help}\n## @end deftypefn\n\nfunction print_usage (name)\n\n  x = dbstack ();\n  ## Handle input\n  if (nargin == 0)\n    ## Determine the name of the calling function\n    if (numel (x) > 1)\n      name = x(2).name;\n    else\n      error (\"Octave:invalid-context\", \"print_usage: invalid function\\n\");\n    endif\n    fullname = evalin (\"caller\", 'mfilename (\"fullpath\")');\n    if (strcmp (fullname(end-length (name)+1:end), name))\n      fullname = [fullname \".m\"];\n    endif\n  elseif (! ischar (name))\n    error (\"Octave:invalid-input-arg\",\n           \"print_usage: input argument must be a string\");\n  else\n    fullname = name;\n  endif\n\n  ## Determine if we were called from top level.\n  at_toplev = length (x) < 2 || (length (x) == 2 && strcmp (x(2).name, name));\n\n  ## Do the actual work\n  [text, format] = get_help_text (fullname);\n  max_len = 80;\n  switch (lower (format))\n    case \"plain text\"\n      [usage_string, status] = get_usage_plain_text (text, max_len);\n    case \"texinfo\"\n      [usage_string, status] = get_usage_texinfo (text, max_len);\n    case \"html\"\n      [usage_string, status] = get_usage_html (text, max_len);\n    case \"not documented\"\n      error (\"print_usage: '%s' is not documented\\n\", name);\n    case \"not found\"\n      error (\"print_usage: '%s' not found\\n\", name);\n    otherwise\n      error (\"print_usage: internal error: unsupported help text format: '%s'\\n\", format);\n  endswitch\n\n  ## Raise the final error\n  if (status != 0)\n    warning (\"print_usage: Texinfo formatting filter exited abnormally\");\n    warning (\"print_usage: raw Texinfo source of help text follows...\\n\");\n  endif\n\n  ## We don't want to start the debugger here if debug_on_error is true\n  ## so we set it to false and make the change local.  Then\n  ## debug_on_error will be reset to true after this function returns\n  ## and the debugger will start at the location of the call to\n  ## print_usage.\n  debug_on_error (false, \"local\");\n\n  if (at_toplev)\n    error (\"Octave:invalid-fun-call\",\n           \"Invalid call to %s.  Correct usage is:\\n\\n%s\\n%s\",\n           name, usage_string, __additional_help_message__ ());\n  else\n    msg = sprintf (\"Invalid call to %s.  Correct usage is:\\n\\n%s\",\n                   name, usage_string);\n    ## Ensure that the error doesn't end up with a newline, as that disables\n    ## backtraces.\n    if (msg(end) == \"\\n\")\n      msg(end) = \" \";\n    endif\n\n    error (\"Octave:invalid-fun-call\", msg);\n  endif\n\nendfunction\n\nfunction [retval, status] = get_usage_plain_text (help_text, max_len)\n  ## Extract first line by searching for a double line-end.\n  line_end_idx = strfind (help_text, \"\\n\\n\");\n  retval = help_text (1:min ([line_end_idx , max_len, length(help_text)]));\n  status = 0;\nendfunction\n\nfunction [retval, status] = get_usage_texinfo (help_text, max_len)\n\n  ## Lines ending with \"@\\n\" are continuation lines, so they should be\n  ## concatenated with the following line.\n  help_text = strrep (help_text, \"@\\n\", \" \");\n\n  ## Find, and keep, lines that start with @def or @end def.  This should\n  ## include things such as @deftypefn, @deftypefnx, @defvar, etc. and their\n  ## corresponding @end's.\n  def_idx = strfind (help_text, \"@def\");\n  if (isempty (def_idx))\n    [retval, status] = get_usage_plain_text (help_text, max_len);\n    return;\n  endif\n\n  endf_idx = strfind (help_text, \"@end def\");\n  def_idx = sort ([def_idx, endf_idx]);\n  endl_idx = find (help_text == \"\\n\");\n  buffer = \"\";\n  for k = 1:length (def_idx)\n    endl = endl_idx(find (endl_idx > def_idx(k), 1));\n    if (isempty (endl))\n      buffer = [buffer, help_text(def_idx(k):end), \"\\n\"];\n    else\n      buffer = [buffer, help_text(def_idx(k):endl)];\n    endif\n  endfor\n\n  ## Generate plain text from the markup.\n  [retval, status] = __makeinfo_restricted__ (buffer);\n  if (status != 0)  # something went wrong in the restricted conversion.\n    ## Use the full conversion.\n    [retval, status] = __makeinfo__ (buffer, \"plain text\");\n  endif\n\nendfunction\n\nfunction [retval, status] = __makeinfo_restricted__ (buffer)\n  ## This function converts the very narrow subset of Texinfo commands\n  ## that are actually used by `print_usage` into plain text,\n  ## without requiring a slow call to `system (\"makeinfo\")`.\n  ##\n  ## As of April 2024, only the following Texinfo commands are being used\n  ## by print_usage strings in Octave core:\n  ##\n  ## @deftypefn, @deftypefnx, @end deftypefn, @var, @qcode, @dots, @, @@\n  ##\n  ## Note: this function is meant only for print_usage (), not for help (),\n  ## which continues to use the full makeinfo.\n\n  retval = \"\";\n  status = -1;  # assume failure to convert\n\n  ## The simple replacements first.\n  buffer = strrep (buffer, \"@deftypefnx\", \"\");\n  buffer = strrep (buffer, \"@end deftypefn\\n\", \"\");\n  buffer = strrep (buffer, \"@deftypefn \", \"\");\n  buffer = strrep (buffer, \"@qcode\", \"\");\n  buffer = strrep (buffer, \"@dots\", \"...\");\n\n  ## Capitalize variable names, so \"@var{foo}\" becomes \"@var{FOO}\".\n  ## FIXME: Replace this loop with a call to regexprep once transformation\n  ## features are available.\n  for j = strfind (buffer, \"@var\")  # each instance of @var\n    ## Uppercase the part between the relevant braces.\n    k = find (buffer(j:end) == '}', 1) + j - 1;\n    buffer((j+5):(k-1)) = upper (buffer((j+5):(k-1)));\n  endfor\n\n  ## Don't need @var any more, nor any braces.\n  buffer = strrep (buffer, \"@var\", \"\");\n  buffer(buffer == '{' | buffer == '}') = [];\n\n  ## There should not be any Texinfo commands remaining at this point.\n  ## Search for this with the regex \"@[a-z]\" because other instances of @\n  ## occur next to uppercase letters or non-letters by this point.\n  if (any (regexp (buffer, \"@[a-z]\")))\n    ## There is some Texinfo command in the deftypefn line\n    ## outside the scope of this restricted function,\n    ## so return with status set to failure.\n    return;\n  endif\n\n  ## Process any remaining @ signs.\n  ## Context: A line like this:\n  ##    setappdata (H, @NAME1, NAME2, ...@, @VALUE1, VALUE2, ...@)\n  ## should become\n  ##    setappdata (H, {NAME1, NAME2, ...}, {VALUE1, VALUE2, ...})\n  ## But a line like this:\n  ##   A = cellfun (@@FCN, C)\n  ## should become:\n  ##   A = cellfun ('FCN', C)\n  ## and not this:\n  ##   A = cellfun ({}FCN, C)\n  ## Currently the code uses a guard string to protect the @@,\n  ## then replaces @ with { or }, then unprotects the @@ and changes it to @.\n  ## FIXME: Simplify this conversion sequence if possible.\n\n  if (any (buffer == '@'))\n    guardstring = \"ZAQWSXCDERFV\";  # some improbable sequence\n    buffer = strrep (buffer, \"@@\", guardstring);\n    ff = find (buffer == '@');  # these show up in pairs, verified with assert\n    buffer(ff(1:2:end)) = '{';  # odd-numbered locations become {\n    buffer(ff(2:2:end)) = '}';  # even-numbered ones become }\n    buffer = strrep (buffer, guardstring, \"@\");\n  endif\n\n  ## Optional: Try inserting \" --\"  after newlines to imitate Texinfo visually.\n  ## This makes `help foo` and plain `foo` look similar.\n  do\n    ## First remove extra spaces; otherwise they interfere.\n    old = numel (buffer);\n    buffer = strrep (buffer, \"  \", \" \");\n  until (numel (buffer) == old)\n  buffer = [\" --\", buffer];\n  buffer = strrep (deblank (buffer), \"\\n\", \"\\n --\");\n\n  retval = buffer;\n  status = 0;  # == success\n\nendfunction\n\nfunction [retval, status] = get_usage_html (help_text, max_len)\n\n  ## Strip tags\n  [help_text, status] = strip_html_tags (help_text);\n\n  ## Extract first line with plain text method.\n  retval = get_usage_plain_text (help_text, max_len);\n\nendfunction\n\n\n## Stop reporting function as missing tests.  No good tests possible.\n%!assert (1)\n"
  },
  {
    "path": "scripts/help/private/__additional_help_message__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{msg} =} __additional_help_message__ ()\n## Undocumented internal function.\n## @end deftypefn\n\nfunction msg = __additional_help_message__ ()\n\n  if (suppress_verbose_help_message ())\n    msg = \"\";\n  else\n    msg = \"\\n\\\nAdditional help for built-in functions and operators is\\n\\\navailable in the online version of the manual.  Use the command\\n\\\n'doc <topic>' to search the manual index.\\n\\\n\\n\\\nHelp and information about Octave is also available on the WWW\\n\\\nat https://www.octave.org and https://octave.discourse.group/c/help/\\n\";\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/help/private/__strip_html_tags__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{text}, @var{status}] =} __strip_html_tags__ (@var{html_text})\n## Undocumented internal function.\n## @end deftypefn\n\n## Remove HTML tags from text.  This is used as a simple HTML-to-text\n## function.\n\nfunction [text, status] = __strip_html_tags__ (html_text)\n\n  start = find (html_text == \"<\");\n  stop  = find (html_text == \">\");\n  if (length (start) == length (stop))\n    text = html_text;\n    for n = length (start):-1:1\n      text (start (n):stop (n)) = [];\n    endfor\n    text = strip_superfluous_endlines (text);\n    status = 0;\n  else\n    warning (\"help: invalid HTML data -- raw HTML source follows...\");\n    disp (html_text);\n    text = \"\";\n    status = 1;\n  endif\n\nendfunction\n\n## This function removes end-lines (\\n) that makes printing look bad\nfunction text = strip_superfluous_endlines (text)\n\n  ## Find groups of end-lines\n  els = find (text == \"\\n\");\n  dels = diff (els);\n  groups = [els(1), 1]; # list containing [start, length] of each group\n  for k = 1:length (dels)\n    if (dels (k) == 1)\n      groups(end, 2)++;\n    else\n      groups(end+1, 1:2) = [els(k+1), 1];\n    endif\n  endfor\n\n  keep = true (size (text));\n\n  ## Remove end-lines in the beginning\n  if (groups (1, 1) == 1)\n    keep(1:groups (1, 2)) = false;\n  endif\n\n  ## Remove end-lines from the end\n  if (sum (groups(end, :)) - 1 == length (text))\n    keep(groups(end, 1):end) = false;\n  endif\n\n  ## Remove groups of end-lines with more than 3 end-lines next to each other\n  idx = find (groups (:, 2) >= 3);\n  for k = 1:length (idx)\n    start = groups(idx(k), 1);\n    stop = start + groups(idx(k), 2) - 1;\n    keep(start+2:stop) = false;\n  endfor\n\n  ## Actually remove the elements\n  text = text(keep);\n\nendfunction\n"
  },
  {
    "path": "scripts/help/slash.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @documentencoding UTF-8\n## @defvr {Documentation} slash\n## Backslash and slash perform various sorts of division.\n##\n## @table @asis\n## @item @code{\\} Matrix Left Division (``backslash'')\n## Solve systems of equations\n## @iftex\n## $Ax = b$ for $x$.\n## @end iftex\n## @ifnottex\n## Ax = b for x.\n## @end ifnottex\n## @code{A \\ b} is conceptually equivalent to @code{inv (A) * b} but is\n## computed more efficiently and accurately, without forming the matrix\n## inverse directly.\n##\n## Example:\n##\n## @example\n## @group\n## A = [1 2; 3 4];\n## b = [4; 2];\n## x = A \\ b\n##   @xresult{} x =\n##        -6\n##         5\n## isequal (A*x, b)\n##   @xresult{} 1\n## @end group\n## @end example\n##\n## If the system is not square, or if the matrix is singular, a minimum-norm\n## solution is computed (@code{norm (A*x - b)}).\n##\n## For dense matrices, backslash uses the Gaussian Elimination algorithm\n## with partial pivoting.  For sparse matrices, backslash uses a direct\n## method to compute an LU factorization (@pxref{XREFlu,,@code{lu}}).  The\n## direct method tries to minimize ``fill-in'' of zeros but it could\n## nonetheless use a lot of memory; if this is a concern, consider an iterative\n## method (@pxref{XREFcgs,,@code{cgs}} or @pxref{XREFgmres,,@code{gmres}}).\n##\n## @item @code{/} Matrix Right Division\n## The forward slash notation can be used to solve systems of the form\n## @iftex\n## $AB = C$ for $A$\n## @end iftex\n## @ifnottex\n## AB = C for A\n## @end ifnottex\n## using @code{A = C / B}.\n##\n## @item @code{./} and @code{.\\} Component-wise ``Hadamard'' Division\n## The ``dot slash'' operators perform element-by-element division, for\n## example:\n##\n## @example\n## @group\n## A = [1 10 12; 24 30 42];\n## B = [1 5 4; 6 6 7];\n## A ./ B\n##   @xresult{}\n##        1   2   3\n##        4   5   6\n## @end group\n## @end example\n##\n## If the sizes are not the same, ``broadcasting'' may apply\n## (@pxref{Broadcasting}):\n##\n## @example\n## @group\n## 420 ./ B\n##   @xresult{}\n##        420    84   105\n##         70    70    60\n## [20; 42] ./ B\n##   @xresult{}\n##        20    4    5\n##         7    7    6\n## @end group\n## @end example\n##\n## @end table\n##\n## @seealso{mldivide, mrdivide, ldivide, rdivide, linsolve}\n## @end defvr\n\n\n## Mark file as being tested.  No real test needed for a documentation .m file\n%!assert (1)\n"
  },
  {
    "path": "scripts/help/type.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} type @var{name} @dots{}\n## @deftypefnx {} {} type -q @var{name} @dots{}\n## @deftypefnx {} {text =} type (\"@var{name}\", @dots{})\n## Display the contents of @var{name} which may be a file, function (m-file),\n## variable, operator, or keyword.\n##\n## @code{type} normally prepends a header line describing the category of\n## @var{name} such as function or variable; The @option{-q} option suppresses\n## this behavior.\n##\n## If no output variable is used the contents are displayed on screen.\n## Otherwise, a cell array of strings is returned, where each element\n## corresponds to the contents of each requested function.\n## @end deftypefn\n\nfunction text = type (varargin)\n\n  if (nargin == 0)\n    print_usage ();\n  elseif (! iscellstr (varargin))\n    error (\"type: input arguments must be strings\");\n  endif\n\n  quiet = false;\n  idx = strcmpi (varargin, \"-q\") | strcmpi (varargin, \"-quiet\");\n  if (any (idx))\n    quiet = true;\n    varargin(idx) = [];\n  endif\n\n  if (nargout > 0)\n    text = cell (size (varargin));\n  endif\n\n  for n = 1:length (varargin)\n    name = varargin{n};\n\n    ## Find function and get its code\n    txt = \"\";\n    cmd = sprintf (\"exist ('%s')\", name);\n    e = evalin (\"caller\", cmd);\n    if (e == 1)\n      ## Variable\n      cmd = sprintf (\"disp (%s);\", name);\n      desc = evalin (\"caller\", cmd);\n      if (quiet)\n        txt = desc;\n      else\n        txt = sprintf (\"%s is a variable\\n%s\", name, desc);\n      endif\n    elseif (e == 2)\n      ## m-file or ordinary file\n      file = which (name);\n      if (length (file) > 2)\n        ext = file(end-1:end);\n      endif\n      if (isempty (file) || ! strcmpi (ext, \".m\"))\n        ## 'name' is an ordinary file, and not a function name.\n        file = file_in_loadpath (name);\n        quiet = true;\n      endif\n\n      ## Read the file\n      fid = fopen (file, \"r\");\n      if (fid < 0)\n        error (\"type: couldn't open '%s' for reading\", file);\n      endif\n      contents = char (fread (fid).');\n      fclose (fid);\n\n      if (quiet)\n        txt = contents;\n      else\n        tmp = __which__ (name);\n        txt = sprintf (\"%s is the %s defined from: %s\\n\\n%s\",\n                        name, tmp.type, file, contents);\n      endif\n    elseif (e == 3)\n      txt = sprintf (\"%s is a dynamically-linked function\", name);\n    elseif (e == 5)\n      txt = sprintf (\"%s is a built-in function\", name);\n    elseif (e == 103)\n      contents = __get_cmdline_fcn_txt__ (name);\n      if (isempty (contents))\n        txt = sprintf (\"%s is a command-line function with no definition\",\n                       name);\n      else\n        if (quiet)\n          txt = contents;\n        else\n          txt = sprintf (\"%s is the command-line function:\\n\\n%s\",\n                         name, contents);\n        endif\n      endif\n    elseif (any (strcmp (__operators__ (), name)))\n      txt = sprintf (\"%s is an operator\", name);\n    elseif (any (strcmp (__keywords__ (), name)))\n      txt = sprintf (\"%s is a keyword\", name);\n    else\n      error (\"type: '%s' undefined\\n\", name);\n    endif\n\n    if (nargout == 0)\n      disp (txt);\n    else\n      text{n} = txt;\n    endif\n  endfor\n\nendfunction\n\n\n%!test\n%! var = 1;\n%! txt = type (\"var\");\n%! typestr = txt{1}(1:17);\n%! assert (typestr, \"var is a variable\");\n\n%!test\n%! txt = type (\"ls\");\n%! typestr = txt{1}(1:31);\n%! assert (typestr, \"ls is the function defined from\");\n\n%!test\n%! txt = type (\"ls\", \"-q\");\n%! assert (regexp (txt{1}, '[#\\s]*Copyright \\(C\\) 2006'));\n\n%!assert (type (\"fftw\"){1}, \"fftw is a dynamically-linked function\")\n%!assert (type (\"cat\"){1}, \"cat is a built-in function\")\n%!assert (type (\"+\"){1}, \"+ is an operator\")\n%!assert (type (\"end\"){1}, \"end is a keyword\")\n\n%!error <Invalid call> type ()\n%!error <'__NO_NAME__' undefined> type ('__NO_NAME__')\n"
  },
  {
    "path": "scripts/help/warning_ids.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @cindex warning ids\n##\n## @table @code\n## @item Octave:abbreviated-property-match\n## If the @code{Octave:abbreviated-property-match} warning is enabled, a\n## warning is printed if a non-exact or ambiguous match is being used for a\n## operation specifying an object property.  For example, for a graphics\n## object, @var{fig}, with the property @qcode{'displayname'},\n## @code{get (@var{fig}, 'dis')} elicits a warning if the\n## @code{Octave:abbreviated-property-match} warning is enabled.\n## By default, the @code{Octave:abbreviated-property-match} warning is enabled.\n##\n## @item Octave:addpath-pkg\n## If the @code{Octave:addpath-pkg} warning is enabled,\n## Octave will warn when a package directory (i.e., +package_name) is added\n## to the @code{path}.  Typically, only the parent directory which contains the\n## package directory should be added to the load path.\n## By default, the @code{Octave:addpath-pkg} warning is enabled.\n##\n## @item Octave:array-as-logical\n## If the @code{Octave:array-as-logical} warning is enabled,\n## Octave will warn when an array of size greater than 1x1 is used\n## as a truth value in an if, while, or until statement.\n## By default, the @code{Octave:array-as-logical} warning is disabled.\n##\n## @item Octave:array-to-scalar\n## If the @code{Octave:array-to-scalar} warning is enabled, Octave will\n## warn when an implicit conversion from an array to a scalar value is\n## attempted.\n## By default, the @code{Octave:array-to-scalar} warning is disabled.\n##\n## @item Octave:array-to-vector\n## If the @code{Octave:array-to-vector} warning is enabled, Octave will\n## warn when an implicit conversion from an array to a vector value is\n## attempted.\n## By default, the @code{Octave:array-to-vector} warning is disabled.\n##\n## @item Octave:assign-as-truth-value\n## If the @code{Octave:assign-as-truth-value} warning is\n## enabled, a warning is issued for statements like\n##\n## @example\n## @group\n## if (s = t)\n##   @dots{}\n## @end group\n## @end example\n##\n## @noindent\n## since such statements are not common, and it is likely that the intent\n## was to write\n##\n## @example\n## @group\n## if (s == t)\n##   @dots{}\n## @end group\n## @end example\n##\n## @noindent\n## instead.\n##\n## There are times when it is useful to write code that contains\n## assignments within the condition of a @code{while} or @code{if}\n## statement.  For example, statements like\n##\n## @example\n## @group\n## while (c = getc ())\n##   @dots{}\n## @end group\n## @end example\n##\n## @noindent\n## are common in C programming.\n##\n## It is possible to avoid all warnings about such statements by\n## disabling the @code{Octave:assign-as-truth-value} warning,\n## but that may also let real errors like\n##\n## @example\n## @group\n## if (x = 1)  # intended to test (x == 1)!\n##   @dots{}\n## @end group\n## @end example\n##\n## @noindent\n## slip by.\n##\n## In such cases, it is possible suppress errors for specific statements by\n## writing them with an extra set of parentheses.  For example, writing the\n## previous example as\n##\n## @example\n## @group\n## while ((c = getc ()))\n##   @dots{}\n## @end group\n## @end example\n##\n## @noindent\n## will prevent the warning from being printed for this statement, while\n## allowing Octave to warn about other assignments used in conditional\n## contexts.\n##\n## By default, the @code{Octave:assign-as-truth-value} warning is enabled.\n##\n## @item Octave:autoload-relative-file-name\n## If the @code{Octave:autoload-relative-file-name} is enabled,\n## Octave will warn when parsing autoload() function calls with relative\n## paths to function files.  This usually happens when using autoload()\n## calls in PKG_ADD files, when the PKG_ADD file is not in the same\n## directory as the .oct file referred to by the autoload() command.\n## By default, the @code{Octave:autoload-relative-file-name} warning is\n## enabled.\n##\n## @item Octave:charmat-truncated\n## If the @code{Octave:charmat-truncated} warning is enabled, a warning is\n## printed when a character matrix with multiple rows is converted to a string.\n## In this case, the Octave interpreter keeps only the first row and discards\n## the others.\n## By default, the @code{Octave:charmat-truncated} warning is enabled.\n##\n## @item Octave:classdef-to-struct\n## If the @code{Octave:classdef-to-struct} warning is enabled, a warning\n## is issued when a classdef object is forcibly converted into a struct with\n## @code{struct (@var{CLASSDEF_OBJ})}.  Conversion removes the access\n## restrictions from the object and makes private and protected properties\n## visible.\n## By default, the @code{Octave:classdef-to-struct} warning is enabled.\n##\n## @item Octave:colon-complex-argument\n## If the @code{Octave:colon-complex-argument} warning is enabled, a warning\n## is issued when one of the three arguments to the colon operator (base,\n## increment, limit) is a complex value.  For example, @code{1:3*i} will\n## cause a warning to be emitted.\n## By default, the @code{Octave:colon-complex-argument} warning is enabled.\n##\n## @item Octave:colon-nonscalar-argument\n## If the @code{Octave:colon-nonscalar-argument} warning is enabled, a warning\n## is issued when one of the three arguments to the colon operator (base,\n## increment, limit) is not a scalar.  For example, @code{1:[3, 5]} will\n## cause a warning to be emitted.\n## By default, the @code{Octave:colon-nonscalar-argument} warning is enabled.\n##\n## @item Octave:data-file-in-path\n## If the @code{Octave:data-file-in-path} warning is enabled, a warning is\n## issued when Octave does not find the target of a file operation such as\n## @code{load} or @code{fopen} directly, but is able to locate the file in\n## Octave's search @code{path} for files.  The warning could indicate that a\n## different file target than the programmer intended is being used.\n## By default, the @code{Octave:data-file-in-path} warning is enabled.\n##\n## @item Octave:datevec:date-format-spec\n## If the @code{Octave:datevec:date-format-spec} warning is enabled, a warning\n## is printed if the date format specification contains questionable date or\n## time specifiers.  Typical bad patterns are using uppercase date specifiers\n## or lowercase time specifiers.\n## By default, the @code{Octave:datevec:date-format-spec} warning is enabled.\n##\n## @item Octave:deprecated-function\n## If the @code{Octave:deprecated-function} warning is enabled, a\n## warning is issued when Octave encounters a function that is obsolete and\n## scheduled for removal from Octave.\n## By default, the @code{Octave:deprecated-function} warning is enabled.\n##\n## @item Octave:deprecated-keyword\n## If the @code{Octave:deprecated-keyword} warning is enabled, a\n## warning is issued when Octave encounters a keyword that is obsolete and\n## scheduled for removal from Octave.\n## By default, the @code{Octave:deprecated-keyword} warning is enabled.\n##\n## @item Octave:deprecated-option\n## If the @code{Octave:deprecated-option} warning is enabled, a\n## warning is issued when an obsolete option or input to a function is used.\n## By default, the @code{Octave:deprecated-option} warning is enabled.\n##\n## @item Octave:deprecated-property\n## If the @code{Octave:deprecated-property} warning is enabled, a\n## warning is issued when Octave encounters a graphics property that\n## is obsolete and scheduled for removal from Octave.\n## By default, the @code{Octave:deprecated-property} warning is enabled.\n##\n## @item Octave:eigs:UnconvergedEigenvalues\n## If the @code{Octave:eigs:UnconvergedEigenvalues} warning is enabled then\n## the eigs function will issue a warning if the number of calculated\n## eigenvalues is less than the number of requested eigenvalues.\n## By default, the @code{Octave:eigs:UnconvergedEigenvalues} warning is\n## enabled.\n##\n## @item Octave:empty-index\n## If the @code{Octave:empty-index} warning is enabled then Octave will emit a\n## warning whenever indexing operators are used without an index, for example\n## @code{@var{x}()}.\n## By default, the @code{Octave:empty-index} warning is enabled.\n##\n## @item Octave:erase:chararray\n## If the @code{Octave:erase:chararray} warning is enabled then the erase\n## function will issue a warning if the input pattern is a character array\n## rather than a string or cell array of strings.\n## By default, the @code{Octave:erase:chararray} warning is enabled.\n##\n## @item Octave:function-name-clash\n## If the @code{Octave:function-name-clash} warning is enabled, a\n## warning is issued when Octave finds that the name of a function\n## defined in a function file differs from the name of the file.  (If\n## the names disagree, the name declared inside the file is ignored.)\n## By default, the @code{Octave:function-name-clash} warning is enabled.\n##\n## @item Octave:future-time-stamp\n## If the @code{Octave:future-time-stamp} warning is enabled, Octave\n## will print a warning if it finds a function file with a time stamp\n## that is in the future.\n## By default, the @code{Octave:future-time-stamp} warning is enabled.\n##\n## @item Octave:glyph-render\n## If the @code{Octave:glyph-render} warning is enabled, Octave will\n## print a warning if the glyph for a character couldn't be rendered with\n## the current font.\n## By default, the @code{Octave:glyph-render} warning is enabled.\n##\n## @item Octave:imag-to-real\n## If the @code{Octave:imag-to-real} warning is enabled, a warning is\n## printed for implicit conversions of complex numbers to real numbers.\n## By default, the @code{Octave:imag-to-real} warning is disabled.\n##\n## @item Octave:infinite-loop\n## If the @code{Octave:infinite-loop} warning is enabled, a warning is\n## printed when an infinite loop is detected such as @code{for i = 1:Inf} or\n## @code{while (1)}.\n## By default, the @code{Octave:infinite-loop} warning is enabled.\n##\n## @item Octave:language-extension\n## Print warnings when using features that are unique to the Octave\n## language and that may still be missing in @sc{matlab}.\n## By default, the @code{Octave:language-extension} warning is disabled.\n## The @option{--traditional} or @option{--braindead} startup options for\n## Octave may also be of use, @pxref{Command Line Options}.\n##\n## @item Octave:legacy-function\n## If the @code{Octave:legacy-function} warning is enabled, a\n## warning is issued when Octave encounters a function that @sc{matlab} has\n## suggested should be avoided.  The function may become obsolete at some\n## point in the future and removed, in which case the warning will change to\n## @code{Octave:deprecated-function}, and the function will continue to exist\n## for two further versions of Octave before being removed.\n## By default, the @code{Octave:legacy-function} warning is enabled.\n##\n## @item Octave:logical-conversion\n## If the @code{Octave:logical-conversion} warning is enabled, a warning is\n## printed if an implicit conversion of an array from numerical to boolean\n## occurs and any of the elements in the array are not equal to zero or one.\n## By default, the @code{Octave:logical-conversion} warning is enabled.\n##\n## @item Octave:lu:sparse_input\n## If the @code{Octave:lu:sparse_input} warning is enabled, Octave\n## will warn when the lu function is called with a sparse input and less than\n## four output arguments.  In this case, sparsity-preserving column\n## permutations are not performed and the result may be inaccurate.\n## By default, the @code{Octave:lu:sparse_input} warning is enabled.\n##\n## @item Octave:missing-glyph\n## If the @code{Octave:glyph-render} warning is enabled, Octave will\n## print a warning if the current font doesn't provide a glyph for a\n## used character.\n## By default, the @code{Octave:missing-glyph} warning is enabled.\n##\n## @item Octave:missing-semicolon\n## If the @code{Octave:missing-semicolon} warning is enabled, Octave\n## will warn when statements in function definitions don't end in\n## semicolons.\n## By default the @code{Octave:missing-semicolon} warning is disabled.\n##\n## @item Octave:mixed-string-concat\n## If the @code{Octave:mixed-string-concat} warning is enabled, print a\n## warning when concatenating a mixture of single and double quoted strings.\n## By default, the @code{Octave:mixed-string-concat} warning is disabled.\n##\n## @item  Octave:nearly-singular-matrix\n## @itemx Octave:singular-matrix\n## These warnings are emitted if a (nearly) singular matrix is inverted.\n## By default, the @code{Octave:nearly-singular-matrix} and\n## @code{Octave:singular-matrix} warnings are enabled.\n##\n## @item Octave:neg-dim-as-zero\n## If the @code{Octave:neg-dim-as-zero} warning is enabled, print a warning\n## for expressions like\n##\n## @example\n## eye (-1)\n## @end example\n##\n## @noindent\n## By default, the @code{Octave:neg-dim-as-zero} warning is disabled.\n##\n## @item Octave:noninteger-range-as-index\n## If the @code{Octave:noninteger-range-as-index} warning is enabled, a warning\n## is printed if an array is indexed with a range that contains non-integer\n## values.  For example,\n##\n## @example\n## @group\n## a = [1 2 3 4 5];\n## b = 2.2:4.2\n## @xresult{} 1.2  2.2  3.2\n## a(b)\n## @xresult{} 2 3 4\n## @end group\n## @end example\n##\n## @noindent\n## elicits a warning if the @code{Octave:noninteger-range-as-index} warning is\n## enabled.\n## By default, the @code{Octave:noninteger-range-as-index} warning is enabled.\n##\n## @item Octave:num-to-str\n## If the @code{Octave:num-to-str} warning is enabled, a warning is\n## printed for implicit conversions of numbers to their UTF-8 encoded character\n## equivalents when strings are constructed using a mixture of strings and\n## numbers in matrix notation.  For example,\n##\n## @example\n## @group\n## [ \"f\", 111, 111 ]\n## @xresult{} \"foo\"\n## @end group\n## @end example\n##\n## @noindent\n## elicits a warning if the @code{Octave:num-to-str} warning is\n## enabled.  By default, the @code{Octave:num-to-str} warning is enabled.\n##\n## @item Octave:possible-matlab-short-circuit-operator\n## If the @code{Octave:possible-matlab-short-circuit-operator} warning\n## is enabled, Octave will warn about using the not short circuiting\n## operators @code{&} and @code{|} inside @code{if} or @code{while}\n## conditions.  They normally never short circuit, but they do short\n## circuit when used in a condition.\n## By default, the @code{Octave:possible-matlab-short-circuit-operator} warning\n## is enabled.\n##\n## @item Octave:pow2:imaginary-ignored\n## If the @code{Octave:pow2:imaginary-ignored} warning is enabled, a warning is\n## printed if either input to @code{pow2} is complex.\n## By default, the @code{Octave:pow2:imaginary-ignored} warning is enabled.\n##\n## @item Octave:recursive-path-search\n## If the @code{Octave:recursive-path-search} warning is enabled, Octave\n## will issue a warning if @code{addpath} is used with double trailing\n## slashes.\n## By default, the @code{Octave:recursive-path-search} warning is enabled.\n##\n## @item Octave:remove-init-dir\n## The @code{path} function changes the search path that Octave uses\n## to find functions.  It is possible to set the path to a value which\n## excludes Octave's own built-in functions.  If the\n## @code{Octave:remove-init-dir} warning is enabled then Octave will warn\n## when the @code{path} function has been used in a way that may render\n## Octave unworkable.\n## By default, the @code{Octave:remove-init-dir} warning is enabled.\n##\n## @item Octave:reload-forces-clear\n## If several functions have been loaded from the same file, Octave must\n## clear all the functions before any one of them can be reloaded.  If\n## the @code{Octave:reload-forces-clear} warning is enabled, Octave will\n## warn you when this happens, and print a list of the additional\n## functions that it is forced to clear.\n## By default, the @code{Octave:reload-forces-clear} warning is enabled.\n##\n## @item Octave:separator-insert\n## Print warning if commas or semicolons might be inserted\n## automatically in literal matrices.\n## By default, the @code{Octave:separator-insert} warning is disabled.\n##\n## @item Octave:shadowed-function\n## If the @code{Octave:shadowed-function} warning is enabled, Octave will\n## warn if a path is added to the search path that contains functions\n## that shadow core functions.\n## By default, the @code{Octave:shadowed-function} warning is enabled.\n##\n## @item Octave:single-quote-string\n## Print warning if a single quote character is used to introduce a\n## string constant.\n## By default, the @code{Octave:single-quote-string} warning is disabled.\n##\n## @item Octave:sparse:double-conversion\n## If the @code{Octave:sparse:double-conversion} warning is enabled, a warning\n## is printed when an implicit conversion from a full, single array occurs\n## during the creation of a sparse array.\n## By default, the @code{Octave:sparse:double-conversion} warning is enabled.\n##\n## @item Octave:sqrtm:SingularMatrix\n## If the @code{Octave:sqrtm:SingularMatrix} warning is enabled, a warning is\n## printed if the matrix square root function @code{sqrtm} is called with an\n## input matrix that is singular.\n## By default, the @code{Octave:sqrtm:SingularMatrix} warning is enabled.\n##\n## @item Octave:str-to-num\n## If the @code{Octave:str-to-num} warning is enabled, a warning is printed\n## for implicit conversions of strings to their numeric UTF-8 encoded byte\n## sequences.  For example,\n##\n## @example\n## @group\n## \"abc\" + 0\n## @xresult{} 97 98 99\n## @end group\n## @end example\n##\n## @noindent\n## elicits a warning if the @code{Octave:str-to-num} warning is enabled.\n## By default, the @code{Octave:str-to-num} warning is disabled.\n##\n## @item Octave:LaTeX:internal-error\n## If the @code{Octave:LaTeX:internal-error} warning is enabled, a warning is\n## printed whenever the @LaTeX{} renderer for text in plots encounters an\n## issue.\n## By default, the @code{Octave:LaTeX:internal-error} warning is enabled.\n##\n## @item Octave:unimplemented-matlab-functionality\n## If the @code{Octave:unimplemented-matlab-functionality} warning is enabled,\n## a warning is printed when a @sc{matlab} code construct is used which the\n## Octave interpreter parses as valid, but for which Octave does not yet\n## implement the functionality.\n## By default, the @code{Octave:unimplemented-matlab-functionality} warning is\n## enabled.\n##\n## @item Octave:variable-switch-label\n## If the @code{Octave:variable-switch-label} warning is enabled, Octave\n## will print a warning if a switch label is not a constant or constant\n## expression.\n## By default, the @code{Octave:variable-switch-label} warning is disabled.\n## @end table\n##\n\nfunction warning_ids ()\n  help (\"warning_ids\");\nendfunction\n\n\n## Mark file as tested.  No tests needed for a documentation m-file.\n%!assert (1)\n"
  },
  {
    "path": "scripts/help/which.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} which @var{name} @dots{}\n## @deftypefnx {} {[@var{str}, @dots{}] =} which ('@var{name}', @dots{})\n## Display the type of each @var{name}.\n##\n## If @var{name} is defined from a function file, the full name of the file is\n## also displayed.\n## @seealso{help, lookfor}\n## @end deftypefn\n\nfunction varargout = which (varargin)\n\n  if (nargin == 0 || ! iscellstr (varargin))\n    print_usage ();\n  endif\n\n  ## FIXME: \"-all\" option not implemented.  Warn user that only the first\n  ##        result found will be returned.  See bug #32088.\n  if (any (isall = strcmpi (varargin, \"-all\")))\n    warning ([\"which: '-all' not yet implemented - only the first result \", ...\n             \"will be returned\\n\"]);\n    varargin = varargin(! isall);\n    nargin = nargin - sum (isall);\n  endif\n\n  m = __which__ (varargin{:});\n\n  ## Check whether each name is a variable, variables take precedence over\n  ## functions in name resolution.\n  for i = 1:nargin\n    m(i).is_variable = evalin (\"caller\",\n                               ['exist (\"' undo_string_escapes(m(i).name) '\", \"var\")'], \"\");\n    if (m(i).is_variable)\n      m(i).file = \"variable\";\n    endif\n  endfor\n\n  if (nargout == 0)\n    for i = 1:nargin\n      if (m(i).is_variable)\n        printf (\"'%s' is a variable\\n\", m(i).name);\n      elseif (isempty (m(i).file))\n        if (! isempty (m(i).type))\n          printf (\"'%s' is a %s\\n\",\n                  m(i).name, m(i).type);\n        endif\n      else\n        if (isempty (m(i).type))\n          if (isfolder (m(i).file))\n            printf (\"'%s' is the directory %s\\n\",\n                    m(i).name, m(i).file);\n          else\n            printf (\"'%s' is the file %s\\n\",\n                    m(i).name, m(i).file);\n          endif\n        else\n          printf (\"'%s' is a %s from the file %s\\n\",\n                  m(i).name, m(i).type, m(i).file);\n        endif\n      endif\n    endfor\n  else\n    varargout = {m.file};\n    ## Return type, instead of \"\", for built-in classes (bug #50541).\n    ## FIXME: remove code if __which__ is updated to return path for classes\n    idx = find (cellfun (\"isempty\", varargout));\n    if (idx)\n      varargout(idx) = m(idx).type;\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! str = which (\"ls\");\n%! assert (str(end-17:end), fullfile (\"miscellaneous\", \"ls.m\"));\n%!test\n%! str = which (\"fftw\");\n%! assert (str(end-7:end), \"fftw.oct\");\n%!assert <*49434> (which (\"inputParser\"), file_in_loadpath (\"inputParser.m\"))\n%!test\n%! x = 3;\n%! str = which (\"x\");\n%! assert (str, \"variable\");\n\n%!assert (which (\"__NO_SUCH_NAME__\"), \"\")\n\n%!test\n%! str = which (\"fftw\");\n%! assert (str(end-7:end), \"fftw.oct\");\n%! fftw = 12;\n%! str = which (\"fftw\");\n%! assert (str, \"variable\");\n%! clear fftw;\n%! str = which (\"fftw\");\n%! assert (str(end-7:end), \"fftw.oct\");\n\n%!error <Invalid call> which ()\n%!error <Invalid call> which (1)\n%!warning <'-all' not yet implemented> which (\"1\", \"-all\")\n"
  },
  {
    "path": "scripts/image/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/image/autumn.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} autumn ()\n## @deftypefnx {} {@var{map} =} autumn (@var{n})\n## Create color colormap.\n## This colormap ranges from red through orange to yellow.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = autumn (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"autumn: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [1, 0, 0];\n  elseif (n > 1)\n    r = ones (n, 1);\n    g = [0:(n-1)]' / (n - 1);\n    b = zeros (n, 1);\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'autumn' colormap profile and as an image\n%! cmap = autumn (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (autumn ()), [256, 3])\n%!assert (size (autumn (16)), [16, 3])\n\n%!assert (autumn (1), [1, 0, 0])\n%!assert (autumn (true), double ([1, 0, 0]))\n%!assert (autumn (char (1)), double ([1, 0, 0]))\n%!assert (autumn (int32 (1)), double ([1, 0, 0]))\n\n%!assert (autumn (0), zeros (0, 3))\n%!assert (autumn (-1), zeros (0, 3))\n\n%!assert (autumn (11), [ones(1,11); [0:0.1:1]; zeros(1,11)]', eps)\n\n## Input validation\n%!error <N must be a scalar integer> autumn (\"foo\")\n%!error <N must be a scalar integer> autumn ([1, 2, 3])\n%!error <N must be a scalar integer> autumn ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/bone.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} bone ()\n## @deftypefnx {} {@var{map} =} bone (@var{n})\n## Create color colormap.  This colormap varies from black to white with\n## gray-blue shades.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = bone (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"bone: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [1/8 1/8 1/8];\n  elseif (n == 2)\n    map = [1/16 1/8 1/8\n            1    1   1 ];\n  elseif (n > 2)\n    x = [0:n-1]' / (n-1);\n\n    idx = floor (3/4*n);\n    nel = n - idx + 1;    # number of elements\n    rem = mod (n, 8);\n    switch (rem)\n      case {2, 4}\n        base = 1 / (16 + 2*(n-rem));\n      case {5, 7}\n        base = 1 / (24 + 2*(n-rem));\n      otherwise\n        base = 0;\n    endswitch\n    r(1:idx,1) = 7/8 * x(1:idx);\n    r(idx:n,1) = linspace (7/8 * x(idx) + base, 1, nel);\n\n    idx = floor (3/8 * n);\n    nel = idx + 1;\n    g(1:idx,1) = 7/8 * x(1:idx);\n    g(idx:2*idx,1) = linspace (7/8 * x(idx), 7/8 * x(2*idx) + 1/8, nel);\n    g(2*idx+1:n,1) = 7/8 * x(2*idx+1:n) + 1/8;\n\n    base = 1 / (8*idx);\n    nel = idx;\n    b(1:idx,1) = linspace (base, 7/8 * x(idx) + 1/8, nel);\n    b(idx:n,1) = 7/8 * x(idx:n) + 1/8;\n\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'bone' colormap profile and as an image\n%! cmap = bone (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (bone ()), [256, 3])\n%!assert (size (bone (16)), [16, 3])\n\n%!assert (bone (1), [1/8, 1/8, 1/8])\n%!assert (bone (true), double ([1/8, 1/8, 1/8]))\n%!assert (bone (char (1)), double ([1/8, 1/8, 1/8]))\n%!assert (bone (int32 (1)), double ([1/8, 1/8, 1/8]))\n%!assert (bone (2), [1/16, 1/8, 1/8; 1 ,1, 1])\n\n%!assert (bone (0), zeros (0, 3))\n%!assert (bone (-1), zeros (0, 3))\n\n%!test\n%! a = [    0,     0,   1/8;\n%!       7/32, 11/32, 11/32;\n%!      23/48,  9/16,  9/16;\n%!      71/96, 25/32, 25/32;\n%!          1,     1,     1];\n%! assert (bone (5), a, eps);\n\n## Input validation\n%!error <N must be a scalar integer> bone (\"foo\")\n%!error <N must be a scalar integer> bone ([1, 2, 3])\n%!error <N must be a scalar integer> bone ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/brighten.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map_out} =} brighten (@var{beta})\n## @deftypefnx {} {@var{map_out} =} brighten (@var{map}, @var{beta})\n## @deftypefnx {} {@var{map_out} =} brighten (@var{h}, @var{beta})\n## @deftypefnx {} {} brighten (@dots{})\n## Brighten or darken a colormap.\n##\n## The argument @var{beta} must be a scalar between -1 and 1, where a negative\n## value darkens and a positive value brightens the colormap.\n##\n## If the @var{map} argument is omitted, the function is applied to the current\n## colormap.\n##\n## The first argument can also be a valid graphics handle @var{h}, in which\n## case @code{brighten} is applied to the colormap associated with this handle.\n##\n## If no output is specified then the result is written to the current\n## colormap.\n## @seealso{colormap, contrast}\n## @end deftypefn\n\nfunction rmap = brighten (arg1, beta)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  h = -1;\n  if (nargin == 1)\n    beta = arg1;\n    m = colormap ();\n    h = gcf ();\n  else\n    if (ishghandle (arg1))\n      h = arg1;\n      m = get (h, \"colormap\");\n    elseif (iscolormap (arg1))\n      m = arg1;\n    else\n      error (\"brighten: first argument must be a colormap or a graphics handle\");\n    endif\n  endif\n\n  if (! isscalar (beta) || beta <= -1 || beta >= 1)\n    error (\"brighten: BETA must be a scalar in the range (-1,1)\");\n  endif\n\n  if (beta > 0)\n    gamma = 1 - beta;\n  else\n    gamma = 1 / (1 + beta);\n  endif\n\n  if (nargout == 0)\n    if (ishghandle (h))\n      set (h, \"colormap\", m .^ gamma);\n    else\n      colormap (m .^ gamma);\n    endif\n  else\n    rmap = m .^ gamma;\n  endif\n\nendfunction\n\n\n%!demo\n%! ## First figure uses default grayscale colormap\n%! clf;\n%! colormap (gray (64));\n%! image (1:64, linspace (0, 1, 64), repmat ((1:64)', 1, 64));\n%! axis ([1, 64, 0, 1], \"xy\");\n%! set (gca, \"xtick\", []);\n%! title (\"default grayscale colormap\");\n%! pos = get (gcf, \"position\");\n%! pos(1) += pos(3) + 25;\n%! ## Second figure uses brightened grayscale colormap\n%! figure (\"position\", pos);\n%! colormap (gray (64));\n%! image (1:64, linspace (0, 1, 64), repmat ((1:64)', 1, 64));\n%! axis ([1, 64, 0, 1], \"xy\");\n%! set (gca, \"xtick\", []);\n%! brighten (0.5);\n%! title (\"grayscale colormap brightened by 0.5\");\n"
  },
  {
    "path": "scripts/image/cmpermute.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{Y}, @var{newmap}] =} cmpermute (@var{X}, @var{map})\n## @deftypefnx {} {[@var{Y}, @var{newmap}] =} cmpermute (@var{X}, @var{map}, @var{index})\n## Reorder colors in a colormap.\n##\n## When called with only two arguments, @code{cmpermute} randomly rearranges\n## the colormap @var{map} and returns a new colormap @var{newmap}.  It also\n## returns the indexed image @var{Y} which is the equivalent of the original\n## input image @var{X} when displayed using @var{newmap}.\n##\n## When called with an optional third argument the order of colors in the new\n## colormap is defined by @var{index}.\n##\n## @strong{Caution:} @var{index} should not have repeated elements or the\n## function will fail.\n##\n## @end deftypefn\n\nfunction [Y, newmap] = cmpermute (X, map, index)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  cls = class (X);\n  if (! any (strcmp (cls, {\"uint8\", \"uint16\", \"single\", \"double\"})))\n    error (\"cmpermute: invalid data type '%s'\", cls);\n  endif\n\n  if (! isreal (X) || issparse (X)\n      || (isfloat (X) && (any (X(:) < 1 || any (X(:) != fix (X(:)))))))\n    error (\"cmpermute: X must be an indexed image\");\n  endif\n\n  if (! iscolormap (map) || min (map(:)) < 0 || max (map(:)) > 1)\n    error (\"cmpermute: MAP must be a valid colormap\");\n  endif\n\n  if (nargin < 3)\n    index = randperm (rows (map));\n  elseif (! isvector (index) || length (index) != rows (map))\n    error (\"cmpermute: invalid parameter INDEX\");\n  endif\n\n  ## new colormap\n  newmap = map(index,:);\n\n  ## build reverse index\n  rindex = zeros (size (index));\n  rindex(index) = 1:length (index);\n\n  ## preserve class of input image in output\n  if (strcmp (cls, \"double\"))\n    Y = rindex(X);\n  elseif (strcmp (cls, \"single\"))\n    rindex = single (rindex);\n    Y = rindex(X);\n  else\n    ## adapt indices\n    rindex = feval (cls, rindex - 1);\n    ## 0-based indices\n    Y = rindex(single (X) + 1);\n  endif\n\nendfunction\n\n\n%!demo\n%! [Y, newmap] = cmpermute ([1:4], hot (4), 4:-1:1)\n%! ## colormap will be arranged in reverse order (so will image)\n\n%!shared X, map\n%! X = uint8 (magic (16));\n%! [X, map] = cmunique (X);\n\n%!test # random permutation, 0-based index\n%! [Y, newmap] = cmpermute (X, map);\n%! ## test we didn't lose colors\n%! assert (sort (map), sortrows (newmap));\n%! ## test if images are equal\n%! assert (map(double (X)+1), newmap(double (Y)+1));\n\n%!test # reverse map, 0-based index\n%! [Y, newmap] = cmpermute (X, map, rows (map):-1:1);\n%! ## we expect a reversed colormap\n%! assert (flipud (newmap), map);\n%! ## we expect reversed indices in image\n%! assert (X, max (Y(:)) - Y);\n\n%!shared X,map\n%! X = uint16 (magic (20));\n%! [X, map] = cmunique (X);\n\n%!test # random permutation, 1-based index\n%! [Y, newmap] = cmpermute (X, map);\n%! ## test we didn't lose colors\n%! assert (sort (map), sortrows (newmap));\n%! ## test if images are equal\n%! assert (map(X), newmap(Y));\n\n%!test # reverse map, 1-based index\n%! [Y, newmap] = cmpermute (X, map, rows (map):-1:1);\n%! ## we expect a reversed colormap\n%! assert (newmap (rows (newmap):-1:1,:), map);\n%! ## we expect reversed indices in image\n%! assert (X, max (Y(:)) + 1 - Y);\n\n## Test input validation\n%!error <Invalid call> cmpermute ()\n%!error <Invalid call> cmpermute (1)\n%!error <invalid data type 'uint32'> cmpermute (uint32 (magic (16)), jet (256))\n%!error <X must be an indexed image> cmpermute (1+i, jet (256))\n%!error <X must be an indexed image> cmpermute (sparse (1), jet (256))\n%!error <X must be an indexed image> cmpermute (0, jet (256))\n%!error <X must be an indexed image> cmpermute (1.5, jet (256))\n%!error <MAP must be a valid colormap> cmpermute (1, \"a\")\n%!error <MAP must be a valid colormap> cmpermute (1, i)\n%!error <MAP must be a valid colormap> cmpermute (1, ones (3,3,3))\n%!error <MAP must be a valid colormap> cmpermute (1, ones (3,2))\n%!error <MAP must be a valid colormap> cmpermute (1, [-1 1 1])\n%!error <MAP must be a valid colormap> cmpermute (1, [2 1 1])\n%!error <invalid parameter INDEX> cmpermute (1, [0 1 0;1 0 1], ones (3))\n%!error <invalid parameter INDEX> cmpermute (1, [0 1 0;1 0 1], 1:3)\n"
  },
  {
    "path": "scripts/image/cmunique.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{Y}, @var{newmap}] =} cmunique (@var{X}, @var{map})\n## @deftypefnx {} {[@var{Y}, @var{newmap}] =} cmunique (@var{RGB})\n## @deftypefnx {} {[@var{Y}, @var{newmap}] =} cmunique (@var{I})\n## Convert an input image @var{X} to an output indexed image @var{Y} which uses\n## the smallest colormap possible @var{newmap}.\n##\n## When the input is an indexed image (@var{X} with colormap @var{map}) the\n## output is a colormap @var{newmap} from which any repeated rows have been\n## eliminated.  The output image, @var{Y}, is the original input image with\n## the indices adjusted to match the new, possibly smaller, colormap.\n##\n## When the input is an RGB image (an @nospell{MxNx3} array), the output\n## colormap will contain one entry for every unique color in the original\n## image.  In the worst case the new map could have as many rows as the\n## number of pixels in the original image.\n##\n## When the input is a grayscale image @var{I}, the output colormap will\n## contain one entry for every unique intensity value in the original image.\n## In the worst case the new map could have as many rows as the number of\n## pixels in the original image.\n##\n## Implementation Details:\n##\n## @var{newmap} is always an Mx3 matrix, even if the input image is\n## an intensity grayscale image @var{I} (all three RGB planes are\n## assigned the same value).\n##\n## The output image is of class uint8 if the size of the new colormap is\n## less than or equal to 256.  Otherwise, the output image is of class double.\n##\n## @seealso{rgb2ind, gray2ind}\n## @end deftypefn\n\n\nfunction [Y, newmap] = cmunique (X, map)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  cls = class (X);\n  if (! any (strcmp (cls, {\"uint8\", \"uint16\", \"single\", \"double\"})))\n    error (\"cmunique: X is of invalid data type '%s'\", cls);\n  endif\n\n  if (nargin == 2)\n    ## (X, map) case\n    if (! iscolormap (map) || min (map(:)) < 0 || max (map(:)) > 1)\n      error (\"cmunique: MAP must be a valid colormap\");\n    endif\n    [newmap,i,j] = unique (map, \"rows\");  # calculate unique colormap\n    if (isfloat (X))\n      Y = j(X);               # find new indices\n    else\n      Y = j(double (X) + 1);  # find new indices, switch to 1-based index\n    endif\n  else\n    switch (size (X,3))\n      case 1\n        ## I case\n        [newmap,i,j] = unique (X);               # calculate unique colormap\n        newmap = repmat (newmap,1,3);            # get a RGB colormap\n        Y = reshape (j, rows (X), columns (X));  # Y is j reshaped\n      case 3\n        ## RGB case\n        ## build a map with all values\n        map = [X(:,:,1)(:), X(:,:,2)(:), X(:,:,3)(:)];\n        [newmap,i,j] = unique (map, \"rows\");     # calculate unique colormap\n        Y = reshape (j, rows (X), columns (X));  # Y is j reshaped\n      otherwise\n        error (\"cmunique: X is not a valid image\");\n    endswitch\n\n    ## if image was uint8 or uint16 we have to convert newmap to [0,1] range\n    if (isinteger (X))\n      newmap = double (newmap) / double (intmax (cls));\n    endif\n  endif\n\n  if (rows (newmap) <= 256)\n    ## convert Y to uint8 and 0-based indexing\n    Y = uint8 (Y-1);\n  endif\n\nendfunction\n\n\n%!demo\n%! [Y, newmap] = cmunique ([1:4;5:8], [hot(4);hot(4)])\n%! ## Both rows are equal since map maps colors to the same value\n%! ## cmunique will give the same indices to both\n\n## Check that output is uint8 in short colormaps\n%!test\n%! [Y, newmap] = cmunique ([1:4;5:8], [hot(4);hot(4)]);\n%! assert (Y, uint8 ([0:3;0:3]));\n%! assert (newmap, hot (4));\n\n## Check that output is double in bigger\n%!test\n%! [Y, newmap] = cmunique ([1:300;301:600], [hot(300);hot(300)]);\n%! assert (Y, [1:300;1:300]);\n%! assert (newmap, hot (300));\n\n## Check boundary case 256\n%!test\n%! [Y, newmap] = cmunique ([1:256;257:512], [hot(256);hot(256)]);\n%! assert (Y, uint8 ([0:255;0:255]));\n%! assert (newmap, hot (256));\n\n## Check boundary case 257\n%!test\n%! [Y, newmap] = cmunique ([1:257;258:514], [hot(257);hot(257)]);\n%! assert (Y, [1:257;1:257]);\n%! assert (newmap, hot (257));\n\n## Random RGB image\n%!test\n%! RGB = rand (10,10,3);\n%! [Y, newmap] = cmunique (RGB);\n%! assert (RGB(:,:,1), newmap(:,1)(Y+1));\n%! assert (RGB(:,:,2), newmap(:,2)(Y+1));\n%! assert (RGB(:,:,3), newmap(:,3)(Y+1));\n\n## Random uint8 RGB image\n%!test\n%! RGB = uint8 (rand (10,10,3)*255);\n%! RGBd = double (RGB) / 255;\n%! [Y, newmap] = cmunique (RGB);\n%! assert (RGBd(:,:,1), newmap(:,1)(Y+1));\n%! assert (RGBd(:,:,2), newmap(:,2)(Y+1));\n%! assert (RGBd(:,:,3), newmap(:,3)(Y+1));\n\n## Random uint16 RGB image\n%!test\n%! RGB = uint16 (rand (10,10,3)*65535);\n%! RGBd = double (RGB) / 65535;\n%! [Y, newmap] = cmunique (RGB);\n%! assert (RGBd(:,:,1), newmap(:,1)(Y+1));\n%! assert (RGBd(:,:,2), newmap(:,2)(Y+1));\n%! assert (RGBd(:,:,3), newmap(:,3)(Y+1));\n\n## Random I image\n%!test\n%! I = rand (10,10);\n%! [Y, newmap] = cmunique (I);\n%! assert (I, newmap(:,1)(Y+1));\n%! assert (I, newmap(:,2)(Y+1));\n%! assert (I, newmap(:,3)(Y+1));\n\n## Random uint8 I image\n%!test\n%! I = uint8 (rand (10,10)*256);\n%! Id = double (I) / 255;\n%! [Y, newmap] = cmunique (I);\n%! assert (Id, newmap(:,1)(Y+1));\n%! assert (Id, newmap(:,2)(Y+1));\n%! assert (Id, newmap(:,3)(Y+1));\n\n## Random uint16 I image\n%!test\n%! I = uint16 (rand (10,10)*65535);\n%! Id = double (I) / 65535;\n%! [Y, newmap] = cmunique (I);\n%! assert (Id, newmap(:,1)(Y+1));\n%! assert (Id, newmap(:,2)(Y+1));\n%! assert (Id, newmap(:,3)(Y+1));\n\n## Test input validation\n%!error <Invalid call> cmunique ()\n%!error <X is of invalid data type> cmunique (uint32 (magic (16)))\n%!error <MAP must be a valid colormap> cmunique (1, \"a\")\n%!error <MAP must be a valid colormap> cmunique (1, i)\n%!error <MAP must be a valid colormap> cmunique (1, ones (3,3,3))\n%!error <MAP must be a valid colormap> cmunique (1, ones (3,2))\n%!error <MAP must be a valid colormap> cmunique (1, [-1 1 1])\n%!error <MAP must be a valid colormap> cmunique (1, [2 1 1])\n"
  },
  {
    "path": "scripts/image/colorcube.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} colorcube ()\n## @deftypefnx {} {@var{map} =} colorcube (@var{n})\n## Create color colormap.  This colormap is composed of as many equally\n## spaced colors (not grays) in the RGB color space as possible.\n##\n## If there are not a perfect number @var{n} of regularly spaced colors then\n## the remaining entries in the colormap are gradients of pure red, green,\n## blue, and gray.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = colorcube (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"colorcube: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n < 9)\n    map = gray (n);\n    return;\n  endif\n\n  ## Create colorcube of evenly spaced points with side length of n^1/3\n  cubelen = fix (cbrt (n));\n  reserve = n - cubelen^3;\n\n  if (reserve == 0)\n    ## Steal space from blue to put the gray gradient\n    [r, g, b] = meshgrid (linspace (0,1,cubelen),\n                          linspace (0,1,cubelen),\n                          linspace (0,1,cubelen-1));\n  else\n    [r, g, b] = meshgrid (linspace (0,1,cubelen),\n                          linspace (0,1,cubelen),\n                          linspace (0,1,cubelen));\n  endif\n\n  ## Create map and weed out grays\n  map = [r(:), g(:), b(:)];\n  idx = any (bsxfun (@ne, map(:, 1), map(:, 2:3)), 2);\n  map = map(idx, :);\n\n  ## Weed out pure colors\n  idx = sum (map == 0, 2);\n  map = map(idx != 2, :);\n\n  ## Put in remaining gradients of pure red, green, blue, and gray\n  reserve = n - rows (map) - 1;\n  csteps = fix (reserve/4);\n  cstepsz = 1 / csteps;\n  cgrad = (cstepsz:cstepsz:1)';\n  gsteps = reserve - 3*csteps;\n  gstepsz = 1 / gsteps;\n  ggrad = (gstepsz:gstepsz:1)';\n  map = [map\n         cgrad, zeros(csteps, 1), zeros(csteps, 1)\n         zeros(csteps, 1), cgrad, zeros(csteps, 1)\n         zeros(csteps, 1), zeros(csteps, 1), cgrad\n         0, 0, 0\n         ggrad, ggrad, ggrad];\n\nendfunction\n\n\n%!demo\n%! ## Show the 'colorcube' colormap as an image\n%! image (1:64, linspace (0, 1, 64), repmat ((1:64)', 1, 64));\n%! axis ([1, 64, 0, 1], \"xy\");\n%! set (gca, \"xtick\", []);\n%! colormap (colorcube (64));\n\n\n%!assert (size (colorcube ()), [256, 3])\n%!assert (size (colorcube (16)), [16, 3])\n\n%!assert (colorcube (1), [0, 0, 0])\n%!assert (colorcube (true), double ([0, 0, 0]))\n%!assert (colorcube (char (1)), double ([0, 0, 0]))\n%!assert (colorcube (int32 (1)), double ([0, 0, 0]))\n\n%!assert (colorcube (0), zeros (0, 3))\n%!assert (colorcube (-1), zeros (0, 3))\n\n%!assert (colorcube (8), gray (8))\n\n%!test\n%! a = [1,   1,   0;\n%!      0,   1,   1;\n%!      1,   0,   1;\n%!      0.5, 0,   0;\n%!      1,   0,   0;\n%!      0,   0.5, 0;\n%!      0,   1,   0;\n%!      0,   0,   0.5;\n%!      0,   0,   1;\n%!      0,   0,   0;\n%!      0.5, 0.5, 0.5;\n%!      1,   1,   1];\n%! assert (colorcube (12), a, eps);\n\n## Input validation\n%!error <N must be a scalar integer> colorcube (\"foo\")\n%!error <N must be a scalar integer> colorcube ([1, 2, 3])\n%!error <N must be a scalar integer> colorcube ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/colormap.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{cmap} =} colormap ()\n## @deftypefnx {} {@var{cmap} =} colormap (@var{map})\n## @deftypefnx {} {@var{cmap} =} colormap (@qcode{\"default\"})\n## @deftypefnx {} {@var{cmap} =} colormap (@var{map_name})\n## @deftypefnx {} {@var{cmap} =} colormap (@var{hax}, @dots{})\n## @deftypefnx {} {@var{cmap} =} colormap (@var{hfig}, @dots{})\n## @deftypefnx {} {} colormap @var{map_name}\n## Query or set the current colormap.\n##\n## With no input arguments, @code{colormap} returns the current colormap.  If\n## there is no current figure, a new figure will be opened and the default\n## colormap will be returned.\n##\n## @code{colormap (@var{map})} sets the current colormap to @var{map}.  The\n## colormap should be an @var{n} row by 3 column matrix.  The columns\n## contain red, green, and blue intensities respectively.  All entries\n## must be between 0 and 1 inclusive.  The new colormap is returned.\n##\n## @code{colormap (@qcode{\"default\"})} restores the default colormap (the\n## @code{viridis} map with 256 entries).  The default colormap is returned.\n##\n## The map may also be specified by a string, @var{map_name}, which\n## is the name of a function that returns a colormap.\n##\n## If the first argument @var{hax} is an axes handle, then the colormap for\n## the specified axes is queried or set.  If the first argument @var{hfig} is a\n## figure handle, then the colormap for the specified figure is queried or set.\n##\n## For convenience, it is also possible to use this function with the\n## command form, @code{colormap @var{map_name}}.\n##\n## The list of built-in colormaps is:\n##\n## @c FIXME: It would be nice to display the actual colormap as an image\n## @c        in the PDF version of the documentation.\n## @multitable @columnfractions 0.15 .85\n## @headitem Map @tab Description\n## @item viridis @tab default\n## @item turbo @tab colormap traversing blue, cyan, green, yellow, red; modern replacement for jet.\n## @item jet @tab colormap traversing blue, cyan, green, yellow, red.\n## @item cubehelix @tab colormap traversing black, blue, green, red, white with increasing intensity.\n## @item hsv @tab cyclic colormap traversing Hue, Saturation, Value space.\n## @item rainbow @tab colormap traversing red, yellow, blue, green, violet.\n## @item ------------- @tab ---------------------------------------------------------------------------------------------\n## @item hot @tab colormap traversing black, red, orange, yellow, white.\n## @item cool @tab colormap traversing cyan, purple, magenta.\n## @item spring @tab colormap traversing magenta to yellow.\n## @item summer @tab colormap traversing green to yellow.\n## @item autumn @tab colormap traversing red, orange, yellow.\n## @item winter @tab colormap traversing blue to green.\n## @item ------------- @tab ---------------------------------------------------------------------------------------------\n## @item gray @tab colormap traversing black to white in shades of gray.\n## @item bone @tab colormap traversing black, gray-blue, white.\n## @item copper @tab colormap traversing black to light copper.\n## @item pink @tab colormap traversing black, gray-pink, white.\n## @item ocean @tab colormap traversing black, dark-blue, white.\n## @item ------------- @tab ---------------------------------------------------------------------------------------------\n## @item colorcube @tab equally spaced colors in RGB color space.\n## @item flag @tab cyclic 4-color map of red, white, blue, black.\n## @item lines @tab cyclic colormap with colors from axes @qcode{\"ColorOrder\"} property.\n## @item prism @tab cyclic 6-color map of red, orange, yellow, green, blue, violet.\n## @item ------------- @tab ---------------------------------------------------------------------------------------------\n## @item white @tab all white colormap (no colors).\n## @end multitable\n## @seealso{viridis, turbo, jet, cubehelix, hsv, rainbow, hot, cool, spring,\n## summer, autumn, winter, gray, bone, copper, pink, ocean, colorcube, flag,\n## lines, prism, white}\n## @end deftypefn\n\nfunction cmap = colormap (varargin)\n\n  hax = [];\n  if (nargin > 0)\n    if (isscalar (varargin{1}) && ishghandle (varargin{1}))\n      htmp = varargin{1};\n      if (isaxes (htmp))\n        hax = htmp;\n      elseif (isfigure (htmp))\n        hax = [];\n      else\n        error (\"colormap: target argument must be a figure or axes handle\");\n      endif\n      ## Delete first item in list that was just processed.\n      varargin(1) = [];\n      nargin = nargin - 1;\n    endif\n  endif\n\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  if (! isempty (hax))\n    have_fig = false;\n    cf = hax;\n  else\n    have_fig = true;\n    cf = get (0, \"currentfigure\");\n  endif\n\n  if (nargin == 1)\n    map = varargin{1};\n    if (ischar (map))\n      map = lower (map);\n      if (strcmp (map, \"default\"))\n        map = viridis (256);\n      else\n        try\n          map = feval (map);\n        catch\n          error (\"colormap: failed to set MAP <%s>\", map);\n        end_try_catch\n      endif\n    endif\n\n    if (! isempty (map))\n      if (! (isnumeric (map) && isreal (map)\n             && ndims (map) == 2 && columns (map) == 3))\n        error (\"colormap: MAP must be a real-valued N x 3 ([R,G,B]) matrix\");\n      endif\n      if (any (map(:) < 0) || any (map(:) > 1))\n        error (\"colormap: all MAP values must be in the range [0,1]\");\n      endif\n      if (isempty (cf))\n        cf = gcf ();\n      endif\n      ## Set the new colormap\n      set (cf, \"colormap\", map);\n      if (have_fig)\n        ## Matlab Compatibility: Also clear any axes colormaps as of R2018A.\n        hax = findobj (cf, '-depth', 1, 'type', 'axes');\n        set (hax, 'colormap', []);\n      endif\n    endif\n  endif\n\n  ## Return current colormap.\n  if (nargout > 0 || nargin == 0)\n    if (isempty (cf))\n      cf = gcf ();\n    endif\n    cmap = get (cf, \"colormap\");\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Create an image for displaying a colormap\n%! image (1:64, linspace (0, 1, 64), repmat ((1:64)', 1, 64));\n%! axis ([1, 64, 0, 1], \"ticy\", \"xy\");\n%! ## Show 'viridis' colormap\n%! colormap (viridis (64));\n%! title \"colormap (viridis (64))\"\n%! disp (\"Press a key to continue\");\n%! pause ();\n%! ## Show 'colorcube' colormap\n%! colormap (colorcube (64));\n%! title \"colormap (colorcube (64))\"\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   cmaptst = [0 1 0; 1 0 1; 1 1 1];\n%!   cmap = colormap (cmaptst);\n%!   assert (cmap, cmaptst);\n%!   cmap = colormap ();\n%!   assert (cmap, cmaptst);\n%!   cmap = (get (gcf, \"colormap\"));\n%!   assert (cmap, cmaptst);\n%!   colormap (\"default\");\n%!   assert (colormap (), viridis (256));\n%!   colormap (\"ocean\");\n%!   assert (colormap, ocean (256));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*65674>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax1 = subplot (2, 1, 1);\n%!   hax2 = subplot (2, 1, 2);\n%!   cmaptst = [0 1 0; 1 0 1; 1 1 1];\n%!   colormap (cmaptst);\n%!   colormap (hax1, jet (16));\n%!   colormap (hax2, pink (16));\n%!   assert (map = colormap (hf), cmaptst);\n%!   assert (map = colormap (hax1), jet (16));\n%!   assert (map = colormap (hax2), pink (16));\n%!   colormap (gray (4));\n%!   assert (map = colormap (hf), gray (4));\n%!   assert (map = colormap (hax1), gray (4));\n%!   assert (map = colormap (hax2), gray (4));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <target argument must be a figure or axes handle> colormap (0)\n%!error <Invalid call> colormap (1,2,3)\n%!error <failed to set MAP .invalid_map_name.> colormap (\"invalid_map_name\")\n%!error <MAP must be a real-valued N x 3> colormap ({1,2,3})\n%!error <MAP must be a real-valued N x 3> colormap ([1 i 1])\n%!error <MAP must be a real-valued N x 3> colormap (ones (3,3,3))\n%!error <MAP must be a real-valued N x 3> colormap ([1 0 1 0])\n%!error <all MAP values must be in the range> colormap ([-1 0 0])\n%!error <all MAP values must be in the range> colormap ([2 0 0])\n"
  },
  {
    "path": "scripts/image/contrast.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{cmap} =} contrast (@var{x})\n## @deftypefnx {} {@var{cmap} =} contrast (@var{x}, @var{n})\n## Return a gray colormap that maximizes the contrast in an image.\n##\n## The returned colormap will have @var{n} rows.  If @var{n} is not defined\n## then the size of the current colormap is used.\n## @seealso{colormap, brighten}\n## @end deftypefn\n\nfunction cmap = contrast (x, n)\n\n  if (nargin == 1)\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 64;\n    endif\n  else\n    if (! isscalar (n))\n      error (\"contrast: N must be a scalar\");\n    endif\n    n = double (n);\n  endif\n\n  x = x(:);\n  minx = min (x);\n  cmap = find (diff (sort ([round(n * ((x - minx) ./ (max(x) - minx))); [0:n]'])));\n  minm = min (cmap);\n  cmap = (cmap - minm) ./ (max (cmap) - minm);\n  cmap = [cmap, cmap, cmap];\n\nendfunction\n\n\n%!demo\n%! clf;\n%! img = reshape (1:100, 10, 10);\n%! imagesc (img);\n%! colormap (gray (64));\n%! title (\"Image with default 64 gray levels\");\n%! pos = get (gcf, \"position\");\n%! pos(1) += pos(3) + 25;\n%! figure (\"position\", pos);\n%! colormap (contrast (img, 10));\n%! imagesc (img);\n%! title (\"Image with contrast enhanced\");\n\n%!assert (contrast (1:100,10), [([0:9]/9)',([0:9]/9)',([0:9]/9)'], 1e-10)\n"
  },
  {
    "path": "scripts/image/cool.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} cool ()\n## @deftypefnx {} {@var{map} =} cool (@var{n})\n## Create color colormap.  The colormap varies from cyan to magenta.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = cool (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"cool: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [0, 1, 1];\n  elseif (n > 1)\n    r = [0:(n-1)]' / (n - 1);\n    g = 1 - r;\n    b = ones (n, 1);\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'cool' colormap profile and as an image\n%! cmap = cool (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (cool ()), [256, 3])\n%!assert (size (cool (16)), [16, 3])\n\n%!assert (cool (1), [0, 1, 1])\n%!assert (cool (true), double ([0, 1, 1]))\n%!assert (cool (char (1)), double ([0, 1, 1]))\n%!assert (cool (int32 (1)), double ([0, 1, 1]))\n\n%!assert (cool (0), zeros (0, 3))\n%!assert (cool (-1), zeros (0, 3))\n\n%!assert (cool (11), [[0:0.1:1]; [1:-0.1:0]; ones(1,11)]', eps)\n\n## Input validation\n%!error <N must be a scalar integer> cool (\"foo\")\n%!error <N must be a scalar integer> cool ([1, 2, 3])\n%!error <N must be a scalar integer> cool ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/copper.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} copper ()\n## @deftypefnx {} {@var{map} =} copper (@var{n})\n## Create color colormap.  This colormap varies from black to a light copper\n## tone.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = copper (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"copper: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [0, 0, 0];\n  elseif (n > 1)\n    x = [0:(n-1)]' / (n - 1);\n    r = (x < 4/5) .* (5/4 * x) ...\n      + (x >= 4/5);\n    g = 0.7812 * x;\n    b = 0.4975 * x;\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'copper' colormap profile and as an image\n%! cmap = copper (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (copper ()), [256, 3])\n%!assert (size (copper (16)), [16, 3])\n\n%!assert (copper (1), [0, 0, 0])\n%!assert (copper (true), double ([0, 0, 0]))\n%!assert (copper (char (1)), double ([0, 0, 0]))\n%!assert (copper (int32 (1)), double ([0, 0, 0]))\n\n%!assert (copper (0), zeros (0, 3))\n%!assert (copper (-1), zeros (0, 3))\n\n%!test\n%! a = [0.25, 0.15624, 0.0995] .* [0:5]';\n%! a(6) = 1;\n%! assert (copper (6), a, eps);\n\n## Input validation\n%!error <N must be a scalar integer> copper (\"foo\")\n%!error <N must be a scalar integer> copper ([1, 2, 3])\n%!error <N must be a scalar integer> copper ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/cubehelix.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} cubehelix ()\n## @deftypefnx {} {@var{map} =} cubehelix (@var{n})\n## @deftypefnx {} {@var{map} =} cubehelix (@var{n}, @var{start}, @var{rots}, @var{hue}, @var{gamma})\n## Create cubehelix colormap.\n##\n## This colormap varies from black to white going though blue, green, and red\n## tones while maintaining a monotonically increasing perception of intensity.\n## This is achieved by traversing a color cube from black to white through\n## a helix, hence the name cubehelix, while taking into account the perceived\n## brightness of each channel according to the NTSC specifications from 1953.\n##\n## @example\n## rgbplot (cubehelix (256))\n## @end example\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n##\n## Reference: @nospell{D.A Green},\n## \"A @nospell{colour} scheme for the display of astronomical intensity\n## images\", @cite{Bulletin of the Astronomical Society of India}, 39,\n## @w{p.@: 289}, 2011.\n##\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = cubehelix (n, start = 0.5, rots = -1.5, hue = 1, gamma = 1)\n\n  if (nargin > 0)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"cubehelix: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n > 1)\n    coeff = [ -0.14861  -0.29227   1.97294\n               1.78277  -0.90649   0.00000];\n\n    fract = ((0:n-1) / (n-1))';\n    angle = 2 * pi * (start/3 + 1 + rots*fract);\n    fract .^= gamma;\n    amp   = hue * fract .* (1-fract) /2;\n    map   = fract + amp .* ([cos(angle) sin(angle)] * coeff);\n\n    ## Clip values (only in case users have changed values of hue or gamma)\n    map(map < 0) = 0;\n    map(map > 1) = 1;\n  elseif (n > 0)\n    map = [0, 0, 0];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n## A better demo of this colormap would be a 3-D plot in NTSC instead of\n## RGB values.  That would really show what this colormap is about.\n%!demo\n%! ## Show the 'cubehelix' colormap profile and as an image\n%! cmap = cubehelix (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (cubehelix ()), [256, 3])\n%!assert (size (cubehelix (16)), [16, 3])\n\n%!assert (cubehelix (1), [0,0,0])\n%!assert (cubehelix (true), double ([0,0,0]))\n%!assert (cubehelix (char (1)), double ([0,0,0]))\n%!assert (cubehelix (int32 (1)), double ([0,0,0]))\n\n%!assert (cubehelix (0), zeros (0, 3))\n%!assert (cubehelix (-1), zeros (0, 3))\n\n%!assert (cubehelix (2), [0, 0, 0; 1, 1, 1])\n%!assert ([cubehelix]([1,end],:), [0, 0, 0; 1, 1, 1])\n\n%!shared a\n%! a = [0,                   0,                   0;\n%!      0.17004232121057959, 0.43679759647517287, 0.22372555555555556;\n%!      0.82995767878942041, 0.56320240352482713, 0.77627444444444445;\n%!      1,                   1,                   1];\n\n%!assert (cubehelix (4), a, eps)\n\n%!shared  # Clear shared varibles to avoid echo on unrelated test errors.\n\n## Input validation\n%!error <N must be a scalar integer> cubehelix (\"foo\")\n%!error <N must be a scalar integer> cubehelix ([1, 2, 3])\n%!error <N must be a scalar integer> cubehelix ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/dither.m",
    "content": "## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## This program is free software: you can redistribute it and/or modify\n## it under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## This program is distributed in the hope that it will be useful,\n## but WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with this program; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{X} =} dither (@var{RGB}, @var{map})\n## @deftypefnx {} {@var{X} =} dither (@var{RGB}, @var{map}, @var{Qm}, @var{Qe})\n## @deftypefnx {} {@var{BW} =} dither (@var{I})\n## Quantize an image using dithering to increase the apparent color resolution.\n##\n## @code{@var{X} = dither (@var{RGB},@var{map})} creates an indexed image\n## approximation.  It uses the color provided in the colormap, and uses\n## dithering to increase apparent color resolution.  The\n## @nospell{Floyd-Steinberg} error\n## filter is:\n## @tex\n## $$\n## \\left[\\matrix{   & x & 7\\cr\n##                3 & 5 & 1}\\right]/16\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##      x    7/16\n## 3/16 5/16 1/16\n## @end group\n## @end example\n##\n## @end ifnottex\n## It uses a raster scan and no weight renormalization at boundaries.\n## The default values are used: @var{Qm}=5 and @var{Qe}=8.\n##\n## @var{RGB} is a MxNx3 array with values in @code{[0, 1]} (double) or\n## @code{[0, 255]} (uint8).\n##\n## @var{map} is Cx3 matrix holding RGB triplets in @code{[0, 1]} (double).\n##\n## @var{Qm} is the number of quantization bits per axis for inverse colormap\n## (default: 5).\n##\n## @var{Qe} is the number of quantization bits for error diffusion (default: 8,\n## max 16).\n##\n## @var{X} is a MxN indexed image (uint8 if c@leq{}256, else uint16) for the\n## colormap @var{map} provided.\n##\n## @var{Qm} is the number of quantization bits along each color axis for the\n## inverse colormap.  @var{Qm} determines the resolution of this grid along\n## each color axis (R, G, B).  @var{Qm} defines the precision of the color\n## space discretization used to map input RGB values to those colors\n## available in the colormap.  @var{Qe} is the number of quantization bits\n## for the color space error calculations in the @nospell{Floyd-Steinberg}\n## error diffusion algorithm.  It controls the precision of the error values\n## that are calculated and propagated during dithering.  If @var{Qe} <\n## @var{Qm}, the error diffusion process may lose precision.  Therefore\n## dithering cannot be performed, and the function returns an undithered\n## indexed image.\n##\n## @code{@var{BW} = dither (@var{I})} converts the grayscale input image\n## @var{I} into binary applying dithering in the process.  The output image\n## @var{BW} is a black and white image where dithering creates the illusion\n## of shades of gray.\n##\n## References:\n##\n## @itemize\n## @item\n## @nospell{R. W. Floyd and L. Steinberg}, \"An Adaptive Algorithm for Spatial\n## Gray Scale\", @cite{International Symposium Digest of Technical Papers},\n## Society for Information Displays, @w{p.@: 36}, 1975.\n##\n## @item\n## @nospell{R. Ulichney}, @cite{Digital Halftoning}, The MIT Press, 1987.\n## @end itemize\n##\n## @seealso{rgb2ind, gray2ind}\n## @end deftypefn\n\nfunction X = dither (RGB, map, Qm = 5, Qe = 8)\n\n  if (nargin < 1 || nargin > 4 || nargin == 3)\n    print_usage ();\n  endif\n\n  if (ndims (RGB) == 2)\n    RGB = cat (3, RGB, RGB, RGB);  # Duplicate grayscale to RGB\n    if nargin < 2,\n      map = [0 0 0; 1 1 1];  # binary (black and white) colormap\n      Qm = 1;\n    endif\n  endif\n  if (ndims (RGB) != 3 || size (RGB, 3) != 3)\n    error ('dither: RGB must be an m x n x 3 array');\n  endif\n  if (! ismatrix (map) || size (map, 2) != 3 ...\n      || min (map(:)) < 0 || max (map(:)) > 1)\n    error ('dither: Colormap must be a c x 3 matrix');\n  endif\n  if (nargin > 2)\n    if (Qm < 1 || Qe < 1 || fix (Qm) != Qm || fix (Qe) != Qe)\n      error ('Qm and Qe must be a positive integers');\n    elseif Qe < Qm\n      warning ('dither: Qe < Qm, returning undithered image');\n      X = zeros (size (RGB, 1), size (RGB, 2), 'uint16');\n      for i = 1:size (RGB, 1)\n        for j = 1:size (RGB, 2)\n          X(i, j) = rgb2indLUT (RGB(i, j, :), map, Qm);\n        endfor\n      endfor\n      if (size (map, 1) <= 256)\n        X = uint8 (X);\n      endif\n      return;\n    endif\n  endif\n  Qe = min (Qe, 16);  # Cap Qe to avoid excessive precision\n\n  ## Scale RGB and map to [0, 1]\n  if (isa (RGB, 'uint8'))\n    RGB = double (RGB) / 255;\n  elseif (max (RGB(:)) > 1)\n    RGB = double (RGB) / 255;\n  endif\n  RGB = max (0, min (1, RGB));\n  if (max (map(:)) > 1)\n    map = double (map) / 255;\n  endif\n  map = max (0, min (1, map));\n\n  ## Initialize output\n  [h, w, _] = size (RGB);\n  X = zeros (h, w, 'uint16');  # Indices (1-based)\n\n  ## Floyd-Steinberg weights (raster scan, no renormalization)\n  FSweights = [0 0 7; 3 5 1] / 16;  # Sum = 1\n\n  ## neighbor offsets and weights\n  offsets = [0 1; 1 -1; 1 0; 1 1];\n  weights = [FSweights(1, 3), FSweights(2, 1), FSweights(2, 2), ...\n             FSweights(2, 3)];\n\n  ## Quantization levels for error (Qe)\n  n_levels = 2^Qe;\n  error_scale = n_levels - 1;\n\n  ## Process pixels in raster order\n  for i = 1:h\n    for j = 1:w\n      ## Get current pixel (with accumulated errors)\n      pixel = RGB(i, j, :);\n      pixel = reshape (max (0, min (1, pixel)), 1, 3);  # Clamp to [0, 1]\n\n      ## Quantize to nearest colormap color\n      id = rgb2indLUT (pixel, map, Qm);\n      X(i, j) = id;\n\n      ## Compute quantization error\n      chosen_color = map(id+1, :);\n      error = pixel - chosen_color;  # 1x3\n      error = round (error * error_scale) / error_scale;  # Quantize to Qe bits\n\n      ## Diffuse error to neighboring pixels (no renormalization)\n      for k = 1:length (weights)\n        ni = i + offsets(k, 1);\n        nj = j + offsets(k, 2);\n        if (ni <= h && nj >= 1 && nj <= w)\n          ## Extract current pixel value as 1x3\n          current = reshape (RGB(ni, nj, :), 1, 3);\n          ## Apply weighted error to each channel\n          new_value = current + error * weights(k);\n          RGB(ni, nj, :) = reshape (new_value, 1, 3);\n        endif\n      endfor\n    endfor\n  endfor\n\n  ## Convert output to uint8 if colormap size allows\n  if size (map, 1) <= 256\n    X = uint8 (X);\n  endif\nendfunction\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{id} =} rgb2indLUT (@var{pixel}, @var{map})\n## @deftypefnx {} {@var{id} =} rgb2indLUT (@var{pixel}, @var{map}, @var{Qm})\n## Map an RGB pixel to the nearest colormap index using a lookup table.\n##\n## @code{@var{id} = rgb2indLUT (@var{pixel}, @var{map})} returns the 1-based\n## index of the closest color in the colormap @var{map} for the input RGB pixel\n## (1x3 vector), using a quantized inverse colormap with 2^5 bins per RGB axis.\n##\n## @code{@var{id} = rgb2indLUT (@var{pixel}, @var{map}, @var{Qm})} uses\n## @var{Qm} bits for quantization per RGB axis.\n##\n## @var{pixel} is a 1x3 vector @code{[R, G, B]}, values in @code{[0, 1]}\n## (double) or @code{[0, 255]} (uint8).\n##\n## @var{map} is a Cx3 matrix, each row an RGB triplet in @code{[0, 1]}\n## (double).\n##\n## @var{Qm} is the number of quantization bits per axis (default: 5).\n##\n## @var{id} is an index (1-based) into the colormap @var{map} for the closest\n## color.\n##\n## Notes: It uses a persistent lookup table (LUT) for speed; LUT is recomputed\n## if @var{map} or @var{Qm} changes; warns if @var{Qm} is too large (>8) due\n## to memory constraints; assumes input @var{pixel} and @var{map} are properly\n## scaled (pixel auto-scaled if needed).\n##\n## Example:\n##\n## @example\n## id = rgb2indLUT (pixel, map);\n## @end example\n##\n## @end deftypefn\n\nfunction id = rgb2indLUT (pixel, map, Qm = 5)\n  ## Validate inputs\n  if (nargin < 2)\n    error (['rgb2indLUT: Not enough input arguments.  ' ...\n    'Pixel and colormap required']);\n  endif\n  if (length (pixel) != 3)\n    error ('rgb2indLUT: Pixel must be a 1x3 RGB vector');\n    if (! isvector (pixel))\n      [s, i] = sort (size (pixel),'descend');\n      pixel = permute (pixel, i);\n    endif\n  endif\n  if (! ismatrix (map) || size (map, 2) != 3)\n    error ('rgb2indLUT: Colormap must be a C-by-3 matrix');\n  endif\n  if (! isscalar (Qm) || Qm < 1 || floor (Qm) != Qm)\n    error ('rgb2indLUT: Qm must be a positive integer');\n  endif\n  if (Qm > 8)\n    warning ('rgb2indLUT: Qm > 8 may use excessive memory (%d^3 bins)', 2^Qm);\n  endif\n\n  ## Scale pixel to [0, 1]\n  if (isa (pixel, 'uint8'))\n    pixel = double (pixel) / 255;  # Convert to [0, 1]\n  elseif (max (pixel(:)) > 1)\n    pixel = double (pixel) / 255;  # Assume [0, 255] if values exceed 1\n  endif\n  pixel = max (0, min (1, pixel));  # Clamp to [0, 1]\n\n  ## Ensure map is in [0, 1]\n  if (max (map(:)) > 1)\n    map = double(map) / 255;\n  endif\n  map = max (0, min (1, map));\n\n  ## Persistent variables for LUT\n  persistent lut last_map last_Qm;\n\n  ## Check if we need to recompute the LUT\n  recompute = (isempty (lut) || Qm != last_Qm || ! isequal (map, last_map));\n\n  ## Number of bins per axis\n  n_bins = 2^Qm;\n\n  ## Scale pixel to [0, n_bins-1] for indexing\n  bin_idx = round (pixel * (n_bins - 1)) + 1;\n\n  if recompute\n    ## Initialize LUT: n_bins x n_bins x n_bins array of colormap indices\n    lut = zeros (n_bins, n_bins, n_bins, 'uint16');\n\n    ## Compute bin centers for distance calculations\n    bin_centers = (0:(n_bins-1))' / (n_bins-1);  # [0, 1] range, column vector\n    [R, G, B] = ndims_grid (n_bins, n_bins, n_bins);  # Meshgrid for bin indices\n    bin_rgb = [bin_centers(R(:)), bin_centers(G(:)), ...\n               bin_centers(B(:))];  # n_bins^3 x 3\n\n    ## Compute Euclidean distances from each bin to each colormap color\n    c = size (map, 1);  # Number of colors\n    distances = zeros (n_bins^3, c);\n    for i = 1:c\n      diff = bin_rgb - map(i, :);  # n_bins^3 x 3\n      distances(:, i) = sqrt (sum (diff.^2, 2));  # n_bins^3 x 1\n    endfor\n\n    ## Find the nearest colormap index (1-based) for each bin\n    [_, indices] = min (distances, [], 2);\n    lut(:) = indices;  # Assign to LUT\n\n    ## Update cached parameters\n    last_map = map;\n    last_Qm = Qm;\n  endif\n\n  ## Look up the colormap index\n  id = lut(bin_idx(1), bin_idx(2), bin_idx(3)) - 1;\nendfunction\n\nfunction [X, Y, Z] = ndims_grid (nx, ny, nz)\n  ## Create 3-D grid indices (emulates meshgrid for 3-D).\n  [x, y, z] = ind2sub ([nx, ny, nz], 1:(nx*ny*nz));\n  X = reshape (x, nx, ny, nz);\n  Y = reshape (y, nx, ny, nz);\n  Z = reshape (z, nx, ny, nz);\nendfunction\n\n%!demo\n%! ## Solid gray\n%!\n%! I = ones (256)/2;\n%! X = dither (I);\n%! clf;\n%! subplot (121); imshow (I); title ('original');\n%! subplot (122); imshow (double(X)); title ('dithered');\n\n%!demo\n%! ## Four solid gray levels\n%!\n%! I = [ones(256,64)/4, ones(256,64)/2, ones(256,64)*3/4, ones(256,64)*7/8];\n%! X = dither (I);\n%! clf;\n%! subplot (121); imshow (I); title ('original');\n%! subplot (122); imshow (double (X)); title ('dithered');\n\n%!demo\n%! ## Black-White Gradient\n%!\n%! I = repmat ([0:255]./255,256,1);\n%! X = dither (I);\n%! clf;\n%! subplot (121); imshow (I); title ('original');\n%! subplot (122); imshow (double (X)); title ('dithered');\n\n%!demo\n%! ## Color Gradient\n%!\n%! width = 256; height = 256;\n%! upperleft = [1, 0, 0];   # Red\n%! upperright = [0, 1, 0];  # Green\n%! lowerleft = [0, 0, 1];   # Blue\n%! lowerright = [0, 0, 0];  # Black\n%!\n%! ## Create a grid for interpolation\n%! [x, y] = meshgrid (linspace (0, 1, width), linspace (0, 1, height));\n%! ## Initialize the 3-D array for the image\n%! image = zeros (height, width, 3);\n%! ## Calculate the interpolated colors for each point\n%! ## The logic is a bilinear interpolation of the four corner colors\n%! ## The first dimension of the `image` matrix is the height (y-axis) and the\n%! ## second is the width (x-axis)\n%! image(:, :, 1) = (1 - x) .* (1 - y) * lowerleft(1) + ...\n%!                  x .* (1 - y) * lowerright(1) + ...\n%!                  (1 - x) .* y * upperleft(1) + x .* y * upperright(1);\n%! image(:, :, 2) = (1 - x) .* (1 - y) * lowerleft(2) + ...\n%!                  x .* (1 - y) * lowerright(2) + ...\n%!                  (1 - x) .* y * upperleft(2) + x .* y * upperright(2);\n%! image(:, :, 3) = (1 - x) .* (1 - y) * lowerleft(3) + ...\n%!                  x .* (1 - y) * lowerright(3) + ...\n%!                  (1 - x) .* y * upperleft(3) + x .* y * upperright(3);\n%!\n%! ## Use the corner colors to define the colormap\n%! map = [upperleft; upperright; lowerleft; lowerright];\n%! ## Apply dither\n%! X = dither (image, map);\n%!\n%! ## Display the results\n%! clf;\n%! subplot (121); imshow (image); title ('original');\n%! subplot (122); imshow (reshape (map(X(:)+1,:), [size(X) 3]));\n%! title ('dithered');\n\n%!demo\n%! # Lenna\n%! url = ['https://upload.wikimedia.org/wikipedia/en/7/7d/' ...\n%!       'Lenna_%28test_image%29.png'];\n%! rgb_image = imread (url);\n%! map = [226 143 122; 199 127 124; 175 71 82; 230 191 168; ...\n%!        210 100 98; 132 50 81; 94 24 65; 149 97 139] / 255;\n%! X = dither (rgb_image, map);\n%! I = reshape (map(X(:)+1,:), [size(X) 3]);\n%! clf;\n%! subplot (121); imshow (rgb_image); title ('original');\n%! subplot (122); imshow (I); title ('dithered');\n\n## Test input validation\n%!error dither ()\n%!error dither (permute (1:3,[1 3 2]))\n%!error dither (1, 1)\n%!error dither (1, 1:3)\n%!error dither (1, [0 0 0]')\n%!error dither (1, [0 0 0], 0)\n%!error dither (1, [0 0 0], 0, 0)\n%!error dither (1, [0 0 0], -1, 1)\n%!error dither (1, [0 0 0], 1, -1)\n\n%!test\n%! X = dither (0, [0 0 0; 1 1 1], 1, 1);\n%! assert (X, uint8 (0));\n\n%!test\n%! X = dither (1, [0 0 0; 1 1 1], 1, 1);\n%! assert (X, uint8 (1));\n\n%!test\n%! X = dither (repmat (ones (3)/2,1,1,3), [0 0 0; 1 1 1], 4, 4);\n%! assert (X, uint8 ([1 0 1; 0 1 0; 1 0 1]));\n\n%!test\n%! X = dither (repmat (ones (3)/4,1,1,3), [0 0 0; 1 1 1], 4, 4);\n%! assert (X, uint8 ([0 0 0; 0 1 0; 0 0 0]));\n\n%!test\n%! X = dither (repmat (ones (3)*3/4,1,1,3), [0 0 0; 1 1 1], 4, 4);\n%! assert (X, uint8 ([1 1 1; 1 0 1; 1 1 1]));\n"
  },
  {
    "path": "scripts/image/flag.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} flag ()\n## @deftypefnx {} {@var{map} =} flag (@var{n})\n## Create color colormap.  This colormap cycles through red, white, blue, and\n## black with each index change.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = flag (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"flag: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n  if (n == 1)\n    map = [1, 0, 0];\n  elseif (n > 1)\n    C = [1, 0, 0; 1, 1, 1; 0, 0, 1; 0, 0, 0];\n    map = C(rem (0:(n-1), 4) + 1, :);\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'flag' colormap profile and as an image\n%! cmap = flag (12);  # 4 colors, therefore cycle 3 times\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (flag ()), [256, 3])\n%!assert (size (flag (16)), [16, 3])\n\n%!assert (flag (1), [1, 0, 0])\n%!assert (flag (true), double ([1, 0, 0]))\n%!assert (flag (char (1)), double ([1, 0, 0]))\n%!assert (flag (int32 (1)), double ([1, 0, 0]))\n\n%!assert (flag (0), zeros (0, 3))\n%!assert (flag (-1), zeros (0, 3))\n\n%!test\n%! a = [1,   0,   0;\n%!      1,   1,   1;\n%!      0,   0,   1;\n%!      0,   0,   0;\n%!      1,   0,   0;\n%!      1,   1,   1;\n%!      0,   0,   1;\n%!      0,   0,   0;\n%!      1,   0,   0;\n%!      1,   1,   1;\n%!      0,   0,   1;\n%!      0,   0,   0];\n%! assert (flag (12), a, eps);\n\n## Input validation\n%!error <N must be a scalar integer> flag (\"foo\")\n%!error <N must be a scalar integer> flag ([1, 2, 3])\n%!error <N must be a scalar integer> flag ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/frame2im.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{x}, @var{map}] =} frame2im (@var{frame})\n## Convert movie frame to indexed image.\n##\n## A movie frame is simply a struct with the fields @qcode{\"cdata\"} and\n## @qcode{\"colormap\"}.\n##\n## Support for N-dimensional images or movies is given when @var{frame} is a\n## struct array.  In such cases, @var{x} will be a @nospell{MxNx1xK or MxNx3xK}\n## for indexed and RGB movies respectively, with each frame concatenated\n## along the 4th dimension.\n##\n## @seealso{im2frame, getframe}\n## @end deftypefn\n\nfunction [x, map] = frame2im (frame)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! all (isfield (frame, {\"cdata\", \"colormap\"})))\n    error (\"frame2im: F must be a struct with the fields colormap and cdata\");\n  endif\n\n  n = numel (frame);\n  if (n == 0)\n    error (\"frame2im: FRAME is empty\");\n  else\n    x   = [frame.cdata];\n    map = frame(1).colormap;\n  endif\n\n  ## support for N-dimensional images if we receive a struct array\n  if (n > 1)\n    x = reshape (x, rows (x), columns (x) / n, n, size (frame(1).cdata, 3));\n    x = permute (x, [1 2 4 3]);\n  endif\n\nendfunction\n\n\n%!function f = make_rgb_f ()\n%!  f = randi ([0 255], 10, 20, 3);\n%!endfunction\n\n%!function f = make_ind_f ()\n%!  f = randi ([1 100], 10, 20, 2);\n%!endfunction\n\n%!test\n%! x = make_ind_f ();\n%! cmap = jet (100);\n%! frame = struct (\"cdata\", x, \"colormap\", cmap);\n%! [rx, rcmap] = frame2im (frame);\n%! assert (rx, x);\n%! assert (rcmap, cmap);\n\n%!test\n%! rgb = make_rgb_f ();\n%! frame = struct (\"cdata\", rgb, \"colormap\", []);\n%! [rrgb, rcmap] = frame2im (frame);\n%! assert (rrgb, rgb);\n%! assert (rcmap, []);\n\n%!test\n%! f1 = make_rgb_f ();\n%! f2 = make_rgb_f ();\n%! f3 = make_rgb_f ();\n%! f4 = make_rgb_f ();\n%! rgb = {f1, f2, f3, f4};\n%! movie = struct (\"cdata\", rgb, \"colormap\", []);\n%! [rx, rcmap] = frame2im (movie);\n%! assert (rx, cat (4, f1, f2, f3, f4));\n%! assert (rcmap, []);\n\n%!test\n%! f1 = make_ind_f ();\n%! f2 = make_ind_f ();\n%! f3 = make_ind_f ();\n%! f4 = make_ind_f ();\n%! ind = {f1, f2, f3, f4};\n%! cmap = jet (100);\n%! movie = struct (\"cdata\", ind, \"colormap\", cmap);\n%! [rx, rcmap] = frame2im (movie);\n%! assert (rx, cat (4, f1, f2, f3, f4));\n%! assert (rcmap, cmap);\n"
  },
  {
    "path": "scripts/image/getframe.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{frame} =} getframe ()\n## @deftypefnx {} {@var{frame} =} getframe (@var{hax})\n## @deftypefnx {} {@var{frame} =} getframe (@var{hfig})\n## @deftypefnx {} {@var{frame} =} getframe (@dots{}, @var{rect})\n##\n## Capture a figure or axes as a movie frame structure.\n##\n## Without an argument, capture the current axes excluding ticklabels, title,\n## and x/y/zlabels.  The returned structure @var{frame} has a field\n## @code{cdata}, which contains the actual image data in the form of an\n## @nospell{NxMx3} (RGB) uint8 matrix in physical screen pixels, and a field\n## @code{colormap} which is provided for @sc{matlab} compatibility but is\n## always empty.\n##\n## If the first argument @var{hax} is an axes handle, then capture this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## If the first argument @var{hfig} is a figure handle then the entire\n## corresponding figure canvas is captured.\n##\n## Finally, if a second argument @var{rect} is provided it must be a\n## four-element vector ([left bottom width height]) defining the region inside\n## the figure to be captured.  Regardless of the figure @qcode{\"units\"}\n## property, @var{rect} must be defined in @strong{pixels}.\n##\n## @seealso{im2frame, frame2im, movie}\n## @end deftypefn\n\nfunction frame = getframe (h = [], rect = [])\n\n  hf = hax = [];\n  if (isempty (h))\n    hf = get (0, \"currentfigure\");\n    if (isempty (hf))\n      error (\"getframe: no figure to capture\");\n    endif\n    hax = get (hf, \"currentaxes\");\n    if (isempty (hax))\n      error (\"getframe: no axes to capture\");\n    endif\n  elseif (isfigure (h))\n    hf = h;\n  elseif (isaxes (h))\n    hf = ancestor (h, \"figure\");\n    hax = h;\n  else\n    error (\"getframe: H must be a figure or axes handle\");\n  endif\n\n  if (strcmp (get (hf, \"__graphics_toolkit__\"), \"gnuplot\"))\n    error (\"getframe: not implemented for gnuplot graphics toolkit\");\n  endif\n\n  unwind_protect\n    htmp = hax;\n    if (h == hf)\n      htmp = hf;\n    endif\n    units = get (htmp, \"units\");\n    set (htmp, \"units\", \"pixels\");\n    pos = get (htmp, \"position\");\n    if (h == hf)\n      pos(1:2) = 1;\n    endif\n  unwind_protect_cleanup\n    set (htmp, \"units\", units)\n  end_unwind_protect\n\n  if (! isempty (rect))\n    xv = [pos(1); pos(1)+pos(3); pos(1)+pos(3); pos(1)];\n    yv = [pos(2); pos(2); pos(2)+pos(4); pos(2)+pos(4)];\n    x = [rect(1); rect(1)+rect(3); rect(1)+rect(3); rect(1)];\n    y = [rect(2); rect(2); rect(2)+rect(4); rect(2)+rect(4)];\n    in = inpolygon (x, y, xv, yv);\n    if (! all (in))\n      error (\"getframe: RECT must define a region inside the figure\");\n    endif\n    pos = rect;\n  endif\n\n  __check_rendering_capability__ (\"getframe\", hf);\n\n  ## __get_frame__ requires that the figure \"units\" is \"pixels\"\n  unwind_protect\n    units = get (hf, \"units\");\n    set (hf, \"units\", \"pixels\");\n    cdata = __get_frame__ (hf);\n\n    if (isempty (cdata))\n      ## FIXME: This can happen if the graphics subsystem is inadequate (e.g.,\n      ##        too low color depth for OpenGL rendering, see bug #65866).\n      ##        This should have been detected earlier and \"have_window_system\"\n      ##        should be false.\n      error ([\"getframe: failed to capture frame data, potentially due to \", ...\n              \"insufficient graphics capabilities\"]);\n    endif\n\n  unwind_protect_cleanup\n    set (hf, \"units\", units)\n  end_unwind_protect\n\n  dpr = get (hf, \"__device_pixel_ratio__\");\n  i1 = max (floor ((pos(1)-1)*dpr+1), 1);\n  i2 = min (ceil ((pos(1)+pos(3)-1)*dpr), columns (cdata));\n  idxx = i1:i2;\n  i1 = max (floor ((pos(2)-1)*dpr+1), 1);\n  i2 = min (ceil ((pos(2)+pos(4)-1)*dpr), rows (cdata));\n  idxy = fliplr (rows (cdata) - (i1:i2) + 1);\n\n  frame = struct (\"cdata\", cdata(idxy,idxx,:), \"colormap\", []);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! contourf (rand (5));\n%! drawnow ();\n%! frame = getframe ();\n%! imshow (frame.cdata);\n\n%!demo\n%! clf reset;\n%! contourf (rand (5));\n%! frame = getframe (gcf ());\n%! imshow (frame.cdata);\n%! set (gca, \"position\", [0 0 1 1]);\n\n%!demo\n%! clf;\n%! hax1 = subplot (2,1,1);\n%! contourf (rand (5));\n%! title (\"Original\");\n%! frame = getframe (hax1);\n%! hax2 = subplot (2,1,2);\n%! image (frame.cdata);\n%! title (\"Frame\");\n\n%!demo\n%! clf;\n%! hax1 = subplot (2,1,1);\n%! contourf (rand (5));\n%! title (\"Original\");\n%!\n%! ## Get the coordinates of the lower-left hand corner in pixels\n%! set (hax1, \"units\", \"pixels\");\n%! pos = get (hax1, \"position\");\n%! set (hax1, \"units\", \"normalized\");\n%! rect = [pos(1:2) pos(3:4)/2];\n%!\n%! frame = getframe (hax1, rect);\n%! hax2 = subplot (2,1,2);\n%! image (frame.cdata);\n%! title (\"Lower left hand corner\");\n\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", graphics_toolkit ()))\n%! hf = figure (\"visible\", \"off\");\n%! graphics_toolkit (hf, \"qt\");\n%! unwind_protect\n%!   pos = get (hf, \"position\");\n%!   dpr = get (hf, \"__device_pixel_ratio__\");\n%!   assert (size (getframe (hf).cdata)(1:2), pos(4:-1:3)*dpr);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", graphics_toolkit ()))\n%! hf = figure (\"visible\", \"off\");\n%! graphics_toolkit (hf, \"qt\");\n%! unwind_protect\n%!   hax = axes (\"visible\", \"off\", \"position\", [0 0 1 1]);\n%!   verts = [0 0; .5 0; 1 0; ...\n%!            0 .5; .5 .5; 1 .5; ...\n%!            0 1; .5 1; 1 1];\n%!   faces = [1 2 5 4; 2 3 6 5; 4 5 8 7; 5 6 9 8];\n%!   fvc = [1 0 0; 0 1 0; 0 0 1; 1 0 1];\n%!   patch (\"vertices\", verts, \"faces\", faces, \"facevertexcdata\", fvc, ...\n%!          \"facecolor\", \"flat\");\n%!\n%!   kk = 1;\n%!   pos = get (hf, \"position\");\n%!\n%!   for jj = [0.05 0.55]\n%!     for ii = [0.05 0.55]\n%!       rect = [ii jj .4 .4].*[pos(3:4) pos(3:4)];\n%!       frame = getframe (hax, rect).cdata;\n%!       assert (frame(:,:,1) == fvc(kk,1)*255);\n%!       assert (frame(:,:,2) == fvc(kk,2)*255);\n%!       assert (frame(:,:,3) == fvc(kk,3)*255);\n%!       kk++;\n%!     endfor\n%!   endfor\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/image/gray.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} gray ()\n## @deftypefnx {} {@var{map} =} gray (@var{n})\n## Create gray colormap.  This colormap varies from black to white with shades\n## of gray.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = gray (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"gray: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [0, 0, 0];\n  elseif (n > 1)\n    gr = [0:(n-1)]' / (n - 1);\n    map = [gr, gr, gr];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'gray' colormap profile and as an image\n%! cmap = gray (16);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (gray ()), [256, 3])\n%!assert (size (gray (16)), [16, 3])\n\n%!assert (gray (1), [0, 0, 0])\n%!assert (gray (true), double ([0, 0, 0]))\n%!assert (gray (char (1)), double ([0, 0, 0]))\n%!assert (gray (int32 (1)), double ([0, 0, 0]))\n\n%!assert (gray (0), zeros (0, 3))\n%!assert (gray (-1), zeros (0, 3))\n\n%!assert (gray (11), [0:.1:1]' .* [1, 1, 1], eps)\n\n## Input validation\n%!error <N must be a scalar integer> gray (\"foo\")\n%!error <N must be a scalar integer> gray ([1, 2, 3])\n%!error <N must be a scalar integer> gray ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/gray2ind.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{img} =} gray2ind (@var{I})\n## @deftypefnx {} {@var{img} =} gray2ind (@var{I}, @var{n})\n## @deftypefnx {} {@var{img} =} gray2ind (@var{BW})\n## @deftypefnx {} {@var{img} =} gray2ind (@var{BW}, @var{n})\n## @deftypefnx {} {[@var{img}, @var{map}] =} gray2ind (@dots{})\n## Convert a grayscale or binary intensity image to an indexed image.\n##\n## The indexed image will consist of @var{n} different intensity values.\n## If not given @var{n} defaults to 64 for grayscale images or 2 for binary\n## black and white images.\n##\n## The output @var{img} is of class uint8 if @var{n} is less than or equal to\n## 256; Otherwise the return class is uint16.\n## @seealso{ind2gray, rgb2ind}\n## @end deftypefn\n\nfunction [I, map] = gray2ind (I, n = 64)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! isreal (I) || issparse (I) || ! ismatrix (I))\n    error (\"gray2ind: I must be a grayscale or binary image\");\n  elseif (! isscalar (n) || n < 1 || n > 65536)\n    error (\"gray2ind: N must be a positive integer in the range [1, 65536]\");\n  endif\n\n  ## default n is different if image is logical\n  if (nargin == 1 && islogical (I))\n    n = 2;\n  endif\n\n  cls = class (I);\n  if (! any (strcmp (cls, {\"logical\", \"uint8\", \"uint16\", \"int16\", ...\n                           \"single\", \"double\"})))\n    error (\"gray2ind: invalid data type '%s'\", cls);\n  elseif (isfloat (I) && (min (I(:) < 0) || max (I(:) > 1)))\n    error (\"gray2ind: floating point images may only contain values between 0 and 1\");\n  endif\n\n  map = gray (n);\n\n  ## Set up scale factor\n  if (isinteger (I))\n    low   = double (intmin (cls));\n    scale = double (intmax (cls)) - low;\n    I = double (I) - low;\n  else\n    scale = 1;\n  endif\n  I *= (n-1)/scale;\n\n  ## Note: no separate call to round () necessary because\n  ##       type conversion does that automatically.\n  if (n <= 256)\n    I = uint8 (I);\n  else\n    I = uint16 (I);\n  endif\n\nendfunction\n\n\n%!assert (gray2ind ([0 0.25 0.5 1]), uint8 ([0 16 32 63]))\n%!assert (gray2ind ([0 0.25 0.5 1], 400), uint16 ([0 100 200 399]))\n%!assert (gray2ind (logical ([1 0 0 1])), uint8 ([1 0 0 1]))\n%!assert (gray2ind (uint8 ([0 64 128 192 255])), uint8 ([0 16 32 47 63]))\n\n%!test\n%! i2g = ind2gray (1:100, gray (100));\n%! g2i = gray2ind (i2g, 100);\n%! assert (g2i, uint8 (0:99));\n\n%!assert (gray2ind ([0 0.25 0.5 1], 256), uint8 ([0 64 128 255]))\n%!assert (gray2ind ([0 (1/511) (1/510) 1-(1/509) 1-(1/510) 1], 256),\n%!        uint8 ([0 0 1 254 255 255]))\n\n%!test\n%! assert (class (gray2ind ([0.0 0.5 1.0], 255)), \"uint8\");\n%! assert (class (gray2ind ([0.0 0.5 1.0], 256)), \"uint8\");\n%! assert (class (gray2ind ([0.0 0.5 1.0], 257)), \"uint16\");\n\n## Test input validation\n%!error <Invalid call> gray2ind ()\n%!error <I must be a grayscale or binary image> gray2ind ({1})\n%!error <I must be a grayscale or binary image> gray2ind ([1+i])\n%!error <I must be a grayscale or binary image> gray2ind (sparse ([1]))\n%!error <I must be a grayscale or binary image> gray2ind (ones (2,2,3))\n%!error <N must be a positive integer> gray2ind (1, ones (2,2))\n%!error <N must be a positive integer> gray2ind (1, 0)\n%!error <N must be a positive integer> gray2ind (1, 65537)\n%!error <invalid data type> gray2ind (uint32 (1))\n%!error <values between 0 and 1> gray2ind (-1)\n%!error <values between 0 and 1> gray2ind (2)\n"
  },
  {
    "path": "scripts/image/hot.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} hot ()\n## @deftypefnx {} {@var{map} =} hot (@var{n})\n## Create color colormap.  This colormap ranges from black through dark red,\n## red, orange, yellow, to white.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = hot (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"hot: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n  if (n == 1)\n    map = [1, 1, 1];\n  elseif (n == 2)\n    map = [1, 1, 1/2\n           1, 1,  1 ];\n  elseif (n > 2)\n    idx = floor (3/8 * n);\n    nel = idx;\n\n    r = ones (n, 1);\n    r(1:idx, 1) = [1:nel]' / nel;\n\n    g = zeros (n, 1);\n    g(idx+1:2*idx, 1) = r(1:idx);\n    g(2*idx+1:end, 1) = 1;\n\n    idx = 2*idx + 1;   # approximately 3/4 *n\n    nel = n - idx + 1;\n\n    b = zeros (n, 1);\n    b(idx:end, 1) = [1:nel]' / nel;\n\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'hot' colormap profile and as an image\n%! cmap = hot (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n%!assert (size (hot ()), [256, 3])\n%!assert (size (hot (16)), [16, 3])\n\n%!assert (hot (1), [1, 1, 1])\n%!assert (hot (true), double ([1, 1, 1]))\n%!assert (hot (char (1)), double ([1, 1, 1]))\n%!assert (hot (int32 (1)), double ([1, 1, 1]))\n%!assert (hot (2), [1, 1, 1/2; 1, 1, 1])\n%!assert (hot (3), [1, 0, 0; 1, 1, 0; 1 1 1])\n\n%!assert (hot (0), zeros (0, 3))\n%!assert (hot (-1), zeros (0, 3))\n\n%!test\n%! a = [0.25, 0,    0;\n%!      0.50, 0,    0;\n%!      0.75, 0,    0;\n%!      1,    0,    0;\n%!      1,    0.25, 0;\n%!      1,    0.50, 0;\n%!      1,    0.75, 0;\n%!      1,    1,    0;\n%!      1,    1,    1/3;\n%!      1,    1,    2/3;\n%!      1,    1,    1];\n%! assert (hot (11), a, eps);\n\n## Input validation\n%!error <N must be a scalar integer> hot (\"foo\")\n%!error <N must be a scalar integer> hot ([1, 2, 3])\n%!error <N must be a scalar integer> hot ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/hsv.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} hsv ()\n## @deftypefnx {} {@var{map} =} hsv (@var{n})\n## Create color colormap.  This colormap begins with red, changes through\n## yellow, green, cyan, blue, and magenta, before returning to red.\n##\n## It is useful for displaying periodic functions.  The map is obtained by\n## linearly varying the hue through all possible values while keeping constant\n## maximum saturation and value.  The equivalent code is\n## @code{hsv2rgb ([(0:N-1)'/N, ones(N,2)])}.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = hsv (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"hsv: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [1, 0, 0];\n  elseif (n > 1)\n    hue = [0:n-1]' / n;\n    map = hsv2rgb ([hue, ones(n,1), ones(n,1)]);\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n## A better demo of this colormap would be to plot the hsv values.\n%!demo\n%! ## Show the 'hsv' colormap profile and as an image\n%! cmap = hsv (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n%!assert (size (hsv ()), [256, 3])\n%!assert (size (hsv (16)), [16, 3])\n\n%!assert (hsv (1), [1, 0, 0])\n%!assert (hsv (true), double ([1, 0, 0]))\n%!assert (hsv (char (1)), double ([1, 0, 0]))\n%!assert (hsv (int32 (1)), double ([1, 0, 0]))\n\n%!assert (hsv (0), zeros (0, 3))\n%!assert (hsv (-1), zeros (0, 3))\n\n%!assert (hsv (6)(:), [1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]')\n\n## Input validation\n%!error <N must be a scalar integer> hsv (\"foo\")\n%!error <N must be a scalar integer> hsv ([1, 2, 3])\n%!error <N must be a scalar integer> hsv ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/hsv2rgb.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{rgb_map} =} hsv2rgb (@var{hsv_map})\n## @deftypefnx {} {@var{rgb_img} =} hsv2rgb (@var{hsv_img})\n## Transform a colormap or image from HSV to RGB color space.\n##\n## A color in HSV space is represented by hue, saturation and value\n## (brightness) levels in a cylindrical coordinate system.  Hue is the\n## azimuth and describes the dominant color.  Saturation is the radial\n## distance and gives the amount of hue mixed into the color.  Value is\n## the height and is the amount of light in the color.\n##\n## The input can be both a colormap or RGB image.  In the case of floating\n## point input, values are expected to be on the [0 1] range.  In the case\n## of hue (azimuth), since the value corresponds to an angle,\n## @code{mod (h, 1)} is used.\n##\n## @example\n## @group\n## >> hsv2rgb ([0.5 1 1])\n## @xresult{} ans = 0 1 1\n##\n## >> hsv2rgb ([2.5 1 1])\n## @xresult{} ans = 0 1 1\n##\n## >> hsv2rgb ([3.5 1 1])\n## @xresult{} ans = 0 1 1\n## @end group\n## @end example\n##\n## Output class and size will be the same as input.\n##\n## @seealso{rgb2hsv, ind2rgb}\n## @end deftypefn\n\nfunction rgb = hsv2rgb (hsv)\n\n  ## Each color value x = (r,g,b) is calculated with\n  ## x = (1-sat)*val+sat*val*f_x(hue)\n  ## where f_x(hue) is a piecewise defined function for\n  ## each color with f_r(hue-2/3) = f_g(hue) = f_b(hue-1/3).\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  [hsv, sz, is_im, is_nd] ...\n    = colorspace_conversion_input_check (\"hsv2rgb\", \"HSV\", hsv);\n\n  h = hsv(:,1);\n  s = hsv(:,2);\n  v = hsv(:,3);\n\n  ## Values of Saturation and Value should also be in the [0 1] range.  With\n  ## the exception of hue, values outside this range don't make any sense\n  ## in a cylindrical coordinate system but we must return something for\n  ## Matlab compatibility.  User case is when a function returns an hsv\n  ## image just slightly outside the range due to floating point rounding\n  ## errors.\n\n  ## Prefill rgb map with v*(1-s)\n  rgb = repmat (v .* (1 - s), 1, 3);\n\n  ## red = hue-2/3 : green = hue : blue = hue-1/3\n  ## Apply modulo 1 to keep within range [0, 1]\n  hue = mod ([h-2/3  h  h-1/3], 1);\n\n  ## factor s*v -> f\n  f = repmat (s .* v, 1, 3);\n\n  ## add s*v*hue-function to rgb map\n  rgb += f .* (6 * (hue < 1/6) .* hue\n               + (hue >= 1/6 & hue < 1/2)\n               + (hue >= 1/2 & hue < 2/3) .* (4 - 6 * hue));\n\n  rgb = colorspace_conversion_revert (rgb, sz, is_im, is_nd);\n\nendfunction\n\n\n## Test pure colors\n%!assert (hsv2rgb ([0 0 1]), [1 1 1])\n%!assert (hsv2rgb ([1 1 0]), [0 0 0])\n%!assert (hsv2rgb ([0 1 1]), [1 0 0])\n%!assert (hsv2rgb ([1 1 1]), [1 0 0])\n%!assert (hsv2rgb ([1/3 1 1]), [0 1 0])\n%!assert (hsv2rgb ([2/3 1 1]), [0 0 1])\n\n%!assert (hsv2rgb ([0 0.5 0.5]), hsv2rgb ([1 0.5 0.5]))\n\n## Not Matlab compatible (Matlab would return [1/2  1/12  1/12]) but\n## it's also invalid input.  This is, however, the same output as Python\n## colorsys module.\n%!assert (hsv2rgb ([0.5 -0.5 0.5]), [0.75 0.5 0.5])\n\n## Not Matlab compatible.  Matlab returns NaN when hue is outside the\n## [0 1] range.  But since it's an angle, we can manage it.\n%!assert (hsv2rgb ([0 0.5 0.5]), hsv2rgb ([2 0.5 0.5]))\n%!assert (hsv2rgb ([0.5 0.5 0.5]), hsv2rgb ([2.5 0.5 0.5]), eps)\n\n%!test\n%! hsv_map = rand (64, 3);\n%! assert (rgb2hsv (hsv2rgb (hsv_map)), hsv_map, 1e-6);\n\n%!test\n%! hsv_img = rand (64, 64, 3);\n%! assert (rgb2hsv (hsv2rgb (hsv_img)), hsv_img, 1e-6);\n\n## support sparse input\n%!assert (hsv2rgb (sparse ([0 0 1])), sparse ([1 1 1]))\n%!assert (hsv2rgb (sparse ([0 1 1])), sparse ([1 0 0]))\n%!assert (hsv2rgb (sparse ([1 1 1])), sparse ([1 0 0]))\n\n## Test input validation\n%!error <Invalid call> hsv2rgb ()\n%!error <invalid data type> hsv2rgb ({1})\n%!error <HSV must be a colormap or HSV image> hsv2rgb (ones (2,2))\n\n## Test N-D input\n%!test\n%! hsv = rand (16, 16, 3, 5);\n%! rgb = zeros (size (hsv));\n%! for i = 1:5\n%!   rgb(:,:,:,i) = hsv2rgb (hsv(:,:,:,i));\n%! endfor\n%! assert (hsv2rgb (hsv), rgb);\n\n## Test output class and size for input images.\n## Most of the tests only test for colormap input.\n\n%!test\n%! rgb = hsv2rgb (rand (10, 10, 3));\n%! assert (class (rgb), \"double\");\n%! assert (size (rgb), [10 10 3]);\n\n%!test\n%! rgb = hsv2rgb (rand (10, 10, 3, \"single\"));\n%! assert (class (rgb), \"single\");\n%! assert (size (rgb), [10 10 3]);\n\n%!test\n%! rgb = (rand (10, 10, 3) * 3 ) - 0.5; # values outside range [0 1]\n%! rgb = hsv2rgb (rgb);\n%! assert (class (rgb), \"double\");\n%! assert (size (rgb), [10 10 3]);\n\n%!test\n%! rgb = (rand (10, 10, 3, \"single\") * 3 ) - 0.5; # values outside range [0 1]\n%! rgb = hsv2rgb (rgb);\n%! assert (class (rgb), \"single\");\n%! assert (size (rgb), [10 10 3]);\n\n%!test\n%! rgb = hsv2rgb (randi ([0 255], 10, 10, 3, \"uint8\"));\n%! assert (class (rgb), \"double\");\n%! assert (size (rgb), [10 10 3]);\n\n%!test\n%! rgb = hsv2rgb (randi ([0 65535], 10, 10, 3, \"uint16\"));\n%! assert (class (rgb), \"double\");\n%! assert (size (rgb), [10 10 3]);\n\n%!test\n%! rgb = hsv2rgb (randi ([-128 127], 10, 10, 3, \"int8\"));\n%! assert (class (rgb), \"double\");\n%! assert (size (rgb), [10 10 3]);\n\n%!test\n%! hsv_double = reshape ([2/3 1/3 1 0 1 1 1 0, 1 1 1 1], [2 2 3]);\n%! hsv_uint8  = reshape (uint8 ([170 85 255 0 255 255 255 0 255 255 255 255]),\n%!                       [2 2 3]);\n%! hsv_int16 = int16 (double (hsv_double * uint16 (65535)) -32768);\n%! expected = reshape ([0 0 1 1 0 1 0 1 1 0 0 1], [2 2 3]);\n%!\n%! assert (hsv2rgb (hsv_double), expected);\n%! assert (hsv2rgb (hsv_uint8), expected);\n%! assert (hsv2rgb (hsv_int16), expected);\n%! assert (hsv2rgb (single (hsv_double)), single (expected), eps (single (2)));\n"
  },
  {
    "path": "scripts/image/im2double.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{dimg} =} im2double (@var{img})\n## @deftypefnx {} {@var{dimg} =} im2double (@var{img}, \"indexed\")\n## Convert image to double precision.\n##\n## The conversion of @var{img} to double precision, is dependent on the type of\n## input image.  The following input classes are supported:\n##\n## @table @samp\n## @item uint8, uint16, and int16\n## The range of values from the class is scaled to the interval [0 1].\n##\n## @item logical\n## True and false values are assigned a value of 1 and 0 respectively.\n##\n## @item single\n## Values are cast to double.\n##\n## @item double\n## Returns the same image.\n##\n## @end table\n##\n## If @var{img} is an indexed image, then the second argument should be the\n## string @qcode{\"indexed\"}.  If so, then @var{img} must either be of floating\n## point class, or unsigned integer class and it will simply be cast to double.\n## If it is an integer class, an offset of +1 is applied.\n##\n## @seealso{double}\n## @end deftypefn\n\nfunction dimg = im2double (img, im_type)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    ## \"normal\" (non-indexed) images\n    switch (class (img))\n      case \"uint8\",   dimg = double (img) / 255;\n      case \"uint16\",  dimg = double (img) / 65535;\n      case \"int16\",   dimg = (double (img) + 32768) / 65535;\n      case \"single\",  dimg = double (img);\n      case \"logical\", dimg = double (img);\n      case \"double\",  dimg = img;\n      otherwise, error ('im2double: IMG is of unsupported class \"%s\"', class (img));\n    endswitch\n  else\n    ## indexed images\n    if (! strcmpi (im_type, \"indexed\"))\n      error ('im2double: second input argument must be the string \"indexed\"');\n    elseif (any (isa (img, {\"uint8\", \"uint16\"})))\n      dimg = double (img) + 1;\n    elseif (isfloat (img) || isbool (img))\n      dimg = double (img);\n    else\n      ## Technically, it could also be of logical class and we do not\n      ## enforce positive integers for floating for Matlab compatibility.\n      ## Still, no need to tell that to the user.\n      error ([\"im2double: if IMG is indexed, then it must be positive \" ...\n              \"integer floating points, or unsigned integer class\"]);\n    endif\n  endif\n\nendfunction\n\n\n%!assert (im2double ([1 2 3]), [1 2 3])\n%!assert (im2double (single ([1 2 3])), [1 2 3])\n%!assert (im2double (uint8 ([0 127 128 255])), [0 127/255 128/255 1])\n%!assert (im2double (uint16 ([0 127 128 65535])), [0 127/65535 128/65535 1])\n%!assert (im2double (int16 ([-32768 -32767 -32766 32767])),\n%!                   [0 1/65535 2/65535 1])\n\n%!assert (im2double (uint8 ([0 1 255]), \"indexed\"), [1 2 256])\n%!assert (im2double (uint16 ([0 1 2557]), \"indexed\"), [1 2 2558])\n%!assert (im2double ([3 25], \"indexed\"), [3 25])\n%!assert (im2double (single ([3 25]), \"indexed\"), [3 25])\n\n## Test for N-D input\n%!function test_im2double_nd (cls, low, high)\n%!  in = rand (2, 4, 2, 3, 2);\n%!  in *= high - low;\n%!  in += low;\n%!  in = cast (in, cls);\n%!  out = zeros (size (in));\n%!  for n = 1:12\n%!    out(:,:,n) = im2double (in(:,:,n));\n%!  endfor\n%!  assert (im2double (in), out);\n%!endfunction\n\n%!test\n%! test_im2double_nd (\"double\", 0, 1);\n%! test_im2double_nd (\"single\", 0, 1);\n%! test_im2double_nd (\"uint8\", 0, 255);\n%! test_im2double_nd (\"uint16\", 0, 6535);\n%! test_im2double_nd (\"int16\", -32768, 32767);\n\n## Test lack of input check for Matlab compatibility\n%!assert (im2double ([0 1 2], \"indexed\"), [0 1 2])\n%!assert (im2double ([0 -1 -2], \"indexed\"), [0 -1 -2])\n%!assert (im2double ([0 -1.5 -2], \"indexed\"), [0 -1.5 -2])\n%!assert (im2double ([0 -1.5 -2i], \"indexed\"), [0 -1.5 -2i])\n%!assert (im2double ([false true], \"indexed\"), [0 1])\n\n%!error <unsigned integer class> im2double (int16 ([17 8]), \"indexed\")\n%!error <unsigned integer class> im2double (int16 ([-7 8]), \"indexed\")\n%!error <must be the string \"indexed\"> im2double ([1 2 3], \"non-indexed\")\n"
  },
  {
    "path": "scripts/image/im2frame.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{frame} =} im2frame (@var{rgb})\n## @deftypefnx {} {@var{frame} =} im2frame (@var{x}, @var{map})\n## Convert image to movie frame.\n##\n## A movie frame is simply a struct with the fields @qcode{\"cdata\"} and\n## @qcode{\"colormap\"}.\n##\n## Support for N-dimensional images is given when each image projection, matrix\n## sizes of @nospell{MxN and MxNx3} for RGB images, is concatenated along the\n## fourth dimension.  In such cases, the returned value is a struct array.\n##\n## @seealso{frame2im}\n## @end deftypefn\n\nfunction frame = im2frame (x, map = [])\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (ndims (x) > 4)\n    error (\"im2frame: X or RGB must be a single image\");\n  endif\n\n  ## FIXME: No validation of class of input.  Matlab only accepts double or\n  ## uint8.\n  ## Matlab documentation is incorrect.  Singleton 3rd dimension will error\n  ## without cmap (no use of default cmap), and cmap is added to the frame\n  ## even when image is RGB.\n\n  nchannels = size (x, 3);\n  if (nchannels == 3)\n    ## RGB image, do nothing\n  elseif (nchannels == 1)\n    if (nargin < 2)\n      error (\"im2frame: MAP required for indexed images\");\n    endif\n    [x, map] = ind2x (\"im2frame\", x, map);\n  else\n    error (\"im2frame: first argument must be indexed or RGB image\");\n  endif\n\n  ## support N-dimensional images and return a struct array\n  if (ndims (x) == 4)\n    x = reshape (num2cell (x, [1 2 3]), 1, size (x, 4));\n  endif\n\n  frame = struct (\"cdata\", x, \"colormap\", map);\n\nendfunction\n\n\n%!function f = make_rgb_f ()\n%!  f = randi ([0 255], 10, 20, 3);\n%!endfunction\n\n%!function f = make_ind_f ()\n%!  f = randi ([1 100], 10, 20, 1);\n%!endfunction\n\n%!test\n%! rgb = make_rgb_f ();\n%! assert (im2frame (rgb), struct (\"cdata\", rgb, \"colormap\", []));\n\n%!test\n%! ind = make_ind_f ();\n%! cmap = bone (100);\n%! assert (im2frame (ind, cmap), struct (\"cdata\", ind, \"colormap\", cmap));\n\n%!test\n%! rgb1 = make_rgb_f ();\n%! rgb2 = make_rgb_f ();\n%! rgb3 = make_rgb_f ();\n%! rgb4 = make_rgb_f ();\n%! assert (im2frame (cat (4, rgb1, rgb2, rgb3, rgb4)),\n%!         struct (\"cdata\", {rgb1, rgb2, rgb3, rgb4}, \"colormap\", []));\n\n%!test\n%! ind1 = make_ind_f ();\n%! ind2 = make_ind_f ();\n%! ind3 = make_ind_f ();\n%! ind4 = make_ind_f ();\n%! cmap = bone (100);\n%! assert (im2frame (cat (4, ind1, ind2, ind3, ind4), cmap),\n%!         struct (\"cdata\", {ind1, ind2, ind3, ind4}, \"colormap\", cmap));\n\n## Test input validation\n%!error <Invalid call> im2frame ()\n%!error <must be a single image> im2frame (ones (1,2,3,4,5))\n%!error <MAP required for indexed images> im2frame (ones (2,2))\n%!error <argument must be indexed or RGB image> im2frame (ones (2,2,2))\n"
  },
  {
    "path": "scripts/image/image.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} image (@var{img})\n## @deftypefnx {} {} image (@var{x}, @var{y}, @var{img})\n## @deftypefnx {} {} image (\"CData\", @var{img})\n## @deftypefnx {} {} image (\"XData\", @var{x}, \"YData\", @var{y}, \"CData\", @var{img})\n## @deftypefnx {} {} image (@dots{}, @var{prop}, @var{val})\n## @deftypefnx {} {} image (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} image (@dots{})\n## Display a matrix as an image.\n##\n## @var{img} may be a 2-D matrix where each element is an index into the\n## current colormap.  For floating point data, the value 1 chooses the first\n## color in the colormap.  For integer data, the value 0 chooses the first\n## color in the colormap.\n##\n## Or @var{img} may be a 3-D matrix where the third dimension is an RGB triplet\n## specifying the color.  If the image data is floating point then the data\n## must be in the range [0, 1].  If the image data is of integer type (uint8 or\n## uint16) then the data must be in the range [0, INTMAX].\n##\n## @var{x} and @var{y} are optional 1-element (@code{[min]}) or 2-element\n## vectors (@w{@code{[min, max]}}) which specify the coordinate(s) of the\n## @emph{center} of a corner pixel.  If unspecified, the default minimum value\n## is 1 and the maximum is the length of @var{img} along the specific\n## dimension.  If a range is specified as @w{@code{[max, min]}}@ then the image\n## will be reversed along that axis.  For convenience, @var{x} and @var{y} may\n## be specified as vectors, however, only the first and last elements will be\n## used to determine the axis limits.\n##\n## Multiple property/value pairs may be specified for the image object, but\n## they must appear in pairs.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the image.\n##\n## Implementation Note: The origin (0, 0) for images is located in the upper\n## left.  For ordinary plots, the origin is located in the lower left.  Octave\n## handles this inversion by plotting the data normally, and then reversing the\n## direction of the y-axis by setting the @code{ydir} property to\n## @qcode{\"reverse\"}.  This has implications whenever an image and an ordinary\n## plot need to be overlaid.  The recommended solution is to display the image\n## and then plot the reversed ydata using, for example, @code{flipud (ydata)}.\n##\n## Calling Forms: The @code{image} function can be called in two forms:\n## High-Level and Low-Level.  When invoked with normal options, the High-Level\n## form is used which first calls @code{newplot} to prepare the graphic figure\n## and axes.  When the only inputs to @code{image} are property/value pairs\n## the Low-Level form is used which creates a new instance of an image object\n## and inserts it in the current axes (as if @code{hold on} was in effect).\n##\n## Graphic Properties: The full list of properties is documented at\n## @ref{Image Properties}.\n## @seealso{imshow, imagesc, colormap}\n## @end deftypefn\n\nfunction h = image (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"image\", varargin{:});\n\n  chararg = find (cellfun (\"isclass\", varargin, \"char\"), 1, \"first\");\n\n  do_new = true;\n  if (nargin == 0)\n    img = get (0, \"defaultimagecdata\");\n    x = y = [];\n  elseif (chararg == 1)\n    ## Low-Level syntax\n    do_new = false;\n    x = y = img = [];\n    idx = find (strcmpi (varargin, \"cdata\"), 1);\n    if (idx)\n      img = varargin{idx+1};\n      varargin(idx:idx+1) = [];\n    endif\n    idx = find (strcmpi (varargin, \"xdata\"), 1);\n    if (idx)\n      x = varargin{idx+1};\n      varargin(idx:idx+1) = [];\n    endif\n    idx = find (strcmpi (varargin, \"ydata\"), 1);\n    if (idx)\n      y = varargin{idx+1};\n      varargin(idx:idx+1) = [];\n    endif\n  elseif (nargin == 1 || chararg == 2)\n    img = varargin{1};\n    x = y = [];\n  elseif (nargin == 2 || chararg == 3)\n    print_usage ();\n  else\n    x = varargin{1};\n    y = varargin{2};\n    img = varargin{3};\n    chararg = 4;\n  endif\n\n  if (iscomplex (img))\n    error (\"image: IMG data can not be complex\");\n  endif\n\n  oldfig = [];\n  if (! isempty (hax))\n    oldfig = get (0, \"currentfigure\");\n  endif\n  unwind_protect\n    if (do_new)\n      hax = newplot (hax);\n    elseif (isempty (hax))\n      hax = gca ();\n    else\n      hax = hax(1);\n    endif\n\n    htmp = __img__ (hax, do_new, x, y, img, varargin{chararg:end});\n\n  unwind_protect_cleanup\n    if (! isempty (oldfig))\n      set (0, \"currentfigure\", oldfig);\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n## Generic image creation.\n##\n## The axis values corresponding to the matrix elements are specified in\n## @var{x} and @var{y}.\n\nfunction h = __img__ (hax, do_new, x, y, img, varargin)\n\n  ## Initialize XDATA and YDATA to handle case where IMG is empty\n  xdata = [];\n  ydata = [];\n\n  if (! isempty (img))\n\n    if (! isempty (x))\n      if (! isvector (x))\n        error (\"image: X must be a vector\");\n      endif\n      if (isscalar (x))\n        xdata = [x(1), x(1)+columns(img)-1];\n      else\n        xdata = x([1, end])(:).';  # (:).' is a hack to guarantee row vector\n      endif\n    endif\n\n    if (! isempty (y))\n      if (! isvector (y))\n        error (\"image: Y must be a vector\");\n      endif\n      if (isscalar (y))\n        ydata = [y(1), y(1)+rows(img)-1];\n      else\n        ydata = y([1, end])(:).';\n      endif\n    endif\n\n  endif\n\n  scale_axis = do_new && ! ishold (hax) && ! isempty (img);\n  if (scale_axis)\n    ## Set axis properties for new images\n    ## NOTE: Do this before calling __go_image__ so that image is not drawn\n    ##       once with default auto-scale axis limits and then a second time\n    ##       with tight axis limits.\n    if (isempty (get (hax, \"children\")))\n      axis (hax, \"tight\");\n    endif\n\n    set (hax, \"view\", [0, 90], \"ydir\", \"reverse\", \"layer\", \"top\", \"box\", \"on\");\n\n  endif\n\n  h = __go_image__ (hax, \"cdata\", img, \"xdata\", xdata, \"ydata\", ydata,\n                         \"cdatamapping\", \"direct\", varargin{:});\n\n  if (scale_axis && isscalar (get (hax, \"children\")))\n    ## Re-scale axis limits for an image in a new figure or axis.\n    axis (hax, \"tight\");\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (jet (21));\n%! img = 1 ./ hilb (11);\n%! x = y = -5:5;\n%! subplot (2,2,1);\n%!  h = image (x, y, img);\n%!  ylabel (\"limits = [-5.5, 5.5]\");\n%!  title (\"image (x, y, img)\");\n%! subplot (2,2,2);\n%!  h = image (-x, y, img);\n%!  title (\"image (-x, y, img)\");\n%! subplot (2,2,3);\n%!  h = image (x, -y, img);\n%!  title (\"image (x, -y, img)\");\n%!  ylabel (\"limits = [-5.5, 5.5]\");\n%! subplot (2,2,4);\n%!  h = image (-x, -y, img);\n%!  title (\"image (-x, -y, img)\");\n\n## test hidden properties x/ydatamode\n%!test <*42121>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   nx = 64; ny = 64;\n%!   cdata = rand (ny, nx)*127;\n%!   hi = image (cdata);             # x/ydatamode is auto\n%!   assert (get (hi, \"xdata\"), [1 nx]);\n%!   assert (get (hi, \"ydata\"), [1 ny]);\n%!   set (hi, \"cdata\", cdata(1:2:end, 1:2:end));\n%!   assert (get (hi, \"xdata\"), [1 nx/2]);\n%!   assert (get (hi, \"ydata\"), [1 ny/2]);\n%!\n%!   set (hi, \"xdata\", [10 100]);    # xdatamode is now manual\n%!   set (hi, \"ydata\", [10 1000]);   # ydatamode is now manual\n%!   set (hi, \"cdata\", cdata);\n%!   assert (get (hi, \"xdata\"), [10 100]);\n%!   assert (get (hi, \"ydata\"), [10 1000]);\n%!\n%!   set (hi, \"ydata\", []);          # ydatamode is now auto\n%!   set (hi, \"cdata\", cdata(1:2:end, 1:2:end));\n%!   assert (get (hi, \"xdata\"), [10 100]);\n%!   assert (get (hi, \"ydata\"), [1 ny/2]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <IMG data can not be complex> image ([1, i])\n"
  },
  {
    "path": "scripts/image/imagesc.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} imagesc (@var{img})\n## @deftypefnx {} {} imagesc (@var{x}, @var{y}, @var{img})\n## @deftypefnx {} {} imagesc (@dots{}, @var{climits})\n## @deftypefnx {} {} imagesc (@dots{}, \"@var{prop}\", @var{val}, @dots{})\n## @deftypefnx {} {} imagesc (\"@var{prop1}\", @var{val1}, @dots{})\n## @deftypefnx {} {} imagesc (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} imagesc (@dots{})\n## Display a scaled version of the matrix @var{img} as a color image.\n##\n## The colormap is scaled so that the entries of the matrix occupy the entire\n## colormap.  If @code{@var{climits} = [@var{lo}, @var{hi}]} is given, then\n## that range is set to the @qcode{\"clim\"} of the current axes.\n##\n## @var{x} and @var{y} are optional 2-element vectors, @w{@code{[min, max]}},\n## which specify the coordinates of the centers of the corner pixels.\n## If a range is specified as @w{@code{[max, min]}}@ then the image will be\n## reversed along that axis.  For convenience, @var{x} and @var{y} may be\n## specified as N-element vectors matching the length of the data in @var{img}.\n## However, only the first and last elements will be used to determine\n## the image limits.\n##\n## The optional return value @var{h} is a graphics handle to the image.\n##\n## Calling Forms: The @code{imagesc} function can be called in two forms:\n## High-Level and Low-Level.  When invoked with normal options, the High-Level\n## form is used which first calls @code{newplot} to prepare the graphic figure\n## and axes.  When the only inputs to @code{image} are property/value pairs\n## the Low-Level form is used which creates a new instance of an image object\n## and inserts it in the current axes.  The full list of properties is\n## documented at @ref{Image Properties}.\n##\n## @seealso{image, imshow, clim}\n## @end deftypefn\n\nfunction h = imagesc (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"imagesc\", varargin{:});\n\n  chararg = find (cellfun (\"isclass\", varargin, \"char\"), 1, \"first\");\n\n  do_new = true;\n  if (nargin == 0)\n    print_usage ();\n  elseif (chararg == 1)\n    ## Low-Level syntax\n    do_new = false;\n    img = x = y = climits = [];\n  elseif (nargin == 1 || chararg == 2)\n    img = varargin{1};\n    x = y = climits = [];\n  elseif (nargin == 2 || chararg == 3)\n    img = varargin{1};\n    climits = varargin{2};\n    x = y = [];\n  elseif (nargin == 3 || chararg == 4)\n    x = varargin{1};\n    y = varargin{2};\n    img = varargin{3};\n    climits = [];\n  elseif (nargin == 4 || chararg == 5)\n    x = varargin{1};\n    y = varargin{2};\n    img = varargin{3};\n    climits = varargin{4};\n  endif\n\n  oldfig = [];\n  if (! isempty (hax))\n    oldfig = get (0, \"currentfigure\");\n  endif\n  unwind_protect\n    if (do_new)\n      hax = newplot (hax);\n    elseif (isempty (hax))\n      hax = gca ();\n    endif\n\n    if (do_new)\n      htmp = image (x, y, img, \"cdatamapping\", \"scaled\", varargin{chararg:end});\n    else\n      htmp = image (\"cdatamapping\", \"scaled\", varargin{:});\n    endif\n\n    if (do_new && ! ishold (hax))\n      ## use given climits or guess them from the matrix\n      if (numel (climits) == 2 && climits(1) <= climits(2))\n        set (hax, \"clim\", double (climits));\n      elseif (! isempty (climits))\n        error (\"imagesc: CLIMITS must be in form [lo, hi]\");\n      endif\n    endif\n  unwind_protect_cleanup\n    if (! isempty (oldfig))\n      set (0, \"currentfigure\", oldfig);\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! img = 1 ./ hilb (11);\n%! x = y = -5:5;\n%! subplot (2,2,1);\n%!  h = imagesc (x, y, img);\n%!  ylabel (\"limits = [-5.5, 5.5]\");\n%!  title (\"imagesc (x, y, img)\");\n%! subplot (2,2,2);\n%!  h = imagesc (-x, y, img);\n%!  title (\"imagesc (-x, y, img)\");\n%! subplot (2,2,3);\n%!  h = imagesc (x, -y, img);\n%!  title (\"imagesc (x, -y, img)\");\n%!  ylabel (\"limits = [-5.5, 5.5]\");\n%! subplot (2,2,4);\n%!  h = imagesc (-x, -y, img);\n%!  title (\"imagesc (-x, -y, img)\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! g = 0.1:0.1:10;\n%! h = g'*g;\n%! imagesc (g, g, sin (h));\n%! hold on;\n%! imagesc (g, g+12, cos (h/2));\n%! axis ([0 10 0 22]);\n%! hold off;\n%! title (\"two consecutive images w/hold()\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! g = 0.1:0.1:10;\n%! h = g'*g;\n%! imagesc (g, g, sin (h));\n%! hold on;\n%! plot (g, 11.0 * ones (size (g)));\n%! imagesc (g, g+12, cos (h/2));\n%! axis ([0 10 0 22]);\n%! hold off;\n%! title (\"image, line, image w/hold()\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! g = 0.1:0.1:10;\n%! h = g'*g;\n%! plot (g, 10.5 * ones (size (g)));\n%! hold on;\n%! imagesc (g, g, sin (h));\n%! plot (g, 11.0 * ones (size (g)));\n%! imagesc (g, g+12, cos (h/2));\n%! plot (g, 11.5 * ones (size (g)));\n%! axis ([0 10 0 22]);\n%! hold off;\n%! title (\"line, image, line, image, line w/hold()\");\n\n%!demo  # bug #48879\n%! clf;\n%! img = reshape (1:100, 10, 10);\n%! imagesc (img);\n%! colormap (prism (10));\n%! title (\"10 vertical color bars\");\n"
  },
  {
    "path": "scripts/image/imfinfo.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{info} =} imfinfo (@var{filename})\n## @deftypefnx {} {@var{info} =} imfinfo (@var{url})\n## @deftypefnx {} {@var{info} =} imfinfo (@dots{}, @var{ext})\n## Read image information from a file.\n##\n## @code{imfinfo} returns a structure containing information about the image\n## stored in the file @var{filename}.  If there is no file @var{filename},\n## and @var{ext} was specified, it will look for a file named @var{filename}\n## and extension @var{ext}, i.e., a file named @var{filename}.@var{ext}.\n##\n## The output structure @var{info} contains the following fields:\n##\n## @table @samp\n## @item Filename\n## The full name of the image file.\n##\n## @item FileModDate\n## Date of last modification to the file.\n##\n## @item FileSize\n## Number of bytes of the image on disk\n##\n## @item Format\n## Image format (e.g., @qcode{\"jpeg\"}).\n##\n## @item Height\n## Image height in pixels.\n##\n## @item Width\n## Image Width in pixels.\n##\n## @item BitDepth\n## Number of bits per channel per pixel.\n##\n## @item ColorType\n## Image type.  Value is @qcode{\"grayscale\"}, @qcode{\"indexed\"},\n## @qcode{\"truecolor\"}, @qcode{\"CMYK\"}, or @qcode{\"undefined\"}.\n##\n## @item XResolution\n## X resolution of the image.\n##\n## @item YResolution\n## Y resolution of the image.\n##\n## @item ResolutionUnit\n## Units of image resolution.  Value is @qcode{\"Inch\"},\n## @qcode{\"Centimeter\"}, or @qcode{\"undefined\"}.\n##\n## @item DelayTime\n## Time in @nospell{1/100ths} of a second (0 to 65535) which must expire before\n## displaying the next image in an animated sequence.\n##\n## @item LoopCount\n## Number of iterations to loop an animation.\n##\n## @item ByteOrder\n## Endian option for formats that support it.  Value is\n## @qcode{\"little-endian\"}, @qcode{\"big-endian\"}, or @qcode{\"undefined\"}.\n##\n## @item Gamma\n## Gamma level of the image.  The same color image displayed on two different\n## workstations may look different due to differences in the display monitor.\n##\n## @item Quality\n## JPEG/MIFF/PNG compression level.  Value is an integer in the range [0 100].\n##\n## @item DisposalMethod\n## Only valid for GIF images, control how successive frames are rendered (how\n## the preceding frame is disposed of) when creating a GIF animation.  Values\n## can be @qcode{\"doNotSpecify\"}, @qcode{\"leaveInPlace\"}, @qcode{\"restoreBG\"},\n## or @qcode{\"restorePrevious\"}.  For non-GIF files, value is an empty string.\n##\n## @item Chromaticities\n## Value is a 1x8 Matrix with the x,y chromaticity values for white, red,\n## green, and blue points, in that order.\n##\n## @item Comment\n## Image comment.\n##\n## @item Compression\n## Compression type.  Value can be @qcode{\"none\"}, @qcode{\"bzip\"},\n## @qcode{\"fax3\"}, @qcode{\"fax4\"}, @qcode{\"jpeg\"}, @qcode{\"lzw\"},\n## @qcode{\"rle\"}, @qcode{\"deflate\"}, @qcode{\"lzma\"}, @qcode{\"jpeg2000\"},\n## @qcode{\"jbig2\"}, @qcode{\"jbig2\"}, or @qcode{\"undefined\"}.\n##\n## @item Colormap\n## Colormap for each image.\n##\n## @item Orientation\n## The orientation of the image with respect to the rows and columns.  Value\n## is an integer between 1 and 8 as defined in the TIFF 6 specifications, and\n## for @sc{matlab} compatibility.\n##\n## @item Software\n## Name and version of the software or firmware of the camera or image input\n## device used to generate the image.\n##\n## @item Make\n## The manufacturer of the recording equipment.  This is the manufacture of the\n## @nospell{DSC}, scanner, video digitizer or other equipment that generated\n## the image.\n##\n## @item Model\n## The model name or model number of the recording equipment as mentioned on\n## the field @qcode{\"Make\"}.\n##\n## @item DateTime\n## The date and time of image creation as defined by the Exif standard, i.e.,\n## it is the date and time the file was changed.\n##\n## @item ImageDescription\n## The title of the image as defined by the Exif standard.\n##\n## @item Artist\n## Name of the camera owner, photographer or image creator.\n##\n## @item Copyright\n## Copyright notice of the person or organization claiming rights to the image.\n##\n## @item DigitalCamera\n## A struct with information retrieved from the Exif tag.\n##\n## @item GPSInfo\n## A struct with geotagging information retrieved from the Exif tag.\n## @end table\n##\n## @seealso{imread, imwrite, imshow, imformats}\n## @end deftypefn\n\nfunction info = imfinfo (filename, varargin)\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  elseif (! ischar (filename))\n    error (\"imfinfo: FILENAME must be a string\");\n  elseif (nargin > 1 && ! ischar (varargin{1}))\n    error (\"imfinfo: EXT must be a string\");\n  endif\n\n  info = imageIO (\"imfinfo\", @__imfinfo__, \"info\", filename, varargin{:});\n\nendfunction\n\n\n## This test is the same as the similar one in imread.  imfinfo must check\n## if file exists before calling __imfinfo_.  This BIST test confirms this.\n%!testif HAVE_MAGICK\n%! warning (\"off\", \"Octave:GraphicsMagick-Quantum-Depth\", \"local\");\n%! fmt = fmt_ori = imformats (\"jpg\");\n%! fmt.info = @true;\n%! error_thrown = false;\n%! imformats (\"update\", \"jpg\", fmt);\n%! unwind_protect\n%!   try\n%!     imread (\"I_sure_hope_this_file_does_not_exist.jpg\");\n%!   catch\n%!     error_thrown = true;\n%!   end_try_catch\n%! unwind_protect_cleanup\n%!   imformats (\"update\", \"jpg\", fmt_ori);\n%! end_unwind_protect\n%! assert (error_thrown, true);\n\n## Test input validation\n%!error <Invalid call> imfinfo ()\n%!error <Invalid call> imfinfo (1,2,3)\n%!error <FILENAME must be a string> imfinfo (1)\n%!error <EXT must be a string> imfinfo (\"foo\", 1)\n"
  },
  {
    "path": "scripts/image/imformats.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} imformats ()\n## @deftypefnx {} {@var{formats} =} imformats (@var{ext})\n## @deftypefnx {} {@var{formats} =} imformats (@var{format})\n## @deftypefnx {} {@var{formats} =} imformats (\"add\", @var{format})\n## @deftypefnx {} {@var{formats} =} imformats (\"remove\", @var{ext})\n## @deftypefnx {} {@var{formats} =} imformats (\"update\", @var{ext}, @var{format})\n## @deftypefnx {} {@var{formats} =} imformats (\"factory\")\n## Manage supported image formats.\n##\n## @var{formats} is a structure with information about each supported file\n## format, or from a specific format @var{ext}, the value displayed on the\n## field @var{ext}.  It contains the following fields:\n##\n## @table @asis\n## @item ext\n## The name of the file format.  This may match the file extension but Octave\n## will automatically detect the file format.\n##\n## @item description\n## A long description of the file format.\n##\n## @item @nospell{isa}\n## A function handle to confirm if a file is of the specified format.\n##\n## @item write\n## A function handle to write if a file is of the specified format.\n##\n## @item read\n## A function handle to open files the specified format.\n##\n## @item info\n## A function handle to obtain image information of the specified format.\n##\n## @item alpha\n## Logical value if format supports alpha channel (transparency or matte).\n##\n## @item multipage\n## Logical value if format supports multipage (multiple images per file).\n## @end table\n##\n## It is possible to change the way Octave manages file formats with the\n## options @qcode{\"add\"}, @qcode{\"remove\"}, and @qcode{\"update\"}, and supplying\n## a structure @var{format} with the required fields.  The option\n## @qcode{\"factory\"} resets the configuration to the default.\n##\n## This can be used by Octave packages to extend the image reading capabilities\n## Octave, through use of the PKG_ADD and PKG_DEL commands.\n##\n## @seealso{imfinfo, imread, imwrite}\n## @end deftypefn\n\nfunction varargout = imformats (arg1, arg2, arg3)\n\n  mlock ();  # prevent formats being removed by \"clear all\"\n  persistent formats = default_formats ();\n\n  if (nargin == 0 && nargout == 0)\n    pretty_print_formats (formats);\n  elseif (nargin >= 1)\n    if (isstruct (arg1))\n      arrayfun (@is_valid_format, arg1);\n      ## FIXME: what is the return value in this situation?\n      formats = arg1;\n\n    elseif (ischar (arg1))\n      switch (lower (arg1))\n        case \"add\",\n          if (! isstruct (arg2))\n            error (\"imformats: FORMAT to %s must be a structure\", arg1);\n          endif\n          arrayfun (@is_valid_format, arg2);\n          formats(end + 1: end + numel (arg2)) = arg2;\n          varargout{1} = formats;\n\n        case {\"remove\", \"update\"},\n          if (! ischar (arg2))\n            error (\"imformats: EXT to %s must be a string\", arg1);\n          endif\n          ## FIXME: Suppose a format with multiple extensions; if one of\n          ##        them is requested to be removed, should we remove the\n          ##        whole format, or just that extension from the format?\n          match = find_ext_idx (formats, arg2);\n          if (! any (match))\n            error (\"imformats: no EXT '%s' found\", arg2);\n          endif\n          if (strcmpi (arg1, \"remove\"))\n            formats(match) = [];\n          else\n            ## then it's update\n            if (! isstruct (arg3))\n              error (\"imformats: FORMAT to update must be a structure\");\n            endif\n            is_valid_format (arg3);\n            formats(match) = arg3;\n          endif\n          varargout{1} = formats;\n\n        case \"factory\",\n          formats = default_formats ();\n        otherwise\n          ## then we look for a format with that extension.\n          match = find_ext_idx (formats, arg1);\n          ## For Matlab compatibility, if we don't find any format we must\n          ## return an empty struct with NO fields.  We can't use match as mask\n          if (any (match))\n            varargout{1} = formats(match);\n          else\n            varargout{1} = struct ();\n          endif\n      endswitch\n    else\n      error (\"imformats: first argument must be either a structure or string\");\n    endif\n  else\n    varargout{1} = formats;\n  endif\n\nendfunction\n\nfunction rformats = default_formats ()\n\n  ## The available formats are dependent on what the user has installed at\n  ## a given time, and how GraphicsMagick was built.  Checking for\n  ## GraphicsMagick features when building Octave is not enough since it\n  ## delegates some of them to external programs which can be removed or\n  ## installed at any time.\n  ## The recommended method would be to use CoderInfoList() to get a list of\n  ## all available coders and try to write and read back a small test image.\n  ## But this will not work since some coders are readable or writable only.\n  ## It will still fail if we test only the ones marked as readable and\n  ## writable because some RW coders are not of image formats (NULL, 8BIM,\n  ## or EXIF for example).\n  ## So we'd need a blacklist (unacceptable because a 'bad' coder may be\n  ## added later) or a whitelist.  A whitelist means that even with a\n  ## super-fancy recent build of GraphicsMagick, some formats won't be listed\n  ## by imformats but in truth, we will still be able to read and write them\n  ## since imread() and imwrite() will give it a try anyway.\n  ##\n  ## For more info and comments from the GraphicsMagick main developer, see\n  ## http://sourceforge.net/mailarchive/forum.php?thread_name=alpine.GSO.2.01.1304301916050.2267%40freddy.simplesystems.org&forum_name=graphicsmagick-help\n\n  persistent formats = struct ( \"coder\", {},\n                                \"ext\", {},\n                                \"isa\", {},\n                                \"info\", {},\n                                \"read\", {},\n                                \"write\", {},\n                                \"alpha\", {},\n                                \"description\", {},\n                                \"multipage\", {});\n\n  ## Image IO abilities won't change during the same Octave session,\n  ## there's no need to go and calculate it all over again if we are\n  ## requested to reset back to factory.\n  if (! isempty (formats))\n    rformats = formats;\n    return;\n  endif\n\n  ##      Building the formats info\n  ##\n  ## As mentioned above we start with a whitelist of coders.  Since the\n  ## GraphicsMagick build may be missing some coders, we will remove those\n  ## from the list.  Some info can be obtained directly from GraphicsMagick\n  ## through the CoderInfo object.  However, some will need to be hardcoded.\n  ##\n  ## The association between file extensions and coders needs to be done\n  ## with a manually coded list (file extensions do not define the image\n  ## format and GraphicsMagick will not be fooled by changing the extension).\n  ##\n  ## We can get the read, write, description and multipage fields from\n  ## CoderInfo in C++.  We should do the same for alpha (GraphicsMagick\n  ## calls it matte) but it's not available from CoderInfo.  The only way to\n  ## check it is to create a sample image with each coder, then try to read\n  ## it back with GraphicsMagick and use the matte method on the Image class.\n  ## But making such test for each Octave session... meh! While technically\n  ## it may be possible that the same coder has different support for alpha\n  ## channel in different versions and builds, this doesn't seem to happen.\n  ## So we also hardcode those.  In the future, maybe the CoderInfo class will\n  ## have a matte method like it does for multipage.\n  ##\n  ## Other notes: some formats have more than one coder that do the same.  For\n  ## example, for jpeg images there is both the JPG and JPEG coders.  However,\n  ## it seems that when reading images, GraphicsMagick only uses one of them\n  ## and that's the one we list (it's the one reported by imfinfo and that we\n  ## can use for isa).  However, in some cases GraphicsMagick seems to rely\n  ## uniquely on the file extension (JBIG and JBG at least.  Create an image\n  ## with each of those coders, swap their extension and it will report the\n  ## other coder).  We don't have such cases on the whitelist but if we did, we\n  ## would need two entries for such cases.\n\n  ## each row: 1st => Coder, 2nd=> file extensions, 3rd=> alpha\n  coders = {\"BMP\",  {\"bmp\"},          true;\n            \"CUR\",  {\"cur\"},          false;\n            \"GIF\",  {\"gif\"},          true;\n            \"ICO\",  {\"ico\"},          true;\n            \"JBG\",  {\"jbg\"},          false;\n            \"JBIG\", {\"jbig\"},         false;\n            \"JP2\",  {\"jp2\", \"jpx\"},   true;\n            \"JPEG\", {\"jpg\", \"jpeg\"},  false; # there is also a JPG coder\n            \"PBM\",  {\"pbm\"},          false;\n            \"PCX\",  {\"pcx\"},          true;\n            \"PGM\",  {\"pgm\"},          false;\n            \"PNG\",  {\"png\"},          true;\n            ## PNM is a family of formats supporting portable bitmaps (PBM),\n            ## graymaps (PGM), and pixmaps (PPM).  There is no file format\n            ## associated with pnm itself.  If PNM is used as the output format\n            ## specifier, then GraphicsMagick automatically selects the most\n            ## appropriate format to represent the image.\n            \"PNM\",  {\"pnm\"},          true;\n            \"PPM\",  {\"ppm\"},          false;\n            \"SUN\",  {\"ras\"},          true; # SUN Rasterfile\n            \"TGA\",  {\"tga\", \"tpic\"},  true;\n            \"TIFF\", {\"tif\", \"tiff\"},  true;\n            \"XBM\",  {\"xbm\"},          false;\n            \"XPM\",  {\"xpm\"},          true;\n            \"XWD\",  {\"xwd\"},          false;\n            };\n\n  for fidx = 1:rows (coders)\n    formats(fidx).coder = coders{fidx, 1};\n    formats(fidx).ext   = coders{fidx, 2};\n    formats(fidx).alpha = coders{fidx, 3};\n    ## default isa is to check if the format returned by imfinfo is the coder\n    formats(fidx).isa   = @(x) isa_magick (coders{fidx,1}, x);\n  endfor\n\n  ## the default info, read, and write functions\n  [formats.info ] = deal (@__imfinfo__);\n  [formats.read ] = deal (@__imread__);\n  [formats.write] = deal (@__imwrite__);\n\n  ## fills rest of format information by checking with GraphicsMagick\n  formats = __magick_formats__ (formats);\n\n  rformats = formats;\n\nendfunction\n\nfunction is_valid_format (format)\n\n  ## the minimal list of fields required in the structure.  We don't\n  ## require multipage because it doesn't exist in matlab\n  min_fields  = {\"ext\", \"read\", \"isa\", \"write\", \"info\", \"alpha\", \"description\"};\n  fields_mask = isfield (format, min_fields);\n  if (! all (fields_mask))\n    error (\"imformats: structure has missing field '%s'\", min_fields(! fields_mask){1});\n  endif\n\nendfunction\n\nfunction match = find_ext_idx (formats, ext)\n\n  ## FIXME: what should we do if there's more than one hit?\n  ##        Should this function prevent the addition of\n  ##        duplicated extensions?\n  match = cellfun (@(x) any (strcmpi (x, ext)), {formats.ext});\n\nendfunction\n\nfunction bool = isa_magick (coder, filename)\n\n  bool = false;\n  try\n    info = __magick_ping__ (filename, 1);\n    bool = strcmp (coder, info.format);\n  end_try_catch\n\nendfunction\n\nfunction pretty_print_formats (formats)\n\n  ## define header names (none should be shorter than 3 characters)\n  headers = {\"Extension\", \"isa\", \"Info\", \"Read\", \"Write\", \"Alpha\", \"Description\"};\n  cols_length = cellfun ('numel', headers);\n\n  ## Adjust the maximal length of the extensions column\n  extensions = cellfun ('strjoin', {formats.ext}, {\", \"},\n                        \"UniformOutput\", false);\n  if (! isempty (extensions))\n    cols_length(1) = max (max (cellfun ('numel', extensions)), cols_length(1));\n  endif\n  headers{1} = postpad (headers{1}, cols_length(1), \" \");\n\n  ## Print the headers\n  disp (strjoin (headers, \" | \"));\n  under_headers = cellfun (@(x) repmat (\"-\", 1, numel (x)), headers,\n                           \"UniformOutput\", false);\n  disp (strjoin (under_headers, \"-+-\"));\n\n  template = strjoin (arrayfun (@(x) sprintf (\"%%-%is\", x), cols_length,\n                                \"UniformOutput\", false), \" | \");\n\n  ## Print the function handle for this things won't be a pretty table.  So\n  ## instead we replace them with \"yes\" or \"no\", based on the support it has.\n  yes_no_cols = cat (2, {formats.isa}(:), {formats.info}(:), {formats.read}(:),\n                     {formats.write}(:), {formats.alpha}(:));\n  empty = cellfun ('isempty', yes_no_cols);\n  yes_no_cols(empty) = \"no\";\n  yes_no_cols(! empty) = \"yes\";\n\n  descriptions = {formats.description};\n  table = cat (2, extensions(:), yes_no_cols, descriptions(:));\n  printf ([template \"\\n\"], table'{:});\n\nendfunction\n\n\n## This must work, even without support for image IO\n%!test\n%! formats = imformats ();\n%! assert (isstruct (formats));\n%!\n%! min_fields = {\"ext\", \"read\", \"isa\", \"write\", \"info\", \"alpha\", \"description\"};\n%! assert (all (ismember (min_fields, fieldnames (formats))));\n%!\n%! if (__have_feature__ (\"MAGICK\"))\n%!   assert (numel (formats) > 0);\n%! else\n%!   assert (numel (formats), 0);\n%! endif\n\n## When imread or imfinfo are called, the file must exist or the\n## function defined by imformats will never be called.  Because\n## of this, we must create a file for the tests to work.\n\n## changing the function that does the reading\n%!testif HAVE_MAGICK\n%! fname = [tempname() \".jpg\"];\n%! def_fmt = imformats ();\n%! fid = fopen (fname, \"w\");\n%! unwind_protect\n%!   fmt = imformats (\"jpg\");\n%!   fmt.read = @numel;\n%!   imformats (\"update\", \"jpg\", fmt);\n%!   assert (imread (fname), numel (fname));\n%! unwind_protect_cleanup\n%!   fclose (fid);\n%!   unlink (fname);\n%!   imformats (def_fmt);\n%! end_unwind_protect\n\n## adding a new format\n%!testif HAVE_MAGICK\n%! fname = [tempname() \".new_fmt\"];\n%! def_fmt = imformats ();\n%! fid = fopen (fname, \"w\");\n%! unwind_protect\n%!   fmt = imformats (\"jpg\"); # take jpg as template\n%!   fmt.ext = \"new_fmt\";\n%!   fmt.read = @(~) true ();\n%!   imformats (\"add\", fmt);\n%!   assert (imread (fname), true);\n%! unwind_protect_cleanup\n%!   fclose (fid);\n%!   unlink (fname);\n%!   imformats (def_fmt);\n%! end_unwind_protect\n\n## adding multiple formats at the same time\n%!testif HAVE_MAGICK\n%! fname1 = [tempname() \".new_fmt1\"];\n%! fid1 = fopen (fname1, \"w\");\n%! fname2 = [tempname() \".new_fmt2\"];\n%! fid2 = fopen (fname2, \"w\");\n%! def_fmt = imformats ();\n%! unwind_protect\n%!   fmt = imformats (\"jpg\"); # take jpg as template\n%!   fmt.ext = \"new_fmt1\";\n%!   fmt.read = @(~) true ();\n%!   fmt(2) = fmt(1);\n%!   fmt(2).ext = \"new_fmt2\";\n%!   imformats (\"add\", fmt);\n%!   assert (imread (fname1), true);\n%!   assert (imread (fname2), true);\n%! unwind_protect_cleanup\n%!   fclose (fid1);\n%!   fclose (fid2);\n%!   unlink (fname1);\n%!   unlink (fname2);\n%!   imformats (def_fmt);\n%! end_unwind_protect\n\n## changing format and resetting back to default\n%!testif HAVE_MAGICK\n%! ori_fmt = mod_fmt = imformats (\"jpg\");\n%! mod_fmt.description = \"Another description\";\n%! imformats (\"update\", \"jpg\", mod_fmt);\n%! new_fmt = imformats (\"jpg\");\n%! assert (new_fmt.description, mod_fmt.description);\n%! imformats (\"factory\");\n%! new_fmt = imformats (\"jpg\");\n%! assert (new_fmt.description, ori_fmt.description);\n\n## updating to an invalid format should cause an error\n%!testif HAVE_MAGICK\n%! fmt = imformats (\"jpg\");\n%! fmt = rmfield (fmt, \"read\");\n%! error_thrown = false;\n%! try\n%!   imformats (\"update\", \"jpg\", fmt);\n%! catch\n%!   error_thrown = true;\n%! end_try_catch\n%! assert (error_thrown, true);\n"
  },
  {
    "path": "scripts/image/imread.m",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{img}, @var{map}, @var{alpha}] =} imread (@var{filename})\n## @deftypefnx {} {[@dots{}] =} imread (@var{url})\n## @deftypefnx {} {[@dots{}] =} imread (@dots{}, @var{ext})\n## @deftypefnx {} {[@dots{}] =} imread (@dots{}, @var{idx})\n## @deftypefnx {} {[@dots{}] =} imread (@dots{}, @var{param1}, @var{value1}, @dots{})\n## Read images from various file formats.\n##\n## Read an image as a matrix from the file @var{filename} or from the online\n## resource @var{url}.  If neither is given, but @var{ext} was specified, look\n## for a file with the extension @var{ext}.\n##\n## The size and class of the output depends on the format of the image.  A\n## color image is returned as an @nospell{MxNx3} matrix.  Grayscale and\n## black-and-white images are of size @nospell{MxN}@.  Multipage images will\n## have an additional 4th dimension.\n##\n## The bit depth of the image determines the class of the output:\n## @qcode{\"uint8\"}, @qcode{\"uint16\"}, or @qcode{\"single\"} for grayscale and\n## color, and @qcode{\"logical\"} for black-and-white.  Note that indexed images\n## always return the indexes for a colormap, independent of whether @var{map}\n## is a requested output.  To obtain the actual RGB image, use @code{ind2rgb}.\n## When more than one indexed image is being read, @var{map} is obtained from\n## the first.  In some rare cases this may be incorrect and @code{imfinfo} can\n## be used to obtain the colormap of each image.\n##\n## See the Octave manual for more information in representing images.\n## (@pxref{Representing Images})\n##\n## Some file formats, such as TIFF and GIF, are able to store multiple images\n## in a single file.  @var{idx} can be a scalar or vector specifying the\n## index of the images to read.  By default, Octave will read only the first\n## page.\n##\n## Depending on the file format, it is possible to configure the reading of\n## images with @var{parameter}, @var{value} pairs.  The following options are\n## supported:\n##\n## @table @asis\n## @item @qcode{\"Frames\"} or @qcode{\"Index\"}\n## This is an alternative method to specify @var{idx}.  When specifying it\n## in this way, its value can also be the string @qcode{\"all\"}.\n##\n## @item @qcode{\"Info\"}\n## This option exists for @sc{matlab} compatibility, but has no effect.  For\n## maximum performance when reading multiple images from a single file, use\n## the @qcode{\"Index\"} option.\n##\n## @item @qcode{\"PixelRegion\"}\n## Controls the image region that is read.  The value must be a cell array with\n## two arrays of 3 elements @code{@{[@var{rows}], [@var{cols}]@}}.  The\n## elements in the array are the start, increment, and end pixel to be read.\n## If the increment value is omitted it defaults to 1.  For example, the\n## following are all equivalent:\n##\n## @format\n## @group\n## @code{imread (filename, \"PixelRegion\", @{[200 600], [300 700]@})}\n## @code{imread (filename, \"PixelRegion\", @{[200 1 600], [300 1 700]@})}\n## @code{imread (filename)(200:600, 300:700)}\n## @end group\n## @end format\n##\n## @end table\n##\n## @seealso{imwrite, imfinfo, imformats}\n## @end deftypefn\n\nfunction [img, varargout] = imread (filename, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! ischar (filename))\n    error (\"imread: FILENAME must be a string\");\n  endif\n\n  [img, varargout{1:nargout-1}] = ...\n    imageIO (\"imread\", @__imread__, \"read\", filename, varargin{:});\n\nendfunction\n\n\n%!testif HAVE_MAGICK\n%! vpng = [ ...\n%!  137,  80,  78,  71,  13,  10,  26,  10,   0,   0, ...\n%!    0,  13,  73,  72,  68,  82,   0,   0,   0,   3, ...\n%!    0,   0,   0,   3,   8,   2,   0,   0,   0, 217, ...\n%!   74,  34, 232,   0,   0,   0,   1, 115,  82,  71, ...\n%!   66,   0, 174, 206,  28, 233,   0,   0,   0,   4, ...\n%!  103,  65,  77,  65,   0,   0, 177, 143,  11, 252, ...\n%!   97,   5,   0,   0,   0,  32,  99,  72,  82,  77, ...\n%!    0,   0, 122,  38,   0,   0, 128, 132,   0,   0, ...\n%!  250,   0,   0,   0, 128, 232,   0,   0, 117,  48, ...\n%!    0,   0, 234,  96,   0,   0,  58, 152,   0,   0, ...\n%!   23, 112, 156, 186,  81,  60,   0,   0,   0,  25, ...\n%!   73,  68,  65,  84,  24,  87,  99,  96,  96,  96, ...\n%!  248, 255, 255,  63, 144,   4,  81, 111, 101,  84, ...\n%!   16,  28, 160,  16,   0, 197, 214,  13,  34,  74, ...\n%!  117, 213,  17,   0,   0,   0,   0,  73,  69,  78, ...\n%!   68, 174,  66,  96, 130];\n%! filename = [tempname() \".png\"];\n%! unwind_protect\n%!   fid = fopen (filename, \"wb\");\n%!   fwrite (fid, vpng);\n%!   fclose (fid);\n%!   A = imread (filename);\n%! unwind_protect_cleanup\n%!   unlink (filename);\n%! end_unwind_protect\n%! assert (A(:,:,1), uint8 ([0, 255, 0; 255, 237, 255; 0, 255, 0]));\n%! assert (A(:,:,2), uint8 ([0, 255, 0; 255,  28, 255; 0, 255, 0]));\n%! assert (A(:,:,3), uint8 ([0, 255, 0; 255,  36, 255; 0, 255, 0]));\n\n%!function [r, cmap, a] = write_and_read (w, f_ext, varargin)\n%!  filename = [tempname() \".\" f_ext];\n%!  unwind_protect\n%!    imwrite (w, filename);\n%!    [r, cmap, a] = imread (filename, varargin{:});\n%!  unwind_protect_cleanup\n%!    unlink (filename);\n%!  end_unwind_protect\n%!endfunction\n\n## test PixelRegion option\n%!testif HAVE_MAGICK\n%! w = randi (255, 100, 100, \"uint8\");\n%! [r, cmap, a] = write_and_read (w, \"tif\", \"PixelRegion\", {[50 70] [20 40]});\n%! assert (r, w(50:70, 20:40));\n%! [r, cmap, a] = write_and_read (w, \"tif\", \"PixelRegion\", {[50 2 70] [20 3 40]});\n%! assert (r, w(50:2:70, 20:3:40));\n\n## If a file does not exist, it's the job of imread to check the file\n## exists before sending it over to __imread__ or whatever function\n## is defined in imformats to handle that specific format.  This is the\n## same in imfinfo.  So in this test we replace one format in imformats\n## with something that will not give an error if the file is missing\n## and make sure we do get an error.\n%!testif HAVE_MAGICK\n%! fmt = fmt_ori = imformats (\"jpg\");\n%! fmt.read = @true;\n%! error_thrown = false;\n%! imformats (\"update\", \"jpg\", fmt);\n%! unwind_protect\n%!   try\n%!     imread (\"I_sure_hope_this_file_does_not_exist.jpg\");\n%!   catch\n%!     error_thrown = true;\n%!   end_try_catch\n%! unwind_protect_cleanup\n%!   imformats (\"update\", \"jpg\", fmt_ori);\n%! end_unwind_protect\n%! assert (error_thrown, true);\n\n## make one of the formats read, return what it received as input to\n## confirm that the input parsing is working correctly\n%!testif HAVE_MAGICK\n%! fname = [tempname() \".jpg\"];\n%! def_fmt = imformats ();\n%! fid = fopen (fname, \"w\");\n%! unwind_protect\n%!   fmt = imformats (\"jpg\");\n%!   fmt.read = @(varargin) varargin;\n%!   imformats (\"update\", \"jpg\", fmt);\n%!   assert (imread (fname), {fname});\n%!   assert (imread (fname, \"jpg\"), {fname});\n%!   assert (imread (fname(1:end-4), \"jpg\"), {fname});\n%!   extra_inputs = {\"some\", 89, i, {6 7 8}};\n%!   assert (imread (fname, extra_inputs{:}), {fname, extra_inputs{:}});\n%!   assert (imread (fname, \"jpg\", extra_inputs{:}), {fname, extra_inputs{:}});\n%!   assert (imread (fname(1:end-4), \"jpg\", extra_inputs{:}),\n%!           {fname, extra_inputs{:}});\n%! unwind_protect_cleanup\n%!   fclose (fid);\n%!   unlink (fname);\n%!   imformats (def_fmt);\n%! end_unwind_protect\n\n## Test for bug #41584 (some GM coders report saturated channels as binary)\n%!testif HAVE_MAGICK <41584>\n%! im = zeros ([16 16 3], \"uint8\");\n%! im(:,:,1) = 255;\n%! im(:,:,3) = repmat (0:16:255, [16 1]);\n%! [r, cmap, a] = write_and_read (im, \"png\");\n%! assert (class (r), \"uint8\");\n%! assert (isempty (cmap));\n%! assert (isempty (a));\n"
  },
  {
    "path": "scripts/image/imshow.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} imshow (@var{im})\n## @deftypefnx {} {} imshow (@var{im}, @var{limits})\n## @deftypefnx {} {} imshow (@var{im}, @var{map})\n## @deftypefnx {} {} imshow (@var{rgb}, @dots{})\n## @deftypefnx {} {} imshow (@var{filename})\n## @deftypefnx {} {} imshow (@dots{}, @var{string_param1}, @var{value1}, @dots{})\n## @deftypefnx {} {@var{h} =} imshow (@dots{})\n## Display the image @var{im}, where @var{im} can be a 2-dimensional\n## (grayscale image) or a 3-dimensional (RGB image) matrix.\n##\n## If @var{limits} is a 2-element vector @code{[@var{low}, @var{high}]}, the\n## image is shown using a display range between @var{low} and @var{high}.  If\n## an empty matrix is passed for @var{limits}, the display range is computed\n## as the range between the minimal and the maximal value in the image.\n##\n## If @var{map} is a valid colormap, the image will be shown as an indexed\n## image using the supplied colormap.\n##\n## If a filename is given instead of an image, the file will be read and shown.\n##\n## If given, the parameter @var{string_param1} has value @var{value1}.\n## @var{string_param1} can be any of the following:\n##\n## @table @asis\n## @item @qcode{\"displayrange\"}\n## @var{value1} is the display range as described above.\n##\n## @item @qcode{\"colormap\"}\n## @var{value1} is the colormap to use when displaying an indexed image.\n##\n## @item @qcode{\"xdata\"}\n## If @var{value1} is a 2-element vector, it must contain horizontal image\n## limits in the form [xfirst, xlast], where xfirst and xlast are the\n## abscissa of the centers of the corner pixels.  Otherwise @var{value1}\n##  must be a vector and only the first and last elements will be used\n## for xfirst and xlast respectively.\n##\n## @item @qcode{\"ydata\"}\n## If @var{value1} is a 2-element vector, it must contain vertical image\n## limits in the form [yfirst, ylast], where yfirst and ylast are the ordinates\n## of the center of the corner pixels.  Otherwise @var{value1} must be a vector\n## and only the first and last elements will be used for yfirst and ylast\n## respectively.\n##\n## @end table\n##\n## The optional return value @var{h} is a graphics handle to the image.\n## @seealso{image, imagesc, colormap, gray2ind, rgb2ind}\n## @end deftypefn\n\nfunction h = imshow (im, varargin)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  display_range = NA;\n  truecolor = false;\n  indexed = false;\n  xdata = ydata = [];\n  prop_val_args = {};\n\n  ## Get the image.\n  if (ischar (im))\n    [im, map] = imread (im);\n    if (isempty (map))\n      indexed = false;\n    else\n      indexed = true;\n      colormap (gca, map);\n    endif\n  endif\n\n  nd = ndims (im);\n\n  if (! ((isnumeric (im) || islogical (im)) && (nd == 2 || nd == 3)))\n    error (\"imshow: IM must be an image or the FILENAME of an image\");\n  endif\n\n  if (nd == 2)\n    if (! indexed)\n      colormap (gca, gray ());\n    endif\n  elseif (size (im, 3) == 3)\n    if (ismember (class (im), {\"uint8\", \"uint16\", \"double\", \"single\"}))\n      truecolor = true;\n    else\n      error (\"imshow: TrueColor image must be uint8, uint16, double, or single\");\n    endif\n  else\n    error (\"imshow: image must be MxN or MxNx3 matrix\");\n  endif\n\n  narg = 1;\n  while (narg <= numel (varargin))\n    arg = varargin{narg++};\n    if (isnumeric (arg))\n      if (numel (arg) == 2 || isempty (arg))\n        display_range = arg;\n      elseif (columns (arg) == 3)\n        indexed = true;\n        if (iscolormap (arg) && min (arg) >= 0 || max (arg) <= 1)\n          colormap (gca, arg);\n        else\n          error (\"imshow: invalid colormap MAP\");\n        endif\n      elseif (! isempty (arg))\n        error (\"imshow: argument number %d is invalid\", narg);\n      endif\n    elseif (ischar (arg))\n      switch (lower (arg))\n        case \"border\"\n          warning (\"imshow: border argument is not implemented\");\n          narg += 1;\n        case \"colormap\"\n          map = varargin{narg++};\n          if (iscolormap (map) && min (map) >= 0 || max (map) <= 1)\n            colormap (gca, map);\n          else\n            error (\"imshow: invalid colormap\");\n          endif\n        case \"displayrange\"\n          display_range = varargin{narg++};\n        case {\"initialmagnification\"}\n          warning (\"imshow: zoom argument ignored -- use GUI features\");\n          narg += 1;\n        case \"parent\"\n          prop_val_args(end+(1:2)) = {\"parent\", varargin{narg++}};\n          if (! isaxes (prop_val_args{end}))\n            error (\"imshow: parent must be an axes handle\");\n          endif\n        case \"reduce\"\n          warning (\"imshow: reduce argument is not implemented\");\n          narg += 1;\n        case \"xdata\"\n          xdata = varargin{narg++};\n          if (! isvector (xdata))\n            error (\"imshow: xdata must be a vector\");\n          endif\n          xdata = [xdata(1) xdata(end)];\n        case \"ydata\"\n          ydata = varargin{narg++};\n          if (! isvector (ydata))\n            error (\"imshow: ydata must be a vector\");\n          endif\n          ydata = [ydata(1) ydata(end)];\n        otherwise\n          warning (\"imshow: unrecognized property %s\", arg);\n          narg += 1;\n      endswitch\n    else\n      error (\"imshow: argument number %d is invalid\", narg);\n    endif\n  endwhile\n\n  ## Check for complex images.\n  if (iscomplex (im))\n    warning (\"imshow: only showing real part of complex image\");\n    im = real (im);\n  endif\n\n  ## Set default display range if display_range not set yet.\n  if (isempty (display_range))\n    display_range = double ([min(im(:)), max(im(:))]);\n  elseif (isna (display_range))\n    t = class (im);\n    switch (t)\n      case {\"double\", \"single\", \"logical\"}\n        display_range = [0, 1];\n      case {\"uint8\", \"uint16\", \"int16\"}\n        display_range = [intmin(t), intmax(t)];\n      otherwise\n        error (\"imshow: invalid data type for image\");\n    endswitch\n  endif\n\n  if (isfloat (im))\n    nans = isnan (im(:));\n    if (any (nans))\n      warning (\"Octave:imshow-NaN\",\n               \"imshow: pixels with NaN or NA values are set to minimum pixel value\");\n      im(nans) = display_range(1);\n    endif\n  endif\n\n  if (truecolor || indexed)\n    htmp = image (xdata, ydata, im, prop_val_args{:});\n  else\n    htmp = imagesc (xdata, ydata, im, display_range, prop_val_args{:});\n    set (get (htmp, \"parent\"), \"clim\", display_range);\n  endif\n  set (get (htmp, \"parent\"), \"visible\", \"off\", \"view\", [0, 90],\n                             \"ydir\", \"reverse\", \"layer\", \"top\");\n  axis (\"image\");\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! imshow (\"default.img\");\n\n%!demo\n%! clf;\n%! imshow (\"default.img\");\n%! colormap (gca, autumn (64));\n\n%!demo\n%! clf;\n%! [I, M] = imread (\"default.img\");\n%! imshow (I, M);\n\n%!demo\n%! clf;\n%! [I, M] = imread (\"default.img\");\n%! [R, G, B] = ind2rgb (I, M);\n%! imshow (cat (3, R, G*0.5, B*0.8));\n\n%!demo\n%! clf;\n%! imshow (rand (100, 100));\n%! title ({\"imshow with random 100x100 matrix\", \"black and white\"});\n\n%!demo\n%! clf;\n%! imshow (rand (100, 100));\n%! colormap (gca, jet (64));\n%! title ({\"imshow with random 100x100 matrix\", \"colormap() makes color image\"});\n\n%!demo\n%! clf;\n%! imshow (rand (100, 100, 3));\n%! title ({\"imshow with random 100x100x3 matrix\", \"RGB color\"});\n\n%!demo\n%! clf;\n%! imshow (100*rand (100, 100, 3));\n%! title ({\"imshow with random 100x100x3 matrix\", \"RGB values > 1 are clipped\"});\n\n## Test input validation\n%!error <Invalid call> imshow ()\n%!error <IM must be an image> imshow ({\"cell\"})\n%!error <TrueColor image must be uint8> imshow (ones (3,3,3, \"uint32\"))\n%!error <TrueColor image must be uint8> imshow (ones (3,3,3, \"int16\"))\n%!error <image must be MxN or MxNx3 matrix> imshow (ones (4,4,4))\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   fail (\"imshow ([1,1], [2 0 0])\", \"all MAP values must be in the range\");\n%!   fail (\"imshow ([1,1], [1 0 0 0])\", \"argument number 2 is invalid\");\n%!   fail ('imshow ([1,1], \"colormap\", [2 0 0])', \"all MAP values must be in the range\");\n%!   fail ('imshow ([1,1], \"parent\", -1)', \"must be an axes handle\");\n%!   fail ('imshow ([1,1], \"xdata\", ones (2,2))', \"xdata must be a vector\");\n%!   fail ('imshow ([1,1], \"ydata\", ones (2,2))', \"ydata must be a vector\");\n%!   fail ('imshow ([1,1], \"foobar\")', \"warning\", \"unrecognized property foobar\");\n%!   fail (\"imshow ([1,1], {1})\", \"argument number 2 is invalid\");\n%!   fail (\"imshow ([1+i,1-i])\", \"warning\", \"only showing real part of complex image\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/image/imwrite.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} imwrite (@var{img}, @var{filename})\n## @deftypefnx {} {} imwrite (@var{img}, @var{filename}, @var{ext})\n## @deftypefnx {} {} imwrite (@var{img}, @var{map}, @var{filename})\n## @deftypefnx {} {} imwrite (@dots{}, @var{param1}, @var{val1}, @dots{})\n## Write images in various file formats.\n##\n## The image @var{img} can be a binary, grayscale, RGB, or multi-dimensional\n## image.  The size and class of @var{img} should be the same as what should\n## be expected when reading it with @code{imread}: the 3rd and 4th dimensions\n## reserved for color space, and multiple pages respectively.  If it's an\n## indexed image, the colormap @var{map} must also be specified.\n##\n## If @var{ext} is not supplied, the file extension of @var{filename} is used\n## to determine the format.  The actual supported formats are dependent on\n## options made during the build of Octave.  Use @code{imformats} to check\n## the support of the different image formats.\n##\n## Depending on the file format, it is possible to configure the writing of\n## images with @var{param}, @var{val} pairs.  The following options are\n## supported:\n##\n## @table @samp\n## @item Alpha\n## Alpha (transparency) channel for the image.  This must be a matrix with\n## same class, and number of rows and columns of @var{img}.  In case of a\n## multipage image, the size of the 4th dimension must also match and the third\n## dimension must be a singleton.  By default, image will be completely opaque.\n##\n## @item Compression\n## Compression to use one the image.  Can be one of the following: \"none\"\n## (default), \"bzip\", \"fax3\", \"fax4\", \"jpeg\", \"lzw\", \"rle\", or \"deflate\".\n## Note that not all compression types are available for all image formats\n## in which it defaults to your @nospell{Magick} library.\n##\n## @item DelayTime\n## For formats that accept animations (such as GIF), controls for how long a\n## frame is displayed until it moves to the next one.  The value must be scalar\n## (which will applied to all frames in @var{img}), or a vector of length\n## equal to the number of frames in @var{im}.  The value is in seconds, must\n## be between 0 and 655.35, and defaults to 0.5.\n##\n## @item DisposalMethod\n## For formats that accept animations (such as GIF), controls what happens to\n## a frame before drawing the next one.  Its value can be one of the\n## following strings: \"doNotSpecify\" (default); \"leaveInPlace\"; \"restoreBG\";\n## and \"restorePrevious\", or a cell array of those string with length equal\n## to the number of frames in @var{img}.\n##\n## @item LoopCount\n## For formats that accept animations (such as GIF), controls how many times\n## the sequence is repeated.  A value of Inf means an infinite loop (default),\n## a value of 0 or 1 that the sequence is played only once (loops zero times),\n## while a value of 2 or above loops that number of times (looping twice means\n## it plays the complete sequence 3 times).  This option is ignored when there\n## is only a single image at the end of writing the file.\n##\n## @item Quality\n## Set the quality of the compression.  The value should be an integer\n## between 0 and 100, with larger values indicating higher visual quality and\n## lower compression.  Defaults to 75.\n##\n## @item WriteMode\n## Some file formats, such as TIFF and GIF, are able to store multiple images\n## in a single file.  This option specifies if @var{img} should be appended\n## to the file (if it exists) or if a new file should be created for it\n## (possibly overwriting an existing file).  The value should be the string\n## @qcode{\"Overwrite\"} (default), or @qcode{\"Append\"}.\n##\n## Despite this option, the most efficient method of writing a multipage\n## image is to pass a 4 dimensional @var{img} to @code{imwrite}, the same\n## matrix that could be expected when using @code{imread} with the option\n## @qcode{\"Index\"} set to @qcode{\"all\"}.\n##\n## @end table\n##\n## @seealso{imread, imfinfo, imformats}\n## @end deftypefn\n\nfunction imwrite (varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  [filename, ext] = imwrite_filename (varargin{2:end});\n\n  fmt = imformats (ext);\n  ## When there is no match, fmt will be a 1x1 structure with\n  ## no fields, so we can't just use 'isempty (fmt)'.\n  if (numfields (fmt) == 0)\n    if (isempty (ext))\n      error (\"imwrite: no extension found for %s to identify the image format\",\n             filename);\n    endif\n    warning (\"imwrite: unlisted image format %s (see imformats).  Trying to save anyway.\",\n             ext);\n    __imwrite__ (varargin{:});\n  else\n    fmt.write (varargin{:});\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> imwrite ()             # Wrong # of args\n%!error <Invalid call> imwrite (1)            # Wrong # of args\n%!error imwrite ({\"cell\"}, \"filename.jpg\")    # Wrong class for img\n%!error imwrite (1, [], \"filename.jpg\")       # Empty image map\n%!error imwrite (1, 2, 3)                     # No filename specified\n%!error imwrite (1, \"filename\")               # No fmt specified\n%!error imwrite (1, \"filename\", \"junk\")       # Invalid fmt specified\n%!error imwrite ([], \"filename.jpg\")          # Empty img matrix\n%!error imwrite (spones (2), \"filename.jpg\")  # Invalid sparse img\n\n%!function [r, cmap, a] = write_and_read (format, varargin)\n%!  filename = [tempname() format];\n%!  unwind_protect\n%!    imwrite (varargin{1}, filename, varargin{2:end});\n%!    [r, cmap, a] = imread (filename, \"Index\", \"all\");\n%!  unwind_protect_cleanup\n%!    unlink (filename);\n%!  end_unwind_protect\n%!endfunction\n\n## typical usage with grayscale uint8 images\n%!testif HAVE_MAGICK\n%! gray = randi (255, 10, 10, 1, \"uint8\");\n%! r = write_and_read (\".tif\", gray);\n%! assert (r, gray);\n\n## grayscale uint8 images with alpha channel\n%!testif HAVE_MAGICK\n%! gray  = randi (255, 10, 10, 1, \"uint8\");\n%! alpha = randi (255, 10, 10, 1, \"uint8\");\n%! [r, ~, a] = write_and_read (\".tif\", gray, \"Alpha\", alpha);\n%! assert (r, gray);\n%! assert (a, alpha);\n\n## multipage grayscale uint8 images\n%!testif HAVE_MAGICK\n%! gray = randi (255, 10, 10, 1, 5, \"uint8\");\n%! r    = write_and_read (\".tif\", gray);\n%! assert (r, gray);\n\n## multipage RGB uint8 images with alpha channel\n%!testif HAVE_MAGICK\n%! gray  = randi (255, 10, 10, 3, 5, \"uint8\");\n%! alpha = randi (255, 10, 10, 1, 5, \"uint8\");\n%! [r, ~, a] = write_and_read (\".tif\", gray, \"Alpha\", alpha);\n%! assert (r, gray);\n%! assert (a, alpha);\n\n## typical usage with RGB uint8 images\n%!testif HAVE_MAGICK\n%! rgb = randi (255, 10, 10, 3, \"uint8\");\n%! r = write_and_read (\".tif\", rgb);\n%! assert (r, rgb);\n\n## RGB uint8 images with alpha channel\n%!testif HAVE_MAGICK\n%! rgb   = randi (255, 10, 10, 3, \"uint8\");\n%! alpha = randi (255, 10, 10, 1, \"uint8\");\n%! [r, ~, a] = write_and_read (\".tif\", rgb, \"Alpha\", alpha);\n%! assert (r, rgb);\n%! assert (a, alpha);\n\n## multipage RGB uint8 images\n%!testif HAVE_MAGICK\n%! rgb = randi (255, 10, 10, 3, 5, \"uint8\");\n%! r = write_and_read (\".tif\", rgb);\n%! assert (r, rgb);\n\n## multipage RGB uint8 images with alpha channel\n%!testif HAVE_MAGICK\n%! rgb   = randi (255, 10, 10, 3, 5, \"uint8\");\n%! alpha = randi (255, 10, 10, 1, 5, \"uint8\");\n%! [r, ~, a] = write_and_read (\".tif\", rgb, \"Alpha\", alpha);\n%! assert (r, rgb);\n%! assert (a, alpha);\n\n%!testif HAVE_MAGICK\n%! gray = repmat (uint8 (0:255), 100, 1);\n%! [g] = write_and_read (\".jpeg\", gray);\n%! assert (g, gray, 2);\n\n%!testif HAVE_MAGICK\n%! gray = repmat (uint8 (0:255), 100, 1);\n%! [g] = write_and_read (\".jpeg\", gray, \"quality\", 100);\n%! assert (g, gray);\n\n%!function compression = get_bmp_compression (ext, cmap = [], varargin)\n%!  gray = repmat (uint8 (0:255), 100, 1);\n%!  filename = [tempname() ext];\n%!  unwind_protect\n%!    if (isempty (cmap))\n%!      imwrite (gray, filename, varargin{1:end});\n%!    else\n%!      imwrite (gray, cmap, filename, varargin{1:end});\n%!    endif\n%!    fid = fopen (filename);\n%!    unwind_protect\n%!      compression = fread (fid, 31)(end);\n%!    unwind_protect_cleanup\n%!      fclose (fid);\n%!    end_unwind_protect\n%!  unwind_protect_cleanup\n%!    unlink (filename);\n%!  end_unwind_protect\n%!endfunction\n\n## BMP images must be saved uncompressed by default\n%!testif HAVE_MAGICK <*45565>\n%! assert (get_bmp_compression (\"\", [], \"BMP\"), 0);\n%! assert (get_bmp_compression (\"\", [], \"bmp\"), 0);\n%! assert (get_bmp_compression (\".BMP\"), 0);\n%! assert (get_bmp_compression (\".bmp\"), 0);\n%! assert (get_bmp_compression (\".bmp\", [], \"bmp\"), 0);\n%! assert (get_bmp_compression (\"\", gray (256), \"bmp\"), 0);\n%! assert (get_bmp_compression (\".bmp\", gray (256), \"Compression\", \"rle\"), 1);\n"
  },
  {
    "path": "scripts/image/ind2gray.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{I} =} ind2gray (@var{x}, @var{map})\n## Convert a color indexed image to a grayscale intensity image.\n##\n## The image @var{x} must be an indexed image which will be converted using the\n## colormap @var{map}.  Pixels in @var{x} that are outside the colormap are\n## @strong{clipped} to the range of @var{map}.\n##\n## The output @var{I} is of the same class as the input @var{x} and may be\n## one of @code{uint8}, @code{uint16}, @code{single}, or @code{double}.\n##\n## Programming Notes: There are several ways of converting colors to\n## grayscale intensities.  This functions uses the luminance value obtained\n## from @code{rgb2gray} which is @code{I = 0.299*R + 0.587*G + 0.114*B}.\n## Other possibilities include the value component from @code{rgb2hsv} or\n## using a single color channel from @code{ind2rgb}.\n##\n## Index values in @var{x} outside of the number of colors in @var{map} are\n## clipped to the range of @var{map}.  For example, negative indices are\n## clipped to the first color while large values, including exceptional values\n## such as @code{NaN} and @code{Inf}, are clipped to the last color.\n##\n## @seealso{gray2ind, ind2rgb}\n## @end deftypefn\n\nfunction I = ind2gray (x, map)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  [x, map] = ind2x (\"ind2gray\", x, map);\n\n  ## Convert colormap to luminance intensity values\n  map *= [0.29894; 0.58704; 0.11402];\n\n  ## Convert colormap to same class as that of input so that reshape\n  ## will produce output of the same type as the input.\n  cls = class (x);\n  if (isinteger (x))\n    ## if we later add support for int16 images, this will not work.  Look into\n    ## im2int16 from image package for such case\n    map *= intmax (cls);\n  elseif (strcmp (cls, \"single\"))\n    map = single (map);\n  endif\n\n  ## Replace indices in the input matrix with the indexed luminance value.\n  I = reshape (map(x(:)), size (x));\n\nendfunction\n\n\n%!shared i2g\n%! i2g = ind2gray (1:100, gray (100));\n%!\n%!assert (i2g, 0:1/99:1, eps)\n%!assert (gray2ind (i2g, 100), uint8 (0:99))\n\n## Test input validation\n%!error <Invalid call> ind2gray ()\n%!error <Invalid call> ind2gray (1)\n%!error <X must be an indexed image> ind2gray (ones (3,3,3), jet (64))\n%!error <X must be an indexed image> ind2gray (1+i, jet (64))\n%!error <X must be an indexed image> ind2gray (sparse (1), jet (64))\n%!error <X must be an indexed image> ind2gray (1.1, jet (64))\n%!error <X must be an indexed image> ind2rgb (int8 (1), jet (64))\n%!error <X must be an indexed image> ind2gray ({1}, jet (64))\n%!error <MAP must be a valid colormap> ind2gray (1, {1})\n%!warning <contains colors outside of colormap> ind2gray ([-1 1], jet (64));\n%!warning <contains colors outside of colormap> ind2gray ([0 1 2], gray (5));\n%!warning <contains colors outside of colormap> ind2gray ([1 2 6], gray (5));\n%!warning <contains colors outside of colormap> ind2gray ([1 2 NaN], gray (5));\n%!warning <contains colors outside of colormap>\n%! ind2gray (uint8 ([1 2 5]), gray (5));\n"
  },
  {
    "path": "scripts/image/ind2rgb.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{rgb} =} ind2rgb (@var{x}, @var{map})\n## @deftypefnx {} {[@var{R}, @var{G}, @var{B}] =} ind2rgb (@var{x}, @var{map})\n## Convert an indexed image to red, green, and blue color components.\n##\n## The image @var{x} must be an indexed image which will be converted using the\n## colormap @var{map}.  Pixels in @var{x} that are outside the colormap are\n## @strong{clipped} to the range of @var{map}.\n##\n## Multi-dimensional indexed images (of size @nospell{MxNx1xK}) are also\n## supported.\n##\n## The output may be a single RGB image (@nospell{MxNx3} matrix where M and N\n## are the original image @var{x} dimensions, one for each of the red, green\n## and blue channels).  Alternatively, the individual red, green, and blue\n## color matrices of size @nospell{MxN} may be returned.\n##\n## Programming Note: Index values in @var{x} outside of the number of colors\n## in @var{map} are clipped to the range of @var{map}.  For example, negative\n## indices are clipped to the first color while large values, including\n## exceptional values such as @code{NaN} and @code{Inf}, are clipped to the\n## last color.\n## @seealso{rgb2ind, ind2gray, hsv2rgb}\n## @end deftypefn\n\nfunction [R, G, B] = ind2rgb (x, map)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  [x, map] = ind2x (\"ind2rgb\", x, map);\n\n  ## Compute result\n  sz = size (x);\n  R = reshape (map(x(:), 1), sz);\n  G = reshape (map(x(:), 2), sz);\n  B = reshape (map(x(:), 3), sz);\n\n  ## Use ND-array if only one output is requested.\n  if (nargout <= 1)\n    if (ndims (x) == 2)\n      R = reshape ([R(:); G(:); B(:)], [sz, 3]);\n    elseif (ndims (x) == 4)\n      R = permute (reshape ([R(:); G(:); B(:)], [sz(1) sz(2) sz(4) 3]), ...\n                   [1 2 4 3]);\n    else\n      ## We should never reach here since ind2x() should filter them out.\n      error (\"ind2rgb: Unreachable code.  Please report this at bugs.octave.org\");\n    endif\n  endif\n\nendfunction\n\n\n%!shared img, map, ergb, rgb, r, g, b\n%! img = [2 4 5; 3 2 5; 1 2 4];\n%! map = [0.0  0.0  0.0\n%!        0.2  0.4  0.6\n%!        0.4  0.4  0.5\n%!        0.3  0.7  1.0\n%!        0.1  0.5  0.8];\n%! ergb(:,:,1) = [0.2 0.3 0.1; 0.4 0.2 0.1; 0.0 0.2 0.3];\n%! ergb(:,:,2) = [0.4 0.7 0.5; 0.4 0.4 0.5; 0.0 0.4 0.7];\n%! ergb(:,:,3) = [0.6 1.0 0.8; 0.5 0.6 0.8; 0.0 0.6 1.0];\n%! ## test basic usage with 1 and 3 outputs\n%! [rgb] = ind2rgb (img, map);\n%! [r, g, b] = ind2rgb (img, map);\n%!\n%!assert (ergb, rgb)\n%!assert (ergb, reshape ([r(:) g(:) b(:)], [size(img) 3]))\n%!test\n%! ## test correction for integers\n%! img = uint8 (img - 1);\n%! [rgb] = ind2rgb (img, map);\n%! assert (ergb, rgb);\n%!test <*41851>\n%! ## Check that values below lower bound are mapped to first color value\n%! warning (\"off\", \"Octave:ind2rgb:invalid-idx-img\", \"local\");\n%! rgb = ind2rgb ([-1 0 2], gray (64));\n%! assert (rgb(:,1:2,:), zeros (1,2,3));\n%! assert (rgb(:,3,:), 1/63 * ones (1,1,3));\n%!test <*56950>\n%! ## Check that NaN & Inf values mapped to last color value\n%! warning (\"off\", \"Octave:ind2rgb:invalid-idx-img\", \"local\");\n%! rgb = ind2rgb ([NaN, Inf, 3], gray (64));\n%! assert (rgb(:,1:2,:), ones (1,2,3));\n%! assert (rgb(:,3,:), 2/63 * ones (1,1,3));\n\n## We support any unsigned integer type which Matlab does not.\n%!test <*47115>\n%! cmap = repmat (linspace (0, 1, 9)(:), [1 3]);\n%! ind = [0 3 6; 1 4 7; 2 5 8];\n%! rgb = repmat (reshape (linspace (0, 1, 9), [3 3]), [1 1 3]);\n%! assert (ind2rgb (uint8  (ind), cmap), rgb);\n%! assert (ind2rgb (uint16 (ind), cmap), rgb);\n%! assert (ind2rgb (uint32 (ind), cmap), rgb);\n%! assert (ind2rgb (uint64 (ind), cmap), rgb);\n%! fail (\"ind2rgb (int8  (ind), cmap)\", \"X must be an indexed image\")\n%! fail (\"ind2rgb (int16 (ind), cmap)\", \"X must be an indexed image\")\n%! fail (\"ind2rgb (int32 (ind), cmap)\", \"X must be an indexed image\")\n%! fail (\"ind2rgb (int64 (ind), cmap)\", \"X must be an indexed image\")\n%!\n%! cmap(65541,:) = cmap(9,:); # index outside the uint16 range\n%! cmap(9,:) = 0;\n%! ind(3,3) = 65540;\n%! assert (ind2rgb (uint32 (ind), cmap), rgb);\n%! assert (ind2rgb (uint64 (ind), cmap), rgb);\n\n%!test <*59242>\n%! warning (\"off\", \"Octave:ind2rgb:invalid-idx-img\", \"local\");\n%! assert (ind2rgb (uint64 (intmax (\"uint64\")), jet (64)), ...\n%!         reshape ([0.5,0,0], [1,1,3]));\n\n## Test input validation\n%!error <Invalid call> ind2rgb ()\n%!error <Invalid call> ind2rgb (1)\n%!error <X must be an indexed image> ind2rgb (ones (3,3,3), jet (64))\n%!error <X must be an indexed image> ind2rgb (1+i, jet (64))\n%!error <X must be an indexed image> ind2rgb (sparse (1), jet (64))\n%!error <X must be an indexed image> ind2rgb (1.1, jet (64))\n%!error <X must be an indexed image> ind2rgb (int8 (1), jet (64))\n%!error <X must be an indexed image> ind2rgb ({1}, jet (64))\n%!error <MAP must be a valid colormap> ind2rgb (1, {1})\n%!warning <contains colors outside of colormap> ind2rgb ([-1 1], jet (64));\n%!warning <contains colors outside of colormap> ind2rgb ([0 1 2], gray (5));\n%!warning <contains colors outside of colormap> ind2rgb ([1 2 6], gray (5));\n%!warning <contains colors outside of colormap> ind2rgb ([1 2 NaN], gray (5));\n%!warning <contains colors outside of colormap>\n%! ind2rgb (uint8 ([1 2 5]), gray (5));\n"
  },
  {
    "path": "scripts/image/iscolormap.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} iscolormap (@var{cmap})\n## Return true if @var{cmap} is a colormap.\n##\n## A colormap is a real matrix, of class single or double, with 3 columns.\n## Each row represents a single color.  The 3 columns contain red, green,\n## and blue intensities respectively.\n##\n## All values in a colormap should be in the range [0, 1], but this is not\n## enforced.  Each function must decide what to do for values outside this\n## range.\n##\n## @seealso{colormap, rgbplot}\n## @end deftypefn\n\nfunction tf = iscolormap (cmap)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = isfloat (cmap) && isreal (cmap) ...\n       && ismatrix (cmap) && columns (cmap) == 3 && ! isempty (cmap);\n\nendfunction\n\n\n%!assert (iscolormap (jet (64)), true)\n%!assert (iscolormap ({0 1 0}), false)\n%!assert (iscolormap ([0 1i 0]), false)\n%!assert (iscolormap (ones (3,3,3)), false)\n%!assert (iscolormap (ones (3,4)), false)\n%!assert (iscolormap (ones (0,3)), false)\n\n%!error <Invalid call> iscolormap ()\n"
  },
  {
    "path": "scripts/image/jet.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} jet ()\n## @deftypefnx {} {@var{map} =} jet (@var{n})\n## Create color colormap.  This colormap ranges from dark blue through blue,\n## cyan, green, yellow, red, to dark red.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n##\n## Programming Note: The @code{jet} colormap is not perceptually uniform.\n## Try the @code{viridis} colormap if that is important.  For a drop-in\n## replacement for @code{jet} with better perceptual characteristics try\n## the @code{turbo} colormap.\n## @seealso{colormap, turbo}\n## @end deftypefn\n\nfunction map = jet (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"jet: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n  if (n == 1)\n    map = [0, 1, 1];\n  elseif (n == 2)\n    map = [0, 0, 1\n           0, 1, 1];\n  elseif (n > 2)\n    nel = ceil (n/4);           # number of elements\n    idx1 = ceil (3/8 * n) + 1;  # ~3/8*n for large n\n    if (mod (n, 8) == 2)\n      idx1 += 1;\n    endif\n    idx2 = idx1 + nel - 1;      # ~5/8*n for large n\n    idx3 = min (idx2 + nel, n); # ~7/8*n for large n\n\n    r = zeros (n, 1);\n    r(idx1:idx2, 1) = [1:nel] / nel;\n    r(idx2:idx3, 1) = 1;\n    nel2 = n - idx3;\n    r(idx3:(idx3+nel2), 1) = [nel:-1:(nel - nel2)] / nel;\n\n    idx1 = idx1 - nel;          # ~1/8*n for large n\n    idx2 = idx1 + nel - 1;      # ~3/8*n for large n\n    idx3 = min (idx2 + nel, n); # ~5/8*n for large n\n\n    g = zeros (n, 1);\n    g(idx1:idx2, 1) = [1:nel] / nel;\n    g(idx2:idx3, 1) = 1;\n    nel2 = min (nel, n - idx3);\n    g(idx3:(idx3+nel2), 1) = [nel:-1:(nel - nel2)] / nel;\n\n    idx1 = max (idx2 - nel, 1); # ~1/8*n for large n\n    idx2 = idx2;                # ~3/8*n for large n\n    idx3 = idx3;                # ~5/8*n for large n\n\n    b = zeros (n, 1);\n    nel2 = min (nel, idx1-1);\n    b(1:idx1, 1) = [(nel - nel2):nel] / nel;\n    b(idx1:idx2, 1) = 1;\n    nel2 = min (nel, n - idx3);\n    b(idx2:(idx2+nel2), 1) = [nel:-1:(nel - nel2)] / nel;\n\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'jet' colormap profile and as an image\n%! cmap = jet (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (jet ()), [256, 3])\n%!assert (size (jet (16)), [16, 3])\n\n%!assert (jet (1), [0, 1, 1])\n%!assert (jet (true), double ([0, 1, 1]))\n%!assert (jet (char (1)), double ([0, 1, 1]))\n%!assert (jet (int32 (1)), double ([0, 1, 1]))\n%!assert (jet (2), [0, 0, 1; 0, 1, 1])\n\n%!assert (jet (0), zeros (0, 3))\n%!assert (jet (-1), zeros (0, 3))\n\n%!test\n%! a = zeros (15, 3);\n%! a([3:13],2) = [0.25, 0.5, 0.75, 1, 1, 1, 1, 1, 0.75, 0.5, 0.25];\n%! a([7:15], 1) = a([3:11], 2);\n%! a(:,3) = flipud (a(:,1));\n%! assert (jet (15), a, eps);\n\n## Input validation\n%!error <N must be a scalar integer> jet (\"foo\")\n%!error <N must be a scalar integer> jet ([1, 2, 3])\n%!error <N must be a scalar integer> jet ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/lines.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} lines ()\n## @deftypefnx {} {@var{map} =} lines (@var{n})\n## Create color colormap.  This colormap is composed of the list of colors\n## in the current axes @qcode{\"ColorOrder\"} property.  The default is blue,\n## orange, yellow, purple, green, light blue, and dark red.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = lines (n)\n\n  hf = get (groot, \"currentfigure\");\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"lines: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [0, 0, 1];\n  elseif (n > 1)\n    hax = get (hf, \"currentaxes\");\n    if (! isempty (hax))\n      C = get (hax, \"colororder\");\n    else\n      C = get (groot, \"defaultaxescolororder\");\n    endif\n    nr = rows (C);\n    map = C(rem (0:(n-1), nr) + 1, :);\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'lines' colormap profile and as an image\n%! cmap = lines (21); # default has 7 colors, therefore cycle 3 times\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (lines ()), [256, 3])\n%!assert (size (lines (16)), [16, 3])\n\n%!assert (lines (1), [0, 0, 1])\n%!assert (lines (true), double ([0, 0, 1]))\n%!assert (lines (char (1)), double ([0, 0, 1]))\n%!assert (lines (int32 (1)), double ([0, 0, 1]))\n\n%!assert (lines (0), zeros (0, 3))\n%!assert (lines (-1), zeros (0, 3))\n\n%!test\n%! a = get (groot, \"defaultaxescolororder\");\n%! nr = rows (a);\n%! assert (lines (3*nr), [a;a;a]);\n\n## Input validation\n%!error <N must be a scalar integer> lines (\"foo\")\n%!error <N must be a scalar integer> lines ([1, 2, 3])\n%!error <N must be a scalar integer> lines ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__imfinfo__.m \\\n  %reldir%/private/__imread__.m \\\n  %reldir%/private/__imwrite__.m \\\n  %reldir%/private/colorspace_conversion_input_check.m \\\n  %reldir%/private/colorspace_conversion_revert.m \\\n  %reldir%/private/imageIO.m \\\n  %reldir%/private/imwrite_filename.m \\\n  %reldir%/private/ind2x.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/autumn.m \\\n  %reldir%/bone.m \\\n  %reldir%/brighten.m \\\n  %reldir%/cmpermute.m \\\n  %reldir%/cmunique.m \\\n  %reldir%/colorcube.m \\\n  %reldir%/colormap.m \\\n  %reldir%/contrast.m \\\n  %reldir%/cool.m \\\n  %reldir%/copper.m \\\n  %reldir%/cubehelix.m \\\n  %reldir%/dither.m \\\n  %reldir%/flag.m \\\n  %reldir%/frame2im.m \\\n  %reldir%/getframe.m \\\n  %reldir%/gray.m \\\n  %reldir%/gray2ind.m \\\n  %reldir%/hot.m \\\n  %reldir%/hsv.m \\\n  %reldir%/hsv2rgb.m \\\n  %reldir%/im2double.m \\\n  %reldir%/im2frame.m \\\n  %reldir%/image.m \\\n  %reldir%/imagesc.m \\\n  %reldir%/imfinfo.m \\\n  %reldir%/imformats.m \\\n  %reldir%/imread.m \\\n  %reldir%/imshow.m \\\n  %reldir%/imwrite.m \\\n  %reldir%/ind2gray.m \\\n  %reldir%/ind2rgb.m \\\n  %reldir%/iscolormap.m \\\n  %reldir%/jet.m \\\n  %reldir%/lines.m \\\n  %reldir%/movie.m \\\n  %reldir%/ocean.m \\\n  %reldir%/pink.m \\\n  %reldir%/prism.m \\\n  %reldir%/rainbow.m \\\n  %reldir%/rgb2gray.m \\\n  %reldir%/rgb2hsv.m \\\n  %reldir%/rgb2ind.m \\\n  %reldir%/rgbplot.m \\\n  %reldir%/spinmap.m \\\n  %reldir%/spring.m \\\n  %reldir%/summer.m \\\n  %reldir%/turbo.m \\\n  %reldir%/viridis.m \\\n  %reldir%/white.m \\\n  %reldir%/winter.m\n\nSCRIPTS_IMAGES += \\\n  %reldir%/default.img\n\n%canon_reldir%dir = $(fcnfiledir)/image\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/image/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/image/movie.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} movie (@var{mov})\n## @deftypefnx {} {} movie (@var{mov}, @var{n})\n## @deftypefnx {} {} movie (@var{mov}, @var{n}, @var{fps})\n## @deftypefnx {} {} movie (@var{h}, @dots{})\n## Play a movie defined by an array of frame structures.\n##\n## The movie @var{mov} must be a struct array of frames with fields\n## @qcode{\"cdata\"} and @qcode{\"colormap\"}, as returned by the @code{getframe}\n## function.  By default all images are displayed once, at 12 fps, in the\n## current axes.\n##\n## The optional argument @var{n} is a scalar or vector of integers that\n## controls the number of times the movie is displayed and which particular\n## frames are shown:\n##\n## @table @asis\n## @item First element:\n##\n## @table @asis\n## @item @var{n}(1) > 0\n## Play the movie @var{n}(1) times.\n##\n## @item @var{n}(1) < 0\n## Play the movie @code{abs (@var{n}(1)} times alternatively in forward and\n## backward order.\n## @end table\n##\n## @item Other elements (if any):\n## Indices of the frames in @var{mov} that will be displayed.\n## @end table\n##\n## If the first argument is a handle to a figure or axes @var{h}, the movie is\n## played in that figure or axes instead of the current axes.\n##\n## @seealso{getframe, im2frame, frame2im}\n## @end deftypefn\n\nfunction movie (varargin)\n\n  if (nargin == 0 || nargin > 4)\n    print_usage ();\n  endif\n\n  ## Extract possible handle argument\n  hax = [];\n  if (ishghandle (varargin{1}))\n    typ = get (varargin{1}, \"type\");\n    if (strcmp (typ, \"axes\"))\n      hax = varargin{1};\n    elseif (strcmp (typ, \"figure\"))\n      hax = get (varargin{1}, \"currentaxes\");\n      if (isempty (hax))\n        hax = axes (\"parent\", varargin{1});\n      endif\n    else\n      error (\"movie: H must be a handle to an axes or figure\");\n    endif\n    varargin(1) = [];\n    nargin = nargin - 1;\n    if (nargin == 0)\n      print_usage ();\n    endif\n  endif\n\n  ## Extract other arguments\n  n = 1;\n  fps = 12;\n  idx = [];\n\n  mov = varargin{1};\n  if (! isfield (mov, \"cdata\") || ! isfield (mov, \"colormap\"))\n    error (\"movie: MOV must be a frame struct array\");\n  elseif (numel (mov) < 2)\n    error (\"movie: MOV must contain at least two frames\");\n  endif\n\n  if (nargin > 1)\n    n = varargin{2};\n    if (! isindex (abs (n(1))))\n      error (\"movie: N must be a nonzero integer\");\n    endif\n\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      idx = n(2:end)(:)';\n      n = n(1);\n      if (! isindex (idx, numel (mov)))\n        error ([\"movie: All elements N(2:end) must be valid indices \", ...\n                \"into the MOV struct array\"]);\n      endif\n    endif\n\n    if (nargin > 2)\n      fps = varargin{3};\n      if (! (isnumeric (fps) && isscalar (fps) && fps > 0))\n        error (\"movie: FPS must be a numeric scalar > 0\");\n      endif\n    endif\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  ## Build the list of frames to be displayed\n  if (isempty (idx))\n    idx = (1:numel (mov));\n  endif\n\n  if (n > 0)\n    idx = repmat (idx, 1, n);\n  else\n    n = -n;\n    tmp = repmat ([idx fliplr(idx)], 1, fix (n/2));\n    if (fix (n/2) != n/2)\n      idx = [tmp, idx];\n    else\n      idx = tmp;\n    endif\n  endif\n\n  ## Initialize graphics objects\n  if (isempty (mov(1).cdata))\n    error (\"movie: empty image data at frame 1\");\n  endif\n\n  him = findobj (hax, \"-depth\", 1, \"tag\", \"__movie_frame__\");\n  if (isempty (him))\n    him = image (\"parent\", hax, \"cdata\", mov(1).cdata,\n                 \"tag\", \"__movie_frame__\");\n  else\n    set (him, \"cdata\", mov(1).cdata);\n  endif\n\n  set (hax, \"ydir\", \"reverse\", \"visible\", \"off\");\n\n  ## Initialize the timer\n  t = tau = 1/fps;\n  timerid = tic ();\n\n  for ii = idx\n    cdata = mov(ii).cdata;\n    if (isempty (cdata))\n      error (\"movie: empty image data at frame %d\", ii);\n    endif\n    set (him, \"cdata\", cdata);\n\n    if (! isempty (mov(ii).colormap))\n      set (hax, \"colormap\", mov(ii).colormap)\n    endif\n\n    pause (t - toc (timerid));\n    t += tau;\n  endfor\n\nendfunction\n\n\n%!demo\n%! nframes = 20;\n%! colors = jet (nframes);\n%! baseim = ones (20, 20, 3, \"uint8\");\n%! mov(nframes) = struct (\"cdata\", [], \"colormap\", []);\n%! for ii = 1:nframes\n%!   im = baseim * 255;\n%!   im(:,ii,1) = colors(ii,1) * 255;\n%!   im(:,ii,2) = colors(ii,2) * 255;\n%!   im(:,ii,3) = colors(ii,3) * 255;\n%!   mov(ii).cdata = im;\n%! endfor\n%! clf ();\n%! title (\"Play movie forward 2 times\");\n%! movie (mov, 2);\n\n%!demo\n%! nframes = 20;\n%! colors = jet (nframes);\n%! baseim = ones (20, 20, 3, \"uint8\");\n%! mov(nframes) = struct (\"cdata\", [], \"colormap\", []);\n%! for ii = 1:nframes\n%!   im = baseim * 255;\n%!   im(:,ii,1) = colors(ii,1) * 255;\n%!   im(:,ii,2) = colors(ii,2) * 255;\n%!   im(:,ii,3) = colors(ii,3) * 255;\n%!   mov(ii).cdata = im;\n%! endfor\n%! clf ();\n%! title (\"Play movie forward and backward 5 times at 25 fps\");\n%! movie (mov, -5, 25);\n\n%!demo\n%! nframes = 20;\n%! colors = jet (nframes);\n%! baseim = ones (20, 20, 3, \"uint8\");\n%! mov(nframes) = struct (\"cdata\", [], \"colormap\", []);\n%! for ii = 1:nframes\n%!   im = baseim * 255;\n%!   im(:,ii,1) = colors(ii,1) * 255;\n%!   im(:,ii,2) = colors(ii,2) * 255;\n%!   im(:,ii,3) = colors(ii,3) * 255;\n%!   mov(ii).cdata = im;\n%! endfor\n%! clf ();\n%! title (\"Play downsampled movie 5 times\");\n%! movie (mov, [5 1:3:nframes]);\n\n%!demo\n%! clf ();\n%! z = sombrero ();\n%! hs = surf (z);\n%! axis manual\n%! nframes = 50;\n%! mov(nframes) = struct (\"cdata\", [], \"colormap\", []);\n%! for ii = 1:nframes\n%!   set (hs, \"zdata\", z * sin (2*pi*ii/nframes));\n%!   mov(ii) = getframe ();\n%! endfor\n%! clf ();\n%! movie (mov, 3, 25);\n\n## Test input validation\n%!error <Invalid call> movie ()\n%!error <Invalid call> movie (1,2,3,4,5)\n%!error <MOV must be a frame struct array> movie ({2})\n%!error <MOV must contain at least two frames>\n%! movie (struct (\"cdata\", [], \"colormap\", []));\n%!error <N must be a nonzero integer>\n%! movie (struct (\"cdata\", {[], []}, \"colormap\", []), 2.3);\n%!error <N must be a nonzero integer>\n%! movie (struct (\"cdata\", {[], []}, \"colormap\", []), [2.3 -6]);\n%!error <All elements N\\(2:end\\) must be valid indices into the MOV struct>\n%! movie (struct (\"cdata\", {[], []}, \"colormap\", []), [1 -1]);\n%!error <All elements N\\(2:end\\) must be valid indices into the MOV struct>\n%! movie (struct (\"cdata\", {[], []}, \"colormap\", []), [1 5]);\n%!error <FPS must be a numeric scalar . 0>\n%! movie (struct (\"cdata\", {[], []}, \"colormap\", []), 1, \"a\");\n%!error <FPS must be a numeric scalar . 0>\n%! movie (struct (\"cdata\", {[], []}, \"colormap\", []), 1, [1 1]);\n%!error <FPS must be a numeric scalar . 0>\n%! movie (struct (\"cdata\", {[], []}, \"colormap\", []), 1, -1/12);\n%!error <empty image data at frame 1>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   movie (hf, struct (\"cdata\", {[], []}, \"colormap\", []));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n%!error <empty image data at frame 2>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   movie (struct (\"cdata\", {ones(2), []}, \"colormap\", []));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/image/ocean.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} ocean ()\n## @deftypefnx {} {@var{map} =} ocean (@var{n})\n## Create color colormap.  This colormap varies from black to white with shades\n## of blue.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = ocean (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"ocean: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [0, 0, 0];\n  elseif (n > 1)\n    cutin = fix (n/3);\n\n    dr = (n - 1) / cutin;\n    r = prepad ([0:dr:(n-1)], n)';\n\n    dg = (n - 1) / (2 * cutin);\n    g = prepad ([0:dg:(n-1)], n)';\n\n    b = [0:(n-1)]';\n\n    map = [r, g, b] / (n - 1);\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'ocean' colormap profile and as an image\n%! cmap = ocean (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (ocean ()), [256, 3])\n%!assert (size (ocean (16)), [16, 3])\n\n%!assert (ocean (1), [0, 0, 0])\n%!assert (ocean (true), double ([0, 0, 0]))\n%!assert (ocean (char (1)), double ([0, 0, 0]))\n%!assert (ocean (int32 (1)), double ([0, 0, 0]))\n\n%!assert (ocean (0), zeros (0, 3))\n%!assert (ocean (-1), zeros (0, 3))\n\n%!assert (ocean()(1,:), [0, 0, 0])\n%!assert (ocean()(end,:), [1, 1, 1])\n\n%!test\n%! a = zeros (11, 3);\n%! a([9:11],1) = [1/3, 2/3, 1];\n%! a([6:11], 2) = 1/6:1/6:1;\n%! a(:, 3) = 0:.1:1;\n%! assert (ocean (11), a, eps);\n\n## Input validation\n%!error <N must be a scalar integer> ocean (\"foo\")\n%!error <N must be a scalar integer> ocean ([1, 2, 3])\n%!error <N must be a scalar integer> ocean ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/pink.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} pink ()\n## @deftypefnx {} {@var{map} =} pink (@var{n})\n## Create color colormap.  This colormap varies from black to white with\n## shades of gray-pink.\n##\n## This colormap gives a sepia tone when used on grayscale images.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = pink (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"pink: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n  if (n == 1)\n    map = sqrt ([1/3, 1/3, 1/3]);\n  elseif (n == 2)\n    map = sqrt ([1/3, 1/3, 1/6\n                  1    1    1 ]);\n  elseif (n > 2)\n    x = [0:(n-1)]' / (n-1);\n    idx = floor (3/8 * n);\n    base = 1 / (3 * idx);\n\n    nel = idx;   # number of elements\n    r(1:idx,1) = linspace (base, 2/3*x(idx) + 1/3, nel);\n    r(idx+1:n,1) = 2/3*x(idx+1:n) + 1/3;\n\n    g(1:idx,1) = 2/3*x(1:idx);\n    g(idx:2*idx,1) = linspace (2/3*x(idx), 2/3*x(2*idx) + 1/3, nel+1);\n    g(2*idx+1:n,1) = 2/3*x(2*idx+1:n) + 1/3;\n\n    nel = n - 2*idx + 1;\n    b(1:2*idx,1) = 2/3*x(1:2*idx);\n    b(2*idx:n,1) = linspace (2/3*x(2*idx), 1, nel);\n\n    map = sqrt ([r, g, b]);\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'pink' colormap profile and as an image\n%! cmap = pink (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (pink ()), [256, 3])\n%!assert (size (pink (16)), [16, 3])\n\n%!assert (pink (1), sqrt ([1/3, 1/3, 1/3]), eps)\n%!assert (pink (true), double (sqrt ([1/3, 1/3, 1/3])), eps)\n%!assert (pink (char (1)), double (sqrt ([1/3, 1/3, 1/3])), eps)\n%!assert (pink (int32 (1)), double (sqrt ([1/3, 1/3, 1/3])), eps)\n%!assert (pink (2), sqrt ([1/3, 1/3, 1/6; 1, 1, 1]))\n\n%!assert (pink (0), zeros (0, 3))\n%!assert (pink (-1), zeros (0, 3))\n%!assert (pink()(end,:), [1 1 1], eps)\n\n%!test\n%! a = sqrt ([1/3, 0,   0;\n%!            5/9, 5/9, 2/9;\n%!            7/9, 7/9, 11/18;\n%!            1,   1,   1]);\n%! assert (pink (4), a, eps);\n\n## Input validation\n%!error <N must be a scalar integer> pink (\"foo\")\n%!error <N must be a scalar integer> pink ([1, 2, 3])\n%!error <N must be a scalar integer> pink ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/prism.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} prism ()\n## @deftypefnx {} {@var{map} =} prism (@var{n})\n## Create color colormap.  This colormap cycles through red, orange, yellow,\n## green, blue and violet with each index change.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = prism (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"prism: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n  if (n == 1)\n    map = [1 0 0];\n  elseif (n > 1)\n    C = [1, 0, 0; 1, 1/2, 0; 1, 1, 0; 0, 1, 0; 0, 0, 1; 2/3, 0, 1];\n    map = C(rem (0:(n-1), 6) + 1, :);\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'prism' colormap profile and as an image\n%! cmap = prism (18); # 6 colors, therefore cycle 3 times\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (prism ()), [256, 3])\n%!assert (size (prism (16)), [16, 3])\n\n%!assert (prism (1), [1, 0, 0])\n%!assert (prism (true), double ([1, 0, 0]))\n%!assert (prism (char (1)), double ([1, 0, 0]))\n%!assert (prism (int32 (1)), double ([1, 0, 0]))\n\n%!assert (prism (0), zeros (0, 3))\n%!assert (prism (-1), zeros (0, 3))\n\n%!test\n%! a = [1, 0, 0; 1, 1/2, 0; 1, 1, 0; 0, 1, 0; 0, 0, 1; 2/3, 0, 1];\n%! nr = rows (a);\n%! assert (prism (3*nr), [a;a;a]);\n\n## Input validation\n%!error <N must be a scalar integer> prism (\"foo\")\n%!error <N must be a scalar integer> prism ([1, 2, 3])\n%!error <N must be a scalar integer> prism ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/private/__imfinfo__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{info} =} __imfinfo__ (@var{filename})\n##\n## This function does all the work of @code{imfinfo}.\n##\n## It exists here as private function so that @code{imfinfo} can use other\n## functions if @code{imformats} is configured to.  It is also needed so that\n## @code{imformats} can create a function handle for it.\n##\n## @seealso{imfinfo}\n## @end deftypefn\n\nfunction info = __imfinfo__ (filename)\n\n  if (nargin < 1)\n    print_usage (\"imfinfo\");\n  elseif (! ischar (filename))\n    error (\"imfinfo: FILENAME must be a string\");\n  endif\n\n  info = __magick_finfo__ (filename);\n\nendfunction\n"
  },
  {
    "path": "scripts/image/private/__imread__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{img}, @var{map}, @var{alpha}] =} __imread__ (@var{filename})\n## @deftypefnx {} {[@dots{}] =} __imread__ (@var{url})\n## @deftypefnx {} {[@dots{}] =} __imread__ (@dots{}, @var{ext})\n## @deftypefnx {} {[@dots{}] =} __imread__ (@dots{}, @var{idx})\n## @deftypefnx {} {[@dots{}] =} __imread__ (@dots{}, @var{param1}, @var{value1}, @dots{})\n## @deftypefnx {} {@var{info} =} __imread__ (@var{filename})\n##\n## This function does all the work of @code{imread}.\n##\n## It exists here as private function so that @code{imread} can use other\n## functions if @code{imformats} is configured to.  It is also needed so that\n## @code{imformats} can create a function handle for it.\n##\n## @seealso{imread}\n## @end deftypefn\n\nfunction varargout = __imread__ (filename, varargin)\n\n  ## keep track of the varargin offset we're looking at each moment\n  offset = 1;\n\n  ## It is possible for a file with multiple pages to have very different\n  ## images on each page.  Specifically, they may have different sizes.\n  ## Because of this, we need to first find out the index of the images to read\n  ## so we can set up defaults for things such as PixelRegion later on.\n  options = struct (\"index\", 1);  # default image index\n\n  ## Index is the only option that can be defined without the parameter/value\n  ## pair style.  When defined here, the string \"all\" is invalid.\n  ## Also, for Matlab compatibility, if index is defined both as an option here\n  ## and parameter/value pair, silently ignore the first.\n  if (nargin >= 2 && ! ischar (varargin{1}))\n    options.index = varargin{1};\n    if (! is_valid_index_option (options.index))\n      error (\"imread: IDX must be a numeric vector\");\n    endif\n    offset = 2;\n  endif\n\n  if (rem (numel (varargin) - offset + 1, 2) != 0)\n    error (\"imread: PARAM/VALUE arguments must occur in pairs\");\n  endif\n\n  ## Check for Index/Frames argument\n  idx = strcmpi (\"index\", varargin) | strcmpi (\"frames\", varargin);\n  if (any (idx))\n    if (sum (idx) > 1)\n      error (\"imread: Index or Frames may only be specified once\");\n    endif\n    val = varargin{circshift (idx, 1)};\n    if (! is_valid_index_option (val) && ! strcmpi (val, \"all\"))\n      error (\"imread: %s must be a vector or the string 'all'\", varargin{idx});\n    endif\n    options.index = val;\n  endif\n\n  ## Use information from the first image to be read to set defaults.\n  if (strcmpi (options.index, \"all\"))\n    info = __magick_ping__ (filename, 1);\n  else\n    info = __magick_ping__ (filename, options.index(1));\n  endif\n\n  ## Set default for options.\n  options.region = {1:1:info.rows, 1:1:info.columns};\n\n  for idx = offset:2:(numel (varargin) - offset + 1)\n    switch (lower (varargin{idx}))\n\n      case {\"frames\", \"index\"}\n        ## Do nothing.  This option was already processed before the loop.\n\n      case \"pixelregion\"\n        options.region = varargin{idx+1};\n        if (! iscell (options.region) || numel (options.region) != 2)\n          error (\"imread: %s must be a 2-element cell array\",\n                 varargin{idx});\n        endif\n        for reg_idx = 1:2\n          if (numel (options.region{reg_idx}) == 3)\n            ## do nothing\n          elseif (numel (options.region{reg_idx}) == 2)\n            options.region{reg_idx}(3) = options.region{reg_idx}(2);\n            options.region{reg_idx}(2) = 1;\n          else\n            error (\"imread: range for %s must be a 2- or 3-element vector\",\n                   varargin{idx});\n          endif\n          options.region{reg_idx} = floor (options.region{reg_idx}(1)): ...\n                                    floor (options.region{reg_idx}(2)): ...\n                                    floor (options.region{reg_idx}(3));\n        endfor\n        if (options.region{1}(end) > info.rows)\n          error (\"imread: end ROWS for PixelRegions option is larger than image height\");\n        elseif (options.region{2}(end) > info.columns)\n          error (\"imread: end COLS for PixelRegions option is larger than image width\");\n        endif\n\n      case \"info\"\n        ## We ignore this option.  This parameter exists in Matlab to\n        ## speed up the reading of multipage TIFF by passing a structure\n        ## that contains information about the start on the file of each\n        ## page.  We can't control it through GraphicsMagic but at least\n        ## we allow to load multiple pages with one command.\n\n      otherwise\n        error (\"imread: invalid PARAMETER '%s'\", varargin{idx});\n\n    endswitch\n  endfor\n\n  [varargout{1:nargout}] = __magick_read__ (filename, options);\n\nendfunction\n\n## Test if the value passed to the Index or Frames is valid.  This option\n## can be defined in two places, but only in one place can it also be the\n## string \"all\"\nfunction bool = is_valid_index_option (arg)\n  bool = isvector (arg) && isnumeric (arg) && isreal (arg);\nendfunction\n"
  },
  {
    "path": "scripts/image/private/__imwrite__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## This function does all the work of imwrite.  It exists here as private\n## function so that imwrite can use other functions if imformats is\n## configured to.  It is also needed so that imformats can create a\n## function handle for it.\n\nfunction __imwrite__ (img, varargin)\n\n  if (nargin < 2 || ! (isnumeric (img) || islogical (img)))\n    print_usage (\"imwrite\");\n  endif\n\n  [filename, ext, map, param_list] = imwrite_filename (varargin{:});\n\n  if (isempty (img))\n    error (\"imwrite: invalid empty image\");\n  elseif (issparse (img) || issparse (map))\n    error (\"imwrite: sparse images are not supported\");\n  endif\n\n  if (rem (numel (param_list), 2) != 0)\n    error (\"imwrite: no pair for all arguments (odd number left)\");\n  endif\n\n  ## set default for options\n  options = struct (\"writemode\", \"overwrite\",\n                    \"disposalmethod\", {repmat({\"doNotSpecify\"}, 1, size (img, 4))},\n                    \"quality\",   75,\n                    \"delaytime\", ones (1, size (img, 4)) *500, # 0.5 seconds\n                    \"loopcount\", 0, ## this is actually Inf\n                    \"alpha\",     cast ([], class (img)),\n                    \"compression\", \"none\");\n\n  for idx = 1:2:numel (param_list)\n\n    switch (lower (param_list{idx}))\n\n      case \"alpha\"\n        options.alpha = param_list{idx+1};\n        if (! isnumeric (options.alpha))\n          error (\"imwrite: value for %s option must be a numeric matrix\",\n                 param_list{idx});\n        elseif (size (options.alpha, 3) != 1)\n          error (\"imwrite: 3rd dimension of matrix for %s must be singleton\",\n                 param_list{idx});\n        elseif (ndims (options.alpha) > 4\n                || any (size (options.alpha)([1 2]) != size (img)([1 2]))\n                || size (options.alpha, 4) != size (img, 4))\n          error (\"imwrite: matrix for %s must have same dimension as image\",\n                 param_list{idx});\n        endif\n\n      case \"compression\"\n        options.compression = param_list{idx+1};\n        if (! ischar (options.compression))\n          error (\"imwrite: value for %s option must be a string\",\n                 param_list{idx});\n        endif\n        options.compression = lower (options.compression);\n        if (! any (strcmp (options.compression, {\"none\", \"bzip\", \"fax3\", ...\n                                                 \"fax4\", \"jpeg\", \"lzw\", ...\n                                                 \"rle\", \"deflate\"})))\n          error (\"imwrite: invalid compression '%s'\", options.compression);\n        endif\n\n      case \"delaytime\"\n        options.delaytime = param_list{idx+1};\n        if (! isnumeric (options.delaytime))\n          error (\"imwrite: value for %s option must be numeric\",\n                 param_list{idx});\n        endif\n        options.delaytime *= 100; # convert to 1/100ths of second\n        if (isscalar (options.delaytime))\n          options.delaytime(1:size (img, 4)) = options.delaytime;\n        elseif (size (img, 4) != numel (options.delaytime))\n          error (\"imwrite: value for %s must either be a scalar or the number of frames\",\n                 param_list{idx});\n        endif\n        if (any (options.delaytime(:) < 0)\n            || any (options.delaytime(:) > 65535))\n          error (\"imwrite: value for %s must be between 0 and 655.35 seconds\",\n                 param_list{idx});\n        endif\n\n      case \"disposalmethod\"\n        options.disposalmethod = param_list{idx+1};\n        if (! ischar (options.disposalmethod)\n            && ! iscellstr (options.disposalmethod))\n          error (\"imwrite: value for %s must be a string or cell array of strings\",\n                 param_list{idx});\n        elseif (! iscell (options.disposalmethod))\n          options.disposalmethod = {options.disposalmethod};\n        endif\n        options.disposalmethod = lower (options.disposalmethod);\n        matches = ismember (options.disposalmethod,\n                            {\"donotspecify\", \"leaveinplace\", ...\n                             \"restorebg\", \"restoreprevious\"});\n        if (any (! matches))\n          error (\"imwrite: unknown method %s for option %s\",\n                 options.disposalmethod{find (! matches, 1)},\n                 param_list{idx});\n        endif\n        if (isscalar (options.disposalmethod))\n          options.disposalmethod = repmat (options.disposalmethod, ...\n                                           1, size (img, 4));\n        elseif (numel (options.disposalmethod) != size (img, 4))\n          error (\"imwrite: if value %s is a cell array must have same length as number of frames\",\n                 param_list{idx});\n        endif\n\n      case \"loopcount\"\n        options.loopcount = param_list{idx+1};\n        if (! isscalar (options.loopcount) || ! isnumeric (options.loopcount)\n            || (! isinf (options.loopcount)\n                && (options.loopcount < 0 || options.loopcount > 65535)))\n          error (\"imwrite: value for %s must be Inf or between 0 and 65535\",\n                 param_list{idx});\n        endif\n        ## Graphics Magick is a bit weird here.  A value of 0 will be an\n        ## infinite loop, a value of 1, will really be no loop, while a\n        ## value of 2 or more will be that number of loops (checked\n        ## with GNOME image viewer).  This means that there is no way\n        ## to make it loop only once.  See\n        ## https://sourceforge.net/p/graphicsmagick/bugs/249/\n        ## There is also the problem of setting this when there is only\n        ## a single frame.  See\n        ## https://sourceforge.net/p/graphicsmagick/bugs/248/\n        if (isinf (options.loopcount))\n          options.loopcount = 0;\n        elseif (options.loopcount == 0 || options.loopcount == 1)\n          options.loopcount += 1;\n        endif\n        options.loopcount = floor (options.loopcount);\n\n      case \"quality\",\n        options.quality = param_list{idx+1};\n        if (! isnumeric (options.quality) || ! isscalar (options.quality)\n            || options.quality < 0 || options.quality > 100)\n          error (\"imwrite: value for %s option must be a scalar between 0 and 100\",\n                 param_list{idx});\n        endif\n        options.quality = round (options.quality);\n\n      case \"writemode\",\n        options.writemode = param_list{idx+1};\n        if (! ischar (options.writemode)\n            || ! any (strcmpi (options.writemode, {\"append\", \"overwrite\"})))\n          error ('imwrite: value for %s option must be \"append\" or \"overwrite\"',\n                 param_list{idx});\n        endif\n        options.writemode = lower (options.writemode);\n\n      otherwise\n        error (\"imwrite: invalid PARAMETER '%s'\", param_list{idx});\n\n    endswitch\n  endfor\n\n  if (! isempty (map))\n    if (! iscolormap (map))\n      error (\"imwrite: invalid MAP for indexed image\");\n    elseif (ndims (img) != 2 && ndims (img) != 4)\n      error (\"imwrite: indexed image must have 2 or 4 dimensions (found %i)\", ndims (img));\n    endif\n\n    ## Fill in the colormap as required with rgb (0, 0, 0) (bug #33615)\n    nColors = rows (map);\n    if (any (strcmp (class (img), {\"uint8\", \"uint16\", \"logical\"})))\n      required_colors = max (img(:)) +1;\n    else\n      required_colors = max (img(:));\n    endif\n    if (nColors < required_colors)\n      warning (\"imwrite: MAP has not enough colors.  Filling with black\");\n      map(nColors+1:required_colors,:) = 0;\n    endif\n\n    ## If the image is floating point, then we convert it to integer (makes\n    ## it easier in __magick_write__ since it only handles integers.  Also,\n    ## if it's floating point, it has an offset of 1\n    if (isfloat (img))\n      if (rows (map) <= 256)\n        img = uint8 (img - 1);\n      else\n        img = uint16 (img - 1);\n      endif\n    endif\n  endif\n\n  if (ndims (img) > 4)\n    error (\"imwrite: invalid %d-dimensional image data\", ndims (img));\n  elseif (all (size (img, 3) != [1 3 4]))\n    ## 1, 3, or 4 for grayscle, RGB, and CMYK respectively\n    error (\"imwrite: IMG 3rd dimension must be 1, 3, or 4\");\n  endif\n\n  __magick_write__ (filename, ext, img, map, options);\n\nendfunction\n"
  },
  {
    "path": "scripts/image/private/colorspace_conversion_input_check.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Private function the functions that convert between color spaces, i.e.,\n## rgb2ntsc, rgb2hsv, hsv2rgb, and ntsc2rgb.  All of these functions need to\n## handle input in the same way.  The returned flags are meant to be handled\n## by the complementary private function colorspace_conversion_revert()\n\nfunction [in_arg, sz, is_im, is_nd] ...\n            = colorspace_conversion_input_check (fcn, arg_name, in_arg)\n\n  cls = class (in_arg);\n  sz = size (in_arg);\n\n  ## If we have an image convert it into a colormap.\n  if (! iscolormap (in_arg))\n    if (! any (strcmp (cls, {\"uint8\", \"int8\", \"int16\", \"uint16\", ...\n                             \"single\", \"double\"})))\n      error (\"%s: %s of invalid data type '%s'\", fcn, arg_name, cls);\n    elseif (size (in_arg, 3) != 3)\n      error (\"%s: %s must be a colormap or %s image\", fcn, arg_name, arg_name);\n    elseif (! isreal (in_arg) || ! isnumeric (in_arg))\n      error (\"%s: %s must be numeric and real\", fcn, arg_name);\n    endif\n    is_im = true;\n\n    ## For floating point values, R, G and B should be in the [0 1] range,\n    ## otherwise they don't make any sense.  We accept those values\n    ## anyways because we must return something for Matlab compatibility.\n    ## User case is when a function returns an RGB image just slightly outside\n    ## the range due to floating point rounding errors.\n\n    ## Allow for N-D images, i.e., multiple images on the 4th dimension.\n    nd = ndims (in_arg);\n    if (nd == 3)\n      is_nd = false;\n    elseif (nd == 4)\n      is_nd = true;\n      in_arg = permute (in_arg, [1 2 4 3]);\n    elseif (nd > 4)\n      error (\"%s: invalid %s with more than 4 dimensions\", fcn, arg_name);\n    endif\n    in_arg = reshape (in_arg, [numel(in_arg)/3 3]);\n  else\n    is_im = false;\n    is_nd = false;\n  endif\n\n  ## Convert to floating point (remember to leave class single alone)\n  if (isinteger (in_arg))\n    int_max = double (intmax (cls));\n    int_min = double (intmin (cls));\n    if (int_min < 0)\n      in_arg = (double (in_arg) - int_min) / (int_max - int_min);\n    else\n      in_arg = double (in_arg) / int_max;\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/image/private/colorspace_conversion_revert.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{rv} =} colorspace_conversion_revert (@var{rv}, @var{sz}, @var{is_im}, @var{is_nd})\n##\n## Private function that converts between color spaces.\n##\n## This reverts a colormap type into the same shape and class as it was in the\n## input.  The flags are meant to come from complementary private function\n## @code{colorspace_conversion_input_check}.\n## @seealso{hsv2rgb, rgb2grap, rgb2hsv, colorspace_conversion_input_check}\n## @end deftypefn\n\nfunction rv = colorspace_conversion_revert (rv, sz, is_im, is_nd)\n\n  if (is_im)\n    if (is_nd)\n      rv = reshape (rv, [sz(1:2) sz(4) sz(3)]);\n      rv = permute (rv, [1 2 4 3]);\n    else\n      rv = reshape (rv, sz);\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/image/private/imageIO.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{varargout} =} imageIO (@var{fcn}, @var{core_fcn}, @var{fieldname}, @var{filename}, @var{varargin})\n##\n## This function bridges the image input functions @code{imread} and\n## @code{imfinfo} to the functions that will actually be used, based on their\n## format.  See below for the details on how it identifies the format, and what\n## the defaults are.\n##\n## It will change the input arguments that were passed to @code{imread} and\n## @code{imfinfo}.  It will change the filename to provide the absolute\n## filepath for the file, it will extract the possible format name from the\n## rest of the input arguments (in case there was one), and will give an error\n## if the file can't be found.\n##\n## Usage:\n##\n## @table @var\n## @item fcn\n## Function name to use in error message.\n##\n## @item core_fcn\n## Function handle for the default function to use if we can't find the format\n## in imformats.\n##\n## @item fieldname\n## Name of the field in the struct returned by imformats that has the function\n## to use.\n##\n## @item filename\n## Most likely the first input argument from the function that called this.\n## May be missing the file extension which can be on varargin.\n##\n## @item varargin\n## Followed by all the OTHER arguments passed to imread and imfinfo.\n## @end table\n##\n## @seealso{imread, imwrite}\n## @end deftypefn\n\nfunction varargout = imageIO (fcn, core_fcn, fieldname, filename, varargin)\n\n  ## First thing: figure out the filename and possibly download it.\n  ## The first attempt is to try the filename and see if it exists.  If it\n  ## does not, we try to add the next argument since the file extension can\n  ## be given as a separate argument.  If we still can't find the file, it\n  ## can be a URL.  Lastly, if we still didn't found a file, try adding the\n  ## extension to the URL\n\n  file_2_delete = false;  # will we have to remove the file in the end?\n  persistent abs_path = @(x) file_in_path (IMAGE_PATH, tilde_expand (x));\n\n  ## Filename was given with file extension\n  fn = abs_path (filename);\n  if (isempty (fn) && ! isempty (varargin))\n    ## Maybe if we add a file extension?\n    fn = abs_path ([filename \".\" varargin{1}]);\n  endif\n\n  ## Maybe we have a URL\n  if (isempty (fn)\n      && ! isempty (regexp (filename, '^[a-zA-Z][a-zA-Z0-9.+-]+:')))\n    file_2_delete = true; # mark file for deletion\n    [fn, ~] = urlwrite (filename, tempname ());\n    ## Maybe the URL is missing the file extension?\n    if (isempty (fn) && ! isempty (varargin))\n      [fn, ~] = urlwrite ([filename \".\" varargin{1}], tempname ());\n    endif\n  endif\n\n  if (isempty (fn))\n    error ([fcn \": unable to find file '\" filename \"'\"]);\n  endif\n\n  ## unwind_protect block because we may have a file to remove in the end\n  unwind_protect\n\n    ## When guessing the format to use, we first check if the second\n    ## argument is a format defined in imformats.  If so, we remove it\n    ## from the rest of arguments before passing them on.  If not, we\n    ## try to guess the format from the file extension.  Finally, if\n    ## we still don't know the format, we use the Octave core functions\n    ## which is the same for all formats.\n    hfcn = []; # the function we will use\n\n    ## We check if the call to imformats (ext) worked using\n    ## \"numfields (fmt) > 0 because when it fails, the returned\n    ## struct is not considered empty.\n\n    ## try the second input argument\n    if (! isempty (varargin) && ischar (varargin{1}))\n      fmt = imformats (varargin{1});\n      if (numfields (fmt) > 0)\n        hfcn = fmt.(fieldname);\n        varargin(1) = []; # remove format name from arguments\n      endif\n    endif\n\n    ## try extension from filename\n    if (isempty (hfcn))\n      [~, ~, ext] = fileparts (fn);\n      if (! isempty (ext))\n        ## remove dot from extension\n        ext = ext(2:end);\n      endif\n      fmt = imformats (ext);\n      if (numfields (fmt) > 0)\n        hfcn = fmt.(fieldname);\n      endif\n    endif\n\n    ## use the core function\n    if (isempty (hfcn))\n      hfcn = core_fcn;\n    endif\n\n    [varargout{1:nargout}] = hfcn (fn, varargin{:});\n\n  unwind_protect_cleanup\n    if (file_2_delete)\n      unlink (fn);\n    endif\n  end_unwind_protect\n\nendfunction\n"
  },
  {
    "path": "scripts/image/private/imwrite_filename.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[filename, ext, cmap, options] =} imwrite_filename (@var{varargin})\n##\n## The input check for @code{imwrite} needs to be done twice, once when\n## @code{imwrite} is called the first time to find where the filename is, and a\n## second time by @code{__imwrite__} after imformats decides what function to\n## use.  Because a user can, and is encouraged to, get a function handle to\n## @code{__imwrite__}, the input check is also done there.\n##\n## In addition, the input check for @code{imwrite} is not that straightforward\n## in order to support the multiple ways the function can be called, and\n## interpretations of @sc{matlab} documentation.\n##\n## Anyway, this will only do the input check until it finds the filename\n## to be used, the only part that @code{imwrite} actually needs.\n## @seealso{imwrite}\n## @end deftypefn\n\nfunction [filename, ext, cmap, options] = imwrite_filename (varargin)\n\n  ## First, we check if the first argument is a colormap or a filename.\n  cmap = [];\n  if (ischar (varargin{1}))\n    filename_idx = 1;\n  elseif (numel (varargin) >= 2\n          && iscolormap (varargin{1}) && ischar (varargin{2}))\n    filename_idx = 2;\n    cmap = varargin{1};\n  else\n    error (\"imwrite: no FILENAME specified\");\n  endif\n  filename = tilde_expand (varargin{filename_idx});\n\n  ## Next, we get the file extension.\n  ## if we have an odd number of leftover arguments, and the next argument\n  ## is a string, we consider it the file extension.  Otherwise we will\n  ## extract what we can from the previously found filename.\n  options_idx = filename_idx + 1;\n  if (numel (varargin) > filename_idx\n      && rem (length (varargin) - filename_idx, 2) != 0\n      && ischar (varargin{filename_idx + 1}))\n    ext = varargin{filename_idx + 1};\n    options_idx += 1;\n  else\n    [~, ~, ext] = fileparts (filename);\n    if (! isempty (ext))\n      ## remove dot from extension\n      ext = ext(2:end);\n    endif\n  endif\n\n  ## After all the work finding where the filename was, we might as well\n  ## send the leftovers list (they should be in key value pairs)\n  options = varargin(options_idx:end);\n\nendfunction\n"
  },
  {
    "path": "scripts/image/private/ind2x.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[x, map] =} ind2x (@var{caller}, @var{x}, @var{map})\n##\n## Private function for the ind2XXX functions which have a lot of code in\n## common.\n## @end deftypefn\n\nfunction [x, map] = ind2x (caller, x, map)\n\n  ## Check if X is an indexed image.\n  ## An indexed image is defined has having only 2 dimensions, and that's how\n  ## Matlab behaves.  But we want to support N-D images, so we will allow up to\n  ## 4-D and check that the 3rd dimension is a singleton.\n  if (all (ndims (x) != [2 4]) || size (x, 3) != 1\n      || iscomplex (x) || issparse (x))\n    error (\"%s: X must be an indexed image\", caller);\n  endif\n\n  ## Keep track of whether any X values are out-of-bounds.\n  do_warn = false;\n  if (isfloat (x))\n    ## NaN values have to be handled specially.\n    invalid_idx = isnan (x);\n    if (any (invalid_idx(:)))\n      do_warn = true;\n      x(invalid_idx) = Inf;  # Set to Inf which will map to last value of cmap.\n    endif\n  endif\n\n  ## Must follow NaN replacement code above or test for floating point integers\n  ## below will fail because NaN != NaN.\n  if (! (isfloat (x) && all (x(:) == fix (x(:)))\n         || (isinteger (x) && intmin (x) == 0)))\n    error (\"%s: X must be an indexed image\", caller);\n  endif\n\n  ## Check if map is a valid colormap.\n  if (! iscolormap (map))\n    error (\"%s: MAP must be a valid colormap\", caller);\n  endif\n\n  ## Any color indices below the lower bound of the colormap are modified\n  ## to point to the first color in the map (bug #41851).\n  if (isfloat (x))\n    invalid_idx = x < 1;\n    if (any (invalid_idx(:)))\n      do_warn = true;\n      x(invalid_idx) = 1;\n    endif\n  endif\n\n  ## Switch to using 1-based indexing.\n  ## It is possible that an integer storage class may not have enough room\n  ## to make the switch, in which case we convert the data to single.\n  maxidx = max (x(:));\n  is_int = isinteger (x);\n  if (is_int)\n    if (maxidx == intmax (x))\n      x = single (x);\n    endif\n    x += 1;\n  endif\n\n  ## When there are more colors in the image, than there are in the map,\n  ## pad the colormap with the last color in the map for Matlab compatibility.\n  num_colors = rows (map);\n  if (num_colors - is_int < maxidx)\n    do_warn = true;\n    if (numel (x) > maxidx - num_colors + is_int)\n      ## The image is large.  So extend the map.\n      pad = repmat (map(end,:), maxidx - num_colors + is_int, 1);\n      map(end+(1:rows (pad)), :) = pad;\n    else\n      ## The map extension would be large.  So clip the image.\n      x(x > rows (map)) = rows (map);\n    endif\n  endif\n\n  ## Only issue warning once.\n  if (do_warn)\n    warning ([\"Octave:\" caller \":invalid-idx-img\"],\n             [caller \": indexed image contains colors outside of colormap\"]);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/image/rainbow.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} rainbow ()\n## @deftypefnx {} {@var{map} =} rainbow (@var{n})\n## Create color colormap.  This colormap ranges from red through orange,\n## yellow, green, blue, to violet.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\n## this colormap is not part of matlab, it is like the prism\n## colormap map but with a continuous map\n\nfunction map = rainbow (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"rainbow: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [1, 0, 0];\n  elseif (n > 1)\n    x = [0:(n-1)]' / (n - 1);\n\n    r = (  (x < 2/5)\n         + (x >= 2/5 & x < 3/5) .* (-5 * x + 3)\n         + (x >= 4/5) .* (10/3 * x - 8/3));\n\n    g = (  (x < 2/5) .* (5/2 * x)\n         + (x >= 2/5 & x < 3/5)\n         + (x >= 3/5 & x < 4/5) .* (-5 * x + 4));\n\n    b = (  (x >= 3/5 & x < 4/5) .* (5 * x - 3)\n         + (x >= 4/5));\n\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'rainbow' colormap profile and as an image\n%! cmap = rainbow (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n%!assert (size (rainbow ()), [256, 3])\n%!assert (size (rainbow (16)), [16, 3])\n\n%!assert (rainbow (1), [1, 0, 0])\n%!assert (rainbow (true), double ([1, 0, 0]))\n%!assert (rainbow (char (1)), double ([1, 0, 0]))\n%!assert (rainbow (int32 (1)), double ([1, 0, 0]))\n\n%!assert (rainbow (0), zeros (0, 3))\n%!assert (rainbow (-1), zeros (0, 3))\n\n%!assert (rainbow (6)(:), [1, 1, 1, 0, 0, 2/3, 0, 0.5, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1]', 3*eps)\n\n## Input validation\n%!error <N must be a scalar integer> rainbow (\"foo\")\n%!error <N must be a scalar integer> rainbow ([1, 2, 3])\n%!error <N must be a scalar integer> rainbow ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/rgb2gray.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{I} =} rgb2gray (@var{rgb_img})\n## @deftypefnx {} {@var{gray_map} =} rgb2gray (@var{rgb_map})\n## Transform an image or colormap from red-green-blue (RGB) color space to\n## a grayscale intensity image.\n##\n## The input may be of class uint8, int8, uint16, int16, single, or double.\n## The output is of the same class as the input.\n##\n## Implementation Note:\n## The grayscale intensity is calculated as\n##\n## @example\n## @group\n## @var{I} = 0.298936*@var{R} + 0.587043*@var{G} + 0.114021*@var{B}\n## @end group\n## @end example\n##\n## @noindent\n## which corresponds to the luminance channel when RGB is translated to\n## @nospell{YIQ} as documented in @url{https://en.wikipedia.org/wiki/YIQ}.\n## @seealso{rgb2hsv, rgb2ind}\n## @end deftypefn\n\nfunction I = rgb2gray (rgb)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  is_int = isinteger (rgb);\n  if (is_int)\n    cls = class (rgb);\n  endif\n  [rgb, sz, is_im, is_nd] ...\n    = colorspace_conversion_input_check (\"rgb2gray\", \"RGB\", rgb);\n\n  ## Reference matrix for transform from http://en.wikipedia.org/wiki/YIQ.\n  ## Matlab uses this matrix for their conversion with oddly more precision.\n  xform = [0.298936; 0.587043; 0.114021];\n  I = rgb * xform;\n\n  sz(3) = 1; # grayscale images have 3rd dimension of length 1\n  I = colorspace_conversion_revert (I, sz, is_im, is_nd);\n\n  ## Restore integer class if necessary\n  if (is_int)\n    if (cls(end) == \"8\")  # uint8 or int8\n      I *= 255;\n      if (cls(1) == \"i\")  # int8\n        I -= 128;\n      endif\n    else                  # uint16 or int16\n      I *= 65535;\n      if (cls(1) == \"i\")  # int16\n        I -= 32768;\n      endif\n    endif\n    I = feval (cls, I);\n  endif\n\nendfunction\n\n\n## Test pure RED, GREEN, BLUE colors\n%!assert (rgb2gray ([1 0 0]), 0.298936)\n%!assert (rgb2gray ([0 1 0]), 0.587043)\n%!assert (rgb2gray ([0 0 1]), 0.114021)\n\n## test tolerance input checking on floats\n%! assert (rgb2gray ([1.5 1 1]), 1.149468, -1.6e-3);\n\n## Test N-D input\n%!test\n%! rgb = rand (16, 16, 3, 5);\n%! I = zeros (16, 16, 1, 5);\n%! for i = 1:5\n%!   I(:,:,1,i) = rgb2gray (rgb(:,:,:,i));\n%! endfor\n%! assert (rgb2gray (rgb), I, eps);\n\n## Test output class and size for input images.\n## Most of the tests only test for colormap input.\n\n%!test\n%! I = rgb2gray (rand (10, 10, 3));\n%! assert (class (I), \"double\");\n%! assert (size (I), [10 10]);\n\n%!test\n%! I = rgb2gray (rand (10, 10, 3, \"single\"));\n%! assert (class (I), \"single\");\n%! assert (size (I), [10 10]);\n\n%!test\n%! rgb = (rand (10, 10, 3) * 3 ) - 0.5; # values outside range [0 1]\n%! I = rgb2gray (rgb);\n%! assert (class (I), \"double\");\n%! assert (size (I), [10 10]);\n\n%!test\n%! rgb = (rand (10, 10, 3, \"single\") * 3 ) - 0.5; # values outside range [0 1]\n%! I = rgb2gray (rgb);\n%! assert (class (I), \"single\");\n%! assert (size (I), [10 10]);\n\n%!test\n%! I = rgb2gray (randi ([0 255], 10, 10, 3, \"uint8\"));\n%! assert (class (I), \"uint8\");\n%! assert (size (I), [10 10]);\n\n%!test\n%! I = rgb2gray (randi ([0 65535], 10, 10, 3, \"uint16\"));\n%! assert (class (I), \"uint16\");\n%! assert (size (I), [10 10]);\n\n%!test\n%! I = rgb2gray (randi ([-128 127], 10, 10, 3, \"int8\"));\n%! assert (class (I), \"int8\");\n%! assert (size (I), [10 10]);\n\n%!test\n%! I = rgb2gray (randi ([-32768 32767], 10, 10, 3, \"int16\"));\n%! assert (class (I), \"int16\");\n%! assert (size (I), [10 10]);\n\n%!test\n%! rgb_double = reshape ([1 0 0 0 0 1 0 0 0 0 1 0], [2 2 3]);\n%! rgb_uint8  = reshape (uint8 ([255 0 0 0 0 255 0 0 0 0 255 0]),\n%!                       [2 2 3]);\n%! rgb_int16 = int16 (double (rgb_double * uint16 (65535)) - 32768);\n%! expected = [0.298936, 0.114021; 0.587043, 0.0];\n%!\n%! assert (rgb2gray (rgb_double), expected);\n%! assert (rgb2gray (rgb_uint8), uint8 (expected*255));\n%! assert (rgb2gray (single (rgb_double)), single (expected));\n\n## Test input validation\n%!error <Invalid call> rgb2gray ()\n%!error <invalid data type 'cell'> rgb2gray ({1})\n%!error <RGB must be a colormap or RGB image> rgb2gray (ones (2,2))\n"
  },
  {
    "path": "scripts/image/rgb2hsv.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hsv_map} =} rgb2hsv (@var{rgb_map})\n## @deftypefnx {} {@var{hsv_img} =} rgb2hsv (@var{rgb_img})\n## Transform a colormap or image from RGB to HSV color space.\n##\n## A color in the RGB space consists of red, green, and blue intensities.\n##\n## A color in HSV space is represented by hue, saturation and value\n## (brightness) levels in a cylindrical coordinate system.  Hue is the\n## azimuth and describes the dominant color.  Saturation is the radial\n## distance and gives the amount of hue mixed into the color.  Value is\n## the height and is the amount of light in the color.\n##\n## Output class and size will be the same as input.\n##\n## @seealso{hsv2rgb, rgb2ind, rgb2gray}\n## @end deftypefn\n\nfunction hsv = rgb2hsv (rgb)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  [rgb, sz, is_im, is_nd] ...\n    = colorspace_conversion_input_check (\"rgb2hsv\", \"RGB\", rgb);\n\n  ## get the max and min for each row\n  s = min (rgb, [], 2);\n  v = max (rgb, [], 2);\n\n  ## set hue to zero for undefined values (gray has no hue)\n  h = zeros (rows (rgb), 1);\n  notgray = (s != v);\n\n  ## blue hue\n  idx = (v == rgb(:,3) & notgray);\n  if (any (idx))\n    h(idx) = 2/3 + 1/6 * (rgb(idx,1) - rgb(idx,2)) ./ (v(idx) - s(idx));\n  endif\n\n  ## green hue\n  idx = (v == rgb(:,2) & notgray);\n  if (any (idx))\n    h(idx) = 1/3 + 1/6 * (rgb(idx,3) - rgb(idx,1)) ./ (v(idx) - s(idx));\n  endif\n\n  ## red hue\n  idx = (v == rgb(:,1) & notgray);\n  if (any (idx))\n    h(idx) =       1/6 * (rgb(idx,2) - rgb(idx,3)) ./ (v(idx) - s(idx));\n  endif\n  h(h < 0) += 1;   # correct for negative red\n\n  ## set the saturation\n  s(! notgray) = 0;\n  s(notgray) = 1 - s(notgray) ./ v(notgray);\n\n  hsv = [h, s, v];\n  hsv = colorspace_conversion_revert (hsv, sz, is_im, is_nd);\n\nendfunction\n\n\n## Test pure colors and gray\n%!assert (rgb2hsv ([1 0 0]), [0 1 1])\n%!assert (rgb2hsv ([0 1 0]), [1/3 1 1])\n%!assert (rgb2hsv ([0 0 1]), [2/3 1 1])\n%!assert (rgb2hsv ([1 1 0]), [1/6 1 1])\n%!assert (rgb2hsv ([0 1 1]), [1/2 1 1])\n%!assert (rgb2hsv ([1 0 1]), [5/6 1 1])\n%!assert (rgb2hsv ([0.5 0.5 0.5]), [0 0 0.5])\n\n## Test tolarant input checking on floats\n%!assert (rgb2hsv ([1.5 1 1]), [0 1/3 1.5], eps)\n\n%!test\n%! rgb_map = rand (64, 3);\n%! assert (hsv2rgb (rgb2hsv (rgb_map)), rgb_map, 1e-6);\n\n%!test\n%! rgb_img = rand (64, 64, 3);\n%! assert (hsv2rgb (rgb2hsv (rgb_img)), rgb_img, 1e-6);\n\n## support sparse input\n%!assert (rgb2hsv (sparse ([0 0 1])), sparse ([2/3 1 1]))\n%!assert (rgb2hsv (sparse ([0 1 1])), sparse ([1/2 1 1]))\n%!assert (rgb2hsv (sparse ([1 1 1])), sparse ([0 0 1]))\n\n## Test input validation\n%!error <Invalid call> rgb2hsv ()\n%!error <invalid data type 'cell'> rgb2hsv ({1})\n%!error <RGB must be a colormap or RGB image> rgb2hsv (ones (2,2))\n\n## Test N-D input\n%!test\n%! rgb = rand (16, 16, 3, 5);\n%! hsv = zeros (size (rgb));\n%! for i = 1:5\n%!   hsv(:,:,:,i) = rgb2hsv (rgb(:,:,:,i));\n%! endfor\n%! assert (rgb2hsv (rgb), hsv);\n\n## Test output class and size for input images.\n## Most of the tests only test for colormap input.\n\n%!test\n%! hsv = rgb2hsv (rand (10, 10, 3));\n%! assert (class (hsv), \"double\");\n%! assert (size (hsv), [10 10 3]);\n\n%!test\n%! hsv = rgb2hsv (rand (10, 10, 3, \"single\"));\n%! assert (class (hsv), \"single\");\n%! assert (size (hsv), [10 10 3]);\n\n%!test\n%! rgb = (rand (10, 10, 3) * 3 ) - 0.5; # values outside range [0 1]\n%! hsv = rgb2hsv (rgb);\n%! assert (class (hsv), \"double\");\n%! assert (size (hsv), [10 10 3]);\n\n%!test\n%! rgb = (rand (10, 10, 3, \"single\") * 3 ) - 0.5; # values outside range [0 1]\n%! hsv = rgb2hsv (rgb);\n%! assert (class (hsv), \"single\");\n%! assert (size (hsv), [10 10 3]);\n\n%!test\n%! hsv = rgb2hsv (randi ([0 255], 10, 10, 3, \"uint8\"));\n%! assert (class (hsv), \"double\");\n%! assert (size (hsv), [10 10 3]);\n\n%!test\n%! hsv = rgb2hsv (randi ([0 65535], 10, 10, 3, \"uint16\"));\n%! assert (class (hsv), \"double\");\n%! assert (size (hsv), [10 10 3]);\n\n%!test\n%! hsv = rgb2hsv (randi ([-128 127], 10, 10, 3, \"int8\"));\n%! assert (class (hsv), \"double\");\n%! assert (size (hsv), [10 10 3]);\n\n%!test\n%! rgb_double = reshape ([1 0 1 .5 1 1 0 .5 0 1 1 .5], [2 2 3]);\n%! rgb_uint8  = reshape (uint8 ([255 0 255 128 255 255 0 128 0 255 255 128]),\n%!                       [2 2 3]);\n%! rgb_int16 = int16 (double (rgb_double * uint16 (65535)) -32768);\n%! expected = reshape ([1/6 1/2 5/6 0 1 1 1 0 1 1 1 .5], [2 2 3]);\n%!\n%! assert (rgb2hsv (rgb_double), expected);\n%! assert (rgb2hsv (rgb_uint8), expected, 0.005);\n%! assert (rgb2hsv (single (rgb_double)), single (expected));\n"
  },
  {
    "path": "scripts/image/rgb2ind.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{x}, @var{map}] =} rgb2ind (@var{rgb})\n## @deftypefnx {} {[@var{x}, @var{map}] =} rgb2ind (@var{R}, @var{G}, @var{B})\n## Convert an image in red-green-blue (RGB) color space to an indexed image.\n##\n## The input image @var{rgb} can be specified as a single matrix of size\n## @nospell{MxNx3}, or as three separate variables, @var{R}, @var{G}, and\n## @var{B}, its three color channels, red, green, and blue.\n##\n## It outputs an indexed image @var{x} and a colormap @var{map} to interpret\n## an image exactly the same as the input.  No dithering or other form of color\n## quantization is performed.  The output class of the indexed image @var{x}\n## can be uint8, uint16 or double, whichever is required to specify the\n## number of unique colors in the image (which will be equal to the number\n## of rows in @var{map}) in order.\n##\n## Multi-dimensional indexed images (of size @nospell{MxNx3xK}) are also\n## supported, both via a single input (@var{rgb}) or its three color channels\n## as separate variables.\n##\n## @seealso{ind2rgb, rgb2hsv, rgb2gray}\n## @end deftypefn\n\n## FIXME: This function has a very different syntax than the Matlab\n##        one of the same name.\n##        Octave function does not support N, MAP, DITHER, or TOL arguments.\n\nfunction [x, map] = rgb2ind (R, G, B)\n\n  if (nargin != 1 && nargin != 3)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    rgb = R;\n    if (ndims (rgb) > 4 || size (rgb, 3) != 3)\n      error (\"rgb2ind: argument is not an RGB image\");\n    else\n      R = rgb(:,:,1,:);\n      G = rgb(:,:,2,:);\n      B = rgb(:,:,3,:);\n    endif\n  elseif (! size_equal (R, G, B))\n    error (\"rgb2ind: R, G, and B must have the same size\");\n  endif\n\n  x = reshape (1:numel (R), size (R));\n\n  map    = unique ([R(:) G(:) B(:)], \"rows\");\n  [~, x] = ismember ([R(:) G(:) B(:)], map, \"rows\");\n  x      = reshape (x, size (R));\n\n  ## a colormap is of class double and values between 0 and 1\n  switch (class (R))\n    case {\"single\", \"double\", \"logical\"}\n      ## do nothing, return the same\n    case {\"uint8\", \"uint16\"}\n      map = double (map) / double (intmax (R));\n    case \"int16\"\n      map = (double (im) + 32768) / 65535;\n    otherwise\n      error (\"rgb2ind: unsupported image class %s\", im_class);\n  endswitch\n\n  ## we convert to the smallest class necessary to encode the image.  Matlab\n  ## documentation does not mention what it does when uint16 is not enough...\n  ## When an indexed image is of integer class, there's a -1 offset to the\n  ## colormap, hence the adjustment\n  if (rows (map) < 256)\n    x = uint8 (x - 1);\n  elseif (rows (map) < 65536)\n    x = uint16 (x - 1);\n  else\n    ## leave it as double\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> rgb2ind ()\n%!error <Invalid call> rgb2ind (1,2)\n%!error <RGB> rgb2ind (rand (10, 10, 4))\n\n## FIXME: the following tests simply make sure that rgb2ind and ind2rgb\n##        reverse each other.  We should have better tests for this.\n\n## Typical usage\n%!test\n%! rgb = rand (10, 10, 3);\n%! [ind, map] = rgb2ind (rgb);\n%! assert (ind2rgb (ind, map), rgb);\n%!\n%! ## test specifying the RGB channels separated\n%! [ind, map] = rgb2ind (rgb(:,:,1), rgb(:,:,2), rgb(:,:,3));\n%! assert (ind2rgb (ind, map), rgb);\n\n## Test N-dimensional images\n%!test\n%! rgb = rand (10, 10, 3, 10);\n%! [ind, map] = rgb2ind (rgb);\n%! assert (ind2rgb (ind, map), rgb);\n%! [ind, map] = rgb2ind (rgb(:,:,1,:), rgb(:,:,2,:), rgb(:,:,3,:));\n%! assert (ind2rgb (ind, map), rgb);\n\n## Test output class\n%!test\n%! ## this should have more than 65535 unique colors\n%! rgb = nchoosek (0:80, 3) / 80;\n%! nr = rows (rgb);\n%! assert (nr > 65535);\n%! rgb = reshape (rgb, [1, nr, 3]);\n%! [ind, map] = rgb2ind (rgb);\n%! assert (class (ind), \"double\");\n%! assert (class (map), \"double\");\n%!\n%! ## and this should have between 256 and 65535 unique colors\n%! rgb = nchoosek (0:40, 3) / 80;\n%! nr = rows (rgb);\n%! assert (nr >= 256 && nr <= 65535);\n%! rgb = reshape (rgb, [1, nr, 3]);\n%! [ind, map] = rgb2ind (rgb);\n%! assert (class (ind), \"uint16\");\n%! assert (class (map), \"double\");\n%!\n%! ## and this one should have fewer than 256 unique colors\n%! rgb = nchoosek (0:10, 3) / 80;\n%! nr = rows (rgb);\n%! assert (nr < 256);\n%! rgb = reshape (rgb, [1, nr, 3]);\n%! [ind, map] = rgb2ind (rgb);\n%! assert (class (ind), \"uint8\");\n%! assert (class (map), \"double\");\n"
  },
  {
    "path": "scripts/image/rgbplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} rgbplot (@var{cmap})\n## @deftypefnx {} {} rgbplot (@var{cmap}, @var{style})\n## @deftypefnx {} {@var{h} =} rgbplot (@dots{})\n## Plot the components of a colormap.\n##\n## Two different @var{style}s are available for displaying the @var{cmap}:\n##\n## @table @asis\n## @item profile (default)\n## Plot the RGB line profile of the colormap for each of the channels (red,\n## green and blue) with the plot lines colored appropriately.  Each line\n## represents the intensity of an RGB component across the colormap.\n##\n## @item composite\n## Draw the colormap across the X-axis so that the actual index colors are\n## visible rather than the individual color components.\n##\n## @end table\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n##\n## Run @code{demo rgbplot} to see an example of @code{rgbplot} and each style\n## option.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction h = rgbplot (cmap, style = \"profile\")\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! iscolormap (cmap))\n    error (\"rgbplot: CMAP must be a valid colormap\");\n  elseif (! ischar (style))\n    error (\"rgbplot: STYLE must be a string\");\n  endif\n\n  switch (lower (style))\n    case \"profile\"\n      x = 1:rows (cmap);\n      htmp = plot (x,cmap(:,1),\"r\", x,cmap(:,2),\"g\", x,cmap(:,3),\"b\");\n      set (gca, \"ytick\", 0:0.1:1, \"xlim\", [0 rows(cmap)]);\n    case \"composite\"\n      htmp = image (1:rows (cmap));\n      set (gca, \"ytick\", []);\n      colormap (cmap);\n    otherwise\n      error (\"rgbplot: unknown STYLE '%s'\", style);\n  endswitch\n  xlabel (\"color index\");\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! subplot (1, 2, 1);\n%!  rgbplot (ocean, \"profile\");\n%! subplot (1, 2, 2);\n%!  rgbplot (ocean, \"composite\");\n\n## Test input validation\n%!error <Invalid call> rgbplot ()\n%!error <CMAP must be a valid colormap> rgbplot ({0 1 0})\n%!error <STYLE must be a string> rgbplot ([0 1 0], 2)\n%!error <unknown STYLE 'nostyle'> rgbplot ([0 1 0], \"nostyle\")\n"
  },
  {
    "path": "scripts/image/spinmap.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} spinmap ()\n## @deftypefnx {} {} spinmap (@var{t})\n## @deftypefnx {} {} spinmap (@var{t}, @var{inc})\n## @deftypefnx {} {} spinmap (\"inf\")\n## Cycle the colormap for @var{t} seconds with a color increment of @var{inc}.\n##\n## Both parameters are optional.  The default cycle time is 5 seconds and the\n## default increment is 2.  If the option @qcode{\"inf\"} is given then cycle\n## continuously until @kbd{Control-C} is pressed.\n##\n## When rotating, the original color 1 becomes color 2, color 2 becomes\n## color 3, etc.  A positive or negative increment is allowed and a higher\n## value of @var{inc} will cause faster cycling through the colormap.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction spinmap (t = 5, inc = 2)\n\n  if (ischar (t))\n    if (strcmpi (t, \"inf\"))\n      t = Inf;\n    else\n      error ('spinmap: time T must be a real scalar or \"inf\"');\n    endif\n  elseif (! isscalar (t) || ! isreal (t))\n    error (\"spinmap: time T must be a real scalar\");\n  endif\n\n  cmap = cmap_orig = get (gcf (), \"colormap\");\n\n  t0 = clock ();\n  while (etime (clock (), t0) < t)\n    cmap = circshift (cmap, inc, 1);\n    set (gcf (), \"colormap\", cmap);\n    drawnow ();\n  endwhile\n\n  set (gcf (), \"colormap\", cmap_orig);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (rainbow (128));\n%! imagesc (1:8);\n%! axis off;\n%! title (\"Rotate color bars to the right\");\n%! spinmap (3, 1);\n"
  },
  {
    "path": "scripts/image/spring.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} spring ()\n## @deftypefnx {} {@var{map} =} spring (@var{n})\n## Create color colormap.  This colormap varies from magenta to yellow.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = spring (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"spring: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [1, 0, 1];\n  elseif (n > 1)\n    r = ones (n, 1);\n    g = [0:(n-1)]' / (n - 1);\n    b = 1 - g;\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'spring' colormap profile and as an image\n%! cmap = spring (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (spring ()), [256, 3])\n%!assert (size (spring (16)), [16, 3])\n%!assert (all ((spring ()(:, 1)) == 1), true)\n%!assert (spring (11)(:,2:3), [[0:0.1:1]; [1:-0.1:0]]', eps)\n\n%!assert (spring (1), [1, 0, 1])\n%!assert (spring (true), double ([1, 0, 1]))\n%!assert (spring (char (1)), double ([1, 0, 1]))\n%!assert (spring (int32 (1)), double ([1, 0, 1]))\n\n%!assert (spring (0), zeros (0, 3))\n%!assert (spring (-1), zeros (0, 3))\n\n## Input validation\n%!error <N must be a scalar integer> spring (\"foo\")\n%!error <N must be a scalar integer> spring ([1, 2, 3])\n%!error <N must be a scalar integer> spring ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/summer.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} summer ()\n## @deftypefnx {} {@var{map} =} summer (@var{n})\n## Create color colormap.  This colormap varies from green to yellow.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = summer (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"summer: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [0, 0.5, 0.4];\n  elseif (n > 1)\n    r = [0:(n-1)]' / (n - 1);\n    g = 0.5 + r / 2;\n    b = 0.4 * ones (n, 1);\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'summer' colormap profile and as an image\n%! cmap = summer (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (summer ()), [256, 3])\n%!assert (size (summer (16)), [16, 3])\n\n%!assert (summer (1), [0, 0.5, 0.4])\n%!assert (summer (true), double ([0, 0.5, 0.4]))\n%!assert (summer (char (1)), double ([0, 0.5, 0.4]))\n%!assert (summer (int32 (1)), double ([0, 0.5, 0.4]))\n\n%!assert (summer (0), zeros (0, 3))\n%!assert (summer (-1), zeros (0, 3))\n\n%!assert (summer (11), [[0:0.1:1]; [0.5:0.05:1]; 0.4 * ones(1,11)]', eps)\n\n## Input validation\n%!error <N must be a scalar integer> summer (\"foo\")\n%!error <N must be a scalar integer> summer ([1, 2, 3])\n%!error <N must be a scalar integer> summer ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/turbo.m",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} turbo ()\n## @deftypefnx {} {@var{map} =} turbo (@var{n})\n## Create color colormap.  This colormap ranges from dark blue through green\n## to dark red; similar to the outdated @code{jet} colormap but perceptually\n## uniform.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\n## This is a port to Octave of the Google LLC colormap \"turbo\"\n## by Anton Mikhailov.  The original file is distributed under Apache-2.0:\n## https://opensource.org/licenses/Apache-2.0\n\nfunction map = turbo (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"turbo: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  persistent turbo_lut = [0.18995, 0.07176, 0.23217;\n                          0.19483, 0.08339, 0.26149;\n                          0.19956, 0.09498, 0.29024;\n                          0.20415, 0.10652, 0.31844;\n                          0.20860, 0.11802, 0.34607;\n                          0.21291, 0.12947, 0.37314;\n                          0.21708, 0.14087, 0.39964;\n                          0.22111, 0.15223, 0.42558;\n                          0.22500, 0.16354, 0.45096;\n                          0.22875, 0.17481, 0.47578;\n                          0.23236, 0.18603, 0.50004;\n                          0.23582, 0.19720, 0.52373;\n                          0.23915, 0.20833, 0.54686;\n                          0.24234, 0.21941, 0.56942;\n                          0.24539, 0.23044, 0.59142;\n                          0.24830, 0.24143, 0.61286;\n                          0.25107, 0.25237, 0.63374;\n                          0.25369, 0.26327, 0.65406;\n                          0.25618, 0.27412, 0.67381;\n                          0.25853, 0.28492, 0.69300;\n                          0.26074, 0.29568, 0.71162;\n                          0.26280, 0.30639, 0.72968;\n                          0.26473, 0.31706, 0.74718;\n                          0.26652, 0.32768, 0.76412;\n                          0.26816, 0.33825, 0.78050;\n                          0.26967, 0.34878, 0.79631;\n                          0.27103, 0.35926, 0.81156;\n                          0.27226, 0.36970, 0.82624;\n                          0.27334, 0.38008, 0.84037;\n                          0.27429, 0.39043, 0.85393;\n                          0.27509, 0.40072, 0.86692;\n                          0.27576, 0.41097, 0.87936;\n                          0.27628, 0.42118, 0.89123;\n                          0.27667, 0.43134, 0.90254;\n                          0.27691, 0.44145, 0.91328;\n                          0.27701, 0.45152, 0.92347;\n                          0.27698, 0.46153, 0.93309;\n                          0.27680, 0.47151, 0.94214;\n                          0.27648, 0.48144, 0.95064;\n                          0.27603, 0.49132, 0.95857;\n                          0.27543, 0.50115, 0.96594;\n                          0.27469, 0.51094, 0.97275;\n                          0.27381, 0.52069, 0.97899;\n                          0.27273, 0.53040, 0.98461;\n                          0.27106, 0.54015, 0.98930;\n                          0.26878, 0.54995, 0.99303;\n                          0.26592, 0.55979, 0.99583;\n                          0.26252, 0.56967, 0.99773;\n                          0.25862, 0.57958, 0.99876;\n                          0.25425, 0.58950, 0.99896;\n                          0.24946, 0.59943, 0.99835;\n                          0.24427, 0.60937, 0.99697;\n                          0.23874, 0.61931, 0.99485;\n                          0.23288, 0.62923, 0.99202;\n                          0.22676, 0.63913, 0.98851;\n                          0.22039, 0.64901, 0.98436;\n                          0.21382, 0.65886, 0.97959;\n                          0.20708, 0.66866, 0.97423;\n                          0.20021, 0.67842, 0.96833;\n                          0.19326, 0.68812, 0.96190;\n                          0.18625, 0.69775, 0.95498;\n                          0.17923, 0.70732, 0.94761;\n                          0.17223, 0.71680, 0.93981;\n                          0.16529, 0.72620, 0.93161;\n                          0.15844, 0.73551, 0.92305;\n                          0.15173, 0.74472, 0.91416;\n                          0.14519, 0.75381, 0.90496;\n                          0.13886, 0.76279, 0.89550;\n                          0.13278, 0.77165, 0.88580;\n                          0.12698, 0.78037, 0.87590;\n                          0.12151, 0.78896, 0.86581;\n                          0.11639, 0.79740, 0.85559;\n                          0.11167, 0.80569, 0.84525;\n                          0.10738, 0.81381, 0.83484;\n                          0.10357, 0.82177, 0.82437;\n                          0.10026, 0.82955, 0.81389;\n                          0.09750, 0.83714, 0.80342;\n                          0.09532, 0.84455, 0.79299;\n                          0.09377, 0.85175, 0.78264;\n                          0.09287, 0.85875, 0.77240;\n                          0.09267, 0.86554, 0.76230;\n                          0.09320, 0.87211, 0.75237;\n                          0.09451, 0.87844, 0.74265;\n                          0.09662, 0.88454, 0.73316;\n                          0.09958, 0.89040, 0.72393;\n                          0.10342, 0.89600, 0.71500;\n                          0.10815, 0.90142, 0.70599;\n                          0.11374, 0.90673, 0.69651;\n                          0.12014, 0.91193, 0.68660;\n                          0.12733, 0.91701, 0.67627;\n                          0.13526, 0.92197, 0.66556;\n                          0.14391, 0.92680, 0.65448;\n                          0.15323, 0.93151, 0.64308;\n                          0.16319, 0.93609, 0.63137;\n                          0.17377, 0.94053, 0.61938;\n                          0.18491, 0.94484, 0.60713;\n                          0.19659, 0.94901, 0.59466;\n                          0.20877, 0.95304, 0.58199;\n                          0.22142, 0.95692, 0.56914;\n                          0.23449, 0.96065, 0.55614;\n                          0.24797, 0.96423, 0.54303;\n                          0.26180, 0.96765, 0.52981;\n                          0.27597, 0.97092, 0.51653;\n                          0.29042, 0.97403, 0.50321;\n                          0.30513, 0.97697, 0.48987;\n                          0.32006, 0.97974, 0.47654;\n                          0.33517, 0.98234, 0.46325;\n                          0.35043, 0.98477, 0.45002;\n                          0.36581, 0.98702, 0.43688;\n                          0.38127, 0.98909, 0.42386;\n                          0.39678, 0.99098, 0.41098;\n                          0.41229, 0.99268, 0.39826;\n                          0.42778, 0.99419, 0.38575;\n                          0.44321, 0.99551, 0.37345;\n                          0.45854, 0.99663, 0.36140;\n                          0.47375, 0.99755, 0.34963;\n                          0.48879, 0.99828, 0.33816;\n                          0.50362, 0.99879, 0.32701;\n                          0.51822, 0.99910, 0.31622;\n                          0.53255, 0.99919, 0.30581;\n                          0.54658, 0.99907, 0.29581;\n                          0.56026, 0.99873, 0.28623;\n                          0.57357, 0.99817, 0.27712;\n                          0.58646, 0.99739, 0.26849;\n                          0.59891, 0.99638, 0.26038;\n                          0.61088, 0.99514, 0.25280;\n                          0.62233, 0.99366, 0.24579;\n                          0.63323, 0.99195, 0.23937;\n                          0.64362, 0.98999, 0.23356;\n                          0.65394, 0.98775, 0.22835;\n                          0.66428, 0.98524, 0.22370;\n                          0.67462, 0.98246, 0.21960;\n                          0.68494, 0.97941, 0.21602;\n                          0.69525, 0.97610, 0.21294;\n                          0.70553, 0.97255, 0.21032;\n                          0.71577, 0.96875, 0.20815;\n                          0.72596, 0.96470, 0.20640;\n                          0.73610, 0.96043, 0.20504;\n                          0.74617, 0.95593, 0.20406;\n                          0.75617, 0.95121, 0.20343;\n                          0.76608, 0.94627, 0.20311;\n                          0.77591, 0.94113, 0.20310;\n                          0.78563, 0.93579, 0.20336;\n                          0.79524, 0.93025, 0.20386;\n                          0.80473, 0.92452, 0.20459;\n                          0.81410, 0.91861, 0.20552;\n                          0.82333, 0.91253, 0.20663;\n                          0.83241, 0.90627, 0.20788;\n                          0.84133, 0.89986, 0.20926;\n                          0.85010, 0.89328, 0.21074;\n                          0.85868, 0.88655, 0.21230;\n                          0.86709, 0.87968, 0.21391;\n                          0.87530, 0.87267, 0.21555;\n                          0.88331, 0.86553, 0.21719;\n                          0.89112, 0.85826, 0.21880;\n                          0.89870, 0.85087, 0.22038;\n                          0.90605, 0.84337, 0.22188;\n                          0.91317, 0.83576, 0.22328;\n                          0.92004, 0.82806, 0.22456;\n                          0.92666, 0.82025, 0.22570;\n                          0.93301, 0.81236, 0.22667;\n                          0.93909, 0.80439, 0.22744;\n                          0.94489, 0.79634, 0.22800;\n                          0.95039, 0.78823, 0.22831;\n                          0.95560, 0.78005, 0.22836;\n                          0.96049, 0.77181, 0.22811;\n                          0.96507, 0.76352, 0.22754;\n                          0.96931, 0.75519, 0.22663;\n                          0.97323, 0.74682, 0.22536;\n                          0.97679, 0.73842, 0.22369;\n                          0.98000, 0.73000, 0.22161;\n                          0.98289, 0.72140, 0.21918;\n                          0.98549, 0.71250, 0.21650;\n                          0.98781, 0.70330, 0.21358;\n                          0.98986, 0.69382, 0.21043;\n                          0.99163, 0.68408, 0.20706;\n                          0.99314, 0.67408, 0.20348;\n                          0.99438, 0.66386, 0.19971;\n                          0.99535, 0.65341, 0.19577;\n                          0.99607, 0.64277, 0.19165;\n                          0.99654, 0.63193, 0.18738;\n                          0.99675, 0.62093, 0.18297;\n                          0.99672, 0.60977, 0.17842;\n                          0.99644, 0.59846, 0.17376;\n                          0.99593, 0.58703, 0.16899;\n                          0.99517, 0.57549, 0.16412;\n                          0.99419, 0.56386, 0.15918;\n                          0.99297, 0.55214, 0.15417;\n                          0.99153, 0.54036, 0.14910;\n                          0.98987, 0.52854, 0.14398;\n                          0.98799, 0.51667, 0.13883;\n                          0.98590, 0.50479, 0.13367;\n                          0.98360, 0.49291, 0.12849;\n                          0.98108, 0.48104, 0.12332;\n                          0.97837, 0.46920, 0.11817;\n                          0.97545, 0.45740, 0.11305;\n                          0.97234, 0.44565, 0.10797;\n                          0.96904, 0.43399, 0.10294;\n                          0.96555, 0.42241, 0.09798;\n                          0.96187, 0.41093, 0.09310;\n                          0.95801, 0.39958, 0.08831;\n                          0.95398, 0.38836, 0.08362;\n                          0.94977, 0.37729, 0.07905;\n                          0.94538, 0.36638, 0.07461;\n                          0.94084, 0.35566, 0.07031;\n                          0.93612, 0.34513, 0.06616;\n                          0.93125, 0.33482, 0.06218;\n                          0.92623, 0.32473, 0.05837;\n                          0.92105, 0.31489, 0.05475;\n                          0.91572, 0.30530, 0.05134;\n                          0.91024, 0.29599, 0.04814;\n                          0.90463, 0.28696, 0.04516;\n                          0.89888, 0.27824, 0.04243;\n                          0.89298, 0.26981, 0.03993;\n                          0.88691, 0.26152, 0.03753;\n                          0.88066, 0.25334, 0.03521;\n                          0.87422, 0.24526, 0.03297;\n                          0.86760, 0.23730, 0.03082;\n                          0.86079, 0.22945, 0.02875;\n                          0.85380, 0.22170, 0.02677;\n                          0.84662, 0.21407, 0.02487;\n                          0.83926, 0.20654, 0.02305;\n                          0.83172, 0.19912, 0.02131;\n                          0.82399, 0.19182, 0.01966;\n                          0.81608, 0.18462, 0.01809;\n                          0.80799, 0.17753, 0.01660;\n                          0.79971, 0.17055, 0.01520;\n                          0.79125, 0.16368, 0.01387;\n                          0.78260, 0.15693, 0.01264;\n                          0.77377, 0.15028, 0.01148;\n                          0.76476, 0.14374, 0.01041;\n                          0.75556, 0.13731, 0.00942;\n                          0.74617, 0.13098, 0.00851;\n                          0.73661, 0.12477, 0.00769;\n                          0.72686, 0.11867, 0.00695;\n                          0.71692, 0.11268, 0.00629;\n                          0.70680, 0.10680, 0.00571;\n                          0.69650, 0.10102, 0.00522;\n                          0.68602, 0.09536, 0.00481;\n                          0.67535, 0.08980, 0.00449;\n                          0.66449, 0.08436, 0.00424;\n                          0.65345, 0.07902, 0.00408;\n                          0.64223, 0.07380, 0.00401;\n                          0.63082, 0.06868, 0.00401;\n                          0.61923, 0.06367, 0.00410;\n                          0.60746, 0.05878, 0.00427;\n                          0.59550, 0.05399, 0.00453;\n                          0.58336, 0.04931, 0.00486;\n                          0.57103, 0.04474, 0.00529;\n                          0.55852, 0.04028, 0.00579;\n                          0.54583, 0.03593, 0.00638;\n                          0.53295, 0.03169, 0.00705;\n                          0.51989, 0.02756, 0.00780;\n                          0.50664, 0.02354, 0.00863;\n                          0.49321, 0.01963, 0.00955;\n                          0.47960, 0.01583, 0.01055];\n\n  p = rows (turbo_lut);\n  map = interp1 (1:p, turbo_lut, linspace (1, p, n), \"linear\");\n\nendfunction\n\n\n%!demo\n%! ## Show the 'turbo' colormap profile and as an image\n%! cmap = turbo (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (turbo ()), [256, 3])\n%!assert (size (turbo (16)), [16, 3])\n\n%!assert (turbo(0), zeros (0, 3))\n%!assert (turbo(-1), zeros (0, 3))\n\n%!shared a\n%! a = [0.18995, 0.07176, 0.23217;\n%!      0.10342, 0.89600, 0.71500;\n%!      0.98000, 0.73000, 0.22161;\n%!      0.47960, 0.01583, 0.01055];\n\n%!assert (turbo (1), a(4,:))\n%!assert (turbo (true), double (a(4,:)))\n%!assert (turbo (char (1)), double (a(4,:)))\n%!assert (turbo (int32 (1)), double (a(4,:)))\n%!assert (turbo (4), a, eps)\n\n%!shared  # Clear shared varibles to avoid echo on unrelated test errors.\n\n## Input validation\n%!error <N must be a scalar integer> turbo (\"foo\")\n%!error <N must be a scalar integer> turbo ([1, 2, 3])\n%!error <N must be a scalar integer> turbo ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/viridis.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} viridis ()\n## @deftypefnx {} {@var{map} =} viridis (@var{n})\n## Create color colormap.  This colormap ranges from dark purplish-blue through\n## blue, green, to yellow.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\n## This is a port to Octave of the default matplotlib colormap \"viridis\"\n## by Eric Firing.  The original file is distributed under CC0:\n## http://creativecommons.org/publicdomain/zero/1.0\n\nfunction map = viridis (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"viridis: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  ## FIXME: Is there no algorithmic definition of the viridis colormap?\n  persistent viridi = [0.26700401  0.00487433  0.32941519\n                       0.26851048  0.00960483  0.33542652\n                       0.26994384  0.01462494  0.34137895\n                       0.27130489  0.01994186  0.34726862\n                       0.27259384  0.02556309  0.35309303\n                       0.27380934  0.03149748  0.35885256\n                       0.27495242  0.03775181  0.36454323\n                       0.27602238  0.04416723  0.37016418\n                       0.2770184   0.05034437  0.37571452\n                       0.27794143  0.05632444  0.38119074\n                       0.27879067  0.06214536  0.38659204\n                       0.2795655   0.06783587  0.39191723\n                       0.28026658  0.07341724  0.39716349\n                       0.28089358  0.07890703  0.40232944\n                       0.28144581  0.0843197   0.40741404\n                       0.28192358  0.08966622  0.41241521\n                       0.28232739  0.09495545  0.41733086\n                       0.28265633  0.10019576  0.42216032\n                       0.28291049  0.10539345  0.42690202\n                       0.28309095  0.11055307  0.43155375\n                       0.28319704  0.11567966  0.43611482\n                       0.28322882  0.12077701  0.44058404\n                       0.28318684  0.12584799  0.44496\n                       0.283072    0.13089477  0.44924127\n                       0.28288389  0.13592005  0.45342734\n                       0.28262297  0.14092556  0.45751726\n                       0.28229037  0.14591233  0.46150995\n                       0.28188676  0.15088147  0.46540474\n                       0.28141228  0.15583425  0.46920128\n                       0.28086773  0.16077132  0.47289909\n                       0.28025468  0.16569272  0.47649762\n                       0.27957399  0.17059884  0.47999675\n                       0.27882618  0.1754902   0.48339654\n                       0.27801236  0.18036684  0.48669702\n                       0.27713437  0.18522836  0.48989831\n                       0.27619376  0.19007447  0.49300074\n                       0.27519116  0.1949054   0.49600488\n                       0.27412802  0.19972086  0.49891131\n                       0.27300596  0.20452049  0.50172076\n                       0.27182812  0.20930306  0.50443413\n                       0.27059473  0.21406899  0.50705243\n                       0.26930756  0.21881782  0.50957678\n                       0.26796846  0.22354911  0.5120084\n                       0.26657984  0.2282621   0.5143487\n                       0.2651445   0.23295593  0.5165993\n                       0.2636632   0.23763078  0.51876163\n                       0.26213801  0.24228619  0.52083736\n                       0.26057103  0.2469217   0.52282822\n                       0.25896451  0.25153685  0.52473609\n                       0.25732244  0.2561304   0.52656332\n                       0.25564519  0.26070284  0.52831152\n                       0.25393498  0.26525384  0.52998273\n                       0.25219404  0.26978306  0.53157905\n                       0.25042462  0.27429024  0.53310261\n                       0.24862899  0.27877509  0.53455561\n                       0.2468114   0.28323662  0.53594093\n                       0.24497208  0.28767547  0.53726018\n                       0.24311324  0.29209154  0.53851561\n                       0.24123708  0.29648471  0.53970946\n                       0.23934575  0.30085494  0.54084398\n                       0.23744138  0.30520222  0.5419214\n                       0.23552606  0.30952657  0.54294396\n                       0.23360277  0.31382773  0.54391424\n                       0.2316735   0.3181058   0.54483444\n                       0.22973926  0.32236127  0.54570633\n                       0.22780192  0.32659432  0.546532\n                       0.2258633   0.33080515  0.54731353\n                       0.22392515  0.334994    0.54805291\n                       0.22198915  0.33916114  0.54875211\n                       0.22005691  0.34330688  0.54941304\n                       0.21812995  0.34743154  0.55003755\n                       0.21620971  0.35153548  0.55062743\n                       0.21429757  0.35561907  0.5511844\n                       0.21239477  0.35968273  0.55171011\n                       0.2105031   0.36372671  0.55220646\n                       0.20862342  0.36775151  0.55267486\n                       0.20675628  0.37175775  0.55311653\n                       0.20490257  0.37574589  0.55353282\n                       0.20306309  0.37971644  0.55392505\n                       0.20123854  0.38366989  0.55429441\n                       0.1994295   0.38760678  0.55464205\n                       0.1976365   0.39152762  0.55496905\n                       0.19585993  0.39543297  0.55527637\n                       0.19410009  0.39932336  0.55556494\n                       0.19235719  0.40319934  0.55583559\n                       0.19063135  0.40706148  0.55608907\n                       0.18892259  0.41091033  0.55632606\n                       0.18723083  0.41474645  0.55654717\n                       0.18555593  0.4185704   0.55675292\n                       0.18389763  0.42238275  0.55694377\n                       0.18225561  0.42618405  0.5571201\n                       0.18062949  0.42997486  0.55728221\n                       0.17901879  0.43375572  0.55743035\n                       0.17742298  0.4375272   0.55756466\n                       0.17584148  0.44128981  0.55768526\n                       0.17427363  0.4450441   0.55779216\n                       0.17271876  0.4487906   0.55788532\n                       0.17117615  0.4525298   0.55796464\n                       0.16964573  0.45626209  0.55803034\n                       0.16812641  0.45998802  0.55808199\n                       0.1666171   0.46370813  0.55811913\n                       0.16511703  0.4674229   0.55814141\n                       0.16362543  0.47113278  0.55814842\n                       0.16214155  0.47483821  0.55813967\n                       0.16066467  0.47853961  0.55811466\n                       0.15919413  0.4822374   0.5580728\n                       0.15772933  0.48593197  0.55801347\n                       0.15626973  0.4896237   0.557936\n                       0.15481488  0.49331293  0.55783967\n                       0.15336445  0.49700003  0.55772371\n                       0.1519182   0.50068529  0.55758733\n                       0.15047605  0.50436904  0.55742968\n                       0.14903918  0.50805136  0.5572505\n                       0.14760731  0.51173263  0.55704861\n                       0.14618026  0.51541316  0.55682271\n                       0.14475863  0.51909319  0.55657181\n                       0.14334327  0.52277292  0.55629491\n                       0.14193527  0.52645254  0.55599097\n                       0.14053599  0.53013219  0.55565893\n                       0.13914708  0.53381201  0.55529773\n                       0.13777048  0.53749213  0.55490625\n                       0.1364085   0.54117264  0.55448339\n                       0.13506561  0.54485335  0.55402906\n                       0.13374299  0.54853458  0.55354108\n                       0.13244401  0.55221637  0.55301828\n                       0.13117249  0.55589872  0.55245948\n                       0.1299327   0.55958162  0.55186354\n                       0.12872938  0.56326503  0.55122927\n                       0.12756771  0.56694891  0.55055551\n                       0.12645338  0.57063316  0.5498411\n                       0.12539383  0.57431754  0.54908564\n                       0.12439474  0.57800205  0.5482874\n                       0.12346281  0.58168661  0.54744498\n                       0.12260562  0.58537105  0.54655722\n                       0.12183122  0.58905521  0.54562298\n                       0.12114807  0.59273889  0.54464114\n                       0.12056501  0.59642187  0.54361058\n                       0.12009154  0.60010387  0.54253043\n                       0.11973756  0.60378459  0.54139999\n                       0.11951163  0.60746388  0.54021751\n                       0.11942341  0.61114146  0.53898192\n                       0.11948255  0.61481702  0.53769219\n                       0.11969858  0.61849025  0.53634733\n                       0.12008079  0.62216081  0.53494633\n                       0.12063824  0.62582833  0.53348834\n                       0.12137972  0.62949242  0.53197275\n                       0.12231244  0.63315277  0.53039808\n                       0.12344358  0.63680899  0.52876343\n                       0.12477953  0.64046069  0.52706792\n                       0.12632581  0.64410744  0.52531069\n                       0.12808703  0.64774881  0.52349092\n                       0.13006688  0.65138436  0.52160791\n                       0.13226797  0.65501363  0.51966086\n                       0.13469183  0.65863619  0.5176488\n                       0.13733921  0.66225157  0.51557101\n                       0.14020991  0.66585927  0.5134268\n                       0.14330291  0.66945881  0.51121549\n                       0.1466164   0.67304968  0.50893644\n                       0.15014782  0.67663139  0.5065889\n                       0.15389405  0.68020343  0.50417217\n                       0.15785146  0.68376525  0.50168574\n                       0.16201598  0.68731632  0.49912906\n                       0.1663832   0.69085611  0.49650163\n                       0.1709484   0.69438405  0.49380294\n                       0.17570671  0.6978996   0.49103252\n                       0.18065314  0.70140222  0.48818938\n                       0.18578266  0.70489133  0.48527326\n                       0.19109018  0.70836635  0.48228395\n                       0.19657063  0.71182668  0.47922108\n                       0.20221902  0.71527175  0.47608431\n                       0.20803045  0.71870095  0.4728733\n                       0.21400015  0.72211371  0.46958774\n                       0.22012381  0.72550945  0.46622638\n                       0.2263969   0.72888753  0.46278934\n                       0.23281498  0.73224735  0.45927675\n                       0.2393739   0.73558828  0.45568838\n                       0.24606968  0.73890972  0.45202405\n                       0.25289851  0.74221104  0.44828355\n                       0.25985676  0.74549162  0.44446673\n                       0.26694127  0.74875084  0.44057284\n                       0.27414922  0.75198807  0.4366009\n                       0.28147681  0.75520266  0.43255207\n                       0.28892102  0.75839399  0.42842626\n                       0.29647899  0.76156142  0.42422341\n                       0.30414796  0.76470433  0.41994346\n                       0.31192534  0.76782207  0.41558638\n                       0.3198086   0.77091403  0.41115215\n                       0.3277958   0.77397953  0.40664011\n                       0.33588539  0.7770179   0.40204917\n                       0.34407411  0.78002855  0.39738103\n                       0.35235985  0.78301086  0.39263579\n                       0.36074053  0.78596419  0.38781353\n                       0.3692142   0.78888793  0.38291438\n                       0.37777892  0.79178146  0.3779385\n                       0.38643282  0.79464415  0.37288606\n                       0.39517408  0.79747541  0.36775726\n                       0.40400101  0.80027461  0.36255223\n                       0.4129135   0.80304099  0.35726893\n                       0.42190813  0.80577412  0.35191009\n                       0.43098317  0.80847343  0.34647607\n                       0.44013691  0.81113836  0.3409673\n                       0.44936763  0.81376835  0.33538426\n                       0.45867362  0.81636288  0.32972749\n                       0.46805314  0.81892143  0.32399761\n                       0.47750446  0.82144351  0.31819529\n                       0.4870258   0.82392862  0.31232133\n                       0.49661536  0.82637633  0.30637661\n                       0.5062713   0.82878621  0.30036211\n                       0.51599182  0.83115784  0.29427888\n                       0.52577622  0.83349064  0.2881265\n                       0.5356211   0.83578452  0.28190832\n                       0.5455244   0.83803918  0.27562602\n                       0.55548397  0.84025437  0.26928147\n                       0.5654976   0.8424299   0.26287683\n                       0.57556297  0.84456561  0.25641457\n                       0.58567772  0.84666139  0.24989748\n                       0.59583934  0.84871722  0.24332878\n                       0.60604528  0.8507331   0.23671214\n                       0.61629283  0.85270912  0.23005179\n                       0.62657923  0.85464543  0.22335258\n                       0.63690157  0.85654226  0.21662012\n                       0.64725685  0.85839991  0.20986086\n                       0.65764197  0.86021878  0.20308229\n                       0.66805369  0.86199932  0.19629307\n                       0.67848868  0.86374211  0.18950326\n                       0.68894351  0.86544779  0.18272455\n                       0.69941463  0.86711711  0.17597055\n                       0.70989842  0.86875092  0.16925712\n                       0.72039115  0.87035015  0.16260273\n                       0.73088902  0.87191584  0.15602894\n                       0.74138803  0.87344918  0.14956101\n                       0.75188414  0.87495143  0.14322828\n                       0.76237342  0.87642392  0.13706449\n                       0.77285183  0.87786808  0.13110864\n                       0.78331535  0.87928545  0.12540538\n                       0.79375994  0.88067763  0.12000532\n                       0.80418159  0.88204632  0.11496505\n                       0.81457634  0.88339329  0.11034678\n                       0.82494028  0.88472036  0.10621724\n                       0.83526959  0.88602943  0.1026459\n                       0.84556056  0.88732243  0.09970219\n                       0.8558096   0.88860134  0.09745186\n                       0.86601325  0.88986815  0.09595277\n                       0.87616824  0.89112487  0.09525046\n                       0.88627146  0.89237353  0.09537439\n                       0.89632002  0.89361614  0.09633538\n                       0.90631121  0.89485467  0.09812496\n                       0.91624212  0.89609127  0.1007168\n                       0.92610579  0.89732977  0.10407067\n                       0.93590444  0.8985704   0.10813094\n                       0.94563626  0.899815    0.11283773\n                       0.95529972  0.90106534  0.11812832\n                       0.96489353  0.90232311  0.12394051\n                       0.97441665  0.90358991  0.13021494\n                       0.98386829  0.90486726  0.13689671\n                       0.99324789  0.90615657  0.1439362 ];\n\n  p = rows (viridi);\n  map = interp1 (1:p, viridi, linspace (1, p, n), \"linear\");\n\nendfunction\n\n\n## A better demo of this colormap would be to plot the CIECAM02 values.\n%!demo\n%! ## Show the 'viridis' colormap profile and as an image\n%! cmap = viridis (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n%!assert (size (viridis ()), [256, 3])\n%!assert (size (viridis (16)), [16, 3])\n\n%!assert (viridis (0), zeros (0, 3))\n%!assert (viridis (-1), zeros (0, 3))\n\n%!shared a\n%! a = [0.26700401, 0.00487433, 0.32941519;\n%!      0.19063135, 0.40706148, 0.55608907;\n%!      0.20803045, 0.71870095, 0.47287330;\n%!      0.99324789, 0.90615657, 0.14393620];\n\n%!assert (viridis (1), a(4,:))\n%!assert (viridis (true), double (a(4,:)))\n%!assert (viridis (char (1)), double (a(4,:)))\n%!assert (viridis (int32 (1)), double (a(4,:)))\n%!assert (viridis (4), a, eps)\n\n%!shared  # Clear shared varibles to avoid echo on unrelated test errors.\n\n## Input validation\n%!error <N must be a scalar integer> viridis (\"foo\")\n%!error <N must be a scalar integer> viridis ([1, 2, 3])\n%!error <N must be a scalar integer> viridis ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/white.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} white ()\n## @deftypefnx {} {@var{map} =} white (@var{n})\n## Create color colormap.  This colormap is completely white.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = white (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"white: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n  map = ones (n, 3);\n\nendfunction\n\n\n%!demo\n%! ## Show the 'white' colormap profile and as an image\n%! cmap = white (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n%!assert (size (white ()), [256, 3])\n%!assert (size (white (16)), [16, 3])\n%!assert (all ((white ()(:)) == 1), true)\n\n%!assert (white (1), [1, 1, 1])\n%!assert (white (true), double ([1, 1, 1]))\n%!assert (white (char (1)), double ([1, 1, 1]))\n%!assert (white (int32 (1)), double ([1, 1, 1]))\n%!assert (white (0), zeros (0, 3))\n%!assert (white (-1), zeros (0, 3))\n\n\n## Input validation\n%!error <N must be a scalar integer> white (\"foo\")\n%!error <N must be a scalar integer> white ([1, 2, 3])\n%!error <N must be a scalar integer> white ({1, 2, 3})\n"
  },
  {
    "path": "scripts/image/winter.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{map} =} winter ()\n## @deftypefnx {} {@var{map} =} winter (@var{n})\n## Create color colormap.  This colormap varies from blue to green.\n##\n## The argument @var{n} must be a scalar.\n## If @var{n} is not specified the length of the current colormap is used.  If\n## there is no current colormap the default value of 256 is used.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction map = winter (n)\n\n  if (nargin == 1)\n    if (! (isscalar (n) && isreal (n) && n == fix (n)))\n      error (\"winter: N must be a scalar integer\");\n    endif\n    n = double (n);\n  else\n    hf = get (0, \"currentfigure\");\n    if (! isempty (hf))\n      n = rows (get (hf, \"colormap\"));\n    else\n      n = 256;\n    endif\n  endif\n\n  if (n == 1)\n    map = [0, 0, 1];\n  elseif (n > 1)\n    r = zeros (n, 1);\n    g = [0:(n-1)]' / (n - 1);\n    b = 1 - g / 2;\n    map = [r, g, b];\n  else\n    map = zeros (0, 3);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Show the 'winter' colormap profile and as an image\n%! cmap = winter (256);\n%! subplot (2, 1, 1);\n%!  rgbplot (cmap, \"composite\");\n%! subplot (2, 1, 2);\n%!  rgbplot (cmap);\n\n\n%!assert (size (winter ()), [256, 3])\n%!assert (size (winter (16)), [16, 3])\n\n%!assert (winter (1), [0, 0, 1])\n%!assert (winter (true), double ([0, 0, 1]))\n%!assert (winter (char (1)), double ([0, 0, 1]))\n%!assert (winter (int32 (1)), double ([0, 0, 1]))\n\n%!assert (winter (0), zeros (0, 3))\n%!assert (winter (-1), zeros (0, 3))\n\n%!assert (winter (11), [zeros(1,11); [0:0.1:1]; [1:-0.05:0.5]]', eps)\n\n## Input validation\n%!error <N must be a scalar integer> winter (\"foo\")\n%!error <N must be a scalar integer> winter ([1, 2, 3])\n%!error <N must be a scalar integer> winter ({1, 2, 3})\n"
  },
  {
    "path": "scripts/io/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/io/beep.m",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} beep ()\n## Produce a beep from the speaker (or visual bell).\n##\n## This function sends the alarm character @qcode{\"@backslashchar{}a\"} to\n## the terminal.  Depending on the user's configuration this may produce an\n## audible beep, a visual bell, or nothing at all.\n## @seealso{puts, fputs, printf, fprintf}\n## @end deftypefn\n\nfunction beep ()\n\n  puts (\"\\a\");\n\nendfunction\n\n\n%!error beep (1)\n"
  },
  {
    "path": "scripts/io/csvread.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} csvread (@var{filename})\n## @deftypefnx {} {@var{x} =} csvread (@var{filename}, @var{dlm_opt1}, @dots{})\n## Read the comma-separated-value (CSV) file @var{filename} into the matrix\n## @var{x}.\n##\n## Note: only CSV files containing numeric data can be read.\n##\n## This function is equivalent to\n##\n## @example\n## @var{x} = dlmread (@var{filename}, \",\" , @var{dlm_opt1}, @dots{})\n## @end example\n##\n## Any optional arguments are passed directly to @code{dlmread}\n## (@pxref{XREFdlmread,,@code{dlmread}}).\n## @seealso{dlmread, textscan, csvwrite, dlmwrite}\n## @end deftypefn\n\nfunction x = csvread (filename, varargin)\n  x = dlmread (filename, \",\", varargin{:});\nendfunction\n\n\n## Tests for csvread() are in csvwrite()\n## Mark file as being tested\n%!assert (1)\n"
  },
  {
    "path": "scripts/io/csvwrite.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} csvwrite (@var{filename}, @var{x})\n## @deftypefnx {} {} csvwrite (@var{filename}, @var{x}, @var{dlm_opt1}, @dots{})\n## Write the numeric matrix @var{x} to the file @var{filename} in\n## @w{comma-separated-value}@ (CSV) format.\n##\n## This function is equivalent to\n##\n## @example\n## dlmwrite (@var{filename}, @var{x}, \",\", @var{dlm_opt1}, @dots{})\n## @end example\n##\n## Any optional arguments are passed directly to @code{dlmwrite}\n## (@pxref{XREFdlmwrite,,@code{dlmwrite}}).\n## @seealso{csvread, dlmwrite, dlmread}\n## @end deftypefn\n\nfunction csvwrite (filename, x, varargin)\n  dlmwrite (filename, x, \",\", varargin{:});\nendfunction\n\n\n%!shared fname\n%! fname = tempname ();\n\n%!test\n%! csvwrite (fname, magic (3));\n%! data = csvread (fname);\n%! unlink (fname);\n%! assert (data, magic (3));\n\n%!test\n%! csvwrite (fname, magic (3), \"precision\", \"%2.1f\", \"newline\", \"unix\");\n%! fid = fopen (fname, \"rt\");\n%! txt = char (fread (fid,Inf,'char')');\n%! fclose (fid);\n%! unlink (fname);\n%! assert (txt, \"8.0,1.0,6.0\\n3.0,5.0,7.0\\n4.0,9.0,2.0\\n\");\n"
  },
  {
    "path": "scripts/io/dlmwrite.m",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} dlmwrite (@var{file}, @var{M})\n## @deftypefnx {} {} dlmwrite (@var{file}, @var{M}, @var{delim}, @var{r}, @var{c})\n## @deftypefnx {} {} dlmwrite (@var{file}, @var{M}, @var{key}, @var{val} @dots{})\n## @deftypefnx {} {} dlmwrite (@var{file}, @var{M}, \"-append\", @dots{})\n## @deftypefnx {} {} dlmwrite (@var{fid}, @dots{})\n## Write the numeric matrix @var{M} to the text file @var{file} using a\n## delimiter.\n##\n## @var{file} should be a filename or a writable file ID given by @code{fopen}.\n##\n## The parameter @var{delim} specifies the delimiter to use to separate values\n## on a row.  If no delimiter is specified the comma character @samp{,} is\n## used.\n##\n## The value of @var{r} specifies the number of delimiter-only lines to add to\n## the start of the file.\n##\n## The value of @var{c} specifies the number of delimiters to prepend to each\n## line of data.\n##\n## If the argument @qcode{\"-append\"} is given, append to the end of @var{file}.\n##\n## In addition, the following keyword value pairs may appear at the end of\n## the argument list:\n##\n## @table @asis\n## @item @qcode{\"append\"}\n## Either @qcode{\"on\"} or @qcode{\"off\"}.  See @qcode{\"-append\"} above.\n##\n## @item @qcode{\"delimiter\"}\n## See @var{delim} above.\n##\n## @item @qcode{\"newline\"}\n## The character(s) to separate each row.  Three special cases exist for this\n## option.  @qcode{\"unix\"} is changed into @qcode{\"@backslashchar{}n\"},\n## @qcode{\"pc\"} is changed into @qcode{\"@backslashchar{}r@backslashchar{}n\"},\n## and @qcode{\"mac\"} is changed into @qcode{\"@backslashchar{}r\"}.  Any other\n## value is used directly as the newline separator.\n##\n## @item @qcode{\"roffset\"}\n## See @var{r} above.\n##\n## @item @qcode{\"coffset\"}\n## See @var{c} above.\n##\n## @item @qcode{\"precision\"}\n## The precision to use when writing the file.  It can either be a format\n## string (as used by fprintf) or a number of significant digits.\n## @end table\n##\n## @example\n## dlmwrite (\"file.csv\", reshape (1:16, 4, 4));\n## @end example\n##\n## @example\n## dlmwrite (\"file.tex\", a, \"delimiter\", \"&\", \"newline\", \"\\n\")\n## @end example\n##\n## @seealso{dlmread, csvread, csvwrite}\n## @end deftypefn\n\n## Author: Paul Kienzle <pkienzle@users.sf.net>\n##\n## This program was originally granted to the public domain\n##\n## 2002-03-08 Paul Kienzle <pkienzle@users.sf.net>\n## * Initial revision\n## 2005-11-27 Bill Denney <bill@givebillmoney.com>\n## * Significant modifications of the input arguments for additional\n## functionality.\n\nfunction dlmwrite (file, M, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  ## set defaults\n  delim = \",\";\n  r = c = 0;\n  newline = \"\\n\";\n  if (ischar (M))\n    precision = \"%c\";\n  else\n    precision = \"%.16g\";\n  endif\n  opentype = \"wt\";\n\n  ## process the input arguments\n  i = 0;\n  while (i < length (varargin))\n    i += 1;\n    if (strcmpi (varargin{i}, \"delimiter\"))\n      delim = varargin{++i};\n    elseif (strcmpi (varargin{i}, \"newline\"))\n      newline = varargin{++i};\n      if (strcmpi (newline, \"unix\"))\n        newline = \"\\n\";\n      elseif (strcmpi (newline, \"pc\"))\n        newline = \"\\r\\n\";\n      elseif (strcmpi (newline, \"mac\"))\n        newline = \"\\r\";\n      endif\n    elseif (strcmpi (varargin{i}, \"roffset\"))\n      r = varargin{++i};\n    elseif (strcmpi (varargin{i}, \"coffset\"))\n      c = varargin{++i};\n    elseif (strcmpi (varargin{i}, \"precision\"))\n      precision = varargin{++i};\n      if (! strcmpi (class (precision), \"char\"))\n        precision = sprintf (\"%%.%gg\", precision);\n      endif\n    elseif (strcmpi (varargin{i}, \"-append\"))\n      opentype = \"at\";\n    elseif (strcmpi (varargin{i}, \"append\"))\n      i += 1;\n      if (strcmpi (varargin{i}, \"on\"))\n        opentype = \"at\";\n      elseif (strcmpi (varargin{i}, \"off\"))\n        opentype = \"wt\";\n      else\n        error ('dlmwrite: append must be \"on\" or \"off\"');\n      endif\n    else\n      if (i == 1)\n        delim = varargin{i};\n      elseif (i == 2)\n        r = varargin{i};\n      elseif (i == 3)\n        c = varargin{i};\n      else\n        print_usage ();\n      endif\n    endif\n  endwhile\n\n  ## Expand '\\t' to TAB for Matlab compatibility\n  if (strcmp (delim, '\\t'))\n    delim = \"\\t\";\n  endif\n\n  if (ischar (file))\n    [fid, msg] = fopen (file, opentype);\n  elseif (is_valid_file_id (file))\n    [fid, msg] = deal (file, \"invalid file number\");\n  else\n    error (\"dlmwrite: FILE must be a filename string or numeric FID\");\n  endif\n\n  if (fid < 0)\n    error ([\"dlmwrite: \" msg]);\n  else\n    if (r > 0)\n      fprintf (fid, \"%s\",\n               repmat ([repmat(delim, 1, c + columns(M)-1), newline], 1, r));\n    endif\n    if (iscomplex (M))\n      cprecision = regexprep (precision, '^%([-\\d.])', '%+$1');\n      template = [precision, cprecision, \"i\", ...\n                  repmat([delim, precision, cprecision, \"i\"], 1, ...\n                  columns(M) - 1), newline ];\n    else\n      template = [precision, repmat([delim, precision], 1, columns(M)-1),...\n                  newline];\n    endif\n    if (c > 0)\n      template = [repmat(delim, 1, c), template];\n    endif\n    if (iscomplex (M))\n      M = M.';\n      b = zeros (2*rows (M), columns (M));\n      b(1: 2 : end, :) = real (M);\n      b(2: 2 : end, :) = imag (M);\n      fprintf (fid, template, b);\n    else\n      fprintf (fid, template, M.');\n    endif\n    if (ischar (file))\n      fclose (fid);\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! f = tempname ();\n%! dlmwrite (f,[1,2;3,4],\"precision\",\"%5.2f\",\"newline\",\"unix\",\"roffset\",1,\"coffset\",1);\n%! fid = fopen (f,\"rt\");\n%! f1 = char (fread (fid,Inf,\"char\")');\n%! fclose (fid);\n%! dlmwrite (f,[5,6],\"precision\",\"%5.2f\",\"newline\",\"unix\",\"coffset\",1,\"delimiter\",\",\",\"-append\");\n%! fid = fopen (f,\"rt\");\n%! f2 = char (fread (fid,Inf,\"char\")');\n%! fclose (fid);\n%! unlink (f);\n%!\n%! assert (f1,\",,\\n, 1.00, 2.00\\n, 3.00, 4.00\\n\");\n%! assert (f2,\",,\\n, 1.00, 2.00\\n, 3.00, 4.00\\n, 5.00, 6.00\\n\");\n"
  },
  {
    "path": "scripts/io/fileread.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{str} =} fileread (@var{filename})\n## @deftypefnx {} {@var{str} =} fileread (@var{filename}, @var{param}, @var{value}, @dots{})\n## Read the contents of @var{filename} and return it as a string.\n##\n## @var{param}, @var{value} are optional pairs of parameters and values.  Valid\n## options are:\n##\n## @table @asis\n## @item @qcode{\"Encoding\"}\n## Specify encoding used when reading from the file.  This is a character\n## string of a valid encoding identifier.  The default is\n## @nospell{@qcode{\"utf-8\"}}.\n## @end table\n##\n## @seealso{fopen, fread, fscanf, importdata, textscan, type}\n## @end deftypefn\n\nfunction str = fileread (filename, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (filename))\n    error (\"fileread: FILENAME argument must be a string\");\n  endif\n\n  encoding = \"utf-8\";\n\n  if (nargin > 1)\n\n    ## Check for parameter/value arguments\n    for i_arg = 1:2:numel (varargin)\n\n      if (! ischar (varargin{i_arg}))\n        error (\"fileread: parameter %d must be a string\", i_arg);\n      endif\n      parameter = varargin{i_arg};\n      if (i_arg+1 > numel (varargin))\n        error ('fileread: parameter \"%s\" missing value', parameter);\n      endif\n\n      switch (lower (parameter))\n        case \"encoding\"\n          encoding = varargin{i_arg+1};\n        otherwise\n          error ('fileread: Unknown option \"%s\"', parameter);\n      endswitch\n\n    endfor\n  endif\n\n  fid = fopen (filename, \"r\", \"n\", encoding);\n  if (fid < 0)\n    error (\"fileread: cannot open file\");\n  endif\n\n  unwind_protect\n    str = (fread (fid, \"*char\")).';\n  unwind_protect_cleanup\n    fclose (fid);\n  end_unwind_protect\n\nendfunction\n\n\n%!test\n%! cstr = {\"Hello World\", \"The answer is 42\", \"Goodbye World\"};\n%! fname = tempname ();\n%! fid = fopen (fname, \"w\");\n%! fprintf (fid, \"%s\\n\", cstr{:});\n%! fclose (fid);\n%! str = fileread (fname);\n%! unlink (fname);\n%! assert (str, [cstr{1} \"\\n\" cstr{2} \"\\n\" cstr{3} \"\\n\"]);\n\n## Test input validation\n%!error <Invalid call> fileread ()\n%!error <FILENAME argument must be a string> fileread (1)\n%!error <parameter \"Encoding\" missing value> fileread (\"filename\", \"Encoding\")\n%!error <Unknown option \"UnknownParam\">\n%! fileread (\"filename\", \"UnknownParam\", \"UnknownValue\")\n## FIXME: The following test should be skipped if\n##        OCTAVE_HAVE_STRICT_ENCODING_FACET is defined.\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! fail ('fileread (\"filename\", \"Encoding\", \"UnknownValue\")', ...\n%!       \"conversion from codepage 'unknownvalue' not supported\");\n"
  },
  {
    "path": "scripts/io/importdata.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{A} =} importdata (@var{fname})\n## @deftypefnx {} {@var{A} =} importdata (@var{fname}, @var{delimiter})\n## @deftypefnx {} {@var{A} =} importdata (@var{fname}, @var{delimiter}, @var{header_rows})\n## @deftypefnx {} {[@var{A}, @var{delimiter}] =} importdata (@dots{})\n## @deftypefnx {} {[@var{A}, @var{delimiter}, @var{header_rows}] =} importdata (@dots{})\n## Import data from the file @var{fname}.\n##\n## Input parameters:\n##\n## @itemize\n## @item @var{fname}\n## The name of the file containing data.\n##\n## @item @var{delimiter}\n## The character separating columns of data.  Use @code{\\t} for tab.\n## (Only valid for ASCII files)\n##\n## @item @var{header_rows}\n## The number of header rows before the data begins.  (Only valid for ASCII\n## files)\n## @end itemize\n##\n## Different file types are supported:\n##\n## @itemize\n## @item ASCII table\n##\n## Import ASCII table using the specified number of header rows and the\n## specified delimiter.\n##\n## @item Image file\n##\n## @item @sc{matlab} file\n##\n## @item Spreadsheet files (depending on external software)\n##\n## @item WAV file\n##\n## @end itemize\n##\n## @seealso{textscan, dlmread, csvread, load}\n## @end deftypefn\n\nfunction [output, delimiter, header_rows] = importdata (fname, delimiter = \"\", header_rows = -1)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (fname))\n    error (\"importdata: FNAME must be a string\");\n  elseif (strcmpi (fname, \"-pastespecial\"))\n    error (\"importdata: option -pastespecial not implemented\");\n  endif\n\n  if (nargin > 1)\n    if (! ischar (delimiter)\n        || (length (delimiter) > 1 && ! strcmp (delimiter, '\\t')))\n      error (\"importdata: DELIMITER must be a single character\");\n    endif\n    if (strcmp (delimiter, '\\t'))\n      delimiter = \"\\t\";\n    endif\n  endif\n\n  if (nargin > 2)\n    if (! isnumeric (header_rows) || header_rows < 0\n        || header_rows != fix (header_rows))\n      error (\"importdata: HEADER_ROWS must be an integer >= 0\");\n    endif\n  endif\n\n  ## Check file format\n  ## Get the extension from the filename.\n  [~, ~, ext] = fileparts (fname);\n  ext = lower (ext);\n\n  switch (ext)\n    case {\".au\", \".snd\", \".flac\", \".ogg\", \".wav\", \".wave\"}\n      [output.data, output.fs] = audioread (fname);\n    case {\".avi\", \".mj2\", \".mpg\", \".asf\", \".asx\", \".wmv\", \".mp4\", \".m4v\", ...\n          \".mov\"}\n      error (\"importdata: not implemented for file format %s\", ext);\n    case {\".bmp\", \".cur\", \".gif\", \".hdf\", \".ico\", \".jpe\", \".jpeg\", \".jpg\", ...\n          \".jp2\", \".jpf\", \".jpx\", \".j2c\", \".j2k\", \".pbm\", \".pcx\", \".pgm\", ...\n          \".png\", \".pnm\", \".ppm\", \".ras\", \".tif\", \".tiff\", \".xwd\"}\n      delimiter = NaN;\n      header_rows = 0;\n      [output.cdata, output.colormap, output.alpha] = imread (fname);\n    case \".mat\"\n      delimiter = NaN;\n      header_rows = 0;\n      output = load (fname);\n    case {\".xls\", \".xlsx\", \".wk1\", \".dbf\", \".pxl\"}\n      ## If there's no Excel file support simply fall back to unimplemented.m\n      output = xlsread (fname);\n    case {\".ods\", \".sxc\", \".fods\", \".uos\", \".xml\"}\n      ## unimplemented.m only knows ML functions; odsread isn't one but is in OF\n      try\n        output = odsread (fname);\n      catch\n        ## Fall back to unimplemented.m.\n        output = xlsread (fname);\n      end_try_catch\n    otherwise\n      ## Assume the file is in ASCII format.\n      [output, delimiter, header_rows] = ...\n        importdata_ascii (fname, delimiter, header_rows);\n  endswitch\n\n  ## If there are any empty fields in the output structure, then remove them\n  if (isstruct (output) && numel (output) == 1)\n    fields = fieldnames (output);\n    for i=1:length (fields)\n      if (isempty (output.(fields{i})))\n        output = rmfield (output, fields{i});\n      endif\n    endfor\n\n    ## If only one field is left, replace the structure with the field,\n    ## i.e., output = output.onlyFieldLeft\n\n    ## Update the list of fields\n    if (numfields (output) == 1)\n      output = output.(fields{1});\n    endif\n  endif\n\nendfunction\n\nfunction [output, delimiter, header_rows] = importdata_ascii (fname, delimiter, num_header_rows)\n\n  ## Define fields in the output structure so that the order will be correct.\n  output.data       = [];\n  output.textdata   = {};\n  output.rowheaders = {};\n  output.colheaders = {};\n\n  [fid, msg] = fopen (fname, \"r\");\n  if (fid == -1)\n    error (msg);\n  endif\n\n  header_rows = 0;\n  header_cols = 0;\n\n  ## Work through first few rows line by line until a delimiter is found.\n  while (ischar (row = fgetl (fid)))\n\n    ## If no delimiter determined yet, make a guess.\n    if (isempty (delimiter))\n      ## Look for number, DELIMITER, DELIMITER*, number\n      delim = regexpi (row, '[-+]?\\d*[.]?\\d+(?:[ed][-+]?\\d+)?[ij]?([^-+\\d.deij])\\1*[-+]?\\d*[.]?\\d+(?:[ed][-+]?\\d+)?[ij]?',\n                       'tokens', 'once');\n      if (! isempty (delim))\n        delimiter = delim{1};\n      endif\n    endif\n\n    if (delimiter == \" \")\n      row_entries = regexp (strtrim (row), ' +', 'split');\n    else\n      row_entries = ostrsplit (row, delimiter);\n    endif\n    row_data = str2double (row_entries);\n    if (header_rows < num_header_rows)\n      header_rows += 1;\n      output.textdata{end+1, 1} = row;\n    elseif (all (isnan (row_data)) && header_rows < 25)\n      header_rows += 1;\n      output.textdata{end+1, 1} = row;\n    elseif (all (isnan (row_data)))\n      ## Failed to find any numeric input in first 25 lines\n      row = -1;\n      break;\n    else\n      ## The number of header rows and header columns is now known.\n      header_cols = find (! isnan (row_data), 1) - 1;\n      has_rowheaders = (header_cols == 1);\n\n      ## Set colheaders output from textdata if appropriate\n      ## NOTE: Octave chooses to be Matlab incompatible and return\n      ## both 'rowheaders' and 'colheaders' when they are present.\n      ## Matlab allows only one to be present at a time.\n      if (! isempty (output.textdata))\n        if (delimiter == \" \")\n          output.colheaders = regexp (strtrim (output.textdata{end}),\n                                      ' +', 'split');\n        else\n          output.colheaders = ostrsplit (output.textdata{end}, delimiter);\n        endif\n\n        nc_hdr = numel (output.colheaders);\n        nc_dat = numel (row_data);\n        if (! has_rowheaders)\n          if (nc_hdr != nc_dat)\n            output = rmfield (output, {\"rowheaders\", \"colheaders\"});\n          else\n            output = rmfield (output, \"rowheaders\");\n          endif\n        else\n          if (nc_hdr != nc_dat-1)\n            output = rmfield (output, \"colheaders\");\n          endif\n        endif\n      endif\n\n      break;\n    endif\n\n  endwhile\n\n  if (row == -1)\n    ## No numeric data found => return file as cellstr array\n    ## 1. Read as char string\n    fseek (fid, 0, \"bof\");\n    output = fread (fid, Inf, \"*char\")';\n    fclose (fid);\n    ## 2. Find EOL type\n    idx = find (output(1:min (4096, length (output))) == \"\\n\", 1) - 1;\n    if (isindex (idx) && output(idx) == \"\\r\")\n      dlm = \"\\r\\n\";\n    else\n      dlm = \"\\n\";\n    endif\n    ## 3. Split each line into a cell (column vector)\n    output = strsplit (output, dlm)';\n    ## 4. Remove last cell (for files with -proper- EOL before EOF)\n    if (isempty (output{end}))\n      output(end) = [];\n    endif\n    ## 5. Return after setting some output data\n    delimiter = \"\";\n    header_rows = numel (output);\n    return;\n  endif\n\n  fclose (fid);\n\n  if (num_header_rows >= 0)\n    ## User has defined a number of header rows which disagrees with the\n    ## auto-detected number.  Print a warning.\n    if (num_header_rows < header_rows)\n      warning (\"Octave:importdata:headerrows_mismatch\",\n               \"importdata: detected %d header rows, but HEADER_ROWS input configured %d rows\", header_rows, num_header_rows);\n    endif\n  else\n    ## use the automatically detected number of header rows\n    num_header_rows = header_rows;\n  endif\n\n  ## Now, let the efficient built-in routine do the bulk of the work.\n  if (delimiter == \" \")\n    output.data = dlmread (fname, \"\", num_header_rows, header_cols,\n                           \"emptyvalue\", NA);\n  else\n    output.data = dlmread (fname, delimiter, num_header_rows, header_cols,\n                           \"emptyvalue\", NA);\n  endif\n\n  ## Go back and correct any individual values that did not convert.\n  ## FIXME: This is only efficient when the number of bad conversions is small.\n  ##        Any file with 'rowheaders' will cause the for loop to execute over\n  ##        *every* line in the file.\n\n  na_idx = isna (output.data);\n  if (header_cols > 0)\n    na_idx = [(true (rows (na_idx), header_cols)), na_idx];\n  endif\n  if (any (na_idx(:)))\n\n    file_content = ostrsplit (fileread (fname), \"\\r\\n\", true);\n\n    na_rows = find (any (na_idx, 2));\n    ## Prune text lines in header that were already collected\n    idx = (na_rows(1:min (header_rows, end)) + num_header_rows) <= header_rows;\n    na_rows(idx) = [];\n    for ridx = na_rows(:)'\n      row = file_content{ridx+num_header_rows};\n      if (delimiter == \" \")\n        fields = regexp (strtrim (row), ' +', 'split');\n      else\n        fields = ostrsplit (row, delimiter);\n      endif\n\n      missing_idx = na_idx(ridx,:);\n      if (! size_equal (missing_idx, fields))\n        ## Fields completely missing at end of line.  Replace with NA.\n        col = columns (fields);\n        ## FIXME: This code should be redundant because dlmread was called\n        ##        with \"emptyval\", NA.  Delete if there are no problems\n        ##        detected after some time.  Commented out: 5/23/2020.\n        ## output.data(ridx, (col+1):end) = NA;\n        missing_idx = missing_idx(1:col);\n      endif\n      text = fields(missing_idx);\n\n      text = text(! strcmpi (text, \"NA\"));  #  Remove valid \"NA\" entries\n      text = text(! strcmpi (text, \"\"));    #  Remove empty entries\n      if (! isempty (text))\n        output.textdata(end+1, 1:columns (text)) = text;\n      endif\n\n      if (has_rowheaders)\n        output.rowheaders(end+1, 1) = fields(1);\n      endif\n    endfor\n\n  endif\n\n  ## Final cleanup to satisfy Matlab compatibility\n  if (all (cellfun (\"isempty\", output.textdata)))\n    output = output.data;\n  else\n    ## Text fields should be cell array of strings, rather than just cell.\n    try\n      output.textdata = cellstr (output.textdata);\n    end_try_catch\n    try\n      output.rowheaders = cellstr (output.rowheaders);\n    end_try_catch\n    try\n      output.colheaders = cellstr (output.colheaders);\n    end_try_catch\n  endif\n\n  if (num_header_rows != header_rows)\n    header_rows = num_header_rows;\n  endif\n\nendfunction\n\n\n%!test\n%! ## Comma-separated values\n%! A = [3.1 -7.2 0; 0.012 6.5 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"3.1,-7.2,0\\n0.012,6.5,128\");\n%! fclose (fid);\n%! [a1,d1,h1] = importdata (fn, \",\");\n%! [a2,d2,h2] = importdata (fn);\n%! unlink (fn);\n%! assert (a1, A);\n%! assert (d1, \",\");\n%! assert (h1, 0);\n%! assert (a2, A);\n%! assert (d2, \",\");\n%! assert (h2, 0);\n\n%!test\n%! ## Tab separated values\n%! A = [3.1 -7.2 0; 0.012 6.5 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"3.1\\t-7.2\\t0\\n0.012\\t6.5\\t128\");\n%! fclose (fid);\n%! [a1,d1,h1] = importdata (fn, \"\\t\");\n%! [a2,d2,h2] = importdata (fn);\n%! unlink (fn);\n%! assert (a1, A);\n%! assert (d1, \"\\t\");\n%! assert (h1, 0);\n%! assert (a2, A);\n%! assert (d2, \"\\t\");\n%! assert (h2, 0);\n\n%!test\n%! ## Space separated values, using multiple spaces to align in columns.\n%! A = [3.1 -7.2 0; 0.012 6.5 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fprintf (fid, \"%10.3f %10.3f %10.3f\\n\", A');\n%! fclose (fid);\n%! [a1,d1,h1] = importdata (fn, \" \");\n%! [a2,d2,h2] = importdata (fn);\n%! unlink (fn);\n%! assert (a1, A);\n%! assert (d1, \" \");\n%! assert (h1, 0);\n%! assert (a2, A);\n%! assert (d2, \" \");\n%! assert (h2, 0);\n\n%!test\n%! ## No separator, 1 column of data only\n%! A = [3.1;-7.2;0;0.012;6.5;128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fprintf (fid, \"%f\\n\", A);\n%! fclose (fid);\n%! [a1,d1,h1] = importdata (fn, \"\");\n%! [a2,d2,h2] = importdata (fn);\n%! unlink (fn);\n%! assert (a1, A);\n%! assert (d1, \"\");\n%! assert (h1, 0);\n%! assert (a2, A);\n%! assert (d2, \"\");\n%! assert (h2, 0);\n\n%!test\n%! ## Header text\n%! A.data = [3.1 -7.2 0; 0.012 6.5 128];\n%! A.textdata = {\"This is a header row.\"; ...\n%!               \"this row does not contain any data, but the next one does.\"};\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fprintf (fid, \"%s\\n\", A.textdata{:});\n%! fputs (fid, \"3.1\\t-7.2\\t0\\n0.012\\t6.5\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 2);\n\n%!test\n%! ## Column headers, only last row is returned in colheaders\n%! A.data = [3.1 -7.2 0; 0.012 6.5 128];\n%! A.textdata = {\"Label1\\tLabel2\\tLabel3\";\n%!               \"\";\n%!               \"col 1\\tcol 2\\tcol 3\"};\n%! A.colheaders = {\"col 1\", \"col 2\", \"col 3\"};\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fprintf (fid, \"%s\\n\", A.textdata{:});\n%! fputs (fid, \"3.1\\t-7.2\\t0\\n0.012\\t6.5\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 3);\n\n%!test\n%! ## Row headers\n%! A.data = [3.1 -7.2 0; 0.012 6.5 128];\n%! A.textdata = {\"row1\"; \"row2\"};\n%! A.rowheaders = A.textdata;\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"row1\\t3.1\\t-7.2\\t0\\nrow2\\t0.012\\t6.5\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 0);\n\n%!test\n%! ## Row/Column headers and Header Text\n%! A.data = [3.1 -7.2 0; 0.012 6.5 128];\n%! A.textdata = {\"This is introductory header text\"\n%!               \"col1\\tcol2\\tcol3\"\n%!               \"row1\"\n%!               \"row2\"};\n%! A.rowheaders = A.textdata(3:4);\n%! A.colheaders = {\"col1\", \"col2\", \"col3\"};\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fprintf (fid, \"%s\\n\", A.textdata{1:2});\n%! fputs (fid, \"row1\\t3.1\\t-7.2\\t0\\nrow2\\t0.012\\t6.5\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 2);\n\n%!test\n%! ## Ignore empty rows containing only spaces\n%! A = [3.1 -7.2 0; 0.012 6.5 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fprintf (fid, \"%10.3f %10.3f %10.3f\\n\", A(1,:));\n%! fputs (fid, \"      \");\n%! fprintf (fid, \"%10.3f %10.3f %10.3f\\n\", A(2,:));\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, \" \");\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \" \");\n%! assert (h, 0);\n\n%!test\n%! ## Exponentials\n%! A = [3.1 -7.2 0; 0.012 6.5 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"+3.1e0\\t-72E-1\\t0\\n12e-3\\t6.5\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 0);\n\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! ## Complex numbers\n%! A = [3.1 -7.2 0-3.4i; 0.012 -6.5+7.2i 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"3.1\\t-7.2\\t0-3.4i\\n0.012\\t-6.5+7.2i\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 0);\n\n%!testif HAVE_LLVM_LIBCXX  <47413>\n%! ## Same test code as above, intended only for test statistics with libc++.\n%! ## Complex numbers\n%! A = [3.1 -7.2 0-3.4i; 0.012 -6.5+7.2i 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"3.1\\t-7.2\\t0-3.4i\\n0.012\\t-6.5+7.2i\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 0);\n\n%!test\n%! ## Exceptional values (Inf, NaN, NA)\n%! A = [3.1 Inf NA; -Inf NaN 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"3.1\\tInf\\tNA\\n-Inf\\tNaN\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 0);\n\n%!test\n%! ## Missing values and Text Values\n%! A.data = [3.1 NA 0; 0.012 NA 128];\n%! A.textdata = {\"NO DATA\"};\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"3.1\\t\\t0\\n0.012\\tNO DATA\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 0);\n\n%!#test\n%! ## CRLF for line breaks\n%! A = [3.1 -7.2 0; 0.012 6.5 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"3.1\\t-7.2\\t0\\r\\n0.012\\t6.5\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 0);\n\n%!#test\n%! ## CR for line breaks\n%! A = [3.1 -7.2 0; 0.012 6.5 128];\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"3.1\\t-7.2\\t0\\r0.012\\t6.5\\t128\");\n%! fclose (fid);\n%! [a,d,h] = importdata (fn, '\\t');\n%! unlink (fn);\n%! assert (a, A);\n%! assert (d, \"\\t\");\n%! assert (h, 0);\n\n%!test <*43393>\n%! ## Distinguish double from complex when no delimiter is supplied\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"2.0000e+02   4.0000e-04\");\n%! fclose (fid);\n%! [a, d, h] = importdata (fn);\n%! unlink (fn);\n%! assert (a, [2e2, 4e-4]);\n%! assert (d, \" \");\n%! assert (h, 0);\n\n%!test\n%! ## Only text / no numeric data; \\n as EOL\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"aaaa 11\\nbbbbb 22\\nccccc 3\\n\");\n%! fclose (fid);\n%! [a, d, h] = importdata (fn);\n%! unlink (fn);\n%! assert (a, {\"aaaa 11\"; \"bbbbb 22\"; \"ccccc 3\"});\n%! assert (d, \"\");\n%! assert (h, 3);\n\n%!test\n%! ## Only text / no numeric data; \\r\\n as EOL; missing last EOL before EOF\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"aaaa 11\\r\\nbbbbb 22\\r\\nccccc 3\");\n%! fclose (fid);\n%! [a, d, h] = importdata (fn);\n%! unlink (fn);\n%! assert (a, {\"aaaa 11\"; \"bbbbb 22\"; \"ccccc 3\"});\n%! assert (d, \"\");\n%! assert (h, 3);\n\n%!test <*58294>\n%! ## Varying values of header lines field\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"header1\\nheader2\\n3.1\\n4.2\");\n%! fclose (fid);\n%! warning (\"off\", \"Octave:importdata:headerrows_mismatch\", \"local\");\n%! ## Base import\n%! [a, d, h] = importdata (fn, \"\");\n%! assert (a.data, [3.1; 4.2]);\n%! assert (a.textdata, {\"header1\"; \"header2\"});\n%! assert (h, 2);\n%! ## Import with 0 header lines\n%! [a, d, h] = importdata (fn, \"\", 0);\n%! assert (a.data, [NA; NA; 3.1; 4.2]);\n%! assert (a.textdata, {\"header1\"; \"header2\"});\n%! assert (h, 0);\n%! ## Import with 1 header lines\n%! [a, d, h] = importdata (fn, \"\", 1);\n%! assert (a.data, [NA; 3.1; 4.2]);\n%! assert (a.textdata, {\"header1\"; \"header2\"});\n%! assert (h, 1);\n%! ## Import with 3 header lines\n%! [a, d, h] = importdata (fn, \"\", 3);\n%! assert (a.data, [4.2]);\n%! assert (a.textdata, {\"header1\"; \"header2\"; \"3.1\"});\n%! assert (h, 3);\n%! unlink (fn);\n\n## Test input validation\n%!error <Invalid call> importdata ()\n%!error <FNAME must be a string> importdata (1)\n%!error <option -pastespecial not implemented> importdata (\"-pastespecial\")\n%!error <DELIMITER must be a single character> importdata (\"foo\", 1)\n%!error <DELIMITER must be a single character> importdata (\"foo\", \"ab\")\n%!error <HEADER_ROWS must be an integer> importdata (\"foo\", \" \", \"1\")\n%!error <HEADER_ROWS must be an integer> importdata (\"foo\", \" \", 1.5)\n%!error <not implemented for file format .avi> importdata (\"foo.avi\")\n%!warning <detected 2 header rows, but HEADER_ROWS input configured 1 rows>\n%! fn  = tempname ();\n%! fid = fopen (fn, \"w\");\n%! fputs (fid, \"header1\\nheader2\\n3.1\");\n%! fclose (fid);\n%! a = importdata (fn, \"\", 1);\n%! unlink (fn);\n"
  },
  {
    "path": "scripts/io/is_valid_file_id.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} is_valid_file_id (@var{fid})\n## Return true if @var{fid} refers to an open file.\n## @seealso{freport, fopen}\n## @end deftypefn\n\nfunction tf = is_valid_file_id (fid)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = false;\n\n  try\n    if (isscalar (fid))\n      [file, mode, arch] = fopen (fid);\n      tf = ! isempty (file);\n    endif\n  end_try_catch\n\nendfunction\n\n\n%!assert (is_valid_file_id (stdout))\n%!assert (! is_valid_file_id ([1,2;3,4]))\n%!assert (! is_valid_file_id (\"not_a_file_id\"))\n%!assert (! is_valid_file_id (-1))\n%!assert (! is_valid_file_id (pi))\n%!test <*65543>\n%! unwind_protect\n%!   fid = tmpfile ();\n%!   assert (is_valid_file_id (fid));\n%! unwind_protect_cleanup\n%!   fclose (fid);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> is_valid_file_id ()\n\n"
  },
  {
    "path": "scripts/io/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/beep.m \\\n  %reldir%/csvread.m \\\n  %reldir%/csvwrite.m \\\n  %reldir%/dlmwrite.m \\\n  %reldir%/fileread.m \\\n  %reldir%/importdata.m \\\n  %reldir%/is_valid_file_id.m\n\n%canon_reldir%dir = $(fcnfiledir)/io\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/java/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/java/javaArray.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{jary} =} javaArray (@var{classname}, @var{sz})\n## @deftypefnx {} {@var{jary} =} javaArray (@var{classname}, @var{m}, @var{n}, @dots{})\n##\n## Create a Java array of size @var{sz} with elements of class @var{classname}.\n##\n## @var{classname} may be a Java object representing a class or a string\n## containing the fully qualified class name.  The size of the object may\n## also be specified with individual integer arguments @var{m}, @var{n}, etc.\n##\n## The generated array is uninitialized.  All elements are set to null if\n## @var{classname} is a reference type, or to a default value (usually 0) if\n## @var{classname} is a primitive type.\n##\n## Sample code:\n##\n## @example\n## @group\n## jary = javaArray (\"java.lang.String\", 2, 2);\n## jary(1,1) = \"Hello\";\n## @end group\n## @end example\n## @seealso{javaObject}\n## @end deftypefn\n\nfunction retval = javaArray (classname, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  retval = javaMethod (\"createArray\", \"org.octave.ClassHelper\",\n                        classname, [varargin{:}]);\n\nendfunction\n"
  },
  {
    "path": "scripts/java/java_get.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{val} =} java_get (@var{obj}, @var{name})\n## Get the value of the field @var{name} of the Java object @var{obj}.\n##\n## For static fields, @var{obj} can be a string representing the fully\n## qualified name of the corresponding class.\n##\n## When @var{obj} is a regular Java object, structure-like indexing can be\n## used as a shortcut syntax.  For instance, the following two statements are\n## equivalent\n##\n## @example\n## @group\n##   java_get (x, \"field1\")\n##   x.field1\n## @end group\n## @end example\n##\n## @seealso{java_set, javaMethod, javaObject}\n## @end deftypefn\n\nfunction retval = java_get (obj, name)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (isjava (obj))\n    retval = obj.(name);\n  elseif (ischar (obj))\n    retval = __java_get__ (obj, name);\n  else\n    error (\"java_get: OBJ must be a Java object\");\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/java/java_set.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{obj} =} java_set (@var{obj}, @var{name}, @var{val})\n## Set the value of the field @var{name} of the Java object @var{obj} to\n## @var{val}.\n##\n## For static fields, @var{obj} can be a string representing the fully\n## qualified named of the corresponding Java class.\n##\n## When @var{obj} is a regular Java object, structure-like indexing can be\n## used as a shortcut syntax.  For instance, the following two statements are\n## equivalent\n##\n## @example\n## @group\n##   java_set (x, \"field1\", val)\n##   x.field1 = val\n## @end group\n## @end example\n##\n## @seealso{java_get, javaMethod, javaObject}\n## @end deftypefn\n\nfunction retval = java_set (obj, name, val)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (isjava (obj))\n    obj.(name) = val;\n  elseif (ischar (obj))\n    retval = __java_set__ (obj, name, val);\n  else\n    error (\"java_set: OBJ must be a Java object\");\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/java/javaaddpath.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} javaaddpath (@var{clspath})\n## @deftypefnx {} {} javaaddpath (@var{clspath1}, @dots{})\n## @deftypefnx {} {} javaaddpath (@{@var{clspath1}, @dots{}@})\n## @deftypefnx {} {} javaaddpath (@dots{}, \"-end\")\n## Add @var{clspath} to the beginning of the dynamic class path of the\n## Java virtual machine.\n##\n## @var{clspath} may either be a directory where @file{.class} files are\n## found, or a @file{.jar} file containing Java classes.  Multiple paths may\n## be added at once by specifying additional arguments, or by using a cell\n## array of strings.\n##\n## If the final argument is @qcode{\"-end\"}, append the new element to the\n## end of the current classpath.\n##\n## @seealso{javarmpath, javaclasspath}\n## @end deftypefn\n\nfunction javaaddpath (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! all (cellfun (@(c) ischar (c) || iscellstr (c), varargin)))\n    error (\"javaaddpath: arguments must be strings or cell array of strings\");\n  endif\n\n  if (strcmp (varargin{end}, \"-end\"))\n    at_end = true;\n    varargin(end) = [];\n  else\n    ## Note that when prepending, we iterate over the arguments in\n    ## reverse so that a call like\n    ##\n    ##   javaaddpath (\"/foo\", \"/bar\")\n    ##\n    ## results in \"/foo\" first in the path followed by \"/bar\".\n    at_end = false;\n    varargin = fliplr (varargin);\n  endif\n\n  for arg = varargin\n    if (iscellstr (arg{1}))\n      if (at_end)\n        ## Guarantee cellstr array is a row vector\n        arg = arg{1}(:).';\n      else\n        ## Iterate in reverse over cell arrays\n        arg = fliplr (arg{1}(:).');\n      endif\n    endif\n\n    for clspath = arg\n      clspath = clspath{1};\n\n      new_path = canonicalize_file_name (tilde_expand (clspath));\n      if (isfolder (new_path))\n        if (new_path(end) != filesep ())\n          new_path = [new_path, filesep()];\n        endif\n      elseif (! exist (new_path, \"file\"))\n        error (\"javaaddpath: CLSPATH does not exist: %s\", clspath);\n      endif\n\n      success = javaMethod (\"addClassPath\", \"org.octave.ClassHelper\",\n                            new_path, at_end);\n\n      if (! success)\n        warning (\"javaaddpath: failed to add '%s' to Java classpath\", new_path);\n      endif\n    endfor\n  endfor\n\nendfunction\n\n\n## FIXME: These tests may fail if either TEMPDIR or HOME have already\n##        been added to the Java class path.\n\n## Basic prepend test with single string\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! pth = tempdir ();\n%! unwind_protect\n%!   clspth1 = javaclasspath (\"-dynamic\");\n%!   javaaddpath (pth);\n%!   clspth2 = javaclasspath (\"-dynamic\");\n%!   assert (clspth2{1}, canonicalize_file_name (pth));\n%!   assert (clspth2(2:end), clspth1(1:end));\n%! unwind_protect_cleanup\n%!   javarmpath (pth);\n%! end_unwind_protect\n\n## Prepend test with two strings\n%!testif HAVE_JAVA; usejava (\"jvm\") && isfolder (\"~\")\n%! pth1 = tempdir ();\n%! pth2 = tilde_expand (\"~\");\n%! unwind_protect\n%!   clspth1 = javaclasspath (\"-dynamic\");\n%!   javaaddpath (pth1, pth2);\n%!   clspth2 = javaclasspath (\"-dynamic\");\n%!   assert (clspth2([1, 2]),\n%!           {canonicalize_file_name(pth1), canonicalize_file_name(pth2)});\n%!   assert (clspth2(3:end), clspth1(1:end));\n%! unwind_protect_cleanup\n%!   javarmpath (pth1, pth2);\n%! end_unwind_protect\n\n## Prepend test with cell array of two strings\n%!testif HAVE_JAVA; usejava (\"jvm\") && isfolder (\"~\")\n%! pth1 = tempdir ();\n%! pth2 = tilde_expand (\"~\");\n%! unwind_protect\n%!   clspth1 = javaclasspath (\"-dynamic\");\n%!   javaaddpath ({pth1, pth2});\n%!   clspth2 = javaclasspath (\"-dynamic\");\n%!   assert (clspth2([1, 2]),\n%!           {canonicalize_file_name(pth1), canonicalize_file_name(pth2)});\n%!   assert (clspth2(3:end), clspth1(1:end));\n%! unwind_protect_cleanup\n%!   javarmpath (pth1, pth2);\n%! end_unwind_protect\n\n## Append test with two strings\n%!testif HAVE_JAVA; usejava (\"jvm\") && isfolder (\"~\")\n%! pth1 = tempdir ();\n%! pth2 = tilde_expand (\"~\");\n%! unwind_protect\n%!   clspth1 = javaclasspath (\"-dynamic\");\n%!   javaaddpath (pth1, pth2, \"-end\");\n%!   clspth2 = javaclasspath (\"-dynamic\");\n%!   assert (clspth2([end-1, end]),\n%!           {canonicalize_file_name(pth1), canonicalize_file_name(pth2)});\n%!   assert (clspth2(1:end-2), clspth1(1:end));\n%! unwind_protect_cleanup\n%!   javarmpath (pth1, pth2);\n%! end_unwind_protect\n\n## Append test with cell array of two strings\n%!testif HAVE_JAVA; usejava (\"jvm\") && isfolder (\"~\")\n%! pth1 = tempdir ();\n%! pth2 = tilde_expand (\"~\");\n%! unwind_protect\n%!   clspth1 = javaclasspath (\"-dynamic\");\n%!   javaaddpath ({pth1, pth2}, \"-end\");\n%!   clspth2 = javaclasspath (\"-dynamic\");\n%!   assert (clspth2([end-1, end]),\n%!           {canonicalize_file_name(pth1), canonicalize_file_name(pth2)});\n%!   assert (clspth2(1:end-2), clspth1(1:end));\n%! unwind_protect_cleanup\n%!   javarmpath (pth1, pth2);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> javaaddpath ()\n%!error <arguments must be strings> javaaddpath (5)\n%!error <arguments must be .* cell array of strings> javaaddpath ({5})\n%!error <CLSPATH does not exist> javaaddpath (\"%_A_Very_Unlikely_Name_%\")\n"
  },
  {
    "path": "scripts/java/javachk.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{msg} =} javachk (@var{feature})\n## @deftypefnx {} {@var{msg} =} javachk (@var{feature}, @var{caller})\n## Check for the presence of the Java @var{feature} in the current session.\n## Return an error structure if @var{feature} is not available, not enabled,\n## or not recognized.\n##\n## Possible recognized features are:\n##\n## @table @asis\n## @item @nospell{@qcode{\"awt\"}}\n## Abstract Window Toolkit for GUIs.\n##\n## @item @qcode{\"desktop\"}\n## Interactive desktop is running.\n##\n## @item @qcode{\"jvm\"}\n## Java Virtual Machine.\n##\n## @item @qcode{\"swing\"}\n## Swing components for lightweight GUIs.\n## @end table\n##\n## If @var{feature} is not supported, a scalar struct with field\n## @qcode{\"message\"} and @qcode{\"identifier\"} is returned.  The field\n## @qcode{\"message\"} contains an error message mentioning @var{feature} as\n## well as the optional user-specified @var{caller}.  This structure is\n## suitable for passing in to the @code{error} function.\n##\n## If @var{feature} is supported and available, an empty struct array is\n## returned with fields @qcode{\"message\"} and @qcode{\"identifier\"}.\n##\n## @code{javachk} determines if specific Java features are available in an\n## Octave session.  This function is provided for scripts which may alter\n## their behavior based on the availability of Java or specific Java runtime\n## features.\n##\n## Compatibility Note: The feature @qcode{\"desktop\"} is never available since\n## Octave has no Java-based desktop.\n##\n## @seealso{usejava, error}\n## @end deftypefn\n\nfunction msg = javachk (feature, caller = \"\")\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! ischar (feature))\n    error (\"javachk: FEATURE must be a string\");\n  elseif (! ischar (caller))\n    error (\"javachk: CALLER must be a string\");\n  endif\n\n  if (isempty (caller))\n    caller = \"this function\";\n  endif\n\n  msg = struct (\"message\", \"\", \"identifier\", \"\");\n\n  ## Check that Octave was compiled with Java support\n  chk = logical (__octave_config_info__ (\"build_features\").JAVA);\n  if (! chk)\n    msg.message = sprintf ([\"javachk: %s is not supported, \" ...\n                            \"Octave was not compiled with Java support\"],\n                            caller);\n    msg.identifier = \"Octave:javachk:java-not-supported\";\n  endif\n\n  if (chk)\n    chk = false;\n    ## For each feature, try methods() on a Java class of a feature\n    switch (feature)\n      case \"awt\"\n        try\n          dum = methods (\"java.awt.Frame\");\n          chk = true;\n        end_try_catch\n      case \"desktop\"\n        ## Octave has no Java based GUI/desktop, leave chk = false\n      case \"jvm\"\n        try\n          dum = methods (\"java.lang.Runtime\");\n          chk = true;\n        end_try_catch\n      case \"swing\"\n        try\n          dum = methods (\"javax.swing.Popup\");\n          chk = true;\n        end_try_catch\n      otherwise\n        ## Unrecognized feature is the same as disabled feature\n    endswitch\n\n    if (! chk)\n      msg.message = sprintf (['javachk: %s is not supported, Java feature '...\n                              '\"%s\" is not available'], caller, feature);\n      msg.identifier = \"Octave:javachk:feature-not-available\";\n    endif\n\n  endif\n\n  if (isempty (msg.message))\n    ## Compatibility: Matlab returns a 0x1 empty struct when javachk passes\n    msg = resize (msg, 0, 1);\n  endif\n\nendfunction\n\n\n%!testif ; ! __octave_config_info__ ().build_features.JAVA\n%! msg = javachk (\"desktop\");\n%! assert (msg.message, \"javachk: this function is not supported, Octave was not compiled with Java support\");\n%! assert (msg.identifier, \"Octave:javachk:java-not-supported\");\n\n%!testif HAVE_JAVA\n%! msg = javachk (\"desktop\");\n%! assert (msg.message, 'javachk: this function is not supported, Java feature \"desktop\" is not available');\n%! assert (msg.identifier, \"Octave:javachk:feature-not-available\");\n\n%!testif HAVE_JAVA\n%! msg = javachk (\"desktop\", \"Java DESKTOP\");\n%! assert (msg.message, 'javachk: Java DESKTOP is not supported, Java feature \"desktop\" is not available');\n%! assert (msg.identifier, \"Octave:javachk:feature-not-available\");\n\n%!testif HAVE_JAVA\n%! msg = javachk (\"nosuchfeature\");\n%! assert (msg.message, 'javachk: this function is not supported, Java feature \"nosuchfeature\" is not available');\n%! assert (msg.identifier, \"Octave:javachk:feature-not-available\");\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! stnul = resize (struct (\"message\", \"\", \"identifier\", \"\"), 0, 1);\n%! assert (javachk (\"jvm\"), stnul);\n\n## Test input validation\n%!error <Invalid call> javachk ()\n%!error <FEATURE must be a string> javachk (1)\n%!error javachk (\"jvm\", 2)\n%!error javachk (\"jvm\", \"feature\", \"ok\")\n"
  },
  {
    "path": "scripts/java/javaclasspath.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} javaclasspath ()\n## @deftypefnx {} {@var{dpath} =} javaclasspath ()\n## @deftypefnx {} {[@var{dpath}, @var{spath}] =} javaclasspath ()\n## @deftypefnx {} {@var{clspath} =} javaclasspath (@var{what})\n## Return the class path of the Java virtual machine in the form of a cell\n## array of strings.\n##\n## If called with no inputs:\n##\n## @itemize\n## @item If no output is requested, the dynamic and static classpaths are\n## printed to the standard output.\n##\n## @item If one output value @var{dpath} is requested, the result is the\n## dynamic classpath.\n##\n## @item If two output values@var{dpath} and @var{spath} are requested, the\n## first variable will contain the dynamic classpath and the second will\n## contain the static classpath.\n## @end itemize\n##\n## If called with a single input parameter @var{what}:\n##\n## @table @asis\n## @item @qcode{\"-dynamic\"}\n## Return the dynamic classpath.\n##\n## @item @qcode{\"-static\"}\n## Return the static classpath.\n##\n## @item @qcode{\"-all\"}\n## Return both the static and dynamic classpath in a single cellstr.\n## @end table\n## @seealso{javaaddpath, javarmpath}\n## @end deftypefn\n\nfunction [path1, path2] = javaclasspath (what = \"\")\n\n  ## dynamic classpath\n  dynamic_path = javaMethod (\"getClassPath\", \"org.octave.ClassHelper\");\n  dynamic_path_list = ostrsplit (dynamic_path, pathsep ());\n\n  ## static classpath\n  static_path = javaMethod (\"getProperty\",\n                            \"java.lang.System\", \"java.class.path\");\n  static_path_list = ostrsplit (static_path, pathsep ());\n  if (numel (static_path_list) > 1)\n    ## remove first element (which is .../octave.jar)\n    static_path_list(1) = [];\n  else\n    static_path_list = {};\n  endif\n\n  if (nargout == 0)\n    if (! nargin)\n      what = \"-all\";\n    endif\n    switch (lower (what))\n      case \"-dynamic\", disp_path_list (\"DYNAMIC\", dynamic_path_list);\n      case \"-static\",  disp_path_list (\"STATIC\", static_path_list);\n      case \"-all\"\n        disp_path_list (\"STATIC\", static_path_list);\n        disp (\"\");\n        disp_path_list (\"DYNAMIC\", dynamic_path_list);\n      otherwise\n        error (\"javaclasspath: invalid value for WHAT\");\n    endswitch\n\n  else\n    if (! nargin)\n      ## This is to allow retrieval of both paths in separate variables with\n      ## a single call to javaclasspath().  Matlab returns only the -dynamic\n      ## path in this case but this won't break compatibility.\n      path1 = cellstr (dynamic_path_list);\n      path2 = cellstr (static_path_list);\n    else\n      switch (lower (what))\n        case \"-all\",     path1 = cellstr ([static_path_list,dynamic_path_list]);\n        case \"-dynamic\", path1 = cellstr (dynamic_path_list);\n        case \"-static\",  path1 = cellstr (static_path_list);\n        otherwise\n          error (\"javaclasspath: invalid value for WHAT\");\n      endswitch\n    endif\n  endif\n\nendfunction\n\n## Display cell array of paths\n\nfunction disp_path_list (what, path_list)\n\n  printf (\"   %s JAVA PATH\\n\\n\", what);\n  if (numel (path_list) > 0)\n    printf (\"      %s\\n\", path_list{:});\n  else\n    printf (\"      - empty -\\n\");\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/java/javamem.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} javamem ()\n## @deftypefnx {} {@var{jmem} =} javamem ()\n## Show the current memory usage of the Java virtual machine (JVM) and run the\n## garbage collector.\n##\n## When no return argument is given the info is printed to the screen.\n## Otherwise, the output cell array @var{jmem} contains Maximum, Total, and\n## Free memory (in bytes).\n##\n## All Java-based routines are run in the JVM's shared memory pool, a\n## dedicated and separate part of memory claimed by the JVM from your\n## computer's total memory (which comprises physical RAM and virtual memory /\n## swap space on hard disk).\n##\n## The maximum allowable memory usage can be configured using the file\n## @file{java.opts}.  The directory where this file resides is determined by\n## the environment variable @w{@env{OCTAVE_JAVA_DIR}}.  If unset, the directory\n## where @file{javaaddpath.m} resides is used instead (typically\n## @file{@w{@env{OCTAVE_HOME}}/share/octave/@w{@env{OCTAVE_VERSION}}/m/java/}).\n##\n## @file{java.opts} is a plain text file with one option per line.  The default\n## initial memory size and default maximum memory size (which are both system\n## dependent) can be overridden like so:\n##\n## @nospell{-Xms64m}\n##\n## @nospell{-Xmx512m}\n##\n## (in megabytes in this example).\n## You can adapt these values to your own requirements if your system has\n## limited available physical memory or if you get Java memory errors.\n##\n## @qcode{\"Total memory\"} is what the operating system has currently assigned\n## to the JVM and depends on actual and active memory usage.\n## @qcode{\"Free memory\"} is self-explanatory.  During operation of Java-based\n## Octave functions the amount of Total and Free memory will vary, due to\n## Java's own cleaning up and your operating system's memory management.\n## @end deftypefn\n\nfunction jmem = javamem ()\n\n  rt = javaMethod (\"getRuntime\", \"java.lang.Runtime\");\n  rt.gc;\n  jvmem = cell (3, 1);\n  jvmem{1} = rt.maxMemory ();\n  jvmem{2} = rt.totalMemory ();\n  jvmem{3} = rt.freeMemory ();\n\n  if (nargout == 0)\n    printf (\"\\nJava virtual machine (JVM) memory info:\\n\");\n    printf (\"Maximum available memory:        %5d MiB;\\n\",\n            jvmem{1} / 1024 / 1024);\n    printf (\"   (...running garbage collector...)\\n\");\n    printf (\"OK, current status:\\n\");\n    printf (\"Total memory in virtual machine: %5d MiB;\\n\",\n            jvmem{2} / 1024 / 1024);\n    printf (\"Free memory in virtual machine:  %5d MiB;\\n\",\n            jvmem{3} / 1024 / 1024);\n    printf (\"%d CPUs available.\\n\", rt.availableProcessors ());\n  else\n    jmem = jvmem;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/java/javarmpath.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} javarmpath (@var{clspath})\n## @deftypefnx {} {} javarmpath (@var{clspath1}, @dots{})\n## @deftypefnx {} {} javarmpath (@{@var{clspath1}, @dots{}@})\n## Remove @var{clspath} from the dynamic class path of the Java virtual\n## machine.\n##\n## @var{clspath} may either be a directory where @file{.class} files are found,\n## or a @file{.jar} file containing Java classes.  Multiple paths may be\n## removed at once by specifying additional arguments, or by using a cell array\n## of strings.\n## @seealso{javaaddpath, javaclasspath}\n## @end deftypefn\n\nfunction javarmpath (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! all (cellfun (@(c) ischar (c) || iscellstr (c), varargin)))\n    error (\"javarmpath: arguments must be strings or cell array of strings\");\n  endif\n\n  for arg = varargin\n    if (iscellstr (arg{1}))\n      arg = arg{1}(:).';  # Guarantee cellstr array is a row vector\n    endif\n\n    for clspath = arg\n      clspath = clspath{1};\n\n      old_path = canonicalize_file_name (tilde_expand (clspath));\n      if (isfolder (old_path))\n        if (old_path(end) != filesep ())\n          old_path = [old_path, filesep()];\n        endif\n      endif\n\n      success = javaMethod (\"removeClassPath\", \"org.octave.ClassHelper\",\n                            old_path);\n\n      if (! success)\n        warning (\"javarmpath: %s: not found in Java classpath\", old_path);\n      endif\n    endfor\n  endfor\n\nendfunction\n\n\n## FIXME: These tests may fail if either TEMPDIR or HOME have already\n##        been added to the Java class path.\n\n## Basic test with single string\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! pth = tempdir ();\n%! unwind_protect\n%!   javaaddpath (pth);\n%!   clspth1 = javaclasspath (\"-dynamic\");\n%!   javarmpath (pth);\n%!   clspth2 = javaclasspath (\"-dynamic\");\n%!   assert (numel (clspth2), numel (clspth1) - 1);\n%!   assert (clspth2(1:end), clspth1(2:end));\n%! unwind_protect_cleanup\n%!   javarmpath (pth);\n%! end_unwind_protect\n\n## Remove two strings\n%!testif HAVE_JAVA; usejava (\"jvm\") && isfolder (\"~\")\n%! pth1 = tempdir ();\n%! pth2 = tilde_expand (\"~\");\n%! unwind_protect\n%!   javaaddpath (pth1, pth2);\n%!   clspth1 = javaclasspath (\"-dynamic\");\n%!   javarmpath (pth1, pth2);\n%!   clspth2 = javaclasspath (\"-dynamic\");\n%!   assert (numel (clspth2), numel (clspth1) - 2);\n%!   assert (clspth2(1:end), clspth1(3:end));\n%! unwind_protect_cleanup\n%!   javarmpath (pth1, pth2);\n%! end_unwind_protect\n\n## Remove cell array of two strings\n%!testif HAVE_JAVA; usejava (\"jvm\") && isfolder (\"~\")\n%! pth1 = tempdir ();\n%! pth2 = tilde_expand (\"~\");\n%! unwind_protect\n%!   javaaddpath (pth1, pth2);\n%!   clspth1 = javaclasspath (\"-dynamic\");\n%!   javarmpath ({pth1, pth2});\n%!   clspth2 = javaclasspath (\"-dynamic\");\n%!   assert (numel (clspth2), numel (clspth1) - 2);\n%!   assert (clspth2(1:end), clspth1(3:end));\n%! unwind_protect_cleanup\n%!   javarmpath (pth1, pth2);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> javarmpath ()\n%!error <arguments must be strings> javarmpath (5)\n%!error <arguments must be .* cell array of strings> javarmpath ({5})\n"
  },
  {
    "path": "scripts/java/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/javaArray.m \\\n  %reldir%/java_get.m \\\n  %reldir%/java_set.m \\\n  %reldir%/javaaddpath.m \\\n  %reldir%/javachk.m \\\n  %reldir%/javaclasspath.m \\\n  %reldir%/javamem.m \\\n  %reldir%/javarmpath.m \\\n  %reldir%/usejava.m\n\nif AMCOND_HAVE_JAVA\n%canon_reldir%_JAR_FILES = %reldir%/octave.jar\n\nJAR_FILES += $(%canon_reldir%_JAR_FILES)\nendif\n\norg_octave_dir = org/octave\n\nif AMCOND_HAVE_JAVA\nJAVA_SRC = \\\n  $(org_octave_dir)/ClassHelper.java \\\n  $(org_octave_dir)/Matrix.java \\\n  $(org_octave_dir)/OctClassLoader.java \\\n  $(org_octave_dir)/Octave.java \\\n  $(org_octave_dir)/OctaveReference.java\nendif\n\nJAVA_CLASSES = $(JAVA_SRC:.java=.class)\n\n%canon_reldir%_JAVA_SRC = $(addprefix %reldir%/, $(JAVA_SRC))\n\n%canon_reldir%_JAVA_CLASSES = $(addprefix %reldir%/, $(JAVA_CLASSES))\n\nOCT_V_JAR = $(oct__v_JAR_$(V))\noct__v_JAR_ = $(oct__v_JAR_$(AM_DEFAULT_VERBOSITY))\noct__v_JAR_0 = @echo \"  JAR     \" $@;\noct__v_JAR_1 =\n\nOCT_V_JAVAC = $(oct__v_JAVAC_$(V))\noct__v_JAVAC_ = $(oct__v_JAVAC_$(AM_DEFAULT_VERBOSITY))\noct__v_JAVAC_0 = @echo \"  JAVAC   \" $@;\noct__v_JAVAC_1 =\n\n$(%canon_reldir%_JAVA_CLASSES) : %.class : %.java | %reldir%/$(octave_dirstamp)\n\t$(OCT_V_JAVAC)$(MKDIR_P) %reldir%/$(org_octave_dir) && \\\n\t( cd $(srcdir)/scripts/java; \\\n\t  \"$(JAVAC)\" -source 8 -target 8 -Xlint:-options \\\n\t             -d $(abs_top_builddir)/scripts/java \\\n\t             $(org_octave_dir)/$(<F) )\n\nif AMCOND_HAVE_JAVA\nJAR_DATE = $(shell $(PERL) -MPOSIX -e 'print strftime (\"%Y-%m-%dT%H:%M:%S+00:00\", gmtime ($(SOURCE_MTIME)))')\n\n%reldir%/octave.jar: $(%canon_reldir%_JAVA_CLASSES)\n\t$(OCT_V_JAR)rm -f $@-t $@ && \\\n\t( cd scripts/java; \\\n\t\tif test \"x$(JAR_SUPPORTS_DATE)\" = \"xyes\"; then \\\n\t\t\t\"$(JAR)\" -c --date=\"$(JAR_DATE)\" -f octave.jar-t $(JAVA_CLASSES) ; \\\n\t\telse \\\n\t\t\t\"$(JAR)\" -c -f octave.jar-t $(JAVA_CLASSES) ; \\\n\t\tfi \\\n\t) && \\\n\tmv $@-t $@\nendif\n\n%canon_reldir%dir = $(fcnfiledir)/java\n\n%canon_reldir%_DATA = \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_JAR_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nscripts_EXTRA_DIST += \\\n  $(%canon_reldir%_JAVA_SRC)\n\nscripts_CLEANFILES += \\\n  $(%canon_reldir%_JAR_FILES) \\\n  $(%canon_reldir%_JAVA_CLASSES)\n"
  },
  {
    "path": "scripts/java/org/octave/ClassHelper.java",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\npackage org.octave;\n\nimport java.lang.reflect.*;\n\npublic class ClassHelper\n{\n  private static OctClassLoader loader;\n\n  static\n  {\n    ClassLoader l = ClassHelper.class.getClassLoader ();\n    loader = (l instanceof OctClassLoader ? (OctClassLoader) l :\n              new OctClassLoader (l));\n  }\n\n\n  /**\n   * Add the given path to the classpath.\n   * @param name String - path to add to the classpath\n   * @param append boolean - if true, append path to classpath, otherwise prepend it.\n   * @return boolean - true if the given path exists and was added to the classpath.\n   * @throws Exception if an error occurs\n   */\n  public static boolean addClassPath (String name, boolean append)\n    throws Exception\n  {\n    boolean found = false;\n    java.io.File f = new java.io.File (name);\n    if (f.exists ())\n      {\n        found = true;\n\n        if (append)\n          {\n            loader.addClassPath (name);\n          }\n        else\n          {\n            // create a completely new class loader because java.net.URLClassLoader appears to have no method to prepend directories to the existing classpath\n\n            // FIXME: is there a more efficient way to do this job?\n\n            java.net.URL[] urls = loader.getURLs ();\n\n            ClassLoader l = ClassHelper.class.getClassLoader ();\n            loader = (l instanceof OctClassLoader ? (OctClassLoader) l :\n                      new OctClassLoader (l));\n\n            loader.addClassPath (name);\n\n            for (int i = 0; i < urls.length; i++)\n              {\n                loader.addURL (urls[i]);\n              }\n          }\n      }\n\n    return (found);\n  }\n\n\n  // new -MH-\n  /**\n   *\n   * @param name String - path to remove from classpath.\n   * @return boolean - true if the given path existed in the classpath before it was removed.\n   * @throws Exception if an error occurs\n   */\n  public static boolean removeClassPath (String name)\n    throws Exception\n  {\n    boolean found = false;\n    java.io.File f = new java.io.File (name);\n    java.net.URL urlToRemove = f.toURI ().toURL ();\n    // save urls in current class path\n    java.net.URL[] urls = loader.getURLs ();\n\n    // create a completely new class loader because java.net.URLClassLoader has no removeClassPath() method\n    ClassLoader l = ClassHelper.class.getClassLoader ();\n    loader = (l instanceof OctClassLoader ? (OctClassLoader) l :\n              new OctClassLoader (l));\n\n    // add the previous urls back, except for the one\n    for (int i = 0; i < urls.length; i++)\n      {\n        java.net.URL url = urls[i];\n        if (!url.equals (urlToRemove))\n          {\n            loader.addURL (url);\n          }\n        else\n          {\n            // path to remove\n            found = true;\n          }\n      }\n\n    return (found);\n  }\n\n\n  public static String getClassPath ()\n  {\n    StringBuilder buf = new StringBuilder();\n    String pathSep = System.getProperty (\"path.separator\");\n    java.net.URL[] urls = loader.getURLs ();\n\n    for (int i = 0; i < urls.length; i++)\n      {\n        try\n          {\n            java.io.File f = new java.io.File (urls[i].toURI ());\n            if (buf.length () > 0)\n              {\n                buf.append (pathSep);\n              }\n            buf.append (f.toString ());\n          }\n        catch (java.net.URISyntaxException ex)\n          {}\n      }\n    return buf.toString ();\n  }\n\n\n  // new -MH-\n  // return list of methods for given class name\n  public static String getMethods (String classname)\n    throws ClassNotFoundException\n  {\n    return (getMethods (Class.forName (classname)));\n  }\n\n\n  // new -MH-\n  // return list of methods for given class instance\n  public static String getMethods (Object obj)\n    throws ClassNotFoundException\n  {\n    return (getMethods (obj.getClass ()));\n  }\n\n\n  // new -MH-\n  // return list of methods for given class\n  public static String getMethods (Class klass)\n  {\n    StringBuilder sb = new StringBuilder();\n    boolean first = true;\n\n    Constructor theConstructor[] = klass.getConstructors ();\n    for (int i = 0; i < theConstructor.length; i++)\n      {\n        if (first)\n          {\n            first = false;\n          }\n        else\n          {\n            sb.append (\";\");\n          }\n\n        sb.append (theConstructor[i].getName ());\n        sb.append (\"(\");\n\n        Class theParameter[] = theConstructor[i].getParameterTypes ();\n        for (int j = 0; j < theParameter.length; j++)\n          {\n            if (j > 0)\n              {\n                sb.append (\", \");\n              }\n            sb.append (theParameter[j].getCanonicalName ());\n          }\n        sb.append (\")\");\n\n        Class theExceptions[] = theConstructor[i].getExceptionTypes ();\n        if (theExceptions.length > 0)\n          {\n            sb.append (\" throws \");\n            for (int j = 0; j < theExceptions.length; j++)\n              {\n                if (j > 0)\n                  {\n                    sb.append (\", \");\n                  }\n                sb.append (theExceptions[j].getCanonicalName ());\n              }\n          }\n      }\n\n    Method theMethod[] = klass.getMethods ();\n    for (int i = 0; i < theMethod.length; i++)\n      {\n        if (first)\n          {\n            first = false;\n          }\n        else\n          {\n            sb.append (\";\");\n          }\n        sb.append (theMethod[i].getReturnType ().getCanonicalName ());\n        sb.append (\" \");\n        sb.append (theMethod[i].getName ());\n        sb.append (\"(\");\n\n        Class theParameter[] = theMethod[i].getParameterTypes ();\n        for (int j = 0; j < theParameter.length; j++)\n          {\n            if (j > 0)\n              {\n                sb.append (\", \");\n              }\n            sb.append (theParameter[j].getCanonicalName ());\n          }\n        sb.append (\")\");\n\n        Class theExceptions[] = theMethod[i].getExceptionTypes ();\n        if (theExceptions.length > 0)\n          {\n            sb.append (\" throws \");\n            for (int j = 0; j < theExceptions.length; j++)\n              {\n                if (j > 0)\n                  {\n                    sb.append (\", \");\n                  }\n                sb.append (theExceptions[j].getCanonicalName ());\n              }\n          }\n      }\n\n    return (sb.toString ());\n  }\n\n\n  // new -MH-\n  // return list of fields for given class\n  public static String getFields (Class klass)\n  {\n    StringBuilder sb = new StringBuilder();\n\n    Field theField[] = klass.getFields ();\n    for (int i = 0; i < theField.length; i++)\n      {\n        if (i > 0)\n          {\n            sb.append (\";\");\n          }\n        sb.append (theField[i].getName ());\n      }\n\n    return (sb.toString ());\n  }\n\n\n  // new -MH-\n  // return list of fields for given class name\n  public static String getFields (String classname)\n    throws ClassNotFoundException\n  {\n    return (getFields (Class.forName (classname)));\n  }\n\n\n  // new -MH-\n  // return list of fields for given class instance\n  public static String getFields (Object obj)\n    throws ClassNotFoundException\n  {\n    return (getFields (obj.getClass ()));\n  }\n\n\n  public static Method findMethod (Class<?> cls, String name, Class<?>[] argTypes)\n  {\n    try\n      {\n        return cls.getMethod (name, argTypes);\n      }\n    catch (Exception e)\n      {\n        Method[] mList = cls.getMethods ();\n        Method m;\n        for (int i = 0; i < mList.length; i++)\n          {\n            m = mList[i];\n            if (m.getName ().equals (name)\n                && m.getParameterTypes ().length == argTypes.length\n                && isCallableFrom (m, argTypes))\n              {\n                return m;\n              }\n          }\n        return null;\n      }\n  }\n\n\n  public static Constructor findConstructor (Class<?> cls, Class<?>[] argTypes)\n  {\n    try\n      {\n        return cls.getConstructor (argTypes);\n      }\n    catch (Exception e)\n      {\n        Constructor[] cList = cls.getConstructors ();\n        //System.out.println(\"# constructors: \" + cList.length);\n        Constructor c;\n        for (int i = 0; i < cList.length; i++)\n          {\n            //System.out.println(\"Considering constructor: \" + cList[i]);\n            c = cList[i];\n            if (c.getParameterTypes ().length == argTypes.length\n                && isCallableFrom (c, argTypes))\n              {\n                return c;\n              }\n          }\n        return null;\n      }\n  }\n\n\n  private static Object invokeMethod (Method m, Object target, Object[] args)\n    throws Exception\n  {\n    try\n      {\n        return m.invoke (target, args);\n      }\n    catch (IllegalAccessException ex)\n      {\n        String mName = m.getName ();\n        Class<?>[] pTypes = m.getParameterTypes ();\n        Class<?> currClass = target.getClass ();\n\n        while (currClass != null)\n          {\n            try\n              {\n                Method meth = currClass.getMethod (mName, pTypes);\n                if (!meth.equals (m))\n                  {\n                    return meth.invoke (target, args);\n                  }\n              }\n            catch (NoSuchMethodException ex2)\n              {}\n            catch (IllegalAccessException ex2)\n              {}\n\n            Class<?>[] ifaceList = currClass.getInterfaces ();\n            for (int i = 0; i < ifaceList.length; i++)\n              {\n                try\n                  {\n                    Method meth = ifaceList[i].getMethod (mName, pTypes);\n                    return meth.invoke (target, args);\n                  }\n                catch (NoSuchMethodException ex2)\n                  {}\n                catch (IllegalAccessException ex2)\n                  {}\n              }\n\n            currClass = currClass.getSuperclass ();\n          }\n\n        throw ex;\n      }\n  }\n\n\n  public static Object invokeMethod (Object target, String name,\n                                     Object[] args, Class[] argTypes)\n    throws Throwable\n  {\n    Method m = findMethod (target.getClass (), name, argTypes);\n    if (m != null)\n      {\n        try\n          {\n            Object result = invokeMethod (m, target,\n                                          castArguments (args, argTypes,\n                                                         m.getParameterTypes ()));\n            return result;\n          }\n        catch (InvocationTargetException ex)\n          {\n            throw ex.getCause ();\n          }\n      }\n    else\n      {\n        throw new NoSuchMethodException (name);\n      }\n  }\n\n\n  public static Object invokeStaticMethod (String cls, String name,\n                                           Object[] args, Class[] argTypes)\n    throws Throwable\n  {\n    Method m = findMethod (Class.forName (cls, true, loader), name,\n                           argTypes);\n    if (m != null)\n      {\n        try\n          {\n            Object result = m.invoke (null,\n                                      castArguments (args, argTypes,\n                                                     m.getParameterTypes ()));\n            return result;\n          }\n        catch (InvocationTargetException ex)\n          {\n            throw ex.getCause ();\n          }\n      }\n    else\n      {\n        throw new NoSuchMethodException (name);\n      }\n  }\n\n\n  public static Object invokeConstructor (String cls, Object[] args,\n                                          Class[] argTypes)\n    throws Throwable\n  {\n    Constructor c = findConstructor (Class.forName (cls, true, loader),\n                                     argTypes);\n    if (c != null)\n      {\n        try\n          {\n            Object result = c.newInstance (castArguments (args, argTypes,\n                                                          c.getParameterTypes ()));\n            return result;\n          }\n        catch (InvocationTargetException ex)\n          {\n            throw ex.getCause ();\n          }\n      }\n    else\n      {\n        throw new NoSuchMethodException (cls);\n      }\n  }\n\n\n  public static Object getField (Object target, String name)\n    throws Throwable\n  {\n    try\n      {\n        Field f = target.getClass ().getField (name);\n        return f.get (target);\n      }\n    catch (NoSuchFieldException ex)\n      {\n        try\n          {\n            return invokeMethod (target, name, new Object[0], new Class[0]);\n          }\n        catch (NoSuchMethodException ex2)\n          {\n            throw ex;\n          }\n      }\n  }\n\n\n  public static Object getStaticField (String cls, String name)\n    throws Throwable\n  {\n    try\n      {\n        Field f = Class.forName (cls, true, loader).getField (name);\n        return f.get (null);\n      }\n    catch (NoSuchFieldException ex)\n      {\n        try\n          {\n            return invokeStaticMethod (cls, name, new Object[0], new Class[0]);\n          }\n        catch (NoSuchMethodException ex2)\n          {\n            throw ex;\n          }\n      }\n  }\n\n\n  public static void setField (Object target, String name, Object value)\n    throws Exception\n  {\n    Field f = target.getClass ().getField (name);\n    f.set (target, castArgument (value, value.getClass (), f.getType ()));\n  }\n\n\n  public static void setStaticField (String cls, String name, Object value)\n    throws Exception\n  {\n    Field f = Class.forName (cls, true, loader).getField (name);\n    f.set (null, castArgument (value, value.getClass (), f.getType ()));\n  }\n\n\n  private static boolean isCallableFrom (Method m, Class[] argTypes)\n  {\n    Class[] expTypes = m.getParameterTypes ();\n    for (int i = 0; i < argTypes.length; i++)\n      {\n        if (!isCallableFrom (expTypes[i], argTypes[i]))\n          {\n            return false;\n          }\n      }\n    return true;\n  }\n\n\n  private static boolean isCallableFrom (Constructor c, Class[] argTypes)\n  {\n    Class[] expTypes = c.getParameterTypes ();\n    for (int i = 0; i < argTypes.length; i++)\n      {\n        if (!isCallableFrom (expTypes[i], argTypes[i]))\n          {\n            return false;\n          }\n      }\n    return true;\n  }\n\n\n  private static boolean isCallableFrom (Class<?> expCls, Class<?> argCls)\n  {\n    //System.out.println(\"isCallableFrom: \"+expCls.getCanonicalName() + \" <=? \" + argCls.getCanonicalName());\n    if (argCls == null)\n      {\n        return!expCls.isPrimitive ();\n      }\n    else if (expCls.isAssignableFrom (argCls))\n      {\n        return true;\n      }\n    else if ((isNumberClass (expCls) || isBooleanClass (expCls))\n             && isNumberClass (argCls))\n      {\n        return true;\n      }\n    else if (isCharClass (expCls) && argCls.equals (Character.class))\n      {\n        /*\n          modified into a more strict check to avoid char to string matching\n          to avoid matching method signatureslike\n          java_method(char) with octave_call('a String')\n        */\n        return true;\n      }\n    else if (isStringClass (expCls) && argCls.equals (String.class))\n      {\n        /*\n          added for strict String to String matching\n          java_method(String) with octave_call('a String')\n          but not\n          java_method(char) with octave_call('a String')\n        */\n        return true;\n      }\n    else if (expCls.isArray () && argCls.isArray ()\n             && isCallableFrom (expCls.getComponentType (),\n                                argCls.getComponentType ()))\n      {\n        return true;\n      }\n    else if (expCls.equals (Object.class) && argCls.isPrimitive ())\n      {\n        return true;\n      }\n    else\n      {\n        return false;\n      }\n  }\n\n\n  private static boolean isNumberClass (Class cls)\n  {\n    return (cls.equals (Integer.TYPE) || cls.equals (Integer.class)\n            || cls.equals (Short.TYPE) || cls.equals (Short.class)\n            || cls.equals (Long.TYPE) || cls.equals (Long.class)\n            || cls.equals (Float.TYPE) || cls.equals (Float.class)\n            || cls.equals (Double.TYPE) || cls.equals (Double.class));\n  }\n\n\n  private static boolean isBooleanClass (Class cls)\n  {\n    return (cls.equals (Boolean.class) || cls.equals (Boolean.TYPE));\n  }\n\n\n  private static boolean isCharClass (Class cls)\n  {\n    return (cls.equals (Character.class) || cls.equals (Character.TYPE));\n  }\n\n\n  /**\n   * Check whether the supplied class is a String class.\n   *\n   * Added for more strict char/string matching of method signatures\n   * @param cls Class - the class to check\n   * @return boolean - true if clas is of class java.lang.String\n   */\n  private static boolean isStringClass (Class cls)\n  {\n    return (\n            cls.equals (String.class)\n            );\n  }\n\n\n  private static Object[] castArguments (Object[] args, Class[] argTypes,\n                                         Class[] expTypes)\n  {\n    for (int i = 0; i < args.length; i++)\n      {\n        args[i] = castArgument (args[i], argTypes[i], expTypes[i]);\n      }\n    return args;\n  }\n\n\n  private static Object castArgument (Object obj, Class<?> type, Class<?> expType)\n  {\n    // System.out.println(\"expType:\"+expType.getCanonicalName() + \" <= type:\" + type.getCanonicalName());\n    if (type == null || expType.isAssignableFrom (type))\n      {\n        return obj;\n      }\n    else if (isNumberClass (expType))\n      {\n        if (expType.equals (Integer.TYPE) || expType.equals (Integer.class))\n          {\n            return Integer.valueOf (((Number) obj).intValue ());\n          }\n        else if (expType.equals (Double.TYPE) || expType.equals (Double.class))\n          {\n            return Double.valueOf (((Number) obj).doubleValue ());\n          }\n        else if (expType.equals (Short.TYPE) || expType.equals (Short.class))\n          {\n            return Short.valueOf (((Number) obj).shortValue ());\n          }\n        else if (expType.equals (Long.TYPE) || expType.equals (Long.class))\n          {\n            return Long.valueOf (((Number) obj).longValue ());\n          }\n        else if (expType.equals (Float.TYPE) || expType.equals (Float.class))\n          {\n            return Float.valueOf (((Number) obj).floatValue ());\n          }\n      }\n    else if (isBooleanClass (expType))\n      {\n        return Boolean.valueOf (((Number) obj).intValue () != 0);\n      }\n    else if (isCharClass (expType))\n      {\n        String s = obj.toString ();\n        if (s.length () != 1)\n          {\n            throw new ClassCastException (\"cannot cast \" + s + \" to character\");\n          }\n        return Character.valueOf (s.charAt (0));\n      }\n    else if (expType.isArray () && type.isArray ())\n      {\n        return castArray (obj, type.getComponentType (),\n                          expType.getComponentType ());\n      }\n    else if (type.isPrimitive ())\n      {\n        return obj;\n      }\n    return null;\n  }\n\n\n  private static Object castArray (Object obj, Class elemType,\n                                   Class elemExpType)\n  {\n    int len = Array.getLength (obj);\n    Object result = Array.newInstance (elemExpType, len);\n    for (int i = 0; i < len; i++)\n      {\n        Array.set (result, i,\n                   castArgument (Array.get (obj, i), elemType, elemExpType));\n      }\n    return result;\n  }\n\n\n  private static int getArrayClassNDims (Class cls)\n  {\n    if (cls != null && cls.isArray ())\n      {\n        return (1 + getArrayClassNDims (cls.getComponentType ()));\n      }\n    else\n      {\n        return 0;\n      }\n  }\n\n\n  private static Class getArrayElemClass (Class cls)\n  {\n    if (cls.isArray ())\n      {\n        return getArrayElemClass (cls.getComponentType ());\n      }\n    else\n      {\n        return cls;\n      }\n  }\n\n\n  private static Object getArrayElements (Object array, int[][] idx,\n                                          int offset,\n                                          int ndims, Class elemType)\n  {\n    if (offset >= ndims)\n      {\n        Object elem = Array.get (array, idx[offset][0]);\n        if (offset < idx.length - 1)\n          {\n            return getArrayElements (elem, idx, offset + 1, ndims, elemType);\n          }\n        else\n          {\n            return elem;\n          }\n      }\n    else\n      {\n        Class compType = elemType.getComponentType ();\n        Object retval = Array.newInstance (compType, idx[offset].length);\n        for (int i = 0; i < idx[offset].length; i++)\n          {\n            Object elem = Array.get (array, idx[offset][i]);\n            if (offset < idx.length - 1)\n              {\n                elem = getArrayElements (elem, idx, offset + 1, ndims, compType);\n              }\n            Array.set (retval, i, elem);\n          }\n        return retval;\n      }\n  }\n\n\n  public static Object arraySubsref (Object obj, int[][] idx)\n    throws Exception\n  {\n    if (!obj.getClass ().isArray ())\n      {\n        throw new IllegalArgumentException (\"not a Java array\");\n      }\n\n    if (idx.length == 1)\n      {\n        if (idx[0].length == 1)\n          {\n            return Array.get (obj, idx[0][0]);\n          }\n        else\n          {\n            Object retval = Array.newInstance (obj.getClass ().\n                                               getComponentType (),\n                                               idx[0].length);\n            for (int i = 0; i < idx[0].length; i++)\n              {\n                Array.set (retval, i, Array.get (obj, idx[0][i]));\n              }\n            return retval;\n          }\n      }\n    else\n      {\n        int[] dims = new int[idx.length];\n        for (int i = 0; i < idx.length; i++)\n          {\n            dims[i] = idx[i].length;\n          }\n\n        if (dims.length != getArrayClassNDims (obj.getClass ()))\n          {\n            throw new IllegalArgumentException (\"index size mismatch\");\n          }\n\n        /* resolve leading singletons */\n        Object theObj = obj;\n        int offset = 0;\n        while (dims[offset] == 1)\n          {\n            theObj = Array.get (theObj, idx[offset][0]);\n            offset = offset + 1;\n            if (offset >= dims.length)\n              {\n                return theObj;\n              }\n          }\n        if (offset > 0)\n          {\n            int[][] new_idx = new int[idx.length - offset][];\n            System.arraycopy (idx, offset, new_idx, 0, idx.length - offset);\n            return arraySubsref (theObj, new_idx);\n          }\n\n        /* chop trailing singletons */\n        int ndims = dims.length;\n        while (ndims > 1 && dims[ndims - 1] == 1)\n          {\n            ndims--;\n          }\n\n        /* create result array */\n        Class elemClass = theObj.getClass ();\n        for (int i = 0; i <= (dims.length - ndims); i++)\n          {\n            elemClass = elemClass.getComponentType ();\n          }\n        Object retval = Array.newInstance (elemClass, dims[0]);\n\n        /* fill-in array */\n        for (int i = 0; i < idx[0].length; i++)\n          {\n            Object elem = getArrayElements (Array.get (theObj, idx[0][i]),\n                                            idx, 1, ndims, elemClass);\n            Array.set (retval, i, elem);\n          }\n\n        return retval;\n      }\n  }\n\n\n  private static Object setArrayElements (Object array, int[][] idx,\n                                          int offset, int ndims, Object rhs)\n    throws Exception\n  {\n    if (offset >= ndims)\n      {\n        if (offset < idx.length - 1)\n          {\n            setArrayElements (Array.get (array, idx[offset][0]), idx,\n                              offset + 1, ndims, rhs);\n          }\n        else\n          {\n            Array.set (array, idx[offset][0], rhs);\n          }\n        return array;\n      }\n    else\n      {\n        for (int i = 0; i < idx[offset].length; i++)\n          {\n            if (offset < idx.length - 1)\n              {\n                setArrayElements (Array.get (array, idx[offset][i]), idx,\n                                  offset + 1, ndims, Array.get (rhs, i));\n              }\n            else\n              {\n                Array.set (array, idx[offset][i], Array.get (rhs, i));\n              }\n          }\n        return array;\n      }\n  }\n\n\n  public static Object arraySubsasgn (Object obj, int[][] idx, Object rhs)\n    throws Exception\n  {\n    if (!obj.getClass ().isArray ())\n      {\n        throw new IllegalArgumentException (\"not a Java array\");\n      }\n\n    if (idx.length == 1)\n      {\n        if (idx[0].length == 1)\n          {\n            Array.set (obj, idx[0][0], rhs);\n          }\n        else\n          {\n            for (int i = 0; i < idx[0].length; i++)\n              {\n                Array.set (obj, idx[0][i], Array.get (rhs, i));\n              }\n          }\n        return obj;\n      }\n    else\n      {\n        int[] dims = new int[idx.length];\n        for (int i = 0; i < idx.length; i++)\n          {\n            dims[i] = idx[i].length;\n          }\n\n        if (dims.length != getArrayClassNDims (obj.getClass ()))\n          {\n            throw new IllegalArgumentException (\"index size mismatch\");\n          }\n\n        /* resolve leading singletons */\n        Object theObj = obj;\n        int offset = 0;\n        while (dims[offset] == 1 && offset < (dims.length - 1))\n          {\n            theObj = Array.get (theObj, idx[offset][0]);\n            offset = offset + 1;\n          }\n        if (offset > 0)\n          {\n            int[][] new_idx = new int[idx.length - offset][];\n            System.arraycopy (idx, offset, new_idx, 0, idx.length - offset);\n            arraySubsasgn (theObj, new_idx, rhs);\n            return obj;\n          }\n\n        /* chop trailing singletons */\n        int ndims = dims.length;\n        while (ndims > 1 && dims[ndims - 1] == 1)\n          {\n            ndims--;\n          }\n\n        for (int i = 0; i < idx[0].length; i++)\n          {\n            setArrayElements (Array.get (theObj, idx[0][i]), idx, 1, ndims,\n                              Array.get (rhs, i));\n          }\n\n        return obj;\n      }\n  }\n\n\n  public static Object createArray (Object cls, int[] dims)\n    throws Exception\n  {\n    Class theClass;\n    if (cls instanceof Class)\n      {\n        theClass = (Class) cls;\n      }\n    else if (cls instanceof String)\n      {\n        theClass = Class.forName ((String) cls, true, loader);\n      }\n    else\n      {\n        throw new IllegalArgumentException (\"invalid class specification \" +\n                                            cls);\n      }\n\n    return Array.newInstance (theClass, dims);\n  }\n\n\n  public static Object createArray (Object cls, int length)\n    throws Exception\n  {\n    return createArray (cls, new int[] {length});\n  }\n}\n"
  },
  {
    "path": "scripts/java/org/octave/Matrix.java",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\npackage org.octave;\n\nimport java.nio.*;\nimport java.text.DecimalFormat;\n\npublic class Matrix\n{\n  private int[] dims;\n  private Buffer data;\n  private Object cache = null;\n\n  public Matrix ()\n  {\n    this (new double[0], new int[] {0, 0});\n  }\n\n  public Matrix (double[] data)\n  {\n    this (data, new int[] {1, data.length});\n  }\n\n  public Matrix (double[][] data)\n  {\n    int m = data.length;\n    int n = (m > 0 ? data[0].length : 0);\n    int idx = 0;\n    double[] buf = new double[m*n];\n\n    for (int j = 0; j < n; j++)\n      for (int i = 0; i < m; i++)\n        buf[idx++] = data[i][j];\n    this.data = DoubleBuffer.wrap(buf);\n    this.dims = new int[] {m, n};\n    this.cache = data;\n  }\n\n  public Matrix (double[][][] data)\n  {\n    int m = data.length;\n    int n = (m > 0 ? data[0].length : 0);\n    int p = (n > 0 ? data[0][0].length : 0);\n    int idx = 0;\n    double[] buf = new double[m*n*p];\n\n    for (int k = 0; k < p; k++)\n      for (int j = 0; j < n; j++)\n        for (int i = 0; i < m; i++)\n          buf[idx++] = data[i][j][k];\n    this.data = DoubleBuffer.wrap(buf);\n    this.dims = new int[] {m, n, p};\n    this.cache = data;\n  }\n\n  public Matrix (double[] data, int[] dims)\n  {\n    this.dims = dims;\n    this.data = DoubleBuffer.wrap(data);\n  }\n\n  public Matrix (byte[] data, int[] dims)\n  {\n    this.dims = dims;\n    this.data = ByteBuffer.wrap(data);\n  }\n\n  public Matrix (int[] data, int[] dims)\n  {\n    this.dims = dims;\n    this.data = IntBuffer.wrap(data);\n  }\n\n  public double[] toDouble ()\n  {\n    if (data instanceof DoubleBuffer)\n      return ((DoubleBuffer)data).array ();\n    else\n      throw new ClassCastException (\"matrix is not of type 'double'\");\n  }\n\n  public byte[] toByte ()\n  {\n    if (data instanceof ByteBuffer)\n      return ((ByteBuffer)data).array ();\n    else\n      throw new ClassCastException (\"matrix is not of type 'byte'\");\n  }\n\n  public int[] toInt ()\n  {\n    if (data instanceof IntBuffer)\n      return ((IntBuffer)data).array ();\n    else\n      throw new ClassCastException (\"matrix is not of type 'integer'\");\n  }\n\n  public int getNDims ()\n  {\n    return (dims == null ? 0 : dims.length);\n  }\n\n  public int getDim (int index)\n  {\n    return (dims == null || index < 0 || index >= dims.length ? -1 : dims[index]);\n  }\n\n  public int[] getDims ()\n  {\n    return dims;\n  }\n\n  public String getClassName ()\n  {\n    if (data instanceof DoubleBuffer)\n      return \"double\";\n    else if (data instanceof IntBuffer)\n      return \"integer\";\n    else if (data instanceof ByteBuffer)\n      return \"byte\";\n    else\n      return \"unknown\";\n  }\n\n  public String toString ()\n  {\n    if (dims == null || data == null)\n      return \"null\";\n\n    String s = \"\";\n\n    if (dims.length == 2 && dims[0] == 1 && dims[1] <= 5)\n      {\n        if (data instanceof DoubleBuffer)\n          {\n            DoubleBuffer b = (DoubleBuffer)data;\n            DecimalFormat fmt = new DecimalFormat (\"0.0000 \");\n            for (int i = 0; i < b.capacity (); i++)\n              s += fmt.format (b.get (i));\n          }\n        else if (data instanceof IntBuffer)\n          {\n            IntBuffer b = (IntBuffer)data;\n            for (int i = 0; i < b.capacity (); i++)\n              s += (Integer.toString (b.get (i)) + \" \");\n          }\n        else if (data instanceof ByteBuffer)\n          {\n            ByteBuffer b = (ByteBuffer)data;\n            for (int i = 0; i < b.capacity (); i++)\n              s += (Byte.toString (b.get (i)) + \" \");\n          }\n        s = (\"[ \" + s + \"]\");\n      }\n    else if (dims.length == 2 && dims[0] == 0 && dims[1] == 0)\n      s = \"[ ]\";\n    else\n      {\n        for (int i = 0; i < dims.length; i++)\n          if (i == 0)\n            s = Integer.toString (dims[i]);\n          else\n            s += (\" by \" + Integer.toString (dims[i]));\n        s = (\"[ (\" + s + \") array of \" + getClassName () + \" ]\");\n      }\n\n    return s;\n  }\n\n  public static Object ident (Object o)\n  {\n    System.out.println (o);\n    return o;\n  }\n\n  public boolean equals (Object value)\n  {\n    if (value instanceof Matrix)\n      {\n        Matrix m = (Matrix)value;\n        if (!java.util.Arrays.equals (dims, m.dims))\n          return false;\n        return data.equals (m.data);\n      }\n    else\n      return false;\n  }\n\n  public boolean isEmpty ()\n  {\n    return (data == null || dims == null || data.capacity () == 0);\n  }\n\n  public boolean isVector ()\n  {\n    return (dims.length == 1 ||\n            (dims.length == 2 && (dims[0] == 1 || dims[1] == 1 ||\n                                  (dims[0] == 0 && dims[1] == 0))));\n  }\n\n  public int getLength ()\n  {\n    return data.capacity ();\n  }\n\n  public double[] asDoubleVector ()\n  {\n    if (data instanceof DoubleBuffer)\n      return toDouble ();\n    else\n      System.out.println (\"Warning: invalid conversion to double vector\");\n    return null;\n  }\n\n  public double[][] asDoubleMatrix ()\n  {\n    if (cache != null)\n      {\n        try { return (double[][])cache; }\n        catch (ClassCastException e) { }\n      }\n\n    if (data instanceof DoubleBuffer && dims.length == 2)\n      {\n        double[][] m = new double[dims[0]][dims[1]];\n        double[] data = ((DoubleBuffer)this.data).array ();\n        int idx = 0;\n        if (data.length > 0)\n          for (int j = 0; j < m[0].length; j++)\n            for (int i = 0; i < m.length; i++)\n              m[i][j] = data[idx++];\n        cache = m;\n        return m;\n      }\n    else\n      System.out.println (\"Warning: invalid conversion to double matrix\");\n\n    return null;\n  }\n\n  public double[][][] asDoubleMatrix3 ()\n  {\n    if (cache != null)\n      {\n        try { return (double[][][])cache; }\n        catch (ClassCastException e) { }\n      }\n\n    if (data instanceof DoubleBuffer && dims.length == 3)\n      {\n        double[][][] m = new double[dims[0]][dims[1]][dims[2]];\n        double[] data = ((DoubleBuffer)this.data).array ();\n        int idx = 0;\n        if (data.length > 0)\n          for (int k = 0; k < dims[2]; k++)\n            for (int j = 0; j < dims[1]; j++)\n              for (int i = 0; i < dims[0]; i++)\n                m[i][j][k] = data[idx++];\n        cache = m;\n        return m;\n      }\n    else\n      System.out.println (\"Warning: invalid conversion to double array\");\n\n    return null;\n  }\n\n  public int[][] asIntMatrix ()\n  {\n    if (cache != null)\n      {\n        try { return (int[][])cache; }\n        catch (ClassCastException e) { }\n      }\n\n    if (data instanceof IntBuffer && dims.length == 2)\n      {\n        int[][] m = new int[dims[0]][dims[1]];\n        int[] data = ((IntBuffer)this.data).array ();\n        int idx = 0;\n        if (data.length > 0)\n          for (int j = 0; j < m[0].length; j++)\n            for (int i = 0; i < m.length; i++)\n              m[i][j] = data[idx++];\n        cache = m;\n        return m;\n      }\n    else\n      System.out.println (\"Warning: invalid conversion to integer matrix\");\n\n    return null;\n  }\n\n  public double minValue ()\n  {\n    double val = Double.POSITIVE_INFINITY;\n\n    if (data instanceof DoubleBuffer)\n      {\n        double[] buf = ((DoubleBuffer)data).array ();\n        for (int i = 0; i < buf.length; i++)\n          if (buf[i] < val)\n            val = buf[i];\n      }\n    else if (data instanceof ByteBuffer)\n      {\n        byte[] buf = ((ByteBuffer)data).array ();\n        for (int i = 0; i < buf.length; i++)\n          if (buf[i] < val)\n            val = buf[i];\n      }\n    else\n      System.out.println (\"Warning: cannot compute min value for array of type '\" + getClassName () + \"'\");\n\n    return val;\n  }\n\n  public double maxValue ()\n  {\n    double val = Double.NEGATIVE_INFINITY;\n\n    if (data instanceof DoubleBuffer)\n      {\n        double[] buf = ((DoubleBuffer)data).array ();\n        for (int i = 0; i < buf.length; i++)\n          if (buf[i] > val)\n            val = buf[i];\n      }\n    else if (data instanceof ByteBuffer)\n      {\n        byte[] buf = ((ByteBuffer)data).array ();\n        for (int i = 0; i <buf.length; i++)\n          if (buf[i] > val)\n            val = buf[i];\n      }\n    else\n      System.out.println (\"Warning: cannot compute max value for array of type '\" + getClassName () + \"'\");\n\n    return val;\n  }\n}\n"
  },
  {
    "path": "scripts/java/org/octave/OctClassLoader.java",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\npackage org.octave;\n\nimport java.io.File;\n\npublic class OctClassLoader extends java.net.URLClassLoader\n{\n  public OctClassLoader ()\n  {\n    super (new java.net.URL[0]);\n  }\n\n  public OctClassLoader (ClassLoader parent)\n  {\n    super (new java.net.URL[0], parent);\n  }\n\n  protected Class findClass (String name) throws ClassNotFoundException\n  {\n    //System.out.println (\"Looking for class \" + name);\n    return super.findClass (name);\n  }\n\n  protected String findLibrary (String libname)\n  {\n    // Look dynamically into java.library.path, because Sun VM does\n    // not do it (seems to cache initial java.library.path instead)\n\n    String[] paths = System.getProperty (\"java.library.path\").split (File.pathSeparator);\n\n    libname = System.mapLibraryName (libname);\n    for (int i = 0; i < paths.length; i++)\n      {\n        File f = new File (paths[i], libname);\n        if (f.exists ())\n          return f.getAbsolutePath ();\n      }\n\n    return null;\n  }\n\n  public void addClassPath (String name) throws Exception\n  {\n    java.io.File f = new java.io.File (name);\n    addURL (f.toURI ().toURL ());\n  }\n\n  // new -MH-\n  public void addURL (java.net.URL url)\n  {\n    super.addURL (url);\n  }\n}\n"
  },
  {
    "path": "scripts/java/org/octave/Octave.java",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\npackage org.octave;\n\nimport java.util.*;\n\npublic class Octave\n{\n  private static Object notifyObject = null;\n  private static Object[] args = null;\n  private static LinkedList<Object> invokeList = new LinkedList<Object> ();\n  private static LinkedList<Object> waitList = new LinkedList<Object> ();\n\n  public native static boolean call (String name, Object[] argin, Object[] argout);\n  public native static void doInvoke (int ID, Object[] args);\n  public native static void doEvalString (String cmd);\n  public native static boolean needThreadedInvokation ();\n\n  public static void checkPendingAction ()\n  {\n    if (notifyObject != null)\n      {\n        synchronized (notifyObject)\n          {\n            if (notifyObject instanceof OctaveReference)\n              doInvoke (((OctaveReference)notifyObject).getID (), args);\n            else if (notifyObject instanceof String)\n              doEvalString ((String)notifyObject);\n            notifyObject.notifyAll ();\n          }\n        notifyObject = null;\n        args = null;\n      }\n\n    Object obj;\n    Object[] objArgs;\n\n    while (true)\n      {\n        obj = null;\n        objArgs = null;\n\n        synchronized (invokeList)\n          {\n            if (invokeList.size () > 0)\n              {\n                obj = invokeList.remove ();\n                if (obj instanceof OctaveReference)\n                  objArgs = (Object[])invokeList.remove ();\n              }\n          }\n\n        if (obj != null)\n          {\n            if (obj instanceof Runnable)\n              ((Runnable)obj).run ();\n            else if (obj instanceof OctaveReference)\n              doInvoke (((OctaveReference)obj).getID (), objArgs);\n            else if (obj instanceof String)\n              doEvalString ((String)obj);\n          }\n        else\n          break;\n      }\n    /*\n      synchronized (invokeList)\n      {\n      while (invokeList.size () > 0)\n      {\n      Object obj = invokeList.remove ();\n      if (obj instanceof Runnable)\n      ((Runnable)obj).run ();\n      if (obj instanceof OctaveReference)\n      {\n      Object[] objArgs = (Object[])invokeList.remove ();\n      doInvoke (((OctaveReference)obj).getID (), objArgs);\n      }\n      else if (obj instanceof String)\n      doEvalString ((String)obj);\n      }\n      }\n    */\n  }\n\n  private static void checkWaitState ()\n  {\n    if (waitList.size () > 0)\n      {\n        Object wObj = waitList.getFirst ();\n        synchronized (wObj)\n          {\n            wObj.notifyAll ();\n          }\n      }\n  }\n\n  public static void invokeAndWait (OctaveReference ref, Object[] invokeArgs)\n  {\n    if (needThreadedInvokation ())\n      {\n        synchronized (ref)\n          {\n            notifyObject = ref;\n            args = invokeArgs;\n            try { checkWaitState (); ref.wait (); }\n            catch (InterruptedException e) {}\n          }\n      }\n    else\n      doInvoke (ref.getID (), invokeArgs);\n  }\n\n  public static void evalAndWait (String cmd)\n  {\n    if (needThreadedInvokation ())\n      {\n        synchronized (cmd)\n          {\n            notifyObject = cmd;\n            args = null;\n            try { checkWaitState (); cmd.wait (); }\n            catch (InterruptedException e) {}\n          }\n      }\n    else\n      doEvalString (cmd);\n  }\n\n  public static void invokeLater (Runnable r)\n  {\n    if (needThreadedInvokation ())\n      synchronized (invokeList)\n        {\n          invokeList.add (r);\n          checkWaitState ();\n        }\n    else\n      r.run ();\n  }\n\n  public static void invokeLater (OctaveReference ref, Object[] invokeArgs)\n  {\n    if (needThreadedInvokation ())\n      synchronized (invokeList)\n        {\n          invokeList.add (ref);\n          invokeList.add (invokeArgs);\n          checkWaitState ();\n        }\n    else\n      doInvoke (ref.getID (), invokeArgs);\n  }\n\n  public static void evalLater (String cmd)\n  {\n    if (needThreadedInvokation ())\n      synchronized (invokeList)\n        {\n          invokeList.add (cmd);\n          checkWaitState ();\n        }\n    else\n      doEvalString (cmd);\n  }\n\n  public static void waitFor (Object wObj)\n  {\n    waitList.add (0, wObj);\n    synchronized (wObj)\n      {\n        while (waitList.size () > 0 && waitList.getFirst () == wObj)\n          {\n            try { wObj.wait (); }\n            catch (InterruptedException e) {}\n            checkPendingAction ();\n          }\n      }\n  }\n\n  public static void endWaitFor (Object obj)\n  {\n    boolean isCurrentWaitObject = (waitList.size () > 0 && waitList.getFirst () == obj);\n\n    waitList.remove (obj);\n    if (needThreadedInvokation () && isCurrentWaitObject)\n      synchronized (obj)\n        {\n          obj.notifyAll ();\n        }\n  }\n\n  public static Object do_test (String name, Object arg0) throws Exception\n  {\n    Object[] argin = new Object[] { arg0 };\n    Object[] argout = new Object[1];\n    if (call (name, argin, argout))\n      return argout[0];\n    throw new Exception (\"octave call failed\");\n  }\n}\n"
  },
  {
    "path": "scripts/java/org/octave/OctaveReference.java",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2007-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\npackage org.octave;\n\nimport java.lang.ref.Cleaner;\n\npublic class OctaveReference\n{\n  private static final Cleaner CLEANER = Cleaner.create ();\n\n  private int ID;\n\n  private native static void doFinalize (int ID);\n\n  public OctaveReference (int ID)\n  {\n    this.ID = ID;\n\n    CLEANER.register (this, () -> doFinalize (ID) );\n  }\n\n  public String toString ()\n  {\n    return (\"<octave reference \" + this.ID + \">\");\n  }\n\n  public int getID ()\n  {\n    return this.ID;\n  }\n\n  public Object invoke (Object[] args)\n  {\n    //System.out.println (\"OctaveReference::invoke\");\n    Octave.doInvoke (this.ID, args);\n    return null;\n  }\n\n  public synchronized Object invokeAndWait (Object[] args)\n  {\n    //System.out.println (\"OctaveReference::invokeandWait\");\n    Octave.invokeAndWait (this, args);\n    return null;\n  }\n}\n"
  },
  {
    "path": "scripts/java/usejava.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} usejava (@var{feature})\n## Return true if the Java element @var{feature} is available.\n##\n## Possible features are:\n##\n## @table @asis\n## @item @nospell{@qcode{\"awt\"}}\n## Abstract Window Toolkit for GUIs.\n##\n## @item @qcode{\"desktop\"}\n## Interactive desktop is running.\n##\n## @item @qcode{\"jvm\"}\n## Java Virtual Machine.\n##\n## @item @qcode{\"swing\"}\n## Swing components for lightweight GUIs.\n## @end table\n##\n## @code{usejava} determines if specific Java features are available in an\n## Octave session.  This function is provided for scripts which may alter\n## their behavior based on the availability of Java.  The feature\n## @qcode{\"desktop\"} always returns @code{false} as Octave has no Java-based\n## desktop.  Other features may be available if Octave was compiled with the\n## Java Interface and Java is installed.\n## @seealso{javachk}\n## @end deftypefn\n\nfunction tf = usejava (feature)\n\n  if (nargin < 1 || ! ischar (feature))\n    print_usage ();\n  endif\n\n  tf = false;\n\n  switch (feature)\n    ## For each feature, try methods() on a Java class of a feature\n    case \"awt\"\n      try\n        dum = methods (\"java.awt.Frame\");\n        tf = ! javaMethod (\"isHeadless\", \"java.awt.GraphicsEnvironment\");\n      end_try_catch\n    case \"desktop\"\n      ## Octave has no Java based GUI/desktop, leave tf = false\n    case \"jvm\"\n      try\n        dum = methods (\"java.lang.Runtime\");\n        tf = true;\n      end_try_catch\n    case \"swing\"\n      try\n        dum = methods (\"javax.swing.Popup\");\n        tf = ! javaMethod (\"isHeadless\", \"java.awt.GraphicsEnvironment\");\n      end_try_catch\n    otherwise\n      error (\"usejava: unrecognized FEATURE '%s'\", feature);\n  endswitch\n\nendfunction\n\n\n%!assert (usejava (\"desktop\"), false)\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! assert (usejava (\"jvm\"), true);\n\n## Test input validation\n%!error <Invalid call> usejava ()\n%!error <Invalid call> usejava (1)\n%!error <unrecognized FEATURE> usejava (\"abc\")\n"
  },
  {
    "path": "scripts/legacy/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/legacy/@inline/argnames.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{args} =} argnames (@var{fobj})\n## Return a cell array of character strings containing the names of the\n## arguments of the inline function object @var{fobj}.\n##\n## Programming Note: @code{symvar (@var{fobj})} is equivalent to\n## @code{argnames (@var{fobj})}.\n## @seealso{symvar, formula, vectorize, inline}\n## @end deftypefn\n\nfunction args = argnames (fobj)\n\n  args = fobj.args;\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/cat.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} cat (@var{fobj1}, @var{dots})\n## Concatenate inline function objects.\n##\n## Concatenating inline function objects is @strong{not} possible;\n## Octave emits an error if this function is called.\n## @seealso{inline}\n## @end deftypefn\n\nfunction cat (varargin)\n\n  error (\"@inline/cat: concatenating inline function objects is not possible\");\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/char.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{fcnstr} =} char (@var{fobj})\n## Return a character string representing the inline function object\n## @var{fobj}.\n##\n## Programming Note: @code{char (@var{fobj})} is equivalent to\n## @code{formula (@var{fobj})}.\n## @seealso{formula, argnames, vectorize, inline}\n## @end deftypefn\n\nfunction fcnstr = char (fobj)\n\n  fcnstr = fobj.expr;\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/disp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} disp (@var{fobj})\n## Display an @code{inline} function object.\n## @seealso{display}\n## @end deftypefn\n\nfunction disp (fobj)\n\n  disp (\"inline function object:\");\n  ## FIXME: inputname doesn't work with @class methods\n  ## str = inputname (1);\n  ## args = strjoin (fobj.args, ',');\n  ## str = [str '(' args ')' \" = \" fobj.expr];\n  ## disp (str);\n  disp (formula (fobj));\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/exist.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{C} =} exist (@var{fobj})\n## Return code 1 indicating @var{fobj} is an Octave variable.\n##\n## @seealso{inline}\n## @end deftypefn\n\nfunction retval = exist (fobj)\n\n  retval = 1;\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/feval.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} feval (@var{fobj}, @dots{})\n## Evaluate the inline function in @var{fobj}.\n##\n## Any arguments after the first are passed as inputs to the function.\n## @seealso{inline}\n## @end deftypefn\n\nfunction retval = feval (fobj, varargin)\n\n  retval = fobj.fh (varargin{:});\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/formula.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{fcnstr} =} formula (@var{fobj})\n## Return a character string representing the inline function @var{fobj}.\n##\n## Programming Note: @code{char (@var{fobj})} is equivalent to\n## @code{formula (@var{fobj})}.\n## @seealso{char, argnames, vectorize, inline}\n## @end deftypefn\n\nfunction fcnstr = formula (obj)\n\n  fcnstr = obj.expr;\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/horzcat.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} horzcat (@var{fobj1}, @var{dots})\n## Horizontally concatenate inline function objects.\n##\n## Concatenating inline function objects is @strong{not} possible;\n## Octave emits an error if this function is called.\n## @seealso{inline}\n## @end deftypefn\n\nfunction horzcat (varargin)\n\n  error (\"@inline/horzcat: concatenating inline function objects is not possible\");\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/inline.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{fobj} =} inline (@var{str})\n## @deftypefnx {} {@var{fobj} =} inline (@var{str}, @var{arg1}, @dots{})\n## @deftypefnx {} {@var{fobj} =} inline (@var{str}, @var{n})\n##\n## This function is obsolete.  Use anonymous functions\n## (@pxref{Anonymous Functions}) instead.\n##\n## Create an inline function object from the character string @var{str}.\n##\n## If called with a single argument, the arguments of the generated\n## function are extracted from the function itself.  The generated\n## function arguments will then be in alphabetical order.  It should be\n## noted that i and j are ignored as arguments due to the ambiguity\n## between their use as a variable and their use as an built-in constant.\n## All arguments followed by a parenthesis are considered to be\n## functions.  If no arguments are found, a function taking a single\n## argument named @code{x} will be created.\n##\n## If the second and subsequent arguments are character strings, they\n## are the names of the arguments of the function.\n##\n## If the second argument is an integer @var{n}, the arguments are\n## @qcode{\"x\"}, @qcode{\"P1\"}, @dots{}, @qcode{\"P@var{N}\"}.\n##\n## @strong{Caution:} the use of @code{inline} is discouraged and it may\n## be removed from a future version of Octave.  The preferred way to\n## create functions from strings is through the use of anonymous\n## functions (@pxref{Anonymous Functions}) or @code{str2func}.\n## @seealso{argnames, formula, vectorize, str2func}\n## @end deftypefn\n\nfunction fobj = inline (expr, varargin)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"inline is obsolete; use anonymous functions instead\\n\");\n  endif\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  if (! ischar (expr))\n    error (\"inline: EXPR must be a string\");\n  endif\n\n  if (nargin == 1)\n    args = parse_expr_for_args (expr);\n  elseif (nargin == 2)\n    n = varargin{1};\n    if (isnumeric (n))\n      if (isscalar (n) && fix (n) == n)\n        if (n > 0)\n          args = strsplit ([\"x\", sprintf(\":P%d\", 1:n)], \":\");\n        else\n          error (\"inline: N must be a positive integer\");\n        endif\n      else\n        error (\"inline: N must be an integer\");\n      endif\n    else\n      args = {\"x\"};\n    endif\n  elseif (iscellstr (varargin))\n    args = varargin;\n  else\n    error (\"inline: additional arguments must be strings\");\n  endif\n\n  p.expr = expr;\n  p.args = args(:);\n  p.nargs = numel (args);\n  p.fh = eval (sprintf (\"@(%s) %s\", strjoin (args(:), \",\"), expr));\n\n  ## FIXME: Do we need these parts of inline struct anymore (4/6/22)?\n  tmp = [args; num2cell(1:numel(args))];\n  p.inputExpr = sprintf (\"%s = INLINE_INPUTS_{%d}; \", tmp{:});\n  p.isEmpty = false;\n  p.version = 1;\n\n  fobj = __inline_ctor__ (p);\n\nendfunction\n\n## The following function was translated directly from the original C++\n## version.  Yes, it will be slow, but the use of inline functions is\n## strongly discouraged anyway, and most expressions will probably be\n## short.  It may also be buggy.  Well, don't use this object!  Use\n## function handles instead!\n\nfunction args = parse_expr_for_args (expr)\n\n  persistent symbols_to_skip = {\"i\", \"j\", \"NaN\", \"nan\", \"Inf\", \"inf\", ...\n                                \"NA\", \"pi\", \"e\", \"eps\"};\n\n  is_arg = false;\n  in_string = false;\n  tmp_arg = \"\";\n  i = 1;\n  expr_length = length (expr);\n  args = {};\n\n  while (i <= expr_length)\n\n    terminate_arg = false;\n    c = expr(i++);\n\n    if (in_string)\n      if (c == \"'\" || c == '\"')\n        in_string = false;\n      endif\n    elseif (c == \"'\" || c == '\"')\n      in_string = true;\n      if (is_arg)\n        terminate_arg = true;\n      endif\n    elseif (! isalpha (c) && c != \"_\")\n      if (! is_arg)\n        continue;\n      elseif (isdigit (c))\n        tmp_arg(end+1) = c;\n      else\n        ## Before we do anything remove trailing whitespaces.\n        while (i <= expr_length && isspace (c))\n          c = expr(i++);\n        endwhile\n\n        ## Do we have a variable or a function?\n        if (c != \"(\")\n          terminate_arg = true;\n        else\n          tmp_arg = \"\";\n          is_arg = false;\n        endif\n      endif\n    elseif (! is_arg)\n      if (c == \"e\" || c == \"E\")\n        ## Possible number in exponent form, not arg.\n        if (isdigit (expr(i)) || expr(i) == \"-\" || expr(i) == \"+\")\n          continue;\n        endif\n      endif\n      is_arg = true;\n      tmp_arg(end+1) = c;\n    else\n      tmp_arg(end+1) = c;\n    endif\n\n    if (terminate_arg || (i == expr_length+1 && is_arg))\n      have_arg = false;\n      if (any (strcmp (tmp_arg, args)))\n        have_arg = true;\n      endif\n\n      if (! (have_arg || any (strcmp (tmp_arg, symbols_to_skip))))\n        args{end+1} = tmp_arg;\n      endif\n\n      tmp_arg = \"\";\n      is_arg = false;\n    endif\n\n  endwhile\n\n  ## Sort the arguments into ASCII order.\n  args = sort (args);\n\n  if (isempty (args))\n    args = {\"x\"};\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/module.mk",
    "content": "## Automake fails to process \"include %reldir%/module.mk\" in the directory\n## above.  All of the commands which would normally be in this file were\n## manually placed in scripts/legacy/module.mk to avoid using the \"include\"\n## directive.\n##\n## This is an Automake bug.  Automake has switched to a Perl backend which uses\n## the following pattern to detect a path:\n##\n## my $PATH_PATTERN = '(\\w|[+/.-])+';\n##\n## This pattern only includes alphanumeric, '_', and [+/.-], but not \"@\".\n"
  },
  {
    "path": "scripts/legacy/@inline/nargin.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{n} =} nargin (@var{fobj})\n## Return the number of input arguments for the inline function object\n## @var{fobj}.\n## @seealso{nargout, argnames, inline}\n## @end deftypefn\n\nfunction n = nargin (fobj)\n\n  n = fobj.nargs;\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/nargout.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{n} =} nargout (@var{fobj})\n## Return the number of output arguments for the inline function object\n## @var{fobj}.\n##\n## Programming Note: The return value is always 1 because @code{inline}\n## function objects only support one output.\n## @seealso{nargin, inline}\n## @end deftypefn\n\nfunction n = nargout (fobj)\n\n  n = 1;\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/subsref.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{value} =} subsref (@var{fobj}, @var{idx})\n## Perform subscripted function call on the inline function object @var{fobj}.\n## @end deftypefn\n\nfunction retval = subsref (fobj, idx)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (isempty (idx))\n    error (\"@inline/subsref: missing index\");\n  endif\n\n  if (strcmp (idx(1).type, \"()\"))\n    args = idx.subs;\n    if (numel (args) > 0)\n      retval = feval (fobj, args{:});\n    else\n      retval = feval (fobj);\n    endif\n  else\n    error (\"@inline/subsref: invalid subscript type\");\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/symvar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{args} =} symvar (@var{fobj})\n## Return a cell array of character strings containing the names of the\n## arguments of the inline function object @var{fobj}.\n##\n## Programming Note: @code{symvar (@var{fobj})} is equivalent to\n## @code{argnames (@var{fobj})}.\n## @seealso{argnames, formula, vectorize, inline}\n## @end deftypefn\n\nfunction args = symvar (fobj)\n\n  args = fobj.args;\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/vectorize.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{vfcn} =} vectorize (@var{fobj})\n## Create a vectorized version of the inline function @var{fobj} by\n## replacing all occurrences of @code{*}, @code{/}, etc., with\n## @code{.*}, @code{./}, etc.\n##\n## This may be useful, for example, when using inline functions with\n## numerical integration or optimization where a vector-valued function\n## is expected.\n##\n## @example\n## @group\n## fobj = vectorize (inline (\"x^2 - 1\"))\n##    @xresult{} fobj = f(x) = x.^2 - 1\n## quadv (fobj, 0, 3)\n##    @xresult{} 6\n## @end group\n## @end example\n## @seealso{inline, formula, argnames}\n## @end deftypefn\n\nfunction vfcn = vectorize (fobj)\n\n  vfcn = inline (__vectorize__ (fobj.expr));\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/@inline/vertcat.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} vertcat (@var{fobj1}, @var{dots})\n## Vertically concatenate inline function objects.\n##\n## Concatenating inline function objects is @strong{not} possible;\n## Octave emits an error if this function is called.\n## @seealso{inline}\n## @end deftypefn\n\nfunction vertcat (varargin)\n\n  error (\"@inline/vertcat: concatenating inline function objects is not possible\");\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/__vectorize__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{new_expr} =} __vectorize__ (@var{expr})\n## Undocumented internal function.\n## @end deftypefn\n\n## The following function was translated directly from the original C++\n## version.  Yes, it will be slow, but its use is strongly discouraged\n## anyway, and most expressions will probably be short.  It may also be\n## buggy.  Well, don't use this function!\n\nfunction new_expr = __vectorize__ (expr)\n\n  new_expr = \"\";\n\n  len = length (expr);\n  i = 1;\n\n  while (i <= len)\n    c = expr(i);\n\n    if (c == \"*\" || c == \"/\" || c == \"\\\\\" || c == \"^\")\n      if (i > 1 && expr(i-1) != \".\")\n        new_expr(end+1) = \".\";\n      endif\n\n      ## Special case for ** operator.\n      if (c == '*' && i < (len - 1) && expr(i+1) == '*')\n        new_expr(end+1) = \"*\";\n        i++;\n      endif\n    endif\n\n    new_expr(end+1) = c;\n    i++;\n\n  endwhile\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/caxis.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} caxis ([cmin cmax])\n## @deftypefnx {} {} caxis (\"auto\")\n## @deftypefnx {} {} caxis (\"manual\")\n## @deftypefnx {} {} caxis (@var{hax}, @dots{})\n## @deftypefnx {} {@var{limits} =} caxis ()\n##\n## This function is not recommended.  Use @code{clim} instead.\n##\n## Query or set color axis limits for plots.\n##\n## The limits argument should be a 2-element vector specifying the lower and\n## upper limits to assign to the first and last value in the colormap.  Data\n## values outside this range are clamped to the first and last colormap\n## entries.\n##\n## If the @qcode{\"auto\"} option is given then automatic colormap limits are\n## applied.  The automatic algorithm sets @var{cmin} to the minimum data value\n## and @var{cmax} to the maximum data value.  If @qcode{\"manual\"} is specified\n## then the @qcode{\"climmode\"} property is set to @qcode{\"manual\"} and the\n## numeric values in the @qcode{\"clim\"} property are used for limits.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## Called without arguments the current color axis limits are returned.\n##\n## Programming Note: The color axis affects the display of image, patch, and\n## surface graphics objects, but @strong{only} if the @qcode{\"cdata\"} property\n## has indexed data and the @qcode{\"cdatamapping\"} property is set to\n## @qcode{\"scaled\"}.  Graphic objects with true color @code{cdata}, or\n## @qcode{\"direct\"} @code{cdatamapping} are not affected.\n## @seealso{clim, colormap, axis}\n## @end deftypefn\n\nfunction limits = caxis (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"caxis\", varargin{:});\n\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  oldfig = [];\n  if (! isempty (hax))\n    oldfig = get (0, \"currentfigure\");\n  endif\n  unwind_protect\n    if (isempty (hax))\n      hax = gca ();\n    endif\n    if (nargin == 0)\n      limits = get (hax, \"clim\");\n    else\n      arg1 = varargin{1};\n      if (ischar (arg1))\n        if (strcmpi (arg1, \"auto\"))\n          set (hax, \"climmode\", \"auto\");\n        elseif (strcmpi (arg1, \"manual\"))\n          set (hax, \"climmode\", \"manual\");\n        else\n          error (\"caxis: invalid mode '%s'\", arg1);\n        endif\n      elseif (isvector (arg1))\n        if (numel (arg1) != 2 || ! isnumeric (arg1) || arg1(1) >= arg1(2))\n          error (\"caxis: LIMITS must be a numeric 2-element vector where LIM1 < LIM2\");\n        endif\n        set (hax, \"clim\", arg1);\n      else\n        print_usage ();\n      endif\n    endif\n  unwind_protect_cleanup\n    if (! isempty (oldfig))\n      set (0, \"currentfigure\", oldfig);\n    endif\n  end_unwind_protect\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   caxis ([e, pi]);\n%!   assert (caxis (), [e, pi]);\n%!   caxis (hax, [-1, 1]);\n%!   assert (caxis (hax), [-1, 1]);\n%!   assert (get (hax, \"climmode\"), \"manual\");\n%!   caxis (\"auto\");\n%!   assert (get (hax, \"climmode\"), \"auto\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error caxis (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   fail (\"caxis ('foo')\", \"invalid mode 'foo'\");\n%!   fail (\"caxis ([1 2 3])\", \"2-element vector\");\n%!   fail (\"caxis ({1 2 3})\", \"numeric 2-element vector\");\n%!   fail (\"caxis ([1 0])\", \"LIM1 < LIM2\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/legacy/findstr.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{v} =} findstr (@var{s}, @var{t})\n## @deftypefnx {} {@var{v} =} findstr (@var{s}, @var{t}, @var{overlap})\n##\n## This function is obsolete.  Use @code{strfind} instead.\n##\n## Return the vector of all positions in the longer of the two strings @var{s}\n## and @var{t} where an occurrence of the shorter of the two starts.\n##\n## If the optional argument @var{overlap} is true (default), the returned\n## vector can include overlapping positions.  For example:\n##\n## @example\n## @group\n## findstr (\"ababab\", \"a\")\n##      @xresult{} [1, 3, 5];\n## findstr (\"abababa\", \"aba\", 0)\n##      @xresult{} [1, 5]\n## @end group\n## @end example\n##\n## @strong{Caution:} @code{findstr} is obsolete.  Use @code{strfind} in all new\n## code.\n## @seealso{strfind, strmatch, strcmp, strncmp, strcmpi, strncmpi, find}\n## @end deftypefn\n\n## Note that this implementation swaps the strings if second one is longer\n## than the first, so try to put the longer one first.\n\nfunction v = findstr (s, t, overlap = true)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"findstr is obsolete; use strfind instead\\n\");\n  endif\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (all (size (s) > 1) || all (size (t) > 1))\n    error (\"findstr: arguments must have only one non-singleton dimension\");\n  endif\n\n  ## Make S be the longer string.\n  if (length (s) < length (t))\n    [s, t] = deal (t, s);\n  endif\n\n  l_s = length (s);\n  l_t = length (t);\n\n  if (l_t == 0)\n    ## zero length target: return empty set\n    v = [];\n\n  elseif (l_t == 1)\n    ## length one target: simple find\n    v = find (s == t);\n\n  elseif (l_t == 2)\n    ## length two target: find first at i and second at i+1\n    v = find (s(1:l_s-1) == t(1) & s(2:l_s) == t(2));\n\n  else\n    ## length three or more: match the first three by find then go through\n    ## the much smaller list to determine which of them are real matches\n    limit = l_s - l_t + 1;\n    v = find (  s(1:limit)   == t(1)\n              & s(2:limit+1) == t(2)\n              & s(3:limit+2) == t(3));\n  endif\n\n  ## Need to search the index vector if our find was too short\n  ## (target length > 3), or if we don't allow overlaps.  Note though\n  ## that there cannot be any overlaps if the first character in the\n  ## target is different from the remaining characters in the target,\n  ## so a single character, two different characters, or first character\n  ## different from the second two don't need to be searched.\n  if (l_t >= 3 || (! overlap && l_t > 1 && any (t(1) == t(2:l_t))))\n    ## force strings to be both row vectors or both column vectors\n    if (all (size (s) != size (t)))\n      t = t.';\n    endif\n\n    ## determine which ones to keep\n    keep = zeros (size (v));\n    ind = 0:l_t-1;\n    if (overlap)\n      for idx = 1:length (v)\n        keep(idx) = all (s(v(idx) + ind) == t);\n      endfor\n    else\n      ## First possible position for next non-overlapping match.\n      next = 1;\n      for idx = 1:length (v)\n        if (v(idx) >= next && s(v(idx) + ind) == t)\n          keep(idx) = 1;\n          ## Skip to the next possible match position.\n          next = v(idx) + l_t;\n        else\n          keep(idx) = 0;\n        endif\n      endfor\n    endif\n    if (! isempty (v))\n      v = v(find (keep));\n    endif\n  endif\n\n  if (isempty (v))\n    v = [];\n  endif\n\n  ## Always return a row vector, because that's what the old one did.\n  if (iscolumn (v))\n    v = v.';\n  endif\n\nendfunction\n\n\n## First test is necessary to provoke 1-time legacy warning\n%!test\n%! warning (\"off\", \"Octave:legacy-function\", \"local\");\n%! findstr (\"\", \"\");\n\n%!assert (findstr (\"abababa\", \"a\"), [1, 3, 5, 7])\n%!assert (findstr (\"abababa\", \"aba\"), [1, 3, 5])\n%!assert (findstr (\"aba\", \"abababa\", 0), [1, 5])\n\n## Test input validation\n%!error <Invalid call> findstr ()\n%!error <Invalid call> findstr (\"str1\")\n%!error <must have only one non-singleton dimension> findstr ([\"AB\" ; \"CD\"], \"C\")\n"
  },
  {
    "path": "scripts/legacy/flipdim.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} flipdim (@var{A})\n## @deftypefnx {} {@var{B} =} flipdim (@var{A}, @var{dim})\n## This function is obsolete.  Use @code{flip} instead.\n## @seealso{flip, fliplr, flipud, rot90, rotdim}\n## @end deftypefn\n\nfunction B = flipdim (varargin)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"flipdim is obsolete; please use flip instead\");\n  endif\n\n  B = flip (varargin{:});\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/genvarname.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{varname} =} genvarname (@var{str})\n## @deftypefnx {} {@var{varname} =} genvarname (@var{str}, @var{exclusions})\n##\n## This function is obsolete.  Use @code{matlab.lang.makeValidName} or\n## @code{matlab.lang.makeUniqueStrings} instead.\n##\n## Create valid unique variable name(s) from @var{str}.\n##\n## If @var{str} is a cellstr, then a unique variable is created for each cell\n## in @var{str}.\n##\n## @example\n## @group\n## genvarname (@{\"foo\", \"foo\"@})\n##   @xresult{}\n##      @{\n##        [1,1] = foo\n##        [1,2] = foo1\n##      @}\n## @end group\n## @end example\n##\n## If @var{exclusions} is given, then the variable(s) will be unique to each\n## other and to @var{exclusions} (@var{exclusions} may be either a string or a\n## cellstr).\n##\n## @example\n## @group\n## x = 3.141;\n## genvarname (\"x\", who ())\n##   @xresult{} x1\n## @end group\n## @end example\n##\n## Note that the result is a char array or cell array of strings, not the\n## variables themselves.  To define a variable, @code{eval()} can be used.\n## The following trivial example sets @code{x} to 42.\n##\n## @example\n## @group\n## name = genvarname (\"x\");\n## eval ([name \" = 42\"]);\n##   @xresult{} x =  42\n## @end group\n## @end example\n##\n## This can be useful for creating unique struct field names.\n##\n## @example\n## @group\n## x = struct ();\n## for i = 1:3\n##   x.(genvarname (\"a\", fieldnames (x))) = i;\n## endfor\n##   @xresult{} x =\n##      @{\n##        a =  1\n##        a1 =  2\n##        a2 =  3\n##      @}\n## @end group\n## @end example\n##\n## Since variable names may only contain letters, digits, and underscores,\n## @code{genvarname} will replace any sequence of disallowed characters with\n## an underscore.  Also, variables may not begin with a digit; in this case\n## an @samp{x} is added before the variable name.\n##\n## Variable names beginning and ending with two underscores @qcode{\"__\"} are\n## valid, but they are used internally by Octave and should generally be\n## avoided; therefore, @code{genvarname} will not generate such names.\n##\n## @code{genvarname} will also ensure that returned names do not clash with\n## keywords such as @qcode{\"for\"} and @qcode{\"if\"}.  A number will be\n## appended if necessary.  Note, however, that this does @strong{not} include\n## function names such as @qcode{\"sin\"}.  Such names should be included in\n## @var{exclusions} if necessary.\n## @seealso{matlab.lang.makeValidName, matlab.lang.makeUniqueStrings,\n## namelengthmax, isvarname, iskeyword, exist, who, tempname, eval}\n## @end deftypefn\n\nfunction varname = genvarname (str, exclusions = {})\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"genvarname is obsolete; use matlab.lang.makeValidName or matlab.lang.makeUniqueStrings instead\\n\");\n  endif\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  strinput = ischar (str);\n  ## Process the inputs\n  if (strinput)\n    if (rows (str) != 1)\n      error (\"genvarname: if more than one STR is given, it must be a cellstr\");\n    endif\n    str = {str};\n  elseif (! iscellstr (str))\n    error (\"genvarname: STR must be a string or cellstr\");\n  endif\n\n  if (ischar (exclusions))\n    if (rows (exclusions) != 1)\n      error (\"genvarname: if more than one exclusion is given, it must be a cellstr\");\n    endif\n    exclusions = {exclusions};\n  elseif (! iscellstr (exclusions))\n    error (\"genvarname: EXCLUSIONS must be a string or cellstr\");\n  else\n    exclusions = exclusions(:);\n  endif\n\n  varname = cell (size (str));\n  for i = 1:numel (str)\n    ## Perform any modifications to the varname to make sure that it is\n    ## a valid variable name.\n\n    ## remove invalid characters\n    str{i}(! (isalnum (str{i}) | str{i} == \"_\")) = \"_\";\n    ## do not use keywords\n    if (iskeyword (str{i}))\n      firstcharacter = upper (str{i}(1));\n      str{i} = [\"x\", firstcharacter, str{i}(2:end)];\n    endif\n    ## The variable cannot be empty\n    if (isempty (str{i}))\n      str{i} = \"x\";\n    endif\n    ## Leading underscores are not Matlab compatible\n    if (str{i}(1) == \"_\")\n      str{i} = [\"x\", str{i}];\n    endif\n    ## it cannot start with a number\n    if (isdigit (str{i}(1)))\n      str{i} = [\"x\", str{i}];\n    endif\n\n    ## make sure that the variable is unique relative to other variables\n    ## and the exclusions list\n    excluded = any (strcmp (str{i}, exclusions));\n    if (excluded && isdigit (str{i}(end)))\n      ## if it is not unique and ends with a digit, add an underscore to\n      ## make the variable name more readable (\"x1_1\" instead of \"x11\")\n      str{i} = [str{i}, \"_\"];\n    endif\n    varname(i) = str(i);\n    idx = 0;\n    while (excluded)\n      idx += 1;\n      varname{i} = sprintf (\"%s%d\", str{i}, idx);\n      excluded = any (strcmp (varname{i}, exclusions));\n    endwhile\n    exclusions(end+1) = varname(i);\n  endfor\n\n  if (strinput)\n    varname = varname{1};\n  endif\n\nendfunction\n\n\n## a single argument\n%!assert (genvarname (\"a\"), \"a\")\n## a single argument with a non-conflicting exception\n%!assert (genvarname (\"a\", \"b\"), \"a\")\n## a single argument with a conflicting exception\n%!assert (genvarname (\"a\", \"a\"), \"a1\")\n## a single argument as a cell\n%!assert (genvarname ({\"a\"}), {\"a\"})\n%!assert (genvarname ({\"a\"}, \"b\"), {\"a\"})\n%!assert (genvarname ({\"a\"}, {\"b\"}), {\"a\"})\n%!assert (genvarname ({\"a\"}, \"a\"), {\"a1\"})\n%!assert (genvarname ({\"a\"}, {\"a\"}), {\"a1\"})\n## Test different arguments\n## orientation\n%!assert (genvarname ({\"a\" \"b\"}), {\"a\" \"b\"})\n%!assert (genvarname ({\"a\";\"b\"}), {\"a\";\"b\"})\n%!assert (genvarname ({\"a\" \"a\"}), {\"a\" \"a1\"})\n%!assert (genvarname ({\"a\" \"b\";\"c\" \"d\"}), {\"a\" \"b\";\"c\" \"d\"})\n%!assert (genvarname ({\"a\" \"a\" \"a\";\"a\" \"a\" \"a\"}),\n%!        {\"a\" \"a2\" \"a4\";\"a1\" \"a3\" \"a5\"})\n## more than one repetition\n%!assert (genvarname ({\"a\" \"a\" \"a\"}), {\"a\" \"a1\" \"a2\"})\n%!assert (genvarname ({\"a\" \"a\" \"a\"}, {\"a\" \"a1\" \"a2\"}), {\"a3\" \"a4\" \"a5\"})\n## more than one repetition not in order\n%!assert (genvarname ({\"a\" \"b\" \"a\" \"b\" \"a\"}), {\"a\" \"b\" \"a1\" \"b1\" \"a2\"})\n## Variable name munging\n%!assert (genvarname (\"__x__\"), \"x__x__\")\n%!assert (genvarname (\"123456789\"), \"x123456789\")\n%!assert (genvarname (\"_$1__\"), \"x__1__\")\n%!assert (genvarname (\"__foo__\", \"x__foo__\"), \"x__foo__1\")\n%!assert (genvarname (\"1million_and1\", \"x1million_and1\"), \"x1million_and1_1\")\n%!assert (genvarname ({\"\", \"\", \"\"}), {\"x\", \"x1\", \"x2\"})\n%!assert (genvarname (\"if\"), \"xIf\")\n%!assert (genvarname ({\"if\", \"if\", \"if\"}), {\"xIf\", \"xIf1\", \"xIf2\"})\n## Exclusions in odd format\n%!assert (genvarname (\"x\", {\"a\", \"b\"; \"x\", \"d\"}), \"x1\")\n\n## Test input validation\n%!error <Invalid call> genvarname ()\n%!error <more than one STR is given, it must be a cellstr> genvarname (char (\"a\", \"b\", \"c\"))\n%!error <STR must be a string or cellstr> genvarname (1)\n%!error <more than one exclusion is given, it must be a cellstr> genvarname (\"x\", char (\"a\", \"b\", \"c\"))\n%!error <EXCLUSIONS must be a string or cellstr> genvarname (\"x\", 1)\n"
  },
  {
    "path": "scripts/legacy/isdir.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isdir (@var{f})\n##\n## This function is not recommended.  Use @code{isfolder} or\n## @code{file_in_loadpath} instead.\n##\n## Return true if @var{f} is a directory and false otherwise.\n##\n## Compatibility Note: The @sc{matlab} function of the same name will also\n## search for @var{f} in the load path directories.  To emulate this behavior\n## use\n##\n## @example\n## @var{tf} = ! isempty (file_in_loadpath (@var{f}))\n## @end example\n##\n## @seealso{isfolder, file_in_loadpath, exist, stat, is_absolute_filename,\n## is_rooted_relative_filename}\n## @end deftypefn\n\nfunction tf = isdir (f)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"isdir is obsolete; use isfolder or dir_in_loadpath instead\\n\");\n  endif\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Exist returns an integer but isdir should return a logical.\n  tf = (exist (f, \"dir\") == 7);\n\nendfunction\n\n\n## First test is necessary to provoke 1-time legacy warning\n%!test\n%! warning (\"off\", \"Octave:legacy-function\", \"local\");\n%! isdir (pwd ());\n\n%!assert (isdir (pwd ()))\n%!assert (! isdir (tempname ()))\n\n%!error <Invalid call> isdir ()\n"
  },
  {
    "path": "scripts/legacy/isequalwithequalnans.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isequalwithequalnans (@var{x1}, @var{x2}, @dots{})\n## This function is obsolete.  Use @code{isequaln} instead.\n## @seealso{isequaln}\n## @end deftypefn\n\n## At one time, Matlab docs stated that this function is obsolete and would be\n## removed in some future version.  Now users are told that it should be\n## avoided, but there is no mention of possible future removal.\n\nfunction tf = isequalwithequalnans (varargin)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"isequalwithequalnans is obsolete; please use isequaln instead\");\n  endif\n\n  tf = isequaln (varargin{:});\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/isstr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isstr (@var{x})\n## This function is obsolete.  Use @code{ischar} instead.\n## @seealso{ischar}\n## @end deftypefn\n\n## At one time, Matlab docs stated that this function is obsolete and would be\n## removed in some future version.  Now users are told that it should be\n## avoided, but there is no mention of possible future removal.\n\nfunction tf = isstr (varargin)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"isstr is obsolete; please use ischar instead\");\n  endif\n\n  tf = ischar (varargin{:});\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/maxNumCompThreads.m",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{n} =} maxNumCompThreads ()\n## @deftypefnx {} {@var{n_old} =} maxNumCompThreads (@var{n})\n## @deftypefnx {} {@var{n_old} =} maxNumCompThreads (\"automatic\")\n## This function is provided for @sc{matlab} compatibility only.\n##\n## The output @var{n} is the number of available processors as determined by\n## the @code{nproc} function.\n##\n## Programming Note: The function may be called with an argument to set the\n## number of computational threads, but that setting has @strong{no effect}.\n## @seealso{nproc}\n## @end deftypefn\n\nfunction retval = maxNumCompThreads (arg)\n\n  persistent nthreads = nproc ();\n\n  retval = nthreads;\n\n  if (nargin == 1)\n    if (isnumeric (arg) && isscalar (arg) && arg == fix (arg)\n        && arg > 0 && isfinite (arg))\n      ## FIXME: Should there be an upper limit?\n      nthreads = arg;\n      warning (\"Octave:maxNumCompThreads:no-effect\",\n               \"maxNumCompThreads: setting number of threads has no effect\");\n    elseif (ischar (arg) && strcmpi (arg, \"automatic\"))\n      nthreads = nproc ();\n    else\n      error (\"maxNumCompThreads: invalid input argument\");\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! maxNumCompThreads (\"automatic\");\n%! assert (maxNumCompThreads (), nproc ());\n\n%!test\n%! warning (\"off\", \"Octave:maxNumCompThreads:no-effect\", \"local\");\n%! maxNumCompThreads (4);\n%! assert (maxNumCompThreads (\"automatic\"), 4);\n\n%!error <invalid input argument> maxNumCompThreads ([1, 2])\n%!error <invalid input argument> maxNumCompThreads (\"foobar\")\n"
  },
  {
    "path": "scripts/legacy/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/__vectorize__.m \\\n  %reldir%/caxis.m \\\n  %reldir%/findstr.m \\\n  %reldir%/flipdim.m \\\n  %reldir%/genvarname.m \\\n  %reldir%/isdir.m \\\n  %reldir%/isequalwithequalnans.m \\\n  %reldir%/isstr.m \\\n  %reldir%/maxNumCompThreads.m \\\n  %reldir%/setstr.m \\\n  %reldir%/strmatch.m \\\n  %reldir%/strread.m \\\n  %reldir%/textread.m \\\n  %reldir%/vectorize.m\n\n## include %reldir%/@inline/module.mk\n## The include above fails because Automake cannot process the '@' character.\n## As a work around, the contents of %reldir%/@inline/module.mk are placed directly\n## in this module.mk file.\nscripts_EXTRA_DIST += %reldir%/@inline/module.mk\n######################## include %reldir%/@inline/module.mk ########################\nFCN_FILE_DIRS += %reldir%/@inline\n\n%canon_reldir%_@inline_FCN_FILES = \\\n  %reldir%/@inline/argnames.m \\\n  %reldir%/@inline/cat.m \\\n  %reldir%/@inline/char.m \\\n  %reldir%/@inline/disp.m \\\n  %reldir%/@inline/exist.m \\\n  %reldir%/@inline/feval.m \\\n  %reldir%/@inline/formula.m \\\n  %reldir%/@inline/horzcat.m \\\n  %reldir%/@inline/inline.m \\\n  %reldir%/@inline/nargin.m \\\n  %reldir%/@inline/nargout.m \\\n  %reldir%/@inline/subsref.m \\\n  %reldir%/@inline/symvar.m \\\n  %reldir%/@inline/vectorize.m \\\n  %reldir%/@inline/vertcat.m\n\n%canon_reldir%_@inlinedir = $(fcnfiledir)/legacy/@inline\n\n%canon_reldir%_@inline_DATA = $(%canon_reldir%_@inline_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_@inline_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/@inline/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/@inline/$(octave_dirstamp)\n####################### end include %reldir%/@inline/module.mk #####################\n\n%canon_reldir%dir = $(fcnfiledir)/legacy\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/legacy/setstr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{s} =} setstr (@var{x})\n## This function is obsolete.  Use @code{char} instead.\n## @seealso{char}\n## @end deftypefn\n\n## At one time, Matlab docs stated that this function is obsolete and would be\n## removed in some future version.  Now users are told that it should be\n## avoided, but there is no mention of possible future removal.\n\nfunction retval = setstr (varargin)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"setstr is obsolete; please use char instead\");\n  endif\n\n  retval = char (varargin{:});\n\nendfunction\n"
  },
  {
    "path": "scripts/legacy/strmatch.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{idx} =} strmatch (@var{s}, @var{A})\n## @deftypefnx {} {@var{idx} =} strmatch (@var{s}, @var{A}, \"exact\")\n##\n## This function is obsolete.  @strong{Use an alternative} such as\n## @code{strncmp} or @code{strcmp} instead.\n##\n## Return indices of entries of @var{A} which begin with the string @var{s}.\n##\n## The second argument @var{A} must be a string, character matrix, or a cell\n## array of strings.\n##\n## If the third argument @qcode{\"exact\"} is not given, then @var{s} only\n## needs to match @var{A} up to the length of @var{s}.  Trailing spaces and\n## nulls in @var{s} and @var{A} are ignored when matching.\n##\n## For example:\n##\n## @example\n## @group\n## strmatch (\"apple\", \"apple juice\")\n##      @xresult{} 1\n##\n## strmatch (\"apple\", [\"apple  \"; \"apple juice\"; \"an apple\"])\n##      @xresult{} [1; 2]\n##\n## strmatch (\"apple\", [\"apple  \"; \"apple juice\"; \"an apple\"], \"exact\")\n##      @xresult{} [1]\n## @end group\n## @end example\n##\n## @strong{Caution:} @code{strmatch} is obsolete (and can produce incorrect\n## results in @sc{matlab} when used with cell arrays of strings.  Use\n## @code{strncmp} (normal case) or @code{strcmp} (@qcode{\"exact\"} case) in all\n## new code.  Other replacement possibilities, depending on application,\n## include @code{regexp} or @code{validatestring}.\n## @seealso{strncmp, strcmp, regexp, strfind, validatestring}\n## @end deftypefn\n\nfunction idx = strmatch (s, A, exact)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"strmatch is obsolete; use strncmp or strcmp instead\\n\");\n  endif\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (iscellstr (s))\n    if (numel (s) > 1)\n      error (\"strmatch: a cell array S must contain only one string\");\n    endif\n    s = char (s);\n  elseif (! ischar (s) || (! isempty (s) && ! isrow (s)))\n    error (\"strmatch: S must be a string\");\n  elseif (! (ischar (A) || iscellstr (A)))\n    error (\"strmatch: A must be a string or cell array of strings\");\n  endif\n\n  ## Trim blanks and nulls from search string\n  if (any (s != \" \" & s != \"\\0\"))\n    s = regexprep (s, \"[ \\\\0]+$\", '');\n  endif\n  len = length (s);\n\n  exact = nargin == 3 && ischar (exact) && strcmp (exact, \"exact\");\n\n  if (ischar (A))\n    [nr, nc] = size (A);\n    if (len > nc)\n      idx = [];\n    else\n      match = all (bsxfun (@eq, A(:,1:len), s), 2);\n      if (exact)\n        AA = A(:,len+1:nc);\n        match &= all (AA == \" \" | AA == \"\\0\", 2);\n      endif\n      idx = find (match);\n    endif\n  else\n    if (len > 0)\n      idx = find (strncmp (s, A, len));\n    else\n      idx = find (strcmp (s, A));\n    endif\n    if (exact)\n      ## We can't just use strcmp, because we need to ignore spaces at end.\n      B = regexprep (A(idx), \"[ \\\\0]+$\", '');\n      idx = idx(strcmp (s, B));\n    endif\n  endif\n\n  ## Return exactly sized and shaped values for Matlab compatibility.\n  if (isempty (idx))\n    idx = [];  # always return 0x0 empty matrix for non-match.\n  else\n    idx = idx(:);  # always return column vector.\n  endif\n\nendfunction\n\n\n## First test is necessary to provoke 1-time legacy warning\n%!test\n%! warning (\"off\", \"Octave:legacy-function\", \"local\");\n%! strmatch (\"\", \"\");\n\n%!assert (strmatch (\"a\", {\"aaa\", \"bab\", \"bbb\"}), 1)\n%!assert (strmatch (\"apple\", \"apple juice\"), 1)\n%!assert (strmatch (\"apple\", [\"apple pie\"; \"apple juice\"; \"an apple\"]), [1; 2])\n%!assert (strmatch (\"apple\", {\"apple pie\"; \"apple juice\"; \"tomato\"}), [1; 2])\n%!assert (strmatch (\"apple pie\", \"apple\"), [])\n%!assert (strmatch (\"a \", \"a\"), 1)\n%!assert (strmatch (\"a\", \"a \\0\", \"exact\"), 1)\n%!assert (strmatch (\"a b\", {\"a b\", \"a c\", \"c d\"}), 1)\n%!assert (strmatch (\"\", {\"\", \"foo\", \"bar\", \"\"}), [1; 4])\n%!assert (strmatch ('', {'', '% comment', 'var a = 5', ''}, \"exact\"), [1;4])\n\n## Weird Matlab corner cases\n%!test <*49601>\n%! assert (strmatch (\" \", \" \"), 1);\n%! assert (strmatch (\" \", \"   \"), 1);\n%! assert (strmatch (\"  \", \" \"), []);\n%! assert (strmatch (\"  \", \"  \"), 1);\n%!test <*54432>\n%! assert (strmatch ({\"a\"}, {\"aaa\", \"bab\", \"bbb\"}), 1);\n%! assert (isempty (strmatch ({}, {\"aaa\", \"bab\"})));\n%!test <*59917>\n%! a = { \"dfr\", \"tgh\", \"rere\", \"rere\" };\n%! b = strmatch (\"rere\", a, \"exact\");\n%! assert (b, [3; 4]);\n\n## Test input validation\n%!error <Invalid call to strmatch> strmatch ()\n%!error <Invalid call to strmatch> strmatch (\"a\")\n%!error <called with too many inputs> strmatch (\"a\", \"aaa\", \"exact\", 1)\n%!error <S must contain only one string> strmatch ({\"a\", \"b\"}, \"aaa\")\n%!error <S must be a string> strmatch (1, \"aaa\")\n%!error <S must be a string> strmatch (char (\"a\", \"bb\"), \"aaa\")\n%!error <A must be a string> strmatch (\"a\", 1)\n%!error <A must be a string> strmatch (\"a\", {\"hello\", [1]})\n"
  },
  {
    "path": "scripts/legacy/strread.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{a}, @dots{}] =} strread (@var{str})\n## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format})\n## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{format_repeat})\n## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{prop1}, @var{value1}, @dots{})\n## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{format_repeat}, @var{prop1}, @var{value1}, @dots{})\n##\n## This function is obsolete.  Use @code{textscan} instead.\n##\n## Read data from a string.\n##\n## The string @var{str} is split into words that are repeatedly matched to the\n## specifiers in @var{format}.  The first word is matched to the first\n## specifier, the second to the second specifier and so forth.  If there are\n## more words than specifiers, the process is repeated until all words have\n## been processed.\n##\n## The string @var{format} describes how the words in @var{str} should be\n## parsed.  It may contain any combination of the following specifiers:\n##\n## @table @code\n## @item %s\n## The word is parsed as a string.\n##\n## @item  %f\n## @itemx %n\n## The word is parsed as a number and converted to double.\n##\n## @item  %d\n## @itemx %u\n## The word is parsed as a number and converted to int32.\n##\n## @item  %*\n## @itemx %*f\n## @itemx %*s\n## The word is skipped.\n##\n## For %s and %d, %f, %n, %u and the associated %*s @dots{} specifiers an\n## optional width can be specified as %Ns, etc.@: where N is an integer > 1.\n## For %f, format specifiers like %N.Mf are allowed.\n##\n## @item literals\n## In addition the format may contain literal character strings; these will be\n## skipped during reading.\n## @end table\n##\n## Parsed word corresponding to the first specifier are returned in the first\n## output argument and likewise for the rest of the specifiers.\n##\n## By default, @var{format} is @t{\"%f\"}, meaning that numbers are read from\n## @var{str}.  This will do if @var{str} contains only numeric fields.\n##\n## For example, the string\n##\n## @example\n## @group\n## @var{str} = \"\\\n## Bunny Bugs   5.5\\n\\\n## Duck Daffy  -7.5e-5\\n\\\n## Penguin Tux   6\"\n## @end group\n## @end example\n##\n## @noindent\n## can be read using\n##\n## @example\n## [@var{a}, @var{b}, @var{c}] = strread (@var{str}, \"%s %s %f\");\n## @end example\n##\n## Optional numeric argument @var{format_repeat} can be used for limiting the\n## number of items read:\n##\n## @table @asis\n## @item -1\n## (default) read all of the string until the end.\n##\n## @item N\n## Read N times @var{nargout} items.  0 (zero) is an acceptable value for\n## @var{format_repeat}.\n## @end table\n##\n## The behavior of @code{strread} can be changed via property-value pairs.  The\n## following properties are recognized:\n##\n## @table @asis\n## @item @qcode{\"commentstyle\"}\n## Parts of @var{str} are considered comments and will be skipped.\n## @var{value} is the comment style and can be any of the following.\n##\n## @itemize\n## @item @qcode{\"shell\"}\n## Everything from @code{#} characters to the nearest end-of-line is skipped.\n##\n## @item @qcode{\"c\"}\n## Everything between @code{/*} and @code{*/} is skipped.\n##\n## @item @qcode{\"c++\"}\n## Everything from @code{//} characters to the nearest end-of-line is skipped.\n##\n## @item @qcode{\"matlab\"}\n## Everything from @code{%} characters to the nearest end-of-line is skipped.\n##\n## @item user-supplied.  Two options:\n## (1) One string, or 1x1 cell string: Skip everything to the right of it;\n## (2) 2x1 cell string array: Everything between the left and right strings\n## is skipped.\n## @end itemize\n##\n## @item @qcode{\"delimiter\"}\n## Any character in @var{value} will be used to split @var{str} into words\n## (default value = any whitespace).  Note that whitespace is implicitly added\n## to the set of delimiter characters unless a @qcode{\"%s\"} format conversion\n## specifier is supplied; see @qcode{\"whitespace\"} parameter below.  The set\n## of delimiter characters cannot be empty; if needed Octave substitutes a\n## space as delimiter.\n##\n## @item @qcode{\"emptyvalue\"}\n## Value to return for empty numeric values in non-whitespace delimited data.\n## The default is NaN@.  When the data type does not support NaN (int32 for\n## example), then default is zero.\n##\n## @item @qcode{\"multipledelimsasone\"}\n## Treat a series of consecutive delimiters, without whitespace in between,\n## as a single delimiter.  Consecutive delimiter series need not be vertically\n## @qcode{\"aligned\"}.\n##\n## @item @qcode{\"treatasempty\"}\n## Treat single occurrences (surrounded by delimiters or whitespace) of the\n## string(s) in @var{value} as missing values.\n##\n## @item @qcode{\"returnonerror\"}\n## If @var{value} true (1, default), ignore read errors and return normally.\n## If false (0), return an error.\n##\n## @item @qcode{\"whitespace\"}\n## Any character in @var{value} will be interpreted as whitespace and trimmed;\n## the string defining whitespace must be enclosed in double quotes for proper\n## processing of special characters like @qcode{\"@backslashchar{}t\"}.  In\n## each data field, multiple consecutive whitespace characters are collapsed\n## into one space and leading and trailing whitespace is removed.  The default\n## value for whitespace is\n## @c Note: the next line specifically has a newline which generates a space\n## @c       in the output of qcode, but keeps the next line < 80 characters.\n## @qcode{\"\n## @backslashchar{}b@backslashchar{}r@backslashchar{}n@backslashchar{}t\"}\n## (note the space).  Whitespace is always added to the set of delimiter\n## characters unless at least one @qcode{\"%s\"} format conversion specifier is\n## supplied; in that case only whitespace explicitly specified in\n## @qcode{\"delimiter\"} is retained as delimiter and removed from the set of\n## whitespace characters.  If whitespace characters are to be kept as-is (in\n## e.g., strings), specify an empty value (i.e., @qcode{\"\"}) for\n## @qcode{\"whitespace\"}; obviously, whitespace cannot be a delimiter then.\n##\n## @end table\n##\n## When the number of words in @var{str} doesn't match an exact multiple of\n## the number of format conversion specifiers, strread's behavior depends on\n## the last character of @var{str}:\n##\n## @table @asis\n## @item last character = @qcode{\"@backslashchar{}n\"}\n## Data columns are padded with empty fields or NaN so that all columns have\n## equal length\n##\n## @item last character is not @qcode{\"@backslashchar{}n\"}\n## Data columns are not padded; strread returns columns of unequal length\n##\n## @end table\n##\n## @seealso{textscan, sscanf}\n## @end deftypefn\n\nfunction varargout = strread (str, format = \"%f\", varargin)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"strread is obsolete; use textscan instead\\n\");\n  endif\n\n  ## Check input\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isempty (str))\n    ## Return empty args (no match), rather than raising an error\n    varargout = cell (1, nargout);\n    return;\n  endif\n\n  if (isempty (format))\n    format = \"%f\";\n  endif\n\n  if (! ischar (str) || ! ischar (format))\n    error (\"strread: STR and FORMAT arguments must be strings\");\n  endif\n\n  if (strcmp (typeinfo (format), \"sq_string\"))\n    format = do_string_escapes (format);\n  endif\n\n  ## Parse format string to compare number of conversion fields and nargout\n  nfields = numel (regexp (format, '(%(\\d*|\\d*\\.\\d*)?[nfduscq]|%\\[)', \"match\"));\n  ## If str only has numeric fields, a (default) format (\"%f\") will do.\n  ## Otherwise:\n  if (! nfields)\n    error (\"strread.m: no valid format conversion specifiers found\\n\");\n  elseif ((max (nargout, 1) != nfields) && ! strcmp (format, \"%f\"))\n    error (\"strread: the number of output variables must match that specified by FORMAT\");\n  endif\n\n  ## Check for format string repeat count\n  format_repeat_count = -1;\n  if (nargin > 2 && isnumeric (varargin{1}))\n    if (varargin{1} >= 0)\n      format_repeat_count = varargin{1};\n    endif\n    if (nargin > 3)\n      varargin = varargin(2:end);\n    else\n      varargin = {};\n    endif\n  endif\n\n  ## Parse options.  First initialize defaults\n  comment_flag = false;\n  open_comment = false;\n  cmt_eol = \"\\n\";\n  delimiter_str = \"\";\n  empty_str = \"\";\n  eol_char = \"\";\n  err_action = 0;\n  mult_dlms_s1 = false;\n  numeric_fill_value = NaN;\n  white_spaces = \" \\b\\r\\n\\t\";\n  for n = 1:2:length (varargin)\n    switch (lower (varargin{n}))\n      case \"bufsize\"\n        ## We could synthesize this, but that just seems weird...\n        warning (\"strread: property 'bufsize' is not implemented\");\n      case \"commentstyle\"\n        comment_flag = true;\n        switch (lower (varargin{n+1}))\n          case \"c\"\n            [comment_start, comment_end] = deal (\"/*\", \"*/\");\n          case \"c++\"\n            [comment_start, comment_end] = deal (\"//\", \"cmt_eol\");\n            open_comment = true;\n          case \"shell\"\n            [comment_start, comment_end] = deal (\"#\" , \"cmt_eol\");\n            open_comment = true;\n          case \"matlab\"\n            [comment_start, comment_end] = deal (\"%\" , \"cmt_eol\");\n            open_comment = true;\n          otherwise\n            if (ischar (varargin{n+1})\n                || (numel (varargin{n+1}) == 1 && iscellstr (varargin{n+1})))\n              [comment_start, comment_end] = deal (char (varargin{n+1}), \"cmt_eol\");\n            open_comment = true;\n            elseif (iscellstr (varargin{n+1}) && numel (varargin{n+1}) == 2)\n              [comment_start, comment_end] = deal (varargin{n+1}{:});\n            else\n              ## FIXME: A user may have numeric values specified: {'//', 7}\n              ##        this will lead to an error in the warning message\n              error (\"strread: unknown or unrecognized comment style '%s'\",\n                      varargin{n+1});\n            endif\n        endswitch\n      case \"delimiter\"\n        delimiter_str = varargin{n+1};\n        if (strcmp (typeinfo (delimiter_str), \"sq_string\"))\n          delimiter_str = do_string_escapes (delimiter_str);\n        endif\n      case \"emptyvalue\"\n        numeric_fill_value = varargin{n+1};\n      case \"expchars\"\n        warning (\"strread: property 'expchars' is not implemented\");\n      case \"whitespace\"\n        white_spaces = varargin{n+1};\n        if (strcmp (typeinfo (white_spaces), \"sq_string\"))\n          white_spaces = do_string_escapes (white_spaces);\n        endif\n      ## The following parameters are specific to textscan and textread\n      case \"endofline\"\n        eol_char = varargin{n+1};\n        if (strcmp (typeinfo (eol_char), \"sq_string\"))\n          eol_char = do_string_escapes (eol_char);\n        endif\n        cmt_eol = eol_char;\n        open_comment = false;\n      case \"returnonerror\"\n        err_action = varargin{n+1};\n      case \"multipledelimsasone\"\n        mult_dlms_s1 = varargin{n+1};\n      case \"treatasempty\"\n        if (iscellstr (varargin{n+1}))\n          empty_str = varargin{n+1};\n        elseif (ischar (varargin{n+1}))\n          empty_str = varargin(n+1);\n        else\n          error (\"strread: 'treatasempty' value must be string or cellstr\");\n        endif\n      otherwise\n        warning (\"strread: unknown property '%s'\", varargin{n});\n    endswitch\n  endfor\n\n  ## First parse of FORMAT\n  if (strcmpi (strtrim (format), \"%f\"))\n    ## Default format specified.  Expand it (to desired nargout)\n    fmt_words = cell (max (nargout, 1), 1);\n    fmt_words (1:max (nargout, 1)) = format;\n  else\n    ## Determine the number of words per line as a first guess.  Forms\n    ## like %f<literal>) (w/o delimiter in between) are fixed further on\n    format = strrep (format, \"%\", \" %\");\n    fmt_words = regexp (format, '[^ ]+', \"match\");\n\n    ## Find position of conversion specifiers (they start with %)\n    fcs_ptrn = '(%\\*?(\\d*|\\d*\\.\\d*)?[nfduscq]|%\\*?\\[)';\n    idy2 = find (! cellfun (\"isempty\", regexp (fmt_words, fcs_ptrn)));\n\n    ## Check for unsupported format specifiers\n    errpat = '(\\[.*\\]|[cq]|[nfdu]8|[nfdu]16|[nfdu]32|[nfdu]64)';\n    if (! all (cellfun (\"isempty\", regexp (fmt_words(idy2), errpat))))\n      error (\"strread: %q, %c, %[] or bit width format specifiers are not supported yet\");\n    endif\n\n    ## Format conversion specifiers following literals w/o space/delim\n    ## in between are separate now.  Separate those w trailing literals\n    a = strfind (fmt_words(idy2), \"%\");\n    b = regexp (fmt_words(idy2), '[nfdus]', \"end\");\n    for jj = 1:numel (a)\n      ## From right to left to avoid losing track\n      ii = numel (a) - jj + 1;\n      ## Check for illegal format specifiers\n      if (isempty (b{ii}))\n        error (\"strread: unknown format specifier #%d ('%s')\\n\",\n              ii, fmt_words{idy2(ii)});\n      endif\n      if (! (length (fmt_words{idy2(ii)}) == b{ii}(1)))\n        ## Split fmt_words(ii) into % conv specifier and trailing literal\n        fmt_words(idy2(ii)+1 : end+1) = fmt_words(idy2(ii) : end);\n        fmt_words{idy2(ii)} = fmt_words{idy2(ii)}(a{ii} : b{ii}(1));\n        fmt_words{idy2(ii)+1} = fmt_words{idy2(ii)+1}(b{ii}+1:end);\n      endif\n    endfor\n  endif\n  num_words_per_line = numel (fmt_words);\n\n  ## Special handling for CRLF EOL character in str\n  if (! isempty (eol_char) && strcmp (eol_char, \"\\r\\n\"))\n    ## Strip CR from CRLF sequences\n    str = strrep (str, \"\\r\\n\", \"\\n\");\n    ## CR serves no further purpose in function\n    eol_char = \"\\n\";\n  endif\n\n  ## Remove comments in str\n  if (comment_flag)\n    ## Expand 'cmt_eol' here, after option processing which may have set value\n    comment_end = strrep (comment_end, \"cmt_eol\", cmt_eol);\n    cstart = strfind (str, comment_start);\n    cstop  = strfind (str, comment_end);\n    if (open_comment)\n      cstop -= 1;\n    endif\n    ## Treat end of string as additional comment stop\n    if (isempty (cstop) || cstop(end) != length (str))\n      cstop(end+1) = length (str);\n    endif\n    if (! isempty (cstart))\n      ## Ignore nested openers.\n      [idx, cidx] = unique (lookup (cstop, cstart), \"first\");\n      if (idx(end) == length (cstop))\n        cidx(end) = []; # Drop the last one if orphaned.\n      endif\n      cstart = cstart(cidx);\n    endif\n    if (! isempty (cstop))\n      ## Ignore nested closers.\n      [idx, cidx] = unique (lookup (cstart, cstop), \"first\");\n      if (idx(1) == 0)\n        cidx(1) = []; # Drop the first one if orphaned.\n      endif\n      cstop = cstop(cidx);\n    endif\n    len = length (str);\n    c2len = length (comment_end);\n    if (cstop + c2len == len)\n      ## Ignore last char of to-the-end-of-line comments\n      c2len += 1;\n    endif\n    str = cellslices (str, [1, cstop + c2len], [cstart - 1, len]);\n    str = [str{:}];\n  endif\n\n  if (! isempty (white_spaces))\n    ## For numeric fields, whitespace is always a delimiter, but not for text\n    ## fields\n    if (isempty (regexp (format, '%\\*?\\d*s')))\n      ## Add whitespace to delimiter set\n      delimiter_str = unique ([white_spaces delimiter_str]);\n    else\n      ## Remove any delimiter chars from white_spaces list\n      white_spaces = setdiff (white_spaces, delimiter_str);\n    endif\n  endif\n  if (isempty (delimiter_str))\n    delimiter_str = \" \";\n  endif\n  if (! isempty (eol_char))\n    ## Add eol_char to delimiter collection\n    delimiter_str = unique ([delimiter_str eol_char]);\n    ## and remove it from whitespace collection\n    white_spaces = strrep (white_spaces, eol_char, '');\n  endif\n\n  ii = numel (fmt_words);\n  while (ii > 0)\n    if (ismember (fmt_words{ii}, delimiter_str)(1))\n      fmt_words(ii) = [];\n      --num_words_per_line;\n    endif\n    --ii;\n  endwhile\n\n  pad_out = 0;\n  ## Trim whitespace if needed\n  if (! isempty (white_spaces))\n    ## Check if trailing \"\\n\" might signal padding output arrays to equal size\n    ## before it is trimmed away below\n    if (str(end) == \"\\n\" && nargout > 1)\n      pad_out = 1;\n    endif\n    ## Condense all repeated whitespace into one single space\n    ## FIXME: this will also fold repeated whitespace in a char field\n    rxp_wsp = sprintf (\"[%s]+\", white_spaces);\n    str = regexprep (str, rxp_wsp, ' ');\n    ## Remove possible leading space at string\n    if (str(1) == \" \")\n       str = str(2:end);\n    endif\n    ## Check for single delimiter followed/preceded by whitespace\n    if (! isempty (delimiter_str))\n      dlmstr = setdiff (delimiter_str, \" \");\n      if (! isempty (dlmstr))\n        rxp_dlmwsp = sprintf ('( [%s] | [%s]|[%s] )', dlmstr, dlmstr, dlmstr);\n        str = regexprep (str, rxp_dlmwsp, delimiter_str(1));\n      endif\n    endif\n    ## Wipe leading and trailing whitespace on each line (it may be\n    ## delimiter too)\n    ## FIXME: Double strrep on str is enormously expensive in CPU time.\n    ## Can this be eliminated?\n    if (! isempty (eol_char))\n      str = strrep (str, [eol_char \" \"], eol_char);\n      str = strrep (str, [\" \" eol_char], eol_char);\n    endif\n  endif\n\n  ## Split 'str' into words\n  words = split_by (str, delimiter_str, mult_dlms_s1, eol_char);\n  if (! isempty (white_spaces))\n    ## Trim leading and trailing 'white_spaces'.\n    ## All whitespace has been converted to space above\n    words = strtrim (words);\n  endif\n  num_words = numel (words);\n  ## First guess at nr. of lines in file (ignoring leading/trailing literals)\n  num_lines = ceil (num_words / num_words_per_line);\n\n  ## Replace TreatAsEmpty char sequences by empty strings\n  if (! isempty (empty_str))\n    for ii = 1:numel (empty_str)\n      idz = strncmp (empty_str{ii}, words, length (empty_str{ii}));\n      words(idz) = {\"\"};\n    endfor\n  endif\n\n  ## fmt_words has been split properly now, but words{} has only been split on\n  ## delimiter positions.  As numeric fields can also be separated by\n  ## whitespace, more splits may be needed.\n  ## We also don't know the number of lines (as EndOfLine may have been set to\n  ## \"\" (empty) by the caller).\n  ##\n  ## We also may have to cope with 3 cases as far as literals go:\n  ## A: Trailing literals (%f<literal>) w/o delimiter in between.\n  ## B: Leading literals (<literal>%f) w/o delimiter in between.\n  ## C. Skipping leftover parts of specified skip fields (%*N )\n  ## Some words columns may have to be split further to fix these.\n  ## To find out, we'll match fmt_words to the words array to see what\n  ## needs to be done.  fwptr tracks which {fmt_words} starts in what {words}\n\n  ## Find indices and pointers to possible literals in fmt_words\n  idf = cellfun (\"isempty\", strfind (fmt_words, \"%\"));\n  ## Find indices and pointers to conversion specifiers with fixed width\n  idg = ! cellfun (\"isempty\", regexp (fmt_words, '%\\*?\\d'));\n  idy = find (idf | idg);\n  ## Find indices to numeric conversion specifiers\n  idn = ! cellfun (\"isempty\", regexp (fmt_words, '%[dnfu]'));\n\n  ## If needed, split up columns in three steps:\n  if (! isempty (idy))\n    ## Try-catch because complexity of strings to read can be infinite\n    try\n\n      ## 1. Assess \"period\" in the split-up words array ( < num_words_per_line).\n      ## Could be done using EndOfLine but that prohibits EndOfLine = \"\" option.\n      ## Alternative below goes by simply parsing a first grab of words and\n      ## matching fmt_words to words until the fmt_words array is exhausted.\n      ## iwrd: ptr to current analyzed word.\n      ## iwrdp: ptr to pos before analyzed char.\n      iwrd = 1; iwrdp = 0; iwrdl = length (words{1});\n      fwptr = zeros (1, numel (fmt_words));\n      ii = 1;\n      while (ii <= numel (fmt_words))\n\n        nxt_wrd = 0;\n        ## Keep track of which words nr. every fmt_words{} is (starts) in.\n        fwptr(ii) = iwrd;\n\n        if (idf(ii))\n          ## Literal expected\n          if (isempty (strfind (fmt_words{ii}, words(iwrd))))\n            ## Not found in current word; supposed to be in next word\n            nxt_wrd = 1;\n          else\n            ## Found it in current word.  Subtract literal length\n            iwrdp += length (fmt_words{ii});\n            if (iwrdp > iwrdl)\n              ## Parse error.  Literal extends beyond delimiter (word boundary)\n              warning (\"strread: literal '%s' (fmt spec # %d) does not match data\", ...\n                fmt_words{ii}, ii);\n              ## Word assumed to be completely \"used up\".  Next word\n              nxt_wrd = 1;\n            elseif (iwrdp == iwrdl)\n              ## Word completely \"used up\".  Next word\n              nxt_wrd = 1;\n            endif\n          endif\n\n        elseif (idg(ii))\n          ## Fixed width specifier (%N or %*N): read just a part of word\n          sw = regexp (fmt_words{ii}, '\\d', \"once\");\n          ew = regexp (fmt_words{ii}, '[nfuds]') - 1;\n          iwrdp += floor (str2double (fmt_words{ii}(sw:ew)));\n          if (iwrdp > iwrdl)\n            ## Match error.  Field extends beyond word boundary.\n            warning  ...\n            (\"strread: field width '%s' (fmt spec # %d) extends beyond actual word limit\", ...\n               fmt_words{ii}, ii);\n            ## Assume word to be completely \"used up\".  Next word\n            nxt_wrd = 1;\n          elseif (iwrdp == iwrdl)\n            ## Word completely \"used up\".  Next word\n            nxt_wrd = 1;\n          endif\n\n        else\n          ## A simple format conv. specifier.  Either (1) uses rest of word, or\n          ## (2) is squeezed between current iwrdp and next literal, or (3) uses\n          ## next word.  (3) is already taken care of.  So just check (1) & (2)\n          if (ii < numel (fmt_words) && idf(ii+1))\n            ## Next fmt_word is a literal...\n            if (! index (words{iwrd}(iwrdp+1:end), fmt_words{ii+1}))\n              ## ...but not found in current word => field uses rest of word\n              nxt_wrd = 1;\n            else\n              ## ..or it IS found.  Add inferred width of current conversion field\n              iwrdp += index (words{iwrd}(iwrdp+1:end), fmt_words{ii+1}) - 1;\n            endif\n          elseif (iwrdp <= iwrdl)\n            ## No bordering literal to the right => field occupies (rest of) word\n            nxt_wrd = 1;\n          endif\n\n        endif\n\n        if (nxt_wrd)\n          ++iwrd; iwrdp = 0;\n          if (iwrd > numel (words))\n            ## Apparently EOF; assume incomplete row already at L.1 of data\n            ii = numel (fmt_words);\n          elseif (ii < numel (fmt_words) && iwrd <= numel (words))\n            iwrdl = length (words{iwrd});\n          endif\n        endif\n\n        ++ii;\n\n      endwhile\n      ## Done\n      words_period = max (iwrd - 1, 1);\n      num_lines = ceil (num_words / words_period);\n\n      ## 2. Pad words array so that it can be reshaped\n      num_words_padded = num_lines * words_period - num_words;\n      if (num_words_padded)\n        words = [words'; cell(num_words_padded, 1)];\n      endif\n      words = reshape (words, words_period, num_lines);\n\n      ## 3. Do the column splitting on rectangular words array\n      icol = 1; ii = 1;    # icol = current column, ii = current fmt_word\n      while (ii <= num_words_per_line)\n\n        ## Check if fmt_words(ii) contains a literal or fixed-width\n        if ((idf(ii) || idg(ii)) && (rows (words) < num_words_per_line))\n          if (idf(ii))\n            s = strfind (words(icol, 1), fmt_words{ii});\n            if (isempty (s{:}))\n              error (\"strread: Literal '%s' not found in column %d\", fmt_words{ii}, icol);\n            endif\n            s = s{:}(1);\n            e = s(1) + length (fmt_words{ii}) - 1;\n          endif\n          if (! strcmp (fmt_words{ii}, words{icol, 1}))\n            ## Column doesn't exactly match literal => split needed.\n            ## Insert a column\n            words(icol+1:end+1, :) = words(icol:end, :);\n            ## Watch out for empty cells\n            jptr = find (! cellfun (\"isempty\", words(icol, :)));\n\n            ## Distinguish leading or trailing literals\n            if (! idg(ii) && ! isempty (s) && s(1) == 1)\n              ## Leading literal.\n              ## Assign literal to icol, paste rest in icol + 1\n              ## Apply only to those cells that do have something beyond literal\n              jptr = find (cellfun (\"length\", words(icol+1, jptr)) > e(1));\n              words(icol+1, :) = {\"\"};\n              words(icol+1, jptr) = cellfun (\n                @(x) substr (x, e(1)+1, length (x) - e(1)), words(icol, jptr),\n                \"UniformOutput\", false);\n              words(icol, jptr) = fmt_words{ii};\n              fwptr = [fwptr(1:ii) (++fwptr(ii+1:end))];\n\n            else\n              if (idg(ii))\n                ## Current field = fixed width.\n                ## Strip into icol, rest in icol+1\n                sw = regexp (fmt_words{ii}, '\\d', \"once\");\n                ew = regexp (fmt_words{ii}, '[nfuds]') - 1;\n                wdth = floor (str2double (fmt_words{ii}(sw:ew)));\n                words(icol+1, jptr) = cellfun (@(x) x(wdth+1:end),\n                     words(icol,jptr), \"UniformOutput\", false);\n                if (isempty ([words(icol+1, :){:}]))\n                  ## Apparently split wasn't needed as turns out to cover\n                  ## entire column.  So delete column again\n                  words(icol+1, :) = [];\n                else\n                  words(icol, jptr) = strtrunc (words(icol, jptr), wdth);\n                  fwptr = [fwptr(1:ii) (++fwptr(ii+1:end))];\n                endif\n              else\n                if (! isempty (strfind (fmt_words{ii-1}, \"%s\")))\n                  ## Trailing literal.\n                  ## Could be ambiguous if preceding format == '%s'\n                  warning (\"strread.m:\\n  Ambiguous '%%s' specifier immediately before literal in column %d\", icol);\n                endif\n                ## FIXME: this assumes char(254)/char(255) won't occur in input!\n                clear wrds;\n                wrds(1:2:2*numel (words(icol, jptr))) = ...\n                     strrep (words(icol, jptr), fmt_words{ii}, ...\n                     [char(255) char(254)]);\n                wrds(2:2:2*numel (words(icol, jptr))-1) = char (255);\n                wrds = ostrsplit ([wrds{:}], char (255));\n                words(icol, jptr) = ...\n                  wrds(find (cellfun (\"isempty\", strfind (wrds, char (254)))));\n                wrds(find (cellfun (\"isempty\", strfind (wrds, char (254))))) ...\n                   = char (255);\n                words(icol+1, jptr) = ostrsplit (strrep ([wrds{2:end}], ...\n                   char (254), fmt_words{ii}), char (255));\n                ## Former trailing literal may now be leading for next specifier\n                --ii;\n                fwptr = [fwptr(1:ii) (++fwptr(ii+1:end))];\n              endif\n            endif\n          endif\n\n        else\n          ## Conversion specifier.\n          ## Peek if next fmt_word needs split from current column.\n          if (ii < num_words_per_line)\n            if (fwptr(ii) == fwptr(ii+1))\n              --icol;\n            endif\n          endif\n        endif\n        ## Next fmt_word, next column\n        ++ii; ++icol;\n      endwhile\n\n      ## Done.\n      ## Reshape words back into one long vector and strip padded empty words\n      words = reshape (words, 1, numel (words))(1 : end-num_words_padded);\n\n    catch\n      warning (\"strread: unable to parse text or file with given format string\");\n      return;\n\n    end_try_catch\n  endif\n\n  ## For each specifier, process corresponding column\n  k = 1;\n  for m = 1:num_words_per_line\n    try\n      if (format_repeat_count < 0)\n        data = words(m:num_words_per_line:end);\n      elseif (format_repeat_count == 0)\n        data = {};\n      else\n        lastline = ...\n          min (num_words_per_line * format_repeat_count + m - 1, numel (words));\n        data = words(m:num_words_per_line:lastline);\n        if (num_lines > format_repeat_count)\n          num_lines = format_repeat_count;\n        endif\n      endif\n\n      ## Map to format\n      ## FIXME: Add support for formats like \"<%s>\", \"%[a-zA-Z]\"\n      ##        Someone with regexp experience is needed.\n      switch (fmt_words{m}(1:min (2, length (fmt_words{m}))))\n        case \"%s\"\n          if (pad_out)\n            data(end+1:num_lines) = {\"\"};\n          endif\n          varargout{k} = data';\n          k += 1;\n        case {\"%d\", \"%u\", \"%f\", \"%n\"}\n          n = cellfun (\"isempty\", data);\n          ### FIXME: Erroneously formatted data lead to NaN, not an error\n          data = str2double (data);\n          if (! isempty (regexp (fmt_words{m}, \"%[du]\")))\n            ## Cast to integer\n            ## FIXME: NaNs will be transformed into zeros\n            data = int32 (data);\n          endif\n          data(n) = numeric_fill_value;\n          if (pad_out)\n            data(end+1:num_lines) = numeric_fill_value;\n          endif\n          varargout{k} = data.';\n          k += 1;\n        case {\"%0\", \"%1\", \"%2\", \"%3\", \"%4\", \"%5\", \"%6\", \"%7\", \"%8\", \"%9\"}\n          sw = regexp (fmt_words{m}, '\\d', \"once\");\n          ew = regexp (fmt_words{m}, '[nfudsq]') - 1;\n          nfmt = ostrsplit (fmt_words{m}(2:ew), \".\");\n          swidth = str2double (nfmt{1});\n          switch (fmt_words{m}(ew+1))\n            case {\"d\", \"u\", \"f\", \"n\"}\n              n = cellfun (\"isempty\", data);\n              ### FIXME: Erroneously formatted data lead to NaN, not an error\n              ###        => ReturnOnError can't be implemented for numeric data\n              data = str2double (strtrunc (data, swidth));\n              data(n) = numeric_fill_value;\n              if (pad_out)\n                data(end+1:num_lines) = numeric_fill_value;\n              endif\n              if (numel (nfmt) > 1)\n                sprec = str2double (nfmt{2});\n                data = 10^-sprec * round (10^sprec * data);\n              elseif (! isempty (regexp (fmt_words{m}, \"[du]\")))\n                ## Cast to integer\n                ## FIXME: NaNs will be transformed into zeros\n                data = int32 (data);\n              endif\n              varargout{k} = data.';\n              k += 1;\n            case \"s\"\n              if (pad_out)\n                data(end+1:num_lines) = {\"\"};\n              endif\n              varargout{k} = strtrunc (data, swidth)';\n              k += 1;\n            otherwise\n          endswitch\n        case {\"%*\", \"%*s\"}\n          ## skip the word\n        otherwise\n          ## Ensure descriptive content is consistent.\n          ## Test made a bit lax to accommodate for incomplete last lines\n          n = find (! cellfun (\"isempty\", data));\n          if (numel (unique (data(n))) > 1\n              || ! strcmpi (unique (data), fmt_words{m}))\n            error (\"strread: FORMAT does not match data\");\n          endif\n      endswitch\n    catch\n      ## As strread processes columnwise, ML-compatible error processing\n      ## (row after row) is not feasible.  In addition Octave sets\n      ## unrecognizable numbers to NaN w/o error.  But maybe Octave is better\n      ## in this respect.\n      if (err_action)\n        ## Just try the next column where ML bails out\n      else\n        rethrow (lasterror);\n      endif\n    end_try_catch\n  endfor\n\nendfunction\n\nfunction out = split_by (text, sep, mult_dlms_s1, eol_char)\n\n  ## Check & if needed, process MultipleDelimsAsOne parameter\n  if (mult_dlms_s1)\n    mult_dlms_s1 = true;\n    ## FIXME: Should re-implement strsplit() function here in order\n    ## to avoid strrep on megabytes of data.\n    ## If \\n is in sep collection we need to enclose it in text\n    ## to avoid it being included in consecutive delim series\n    enchr = ' ';\n    ## However watch out if eol_char is also in delimiters\n    if (index (sep, eol_char)); enchr = char (255); endif\n    text = strrep (text, eol_char, [enchr eol_char enchr]);\n  else\n    mult_dlms_s1 = false;\n  endif\n\n  ## Split text string along delimiters\n  out = ostrsplit (text, sep, mult_dlms_s1);\n  if (index (sep, eol_char)); out = strrep (out, char (255), ''); endif\n  ## In case of trailing delimiter, strip stray last empty word\n  if (! isempty (out) && any (sep == text(end)) && ! mult_dlms_s1)\n    out(end) = [];\n  endif\n\n  ## Empty cells converted to empty cellstrings.\n  out(cellfun (\"isempty\", out)) = {\"\"};\n\nendfunction\n\n\n## First test is necessary to provoke 1-time legacy warning\n%!test\n%! warning (\"off\", \"Octave:legacy-function\", \"local\");\n%! strread (\"\");\n\n%!test\n%! [a, b] = strread (\"1 2\", \"%f%f\");\n%! assert (a, 1);\n%! assert (b, 2);\n\n%!test\n%! str = \"\";\n%! a = rand (10, 1);\n%! b = char (randi ([65, 85], 10, 1));\n%! for k = 1:10\n%!   str = sprintf (\"%s %.6f %s\\n\", str, a(k), b(k));\n%! endfor\n%! [aa, bb] = strread (str, \"%f %s\");\n%! assert (aa, a, 1e-6);\n%! assert (bb, cellstr (b));\n\n%!test\n%! str = \"\";\n%! a = rand (10, 1);\n%! b = char (randi ([65, 85], 10, 1));\n%! for k = 1:10\n%!   str = sprintf (\"%s %.6f %s\\n\", str, a(k), b(k));\n%! endfor\n%! aa = strread (str, \"%f %*s\");\n%! assert (aa, a, 1e-6);\n\n%!test\n%! str = sprintf (\"/* this is\\nacomment*/ 1 2 3\");\n%! a = strread (str, \"%f\", \"commentstyle\", \"c\");\n%! assert (a, [1; 2; 3]);\n\n%!test\n%! str = \"# comment\\n# comment\\n1 2 3\";\n%! [a, b] = strread (str, \"%n %s\", \"commentstyle\", \"shell\", \"endofline\", \"\\n\");\n%! assert (a, [1; 3]);\n%! assert (b, {\"2\"});\n\n%!test\n%! assert (strread (\"Hello World! // this is comment\", \"%s\",\n%!                  \"commentstyle\", \"c++\"),\n%!         {\"Hello\"; \"World!\"});\n%! assert (strread (\"Hello World! % this is comment\", \"%s\",...\n%!                  \"commentstyle\", \"matlab\"), ...\n%!         {\"Hello\"; \"World!\"});\n%! assert (strread (\"Hello World! # this is comment\", \"%s\",...\n%!                  \"commentstyle\", \"shell\"), ...\n%!         {\"Hello\"; \"World!\"});\n\n%!test <*49454>\n%! assert (strread (\"hello%foo\\nworld, another%bar\\r\\nday\", \"%s\", ...\n%!                  \"commentstyle\", \"matlab\", \"delimiter\", \" ,\"),...\n%!         {\"hello\"; \"world\"; \"another\"; \"day\"});\n\n%!test\n%! str = sprintf (\"Tom 100 miles/hr\\nDick 90 miles/hr\\nHarry 80 miles/hr\");\n%! fmt = \"%s %f miles/hr\";\n%! c = cell (1, 2);\n%! [c{:}] = strread (str, fmt);\n%! assert (c{1}, {\"Tom\"; \"Dick\"; \"Harry\"});\n%! assert (c{2}, [100; 90; 80]);\n\n%!test\n%! a = strread (\"a b c, d e, , f\", \"%s\", \"delimiter\", \",\");\n%! assert (a, {\"a b c\"; \"d e\"; \"\"; \"f\"});\n\n%! ## Format repeat counters w & w/o trailing EOL even within partly read files\n%!test\n%! [a, b] = strread (\"10 a 20 b\\n 30 c 40\", \"%d %s\", 4);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"});\n%! [a, b] = strread (\"10 a 20 b\\n 30 c 40\\n\", \"%d %s\", 4);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"; \"\"});\n%! [a, b] = strread (\"10 a 20 b\\n 30 c 40\", \"%d %s\", 1);\n%! assert (a, int32 (10));\n%! assert (b, {\"a\"});\n\n%!test <*33536>\n%! [a, b, c] = strread (\"1,,2\", \"%s%s%s\", \"delimiter\", \",\");\n%! assert (a{1}, \"1\");\n%! assert (b{1}, \"\");\n%! assert (c{1}, \"2\");\n\n%!test <*33536>\n%!test\n%! a = strread (\"[SomeText]\", \"[%s\", \"delimiter\", \"]\");\n%! assert (a{1}, \"SomeText\");\n\n%!test\n%! dat = \"Data file.\\r\\n=  =  =  =  =\\r\\nCOMPANY    : <Company name>\\r\\n\";\n%! a = strread (dat, \"%s\", \"delimiter\", \"\\n\", \"whitespace\", \"\", \"endofline\", \"\\r\\n\");\n%! assert (a{2}, \"=  =  =  =  =\");\n%! assert (double (a{3}(end-5:end)), [32 110 97 109 101 62]);\n\n%!test\n%! [a, b, c, d] = strread (\"1,2,3,,5,6\", \"%d%f%d%f\", \"delimiter\", \",\");\n%! assert (c, int32 (3));\n%! assert (d, NaN);\n\n%!test\n%! [a, b, c, d] = strread (\"1,2,3,,5,6\\n\", \"%d%d%f%d\", \"delimiter\", \",\");\n%! assert (c, [3; NaN]);\n%! assert (d, int32 ([0; 0]));\n\n## Default format (= %f)\n%!test\n%! [a, b, c] = strread (\"0.12 0.234 0.3567\");\n%! assert (a, 0.12);\n%! assert (b, 0.234);\n%! assert (c, 0.3567);\n\n%!test\n%! [a, b] = strread (\"0.41 8.24 3.57 6.24 9.27\", \"%f%f\", 2, \"delimiter\", \" \");\n%! assert (a, [0.41; 3.57]);\n\n## TreatAsEmpty\n%!test\n%! [a, b, c, d] = strread (\"1,2,3,NN,5,6\\n\", \"%d%d%d%f\", \"delimiter\", \",\", \"TreatAsEmpty\", \"NN\");\n%! assert (c, int32 ([3; 0]));\n%! assert (d, [NaN; NaN]);\n\n## No delimiters at all besides EOL.  Plain reading numbers & strings\n%!test\n%! str = \"Text1Text2Text\\nText398Text4Text\\nText57Text\";\n%! [a, b] = strread (str, \"Text%dText%1sText\");\n%! assert (a, int32 ([1; 398; 57]));\n%! assert (b(1:2), {\"2\"; \"4\"});\n%! assert (isempty (b{3}), true);\n\n## MultipleDelimsAsOne\n%!test\n%! str = \"11, 12, 13,, 15\\n21,, 23, 24, 25\\n,, 33, 34, 35\";\n%! [a b c d] = strread (str, \"%f %f %f %f\", \"delimiter\", \",\", \"multipledelimsasone\", 1, \"endofline\", \"\\n\");\n%! assert (a', [11, 21, NaN]);\n%! assert (b', [12, 23, 33]);\n%! assert (c', [13, 24, 34]);\n%! assert (d', [15, 25, 35]);\n\n%!assert <*44750> (strread ('/home/foo/','%s','delimiter','/','MultipleDelimsAsOne',1),\n%!                {\"home\"; \"foo\"})\n\n## delimiter as sq_string and dq_string\n%!assert (strread (\"1\\n2\\n3\", \"%d\", \"delimiter\", \"\\n\"),\n%!        strread (\"1\\n2\\n3\", \"%d\", \"delimiter\", '\\n'))\n\n## whitespace as sq_string and dq_string\n%!assert (strread (\"1\\b2\\r3\\b4\\t5\", \"%d\", \"whitespace\", \"\\b\\r\\n\\t\"),\n%!        strread (\"1\\b2\\r3\\b4\\t5\", \"%d\", \"whitespace\", '\\b\\r\\n\\t'))\n\n%!test\n%! str =  \"0.31 0.86 0.94\\n 0.60 0.72 0.87\";\n%! fmt = \"%f %f %f\";\n%! args = {\"delimiter\", \" \", \"endofline\", \"\\n\", \"whitespace\", \" \"};\n%! [a, b, c] = strread (str, fmt, args{:});\n%! assert (a, [0.31; 0.60], 0.01);\n%! assert (b, [0.86; 0.72], 0.01);\n%! assert (c, [0.94; 0.87], 0.01);\n\n%!test\n%! str =  \"0.31,0.86,0.94\\n0.60,0.72,0.87\";\n%! fmt = \"%f %f %f\";\n%! args = {\"delimiter\", \",\", \"endofline\", \"\\n\", \"whitespace\", \" \"};\n%! [a, b, c] = strread (str, fmt, args{:});\n%! assert (a, [0.31; 0.60], 0.01);\n%! assert (b, [0.86; 0.72], 0.01);\n%! assert (c, [0.94; 0.87], 0.01);\n\n%!test\n%! str =  \"0.31 0.86 0.94\\n 0.60 0.72 0.87\";\n%! fmt = \"%f %f %f\";\n%! args = {\"delimiter\", \",\", \"endofline\", \"\\n\", \"whitespace\", \" \"};\n%! [a, b, c] = strread (str, fmt, args{:});\n%! assert (a, [0.31; 0.60], 0.01);\n%! assert (b, [0.86; 0.72], 0.01);\n%! assert (c, [0.94; 0.87], 0.01);\n\n%!test\n%! str =  \"0.31, 0.86, 0.94\\n 0.60, 0.72, 0.87\";\n%! fmt = \"%f %f %f\";\n%! args = {\"delimiter\", \",\", \"endofline\", \"\\n\", \"whitespace\", \" \"};\n%! [a, b, c] = strread (str, fmt, args{:});\n%! assert (a, [0.31; 0.60], 0.01);\n%! assert (b, [0.86; 0.72], 0.01);\n%! assert (c, [0.94; 0.87], 0.01);\n\n%!test\n%! [a, b] = strread ([\"Empty 1\" char(10)], \"Empty%s %f\");\n%! assert (a{1}, '1');\n%! assert (b, NaN);\n\n%!test\n%! [a, b] = strread ([\"Empty\" char(10)], \"Empty%f %f\");\n%! assert (a, NaN);\n%! assert (b, NaN);\n\n%!test <*35999>\n%! [a, b, c] = strread (\"\", \"%f\");\n%! assert (isempty (a));\n%! assert (isempty (b));\n%! assert (isempty (c));\n\n%!test <*37023>\n%! [a, b] = strread (\" 1. 1 \\n  2 3 \\n\", \"%f %f\", \"endofline\", \"\\n\");\n%! assert (a, [1; 2], 1e-15);\n%! assert (b, [1; 3], 1e-15);\n\n## Test for no output arg (interactive use)\n%!assert (strread (\",2,,4\\n5,,7,\", \"\", \"delimiter\", \",\"),\n%!        [NaN; 2; NaN; 4; 5; NaN; 7])\n\n## Test #1 bug #42609\n%!test <*42609>\n%! [a, b, c] = strread (\"1 2 3\\n4 5 6\\n7 8 9\\n\", \"%f %f %f\\n\");\n%! assert (a, [1; 4; 7]);\n%! assert (b, [2; 5; 8]);\n%! assert (c, [3; 6; 9]);\n\n## Test #2 bug #42609\n%!test <*42609>\n%! [a, b, c] = strread (\"1 2\\n3\\n4 5\\n6\\n7 8\\n9\\n\", \"%f %f\\n%f\");\n%! assert (a, [1;4;7]);\n%! assert (b, [2; 5; 8]);\n%! assert (c, [3; 6; 9]);\n\n## Test #3 bug #42609\n%!test <*42609>\n%! [a, b, c] = strread (\"1 2 3\\n4 5 6\\n7 8 9\\n\", '%f %f %f\\n');\n%! assert (a, [1; 4; 7]);\n%! assert (b, [2; 5; 8]);\n%! assert (c, [3; 6; 9]);\n\n## Test #4 bug #42609\n%!test <*42609>\n%! [a, b, c] = strread (\"1 2\\n3\\n4 5\\n6\\n7 8\\n9\\n\", '%f %f\\n%f');\n%! assert (a, [1;4;7]);\n%! assert (b, [2; 5; 8]);\n%! assert (c, [3; 6; 9]);\n\n## Unsupported format specifiers\n%!error <format specifiers are not supported> strread (\"a\", \"%c\")\n%!error <format specifiers are not supported> strread (\"a\", \"%*c %d\")\n%!error <format specifiers are not supported> strread (\"a\", \"%q\")\n%!error <format specifiers are not supported> strread (\"a\", \"%*q %d\")\n%!error <format specifiers are not supported> strread (\"a\", \"%[a]\")\n%!error <format specifiers are not supported> strread (\"a\", \"%*[a] %d\")\n%!error <format specifiers are not supported> strread (\"a\", \"%[^a]\")\n%!error <format specifiers are not supported> strread (\"a\", \"%*[^a] %d\")\n%!error <format specifiers are not supported> strread (\"a\", \"%d8\")\n%!error <format specifiers are not supported> strread (\"a\", \"%*d8 %s\")\n%!error <format specifiers are not supported> strread (\"a\", \"%f64\")\n%!error <format specifiers are not supported> strread (\"a\", \"%*f64 %s\")\n%!error <format specifiers are not supported> strread (\"a\", \"%u32\")\n%!error <format specifiers are not supported> strread (\"a\", \"%*u32 %d\")\n\n## Illegal format specifiers\n%!error <no valid format conversion specifiers> strread (\"1.0\", \"%z\")\n\n## Test for false positives in check for non-supported format specifiers\n%!assert (strread (\"Total: 32.5 % (of cm values)\",\"Total: %f % (of cm values)\"),\n%!        32.5, 1e-5)\n\n## Test various forms of string format specifiers\n%!test <*45712>\n%! str = \"14 :1 z:2 z:3 z:5 z:11\";\n%! [a, b, c, d] = strread (str, \"%f %s %*s %3s %*3s %f\", \"delimiter\", \":\");\n%! assert ({a, b, c, d}, {14, {\"1 z\"}, {\"3 z\"}, 11});\n\n## Allow cuddling %sliteral but warn that it is ambiguous\n%!warning <Ambiguous '%s' specifier immediately before literal in column 1>\n%! [a, b] = strread (\"abcxyz51\\nxyz83\\n##xyz101\", \"%s xyz %d\");\n%! assert (a([1 3]), {\"abc\"; \"##\"});\n%! assert (isempty (a{2}), true);\n%! assert (b, int32([51; 83; 101]));\n"
  },
  {
    "path": "scripts/legacy/textread.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{a}, @dots{}] =} textread (@var{filename})\n## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format})\n## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{n})\n## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{prop1}, @var{value1}, @dots{})\n## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{n}, @var{prop1}, @var{value1}, @dots{})\n##\n## This function is obsolete.  Use @code{textscan} instead.\n##\n## Read data from a text file.\n##\n## The file @var{filename} is read and parsed according to @var{format}.  The\n## function behaves like @code{strread} except it works by parsing a file\n## instead of a string.  See the documentation of @code{strread} for details.\n##\n## In addition to the options supported by @code{strread}, this function\n## supports two more:\n##\n## @itemize\n## @item @qcode{\"headerlines\"}:\n## The first @var{value} number of lines of @var{filename} are skipped.\n##\n## @item @qcode{\"endofline\"}:\n## Specify a single character or\n## @qcode{\"@backslashchar{}r@backslashchar{}n\"}.  If no value is given, it\n## will be inferred from the file.  If set to @qcode{\"\"} (empty string) EOLs\n## are ignored as delimiters.\n## @end itemize\n##\n## The optional input @var{n} (format repeat count) specifies the number of\n## times the format string is to be used or the number of lines to be read,\n## whichever happens first while reading.  The former is equivalent to\n## requesting that the data output vectors should be of length @var{N}.\n## Note that when reading files with format strings referring to multiple\n## lines, @var{n} should rather be the number of lines to be read than the\n## number of format string uses.\n##\n## If the format string is empty (not just omitted) and the file contains only\n## numeric data (excluding headerlines), textread will return a rectangular\n## matrix with the number of columns matching the number of numeric fields on\n## the first data line of the file.  Empty fields are returned as zero values.\n##\n## Examples:\n##\n## @example\n## @group\n##   Assume a data file like:\n##   1 a 2 b\n##   3 c 4 d\n##   5 e\n## @end group\n## @end example\n##\n## @example\n## @group\n##   [a, b] = textread (f, \"%f %s\")\n##   returns two columns of data, one with doubles, the other a\n##   cellstr array:\n##   a = [1; 2; 3; 4; 5]\n##   b = @{\"a\"; \"b\"; \"c\"; \"d\"; \"e\"@}\n## @end group\n## @end example\n##\n## @example\n## @group\n##   [a, b] = textread (f, \"%f %s\", 3)\n##   (read data into two culumns, try to use the format string\n##   three times)\n##   returns\n##   a = [1; 2; 3]\n##   b = @{\"a\"; \"b\"; \"c\"@}\n##\n## @end group\n## @end example\n##\n## @example\n## @group\n##   With a data file like:\n##   1\n##   a\n##   2\n##   b\n##\n##   [a, b] = textread (f, \"%f %s\", 2)\n##   returns a = 1 and b = @{\"a\"@}; i.e., the format string is used\n##   only once because the format string refers to 2 lines of the\n##   data file.  To obtain 2x1 data output columns, specify N = 4\n##   (number of data lines containing all requested data) rather\n##   than 2.\n## @end group\n## @end example\n##\n## @seealso{textscan, load, dlmread, fscanf, strread}\n## @end deftypefn\n\nfunction varargout = textread (filename, format = \"%f\", varargin)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"textread is obsolete; use textscan instead\\n\");\n  endif\n\n  ## Check input\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (filename) || ! ischar (format))\n    error (\"textread: FILENAME and FORMAT arguments must be strings\");\n  endif\n\n  if (! isempty (varargin) && isnumeric (varargin{1}))\n    nlines = varargin{1};\n  else\n    nlines = Inf;\n  endif\n  if (nlines < 1)\n    printf (\"textread: N = 0, no data read\\n\");\n    varargout = cell (1, nargout);\n    return;\n  endif\n\n  BUFLENGTH = 4096;       # Read buffer to speed up processing @var{n}\n\n  ## Read file\n  fid = fopen (filename, \"r\");\n  if (fid == -1)\n    error (\"textread: could not open '%s' for reading\", filename);\n  endif\n\n  ## Skip header lines if requested\n  headerlines = find (strcmpi (varargin, \"headerlines\"), 1);\n  if (! isempty (headerlines))\n    ## Beware of missing or wrong headerline value\n    if (headerlines == numel (varargin)\n       || ! isnumeric (varargin{headerlines + 1}))\n      error (\"textread: missing or invalid value for 'headerlines'\" );\n    endif\n    ## Avoid conveying floats to fskipl\n    varargin{headerlines + 1} = round (varargin{headerlines + 1});\n    ## Beware of zero valued headerline, fskipl would skip to EOF\n    if (varargin{headerlines + 1} > 0)\n      fskipl (fid, varargin{headerlines + 1});\n    elseif (varargin{headerlines + 1} < 0)\n      warning (\"textread: negative headerline value ignored\");\n    endif\n    varargin(headerlines:headerlines+1) = [];\n  endif\n  st_pos = ftell (fid);\n\n  ## Read a first file chunk.  Rest follows after endofline processing\n  [str, count] = fscanf (fid, \"%c\", BUFLENGTH);\n  if (isempty (str) || count < 1)\n    warning (\"textread: empty file\");\n    varargout = cell (1, nargout);\n    return;\n  endif\n\n  endofline = find (strcmpi (varargin, \"endofline\"), 1);\n  if (! isempty (endofline))\n    ## 'endofline' option set by user.\n    if (ischar (varargin{endofline + 1}))\n      eol_char = varargin{endofline + 1};\n      if (strcmp (typeinfo (eol_char), \"sq_string\"))\n        eol_char = do_string_escapes (eol_char);\n      endif\n      if (! any (strcmp (eol_char, {\"\", \"\\n\", \"\\r\", \"\\r\\n\"})))\n        error (\"textread: invalid EndOfLine character value specified\");\n      endif\n    else\n      error (\"textread: character value required for EndOfLine\");\n    endif\n  else\n    ## Determine EOL from file.\n    ## Search for EOL candidates in the first BUFLENGTH chars\n    ## FIXME: Ignore risk of 2-byte EOL (\\r\\n) being split at exactly BUFLENGTH\n    eol_srch_len = min (length (str), BUFLENGTH);\n    ## First try DOS (CRLF)\n    if (! isempty (strfind (str(1 : eol_srch_len), \"\\r\\n\")))\n      eol_char = \"\\r\\n\";\n    ## Perhaps old Macintosh? (CR)\n    elseif (! isempty (strfind (str(1 : eol_srch_len), \"\\r\")))\n      eol_char = \"\\r\";\n    ## Otherwise, use plain *nix (LF)\n    else\n      eol_char = \"\\n\";\n    endif\n    ## Set up default endofline param value\n    varargin(end+1:end+2) = {\"endofline\", eol_char};\n  endif\n\n  ## Now that we know what EOL looks like, we can process format_repeat_count.\n  ## FIXME: The below isn't ML-compatible: counts lines, not format string uses\n  if (isfinite (nlines) && (nlines > 0))\n    l_eol_char = length (eol_char);\n    eoi = strfind (str, eol_char);\n    n_eoi = length (eoi);\n    nblks = 0;\n    ## Avoid slow repeated str concatenation, first seek requested end of data\n    while (n_eoi < nlines && count == BUFLENGTH)\n      [nstr, count] = fscanf (fid, \"%c\", BUFLENGTH);\n      if (count > 0)\n        ## Watch out for multichar EOL being missed across buffer boundaries\n        if (l_eol_char > 1)\n          str = [str(end - length (eol_char) + 2 : end) nstr];\n        else\n          str = nstr;\n        endif\n        eoi = strfind (str, eol_char);\n        n_eoi += numel (eoi);\n        ++nblks;\n      endif\n    endwhile\n    ## Handle case of missing or incomplete trailing EOL\n    if (! strcmp (str(end - length (eol_char) + 1 : end), eol_char))\n      eoi = [ eoi (length (str)) ];\n      ++n_eoi;\n    endif\n    ## Found EOL delimiting last requested line.  Compute ptr (incl. EOL)\n    if (isempty (eoi))\n      eoi_pos = nblks * BUFLENGTH + count;\n    else\n      eoi_pos = (nblks * BUFLENGTH) + eoi(end + min (nlines, n_eoi) - n_eoi);\n    endif\n    fseek (fid, st_pos, \"bof\");\n    str = fscanf (fid, \"%c\", eoi_pos);\n  else\n    fseek (fid, st_pos, \"bof\");\n    str = fread (fid, \"char=>char\").';\n  endif\n  fclose (fid);\n\n  ## Set up default whitespace param value if needed\n  if (isempty (find (strcmpi (\"whitespace\", varargin))))\n    varargin(end+1:end+2) = {\"whitespace\", \" \\b\\t\"};\n  endif\n\n  ## Call strread to make it do the real work\n  warning (\"off\", \"Octave:legacy-function\", \"local\");\n  [varargout{1:max (nargout, 1)}] = strread (str, format, varargin{:});\n\n  ## Hack to concatenate/reshape numeric output into 2-D array (undocumented ML)\n  ## In ML this only works in case of an empty format string\n  if (isempty (format))\n    ## Get number of fields per line.\n    ## 1. Get eol_char position\n    iwhsp = find (strcmpi (\"whitespace\", varargin));\n    whsp = varargin{iwhsp + 1};\n    idx = regexp (str, eol_char, \"once\");\n    ## 2. Get first data line til EOL.  Avoid corner case of just one line\n    if (! isempty (idx))\n      str = str(1:idx-1);\n    endif\n    idelimiter = find (strcmpi (varargin, \"delimiter\"), 1);\n    if (isempty (idelimiter))\n      ## Assume delimiter = whitespace\n      ## 3A. whitespace incl. consecutive whitespace => single space\n      str = regexprep (str, sprintf (\"[%s]+\", whsp), ' ');\n      ## 4A. Remove possible leading & trailing spaces\n      str = strtrim (str);\n      ## 5A. Count spaces, add one to get nr of data fields per line\n      ncols = numel (strfind (str, \" \")) + 1;\n    else\n      ## 3B. Just count delimiters.  FIXME: delimiters could occur in literals\n      delimiter = varargin{idelimiter+1};\n      ncols = numel (regexp (str, sprintf (\"[%s]\", delimiter))) + 1;\n    endif\n    ## 6. Reshape; watch out, we need a transpose\n    nrows = ceil (numel (varargout{1}) / ncols);\n    pad = mod (numel (varargout{1}), ncols);\n    if (pad > 0)\n      pad = ncols - pad;\n      varargout{1}(end+1 : end+pad) = NaN;\n    endif\n    varargout{1} = reshape (varargout{1}, ncols, nrows)';\n    ## ML replaces empty values with NaNs\n    varargout{1}(find (isnan (varargout{1}))) = 0;\n  endif\n\nendfunction\n\n\n## First test is necessary to provoke 1-time legacy warning\n%!test\n%! warning (\"off\", \"Octave:legacy-function\", \"local\");\n%! try\n%!   textread (\"\");\n%! catch\n%!   ## Nothing to do, just wanted to suppress error.\n%! end_try_catch\n\n%!test\n%! f = tempname ();\n%! d = rand (5, 3);\n%! dlmwrite (f, d, \"precision\", \"%5.2f\");\n%! [a, b, c] = textread (f, \"%f %f %f\", \"delimiter\", \",\", \"headerlines\", 3);\n%! unlink (f);\n%! assert (a, d(4:5, 1), 1e-2);\n%! assert (b, d(4:5, 2), 1e-2);\n%! assert (c, d(4:5, 3), 1e-2);\n\n%!test\n%! f = tempname ();\n%! d = rand (7, 2);\n%! dlmwrite (f, d, \"precision\", \"%5.2f\");\n%! [a, b] = textread (f, \"%f, %f\", \"headerlines\", 1);\n%! unlink (f);\n%! assert (a, d(2:7, 1), 1e-2);\n\n## Test reading 2-D matrix with empty format\n%!test\n%! f = tempname ();\n%! d = rand (5, 2);\n%! dlmwrite (f, d, \"precision\", \"%5.2f\");\n%! A = textread (f, \"\", \"headerlines\", 3);\n%! unlink (f);\n%! assert (A, d(4:5, :), 1e-2);\n\n## Read multiple lines using empty format string\n%!test\n%! f = tempname ();\n%! sts = unlink (f);\n%! fid = fopen (f, \"w\");\n%! d = rand (1, 4);\n%! fprintf (fid, \"  %f %f   %f  %f \", d);\n%! fclose (fid);\n%! A = textread (f, \"\");\n%! unlink (f);\n%! assert (A, d, 1e-6);\n\n## Empty format, corner case = one line w/o EOL\n%!test\n%! f = tempname ();\n%! sts = unlink (f);\n%! fid = fopen (f, \"w\");\n%! d = rand (1, 4);\n%! fprintf (fid, \"  %f %f   %f  %f \", d);\n%! fclose (fid);\n%! A = textread (f, \"\");\n%! unlink (f);\n%! assert (A, d, 1e-6);\n\n## Tests with format repeat count #1\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w\");\n%! fprintf (fid, \"%2d %s %2d %s\\n %2d %s %2d %s \\n\", ...\n%!                10, \"a\", 20, \"b\", 30, \"c\", 40, \"d\");\n%! fclose (fid);\n%! [a, b] = textread (f, \"%d %s\", 1);\n%! assert (a, int32 (10));\n%! assert (b, {\"a\"});\n%! [a, b] = textread (f, \"%d %s\", 2);\n%! assert (a, int32 ([10; 20]));\n%! assert (b, {\"a\"; \"b\"});\n%! [a, b] = textread (f, \"%d %s\", 3);\n%! assert (a, int32 ([10; 20; 30]));\n%! assert (b, {\"a\"; \"b\"; \"c\"});\n%! [a, b] = textread (f, \"%d %s\", 4);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"; \"d\"});\n%! [a, b] = textread (f, \"%d %s\", 5);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"; \"d\"});\n%! unlink (f);\n\n## Tests with format repeat count #2, missing last EOL\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w\");\n%! fprintf (fid, \"%2d %s %2d %s\\n %2d %s %2d %s\", ...\n%!                10, \"a\", 20, \"b\", 30, \"c\", 40, \"d\");\n%! fclose (fid);\n%! [a, b] = textread (f, \"%d %s\", 1);\n%! assert (a, int32 (10));\n%! assert (b, {\"a\"});\n%! [a, b] = textread (f, \"%d %s\", 2);\n%! assert (a, int32 ([10; 20]));\n%! assert (b, {\"a\"; \"b\"});\n%! [a, b] = textread (f, \"%d %s\", 3);\n%! assert (a, int32 ([10; 20; 30]));\n%! assert (b, {\"a\"; \"b\"; \"c\"});\n%! [a, b] = textread (f, \"%d %s\", 4);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"; \"d\"});\n%! [a, b] = textread (f, \"%d %s\", 5);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"; \"d\"});\n%! unlink (f);\n\n## Tests with format repeat count #3, incomplete last line\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w\");\n%! fprintf (fid, \"%2d %s %2d %s\\n %2d %s %2d\", ...\n%!                10, \"a\", 20, \"b\", 30, \"c\", 40);\n%! fclose (fid);\n%! [a, b] = textread (f, \"%d %s\", 1);\n%! assert (a, int32 (10));\n%! assert (b, {\"a\"});\n%! [a, b] = textread (f, \"%d %s\", 2);\n%! assert (a, int32 ([10; 20]));\n%! assert (b, {\"a\"; \"b\"});\n%! [a, b] = textread (f, \"%d %s\", 3);\n%! assert (a, int32 ([10; 20; 30]));\n%! assert (b, {\"a\"; \"b\"; \"c\"});\n%! [a, b] = textread (f, \"%d %s\", 4);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"});\n%! [a, b] = textread (f, \"%d %s\", 5);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"});\n%! unlink (f);\n\n## Tests with format repeat count #4, incomplete last line but with trailing EOL\n%!test\n%! f = tempname ();\n%! fid = fopen (f, \"w\");\n%! fprintf (fid, \"%2d %s %2d %s\\n %2d %s %2d\\n\", ...\n%!                10, \"a\", 20, \"b\", 30, \"c\", 40);\n%! fclose (fid);\n%! [a, b] = textread (f, \"%d %s\", 4);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"; \"\"});\n%! [a, b] = textread (f, \"%d %s\", 5);\n%! assert (a, int32 ([10; 20; 30; 40]));\n%! assert (b, {\"a\"; \"b\"; \"c\"; \"\"});\n%! unlink (f);\n\n### Tests with format repeat count #5, nr of data lines = limiting factor\n%!#test\n%!# f = tempname ();\n%!# fid = fopen (f, \"w\");\n%!# fprintf (fid, \"%2d\\n%s\\n%2dn%s\", ...\n%!#                1, \"a\", 2, \"b\");\n%!# fclose (fid);\n%!# [a, b] = textread (f, \"%d %s\", 2);\n%!# assert (a, int32 (1));\n%!# assert (b, {\"a\"});\n\n### Read multiple lines using empty format string, missing data (should be 0)\n%!#test\n%!# f = tempname ();\n%!# unlink (f);\n%!# fid = fopen (f, \"w\");\n%!# d = rand (1, 4);\n%!# fprintf (fid, \"%f, %f, ,  %f,  %f \", d);\n%!# fclose (fid);\n%!# A = textread (f, \"\");\n%!# unlink (f);\n%!# assert (A, [ d(1:2) 0 d(3:4)], 1e-6);\n\n### Test with empty positions - ML returns 0 for empty fields\n%!#test\n%!# f = tempname ();\n%!# unlink (f);\n%!# fid = fopen (f, \"w\");\n%!# d = rand (1, 4);\n%!# fprintf (fid, \",2,,4\\n5,,7,\\n\");\n%!# fclose (fid);\n%!# A = textread (f, \"\", \"delimiter\", \",\");\n%!# unlink (f);\n%!# assert (A, [0 2 0 4; 5 0 7 0], 1e-6);\n\n### Another test with empty format + positions, now with more incomplete lower\n### row (must be appended with zeros to get rectangular matrix)\n%!#test\n%!# f = tempname ();\n%!# unlink (f);\n%!# fid = fopen (f, \"w\");\n%!# d = rand (1, 4);\n%!# fprintf (fid, \",2,,4\\n5,\\n\");\n%!# fclose (fid);\n%!# A = textread (f, \"\", \"delimiter\", \",\");\n%!# unlink (f);\n%!# assert (A, [0 2 0 4; 5 0 0 0], 1e-6);\n\n### Test endofline\n%!#test <*45046>\n%!# f = tempname ();\n%!# fid = fopen (f, \"w\");\n%!# fprintf (fid, \"a\\rb\\rc\");\n%!# fclose (fid);\n%!# ## Test EOL detection\n%!# d = textread (f, \"%s\");\n%!# assert (d, {\"a\";\"b\";\"c\"});\n%!# ## Test explicit EOL specification (bug #45046)\n%!# d = textread (f, \"%s\", \"endofline\", \"\\r\");\n%!# assert (d, {\"a\"; \"b\"; \"c\"});\n%!# unlink (f);\n\n### Properly process single-quoted EOL args\n%!#test <*46477>\n%!# f = tempname ();\n%!# fid = fopen (f, \"w\");\n%!# fprintf (fid, \"hello, world!\");\n%!# fclose (fid);\n%!# [a, b] = textread (f, \"%s%s\", \"endofline\", '\\n');\n%!# assert (a{1}, \"hello,\");\n%!# assert (b{1}, \"world!\");\n\n### Test input validation\n%!#error textread ()\n%!#error textread (1)\n%!#error <arguments must be strings> textread (1, \"%f\")\n%!#error <arguments must be strings> textread (\"fname\", 1)\n%!#error <missing or invalid value for> textread (file_in_loadpath (\"textread.m\"), \"\", \"headerlines\")\n%!#error <missing or invalid value for> textread (file_in_loadpath (\"textread.m\"), \"\", \"headerlines\", 'hh')\n%!#error <character value required for> textread (file_in_loadpath (\"textread.m\"), \"%s\", \"endofline\", true)\n"
  },
  {
    "path": "scripts/legacy/vectorize.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{vfcn} =} vectorize (@var{fcn})\n## Create a vectorized version of the anonymous function or expression\n## @var{fcn} by replacing all occurrences of @code{*}, @code{/}, etc.,\n## with @code{.*}, @code{./}, etc.\n##\n## Note that the transformation is extremely simplistic.  Use of this\n## function is strongly discouraged.  It may be removed from a future\n## version of Octave.\n## @end deftypefn\n\nfunction vfcn = vectorize (fcn)\n\n  persistent warned = false;\n  if (! warned)\n    warned = true;\n    warning (\"Octave:legacy-function\",\n             \"vectorize is unreliable; its use is strongly discouraged\\n\");\n  endif\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (is_function_handle (fcn))\n    finfo = functions (fcn);\n    if (! strcmp (finfo.type, \"anonymous\"))\n      error (\"vectorize: FCN must be a string or anonymous function handle\");\n    endif\n    expr = finfo.function;\n    idx = index (expr, \")\");\n    args = expr(1:idx);\n    expr = expr(idx+1:end);\n    new_expr = __vectorize__ (expr);\n    vfcn = str2func ([args, new_expr]);\n  elseif (ischar (fcn))\n    vfcn = __vectorize__ (fcn);\n  else\n    error (\"vectorize: FCN must be a string or anonymous function handle\");\n  endif\n\nendfunction\n\n\n%!assert (vectorize (\"x.^2 + 1\"), \"x.^2 + 1\")\n%!test\n%! fh = @(x) x.^2 + 1;\n%! finfo = functions (vectorize (fh));\n%! assert (finfo.function, \"@(x) x .^ 2 + 1\");\n\n%!assert (vectorize (\"1e-3*y + 2e4*z\"), \"1e-3.*y + 2e4.*z\")\n%!test\n%! fh = @(x, y, z) 1e-3*y + 2e4*z;\n%! finfo = functions (vectorize (fh));\n%! assert (finfo.function, \"@(x, y, z) 1e-3 .* y + 2e4 .* z\");\n\n%!assert (vectorize (\"2^x^5\"), \"2.^x.^5\")\n%!test\n%! fh = @(x) 2^x^5;\n%! finfo = functions (vectorize (fh));\n%! assert (finfo.function, \"@(x) 2 .^ x .^ 5\");\n\n## Test input validation\n%!error <Invalid call> vectorize ()\n%!error <FCN must be a string or anonymous function handle> vectorize (1)\n"
  },
  {
    "path": "scripts/linear-algebra/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/linear-algebra/bandwidth.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{bw} =} bandwidth (@var{A}, @var{type})\n## @deftypefnx {} {[@var{lower}, @var{upper}] =} bandwidth (@var{A})\n## Compute the bandwidth of @var{A}.\n##\n## The @var{type} argument is the string @qcode{\"lower\"} for the lower\n## bandwidth and @qcode{\"upper\"} for the upper bandwidth.  If no @var{type} is\n## specified return both the lower and upper bandwidth of @var{A}.\n##\n## The lower/upper bandwidth of a matrix is the number of\n## subdiagonals/superdiagonals with nonzero entries.\n##\n## @seealso{isbanded, isdiag, istril, istriu}\n## @end deftypefn\n\nfunction [lower, upper] = bandwidth (A, type)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (A) && ! islogical (A) || ndims (A) != 2)\n    error (\"bandwidth: A must be a 2-D numeric or logical matrix\");\n  elseif (nargin == 2 && ! (strcmp (type, \"lower\") || strcmp (type, \"upper\")))\n    error ('bandwidth: TYPE must be \"lower\" or \"upper\"');\n  endif\n\n  if (nargin == 1)\n    [i, j] = find (A);\n    if (isempty (i))\n      lower = upper = 0;\n    else\n      lower = max (0, max (i - j));\n      upper = max (0, max (j - i));\n    endif\n  else\n    [i, j] = find (A);\n    if (isempty (i))\n      lower = 0;\n    elseif (strcmp (type, \"lower\"))\n      lower = max (0, max (i - j));\n    else\n      lower = max (0, max (j - i));\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! [a,b] = bandwidth (speye (100));\n%! assert ([a,b], [0,0]);\n%! assert (bandwidth (speye (100), \"upper\"), 0);\n%! assert (bandwidth (speye (100), \"lower\"), 0);\n\n%!test\n%! A = [2 3 0 0 0; 1 2 3 0 0; 0 1 2 3 0; 0 0 1 2 3; 0 0 0 1 2];\n%! [a,b] = bandwidth (A);\n%! assert ([a,b], [1,1]);\n%! assert (bandwidth (A, \"lower\"), 1);\n%! assert (bandwidth (A, \"upper\"), 1);\n\n%!assert (bandwidth ([], \"lower\"), 0)\n%!assert (bandwidth ([], \"upper\"), 0)\n%!assert (bandwidth ([]), 0)\n%!assert (bandwidth (zeros (3,3), \"lower\"), 0)\n%!assert (bandwidth (zeros (3,3), \"upper\"), 0)\n%!assert (bandwidth (zeros (3,3)), 0)\n%!assert (bandwidth (ones (5,5), \"lower\"), 4)\n%!assert (bandwidth (ones (5,5), \"upper\"), 4)\n%!assert (bandwidth (ones (5,5)), 4)\n\n%!assert (bandwidth ([0,1,2,0]), 0)\n\n%!test\n%! [a,b] = bandwidth ([]);\n%! assert ([a,b], [0,0]);\n%!test\n%! [a,b] = bandwidth (zeros (3,3));\n%! assert ([a,b], [0,0]);\n%!test\n%! [a,b] = bandwidth (ones (5,5));\n%! assert ([a,b], [4,4]);\n\n## Test input validation\n%!error <Invalid call> bandwidth ()\n%!error <A must be a 2-D numeric or logical> bandwidth (\"string\", \"lower\")\n%!error <A must be a 2-D numeric or logical> bandwidth (ones (3,3,3), \"lower\")\n%!error <TYPE must be \"lower\" or \"upper\"> bandwidth (ones (2), \"uper\")\n%!error <TYPE must be \"lower\" or \"upper\"> bandwidth (ones (2), \"uppper\")\n"
  },
  {
    "path": "scripts/linear-algebra/commutation_matrix.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{k} =} commutation_matrix (@var{m}, @var{n})\n## Return the commutation matrix\n## @tex\n##  $K_{m,n}$\n## @end tex\n## @ifnottex\n## K(m,n)\n## @end ifnottex\n## which is the unique\n## @tex\n##  $m n \\times m n$\n## @end tex\n## @ifnottex\n## @var{m}*@var{n} by @var{m}*@var{n}\n## @end ifnottex\n## matrix such that\n## @tex\n##  $K_{m,n} \\cdot {\\rm vec} (A) = {\\rm vec} (A^T)$\n## @end tex\n## @ifnottex\n## @math{K(m,n) * vec(A) = vec(A')}\n## @end ifnottex\n## for all\n## @tex\n##  $m\\times n$\n## @end tex\n## @ifnottex\n## @math{m} by @math{n}\n## @end ifnottex\n## matrices\n## @tex\n##  $A$.\n## @end tex\n## @ifnottex\n## @math{A}.\n## @end ifnottex\n##\n## If only one argument @var{m} is given,\n## @tex\n##  $K_{m,m}$\n## @end tex\n## @ifnottex\n## @math{K(m,m)}\n## @end ifnottex\n## is returned.\n##\n## See @nospell{Magnus and Neudecker}, @cite{Matrix Differential\n## Calculus with Applications in Statistics and Econometrics}, 1988.\n## @end deftypefn\n\nfunction k = commutation_matrix (m, n)\n\n  if (nargin < 1)\n    print_usage ();\n  else\n    if (! (isscalar (m) && m == fix (m) && m > 0))\n      error (\"commutation_matrix: M must be a positive integer\");\n    endif\n    if (nargin == 1)\n      n = m;\n    elseif (! (isscalar (n) && n == fix (n) && n > 0))\n      error (\"commutation_matrix: N must be a positive integer\");\n    endif\n  endif\n\n  ## It is clearly possible to make this a LOT faster!\n  k = zeros (m * n, m * n);\n  for i = 1 : m\n    for j = 1 : n\n      k((i - 1) * n + j, (j - 1) * m + i) = 1;\n    endfor\n  endfor\n\nendfunction\n\n\n%!test\n%! c = commutation_matrix (1,1);\n%! assert (c,1);\n\n%!test\n%! A = rand (3,5);\n%! vc = vec (A);\n%! vr = vec (A');\n%! c = commutation_matrix (3,5);\n%! assert (c*vc, vr);\n\n%!test\n%! A = rand (4,6);\n%! vc = vec (A);\n%! vr = vec (A');\n%! c = commutation_matrix (4,6);\n%! assert (c*vc, vr);\n\n%!error <M must be a positive integer> commutation_matrix (0,0)\n%!error <N must be a positive integer> commutation_matrix (1,0)\n%!error <M must be a positive integer> commutation_matrix (0,1)\n"
  },
  {
    "path": "scripts/linear-algebra/cond.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} cond (@var{A})\n## @deftypefnx {} {@var{c} =} cond (@var{A}, @var{p})\n## Compute the @var{p}-norm condition number of a matrix with respect to\n## inversion.\n##\n## @code{cond (@var{A})} is defined as\n## @tex\n## $ {\\parallel A \\parallel_p * \\parallel A^{-1} \\parallel_p .} $\n## @end tex\n## @ifnottex\n## @code{norm (@var{A}, @var{p}) * norm (inv (@var{A}), @var{p})}.\n## @end ifnottex\n##\n## By default, @code{@var{p} = 2} is used which implies a (relatively slow)\n## singular value decomposition.  Other possible selections are\n## @code{@var{p} = 1, Inf, \"fro\"} which are generally faster.  For a full\n## discussion of possible @var{p} values, @pxref{XREFnorm,,@code{norm}}.\n##\n## The condition number of a matrix quantifies the sensitivity of the matrix\n## inversion operation when small changes are made to matrix elements.  Ideally\n## the condition number will be close to 1.  When the number is large this\n## indicates small changes (such as underflow or round-off error) will produce\n## large changes in the resulting output.  In such cases the solution results\n## from numerical computing are not likely to be accurate.\n## @seealso{condest, rcond, condeig, norm, svd}\n## @end deftypefn\n\nfunction c = cond (A, p = 2)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ndims (A) > 2)\n    error (\"cond: A must be a 2-D matrix\");\n  endif\n\n  if (p == 2)\n    if (isempty (A))\n      c = 0.0;\n    else\n      try\n        sigma = svd (A);\n      catch\n        error (\"cond: A must not contain Inf or NaN values\");\n      end_try_catch\n      sigma_1 = sigma(1);\n      sigma_n = sigma(end);\n      if (sigma_1 == 0 || sigma_n == 0)\n        c = Inf;\n      else\n        c = sigma_1 / sigma_n;\n      endif\n    endif\n  else\n    c = norm (A, p) * norm (inv (A), p);\n  endif\n\nendfunction\n\n\n%!test\n%! y = [7, 2, 3; 1, 3, 4; 6, 4, 5];\n%! tol = 1e-6;\n%! type = {1, 2, \"fro\", \"inf\", inf};\n%! for n = 1:numel (type)\n%!   rcondition(n) = 1 / cond (y, type{n});\n%! endfor\n%! assert (rcondition, [0.017460, 0.019597, 0.018714, 0.012022, 0.012022], tol);\n\n%!assert (cond ([1, 2; 2, 1]), 3, sqrt (eps))\n%!assert (cond ([1, 2, 3; 4, 5, 6; 7, 8, 9]) > 1.0e+16)\n\n%!error <Invalid call> cond ()\n%!error <A must be a 2-D matrix> cond (ones (1,3,3))\n%!error <A must not contain Inf or NaN value> cond ([1, 2;Inf 4])\n%!error <A must not contain Inf or NaN value> cond ([1, 2;NaN 4])\n"
  },
  {
    "path": "scripts/linear-algebra/condeig.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} condeig (@var{a})\n## @deftypefnx {} {[@var{v}, @var{lambda}, @var{c}] =} condeig (@var{a})\n## Compute condition numbers of a matrix with respect to eigenvalues.\n##\n## The condition numbers are the reciprocals of the cosines of the angles\n## between the left and right eigenvectors; Large values indicate that the\n## matrix has multiple distinct eigenvalues.\n##\n## The input @var{a} must be a square numeric matrix.\n##\n## The outputs are:\n##\n## @itemize @bullet\n## @item\n## @var{c} is a vector of condition numbers for the eigenvalues of\n## @var{a}.\n##\n## @item\n## @var{v} is the matrix of right eigenvectors of @var{a}.  The result is\n## equivalent to calling @code{[@var{v}, @var{lambda}] = eig (@var{a})}.\n##\n## @item\n## @var{lambda} is the diagonal matrix of eigenvalues of @var{a}.  The\n## result is equivalent to calling\n## @code{[@var{v}, @var{lambda}] = eig (@var{a})}.\n## @end itemize\n##\n## Example\n##\n## @example\n## @group\n## a = [1, 2; 3, 4];\n## c = condeig (a)\n##   @xresult{} c =\n##        1.0150\n##        1.0150\n## @end group\n## @end example\n## @seealso{eig, cond, balance}\n## @end deftypefn\n\nfunction [v, lambda, c] = condeig (a)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (a) && issquare (a)))\n    error (\"condeig: A must be a square numeric matrix\");\n  endif\n\n  if (issparse (a) && nargout <= 1)\n    ## Try to use svds to calculate the condition number as it will typically\n    ## be much faster than calling eig as only the smallest and largest\n    ## eigenvalue are calculated.\n\n    ## FIXME: This calculates one condition number for the entire matrix.\n    ## In the full case, separate condition numbers are calculated for every\n    ## eigenvalue.\n    try\n      s0 = svds (a, 1, 0);    # min eigenvalue\n      v = svds (a, 1) / s0;   # max eigenvalue\n    catch\n      ## Caught an error as there is a singular value exactly at zero!!\n      v = Inf;\n    end_try_catch\n    return;\n  endif\n\n  ## Right eigenvectors\n  [v, lambda] = eig (a);\n\n  if (isempty (a))\n    c = [];\n  else\n    ## Corresponding left eigenvectors\n    ## Use 2-argument form to suppress possible singular matrix warning.\n    [vl, ~] = inv (v);\n    vl = vl';\n    ## Normalize vectors\n    vl ./= repmat (sqrt (sum (abs (vl .^ 2))), rows (vl), 1);\n\n    ## Condition numbers\n    ## Definition: 1 / cos (angle) = (norm (v1) * norm (v2)) / dot (v1, v2)\n    ## Eigenvectors have been normalized so 'norm (v1) * norm (v2)' = 1\n    c = abs (1 ./ dot (vl, v)');\n  endif\n\n  if (nargout <= 1)\n    v = c;\n  endif\n\nendfunction\n\n\n%!test\n%! a = [1, 2; 3, 4];\n%! c = condeig (a);\n%! expected_c = [1.0150; 1.0150];\n%! assert (c, expected_c, 0.001);\n\n%!test\n%! a = [1, 3; 5, 8];\n%! [v, lambda, c] = condeig (a);\n%! [expected_v, expected_lambda] = eig (a);\n%! expected_c = [1.0182; 1.0182];\n%! assert (v, expected_v, 0.001);\n%! assert (lambda, expected_lambda, 0.001);\n%! assert (c, expected_c, 0.001);\n\n## Test empty input\n%!assert (condeig ([]), [])\n\n## Test input validation\n%!error <Invalid call> condeig ()\n%!error <A must be a square numeric matrix> condeig ({1})\n%!error <A must be a square numeric matrix> condeig (ones (3,2))\n%!error <A must be a square numeric matrix> condeig (ones (2,2,2))\n"
  },
  {
    "path": "scripts/linear-algebra/condest.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{cest} =} condest (@var{A})\n## @deftypefnx {} {@var{cest} =} condest (@var{A}, @var{t})\n## @deftypefnx {} {@var{cest} =} condest (@var{A}, @var{Ainvfcn})\n## @deftypefnx {} {@var{cest} =} condest (@var{A}, @var{Ainvfcn}, @var{t})\n## @deftypefnx {} {@var{cest} =} condest (@var{A}, @var{Ainvfcn}, @var{t}, @var{p1}, @var{p2}, @dots{})\n## @deftypefnx {} {@var{cest} =} condest (@var{Afcn}, @var{Ainvfcn})\n## @deftypefnx {} {@var{cest} =} condest (@var{Afcn}, @var{Ainvfcn}, @var{t})\n## @deftypefnx {} {@var{cest} =} condest (@var{Afcn}, @var{Ainvfcn}, @var{t}, @var{p1}, @var{p2}, @dots{})\n## @deftypefnx {} {[@var{cest}, @var{v}] =} condest (@dots{})\n##\n## Estimate the 1-norm condition number of a square matrix @var{A} using\n## @var{t} test vectors and a randomized 1-norm estimator.\n##\n## The optional input @var{t} specifies the number of test vectors (default 5).\n##\n## The input may be a matrix @var{A} (the algorithm is particularly\n## appropriate for large, sparse matrices).  Alternatively, the behavior of\n## the matrix can be defined implicitly by functions.  When using an implicit\n## definition, @code{condest} requires the following functions:\n##\n## @itemize @minus\n## @item @code{@var{Afcn} (@var{flag}, @var{x})} which must return\n##\n## @itemize @bullet\n## @item\n## the dimension @var{n} of @var{A}, if @var{flag} is @qcode{\"dim\"}\n##\n## @item\n## true if @var{A} is a real operator, if @var{flag} is @qcode{\"real\"}\n##\n## @item\n## the result @code{@var{A} * @var{x}}, if @var{flag} is \"notransp\"\n##\n## @item\n## the result @code{@var{A}' * @var{x}}, if @var{flag} is \"transp\"\n## @end itemize\n##\n## @item @code{@var{Ainvfcn} (@var{flag}, @var{x})} which must return\n##\n## @itemize @bullet\n## @item\n## the dimension @var{n} of @code{inv (@var{A})}, if @var{flag} is\n## @qcode{\"dim\"}\n##\n## @item\n## true if @code{inv (@var{A})} is a real operator, if @var{flag} is\n## @qcode{\"real\"}\n##\n## @item\n## the result @code{inv (@var{A}) * @var{x}}, if @var{flag} is \"notransp\"\n##\n## @item\n## the result @code{inv (@var{A})' * @var{x}}, if @var{flag} is \"transp\"\n## @end itemize\n## @end itemize\n##\n## Any parameters @var{p1}, @var{p2}, @dots{} are additional arguments of\n## @code{@var{Afcn} (@var{flag}, @var{x}, @var{p1}, @var{p2}, @dots{})}\n## and @code{@var{Ainvfcn} (@var{flag}, @var{x}, @var{p1}, @var{p2}, @dots{})}.\n##\n## The principal output is the 1-norm condition number estimate @var{cest}.\n##\n## The optional second output @var{v} is an approximate null vector; it\n## satisfies the equation @code{norm (@var{A}*@var{v}, 1) ==\n## norm (@var{A}, 1) * norm (@var{v}, 1) / @var{cest}}.\n##\n## Algorithm Note: @code{condest} uses a randomized algorithm to approximate\n## the 1-norms.  Therefore, if consistent results are required, the\n## @qcode{\"state\"} of the random generator should be fixed before invoking\n## @code{condest}.\n##\n## References:\n##\n## @itemize\n## @item\n## @nospell{N.J. Higham and F. Tisseur}, \"A Block Algorithm for Matrix 1-Norm\n## Estimation, with an Application to 1-Norm Pseudospectra\",\n## @cite{SIAM Journal on Matrix Analysis and Applications}, @w{Vol.@: 21},\n## @nospell{@w{Iss.@: 4}}, @w{pp.@: 1185}--1201, 2000,\n## @url{https://dx.doi.org/10.1137/S0895479899356080}.\n##\n## @item\n## @nospell{N.J. Higham and F. Tisseur}, @cite{A Block Algorithm for Matrix\n## 1-Norm Estimation, with an Application to 1-Norm Pseudospectra},\n## @url{https://citeseer.ist.psu.edu/223007.html}.\n## @end itemize\n##\n## @seealso{cond, rcond, norm, normest1, normest}\n## @end deftypefn\n\n## Code originally licensed under:\n##\n## Copyright (c) 2007, Regents of the University of California\n## All rights reserved.\n##\n## Redistribution and use in source and binary forms, with or without\n## modification, are permitted provided that the following conditions\n## are met:\n##\n##    * Redistributions of source code must retain the above copyright\n##      notice, this list of conditions and the following disclaimer.\n##\n##    * Redistributions in binary form must reproduce the above\n##      copyright notice, this list of conditions and the following\n##      disclaimer in the documentation and/or other materials provided\n##      with the distribution.\n##\n##    * Neither the name of the University of California, Berkeley nor\n##      the names of its contributors may be used to endorse or promote\n##      products derived from this software without specific prior\n##      written permission.\n##\n## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''\n## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n## PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND\n## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT\n## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n## SUCH DAMAGE.\n\nfunction [cest, v] = condest (varargin)\n\n  if (nargin < 1 || nargin > 6)\n    print_usage ();\n  endif\n\n  have_A = false;\n  have_t = false;\n  have_Afcn = false;\n  have_Ainvfcn = false;\n\n  if (isnumeric (varargin{1}))\n    A = varargin{1};\n    if (! issquare (A))\n      error (\"condest: A must be square\");\n    endif\n    have_A = true;\n    n = rows (A);\n    if (nargin > 1)\n      if (is_function_handle (varargin{2}))\n        Ainvfcn = varargin{2};\n        have_Ainvfcn = true;\n        if (nargin > 2)\n          t = varargin{3};\n          have_t = true;\n        endif\n      else\n        t = varargin{2};\n        have_t = true;\n      endif\n    endif\n  elseif (is_function_handle (varargin{1}))\n    if (nargin == 1)\n      error (\"condest: must provide AINVFCN when using AFCN\");\n    endif\n    Afcn = varargin{1};\n    have_Afcn = true;\n    if (! is_function_handle (varargin{2}))\n      error (\"condest: AINVFCN must be a function handle\");\n    endif\n    Ainvfcn = varargin{2};\n    have_Ainvfcn = true;\n    n = Afcn (\"dim\", [], varargin{4:end});\n    if (nargin > 2)\n      t = varargin{3};\n      have_t = true;\n    endif\n  else\n    error (\"condest: first argument must be a square matrix or function handle\");\n  endif\n\n  if (! have_t)\n    t = min (n, 5);\n  endif\n\n  ## Disable warnings which may be emitted during calculation process.\n  warning (\"off\", \"Octave:nearly-singular-matrix\", \"local\");\n\n  if (! have_Ainvfcn)\n    ## Prepare Ainvfcn in normest1 form\n    if (issparse (A))\n      [L, U, P, Q] = lu (A);\n      Ainvfcn = @inv_sparse_fcn;\n    else\n      [L, U, P] = lu (A);\n      Q = [];\n      Ainvfcn = @inv_full_fcn;\n    endif\n\n    ## Check for singular matrices before continuing (bug #46737)\n    if (any (diag (U) == 0))\n      cest = Inf;\n      v = [];\n      return;\n    endif\n\n    ## Initialize solver\n    Ainvfcn (\"init\", A, L, U, P, Q);\n    clear L U P Q;\n  endif\n\n  if (have_A)\n    Anorm = norm (A, 1);\n  else\n    Anorm = normest1 (Afcn, t, [], varargin{4:end});\n  endif\n  [Ainv_norm, v, w] = normest1 (Ainvfcn, t, [], varargin{4:end});\n\n  cest = Anorm * Ainv_norm;\n  if (nargout > 1)\n    v = w / norm (w, 1);\n  endif\n\n  if (! have_Ainvfcn)\n    Ainvfcn (\"clear\");  # clear persistent memory in subfunction\n  endif\n\nendfunction\n\nfunction retval = inv_sparse_fcn (flag, x, varargin)\n\n  ## FIXME: Sparse algorithm is less accurate than full matrix version.\n  ##        See BIST test for asymmetric matrix where relative tolerance\n  ##        of 1e-12 is used for sparse, but 4e-16 for full matrix.\n  ##        BUT, does it really matter for an \"estimate\"?\n  persistent Ainv Ainvt n isreal_op;\n\n  switch (flag)\n    case \"dim\"\n      retval = n;\n    case \"real\"\n      retval = isreal_op;\n    case \"notransp\"\n      retval = Ainv * x;\n    case \"transp\"\n      retval = Ainvt * x;\n    case \"init\"\n      n = rows (x);\n      isreal_op = isreal (x);\n      [L, U, P, Q] = deal (varargin{1:4});\n      Ainv = Q * (U \\ (L \\ P));\n      Ainvt = P' * (L' \\ (U' \\ Q'));\n    case \"clear\"  # called to free memory at end of condest function\n      clear Ainv Ainvt n isreal_op;\n  endswitch\n\nendfunction\n\nfunction retval = inv_full_fcn (flag, x, varargin)\n  persistent Ainv Ainvt n isreal_op;\n\n  switch (flag)\n    case \"dim\"\n      retval = n;\n    case \"real\"\n      retval = isreal_op;\n    case \"notransp\"\n      retval = Ainv * x;\n    case \"transp\"\n      retval = Ainvt \\ x;\n    case \"init\"\n      n = rows (x);\n      isreal_op = isreal (x);\n      [L, U, P] = deal (varargin{1:3});\n      Ainv = U \\ (L \\ P);\n      Ainvt = P' * (L' \\ U');\n    case \"clear\"  # called to free memory at end of condest function\n      clear Ainv Ainvt n isreal_op;\n  endswitch\n\nendfunction\n\n\n## Note: These test bounds are very loose.  There is enough randomization to\n## trigger odd cases with hilb().\n\n%!function retval = __Afcn__ (flag, x, A, m)\n%!  if (nargin == 3)\n%!    m = 1;\n%!  endif\n%!  switch (flag)\n%!    case \"dim\"\n%!      retval = length (A);\n%!    case \"real\"\n%!      retval = isreal (A);\n%!    case \"notransp\"\n%!      retval = x; for i = 1:m, retval = A * retval;, endfor\n%!    case \"transp\"\n%!      retval = x; for i = 1:m, retval = A' * retval;, endfor\n%!  endswitch\n%!endfunction\n%!function retval = __Ainvfcn__ (flag, x, A, m)\n%!  if (nargin == 3)\n%!    m = 1;\n%!  endif\n%!  switch (flag)\n%!    case \"dim\"\n%!      retval = length (A);\n%!    case \"real\"\n%!      retval = isreal (A);\n%!    case \"notransp\"\n%!      retval = x; for i = 1:m, retval = A \\ retval;, endfor\n%!    case \"transp\"\n%!      retval = x; for i = 1:m, retval = A' \\ retval;, endfor\n%!  endswitch\n%!endfunction\n\n%!test\n%! N = 6;\n%! A = hilb (N);\n%! cA = condest (A);\n%! cA_test = norm (inv (A), 1) * norm (A, 1);\n%! assert (cA, cA_test, -2^-8);\n\n%!test\n%! N = 12;\n%! A = hilb (N);\n%! [~, v] = condest (A);\n%! x = A*v;\n%! assert (norm (x, inf), 0, eps);\n\n%!test\n%! N = 6;\n%! A = hilb (N);\n%! Ainvfcn = @(flag, x) __Ainvfcn__ (flag, x, A);\n%! cA = condest (A, Ainvfcn);\n%! cA_test = norm (inv (A), 1) * norm (A, 1);\n%! assert (cA, cA_test, -2^-6);\n\n%!test\n%! N = 6;\n%! A = hilb (N);\n%! Afcn = @(flag, x) __Afcn__ (flag, x, A);\n%! Ainvfcn = @(flag, x) __Ainvfcn__ (flag, x, A);\n%! cA = condest (Afcn, Ainvfcn);\n%! cA_test = norm (inv (A), 1) * norm (A, 1);\n%! assert (cA, cA_test, -2^-6);\n\n%!test # parameters for apply and Ainvfcn functions\n%! N = 6;\n%! A = hilb (N);\n%! m = 2;\n%! cA = condest (@__Afcn__, @__Ainvfcn__, [], A, m);\n%! cA_test = norm (inv (A^2), 1) * norm (A^2, 1);\n%! assert (cA, cA_test, -2^-6);\n\n## Test singular matrices\n%!test <*46737>\n%! A = [ 0         0         0\n%!       0   3.33333 0.0833333\n%!       0 0.0833333   1.66667];\n%! [cest, v] = condest (A);\n%! assert (cest, Inf);\n%! assert (v, []);\n\n## Test asymmetric matrices\n%!test <*57968>\n%! A = reshape (sqrt (0:15), 4, 4);\n%! cexp = norm (A, 1) * norm (inv (A), 1);\n%! cest = condest (A);\n%! assert (cest, cexp, -2*eps);\n\n%!testif HAVE_UMFPACK <*57968>\n%! As = sparse (reshape (sqrt (0:15), 4, 4));\n%! cexp = norm (As, 1) * norm (inv (As), 1);\n%! cest = condest (As);\n%! assert (cest, cexp, -1e-12);\n\n## Test input validation\n%!error <Invalid call> condest ()\n%!error <Invalid call> condest (1,2,3,4,5,6,7)\n%!error <A must be square> condest ([1, 2])\n%!error <must provide AINVFCN when using AFCN> condest (@sin)\n%!error <AINVFCN must be a function handle> condest (@sin, 1)\n%!error <argument must be a square matrix or function handle> condest ({1})\n"
  },
  {
    "path": "scripts/linear-algebra/cross.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{z} =} cross (@var{x}, @var{y})\n## @deftypefnx {} {@var{z} =} cross (@var{x}, @var{y}, @var{dim})\n## Compute the vector cross product of two 3-dimensional vectors @var{x} and\n## @var{y}.\n##\n## If @var{x} and @var{y} are arrays, the cross product is applied along the\n## first dimension with three elements.\n##\n## The optional argument @var{dim} forces the cross product to be calculated\n## along the specified dimension.  An error will be produced if the specified\n## dimension is not three elements in size.\n##\n## In the case of a complex output, orthogonality of the output with respect\n## to the inputs is also satisfied, and the condition\n##\n## @example\n## @code{dot (conj (@var{z}), @var{x}) @equiv{} dot (conj (@var{z}), @var{y}) = 0}\n## @end example\n##\n## @noindent\n## is met.  @code{dot (@var{z}, @var{x}) = 0} and\n## @code{dot (@var{z}, @var{y}) = 0} will not hold.  Also note that instead of\n## using the @code{dot} function, the inner product\n##\n## @example\n## @code{@var{z}(:).' * @var{x}(:) @equiv{} @var{z}(:).' * @var{y}(:) = 0}\n## @end example\n##\n## @noindent\n## will meet the orthogonality condition for vector input.\n##\n## Example Code:\n##\n## @example\n## @group\n## cross ([1, 1, 0], [0, 1, 1])\n##   @xresult{}\n##        1  -1   1\n## @end group\n## @end example\n##\n## @example\n## @group\n## cross (magic (3), eye (3), 2)\n##   @xresult{}\n##        0   6  -1\n##       -7   0   3\n##        9  -4   0\n## @end group\n## @end example\n##\n## @seealso{dot, curl, divergence, conj}\n## @end deftypefn\n\nfunction z = cross (x, y, dim)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  nd = ndims (x);\n\n  if (nargin < 3 && nd < 3 && ndims (y) < 3)\n    ## Matlab Compatibility: mixed row/column vector inputs.\n    ## Transpose x and y in the assignments below to get row output to match\n    ## Matlab behavior (verified version: 2023b).\n    ## Recommend instead that programmers change calling code to use matched\n    ## vectors to remove any ambiguity in output form.\n    if (columns (x) == 1 && rows (y) == 1)\n      warning (\"cross: cross product of column by row produces row output\");\n      x = x.';\n    elseif (rows (x) == 1 && columns (y) == 1)\n      warning (\"cross: cross product of row by column produces row output\");\n      y = y.';\n    endif\n  endif\n\n  sz = size (x);\n\n  if (nargin == 2)\n     dim = find (sz == 3, 1);\n     if (isempty (dim))\n       error (\"cross: must have at least one dimension with 3 elements\");\n     endif\n  else\n    if (! (isnumeric (dim) && dim > 0 && isreal (dim) && ...\n          isscalar (dim) && dim == fix (dim)))\n      error (\"cross: DIM must be a positive scalar whole number\");\n    endif\n\n    if (dim > nd || sz(dim) != 3 || ...\n         dim > ndims (y) || size (y, dim) != 3)\n      error (\"cross: X and Y must have three elements in dimension DIM\");\n    endif\n  endif\n\n  idx2 = idx3 = idx1 = {':'}(ones (1, nd));\n  idx1(dim) = 1;\n  idx2(dim) = 2;\n  idx3(dim) = 3;\n\n  if (size_equal (x, y))\n    x1 = x(idx1{:});\n    x2 = x(idx2{:});\n    x3 = x(idx3{:});\n    y1 = y(idx1{:});\n    y2 = y(idx2{:});\n    y3 = y(idx3{:});\n    z = cat (dim, (x2.*y3 - x3.*y2), (x3.*y1 - x1.*y3), (x1.*y2 - x2.*y1));\n  else\n    error (\"cross: X and Y must have the same dimensions\");\n  endif\n\nendfunction\n\n\n%!test\n%! x = [1, 0, 0];\n%! y = [0, 1, 0];\n%! r = [0, 0, 1];\n%! assert (cross (x, y), r, eps);\n\n%!test\n%! x = [1, 2, 3];\n%! y = [4, 5, 6];\n%! r = [(2*6-3*5), (3*4-1*6), (1*5-2*4)];\n%! assert (cross (x, y), r, eps);\n\n%!test\n%! x = [1, 0, 0; 0, 1, 0; 0, 0, 1];\n%! y = [0, 1, 0; 0, 0, 1; 1, 0, 0];\n%! r = [0, 0, 1; 1, 0, 0; 0, 1, 0];\n%! assert (cross (x, y, 2), r, eps);\n%! assert (cross (x, y, 1), -r, eps);\n\n%!test\n%! x = [1, 0, 0; 0, 1, 0; 0, 0, 1];\n%! x = cat (3, x, x);\n%! y = [0, 1, 0; 0, 0, 1; 1, 0, 0];\n%! y = cat (3, y, y);\n%! r = [0, 0, 1; 1, 0, 0; 0, 1, 0];\n%! r = cat (3, r, r);\n%! assert (cross (x, y, 2), r, eps);\n%! assert (cross (x, y, 1), -r, eps);\n%! fail (\"cross (x, y, 3)\", \"X and Y must have three elements\");\n\n## Test mixed vector inputs\n%!test <*61295>\n%! x = [1, 0, 0];\n%! y = [0, 1, 0];\n%! r = [0, 0, 1];\n%! warning (\"off\", \"all\", \"local\");\n%! assert (cross (x, y), r, eps);\n%! assert (cross (x', y'), r', eps);\n%! assert (cross (x', y), r, eps);\n%! assert (cross (x, y'), r, eps);\n\n\n## Test input validation\n%!error <Invalid call> cross ()\n%!error <Invalid call> cross (1)\n%!error <must have at least one dimension with 3 elements> cross (0, 0)\n%!error <must have at least one dimension with 3 elements> cross ([1, 2], [3, 4])\n%!error <must have at least one dimension with 3 elements> cross ([1, 2], [3, 4, 5])\n%!error <X and Y must have three elements in dimension DIM> cross (0, 0, 1)\n%!error <X and Y must have three elements in dimension DIM> cross ([1, 2, 3], [1, 2, 3], 1)\n%!error <X and Y must have three elements in dimension DIM> cross ([1, 2, 3], [1, 2, 3], 9)\n%!error <X and Y must have three elements in dimension DIM> cross (magic (3), magic (3), 4)\n%!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], {1})\n%!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], \"a\")\n%!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], true)\n%!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], [1, 2])\n%!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], 0)\n%!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], -1)\n%!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], 1.5)\n%!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], 2i)\n%!error <X and Y must have the same dimensions> cross ([1, 2, 3], [3, 4])\n%!warning <cross product of column by row> cross ([1, 2, 3]', [4, 5, 6]);\n%!warning <cross product of row by column> cross ([1, 2, 3], [4, 5, 6]');\n\n%!test\n%! x = cat (3, [1, 1, 1]', [1, 1, 1]');\n%! y = cat (3, [1, 0, 0], [1, 0, 0]);\n%! fail (\"cross (x, y)\", \"X and Y must have the same dimensions\");\n%! fail (\"cross (y, x)\", \"X and Y must have the same dimensions\");\n"
  },
  {
    "path": "scripts/linear-algebra/duplication_matrix.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{d} =} duplication_matrix (@var{n})\n## Return the duplication matrix\n## @tex\n##  $D_n$\n## @end tex\n## @ifnottex\n## @nospell{@math{Dn}}\n## @end ifnottex\n## which is the unique\n## @tex\n##  $n^2 \\times n(n+1)/2$\n## @end tex\n## @ifnottex\n## @math{N^2}-by-@math{N*(N+1)/2}\n## @end ifnottex\n## matrix such that\n## @tex\n##  $D_n * {\\rm vech} (A) = {\\rm vec} (A)$\n## @end tex\n## @ifnottex\n## @nospell{@code{Dn * vech (A) = vec (A)}}\n## @end ifnottex\n## for all symmetric\n## @tex\n##  $n \\times n$\n## @end tex\n## @ifnottex\n## @math{N}-by-@math{N}\n## @end ifnottex\n## matrices\n## @tex\n##  $A$.\n## @end tex\n## @ifnottex\n## @math{A}.\n## @end ifnottex\n##\n## See @nospell{Magnus and Neudecker}, @cite{Matrix Differential Calculus with\n## Applications in Statistics and Econometrics}, 1988.\n## @end deftypefn\n\nfunction d = duplication_matrix (n)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (n) && n > 0 && n == fix (n)))\n    error (\"duplication_matrix: N must be a positive integer\");\n  endif\n\n  d = zeros (n * n, n * (n + 1) / 2);\n\n  ## It is clearly possible to make this a LOT faster!\n  count = 0;\n  for j = 1 : n\n    d((j - 1) * n + j, count + j) = 1;\n    for i = (j + 1) : n\n      d((j - 1) * n + i, count + i) = 1;\n      d((i - 1) * n + j, count + i) = 1;\n    endfor\n    count += n - j;\n  endfor\n\nendfunction\n\n\n%!test\n%! N = 2;\n%! A = rand (N);\n%! B = A * A';\n%! C = A + A';\n%! D = duplication_matrix (N);\n%! assert (D * vech (B), vec (B), 1e-6);\n%! assert (D * vech (C), vec (C), 1e-6);\n\n%!test\n%! N = 3;\n%! A = rand (N);\n%! B = A * A';\n%! C = A + A';\n%! D = duplication_matrix (N);\n%! assert (D * vech (B), vec (B), 1e-6);\n%! assert (D * vech (C), vec (C), 1e-6);\n\n%!test\n%! N = 4;\n%! A = rand (N);\n%! B = A * A';\n%! C = A + A';\n%! D = duplication_matrix (N);\n%! assert (D * vech (B), vec (B), 1e-6);\n%! assert (D * vech (C), vec (C), 1e-6);\n\n%!error <Invalid call> duplication_matrix ()\n%!error duplication_matrix (0.5)\n%!error duplication_matrix (-1)\n%!error duplication_matrix (ones (1,4))\n"
  },
  {
    "path": "scripts/linear-algebra/expm.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{r} =} expm (@var{A})\n## Return the exponential of a matrix.\n##\n## The matrix exponential is defined as the infinite Taylor series\n## @tex\n## $$\n##  \\exp (A) = I + A + {A^2 \\over 2!} + {A^3 \\over 3!} + \\cdots\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## expm (A) = I + A + A^2/2! + A^3/3! + @dots{}\n## @end example\n##\n## @end ifnottex\n## However, the Taylor series is @emph{not} the way to compute the matrix\n## exponential; see @nospell{Moler and Van Loan}, \"Nineteen Dubious Ways\n## to Compute the Exponential of a Matrix\", @cite{SIAM Review}, 1978.  This\n## routine uses Ward's diagonal Pad@'e approximation method with three step\n## preconditioning (@cite{SIAM Journal on Numerical Analysis}, 1977).  Diagonal\n## Pad@'e approximations are rational polynomials of matrices\n## @tex\n## $D_q(A)^{-1}N_q(A)$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##      -1\n## D (A)   N (A)\n## @end group\n## @end example\n##\n## @end ifnottex\n## whose Taylor series matches the first\n## @tex\n## $2 q + 1 $\n## @end tex\n## @ifnottex\n## @code{2q+1}\n## @end ifnottex\n## terms of the Taylor series above; direct evaluation of the Taylor series\n## (with the same preconditioning steps) may be desirable in lieu of the\n## Pad@'e approximation when\n## @tex\n## $D_q(A)$\n## @end tex\n## @ifnottex\n## @code{Dq(A)}\n## @end ifnottex\n## is ill-conditioned.\n## @seealso{logm, sqrtm}\n## @end deftypefn\n\nfunction r = expm (A)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (A) || ! issquare (A))\n    error (\"expm: A must be a square matrix\");\n  endif\n\n  if (isempty (A))\n    r = A;\n    return;\n  elseif (isscalar (A))\n    r = exp (A);\n    return;\n  elseif (isdiag (A))\n    r = diag (exp (diag (A)));\n    return;\n  endif\n\n  n = rows (A);\n  id = eye (n);\n  ## Trace reduction.\n  A(A == -Inf) = -realmax ();\n  trshift = trace (A) / n;\n  if (trshift > 0)\n    A -= trshift * id;\n  endif\n  ## Balancing.\n  [d, p, aa] = balance (A);\n  [~, e] = log2 (norm (aa, \"inf\"));\n  s = max (0, e);\n  s = min (s, 1023);\n  aa *= 2^(-s);\n\n  ## Pade approximation for exp(A).\n  c = [5.0000000000000000e-1, ...\n       1.1666666666666667e-1, ...\n       1.6666666666666667e-2, ...\n       1.6025641025641026e-3, ...\n       1.0683760683760684e-4, ...\n       4.8562548562548563e-6, ...\n       1.3875013875013875e-7, ...\n       1.9270852604185938e-9];\n\n  a2 = aa^2;\n  x = (((c(8) * a2 + c(6) * id) * a2 + c(4) * id) * a2 + c(2) * id) * a2 + id;\n  y = (((c(7) * a2 + c(5) * id) * a2 + c(3) * id) * a2 + c(1) * id) * aa;\n\n  r = (x - y) \\ (x + y);\n\n  ## Undo scaling by repeated squaring.\n  for k = 1:s\n    r ^= 2;\n  endfor\n\n  ## inverse balancing.\n  d = diag (d);\n  r = d * r / d;\n  r(p, p) = r;\n  ## Inverse trace reduction.\n  if (trshift > 0)\n    r *= exp (trshift);\n  endif\n\nendfunction\n\n\n%!assert (norm (expm ([1 -1;0 1]) - [e -e; 0 e]) < 1e-5)\n%!assert (expm ([1 -1 -1;0 1 -1; 0 0 1]), [e -e -e/2; 0 e -e; 0 0 e], 1e-5)\n\n%!assert (expm ([]), [])\n%!assert (expm (10), exp (10))\n%!assert (full (expm (eye (3))), expm (full (eye (3))))\n%!assert (full (expm (10*eye (3))), expm (full (10*eye (3))), 8*eps)\n%!assert (expm (zeros (3)), eye (3))\n\n## Test input validation\n%!error <Invalid call> expm ()\n%!error <expm: A must be a square matrix> expm ({1})\n%!error <expm: A must be a square matrix> expm ([1 0;0 1; 2 2])\n"
  },
  {
    "path": "scripts/linear-algebra/funm.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{F} =} funm (@var{A}, @var{fun})\n## @deftypefnx {} {@var{F} =} funm (@var{A}, @var{fun}, @var{options})\n## @deftypefnx {} {@var{F} =} funm (@var{A}, @var{fun}, @var{options}, @var{p1}, @dots{})\n## @deftypefnx {} {[@var{F}, @var{exitflag}] =} funm (@dots{})\n## @deftypefnx {} {[@var{F}, @var{exitflag}, @var{output}] =} funm (@dots{})\n##\n## Evaluate a general matrix function.\n##\n## @code{funm (@var{A}, @var{fun})} evaluates the function @var{fun} at the\n## square matrix @var{A}.  The input @w{@code{@var{fun} (@var{x}, @var{k})}}\n## must return the @var{k}'th derivative of the function represented by\n## @var{fun} evaluated at the vector @var{x}.  The function @var{fun} must have\n## a Taylor series representation with an infinite radius of convergence.\n##\n## The special functions @code{exp}, @code{log}, @code{sin}, @code{cos},\n## @code{sinh}, and @code{cosh} can be passed by function handle; for example\n## @w{@code{funm (@var{A}, @@cos)}}.\n##\n## For matrix square roots, use @code{sqrtm} instead.  For matrix exponentials,\n## either @code{expm} or @w{@code{funm (@var{A}, @@exp)}} may be faster or more\n## accurate, depending on @var{A}.\n##\n## An optional third input in the form of an options struct @var{options} can\n## be used to specify verbosity of the function and to influence certain of the\n## algorithms.  See the references below for more details on the latter.\n##\n## @var{options} can have the following fields:\n##\n## @table @code\n## @item Display\n## Specify what information will be printed to the screen during the course of\n## calculations.  It can be either a string value of @qcode{\"off\"} (no info,\n## the default), @qcode{\"on\"} (some info), @qcode{\"verbose\"} (maximum info); or\n## a scalar value between @code{0} (no info, the default) and @code{5} (maximum\n## info).  When @code{Display} is @qcode{\"verbose\"} or a scalar value @geq{}\n## @code{3}, a plot of the eigenvalues and groups will also be shown.\n##\n## @item TolBlk\n## Tolerance used in determining the blocking (positive scalar, default:\n## @code{0.1}).\n##\n## @item TolTay\n## Tolerance used in the convergence test for evaluating the Taylor series\n## (positive scalar, default: @code{eps}).\n##\n## @item MaxTerms\n## The maximum number of Taylor series terms (positive integer, default:\n## @code{250}).\n##\n## @item MaxSqrt\n## The maximum number of square roots evaluated in the course of inverse\n## scaling and squaring (positive integer, default: @code{100}).  This option\n## is only used when computing a logarithm where it functions similarly to\n## @code{MaxTerms}.\n##\n## @item Ord\n## Define a custom blocking pattern in the form of a vector whose length equals\n## the order of the matrix @var{A}.\n##\n## @end table\n##\n## Octave accepts any case for these fieldnames.\n##\n## All inputs beyond @var{options} will be passed as positional arguments to\n## the function @var{fun}.\n##\n## Optional outputs:\n##\n## @table @var\n## @item exitflag\n## Scalar exit flag that describes the exit condition:\n##\n## @itemize @w{}\n## @item @code{0} --- The algorithm was successful.\n##\n## @item @code{1} --- One or more Taylor series evaluations did not converge,\n## but the computed value of @var{F} might still be accurate.\n## @end itemize\n##\n## @item output\n## Structure with the following fields:\n##\n## @table @code\n## @item terms\n## Vector for which @code{output.terms(i)} is the number of Taylor series terms\n## used when evaluating the @nospell{i'th} block, or, in the case of the\n## logarithm, the number of square roots of matrices of dimension greater than\n## 2.\n##\n## @item ind\n## Cell array for which the (i,j) block of the reordered Schur factor @var{T}\n## is @code{@var{T}(output.ind@{i@}, output.ind@{j@})}.\n##\n## @item ord\n## Ordering of the Schur form, as passed to @code{ordschur}.\n##\n## @item T\n## Reordered Schur form.\n## @end table\n##\n## If the Schur form is diagonal then\n## @code{output = struct (\"terms\", ones (n, 1), \"ind\", @{1:n@}, \"ord\", [],\n## \"T\", @var{T})}.\n## @end table\n##\n## Example:\n##\n## @example\n## @group\n## F = funm (magic (3), @@sin);\n## @result{} F =\n##    -0.3850    1.0191    0.0162\n##     0.6179    0.2168   -0.1844\n##     0.4173   -0.5856    0.8185\n## @end group\n## @end example\n##\n## The code\n##\n## @example\n## @group\n## S = funm (X, @@sin);\n## C = funm (X, @@cos);\n## @end group\n## @end example\n##\n## @noindent\n## will produce the same results (within possible rounding error) as\n##\n## @example\n## @group\n## E = expm (i*X);\n## C = real (E);\n## S = imag (E);\n## @end group\n## @end example\n##\n## References:\n##\n## @nospell{Philip I. Davies and Nicholas J. Higham},\n## \"A @nospell{Schur-Parlett} algorithm for computing matrix functions\",\n## @cite{SIAM Journal on Matrix Analysis and Applications}, @w{Vol.@: 25(2)},\n## @w{pp.@: 464}--485, 2003.\n##\n## @nospell{Nicholas J. Higham}, @cite{Functions of Matrices: Theory and\n## Computation}, SIAM, @w{pp.@: 425}, 2008, ISBN 978-0-898716-46-7.\n##\n## @seealso{expm, logm, sqrtm}\n## @end deftypefn\n\nfunction [F, exitflag, output] = funm (A, fun, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  elseif (! (issquare (A) && isnumeric (A)))\n    error (\"funm: A must be a numeric square matrix\");\n  elseif (! (isa (fun, \"function_handle\") || ischar (fun)))\n    error (\"funm: FUN must be a function handle or function name\");\n  elseif (nargin > 2 && ! (isstruct (varargin{1}) && isscalar (varargin{1})))\n    error (\"funm: OPTIONS must be a scalar struct\");\n  endif\n\n  ## Default values:\n  tolblk    = 0.1;   # Tolerance for blocking\n  taytol   = eps;   # Convergence tolerance for Taylor expansion\n  prnt     = 0;     # Disable display of algorithm progress\n  maxterms = 250;   # max # of Taylor series terms\n  maxsqrt  = 100;   # i.c.o. logarithm,\n                    # max # of sq_roots computed in inv. scaling\n  m        = [];    # blocking order\n\n  ## Check options if present.\n  if (nargin > 2)\n    options = varargin{1};\n    varargin(1) = [];\n\n    for opt = (fieldnames (options)).'\n      val = options.(opt{1});\n      switch (lower (opt{1}))\n\n        case \"display\"\n          ## Matlab seems to support just two verbosity settings, but in the\n          ## code below we use [0, 1, 2, 3, 5].  We use 1 for \"on\" and 4 for\n          ## \"verbose\".  AND, we will still support the more fine-grained\n          ## existing numerical verbosity setting next to Matlab's string\n          ## values.\n          if (ischar (val))\n            if (strcmpi (val, \"on\"))\n              prnt = 1;\n            elseif (strcmpi (val, \"verbose\"))\n              prnt = 4;\n            elseif (strcmpi (val, \"off\"))\n              prnt = 0;\n            else\n              error (\"funm: invalid string value specified for options field Display: %s\", val);\n            endif\n          elseif (isnumeric (val) && isscalar (val) && val >= 0)\n            prnt = val;\n          else\n            error (\"funm: options.Display must be a string or scalar value >= 0\");\n          endif\n\n        case \"tolblk\"\n          if (! (isnumeric (val) && isscalar (val) && val > 0))\n            error (\"funm: options.TolBlk must be a positive scalar value\");\n          endif\n          tolblk = val;\n\n        case \"toltay\"\n          if (! (isnumeric (val) && isscalar (val) && val > 0))\n            error (\"funm: options.TolTay must be a positive scalar value\");\n          endif\n          taytol = val;\n\n        case \"maxterms\"\n          if (! (isnumeric (val) && isscalar (val) && val > 0))\n            error (\"funm: options.MaxTerms must be a positive integer value\");\n          endif\n          maxterms = ceil (val);\n\n        case \"maxsqrt\"\n          if (! (isnumeric (val) && isscalar (val) && val > 0))\n            error (\"funm: options.MaxSqrt must be a positive integer value\");\n          endif\n          maxsqrt = ceil (val);\n\n        case \"ord\"\n          if (! (isindex (val) && isvector (val) && numel (val) == rows (A)))\n            error (\"funm: options.Ord must be a numeric or logical vector with a length equal to order (A)\");\n          endif\n          m = val;\n\n        otherwise\n          warning (\"funm: ignoring unknown options field '%s'\", opt{1});\n\n      endswitch\n    endfor\n  endif\n\n  ## Algorithm performs all calculations in double.\n  ## Return class single if A is single, otherwise double.\n\n  ## Convert to double\n  input_is_single = isa (A, \"single\");  # Remember input class.\n  A = double (A);\n\n  ## Check for special functions\n  switch (fun)\n    case {@exp, \"exp\"}\n      fun = @fun_exp;\n    case {@log, \"log\"}\n      fun = @fun_log;\n    case {@sin, \"sin\"}\n      fun = @fun_sin;\n    case {@cos, \"cos\"}\n      fun = @fun_cos;\n    case {@sinh, \"sinh\"}\n      fun = @fun_sinh;\n    case {@cosh, \"cosh\"}\n      fun = @fun_cosh;\n  endswitch\n\n  n = rows (A);\n  exitflag = 0;  # Initialize exitflag: 0 = success, 1 = convergence issues\n\n  ## Form complex Schur form (if A not already upper triangular).\n  T_upper = triu (A);\n  if (norm (A - T_upper, \"fro\") <= 10 * n * eps * norm (A, \"fro\"))\n    U = eye (n);\n    T = T_upper;\n  else\n    [U, T] = schur (A, \"complex\");\n  endif\n\n  ## Handle special case of diagonal T.\n  D = diag (T);\n  if (norm (T - diag (D), \"fro\") <= 10 * n * eps * norm (T, \"fro\"))\n    F = U * diag (feval (fun, D, varargin{:})) * U';\n\n    if (nargout > 2)\n      output = struct (\"terms\", ones (n, 1), \"ind\", {{1:n}},\n                       \"ord\", [], \"T\", T);\n    endif\n\n    ## Return single output class if necessary.\n    if (input_is_single)\n      F = single (F);\n      if (nargout > 2)\n        output.T = single (output.T);\n      endif\n    endif\n    return;\n\n  endif\n\n  ## Determine reordering of Schur form into block form.\n  if (isempty (m))\n    m = blocking (T, tolblk, (prnt >= 3));\n  endif\n\n  if (prnt)\n    printf (\"TolBlk (blocking) = %9.2e, TayTol (TS) = %9.2e\\n\", tolblk, taytol);\n  endif\n\n  [M, ind, n_swaps, ord] = swapping (m);\n  if (n_swaps > 0)\n    ## Reordering is needed.\n    [U, T] = trexc (U, T, M);\n  endif\n\n  m = numel (ind);\n\n  ## Calculate F(T).\n  F = zeros (n);\n\n  for col = 1:m\n    j = ind{col};\n    [F(j, j), n_terms] = funm_atom (T(j, j), fun, taytol, ...\n                                    (prnt >= 2), maxterms, maxsqrt);\n    terms(col) = n_terms;\n\n    ## Check for convergence failure.\n    if (n_terms == -1)\n      exitflag = 1;\n    endif\n\n    for row = col-1 : -1 : 1\n      i = ind{row};\n      if (numel (i) == 1 && numel (j) == 1)\n        ## Scalar case.\n        k = i + 1 : j - 1;\n        temp =   T(i, j) * (F(i, i) - F(j, j))  ...\n               + F(i, k) * T(k, j)              ...\n               - T(i, k) * F(k, j);\n        F(i, j) = temp / (T(i, i) - T(j, j));\n      else\n        k = cat (2, ind{row + 1 : col - 1});\n        rhs = F(i, i) * T(i, j) - T(i, j) * F(j, j) + ...\n              F(i, k) * T(k, j) - T(i, k) * F(k, j);\n        F(i, j) = sylvester (T(i, i), -T(j, j), rhs);\n      endif\n    endfor\n  endfor\n\n  F = U * F * U';\n\n  ## As in FUNM:\n  if (isreal (A) && norm (imag (F), \"fro\") <= 10 * n * eps * norm (F, \"fro\"))\n    F = real (F);\n  endif\n\n  ## Prepare output structure if requested.\n  if (nargout > 2)\n    output = struct (\"terms\", terms, \"ind\", {ind}, \"ord\", ord, \"T\", T);\n  endif\n\n  ## Return single output class if necessary.\n  if (input_is_single)\n    F = single (F);\n    if (nargout > 2)\n      output.T = single (output.T);\n    endif\n  endif\n\nendfunction\n\n\n## FUN_COS\nfunction f = fun_cos (x, k)\n\n  if (nargin < 2 || k == 0)\n    f = cos (x);\n  else\n    g = mod (ceil (k / 2), 2);\n    h = mod (k, 2);\n    if (h == 1)\n      f = sin (x) * (-1)^g;\n    else\n      f = cos (x) * (-1)^g;\n    endif\n  endif\n\nendfunction\n\n\n## FUN_COSH\nfunction f = fun_cosh (x, k)\n\n  if (nargin < 2 || k == 0)\n    f = cosh (x);\n  elseif (mod (k, 2))\n    f = sinh (x);\n  else\n    f = cosh (x);\n  endif\n\nendfunction\n\n\n## FUN_SINH\nfunction f = fun_sinh (x, k)\n\n  if (nargin < 2 || k == 0)\n    f = sinh (x);\n  elseif (mod (k, 2))\n    f = cosh (x);\n  else\n    f = sinh (x);\n  endif\n\nendfunction\n\n\n## FUN_EXP\nfunction f = fun_exp (x, k)\n\n  f = exp (x);\n\nendfunction\n\n\n## FUN_SIN\nfunction f = fun_sin (x, k)\n\n  if (nargin < 2 || k == 0)\n    f = sin (x);\n  else\n    k = k - 1;\n    g = mod (ceil (k / 2), 2);\n    h = mod (k, 2);\n    if (h == 1)\n      f = sin (x) * (-1)^g;\n    else\n      f = cos (x) * (-1)^g;\n    endif\n  endif\n\nendfunction\n\n\n## BLOCKING function\n## Produce blocking pattern for block Parlett recurrence.\n##\n## M = blocking (A, DELTA, SHOWPLOT) accepts an upper triangular matrix A and\n## produces a blocking pattern, specified by the vector M, for the block\n## Parlett recurrence.\n##\n## M(i) is the index of the block into which A(i,i) should be placed.\n##\n## DELTA is a gap parameter used to determine the blocking.\n##\n## Setting SHOWPLOT nonzero produces a plot of the eigenvalues\n## that indicates the blocking:\n##  - Black circles show a set of 1 eigenvalue.\n##  - Blue circles show a set of >1 eigenvalues.\n##    The lines connect eigenvalues in the same set.\n##\n## For A coming from a real matrix it should be possible to take\n## advantage of the symmetry about the real axis.  This code does not.\nfunction m = blocking (A, delta, showplot)\n\n  a = diag (A);\n  n = numel (a);\n  m = zeros (1, n);\n  maxM = 0;\n\n  if (showplot)\n    clf;\n    hold on;\n  endif\n\n  ## Pre-compute distance matrix.\n  a_col = a(:);\n  a_row = a_col.';\n  dist_matrix = abs (a_col - a_row);\n\n  for i = 1:n\n    if (m(i) == 0)\n      m(i) = maxM + 1;             # If a(i) hasn't been assigned to a set\n      maxM = maxM + 1;             # then make a new set and assign a(i) to it.\n    endif\n\n    for j = i + 1 : n\n      if (m(i) != m(j) && dist_matrix(i, j) <= delta)\n        if (showplot)\n          plot (real ([a(i) a(j)]), imag ([a(i) a(j)]), \"o-\");\n        endif\n\n        if (m(j) == 0)\n          m(j) = m(i);             # If a(j) hasn't been assigned to a set,\n                                   # assign it to the same set as a(i).\n        else\n          p = max (m(i), m(j));\n          q = min (m(i), m(j));\n          m(m == p) = q;           # If a(j) has been assigned to a set\n                                   # place all the elements in the set\n                                   # containing a(j) into the set\n                                   # containing a(i) (or vice versa).\n\n          m(m > p) = m(m > p) - 1; # Tidying up.  As we have deleted set p,\n          maxM = maxM - 1;         # we reduce the index of the sets > p by 1.\n        endif\n      endif\n    endfor\n  endfor\n\n  if (showplot)\n    for i = 1 : max (m)            # for each cluster\n      a_ind = a(m == i);           # get eigv in cluster i\n      if (numel (a_ind) == 1)      # if only one eigv in cluster\n        plot (real (a_ind), imag (a_ind), \"ok\");  # plot it alone\n      endif\n    endfor\n    hold off;\n    grid on;\n    box on;\n    xlabel ('Re(\\lambda)');\n    ylabel ('Im(\\lambda)');\n    title (sprintf ('Eigenvalue clustering (\\\\delta = %g)', delta));\n  endif\n\nendfunction\n\n\n## SWAPPING function\n## Confluent permutation by swapping adjacent elements.\n##\n## [M, IND, N_SWAPS, ORD] = swapping (M) takes a vector M containing block\n## indices and constructs a swapping scheme that produces a confluent\n## permutation, with elements ordered by ascending average position.  The\n## confluent permutation is obtained by using the LAPACK routine ZTREXC to move\n## m(M(i,2)) to m(M(i,1)) by swapping adjacent elements, for i = 1:SIZE(M,1).\n##\n## The cell array vector IND defines the resulting block form: IND{i} contains\n## the indices of the i'th block in the permuted form.\n##\n## N_SWAPS is the total number of swaps required.\n\n## ORD is the cluster ordering vector suitable for use with ordschur.\nfunction [M, ind, n_swaps, ord] = swapping (m)\n\n  n = numel (m);\n  mmax = max (m);\n  M = [];\n  ind = {};\n  h = zeros (1, mmax);\n  g = zeros (1, mmax);\n\n  for i = 1 : mmax\n    p = find (m == i);\n    h(i) = numel (p);\n    g(i) = sum (p) / h(i);\n  endfor\n\n  [~, y] = sort (g);\n\n  ## Compute ord: eigenvalues in block y(k) get cluster k.\n  ord = zeros (1, n);\n  for k = 1 : mmax\n    ord(m == y(k)) = k;\n  endfor\n\n  mdone = 1;\n\n  for i = y\n    if (any (m(mdone : mdone + h(i) - 1) != i))\n      f = find (m == i);\n      g = mdone : mdone + h(i) - 1;\n      ff = f(f != g);\n      gg = g(f != g);\n\n      ## Create vector v = mdone:f(end) with all elements of f deleted.\n      v = mdone - 1 + find (m(mdone : f(end)) != i);\n\n      M(end + 1 : end + numel (gg), :) = [gg' ff'];\n\n      m(g(end) + 1 : f(end)) = m(v);\n      m(g) = i * ones (1, h(i));\n      ind = cat (2, ind, {mdone : mdone + h(i) - 1});\n      mdone = mdone + h(i);\n    else\n      ind = cat (2, ind, {mdone : mdone + h(i) - 1});\n      mdone = mdone + h(i);\n    endif\n  endfor\n\n  n_swaps = sum (abs (diff (M')));\n\nendfunction\n\n\n## FUNM_ATOM functions\n## Function of triangular matrix with nearly constant diagonal.\n##\n## [F, N_TERMS] = funm_atom (T, FUN, TOL, PRNT) evaluates function FUN at the\n## upper triangular matrix T, where T has nearly constant diagonal.  A Taylor\n## series is used.\n##\n## FUN(X,K) must return the K'th derivative of the function represented by FUN\n## evaluated at the vector X.\n##\n## TOL is a convergence tolerance for the Taylor series.\n##\n## If PRNT != 0 trace information is printed.\n##\n## N_TERMS is the number of terms taken in the Taylor series.\n##\n## N_TERMS = -1 signals lack of convergence.\nfunction [F, n_terms] = funm_atom (T, fun, tol, prnt, maxterms, maxsqrt, ...\n                                   varargin)\n\n  if (isequal (fun, @fun_log))        # LOG is special case.\n    [F, iter] = logm_isst (T, prnt, maxsqrt);\n    n_terms = iter;                   # iter = -1 signals convergence failure\n    return;\n  endif\n\n  n = rows (T);\n  if (n == 1)\n    F = feval (fun, T, 0, varargin{:});\n    n_terms = 1;\n    return;\n  endif\n\n  lambda = sum (diag (T)) / n;\n  F = eye (n) * feval (fun, lambda, 0, varargin{:});\n  f_deriv_max = zeros (maxterms + n - 1, 1);\n  N = T - lambda * eye (n);\n  mu = norm ((eye (n) - abs (triu (T, 1))) \\ ones (n, 1), \"fro\");\n\n  P = N;\n  max_d = 1;\n\n  for k = 1 : maxterms\n    f = feval (fun, lambda, k, varargin{:});\n    F_old = F;\n    F = F + P * f;\n    rel_diff = norm (F - F_old, \"fro\") / (tol + norm (F_old, \"fro\"));\n    if (prnt)\n      printf (\"%3.0f: coef = %5.0e\", k, abs (f) / factorial (k));\n      printf (\"  N^k/k! = %7.1e\", norm (P, \"fro\"));\n      printf (\"  rel_d = %5.0e\", rel_diff);\n      printf (\"  abs_d = %5.0e\\n\", norm (F - F_old, \"fro\"));\n    endif\n    P = P * N / (k + 1);\n\n    if (rel_diff <= tol)\n      ## Approximate the maximum of derivatives in convex set containing\n      ## eigenvalues by maximum of derivatives at eigenvalues.\n      for j = max_d : k + n - 1\n        f_deriv_max(j) = norm (feval (fun, diag (T), j, varargin{:}), \"fro\");\n      endfor\n      max_d = k + n;\n      omega = 0;\n      for j = 0 : n - 1\n        omega = max (omega, f_deriv_max(k + j) / factorial (j));\n      endfor\n\n      trunc = norm (P, \"fro\") * mu * omega; # norm(F) moved to RHS to avoid / 0\n      if (prnt)\n        printf (\"  [trunc, test] = [%5.0e %5.0e]\\n\", ...\n                                    trunc, tol * norm (F, \"fro\"));\n      endif\n      if (prnt == 5)\n        trunc = 0;  # Force algorithm to stop in test below.\n      endif\n      if (trunc <= tol * norm (F, \"fro\"))  # stopping test.\n        n_terms = k + 1;\n        return;\n      endif\n    endif\n\n  endfor\n\n  n_terms = -1;  # Algorithm did not converge\n\nendfunction\n\n\n## FUN_LOG function\n## Only to be called for plain log evaluation.\nfunction f = fun_log (x)\n\n  f = log (x);\n\nendfunction\n\n\n## LOGM_ISST function\n## Log of triangular matrix by Schur-Pade method with scaling.\n##\n## X = LOGM_ISST(A, PRNT) computes the logarithm of an upper triangular matrix\n## A, for a matrix with no nonpositive real eigenvalues, using the inverse\n## scaling and squaring method with Pade approximation.\n##\n## [X, ITER] = LOGM_ISST(A, PRNT) returns the number ITER of square roots\n## computed and prints this information if PRNT is nonzero.\n##\n## ITER = -1 signals that too many square roots were needed.\n##\n## References:\n## S. H. Cheng, N. J. Higham, C. S. Kenney, and A. J. Laub, Approximating the\n##    logarithm of a matrix to specified accuracy, SIAM J. Matrix Anal. Appl.,\n##    22(4):1112-1125, 2001.\n## N. J. Higham, Evaluating Pade approximants of the matrix logarithm,\n##    SIAM J. Matrix Anal. Appl., 22(4):1126-1135, 2001.\nfunction [X, iter] = logm_isst (T, prnt, maxlogiter)\n\n  n = rows (T);\n\n  if (any (imag (diag (T)) == 0 & real (diag (T)) <= 0))\n    warning (\"funm: A must not have nonpositive real eigenvalues\");\n  endif\n\n  if (n == 1)\n    X = log (T);\n    iter = 0;\n    return;\n  endif\n\n  R = T;\n\n  for iter = 0:maxlogiter\n    phi = norm (T - eye (n), \"fro\");\n    if (phi <= 0.25)\n      if (prnt)\n        printf (\"LOGM_ISST computed %g square roots.\\n\", iter);\n      endif\n      break;\n    endif\n    if (iter == maxlogiter)\n      ## Signal convergence failure instead of error.\n      warning (\"funm: too many square roots in LOGM_ISST\");\n      X = 2 ^ (iter) * logm_pf (T - eye (n), 8);\n      iter = -1;    # Signal failure\n      return;\n    endif\n\n    ## Compute upper triangular square root R of T, a column at a time.\n    for j = 1 : n\n      R(j, j) = sqrt (T(j, j));\n      for i = j - 1 : -1 : 1\n        R(i, j) = (T(i, j) - R(i, i + 1 : j - 1) * R(i + 1 : j - 1, j)) / ...\n                  (R(i, i) + R(j, j));\n      endfor\n    endfor\n    T = R;\n  endfor\n\n  X = 2 ^ (iter) * logm_pf (T - eye (n), 8);\n\nendfunction\n\n\n## LOGM_PF\n## Pade approximation to matrix log by partial fraction expansion.\n##\n## S = LOGM_PF(A, M) approximates LOG(I+A) using M-point Gauss-Legendre\n## quadrature.\nfunction S = logm_pf (A, m)\n\n  [nodes, wts] = gauss_legendre (m);\n  ## Convert from [-1,1] to [0,1].\n  nodes = (nodes + 1) / 2;\n  wts = wts / 2;\n\n  n = rows (A);\n  S = zeros (n);\n\n  for j = 1 : m\n    S = S + wts(j) * (A / (eye (n) + nodes(j) * A));\n  endfor\n\nendfunction\n\n\n## GAUSS_LEGENDRE function\n## Nodes and weights for Gauss-Legendre quadrature.\n##\n## [X, W] = GAUSS_LEGENDRE(N) returns the N-point Gauss-Legendre nodes X and\n## weights W for integration on [-1, 1].\n##\n## Reference:\n## G. H. Golub and J. H. Welsch, Calculation of Gauss quadrature rules,\n## Math. Comp., 23(106):221-230, 1969.\nfunction [x, w] = gauss_legendre (n)\n\n  i = 1 : n - 1;\n  v = i ./ sqrt ((2 * i) .^ 2 - 1);\n  [V, D] = eig (diag (v, -1) + diag (v, 1));\n  x = diag (D);\n  w = 2 * (V(1, :)' .^ 2);\n\nendfunction\n\n\n%!demo\n%! ## Create a non-normal matrix with clustered complex eigenvalues.\n%! ## Use non-symmetric 2x2 blocks to ensure non-normality.\n%! B1 = [  1.1  3;  -2   1.1 ];  # eigenvalues: 1.1 +/- sqrt(6)i\n%! B2 = [  1.4  2;  -2   1.4 ];  # eigenvalues: 1.5 +/- 2i (close, will cluster)\n%! B3 = [ -0.3  1;   0   0.3 ];  # eigenvalues: -0.3, 0.3 (real1)\n%! B4 = [  2.4  2;  -1   2.4 ];  # eigenvalues: 2.4 +/- sqrt(2)i\n%! A = blkdiag (B1, B2, B3, B4);\n%! ## Add some noise to make A less structured, but with the same eigenvalues.\n%! Q = orth (randn (size (A)));\n%! A = Q' * A * Q;\n%! opts = struct (\"Display\", \"on\", \"TolBlk\", 0.8, \"TolTay\", eps);\n%! [F, exitflag] = funm (A, @sin, opts); # opts.Display = \"verbose\" triggers plot\n%! disp (\"Eigenvalues of A:\");\n%! disp (eig (A));\n\n## Basic function tests\n%!assert (funm (10, @log), log (10))\n%!assert (funm ([1 2;3 4], @sin), [-0.4656 -0.1484;-0.2226 -0.6882], 4e-5)\n%!assert (funm ([1 2;3 4], @cos), [0.8554 -0.1109;-0.1663 0.6891], 3e-5)\n%!assert (funm ([1 2;3 4], @exp), [51.9690 74.7366;112.1048 164.0738], 5e-5)\n%!assert (funm ([1 2;3 4], @logm), ...\n%!        [-0.35044+2.39112i 0.92935-1.09376i;\n%!         1.39403-1.64064i 1.04359+0.75047i], 1e-5)\n%!assert (funm ([1 2;3 4], @sinh), [25.4317 37.6201;56.4301 81.8618], 4e-5)\n%!assert (funm ([1 2;3 4], @cosh), [26.5372 37.1165;55.6747 82.2120], 5e-5)\n\n## Matrix with algebraic multiplicity for L=3 = 2, geometric multiplicity = 1\n%!test\n%! [a, b, c] = funm ([3 0 0 0; -6 4 1 5; 2 1 4 -1; 4 0 0 -3], @cos);\n%! assert (a, [-0.9900, 0, 0, 0; -0.3546, -0.3532, 0.6368, 0.3184; ...\n%!             -0.9191, 0.6368, -0.3532, 0.3184; 0, 0, 0, -0.9900], 5e-5)\n%! assert (b, 0);\n%! assert (c.terms, [1 3 1]);\n%! assert (c.ind, {1, [2 3], 4});\n%! assert (c.ord, [1 2 3 2]);\n\n## Another matrix with algebraic mult. = 3, geometric multipl. = 2\n%!test\n%! a = funm ([2, 0, 0; 4, 2, 0; 6, 0, 2], @sin);\n%! assert (a, [0.9093, 0, 0; -1.6646, 0.9093, 0; -2.4969, 0, 0.9093], 3e-5);\n\n## Test output format [F, exitflag]\n%!test\n%! [F, exitflag] = funm ([1 2;3 4], @sin);\n%! assert (F, [-0.4656 -0.1484;-0.2226 -0.6882], 4e-5);\n%! assert (exitflag, 0);\n\n## Test output format [F, exitflag, output]\n%!test\n%! [F, exitflag, output] = funm ([1 2;3 4], @cos);\n%! assert (F, [0.8554 -0.1109;-0.1663 0.6891], 3e-5);\n%! assert (exitflag, 0);\n%! assert (isstruct (output));\n%! assert (isfield (output, \"terms\"));\n%! assert (isfield (output, \"ind\"));\n%! assert (isfield (output, \"ord\"));\n%! assert (isfield (output, \"T\"));\n\n## Test that sin/cos via funm matches expm approach\n%!test\n%! X = [1 2;3 4];\n%! S = funm (X, @sin);\n%! C = funm (X, @cos);\n%! E = expm (i*X);\n%! assert (S, imag (E), 4*eps);\n%! assert (C, real (E), 4*eps);\n%! I = eye (size (X));\n%! assert (S*S + C*C, I, 5*eps);\n\n## Test input/output class handling\n\n%!test\n%! ## Single precision input should return single precision output\n%! A = single (magic (5));\n%! F = funm (A, @exp);\n%! assert (isa (F, \"single\"));\n\n%!test\n%! ## Double precision input should return double precision output\n%! A = magic (5);\n%! F = funm (A, @sin);\n%! assert (isa (F, \"double\"));\n\n%!test\n%! ## Single precision result should be accurate\n%! A = single (magic (4));\n%! F_single = funm (A, @exp);\n%! F_double = funm (double (A), @exp);\n%! ## Should match within single precision tolerance\n%! assert (F_single, single (F_double), eps (\"single\"));\n\n%!test\n%! ## Integer input should return double output\n%! A = uint8 (magic (4));\n%! F = funm (A, @exp);\n%! assert (isa (F, \"double\"));\n%! ## Result should match double computation\n%! F_ref = funm (double (A), @exp);\n%! assert (F, F_ref, eps);\n\n%!test\n%! ## Int32 input should return double output\n%! A = int32 (magic (3));\n%! F = funm (A, @sin);\n%! assert (isa (F, \"double\"));\n\n%!test\n%! ## Single complex should remain single\n%! A = single (complex (randn (5), randn (5)));\n%! F = funm (A, @exp);\n%! assert (isa (F, \"single\"));\n\n%!test\n%! ## Output structure T field should match input precision (single)\n%! A = single (magic (4));\n%! [F, exitflag, output] = funm (A, @exp);\n%! assert (isa (output.T, \"single\"));\n\n%!test\n%! ## Output structure T field should match input precision (double)\n%! A = magic (4);\n%! [F, exitflag, output] = funm (A, @exp);\n%! assert (isa (output.T, \"double\"));\n\n## Additional edge cases\n\n%!test\n%! ## Empty matrix\n%! A = [];\n%! F = funm (A, @exp);\n%! assert (F, []);\n\n%!test\n%! ## 1x1 matrix (scalar)\n%! A = 2;\n%! F = funm (A, @exp);\n%! assert (F, exp (2), eps);\n\n%!test\n%! ## 1x1 single precision\n%! A = single (2);\n%! F = funm (A, @exp);\n%! assert (isa (F, \"single\"));\n%! assert (F, single (exp (2)), eps (\"single\"));\n\n%!test\n%! ## Diagonal matrix (already upper triangular)\n%! A = diag ([1, 2, 3, 4, 5]);\n%! F = funm (A, @exp);\n%! assert (diag (F), exp ([1; 2; 3; 4; 5]), eps);\n\n%!test\n%! ## Diagonal single precision\n%! A = single (diag ([1, 2, 3]));\n%! F = funm (A, @sin);\n%! assert (isa (F, \"single\"));\n%! assert (diag (F), single (sin ([1; 2; 3])), eps (\"single\"));\n\n%!test\n%! ## Test sylvester code path: matrix with clustered eigenvalues\n%! D = diag ([1, 1.05, 3, 3.05]);\n%! [Q, ~] = qr (randn (4));\n%! A = Q * D * Q';\n%! F = funm (A, @exp);\n%! assert (F, expm (A), 1e-10);\n\n## Test input validation\n%!error <Invalid call> funm ()\n%!error <Invalid call> funm (eye (3))\n%!error <A must be a numeric square matrix> funm (\"not a matrix\", @exp)\n%!error <A must be a numeric square matrix> funm ({1, 2; 3, 4}, @exp)\n%!error <A must be a numeric square matrix> funm (ones (5, 2), @exp)\n%!error <A must be a numeric square matrix> funm ([1 2 3; 0 4 5], @exp)\n%!error <FUN must be a function handle or function name> funm (eye (3), 123)\n%!error <FUN must be a function handle or function name> funm (eye (3), [1 2 3])\n## Test options struct entries\n## Parsing follows mostly the same algorithm so just sample a few cases.\n%!error <OPTIONS must be a .* struct>\n%! funm (eye (3), @exp, \"Not a struct\");\n%!error <OPTIONS must be a scalar struct>\n%! funm (eye (3), @exp, struct (\"Display\", {0; 1}));\n%!error <TolBlk must be a positive scalar>\n%! funm (eye (3), @exp, struct (\"TolBlk\", \"a\"));\n%!error <TolTay must be a positive scalar>\n%! funm (eye (3), @exp, struct (\"TolTay\", [1, 2]));\n%!error <MaxTerms must be a positive integer>\n%! funm (eye (3), @exp, struct (\"MaxTerms\", -1));\n%!error <Ord must be a numeric or logical vector>\n%! funm (eye (3), @exp, struct (\"Ord\", 1));\n%!error <Ord must be a numeric or logical vector>\n%! funm (eye (3), @exp, struct (\"Ord\", \"A\"));\n%!error <Ord must be a numeric or logical vector>\n%! funm (eye (3), @exp, struct (\"Ord\", { {\"a\", \"1\"} }));\n%!error <Ord must be a numeric or logical vector>\n%! funm (eye (3), @exp, struct (\"Ord\", [true false true false]));\n%!error <invalid string value specified>\n%! funm (eye (3), @exp, struct (\"Display\", \"Hello!\"));\n%!error <string or scalar value .= 0>\n%! funm (eye (3), @exp, struct (\"Display\", -1));\n%!error <string or scalar value>\n%! funm (eye (3), @exp, struct (\"Display\", [0 1]));\n%!error <string or scalar value>\n%! funm (eye (3), @exp, struct (\"Display\", { {0 1} }));\n"
  },
  {
    "path": "scripts/linear-algebra/gls.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{beta}, @var{v}, @var{r}] =} gls (@var{y}, @var{x}, @var{o})\n## Generalized least squares (GLS) model.\n##\n## Perform a generalized least squares estimation for the multivariate model\n## @tex\n## $@var{y} = @var{x}\\,@var{b} + @var{e}$\n## @end tex\n## @ifnottex\n## @w{@math{@var{y} = @var{x}*@var{B} + @var{E}}}\n## @end ifnottex\n## where\n## @tex\n## $@var{y}$ is a $t \\times p$ matrix, $@var{x}$ is a $t \\times k$ matrix,\n## $@var{b}$ is a $k \\times p$ matrix and $@var{e}$ is a $t \\times p$ matrix.\n## @end tex\n## @ifnottex\n## @var{y} is a @math{t}-by-@math{p} matrix, @var{x} is a\n## @math{t}-by-@math{k} matrix, @var{b} is a @math{k}-by-@math{p} matrix\n## and @var{e} is a @math{t}-by-@math{p} matrix.\n## @end ifnottex\n##\n## @noindent\n## Each row of @var{y} is a @math{p}-variate observation in which each column\n## represents a variable.  Likewise, the rows of @var{x} represent\n## @math{k}-variate observations or possibly designed values.  Furthermore,\n## the collection of observations @var{x} must be of adequate rank, @math{k},\n## otherwise @var{b} cannot be uniquely estimated.\n##\n## The observation errors, @var{e}, are assumed to originate from an\n## underlying @math{p}-variate distribution with zero mean but possibly\n## heteroscedastic observations.  That is, in general,\n## @tex\n## $\\bar{@var{e}} = 0$ and cov(vec(@var{e})) = $s^2@var{o}$\n## @end tex\n## @ifnottex\n## @code{@math{mean (@var{e}) = 0}} and\n## @code{@math{cov (vec (@var{e})) = (@math{s}^2)*@var{o}}}\n## @end ifnottex\n## in which @math{s} is a scalar and @var{o} is a\n## @tex\n## @math{t \\, p \\times t \\, p}\n## @end tex\n## @ifnottex\n## @math{t*p}-by-@math{t*p}\n## @end ifnottex\n## matrix.\n##\n## The return values @var{beta}, @var{v}, and @var{r} are\n## defined as follows.\n##\n## @table @var\n## @item beta\n## The GLS estimator for matrix @var{b}.\n##\n## @item v\n## The GLS estimator for scalar @math{s^2}.\n##\n## @item r\n## The matrix of GLS residuals, @math{@var{r} = @var{y} - @var{x}*@var{beta}}.\n## @end table\n## @seealso{ols}\n## @end deftypefn\n\nfunction [beta, v, r] = gls (y, x, o)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) && isnumeric (y) && isnumeric (o)))\n    error (\"gls: X, Y, and O must be numeric matrices or vectors\");\n  endif\n\n  if (ndims (x) != 2 || ndims (y) != 2 || ndims (o) != 2)\n    error (\"gls: X, Y and O must be 2-D matrices or vectors\");\n  endif\n\n  [rx, cx] = size (x);\n  [ry, cy] = size (y);\n  [ro, co] = size (o);\n  if (rx != ry)\n    error (\"gls: number of rows of X and Y must be equal\");\n  endif\n  if (! issquare (o) || ro != ry*cy)\n    error (\"gls: matrix O must be square matrix with rows = rows (Y) * cols (Y)\");\n  endif\n\n  if (isinteger (x))\n    x = double (x);\n  endif\n  if (isinteger (y))\n    y = double (y);\n  endif\n  if (isinteger (o))\n    o = double (o);\n  endif\n\n  ## Start of algorithm\n  o ^= -1/2;\n  z = kron (eye (cy), x);\n  z = o * z;\n  y1 = o * reshape (y, ry*cy, 1);\n  u = z' * z;\n  r = rank (u);\n\n  if (r == cx*cy)\n    b = u \\ (z' * y1);\n  else\n    b = z \\ y1;\n  endif\n\n  beta = reshape (b, cx, cy);\n\n  if (nargout > 1)\n    r = y - x * beta;\n    v = (reshape (r, ry*cy, 1))' * (o^2) * reshape (r, ry*cy, 1) / (rx*cy - r);\n  endif\n\nendfunction\n\n%!demo\n%! ## Filip data from NIST StRD - Polynomial Regression (degree 10)\n%! ## https://www.itl.nist.gov/div898/strd/lls/data/Filip.shtml\n%! xy = [0.8116   -6.860120914;  0.9072   -4.324130045\n%!       0.9052   -4.358625055;  0.9039   -4.358426747\n%!       0.8053   -6.955852379;  0.8377   -6.661145254\n%!       0.8667   -6.355462942;  0.8809   -6.118102026\n%!       0.7975   -7.115148017;  0.8162   -6.815308569\n%!       0.8515   -6.519993057;  0.8766   -6.204119983\n%!       0.8885   -5.853871964;  0.8859   -6.109523091\n%!       0.8959   -5.79832982;   0.8913   -5.482672118\n%!       0.8959   -5.171791386;  0.8971   -4.851705903\n%!       0.9021   -4.517126416;  0.909    -4.143573228\n%!       0.9139   -3.709075441;  0.9199   -3.499489089\n%!       0.8692   -6.300769497;  0.8872   -5.953504836\n%!       0.89     -5.642065153;  0.891    -5.031376979\n%!       0.8977   -4.680685696;  0.9035   -4.329846955\n%!       0.9078   -3.928486195;  0.7675   -8.56735134\n%!       0.7705   -8.363211311;  0.7713   -8.107682739\n%!       0.7736   -7.823908741;  0.7775   -7.522878745\n%!       0.7841   -7.218819279;  0.7971   -6.920818754\n%!       0.8329   -6.628932138;  0.8641   -6.323946875\n%!       0.8804   -5.991399828;  0.7668   -8.781464495\n%!       0.7633   -8.663140179;  0.7678   -8.473531488\n%!       0.7697   -8.247337057;  0.77     -7.971428747\n%!       0.7749   -7.676129393;  0.7796   -7.352812702\n%!       0.7897   -7.072065318;  0.8131   -6.774174009\n%!       0.8498   -6.478861916;  0.8741   -6.159517513\n%!       0.8061   -6.835647144;  0.846    -6.53165267\n%!       0.8751   -6.224098421;  0.8856   -5.910094889\n%!       0.8919   -5.598599459;  0.8934   -5.290645224\n%!       0.894    -4.974284616;  0.8957   -4.64454848\n%!       0.9047   -4.290560426;  0.9129   -3.885055584\n%!       0.9209   -3.408378962;  0.9219   -3.13200249\n%!       0.7739   -8.726767166;  0.7681   -8.66695597\n%!       0.7665   -8.511026475;  0.7703   -8.165388579\n%!       0.7702   -7.886056648;  0.7761   -7.588043762\n%!       0.7809   -7.283412422;  0.7961   -6.995678626\n%!       0.8253   -6.691862621;  0.8602   -6.392544977\n%!       0.8809   -6.067374056;  0.8301   -6.684029655\n%!       0.8664   -6.378719832;  0.8834   -6.065855188\n%!       0.8898   -5.752272167;  0.8964   -5.132414673\n%!       0.8963   -4.811352704;  0.9074   -4.098269308\n%!       0.9119   -3.66174277;   0.9228   -3.2644011];\n%! %! ## Certified values (NIST)\n%! b_cert = [-1467.48961422980; -2772.17959193342; -2316.37108160893;\n%!           -1127.97394098372; -354.478233703349; -75.1242017393757;\n%!           -10.8753180355343; -1.06221498588947; -0.670191154593408E-01;\n%!           -0.246781078275479E-02; -0.402962525080404E-04];\n%! y = xy(:,1);\n%! x = xy(:,2);\n%! ## Fit degree-10 polynomial using GLS\n%! X = vander (x, 11);\n%! o = eye (numel (x)); # identity covariance matrix\n%! [b, sigma, r] = gls (y, X, o);\n%! clf;\n%! subplot (3, 1, [1 2]);\n%! plot (x, y, \"bo\", \"markerfacecolor\", \"b\", \"markersize\", 2);\n%! hold on;\n%! x_fit = linspace (min (x), max (x), 200);\n%! plot (x_fit, polyval (b, x_fit), \"r-\", \"linewidth\", 1);\n%! hold off;\n%! grid on;\n%! ylabel (\"y\");\n%! title (\"NIST Filip Dataset: Degree-10 Polynomial Fit\");\n%! legend (\"Data\", \"GLS Fit\", \"location\", \"northwest\");\n%! subplot (3, 1, 3);\n%! stem (x, r, \"filled\", \"markersize\", 2);\n%! grid on;\n%! xlabel (\"x\");\n%! ylabel (\"Residual\");\n%! title (sprintf (\"Residuals (RMS = %.2e)\", sqrt (mean (r.^2))));\n%! assert (flip (b), b_cert, -2e-6);\n\n%!test\n%! x = [1:5]';\n%! y = 3*x + 2;\n%! x = [x, ones(5,1)];\n%! o = diag (ones (5,1));\n%! assert (gls (y,x,o), [3; 2], 50*eps);\n\n## Test input validation\n%!error <Invalid call> gls ()\n%!error <Invalid call> gls (1)\n%!error <Invalid call> gls (1, 2)\n%!error gls ([true, true], [1, 2], ones (2))\n%!error gls ([1, 2], [true, true], ones (2))\n%!error gls ([1, 2], [1, 2], true (2))\n%!error gls (ones (2,2,2), ones (2,2), ones (4,4))\n%!error gls (ones (2,2), ones (2,2,2), ones (4,4))\n%!error gls (ones (2,2), ones (2,2), ones (4,4,4))\n%!error gls (ones (1,2), ones (2,2), ones (2,2))\n%!error gls (ones (2,2), ones (2,2), ones (2,2))\n"
  },
  {
    "path": "scripts/linear-algebra/housh.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{housv}, @var{beta}, @var{zer}] =} housh (@var{x}, @var{j}, @var{z})\n## Compute Householder reflection vector @var{housv} to reflect @var{x} to be\n## the j-th column of identity, i.e.,\n##\n## @example\n## @group\n## (I - beta*housv*housv')x =  norm (x)*e(j) if x(j) < 0,\n## (I - beta*housv*housv')x = -norm (x)*e(j) if x(j) >= 0\n## @end group\n## @end example\n##\n## @noindent\n## Inputs\n##\n## @table @var\n## @item x\n## vector\n##\n## @item j\n## index into vector\n##\n## @item z\n## threshold for zero  (usually should be the number 0)\n## @end table\n##\n## @noindent\n## Outputs (see @nospell{Golub and Van Loan}):\n##\n## @table @var\n## @item beta\n## If beta = 0, then no reflection need be applied (@nospell{zer} set to 0)\n##\n## @item housv\n## householder vector\n## @end table\n## @end deftypefn\n\nfunction [housv, beta, zer] = housh (x, j, z)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  ## Check for valid inputs.\n  if (! isvector (x) && ! isscalar (x))\n    error (\"housh: first input must be a vector\");\n  elseif (! isscalar (j))\n    error (\"housh: second argument must be an integer scalar\");\n  else\n    housv = x;\n    m = max (abs (housv));\n    if (m != 0.0)\n      housv /= m;\n      alpha = norm (housv);\n      if (alpha > z)\n        beta = 1.0 / (alpha * (alpha + abs (housv(j))));\n        sg = sign (housv(j));\n        if (sg == 0)\n          sg = 1;\n        endif\n        housv(j) = housv(j) + alpha*sg;\n      else\n        beta = 0.0;\n      endif\n    else\n      beta = 0.0;\n    endif\n    zer = (beta == 0);\n  endif\n\nendfunction\n\n\n%!test\n%! x = [1 2 3]';\n%! j = 3;\n%! [hv, b, z] = housh (x, j, 0);\n%! r = (eye (3) - b*hv*hv') * x;\n%! d = - norm (x) * [0 0 1]';\n%! assert (r, d, 2e-8);\n%! assert (z, 0, 2e-8);\n\n%!test\n%! x = [7 -3 1]';\n%! j = 2;\n%! [hv, b, z] = housh (x, j, 0);\n%! r = (eye (3) - b*hv*hv') * x;\n%! d = norm (x) * [0 1 0]';\n%! assert (r, d, 2e-8);\n%! assert (z, 0, 2e-8);\n\n%!test\n%! x = [1 0 0]';\n%! j = 1;\n%! [hv, b, z] = housh (x, j, 10);\n%! r = (eye (3) - b*hv*hv') * x;\n%! d = norm (x) * [1 0 0]';\n%! assert (r, d, 2e-8);\n%! assert (z, 1, 2e-8);\n\n%!test\n%! x = [5 0 4 1]';\n%! j = 2;\n%! [hv, b, z] = housh (x, j, 0);\n%! r = (eye (4) - b*hv*hv') * x;\n%! d = - norm (x) * [0 1 0 0]';\n%! assert (r, d, 2e-8);\n%! assert (z, 0, 2e-8);\n\n%!error <Invalid call> housh ()\n%!error <Invalid call> housh (1)\n%!error <Invalid call> housh (1,2)\n"
  },
  {
    "path": "scripts/linear-algebra/isbanded.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isbanded (@var{A}, @var{lower}, @var{upper})\n## Return true if @var{A} is a numeric matrix with entries confined between\n## @var{lower} diagonals below the main diagonal and @var{upper} diagonals\n## above the main diagonal.\n##\n## @var{lower} and @var{upper} must be non-negative integers.\n## @seealso{isdiag, istril, istriu, bandwidth}\n## @end deftypefn\n\nfunction tf = isbanded (A, lower, upper)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (! isreal (lower) || ! isreal (upper) || lower < 0 || upper < 0)\n    error (\"isbanded: LOWER and UPPER must be non-negative integers\");\n  endif\n\n  if (isempty (A))\n    tf = [];\n  else\n    tf = (isnumeric (A) || islogical (A)) && ndims (A) == 2;\n    if (tf)\n      [i, j] = find (A);\n      pupp = j >= i;\n      tf = all (j(pupp) - i(pupp) <= upper);\n      if (tf)\n        plow = i >= j;\n        tf = all (i(plow) - j(plow) <= lower);\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!assert (! isbanded (\"string\", 0, 0))\n%!assert (! isbanded (zeros (2,2,2), 0, 0))\n%!assert (isbanded ([], 0, 0), [])\n%!assert (isbanded (1,0,0))\n%!assert (isbanded (1,10,10))\n\n%!assert (isbanded ([1, 1],1,1))\n%!assert (isbanded ([1; 1],1,1))\n%!assert (isbanded (eye (10),0,0))\n%!assert (isbanded (eye (10),1,1))\n%!assert (isbanded (i*eye (10),1,1))\n%!assert (isbanded (logical (eye (10)),1,1))\n\n%! A = [2 3 0 0 0; 1 2 3 0 0; 0 1 2 3 0; 0 0 1 2 3; 0 0 0 1 2];\n%! assert (isbanded (A,1,1));\n%! assert (! isbanded (A,0,1));\n%! assert (! isbanded (A,1,0));\n\n## Test input validation\n%!error <Invalid call> isbanded ()\n%!error <Invalid call> isbanded (1)\n%!error <Invalid call> isbanded (1,2)\n%!error <LOWER and UPPER must be non-negative> isbanded (1, -1, 1)\n%!error <LOWER and UPPER must be non-negative> isbanded (1, 1, -1)\n%!error <LOWER and UPPER must be non-negative> isbanded (1, {1}, 1)\n%!error <LOWER and UPPER must be non-negative> isbanded (1, 1, {1})\n"
  },
  {
    "path": "scripts/linear-algebra/isdefinite.m",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} isdefinite (@var{A})\n## @deftypefnx {} {@var{tf} =} isdefinite (@var{A}, @var{tol})\n## Return true if @var{A} is symmetric positive definite numeric matrix within\n## the tolerance specified by @var{tol}.\n##\n## If @var{tol} is omitted, use a tolerance of\n## @code{100 * eps * norm (@var{A}, \"fro\")}.\n##\n## Background: A positive definite matrix has eigenvalues which are all\n## greater than zero.  A positive semi-definite matrix has eigenvalues which\n## are all greater than or equal to zero.  The matrix @var{A} is very likely to\n## be positive semi-definite if the following two conditions hold for a\n## suitably small tolerance @var{tol}.\n##\n## @example\n## @group\n## isdefinite (@var{A}) @xresult{} 0\n## isdefinite (@var{A} + 5*@var{tol}, @var{tol}) @xresult{} 1\n## @end group\n## @end example\n## @seealso{issymmetric, ishermitian}\n## @end deftypefn\n\nfunction tf = isdefinite (A, tol)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Validate inputs\n  tf = false;\n  if (! isnumeric (A))\n    return;\n  endif\n\n  if (! isfloat (A))\n    A = double (A);\n  endif\n\n  if (nargin == 1)\n    tol = 100 * eps (class (A)) * norm (A, \"fro\");\n  elseif (! (isnumeric (tol) && isscalar (tol) && tol >= 0))\n    error (\"isdefinite: TOL must be a scalar >= 0\");\n  endif\n\n  if (! ishermitian (A, tol))\n    return;\n  endif\n\n  e = tol * eye (rows (A));\n  [~, p] = chol (A - e);\n  if (p == 0)\n    tf = true;\n  endif\n\nendfunction\n\n\n%!test\n%! A = [-1, 0; 0, -1];\n%! assert (isdefinite (A), false);\n\n%!test\n%! A = [1, 0; 0, 1];\n%! assert (isdefinite (A), true);\n\n%!test\n%! A = [2, -1,  0; -1, 2, -1; 0, -1, 2];\n%! assert (isdefinite (A), true);\n\n## Test for positive semi-definite matrix\n%!test\n%! A = [1, 0; 0, 0];\n%! assert (isdefinite (A), false);\n%! tol = 100*eps;\n%! assert (isdefinite (A+5*tol, tol), true);\n\n%!assert (! isdefinite (magic (3)))\n\n%!error <Invalid call> isdefinite ()\n%!error <TOL must be a scalar .= 0> isdefinite (1, {1})\n%!error <TOL must be a scalar .= 0> isdefinite (1, [1 1])\n%!error <TOL must be a scalar .= 0> isdefinite (1, -1)\n"
  },
  {
    "path": "scripts/linear-algebra/isdiag.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isdiag (@var{A})\n## Return true if @var{A} is a diagonal numeric matrix which is defined as a\n## 2-D array where all elements above and below the main diagonal are zero.\n## @seealso{isbanded, istril, istriu, diag, bandwidth}\n## @end deftypefn\n\nfunction tf = isdiag (A)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (strfind (typeinfo (A), \"diagonal matrix\"))\n    tf = true;\n  elseif ((isnumeric (A) || islogical (A)) && ndims (A) == 2)\n    [i, j] = find (A);\n    tf = all (i == j);\n  else\n    tf = false;\n  endif\n\nendfunction\n\n\n%!assert (isdiag (\"string\"), false)\n%!assert (isdiag (zeros (2,2,2)), false)\n%!assert (isdiag (zeros (2)))\n%!assert (isdiag ([]))\n%!assert (isdiag (1))\n%!assert (isdiag ([1, 1]), false)\n%!assert (isdiag ([1; 1]), false)\n%!assert (isdiag (eye (10)))\n%!assert (isdiag (single (eye (10))))\n%!assert (isdiag (logical (eye (10))))\n%!assert (isdiag (speye (1e2)))\n%!assert (isdiag (diag (1:10)))\n\n## Test input validation\n%!error <Invalid call> isdiag ()\n"
  },
  {
    "path": "scripts/linear-algebra/ishermitian.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} ishermitian (@var{A})\n## @deftypefnx {} {@var{tf} =} ishermitian (@var{A}, @var{tol})\n## @deftypefnx {} {@var{tf} =} ishermitian (@var{A}, @qcode{\"skew\"})\n## @deftypefnx {} {@var{tf} =} ishermitian (@var{A}, @qcode{\"skew\"}, @var{tol})\n## Return true if @var{A} is a Hermitian or skew-Hermitian numeric matrix\n## within the tolerance specified by @var{tol}.\n##\n## The default tolerance is zero (uses faster code).\n##\n## The type of symmetry to check may be specified with the additional input\n## @qcode{\"nonskew\"} (default) for regular Hermitian or @qcode{\"skew\"} for\n## skew-Hermitian.\n##\n## Background: A matrix is Hermitian if the complex conjugate transpose of the\n## matrix is equal to the original matrix: @w{@tcode{@var{A} == @var{A}'}}.  If\n## a tolerance is given then the calculation is\n## @code{norm (@var{A} - @var{A}', Inf) / norm (@var{A}, Inf) < @var{tol}}.\n##\n## A matrix is skew-Hermitian if the complex conjugate transpose of the matrix\n## is equal to the negative of the original matrix:\n## @w{@tcode{@var{A} == -@var{A}'}}.  If a\n## tolerance is given then the calculation is\n## @code{norm (@var{A} + @var{A}', Inf) / norm (@var{A}, Inf) < @var{tol}}.\n## @seealso{issymmetric, isdefinite}\n## @end deftypefn\n\nfunction tf = ishermitian (A, skewopt = \"nonskew\", tol = 0)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 2)\n    ## Decode whether second argument is skewopt or tol\n    if (isnumeric (skewopt))\n      tol = skewopt;\n      skewopt = \"nonskew\";\n    elseif (! ischar (skewopt))\n      error (\"ishermitian: second argument must be a non-negative scalar TOL, or one of the strings: 'skew' / 'nonskew'\");\n    endif\n  endif\n\n  ## Validate inputs\n  tf = (isnumeric (A) || islogical (A)) && issquare (A);\n  if (! tf)\n    return;\n  endif\n\n  if (! (strcmp (skewopt, \"skew\") || strcmp (skewopt, \"nonskew\")))\n    error (\"ishermitian: SKEWOPT must be 'skew' or 'nonskew'\");\n  endif\n\n  if (! (isnumeric (tol) && isscalar (tol) && tol >= 0))\n    error (\"ishermitian: TOL must be a scalar >= 0\");\n  endif\n\n  ## Calculate Hermitian-ness\n  if (strcmp (skewopt, \"nonskew\"))\n    if (tol == 0)\n      ## check for exact symmetry\n      tf = full (! any ((A != A')(:)));\n    else\n      if (islogical (A))\n        ## Hack to allow norm to work.  Choose single to minimize memory.\n        A = single (A);\n      endif\n      norm_x = norm (A, Inf);\n      tf = norm_x == 0 || norm (A - A', Inf) / norm_x <= tol;\n    endif\n  else\n    ## skew-Hermitian\n    if (tol == 0)\n      tf = full (! any ((A != -A')(:)));\n    else\n      if (islogical (A))\n        ## Hack to allow norm to work.  Choose single to minimize memory.\n        A = single (A);\n      endif\n      norm_x = norm (A, Inf);\n      tf = norm_x == 0 || norm (A + A', Inf) / norm_x <= tol;\n    endif\n  endif\n\nendfunction\n\n\n%!assert (ishermitian (1))\n%!assert (! ishermitian ([1, 2]))\n%!assert (ishermitian ([]))\n%!assert (ishermitian ([1, 2; 2, 1]))\n%!assert (ishermitian ([1, 2.1; 2, 1.1], 0.2))\n%!assert (ishermitian ([1, -2i; 2i, 1]))\n%!assert (ishermitian (speye (100)), true)  # Return full logical value.\n%!assert (ishermitian (logical (eye (2))))\n%!assert (! ishermitian (logical ([1 1; 0 1])))\n%!assert (ishermitian (logical ([1 1; 0 1]), 0.5))\n%!assert (ishermitian ([0, 2i; 2i, 0], \"skew\"))\n%!assert (! ishermitian ([0, 2; -2, eps], \"skew\"))\n%!assert (ishermitian ([0, 2; -2, eps], \"skew\", eps))\n\n%!assert (! (ishermitian (\"test\")))\n%!assert (! (ishermitian (\"t\")))\n%!assert (! (ishermitian ([\"te\"; \"et\"])))\n%!assert (! ishermitian ({1}))\n%!test\n%! s.a = 1;\n%! assert (! ishermitian (s));\n\n## Test input validation\n%!error <Invalid call> ishermitian ()\n%!error <second argument must be> ishermitian (1, {\"skew\"})\n%!error <SKEWOPT must be 'skew' or 'nonskew'> ishermitian (1, \"foobar\")\n%!error <SKEWOPT must be 'skew' or 'nonskew'> ishermitian (1, \"foobar\")\n%!error <TOL must be a scalar .= 0> ishermitian (1, \"skew\", {1})\n%!error <TOL must be a scalar .= 0> ishermitian (1, \"skew\", [1 1])\n%!error <TOL must be a scalar .= 0> ishermitian (1, -1)\n"
  },
  {
    "path": "scripts/linear-algebra/issymmetric.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} issymmetric (@var{A})\n## @deftypefnx {} {@var{tf} =} issymmetric (@var{A}, @var{tol})\n## @deftypefnx {} {@var{tf} =} issymmetric (@var{A}, @qcode{\"skew\"})\n## @deftypefnx {} {@var{tf} =} issymmetric (@var{A}, @qcode{\"skew\"}, @var{tol})\n## Return true if @var{A} is a symmetric or skew-symmetric numeric matrix\n## within the tolerance specified by @var{tol}.\n##\n## The default tolerance is zero (uses faster code).\n##\n## The type of symmetry to check may be specified with the additional input\n## @qcode{\"nonskew\"} (default) for regular symmetry or @qcode{\"skew\"} for\n## skew-symmetry.\n##\n## Background: A matrix is symmetric if the transpose of the matrix is equal\n## to the original matrix: @w{@tcode{@var{A} == @var{A}.'}}.  If a tolerance\n## is given then symmetry is determined by\n## @code{norm (@var{A} - @var{A}.', Inf) / norm (@var{A}, Inf) < @var{tol}}.\n##\n## A matrix is skew-symmetric if the transpose of the matrix is equal to the\n## negative of the original matrix: @w{@tcode{@var{A} == -@var{A}.'}}.  If a\n## tolerance is given then skew-symmetry is determined by\n## @code{norm (@var{A} + @var{A}.', Inf) / norm (@var{A}, Inf) < @var{tol}}.\n## @seealso{ishermitian, isdefinite}\n## @end deftypefn\n\nfunction tf = issymmetric (A, skewopt = \"nonskew\", tol = 0)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 2)\n    ## Decode whether second argument is skewopt or tol\n    if (isnumeric (skewopt))\n      tol = skewopt;\n      skewopt = \"nonskew\";\n    elseif (! ischar (skewopt))\n      error (\"issymmetric: second argument must be a non-negative scalar TOL, or one of the strings: 'skew' / 'nonskew'\");\n    endif\n  endif\n\n  ## Validate inputs\n  if (! (isnumeric (A) || islogical (A) || ischar (A)))\n    error (\"issymmetric: A must be a numeric, logical, or character matrix\");\n  endif\n\n  if (! (strcmp (skewopt, \"skew\") || strcmp (skewopt, \"nonskew\")))\n    error (\"issymmetric: SKEWOPT must be 'skew' or 'nonskew'\");\n  endif\n\n  if (! (isnumeric (tol) && isscalar (tol) && tol >= 0))\n    error (\"issymmetric: TOL must be a scalar >= 0\");\n  endif\n\n  if (! issquare (A))\n    tf = false;\n    return;\n  endif\n\n  ## Calculate symmetry\n  if (strcmp (skewopt, \"nonskew\"))\n    if (tol == 0)\n      ## check for exact symmetry\n      tf = full (! any ((A != A.')(:)));\n    else\n      if (! isnumeric (A))\n        ## Hack to allow norm to work.  Choose single to minimize memory.\n        A = single (A);\n      endif\n      norm_x = norm (A, Inf);\n      tf = norm_x == 0 || norm (A - A.', Inf) / norm_x <= tol;\n    endif\n  else\n    ## skew symmetry\n    if (tol == 0)\n      tf = full (! any ((A != -A.')(:)));\n    else\n      if (! isnumeric (A))\n        ## Hack to allow norm to work.  Choose single to minimize memory.\n        A = single (A);\n      endif\n      norm_x = norm (A, Inf);\n      tf = norm_x == 0 || norm (A + A.', Inf) / norm_x <= tol;\n    endif\n  endif\n\nendfunction\n\n\n%!assert (issymmetric (1))\n%!assert (! issymmetric ([1, 2]))\n%!assert (issymmetric ([]))\n%!assert (issymmetric ([1, 2; 2, 1]))\n%!assert (issymmetric ([1, 2.1; 2, 1.1], 0.2))\n%!assert (issymmetric ([1, 2i; 2i, 1]))\n%!assert (issymmetric (speye (100)), true)  # Return full logical value.\n%!assert (! issymmetric ([0, 2; -2, 0], \"nonskew\"))\n%!assert (issymmetric ([0, 2; -2, 0], \"skew\"))\n%!assert (! issymmetric ([0, 2; -2, eps], \"skew\"))\n%!assert (issymmetric ([0, 2; -2, eps], \"skew\", eps))\n%!assert (issymmetric (logical (eye (2))))\n%!assert (! issymmetric (logical ([1 1; 0 1])))\n%!assert (issymmetric (logical ([1 1; 0 1]), 0.5))\n%!assert (! issymmetric (\"test\"))\n%!assert (issymmetric (\"t\"))\n%!assert (issymmetric ([\"te\"; \"et\"]))\n\n## Test input validation\n%!error <Invalid call> issymmetric ()\n%!error <second argument must be> issymmetric (1, {\"skew\"})\n%!error <A must be a numeric,.* matrix> issymmetric ({1})\n%!error <SKEWOPT must be 'skew' or 'nonskew'> issymmetric (1, \"foobar\")\n%!error <TOL must be a scalar .= 0> issymmetric (1, \"skew\", {1})\n%!error <TOL must be a scalar .= 0> issymmetric (1, \"skew\", [1 1])\n%!error <TOL must be a scalar .= 0> issymmetric (1, -1)\n"
  },
  {
    "path": "scripts/linear-algebra/istril.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} istril (@var{A})\n## Return true if @var{A} is a lower triangular numeric matrix.\n##\n## A lower triangular matrix has nonzero entries only on the main diagonal and\n## below.\n## @seealso{istriu, isbanded, isdiag, tril, bandwidth}\n## @end deftypefn\n\nfunction tf = istril (A)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = (isnumeric (A) || islogical (A)) && ndims (A) == 2;\n  if (tf)\n    [i, j] = find (A);\n    tf = all (i >= j);\n  endif\n\nendfunction\n\n\n%!assert (! istril (\"string\"))\n%!assert (istril ([]))\n%!assert (! istril (zeros (2,2,2)))\n\n%!assert (istril (1))\n%!assert (! istril ([1, 1]))\n%!assert (istril ([1; 1]))\n%!assert (istril (eye (10)))\n%!assert (istril (speye (100)))\n\n%!assert (istril (tril (randn (10))))\n%!assert (! istril (randn (10)))\n\n## Test input validation\n%!error <Invalid call> istril ()\n"
  },
  {
    "path": "scripts/linear-algebra/istriu.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} istriu (@var{A})\n## Return true if @var{A} is an upper triangular numeric matrix.\n##\n## An upper triangular matrix has nonzero entries only on the main diagonal and\n## above.\n## @seealso{isdiag, isbanded, istril, triu, bandwidth}\n## @end deftypefn\n\nfunction tf = istriu (A)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = (isnumeric (A) || islogical (A)) && ndims (A) == 2;\n  if (tf)\n    [i, j] = find (A);\n    tf = all (i <= j);\n  endif\n\nendfunction\n\n\n%!assert (! istriu (\"string\"))\n%!assert (istriu ([]))\n%!assert (! istriu (zeros (2,2,2)))\n\n%!assert (istriu (1))\n%!assert (istriu ([1, 1]))\n%!assert (! istriu ([1; 1]))\n%!assert (istriu (eye (10)))\n%!assert (istriu (speye (100)))\n\n%!assert (istriu (triu (randn (10))))\n%!assert (! istriu (randn (10)))\n\n## Test input validation\n%!error <Invalid call> istriu ()\n"
  },
  {
    "path": "scripts/linear-algebra/krylov.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{u}, @var{h}, @var{nu}] =} krylov (@var{A}, @var{V}, @var{k}, @var{eps1}, @var{pflg})\n## Construct an orthogonal basis @var{u} of a block Krylov subspace.\n##\n## The block Krylov subspace has the following form:\n##\n## @example\n## [v a*v a^2*v @dots{} a^(k+1)*v]\n## @end example\n##\n## @noindent\n## The construction is made with Householder reflections to guard against loss\n## of orthogonality.\n##\n## If @var{V} is a vector, then @var{h} contains the Hessenberg matrix\n## such that @nospell{@tcode{a*u == u*h+rk*ek'}}, in which\n## @code{rk = a*u(:,k)-u*h(:,k)}, and @nospell{@tcode{ek'}} is the vector\n## @code{[0, 0, @dots{}, 1]} of length @var{k}.  Otherwise, @var{h} is\n## meaningless.\n##\n## If @var{V} is a vector and @var{k} is greater than @code{length (A) - 1},\n## then @var{h} contains the Hessenberg matrix such that @code{a*u == u*h}.\n##\n## The value of @var{nu} is the dimension of the span of the Krylov subspace\n## (based on @var{eps1}).\n##\n## If @var{b} is a vector and @var{k} is greater than @var{m-1}, then @var{h}\n## contains the Hessenberg decomposition of @var{A}.\n##\n## The optional parameter @var{eps1} is the threshold for zero.  The default\n## value is 1e-12.\n##\n## If the optional parameter @var{pflg} is nonzero, row pivoting is used to\n## improve numerical behavior.  The default value is 0.\n##\n## Reference: @nospell{A. Hodel, P. Misra}, \"Partial Pivoting in the\n## Computation of Krylov Subspaces of Large Sparse Systems\",\n## @cite{Proceedings of the 42nd IEEE Conference on Decision and Control},\n## December 2003.\n## @end deftypefn\n\nfunction [Uret, H, nu] = krylov (A, V, k, eps1, pflg)\n\n  if (isa (A, \"single\") || isa (V, \"single\"))\n    defeps = 1e-6;\n  else\n    defeps = 1e-12;\n  endif\n\n  if (nargin < 3)\n    print_usage ();\n  elseif (nargin < 5)\n    ## Default permutation flag.\n    pflg = 0;\n  endif\n\n  if (nargin < 4)\n    ## Default tolerance parameter.\n    eps1 = defeps;\n  endif\n\n  if (isempty (eps1))\n    eps1 = defeps;\n  endif\n\n  if (! issquare (A) || isempty (A))\n    error (\"krylov: A(%d x %d) must be a non-empty square matrix\", rows (A), columns (A));\n  endif\n  na = rows (A);\n\n  [m, kb] = size (V);\n  if (m != na)\n    error (\"krylov: A(%d x %d), V(%d x %d): argument dimensions do not match\",\n           na, na, m, kb);\n  endif\n\n  if (! isscalar (k))\n    error (\"krylov: K must be a scalar integer\");\n  endif\n\n  Vnrm = norm (V, Inf);\n\n  ## check for trivial solution.\n  if (Vnrm == 0)\n    Uret = [];\n    H = [];\n    nu = 0;\n    return;\n  endif\n\n  ## Identify trivial null space.\n  abm = max (abs ([A, V]'));\n  zidx = find (abm == 0);\n\n  ## Set up vector of pivot points.\n  pivot_vec = 1:na;\n\n  iter = 0;\n  alpha = [];\n  nh = 0;\n  while (length (alpha) < na) && (columns (V) > 0) && (iter < k)\n    iter += 1;\n\n    ## Get orthogonal basis of V.\n    jj = 1;\n    while (jj <= columns (V) && length (alpha) < na)\n      ## Index of next Householder reflection.\n      nu = length (alpha)+1;\n\n      short_pv = pivot_vec(nu:na);\n      q = V(:,jj);\n      short_q = q(short_pv);\n\n      if (norm (short_q) < eps1)\n        ## Insignificant column; delete.\n        nv = columns (V);\n        if (jj != nv)\n          [V(:,jj), V(:,nv)] = swap (V(:,jj), V(:,nv));\n          ## FIXME: H columns should be swapped too.\n          ##        Not done since Block Hessenberg structure is lost anyway.\n        endif\n        V = V(:,1:(nv-1));\n        ## One less reflection.\n        nu -= 1;\n      else\n        ## New householder reflection.\n        if (pflg)\n          ## Locate max magnitude element in short_q.\n          asq = abs (short_q);\n          maxv = max (asq);\n          maxidx = find (asq == maxv, 1);\n          pivot_idx = short_pv(maxidx);\n\n          ## See if need to change the pivot list.\n          if (pivot_idx != pivot_vec(nu))\n            swapidx = maxidx + (nu-1);\n            [pivot_vec(nu), pivot_vec(swapidx)] = ...\n                swap (pivot_vec(nu), pivot_vec(swapidx));\n          endif\n        endif\n\n        ## Isolate portion of vector for reflection.\n        idx = pivot_vec(nu:na);\n        jdx = pivot_vec(1:nu);\n\n        [hv, av, z] = housh (q(idx), 1, 0);\n        alpha(nu) = av;\n        U(idx,nu) = hv;\n\n        ## Reduce V per the reflection.\n        V(idx,:) = V(idx,:) - av*hv*(hv' * V(idx,:));\n        if (iter > 1)\n          ## FIXME: not done correctly for block case.\n          H(nu,nu-1) = V(pivot_vec(nu),jj);\n        endif\n\n        ## Advance to next column of V.\n        jj += 1;\n      endif\n    endwhile\n\n    ## Check for oversize V (due to full rank).\n    if ((columns (V) > na) && (length (alpha) == na))\n      ## Trim to size.\n      V = V(:,1:na);\n    elseif (columns (V) > na)\n      krylov_V = V;\n      krylov_na = na;\n      krylov_length_alpha = length (alpha);\n      error (\"krylov: this case should never happen; submit a bug report\");\n    endif\n\n    if (columns (V) > 0)\n      ## Construct next Q and multiply.\n      Q = zeros (size (V));\n      for kk = 1:columns (Q)\n        Q(pivot_vec(nu-columns (Q)+kk),kk) = 1;\n      endfor\n\n      ## Apply Householder reflections.\n      for ii = nu:-1:1\n        idx = pivot_vec(ii:na);\n        hv = U(idx,ii);\n        av = alpha(ii);\n        Q(idx,:) = Q(idx,:) - av*hv*(hv'*Q(idx,:));\n      endfor\n    endif\n\n    ## Multiply to get new vector.\n    V = A*Q;\n    ## Project off of previous vectors.\n    nu = length (alpha);\n    for i = 1:nu\n      hv = U(:,i);\n      av = alpha(i);\n      V -= av*hv*(hv'*V);\n      H(i,nu-columns (V)+(1:columns (V))) = V(pivot_vec(i),:);\n    endfor\n\n  endwhile\n\n  ## Back out complete U matrix.\n  ## back out U matrix.\n  j1 = columns (U);\n  for i = j1:-1:1\n    idx = pivot_vec(i:na);\n    hv = U(idx,i);\n    av = alpha(i);\n    U(:,i) = zeros (na, 1);\n    U(idx(1),i) = 1;\n    U(idx,i:j1) = U(idx,i:j1)-av*hv*(hv'*U(idx,i:j1));\n  endfor\n\n  nu = length (alpha);\n  Uret = U;\n  if (max (max (abs (Uret(zidx,:)))) > 0)\n    warning (\"krylov: trivial null space corrupted; set pflg = 1 or eps1 > %e\",\n             eps1);\n  endif\n\nendfunction\n\n\nfunction [a1, b1] = swap (a, b)\n\n  a1 = b;\n  b1 = a;\n\nendfunction\n"
  },
  {
    "path": "scripts/linear-algebra/linsolve.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} linsolve (@var{A}, @var{b})\n## @deftypefnx {} {@var{x} =} linsolve (@var{A}, @var{b}, @var{opts})\n## @deftypefnx {} {[@var{x}, @var{R}] =} linsolve (@dots{})\n## Solve the linear system @code{A*x = b}.\n##\n## With no options, this function is equivalent to the left division operator\n## @w{(@code{x = A \\ b})}@ or the matrix-left-divide function\n## @w{(@code{x = mldivide (A, b)})}.\n##\n## Octave ordinarily examines the properties of the matrix @var{A} and chooses\n## a solver that best matches the matrix.  By passing a structure @var{opts}\n## to @code{linsolve} you can inform Octave directly about the matrix @var{A}.\n## In this case Octave will skip the matrix examination and proceed directly\n## to solving the linear system.\n##\n## @strong{Warning:} If the matrix @var{A} does not have the properties listed\n## in the @var{opts} structure then the result will not be accurate AND no\n## warning will be given.  When in doubt, let Octave examine the matrix and\n## choose the appropriate solver as this step takes little time and the result\n## is cached so that it is only done once per linear system.\n##\n## Possible @var{opts} fields (set value to true/false):\n##\n## @table @asis\n## @item LT\n##   @var{A} is lower triangular\n##\n## @item UT\n##   @var{A} is upper triangular\n##\n## @item UHESS\n##   @var{A} is upper Hessenberg (currently makes no difference)\n##\n## @item SYM\n##   @var{A} is symmetric or complex Hermitian (currently makes no difference)\n##\n## @item POSDEF\n##   @var{A} is positive definite\n##\n## @item RECT\n##   @var{A} is general rectangular (currently makes no difference)\n##\n## @item TRANSA\n##   Solve @code{A'*x = b} if true rather than @code{A*x = b}\n## @end table\n##\n## The optional second output @var{R} is the inverse condition number of\n## @var{A} (zero if matrix is singular).\n## @seealso{mldivide, matrix_type, rcond}\n## @end deftypefn\n\nfunction [x, R] = linsolve (A, b, opts)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (A) && isnumeric (b)))\n    error (\"linsolve: A and B must be numeric\");\n  endif\n\n  trans_A = false;\n\n  ## Process any opts\n  if (nargin > 2)\n    if (! isstruct (opts))\n      error (\"linsolve: OPTS must be a structure\");\n    endif\n    if (isfield (opts, \"TRANSA\") && opts.TRANSA)\n      trans_A = true;\n    endif\n    if (isfield (opts, \"POSDEF\") && opts.POSDEF)\n      A = matrix_type (A, \"positive definite\");\n    endif\n    if (isfield (opts, \"LT\") && opts.LT)\n      A = matrix_type (A, \"lower\");\n    elseif (isfield (opts, \"UT\") && opts.UT)\n      A = matrix_type (A, \"upper\");\n    endif\n  endif\n\n  ## This way is faster as the transpose is not calculated in Octave,\n  ## but forwarded as a flag option to BLAS.\n  if (trans_A)\n    x = A' \\ b;\n  else\n    x = A \\ b;\n  endif\n\n  if (nargout > 1)\n    if (issquare (A))\n      R = rcond (A);\n    else\n      R = 0;\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! n = 10;\n%! A = rand (n);\n%! x = rand (n, 1);\n%! b = A * x;\n%! assert (linsolve (A, b), A \\ b);\n%! assert (linsolve (A, b, struct ()), A \\ b);\n\n%!test\n%! n = 10;\n%! A = triu (gallery (\"condex\", n));\n%! x = rand (n, 1);\n%! b = A' * x;\n%! opts.UT = true;\n%! opts.TRANSA = true;\n%! assert (linsolve (A, b, opts), A' \\ b);\n\n%!error <Invalid call> linsolve ()\n%!error <Invalid call> linsolve (1)\n%!error linsolve (1,2,3)\n%!error <A and B must be numeric> linsolve ({1},2)\n%!error <A and B must be numeric> linsolve (1,{2})\n%!error <OPTS must be a structure> linsolve (1,2,3)\n"
  },
  {
    "path": "scripts/linear-algebra/logm.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{s} =} logm (@var{A})\n## @deftypefnx {} {@var{s} =} logm (@var{A}, @var{opt_iters})\n## @deftypefnx {} {[@var{s}, @var{iters}] =} logm (@dots{})\n## Compute the matrix logarithm of the square matrix @var{A}.\n##\n## The implementation utilizes a Pad@'e approximant and the identity\n##\n## @example\n## logm (@var{A}) = 2^k * logm (@var{A}^(1 / 2^k))\n## @end example\n##\n## The optional input @var{opt_iters} is the maximum number of square roots\n## to compute and defaults to 100.\n##\n## The optional output @var{iters} is the number of square roots actually\n## computed.\n## @seealso{expm, sqrtm}\n## @end deftypefn\n\n## Reference: N. J. Higham, Functions of Matrices: Theory and Computation,\n##            SIAM, 2008.\n\n## Author: N. J. Higham\n## Author: Richard T. Guy <guyrt7@wfu.edu>\n\nfunction [s, iters] = logm (A, opt_iters = 100)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  if (! issquare (A))\n    error (\"logm: A must be a square matrix\");\n  endif\n\n  if (isscalar (A))\n    s = log (A);\n    return;\n  elseif (isdiag (A))\n    s = diag (log (diag (A)));\n    return;\n  endif\n\n  [u, s] = schur (A);\n\n  if (isreal (A))\n    [u, s] = rsf2csf (u, s);\n  endif\n\n  eigv = diag (s);\n  n = rows (A);\n  tol = n * eps (max (abs (eigv)));\n  real_neg_eigv = (real (eigv) < -tol) & (imag (eigv) <= tol);\n  if (any (real_neg_eigv))\n    warning (\"Octave:logm:non-principal\",\n             \"logm: principal matrix logarithm is not defined for matrices with negative eigenvalues; computing non-principal logarithm\");\n  endif\n\n  real_eig = ! any (real_neg_eigv);\n\n  if (max (abs (triu (s,1))(:)) < tol)\n    ## Will run for Hermitian matrices as Schur decomposition is diagonal.\n    ## This way is faster and more accurate but only works on a diagonal matrix.\n    logeigv = log (eigv);\n    logeigv(isinf (logeigv)) = -log (realmax ());\n    s = u * diag (logeigv) * u';\n    iters = 0;\n  else\n    k = 0;\n    ## Algorithm 11.9 in \"Function of matrices\", by N. Higham\n    theta = [0, 0, 1.61e-2, 5.38e-2, 1.13e-1, 1.86e-1, 2.6429608311114350e-1];\n    p = 0;\n    m = 7;\n    while (k < opt_iters)\n      tau = norm (s - eye (n), 1);\n      if (tau <= theta (7))\n        p += 1;\n        j(1) = find (tau <= theta, 1);\n        j(2) = find (tau / 2 <= theta, 1);\n        if (j(1) - j(2) <= 1 || p == 2)\n          m = j(1);\n          break;\n        endif\n      endif\n      k += 1;\n      s = sqrtm (s);\n    endwhile\n\n    if (k >= opt_iters)\n      warning (\"logm: maximum number of square roots exceeded; results may still be accurate\");\n    endif\n\n    s -= eye (n);\n\n    if (m > 1)\n      s = logm_pade_pf (s, m);\n    endif\n\n    s = 2^k * u * s * u';\n\n    if (nargout == 2)\n      iters = k;\n    endif\n  endif\n  ## Remove small complex values (O(eps)) which may have entered calculation\n  if (real_eig && isreal (A))\n    s = real (s);\n  endif\n\nendfunction\n\n################## ANCILLARY FUNCTIONS ################################\n######  Taken from the mfttoolbox (GPL 3) by D. Higham.\n######  Reference:\n######    D. Higham, Functions of Matrices: Theory and Computation,\n######    SIAM, 2008.\n#######################################################################\n\n## LOGM_PADE_PF   Evaluate Pade approximant to matrix log by partial fractions.\n##   Y = LOGM_PADE_PF(A,M) evaluates the [M/M] Pade approximation to\n##   LOG(EYE(SIZE(A))+A) using a partial fraction expansion.\n\nfunction s = logm_pade_pf (A, m)\n\n  [nodes, wts] = gauss_legendre (m);\n  ## Convert from [-1,1] to [0,1].\n  nodes = (nodes+1)/2;\n  wts /= 2;\n\n  n = length (A);\n  s = zeros (n);\n  for j = 1:m\n    s += wts(j)*(A/(eye (n) + nodes(j)*A));\n  endfor\n\nendfunction\n\n######################################################################\n## GAUSS_LEGENDRE  Nodes and weights for Gauss-Legendre quadrature.\n##   [X,W] = GAUSS_LEGENDRE(N) computes the nodes X and weights W\n##   for N-point Gauss-Legendre quadrature.\n\n## Reference:\n## G. H. Golub and J. H. Welsch, Calculation of Gauss quadrature\n## rules, Math. Comp., 23(106):221-230, 1969.\n\nfunction [x, w] = gauss_legendre (n)\n\n  i = 1:n-1;\n  v = i./sqrt ((2*i).^2-1);\n  [V, D] = eig (diag (v, -1) + diag (v, 1));\n  x = diag (D);\n  w = 2*(V(1,:)'.^2);\n\nendfunction\n\n\n%!assert (norm (logm ([1 -1;0 1]) - [0 -1; 0 0]) < 1e-5)\n%!test\n%! warning (\"off\", \"Octave:logm:non-principal\", \"local\");\n%! assert (norm (expm (logm ([-1 2 ; 4 -1])) - [-1 2 ; 4 -1]) < 1e-5);\n%!assert (logm ([1 -1 -1;0 1 -1; 0 0 1]), [0 -1 -1.5; 0 0 -1; 0 0 0], 1e-5)\n%!assert (logm (10), log (10))\n%!assert (full (logm (eye (3))), logm (full (eye (3))))\n%!assert (full (logm (10*eye (3))), logm (full (10*eye (3))), 8*eps)\n%!assert (logm (expm ([0 1i; -1i 0])), [0 1i; -1i 0], 10 * eps)\n%!test <*60738>\n%! A = [0.2510, 1.2808, -1.2252; ...\n%!      0.2015, 1.0766, 0.5630; ...\n%!      -1.9769, -1.0922, -0.5831];\n%! if (__have_feature__ (\"LLVM_LIBCXX\"))\n%!   ## The math libraries in libc++ seem to require larger tolerances\n%!   tol = 65*eps;\n%! else\n%!   tol = 42*eps;\n%! endif\n%! warning (\"off\", \"Octave:logm:non-principal\", \"local\");\n%! assert (expm (logm (A)), A, tol);\n%!assert (expm (logm (eye (3))), eye (3))\n%!assert (expm (logm (zeros (3))), zeros (3))\n\n## Test input validation\n%!error <Invalid call> logm ()\n%!error <logm: A must be a square matrix> logm ([1 0;0 1; 2 2])\n"
  },
  {
    "path": "scripts/linear-algebra/lscov.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} lscov (@var{A}, @var{b})\n## @deftypefnx {} {@var{x} =} lscov (@var{A}, @var{b}, @var{V})\n## @deftypefnx {} {@var{x} =} lscov (@var{A}, @var{b}, @var{V}, @var{alg})\n## @deftypefnx {} {[@var{x}, @var{stdx}, @var{mse}, @var{S}] =} lscov (@dots{})\n##\n## Compute a generalized linear least squares fit.\n##\n## Estimate @var{x} under the model @var{b} = @var{A}@var{x} + @var{w}, where\n## the noise @var{w} is assumed to follow a normal distribution with covariance\n## matrix @math{{\\sigma^2} V}.\n##\n## If the size of the coefficient matrix @var{A} is n-by-p, the size of the\n## vector/array of constant terms @var{b} must be n-by-k.\n##\n## The optional input argument @var{V} may be an n-element vector of positive\n## weights (inverse variances), or an n-by-n symmetric positive semi-definite\n## matrix representing the covariance of @var{b}.  If @var{V} is not supplied,\n## the ordinary least squares solution is returned.\n##\n## The @var{alg} input argument, a guidance on solution method to use, is\n## currently ignored.\n##\n## Besides the least-squares estimate matrix @var{x} (p-by-k), the function\n## also returns @var{stdx} (p-by-k), the error standard deviation of estimated\n## @var{x}; @var{mse} (k-by-1), the estimated data error covariance scale\n## factors (@math{\\sigma^2}); and @var{S} (p-by-p, or p-by-p-by-k if k > 1),\n## the error covariance of @var{x}.\n##\n## Reference: @nospell{Golub and Van Loan},\n## @cite{Matrix Computations (3rd Ed.)}, Johns Hopkins, Section 5.6.3, 1996.\n##\n## @seealso{ols, gls, lsqnonneg}\n## @end deftypefn\n\nfunction [x, stdx, mse, S] = lscov (A, b, V = [], alg)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (rows (A) != rows (b))\n    error (\"lscov: A and B must have the same number of rows\");\n  endif\n\n\n  if (nargin == 4)\n    warning (\"lscov: algorithm selection input ALG is not yet implemented, using default\");\n  endif\n\n  n = rows (A);\n  p = columns (A);\n  k = columns (b);\n\n  if (! isempty (V))\n\n    if (isvector (V))\n      ## n-element vector of inverse variances\n      if (numel (V) != n)\n        error (\"lscov: vector V must have n (number of row in A) elements \");\n      endif\n\n      v = diag (sqrt (V));\n      A = v * A;\n      b = v * b;\n    else\n      ## n-by-n covariance matrix\n      if (size (V) != [n, n])\n        error (\"lscov: matrix V must be square with the same number of rows as A\");\n      endif\n\n      try\n        ## Ordinarily V will be positive definite\n        B = chol (V)';\n      catch\n        ## If V is only positive semi-definite, use its\n        ## eigendecomposition to find a factor B such that V = B*B'\n        [B, lambda] = eig (V);\n        image_dims = (diag (lambda) > 0);\n        B = B(:, image_dims) * sqrt (lambda(image_dims, image_dims));\n      end_try_catch\n      A = B \\ A;\n      b = B \\ b;\n    endif\n  endif\n\n  pinv_A = pinv (A);\n\n  x = pinv_A * b;\n\n  if (nargout > 1)\n    dof = n - p;  # degrees of freedom remaining after fit\n    SSE = sumsq (b - A * x);\n    mse = SSE / dof;\n\n    s = pinv_A * pinv_A';\n    stdx = sqrt (diag (s) * mse);\n\n    if (nargout > 3)\n      if (k == 1)\n        S = mse * s;\n      else\n        S = NaN (p, p, k);\n        for i = 1:k\n          S(:, :, i) = mse(i) * s;\n        endfor\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!test <49040>\n%! ## Longley data from the NIST Statistical Reference Dataset\n%! Z = [  60323    83.0   234289   2356     1590    107608  1947\n%!        61122    88.5   259426   2325     1456    108632  1948\n%!        60171    88.2   258054   3682     1616    109773  1949\n%!        61187    89.5   284599   3351     1650    110929  1950\n%!        63221    96.2   328975   2099     3099    112075  1951\n%!        63639    98.1   346999   1932     3594    113270  1952\n%!        64989    99.0   365385   1870     3547    115094  1953\n%!        63761   100.0   363112   3578     3350    116219  1954\n%!        66019   101.2   397469   2904     3048    117388  1955\n%!        67857   104.6   419180   2822     2857    118734  1956\n%!        68169   108.4   442769   2936     2798    120445  1957\n%!        66513   110.8   444546   4681     2637    121950  1958\n%!        68655   112.6   482704   3813     2552    123366  1959\n%!        69564   114.2   502601   3931     2514    125368  1960\n%!        69331   115.7   518173   4806     2572    127852  1961\n%!        70551   116.9   554894   4007     2827    130081  1962 ];\n%! ## Results certified by NIST using 500 digit arithmetic\n%! ## b and standard error in b\n%! V = [  -3482258.63459582         890420.383607373\n%!         15.0618722713733         84.9149257747669\n%!        -0.358191792925910E-01    0.334910077722432E-01\n%!        -2.02022980381683         0.488399681651699\n%!        -1.03322686717359         0.214274163161675\n%!        -0.511041056535807E-01    0.226073200069370\n%!         1829.15146461355         455.478499142212 ];\n%! rsd =  304.854073561965;\n%! y = Z(:,1); X = [ones(rows(Z),1), Z(:,2:end)];\n%! alpha = 0.05;\n%! [b, stdb, mse] = lscov (X, y);\n%! assert (b, V(:,1), 3e-6);\n%! assert (stdb, V(:,2), -1.e-5);\n%! assert (sqrt (mse), rsd, -1E-6);\n\n%!test\n%! ## Adapted from example in Matlab documentation\n%! x1 = [.2 .5 .6 .8 1.0 1.1]';\n%! x2 = [.1 .3 .4 .9 1.1 1.4]';\n%! X = [ones(size(x1)) x1 x2];\n%! y = [.17 .26 .28 .23 .27 .34]';\n%! [b, se_b, mse, S] = lscov(X, y);\n%! assert (b, [0.1203 0.3284 -0.1312]', 1E-4);\n%! assert (se_b, [0.0643 0.2267 0.1488]', 1E-4);\n%! assert (mse, 0.0015, 1E-4);\n%! assert (S, [0.0041 -0.0130 0.0075; -0.0130 0.0514 -0.0328; 0.0075 -0.0328 0.0221], 1E-4);\n%! w = [1 1 1 1 1 .1]';\n%! [bw, sew_b, msew] = lscov (X, y, w);\n%! assert (bw, [0.1046 0.4614 -0.2621]', 1E-4);\n%! assert (sew_b, [0.0309 0.1152 0.0814]', 1E-4);\n%! assert (msew, 3.4741e-004, -1E-4);\n%! V = .2*ones (length (x1)) + .8*diag (ones (size (x1)));\n%! [bg, sew_b, mseg] = lscov (X, y, V);\n%! assert (bg, [0.1203 0.3284 -0.1312]', 1E-4);\n%! assert (sew_b, [0.0672 0.2267 0.1488]', 1E-4);\n%! assert (mseg, 0.0019, 1E-4);\n%! y2 = [y 2*y];\n%! [b2, se_b2, mse2, S2] = lscov (X, y2);\n%! assert (b2, [b 2*b], 2*eps);\n%! assert (se_b2, [se_b 2*se_b], 3*eps);\n%! assert (mse2, [mse 4*mse], eps);\n%! assert (S2(:, :, 1), S, eps);\n%! assert (S2(:, :, 2), 4*S, 3*eps);\n\n%!test\n%! ## Artificial example with positive semi-definite weight matrix\n%! x = (0:0.2:2)';\n%! y = round (100*sin (x) + 200*cos (x));\n%! X = [ones(size(x)) sin(x) cos(x)];\n%! V = eye (numel (x));\n%! V(end, end-1) = V(end-1, end) = 1;\n%! [b, seb, mseb, S] = lscov (X, y, V);\n%! assert (b, [0 100 200]', 0.2);\n\n## Test input validation\n%!error <Invalid call> lscov ()\n%!error <Invalid call> lscov (1)\n%!error <A and B must have the same number of rows> lscov (ones (2,2),1)\n%!warning <algorithm selection input ALG is not yet implemented>\n%! lscov (1,1, [], \"chol\");\n%!error <vector V must have n .* elements> lscov (1,2, [1, 2])\n%!error <matrix V must be square> lscov (1,2, [1 2 3; 4 5 6])\n"
  },
  {
    "path": "scripts/linear-algebra/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/bandwidth.m \\\n  %reldir%/commutation_matrix.m \\\n  %reldir%/cond.m \\\n  %reldir%/condeig.m \\\n  %reldir%/condest.m \\\n  %reldir%/cross.m \\\n  %reldir%/duplication_matrix.m \\\n  %reldir%/expm.m \\\n  %reldir%/funm.m \\\n  %reldir%/gls.m \\\n  %reldir%/housh.m \\\n  %reldir%/isbanded.m \\\n  %reldir%/isdefinite.m \\\n  %reldir%/isdiag.m \\\n  %reldir%/ishermitian.m \\\n  %reldir%/issymmetric.m \\\n  %reldir%/istril.m \\\n  %reldir%/istriu.m \\\n  %reldir%/krylov.m \\\n  %reldir%/linsolve.m \\\n  %reldir%/logm.m \\\n  %reldir%/lscov.m \\\n  %reldir%/normest.m \\\n  %reldir%/normest1.m \\\n  %reldir%/null.m \\\n  %reldir%/ols.m \\\n  %reldir%/ordeig.m \\\n  %reldir%/orth.m \\\n  %reldir%/planerot.m \\\n  %reldir%/qzhess.m \\\n  %reldir%/rank.m \\\n  %reldir%/rref.m \\\n  %reldir%/subspace.m \\\n  %reldir%/trace.m \\\n  %reldir%/tensorprod.m \\\n  %reldir%/vech.m \\\n  %reldir%/vecnorm.m\n\n%canon_reldir%dir = $(fcnfiledir)/linear-algebra\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/linear-algebra/normest.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{nest} =} normest (@var{A})\n## @deftypefnx {} {@var{nest} =} normest (@var{A}, @var{tol})\n## @deftypefnx {} {[@var{nest}, @var{iter}] =} normest (@dots{})\n## Estimate the 2-norm of the matrix @var{A} using a power series analysis.\n##\n## This is typically used for large matrices, where the cost of calculating\n## @code{norm (@var{A})} is prohibitive and an approximation to the 2-norm is\n## acceptable.\n##\n## @var{tol} is the tolerance to which the 2-norm is calculated.  By default\n## @var{tol} is 1e-6.\n##\n## The optional output @var{iter} returns the number of iterations that were\n## required for @code{normest} to converge.\n## @seealso{normest1, norm, cond, condest}\n## @end deftypefn\n\nfunction [nest, iter] = normest (A, tol = 1e-6)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (A) || ndims (A) != 2)\n    error (\"normest: A must be a numeric 2-D matrix\");\n  endif\n\n  if (! (isscalar (tol) && isreal (tol)))\n    error (\"normest: TOL must be a real scalar\");\n  endif\n\n  if (! isfloat (A))\n    A = double (A);\n  endif\n\n  tol = max (tol, eps (class (A)));\n  ## Set random number generator to depend on target matrix\n  v = rand (\"state\");\n  rand (\"state\", full (trace (A)));\n  ncols = columns (A);\n  ## Randomize y to avoid bad guesses for important matrices.\n  y = rand (ncols, 1);\n  iter = 0;\n  nest = 0;\n  do\n    n0 = nest;\n    x = A * y;\n    normx = norm (x);\n    if (normx == 0)\n      x = rand (ncols, 1);\n    else\n      x /= normx;\n    endif\n    y = A' * x;\n    nest = norm (y);\n    iter += 1;\n  until (abs (nest - n0) <= tol * nest)\n\n  rand (\"state\", v);    # restore state of random number generator\n\nendfunction\n\n\n%!test\n%! A = toeplitz ([-2,1,0,0]);\n%! assert (normest (A), norm (A), 1e-6);\n\n%!test\n%! A = rand (10);\n%! assert (normest (A), norm (A), 1e-6);\n\n## Test input validation\n%!error <Invalid call> normest ()\n%!error <A must be a numeric .* matrix> normest ([true true])\n%!error <A must be .* 2-D matrix> normest (ones (3,3,3))\n%!error <TOL must be a real scalar> normest (1, [1, 2])\n%!error <TOL must be a real scalar> normest (1, 1+1i)\n"
  },
  {
    "path": "scripts/linear-algebra/normest1.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{nest} =} normest1 (@var{A})\n## @deftypefnx {} {@var{nest} =} normest1 (@var{A}, @var{t})\n## @deftypefnx {} {@var{nest} =} normest1 (@var{A}, @var{t}, @var{x0})\n## @deftypefnx {} {@var{nest} =} normest1 (@var{Afcn}, @var{t}, @var{x0}, @var{p1}, @var{p2}, @dots{})\n## @deftypefnx {} {[@var{nest}, @var{v}] =} normest1 (@var{A}, @dots{})\n## @deftypefnx {} {[@var{nest}, @var{v}, @var{w}] =} normest1 (@var{A}, @dots{})\n## @deftypefnx {} {[@var{nest}, @var{v}, @var{w}, @var{iter}] =} normest1 (@var{A}, @dots{})\n## Estimate the 1-norm of the matrix @var{A} using a block algorithm.\n##\n## @code{normest1} is best for large sparse matrices where only an estimate of\n## the norm is required.  For small to medium sized matrices, consider using\n## @code{norm (@var{A}, 1)}.  In addition, @code{normest1} can be used for the\n## estimate of the 1-norm of a linear operator @var{A} when matrix-vector\n## products @code{@var{A} * @var{x}} and @code{@var{A}' * @var{x}} can be\n## cheaply computed.  In this case, instead of the matrix @var{A}, a function\n## @code{@var{Afcn} (@var{flag}, @var{x})} is used; it must return:\n##\n## @itemize @bullet\n## @item\n## the dimension @var{n} of @var{A}, if @var{flag} is @qcode{\"dim\"}\n##\n## @item\n## true if @var{A} is a real operator, if @var{flag} is @qcode{\"real\"}\n##\n## @item\n## the result @code{@var{A} * @var{x}}, if @var{flag} is @qcode{\"notransp\"}\n##\n## @item\n## the result @code{@var{A}' * @var{x}}, if @var{flag} is @qcode{\"transp\"}\n## @end itemize\n##\n## A typical case is @var{A} defined by @code{@var{b} ^ @var{m}}, in which the\n## result @code{@var{A} * @var{x}} can be computed without even forming\n## explicitly @code{@var{b} ^ @var{m}} by:\n##\n## @example\n## @group\n## @var{y} = @var{x};\n## for @var{i} = 1:@var{m}\n##   @var{y} = @var{b} * @var{y};\n## endfor\n## @end group\n## @end example\n##\n## The parameters @var{p1}, @var{p2}, @dots{} are arguments of\n## @code{@var{Afcn} (@var{flag}, @var{x}, @var{p1}, @var{p2}, @dots{})}.\n##\n## The default value for @var{t} is 2.  The algorithm requires matrix-matrix\n## products with sizes @var{n} x @var{n} and @var{n} x @var{t}.\n##\n## The initial matrix @var{x0} should have columns of unit 1-norm.  The default\n## initial matrix @var{x0} has the first column\n## @code{ones (@var{n}, 1) / @var{n}} and, if @var{t} > 1, the remaining\n## columns with random elements @code{-1 / @var{n}}, @code{1 / @var{n}},\n## divided by @var{n}.\n##\n## On output, @var{nest} is the desired estimate, @var{v} and @var{w}\n## are vectors such that @code{@var{w} = @var{A} * @var{v}}, with\n## @code{norm (@var{w}, 1)} = @code{@var{c} * norm (@var{v}, 1)}.  @var{iter}\n## contains in @code{@var{iter}(1)} the number of iterations (the maximum is\n## hardcoded to 5) and in @code{@var{iter}(2)} the total number of products\n## @code{@var{A} * @var{x}} or @code{@var{A}' * @var{x}} performed by the\n## algorithm.\n##\n## Algorithm Note: @code{normest1} uses random numbers during evaluation.\n## Therefore, if consistent results are required, the @qcode{\"state\"} of the\n## random generator should be fixed before invoking @code{normest1}.\n##\n## Reference: @nospell{N. J. Higham and F. Tisseur},\n## \"A block algorithm for matrix 1-norm estimation, with and application to\n## 1-norm @nospell{pseudospectra}\",\n## @cite{@nospell{SIAM J. Matrix Anal.@: Appl.@:}}, @w{Vol.@: 21}, @w{No.@: 4},\n## @w{pp.@: 1185}--1201, 2000.\n##\n## @seealso{normest, norm, cond, condest}\n## @end deftypefn\n\n## Ideally, we would set t and X to their default values but Matlab\n## compatibility would require we set the default even when they are empty.\nfunction [nest, v, w, iter] = normest1 (A, t = [], x0 = [], varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isempty (t))\n    t = 2;\n  endif\n\n  ## FIXME: t < 0 should print trace information\n  if (isnumeric (A) && issquare (A))\n    Aismat = true;\n    Aisreal = isreal (A);\n    n = rows (A);\n    if (n <= 4 || t == n)\n      ## small input, compute directly\n      [nest, idx] = max (sum (abs (A), 1), [] , 2);\n      v = zeros (n, 1);\n      v(idx) = 1;\n      w = A(:, idx);\n      ## Matlab incompatible on purpose.  Matlab returns iter as a row vector\n      ## for this special case, but a column vector in all other cases.\n      ## This is obviously a bug in Matlab that we don't reproduce.\n      iter = [0; 1];\n      return;\n    endif\n  elseif (is_function_handle (A))\n    Aismat = false;\n    Aisreal = A (\"real\", [], varargin{:});\n    n = A (\"dim\", [], varargin{:});\n    Afcn = @(x) A (\"notransp\", x, varargin{:});\n    A1fcn = @(x) A (\"transp\", x, varargin{:});\n  else\n    error (\"normest1: A must be a square matrix or a function handle\");\n  endif\n\n  t = min (t, n);\n\n  if (isempty (x0))\n    X = [ones(n, 1), sign(2 * rand(n, t - 1) - 1)];\n    i = 2;\n    imax = min (t, 2^(n-1));\n    ## There are at most 2^(n-1) unparallel columns, see later.\n    while (i <= imax)\n      if (any (abs (X(:,i)' * X(:,1:i-1)) == n))\n        ## column i is parallel to a column 1:i-1.  Change it.\n        X(:,i) = sign (2 * rand (n, 1) - 1);\n      else\n        i++;\n      endif\n    endwhile\n    X /= n;\n  else\n    if (columns (x0) < t)\n      error (\"normest1: X0 must have %d columns\", t);\n    endif\n    X = x0;\n  endif\n\n  itmax = 5;\n  idx_hist = zeros (n, 1);\n  nest_old = 0;\n  idx = zeros (n, 1);\n  S = zeros (n, t);\n  iter = [0; 0];\n  converged = false;\n  while (! converged && (iter(1) < itmax))\n    iter(1)++;\n    if (Aismat)\n      Y = A * X;\n    else\n      Y = Afcn (X);\n    endif\n    iter(2)++;\n    [nest, j] = max (sum (abs (Y), 1), [], 2);\n    if ((nest > nest_old) || (iter(1) == 2))\n      idx_best = idx(j);\n      w = Y(:, j);  # there is an error in Algorithm 2.4\n    endif\n    if (nest <= nest_old && iter(1) >= 2)  # (1) of Algorithm 2.4\n      nest = nest_old;\n      break;  # while\n    endif\n    nest_old = nest;\n    Sold = S;\n    S = sign (Y);\n    S(S==0) = 1;\n    possible_break = false;\n    if (Aisreal)\n      ## test parallel (only real case)\n      if (all (any (abs (Sold' * S) == n)))  # (2) of Algorithm 2.4\n        ## all columns of S parallel to a column of Sold, exit\n        possible_break = true;\n        converged = true;\n      else\n        if (t > 1)\n          ## at least two columns of S are not parallel\n          i = 1;\n          ## The maximum number of unparallel columns of length n with\n          ## entries {-1,1} is 2^(n-1).  n of them are already in Sold.\n          imax = min (t, 2 ^ (n - 1) - n);\n          while (i <= imax)\n            if (any (abs (S(:,i)' * S(:,1:i-1)) == n)\n                || any (abs (S(:,i)' * Sold) == n))\n              ## i-th column of S is parallel to a previous column\n              ## or to a column of Sold.  Change it.\n              S(:,i) = sign (2*rand (n, 1)-1);\n            else\n              i++;\n            endif\n          endwhile\n        endif\n      endif\n    endif\n    if (! possible_break)\n      if (Aismat)\n        Z = A' * S;\n      else\n        Z = A1fcn (S);  # (3) of Algorithm 2.4\n      endif\n      iter(2)++;\n      h = max (abs (Z), [], 2);\n      idx = (1:n)';\n      if (iter(1) >= 2 && (max (h, [], 1) == h(idx_best)))  # (4) of Alg. 2.4\n        break;  # while\n      endif\n      [h, idx] = sort (h, \"descend\");\n      if (t > 1)\n       if (all (idx_hist(idx(1:t)))) # (5) of Algorithm 2.4\n          break;  # while\n        endif\n        idx = idx(! idx_hist(idx));\n        ## length(idx) could be less than t, especially if t is not << n.\n        ## This is not considered in point (5) of Algorithm 2.4.\n        tmax = min (numel (idx), t);\n        idx = idx(1:tmax);\n      else\n        tmax = 1;\n      endif\n      X = zeros (n, tmax);\n      X(sub2ind (size (X), idx(1:tmax), (1:tmax)')) = 1;\n      idx_hist(idx(1:tmax)) = 1;\n    endif\n  endwhile\n  v = zeros (n, 1);\n  v(idx_best) = 1;\n\nendfunction\n\n\n%!function z = afcn_A (flag, x, A, n)\n%!  switch (flag)\n%!  case {\"dim\"}\n%!    z = n;\n%!  case {\"real\"}\n%!    z = isreal (A);\n%!  case {\"transp\"}\n%!    z = A' * x;\n%!  case {\"notransp\"}\n%!    z = A * x;\n%!  endswitch\n%!endfunction\n%!function z = afcn_A_P (flag, x, A, m)\n%!  switch (flag)\n%!  case \"dim\"\n%!    z = length (A);\n%!  case \"real\"\n%!    z = isreal (A);\n%!  case \"transp\"\n%!    z = x; for i = 1:m, z = A' * z;, endfor\n%!  case \"notransp\"\n%!    z = x; for i = 1:m, z = A * z;, endfor\n%!  endswitch\n%!endfunction\n\n%!test\n%! A = reshape ((1:16)-8, 4, 4);\n%! assert (normest1 (A), norm (A, 1), eps);\n\n## test t=1\n%!test\n%! A = rand (4); # for positive matrices always work\n%! assert (normest1 (A, 1), norm (A,1), 4 * eps);\n\n## test t=3\n%!test\n%! A = [-0.21825   0.16598   0.19388   0.75297\n%!      -1.47732   0.78443  -1.04254   0.42240\n%!       1.39857  -0.34046   2.28617   0.68089\n%!       0.31205   1.50529  -0.75804  -1.22476];\n%! X = [1,1,-1;1,1,1;1,1,-1;1,-1,-1]/3;\n%! assert (normest1 (A, 3, X), norm (A, 1), 2 * eps);\n\n## test Afcn\n%!test\n%! A = rand (10);\n%! n = length (A);\n%! Afcn = @(flag, x) afcn_A (flag, x, A, n);\n%! assert (normest1 (Afcn), norm (A, 1), 4 * eps);\n\n## test Afcn with parameters\n%!test\n%! A = rand (10);\n%! assert (normest1 (@afcn_A_P, [], [], A, 3), norm (A ^ 3, 1), 1000 * eps);\n\n## test output\n%!test\n%! A = reshape (1:16,4,4);\n%! [nest, v, w, iter] = normest1 (A);\n%! assert (norm (w, 1), nest * norm (v, 1), eps);\n\n## test output\n%!test\n%! A = rand (100);\n%! A(A <= 1/3) = -1;\n%! A(A > 1/3 & A <= 2/3) = 0;\n%! A(A > 2/3) = 1;\n%! [nest, v, w, iter] = normest1 (A, 10);\n%! assert (w, A * v, eps);\n\n%!test\n%! A = rand (5);\n%! nest = normest1 (A, 6);\n%! assert (nest, norm (A,1), 4 * eps);\n\n%!test\n%! A = rand (5);\n%! nest = normest1 (A, 2, ones (5, 2) / 5);\n%! assert (nest, norm (A,1), 4 * eps);\n\n%!test\n%! N = 10;\n%! A = ones (N);\n%! [nm1, v1, w1] = normest1 (A);\n%! [nminf, vinf, winf] = normest1 (A', 6);\n%! assert (nm1, N, -2*eps);\n%! assert (nminf, N, -2*eps);\n%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps);\n%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps);\n\n%!test\n%! N = 5;\n%! A = hilb (N);\n%! [nm1, v1, w1] = normest1 (A);\n%! [nminf, vinf, winf] = normest1 (A', 6);\n%! assert (nm1, norm (A, 1), -2*eps);\n%! assert (nminf, norm (A, inf), -2*eps);\n%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps);\n%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps);\n\n## Only likely to be within a factor of 10.\n%!test\n%! old_state = rand (\"state\");\n%! unwind_protect\n%!   rand (\"state\", 42);  # Initialize to guarantee reproducible results\n%!   N = 100;\n%!   A = rand (N);\n%!   [nm1, v1, w1] = normest1 (A);\n%!   [nminf, vinf, winf] = normest1 (A', 6);\n%!   assert (nm1, norm (A, 1), -.1);\n%!   assert (nminf, norm (A, inf), -.1);\n%!   assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps);\n%!   assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps);\n%! unwind_protect_cleanup\n%!   rand (\"state\", old_state);\n%! end_unwind_protect\n\n## Check ITER is always a column vector.\n%!test\n%! [~, ~, ~, it] = normest1 (rand (3), 3);\n%! assert (iscolumn (it));\n%! [~, ~, ~, it] = normest1 (rand (50), 20);\n%! assert (iscolumn (it));\n\n## Test input validation\n%!error <Invalid call> normest1 ()\n%!error <A must be a square matrix or a function handle> normest1 ({1})\n%!error <A must be a square matrix> normest1 ([1 2])\n%!error <X0 must have 2 columns> normest1 (magic (5), :, [1])\n"
  },
  {
    "path": "scripts/linear-algebra/null.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{Z} =} null (@var{A})\n## @deftypefnx {} {@var{Z} =} null (@var{A}, @var{tol})\n## Return an orthonormal basis @var{Z} of the null space of @var{A}.\n##\n## The dimension of the null space @var{Z} is taken as the number of singular\n## values of @var{A} not greater than @var{tol}.  If the argument @var{tol}\n## is missing, it is computed as\n##\n## @example\n## max (size (@var{A})) * max (svd (@var{A}, 0)) * eps\n## @end example\n## @seealso{orth, svd}\n## @end deftypefn\n\nfunction Z = null (A, tol)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (nargin == 2 && strcmp (tol, \"r\"))\n    error (\"null: option for rational not yet implemented\");\n  endif\n\n  [~, S, V] = svd (A, 0);  # Use economy-sized svd if possible.\n\n  if (isempty (A))\n    ## In case of A = [], zeros (0,X), zeros (X,0) Matlab R2020b seems to\n    ## simply return the nullspace \"V\" of the svd-decomposition (bug #59630).\n    Z = V;\n  else\n    out_cls = class (V);\n\n    ## Extract column vector from Diagonal Matrix which depends on size\n    if (rows (S) > 1)\n      s = diag (S);\n    else\n      s = S(1);\n    endif\n    if (nargin == 1)\n      tol = max (size (A)) * s(1) * eps (out_cls);\n    endif\n    rank = sum (s > tol);\n\n    cols = columns (A);\n    if (rank < cols)\n      Z = V(:, rank+1:cols);\n      Z(abs (Z) < eps (out_cls)) = 0;\n    else\n      Z = zeros (cols, 0, out_cls);\n    endif\n  endif\n\nendfunction\n\n\n## Exact tests\n%!test\n%! A = {\n%!   [], [];\n%!   zeros(1,0), [];\n%!   zeros(4,0), [];\n%!   zeros(0,1), 1;\n%!   zeros(0,4), eye(4);\n%!   0, 1;\n%!   1, zeros(1,0);\n%!   [1 0; 0 1], zeros(2,0);\n%!   [1 0; 1 0], [0 1]';\n%! };\n%! for i = 1:rows (A)\n%!   assert (null (A{i,1}), A{i,2});\n%!   assert (null (single (A{i,1})), single (A{i,2}));\n%! endfor\n\n## Inexact tests\n%!test\n%! A = {\n%!   [1 1; 0 0], [-1/sqrt(2) 1/sqrt(2)]';\n%! };\n%! for i = 1:rows (A)\n%!   assert (null (A{i,1}), A{i,2}, eps);\n%!   assert (null (single (A{i,1})), single (A{i,2}), eps);\n%! endfor\n\n## Tests with tolerance input\n%!test\n%! tol = 1e-4;\n%! A = {\n%!   @(e) [1 0; 0 tol-e], [0 1]';\n%!   @(e) [1 0; 0 tol+e], zeros(2,0);\n%! };\n%! for i = 1:rows (A)\n%!   assert (null (A{i,1}(eps (\"double\")), tol), A{i,2});\n%!   assert (null (single (A{i,1}(eps (\"single\"))), tol), single (A{i,2}));\n%! endfor\n\n## Input corner cases\n%!assert (null (uint8 ([])), [])\n\n## Test input validation\n%!error <Invalid call> null ()\n%!error <rational not yet implemented> null (1, 'r')\n"
  },
  {
    "path": "scripts/linear-algebra/ols.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{beta}, @var{sigma}, @var{r}] =} ols (@var{y}, @var{x})\n## Ordinary least squares (OLS) estimation.\n##\n## OLS applies to the multivariate model\n## @tex\n## $@var{y} = @var{x}\\,@var{b} + @var{e}$\n## @end tex\n## @ifnottex\n## @w{@math{@var{y} = @var{x}*@var{b} + @var{e}}}\n## @end ifnottex\n## where\n## @tex\n## $@var{y}$ is a $t \\times p$ matrix, $@var{x}$ is a $t \\times k$ matrix,\n## $@var{b}$ is a $k \\times p$ matrix, and $@var{e}$ is a $t \\times p$ matrix.\n## @end tex\n## @ifnottex\n## @math{@var{y}} is a @math{t}-by-@math{p} matrix, @math{@var{x}} is a\n## @math{t}-by-@math{k} matrix, @var{b} is a @math{k}-by-@math{p} matrix, and\n## @var{e} is a @math{t}-by-@math{p} matrix.\n## @end ifnottex\n##\n## Each row of @var{y} is a @math{p}-variate observation in which each column\n## represents a variable.  Likewise, the rows of @var{x} represent\n## @math{k}-variate observations or possibly designed values.  Furthermore,\n## the collection of observations @var{x} must be of adequate rank, @math{k},\n## otherwise @var{b} cannot be uniquely estimated.\n##\n## The observation errors, @var{e}, are assumed to originate from an\n## underlying @math{p}-variate distribution with zero mean and\n## @math{p}-by-@math{p} covariance matrix @var{S}, both constant conditioned\n## on @var{x}.  Furthermore, the matrix @var{S} is constant with respect to\n## each observation such that\n## @tex\n## $\\bar{@var{e}} = 0$ and cov(vec(@var{e})) =  kron(@var{s},@var{I}).\n## @end tex\n## @ifnottex\n## @code{mean (@var{e}) = 0} and\n## @code{cov (vec (@var{e})) = kron (@var{s}, @var{I})}.\n## @end ifnottex\n## (For cases\n## that don't meet this criteria, such as autocorrelated errors, see\n## generalized least squares, gls, for more efficient estimations.)\n##\n## The return values @var{beta}, @var{sigma}, and @var{r} are defined as\n## follows.\n##\n## @table @var\n## @item beta\n## The OLS estimator for matrix @var{b}.\n## @tex\n## @var{beta} is calculated directly via $(@var{x}^T@var{x})^{-1} @var{x}^T\n## @var{y}$ if the matrix $@var{x}^T@var{x}$ is of full rank.\n## @end tex\n## @ifnottex\n## @var{beta} is calculated directly via\n## @code{inv (@var{x}'*@var{x}) * @var{x}' * @var{y}} if the matrix\n## @code{@var{x}'*@var{x}} is of full rank.\n## @end ifnottex\n## Otherwise, @code{@var{beta} = pinv (@var{x}) * @var{y}} where\n## @code{pinv (@var{x})} denotes the pseudoinverse of @var{x}.\n##\n## @item sigma\n## The OLS estimator for the matrix @var{s},\n##\n## @example\n## @group\n## @var{sigma} = (@var{y}-@var{x}*@var{beta})' * (@var{y}-@var{x}*@var{beta}) / (@math{t}-rank(@var{x}))\n## @end group\n## @end example\n##\n## @item r\n## The matrix of OLS residuals, @code{@var{r} = @var{y} - @var{x}*@var{beta}}.\n## @end table\n## @seealso{gls, pinv}\n## @end deftypefn\n\nfunction [beta, sigma, r] = ols (y, x)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) && isnumeric (y)))\n    error (\"ols: X and Y must be numeric matrices or vectors\");\n  endif\n\n  if (ndims (x) != 2 || ndims (y) != 2)\n    error (\"ols: X and Y must be 2-D matrices or vectors\");\n  endif\n\n  [nr, nc] = size (x);\n  [ry, cy] = size (y);\n  if (nr != ry)\n    error (\"ols: number of rows of X and Y must be equal\");\n  endif\n\n  if (isinteger (x))\n    x = double (x);\n  endif\n  if (isinteger (y))\n    y = double (y);\n  endif\n\n  ## Start of algorithm\n  z = x' * x;\n  [u, p] = chol (z);\n\n  if (p)\n    beta = x \\ y;\n  else\n    beta = u \\ (u' \\ (x' * y));\n  endif\n\n  if (nargout > 1)\n    r = y - x * beta;\n\n    ## z is of full rank, avoid the SVD in rnk\n    if (p == 0)\n      rnk = columns (z);\n    else\n      rnk = rank (z);\n    endif\n\n    sigma = r' * r / (nr - rnk);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Filip data from NIST StRD - Polynomial Regression (degree 10)\n%! ## https://www.itl.nist.gov/div898/strd/lls/data/Filip.shtml\n%! xy = [0.8116   -6.860120914;  0.9072   -4.324130045\n%!       0.9052   -4.358625055;  0.9039   -4.358426747\n%!       0.8053   -6.955852379;  0.8377   -6.661145254\n%!       0.8667   -6.355462942;  0.8809   -6.118102026\n%!       0.7975   -7.115148017;  0.8162   -6.815308569\n%!       0.8515   -6.519993057;  0.8766   -6.204119983\n%!       0.8885   -5.853871964;  0.8859   -6.109523091\n%!       0.8959   -5.79832982;   0.8913   -5.482672118\n%!       0.8959   -5.171791386;  0.8971   -4.851705903\n%!       0.9021   -4.517126416;  0.909    -4.143573228\n%!       0.9139   -3.709075441;  0.9199   -3.499489089\n%!       0.8692   -6.300769497;  0.8872   -5.953504836\n%!       0.89     -5.642065153;  0.891    -5.031376979\n%!       0.8977   -4.680685696;  0.9035   -4.329846955\n%!       0.9078   -3.928486195;  0.7675   -8.56735134\n%!       0.7705   -8.363211311;  0.7713   -8.107682739\n%!       0.7736   -7.823908741;  0.7775   -7.522878745\n%!       0.7841   -7.218819279;  0.7971   -6.920818754\n%!       0.8329   -6.628932138;  0.8641   -6.323946875\n%!       0.8804   -5.991399828;  0.7668   -8.781464495\n%!       0.7633   -8.663140179;  0.7678   -8.473531488\n%!       0.7697   -8.247337057;  0.77     -7.971428747\n%!       0.7749   -7.676129393;  0.7796   -7.352812702\n%!       0.7897   -7.072065318;  0.8131   -6.774174009\n%!       0.8498   -6.478861916;  0.8741   -6.159517513\n%!       0.8061   -6.835647144;  0.846    -6.53165267\n%!       0.8751   -6.224098421;  0.8856   -5.910094889\n%!       0.8919   -5.598599459;  0.8934   -5.290645224\n%!       0.894    -4.974284616;  0.8957   -4.64454848\n%!       0.9047   -4.290560426;  0.9129   -3.885055584\n%!       0.9209   -3.408378962;  0.9219   -3.13200249\n%!       0.7739   -8.726767166;  0.7681   -8.66695597\n%!       0.7665   -8.511026475;  0.7703   -8.165388579\n%!       0.7702   -7.886056648;  0.7761   -7.588043762\n%!       0.7809   -7.283412422;  0.7961   -6.995678626\n%!       0.8253   -6.691862621;  0.8602   -6.392544977\n%!       0.8809   -6.067374056;  0.8301   -6.684029655\n%!       0.8664   -6.378719832;  0.8834   -6.065855188\n%!       0.8898   -5.752272167;  0.8964   -5.132414673\n%!       0.8963   -4.811352704;  0.9074   -4.098269308\n%!       0.9119   -3.66174277;   0.9228   -3.2644011];\n%! ## Certified values (NIST)\n%! b_cert = [-1467.48961422980; -2772.17959193342; -2316.37108160893;\n%!           -1127.97394098372; -354.478233703349; -75.1242017393757;\n%!           -10.8753180355343; -1.06221498588947; -0.670191154593408E-01;\n%!           -0.246781078275479E-02; -0.402962525080404E-04];\n%! y = xy(:,1);\n%! x = xy(:,2);\n%! ## Fit degree-10 polynomial using OLS\n%! X = vander (x, 11);\n%! [b, sigma, r] = ols (y, X);\n%! clf;\n%! subplot (3, 1, [1 2]);\n%! plot (x, y, \"bo\", \"markerfacecolor\", \"b\", \"markersize\", 2);\n%! hold on;\n%! x_fit = linspace (min (x), max (x), 200);\n%! plot (x_fit, polyval (b, x_fit), \"r-\", \"linewidth\", 1);\n%! hold off;\n%! grid on;\n%! ylabel (\"y\");\n%! title (\"NIST Filip Dataset: Degree-10 Polynomial Fit\");\n%! legend (\"Data\", \"OLS Fit\", \"location\", \"northwest\");\n%! subplot (3, 1, 3);\n%! stem (x, r, \"filled\", \"markersize\", 2);\n%! grid on;\n%! xlabel (\"x\");\n%! ylabel (\"Residual\");\n%! title (sprintf (\"Residuals (RMS = %.2e)\", sqrt (mean (r.^2))));\n%! assert (flip (b), b_cert, -2e-6);\n\n%!test\n%! x = [1:5]';\n%! y = 3*x + 2;\n%! x = [x, ones(5,1)];\n%! assert (ols (y,x), [3; 2], 50*eps);\n\n%!test\n%! x = [1, 2; 3, 4];\n%! y = [1; 2];\n%! [b, s, r] = ols (x, y);\n%! assert (b, [1.4, 2], 2*eps);\n%! assert (s, [0.2, 0; 0, 0], 2*eps);\n%! assert (r, [-0.4, 0; 0.2, 0], 2*eps);\n\n%!test\n%! x = [1, 2; 3, 4];\n%! y = [1; 2];\n%! [b, s] = ols (x, y);\n%! assert (b, [1.4, 2], 2*eps);\n%! assert (s, [0.2, 0; 0, 0], 2*eps);\n\n%!test\n%! x = [1, 2; 3, 4];\n%! y = [1; 2];\n%! b = ols (x, y);\n%! assert (b, [1.4, 2], 2*eps);\n\n## Test input validation\n%!error <Invalid call> ols ()\n%!error <Invalid call> ols (1)\n%!error ols ([true, true], [1, 2])\n%!error ols ([1, 2], [true, true])\n%!error ols (ones (2,2,2), ones (2,2))\n%!error ols (ones (2,2), ones (2,2,2))\n%!error ols (ones (1,2), ones (2,2))\n"
  },
  {
    "path": "scripts/linear-algebra/ordeig.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{lambda} =} ordeig (@var{A})\n## @deftypefnx {} {@var{lambda} =} ordeig (@var{A}, @var{B})\n## Return the eigenvalues of quasi-triangular matrices in their order of\n## appearance in the matrix @var{A}.\n##\n## The quasi-triangular matrix @var{A} is usually the result of a Schur\n## factorization.  If called with a second input @var{B} then the generalized\n## eigenvalues of the pair @var{A}, @var{B} are returned in the order of\n## appearance of the matrix @code{@var{A}-@var{lambda}*@var{B}}.  The pair\n## @var{A}, @var{B} is usually the result of a QZ decomposition.\n##\n## @seealso{ordschur, ordqz, eig, schur, qz}\n## @end deftypefn\n\nfunction lambda = ordeig (A, B)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (A) || ! issquare (A))\n    error (\"ordeig: A must be a square matrix\");\n  endif\n\n  n = length (A);\n\n  if (nargin == 1)\n    B = eye (n);\n    if (isreal (A))\n      if (! is_quasitri (A))\n        error (\"ordeig: A must be quasi-triangular (i.e., upper block triangular with 1x1 or 2x2 blocks on the diagonal)\");\n      endif\n    else\n      if (! istriu (A))\n        error (\"ordeig: A must be upper-triangular when it is complex\");\n      endif\n    endif\n  else\n    if (! isnumeric (B) || ! issquare (B))\n      error (\"ordeig: B must be a square matrix\");\n    elseif (length (B) != n)\n      error (\"ordeig: A and B must be the same size\");\n    endif\n    if (isreal (A) && isreal (B))\n      if (! is_quasitri (A) || ! is_quasitri (B))\n        error (\"ordeig: A and B must be quasi-triangular (i.e., upper block triangular with 1x1 or 2x2 blocks on the diagonal)\");\n      endif\n    else\n      if (! istriu (A) || ! istriu (B))\n        error (\"ordeig: A and B must both be upper-triangular if either is complex\");\n      endif\n    endif\n  endif\n\n  ## Start of algorithm\n  lambda = zeros (n, 1);\n\n  i = 1;\n  while (i <= n)\n    if (i == n || (A(i+1,i) == 0 && B(i+1,i) == 0))\n      lambda(i) = A(i,i) / B(i,i);\n    else\n      a = B(i,i) * B(i+1,i+1);\n      b = - (A(i,i) * B(i+1,i+1) + A(i+1,i+1) * B(i,i));\n      c = A(i,i) * A(i+1,i+1) - ...\n          (A(i,i+1) - B(i,i+1)) * (A(i+1,i) - B(i+1,i));\n      if (b > 0)\n        lambda(i) = 2*c / (-b - sqrt (b^2 - 4*a*c));\n        i += 1;\n        lambda(i) = (-b - sqrt (b^2 - 4*a*c)) / 2 / a;\n      else\n        lambda(i) = (-b + sqrt (b^2 - 4*a*c)) / 2 / a;\n        i += 1;\n        lambda(i) = 2*c / (-b + sqrt (b^2 - 4*a*c));\n      endif\n    endif\n    i += 1;\n  endwhile\n\nendfunction\n\n## Check whether a matrix is quasi-triangular\nfunction retval = is_quasitri (A)\n\n  if (length (A) <= 2)\n    retval = true;\n  else\n    v = diag (A, -1) != 0;\n    retval = (all (tril (A, -2)(:) == 0) && all (v(1:end-1) + v(2:end) < 2));\n  endif\n\nendfunction\n\n\n%!test\n%! A = toeplitz ([0, 1, 0, 0], [0, -1, 0, 0]);\n%! T = schur (A);\n%! lambda = ordeig (T);\n%! assert (lambda, [1.61803i; -1.61803i; 0.61803i; -0.61803i], 1e-4);\n\n%!test\n%! A = toeplitz ([0, 1, 0, 0], [0, -1, 0, 0]);\n%! B = toeplitz ([0, 0, 0, 1], [0, -1, 0, 2]);\n%! [AA, BB] = qz (A, B, 'real');\n%! assert (isreal (AA) && isreal (BB));\n%! lambda = ordeig (AA, BB);\n%! assert (lambda, [0.5+0.86603i; 0.5-0.86603i; i; -i], 1e-4);\n%! [AA, BB] = qz (A, B, 'complex');\n%! assert (iscomplex (AA) && iscomplex (BB));\n%! lambda = ordeig (AA, BB);\n%! assert (lambda, diag (AA) ./ diag (BB));\n\n## Check trivial 1x1 case\n%!test <*55779>\n%! lambda = ordeig ([6], [2]);\n%! assert (lambda, 3);\n\n## Test input validation\n%!error <Invalid call> ordeig ()\n%!error <A must be a square matrix> ordeig ('a')\n%!error <A must be a square matrix> ordeig ([1, 2, 3])\n%!error <A must be quasi-triangular> ordeig (magic (3))\n%!error <A must be upper-triangular> ordeig ([1, 0; i, 1])\n%!error <B must be a square matrix> ordeig (1, 'a')\n%!error <B must be a square matrix> ordeig (1, [1, 2])\n%!error <A and B must be the same size> ordeig (1, ones (2,2))\n%!error <A and B must be quasi-triangular>\n%! ordeig (triu (magic (3)), magic (3))\n%!error <A and B must both be upper-triangular>\n%! ordeig ([1, 1; 0, 1], [1, 0; i, 1])\n"
  },
  {
    "path": "scripts/linear-algebra/orth.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} orth (@var{A})\n## @deftypefnx {} {@var{B} =} orth (@var{A}, @var{tol})\n## Return an orthonormal basis of the range space of @var{A}.\n##\n## The dimension of the range space is taken as the number of singular values\n## of @var{A} greater than @var{tol}.  If the argument @var{tol} is missing, it\n## is computed as\n##\n## @example\n## max (size (@var{A})) * max (svd (@var{A})) * eps\n## @end example\n## @seealso{null}\n## @end deftypefn\n\nfunction B = orth (A, tol)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isempty (A))\n    B = [];\n    return;\n  endif\n\n  [U, S, V] = svd (A);\n\n  [rows, cols] = size (A);\n\n  [S_nr, S_nc] = size (S);\n\n  if (S_nr == 1 || S_nc == 1)\n    s = S(1);\n  else\n    s = diag (S);\n  endif\n\n  if (nargin == 1)\n    if (isa (A, \"single\"))\n      tol = max (size (A)) * s (1) * eps (\"single\");\n    else\n      tol = max (size (A)) * s (1) * eps;\n    endif\n  endif\n\n  rank = sum (s > tol);\n\n  if (rank > 0)\n    B = -U(:, 1:rank);\n  else\n    B = zeros (rows, 0);\n  endif\n\nendfunction\n\n\n%!test\n%! for i = 1:20\n%!   A = rand (10, 10);\n%!   V = orth (A);\n%!   if (det (A) != 0)\n%!     assert (V'*V, eye (10), 100*eps);\n%!   endif\n%! endfor\n"
  },
  {
    "path": "scripts/linear-algebra/planerot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{G}, @var{y}] =} planerot (@var{x})\n## Compute the Givens rotation matrix for the two-element column vector\n## @var{x}.\n## @tex\n## The Givens matrix is a $2\\times 2$ orthogonal matrix\n## $$\n##  G = \\left[\\matrix{c & s\\cr -s'& c\\cr}\\right]\n## $$\n## such that\n## $$\n##  G \\left[\\matrix{x(1)\\cr x(2)}\\right] = \\left[\\matrix{\\ast\\cr 0}\\right]\n## $$\n## @end tex\n## @ifnottex\n## The Givens matrix is a 2-by-2 orthogonal matrix\n##\n## @example\n## @group\n## @var{G} = [ @var{c} , @var{s}\n##      -@var{s}', @var{c}]\n## @end group\n## @end example\n##\n## @noindent\n## such that\n##\n## @example\n## @var{y} = @var{G} * [@var{x}(1); @var{x}(2)] @equiv{} [*; 0]\n## @end example\n##\n## @end ifnottex\n##\n## Note: The Givens matrix represents a counterclockwise rotation of a 2-D\n## plane and can be used to introduce zeros into a matrix prior to complete\n## factorization.\n## @seealso{givens, qr}\n## @end deftypefn\n\nfunction [G, y] = planerot (x)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! (isvector (x) && numel (x) == 2))\n    error (\"planerot: X must be a 2-element vector\");\n  endif\n\n  G = givens (x(1), x(2));\n  y = G * x(:);\n\nendfunction\n\n\n%!test\n%! x = [3 4];\n%! [g y] = planerot (x);\n%! assert (g, [x(1) x(2); -x(2) x(1)] / sqrt (x(1)^2 + x(2)^2), 2e-8);\n%! assert (y(2), 0, 2e-8);\n\n## Test input validation\n%!error <Invalid call> planerot ()\n%!error <X must be a 2-element vector> planerot (ones (2,2))\n%!error <X must be a 2-element vector> planerot ([0 0 0])\n"
  },
  {
    "path": "scripts/linear-algebra/qzhess.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{aa}, @var{bb}, @var{q}, @var{z}] =} qzhess (@var{A}, @var{B})\n## Compute the Hessenberg-triangular decomposition of the matrix pencil\n## @code{(@var{A}, @var{B})}, returning\n## @code{@var{aa} = @var{q} * @var{A} * @var{z}},\n## @code{@var{bb} = @var{q} * @var{B} * @var{z}}, with @var{q} and @var{z}\n## orthogonal.\n##\n## For example:\n##\n## @example\n## @group\n## [aa, bb, q, z] = qzhess ([1, 2; 3, 4], [5, 6; 7, 8])\n##   @xresult{} aa =\n##       -3.02244  -4.41741\n##        0.92998   0.69749\n##   @xresult{} bb =\n##       -8.60233  -9.99730\n##        0.00000  -0.23250\n##   @xresult{} q =\n##       -0.58124  -0.81373\n##       -0.81373   0.58124\n##   @xresult{} z =\n##      Diagonal Matrix\n##        1   0\n##        0   1\n## @end group\n## @end example\n##\n## The Hessenberg-triangular decomposition is the first step in\n## @nospell{Moler and Stewart's} QZ@tie{}decomposition algorithm.\n##\n## Algorithm taken from @nospell{Golub and Van Loan},\n## @cite{Matrix Computations, 2nd edition}.\n##\n## @seealso{lu, chol, hess, qr, qz, schur, svd}\n## @end deftypefn\n\nfunction [aa, bb, q, z] = qzhess (A, B)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  [na, ma] = size (A);\n  [nb, mb] = size (B);\n  if (na != ma || na != nb || nb != mb)\n    error (\"qzhess: incompatible dimensions\");\n  endif\n\n  ## Reduce to hessenberg-triangular form.\n\n  [q, bb] = qr (B);\n  aa = q' * A;\n  q = q';\n  z = eye (na);\n  for j = 1:(na-2)\n    for i = na:-1:(j+2)\n\n      ## disp ([\"zero out aa(\", num2str(i), \",\", num2str(j), \")\"])\n\n      rot = givens (aa (i-1, j), aa (i, j));\n      aa((i-1):i, :) = rot *aa((i-1):i, :);\n      bb((i-1):i, :) = rot *bb((i-1):i, :);\n       q((i-1):i, :) = rot * q((i-1):i, :);\n\n      ## disp ([\"now zero out bb(\", num2str(i), \",\", num2str(i-1), \")\"])\n\n      rot = givens (bb (i, i), bb (i, i-1))';\n      bb(:, (i-1):i) = bb(:, (i-1):i) * rot';\n      aa(:, (i-1):i) = aa(:, (i-1):i) * rot';\n       z(:, (i-1):i) =  z(:, (i-1):i) * rot';\n\n    endfor\n  endfor\n\n  bb(2, 1) = 0.0;\n  for i = 3:na\n    bb (i, 1:(i-1)) = zeros (1, i-1);\n    aa (i, 1:(i-2)) = zeros (1, i-2);\n  endfor\n\nendfunction\n\n\n%!test\n%! a = [1 2 1 3;\n%!      2 5 3 2;\n%!      5 5 1 0;\n%!      4 0 3 2];\n%! b = [0 4 2 1;\n%!      2 3 1 1;\n%!      1 0 2 1;\n%!      2 5 3 2];\n%! mask = [0 0 0 0;\n%!         0 0 0 0;\n%!         1 0 0 0;\n%!         1 1 0 0];\n%! [aa, bb, q, z] = qzhess (a, b);\n%! assert (inv (q) - q', zeros (4), 2e-8);\n%! assert (inv (z) - z', zeros (4), 2e-8);\n%! assert (q * a * z, aa, 2e-8);\n%! assert (aa .* mask, zeros (4), 2e-8);\n%! assert (q * b * z, bb, 2e-8);\n%! assert (bb .* mask, zeros (4), 2e-8);\n\n%!test\n%! a = [1 2 3 4 5;\n%!      3 2 3 1 0;\n%!      4 3 2 1 1;\n%!      0 1 0 1 0;\n%!      3 2 1 0 5];\n%! b = [5 0 4 0 1;\n%!      1 1 1 2 5;\n%!      0 3 2 1 0;\n%!      4 3 0 3 5;\n%!      2 1 2 1 3];\n%! mask = [0 0 0 0 0;\n%!         0 0 0 0 0;\n%!         1 0 0 0 0;\n%!         1 1 0 0 0;\n%!         1 1 1 0 0];\n%! [aa, bb, q, z] = qzhess (a, b);\n%! assert (inv (q) - q', zeros (5), 2e-8);\n%! assert (inv (z) - z', zeros (5), 2e-8);\n%! assert (q * a * z, aa, 2e-8);\n%! assert (aa .* mask, zeros (5), 2e-8);\n%! assert (q * b * z, bb, 2e-8);\n%! assert (bb .* mask, zeros (5), 2e-8);\n\n## Test input validation\n%!error <Invalid call> qzhess ()\n%!error <Invalid call> qzhess (1)\n"
  },
  {
    "path": "scripts/linear-algebra/rank.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{k} =} rank (@var{A})\n## @deftypefnx {} {@var{k} =} rank (@var{A}, @var{tol})\n## Compute the rank of matrix @var{A}, using the singular value decomposition.\n##\n## The rank is taken to be the number of singular values of @var{A} that are\n## greater than the specified tolerance @var{tol}.  If the second argument is\n## omitted, it is taken to be\n##\n## @example\n## tol = max (size (@var{A})) * sigma(1) * eps;\n## @end example\n##\n## @noindent\n## where @code{eps} is machine precision and @code{sigma(1)} is the largest\n## singular value of @var{A}.\n##\n## The rank of a matrix is the number of linearly independent rows or columns\n## and equals the dimension of the row and column space.  The function\n## @code{orth} may be used to compute an orthonormal basis of the column space.\n##\n## For testing if a system @code{@var{A}*@var{x} = @var{b}} of linear equations\n## is solvable, one can use\n##\n## @example\n## rank (@var{A}) == rank ([@var{A} @var{b}])\n## @end example\n##\n## In this case, @code{@var{x} = @var{A} \\ @var{b}} finds a particular solution\n## @var{x}.  The general solution is @var{x} plus the null space of matrix\n## @var{A}.  The function @code{null} may be used to compute a basis of the\n## null space.\n##\n## Example:\n##\n## @example\n## @group\n## A = [1 2 3\n##      4 5 6\n##      7 8 9];\n## rank (A)\n##   @xresult{} 2\n## @end group\n## @end example\n##\n## @noindent\n## In this example, the number of linearly independent rows is only 2 because\n## the final row is a linear combination of the first two rows:\n##\n## @example\n## A(3,:) == -A(1,:) + 2 * A(2,:)\n## @end example\n##\n## @seealso{null, orth, sprank, svd, eps}\n## @end deftypefn\n\nfunction k = rank (A, tol)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    sigma = svd (A);\n    if (isempty (sigma))\n      tolerance = 0;\n    else\n      if (isa (A, \"single\"))\n        tolerance = max (size (A)) * sigma (1) * eps (\"single\");\n      else\n        tolerance = max (size (A)) * sigma (1) * eps;\n      endif\n    endif\n  else\n    sigma = svd (A);\n    tolerance = tol;\n  endif\n\n  k = sum (sigma > tolerance);\n\nendfunction\n\n\n%!test\n%! A = [1 2 3 4 5 6 7;\n%!      4 5 6 7 8 9 12;\n%!      1 2 3.1 4 5 6 7;\n%!      2 3 4 5 6 7 8;\n%!      3 4 5 6 7 8 9;\n%!      4 5 6 7 8 9 10;\n%!      5 6 7 8 9 10 11];\n%! assert (rank (A), 4);\n\n%!test\n%! A = [1 2 3 4 5 6 7;\n%!      4 5 6 7 8 9 12;\n%!      1 2 3.0000001 4 5 6 7;\n%!      4 5 6 7 8 9 12.00001;\n%!      3 4 5 6 7 8 9;\n%!      4 5 6 7 8 9 10;\n%!      5 6 7 8 9 10 11];\n%! assert (rank (A), 4);\n\n%!test\n%! A = [1 2 3 4 5 6 7;\n%!      4 5 6 7 8 9 12;\n%!      1 2 3 4 5 6 7;\n%!      4 5 6 7 8 9 12.00001;\n%!      3 4 5 6 7 8 9;\n%!      4 5 6 7 8 9 10;\n%!      5 6 7 8 9 10 11];\n%! assert (rank (A), 3);\n\n%!test\n%! A = [1 2 3 4 5 6 7;\n%!      4 5 6 7 8 9 12;\n%!      1 2 3 4 5 6 7;\n%!      4 5 6 7 8 9 12;\n%!      3 4 5 6 7 8 9;\n%!      4 5 6 7 8 9 10;\n%!      5 6 7 8 9 10 11];\n%! assert (rank (A), 3);\n\n%!test\n%! A = eye (100);\n%! assert (rank (A), 100);\n\n%!assert (rank ([]), 0)\n%!assert (rank ([1:9]), 1)\n%!assert (rank ([1:9]'), 1)\n\n%!test\n%! A = [1, 2, 3; 1, 2.001, 3; 1, 2, 3.0000001];\n%! assert (rank (A), 3);\n%! assert (rank (A,0.0009), 1);\n%! assert (rank (A,0.0006), 2);\n%! assert (rank (A,0.00000002), 3);\n"
  },
  {
    "path": "scripts/linear-algebra/rref.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{r} =} rref (@var{A})\n## @deftypefnx {} {@var{r} =} rref (@var{A}, @var{tol})\n## @deftypefnx {} {[@var{r}, @var{k}] =} rref (@dots{})\n## Return the reduced row echelon form of @var{A}.\n##\n## @var{tol} defaults to\n## @code{eps * max (size (@var{A})) * norm (@var{A}, inf)}.\n##\n## The optional return argument @var{k} contains the vector of\n## \"bound variables\", which are those columns on which elimination has been\n## performed.\n##\n## @end deftypefn\n\nfunction [A, k] = rref (A, tol)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ndims (A) > 2)\n    error (\"rref: A must be a 2-dimensional matrix\");\n  endif\n\n  [rows, cols] = size (A);\n\n  if (nargin < 2)\n    if (isa (A, \"single\"))\n      tol = eps (\"single\") * max (rows, cols) * norm (A, inf (\"single\"));\n    else\n      tol = eps * max (rows, cols) * norm (A, inf);\n    endif\n  endif\n\n  used = zeros (1, cols);\n  r = 1;\n  for c = 1:cols\n    ## Find the pivot row\n    [m, pivot] = max (abs (A(r:rows,c)));\n    pivot = r + pivot - 1;\n\n    if (m <= tol)\n      ## Skip column c, making sure the approximately zero terms are\n      ## actually zero.\n      A(r:rows, c) = zeros (rows-r+1, 1);\n    else\n      ## keep track of bound variables\n      used(1, c) = 1;\n\n      ## Swap current row and pivot row\n      A([pivot, r], c:cols) = A([r, pivot], c:cols);\n\n      ## Normalize pivot row\n      A(r, c:cols) = A(r, c:cols) / A(r, c);\n\n      ## Eliminate the current column\n      ridx = [1:r-1, r+1:rows];\n      A(ridx, c:cols) = A(ridx, c:cols) - A(ridx, c) * A(r, c:cols);\n\n      ## Check if done\n      if (r++ == rows)\n        break;\n      endif\n    endif\n  endfor\n  if (nargout > 1)\n    k = find (used);\n  endif\n\nendfunction\n\n\n%!test\n%! a = [1];\n%! [r k] = rref (a);\n%! assert (r, [1], 2e-8);\n%! assert (k, [1], 2e-8);\n\n%!test\n%! a = [1 3; 4 5];\n%! [r k] = rref (a);\n%! assert (rank (a), rank (r), 2e-8);\n%! assert (r, eye (2), 2e-8);\n%! assert (k == [1, 2] || k == [2, 1]);\n\n%!test\n%! a = [1 3; 4 5; 7 9];\n%! [r k] = rref (a);\n%! assert (rank (a), rank (r), 2e-8);\n%! assert (r, eye (3)(:,1:2), 2e-8);\n%! assert (k, [1 2], 2e-8);\n\n%!test\n%! a = [1 2 3; 2 4 6; 7 2 0];\n%! [r k] = rref (a);\n%! assert (rank (a), rank (r), 2e-8);\n%! assert (r, [1 0 (3-7/2); 0 1 (7/4); 0 0 0], 2e-8);\n%! assert (k, [1 2], 2e-8);\n\n%!test\n%! a = [1 2 1; 2 4 2.01; 2 4 2.1];\n%! tol = 0.02;\n%! [r k] = rref (a, tol);\n%! assert (rank (a, tol), rank (r, tol), 2e-8);\n%! tol = 0.2;\n%! [r k] = rref (a, tol);\n%! assert (rank (a, tol), rank (r, tol), 2e-8);\n\n## Test input validation\n%!error <Invalid call> rref ()\n"
  },
  {
    "path": "scripts/linear-algebra/subspace.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{angle} =} subspace (@var{A}, @var{B})\n## Determine the largest principal angle between two subspaces\n## spanned by the columns of matrices @var{A} and @var{B}.\n##\n## Reference:\n## @nospell{Andrew V. Knyazev, Merico E. Argentati},\n## \"Principal Angles between Subspaces in an A-Based Scalar Product:\n## Algorithms and Perturbation Estimates\",\n## @cite{SIAM Journal on Scientific Computing}, @w{Vol.@: 23}, @w{No.@: 6},\n## @w{pp.@: 2008}--2040.\n## @end deftypefn\n\n\nfunction ang = subspace (A, B)\n\n  if (nargin != 2)\n    print_usage ();\n  elseif (ndims (A) != 2 || ndims (B) != 2)\n    error (\"subspace: A and B must be 2-dimensional arrays\");\n  elseif (rows (A) != rows (B))\n    error (\"subspace: column dimensions of A and B must match\");\n  endif\n\n  A = orth (A);\n  B = orth (B);\n  c = A'*B;\n  scos = min (svd (c));\n  if (scos^2 > 1/2)\n    if (columns (A) >= columns (B))\n      c = B - A*c;\n    else\n      c = A - B*c';\n    endif\n    ssin = max (svd (c));\n    ang = asin (min (ssin, 1));\n  else\n    ang = acos (scos);\n  endif\n\nendfunction\n\n\n%!assert (subspace (1, 1), 0)\n%!assert (subspace ([1, 0]', [1, 1; 0, 1]'), 0, 3*eps)\n%!assert (subspace ([1, 0, 1]', [1, 1, 0; 1, -1, 0]'), pi/4, 3*eps)\n%!assert (subspace ([1 5 0 0; -3 2 0 0]', [0 0 4 2; 0 0 4 3]'), pi/2)\n%!assert (subspace ([1 1 1 1; 1 2 3 4]', [1 -1 -1 1]'), pi/2)\n\n%!test\n%! ## For small angle between subspaces\n%! theta = pi/200;\n%! Ry = [cos(theta), 0, sin(theta);0, 1, 0;-sin(theta), 0, cos(theta)];\n%! a = Ry*[3*e, 0, 0]';\n%! b = [1, 1, 0; 1, -1, 0]';\n%! assert (theta, subspace (a, b), eps);\n"
  },
  {
    "path": "scripts/linear-algebra/tensorprod.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{C} =} tensorprod (@var{A}, @var{B}, @var{dimA}, @var{dimB})\n## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, @var{dim})\n## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B})\n## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, \"all\")\n## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, @dots{}, \"NumDimensionsA\", @var{value})\n## Compute the tensor product between numeric tensors @var{A} and @var{B}.\n##\n## The dimensions of @var{A} and @var{B} that are contracted are defined by\n## @var{dimA} and @var{dimB}, respectively.  @var{dimA} and @var{dimB} are\n## scalars or equal length vectors that define the dimensions to match up.\n## The matched dimensions of @var{A} and @var{B} must have the same number of\n## elements.\n##\n## When only @var{dim} is used, it is equivalent to\n## @code{@var{dimA} = @var{dimB} = @var{dim}}.\n##\n## When no dimensions are specified, @code{@var{dimA} = @var{dimB} = []}.  This\n## computes the outer product between @var{A} and @var{B}.\n##\n## Using the @qcode{\"all\"} option results in the inner product between @var{A}\n## and @var{B}.  This requires @code{size (@var{A}) == size (@var{B})}.\n##\n## Use the property-value pair with the property name\n## @nospell{@qcode{\"NumDimensionsA\"}} when @var{A} has trailing singleton\n## dimensions that should be transferred to @var{C}.  The specified @var{value}\n## should be the total number of dimensions of @var{A}.\n##\n## @sc{matlab} Compatibility: Octave does not currently support the\n## @qcode{\"@var{property_name}=@var{value}\"} syntax for the\n## @nospell{@qcode{\"NumDimensionsA\"}} parameter.\n##\n## @seealso{kron, dot, mtimes}\n## @end deftypefn\n\nfunction C = tensorprod (A, B, varargin)\n\n  ## FIXME: shortcut code paths could be added for trivial cases, such as if\n  ##        either A or B are a scalars, null, identity tensors, etc.\n\n  if (nargin < 2 || nargin > 6)\n    print_usage ();\n  endif\n\n  ## Check that A and B are single or double\n  if (! isfloat (A))\n    error (\"tensorprod: A must be a single or double precision array\");\n  endif\n  if (! isfloat (B))\n    error (\"tensorprod: B must be a single or double precision array\");\n  endif\n\n  ## Check for misplaced NumDimensionsA property\n  NumDimensionsA = 0;\n  if (nargin > 2)\n    if (strcmpi (varargin{end}, \"NumDimensionsA\"))\n      error (\"tensorprod: a value for the NumDimensionsA property must be provided\");\n    elseif (strncmpi (arg = inputname (nargin, false), \"NumDimensionsA\", 13))\n      error (\"tensorprod: NumDimensionsA=VALUE syntax is unsupported.  Use syntax 'NumDimensionsA', VALUE\");\n    endif\n  endif\n  ## Check for NumDimensionsA property\n  if (nargin > 3)\n    if (strcmpi (varargin{end-1}, \"NumDimensionsA\"))\n      NumDimensionsA = varargin{end};\n      if (! (isnumeric (NumDimensionsA) && isscalar (NumDimensionsA)))\n        error (\"tensorprod: value for NumDimensionsA must be a numeric scalar\");\n      elseif (! isindex (NumDimensionsA))\n        error (\"tensorprod: value for NumDimensionsA must be a positive integer\");\n      endif\n      nargin = nargin - 2;\n    endif\n  endif\n\n  ndimargs = nargin - 2;\n\n  ## Set dimA and dimB\n  if (ndimargs == 0)\n    ## Calling without dimension arguments\n    dimA = [];\n    dimB = [];\n  elseif (ndimargs == 1)\n    ## Calling with dim or \"all\" option\n    if (isnumeric (varargin{1}))\n      if (! (isvector (varargin{1}) || isnull (varargin{1})))\n        error (\"tensorprod: DIM must be a numeric vector of integers or []\");\n      endif\n      ## Calling with dim\n      dimA = varargin{1}(:).';  # Reshape to row vector\n    elseif (ischar (varargin{1}))\n      if (strcmpi (varargin{1}, \"all\"))\n        if (! size_equal (A, B))\n          error (\"tensorprod: size of A and B must be identical when using the 'all' option\");\n        endif\n      else\n        error (\"tensorprod: unknown option '%s'\", varargin{1});\n      endif\n      ## Calling with \"all\" option\n      dimA = 1:ndims (A);\n    else\n      error (\"tensorprod: third argument must be a numeric vector of integers, [], or 'all'\");\n    endif\n    dimB = dimA;\n  elseif (ndimargs == 2)\n    ## Calling with dimA and dimB\n    if (! (isnumeric (varargin{1})\n           && (isvector (varargin{1}) || isnull (varargin{1}))))\n      error(\"tensorprod: DIMA must be a numeric vector of integers or []\");\n    endif\n\n    if (! (isnumeric (varargin{2})\n           && (isvector (varargin{2}) || isnull (varargin{2}))))\n      error (\"tensorprod: DIMB must be a numeric vector of integers or []\");\n    endif\n\n    if (numel (varargin{1}) != numel (varargin{2}))\n      error (\"tensorprod: an equal number of dimensions must be matched for A and B\");\n    endif\n    dimA = varargin{1}(:).';  # Reshape to row vector\n    dimB = varargin{2}(:).';\n  else\n    ## Something is wrong - try to find the error\n    for i = 1:ndimargs\n      if (ischar (varargin{i}))\n        if (strcmpi (varargin{i}, \"NumDimensionsA\"))\n          error (\"tensorprod: misplaced 'NumDimensionsA' option\");\n        elseif (strcmpi (varargin{i}, \"all\"))\n          error (\"tensorprod: misplaced 'all' option\");\n        else\n          error (\"tensorprod: unknown option '%s'\", varargin{i});\n        endif\n      elseif (! isnumeric (varargin{i}))\n        error (\"tensorprod: optional arguments must be numeric vectors of integers, [], 'all', or 'NumDimensionsA'\");\n      endif\n    endfor\n    error (\"tensorprod: too many dimension inputs given\");\n  endif\n\n  ## Check that dimensions are positive integers ([] will also pass)\n  if (! isindex (dimA) || ! isindex (dimB))\n    error (\"tensorprod: dimensions must be positive integers\");\n  endif\n\n  ## Check that the length of matched dimensions are equal\n  if (any (size (A, dimA) != size (B, dimB)))\n    error (\"tensorprod: matched dimensions of A and B must have the same lengths\");\n  endif\n\n  ## Find size and ndims of A and B\n  ndimsA = max ([ndims(A), max(dimA)]);\n  sizeA = size (A, 1:ndimsA);\n  ndimsB = max ([ndims(B), max(dimB)]);\n  sizeB = size (B, 1:ndimsB);\n\n  ## Take NumDimensionsA property into account\n  if (NumDimensionsA)\n    if (NumDimensionsA < ndimsA)\n      if (ndimargs == 1)\n        error (\"tensorprod: highest dimension of dim must be less than or equal to NumDimensionsA\");\n      elseif (ndimargs == 2)\n        error (\"tensorprod: highest dimension of dimA must be less than or equal to NumDimensionsA\");\n      else\n        error (\"tensorprod: NumDimensionsA cannot be smaller than the number of dimensions of A\");\n      endif\n    elseif (NumDimensionsA > ndimsA)\n      sizeA = [sizeA, ones(1, NumDimensionsA - ndimsA)];\n      ndimsA = NumDimensionsA;\n    endif\n  endif\n\n  ## Interchange the dimension to sum over the end of A and the front of B\n  ## Prepare for A\n  remainDimA = [1:ndimsA];\n  remainDimA(dimA) = [];   # Dimensions of A to keep\n  newDimOrderA = [remainDimA, dimA];  # New dim order [to_keep, to_contract]\n  newSizeA = [prod(sizeA(remainDimA)), prod(sizeA(dimA))]; # tmp 2-D size for A\n\n  ## Prepare for B (See comments for A.\n  ## FIXME: Note that in principle, prod (sizeB (dimB)) should always be equal\n  ## to prod (sizeA (dimA)).  May be able to optimize further here.\n  remainDimB = [1:ndimsB];\n  remainDimB(dimB) = [];   # Dimensions of B to keep\n  newDimOrderB = [remainDimB, dimB];\n  newSizeB = [prod(sizeB(remainDimB)), prod(sizeB(dimB))];\n\n  ## Do reshaping into 2-D array\n  newA = reshape (permute (A, newDimOrderA), newSizeA);\n  newB = reshape (permute (B, newDimOrderB), newSizeB);\n\n  ## Compute\n  C = newA * newB.';\n\n  ## If not an inner product, reshape back to tensor\n  if (! isscalar (C))\n    ## Contribution to size of C from remaining dims\n    remainSizeA = sizeA(remainDimA);\n    remainSizeB = sizeB(remainDimB);\n    dims = [remainSizeA, remainSizeB];\n    if (numel (dims) < 2)\n      dims(2) = 1;  # Return a column vector for Matlab compatibility\n    endif\n    C = reshape (C, dims);\n  endif\n\nendfunction\n\n\n%!assert (tensorprod (2, 3), 6)\n%!assert (tensorprod (2, 3, 1), 6)\n%!assert (tensorprod (2, 3, 2), 6)\n%!assert (tensorprod (2, 3, 10), 6)\n%!assert (tensorprod (2, 3, [1 2]), 6)\n%!assert (tensorprod (2, 3, [1 10]), 6)\n%!assert (tensorprod (2, 3, []), 6)\n%!assert (tensorprod (2, 3, 2, 1), 6)\n%!assert (tensorprod (2, 3, [], []), 6)\n\n%!shared v1, v2, M1, M2, T\n%! v1 = [1, 2];\n%! M1 = [1, 2; 3, 4];\n%! M2 = [1, 2; 3, 4; 5, 6];\n%! T = cat (3, M2, M2);\n\n%!assert (tensorprod (3, v1), reshape ([3, 6], [1, 1, 1, 2]))\n%!assert (tensorprod (v1, 3), [3, 6])\n%!assert (tensorprod (v1, v1, \"all\"), 5)\n%!assert (tensorprod (v1, v1), reshape ([1, 2, 2, 4], [1, 2, 1, 2]))\n%!assert (tensorprod (v1, v1, 1), [1, 2; 2, 4])\n%!assert (tensorprod (v1, v1, 2), 5)\n%!assert (tensorprod (v1, v1, 3), reshape ([1, 2, 2, 4], [1, 2, 1, 2]))\n%!assert (tensorprod (v1, v1, 5), reshape ([1, 2, 2, 4], [1, 2, 1, 1, 1, 2]))\n\n%!assert (tensorprod (M1, v1), cat (4, [1,2;3,4], [2,4;6,8]))\n%!assert (tensorprod (M1, v1'), cat (3, [1,2;3,4], [2,4;6,8]))\n%!assert (tensorprod (v1, M1), reshape ([1 2 3 6 2 4 4 8], [1,2,2,2]))\n%!assert (tensorprod (v1', M1), reshape ([1 2 3 6 2 4 4 8], [2,1,2,2]))\n%!assert (tensorprod (M1, v1', 2, 1), [5; 11])\n%!assert (tensorprod (M1, v1', 4, 4), cat (4, M1, 2*M1))\n%!assert (tensorprod (M1, v1', [1, 3]), [7; 10])\n%!assert (tensorprod (M1, v1', [1, 3], [1, 3]), [7; 10])\n%!assert (tensorprod (M1, v1', [2, 3], [1, 3]), [5; 11])\n%!assert (tensorprod (M1, v1', [2; 3], [1; 3]), [5; 11])\n%!assert (tensorprod (M1, v1', [2; 3], [1, 3]), [5; 11])\n%!assert (tensorprod (M1, v1', [2, 3], [1; 3]), [5; 11])\n%!assert (tensorprod (M1, v1', [], []), cat (3, M1, 2*M1))\n%!assert (tensorprod (M1, M1, \"all\"), 30)\n%!assert (tensorprod (M1, M1, 1), [10, 14; 14, 20])\n%!assert (tensorprod (M1, M1, 2), [5, 11; 11, 25])\n%!assert (tensorprod (M1, M2, 2), [5, 11, 17; 11, 25, 39])\n%!assert (tensorprod (M1, M2, 1, 2), [7, 15, 23; 10, 22, 34])\n%!assert (tensorprod (M1, M2), reshape ([1,3,2,4,3,9,6,12,5,15,10,20,2,6,4, ...\n%!                                      8,4,12,8,16,6,18,12,24], [2,2,3,2]))\n\n%!assert (tensorprod (T, M1),\n%!        reshape([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18,2, ...\n%!                6,10,4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24],\n%!                [3,2,2,2,2]))\n%!assert (tensorprod (T, M1, 2),\n%!        cat (3, [5, 5; 11 11; 17, 17], [11, 11; 25, 25; 39, 39]))\n%!assert (tensorprod (T, M2, 1), cat (3, [35, 35; 44, 44], [44, 44; 56, 56]))\n%!assert (tensorprod (T, M2, 2), cat (3, [5, 5; 11, 11; 17, 17],\n%!                     [11,11;25,25;39,39], [17, 17; 39, 39; 61, 61]))\n%!assert (tensorprod (T, T, \"all\"), 182)\n%!assert (tensorprod (T, T, 1),\n%!        reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56],\n%!                 [2,2,2,2]))\n%!assert (tensorprod (T, T, 2),\n%!        reshape ([5,11,17,5,11,17,11,25,39,11,25,39,17,39,61,17,39,61,5, ...\n%!                 11,17,5,11,17,11,25,39,11,25,39,17,39,61,17,39,61],\n%!                 [3,2,3,2]))\n%!assert (tensorprod (T, T, 3),\n%!        reshape ([2,6,10,4,8,12,6,18,30,12,24,36,10,30,50,20,40,60,4,12, ...\n%!                 20,8,16,24,8,24,40,16,32,48,12,36,60,24,48,72], [3,2,3,2]));\n%!assert (tensorprod (T, T, 10),\n%!        reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18, ...\n%!                 5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10, ...\n%!                 4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36, ...\n%!                 6,18,30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18, ...\n%!                 3,9,15,6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10, ...\n%!                 4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6, ...\n%!                 18,30,12,24,36,6,18,30,12,24,36],\n%!                 [3,2,2,1,1,1,1,1,1,3,2,2]))\n%!assert (tensorprod (T, T, []),\n%!        reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18, ...\n%!                 5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10, ...\n%!                 4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36, ...\n%!                 6,18,30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18, ...\n%!                 3,9,15,6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10, ...\n%!                 4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6, ...\n%!                 18,30,12,24,36,6,18,30,12,24,36],\n%!                 [3,2,2,3,2,2]))\n%!assert (tensorprod (T, T, 2, 3),\n%!        reshape ([3,7,11,3,7,11,9,21,33,9,21,33,15,35,55,15,35,55,6,14, ...\n%!                 22,6,14,22,12,28,44,12,28,44,18,42,66,18,42,66],\n%!                 [3,2,3,2]))\n%!assert (tensorprod (T, T(1:2, 1:2, :), [2, 3],[1, 3]),\n%!        [14, 20; 30, 44; 46, 68])\n%!assert (tensorprod (T, T(1:2, 1:2, :), [3, 2],[1, 3]),\n%!        [12, 18; 28, 42; 44, 66])\n%!assert (tensorprod (T, reshape (T, [2, 2, 3]), 2, 1),\n%!        reshape ([7,15,23,7,15,23,9,23,37,9,23,37,16,36,56,16,36,56,7,15, ...\n%!                 23,7,15,23,9,23,37,9,23,37,16,36,56,16,36,56],\n%!                 [3,2,2,3]))\n%!assert (tensorprod (T, T, [1, 3]), [70, 88; 88, 112])\n%!assert (tensorprod (T, T, [1, 3]), tensorprod (T, T, [3, 1]))\n%!assert (tensorprod (T, reshape (T, [2, 2, 3]), [2, 3], [1, 2]),\n%!        [16, 23, 25; 38, 51, 59; 60, 79, 93])\n\n## NumDimensionsA tests\n%!assert (tensorprod (v1, v1, \"NumDimensionsA\", 2),\n%!        reshape ([1, 2, 2, 4], [1, 2, 1, 2]));\n%!assert (tensorprod (v1, v1, \"numdimensionsa\", 2),\n%!        tensorprod (v1, v1, \"NumDimensionsA\", 2));\n%!assert (tensorprod (v1, v1, \"NumDimensionsA\", 3),\n%!        reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2]));\n%!assert (tensorprod (v1, v1, [], \"NumDimensionsA\", 3),\n%!        reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2]));\n%!assert (tensorprod (v1, v1, [], [], \"NumDimensionsA\", 3),\n%!        reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2]));\n%!assert (tensorprod (v1, v1, \"all\", \"NumDimensionsA\", 3), 5)\n%!assert (tensorprod (M1, v1, 2, \"NumDimensionsA\", 2), [5; 11])\n%!assert (tensorprod (M1, v1, 2, \"NumDimensionsA\", 5), [5; 11])\n%!assert (tensorprod (M1, v1, [2, 3], \"NumDimensionsA\", 5), [5; 11])\n%!assert (tensorprod (M1, M2, \"NumDimensionsA\", 2), reshape ([1,3,2,4,3,9,6, ...\n%!        12,5,15,10,20,2,6,4,8,4,12,8,16,6,18,12,24], [2,2,3,2]))\n%!assert (tensorprod (M1, M2, \"NumDimensionsA\", 3), reshape ([1,3,2,4,3,9,6, ...\n%!        12,5,15,10,20,2,6,4,8,4,12,8,16,6,18,12,24], [2,2,1,3,2]))\n%!assert (tensorprod (T, T, 1, \"NumDimensionsA\", 3),\n%!        reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56],\n%!                 [2,2,2,2]))\n%!assert (tensorprod (T, T, 3, \"NumDimensionsA\", 3),\n%!        reshape ([2,6,10,4,8,12,6,18,30,12,24,36,10,30,50,20,40,60,4,12, ...\n%!                20,8,16,24, 8,24,40,16,32,48,12,36,60,24,48,72],\n%!                [3,2,3,2]))\n%!assert (tensorprod (T, T, 1, \"NumDimensionsA\", 4),\n%!        reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56],\n%!                [2,2,1,2,2]))\n%!assert (tensorprod (T, T, 4, \"NumDimensionsA\", 4),\n%!        reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18,5, ...\n%!                15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10,4,8, ...\n%!                12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36,6,18, ...\n%!                30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15, ...\n%!                6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2, ...\n%!                6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24, ...\n%!                36,6,18,30,12,24,36],\n%!                [3,2,2,3,2,2]))\n\n## Test empty inputs\n%!assert (tensorprod ([], []), zeros (0, 0, 0, 0))\n%!assert (tensorprod ([], 1), [])\n%!assert (tensorprod (1, []), zeros (1, 1, 0, 0))\n%!assert (tensorprod (zeros (0, 0, 0), zeros (0, 0, 0)), zeros (0, 0, 0, 0, 0, 0))\n%!assert (tensorprod ([], [], []), zeros (0, 0, 0, 0))\n%!assert (tensorprod ([], [], 1), [])\n%!assert (tensorprod ([], [], 2), [])\n%!assert (tensorprod ([], [], 3), zeros (0, 0, 0, 0))\n%!assert (tensorprod ([], [], 4), zeros (0, 0, 1, 0, 0))\n%!assert (tensorprod ([], [], 5), zeros (0, 0, 1, 1, 0, 0))\n%!assert (tensorprod ([], [], 3, \"NumDimensionsA\", 4), zeros (0, 0, 1, 0, 0))\n%!assert (tensorprod ([], [], 3, 4, \"NumDimensionsA\", 5), zeros (0, 0, 1, 1, 0, 0))\n\n%!test <*66950>\n%! T = ones (3,3,3);\n%! A = eye (3);\n%! TA = tensorprod (T,A, [1,2]);\n%! assert (TA, 3 * ones (3, 1));\n\n%!test <*66950>\n%! T = ones (3,3);\n%! A = ones (3,3,3,3);\n%! TA = tensorprod (T,A, [1,2], [3,4]);\n%! assert (TA, 9 * ones (3, 3));\n\n%!test <*66950>\n%! T = ones (3,3,3);\n%! A = ones (3,3,3,3);\n%! TA = tensorprod (T,A, [1,2,3], [2,3,4]);\n%! assert (TA, 27 * ones (3, 1));\n\n## Test input validation\n%!error <Invalid call> tensorprod ()\n%!error <Invalid call> tensorprod (1)\n%!error <Invalid call> tensorprod (1,2,3,4,5,6,7)\n%!error <A must be a single or double precision array> tensorprod (\"foo\", 1)\n%!error <B must be a single or double precision array> tensorprod (1, \"bar\")\n%!error <A must be a single or double precision array> tensorprod (int32(1), 1)\n%!error <B must be a single or double precision array> tensorprod (1, int32(1))\n%!error <value for the NumDimensionsA property must be provided> tensorprod (1, 1, \"NumDimensionsA\")\n%!error <NumDimensionsA=VALUE syntax is unsupported> tensorprod (1, 1, NumDimensionsA=1)\n%!error <value for NumDimensionsA must be a numeric scalar> tensorprod (1, 1, 2, 1, \"NumDimensionsA\", \"foo\")\n%!error <value for NumDimensionsA must be a numeric scalar> tensorprod (1, 1, 2, 1, \"NumDimensionsA\", [1 2])\n%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, \"NumDimensionsA\", -1)\n%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, \"NumDimensionsA\", 0)\n%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, \"NumDimensionsA\", 1.5)\n%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, \"NumDimensionsA\", NaN)\n%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, \"NumDimensionsA\", Inf)\n%!error <DIM must be a numeric vector of integers or \\[\\]> tensorprod (1, 1, ones (2,2))\n%!error <DIM must be a numeric vector of integers or \\[\\]> tensorprod (1, 1, zeros (0,0,0))\n%!error <size of A and B must be identical when using the 'all' option> tensorprod (ones (3, 4), ones (4, 3), \"all\")\n%!error <unknown option 'foo'> tensorprod (1, 1, \"foo\")\n%!error <third argument must be a numeric vector of integers, \\[\\], or 'all'> tensorprod (1, 1, {})\n%!error <DIMA must be a numeric vector of integers or \\[\\]> tensorprod (1, 1, \"foo\", 1)\n%!error <DIMA must be a numeric vector of integers or \\[\\]> tensorprod (1, 1, ones (2,2), 1)\n%!error <DIMA must be a numeric vector of integers or \\[\\]> tensorprod (1, 1, zeros (0,0,0), 1)\n%!error <DIMB must be a numeric vector of integers or \\[\\]> tensorprod (1, 1, 1, \"bar\")\n%!error <DIMB must be a numeric vector of integers or \\[\\]> tensorprod (1, 1, 1, ones (2,2))\n%!error <DIMB must be a numeric vector of integers or \\[\\]> tensorprod (1, 1, 1, zeros (0,0,0))\n%!error <an equal number of dimensions must be matched for A and B> tensorprod (ones (3, 4), ones (4, 3), 1, [1, 2])\n%!error <an equal number of dimensions must be matched for A and B> tensorprod (ones (3, 4), ones (4, 3), 1, [])\n%!error <an equal number of dimensions must be matched for A and B> tensorprod (ones (3, 4), ones (4, 3), [], [1, 2])\n%!error <misplaced 'NumDimensionsA' option> tensorprod (1, 1, \"NumDimensionsA\", 1, 1)\n%!error <misplaced 'all' option> tensorprod (1, 1, 1, \"all\", 1)\n%!error <unknown option 'foo'> tensorprod (1, 1, 1, \"foo\", 1)\n%!error <optional arguments must be numeric vectors of integers, \\[\\], 'all', or 'NumDimensionsA'> tensorprod (1, 1, 1, {}, 1)\n%!error <too many dimension inputs given> tensorprod (1, 1, 2, 1, 1)\n%!error <too many dimension inputs given> tensorprod (1, 1, 2, 1, 1, 1)\n%!error <dimensions must be positive integers> tensorprod (1, 1, 0)\n%!error <dimensions must be positive integers> tensorprod (1, 1, -1)\n%!error <dimensions must be positive integers> tensorprod (1, 1, 1.5)\n%!error <dimensions must be positive integers> tensorprod (1, 1, NaN)\n%!error <dimensions must be positive integers> tensorprod (1, 1, Inf)\n%!error <matched dimensions of A and B must have the same lengths> tensorprod (ones (3, 4), ones (4, 3), 1)\n%!error <matched dimensions of A and B must have the same lengths> tensorprod (ones (3, 4), ones (4, 3), 1, 1)\n%!error <highest dimension of dim must be less than or equal to NumDimensionsA> tensorprod (1, 1, 5, \"NumDimensionsA\", 4)\n%!error <highest dimension of dimA must be less than or equal to NumDimensionsA> tensorprod (1, 1, 5, 2, \"NumDimensionsA\", 4)\n%!error <NumDimensionsA cannot be smaller than the number of dimensions of A> tensorprod (ones (2, 2, 2), 1, \"NumDimensionsA\", 2)\n"
  },
  {
    "path": "scripts/linear-algebra/trace.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{t} =} trace (@var{A})\n## Compute the trace of @var{A}, the sum of the elements along the main\n## diagonal.\n##\n## The implementation is straightforward: @code{sum (diag (@var{A}))}.\n## @seealso{eig}\n## @end deftypefn\n\nfunction t = trace (A)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ndims (A) > 2)\n    error (\"trace: only valid on 2-D objects\");\n  elseif (isempty (A))\n    t = 0;\n  elseif (isvector (A))\n    t = A(1);\n  else\n    t = sum (diag (A));\n  endif\n\nendfunction\n\n\n%!assert (trace ([1, 2; 3, 4]), 5)\n%!assert (trace ([1, 2; 3, 4; 5, 6]), 5)\n%!assert (trace ([1, 3, 5; 2, 4, 6]), 5)\n%!assert (trace ([]), 0)\n%!assert (trace (rand (1,0)), 0)\n%!assert (trace ([3:10]), 3)\n\n%!error <Invalid call> trace ()\n%!error <only valid on 2-D objects> trace (reshape (1:9,[1,3,3]))\n"
  },
  {
    "path": "scripts/linear-algebra/vech.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{v} =} vech (@var{x})\n## Return the vector obtained by eliminating all superdiagonal elements of\n## the square matrix @var{x} and stacking the result one column above the\n## other.\n##\n## This has uses in matrix calculus where the underlying matrix is symmetric\n## and it would be pointless to keep values above the main diagonal.\n## @seealso{vec}\n## @end deftypefn\n\n## See Magnus and Neudecker, Matrix differential calculus with applications in\n## statistics and econometrics, 1988.\n\nfunction v = vech (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! issquare (x))\n    error (\"vech: X must be square\");\n  endif\n\n  n = rows (x);\n  slices = cellslices (x(:), (1:n) + n*(0:n-1), n*(1:n));\n  v = vertcat (slices{:});\n\nendfunction\n\n\n%!assert (vech ([1, 2, 3; 4, 5, 6; 7, 8, 9]), [1; 4; 7; 5; 8; 9])\n\n## Test input validation\n%!error <Invalid call> vech ()\n%!error <X must be square> vech ([1,2,3;4,5,6])\n"
  },
  {
    "path": "scripts/linear-algebra/vecnorm.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{n} =} vecnorm (@var{A})\n## @deftypefnx {} {@var{n} =} vecnorm (@var{A}, @var{p})\n## @deftypefnx {} {@var{n} =} vecnorm (@var{A}, @var{p}, @var{dim})\n## Return the vector p-norm of the elements of array @var{A} along dimension\n## @var{dim}.\n##\n## The p-norm of a vector is defined as\n## @tex\n## $$ {\\Vert A \\Vert}_p  = \\left[ \\sum_{i=1}^N {| A_i |}^p \\right] ^ {1/p} $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @var{p-norm} (@var{A}, @var{p}) = (sum (abs (@var{A}) .^ @var{p})) ^ (1/@var{p})\n## @end example\n##\n## @end ifnottex\n## The input @var{p} must be a positive scalar.  If omitted it defaults to 2\n## (Euclidean norm or distance).  Other special values of @var{p} are 1\n## (Manhattan norm, sum of absolute values) and @code{Inf} (absolute value of\n## largest element).\n##\n## The input @var{dim} specifies the dimension of the array on which the\n## function operates and must be a positive integer.  If omitted the first\n## non-singleton dimension is used.\n##\n## @seealso{norm}\n## @end deftypefn\n\nfunction n = vecnorm (A, p = 2, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (A))\n    error (\"vecnorm: A must be numeric\");\n  endif\n\n  if (! (isscalar (p) && isreal (p) && p > 0))\n    error (\"vecnorm: P must be positive real scalar or Inf\");\n  endif\n\n  if (nargin < 3)\n    ## Find the first non-singleton dimension.\n    (dim = find (size (A) > 1, 1)) || (dim = 1);\n  elseif (! (isscalar (dim) && isindex (dim)))\n    error (\"vecnorm: DIM must be a positive integer\");\n  endif\n\n  ## Use norm() to calculate the p-norm along dimension dim.\n  C = num2cell (A, dim);\n  n = cellfun (@(x) norm (x(:), p), C);\n\nendfunction\n\n\n%!test\n%! A = [0 1 2; 3 4 5];\n%! c = vecnorm (A);\n%! r = vecnorm (A, 2, 2);\n%! i = vecnorm (A, Inf);\n%! assert (c, [3.0000, 4.1231, 5.3852], 1e-4);\n%! assert (r, [2.2361; 7.0711], 1e-4);\n%! assert (i, [3, 4, 5]);\n%!test\n%! A = [1, 2];\n%! assert (vecnorm (A), 2.2361, 1e-4);\n%!test\n%! A(:, :, 1) = [1, 2];\n%! A(:, :, 2) = [3, 4];\n%! A(:, :, 3) = [5, 6];\n%! ret(:, :, 1) = 2.2361;\n%! ret(:, :, 2) = 5;\n%! ret(:, :, 3) = 7.8102;\n%! assert (vecnorm (A), ret, 1e-4);\n\n## Test input validation\n%!error <Invalid call> vecnorm ()\n%!error <A must be numeric> vecnorm ({1})\n%!error <P must be positive real scalar> vecnorm (1, [1 2])\n%!error <P must be positive real scalar> vecnorm (1, i)\n%!error <P must be positive real scalar> vecnorm (1, -1)\n%!error <P must be positive real scalar> vecnorm (1, 0)\n%!error <DIM must be a positive integer> vecnorm (1, 2, [1 2])\n%!error <DIM must be a positive integer> vecnorm (1, 2, -1)\n%!error <DIM must be a positive integer> vecnorm (1, 2, 0)\n%!error <DIM must be a positive integer> vecnorm (1, 2, 1.5)\n"
  },
  {
    "path": "scripts/miscellaneous/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/miscellaneous/bug_report.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} bug_report ()\n## Display information about how to submit bug reports for Octave.\n## @end deftypefn\n\nfunction bug_report ()\n\n  disp (\" \");\n  disp (\"  Bug reports play an essential role in making Octave\");\n  disp (\"  reliable.  Please use the Octave bug tracker at\");\n  disp (\" \");\n  disp (\"    https://bugs.octave.org\");\n  disp (\" \");\n  disp (\"  to report problems.\");\n  disp (\" \");\n  disp (\"  Please also read the bug reporting guidelines at\");\n  disp (\" \");\n  disp (\"    https://www.octave.org/bugs.html\");\n  disp (\" \");\n  disp (\"  to learn how to submit useful bug reports that will\");\n  disp (\"  help the Octave community diagnose and fix the problem\");\n  disp (\"  quickly and efficiently.\");\n  disp (\" \");\n\nendfunction\n\n\n## Mark file as being tested.  No real test needed for this function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/miscellaneous/bunzip2.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} bunzip2 (@var{bzfile})\n## @deftypefnx {} {} bunzip2 (@var{bzfile}, @var{dir})\n## @deftypefnx {} {@var{filelist} =} bunzip2 (@dots{})\n## Unpack the bzip2 archive @var{bzfile}.\n##\n## If @var{dir} is specified the files are unpacked in this directory rather\n## than the one where @var{bzfile} is located.\n##\n## The optional output @var{filelist} is a list of the uncompressed files.\n## @seealso{bzip2, unpack, gunzip, unzip, untar}\n## @end deftypefn\n\nfunction filelist = bunzip2 (bzfile, dir = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isempty (dir) && ischar (bzfile))\n    dir = fileparts (bzfile);\n  endif\n\n  if (nargout > 0)\n    filelist = unpack (bzfile, dir, \"bz2\");\n  else\n    unpack (bzfile, dir, \"bz2\");\n  endif\n\nendfunction\n\n\n## Tests for this m-file are located in bzip2.m\n## Remove from test statistics\n%!assert (1)\n"
  },
  {
    "path": "scripts/miscellaneous/cast.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} cast (@var{x}, \"@var{type}\")\n## @deftypefnx {} {@var{y} =} cast (@var{x}, \"@var{like}\", @var{var})\n## Convert @var{x} to data type @var{type}.\n##\n## The input @var{x} may be a scalar, vector, or matrix of a class that is\n## convertible to the target class (see below).\n##\n## If a variable @var{var} is specified after @qcode{\"like\"}, @var{x} is\n## converted to the same data type and sparsity attribute.  If @var{var} is\n## complex, @var{x} will be complex, too.\n##\n## @var{var} may be and @var{type} may name any of the following built-in\n## numeric classes:\n##\n## @example\n## @group\n## \"double\"\n## \"single\"\n## \"logical\"\n## \"char\"\n## \"int8\"\n## \"int16\"\n## \"int32\"\n## \"int64\"\n## \"uint8\"\n## \"uint16\"\n## \"uint32\"\n## \"uint64\"\n## @end group\n## @end example\n##\n## The value @var{x} may be modified to fit within the range of the new type.\n##\n## Examples:\n##\n## @example\n## @group\n## cast (-5, \"uint8\")\n##    @xresult{} 0\n## cast (300, \"int8\")\n##    @xresult{} 127\n## @end group\n## @end example\n##\n## Programming Note: This function relies on the object @var{x} having a\n## conversion method named @var{type}.  User-defined classes may implement only\n## a subset of the full list of types shown above.  In that case, it may be\n## necessary to call cast twice in order to reach the desired type.\n## For example, the conversion to double is nearly always implemented, but\n## the conversion to uint8 might not be.  In that case, the following code will\n## work:\n##\n## @example\n## cast (cast (@var{user_defined_val}, \"double\"), \"uint8\")\n## @end example\n##\n## @seealso{typecast, int8, uint8, int16, uint16, int32, uint32, int64, uint64,\n## double, single, logical, char, class, typeinfo}\n## @end deftypefn\n\nfunction y = cast (x, type, var)\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n  endif\n\n  if (! ischar (type))\n    error (\"cast: TYPE must be a string\");\n  endif\n\n  if (strcmp (type, \"like\"))\n    is_like = true;\n    type = class (var);\n  else\n    is_like = false;\n  endif\n\n  if ((! is_like && nargin != 2) || (is_like && nargin != 3))\n    print_usage ();\n  endif\n\n  if (! isnumeric (x) && ! islogical (x) && ! ischar (x))\n    error (\"cast: type conversion from '%s' is not supported\", class (x));\n  endif\n\n  if (! any (strcmp (type, {\"int8\"; \"uint8\"; \"int16\"; \"uint16\"; \"int32\";\n                            \"uint32\"; \"int64\"; \"uint64\"; \"double\"; \"single\";\n                            \"logical\"; \"char\"})))\n    error (\"cast: type conversion to '%s' is not supported\", type);\n  endif\n\n  y = feval (type, x);\n\n  if (is_like)\n    if (issparse (var) && ! issparse (y))\n      ## y is of the same type as var, so it must be convertible to sparse\n      y = sparse (y);\n    elseif (! issparse (var) && issparse (y))\n      y = full (y);\n    endif\n    if (iscomplex (var) || iscomplex (x))\n      y = complex (y);\n    endif\n  endif\n\nendfunction\n\n\n%!assert (cast (single (2.5), \"double\"), 2.5)\n%!assert (cast (2.5, \"single\"), single (2.5))\n%!assert (cast ([5 0 -5], \"logical\"), [true false true])\n%!assert (cast ([65 66 67], \"char\"), \"ABC\")\n%!assert (cast ([-2.5 1.1 2.5], \"int8\"), int8 ([-3 1 3]))\n%!assert (cast ([-2.5 1.1 2.5], \"uint8\"), uint8 ([0 1 3]))\n%!assert (cast ([-2.5 1.1 2.5], \"int16\"), int16 ([-3 1 3]))\n%!assert (cast ([-2.5 1.1 2.5], \"uint16\"), uint16 ([0 1 3]))\n%!assert (cast ([-2.5 1.1 2.5], \"int32\"), int32 ([-3 1 3]))\n%!assert (cast ([-2.5 1.1 2.5], \"uint32\"), uint32 ([0 1 3]))\n%!assert (cast ([-2.5 1.1 2.5], \"int64\"), int64 ([-3 1 3]))\n%!assert (cast ([-2.5 1.1 2.5], \"uint64\"), uint64 ([0 1 3]))\n%!assert (cast (1, \"like\", 2), 1)\n%!assert (cast (1, \"like\", 2i), complex (1))\n%!assert (cast (1, \"like\", speye (2)), sparse (1))\n%!assert (cast (1, \"like\", sparse (2i)), complex (sparse (1)))\n%!assert (cast (single (1), \"like\", speye (2)), sparse (1))\n%!assert (cast (sparse (1), \"like\", 2), 1)\n%!assert (cast (sparse (1), \"like\", 2i), complex (1))\n%!assert (cast (complex (1), \"like\", 2), complex (1))\n%!assert (cast (complex (1), \"like\", single (2)), complex (single (1)))\n%!assert (cast (\"a\", \"like\", \"octave\"), \"a\")\n%!assert (cast (\"a\", \"like\", 1i), complex (97))\n\n## Test input validation\n%!error <Invalid call> cast ()\n%!error <Invalid call> cast (1)\n%!error <Invalid call> cast (1, \"double\", 2)\n%!error <TYPE must be a string> cast (1, {\"foobar\"})\n%!error <type conversion from .* not supported> cast ({}, \"double\");\n%!error <type conversion from .* not supported> cast (struct (), \"double\")\n%!error <type conversion to .* not supported> cast (1, \"foobar\")\n%!error <type conversion to .* not supported> cast (1, \"cell\")\n%!error <type conversion to .* not supported> cast (1, \"like\", {})\n%!error <type conversion to .* not supported> cast (1, \"like\", struct ())\n"
  },
  {
    "path": "scripts/miscellaneous/citation.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} citation\n## @deftypefnx {} {} citation @var{package}\n## Display instructions for citing GNU Octave or its packages in publications.\n##\n## When called without an argument, display information on how to cite the core\n## GNU Octave system.\n##\n## When given a package name @var{package}, display information on citing the\n## specific named package.  Note that some packages may not yet have\n## instructions on how to cite them.\n##\n## The GNU Octave developers and its active community of package authors have\n## invested a lot of time and effort in creating GNU Octave as it is today.\n## Please give credit where credit is due and cite GNU Octave and its packages\n## when you use them.\n##\n## @end deftypefn\n\n## Author: Carnë Draug <carandraug+dev@gmail.com>\n## Idea and documentation from R's citation() (also under GPL)\n\nfunction citation (package = \"octave\")\n\n  ## function takes care of validating PACKAGE input\n  display_info_file (\"citation\", package, \"CITATION\");\n\nendfunction\n\n\n## Test input validation\n%!error <citation: PACKAGE must be a string> citation (1)\n%!error <citation: package .* is not installed>\n%! citation (\"__NOT_A_VALID_PKG_NAME__\");\n"
  },
  {
    "path": "scripts/miscellaneous/clearAllMemoizedCaches.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} clearAllMemoizedCaches ()\n## Clear all memoized caches.\n##\n## Memoization maintains internal tables of which functions have been called\n## with which inputs.  This function clears those tables to free memory,\n## or for a fresh start.\n##\n## @seealso{memoize}\n## @end deftypefn\n\nfunction clearAllMemoizedCaches ()\n\n  __memoize__ ();\n\nendfunction\n\n\n## Mark file as being tested.  No real test needed for this function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/miscellaneous/clearvars.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} clearvars\n## @deftypefnx {} {} clearvars @var{pattern} @dots{}\n## @deftypefnx {} {} clearvars -regexp @var{pattern} @dots{}\n## @deftypefnx {} {} clearvars @dots{} -except @var{pattern} @dots{}\n## @deftypefnx {} {} clearvars @dots{} -except -regexp @var{pattern} @dots{}\n## @deftypefnx {} {} clearvars -global @dots{}\n## Delete the variables matching the given @var{pattern}s from memory.\n##\n## The @var{pattern} may contain the following special characters:\n##\n## @table @code\n## @item ?\n## Match any single character.\n##\n## @item *\n## Match zero or more characters.\n##\n## @item [ @var{list} ]\n## Match the list of characters specified by @var{list}.  If the first\n## character is @code{!} or @code{^}, match all characters except those\n## specified by @var{list}.  For example, the pattern @code{[a-zA-Z]} will\n## match all lowercase and uppercase alphabetic characters.\n## @end table\n##\n## If the @option{-regexp} option is given then subsequent patterns are treated\n## as regular expressions and any matches will be cleared.\n##\n## If the @option{-except} option is given then subsequent patterns select\n## variables that will @strong{not} be cleared.\n##\n## If the @option{-global} option is given then all patterns will be applied\n## to global variables rather than local variables.\n##\n## When called with no arguments, @code{clearvars} deletes all local variables.\n##\n## Example Code:\n##\n## Clear all variables starting with @qcode{'x'} and the specific variable\n## @qcode{\"foobar\"}\n##\n## @example\n## clearvars x* foobar\n## @end example\n##\n## Clear the specific variable @qcode{\"foobar\"} and use regular expressions to\n## clear all variables starting with @qcode{'x'} or @qcode{'y'}.\n##\n## @example\n## clearvars foobar -regexp ^x ^y\n## @end example\n##\n## Clear all variables except for @qcode{\"foobar\"}\n##\n## @example\n## clearvars -except foobar\n## @end example\n##\n## Clear all variables beginning with @qcode{\"foo\"}, except for those ending\n## in @qcode{\"bar\"}\n##\n## @example\n## clearvars foo* -except -regexp bar$\n## @end example\n##\n## @seealso{clear, who, whos, exist}\n## @end deftypefn\n\nfunction clearvars (varargin)\n\n  numvar = 0;\n  global_mode = false;\n  except_mode = false;\n  regexp_mode = false;\n\n  ## Parse arguments\n  for cellarg = varargin\n    arg = cellarg{1};\n\n    ## Parse options\n    if (strcmp (arg, \"-global\"))\n      if (numvar > 0)\n        error (\"clearvars: '-global' must be the first option when present\");\n      endif\n      global_mode = true;\n      continue;\n    elseif (strcmp (arg, \"-except\"))\n      if (except_mode)\n        error (\"clearvars: '-except' may only be specified once\");\n      endif\n      except_mode = true;\n      regexp_mode = false;\n      continue;\n    elseif (strcmp (arg, \"-regexp\"))\n      regexp_mode = true;\n      continue;\n    endif\n\n    ## Parse patterns\n    numvar += 1;\n    vars(numvar).except = except_mode;\n    if (! regexp_mode)\n      vars(numvar).var_name = [ '\\<' regexptranslate(\"wildcard\", arg) '\\>' ];\n    else\n      vars(numvar).var_name = arg;\n    endif\n\n  endfor\n\n  if (global_mode)\n    varlist = evalin (\"caller\", \"who ('global')\");\n  else\n    varlist = evalin (\"caller\", \"who ()\");\n  endif\n\n  ## evalin will cause the automatic creation of 'ans' variable (bug #53339).\n  ## Determine if it needs to be removed at the end of the function.\n  clear_ans = ! any (strcmp (varlist, \"ans\"));\n\n  if (numvar == 0 || all ([vars.except]))\n    ## For wildcard, select all variables in list\n    idx_clear = true (numel (varlist), 1);\n  else\n    ptn = strjoin ({ vars(! [vars.except]).var_name }, '|');\n    idx_clear = ! cellfun ('isempty', regexp (varlist, ptn));\n  endif\n\n  if (numvar > 0 && any ([vars.except]))\n    ptn = strjoin ({ vars([vars.except]).var_name }, '|');\n    idx_except = ! cellfun ('isempty', regexp (varlist, ptn));\n    idx_clear(idx_except) = false;\n  endif\n\n  varlist = varlist(idx_clear);\n  names = strjoin (varlist, \"', '\");\n\n  if (! isempty (names))\n    if (global_mode)\n      evalin (\"caller\", [\"clear ('-global', '\", names, \"')\"]);\n    else\n      evalin (\"caller\", [\"clear ('\", names, \"')\"]);\n    endif\n  endif\n\n  ## Clean up automatic variable \"ans\" if necessary\n  if (clear_ans)\n    evalin (\"caller\", \"clear ('ans')\");\n  endif\n\nendfunction\n\n\n## Tests must be done in a function namespace;\n## Otherwise, they interfere with the BIST environment itself.\n%!function __test_local_vars__ ()\n%!  global x y z\n%!  a = 1; b = 2; c = 3;\n%!  assert (all (ismember ({\"a\"; \"b\"; \"c\"}, who ())));\n%!  ## Test 0-argument form\n%!  clearvars\n%!  assert (isempty (who ()));\n%!\n%!  a = 1; a2 = 2; a33 = 3;\n%!  ## Test special wildcard pattern\n%!  clearvars a?3\n%!  assert (isempty (who (\"a33\")));\n%!\n%!  a33 = 3;\n%!  ## Test -regexp option\n%!  clearvars -regexp 2 3$\n%!  assert (who (\"a*\"), {\"a\"});\n%!\n%!  a = 1; a2 = 2; a33 = 3;\n%!  ## Test -except option\n%!  clearvars a* -except a33\n%!  assert (who (\"a\", \"a2\", \"a33\"), {\"a33\"});\n%!\n%!  ## Test that non-regexp patterns only select full words\n%!  clearvars a3\n%!  assert (who (\"a33\"), {\"a33\"});\n%!endfunction\n\n%!function __test_global_vars__ ()\n%!  global x y z\n%!  a = 1; b = 2; c = 3;\n%!  assert (all (ismember ({\"x\"; \"y\"; \"z\"}, who (\"global\"))));\n%!  clearvars -global\n%!  assert (isempty (who (\"global\")));\n%!\n%!  global x y z\n%!  clearvars -global -regexp ^y\n%!  assert (! any (strcmp (\"y\", who (\"global\"))));\n%!endfunction\n\n## Run BIST test functions\n%!test __test_local_vars__ ();\n%!test __test_global_vars__ ();\n\n## Test input validation\n%!error <'-global' must be the first option> clearvars (\"ans\", \"-global\")\n%!error <'-except' may only be specified once> clearvars (\"-except\", \"-except\")\n\n%!test\n%!  clear -global x y z;  # cleanup after test\n"
  },
  {
    "path": "scripts/miscellaneous/compare_versions.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} compare_versions (@var{v1}, @var{v2}, @var{operator})\n## Compare two version strings using the given @var{operator}.\n##\n## This function assumes that versions @var{v1} and @var{v2} are arbitrarily\n## long strings made of numeric and period characters possibly followed by an\n## arbitrary string (e.g., @qcode{\"1.2.3\"}, @qcode{\"0.3\"}, @qcode{\"0.1.2+\"},\n## or @qcode{\"1.2.3.4-test1\"}).\n##\n## The version is first split into numeric and character portions and then\n## the parts are padded to be the same length (i.e., @qcode{\"1.1\"} would be\n## padded to be @qcode{\"1.1.0\"} when being compared with @qcode{\"1.1.1\"}, and\n## separately, the character parts of the strings are padded with nulls).\n##\n## The operator can be any logical operator from the set\n##\n## @itemize @bullet\n## @item\n## @qcode{\"==\"}\n## equal\n##\n## @item\n## @qcode{\"<\"}\n## less than\n##\n## @item\n## @qcode{\"<=\"}\n## less than or equal to\n##\n## @item\n## @qcode{\">\"}\n## greater than\n##\n## @item\n## @qcode{\">=\"}\n## greater than or equal to\n##\n## @item @qcode{\"!=\"}, @qcode{\"~=\"}\n## not equal\n##\n## @end itemize\n##\n## Note that version @qcode{\"1.1-test2\"} will compare as greater than\n## @qcode{\"1.1-test10\"}.  Also, since the numeric part is compared first,\n## @qcode{\"a\"} compares less than @qcode{\"1a\"} because the second string\n## starts with a numeric part even though @code{double (\"a\")} is greater than\n## @code{double (\"1\").}\n## @end deftypefn\n\nfunction tf = compare_versions (v1, v2, operator)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  ## Make sure that the version numbers are valid.\n  if (! (ischar (v1) && ischar (v2)))\n    error (\"compare_versions: version numbers V1 and V2 must be strings\");\n  elseif (rows (v1) != 1 || rows (v2) != 1)\n    error (\"compare_versions: version numbers V1 and V2 must be a single row\");\n  endif\n\n  ## check and make sure that the operator is valid\n  if (! ischar (operator))\n    error (\"compare_versions: OPERATOR must be a string\");\n  elseif (numel (operator) > 2)\n    error (\"compare_versions: OPERATOR must be 1 or 2 characters long\");\n  endif\n\n  ## trim off any character data that is not part of a normal version number\n  v1firstchar = find (! (isdigit (v1) | v1 == \".\"), 1);\n  v2firstchar = find (! (isdigit (v2) | v2 == \".\"), 1);\n\n  if (isempty (v1firstchar))\n    v1c = \"\";\n    v1nochar = v1;\n  else\n    v1c = v1(v1firstchar:end);\n    v1nochar = v1(1:v1firstchar-1);\n  endif\n  if (isempty (v2firstchar))\n    v2c = \"\";\n    v2nochar = v2;\n  else\n    v2c = v2(v2firstchar:end);\n    v2nochar = v2(1:v2firstchar-1);\n  endif\n\n  v1n = str2double (ostrsplit (v1nochar, \".\")');\n  if (isnan (v1n))\n    v1n = [];\n  endif\n  v2n = str2double (ostrsplit (v2nochar, \".\")');\n  if (isnan (v2n))\n    v2n = [];\n  endif\n\n  if (isempty (v1n) && isempty (v1c))\n    error (\"compare_versions: version string V1 is not valid: %s\", v1);\n  elseif (isempty (v2n) && isempty (v2c))\n    error (\"compare_versions: version string V2 is not valid: %s\", v2);\n  endif\n\n  ## Assume any additional elements would be 0 if one is longer than the other.\n  maxnumlen = max ([length(v1n) length(v2n)]);\n  v1n(end+1:maxnumlen) = 0;\n  v2n(end+1:maxnumlen) = 0;\n\n  ## Assume any additional character elements would be 0,\n  ## if one is longer than the other.\n  maxcharlen = max ([length(v1c), length(v2c)]);\n  v1c(end+1:maxcharlen) = \"\\0\";\n  v2c(end+1:maxcharlen) = \"\\0\";\n\n  ## Determine the operator.\n  equal_op = any (operator == \"=\");\n  not_op = any (operator == \"!\" | operator == \"~\");\n  lt_op = any (operator == \"<\");\n  gt_op = any (operator == \">\");\n\n  ## Make sure that we don't have conflicting operators.\n  if (gt_op && lt_op)\n    error (\"compare_versions: OPERATOR cannot contain both greater and less than symbols\");\n  elseif ((gt_op || lt_op) && not_op)\n    error (\"compare_versions: OPERATOR cannot contain not and greater than or less than symbols\");\n  elseif (strcmp (operator, \"=\"))\n    error ('compare_versions: equality OPERATOR is \"==\", not \"=\"');\n  elseif (! (equal_op || not_op || lt_op || gt_op))\n    error (\"compare_versions: no valid OPERATOR specified\");\n  endif\n\n  ## Compare the versions (making sure that they're the same shape)\n  vcmp = v1n(:) - v2n(:);\n  vcmp = [vcmp; (v1c - v2c)(:)];\n  if (lt_op)\n    ## so that we only need to check for the output being greater than 1\n    vcmp = -vcmp;\n  endif\n  firstdiff = find (vcmp, 1);\n\n  if (isempty (firstdiff))\n    ## They're equal.\n    tf = equal_op;\n  elseif (lt_op || gt_op)\n    ## They're correctly less than or greater than.\n    tf = (vcmp(firstdiff) > 0);\n  else\n    ## They're not correctly less than or greater than, and they're not equal.\n    tf = false;\n  endif\n\n  ## Reverse the output if not is given.\n  if (not_op)\n    tf = ! tf;\n  endif\n\nendfunction\n\n\n## tests\n## test both equality symbols\n## test arbitrarily long equality\n%!assert (compare_versions (\"1.1.0.0.0\", \"1.1\", \"==\"), true)\n%!assert (compare_versions (\"1\", \"1.1\", \"<\"), true)\n%!assert (compare_versions (\"1.1\", \"1.1\", \"<=\"), true)\n%!assert (compare_versions (\"1.1\", \"1.1.1\", \"<=\"), true)\n%!assert (compare_versions (\"1.23\", \"1.24\", \"=<\"), true)\n## test different length numbers\n%!assert (compare_versions (\"23.2000\", \"23.1\", \">\"), true)\n%!assert (compare_versions (\"0.0.2\", \"0.0.1\", \">=\"), true)\n%!assert (compare_versions (\"0.2\", \"0.0.100\", \"=>\"), true)\n%!assert (compare_versions (\"0.1\", \"0.2\", \"!=\"), true)\n%!assert (compare_versions (\"0.1\", \"0.2\", \"~=\"), true)\n\n## test alphanumeric strings\n%!assert (compare_versions (\"1a\", \"1b\", \"<\"), true)\n%!assert (compare_versions (\"a\", \"1\", \"<\"), true)\n%!assert (compare_versions (\"1a\", \"1b\", \">\"), false)\n%!assert (compare_versions (\"a\", \"1\", \">\"), false)\n%!assert (compare_versions (\"1.1.0a\", \"1.1.0b\", \"==\"), false)\n%!assert (compare_versions (\"1.1.0a\", \"1.1.0b\", \"!=\"), true)\n%!assert (compare_versions (\"1.1.0test\", \"1.1.0b\", \"==\"), false)\n%!assert (compare_versions (\"1.1.0test\", \"1.1.0test\", \"==\"), true)\n\n## make sure that it won't just give true output\n%!assert (compare_versions (\"1\", \"0\", \"==\"), false)\n## test arbitrarily long equality\n%!assert (compare_versions (\"1.1.1.0.0\", \"1.1\", \"==\"), false)\n%!assert (compare_versions (\"1.1\", \"1\", \"<\"), false)\n%!assert (compare_versions (\"2\", \"1.1\", \"<=\"), false)\n%!assert (compare_versions (\"1.1.1\", \"1.1\", \"<=\"), false)\n%!assert (compare_versions (\"1.25\", \"1.24\", \"=<\"), false)\n## test different length numbers\n%!assert (compare_versions (\"23.2\", \"23.100\", \">\"), false)\n%!assert (compare_versions (\"0.0.0.2\", \"0.0.1\", \">=\"), false)\n%!assert (compare_versions (\"0.0.20\", \"0.10.2\", \"=>\"), false)\n%!assert (compare_versions (\"0.1\", \"0.1\", \"!=\"), false)\n%!assert (compare_versions (\"0.1\", \"0.1\", \"~=\"), false)\n\n## Test input validation\n%!error <Invalid call> compare_versions ()\n%!error <Invalid call> compare_versions (1)\n%!error <Invalid call> compare_versions (1,2)\n%!error <V1 and V2 must be strings> compare_versions (0.1, \"0.1\", \"==\")\n%!error <V1 and V2 must be strings> compare_versions (\"0.1\", 0.1, \"==\")\n%!error <V1 and V2 must be a single row> compare_versions ([\"0\";\".\";\"1\"], \"0.1\", \"==\")\n%!error <V1 and V2 must be a single row> compare_versions (\"0.1\", [\"0\";\".\";\"1\"], \"==\")\n%!error <OPERATOR must be a string> compare_versions (\"0.1\", \"0.1\", 1)\n%!error <OPERATOR must be 1 or 2> compare_versions (\"0.1\", \"0.1\", \"==>\")\n%!error <V1 is not valid> compare_versions (\".\", \"0.1\", \"==\")\n%!error <V2 is not valid> compare_versions (\"0.1\", \".\", \"==\")\n\n%!error <cannot contain both greater and less than> compare_versions (\"0.1\", \"0.1\", \"<>\")\n%!error <cannot contain not and greater than> compare_versions (\"0.1\", \"0.1\", \"!>\")\n%!error <cannot contain not and greater than> compare_versions (\"0.1\", \"0.1\", \"!<\")\n%!error <equality OPERATOR is \"==\"> compare_versions (\"0.1\", \"0.1\", \"=\")\n%!error <no valid OPERATOR> compare_versions (\"0.1\", \"0.1\", \"aa\")\n"
  },
  {
    "path": "scripts/miscellaneous/computer.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} computer ()\n## @deftypefnx {} {@var{comp} =} computer ()\n## @deftypefnx {} {[@var{comp}, @var{maxsize}] =} computer ()\n## @deftypefnx {} {[@var{comp}, @var{maxsize}, @var{endian}] =} computer ()\n## @deftypefnx {} {@var{arch} =} computer (\"arch\")\n## Print or return a string of the form @var{cpu}-@var{vendor}-@var{os} that\n## identifies the type of computer that Octave is running on.\n##\n## If invoked with an output argument, the value is returned instead of\n## printed.  For example:\n##\n## @example\n## @group\n## computer ()\n##    @print{} x86_64-pc-linux-gnu\n##\n## mycomp = computer ()\n##    @xresult{} mycomp = x86_64-pc-linux-gnu\n## @end group\n## @end example\n##\n## If two output arguments are requested, also return the maximum number of\n## elements for an array.  This will depend on whether Octave has been\n## compiled with 32-bit or 64-bit index vectors.\n##\n## If three output arguments are requested, also return the byte order of the\n## current system as a character (@qcode{\"B\"} for big-endian or @qcode{\"L\"}\n## for little-endian).\n##\n## If the argument @qcode{\"arch\"} is specified, return a string indicating the\n## architecture of the computer on which Octave is running.\n##\n## Results may be different if Octave was invoked with the --traditional\n## option.\n## @seealso{isunix, ismac, ispc}\n## @end deftypefn\n\nfunction [comp, maxsize, endian] = computer (arch)\n\n  if (nargin == 1 && ! strcmpi (arch, \"arch\"))\n    error ('computer: \"arch\" is only valid argument');\n  endif\n\n  canonical_host_type = __octave_config_info__ (\"canonical_host_type\");\n  traditional = __traditional__ ();\n  enable_64 = __octave_config_info__ (\"ENABLE_64\");\n  host_parts = ostrsplit (canonical_host_type, \"-\");\n\n  if (nargin == 0)\n\n    host = \"\";\n    if (traditional && enable_64)\n      if (ismac ())\n        host = \"MACI64\";\n      elseif (ispc ())\n        host = \"PCWIN64\";\n      elseif (strcmp ([host_parts{3} \"-\" host_parts{1}], \"linux-x86_64\"))\n        host = \"GLNXA64\";\n      endif\n    endif\n    if (isempty (host))\n      host = canonical_host_type;\n    elseif (strcmp (host, \"unknown\"))\n      host = \"Hi Dave, I'm a HAL-9000\";\n    endif\n\n    if (nargout == 0)\n      disp (host);\n    else\n      comp = host;\n      if (nargout > 1)\n        if (enable_64)\n          if (traditional)\n            maxsize = 2^48-1;\n          else\n            maxsize = 2^63-1;\n          endif\n        else\n          maxsize = 2^31-1;\n        endif\n      endif\n      if (nargout > 2)\n        if (__octave_config_info__ (\"words_big_endian\"))\n          endian = \"B\";\n        elseif (__octave_config_info__ (\"words_little_endian\"))\n          endian = \"L\";\n        else\n          endian = \"?\";\n        endif\n      endif\n    endif\n\n  else\n\n    ## \"arch\" case.\n    comp = \"\";\n    if (traditional && enable_64)\n      if (ismac ())\n        comp = \"maci64\";\n      elseif (ispc ())\n        comp = \"win64\";\n      elseif (strcmp ([host_parts{3} \"-\" host_parts{1}], \"linux-x86_64\"))\n        comp = \"glnxa64\";\n      endif\n    endif\n    if (isempty (comp))\n      comp = [host_parts{3} \"-\" host_parts{1}];\n      if (numel (host_parts) == 4)\n        comp = [host_parts{4} \"-\" comp];\n      endif\n    endif\n\n  endif\n\nendfunction\n\n\n%!assert (ischar (computer ()))\n%!assert (computer (), __octave_config_info__ (\"canonical_host_type\"))\n%!assert (ischar (computer (\"arch\")))\n\n%!error computer (1,2)\n%!error <\"arch\" is only valid argument> computer (\"xyz\")\n"
  },
  {
    "path": "scripts/miscellaneous/copyfile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} copyfile @var{f1} @var{f2}\n## @deftypefnx {} {} copyfile @var{f1} @var{f2} f\n## @deftypefnx {} {} copyfile (@var{f1}, @var{f2})\n## @deftypefnx {} {} copyfile (@var{f1}, @var{f2}, 'f')\n## @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} copyfile (@dots{})\n## Copy the source file(s) or directory @var{f1} to the destination @var{f2}.\n##\n## The name @var{f1} may contain globbing patterns, or may be a cell array of\n## strings.  If @var{f1} expands to multiple filenames, @var{f2} must be a\n## directory.\n##\n## When the force flag @qcode{'f'} is given any existing files will be\n## overwritten without prompting.\n##\n## If successful, @var{status} is logical 1, and @var{msg}, @var{msgid} are\n## empty character strings (\"\").  Otherwise, @var{status} is logical 0,\n## @var{msg} contains a system-dependent error message, and @var{msgid}\n## contains a unique message identifier.  Note that the status code is exactly\n## opposite that of the @code{system} command.\n## @seealso{movefile, rename, unlink, delete, glob}\n## @end deftypefn\n\nfunction [status, msg, msgid] = copyfile (f1, f2, force)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  max_cmd_line = 8000;  # Windows cmd.exe is the most restrictive at 8,191.\n  sts = true;\n  msg = \"\";\n  msgid = \"\";\n\n  is_windows = (ispc () && isempty (file_in_path (getenv (\"PATH\"), \"cp.exe\")));\n  ## FIXME: Maybe use the same method as in ls to allow users control\n  ##        over the command that is executed.\n  if (is_windows)\n    cmd = \"cmd /C xcopy /E\";\n    cmd_force_flag = \"/Y\";\n  else\n    cmd = \"cp -r\";\n    cmd_force_flag = \"-f\";\n  endif\n\n  ## Input type check.\n  if (ischar (f1))\n    f1 = cellstr (f1);\n  elseif (! iscellstr (f1))\n    error (\"copyfile: F1 must be a string or a cell array of strings\");\n  endif\n  if (! ischar (f2))\n    error (\"copyfile: F2 must be a string\");\n  endif\n\n  if (nargin == 3 && strcmp (force, \"f\"))\n    cmd = [cmd \" \" cmd_force_flag];\n  endif\n\n  ## If f1 has more than 1 element then f2 must be a directory\n  isdir_f2 = isfolder (f2);\n  if (numel (f1) > 1 && ! isdir_f2)\n    if (nargout == 0)\n      error (\"copyfile: when copying multiple files, F2 must be a directory\");\n    else\n      status = false;\n      msg = \"when copying multiple files, F2 must be a directory\";\n      msgid = \"copyfile\";\n      return;\n    endif\n  endif\n\n  ## Protect the filename(s).\n  if (ispc ())\n    f1 = __wglob__ (f1);\n  else\n    f1 = glob (f1);\n  endif\n  if (isempty (f1))\n    if (nargout == 0)\n      error (\"copyfile: no files to move\");\n    else\n      status = false;\n      msg = \"no files to move\";\n      msgid = \"copyfile\";\n      return;\n    endif\n  endif\n  ## Protect possible whitespace in filenames with double quotes.\n  p1 = sprintf ('\"%s\" ', f1{:});\n  p2 = tilde_expand (f2);\n\n  if (isdir_f2 && length (p1) > max_cmd_line)\n    ## Divide list of files and call shell with smaller command lines.\n    l2 = length (p2) + length (cmd) + 6;\n    while (! isempty (f1))\n      p1 = sprintf ('\"%s\"', f1{1});\n      f1(1) = [];\n      while (! isempty (f1)\n             && (length (p1) + length (f1{1}) + l2 < max_cmd_line))\n        p1 = sprintf ('%s \"%s\"', p1, f1{1});\n        f1(1) = [];\n      endwhile\n\n      if (is_windows)\n        p1 = strrep (p1, '\\', '/');\n        p2 = strrep (p2, '\\', '/');\n      endif\n\n      ## Copy the files.\n      [err, msg] = system (sprintf ('%s %s \"%s\"', cmd, p1, p2));\n      if (err != 0)\n        sts = false;\n        msgid = \"copyfile\";\n        break;\n      endif\n    endwhile\n\n  else\n    ## cmd is short enough to be executed in one call to shell.\n    if (is_windows)\n      p1 = strrep (p1, '\\', '/');\n      p2 = strrep (p2, '\\', '/');\n    endif\n\n    ## Copy the files.\n    [err, msg] = system (sprintf ('%s %s \"%s\"', cmd, p1, p2));\n    if (err != 0)\n      sts = false;\n      msgid = \"copyfile\";\n    endif\n  endif\n\n  if (nargout == 0)\n    if (! sts)\n      error (\"copyfile: operation failed: %s\", msg);\n    endif\n  else\n    status = sts;\n  endif\n\nendfunction\n\n\n%!test\n%! unwind_protect\n%!   f1 = tempname ();\n%!   tmp_var = pi;\n%!   save (f1, \"tmp_var\");\n%!   f2 = tempname ();\n%!   assert (copyfile (f1, f2));\n%!   assert (exist (f2, \"file\"));\n%!   fid = fopen (f1, \"rb\");\n%!   assert (fid >= 0);\n%!   orig_data = fread (fid);\n%!   fclose (fid);\n%!   fid = fopen (f2, \"rb\");\n%!   assert (fid >= 0);\n%!   new_data = fread (fid);\n%!   fclose (fid);\n%!   if (orig_data != new_data)\n%!     error (\"copied file not equal to original file!\");\n%!   endif\n%! unwind_protect_cleanup\n%!   delete ([f1, '*']);\n%!   delete (f2);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> copyfile ()\n%!error <Invalid call> copyfile (1)\n%!error <F1 must be a string> copyfile (1, \"foobar\")\n%!error <F2 must be a string> copyfile (\"foobar\", 1)\n%!error <F2 must be a directory> copyfile ({\"a\", \"b\"}, \"%_NOT_A_DIR_%\")\n%!error <no files to move> copyfile (\"%_NOT_A_FILENAME1_%\", \"%_NOT_A_FILENAME2_%\")\n"
  },
  {
    "path": "scripts/miscellaneous/delete.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} delete @var{file}\n## @deftypefnx {} {} delete @var{file1} @var{file2} @dots{}\n## @deftypefnx {} {} delete (@var{file})\n## @deftypefnx {} {} delete (@var{file1}, @var{file2}, @dots{})\n## @deftypefnx {} {} delete (@var{handle})\n## Delete the named file or graphics handle.\n##\n## @var{file} may contain globbing patterns such as @samp{*}.  Multiple files\n## to be deleted may be specified in the same function call.\n##\n## @var{handle} may be a scalar or vector of graphic handles to delete.\n##\n## Programming Note: Deleting graphics objects is the proper way to remove\n## features from a plot without clearing the entire figure.\n## @seealso{clf, cla, unlink, rmdir}\n## @end deftypefn\n\nfunction delete (varargin)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  if (iscellstr (varargin))\n    for arg = varargin\n      if (ispc ())\n        files = __wglob__ (arg{1});\n      else\n        files = glob (arg{1});\n      endif\n      if (isempty (files))\n        warning (\"Octave:delete:no-such-file\", ...\n                 \"delete: no such file: %s\", arg{1});\n      endif\n      for i = 1:length (files)\n        file = files{i};\n        [err, msg] = unlink (file);\n        if (err)\n          warning (\"Octave:delete:unlink-error\", ...\n                   \"delete: %s: %s\", file, msg);\n        endif\n      endfor\n    endfor\n\n  elseif (isscalar (varargin) && all (ishghandle (varargin{1}(:))))\n    ## Delete a graphics object.\n    __go_delete__ (varargin{1});\n\n  else\n    error (\"Octave:delete:unsupported-object\", ...\n           \"delete: first argument must be a filename or graphics handle\");\n  endif\n\nendfunction\n\n\n%!test\n%! unwind_protect\n%!   file = tempname ();\n%!   tmp_var = pi;\n%!   save (file, \"tmp_var\");\n%!   assert (exist (file, \"file\"));\n%!   delete (file);\n%!   assert (! exist (file, \"file\"));\n%! unwind_protect_cleanup\n%!   delete ([file, '*']);\n%! end_unwind_protect\n\n%!test\n%! unwind_protect\n%!   hf = figure (\"visible\", \"off\");\n%!   hl = plot (1:10);\n%!   assert (get (gca, \"children\"), hl);\n%!   delete (hl);\n%!   assert (get (gca, \"children\"), zeros (0,0));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> delete ()\n%!error <first argument must be a filename> delete (struct ())\n"
  },
  {
    "path": "scripts/miscellaneous/dir.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} dir\n## @deftypefnx {} {} dir @var{directory}\n## @deftypefnx {} {[@var{list}] =} dir (@var{directory})\n## Display file listing for directory @var{directory}.\n##\n## If @var{directory} is not specified then list the present working directory.\n##\n## If a return value is requested, return a structure array with the fields\n##\n## @table @asis\n## @item name\n## File or directory name.\n##\n## @item folder\n## Location of file or directory\n##\n## @item date\n## Timestamp of file modification (string value).\n##\n## @item bytes\n## File size in bytes.\n##\n## @item isdir\n## True if name is a directory.\n##\n## @item datenum\n## Timestamp of file modification as serial date number (double).\n##\n## @item statinfo\n## Information structure returned from @code{stat}.\n## @end table\n##\n## If @var{directory} is a filename, rather than a directory, then return\n## information about the named file.  @var{directory} may also be a list rather\n## than a single directory or file.\n##\n## @var{directory} is subject to shell expansion if it contains any wildcard\n## characters @samp{*}, @samp{?}, @samp{[]}.  If these wildcard characters are\n## escaped with a backslash @samp{\\} (e.g., @samp{\\*}) on a POSIX platform,\n## then they are not treated as wildcards, but as the corresponding literal\n## character.  On Windows, it is not possible to escape wildcard characters\n## because backslash @samp{\\} is treated as a file separator.  On Windows, use\n## @code{ls} for file or folder names that contain characters that would be\n## treated as wildcards by @code{dir}.\n##\n## Note that for symbolic links, @code{dir} returns information about the\n## file that the symbolic link points to rather than the link itself.  However,\n## if the link points to a nonexistent file, @code{dir} returns information\n## about the link.\n## @seealso{ls, readdir, glob, what, stat, lstat}\n## @end deftypefn\n\n## FIXME: This is quite slow for large directories.\n##        Perhaps it should be converted to C++?\n\nfunction list = dir (directory = \".\")\n\n  if (! ischar (directory))\n    error (\"dir: DIRECTORY argument must be a string\");\n  endif\n\n  ## Prep the list.\n  info = struct (zeros (0, 1),\n           {\"name\", \"folder\" \"date\", \"bytes\", \"isdir\", \"datenum\", \"statinfo\"});\n\n  if (strcmp (directory, \"*\"))\n    directory = \".\";\n  endif\n  if (strcmp (directory, \".\"))\n    flst = {\".\"};\n    nf = 1;\n    dir_has_wildcard = false;\n  else\n    flst = __wglob__ (directory);\n    nf = numel (flst);\n    dir_has_wildcard = any (directory == '*');  # See Bug #58976.\n  endif\n\n  ## Determine the file list for the case where a single directory is specified.\n  if (nf == 1)\n    fn = flst{1};\n    [st, err, msg] = stat (fn);\n    if (err < 0)\n      warning (\"dir: 'stat (%s)' failed: %s\", fn, msg);\n      nf = 0;\n    elseif (S_ISDIR (st.mode) && ! dir_has_wildcard)\n      flst = readdir (flst{1});\n      nf = numel (flst);\n      flst = strcat ([fn filesep], flst);\n    endif\n  endif\n\n  if (nf > 0)\n\n    fs = regexptranslate (\"escape\", filesep (\"all\"));\n    re = sprintf ('(^.+)[%s]([^%s.]*)([.][^%s]*)?$', fs, fs, fs);\n    last_dir = last_absdir = \"\";\n    info(nf,1).name = \"\";  # pre-declare size of struct array\n\n    ## Collect results.\n    cnt = 0;\n    for i = 1:nf\n      fn = flst{i};\n      [st, err, msg] = lstat (fn);\n      if (err < 0)\n        warning (\"dir: 'lstat (%s)' failed: %s\", fn, msg);\n        continue;\n      else\n        ## If we are looking at a link that points to something,\n        ## return info about the target of the link, otherwise, return\n        ## info about the link itself.\n        if (S_ISLNK (st.mode))\n          [xst, err] = stat (fn);\n          if (! err)\n            st = xst;\n          endif\n        endif\n        tmpdir = regexprep (fn, re, '$1');\n        if (is_same_file (fn, tmpdir))\n          ## regexrep failed to match, no directory component.\n          no_dir = true;\n        else\n          no_dir = false;\n        endif\n        fn = regexprep (fn, re, '$2$3');\n        info(++cnt).name = fn;\n        if (nargout > 0)\n          if (no_dir && ! strcmp (fn, \".\"))\n            tmpdir = \".\";\n          endif\n          if (! is_same_file (last_dir, tmpdir))\n            ## Caching mechanism to speed up function\n            last_dir = tmpdir;\n            last_absdir = canonicalize_file_name (last_dir);\n          endif\n          info(cnt).folder = last_absdir;\n          lt = localtime (st.mtime);\n          info(cnt).date = strftime (\"%d-%b-%Y %T\", lt);\n          info(cnt).bytes = st.size;\n          info(cnt).isdir = S_ISDIR (st.mode);\n          info(cnt).datenum = [lt.year + 1900, lt.mon + 1, lt.mday, ...\n                               lt.hour, lt.min, lt.sec];\n          info(cnt).statinfo = st;\n        endif\n      endif\n    endfor\n    info((cnt+1):end) = [];  # remove any unused entries\n    if (nargout > 0)\n      ## A lot of gymnastics in order to call datenum just once.  2x speed up.\n      dvec = [info.datenum]([[1:6:end]', [2:6:end]', [3:6:end]', ...\n                             [4:6:end]', [5:6:end]', [6:6:end]']);\n      dnum = datenum (dvec);\n      ctmp = mat2cell (dnum, ones (cnt,1), 1);\n      [info.datenum] = ctmp{:};\n    endif\n  endif\n\n  ## Return the output arguments.\n  if (nargout > 0)\n    ## Return the requested structure.\n    list = info;\n  elseif (numel (info) > 0)\n    ## Print the structure to the screen.\n    printf (\"%s\", list_in_columns ({info.name}));\n  else\n    warning (\"dir: nonexistent directory '%s'\", directory);\n  endif\n\nendfunction\n\n\n%!test\n%! orig_dir = pwd ();\n%! tmp_dir = tempname ();\n%! unwind_protect\n%!   assert (mkdir (tmp_dir));\n%!   chdir (tmp_dir);\n%!   fclose (fopen (\"f1\", \"w\"));\n%!   list = dir ();\n%!   assert (isstruct (list) && ! isempty (list));\n%!   assert (fieldnames (list),\n%!           {\"name\"; \"folder\"; \"date\"; \"bytes\"; \"isdir\"; \"datenum\"; \"statinfo\"});\n%!\n%!   if (isunix ())\n%!     idx = find (strcmp ({list.name}, \".\"), 1);\n%!     assert ({list(idx:idx+1).name}, {\".\", \"..\"});\n%!     assert ([list(idx:idx+1).isdir], [true true]);\n%!   endif\n%!\n%!   ## test that specifying a filename works the same as using a directory.\n%!   found = find (! [list.isdir], 1);\n%!   if (! isempty (found))\n%!     list2 = dir (fullfile (list(found).folder, list(found).name));\n%!     assert (list(found), list2);\n%!   endif\n%! unwind_protect_cleanup\n%!   chdir (orig_dir);\n%!   confirm_recursive_rmdir (false, \"local\");\n%!   if (exist (tmp_dir))\n%!     sts = rmdir (tmp_dir, \"s\");\n%!   endif\n%! end_unwind_protect\n\n%!test <*58976>\n%! orig_dir = pwd ();\n%! tmp_dir = tempname ();\n%! unwind_protect\n%!   assert (mkdir (tmp_dir));\n%!   assert (mkdir (fullfile (tmp_dir, \"dir1\")));\n%!   assert (mkdir (fullfile (tmp_dir, \"dir2\")));\n%!   chdir (fullfile (tmp_dir, \"dir1\"));\n%!   fclose (fopen (\"f1\", \"w\"));\n%!   chdir (tmp_dir);\n%!\n%!   ## Wildcard with multiple matches lists directories\n%!   list = dir (fullfile (tmp_dir, \"dir*\"));\n%!   assert (numel (list) == 2);\n%!   assert ({list.name}, {\"dir1\", \"dir2\"});\n%!\n%!   ## Wildcard with single match lists directories\n%!   assert (rmdir (fullfile (tmp_dir, \"dir2\")));\n%!   list = dir (fullfile (tmp_dir, \"dir*\"));\n%!   assert (numel (list) == 1);\n%!   assert ({list.name}, {\"dir1\"});\n%!\n%!   ## No wildcard returns listing of directory contents\n%!   list = dir (fullfile (tmp_dir, \"dir1\"));\n%!   assert (any (strcmp ({list.name}, \"f1\")));\n%! unwind_protect_cleanup\n%!   chdir (orig_dir);\n%!   confirm_recursive_rmdir (false, \"local\");\n%!   if (exist (tmp_dir))\n%!     sts = rmdir (tmp_dir, \"s\");\n%!   endif\n%! end_unwind_protect\n\n%!test <*57666>\n%! orig_dir = pwd ();\n%! tmp_dir = tempname ();\n%! unwind_protect\n%!   assert (mkdir (tmp_dir));\n%!   list = dir (tmp_dir);\n%!   assert (list(1).name, \".\");\n%!   assert (list(1).folder, canonicalize_file_name (tmp_dir));\n%! unwind_protect_cleanup\n%!   if (exist (tmp_dir))\n%!     sts = rmdir (tmp_dir);\n%!   endif\n%! end_unwind_protect\n\n## Test input validation\n%!error <DIRECTORY argument must be a string> dir (1)\n%!warning <nonexistent directory> dir (\"_%UNLIKELY_DIR_NAME%_\");\n"
  },
  {
    "path": "scripts/miscellaneous/dos.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} dos (\"@var{command}\")\n## @deftypefnx {} {@var{status} =} dos (\"@var{command}\")\n## @deftypefnx {} {[@var{status}, @var{text}] =} dos (\"@var{command\"})\n## @deftypefnx {} {[@dots{}] =} dos (\"@var{command}\", \"-echo\")\n## Execute a system command if running under a Windows-like operating system,\n## otherwise do nothing.\n##\n## Octave waits for the external command to finish before returning the exit\n## status of the program in @var{status} and any output in @var{text}.\n##\n## When called with no output argument, or the @qcode{\"-echo\"} argument is\n## given, then @var{text} is also sent to standard output.\n## @seealso{unix, system, isunix, ismac, ispc}\n## @end deftypefn\n\nfunction [status, text] = dos (command, echo_arg)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  status = 1;\n  text = \"\";\n\n  if (ispc ())\n    [status, text] = system (command);\n    if (nargin > 1 || nargout == 0)\n      printf (\"%s\\n\", text);\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! cmd = ls_command ();\n%! [status, output] = dos (cmd);\n%!\n%! if (ispc ())\n%!   [status, output] = dos (cmd);\n%!   assert (status, 0);\n%!   assert (ischar (output));\n%!   assert (! isempty (output));\n%! else\n%!   assert (status, 1);\n%!   assert (output, \"\");\n%! endif\n\n## Test input validation\n%!error <Invalid call> dos ()\n%!error dos (1, 2, 3)\n"
  },
  {
    "path": "scripts/miscellaneous/edit.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} edit @var{name}\n## @deftypefnx {} {} edit @var{field} @var{value}\n## @deftypefnx {} {@var{value} =} edit (\"get\", @var{field})\n## @deftypefnx {} {@var{value} =} edit (\"get\", \"all\")\n## Edit the named function, or change editor settings.\n##\n## If @code{edit} is called with the name of a file or function as its\n## argument it will be opened in the default text editor.  The default editor\n## for the Octave GUI is specified in the Editor tab of Preferences.  The\n## default editor for the CLI is specified by the @code{EDITOR} function.\n##\n## @itemize @bullet\n## @item\n## If the function @var{name} is available in a file on your path, then it\n## will be opened in the editor.  If no file is found, then the m-file\n## variant, ending with @qcode{\".m\"}, will be considered.  If still no file is\n## found, then variants with a leading @qcode{\"@@\"} and then with both a\n## leading @qcode{\"@@\"} and trailing @qcode{\".m\"} will be considered.\n##\n## @item\n## If @var{name} is the name of a command-line function, then an m-file will\n## be created to contain that function along with its current definition.\n##\n## @item\n## If @code{@var{name}.cc} is specified, then it will search for\n## @file{@var{name}.cc} in the path and open it in the editor.  If the file is\n## not found, then a new @file{.cc} file will be created.  If @var{name}\n## happens to be an m-file or command-line function, then the text of that\n## function will be inserted into the .cc file as a comment.\n##\n## @item\n## If @file{@var{name}.ext} is on your path then it will be edited, otherwise\n## the editor will be started with @file{@var{name}.ext} in the current\n## directory as the filename.\n##\n## @strong{Warning:} You may need to clear @var{name} before the new definition\n## is available.  If you are editing a .cc file, you will need to execute\n## @code{mkoctfile @file{@var{name}.cc}} before the definition will be\n## available.\n## @end itemize\n##\n## If @code{edit} is called with @var{field} and @var{value} variables, the\n## value of the control field @var{field} will be set to @var{value}.\n##\n## If an output argument is requested and the first input argument is\n## @code{get} then @code{edit} will return the value of the control field\n## @var{field}.  If the control field does not exist, edit will return a\n## structure containing all fields and values.  Thus, @code{edit (\"get\",\n## @qcode{\"all\"})} returns a complete control structure.\n##\n## The following control fields are used:\n##\n## @table @samp\n## @item author\n## This is the name to put after the \"## Author:\" field of new functions.  By\n## default it guesses from the @code{gecos} field of the password database.\n##\n## @item email\n## This is the e-mail address to list after the name in the author field.  By\n## default it guesses @code{<$LOGNAME@@$HOSTNAME>}, and if @code{$HOSTNAME}\n## is not defined it uses @code{uname -n}.  You probably want to override\n## this.  Be sure to use the format @code{@email{user@@host}}.\n##\n## @item license\n##\n## @table @samp\n## @item gpl\n## GNU General Public License (default).\n##\n## @item bsd\n## BSD-style license without advertising clause.\n##\n## @item pd\n## Public domain.\n##\n## @item \"text\"\n## Your own default copyright and license.\n## @end table\n##\n## Unless you specify @samp{pd}, edit will prepend the copyright statement\n## with \"Copyright (C) YYYY Author\".\n##\n## @item mode\n## This value determines whether the editor should be started in async mode\n## (editor is started in the background and Octave continues) or sync mode\n## (Octave waits until the editor exits).  Set it to @qcode{\"sync\"} to start\n## the editor in sync mode.  The default is @qcode{\"async\"}\n## (@pxref{XREFsystem,,@code{system}}).\n##\n## @item editinplace\n## Determines whether files should be edited in place, without regard to\n## whether they are modifiable or not.  The default is @code{true}.\n## Set it to @code{false} to have read-only function files automatically\n## copied to @samp{home}, if it exists, when editing them.\n##\n## @item home\n## This value indicates a directory that system m-files should be copied into\n## before opening them in the editor.  The intent is that this directory is\n## also in the path, so that the edited copy of a system function file shadows\n## the original.  This setting only has an effect when @samp{editinplace} is\n## set to @code{false}.  The default is the empty matrix (@code{[]}), which\n## means it is not used.  The default in previous versions of Octave was\n## @file{~/octave}.\n## @end table\n## @seealso{EDITOR, path}\n## @end deftypefn\n\n## Original version by Paul Kienzle distributed as free software in the\n## public domain.\n\nfunction retval = edit (varargin)\n\n  ## Pick up globals or default them.\n\n  persistent FUNCTION = struct (\"HOME\", [],\n                                \"AUTHOR\", default_user(1),\n                                \"EMAIL\", [],\n                                \"LICENSE\", \"GPL\",\n                                \"MODE\", \"async\",\n                                \"EDITINPLACE\", true);\n  ## Make sure the stateval variables survive \"clear functions\".\n  mlock ();\n\n  ## Get default editor every time in case the user has changed it\n  FUNCTION.EDITOR = [EDITOR() \" %s\"];\n\n  if (nargin == 1)\n    ## User has supplied one arg, this can be a single filename\n    ## or a cell array of strings containing multiple files to be opened\n    if (iscellstr (varargin{1}))\n      ## If first arg is a cell array of strings,\n      ## it becomes the list of files to be edited\n      editfilelist = varargin{1};\n    elseif (ischar (varargin{1}))\n      ## If first arg is a string, create a cell array of strings\n      ## of length 1 (by copying the input cell array)\n      editfilelist = varargin(1);\n    else\n      error (\"edit: file NAME must be a string or cell array of strings\");\n    endif\n  elseif (nargin == 2)\n    ## User has supplied two arguments, these could be two filenames,\n    ## or a combination of editor state name and new value for that state,\n    ## so first check for the various states\n    statevar = varargin{1};\n    stateval = varargin{2};\n    switch (upper (statevar))\n      case \"EDITOR\"\n        error (\"Octave:deprecated-function\",\n               \"The EDITOR option of edit has been removed.  Use EDITOR() directly.\");\n      case \"HOME\"\n        FUNCTION.HOME = stateval;\n        return;\n      case \"AUTHOR\"\n        FUNCTION.AUTHOR = stateval;\n        return;\n      case \"EMAIL\"\n        FUNCTION.EMAIL = stateval;\n        return;\n      case \"LICENSE\"\n        FUNCTION.LICENSE = stateval;\n        return;\n      case \"MODE\"\n        if (strcmp (stateval, \"sync\") || strcmp (stateval, \"async\"))\n          FUNCTION.MODE = stateval;\n        else\n          error (\"edit: MODE must be sync or async\");\n        endif\n        return;\n      case \"EDITINPLACE\"\n        if (ischar (stateval))\n          if (strcmpi (stateval, \"true\"))\n            stateval = true;\n          elseif (strcmpi (stateval, \"false\"))\n            stateval = false;\n          else\n            stateval = eval (stateval);\n          endif\n        endif\n        FUNCTION.EDITINPLACE = stateval;\n        return;\n      case \"GET\"\n        if (isfield (FUNCTION, upper (stateval)))\n          retval = FUNCTION.(upper (stateval));\n        else\n          retval = FUNCTION;\n        endif\n        return;\n      otherwise\n        ## If none of the states match, assume both inputs are actually\n        ## filenames to be opened.\n        editfilelist = varargin;\n    endswitch\n  elseif (nargin > 2)\n    if (iscellstr (varargin))\n      editfilelist = varargin;\n    else\n      error (\"edit: if supplying more than one input all inputs must be strings containing field names to open\");\n    endif\n  endif\n\n  ## Only use the legacy \"HOME\" directory if the user explicitly configured\n  ## it and if the directory exists.  In previous versions of Octave, HOME\n  ## was ~/octave by default and edited functions were copied into ~/octave.\n  ## Now 'edit_file_in_place' should be true by default unless the user\n  ## opts in by setting \"EDITINPLACE\" to false and \"HOME\" to a directory.\n  edit_file_in_place = (FUNCTION.EDITINPLACE || isempty (FUNCTION.HOME)\n                        || ! isfolder (FUNCTION.HOME));\n\n  ## Start the editor without a file if no file is given.\n  if (nargin == 0)\n    if (! edit_file_in_place && ! strcmp (FUNCTION.HOME, \".\"))\n      curr_dir = pwd ();\n      unwind_protect\n        chdir (FUNCTION.HOME);\n        do_edit (FUNCTION.EDITOR, \"\", FUNCTION.MODE);\n      unwind_protect_cleanup\n        chdir (curr_dir);\n      end_unwind_protect\n    else\n      do_edit (FUNCTION.EDITOR, \"\", FUNCTION.MODE);\n    endif\n    return;\n  endif\n\n  if (numel (editfilelist) > 1)\n\n    ## Call edit on each of the files in the list if there are more than 1\n    for i = 1:numel (editfilelist)\n      edit (editfilelist{i});\n    endfor\n\n  else\n\n    ## Only one filename was supplied, get it from the cell array\n    file = tilde_expand (editfilelist{1});\n\n    ## Check whether the user is trying to edit a builtin or compiled function.\n    switch (exist (file))\n      case {3, 5}\n        error (\"edit: unable to edit a built-in or compiled function\");\n    endswitch\n\n    ## Checks for whether the file is\n    ## absolute or relative should be handled inside file_in_loadpath.\n    ## That way, it will be possible to look up files correctly given\n    ## partial path information.  For example, you should be able to\n    ## edit a particular overloaded function by doing any one of\n    ##\n    ##   edit classname/foo\n    ##   edit classname/foo.m\n    ##   edit @classname/foo\n    ##   edit @classname/foo.m\n    ##\n    ## This functionality is needed for other functions as well (at least\n    ## help and type; there may be more).  So the place to fix that is in\n    ## file_in_loadpath, possibly with some help from the load_path class.\n\n    ## The code below includes a portion that serves as a place-holder for\n    ## the changes suggested above.\n\n    ## Create list of explicit and implicit filenames.\n    filelist = {file};\n    ## If file has no extension, add file.m and file.cc to the list.\n    idx = rindex (file, \".\");\n    if (idx == 0)\n      if (isempty (regexp (file, '\\.m$')))\n        ## No \".m\" at the end of the file, add to the list.\n        filelist(end+1) = [file \".m\"];\n      endif\n      if (isempty (regexp (file, '\\.cc$')))\n        ## No \".cc\" at the end of the file, add to the list.\n        filelist(end+1) = [file \".cc\"];\n      endif\n    endif\n\n    ## If the file includes a path, it may be an overloaded function.\n    if (! index (file, \"@\") && strchr (file, '/\\'))\n      ## No \"@\" at the beginning of the file, add to the list.\n      numfiles = numel (filelist);\n      for n = 1:numfiles\n        filelist(n+numfiles) = [\"@\" filelist{n}];\n      endfor\n    endif\n\n    ## Search the entire path for the 1st instance of a file in the list.\n    fileandpath = \"\";\n    for n = 1:numel (filelist)\n      filetoedit = file_in_loadpath (filelist{n});\n      if (! isempty (filetoedit))\n        ## The path is explicitly included.\n        fileandpath = filetoedit;\n        break;\n      endif\n    endfor\n\n    if (! isempty (fileandpath))\n      ## If the file exists, then edit it.\n      if (edit_file_in_place)\n        ## Edit in place even if it is protected.\n        do_edit (FUNCTION.EDITOR, fileandpath, FUNCTION.MODE);\n        return;\n      else\n        ## If the file is modifiable in place then edit it,\n        ## otherwise make a copy in HOME and then edit it.\n        fid = fopen (fileandpath, \"r+t\");\n        if (fid < 0)\n          from = fileandpath;\n          [~, fname, ext] = fileparts (from);\n          fileandpath = fullfile (tilde_expand (FUNCTION.HOME), [fname, ext]);\n          [status, msg] = copyfile (from, fileandpath, 1);\n          if (status == 0)\n            error (msg);\n          endif\n        else\n          fclose (fid);\n        endif\n        do_edit (FUNCTION.EDITOR, fileandpath, FUNCTION.MODE);\n        return;\n      endif\n    endif\n\n    ## If editing a new file, prompt for creation if GUI is running\n    if (isguirunning ())\n      if (! __event_manager_edit_file__ (file, \"prompt\"))\n        return;\n      endif\n    endif\n\n    ## If editing a new file that is neither an m-file nor an oct-file,\n    ## just edit it.\n    ## If in gui-mode, create it before or editor would prompt again.\n    fileandpath = file;\n    idx = rindex (file, \".\");\n    if (idx)\n      name = file(1:idx-1);\n      ext = file(idx+1:end);\n    else\n      name = file;\n      ext = \"\";\n    endif\n    if (! any (strcmp (ext, {\"cc\", \"m\"})))\n      ## Some unknown file.  Create and open it or just open it.\n      if (isempty (ext))\n        fileandpath = [fileandpath \".m\"];  # Add .m extension per default\n      endif\n      if (isguirunning ())\n        ## Write the initial file (if there is anything to write)\n        ## Give user the opportunity to change the file extension\n        fileandpath = uiputfile (fileandpath);\n        if (! ischar (fileandpath))\n          return;  # Cancel Button pressed\n        endif\n        fid = fopen (fileandpath, \"wt\");\n        if (fid < 0)\n          error (\"edit: could not create %s\", fileandpath);\n        endif\n        fclose (fid);\n      endif\n      do_edit (FUNCTION.EDITOR, fileandpath, FUNCTION.MODE);\n      return;\n    endif\n\n    ## The file doesn't exist in path so\n    ## create it, put in the function template, and edit it.\n\n    ## Guess the email name if it was not given.\n    if (isempty (FUNCTION.EMAIL))\n      host = getenv (\"HOSTNAME\");\n      if (isempty (host) && ispc ())\n        host = getenv (\"COMPUTERNAME\");\n      endif\n      if (isempty (host))\n        [~, host] = system (\"uname -n\");\n        ## trim newline from end of hostname\n        if (! isempty (host))\n          host = host(1:end-1);\n        endif\n      endif\n      if (isempty (host))\n        FUNCTION.EMAIL = \" \";\n      else\n        FUNCTION.EMAIL = [\"<\" default_user(0) \"@\" host \">\"];\n      endif\n    endif\n\n    ## Fill in the revision string.\n    now = localtime (time);\n    revs = [\"Created: \" strftime(\"%Y-%m-%d\",now)];\n\n    ## Fill in the copyright string.\n    copyright = [strftime(\"Copyright (C) %Y \",now) FUNCTION.AUTHOR];\n\n    ## Fill in the author tag field.\n    author = [\"Author: \" FUNCTION.AUTHOR \" \" FUNCTION.EMAIL];\n\n    ## Fill in the header.\n    uclicense = upper (FUNCTION.LICENSE);\n    switch (uclicense)\n      case \"GPL\"\n        head = cstrcat (copyright, \"\\n\\n\", \"\\\nThis program is free software: you can redistribute it and/or modify\\n\\\nit under the terms of the GNU General Public License as published by\\n\\\nthe Free Software Foundation, either version 3 of the License, or\\n\\\n(at your option) any later version.\\n\\\n\\n\\\nThis program is distributed in the hope that it will be useful,\\n\\\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\\n\\\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n\\\nGNU General Public License for more details.\\n\\\n\\n\\\nYou should have received a copy of the GNU General Public License\\n\\\nalong with this program.  If not, see <https://www.gnu.org/licenses/>.\\\n\");\n        tail = [author, \"\\n\", revs];\n\n      case \"BSD\"\n        head = cstrcat (copyright, \"\\n\\n\", \"\\\nThis program is free software: redistribution and use in source and\\n\\\nbinary forms, with or without modification, are permitted provided that\\n\\\nthe following conditions are met:\\n\\\n1. Redistributions of source code must retain the above copyright\\n\\\n   notice, this list of conditions and the following disclaimer.\\n\\\n2. Redistributions in binary form must reproduce the above copyright\\n\\\n   notice, this list of conditions and the following disclaimer in the\\n\\\n   documentation and/or other materials provided with the distribution.\\n\\\n\\n\\\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\\n\\\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\\n\\\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\\n\\\nARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\\n\\\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\\n\\\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\\n\\\nOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\\n\\\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\\n\\\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\\n\\\nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\\n\\\nSUCH DAMAGE.\\\n\");\n        tail = [author, \"\\n\", revs];\n\n      case \"PD\"\n        head = \"\";\n        tail = [author, \"\\n\", revs, \"\\n\\n\", ...\n                \"This program is granted to the public domain.\"];\n\n      otherwise\n        head = \"\";\n        tail = [copyright, \"\\n\\n\", FUNCTION.LICENSE, \"\\n\", author, \"\\n\", revs];\n    endswitch\n\n    ## Generate the function template.\n    [~, basename] = fileparts (name);\n    exists = exist (name);\n    switch (ext)\n      case {\"cc\", \"C\", \"cpp\"}\n        if (isempty (head))\n          comment = [\"/*\\n\\n\", tail, \"\\n\\n*/\\n\\n\"];\n        else\n          comment = [\"/*\\n\\n\", head, \"\\n\\n\", tail, \"\\n\\n*/\\n\\n\"];\n        endif\n        ## If we are shadowing an m-file, paste the code for the m-file.\n        if (any (exists == [2, 103]))\n          code = ['\\ ', strrep(type(name){1}, \"\\n\", \"\\n// \")];\n        else\n          code = \" \";\n        endif\n        body = [\"#include <octave/oct.h>\\n\\n\"             ...\n                \"DEFUN_DLD(\" basename \", args, nargout,\\n\"...\n                \"          \\\"-*- texinfo -*-\\\\n\\\\\\n\"      ...\n                \"@deftypefn {} {@var{retval} =} \" basename...\n                \" (@var{input1}, @var{input2})\\\\n\\\\\\n\"    ...\n                \"@seealso{}\\\\n\\\\\\n@end deftypefn\\\")\\n{\\n\" ...\n                \"  octave_value_list retval;\\n\"           ...\n                \"  int nargin = args.length ();\\n\\n\"      ...\n                code, \"\\n  return retval;\\n}\\n\"];\n\n        text = [comment, body];\n      case \"m\"\n        ## If we are editing a function defined on the fly, paste the code.\n        if (any (exists == [2, 103]))\n          body = type (name){1};\n        else\n          body = [\"function retval = \" basename \" (input1, input2)\\n\\n\" ...\n                  \"endfunction\\n\"];\n        endif\n        if (isempty (head))\n          comment = [\"## -*- texinfo -*-\\n## @deftypefn {} \" ...\n                     \"{@var{retval} =} \" basename                          ...\n                     \" (@var{input1}, @var{input2})\\n##\\n\"                 ...\n                     \"## @seealso{}\\n## @end deftypefn\\n\\n\"                ...\n                     \"## \" strrep(tail, \"\\n\", \"\\n## \") \"\\n\\n\"];\n        else\n          comment = [\"## \" strrep(head,\"\\n\",\"\\n## \") \"\\n\\n\"                ...\n                     \"## -*- texinfo -*-\\n## @deftypefn {} \" ...\n                     \"{@var{retval} =} \" basename                          ...\n                     \" (@var{input1}, @var{input2})\\n##\\n\"                 ...\n                     \"## @seealso{}\\n## @end deftypefn\\n\\n\"                ...\n                     \"## \" strrep(tail, \"\\n\", \"\\n## \") \"\\n\\n\"];\n        endif\n        comment = strrep (comment, \" \\n\", \"\\n\");\n        text = [comment, body];\n    endswitch\n\n    ## Write the initial file (if there is anything to write)\n    fid = fopen (fileandpath, \"wt\");\n    if (fid < 0)\n      error (\"edit: could not create %s\", fileandpath);\n    endif\n    fputs (fid, text);\n    fclose (fid);\n\n    do_edit (FUNCTION.EDITOR, fileandpath, FUNCTION.MODE);\n\n  endif\n\nendfunction\n\n## Return the name associated with the current user ID.\n##\n## If LONG_FORM is 1, return the full name.  This will be the\n## default author.  Otherwise return the login name.\n## login@host will be the default email address.\n\nfunction retval = default_user (long_form)\n\n  ent = getpwuid (getuid);\n  if (! isstruct (ent))\n    retval = getenv (\"USER\");\n    if (isempty (retval))\n      retval = getenv (\"USERNAME\");\n    endif\n  elseif (long_form)\n    retval = ent.gecos;\n    pos = strfind (retval, \",\");\n    if (! isempty (pos))\n      retval = retval(1:pos(1)-1);\n    endif\n  else\n    retval = ent.name;\n  endif\n\nendfunction\n\nfunction do_edit (editor, file, mode)\n\n  if (isguirunning ())\n    __event_manager_edit_file__ (file);\n  else\n    system (sprintf (undo_string_escapes (editor), ['\"' file '\"']), false, mode);\n  endif\n\nendfunction\n\n\n%!test\n%! s.home = edit (\"get\", \"home\");\n%! s.author = edit (\"get\", \"author\");\n%! s.email = edit (\"get\", \"email\");\n%! s.license = edit (\"get\", \"license\");\n%! s.editinplace = edit (\"get\", \"editinplace\");\n%! s.mode = edit (\"get\", \"mode\");\n%! edit home none\n%! edit author none\n%! edit email none\n%! edit license none\n%! edit (\"editinplace\", ! s.editinplace);\n%! if (s.mode(1) == \"a\")\n%!   edit mode sync\n%! else\n%!   edit mode async\n%! endif\n%! edit (\"home\", s.home);\n%! edit (\"author\", s.author);\n%! edit (\"email\", s.email);\n%! edit (\"license\", s.license);\n%! edit (\"editinplace\", s.editinplace);\n%! edit (\"mode\", s.mode);\n%! assert (edit (\"get\", \"home\"), s.home);\n%! assert (edit (\"get\", \"author\"), s.author);\n%! assert (edit (\"get\", \"email\"), s.email);\n%! assert (edit (\"get\", \"license\"), s.license);\n%! assert (edit (\"get\", \"editinplace\"), s.editinplace);\n%! assert (edit (\"get\", \"mode\"), s.mode);\n"
  },
  {
    "path": "scripts/miscellaneous/fieldnames.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{names} =} fieldnames (@var{struct})\n## @deftypefnx {} {@var{names} =} fieldnames (@var{obj})\n## @deftypefnx {} {@var{names} =} fieldnames (@var{javaobj})\n## @deftypefnx {} {@var{names} =} fieldnames (\"@var{javaclassname}\")\n## Return a cell array of strings with the names of the fields in the specified\n## input.\n##\n## When the input is a structure @var{struct}, the @var{names} are the elements\n## of the structure.\n##\n## When the input is an Octave object @var{obj}, the @var{names} are the public\n## properties of the object.\n##\n## When the input is a Java object @var{javaobj} or a string containing the\n## name of a Java class @var{javaclassname}, the @var{names} are the public\n## fields (data members) of the object or class.\n## @seealso{numfields, isfield, orderfields, struct, properties}\n## @end deftypefn\n\nfunction names = fieldnames (obj)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isstruct (obj))\n    names = __fieldnames__ (obj);\n  elseif (isobject (obj))\n    try\n      names = properties (obj);      # classdef object\n    catch\n      names = __fieldnames__ (obj);  # @class object\n    end_try_catch\n  elseif (isjava (obj) || ischar (obj))\n    ## FIXME: Function prototype that accepts java obj exists, but doesn't\n    ##        work if obj is java.lang.String.  Convert obj to classname.\n    ## FIXME: this is now working for objects whose class is in the dynamic\n    ##        classpath but will continue to fail if such classnames are used\n    ##        instead (see bug #42710).\n    if (isa (obj, \"java.lang.String\"))\n      obj = class (obj);\n    endif\n    names_str = javaMethod (\"getFields\", \"org.octave.ClassHelper\", obj);\n    names = ostrsplit (names_str, ';');\n  else\n    error (\"fieldnames: Invalid input argument\");\n  endif\n\nendfunction\n\n\n## Test preservation of fieldname order\n%!test\n%! x(3).d=1;  x(2).a=2;  x(1).b=3;  x(2).c=3;\n%! assert (fieldnames (x), {\"d\"; \"a\"; \"b\"; \"c\"});\n\n## Test empty structure\n%!test\n%! s = struct ();\n%! assert (fieldnames (s), cell (0, 1));\n\n## Test classdef object\n%!test\n%! m = containers.Map ();\n%! f = fieldnames (m);\n%! assert (f, {\"KeyType\"; \"ValueType\"; \"Count\"; \"map\"; \"numeric_keys\"});\n\n## Test old-style @class object\n%!test\n%! obj = ftp ();\n%! f = fieldnames (obj);\n%! assert (f, {\"host\"; \"username\"; \"password\"; \"curlhandle\"});\n\n## Test Java classname by passing classname\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! names = fieldnames (\"java.lang.Double\");\n%! assert (any (strcmp (names, \"MAX_VALUE\")));\n\n## Test Java classname by passing java object\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! names = fieldnames (javaObject (\"java.lang.Double\", 10));\n%! assert (any (strcmp (names, \"MAX_VALUE\")));\n%! assert (all (ismember ({\"POSITIVE_INFINITY\", \"NEGATIVE_INFINITY\", ...\n%!                         \"NaN\", \"MAX_VALUE\", \"MIN_NORMAL\", \"MIN_VALUE\", ...\n%!                         \"MAX_EXPONENT\", \"MIN_EXPONENT\", \"SIZE\", \"TYPE\"},\n%!                        names)));\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! names = fieldnames (javaObject (\"java.lang.String\", \"Hello\"));\n%! assert (any (strcmp (names, \"CASE_INSENSITIVE_ORDER\")));\n"
  },
  {
    "path": "scripts/miscellaneous/fileattrib.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} fileattrib\n## @deftypefnx {} {} fileattrib @var{file}\n## @deftypefnx {} {} fileattrib (@var{file})\n## @deftypefnx {} {[@var{status}, @var{attrib}] =} fileattrib (@dots{})\n## @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} fileattrib (@dots{})\n## Report attribute information about @var{file}.\n##\n## If no file or directory is specified, report information about the present\n## working directory.\n##\n## If successful, the output is a structure with the following fields:\n##\n## @table @code\n## @item Name\n## Full name of @var{file}.\n##\n## @item archive\n## True if @var{file} is an archive (Windows).\n##\n## @item system\n## True if @var{file} is a system file (Windows).\n##\n## @item hidden\n## True if @var{file} is a hidden file (Windows).\n##\n## @item directory\n## True if @var{file} is a directory.\n##\n## @item  UserRead\n## @itemx GroupRead\n## @itemx OtherRead\n## True if the user (group; other users) has read permission for @var{file}.\n##\n## @item  UserWrite\n## @itemx GroupWrite\n## @itemx OtherWrite\n## True if the user (group; other users) has write permission for @var{file}.\n##\n## @item  UserExecute\n## @itemx GroupExecute\n## @itemx OtherExecute\n## True if the user (group; other users) has execute permission for @var{file}.\n## @end table\n##\n## If an attribute does not apply (e.g., archive on a Unix system) then the\n## field is set to NaN.\n##\n## If @var{file} contains globbing characters, information about all matching\n## files is returned in a structure array.\n##\n## If outputs are requested, the first is @var{status} which takes the value 1\n## when the operation was successful, and 0 otherwise.  The second output\n## contains the structure described above (@var{attrib}) if the operation was\n## successful; otherwise, the second output is a system-dependent error message\n## (@var{msg}).  The third output is an empty string (\"\") when the operation\n## was successful, or a unique message identifier (@var{msgid}) in the case of\n## failure.\n## @seealso{stat, glob}\n## @end deftypefn\n\nfunction [status, msg, msgid] = fileattrib (file = \".\")\n\n  if (! ischar (file))\n    error (\"fileattrib: FILE must be a string\");\n  endif\n\n  sts = 1;\n  msg = \"\";\n  msgid = \"\";\n\n  if (ispc ())\n    files = __wglob__ (file);\n  else\n    files = glob (file);\n  endif\n  if (isempty (files))\n    files = {file};\n  endif\n  nfiles = numel (files);\n\n  for i = [nfiles, 1:nfiles-1]  # first time in loop extends the struct array\n    [info, err, msg] = stat (files{i});\n    if (! err)\n      r(i).Name = canonicalize_file_name (files{i});\n\n      if (isunix ())\n        r(i).archive = NaN;\n        r(i).system = NaN;\n        r(i).hidden = NaN;\n      else\n        [~, attrib] = dos (sprintf ('attrib \"%s\"', r(i).Name));\n        ## DOS never returns error status so have to check it indirectly\n        if (! isempty (strfind (attrib, \" -\")))\n          sts = 0;\n          break;\n        endif\n        attrib = regexprep (attrib, '\\S+:.*', \"\");\n        r(i).archive = any (attrib == \"A\");\n        r(i).system = any (attrib == \"S\");\n        r(i).hidden = any (attrib == \"H\");\n      endif\n\n      r(i).directory = S_ISDIR (info.mode);\n\n      modestr = info.modestr;\n      r(i).UserRead = (modestr(2) == \"r\");\n      r(i).UserWrite = (modestr(3) == \"w\");\n      r(i).UserExecute = (modestr(4) == \"x\");\n      if (isunix ())\n        r(i).GroupRead = (modestr(5) == \"r\");\n        r(i).GroupWrite = (modestr(6) == \"w\");\n        r(i).GroupExecute = (modestr(7) == \"x\");\n        r(i).OtherRead = (modestr(8) == \"r\");\n        r(i).OtherWrite = (modestr(9) == \"w\");\n        r(i).OtherExecute = (modestr(10) == \"x\");\n      else\n        r(i).GroupRead = NaN;\n        r(i).GroupWrite = NaN;\n        r(i).GroupExecute = NaN;\n        r(i).OtherRead = NaN;\n        r(i).OtherWrite = NaN;\n        r(i).OtherExecute = NaN;\n      endif\n    else\n      sts = 0;\n      break;\n    endif\n  endfor\n\n  if (nargout == 0)\n    if (! sts)\n      error (\"fileattrib: operation failed\");\n    endif\n    status = r;\n  else\n    status = sts;\n    if (! sts)\n      if (isempty (msg))\n        msg = \"operation failed\";\n      endif\n      msgid = \"fileattrib\";\n    else\n      msg = r;\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! def_tmpdir = canonicalize_file_name (P_tmpdir ());\n%! while (length (def_tmpdir) > 2 && strfind (filesep (\"all\"), def_tmpdir(end)))\n%!   def_tmpdir(end) = [];\n%! endwhile\n%! [status, attr] = fileattrib (P_tmpdir ());\n%! assert (status);\n%! assert (isstruct (attr));\n%! assert (numfields (attr), 14);\n%! assert (attr.Name, def_tmpdir);\n%! assert (attr.directory);\n%! if (ispc ())\n%!   assert (! isnan (attr.archive));\n%! else\n%!   assert (isnan (attr.archive));\n%! endif\n%! assert (attr.UserRead);\n%! if (ispc ())\n%!   assert (isnan (attr.GroupRead));\n%! else\n%!   assert (! isnan (attr.GroupRead));\n%! endif\n\n%!error fileattrib (1, 2)\n%!error <FILE must be a string> fileattrib (1)\n"
  },
  {
    "path": "scripts/miscellaneous/fileparts.m",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{dir}, @var{name}, @var{ext}] =} fileparts (@var{filename})\n## Return the directory, name, and extension components of @var{filename}.\n##\n## The input @var{filename} is a string which is parsed.  There is no attempt\n## to check whether the filename or directory specified actually exists.\n## @seealso{fullfile, filesep}\n## @end deftypefn\n\nfunction [dir, name, ext] = fileparts (filename)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (filename) || rows (filename) > 1)\n    error (\"fileparts: FILENAME must be a single string\");\n  endif\n\n  ds = strchr (filename, filesep (\"all\"), 1, \"last\");\n  if (isempty (ds))\n    ds = 0;\n  endif\n  es = rindex (filename, \".\");\n  ## These can be the same if they are both 0 (no dir or ext).\n  if (es <= ds)\n    es = length (filename)+1;\n  endif\n\n  if (ds == 0)\n    if (ispc () && length (filename) >= 2 && strcmp (filename(2), \":\"))\n      ## Relative path on Windows drive.  At least, fix file name.\n      ds = 2;\n      dir = filename(1:2);\n    else\n      dir = \"\";\n    endif\n  elseif (ds == 1)\n    dir = filename(1);\n  else\n    dir = filename(1:ds-1);\n  endif\n\n  name = filename(ds+1:es-1);\n  if (isempty (name))\n    name = \"\";\n  endif\n\n  if (es > 0 && es <= length (filename))\n    ext = filename(es:end);\n  else\n    ext = \"\";\n  endif\n\nendfunction\n\n\n%!test\n%! [d, n, e] = fileparts (\"file\");\n%! assert (d, \"\");\n%! assert (n, \"file\");\n%! assert (e, \"\");\n\n%!test\n%! [d, n, e] = fileparts (\"file.ext\");\n%! assert (d, \"\");\n%! assert (n, \"file\");\n%! assert (e, \".ext\");\n\n%!test\n%! [d, n, e] = fileparts (\"/file.ext\");\n%! assert (d, \"/\");\n%! assert (n, \"file\");\n%! assert (e, \".ext\");\n\n%!test\n%! [d, n, e] = fileparts (\"dir/file.ext\");\n%! assert (d, \"dir\");\n%! assert (n, \"file\");\n%! assert (e, \".ext\");\n\n%!test\n%! [d, n, e] = fileparts (\"./file.ext\");\n%! assert (d, \".\");\n%! assert (n, \"file\");\n%! assert (e, \".ext\");\n\n%!test\n%! [d, n, e] = fileparts (\"d1/d2/file.ext\");\n%! assert (d, \"d1/d2\");\n%! assert (n, \"file\");\n%! assert (e, \".ext\");\n\n%!test\n%! [d, n, e] = fileparts (\"/d1/d2/file.ext\");\n%! assert (d, \"/d1/d2\");\n%! assert (n, \"file\");\n%! assert (e, \".ext\");\n\n%!test\n%! [d, n, e] = fileparts (\"/.ext\");\n%! assert (d, \"/\");\n%! assert (n, \"\");\n%! assert (e, \".ext\");\n\n%!test\n%! [d, n, e] = fileparts (\".ext\");\n%! assert (d, \"\");\n%! assert (n, \"\");\n%! assert (e, \".ext\");\n\n%!test\n%! [d, n, e] = fileparts (\"a\");\n%! assert (d, \"\");\n%! assert (n, \"a\");\n%! assert (e, \"\");\n\n%!test\n%! [d, n, e] = fileparts (\"\");\n%! assert (d, \"\");\n%! assert (n, \"\");\n%! assert (e, \"\");\n\n%!testif ; ispc () <*64462>\n%! [d, n, e] = fileparts (\"c:file.ext\");\n%! assert (d, \"c:\");\n%! assert (n, \"file\");\n%! assert (e, \".ext\");\n\n%!testif ; ispc () <*64462>\n%! [d, n, e] = fileparts (\"c:d1/../d2/file.ext\");\n%! assert (d, \"c:d1/../d2\");\n%! assert (n, \"file\");\n%! assert (e, \".ext\");\n\n%!testif ; ispc ()\n%! [d, n, e] = fileparts ('c:\\dir\\file.ext');\n%! assert (d, 'c:\\dir');\n%! assert (n, \"file\");\n%! assert (e, \".ext\");\n\n## Test input validation\n%!error <Invalid call> fileparts ()\n%!error <FILENAME must be a single string> fileparts (1)\n%!error <FILENAME must be a single string> fileparts ([\"a\"; \"b\"])\n"
  },
  {
    "path": "scripts/miscellaneous/fullfile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{filename} =} fullfile (@var{dir1}, @var{dir2}, @dots{}, @var{file})\n## Build complete filename from separate parts.\n##\n## The function joins any number of path components intelligently.  The return\n## value is the concatenation of each component with exactly one file separator\n## between each part of the path and at most one leading and/or trailing file\n## separator.\n##\n## The input arguments might be strings or cell strings.  Any input arguments\n## that are cell strings must contain one single string or must be equal in\n## size.  In that case, the function returns a cell string of filepaths of the\n## same dimensions as the input cell strings, for example:\n##\n## @example\n## @group\n## fullfile (\"/home/username\", \"data\", @{\"f1.csv\", \"f2.csv\", \"f3.csv\"@})\n##   @xresult{}\n##       @{\n##         [1,1] = /home/username/data/f1.csv\n##         [1,2] = /home/username/data/f2.csv\n##         [1,3] = /home/username/data/f3.csv\n##       @}\n## @end group\n## @end example\n##\n## On Windows systems, while forward slash file separators do work, they are\n## replaced by backslashes.  In addition, drive letters are stripped of leading\n## file separators to obtain a valid file path.\n##\n## Note: @code{fullfile} does not perform any validation of the resulting full\n## filename.\n## @seealso{fileparts, filesep}\n## @end deftypefn\n\nfunction filename = fullfile (varargin)\n\n  ## remove empty arguments\n  varargin(cellfun (@(x) isempty (x) & ! iscell (x), varargin)) = [];\n\n  if (isempty (varargin))\n    ## return early for all empty or no input\n    filename = \"\";\n    return;\n  endif\n\n  ## check input type\n  is_cellstr = cellfun ('iscellstr', varargin);\n  if (! all (is_cellstr | cellfun ('ischar', varargin)))\n    error (\"fullfile: input must either be strings or cell strings\");\n  endif\n\n  ## convert regular strings to cell strings\n  varargin(! is_cellstr) = num2cell (varargin(! is_cellstr));\n\n  ## check if input size matches\n  if (numel (varargin) > 1 && common_size (varargin{:}) != 0)\n    error (\"fullfile: cell string input must be scalar or of the same size\");\n  endif\n\n  fs = filesep ();\n\n  if (ispc ())\n    ## replace forward slashes with backslashes\n    varargin = cellfun (@(x) strrep (x, \"/\", fs), varargin,\n                        \"UniformOutput\", false);\n\n    ## Strip fileseps preceeding drive letters\n    varargin{1} = regexprep (varargin{1}, '\\\\*([a-zA-Z]:\\\\*)', \"$1\");\n\n    unc = strncmp (varargin{1}, '\\\\', 2);\n  endif\n\n  ## insert file separator between elements\n  varargin(2,:) = {fs};\n  varargin{end} = \"\";\n\n  filename = strcat (varargin{:});\n\n  ## remove multiplicate file separators\n  filename = regexprep (filename, [undo_string_escapes(fs), \"*\"], fs);\n\n  if (ispc ())\n    ## prepend removed file separator for UNC paths\n    filename(unc) = strcat (fs, filename(unc));\n  endif\n\n  if (! any (is_cellstr))\n    filename = filename{1};\n  endif\n\nendfunction\n\n\n%!shared fs, fsx, xfs, fsxfs, xfsy, xfsyfs\n%! fs = filesep ();\n%! fsx = [fs, \"x\"];\n%! xfs = [\"x\", fs];\n%! fsxfs = [fs, \"x\", fs];\n%! xfsy = [\"x\", fs, \"y\"];\n%! xfsyfs = [\"x\", fs, \"y\", fs];\n\n%!assert (fullfile (\"\"), \"\")\n%!assert (fullfile (\"\", \"\"), \"\")\n%!assert (fullfile (fs), fs)\n%!assert (fullfile (\"\", fs), fs)\n%!assert (fullfile (fs, \"\"), fs)\n%!assert (fullfile (\"\", fs), fs)\n%!assert (fullfile (\"x\"), \"x\")\n%!assert (fullfile (\"\", \"x\"), \"x\")\n%!assert (fullfile (\"x\", \"\"), \"x\")\n%!assert (fullfile (\"\", \"x\", \"\"), \"x\")\n%!assert (fullfile (\"x\", \"y\"), xfsy)\n%!assert (fullfile (\"x\", \"\", \"y\"), xfsy)\n%!assert (fullfile (\"x\", \"\", \"y\", \"\"), xfsy)\n%!assert (fullfile (\"\", \"x\", \"\", \"y\", \"\"), xfsy)\n%!assert (fullfile (fs), fs)\n%!assert (fullfile (fs, \"x\"), fsx)\n%!assert (fullfile (fs, xfs), fsxfs)\n%!assert (fullfile (fsx, fs), fsxfs)\n%!assert (fullfile (fs, \"x\", fs), fsxfs)\n\n%!assert (fullfile (\"x/\", \"/\", \"/\", \"y\", \"/\", \"/\"), xfsyfs)\n%!assert (fullfile (\"/\", \"x/\", \"/\", \"/\", \"y\", \"/\", \"/\"), [fs, xfsyfs])\n%!assert (fullfile (\"/x/\", \"/\", \"/\", \"y\", \"/\", \"/\"), [fs, xfsyfs])\n\n## different on purpose so that \"fullfile (c{:})\" works for empty c\n%!assert (fullfile (), \"\")\n\n%!assert (fullfile (\"x\", \"y\", {\"c\", \"d\"}), {[xfsyfs, \"c\"], [xfsyfs, \"d\"]})\n%!assert (fullfile ({\"folder1\", \"folder2\"}, \"sub\", {\"f1.m\", \"f2.m\"}), ...\n%!        {[\"folder1\", fs, \"sub\", fs, \"f1.m\"], ...\n%!         [\"folder2\", fs, \"sub\", fs, \"f2.m\"]});\n\n%!assert <*64377> (fullfile (\"x\", {}), {})\n\n## Windows specific - drive letters and file sep type\n%!testif ; ispc ()\n%! assert (fullfile ('\\/\\/\\//A:/\\/\\', \"x/\", \"/\", \"/\", \"y\", \"/\", \"/\"), ...\n%!         ['A:\\' xfsyfs]);\n\n## *nix specific - double slash\n%!testif ; ! ispc ()\n%! assert (fullfile (fs, fs), fs);\n\n## Windows specific - UNC path\n%!testif ; ispc ()\n%! assert (fullfile ({'\\/\\//server1', 'C:', '\\\\server2\\/'}, ...\n%!                   \"x/\", \"/\", \"/\", \"y\", \"/\", \"/\"), ...\n%!         {['\\\\server1\\', xfsyfs], ['C:\\', xfsyfs], ['\\\\server2\\', xfsyfs]});\n\n## Windows specific - drive letters and file sep type, cell array\n%!testif ; ispc ()\n%! tmp = fullfile ({'\\\\\\/B:\\//', 'A://c', '\\\\\\C:/g/h/i/j\\/'});\n%! assert (tmp{1}, 'B:\\');\n%! assert (tmp{2}, 'A:\\c');\n%! assert (tmp{3}, 'C:\\g\\h\\i\\j\\');\n\n%!error <strings or cell strings> fullfile (1)\n%!error <strings or cell strings> fullfile ({1})\n%!error <same size> fullfile ({\"a\", \"b\"}, {\"a\", \"b\", \"c\"})\n"
  },
  {
    "path": "scripts/miscellaneous/getfield.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{val} =} getfield (@var{s}, @var{field})\n## @deftypefnx {} {@var{val} =} getfield (@var{s}, @var{sidx1}, @var{field1}, @var{fidx1}, @dots{})\n## Get the value of the field named @var{field} from a structure or nested\n## structure @var{s}.\n##\n## If @var{s} is a structure array then @var{sidx} selects an element of the\n## structure array, @var{field} specifies the field name of the selected\n## element, and @var{fidx} selects which element of the field (in the case of\n## an array or cell array).  For a more complete description of the syntax,\n## @pxref{XREFsetfield,,@code{setfield}}.\n##\n## @seealso{setfield, rmfield, orderfields, isfield, fieldnames, isstruct,\n## struct}\n## @end deftypefn\n\nfunction val = getfield (s, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  subs = varargin;\n  flds = cellfun (\"isclass\", subs, \"char\");\n  idxs = cellfun (\"isclass\", subs, \"cell\");\n  if (! all (flds | idxs))\n    error (\"getfield: invalid index\");\n  endif\n\n  typs = merge (flds, {\".\"}, {\"()\"});\n  val = subsref (s, struct (\"type\", typs, \"subs\", subs));\n\nendfunction\n\n\n%!test\n%! x.a = \"hello\";\n%! assert (getfield (x, \"a\"), \"hello\");\n%!test\n%! ss(1,2).fd(3).b(1,4) = 5;\n%! assert (getfield (ss,{1,2},\"fd\",{3},\"b\", {1,4}), 5);\n\n## Test input validation\n%!error <Invalid call> getfield ()\n%!error <Invalid call> getfield (1)\n%!error <invalid index> getfield (1,2)\n"
  },
  {
    "path": "scripts/miscellaneous/grabcode.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} grabcode @var{filename}\n## @deftypefnx {} {} grabcode @var{url}\n## @deftypefnx {} {@var{code_str} =} grabcode (@dots{})\n##\n## Grab the code from a report created by the @code{publish} function.\n##\n## The grabbed code inside the published report must be enclosed by the\n## strings @samp{##### SOURCE BEGIN #####} and @samp{##### SOURCE END #####}.\n## The @code{publish} function creates this format automatically.\n##\n## If no return value is requested the code is saved to a temporary file and\n## opened in the default editor.  NOTE: The temporary file must be saved to a\n## new filename or the code will be lost.\n##\n## If an output is requested the grabbed code will be returned as string\n## @var{code_str}.\n##\n## Example:\n##\n## @example\n## @group\n## publish (\"my_script.m\");\n## grabcode (\"html/my_script.html\");\n## @end group\n## @end example\n##\n## The example above publishes @file{my_script.m} to the default location\n## @file{html/my_script.html}.  Next, the published Octave script is grabbed to\n## edit its content in a new temporary file.\n##\n## @seealso{publish}\n## @end deftypefn\n\nfunction code_str = grabcode (url)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (exist (url) == 2)\n    ## URL is a local file\n    oct_code = fileread (url);\n  else\n    ## Otherwise, try to read remote URL\n    [oct_code, success, message] = urlread (url);\n    if (! success)\n      error ([\"grabcode: \" message]);\n    endif\n  endif\n\n  ## Extract relevant part\n  oct_code = regexp (oct_code, ...\n    '##### SOURCE BEGIN #####\\n(.*)##### SOURCE END #####', \"once\", \"tokens\");\n  oct_code = oct_code{1};\n\n  if (nargout == 1)\n    code_str = oct_code;\n  else\n    ## Open temporary file in editor\n    fname = [tempname() \".m\"];\n    fid = fopen (fname, \"w\");\n    if (fid < 0)\n      error (\"grabcode: could not open temporary file\");\n    endif\n    fprintf (fid, \"%s\", oct_code);\n    fclose (fid);\n    edit (fname);\n    warndlg ([\"grabcode: Make sure to save the temporary file\\n\\n\\t\", ...\n              fname, \"\\n\\nto a location of your choice.  \", ...\n              \"Otherwise all grabbed code will be lost!\"]);\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> grabcode ()\n"
  },
  {
    "path": "scripts/miscellaneous/gunzip.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} gunzip (@var{gzfile})\n## @deftypefnx {} {} gunzip (@var{gzfile}, @var{outdir})\n## @deftypefnx {} {@var{filelist} =} gunzip (@dots{})\n## Unpack the gzip archive @var{gzfile}.\n##\n## If @var{gzfile} is a directory, all gzfiles in the directory will be\n## recursively unpacked.\n##\n## If @var{outdir} is specified the files are unpacked in this directory rather\n## than the one where @var{gzfile} is located.\n##\n## The optional output @var{filelist} is a list of the uncompressed files.\n## @seealso{gzip, unpack, bunzip2, unzip, untar}\n## @end deftypefn\n\nfunction filelist = gunzip (gzfile, outdir = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isempty (outdir) && ischar (gzfile))\n    outdir = fileparts (gzfile);\n  endif\n\n  if (nargout > 0)\n    filelist = unpack (gzfile, outdir, \"gz\");\n  else\n    unpack (gzfile, outdir, \"gz\");\n  endif\n\nendfunction\n\n\n## Tests for this m-file are located in gzip.m\n## Remove from test statistics\n%!assert (1)\n"
  },
  {
    "path": "scripts/miscellaneous/info.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} info ()\n## Display contact information for the GNU Octave community.\n## @end deftypefn\n\nfunction info ()\n\n  printf (\"\\n\\\n  Additional information about GNU Octave is available at\\n\\\n  https://www.octave.org\\n\\\n\\n\\\n  Links to the mailing list and other resources for getting help with\\n\\\n  Octave are available at\\n\\\n  https://www.octave.org/support.html\\n\\\n\\n\\\n  The Octave Wiki has user-generated content on a variety of subjects\\n\\\n  including installation and is available at\\n\\\n  https://wiki.octave.org\\n\\\n\\n\\\n  Additional functionality is provided by add-on packages at\\n\\\n  https://packages.octave.org\\n\\\n\\n\\\n  Report bugs to the bug tracker at\\n\\\n  https://bugs.octave.org\\n\\\n  But first, please read the guidelines to writing a helpful report at\\n\\\n  https://www.octave.org/bugs.html\\n\");\n\nendfunction\n\n\n## Mark file as being tested.  No real test needed for a documentation .m file\n%!assert (1)\n"
  },
  {
    "path": "scripts/miscellaneous/inputParser.m",
    "content": "########################################################################\n##\n## Copyright (C) 2011-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nclassdef inputParser < handle\n\n  ## -*- texinfo -*-\n  ## @deftypefn {} {@var{p} =} inputParser ()\n  ## Create object @var{p} of the inputParser class.\n  ##\n  ## This class is designed to allow easy parsing of function arguments.  The\n  ## class supports four types of arguments:\n  ##\n  ## @enumerate\n  ## @item mandatory (see @code{addRequired});\n  ##\n  ## @item optional (see @code{addOptional});\n  ##\n  ## @item named (see @code{addParameter});\n  ##\n  ## @item switch (see @code{addSwitch}).\n  ## @end enumerate\n  ##\n  ## After defining the function API with these methods, the supplied arguments\n  ## can be parsed with the @code{parse} method and the results accessed with\n  ## the @code{Results} accessor.\n  ## @end deftypefn\n  ##\n  ## @deftypefn {} {} inputParser.Parameters\n  ## Return the list of parameter names already defined.  (read-only)\n  ## @end deftypefn\n  ##\n  ## @deftypefn {} {} inputParser.Results\n  ## Return a structure with argument names as fieldnames and corresponding\n  ## values.  (read-only)\n  ## @end deftypefn\n  ##\n  ## @deftypefn {} {} inputParser.Unmatched\n  ## Return a structure similar to @code{Results}, but for unmatched\n  ## parameters.  (read-only)\n  ## See the @code{KeepUnmatched} property.\n  ## @end deftypefn\n  ##\n  ## @deftypefn {} {} inputParser.UsingDefaults\n  ## Return cell array with the names of arguments that are using default\n  ## values.  (read-only)\n  ## @end deftypefn\n  ##\n  ## @deftypefn {} {} inputParser.FunctionName = @var{name}\n  ## Set function name to be used in error messages; Defaults to empty string.\n  ## @end deftypefn\n  ##\n  ## @deftypefn {} {} inputParser.CaseSensitive = @var{boolean}\n  ## Set whether matching of argument names should be case sensitive; Defaults\n  ## to false.\n  ## @end deftypefn\n  ##\n  ## @deftypefn {} {} inputParser.KeepUnmatched = @var{boolean}\n  ## Set whether string arguments which do not match any Parameter are parsed\n  ## and stored in the @code{Unmatched} property; Defaults to false.  If false,\n  ## an error will be emitted at the first unrecognized argument and parsing\n  ## will stop.  Note that since @code{Switch} and @code{Parameter} arguments\n  ## can be mixed, it is not possible to know the type of the unmatched\n  ## argument.  Octave assumes that all unmatched arguments are of the\n  ## @code{Parameter} type and therefore must be followed by a value.\n  ## @end deftypefn\n  ##\n  ## @deftypefn {} {} inputParser.PartialMatching = @var{boolean}\n  ## Set whether argument names for @code{Parameter} and @code{Switch} options\n  ## may be given in shortened form as long as the name uniquely identifies\n  ## an option; Defaults to true.  For example, the argument @qcode{'opt'} will\n  ## match a parameter @qcode{'opt_color'}, but will fail if there is also a\n  ## parameter @qcode{'opt_case'}.\n  ## @end deftypefn\n  ##\n  ## @deftypefn {} {} inputParser.StructExpand = @var{boolean}\n  ## Set whether a structure passed to the function is expanded into\n  ## parameter/value pairs (parameter = fieldname); Defaults to true.\n  ##\n  ## The following example shows how to use this class:\n  ##\n  ## @example\n  ## function check (varargin)\n  ## @c The next two comments need to be indented by one for alignment\n  ##   p = inputParser ();                      # create object\n  ##   p.FunctionName = \"check\";                # set function name\n  ##   p.addRequired (\"pack\", @@ischar);         # mandatory argument\n  ##   p.addOptional (\"path\", pwd(), @@ischar);  # optional argument\n  ##\n  ##   ## Create anonymous function handle for validators\n  ##   valid_vec = @@(x) isvector (x) && all (x >= 0) && all (x <= 1);\n  ##   p.addOptional (\"vec\", [0 0], valid_vec);\n  ##\n  ##   ## Create two arguments of type \"Parameter\"\n  ##   vld_type = @@(x) any (strcmp (x, @{\"linear\", \"quadratic\"@}));\n  ##   p.addParameter (\"type\", \"linear\", vld_type);\n  ##   vld_tol = @@(x) any (strcmp (x, @{\"low\", \"medium\", \"high\"@}));\n  ##   p.addParameter (\"tolerance\", \"low\", vld_tol);\n  ##\n  ##   ## Create a switch type of argument\n  ##   p.addSwitch (\"verbose\");\n  ##\n  ##   p.parse (varargin@{:@});  # Run created parser on inputs\n  ##\n  ##   ## The rest of the function can access inputs by using p.Results.\n  ##   ## For example, get the tolerance input with p.Results.tolerance\n  ## endfunction\n  ## @end example\n  ##\n  ## @example\n  ## @group\n  ## check (\"mech\");           # valid, use defaults for other arguments\n  ## check ();                 # error, one argument is mandatory\n  ## check (1);                # error, since ! ischar\n  ## check (\"mech\", \"~/dev\");  # valid, use defaults for other arguments\n  ##\n  ## check (\"mech\", \"~/dev\", [0 1 0 0], \"type\", \"linear\");  # valid\n  ##\n  ## ## following is also valid.  Note how the Switch argument type can\n  ## ## be mixed in with or before the Parameter argument type (but it\n  ## ## must still appear after any Optional arguments).\n  ## check (\"mech\", \"~/dev\", [0 1 0 0], \"verbose\", \"tolerance\", \"high\");\n  ##\n  ## ## following returns an error since an Optional argument, 'path',\n  ## ## was given after the Parameter argument 'type'.\n  ## check (\"mech\", \"type\", \"linear\", \"~/dev\");\n  ## @end group\n  ## @end example\n  ##\n  ## @emph{Note 1}: A function can have any mixture of the four API types but\n  ## they must appear in a specific order.  @code{Required} arguments must be\n  ## first and can be followed by any @code{Optional} arguments.  Only the\n  ## @code{Parameter} and @code{Switch} arguments may be mixed together and\n  ## they must appear following the first two types.\n  ##\n  ## @emph{Note 2}: If both @code{Optional} and @code{Parameter} arguments\n  ## are mixed in a function API then once a string Optional argument fails to\n  ## validate it will be considered the end of the @code{Optional} arguments.\n  ## The remaining arguments will be compared against any @code{Parameter} or\n  ## @code{Switch} arguments.\n  ##\n  ## @seealso{nargin, validateattributes, validatestring, varargin}\n  ## @end deftypefn\n\n  properties\n    ## FIXME: set input checking for these properties\n    CaseSensitive   = false;\n    FunctionName    = \"\";\n    KeepUnmatched   = false;\n    PartialMatching = true;\n    StructExpand    = true;\n  endproperties\n\n  properties (SetAccess = protected)\n    Parameters    = cell ();\n    Results       = struct ();\n    Unmatched     = struct ();\n    UsingDefaults = cell ();\n  endproperties\n\n  properties (Access = protected)\n    ## Since Required and Optional are ordered, they get a cell array of\n    ## structs with the fields \"name\", \"def\" (default), and \"val\" (validator).\n    Required = cell ();\n    Optional = cell ();\n    ## Parameter and Switch are unordered so we use a struct array with\n    ## fields \"name\", \"def\" (default\", and \"val\" (validator).\n    Parameter = struct ([]);  # create 0x0 struct array, not scalar struct\n    Switch    = struct ([]);\n\n    ## List of Parameter and Switch names to simplify searches\n    ParameterNames = cell ();\n    SwitchNames    = cell ();\n\n    ## Simplify searches by cacheing the last name and last index of a\n    ## match from is_argname() into the Parameter or Switch struct arrays.\n    last_name = \"\";\n    last_idx = 1;\n  endproperties\n\n  properties (Access = protected, Constant = true)\n    ## Default validator, always returns scalar true.\n    def_val = @(~) true;\n  endproperties\n\n  methods\n\n    function addRequired (this, name, val = inputParser.def_val)\n\n      ## -*- texinfo -*-\n      ## @deftypefn  {} {} addRequired (@var{argname})\n      ## @deftypefnx {} {} addRequired (@var{argname}, @var{validator})\n      ## Add new mandatory argument to the object @var{parser} of inputParser\n      ## class.\n      ##\n      ## This method implements an ordered-argument type of API.\n      ##\n      ## @var{argname} must be a string with the name of the new argument.  The\n      ## order in which new arguments are added with @code{addRequired}\n      ## defines the expected order of arguments.\n      ##\n      ## The optional argument @var{validator} is a function (handle or name)\n      ## that will return false or throw an error if the input @var{argname}\n      ## is invalid.\n      ##\n      ## See @code{help inputParser} for examples.\n      ##\n      ## @emph{Note}: A Required argument can be used together with other\n      ## types of arguments but it must be the first (see @code{@@inputParser}).\n      ##\n      ## @end deftypefn\n\n      if (nargin < 2)\n        print_usage ();\n      elseif (numel (this.Optional)\n              || numel (this.Parameter) || numel (this.Switch))\n        error ([\"inputParser.addRequired: can't have a Required argument \" ...\n                \"after Optional, Parameter, or Switch\"]);\n      endif\n      this.validate_name (\"Required\", name);\n      this.Required{end+1} = struct (\"name\", name, \"val\", val);\n\n    endfunction\n\n    function addOptional (this, name, def, val = inputParser.def_val)\n\n      ## -*- texinfo -*-\n      ## @deftypefn  {} {} addOptional (@var{argname}, @var{default})\n      ## @deftypefnx {} {} addOptional (@var{argname}, @var{default}, @var{validator})\n      ## Add new optional argument to the object @var{parser} of the class\n      ## inputParser.\n      ##\n      ## This method implements an ordered-argument type of API.\n      ##\n      ## @var{argname} must be a string with the name of the new argument.  The\n      ## order in which new arguments are added with @code{addOptional}\n      ## defines the expected order of arguments.\n      ##\n      ## @var{default} will be the value used when the argument is not\n      ## specified.\n      ##\n      ## The optional argument @var{validator} is a function (handle or name)\n      ## that will return false or throw an error if the input @var{argname}\n      ## is invalid.\n      ##\n      ## See @code{help inputParser} for examples.\n      ##\n      ## @emph{Note1}: If an optional argument is not given a validator then\n      ## anything will be valid, and therefore a string in the correct position\n      ## (after Required arguments) will be assigned to the value of the\n      ## Optional argument @emph{even} if the string is the name of a Parameter\n      ## key.  @sc{matlab} adds a default validator @code{@@(x) ~ischar (x)} if\n      ## none is specified which emits an error in this instance.\n      ##\n      ## @emph{Note2}: if a string argument fails validation, it will be\n      ## considered as a possible Parameter.\n      ## @end deftypefn\n\n      if (nargin < 3)\n        print_usage ();\n      elseif (numel (this.Parameter) || numel (this.Switch))\n        error ([\"inputParser.Optional: can't have Optional arguments \" ...\n                \"after Parameter or Switch\"]);\n      endif\n      this.validate_name (\"Optional\", name);\n      if (iscell (def))\n        def = {def};\n      endif\n      this.Optional{end+1} = struct (\"name\", name, \"def\", def, \"val\", val);\n\n    endfunction\n\n    function addParamValue (this, name, def, val = inputParser.def_val)\n\n      ## -*- texinfo -*-\n      ## @deftypefn  {} {} addParamValue (@var{argname}, @var{default})\n      ## @deftypefnx {} {} addParamValue (@var{argname}, @var{default}, @var{validator})\n      ## This function is deprecated.  Use @code{addParameter} in all new code.\n      ##\n      ## Add new parameter to the object @var{parser} of the class inputParser.\n      ##\n      ## This method implements a name/value pair type of API.\n      ##\n      ## This is an alias for @code{addParameter} method without the\n      ## @qcode{\"PartialMatchPriority\"} option.  See @code{addParameter} for\n      ## the help text.\n      ##\n      ## @end deftypefn\n\n      if (nargin < 3)\n        print_usage ();\n      endif\n      this.addParameter (name, def, val);\n\n    endfunction\n\n    function addParameter (this, name, def, varargin)\n\n      ## -*- texinfo -*-\n      ## @deftypefn  {} {} addParameter (@var{argname}, @var{default})\n      ## @deftypefnx {} {} addParameter (@var{argname}, @var{default}, @var{validator})\n      ## Add new parameter argument to the object @var{parser} of the class\n      ## inputParser.\n      ##\n      ## This method implements a name/value pair type of API.\n      ##\n      ## @var{argname} must be a string with the name of the new parameter.\n      ##\n      ## @var{default} will be the value used when the parameter is not\n      ## specified.\n      ##\n      ## The optional argument @var{validator} is a function handle that will\n      ## return false or throw an error if the input @var{argname} is invalid.\n      ##\n      ## See @code{help inputParser} for examples.\n      ##\n      ## @end deftypefn\n\n      if (nargin < 3 || nargin > 6)\n        print_usage ();\n      endif\n\n      this.validate_name (\"Parameter\", name);\n\n      n_opt = numel (varargin);\n\n      if (n_opt == 0 || n_opt == 2)\n        val = inputParser.def_val;\n      else  # n_opt is 1 or 3\n        val = varargin{1};\n        if (! is_function_handle (val))\n          error (\"inputParser.addParameter: VALIDATOR must be a function handle\");\n        endif\n      endif\n\n      ## FIXME: PartialMatchPriority is parsed, but not implemented\n      if (n_opt == 0 || n_opt == 1)\n        match_priority = 1;\n      else  # n_opt is 2 or 3\n        if (! strcmpi (varargin{end-1}, \"PartialMatchPriority\"))\n          error (\"inputParser.addParameter: unrecognized option\");\n        endif\n        match_priority = varargin{end};\n        validateattributes (match_priority, {\"numeric\"}, {\"positive\", \"integer\"},\n                            \"inputParser.addParameter\",\n                            \"PartialMatchPriority\");\n      endif\n\n      if (iscell (def))\n        ## Accept cell default values (bug #64305).\n        ## Use builtin() to avoid struct overload in classdef (bug #65667)\n        this.Parameter(end+1) = builtin (\"struct\", \"name\", name, \"def\", {def}, \"val\", val);\n      else\n        this.Parameter(end+1) = builtin (\"struct\", \"name\", name, \"def\", def, \"val\", val);\n      endif\n\n    endfunction\n\n    function addSwitch (this, name)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {} addSwitch (@var{argname})\n      ## Add new switch argument to the object @var{parser} of the class\n      ## inputParser.\n      ##\n      ## This method implements a name/boolean type of API.\n      ##\n      ## @var{argname} must be a string with the name of the new argument.\n      ##\n      ## Arguments of this type must be specified after @code{Required} and\n      ## @code{Optional} arguments, but can be mixed with any @code{Parameter}\n      ## definitions.  The default for switch arguments is false.  During\n      ## parsing, if one of the arguments supplied is a string such as\n      ## @var{argname} that matches a defined switch such as\n      ## @w{@code{addSwitch (@var{argname})}}, then after parsing the value\n      ## of @code{parse.Results.@var{argname}} will be true.\n      ##\n      ## See @code{help inputParser} for examples.\n      ##\n      ## Compatibility Note: @code{addSwitch} is an Octave extension not\n      ## present in @sc{matlab}.\n      ##\n      ## @end deftypefn\n\n      if (nargin != 2)\n        print_usage ();\n      endif\n      this.validate_name (\"Switch\", name);\n      this.Switch(end+1) = struct (\"name\", name, \"def\", false);\n\n    endfunction\n\n    function parse (this, varargin)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {} parse (@var{varargin})\n      ## Parse and validate a list of arguments according to object\n      ## @var{parser} of the class inputParser.\n      ##\n      ## After parsing, the results can be accessed with the @code{Results}\n      ## accessor.  See @code{help inputParser} for a more complete\n      ## description.\n      ##\n      ## @end deftypefn\n\n      this.Results = struct ();\n      this.Unmatched = struct ();\n      this.UsingDefaults = cell ();\n      if (numel (varargin) < numel (this.Required))\n        if (this.FunctionName)\n          print_usage (this.FunctionName);\n        else\n          this.error (\"inputParser.parse: not enough input arguments\");\n        endif\n      endif\n      pnargin = numel (varargin);\n      this.ParameterNames = {};\n      if (numel (this.Parameter))\n        this.ParameterNames = {this.Parameter.name};\n      endif\n      this.SwitchNames = {};\n      if (numel (this.Switch))\n        this.SwitchNames = {this.Switch.name};\n      endif\n\n      ## Evaluate the Required arguments first\n      nReq = numel (this.Required);\n      for idx = 1:nReq\n        req = this.Required{idx};\n        this.validate_arg (req.name, req.val, varargin{idx});\n      endfor\n\n      vidx = nReq;  # current index in varargin\n\n      ## Search for a list of Optional arguments\n      idx  = 0;     # current index on the array of Optional\n      nOpt = numel (this.Optional);\n      while (vidx < pnargin && idx < nOpt)\n        opt = this.Optional{++idx};\n        in  = varargin{++vidx};\n        if ((this.is_argname (\"Parameter\", in) && vidx < pnargin)\n            || this.is_argname (\"Switch\", in))\n          ## The string value looks like an optional parameter/value pair or a\n          ## switch.  The Optional positional argument which could apply here\n          ## is specifically not used (this is Matlab compatible).\n          ## See bug #50752.\n          idx -= 1;\n          vidx -= 1;\n          break;\n        endif\n        valid_option = this.validate_arg (\"\", opt.val, in);\n        if (! valid_option)\n          ## If it does not match there are two options:\n          ##   1a) it's a Parameter or Switch name and we should use\n          ##       the default for the rest;\n          ##   1b) it's a struct with the Parameter pairs.\n          ##   2) input is actually wrong and we should error;\n          if (ischar (in)\n              || (this.StructExpand && isstruct (in) && isscalar (in)))\n            idx -= 1;\n            vidx -= 1;\n            break;\n          else\n            this.error (sprintf ([\"failed validation of '%s'\\n\", ...\n                                  \"Validation function: %s\"],\n                                 opt.name, disp (opt.val)));\n          endif\n        endif\n        this.Results.(opt.name) = in;\n      endwhile\n\n      ## Fill in with defaults of missing Optional\n      while (idx++ < nOpt)\n        opt = this.Optional{idx};\n        this.UsingDefaults{end+1} = opt.name;\n        this.Results.(opt.name) = opt.def;\n      endwhile\n\n      ## Search unordered Options (Switch and Parameter)\n      while (vidx++ < pnargin)\n        name = varargin{vidx};\n\n        if (this.StructExpand && isstruct (name) && isscalar (name))\n          expanded_options = [fieldnames(name) struct2cell(name)]'(:);\n          if (isempty (expanded_options))\n            continue;  # empty, continue to next argument\n          endif\n          n_new_args = numel (expanded_options) - 1;\n          pnargin += n_new_args;\n          varargin(vidx+n_new_args+1:pnargin) = varargin(vidx+1:end);\n          varargin(vidx:vidx+n_new_args) = expanded_options;\n          name = varargin{vidx};\n        endif\n\n        if (! ischar (name))\n          this.error (\"Parameter or Switch name must be a string\");\n        endif\n\n        if (this.is_argname (\"Parameter\", name))\n          if (++vidx > pnargin)\n            this.error (sprintf (\"no value for parameter '%s'\", name));\n          endif\n          this.validate_arg (this.last_name,\n                             this.Parameter(this.last_idx).val,\n                             varargin{vidx});\n        elseif (this.is_argname (\"Switch\", name))\n          this.Results.(this.last_name) = true;\n        else\n          if (vidx++ < pnargin && this.KeepUnmatched)\n            this.Unmatched.(name) = varargin{vidx};\n          else\n            this.error (sprintf (\"argument '%s' is not a declared parameter or switch\", name));\n          endif\n        endif\n      endwhile\n      ## Add them to the UsingDefaults list\n      this.add_missing (\"Parameter\");\n      this.add_missing (\"Switch\");\n\n      ## Sort fields for Matlab compatibility (bug #64003)\n      this.Results = orderfields (this.Results);\n\n    endfunction\n\n    function disp (this)\n\n      if (nargin != 1)\n        print_usage ();\n      endif\n      printf (\"inputParser object with properties:\\n\\n\");\n      b2s = @(x) ifelse (any (x), \"true\", \"false\");\n      printf ([\"   FunctionName    : \\\"%s\\\"\\n\" ...\n               \"   CaseSensitive   : %s\\n\" ...\n               \"   KeepUnmatched   : %s\\n\" ...\n               \"   PartialMatching : %s\\n\" ...\n               \"   StructExpand    : %s\\n\\n\"],\n               this.FunctionName, b2s (this.CaseSensitive),\n               b2s (this.KeepUnmatched), b2s (this.PartialMatching),\n               b2s (this.StructExpand));\n      printf (\"Defined parameters:\\n\\n   {%s}\\n\",\n              strjoin (this.Parameters, \", \"));\n\n    endfunction\n\n  endmethods\n\n  methods (Access = private)\n\n    function validate_name (this, type, name)\n\n      if (! isvarname (name))\n        error (\"inputParser.add%s: NAME is an invalid identifier\", method);\n      elseif (any (strcmpi (this.Parameters, name)))\n        ## Even if CaseSensitive is true, we still shouldn't allow\n        ## two args with the same name.\n        error (\"inputParser.add%s: argname '%s' has already been declared\",\n               type, name);\n      endif\n      this.Parameters{end+1} = name;\n      ## Sort Parameters for Matlab compatibility (bug #64003)\n      this.Parameters = sort (this.Parameters);\n\n    endfunction\n\n    function r = validate_arg (this, name, val, in)\n\n      ## Validation function can either produce a true/false result or have\n      ## no outputs but throw an error when failing.  Tricky code here\n      ## relies on side effect, but calls validation function only once\n      ## which is a performance win and may also be necessary if validation\n      ## function maintains state.  See bug #49793.\n      ans = true;\n      lasterr (\"\");  # clear error message\n      try\n        val (in);  # call function with no arguments in case nargout == 0\n        ok = ans;  # use side effect of assignment to 'ans' when nargout == 1\n      catch\n        ok = false;\n      end_try_catch\n\n      if (nargout > 0)\n        r = ok;\n      else\n        if (! ok)\n          err = lasterr ();\n          if (! isempty (err))\n            ## rethrow error message if one was generated\n            this.error (err);\n          else\n            ## emit general error message that validation function failed\n            err = sprintf ('Checked with \"%s\"', func2str (val));\n            this.error (sprintf (\"failed validation of '%s'.  %s\", name, err));\n          endif\n        endif\n        this.Results.(name) = in;\n      endif\n\n    endfunction\n\n    function r = is_argname (this, type, name)\n\n      r = ischar (name) && isrow (name);\n      if (r)\n        fnames = this.([type \"Names\"]);\n        if (this.PartialMatching)\n          if (this.CaseSensitive)\n            idx = strncmp (name, fnames, numel (name));\n            r = sum (idx);\n            if (r > 1)\n              ## Check for exact match and prefer it over a partial match\n              idx2 = strcmp (name, {fnames{idx}});\n              if (any (idx2))\n                idx = (find (idx))(idx2);\n                r = 1;\n              else\n                matches = sprintf (\"'%s', \", fnames{idx})(1:end-1);\n                matches(end) = '.';\n                this.error (sprintf (\"argument '%s' matches more than one %s: %s\", name, type, matches));\n              endif\n            endif\n            r = logical (r);\n          else  # not CaseSensitive\n            idx = strncmpi (name, fnames, numel (name));\n            r = sum (idx);\n            if (r > 1)\n              idx2 = strcmpi (name, {fnames{idx}});\n              if (any (idx2))\n                idx = (find (idx))(idx2);\n                r = 1;\n              else\n                matches = sprintf (\"'%s', \", fnames{idx})(1:end-1);\n                matches(end) = '.';\n                this.error (sprintf (\"argument '%s' matches more than one %s: %s\", name, type, matches));\n              endif\n            endif\n            r = logical (r);\n          endif\n        else  # no PartialMatching\n          if (this.CaseSensitive)\n            idx = strcmp (name, fnames);\n            r = any (idx(:));\n          else\n            idx = strcmpi (name, fnames);\n            r = any (idx(:));\n          endif\n        endif\n      endif\n\n      if (r)\n        ## Cache values to simplify and speed up later code.\n        this.last_name = fnames{idx};\n        this.last_idx = find (idx);\n      endif\n\n    endfunction\n\n    function add_missing (this, type)\n\n      if (isempty (this.(type)))\n        return;\n      endif\n\n      ## Implement setdiff() without calling out to function for performance.\n      typenames = {this.(type).name}(:);\n      Resultnames = fieldnames (this.Results);\n      [sorted, sidx] = sort ([typenames; Resultnames]);\n      dups = strcmp (sorted(1:end-1), sorted(2:end));\n      idx = true (size (typenames));\n      idx(sidx(dups)) = false;\n      if (any (idx))\n        unmatched_names = typenames(idx);\n        unmatched_def = {this.(type)(idx).def}(:);\n        this.Results = ...\n          cell2struct (vertcat (struct2cell (this.Results), unmatched_def),\n                       [Resultnames; unmatched_names]);\n        this.UsingDefaults = [this.UsingDefaults, unmatched_names.'];\n      endif\n\n    endfunction\n\n    function error (this, msg)\n\n      where = \"\";\n      if (this.FunctionName)\n        where = [this.FunctionName \": \"];\n      endif\n      error (\"%s%s\", where, msg);\n\n    endfunction\n\n  endmethods\n\nendclassdef\n\n\n%!function p = create_p ()\n%!  p = inputParser ();\n%!  p.CaseSensitive = true;\n%!  p.PartialMatching = false;\n%!  p.addRequired (\"req1\", @(x) ischar (x));\n%!  p.addOptional (\"op1\", \"val\", @(x) any (strcmp (x, {\"val\", \"foo\"})));\n%!  p.addOptional (\"op2\", 78, @(x) x > 50);\n%!  p.addSwitch (\"verbose\");\n%!  p.addParameter (\"line\", \"tree\", @(x) any (strcmp (x, {\"tree\", \"circle\"})));\n%!endfunction\n\n## check normal use, only required are given\n%!test\n%! p = create_p ();\n%! p.parse (\"file\");\n%! r = p.Results;\n%! assert (r.req1, \"file\");\n%! assert (sort (p.UsingDefaults), sort ({\"op1\", \"op2\", \"verbose\", \"line\"}));\n%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},\n%!         {\"file\", \"val\", 78,    false,     \"tree\"});\n\n## check normal use, but give values different than defaults\n%!test\n%! p = create_p ();\n%! p.parse (\"file\", \"foo\", 80, \"line\", \"circle\", \"verbose\");\n%! r = p.Results;\n%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},\n%!         {\"file\", \"foo\", 80,    true,      \"circle\"});\n\n## check optional is skipped and considered Parameter if unvalidated string\n%!test\n%! p = create_p ();\n%! p.parse (\"file\", \"line\", \"circle\");\n%! r = p.Results;\n%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},\n%!         {\"file\", \"val\", 78,    false,     \"circle\"});\n\n## check CaseSensitive (default false state)\n%!test\n%! p = create_p ();\n%! p.CaseSensitive = false;\n%! p.parse (\"file\", \"foo\", 80, \"LiNE\", \"circle\", \"vERbOSe\");\n%! r = p.Results;\n%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},\n%!         {\"file\", \"foo\", 80,    true,      \"circle\"});\n\n## check PartialMatching (default true state)\n%!test\n%! p = create_p ();\n%! p.PartialMatching = true;\n%! p.parse (\"file\", \"foo\", 80, \"l\", \"circle\", \"verb\");\n%! r = p.Results;\n%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},\n%!         {\"file\", \"foo\", 80,    true,      \"circle\"});\n\n## Check PartialMatching selects an exact match if it exists\n%!test\n%! p = inputParser ();\n%! p.addParameter ('Mass', []);\n%! p.addParameter ('MassSingular', []);\n%! p.parse (\"Mass\", pi);\n%! r = p.Results;\n%! assert ({r.Mass, r.MassSingular}, {pi, []});\n\n## check KeepUnmatched\n%!test\n%! p = create_p ();\n%! p.KeepUnmatched = true;\n%! p.parse (\"file\", \"foo\", 80, \"line\", \"circle\", \"verbose\", \"extra\", 50);\n%! assert (p.Unmatched.extra, 50);\n\n## check error when missing required\n%!error <not enough input arguments>\n%! p = create_p ();\n%! p.parse ();\n\n## check error when required arg does not validate\n%!error <failed validation of >\n%! p = create_p ();\n%! p.parse (50);\n\n## check error when optional arg does not validate\n%!error <is not a declared parameter or switch>\n%! p = create_p ();\n%! p.parse (\"file\", \"no-val\");\n\n## check error when Parameter arg does not validate\n%!error <failed validation of >\n%! p = create_p ();\n%! p.parse (\"file\", \"foo\", 51, \"line\", \"round\");\n\n## check PartialMatching errors\n%!error <'arg' matches more than one Parameter: 'arg123', 'arg456'>\n%! p = inputParser ();\n%! p.addParameter ('arg123', 123);\n%! p.addParameter ('arg456', 456);\n%! p.addSwitch ('arg789');\n%! p.addSwitch ('arg790');\n%! p.parse ('arg', 'bad');\n\n%!error <'arg7' matches more than one Switch: 'arg789', 'arg790'>\n%! p = inputParser ();\n%! p.addParameter ('arg123', 123);\n%! p.addParameter ('arg456', 456);\n%! p.addSwitch ('arg789');\n%! p.addSwitch ('arg790');\n%! p.parse ('arg7', 'bad');\n\n## check alternative method (obj, ...) API\n%!function p2 = create_p2 ();\n%!  p2 = inputParser ();\n%!  addRequired (p2, \"req1\", @(x) ischar (x));\n%!  addOptional (p2, \"op1\", \"val\", @(x) any (strcmp (x, {\"val\", \"foo\"})));\n%!  addOptional (p2, \"op2\", 78, @(x) x > 50);\n%!  addSwitch (p2, \"verbose\");\n%!  addParameter (p2, \"line\", \"tree\", @(x) any (strcmp (x, {\"tree\", \"circle\"})));\n%!endfunction\n\n## check normal use, only required are given\n%!test\n%! p2 = create_p2 ();\n%! parse (p2, \"file\");\n%! r = p2.Results;\n%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},\n%!         {\"file\", \"val\", 78,    false,     \"tree\"});\n%! assert (sort (p2.UsingDefaults), sort ({\"op1\", \"op2\", \"verbose\", \"line\"}));\n\n## check normal use, but give values different than defaults\n%!test\n%! p2 = create_p2 ();\n%! parse (p2, \"file\", \"foo\", 80, \"line\", \"circle\", \"verbose\");\n%! r = p2.Results;\n%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},\n%!         {\"file\", \"foo\", 80,    true,      \"circle\"});\n\n## Octave must not perform validation of default values\n%!test <*45837>\n%! p = inputParser ();\n%! p.addParameter (\"Dir\", [], @ischar);\n%! p.parse ();\n%! assert (p.Results.Dir, []);\n\n%!test\n%! p = inputParser ();\n%! p.addParameter (\"positive\", -1, @(x) x > 5);\n%! p.parse ();\n%! assert (p.Results.positive, -1);\n\n## Throw an error on validation of optional argument to check that it\n## is caught without preventing continuation into param/value pairs.\n%!test\n%! p = inputParser ();\n%! p.addOptional (\"err\", \"foo\", @error);\n%! p.addParameter (\"not_err\", \"bar\", @ischar);\n%! p.parse (\"not_err\", \"qux\");\n%! assert (p.Results.err, \"foo\");\n%! assert (p.Results.not_err, \"qux\");\n\n## With more Parameters to test StructExpand\n%!function p3 = create_p3 ();\n%!  p3 = inputParser ();\n%!  addOptional (p3, \"op1\", \"val\", @(x) any (strcmp (x, {\"val\", \"foo\"})));\n%!  addOptional (p3, \"op2\", 78, @(x) x > 50);\n%!  addSwitch (p3, \"verbose\");\n%!  addParameter (p3, \"line\", \"tree\", @(x) any (strcmp (x, {\"tree\", \"circle\"})));\n%!  addParameter (p3, \"color\", \"red\", @(x) any (strcmp (x, {\"red\", \"green\"})));\n%!  addParameter (p3, \"style\", \"tt\", @(x) any (strcmp (x, {\"tt\", \"f\", \"i\"})));\n%!endfunction\n\n## check StructExpand\n%!test\n%! p3 = create_p3 ();\n%! p3.parse (struct (\"line\", \"circle\", \"color\", \"green\"));\n%! assert (p3.Results, struct (\"op1\", \"val\", \"op2\", 78, \"verbose\", false,\n%!                             \"line\", \"circle\", \"color\", \"green\",\n%!                             \"style\", \"tt\"))\n\n%!test  # check last param/value pair overrides previous\n%! p3 = create_p3 ();\n%! p3.parse (struct (\"line\", \"circle\", \"color\", \"green\"), \"line\", \"tree\");\n%! assert (p3.Results.line, \"tree\");\n%! p3.parse (\"line\", \"tree\", struct (\"line\", \"circle\", \"color\", \"green\"));\n%! assert (p3.Results.line, \"circle\");\n\n%!test # unmatched parameters with StructExpand\n%! p3 = create_p3 ();\n%! p3.KeepUnmatched = true;\n%! p3.parse (struct (\"line\", \"circle\", \"color\", \"green\", \"bar\", \"baz\"));\n%! assert (p3.Unmatched.bar, \"baz\");\n\n## The validation for the second optional argument throws an error with\n## a struct so check that we can handle it.\n%!test\n%! p3 = create_p3 ();\n%! p3.parse (\"foo\", struct (\"color\", \"green\"), \"line\", \"tree\");\n%! assert (p3.Results.op1, \"foo\");\n%! assert (p3.Results.line, \"tree\");\n%! assert (p3.Results.color, \"green\");\n%! assert (p3.Results.verbose, false);\n\n## Some simple tests for addParamValue since all the other ones use add\n## addParameter but they use the same codepath.\n%!test\n%! p = inputParser ();\n%! addParamValue (p, \"line\", \"tree\", @(x) any (strcmp (x, {\"tree\", \"circle\"})));\n%! addParamValue (p, \"color\", \"red\", @(x) any (strcmp (x, {\"red\", \"green\"})));\n%! p.parse (\"line\", \"circle\");\n%! assert ({p.Results.line, p.Results.color}, {\"circle\", \"red\"});\n\n%!test\n%! p = inputParser ();\n%! p.addParamValue (\"foo\", \"bar\", @ischar);\n%! p.parse ();\n%! assert (p.Results, struct (\"foo\", \"bar\"));\n%! p.parse (\"foo\", \"qux\");\n%! assert (p.Results, struct (\"foo\", \"qux\"));\n\n## An Optional argument which has a string value that is the name of a\n## Parameter will be parsed as a Parameter/Value pair.\n## This is required for Matlab compatibility.\n%!test <*50752>\n%! p = inputParser ();\n%! p.addOptional (\"op1\", \"val\");\n%! p.addParameter (\"line\", \"tree\");\n%! p.parse (\"line\", \"circle\");\n%! assert (p.Results, struct (\"op1\", \"val\", \"line\", \"circle\"));\n%!\n%! p = inputParser ();\n%! p.addOptional (\"op1\", \"val1\");\n%! p.addOptional (\"op2\", \"val2\");\n%! p.addParameter (\"line\", \"tree\");\n%! p.parse (\"line\", \"circle\");\n%! assert (p.Results.op1, \"val1\");\n%! assert (p.Results.op2, \"val2\");\n%! assert (p.Results.line, \"circle\");\n%!\n%! ## If there's enough arguments to fill the positional options and\n%! ## param/key, it still skips positional options.\n%! p = inputParser ();\n%! p.addOptional (\"op1\", \"val1\");\n%! p.addOptional (\"op2\", \"val2\");\n%! p.addParameter (\"line\", \"tree\");\n%! p.parse (\"line\", \"circle\", \"line\", \"rectangle\");\n%! assert (p.Results, struct (\"op1\", \"val1\", \"op2\", \"val2\",\n%!                            \"line\", \"rectangle\"))\n%!\n%! ## Even if the key/param fails validation, it does not backtrack to\n%! ## check if the values are valid positional options.\n%! p = inputParser ();\n%! p.addOptional (\"op1\", \"val1\", @ischar);\n%! p.addOptional (\"op2\", \"val2\", @isnumeric);\n%! p.addParameter (\"line\", \"circle\", @ischar);\n%! fail ('p.parse (\"line\", 89)', \"failed validation of 'line'\")\n%!\n%! p = inputParser ();\n%! p.addOptional (\"op1\", \"val1\");\n%! p.addParamValue (\"line\", \"circle\", @ischar);\n%! fail ('p.parse (\"line\", \"line\", 89)',\n%!       \"Parameter or Switch name must be a string\")\n\n%!test <*50752>\n%! ## This fails in Matlab but works in Octave.  It is a bug there\n%! ## that we do not replicate.\n%! p = inputParser ();\n%! p.addOptional (\"op1\", \"val1\");\n%! p.addParameter (\"line\", \"circle\");\n%! p.parse (\"line\");\n%! assert (p.Results, struct (\"op1\", \"line\", \"line\", \"circle\"));\n\n%!test <*50752>\n%! p = inputParser ();\n%! p.addOptional (\"op1\", \"val1\");\n%! p.addSwitch (\"line\");\n%! p.parse (\"line\");\n%! assert (p.Results.op1, \"val1\");\n%! assert (p.Results.line, true);\n\n%!test\n%! p = inputParser ();\n%! p.addParameter (\"a\", []);\n%! p.addParameter (\"b\", []);\n%! p.parse (\"a\", 1);\n%! p.parse (\"b\", 1);\n%! assert (p.Results, struct (\"a\", [], \"b\", 1));\n%! assert (p.UsingDefaults, {\"a\"});\n\n%!test\n%! p = inputParser ();\n%! p.addParameter (\"b\", []);\n%! p.KeepUnmatched = true;\n%! p.parse (\"a\", 1);\n%! p.parse (\"b\", 1);\n%! assert (p.Results, struct (\"b\", 1));\n%! assert (p.Unmatched, struct ());\n\n## Test for patch #9241\n%!error <failed validation of 'a'.*ischar>\n%! p = inputParser ();\n%! p.addParameter (\"a\", [], @ischar);\n%! p.parse (\"a\", 1);\n\n%!test <*58112>\n%! p = inputParser ();\n%! p.addRequired (\"first\");\n%! p.addOptional (\"second\", []);\n%! p.parse (1, {\"test\", 1, 2, 3});\n%! r = p.Results;\n%! assert (r.first, 1);\n%! assert (r.second, {\"test\", 1, 2, 3});\n\n%!test <*62639>\n%! p = inputParser ();\n%! p.addOptional (\"opt\", {});\n%! p.parse ();\n%! r = p.Results;\n%! assert (r.opt, {});\n%! p.parse (\"x\");\n%! r = p.Results;\n%! assert (r.opt, \"x\");\n\n%!test <*62639>\n%! p = inputParser ();\n%! p.addOptional (\"opt\", {1,2,3});\n%! p.parse ();\n%! r = p.Results;\n%! assert (r.opt, {1,2,3});\n%! p.parse (\"x\");\n%! r = p.Results;\n%! assert (r.opt, \"x\");\n\n%!test <*64003>\n%! p = inputParser ();\n%! p.addOptional ('c',3);\n%! p.addOptional ('z',4);\n%! p.addParameter ('b',2);\n%! p.addParameter ('a',1);\n%! p.parse (30, 'b', 20, 'a',10);\n%! assert (fieldnames (p.Results), {'a'; 'b'; 'c'; 'z'});\n\n%!test <*64305>\n%! p = inputParser ();\n%! p.addParameter ('a',{});\n%! p.parse ('a', 20);\n%! assert (fieldnames (p.Results), {'a'});\n%! assert (p.Results.a, 20);\n\n%!test <*49793>\n%! p = inputParser ();\n%! p.addRequired (\"name\", @(x) validateattributes (x, {'char'}, {'nonempty'}));\n%! p.addOptional (\"year\", 0001, @(x) validateattributes (x, {'numeric'}, ...\n%!                                     {'nonempty','integer','positive'}));\n%! p.addParameter (\"color\", '-', @(x) validateattributes (x, {'char'}, ...\n%!                                                           {'nonempty'}));\n%! p.parse ('Jim', 1980, 'color', 'black');\n%! assert (p.Results.name, 'Jim');\n%! assert (p.Results.year, 1980);\n%! assert (p.Results.color, 'black');\n\n%!test <*64318>\n%! p = inputParser;\n%! p.addOptional ('p_opt', []);\n%! p.addParameter ('p1', 'p1_default');\n%! p.addParameter ('p2', 'p2_default');\n%! p.parse ();\n%! assert (size (p.UsingDefaults), [1, 3]);\n\n%!test <*66873>\n%! function validate_type (x)\n%!   validatestring (x, {'good', 'bad', 'ugly'}, 'type_check', 'type');\n%! endfunction\n%!\n%! p = inputParser;\n%! p.CaseSensitive = false;\n%! p.FunctionName = 'foo';\n%! addParameter (p, 'type', 'good', @validate_type);\n%!\n%! fail (\"parse(p, 'type', 'clint')\",\n%!       \"type_check: 'clint' \\\\(variable type\\\\) does not match any of\");\n"
  },
  {
    "path": "scripts/miscellaneous/isdeployed.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isdeployed ()\n## Return true if the current program has been compiled and is running\n## separately from the Octave interpreter and false if it is running in\n## the Octave interpreter.\n##\n## Currently, this function always returns false in Octave.\n## @end deftypefn\n\nfunction tf = isdeployed ()\n  tf = false;\nendfunction\n\n\n%!assert (isdeployed (), false)\n"
  },
  {
    "path": "scripts/miscellaneous/isfile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isfile (@var{f})\n## Return true if @var{f} is a regular file and false otherwise.\n##\n## If @var{f} is a cell array of strings, @var{tf} is a logical array of the\n## same size.\n## @seealso{isfolder, exist, stat, is_absolute_filename,\n## is_rooted_relative_filename}\n## @end deftypefn\n\nfunction retval = isfile (f)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (ischar (f) || iscellstr (f)))\n    error (\"isfile: F must be a string or cell array of strings\");\n  endif\n\n  f = cellstr (f);\n  retval = false (size (f));\n  for i = 1:numel (f)\n    [info, err] = stat (f{i});\n    retval(i) = (! err && S_ISREG (info.mode));\n  endfor\n\nendfunction\n\n\n%!shared mfile\n%! mfile = which (\"isfile\");\n\n%!assert (isfile (mfile))\n%!assert (! isfile (tempdir ()))\n%!assert (isfile ({mfile, pwd()}), [true, false])\n%!assert (isfile ({mfile; pwd()}), [true; false])\n\n%!test\n%! unwind_protect\n%!   tmp = tempname ();\n%!   [d, n] = fileparts (tmp);\n%!   assert (! isfile (tmp));\n%!   save (\"-text\", tmp, \"tmp\");  # cheap way to create a file\n%!   assert (isfile (tmp));\n%!   addpath (d);\n%!   assert (! isfile (n));\n%! unwind_protect_cleanup\n%!   try, delete ([tmp, '*']); end_try_catch\n%!   try, rmpath (d); end_try_catch\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> isfile ()\n%!error isfile (\"a\", \"b\")\n%!error <F must be a string> isfile (1.0)\n"
  },
  {
    "path": "scripts/miscellaneous/isfolder.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isfolder (@var{f})\n## Return true if @var{f} is a directory and false otherwise.\n##\n## If @var{f} is a cell array of strings, @var{tf} is a logical array of the\n## same size.\n## @seealso{isfile, exist, stat, is_absolute_filename,\n## is_rooted_relative_filename}\n## @end deftypefn\n\nfunction tf = isfolder (f)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (ischar (f) || iscellstr (f)))\n    error (\"isfolder: F must be a string or cell array of strings\");\n  endif\n\n  f = cellstr (f);\n  tf = false (size (f));\n  for i = 1:numel (f)\n    [info, err] = stat (f{i});\n    tf(i) = (! err && S_ISDIR (info.mode));\n  endfor\n\nendfunction\n\n\n%!assert (isfolder (pwd ()))\n%!assert (! isfolder (tempname ()))\n%!assert (! isfolder (which (\"isfolder\")))\n%!assert (isfolder ( {pwd(), tempname()}), [true, false])\n%!assert (isfolder ( {pwd(); tempname()}), [true; false])\n\n%!test\n%! unwind_protect\n%!   tmp = tempname ();\n%!   [d, n] = fileparts (tmp);\n%!   assert (! isfolder (tmp));\n%!   mkdir (tmp);\n%!   assert (isfolder (tmp));\n%!   assert (! isfolder (n));\n%!   addpath (d);\n%!   assert (! isfolder (n));\n%! unwind_protect_cleanup\n%!   sts = rmdir (tmp);\n%!   rmpath (d);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> isfolder ()\n%!error isfolder (\"a\", \"b\")\n%!error <F must be a string> isfolder (1.0)\n"
  },
  {
    "path": "scripts/miscellaneous/ismac.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} ismac ()\n## Return true if Octave is running on a Mac OS X system and false otherwise.\n## @seealso{isunix, ispc}\n## @end deftypefn\n\nfunction tf = ismac ()\n\n  tf = __octave_config_info__ (\"mac\");\n\nendfunction\n\n\n%!assert (islogical (ismac ()))\n"
  },
  {
    "path": "scripts/miscellaneous/ismethod.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} ismethod (@var{obj}, @var{method})\n## @deftypefnx {} {@var{tf} =} ismethod (@var{class_name}, @var{method})\n## Return true if the string @var{method} is a valid method of the object\n## @var{obj} or of the class @var{clsname}.\n## @seealso{isprop, isobject, isjava, methods}\n## @end deftypefn\n\nfunction tf = ismethod (obj, method)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! (ischar (obj) || isobject (obj) || isjava (obj)))\n    error (\"ismethod: first argument must be object or class name\");\n  endif\n\n  if (! ischar (method))\n    error (\"ismethod: METHOD must be a string\");\n  endif\n\n  method_list = methods (obj);\n\n  tf = ismember (method, method_list);\n\nendfunction\n\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! assert (ismethod (javaObject (\"java.lang.String\", \"Yo\"), \"hashCode\"));\n\n%!assert (ismethod (ftp (), \"ascii\"))\n%!assert (ismethod (inputParser (), \"addRequired\"))\n"
  },
  {
    "path": "scripts/miscellaneous/ispc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} ispc ()\n## Return true if Octave is running on a Windows system and false otherwise.\n## @seealso{isunix, ismac}\n## @end deftypefn\n\nfunction tf = ispc ()\n\n  tf = __octave_config_info__ (\"windows\");\n\nendfunction\n\n\n%!assert (islogical (ispc ()))\n"
  },
  {
    "path": "scripts/miscellaneous/isunix.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isunix ()\n## Return true if Octave is running on a Unix-like system and false otherwise.\n## @seealso{ismac, ispc}\n## @end deftypefn\n\nfunction tf = isunix ()\n\n  tf = __octave_config_info__ (\"unix\");\n\nendfunction\n\n\n%!assert (islogical (isunix ()))\n"
  },
  {
    "path": "scripts/miscellaneous/jupyter_notebook.m",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nclassdef jupyter_notebook < handle\n\n  ## -*- texinfo -*-\n  ## @deftypefn  {} {@var{notebook} =} jupyter_notebook (@var{notebook_filename})\n  ## @deftypefnx {} {@var{notebook} =} jupyter_notebook (@var{notebook_filename}, @var{options})\n  ##\n  ## Run and fill the Jupyter Notebook in file @var{notebook_filename} from\n  ## within GNU Octave.\n  ##\n  ## Both text and graphical Octave outputs are supported.\n  ##\n  ## This class has a public property @code{notebook} which is a structure\n  ## representing the JSON-decoded Jupyter Notebook.  This property is\n  ## intentionally public to enable advanced notebook manipulations.\n  ##\n  ## Note: Jupyter Notebook versions (@code{nbformat}) lower than 4.0 are not\n  ## supported.\n  ##\n  ## The optional second argument @var{options} is a struct with fields:\n  ##\n  ## @itemize @bullet\n  ## @item\n  ## @code{tmpdir} to set the temporary working directory.\n  ## @end itemize\n  ##\n  ## @code{%plot} magic is supported with the following settings:\n  ##\n  ## @itemize @bullet\n  ## @item\n  ## \"@code{%plot -f <format>}\" or \"@code{%plot --format <format>}\": specifies\n  ## the image storage format.  Supported formats are:\n  ##\n  ## @itemize @minus\n  ## @item\n  ## PNG (default)\n  ##\n  ## @item SVG\n  ## (Note: If SVG images do not appear in the notebook, it is most likely\n  ## related to Jupyter Notebook security mechanisms and explicitly \"trusting\"\n  ## them will be necessary).\n  ##\n  ## @item\n  ## JPG\n  ## @end itemize\n  ##\n  ## @item\n  ## \"@code{%plot -r <number>}\" or \"@code{%plot --resolution <number>}\":\n  ## specifies the image resolution.\n  ##\n  ## @item\n  ## \"@code{%plot -w <number>}\" or \"@code{%plot --width <number>}\":\n  ## specifies the image width.\n  ##\n  ## @item\n  ## \"@code{%plot -h <number>}\" or \"@code{%plot --height <number>}\":\n  ## specifies the image height.\n  ## @end itemize\n  ##\n  ## Examples:\n  ##\n  ## @example\n  ## @group\n  ## ## Run all cells and generate the filled notebook\n  ##\n  ## ## Instantiate an object from a notebook file\n  ## notebook = jupyter_notebook (\"myNotebook.ipynb\");\n  ## ## Run the code and embed the results in the @code{notebook} property\n  ## notebook.run_all ();\n  ## ## Generate a new notebook by overwriting the original notebook\n  ## notebook.generate_notebook (\"myNotebook.ipynb\");\n  ## @end group\n  ##\n  ## @group\n  ## ## Run just the second cell and generate the filled notebook\n  ##\n  ## ## Instantiate an object from a notebook file\n  ## notebook = jupyter_notebook (\"myNotebook.ipynb\");\n  ## ## Run the code and embed the results in the @code{notebook} property\n  ## notebook.run (2)\n  ## ## Generate a new notebook in a new file\n  ## notebook.generate_notebook (\"myNewNotebook.ipynb\");\n  ## @end group\n  ##\n  ## @group\n  ## ## Generate an Octave script from a notebook\n  ##\n  ## ## Instantiate an object from a notebook file\n  ## notebook = jupyter_notebook (\"myNotebook.ipynb\");\n  ## ## Generate the Octave script\n  ## notebook.generate_octave_script (\"jup_script.m\");\n  ## @end group\n  ## @end example\n  ##\n  ## @seealso{jsondecode, jsonencode}\n  ## @end deftypefn\n\n  properties\n\n    notebook = struct ();\n\n  endproperties\n\n  properties (Access = \"private\")\n\n    context = struct (\"ans\", \"\");\n\n    ## Note: This name needs to be stored in a property because it is\n    ## set in the constructor but used in some other methods.  However,\n    ## we want to defer calling tempname() until immediately before\n    ## calling mkdir().  The temporary directory currently created and\n    ## deleted in the constructor and the name is reset to the empty\n    ## string when the directory is deleted.  Another possible\n    ## implementation might be to generate the name and create the\n    ## temporary directory here, then delete it in the class destructor.\n\n    tmpdir = \"\";\n\n  endproperties\n\n  methods\n\n    function obj = jupyter_notebook (notebook_filename, options)\n\n      if (nargin < 1)\n        print_usage ();\n      endif\n\n      if (! (ischar (notebook_filename) && isrow (notebook_filename)))\n        error (\"jupyter_notebook: NOTEBOOK_FILENAME must be a string\");\n      endif\n\n      ## Validate options if present.\n      if (nargin == 2 && ! isstruct (options))\n        error (\"jupyter_notebook: OPTIONS must be a struct\");\n      endif\n      if (nargin == 2 && isfield (options, \"tmpdir\"))\n        obj.tmpdir = options.tmpdir;\n      endif\n\n      obj.notebook = jsondecode (fileread (notebook_filename),\n                                 \"makeValidName\", false);\n\n      ## Validate the notebook's format according to nbformat: 4.0\n      if (! all (isfield (obj.notebook,\n                          {\"metadata\", \"nbformat\", \"nbformat_minor\", \"cells\"})))\n        error (\"jupyter_notebook: invalid format for Jupyter notebooks\");\n      endif\n\n      ## Issue a warning if the format is lower than 4.0.\n      if (obj.notebook.nbformat < 4)\n        warning ([\"jupyter_notebook: nbformat versions lower than 4.0 are \", ...\n                  \"not supported\"]);\n      endif\n\n      ## Handle the case of only one cell.\n      ## Make \"obj.notebook.cells\" a cell of structs to match the format.\n      if (numel (obj.notebook.cells) == 1)\n        obj.notebook.cells = {obj.notebook.cells};\n      endif\n\n      ## Handle the case where the cells have the same keys.\n      ## Make \"obj.notebook.cells\" a cell of structs, instead of struct array,\n      ## to unify the indexing method.\n      if (isstruct (obj.notebook.cells))\n        obj.notebook.cells = num2cell (obj.notebook.cells);\n      endif\n\n      for i = 1:numel (obj.notebook.cells)\n        nbcell = obj.notebook.cells{i};\n        if (! isfield (nbcell, \"source\"))\n          error ('jupyter_notebook: cells must contain a \"source\" field');\n        endif\n\n        if (! isfield (nbcell, \"cell_type\"))\n          error ('jupyter_notebook: cells must contain a \"cell_type\" field');\n        endif\n\n        ## Handle null JSON values which are decoded into empty arrays.\n        if (isfield (nbcell, \"execution_count\")\n            && numel (nbcell.execution_count) == 0)\n          obj.notebook.cells{i}.execution_count = 1;\n        endif\n\n        ## Handle the case of only one output in the cell.\n        ## Make the outputs of the cell a cell of structs to match the format.\n        if (isfield (nbcell, \"outputs\") && numel (nbcell.outputs) == 1)\n          obj.notebook.cells{i}.outputs = {obj.notebook.cells{i}.outputs};\n        endif\n      endfor\n\n    endfunction\n\n\n    function generate_octave_script (obj, script_filename)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {} generate_octave_script (@var{script_filename})\n      ##\n      ## Write an Octave script that has the contents of the Jupyter Notebook\n      ## stored in the @code{notebook} attribute to @var{script_filename}.\n      ##\n      ## Non-code cells are generated as block comments.\n      ##\n      ## See @code{help jupyter_notebook} for examples.\n      ##\n      ## @seealso{jupyter_notebook}\n      ## @end deftypefn\n\n      if (nargin != 2)\n        print_usage ();\n      endif\n\n      if (! (ischar (script_filename) && isrow (script_filename)))\n        error (\"jupyter_notebook: SCRIPT_FILENAME must be a string\");\n      endif\n\n      fid = fopen (script_filename, \"w\");\n\n      for i = 1:numel (obj.notebook.cells)\n        nbcell = obj.notebook.cells{i};\n        is_markdown = strcmp (nbcell.cell_type, \"markdown\");\n\n        if (is_markdown)\n          fputs (fid, \"\\n#{\\n\");\n        endif\n\n        for k = 1:numel (nbcell.source)\n          fputs (fid, nbcell.source{k});\n        endfor\n\n        if (is_markdown)\n          fputs (fid, \"\\n#}\\n\");\n        endif\n        fputs (fid, \"\\n\");\n      endfor\n      fclose (fid);\n\n    endfunction\n\n\n    function generate_notebook (obj, notebook_filename)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {} generate_notebook (@var{notebook_filename})\n      ##\n      ## Write the Jupyter Notebook stored in the @code{notebook} attribute to\n      ## @var{notebook_filename}.\n      ##\n      ## The @code{notebook} attribute is encoded to JSON text.\n      ##\n      ## See @code{help jupyter_notebook} for examples.\n      ##\n      ## @seealso{jupyter_notebook}\n      ## @end deftypefn\n\n      if (nargin != 2)\n        print_usage ();\n      endif\n\n      if (! (ischar (notebook_filename) && isrow (notebook_filename)))\n        error (\"jupyter_notebook: NOTEBOOK_FILENAME must be a string\");\n      endif\n\n      fid = fopen (notebook_filename, \"w\");\n\n      fputs (fid, jsonencode (obj.notebook,\n                              \"ConvertInfAndNaN\", false,\n                              \"PrettyPrint\", true));\n\n      fclose (fid);\n\n    endfunction\n\n\n    function run (obj, cell_index)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {} run (@var{cell_index})\n      ##\n      ## Run the Jupyter Notebook cell with index @var{cell_index} and\n      ## eventually replace previous output cells in the object.\n      ##\n      ## The first Jupyter Notebook cell has the index 1.\n      ##\n      ## Note: The code evaluation of the Jupyter Notebook cells is done in a\n      ## separate Jupyter Notebook context.  Thus, currently open figures and\n      ## workspace variables won't be affected by executing this function.\n      ## However, current workspace variables cannot be accessed either.\n      ##\n      ## See @code{help jupyter_notebook} for examples.\n      ##\n      ## @seealso{jupyter_notebook}\n      ## @end deftypefn\n\n      if (nargin != 2)\n        print_usage ();\n      endif\n\n      if (! (isscalar (cell_index) && isindex (cell_index)))\n        error (\"jupyter_notebook: CELL_INDEX must be a scalar positive integer\");\n      endif\n\n      if (cell_index > numel (obj.notebook.cells))\n        error (\"jupyter_notebook: CELL_INDEX is out of bound\");\n      endif\n\n      nbcell = obj.notebook.cells{cell_index};\n\n      if (! strcmp (nbcell.cell_type, \"code\"))\n        return;\n      endif\n\n      ## Remove previous outputs.\n      obj.notebook.cells{cell_index}.outputs = {};\n\n      if (isempty (nbcell.source))\n        return;\n      endif\n\n      ## Default values for printOptions.\n      printOptions.imageFormat = \"png\";\n      printOptions.resolution = \"0\";\n\n      ## The default width and height in Jupyter notebook\n      printOptions.width = \"640\";\n      printOptions.height = \"480\";\n\n      ## Parse \"plot magic\" commands.\n      ## https://github.com/Calysto/metakernel/blob/master/metakernel/magics/README.md#plot\n      for j = 1 : numel (nbcell.source)\n        if (strncmpi (nbcell.source{j}, \"%plot\", 5))\n          magics = strsplit (strtrim (nbcell.source{j}));\n          for i = 1 : numel (magics)\n            if (any (strcmp (magics{i}, {\"-f\", \"--format\"}))\n                && (i < numel (magics)))\n              printOptions.imageFormat = magics{i+1};\n            endif\n            if (any (strcmp (magics{i}, {\"-r\", \"--resolution\"}))\n                && (i < numel (magics)))\n              printOptions.resolution = magics{i+1};\n            endif\n            if (any (strcmp (magics{i}, {\"-w\", \"--width\"}))\n                && (i < numel (magics)))\n              printOptions.width = magics{i+1};\n            endif\n            if (any (strcmp (magics{i}, {\"-h\", \"--height\"}))\n                && (i < numel (magics)))\n              printOptions.height = magics{i+1};\n            endif\n          endfor\n        endif\n      endfor\n\n      ## Remember previously opened figures.\n      fig_ids = findall (groot, \"type\", \"figure\");\n\n      ## Create a new figure, if there are existing plots.\n      if (! isempty (fig_ids))\n        newFig = figure ();\n      endif\n\n      unwind_protect\n        stream_output = struct (\"name\", \"stdout\", \"output_type\", \"stream\");\n\n        output_lines = obj.evalCode (strjoin (nbcell.source));\n\n        if (! isempty (output_lines))\n          stream_output.text = {output_lines};\n        endif\n\n        if (isfield (stream_output, \"text\"))\n          obj.notebook.cells{cell_index}.outputs{end+1} = stream_output;\n        endif\n\n      unwind_protect_cleanup\n        ## If there are existing plots and newFig is empty, delete it.\n        if (exist (\"newFig\") && ishandle (newFig) && ...\n            isempty (get (newFig, \"children\")))\n          delete (newFig);\n        endif\n\n        ## Check for newly created figures.\n        fig_ids_new = setdiff (findall (groot, \"type\", \"figure\"), fig_ids);\n\n        if (! isempty (fig_ids_new))\n          if (! isempty (obj.tmpdir) && exist (obj.tmpdir, \"dir\"))\n            ## Delete open figures before raising the error.\n            delete (fig_ids_new);\n            error ([\"JupyterNotebook: temporary directory %s exists.  \", ...\n                    \"Please remove it manually.\"], obj.tmpdir);\n          endif\n\n          if (isempty (obj.tmpdir))\n            obj.tmpdir = tempname ();\n            clear_tmpdir_property = true;\n          else\n            clear_tmpdir_property = false;\n          endif\n          [status, msg] = mkdir (obj.tmpdir);\n          if (status == 0)\n            ## Delete open figures before raising the error.\n            delete (fig_ids_new);\n            error ([\"jupyter_notebook: cannot create a temporary directory.  \", ...\n                    msg]);\n          endif\n\n          for i = 1:numel (fig_ids_new)\n            figure (fig_ids_new(i), \"visible\", \"off\");\n            obj.embedImage (cell_index, fig_ids_new(i), printOptions);\n            delete (fig_ids_new(i));\n          endfor\n\n          [status, msg] = rmdir (obj.tmpdir);\n          if (status == 0)\n            error ([\"jupyter_notebook: cannot delete the temporary \", ...\n                    \"directory.  \", msg]);\n          endif\n          if (clear_tmpdir_property)\n            obj.tmpdir = \"\";\n          endif\n        endif\n      end_unwind_protect\n\n    endfunction\n\n\n    function run_all (obj)\n\n      ## -*- texinfo -*-\n      ## @deftypefn {} {} run_all ()\n      ##\n      ## Run all Jupyter Notebook cells and eventually replace previous output\n      ## cells in the object.\n      ##\n      ## Note: The code evaluation of the Jupyter Notebook cells is done in a\n      ## separate Jupyter Notebook context.  Thus, currently open figures and\n      ## workspace variables won't be affected by executing this function.\n      ## However, current workspace variables cannot be accessed either.\n      ##\n      ## See @code{help jupyter_notebook} for examples.\n      ##\n      ## @seealso{jupyter_notebook}\n      ## @end deftypefn\n\n      if (nargin != 1)\n        print_usage ();\n      endif\n\n      for i = 1:numel (obj.notebook.cells)\n        obj.run (i);\n      endfor\n\n    endfunction\n\n  endmethods\n\n\n  methods (Access = \"private\")\n\n    function retval = evalCode (__obj__, __code__)\n\n      ## Evaluate the code string \"__code__\" using \"evalc\".\n      ## Before the code is evaluated, the previous notebook context is\n      ## loaded from \"__obj__\" and the new context is saved to that struct.\n\n      if (nargin != 2)\n        print_usage ();\n      endif\n\n      if (isempty (__code__))\n        retval = [];\n        return;\n      endif\n\n      if (! (ischar (__code__) && isrow (__code__)))\n        error (\"jupyter_notebook: CODE must be a string\");\n      endif\n\n      __obj__.loadContext ();\n\n      ## Add a statement to detect the value of the variable \"ans\"\n      __code__ = [__code__, \"\\nans\"];\n\n      retval = strtrim (evalc (__code__, [\"printf (\\\"error: \\\"); \", ...\n                                          \"printf (lasterror.message)\"]));\n\n      ## Handle the \"ans\" variable in the context.\n      start_index = rindex (retval, \"ans =\") + 6;\n      if (start_index > 6)\n        if (start_index <= length (retval))\n          end_index = start_index;\n          ## FIXME: loops are slow.\n          idx = find (retval(start_index+1:end) == \"\\n\", 1);\n          if (idx)\n            end_index = start_index + idx;\n          else\n            end_index = length (retval);\n          endif\n          __obj__.context.ans = retval(start_index:end_index);\n        else\n          end_index = length (retval);\n          __obj__.context.ans = \"\";\n        endif\n\n        ## Delete the output of the additional statement if the execution\n        ## is completed with no errors.\n        if (end_index == length (retval))\n          ## Remove the extra new line if there are other outputs with\n          ## the \"ans\" statement output\n          if (start_index == 7)\n            start_index = 1;\n          else\n            start_index -= 7;\n          endif\n          retval(start_index:end_index) = \"\";\n        endif\n      endif\n\n      __obj__.saveContext ();\n\n    endfunction\n\n\n    function saveContext (obj)\n\n      ## Save the context in private \"obj\" attribute.\n\n      ## Handle the \"ans\" variable in the context.\n      obj.context = struct (\"ans\", obj.context.ans);\n\n      forbidden_var_names = {\"__code__\", \"__obj__\", \"ans\"};\n\n      ## Get variable names.\n      var_names = {evalin(\"caller\", \"whos\").name};\n\n      ## Store all variables to context.\n      for i = 1:numel (var_names)\n        if (! any (strcmp (var_names{i}, forbidden_var_names)))\n          obj.context.(var_names{i}) = evalin (\"caller\", var_names{i});\n        endif\n      endfor\n\n    endfunction\n\n\n    function loadContext (obj)\n\n      ## Load the context from private \"obj\" attribute.\n      for [val, key] = obj.context\n        assignin (\"caller\", key, val);\n      endfor\n\n    endfunction\n\n\n    function embedImage (obj, cell_index, figHandle, printOptions)\n\n      ## Embed images in the notebook.\n      ##\n      ## To support a new format:\n      ## 1. Create a new function that embeds the new format\n      ##    (e.g., embed_svg_image).\n      ## 2. Add a new case to the switch-statement below.\n\n      if (isempty (get (figHandle, \"children\")))\n        error_text = {\"The figure is empty!\"};\n        obj.addErrorOutput (cell_index, \"The figure is empty!\");\n        return;\n      endif\n\n      ## Check if the resolution is correct\n      if (isempty (str2num (printOptions.resolution)))\n        obj.addErrorOutput (cell_index,\n                            \"A number is required for resolution, not a string\");\n        return;\n      endif\n\n      ## Check if the width is correct\n      if (isempty (str2num (printOptions.width)))\n        obj.addErrorOutput (cell_index,\n                            \"A number is required for width, not a string\");\n        return;\n      endif\n\n      ## Check if the height is correct\n      if (isempty (str2num (printOptions.height)))\n        obj.addErrorOutput (cell_index,\n                            \"A number is required for height, not a string\");\n        return;\n      endif\n\n      switch (lower (printOptions.imageFormat))\n        case \"png\"\n          display_output = obj.embed_png_jpg_image (figHandle,\n                                                    printOptions, \"png\");\n        case \"jpg\"\n          display_output = obj.embed_png_jpg_image (figHandle,\n                                                    printOptions, \"jpg\");\n        case \"svg\"\n          display_output = obj.embed_svg_image (figHandle, printOptions);\n        otherwise\n          obj.addErrorOutput (cell_index, [\"Cannot embed the \\'\", ...\n                                           printOptions.imageFormat, ...\n                                           \"\\' image format\\n\"]);\n          return;\n      endswitch\n\n      obj.notebook.cells{cell_index}.outputs{end+1} = display_output;\n\n    endfunction\n\n\n    function dstruct = embed_png_jpg_image (obj, figHandle, printOptions, fmt)\n\n      if (strcmp (fmt, \"png\"))\n        mime = \"image/png\";\n      else\n        mime = \"image/jpeg\";\n      endif\n\n      image_path = fullfile (obj.tmpdir, [\"temp.\" fmt]);\n      print (figHandle, image_path, [\"-d\" fmt],\n             [\"-r\" printOptions.resolution]);\n\n      dstruct.output_type = \"display_data\";\n      dstruct.metadata.(mime).width  = printOptions.width;\n      dstruct.metadata.(mime).height = printOptions.height;\n      dstruct.data.(\"text/plain\") = {\"<IPython.core.display.Image object>\"};\n      dstruct.data.(mime) = base64_encode (uint8 (fileread (image_path)));\n\n      delete (image_path);\n\n    endfunction\n\n\n    function dstruct = embed_svg_image (obj, figHandle, printOptions)\n\n      image_path = fullfile (obj.tmpdir, \"temp.svg\");\n      print (figHandle, image_path, \"-dsvg\", [\"-r\" printOptions.resolution]);\n\n      dstruct.output_type = \"display_data\";\n      dstruct.metadata = struct ();\n      dstruct.data.(\"text/plain\") = {\"<IPython.core.display.SVG object>\"};\n      dstruct.data.(\"image/svg+xml\") = strsplit (fileread (image_path), \"\\n\");\n\n      ## FIXME: The following is a workaround until we can properly print\n      ##        SVG images in the right width and height.\n      ## Detect the <svg> tag; it is either the first or the second item.\n      if (strncmpi (dstruct.data.(\"image/svg+xml\"){1}, \"<svg\", 4))\n        i = 1;\n      else\n        i = 2;\n      endif\n\n      ## Embed the width and height in the image itself\n      svg_tag = dstruct.data.(\"image/svg+xml\"){i};\n      svg_tag = regexprep (svg_tag, 'width=\".*?\"',\n                           ['width=\"' printOptions.width 'px\"']);\n      svg_tag = regexprep (svg_tag, 'height=\".*?\"',\n                           ['height=\"' printOptions.height 'px\"']);\n      dstruct.data.(\"image/svg+xml\"){i} = svg_tag;\n\n      delete (image_path);\n\n    endfunction\n\n\n    function addErrorOutput (obj, cell_index, error_msg)\n\n      stream_output.name        = \"stderr\";\n      stream_output.output_type = \"stream\";\n      stream_output.text        = {error_msg};\n      obj.notebook.cells{cell_index}.outputs{end+1} = stream_output;\n\n    endfunction\n\n  endmethods\n\nendclassdef\n\n\n## Note: Functional BIST tests are located in the 'test/jupyter-notebook'\n##       directory.\n\n## Test input validation\n%!error <Invalid call> jupyter_notebook ()\n%!error <NOTEBOOK_FILENAME must be a string> jupyter_notebook (1)\n%!error <NOTEBOOK_FILENAME must be a string> jupyter_notebook (['a';'b'])\n%!error <OPTIONS must be a struct> jupyter_notebook (\"fname\", 1)\n"
  },
  {
    "path": "scripts/miscellaneous/license.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} license\n## @deftypefnx {} {} license inuse\n## @deftypefnx {} {} license inuse @var{feature}\n## @deftypefnx {} {} license (\"inuse\")\n## @deftypefnx {} {@var{license_struct} =} license (\"inuse\")\n## @deftypefnx {} {@var{license_struct} =} license (\"inuse\", @var{feature})\n## @deftypefnx {} {@var{status} =} license (\"test\", @var{feature})\n## @deftypefnx {} {@var{status} =} license (\"checkout\", @var{feature})\n## @deftypefnx {} {[@var{status}, @var{errmsg}] =} license (\"checkout\", @var{feature})\n## Get license information for Octave and Octave packages.\n##\n## GNU Octave is free software distributed under the GNU General Public\n## License (GPL), and a license manager makes no sense.  This function is\n## provided only for @sc{matlab} compatibility.\n##\n## When called with no extra input arguments, it returns the Octave license,\n## otherwise the first input defines the operation mode and must be one of\n## the following strings: @code{inuse}, @code{test}, and @code{checkout}.\n## The optional @var{feature} argument can either be @qcode{\"octave\"} (core)\n## or the name of an Octave package.\n##\n## @table @asis\n## @item @qcode{\"inuse\"}\n## Print a list of loaded features, i.e., \"octave\" and the list of loaded\n## packages.  If an output is requested, it returns a struct array with\n## the fields @qcode{\"feature\"}, and @qcode{\"user\"}.\n##\n## @item @qcode{\"test\"}\n## Return true if the specified @var{feature} is installed, false otherwise.\n##\n## An optional third argument @qcode{\"enable\"} or @qcode{\"disable\"} is\n## accepted but ignored.\n##\n## @item @qcode{\"checkout\"}\n## Return true if the specified @var{feature} is installed, false otherwise.\n## An optional second output will have an error message if a package is not\n## installed.\n##\n## @end table\n##\n## @seealso{pkg, ver, version}\n## @end deftypefn\n\nfunction [status, errmsg] = license (cmd, feature, toggle)\n\n  if (nargin == 0)\n    ## then only give information about Octave core\n    status = \"GNU General Public License v3+\";\n    return;\n  endif\n\n  [features, loaded] = get_all_features ();\n\n  switch (lower (cmd))\n    case \"inuse\"\n      features = features(loaded);\n\n      if (nargin > 1)\n        features = features(strcmp (features, feature));\n      endif\n      if (nargout == 0)\n        printf (\"%s\\n\", features{:});\n      else\n        status = struct (\"feature\", features, \"user\", get_username ());\n      endif\n\n    case \"test\"\n      if (nargin < 2)\n        print_usage ();\n      endif\n\n      if (nargin > 2)\n        ## We ignore the toggle argument because... what's the point?  We\n        ## don't need a license management system on Octave.  This function\n        ## will return true, even if anyone tries to disable a license.\n        switch (lower (toggle))\n          case \"enable\"   # do nothing\n          case \"disable\"  # do nothing\n          otherwise\n            error (\"license: TOGGLE must be enable or disable\");\n        endswitch\n      endif\n\n      status = any (strcmp (features, feature));\n\n    case \"checkout\"\n      ## I guess we could have the checkout command load packages but it's not\n      ## really the same thing.  The closest we have is simply to check if\n      ## there is a package with the feature name, and give an error if not.\n      if (nargin != 2)\n        print_usage ();\n      endif\n\n      status = any (strcmp (features, feature));\n      errmsg = \"\";\n\n      if (! status)\n        errmsg = ['No package named \"' feature '\" installed'];\n      endif\n\n    otherwise\n      print_usage ();\n  endswitch\n\nendfunction\n\nfunction username = get_username ()\n\n  pw = getpwuid (getuid ());\n  if (isstruct (pw))\n    username = pw.name;\n  else\n    username = \"octave_user\";\n  endif\n\nendfunction\n\nfunction [features, loaded] = get_all_features ()\n  pkg_list = pkg (\"list\");\n  features = {\"octave\", ...\n              cellfun(@(x) x.name, pkg_list, \"uniformoutput\", false){:}};\n  loaded = [true, cellfun(@(x) x.loaded, pkg_list)];\nendfunction\n\n\n%!assert (license (), \"GNU General Public License v3+\")\n%!assert ((license (\"inuse\", \"octave\")).feature, \"octave\")\n\n%!shared list\n%!test\n%! list = pkg (\"list\");\n%! for idx = 1: numel (list)\n%!   name = list{idx}.name;\n%!   if (list{idx}.loaded)\n%!     assert ((license (\"inuse\", name)).feature, name);\n%!   else\n%!     rv = license (\"inuse\", name);\n%!     assert (isstruct (rv));\n%!     assert (all (isfield (rv, {\"feature\", \"user\"})));\n%!   endif\n%! endfor\n\n%!assert (license (\"test\", \"octave\"), true)\n%!assert (license (\"test\", \"not_a_valid package name\"), false)\n\n%!test\n%! for idx = 1: numel (list)\n%!   assert (license (\"test\", list{idx}.name), true);\n%! endfor\n\n%!assert (license (\"checkout\", \"octave\"), true)\n\n%!test\n%! [s, e] = license (\"checkout\", \"NOT_A_PACKAGE\");\n%! assert (e, 'No package named \"NOT_A_PACKAGE\" installed');\n\n## Test input validation\n%!error license (\"not_inuse\")\n%!error license (\"not_test\", \"octave\", \"enable\")\n%!error <TOGGLE must be enable or disable> license (\"test\", \"octave\", \"invalid_toggle\")\n"
  },
  {
    "path": "scripts/miscellaneous/list_primes.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{p} =} list_primes ()\n## @deftypefnx {} {@var{p} =} list_primes (@var{n})\n## List the first @var{n} primes.\n##\n## If @var{n} is unspecified, the first 25 primes are listed.\n## @seealso{primes, isprime}\n## @end deftypefn\n\nfunction p = list_primes (n = 25)\n\n  if (! isreal (n) || ! isscalar (n))\n    error (\"list_primes: N must be a real scalar\");\n  endif\n\n  n = floor (n);\n\n  if (n < 1)\n    p = [];\n    return;\n  elseif (n == 1)\n    p = 2;\n    return;\n  endif\n\n  list = primes (n * log (5 * n));\n  if (numel (list) < n)\n    ## Algorithm tested up to n=10,000 without failure.\n    error (\"list_primes: Algorithm failed.  Try primes (n*log (6*n))(1:n)\");\n  endif\n\n  p = list(1:n);\n\nendfunction\n\n\n%!assert (list_primes (), [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, ...\n%!                         43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97])\n%!assert (list_primes (5), [2, 3, 5, 7, 11])\n\n%!assert (list_primes (0), [])\n%!assert (list_primes (1), [2])\n\n## Test input validation\n%!error <N must be a real scalar> list_primes (i)\n%!error <N must be a real scalar> list_primes ([1 2])\n"
  },
  {
    "path": "scripts/miscellaneous/loadobj.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{b} =} loadobj (@var{a})\n## Method of a class to manipulate an object after loading it from a file.\n##\n## The function @code{loadobj} is called when the object @var{a} is loaded\n## using the @code{load} function.  An example of the use of @code{saveobj}\n## might be to add fields to an object that don't make sense to be saved.\n## For example:\n##\n## @example\n## @group\n## function b = loadobj (a)\n##   b = a;\n##   b.addmissingfield = addfield (b);\n## endfunction\n## @end group\n## @end example\n##\n## @seealso{saveobj, class}\n## @end deftypefn\n\nfunction b = loadobj (a)\n  error ('loadobj: not defined for class \"%s\"', class (a));\nendfunction\n"
  },
  {
    "path": "scripts/miscellaneous/ls.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ls\n## @deftypefnx {} {} ls @var{filenames}\n## @deftypefnx {} {} ls @var{options}\n## @deftypefnx {} {} ls @var{options} @var{filenames}\n## @deftypefnx {} {@var{list} =} ls (@dots{})\n##\n## List directory contents.\n##\n## The @code{ls} function forwards to the @code{ls} command if it is available.\n## It falls back to calling the native operating system's directory listing\n## command.  Available @var{options} may vary from system to system.\n##\n## Filenames are subject to shell expansion if they contain any wildcard\n## characters @samp{*}, @samp{?}, @samp{[]}.  If these wildcard characters are\n## escaped with a backslash @samp{\\} (e.g., @samp{\\*}) then they are not\n## treated as wildcards, but instead as the corresponding literal character.\n##\n## If the optional output @var{list} is requested then @code{ls} returns a\n## character array with one row for each file/directory name.\n##\n## Example usage on a UNIX-like system:\n##\n## @example\n## @group\n## ls -l\n##      @print{} total 12\n##      @print{} -rw-r--r--   1 jwe  users  4488 Aug 19 04:02 foo.m\n##      @print{} -rw-r--r--   1 jwe  users  1315 Aug 17 23:14 bar.m\n## @end group\n## @end example\n##\n## @seealso{dir, readdir, glob, what, stat, filesep, ls_command}\n## @end deftypefn\n\nfunction list = ls (varargin)\n\n  if (! iscellstr (varargin))\n    error (\"ls: all arguments must be character strings\");\n  endif\n\n  ls_cmd = ls_command ();\n\n  if (nargin > 0)\n    args = tilde_expand (varargin);\n\n    if (ispc ())\n      ## Windows platform\n      if (strncmp (ls_cmd, \"ls\", 2))\n        ## Replace backslashes with forward slashes (unless they escape a\n        ## wildcard character)\n        args = regexprep (args, '\\\\(?![*?\\[\\]])', '/');\n        ## Enclose paths, potentially having spaces, in double quotes:\n        args = strcat ('\"', args, '\"');\n        ## Exclude glob patterns and escaped characters from quoted part of\n        ## FILENAMES string\n        args = regexprep (args, '(?<!\\\\)([*?])', '\"$1\"');\n        args = regexprep (args, '(?<!\\\\)\\[', '\"[');\n        args = regexprep (args, '(?<!\\\\)\\]', ']\"');\n        args = regexprep (args, '(\\\\.)', '\"$1\"');\n      else\n        idx = ! strncmp (args, '/', 1);\n        ## Enclose paths, potentially having spaces, in double quotes:\n        args(idx) = strcat ('\"', args(idx), '\"');\n        ## shell (cmd.exe) on MinGW uses '^' as escape character\n        args = regexprep (args, '([^\\w.*?])', '^$1');\n      endif\n    else\n      ## Escape any special characters in filename\n      args = regexprep (args, '(?<!\\\\)([^][\\w.*?-\\\\])', '\\\\$1');\n      ## Undo escaped spaces following command args\n      ## Only used for command form where single str contains many args.\n      ## Example: list = ls (\"-l /usr/bin\")\n      args = regexprep (args, '(-\\w+)(?:\\\\ )+', '$1 ');\n    endif\n\n    args = sprintf (\"%s \", args{:});\n  else\n    args = \"\";\n  endif\n\n  if (nargout > 0 && strncmp (ls_cmd, \"ls\", 2))\n    args = [\"-1 \" args];\n  endif\n\n  cmd = [ls_cmd \" \" args];\n\n  if (page_screen_output () || nargout > 0)\n    [status, output] = system (cmd);\n\n    if (status != 0)\n      error (\"ls: command exited abnormally with status %d\\n\", status);\n    elseif (nargout == 0)\n      puts (output);\n    else\n      list = strvcat (regexp (output, \"[\\r\\n]+\", \"split\"){:});\n    endif\n  else\n    ## Just let the output flow if the pager is off.  That way the\n    ## output from things like \"ls -R /\" will show up immediately and\n    ## we won't have to buffer all the output.\n    system (cmd);\n  endif\n\nendfunction\n\n\n%!test\n%! list = ls ();\n%! assert (ischar (list));\n%! assert (! isempty (list));\n\n%!test\n%! if (isunix ())\n%!   list = ls (\"/\");\n%!   list = (list')(:)';   # transform to a single row vector\n%!   assert (! isempty (strfind (list, \"sbin\")));\n%!   list2 = ls (\"-l /\");\n%!   list2 = (list2')(:)';   # transform to a single row vector\n%!   assert (! isempty (strfind (list2, \"sbin\")));\n%!   assert (rows (list) == rows (list2));\n%! endif\n\n%!error <all arguments must be character strings> ls (1)\n## Test below is valid, but produces confusing output on screen\n%!#error <command exited abnormally> ls (\"-!\")\n"
  },
  {
    "path": "scripts/miscellaneous/ls_command.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{val} =} ls_command ()\n## @deftypefnx {} {@var{old_val} =} ls_command (@var{new_val})\n## Query or set the shell command used by Octave's @code{ls} command.\n## @seealso{ls}\n## @end deftypefn\n\nfunction old_val = ls_command (new_val)\n\n  persistent __ls_command__;\n\n  if (isempty (__ls_command__))\n    if (ispc () && system (\"where ls\", true))\n      ## Windows uses different ls_command\n      __ls_command__ = \"dir /D\";\n    else\n      __ls_command__ = \"ls -C\";\n    endif\n  endif\n\n  if (nargin == 0 || nargin == 1)\n\n    old_val = __ls_command__;\n\n    if (nargin == 1)\n      if (! ischar (new_val))\n        error (\"ls_command: argument must be a character string\");\n      endif\n\n      __ls_command__ = new_val;\n    endif\n\n  endif\n\nendfunction\n\n\n%!test\n%! cmd = ls_command ();\n%! assert (ischar (cmd));\n%! if (ispc () && system (\"where ls\", true))\n%!   assert (cmd(1:3), \"dir\");\n%! else\n%!   assert (cmd(1:2), \"ls\");\n%! endif\n\n%!error <argument must be a character string> ls_command (123)\n"
  },
  {
    "path": "scripts/miscellaneous/memoize.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{mem_fcn_handle} =} memoize (@var{fcn_handle})\n##\n## Create a memoized version @var{mem_fcn_handle} of function @var{fcn_handle}.\n##\n## Each call to the memoized version @var{mem_fcn_handle} checks the inputs\n## against an internally maintained table, and if the inputs have occurred\n## previously, then the result of the function call is returned from the table\n## itself instead of evaluating the full function again.  This speeds up the\n## execution of functions that are called with the same inputs multiple times.\n##\n## For example, here we take a slow user-written function named @code{slow_fcn}\n## and memoize it to a new handle @code{cyc}.  The first executions of both\n## versions take the same time, but the subsequent executions of the memoized\n## version returns the previously computed value, thus reducing 2.4 seconds of\n## runtime to only 2.4 milliseconds.  The final check verifies that the same\n## result was returned from both versions.\n##\n## @example\n## @group\n## >> tic; @var{p} = slow_fcn (5040); toc\n## Elapsed time is 2.41244 seconds.\n## >> tic; @var{p} = slow_fcn (5040); toc\n## Elapsed time is 2.41542 seconds.\n##\n## >> cyc = memoize (@@slow_fcn);\n## >> tic; @var{r} = cyc (5040); toc\n## Elapsed time is 2.42609 seconds.\n## >> tic; @var{r} = cyc (5040); toc\n## Elapsed time is 0.00236511 seconds.\n##\n## >> all (@var{p} == @var{r})\n## ans = 1\n## @end group\n## @end example\n##\n## @seealso{clearAllMemoizedCaches}\n## @end deftypefn\n\nfunction mem_fcn_handle = memoize (fcn_handle)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  if (! is_function_handle (fcn_handle))\n    error (\"memoize: FCN_HANDLE must be a function handle\");\n  endif\n\n  mem_fcn_handle = __memoize__ (fcn_handle);\n\nendfunction\n\n\n%!test\n%! fcn1 = memoize (@sin);\n%! assert (isa (fcn1, \"matlab.lang.MemoizedFunction\"));\n%! fcn1 (pi);\n%! fcn2 = memoize (@sin);\n%! fcn2 (2*pi);\n%! assert (isequal (fcn1, fcn2));\n\n%!test\n%! fcn = memoize (@rand);\n%! a = fcn ();\n%! b = fcn ();\n%! assert (a, b);\n%! fcn2 = memoize (@rand);\n%! c = fcn2 ();\n%! assert (a, c);\n\n%!test\n%! fcn = memoize (@plus);\n%! fcn.stats;\n%! stats (fcn);\n%! clearCache (fcn);\n%! fcn.clearCache;\n\n## Test input validation\n%!error <Invalid call> memoize ();\n%!error <FCN_HANDLE must be a function handle> memoize (1);\n"
  },
  {
    "path": "scripts/miscellaneous/memory.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} memory ()\n## @deftypefnx {} {[@var{userdata}, @var{systemdata}] =} memory ()\n## Display or return information about the memory usage of Octave.\n##\n## If the function is called without output arguments, a table with an overview\n## of the current memory consumption is displayed.\n##\n## The output argument @var{userdata} is a structure with the following fields\n## containing data for the Octave process:\n##\n## @table @code\n## @item MaxPossibleArrayBytes\n## Maximum size for an array to be allocated.  Be aware that this includes\n## @emph{all} physical memory and swap space.  Allocating that amount of memory\n## might result in system instability, data corruption, and/or file system\n## corruption.  Note that depending on the platform (32-bit systems), the\n## largest contiguous memory block might further limit the maximum possible\n## allocatable array.  This check is not currently implemented.\n##\n## @item MemAvailableAllArrays\n## The total size of available memory in bytes.\n##\n## @item ram_available_all_arrays\n## The maximum size for an array that can be allocated in physical memory\n## (excluding swap space).  Note that depending on the platform (32-bit\n## systems), the largest contiguous memory block might further limit the\n## maximum possible allocatable array.  This check is not currently\n## implemented.\n##\n## @item  MemUsedMATLAB\n## @itemx mem_used_octave\n## The memory (including swap space) currently used by Octave in bytes.\n##\n## @item ram_used_octave\n## The physical memory (excluding swap space) currently used by Octave in\n## bytes.\n##\n## @end table\n##\n## The output argument @var{systemdata} is a nested structure with the\n## following fields containing information about the system's memory:\n##\n## @table @code\n## @item PhysicalMemory.Available\n## The currently available physical memory in bytes.\n##\n## @item PhysicalMemory.Total\n## The total physical memory in bytes.\n##\n## @item SystemMemory.Available\n## The currently available memory (including swap space) in bytes.\n##\n## @item SystemMemory.Total\n## The total memory (including swap space) in bytes.\n##\n## @item VirtualAddressSpace.Available\n## The currently available virtual address space in bytes.\n##\n## @item VirtualAddressSpace.Total\n## The total virtual address space in bytes.\n##\n## @end table\n##\n## Example #1 : print formatted table of memory usage\n##\n## @example\n## @group\n## memory ()\n## @xresult{}\n## System    RAM: 3934008 KiB,  swap: 4087804 KiB\n## Octave    RAM:  170596 KiB,  virt: 1347944 KiB\n## Free      RAM: 1954940 KiB,  swap: 4087804 KiB\n## Available RAM: 2451948 KiB, total: 6042744 KiB\n## @end group\n## @end example\n##\n## Example #2 : return structs with memory usage information\n##\n## @example\n## [userdata, systemdata] = memory ()\n## @xresult{}\n##  userdata =\n##\n##    scalar structure containing the fields:\n##\n##      MaxPossibleArrayBytes = 6.1622e+09\n##      MemAvailableAllArrays = 6.1622e+09\n##      ram_available_all_arrays = 2.4883e+09\n##      MemUsedMATLAB = 1.3825e+09\n##      mem_used_octave = 1.3825e+09\n##      ram_used_octave = 1.7824e+08\n##\n##  systemdata =\n##\n##    scalar structure containing the fields:\n##\n##      PhysicalMemory =\n##\n##        scalar structure containing the fields:\n##\n##          Available = 2.4954e+09\n##          Total = 4.0284e+09\n##\n##      SystemMemory =\n##\n##        scalar structure containing the fields:\n##\n##          Available = 6.6813e+09\n##          Total = 8.2143e+09\n##\n##      VirtualAddressSpace =\n##\n##        scalar structure containing the fields:\n##\n##          Available = 2.8147e+14\n##          Total = 2.8147e+14\n## @end example\n##\n## Programming Note: This function is implemented for Linux and Windows only.\n##\n## @seealso{computer, getpid, getrusage, nproc, uname}\n## @end deftypefn\n\nfunction [userdata, systemdata] = memory ()\n\n  if ((! isunix () || ismac ()) && ! ispc ())\n    if (nargout > 0)\n      error (\"memory: function not yet implemented for this architecture\");\n    else\n      warning (\"memory: function not yet implemented for this architecture\");\n    endif\n    return;\n  endif\n\n  kiB = 1024;\n  [architecture, bits] = computer ();\n\n  if (isunix () && ! ismac ())\n    ## Read values from pseudofiles\n    [status, meminfo] = lmemory ();\n\n    ## FIXME: Query the actual size of the user address space,\n    ##        e.g., with getrlimit (RLIMIT_AS, rlp)\n    if (log2 (bits) > 32)\n      ## 64-bit platform\n      address_space = 2^48;  # 256 TiB\n    else\n      ## 32-bit platform\n      address_space = 3 * 2^30;  # 3 GiB\n    endif\n\n    total_ram = meminfo.MemTotal * kiB;\n    total_swap = meminfo.SwapTotal * kiB;\n    free_ram = meminfo.MemFree * kiB;\n    if (isfield (meminfo, \"MemAvailable\"))\n      available_ram = meminfo.MemAvailable * kiB;\n    else\n      ## On kernels from before 2014 MemAvailable is not present.\n      ## This is a rough estimate that can be used instead.\n      available_ram = meminfo.MemFree * kiB;\n      if (isfield (meminfo, \"Cached\"))\n        ## Some platforms don't support \"Cached\" (e.g., Cygwin).\n        ## That makes the result even more unreliable.  But it might be better\n        ## than nothing.\n        available_ram += meminfo.Cached * kiB;\n      endif\n    endif\n    free_swap = meminfo.SwapFree * kiB;\n    used_ram = status.VmRSS * kiB;\n    used_virtual = status.VmSize * kiB;\n    avail_virtual = address_space - used_virtual;\n\n  elseif (ispc ())\n    [proc, sys] = __wmemory__ ();\n\n    total_ram = sys.TotalPhys;\n    total_swap = sys.TotalPageFile;\n    available_ram = sys.AvailPhys;\n    free_swap = sys.AvailPageFile;\n    used_ram = proc.WorkingSetSize;\n    used_virtual = proc.WorkingSetSize + proc.PagefileUsage;\n    avail_virtual = sys.AvailVirtual;\n    address_space = sys.TotalVirtual;\n\n  endif\n\n  available = min (available_ram + free_swap, avail_virtual);\n  ram_available = min (available_ram, avail_virtual);\n\n  ## FIXME: On 32-bit systems, the largest possible array is limited by the\n  ##        largest contiguous block in memory.\n  user.MaxPossibleArrayBytes = available;\n  user.MemAvailableAllArrays = available;\n  user.ram_available_all_arrays = ram_available;\n  user.MemUsedMATLAB = used_virtual;  # For compatibility\n  user.mem_used_octave = used_virtual;\n  user.ram_used_octave = used_ram;\n\n  syst.PhysicalMemory.Available = available_ram;\n  syst.PhysicalMemory.Total = total_ram;\n  syst.SystemMemory.Available = available_ram + free_swap;\n  syst.SystemMemory.Total = total_ram + total_swap;\n  syst.VirtualAddressSpace.Available = avail_virtual;\n  syst.VirtualAddressSpace.Total = address_space;\n\n  if (nargout)\n    userdata = user;\n    systemdata = syst;\n  else\n    unitsize = kiB;\n    unitname = 'kiB';\n    disp (sprintf (\"Octave is running on %s\", architecture))\n    disp (sprintf (\"System    RAM: %9.0f %s,  swap: %9.0f %s\",\n                   round (syst.PhysicalMemory.Total / unitsize), unitname,\n                   round (total_swap / unitsize), unitname ))\n    disp (sprintf (\"Octave    RAM: %9.0f %s,  virt: %9.0f %s\",\n                   round (user.ram_used_octave / unitsize), unitname,\n                   round (user.mem_used_octave / unitsize), unitname))\n    if (isunix ())\n      ## The concept of free vs. available RAM doesn't seem to exist on Windows\n      disp (sprintf (\"Free      RAM: %9.0f %s,  swap: %9.0f %s\",\n                     round (free_ram / unitsize), unitname,\n                     round (free_swap / unitsize), unitname))\n    endif\n    disp (sprintf (\"Available RAM: %9.0f %s, total: %9.0f %s\",\n                   round (user.ram_available_all_arrays / unitsize), unitname,\n                   round (user.MemAvailableAllArrays / unitsize), unitname))\n  endif\n\nendfunction\n\nfunction [status, meminfo] = lmemory ()\n\n  ## Read pseudo files to gather memory information on Linux\n\n  ## Read the proc/self/status pseudofile.\n  ## See https://linuxwiki.de/proc/pid#A.2Fproc.2Fpid.2Fstatus.\n  ## It contains a variable number of lines with name-value pairs.\n\n  f = fopen (\"/proc/self/status\");\n  buffer = textscan (f, \"%s %s\", \"delimiter\", ':\\n');\n  fclose (f);\n  for i = 1:rows (buffer{1})\n    status.(buffer{1}{i}) = textscan (buffer{2}{i}){1};\n  endfor\n\n  ## Read the /proc/meminfo pseudofile\n  ## see https://linuxwiki.de/proc/meminfo\n  ## It contains a variable number of lines with name-value pairs.\n\n  f = fopen (\"/proc/meminfo\");\n  buffer = textscan (f, \"%s %s\", \"delimiter\", ':\\n');\n  fclose (f);\n  for i = 1:rows (buffer{1})\n    meminfo.(buffer{1}{i}) = textscan (buffer{2}{i}){1};\n  endfor\n\nendfunction\n\n\n%!testif ; (isunix () && ! ismac ()) || ispc ()\n%! [user, syst] = memory ();\n%! assert (user.mem_used_octave > 0);\n%! assert (user.ram_used_octave <= user.mem_used_octave);\n%! assert (user.mem_used_octave < syst.SystemMemory.Total);\n%! assert (user.MemAvailableAllArrays <= syst.SystemMemory.Available);\n\n%!testif ; (! isunix () || ismac ()) && ! ispc ()\n%! fail (\"[user] = memory ()\",\n%!       \"function not yet implemented for this architecture\");\n%! fail (\"memory ()\", \"warning\",\n%!       \"function not yet implemented for this architecture\");\n"
  },
  {
    "path": "scripts/miscellaneous/menu.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{choice} =} menu (@var{title}, @var{opt1}, @dots{})\n## @deftypefnx {} {@var{choice} =} menu (@var{title}, @{@var{opt1}, @dots{}@})\n## Display a menu with heading @var{title} and options @var{opt1}, @dots{},\n## and wait for user input.\n##\n## If the GUI is running, the menu is displayed graphically using\n## @code{listdlg}.  Otherwise, the title and menu options are printed on the\n## console.\n##\n## @var{title} is a string and the options may be input as individual strings\n## or as a cell array of strings.\n##\n## The return value @var{choice} is the number of the option selected by the\n## user counting from 1.  If the user aborts the dialog or makes an invalid\n## selection then 0 is returned.\n##\n## This function is useful for interactive programs.  There is no limit to the\n## number of options that may be passed in, but it may be confusing to present\n## more than will fit easily on one screen.\n## @seealso{input, listdlg}\n## @end deftypefn\n\nfunction choice = menu (title, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! ischar (title))\n    error (\"menu: TITLE must be a string\");\n  elseif (nargin > 2 && ! iscellstr (varargin))\n    error (\"menu: All OPTIONS must be strings\");\n  elseif (! ischar (varargin{1}) && ! iscellstr (varargin{1}))\n    error (\"menu: OPTIONS must be string or cell array of strings\");\n  endif\n\n  if (__event_manager_have_dialogs__ ())  # GUI menu\n    [choice, ok] = listdlg (\"Name\", \"menu\", \"PromptString\", title,\n                            \"ListString\", varargin, \"SelectionMode\", \"Single\");\n    if (! ok)\n      choice = 0;\n    endif\n  else  # console menu\n    ## Force pending output to appear before the menu.\n    fflush (stdout);\n\n    ## Don't send the menu through the pager as that can cause major confusion.\n    page_screen_output (false, \"local\");\n\n    if (! isempty (title))\n      printf (\"%s\\n\", title);\n    endif\n\n    ## Handle case where choices are given as a cell array\n    if (iscellstr (varargin{1}))\n      varargin = varargin{1};\n    endif\n\n    nopt = numel (varargin);\n    for i = 1:nopt\n      printf (\"  [%2d] %s\\n\", i, varargin{i});\n    endfor\n    printf (\"\\n\");\n\n    s = input (\"Select a number: \", \"s\");\n    choice = sscanf (s, \"%d\");\n\n    if (! isscalar (choice) || choice < 1 || choice > nopt)\n      warning (\"menu: input invalid or out of range\\n\");\n      choice = 0;\n    endif\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> menu ()\n%!error <Invalid call> menu (\"title\")\n%!error <TITLE must be a string> menu (1, \"opt1\")\n%!error <All OPTIONS must be strings> menu (\"title\", \"opt1\", 1)\n%!error <OPTIONS must be string or cell array of strings> menu (\"title\", 1)\n"
  },
  {
    "path": "scripts/miscellaneous/methods.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} methods (@var{obj})\n## @deftypefnx {} {} methods (\"@var{classname}\")\n## @deftypefnx {} {} methods (@dots{}, \"-full\")\n## @deftypefnx {} {@var{mtds} =} methods (@dots{})\n## List the names of the public methods for the object @var{obj} or the\n## named class @var{classname}.\n##\n## @var{obj} may be an Octave class object or a Java object.\n## @var{classname} may be the name of an Octave class or a Java class.\n##\n## If the optional argument @qcode{\"-full\"} is given then Octave returns\n## full method signatures which include output type, name of method,\n## and the number and type of inputs.\n##\n## When called with no output arguments, @code{methods} prints the list of\n## method names to the screen.  Otherwise, the output argument @var{mtds}\n## contains the list in a cell array of strings.\n## @seealso{ismethod, properties, fieldnames}\n## @end deftypefn\n\nfunction mtds = methods (obj, fullopt)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  havesigs = false;\n  showsigs = false;\n  if (nargin == 2)\n    if (! strcmp (fullopt, \"-full\"))\n      error (\"methods: invalid option\");\n    endif\n    showsigs = true;\n  endif\n\n  if (isobject (obj))\n    ## Call internal C++ function for Octave objects.\n    mtds_list = __methods__ (obj);\n  elseif (ischar (obj))\n    ## CLASSNAME could be an Octave class or Java class.\n    ## Try Octave class first.\n    [mtds_list, valid] = __methods__ (obj);\n    if (! valid)\n      ## Try Java class second.\n      try\n        mtds_str = javaMethod (\"getMethods\", \"org.octave.ClassHelper\", obj);\n      catch\n        error (\"methods: class '%s' not found\", obj);\n      end_try_catch\n      mtds_list = ostrsplit (mtds_str, ';');\n      mtds_list = mtds_list(:);  # return a column vector for compatibility\n      havesigs = true;\n    endif\n  elseif (isjava (obj))\n    ## If obj is a String or a subclass of String, then get the methods of its\n    ## class name, not the methods of the class that may be named by the\n    ## content of the string.\n    if (isa (obj, \"java.lang.String\"))\n      klass = class (obj);\n      mtds_str = javaMethod (\"getMethods\", \"org.octave.ClassHelper\", klass);\n    else\n      mtds_str = javaMethod (\"getMethods\", \"org.octave.ClassHelper\", obj);\n    endif\n    mtds_list = strsplit (mtds_str, ';');\n    mtds_list = mtds_list(:);  # return a column vector for compatibility\n    havesigs = true;\n  else\n    error (\"methods: invalid input argument\");\n  endif\n\n  if (havesigs && ! showsigs)\n    ## Extract only the method name for ordinary class methods, delete the\n    ## return type and the argument list.\n    mtds_list = regexprep (mtds_list, '^(?:[^(]+) (\\w+) ?\\(.*$', '$1');\n\n    ## Extract only the class name for class constructors, delete the optional\n    ## \"org.example.\" package prefix and the argument list.\n    mtds_list = regexprep (mtds_list, '^(?:[\\.\\w]+\\.)?(\\w+) ?\\(.*$', '$1');\n\n    mtds_list = unique (mtds_list);\n  else\n    ## Delete the \"org.example.\" package prefix if present.\n    mtds_list = regexprep (mtds_list, '^(?:[\\.\\w]+\\.)(\\w+ ?\\(.*)$', '$1');\n  endif\n\n  if (nargout == 0)\n    classname = ifelse (ischar (obj), obj, class (obj));\n    printf (\"Methods for class %s:\\n\", classname);\n    disp (list_in_columns (mtds_list));\n  else\n    mtds = mtds_list;\n  endif\n\nendfunction\n\n\n## test classdef object\n%!test\n%! ip = inputParser ();\n%! assert (methods (ip),\n%!         {\"addOptional\"; \"addParamValue\"; \"addParameter\"; \"addRequired\";\n%!          \"addSwitch\"; \"delete\"; \"disp\"; \"parse\"; });\n\n## test classdef classname\n%!assert (methods (\"inputParser\"),\n%!        {\"addOptional\"; \"addParamValue\"; \"addParameter\"; \"addRequired\";\n%!         \"addSwitch\"; \"delete\"; \"disp\"; \"parse\"; });\n\n## test old-style @classname\n%!test\n%! mtds = methods (\"ftp\");\n%! assert (mtds{1}, \"ascii\");\n%! assert (numel (mtds), 15);\n\n## test Java classname\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! mtds = methods (\"java.lang.Double\");\n%! search = strfind (mtds, \"valueOf\");\n%! assert (! isempty ([search{:}]));\n\n## test Java classname with -full prototypes\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! mtds = methods (\"java.lang.Double\", \"-full\");\n%! search = strfind (mtds, \"java.lang.Double valueOf\");\n%! assert (! isempty ([search{:}]));\n\n## test Java object\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! jobject = javaObject (\"java.lang.Double\", pi);\n%! assert (methods (jobject), methods (\"java.lang.Double\"));\n\n## test exceptional case of Java String object\n%!testif HAVE_JAVA; usejava (\"jvm\") <*48758>\n%! jobject = javaObject (\"java.lang.String\", \"java.lang.Integer\");\n%! assert (methods (jobject), methods (\"java.lang.String\"));\n\n## Test input validation\n%!error <Invalid call> methods ()\n%!error <invalid option> methods (\"ftp\", \"option1\")\n%!error <class 'foobar' not found> methods ('foobar')\n%!error <invalid input argument> methods (1)\n"
  },
  {
    "path": "scripts/miscellaneous/mex.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} mex [-options] file @dots{}\n## @deftypefnx {} {@code{status} =} mex (@dots{})\n## Compile source code written in C, C++, or Fortran, to a MEX file.\n##\n## @var{status} is the return status of the @code{mkoctfile} function.\n##\n## If the compilation fails, and the output argument is not requested,\n## an error is raised.  If the programmer requests @var{status}, however,\n## Octave will merely issue a warning and it is the programmer's responsibility\n## to verify the command was successful.\n##\n## This is equivalent to @code{mkoctfile --mex [-options] file}.\n##\n## @seealso{mkoctfile, mexext}\n## @end deftypefn\n\nfunction status = mex (varargin)\n\n  [out, sts] = mkoctfile (\"--mex\", varargin{:});\n\n  if (! isempty (out))\n    printf (\"%s\\n\", out);\n  endif\n  if (nargout > 0)\n    status = sts;\n  else\n    if (sts != 0)\n      error (\"mex: building exited with failure status\\n\");\n    endif\n  endif\n\nendfunction\n\n\n## Remove from test statistics.  All real tests are in mkoctfile.\n%!assert (1)\n"
  },
  {
    "path": "scripts/miscellaneous/mexext.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{ext} =} mexext ()\n## Return the filename extension used for MEX files.\n##\n## Programming Note: Octave uses the extension @file{mex} for all MEX files\n## regardless of the operating system (Linux, Windows, Apple) or the bit-width\n## (32-bit or 64-bit) of the hardware.\n## @seealso{mex}\n## @end deftypefn\n\nfunction ext = mexext ()\n  ext = \"mex\";\nendfunction\n\n\n%!assert (mexext (), \"mex\")\n"
  },
  {
    "path": "scripts/miscellaneous/mkdir.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} mkdir @var{dirname}\n## @deftypefnx {} {} mkdir @var{parent} @var{dirname}\n## @deftypefnx {} {} mkdir (@var{dirname})\n## @deftypefnx {} {} mkdir (@var{parent}, @var{dirname})\n## @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} mkdir (@dots{})\n## Create a directory named @var{dirname} in the directory @var{parent},\n## creating any intermediate directories if necessary.\n##\n## If @var{dirname} is a relative path, and no @var{parent} directory is\n## specified, then the present working directory is used.\n##\n## If successful, @var{status} is logical 1, and @var{msg}, @var{msgid} are\n## empty character strings (\"\").  Otherwise, @var{status} is logical 0,\n## @var{msg} contains a system-dependent error message, and @var{msgid}\n## contains a unique message identifier.  Note that the status code is exactly\n## opposite that of the @code{system} command.\n##\n## When creating a directory permissions will be set to\n## @w{@code{0777 - UMASK}}.\n##\n## @seealso{rmdir, pwd, cd, umask}\n## @end deftypefn\n\n## There is/was a bug in gnulib's mkdir-p module under Windows.\n## This file is a workaround until that is fixed and the fix incorporated\n## into Octave.\n\nfunction [status, msg, msgid] = mkdir (parent, dirname)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  parent = tilde_expand (parent);\n\n  if (nargin == 1)\n    dirname = parent;\n  else\n    dirname = fullfile (parent, dirname);\n  endif\n\n  dirname = make_absolute_filename (dirname);\n\n  ## Move leading directory names from dirname to parent\n  [parent, dirname, ext] = fileparts (dirname);\n\n  [sts, msg, msgid] = mkdir_recur (parent, [dirname, ext]);\n\n  if (nargout == 0)\n    if (! sts)\n      error (\"mkdir: operation failed: %s\", msg);\n    elseif (strcmp (msg, \"directory exists\"))\n      warning (\"mkdir: directory exists\\n\");\n    endif\n  else\n    status = sts;\n  endif\n\nendfunction\n\n## Recursively make directories until parent/dirname can be created.\nfunction [status, msg, msgid] = mkdir_recur (parent, dirname)\n\n  status = true;\n\n  if (isempty (parent))\n    error (\"mkdir: invalid PARENT\");\n  endif\n\n  if (! isfolder (parent))\n    [grandparent, name, ext] = fileparts (parent);\n    [status, msg, msgid] = mkdir_recur (grandparent, [name, ext]);\n  endif\n\n  if (status)\n    [status, msg, msgid] = __mkdir__ (parent, dirname);\n  endif\n\nendfunction\n\n\n%!test\n%! dir1 = tempname ();\n%! dir2 = \"%_unlikely_name_%\";\n%! dir = fullfile (dir1, dir2);\n%! unwind_protect\n%!   status = mkdir (dir);\n%!   assert (status);\n%!   assert (isfolder (dir));\n%! unwind_protect_cleanup\n%!   confirm_recursive_rmdir (false, \"local\");\n%!   sts = rmdir (dir1, \"s\");\n%! end_unwind_protect\n\n%!test <*53031>\n%! HOME = getenv (\"HOME\");\n%! tmp_dir = tempname ();\n%! unwind_protect\n%!   mkdir (tmp_dir);\n%!   setenv (\"HOME\", tmp_dir);\n%!   status = mkdir (\"~/subdir\");\n%!   assert (status);\n%!   assert (isfolder (fullfile (tmp_dir, \"subdir\")));\n%! unwind_protect_cleanup\n%!   sts = rmdir (fullfile (tmp_dir, \"subdir\"));\n%!   sts = rmdir (tmp_dir);\n%!   if (isempty (HOME))\n%!     unsetenv (\"HOME\");\n%!   else\n%!     setenv (\"HOME\", HOME);\n%!   endif\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> mkdir ()\n"
  },
  {
    "path": "scripts/miscellaneous/mkoctfile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} mkoctfile [-options] file @dots{}\n## @deftypefnx {} {[@var{output}, @var{status}] =} mkoctfile (@dots{})\n##\n## The @code{mkoctfile} function compiles source code written in C, C++, or\n## Fortran.  Depending on the options used with @code{mkoctfile}, the\n## compiled code can be called within Octave or can be used as a stand-alone\n## application.\n##\n## @code{mkoctfile} can be called from the shell prompt or from the Octave\n## prompt.  Calling it from the Octave prompt simply delegates the call to\n## the shell prompt.  Any output is stored in the @var{output} variable and\n## the exit status in the @var{status} variable.  If called with no outputs\n## and the compilation fails then Octave will emit an error.  If the programmer\n## requests @var{output} or @var{status}, however, Octave will merely issue\n## a warning and it is the programmer's responsibility to verify the command\n## was successful.\n##\n## @code{mkoctfile} accepts the following options, all of which are optional\n## except for the filename of the code you wish to compile:\n##\n## @table @samp\n## @item -I DIR\n## Add the include directory DIR to compile commands.\n##\n## @item -D DEF\n## Add the definition DEF to the compiler call.\n##\n## @item -l LIB\n## Add the library LIB to the link command.\n##\n## @item -L DIR\n## Add the library directory DIR to the link command.\n##\n## @item  -M\n## @itemx --depend\n## Generate dependency files (.d) for C and C++ source files.\n##\n## @item -R DIR\n## Add the run-time path to the link command.\n##\n## @item @nospell{-Wl,@dots{}}\n## Pass options to the linker like @nospell{\"-Wl,-rpath=@dots{}\"}.\n## The quotes are needed since commas are interpreted as command\n## separators.\n##\n## @item -W@dots{}\n## Pass options to the assembler like @nospell{\"-Wa,OPTION\"}.\n##\n## @item -c\n## Compile but do not link.\n##\n## @item -g\n## Enable debugging options for compilers.\n##\n## @item  -o FILE\n## @itemx --output FILE\n## Output filename.  Default extension is @file{.oct} (or @file{.mex} if\n## @samp{--mex} is specified) unless linking a stand-alone executable.\n##\n## @item  -p VAR\n## @itemx --print VAR\n## Print configuration variable VAR@.  There are three categories of\n## variables:\n##\n## Octave configuration variables that users may override with environment\n## variables.  These are used in commands that @code{mkoctfile} executes.\n##\n## @example\n##    ALL_CFLAGS                  INCLUDEDIR\n##    ALL_CXXFLAGS                LAPACK_LIBS\n##    ALL_FFLAGS                  LDFLAGS\n##    ALL_LDFLAGS                 LD_STATIC_FLAG\n##    BLAS_LIBS                   LIBDIR\n##    CC                          LIBOCTAVE\n##    CFLAGS                      LIBOCTINTERP\n##    CPICFLAG                    LIBOCTMEX\n##    CPPFLAGS                    OCTAVE_LINK_OPTS\n##    CXX                         OCTINCLUDEDIR\n##    CXXFLAGS                    OCTAVE_LIBS\n##    CXXLD                       OCTAVE_LINK_DEPS\n##    CXXPICFLAG                  OCTLIBDIR\n##    DL_LDFLAGS                  OCT_LINK_DEPS\n##    F77                         OCT_LINK_OPTS\n##    F77_INTEGER8_FLAG           RDYNAMIC_FLAG\n##    FFLAGS                      SPECIAL_MATH_LIB\n##    FPICFLAG                    XTRA_CFLAGS\n##    INCFLAGS                    XTRA_CXXFLAGS\n## @end example\n##\n## Octave configuration variables as above, but currently unused by\n## @code{mkoctfile}.\n##\n## @example\n## @group\n##    AR\n##    DEPEND_EXTRA_SED_PATTERN\n##    DEPEND_FLAGS\n##    FFTW3F_LDFLAGS\n##    FFTW3F_LIBS\n##    FFTW3_LDFLAGS\n##    FFTW3_LIBS\n##    FFTW_LIBS\n##    FLIBS\n##    LIBS\n##    RANLIB\n##    READLINE_LIBS\n## @end group\n## @end example\n##\n## Octave configuration variables that are provided for informational\n## purposes only.  Except for @samp{OCTAVE_HOME} and @samp{OCTAVE_EXEC_HOME},\n## users may not override these variables.\n##\n## If @w{@env{OCTAVE_HOME}}@ or @w{@env{OCTAVE_EXEC_HOME}}@ are set in the\n## environment, then other variables are adjusted accordingly with\n## @w{@env{OCTAVE_HOME}}@ or @w{@env{OCTAVE_EXEC_HOME}}@ substituted for the\n## original value of the directory specified by the @option{--prefix} or\n## @option{--exec-prefix} options that were used when Octave was configured.\n##\n## @example\n## @group\n##    API_VERSION                 LOCALARCHLIBDIR\n##    ARCHLIBDIR                  LOCALFCNFILEDIR\n##    BINDIR                      LOCALOCTFILEDIR\n##    CANONICAL_HOST_TYPE         LOCALSTARTUPFILEDIR\n##    DATADIR                     LOCALVERARCHLIBDIR\n##    DATAROOTDIR                 LOCALVERFCNFILEDIR\n##    DEFAULT_PAGER               LOCALVEROCTFILEDIR\n##    EXEC_PREFIX                 MAN1DIR\n##    EXEEXT                      MAN1EXT\n##    FCNFILEDIR                  MANDIR\n##    IMAGEDIR                    OCTAVE_EXEC_HOME\n##    INCLUDEDIR                  OCTAVE_HOME\n##    INFODIR                     OCTDATADIR\n##    INFOFILE                    OCTDOCDIR\n##    LIBDIR                      OCTFILEDIR\n##    LIBEXECDIR                  OCTFONTSDIR\n##    LOCALAPIARCHLIBDIR          OCTINCLUDEDIR\n##    LOCALAPIFCNFILEDIR          OCTLIBDIR\n##    LOCALAPIOCTFILEDIR          STARTUPFILEDIR\n##    LOCALAPIPKGDIR              VERSION\n## @end group\n## @end example\n##\n## @item --link-stand-alone\n## Link a stand-alone executable file.\n##\n## @item --mex\n## Assume creation of a MEX file.  Set the default output extension to\n## @file{.mex}.  Link to liboctmex instead of liboctinterp and liboctave.\n##\n## @item  -s\n## @itemx --strip\n## Strip the output file.\n##\n## @item  -v\n## @itemx --verbose\n## Echo commands as they are executed.\n##\n## @item file\n## The file to compile or link.  Recognized file types are:\n##\n## @example\n## @group\n##    .c    C source\n##    .cc   C++ source\n##    .cp   C++ source\n##    .cpp  C++ source\n##    .CPP  C++ source\n##    .cxx  C++ source\n##    .c++  C++ source\n##    .C    C++ source\n##    .f    Fortran source (fixed form)\n##    .F    Fortran source (fixed form)\n##    .f90  Fortran source (free form)\n##    .F90  Fortran source (free form)\n##    .o    object file\n##    .a    library file\n## @end group\n## @end example\n##\n## @end table\n## @end deftypefn\n\nfunction [output, status] = mkoctfile (varargin)\n\n  bindir = __octave_config_info__ (\"bindir\");\n  ext = __octave_config_info__ (\"EXEEXT\");\n\n  shell_script = fullfile (bindir,\n                           sprintf (\"mkoctfile-%s%s\", OCTAVE_VERSION, ext));\n\n  if (! exist (shell_script, \"file\"))\n    __gripe_missing_component__ (\"mkoctfile\", \"mkoctfile\");\n  endif\n\n  cmd = ['\"' shell_script '\"'];\n  for i = 1:nargin\n    cmd = [cmd ' \"' varargin{i} '\"'];\n  endfor\n\n  [sts, out] = system (cmd);\n\n  if (nargout > 0)\n    [output, status] = deal (strtrim (out), sts);\n    if (sts != 0)\n      warning (\"mkoctfile: building exited with failure status\\n\");\n    endif\n  else\n    printf (\"%s\", out);\n    if (sts != 0)\n      error (\"mkoctfile: building exited with failure status\\n\");\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/miscellaneous/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__memoize__.m \\\n  %reldir%/private/__publish_html_output__.m \\\n  %reldir%/private/__publish_latex_output__.m \\\n  %reldir%/private/__w2mpth__.m \\\n  %reldir%/private/display_info_file.m \\\n  %reldir%/private/tar_is_bsd.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/bug_report.m \\\n  %reldir%/bunzip2.m \\\n  %reldir%/cast.m \\\n  %reldir%/citation.m \\\n  %reldir%/clearAllMemoizedCaches.m \\\n  %reldir%/clearvars.m \\\n  %reldir%/compare_versions.m \\\n  %reldir%/computer.m \\\n  %reldir%/copyfile.m \\\n  %reldir%/delete.m \\\n  %reldir%/dir.m \\\n  %reldir%/dos.m \\\n  %reldir%/edit.m \\\n  %reldir%/fieldnames.m \\\n  %reldir%/fileattrib.m \\\n  %reldir%/fileparts.m \\\n  %reldir%/fullfile.m \\\n  %reldir%/getfield.m \\\n  %reldir%/grabcode.m \\\n  %reldir%/gunzip.m \\\n  %reldir%/info.m \\\n  %reldir%/inputParser.m \\\n  %reldir%/isdeployed.m \\\n  %reldir%/isfile.m \\\n  %reldir%/isfolder.m \\\n  %reldir%/ismac.m \\\n  %reldir%/ismethod.m \\\n  %reldir%/ispc.m \\\n  %reldir%/isunix.m \\\n  %reldir%/jupyter_notebook.m \\\n  %reldir%/license.m \\\n  %reldir%/list_primes.m \\\n  %reldir%/loadobj.m \\\n  %reldir%/ls.m \\\n  %reldir%/ls_command.m \\\n  %reldir%/memoize.m \\\n  %reldir%/memory.m \\\n  %reldir%/menu.m \\\n  %reldir%/methods.m \\\n  %reldir%/mex.m \\\n  %reldir%/mexext.m \\\n  %reldir%/mkdir.m \\\n  %reldir%/mkoctfile.m \\\n  %reldir%/movefile.m \\\n  %reldir%/mustBeFinite.m \\\n  %reldir%/mustBeGreaterThan.m \\\n  %reldir%/mustBeGreaterThanOrEqual.m \\\n  %reldir%/mustBeInteger.m \\\n  %reldir%/mustBeLessThan.m \\\n  %reldir%/mustBeLessThanOrEqual.m \\\n  %reldir%/mustBeMember.m \\\n  %reldir%/mustBeNegative.m \\\n  %reldir%/mustBeNonempty.m \\\n  %reldir%/mustBeNonNan.m \\\n  %reldir%/mustBeNonnegative.m \\\n  %reldir%/mustBeNonpositive.m \\\n  %reldir%/mustBeNonsparse.m \\\n  %reldir%/mustBeNonzero.m \\\n  %reldir%/mustBeNumeric.m \\\n  %reldir%/mustBeNumericOrLogical.m \\\n  %reldir%/mustBePositive.m \\\n  %reldir%/mustBeReal.m \\\n  %reldir%/namedargs2cell.m \\\n  %reldir%/namelengthmax.m \\\n  %reldir%/nargchk.m \\\n  %reldir%/narginchk.m \\\n  %reldir%/nargoutchk.m \\\n  %reldir%/news.m \\\n  %reldir%/nthargout.m \\\n  %reldir%/open.m \\\n  %reldir%/orderfields.m \\\n  %reldir%/pack.m \\\n  %reldir%/parseparams.m \\\n  %reldir%/perl.m \\\n  %reldir%/publish.m \\\n  %reldir%/python.m \\\n  %reldir%/recycle.m \\\n  %reldir%/run.m \\\n  %reldir%/saveobj.m \\\n  %reldir%/setfield.m \\\n  %reldir%/substruct.m \\\n  %reldir%/swapbytes.m \\\n  %reldir%/symvar.m \\\n  %reldir%/tar.m \\\n  %reldir%/unix.m \\\n  %reldir%/unpack.m \\\n  %reldir%/untar.m \\\n  %reldir%/unzip.m \\\n  %reldir%/validateattributes.m \\\n  %reldir%/ver.m \\\n  %reldir%/verLessThan.m \\\n  %reldir%/version.m \\\n  %reldir%/what.m \\\n  %reldir%/zip.m\n\n%canon_reldir%dir = $(fcnfiledir)/miscellaneous\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/miscellaneous/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/miscellaneous/movefile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} movefile @var{f1}\n## @deftypefnx {} {} movefile @var{f1} @var{f2}\n## @deftypefnx {} {} movefile @var{f1} @var{f2} f\n## @deftypefnx {} {} movefile (@var{f1})\n## @deftypefnx {} {} movefile (@var{f1}, @var{f2})\n## @deftypefnx {} {} movefile (@var{f1}, @var{f2}, 'f')\n## @deftypefnx {} {[@var{status}] =} movefile (@dots{})\n## @deftypefnx {} {[@var{status}, @var{msg}] =} movefile (@dots{})\n## @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} movefile (@dots{})\n## Move the source file or directory @var{f1} to the destination @var{f2}.\n##\n## The name @var{f1} may contain globbing patterns, or may be a cell array of\n## strings.  If @var{f1} expands to multiple filenames, @var{f2} must be a\n## directory.\n##\n## If no destination @var{f2} is specified then the destination is the present\n## working directory.  If @var{f2} is a filename then @var{f1} is renamed to\n## @var{f2}.\n##\n## When the force flag @qcode{'f'} is given any existing files will be\n## overwritten without prompting.\n##\n## If successful, @var{status} is logical 1, and @var{msg}, @var{msgid} are\n## empty character strings (\"\").  Otherwise, @var{status} is logical 0,\n## @var{msg} contains a system-dependent error message, and @var{msgid}\n## contains a unique message identifier.  Note that the status code is exactly\n## opposite that of the @code{system} command.\n## @seealso{rename, copyfile, unlink, delete, glob}\n## @end deftypefn\n\nfunction [status, msg, msgid] = movefile (f1, f2, force)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  max_cmd_line = 8000;  # Windows cmd.exe is the most restrictive at 8,191.\n  sts = true;\n  msg = \"\";\n  msgid = \"\";\n\n  is_windows = (ispc () && isempty (file_in_path (getenv (\"PATH\"), \"mv.exe\")));\n  ## FIXME: maybe use the same method as in ls to allow users control\n  ##        over the command that is executed.\n  if (is_windows)\n    cmd = \"cmd /C move\";\n    cmd_force_flag = \"/Y\";\n  else\n    cmd = \"mv\";\n    cmd_force_flag = \"-f\";\n  endif\n\n  ## Input type check.\n  if (ischar (f1))\n    f1 = cellstr (f1);\n  elseif (! iscellstr (f1))\n    error (\"copyfile: F1 must be a string or a cell array of strings\");\n  endif\n\n  if (nargin == 1)\n    f2 = pwd ();\n  elseif (! ischar (f2))\n    error (\"movefile: F2 must be a string\");\n  endif\n\n  if (nargin == 3 && strcmp (force, \"f\"))\n    cmd = [cmd \" \" cmd_force_flag];\n  endif\n\n  ## If f1 has more than 1 element then f2 must be a directory\n  isdir_f2 = isfolder (f2);\n  if (numel (f1) > 1 && ! isdir_f2)\n    if (nargout == 0)\n      error (\"movefile: when copying multiple files, F2 must be a directory\");\n    else\n      status = false;\n      msg = \"when copying multiple files, F2 must be a directory\";\n      msgid = \"movefile\";\n      return;\n    endif\n  endif\n\n  ## Protect the filename(s).\n  if (ispc ())\n    f1 = __wglob__ (f1);\n  else\n    f1 = glob (f1);\n  endif\n  if (isempty (f1))\n    if (nargout == 0)\n      error (\"movefile: no files to move\");\n    else\n      status = false;\n      msg = \"no files to move\";\n      msgid = \"movefile\";\n      return;\n    endif\n  endif\n  ## Protect possible whitespace in filenames with double quotes.\n  p1 = sprintf ('\"%s\" ', f1{:});\n  p2 = tilde_expand (f2);\n\n  if (isdir_f2 && length (p1) > max_cmd_line)\n    ## Divide list of files and call shell with smaller command lines.\n    l2 = length (p2) + length (cmd) + 6;\n    while (! isempty (f1))\n      p1 = sprintf ('\"%s\"', f1{1});\n      f1(1) = [];\n      while (! isempty (f1)\n             && (length (p1) + length (f1{1}) + l2 < max_cmd_line))\n        p1 = sprintf ('%s \"%s\"', p1, f1{1});\n        f1(1) = [];\n      endwhile\n\n      if (is_windows)\n        p1 = strrep (p1, '\\', '/');\n        p2 = strrep (p2, '\\', '/');\n      endif\n\n      ## Close old file(s) in editor\n      __event_manager_file_remove__ (p1, p2);\n      ## Move the file(s).\n      [err, msg] = system (sprintf ('%s %s \"%s\"', cmd, p1, p2));\n      if (err != 0)\n        sts = false;\n        msgid = \"movefile\";\n      endif\n      ## Load new file(s) in editor\n      __event_manager_file_renamed__ (sts);\n    endwhile\n  else\n    ## cmd is short enough to be executed in one call to shell.\n    if (is_windows)\n      p1 = strrep (p1, '\\', '/');\n      p2 = strrep (p2, '\\', '/');\n    endif\n\n    ## Close old file(s) in editor\n    __event_manager_file_remove__ (p1, p2);\n    ## Move the file(s).\n    [err, msg] = system (sprintf ('%s %s \"%s\"', cmd, p1, p2));\n    if (err != 0)\n      sts = false;\n      msgid = \"movefile\";\n    endif\n    ## Load new file(s) in editor\n    __event_manager_file_renamed__ (sts);\n  endif\n\n  if (nargout == 0)\n    if (! sts)\n      error (\"movefile: operation failed: %s\", msg);\n    endif\n  else\n    status = sts;\n  endif\n\nendfunction\n\n\n%!test\n%! unwind_protect\n%!   f1 = tempname ();\n%!   tmp_var = pi;\n%!   save (f1, \"tmp_var\");\n%!   fid = fopen (f1, \"rb\");\n%!   assert (fid >= 0);\n%!   orig_data = fread (fid);\n%!   fclose (fid);\n%!   f2 = tempname ();\n%!   assert (movefile (f1, f2));\n%!   assert (! exist (f1, \"file\"));\n%!   assert (exist (f2, \"file\"));\n%!   fid = fopen (f2, \"rb\");\n%!   assert (fid >= 0);\n%!   new_data = fread (fid);\n%!   fclose (fid);\n%!   if (orig_data != new_data)\n%!     error (\"moved file not equal to original file!\");\n%!   endif\n%! unwind_protect_cleanup\n%!   delete ([f1, '*']);\n%!   delete (f2);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> movefile ()\n%!error <F1 must be a string> movefile (1, \"foobar\")\n%!error <F2 must be a string> movefile (\"foobar\", 1)\n%!error <F2 must be a directory> movefile ({\"a\", \"b\"}, \"%_NOT_A_DIR_%\")\n%!error <no files to move> movefile (\"%_NOT_A_FILENAME1_%\", \"%_NOT_A_FILENAME2_%\")\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeFinite.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeFinite (@var{x})\n##\n## Require that input @var{x} is finite.\n##\n## Raise an error if any element of the input @var{x} is not finite, as\n## determined by @code{isfinite (x)}.\n##\n## @seealso{mustBeNonNan, isfinite}\n## @end deftypefn\n\nfunction mustBeFinite (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = isfinite (x(:));\n  if (! all (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (! tf);\n    error (\"%s must be finite; found %d non-finite elements: indexes %s\",\n           label, numel (bad_idx), mat2str (bad_idx));\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeFinite ([]);\n%! mustBeFinite (42);\n%! mustBeFinite (-100:.1:100);\n%! mustBeFinite (int32 (42));\n\n%!error <Invalid call> mustBeFinite ()\n%!error <found 1 non-finite> mustBeFinite (Inf)\n%!error <indexes 4> mustBeFinite ([1 2 3 Inf])\n%!error <indexes 1> mustBeFinite ([-Inf -1 0 1])\n%!error <indexes 1> mustBeFinite ([NaN -1])\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeGreaterThan.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeGreaterThan (@var{x}, @var{c})\n##\n## Require that input @var{x} is greater than @var{c}.\n##\n## Raise an error if any element of the input @var{x} is not greater than\n## @var{c}, as determined by @code{@var{x} > @var{c}}.\n##\n## @seealso{mustBeGreaterThanOrEqual, mustBeLessThan, gt}\n## @end deftypefn\n\nfunction mustBeGreaterThan (x, c)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  tf = (x > c)(:);\n  if (! all (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (! tf);\n    try\n      bad_val = x(bad_idx);\n      errmsg = sprintf (\"%s must be greater than %f; found %d elements that were not: values %s\", ...\n                        label, c, numel (bad_idx), mat2str (bad_val));\n    catch\n      errmsg = sprintf (\"%s must be greater than %f; found %d elements that were not: indexes %s\", ...\n                        label, c, numel (bad_idx), mat2str (bad_idx));\n    end_try_catch\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeGreaterThan (42, 0);\n%! mustBeGreaterThan (Inf, 9999);\n\n%!error <Invalid call> mustBeGreaterThan ()\n%!error <Invalid call> mustBeGreaterThan (1)\n%!error <called with too many inputs> mustBeGreaterThan (1, 2, 3)\n%!error <input must be greater than 42> mustBeGreaterThan (42, 42)\n%!error <found 1 elements that were not> mustBeGreaterThan (Inf, Inf)\n%!error <must be greater than 0> mustBeGreaterThan (NaN, 0)\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeGreaterThanOrEqual.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeGreaterThanOrEqual (@var{x}, @var{c})\n##\n## Require that input @var{x} is greater than or equal to @var{c}.\n##\n## Raise an error if any element of the input @var{x} is not greater than\n## or equal to @var{c}, as determined by @code{@var{x} >= @var{c}}.\n##\n## @seealso{mustBeGreaterThan, mustBeLessThanOrEqual, ge}\n## @end deftypefn\n\nfunction mustBeGreaterThanOrEqual (x, c)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  tf = (x >= c)(:);\n  if (! all (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (! tf);\n    try\n      bad_val = x(bad_idx);\n      errmsg = sprintf (\"%s must be greater than or equal to %f; found %d elements that were not: values %s\", ...\n                        label, c, numel (bad_idx), mat2str (bad_val));\n    catch\n      errmsg = sprintf (\"%s must be greater than or equal to %f; found %d elements that were not: indexes %s\", ...\n                        label, c, numel (bad_idx), mat2str (bad_idx));\n    end_try_catch\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeGreaterThanOrEqual (42, 0);\n%! mustBeGreaterThanOrEqual (Inf, 9999);\n%! mustBeGreaterThanOrEqual (42, 42);\n%! mustBeGreaterThanOrEqual (Inf, Inf);\n\n%!error <Invalid call> mustBeGreaterThanOrEqual ()\n%!error <Invalid call> mustBeGreaterThanOrEqual (1)\n%!error <called with too many inputs> mustBeGreaterThanOrEqual (1, 2, 3)\n%!error <must be greater than or equal to 2> mustBeGreaterThanOrEqual (1, 2)\n%!error <must be greater than or equal to 0> mustBeGreaterThanOrEqual (NaN, 0)\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeInteger.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeInteger (@var{x})\n##\n## Require that input @var{x} is integer-valued (but not necessarily\n## integer-typed).\n##\n## Raise an error if any element of the input @var{x} is not a finite,\n## real, integer-valued numeric value, as determined by various checks.\n##\n## @seealso{mustBeNumeric}\n## @end deftypefn\n\nfunction mustBeInteger (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isinteger (x) || islogical (x))\n    return;\n  endif\n\n  but = [];\n  if (! isnumeric (x))\n    but = sprintf (\"it was non-numeric (found a %s)\", class (x));\n  elseif (! isreal (x))\n    but = \"it was complex\";\n  elseif (issparse (x) && (any (isinf (x)) || any (isnan (x))))\n    but = \"there were non-finite values\";\n  elseif (! issparse (x) && any (! isfinite (x)))\n    but = \"there were non-finite values\";\n  elseif (any (x != fix (x)))\n    but = \"it had fractional values in some elements\";\n  endif\n\n  if (! isempty (but))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    error (\"%s must be integer-valued; but %s\", label, but);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeInteger ([]);\n%! mustBeInteger (42);\n%! mustBeInteger (1:1000);\n%! mustBeInteger (int32 (42));\n%! mustBeInteger (true);\n\n%!error <Invalid call> mustBeInteger ()\n%!error <it was non-numeric> mustBeInteger (\"Hello World\")\n%!error <it was complex> mustBeInteger ([1, 2i])\n%!error <there were non-finite values> mustBeInteger (Inf)\n%!error <there were non-finite values> mustBeInteger (NaN)\n%!error <it had fractional values> mustBeInteger ([1 2 3 4.4])\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeLessThan.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeLessThan (@var{x}, @var{c})\n##\n## Require that input @var{x} is less than @var{c}.\n##\n## Raise an error if any element of the input @var{x} is not less than\n## @var{c}, as determined by @code{@var{x} < @var{c}}.\n##\n## @seealso{mustBeLessThanOrEqual, mustBeGreaterThan, lt}\n## @end deftypefn\n\nfunction mustBeLessThan (x, c)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  tf = (x < c)(:);\n  if (! all (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (! tf);\n    try\n      bad_val = x(bad_idx);\n      errmsg = sprintf (\"%s must be less than %f; found %d elements that were not: values %s\", ...\n                        label, c, numel (bad_idx), mat2str (bad_val));\n    catch\n      errmsg = sprintf (\"%s must be less than %f; found %d elements that were not: indexes %s\", ...\n                        label, c, numel (bad_idx), mat2str (bad_idx));\n    end_try_catch\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeLessThan (0, 1);\n%! mustBeLessThan (-Inf, 42);\n%! mustBeLessThan (42, Inf);\n%! mustBeLessThan (1:41, 42);\n\n%!error <Invalid call> mustBeLessThan ()\n%!error <Invalid call> mustBeLessThan (1)\n%!error <called with too many inputs> mustBeLessThan (1, 2, 3)\n%!error <must be less than 0> mustBeLessThan (1, 0)\n%!error <must be less than 1> mustBeLessThan (1, 1)\n%!error <must be less than Inf> mustBeLessThan (Inf, Inf)\n%!error <must be less than 42> mustBeLessThan (1:42, 42)\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeLessThanOrEqual.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeLessThanOrEqual (@var{x}, @var{c})\n##\n## Require that input is less than or equal to a given value.\n##\n## Raise an error if any element of the input @var{x} is not less than\n## or equal to @var{c}, as determined by @code{@var{x} <= @var{c}}.\n##\n## @seealso{mustBeLessThan, mustBeGreaterThanOrEqual, le}\n## @end deftypefn\n\nfunction mustBeLessThanOrEqual (x, c)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  tf = (x <= c)(:);\n  if (! all (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (! tf);\n    try\n      bad_val = x(bad_idx);\n      errmsg = sprintf (\"%s must be less than or equal to %f; found %d elements that were not: values %s\", ...\n                        label, c, numel (bad_idx), mat2str (bad_val));\n    catch\n      errmsg = sprintf (\"%s must be less than or equal to %f; found %d elements that were not: indexes %s\", ...\n                        label, c, numel (bad_idx), mat2str (bad_idx));\n    end_try_catch\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeLessThanOrEqual (0, 1);\n%! mustBeLessThanOrEqual (-Inf, 42);\n%! mustBeLessThanOrEqual (42, Inf);\n%! mustBeLessThanOrEqual (1:41, 42);\n%! mustBeLessThanOrEqual (1:42, 42);\n%! mustBeLessThanOrEqual (1, 1);\n%! mustBeLessThanOrEqual (Inf, Inf);\n\n%!error <Invalid call> mustBeLessThanOrEqual ()\n%!error <Invalid call> mustBeLessThanOrEqual (1)\n%!error <called with too many inputs> mustBeLessThanOrEqual (1, 2, 3)\n%!error <must be less than or equal to 0> mustBeLessThanOrEqual (1, 0)\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeMember.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeMember (@var{x}, @var{valid})\n##\n## Require that input @var{x} is a member of a set of given valid values.\n##\n## Raise an error if any element of the input @var{x} is not a member\n## of the set @var{valid}, as determined by @code{ismember (@var{x})}.\n##\n## Programming Note: char inputs may behave strangely because of the\n## interaction between chars and cellstrings when calling @code{ismember} on\n## them.  But it will probably \"do what you mean\" if you just use it naturally.\n## To guarantee operation, convert all char arrays to cellstrings with\n## @code{cellstr}.\n##\n## @seealso{mustBeNonempty, ismember}\n## @end deftypefn\n\nfunction mustBeMember (x, valid)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  tf = ! (ismember (x, valid))(:);\n  if (any (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    n_bad = numel (find (tf));\n    ## FIXME: Fancy inclusion of bad_val & valid values in the error message.\n    ##        Probably use mat2str() in a try/catch for that.\n    error (\"%s must be one of the specified valid values; found %d elements that were not\", ...\n           label, n_bad);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeMember (42, 38:50);\n%! mustBeMember (\"foo\", {\"foo\", \"bar\", \"baz\"});\n%! mustBeMember (38:42, 37:43);\n%! mustBeMember ({\"foo\",\"bar\"}, {\"foo\", \"bar\", \"baz\"});\n\n%!error <Invalid call> mustBeMember ()\n%!error <Invalid call> mustBeMember (1)\n%!error <called with too many inputs> mustBeMember (1, 2, 3)\n%!error <found 1 elements> mustBeMember ([1, 42], 1:5)\n%!error <found 1 elements> mustBeMember (\"nope\", {\"foo\", \"bar\", \"baz\"})\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeNegative.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeNegative (@var{x})\n##\n## Require that input @var{x} is negative.\n##\n## Raise an error if any element of the input @var{x} is not negative, as\n## determined by @code{@var{x} < 0}.\n##\n## @seealso{mustBeNonnegative}\n## @end deftypefn\n\nfunction mustBeNegative (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = (x < 0)(:);\n  if (! all (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (! tf);\n    try\n      bad_val = x(bad_idx);\n      errmsg = sprintf (\"%s must be negative; found %d elements that were not: values %s\", ...\n                        label, numel (bad_idx), mat2str (bad_val));\n    catch\n      errmsg = sprintf (\"%s must be negative; found %d elements that were not: indexes %s\", ...\n                        label, numel (bad_idx), mat2str (bad_idx));\n    end_try_catch\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeNegative ([]);\n%! mustBeNegative (-42);\n%! mustBeNegative (-10:-2);\n\n%!error <Invalid call> mustBeNegative ()\n%!error <found 1 elements> mustBeNegative ([-1, 42])\n%!error <found 6 elements> mustBeNegative (-5:5)\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeNonNan.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeNonNan (@var{x})\n##\n## Require that input @var{x} is non-@code{NaN}.\n##\n## Raise an error if any element of the input @var{x} is @code{NaN}, as\n## determined by @code{isnan (@var{x})}.\n##\n## @seealso{mustBeFinite, mustBeNonempty, isnan}\n## @end deftypefn\n\nfunction mustBeNonNan (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = isnan (x(:));\n  if (any (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (tf);\n    errmsg = sprintf (\"%s must be non-NaN; found %d elements that were not: indexes %s\", ...\n                      label, numel (bad_idx), mat2str (bad_idx));\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeNonNan (42);\n%! mustBeNonNan (\"foo\");\n%! mustBeNonNan (1:10);\n%! mustBeNonNan (Inf);\n%! mustBeNonNan (-Inf);\n\n%!error <Invalid call> mustBeNonNan ()\n%!error <must be non-NaN> mustBeNonNan (NaN)\n%!error <input must be non-NaN> mustBeNonNan ([1 2 3 NaN])\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeNonempty.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeNonempty (@var{x})\n##\n## Require that input @var{x} is nonempty.\n##\n## Raise an error if the input @var{x} is empty, as determined by\n## @code{isempty (@var{x})}.\n##\n## @seealso{mustBeMember, mustBeNonzero, isempty}\n## @end deftypefn\n\nfunction mustBeNonempty (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isempty (x))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    error (\"%s must not be empty\", label);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeNonempty (42);\n%! mustBeNonempty (\"Hello\");\n%! mustBeNonempty (Inf);\n%! mustBeNonempty (NaN);\n\n%!error <Invalid call> mustBeNonempty ()\n%!error <input must not be empty> mustBeNonempty ([])\n%!error <input must not be empty> mustBeNonempty ('')\n%!error <input must not be empty> mustBeNonempty (reshape ([], [0 3 3 3]))\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeNonnegative.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeNonnegative (@var{x})\n##\n## Require that input @var{x} is not negative.\n##\n## Raise an error if any element of the input @var{x} is negative, as\n## determined by @code{@var{x} >= 0}.\n##\n## @seealso{mustBeNonzero, mustBePositive}\n## @end deftypefn\n\nfunction mustBeNonnegative (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = (x(:) >= 0);\n  if (! all (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (! tf);\n    try\n      bad_val = x(bad_idx);\n      errmsg = sprintf (\"%s must be non-negative; found %d elements that were not: values %s\", ...\n                        label, numel (bad_idx), mat2str (bad_val));\n    catch\n      errmsg = sprintf (\"%s must be non-negative; found %d elements that were not: indexes %s\", ...\n                        label, numel (bad_idx), mat2str (bad_idx));\n    end_try_catch\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeNonnegative (0);\n%! mustBeNonnegative (1);\n%! mustBeNonnegative (123.456);\n%! mustBeNonnegative (Inf);\n%! mustBeNonnegative (0:10);\n%! mustBeNonnegative (eps);\n\n%!error <Invalid call> mustBeNonnegative ()\n%!error <input must be non-negative> mustBeNonnegative (-1)\n%!error <found 1 elements> mustBeNonnegative ([0 1 2 3 -4])\n%!error <input must be non-negative> mustBeNonnegative (-Inf)\n%!error <must be non-negative> mustBeNonnegative (NaN)\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeNonpositive.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeNonpositive (@var{x})\n##\n## Require that input @var{x} is not positive.\n##\n## Raise an error if any element of the input @var{x} is positive, as\n## determined by @code{@var{x} <= 0}.\n##\n## @seealso{mustBeNegative, mustBeNonzero}\n## @end deftypefn\n\nfunction mustBeNonpositive (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = (x(:) <= 0);\n  if (! all (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (! tf);\n    try\n      bad_val = x(bad_idx);\n      errmsg = sprintf (\"%s must be non-positive; found %d elements that were not: values %s\", ...\n                        label, numel (bad_idx), mat2str (bad_val));\n    catch\n      errmsg = sprintf (\"%s must be non-positive; found %d elements that were not: indexes %s\", ...\n                        label, numel (bad_idx), mat2str (bad_idx));\n    end_try_catch\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeNonpositive (0);\n%! mustBeNonpositive (-1);\n%! mustBeNonpositive (-5:-1);\n%! mustBeNonpositive (-Inf);\n\n%!error <Invalid call> mustBeNonpositive ()\n%!error <must be non-positive> mustBeNonpositive (1)\n%!error <found 2 elements> mustBeNonpositive (-10:2)\n%!error <must be non-positive> mustBeNonpositive (NaN)\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeNonsparse.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeNonsparse (@var{x})\n##\n## Require that input @var{x} is not sparse.\n##\n## Raise an error if the input @var{x} is sparse, as determined by\n## @code{issparse (@var{x})}.\n##\n## @seealso{issparse}\n## @end deftypefn\n\nfunction mustBeNonsparse (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (issparse (x))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    error (\"%s must be nonsparse\", label);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeNonsparse ([]);\n%! mustBeNonsparse (42);\n%! mustBeNonsparse (1:100);\n%! mustBeNonsparse (\"Hello World\");\n\n%!error <Invalid call> mustBeNonsparse ()\n%!error <input must be nonsparse> mustBeNonsparse (sparse (42))\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeNonzero.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeNonzero (@var{x})\n##\n## Require that input @var{x} is not zero.\n##\n## Raise an error if any element of the input @var{x} is zero, as determined\n## by @code{@var{x} == 0}.\n##\n## @seealso{mustBeNonnegative, mustBePositive}\n## @end deftypefn\n\nfunction mustBeNonzero (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = (x(:) == 0);\n  if (any (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (tf);\n    errmsg = sprintf (\"%s must be nonzero; found %d elements that were zero: indexes %s\", ...\n                      label, numel (bad_idx), mat2str (bad_idx));\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeNonzero (1);\n%! mustBeNonzero (-1);\n%! mustBeNonzero ([-5:-1 1:5]);\n%! mustBeNonzero (Inf);\n%! mustBeNonzero (-Inf);\n%! mustBeNonzero (NaN);\n%! mustBeNonzero (eps);\n\n%!error <Invalid call> mustBeNonzero ()\n%!error <found 1 elements> mustBeNonzero (-10:10)\n%!error <found 2 elements> mustBeNonzero ([-1, 0, 0, 1])\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeNumeric.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeNumeric (@var{x})\n##\n## Require that input @var{x} is numeric.\n##\n## Raise an error if the input @var{x} is not numeric, as determined by\n## @code{isnumeric (@var{x})}.\n##\n## @seealso{mustBeNumericOrLogical, isnumeric}\n## @end deftypefn\n\nfunction mustBeNumeric (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    error (\"%s must be numeric; found a %s\", label, class (x));\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeNumeric ([]);\n%! mustBeNumeric (42);\n%! mustBeNumeric (int32 (42));\n%! mustBeNumeric (NaN);\n\n%!error <Invalid call> mustBeNumeric ()\n%!error <found a char> mustBeNumeric (\"foo\")\n%!error <found a logical> mustBeNumeric (true)\n%!error <found a struct> mustBeNumeric (struct ())\n%!error <found a cell> mustBeNumeric (cell ())\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeNumericOrLogical.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeNumericOrLogical (@var{x})\n##\n## Require that input @var{x} is numeric or logical.\n##\n## Raise an error if the input @var{x} is not numeric or logical, as\n## determined by @code{isnumeric (@var{x}) || islogical (@var{x})}.\n##\n## @seealso{mustBeNumeric, isnumeric, islogical}\n## @end deftypefn\n\nfunction mustBeNumericOrLogical (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    error (\"%s must be numeric or logical; found a %s\", label, class (x));\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeNumericOrLogical ([]);\n%! mustBeNumericOrLogical (true);\n%! mustBeNumericOrLogical (false);\n%! mustBeNumericOrLogical (42);\n%! mustBeNumericOrLogical (int32 (42));\n\n%!error <Invalid call> mustBeNumericOrLogical ()\n%!error <found a char> mustBeNumericOrLogical (\"foo\")\n%!error <found a struct> mustBeNumericOrLogical (struct ())\n%!error <found a cell> mustBeNumericOrLogical (cell ())\n"
  },
  {
    "path": "scripts/miscellaneous/mustBePositive.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBePositive (@var{x})\n##\n## Require that input @var{x} is positive.\n##\n## Raise an error if any element of the input @var{x} is not positive, as\n## determined by @code{@var{x} > 0}.\n##\n## @seealso{mustBeNonnegative, mustBeNonzero}\n## @end deftypefn\n\nfunction mustBePositive (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = (x(:) > 0);\n  if (! all (tf))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    bad_idx = find (! tf);\n    try\n      bad_val = x(bad_idx);\n      errmsg = sprintf (\"%s must be positive; found %d elements that were not: values %s\", ...\n                        label, numel (bad_idx), mat2str (bad_val));\n    catch\n      errmsg = sprintf (\"%s must be positive; found %d elements that were not: indexes %s\", ...\n                        label, numel (bad_idx), mat2str (bad_idx));\n    end_try_catch\n    error (errmsg);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBePositive (1);\n%! mustBePositive (123.456);\n%! mustBePositive (Inf);\n%! mustBePositive (eps);\n\n%!error <Invalid call> mustBePositive ()\n%!error <found 1 elements> mustBePositive (0)\n%!error <found 1 elements> mustBePositive (0:10)\n%!error <found 2 elements> mustBePositive ([-1 -2])\n%!error <found 2 elements> mustBePositive ([0 1 2 3 -4])\n%!error <found 1 elements> mustBePositive (-Inf)\n%!error <found 1 elements> mustBePositive (NaN)\n"
  },
  {
    "path": "scripts/miscellaneous/mustBeReal.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} mustBeReal (@var{x})\n##\n## Require that input @var{x} is real.\n##\n## Raise an error if the input @var{x} is not real, as determined by\n## @code{isreal (@var{x})}.\n##\n## @seealso{mustBeFinite, mustBeNonNan, isreal}\n## @end deftypefn\n\nfunction mustBeReal (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isreal (x))\n    label = inputname (1);\n    if (isempty (label))\n      label = \"input\";\n    endif\n    error (\"%s must be real\", label);\n  endif\n\nendfunction\n\n\n%!test\n%! mustBeReal ([]);\n%! mustBeReal (42);\n%! mustBeReal (Inf);\n%! mustBeReal (NaN);\n%! mustBeReal (1:100);\n%! mustBeReal (int32 (42));\n\n%!error <Invalid call> mustBeReal ()\n%!error <must be real> mustBeReal (i)\n%!error <input must be real> mustBeReal (2 + i)\n"
  },
  {
    "path": "scripts/miscellaneous/namedargs2cell.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{c} =} namedargs2cell (@var{s})\n## Create a cell array of field name/value pairs from a scalar structure.\n##\n## Example:\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## s.Name = \"Peter\";\n## s.Height = 185;\n## s.Age = 42;\n##\n## c = namedargs2cell (s)\n##   @xresult{} @{ \"Name\", \"Peter\", \"Height\", 185, \"Age\", 42 @}\n## @end group\n## @end example\n##\n## @seealso{struct2cell}\n## @end deftypefn\n\nfunction c = namedargs2cell (s)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! isstruct (s) || ! isscalar (s))\n    error (\"namedargs2cell: S must be a scalar structure\");\n  endif\n\n  c = reshape ([fieldnames(s), struct2cell(s)].', 1, []);\n\nendfunction\n\n\n%!test\n%! data = { \"Name\", \"Peter\", \"Height\", 185, \"Age\", 42};\n%! s = struct (data{:});\n%! c = namedargs2cell (s);\n%! assert (isequal (c, data));\n\n## Test input validation\n%!error <Invalid call> namedargs2cell ()\n%!error <called with too many inputs> namedargs2cell (1, 2)\n%!error <S must be a scalar structure> namedargs2cell (true)\n%!error <S must be a scalar structure> namedargs2cell (struct (\"name\", {1, 2}))\n"
  },
  {
    "path": "scripts/miscellaneous/namelengthmax.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{n} =} namelengthmax ()\n## Return the @sc{matlab} compatible maximum variable name length.\n##\n## Octave is capable of storing strings up to @math{2^{31} - 1} in length.\n## However for @sc{matlab} compatibility all variable, function, and structure\n## field names should be shorter than the length returned by\n## @code{namelengthmax}.  In particular, variables stored to a @sc{matlab} file\n## format (@file{*.mat}) will have their names truncated to this length.\n## @end deftypefn\n\nfunction n = namelengthmax ()\n  n = 63;\nendfunction\n\n\n%!assert (namelengthmax (), 63)\n"
  },
  {
    "path": "scripts/miscellaneous/nargchk.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{msgstr} =} nargchk (@var{minargs}, @var{maxargs}, @var{nargs})\n## @deftypefnx {} {@var{msgstr} =} nargchk (@var{minargs}, @var{maxargs}, @var{nargs}, \"string\")\n## @deftypefnx {} {@var{msgstruct} =} nargchk (@var{minargs}, @var{maxargs}, @var{nargs}, \"struct\")\n## Return an appropriate error message string (or structure) if the number of\n## inputs requested is invalid.\n##\n## This is useful for checking to see that the number of input arguments\n## supplied to a function is within an acceptable range.\n##\n## @strong{Caution}: @code{nargchk} is scheduled for deprecation.  Use\n## @code{narginchk} in all new code.\n## @seealso{narginchk, nargoutchk, error, nargin, nargout}\n## @end deftypefn\n\nfunction msg = nargchk (minargs, maxargs, nargs, outtype = \"string\")\n\n  if (nargin < 3)\n    print_usage ();\n  elseif (minargs > maxargs)\n    error (\"nargchk: MINARGS must be <= MAXARGS\");\n  elseif (! any (strcmpi (outtype, {\"string\", \"struct\"})))\n    error ('nargchk: output type must be either \"string\" or \"struct\"');\n  elseif (! (isscalar (minargs) && isscalar (maxargs) && isscalar (nargs)))\n    error (\"nargchk: MINARGS, MAXARGS, and NARGS must be scalars\");\n  endif\n\n  msg = struct (\"message\", \"\", \"identifier\", \"\");\n  if (nargs < minargs)\n    msg.message = \"not enough input arguments\";\n    msg.identifier = \"Octave:nargchk:not-enough-inputs\";\n  elseif (nargs > maxargs)\n    msg.message = \"too many input arguments\";\n    msg.identifier = \"Octave:nargchk:too-many-inputs\";\n  endif\n\n  if (strcmpi (outtype, \"string\"))\n    msg = msg.message;\n  elseif (isempty (msg.message))\n    ## Compatibility: Matlab returns a 0x1 empty struct when nargchk passes\n    msg = resize (msg, 0, 1);\n  endif\n\nendfunction\n\n\n## Tests\n%!shared stnul, stmin, stmax\n%! stnul = resize (struct (\"message\", \"\", \"identifier\", \"\"), 0, 1);\n%! stmin = struct (\"message\", \"not enough input arguments\",\n%!                 \"identifier\", \"Octave:nargchk:not-enough-inputs\");\n%! stmax = struct (\"message\", \"too many input arguments\",\n%!                 \"identifier\", \"Octave:nargchk:too-many-inputs\");\n%!assert (nargchk (0, 1, 0), \"\")\n%!assert (nargchk (0, 1, 1), \"\")\n%!assert (nargchk (1, 1, 0), \"not enough input arguments\")\n%!assert (nargchk (0, 1, 2), \"too many input arguments\")\n%!assert (nargchk (0, 1, 2, \"string\"), \"too many input arguments\")\n## Struct outputs\n%!assert (nargchk (0, 1, 0, \"struct\"), stnul)\n%!assert (nargchk (0, 1, 1, \"struct\"), stnul)\n%!assert (nargchk (1, 1, 0, \"struct\"), stmin)\n%!assert (nargchk (0, 1, 2, \"struct\"), stmax)\n"
  },
  {
    "path": "scripts/miscellaneous/narginchk.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} narginchk (@var{minargs}, @var{maxargs})\n## Check for correct number of input arguments.\n##\n## Generate an error message if the number of arguments in the calling function\n## is outside the range @var{minargs} and @var{maxargs}.  Otherwise, do\n## nothing.\n##\n## Both @var{minargs} and @var{maxargs} must be scalar numeric values.  Zero,\n## Inf, and negative values are all allowed, and @var{minargs} and\n## @var{maxargs} may be equal.\n##\n## Note that this function evaluates @code{nargin} on the caller.\n##\n## @seealso{nargoutchk, error, nargout, nargin}\n## @end deftypefn\n\nfunction narginchk (minargs, maxargs)\n\n  if (nargin != 2)\n    print_usage ();\n  elseif (! isnumeric (minargs) || ! isscalar (minargs))\n    error (\"narginchk: MINARGS must be a numeric scalar\");\n  elseif (! isnumeric (maxargs) || ! isscalar (maxargs))\n    error (\"narginchk: MAXARGS must be a numeric scalar\");\n  elseif (minargs > maxargs)\n    error (\"narginchk: MINARGS cannot be larger than MAXARGS\");\n  endif\n\n  args = evalin (\"caller\", \"nargin;\");\n\n  if (args < minargs)\n    error (\"narginchk: not enough input arguments\");\n  elseif (args > maxargs)\n    error (\"narginchk: too many input arguments\");\n  endif\n\nendfunction\n\n\n%!function f (nargs, varargin)\n%! narginchk (nargs(1), nargs(2));\n%!endfunction\n\n%!error <too many input arguments> f([0,0])\n%!error <not enough input arguments> f([3, 3], 1)\n\n%!test\n%! f([1,1]);\n%!test\n%! f([1,5], 2, 3, 4, 5);\n"
  },
  {
    "path": "scripts/miscellaneous/nargoutchk.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} nargoutchk (@var{minargs}, @var{maxargs})\n## @deftypefnx {} {@var{msgstr} =} nargoutchk (@var{minargs}, @var{maxargs}, @var{nargs})\n## @deftypefnx {} {@var{msgstr} =} nargoutchk (@var{minargs}, @var{maxargs}, @var{nargs}, \"string\")\n## @deftypefnx {} {@var{msgstruct} =} nargoutchk (@var{minargs}, @var{maxargs}, @var{nargs}, \"struct\")\n## Check for correct number of output arguments.\n##\n## In the first form, return an error if the number of arguments is not between\n## @var{minargs} and @var{maxargs}.  Otherwise, do nothing.  Note that this\n## function evaluates the value of @code{nargout} on the caller so its value\n## must have not been tampered with.\n##\n## Both @var{minargs} and @var{maxargs} must be numeric scalars.  Zero, Inf,\n## and negative are all valid, and they can have the same value.\n##\n## For backwards compatibility, the other forms return an appropriate error\n## message string (or structure) if the number of outputs requested is\n## invalid.\n##\n## This is useful for checking to that the number of output arguments supplied\n## to a function is within an acceptable range.\n## @seealso{narginchk, error, nargout, nargin}\n## @end deftypefn\n\nfunction msg = nargoutchk (minargs, maxargs, nargs, outtype)\n\n  ## Before Matlab 2011b, nargoutchk would return an error message (just the\n  ## message in a string).  With 2011b, it no longer returns anything, it\n  ## simply gives an error if the args number is incorrect.\n  ## To try to keep compatibility with both versions, check nargout and nargin\n  ## to guess if the caller is expecting a value (old syntax) or none\n  ## (new syntax).\n\n  if (nargout == 1 && (nargin == 3 || nargin == 4))\n\n    if (minargs > maxargs)\n      error (\"nargoutchk: MINARGS must be <= MAXARGS\");\n    elseif (nargin == 3)\n      outtype = \"string\";\n    elseif (! any (strcmpi (outtype, {\"string\" \"struct\"})))\n      error (\"nargoutchk: output type must be either string or struct\");\n    elseif (! (isscalar (minargs) && isscalar (maxargs) && isscalar (nargs)))\n      error (\"nargoutchk: MINARGS, MAXARGS, and NARGS must be scalars\");\n    endif\n\n    msg = struct (\"message\", \"\", \"identifier\", \"\");\n    if (nargs < minargs)\n      msg.message = \"not enough output arguments\";\n      msg.identifier = \"Octave:nargoutchk:not-enough-outputs\";\n    elseif (nargs > maxargs)\n      msg.message = \"too many output arguments\";\n      msg.identifier = \"Octave:nargoutchk:too-many-outputs\";\n    endif\n\n    if (strcmpi (outtype, \"string\"))\n      msg = msg.message;\n    elseif (isempty (msg.message))\n      ## Compatibility: Matlab returns a 0x1 empty struct when nargoutchk passes\n      msg = resize (msg, 0, 1);\n    endif\n\n  elseif (nargout == 0 && nargin == 2)\n\n    if (! isnumeric (minargs) || ! isscalar (minargs))\n      error (\"nargoutchk: MINARGS must be a numeric scalar\");\n    elseif (! isnumeric (maxargs) || ! isscalar (maxargs))\n      error (\"nargoutchk: MAXARGS must be a numeric scalar\");\n    elseif (minargs > maxargs)\n      error (\"nargoutchk: MINARGS cannot be larger than MAXARGS\");\n    endif\n\n    args = evalin (\"caller\", \"nargout;\");\n\n    if (args < minargs)\n      error (\"nargoutchk: Not enough output arguments\");\n    elseif (args > maxargs)\n      error (\"nargoutchk: Too many output arguments\");\n    endif\n\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!shared stnul, stmin, stmax\n%! stnul = resize (struct (\"message\", \"\", \"identifier\", \"\"), 0, 1);\n%! stmin = struct (\"message\", \"not enough output arguments\",\n%!                 \"identifier\", \"Octave:nargoutchk:not-enough-outputs\");\n%! stmax = struct (\"message\", \"too many output arguments\",\n%!                 \"identifier\", \"Octave:nargoutchk:too-many-outputs\");\n%!assert (nargoutchk (0, 1, 0), \"\")\n%!assert (nargoutchk (0, 1, 1), \"\")\n%!assert (nargoutchk (1, 1, 0), \"not enough output arguments\")\n%!assert (nargoutchk (0, 1, 2), \"too many output arguments\")\n%!assert (nargoutchk (0, 1, 2, \"string\"), \"too many output arguments\")\n## Struct outputs\n%!assert (nargoutchk (0, 1, 0, \"struct\"), stnul)\n%!assert (nargoutchk (0, 1, 1, \"struct\"), stnul)\n%!assert (nargoutchk (1, 1, 0, \"struct\"), stmin)\n%!assert (nargoutchk (0, 1, 2, \"struct\"), stmax)\n"
  },
  {
    "path": "scripts/miscellaneous/news.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} news\n## @deftypefnx {} {} news @var{package}\n## Display the current NEWS file for Octave or an installed package.\n##\n## When called without an argument, display the NEWS file for Octave.\n##\n## When given a package name @var{package}, display the current NEWS file for\n## that package.\n## @seealso{ver, pkg}\n## @end deftypefn\n\nfunction news (package = \"octave\")\n\n  ## function takes care of validating PACKAGE input\n  display_info_file (\"news\", package, \"NEWS\");\n\nendfunction\n\n\n%!error <news: PACKAGE must be a string> news (1)\n%!error <news: package .* is not installed> news (\"__NOT_A_VALID_PKG_NAME__\")\n"
  },
  {
    "path": "scripts/miscellaneous/nthargout.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{arg} =} nthargout (@var{n}, @var{fcn}, @dots{})\n## @deftypefnx {} {@var{arg} =} nthargout (@var{n}, @var{ntot}, @var{fcn}, @dots{})\n## Return the @var{n}th output argument of the function specified by the\n## function handle or string @var{fcn}.\n##\n## Any additional arguments are passed directly to @var{fcn}.  The total\n## number of arguments to call @var{fcn} with can be passed in @var{ntot}; by\n## default @var{ntot} is @var{n}.  The input @var{n} can also be a vector of\n## indices of the output, in which case the output will be a cell array of the\n## requested output arguments.\n##\n## The intended use of @code{nthargout} is to avoid intermediate variables.\n## For example, when finding the indices of the maximum entry of a matrix, the\n## following two compositions of @code{nthargout}\n##\n## @example\n## @group\n## @var{m} = magic (5);\n## cell2mat (nthargout ([1, 2], @@ind2sub, size (@var{m}),\n##                      nthargout (2, @@max, @var{m}(:))))\n## @xresult{} 5   3\n## @end group\n## @end example\n##\n## @noindent\n## are completely equivalent to the following lines:\n##\n## @example\n## @group\n## @var{m} = magic (5);\n## [~, idx] = max (@var{M}(:));\n## [i, j] = ind2sub (size (@var{m}), idx);\n## [i, j]\n## @xresult{} 5   3\n## @end group\n## @end example\n##\n## It can also be helpful to have all output arguments collected in a single\n## cell array as the following code demonstrates:\n##\n## @example\n## @var{USV} = nthargout ([1:3], @@svd, hilb (5));\n## @end example\n##\n## Programming Note: Equivalent functionality to the @code{nthargout} function\n## is frequently possible by using the character @samp{~} in code to ignore\n## outputs.  This functionality is implemented by the Octave interpreter and\n## is even more efficient than using this function.\n##\n## Equivalent Code:\n##\n## @example\n## @group\n## idx = nthargout (2, @@max, rand (100, 1));\n## @equiv{}\n## [~, idx] = max (rand (100, 1));\n## @end group\n## @end example\n##\n## @seealso{nargin, nargout, varargin, varargout, isargout}\n## @end deftypefn\n\nfunction arg = nthargout (n, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (is_function_handle (varargin{1}) || ischar (varargin{1}))\n    ntot = max (n(:));\n    fcn = varargin{1};\n    args = varargin(2:end);\n  elseif (isnumeric (varargin{1})\n          && (is_function_handle (varargin{2}) || ischar (varargin{2})))\n    ntot = varargin{1};\n    fcn = varargin{2};\n    args = varargin(3:end);\n  else\n    print_usage ();\n  endif\n\n  if (any (n != fix (n))  || ntot != fix (ntot) || any (n <= 0) || ntot <= 0)\n    error (\"nthargout: N and NTOT must be positive integers\");\n  endif\n\n  outargs = cell (1, ntot);\n\n  try\n    [outargs{:}] = feval (fcn, args{:});\n    if (numel (n) > 1)\n      arg = outargs(n);\n    else\n      arg = outargs{n};\n    endif\n  catch\n    err = lasterror ();\n    if (strfind (err.message, \"some elements undefined in return list\"))\n      error (\"nthargout: too many output arguments: %d\", ntot);\n    else\n      rethrow (err);\n    endif\n  end_try_catch\n\nendfunction\n\n\n%!shared m\n%! m = magic (5);\n%!\n%!assert (nthargout ([1,2], @ind2sub, size (m), nthargout (2, @max, m(:))), {5,3})\n%!assert (nthargout (3, @find, m(m>20)), [23, 24, 25, 21, 22]')\n\n## Test input validation\n%!error <Invalid call> nthargout ()\n%!error <Invalid call> nthargout (1)\n%!error <N .* must be positive integers> nthargout (1.5, @sin)\n%!error <N .* must be positive integers> nthargout (1, 1.5, @sin)\n%!error <N .* must be positive integers> nthargout (0, @sin)\n%!error <N .* must be positive integers> nthargout (0, 1, @sin)\n%!error <too many output arguments: 2> nthargout (2, @sin, pi)\n"
  },
  {
    "path": "scripts/miscellaneous/open.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} open @var{file}\n## @deftypefnx {} {@var{output} =} open (@var{file})\n## Open the file @var{file} in Octave or in an external application based on\n## the file type as determined by the filename extension.\n##\n## By default, recognized file types are\n##\n## @table @code\n## @item .m\n## Open file in the editor.  No @var{output} value is returned.\n##\n## @item  .mat\n## @itemx octave-workspace\n## Open the data file with @code{load}.  If no return value @var{output}\n## is requested, variables are loaded in the base workspace.  Otherwise\n## @var{output} will be a structure containing loaded data.\n## @xref{XREFload,,load function}.\n##\n## @item .ofig\n## Open the figure with @code{hgload}.\n## @xref{XREFhgload,,hgload function}.\n##\n## @item .fig, .ofig\n## Load the figure\n##\n## @item .exe\n## Execute the program (on Windows systems only).  No @var{output} value\n## is returned.\n## @end table\n##\n## Custom file extensions may also be handled if a function @code{openxxx},\n## where @code{xxx} is the extension, is found in the load path.  The function\n## must accept the file name as input.  For example, in order to load\n## @nospell{@qcode{\".dat\"}} data files in the base workspace, as is done by\n## default for @qcode{\".mat\"} files, one may define\n## @nospell{@qcode{\"opendat.m\"}} with the following contents:\n##\n## @example\n## @group\n## function retval = opendat (fname)\n##   evalin (\"base\", sprintf (\"load ('%s');\", fname));\n## endfunction\n## @end group\n## @end example\n##\n## Other file types are opened in the appropriate external application.\n## @end deftypefn\n\nfunction output = open (file)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (file))\n    error (\"open: FILE must be a string\");\n  endif\n\n  if (! exist (file, \"file\"))\n    error (\"open: unable to find file %s\", file);\n  endif\n\n  file = make_absolute_filename (tilde_expand (file));\n\n  [~, fname, ext] = fileparts (file);\n\n  if (! isempty (ext)\n      && any (exist ([\"open\" lower(ext(2:end))]) == [2 3 5 103]))\n    try\n      openfcn = [\"open\" lower(ext(2:end))];\n      if (nargout > 0)\n        output = feval (openfcn, file);\n      else\n        feval (openfcn, file);\n      endif\n    catch\n      error (\"open: %s\", lasterr);\n    end_try_catch\n  elseif (strcmpi (ext, \".m\"))\n    edit (file);\n  elseif (strcmpi (ext, \".mat\") || strcmp (fname, \"octave-workspace\"))\n    if (nargout > 0)\n      output = load (file);\n    else\n      evalin (\"base\", sprintf (\"load ('%s');\", file));\n    endif\n  elseif (strcmpi (ext, \".ofig\"))\n    if (nargout > 0)\n      output = openfig (file);\n    else\n      openfig (file);\n    endif\n  elseif (any (strcmpi (ext, {\".mdl\", \".slx\", \".prj\"})))\n    error (\"open: opening file type '%s' is not supported\", ext);\n  elseif (strcmpi (ext, \".exe\"))\n    if (! ispc ())\n      error (\"open: executing .exe files is only supported on Windows systems\");\n    endif\n    dos (file);\n  else\n    __open_with_system_app__ (file);\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> open ()\n%!error open (\"abc\", \"def\")\n%!error <FILE must be a string> open (1)\n"
  },
  {
    "path": "scripts/miscellaneous/orderfields.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{sout} =} orderfields (@var{s1})\n## @deftypefnx {} {@var{sout} =} orderfields (@var{s1}, @var{s2})\n## @deftypefnx {} {@var{sout} =} orderfields (@var{s1}, @{@var{cellstr}@})\n## @deftypefnx {} {@var{sout} =} orderfields (@var{s1}, @var{p})\n## @deftypefnx {} {[@var{sout}, @var{p}] =} orderfields (@dots{})\n## Return a @emph{copy} of @var{s1} with fields arranged alphabetically, or as\n## specified by the second input.\n##\n## Given one input struct @var{s1}, arrange field names alphabetically.\n##\n## If a second struct argument is given, arrange field names in @var{s1} as\n## they appear in @var{s2}.  The second argument may also specify the order\n## in a cell array of strings @var{cellstr}.  The second argument may also\n## be a permutation vector.\n##\n## The optional second output argument @var{p} is the permutation vector which\n## converts the original name order to the new name order.\n##\n## Examples:\n##\n## @example\n## @group\n## s = struct (\"d\", 4, \"b\", 2, \"a\", 1, \"c\", 3);\n## t1 = orderfields (s)\n##   @xresult{} t1 =\n##        scalar structure containing the fields:\n##          a =  1\n##          b =  2\n##          c =  3\n##          d =  4\n## @end group\n## @end example\n##\n## @example\n## @group\n## t = struct (\"d\", @{@}, \"c\", @{@}, \"b\", @{@}, \"a\", @{@});\n## t2 = orderfields (s, t)\n##   @xresult{} t2 =\n##        scalar structure containing the fields:\n##          d =  4\n##          c =  3\n##          b =  2\n##          a =  1\n## @end group\n## @end example\n##\n## @example\n## @group\n## t3 = orderfields (s, [3, 2, 4, 1])\n##   @xresult{} t3 =\n##        scalar structure containing the fields:\n##          a =  1\n##          b =  2\n##          c =  3\n##          d =  4\n## @end group\n## @end example\n##\n## @example\n## @group\n## [t4, p] = orderfields (s, @{\"d\", \"c\", \"b\", \"a\"@})\n##   @xresult{} t4 =\n##        scalar structure containing the fields:\n##          d =  4\n##          c =  3\n##          b =  2\n##          a =  1\n##      p =\n##         1\n##         4\n##         2\n##         3\n## @end group\n## @end example\n##\n## @seealso{fieldnames, getfield, setfield, rmfield, isfield, isstruct, struct}\n## @end deftypefn\n\nfunction [sout, p] = orderfields (s1, s2)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isstruct (s1))\n    error (\"orderfields: S1 must be a struct\");\n  endif\n\n  names = fieldnames (s1);\n\n  if (nargin == 1)\n    ## One structure: return the fields in alphabetical order.\n    [~, p] = sort (names);\n  elseif (nargin == 2)\n\n    if (isstruct (s2))\n      ## Two structures: return the fields in the order of s2.\n      names2 = fieldnames (s2);\n      [ns1, idx1] = sort (names);\n      [ns2, idx2] = sort (names2);\n      if (! isequal (ns1, ns2))\n        error (\"orderfields: structures S1 and S2 do not have the same fields\");\n      endif\n      p = eye (numel (idx2))(idx2,:).' * idx1;\n\n    elseif (iscellstr (s2))\n      ## A structure and a list of fields: order by the list of fields.\n      names2 = s2(:);\n      [ns1, idx1] = sort (names);\n      [ns2, idx2] = sort (names2);\n      if (! isequal (ns1, ns2))\n        error (\"orderfields: CELLSTR list does not match structure fields\");\n      endif\n      p = eye (numel (idx2))(idx2,:).' * idx1;\n\n    elseif (isnumeric (s2))\n      ## A structure and a permutation vector: permute the order of s1.\n      p = s2(:);\n      if (! isequal (sort (p), (1:numel (names)).'))\n        error (\"orderfields: invalid permutation vector P\");\n      endif\n\n    else\n      error (\"orderfields: second argument must be structure, cellstr, or permutation vector\");\n    endif\n  endif\n\n  ## Permute the names in the structure.\n  names = names(p);\n  C = struct2cell (s1);\n  C = C(p,:);\n  sout = cell2struct (C, names);\n  ## Inherit dimensions.\n  sout = reshape (sout, size (s1));\n\nendfunction\n\n\n%!shared a, b, c\n%! a = struct (\"C\", {1, 2}, \"A\", {3, 4}, \"B\", {5, 6});\n%! b = struct (\"A\", 1, \"B\", 2, \"C\", 3);\n%! c = struct (\"B\", {7, 8}, \"C\", 9, \"A\", 10);\n%!test\n%! x = orderfields (b, a);\n%! assert (fieldnames (x), {\"C\"; \"A\"; \"B\"});\n%! assert (x.A, 1);\n%! assert (x.B, 2);\n%! assert (x.C, 3);\n%!test\n%! [x, p] = orderfields (b, [3 2 1]);\n%! assert (fieldnames (x), {\"C\"; \"B\"; \"A\"});\n%! assert (p, [3; 2; 1]);\n%! assert (x.A, 1);\n%! assert (x.B, 2);\n%! assert (x.C, 3);\n%!test\n%! x = orderfields (b, {\"B\", \"C\", \"A\"});\n%! assert (fieldnames (x), {\"B\"; \"C\"; \"A\"});\n%! assert (x.A, 1);\n%! assert (x.B, 2);\n%! assert (x.C, 3);\n%!test\n%! x(1:2) = orderfields (c, {\"C\", \"A\", \"B\"});\n%! assert (fieldnames (x), {\"C\"; \"A\"; \"B\"});\n%! assert (x(2).A, 10);\n%! assert (x(2).B, 8);\n%! assert (x(2).C, 9);\n\n%!test\n%! aa.x = {1, 2};\n%! aa.y = 3;\n%! aa(2).x = {4, 5};\n%! bb.y = {6, 7};\n%! bb.x = 8;\n%! aa(2) = orderfields (bb, aa);\n%! assert (aa(2).x, 8);\n%! assert (aa(2).y{1}, 6);\n\n## Corner case of empty struct\n%!assert <*40224> (orderfields (struct ()), struct ())\n%!test\n%! s(2,2).a = 1;\n%! s(1,1).b = 2;\n%! s = resize (s, [1 0]);\n%! s2 = orderfields (s, {\"b\", \"a\"});\n%! assert (fieldnames (s2), {\"b\"; \"a\"});\n%! assert (size_equal (s, s2));\n\n## Test input validation\n%!error <Invalid call> orderfields ()\n%!error <S1 must be a struct> orderfields (1)\n%!error <S1 and S2 do not have the same fields>\n%! s1.a = 1;\n%! s2.b = 2;\n%! orderfields (s1, s2);\n%!error <CELLSTR list does not match structure fields>\n%! s1.a = 1;\n%! orderfields (s1, {\"b\"});\n%!error <invalid permutation vector P>\n%! s1.a = 1;\n%! orderfields (s1, [2 1]);\n%!error <invalid permutation vector P>\n%! s1.a = 1;\n%! orderfields (s1, ones (2,2));\n%!error <second argument must be structure, cellstr, or permutation vector>\n%! s1.a = 1;\n%! orderfields (s1, \"foobar\");\n"
  },
  {
    "path": "scripts/miscellaneous/pack.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} pack ()\n## Consolidate workspace memory in @sc{matlab}.\n##\n## This function is provided for compatibility, but does nothing in Octave.\n## @seealso{clear}\n## @end deftypefn\n\nfunction pack ()\n\nendfunction\n\n\n## No test needed for empty function\n%!assert (1)\n"
  },
  {
    "path": "scripts/miscellaneous/parseparams.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{reg}, @var{prop}] =} parseparams (@var{params})\n## @deftypefnx {} {[@var{reg}, @var{var1}, @dots{}] =} parseparams (@var{params}, @var{name1}, @var{default1}, @dots{})\n## Return in @var{reg} the cell elements of @var{param} up to the first\n## string element and in @var{prop} all remaining elements beginning with the\n## first string element.\n##\n## For example:\n##\n## @example\n## @group\n## [reg, prop] = parseparams (@{1, 2, \"linewidth\", 10@})\n## reg =\n## @{\n##   [1,1] = 1\n##   [1,2] = 2\n## @}\n## prop =\n## @{\n##   [1,1] = linewidth\n##   [1,2] = 10\n## @}\n## @end group\n## @end example\n##\n## The parseparams function may be used to separate regular numeric arguments\n## from additional arguments given as property/value pairs of the\n## @var{varargin} cell array.\n##\n## In the second form of the call, available options are specified directly\n## with their default values given as name-value pairs.  If @var{params} do\n## not form name-value pairs, or if an option occurs that does not match any\n## of the available options, an error occurs.\n##\n## When called from an m-file function, the error is prefixed with the name\n## of the caller function.\n##\n## The matching of options is case-insensitive.\n##\n## @seealso{varargin, inputParser}\n## @end deftypefn\n\nfunction [reg, varargout] = parseparams (params, varargin)\n\n  strs = cellfun (\"isclass\", params, \"char\");\n  i = find (strs, 1);\n  if (i)\n    reg = params(1:i-1);\n    prop = params(i:end);\n  else\n    reg = params;\n    prop = {};\n  endif\n\n  if (nargin == 1)\n    varargout = {prop};\n  else\n    names = varargin(1:2:end);\n    defaults = varargin(2:2:end);\n    if (! size_equal (names, defaults))\n      error (\"parseparams: needs odd number of arguments\");\n    endif\n    [names, sidx] = sort (upper (names));\n\n    varargout = defaults;\n    if (i)\n      ## Let's parse the properties.\n      pnames = prop(1:2:end);\n      values = prop(2:2:end);\n      if (! size_equal (pnames, values) || ! all (strs(i:2:end)))\n        error_as_caller (\"options must be given as name-value pairs\");\n      endif\n      idx = lookup (names, upper (pnames), \"m\");\n      if (! all (idx))\n        error_as_caller (\"unrecognized option: %s\", pnames{find (idx == 0, 1)});\n      else\n        varargout(sidx(idx)) = values;\n      endif\n    endif\n  endif\n\nendfunction\n\nfunction error_as_caller (msg, varargin)\n  stack = dbstack (1); # omit me\n  fname = stack(min (2, end)).name;\n  error ([fname, \": \", msg], varargin{:});\nendfunction\n\n\n%!test\n%! [reg, prop] = parseparams ({1, 2, \"linewidth\", 10});\n%! assert (reg, {[1], [2]});\n%! assert (prop, {\"linewidth\", 10});\n%!test\n%! [reg, prop] = parseparams ({1, 2, 3});\n%! assert (reg, {[1], [2], [3]});\n%! assert (isempty (prop));\n%!test\n%! [reg, prop] = parseparams ({\"prop1\", \"val1\"});\n%! assert (isempty (reg));\n%! assert (prop, {\"prop1\", \"val1\"});\n%!test\n%! [reg, prop1] = parseparams ({\"linewidth\", 5}, \"linewidth\", 10);\n%! assert (isempty (reg));\n%! assert (prop1, 5);\n%!test <*58533>\n%! [foo, bar1, bar2] = parseparams ({ 0, \"model\", 1, \"N\", 2},\"model\", 4, \"N\", 5, \"d\", 6);\n%! assert (foo, {0});\n%! assert (bar1, 1);\n%! assert (bar2, 2);\n\n%!error <needs odd number of arguments> parseparams ({1}, \"linewidth\")\n%!error <must be given as name-value pairs> parseparams ({1, \"color\"}, \"linewidth\", 5)\n%!error <unrecognized option: color> parseparams ({1, \"color\", 5}, \"linewidth\", 5)\n"
  },
  {
    "path": "scripts/miscellaneous/perl.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{output} =} perl (@var{scriptfile})\n## @deftypefnx {} {@var{output} =} perl (@var{scriptfile}, @var{argument1}, @var{argument2}, @dots{})\n## @deftypefnx {} {[@var{output}, @var{status}] =} perl (@dots{})\n## Invoke Perl script @var{scriptfile}, possibly with a list of command line\n## arguments.\n##\n## Return output in @var{output} and optional status in @var{status}.  If\n## @var{scriptfile} is not an absolute filename it is searched for in the\n## current directory and then in the Octave loadpath.\n## @seealso{system, python}\n## @end deftypefn\n\nfunction [output, status] = perl (scriptfile, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (ischar (scriptfile) && isrow (scriptfile)) || isempty (scriptfile))\n    error (\"perl: SCRIPTFILE must be a non-empty string\");\n  endif\n  if (nargin > 1 && ! iscellstr (varargin))\n    error (\"perl: ARGUMENTS must be strings\");\n  endif\n\n  if (numel (scriptfile) < 2 || ! strcmp (scriptfile(1:2), \"-e\"))\n    ## Attempt to find file in loadpath.  No effect for absolute filenames.\n    fname = file_in_loadpath (scriptfile);\n  endif\n\n  if (! exist (fname, 'file'))\n    error (\"perl: SCRIPTFILE <%s> not found\", scriptfile);\n  endif\n\n  [status, output] = system ([\"perl \" fname sprintf(\" %s\", varargin{:})]);\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> perl ()\n%!error <SCRIPTFILE must be a non-empty string> perl (123)\n%!error <SCRIPTFILE must be a non-empty string> perl (['a';'b'])\n%!error <SCRIPTFILE must be a non-empty string> perl (\"\")\n%!error <ARGUMENTS must be strings> perl (\"perlfile\", 123)\n%!error <SCRIPTFILE .* not found> perl (\"%%_not_a_name.XYZ\")\n"
  },
  {
    "path": "scripts/miscellaneous/private/__memoize__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{mem_fcn_handle} =} __memoize__ (@var{fcn_handle})\n## @deftypefnx {} {} __memoize__ ()\n## Internal function used by @code{memoize}.\n##\n## @seealso{clearAllMemoizedCaches, memoize}\n## @end deftypefn\n\nfunction mem_fcn_handle = __memoize__ (fcn_handle)\n  persistent cached_mem_fcn_handle;\n\n  if (nargin)\n\n    for i = 1:numel (cached_mem_fcn_handle)\n      if (isequal (cached_mem_fcn_handle{i}.Function, fcn_handle))\n        mem_fcn_handle = cached_mem_fcn_handle{i};\n        return;\n      endif\n    endfor\n\n    mem_fcn_handle = matlab.lang.MemoizedFunction (fcn_handle);\n    cached_mem_fcn_handle{end+1} = mem_fcn_handle;\n\n  else\n\n    for i = 1:numel (cached_mem_fcn_handle)\n      clearCache (cached_mem_fcn_handle{i});\n    endfor\n\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/miscellaneous/private/__publish_html_output__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{outstr} =} __publish_html_output__ (@var{type}, @var{varargin})\n##\n## Internal function.\n##\n## The first input argument @var{type} defines the required strings\n## (@samp{str}) or cell-strings (@samp{cstr}) in @var{varargin} in order\n## to produce HTML output.\n##\n## @var{type} is one of\n##\n## @itemize @bullet\n## @item\n## @samp{output_file_extension} ()\n##\n## @item\n## @samp{header} (title_str, intro_str, toc_cstr)\n##\n## @item\n## @samp{footer} ()\n##\n## @item\n## @samp{code} (str)\n##\n## @item\n## @samp{code_output} (str)\n##\n## @item\n## @samp{section} (str)\n##\n## @item\n## @samp{preformatted_code} (str)\n##\n## @item\n## @samp{preformatted_text} (str)\n##\n## @item\n## @samp{bulleted_list} (cstr)\n##\n## @item\n## @samp{numbered_list} (cstr)\n##\n## @item\n## @samp{graphic} (str)\n##\n## @item\n## @samp{html} (str)\n##\n## @item\n## @samp{latex} (str)\n##\n## @item\n## @samp{text} (str)\n##\n## @item\n## @samp{blockmath} (str)\n##\n## @item\n## @samp{inlinemath} (str)\n##\n## @item\n## @samp{bold} (str)\n##\n## @item\n## @samp{italic} (str)\n##\n## @item\n## @samp{monospaced} (str)\n##\n## @item\n## @samp{link} (url_str, url_str, str)\n##\n## @item\n## @samp{TM} ()\n##\n## @item\n## @samp{R} ()\n##\n## @item\n## @samp{escape_special_chars} (str)\n## @end itemize\n## @end deftypefn\n\nfunction outstr = __publish_html_output__ (type, varargin)\n  outstr = feval ([\"do_\" type], varargin{:});\nendfunction\n\nfunction outstr = do_output_file_extension ()\n  outstr = \".html\";\nendfunction\n\nfunction outstr = do_header (title_str, intro_str, toc_cstr)\n\n  mathjax_str = sprintf (\"%s\\n\",\n\"<script>\",\n\"MathJax = {\",\n\"  tex: {\",\n\"    inlineMath: [['$','$'], ['\\\\\\\\(','\\\\\\\\)']],\",\n\"    tags: 'all'\",\n\"  }\",\n\"};\",\n\"</script>\",\n'<script type=\"text/javascript\" async ',\n'src=\"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\">',\n\"</script>\");\n\n  stylesheet_str = sprintf (\"%s\\n\",\n\"<style>\",\n\"body > * {\",\n\"  max-width: 42em;\",\n\"}\",\n\"body {\",\n'  font-family: \"Roboto Condensed\", sans-serif;',\n\"  padding-left: 7.5em;\",\n\"  padding-right: 7.5em;\",\n\"}\",\n\"pre, code {\",\n\"  max-width: 50em;\",\n\"  font-family: monospace;\",\n\"}\",\n\"pre.oct-code {\",\n\"  border: 1px solid Grey;\",\n\"  padding: 5px;\",\n\"}\",\n\"pre.oct-code-output {\",\n\"  margin-left: 2em;\",\n\"}\",\n\"span.comment {\",\n\"  color: ForestGreen;\",\n\"}\",...\n\"span.keyword {\",\n\"  color: Blue;\",\n\"}\",...\n\"span.string {\",\n\"  color: DarkOrchid;\",\n\"}\",...\n\"footer {\",\n\"  margin-top: 2em;\",\n\"  font-size: 80%;\",\n\"}\",\n\"a, a:visited {\",\n\"  color: Blue;\",\n\"}\",\n\"h2 {\",\n'  font-family: \"Roboto Condensed\", serif;',\n\"  margin-top: 1.5em;\",\n\"}\",\n\"h2 a, h2 a:visited {\",\n\"  color: Black;\",\n\"}\",\n\"</style>\");\n\n  outstr = sprintf (\"%s\\n\",\n\"<!DOCTYPE html>\",\n\"<html>\",\n\"<head>\",\n'<meta charset=\"UTF-8\">',\n[\"<title>\" title_str \"</title>\"],\nmathjax_str,\nstylesheet_str,\n\"</head>\",\n\"<body>\",\n[\"<h1>\" title_str \"</h1>\"],\nintro_str);\n\n  if (! isempty (toc_cstr))\n    for i = 1:numel (toc_cstr)\n      toc_cstr{i} = do_link ([\"#node\" sprintf(\"%d\", i)], toc_cstr{i});\n    endfor\n    outstr = [outstr, \"<h2>Contents</h2>\", do_bulleted_list(toc_cstr)];\n  endif\n\n  ## Reset section counter\n  do_section ();\n\nendfunction\n\nfunction outstr = do_footer (m_source_str)\n\n  outstr = sprintf (\"%s\\n\",\n\"\",\n\"<footer>\",\n\"<hr>\",\n['<a href=\"https://www.octave.org\">Published with GNU Octave ' version() '</a>'],\n\"</footer>\",\n\"<!--\",\n\"##### SOURCE BEGIN #####\",\nm_source_str,\n\"##### SOURCE END #####\",\n\"-->\",\n\"</body>\",\n\"</html>\");\n\nendfunction\n\nfunction outstr = do_code (str)\n  outstr = [\"\\n\", '<pre class=\"oct-code\">' syntax_highlight(str) \"</pre>\\n\"];\nendfunction\n\nfunction outstr = do_code_output (str)\n  str = do_escape_special_chars (str);\n  outstr = [\"\\n\", '<pre class=\"oct-code-output\">' str \"</pre>\\n\"];\nendfunction\n\nfunction outstr = do_section (varargin)\n  persistent counter = 1;\n\n  if (nargin == 0)\n    outstr = \"\";\n    counter = 1;\n    return;\n  endif\n\n  outstr = ['<h2><a id=\"node' sprintf(\"%d\", counter) '\">', ...\n            varargin{1}, ...\n            \"</a></h2>\"];\n\n  counter++;\n\nendfunction\n\nfunction outstr = do_preformatted_code (str)\n  outstr = [\"\\n\", '<pre class=\"pre-code\">' syntax_highlight(str) \"</pre>\\n\"];\nendfunction\n\nfunction outstr = do_preformatted_text (str)\n  str = do_escape_special_chars (str);\n  outstr = [\"\\n\", '<pre class=\"pre-text\">' str \"</pre>\\n\"];\nendfunction\n\nfunction outstr = do_bulleted_list (cstr)\n\n  outstr = \"\\n<ul>\\n\";\n  for i = 1:numel (cstr)\n    outstr = [outstr, \"<li>\" cstr{i} \"</li>\\n\"];\n  endfor\n  outstr = [outstr, \"</ul>\\n\"];\n\nendfunction\n\nfunction outstr = do_numbered_list (cstr)\n\n  outstr = \"\\n<ol>\\n\";\n  for i = 1:numel (cstr)\n    outstr = [outstr, \"<li>\" cstr{i} \"</li>\\n\"];\n  endfor\n  outstr = [outstr, \"</ol>\\n\"];\n\nendfunction\n\nfunction outstr = do_graphic (str)\n  outstr = ['<img src=\"' str '\" alt=\"' str '\">'];\nendfunction\n\nfunction outstr = do_html (str)\n  outstr = [\"\\n\" str \"\\n\"];\nendfunction\n\nfunction outstr = do_latex (str)\n  outstr = \"\";\nendfunction\n\nfunction outstr = do_link (url_str, str)\n  outstr = ['<a href=\"' url_str '\">' str \"</a>\"];\nendfunction\n\nfunction outstr = do_text (str)\n  outstr = [\"\\n<p>\" str \"</p>\\n\"];\nendfunction\n\nfunction outstr = do_blockmath (str)\n  outstr = [\"$$\" str \"$$\"];\nendfunction\n\nfunction outstr = do_inlinemath (str)\n  outstr = [\"$\" str \"$\"];\nendfunction\n\nfunction outstr = do_bold (str)\n  outstr = [\"<b>\" str \"</b>\"];\nendfunction\n\nfunction outstr = do_italic (str)\n  outstr = [\"<i>\" str \"</i>\"];\nendfunction\n\nfunction outstr = do_monospaced (str)\n  outstr = [\"<code>\" str \"</code>\"];\nendfunction\n\nfunction outstr = do_TM ()\n  outstr = \"&trade;\";\nendfunction\n\nfunction outstr = do_R ()\n  outstr = \"&reg;\";\nendfunction\n\nfunction str = do_escape_special_chars (str)\n  str = regexprep (str, '&', '&amp;');\n  str = regexprep (str, '<', '&lt;');\n  str = regexprep (str, '>', '&gt;');\n  ## str = regexprep (str, '\"', '&quot;'); ## MATLAB R2017a compatibility.\nendfunction\n\n## SYNTAX_HIGHLIGHT: A primitive parser to highlight syntax via <span> tags.\n## FIXME: Needs to be replaced by a better solution.\nfunction outstr = syntax_highlight (str)\n\n  str = do_escape_special_chars (str);\n  outstr = \"\";\n  placeholder_cstr = {};\n  i = 1;\n  plh = 0;\n\n  while (i <= numel (str))\n    ## Block comment\n    if (any (strncmp (str(i:end), {\"%{\", \"#{\"}, 2)))\n      plh_str = ['<span class=\"comment\">', str(i:i+1)];\n      i += 2;\n      while (i <= numel (str)\n             && ! (any (strncmp (str(i:end), {\"%}\", \"#}\"}, 2))))\n        plh_str = [plh_str, str(i)];\n        i += 1;\n      endwhile\n      if (i < numel (str))\n        plh_str = [plh_str, str(i:i+1), \"</span>\"];\n        i += 2;\n      else\n        plh_str = [plh_str, \"</span>\"];\n      endif\n      plh += 1;\n      placeholder_cstr{plh} = plh_str;\n      outstr = [outstr, \" PUBLISHPLACEHOLDER\", sprintf(\"%d\", plh), \" \"];\n    ## Line comment\n    elseif (str(i) == \"#\" || str(i) == \"%\")\n      plh_str = '<span class=\"comment\">';\n      idx = find (str(i:end) == \"\\n\", 1);\n      if (isempty (idx))\n        plh_str = [plh_str, str(i:end)];\n        i = numel (str) + 1;\n      else\n        plh_str = [plh_str, str(i:i+idx-2)];\n        i += idx;\n      endif\n      plh_str = [plh_str, \"</span>\\n\"];\n      plh += 1;\n      placeholder_cstr{plh} = plh_str;\n      outstr = [outstr, \" PUBLISHPLACEHOLDER\", sprintf(\"%d\", plh), \" \"];\n    ## Single quoted string\n    elseif (str(i) == \"'\")\n      plh_str = \"<span class=\\\"string\\\">'\";\n      i += 1;\n      while (i <= numel (str))\n        ## Ignore escaped string terminations\n        if (strncmp (str(i:end), \"''\", 2))\n          plh_str = [plh_str, \"''\"];\n          i += 2;\n        ## Is char a string termination?\n        elseif (str(i) == \"'\")\n          plh_str = [plh_str, \"'\"];\n          i += 1;\n          break;\n        ## Is string terminated by line break?\n        elseif (str(i) == \"\\n\")\n          break;\n        ## String content\n        else\n          plh_str = [plh_str, str(i)];\n          i += 1;\n        endif\n      endwhile\n      plh_str = [plh_str, \"</span>\"];\n      plh += 1;\n      placeholder_cstr{plh} = plh_str;\n      outstr = [outstr, \" PUBLISHPLACEHOLDER\", sprintf(\"%d\", plh), \" \"];\n    ## Double quoted string\n    elseif (str(i) == '\"')\n      plh_str = '<span class=\"string\">\"';\n      i += 1;\n      while (i <= numel (str))\n        ## Is char a string termination?\n        if (str(i) == '\"' && str(i-1) != '\\')\n          plh_str = [plh_str, '\"'];\n          i += 1;\n          break;\n        ## Is string terminated by line break?\n        elseif (str(i) == \"\\n\")\n          break;\n        ## String content\n        else\n          plh_str = [plh_str, str(i)];\n          i += 1;\n        endif\n      endwhile\n      plh_str = [plh_str, \"</span>\"];\n      plh += 1;\n      placeholder_cstr{plh} = plh_str;\n      outstr = [outstr, \" PUBLISHPLACEHOLDER\", sprintf(\"%d\", plh), \" \"];\n    else\n      outstr = [outstr, str(i)];\n      i += 1;\n    endif\n  endwhile\n\n  persistent kword_ptn = strjoin (iskeyword (), '|');\n\n  ## FIXME: remove hack for regexprep once bug #38149 is solved\n  outstr = [\" \", strrep(outstr, \"\\n\", \" \\n \"), \" \"];\n  outstr = regexprep (outstr,\n                      ['(\\s)(' kword_ptn ')(\\s|\\()'],\n                      ['$1<span class=\"keyword\">$2</span>$3']);\n  ## FIXME: remove hack for regexprep once bug #38149 is solved\n  outstr = strrep (outstr(2:end-1), \" \\n \", \"\\n\");\n\n  ## Restore placeholders\n  for i = plh:-1:1\n    outstr = strrep (outstr, [\" PUBLISHPLACEHOLDER\", sprintf(\"%d\", i), \" \"],\n                             placeholder_cstr{i});\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/miscellaneous/private/__publish_latex_output__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{outstr} =} __publish_latex_output__ (@var{type}, @var{varargin})\n##\n## Internal function.\n##\n## The first input argument @var{type} defines the required strings\n## (@samp{str}) or cell-strings (@samp{cstr}) in @var{varargin} in order\n## to produce @LaTeX{} output.\n##\n## @var{type} is one of\n##\n## @itemize @bullet\n## @item\n## @samp{output_file_extension} ()\n##\n## @item\n## @samp{header} (title_str, intro_str, toc_cstr)\n##\n## @item\n## @samp{footer} ()\n##\n## @item\n## @samp{code} (str)\n##\n## @item\n## @samp{code_output} (str)\n##\n## @item\n## @samp{section} (str)\n##\n## @item\n## @samp{preformatted_code} (str)\n##\n## @item\n## @samp{preformatted_text} (str)\n##\n## @item\n## @samp{bulleted_list} (cstr)\n##\n## @item\n## @samp{numbered_list} (cstr)\n##\n## @item\n## @samp{graphic} (str)\n##\n## @item\n## @samp{html} (str)\n##\n## @item\n## @samp{latex} (str)\n##\n## @item\n## @samp{text} (str)\n##\n## @item\n## @samp{blockmath} (str)\n##\n## @item\n## @samp{inlinemath} (str)\n##\n## @item\n## @samp{bold} (str)\n##\n## @item\n## @samp{italic} (str)\n##\n## @item\n## @samp{monospaced} (str)\n##\n## @item\n## @samp{link} (url_str, url_str, str)\n##\n## @item\n## @samp{TM} ()\n##\n## @item\n## @samp{R} ()\n##\n## @item\n## @samp{escape_special_chars} (str)\n## @end itemize\n## @end deftypefn\n\nfunction outstr = __publish_latex_output__ (type, varargin)\n  outstr = feval ([\"do_\" type], varargin{:});\nendfunction\n\nfunction outstr = do_output_file_extension ()\n  outstr = \".tex\";\nendfunction\n\nfunction outstr = do_header (title_str, intro_str, toc_cstr)\n\n  publish_comment = sprintf (\"%s\\n\",\n\"\",\n\"\",\n\"% This document was generated by the publish-function\",\n[\"% from GNU Octave \" version()],\n\"\");\n\n  latex_preamble = sprintf (\"%s\\n\",\n\"\",\n\"\",\n'\\documentclass[10pt]{article}',\n'\\usepackage{listings}',\n'\\usepackage{mathtools}',\n'\\usepackage{amssymb}',\n'\\usepackage{graphicx}',\n'\\usepackage{hyperref}',\n'\\usepackage{xcolor}',\n'\\usepackage{titlesec}',\n'\\usepackage[utf8]{inputenc}',\n'\\usepackage[T1]{fontenc}',\n'\\usepackage{lmodern}');\n\n  ## \"lstlisting\" doesn't support multi-byte UTF-8 characters.\n  ## Add substitution rules for some characters (commonly used in languages with\n  ## Latin-based script).\n  ## Set of substitions taken from:\n  ## https://en.wikibooks.org/w/index.php?title=LaTeX/Source_Code_Listings&oldid=3815132#Encoding_issue\n  ## FIXME: Any multi-byte UTF-8 character in a non-section comment without a\n  ##        substitution rule will still cause an error.  This should be fixed\n  ##        more generally, or a way how to work around this limitation should\n  ##        be documented.\n  listings_option = sprintf (\"%s\\n\",\n\"\",\n\"\",\n'\\lstset{',\n'language=Octave,',\n'numbers=none,',\n'frame=single,',\n'tabsize=2,',\n'showstringspaces=false,',\n'breaklines=true,',\n'inputencoding=utf8,',\n'extendedchars=true,',\n'literate=',\n'  {á}{{\\''a}}1 {é}{{\\''e}}1 {í}{{\\''i}}1 {ó}{{\\''o}}1 {ú}{{\\''u}}1',\n'  {Á}{{\\''A}}1 {É}{{\\''E}}1 {Í}{{\\''I}}1 {Ó}{{\\''O}}1 {Ú}{{\\''U}}1',\n'  {à}{{\\`a}}1 {è}{{\\`e}}1 {ì}{{\\`i}}1 {ò}{{\\`o}}1 {ù}{{\\`u}}1',\n'  {À}{{\\`A}}1 {È}{{\\''E}}1 {Ì}{{\\`I}}1 {Ò}{{\\`O}}1 {Ù}{{\\`U}}1',\n'  {ä}{{\\\"a}}1 {ë}{{\\\"e}}1 {ï}{{\\\"i}}1 {ö}{{\\\"o}}1 {ü}{{\\\"u}}1',\n'  {Ä}{{\\\"A}}1 {Ë}{{\\\"E}}1 {Ï}{{\\\"I}}1 {Ö}{{\\\"O}}1 {Ü}{{\\\"U}}1',\n'  {â}{{\\^a}}1 {ê}{{\\^e}}1 {î}{{\\^i}}1 {ô}{{\\^o}}1 {û}{{\\^u}}1',\n'  {Â}{{\\^A}}1 {Ê}{{\\^E}}1 {Î}{{\\^I}}1 {Ô}{{\\^O}}1 {Û}{{\\^U}}1',\n'  {ã}{{\\~a}}1 {ẽ}{{\\~e}}1 {ĩ}{{\\~i}}1 {õ}{{\\~o}}1 {ũ}{{\\~u}}1',\n'  {Ã}{{\\~A}}1 {Ẽ}{{\\~E}}1 {Ĩ}{{\\~I}}1 {Õ}{{\\~O}}1 {Ũ}{{\\~U}}1',\n'  {œ}{{\\oe}}1 {Œ}{{\\OE}}1 {æ}{{\\ae}}1 {Æ}{{\\AE}}1 {ß}{{\\ss}}1',\n'  {ű}{{\\H{u}}}1 {Ű}{{\\H{U}}}1 {ő}{{\\H{o}}}1 {Ő}{{\\H{O}}}1',\n'  {ç}{{\\c c}}1 {Ç}{{\\c C}}1 {ø}{{\\o}}1 {å}{{\\r a}}1 {Å}{{\\r A}}1',\n'  {€}{{\\euro}}1 {£}{{\\pounds}}1 {«}{{\\guillemotleft}}1',\n'  {»}{{\\guillemotright}}1 {ñ}{{\\~n}}1 {Ñ}{{\\~N}}1 {¿}{{?`}}1 {¡}{{!`}}1',\n'}');\n\n  latex_head = sprintf (\"%s\\n\",\n\"\",\n\"\",\n'\\titleformat*{\\section}{\\Huge\\bfseries}',\n'\\titleformat*{\\subsection}{\\large\\bfseries}',\n'\\renewcommand{\\contentsname}{\\Large\\bfseries Contents}',\n'\\setlength{\\parindent}{0pt}',\n\"\",\n'\\begin{document}',\n\"\",\n['{\\Huge\\section*{' title_str '}}'],\n\"\",\n'\\tableofcontents',\n'\\vspace*{4em}',\n\"\");\n\n  outstr = [publish_comment, latex_preamble, listings_option, latex_head];\n\nendfunction\n\nfunction outstr = do_footer (m_source_str)\n  outstr = [\"\\n\\n\" '\\end{document}' \"\\n\"];\nendfunction\n\nfunction outstr = do_code (str)\n  outstr = ['\\begin{lstlisting}' \"\\n\", str, \"\\n\" '\\end{lstlisting}' \"\\n\"];\nendfunction\n\nfunction outstr = do_code_output (str)\n  outstr = sprintf (\"%s\\n\",\n'\\begin{lstlisting}[language={},xleftmargin=5pt,frame=none]',\nstr,\n'\\end{lstlisting}');\nendfunction\n\nfunction outstr = do_section (str)\n\n  outstr = sprintf (\"%s\\n\",\n\"\",\n\"\",\n'\\phantomsection',\n['\\addcontentsline{toc}{section}{' str '}'],\n['\\subsection*{' str '}'],\n\"\");\n\nendfunction\n\nfunction outstr = do_preformatted_code (str)\n  outstr = sprintf (\"%s\\n\",\n'\\begin{lstlisting}',\nstr,\n'\\end{lstlisting}');\nendfunction\n\nfunction outstr = do_preformatted_text (str)\n  outstr = sprintf (\"%s\\n\",\n'\\begin{lstlisting}[language={}]',\nstr,\n'\\end{lstlisting}');\nendfunction\n\nfunction outstr = do_bulleted_list (cstr)\n\n  outstr = [\"\\n\" '\\begin{itemize}' \"\\n\"];\n  for i = 1:numel (cstr)\n    outstr = [outstr, '\\item ' cstr{i} \"\\n\"];\n  endfor\n  outstr = [outstr, '\\end{itemize}' \"\\n\"];\n\nendfunction\n\nfunction outstr = do_numbered_list (cstr)\n\n  outstr = [\"\\n\" '\\begin{enumerate}' \"\\n\"];\n  for i = 1:numel (cstr)\n    outstr = [outstr, '\\item ' cstr{i} \"\\n\"];\n  endfor\n  outstr = [outstr, \"\\\\end{enumerate}\\n\"];\n\nendfunction\n\nfunction outstr = do_graphic (str)\n  outstr = sprintf (\"%s\\n\",\n'\\begin{figure}[!ht]',\n['\\includegraphics[width=\\textwidth]{' str '}'],\n'\\end{figure}');\nendfunction\n\nfunction outstr = do_html (str)\n  outstr = \"\";\nendfunction\n\nfunction outstr = do_latex (str)\n  outstr = [\"\\n\" str \"\\n\"];\nendfunction\n\nfunction outstr = do_link (url_str, str)\n  outstr = ['\\href{' url_str '}{' str '}'];\nendfunction\n\nfunction outstr = do_text (str)\n  outstr = [\"\\n\\n\" str \"\\n\\n\"];\nendfunction\n\nfunction outstr = do_blockmath (str)\n  outstr = [\"$$\" str \"$$\"];\nendfunction\n\nfunction outstr = do_inlinemath (str)\n  outstr = [\"$\" str \"$\"];\nendfunction\n\nfunction outstr = do_bold (str)\n  outstr = ['\\textbf{' str '}'];\nendfunction\n\nfunction outstr = do_italic (str)\n  outstr = ['\\textit{' str '}'];\nendfunction\n\nfunction outstr = do_monospaced (str)\n  outstr = ['\\texttt{' str '}'];\nendfunction\n\nfunction outstr = do_TM ()\n  outstr = '\\texttrademark ';\nendfunction\n\nfunction outstr = do_R ()\n  outstr = '\\textregistered ';\nendfunction\n\nfunction str = do_escape_special_chars (str)\n\n  ## Escape \\, {, }, &, %, #, _, ~, ^, <, >\n  str = regexprep (str, '\\\\', \"\\\\ensuremath{\\\\backslash}\");\n  str = regexprep (str, '(?<!\\\\)(\\{|\\}|&|%|#|_)', '\\\\$1');\n  ## Revert accidental {} replacements for backslashes\n  str = strrep (str, '\\ensuremath\\{\\backslash\\}', '\\ensuremath{\\backslash}');\n  str = regexprep (str, '(?<!\\\\)~', \"\\\\ensuremath{\\\\tilde{\\\\;}}\");\n  str = regexprep (str, '(?<!\\\\)\\^', \"\\\\^{}\");\n  str = regexprep (str, '(?<!\\\\)<', \"\\\\ensuremath{<}\");\n  str = regexprep (str, '(?<!\\\\)>', \"\\\\ensuremath{>}\");\n\nendfunction\n"
  },
  {
    "path": "scripts/miscellaneous/private/__w2mpth__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{mingwpath} =} __w2mpth__ (@var{winpath})\n## Convert a Windows-style relative or full path name to MinGW style.\n##\n## @strong{Caution:} __w2mpth__ does not check the validity of the path.\n##\n## Examples:\n##\n## @example\n## @group\n##   mpth = __w2mpth__ ('D:\\full\\path\\to\\file.dat')\n##   @xresult{} '/D/full/path/to/file.dat'\n## @end group\n## @end example\n##\n## @example\n## @group\n##   mpth = __w2mpth__ ('relative\\path\\to\\file.dat')\n##   @xresult{} 'relative/path/to/file.dat'\n## @end group\n## @end example\n##\n## @end deftypefn\n\nfunction mingwpath = __w2mpth__ (winpath)\n\n  ## Check for platform\n  if (! ispc)\n    error (\"__w2mpth__: function must only be called on Windows platforms\\n\");\n  endif\n\n  ## Replace backslash file separators by forward slashes\n  mingwpath = strrep (winpath, '\\', '/');\n  ## Also treat drive letter but beware of relative filenames\n  mingwpath = regexprep (mingwpath, '^([a-zA-Z]):', '/$1');\n\nendfunction\n\n\n## Use single quote strings for winpaths to cope with backslashes.\n## These tests are commented out until a better place is found (bug #44581)\n%!#test\n%!# if (ispc)\n%!#   assert (__w2mpth__ ('file.fil'), 'file.fil');\n%!#   assert (__w2mpth__ ('\\file.fil'), '/file.fil');\n%!#   assert (__w2mpth__ ('G:\\file.fil'), '/G/file.fil');\n%!#   assert (__w2mpth__ ('r:\\subdir\\file.fil'), '/r/subdir/file.fil');\n%!#   assert (__w2mpth__ ('relative\\path\\to\\file.dat'),\n%!#                       'relative/path/to/file.dat')\n%!# endif\n"
  },
  {
    "path": "scripts/miscellaneous/private/display_info_file.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## news() and citation() are very much alike.  They both do the same thing,\n## just for different files.  This function does all the work.\n\nfunction display_info_file (fcn, package, file)\n\n  if (! ischar (package))\n    error (\"%s: PACKAGE must be a string\", fcn);\n  endif\n\n  if (strcmpi (package, \"octave\"))\n    octetcdir = __octave_config_info__ (\"octetcdir\");\n    filepath  = fullfile (octetcdir, file);\n  else\n    installed = pkg (\"list\");\n    names     = cellfun (@(x) x.name, installed, \"UniformOutput\", false);\n    pos       = strcmpi (names, package);\n    if (! any (pos))\n      error (\"%s: package '%s' is not installed\", fcn, package);\n    endif\n    filepath = fullfile (installed{pos}.dir, \"packinfo\", file);\n  endif\n\n  if (! exist (filepath, \"file\"))\n    if (strcmpi (package, \"octave\"))\n      error (\"%s: broken installation -- unable to locate %s file\", fcn, file);\n    else\n      error (\"%s: unable to locate %s file for package %s\", fcn, file, package);\n    endif\n  endif\n\n  fid = fopen (filepath, \"r\");\n  while (ischar (line = fgets (fid)))\n    puts (line);\n  endwhile\n  fclose (fid);\n\nendfunction\n"
  },
  {
    "path": "scripts/miscellaneous/private/tar_is_bsd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{out} =} tar_is_bsd ()\n## True if the default tar command is BSD tar.\n##\n## Checks whether the default tar command (the one invoked when an un-prefixed\n## @code{tar} is executed) is BSD tar or another tar.  Caches the results for\n## performance.\n##\n## Returns true if the detected tar is BSD tar, and false otherwise.  Errors if\n## @code{tar --version} does not succeed.\n## @end deftypefn\n\nfunction out = tar_is_bsd ()\n\n  ## BSD tar needs to be handled differently from GNU tar\n  persistent cache;\n  if (isempty (cache))\n    [status, tar_ver_str] = system (\"tar --version\");\n    if (status)\n      error (\"tar: Failed executing tar --version (status = %d)\", status);\n    endif\n    cache = ! isempty (regexp (tar_ver_str, \"bsdtar\"));\n  endif\n  out = cache;\n\nendfunction\n"
  },
  {
    "path": "scripts/miscellaneous/publish.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} publish (@var{file})\n## @deftypefnx {} {} publish (@var{file}, @var{output_format})\n## @deftypefnx {} {} publish (@var{file}, @var{option1}, @var{value1}, @dots{})\n## @deftypefnx {} {} publish (@var{file}, @var{options})\n## @deftypefnx {} {@var{output_file} =} publish (@var{file}, @dots{})\n##\n## Generate a report from the Octave script file @var{file} in one of several\n## output formats.\n##\n## The generated reports interpret Publishing Markup in section comments, which\n## is explained in detail in the GNU Octave manual.  Section comments are\n## comment blocks that start with a line with double comment character.\n##\n## Assume the following example, using some Publishing Markup, to be the\n## contents of the script file @file{pub_example.m}:\n##\n## @example\n## @group\n## ## Headline title\n## #\n## # Some *bold*, _italic_, or |monospaced| Text with\n## # a <https://www.octave.org link to *GNU Octave*>.\n## ##\n##\n## # \"Real\" Octave commands to be evaluated\n## sombrero ()\n##\n## %% @sc{matlab} comment style ('%') is supported as well\n## %\n## % * Bulleted list item 1\n## % * Bulleted list item 2\n## %\n## % # Numbered list item 1\n## % # Numbered list item 2\n## @end group\n## @end example\n##\n## To publish this script file, type @code{publish (\"pub_example.m\")}.\n##\n## When called with one input argument, a HTML report is generated in a\n## subdirectory @file{html} relative to the current working directory.  Any\n## Octave commands in @file{pub_example.m} are evaluated in a separate context\n## and any figures created while executing the script file are included in the\n## report.\n##\n## Using @code{publish (@var{file}, @var{output_format})} is equivalent to the\n## function call using a structure\n##\n## @example\n## @group\n## @var{options}.format = @var{output_format};\n## publish (@var{file}, @var{options})\n## @end group\n## @end example\n##\n## @noindent\n## which is described below.  The same holds for using option/value pairs\n##\n## @example\n## @group\n## @var{options}.@var{option1} = @var{value1};\n## publish (@var{file}, @var{options})\n## @end group\n## @end example\n##\n## The structure @var{options} can have the following field names.  If a field\n## name is not specified, the default value is used:\n##\n## @itemize @bullet\n## @item\n## @samp{format} --- Output format of the published script file, one of\n##\n## @samp{html} (default), @samp{doc}, @samp{latex}, @samp{ppt},\n## @samp{pdf}, or @samp{xml}.\n##\n## The output formats @samp{doc}, @samp{ppt}, and @samp{xml} are not currently\n## supported.  To generate a @samp{doc} report, open a generated @samp{html}\n## report with your office suite.\n##\n## In Octave custom formats are supported by implementing all callback\n## subfunctions in a function file named\n## @samp{__publish_<custom format>_output__.m}.  To obtain a template for the\n## HTML format type:\n##\n## @example\n## @group\n## edit (fullfile (fileparts (which (\"publish\")), ...\n##       \"private\", \"__publish_html_output__.m\"))\n## @end group\n## @end example\n##\n## @item\n## @samp{outputDir} --- Full path of the directory where the generated report\n## will be located.  If no directory is given, the report is generated in a\n## subdirectory @file{html} relative to the current working directory.\n##\n## @item\n## @samp{stylesheet} --- Not supported, only for @sc{matlab} compatibility.\n##\n## @item\n## @samp{createThumbnail} --- Not supported, only for @sc{matlab}\n## compatibility.\n##\n## @item\n## @samp{figureSnapMethod} --- Not supported, only for @sc{matlab}\n## compatibility.\n##\n## @item\n## @samp{imageFormat} --- Desired format for any images produced while\n## evaluating the code.  The allowed image formats depend on the output format:\n##\n## @itemize @bullet\n## @item @samp{html}, @samp{xml} --- @samp{png} (default), any image format\n## supported by Octave\n##\n## @item @samp{latex} --- @samp{epsc2} (default), any image format supported by\n## Octave\n##\n## @item @samp{pdf} --- @samp{jpg} (default) or @samp{bmp}, note @sc{matlab}\n## uses @samp{bmp} as default\n##\n## @item @samp{doc} or @samp{ppt} --- @samp{png} (default), @samp{jpg},\n## @samp{bmp}, or @samp{tiff}\n## @end itemize\n##\n## @item\n## @samp{maxWidth} and @samp{maxHeight} --- Maximum width (height) of the\n## produced images in pixels.  An empty value means no restriction.  Both\n## values must be set in order for the option to work properly.\n##\n## @samp{[]} (default), integer value @geq{} 0\n##\n## @item\n## @samp{useNewFigure} --- Use a new figure window for figures created by the\n## evaluated code.  This avoids side effects with already opened figure\n## windows.\n##\n## @samp{true} (default) or @samp{false}\n##\n## @item\n## @samp{evalCode} --- Evaluate code of the Octave source file\n##\n## @samp{true} (default) or @samp{false}\n##\n## @item\n## @samp{catchError} --- Catch errors while evaluating code and continue\n##\n## @samp{true} (default) or @samp{false}\n##\n## @item\n## @samp{codeToEvaluate} --- Octave commands that should be evaluated prior to\n## publishing the script file.  These Octave commands do not appear in the\n## generated report.\n##\n## @item\n## @samp{maxOutputLines} --- Maximum number of output lines from code\n## evaluation which are included in output.\n##\n## @samp{Inf} (default) or integer value > 0\n##\n## @item\n## @samp{showCode} --- Show the evaluated Octave commands in the generated\n## report\n##\n## @samp{true} (default) or @samp{false}\n## @end itemize\n##\n## The option output @var{output_file} is a string with path and file name\n## of the generated report.\n##\n## @seealso{grabcode}\n## @end deftypefn\n\nfunction output_file = publish (file, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (exist (file, \"file\") != 2)\n    error (\"publish: FILE does not exist\");\n  endif\n\n  ## Check file to be in Octave's load path\n  [file_path, file_name, file_ext] = fileparts (file);\n  if (isempty (file_path))\n    file_path = pwd ();\n  endif\n  if (exist ([file_name, file_ext]) != 2)\n    error ([\"publish: \" file \" is not in the load path\"]);\n  endif\n\n  ## Check file extension and that file is an Octave script\n  file_info = __which__ (file_name);\n  if (! strcmp (file_ext, \".m\") || ! strcmp (file_info.type, \"script\"))\n    error (\"publish: only script files can be published\");\n  endif\n\n  ## Check file to be parsable\n  __parse_file__ (file);\n\n  ## Get structure with necessary options\n  options = struct ();\n  if (numel (varargin) == 1)\n    ## Call: publish (file, format)\n    if (ischar (varargin{1}))\n      options.format = varargin{1};\n    ## Call: publish (file, options)\n    elseif (isstruct (varargin{1}))\n      options = varargin{1};\n    else\n      error (\"publish: second argument must be OUTPUT_FORMAT or OPTIONS\");\n    endif\n  ## Call: publish (file, Name1, Value1, Name2, Value2, ...)\n  elseif (rem (numel (varargin), 2) == 0\n          && all (cellfun ('ischar', varargin(1:2:end))))\n    options = cell2struct (varargin(2:2:end), varargin(1:2:end), 2);\n  else\n    error (\"publish: invalid arguments\");\n  endif\n\n  ## Validate options struct\n\n  ## Options for the output\n  if (! isfield (options, \"format\"))\n    options.format = \"html\";\n  else\n    ## FIXME: Implement remaining formats\n    if (any (strcmpi (options.format, {\"doc\", \"ppt\", \"xml\"})))\n      error ('publish: Output format \"%s\" is not yet supported',\n             options.format);\n    endif\n    ## Supported or custom output format\n    supported_formats = {\"html\", \"doc\", \"latex\", \"ppt\", \"xml\", \"pdf\"};\n    if (! any (strcmpi (options.format, supported_formats)))\n      ## Check existence of custom formatter\n      custom_formatter = [\"__publish_\", options.format, \"_output__\"];\n      if (! exist (custom_formatter, \"file\"))\n        error (['publish: Custom output format \"%s\" requires the ', ...\n                \"formatter function:\\n\\n\\t%s\\n\\n\\t\", ...\n                'See \"help publish\" for more information.'],\n                options.format, custom_formatter);\n      endif\n    else\n      options.format = validatestring (options.format, supported_formats);\n    endif\n  endif\n\n  if (! isfield (options, \"outputDir\"))\n    ## Matlab R2016a doc says default is \"\", but specifies to create a\n    ## subdirectory named \"html\" in the current working directory.\n    options.outputDir = fullfile (file_path, \"html\");\n  elseif (! ischar (options.outputDir))\n    error (\"publish: OUTPUTDIR must be a string\");\n  endif\n\n  if (! isfield (options, \"stylesheet\"))\n    options.stylesheet = \"\";\n  elseif (! ischar (options.stylesheet))\n    error (\"publish: STYLESHEET must be a string\");\n  endif\n\n  ## Options for the figures\n  if (! isfield (options, \"createThumbnail\"))\n    options.createThumbnail = true;\n  elseif (! isscalar (options.createThumbnail)\n          || ! isreal (options.createThumbnail))\n    error (\"publish: CREATETHUMBNAIL must be TRUE or FALSE\");\n  endif\n\n  if (! isfield (options, \"figureSnapMethod\"))\n    options.figureSnapMethod = \"entireGUIWindow\";\n  else\n    options.figureSnapMethod = validatestring (options.figureSnapMethod, ...\n      {\"entireGUIWindow\", \"print\", \"getframe\", \"entireFigureWindow\"});\n    ## FIXME: implement other SnapMethods\n    warning (\"publish: option FIGURESNAPMETHOD currently not supported\");\n  endif\n\n  if (! isfield (options, \"imageFormat\"))\n    switch (options.format)\n      case \"latex\"\n        options.imageFormat = \"epsc2\";\n      case \"pdf\"\n        ## Note: Matlab R2016a uses bmp as default\n        options.imageFormat = \"jpg\";\n      otherwise\n        options.imageFormat = \"png\";\n    endswitch\n  elseif (! ischar (options.imageFormat))\n    error (\"publish: IMAGEFORMAT must be a string\");\n  else\n    ## Check valid imageFormat for chosen format\n    ##   html, latex, and xml accept any imageFormat\n    switch (options.format)\n      case {\"doc\", \"ppt\"}\n        options.imageFormat = validatestring (options.imageFormat,\n                                              {\"png\", \"jpg\", \"bmp\", \"tiff\"});\n      case \"pdf\"\n        options.imageFormat = validatestring (options.imageFormat,\n                                              {\"bmp\", \"jpg\"});\n    endswitch\n  endif\n\n  if (! isfield (options, \"maxHeight\"))\n    options.maxHeight = [];\n  elseif (! isscalar (options.maxHeight) || options.maxHeight < 1)\n    error (\"publish: MAXHEIGHT must be a positive integer\");\n  else\n    options.maxHeight = uint64 (options.maxHeight);\n  endif\n\n  if (! isfield (options, \"maxWidth\"))\n    options.maxWidth = [];\n  elseif (! isscalar (options.maxWidth) || options.maxWidth < 1)\n    error (\"publish: MAXWIDTH must be a positive integer\");\n  else\n    options.maxWidth = uint64 (options.maxWidth);\n  endif\n\n  if (! isfield (options, \"useNewFigure\"))\n    options.useNewFigure = true;\n  elseif (! isscalar (options.useNewFigure) || ! isreal (options.useNewFigure))\n    error (\"publish: USENEWFIGURE must be TRUE or FALSE\");\n  endif\n\n  ## Options for the code\n  if (! isfield (options, \"evalCode\"))\n    options.evalCode = true;\n  elseif (! isscalar (options.evalCode) || ! isreal (options.evalCode))\n    error (\"publish: EVALCODE must be TRUE or FALSE\");\n  endif\n\n  if (! isfield (options, \"catchError\"))\n    options.catchError = true;\n  elseif (! isscalar (options.catchError) || ! isreal (options.catchError))\n    error (\"publish: CATCHERROR must be TRUE or FALSE\");\n  endif\n\n  if (! isfield (options, \"codeToEvaluate\"))\n    options.codeToEvaluate = \"\";\n  elseif (! ischar (options.codeToEvaluate))\n    error (\"publish: CODETOEVALUTE must be a string\");\n  endif\n\n  if (! isfield (options, \"maxOutputLines\"))\n    options.maxOutputLines = Inf;\n  elseif (! isscalar (options.maxOutputLines) || options.maxOutputLines < 0)\n    error (\"publish: MAXOUTPUTLINES must be an integer >= 0\");\n  else\n    options.maxOutputLines = uint64 (options.maxOutputLines);\n  endif\n\n  if (! isfield (options, \"showCode\"))\n    options.showCode = true;\n  elseif (! isscalar (options.showCode) || ! isreal (options.showCode))\n    error (\"publish: SHOWCODE must be TRUE or FALSE\");\n  endif\n\n  doc.title = \"\";\n  doc.intro = \"\";\n  doc.body = cell ();\n  doc.m_source = deblank (read_file_to_cellstr (file));\n  doc.m_source_file_name = file;\n\n  ## Split code and paragraphs, find formatting\n  doc = parse_m_source (doc);\n\n  ## Create output directory\n  [status, msg] = mkdir (options.outputDir);\n  if (status != 1)\n    error (\"publish: cannot create output directory: %s\", msg);\n  endif\n\n  if (options.evalCode)\n    doc = eval_code (doc, options);\n    eval_context (\"clear\");\n  endif\n\n  output_file = create_output (doc, options);\n\nendfunction\n\n\nfunction doc = parse_m_source (doc)\n\n  ## PARSE_M_SOURCE First parsing level\n  ##   This function extracts the overall structure (paragraphs and code\n  ##   sections) given in doc.m_source.\n  ##\n  ##   The result is written to doc.body, which then contains a cell\n  ##   vector of structs, either of\n  ##\n  ##     a) {struct (\"type\", \"code\", ...\n  ##                 \"lines\", [a, b], ...\n  ##                 \"output\", [])}\n  ##     b) {struct (\"type\", \"section\", ...\n  ##                 \"content\", title_str)}\n  ##\n  ##   Second parsing level is invoked for the paragraph contents, resulting\n  ##   in more elements for doc.body.\n\n  if (isempty (doc.m_source))\n    return;  # Nothing to parse\n  endif\n\n  ## Parsing helper functions\n  ##\n  ## Checks line to have N \"%\" or \"#\" lines\n  ## followed either by a space or end of string\n  function r = is_publish_markup (cstr, N)\n\n    str = char (cstr);\n\n    r = any (strncmp (str, {\"%%%\", \"##\"}, N));\n    if (r)\n      len = length (str);\n      if (len == N)\n        r = true;\n      elseif (len > N && str(N+1) == \" \")\n        r = true;\n      else\n        r = false;\n      endif\n    endif\n\n    return;\n\n  endfunction\n  ## Checks line of cellstring to be a paragraph line\n  is_paragraph = @(cstr) is_publish_markup (cstr, 1);\n  ## Checks line of cellstring to be a section headline\n  is_head = @(cstr) is_publish_markup (cstr, 2);\n  ## Checks line of cellstring to be a headline without section break, using\n  ## the cell mode in Matlab (for compatibility), just treated as a new head.\n  is_no_break_head = @(cstr) is_publish_markup (cstr, 3);\n\n  ## Find the indices of paragraphs starting with \"%%\", \"##\", or \"%%%\"\n  par_start_idx = find (cellfun (is_head, doc.m_source)\n                        | cellfun (is_no_break_head, doc.m_source));\n\n  ## If the whole document is code\n  if (isempty (par_start_idx))\n    doc.body{end+1}.type = \"code\";\n    doc.body{end}.content = strtrim (strjoin (doc.m_source, \"\\n\"));\n    doc.body{end}.lines = [1, length(doc.m_source)];\n    doc.body{end}.output = {};\n    return;\n  endif\n\n  ## Determine continuous range of paragraphs\n  par_end_idx = [par_start_idx(2:end) - 1, length(doc.m_source)];\n  for i = 1:numel (par_end_idx)\n    idx = find (! cellfun (is_paragraph,\n                           doc.m_source(par_start_idx(i) + 1:par_end_idx(i))));\n    if (! isempty (idx))\n      par_end_idx(i) = par_start_idx(i) + idx(1) - 1;\n    endif\n  endfor\n  ## Code sections between paragraphs\n  code_start_idx = par_end_idx(1:end-1) + 1;\n  code_end_idx = par_start_idx(2:end) - 1;\n  ## Code at the beginning?\n  if (par_start_idx(1) > 1)\n    code_start_idx = [1, code_start_idx];\n    code_end_idx = [par_start_idx(1) - 1, code_end_idx];\n  endif\n  ## Code at the end?\n  if (par_end_idx(end) < length (doc.m_source))\n    code_start_idx = [code_start_idx, par_end_idx(end) + 1];\n    code_end_idx = [code_end_idx, length(doc.m_source)];\n  endif\n  ## Remove overlaps\n  idx = code_start_idx > code_end_idx;\n  code_start_idx(idx) = [];\n  code_end_idx(idx) = [];\n  ## Remove empty code blocks\n  idx = [];\n  for i = 1:numel (code_start_idx)\n    if (all (cellfun (@(cstr) isempty (char (cstr)),\n                      doc.m_source(code_start_idx(i):code_end_idx(i)))))\n      idx = [idx, i];\n    endif\n  endfor\n  code_start_idx(idx) = [];\n  code_end_idx(idx) = [];\n\n  ## Try to find a document title and introduction text\n  ##   1. First paragraph must start in first line\n  ##   2. Second paragraph must start before any code\n  title_offset = 0;\n  if (is_head (doc.m_source{1})\n      && ! isempty (par_start_idx)\n      && par_start_idx(1) == 1\n      && (isempty (code_start_idx)\n          || (length (par_start_idx) > 1\n              && par_start_idx(2) < code_start_idx(1))))\n    doc.title = doc.m_source{1};\n    doc.title = doc.title(4:end);\n    content = doc.m_source(2:par_end_idx(1));\n    ## Strip leading \"# \"\n    content = cellfun (@(c) cellstr (c(3:end)), content);\n    doc.intro = parse_paragraph_content (content);\n    title_offset = 1;\n  endif\n\n  ## Add non-empty paragraphs and code to doc\n  j = 1;\n  i = (1 + title_offset);\n  while (i <= numel (par_start_idx) || j <= numel (code_start_idx))\n    ## Add code while there is code left\n    ##   and code is before the next paragraph or there are no more paragraphs\n    while (j <= numel (code_start_idx)\n           && (i > numel (par_start_idx)\n               || par_start_idx(i) > code_start_idx(j)))\n      doc.body{end+1}.type = \"code\";\n      lines = [code_start_idx(j), code_end_idx(j)];\n      doc.body{end}.content = ...\n        strtrim (strjoin (doc.m_source(lines(1):lines(2)), \"\\n\"));\n      doc.body{end}.lines = lines;\n      doc.body{end}.output = {};\n      j++;\n    endwhile\n\n    if (i <= numel (par_start_idx))\n      type_str = \"section\";\n      title_str = doc.m_source{par_start_idx(i)};\n      if (is_head (doc.m_source(par_start_idx(i))))\n        title_str = title_str(4:end);\n      else\n        title_str = title_str(5:end);\n      endif\n      ## Append, if paragraph title is given\n      if (! isempty (title_str))\n        doc.body{end+1}.type = type_str;\n        doc.body{end}.content = title_str;\n      endif\n\n      content = doc.m_source(par_start_idx(i) + 1:par_end_idx(i));\n      ## Strip leading \"# \"\n      content = cellfun (@(c) cellstr (c(3:end)), content);\n      doc.body = [doc.body, parse_paragraph_content(content)];\n      i++;\n    endif\n  endwhile\n\nendfunction\n\n\nfunction p_content = parse_paragraph_content (content)\n\n  ## PARSE_PARAGRAPH_CONTENT second parsing level\n  ##\n  ##   Parses the content of a paragraph (without potential title) and\n  ##   returns a cell vector of structs, that can be appended to doc.body,\n  ##   either of\n  ##\n  ##     a) {struct (\"type\", \"preformatted_code\", ...\n  ##                 \"content\", code_str)}\n  ##     b) {struct (\"type\", \"preformatted_text\", ...\n  ##                 \"content\", text_str)}\n  ##     c) {struct (\"type\", \"bulleted_list\", ...\n  ##                 \"content\", {\"item1\", \"item2\", ..})}\n  ##     d) {struct (\"type\", \"numbered_list\", ...\n  ##                 \"content\", {\"item1\", \"item2\", ..})}\n  ##     e) {struct (\"type\", \"include\", ...\n  ##                 \"content\", file_str)}\n  ##     f) {struct (\"type\", \"graphic\", ...\n  ##                 \"content\", file_str)}\n  ##     g) {struct (\"type\", \"html\", ...\n  ##                 \"content\", html_str)}\n  ##     h) {struct (\"type\", \"latex\", ...\n  ##                 \"content\", latex_str)}\n  ##     i) {struct (\"type\", \"text\", ...\n  ##                 \"content\", text_str)}\n  ##\n  ##   Option i) might contain:\n  ##\n  ##     * Italic \"_\", bold \"*\", and monospaced \"|\" text\n  ##     * Inline \"$\" and block \"$$\" LaTeX math\n  ##     * Links\n  ##     * Trademark symbols\n\n  p_content = cell ();\n\n  if (isempty (content))\n    return;\n  endif\n\n  ## Extract <html> and <latex> blocks recursively.\n  content_str = strjoin (content, \"\\n\");\n  tags = {\"html\", \"latex\"};\n  for i = 1:length (tags)\n    tok = regexp (content_str, ...\n      ['(.*?)(^|\\n\\n)(<', tags{i}, '>)\\n(.*?)\\n(<\\/', ...\n        tags{i}, '>)($|\\n\\n)(.*)'], \"tokens\", \"once\");\n    if (! isempty (tok))\n      ## If there was some text before that block --> recursion\n      if (! strcmpi (tok{1}, [\"<\", tags{i}, \">\"]))\n        p_content = parse_paragraph_content (strsplit (tok{1}, \"\\n\"));\n        tok(1:2) = [];\n      endif\n      ## Extract the block content\n      p_content{end+1}.type = tags{i};\n      p_content{end}.content = tok{2};\n      ## If there was some text after that block --> recursion\n      if (length (tok) == 5)\n        p_content = [p_content, ...\n          parse_paragraph_content(strsplit (tok{5}, \"\\n\"))];\n      endif\n      return;\n    endif\n  endfor\n\n  ## Split into blocks separated by empty lines\n  idx = [0, find(cellfun ('isempty', content)), length(content) + 1];\n\n  ## For each block\n  for i = find (diff (idx) > 1)\n    block = content(idx(i) + 1:idx(i+1) - 1);\n\n    ## Octave code (two leading spaces)\n    if (all (cellfun (@(c) strncmp (char (c), \"  \", 2), block)))\n      p_content{end+1}.type = \"preformatted_code\";\n      block = cellfun (@(c) cellstr (c(3:end)), block);\n      p_content{end}.content = strjoin (block, \"\\n\");\n      continue;\n    endif\n\n    ## Preformatted text (one leading space)\n    if (all (cellfun (@(c) strncmp (char (c), \" \", 1), block)))\n      p_content{end+1}.type = \"preformatted_text\";\n      block = cellfun (@(c) cellstr (c(2:end)), block);\n      p_content{end}.content = strjoin (block, \"\\n\");\n      continue;\n    endif\n\n    ## Bulleted list starts with \"* \"\n    if (strncmp (block{1}, \"* \", 2))\n      p_content{end+1}.type = \"bulleted_list\";\n      tmpstr = strjoin (block, \"\\n\");\n      ## Remove first \"* \"\n      tmpstr = tmpstr(3:end);\n      ## Split items\n      p_content{end}.content = strsplit (tmpstr, \"\\n* \");\n      continue;\n    endif\n\n    ## Numbered list starts with \"# \"\n    if (strncmp (block{1}, \"# \", 2))\n      p_content{end+1}.type = \"numbered_list\";\n      tmpstr = strjoin (block, \"\\n\");\n      ## Remove first \"# \"\n      tmpstr = tmpstr(3:end);\n      ## Split items\n      p_content{end}.content = strsplit (tmpstr, \"\\n# \");\n      continue;\n    endif\n\n    ## Include <include>fname.m</include>\n    if (! isempty (fname = regexpi (strjoin (block, \"\"),\n                                    '^<include>(.*)</include>$',\n                                    \"tokens\")))\n      ## Includes result in preformatted code\n      p_content{end+1}.type = \"preformatted_code\";\n      include_code = read_file_to_cellstr (strtrim ((fname{1}){1}));\n      p_content{end}.content = strjoin (include_code, \"\\n\");\n\n      continue;\n    endif\n\n    ## Graphic <<myGraphic.png>>\n    if (! isempty (fname = regexpi (strjoin (block, \"\"),\n                                    '^<<(.*)>>$',\n                                    \"tokens\")))\n      p_content{end+1}.type = \"graphic\";\n      p_content{end}.content = strtrim ((fname{1}){1});\n      continue;\n    endif\n\n    ## Now it can be only normal text or markups belonging to normal text\n    ## that are handled while output generation:\n    ##\n    ## * Italic \"_\", bold \"*\", and monospaced \"|\" text\n    ## * Inline \"$\" and block \"$$\" LaTeX math\n    ## * Links\n    ## * Trademark symbols\n    p_content{end+1}.type = \"text\";\n    p_content{end}.content = strjoin (block, \"\\n\");\n  endfor\n\nendfunction\n\n\nfunction m_source = read_file_to_cellstr (file)\n\n  ## READ_FILE_TO_CELLSTR reads a given file line by line into a cellstring\n  fid = fopen (file, \"r\");\n  i = 0;\n  do\n    m_source{++i} = fgetl (fid);\n  until (! ischar (m_source{i}))\n  fclose (fid);\n  m_source = m_source(1:end-1);  # No EOL\n\nendfunction\n\n\nfunction ofile = create_output (doc, options)\n\n  ## CREATE_OUTPUT creates the desired output file\n  formatter = [];\n  switch (options.format)\n    case \"html\"\n      formatter = @__publish_html_output__;\n    case {\"latex\", \"pdf\"}\n      formatter = @__publish_latex_output__;\n    otherwise\n      ## Custom formatter\n      formatter = eval ([\"@__publish_\", options.format, \"_output__\"]);\n  endswitch\n\n  ## Use title, or if not given, the m-file name\n  title_str = doc.title;\n  if (isempty (title_str))\n    [~, title_str] = fileparts (doc.m_source_file_name);\n  endif\n\n  content = formatter (\"header\",\n                       formatter (\"escape_special_chars\", title_str),\n                       format_output (doc.intro, formatter, options),\n                       get_toc (doc.body, formatter));\n  content = [content, format_output(doc.body, formatter, options)];\n  content = [content, formatter(\"footer\", strjoin (doc.m_source, \"\\n\"))];\n\n  ## Write file\n  [~, ofile] = fileparts (doc.m_source_file_name);\n  ofile_name = [ofile, formatter(\"output_file_extension\")];\n  ofile = fullfile (options.outputDir, ofile_name);\n  fid = fopen (ofile, \"w\");\n  fputs (fid, content);\n  fclose (fid);\n\n  ## Compile LaTeX, if compiler found\n  if (strcmp (options.format, \"pdf\"))\n    status = system (\"pdflatex --version\");\n    if (status == 0)\n      ## FIXME: Why is the same command run twice?\n      for i = 1:2\n        ## Wrap directory in double quotes in case of spaces (bug #67991).\n        system (['cd \"' options.outputDir '\" && pdflatex ' ofile_name]);\n      endfor\n    endif\n  endif\n\nendfunction\n\n\nfunction toc_cstr = get_toc (cstr, formatter)\n\n  ## GET_TOC extracts the table of contents from a cellstring (e.g., doc.body)\n  ## with each section headline as a cell in a returned cellstring.\n  toc_cstr = cell ();\n  for i = 1:numel (cstr)\n    if (strcmp (cstr{i}.type, \"section\"))\n      toc_cstr{end+1} = format_text (cstr{i}.content, formatter);\n    endif\n  endfor\n\nendfunction\n\n\nfunction str = format_output (cstr, formatter, options)\n\n  ## FORMAT_OUTPUT steps through all blocks (doc.intro or doc.body) in cstr and\n  ## produces a single result string with the source code in the desired output\n  ## format.\n  ##\n  ##   formatter has the only knowledge how to enforce the target format\n  ##   and produces for each block the necessary target format source string.\n  str = \"\";\n  for i = 1:numel (cstr)\n    switch (cstr{i}.type)\n      case \"code\"\n        if (options.showCode)\n          str = [str, formatter(\"code\", cstr{i}.content)];\n        endif\n        if ((options.evalCode) && (! isempty (cstr{i}.output)))\n          str = [str, formatter(\"code_output\", cstr{i}.output)];\n        endif\n      case {\"text\", \"section\"}\n        str = [str, formatter(cstr{i}.type, ...\n                              format_text (cstr{i}.content, formatter))];\n      case {\"bulleted_list\", \"numbered_list\"}\n        items = cellfun (@(str) format_text(str, formatter), ...\n                         cstr{i}.content, \"UniformOutput\", false);\n        str = [str, formatter(cstr{i}.type, items)];\n      otherwise\n        str = [str, formatter(cstr{i}.type, cstr{i}.content)];\n    endswitch\n  endfor\n\nendfunction\n\n\nfunction str = format_text (str, formatter)\n\n  ## FORMAT_TEXT formats inline formats in strings.\n  ##   These are: links, block/inline math, bold, italic, monospaced, (TM), (R)\n\n  ## Helper to clarify the following regular expressions.  It is suitable for\n  ## inline formatting, that is delimited literally at start and end by\n  ## 'delim'.  'term' is an indicating character for the end delimiter.\n  ##\n  ## Best explained by example ('^' start and '$' end of input):\n  ##\n  ##  Positive matches:\n  ##\n  ##    ^*bold*$\n  ##    ^*bold*.$\n  ##    ^(*bold*)$\n  ##    ^ *bold* $\n  ##    ^Text *bold* text$\n  ##    ^*bold text*$\n  ##\n  ##  Negative matches:\n  ##\n  ##    ^Text*bold*text$\n  ##    ^*bold *$\n  ##    ^* bold* $\n  ##    ^*bold text *$\n  ##\n  regex_helper = @(delim, term) ['(^|(?<=\\s)|(?=\\W))', delim, ...\n    '(?!\\s)[^', term, ']*(?<!\\s)', delim, '($|(?=\\s)|(?=\\W))'];\n\n  ## Regular expressions for the formats:\n  ##\n  ## 1) Links \"<https://www.someurl.com>\"\n  ## 2) Links \"<octave:Function SOME TEXT>\"\n  ## 3) Links \"<https://www.someurl.com SOME TEXT>\"\n  ## 4) LaTeX block math \"$$x^2$$\"\n  ## 5) LaTeX inline math \"$x^2$\"\n  ## 6) Bold *text*\n  ## 7) Italic _text_\n  ## 8) Monospaced |text|\n  ## 9) (TM) or (R)\n  regexes = {'<\\S{3,}[^\\s<>]*>', ...\n             '<octave:[^\\s<>]* *[^<>$]*>', ...\n             '<\\S{3,}[^\\s<>]* *[^<>$]*>', ...\n             regex_helper('\\$\\$', '$'), ...\n             regex_helper('\\$', '$'), ...\n             regex_helper('\\*', '*'), ...\n             regex_helper('_', '_'), ...\n             regex_helper('\\|', '|'), ...\n             '\\((TM|R)\\)'};\n\n  ## Function to escape some special characters for the GNU Octave manual,\n  ## see https://www.gnu.org/software/texinfo/manual/texinfo/html_node/HTML-Xref-Node-Name-Expansion.html\n  texinfo_esc = @(str) strrep (strrep (str, \"-\", \"_002d\"), \"_\", \"_005f\");\n\n  ## Substitute all occurrences with placeholders\n  placeholder_cstr = {};\n  plh = 0;\n  for i = 1:numel (regexes)\n    cstr = regexp (str, regexes{i}, \"match\");\n    for j = 1:numel (cstr)\n      plh += 1;\n      str = regexprep (str, regexes{i}, [\"PUBLISHPLACEHOLDER\" num2str(plh)],\n                       \"once\");\n      switch (i)\n        case 1\n          ## Links \"<https://www.someurl.com>\"\n          url = cstr{j};\n          cstr{j} = formatter (\"link\", url(2:end-1), url(2:end-1));\n        case 2\n          ## Links \"<octave:Function SOME TEXT>\"\n          idx = strfind (cstr{j}, \" \")(1);\n          url = cstr{j};\n          url = texinfo_esc (url(9:idx-1));\n          v = version ();\n          if (v(end) != '0')  # No official release\n            v = \"latest\";\n          else\n            v = [\"v\" v];  # \"v6.4.0\" etc.\n          endif\n          url = sprintf (\"https://octave.org/doc/%s/XREF%s.html\", v, url);\n          txt = cstr{j};\n          txt = format_text (txt(idx+1:end-1), formatter);\n          cstr{j} = formatter (\"link\", url, txt);\n        case 3\n          ## Links \"<https://www.someurl.com SOME TEXT>\"\n          idx = strfind (cstr{j}, \" \")(1);\n          url = cstr{j};\n          url = url(2:idx-1);\n          txt = cstr{j};\n          txt = format_text (txt(idx+1:end-1), formatter);\n          cstr{j} = formatter (\"link\", url, txt);\n        case 4\n          ## LaTeX block math \"$$\"\n          txt = cstr{j};\n          cstr{j} = formatter (\"blockmath\", txt(3:end-2));\n        case 5\n          ## LaTeX inline math \"$\"\n          txt = cstr{j};\n          cstr{j} = formatter (\"inlinemath\", txt(2:end-1));\n        case 6\n          ## Bold\n          txt = cstr{j};\n          cstr{j} = formatter (\"bold\", format_text (txt(2:end-1), formatter));\n        case 7\n          ## Italic\n          txt = cstr{j};\n          cstr{j} = formatter (\"italic\", format_text (txt(2:end-1), formatter));\n        case 8\n          ## Monospaced\n          txt = cstr{j};\n          cstr{j} = formatter (\"monospaced\", format_text (txt(2:end-1), ...\n                               formatter));\n        case 9\n          ## (TM) or (R)\n          txt = cstr{j};\n          cstr{j} = formatter (txt(2:end-1));\n      endswitch\n    endfor\n    placeholder_cstr = [placeholder_cstr, cstr];\n  endfor\n\n  ## Replace special symbols\n  str = formatter (\"escape_special_chars\", str);\n\n  ## Restore placeholders\n  for i = plh:-1:1\n    str = strrep (str, [\"PUBLISHPLACEHOLDER\" sprintf(\"%d\", i)],\n                       placeholder_cstr{i});\n  endfor\n\nendfunction\n\n\nfunction doc = eval_code (doc, options)\n\n  ## EVAL_CODE Third level parsing\n  ##\n  ##   Generates the output of the script code and takes care of generated\n  ##   figures.\n\n  ## Necessary as the code does not run interactively\n  page_screen_output (false, \"local\");\n\n  ## Remember previously opened figures\n  fig_ids = findall (0, \"type\", \"figure\");\n  [~, fig_name] = fileparts (doc.m_source_file_name);\n  fig_num = 1;\n  fig_list = struct ();\n\n  ## Evaluate code, that does not appear in the output.\n  eval_code_helper (options.codeToEvaluate);\n\n  ## Create a new figure, if there are existing plots\n  if (! isempty (fig_ids) && options.useNewFigure)\n    figure ();\n  endif\n\n  for i = 1:numel (doc.body)\n    if (strcmp (doc.body{i}.type, \"code\"))\n      r = doc.body{i}.lines;\n      code_str = strjoin (doc.m_source(r(1):r(2)), \"\\n\");\n      if (options.catchError)\n        try\n          doc.body{i}.output = eval_code_helper (code_str);\n         catch err\n          doc.body{i}.output = cellstr ([\"error: \", err.message, ...\n                                                 \"\\n\\tin:\\n\\n\", code_str]);\n        end_try_catch\n      else\n        doc.body{i}.output = eval_code_helper (code_str);\n      endif\n\n      ## Check for newly created figures ...\n      fig_ids_new = setdiff (findall (0, \"type\", \"figure\"), fig_ids);\n      ## ... and save them\n      for j = 1:numel (fig_ids_new)\n        drawnow ();\n        if (isempty (get (fig_ids_new(j), \"children\")))\n          continue;\n        endif\n        fname = [fig_name, \"-\", sprintf(\"%d\", fig_num)];\n        if (strncmp (options.imageFormat, \"eps\", 3))\n          fname = [fname \".eps\"];\n        else\n          fname = [fname \".\" options.imageFormat];\n        endif\n        print_opts = {fig_ids_new(j), ...\n                      fullfile(options.outputDir, fname), ...\n                      [\"-d\" options.imageFormat], \"-color\"};\n        if (! isempty (options.maxWidth) && ! isempty (options.maxHeight))\n          print_opts{end+1} = sprintf (\"-S%d,%d\", options.maxWidth,\n                                                  options.maxHeight);\n        elseif (! isempty (options.maxWidth) || ! isempty (options.maxHeight))\n          warning ([\"publish: specify both options.maxWidth \", ...\n                              \"and options.maxHeight\"]);\n        endif\n        print (print_opts{:});\n        fig_num++;\n        delete (fig_ids_new(j));\n        fig_elem = cell ();\n        fig_elem{1} = struct (\"type\", \"graphic\", \"content\", fname);\n        if (isfield (fig_list, num2str (i)))\n          fig_elem = [getfield(fig_list, sprintf (\"%d\", i)), fig_elem];\n        endif\n        fig_list = setfield (fig_list, sprintf (\"%d\", i), fig_elem);\n        ## Create a new figure, if there are existing plots\n        if (isempty (setdiff (findall (0, \"type\", \"figure\"), fig_ids)) ...\n            && ! isempty (fig_ids) && options.useNewFigure)\n          figure ();\n        endif\n      endfor\n\n      ## Truncate output to desired length\n      if (options.maxOutputLines < length (doc.body{i}.output))\n        doc.body{i}.output = doc.body{i}.output(1:options.maxOutputLines);\n      endif\n      doc.body{i}.output = strjoin (doc.body{i}.output, \"\\n\");\n    endif\n  endfor\n\n  ## Close any figures opened by publish function\n  delete (setdiff (findall (0, \"type\", \"figure\"), fig_ids));\n\n  ## Insert figures to document\n  fig_code_blocks = fieldnames (fig_list);\n  body_offset = 0;\n  for i = 1:numel (fig_code_blocks)\n    elems = getfield (fig_list, fig_code_blocks{i});\n    ## Compute index where the figure(s) has to be inserted\n    j = str2double (fig_code_blocks{i}) + body_offset;\n    doc.body = [doc.body(1:j), elems, doc.body(j+1:end)];\n    body_offset = body_offset + numel (elems);\n  endfor\n\nendfunction\n\n\nfunction cstr = eval_code_helper (__code__)\n\n  ## EVAL_CODE_HELPER evaluates a given string with Octave code in an extra\n  ## temporary context and returns a cellstring with the eval output.\n\n  if (isempty (__code__))\n    return;\n  endif\n\n  eval_context (\"load\");\n  cstr = evalc (__code__);\n  ## Split string by lines and preserve blank lines.\n  cstr = strsplit (strrep (cstr, \"\\n\\n\", \"\\n \\n\"), \"\\n\");\n  eval_context (\"save\");\n\nendfunction\n\n\nfunction cstr = eval_context (op)\n\n  ## EVAL_CONTEXT temporary evaluation context.\n  persistent ctext;\n\n  ## Variable cstr in \"eval_code_helper\" is newly created anyways.\n  forbidden_var_names = {\"__code__\"};\n\n  switch (op)\n    case \"save\"\n      ## Clear previous context\n      ctext = containers.Map;\n      ## Get variable names\n      var_names = evalin (\"caller\", \"whos\");\n      var_names = {var_names.name};\n      ## Store all variables to context\n      for i = 1:length (var_names)\n        if (! any (strcmp (var_names{i}, forbidden_var_names)))\n          ctext(var_names{i}) = evalin (\"caller\", var_names{i});\n        endif\n      endfor\n\n    case \"load\"\n      if (! isempty (ctext))\n        keys = ctext.keys ();\n        for i = 1:length (keys)\n          assignin (\"caller\", keys{i}, ctext(keys{i}));\n        endfor\n      endif\n\n    case \"clear\"\n      ## Clear any context\n      ctext = [];\n\n    otherwise\n      ## Do nothing\n\n  endswitch\n\nendfunction\n\n\n## Note: Functional BIST tests are located in the 'test/publish' directory.\n\n## Test input validation\n%!error <Invalid call> publish ()\n%!error publish (1)\n%!error <FILE does not exist> publish (\"%%_non_existent_file_%%.m\")\n%!error <only script files can be published> publish (\"publish.m\")\n%!error publish (\"test_script.m\", \"format\", \"html\", \"showCode\")\n"
  },
  {
    "path": "scripts/miscellaneous/python.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{output} =} python (@var{scriptfile})\n## @deftypefnx {} {@var{output} =} python (@var{scriptfile}, @var{argument1}, @var{argument2}, @dots{})\n## @deftypefnx {} {[@var{output}, @var{status}] =} python (@dots{})\n## Invoke Python script @var{scriptfile}, possibly with a list of command line\n## arguments.\n##\n## Return output in @var{output} and optional status in @var{status}.  If\n## @var{scriptfile} is not an absolute filename it is searched for in the\n## current directory and then in the Octave loadpath.\n##\n## Programming Note: On UNIX systems, the script will be executed by\n## @command{python3} and on Windows by @command{python}.  You can override\n## these defaults by setting the @env{PYTHON} environment variable, for example\n## from within Octave using @code{setenv PYTHON /usr/local/bin/python3}.\n##\n## @seealso{system, perl}\n## @end deftypefn\n\nfunction [output, status] = python (scriptfile, varargin)\n\n  persistent pyexec = get_python_executable ();\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (ischar (scriptfile) && isrow (scriptfile)) || isempty (scriptfile))\n    error (\"python: SCRIPTFILE must be a non-empty string\");\n  endif\n  if (nargin > 1 && ! iscellstr (varargin))\n    error (\"python: ARGUMENTS must be strings\");\n  endif\n\n  if (numel (scriptfile) < 2 || ! strcmp (scriptfile(1:2), \"-c\"))\n    ## Attempt to find file in loadpath.  No effect for absolute filenames.\n    fname = file_in_loadpath (scriptfile);\n  endif\n\n  if (! exist (fname, 'file'))\n    error (\"python: SCRIPTFILE <%s> not found\", scriptfile);\n  endif\n\n  [status, output] = system ([pyexec \" \" fname sprintf(\" %s\", varargin{:})]);\n\nendfunction\n\nfunction pyexec = get_python_executable ()\n\n  pyexec = getenv (\"PYTHON\");\n  if (isempty (pyexec))\n    ## PEP394 says Python 3 installs should all provide this command\n    pyexec = \"python3\";\n\n    if (ispc ())\n      ## 2020-03: Python.org installer/Anaconda do not provide python3\n      pyexec = \"python\";\n    endif\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> python ()\n%!error <SCRIPTFILE must be a non-empty string> python (123)\n%!error <SCRIPTFILE must be a non-empty string> python (['a';'b'])\n%!error <SCRIPTFILE must be a non-empty string> python (\"\")\n%!error <ARGUMENTS must be strings> python (\"pythonfile\", 123)\n%!error <SCRIPTFILE .* not found> python (\"%%_not_a_name.XYZ\")\n"
  },
  {
    "path": "scripts/miscellaneous/recycle.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{val} =} recycle ()\n## @deftypefnx {} {@var{old_val} =} recycle (@var{new_val})\n## Query or set the preference for recycling deleted files.\n##\n## When recycling is enabled, commands which would permanently erase files\n## instead move them to a temporary location (such as the directory labeled\n## Trash).\n##\n## Programming Note: This function is provided for @sc{matlab} compatibility,\n## but recycling is not implemented in Octave.  To help avoid accidental data\n## loss an error will be raised if an attempt is made to enable file recycling.\n## @seealso{delete, rmdir}\n## @end deftypefn\n\nfunction val = recycle (new_val)\n\n  persistent current_state = \"off\";\n\n  if (nargin == 0 || nargout > 0)\n    val = current_state;\n  endif\n\n  if (nargin == 1)\n    if (! ischar (new_val))\n      error (\"recycle: NEW_VAL must be a character string\");\n    endif\n\n    if (strcmpi (new_val, \"on\"))\n      error (\"recycle: recycling files is not implemented\");\n    elseif (strcmpi (new_val, \"off\"))\n      current_state = \"off\";\n    else\n      error (\"recycle: invalid value '%s'\", new_val);\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! recycle (\"off\");\n%! assert (recycle (\"off\"), \"off\");\n\n%!error recycle (\"on\", \"and I mean it\")\n%!error <NEW_VAL must be a character string> recycle (1)\n%!error <recycling files is not implemented> recycle (\"on\")\n%!error <invalid value 'foobar'> recycle (\"foobar\")\n"
  },
  {
    "path": "scripts/miscellaneous/run.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} run @var{script}\n## @deftypefnx {} {} run (\"@var{script}\")\n## Run @var{script} in the current workspace.\n##\n## Scripts which reside in directories specified in Octave's load path, and\n## which end with the extension @file{.m}, can be run simply by typing\n## their name.  For scripts not located on the load path, use @code{run}.\n##\n## The filename @var{script} can be a bare, fully qualified, or relative\n## filename and with or without a file extension.  If no extension is\n## specified, Octave will first search for a script with the @file{.m}\n## extension before falling back to the script name without an extension.\n##\n## Implementation Note: If @var{script} includes a path component, then\n## @code{run} first changes the working directory to the directory where\n## @var{script} is found.  Next, the script is executed.  Finally, @code{run}\n## returns to the original working directory @emph{unless} @var{script} has\n## specifically changed directories.\n## @seealso{path, addpath, source}\n## @end deftypefn\n\nfunction run (script)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  [d, f, ext] = fileparts (script);\n  if (! strcmp (ext, \".m\"))\n    ## prefer files with .m extension for compatibility with Matlab\n    if (exist ([script \".m\"], \"file\"))\n      f = [f ext];\n      ext = \".m\";\n      script = [script \".m\"];\n    endif\n  endif\n\n  if (! exist (script, \"file\"))\n    error (\"run: file SCRIPT must exist and be a valid Octave scriptfile\");\n  endif\n\n  if (! isempty (d))\n    if (! isfolder (d))\n      error (\"run: the path %s doesn't exist\", d);\n    endif\n\n    startdir = pwd ();\n    scriptdir = \"\";\n    unwind_protect\n      cd (d);\n      scriptdir = pwd ();\n      evalin (\"caller\", sprintf (\"source ('%s%s');\", f, ext),\n              \"rethrow (lasterror ())\");\n    unwind_protect_cleanup\n      if (is_same_file (scriptdir, pwd ()))\n        cd (startdir);\n      endif\n    end_unwind_protect\n\n  else\n    if (! isempty (ext))\n      script = which (script);\n    else\n      ## Search PATH with null extension ('.' will be stripped and ext = \"\")\n      script = which ([script \".\"]);\n    endif\n    evalin (\"caller\", sprintf (\"source ('%s');\", script),\n            \"rethrow (lasterror ())\");\n  endif\n\nendfunction\n\n\n## Test script file execution\n## Use a variable name that is unlikely to be the name of a function.\n%!test\n%! clear _5yVNhWVJWJn47RKnzxPsyb_\n%! assert (exist (\"_5yVNhWVJWJn47RKnzxPsyb_\"), 0);\n%! tmp_dir = tempname ();\n%! test_script = fullfile (tmp_dir, \"test_script.m\");\n%! unwind_protect\n%!   mkdir (tmp_dir);\n%!   fid = fopen (test_script, \"w\");\n%!   fprintf (fid, \"_5yVNhWVJWJn47RKnzxPsyb_ = 1337;\\n\");\n%!   fclose (fid);\n%!   run (test_script);\n%!   assert (exist (\"_5yVNhWVJWJn47RKnzxPsyb_\", \"var\"), 1);\n%!   assert (_5yVNhWVJWJn47RKnzxPsyb_, 1337);\n%! unwind_protect_cleanup\n%!   unlink (test_script);\n%!   sts = rmdir (tmp_dir);\n%! end_unwind_protect\n\n## Test function file execution\n%!test\n%! path_orig = path ();\n%! tmp_dir = tempname ();\n%! test_function = fullfile (tmp_dir, \"tf.m\");\n%! unwind_protect\n%!   mkdir (tmp_dir);\n%!   fid = fopen (test_function, \"w\");\n%!   fprintf (fid, \"function tf ()\\n\");\n%!   fprintf (fid, \"  addpath ('%s');\\n\", tmp_dir);\n%!   fprintf (fid, \"endfunction\\n\");\n%!   fclose (fid);\n%!   ## Check if temporary directory is on the loadpath.\n%!   ## Function 'dir_in_loadpath' is broken for this use case, so code a test.\n%!   dirs = strsplit (path (), pathsep ());\n%!   tstval1 = any (is_same_file (tmp_dir, dirs));\n%!   run (test_function);\n%!   dirs = strsplit (path (), pathsep ());\n%!   tstval2 = any (is_same_file (tmp_dir, dirs));\n%!   assert (tstval1, false);\n%!   assert (tstval2, true);\n%! unwind_protect_cleanup\n%!   unlink (test_function);\n%!   sts = rmdir (tmp_dir);\n%!   path (path_orig);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> run ()\n%!error run (\"a\", \"b\")\n%!error <SCRIPT must exist> run (\"__A_very_#unlikely#_file_name__\")\n"
  },
  {
    "path": "scripts/miscellaneous/saveobj.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{b} =} saveobj (@var{a})\n## Method of a class to manipulate an object prior to saving it to a file.\n##\n## The function @code{saveobj} is called when the object @var{a} is saved\n## using the @code{save} function.  An example of the use of @code{saveobj}\n## might be to remove fields of the object that don't make sense to be saved\n## or it might be used to ensure that certain fields of the object are\n## initialized before the object is saved.  For example:\n##\n## @example\n## @group\n## function b = saveobj (a)\n##   b = a;\n##   if (isempty (b.field))\n##      b.field = initfield (b);\n##   endif\n## endfunction\n## @end group\n## @end example\n##\n## @seealso{loadobj, class}\n## @end deftypefn\n\nfunction b = saveobj (a)\n  error ('saveobj: not defined for class \"%s\"', class (a));\nendfunction\n"
  },
  {
    "path": "scripts/miscellaneous/setfield.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{sout} =} setfield (@var{s}, @var{field}, @var{val})\n## @deftypefnx {} {@var{sout} =} setfield (@var{s}, @var{sidx1}, @var{field1}, @var{fidx1}, @var{sidx2}, @var{field2}, @var{fidx2}, @dots{}, @var{val})\n##\n## Return a @emph{copy} of the structure @var{s} with the field member\n## @var{field} set to the value @var{val}.\n##\n## For example:\n##\n## @example\n## @group\n## @var{s} = struct ();\n## @var{s} = setfield (@var{s}, \"foo bar\", 42);\n## @end group\n## @end example\n##\n## @noindent\n## This is equivalent to\n##\n## @example\n## @var{s}.(\"foo bar\") = 42;\n## @end example\n##\n## @noindent\n## Note that ordinary structure syntax @code{@var{s}.foo bar = 42} cannot be\n## used here, as the field name is not a valid Octave identifier because of\n## the space character.  Using arbitrary strings for field names is\n## incompatible with @sc{matlab}, and this usage will emit a warning if the\n## warning ID @code{Octave:language-extension} is enabled.\n## @xref{XREFwarning_ids,,warning_ids}.\n##\n## With the second calling form, set a field of a structure array.  The\n## input @var{sidx} selects an element of the structure array, @var{field}\n## specifies the field name of the selected element, and @var{fidx} selects\n## which element of the field (in the case of an array or cell array).\n## The @var{sidx}, @var{field}, and @var{fidx} inputs can be repeated to\n## address nested structure array elements.  The structure array index and\n## field element index must be cell arrays while the field name must be a\n## string.\n##\n## For example:\n##\n## @example\n## @group\n## @var{s} = struct (\"baz\", 42);\n## setfield (@var{s}, @{1@}, \"foo\", @{1@}, \"bar\", 54)\n## @xresult{}\n##   ans =\n##     scalar structure containing the fields:\n##       baz =  42\n##       foo =\n##         scalar structure containing the fields:\n##           bar =  54\n## @end group\n## @end example\n##\n## The example begins with an ordinary scalar structure to which a nested\n## scalar structure is added.  In all cases, if the structure index @var{sidx}\n## is not specified it defaults to 1 (scalar structure).  Thus, the example\n## above could be written more concisely as\n## @code{setfield (@var{s}, \"foo\", \"bar\", 54)}\n##\n## Finally, an example with nested structure arrays:\n##\n## @example\n## @group\n## @var{sa}.foo = 1;\n## @var{sa} = setfield (@var{sa}, @{2@}, \"bar\", @{3@}, \"baz\", @{1, 4@}, 5);\n## @var{sa}(2).bar(3)\n## @xresult{}\n##   ans =\n##     scalar structure containing the fields:\n##       baz =  0   0   0   5\n## @end group\n## @end example\n##\n## Here @var{sa} is a structure array whose field at elements 1 and 2 is in\n## turn another structure array whose third element is a simple scalar\n## structure.  The terminal scalar structure has a field which contains a\n## matrix value.\n##\n## Note that the same result as in the above example could be achieved by:\n##\n## @example\n## @group\n## @var{sa}.foo = 1;\n## @var{sa}(2).bar(3).baz(1,4) = 5\n## @end group\n## @end example\n## @seealso{getfield, rmfield, orderfields, isfield, fieldnames, isstruct,\n## struct}\n## @end deftypefn\n\nfunction sout = setfield (s, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  subs = varargin(1:end-1);\n  val = varargin{end};\n  flds = cellfun (\"isclass\", subs, \"char\");\n  idxs = cellfun (\"isclass\", subs, \"cell\");\n  if (! all (flds | idxs))\n    error (\"setfield: invalid index\");\n  endif\n\n  typs = ifelse (flds, {\".\"}, {\"()\"});\n  sout = subsasgn (s, struct (\"type\", typs, \"subs\", subs), val);\n\nendfunction\n\n\n%!test\n%! x.a = \"hello\";\n%! x = setfield (x, \"b\", \"world\");\n%! y = struct (\"a\", \"hello\", \"b\", \"world\");\n%! assert (x, y);\n%!test\n%! oo(1,1).f0 = 1;\n%! oo = setfield (oo,{1,2},\"fd\",{3},\"b\", {1,4}, 6);\n%! assert (oo(1,2).fd(3).b(1,4), 6);\n\n## Test input validation\n%!error <Invalid call> setfield ()\n%!error <Invalid call> setfield (1)\n%!error <Invalid call> setfield (1,2)\n%!error <invalid index> setfield (1,2,3)\n"
  },
  {
    "path": "scripts/miscellaneous/substruct.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{s} =} substruct (@var{type}, @var{subs}, @dots{})\n## Create a subscript structure for use with @code{subsref} or @code{subsasgn}.\n##\n## For example:\n##\n## @example\n## @group\n## idx = substruct (\"()\", @{3, \":\"@})\n##   @xresult{} idx =\n##        scalar structure containing the fields:\n##          type = ()\n##          subs =\n##          @{\n##            [1,1] =  3\n##            [1,2] = :\n##          @}\n## x = [1, 2, 3;\n##      4, 5, 6;\n##      7, 8, 9];\n## subsref (x, idx)\n##   @xresult{}   7   8   9\n## @end group\n## @end example\n##\n## Note: The keyword @code{end} cannot be used within @code{subsref} or\n## @code{subsasgn} for indexing assignments.\n## @seealso{subsref, subsasgn}\n## @end deftypefn\n\nfunction s = substruct (varargin)\n\n  if (nargin < 2 || mod (nargin, 2) != 0)\n    print_usage ();\n  endif\n\n  typ = varargin(1:2:nargin);\n  sub = varargin(2:2:nargin);\n  braces = strcmp (typ, \"()\") | strcmp (typ, \"{}\");\n  dots = strcmp (typ, \".\");\n  if (all (braces | dots))\n    cells = cellfun (\"isclass\", sub, \"cell\");\n    chars = cellfun (\"isclass\", sub, \"char\");\n    if (any (braces & ! cells))\n      error (\"substruct: for TYPE == () or {}, SUBS must be a cell array\");\n    elseif (any (dots & ! chars))\n      error (\"substruct: for TYPE == ., SUBS must be a character string\");\n    endif\n  else\n    error ('substruct: TYPE must be one of \"()\", \"{}\", or \"\"');\n  endif\n\n  s = struct (\"type\", typ, \"subs\", sub);\n\nendfunction\n\n\n%!test\n%! x(1,1).type = \"()\";\n%! x(1,2).type = \"{}\";\n%! x(1,3).type = \".\";\n%! x(1,1).subs = {1,2,3};\n%! x(1,2).subs = {\":\"};\n%! x(1,3).subs = \"foo\";\n%! y = substruct (\"()\", {1,2,3}, \"{}\", {\":\"}, \".\", \"foo\");\n%! assert (x,y);\n\n## Test input validation\n%!error <Invalid call> substruct ()\n%!error <Invalid call> substruct (1)\n%!error <Invalid call> substruct (1, 2, 3)\n%!error substruct (\"x\", 1)\n%!error substruct (\"()\", [1,2,3])\n%!error substruct (\".\", {1,2,3})\n"
  },
  {
    "path": "scripts/miscellaneous/swapbytes.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} swapbytes (@var{x})\n## Swap the byte order on values, converting from little endian to big endian\n## and vice versa.\n##\n## For example:\n##\n## @example\n## @group\n## swapbytes (uint16 (1:4))\n## @xresult{}   256   512   768  1024\n## @end group\n## @end example\n##\n## @seealso{typecast, cast}\n## @end deftypefn\n\nfunction y = swapbytes (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  cls = class (x);\n  if (strcmp (cls, \"int8\") || strcmp (cls, \"uint8\") || isempty (x))\n    y = x;\n  else\n    if (strcmp (cls, \"int16\") || strcmp (cls, \"uint16\"))\n      nb = 2;\n    elseif (strcmp (cls, \"single\")\n            || strcmp (cls, \"int32\") || strcmp (cls, \"uint32\"))\n      nb = 4;\n    elseif (strcmp (cls, \"double\")\n            || strcmp (cls, \"int64\") || strcmp (cls, \"uint64\"))\n      nb = 8;\n    else\n      error (\"swapbytes: invalid object of class '%s'\", cls);\n    endif\n    y = reshape (typecast (reshape (typecast (x(:), \"uint8\"), nb, numel (x))\n                           ([nb : -1 : 1], :) (:), cls), size (x));\n  endif\n\nendfunction\n\n\n%!assert (swapbytes (uint16 (1:4)), uint16 ([256 512 768 1024]))\n%!test\n%! assert (swapbytes (swapbytes (pi)), pi);\n%! assert (swapbytes (swapbytes (single (pi))), single (pi));\n\n## Test input validation\n%!error <Invalid call> swapbytes ()\n%!error <invalid object of class 'cell'> swapbytes ({1})\n"
  },
  {
    "path": "scripts/miscellaneous/symvar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{vars} =} symvar (@var{str})\n## Identify the symbolic variable names in the string @var{str}.\n##\n## Common constant names such as @code{i}, @code{j}, @code{pi}, @code{Inf} and\n## Octave functions such as @code{sin} or @code{plot} are ignored.\n##\n## Any names identified are returned in a cell array of strings.  The array is\n## empty if no variables were found.\n##\n## Example:\n##\n## @example\n## @group\n## symvar (\"x^2 + y^2 == 4\")\n## @xresult{} @{\n##      [1,1] = x\n##      [2,1] = y\n##    @}\n## @end group\n## @end example\n## @end deftypefn\n\nfunction vars = symvar (str)\n\n  warning (\"off\", \"Octave:legacy-function\", \"local\");  # using inline below.\n  vars = argnames (inline (str));\n  ## Correct for auto-generated 'x' variable when no symvar was found.\n  if (numel (vars) == 1 && strcmp (vars{1}, \"x\") && ! any (str == \"x\"))\n    vars = {};\n  endif\n\nendfunction\n\n\n%!assert (symvar (\"3*x + 4*y + 5*cos (z)\"), {\"x\"; \"y\"; \"z\"})\n%!assert (symvar (\"sin ()^2 + cos ()^2 == 1\"), {})\n%!assert (symvar (\"1./x\"), {\"x\"})\n"
  },
  {
    "path": "scripts/miscellaneous/tar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{filelist} =} tar (@var{tarfile}, @var{files})\n## @deftypefnx {} {@var{filelist} =} tar (@var{tarfile}, @var{files}, @var{rootdir})\n## Pack the list of files and directories specified in @var{files} into the\n## TAR archive @var{tarfile}.\n##\n## @var{files} is a character array or cell array of strings.  Shell wildcards\n## in the filename such as @samp{*} or @samp{?} are accepted and expanded.\n## Directories are recursively traversed and all files are added to the\n## archive.\n##\n## If @var{rootdir} is defined then any files without absolute pathnames are\n## located relative to @var{rootdir} rather than the current directory.\n##\n## The optional output @var{filelist} is a list of the files that were included\n## in the archive.\n## @seealso{untar, unpack, bzip2, gzip, zip}\n## @end deftypefn\n\nfunction filelist = tar (tarfile, files, rootdir = \".\")\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! ischar (tarfile))\n    error (\"tar: TARFILE must be a string\");\n  elseif (ischar (files))\n    files = cellstr (files);\n  elseif (! iscellstr (files))\n    error (\"tar: FILES must be a character array or cellstr\");\n  endif\n\n  rootdir = tilde_expand (rootdir);\n\n  tarfile = make_absolute_filename (tarfile);\n\n  if (ispc)\n    ## Change tarfile into a MinGW style acceptable for tar\n    tarfile = __w2mpth__ (tarfile);\n  endif\n\n  ## BSD tar emits progress on stderr\n  if (tar_is_bsd ())\n    cmd = sprintf ('tar cvf \"%s\" -C \"%s\" %s 2>&1',\n                            tarfile, rootdir, sprintf (' \"%s\"', files{:}));\n  else\n    cmd = sprintf ('tar cvf \"%s\" -C \"%s\" %s',\n                            tarfile, rootdir, sprintf (' \"%s\"', files{:}));\n  endif\n\n  ## Save and restore the TAR_OPTIONS environment variable used by GNU tar.\n  tar_options_env = getenv (\"TAR_OPTIONS\");\n  unwind_protect\n    unsetenv (\"TAR_OPTIONS\");\n    [status, output] = system (cmd);\n  unwind_protect_cleanup\n    if (! isempty (tar_options_env))\n      setenv (\"TAR_OPTIONS\", tar_options_env);\n    endif\n  end_unwind_protect\n\n  if (status)\n    error (\"tar: tar exited with status = %d\", status);\n  endif\n\n  if (nargout > 0)\n    filelist = ostrsplit (output, \"\\r\\n\", true);\n    filelist = filelist';\n\n    ## BSD tar emits file actions in the first 2 columns\n    if (tar_is_bsd ())\n      filelist = cellfun (@(x) x(3:end), filelist, 'UniformOutput', false);\n    endif\n  endif\n\nendfunction\n\n\n## FIXME: This test may fail if the tar command is not installed.  If this\n##        test fails, it might be better to change it into a testif with a\n##        runtime condition on the tar program.\n%!test\n%! ## test tar together with untar\n%! orig_dir = pwd ();\n%! unwind_protect\n%!   dirname = tarname = outdir = \"\";\n%!   dirname = tempname ();\n%!   assert (mkdir (dirname));\n%!   chdir (dirname);\n%!   dirname2 = \"dir2\";\n%!   assert (mkdir (dirname2));\n%!   fname1 = \"file1\";\n%!   fname2 = fullfile (dirname2, \"file2\");\n%!   fid = fopen (fname1, \"wt\");\n%!   assert (fid >= 0);\n%!   fdisp (fid, \"Hello World\");\n%!   fclose (fid);\n%!   fid = fopen (fname2, \"wt\");\n%!   assert (fid >= 0);\n%!   fdisp (fid, \"Goodbye World\");\n%!   fclose (fid);\n%!   tarname = [tempname() \".tar\"];\n%!   filelist = tar (tarname, {dirname2, fname1});\n%!   if (! strcmp (filelist{3}, fname1))\n%!     error (\"tar file contents does not match expected file\");\n%!   endif\n%!   if (! exist (tarname, \"file\"))\n%!     error (\"tar archive file cannot be found!\");\n%!   endif\n%!   outdir = tempname ();\n%!   untar (tarname, outdir);\n%!   fid = fopen (fullfile (outdir, fname1), \"rt\");\n%!   assert (fid >= 0);\n%!   str = fgetl (fid);\n%!   fclose (fid);\n%!   assert (str, \"Hello World\");\n%!   fid = fopen (fullfile (outdir, fname2), \"rt\");\n%!   assert (fid >= 0);\n%!   str = fgetl (fid);\n%!   fclose (fid);\n%!   assert (str, \"Goodbye World\");\n%! unwind_protect_cleanup\n%!   chdir (orig_dir);\n%!   unlink (tarname);\n%!   confirm_recursive_rmdir (false, \"local\");\n%!   sts = rmdir (dirname, \"s\");\n%!   sts = rmdir (outdir, \"s\");\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> tar ()\n%!error <Invalid call> tar (1)\n%!error <TARFILE must be a string> tar (1, \"foobar\")\n%!error <FILES must be a character array or cellstr> tar (\"foobar\", 1)\n"
  },
  {
    "path": "scripts/miscellaneous/unix.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} unix (\"@var{command}\")\n## @deftypefnx {} {@var{status} =} unix (\"@var{command}\")\n## @deftypefnx {} {[@var{status}, @var{text}] =} unix (\"@var{command}\")\n## @deftypefnx {} {[@dots{}] =} unix (\"@var{command}\", \"-echo\")\n## Execute a system command if running under a Unix-like operating system,\n## otherwise do nothing.\n##\n## Octave waits for the external command to finish before returning the exit\n## status of the program in @var{status} and any output in @var{text}.\n##\n## When called with no output argument, or the @qcode{\"-echo\"} argument is\n## given, then @var{text} is also sent to standard output.\n## @seealso{dos, system, isunix, ismac, ispc}\n## @end deftypefn\n\nfunction [status, text] = unix (command, echo_arg)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  status = 1;\n  text = \"\";\n\n  if (isunix ())\n    [status, text] = system (command);\n    if (nargin > 1 || nargout == 0)\n      printf (\"%s\\n\", text);\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! cmd = ls_command ();\n%! [status, output] = unix (cmd);\n%!\n%! if (isunix ())\n%!   assert (status, 0);\n%!   assert (ischar (output));\n%!   assert (! isempty (output));\n%! else\n%!   assert (status, 1);\n%!   assert (output, \"\");\n%! endif\n\n## Test input validation\n%!error <Invalid call> unix ()\n"
  },
  {
    "path": "scripts/miscellaneous/unpack.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{files} =} unpack (@var{file})\n## @deftypefnx {} {@var{files} =} unpack (@var{file}, @var{dir})\n## @deftypefnx {} {@var{files} =} unpack (@var{file}, @var{dir}, @var{filetype})\n## Unpack the archive @var{file} based on its extension to the directory\n## @var{dir}.\n##\n## If @var{file} is a list of strings, then each file is unpacked\n## individually.  Shell wildcards in the filename such as @samp{*} or\n## @samp{?} are accepted and expanded.\n##\n## If @var{dir} is not specified or is empty (@code{[]}), it defaults to the\n## current directory.  If a directory is in the file list, then @var{filetype}\n## must also be specified.\n##\n## The specific archive filetype is inferred from the extension of the file.\n## The @var{filetype} may also be specified directly using a string which\n## corresponds to a known extension.\n##\n## Valid filetype extensions:\n##\n## @table @code\n## @item  @nospell{bz}\n## @itemx @nospell{bz2}\n## bzip archive\n##\n## @item @nospell{gz}\n## gzip archive\n##\n## @item tar\n## tar archive\n##\n## @item  tarbz\n## @itemx tarbz2\n## @itemx tbz\n## @itemx tbz2\n## tar + bzip archive\n##\n## @item  targz\n## @itemx tgz\n## tar + gzip archive\n##\n## @item z\n## compress archive\n##\n## @item zip\n## zip archive\n## @end table\n##\n## The optional return value is a list of @var{files} unpacked.\n## @seealso{bunzip2, gunzip, unzip, untar, bzip2, gzip, zip, tar}\n## @end deftypefn\n\nfunction filelist = unpack (file, dir = [], filetype = \"\")\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (file) && ! iscellstr (file))\n    error (\"unpack: FILE must be a string or cell array of strings\");\n  endif\n\n  ## Convert char arrays to cell strings to simplify further processing\n  if (ischar (file))\n    file = cellstr (file);\n  endif\n  if (numel (file) == 1)\n    ## FIXME: The code below is not a perfect test for a URL\n    if (isempty (strfind (file{1}, \"://\")))\n      if (ispc ())\n        gfile = __wglob__ (file);\n      else\n        gfile = glob (file);\n      endif\n      if (isempty (gfile))\n        error ('unpack: FILE \"%s\" not found', file{1});\n      else\n        file = gfile;\n      endif\n    endif\n  endif\n\n  ## Recursively unpack cellstr arrays one file at a time\n  if (numel (file) > 1)\n    files = {};\n    for i = 1:numel (file)\n      if (! isempty (dir))\n        tmpfiles = unpack (file{i}, dir);\n      else\n        tmpfiles = unpack (file{i}, fileparts (file{i}));\n      endif\n      files = {files{:} tmpfiles{:}};\n    endfor\n\n    ## Return output if requested.\n    if (nargout > 0)\n      filelist = files;\n    endif\n    return;\n\n  else\n    file = file{1};\n  endif\n\n  if (nargin == 3 && (! ischar (filetype) || ! isrow (filetype)))\n    error (\"unpack: FILETYPE must be a string\");\n  endif\n\n  if (isfolder (file))\n    if (isempty (filetype))\n      error (\"unpack: FILETYPE must be given for a directory\");\n    elseif (! strcmpi (filetype, \"gz\"))\n      error ('unpack: FILETYPE must be \"gz\" for a directory');\n    endif\n    ext = \".gz\";\n  else\n    [pathstr, name, ext] = fileparts (file);\n\n    if (nargin == 3 && ! strcmpi (ext, filetype))\n      ## override extension with given filetype\n      if (isempty (ext))\n        ext = filetype;\n      else\n        ext = regexprep (ext, '(\\.?)\\S*$', ['$1' filetype]);\n      endif\n    endif\n\n    ## Check to see if it's .tar.gz, .tar.Z, etc.\n    if (any (strcmpi ({\".gz\" \".Z\" \".bz2\" \".bz\"}, ext)))\n      [~, tmpname, tmpext] = fileparts (name);\n      if (strcmpi (tmpext, \".tar\"))\n        name = tmpname;\n        ext = [tmpext ext];\n      endif\n    endif\n\n    ## If the file is a URL, download it and then work with that file.\n    if (! isempty (strfind (file, \"://\")))\n      ## FIXME: The above code is not a perfect test for a URL\n      urlfile = file;\n      tmpfile = fullfile (tempdir (), [name ext]);\n      [file, success, msg] = urlwrite (urlfile, tmpfile);\n      if (! success)\n        error ('unpack: could not fetch \"%s\": %s', urlfile, msg);\n      endif\n    endif\n\n  endif\n\n  file = make_absolute_filename (file);\n\n  if (isempty (dir))\n    dir = \".\";\n  else\n    dir = tilde_expand (dir);\n  endif\n\n  ## Instructions on what to do for any extension.\n  ##\n  ## The field names are the file extension without periods.\n  ## The first cell is what is executed to unpack an archive verbosely.\n  ## The second cell is what is executed to unpack an archive quietly.\n  ## The third cell is the function to execute on output to get the files list.\n  ## The fourth cell indicates if the files may need to be manually moved\n  ##   (i.e., tar and unzip decompress into the current directory while\n  ##    bzip2 and gzip decompress the file at its location).\n  persistent commandlist;\n  if (isempty (commandlist))\n    commandlist.gz = {'gzip -d -k -v -f -r \"%s\"', ...\n                      'gzip -d -k -f -r \"%s\"', ...\n                      @__parse_gzip__, true};\n    commandlist.z = commandlist.gz;\n    commandlist.bz2 = {'bzip2 -d -k -v -f \"%s\"', ...\n                       'bzip2 -d -k -f \"%s\"', ...\n                       @__parse_bzip2__, true};\n    commandlist.bz = commandlist.bz2;\n    commandlist.tar = {'tar xvf \"%s\"', ...\n                       'tar xf \"%s\"', ...\n                       @__parse_tar__, false};\n    commandlist.targz = {'gzip -d -c \"%s\" | tar xvf -', ...\n                         'gzip -d -c \"%s\" | tar xf -', ...\n                         @__parse_tar__, false};\n    commandlist.tgz = commandlist.targz;\n    commandlist.tarbz2 = {'bzip2 -d -c \"%s\" | tar xvf -', ...\n                          'bzip2 -d -c \"%s\" | tar xf -', ...\n                          @__parse_tar__, false};\n    commandlist.tarbz = commandlist.tarbz2;\n    commandlist.tbz2 = commandlist.tarbz2;\n    commandlist.tbz = commandlist.tarbz2;\n    commandlist.zip = {'unzip -n \"%s\"', ...\n                       'unzip -nq \"%s\"', ...\n                       @__parse_zip__, false};\n  endif\n\n  ## Unzip doesn't actually care about the extension\n  if (strcmpi (filetype, \"zip\"))\n    nodotext = \"zip\";\n  else\n    nodotext = ext(ext != '.');\n  endif\n\n  if (ispc && strcmp (nodotext, \"tar\"))\n    ## Change file pathname into a MinGW style acceptable for tar\n    file = __w2mpth__ (file);\n  endif\n\n  ## Create the output directory if necessary.\n  s = stat (dir);\n  if (isempty (s))\n    [status, msg] = mkdir (dir);\n    if (! status)\n      error (\"unpack: mkdir failed to create %s: %s\", dir, msg);\n    endif\n  elseif (! S_ISDIR (s.mode))\n    error (\"unpack: %s: not a directory\", dir);\n  endif\n\n  if (isfield (commandlist, lower (nodotext)))\n    [commandv, commandq, parsefcn, move] = deal (commandlist.(nodotext){:});\n    origdir = pwd ();\n    if (move)\n      startdir = fileparts (file);\n    else\n      startdir = origdir;\n    endif\n    cstartdir = make_absolute_filename (startdir);\n    cenddir = make_absolute_filename (dir);\n    if (cenddir(end) == filesep)\n      cenddir(end) = [];\n    endif\n    needmove = move && ! is_same_file (cstartdir, cenddir);\n    if (nargout > 0 || needmove)\n      command = commandv;\n    else\n      command = commandq;\n    endif\n  else\n    warning (\"unpack: unrecognized FILETYPE <%s>\", nodotext);\n    filelist = {};\n    return;\n  endif\n\n  ## Save and restore the TAR_OPTIONS environment variable used by GNU tar.\n  tar_options_env = getenv (\"TAR_OPTIONS\");\n  unwind_protect\n    unsetenv (\"TAR_OPTIONS\");\n    cd (dir);\n    if (ispc ())\n      ## Escape backslashes (necessary for UNC paths).\n      file = strrep (file, '\\', '\\\\');\n    endif\n    [status, output] = system (sprintf ([command \" 2>&1\"], file));\n  unwind_protect_cleanup\n    cd (origdir);\n    if (! isempty (tar_options_env))\n      setenv (\"TAR_OPTIONS\", tar_options_env);\n    endif\n  end_unwind_protect\n\n  if (status)\n    error (\"unpack: unarchiving program exited with status: %d\\n%s\",\n           status, output);\n  endif\n\n  if (nargout > 0 || needmove)\n    ## Trim the last CR or NL if needed.\n    files = parsefcn (ostrsplit (output, \"\\r\\n\", true))';\n\n    ## Move files if necessary.\n    if (needmove)\n      [st, msg] = movefile (files, cenddir);\n      if (! st)\n        error ('unpack: unable to move files to \"%s\": %s', dir, msg);\n      endif\n\n      ## Fix the names of the files since they were moved.\n      files = strrep (files, cstartdir, cenddir);\n    endif\n\n    ## Return output if requested.\n    if (nargout > 0)\n      filelist = files;\n    endif\n  endif\n\nendfunction\n\nfunction files = __parse_zip__ (output)\n  ## Parse the output from zip and unzip.\n\n  ## Skip first line which is Archive header.\n  files = char (output(2:end));\n  ## Trim constant width prefix and return cell array.\n  files = cellstr (files(:,14:end));\n\nendfunction\n\nfunction output = __parse_tar__ (output)\n  ## BSD tar emits file actions in the first 2 columns\n\n  if (tar_is_bsd ())\n    output = cellfun (@(x) x(3:end), output, 'UniformOutput', false);\n  endif\nendfunction\n\nfunction files = __parse_gzip__ (output)\n  ## Parse the output from gzip and gunzip returning the files\n  ## compressed (or decompressed).\n\n  files = regexprep (output, '^.+ -- (?:created|replaced with) (.*)$', '$1');\nendfunction\n\nfunction files = __parse_bzip2__ (output)\n  ## Parse the output from bzip2 and bunzip2 returning the files\n  ## compressed (or decompressed).\n\n  ## Strip leading blanks and .bz2 extension from filename\n  files = regexprep (output, '^\\s+(.*)\\.bz2: .*', '$1');\nendfunction\n\n\n%!testif HAVE_ZLIB\n%! envvar = {\"TMPDIR\", \"TMP\"};\n%! envdir = cellfun (@(x) getenv (x), envvar, \"uniformoutput\", false);\n%! unwind_protect\n%!   cellfun (@(x) unsetenv (x), envvar);\n%!   ## Create temporary directory and file for packing and unpacking\n%!   dirname = tempname ();\n%!   assert (mkdir (dirname));\n%!   filename = tempname ();\n%!   fid = fopen (filename, \"wt\");\n%!   assert (fid >= 0);\n%!   fprintf (fid, \"Hello World\\n\");\n%!   fprintf (fid, \"123 456 789\\n\");\n%!   fclose (fid);\n%!\n%!   unwind_protect\n%!     copyfile (filename, [filename \".orig\"]);\n%!     gzip (filename, dirname);\n%!     [~, f] = fileparts (filename);\n%!     filelist = unpack (fullfile (dirname, [f \".gz\"]), tempdir);\n%!     assert (filelist{1}, filename);\n%!     fid = fopen ([filename \".orig\"], \"rb\");\n%!     assert (fid >= 0);\n%!     orig_data = fread (fid);\n%!     fclose (fid);\n%!     fid = fopen (filename, \"rb\");\n%!     assert (fid >= 0);\n%!     new_data = fread (fid);\n%!     fclose (fid);\n%!     if (orig_data != new_data)\n%!       error (\"unpack: Unpacked file does not equal original\");\n%!     endif\n%!   unwind_protect_cleanup\n%!     unlink (filename);\n%!     unlink ([filename \".orig\"]);\n%!     confirm_recursive_rmdir (false, \"local\");\n%!     sts = rmdir (dirname, \"s\");\n%!   end_unwind_protect\n%! unwind_protect_cleanup\n%!   ## Restore environment variables TMPDIR, TMP\n%!   for i = 1:numel (envvar)\n%!     if (isempty (envdir{i}))\n%!       unsetenv (envvar{i});\n%!     else\n%!       setenv (envvar{i}, envdir{i});\n%!     endif\n%!   endfor\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> unpack ()\n%!error <FILE must be a string or cell array of strings> unpack (1)\n%!error <FILE \"_%NOT_A_FILENAME%_\" not found> unpack (\"_%NOT_A_FILENAME%_\")\n%!error <FILE \"_%NOT_A_FILENAME%_\" not found> unpack ({\"_%NOT_A_FILENAME%_\"})\n%!error <FILE \"_%NOT_A_FILENAME%_\" not found> unpack ({\"_%NOT_A_FILENAME%_\", \"2nd_filename\"})\n%!error <FILETYPE must be a string>\n%! if (isunix)\n%!   unpack (\"/\", [], 1)\n%! else\n%!   unpack ('C:\\', [], 1)\n%! endif\n%!error <FILETYPE must be given for a directory>\n%! if (isunix)\n%!   unpack (\"/\");\n%! else\n%!   unpack ('C:\\');\n%! endif\n%!error <FILETYPE must be \"gz\" for a directory>\n%! if (isunix)\n%!   unpack (\"/\", [], \"foobar\");\n%! else\n%!   unpack ('C:\\', [], \"foobar\");\n%! endif\n"
  },
  {
    "path": "scripts/miscellaneous/untar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} untar (@var{tarfile})\n## @deftypefnx {} {} untar (@var{tarfile}, @var{dir})\n## @deftypefnx {} {@var{filelist} =} untar (@dots{})\n## Unpack the TAR archive @var{tarfile}.\n##\n## If @var{dir} is specified the files are unpacked in this directory rather\n## than the current directory.\n##\n## The optional output @var{filelist} is a list of the uncompressed files.\n## @seealso{tar, unpack, bunzip2, gunzip, unzip}\n## @end deftypefn\n\nfunction filelist = untar (tarfile, dir = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    filelist = unpack (tarfile, dir, \"tar\");\n  else\n    unpack (tarfile, dir, \"tar\");\n  endif\n\nendfunction\n\n\n## Tests for this m-file are located in tar.m\n## Remove from test statistics\n%!assert (1)\n"
  },
  {
    "path": "scripts/miscellaneous/unzip.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} unzip (@var{zipfile})\n## @deftypefnx {} {} unzip (@var{zipfile}, @var{dir})\n## @deftypefnx {} {@var{filelist} =} unzip (@dots{})\n## Unpack the ZIP archive @var{zipfile}.\n##\n## If @var{dir} is specified the files are unpacked in this directory rather\n## than the current directory.\n##\n## The optional output @var{filelist} is a list of the uncompressed files.\n## @seealso{zip, unpack, bunzip2, gunzip, untar}\n## @end deftypefn\n\nfunction filelist = unzip (zipfile, dir = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    filelist = unpack (zipfile, dir, \"zip\");\n  else\n    unpack (zipfile, dir, \"zip\");\n  endif\n\nendfunction\n\n\n## Tests for this m-file are located in zip.m\n## Remove from test statistics\n%!assert (1)\n"
  },
  {
    "path": "scripts/miscellaneous/validateattributes.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} validateattributes (@var{A}, @var{classes}, @var{attributes})\n## @deftypefnx {} {} validateattributes (@var{A}, @var{classes}, @var{attributes}, @var{arg_idx})\n## @deftypefnx {} {} validateattributes (@var{A}, @var{classes}, @var{attributes}, @var{func_name})\n## @deftypefnx {} {} validateattributes (@var{A}, @var{classes}, @var{attributes}, @var{func_name}, @var{arg_name})\n## @deftypefnx {} {} validateattributes (@var{A}, @var{classes}, @var{attributes}, @var{func_name}, @var{arg_name}, @var{arg_idx})\n## Check validity of input argument.\n##\n## Confirms that the argument @var{A} is valid by belonging to one of\n## @var{classes}, and holding all of the @var{attributes}.  If it does not,\n## an error is thrown, with a message formatted accordingly.  The error\n## message can be made further complete by the function name @var{fun_name},\n## the argument name @var{arg_name}, and its position in the input\n## @var{arg_idx}.\n##\n## @var{classes} must be a cell array of strings (an empty cell array is\n## allowed) with the name of classes (remember that a class name is case\n## sensitive).  In addition to the class name, the following categories\n## names are also valid:\n##\n## @table @asis\n## @item @qcode{\"float\"}\n## Floating point value comprising classes @qcode{\"double\"} and\n## @qcode{\"single\"}.\n##\n## @item @qcode{\"integer\"}\n## Integer value comprising classes (u)int8, (u)int16, (u)int32, (u)int64.\n##\n## @item @qcode{\"numeric\"}\n## Numeric value comprising either a floating point or integer value.\n##\n## @end table\n##\n## @var{attributes} must be a cell array with names of checks for @var{A}.\n## Some of them require an additional value to be supplied right after the\n## name (see details for each below).\n##\n## @table @asis\n## @item @qcode{\"<=\"}\n## All values are less than or equal to the following value in\n## @var{attributes}.\n##\n## @item @qcode{\"<\"}\n## All values are less than the following value in @var{attributes}.\n##\n## @item @qcode{\">=\"}\n## All values are greater than or equal to the following value in\n## @var{attributes}.\n##\n## @item @qcode{\">\"}\n## All values are greater than the following value in @var{attributes}.\n##\n## @item @qcode{\"2d\"}\n## A 2-dimensional matrix.  Note that vectors and empty matrices have\n## 2 dimensions, one of them being of length 1, or both length 0.\n##\n## @item @qcode{\"3d\"}\n## Has no more than 3 dimensions.  A 2-dimensional matrix is a 3-D matrix\n## whose 3rd dimension is of length 1.\n##\n## @item @qcode{\"binary\"}\n## All values are either 1 or 0.\n##\n## @item @qcode{\"column\"}\n## Values are arranged in a single column.\n##\n## @item @qcode{\"decreasing\"}\n## No value is @var{NaN}, and each is less than the preceding one.\n##\n## @item @qcode{\"diag\"}\n## Value is a diagonal matrix.\n##\n## @item @qcode{\"even\"}\n## All values are even numbers.\n##\n## @item @qcode{\"finite\"}\n## All values are finite.\n##\n## @item @qcode{\"increasing\"}\n## No value is @var{NaN}, and each is greater than the preceding one.\n##\n## @item @qcode{\"integer\"}\n## All values are integer.  This is different than using @code{isinteger}\n## which only checks its an integer type.  This checks that each value in\n## @var{A} is an integer value, i.e., it has no decimal part.\n##\n## @item @qcode{\"ncols\"}\n## Has exactly as many columns as the next value in @var{attributes}.\n##\n## @item @qcode{\"ndims\"}\n## Has exactly as many dimensions as the next value in @var{attributes}.\n##\n## @item @qcode{\"nondecreasing\"}\n## No value is @var{NaN}, and each is greater than or equal to the preceding\n## one.\n##\n## @item @qcode{\"nonempty\"}\n## It is not empty.\n##\n## @item @qcode{\"nonincreasing\"}\n## No value is @var{NaN}, and each is less than or equal to the preceding one.\n##\n## @item @qcode{\"nonnan\"}\n## No value is a @code{NaN}.\n##\n## @item @nospell{@qcode{\"nonnegative\"}}\n## All values are non negative.\n##\n## @item @qcode{\"nonsparse\"}\n## It is not a sparse matrix.\n##\n## @item @qcode{\"nonzero\"}\n## No value is zero.\n##\n## @item @qcode{\"nrows\"}\n## Has exactly as many rows as the next value in @var{attributes}.\n##\n## @item @qcode{\"numel\"}\n## Has exactly as many elements as the next value in @var{attributes}.\n##\n## @item @qcode{\"odd\"}\n## All values are odd numbers.\n##\n## @item @qcode{\"positive\"}\n## All values are positive.\n##\n## @item @qcode{\"real\"}\n## It is a non-complex matrix.\n##\n## @item @qcode{\"row\"}\n## Values are arranged in a single row.\n##\n## @item @qcode{\"scalar\"}\n## It is a scalar.\n##\n## @item @qcode{\"size\"}\n## Its size has length equal to the values of the next in @var{attributes}.\n## The next value must is an array with the length for each dimension.  To\n## ignore the check for a certain dimension, the value of @code{NaN} can be\n## used.\n##\n## @item @qcode{\"square\"}\n## Is a square matrix.\n##\n## @item @qcode{\"vector\"}\n## Values are arranged in a single vector (column or vector).\n##\n## @end table\n##\n## @seealso{isa, validatestring, inputParser}\n## @end deftypefn\n\nfunction validateattributes (A, cls, attr, varargin)\n\n  if (nargin < 3 || nargin > 6)\n    print_usage ();\n  elseif (! iscellstr (cls))\n    error (\"Octave:invalid-type\",\n           \"validateattributes: CLASSES must be a cell array of strings\");\n  elseif (! iscell (attr))\n    error (\"Octave:invalid-type\",\n           \"validateattributes: ATTRIBUTES must be a cell array\");\n  endif\n\n  ## Built start of error message from the extra optional arguments\n  func_name = \"\";\n  var_name  = \"input\";\n  if (nargin > 3)\n    fourth = varargin{1};\n    if (ischar (fourth))\n      func_name = [fourth \": \"];\n    elseif (nargin == 4 && valid_arg_idx (fourth))\n      var_name = sprintf (\"input %d\", fourth);\n    else\n      error (\"Octave:invalid-input-arg\",\n             \"validateattributes: 4th input argument must be ARG_IDX or FUNC_NAME\");\n    endif\n\n    if (nargin > 4)\n      var_name = varargin{2};\n      if (! ischar (var_name))\n        error (\"Octave:invalid-type\",\n               \"validateattributes: VAR_NAME must be a string\");\n      endif\n\n      if (nargin > 5)\n        arg_idx = varargin{3};\n        if (! valid_arg_idx (arg_idx))\n          error (\"Octave:invalid-input-arg\",\n                 \"validateattributes: ARG_IDX must be a positive integer\");\n        endif\n        var_name = sprintf (\"%s (argument #%i)\", var_name, arg_idx);\n      endif\n    endif\n  endif\n  err_ini = [func_name var_name];\n\n  check_cl = isa (A, cls);\n  if (! isempty (check_cl) && ! any (check_cl))\n    ## Allowing for an empty list of classes is Matlab incompatible but\n    ## that should count as a just a Matlab bug, not an incompatibility.\n\n    ## Replace the category names with the classes that belong to it.\n    integer = { \"int8\"  \"int16\"  \"int32\"  \"int64\" ...\n               \"uint8\" \"uint16\" \"uint32\" \"uint64\"};\n    float   = {\"single\" \"double\"};\n    numeric = {integer{:} float{:}};\n    cls = replace_cl_group (cls, \"integer\", integer);\n    cls = replace_cl_group (cls, \"float\",   float  );\n    cls = replace_cl_group (cls, \"numeric\", numeric);\n    cls = unique (cls);\n\n    classes = sprintf (\" %s\", cls{:});\n    error (\"Octave:invalid-type\",\n           \"%s must be of class:\\n\\n %s\\n\\nbut was of class %s\",\n           err_ini, classes, class (A));\n  endif\n\n  ## We use a while loop because some attributes require the following value\n  ## in the cell array.  Also, we can't just get the boolean value for the\n  ## test and check at the end the error message since some of the tests\n  ## require some more complex error message.\n\n  ## It may look like that we don't perform enough input check in this\n  ## function (e.g., we don't check if there's a value after the size\n  ## attribute).  The reasoning is that this will be a function mostly used\n  ## by developers with fairly static input so any problem would be caught\n  ## immediately during that function development, it's no dependent on the\n  ## final user input.  In addition, it can be called so many times at the\n  ## start of every function, we want it to run specially fast.\n  idx = 1;\n  problem = false; # becomes true when one of the tests fails\n  while (idx <= numel (attr))\n    ## FIXME: once we use this in Octave core, it might be worthy to find\n    ## which attributes are checked more often, and place them in that\n    ## order inside the switch block.\n    switch (lower (attr{idx++}))\n      case \"2d\",\n        problem = ndims (A) != 2;\n        err_id = \"Octave:expected-2d\";\n      case \"3d\",\n        problem = ndims (A) > 3;\n        err_id = \"Octave:expected-3d\";\n      case \"column\",\n        problem = ! iscolumn (A);\n        err_id = \"Octave:expected-column\";\n      case \"row\",\n        problem = ! isrow (A);\n        err_id = \"Octave:expected-row\";\n      case \"scalar\",\n        problem = ! isscalar (A);\n        err_id = \"Octave:expected-scalar\";\n      case \"vector\",\n        problem = ! isvector (A);\n        err_id = \"Octave:expected-vector\";\n      case \"square\",\n        problem = ! issquare (A);\n        err_id = \"Octave:expected-square\";\n      case \"diag\",\n        problem = ! isdiag (A);\n        err_id = \"Octave:expected-diag\";\n      case \"nonempty\",\n        problem = isempty (A);\n        err_id = \"Octave:expected-nonempty\";\n      case \"nonsparse\",\n        problem = issparse (A);\n        err_id = \"Octave:expected-nonsparse\";\n      case \"binary\",\n        problem = ! islogical (A) && ...\n                  any ((A(:) != 1) & (A(:) != 0));\n        err_id = \"Octave:expected-binary\";\n      case \"even\",\n        problem = any (rem (A(:), 2) != 0);\n        err_id = \"Octave:expected-even\";\n      case \"odd\",\n        problem = any (mod (A(:), 2) != 1);\n        err_id = \"Octave:expected-odd\";\n      case \"integer\",\n        problem = ! isinteger (A) && ...\n                  any (ceil (A(:)) != A(:));\n        err_id = \"Octave:expected-integer\";\n      case \"real\",\n        problem = ! isreal (A);\n        err_id = \"Octave:expected-real\";\n      case \"finite\",\n        problem = ! isinteger (A) && ...\n                  ! all (isfinite (A(:)));\n        err_id = \"Octave:expected-finite\";\n      case \"nonnan\",\n        problem = ! isinteger (A) && ...\n                  any (isnan (A(:)));\n        err_id = \"Octave:expected-nonnan\";\n      case \"nonnegative\",\n        problem = any (A(:) < 0);\n        err_id = \"Octave:expected-nonnegative\";\n      case \"nonzero\",\n        problem = any (A(:) == 0);\n        err_id = \"Octave:expected-nonzero\";\n      case \"positive\",\n        problem = any (A(:) <= 0);\n        err_id = \"Octave:expected-positive\";\n      case \"decreasing\",\n        problem = (any (isnan (A(:)))\n                   || any (diff (A(:)) >= 0));\n        err_id = \"Octave:expected-decreasing\";\n      case \"increasing\",\n        problem = (any (isnan (A(:)))\n                   || any (diff (A(:)) <= 0));\n        err_id = \"Octave:expected-increasing\";\n      case \"nondecreasing\",\n        problem = (any (isnan (A(:)))\n                   || any (diff (A(:)) <  0));\n        err_id = \"Octave:expected-nondecreasing\";\n      case \"nonincreasing\",\n        problem = (any (isnan (A(:)))\n                   || any (diff (A(:)) >  0));\n        err_id = \"Octave:expected-nonincreasing\";\n      case \"size\",\n        A_size = size (A);\n        w_size = attr{idx++};\n        A_size(isnan (w_size)) = NaN;\n        if (! isequaln (A_size, w_size))\n          A_size_str = sprintf (\"%dx\", size (A))(1:end-1);\n          w_size_str = sprintf (\"%ix\", w_size)(1:end-1);\n          w_size_str = strrep (w_size_str, \"NaN\", \"N\");\n          err_id = \"Octave:incorrect-size\";\n          error (err_id,\n                 \"%s must be of size %s but was %s\",\n                 err_ini, w_size_str, A_size_str);\n        endif\n      case \"numel\",\n        if (numel (A) != attr{idx++})\n          err_id = \"Octave:incorrect-numel\";\n          error (err_id,\n                 \"%s must have %d elements\", err_ini, attr{idx-1});\n        endif\n      case \"ncols\",\n        if (columns (A) != attr{idx++})\n          err_id = \"Octave:incorrect-numcols\";\n          error (err_id,\n                 \"%s must have %d columns\", err_ini, attr{idx-1});\n        endif\n      case \"nrows\",\n        if (rows (A) != attr{idx++})\n          err_id = \"Octave:incorrect-numrows\";\n          error (err_id,\n                 \"%s must have %d rows\", err_ini, attr{idx-1});\n        endif\n      case \"ndims\",\n        ## Note that a [4 5 1] matrix is not considered to have ndims == 3\n        ## but is ok for \"3d\".  This is not a bug.\n        if (ndims (A) != attr{idx++})\n          err_id = \"Octave:incorrect-numdims\";\n          error (err_id,\n                 \"%s must have %d dimensions\", err_ini, attr{idx-1});\n        endif\n      case \">\"\n        if (! all (A(:) > attr{idx++}))\n          err_id = \"Octave:expected-greater\";\n          error (err_id,\n                 \"%s must be greater than %f\", err_ini, attr{idx-1});\n        endif\n      case \">=\"\n        if (! all (A(:) >= attr{idx++}))\n          err_id = \"Octave:expected-greater-equal\";\n          error (err_id,\n                 \"%s must be greater than or equal to %f\", err_ini, attr{idx-1});\n        endif\n      case \"<\"\n        if (! all (A(:) < attr{idx++}))\n          err_id = \"Octave:expected-less\";\n          error (err_id,\n                 \"%s must be less than %f\", err_ini, attr{idx-1});\n        endif\n      case \"<=\"\n        if (! all (A(:) <= attr{idx++}))\n          err_id = \"Octave:expected-less-equal\";\n          error (err_id,\n                 \"%s must be less than or equal to %f\", err_ini, attr{idx-1});\n        endif\n      otherwise\n        err_id = \"Octave:invalid-input-arg\";\n        error (err_id,\n               \"validateattributes: unknown ATTRIBUTE %s\", attr{idx-1});\n    endswitch\n    if (problem)\n      error (err_id,\n             \"%s must be %s\", err_ini, attr{idx-1});\n    endif\n  endwhile\n\nendfunction\n\nfunction retval = valid_arg_idx (arg)\n  retval = isnumeric (arg) && isscalar (arg) && arg > 0 && arg == fix (arg);\nendfunction\n\nfunction cls = replace_cl_group (cls, name, group)\n  num_pos = strcmpi (cls, name);\n  if (any (num_pos))\n    cls(num_pos) = [];\n    cls(end+1:end+numel (group)) = group;\n  endif\nendfunction\n\n\n%!error <double> validateattributes (rand (5), {\"uint8\"}, {})\n%!error <single> validateattributes (uint8 (rand (5)), {\"float\"}, {})\n%!error <2d> validateattributes (rand (5, 5, 5), {}, {\"2d\"})\n%!error <3d> validateattributes (rand (5, 5, 5, 7), {}, {\"3d\"})\n%!error <column> validateattributes (rand (5, 5), {}, {\"column\"})\n%!error <column> validateattributes (rand (1, 5), {}, {\"column\"})\n%!error <row> validateattributes (rand (5, 5), {}, {\"row\"})\n%!error <row> validateattributes (rand (5, 1), {}, {\"row\"})\n%!error <scalar> validateattributes (rand (1, 5), {}, {\"scalar\"})\n%!error <vector> validateattributes (rand (5), {}, {\"vector\"})\n%!error <square> validateattributes (rand (5, 6), {}, {\"square\"})\n%!error <nonempty> validateattributes ([], {}, {\"nonempty\"})\n%!error <nonsparse> validateattributes (sparse(rand(5)), {}, {\"nonsparse\"})\n%!error <binary> validateattributes (\"text\", {}, {\"binary\"})\n%!error <binary> validateattributes ([0 1 0 3 0], {}, {\"binary\"})\n%!error <even> validateattributes ([2 3 6 8], {}, {\"even\"})\n%!error <even> validateattributes ([2 NaN], {}, {\"even\"})\n%!error <odd> validateattributes ([3 4 7 5], {}, {\"odd\"})\n%!error <odd> validateattributes ([5 NaN], {}, {\"odd\"})\n%!error <integer> validateattributes ([5 5.2 5.7], {}, {\"integer\"})\n%!error <real> validateattributes ([5i 8 9], {}, {\"real\"})\n%!error <finite> validateattributes ([5i Inf 8], {}, {\"finite\"})\n%!error <nonnan> validateattributes ([NaN Inf 8], {}, {\"nonnan\"})\n%!error <nonnegative> validateattributes ([7 8 -9], {}, {\"nonnegative\"})\n%!error <nonzero> validateattributes ([7 8 0], {}, {\"nonzero\"})\n%!error <positive> validateattributes ([7 0 8], {}, {\"positive\"})\n%!error <decreasing> validateattributes ([7 8 4 3 -5], {}, {\"decreasing\"})\n%!error <decreasing> validateattributes ([7 NaN 4 3 -5], {}, {\"decreasing\"})\n%!error <increasing> validateattributes ([7 8 4 9 20], {}, {\"increasing\"})\n%!error <increasing> validateattributes ([7 8 NaN 9 20], {}, {\"increasing\"})\n%!error <nonincreasing> validateattributes ([7 8 4 9 20], {}, {\"nonincreasing\"})\n%!error <nonincreasing> validateattributes ([7 8 NaN 9 20], {}, {\"nonincreasing\"})\n%!error <nondecreasing> validateattributes ([7 8 4 3 -5], {}, {\"nondecreasing\"})\n%!error <nondecreasing> validateattributes ([7 NaN 4 3 -5], {}, {\"nondecreasing\"})\n%!error <size> validateattributes (ones (5, 3, 6), {}, {\"size\", [5 4 7]})\n%!error <size> validateattributes (ones (5, 3, 6), {}, {\"size\", [5 NaN 7]})\n%!error <size> validateattributes (ones (5, 3, 6), {}, {\"size\", [5 3 6 2]})\n%!error <elements> validateattributes (ones (6, 3), {}, {\"numel\", 12})\n%!error <columns> validateattributes (ones (6, 2), {}, {\"ncols\", 3})\n%!error <rows> validateattributes (ones (6, 2), {}, {\"nrows\", 3})\n%!error <dimensions> validateattributes (ones (6, 2, 6, 3), {}, {\"ndims\", 3})\n%!error <greater than> validateattributes ([6 7 8 5], {}, {\">\", 5})\n%!error <greater than> validateattributes ([6 7 8 5], {}, {\">=\", 6})\n%!error <less than> validateattributes ([6 7 8 5], {}, {\"<\", 8})\n%!error <less than> validateattributes ([6 7 8 5], {}, {\"<=\", 7})\n%!error <diag> validateattributes ([0 0 0; 0 0 0; 1 0 0], {}, {\"diag\"})\n%!error <diag> validateattributes (repmat (eye (3), [1 1 3]), {}, {\"diag\"})\n\n%!test\n%! validateattributes (rand (5), {\"numeric\"}, {});\n%! validateattributes (rand (5), {\"float\"}, {});\n%! validateattributes (rand (5), {\"double\"}, {});\n%! validateattributes (\"text\", {\"char\"}, {});\n%! validateattributes (rand (5), {}, {\"2d\"});\n%! validateattributes (rand (5), {}, {\"3d\"});\n%! validateattributes (rand (5, 5, 5), {}, {\"3d\"});\n%! validateattributes (rand (5, 1), {}, {\"column\"});\n%! validateattributes (rand (1, 5), {}, {\"row\"});\n%! validateattributes (\"a\", {}, {\"scalar\"});\n%! validateattributes (5, {}, {\"scalar\"});\n%! validateattributes (rand (1, 5), {}, {\"vector\"});\n%! validateattributes (rand (5, 1), {}, {\"vector\"});\n%! validateattributes (rand (5), {}, {\"square\"});\n%! validateattributes (rand (5), {}, {\"nonempty\"});\n%! validateattributes (rand (5), {}, {\"nonsparse\"});\n%! validateattributes ([0 1 0 1 0], {}, {\"binary\"});\n%! validateattributes (rand (5) > 0.5, {}, {\"binary\"});\n%! validateattributes ([8 4 0 6], {}, {\"even\"});\n%! validateattributes ([-1 3 5], {}, {\"odd\"});\n%! validateattributes ([8 4 0 6], {}, {\"real\"});\n%! validateattributes ([8 4i 0 6], {}, {\"finite\"});\n%! validateattributes (uint8 ([8 4]), {}, {\"finite\"});\n%! validateattributes ([8 Inf], {}, {\"nonnan\"});\n%! validateattributes ([0 7 4], {}, {\"nonnegative\"});\n%! validateattributes ([-8 7 4], {}, {\"nonzero\"});\n%! validateattributes ([8 7 4], {}, {\"positive\"});\n%! validateattributes ([8 7 4 -5], {}, {\"decreasing\"});\n%! validateattributes ([-8 -7 4 5], {}, {\"increasing\"});\n%! validateattributes ([8 4 4 -5], {}, {\"nonincreasing\"});\n%! validateattributes ([-8 -8 4 5], {}, {\"nondecreasing\"});\n%! validateattributes (rand (4, 6, 7, 2), {}, {\"size\", [4 6 7 2]});\n%! validateattributes (rand (4, 6, 7, 2), {}, {\"size\", [4 NaN 7 2]});\n%! validateattributes (rand (4, 6, 7, 2), {}, {\"size\", [4 6 NaN 2 NaN]});\n%! validateattributes (rand (6, 2), {}, {\"numel\", 12});\n%! validateattributes (rand (6, 2), {}, {\"ncols\", 2});\n%! validateattributes (rand (6, 2), {}, {\"nrows\", 6});\n%! validateattributes (rand (6, 2, 4, 5), {}, {\"ndims\", 4});\n%! validateattributes ([4 5 6 7], {}, {\">\", 3});\n%! validateattributes ([4 5 6 7], {}, {\">=\", 4});\n%! validateattributes ([4 5 6 7], {}, {\"<\", 8});\n%! validateattributes ([4 5 6 7], {}, {\"<=\", 7});\n%! validateattributes (eye (3), {}, {\"diag\"});\n%! validateattributes ([1 0 0; 0 1 0; 0 0 1], {}, {\"diag\"});\n%! validateattributes (zeros (3), {}, {\"diag\"});\n\n%!test\n%! validateattributes ([0 1 0 1], {\"double\", \"uint8\"}, {\"binary\", \"size\", [NaN 4], \"nonnan\"});\n\n%!test\n%! try validateattributes (ones(1,2,3), {\"numeric\"}, {\"2d\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-2d\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (ones(1,2,3,4), {\"numeric\"}, {\"3d\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-3d\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([1 2], {\"numeric\"}, {\"column\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-column\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([1 2].', {\"numeric\"}, {\"row\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-row\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([1 2], {\"numeric\"}, {\"scalar\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-scalar\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (ones(3), {\"numeric\"}, {\"vector\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-vector\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([1 2], {\"numeric\"}, {\"size\", [1 1]});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:incorrect-size\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1, {\"numeric\"}, {\"numel\", 7});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:incorrect-numel\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1, {\"numeric\"}, {\"ncols\", 7});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:incorrect-numcols\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1, {\"numeric\"}, {\"nrows\", 7});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:incorrect-numrows\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1, {\"numeric\"}, {\"ndims\", 5});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:incorrect-numdims\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([1 2], {\"numeric\"}, {\"square\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-square\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([1 2], {\"numeric\"}, {\"diag\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-diag\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([], {\"numeric\"}, {\"nonempty\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-nonempty\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (speye(2), {\"numeric\"}, {\"nonsparse\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-nonsparse\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1, {\"numeric\"}, {\">\", 3});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-greater\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1, {\"numeric\"}, {\">=\", 3});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-greater-equal\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1, {\"numeric\"}, {\"<\", -3});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-less\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1, {\"numeric\"}, {\"<=\", -3});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-less-equal\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (3, {\"numeric\"}, {\"binary\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-binary\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1, {\"numeric\"}, {\"even\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-even\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (2, {\"numeric\"}, {\"odd\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-odd\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1.1, {\"numeric\"}, {\"integer\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-integer\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (1+1i*2, {\"numeric\"}, {\"real\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-real\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (Inf, {\"numeric\"}, {\"finite\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-finite\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (NaN, {\"numeric\"}, {\"nonnan\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-nonnan\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (-1, {\"numeric\"}, {\"nonnegative\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-nonnegative\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (0, {\"numeric\"}, {\"nonzero\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-nonzero\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (-1, {\"numeric\"}, {\"positive\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-positive\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([1 2], {\"numeric\"}, {\"decreasing\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-decreasing\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([2 1], {\"numeric\"}, {\"increasing\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-increasing\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([1 0], {\"numeric\"}, {\"nondecreasing\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-nondecreasing\");\n%! end_try_catch\n\n%!test\n%! try validateattributes ([1 2], {\"numeric\"}, {\"nonincreasing\"});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:expected-nonincreasing\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (@sin, {\"numeric\"}, {});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:invalid-type\");\n%! end_try_catch\n\n%!test\n%! try validateattributes (@sin, 1, {});\n%! catch id,\n%! assert (getfield (id, \"identifier\"), \"Octave:invalid-type\");\n%! end_try_catch\n"
  },
  {
    "path": "scripts/miscellaneous/ver.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ver\n## @deftypefnx {} {} ver Octave\n## @deftypefnx {} {} ver @var{package}\n## @deftypefnx {} {v =} ver (@dots{})\n##\n## Display a header containing the current Octave version number, license\n## string, and operating system.  The header is followed by a list of installed\n## packages, versions, and installation directories.\n##\n## Use the package name @var{package} or Octave to query a specific component.\n##\n## When called with an output argument, return a vector of structures\n## describing Octave and each installed package.  Each structure includes the\n## following fields.\n##\n## @table @code\n## @item Name\n## Package name.\n##\n## @item Version\n## Version of the package.\n##\n## @item Release\n## Release of the package (currently unused, defaults to @code{[]}).\n##\n## @item Date\n## Date that the version was released.\n## @end table\n##\n## @seealso{version, usejava, pkg}\n## @end deftypefn\n\nfunction v = ver (package = \"\")\n\n  if (nargout == 0)\n    hg_id = __octave_config_info__ (\"hg_id\");\n\n    [unm, err] = uname ();\n\n    if (err)\n      os_string = \"unknown\";\n    else\n      os_string = sprintf (\"%s %s %s %s\",\n                           unm.sysname, unm.release, unm.version, unm.machine);\n    endif\n\n    hbar(1:70) = \"-\";\n    desc = {hbar\n            [\"GNU Octave Version: \" OCTAVE_VERSION \" (hg id: \" hg_id \")\"]\n            [\"GNU Octave License: \" license]\n            [\"Operating System: \" os_string]\n            hbar};\n\n    printf (\"%s\\n\", desc{:});\n\n    if (isempty (package))\n      pkg (\"list\");\n    elseif (strcmpi (package, \"Octave\"))\n      ## Nothing to do, Octave version was already reported\n    else\n      pkg (\"list\", package);\n    endif\n  else\n    ## Return outputs rather than displaying summary to screen.\n    if (isempty (package))\n      ## Start with the version info for Octave\n      [octver, octdate] = version ();\n      v = struct (\"Name\", \"Octave\", \"Version\", octver,\n                  \"Release\", [], \"Date\", octdate);\n      lst = pkg (\"list\");\n      for i = 1:numel (lst)\n        v(end+1) = struct (\"Name\", lst{i}.name, \"Version\", lst{i}.version,\n                           \"Release\", [], \"Date\", lst{i}.date);\n      endfor\n    elseif (strcmpi (package, \"Octave\"))\n      [octver, octdate] = version ();\n      v = struct (\"Name\", \"Octave\", \"Version\", octver,\n                  \"Release\", [], \"Date\", octdate);\n    else\n      lst = pkg (\"list\", package);\n      if (isempty (lst))\n        v = struct (\"Name\", {}, \"Version\", {}, \"Release\", {}, \"Date\", {});\n      else\n        v = struct (\"Name\", lst{1}.name, \"Version\", lst{1}.version,\n                    \"Release\", [], \"Date\", lst{1}.date);\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! result = ver;\n%! assert (result(1).Name, \"Octave\");\n%! assert (result(1).Version, OCTAVE_VERSION ());\n%! assert (result(1).Release, []);\n%! assert (result(1).Date, __octave_config_info__ (\"release_date\"));\n%! result = ver (\"octave\");\n%! assert (result.Name, \"Octave\");\n%! assert (result.Version, OCTAVE_VERSION ());\n%! assert (result.Release, []);\n%! assert (result.Date, __octave_config_info__ (\"release_date\"));\n\n%!test\n%! lst = pkg (\"list\");\n%! for n = 1:numel (lst)\n%!   expected = lst{n}.name;\n%!   result = ver (expected);\n%!   assert (result.Name, expected);\n%!   assert (isfield (result, \"Version\"), true);\n%!   assert (isfield (result, \"Release\"), true);\n%!   assert (isfield (result, \"Date\"), true);\n%! endfor\n\n%!test\n%! result = ver (\"%_an_unknown_package_%\");\n%! assert (isempty (result), true);\n"
  },
  {
    "path": "scripts/miscellaneous/verLessThan.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} verLessThan (@var{package}, @var{version})\n## Return true if the installed version of the package is less than\n## @var{version}.\n##\n## @var{package} is the name of the package to check.  Use @qcode{\"Octave\"} as\n## the @var{package} to check the version of Octave itself.\n##\n## @var{version} is the version to compare it to.  A version is a string in the\n## format accepted by @code{compare_versions}: an arbitrarily long string\n## composed of numeric and period characters, possibly followed by an arbitrary\n## string (e.g., @qcode{\"1.2.3\"}, @qcode{\"0.3\"}, @qcode{\"0.1.2+\"}, or\n## @qcode{\"1.2.3.4-test1\"}).\n##\n## Examples:\n##\n## @example\n## @group\n## tf = verLessThan (\"Octave\", \"5\")\n## @xresult{} tf = 0\n##\n## tf = verLessThan (\"io\", \"2.4.12\")\n## @xresult{} ...\n##\n## if (! verLessThan (\"Octave\", \"5\"))\n##   ## ... use new Octave 5 features ...\n## endif\n## @end group\n## @end example\n##\n## @seealso{compare_versions, version, ver, pkg}\n## @end deftypefn\n\nfunction tf = verLessThan (package, version)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! ischar (package) || rows (package) != 1)\n    error (\"verLessThan: PACKAGE must be a string\");\n  endif\n\n  v = ver ();\n  idx = find (strcmpi (package, {v.Name}));\n  if (isempty (idx))\n    error ('verLessThan: package \"%s\" is not installed', package);\n  endif\n\n  tf = compare_versions (v(idx).Version, version, \"<\");\n\nendfunction\n\n\n%!assert (! verLessThan (\"Octave\", \"0\"))\n%!assert (! verLessThan (\"Octave\", \"6\"))\n%!assert (! verLessThan (\"Octave\", \"3.0.0\"))\n%!assert (verLessThan (\"Octave\", \"99.9.9\"))\n\n## Test input validation\n%!error <Invalid call> verLessThan ()\n%!error verLessThan (\"a\")\n%!error verLessThan (\"a\", \"1\", \"b\")\n%!error <package \"no-such-package\" is not installed>\n%! verLessThan (\"no-such-package\", \"1.1.1\")\n%!error <compare_versions: version numbers V1 and V2 must be strings>\n%! verLessThan (\"Octave\", 4.1)\n"
  },
  {
    "path": "scripts/miscellaneous/version.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{v} =} version ()\n## @deftypefnx {} {[@var{v}, @var{d}] =} version ()\n## @deftypefnx {} {@var{v} =} version (@var{feature})\n## Get version information for Octave.\n##\n## If called without input argument, the first return value @var{v} gives the\n## version number of Octave as a string.  The second return value @var{d} holds\n## the release date as a string.\n##\n## The following options can be passed for @var{feature}:\n##\n## @table @asis\n## @item @qcode{\"-date\"}\n## for the release date of the running build,\n##\n## @item @qcode{\"-description\"}\n## for a description of the release (always an empty string),\n##\n## @item @qcode{\"-release\"}\n## for the name of the running build (always an empty string),\n##\n## @item @qcode{\"-java\"}\n## for version information of the Java @nospell{VM},\n##\n## @item @qcode{\"-fftw\"}\n## for version information for the linked @sc{fftw},\n##\n## @item @qcode{\"-blas\"}\n## for version information for the linked @sc{blas},\n##\n## @item @qcode{\"-lapack\"}\n## for version information for the linked @sc{lapack}.\n##\n## @item @qcode{\"-hgid\"}\n## the mercurial ID of the sources used to build Octave.\n## @end table\n##\n## The information returned for the @qcode{\"-blas\"} and @qcode{\"-lapack\"}\n## options might be unreliable.  It might report which library was linked in\n## when Octave was built instead of which library is currently used.\n##\n## The variant with no input and output argument is an alias for the function\n## @w{@env{OCTAVE_VERSION}}@ provided for compatibility.\n## @seealso{OCTAVE_VERSION, ver}\n## @end deftypefn\n\nfunction [v, d] = version (feature)\n\n  if (nargin == 1 && (nargout > 1 || ! ischar (feature)))\n    print_usage ();\n  endif\n\n  if (nargin == 0)\n    v = OCTAVE_VERSION ();\n\n    if (nargout > 1)\n      d = __octave_config_info__ (\"release_date\");\n    endif\n  else\n    switch (lower (feature))\n      case \"-date\"\n        v = __octave_config_info__ (\"release_date\");\n      case \"-description\"\n        v = \"\";\n      case \"-release\"\n        v = \"\";\n      case \"-java\"\n        try\n          jversion = javaMethod (\"getProperty\", \"java.lang.System\", ...\n                                 \"java.runtime.version\");\n          jvendor = javaMethod (\"getProperty\", \"java.lang.System\", ...\n                                \"java.vendor\");\n          jname = javaMethod (\"getProperty\", \"java.lang.System\", ...\n                              \"java.vm.name\");\n          jjitmode = javaMethod (\"getProperty\", \"java.lang.System\", ...\n                                 \"java.vm.info\");\n          v = [\"Java \" jversion \" with \" jvendor \" \" jname \" \" jjitmode];\n        catch err\n          v = sprintf (\"no usable Java Runtime Environment (%s) found:\\n%s\", ...\n                       uname ().machine, err.message);\n        end_try_catch\n      case \"-fftw\"\n        v = __octave_config_info__ (\"fftw_version\");\n      case \"-blas\"\n        v = __blas_version__ ();\n      case \"-lapack\"\n        v = __lapack_version__ ();\n      case \"-hgid\"\n        v = __octave_config_info__ (\"hg_id\");\n      otherwise\n        error (\"version: invalid FEATURE\");\n    endswitch\n  endif\n\nendfunction\n\n\n%!assert (ischar (version ()))\n\n%!test\n%! [v, d] = version ();\n%! assert (v, OCTAVE_VERSION);\n%! assert (d, __octave_config_info__ (\"release_date\"));\n\n%!assert (version (\"-date\"), __octave_config_info__ (\"release_date\"))\n\n%!assert (version (\"-description\"), \"\")\n%!assert (version (\"-release\"), \"\")\n%!assert (ischar (version (\"-blas\")))\n%!assert (ischar (version (\"-LAPACK\")))\n\n## Test input validation\n%!error version (\"-date\", \"-release\")\n%!error [v, d] = version (\"-date\")\n%!error version (1)\n%!error <invalid FEATURE> version (\"-foobar\")\n"
  },
  {
    "path": "scripts/miscellaneous/what.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} what\n## @deftypefnx {} {} what @var{dir}\n## @deftypefnx {} {w =} what (@var{dir})\n## List the Octave specific files in directory @var{dir}.\n##\n## If @var{dir} is not specified then the current directory is used.\n##\n## If a return argument is requested, the files found are returned in the\n## structure @var{w}.  The structure contains the following fields:\n##\n## @table @asis\n## @item path\n## Full path to directory @var{dir}\n##\n## @item m\n## Cell array of m-files\n##\n## @item mat\n## Cell array of mat files\n##\n## @item mex\n## Cell array of mex files\n##\n## @item oct\n## Cell array of oct files\n##\n## @item mdl\n## Cell array of mdl files\n##\n## @item slx\n## Cell array of slx files\n##\n## @item p\n## Cell array of p-files\n##\n## @item classes\n## Cell array of class directories (@file{@@@var{classname}/})\n##\n## @item packages\n## Cell array of package directories (@file{+@var{pkgname}/})\n## @end table\n##\n## Compatibility Note: Octave does not support mdl, slx, and p files.\n## @code{what} will always return an empty list for these categories.\n## @seealso{which, ls, exist}\n## @end deftypefn\n\nfunction w = what (dir)\n\n  if (nargin == 0)\n    dir = { pwd() };\n  else\n    dtmp = canonicalize_file_name (dir);\n    if (isempty (dtmp))\n      dtmp = {};\n    else\n      dtmp = {dtmp};\n    endif\n    ## Search for directory name in path\n    if (dir(end) == '/' || dir(end) == '\\')\n      dir(end) = [];\n    endif\n    dtmp = unique ([dtmp; dir_in_loadpath(dir, \"all\")]);\n\n    if (isempty (dtmp) && nargout == 0)\n      printf (\"%s not found\\n\", dir);\n      return;\n    endif\n\n    dir = dtmp;\n  endif\n\n   ## Lookup info for each directory\n   for i = 1 : numel (dir)\n     ws(i) = __what__ (dir{i});\n   endfor\n\n   ## If none was found, return an empty struct\n   if (numel (dir) == 0)\n     ws = __what__ (\"\");\n     ws = resize (ws, [0, 1]);  # Matlab compatibility, return 0x1 empty array\n   endif\n\n  if (nargout == 0)\n    for i = 1 : numel (ws)\n      __print_fnames__ (\"M-files in directory\", ws(i).path, ws(i).m);\n      __print_fnames__ (\"\\nMAT-files in directory\", ws(i).path, ws(i).mat);\n      __print_fnames__ (\"\\nMEX-files in directory\", ws(i).path, ws(i).mex);\n      __print_fnames__ (\"\\nOCT-files in directory\", ws(i).path, ws(i).oct);\n      __print_fnames__ (\"\\nClasses in directory\", ws(i).path, ws(i).classes);\n      __print_fnames__ (\"\\nPackages in directory\", ws(i).path, ws(i).packages);\n    endfor\n  else\n    w = ws;\n  endif\n\nendfunction\n\n\n## what() functionality for a single directory\nfunction w = __what__ (dir)\n\n  files = readdir (dir);\n  w.path = dir;\n  w.m = cell (0, 1);\n  w.mat = cell (0, 1);\n  w.mex = cell (0, 1);\n  w.oct = cell (0, 1);\n  w.mdl = cell (0, 1);\n  w.slx = cell (0, 1);\n  w.p = cell (0, 1);\n  w.classes = cell (0, 1);\n  w.packages = cell (0, 1);\n\n  for i = 1 : numel (files)\n    nm = files{i};\n\n    if (strcmp (nm, \".\") || strcmp (nm, \"..\"))\n      continue;   # Ignore . and ..\n    endif\n\n    ## mdl, slx, and p are ignored (no if test) since they are not implemented\n    [~, f, e] = fileparts (nm);\n    if (strcmp (e, \".m\"))\n      if (isfile (fullfile (dir, nm)))\n        w.m{end+1} = nm;\n      endif\n    elseif (strcmp (e, \".mat\"))\n      if (isfile (fullfile (dir, nm)))\n        w.mat{end+1} = nm;\n      endif\n    elseif (strcmp (e, \".oct\"))\n      if (isfile (fullfile (dir, nm)))\n        w.oct{end+1} = nm;\n      endif\n    elseif (strcmp (e, ['.' mexext]))\n      if (isfile (fullfile (dir, nm)))\n        w.mex{end+1} = nm;\n      endif\n    elseif (nm(1) == \"@\")\n      if (isfolder (fullfile (dir, nm)))\n        w.classes{end+1} = nm;\n      endif\n    elseif (nm(1) == \"+\")\n      if (isfolder (fullfile (dir, nm)))\n        w.packages{end+1} = nm;\n      endif\n    endif\n\n  endfor\n\nendfunction\n\n\n## Pretty print filenames to terminal\nfunction __print_fnames__ (msg, p, f)\n\n  if (! isempty (f))\n    printf (\"%s %s:\\n\\n\", msg, p);\n    printf (\"%s\", list_in_columns (f, 0, \"   \"));\n  endif\n\nendfunction\n\n\n%!test\n%! w = what ();\n%! assert (w.path, pwd);\n%! assert (fieldnames (w), {\"path\"; \"m\"; \"mat\"; \"mex\"; \"oct\"; \"mdl\"; \"slx\";\n%!                          \"p\"; \"classes\"; \"packages\"});\n\n## FIXME: Should have additional tests.  Possibly create a temporary directory\n## within TMPDIR, create files and folders, and call what() on that dir.\n%!error what (1, 2)\n"
  },
  {
    "path": "scripts/miscellaneous/zip.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{filelist} =} zip (@var{zipfile}, @var{files})\n## @deftypefnx {} {@var{filelist} =} zip (@var{zipfile}, @var{files}, @var{rootdir})\n## Compress the list of files and directories specified in @var{files} into the\n## ZIP archive @var{zipfile}.\n##\n## @var{files} is a character array or cell array of strings.  Shell\n## wildcards in the filename such as @samp{*} or @samp{?} are accepted and\n## expanded.  Directories are recursively traversed and all files are\n## compressed and added to the archive.\n##\n## If @var{rootdir} is defined then any files without absolute pathnames are\n## located relative to @var{rootdir} rather than the current directory.\n##\n## The optional output @var{filelist} is a list of the files that were included\n## in the archive.\n## @seealso{unzip, unpack, bzip2, gzip, tar}\n## @end deftypefn\n\nfunction filelist = zip (zipfile, files, rootdir = \".\")\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! ischar (zipfile))\n    error (\"zip: ZIPFILE must be a string\");\n  elseif (ischar (files))\n    files = cellstr (files);\n  elseif (! iscellstr (files))\n    error (\"zip: FILES must be a character array or cellstr\");\n  endif\n\n  rootdir = tilde_expand (rootdir);\n\n  zipfile = make_absolute_filename (zipfile);\n\n  ## FIXME: This is a lot of processing that could be done by the shell\n  ##        if Octave had a way to call system without passing a single string.\n  ## Escape bad shell characters\n  files = regexprep (files, \"([|&;<>()$`\\\\'\\\" ])\", '\\\\$1');\n  files = sprintf (' %s', files{:});   # convert to space separated list\n  zipfile = regexprep (zipfile, \"'\", \"\\\\'\");  # escape single quotes\n  cmd = sprintf (\"zip -r '%s' %s\", zipfile, files);\n  if (ispc ())\n    cmd = strrep (cmd, '\\', '/');\n  endif\n\n  origdir = pwd ();\n  cd (rootdir);\n  [status, output] = system (cmd);\n  cd (origdir);\n\n  if (status)\n    error (\"zip: zip failed with exit status = %d\", status);\n  endif\n\n  if (nargout > 0)\n    cmd = sprintf (\"unzip -Z -1 '%s'\", zipfile);\n    [status, filelist] = system (cmd);\n    if (status)\n      error (\"zip: zipinfo failed with exit status = %d\", status);\n    endif\n    filelist = ostrsplit (filelist, \"\\r\\n\", true);\n  endif\n\nendfunction\n\n\n## FIXME: This test may fail if the zip or unzip command is not installed.\n##        If this test fails, it might be better to change it into a testif\n##        with a runtime condition on the zip and unzip programs.\n%!test\n%! ## test zip together with unzip\n%! unwind_protect\n%!   filename = tempname ();\n%!   tmp_var  = pi;\n%!   save (filename, \"tmp_var\");\n%!   dirname = tempname ();\n%!   mkdir (dirname);\n%!   zipfile = tempname ();\n%!   [~, basename, ext] = fileparts (filename);\n%!   filelist = zip (zipfile, [basename ext], tempdir);\n%!   filelist = filelist{1};\n%!   if (! strcmp (filelist, [basename ext]))\n%!     error (\"zip archive does not contain expected name!\");\n%!   endif\n%!   if (! exist ([zipfile \".zip\"], \"file\"))\n%!     error (\"zip file cannot be found!\");\n%!   endif\n%!   unzip ([zipfile \".zip\"], dirname);\n%!   fid = fopen (filename, \"rb\");\n%!   assert (fid >= 0);\n%!   orig_data = fread (fid);\n%!   fclose (fid);\n%!   fid = fopen ([dirname filesep basename ext], \"rb\");\n%!   assert (fid >= 0);\n%!   new_data = fread (fid);\n%!   fclose (fid);\n%!   if (orig_data != new_data)\n%!     error (\"unzipped file not equal to original file!\");\n%!   endif\n%! unwind_protect_cleanup\n%!   delete ([filename '*']);\n%!   sts = unlink ([dirname, filesep, basename, ext]);\n%!   sts = unlink (zipfile);\n%!   sts = unlink ([zipfile \".zip\"]);\n%!   sts = rmdir (dirname);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> zip ()\n%!error <Invalid call> zip (1)\n%!error <ZIPFILE must be a string> zip (1, \"foobar\")\n%!error <FILES must be a character array or cellstr> zip (\"foobar\", 1)\n"
  },
  {
    "path": "scripts/mk-doc.pl",
    "content": "#! /usr/bin/perl\nuse utf8;\n\n########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nuse strict;\nuse warnings;\nuse File::Spec;\nuse Cwd;\n\n## Expecting arguments in this order:\n##\n##  SRCDIR SRCDIR-FILES ...\n\nunless (@ARGV >= 2) { die \"Usage: $0 srcdir m_filename1 ...\" ; }\n\nmy $srcdir = shift (@ARGV);\n\nprint <<__END_OF_MSG__;\n### DO NOT EDIT!\n###\n### This file is generated automatically from Octave source files.\n### Edit source files directly and run make to update this file.\n\n__END_OF_MSG__\n\nMFILE: foreach my $m_fname (@ARGV)\n{\n  my $full_fname = File::Spec->catfile ($srcdir, $m_fname);\n  my @paths = File::Spec->splitdir ($full_fname);\n  if (@paths < 3\n      || $paths[-2] eq \"private\"   # skip private directories\n      || $paths[-1] !~ s/(\\.in|)\\.m$//i)  # skip non m-files, and remove extension\n    { next MFILE; }\n\n  my $fcn;\n  if ($paths[-2] =~ m/^@/)\n    {\n      ## @classes will have @class/method as their function name\n      $fcn = File::Spec->catfile (@paths[-2, -1]);\n    }\n  elsif ($paths[-2] =~ m/^\\+/)\n    {\n      $fcn = $paths[-1];\n      for (my $i = 2; $i < @paths; $i++)\n        {\n          if ($paths[-$i] =~ m/^\\+/)\n            {\n              ## +package functions have package.name their function name\n              $fcn = substr ($paths[-$i], 1) . \".\" . $fcn;\n            }\n        }\n    }\n  else\n    {\n      $fcn = $paths[-1];\n    }\n\n  my @help_txt = gethelp ($fcn, $full_fname);\n  next MFILE unless @help_txt;\n\n  print \"\\x{1d}$fcn\\n\";\n  print \"\\@c $fcn $m_fname\\n\";\n\n  foreach $_ (@help_txt)\n    {\n      my $in_example = (m/\\s*\\@example\\b/ .. m/\\s*\\@end\\s+example\\b/);\n      s/^\\s+\\@/\\@/ unless $in_example;\n      s/^\\s+(\\@(?:end)\\s+(group|example))/$1/;\n      print $_;\n    }\n}\n\n################################################################################\n# Subroutines\n################################################################################\nsub gethelp\n{\n  my $fcn   = shift;\n  my $fname = shift;\n  my $have_cdef_file = 0;\n  my $found_code = 0;\n\n  open (my $fh, \"<\", $fname) or return;\n\n  my @help_txt;\n  while (my $line = <$fh>)\n    {\n      next if $line =~ m/^[\\s#%]*$/;  # skip empty lines\n\n      if ($line !~ m/^\\s*(#|%)/)\n        {\n          if (! $found_code)\n            {\n              $found_code = 1;\n              $have_cdef_file = ! $have_cdef_file && $line =~ m/^\\s*classdef/;\n            }\n\n          next if $have_cdef_file;\n          last;\n        }\n\n      my $reading_block = sub {defined ($line = <$fh>) && $line !~ m/^\\s*$/};\n\n      ## Skip this block\n      if ($line =~ /(Copyright|Author)/)\n        { while (&$reading_block ()) {} }\n      else\n        {\n          do\n            {\n              $line =~ s/^\\s*(%|#)+ ?//;\n              push (@help_txt, $line);\n            } while (&$reading_block ());\n          last;\n\n          ## Instead of jumping out here unconditionally, should we\n          ## attempt to extract multiple help comment blocks in a\n          ## classdef file by searching forward for the next line that\n          ## begins with \"function\" and then saving the first comment\n          ## block after that?  We will need a way to recognize the\n          ## method name to print the docstring separator line.  Maybe\n          ## we should just be using Octave's parser and help system for\n          ## this job?\n\n          ## if ($have_cdef_file)\n          ##   {\n          ##     while (my $line = <$fh>)\n          ##       {\n          ##         last if $line =~ /^\\s*function/;\n          ##       }\n          ##   }\n          ## else\n          ##  {\n          ##    last;\n          ##  }\n        }\n    }\n\n  close ($fh);\n  return @help_txt;\n}\n"
  },
  {
    "path": "scripts/mk-pkg-add.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Expecting arguments in this order:\n##\n##  SRCDIR SRCDIR-FILES ... -- LOCAL-FILES ...\n\nset -e\n\nSED=${SED:-sed}\n\nprefix=\"$1/\"\nif [ \"$1\" ]; then\n  shift\nfi\n\nfor arg\ndo\n  if [ \"$arg\" = \"--\" ]; then\n    prefix=\"\"\n  else\n    $SED -n 's/^[#%][#%]* *PKG_ADD: *//p' \"$prefix$arg\"\n  fi\ndone\n"
  },
  {
    "path": "scripts/module.mk",
    "content": "%canon_reldir%_EXTRA_DIST =\n\n%canon_reldir%_CLEANFILES =\n%canon_reldir%_DISTCLEANFILES =\n%canon_reldir%_MAINTAINERCLEANFILES =\n\ninclude %reldir%/+containers/module.mk\ninclude %reldir%/+matlab/+lang/module.mk\ninclude %reldir%/+matlab/+net/module.mk\ninclude %reldir%/audio/module.mk\ninclude %reldir%/deprecated/module.mk\ninclude %reldir%/elfun/module.mk\ninclude %reldir%/general/module.mk\ninclude %reldir%/geometry/module.mk\ninclude %reldir%/gui/module.mk\ninclude %reldir%/help/module.mk\ninclude %reldir%/image/module.mk\ninclude %reldir%/io/module.mk\ninclude %reldir%/java/module.mk\ninclude %reldir%/legacy/module.mk\ninclude %reldir%/linear-algebra/module.mk\ninclude %reldir%/miscellaneous/module.mk\ninclude %reldir%/ode/module.mk\ninclude %reldir%/optimization/module.mk\ninclude %reldir%/path/module.mk\ninclude %reldir%/pkg/module.mk\ninclude %reldir%/plot/appearance/module.mk\ninclude %reldir%/plot/draw/module.mk\ninclude %reldir%/plot/util/module.mk\ninclude %reldir%/polynomial/module.mk\ninclude %reldir%/prefs/module.mk\ninclude %reldir%/profiler/module.mk\ninclude %reldir%/set/module.mk\ninclude %reldir%/signal/module.mk\ninclude %reldir%/sparse/module.mk\ninclude %reldir%/specfun/module.mk\ninclude %reldir%/special-matrix/module.mk\ninclude %reldir%/startup/module.mk\ninclude %reldir%/statistics/module.mk\ninclude %reldir%/strings/module.mk\ninclude %reldir%/testfun/module.mk\ninclude %reldir%/time/module.mk\ninclude %reldir%/web/module.mk\n\n## include %reldir%/@ftp/module.mk\n## The include above fails because Automake cannot process the '@' character.\n## As a work around, the contents of %reldir%/@ftp/module.mk are placed directly\n## in this module.mk file.\nscripts_EXTRA_DIST += %reldir%/@ftp/module.mk\n######################## include %reldir%/@ftp/module.mk ########################\nFCN_FILE_DIRS += %reldir%/@ftp\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config\n\n%canon_reldir%_@ftp_FCN_FILES = \\\n  %reldir%/@ftp/ascii.m \\\n  %reldir%/@ftp/binary.m  \\\n  %reldir%/@ftp/cd.m  \\\n  %reldir%/@ftp/close.m  \\\n  %reldir%/@ftp/delete.m  \\\n  %reldir%/@ftp/dir.m  \\\n  %reldir%/@ftp/disp.m  \\\n  %reldir%/@ftp/ftp.m  \\\n  %reldir%/@ftp/loadobj.m  \\\n  %reldir%/@ftp/mget.m  \\\n  %reldir%/@ftp/mkdir.m  \\\n  %reldir%/@ftp/mput.m  \\\n  %reldir%/@ftp/rename.m  \\\n  %reldir%/@ftp/rmdir.m  \\\n  %reldir%/@ftp/saveobj.m\n\n%canon_reldir%_@ftpdir = $(fcnfiledir)/@ftp\n\n%canon_reldir%_@ftp_DATA = $(%canon_reldir%_@ftp_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_@ftp_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/@ftp/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/@ftp/$(octave_dirstamp)\n####################### end include %reldir%/@ftp/module.mk #####################\n\nimage_DATA += $(SCRIPTS_IMAGES)\n\nGEN_FCN_FILES_IN = $(GEN_FCN_FILES:.m=.in.m)\n\nALL_LOCAL_TARGETS += \\\n  $(JAR_FILES)\n\nOCTAVE_INTERPRETER_TARGETS += \\\n  $(GEN_FCN_FILES) \\\n  $(PKG_ADD_FILES)\n\nFCN_FILES_WITH_TESTS = $(shell $(SHELL) build-aux/find-files-with-tests.sh \"$(srcdir)\" $(FCN_FILES) $(GEN_FCN_FILES_IN))\n\ndefine PKG_ADD_FILE_TEMPLATE\n$(1)/PKG_ADD: $$($(2)_FCN_FILES) $$($(2)_GEN_FCN_FILES) $(1)/$(octave_dirstamp) %reldir%/mk-pkg-add.sh\n\t$$(AM_V_GEN)rm -f $$@-t $$@ && \\\n\t$$(SHELL) $$(srcdir)/%reldir%/mk-pkg-add.sh $(srcdir) $$($(2)_FCN_FILES) -- $$($(2)_GEN_FCN_FILES) > $$@-t && \\\n\tmv $$@-t $$@\nendef\n\n$(foreach d, $(FCN_FILE_DIRS), $(eval $(call PKG_ADD_FILE_TEMPLATE, $(d),$(subst /,_,$(subst -,_,$(d))))))\n\ndefine GEN_FCN_FILES_TEMPLATE\n$(1): $(1:.m=.in.m) build-aux/subst-config-vals.sh $(dir $(1))$(octave_dirstamp)\n\t$$(AM_V_GEN)$$(call simple-filter-rule,build-aux/subst-config-vals.sh)\nendef\n\n$(foreach f, $(GEN_FCN_FILES), $(eval $(call GEN_FCN_FILES_TEMPLATE, $(f))))\n\nDOCSTRING_FILES += %reldir%/DOCSTRINGS\n\n%reldir%/DOCSTRINGS: $(FCN_FILES) $(GEN_FCN_FILES_IN) | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)rm -f %reldir%/DOCSTRINGS-t && \\\n\t$(PERL) $(srcdir)/%reldir%/mk-doc.pl \"$(srcdir)\" $(FCN_FILES) $(GEN_FCN_FILES_IN) > %reldir%/DOCSTRINGS-t && \\\n\t$(call move_if_change_rule,%reldir%/DOCSTRINGS-t,$@)\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\ncheck-m-sources:\n\t@echo \"checking whether files in source tree are listed in module.mk files...\"; \\\n\tfor f in $$(find $(srcdir)/scripts -name '*.m'); do \\\n\t  found=false; \\\n\t  for m in $(FCN_FILES) $(GEN_FCN_FILES); do \\\n\t    if [ \"$$f\" = $(srcdir)/%reldir%/\"$$m\" ]; then \\\n\t      found=true; \\\n\t      break; \\\n\t    fi; \\\n\t  done; \\\n\t  if $$found; then \\\n\t    true; \\\n\t  else \\\n\t    missing=$$(echo $$f | $(SED) \"s|^$(srcdir)/scripts||\"); \\\n\t    echo \"$$missing: not listed in SOURCES\"; \\\n\t  fi; \\\n\tdone; \\\n\tif test -z \"$$missing\"; then \\\n\t  echo \"yes\"; \\\n\tfi\n.PHONY: check-m-sources\n\ncheck-missing-semicolon:\n\t@echo \"checking for missing semicolons in .m files...\"\n\t@( echo \"warning on Octave:missing-semicolon;\"; \\\n\t  for m in $(addprefix $(srcdir)/, $(FCN_FILES)) $(GEN_FCN_FILES); do \\\n\t    ! $(GREP) -q -E '^classdef' $$m || continue; \\\n\t    ! $(GREP) -q -E '^  *\\<function\\>' $$m || continue; \\\n\t    ! (echo $$m | $(GREP) -q __splinefit__.m) || continue; \\\n\t    echo \"source ('$$m');\"; \\\n\t  done ) | $(SHELL) run-octave --norc --quiet --no-history\n.PHONY: check-missing-semicolon\n\n## Include m-files in list of sources when building tag files.\n## Automake will not include these because there is no xxx_SOURCES target\nTAGS_DEPENDENCIES = $(addprefix $(srcdir)/, $(FCN_FILES)) $(GEN_FCN_FILES)\nTAGS_FILES = $(addprefix $(srcdir)/, $(FCN_FILES)) $(GEN_FCN_FILES)\n\ninstall-data-local: install-startup-files install-pkg-add\n\nuninstall-local: uninstall-startup-files uninstall-pkg-add\n\ninstall-pkg-add:\n\tfor f in $(PKG_ADD_FILES); do \\\n\t  if [ -n \"`cat $$f`\" ]; then \\\n\t    base=`echo $$f | $(SED) 's,^%reldir%/,,'`; \\\n\t    $(MKDIR_P) $(DESTDIR)$(fcnfiledir)/`echo $$base | $(SED) 's,/[^/]*$$,,'`; \\\n\t    $(INSTALL_DATA) $$f $(DESTDIR)$(fcnfiledir)/$$base; \\\n\t  fi \\\n\tdone\n.PHONY: install-pkg-add\n\nuninstall-pkg-add:\n\tfor f in $(PKG_ADD_FILES); do \\\n\t  base=`echo $$f | $(SED) 's,^%reldir%/,,'`; \\\n\t  rm -f $(DESTDIR)$(fcnfiledir)/$$base; \\\n\tdone\n.PHONY: uninstall-pkg-add\n\nif AMCOND_HAVE_JAVA\nscripts-dist-hook:\nelse\nscripts-dist-hook:\n\t@echo \"Packaging distribution requires Java.\" ; exit 1;\nendif\n\n%canon_reldir%_EXTRA_DIST += \\\n  $(SCRIPTS_IMAGES) \\\n  $(FCN_FILES) \\\n  $(GEN_FCN_FILES_IN) \\\n  %reldir%/DOCSTRINGS \\\n  %reldir%/mk-doc.pl \\\n  %reldir%/mk-pkg-add.sh\n\nEXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)\n\n%canon_reldir%_CLEANFILES += \\\n  $(GEN_FCN_FILES) \\\n  $(PKG_ADD_FILES)\n\n%canon_reldir%_DISTCLEANFILES += \\\n  $(DIRSTAMP_FILES)\n\n%canon_reldir%_MAINTAINERCLEANFILES += \\\n  %reldir%/DOCSTRINGS\n\nCLEANFILES += $(%canon_reldir%_CLEANFILES)\nDISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)\nMAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)\n\nscripts-clean:\n\trm -f $(%canon_reldir%_CLEANFILES)\n\nscripts-distclean: scripts-clean\n\trm -f $(%canon_reldir%_DISTCLEANFILES)\n\nscripts-maintainer-clean: scripts-distclean\n\trm -f $(%canon_reldir%_MAINTAINERCLEANFILES)\n"
  },
  {
    "path": "scripts/ode/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/ode/decic.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{y0_new}, @var{yp0_new}] =} decic (@var{fcn}, @var{t0}, @var{y0}, @var{fixed_y0}, @var{yp0}, @var{fixed_yp0})\n## @deftypefnx {} {[@var{y0_new}, @var{yp0_new}] =} decic (@var{fcn}, @var{t0}, @var{y0}, @var{fixed_y0}, @var{yp0}, @var{fixed_yp0}, @var{options})\n## @deftypefnx {} {[@var{y0_new}, @var{yp0_new}, @var{resnorm}] =} decic (@dots{})\n##\n## Compute consistent implicit ODE initial conditions @var{y0_new} and\n## @var{yp0_new} given initial guesses @var{y0} and @var{yp0}.\n##\n## A maximum of @code{length (@var{y0})} components between @var{fixed_y0} and\n## @var{fixed_yp0} may be chosen as fixed values.\n##\n## @var{fcn} is a function handle.  The function must accept three inputs where\n## the first is time @var{t}, the second is a column vector of unknowns\n## @var{y}, and the third is a column vector of unknowns @var{yp}.\n##\n## @var{t0} is the initial time such that\n## @code{@var{fcn}(@var{t0}, @var{y0_new}, @var{yp0_new}) = 0}, specified as a\n## scalar.\n##\n## @var{y0} is a vector used as the initial guess for @var{y}.\n##\n## @var{fixed_y0} is a vector which specifies the components of @var{y0} to\n## hold fixed.  Choose a maximum of @code{length (@var{y0})} components between\n## @var{fixed_y0} and @var{fixed_yp0} as fixed values.\n## Set @var{fixed_y0}(i) component to 1 if you want to fix the value of\n## @var{y0}(i).\n## Set @var{fixed_y0}(i) component to 0 if you want to allow the value of\n## @var{y0}(i) to change.\n##\n## @var{yp0} is a vector used as the initial guess for @var{yp}.\n##\n## @var{fixed_yp0} is a vector which specifies the components of @var{yp0} to\n## hold fixed.  Choose a maximum of @code{length (@var{yp0})} components\n## between @var{fixed_y0} and @var{fixed_yp0} as fixed values.\n## Set @var{fixed_yp0}(i) component to 1 if you want to fix the value of\n## @var{yp0}(i).\n## Set @var{fixed_yp0}(i) component to 0 if you want to allow the value of\n## @var{yp0}(i) to change.\n##\n## The optional seventh argument @var{options} is a structure array.  Use\n## @code{odeset} to generate this structure.  The relevant options are\n## @code{RelTol} and @code{AbsTol} which specify the error thresholds used to\n## compute the initial conditions.\n##\n## The function typically returns two outputs.  Variable @var{y0_new} is a\n## column vector and contains the consistent initial value of @var{y}.  The\n## output @var{yp0_new} is a column vector and contains the consistent initial\n## value of @var{yp}.\n##\n## The optional third output @var{resnorm} is the norm of the vector of\n## residuals.  If @var{resnorm} is small, @code{decic} has successfully\n## computed the initial conditions.  If the value of @var{resnorm} is large,\n## use @code{RelTol} and @code{AbsTol} to adjust it.\n##\n## Example: Compute initial conditions for @nospell{Robertson's} equations:\n##\n## @smallexample\n## @group\n## function r = robertson_dae (@var{t}, @var{y}, @var{yp})\n##   r = [ -(@var{yp}(1) + 0.04*@var{y}(1) - 1e4*@var{y}(2)*@var{y}(3))\n##         -(@var{yp}(2) - 0.04*@var{y}(1) + 1e4*@var{y}(2)*@var{y}(3) + 3e7*@var{y}(2)^2)\n##        @var{y}(1) + @var{y}(2) + @var{y}(3) - 1 ];\n## endfunction\n## @end group\n## [@var{y0_new},@var{yp0_new}] = decic (@@robertson_dae, 0, [1; 0; 0], [1; 1; 0],\n## [-1e-4; 1; 0], [0; 0; 0]);\n## @end smallexample\n## @seealso{ode15i, odeset}\n## @end deftypefn\n\nfunction [y0_new, yp0_new, resnorm] = decic (fcn, t0,\n                                             y0, fixed_y0, yp0, fixed_yp0,\n                                             options)\n\n  if (nargin < 6)\n    print_usage ();\n  endif\n\n  ## Validate inputs\n  if (! is_function_handle (fcn))\n    error (\"Octave:invalid-input-arg\",\n           \"decic: FCN must be a valid function handle\");\n  endif\n\n  if (! (isnumeric (t0) && isscalar (t0)))\n    error (\"Octave:invalid-input-arg\",\n           \"decic: T0 must be a numeric scalar\");\n  endif\n\n  if (   ! (isnumeric (y0) && isvector (y0))\n      || ! (isnumeric (fixed_y0) && isvector (fixed_y0))\n      || ! (isnumeric (yp0) && isvector (yp0))\n      || ! (isnumeric (fixed_yp0) && isvector (fixed_yp0)))\n   error (\"Octave:invalid-input-arg\",\n          \"decic: Y0, FIXED_Y0, YP0, and FIXED_YP0 must be numeric vectors\");\n\n  elseif (! isequal (numel (y0), numel (fixed_y0), numel (yp0),\n                     numel (fixed_yp0)))\n    error (\"Octave:invalid-input-arg\",\n           \"decic: length of Y0, FIXED_Y0, YP0, and FIXED_YP0 must be equal\");\n  endif\n\n  ## FIXME: This level of checking isn't necessary\n  for i = 1:numel (y0)\n    if (! (fixed_y0(i) == 0 || fixed_y0(i) == 1) || ! (fixed_yp0(i) == 0\n        || fixed_yp0(i) == 1))\n      error (\"Octave:invalid-input-arg\",\n             \"decic: FIXED_Y0 and FIXED_YP0 must be boolean vectors\");\n    endif\n  endfor\n\n  n  = numel (y0);\n  nl = sum (! fixed_y0);\n  nu = sum (! fixed_yp0);\n\n  if (n - nl - nu > 0)\n    error (\"Octave:invalid-input-arg\",\n           \"decic: cannot fix more than length (Y0) components\");\n  endif\n\n  ## Set default values\n  TolFun = 0;\n  TolX   = eps;\n\n  ## Check AbsTol and RelTol\n  if (nargin == 7)\n    if (! isempty (options.AbsTol))\n      if (! isscalar (options.AbsTol))\n        error (\"Octave:invalid-input-arg\",\n               \"decic: AbsTol must be a scalar value\");\n      else\n        TolFun = options.AbsTol;\n      endif\n    endif\n\n    if (! isempty (options.RelTol))\n      if (! isscalar (options.RelTol))\n        error (\"Octave:invalid-input-arg\",\n               \"decic: RelTol must be a scalar value\");\n      else\n        TolX = options.RelTol;\n      endif\n    endif\n  endif\n\n  x0 = [y0(! fixed_y0); yp0(! fixed_yp0)];\n  opt = optimset (\"tolfun\", TolFun, \"tolx\", TolX, \"FinDiffType\", \"central\");\n  x = ...\n    fminunc (@(x) objective (x, t0, y0, fixed_y0, yp0, fixed_yp0, nl, nu, fcn),\n             x0, opt);\n\n  y0_new  = y0;\n  yp0_new = yp0;\n\n  y0_new(! fixed_y0)   = x(1:nl);\n  yp0_new(! fixed_yp0) = x(nl+1:nl+nu);\n  if (nargout > 2)\n    resnorm = fcn (t0, y0_new, yp0_new);\n  endif\n\nendfunction\n\nfunction res = objective (x, t0, y0, fixed_y0, yp0, fixed_yp0, nl, nu, fcn)\n\n  y = y0;\n  y(! fixed_y0) = x(1:nl);\n  yp = yp0;\n  yp(! fixed_yp0) = x(nl+1:nl+nu);\n  res = sqrt (sum (fcn (t0, y, yp) .^ 2));\n\nendfunction\n\n\n%!function res = rob (t, y, yp)\n%!  res =[-(yp(1) + 0.04*y(1) - 1e4*y(2)*y(3));\n%!        -(yp(2) - 0.04*y(1) + 1e4*y(2)*y(3) + 3e7*y(2)^2);\n%!        y(1) + y(2) + y(3) - 1];\n%!endfunction\n\n%!test  # Without options\n%! ref1 = [1;0;0];\n%! ref2 = [-4e-2; 4e-2; 0];\n%! [ynew, ypnew] = decic (@rob,0,[1;0;0],[1;1;0],[23;110;0],[0;0;1]);\n%! assert ([ynew(1:end), ypnew(1:end)], [ref1(1:end), ref2(1:end)], 1e-10);\n%!test  # With options\n%! ref1 = [1;0;0];\n%! ref2 = [-4e-2; 4e-2; 0];\n%! opt = odeset (\"AbsTol\", 1e-8, \"RelTol\", 1e-4);\n%! [ynew, ypnew] = decic (@rob,0,[1;0;0],[1;1;0],[23;110;0],[0;0;1],opt);\n%! assert ([ynew(1:end), ypnew(1:end)], [ref1(1:end), ref2(1:end)], 1e-5);\n\n## Test input validation\n%!error <Invalid call> decic ()\n%!error <Invalid call> decic (1)\n%!error <Invalid call> decic (1,2)\n%!error <Invalid call> decic (1,2,3)\n%!error <Invalid call> decic (1,2,3,4)\n%!error <Invalid call> decic (1,2,3,4,5)\n%!error <FCN must be a valid function handle>\n%! decic (1, 0, [1; 0; 0], [1; 1; 0], [-1e-4; 1; 0], [0; 0; 0]);\n%!error <T0 must be a numeric scalar>\n%! decic (@rob, [1, 1], [1; 0; 0], [1; 1; 0], [-1e-4; 1; 0], [0; 0; 0]);\n%!error <length of Y0, FIXED_Y0, YP0, and FIXED_YP0 must be equal>\n%! decic (@rob, 0, [0; 0], [1; 1; 0], [-1e-4; 1; 0], [0; 0; 0]);\n%!error <Y0, FIXED_Y0, YP0, and FIXED_YP0 must be numeric vectors>\n%! decic (@rob, 0, [1; 0; 0], [1; 0],\"\", [0; 0; 0]);\n%!error <Y0, FIXED_Y0, YP0, and FIXED_YP0 must be numeric vectors>\n%! decic (@rob, 0, [1; 0; 0], [1; 1; 0], [-1e-4; 1; 0], [0; 0; \"1\"]);\n%!error <FIXED_Y0 and FIXED_YP0 must be boolean vectors>\n%! decic (@rob, 0, [1; 0; 0], [5; 5; 0], [-1e-4; 1; 0], [0; 0; 0]);\n%!error <FIXED_Y0 and FIXED_YP0 must be boolean vectors>\n%! decic (@rob, 0, [1; 0; 0], [1; 1; 0], [-1e-4; 1; 0], [0; 4; 0]);\n%!error  <cannot fix more than length \\(Y0\\) components>\n%! decic (@rob, 0, [1; 0; 0], [1; 1; 0], [-1e-4; 1; 0], [0; 1; 1]);\n"
  },
  {
    "path": "scripts/ode/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/AbsRel_norm.m \\\n  %reldir%/private/check_default_input.m \\\n  %reldir%/private/integrate_adaptive.m \\\n  %reldir%/private/kahan.m \\\n  %reldir%/private/ode_event_handler.m \\\n  %reldir%/private/odedefaults.m \\\n  %reldir%/private/odemergeopts.m \\\n  %reldir%/private/runge_kutta_23.m \\\n  %reldir%/private/runge_kutta_23s.m \\\n  %reldir%/private/runge_kutta_45_dorpri.m \\\n  %reldir%/private/runge_kutta_interpolate.m \\\n  %reldir%/private/starting_stepsize.m\n\n%canon_reldir%_FCN_FILES =  \\\n  %reldir%/.oct-config \\\n  %reldir%/decic.m \\\n  %reldir%/ode15i.m \\\n  %reldir%/ode15s.m \\\n  %reldir%/ode23.m \\\n  %reldir%/ode23s.m \\\n  %reldir%/ode45.m \\\n  %reldir%/odeget.m \\\n  %reldir%/odeplot.m \\\n  %reldir%/odeset.m\n\n%canon_reldir%dir = $(fcnfiledir)/ode\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/ode/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/ode/ode15i.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{t}, @var{y}] =} ode15i (@var{fcn}, @var{trange}, @var{y0}, @var{yp0})\n## @deftypefnx {} {[@var{t}, @var{y}] =} ode15i (@var{fcn}, @var{trange}, @var{y0}, @var{yp0}, @var{ode_opt})\n## @deftypefnx {} {[@var{t}, @var{y}, @var{te}, @var{ye}, @var{ie}] =} ode15i (@dots{})\n## @deftypefnx {} {@var{solution} =} ode15i (@dots{})\n## @deftypefnx {} {} ode15i (@dots{})\n## Solve a set of fully-implicit Ordinary Differential Equations (ODEs) or\n## index 1 Differential Algebraic Equations (DAEs).\n##\n## @code{ode15i} uses a variable step, variable order BDF (Backward\n## Differentiation Formula) method that ranges from order 1 to 5.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function that defines the ODE: @code{0 = f(t,y,yp)}.  The\n## function must accept three inputs where the first is time @var{t}, the\n## second is the function value @var{y} (a column vector), and the third\n## is the derivative value @var{yp} (a column vector).\n##\n## @var{trange} specifies the time interval over which the ODE will be\n## evaluated.  Typically, it is a two-element vector specifying the initial and\n## final times (@code{[tinit, tfinal]}).  If there are more than two elements\n## then the solution will also be evaluated at these intermediate time\n## instances.\n##\n## @var{y0} and @var{yp0} contain the initial values for the unknowns @var{y}\n## and @var{yp}.  If they are row vectors then the solution @var{y} will be a\n## matrix in which each column is the solution for the corresponding initial\n## value in @var{y0} and @var{yp0}.\n##\n## @var{y0} and @var{yp0} must be consistent initial conditions, meaning that\n## @code{f(t,y0,yp0) = 0} is satisfied.  The function @code{decic} may be used\n## to compute consistent initial conditions given initial guesses.\n##\n## The optional fifth argument @var{ode_opt} specifies non-default options to\n## the ODE solver.  It is a structure generated by @code{odeset}.\n##\n## The function typically returns two outputs.  Variable @var{t} is a\n## column vector and contains the times where the solution was found.  The\n## output @var{y} is a matrix in which each column refers to a different\n## unknown of the problem and each row corresponds to a time in @var{t}.\n##\n## The output can also be returned as a structure @var{solution} which has a\n## field @var{x} containing a row vector of times where the solution was\n## evaluated and a field @var{y} containing the solution matrix such that each\n## column corresponds to a time in @var{x}.  Use\n## @w{@code{fieldnames (@var{solution})}}@ to see the other fields and\n## additional information returned.\n##\n## If no output arguments are requested, and no @qcode{\"OutputFcn\"} is\n## specified in @var{ode_opt}, then the @qcode{\"OutputFcn\"} is set to\n## @code{odeplot} and the results of the solver are plotted immediately.\n##\n## If using the @qcode{\"Events\"} option then three additional outputs may be\n## returned.  @var{te} holds the time when an Event function returned a zero.\n## @var{ye} holds the value of the solution at time @var{te}.  @var{ie}\n## contains an index indicating which Event function was triggered in the case\n## of multiple Event functions.\n##\n## Example: Solve @nospell{Robertson's} equations:\n##\n## @smallexample\n## @group\n## function r = robertson_dae (@var{t}, @var{y}, @var{yp})\n##   r = [ -(@var{yp}(1) + 0.04*@var{y}(1) - 1e4*@var{y}(2)*@var{y}(3))\n##         -(@var{yp}(2) - 0.04*@var{y}(1) + 1e4*@var{y}(2)*@var{y}(3) + 3e7*@var{y}(2)^2)\n##         @var{y}(1) + @var{y}(2) + @var{y}(3) - 1 ];\n## endfunction\n## [@var{t},@var{y}] = ode15i (@@robertson_dae, [0, 1e3], [1; 0; 0], [-1e-4; 1e-4; 0]);\n## @end group\n## @end smallexample\n## @seealso{decic, odeset, odeget}\n## @end deftypefn\n\nfunction varargout = ode15i (fcn, trange, y0, yp0, varargin)\n\n  if (nargin < 4)\n    print_usage ();\n  endif\n\n  solver = \"ode15i\";\n\n  n = numel (y0);\n\n  if (nargin > 4)\n   options = varargin{1};\n  else\n   options = odeset ();\n  endif\n\n  ## Check fcn, trange, y0, yp0\n  fcn = check_default_input (fcn, trange, solver, y0, yp0);\n\n  if (! isempty (options.Jacobian))\n    if (ischar (options.Jacobian))\n      if (! exist (options.Jacobian))\n        error (\"Octave:invalid-input-arg\",\n               ['ode15i: \"Jacobian\" function \"' options.Jacobian '\" not found']);\n      endif\n      options.Jacobian = str2func (options.Jacobian);\n    endif\n  endif\n\n  if (! isempty (options.OutputFcn))\n    if (ischar (options.OutputFcn))\n      if (! exist (options.OutputFcn))\n        error (\"Octave:invalid-input-arg\",\n               ['ode15i: \"OutputFcn\" function \"' options.OutputFcn '\" not found']);\n      endif\n      options.OutputFcn = str2func (options.OutputFcn);\n    endif\n    if (! is_function_handle (options.OutputFcn))\n      error (\"Octave:invalid-input-arg\",\n             'ode15i: \"OutputFcn\" must be a valid function handle');\n    endif\n  endif\n\n  if (! isempty (options.Events))\n    if (ischar (options.Events))\n      if (! exist (options.Events))\n        error (\"Octave:invalid-input-arg\",\n               ['ode15i: \"Events\" function \"' options.Events '\" not found']);\n      endif\n      options.Events = str2func (options.Events);\n    endif\n    if (! is_function_handle (options.Events))\n      error (\"Octave:invalid-input-arg\",\n             'ode15i: \"Events\" must be a valid function handle');\n    endif\n  endif\n\n  [defaults, classes, attributes] = odedefaults (n, trange(1), trange(end));\n\n  persistent ignorefields = {\"NonNegative\", \"Mass\", ...\n                             \"MStateDependence\", \"MvPattern\", ...\n                             \"MassSingular\", \"InitialSlope\", \"BDF\"};\n\n  defaults   = rmfield (defaults, ignorefields);\n  classes    = rmfield (classes, ignorefields);\n  attributes = rmfield (attributes, ignorefields);\n\n  classes    = odeset (classes, \"Vectorized\", {});\n  attributes = odeset (attributes, \"Jacobian\", {}, \"Vectorized\", {});\n\n  options = odemergeopts (\"ode15i\", options, defaults,\n                          classes, attributes, solver);\n\n  ## Jacobian\n  options.havejac       = false;\n  options.havejacsparse = false;\n  options.havejacfcn    = false;\n\n  if (! isempty (options.Jacobian))\n    options.havejac = true;\n    if (iscell (options.Jacobian))\n      if (numel (options.Jacobian) == 2)\n        J1 = options.Jacobian{1};\n        J2 = options.Jacobian{2};\n        if (   ! issquare (J1) || ! issquare (J2)\n            || rows (J1) != n || rows (J2) != n\n            || ! isnumeric (J1) || ! isnumeric (J2)\n            || ! isreal (J1) || ! isreal (J2))\n          error (\"Octave:invalid-input-arg\",\n                 'ode15i: \"Jacobian\" matrices must be real square matrices');\n        endif\n        if (issparse (J1) && issparse (J2))\n          options.havejacsparse = true;  # Jac is sparse cell\n        endif\n      else\n        error (\"Octave:invalid-input-arg\",\n               'ode15i: invalid value assigned to field \"Jacobian\"');\n      endif\n\n    elseif (is_function_handle (options.Jacobian))\n      options.havejacfcn = true;\n      if (nargin (options.Jacobian) == 3)\n        [J1, J2] = options.Jacobian (trange(1), y0, yp0);\n\n        if (   ! issquare (J1) || rows (J1) != n\n            || ! isnumeric (J1) || ! isreal (J1)\n            || ! issquare (J2) || rows (J2) != n\n            || ! isnumeric (J2) || ! isreal (J2))\n          error (\"Octave:invalid-input-arg\",\n                 'ode15i: \"Jacobian\" function must evaluate to a real square matrix');\n        endif\n        if (issparse (J1) && issparse (J2))\n          options.havejacsparse = true;  # Jac is sparse fcn\n        endif\n      else\n        error (\"Octave:invalid-input-arg\",\n               'ode15i: invalid value assigned to field \"Jacobian\"');\n      endif\n    else\n      error (\"Octave:invalid-input-arg\",\n             'ode15i: \"Jacobian\" field must be a function handle or 2-element cell array of square matrices');\n    endif\n  endif\n\n  ## Abstol and Reltol\n  options.haveabstolvec = false;\n\n  if (numel (options.AbsTol) != 1 && numel (options.AbsTol) != n)\n    error (\"Octave:invalid-input-arg\",\n           'ode15i: invalid value assigned to field \"AbsTol\"');\n\n  elseif (numel (options.AbsTol) == n)\n    options.haveabstolvec = true;\n  endif\n\n  ## Stats\n  options.havestats = strcmpi (options.Stats, \"on\");\n\n  ## Don't use Refine when the output is a structure\n  if (nargout == 1)\n    options.Refine = 1;\n  endif\n\n  ## OutputFcn and OutputSel\n  if (isempty (options.OutputFcn) && nargout == 0)\n    options.OutputFcn = @odeplot;\n    options.haveoutputfunction = true;\n  else\n    options.haveoutputfunction = ! isempty (options.OutputFcn);\n  endif\n\n  options.haveoutputselection = ! isempty (options.OutputSel);\n  if (options.haveoutputselection)\n    options.OutputSel = options.OutputSel - 1;\n  endif\n\n  ## Events\n  options.haveeventfunction = ! isempty (options.Events);\n\n  ## 3 arguments in the event callback of ode15i\n  [t, y, te, ye, ie] = __ode15__ (fcn, trange, y0, yp0, options, 3);\n\n  if (nargout == 2)\n    varargout{1} = t;\n    varargout{2} = y;\n  elseif (nargout == 1)\n    varargout{1}.x = t.';  # Time stamps saved in field x (row vector)\n    varargout{1}.y = y.';  # Results are saved in field y (row vector)\n    varargout{1}.solver = solver;\n    if (options.haveeventfunction)\n      varargout{1}.xe = te.';  # Time info when an event occurred\n      varargout{1}.ye = ye.';  # Results when an event occurred\n      varargout{1}.ie = ie.';  # Index info which event occurred\n    endif\n  elseif (nargout > 2)\n    varargout = cell (1,5);\n    varargout{1} = t;\n    varargout{2} = y;\n    if (options.haveeventfunction)\n      varargout{3} = te;  # Time info when an event occurred\n      varargout{4} = ye;  # Results when an event occurred\n      varargout{5} = ie;  # Index info which event occurred\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Solve Robertson's equations with ode15i\n%! fcn = @(t, y, yp) [-(yp(1) + 0.04*y(1) - 1e4*y(2)*y(3));\n%!                    -(yp(2) - 0.04*y(1) + 1e4*y(2)*y(3) + 3e7*y(2)^2);\n%!                    y(1) + y(2) + y(3) - 1];\n%!\n%! opt = odeset (\"RelTol\", 1e-4, \"AbsTol\", [1e-8, 1e-14, 1e-6]);\n%! y0 = [1; 0; 0];\n%! yp0 = [-1e-4; 1e-4; 0];\n%! tspan = [eps 4*logspace(-6, 6)];\n%!\n%! [t, y] = ode15i (fcn, tspan, y0, yp0, opt);\n%!\n%! y(:,2) = 1e4 * y(:, 2);\n%! figure (2);\n%! semilogx (t, y, \"o\");\n%! xlabel (\"time\");\n%! ylabel (\"species concentration\");\n%! title (\"Robertson DAE problem with a Conservation Law\");\n%! legend (\"y1\", \"y2\", \"y3\");\n\n%!function res = rob (t, y, yp)\n%!  res =[-(yp(1) + 0.04*y(1) - 1e4*y(2)*y(3));\n%!        -(yp(2) - 0.04*y(1) + 1e4*y(2)*y(3) + 3e7*y(2)^2);\n%!        y(1) + y(2) + y(3) - 1];\n%!endfunction\n%!\n%!function ref = fref ()\n%!  ref = [100, 0.617234887614937, 0.000006153591397, 0.382758958793666];\n%!endfunction\n%!\n%!function ref2 = fref2 ()\n%!  ref2 = [4e6 0 0 1];\n%!endfunction\n%!\n%!function [DFDY, DFDYP] = jacfundense (t, y, yp)\n%!  DFDY = [-0.04,           1e4*y(3),  1e4*y(2);\n%!           0.04, -1e4*y(3)-6e7*y(2), -1e4*y(2);\n%!              1,                  1,         1];\n%!  DFDYP = [-1,  0, 0;\n%!            0, -1, 0;\n%!            0,  0, 0];\n%!endfunction\n%!\n%!function [DFDY, DFDYP] = jacfunsparse (t, y, yp)\n%!  DFDY = sparse ([-0.04,           1e4*y(3),  1e4*y(2);\n%!                   0.04, -1e4*y(3)-6e7*y(2), -1e4*y(2);\n%!                      1,                  1,         1]);\n%!  DFDYP = sparse ([-1,  0, 0;\n%!                    0, -1, 0;\n%!                    0,  0, 0]);\n%!endfunction\n%!\n%!function [DFDY, DFDYP] = jacwrong (t, y, yp)\n%!  DFDY = [-0.04,           1e4*y(3);\n%!           0.04, -1e4*y(3)-6e7*y(2)];\n%!  DFDYP = [-1,  0;\n%!            0, -1];\n%!endfunction\n%!\n%!function [DFDY, DFDYP, A] = jacwrong2 (t, y, yp)\n%!  DFDY = [-0.04,           1e4*y(3),  1e4*y(2);\n%!           0.04, -1e4*y(3)-6e7*y(2), -1e4*y(2);\n%!              1,                  1,         1];\n%!  DFDYP = [-1,  0, 0;\n%!            0, -1, 0;\n%!            0,  0, 0];\n%!  A = DFDY;\n%!endfunction\n%!\n%!function [val, isterminal, direction] = ff (t, y, yp)\n%!  isterminal = [0, 1];\n%!  if (t < 1e1)\n%!    val = [-1, -2];\n%!  else\n%!    val = [1, 3];\n%!  endif\n%!\n%!  direction = [1, 0];\n%!endfunction\n\n## anonymous function instead of real function\n%!testif HAVE_SUNDIALS\n%! ref = 0.049787079136413;\n%! ff = @(t, u, udot)  udot + 3 * u;\n%! [t, y] = ode15i (ff, 0:1, 1, -3);\n%! assert ([t(end), y(end)], [1, ref], 1e-3);\n\n## function passed as string\n%!testif HAVE_SUNDIALS\n%! [t, y] = ode15i (\"rob\", [0, 100, 200], [1; 0; 0], [-1e-4; 1e-4; 0]);\n%! assert ([t(2), y(2,:)], fref, 1e-3);\n\n##  solve in intermediate step\n%!testif HAVE_SUNDIALS\n%! [t, y] = ode15i (@rob, [0, 100, 200], [1; 0; 0], [-1e-4; 1e-4; 0]);\n%! assert ([t(2), y(2,:)], fref, 1e-3);\n\n## numel(trange) = 2 final value\n%!testif HAVE_SUNDIALS\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0]);\n%! assert ([t(end), y(end,:)], fref, 1e-5);\n\n## With empty options\n%!testif HAVE_SUNDIALS\n%! opt = odeset ();\n%! [t, y] = ode15i (@rob, [0, 1e6, 2e6, 3e6, 4e6], [1; 0; 0],\n%!                  [-1e-4; 1e-4; 0], opt);\n%! assert ([t(end), y(end,:)], fref2, 1e-3);\n%! opt = odeset ();\n\n## Without options\n%!testif HAVE_SUNDIALS\n%! [t, y] = ode15i (@rob, [0, 1e6, 2e6, 3e6, 4e6], [1; 0; 0],[-1e-4; 1e-4; 0]);\n%! assert ([t(end), y(end,:)], fref2, 1e-3);\n\n## InitialStep option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"InitialStep\", 1e-8);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert (t(2)-t(1), 1e-8, 1e-9);\n\n## MaxStep option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MaxStep\", 1e-3);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0]);\n%! assert (t(5)-t(4), 1e-3, 1e-3);\n\n## AbsTol scalar option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"AbsTol\", 1e-8);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert ([t(end), y(end,:)], fref, 1e-3);\n\n## AbsTol scalar and RelTol option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"AbsTol\", 1e-8, \"RelTol\", 1e-6);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert ([t(end), y(end,:)], fref, 1e-3);\n\n## AbsTol vector option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"AbsTol\", [1e-8, 1e-14, 1e-6]);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert ([t(end), y(end,:)], fref, 1e-3);\n\n## AbsTol vector and RelTol option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"AbsTol\", [1e-8, 1e-14,1e-6], \"RelTol\", 1e-6);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4;1e-4;0], opt);\n%! assert ([t(end), y(end,:)], fref, 1e-3);\n\n## RelTol option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"RelTol\", 1e-6);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert ([t(end), y(end,:)], fref, 1e-3);\n\n## Jacobian fcn dense\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Jacobian\", @jacfundense);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert ([t(end), y(end,:)], fref, 1e-3);\n\n## Jacobian fcn dense as string\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Jacobian\", \"jacfundense\");\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert ([t(end), y(end,:)], fref, 1e-3);\n\n## Jacobian fcn sparse\n%!testif HAVE_SUNDIALS_SUNLINSOL_KLU\n%! opt = odeset (\"Jacobian\", @jacfunsparse, \"AbsTol\", 1e-7, \"RelTol\", 1e-7);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert ([t(end), y(end,:)], fref, 1e-3);\n\n## Solve in backward direction starting at t=100\n%!testif HAVE_SUNDIALS\n%! YPref = [-0.001135972751027; -0.000000027483627; 0.001136000234654];\n%! Yref = [0.617234887614937, 0.000006153591397, 0.382758958793666];\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0]);\n%! [t2, y2] = ode15i (@rob, [100, 0], Yref', YPref);\n%! assert ([t2(end), y2(end,:)], [0, 1, 0, 0], 2e-2);\n\n## Solve in backward direction with MaxStep option\n%!#testif HAVE_SUNDIALS\n%! YPref = [-0.001135972751027; -0.000000027483627; 0.001136000234654];\n%! Yref = [0.617234887614937, 0.000006153591397, 0.382758958793666];\n%! opt = odeset (\"MaxStep\", 1e-2);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0]);\n%! [t2, y2] = ode15i (@rob, [100, 0], Yref', YPref, opt);\n%! assert ([t2(end), y2(end,:)], [0, 1, 0, 0], 2e-2);\n%! assert (t2(9)-t2(10), 1e-2, 1e-2);\n\n## Solve in backward direction starting with intermediate step\n%!#testif HAVE_SUNDIALS\n%! YPref = [-0.001135972751027; -0.000000027483627; 0.001136000234654];\n%! Yref = [0.617234887614937, 0.000006153591397, 0.382758958793666];\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0]);\n%! [t2, y2] = ode15i (@rob, [100, 5, 0], Yref', YPref);\n%! assert ([t2(end), y2(end,:)], [0, 1, 0, 0], 2e-2);\n\n## Refine\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Refine\", 3);\n%! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0]);\n%! [t2, y2] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert (numel (t2), numel (t) * 3, 3);\n\n## Refine ignored if numel (trange) > 2\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Refine\", 3);\n%! [t, y] = ode15i (@rob, [0, 10, 100], [1; 0; 0], [-1e-4; 1e-4; 0]);\n%! [t2, y2] = ode15i (@rob, [0, 10, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert (numel (t2), numel (t));\n\n## Events option add further elements in sol\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Events\", @ff);\n%! sol = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);\n%! assert (isfield (sol, \"ie\"));\n%! assert (sol.ie, [1, 2]);\n%! assert (isfield (sol, \"xe\"));\n%! assert (isfield (sol, \"ye\"));\n%! assert (sol.x(end), 10, 1);\n\n## Events option, five output arguments\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Events\", @ff);\n%! [t, y, te, ye, ie] = ode15i (@rob, [0, 100], [1; 0; 0],\n%!                              [-1e-4; 1e-4; 0], opt);\n%! assert (t(end), 10, 1);\n%! assert (te, [10; 10], 0.2);\n%! assert (ie, [1; 2]);\n\n## Initial solutions as row vectors\n%!testif HAVE_SUNDIALS\n%! A = eye (2);\n%! [tout, yout] = ode15i (@(t, y, yp) A * y - A * yp, ...\n%! [0, 1], [1, 1], [1, 1]);\n%! assert (size (yout), [20, 2]);\n\n%!testif HAVE_SUNDIALS\n%! A = eye (2);\n%! [tout, yout] = ode15i (@(t, y, yp) A * y - A * yp, ...\n%! [0, 1], [1, 1], [1; 1]);\n%! assert (size (yout), [20, 2]);\n\n## Jacobian fcn wrong dimension\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Jacobian\", @jacwrong);\n%! fail (\"[t, y] = ode15i (@rob, [0, 4e6], [1; 0; 0], [-1e-4; 1e-4; 0], opt)\",\n%!       '\"Jacobian\" function must evaluate to a real square matrix');\n\n## Jacobian cell dense wrong dimension\n%!testif HAVE_SUNDIALS\n%! DFDY = [-0.04, 1;\n%!          0.04, 1];\n%! DFDYP = [-1,  0, 0;\n%!           0, -1, 0;\n%!           0,  0, 0];\n%! opt = odeset (\"Jacobian\", {DFDY, DFDYP});\n%! fail (\"[t, y] = ode15i (@rob, [0, 4e6], [1; 0; 0], [-1e-4; 1e-4; 0], opt)\",\n%!       '\"Jacobian\" matrices must be real square matrices');\n\n## Jacobian cell sparse wrong dimension\n%!testif HAVE_SUNDIALS_SUNLINSOL_KLU\n%! DFDY = sparse ([-0.04, 1;\n%!                  0.04, 1]);\n%! DFDYP = sparse ([-1,  0, 0;\n%!                   0, -1, 0;\n%!                   0,  0, 0]);\n%! opt = odeset (\"Jacobian\", {DFDY, DFDYP});\n%! fail (\"[t, y] = ode15i (@rob, [0, 4e6], [1; 0; 0], [-1e-4; 1e-4; 0], opt)\",\n%!       '\"Jacobian\" matrices must be real square matrices');\n\n## Jacobian cell wrong number of matrices\n%!testif HAVE_SUNDIALS\n%! A = [1 2 3; 4 5 6; 7 8 9];\n%! opt = odeset (\"Jacobian\", {A,A,A});\n%! fail (\"[t, y] = ode15i (@rob, [0, 4e6], [1; 0; 0], [-1e-4; 1e-4; 0], opt)\",\n%!       'invalid value assigned to field \"Jacobian\"');\n\n## Jacobian single matrix\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Jacobian\", [1 2 3; 4 5 6; 7 8 9]);\n%! fail (\"[t, y] = ode15i (@rob, [0, 4e6], [1; 0; 0], [-1e-4; 1e-4; 0], opt)\",\n%!       '\"Jacobian\" field must be a function handle or 2-element cell array of square matrices');\n\n## Jacobian single matrix wrong dimension\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Jacobian\", [1 2 3; 4 5 6]);\n%! fail (\"[t, y] = ode15i (@rob, [0, 4e6], [1; 0; 0], [-1e-4; 1e-4; 0], opt)\",\n%!       '\"Jacobian\" field must be a function handle or 2-element cell array of square matrices');\n\n## Jacobian strange field\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Jacobian\", \"_5yVNhWVJWJn47RKnzxPsyb_\");\n%! fail (\"[t, y] = ode15i (@rob, [0, 4e6], [1; 0; 0], [-1e-4; 1e-4; 0], opt)\",\n%!       '\"Jacobian\" function \"_5yVNhWVJWJn47RKnzxPsyb_\" not found');\n\n%!function ydot = fcn (t, y, yp)\n%!  ydot = [y - yp];\n%!endfunction\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i ()\", \"Invalid call to ode15i\");\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i (1)\", \"Invalid call to ode15i\");\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i (1, 1)\", \"Invalid call to ode15i\");\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i (1, 1, 1)\", \"Invalid call to ode15i\");\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i (1, 1, 1, 1)\", \"ode15i: fcn must be of class:\");\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i (1, 1, 1, 1, 1)\", \"ode15i: fcn must be of class:\");\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i (1, 1, 1, 1, 1, 1)\", \"ode15i: fcn must be of class:\");\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i (@fcn, 1, 1, 1)\",\n%!       \"ode15i: invalid value assigned to field 'trange'\");\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i (@fcn, [1, 1], 1, 1)\",\n%!       \"ode15i: invalid value assigned to field 'trange'\");\n\n%!testif HAVE_SUNDIALS\n%! fail (\"ode15i (@fcn, [1, 2], 1, [1, 2])\",\n%!       \"ode15i: y0 must have 2 elements\");\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"RelTol\", \"_5yVNhWVJWJn47RKnzxPsyb_\");\n%! fail (\"[t, y] = ode15i (@fcn, [0, 2], 2, 2, opt)\",\n%!       \"ode15i: RelTol must be of class:\");\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"RelTol\", [1, 2]);\n%! fail (\"[t, y] = ode15i (@fcn, [0, 2], 2, 2, opt)\",\n%!       \"ode15i: RelTol must be scalar\");\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"RelTol\", -2);\n%! fail (\"[t, y] = ode15i (@fcn, [0, 2], 2, 2, opt)\",\n%!       \"ode15i: RelTol must be positive\");\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"AbsTol\", \"_5yVNhWVJWJn47RKnzxPsyb_\");\n%! fail (\"[t, y] = ode15i (@fcn, [0, 2], 2, 2, opt)\",\n%!       \"ode15i: AbsTol must be of class:\");\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"AbsTol\", -1);\n%! fail (\"[t, y] = ode15i (@fcn, [0, 2], 2, 2, opt)\",\n%!       \"ode15i: AbsTol must be positive\");\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"AbsTol\", [1, 1, 1]);\n%! fail (\"[t, y] = ode15i (@fcn, [0, 2], 2, 2, opt)\",\n%!       'ode15i: invalid value assigned to field \"AbsTol\"');\n\n%!testif HAVE_SUNDIALS\n%! A = zeros (2);\n%! fail (\"ode15i (@(t, y, yp) A * y - A * yp, [0, 1], eye (2), [1, 1])\",\n%!       \"ode15i: Y0 must be a numeric vector\");\n\n%!testif HAVE_SUNDIALS\n%! A = zeros (2);\n%! fail (\"ode15i (@(t, y, yp) A * y - A * yp, [0, 1], [1, 1], eye (2))\",\n%!       \"ode15i: YP0 must be a numeric vector\");\n"
  },
  {
    "path": "scripts/ode/ode15s.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{t}, @var{y}] =} ode15s (@var{fcn}, @var{trange}, @var{y0})\n## @deftypefnx {} {[@var{t}, @var{y}] =} ode15s (@var{fcn}, @var{trange}, @var{y0}, @var{ode_opt})\n## @deftypefnx {} {[@var{t}, @var{y}, @var{te}, @var{ye}, @var{ie}] =} ode15s (@dots{})\n## @deftypefnx {} {@var{solution} =} ode15s (@dots{})\n## @deftypefnx {} {} ode15s (@dots{})\n## Solve a set of stiff Ordinary Differential Equations (ODEs) or stiff\n## semi-explicit index 1 Differential Algebraic Equations (DAEs).\n##\n## @code{ode15s} uses a variable step, variable order BDF (Backward\n## Differentiation Formula) method that ranges from order 1 to 5.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function that defines the ODE: @code{y' = f(t,y)}.  The function\n## must accept two inputs where the first is time @var{t} and the second is a\n## column vector of unknowns @var{y}.\n##\n## @var{trange} specifies the time interval over which the ODE will be\n## evaluated.  Typically, it is a two-element vector specifying the initial and\n## final times (@code{[tinit, tfinal]}).  If there are more than two elements\n## then the solution will also be evaluated at these intermediate time\n## instances.\n##\n## @var{init} contains the initial value for the unknowns.  If it is a row\n## vector then the solution @var{y} will be a matrix in which each column is\n## the solution for the corresponding initial value in @var{init}.\n##\n## The optional fourth argument @var{ode_opt} specifies non-default options to\n## the ODE solver.  It is a structure generated by @code{odeset}.\n##\n## The function typically returns two outputs.  Variable @var{t} is a\n## column vector and contains the times where the solution was found.  The\n## output @var{y} is a matrix in which each column refers to a different\n## unknown of the problem and each row corresponds to a time in @var{t}.\n##\n## The output can also be returned as a structure @var{solution} which has a\n## field @var{x} containing a row vector of times where the solution was\n## evaluated and a field @var{y} containing the solution matrix such that each\n## column corresponds to a time in @var{x}.  Use\n## @w{@code{fieldnames (@var{solution})}}@ to see the other fields and\n## additional information returned.\n##\n## If no output arguments are requested, and no @qcode{\"OutputFcn\"} is\n## specified in @var{ode_opt}, then the @qcode{\"OutputFcn\"} is set to\n## @code{odeplot} and the results of the solver are plotted immediately.\n##\n## If using the @qcode{\"Events\"} option then three additional outputs may be\n## returned.  @var{te} holds the time when an Event function returned a zero.\n## @var{ye} holds the value of the solution at time @var{te}.  @var{ie}\n## contains an index indicating which Event function was triggered in the case\n## of multiple Event functions.\n##\n## Example: Solve @nospell{Robertson's} equations:\n##\n## @smallexample\n## @group\n## function r = robertson_dae (@var{t}, @var{y})\n##   r = [ -0.04*@var{y}(1) + 1e4*@var{y}(2)*@var{y}(3)\n##          0.04*@var{y}(1) - 1e4*@var{y}(2)*@var{y}(3) - 3e7*@var{y}(2)^2\n##               @var{y}(1) + @var{y}(2) + @var{y}(3) - 1 ];\n## endfunction\n## opt = odeset (\"Mass\", [1 0 0; 0 1 0; 0 0 0], \"MStateDependence\", \"none\");\n## [@var{t},@var{y}] = ode15s (@@robertson_dae, [0, 1e3], [1; 0; 0], opt);\n## @end group\n## @end smallexample\n## @seealso{decic, odeset, odeget, ode23, ode45}\n## @end deftypefn\n\nfunction varargout = ode15s (fcn, trange, y0, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  solver = \"ode15s\";\n  ## Check fcn, trange, y0, yp0\n  fcn = check_default_input (fcn, trange, solver, y0);\n\n  n = numel (y0);\n\n  if (nargin > 3)\n   options = varargin{1};\n  else\n   options = odeset ();\n  endif\n\n  if (! isempty (options.Mass))\n    if (ischar (options.Mass))\n      if (! exist (options.Mass))\n        error (\"Octave:invalid-input-arg\",\n               ['ode15s: \"Mass\" function \"' options.Mass '\" not found']);\n      endif\n      options.Mass = str2func (options.Mass);\n    endif\n    if (! is_function_handle (options.Mass) && ! isnumeric (options.Mass))\n      error (\"Octave:invalid-input-arg\",\n             'ode15s: \"Mass\" field must be a function handle or square matrix');\n    endif\n  endif\n\n  if (! isempty (options.Jacobian))\n    if (ischar (options.Jacobian))\n      if (! exist (options.Jacobian))\n        error (\"Octave:invalid-input-arg\",\n               ['ode15s: \"Jacobian\" function \"' options.Jacobian '\" not found']);\n      endif\n      options.Jacobian = str2func (options.Jacobian);\n    endif\n    if (! is_function_handle (options.Jacobian)\n        && ! isnumeric (options.Jacobian))\n      error (\"Octave:invalid-input-arg\",\n             'ode15s: \"Jacobian\" field must be a function handle or square matrix');\n    endif\n  endif\n\n  if (! isempty (options.OutputFcn))\n    if (ischar (options.OutputFcn))\n      if (! exist (options.OutputFcn))\n        error (\"Octave:invalid-input-arg\",\n               ['ode15s: \"OutputFcn\" function \"' options.OutputFcn '\" not found']);\n      endif\n      options.OutputFcn = str2func (options.OutputFcn);\n    endif\n    if (! is_function_handle (options.OutputFcn))\n      error (\"Octave:invalid-input-arg\",\n             'ode15s: \"OutputFcn\" must be a valid function handle');\n    endif\n  endif\n\n  if (! isempty (options.Events))\n    if (ischar (options.Events))\n      if (! exist (options.Events))\n        error (\"Octave:invalid-input-arg\",\n               ['ode15s: \"Events\" function \"' options.Events '\" not found']);\n      endif\n      options.Events = str2func (options.Events);\n    endif\n    if (! is_function_handle (options.Events))\n      error (\"Octave:invalid-input-arg\",\n             'ode15s: \"Events\" must be a valid function handle');\n    endif\n  endif\n\n  [defaults, classes, attributes] = odedefaults (n, trange(1), trange(end));\n\n  classes    = odeset (classes, \"Vectorized\", {});\n  attributes = odeset (attributes, \"Jacobian\", {}, \"Vectorized\", {});\n\n  options = odemergeopts (\"ode15s\", options, defaults,\n                          classes, attributes, solver);\n\n  ## Mass\n  options.havemassfcn    = false;\n  options.havestatedep   = false;\n  options.havetimedep    = false;\n  options.havemasssparse = false;\n\n  if (! isempty (options.Mass))\n    if (is_function_handle (options.Mass))\n      options.havemassfcn = true;\n      if (nargin (options.Mass) == 2)\n        options.havestatedep = true;\n        M = options.Mass (trange(1), y0);\n        if (! issquare (M) || rows (M) != n || ! isnumeric (M) || ! isreal (M))\n          error (\"Octave:invalid-input-arg\",\n                 'ode15s: \"Mass\" function must evaluate to a real square matrix');\n        endif\n        options.havemasssparse = issparse (M);\n      elseif (nargin (options.Mass) == 1)\n        options.havetimedep = true;\n        M = options.Mass (trange(1));\n        if (! issquare (M) || rows (M) != n || ! isnumeric (M) || ! isreal (M))\n          error (\"Octave:invalid-input-arg\",\n                 'ode15s: \"Mass\" function must evaluate to a real square matrix');\n        endif\n        options.havemasssparse = issparse (M);\n      else\n        error (\"Octave:invalid-input-arg\",\n               'ode15s: invalid value assigned to field \"Mass\"');\n      endif\n    else    # matrix Mass input\n      if (! issquare (options.Mass) || rows (options.Mass) != n\n          || ! isnumeric (options.Mass) || ! isreal (options.Mass))\n        error (\"Octave:invalid-input-arg\",\n               'ode15s: \"Mass\" matrix must be a real square matrix');\n      endif\n      options.havemasssparse = issparse (options.Mass);\n    endif\n  endif\n\n  ## Jacobian\n  options.havejac       = false;\n  options.havejacsparse = false;\n  options.havejacfcn    = false;\n\n  if (! isempty (options.Jacobian))\n    options.havejac = true;\n    if (is_function_handle (options.Jacobian))\n      options.havejacfcn = true;\n      if (nargin (options.Jacobian) == 2)\n        A = options.Jacobian (trange(1), y0);\n        if (! issquare (A) || rows (A) != n || ! isnumeric (A) || ! isreal (A))\n          error (\"Octave:invalid-input-arg\",\n                 'ode15s: \"Jacobian\" function must evaluate to a real square matrix');\n        endif\n        options.havejacsparse = issparse (A);  # Jac is sparse fcn\n      else\n        error (\"Octave:invalid-input-arg\",\n               'ode15s: invalid value assigned to field \"Jacobian\"');\n      endif\n    else  # matrix input\n      if (! issquare (options.Jacobian) || rows (options.Jacobian) != n\n          || ! isnumeric (options.Jacobian) || ! isreal (options.Jacobian))\n        error (\"Octave:invalid-input-arg\",\n               'ode15s: \"Jacobian\" matrix must be a real square matrix');\n      endif\n      options.havejacsparse = issparse (options.Jacobian);\n    endif\n  endif\n\n  ## Derivative of M(t,y) for implicit problem not implemented yet\n  if (! isempty (options.Mass) && ! isempty (options.Jacobian))\n    if (options.MStateDependence != \"none\" || options.havestatedep == true)\n      options.havejac = false;\n      options.Jacobian = [];\n      warning (\"ode15s:mass_state_dependent_provided\",\n              [\"with MStateDependence != 'none' an internal\", ...\n               \" approximation of the Jacobian Matrix will be used.\", ...\n               \"  Set MStateDependence equal to 'none' if you want\", ...\n               \" to provide a constant or time-dependent Jacobian\"]);\n    endif\n  endif\n\n  ## Use sparse methods only if all matrices are sparse\n  if (! isempty (options.Mass)) && (! options.havemasssparse)\n    options.havejacsparse = false;\n  endif\n\n  ## If Mass or Jacobian is fcn, then new Jacobian is fcn\n  if (options.havejac)\n    if (options.havejacfcn || options.havetimedep)\n      options.Jacobian = @ (t, y, yp) wrapjacfcn (t, y, yp,\n                                                  options.Jacobian,\n                                                  options.Mass,\n                                                  options.havetimedep,\n                                                  options.havejacfcn);\n      options.havejacfcn = true;\n    else   # All matrices are constant\n      if (! isempty (options.Mass))\n        options.Jacobian = {[- options.Jacobian], [options.Mass]};\n      else\n        if (options.havejacsparse)\n          options.Jacobian = {[- options.Jacobian], speye(n)};\n        else\n          options.Jacobian = {[- options.Jacobian], eye(n)};\n        endif\n      endif\n\n    endif\n  endif\n\n  ## Abstol and Reltol\n  options.haveabstolvec = false;\n\n  if (numel (options.AbsTol) != 1 && numel (options.AbsTol) != n)\n    error (\"Octave:invalid-input-arg\",\n           'ode15s: invalid value assigned to field \"AbsTol\"');\n  elseif (numel (options.AbsTol) == n)\n    options.haveabstolvec = true;\n  endif\n\n  ## Stats\n  options.havestats = strcmpi (options.Stats, \"on\");\n\n  ## Don't use Refine when the output is a structure\n  if (nargout == 1)\n    options.Refine = 1;\n  endif\n\n  ## OutputFcn and OutputSel\n  if (isempty (options.OutputFcn) && nargout == 0)\n    options.OutputFcn = @odeplot;\n    options.haveoutputfunction = true;\n  else\n    options.haveoutputfunction = ! isempty (options.OutputFcn);\n  endif\n\n  options.haveoutputselection = ! isempty (options.OutputSel);\n  if (options.haveoutputselection)\n    options.OutputSel = options.OutputSel - 1;\n  endif\n\n  ## Events\n  options.haveeventfunction = ! isempty (options.Events);\n\n  yp0 = options.InitialSlope;\n\n  ## 2 arguments in the event callback of ode15s\n  [t, y, te, ye, ie] = __ode15__ (@ (t, y, yp) wrap (t, y, yp, options.Mass,\n                                                     options.havetimedep,\n                                                     options.havestatedep,\n                                                     fcn),\n                                  trange, y0, yp0, options, 2);\n\n  if (nargout == 2)\n    varargout{1} = t;\n    varargout{2} = y;\n  elseif (nargout == 1)\n    varargout{1}.x = t.';  # Time stamps saved in field x (row vector)\n    varargout{1}.y = y.';  # Results are saved in field y (row vector)\n    varargout{1}.solver = solver;\n    if (options.haveeventfunction)\n      varargout{1}.xe = te.';  # Time info when an event occurred\n      varargout{1}.ye = ye.';  # Results when an event occurred\n      varargout{1}.ie = ie.';  # Index info which event occurred\n    endif\n  elseif (nargout > 2)\n    varargout = cell (1,5);\n    varargout{1} = t;\n    varargout{2} = y;\n    if (options.haveeventfunction)\n      varargout{3} = te;  # Time info when an event occurred\n      varargout{4} = ye;  # Results when an event occurred\n      varargout{5} = ie;  # Index info which event occurred\n    endif\n  endif\n\nendfunction\n\nfunction res = wrap (t, y, yp, Mass, havetimedep, havestatedep, fcn)\n\n  if (! isempty (Mass) && havestatedep)\n    res = Mass (t, y) * yp - fcn (t, y);\n  elseif (! isempty (Mass) && havetimedep)\n    res = Mass (t) * yp - fcn (t, y);\n  elseif (! isempty (Mass))\n    res = Mass * yp - fcn (t, y);\n  else\n    res = yp - fcn (t, y);\n  endif\n\nendfunction\n\nfunction [jac, jact] = wrapjacfcn (t, y, yp, Jac, Mass,\n                                   havetimedep, havejacfcn)\n\n  if (havejacfcn)\n    jac = - Jac (t, y);\n  else\n    jac = - Jac;\n  endif\n\n  if (! isempty (Mass) && havetimedep)\n    jact = Mass (t);\n  elseif (! isempty (Mass))\n    jact = Mass;\n  else\n    jact = speye (numel (y));\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Solve Robertson's equations with ode15s\n%! fcn = @ (t, y) [-0.04*y(1) + 1e4*y(2).*y(3);\n%!                  0.04*y(1) - 1e4*y(2).*y(3) - 3e7*y(2).^2;\n%!                  y(1) + y(2) + y(3) - 1];\n%!\n%! y0 = [1; 0; 0];\n%! tspan = [eps, 4*logspace(-6, 6)];\n%! M = [1, 0, 0; 0, 1, 0; 0, 0, 0];\n%!\n%! options = odeset (\"RelTol\", 1e-4, \"AbsTol\", [1e-6, 1e-10, 1e-6],\n%!                   \"MStateDependence\", \"none\", \"Mass\", M);\n%!\n%! [t, y] = ode15s (fcn, tspan, y0, options);\n%!\n%! y(:,2) = 1e4 * y(:,2);\n%! figure (2);\n%! semilogx (t, y, \"o\");\n%! xlabel (\"time\");\n%! ylabel (\"species concentration\");\n%! title (\"Robertson DAE problem with a Conservation Law\");\n%! legend (\"y1\", \"y2\", \"y3\");\n\n%!function ydot = fpol (t, y)  # Van der Pol equation\n%!  ydot = [y(2); (1 - y(1)^2) * y(2) - y(1)];\n%!endfunction\n%!\n%!function ref = fref ()       # The computed reference sol\n%!  ref = [0.32331666704577, -1.83297456798624];\n%!endfunction\n%!\n%!function jac = fjac (t, y)   # its Jacobian\n%!  jac = [0, 1; -1 - 2 * y(1) * y(2), 1 - y(1)^2];\n%!endfunction\n%!\n%!function jac = fjcc (t, y)   # sparse type\n%!  jac = sparse ([0, 1; -1 - 2 * y(1) * y(2), 1 - y(1)^2]);\n%!endfunction\n%!\n%!function mas = fmas (t, y)\n%!  mas = [1, 0; 0, 1];           # Dummy mass matrix for tests\n%!endfunction\n%!\n%!function mas = fmsa (t, y)\n%!  mas = sparse ([1, 0; 0, 1]);  # A sparse dummy matrix\n%!endfunction\n%!\n%!function res = rob (t, y)\n%!  res = [-0.04*y(1) + 1e4*y(2).*y(3);\n%!          0.04*y(1) - 1e4*y(2).*y(3) - 3e7*y(2).^2;\n%!          y(1) + y(2) + y(3) - 1];\n%!endfunction\n%!\n%!function refrob = frefrob ()\n%!  refrob = [100, 0.617234887614937, 0.000006153591397, 0.382758958793666];\n%!endfunction\n%!\n%!function [val, isterminal, direction] = feve (t, y)\n%!  isterminal = [0, 1];\n%!  if (t < 1e1)\n%!    val = [-1, -2];\n%!  else\n%!    val = [1, 3];\n%!  endif\n%!\n%!  direction = [1, 0];\n%!endfunction\n%!\n%!function masrob = massdensefunstate (t, y)\n%!  masrob = [1, 0, 0; 0, 1, 0; 0, 0, 0];\n%!endfunction\n%!\n%!function masrob = masssparsefunstate (t, y)\n%!  masrob = sparse ([1, 0, 0; 0, 1, 0; 0, 0, 0]);\n%!endfunction\n%!\n%!function masrob = massdensefuntime (t)\n%!  masrob = [1, 0, 0; 0, 1, 0; 0, 0, 0];\n%!endfunction\n%!\n%!function masrob = masssparsefuntime (t)\n%!  masrob = sparse ([1, 0, 0; 0, 1, 0; 0, 0, 0]);\n%!endfunction\n%!\n%!function jac = jacfundense (t, y)\n%!  jac = [-0.04,           1e4*y(3),  1e4*y(2);\n%!          0.04, -1e4*y(3)-6e7*y(2), -1e4*y(2);\n%!             1,                  1,         1];\n%!endfunction\n%!\n%!function jac = jacfunsparse (t, y)\n%!  jac = sparse ([-0.04,           1e4*y(3),  1e4*y(2);\n%!                  0.04, -1e4*y(3)-6e7*y(2), -1e4*y(2);\n%!                     1,                  1,         1]);\n%!endfunction\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", [1, 0, 0; 0, 1, 0; 0, 0, 0]);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", sparse ([1, 0, 0; 0, 1, 0; 0, 0, 0]));\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", @massdensefunstate);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", @masssparsefunstate);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", \"massdensefuntime\");\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", [1, 0, 0; 0, 1, 0; 0, 0, 0],\n%!               \"Jacobian\", \"jacfundense\");\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", sparse ([1, 0, 0; 0, 1, 0; 0, 0, 0]),\n%!               \"Jacobian\", @jacfundense);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! warning (\"off\", \"ode15s:mass_state_dependent_provided\", \"local\");\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", @massdensefunstate,\n%!               \"Jacobian\", @jacfundense);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! warning (\"off\", \"ode15s:mass_state_dependent_provided\", \"local\");\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", @masssparsefunstate,\n%!               \"Jacobian\", @jacfundense);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", @massdensefuntime,\n%!               \"Jacobian\", @jacfundense);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", \"masssparsefuntime\",\n%!               \"Jacobian\", \"jacfundense\");\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS_SUNLINSOL_KLU\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", [1, 0, 0; 0, 1, 0; 0, 0, 0],\n%!               \"Jacobian\", @jacfunsparse);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS_SUNLINSOL_KLU\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", sparse ([1, 0, 0; 0, 1, 0; 0, 0, 0]),\n%!               \"Jacobian\", @jacfunsparse);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS_SUNLINSOL_KLU\n%! warning (\"off\", \"ode15s:mass_state_dependent_provided\", \"local\");\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", @massdensefunstate,\n%!               \"Jacobian\", @jacfunsparse);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS\n%! warning (\"off\", \"ode15s:mass_state_dependent_provided\", \"local\");\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", @masssparsefunstate,\n%!               \"Jacobian\", @jacfunsparse);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS_SUNLINSOL_KLU\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", @massdensefuntime,\n%!               \"Jacobian\", @jacfunsparse);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n%!testif HAVE_SUNDIALS_SUNLINSOL_KLU\n%! opt = odeset (\"MStateDependence\", \"none\",\n%!               \"Mass\", @masssparsefuntime,\n%!               \"Jacobian\", @jacfunsparse);\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert ([t(end), y(end,:)], frefrob, 1e-3);\n\n## Jacobian as const matrix\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"RelTol\", 1e-4, \"AbsTol\", 1e-5,\n%!               \"Jacobian\", [98, 198; -99, -199]);\n%! [t, y] = ode15s (@(t, y)[98, 198; -99, -199] * (y - [1; 0]),\n%!                 [0, 5], [2; 0], opt);\n%! y1xct = @(t) 2 * exp (-t) - exp (-100 * t) + 1;\n%! y2xct = @(t) - exp (-t) + exp (-100 * t);\n%! assert ([y1xct(t), y2xct(t)], y, 1e-3);\n\n## two output arguments\n%!testif HAVE_SUNDIALS\n%! [t, y] = ode15s (@fpol, [0, 2], [2, 0]);\n%! assert ([t(end), y(end,:)], [2, fref], 1e-2);\n\n## anonymous function instead of real function\n%!testif HAVE_SUNDIALS\n%! fvdb = @(t,y) [y(2); (1 - y(1)^2) * y(2) - y(1)];\n%! [t, y] = ode15s (fvdb, [0, 2], [2, 0]);\n%! assert ([t(end), y(end,:)], [2, fref], 1e-2);\n\n## Solve another anonymous function below zero\n%!testif HAVE_SUNDIALS\n%! ref = [0, 14.77810590694212];\n%! [t, y] = ode15s (@(t,y) y, [-2, 0], 2);\n%! assert ([t(end), y(end,:)], ref, 5e-2);\n\n## InitialStep option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"InitialStep\", 1e-8);\n%! [t, y] = ode15s (@fpol, [0, 0.2], [2, 0], opt);\n%! assert (t(2)-t(1), 1e-8, 1e-9);\n\n## MaxStep option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"MaxStep\", 1e-3);\n%! sol = ode15s (@fpol, [0, 0.2], [2, 0], opt);\n%! assert (sol.x(5)-sol.x(4), 1e-3, 1e-3);\n\n## Solve in backward direction starting at t=0\n%!testif HAVE_SUNDIALS\n%! ref = [-1.205364552835178; 0.951542399860817];\n%! sol = ode15s (@fpol, [0 -2], [2, 0]);\n%! assert ([sol.x(end); sol.y(:,end)], [-2; ref], 5e-3);\n\n## Solve in backward direction starting at t=2\n%!testif HAVE_SUNDIALS\n%! ref = [-1.205364552835178; 0.951542399860817];\n%! sol = ode15s (@fpol, [2, 0 -2], fref);\n%! assert ([sol.x(end); sol.y(:,end)], [-2; ref], 3e-2);\n\n## Solve another anonymous function in backward direction\n%!testif HAVE_SUNDIALS\n%! ref = [-1; 0.367879437558975];\n%! sol = ode15s (@(t,y) y, [0 -1], 1);\n%! assert ([sol.x(end); sol.y(:,end)], ref, 1e-2);\n\n## Solve another anonymous function below zero\n%!testif HAVE_SUNDIALS\n%! ref = [0; 14.77810590694212];\n%! sol = ode15s (@(t,y) y, [-2, 0], 2);\n%! assert ([sol.x(end); sol.y(:,end)], ref, 5e-2);\n\n## Solve in backward direction starting at t=0 with MaxStep option\n%!testif HAVE_SUNDIALS\n%! ref = [-1.205364552835178; 0.951542399860817];\n%! opt = odeset (\"MaxStep\", 1e-3);\n%! sol = ode15s (@fpol, [0 -2], [2, 0], opt);\n%! assert (abs (sol.x(8)-sol.x(7)), 1e-3, 1e-3);\n%! assert ([sol.x(end); sol.y(:,end)], [-2; ref], 1e-3);\n\n## AbsTol option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"AbsTol\", 1e-5);\n%! sol = ode15s (@fpol, [0, 2], [2, 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2, fref].', 4e-3);\n\n## AbsTol and RelTol option\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"AbsTol\", 1e-8, \"RelTol\", 1e-8);\n%! sol = ode15s (@fpol, [0, 2], [2, 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2, fref].', 1e-3);\n\n## RelTol option -- higher accuracy\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"RelTol\", 1e-8);\n%! sol = ode15s (@fpol, [0, 2], [2, 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2, fref].', 1e-4);\n\n## Mass option as function\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Mass\", @fmas, \"MStateDependence\", \"none\");\n%! sol = ode15s (@fpol, [0, 2], [2, 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2, fref].', 3e-3);\n\n## Mass option as matrix\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Mass\", eye (2,2), \"MStateDependence\", \"none\");\n%! sol = ode15s (@fpol, [0, 2], [2, 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2, fref].', 3e-3);\n\n## Mass option as sparse matrix\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Mass\", speye (2), \"MStateDependence\", \"none\");\n%! sol = ode15s (@fpol, [0, 2], [2, 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2, fref].', 3e-3);\n\n## Mass option as function and sparse matrix\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Mass\", \"fmsa\", \"MStateDependence\", \"none\");\n%! sol = ode15s (@fpol, [0, 2], [2, 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2, fref].', 3e-3);\n\n## Refine\n%!testif HAVE_SUNDIALS\n%! opt2 = odeset (\"Refine\", 3, \"Mass\", @massdensefunstate,\n%!                \"MStateDependence\", \"none\");\n%! opt1 = odeset (\"Mass\", @massdensefunstate, \"MStateDependence\", \"none\");\n%! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt1);\n%! [t2, y2] = ode15s (@rob, [0, 100], [1; 0; 0], opt2);\n%! assert (numel (t2), numel (t) * 3, 3);\n\n## Refine ignored if numel (trange) > 2\n%!testif HAVE_SUNDIALS\n%! opt2 = odeset (\"Refine\", 3, \"Mass\", \"massdensefunstate\",\n%!                \"MStateDependence\", \"none\");\n%! opt1 = odeset (\"Mass\", @massdensefunstate, \"MStateDependence\", \"none\");\n%! [t, y] = ode15s (\"rob\", [0, 10, 100], [1; 0; 0], opt1);\n%! [t2, y2] = ode15s (\"rob\", [0, 10, 100], [1; 0; 0], opt2);\n%! assert (numel (t2), numel (t));\n\n## Events option add further elements in sol\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Events\", @feve, \"Mass\", @massdensefunstate,\n%!               \"MStateDependence\", \"none\");\n%! sol = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert (isfield (sol, \"ie\"));\n%! assert (sol.ie, [1, 2]);\n%! assert (isfield (sol, \"xe\"));\n%! assert (isfield (sol, \"ye\"));\n%! assert (sol.x(end), 10, 1);\n\n## Events option, five output arguments\n%!testif HAVE_SUNDIALS\n%! opt = odeset (\"Events\", @feve, \"Mass\", @massdensefunstate,\n%!               \"MStateDependence\", \"none\");\n%! [t, y, te, ye, ie] = ode15s (@rob, [0, 100], [1; 0; 0], opt);\n%! assert (t(end), 10, 1);\n%! assert (te, [10; 10], 0.5);\n%! assert (ie, [1; 2]);\n\n## Initial solution as row vector\n%!testif HAVE_SUNDIALS\n%! A = zeros (2);\n%! [tout, yout] = ode15s (@(t, y) A * y, [0, 1], [1, 1]);\n%! assert (yout, ones (18, 2));\n\n%!testif HAVE_SUNDIALS\n%! A = zeros (2);\n%! fail (\"ode15s (@(t, y) A * y, [0, 1], eye (2))\",\n%!       \"ode15s: Y0 must be a numeric vector\");\n"
  },
  {
    "path": "scripts/ode/ode23.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{t}, @var{y}] =} ode23 (@var{fcn}, @var{trange}, @var{init})\n## @deftypefnx {} {[@var{t}, @var{y}] =} ode23 (@var{fcn}, @var{trange}, @var{init}, @var{ode_opt})\n## @deftypefnx {} {[@var{t}, @var{y}, @var{te}, @var{ye}, @var{ie}] =} ode23 (@dots{})\n## @deftypefnx {} {@var{solution} =} ode23 (@dots{})\n## @deftypefnx {} {} ode23 (@dots{})\n##\n## Solve a set of non-stiff Ordinary Differential Equations (non-stiff ODEs)\n## with the well known explicit @nospell{Bogacki-Shampine} method of order 3.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function that defines the ODE: @code{y' = f(t,y)}.  The function\n## must accept two inputs where the first is time @var{t} and the second is a\n## column vector of unknowns @var{y}.\n##\n## @var{trange} specifies the time interval over which the ODE will be\n## evaluated.  Typically, it is a two-element vector specifying the initial and\n## final times (@code{[tinit, tfinal]}).  If there are more than two elements\n## then the solution will also be evaluated at these intermediate time\n## instances.\n##\n## By default, @code{ode23} uses an adaptive timestep with the\n## @code{integrate_adaptive} algorithm.  The tolerance for the timestep\n## computation may be changed by using the options @qcode{\"RelTol\"} and\n## @qcode{\"AbsTol\"}.\n##\n## @var{init} contains the initial value for the unknowns.  If it is a row\n## vector then the solution @var{y} will be a matrix in which each column is\n## the solution for the corresponding initial value in @var{init}.\n##\n## The optional fourth argument @var{ode_opt} specifies non-default options to\n## the ODE solver.  It is a structure generated by @code{odeset}.\n##\n## The function typically returns two outputs.  Variable @var{t} is a\n## column vector and contains the times where the solution was found.  The\n## output @var{y} is a matrix in which each column refers to a different\n## unknown of the problem and each row corresponds to a time in @var{t}.\n##\n## The output can also be returned as a structure @var{solution} which has a\n## field @var{x} containing a row vector of times where the solution was\n## evaluated and a field @var{y} containing the solution matrix such that each\n## column corresponds to a time in @var{x}.  Use\n## @w{@code{fieldnames (@var{solution})}}@ to see the other fields and\n## additional information returned.\n##\n## If no output arguments are requested, and no @qcode{\"OutputFcn\"} is\n## specified in @var{ode_opt}, then the @qcode{\"OutputFcn\"} is set to\n## @code{odeplot} and the results of the solver are plotted immediately.\n##\n## If using the @qcode{\"Events\"} option then three additional outputs may be\n## returned.  @var{te} holds the time when an Event function returned a zero.\n## @var{ye} holds the value of the solution at time @var{te}.  @var{ie}\n## contains an index indicating which Event function was triggered in the case\n## of multiple Event functions.\n##\n## Example: Solve the @nospell{Van der Pol} equation\n##\n## @example\n## @group\n## fvdp = @@(@var{t},@var{y}) [@var{y}(2); (1 - @var{y}(1)^2) * @var{y}(2) - @var{y}(1)];\n## [@var{t},@var{y}] = ode23 (fvdp, [0, 20], [2, 0]);\n## @end group\n## @end example\n##\n## Reference: For the definition of this method see\n## @url{https://en.wikipedia.org/wiki/List_of_Runge%E2%80%93Kutta_methods}.\n## @seealso{odeset, odeget, ode45, ode15s}\n## @end deftypefn\n\nfunction varargout = ode23 (fcn, trange, init, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  solver = \"ode23\";\n  order  = 3;\n\n  if (nargin >= 4)\n    if (! isstruct (varargin{1}))\n      ## varargin{1:len} are parameters for fcn\n      odeopts = odeset ();\n      funarguments = varargin;\n    elseif (numel (varargin) > 1)\n      ## varargin{1} is an ODE options structure opt\n      odeopts = varargin{1};\n      funarguments = {varargin{2:numel (varargin)}};\n    else\n      ## varargin{1} is an ODE options structure opt\n      odeopts = varargin{1};\n      funarguments = {};\n    endif\n  else  # nargin == 3\n    odeopts = odeset ();\n    funarguments = {};\n  endif\n\n  if (! isnumeric (trange) || ! isvector (trange))\n    error (\"Octave:invalid-input-arg\",\n           \"ode23: TRANGE must be a numeric vector\");\n  endif\n\n  if (numel (trange) < 2)\n    error (\"Octave:invalid-input-arg\",\n           \"ode23: TRANGE must contain at least 2 elements\");\n  elseif (trange(2) == trange(1))\n    error (\"Octave:invalid-input-arg\",\n           \"ode23: invalid time span, TRANGE(1) == TRANGE(2)\");\n  else\n    direction = sign (trange(2) - trange(1));\n  endif\n  trange = trange(:);\n\n  if (! isnumeric (init) || ! isvector (init))\n    error (\"Octave:invalid-input-arg\",\n           \"ode23: INIT must be a numeric vector\");\n  endif\n  init = init(:);\n\n  if (ischar (fcn))\n    if (! exist (fcn))\n      error (\"Octave:invalid-input-arg\",\n             ['ode23: function \"' fcn '\" not found']);\n    endif\n    fcn = str2func (fcn);\n  endif\n  if (! is_function_handle (fcn))\n    error (\"Octave:invalid-input-arg\",\n           \"ode23: FCN must be a valid function handle\");\n  endif\n\n  ## FIXME: Warn user if ! isempty (funarguments)\n  ## Not a documented behavior and may be deprecated\n\n\n  ## Start preprocessing, have a look which options are set in odeopts,\n  ## check if an invalid or unused option is set.\n  [defaults, classes, attributes] = odedefaults (numel (init),\n                                                 trange(1), trange(end));\n\n  persistent ode23_ignore_options = ...\n    {\"BDF\", \"InitialSlope\", \"Jacobian\", \"JPattern\",\n     \"MassSingular\", \"MaxOrder\", \"MvPattern\", \"Vectorized\"};\n\n  defaults   = rmfield (defaults, ode23_ignore_options);\n  classes    = rmfield (classes, ode23_ignore_options);\n  attributes = rmfield (attributes, ode23_ignore_options);\n\n  odeopts = odemergeopts (\"ode23\", odeopts, defaults, classes, attributes);\n\n  odeopts.funarguments = funarguments;\n  odeopts.direction    = direction;\n\n  if (! isempty (odeopts.NonNegative))\n    if (isempty (odeopts.Mass))\n      odeopts.havenonnegative = true;\n    else\n      odeopts.havenonnegative = false;\n      warning (\"Octave:invalid-input-arg\",\n               ['ode23: option \"NonNegative\" is ignored', ...\n                \" when mass matrix is set\\n\"]);\n    endif\n  else\n    odeopts.havenonnegative = false;\n  endif\n\n  if (isempty (odeopts.OutputFcn) && nargout == 0)\n    odeopts.OutputFcn = @odeplot;\n    odeopts.haveoutputfunction = true;\n  else\n    odeopts.haveoutputfunction = ! isempty (odeopts.OutputFcn);\n  endif\n\n  if (isempty (odeopts.InitialStep))\n    odeopts.InitialStep = odeopts.direction * ...\n                          starting_stepsize (order, fcn, trange(1), init,\n                                             odeopts.AbsTol, odeopts.RelTol,\n                                             strcmpi (odeopts.NormControl,\n                                             \"on\"), odeopts.funarguments);\n  endif\n\n  if (! isempty (odeopts.Mass))\n    if (isnumeric (odeopts.Mass))\n      havemasshandle = false;\n      mass = odeopts.Mass;  # constant mass\n    elseif (is_function_handle (odeopts.Mass))\n      havemasshandle = true;    # mass defined by a function handle\n    else\n      error (\"Octave:invalid-input-arg\",\n             'ode45: \"Mass\" field must be a function handle or square matrix');\n    endif\n  else  # no mass matrix - create a diag-matrix of ones for mass\n    havemasshandle = false;   # mass = diag (ones (length (init), 1), 0);\n  endif\n\n  ## Starting the initialization of the core solver ode23\n\n  if (havemasshandle)   # Handle only the dynamic mass matrix,\n    if (! strcmp (odeopts.MStateDependence, \"none\"))\n      ## constant mass matrices have already been handled\n      mass = @(t,x) odeopts.Mass (t, x, odeopts.funarguments{:});\n      fcn = @(t,x) mass (t, x, odeopts.funarguments{:}) ...\n                   \\ fcn (t, x, odeopts.funarguments{:});\n    else\n      mass = @(t) odeopts.Mass (t, odeopts.funarguments{:});\n      fcn = @(t,x) mass (t, odeopts.funarguments{:}) ...\n                   \\ fcn (t, x, odeopts.funarguments{:});\n    endif\n  endif\n\n  if (numel (trange) > 2)\n    odeopts.Refine = [];  # disable Refine when specific times requested\n  endif\n\n  solution = integrate_adaptive (@runge_kutta_23,\n                                 order, fcn, trange, init, odeopts);\n\n  ## Postprocessing, do whatever when terminating integration algorithm\n  if (odeopts.haveoutputfunction)  # Cleanup plotter\n    feval (odeopts.OutputFcn, [], [], \"done\", odeopts.funarguments{:});\n  endif\n  if (! isempty (odeopts.Events))   # Cleanup event function handling\n    ode_event_handler ([], [], [], [], [], \"done\");\n  endif\n\n  ## Print additional information if option Stats is set\n  if (strcmpi (odeopts.Stats, \"on\"))\n    nsteps    = solution.cntloop;             # cntloop from 2..end\n    nfailed   = solution.cntcycles - nsteps;  # cntcycl from 1..end\n    nfevals   = 3 * solution.cntcycles + 1;   # number of ode evaluations\n    ndecomps  = 0;  # number of LU decompositions\n    npds      = 0;  # number of partial derivatives\n    nlinsols  = 0;  # no. of solutions of linear systems\n\n    printf (\"Number of successful steps: %d\\n\", nsteps);\n    printf (\"Number of failed attempts:  %d\\n\", nfailed);\n    printf (\"Number of function calls:   %d\\n\", nfevals);\n  endif\n\n  if (nargout == 2)\n    varargout{1} = solution.output_t; # Time stamps are first output argument\n    varargout{2} = solution.output_x; # Results are second output argument\n  elseif (nargout == 1)\n    varargout{1}.x = solution.ode_t.'; #Time stamps saved in field x (row vect.)\n    varargout{1}.y = solution.ode_x.'; #Results are saved in field y (row vect.)\n    varargout{1}.solver = solver; # Solver name is saved in field solver\n    if (! isempty (odeopts.Events))\n      varargout{1}.xe = solution.event{3}.'; # Time info when an event occurred\n      varargout{1}.ye = solution.event{4}.'; # Results when an event occurred\n      varargout{1}.ie = solution.event{2}.'; # Index info which event occurred\n    endif\n    if (strcmpi (odeopts.Stats, \"on\"))\n      varargout{1}.stats = struct ();\n      varargout{1}.stats.nsteps   = nsteps;\n      varargout{1}.stats.nfailed  = nfailed;\n      varargout{1}.stats.nfevals  = nfevals;\n      varargout{1}.stats.npds     = npds;\n      varargout{1}.stats.ndecomps = ndecomps;\n      varargout{1}.stats.nlinsols = nlinsols;\n    endif\n  elseif (nargout > 2)\n    varargout = cell (1,5);\n    varargout{1} = solution.output_t;\n    varargout{2} = solution.output_x;\n    if (! isempty (odeopts.Events))\n      varargout{3} = solution.event{3};  # Time info when an event occurred\n      varargout{4} = solution.event{4};  # Results when an event occurred\n      varargout{5} = solution.event{2};  # Index info which event occurred\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Demonstrate convergence order for ode23\n%! tol = 1e-5 ./ 10.^[0:8];\n%! for i = 1 : numel (tol)\n%!   opt = odeset (\"RelTol\", tol(i), \"AbsTol\", realmin);\n%!   [t, y] = ode23 (@(t, y) -y, [0, 1], 1, opt);\n%!   h(i) = 1 / (numel (t) - 1);\n%!   err(i) = norm (y .* exp (t) - 1, Inf);\n%! endfor\n%!\n%! ## Estimate order visually\n%! loglog (h, tol, \"-ob\",\n%!         h, err, \"-r\",\n%!         h, (h/h(end)) .^ 2 .* tol(end), \"k--\",\n%!         h, (h/h(end)) .^ 3 .* tol(end), \"k-\");\n%! axis tight\n%! xlabel (\"h\");\n%! ylabel (\"err(h)\");\n%! title (\"Convergence plot for ode23\");\n%! legend (\"imposed tolerance\", \"ode23 (relative) error\",\n%!         \"order 2\", \"order 3\", \"location\", \"northwest\");\n%!\n%! ## Estimate order numerically\n%! p = diff (log (err)) ./ diff (log (h))\n\n## We are using the Van der Pol equation for all tests.\n## Further tests also define a reference solution (computed at high accuracy)\n%!function ydot = fpol (t, y, varargin)  # The Van der Pol ODE\n%!  ydot = [y(2); (1 - y(1)^2) * y(2) - y(1)];\n%!endfunction\n%!function ref = fref ()       # The computed reference sol\n%!  ref = [0.32331666704577, -1.83297456798624];\n%!endfunction\n%!function [val, trm, dir] = feve (t, y, varargin)\n%!  val = fpol (t, y, varargin{:});  # We use the derivatives\n%!  trm = zeros (2,1);            # that's why component 2\n%!  dir = ones (2,1);             # does not seem to be exact\n%!endfunction\n%!function [val, trm, dir] = fevn (t, y, varargin)\n%!  val = fpol (t, y, varargin{:});  # We use the derivatives\n%!  trm = ones (2,1);             # that's why component 2\n%!  dir = ones (2,1);             # does not seem to be exact\n%!endfunction\n%!function mas = fmas (t, y, varargin)\n%!  mas = [1, 0; 0, 1];           # Dummy mass matrix for tests\n%!endfunction\n%!function mas = fmsa (t, y, varargin)\n%!  mas = sparse ([1, 0; 0, 1]);  # A sparse dummy matrix\n%!endfunction\n%!function out = fout (t, y, flag, varargin)\n%!  out = false;\n%!  if (strcmp (flag, \"init\"))\n%!    if (! isequal (size (t), [2, 1]))\n%!      error ('fout: step \"init\"');\n%!    endif\n%!  elseif (isempty (flag))\n%!  # Multiple steps can be sent in one function call\n%!    if (! isequal ( size (t), size (y)))\n%!      error ('fout: step \"calc\"');\n%!    endif\n%!  elseif (strcmp (flag, \"done\"))\n%!    if (! isempty (t))\n%!      warning ('fout: step \"done\"');\n%!    endif\n%!  else\n%!    error (\"fout: invalid flag <%s>\", flag);\n%!  endif\n%!endfunction\n%!function stop_solve = OutputSel_test (t, y, flag, x)\n%!  ## x == 1: select y(1)\n%!  ## x == 2: select y(2)\n%!  ## x == 3: select y([1,2])\n%!  persistent y_last\n%!  if (strcmp (flag, \"init\"))\n%!    y_last = y;\n%!    if (x == 1 || x == 2)\n%!      assert (length (y) == 1);\n%!    elseif (x == 3)\n%!      assert (length (y) == 2);\n%!    endif\n%!  elseif (strcmp (flag, \"done\"))\n%!    y_exp = fref ().';\n%!    if (x < 3)\n%!      assert (y_last, y_exp(x), 5e-4);\n%!    else\n%!      assert (y_last, y_exp, 5e-4);\n%!    endif\n%!  else  # flag == \"\"\n%!    y_last = y(:, end);\n%!    if (x == 1 || x == 2)\n%!      assert (length (t) == length (y));\n%!    else\n%!      assert (2 * length (t) == length (y(:)));\n%!    endif\n%!  endif\n%!  stop_solve = 0;\n%!endfunction\n%!\n%!test  # two output arguments\n%! [t, y] = ode23 (@fpol, [0 2], [2 0]);\n%! assert ([t(end), y(end,:)], [2, fref], 1e-3);\n%!test  # correct number of steps with Refine\n%! [t1, y1] = ode23 (@fpol, [0 2], [2 0], odeset (\"Refine\", 1));\n%! [t2, y2] = ode23 (@fpol, [0 2], [2 0], odeset (\"Refine\", 4));\n%! [t3, y3] = ode23 (@fpol, [0 2], [2 0]); #default Refine=1\n%! s = ode23 (@fpol, [0 2], [2 0], odeset (\"Refine\", 4));\n%! assert (length (t1) == length (t3));\n%! assert (length (t2) == 4*length (t1) - 3);\n%! assert (length (s.x) == length (t1));\n%!test  # anonymous function instead of real function\n%! fvdp = @(t,y) [y(2); (1 - y(1)^2) * y(2) - y(1)];\n%! [t, y] = ode23 (fvdp, [0 2], [2 0]);\n%! assert ([t(end), y(end,:)], [2, fref], 1e-3);\n%!test  # extra input arguments passed through\n%! [t, y] = ode23 (@fpol, [0 2], [2 0], 12, 13, \"KL\");\n%! assert ([t(end), y(end,:)], [2, fref], 1e-3);\n%!test  # empty OdePkg structure *but* extra input arguments\n%! opt = odeset ();\n%! [t, y] = ode23 (@fpol, [0 2], [2 0], opt, 12, 13, \"KL\");\n%! assert ([t(end), y(end,:)], [2, fref], 1e-2);\n%!test  # Solve another anonymous function below zero\n%! ref = [0, 14.77810590694212];\n%! [t, y] = ode23 (@(t,y) y, [-2 0], 2);\n%! assert ([t(end), y(end,:)], ref, 1e-2);\n%!test  # InitialStep option\n%! opt = odeset (\"InitialStep\", 1e-8);\n%! [t, y] = ode23 (@fpol, [0 0.2], [2 0], opt);\n%! assert ([t(2)-t(1)], [1e-8], 1e-9);\n%!test  # MaxStep option\n%! opt = odeset (\"MaxStep\", 1e-3);\n%! sol = ode23 (@fpol, [0 0.2], [2 0], opt);\n%! assert ([sol.x(5)-sol.x(4)], [1e-3], 1e-4);\n%!test  # Solve in backward direction starting at t=0\n%! ref = [-1.205364552835178, 0.951542399860817];\n%! sol = ode23 (@fpol, [0 -2], [2 0]);\n%! assert ([sol.x(end); sol.y(:,end)], [-2; ref'], 5e-3);\n%!test  # Solve in backward direction starting at t=2\n%! ref = [-1.205364552835178, 0.951542399860817];\n%! sol = ode23 (@fpol, [2 0 -2], fref);\n%! assert ([sol.x(end); sol.y(:,end)], [-2; ref'], 2e-2);\n%!test  # Solve another anonymous function in backward direction\n%! ref = [-1, 0.367879437558975];\n%! sol = ode23 (@(t,y) y, [0 -1], 1);\n%! assert ([sol.x(end); sol.y(:,end)], ref', 1e-2);\n%!test  # Solve another anonymous function below zero\n%! ref = [0, 14.77810590694212];\n%! sol = ode23 (@(t,y) y, [-2 0], 2);\n%! assert ([sol.x(end); sol.y(:,end)], ref', 1e-2);\n%!test  # Solve in backward direction starting at t=0 with MaxStep option\n%! ref = [-1.205364552835178, 0.951542399860817];\n%! opt = odeset (\"MaxStep\", 1e-3);\n%! sol = ode23 (@fpol, [0 -2], [2 0], opt);\n%! assert ([abs(sol.x(8)-sol.x(7))], [1e-3], 1e-3);\n%! assert ([sol.x(end); sol.y(:,end)], [-2; ref'], 1e-3);\n%!test  # AbsTol option\n%! opt = odeset (\"AbsTol\", 1e-5);\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # AbsTol and RelTol option\n%! opt = odeset (\"AbsTol\", 1e-8, \"RelTol\", 1e-8);\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # hermite_cubic_interpolation\n%! opt = odeset (\"RelTol\", 1e-8, \"NormControl\", \"on\");\n%! [t,sol] = ode23(@(t,x)[x(2);x(1)],linspace(0,1),[1;0],opt);\n%! assert (max (abs (sol(:,1)-cosh (t))),0,1e-6);\n%!test  # RelTol and NormControl option -- higher accuracy\n%! opt = odeset (\"RelTol\", 1e-8, \"NormControl\", \"on\");\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-4);\n%!test  # Keeps initial values while integrating\n%! opt = odeset (\"NonNegative\", 2);\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; 2; 0], 1e-1);\n%!test  # OutputSel 1 (see function OutputSel_test for asserts)\n%! opt = odeset (\"OutputFcn\", @(t, y, flag) OutputSel_test (t, y, flag, 1), ...\n%!               \"OutputSel\", 1);\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%!test  # OutputSel 2 (see function OutputSel_test for asserts)\n%! opt = odeset (\"OutputFcn\", @(t, y, flag) OutputSel_test (t, y, flag, 2), ...\n%!               \"OutputSel\", 2);\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%!test  # OutputSel [1,2] (see function OutputSel_test for asserts)\n%! opt = odeset (\"OutputFcn\", @(t, y, flag) OutputSel_test (t, y, flag, 3), ...\n%!               \"OutputSel\", [1, 2]);\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%!test  # Stats must add further elements in sol\n%! opt = odeset (\"Stats\", \"on\");\n%! stat_str = evalc (\"sol = ode23 (@fpol, [0 2], [2 0], opt);\");\n%! assert (strncmp (stat_str, \"Number of successful steps:\", 27));\n%! assert (isfield (sol, \"stats\"));\n%! assert (isfield (sol.stats, \"nsteps\"));\n%!test  # Events option add further elements in sol\n%! opt = odeset (\"Events\", @feve);\n%! sol = ode23 (@fpol, [0 10], [2 0], opt);\n%! assert (isfield (sol, \"ie\"));\n%! assert (sol.ie(1), 2);\n%! assert (isfield (sol, \"xe\"));\n%! assert (isfield (sol, \"ye\"));\n%!test  # Events option, now stop integration\n%! opt = odeset (\"Events\", @fevn, \"NormControl\", \"on\");\n%! sol = ode23 (@fpol, [0 10], [2 0], opt);\n%! assert ([sol.ie, sol.xe, sol.ye.'],\n%!         [2.0, 2.496110, -0.830550, -2.677589], 1e-3);\n%!test  # Events option, five output arguments\n%! opt = odeset (\"Events\", @fevn, \"NormControl\", \"on\");\n%! [t, y, vxe, ye, vie] = ode23 (@fpol, [0 10], [2 0], opt);\n%! assert ([vie, vxe, ye], [2.0, 2.496110, -0.830550, -2.677589], 1e-3);\n%!test  # Mass option as function\n%! opt = odeset (\"Mass\", @fmas);\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as matrix\n%! opt = odeset (\"Mass\", eye (2,2));\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as sparse matrix\n%! opt = odeset (\"Mass\", sparse (eye (2,2)));\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as function and sparse matrix\n%! opt = odeset (\"Mass\", @fmsa);\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as function and MStateDependence\n%! opt = odeset (\"Mass\", @fmas, \"MStateDependence\", \"strong\");\n%! sol = ode23 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n\n## Note: The following options have no effect on this solver\n##       therefore it makes no sense to test them here:\n##\n## \"BDF\"\n## \"InitialSlope\"\n## \"JPattern\"\n## \"Jacobian\"\n## \"MassSingular\"\n## \"MaxOrder\"\n## \"MvPattern\"\n## \"Vectorized\"\n\n%!test  # Check that imaginary part of solution does not get inverted\n%! sol = ode23 (@(x,y) 1, [0 1], 1i);\n%! assert (imag (sol.y), ones (size (sol.y)));\n%! [x, y] = ode23 (@(x,y) 1, [0 1], 1i);\n%! assert (imag (y), ones (size (y)));\n\n## Test input validation\n%!error <Invalid call> ode23 ()\n%!error <Invalid call> ode23 (1)\n%!error <Invalid call> ode23 (1,2)\n%!error <TRANGE must be a numeric> ode23 (@fpol, {[0 25]}, [3 15 1])\n%!error <TRANGE must be a .* vector> ode23 (@fpol, [0 25; 25 0], [3 15 1])\n%!error <TRANGE must contain at least 2 elements> ode23 (@fpol, [1], [3 15 1])\n%!error <invalid time span>  ode23 (@fpol, [1 1], [3 15 1])\n%!error <INIT must be a numeric> ode23 (@fpol, [0 25], {[3 15 1]})\n%!error <INIT must be a .* vector> ode23 (@fpol, [0 25], [3 15 1; 3 15 1])\n%!error <FCN must be a valid function handle> ode23 (1, [0 25], [3 15 1])\n"
  },
  {
    "path": "scripts/ode/ode23s.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{t}, @var{y}] =} ode23s (@var{fcn}, @var{trange}, @var{init})\n## @deftypefnx {} {[@var{t}, @var{y}] =} ode23s (@var{fcn}, @var{trange}, @var{init}, @var{ode_opt})\n## @deftypefnx {} {[@var{t}, @var{y}] =} ode23s (@dots{}, @var{par1}, @var{par2}, @dots{})\n## @deftypefnx {} {[@var{t}, @var{y}, @var{te}, @var{ye}, @var{ie}] =} ode23s (@dots{})\n## @deftypefnx {} {@var{solution} =} ode23s (@dots{})\n##\n## Solve a set of stiff Ordinary Differential Equations (stiff ODEs) with a\n## @nospell{Rosenbrock} method of order (2,3).\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function that defines the ODE: @code{M y' = f(t,y)}.  The\n## function must accept two inputs where the first is time @var{t} and the\n## second is a column vector of unknowns @var{y}.  @var{M} is a constant mass\n## matrix, non-singular and possibly sparse.  Set the field @qcode{\"Mass\"} in\n## @var{odeopts} using @var{odeset} to specify a mass matrix.\n##\n## @var{trange} specifies the time interval over which the ODE will be\n## evaluated.  Typically, it is a two-element vector specifying the initial\n## and final times (@code{[tinit, tfinal]}).  If there are more than two\n## elements then the solution will also be evaluated at these intermediate\n## time instances using an interpolation procedure of the same order as the\n## one of the solver.\n##\n## By default, @code{ode23s} uses an adaptive timestep with the\n## @code{integrate_adaptive} algorithm.  The tolerance for the timestep\n## computation may be changed by using the options @qcode{\"RelTol\"} and\n## @qcode{\"AbsTol\"}.\n##\n## @var{init} contains the initial value for the unknowns.  If it is a row\n## vector then the solution @var{y} will be a matrix in which each column is\n## the solution for the corresponding initial value in @var{init}.\n##\n## The optional fourth argument @var{ode_opt} specifies non-default options to\n## the ODE solver.  It is a structure generated by @code{odeset}.\n## @code{ode23s} will ignore the following options: @qcode{\"BDF\"},\n## @qcode{\"InitialSlope\"}, @qcode{\"MassSingular\"}, @qcode{\"MStateDependence\"},\n## @qcode{\"MvPattern\"}, @qcode{\"MaxOrder\"}, @qcode{\"Non-negative\"}.\n##\n## The function typically returns two outputs.  Variable @var{t} is a\n## column vector and contains the times where the solution was found.  The\n## output @var{y} is a matrix in which each column refers to a different\n## unknown of the problem and each row corresponds to a time in @var{t}.  If\n## @var{trange} specifies intermediate time steps, only those will be returned.\n##\n## The output can also be returned as a structure @var{solution} which has a\n## field @var{x} containing a row vector of times where the solution was\n## evaluated and a field @var{y} containing the solution matrix such that each\n## column corresponds to a time in @var{x}.  Use\n## @w{@code{fieldnames (@var{solution})}}@ to see the other fields and\n## additional information returned.\n##\n## If using the @qcode{\"Events\"} option then three additional outputs may be\n## returned.  @var{te} holds the time when an Event function returned a zero.\n## @var{ye} holds the value of the solution at time @var{te}.  @var{ie}\n## contains an index indicating which Event function was triggered in the case\n## of multiple Event functions.\n##\n## Example: Solve the stiff @nospell{Van der Pol} equation\n##\n## @example\n## @group\n## f = @@(@var{t},@var{y}) [@var{y}(2); 1000*(1 - @var{y}(1)^2) * @var{y}(2) - @var{y}(1)];\n## opt = odeset ('Mass', [1 0; 0 1], 'MaxStep', 1e-1);\n## [vt, vy] = ode23s (f, [0 2000], [2 0], opt);\n## @end group\n## @end example\n## @seealso{odeset, daspk, dassl}\n## @end deftypefn\n\nfunction varargout = ode23s (fcn, trange, init, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  solver = \"ode23s\";\n  order = 2;\n\n  if (nargin >= 4)\n    if (! isstruct (varargin{1}))\n      ## varargin{1:len} are parameters for fcn\n      odeopts = odeset ();\n      funarguments = varargin;\n    elseif (numel (varargin) > 1)\n      ## varargin{1} is an ODE options structure opt\n      odeopts = varargin{1};\n      funarguments = {varargin{2:numel (varargin)}};\n    else\n      ## varargin{1} is an ODE options structure opt\n      odeopts = varargin{1};\n      funarguments = {};\n    endif\n  else  # nargin == 3\n    odeopts = odeset ();\n    funarguments = {};\n  endif\n\n  if (! isnumeric (trange) || ! isvector (trange))\n    error (\"Octave:invalid-input-arg\",\n           \"ode23s: TRANGE must be a numeric vector\");\n  endif\n\n  if (numel (trange) < 2)\n    error (\"Octave:invalid-input-arg\",\n           \"ode23s: TRANGE must contain at least 2 elements\");\n  elseif (trange(2) == trange(1))\n    error (\"Octave:invalid-input-arg\",\n           \"ode23s: invalid time span, TRANGE(1) == TRANGE(2)\");\n  else\n    direction = sign (trange(2) - trange(1));\n  endif\n  trange = trange(:);\n\n  if (! isnumeric (init) || ! isvector (init))\n    error (\"Octave:invalid-input-arg\",\n           \"ode23s: INIT must be a numeric vector\");\n  endif\n  init = init(:);\n\n  if (ischar (fcn))\n    if (! exist (fcn))\n      error (\"Octave:invalid-input-arg\",\n             ['ode23s: function \"' fcn '\" not found']);\n    endif\n    fcn = str2func (fcn);\n  endif\n  if (! is_function_handle (fcn))\n    error (\"Octave:invalid-input-arg\",\n           \"ode23s: FCN must be a valid function handle\");\n  endif\n\n  ## FIXME: Warn user if ! isempty (funarguments)\n  ## Not a documented behavior and may be deprecated\n\n\n  ## Start preprocessing, have a look which options are set in odeopts,\n  ## check if an invalid or unused option is set.\n  [defaults, classes, attributes] = odedefaults (numel (init),\n                                                 trange(1), trange(end));\n\n  persistent ode23s_ignore_options = ...\n    {\"BDF\", \"InitialSlope\", \"MassSingular\", \"MStateDependence\", ...\n     \"MvPattern\", \"MaxOrder\", \"NonNegative\"};\n\n  defaults   = rmfield (defaults, ode23s_ignore_options);\n  classes    = rmfield (classes, ode23s_ignore_options);\n  attributes = rmfield (attributes, ode23s_ignore_options);\n\n  odeopts = odemergeopts (\"ode23s\", odeopts, defaults, classes, attributes);\n\n  odeopts.funarguments = funarguments;\n  odeopts.direction    = direction;\n  ## ode23s ignores \"NonNegative\" option, but integrate_adaptive needs it...\n  odeopts.havenonnegative = false;\n\n  if (isempty (odeopts.OutputFcn) && nargout == 0)\n    odeopts.OutputFcn = @odeplot;\n    odeopts.haveoutputfunction = true;\n  else\n    odeopts.haveoutputfunction = ! isempty (odeopts.OutputFcn);\n  endif\n\n  if (isempty (odeopts.InitialStep))\n    odeopts.InitialStep = odeopts.direction * ...\n                          starting_stepsize (order, fcn, trange(1), init,\n                                             odeopts.AbsTol, odeopts.RelTol,\n                                             strcmpi (odeopts.NormControl,\n                                                      \"on\"),\n                                             odeopts.funarguments);\n  endif\n\n  if (! isempty (odeopts.Mass) && isnumeric (odeopts.Mass))\n    havemasshandle = false;\n    mass = odeopts.Mass;     # constant mass\n  elseif (is_function_handle (odeopts.Mass))\n    havemasshandle = true;   # mass defined by a function handle\n    odeopts.Mass = feval (odeopts.Mass, trange(1), init,\n                          odeopts.funarguments{:});\n  else  # no mass matrix - create a diag-matrix of ones for mass\n    havemasshandle = false;\n    odeopts.Mass = diag (ones (length (init), 1), 0);\n  endif\n\n  ## Starting the initialization of the core solver ode23s\n\n  if (numel (trange) > 2)\n    odeopts.Refine = [];  # disable Refine when specific times requested\n  endif\n\n  solution = integrate_adaptive (@runge_kutta_23s, ...\n                                 order, fcn, trange, init, odeopts);\n\n  ## Postprocessing, do whatever when terminating integration algorithm\n  if (odeopts.haveoutputfunction)  # Cleanup plotter\n    feval (odeopts.OutputFcn, [], [], \"done\", odeopts.funarguments{:});\n  endif\n  if (! isempty (odeopts.Events))   # Cleanup event function handling\n    ode_event_handler ([], [], [], [], [], \"done\");\n  endif\n\n  ## Print additional information if option Stats is set\n  if (strcmpi (odeopts.Stats, \"on\"))\n    nsteps    = solution.cntloop;             # cntloop from 2..end\n    nfailed   = solution.cntcycles - nsteps;  # cntcycl from 1..end\n    nfevals   = 5 * solution.cntcycles;       # number of ode evaluations\n    ndecomps  = nsteps;  # number of LU decompositions\n    npds      = 0;  # number of partial derivatives\n    nlinsols  = 3 * nsteps;  # no. of solutions of linear systems\n\n    printf (\"Number of successful steps: %d\\n\", nsteps);\n    printf (\"Number of failed attempts:  %d\\n\", nfailed);\n    printf (\"Number of function calls:   %d\\n\", nfevals);\n  endif\n\n  if (nargout == 2)\n    varargout{1} = solution.output_t; # Time stamps are first output argument\n    varargout{2} = solution.output_x; # Results are second output argument\n  elseif (nargout == 1)\n    varargout{1}.x = solution.ode_t.'; #Time stamps saved in field x (row vect.)\n    varargout{1}.y = solution.ode_x.'; #Results are saved in field y (row vect.)\n    varargout{1}.solver = solver;   # Solver name is saved in field solver\n    if (! isempty (odeopts.Events))\n      varargout{1}.xe = solution.event{3}.'; # Time info when an event occurred\n      varargout{1}.ye = solution.event{4}.'; # Results when an event occurred\n      varargout{1}.ie = solution.event{2}.'; # Index info which event occurred\n    endif\n    if (strcmpi (odeopts.Stats, \"on\"))\n      varargout{1}.stats = struct ();\n      varargout{1}.stats.nsteps   = nsteps;\n      varargout{1}.stats.nfailed  = nfailed;\n      varargout{1}.stats.nfevals  = nfevals;\n      varargout{1}.stats.npds     = npds;\n      varargout{1}.stats.ndecomps = ndecomps;\n      varargout{1}.stats.nlinsols = nlinsols;\n    endif\n  elseif (nargout == 5)\n    varargout = cell (1,5);\n    varargout{1} = solution.output_t;\n    varargout{2} = solution.output_x;\n    if (! isempty (odeopts.Events))\n      varargout{3} = solution.event{3};  # Time info when an event occurred\n      varargout{4} = solution.event{4};  # Results when an event occurred\n      varargout{5} = solution.event{2};  # Index info which event occurred\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Demo function: stiff Van Der Pol equation\n%! fcn = @(t,y) [y(2); 10*(1-y(1)^2)*y(2)-y(1)];\n%! ## Calling ode23s method\n%! tmr = tic ();\n%! [vt, vy] = ode23s (fcn, [0 20], [2 0]);\n%! toc (tmr);\n%! ## Plotting the result\n%! plot (vt,vy(:,1),'-o');\n\n%!demo\n%! ## Demo function: stiff Van Der Pol equation\n%! fcn = @(t,y) [y(2); 10*(1-y(1)^2)*y(2)-y(1)];\n%! ## Calling ode23s method\n%! odeopts = odeset (\"Jacobian\", @(t,y) [0 1; -20*y(1)*y(2)-1, 10*(1-y(1)^2)],\n%!                   \"InitialStep\", 1e-3)\n%! tmr = tic ();\n%! [vt, vy] = ode23s (fcn, [0 20], [2 0], odeopts);\n%! toc (tmr);\n%! ## Plotting the result\n%! plot (vt,vy(:,1),'-o');\n\n%!demo\n%! ## Demo function: stiff Van Der Pol equation\n%! fcn = @(t,y) [y(2); 100*(1-y(1)^2)*y(2)-y(1)];\n%! ## Calling ode23s method\n%! odeopts = odeset (\"InitialStep\", 1e-4);\n%! tmr = tic ();\n%! [vt, vy] = ode23s (fcn, [0 200], [2 0]);\n%! toc (tmr);\n%! ## Plotting the result\n%! plot (vt,vy(:,1),'-o');\n\n%!demo\n%! ## Demo function: stiff Van Der Pol equation\n%! fcn = @(t,y) [y(2); 100*(1-y(1)^2)*y(2)-y(1)];\n%! ## Calling ode23s method\n%! odeopts = odeset (\"Jacobian\", @(t,y) [0 1; -200*y(1)*y(2)-1, 100*(1-y(1)^2)],\n%!                   \"InitialStep\", 1e-4);\n%! tmr = tic ();\n%! [vt, vy] = ode23s (fcn, [0 200], [2 0], odeopts);\n%! toc (tmr);\n%! ## Plotting the result\n%! plot (vt,vy(:,1),'-o');\n\n%!demo\n%! ## Demonstrate convergence order for ode23s\n%! tol = 1e-5 ./ 10.^[0:5];\n%! for i = 1 : numel (tol)\n%!   opt = odeset (\"RelTol\", tol(i), \"AbsTol\", realmin);\n%!   [t, y] = ode23s (@(t, y) -y, [0, 1], 1, opt);\n%!   h(i) = 1 / (numel (t) - 1);\n%!   err(i) = norm (y .* exp (t) - 1, Inf);\n%! endfor\n%!\n%! ## Estimate order visually\n%! loglog (h, tol, \"-ob\",\n%!         h, err, \"-r\",\n%!         h, (h/h(end)) .^ 2 .* tol(end), \"k--\",\n%!         h, (h/h(end)) .^ 3 .* tol(end), \"k-\");\n%! axis tight\n%! xlabel (\"h\");\n%! ylabel (\"err(h)\");\n%! title (\"Convergence plot for ode23s\");\n%! legend (\"imposed tolerance\", \"ode23s (relative) error\",\n%!         \"order 2\", \"order 3\", \"location\", \"northwest\");\n%!\n%! ## Estimate order numerically\n%! p = diff (log (err)) ./ diff (log (h))\n\n%!test\n%! [vt, vy] = ode23s (@(t,y) t - y + 1, [0 10], [1]);\n%! assert ([vt(end), vy(end)], [10, exp(-10) + 10], 1e-3);\n\n%!test\n%! opts = odeset ('Mass', 5, 'Jacobian', -5, 'JConstant', 'on');\n%! [vt, vy] = ode23s (@(t,y) 5 * (t - y + 1), [0 10], [1], opts);\n%! assert ([vt(end), vy(end)], [10, exp(-10) + 10], 1e-3);\n\n## We are using the \"Van der Pol\" implementation for all tests that are done\n## for this function.  For further tests we also define a reference solution\n## (computed at high accuracy).\n%!function ydot = fpol (t, y, varargin)  # The Van der Pol ODE\n%!  ydot = [y(2); 10 * (1 - y(1)^2) * y(2) - y(1)];\n%!endfunction\n%!function ydot = jac (t, y)   # The Van der Pol ODE\n%!  ydot = [0 1; -20 * y(1) * y(2) - 1, 10 * (1 - y(1)^2)];\n%!endfunction\n%!function ref = fref ()       # The computed reference sol\n%!  ref = [1.8610687248524305  -0.0753216319179125];\n%!endfunction\n%!function [val, trm, dir] = feve (t, y, varargin)\n%!  val = fpol (t, y, varargin{:});  # We use the derivatives\n%!  trm = zeros (2,1);            # that's why component 2\n%!  dir = ones (2,1);             # does not seem to be exact\n%!endfunction\n%!function [val, trm, dir] = fevn (t, y, varargin)\n%!  val = fpol (t, y, varargin{:});  # We use the derivatives\n%!  trm = ones (2,1);             # that's why component 2\n%!  dir = ones (2,1);             # does not seem to be exact\n%!endfunction\n%!function mas = fmas (t, y, varargin)\n%!  mas = [1, 0; 0, 1];           # Dummy mass matrix for tests\n%!endfunction\n%!function mas = fmsa (t, y, varargin)\n%!  mas = sparse ([1, 0; 0, 1]);  # A sparse dummy matrix\n%!endfunction\n%!function out = fout (t, y, flag, varargin)\n%!  out = false;\n%!  if (strcmp (flag, \"init\"))\n%!    if (! isequal (size (t), [2, 1]))\n%!      error ('fout: step \"init\"');\n%!    endif\n%!  elseif (isempty (flag))\n%!  # Multiple steps can be sent in one function call\n%!    if (! isequal ( size (t), size (y)))\n%!      error ('fout: step \"calc\"');\n%!    endif\n%!  elseif (strcmp (flag, \"done\"))\n%!    if (! isempty (t))\n%!      warning ('fout: step \"done\"');\n%!    endif\n%!  else\n%!    error (\"fout: invalid flag <%s>\", flag);\n%!  endif\n%!endfunction\n%!function stop_solve = OutputSel_test (t, y, flag, x)\n%!  ## x == 1: select y(1)\n%!  ## x == 2: select y(2)\n%!  ## x == 3: select y([1,2])\n%!  persistent y_last\n%!  if (strcmp (flag, \"init\"))\n%!    y_last = y;\n%!    if (x == 1 || x == 2)\n%!      assert (length (y) == 1);\n%!    elseif (x == 3)\n%!      assert (length (y) == 2);\n%!    endif\n%!  elseif (strcmp (flag, \"done\"))\n%!    y_exp = fref ().';\n%!    if (x < 3)\n%!      assert (y_last, y_exp(x), 1e-4);\n%!    else\n%!      assert (y_last, y_exp, 1e-4);\n%!    endif\n%!  else  # flag == \"\"\n%!    y_last = y(:,end);\n%!    if (x == 1 || x == 2)\n%!      assert (length (t) == length (y));\n%!    else\n%!      assert (2 * length (t) == length (y(:)));\n%!    endif\n%!  endif\n%!  stop_solve = 0;\n%!endfunction\n%!\n%!test  # two output arguments\n%! [t, y] = ode23s (@fpol, [0 2], [2 0]);\n%! assert ([t(end), y(end,:)], [2, fref], 1e-3);\n%!test  # correct number of steps with Refine\n%! [t1, y1] = ode23s (@fpol, [0 2], [2 0], odeset (\"Refine\", 1));\n%! [t2, y2] = ode23s (@fpol, [0 2], [2 0], odeset (\"Refine\", 4));\n%! [t3, y3] = ode23s (@fpol, [0 2], [2 0]); #default Refine=1\n%! s = ode23s (@fpol, [0 2], [2 0], odeset (\"Refine\", 4));\n%! assert (length (t1) == length (t3));\n%! assert (length (t2) == 4*length (t1) - 3);\n%! assert (length (s.x) == length (t1));\n%!test  # anonymous function instead of real function\n%! fvdp = @(t,y) [y(2); 10 * (1 - y(1)^2) * y(2) - y(1)];\n%! [t, y] = ode23s (fvdp, [0 2], [2 0]);\n%! assert ([t(end), y(end,:)], [2, fref], 1e-3);\n%!test  # extra input arguments passed through\n%! [t, y] = ode23s (@fpol, [0 2], [2 0], 12, 13, \"KL\");\n%! assert ([t(end), y(end,:)], [2, fref], 1e-3);\n%!test  # empty OdePkg structure *but* extra input arguments\n%! opt = odeset ();\n%! [t, y] = ode23s (@fpol, [0 2], [2 0], opt, 12, 13, \"KL\");\n%! assert ([t(end), y(end,:)], [2, fref], 1e-2);\n%!test  # InitialStep option\n%! opt = odeset (\"InitialStep\", 1e-8);\n%! [t, y] = ode23s (@fpol, [0 0.2], [2 0], opt);\n%! assert ([t(2)-t(1)], [1e-8], 1e-9);\n%!test  # MaxStep option\n%! opt = odeset (\"MaxStep\", 1e-3);\n%! sol = ode23s (@fpol, [0 0.2], [2 0], opt);\n%! assert ([sol.x(5)-sol.x(4)], [1e-3], 1e-4);\n%!test  # AbsTol option\n%! opt = odeset (\"AbsTol\", 1e-5);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # AbsTol and RelTol option\n%! opt = odeset (\"AbsTol\", 1e-8, \"RelTol\", 1e-8);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # RelTol and NormControl option -- higher accuracy\n%! opt = odeset (\"RelTol\", 1e-8, \"NormControl\", \"on\");\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-4);\n%!test  # OutputSel 1 (see function OutputSel_test for asserts)\n%! opt = odeset (\"OutputFcn\", @(t, y, flag) OutputSel_test (t, y, flag, 1), ...\n%!               \"OutputSel\", 1);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%!test  # OutputSel 2 (see function OutputSel_test for asserts)\n%! opt = odeset (\"OutputFcn\", @(t, y, flag) OutputSel_test (t, y, flag, 2), ...\n%!               \"OutputSel\", 2);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%!test  # OutputSel [1,2] (see function OutputSel_test for asserts)\n%! opt = odeset (\"OutputFcn\", @(t, y, flag) OutputSel_test (t, y, flag, 3), ...\n%!               \"OutputSel\", [1, 2]);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%!test  # Stats must add further elements in sol\n%! opt = odeset (\"Stats\", \"on\");\n%! stat_str = evalc (\"sol = ode23s (@fpol, [0 2], [2 0], opt);\");\n%! assert (strncmp (stat_str, \"Number of successful steps:\", 27));\n%! assert (isfield (sol, \"stats\"));\n%! assert (isfield (sol.stats, \"nsteps\"));\n%!test  # Events option add further elements in sol\n%! opt = odeset (\"Events\", @feve);\n%! sol = ode23s (@fpol, [0 10], [2 0], opt);\n%! assert (isfield (sol, \"ie\"));\n%! assert (sol.ie(1), 2);\n%! assert (isfield (sol, \"xe\"));\n%! assert (isfield (sol, \"ye\"));\n%!test  # Events option, now stop integration\n%! opt = odeset (\"Events\", @fevn, \"NormControl\", \"on\");\n%! sol = ode23s (@fpol, [0 10], [2 0], opt);\n%! assert ([sol.ie, sol.xe, sol.ye.'],\n%!         [2.0, 9.094439, -0.996480, -14.180147], 2e-2);\n%!test  # Events option, five output arguments\n%! opt = odeset (\"Events\", @fevn, \"NormControl\", \"on\");\n%! [t, y, vxe, ye, vie] = ode23s (@fpol, [0 10], [2 0], opt);\n%! assert ([vie, vxe, ye], [2.0, 9.094439, -0.996480, -14.180147], 2e-2);\n%!test  # Mass option as function\n%! opt = odeset (\"Mass\", @fmas);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as matrix\n%! opt = odeset (\"Mass\", eye (2,2));\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as sparse matrix\n%! opt = odeset (\"Mass\", sparse (eye (2,2)));\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as function and sparse matrix\n%! opt = odeset (\"Mass\", @fmsa);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Jacobian option as function\n%! opt = odeset ('Jacobian', @jac);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!testif HAVE_UMFPACK  # Sparse Jacobian\n%! jac = @(t, y) sparse ([0 1; -20*y(1)*y(2)-1, 10*(1-y(1)^2)]);\n%! opt = odeset ('Jacobian', jac);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!testif HAVE_UMFPACK  # Jpattern\n%! S = sparse ([0 1; 1 1]);\n%! opt = odeset (\"Jpattern\", S);\n%! sol = ode23s (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n\n## Note: The following options have no effect on this solver\n##       therefore it makes no sense to test them here:\n##\n## \"BDF\"\n## \"InitialSlope\"\n## \"MassSingular\"\n## \"MStateDependence\"\n## \"MaxOrder\"\n## \"MvPattern\"\n## \"NonNegative\"\n\n%!test  # Check that imaginary part of solution does not get inverted\n%! sol = ode23s (@(x,y) 1, [0 1], 1i);\n%! assert (imag (sol.y), ones (size (sol.y)));\n%! [x, y] = ode23s (@(x,y) 1, [0 1], 1i);\n%! assert (imag (y), ones (size (y)));\n\n## Test input validation\n%!error <Invalid call> ode23s ()\n%!error <Invalid call> ode23s (1)\n%!error <Invalid call> ode23s (1,2)\n%!error <TRANGE must be a numeric> ode23s (@fpol, {[0 25]}, [3 15 1])\n%!error <TRANGE must be a .* vector> ode23s (@fpol, [0 25; 25 0], [3 15 1])\n%!error <TRANGE must contain at least 2 elements> ode23s (@fpol, [1], [3 15 1])\n%!error <invalid time span>  ode23s (@fpol, [1 1], [3 15 1])\n%!error <INIT must be a numeric> ode23s (@fpol, [0 25], {[3 15 1]})\n%!error <INIT must be a .* vector> ode23s (@fpol, [0 25], [3 15 1; 3 15 1])\n%!error <FCN must be a valid function handle> ode23s (1, [0 25], [3 15 1])\n"
  },
  {
    "path": "scripts/ode/ode45.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{t}, @var{y}] =} ode45 (@var{fcn}, @var{trange}, @var{init})\n## @deftypefnx {} {[@var{t}, @var{y}] =} ode45 (@var{fcn}, @var{trange}, @var{init}, @var{ode_opt})\n## @deftypefnx {} {[@var{t}, @var{y}, @var{te}, @var{ye}, @var{ie}] =} ode45 (@dots{})\n## @deftypefnx {} {@var{solution} =} ode45 (@dots{})\n## @deftypefnx {} {} ode45 (@dots{})\n##\n## Solve a set of non-stiff Ordinary Differential Equations (non-stiff ODEs)\n## with the well known explicit @nospell{Dormand-Prince} method of order 4.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function that defines the ODE: @code{y' = f(t,y)}.  The function\n## must accept two inputs where the first is time @var{t} and the second is a\n## column vector of unknowns @var{y}.\n##\n## @var{trange} specifies the time interval over which the ODE will be\n## evaluated.  Typically, it is a two-element vector specifying the initial and\n## final times (@code{[tinit, tfinal]}).  If there are more than two elements\n## then the solution will also be evaluated at these intermediate time\n## instances.\n##\n## By default, @code{ode45} uses an adaptive timestep with the\n## @code{integrate_adaptive} algorithm.  The tolerance for the timestep\n## computation may be changed by using the options @qcode{\"RelTol\"} and\n## @qcode{\"AbsTol\"}.\n##\n## @var{init} contains the initial value for the unknowns.  If it is a row\n## vector then the solution @var{y} will be a matrix in which each column is\n## the solution for the corresponding initial value in @var{init}.\n##\n## The optional fourth argument @var{ode_opt} specifies non-default options to\n## the ODE solver.  It is a structure generated by @code{odeset}.\n##\n## The function typically returns two outputs.  Variable @var{t} is a\n## column vector and contains the times where the solution was found.  The\n## output @var{y} is a matrix in which each column refers to a different\n## unknown of the problem and each row corresponds to a time in @var{t}.\n##\n## The output can also be returned as a structure @var{solution} which has a\n## field @var{x} containing a row vector of times where the solution was\n## evaluated and a field @var{y} containing the solution matrix such that each\n## column corresponds to a time in @var{x}.  Use\n## @w{@code{fieldnames (@var{solution})}}@ to see the other fields and\n## additional information returned.\n##\n## If no output arguments are requested, and no @qcode{\"OutputFcn\"} is\n## specified in @var{ode_opt}, then the @qcode{\"OutputFcn\"} is set to\n## @code{odeplot} and the results of the solver are plotted immediately.\n##\n## If using the @qcode{\"Events\"} option then three additional outputs may be\n## returned.  @var{te} holds the time when an Event function returned a zero.\n## @var{ye} holds the value of the solution at time @var{te}.  @var{ie}\n## contains an index indicating which Event function was triggered in the case\n## of multiple Event functions.\n##\n## Example: Solve the @nospell{Van der Pol} equation\n##\n## @example\n## @group\n## fvdp = @@(@var{t},@var{y}) [@var{y}(2); (1 - @var{y}(1)^2) * @var{y}(2) - @var{y}(1)];\n## [@var{t},@var{y}] = ode45 (fvdp, [0, 20], [2, 0]);\n## @end group\n## @end example\n## @seealso{odeset, odeget, ode23, ode15s}\n## @end deftypefn\n\nfunction varargout = ode45 (fcn, trange, init, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  solver = \"ode45\";\n  order  = 5;  # runge_kutta_45_dorpri uses local extrapolation\n\n  if (nargin >= 4)\n    if (! isstruct (varargin{1}))\n      ## varargin{1:len} are parameters for fcn\n      odeopts = odeset ();\n      funarguments = varargin;\n    elseif (numel (varargin) > 1)\n      ## varargin{1} is an ODE options structure opt\n      odeopts = varargin{1};\n      funarguments = {varargin{2:numel (varargin)}};\n    else\n      ## varargin{1} is an ODE options structure opt\n      odeopts = varargin{1};\n      funarguments = {};\n    endif\n  else  # nargin == 3\n    odeopts = odeset ();\n    funarguments = {};\n  endif\n\n  if (! isnumeric (trange) || ! isvector (trange))\n    error (\"Octave:invalid-input-arg\",\n           \"ode45: TRANGE must be a numeric vector\");\n  endif\n\n  if (numel (trange) < 2)\n    error (\"Octave:invalid-input-arg\",\n           \"ode45: TRANGE must contain at least 2 elements\");\n  elseif (trange(1) == trange(2))\n    error (\"Octave:invalid-input-arg\",\n           \"ode45: invalid time span, TRANGE(1) == TRANGE(2)\");\n  else\n    direction = sign (trange(2) - trange(1));\n  endif\n  trange = trange(:);\n\n  if (! isnumeric (init) || ! isvector (init))\n    error (\"Octave:invalid-input-arg\",\n           \"ode45: INIT must be a numeric vector\");\n  endif\n  init = init(:);\n\n  if (ischar (fcn))\n    if (! exist (fcn))\n      error (\"Octave:invalid-input-arg\",\n             ['ode45: function \"' fcn '\" not found']);\n    endif\n    fcn = str2func (fcn);\n  endif\n  if (! is_function_handle (fcn))\n    error (\"Octave:invalid-input-arg\",\n           \"ode45: FCN must be a valid function handle\");\n  endif\n\n  ## FIXME: Warn user if ! isempty (funarguments)\n  ## Not a documented behavior and may be deprecated\n\n\n  ## Start preprocessing, have a look which options are set in odeopts,\n  ## check if an invalid or unused option is set\n  [defaults, classes, attributes] = odedefaults (numel (init),\n                                                 trange(1), trange(end));\n\n  defaults = odeset (defaults, \"Refine\", 4);\n\n  persistent ode45_ignore_options = ...\n    {\"BDF\", \"InitialSlope\", \"Jacobian\", \"JPattern\",\n     \"MassSingular\", \"MaxOrder\", \"MvPattern\", \"Vectorized\"};\n\n  defaults   = rmfield (defaults, ode45_ignore_options);\n  classes    = rmfield (classes, ode45_ignore_options);\n  attributes = rmfield (attributes, ode45_ignore_options);\n\n  odeopts = odemergeopts (\"ode45\", odeopts, defaults, classes, attributes);\n\n  odeopts.funarguments = funarguments;\n  odeopts.direction    = direction;\n\n  if (! isempty (odeopts.NonNegative))\n    if (isempty (odeopts.Mass))\n      odeopts.havenonnegative = true;\n    else\n      odeopts.havenonnegative = false;\n      warning (\"Octave:invalid-input-arg\",\n               ['ode45: option \"NonNegative\" is ignored', ...\n                \" when mass matrix is set\\n\"]);\n    endif\n  else\n    odeopts.havenonnegative = false;\n  endif\n\n  if (isempty (odeopts.OutputFcn) && nargout == 0)\n    odeopts.OutputFcn = @odeplot;\n    odeopts.haveoutputfunction = true;\n  else\n    odeopts.haveoutputfunction = ! isempty (odeopts.OutputFcn);\n  endif\n\n  if (isempty (odeopts.InitialStep))\n    odeopts.InitialStep = odeopts.direction * ...\n                          starting_stepsize (order, fcn, trange(1), init,\n                                             odeopts.AbsTol, odeopts.RelTol,\n                                             strcmpi (odeopts.NormControl,\n                                             \"on\"), odeopts.funarguments);\n  endif\n\n  if (! isempty (odeopts.Mass))\n    if (isnumeric (odeopts.Mass))\n      havemasshandle = false;\n      mass = odeopts.Mass;  # constant mass\n    elseif (is_function_handle (odeopts.Mass))\n      havemasshandle = true;    # mass defined by a function handle\n    else\n      error (\"Octave:invalid-input-arg\",\n             'ode45: \"Mass\" field must be a function handle or square matrix');\n    endif\n  else  # no mass matrix - create a diag-matrix of ones for mass\n    havemasshandle = false;   # mass = diag (ones (length (init), 1), 0);\n  endif\n\n  ## Starting the initialization of the core solver ode45\n\n  if (havemasshandle)   # Handle only the dynamic mass matrix,\n    if (! strcmp (odeopts.MStateDependence, \"none\"))\n      ### constant mass matrices have already\n      mass = @(t,x) odeopts.Mass (t, x, odeopts.funarguments{:});\n      fcn = @(t,x) mass (t, x, odeopts.funarguments{:}) ...\n                   \\ fcn (t, x, odeopts.funarguments{:});\n    else\n      mass = @(t) odeopts.Mass (t, odeopts.funarguments{:});\n      fcn = @(t,x) mass (t, odeopts.funarguments{:}) ...\n                   \\ fcn (t, x, odeopts.funarguments{:});\n    endif\n  endif\n\n  if (numel (trange) > 2)\n    odeopts.Refine = [];  # disable Refine when specific times requested\n  endif\n\n  solution = integrate_adaptive (@runge_kutta_45_dorpri,\n                                 order, fcn, trange, init, odeopts);\n\n  ## Postprocessing, do whatever when terminating integration algorithm\n  if (odeopts.haveoutputfunction)  # Cleanup plotter\n    feval (odeopts.OutputFcn, [], [], \"done\", odeopts.funarguments{:});\n  endif\n  if (! isempty (odeopts.Events))   # Cleanup event function handling\n    ode_event_handler ([], [], [], [], [], \"done\");\n  endif\n\n  ## Print additional information if option Stats is set\n  if (strcmpi (odeopts.Stats, \"on\"))\n    nsteps    = solution.cntloop;             # cntloop from 2..end\n    nfailed   = solution.cntcycles - nsteps;  # cntcycl from 1..end\n    nfevals   = 6 * solution.cntcycles + 1;   # number of ode evaluations\n    ndecomps  = 0;  # number of LU decompositions\n    npds      = 0;  # number of partial derivatives\n    nlinsols  = 0;  # no. of linear systems solutions\n\n    printf (\"Number of successful steps: %d\\n\", nsteps);\n    printf (\"Number of failed attempts:  %d\\n\", nfailed);\n    printf (\"Number of function calls:   %d\\n\", nfevals);\n  endif\n\n  if (nargout == 2)\n    varargout{1} = solution.output_t; # Time stamps are first output argument\n    varargout{2} = solution.output_x; # Results are second output argument\n  elseif (nargout == 1)\n    varargout{1}.x = solution.ode_t.'; #Time stamps saved in field x (row vect.)\n    varargout{1}.y = solution.ode_x.'; #Results are saved in field y (row vect.)\n    varargout{1}.solver = solver; # Solver name is saved in field solver\n    if (! isempty (odeopts.Events))\n      varargout{1}.xe = solution.event{3}.'; # Time info when an event occurred\n      varargout{1}.ye = solution.event{4}.'; # Results when an event occurred\n      varargout{1}.ie = solution.event{2}.'; # Index info which event occurred\n    endif\n    if (strcmpi (odeopts.Stats, \"on\"))\n      varargout{1}.stats = struct ();\n      varargout{1}.stats.nsteps   = nsteps;\n      varargout{1}.stats.nfailed  = nfailed;\n      varargout{1}.stats.nfevals  = nfevals;\n      varargout{1}.stats.npds     = npds;\n      varargout{1}.stats.ndecomps = ndecomps;\n      varargout{1}.stats.nlinsols = nlinsols;\n    endif\n  elseif (nargout > 2)\n    varargout = cell (1,5);\n    varargout{1} = solution.output_t;\n    varargout{2} = solution.output_x;\n    if (! isempty (odeopts.Events))\n      varargout{3} = solution.event{3};  # Time info when an event occurred\n      varargout{4} = solution.event{4};  # Results when an event occurred\n      varargout{5} = solution.event{2};  # Index info which event occurred\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Demonstrate convergence order for ode45\n%! tol = 1e-5 ./ 10.^[0:8];\n%! for i = 1 : numel (tol)\n%!   opt = odeset (\"RelTol\", tol(i), \"AbsTol\", realmin);\n%!   [t, y] = ode45 (@(t, y) -y, [0, 1], 1, opt);\n%!   h(i) = 1 / (numel (t) - 1);\n%!   err(i) = norm (y .* exp (t) - 1, Inf);\n%! endfor\n%!\n%! ## Estimate order visually\n%! loglog (h, tol, \"-ob\",\n%!         h, err, \"-r\",\n%!         h, (h/h(end)) .^ 4 .* tol(end), \"k--\",\n%!         h, (h/h(end)) .^ 5 .* tol(end), \"k-\");\n%! axis tight\n%! xlabel (\"h\");\n%! ylabel (\"err(h)\");\n%! title (\"Convergence plot for ode45\");\n%! legend (\"imposed tolerance\", \"ode45 (relative) error\",\n%!         \"order 4\", \"order 5\", \"location\", \"northwest\");\n%!\n%! ## Estimate order numerically\n%! p = diff (log (err)) ./ diff (log (h))\n\n## We are using the Van der Pol equation for all tests.\n## Further tests also define a reference solution (computed at high accuracy)\n%!function ydot = fpol (t, y, varargin)  # The Van der Pol ODE\n%!  ydot = [y(2); (1 - y(1)^2) * y(2) - y(1)];\n%!endfunction\n%!function ref = fref ()       # The computed reference solution\n%!  ref = [0.32331666704577, -1.83297456798624];\n%!endfunction\n%!function [val, trm, dir] = feve (t, y, varargin)\n%!  val = fpol (t, y, varargin{:});  # We use the derivatives\n%!  trm = zeros (2,1);            # that's why component 2\n%!  dir = ones (2,1);             # does not seem to be exact\n%!endfunction\n%!function [val, trm, dir] = fevn (t, y, varargin)\n%!  val = fpol (t, y, varargin{:});  # We use the derivatives\n%!  trm = ones (2,1);             # that's why component 2\n%!  dir = ones (2,1);             # does not seem to be exact\n%!endfunction\n%!function mas = fmas (t, y, varargin)\n%!  mas = [1, 0; 0, 1];           # Dummy mass matrix for tests\n%!endfunction\n%!function mas = fmsa (t, y, varargin)\n%!  mas = sparse ([1, 0; 0, 1]);  # A sparse dummy matrix\n%!endfunction\n%!function out = fout (t, y, flag, varargin)\n%!  out = false;\n%!  if (strcmp (flag, \"init\"))\n%!    if (! isequal (size (t), [2, 1]))\n%!      error ('fout: step \"init\"');\n%!    endif\n%!  elseif (isempty (flag))\n%!  # Multiple steps can be sent in one function call\n%!    if (! isequal ( size (t), size (y)))\n%!      error ('fout: step \"calc\"');\n%!    endif\n%!  elseif (strcmp (flag, \"done\"))\n%!    if (! isempty (t))\n%!      warning ('fout: step \"done\"');\n%!    endif\n%!  else\n%!    error (\"fout: invalid flag <%s>\", flag);\n%!  endif\n%!endfunction\n%!function stop_solve = OutputSel_test (t, y, flag, x)\n%!  ## x == 1: select y(1)\n%!  ## x == 2: select y(2)\n%!  ## x == 3: select y([1,2])\n%!  persistent y_last\n%!  if (strcmp (flag, \"init\"))\n%!    y_last = y;\n%!    if (x == 1 || x == 2)\n%!      assert (length (y) == 1);\n%!    elseif (x == 3)\n%!      assert (length (y) == 2);\n%!    endif\n%!  elseif (strcmp (flag, \"done\"))\n%!    y_exp = fref ().';\n%!    if (x < 3)\n%!      assert (y_last, y_exp(x), 1e-4);\n%!    else\n%!      assert (y_last, y_exp, 1e-4);\n%!    endif\n%!  else  # flag == \"\"\n%!    y_last = y(:,end);\n%!    if (x == 1 || x == 2)\n%!      assert (length (t) == length (y));\n%!    else\n%!      assert (2 * length (t) == length (y(:)));\n%!    endif\n%!  endif\n%!  stop_solve = 0;\n%!endfunction\n%!\n%!test  # two output arguments\n%! [t, y] = ode45 (@fpol, [0 2], [2 0]);\n%! assert ([t(end), y(end,:)], [2, fref], 1e-2);\n%!test  # not too many steps\n%! [t, y] = ode45 (@fpol, [0 2], [2 0], odeset(\"Refine\",1));\n%! assert (size (t) < 20);\n%!test  # correct number of steps with Refine\n%! [t1, y1] = ode45 (@fpol, [0 2], [2 0], odeset (\"Refine\", 1));\n%! [t2, y2] = ode45 (@fpol, [0 2], [2 0], odeset (\"Refine\", 4));\n%! [t3, y3] = ode45 (@fpol, [0 2], [2 0]); #default Refine=4\n%! s = ode45 (@fpol, [0 2], [2 0], odeset (\"Refine\", 4));\n%! assert (length (t2) == length (t3));\n%! assert (length (t2) == 4*length (t1) - 3);\n%! assert (length (s.x) == length (t1));\n%!test  # anonymous function instead of real function\n%! fvdp = @(t,y) [y(2); (1 - y(1)^2) * y(2) - y(1)];\n%! [t, y] = ode45 (fvdp, [0 2], [2 0]);\n%! assert ([t(end), y(end,:)], [2, fref], 1e-2);\n%!test  # string instead of function\n%! [t, y] = ode45 (\"fpol\", [0 2], [2 0]);\n%! assert ([t(end), y(end,:)], [2, fref], 1e-2);\n%!test  # extra input arguments passed through\n%! [t, y] = ode45 (@fpol, [0 2], [2 0], 12, 13, \"KL\");\n%! assert ([t(end), y(end,:)], [2, fref], 1e-2);\n%!test  # empty ODEOPT structure *but* extra input arguments\n%! opt = odeset;\n%! [t, y] = ode45 (@fpol, [0 2], [2 0], opt, 12, 13, \"KL\");\n%! assert ([t(end), y(end,:)], [2, fref], 1e-2);\n%!test  # Solve another anonymous function below zero\n%! vref = [0, 14.77810590694212];\n%! [t, y] = ode45 (@(t,y) y, [-2 0], 2);\n%! assert ([t(end), y(end,:)], vref, 1e-1);\n%!test  # InitialStep option\n%! opt = odeset (\"InitialStep\", 1e-8, \"Refine\", 1);\n%! [t, y] = ode45 (@fpol, [0 0.2], [2 0], opt);\n%! assert ([t(2)-t(1)], [1e-8], 1e-9);\n%!test  # MaxStep option\n%! opt = odeset (\"MaxStep\", 1e-3);\n%! sol = ode45 (@fpol, [0 0.2], [2 0], opt);\n%! assert ([sol.x(5)-sol.x(4)], [1e-3], 1e-3);\n%!test  # Solve with intermediate step\n%! [t, y] = ode45 (@fpol, [0 1 2], [2 0]);\n%! assert (any ((t-1) == 0));\n%! assert ([t(end), y(end,:)], [2, fref], 1e-3);\n%!test  # Solve in backward direction starting at t=0\n%! vref = [-1.205364552835178, 0.951542399860817];\n%! sol = ode45 (@fpol, [0 -2], [2 0]);\n%! assert ([sol.x(end); sol.y(:,end)], [-2; vref'], 1e-2);\n%!test  # Solve in backward direction starting at t=2\n%! vref = [-1.205364552835178, 0.951542399860817];\n%! sol = ode45 (@fpol, [2 -2], fref);\n%! assert ([sol.x(end); sol.y(:,end)], [-2; vref'], 1e-2);\n%!test  # Solve in backward direction starting at t=2, with intermediate step\n%! vref = [-1.205364552835178, 0.951542399860817];\n%! [t, y] = ode45 (@fpol, [2 0 -2], fref);\n%! idx = find (y < 0, 1, \"first\") - 1;\n%! assert ([t(idx), y(idx,:)], [0,2,0], 1e-2);\n%! assert ([t(end), y(end,:)], [-2, vref], 1e-2);\n%!test  # Solve another anonymous function in backward direction\n%! vref = [-1, 0.367879437558975];\n%! sol = ode45 (@(t,y) y, [0 -1], 1);\n%! assert ([sol.x(end); sol.y(:,end)], vref', 1e-3);\n%!test  # Solve another anonymous function below zero\n%! vref = [0, 14.77810590694212];\n%! sol = ode45 (@(t,y) y, [-2 0], 2);\n%! assert ([sol.x(end); sol.y(:,end)], vref', 1e-3);\n%!test  # Solve in backward direction starting at t=0 with MaxStep option\n%! vref = [-1.205364552835178, 0.951542399860817];\n%! opt = odeset (\"MaxStep\", 1e-3);\n%! sol = ode45 (@fpol, [0 -2], [2 0], opt);\n%! assert ([abs(sol.x(8)-sol.x(7))], [1e-3], 1e-3);\n%! assert ([sol.x(end); sol.y(:,end)], [-2; vref'], 1e-3);\n%!test  # AbsTol option\n%! opt = odeset (\"AbsTol\", 1e-5);\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # AbsTol and RelTol option\n%! opt = odeset (\"AbsTol\", 1e-8, \"RelTol\", 1e-8);\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # RelTol and NormControl option -- higher accuracy\n%! opt = odeset (\"RelTol\", 1e-8, \"NormControl\", \"on\");\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-5);\n%!test  # Keeps initial values while integrating\n%! opt = odeset (\"NonNegative\", 2);\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; 2; 0], 0.5);\n%!test  # OutputSel 1 (see function OutputSel_test for asserts)\n%! opt = odeset (\"OutputFcn\", @(t, y, flag) OutputSel_test (t, y, flag, 1), ...\n%!               \"OutputSel\", 1);\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%!test  # OutputSel 2 (see function OutputSel_test for asserts)\n%! opt = odeset (\"OutputFcn\", @(t, y, flag) OutputSel_test (t, y, flag, 2), ...\n%!               \"OutputSel\", 2);\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%!test  # OutputSel [1,2] (see function OutputSel_test for asserts)\n%! opt = odeset (\"OutputFcn\", @(t, y, flag) OutputSel_test (t, y, flag, 3), ...\n%!               \"OutputSel\", [1,2]);\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%!test  # Stats must add further elements in sol\n%! opt = odeset (\"Stats\", \"on\");\n%! stat_str = evalc (\"sol = ode45 (@fpol, [0 2], [2 0], opt);\");\n%! assert (strncmp (stat_str, \"Number of successful steps:\", 27));\n%! assert (isfield (sol, \"stats\"));\n%! assert (isfield (sol.stats, \"nsteps\"));\n%!test  # Events option add further elements in sol\n%! opt = odeset (\"Events\", @feve);\n%! sol = ode45 (@fpol, [0 10], [2 0], opt);\n%! assert (isfield (sol, \"ie\"));\n%! assert (sol.ie(1), 2);\n%! assert (isfield (sol, \"xe\"));\n%! assert (isfield (sol, \"ye\"));\n%!test  # Events option, now stop integration\n%! opt = odeset (\"Events\", @fevn, \"NormControl\", \"on\");\n%! sol = ode45 (@fpol, [0 10], [2 0], opt);\n%! assert ([sol.ie, sol.xe, sol.ye.'],\n%!         [2.0, 2.496110, -0.830550, -2.677589], 2e-3);\n%!test  # Events option, five output arguments\n%! opt = odeset (\"Events\", @fevn, \"NormControl\", \"on\");\n%! [t, y, vxe, ye, vie] = ode45 (@fpol, [0 10], [2 0], opt);\n%! assert ([vie, vxe, ye],\n%!         [2.0, 2.496110, -0.830550, -2.677589], 2e-3);\n%!test  # Mass option as function\n%! opt = odeset (\"Mass\", @fmas);\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as matrix\n%! opt = odeset (\"Mass\", eye (2,2));\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as sparse matrix\n%! opt = odeset (\"Mass\", sparse (eye (2,2)));\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as function and sparse matrix\n%! opt = odeset (\"Mass\", @fmsa);\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n%!test  # Mass option as function and MStateDependence\n%! opt = odeset (\"Mass\", @fmas, \"MStateDependence\", \"strong\");\n%! sol = ode45 (@fpol, [0 2], [2 0], opt);\n%! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-3);\n\n## Note: The following options have no effect on this solver\n##       therefore it makes no sense to test them here:\n##\n## \"BDF\"\n## \"InitialSlope\"\n## \"JPattern\"\n## \"Jacobian\"\n## \"MassSingular\"\n## \"MaxOrder\"\n## \"MvPattern\"\n## \"Vectorized\"\n\n%!test  # Check that imaginary part of solution does not get inverted\n%! sol = ode45 (@(x,y) 1, [0 1], 1i);\n%! assert (imag (sol.y), ones (size (sol.y)));\n%! [x, y] = ode45 (@(x,y) 1, [0 1], 1i, odeset (\"Refine\", 1));\n%! assert (imag (y), ones (size (y)));\n\n%!error <Invalid call> ode45 ()\n%!error <Invalid call> ode45 (1)\n%!error <Invalid call> ode45 (1,2)\n%!error <TRANGE must be a numeric> ode45 (@fpol, {[0 25]}, [3 15 1])\n%!error <TRANGE must be a .* vector> ode45 (@fpol, [0 25; 25 0], [3 15 1])\n%!error <TRANGE must contain at least 2 elements> ode45 (@fpol, [1], [3 15 1])\n%!error <invalid time span> ode45 (@fpol, [1 1], [3 15 1])\n%!error <INIT must be a numeric> ode45 (@fpol, [0 25], {[3 15 1]})\n%!error <INIT must be a .* vector> ode45 (@fpol, [0 25], [3 15 1; 3 15 1])\n%!error <FCN must be a valid function handle> ode45 (1, [0 25], [3 15 1])\n"
  },
  {
    "path": "scripts/ode/odeget.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{val} =} odeget (@var{ode_opt}, @var{field})\n## @deftypefnx {} {@var{val} =} odeget (@var{ode_opt}, @var{field}, @var{default})\n##\n## Query the value of the property @var{field} in the ODE options structure\n## @var{ode_opt}.\n##\n## If called with two input arguments and the first input argument\n## @var{ode_opt} is an ODE option structure and the second input argument\n## @var{field} is a string specifying an option name, then return the option\n## value @var{val} corresponding to @var{field} from @var{ode_opt}.\n##\n## If called with an optional third input argument, and @var{field} is\n## not set in the structure @var{ode_opt}, then return the default value\n## @var{default} instead.\n## @seealso{odeset}\n## @end deftypefn\n\nfunction val = odeget (ode_opt, field, default = [])\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  validateattributes (ode_opt, {\"struct\"}, {\"nonempty\"});\n  validateattributes (field, {\"char\"}, {\"nonempty\"});\n\n  if (! isfield (ode_opt, field))\n    error (\"Octave:odeget:InvalidPropName\",\n           'odeget: Unrecognized property name \"%s\".', field);\n  else\n    val = ode_opt.(field);\n    if (isempty (val))\n      val = default;\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Return the manually changed value RelTol of the ODE options\n%! ## structure A.  If RelTol wouldn't have been changed then an\n%! ## empty matrix value would have been returned.\n%!\n%! A = odeset (\"RelTol\", 1e-1, \"AbsTol\", 1e-2);\n%! odeget (A, \"RelTol\", [])\n\n%!assert (odeget (odeset (), \"RelTol\"), [])\n%!assert (odeget (odeset (\"RelTol\", 10), \"RelTol\"), 10)\n%!assert (odeget (odeset (), \"RelTol\", 10), 10)\n%!assert (odeget (odeset (), \"Stats\"), [])\n%!assert (odeget (odeset (), \"Stats\", \"on\"), \"on\")\n%!assert (odeget (odeset (), \"Mass\"), [])\n%!assert (odeget (odeset (), \"AbsTol\", 1e-9), 1e-9)\n%!assert (odeget (odeset (\"AbsTol\", 1e-9), \"AbsTol\", []), 1e-9)\n%!test\n%! warning (\"off\", \"Octave:invalid-input-arg\", \"local\");\n%! assert (odeget (odeset (\"foo\", 42), \"foo\"), 42);\n\n## Test input validation\n%!error <Invalid call> odeget ()\n%!error <Invalid call> odeget (1)\n%!error odeget (1, \"opt1\")\n%!error odeget (struct (\"opt1\", 1), 1)\n%!error odeget (struct (\"opt1\", 1), \"foo\")\n"
  },
  {
    "path": "scripts/ode/odeplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{stop_solve} =} odeplot (@var{t}, @var{y}, @var{flag})\n##\n## Open a new figure window and plot the solution of an ode problem at each\n## time step during the integration.\n##\n## The types and values of the input parameters @var{t} and @var{y} depend on\n## the input @var{flag} that is of type string.  Valid values of @var{flag}\n## are:\n##\n## @table @option\n## @item @qcode{\"init\"}\n## The input @var{t} must be a column vector of length 2 with the first and\n## last time step (@code{[@var{tfirst} @var{tlast}]}.  The input @var{y}\n## contains the initial conditions for the ode problem (@var{y0}).\n##\n## @item @qcode{\"\"}\n## The input @var{t} must be a scalar double or vector specifying the time(s)\n## for which the solution in input @var{y} was calculated.\n##\n## @item @qcode{\"done\"}\n## The inputs should be empty, but are ignored if they are present.\n## @end table\n##\n## @code{odeplot} always returns false, i.e., don't stop the ode solver.\n##\n## Example: solve an anonymous implementation of the\n## @nospell{@qcode{\"Van der Pol\"}} equation and display the results while\n## solving.\n##\n## @example\n## @group\n## fvdp = @@(t,y) [y(2); (1 - y(1)^2) * y(2) - y(1)];\n##\n## opt = odeset (\"OutputFcn\", @@odeplot, \"RelTol\", 1e-6);\n## sol = ode45 (fvdp, [0 20], [2 0], opt);\n## @end group\n## @end example\n##\n## Background Information:\n## This function is called by an ode solver function if it was specified in\n## the @qcode{\"OutputFcn\"} property of an options structure created with\n## @code{odeset}.  The ode solver will initially call the function with the\n## syntax @code{odeplot ([@var{tfirst}, @var{tlast}], @var{y0}, \"init\")}.  The\n## function initializes internal variables, creates a new figure window, and\n## sets the x limits of the plot.  Subsequently, at each time step during the\n## integration the ode solver calls @code{odeplot (@var{t}, @var{y}, [])}.\n## At the end of the solution the ode solver calls\n## @code{odeplot ([], [], \"done\")} so that odeplot can perform any clean-up\n## actions required.\n## @seealso{odeset, odeget, ode23, ode45}\n## @end deftypefn\n\nfunction stop_solve = odeplot (t, y, flag)\n\n  ## No input argument checking is done for better performance\n  persistent hlines num_lines told yold;\n\n  ## odeplot never stops the integration\n  stop_solve = false;\n\n  if (isempty (flag))\n    ## Default case, plot and return a value\n    told = [told; t(:)];\n    yold = [yold, y];\n    for i = 1:num_lines\n      set (hlines(i), \"xdata\", told, \"ydata\", yold(i,:));\n    endfor\n    drawnow ();\n\n    retval = false;\n\n  elseif (strcmp (flag, \"init\"))\n    ## t is either the time slot [tstart tstop] or [t0, t1, ..., tn]\n    ## y is the initial value vector for the ode solution\n    told = t(1);\n    yold = y(:);\n    figure ();\n    hlines = plot (told, yold, \"o-\");\n    xlim ([t(1), t(end)]);  # Fix limits which also speeds up plotting\n    num_lines = numel (hlines);\n\n  elseif (strcmp (flag, \"done\"))\n    ## Cleanup after ode solver has finished.\n    hlines = num_lines = told = yold = [];\n\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Solve an anonymous implementation of the Van der Pol equation\n%! ## and display the results while solving\n%! fvdp = @(t,y) [y(2); (1 - y(1)^2) * y(2) - y(1)];\n%! opt = odeset (\"RelTol\", 1e-6);\n%! ode45 (fvdp, [0 20], [2 0], opt);\n\n%!demo\n%! ## Demonstrate simple multi-curve plot from t = 0 to 2 using initial,\n%! ## intermediate, and terminating odeplot calling syntaxes.\n%! t = linspace (0,2,10);\n%! y = [0.2*t; -0.1*t.^2-1; sin(t)];\n%!\n%! disp (\"Plot initial points\\n\");\n%! odeplot ([0 2], y(:,1), \"init\");\n%! title (\"Plot first time step\");\n%! pause (1.5);\n%!\n%! disp (\"Append single time step\\n\");\n%! odeplot (t(2), y(:,2), []);\n%! title (\"Append second time step\");\n%! pause (1.5);\n%!\n%! disp (\"Append remaining time steps\\n\");\n%! odeplot (t(3:end), y(:, 3:end), []);\n%! title (\"Plot all time steps\");\n%! pause (1.5);\n%!\n%! disp (\"Terminate odeplot\\n\");\n%! odeplot ([], [], \"done\");\n%! title (\"Plot complete\");\n"
  },
  {
    "path": "scripts/ode/odeset.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{odestruct} =} odeset ()\n## @deftypefnx {} {@var{odestruct} =} odeset (@var{\"field1\"}, @var{value1}, @var{\"field2\"}, @var{value2}, @dots{})\n## @deftypefnx {} {@var{odestruct} =} odeset (@var{oldstruct}, @var{\"field1\"}, @var{value1}, @var{\"field2\"}, @var{value2}, @dots{})\n## @deftypefnx {} {@var{odestruct} =} odeset (@var{oldstruct}, @var{newstruct})\n## @deftypefnx {} {} odeset ()\n##\n## Create or modify an ODE options structure.\n##\n## When called with no input argument and one output argument, return a new ODE\n## options structure that contains all possible fields initialized to their\n## default values.  If no output argument is requested, display a list of\n## the common ODE solver options along with their default value.\n##\n## If called with name-value input argument pairs @var{\"field1\"},\n## @var{\"value1\"}, @var{\"field2\"}, @var{\"value2\"}, @dots{} return a new\n## ODE options structure with all the most common option fields\n## initialized, @strong{and} set the values of the fields @var{\"field1\"},\n## @var{\"field2\"}, @dots{} to the values @var{value1}, @var{value2},\n## @enddots{}\n##\n## If called with an input structure @var{oldstruct} then overwrite the\n## values of the options @var{\"field1\"}, @var{\"field2\"}, @dots{} with\n## new values @var{value1}, @var{value2}, @dots{} and return the\n## modified structure.\n##\n## When called with two input ODE options structures @var{oldstruct} and\n## @var{newstruct} overwrite all values from the structure\n## @var{oldstruct} with new values from the structure @var{newstruct}.\n## Empty values in @var{newstruct} will not overwrite values in\n## @var{oldstruct}.\n##\n## The most commonly used ODE options, which are always assigned a value\n## by @code{odeset}, are the following:\n##\n## @table @asis\n## @item @code{AbsTol}: positive scalar | vector, def. @code{1e-6}\n## Absolute error tolerance.\n##\n## @item @code{BDF}: @{@qcode{\"off\"}@} | @qcode{\"on\"}\n## Use BDF formulas in implicit multistep methods.\n## @emph{Note}: This option is not yet implemented.\n##\n## @item @code{Events}: function_handle\n## Event function.  An event function must have the form\n## @code{[value, isterminal, direction] = my_events_f (t, y)}\n##\n## @item @code{InitialSlope}: vector\n## Consistent initial slope vector for DAE solvers.\n##\n## @item @code{InitialStep}: positive scalar\n## Initial time step size.\n##\n## @item @code{Jacobian}: matrix | function_handle\n## Jacobian matrix, specified as a constant matrix or a function of\n## time and state.\n##\n## @item @code{JConstant}: @{@qcode{\"off\"}@} | @qcode{\"on\"}\n## Specify whether the Jacobian is a constant matrix or depends on the\n## state.\n##\n## @item @code{JPattern}: sparse matrix\n## If the Jacobian matrix is sparse and non-constant but maintains a\n## constant sparsity pattern, specify the sparsity pattern.\n##\n## @item @code{Mass}: matrix | function_handle\n## Mass matrix, specified as a constant matrix or a function of\n## time and state.\n##\n## @item @code{MassSingular}: @{@qcode{\"maybe\"}@} | @qcode{\"yes\"} | @qcode{\"on\"}\n## Specify whether the mass matrix is singular.\n##\n## @item @code{MaxOrder}: @{@qcode{5}@} | @qcode{4} | @qcode{3} | @qcode{2} | @qcode{1}\n## Maximum order of formula.\n##\n## @item @code{MaxStep}: positive scalar\n## Maximum time step value.\n##\n## @item @code{MStateDependence}: @{@qcode{\"weak\"}@} | @qcode{\"none\"} | @qcode{\"strong\"}\n## Specify whether the mass matrix depends on the state or only on time.\n##\n## @item @code{MvPattern}: sparse matrix\n## If the mass matrix is sparse and non-constant but maintains a\n## constant sparsity pattern, specify the sparsity pattern.\n## @emph{Note}: This option is not yet implemented.\n##\n## @item @code{NonNegative}: scalar | vector\n## Specify elements of the state vector that are expected to remain\n## non-negative during the simulation.\n##\n## @item @code{NormControl}: @{@qcode{\"off\"}@} | @qcode{\"on\"}\n## Control error relative to the 2-norm of the solution, rather than its\n## absolute value.\n##\n## @item @code{OutputFcn}: function_handle\n## Function to monitor the state during the simulation.  For the form of\n## the function to use @pxref{XREFodeplot,,@code{odeplot}}.\n##\n## @item @code{OutputSel}: scalar | vector\n## Indices of elements of the state vector to be passed to the output\n## monitoring function.\n##\n## @item @code{Refine}: positive scalar\n## Specify whether output should be returned only at the end of each\n## time step or also at intermediate time instances.  The value should be\n## a scalar indicating the number of equally spaced time points to use\n## within each timestep at which to return output.\n##\n## @item @code{RelTol}: positive scalar\n## Relative error tolerance.\n##\n## @item @code{Stats}: @{@qcode{\"off\"}@} | @qcode{\"on\"}\n## Print solver statistics after simulation.\n##\n## @item @code{Vectorized}: @{@qcode{\"off\"}@} | @qcode{\"on\"}\n## Specify whether @code{odefcn} can be passed multiple values of the\n## state at once.\n##\n## @end table\n##\n## Field names that are not in the above list are also accepted and\n## added to the result structure.\n##\n## @seealso{odeget}\n## @end deftypefn\n\nfunction odestruct = odeset (varargin)\n\n  persistent p;\n\n  if (isempty (p))\n    p = inputParser ();\n    p.addParameter (\"AbsTol\", []);\n    p.addParameter (\"BDF\", []);\n    p.addParameter (\"Events\", []);\n    p.addParameter (\"InitialSlope\", []);\n    p.addParameter (\"InitialStep\", []);\n    p.addParameter (\"Jacobian\", []);\n    p.addParameter (\"JConstant\", []);\n    p.addParameter (\"JPattern\", []);\n    p.addParameter (\"Mass\", []);\n    p.addParameter (\"MassSingular\", []);\n    p.addParameter (\"MaxOrder\", []);\n    p.addParameter (\"MaxStep\", []);\n    p.addParameter (\"MStateDependence\", []);\n    p.addParameter (\"MvPattern\", []);\n    p.addParameter (\"NonNegative\", []);\n    p.addParameter (\"NormControl\", []);\n    p.addParameter (\"OutputFcn\", []);\n    p.addParameter (\"OutputSel\", []);\n    p.addParameter (\"Refine\", []);\n    p.addParameter (\"RelTol\", []);\n    p.addParameter (\"Stats\", []);\n    p.addParameter (\"Vectorized\", []);\n    p.KeepUnmatched = true;\n  endif\n\n  if (nargin == 0 && nargout == 0)\n    print_options ();\n  else\n    p.parse (varargin{:});\n    odestruct = p.Results;\n    odestruct_extra = p.Unmatched;\n\n    xtra_fields = fieldnames (odestruct_extra);\n    if (! isempty (xtra_fields))\n      ## Merge extra fields into existing odestruct\n      for fldname = sort (xtra_fields.')\n        fldname = fldname{1};\n        warning (\"Octave:invalid-input-arg\",\n                 \"odeset: unknown option \\\"%s\\\"\\n\", fldname);\n        odestruct.(fldname) = odestruct_extra.(fldname);\n      endfor\n    endif\n\n  endif\n\nendfunction\n\n## function to print all possible options\nfunction print_options ()\n\n  disp (\"List of the most common ODE solver options.\");\n  disp (\"Default values are in square brackets.\");\n  disp (\"\");\n  disp ('             AbsTol:  scalar or vector, >0, [1e-6]');\n  disp ('                BDF:  binary, {[\"off\"], \"on\"}');\n  disp ('             Events:  function_handle, []');\n  disp ('       InitialSlope:  vector, []');\n  disp ('        InitialStep:  scalar, >0, []');\n  disp ('           Jacobian:  matrix or function_handle, []');\n  disp ('          JConstant:  binary, {[\"off\"], \"on\"}');\n  disp ('           JPattern:  sparse matrix, []');\n  disp ('               Mass:  matrix or function_handle, []');\n  disp ('       MassSingular:  switch, {[\"maybe\"], \"no\", \"yes\"}');\n  disp ('           MaxOrder:  switch, {[5], 1, 2, 3, 4, }');\n  disp ('            MaxStep:  scalar, >0, []');\n  disp ('   MStateDependence:  switch, {[\"weak\"], \"none\", \"strong\"}');\n  disp ('          MvPattern:  sparse matrix, []');\n  disp ('        NonNegative:  vector of integers, []');\n  disp ('        NormControl:  binary, {[\"off\"], \"on\"}');\n  disp ('          OutputFcn:  function_handle, []');\n  disp ('          OutputSel:  scalar or vector, []');\n  disp ('             Refine:  scalar, integer, >0, []');\n  disp ('             RelTol:  scalar, >0, [1e-3]');\n  disp ('              Stats:  binary, {[\"off\"], \"on\"}');\n  disp ('         Vectorized:  binary, {[\"off\"], \"on\"}');\n\nendfunction\n\n\n%!demo\n%! ## A new ODE options structure with default values is created.\n%!\n%! odeoptA = odeset ()\n\n%!demo\n%! ## A new ODE options structure with manually set options\n%! ## for \"AbsTol\" and \"RelTol\" is created.\n%!\n%! odeoptB = odeset (\"AbsTol\", 1e-2, \"RelTol\", 1e-1)\n\n%!demo\n%! ## A new ODE options structure is created from odeoptB with\n%! ## a modified value for option \"NormControl\".\n%!\n%! odeoptB = odeset (\"AbsTol\", 1e-2, \"RelTol\", 1e-1)\n%! odeoptC = odeset (odeoptB, \"NormControl\", \"on\")\n\n%!test\n%! odeoptA = odeset ();\n%! assert (isstruct (odeoptA));\n%! assert (numfields (odeoptA), 22);\n%! assert (all (structfun (\"isempty\", odeoptA)));\n\n%!shared odeoptB, odeoptC\n%!test\n%! odeoptB = odeset (\"ABSTOL\", 1e-2, \"reltol\", 1e-1);\n%! assert (odeoptB.AbsTol, 1e-2);  # Check canonicalization of name\n%! assert (odeoptB.RelTol, 1e-1);\n\n%!test\n%! odeoptC = odeset (odeoptB, \"NormControl\", \"on\");\n%! assert (odeoptC.AbsTol, 1e-2);       # check values from first struct copied\n%! assert (odeoptC.NormControl, \"on\");  # check new values override old ones\n\n%!test\n%! odeoptD = odeset (odeoptB, odeoptC);\n%! assert (odeoptD, odeoptC);\n\n## Test custom user-defined option\n%!test\n%! warning (\"off\", \"Octave:invalid-input-arg\", \"local\");\n%! odeopt = odeset (\"NewtonTol\", 3);\n%! assert (odeopt.NewtonTol, 3);\n\n## Test input validation\n%!error <argument 'opt1' is not a declared parameter> odeset (\"opt1\")\n%!error odeset (1, 1)\n%!error <argument 'opt1' is not a declared parameter> odeset (odeset (), \"opt1\")\n%!error odeset (odeset (), 1, 1)\n%!error <'Re' matches more than one Parameter: 'Refine', 'RelTol'>\n%! odeset ('Re', 1);\n"
  },
  {
    "path": "scripts/ode/private/AbsRel_norm.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {retval =} AbsRel_norm (@var{x}, @var{x_old}, @var{AbsTol}, @var{RelTol}, @var{normcontrol}, @var{y})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction retval = AbsRel_norm (x, x_old, AbsTol, RelTol, normcontrol, y = zeros (size (x)))\n\n  if (normcontrol)\n    sc = max (AbsTol(:), RelTol * max (sqrt (sumsq (x)), sqrt (sumsq (x_old))));\n    retval = sqrt (sumsq ((x - y))) / sc;\n  else\n    sc = max (AbsTol(:), RelTol .* max (abs (x), abs (x_old)));\n    retval = max (abs (x - y) ./ sc);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/check_default_input.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{fcn} =} check_default_input (@var{fcn}, @var{trange}, @var{solver}, @var{y0}, @var{yp0})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction fcn = check_default_input (fcn, trange, solver, y0, yp0)\n\n  if (nargin < 4)\n    print_usage ();\n  endif\n\n  ## Check fcn\n  validateattributes (fcn, {\"function_handle\", \"char\"}, {}, solver, \"fcn\");\n\n  if (! (nargin (fcn) == nargin - 2))\n    error (\"Octave:invalid-input-arg\",\n           [solver \": invalid value assigned to field 'fcn'\"]);\n  endif\n\n  if (ischar (fcn))\n    if (! exist (fcn))\n      error (\"Octave:invalid-input-arg\",\n             [solver \": function '\" fcn \"' not found\"]);\n    endif\n    fcn = str2func (fcn);\n  endif\n  if (! is_function_handle (fcn))\n    error (\"Octave:invalid-input-arg\",\n           [solver \": invalid value assigned to field '\" fcn \"'\"]);\n  endif\n\n  ## Check trange\n  validateattributes (trange, {\"float\"}, {\"vector\", \"real\"}, solver, \"trange\");\n\n  if (numel (trange) < 2)\n    error (\"Octave:invalid-input-arg\",\n           [solver \": invalid value assigned to field 'trange'\"]);\n  elseif (! ((all (diff (trange) > 0)) || all (diff (-trange) > 0)))\n    error (\"Octave:invalid-input-arg\",\n           [solver \": invalid value assigned to field 'trange'\"]);\n  endif\n\n  ## Check y0 and yp0\n  if (! isnumeric (y0) || ! isvector (y0))\n    error (\"Octave:invalid-input-arg\",\n           [solver \": Y0 must be a numeric vector\"]);\n  endif\n  y0 = y0(:);\n\n  if (nargin == 5)\n    if (! isnumeric (yp0) || ! isvector (yp0))\n      error (\"Octave:invalid-input-arg\",\n             [solver \": YP0 must be a numeric vector\"]);\n    endif\n    yp0 = yp0(:);\n\n    n = numel (feval (fcn, trange(1), y0, yp0));\n    validateattributes (yp0, {\"float\"}, {\"numel\", n}, solver, \"yp0\");\n  else\n    n = numel (feval (fcn, trange(1), y0));\n  endif\n\n  validateattributes (y0, {\"float\"}, {\"numel\", n}, solver, \"y0\");\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/integrate_adaptive.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{solution} =} integrate_adaptive (@var{@@stepper}, @var{order}, @var{@@fcn}, @var{tspan}, @var{x0}, @var{options})\n##\n## This function file can be called by an ODE solver function in order to\n## integrate the set of ODEs on the interval @var{[t0, t1]} with an adaptive\n## timestep.\n##\n## The function returns a structure @var{solution} with two fields: @var{t}\n## and @var{y}.  @var{t} is a column vector and contains the time stamps.\n## @var{y} is a matrix in which each column refers to a different unknown\n## of the problem and the row number is the same as the @var{t} row number.\n## Thus, each row of the matrix @var{y} contains the values of all unknowns at\n## the time value contained in the corresponding row in @var{t}.\n##\n## The first input argument must be a function handle or inline function\n## representing the stepper, i.e., the function responsible for step-by-step\n## integration.  This function discriminates one method from the others.\n##\n## The second input argument is the order of the stepper.  It is needed\n## to compute the adaptive timesteps.\n##\n## The third input argument is a function handle or inline function that\n## defines the ODE:\n##\n## @ifhtml\n##\n## @example\n## @math{y' = f(t,y)}\n## @end example\n##\n## @end ifhtml\n## @ifnothtml\n## @math{y' = f(t,y)}.\n## @end ifnothtml\n##\n## The fourth input argument is the time vector which defines the integration\n## interval, i.e., @var{[tspan(1), tspan(end)]} and all intermediate elements\n## are taken as times at which the solution is required.\n##\n## The fifth argument represents the initial conditions for the ODEs and the\n## last input argument contains some options that may be needed for the\n## stepper.\n##\n## @end deftypefn\n\nfunction solution = integrate_adaptive (stepper, order, fcn, tspan, x0,\n                                        options)\n\n  fixed_times = numel (tspan) > 2;\n\n  t_new = t_old = ode_t = output_t = tspan(1);\n  x_new = x_old = ode_x = output_x = x0(:);\n\n  ## Get first initial timestep\n  dt = options.InitialStep;\n  if (isempty (dt))\n    dt = starting_stepsize (order, fcn, ode_t, ode_x,\n                            options.AbsTol, options.RelTol,\n                            strcmp (options.NormControl, \"on\"),\n                            options.funarguments);\n  endif\n\n  dir = options.direction;\n  dt = dir * min (abs (dt), options.MaxStep);\n\n  options.comp = 0.0;\n\n  ## Factor multiplying the stepsize guess\n  facmin = 0.8;\n  facmax = 1.5;\n  fac = 0.38^(1/(order+1));  # formula taken from Hairer\n\n  ## Initialize Refine value\n  refine = options.Refine;\n  if (isempty (refine))\n    refine = 1;\n  elseif ((refine != round (refine)) || (refine < 1))\n    refine = 1;\n    warning (\"integrate_adaptive:invalid_refine\",\n               [\"Invalid value of Refine.  Refine must be a positive \" ...\n                \"integer.  Setting Refine = 1.\"] );\n  endif\n\n  ## Initialize the OutputFcn\n  if (options.haveoutputfunction)\n    if (! isempty (options.OutputSel))\n      solution.retout = output_x(options.OutputSel, end);\n    else\n      solution.retout = output_x;\n    endif\n    feval (options.OutputFcn, tspan, solution.retout, \"init\",\n           options.funarguments{:});\n  endif\n\n  ## Initialize the EventFcn\n  have_EventFcn = false;\n  if (! isempty (options.Events))\n    have_EventFcn  = true;\n    options.Events = @(t,y) options.Events (t, y, options.funarguments{:});\n    ode_event_handler (options.Events, tspan(1), ode_x, ...\n                       [], order, \"init\");\n  endif\n\n  if (options.havenonnegative)\n    nn = options.NonNegative;\n  endif\n\n  solution.cntloop = 0;\n  solution.cntcycles = 0;\n  solution.cntsave = 2;\n  solution.unhandledtermination = true;\n  ireject = 0;\n\n  NormControl = strcmp (options.NormControl, \"on\");\n  k_vals = [];\n  iout = istep = 1;\n\n  while (dir * t_old < dir * tspan(end))\n\n    ## Compute integration step from t_old to t_new = t_old + dt\n    [t_new, options.comp] = kahan (t_old, options.comp, dt);\n    [t_new, x_new, x_est, new_k_vals] = ...\n      stepper (fcn, t_old, x_old, dt, options, k_vals, t_new);\n\n    solution.cntcycles += 1;\n\n    if (options.havenonnegative)\n      x_new(nn, end) = abs (x_new(nn, end));\n      x_est(nn, end) = abs (x_est(nn, end));\n    endif\n\n    err = AbsRel_norm (x_new, x_old, options.AbsTol, options.RelTol,\n                       NormControl, x_est);\n\n    ## Accept solution only if err <= 1.0\n    if (err <= 1)\n\n      solution.cntloop += 1;\n      ireject = 0;              # Clear reject counter\n      terminal_event = false;\n      terminal_output = false;\n\n      istep++;\n      ode_t(istep) = t_new;\n      ode_x(:, istep) = x_new;\n      iadd = 0;                 # Number of output points added this iteration\n\n      ## Check for Events\n      if (have_EventFcn)\n        solution.event = ode_event_handler ([], t_new, x_new, ...\n                                            new_k_vals, [], []);\n        ## Check for terminal Event\n        if (! isempty (solution.event{1}) && solution.event{1} == 1)\n          ode_t(istep) = solution.event{3}(end);\n          ode_x(:, istep) = solution.event{4}(end, :).';\n          solution.unhandledtermination = false;\n          terminal_event = true;\n        endif\n      endif\n\n      ## Interpolate to specified or Refined points\n      if (fixed_times)\n        t_caught = find ((dir * tspan(iout:end) > dir * t_old) ...\n                         & (dir * tspan(iout:end) <= dir * ode_t(istep)));\n        t_caught = t_caught + iout - 1;\n        iadd = length (t_caught);\n        if (! isempty (t_caught))\n          output_t(t_caught) = tspan(t_caught);\n          iout = max (t_caught);\n          output_x(:, t_caught) = ...\n            runge_kutta_interpolate (order, [t_old t_new], [x_old x_new], ...\n                                     output_t(t_caught), new_k_vals);\n        endif\n        ## Add a possible additional output value if we found a terminal Event\n        if ((terminal_event == true) && ...\n            (dir * ode_t(istep) > dir * output_t(iout)))\n          iadd += 1;\n          iout += 1;\n          output_x(:, iout) = ode_x(:, istep);\n          output_t(iout) = ode_t(istep);\n        endif\n      elseif (refine > 1)\n        iadd = refine;\n        tadd = linspace (t_old, ode_t(istep), refine + 1);\n        tadd = tadd(2:end);\n        output_x(:, iout + (1:iadd)) = ...\n          runge_kutta_interpolate (order, [t_old t_new], [x_old x_new], ...\n                                   tadd, new_k_vals);\n        output_t(iout + (1:iadd)) = tadd;\n        iout = length (output_t);\n      else                         # refine = 1\n        iadd = 1;\n        iout += iadd;\n        output_x(:, iout) = ode_x(:, istep);\n        output_t(iout) = ode_t(istep);\n      endif\n\n      ## Call OutputFcn\n      if ((options.haveoutputfunction) && (iadd > 0))\n        xadd = output_x(:, (iout-iadd+1):end);\n        tadd = output_t((iout-iadd+1):end);\n        if (! isempty (options.OutputSel))\n          xadd = xadd(options.OutputSel, :);\n        endif\n        stop_solve = feval (options.OutputFcn, tadd, xadd, ...\n                            [], options.funarguments{:});\n        if (stop_solve)\n          solution.unhandledtermination = false;\n          terminal_output = true;\n        endif\n      endif\n      if (terminal_event || terminal_output)\n        break;                     # break from main loop\n      endif\n\n\n      ## move to next time-step\n      t_old = t_new;\n      x_old = x_new;\n      k_vals = new_k_vals;\n\n    else  # error condition\n\n      ireject += 1;\n\n      ## Stop solving if, in the last 5,000 steps, no successful valid\n      ## value has been found.\n      if (ireject >= 5_000)\n        error ([\"integrate_adaptive: Solving was not successful. \", ...\n                \" The iterative integration loop exited at time\", ...\n                \" t = %f before the endpoint at tend = %f was reached. \", ...\n                \" This happened because the iterative integration loop\", ...\n                \" did not find a valid solution at this time stamp. \", ...\n                \" Try to reduce the value of 'InitialStep' and/or\", ...\n                \" 'MaxStep' with the command 'odeset'.\\n\"],\n               t_old, tspan(end));\n      endif\n\n    endif\n\n    ## Compute next timestep, formula taken from Hairer\n    err += eps;  # avoid divisions by zero\n    dt *= min (facmax, max (facmin, fac * (1 / err)^(1 / (order + 1))));\n    dt = dir * min (abs (dt), options.MaxStep);\n    if (! (abs (dt) > eps (ode_t(end))))\n      break;\n    endif\n\n    ## Make sure we don't go past tpan(end)\n    dt = dir * min (abs (dt), abs (tspan(end) - t_old));\n\n  endwhile\n\n  ## Check if integration of the ode has been successful\n  if (dir * ode_t(end) < dir * tspan(end))\n    if (solution.unhandledtermination == true)\n      warning (\"integrate_adaptive:unexpected_termination\",\n               [\" Solving was not successful. \", ...\n                \" The iterative integration loop exited at time\", ...\n                \" t = %f before the endpoint at tend = %f was reached. \", ...\n                \" This may happen if the stepsize becomes too small. \", ...\n                \" Try to reduce the value of 'InitialStep'\", ...\n                \" and/or 'MaxStep' with the command 'odeset'.\"],\n               ode_t(end), tspan(end));\n    endif\n  endif\n\n  ## Set up return structure\n  solution.ode_t = ode_t(:);\n  solution.ode_x = ode_x.';\n  solution.output_t = output_t(:);\n  solution.output_x = output_x.';\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/kahan.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{sum} =} kahan (@var{sum}, @var{comp}, @var{term})\n## @deftypefnx {} {[@var{sum}, @var{comp}] =} kahan (@var{sum}, @var{comp}, @var{term})\n##\n## This function implements the Kahan summation algorithm, also known as\n## compensated summation.\n##\n## The algorithm significantly reduces the numerical error in the total\n## obtained by adding a sequence of finite precision floating point numbers,\n## compared to the straightforward approach.  For more details\n## see @url{http://en.wikipedia.org/wiki/Kahan_summation_algorithm}.\n## This function is called by @code{integrate_adaptive} to better catch\n## equality comparisons.\n##\n## The first input argument is the variable that will contain the summation.\n## This variable is also returned as the first output argument in order to\n## reuse it in subsequent calls to @code{kahan} function.\n##\n## The second input argument contains the compensation term and is returned\n## as the second output argument so that it can be reused in future calls of\n## the same summation.\n##\n## The third input argument @var{term} is the variable to be added to\n## @var{sum}.\n## @end deftypefn\n\nfunction [sum, comp] = kahan (sum, comp, term)\n\n  y = term - comp;\n  t = sum + y;\n  comp = (t - sum) - y;\n  sum = t;\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/ode_event_handler.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{retval} =} ode_event_handler (@var{@@evt_fcn}, @var{t}, @var{y}, @var{k_vals}, @var{ord}, @var{flag})\n##\n## Return the solution of the event function (@var{@@evt_fcn}) which is\n## specified in the form of a function handle.\n##\n## The second input argument @var{t} is a scalar double and specifies the time\n## of the event evaluation.\n##\n## The third input argument @var{y} is a scalar or a column vector of type\n## double which specifies the solution(s) at time @var{t}.\n##\n## The fourth input argument @var{k_vals} is a vector or matrix with the\n## k values obtained from the most recent integration step.\n##\n## The fifth input argument @var{ord} the order of the integration technique.\n##\n## The sixth input argument @var{flag} is of type string.  Valid values are:\n##\n## @table @option\n## @item  @qcode{\"init\"}\n## Initialize internal persistent variables of the function\n## @code{ode_event_handler} and return an empty cell array of size 4.\n##\n## @item  @qcode{\"\"}\n## (default) Evaluate the event function and return the solution @var{retval}\n## as a cell array of size 4.  Inputs @var{ord} and @var{@@evt_fcn} are\n## ignored, since they are set in the @qcode{\"init\"} step.\n##\n## @item  @qcode{\"done\"}\n## Clean up internal variables of the function @code{ode_event_handler} and\n## return an empty cell array of size 4.  All other inputs are ignored with\n## this flag.\n## @end table\n##\n## This function is an ODE internal helper function and it should never be\n## necessary to call it directly.\n## @end deftypefn\n\nfunction retval = ode_event_handler (evt_fcn, t, y, k_vals, ord, flag = \"\")\n\n  ## No error handling has been implemented in this function to achieve\n  ## the highest performance possible.\n\n  ## retval{1} is true (to terminate) or false (to continue)\n  ## retval{2} is the index information for which an event occurred\n  ## retval{3} is the time information column vector\n  ## retval{4} is the line by line result information matrix\n\n  ## These persistent variables store the results and time value from the\n  ## processing in the previous time stamp.\n  ## evtold  the results from the event function\n  ## told    the time stamp\n  ## yold    the ODE result\n  ## retcell the return values cell array\n  ## evtcnt  the counter for how often this function has been called\n  persistent evtold told yold retcell order evtfcn;\n  persistent evtcnt = 1;   # Don't remove.  Required for Octave parser.\n  persistent firstrun = true;\n\n  if (isempty (flag))\n    ## Process the event, i.e.,\n    ## find the zero crossings for either a rising or falling edge\n    [evt, term, dir] = evtfcn (t, y);\n\n    ## We require that all return values be row vectors\n    evt = evt(:).'; term = term(:).'; dir = dir(:).';\n\n    ## Check if one or more signs of the event has changed\n    signum = (sign (evtold) != sign (evt));\n    if (any (signum))         # One or more values have changed\n      ## Find events where either rising and falling edges are counted (dir==0)\n      ## or where the specified edge type matches the event edge type.\n      idx = signum & (dir == 0 | dir == sign (evt));\n      idx = find (idx);  # convert logical to numeric index or []\n\n      ## Create new output values if a valid index has been found\n      if (! isempty (idx))\n        ## Change the persistent result cell array\n        if (firstrun)\n          ## Matlab compatibility requires ignoring condition on first run.\n          retcell{1} = false;\n        else\n          retcell{1} = any (term(idx));     # Stop integration or not\n        endif\n        evtcntnew = 1;\n        ## Add all events this step to the output.\n        for idx2 = idx                      # Loop through all values of idx\n          ## Calculate the time stamp when the event function returned 0 and\n          ## calculate new values for the integration results.  We do both by\n          ## root solving, calling the Event function with y values from\n          ## the RK interpolation polynomial.  Set tolerance to zero (actually\n          ## uses machine tolerance based criterion in this case) since we\n          ## don't have a way for the user to specify an acceptable tolerance.\n          ## For simple Event functions, this means we're basically root\n          ## finding on a small interval for a polynomial, so we expect\n          ## pretty quick convergence.\n          tvals = [told t];\n          yvals = [yold y];\n          tnew = fzero (@(t2) evtfcn_val (evtfcn, t2, ...\n                        runge_kutta_interpolate (order, tvals, yvals, ...\n                        t2, k_vals), idx2), tvals, optimset (\"TolX\", 0));\n          ynew = runge_kutta_interpolate (order, tvals, yvals, tnew, k_vals);\n\n          tnews(evtcntnew, 1) = tnew;\n          ynews(evtcntnew, :) = ynew;\n          terms(evtcntnew, 1) = term(idx2);\n          evtcntnew += 1;\n        endfor\n        ## Sort by time of event\n        if (length (idx) > 1)\n          [tnews, idx_sort] = sort (tnews, \"ascend\");\n          idxs = idx(idx_sort);\n          ynews = ynews(idx_sort,:);\n          terms = terms(idx_sort);\n        else\n          idxs = idx;\n        endif\n        ## Check for terminal events and remove any events after terminal.\n        ## Any events at same time as first terminal event will be retained.\n        idx3 = find (terms, 1);          # Find first terminal event by time\n        if (! isempty (idx3))\n          t_cutoff = tnews(idx3);\n          ## Last index to return\n          evtcntnew = find (tnews == t_cutoff, 1, \"last\");\n        else\n          evtcntnew = length (terms);         # Return all indices if no terminal\n        endif\n        idxs = idxs(1:evtcntnew);\n        tnews = tnews(1:evtcntnew);\n\n        ## Populate return values with sorted, clipped values\n        evtcntrange = evtcnt - 1 + (1:evtcntnew);\n        evtcnt += evtcntnew;\n        retcell{2}(evtcntrange, 1) = idxs(:);\n        retcell{3}(evtcntrange, 1) = tnews(:);\n        retcell{4}(evtcntrange, :) = ynews(1:evtcntnew,:);\n      endif\n\n    endif\n\n    firstrun = false;\n    evtold = evt; told = t; yold = y;\n    retval = retcell;\n\n  elseif (strcmp (flag, \"init\"))\n    ## Call the event function if an event function has been defined to\n    ## initialize the internal variables of the event function and to get\n    ## a value for evtold.\n\n    firstrun = true;\n    order = ord;\n    evtfcn = evt_fcn;\n\n    [evtold, ~, ~] = evtfcn (t, y);\n\n    ## We require that all return values be row vectors\n    evtold = evtold(:).'; told = t; yold = y;\n    evtcnt = 1;\n    retval = retcell = cell (1,4);\n\n  elseif (strcmp (flag, \"done\"))\n    ## Clear this event handling function\n    firstrun = true;\n    evtold = told = yold = evtcnt = order = evtfcn = [];\n    retval = retcell = cell (1,4);\n\n  endif\n\nendfunction\n\nfunction val = evtfcn_val (evtfcn, t, y, ind)\n  [evt, ~, ~] = evtfcn (t, y);\n  val = evt(ind);\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/odedefaults.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{defaults}, @var{classes}, @var{attributes}] =} odedefaults (@var{n}, @var{t0}, @var{tf})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [rdefaults, rclasses, rattributes] = odedefaults (n, t0, tf)\n\n  persistent defaults = struct (\"AbsTol\", 1e-6,\n                                \"BDF\", \"off\",\n                                \"Events\", [],\n                                \"InitialSlope\", zeros (n,1),\n                                \"InitialStep\", [],\n                                \"Jacobian\", [],\n                                \"JConstant\", \"off\",\n                                \"JPattern\", [],\n                                \"Mass\", [],\n                                \"MassSingular\", \"maybe\",\n                                \"MaxOrder\", 5,\n                                \"MaxStep\", 0.1 * abs (tf - t0),\n                                \"MStateDependence\", \"weak\",\n                                \"MvPattern\", [],\n                                \"NonNegative\", [],\n                                \"NormControl\", \"off\",\n                                \"OutputFcn\", [],\n                                \"OutputSel\", [],\n                                \"Refine\", 1,\n                                \"RelTol\", 1e-3,\n                                \"Stats\", \"off\",\n                                \"Vectorized\", \"off\");\n\n  defaults.InitialSlope = zeros (n,1);\n  defaults.MaxStep = 0.1 * abs (tf -t0);\n\n  persistent classes = struct (\"AbsTol\", {{\"float\"}},\n                               \"BDF\", \"char\",\n                               \"Events\", {{\"function_handle\"}},\n                               \"InitialSlope\", {{\"float\"}},\n                               \"InitialStep\", {{\"float\"}},\n                               \"Jacobian\", {{\"float\", \"function_handle\", \"cell\"}},\n                               \"JConstant\", \"char\",\n                               \"JPattern\", {{\"float\"}},\n                               \"Mass\", {{\"float\", \"function_handle\"}},\n                               \"MassSingular\", \"char\",\n                               \"MaxOrder\", {{\"float\"}},\n                               \"MaxStep\", {{\"float\"}},\n                               \"MStateDependence\", \"char\",\n                               \"MvPattern\", {{\"float\"}},\n                               \"NonNegative\", {{\"float\"}},\n                               \"NormControl\", \"char\",\n                               \"OutputFcn\", {{\"function_handle\"}},\n                               \"OutputSel\", {{\"float\"}},\n                               \"Refine\", {{\"float\"}},\n                               \"RelTol\", {{\"float\"}},\n                               \"Stats\", \"char\",\n                               \"Vectorized\", \"char\");\n\n  persistent attributes = struct (\"AbsTol\", {{\"real\", \"vector\", \"positive\"}},\n                                  \"BDF\", {{\"on\", \"off\"}},\n                                  \"Events\", {{}},\n                                  \"InitialSlope\", {{\"real\", \"vector\", \"numel\", n}},\n                                  \"InitialStep\", {{\"positive\", \"scalar\"}},\n                                  \"Jacobian\", {{}},\n                                  \"JConstant\", {{\"on\", \"off\"}},\n                                  \"JPattern\", {{}},\n                                  \"Mass\", {{}},\n                                  \"MassSingular\", {{\"no\", \"maybe\", \"yes\"}},\n                                  \"MaxOrder\", {{\">=\", 0, \"<=\", 5, \"integer\"}},\n                                  \"MaxStep\", {{\"positive\", \"scalar\", \"real\"}},\n                                  \"MStateDependence\", {{\"weak\", \"strong\", \"none\"}},\n                                  \"MvPattern\", {{}},\n                                  \"NonNegative\", {{\"vector\", \"integer\", \"positive\"}},\n                                  \"NormControl\", {{\"on\", \"off\"}},\n                                  \"OutputFcn\", {{}},\n                                  \"OutputSel\", {{\"vector\", \"integer\", \"positive\",...\n                                                 \">\", 0, \"<=\", n}},\n                                  \"Refine\", {{\"scalar\", \">\", 0, \"integer\"}},\n                                  \"RelTol\", {{\"scalar\", \"positive\", \"real\"}},\n                                  \"Stats\", {{\"on\", \"off\"}},\n                                  \"Vectorized\", {{\"on\", \"off\"}});\n\n  attributes.InitialSlope = {\"real\", \"vector\", \"numel\", n};\n  attributes.OutputSel = {\"vector\", \"integer\", \"positive\", \">\", 0, \"<=\", n};\n\n  rdefaults = defaults;\n  rclasses = classes;\n  rattributes = attributes;\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/odemergeopts.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{options} =} odemergeopts (@var{caller}, @var{useroptions}, @var{options}, @var{classes}, @var{attributes}, @var{solver})\n## Undocumented internal function.\n## @end deftypefn\n\n## FIXME: there are some calls to odemergeopts with a \"solver\" argument\n## but we don't use that here.  Should the calls be fixed or should we\n## do something with the solver argument here?\n\nfunction options = odemergeopts (caller, useroptions, options, classes, attributes, solver)\n\n  for [value, key] = options\n\n    if (isfield (useroptions, key) && ! isempty (useroptions.(key)))\n\n      if (! strcmp (classes.(key), \"char\"))\n        validateattributes (useroptions.(key), classes.(key),\n                            attributes.(key), caller, key);\n\n      elseif (ischar (useroptions.(key)))\n        validatestring (useroptions.(key), attributes.(key), caller, key);\n\n      else\n        error (\"Octave:invalid-input-arg\",\n               [caller \": invalid value assigned to field '%s'\"], key);\n      endif\n\n      options.(key) = useroptions.(key);\n\n    endif\n\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/runge_kutta_23.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{t_next}, @var{x_next}] =} runge_kutta_23 (@var{fcn}, @var{t}, @var{x}, @var{dt})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}] =} runge_kutta_23 (@var{fcn}, @var{t}, @var{x}, @var{dt}, @var{options})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}] =} runge_kutta_23 (@var{fcn}, @var{t}, @var{x}, @var{dt}, @var{options}, @var{k_vals})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}] =} runge_kutta_23 (@var{fcn}, @var{t}, @var{x}, @var{dt}, @var{options}, @var{k_vals}, @var{t_next})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}, @var{x_est}] =} runge_kutta_23 (@dots{})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}, @var{x_est}, @var{k_vals_out}] =} runge_kutta_23 (@dots{})\n##\n## This function can be used to integrate a system of ODEs with a given initial\n## condition @var{x} from @var{t} to @var{t+dt}, with the Bogacki-Shampine\n## method of third order.  For the definition of this method see\n## @url{http://en.wikipedia.org/wiki/List_of_Runge%E2%80%93Kutta_methods}.\n##\n## @var{fcn} is a function handle that defines the ODE: @code{y' = f(tau,y)}.\n## The function must accept two inputs where the first is time @var{tau} and\n## the second is a column vector of unknowns @var{y}.\n##\n## @var{t} is the first extreme of integration interval.\n##\n## @var{x} is the initial condition of the system..\n##\n## @var{dt} is the timestep, that is the length of the integration interval.\n##\n## The optional fourth argument @var{options} specifies options for the ODE\n## solver.  It is a structure generated by @code{odeset}.  In particular it\n## contains the field @var{funarguments} with the optional arguments to be used\n## in the evaluation of @var{fcn}.\n##\n## The optional fifth argument @var{k_vals_in} contains the Runge-Kutta\n## evaluations of the previous step to use in a FSAL scheme.\n##\n## The optional sixth argument @var{t_next} (@code{t_next = t + dt}) specifies\n## the end of the integration interval.  The output @var{x_next} s the higher\n## order computed solution at time @var{t_next} (local extrapolation is\n## performed).\n##\n## Optionally the functions can also return @var{x_est}, a lower order solution\n## for the estimation of the error, and @var{k_vals_out}, a matrix containing\n## the Runge-Kutta evaluations to use in a FSAL scheme or for dense output.\n##\n## @seealso{runge_kutta_45_dorpri}\n## @end deftypefn\n\nfunction [t_next, x_next, x_est, k] = runge_kutta_23 (fcn, t, x, dt,\n                                                      options = [],\n                                                      k_vals = [],\n                                                      t_next = t + dt)\n\n  persistent a = [0   0   0;\n                  1/2 0   0;\n                  0   3/4 0];\n  persistent b = [0, 1/2, 3/4, 1];\n  persistent c = [2/9, 1/3, 4/9];\n  persistent c_prime = [7/24, 1/4, 1/3, 1/8];\n\n  s = t + dt * b;\n  cc = dt * c;\n  aa = dt * a;\n  k = zeros (rows (x), 4);\n\n  if (! isempty (options))  # extra arguments for function evaluator\n    args = options.funarguments;\n  else\n    args = {};\n  endif\n\n  if (! isempty (k_vals))    # k values from previous step are passed\n    k(:,1) = k_vals(:,end);  # FSAL property\n  else\n    k(:,1) = feval (fcn, t, x, args{:});\n  endif\n\n  k(:,2) = feval (fcn, s(2), x + k(:,1) * aa(2, 1).', args{:});\n  k(:,3) = feval (fcn, s(3), x + k(:,2) * aa(3, 2).', args{:});\n\n  ## compute new time and new values for the unknowns\n  ## t_next = t + dt;\n  x_next = x + k(:,1:3) * cc(:);  # 3rd order approximation\n\n  ## if the estimation of the error is required\n  if (nargout >= 3)\n    ## new solution to be compared with the previous one\n    k(:,4) = feval (fcn, t_next, x_next, args{:});\n    cc_prime = dt * c_prime;\n    x_est = x + k * cc_prime(:);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/runge_kutta_23s.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{t_next}, @var{x_next}] =} runge_kutta_23s (@var{fcn}, @var{t}, @var{x}, @var{dt})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}] =} runge_kutta_23s (@var{fcn}, @var{t}, @var{x}, @var{dt}, @var{options})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}] =} runge_kutta_23s (@var{fcn}, @var{t}, @var{x}, @var{dt}, @var{options}, @var{k_vals})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}] =} runge_kutta_23s (@var{fcn}, @var{t}, @var{x}, @var{dt}, @var{options}, @var{k_vals}, @var{t_next})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}, @var{x_est}] =} runge_kutta_23s (@dots{})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}, @var{x_est}, @var{k_vals_out}] =} runge_kutta_23s (@dots{})\n##\n## This function can be used to integrate a system of ODEs with a given initial\n## condition @var{x} from @var{t} to @var{t+dt}, with a Rosenbrock method of\n## order (2,3).  All the mathematical formulas are from\n## @nospell{L. F. Shampine and M. W. Reichelt}, \"The MATLAB ODE Suite\",\n## @cite{SIAM Journal on Scientific Computing}, @w{Vol.@: 18}, @w{pp.@: 1}--22,\n## 1997.\n##\n## @var{f} is a function handle that defines the ODE: @code{y' = f(tau,y)}.\n## The function must accept two inputs where the first is time @var{tau} and\n## the second is a column vector of unknowns @var{y}.\n##\n## @var{t} is the first extreme of integration interval.\n##\n## @var{x} is the initial condition of the system..\n##\n## @var{dt} is the timestep, that is the length of the integration interval.\n##\n## The optional fourth argument @var{options} specifies options for the ODE\n## solver.  It is a structure generated by @code{odeset}.  In particular it\n## contains the field @var{funarguments} with the optional arguments to be used\n## in the evaluation of @var{fcn}.\n##\n## The optional fifth argument @var{k_vals_in} contains the Runge-Kutta\n## evaluations of the previous step to use in a FSAL scheme.\n##\n## The optional sixth argument @var{t_next} (@code{t_next = t + dt}) specifies\n## the end of the integration interval.  The output @var{x_next} s the higher\n## order computed solution at time @var{t_next} (local extrapolation is\n## performed).\n##\n## Optionally the functions can also return @var{x_est}, a lower order solution\n## for the estimation of the error, and @var{k_vals_out}, a matrix containing\n## the Runge-Kutta evaluations to use in a FSAL scheme or for dense output.\n##\n## @seealso{runge_kutta_23}\n## @end deftypefn\n\nfunction [t_next, x_next, x_est, k] = runge_kutta_23s (fcn, t, x, dt,\n                                                       options = [],\n                                                       k_vals = [],\n                                                       t_next = t + dt)\n\n  persistent d = 1 / (2 + sqrt (2));\n  persistent a = 1 / 2;\n  persistent e32 = 6 + sqrt (2);\n\n  ## extra arguments for function evaluator\n  if (! isempty (options))\n    args = options.funarguments;\n  else\n    args = {};\n  endif\n\n  jacfcn = false;\n  jacmat = false;\n  if (! isempty (options.Jacobian))\n    if (ischar (options.Jacobian))\n      jacfcn = true;\n      jac = str2fun (options.Jacobian);\n    elseif (is_function_handle (options.Jacobian))\n      jacfcn = true;\n      jac = options.Jacobian;\n    elseif (ismatrix (options.Jacobian))\n      jacmat = true;\n      jac = options.Jacobian;\n    else\n      error ([\"ode23s: the jacobian should be passed as a matrix, \", ...\n        \"a string or a function handle\"])\n    endif\n  endif\n\n  jacpat = false;\n  if (! isempty (options.JPattern))\n    jacpat = true;\n    pattern = logical (options.JPattern);\n  endif\n\n  ## Jacobian matrix, dfxpdp\n  if (jacmat)\n    J = jac;\n  elseif (jacfcn)\n    J = jac (t, x);\n  elseif (! jacpat)\n    J = __dfxpdp__ (x, @(a) feval (fcn, t, a, args{:}), options.RelTol);\n  elseif (jacpat)\n    J = __dfxpdp__ (x, @(a) feval (fcn, t, a, args{:}), options.RelTol, pattern);\n  endif\n\n  T = (feval (fcn, t + .1 * dt, x) - feval (fcn, t, x, args{:})) / (.1 * dt);\n\n  ## Wolfbrandt coefficient\n  if (isempty (options.Mass))\n    M = speye (length (x));\n  else\n    M = options.Mass;\n  endif\n  W = M - dt*d*J;\n\n  if (issparse (W))\n    [Lw, Uw, Pw, Qw, Rw] = lu  (W);\n  else\n    [Lw, Uw, Pw] = lu (W);\n  endif\n\n  ## compute the slopes\n  F(:,1) = feval (fcn, t, x, args{:});\n  if (issparse (W))\n    k(:,1) = Qw * (Uw \\ (Lw \\ (Pw * (Rw \\ (F(:,1) + dt*d*T)))));\n  else\n    k(:,1) = Uw \\ (Lw \\ (Pw * (F(:,1) + dt*d*T)));\n  endif\n  F(:,2) = feval (fcn, t+a*dt, x+a*dt*k(:,1), args{:});\n  if (issparse (W))\n    k(:,2) = Uw * (Uw \\ (Lw \\ (Pw * (Rw \\ (F(:,2) - M*k(:,1)))))) + k(:,1);\n  else\n    k(:,2) = Uw \\ (Lw \\ (Pw * (F(:,2) - M*k(:,1)))) + k(:,1);\n  endif\n\n  ## compute the 2nd order estimate\n  x_next = x + dt*k(:,2);\n\n  if (nargout >= 3)\n    ## 3rd order, needed in error formula\n    F(:,3) = feval (fcn, t+dt, x_next, args{:});\n    if (issparse (W))\n      k(:,3) = Qw * (Uw \\ (Lw \\ (Pw * (Rw \\ (F(:,3) - e32 * (M*k(:,2) - F(:,2)) - 2 * (M*k(:,1) - F(:,1)) + dt*d*T)))));\n    else\n      k(:,3) = Uw \\ (Lw \\ (Pw * (F(:,3) - e32 * (M*k(:,2) - F(:,2)) - 2 * (M*k(:,1) - F(:,1)) + dt*d*T)));\n    endif\n\n    ## estimate the error\n    err_est = (dt/6) * (k(:,1) - 2*k(:,2) + k(:,3));\n\n    ## FIXME: to use in AbsRel_Norm function I need x_est and not err directly\n    x_est = x_next + err_est;\n  endif\n\nendfunction\n\n\nfunction prt = __dfxpdp__ (p, fcn, rtol, pattern)\n\n  ## This subfunction was copied 2011 from the OF \"optim\" package\n  ## \"inst/private/__dfdp__.m\".\n\n  f = fcn (p)(:);\n  m = numel (f);\n  n = numel (p);\n\n  diffp = rtol .* ones (n, 1);\n\n  del = ifelse (p == 0, diffp, diffp .* p);\n  absdel = abs (del);\n\n  ## double sided interval\n  p1 = p + absdel / 2;\n  p2 = p - absdel / 2;\n\n  ps = p;\n  if (nargin > 3 && issparse (pattern))\n    prt = pattern;  # initialize Jacobian\n    for j = find (any (pattern, 1))\n      ps(j) = p1(j);\n      tp1 = fcn (ps);\n      ps(j) = p2(j);\n      tp2 = fcn (ps);\n      pattern_nnz = find (pattern(:, j));\n      prt(pattern_nnz, j) = (tp1(pattern_nnz) - tp2(pattern_nnz)) / absdel(j);\n      ps(j) = p(j);\n    endfor\n  else\n    prt = zeros (m, n); # initialize Jacobian\n    for j = 1:n\n      ps(j) = p1(j);\n      tp1 = fcn (ps);\n      ps(j) = p2(j);\n      tp2 = fcn (ps);\n      prt(:, j) = (tp1(:) - tp2(:)) / absdel(j);\n      ps(j) = p(j);\n    endfor\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/runge_kutta_45_dorpri.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{t_next}, @var{x_next}] =} runge_kutta_45_dorpri (@var{@@fcn}, @var{t}, @var{x}, @var{dt})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}] =} runge_kutta_45_dorpri (@var{@@fcn}, @var{t}, @var{x}, @var{dt}, @var{options})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}] =} runge_kutta_45_dorpri (@var{@@fcn}, @var{t}, @var{x}, @var{dt}, @var{options}, @var{k_vals})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}] =} runge_kutta_45_dorpri (@var{@@fcn}, @var{t}, @var{x}, @var{dt}, @var{options}, @var{k_vals}, @var{t_next})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}, @var{x_est}] =} runge_kutta_45_dorpri (@dots{})\n## @deftypefnx {} {[@var{t_next}, @var{x_next}, @var{x_est}, @var{k_vals_out}] =} runge_kutta_45_dorpri (@dots{})\n##\n## This function can be used to integrate a system of ODEs with a given initial\n## condition @var{x} from @var{t} to @var{t+dt} with the Dormand-Prince method.\n## For the definition of this method see\n## @url{http://en.wikipedia.org/wiki/Dormand%E2%80%93Prince_method}.\n##\n## First input argument is the function describing the system of ODEs to be\n## integrated.\n##\n## Second input parameter is the first extreme of integration interval.\n##\n## Third input argument is the initial condition of the system.\n##\n## Fourth input argument is the timestep, that is the length of the\n## integration interval.\n##\n## Fifth input parameter is optional and describes a set of options useful to\n## adapt the computation to what is needed.\n##\n## Sixth input parameter is optional and describes the Runge-Kutta evaluations\n## of the previous step to use in an FSAL scheme.\n##\n## Seventh input parameter is optional and is the time (@var{t_next}) to\n## integrate to.  The default is @code{@var{t} + @var{dt}}.\n##\n## First output argument is the final integration time value.\n##\n## Second output parameter is the higher order computed solution at time\n## @var{t_next} (local extrapolation).\n##\n## Third output parameter is a lower order solution for the estimation of the\n## error.\n##\n## Fourth output parameter is matrix containing the Runge-Kutta evaluations\n## to use in an FSAL scheme or for dense output.\n## @end deftypefn\n\nfunction [t_next, x_next, x_est, k] = runge_kutta_45_dorpri (fcn, t, x, dt,\n                                                             options = [],\n                                                             k_vals = [],\n                                                             t_next = t + dt)\n\n  ## Reference: Ernst Hairer, Syvert Paul Nørsett, Gerhard Wanner,\n  ## Solving ordinary differential equations I: Nonstiff problems,\n  ## Springer-Verlag: Berlin, New York, 2008, ISBN 978-3-540-56670-0.\n  persistent a = [0           0          0           0        0          0;\n                  1/5         0          0           0        0          0;\n                  3/40        9/40       0           0        0          0;\n                  44/45      -56/15      32/9        0        0          0;\n                  19372/6561 -25360/2187 64448/6561 -212/729  0          0;\n                  9017/3168  -355/33     46732/5247  49/176  -5103/18656 0];\n  persistent b = [0, 1/5, 3/10, 4/5, 8/9, 1, 1];\n  persistent c = [35/384, 0, 500/1113, 125/192, -2187/6784, 11/84];\n  persistent c_prime = [5179/57600, 0, 7571/16695, 393/640, ...\n                        -92097/339200, 187/2100, 1/40];\n\n  s = t + dt * b;\n  cc = dt * c;\n  aa = dt * a;\n  k = zeros (rows (x), 7);\n\n  if (! isempty (options))   # extra arguments for function evaluator\n    args = options.funarguments;\n  else\n    args = {};\n  endif\n\n  if (! isempty (k_vals))    # k values from previous step are passed\n    k(:,1) = k_vals(:,end);  # FSAL property\n  else\n    k(:,1) = feval (fcn, t, x, args{:});\n  endif\n\n  k(:,2) = feval (fcn, s(2), x + k(:,1)   * aa(2, 1).'  , args{:});\n  k(:,3) = feval (fcn, s(3), x + k(:,1:2) * aa(3, 1:2).', args{:});\n  k(:,4) = feval (fcn, s(4), x + k(:,1:3) * aa(4, 1:3).', args{:});\n  k(:,5) = feval (fcn, s(5), x + k(:,1:4) * aa(5, 1:4).', args{:});\n  k(:,6) = feval (fcn, s(6), x + k(:,1:5) * aa(6, 1:5).', args{:});\n\n  ## compute new time and new values for the unknowns\n  ## t_next = t + dt;\n  x_next = x + k(:,1:6) * cc(:);  # 5th order approximation\n\n  ## if the estimation of the error is required\n  if (nargout >= 3)\n    ## new solution to be compared with the previous one\n    k(:,7) = feval (fcn, t_next, x_next, args{:});\n    cc_prime = dt * c_prime;\n    x_est = x + k * cc_prime(:);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/runge_kutta_interpolate.m",
    "content": "########################################################################\n##\n## Copyright (C) 2015-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{u_interp} =} odemergeopts (@var{order}, @var{z}, @var{t}, @var{u}, @var{k_vals})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction u_interp = runge_kutta_interpolate (order, z, u, t, k_vals)\n\n  switch (order)\n\n    case 1\n      ## Unused\n      u_interp = interp1 (z, u.', t, \"linear\");\n\n    case 2\n      ## ode23s with Rosenbrock scheme:\n      der = k_vals(:,1);\n      u_interp = quadratic_interpolation (z, u, der, t);\n\n    case 3\n      ## ode23 with Bogacki-Shampine scheme:\n      u_interp = hermite_cubic_interpolation (z, u, k_vals, t);\n\n    case 5\n      ## ode45 with Dormand-Prince scheme:\n      u_interp = hermite_quartic_interpolation (z, u, k_vals, t);\n\n    otherwise\n      ## This should never happen\n      warning ([\"Invalid/unimplemented interpolation order: \", ...\n                \"using linear interpolation instead\"]);\n      u_interp = interp1 (z, u.', t, \"linear\");\n\n  endswitch\n\nendfunction\n\n## The function below can be used in an ODE solver to interpolate the solution\n## at the time t_out using 2nd order Hermite interpolation.\nfunction x_out = quadratic_interpolation (t, x, der, t_out)\n\n  ## coefficients of the parabola\n  a = -(x(:,1) - x(:,2) - der(:).*(t(1)-t(2))) / (t(1) - t(2))^2;\n  b = der(:) - 2*t(1).*a;\n  c = x(:,1) - a*t(1)^2 - b*t(1);\n\n  ## evaluate in t_out\n  x_out = a*t_out.^2 + b*t_out + c;\n\nendfunction\n\n## The function below can be used in an ODE solver to interpolate the\n## solution at the time t_out using 3rd order Hermite interpolation.\nfunction x_out = hermite_cubic_interpolation (t, x, der, t_out)\n\n  dt = (t(2) - t(1));\n  s = (t_out - t(1)) / dt;\n  x_out = ((1 + 2*s) .* (1-s).^2) .* x(:,1) + ...\n          (s .* (1-s).^2 * dt   ) .* der(:,1) + ...\n          ((3-2*s) .* s.^2      ) .* x(:,end) + ...\n          ((s-1) .* s.^2   * dt ) .* der(:,end);\n\nendfunction\n\n## The function below can be used in an ODE solver to interpolate the\n## solution at the time t_out using 4th order Hermite interpolation.\nfunction x_out = hermite_quartic_interpolation (t, x, der, t_out)\n\n  persistent coefs_u_half = ...\n    [6025192743/30085553152; 0; 51252292925/65400821598;\n     -2691868925/45128329728; 187940372067/1594534317056;\n     -1776094331/19743644256; 11237099/235043384];\n\n  ## 4th order approximation of y in t+dt/2 as proposed by Shampine in\n  ## Lawrence, Shampine, \"Some Practical Runge-Kutta Formulas\", 1986.\n  dt = t(2) - t(1);\n  u_half = x(:,1) + (1/2) * dt * (der(:,1:7) * coefs_u_half);\n\n  ## Rescale time on [0,1]\n  s = (t_out - t(1)) / dt;\n\n  ## Hermite basis functions\n  ## H0 = 1   - 11*s.^2 + 18*s.^3 -  8*s.^4;\n  ## H1 =   s -  4*s.^2 +  5*s.^3 -  2*s.^4;\n  ## H2 =       16*s.^2 - 32*s.^3 + 16*s.^4;\n  ## H3 =     -  5*s.^2 + 14*s.^3 -  8*s.^4;\n  ## H4 =          s.^2 -  3*s.^3 +  2*s.^4;\n\n  x_out = (1   - 11*s.^2 + 18*s.^3 -  8*s.^4) .* x(:,1) + ...\n          (  s -  4*s.^2 +  5*s.^3 -  2*s.^4) .* (dt * der(:,1)) + ...\n          (      16*s.^2 - 32*s.^3 + 16*s.^4) .* u_half + ...\n          (    -  5*s.^2 + 14*s.^3 -  8*s.^4) .* x(:,2) + ...\n          (         s.^2 -  3*s.^3 +  2*s.^4) .* (dt * der(:,end));\n\nendfunction\n"
  },
  {
    "path": "scripts/ode/private/starting_stepsize.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} starting_stepsize (@var{order}, @var{fcn}, @var{t0}, @var{x0}, @var{AbsTol}, @var{RelTol}, @var{normcontrol}, @var{args})\n##\n## Determine a good initial timestep for an ODE solver of order @var{order}\n## using the algorithm described in reference [1].\n##\n## The input argument @var{fcn}, is the function describing the differential\n## equations, @var{t0} is the initial time, and @var{x0} is the initial\n## condition.  @var{AbsTol} and @var{RelTol} are the absolute and relative\n## tolerance on the ODE integration taken from an ode options structure.\n##\n## Reference:\n## @nospell{E. Hairer, S.P. Norsett and G. Wanner},\n## @cite{Solving Ordinary Differential Equations I: Nonstiff Problems},\n## Springer.\n##\n## @seealso{odepkg}\n## @end deftypefn\n\nfunction h = starting_stepsize (order, fcn, t0, x0,\n                                AbsTol, RelTol, normcontrol,\n                                args = {})\n\n  ## compute norm of initial conditions\n  d0 = AbsRel_norm (x0, x0, AbsTol, RelTol, normcontrol);\n\n  ## compute norm of the function evaluated at initial conditions\n  y = fcn (t0, x0, args{:});\n  if (iscell (y))\n    y = y{1};\n  endif\n  d1 = AbsRel_norm (y, y, AbsTol, RelTol, normcontrol);\n\n  if (d0 < 1e-5 || d1 < 1e-5)\n    h0 = 1e-6;\n  else\n    h0 = .01 * (d0 / d1);\n  endif\n\n  ## compute one step of Explicit-Euler\n  x1 = x0 + h0 * y;\n\n  ## approximate the derivative norm\n  yh = fcn (t0+h0, x1, args{:});\n  if (iscell (yh))\n    yh = yh{1};\n  endif\n  d2 = (1 / h0) * ...\n       AbsRel_norm (yh - y, yh - y, AbsTol, RelTol, normcontrol);\n\n  if (max (d1, d2) <= 1e-15)\n    h1 = max (1e-6, h0 * 1e-3);\n  else\n    h1 = (1e-2 / max (d1, d2)) ^(1 / (order+1));\n  endif\n\n  h = min (100 * h0, h1);\n\nendfunction\n"
  },
  {
    "path": "scripts/optimization/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/optimization/__all_opts__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{names} =} __all_opts__ (@dots{})\n## Internal function.\n##\n## Query all options from all known optimization functions and return a\n## list of possible values.\n## @end deftypefn\n\nfunction names = __all_opts__ (varargin)\n\n  ## This variable is filled by the auto-generated PKG_ADD script at\n  ## Octave startup.\n  persistent saved_names = {};\n\n  ## do not clear this function\n  mlock ();\n\n  ## guard against recursive calls.\n  persistent recursive = false;\n\n  if (recursive)\n    names = {};\n  elseif (nargin == 0)\n    names = saved_names;\n  else\n    ## Query all options from all known functions.  These may call optimset,\n    ## which will in turn call us, but we won't answer.\n    recursive = true;\n    names = saved_names;\n    for i = 1:nargin\n      try\n        opts = optimset (varargin{i});\n        fcn = fieldnames (opts).';\n        names = [names, fcn];\n      catch\n        ## throw the error as a warning.\n        warning (lasterr ());\n      end_try_catch\n    endfor\n    names = unique (names);\n    [lnames, idx] = unique (lower (names));\n    if (length (lnames) < length (names))\n      ## This is bad.\n      error (\"__all_opts__: duplicate options with inconsistent case\");\n    else\n      names = names(idx);\n    endif\n    saved_names = names;\n    recursive = false;\n  endif\n\nendfunction\n\n\n## No test needed for internal helper function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/optimization/fminbnd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} fminbnd (@var{fcn}, @var{a}, @var{b})\n## @deftypefnx {} {@var{x} =} fminbnd (@var{fcn}, @var{a}, @var{b}, @var{options})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}, @var{output}] =} fminbnd (@dots{})\n## Find a minimum point of a univariate function.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function to evaluate.\n##\n## The starting interval is specified by @var{a} (left boundary) and @var{b}\n## (right boundary).  The endpoints must be finite.\n##\n## @var{options} is a structure specifying additional parameters which\n## control the algorithm.  Currently, @code{fminbnd} recognizes these options:\n## @qcode{\"Display\"}, @qcode{\"FunValCheck\"}, @qcode{\"MaxFunEvals\"},\n## @qcode{\"MaxIter\"}, @qcode{\"OutputFcn\"}, @qcode{\"TolX\"}.\n##\n## @qcode{\"MaxFunEvals\"} proscribes the maximum number of function evaluations\n## before optimization is halted.  The default value is 500.\n## The value must be a positive integer.\n##\n## @qcode{\"MaxIter\"} proscribes the maximum number of algorithm iterations\n## before optimization is halted.  The default value is 500.\n## The value must be a positive integer.\n##\n## @qcode{\"TolX\"} specifies the termination tolerance for the solution @var{x}.\n## The default is @code{1e-4}.\n##\n## For a description of the other options,\n## @pxref{XREFoptimset,,@code{optimset}}.\n## To initialize an options structure with default values for @code{fminbnd}\n## use @code{options = optimset (\"fminbnd\")}.\n##\n## On exit, the function returns @var{x}, the approximate minimum point, and\n## @var{fval}, the function evaluated @var{x}.\n##\n## The third output @var{info} reports whether the algorithm succeeded and may\n## take one of the following values:\n##\n## @itemize\n## @item 1\n## The algorithm converged to a solution.\n##\n## @item 0\n## Iteration limit (either @code{MaxIter} or @code{MaxFunEvals}) exceeded.\n##\n## @item -1\n## The algorithm was terminated by a user @code{OutputFcn}.\n## @end itemize\n##\n## Application Notes:\n## @enumerate\n## @item\n## The search for a minimum is restricted to be in the\n## finite interval bound by @var{a} and @var{b}.  If you have only one initial\n## point to begin searching from then you will need to use an unconstrained\n## minimization algorithm such as @code{fminunc} or @code{fminsearch}.\n## @code{fminbnd} internally uses a Golden Section search strategy.\n##\n## @item\n## Use @ref{Anonymous Functions} to pass additional parameters to @var{fcn}.\n## For specific examples of doing so for @code{fminbnd} and other\n## minimization functions see the @ref{Minimizers} section of the GNU Octave\n## manual.\n## @end enumerate\n## @seealso{fzero, fminunc, fminsearch, optimset}\n## @end deftypefn\n\n## This is patterned after opt/fmin.f from Netlib, which in turn is taken from\n## Richard Brent: Algorithms For Minimization Without Derivatives,\n## Prentice-Hall, 1973.\n\n## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.\n## PKG_ADD: [~] = __all_opts__ (\"fminbnd\");\n\nfunction [x, fval, info, output] = fminbnd (fcn, a, b, options = struct ())\n\n  ## Get default options if requested.\n  if (nargin == 1 && ischar (fcn) && strcmp (fcn, \"defaults\"))\n    x = struct (\"Display\", \"notify\", \"FunValCheck\", \"off\",\n                \"MaxFunEvals\", 500, \"MaxIter\", 500,\n                \"OutputFcn\", [], \"TolX\", 1e-4);\n    return;\n  endif\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (isscalar (a) && isfloat (a) && isfinite (a)))\n    error (\"Octave:invalid-input-arg\",\n           \"fminbnd: endpoint A must be a finite floating point scalar\");\n  elseif (! (isscalar (b) && isfloat (b) && isfinite (b)))\n    error (\"Octave:invalid-input-arg\",\n           \"fminbnd: endpoint B must be a finite floating point scalar\");\n  elseif (a > b)\n    error (\"Octave:invalid-input-arg\",\n           \"fminbnd: the lower bound cannot be greater than the upper one\");\n  endif\n\n  if (ischar (fcn))\n    fcn = str2func (fcn);\n  endif\n\n  displ = optimget (options, \"Display\", \"notify\");\n  funvalchk = strcmpi (optimget (options, \"FunValCheck\", \"off\"), \"on\");\n  outfcn = optimget (options, \"OutputFcn\");\n  tolx = optimget (options, \"TolX\", 1e-4);\n  maxiter = optimget (options, \"MaxIter\", 500);\n  maxfev = optimget (options, \"MaxFunEvals\", 500);\n\n  if (funvalchk)\n    ## Replace fcn with a guarded version.\n    fcn = @(x) guarded_eval (fcn, x);\n  endif\n\n  ## The default exit flag if exceeded number of iterations.\n  info = 0;\n  niter = 0;\n  nfev = 0;\n\n  c = 0.5*(3 - sqrt (5));\n  v = a + c*(b-a);\n  w = x = v;\n  e = 0;\n  fv = fw = fval = fcn (x);\n  nfev += 1;\n\n  if (isa (a, \"single\") || isa (b, \"single\") || isa (fval, \"single\"))\n    sqrteps = eps (\"single\");\n  else\n    sqrteps = eps (\"double\");\n  endif\n\n  ## Only for display purposes.\n  iter(1).funccount = nfev;\n  iter(1).x = x;\n  iter(1).fx = fval;\n\n  while (niter < maxiter && nfev < maxfev)\n    xm = 0.5*(a+b);\n    ## FIXME: the golden section search can actually get closer than sqrt(eps)\n    ## sometimes.  Sometimes not, it depends on the function.  This is the\n    ## strategy from the Netlib code.  Something smarter would be good.\n    tol = 2 * sqrteps * abs (x) + tolx / 3;\n    if (abs (x - xm) <= (2*tol - 0.5*(b-a)))\n      info = 1;\n      break;\n    endif\n\n    if (abs (e) > tol)\n      dogs = false;\n      ## Try inverse parabolic step.\n      iter(niter+1).procedure = \"parabolic\";\n\n      r = (x - w)*(fval - fv);\n      q = (x - v)*(fval - fw);\n      p = (x - v)*q - (x - w)*r;\n      q = 2*(q - r);\n      p *= -sign (q);\n      q = abs (q);\n      r = e;\n      e = d;\n\n      if (abs (p) < abs (0.5*q*r) && p > q*(a-x) && p < q*(b-x))\n        ## The parabolic step is acceptable.\n        d = p / q;\n        u = x + d;\n\n        ## f must not be evaluated too close to ax or bx.\n        if (min (u-a, b-u) < 2*tol)\n          d = tol * (sign (xm - x) + (xm == x));\n        endif\n      else\n        dogs = true;\n      endif\n    else\n      dogs = true;\n    endif\n    if (dogs)\n      ## Default to golden section step.\n\n      ## WARNING: This is also the \"initial\" procedure following MATLAB\n      ## nomenclature.  After the loop we'll fix the string for the first step.\n      iter(niter+1).procedure = \"golden\";\n\n      e = ifelse (x >= xm, a - x, b - x);\n      d = c * e;\n    endif\n\n    ## f must not be evaluated too close to x.\n    u = x + max (abs (d), tol) * (sign (d) + (d == 0));\n    fu = fcn (u);\n\n    niter += 1;\n\n    iter(niter).funccount = nfev++;\n    iter(niter).x = u;\n    iter(niter).fx = fu;\n\n    ## update a, b, v, w, and x\n\n    if (fu < fval)\n      if (u < x)\n        b = x;\n      else\n        a = x;\n      endif\n      v = w; fv = fw;\n      w = x; fw = fval;\n      x = u; fval = fu;\n    else\n      ## The following if-statement was originally executed even if fu == fval.\n      if (u < x)\n        a = u;\n      else\n        b = u;\n      endif\n      if (fu <= fw || w == x)\n        v = w; fv = fw;\n        w = u; fw = fu;\n      elseif (fu <= fv || v == x || v == w)\n        v = u;\n        fv = fu;\n      endif\n    endif\n\n    ## If there's an output function, use it now.\n    if (! isempty (outfcn))\n      optv.funccount = nfev;\n      optv.fval = fval;\n      optv.iteration = niter;\n      if (outfcn (x, optv, \"iter\"))\n        info = -1;\n        break;\n      endif\n    endif\n  endwhile\n\n  ## Fix the first step procedure.\n  iter(1).procedure = \"initial\";\n\n  ## Handle the \"Display\" option\n  switch (displ)\n    case \"iter\"\n      print_formatted_table (iter);\n      print_exit_msg (info, struct (\"TolX\", tolx, \"fx\", fval));\n    case \"notify\"\n      if (info == 0)\n        print_exit_msg (info, struct (\"fx\",fval));\n      endif\n    case \"final\"\n      print_exit_msg (info, struct (\"TolX\", tolx, \"fx\", fval));\n    case \"off\"\n      \"skip\";\n    otherwise\n      warning (\"fminbnd: unknown option for Display: '%s'\", displ);\n  endswitch\n\n  output.iterations = niter;\n  output.funcCount = nfev;\n  output.algorithm = \"golden section search, parabolic interpolation\";\n  output.bracket = [a, b];\n  ## FIXME: bracketf possibly unavailable.\n\nendfunction\n\n## A helper function that evaluates a function and checks for bad results.\nfunction fx = guarded_eval (fcn, x)\n\n  fx = fcn (x);\n  fx = fx(1);\n  if (! isreal (fx))\n    error (\"Octave:fmindbnd:notreal\", \"fminbnd: non-real value encountered\");\n  elseif (isnan (fx))\n    error (\"Octave:fmindbnd:isnan\", \"fminbnd: NaN value encountered\");\n  endif\n\nendfunction\n\n## A hack for printing a formatted table\nfunction print_formatted_table (table)\n\n  printf (\"\\n Fcn-count     x          f(x)         Procedure\\n\");\n  for row=table\n    printf (\"%5.5s        %7.7s    %8.8s\\t%s\\n\",\n            int2str (row.funccount), num2str (row.x,\"%.5f\"),\n            num2str (row.fx,\"%.6f\"), row.procedure);\n  endfor\n  printf (\"\\n\");\n\nendfunction\n\n## Print either a success termination message or bad news\nfunction print_exit_msg (info, opt=struct ())\n\n  printf (\"\");\n  switch (info)\n    case 1\n      printf (\"Optimization terminated:\\n\");\n      printf (\" the current x satisfies the termination criteria using OPTIONS.TolX of %e\\n\", opt.TolX);\n    case 0\n      printf (\"Exiting: Maximum number of iterations has been exceeded\\n\");\n      printf (\"         - increase MaxIter option.\\n\");\n      printf (\"         Current function value: %.6f\\n\", opt.fx);\n    case -1\n      \"FIXME\"; # FIXME: what's the message MATLAB prints for this case?\n    otherwise\n      error (\"fminbnd: internal error, info return code was %d\", info);\n  endswitch\n  printf (\"\\n\");\n\nendfunction\n\n\n%!shared opt0\n%! opt0 = optimset (\"tolx\", 0);\n%!assert (fminbnd (@cos, pi/2, 3*pi/2, opt0), pi, 10*sqrt (eps))\n%!assert (fminbnd (@(x) (x - 1e-3)^4, -1, 1, opt0), 1e-3, 10e-3*sqrt (eps))\n%!assert (fminbnd (@(x) abs (x-1e7), 0, 1e10, opt0), 1e7, 10e7*sqrt (eps))\n%!assert (fminbnd (@(x) x^2 + sin (2*pi*x), 0.4, 1, opt0), fzero (@(x) 2*x + 2*pi*cos (2*pi*x), [0.4, 1], opt0), sqrt (eps))\n%!assert (fminbnd (@(x) x > 0.3, 0, 1) < 0.3)\n%!assert (fminbnd (@(x) sin (x), 0, 0), 0, eps)\n\n## Test input validation\n%!error <Invalid call> fminbnd (1)\n%!error <A must be a finite floating point scalar> fminbnd (1, [2, 3], 4)\n%!error <A must be a finite floating point scalar> fminbnd (1, int8 (2), 3)\n%!error <A must be a finite floating point scalar> fminbnd (1, Inf, 3)\n%!error <B must be a finite floating point scalar> fminbnd (1, 2, [3, 4])\n%!error <B must be a finite floating point scalar> fminbnd (1, 2, int8 (3))\n%!error <B must be a finite floating point scalar> fminbnd (1, 2, Inf)\n%!error <lower bound cannot be greater> fminbnd (@(x) sin (x), 0, -pi)\n"
  },
  {
    "path": "scripts/optimization/fminsearch.m",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} fminsearch (@var{fcn}, @var{x0})\n## @deftypefnx {} {@var{x} =} fminsearch (@var{fcn}, @var{x0}, @var{options})\n## @deftypefnx {} {@var{x} =} fminsearch (@var{problem})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{exitflag}, @var{output}] =} fminsearch (@dots{})\n##\n## Find a value of @var{x} which minimizes the multi-variable function\n## @var{fcn}.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function to evaluate.\n##\n## The search begins at the point @var{x0} and iterates using the\n## @nospell{Nelder & Mead} Simplex algorithm (a derivative-free method).  This\n## algorithm is better-suited to functions which have discontinuities or for\n## which a gradient-based search such as @code{fminunc} fails.\n##\n## Options for the search are provided in the parameter @var{options} using the\n## function @code{optimset}.  Currently, @code{fminsearch} accepts the options:\n## @qcode{\"Display\"}, @qcode{\"FunValCheck\"},@qcode{\"MaxFunEvals\"},\n## @qcode{\"MaxIter\"}, @qcode{\"OutputFcn\"}, @qcode{\"TolFun\"}, @qcode{\"TolX\"}.\n##\n## @qcode{\"MaxFunEvals\"} proscribes the maximum number of function evaluations\n## before optimization is halted.  The default value is\n## @code{200 * number_of_variables}, i.e., @code{200 * length (@var{x0})}.\n## The value must be a positive integer.\n##\n## @qcode{\"MaxIter\"} proscribes the maximum number of algorithm iterations\n## before optimization is halted.  The default value is\n## @code{200 * number_of_variables}, i.e., @code{200 * length (@var{x0})}.\n## The value must be a positive integer.\n##\n## For a description of the other options,\n## @pxref{XREFoptimset,,@code{optimset}}.  To initialize an options structure\n## with default values for @code{fminsearch} use\n## @code{options = optimset (\"fminsearch\")}.\n##\n## @code{fminsearch} may also be called with a single structure argument\n## with the following fields:\n##\n## @table @code\n## @item objective\n## The objective function.\n##\n## @item x0\n## The initial point.\n##\n## @item solver\n## Must be set to @qcode{\"fminsearch\"}.\n##\n## @item options\n## A structure returned from @code{optimset} or an empty matrix to\n## indicate that defaults should be used.\n## @end table\n##\n## @noindent\n## The field @code{options} is optional.  All others are required.\n##\n## On exit, the function returns @var{x}, the minimum point, and @var{fval},\n## the function value at the minimum.\n##\n## The third output @var{exitflag} reports whether the algorithm succeeded and\n## may take one of the following values:\n##\n## @table @asis\n## @item 1\n## if the algorithm converged\n## (size of the simplex is smaller than @code{TolX} @strong{AND} the step in\n## function value between iterations is smaller than @code{TolFun}).\n##\n## @item 0\n## if the maximum number of iterations or the maximum number of function\n## evaluations are exceeded.\n##\n## @item -1\n## if the iteration is stopped by the @qcode{\"OutputFcn\"}.\n## @end table\n##\n## The fourth output is a structure @var{output} containing runtime\n## about the algorithm.  Fields in the structure are @code{funcCount}\n## containing the number of function calls to @var{fcn}, @code{iterations}\n## containing the number of iteration steps, @code{algorithm} with the name of\n## the search algorithm (always:\n## @nospell{@qcode{\"Nelder-Mead simplex direct search\"}}), and @code{message}\n## with the exit message.\n##\n## Example:\n##\n## @example\n## fminsearch (@@(x) (x(1)-5).^2+(x(2)-8).^4, [0;0])\n## @end example\n##\n## Application Notes:\n## @enumerate\n## @item\n## If you need to find the minimum of a single variable function it is\n## probably better to use @code{fminbnd}.\n##\n## @item\n## The legacy, undocumented syntax for passing parameters to @var{fcn} by\n## appending them to the input argument list after @var{options} has been\n## removed in Octave 10.  The cross-platform compatible method of passing\n## parameters to @var{fcn} is through the use of @ref{Anonymous Functions}.  For\n## specific examples of doing so for @code{fminsearch} and other minimization\n## functions see the @ref{Minimizers} section of the GNU Octave manual.\n## @end enumerate\n## @seealso{fminbnd, fminunc, optimset}\n## @end deftypefn\n\n## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.\n## PKG_ADD: [~] = __all_opts__ (\"fminsearch\");\n\n## FIXME: Add support for output function with \"state\" set to \"interrupt\".\n\nfunction [x, fval, exitflag, output] = fminsearch (varargin)\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  ## Get default options if requested.\n  if (nargin == 1 && ischar (varargin{1}) && strcmp (varargin{1}, \"defaults\"))\n    x = struct (\"Display\", \"notify\", \"FunValCheck\", \"off\",\n                \"MaxFunEvals\", [], \"MaxIter\", [],\n                \"OutputFcn\", [],\n                \"TolFun\", 1e-4, \"TolX\", 1e-4);\n    return;\n  endif\n\n  if (nargin == 1)\n    problem = varargin{1};\n    varargin = {};\n    if (! isstruct (problem))\n      error (\"fminsearch: PROBLEM must be a structure\");\n    endif\n    fcn = problem.objective;\n    x0 = problem.x0;\n    if (! strcmp (problem.solver, \"fminsearch\"))\n      error ('fminsearch: problem.solver must be set to \"fminsearch\"');\n    endif\n    if (isfield (problem, \"options\"))\n      options = problem.options;\n    else\n      options = [];\n    endif\n  elseif (nargin > 1)\n    fcn = varargin{1};\n    x0 = varargin{2};\n    if (nargin > 2)\n      options = varargin{3};\n      varargin(1:3) = [];\n    else\n      options = [];\n      varargin = {};\n    endif\n  endif\n\n  if (ischar (fcn))\n    fcn = str2func (fcn);\n  endif\n\n  if (isempty (options))\n    options = struct ();\n  endif\n\n  [x, exitflag, output] = nmsmax (fcn, x0, options);\n\n  if (nargout > 1)\n    fval = feval (fcn, x);\n  endif\n\nendfunction\n\n## NMSMAX  Nelder-Mead simplex method for direct search optimization.\n##        [x, fmax, nf] = NMSMAX(FCN, x0, STOPIT, SAVIT) attempts to\n##        maximize the function FCN, using the starting vector x0.\n##        The Nelder-Mead direct search method is used.\n##        Output arguments:\n##               x    = vector yielding largest function value found,\n##               fmax = function value at x,\n##               nf   = number of function evaluations.\n##        The iteration is terminated when either\n##               - the relative size of the simplex is <= STOPIT(1)\n##                 (default 1e-3),\n##               - STOPIT(2) function evaluations have been performed\n##                 (default inf, i.e., no limit), or\n##               - a function value equals or exceeds STOPIT(3)\n##                 (default inf, i.e., no test on function values).\n##        The form of the initial simplex is determined by STOPIT(4):\n##           STOPIT(4) = 0: regular simplex (sides of equal length, the default)\n##           STOPIT(4) = 1: right-angled simplex.\n##        Progress of the iteration is not shown if STOPIT(5) = 0 (default 1).\n##           STOPIT(6) indicates the direction (i.e., minimization or\n##                   maximization.) Default is 1, maximization.\n##                   set STOPIT(6)=-1 for minimization\n##        If a non-empty fourth parameter string SAVIT is present, then\n##        'SAVE SAVIT x fmax nf' is executed after each inner iteration.\n##        NB: x0 can be a matrix.  In the output argument, in SAVIT saves,\n##            and in function calls, x has the same shape as x0.\n##        NMSMAX(FCN, x0, STOPIT, SAVIT, P1, P2,...) allows additional\n##        arguments to be passed to FCN, via feval(FCN,x,P1,P2,...).\n## References:\n## N. J. Higham, Optimization by direct search in matrix computations,\n##    SIAM J. Matrix Anal. Appl, 14(2): 317-333, 1993.\n## C. T. Kelley, Iterative Methods for Optimization, Society for Industrial\n##    and Applied Mathematics, Philadelphia, PA, 1999.\n\n## From Matrix Toolbox\n## Copyright (C) 2002, 2013 N.J.Higham\n## www.maths.man.ac.uk/~higham/mctoolbox\n##\n## Modifications for Octave by A.Adler 2003\n\nfunction [stopit, savit, dirn, trace, tol, maxiter, tol_f, outfcn] = ...\n                                                     parse_options (options, x)\n\n  ## Tolerance for cgce test based on relative size of simplex.\n  stopit(1) = tol = optimget (options, \"TolX\", 1e-4);\n\n  ## Tolerance for cgce test based on step in function value.\n  tol_f = optimget (options, \"TolFun\", 1e-4);\n\n  ## Max number of function evaluations.\n  stopit(2) = optimget (options, \"MaxFunEvals\", 200 * length (x));\n\n  ## Max number of iterations\n  maxiter = optimget (options, \"MaxIter\", 200 * length (x));\n\n  ## Default target for function values.\n  stopit(3) = Inf;  # FIXME: expose this parameter to the outside\n\n  ## Default initial simplex.\n  stopit(4) = 0;    # FIXME: expose this parameter to the outside\n\n  ## Default: show progress.\n  display = optimget (options, \"Display\", \"notify\");\n  switch (display)\n    case \"iter\"\n      stopit(5) = 1;\n    case \"final\"\n      stopit(5) = 2;\n    case \"notify\"\n      stopit(5) = 3;\n    otherwise  # \"none\"\n      stopit(5) = 0;\n  endswitch\n  trace = stopit(5);\n\n  ## Use function to minimize, not maximize\n  stopit(6) = dirn = -1;\n\n  ## Filename for snapshots.\n  savit = [];  # FIXME: expose this parameter to the outside\n\n  ## OutputFcn\n  outfcn = optimget (options, \"OutputFcn\");\n\nendfunction\n\nfunction [x, exitflag, output] = nmsmax (fcn, x, options)\n\n  [stopit, savit, dirn, trace, tol, maxiter, tol_f, outfcn] = ...\n                                                    parse_options (options, x);\n\n  if (strcmpi (optimget (options, \"FunValCheck\", \"off\"), \"on\"))\n    ## Replace fcn with a guarded version.\n    fcn = @(x) guarded_eval (fcn, x);\n  else\n    fcn = @(x) real (fcn (x));\n  endif\n\n  x0 = x(:);  # Work with column vector internally.\n  n = length (x0);\n\n  V = [zeros(n,1) eye(n)];\n  f = zeros (n+1,1);\n  V(:,1) = x0;\n  f(1) = dirn * fcn (x);\n  fmax_old = f(1);\n  nf = 1;\n\n  if (trace == 1)\n    printf (\"f(x0) = %9.4e\\n\", dirn * f(1));\n  endif\n\n  k = 0; m = 0;\n\n  ## Set up initial simplex.\n  scale = max (norm (x0, Inf), 1);\n  if (stopit(4) == 0)\n    ## Regular simplex - all edges have same length.\n    ## Generated from construction given in reference [18, pp. 80-81] of [1].\n    alpha = scale / (n*sqrt (2)) * [sqrt(n+1)-1+n, sqrt(n+1)-1];\n    #V(:,2:n+1) = (x0 + alpha(2)*ones (n,1)) * ones (1,n);\n    V(:,2:n+1) = repmat (x0 + alpha(2), 1, n);\n    for j = 2:n+1\n      V(j-1,j) = x0(j-1) + alpha(1);\n      x(:) = V(:,j);\n      f(j) = dirn * fcn (x);\n    endfor\n  else\n    ## Right-angled simplex based on co-ordinate axes.\n    alpha = scale * ones (n+1,1);\n    for j = 2:n+1\n      V(:,j) = x0 + alpha(j)*V(:,j);\n      x(:) = V(:,j);\n      f(j) = dirn * fcn (x);\n    endfor\n  endif\n  nf += n;\n  how = \"initial  \";\n\n  [~, j] = sort (f);\n  j = j(n+1:-1:1);\n  f = f(j);\n  V = V(:,j);\n\n  exitflag = 0;\n\n  if (! isempty (outfcn))\n    optimvalues.iteration = 0;\n    optimvalues.funccount = nf;\n    optimvalues.fval = dirn * f(1);\n    optimvalues.procedure = how;\n    state = \"init\";\n    stop = outfcn (x, optimvalues, state);\n    if (stop)\n      msg = \"Stopped by OutputFcn\\n\";\n      exitflag = -1;\n    endif\n  endif\n\n  alpha = 1;  beta = 1/2;  gamma = 2;\n\n  while (exitflag != -1)   # Outer (and only) loop.\n    k += 1;\n\n    if (k > maxiter)\n      msg = \"Exceeded maximum iterations\\n\";\n      break;\n    endif\n\n    fmax = f(1);\n    if (fmax > fmax_old)\n      if (! isempty (savit))\n        x(:) = V(:,1);\n        eval ([\"save \" savit \" x fmax nf\"]);\n      endif\n    endif\n    if (trace == 1)\n      printf (\"Iter. %2.0f,\", k);\n      printf (\"  how = %-11s\", [how \",\"]);\n      printf (\"nf = %3.0f,  f = %9.4e  (%2.1f%%)\\n\", nf, dirn * fmax, ...\n              100*(fmax-fmax_old)/(abs (fmax_old)+eps));\n    endif\n    fmax_old = fmax;\n\n    ## Three stopping tests from MDSMAX.M\n\n    ## Stopping Test 1 - f reached target value?\n    if (fmax >= stopit(3))\n      msg = \"Exceeded target...quitting\\n\";\n      ## FIXME: Add documentation when stopit(3) gets exposed to the outside\n      exitflag = -1;\n      break;\n    endif\n\n    ## Stopping Test 2 - too many f-evals?\n    if (nf >= stopit(2))\n      msg = \"Exceeded maximum number of function evaluations\\n\";\n      exitflag = 0;\n      break;\n    endif\n\n    ## Stopping Test 3 - converged?   The first part is test (4.3) in [1].\n    v1 = V(:,1);\n    size_simplex = norm (V(:,2:n+1)-v1(:,ones (1,n)),1) / max (1, norm (v1,1));\n    step_f = max (abs (f(1) - f(2:n+1)));\n    if (size_simplex <= tol && step_f <= tol_f )\n      msg = sprintf ([\"Algorithm converged.  Simplex size %9.4e <= %9.4e \", ...\n                      \"and step in function value %9.4e <= %9.4e\\n\"], ...\n                      size_simplex, tol, step_f, tol_f);\n      exitflag = 1;\n      break;\n    endif\n\n    ## Call OutputFcn\n    if (! isempty (outfcn))\n      optimvalues.funccount = nf;\n      optimvalues.fval = dirn * f(1);\n      optimvalues.iteration = k;\n      optimvalues.procedure = how;\n      state = \"iter\";\n      stop = outfcn (x, optimvalues, state);\n      if (stop)\n        msg = \"Stopped by OutputFcn\\n\";\n        exitflag = -1;\n        break;\n      endif\n    endif\n\n    ##  One step of the Nelder-Mead simplex algorithm\n    ##  NJH: Altered function calls and changed CNT to NF.\n    ##       Changed each 'fr < f(1)' type test to '>' for maximization\n    ##       and re-ordered function values after sort.\n\n    vbar = (sum (V(:,1:n)')/n)';  # Mean value\n    #vbar = mean(V(:,1:n), 2);\n    vr = (1 + alpha)*vbar - alpha*V(:,n+1);\n    x(:) = vr;\n    fr = dirn * fcn (x);\n    nf += 1;\n    vk = vr;  fk = fr;  how = \"reflect\";\n    if (fr > f(n))\n      if (fr > f(1))\n        ve = gamma*vr + (1-gamma)*vbar;\n        x(:) = ve;\n        fe = dirn * fcn (x);\n        nf += 1;\n        if (fe > f(1))\n          vk = ve;\n          fk = fe;\n          how = \"expand\";\n        endif\n      endif\n    else\n      vt = V(:,n+1);\n      ft = f(n+1);\n      if (fr > ft)\n        vt = vr;\n        ft = fr;\n      endif\n      vc = beta*vt + (1-beta)*vbar;\n      x(:) = vc;\n      fc = dirn * fcn (x);\n      nf += 1;\n      if (fc > f(n))\n        vk = vc; fk = fc;\n        how = \"contract\";\n      else\n        for j = 2:n\n          V(:,j) = (V(:,1) + V(:,j))/2;\n          x(:) = V(:,j);\n          f(j) = dirn * fcn (x);\n        endfor\n        nf += n-1;\n        vk = (V(:,1) + V(:,n+1))/2;\n        x(:) = vk;\n        fk = dirn * fcn (x);\n        nf += 1;\n        how = \"shrink\";\n      endif\n    endif\n    V(:,n+1) = vk;\n    f(n+1) = fk;\n    [~,j] = sort(f);\n    j = j(n+1:-1:1);\n    f = f(j);\n    V = V(:,j);\n\n  endwhile   # End of outer (and only) loop.\n\n  ## Finished.\n  if ( (trace == 1) || (trace == 2) || (trace == 3 && exitflag != 1) )\n    printf (msg);\n  endif\n  x(:) = V(:,1);\n\n  ## FIXME: Should outputfcn be called only if exitflag != 0,\n  ##        i.e., only when we have successfully converged?\n  if (! isempty (outfcn))\n    optimvalues.funccount = nf;\n    optimvalues.fval = dirn * f(1);\n    optimvalues.iteration = k;\n    optimvalues.procedure = how;\n    state = \"done\";\n    outfcn (x, optimvalues, state);\n  endif\n\n  ## output\n  output.iterations = k;\n  output.funcCount = nf;\n  output.algorithm = \"Nelder-Mead simplex direct search\";\n  output.message = msg;\n\nendfunction\n\n## A helper function that evaluates a function and checks for bad results.\nfunction y = guarded_eval (fcn, x)\n\n  y = fcn (x);\n\n  if (! (isreal (y)))\n    error (\"fminsearch:notreal\", \"fminsearch: non-real value encountered\");\n  elseif (any (isnan (y(:))))\n    error (\"fminsearch:isnan\", \"fminsearch: NaN value encountered\");\n  elseif (any (isinf (y(:))))\n    error (\"fminsearch:isinf\", \"fminsearch: Inf value encountered\");\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! hold on;\n%! box on;\n%! axis square;\n%! draw_fcn = @(x, ~, ~) (plot (x(1), x(2), 'o', 'MarkerSize', 5) && false);\n%! fcn = @(x) (x(1)-5).^2 + (x(2)-8).^4;\n%! x0 = [0;0];\n%! [xmin, fval] = fminsearch (fcn, x0, optimset (\"OutputFcn\", draw_fcn))\n%! ## Mark the solution\n%! hf = plot (xmin(1), xmin(2), '+r', 'MarkerSize', 10, 'LineWidth', 2);\n%! legend (hf, 'Solution');\n%! hold off;\n\n%!assert (fminsearch (@sin, 3, optimset (\"MaxIter\", 30)), 3*pi/2, 1e-4)\n\n## FIXME: The following test is for checking that fminsearch stops earlier\n##        with these settings.  If the optimizer algorithm is changed, it\n##        may fail.  Just adapt the values to make it pass again.\n%!test\n%! x = fminsearch (@sin, 3, optimset (\"MaxIter\", 3, \"Display\", \"none\"));\n%! assert (x, 4.8750, 1e-4);\n%! x = fminsearch (@sin, 3, optimset (\"MaxFunEvals\", 18, \"Display\", \"none\"));\n%! assert (x, 4.7109, 1e-4);\n\n%!test\n%! problem.objective = @sin;\n%! problem.x0 = 3;\n%! problem.solver = \"fminsearch\";\n%! problem.options = optimset (\"MaxIter\", 3, \"Display\", \"none\");\n%! x = fminsearch (problem);\n%! assert (x, 4.8750, 1e-4);\n%! problem.options = optimset (\"MaxFunEvals\", 18, \"Display\", \"none\");\n%! x = fminsearch (problem);\n%! assert (x, 4.7109, 1e-4);\n\n%!test\n%! c = 1.5;\n%! assert (fminsearch (@(x) x(1).^2 + c*x(2).^2, [1;1]), [0;0], 1e-4);\n\n## all output arguments\n%!test\n%! options = optimset (\"Display\", \"none\", \"TolX\", 1e-4, \"TolFun\", 1e-7);\n%! [x, fval, exitflag, output] = fminsearch (@sin, 3, options);\n%! assert (x, 3*pi/2, options.TolX);\n%! assert (fval, -1, options.TolFun);\n%! assert (exitflag, 1);\n%! assert (isstruct (output));\n%! assert (isfield (output, \"iterations\") && isnumeric (output.iterations)\n%!         && isscalar (output.iterations) && output.iterations > 0);\n%! assert (isfield (output, \"funcCount\") && isnumeric (output.funcCount)\n%!         && isscalar (output.funcCount) && output.funcCount > 0);\n%! assert (isfield (output, \"algorithm\") && ischar (output.algorithm));\n%! assert (isfield (output, \"message\") && ischar (output.message));\n\n## Tests for guarded_eval\n%!error <non-real value encountered>\n%! fminsearch (@(x) ([0 2i]), 0, optimset (\"FunValCheck\", \"on\"));\n%!error <NaN value encountered>\n%! fminsearch (@(x) (NaN), 0, optimset (\"FunValCheck\", \"on\"));\n%!error <Inf value encountered>\n%! fminsearch (@(x) (Inf), 0, optimset (\"FunValCheck\", \"on\"));\n\n## Test input validation\n%!error <Invalid call> fminsearch ()\n%!error <Invalid call> fminsearch (1, 2, 3, 4)\n%!error <PROBLEM must be a structure> fminsearch (1)\n%!test <*55742>\n%! problem.objective = @sin;\n%! problem.x0 = 3;\n%! problem.solver = \"foo\";\n%! fail (\"fminsearch (problem)\",\"problem.solver must be set to\");\n\n## additional input argument - no longer supported.  nargin > 3 should fail.\n%!test <*55742>\n%! fail (\"fminsearch (@(x, c) x(1).^2 + c*x(2).^2, [1;1], [], 1.5)\", \"Invalid call\");\n%! fail (\"fminsearch (@(x, c) c(1)*x(1).^2 + c(2)*x(2).^2, [1;1], optimset ('Display', 'none'), [1 1.5])\", \"Invalid call\");\n"
  },
  {
    "path": "scripts/optimization/fminunc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} fminunc (@var{fcn}, @var{x0})\n## @deftypefnx {} {@var{x} =} fminunc (@var{fcn}, @var{x0}, @var{options})\n## @deftypefnx {} {[@var{x}, @var{fval}] =} fminunc (@var{fcn}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}] =} fminunc (@var{fcn}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}, @var{output}] =} fminunc (@var{fcn}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}, @var{output}, @var{grad}] =} fminunc (@var{fcn}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}, @var{output}, @var{grad}, @var{hess}] =} fminunc (@var{fcn}, @dots{})\n## Solve an unconstrained optimization problem defined by the function\n## @var{fcn}.\n##\n## @code{fminunc} attempts to determine a vector @var{x} such that\n## @code{@var{fcn} (@var{x})} is a local minimum.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function to evaluate.  @var{fcn} should accept a vector (array)\n## defining the unknown variables, and return the objective function value,\n## optionally with gradient.\n##\n## @var{x0} determines a starting guess.  The shape of @var{x0} is preserved in\n## all calls to @var{fcn}, but otherwise is treated as a column vector.\n##\n## @var{options} is a structure specifying additional parameters which\n## control the algorithm.  Currently, @code{fminunc} recognizes these options:\n## @qcode{\"AutoScaling\"}, @qcode{\"FinDiffType\"}, @qcode{\"FunValCheck\"},\n## @qcode{\"GradObj\"}, @qcode{\"MaxFunEvals\"}, @qcode{\"MaxIter\"},\n## @qcode{\"OutputFcn\"}, @qcode{\"TolFun\"}, @qcode{\"TolX\"}, @qcode{\"TypicalX\"}.\n##\n## If @qcode{\"AutoScaling\"} is @qcode{\"on\"}, the variables will be\n## automatically scaled according to the column norms of the (estimated)\n## Jacobian.  As a result, @qcode{\"TolFun\"} becomes scaling-independent.  By\n## default, this option is @qcode{\"off\"} because it may sometimes deliver\n## unexpected (though mathematically correct) results.\n##\n## If @qcode{\"GradObj\"} is @qcode{\"on\"}, it specifies that @var{fcn}---when\n## called with two output arguments---also returns the Jacobian matrix of\n## partial first derivatives at the requested point.\n##\n## @qcode{\"MaxFunEvals\"} proscribes the maximum number of function evaluations\n## before optimization is halted.  The default value is\n## @code{100 * number_of_variables}, i.e., @code{100 * length (@var{x0})}.\n## The value must be a positive integer.\n##\n## @qcode{\"MaxIter\"} proscribes the maximum number of algorithm iterations\n## before optimization is halted.  The default value is 400.\n## The value must be a positive integer.\n##\n## @qcode{\"TolX\"} specifies the termination tolerance for the unknown variables\n## @var{x}, while @qcode{\"TolFun\"} is a tolerance for the objective function\n## value @var{fval}.  The default is @code{1e-6} for both options.\n##\n## For a description of the other options,\n## @pxref{XREFoptimset,,@code{optimset}}.\n##\n## On return, @var{x} is the location of the minimum and @var{fval} contains\n## the value of the objective function at @var{x}.\n##\n## @var{info} may be one of the following values:\n##\n## @table @asis\n## @item 1\n## Converged to a solution point.  Relative gradient error is less than\n## specified by @code{TolFun}.\n##\n## @item 2\n## Last relative step size was less than @code{TolX}.\n##\n## @item 3\n## Last relative change in function value was less than @code{TolFun}.\n##\n## @item 0\n## Iteration limit exceeded---either maximum number of algorithm iterations\n## @code{MaxIter} or maximum number of function evaluations @code{MaxFunEvals}.\n##\n## @item -1\n## Algorithm terminated by @code{OutputFcn}.\n##\n## @item -3\n## The trust region radius became excessively small.\n## @end table\n##\n## Optionally, @code{fminunc} can return a structure with convergence\n## statistics (@var{output}), the output gradient (@var{grad}) at the\n## solution @var{x}, and approximate Hessian (@var{hess}) at the solution\n## @var{x}.\n##\n## Application Notes:\n## @enumerate\n## @item\n## If the objective function is a single nonlinear equation\n## of one variable then using @code{fminbnd} is usually a better choice.\n##\n## @item\n## The algorithm used by @code{fminunc} is a gradient search which depends\n## on the objective function being differentiable.  If the function has\n## discontinuities it may be better to use a derivative-free algorithm such as\n## @code{fminsearch}.\n##\n## @item\n## Use @ref{Anonymous Functions} to pass additional parameters to @var{fcn}.\n## For specific examples of doing so for @code{fminunc} and other\n## minimization functions see the @ref{Minimizers} section of the GNU Octave\n## manual.\n## @end enumerate\n## @seealso{fminbnd, fminsearch, optimset}\n## @end deftypefn\n\n## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.\n## PKG_ADD: [~] = __all_opts__ (\"fminunc\");\n\nfunction [x, fval, info, output, grad, hess] = fminunc (fcn, x0, options = struct ())\n\n  ## Get default options if requested.\n  if (nargin == 1 && strcmp (fcn, \"defaults\"))\n    x = struct (\"AutoScaling\", \"off\", \"FunValCheck\", \"off\",\n                \"FinDiffType\", \"forward\", \"GradObj\", \"off\",\n                \"MaxFunEvals\", [], \"MaxIter\", 400, \"OutputFcn\", [],\n                \"TolFun\", 1e-6, \"TolX\", 1e-6, \"TypicalX\", []);\n    return;\n  endif\n\n  if (nargin < 2 || ! isnumeric (x0))\n    print_usage ();\n  endif\n\n  if (ischar (fcn))\n    fcn = str2func (fcn);\n  endif\n\n  xsz = size (x0);\n  n = numel (x0);\n\n  has_grad = strcmpi (optimget (options, \"GradObj\", \"off\"), \"on\");\n  cdif = strcmpi (optimget (options, \"FinDiffType\", \"forward\"), \"central\");\n  maxiter = optimget (options, \"MaxIter\", 400);\n  maxfev = optimget (options, \"MaxFunEvals\", 100*n);\n  outfcn = optimget (options, \"OutputFcn\");\n\n  ## Get scaling matrix using the TypicalX option.  If set to \"auto\", the\n  ## scaling matrix is estimated using the Jacobian.\n  typicalx = optimget (options, \"TypicalX\");\n  if (isempty (typicalx))\n    typicalx = ones (n, 1);\n  endif\n  autoscale = strcmpi (optimget (options, \"AutoScaling\", \"off\"), \"on\");\n  if (! autoscale)\n    dg = 1 ./ typicalx;\n  endif\n\n  funvalchk = strcmpi (optimget (options, \"FunValCheck\", \"off\"), \"on\");\n\n  if (funvalchk)\n    ## Replace fcn with a guarded version.\n    fcn = @(x) guarded_eval (fcn, x);\n  endif\n\n  ## These defaults are rather stringent.  I think that normally, user\n  ## prefers accuracy to performance.\n\n  tolx = optimget (options, \"TolX\", 1e-7);\n  tolf = optimget (options, \"TolFun\", 1e-7);\n\n  factor = 0.1;\n  ## FIXME: TypicalX corresponds to user scaling (???)\n  autodg = true;\n\n  niter = 1;\n  nfev = 0;\n\n  x = x0(:);\n  info = 0;\n\n  ## Initial evaluation.\n  fval = fcn (reshape (x, xsz));\n  n = length (x);\n\n  if (! isempty (outfcn))\n    optimvalues.iter = niter;\n    optimvalues.funccount = nfev;\n    optimvalues.fval = fval;\n    optimvalues.searchdirection = zeros (n, 1);\n    state = \"init\";\n    stop = outfcn (x, optimvalues, state);\n    if (stop)\n      info = -1;\n      return;\n    endif\n  endif\n\n  if (isa (x0, \"single\") || isa (fval, \"single\"))\n    macheps = eps (\"single\");\n  else\n    macheps = eps (\"double\");\n  endif\n\n  nsuciter = 0;\n  lastratio = 0;\n\n  grad = [];\n\n  ## Outer loop.\n  while (niter < maxiter && nfev < maxfev && ! info)\n\n    grad0 = grad;\n\n    ## Calculate function value and gradient (possibly via FD).\n    if (has_grad)\n      [fval, grad] = fcn (reshape (x, xsz));\n      grad = grad(:);\n      nfev += 1;\n    else\n      grad = __fdjac__ (fcn, reshape (x, xsz), fval, typicalx, cdif)(:);\n      nfev += (1 + cdif) * length (x);\n    endif\n\n    if (niter == 1)\n      ## Initialize by identity matrix.\n      hesr = eye (n);\n    else\n      ## Use the damped BFGS formula.\n      y = grad - grad0;\n      sBs = sumsq (w);\n      Bs = hesr' * w;\n      sy = y' * s;\n      theta = 0.8 / max (1 - sy / sBs, 0.8);\n      r = theta * y + (1-theta) * Bs;\n      hesr = cholupdate (hesr, r / sqrt (s' * r), \"+\");\n      [hesr, info] = cholupdate (hesr, Bs / sqrt (sBs), \"-\");\n      if (info)\n        hesr = eye (n);\n      endif\n    endif\n\n    if (autoscale)\n      ## Second derivatives approximate the Hessian.\n      d2f = norm (hesr, \"columns\").';\n      if (niter == 1)\n        dg = d2f;\n      else\n        ## FIXME: maybe fixed lower and upper bounds?\n        dg = max (0.1*dg, d2f);\n      endif\n    endif\n\n    if (niter == 1)\n      xn = norm (dg .* x);\n      ## FIXME: something better?\n      delta = factor * max (xn, 1);\n    endif\n\n    ## FIXME: why tolf*n*xn?  If abs (e) ~ abs(x) * eps is a vector\n    ## of perturbations of x, then norm (hesr*e) <= eps*xn, i.e., by\n    ## tolf ~ eps we demand as much accuracy as we can expect.\n    if (norm (grad) <= tolf*n*xn)\n      info = 1;\n      break;\n    endif\n\n    suc = false;\n    decfac = 0.5;\n\n    ## Inner loop.\n    while (! suc && niter <= maxiter && nfev < maxfev && ! info)\n\n      s = - __doglegm__ (hesr, grad, dg, delta);\n\n      sn = norm (dg .* s);\n      if (niter == 1)\n        delta = min (delta, sn);\n      endif\n\n      fval1 = fcn (reshape (x + s, xsz))(:);\n      nfev += 1;\n\n      if (fval1 < fval)\n        ## Scaled actual reduction.\n        actred = (fval - fval1) / (abs (fval1) + abs (fval));\n      else\n        actred = -1;\n      endif\n\n      w = hesr * s;\n      ## Scaled predicted reduction, and ratio.\n      t = 1/2 * sumsq (w) + grad'*s;\n      if (t < 0)\n        prered = -t/(abs (fval) + abs (fval + t));\n        ratio = actred / prered;\n      else\n        prered = 0;\n        ratio = 0;\n      endif\n\n      ## Update delta.\n      if (ratio < min (max (0.1, 0.8*lastratio), 0.9))\n        delta *= decfac;\n        decfac ^= 1.4142;\n        if (delta <= 10*macheps*xn)\n          ## Trust region became uselessly small.\n          info = -3;\n          break;\n        endif\n      else\n        lastratio = ratio;\n        decfac = 0.5;\n        if (abs (1-ratio) <= 0.1)\n          delta = 1.4142*sn;\n        elseif (ratio >= 0.5)\n          delta = max (delta, 1.4142*sn);\n        endif\n      endif\n\n      if (ratio >= 1e-4)\n        ## Successful iteration.\n        x += s;\n        xn = norm (dg .* x);\n        fval = fval1;\n        nsuciter += 1;\n        suc = true;\n      endif\n\n      niter += 1;\n\n      ## FIXME: should outputfcn be called only after a successful iteration?\n      if (! isempty (outfcn))\n        optimvalues.iter = niter;\n        optimvalues.funccount = nfev;\n        optimvalues.fval = fval;\n        optimvalues.searchdirection = s;\n        state = \"iter\";\n        stop = outfcn (x, optimvalues, state);\n        if (stop)\n          info = -1;\n          break;\n        endif\n      endif\n\n      ## Tests for termination conditions.  A mysterious place, anything\n      ## can happen if you change something here...\n\n      ## The rule of thumb (which I'm not sure M*b is quite following)\n      ## is that for a tolerance that depends on scaling, only 0 makes\n      ## sense as a default value.  But 0 usually means uselessly long\n      ## iterations, so we need scaling-independent tolerances wherever\n      ## possible.\n\n      ## The following tests done only after successful step.\n      if (ratio >= 1e-4)\n        ## This one is classic.  Note that we use scaled variables again,\n        ## but compare to scaled step, so nothing bad.\n        if (sn <= tolx*xn)\n          info = 2;\n          ## Again a classic one.\n        elseif (actred < tolf)\n          info = 3;\n        endif\n      endif\n\n    endwhile\n  endwhile\n\n  ## When info != 1, recalculate the gradient and Hessian using the final x.\n  if (nargout > 4 && (info == -1 || info == 2 || info == 3))\n    grad0 = grad;\n    if (has_grad)\n      [fval, grad] = fcn (reshape (x, xsz));\n      grad = grad(:);\n    else\n      grad = __fdjac__ (fcn, reshape (x, xsz), fval, typicalx, cdif)(:);\n    endif\n\n    if (nargout > 5)\n      ## Use the damped BFGS formula.\n      y = grad - grad0;\n      sBs = sumsq (w);\n      Bs = hesr' * w;\n      sy = y' * s;\n      theta = 0.8 / max (1 - sy / sBs, 0.8);\n      r = theta * y + (1-theta) * Bs;\n      hesr = cholupdate (hesr, r / sqrt (s' * r), \"+\");\n      hesr = cholupdate (hesr, Bs / sqrt (sBs), \"-\");\n    endif\n    ## Return the gradient in the same shape as x\n    grad = reshape (grad, xsz);\n  endif\n\n  ## Restore original shapes.\n  x = reshape (x, xsz);\n\n  if (nargout > 3)\n    output.iterations = niter;\n    output.successful = nsuciter;\n    output.funcCount = nfev;\n  endif\n\n  if (nargout > 5)\n    hess = hesr'*hesr;\n  endif\n\nendfunction\n\n## A helper function that evaluates a function and checks for bad results.\nfunction [fx, gx] = guarded_eval (fcn, x)\n\n  if (nargout > 1)\n    [fx, gx] = fcn (x);\n  else\n    fx = fcn (x);\n    gx = [];\n  endif\n\n  if (! (isreal (fx) && isreal (gx)))\n    error (\"Octave:fminunc:notreal\", \"fminunc: non-real value encountered\");\n  elseif (any (isnan (fx(:))))\n    error (\"Octave:fminunc:isnan\", \"fminunc: NaN value encountered\");\n  elseif (any (isinf (fx(:))))\n    error (\"Octave:fminunc:isinf\", \"fminunc: Inf value encountered\");\n  endif\n\nendfunction\n\n\n%!function f = __rosenb__ (x)\n%!  n = length (x);\n%!  f = sumsq (1 - x(1:n-1)) + 100 * sumsq (x(2:n) - x(1:n-1).^2);\n%!endfunction\n%!\n%!test\n%! [x, fval, info, out] = fminunc (@__rosenb__, [5, -5]);\n%! tol = 2e-5;\n%! assert (info > 0);\n%! assert (x, ones (1, 2), tol);\n%! assert (fval, 0, tol);\n%!test\n%! [x, fval, info, out] = fminunc (@__rosenb__, zeros (1, 4));\n%! tol = 2e-5;\n%! assert (info > 0);\n%! assert (x, ones (1, 4), tol);\n%! assert (fval, 0, tol);\n\n## Test FunValCheck works correctly\n%!assert (fminunc (@(x) x^2, 1, optimset (\"FunValCheck\", \"on\")), 0, 1e-6)\n%!error <non-real value> fminunc (@(x) x + i, 1, optimset (\"FunValCheck\", \"on\"))\n%!error <NaN value> fminunc (@(x) x + NaN, 1, optimset (\"FunValCheck\", \"on\"))\n%!error <Inf value> fminunc (@(x) x + Inf, 1, optimset (\"FunValCheck\", \"on\"))\n\n\n## Solve the double dogleg trust-region minimization problem:\n## Minimize 1/2*norm(r*x)^2  subject to the constraint norm(d.*x) <= delta,\n## x being a convex combination of the gauss-newton and scaled gradient.\n\n## FIXME: error checks\n## FIXME: handle singularity, or leave it up to mldivide?\n\nfunction x = __doglegm__ (r, g, d, delta)\n\n  ## Get Gauss-Newton direction.\n  b = r' \\ g;\n  x = r \\ b;\n  xn = norm (d .* x);\n  if (xn > delta)\n    ## GN is too big, get scaled gradient.\n    s = g ./ d;\n    sn = norm (s);\n    if (sn > 0)\n      ## Normalize and rescale.\n      s = (s / sn) ./ d;\n      ## Get the line minimizer in s direction.\n      tn = norm (r*s);\n      snm = (sn / tn) / tn;\n      if (snm < delta)\n        ## Get the dogleg path minimizer.\n        bn = norm (b);\n        dxn = delta/xn; snmd = snm/delta;\n        t = (bn/sn) * (bn/xn) * snmd;\n        t -= dxn * snmd^2 - sqrt ((t-dxn)^2 + (1-dxn^2)*(1-snmd^2));\n        alpha = dxn*(1-snmd^2) / t;\n      else\n        alpha = 0;\n      endif\n    else\n      alpha = delta / xn;\n      snm = 0;\n    endif\n    ## Form the appropriate convex combination.\n    x = alpha * x + ((1-alpha) * min (snm, delta)) * s;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/optimization/fsolve.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} fsolve (@var{fcn}, @var{x0})\n## @deftypefnx {} {@var{x} =} fsolve (@var{fcn}, @var{x0}, @var{options})\n## @deftypefnx {} {[@var{x}, @var{fval}] =} fsolve (@dots{})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}] =} fsolve (@dots{})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}, @var{output}] =} fsolve (@dots{})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}, @var{output}, @var{fjac}] =} fsolve (@dots{})\n## Solve a system of nonlinear equations defined by the function @var{fcn}.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function to evaluate.  @var{fcn} should accept a vector (array)\n## defining the unknown variables, and return a vector of left-hand sides of\n## the equations.  Right-hand sides are defined to be zeros.  In other words,\n## this function attempts to determine a vector @var{x} such that\n## @code{@var{fcn} (@var{x})} gives (approximately) all zeros.\n##\n## @var{x0} is an initial guess for the solution.  The shape of @var{x0} is\n## preserved in all calls to @var{fcn}, but otherwise is treated as a column\n## vector.\n##\n## @var{options} is a structure specifying additional parameters which\n## control the algorithm.  Currently, @code{fsolve} recognizes these options:\n## @qcode{\"AutoScaling\"}, @qcode{\"ComplexEqn\"}, @qcode{\"FinDiffType\"},\n## @qcode{\"FunValCheck\"}, @qcode{\"Jacobian\"}, @qcode{\"MaxFunEvals\"},\n## @qcode{\"MaxIter\"}, @qcode{\"OutputFcn\"}, @qcode{\"TolFun\"}, @qcode{\"TolX\"},\n## @qcode{\"TypicalX\"}, and @qcode{\"Updating\"}.\n##\n## If @qcode{\"AutoScaling\"} is @qcode{\"on\"}, the variables will be\n## automatically scaled according to the column norms of the (estimated)\n## Jacobian.  As a result, @qcode{\"TolFun\"} becomes scaling-independent.  By\n## default, this option is @qcode{\"off\"} because it may sometimes deliver\n## unexpected (though mathematically correct) results.\n##\n## If @qcode{\"ComplexEqn\"} is @qcode{\"on\"}, @code{fsolve} will attempt to solve\n## complex equations in complex variables, assuming that the equations possess\n## a complex derivative (i.e., are holomorphic).  If this is not what you want,\n## you should unpack the real and imaginary parts of the system to get a real\n## system.\n##\n## If @qcode{\"Jacobian\"} is @qcode{\"on\"}, it specifies that @var{fcn}---when\n## called with 2 output arguments---also returns the Jacobian matrix of\n## right-hand sides at the requested point.\n##\n## @qcode{\"MaxFunEvals\"} proscribes the maximum number of function evaluations\n## before optimization is halted.  The default value is\n## @code{100 * number_of_variables}, i.e., @code{100 * length (@var{x0})}.\n## The value must be a positive integer.\n##\n## If @qcode{\"Updating\"} is @qcode{\"on\"}, the function will attempt to use\n## @nospell{Broyden} updates to update the Jacobian, in order to reduce the\n## number of Jacobian calculations.  If your user function always calculates\n## the Jacobian (regardless of number of output arguments) then this option\n## provides no advantage and should be disabled.\n##\n## @qcode{\"TolX\"} specifies the termination tolerance in the unknown variables,\n## while @qcode{\"TolFun\"} is a tolerance for equations.  Default is @code{1e-6}\n## for both @qcode{\"TolX\"} and @qcode{\"TolFun\"}.\n##\n## For a description of the other options,\n## @pxref{XREFoptimset,,@code{optimset}}.  To initialize an options structure\n## with default values for @code{fsolve} use\n## @code{options = optimset (\"fsolve\")}.\n##\n## The first output @var{x} is the solution while the second output @var{fval}\n## contains the value of the function @var{fcn} evaluated at @var{x} (ideally\n## a vector of all zeros).\n##\n## The third output @var{info} reports whether the algorithm succeeded and may\n## take one of the following values:\n##\n## @table @asis\n## @item 1\n## Converged to a solution point.  Relative residual error is less than\n## specified by @code{TolFun}.\n##\n## @item 2\n## Last relative step size was less than @code{TolX}.\n##\n## @item 3\n## Last relative decrease in residual was less than @code{TolFun}.\n##\n## @item 0\n## Iteration limit (either @code{MaxIter} or @code{MaxFunEvals}) exceeded.\n##\n## @item -1\n## Stopped by @code{OutputFcn}.\n##\n## @item -2\n## The Jacobian became excessively small and the search stalled.\n##\n## @item -3\n## The trust region radius became excessively small.\n## @end table\n##\n## @var{output} is a structure containing runtime information about the\n## @code{fsolve} algorithm.  Fields in the structure are:\n##\n## @table @code\n## @item iterations\n##  Number of iterations through loop.\n##\n## @item successful\n##  Number of successful iterations.\n##\n## @item @nospell{funcCount}\n##  Number of function evaluations.\n##\n## @end table\n##\n## The final output @var{fjac} contains the value of the Jacobian evaluated\n## at @var{x}.\n##\n## Note: If you only have a single nonlinear equation of one variable, using\n## @code{fzero} is usually a much better idea.\n##\n## Note about user-supplied Jacobians:\n## As an inherent property of the algorithm, a Jacobian is always requested for\n## a solution vector whose residual vector is already known, and it is the last\n## accepted successful step.  Often this will be one of the last two calls, but\n## not always.  If the savings by reusing intermediate results from residual\n## calculation in Jacobian calculation are significant, the best strategy is to\n## employ @code{OutputFcn}: After a vector is evaluated for residuals, if\n## @code{OutputFcn} is called with that vector, then the intermediate results\n## should be saved for future Jacobian evaluation, and should be kept until a\n## Jacobian evaluation is requested or until @code{OutputFcn} is called with a\n## different vector, in which case they should be dropped in favor of this most\n## recent vector.  A short example how this can be achieved follows:\n##\n## @example\n## function [fval, fjac] = user_fcn (x, optimvalues, state)\n## persistent sav = [], sav0 = [];\n## if (nargin == 1)\n##   ## evaluation call\n##   if (nargout == 1)\n##     sav0.x = x;  # mark saved vector\n##     ## calculate fval, save results to sav0.\n##   elseif (nargout == 2)\n##     ## calculate fjac using sav.\n##   endif\n## else\n##   ## outputfcn call.\n##   if (all (x == sav0.x))\n##     sav = sav0;\n##   endif\n##   ## maybe output iteration status, etc.\n## endif\n## endfunction\n##\n## ## @dots{}\n##\n## fsolve (@@user_fcn, x0, optimset (\"OutputFcn\", @@user_fcn, @dots{}))\n## @end example\n## @seealso{fzero, optimset}\n## @end deftypefn\n\n## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.\n## PKG_ADD: [~] = __all_opts__ (\"fsolve\");\n\nfunction [x, fval, info, output, fjac] = fsolve (fcn, x0, options = struct ())\n\n  ## Get default options if requested.\n  if (nargin == 1 && ischar (fcn) && strcmp (fcn, \"defaults\"))\n    x = struct (\"AutoScaling\", \"off\", \"ComplexEqn\", \"off\",\n                \"FunValCheck\", \"off\", \"FinDiffType\", \"forward\",\n                \"Jacobian\", \"off\",  \"MaxFunEvals\", [], \"MaxIter\", 400,\n                \"OutputFcn\", [], \"Updating\", \"off\", \"TolFun\", 1e-6,\n                \"TolX\", 1e-6, \"TypicalX\", []);\n    return;\n  endif\n\n  if (nargin < 2 || ! isnumeric (x0))\n    print_usage ();\n  endif\n\n  if (ischar (fcn))\n    fcn = str2func (fcn);\n  elseif (iscell (fcn))\n    fcn = @(x) make_fcn_jac (x, fcn{1}, fcn{2});\n  endif\n\n  xsiz = size (x0);\n  n = numel (x0);\n\n  has_jac = strcmpi (optimget (options, \"Jacobian\", \"off\"), \"on\");\n  cdif = strcmpi (optimget (options, \"FinDiffType\", \"forward\"), \"central\");\n  maxiter = optimget (options, \"MaxIter\", 400);\n  maxfev = optimget (options, \"MaxFunEvals\", 100*n);\n  outfcn = optimget (options, \"OutputFcn\");\n  updating = strcmpi (optimget (options, \"Updating\", \"off\"), \"on\");\n  complexeqn = strcmpi (optimget (options, \"ComplexEqn\", \"off\"), \"on\");\n\n  ## Get scaling matrix using the TypicalX option.  If set to \"auto\", the\n  ## scaling matrix is estimated using the Jacobian.\n  typicalx = optimget (options, \"TypicalX\", ones (n, 1));\n\n  autoscale = strcmpi (optimget (options, \"AutoScaling\", \"off\"), \"on\");\n  if (! autoscale)\n    dg = 1 ./ typicalx;\n  endif\n\n  funvalchk = strcmpi (optimget (options, \"FunValCheck\", \"off\"), \"on\");\n\n  if (funvalchk)\n    ## Replace fcn with a guarded version.\n    fcn = @(x) guarded_eval (fcn, x, complexeqn);\n  endif\n\n  ## These defaults are rather stringent.\n  ## Normally user prefers accuracy to performance.\n\n  tolx = optimget (options, \"TolX\", 1e-6);\n  tolf = optimget (options, \"TolFun\", 1e-6);\n\n  factor = 1;\n\n  niter = 1;\n  nfev = 1;\n\n  x = x0(:);\n  info = 0;\n\n  ## Initial evaluation.\n  ## Handle arbitrary shapes of x and f and remember them.\n  fval = fcn (reshape (x, xsiz));\n  fsiz = size (fval);\n  fval = fval(:);\n  fn = norm (fval);\n  m = length (fval);\n  n = length (x);\n\n  if (! isempty (outfcn))\n    optimvalues.iter = niter;\n    optimvalues.funccount = nfev;\n    optimvalues.fval = fn;\n    optimvalues.searchdirection = zeros (n, 1);\n    state = \"init\";\n    stop = outfcn (x, optimvalues, state);\n    if (stop)\n      info = -1;\n      output.iterations = niter;\n      output.successful = 0;\n      output.funcCount = nfev;\n      fjac = NaN;\n      return;\n    endif\n  endif\n\n  if (isa (x0, \"single\") || isa (fval, \"single\"))\n    macheps = eps (\"single\");\n  else\n    macheps = eps (\"double\");\n  endif\n\n  nsuciter = 0;\n\n  ## Outer loop.\n  while (niter < maxiter && nfev < maxfev && ! info)\n\n    ## Calculate function value and Jacobian (possibly via FD).\n    if (has_jac)\n      [fval, fjac] = fcn (reshape (x, xsiz));\n      if (! all (size (fjac) == [m, n]))\n        error (\"fsolve: Jacobian size should be (%d,%d), not (%d,%d)\",\n               m, n, rows (fjac), columns (fjac));\n      endif\n      ## If the Jacobian is sparse, disable Broyden updating.\n      if (issparse (fjac))\n        updating = false;\n      endif\n      fval = fval(:);\n      nfev += 1;\n    else\n      fjac = __fdjac__ (fcn, reshape (x, xsiz), fval, typicalx, cdif);\n      nfev += (1 + cdif) * length (x);\n    endif\n\n    ## For square and overdetermined systems, we update a QR factorization of\n    ## the Jacobian to avoid solving a full system in each step.  In this case,\n    ## we pass a triangular matrix to __dogleg__.\n    useqr = updating && m >= n && n > 10;\n\n    if (useqr)\n      ## FIXME: Currently, pivoting is mostly useless because the \\ operator\n      ## cannot exploit the resulting props of the triangular factor.\n      ## Unpivoted QR is significantly faster so it doesn't seem right to pivot\n      ## just to get invariance.  Original MINPACK didn't pivot either,\n      ## at least when qr updating was used.\n      [q, r] = qr (fjac, 0);\n    endif\n\n    if (autoscale)\n      ## Get column norms, use them as scaling factors.\n      jcn = norm (fjac, \"columns\").';\n      if (niter == 1)\n        dg = jcn;\n        dg(dg == 0) = 1;\n      else\n        ## Rescale adaptively.\n        ## FIXME: the original minpack used the following rescaling strategy:\n        ##   dg = max (dg, jcn);\n        ## but it seems not good if we start with a bad guess yielding Jacobian\n        ## columns with large norms that later decrease, because the\n        ## corresponding variable will still be overscaled.  Instead, we only\n        ## give the old scaling a small momentum, but do not honor it.\n\n        dg = max (0.1*dg, jcn);\n      endif\n    endif\n\n    if (niter == 1)\n      xn = norm (dg .* x);\n      ## FIXME: something better?\n      delta = factor * max (xn, 1);\n    endif\n\n    ## It also seems that in the case of fast (and inhomogeneously) changing\n    ## Jacobian, the Broyden updates are of little use, so maybe we could\n    ## skip them if a big disproportional change is expected.  The question is,\n    ## of course, how to define the above terms :)\n\n    lastratio = 0;\n    nfail = 0;\n    nsuc = 0;\n    decfac = 0.5;\n\n    ## Inner loop.\n    while (niter <= maxiter && nfev < maxfev && ! info)\n\n      ## Get trust-region model (dogleg) minimizer.\n      if (useqr)\n        if (norm (r, 1) < macheps * rows (r))\n          info = -2;\n          break;\n        endif\n        qtf = q'*fval;\n        s = - __dogleg__ (r, qtf, dg, delta);\n        w = qtf + r * s;\n      else\n        if (norm (fjac, 1) < macheps * rows (fjac))\n          info = -2;\n          break;\n        endif\n        s = - __dogleg__ (fjac, fval, dg, delta);\n        w = fval + fjac * s;\n      endif\n\n      sn = norm (dg .* s);\n      if (niter == 1)\n        delta = min (delta, sn);\n      endif\n\n      fval1 = fcn (reshape (x + s, xsiz)) (:);\n      fn1 = norm (fval1);\n      nfev += 1;\n\n      if (fn1 < fn)\n        ## Scaled actual reduction.\n        actred = 1 - (fn1/fn)^2;\n      else\n        actred = -1;\n      endif\n\n      ## Scaled predicted reduction, and ratio.\n      t = norm (w);\n      if (t < fn)\n        prered = 1 - (t/fn)^2;\n        ratio = actred / prered;\n      else\n        prered = 0;\n        ratio = 0;\n      endif\n\n      ## Update delta.\n      if (ratio < min (max (0.1, 0.8*lastratio), 0.9))\n        nsuc = 0;\n        nfail += 1;\n        delta *= decfac;\n        decfac ^= 1.4142;\n        if (fn <= tolf*n*xn)\n          info = 1;\n        elseif (delta <= 1e1*macheps*xn)\n          ## Trust region became uselessly small.\n          info = -3;\n          break;\n        endif\n      else\n        lastratio = ratio;\n        decfac = 0.5;\n        nfail = 0;\n        nsuc += 1;\n        if (abs (1-ratio) <= 0.1)\n          delta = 1.4142*sn;\n        elseif (ratio >= 0.5 || nsuc > 1)\n          delta = max (delta, 1.4142*sn);\n        endif\n      endif\n\n      if (ratio >= 1e-4)\n        ## Successful iteration.\n        x += s;\n        xn = norm (dg .* x);\n        fval = fval1;\n        fn = fn1;\n        nsuciter += 1;\n      endif\n\n      niter += 1;\n\n      ## FIXME: should outputfcn be only called after a successful iteration?\n      if (! isempty (outfcn))\n        optimvalues.iter = niter;\n        optimvalues.funccount = nfev;\n        optimvalues.fval = fn;\n        optimvalues.searchdirection = s;\n        state = \"iter\";\n        stop = outfcn (x, optimvalues, state);\n        if (stop)\n          info = -1;\n          output.iterations = niter;\n          output.successful = nsuciter;\n          output.funcCount = nfev;\n          break;\n        endif\n      endif\n\n      ## Tests for termination conditions.  A mysterious place, anything\n      ## can happen if you change something here...\n\n      ## The rule of thumb (which I'm not sure M*b is quite following)\n      ## is that for a tolerance that depends on scaling, only 0 makes\n      ## sense as a default value.  But 0 usually means uselessly long\n      ## iterations, so we need scaling-independent tolerances wherever\n      ## possible.\n\n      ## FIXME: Why tolf*n*xn? If abs (e) ~ abs(x) * eps is a vector\n      ## of perturbations of x, then norm (fjac*e) <= eps*n*xn, i.e., by\n      ## tolf ~ eps we demand as much accuracy as we can expect.\n      if (fn <= tolf*n*xn)\n        info = 1;\n        ## The following tests done only after successful step.\n      elseif (ratio >= 1e-4)\n        ## This one is classic.  Note that we use scaled variables again,\n        ## but compare to scaled step, so nothing bad.\n        if (sn <= tolx*xn)\n          info = 2;\n          ## Again a classic one.  It seems weird to use the same tolf\n          ## for two different tests, but that's what M*b manual appears\n          ## to say.\n        elseif (actred < tolf)\n          info = 3;\n        endif\n      endif\n\n      ## Criterion for recalculating Jacobian.\n      if (! updating || nfail == 2 || nsuciter < 2)\n        break;\n      endif\n\n      ## Compute the scaled Broyden update.\n      if (useqr)\n        u = (fval1 - q*w) / sn;\n        v = dg .* ((dg .* s) / sn);\n\n        ## Update the QR factorization.\n        [q, r] = qrupdate (q, r, u, v);\n      else\n        u = (fval1 - w);\n        v = dg .* ((dg .* s) / sn);\n\n        ## update the Jacobian\n        fjac += u * v';\n      endif\n    endwhile\n  endwhile\n\n  ## Restore original shapes.\n  x = reshape (x, xsiz);\n  fval = reshape (fval, fsiz);\n\n  output.iterations = niter;\n  output.successful = nsuciter;\n  output.funcCount = nfev;\n\nendfunction\n\n## A helper function that evaluates a function and checks for bad results.\nfunction [fx, jx] = guarded_eval (fcn, x, complexeqn)\n\n  if (nargout > 1)\n    [fx, jx] = fcn (x);\n  else\n    fx = fcn (x);\n    jx = [];\n  endif\n\n  if (! complexeqn && ! (isreal (fx) && isreal (jx)))\n    error (\"Octave:fsolve:notreal\", \"fsolve: non-real value encountered\");\n  elseif (complexeqn && ! (isnumeric (fx) && isnumeric (jx)))\n    error (\"Octave:fsolve:notnum\", \"fsolve: non-numeric value encountered\");\n  elseif (any (isnan (fx(:))))\n    error (\"Octave:fsolve:isnan\", \"fsolve: NaN value encountered\");\n  elseif (any (isinf (fx(:))))\n    error (\"Octave:fsolve:isinf\", \"fsolve: Inf value encountered\");\n  endif\n\nendfunction\n\nfunction [fx, jx] = make_fcn_jac (x, fcn, fjac)\n\n  fx = fcn (x);\n  if (nargout == 2)\n    jx = fjac (x);\n  endif\n\nendfunction\n\n## Solve the double dogleg trust-region least-squares problem:\n## Minimize norm (r*x-b) subject to the constraint norm (d.*x) <= delta,\n## x being a convex combination of the gauss-newton and scaled gradient.\n\n## FIXME: error checks\n## FIXME: handle singularity, or leave it up to mldivide?\n\nfunction x = __dogleg__ (r, b, d, delta)\n\n  ## Get Gauss-Newton direction.\n  x = r \\ b;\n  xn = norm (d .* x);\n  if (xn > delta)\n    ## GN is too big, get scaled gradient.\n    s = (r' * b) ./ d;\n    sn = norm (s);\n    if (sn > 0)\n      ## Normalize and rescale.\n      s = (s / sn) ./ d;\n      ## Get the line minimizer in s direction.\n      tn = norm (r*s);\n      snm = (sn / tn) / tn;\n      if (snm < delta)\n        ## Get the dogleg path minimizer.\n        bn = norm (b);\n        dxn = delta/xn; snmd = snm/delta;\n        t = (bn/sn) * (bn/xn) * snmd;\n        t -= dxn * snmd^2 - sqrt ((t-dxn)^2 + (1-dxn^2)*(1-snmd^2));\n        alpha = dxn*(1-snmd^2) / t;\n      else\n        alpha = 0;\n      endif\n    else\n      alpha = delta / xn;\n      snm = 0;\n    endif\n    ## Form the appropriate convex combination.\n    x = alpha * x + ((1-alpha) * min (snm, delta)) * s;\n  endif\n\nendfunction\n\n\n%!function retval = __f (p)\n%!  x = p(1);\n%!  y = p(2);\n%!  z = p(3);\n%!  retval = zeros (3, 1);\n%!  retval(1) = sin (x) + y^2 + log (z) - 7;\n%!  retval(2) = 3*x + 2^y -z^3 + 1;\n%!  retval(3) = x + y + z - 5;\n%!endfunction\n%!test\n%! x_opt = [ 0.599054;\n%!           2.395931;\n%!           2.005014 ];\n%! tol = 1.0e-5;\n%! [x, fval, info] = fsolve (@__f, [ 0.5; 2.0; 2.5 ]);\n%! assert (info > 0);\n%! assert (norm (x - x_opt, Inf) < tol);\n%! assert (norm (fval) < tol);\n\n%!function retval = __f (p)\n%!  x = p(1);\n%!  y = p(2);\n%!  z = p(3);\n%!  w = p(4);\n%!  retval = zeros (4, 1);\n%!  retval(1) = 3*x + 4*y + exp (z + w) - 1.007;\n%!  retval(2) = 6*x - 4*y + exp (3*z + w) - 11;\n%!  retval(3) = x^4 - 4*y^2 + 6*z - 8*w - 20;\n%!  retval(4) = x^2 + 2*y^3 + z - w - 4;\n%!endfunction\n%!test\n%! x_opt = [ -0.767297326653401, 0.590671081117440, ...\n%!            1.47190018629642, -1.52719341133957 ];\n%! tol = 1.0e-4;\n%! [x, fval, info] = fsolve (@__f, [-1, 1, 2, -1]);\n%! assert (info > 0);\n%! assert (norm (x - x_opt, Inf) < tol);\n%! assert (norm (fval) < tol);\n\n%!function retval = __f (p)\n%!  x = p(1);\n%!  y = p(2);\n%!  z = p(3);\n%!  retval = zeros (3, 1);\n%!  retval(1) = sin (x) + y^2 + log (z) - 7;\n%!  retval(2) = 3*x + 2^y -z^3 + 1;\n%!  retval(3) = x + y + z - 5;\n%!  retval(4) = x*x + y - z*log (z) - 1.36;\n%!endfunction\n%!test\n%! x_opt = [ 0.599054;\n%!           2.395931;\n%!           2.005014 ];\n%! tol = 1.0e-5;\n%! [x, fval, info] = fsolve (@__f, [ 0.5; 2.0; 2.5 ]);\n%! assert (info > 0);\n%! assert (norm (x - x_opt, Inf) < tol);\n%! assert (norm (fval) < tol);\n\n%!function retval = __f (p)\n%!  x = p(1);\n%!  y = p(2);\n%!  z = p(3);\n%!  retval = zeros (3, 1);\n%!  retval(1) = sin (x) + y^2 + log (z) - 7;\n%!  retval(2) = 3*x + 2^y -z^3 + 1;\n%!  retval(3) = x + y + z - 5;\n%!endfunction\n%!test\n%! x_opt = [ 0.599054;\n%!           2.395931;\n%!           2.005014 ];\n%! tol = 1.0e-5;\n%! opt = optimset (\"Updating\", \"qrp\");\n%! [x, fval, info] = fsolve (@__f, [ 0.5; 2.0; 2.5 ], opt);\n%! assert (info > 0);\n%! assert (norm (x - x_opt, Inf) < tol);\n%! assert (norm (fval) < tol);\n\n%!test\n%! b0 = 3;\n%! a0 = 0.2;\n%! x = 0:.5:5;\n%! noise = 1e-5 * sin (100*x);\n%! y = exp (-a0*x) + b0 + noise;\n%! c_opt = [a0, b0];\n%! tol = 1e-5;\n%!\n%! [c, fval, info, output] = fsolve (@(c) (exp(-c(1)*x) + c(2) - y), [0, 0]);\n%! assert (info > 0);\n%! assert (norm (c - c_opt, Inf) < tol);\n%! assert (norm (fval) < norm (noise));\n\n%!function y = cfcn (x)\n%!  y(1) = (1+i)*x(1)^2 - (1-i)*x(2) - 2;\n%!  y(2) = sqrt (x(1)*x(2)) - (1-2i)*x(3) + (3-4i);\n%!  y(3) = x(1) * x(2) - x(3)^2 + (3+2i);\n%!endfunction\n\n%!test\n%! x_opt = [-1+i, 1-i, 2+i];\n%! x = [i, 1, 1+i];\n%!\n%! [x, f, info] = fsolve (@cfcn, x, optimset (\"ComplexEqn\", \"on\"));\n%! tol = 1e-5;\n%! assert (norm (f) < tol);\n%! assert (norm (x - x_opt, Inf) < tol);\n\n%!test <*53991>\n%! A = @(lam) [0 1 0 0; 0 0 1 0; 0 0 0 1; 0 0 -lam^2 0];\n%! C = [1 0 0 0; 0 0 1 0];\n%! B = @(lam) [C*expm(A(lam)*0); C*expm(A(lam)*1)];\n%! detB = @(lam) det (B(lam));\n%!\n%! [x, fval, info] = fsolve (detB, 0);\n%! assert (x == 0);\n%! assert (fval == -1);\n%! assert (info == -2);\n\n%!test <*53991>\n%! [x, fval, info] = fsolve (@(x) 5*x, 0);\n%! assert (x == 0);\n%! assert (fval == 0);\n%! assert (info == 1);\n"
  },
  {
    "path": "scripts/optimization/fzero.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} fzero (@var{fcn}, @var{x0})\n## @deftypefnx {} {@var{x} =} fzero (@var{fcn}, @var{x0}, @var{options})\n## @deftypefnx {} {[@var{x}, @var{fval}] =} fzero (@dots{})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}] =} fzero (@dots{})\n## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}, @var{output}] =} fzero (@dots{})\n## Find a zero of a univariate function.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function to evaluate.\n##\n## @var{x0} should be a two-element vector specifying two points which bracket\n## a zero.  In other words, there must be a change in sign of the function\n## between @var{x0}(1) and @var{x0}(2).  More mathematically, the following\n## must hold\n##\n## @example\n## sign (@var{fcn} (@var{x0}(1))) * sign (@var{fcn} (@var{x0}(2))) <= 0\n## @end example\n##\n## If @var{x0} is a single scalar then several nearby and distant values are\n## probed in an attempt to obtain a valid bracketing.  If this is not\n## successful, the function fails.\n##\n## @var{options} is a structure specifying additional options.  Currently,\n## @code{fzero} recognizes these options:\n## @qcode{\"Display\"}, @qcode{\"FunValCheck\"}, @qcode{\"MaxFunEvals\"},\n## @qcode{\"MaxIter\"}, @qcode{\"OutputFcn\"}, and @qcode{\"TolX\"}.\n##\n## @qcode{\"MaxFunEvals\"} proscribes the maximum number of function evaluations\n## before the search is halted.  The default value is @code{Inf}.\n## The value must be a positive integer.\n##\n## @qcode{\"MaxIter\"} proscribes the maximum number of algorithm iterations\n## before the search is halted.  The default value is @code{Inf}.\n## The value must be a positive integer.\n##\n## @qcode{\"TolX\"} specifies the termination tolerance for the solution @var{x}.\n## The default value is @code{eps}.\n##\n## For a description of the other options,\n## @pxref{XREFoptimset,,@code{optimset}}.\n## To initialize an options structure with default values for @code{fzero} use\n## @code{options = optimset (\"fzero\")}.\n##\n## On exit, the function returns @var{x}, the approximate zero point, and\n## @var{fval}, the function evaluated at @var{x}.\n##\n## The third output @var{info} reports whether the algorithm succeeded and\n## may take one of the following values:\n##\n## @itemize\n## @item 1\n##  The algorithm converged to a solution.\n##\n## @item 0\n##  Maximum number of iterations or function evaluations has been reached.\n##\n## @item -1\n##  The algorithm has been terminated by a user @code{OutputFcn}.\n##\n## @item -5\n##  The algorithm may have converged to a singular point.\n##\n## @item -6\n##  No valid initial bracketing with a sign change found.\n## @end itemize\n##\n## @var{output} is a structure containing runtime information about the\n## @code{fzero} algorithm.  Fields in the structure are:\n##\n## @itemize\n## @item @nospell{intervaliterations}\n##  Number of iterations searching for a bracketing interval.\n##\n## @item iterations\n##  Number of iterations searching for a zero.\n##\n## @item @nospell{funcCount}\n##  Number of function evaluations.\n##\n## @item algorithm\n##  The string @qcode{\"bisection, interpolation\"}.\n##\n## @item message\n##  A string with the final status of the algorithm.\n##\n## @item bracketx\n##  A two-element vector with the final bracketing of the zero along the\n## x-axis.\n##\n## @item brackety\n##  A two-element vector with the final bracketing of the zero along the\n## y-axis.\n## @end itemize\n##\n## Programming Notes: The algorithm relies on the function crossing the x-axis\n## and having both positive and negative values.  It will not generally work\n## for functions which only touch the x-axis, e.g., @math{x^2}.  The function\n## will generally be faster if a 2-element bracketing interval @var{x0} is\n## supplied since no interval search will be conducted.\n## @seealso{fsolve, fminbnd, optimset}\n## @end deftypefn\n\n## This is essentially the @nospell{ACM} algorithm 748: Enclosing Zeros of\n## Continuous Functions due to Alefeld, Potra and Shi, @nospell{ACM}\n## Transactions on Mathematical Software, @w{Vol.@: 21}, @w{No.@: 3}, September\n## 1995.\n## Although the workflow should be the same, the structure of the algorithm has\n## been transformed non-trivially; instead of the authors' approach of\n## sequentially calling building block subprograms we implement here an\n## FSM version using one interior point determination and one bracketing\n## per iteration, thus reducing the number of temporary variables and\n## simplifying the algorithm structure.  Further, this approach reduces\n## the need for external functions and error handling.  The algorithm has\n## also been slightly modified.\n\n## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.\n## PKG_ADD: [~] = __all_opts__ (\"fzero\");\n\nfunction [x, fval, info, output] = fzero (fcn, x0, options = struct ())\n\n  ## Get default options if requested.\n  if (nargin == 1 && ischar (fcn) && strcmp (fcn, \"defaults\"))\n    x = struct (\"Display\", \"notify\", \"FunValCheck\", \"off\",\n                \"MaxFunEvals\", Inf, \"MaxIter\", Inf,\n                \"OutputFcn\", [], \"TolX\", eps);\n    return;\n  endif\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (ischar (fcn))\n    fcn = str2func (fcn);\n  endif\n\n  displev = optimget (options, \"Display\", \"notify\");\n  switch (displev)\n    case \"iter\"\n      displev = 1;\n    case \"final\"\n      displev = 2;\n    case \"notify\"\n      displev = 3;\n    otherwise  # \"none\"\n      displev = 0;\n  endswitch\n\n  funvalchk = strcmpi (optimget (options, \"FunValCheck\", \"off\"), \"on\");\n  maxfev = optimget (options, \"MaxFunEvals\", Inf);\n  maxiter = optimget (options, \"MaxIter\", Inf);\n  outfcn = optimget (options, \"OutputFcn\");\n  have_outfcn = ! isempty (outfcn);\n  tolx = optimget (options, \"TolX\", eps);\n\n  ## FIXME: This \"constant\" is used twice, but no apparent reason why it\n  ## shouldn't just be a fixed value in the code.\n  mu = 0.5;\n\n  if (funvalchk)\n    ## Replace fcn with a guarded version.\n    fcn = @(x) guarded_eval (fcn, x);\n  endif\n\n  info = 0;  # The default exit flag if number of iterations exceeded.\n  nint = 0;  # number of interval searches if only one point x0 given\n  niter = 0; # number of iterations of search algorithm\n  nfev = 0;  # number of function evaluations\n  x = fval = a = fa = b = fb = NaN;\n\n  ## Prepare initial bracket [a,b] around a change in sign\n  a = x0(1);\n  fa = fcn (a);\n  nfev = 1;\n  if (numel (x0) > 1)\n    ## fzero called with initial bracket x0 = [a,b]\n    b = x0(2);\n    fb = fcn (b);\n    nfev += 1;\n  else\n    ## Only a given.  Try to find a value for b which brackets a zero-crossing.\n    ## For very small values, switch to absolute rather than relative search\n    if (abs (a) < .001)\n      aa = ifelse (a == 0, 0.1, sign (a) * 0.1);\n    else\n      aa = a;\n    endif\n\n    if (displev == 1)\n      printf (\"\\nSearch for an interval around %g containing a sign change:\\n\", a);\n      printf (\" Fcn-count       a           f(a)            b           f(b)        Procedure\\n\");\n      fmt_str = \" %4d     %13.6g %13.6g %13.6g %13.6g    %s\\n\";\n      printf (fmt_str, nfev, a, fa, a, fa, \"initial interval\");\n    endif\n\n    info = -6;  # Preset error condition as bracket not found\n    ## Search in an ever-widening range around the initial point.\n    ## FIXME: Matlab does a much more exhaustive search moving both a and b and\n    ## increasing the range by approximately sqrt(2) each time.  This can\n    ## proceed for 1000's of function evaluations.  Octave does a quick search\n    ## and if no bracket is found returns control to the user to provide a\n    ## bracket.\n    for srch = [-.01 +.025 -.05 +.10 -.25 +.50 -1 +2.5 -5 +10 -50 +100 -500 +1000]\n      b = aa + aa*srch;\n      nint += 1;\n      fb = fcn (b);\n      nfev += 1;\n      if (displev == 1)\n        printf (fmt_str, nfev, a, fa, b, fb, \"search\");\n      endif\n      if (sign (fa) * sign (fb) <= 0)\n        info = 0;\n        break;\n      endif\n    endfor\n  endif\n\n  if (iscomplex (fa) || iscomplex (fb) || ! isfinite (fa) || ! isfinite (fb))\n    error (\"Octave:fzero:bracket\", \"fzero: function must be real and finite at bracketing endpoints\");\n  endif\n\n  if (b < a)\n    ## Swap a and b so that a is lower bound and b is upper bound\n    u = a;\n    a = b;\n    b = u;\n\n    fu = fa;\n    fa = fb;\n    fb = fu;\n  endif\n\n  if (info == 0 && ! (sign (fa) * sign (fb) <= 0))\n    error (\"Octave:fzero:bracket\", \"fzero: not a valid initial bracketing\");\n  endif\n\n  if (displev == 1)\n    printf (\"\\nSearch for a zero in the interval [%g, %g]:\\n\", a, b);\n    disp (\" Fcn-count       x           f(x)        Procedure\");\n    fmt_str = \" %4d     %13.6g %13.6g    %s\\n\";\n  endif\n\n  ## Call user OutputFcn first time with 'init' state\n  if (have_outfcn)\n    optv.funccount = nfev;\n    optv.fval = [];\n    optv.iteration = 0;\n    if (outfcn ([], optv, \"init\"))\n      info = -1;\n    endif\n  endif\n\n  slope0 = (fb - fa) / (b - a);\n\n  if (fa == 0)\n    b = a;\n    fb = fa;\n  elseif (fb == 0)\n    a = b;\n    fa = fb;\n  endif\n\n  itype = 1;  # \"initial\" iter indicator\n\n  if (abs (fa) < abs (fb))\n    u = a; fu = fa;\n  else\n    u = b; fu = fb;\n  endif\n  if (displev == 1)\n    printf (fmt_str, nfev, u, fu, \"initial\");\n  endif\n\n  if (isa (x0, \"single\") || isa (fa, \"single\"))\n    macheps = eps (\"single\");\n  else\n    macheps = eps (\"double\");\n  endif\n\n  d = e = u;\n  fd = fe = fu;\n  mba = mu*(b - a);\n  while (niter < maxiter && nfev < maxfev)\n    switch (itype)\n      case 1\n        ## The initial test for termination.\n        if (info != 0)\n          break;  # interval search or OutputFcn caused termination\n        endif\n        if (b - a <= 2*(2 * abs (u) * macheps + tolx))\n          x = u; fval = fu;\n          info = 1;\n          break;\n        endif\n        if (abs (fa) <= 1e3*abs (fb) && abs (fb) <= 1e3*abs (fa))\n          ## Secant step.\n          c = u - (a - b) / (fa - fb) * fu;\n        else\n          ## Bisection step.\n          c = 0.5 * (a + b);\n        endif\n        d = u; fd = fu;\n        itype = 5;\n      case {2, 3}\n        ## l = numel (unique ([fa, fb, fd, fe]));\n        ## unique() code is heavyweight, replace with quick local version\n        uniq = sort ([fa, fb, fd, fe]);\n        l = 1 + sum (uniq(1:end-1) != uniq(2:end));\n        if (l == 4)\n          ## Inverse cubic interpolation.\n          q11 = (d - e) * fd / (fe - fd);\n          q21 = (b - d) * fb / (fd - fb);\n          q31 = (a - b) * fa / (fb - fa);\n          d21 = (b - d) * fd / (fd - fb);\n          d31 = (a - b) * fb / (fb - fa);\n          q22 = (d21 - q11) * fb / (fe - fb);\n          q32 = (d31 - q21) * fa / (fd - fa);\n          d32 = (d31 - q21) * fd / (fd - fa);\n          q33 = (d32 - q22) * fa / (fe - fa);\n          c = a + q31 + q32 + q33;\n        endif\n        if (l < 4 || sign (c - a) * sign (c - b) > 0)\n          ## Quadratic interpolation + Newton.\n          a0 = fa;\n          a1 = (fb - fa)/(b - a);\n          a2 = ((fd - fb)/(d - b) - a1) / (d - a);\n          ## Modification 1: this is simpler and does not seem to be worse.\n          c = a - a0/a1;\n          if (a2 != 0)\n            c = a - a0/a1;\n            for i = 1:itype\n              pc = a0 + (a1 + a2*(c - b))*(c - a);\n              pdc = a1 + a2*(2*c - a - b);\n              if (pdc == 0)\n                c = a - a0/a1;\n                break;\n              endif\n              c -= pc/pdc;\n            endfor\n          endif\n        endif\n        itype += 1;\n      case 4\n        ## Double secant step.\n        c = u - 2*(b - a)/(fb - fa)*fu;\n        ## Bisect if too far.\n        if (abs (c - u) > 0.5*(b - a))\n          c = 0.5 * (a + b);\n        endif\n        itype = 5;\n      case 5\n        ## Bisection step.\n        c = 0.5 * (a + b);\n        itype = 2;\n    endswitch\n\n    ## Don't let c come too close to a or b.\n    delta = 2*0.7*(2 * abs (u) * macheps + tolx);\n    if ((b - a) <= 2*delta)\n      c = 0.5 * (a + b);\n    else\n      c = max (a + delta, min (b - delta, c));\n    endif\n\n    ## Calculate new point.\n    x = c;\n    fval = fc = fcn (c);\n    niter += 1; nfev += 1;\n    if (displev == 1)\n      printf (fmt_str, nfev, x, fc, \"interpolation\");\n    endif\n\n    ## Modification 2: skip inverse cubic interpolation if\n    ## nonmonotonicity is detected.\n    if (sign (fc - fa) * sign (fc - fb) >= 0)\n      ## The new point broke monotonicity.\n      ## Disable inverse cubic.\n      fe = fc;\n    else\n      e = d; fe = fd;\n    endif\n\n    ## Bracketing.\n    if (sign (fa) * sign (fc) < 0)\n      d = b; fd = fb;\n      b = c; fb = fc;\n    elseif (sign (fb) * sign (fc) < 0)\n      d = a; fd = fa;\n      a = c; fa = fc;\n    elseif (fc == 0)\n      ## Found an exact zero, stop.\n      a = b = c; fa = fb = fc;\n      info = 1;\n      break;\n    else\n      ## This should never happen.\n      error (\"Octave:fzero:bracket\", \"fzero: zero point is not bracketed\");\n    endif\n\n    ## Call user OutputFcn at end of each iteration\n    if (have_outfcn)\n      optv.funccount = nfev;\n      optv.fval = fval;\n      optv.iteration = niter;\n      if (outfcn (x, optv, \"iter\"))\n        info = -1;\n        break;\n      endif\n    endif\n\n    if (abs (fa) < abs (fb))\n      u = a; fu = fa;\n    else\n      u = b; fu = fb;\n    endif\n    ## Check whether algorithm has converged at end of every iteration\n    if (b - a <= 2*(2 * abs (u) * macheps + tolx))\n      info = 1;\n      break;\n    endif\n\n    ## Skip bisection step if successful reduction.\n    if (itype == 5 && (b - a) <= mba)\n      itype = 2;\n    endif\n    if (itype == 2)\n      mba = mu * (b - a);\n    endif\n  endwhile\n\n  #############################################################\n  ## Post-algorithm operations\n\n  if (info == 1)\n    ## Solution converged.  Pick 'a' or 'b' based on smallest residual y-value.\n    if (abs (fa) < abs (fb))\n      x = a;\n      fval = fa;\n    else\n      x = b;\n      fval = fb;\n    endif\n\n    ## Check solution for a singularity by examining slope\n    if ((b - a) != 0\n        && abs ((fb - fa)/(b - a) / slope0) > max (1e6, 0.5/(macheps+tolx)))\n      info = -5;\n    endif\n  endif\n\n  ## Call user OutputFcn final time with 'done' state\n  if (have_outfcn)\n    optv.funccount = nfev;\n    optv.fval = fval;\n    optv.iteration = niter;\n    if (outfcn (x, optv, \"done\"))\n      info = -1;\n    endif\n  endif\n\n  if (displev != 0 || nargout == 4)\n    switch (info)\n      case 1\n        msg = \"Algorithm converged.\";\n      case 0\n        msg = \"Maximum number of iterations or function evaluations reached.\";\n      case -1\n        msg = \"Algorithm terminated by user OutputFcn.\";\n      case -5\n        msg = \"Algorithm seemingly converged to a singular point.\";\n      case -6\n        msg = \"No valid initial bracketing with a sign change found.\";\n    endswitch\n  endif\n\n  if (displev != 0)\n    if (info != 1)\n      disp ([\"\\n\" msg \"\\n\"]);\n    elseif (displev != 3)\n      disp ([\"\\n\" msg \"\\n\"]);\n    endif\n  endif\n\n  if (nargout == 4)\n    output.intervaliterations = nint;\n    output.iterations = niter;\n    output.funcCount = nfev;\n    output.algorithm = \"bisection, interpolation\";\n    output.message = msg;\n    output.bracketx = [a, b];\n    output.brackety = [fa, fb];\n  endif\n\nendfunction\n\n## A helper function that evaluates a function and checks for bad results.\nfunction fx = guarded_eval (fcn, x)\n\n  fx = fcn (x);\n  fx = fx(1);\n  if (! isreal (fx))\n    error (\"Octave:fzero:notreal\", \"fzero: non-real value encountered\");\n  elseif (isnan (fx))\n    error (\"Octave:fzero:isnan\", \"fzero: NaN value encountered\");\n  endif\n\nendfunction\n\n\n%!shared opt0\n%! opt0 = optimset (\"tolx\", 0);\n%!assert (fzero (@cos, [0, 3], opt0), pi/2, 10*eps)\n%!assert (fzero (@(x) x^(1/3) - 1e-8, [0,1], opt0), 1e-24, 1e-22*eps)\n\n%!assert <*54445> (fzero (@ (x) x, 0), 0)\n%!assert <*54445> (fzero (@ (x) x + 1, 0), -1)\n\n## Test exit codes\n%!shared optsilent\n%! optsilent = optimset ('Display', 'none');\n%!test\n%! ## Code 1 : Algorithm converged\n%! [~, ~, info] = fzero (@(x) x.^2 - 4, [1, 3], optsilent);\n%! assert (info, 1);\n\n%!test\n%! ## Code 0 : Maximum iterations exceeded\n%! opts = optimset (optsilent, 'MaxIter', 1);\n%! [~, ~, info] = fzero (@sin, [-2, 1], opts);\n%! assert (info, 0);\n%! clear opts\n%! opts = optimset (optsilent, 'MaxFunEvals', 1);\n%! [~, ~, info] = fzero (@sin, [-2, 1], opts);\n%! assert (info, 0);\n\n%!function stop = terminate_outputfcn1 (x, optv, state)\n%!  stop = true;\n%!endfunction\n%!function stop = terminate_outputfcn2 (x, optv, state)\n%!  stop = false;\n%!  if (strcmp (state, 'iter'))\n%!    stop = true;\n%!  endif\n%!endfunction\n%!test\n%! ## Code -1 : Algorithm terminated by OutputFcn in 'init' state\n%! opts = optimset (optsilent, 'OutputFcn', @terminate_outputfcn1);\n%! [x, fval, info, output] = fzero (@sin, [-2, 1], opts);\n%! assert (info, -1);\n%! assert (x, NaN);\n%! assert (fval, NaN);\n%! assert (output.iterations, 0);\n%!test\n%! ## Code -1 : Algorithm terminated by OutputFcn in 'iter' state\n%! opts = optimset (optsilent, 'OutputFcn', @terminate_outputfcn2);\n%! [x, fval, info, output] = fzero (@sin, [-2, 1], opts);\n%! assert (info, -1);\n%! assert (output.iterations, 1);\n\n%!test\n%! ## Code -5 : Algorithm converged to a singular point\n%! [~, ~, info] = fzero (@(x) 1./x, [-1, 1], optsilent);\n%! assert (info, -5);\n\n%!test\n%! ## Code -6 : No valid initial bracking found\n%! [~, ~, info] = fzero (@(x) x.^2 + 1, 0, optsilent);\n%! assert (info, -6);\n\n## Test input validation\n%!error <Invalid call> fzero ()\n%!error <Invalid call> fzero (@sin)\n%!error <function must be real> fzero (@(x) i*x, [-1, 0])\n%!error <function must be real> fzero (@(x) i*x, [0, 1])\n%!error <function must be .* finite> fzero (@(x) 1./x - 1, [0, 2])\n%!error <function must be .* finite> fzero (@(x) 1./x - 1, [-2, 0])\n%!error <not a valid initial bracketing> fzero (@sin, [1, 2])\n"
  },
  {
    "path": "scripts/optimization/glpk.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{xopt}, @var{fmin}, @var{errnum}, @var{extra}] =} glpk (@var{c}, @var{A}, @var{b}, @var{lb}, @var{ub}, @var{ctype}, @var{vartype}, @var{sense}, @var{param})\n## Solve a linear program using the GNU @sc{glpk} library.\n##\n## Given three arguments, @code{glpk} solves the following standard LP:\n## @tex\n## $$\n##   \\min_x C^T x\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## min C'*x\n## @end example\n##\n## @end ifnottex\n## subject to\n## @tex\n## $$\n##   Ax = b \\qquad x \\geq 0\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## A*x  = b\n##   x >= 0\n## @end group\n## @end example\n##\n## @end ifnottex\n## but may also solve problems of the form\n## @tex\n## $$\n##   [ \\min_x | \\max_x ] C^T x\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## [ min | max ] C'*x\n## @end example\n##\n## @end ifnottex\n## subject to\n## @tex\n## $$\n##  Ax [ = | \\leq | \\geq ] b \\qquad LB \\leq x \\leq UB\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## A*x [ \"=\" | \"<=\" | \">=\" ] b\n##   x >= LB\n##   x <= UB\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## Input arguments:\n##\n## @table @var\n## @item c\n## A column array containing the objective function coefficients.\n##\n## @item A\n## A matrix containing the constraints coefficients.\n##\n## @item b\n## A column array containing the right-hand side value for each constraint in\n## the constraint matrix.\n##\n## @item lb\n## An array containing the lower bound on each of the variables.  If @var{lb}\n## is not supplied, the default lower bound for the variables is zero.\n##\n## @item ub\n## An array containing the upper bound on each of the variables.  If @var{ub}\n## is not supplied, the default upper bound is assumed to be infinite.\n##\n## @item ctype\n## An array of characters containing the sense of each constraint in the\n## constraint matrix.  Each element of the array may be one of the following\n## values\n##\n## @table @asis\n## @item @qcode{\"F\"}\n## A free (unbounded) constraint (the constraint is ignored).\n##\n## @item @qcode{\"U\"}\n## An inequality constraint with an upper bound (@code{A(i,:)*x <= b(i)}).\n##\n## @item @qcode{\"S\"}\n## An equality constraint (@code{A(i,:)*x = b(i)}).\n##\n## @item @qcode{\"L\"}\n## An inequality with a lower bound (@code{A(i,:)*x >= b(i)}).\n##\n## @item @qcode{\"D\"}\n## An inequality constraint with both upper and lower bounds\n## (@code{A(i,:)*x >= -b(i)}) @emph{and} (@code{A(i,:)*x <= b(i)}).\n## @end table\n##\n## @item vartype\n## A column array containing the types of the variables.\n##\n## @table @asis\n## @item @qcode{\"C\"}\n## A continuous variable.\n##\n## @item @qcode{\"I\"}\n## An integer variable.\n## @end table\n##\n## @item sense\n## If @var{sense} is 1, the problem is a minimization.  If @var{sense} is -1,\n## the problem is a maximization.  The default value is 1.\n##\n## @item param\n## A structure containing the following parameters used to define the\n## behavior of solver.  Missing elements in the structure take on default\n## values, so you only need to set the elements that you wish to change from\n## the default.\n##\n## Integer parameters:\n##\n## @table @code\n## @item msglev (default: 1)\n## Level of messages output by solver routines:\n##\n## @table @asis\n## @item 0 (@w{@code{GLP_MSG_OFF}})\n## No output.\n##\n## @item 1 (@w{@code{GLP_MSG_ERR}})\n## Error and warning messages only.\n##\n## @item 2 (@w{@code{GLP_MSG_ON}})\n## Normal output.\n##\n## @item 3 (@w{@code{GLP_MSG_ALL}})\n## Full output (includes informational messages).\n## @end table\n##\n## @item scale (default: 16)\n## Scaling option.  The values can be combined with the bitwise OR operator and\n## may be the following:\n##\n## @table @asis\n## @item 1 (@w{@code{GLP_SF_GM}})\n## Geometric mean scaling.\n##\n## @item 16 (@w{@code{GLP_SF_EQ}})\n## Equilibration scaling.\n##\n## @item 32 (@w{@code{GLP_SF_2N}})\n## Round scale factors to power of two.\n##\n## @item 64 (@w{@code{GLP_SF_SKIP}})\n## Skip if problem is well scaled.\n## @end table\n##\n## Alternatively, a value of 128 (@w{@env{GLP_SF_AUTO}}) may be also\n## specified, in which case the routine chooses the scaling options\n## automatically.\n##\n## @item dual (default: 1)\n## Simplex method option:\n##\n## @table @asis\n## @item 1 (@w{@code{GLP_PRIMAL}})\n## Use two-phase primal simplex.\n##\n## @item 2 (@w{@code{GLP_DUALP}})\n## Use two-phase dual simplex, and if it fails, switch to the primal simplex.\n##\n## @item 3 (@w{@code{GLP_DUAL}})\n## Use two-phase dual simplex.\n## @end table\n##\n## @item price (default: 34)\n## Pricing option (for both primal and dual simplex):\n##\n## @table @asis\n## @item 17 (@w{@code{GLP_PT_STD}})\n## Textbook pricing.\n##\n## @item 34 (@w{@code{GLP_PT_PSE}})\n## Steepest edge pricing.\n## @end table\n##\n## @item itlim (default: intmax)\n## Simplex iterations limit.  It is decreased by one each time when one simplex\n## iteration has been performed, and reaching zero value signals the solver to\n## stop the search.\n##\n## @item outfrq (default: 200)\n## Output frequency, in iterations.  This parameter specifies how frequently\n## the solver sends information about the solution to the standard output.\n##\n## @item branch (default: 4)\n## Branching technique option (for MIP only):\n##\n## @table @asis\n## @item 1 (@w{@code{GLP_BR_FFV}})\n## First fractional variable.\n##\n## @item 2 (@w{@code{GLP_BR_LFV}})\n## Last fractional variable.\n##\n## @item 3 (@w{@code{GLP_BR_MFV}})\n## Most fractional variable.\n##\n## @item 4 (@w{@code{GLP_BR_DTH}})\n## Heuristic by @nospell{Driebeck and Tomlin}.\n##\n## @item 5 (@w{@code{GLP_BR_PCH}})\n## Hybrid @nospell{pseudocost} heuristic.\n## @end table\n##\n## @item btrack (default: 4)\n## Backtracking technique option (for MIP only):\n##\n## @table @asis\n## @item 1 (@w{@code{GLP_BT_DFS}})\n## Depth first search.\n##\n## @item 2 (@w{@code{GLP_BT_BFS}})\n## Breadth first search.\n##\n## @item 3 (@w{@code{GLP_BT_BLB}})\n## Best local bound.\n##\n## @item 4 (@w{@code{GLP_BT_BPH}})\n## Best projection heuristic.\n## @end table\n##\n## @item presol (default: 1)\n## If this flag is set, the simplex solver uses the built-in LP presolver.\n## Otherwise the LP presolver is not used.\n##\n## @item lpsolver (default: 1)\n## Select which solver to use.  If the problem is a MIP problem this flag\n## will be ignored.\n##\n## @table @asis\n## @item 1\n## Revised simplex method.\n##\n## @item 2\n## Interior point method.\n## @end table\n##\n## @item rtest (default: 34)\n## Ratio test technique:\n##\n## @table @asis\n## @item 17 (@w{@code{GLP_RT_STD}})\n## Standard (\"textbook\").\n##\n## @item 34 (@w{@code{GLP_RT_HAR}})\n## Harris' two-pass ratio test.\n## @end table\n##\n## @item tmlim (default: intmax)\n## Searching time limit, in milliseconds.\n##\n## @item outdly (default: 0)\n## Output delay, in seconds.  This parameter specifies how long the solver\n## should delay sending information about the solution to the standard output.\n##\n## @item save (default: 0)\n## If this parameter is nonzero, save a copy of the problem in @nospell{CPLEX}\n## LP format to the file @file{\"outpb.lp\"}.  There is currently no way to\n## change the name of the output file.\n## @end table\n##\n## Real parameters:\n##\n## @table @code\n## @item tolbnd (default: 1e-7)\n## Relative tolerance used to check if the current basic solution is primal\n## feasible.  It is not recommended that you change this parameter unless you\n## have a detailed understanding of its purpose.\n##\n## @item toldj (default: 1e-7)\n## Absolute tolerance used to check if the current basic solution is dual\n## feasible.  It is not recommended that you change this parameter unless you\n## have a detailed understanding of its purpose.\n##\n## @item tolpiv (default: 1e-9)\n## Relative tolerance used to choose eligible pivotal elements of the simplex\n## table.  It is not recommended that you change this parameter unless you have\n## a detailed understanding of its purpose.\n##\n## @item objll (default: -DBL_MAX)\n## Lower limit of the objective function.  If the objective function reaches\n## this limit and continues decreasing, the solver stops the search.  This\n## parameter is used in the dual simplex method only.\n##\n## @item objul (default: +DBL_MAX)\n## Upper limit of the objective function.  If the objective function reaches\n## this limit and continues increasing, the solver stops the search.  This\n## parameter is used in the dual simplex only.\n##\n## @item tolint (default: 1e-5)\n## Relative tolerance used to check if the current basic solution is integer\n## feasible.  It is not recommended that you change this parameter unless you\n## have a detailed understanding of its purpose.\n##\n## @item tolobj (default: 1e-7)\n## Relative tolerance used to check if the value of the objective function is\n## not better than in the best known integer feasible solution.  It is not\n## recommended that you change this parameter unless you have a detailed\n## understanding of its purpose.\n## @end table\n## @end table\n##\n## Output values:\n##\n## @table @var\n## @item xopt\n## The optimizer (the value of the decision variables at the optimum).\n##\n## @item fopt\n## The optimum value of the objective function.\n##\n## @item errnum\n## Error code.\n##\n## @table @asis\n## @item 0\n## No error.\n##\n## @item 1 (@w{@code{GLP_EBADB}})\n## Invalid basis.\n##\n## @item 2 (@w{@code{GLP_ESING}})\n## Singular matrix.\n##\n## @item 3 (@w{@code{GLP_ECOND}})\n## Ill-conditioned matrix.\n##\n## @item 4 (@w{@code{GLP_EBOUND}})\n## Invalid bounds.\n##\n## @item 5 (@w{@code{GLP_EFAIL}})\n## Solver failed.\n##\n## @item 6 (@w{@code{GLP_EOBJLL}})\n## Objective function lower limit reached.\n##\n## @item 7 (@w{@code{GLP_EOBJUL}})\n## Objective function upper limit reached.\n##\n## @item 8 (@w{@code{GLP_EITLIM}})\n## Iterations limit exhausted.\n##\n## @item 9 (@w{@code{GLP_ETMLIM}})\n## Time limit exhausted.\n##\n## @item 10 (@w{@code{GLP_ENOPFS}})\n## No primal feasible solution.\n##\n## @item 11 (@w{@code{GLP_ENODFS}})\n## No dual feasible solution.\n##\n## @item 12 (@w{@code{GLP_EROOT}})\n## Root LP optimum not provided.\n##\n## @item 13 (@w{@code{GLP_ESTOP}})\n## Search terminated by application.\n##\n## @item 14 (@w{@code{GLP_EMIPGAP}})\n## Relative MIP gap tolerance reached.\n##\n## @item 15 (@w{@code{GLP_ENOFEAS}})\n## No primal/dual feasible solution.\n##\n## @item 16 (@w{@code{GLP_ENOCVG}})\n## No convergence.\n##\n## @item 17 (@w{@code{GLP_EINSTAB}})\n## Numerical instability.\n##\n## @item 18 (@w{@code{GLP_EDATA}})\n## Invalid data.\n##\n## @item 19 (@w{@code{GLP_ERANGE}})\n## Result out of range.\n## @end table\n##\n## @item extra\n## A data structure containing the following fields:\n##\n## @table @code\n## @item lambda\n## Dual variables.\n##\n## @item redcosts\n## Reduced Costs.\n##\n## @item time\n## Time (in seconds) used for solving LP/MIP problem.\n##\n## @item status\n## Status of the optimization.\n##\n## @table @asis\n## @item 1 (@w{@code{GLP_UNDEF}})\n## Solution status is undefined.\n##\n## @item 2 (@w{@code{GLP_FEAS}})\n## Solution is feasible.\n##\n## @item 3 (@w{@code{GLP_INFEAS}})\n## Solution is infeasible.\n##\n## @item 4 (@w{@code{GLP_NOFEAS}})\n## Problem has no feasible solution.\n##\n## @item 5 (@w{@code{GLP_OPT}})\n## Solution is optimal.\n##\n## @item 6 (@w{@code{GLP_UNBND}})\n## Problem has no unbounded solution.\n## @end table\n## @end table\n## @end table\n##\n## Example:\n##\n## @example\n## @group\n## c = [10, 6, 4]';\n## A = [ 1, 1, 1;\n##      10, 4, 5;\n##       2, 2, 6];\n## b = [100, 600, 300]';\n## lb = [0, 0, 0]';\n## ub = [];\n## ctype = \"UUU\";\n## vartype = \"CCC\";\n## s = -1;\n##\n## param.msglev = 1;\n## param.itlim = 100;\n##\n## [xmin, fmin, status, extra] = ...\n##    glpk (c, A, b, lb, ub, ctype, vartype, s, param);\n## @end group\n## @end example\n## @end deftypefn\n\nfunction [xopt, fmin, errnum, extra] = glpk (c, A, b, lb, ub, ctype, vartype, sense, param)\n\n  ## If there is no input output the version and syntax\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n   if (! isvector (c) || iscomplex (c) || ischar (c) || any (isinf (c))\n       || any (isnan (c)))\n     error (\"glpk: C must be a real vector with finite values\");\n  endif\n  nx = length (c);\n  ## Force column vector.\n  c = c(:);\n\n  ## 2) Matrix constraint\n\n  if (isempty (A))\n    error (\"glpk: A cannot be an empty matrix\");\n  endif\n  if (! isreal (A))\n    error (\"glpk: A must be real valued, not %s\", typeinfo (A));\n  endif\n  if (any (isinf (A(:))) || any (isnan (A(:))))\n    error (\"glpk: The values in A must be finite\");\n  endif\n\n  [nc, nxa] = size (A);\n  if (nxa != nx)\n    error (\"glpk: A must be %d-by-%d, not %d-by-%d\",\n           nc, nx, rows (A), columns (A));\n  endif\n\n  ## 3) RHS\n\n  if (isempty (b))\n    error (\"glpk: B cannot be an empty vector\");\n  endif\n  if (! isreal (b) || length (b) != nc)\n    error (\"glpk: B must be a real-valued %d-by-1 vector\", nc);\n  endif\n  if (any (! isfinite (b(:))))\n    error (\"glpk: The values in B must be finite\");\n  endif\n\n  ## 4) Vector with the lower bound of each variable\n\n  if (nargin > 3)\n    if (isempty (lb))\n      lb = zeros (nx, 1);\n    elseif (! isreal (lb) || all (size (lb) > 1) || length (lb) != nx\n            || any (isnan (lb)))\n      error (\"glpk: LB must be a real-valued %d-by-1 column vector\", nx);\n    endif\n  else\n    lb = zeros (nx, 1);\n  endif\n\n  ## 5) Vector with the upper bound of each variable\n\n  if (nargin > 4)\n    if (isempty (ub))\n      ub = Inf (nx, 1);\n    elseif (! isreal (ub) || all (size (ub) > 1) || length (ub) != nx\n            || any (isnan (ub)))\n      error (\"glpk: UB must be a real-valued %d-by-1 column vector\", nx);\n    endif\n  else\n    ub = Inf (nx, 1);\n  endif\n\n  ## 6) Sense of each constraint\n\n  if (nargin > 5)\n    if (isempty (ctype))\n      ctype = repmat (\"S\", nc, 1);\n    elseif (! ischar (ctype) || all (size (ctype) > 1) || length (ctype) != nc)\n      error (\"glpk: CTYPE must be a char vector of length %d\", nc);\n    elseif (! all (ctype == \"F\" | ctype == \"U\" | ctype == \"S\"\n                   | ctype == \"L\" | ctype == \"D\"))\n      error (\"glpk: CTYPE must contain only F, U, S, L, or D\");\n    endif\n  else\n    ctype = repmat (\"S\", nc, 1);\n  endif\n\n  ## 7) Vector with the type of variables\n\n  if (nargin > 6)\n    if (isempty (vartype))\n      vartype = repmat (\"C\", nx, 1);\n    elseif (! ischar (vartype) || all (size (vartype) > 1)\n            || length (vartype) != nx)\n      error (\"glpk: VARTYPE must be a char vector of length %d\", nx);\n    elseif (! all (vartype == \"C\" | vartype == \"I\"))\n      error (\"glpk: VARTYPE must contain only C or I\");\n    endif\n  else\n    ## As default we consider continuous vars\n    vartype = repmat (\"C\", nx, 1);\n  endif\n\n  ## 8) Sense of optimization\n\n  if (nargin > 7)\n    if (isempty (sense))\n      sense = 1;\n    elseif (ischar (sense) || all (size (sense) > 1) || ! isreal (sense)\n            || any (! isfinite (sense)))\n      error (\"glpk: SENSE must be an integer value\");\n    elseif (sense >= 0)\n      sense = 1;\n    else\n      sense = -1;\n    endif\n  else\n    sense = 1;\n  endif\n\n  ## 9) Parameters vector\n\n  if (nargin > 8)\n    if (! isstruct (param))\n      error (\"glpk: PARAM must be a structure\");\n    endif\n  else\n    param = struct ();\n  endif\n\n  [xopt, fmin, errnum, extra] = ...\n    __glpk__ (c, A, b, lb, ub, ctype, vartype, sense, param);\n\nendfunction\n\n\n%!testif HAVE_GLPK\n%! sense = -1;\n%! c = [10, 6, 4]';\n%! A = [1, 1, 1; 10, 4, 5; 2, 2, 6];\n%! b = [100, 600, 300]';\n%! ctype = ['U', 'U', 'U']';\n%! lb = [0, 0, 0]';\n%! ub = [];\n%! vartype = ['C', 'C', 'C']';\n%! param.msglev = 0;\n%! param.lpsolver = 1;\n%! [xmin, fmin, errnum, extra] = glpk (c, A, b, lb, ub, ctype, vartype, ...\n%!   sense, param);\n%! assert (fmin, c' * xmin);\n%! for i = 1:3\n%!   assert (A(i,:) * xmin <= b(i));\n%! endfor\n\n%!testif HAVE_GLPK\n%! sense = 1;\n%! c = [-1, -1]';\n%! A = [-2, 5; 2, -2];\n%! b = [5, 1]';\n%! ctype = ['U', 'U']';\n%! lb = [0, 0]';\n%! ub = [];\n%! vartype = ['I', 'I']';\n%! param.msglev = 0;\n%! [xmin, fmin, errnum, extra] = glpk (c, A, b, lb, ub, ctype, vartype, ...\n%!   sense, param);\n%! assert (fmin, c' * xmin);\n%! for i = 1:2\n%!   assert (A(i,:) * xmin <= b(i));\n%! endfor\n\n%!testif HAVE_GLPK\n%! sense = 1;\n%! c = [-1, -1]';\n%! A = [1, 0; 0, 1];\n%! b = [1, 1]';\n%! ctype = ['D', 'D']';\n%! lb = [-1, -1]';\n%! ub = [];\n%! vartype = ['I', 'I']';\n%! param.msglev = 0;\n%! [xmin, fmin, errnum, extra] = glpk (c, A, b, lb, ub, ctype, vartype, ...\n%!   sense, param);\n%! assert (fmin, c' * xmin);\n%! for i = 1:2\n%!   assert (A(i,:) * xmin <= b(i));\n%! endfor\n\n%!testif HAVE_GLPK\n%! sense = 1;\n%! c = [0, 0, 0, -1, -1]';\n%! A = [-2, 0, 0, 1, 0; 0, 1, 0, 0, 2; 0, 0, 1, 3, 2];\n%! b = [4, 12, 18]';\n%! ctype = ['S', 'S', 'S']';\n%! lb = [0, 0, 0, 0, 0]';\n%! ub = [];\n%! vartype = ['C', 'C', 'C', 'C', 'C']';\n%! param.msglev = 0;\n%! [xmin, fmin, errnum, extra] = glpk (c, A, b, lb, ub, ctype, vartype, ...\n%!   sense, param);\n%! assert (fmin, c' * xmin);\n%! assert (A * xmin, b);\n\n%!error <C .* finite values> glpk (NaN, 2, 3)\n%!error <A must be finite> glpk (1, NaN, 3)\n%!error <B must be finite> glpk (1, 2, NaN)\n%!error <LB must be a real-valued> glpk (1, 2, 3, NaN)\n%!error <UB must be a real-valued> glpk (1, 2, 3, 4, NaN)\n%!error <SENSE must be .* integer> glpk (1, 2, 3, 4, 5, \"F\", \"C\", NaN)\n"
  },
  {
    "path": "scripts/optimization/humps.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} humps (@var{x})\n## @deftypefnx {} {[@var{x}, @var{y}] =} humps (@var{x})\n## Evaluate a function with multiple minima, maxima, and zero crossings.\n##\n## The output @var{y} is the evaluation of the rational function:\n## @tex\n## $$y = -{ {1200x^4 - 2880x^3 + 2036x^2 - 348x - 88} \\over {200x^4 - 480x^3 + 406x^2 - 138x + 17} }$$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##         1200*@var{x}^4 - 2880*@var{x}^3 + 2036*@var{x}^2 - 348*@var{x} - 88\n##  @var{y} = - ---------------------------------------------\n##          200*@var{x}^4 - 480*@var{x}^3 + 406*@var{x}^2 - 138*@var{x} + 17\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @var{x} may be a scalar, vector or array.  If @var{x} is omitted, the\n## default range [0:0.05:1] is used.\n##\n## When called with two output arguments, [@var{x}, @var{y}], @var{x} will\n## contain the input values, and @var{y} will contain the output from\n## @code{humps}.\n##\n## Programming Notes: @code{humps} has two local maxima located near @var{x} =\n## 0.300 and 0.893, a local minimum near @var{x} = 0.637, and zeros near\n## @var{x} = -0.132 and 1.300.  @code{humps} is a useful function for testing\n## algorithms which find zeros or local minima and maxima.\n##\n## Try @code{demo humps} to see a plot of the @code{humps} function.\n## @seealso{fzero, fminbnd, fminunc, fminsearch}\n## @end deftypefn\n\nfunction [x, y] = humps (x = [0:0.05:1])\n\n  y = - 4*( 300*x.^4 - 720*x.^3 + 509*x.^2 - 87*x - 22) ./ ...\n          ((10*x.^2 - 6*x + 1).*(20*x.^2 - 36*x + 17));\n\n  if (nargout <= 1)\n    x = y;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! fplot (@humps, [0, 2]);\n%! title (\"humps() function\");\n\n## value checks\n%!assert (humps (0), 88/17, 10*eps)\n%!assert (humps (1), 16, 10*eps)\n%!assert (humps (-1), -6376/1241, 10*eps)\n%!assert (humps (), [88/17, 16106/1769, 263/17, 82802/3133, 2432/53, ...\n%!   2818/37, 193/2, 10538/137, 1376/29, 36434/1261, 19, 5258/377,  ...\n%!   152/13, 24562/2173, 421/34, 250/17, 232/13, 1762/85, 803/37,   ...\n%!   58354/2941, 16], 1000*eps)\n\n## vector checks\n%!assert (humps ([0, 1]), [88/17, 16], 10*eps)\n%!assert (humps ([0, 1]'), [88/17, 16]', 10*eps)\n%!assert (humps ([0, 1; 1, 0]'), [88/17, 16; 16, 88/17]', 10*eps)\n\n## array checks\n%!assert (humps (repmat (eye (2), 1, 1, 2)),\n%!        repmat ([16, 88/17; 88/17, 16], 1, 1, 2), 10*eps)\n\n## other checks\n%!assert (humps (NaN), NaN)\n%!assert (humps ([]), [])\n\n## Test input validation\n%!error humps (1,3)\n"
  },
  {
    "path": "scripts/optimization/lsqnonneg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} lsqnonneg (@var{c}, @var{d})\n## @deftypefnx {} {@var{x} =} lsqnonneg (@var{c}, @var{d}, @var{x0})\n## @deftypefnx {} {@var{x} =} lsqnonneg (@var{c}, @var{d}, @var{x0}, @var{options})\n## @deftypefnx {} {[@var{x}, @var{resnorm}] =} lsqnonneg (@dots{})\n## @deftypefnx {} {[@var{x}, @var{resnorm}, @var{residual}] =} lsqnonneg (@dots{})\n## @deftypefnx {} {[@var{x}, @var{resnorm}, @var{residual}, @var{exitflag}] =} lsqnonneg (@dots{})\n## @deftypefnx {} {[@var{x}, @var{resnorm}, @var{residual}, @var{exitflag}, @var{output}] =} lsqnonneg (@dots{})\n## @deftypefnx {} {[@var{x}, @var{resnorm}, @var{residual}, @var{exitflag}, @var{output}, @var{lambda}] =} lsqnonneg (@dots{})\n##\n## Minimize @code{norm (@var{c}*@var{x} - @var{d})} subject to\n## @code{@var{x} >= 0}.\n##\n## @var{c} and @var{d} must be real matrices.\n##\n## @var{x0} is an optional initial guess for the solution @var{x}.\n##\n## @var{options} is an options structure to change the behavior of the\n## algorithm (@pxref{XREFoptimset,,@code{optimset}}).  @code{lsqnonneg}\n## recognizes these options: @qcode{\"MaxIter\"}, @qcode{\"TolX\"}.\n##\n## Outputs:\n##\n## @table @var\n## @item resnorm\n## The squared 2-norm of the residual: @code{norm (@var{c}*@var{x}-@var{d})^2}\n##\n## @item residual\n## The residual: @code{@var{d}-@var{c}*@var{x}}\n##\n## @item exitflag\n## An indicator of convergence.  0 indicates that the iteration count was\n## exceeded, and therefore convergence was not reached; >0 indicates that the\n## algorithm converged.  (The algorithm is stable and will converge given\n## enough iterations.)\n##\n## @item output\n## A structure with two fields:\n##\n## @itemize @bullet\n## @item @qcode{\"algorithm\"}: The algorithm used (@qcode{\"nnls\"})\n##\n## @item @qcode{\"iterations\"}: The number of iterations taken.\n## @end itemize\n##\n## @item lambda\n## Lagrange multipliers.  If these are nonzero, the corresponding @var{x}\n## values should be zero, indicating the solution is pressed up against a\n## coordinate plane.  The magnitude indicates how much the residual would\n## improve if the @code{@var{x} >= 0} constraints were relaxed in that\n## direction.\n##\n## @end table\n## @seealso{pqpnonneg, lscov, optimset}\n## @end deftypefn\n\n## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.\n## PKG_ADD: [~] = __all_opts__ (\"lsqnonneg\");\n\n## This is implemented from Lawson and Hanson's 1973 algorithm on page 161 of\n## Solving Least Squares Problems.\n\nfunction [x, resnorm, residual, exitflag, output, lambda] = lsqnonneg (c, d, x0 = [], options = struct ())\n\n  ## Special case: called to find default optimization options\n  if (nargin == 1 && ischar (c) && strcmp (c, \"defaults\"))\n    x = struct (\"MaxIter\", 1e5);\n    return;\n  endif\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (c) && ismatrix (c)) || ! (isnumeric (d) && ismatrix (d)))\n    error (\"lsqnonneg: C and D must be numeric matrices\");\n  endif\n\n  if (! isstruct (options))\n    error (\"lsqnonneg: OPTIONS must be a struct\");\n  endif\n\n  ## Lawson-Hanson Step 1 (LH1): initialize the variables.\n  m = rows (c);\n  n = columns (c);\n  if (isempty (x0))\n    ## Initial guess is all zeros.\n    x = zeros (n, 1);\n  else\n    ## ensure nonnegative guess.\n    x = max (x0, 0);\n  endif\n\n  useqr = (m >= n);\n  max_iter = optimget (options, \"MaxIter\", 1e5);\n\n  ## Initialize P, according to zero pattern of x.\n  p = find (x > 0).';\n  if (useqr)\n    ## Initialize the QR factorization, economized form.\n    [q, r] = qr (c(:,p), 0);\n  endif\n\n  iter = 0;\n\n  ## LH3: test for completion.\n  while (iter < max_iter)\n    while (iter < max_iter)\n      iter += 1;\n\n      ## LH6: compute the positive matrix and find the min norm solution\n      ## of the positive problem.\n      if (useqr)\n        xtmp = r \\ q'*d;\n      else\n        xtmp = c(:,p) \\ d;\n      endif\n      idx = find (xtmp < 0);\n\n      if (isempty (idx))\n        ## LH7: tmp solution found, iterate.\n        x(:) = 0;\n        x(p) = xtmp;\n        break;\n      else\n        ## LH8, LH9: find the scaling factor.\n        pidx = p(idx);\n        sf = x(pidx) ./ (x(pidx) - xtmp(idx));\n        alpha = min (sf);\n        ## LH10: adjust X.\n        xx = zeros (n, 1);\n        xx(p) = xtmp;\n        x += alpha*(xx - x);\n        ## LH11: move from P to Z all X == 0.\n        ## This corresponds to those indices where minimum of sf is attained.\n        idx = idx(sf == alpha);\n        p(idx) = [];\n        if (useqr)\n          ## update the QR factorization.\n          [q, r] = qrdelete (q, r, idx);\n        endif\n      endif\n    endwhile\n\n    ## compute the gradient.\n    w = c'*(d - c*x);\n    w(p) = [];\n    tolx = optimget (options, \"TolX\", 10*eps*norm (c, 1)*length (c));\n    if (! any (w > tolx))\n      if (useqr)\n        ## verify the solution achieved using qr updating.\n        ## in the best case, this should only take a single step.\n        useqr = false;\n        continue;\n      else\n        ## we're finished.\n        break;\n      endif\n    endif\n\n    ## find the maximum gradient.\n    idx = find (w == max (w));\n    if (numel (idx) > 1)\n      warning (\"lsqnonneg:nonunique\",\n               \"a non-unique solution may be returned due to equal gradients\");\n      idx = idx(1);\n    endif\n    ## move the index from Z to P.  Keep P sorted.\n    z = [1:n]; z(p) = [];\n    zidx = z(idx);\n    jdx = 1 + lookup (p, zidx);\n    p = [p(1:jdx-1), zidx, p(jdx:end)];\n    if (useqr)\n      ## insert the column into the QR factorization.\n      [q, r] = qrinsert (q, r, jdx, c(:,zidx));\n    endif\n\n  endwhile\n  ## LH12: complete.\n\n  ## Generate the additional output arguments.\n  if (nargout > 1)\n    resnorm = norm (c*x - d) ^ 2;\n  endif\n  if (nargout > 2)\n    residual = d - c*x;\n  endif\n  if (nargout > 3)\n    if (iter >= max_iter)\n      exitflag = 0;\n    else\n      exitflag = iter;\n    endif\n  endif\n  if (nargout > 4)\n    output = struct (\"algorithm\", \"nnls\", \"iterations\", iter);\n  endif\n  if (nargout > 5)\n    lambda = zeros (size (x));\n    lambda (setdiff (1:numel (x), p)) = w;\n  endif\n\nendfunction\n\n\n%!test\n%! C = [1 0;0 1;2 1];\n%! d = [1;3;-2];\n%! assert (lsqnonneg (C, d), [0;0.5], 100*eps);\n\n%!test\n%! C = [0.0372 0.2869;0.6861 0.7071;0.6233 0.6245;0.6344 0.6170];\n%! d = [0.8587;0.1781;0.0747;0.8405];\n%! xnew = [0;0.6929];\n%! assert (lsqnonneg (C, d), xnew, 0.0001);\n\n## Test Lagrange multiplier duality: x .* lambda == 0\n\n%!test\n%! [x, resn, resid, ~, ~, lambda] = lsqnonneg ([1 0; 0 1; 2 1], [1 1 3]');\n%! assert (x, [1 1]', 10*eps);\n%! assert (resn, 0, 10*eps);\n%! assert (resid, [0 0 0]', 10*eps);\n%! assert (lambda, [0 0]', 10*eps);\n%! assert (x .* lambda, [0 0]');\n\n%!test\n%! [x, resn, resid, ~, ~, lambda] = lsqnonneg ([1 0; 0 1; 2 1], [1 -1 1]');\n%! assert (x, [0.6 0]', 10*eps);\n%! assert (resn, 1.2, 10*eps);\n%! assert (resid, [0.4 -1 -0.2]', 10*eps);\n%! assert (lambda, [0 -1.2]', 10*eps);\n%! assert (x .* lambda, [0 0]');\n\n%!test\n%! [x, resn, resid, ~, ~, lambda] = lsqnonneg ([1 0; 0 1; 2 1], [-1 1 -1]');\n%! assert (x, [0 0]', 10*eps);\n%! assert (resn, 3, 10*eps);\n%! assert (resid, [-1 1 -1]', 10*eps);\n%! assert (lambda, [-3 0]', 10*eps);\n%! assert (x .* lambda, [0 0]');\n\n%!test\n%! [x, resn, resid, ~, ~, lambda] = lsqnonneg ([1 0; 0 1; 2 1], [-1 -1 -3]');\n%! assert (x, [0 0]', 10*eps);\n%! assert (resn, 11, 20*eps);\n%! assert (resid, [-1 -1 -3]', 10*eps);\n%! assert (lambda, [-7 -4]', 10*eps);\n%! assert (x .* lambda, [0 0]');\n\n## Test input validation\n%!error <Invalid call> lsqnonneg ()\n%!error <Invalid call> lsqnonneg (1)\n%!error <C .* must be numeric matrices> lsqnonneg ({1},2)\n%!error <C .* must be numeric matrices> lsqnonneg (ones (2,2,2),2)\n%!error <D must be numeric matrices> lsqnonneg (1,{2})\n%!error <D must be numeric matrices> lsqnonneg (1, ones (2,2,2))\n%!error <OPTIONS must be a struct> lsqnonneg (1, 2, [], 3)\n"
  },
  {
    "path": "scripts/optimization/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__fdjac__.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/__all_opts__.m \\\n  %reldir%/fminbnd.m \\\n  %reldir%/fminsearch.m \\\n  %reldir%/fminunc.m \\\n  %reldir%/fsolve.m \\\n  %reldir%/fzero.m \\\n  %reldir%/glpk.m \\\n  %reldir%/humps.m \\\n  %reldir%/lsqnonneg.m \\\n  %reldir%/optimget.m \\\n  %reldir%/optimset.m \\\n  %reldir%/pqpnonneg.m \\\n  %reldir%/qp.m \\\n  %reldir%/sqp.m\n\n%canon_reldir%dir = $(fcnfiledir)/optimization\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/optimization/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/optimization/optimget.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{val} =} optimget (@var{options}, @var{par})\n## @deftypefnx {} {@var{val} =} optimget (@var{options}, @var{par}, @var{default})\n## Return the value of the specific parameter @var{par} from the optimization\n## options structure @var{options} created by @code{optimset}.\n##\n## If @var{par} is not defined then return the @var{default} value if\n## supplied, otherwise return an empty matrix.\n##\n## If @var{par} does not exactly match the name of a standard parameter,\n## @code{optimget} will attempt to match @var{par} to a standard parameter\n## and will return that parameter's value if a match is found.  Matching is\n## case insensitive and is based on character matching at the start of the\n## parameter name.  @code{optimget} produces an error if it finds multiple\n## ambiguous matches.  If no standard parameter matches are found a warning is\n## issued.  See @code{optimset} for information about the standard options\n## list.\n##\n## Note: Only parameter names from the standard list are considered when\n## matching short parameter names, and @var{par} will always be expanded to\n## match a standard parameter even if an exact non-standard match exists.  The\n## value of a non-standard parameter that is ambiguous with one or more\n## standard parameters cannot be returned by @code{optimget} and can only be\n## accessed using @code{getfield} or dot notation for structs.\n## @seealso{optimset}\n## @end deftypefn\n\nfunction optval = optimget (options, optname, default)\n\n  if (nargin < 2 || ! isstruct (options) || ! ischar (optname))\n    print_usage ();\n  endif\n\n  ## Expand partial-length names into full names\n  opts = __all_opts__ ();\n  idx = strncmpi (opts, optname, length (optname));\n  nmatch = sum (idx);\n\n  if (nmatch == 1)\n    optname = opts{idx};\n  elseif (nmatch == 0)\n    warning (\"optimget: unrecognized option: '%s'\", optname);\n  else\n    fmt = sprintf (\"optimget: ambiguous option: '%%s' (%s%%s)\",\n                   repmat (\"%s, \", 1, nmatch-1));\n    error (fmt, optname, opts{idx});\n  endif\n\n  if (isfield (options, optname) && ! isempty (options.(optname)))\n    optval = options.(optname);\n  elseif (nargin > 2)\n    optval = default;\n  else\n    optval = [];\n  endif\n\nendfunction\n\n\n%!shared opts\n%! opts = optimset (\"tolx\", 0.1, \"maxit\", 100);\n%!assert (optimget (opts, \"TolX\"), 0.1)\n%!assert (optimget (opts, \"maxit\"), 100)\n%!assert (optimget (opts, \"MaxITer\"), 100)\n%!assert (optimget (opts, \"TolFun\"), [])\n%!assert (optimget (opts, \"TolFun\", 1e-3), 1e-3)\n\n## Test input validation\n%!error <Invalid call> optimget ()\n%!error <Invalid call> optimget (1)\n%!error optimget (1, \"name\")\n%!error optimget (struct (), 2)\n%!warning <unrecognized option: 'foobar'> (optimget (opts, \"foobar\"));\n%!error <ambiguous option: 'Max'> (optimget (opts, \"Max\"));\n"
  },
  {
    "path": "scripts/optimization/optimset.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} optimset ()\n## @deftypefnx {} {@var{options} =} optimset ()\n## @deftypefnx {} {@var{options} =} optimset (@var{par}, @var{val}, @dots{})\n## @deftypefnx {} {@var{options} =} optimset (@var{old}, @var{par}, @var{val}, @dots{})\n## @deftypefnx {} {@var{options} =} optimset (@var{old}, @var{new})\n## Create options structure for optimization functions.\n##\n## When called without any input or output arguments, @code{optimset} prints\n## a list of all valid optimization parameters.\n##\n## When called with one output and no inputs, return an options structure with\n## all valid option parameters initialized to @code{[]}.\n##\n## When called with a list of parameter/value pairs, return an options\n## structure with only the named parameters initialized.\n##\n## When the first input is an existing options structure @var{old}, the values\n## are updated from either the @var{par}/@var{val} list or from the options\n## structure @var{new}.\n##\n## If @var{par} does not exactly match the name of a standard parameter,\n## @code{optimset} will attempt to match @var{par} to a standard parameter\n## and will set the value of that parameter if a match is found.  Matching is\n## case insensitive and is based on character matching at the start of the\n## parameter name.  @code{optimset} produces an error if it finds multiple\n## ambiguous matches.  If no standard parameter matches are found a warning is\n## issued and the non-standard parameter is created.\n##\n## Standard list of valid parameters:\n##\n## @table @asis\n## @item AutoScaling\n##\n## @item ComplexEqn\n##\n## @item Display\n## Request verbose display of results from optimizations.  Values are:\n##\n## @table @asis\n## @item @qcode{\"off\"} [default]\n## No display.\n##\n## @item @qcode{\"iter\"}\n## Display intermediate results for every loop iteration.\n##\n## @item @qcode{\"final\"}\n## Display the result of the final loop iteration.\n##\n## @item @qcode{\"notify\"}\n## Display the result of the final loop iteration if the function has\n## failed to converge.\n## @end table\n##\n## @item FinDiffType\n##\n## @item FunValCheck\n## When enabled, display an error if the objective function returns an invalid\n## value (a complex number, NaN, or Inf).  Must be set to @qcode{\"on\"} or\n## @qcode{\"off\"} [default].  Note: the functions @code{fzero} and\n## @code{fminbnd} correctly handle Inf values and only complex values or NaN\n## will cause an error in this case.\n##\n## @item GradObj\n## When set to @qcode{\"on\"}, the function to be minimized must return a\n## second argument which is the gradient, or first derivative, of the\n## function at the point @var{x}.  If set to @qcode{\"off\"} [default], the\n## gradient is computed via finite differences.\n##\n## @item Jacobian\n## When set to @qcode{\"on\"}, the function to be minimized must return a\n## second argument which is the Jacobian, or first derivative, of the\n## function at the point @var{x}.  If set to @qcode{\"off\"} [default], the\n## Jacobian is computed via finite differences.\n##\n## @item MaxFunEvals\n## Maximum number of function evaluations before optimization stops.\n## Must be a positive integer.\n##\n## @item MaxIter\n## Maximum number of algorithm iterations before optimization stops.\n## Must be a positive integer.\n##\n## @item OutputFcn\n## A user-defined function executed once per algorithm iteration.\n##\n## @item TolFun\n## Termination criterion for the function output.  If the difference in the\n## calculated objective function between one algorithm iteration and the next\n## is less than @code{TolFun} the optimization stops.  Must be a positive\n## scalar.\n##\n## @item TolX\n## Termination criterion for the function input.  If the difference in @var{x},\n## the current search point, between one algorithm iteration and the next is\n## less than @code{TolX} the optimization stops.  Must be a positive scalar.\n##\n## @item TypicalX\n##\n## @item Updating\n## @end table\n##\n## This list can be extended by the user or other loaded Octave packages.  An\n## updated valid parameters list can be queried using the no-argument form of\n## @code{optimset}.\n##\n## Note 1: Only parameter names from the standard list are considered when\n## matching short parameter names, and @var{par} will always be expanded\n## to match a standard parameter even if an exact non-standard match exists.\n## The value of a non-standard parameter that is ambiguous with one or more\n## standard parameters cannot be set by @code{optimset} and can only be set\n## using @code{setfield} or dot notation for structs.\n##\n## Note 2: The optimization options structure is primarily intended for\n## manipulation of known parameters by @code{optimset} and @code{optimget}.\n## Unpredictable behavior on future calls to @code{optimset} or\n## @code{optimget} can result from creating non-standard or ambiguous\n## parameters or from loading/unloading packages that change the known\n## parameter list after creation of an optimization options structure.\n## @seealso{optimget}\n## @end deftypefn\n\nfunction retval = optimset (varargin)\n\n  nargs = nargin;\n\n  opts = __all_opts__ ();\n  ## Skip validation if we're in the internal query.\n  validation = ! isempty (opts);\n\n  if (nargs == 0)\n    if (nargout == 0)\n      ## Display possibilities.\n      puts (\"\\nAll possible optimization options:\\n\\n\");\n      printf (\"  %s\\n\", opts{:});\n      puts (\"\\n\");\n    else\n      ## Return struct with all options initialized to []\n      retval = cell2struct (repmat ({[]}, size (opts)), opts, 2);\n    endif\n  elseif (nargs == 1 && ischar (varargin{1}))\n    ## Return defaults for named function.\n    fcn = varargin{1};\n    try\n      retval = feval (fcn, \"defaults\");\n    catch\n      error (\"optimset: no defaults for function '%s'\", fcn);\n    end_try_catch\n  elseif (nargs == 2 && isstruct (varargin{1}) && isstruct (varargin{2}))\n    ## Set slots in old from non-empties in new.\n    ## Should we be checking to ensure that the field names are expected?\n    old = varargin{1};\n    new = varargin{2};\n    useempty = false; # Matlab drops empty new fields, too.\n    retval = setoptionfields (opts, old, new, validation, useempty);\n  elseif (rem (nargs, 2) && isstruct (varargin{1}))\n    ## Set values in old from name/value pairs.\n    old = varargin{1};\n    pairs = reshape (varargin(2:end), 2, []);\n    new = cell2struct (pairs(2, :), pairs(1, :), 2);\n    useempty = true; # Matlab preserves empty arguments, too.\n    retval = setoptionfields (opts, old, new, validation, useempty);\n  elseif (rem (nargs, 2) == 0)\n    ## Create struct.\n    ## Default values are replaced by those specified by name/value pairs.\n    old = struct ();\n    pairs = reshape (varargin, 2, []);\n    new = cell2struct (pairs(2, :), pairs(1, :), 2);\n    useempty = true; # Matlab preserves empty arguments, too.\n    retval = setoptionfields (opts, old, new, validation, useempty);\n  else\n    print_usage ();\n  endif\n\nendfunction\n\nfunction retval = setoptionfields (opts, old, new, validation, useempty)\n\n  for [val, key] = new\n    if (validation)\n      ## Case insensitive lookup in all options.\n      i = strncmpi (opts, key, length (key));\n      nmatch = sum (i);\n      ## Validate option.\n      if (nmatch == 1)\n        key = opts{find (i)};\n      elseif (nmatch == 0)\n        warning (\"optimset: unrecognized option: '%s'\", key);\n      else\n        fmt = sprintf (\"optimset: ambiguous option: '%%s' (%s%%s)\",\n                       repmat (\"%s, \", 1, nmatch-1));\n        error (fmt, key, opts{i});\n      endif\n    endif\n    if (useempty || ! isempty (val))\n      old.(key) = val;\n    endif\n  endfor\n  retval = old;\n\nendfunction\n\n\n%!assert (isfield (optimset (), \"TolFun\"))\n%!assert (isfield (optimset (\"tolFun\", 1e-3), \"TolFun\"))\n%!assert (optimget (optimset (\"tolx\", 1e-2), \"tOLx\"), 1e-2)\n%!test\n%! old = optimset ();\n%! old.TolX = 1e-2;\n%! new = optimset ();\n%! new.TolFun = 1e-3;\n%! joint = optimset (old, new);\n%! assert (joint.TolX, 1e-2);\n%! assert (joint.TolFun, 1e-3);\n\n## Test preserving empty values given as arguments\n%!test\n%! opts = optimset (\"TypicalX\", []);\n%! assert (isempty (opts.TypicalX));\n\n## Test input validation\n%!error optimset (\"1_Parameter\")\n%!error <no defaults for function> optimset (\"%NOT_A_REAL_FUNCTION_NAME%\")\n%!warning <unrecognized option: 'foobar'> optimset (\"foobar\", 13);\n%!error <ambiguous option: 'Max'> optimset (\"Max\", 10);\n"
  },
  {
    "path": "scripts/optimization/pqpnonneg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} pqpnonneg (@var{c}, @var{d})\n## @deftypefnx {} {@var{x} =} pqpnonneg (@var{c}, @var{d}, @var{x0})\n## @deftypefnx {} {@var{x} =} pqpnonneg (@var{c}, @var{d}, @var{x0}, @var{options})\n## @deftypefnx {} {[@var{x}, @var{minval}] =} pqpnonneg (@dots{})\n## @deftypefnx {} {[@var{x}, @var{minval}, @var{exitflag}] =} pqpnonneg (@dots{})\n## @deftypefnx {} {[@var{x}, @var{minval}, @var{exitflag}, @var{output}] =} pqpnonneg (@dots{})\n## @deftypefnx {} {[@var{x}, @var{minval}, @var{exitflag}, @var{output}, @var{lambda}] =} pqpnonneg (@dots{})\n##\n## Minimize @code{ (1/2 * @var{x}' * @var{c} * @var{x} + @var{d}' * @var{x}) }\n## subject to @code{@var{x} >= 0}.\n##\n## @var{c} and @var{d} must be real matrices, and @var{c} must be symmetric and\n## positive definite.\n##\n## @var{x0} is an optional initial guess for the solution @var{x}.\n##\n## @var{options} is an options structure to change the behavior of the\n## algorithm (@pxref{XREFoptimset,,@code{optimset}}).  @code{pqpnonneg}\n## recognizes one option: @qcode{\"MaxIter\"}.\n##\n## Outputs:\n##\n## @table @var\n##\n## @item x\n## The solution matrix\n##\n## @item minval\n## The minimum attained model value,\n## @code{1/2*@var{xmin}'*@var{c}*@var{xmin} + @var{d}'*@var{xmin}}\n##\n## @item exitflag\n## An indicator of convergence.  0 indicates that the iteration count was\n## exceeded, and therefore convergence was not reached; >0 indicates that the\n## algorithm converged.  (The algorithm is stable and will converge given\n## enough iterations.)\n##\n## @item output\n## A structure with two fields:\n##\n## @itemize @bullet\n## @item @qcode{\"algorithm\"}: The algorithm used (@nospell{@qcode{\"nnls\"}})\n##\n## @item @qcode{\"iterations\"}: The number of iterations taken.\n## @end itemize\n##\n## @item lambda\n## Lagrange multipliers.  If these are nonzero, the corresponding @var{x}\n## values should be zero, indicating the solution is pressed up against a\n## coordinate plane.  The magnitude indicates how much the residual would\n## improve if the @code{@var{x} >= 0} constraints were relaxed in that\n## direction.\n##\n## @end table\n## @seealso{lsqnonneg, qp, optimset}\n## @end deftypefn\n\n## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.\n## PKG_ADD: [~] = __all_opts__ (\"pqpnonneg\");\n\n## This is analogical to the lsqnonneg implementation, which is implemented\n## from Lawson and Hanson's 1973 algorithm on page 161 of Solving Least Squares\n## Problems.  It shares the convergence guarantees.\n\nfunction [x, minval, exitflag, output, lambda] = pqpnonneg (c, d, x0 = [],\n                                                            options = struct ())\n\n  ## Special case: called to find default optimization options\n  if (nargin == 1 && ischar (c) && strcmp (c, \"defaults\"))\n    x = struct (\"MaxIter\", 1e5);\n    return;\n  endif\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (c) && ismatrix (c)) || ! (isnumeric (d) && ismatrix (d)))\n    error (\"pqpnonneg: C and D must be numeric matrices\");\n  endif\n  if (! issquare (c))\n    error (\"pqpnonneg: C must be a square matrix\");\n  endif\n\n  if (! isstruct (options))\n    error (\"pqpnonneg: OPTIONS must be a struct\");\n  endif\n\n  ## Lawson-Hanson Step 1 (LH1): initialize the variables.\n  n = columns (c);\n  if (isempty (x0))\n    ## Initial guess is all zeros.\n    x = zeros (n, 1);\n  else\n    ## ensure nonnegative guess.\n    x = max (x0, 0);\n  endif\n\n  max_iter = optimget (options, \"MaxIter\", 1e5);\n\n  ## Initialize P, according to zero pattern of x.\n  p = find (x > 0).';\n  ## Initialize the Cholesky factorization.\n  r = chol (c(p, p));\n  usechol = true;\n\n  iter = 0;\n\n  ## LH3: test for completion.\n  while (iter < max_iter)\n    while (iter < max_iter)\n      iter += 1;\n\n      ## LH6: compute the positive matrix and find the min norm solution\n      ## of the positive problem.\n      if (usechol)\n        xtmp = -(r \\ (r' \\ d(p)));\n      else\n        xtmp = -(c(p,p) \\ d(p));\n      endif\n      idx = find (xtmp < 0);\n\n      if (isempty (idx))\n        ## LH7: tmp solution found, iterate.\n        x(:) = 0;\n        x(p) = xtmp;\n        break;\n      else\n        ## LH8, LH9: find the scaling factor.\n        pidx = p(idx);\n        sf = x(pidx) ./ (x(pidx) - xtmp(idx));\n        alpha = min (sf);\n        ## LH10: adjust X.\n        xx = zeros (n, 1);\n        xx(p) = xtmp;\n        x += alpha*(xx - x);\n        ## LH11: move from P to Z all X == 0.\n        ## This corresponds to those indices where minimum of sf is attained.\n        idx = idx(sf == alpha);\n        p(idx) = [];\n        if (usechol)\n          ## update the Cholesky factorization.\n          r = choldelete (r, idx);\n        endif\n      endif\n    endwhile\n\n    ## compute the gradient.\n    w = -(d + c*x);\n    w(p) = [];\n    if (! any (w > 0))\n      if (usechol)\n        ## verify the solution achieved using qr updating.\n        ## In the best case, this should only take a single step.\n        usechol = false;\n        continue;\n      else\n        ## we're finished.\n        break;\n      endif\n    endif\n\n    ## find the maximum gradient.\n    idx = find (w == max (w));\n    if (numel (idx) > 1)\n      warning (\"pqpnonneg:nonunique\",\n               \"a non-unique solution may be returned due to equal gradients\");\n      idx = idx(1);\n    endif\n    ## move the index from Z to P.  Keep P sorted.\n    z = [1:n]; z(p) = [];\n    zidx = z(idx);\n    jdx = 1 + lookup (p, zidx);\n    p = [p(1:jdx-1), zidx, p(jdx:end)];\n    if (usechol)\n      ## insert the column into the Cholesky factorization.\n      [r, bad] = cholinsert (r, jdx, c(p,zidx));\n      if (bad)\n        ## If the insertion failed, we switch off updates and go on.\n        usechol = false;\n      endif\n    endif\n\n  endwhile\n  ## LH12: complete.\n\n  ## Generate the additional output arguments.\n  if (nargout > 1)\n    minval = 1/2*(x'*c*x) + d'*x;\n  endif\n  if (nargout > 2)\n    if (iter >= max_iter)\n      exitflag = 0;\n    else\n      exitflag = iter;\n    endif\n  endif\n  if (nargout > 3)\n    output = struct (\"algorithm\", \"nnls-pqp\", \"iterations\", iter);\n  endif\n  if (nargout > 4)\n    lambda = zeros (size (x));\n    lambda (setdiff (1:numel (x), p)) = w;\n  endif\n\nendfunction\n\n\n%!test\n%! C = [5 2;2 2];\n%! d = [3; -1];\n%! assert (pqpnonneg (C, d), [0;0.5], 100*eps);\n\n## Test equivalence of lsq and pqp\n%!test\n%! C = rand (20, 10);\n%! d = rand (20, 1);\n%! assert (pqpnonneg (C'*C, -C'*d), lsqnonneg (C, d), 100*eps);\n\n## Test Lagrange multiplier duality: lambda .* x == 0\n%!test\n%! [x, resid, ~, ~, lambda] = pqpnonneg ([3 2; 2 2], [6; 5]);\n%! assert (x, [0 0]', eps);\n%! assert (resid, 0, eps);\n%! assert (lambda, [-6 -5]', eps);\n%! assert (x .* lambda, [0 0]');\n\n%!test\n%! [x, resid, ~, ~, lambda] = pqpnonneg ([3 2; 2 2], [6; -5]);\n%! assert (x, [0 2.5]', eps);\n%! assert (resid, -6.25, eps);\n%! assert (lambda, [-11 0]', eps);\n%! assert (x .* lambda, [0 0]');\n\n%!test\n%! [x, resid, ~, ~, lambda] = pqpnonneg ([3 2; 2 2], [-6; 5]);\n%! assert (x, [2 0]', eps);\n%! assert (resid, -6, eps);\n%! assert (lambda, [0 -9]', eps);\n%! assert (x .* lambda, [0 0]');\n\n%!test\n%! [x, resid, ~, ~, lambda] = pqpnonneg ([3 2; 2 2], [-6; -5]);\n%! assert (x, [1 1.5]', 10*eps);\n%! assert (resid, -6.75, 10*eps);\n%! assert (lambda, [0 0]', eps);\n%! assert (x .* lambda, [0 0]');\n\n## Test input validation\n%!error <Invalid call> pqpnonneg ()\n%!error <Invalid call> pqpnonneg (1)\n%!error <C .* must be numeric matrices> pqpnonneg ({1},2)\n%!error <C .* must be numeric matrices> pqpnonneg (ones (2,2,2),2)\n%!error <D must be numeric matrices> pqpnonneg (1,{2})\n%!error <D must be numeric matrices> pqpnonneg (1, ones (2,2,2))\n%!error <C must be a square matrix> pqpnonneg ([1 2], 2)\n%!error <OPTIONS must be a struct> pqpnonneg (1, 2, [], 3)\n"
  },
  {
    "path": "scripts/optimization/private/__fdjac__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{fjac} =} __fdjac__ (@var{fcn}, @var{x}, @var{fvec}, @var{typicalx}, @var{cdif}, @var{err})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction fjac = __fdjac__ (fcn, x, fvec, typicalx, cdif, err = 0)\n\n  if (cdif)\n    err = (max (eps, err)) ^ (1/3);\n    h = err * max (abs (x), typicalx);\n    fjac = zeros (length (fvec), numel (x));\n    for i = 1:numel (x)\n      x1 = x2 = x;\n      x1(i) += h(i);\n      x2(i) -= h(i);\n      fjac(:,i) = (fcn (x1)(:) - fcn (x2)(:)) / (x1(i) - x2(i));\n    endfor\n  else\n    err = sqrt (max (eps, err));\n    signp = sign (x);\n    signp(signp == 0) = 1;\n    h = err * signp .* max (abs (x), typicalx);\n    fjac = zeros (length (fvec), numel (x));\n    for i = 1:numel (x)\n      x1 = x;\n      x1(i) += h(i);\n      fjac(:,i) = (fcn (x1)(:) - fvec) / (x1(i) - x(i));\n    endfor\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/optimization/qp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{x}, @var{obj}, @var{info}, @var{lambda}] =} qp (@var{x0}, @var{H})\n## @deftypefnx {} {[@var{x}, @var{obj}, @var{info}, @var{lambda}] =} qp (@var{x0}, @var{H}, @var{q})\n## @deftypefnx {} {[@var{x}, @var{obj}, @var{info}, @var{lambda}] =} qp (@var{x0}, @var{H}, @var{q}, @var{A}, @var{b})\n## @deftypefnx {} {[@var{x}, @var{obj}, @var{info}, @var{lambda}] =} qp (@var{x0}, @var{H}, @var{q}, @var{A}, @var{b}, @var{lb}, @var{ub})\n## @deftypefnx {} {[@var{x}, @var{obj}, @var{info}, @var{lambda}] =} qp (@var{x0}, @var{H}, @var{q}, @var{A}, @var{b}, @var{lb}, @var{ub}, @var{A_lb}, @var{A_in}, @var{A_ub})\n## @deftypefnx {} {[@var{x}, @var{obj}, @var{info}, @var{lambda}] =} qp (@dots{}, @var{options})\n## Solve a quadratic program (QP).\n##\n## Solve the quadratic program defined by\n## @tex\n## $$\n##  \\min_x {1 \\over 2} x^T H x + x^T q\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## min 0.5 x'*H*x + x'*q\n##  x\n## @end group\n## @end example\n##\n## @end ifnottex\n## subject to\n## @tex\n## $$\n##  A x = b \\qquad lb \\leq x \\leq ub \\qquad A_{lb} \\leq A_{in} x \\leq A_{ub}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## A*x = b\n## lb <= x <= ub\n## A_lb <= A_in*x <= A_ub\n## @end group\n## @end example\n##\n## @end ifnottex\n## @noindent\n## using a null-space active-set method.\n##\n## Any bound (@var{A}, @var{b}, @var{lb}, @var{ub}, @var{A_in}, @var{A_lb},\n## @var{A_ub}) may be set to the empty matrix (@code{[]}) if not present.  The\n## constraints @var{A} and @var{A_in} are matrices with each row representing\n## a single constraint.  The other bounds are scalars or vectors depending on\n## the number of constraints.  The algorithm is faster if the initial guess is\n## feasible.\n##\n## @var{options} is a structure specifying additional parameters which\n## control the algorithm.  Currently, @code{qp} recognizes these options:\n## @qcode{\"MaxIter\"}, @qcode{\"TolX\"}, @qcode{\"AllowSemidefinite\"}.\n##\n## @qcode{\"MaxIter\"} sets the maximum number of algorithm iterations before\n## optimization is halted.  The default value is 200.\n## The value must be a positive integer.\n##\n## @qcode{\"TolX\"} specifies the termination tolerance for the unknown variables\n## @var{x}.  The default is @code{sqrt (eps)} or approximately 1e-8.\n##\n## @qcode{\"AllowSemidefinite\"} is a boolean flag: @code{true} allows positive\n## semi-definite problems (one or more eigenvalues of the Hessian are zero).\n## @code{false} requires positive definiteness (all eigenvalues positive).\n## The default is @code{false}.\n##\n## On return, @var{x} is the location of the minimum and @var{fval} contains\n## the value of the objective function at @var{x}.\n##\n## @table @var\n## @item info\n## Structure containing run-time information about the algorithm.  The\n## following fields are defined:\n##\n## @table @code\n## @item solveiter\n## The number of iterations required to find the solution.\n##\n## @item info\n## An integer indicating the status of the solution.\n##\n## @table @asis\n## @item 0\n## The problem is feasible and convex.  Global solution found.\n##\n## @item 1\n## The problem is not convex.  Local solution found.\n##\n## @item 2\n## The problem is not convex and unbounded.\n##\n## @item 3\n## Maximum number of iterations reached.\n##\n## @item 6\n## The problem is infeasible.\n## @end table\n## @end table\n## @end table\n## @seealso{sqp}\n## @end deftypefn\n\n## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.\n## PKG_ADD: [~] = __all_opts__ (\"qp\");\n\nfunction [x, obj, INFO, lambda] = qp (x0, H, varargin)\n\n  if (nargin == 1 && ischar (x0) && strcmp (x0, \"defaults\"))\n    x = struct (\"MaxIter\", 200, \"TolX\", sqrt (eps), \"AllowSemidefinite\", false);\n    return;\n  endif\n\n  nargs = nargin;\n  if (nargs > 2 && isstruct (varargin{end}))\n    options = varargin{end};\n    nargs -= 1;\n  else\n    options = struct ();\n  endif\n\n  if (nargs != 2 && nargs != 3 && nargs != 5 && nargs != 7 && nargs != 10)\n    print_usage ();\n  endif\n\n  if (nargs >= 3)\n    q = varargin{1};\n  else\n    q = [];\n  endif\n\n  if (nargs >= 5)\n    A = varargin{2};\n    b = varargin{3};\n  else\n    A = [];\n    b = [];\n  endif\n\n  if (nargs >= 7)\n    lb = varargin{4};\n    ub = varargin{5};\n  else\n    lb = [];\n    ub = [];\n  endif\n\n  if (nargs == 10)\n    A_lb = varargin{6};\n    A_in = varargin{7};\n    A_ub = varargin{8};\n  else\n    A_lb = [];\n    A_in = [];\n    A_ub = [];\n  endif\n\n  maxit = optimget (options, \"MaxIter\", 200);\n  tol = optimget (options, \"TolX\", sqrt (eps));\n  allowsemidefinite = optimget (options, \"AllowSemidefinite\", false);\n\n  ## Validate options.\n  if (maxit <= 0 || ceil (maxit) != floor (maxit))\n    error (\"qp: MaxIter should be a positive integer\");\n  endif\n  if (! islogical (allowsemidefinite))\n    warning (\"qp: converting AllowSemidefinite to a logical value (true or false)\");\n    allowsemidefinite = logical (allowsemidefinite)\n  endif\n\n  ## Validate the quadratic penalty.\n  if (! issquare (H))\n    error (\"qp: quadratic penalty matrix must be square\");\n  elseif (! ishermitian (H))\n    ## warning (\"qp: quadratic penalty matrix not hermitian\");\n    H = (H + H')/2;\n  endif\n  n = rows (H);\n\n  ## Validate the initial guess.\n  ## If empty it is resized to the right dimension and filled with 0.\n  if (isempty (x0))\n    x0 = zeros (n, 1);\n  else\n    if (! isvector (x0))\n      error (\"qp: the initial guess X0 must be a vector\");\n    elseif (numel (x0) != n)\n      error (\"qp: the initial guess X0 has incorrect length\");\n    endif\n    x0 = x0(:);  # always use column vector.\n  endif\n\n  ## Validate linear penalty.\n  if (isempty (q))\n    q = zeros (n, 1);\n  else\n    if (! isvector (q))\n      error (\"qp: Q must be a vector\");\n    elseif (numel (q) != n)\n      error (\"qp: Q has incorrect length\");\n    endif\n    q = q(:);   # always use column vector.\n  endif\n\n  ## Validate equality constraint matrices.\n  if (isempty (A) || isempty (b))\n    A = zeros (0, n);\n    b = zeros (0, 1);\n    n_eq = 0;\n  else\n    [n_eq, n1] = size (A);\n    if (n1 != n)\n      error (\"qp: equality constraint matrix has incorrect column dimension\");\n    endif\n    if (numel (b) != n_eq)\n      error (\"qp: equality constraint matrix and vector have inconsistent dimensions\");\n    endif\n  endif\n\n  ## Validate bound constraints.\n  Ain = zeros (0, n);\n  bin = zeros (0, 1);\n  n_in = 0;\n  if (nargs > 5)\n    if (! isempty (lb))\n      if (numel (lb) != n)\n        error (\"qp: lower bound LB has incorrect length\");\n      elseif (isempty (ub))\n        Ain = [Ain; eye(n)];\n        bin = [bin; lb];\n      endif\n    endif\n\n    if (! isempty (ub))\n      if (numel (ub) != n)\n        error (\"qp: upper bound UB has incorrect length\");\n      elseif (isempty (lb))\n        Ain = [Ain; -eye(n)];\n        bin = [bin; -ub];\n      endif\n    endif\n\n    if (! isempty (lb) && ! isempty (ub))\n      rtol = tol;\n      for i = 1:n\n        if (abs (lb (i) - ub(i)) < rtol*(1 + max (abs (lb(i) + ub(i)))))\n          ## These are actually an equality constraint\n          tmprow = zeros (1,n);\n          tmprow(i) = 1;\n          A = [A;tmprow];\n          b = [b; 0.5*(lb(i) + ub(i))];\n          n_eq += 1;\n        else\n          tmprow = zeros (1,n);\n          tmprow(i) = 1;\n          Ain = [Ain; tmprow; -tmprow];\n          bin = [bin; lb(i); -ub(i)];\n          n_in += 2;\n        endif\n      endfor\n    endif\n  endif\n\n  ## Validate inequality constraints.\n  if (nargs > 7 && isempty (A_in) && ! (isempty (A_lb) || isempty (A_ub)))\n    warning (\"qp: empty inequality constraint matrix but non-empty bound vectors\");\n  endif\n\n  if (nargs > 7 && ! isempty (A_in))\n    [dimA_in, n1] = size (A_in);\n    if (n1 != n)\n      error (\"qp: inequality constraint matrix has incorrect column dimension, expected %i\", n1);\n    else\n      if (! isempty (A_lb))\n        if (numel (A_lb) != dimA_in)\n          error (\"qp: inequality constraint matrix and lower bound vector are inconsistent, %i != %i\", dimA_in, numel (A_lb));\n        elseif (isempty (A_ub))\n          Ain = [Ain; A_in];\n          bin = [bin; A_lb];\n        endif\n      endif\n      if (! isempty (A_ub))\n        if (numel (A_ub) != dimA_in)\n          error (\"qp: inequality constraint matrix and upper bound vector are inconsistent, %i != %i\", dimA_in, numel (A_ub));\n        elseif (isempty (A_lb))\n          Ain = [Ain; -A_in];\n          bin = [bin; -A_ub];\n        endif\n      endif\n\n      if (! isempty (A_lb) && ! isempty (A_ub))\n        rtol = tol;\n        for i = 1:dimA_in\n          if (abs (A_lb(i) - A_ub(i))\n              < rtol*(1 + max (abs (A_lb(i) + A_ub(i)))))\n            ## These are actually an equality constraint\n            tmprow = A_in(i,:);\n            A = [A;tmprow];\n            b = [b; 0.5*(A_lb(i) + A_ub(i))];\n            n_eq += 1;\n          else\n            tmprow = A_in(i,:);\n            Ain = [Ain; tmprow; -tmprow];\n            bin = [bin; A_lb(i); -A_ub(i)];\n            n_in += 2;\n          endif\n        endfor\n      endif\n    endif\n  endif\n\n  ## Now we should have the following QP:\n  ##\n  ##   min_x  0.5*x'*H*x + x'*q\n  ##   s.t.   A*x = b\n  ##          Ain*x >= bin\n\n  ## Discard inequality constraints that have -Inf bounds since those\n  ## will never be active.\n  idx = (bin == -Inf);\n\n  bin(idx) = [];\n  Ain(idx,:) = [];\n\n  n_in = numel (bin);\n\n  ## Check if the initial guess is feasible.\n  if (isa (x0, \"single\") || isa (H, \"single\") || isa (q, \"single\")\n      || isa (A, \"single\") || isa (b, \"single\"))\n    rtol = sqrt (eps (\"single\"));\n  else\n    rtol = tol;\n  endif\n\n  eq_infeasible = (n_eq > 0 && norm (A*x0-b) > rtol*(1+abs (b)));\n  in_infeasible = (n_in > 0 && any (Ain*x0-bin < -rtol*(1+abs (bin))));\n\n  info = 0;\n\n  if (! allowsemidefinite && isdefinite (H) != 1)\n    info = 2;\n  endif\n\n  if (info == 0 && (eq_infeasible || in_infeasible))\n    ## The initial guess is not feasible.\n    ## First, define an xbar that is feasible with respect to the\n    ## equality constraints.\n    if (eq_infeasible)\n      if (rank (A) < n_eq)\n        error (\"qp: equality constraint matrix must be full row rank\");\n      endif\n      xbar = pinv (A) * b;\n    else\n      xbar = x0;\n    endif\n\n    ## Second, check that xbar is also feasible with respect to the\n    ## inequality constraints.\n    if (n_in > 0)\n      res = Ain * xbar - bin;\n      if (any (res < -rtol * (1 + abs (bin))))\n        ## xbar is not feasible with respect to the inequality constraints.\n        ## Compute a step in the null space of the equality constraints,\n        ## by solving a QP.  If the slack is small, we have a feasible initial\n        ## guess.  Otherwise, the problem is infeasible.\n        if (n_eq > 0)\n          Z = null (A);\n          if (isempty (Z))\n            ## The problem is infeasible because A is square and full rank,\n            ## but xbar is not feasible.\n            info = 6;\n          endif\n        endif\n\n        if (info != 6)\n          ## Solve an LP with additional slack variables\n          ## to find a feasible starting point.\n          gamma = eye (n_in);\n          if (n_eq > 0)\n            Atmp = [Ain*Z, gamma];\n            btmp = -res;\n          else\n            Atmp = [Ain, gamma];\n            btmp = bin;\n          endif\n          ctmp = [zeros(n-n_eq, 1); ones(n_in, 1)];\n          lb = [-Inf(n-n_eq,1); zeros(n_in,1)];\n          ub = [];\n          ctype = repmat (\"L\", n_in, 1);\n          [P, FMIN, status] = glpk (ctmp, Atmp, btmp, lb, ub, ctype);\n          ## FIXME: Test based only on rtol occasionally fails (Bug #38353).\n          ## This seems to be a problem in glpk in which return value XOPT(1)\n          ## is the same as FMIN.  Workaround this by explicit test\n          if (status != 0)\n            info = 6;  # The problem is infeasible\n          else\n            if (all (abs (P(n-n_eq+2:end)) < rtol * (1 + norm (btmp)))\n                && (P(n-n_eq+1) < rtol * (1 + norm (btmp))\n                    || P(n-n_eq+1) == FMIN))\n              ## We found a feasible starting point\n              if (n_eq > 0)\n                x0 = xbar + Z*P(1:n-n_eq);\n              else\n                x0 = P(1:n);\n              endif\n            else\n              info = 6;  # The problem is infeasible\n            endif\n          endif\n        endif\n      else\n        ## xbar is feasible.  We use it a starting point.\n        x0 = xbar;\n      endif\n    else\n      ## xbar is feasible.  We use it a starting point.\n      x0 = xbar;\n    endif\n  endif\n\n  if (info == 0)\n    ## The initial (or computed) guess is feasible.  Call the solver.\n    [x, lambda, info, iter] = __qp__ (x0, H, q, A, b, Ain, bin, maxit, rtol);\n  else\n    iter = 0;\n    x = x0;\n    lambda = [];\n  endif\n  if (nargout > 1)\n    obj = 0.5 * x' * H * x + q' * x;\n  endif\n  if (nargout > 2)\n    INFO.solveiter = iter;\n    INFO.info = info;\n  endif\n\nendfunction\n\n\n## Test infeasible initial guess\n%!testif HAVE_GLPK <*40536>\n%!\n%! H = 1;  q = 0;                # objective: x -> 0.5 x^2\n%! A = 1;  lb = 1;  ub = +inf;   # constraint: x >= 1\n%! x0 = 0;                       # infeasible initial guess\n%!\n%! [x, obj_qp, INFO, lambda] = qp (x0, H, q, [], [], [], [], lb, A, ub);\n%!\n%! assert (isstruct (INFO) && isfield (INFO, \"info\") && (INFO.info == 0));\n%! assert ([x obj_qp], [1.0 0.5], eps);\n\n%!test <*61762>\n%! [x, obj, info] = qp ([], [21, 30, 39; 30, 45, 60; 39, 60, 81], [-40; -65; -90]);\n%! assert (x, zeros (3, 1));\n%! assert (obj, 0);\n%! assert (info.info, 2);\n\n## Check positive semi-definite input\n%!test <*64346>\n%! H = [1 1; 1 1];\n%! q = [-1; -1];\n%! A = [1 -1];\n%! b = 0;\n%! lb = [0; 0];\n%! ub = [10; 10];\n%! [x, obj, info, lambda] = qp([], H, q, A, b, lb, ub, [], [], []);  # default value: semidefinite not allowed\n%! assert (info.info, 2);\n%! [x, obj, info, lambda] = qp([], H, q, A, b, lb, ub, [], [], [], optimset (\"AllowSemidefinite\", true));\n%! assert (info.info, 0);\n%! assert (x, [1/2; 1/2], eps);\n"
  },
  {
    "path": "scripts/optimization/sqp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{x}, @var{obj}, @var{info}, @var{iter}, @var{nf}, @var{lambda}] =} sqp (@var{x0}, @var{phi})\n## @deftypefnx {} {[@dots{}] =} sqp (@var{x0}, @var{phi}, @var{g})\n## @deftypefnx {} {[@dots{}] =} sqp (@var{x0}, @var{phi}, @var{g}, @var{h})\n## @deftypefnx {} {[@dots{}] =} sqp (@var{x0}, @var{phi}, @var{g}, @var{h}, @var{lb}, @var{ub})\n## @deftypefnx {} {[@dots{}] =} sqp (@var{x0}, @var{phi}, @var{g}, @var{h}, @var{lb}, @var{ub}, @var{maxiter})\n## @deftypefnx {} {[@dots{}] =} sqp (@var{x0}, @var{phi}, @var{g}, @var{h}, @var{lb}, @var{ub}, @var{maxiter}, @var{tolerance})\n## Minimize an objective function using sequential quadratic programming (SQP).\n##\n## Solve the nonlinear program\n## @tex\n## $$\n## \\min_x \\phi (x)\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## min phi (x)\n##  x\n## @end group\n## @end example\n##\n## @end ifnottex\n## subject to\n## @tex\n## $$\n##  g(x) = 0 \\qquad h(x) \\geq 0 \\qquad lb \\leq x \\leq ub\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## g(x)  = 0\n## h(x) >= 0\n## lb <= x <= ub\n## @end group\n## @end example\n##\n## @end ifnottex\n## @noindent\n## using a sequential quadratic programming method.\n##\n## The first argument is the initial guess for the vector @var{x0}.\n##\n## The second argument is a function handle pointing to the objective function\n## @var{phi}.  The objective function must accept one vector argument and\n## return a scalar.\n##\n## The second argument may also be a 2- or 3-element cell array of function\n## handles.  The first element should point to the objective function, the\n## second should point to a function that computes the gradient of the\n## objective function, and the third should point to a function that computes\n## the Hessian of the objective function.  If the gradient function is not\n## supplied, the gradient is computed by finite differences.  If the Hessian\n## function is not supplied, a BFGS update formula is used to approximate the\n## Hessian.\n##\n## When supplied, the gradient function @code{@var{phi}@{2@}} must accept one\n## vector argument and return a vector.  When supplied, the Hessian function\n## @code{@var{phi}@{3@}} must accept one vector argument and return a matrix.\n##\n## The third and fourth arguments @var{g} and @var{h} are function handles\n## pointing to functions that compute the equality constraints and the\n## inequality constraints, respectively.  If the problem does not have\n## equality (or inequality) constraints, then use an empty matrix ([]) for\n## @var{g} (or @var{h}).  When supplied, these equality and inequality\n## constraint functions must accept one vector argument and return a vector.\n##\n## The third and fourth arguments may also be 2-element cell arrays of\n## function handles.  The first element should point to the constraint\n## function and the second should point to a function that computes the\n## gradient of the constraint function:\n## @tex\n## $$\n##  \\Bigg( {\\partial f(x) \\over \\partial x_1},\n##         {\\partial f(x) \\over \\partial x_2}, \\ldots,\n##         {\\partial f(x) \\over \\partial x_N} \\Bigg)^T\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##             [ d f(x)   d f(x)        d f(x) ]\n## transpose ( [ ------   -----   ...   ------ ] )\n##             [  dx_1     dx_2          dx_N  ]\n## @end group\n## @end example\n##\n## @end ifnottex\n## The fifth and sixth arguments, @var{lb} and @var{ub}, contain lower and\n## upper bounds on @var{x} and when provided must be vectors of the same size\n## as the vector @var{x0}.  The bounds must be consistent with the\n## equality and inequality constraints @var{g} and @var{h}.\n##\n## The seventh argument @var{maxiter} specifies the maximum number of\n## iterations.  The default value is 100.\n##\n## The eighth argument @var{tolerance} specifies the tolerance for the stopping\n## criteria.  The default value is @code{sqrt (eps)}.\n##\n## The value returned in @var{info} may be one of the following:\n##\n## @table @asis\n## @item 101\n## The algorithm terminated normally.\n## All constraints meet the specified tolerance.\n##\n## @item 102\n## The BFGS update failed.\n##\n## @item 103\n## The maximum number of iterations was reached.\n##\n## @item 104\n## The stepsize has become too small, i.e.,\n## @tex\n## $\\Delta x,$\n## @end tex\n## @ifnottex\n## delta @var{x},\n## @end ifnottex\n## is less than @code{@var{tol} * norm (x)}.\n## @end table\n##\n## An example of calling @code{sqp}:\n##\n## @example\n## function r = g (x)\n##   r = [ sumsq(x)-10;\n##         x(2)*x(3)-5*x(4)*x(5);\n##         x(1)^3+x(2)^3+1 ];\n## endfunction\n##\n## function obj = phi (x)\n##   obj = exp (prod (x)) - 0.5*(x(1)^3+x(2)^3+1)^2;\n## endfunction\n##\n## x0 = [-1.8; 1.7; 1.9; -0.8; -0.8];\n##\n## [x, obj, info, iter, nf, lambda] = sqp (x0, @@phi, @@g, [])\n##\n## x =\n##\n##   -1.71714\n##    1.59571\n##    1.82725\n##   -0.76364\n##   -0.76364\n##\n## obj = 0.053950\n## info = 101\n## iter = 8\n## nf = 10\n## lambda =\n##\n##   -0.0401627\n##    0.0379578\n##   -0.0052227\n## @end example\n##\n## @seealso{qp}\n## @end deftypefn\n\nfunction [x, obj, info, iter, nf, lambda] = sqp (x0, objf, cef, cif, lb, ub, maxiter, tolerance)\n\n  globals = struct (); # data and handles, needed and changed by subfunctions\n\n  if (nargin < 2 || nargin == 5)\n    print_usage ();\n  endif\n\n  if (! isvector (x0))\n    error (\"sqp: X0 must be a vector\");\n  endif\n  if (rows (x0) == 1)\n    x0 = x0';\n  endif\n\n  have_grd = 0;\n  have_hess = 0;\n  if (iscell (objf))\n    switch (numel (objf))\n      case 1\n        obj_fcn = objf{1};\n        obj_grd = @(x, obj) fd_obj_grd (x, obj, obj_fcn);\n      case 2\n        obj_fcn = objf{1};\n        obj_grd = objf{2};\n        have_grd = 1;\n      case 3\n        obj_fcn = objf{1};\n        obj_grd = objf{2};\n        obj_hess = objf{3};\n        have_grd = 1;\n        have_hess = 1;\n      otherwise\n        error (\"sqp: invalid objective function specification\");\n    endswitch\n  else\n    obj_fcn = objf;   # No cell array, only obj_fcn set\n    obj_grd = @(x, obj) fd_obj_grd (x, obj, obj_fcn);\n  endif\n\n  ce_fcn = @empty_cf;\n  ce_grd = @empty_jac;\n  if (nargin > 2)\n    if (iscell (cef))\n      switch (numel (cef))\n        case 1\n          ce_fcn = cef{1};\n          ce_grd = @(x) fd_ce_jac (x, ce_fcn);\n        case 2\n          ce_fcn = cef{1};\n          ce_grd = cef{2};\n        otherwise\n          error (\"sqp: invalid equality constraint function specification\");\n      endswitch\n    elseif (! isempty (cef))\n      ce_fcn = cef;   # No cell array, only constraint equality function set\n      ce_grd = @(x) fd_ce_jac (x, ce_fcn);\n    endif\n  endif\n\n  ci_fcn = @empty_cf;\n  ci_grd = @empty_jac;\n  if (nargin > 3)\n    ## constraint function given by user with possible gradient\n    globals.cif = cif;\n    ## constraint function given by user without gradient\n    globals.cifcn = @empty_cf;\n    if (iscell (cif))\n      if (length (cif) > 0)\n        globals.cifcn = cif{1};\n      endif\n    elseif (! isempty (cif))\n      globals.cifcn = cif;\n    endif\n\n    if (nargin < 5 || (nargin > 5 && isempty (lb) && isempty (ub)))\n      ## constraint inequality function only without any bounds\n      ci_grd = @(x) fd_ci_jac (x, globals.cifcn);\n      if (iscell (cif))\n        switch (length (cif))\n          case 1\n            ci_fcn = cif{1};\n          case 2\n            ci_fcn = cif{1};\n            ci_grd = cif{2};\n          otherwise\n           error (\"sqp: invalid inequality constraint function specification\");\n        endswitch\n      elseif (! isempty (cif))\n        ci_fcn = cif;   # No cell array, only constraint inequality function set\n      endif\n    else\n      ## constraint inequality function with bounds present\n      lb_idx = ub_idx = true (size (x0));\n      ub_grad = - (lb_grad = eye (rows (x0)));\n\n      ## if unspecified set ub and lb to +/-Inf, preserving single type\n      if (isempty (lb))\n        if (isa (x0, \"single\"))\n          lb = - inf (size (x0), \"single\");\n        else\n          lb = - inf (size (x0));\n        endif\n      endif\n\n      if (isvector (lb))\n        lb = lb(:);\n        lb_idx(:) = (lb != -Inf);\n        globals.lb = lb(lb_idx, 1);\n        lb_grad = lb_grad(lb_idx, :);\n      else\n        error (\"sqp: invalid lower bound\");\n      endif\n\n      if (isempty (ub))\n        if (isa (x0, \"single\"))\n          ub = inf (size (x0), \"single\");\n        else\n          ub = inf (size (x0));\n        endif\n      endif\n\n      if (isvector (ub))\n        ub = ub(:);\n        ub_idx(:) = (ub != Inf);\n        globals.ub = ub(ub_idx, 1);\n        ub_grad = ub_grad(ub_idx, :);\n      else\n        error (\"sqp: invalid upper bound\");\n      endif\n\n      if (any (globals.lb > globals.ub))\n        error (\"sqp: upper bound smaller than lower bound\");\n      endif\n      bounds_grad = [lb_grad; ub_grad];\n      ci_fcn = @(x) cf_ub_lb (x, lb_idx, ub_idx, globals);\n      ci_grd = @(x) cigrad_ub_lb (x, bounds_grad, globals);\n    endif\n\n  endif   # if (nargin > 3)\n\n  iter_max = 100;\n  if (nargin > 6 && ! isempty (maxiter))\n    if (isscalar (maxiter) && maxiter > 0 && fix (maxiter) == maxiter)\n      iter_max = maxiter;\n    else\n      error (\"sqp: invalid number of maximum iterations\");\n    endif\n  endif\n\n  tol = sqrt (eps);\n  if (nargin > 7 && ! isempty (tolerance))\n    if (isscalar (tolerance) && tolerance > 0)\n      tol = tolerance;\n    else\n      error (\"sqp: invalid value for TOLERANCE\");\n    endif\n  endif\n\n  ## Initialize variables for search loop\n  ## Seed x with initial guess and evaluate objective function, constraints,\n  ## and gradients at initial value x0.\n  ##\n  ## obj_fcn   -- objective function\n  ## obj_grad  -- objective gradient\n  ## ce_fcn    -- equality constraint functions\n  ## ci_fcn    -- inequality constraint functions\n  ## A == [grad_{x_1} cx_fun, grad_{x_2} cx_fun, ..., grad_{x_n} cx_fun]^T\n  x = x0;\n\n  obj = feval (obj_fcn, x0);\n  globals.nfev = 1;\n\n  if (have_grd)\n    c = feval (obj_grd, x0);\n  else\n    c = feval (obj_grd, x0, obj);\n  endif\n\n  ## Choose an initial NxN symmetric positive definite Hessian approximation B.\n  n = length (x0);\n  if (have_hess)\n    B = feval (obj_hess, x0);\n  else\n    B = eye (n, n);\n  endif\n\n  ce = feval (ce_fcn, x0);\n  F = feval (ce_grd, x0);\n\n  ci = feval (ci_fcn, x0);\n  C = feval (ci_grd, x0);\n\n  A = [F; C];\n\n  ## Choose an initial lambda (x is provided by the caller).\n  lambda = 100 * ones (rows (A), 1);\n\n  qp_iter = 1;\n  alpha = 1;\n\n  info = 0;\n  iter = 0;\n  ## report ();  # Called with no arguments to initialize reporting\n  ## report (iter, qp_iter, alpha, __sqp_nfev__, obj);\n\n  while (++iter < iter_max)\n\n    ## Check convergence.  This is just a simple check on the first\n    ## order necessary conditions.\n    nr_f = rows (F);\n\n    lambda_e = lambda((1:nr_f)');\n    lambda_i = lambda((nr_f+1:end)');\n\n    con = [ce; ci];\n\n    t0 = norm (c - A' * lambda);\n    t1 = norm (ce);\n    t2 = all (ci >= 0);\n    t3 = all (lambda_i >= 0);\n    t4 = norm (lambda .* con);\n\n    ## Normal convergence.  All constraints are satisfied\n    ## and objective has converged.\n    if (t2 && t3 && max ([t0; t1; t4]) < tol)\n      info = 101;\n      break;\n    endif\n\n    ## Compute search direction p by solving QP.\n    g = -ce;\n    d = -ci;\n\n    old_lambda = lambda;\n    [p, obj_qp, INFO, lambda] = qp (x, B, c, F, g, [], [], d, C,\n                                    Inf (size (d)), struct (\"TolX\", tol));\n\n    info = INFO.info;\n\n    ## FIXME: check QP solution and attempt to recover if it has failed.\n    ##        For now, just warn about possible problems.\n\n    id = \"Octave:SQP-QP-subproblem\";\n    switch (info)\n      case 2\n        warning (id, \"sqp: QP subproblem is non-convex and unbounded\");\n      case 3\n        warning (id, \"sqp: QP subproblem failed to converge in %d iterations\",\n                 INFO.solveiter);\n      case 6\n        warning (id, \"sqp: QP subproblem is infeasible\");\n        lambda = old_lambda;  # The return value was size 0x0 in this case.\n    endswitch\n\n    ## Choose mu such that p is a descent direction for the chosen\n    ## merit function phi.\n    [x_new, alpha, obj_new, globals] = ...\n        linesearch_L1 (x, p, obj_fcn, obj_grd, ce_fcn, ci_fcn, lambda, ...\n                       obj, c, globals);\n\n    delx = x_new - x;\n\n    ## Check if step size has become too small (indicates lack of progress).\n    if (norm (delx) < tol * norm (x))\n      info = 104;\n      break;\n    endif\n\n    ## Evaluate objective function, constraints, and gradients at x_new.\n    if (have_grd)\n      c_new = feval (obj_grd, x_new);\n    else\n      c_new = feval (obj_grd, x_new, obj_new);\n    endif\n\n    ce_new = feval (ce_fcn, x_new);\n    F_new = feval (ce_grd, x_new);\n\n    ci_new = feval (ci_fcn, x_new);\n    C_new = feval (ci_grd, x_new);\n\n    A_new = [F_new; C_new];\n\n    ## Set\n    ##\n    ## s = alpha * p\n    ## y = grad_x L (x_new, lambda) - grad_x L (x, lambda})\n\n    y = c_new - c;\n\n    if (! isempty (A))\n      t = ((A_new - A)'*lambda);\n      y -= t;\n    endif\n\n    if (have_hess)\n\n      B = feval (obj_hess, x);\n\n    else\n      ## Update B using a quasi-Newton formula.\n      delxt = delx';\n\n      ## Damped BFGS.  Or maybe we would actually want to use the Hessian\n      ## of the Lagrangian, computed directly?\n      d1 = delxt*B*delx;\n\n      t1 = 0.2 * d1;\n      t2 = delxt*y;\n\n      if (t2 < t1)\n        theta = 0.8*d1/(d1 - t2);\n      else\n        theta = 1;\n      endif\n\n      r = theta*y + (1-theta)*B*delx;\n\n      d2 = delxt*r;\n\n      ## Check if the next BFGS update will work properly.\n      ## If d1 or d2 vanish, the BFGS update will fail.\n      if (d1 == 0 || d2 == 0)\n        info = 102;\n        break;\n      endif\n\n      B = B - B*delx*delxt*B/d1 + r*r'/d2;\n\n    endif\n\n    x = x_new;\n\n    obj = obj_new;\n\n    c = c_new;\n\n    ce = ce_new;\n    F = F_new;\n\n    ci = ci_new;\n    C = C_new;\n\n    A = A_new;\n\n    ## report (iter, qp_iter, alpha, __sqp_nfev__, obj);\n\n  endwhile\n\n  ## Check if we've spent too many iterations without converging.\n  if (iter >= iter_max)\n    info = 103;\n  endif\n\n  nf = globals.nfev;\n\nendfunction\n\n\nfunction [merit, obj, globals] = phi_L1 (obj, obj_fcn, ce_fcn, ci_fcn, ...\n                                         x, mu, globals)\n\n  ce = feval (ce_fcn, x);\n  ci = feval (ci_fcn, x);\n\n  idx = ci < 0;\n\n  con = [ce; ci(idx)];\n\n  if (isempty (obj))\n    obj = feval (obj_fcn, x);\n    globals.nfev += 1;\n  endif\n\n  merit = obj;\n  t = norm (con, 1) / mu;\n\n  if (! isempty (t))\n    merit += t;\n  endif\n\nendfunction\n\n\nfunction [x_new, alpha, obj, globals] = ...\n  linesearch_L1 (x, p, obj_fcn, obj_grd, ce_fcn, ci_fcn, lambda, obj, c, globals)\n\n  ## Choose parameters\n  ##\n  ## eta in the range (0, 0.5)\n  ## tau in the range (0, 1)\n\n  eta = 0.25;\n  tau = 0.5;\n\n  delta_bar = sqrt (eps);\n\n  if (isempty (lambda))\n    mu = 1 / delta_bar;\n  else\n    mu = 1 / (norm (lambda, Inf) + delta_bar);\n  endif\n\n  alpha = 1;\n\n  ce = feval (ce_fcn, x);\n\n  [phi_x_mu, obj, globals] = phi_L1 (obj, obj_fcn, ce_fcn, ci_fcn, x, ...\n                                     mu, globals);\n\n  D_phi_x_mu = c' * p;\n  d = feval (ci_fcn, x);\n  ## only those elements of d corresponding\n  ## to violated constraints should be included.\n  idx = d < 0;\n  t = - norm ([ce; d(idx)], 1) / mu;\n  if (! isempty (t))\n    D_phi_x_mu += t;\n  endif\n\n  while (1)\n    [p1, obj, globals] = phi_L1 ([], obj_fcn, ce_fcn, ci_fcn, ...\n                                 x+alpha*p, mu, globals);\n    p2 = phi_x_mu+eta*alpha*D_phi_x_mu;\n    if (p1 > p2)\n      ## Reset alpha = tau_alpha * alpha for some tau_alpha in the\n      ## range (0, tau).\n      tau_alpha = 0.9 * tau;  # ??\n      alpha = tau_alpha * alpha;\n    else\n      break;\n    endif\n  endwhile\n\n  x_new = x + alpha * p;\n\nendfunction\n\n\nfunction grd = fdgrd (f, x, y0)\n\n  if (! isempty (f))\n    nx = length (x);\n    grd = zeros (nx, 1);\n    deltax = sqrt (eps);\n    for i = 1:nx\n      t = x(i);\n      x(i) += deltax;\n      grd(i) = (feval (f, x) - y0) / deltax;\n      x(i) = t;\n    endfor\n  else\n    grd = zeros (0, 1);\n  endif\n\nendfunction\n\n\nfunction jac = fdjac (f, x)\n\n  nx = length (x);\n  if (! isempty (f))\n    y0 = feval (f, x);\n    nf = length (y0);\n    nx = length (x);\n    jac = zeros (nf, nx);\n    deltax = sqrt (eps);\n    for i = 1:nx\n      t = x(i);\n      x(i) += deltax;\n      jac(:,i) = (feval (f, x) - y0) / deltax;\n      x(i) = t;\n    endfor\n  else\n    jac = zeros  (0, nx);\n  endif\n\nendfunction\n\n\nfunction grd = fd_obj_grd (x, obj, obj_fcn)\n\n  grd = fdgrd (obj_fcn, x, obj);\n\nendfunction\n\n\nfunction res = empty_cf (x)\n\n  res = zeros (0, 1);\n\nendfunction\n\n\nfunction res = empty_jac (x)\n\n  res = zeros (0, length (x));\n\nendfunction\n\n\nfunction jac = fd_ce_jac (x, ce_fcn)\n\n  jac = fdjac (ce_fcn, x);\n\nendfunction\n\n\nfunction jac = fd_ci_jac (x, cifcn)\n\n  ## cifcn = constraint function without gradients and lb or ub\n  jac = fdjac (cifcn, x);\n\nendfunction\n\n\nfunction res = cf_ub_lb (x, lbidx, ubidx, globals)\n  ## function returning constraint evaluated at x, and distance between ub/lb\n  ## and x, when they are specified (otherwise return empty)\n\n  ## inequality constraints\n  if (! isempty (globals.cifcn))\n    ci = feval (globals.cifcn, x);\n  else\n    ci = [];\n  endif\n\n  ## lower bounds\n  if (! isempty (globals.lb))\n    lb = x(lbidx, 1) - globals.lb;\n  else\n    lb = [];\n  endif\n\n  ## upper bounds\n  if (! isempty (globals.ub))\n    ub = globals.ub - x(ubidx, 1);\n  else\n    ub = [];\n  endif\n\n  res = [ci; lb; ub];\n\nendfunction\n\n\nfunction res = cigrad_ub_lb (x, bgrad, globals)\n\n  cigradfcn = @(x) fd_ci_jac (x, globals.cifcn);\n\n  if (iscell (globals.cif) && length (globals.cif) > 1)\n    cigradfcn = globals.cif{2};\n  endif\n\n  if (isempty (cigradfcn))\n    res = bgrad;\n  else\n    res = [feval(cigradfcn,x); bgrad];\n  endif\n\nendfunction\n\n## Utility function used to debug sqp\nfunction report (iter, qp_iter, alpha, nfev, obj)\n\n  if (nargin == 0)\n    printf (\"  Itn ItQP     Step  Nfev     Objective\\n\");\n  else\n    printf (\"%5d %4d %8.1g %5d %13.6e\\n\", iter, qp_iter, alpha, nfev, obj);\n  endif\n\nendfunction\n\n\n################################################################################\n## Test Code\n\n%!function r = __g (x)\n%!  r = [sumsq(x)-10;\n%!       x(2)*x(3)-5*x(4)*x(5);\n%!       x(1)^3+x(2)^3+1 ];\n%!endfunction\n%!\n%!function obj = __phi (x)\n%!  obj = exp (prod (x)) - 0.5*(x(1)^3 + x(2)^3 + 1)^2;\n%!endfunction\n%!\n%!test\n%!\n%! x0 = [-1.8; 1.7; 1.9; -0.8; -0.8];\n%!\n%! [x, obj, info, iter, nf, lambda] = sqp (x0, @__phi, @__g, []);\n%!\n%! x_opt = [-1.717143501952599;\n%!           1.595709610928535;\n%!           1.827245880097156;\n%!          -0.763643103133572;\n%!          -0.763643068453300];\n%!\n%! obj_opt = 0.0539498477702739;\n%!\n%! assert (x, x_opt, 10 * sqrt (eps));\n%! assert (obj, obj_opt, sqrt (eps));\n\n## Test input validation\n%!error <Invalid call> sqp ()\n%!error <Invalid call> sqp (1)\n%!error <Invalid call> sqp (1,2,3,4,5)\n%!error sqp (ones (2,2))\n%!error sqp (1, cell (4,1))\n%!error sqp (1, cell (3,1), cell (3,1))\n%!error sqp (1, cell (3,1), cell (2,1), cell (3,1))\n%!error sqp (1, cell (3,1), cell (2,1), cell (2,1), ones (2,2),[])\n%!error sqp (1, cell (3,1), cell (2,1), cell (2,1),[], ones (2,2))\n%!error sqp (1, cell (3,1), cell (2,1), cell (2,1),1,-1)\n%!error sqp (1, cell (3,1), cell (2,1), cell (2,1),[],[], ones (2,2))\n%!error sqp (1, cell (3,1), cell (2,1), cell (2,1),[],[],-1)\n%!error sqp (1, cell (3,1), cell (2,1), cell (2,1),[],[],1.5)\n%!error sqp (1, cell (3,1), cell (2,1), cell (2,1),[],[],[], ones (2,2))\n%!error sqp (1, cell (3,1), cell (2,1), cell (2,1),[],[],[],-1)\n"
  },
  {
    "path": "scripts/path/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/path/import.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} import PACKAGE.FUNCTION\n## @deftypefnx {} {} import PACKAGE.CLASS\n## @deftypefnx {} {} import PACKAGE.*\n## @deftypefnx {} {} import\n## @deftypefnx {} {@var{list} =} import\n##\n## Import function or classes into the current scope.\n##\n## @strong{Warning:} This functionality is not yet implemented, and invoking\n## the function will emit an error.\n##\n## When invoked with the name of a PACKAGE and a FUNCTION or CLASS name, that\n## name is made available in the current code without having to use namespace\n## qualifiers.  This can facilitate the readability of the code, and require\n## less typing by programmers.\n##\n## Example\n##\n## @example\n## @group\n## import containers.Map;\n##\n## m = Map (@{\"A\", \"B\"@}, @{[1], [2]@});\n## @end group\n## @end example\n##\n## When called with no inputs and no outputs @code{import} prints a list of\n## any import definitions.\n##\n## When called with no inputs and one output, a cell array of strings\n## @var{list} is returned with any import definitions.\n##\n## @end deftypefn\n\nfunction list = import (varargin)\n\n  error (\"the import function is not yet implemented in Octave\");\n\nendfunction\n\n\n%!error <not yet implemented> import (\"foobar\")\n"
  },
  {
    "path": "scripts/path/matlabroot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{dir} =} matlabroot ()\n## Return the name of the top-level Octave installation directory.\n##\n## This is an alias for the function @w{@code{OCTAVE_HOME}}@ provided for\n## compatibility.\n## @seealso{OCTAVE_HOME}\n## @end deftypefn\n\nfunction dir = matlabroot ()\n\n  dir = OCTAVE_HOME ();\n\nendfunction\n\n\n%!assert (matlabroot (), OCTAVE_HOME ())\n"
  },
  {
    "path": "scripts/path/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/getsavepath.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/import.m \\\n  %reldir%/matlabroot.m \\\n  %reldir%/pathdef.m \\\n  %reldir%/savepath.m\n\n%canon_reldir%dir = $(fcnfiledir)/path\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/path/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/path/pathdef.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{val} =} pathdef ()\n## Return the default path for Octave.\n##\n## The path information is extracted from one of four sources.\n## The possible sources, in order of preference, are:\n##\n## @enumerate\n## @item @file{.octaverc}\n##\n## @item @file{~/.octaverc}\n##\n## @item @file{<OCTAVE_HOME>/@dots{}/<version>/m/startup/octaverc}\n##\n## @item Octave's path prior to changes by any octaverc file.\n## @end enumerate\n## @seealso{path, addpath, rmpath, genpath, savepath}\n## @end deftypefn\n\nfunction val = pathdef ()\n\n  ## Locate any project-specific .octaverc file.\n  proj_octaverc = fullfile (pwd, \".octaverc\");\n  if (exist (proj_octaverc, \"file\"))\n    proj_path = __extractpath__ (proj_octaverc);\n    if (! isempty (proj_path))\n      val = proj_path;\n      return;\n    endif\n  endif\n\n  ## Locate the user's ~/.octaverc file.\n  user_octaverc = fullfile (\"~\", \".octaverc\");\n  if (exist (user_octaverc, \"file\"))\n    user_path = __extractpath__ (user_octaverc);\n    if (! isempty (user_path))\n      val = user_path;\n      return;\n    endif\n  endif\n\n  ## No user octaverc file, locate the site octaverc file.\n  pathdir = __octave_config_info__ (\"localstartupfiledir\");\n  site_octaverc = fullfile (pathdir, \"octaverc\");\n  site_path = __extractpath__ (site_octaverc);\n  if (! isempty (site_path))\n    val = site_path;\n    return;\n  endif\n\n  ## No project, user, or site octaverc file.  Use Octave's default.\n  val = __pathorig__ ();\n\nendfunction\n\n## Extract the path information from the script/function @var{file}, created by\n## @file{savepath.m}.  If successful, @code{__extractpath__} returns the path\n## specified in @var{file}.\n\nfunction path = __extractpath__ (savefile)\n\n  [filelines, startline, endline] = getsavepath (savefile);\n  if (startline > 0)\n    tmp = regexprep (filelines(startline+1:endline-1),\n                     \"^.*path \\\\('([^\\']+)'.*$\", \"$1\");\n    path = strjoin (tmp, \":\");\n  else\n    path = \"\";\n  endif\n\nendfunction\n\n\n## Test that pathdef does not contain a newly added directory\n%!test\n%! path_orig = path ();\n%! tmp_dir = tempname ();\n%! unwind_protect\n%!   mkdir (tmp_dir);\n%!   ## Required on Windows to make sure an 8.3 name is converted to full name\n%!   ## which is what is always stored in path().  See bug #59039.\n%!   tmp_dir = canonicalize_file_name (tmp_dir);\n%!   addpath (tmp_dir);\n%!   p1 = path ();\n%!   p2 = pathdef ();\n%!   assert (! isempty (strfind (p1, tmp_dir)));\n%!   assert (isempty (strfind (p2, tmp_dir)));\n%! unwind_protect_cleanup\n%!   sts = rmdir (tmp_dir);\n%!   path (path_orig);\n%! end_unwind_protect\n\n## Test that pathdef does not modify the current load path\n%!test <*51994>\n%! path_orig = path ();\n%! tmp_dir = tempname ();\n%! unwind_protect\n%!   mkdir (tmp_dir);\n%!   tmp_dir = canonicalize_file_name (tmp_dir);\n%!   addpath (tmp_dir);\n%!   path_1 = path ();\n%!   p = pathdef ();\n%!   path_2 = path ();\n%!   assert (path_1, path_2);\n%! unwind_protect_cleanup\n%!   sts = rmdir (tmp_dir);\n%!   path (path_orig);\n%! end_unwind_protect\n\n## Test input validation\n%!error pathdef (1)\n%!error pathdef (\"/\")\n"
  },
  {
    "path": "scripts/path/private/getsavepath.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{filelines}, @var{startline}, @var{endline}] =} getsavepath (@var{file})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [filelines, startline, endline] = getsavepath (file)\n\n  beginstring = \"## Begin savepath auto-created section, do not edit\";\n  endstring   = \"## End savepath auto-created section\";\n\n  ## Read in the file while checking for errors along the way.\n  startline = endline = 0;\n  filelines = {};\n  if (exist (file) == 2)\n    [fid, msg] = fopen (file, \"rt\");\n    if (fid < 0)\n      error (\"getsavepath: could not open file, %s: %s\", file, msg);\n    endif\n    linenum = 0;\n    while (ischar (line = fgetl (fid)))\n      filelines{++linenum} = line;\n      ## Find the first and last lines if they exist in the file.\n      if (strcmp (line, beginstring))\n        startline = linenum;\n      elseif (strcmp (line, endstring))\n        endline = linenum;\n      endif\n    endwhile\n    if (fclose (fid) < 0)\n      error (\"getsavepath: could not close file after reading, %s\", file);\n    endif\n  endif\n\n  ## Verify the file was correctly formatted.\n  if (startline > endline || (startline > 0 && endline == 0))\n    error (\"getsavepath: unable to parse file, %s\", file);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/path/savepath.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} savepath\n## @deftypefnx {} {} savepath @var{file}\n## @deftypefnx {} {@var{status} =} savepath (@dots{})\n## Save the unique portion of the current function search path to @var{file}.\n##\n## The list of folders that are saved in @var{file} does @emph{not} include\n## the folders that are added for Octave's own functions, those that belong to\n## Octave packages (@pxref{XREFpkg,,pkg load}), and those added via command\n## line switches.\n##\n## If @var{file} is omitted, Octave looks in the current directory for a\n## project-specific @file{.octaverc} file in which to save the path\n## information.  If no such file is present then the user's configuration file\n## @file{~/.octaverc} is used.\n##\n## If successful, @code{savepath} returns 0.\n##\n## The @code{savepath} function makes it simple to customize a user's\n## configuration file to restore the working paths necessary for a particular\n## instance of Octave.  Assuming no filename is specified, Octave will\n## automatically restore the saved directory paths from the appropriate\n## @file{.octaverc} file when starting up.  If a filename has been specified\n## then the paths may be restored manually by calling @code{source @var{file}}.\n## @seealso{path, addpath, rmpath, genpath, pathdef}\n## @end deftypefn\n\nfunction status = savepath (file)\n\n  beginstring = \"## Begin savepath auto-created section, do not edit\";\n  endstring   = \"## End savepath auto-created section\";\n\n  ## Use project-specific or user's .octaverc when no file specified\n  if (nargin == 0)\n    file = fullfile (pwd, \".octaverc\");\n    if (! exist (file, \"file\"))\n      file = fullfile (\"~\", \".octaverc\");\n    endif\n  endif\n\n  ## Read in the file\n  [filelines, startline, endline] = getsavepath (file);\n\n  ## Determine where the savepath lines are placed in the file.\n  if (isempty (filelines)\n      || (startline == 1 && endline == length (filelines)))\n    ## savepath is the entire file.\n    pre = post = {};\n  elseif (endline == 0)\n    ## Drop the savepath statements at the end of the file.\n    pre = filelines;\n    post = {};\n  elseif (startline == 1)\n    pre = {};\n    post = filelines(endline+1:end);\n  elseif (endline == length (filelines))\n    pre = filelines(1:startline-1);\n    post = {};\n  else\n    ## Insert in the middle.\n    pre = filelines(1:startline-1);\n    post = filelines(endline+1:end);\n  endif\n\n  ## Write the results.\n  [fid, msg] = fopen (file, \"wt\");\n  if (fid < 0)\n    error (\"savepath: unable to open FILE for writing, %s, %s\", file, msg);\n  endif\n  unwind_protect\n    fprintf (fid, \"%s\\n\", pre{:});\n\n    ## Remove the portion of the path defined via the command line\n    ## and/or the environment.\n    workingpath = parsepath (path);\n    cmd_line_path = parsepath (command_line_path ());\n    octave_path = parsepath (getenv (\"OCTAVE_PATH\"));\n    default_path = pathdef ();\n    if (isempty (default_path))\n      ## This occurs when running octave via run-octave.  In this instance\n      ## the entire path is specified via the command line and pathdef()\n      ## is empty.\n      [~, n] = setdiff (workingpath, octave_path);\n      default_path = cmd_line_path;\n    else\n      [~, n] = setdiff (workingpath, union (cmd_line_path, octave_path));\n      default_path = parsepath (default_path);\n    endif\n    ## This is the path we'd like to preserve when octave is run.\n    path_to_preserve = workingpath(sort (n));\n\n    ## Determine the path to Octave's user and system wide packages.\n    [pkg_user, pkg_system] = pkg (\"list\");\n\n    ## Conversion from cell array of structs to cellarray of strings with the\n    ## unique contents of the fields \"dir\" and \"archprefix\".\n    pkg_path = unique ([cellfun(@(elt) elt.dir,\n                                [pkg_user, pkg_system],\n                                \"uniformoutput\", false);\n                        cellfun(@(elt) elt.archprefix,\n                                [pkg_user, pkg_system],\n                                \"uniformoutput\", false)]);\n\n    ## If there are packages without binaries (or without .m files), their\n    ## \"archprefix\" (or \"dir\") field might be empty.  Remove empty paths before\n    ## trying to match the regular expression in the next step.\n    pkg_path(cellfun ('isempty', pkg_path)) = [];\n\n    ## Rely on Octave's initialization to include the pkg path elements.\n    for i_pkg = 1:numel (pkg_path)\n      ## Remove all paths that are (sub-)folders of a package folder.\n      pkg_path_pattern = [regexptranslate(\"escape\", pkg_path{i_pkg}), \".*\"];\n      not_pkg_path ...\n        = cellfun ('isempty', regexp (path_to_preserve, pkg_path_pattern));\n      path_to_preserve = path_to_preserve(not_pkg_path);\n    endfor\n\n    ## Split the path to be saved into two groups.  Those path elements that\n    ## belong at the beginning and those at the end.\n    if (! isempty (default_path))\n      n1 = find (strcmp (default_path{1}, path_to_preserve));\n      n2 = find (strcmp (default_path{end}, path_to_preserve));\n      n_middle = round ((n1+n2)/2);\n      [~, n] = setdiff (path_to_preserve, default_path);\n      path_to_save = path_to_preserve(sort (n));\n      ## Remove pwd\n      path_to_save(strcmp (path_to_save, [\".\" pathsep()])) = [];\n      if (! isempty (path_to_save))\n        n = ones (numel (path_to_save), 1);\n        for m = 1:numel (path_to_save)\n          n(m) = find (strcmp (path_to_save{m}, path_to_preserve));\n        endfor\n        path_to_save_begin = path_to_save(n <= n_middle);\n        path_to_save_end   = path_to_save(n > n_middle);\n      else\n        path_to_save_begin = {};\n        path_to_save_end   = {};\n      endif\n    else\n      path_to_save_begin = path_to_preserve;\n      path_to_save_end   = {};\n    endif\n    path_to_save_begin = cell2mat (path_to_save_begin);\n    path_to_save_end   = cell2mat (path_to_save_end);\n\n    ## Use single quotes for PATH argument to avoid string escape\n    ## processing.  Since we are using single quotes around the arg,\n    ## double any single quote characters found in the string.\n    fprintf (fid, \"%s\\n\", beginstring);\n    if (! isempty (path_to_save_begin))\n      n = find (path_to_save_begin != pathsep, 1, \"last\");\n      fprintf (fid, \"  addpath ('%s', '-begin');\\n\",\n               strrep (path_to_save_begin(1:n), \"'\", \"''\"));\n    endif\n    if (! isempty (path_to_save_end))\n      n = find (path_to_save_end != pathsep, 1, \"last\");\n      fprintf (fid, \"  addpath ('%s', '-end');\\n\",\n               strrep (path_to_save_end(1:n), \"'\", \"''\"));\n    endif\n    fprintf (fid, \"%s\\n\", endstring);\n\n    fprintf (fid, \"%s\\n\", post{:});\n  unwind_protect_cleanup\n    sts = fclose (fid);\n    if (sts < 0)\n      error (\"savepath: could not close savefile after writing, %s\", file);\n    elseif (nargin == 0)\n      warning (\"off\", \"backtrace\", \"local\");\n      warning (\"Octave:savepath-local\",\n               \"savepath: current path saved to %s\", file);\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    status = 0;\n  endif\n\nendfunction\n\n## Convert single string of paths to cell array of paths\nfunction path_elements = parsepath (p)\n  path_elements = strcat (ostrsplit (p, pathsep), pathsep);\nendfunction\n\n\n%!test\n%! fname = tempname ();\n%! test_dir = tempname ();\n%! unwind_protect\n%!   if (! mkdir (test_dir))\n%!     error (\"unable to create directory for tests\");\n%!   endif\n%!   status = savepath (fname);\n%!   assert (status == 0);\n%!   old_dir = pwd ();\n%!   unwind_protect\n%!     cd (test_dir);\n%!     if (exist (fullfile (pwd, \".octaverc\")))\n%!       unlink (\".octaverc\");\n%!     endif\n%!     ## Create blank .octaverc file\n%!     fid = fopen (\".octaverc\", \"wt\");\n%!     assert (fid >= 0);\n%!     fclose (fid);\n%!     ## Save path into local .octaverc file\n%!     warning (\"off\", \"Octave:savepath-local\", \"local\");\n%!     status = savepath ();\n%!     assert (status == 0);\n%!     ## Compare old and new versions\n%!     fid = fopen (fname, \"rb\");\n%!     assert (fid >= 0);\n%!     orig_data = fread (fid);\n%!     fclose (fid);\n%!     fid = fopen (\".octaverc\", \"rb\");\n%!     assert (fid >= 0);\n%!     new_data = fread (fid);\n%!     fclose (fid);\n%!     assert (orig_data, new_data);\n%!   unwind_protect_cleanup\n%!     cd (old_dir);\n%!   end_unwind_protect\n%! unwind_protect_cleanup\n%!   confirm_recursive_rmdir (false, \"local\");\n%!   sts = rmdir (test_dir, \"s\");\n%!   unlink (fname);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/pkg/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/pkg/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/build.m \\\n  %reldir%/private/configure_make.m \\\n  %reldir%/private/convert_possible_cell_to_struct.m \\\n  %reldir%/private/default_prefix.m \\\n  %reldir%/private/describe.m \\\n  %reldir%/private/dirempty.m \\\n  %reldir%/private/expand_rel_paths.m \\\n  %reldir%/private/standardize_paths.m \\\n  %reldir%/private/get_description.m \\\n  %reldir%/private/get_inverse_dependencies.m \\\n  %reldir%/private/get_pkg_info.m \\\n  %reldir%/private/get_unsatisfied_deps.m \\\n  %reldir%/private/get_validated_pkg_list.m \\\n  %reldir%/private/getarch.m \\\n  %reldir%/private/getarchdir.m \\\n  %reldir%/private/install.m \\\n  %reldir%/private/installed_packages.m \\\n  %reldir%/private/load_packages.m \\\n  %reldir%/private/load_packages_and_dependencies.m \\\n  %reldir%/private/make_rel_paths.m \\\n  %reldir%/private/rebuild.m \\\n  %reldir%/private/save_order.m \\\n  %reldir%/private/search_packages.m \\\n  %reldir%/private/uninstall.m \\\n  %reldir%/private/unload_packages.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/pkg.m\n\n%canon_reldir%dir = $(fcnfiledir)/pkg\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/pkg/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/pkg/pkg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} pkg @var{command}\n## @deftypefnx {} {} pkg @var{command} @var{pkg_name}\n## @deftypefnx {} {} pkg @var{command} @var{pkg_name1} @var{pkg_name2} @dots{}\n## @deftypefnx {} {} pkg @var{command} @var{option1} @dots{} @var{pkg_name1} @dots{}\n## @deftypefnx {} {[@var{out1}, @dots{}] =} pkg (@var{command}, @dots{})\n## Manage or query packages (groups of add-on functions) for Octave.\n##\n## Depending on the value of @var{command} and on the number of requested\n## return arguments, @code{pkg} can be used to perform several tasks.\n## Possible values for @var{command} are:\n##\n## @table @samp\n##\n## @item search\n## Search for packages having the specified search terms in the Octave Packages\n## index.  This may require an internet connection and the cURL library.\n##\n## @example\n## pkg search foo bar baz\n## @end example\n##\n## @noindent\n## shows packages whose descriptions contain all the search terms.\n##\n## Search terms are case-insensitive and can be regular expressions as well.\n## For example,\n##\n## @example\n## pkg search \"[aeiou]@{4,@}\"\n## @end example\n##\n## @noindent\n## shows all packages whose descriptions have four or more consecutive vowels.\n##\n## The option @option{-all} as in\n##\n## @example\n## pkg search -all\n## @end example\n##\n## @noindent\n## shows @emph{all} packages available on the Octave Packages index (not only\n## those that can be installed with the @command{pkg} command).\n##\n## By default, the Octave Packages index is downloaded only once per Octave\n## session in order to improve performance and to reduce the load on the index\n## server during repeated searches.  An update of the index can be enforced\n## with the option @option{-refresh}:\n##\n## @example\n## pkg search -all -refresh foo\n## @end example\n##\n## If an output variable is provided, as in\n##\n## @example\n## mypackages = pkg (\"search\", \"foo\")\n## @end example\n##\n## @noindent\n## then @code{pkg search} returns only those package names matching the search\n## term(s) @emph{and} which can be installed with @code{pkg install}.\n##\n## @item install\n## Install named packages.  For example, each of the following commands:\n##\n## @example\n## @group\n## pkg install pkgname\n## pkg install 'pkgname-1.0.0.tar.gz'\n## pkg install 'https://somewebsite.org/pkgname-1.0.0.tar.gz'\n## @end group\n## @end example\n##\n## @noindent\n## might install the package @code{pkgname}.  The sequence for the resolution\n## of the arguments after @code{pkg install} is:\n##\n## @enumerate\n## @item\n## If @code{pkgname} is a local file, Octave installs it.\n##\n## @item\n## Otherwise, if @code{pkgname} resembles a URL, Octave downloads and\n## installs it.\n##\n## @item\n## Otherwise, Octave queries the Octave Packages index online for a package\n## named @code{pkgname}, and if found, downloads and installs its latest\n## version.  If the Octave Packages index cannot be reached, a locally cached\n## version of the index might be used.  The Octave Packages index is only\n## downloaded once per Octave session (unless an index refresh is requested\n## with the option @option{-refresh}).\n## @end enumerate\n##\n## Online access requires an internet connection and the cURL library.\n##\n## @noindent\n## @emph{No support}: the GNU Octave community is not responsible for any\n## installed packages.  For support or for reporting bugs, you need to contact\n## the maintainers of the installed package directly (run @code{pkg describe}\n## on the package to get information).\n##\n## The following options are accepted for @code{pkg install}:\n##\n## @table @code\n## @item -nodeps\n## Disable dependency checking.  With this option it is possible to install a\n## package even when it depends on another package which is not installed on\n## the system.  @strong{Use this option with care.}\n##\n## @item -local\n## A local installation (package available only to current user) is forced,\n## even if Octave is being run with administrative privileges.\n##\n## @item -global\n## Force a global installation (package available to all users), even if\n## Octave is not being run with administrative privileges.  The user must have\n## write access to the global package store.\n##\n## @item -verbose\n## Print the output of all commands as they are performed.\n##\n## @item -refresh\n## Force an update of the cached package database from the online index.  By\n## default, Octave tries to download the Octave Packages index only once per\n## Octave session.  This option forces refreshing the index even if it was\n## already downloaded in the current Octave session.  The option\n## @option{-refresh} applies to @code{install}, @code{search}, and\n## @code{update} commands.\n##\n## @item -forge\n## The option @option{-forge} forces an installation of a package from the\n## Octave Packages index.  It cannot be used to install packages from a URL or\n## a local file.  It implies @option{-refresh}.\n## @end table\n##\n## If the package tarball contains a @file{configure} script, it is run during\n## the installation of the package.  If it contains a @file{Makefile}, the\n## command @command{make} is used by default.  It is possible to override the\n## default command with the environment variable @env{MAKE}.  Some Octave\n## packages might require GNU @command{make} which may be present under a\n## different name such as @command{gmake}.\n##\n## @item update\n## Check installed Octave packages against the latest version on the Octave\n## Packages index and update any outdated items.  Updated packages are\n## installed either globally or locally depending on whether Octave is running\n## with elevated privileges.  This requires an internet connection and the cURL\n## library.\n##\n## Options for the install command and the names of individual packages to be\n## checked for updates may be specified as a list following the update command.\n## If the option @option{-local} or @option{-global} is specified,\n## @code{pkg update} limits the update check to the local or global installed\n## packages, and installs updates in that same context.  For example,\n##\n## Update all packages:\n##\n## @example\n## pkg update\n## @end example\n##\n## Update all local packages:\n##\n## @example\n## pkg update -local\n## @end example\n##\n## Update certain packages, ignore dependencies, max verbosity:\n##\n## @example\n## pkg update -verbose -nodeps image signal geometry\n## @end example\n##\n## @noindent\n## Updates for multiple packages are sorted alphabetically and not checked\n## for dependencies affected by installation order.  If a dependency order\n## related @code{pkg update} failure occurs, use @code{pkg update -nodeps} to\n## ignore dependencies, or @code{pkg install <package_name>} to update\n## individual packages manually.\n##\n## @item uninstall\n## Uninstall named packages.  For example,\n##\n## @example\n## pkg uninstall image\n## @end example\n##\n## @noindent\n## removes the @code{image} package from the system.  If another installed\n## package depends on the @code{image} package an error is issued.  The package\n## removal can be forced by using the @option{-nodeps} option.\n##\n## Depending on whether Octave is being run with administrative privileges\n## only global or local packages are removed by default.  See @option{-global}\n## or @option{-local} to override that default behavior.\n##\n## @item load\n## Add named packages to the path.  After loading a package it is possible to\n## use the functions provided by the package.  For example,\n##\n## @example\n## pkg load image\n## @end example\n##\n## @noindent\n## adds the @code{image} package to the path.\n##\n## Note: When loading a package, @code{pkg} automatically tries to load any\n## unloaded dependencies as well, unless the @option{-nodeps} flag has been\n## specified.  For example,\n##\n## @example\n## pkg load signal\n## @end example\n##\n## @noindent\n## adds the @code{signal} package and also tries to load its dependency: the\n## @code{control} package.  Be aware that use of the @option{-nodeps} option\n## can adversely affect package functionality.\n##\n## @item unload\n## Remove named packages from the path.  After unloading a package it is no\n## longer possible to use the functions provided by the package.  Trying to\n## unload a package that other loaded packages still depend on causes an error;\n## no packages are unloaded in this case.  A package can be forcibly unloaded\n## with the @option{-nodeps} flag, at the risk of breaking dependent packages\n## that are still loaded.\n##\n## @item list\n## Show the list of currently installed packages.  For example,\n##\n## @example\n## pkg list\n## @end example\n##\n## @noindent\n## will produce a short report with the package name, version, and installation\n## directory for each installed package.  Supply a package name to limit\n## reporting to a particular package.  For example:\n##\n## @example\n## pkg list image\n## @end example\n##\n## If a single return argument is requested then @code{pkg} returns a cell\n## array where each element is a structure with information on a single\n## package.\n##\n## @example\n## installed_packages = pkg (\"list\")\n## @end example\n##\n## If two output arguments are requested @code{pkg} splits the list of\n## installed packages into those which were installed by the current user\n## (local packages), and those which were installed by the system administrator\n## (global packages).\n##\n## @example\n## [user_packages, system_packages] = pkg (\"list\")\n## @end example\n##\n## The option @option{-forge} lists all packages available on the Octave\n## Packages index that can be installed with the @code{pkg} command.  This\n## requires an internet connection and the cURL library.  This also updates the\n## locally cached file of the Octave Packages index.  Calling\n##\n## @example\n## octave_packages = pkg (\"list\", \"-forge\")\n## @end example\n##\n## @noindent\n## is identical to calling\n##\n## @example\n## octave_packages = pkg (\"search\", \"-refresh\", \"-all\")\n## @end example\n##\n## @item describe\n## Show a short description of installed packages.  With the option\n## @qcode{\"-verbose\"} also list functions provided by the package.  For\n## example,\n##\n## @example\n## pkg describe -verbose\n## @end example\n##\n## @noindent\n## describes all installed packages and the functions they provide.\n##\n## The result can be limited to a set of packages:\n##\n## @example\n## @group\n## ## describe control and signal packages\n## pkg describe control signal\n## @end group\n## @end example\n##\n## If one output is requested a cell of structure containing the\n## description and list of functions of each package is returned as\n## output rather than printed on screen:\n##\n## @example\n## desc = pkg (\"describe\", \"secs1d\", \"image\")\n## @end example\n##\n## @noindent\n## If any of the requested packages is not installed, @code{pkg} returns an\n## error, unless a second output is requested:\n##\n## @example\n## [desc, flag] = pkg (\"describe\", \"secs1d\", \"image\")\n## @end example\n##\n## @noindent\n## @var{flag} takes one of the values @qcode{\"Not installed\"},\n## @qcode{\"Loaded\"}, or @qcode{\"Not loaded\"} for each of the named packages.\n##\n## @item prefix\n## Set the installation prefix directory.  For example,\n##\n## @example\n## pkg prefix ~/my_octave_packages\n## @end example\n##\n## @noindent\n## sets the installation prefix to @file{~/my_octave_packages}.\n##\n## Packages are installed in this directory.\n##\n## Giving an output argument returns the current installation prefix.\n## For example:\n##\n## @example\n## pfx = pkg (\"prefix\")\n## @end example\n##\n## The location in which to install the architecture dependent files can be\n## independently specified with an additional argument.  For example:\n##\n## @example\n## pkg prefix ~/my_octave_packages ~/my_arch_dep_pkgs\n## @end example\n##\n## @item local_list\n## Set the file in which to look for information on locally installed\n## packages.  Locally installed packages are those that are typically available\n## only to the current user.  For example:\n##\n## @example\n## pkg local_list ~/.octave_packages\n## @end example\n##\n## Get the current value of local_list with\n##\n## @example\n## pkg local_list\n## @end example\n##\n## @item global_list\n## Set the file in which to look for information on globally installed\n## packages.  Globally installed packages are those that are typically\n## available to all users.  For example:\n##\n## @smallexample\n## pkg global_list /usr/share/octave/site/api-v59/octave_packages\n## @end smallexample\n##\n## Get the current value of global_list with\n##\n## @example\n## pkg global_list\n## @end example\n##\n## @item build\n## Build a binary form of a package or packages.  The binary file produced\n## is itself an Octave package that can be installed normally with @code{pkg}.\n## For example:\n##\n## @example\n## pkg build builddir image-1.0.0.tar.gz @dots{}\n## @end example\n##\n## @noindent\n## where @code{builddir} is a directory where the binary packages are built.\n## The options @option{-verbose} and @option{-nodeps} are respected, while\n## all other options are ignored.\n##\n## @item rebuild\n## Rebuild the package database from the installed global and local packages.\n## This can be used in cases where the package database has been corrupted.\n##\n## @item test\n## Perform the built-in self tests contained in all functions provided by\n## the named packages.  For example:\n##\n## @example\n## pkg test image\n## @end example\n##\n## @end table\n## @seealso{ver, news}\n## @end deftypefn\n\nfunction [local_packages, global_packages] = pkg (varargin)\n\n  ## Installation prefix\n  persistent user_prefix = false;\n  persistent prefix = false;\n  persistent archprefix = -1;\n  persistent local_list = fullfile (user_config_dir (), \"octave\", ...\n                                    __octave_config_info__ (\"api_version\"), ...\n                                    \"octave_packages\");\n  persistent global_list = fullfile (__octave_config_info__ (\"localapipkgdir\"),\n                                     \"octave_packages\");\n\n  ## If user is superuser (posix) or the process has elevated rights (Windows),\n  ## set global_install to true.\n  if (ispc ())\n    global_install = __is_elevated_process__ ();\n  else\n    global_install = (geteuid () == 0);\n  endif\n\n  if (! user_prefix)\n    [prefix, archprefix] = default_prefix (global_install);\n    prefix = tilde_expand (prefix);\n    archprefix = tilde_expand (archprefix);\n  endif\n\n  mlock ();\n\n  confirm_recursive_rmdir (false, \"local\");\n\n  ## valid actions in alphabetical order\n  available_actions = {\"build\", \"describe\", \"global_list\",  \"install\", ...\n                       \"list\", \"load\", \"local_list\", \"prefix\", \"rebuild\", ...\n                       \"search\", \"test\", \"uninstall\", \"unload\", \"update\"};\n\n  ## Parse input arguments\n  if (isempty (varargin) || ! iscellstr (varargin))\n    print_usage ();\n  endif\n  files = {};\n  deps = true;\n  action = \"none\";\n  verbose = false;\n  octave_forge = false;\n  want_all_packages = false;\n  force_refresh = false;\n  for i = 1:numel (varargin)\n    switch (varargin{i})\n      case \"-nodeps\"\n        deps = false;\n      ## TODO completely remove these warnings after some releases.\n      case \"-noauto\"\n        warning (\"Octave:deprecated-option\",\n                 [\"pkg: autoload is no longer supported.  The -noauto \"...\n                  \"option is no longer required.\\n\"]);\n      case \"-auto\"\n        warning (\"Octave:deprecated-option\",\n                 [\"pkg: autoload is no longer supported.  Add a \"...\n                  \"'pkg load ...' command to octaverc instead.\\n\"]);\n      case \"-verbose\"\n        verbose = true;\n        ## Send verbose output to pager immediately.  Change setting locally.\n        page_output_immediately (true, \"local\");\n      case \"-refresh\"\n        force_refresh = true;\n      case \"-forge\"\n        if (! __octave_config_info__ (\"CURL_LIBS\"))\n          error (\"pkg: can't download from Octave Packages without the cURL library\");\n        endif\n        octave_forge = true;\n        force_refresh = true;\n      case \"-all\"\n        if (! __octave_config_info__ (\"CURL_LIBS\"))\n          error (\"pkg: can't download from Octave Packages without the cURL library\");\n        endif\n        want_all_packages = true;\n      case \"-local\"\n        global_install = false;\n        if (! user_prefix)\n          [prefix, archprefix] = default_prefix (global_install);\n        endif\n      case \"-global\"\n        global_install = true;\n        if (! user_prefix)\n          [prefix, archprefix] = default_prefix (global_install);\n        endif\n      case available_actions\n        if (! strcmp (action, \"none\"))\n          error (\"pkg: more than one action specified\");\n        endif\n        action = varargin{i};\n      otherwise\n        files{end+1} = varargin{i};\n    endswitch\n  endfor\n\n  if (octave_forge)\n    if (strcmp (action, \"install\"))\n      ## Do nothing.\n    elseif (strcmp (action, \"list\"))\n      ## Proceed as though user has invoked \"pkg search -refresh -all\"\n      action = \"search\";\n      want_all_packages = true;\n    else\n      error (\"pkg: action '%s' does not accept option '-forge'\", action);\n    endif\n  endif\n\n  if (want_all_packages)\n    if (! strcmp (action, \"search\"))\n      error (\"pkg: option '-all' is only available for action 'search'\");\n    elseif (! isempty (files))\n      error (\"pkg: cannot specify extra search terms with option '-all'\");\n    endif\n  endif\n\n  ## Take action\n  switch (action)\n    case \"list\"\n      if (nargout == 1)\n        local_packages = installed_packages (local_list, global_list, files);\n      elseif (nargout > 1)\n        [local_packages, global_packages] = installed_packages (local_list,\n                                                                global_list,\n                                                                files);\n      else\n        installed_packages (local_list, global_list, files);\n      endif\n\n    case \"search\"\n      if (! want_all_packages && isempty (files))\n        error (\"pkg: search action requires at least one search term or '-all'\");\n      endif\n\n      ## Pre-load package database (respecting force_refresh flag)\n      get_validated_pkg_list (force_refresh, verbose);\n\n      if (nargout)\n        local_packages = search_packages (files, want_all_packages, verbose);\n      else\n        search_packages (files, want_all_packages, verbose);\n      endif\n\n    case \"install\"\n      if (isempty (files))\n        error (\"pkg: install action requires at least one filename\");\n      endif\n\n      if (octave_forge)\n        needs_pkg_lookup = true;\n      else\n        ## Pre-load package database only if needed for package name lookups.\n        ## Check if any files require online lookup (not local files nor URLs).\n        needs_pkg_lookup = false;\n        for file = files\n          file = char (file);\n          if (! isfile (file) && isempty (regexp (file, '^\\w+://')))\n            needs_pkg_lookup = true;\n            break;\n          endif\n        endfor\n      endif\n\n      if (needs_pkg_lookup)\n        get_validated_pkg_list (force_refresh, verbose);\n      endif\n\n      local_files = {};\n      tmp_dir = tempname ();\n      unwind_protect\n\n        [success, msg] = mkdir (tmp_dir);\n        if (! success)\n          error (\"pkg: failed to create temporary directory: %s\", msg);\n        endif\n\n        for file = files  # process each of the inputs one at a time\n\n          file = char (file);  # convert cell to char string\n\n          ## Sequence: local file, then URL, then package_name.\n          if (! octave_forge && isfile (file))\n\n            ## Do nothing extra; \"files\" does not need to change.\n\n          elseif (! octave_forge && regexp (file, '^\\w+://'))\n            ## looks like a URL\n\n            ## Make a temp file from the URL.\n            [~, fname, fext] = fileparts (file);\n            tmp_file = fullfile (tmp_dir, [fname fext]);\n            local_files(end+1) = {tmp_file};  # so that it gets cleaned up\n\n            ## Download the URL into the temp file we just created.\n            [~, success, msg] = urlwrite (file, tmp_file);\n            if (! success)\n              error (\"pkg: failed to download '%s': %s\", file, msg);\n            endif\n\n            ## Replace the URL provided with the file we just downloaded.\n            files(strcmp (files, file)) = {tmp_file};\n\n          else\n            ## either with option '-forge' or not a local file, not a URL\n            ## ==> try package name\n\n            ## Get corresponding URL and make a temp file.\n            ## FIXME: Automate filetype recognition instead of adding \".tar.gz\"\n            ## manually, just in case the package author chooses zip\n            ## or any other archive format? Or will all packages always\n            ## be required to give .tar.gz?\n            [v, url, sha256_online] = get_pkg_info (file);\n            tmp_file = tempname (tmp_dir, [file \"-\" v \"-\"]);\n            tmp_file = [tmp_file, \".tar.gz\"];\n            local_files(end+1) = {tmp_file};  # so that it gets cleaned up\n\n            if (verbose)\n              printf (\"downloading tarball from:\\n- %s\\n\", url);\n            endif\n\n            ## Download the URL into the temp file we just created.\n            [~, success, msg] = urlwrite (url, tmp_file);\n            if (! success)\n              error (\"pkg: failed to download '%s': %s\", url, msg);\n            endif\n\n            ## Check sha256 checksum, unless it is a 'dev' version\n            if (! strcmp (v, \"dev\"))\n              if (verbose)\n                printf (\"comparing hash... \");\n              endif\n\n              sha256_local = hash (\"sha256\", fileread (tmp_file));\n\n              if (! strcmp (sha256_online, sha256_local))\n                if (verbose)\n                  printf (\"FAILED!\\n\");\n                endif\n                error (\"pkg: downloaded package is corrupt:\\n- sha256: %s\", ...\n                       sha256_local);\n              elseif (verbose)\n                printf (\"verified!\\n\");\n              endif\n            endif\n\n            ## Replace the URL provided with the file we just downloaded.\n            files(strcmp (files, file)) = {tmp_file};\n\n          endif\n        endfor\n\n        ## make sure the PREFIX and the ARCHPREFIX directories are created\n        if (! isfolder (prefix))\n          mkdir (prefix);\n        endif\n        if (! isfolder (archprefix))\n          mkdir (archprefix);\n        endif\n\n        install (files, deps, prefix, archprefix, verbose, local_list,\n                 global_list, global_install);\n\n      unwind_protect_cleanup\n        [~] = cellfun (\"unlink\", local_files);\n        if (exist (tmp_dir, \"file\"))\n          [~] = rmdir (tmp_dir, \"s\");\n        endif\n      end_unwind_protect\n\n    case \"uninstall\"\n      if (isempty (files))\n        error (\"pkg: uninstall action requires at least one package name\");\n      endif\n      uninstall (files, deps, verbose, local_list, global_list, global_install);\n\n    case \"load\"\n      if (isempty (files))\n        error (\"pkg: load action requires at least one package name\");\n      endif\n      load_packages (files, deps, local_list, global_list);\n\n    case \"unload\"\n      if (isempty (files))\n        error (\"pkg: unload action requires at least one package name\");\n      endif\n      unload_packages (files, deps, local_list, global_list);\n\n    case \"prefix\"\n      if (isempty (files) && ! nargout)\n        printf (\"Installation prefix:             %s\\n\", prefix);\n        printf (\"Architecture dependent prefix:   %s\\n\", archprefix);\n      elseif (isempty (files) && nargout)\n        local_packages = prefix;\n        global_packages = archprefix;\n      elseif (numel (files) >= 1 && ischar (files{1}))\n        prefix = tilde_expand (files{1});\n        local_packages = prefix = make_absolute_filename (prefix);\n        user_prefix = true;\n        if (numel (files) >= 2 && ischar (files{2}))\n          archprefix = make_absolute_filename (tilde_expand (files{2}));\n        endif\n      else\n        error (\"pkg: prefix action requires a directory input, or an output argument\");\n      endif\n\n    case \"local_list\"\n      if (isempty (files) && ! nargout)\n        disp (local_list);\n      elseif (isempty (files) && nargout)\n        local_packages = local_list;\n      elseif (numel (files) == 1 && ! nargout && ischar (files{1}))\n        local_list = tilde_expand (files{1});\n        if (! exist (local_list, \"file\"))\n          try\n            ## Force file to be created\n            fclose (fopen (local_list, \"wt\"));\n          catch\n            error (\"pkg: cannot create file %s\", local_list);\n          end_try_catch\n        endif\n        local_list = canonicalize_file_name (local_list);\n      else\n        error (\"pkg: specify a local_list file, or request an output argument\");\n      endif\n\n    case \"global_list\"\n      if (isempty (files) && ! nargout)\n        disp (global_list);\n      elseif (isempty (files) && nargout)\n        local_packages = global_list;\n      elseif (numel (files) == 1 && ! nargout && ischar (files{1}))\n        global_list = files{1};\n        if (! exist (global_list, \"file\"))\n          try\n            ## Force file to be created\n            fclose (fopen (files{1}, \"wt\"));\n          catch\n            error (\"pkg: cannot create file %s\", global_list);\n          end_try_catch\n        endif\n        global_list = canonicalize_file_name (global_list);\n      else\n        error (\"pkg: specify a global_list file, or request an output argument\");\n      endif\n\n    case \"rebuild\"\n      if (global_install)\n        global_packages = rebuild (prefix, archprefix, global_list, files,\n                                   verbose);\n        global_packages = save_order (global_packages);\n        if (ispc)\n          ## On Windows ensure LFN paths are saved rather than 8.3 style paths\n          global_packages = standardize_paths (global_packages);\n        endif\n        global_packages = make_rel_paths (global_packages);\n        global_list_dir = fileparts (global_list);\n        if (! isempty (global_list_dir) && ! exist (global_list_dir, \"dir\"))\n          mkdir (global_list_dir);\n        endif\n        save (global_list, \"global_packages\");\n        if (nargout)\n          local_packages = global_packages;\n        endif\n      else\n        local_packages = rebuild (prefix, archprefix, local_list, files,\n                                  verbose);\n        local_packages = save_order (local_packages);\n        if (ispc)\n          local_packages = standardize_paths (local_packages);\n        endif\n        local_list_dir = fileparts (local_list);\n        if (! isempty (local_list_dir) && ! exist (local_list_dir, \"dir\"))\n          mkdir (local_list_dir);\n        endif\n        save (local_list, \"local_packages\");\n        if (! nargout)\n          clear (\"local_packages\");\n        endif\n      endif\n\n    case \"build\"\n      if (numel (files) < 2)\n        error (\"pkg: build action requires build directory and at least one filename\");\n      endif\n      build (files{1}, files(2:end), verbose);\n\n    case \"describe\"\n      ## FIXME: name of the output variables is inconsistent with their content\n      if (nargout)\n        [local_packages, global_packages] = describe (files, verbose,\n                                                      local_list, global_list);\n      else\n        describe (files, verbose, local_list, global_list);\n      endif\n\n    case \"update\"\n      installed_pkgs_lst = installed_packages (local_list, global_list);\n\n      ## If -global or -local, limit updates to global or local list pkgs\n      globalflag = any (strcmp (varargin, \"-global\"));\n      localflag = any (strcmp (varargin, \"-local\"));\n      if (globalflag || localflag)\n        if (globalflag && localflag)\n          error (\"pkg: cannot specify both global and local options.\");\n        elseif (globalflag)\n          [~, installed_pkgs_lst] = installed_packages (local_list, global_list);\n        else\n          [installed_pkgs_lst, ~] = installed_packages (local_list, global_list);\n        endif\n      else\n        installed_pkgs_lst = installed_packages (local_list, global_list);\n      endif\n\n      ## Explicit list of packages to update, rather than all packages\n      if (numel (files) > 0)\n        update_lst = {};\n        installed_names = cellfun (@(idx) idx.name, installed_pkgs_lst,\n                                   \"UniformOutput\", false);\n        for i = 1:numel (files)\n          idx = find (strcmp (files{i}, installed_names), 1);\n          if (isempty (idx))\n            warning (\"pkg: package %s is not installed - skipping update\\n\",\n                     files{i});\n          else\n            update_lst = [ update_lst, installed_pkgs_lst(idx) ];\n          endif\n        endfor\n        installed_pkgs_lst = update_lst;\n      endif\n\n      ## Pre-load package database once (respecting force_refresh flag)\n      ## This prevents repeated downloads in the loop below\n      get_validated_pkg_list (force_refresh, verbose);\n\n      for i = 1:numel (installed_pkgs_lst)\n        installed_pkg_name = installed_pkgs_lst{i}.name;\n        installed_pkg_version = installed_pkgs_lst{i}.version;\n        try\n          ## Use already-loaded package database\n          online_pkg_version = get_pkg_info (installed_pkg_name, verbose);\n        catch\n          warning (\"pkg: package %s not found on Octave Packages - skipping update\\n\",\n                   installed_pkg_name);\n          online_pkg_version = \"0\";\n        end_try_catch\n        if (compare_versions (online_pkg_version, installed_pkg_version, \">\"))\n          ## Pass options but exclude -refresh (we already refreshed once above)\n          options_to_pass = varargin (strncmp (varargin, \"-\", 1));\n          options_to_pass(strcmp (options_to_pass, \"-refresh\")) = [];\n          feval (@pkg, \"install\", options_to_pass{:}, installed_pkg_name);\n        endif\n      endfor\n\n    case \"test\"\n      if (isempty (files))\n        error (\"pkg: test action requires at least one package name\");\n      endif\n      ## Make sure the requested packages are loaded\n      orig_path = path ();\n      load_packages (files, deps, local_list, global_list);\n      ## Test packages one by one\n      installed_pkgs_lst = installed_packages (local_list, global_list, files);\n      unwind_protect\n        for i = 1:numel (installed_pkgs_lst)\n          printf (\"Testing functions in package '%s':\\n\", files{i});\n          installed_pkgs_dirs = {installed_pkgs_lst{i}.dir, ...\n                                 installed_pkgs_lst{i}.archprefix};\n          installed_pkgs_dirs = ...\n            installed_pkgs_dirs (! cellfun ('isempty', installed_pkgs_dirs));\n          ## For local installs installed_pkgs_dirs contains the same subdirs\n          installed_pkgs_dirs = unique (installed_pkgs_dirs);\n          if (! isempty (installed_pkgs_dirs))\n            ## FIXME invoke another test routine once that is available.\n            ## Until then __run_test_suite__.m will do the job fine enough\n            __run_test_suite__ ({installed_pkgs_dirs{:}}, {});\n          endif\n        endfor\n      unwind_protect_cleanup\n        ## Restore load path back to its original value before loading packages\n        path (orig_path);\n      end_unwind_protect\n\n    otherwise\n      error (\"pkg: invalid action.  See 'help pkg' for available actions\");\n  endswitch\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/build.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} build (@var{builddir}, @var{tarballs}, @var{verbose})\n## Prepare binary packages from Octave source packages.\n##\n## Boils down to (for each in @var{tarballs}):\n##\n## @enumerate\n## @item untar the tarball in @var{builddir};\n##\n## @item build anything necessary (configure and make);\n##\n## @item repackage specifying the build arch in the tarball filename.\n## @end enumerate\n##\n## @end deftypefn\n\nfunction build (builddir, tarballs, verbose)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (! isfolder (builddir))\n    warning (\"creating build directory %s\", builddir);\n    [status, msg] = mkdir (builddir);\n    if (status != 1)\n      error (\"could not create installation directory: %s\", msg);\n    endif\n  endif\n\n  for i = 1:numel (tarballs)\n    filelist = unpack (tarballs{i}, builddir);\n\n    ## We want the path for the package root but we can't assume that\n    ## exists in the filelist (see patch #9030).  So we deduce it from\n    ## the path of the DESCRIPTION file (smallest in case there's another\n    ## file named DESCRIPTION somewhere).\n    desc_pos = regexp (filelist, \"DESCRIPTION$\");\n    desc_mask = ! cellfun (\"isempty\", desc_pos);\n    [~, desc_r_idx] = min ([desc_pos{desc_mask}]);\n    desc_path = fullfile (builddir, filelist(desc_mask){desc_r_idx});\n    build_root = desc_path(1:end-12); # do not include the last filesep\n\n    desc = get_description (desc_path);\n\n    ## If there is no configure or Makefile within src/, there is nothing\n    ## to do to prepare a \"binary\" package.  We only repackage to add more\n    ## info to the tarball filename (version and arch).\n    if (! exist (fullfile (build_root, \"src\", \"configure\"), \"file\")\n        && ! exist (fullfile (build_root, \"src\", \"Makefile\"), \"file\"))\n      arch_abi = \"any-none\";\n    else\n      arch_abi = getarch ();\n      configure_make (desc, build_root, verbose);\n      if (exist (fullfile (build_root, \"src\", \"configure\"), \"file\"))\n        unlink (fullfile (build_root, \"src\", \"configure\"));\n      endif\n      if (exist (fullfile (build_root, \"src\", \"Makefile\"), \"file\"))\n        unlink (fullfile (build_root, \"src\", \"Makefile\"));\n      endif\n    endif\n    tar_name = [desc.name \"-\" desc.version \"-\" arch_abi \".tar\"];\n    tar_path = fullfile (builddir, tar_name);\n\n    ## Figure out the directory name of the build.  Note that fileparts\n    ## gets confused with the version string (the periods makes it think\n    ## it's a file extension).\n    [~, package_root, package_ext] = fileparts (build_root);\n    package_root = [package_root, package_ext];\n\n    tar (tar_path, package_root, builddir);\n    gzip (tar_path, builddir);\n    [~] = rmdir (build_root, \"s\");\n\n    ## Currently does nothing because gzip() removes the original tar\n    ## file but that should change in the future (bug #43431).\n    [~] = unlink (tar_path);\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/configure_make.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} configure_make (@var{desc}, @var{packdir}, @var{verbose})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction configure_make (desc, packdir, verbose)\n\n  ## Perform ./configure, make, make install in \"src\".\n  if (isfolder (fullfile (packdir, \"src\")))\n    src = fullfile (packdir, \"src\");\n    octave_bindir = __octave_config_info__ (\"bindir\");\n    ver = version ();\n    ext = __octave_config_info__ (\"EXEEXT\");\n    mkoctfile_program = fullfile (octave_bindir, ...\n                                  sprintf (\"mkoctfile-%s%s\", ver, ext));\n    octave_config_program = fullfile (octave_bindir, ...\n                                      sprintf (\"octave-config-%s%s\", ver, ext));\n    octave_binary = fullfile (octave_bindir, sprintf (\"octave-%s%s\", ver, ext));\n\n    if (! exist (mkoctfile_program, \"file\"))\n      __gripe_missing_component__ (\"pkg\", \"mkoctfile\");\n    endif\n    if (! exist (octave_config_program, \"file\"))\n      __gripe_missing_component__ (\"pkg\", \"octave-config\");\n    endif\n    if (! exist (octave_binary, \"file\"))\n      __gripe_missing_component__ (\"pkg\", \"octave\");\n    endif\n\n    if (ispc () && ! isunix ())\n      ## Replace all backslashes with forward slashes\n      mkoctfile_program = strrep (mkoctfile_program, '\\', '/');\n      octave_config_program = strrep (octave_config_program, '\\', '/');\n      octave_binary = strrep (octave_binary, '\\', '/');\n    endif\n\n    ## Escape spaces in file paths unless they are already escaped\n    mkoctfile_program = regexprep (mkoctfile_program, '([^\\\\]) ', '$1\\\\ ');\n    octave_config_program = regexprep (octave_config_program, ...\n                                       '([^\\\\]) ', '$1\\\\ ');\n    octave_binary = regexprep (octave_binary, '([^\\\\]) ', '$1\\\\ ');\n\n    if (verbose)\n      mkoctfile_program = [mkoctfile_program \" --verbose\"];\n    endif\n\n    cenv = {\"MKOCTFILE\"; mkoctfile_program;\n            \"OCTAVE_CONFIG\"; octave_config_program;\n            \"OCTAVE\"; octave_binary};\n    scenv = sprintf (\"%s='%s' \", cenv{:});\n\n    if (verbose)\n      ## Add standard V=1 make argument for verbose build rules\n      scenv = [scenv, \"V=1\"];\n    endif\n\n    ## Configure.\n    if (exist (fullfile (src, \"configure\"), \"file\"))\n      flags = \"\";\n      if (isempty (getenv (\"CC\")))\n        flags = [flags ' CC=\"' mkoctfile(\"-p\", \"CC\") '\"'];\n      endif\n      if (isempty (getenv (\"CXX\")))\n        flags = [flags ' CXX=\"' mkoctfile(\"-p\", \"CXX\") '\"'];\n      endif\n      if (isempty (getenv (\"AR\")))\n        flags = [flags ' AR=\"' mkoctfile(\"-p\", \"AR\") '\"'];\n      endif\n      if (isempty (getenv (\"RANLIB\")))\n        flags = [flags ' RANLIB=\"' mkoctfile(\"-p\", \"RANLIB\") '\"'];\n      endif\n      cmd = [\"cd '\" src \"'; \" scenv \" ./configure \" flags];\n      [status, output] = shell (cmd, verbose);\n      if (status != 0)\n        disp (output);\n        error (\"pkg: error running the configure script for %s\", desc.name);\n      endif\n    endif\n\n    ## Make.\n    if (ispc ())\n      jobs = 1;\n    else\n      jobs = nproc (\"overridable\");\n    endif\n\n    if (exist (fullfile (src, \"Makefile\"), \"file\"))\n      make_cmd = getenv (\"MAKE\");\n      if (isempty (make_cmd))\n        make_cmd = \"make\";\n      endif\n      [status, output] = shell (sprintf (\"%s %s -j %i -C '%s'\",\n                                         scenv, make_cmd, jobs, src), verbose);\n      if (status != 0)\n        disp (output);\n        error (\"pkg: error running 'make' for the %s package\", desc.name);\n      endif\n    endif\n\n    ## Extract tests from source files which will not to be installed\n    tst_files_src = [];\n    for suffix = {\"*.cc\", \"*.c\", \"*.C\", \"*.cpp\", \"*.cxx\"}\n      tst_files_src = [tst_files_src; ...\n                       nthargout(1, 1, @dir, fullfile (src, suffix{1}))];\n    endfor\n    if (! isempty (tst_files_src))\n      for tst_file_src = {tst_files_src.name}\n        full_tst_file_src = fullfile (src, tst_file_src{1});\n        tst_code = __extract_test_code__ (full_tst_file_src);\n        if (isempty (tst_code))\n          continue;\n        endif\n        full_tst_file = strcat (full_tst_file_src, \"-tst\");\n        if (exist (full_tst_file))\n          continue;\n        endif\n        tst_code = ...\n          [\"## DO NOT EDIT!\\n\", ...\n           \"## Generated automatically from \", tst_file_src{1}, \"\\n\", ...\n           \"## by \", mfilename(), \".m during package installation.\\n\\n\", ...\n           tst_code];\n        [fid, output] = fopen (full_tst_file, \"w\");\n        if (fid == -1)\n          error (\"Octave:pkg:extract-tests\", ...\n                 \"pkg: error writing extracted tests to 'src': %s\", output);\n        endif\n        fputs (fid, tst_code);\n        fclose (fid);\n      endfor\n    endif\n\n  endif\n\nendfunction\n\n## Executes a shell command.\n## In the end it calls system(), but in the case of MS Windows it will first\n## check if sh.exe works.\n##\n## If VERBOSE is true, it will prints the output to STDOUT in real time and\n## the second output argument will be an empty string.  Otherwise, it will\n## contain the output of the execeuted command.\nfunction [status, output] = shell (cmd, verbose)\n  persistent have_sh;\n\n  if (ispc () && ! isunix ())\n    if (isempty (have_sh))\n      if (system ('sh.exe -c \"exit\"'))\n        have_sh = false;\n      else\n        have_sh = true;\n      endif\n    endif\n    if (have_sh)\n      cmd = ['sh.exe -c \"' cmd '\"'];\n    else\n      error (\"pkg: unable to find the command shell\");\n    endif\n  endif\n  ## if verbose, we want to display the output in real time.  To do this, we\n  ## must call system with 1 output argument.  But then the variable 'output'\n  ## won't exist.  So we initialize it empty.  If an error does occur, and we\n  ## are verbose we will return an empty string but it's all fine since\n  ## the error message has already been displayed.\n  output = \"\";\n  if (verbose)\n    [status] = system (cmd);\n  else\n    [status, output] = system (cmd);\n  endif\n\nendfunction\n\nfunction body = __extract_test_code__ (nm)\n\n  ## Collect all BIST lines starting %! from the file named nm\n  ## and return them as a single \\n-delimited string.\n  fid = fopen (nm, \"rt\");\n  body = \"\";\n  if (fid >= 0)\n    while (ischar (ln = fgets (fid)))\n      if (strncmp (ln, \"%!\", 2))\n        body = [body, ln];\n      endif\n    endwhile\n    fclose (fid);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/convert_possible_cell_to_struct.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} @var{retval} = convert_possible_cell_to_struct ()\n## Workaround for a complication that happens with some packages, where a part\n## of the package metadata returned by the server contains a cell array instead\n## of a struct for reasons internal to the server, so this private function\n## is used to work around that unavoidable inconsistency in the metadata\n## format.\n## @end deftypefn\n\nfunction retval = convert_possible_cell_to_struct (obj)\n  if (isstruct (obj))\n    retval = obj;\n  elseif (iscell (obj))\n    retval = obj{1};\n  else\n    error (\"pkg: internal error: obj is neither cell nor struct but type '%s'.\", class (obj));\n  endif\n\n  if (! isstruct (retval))\n    error (\"pkg: internal error: expected retval to be struct but got '%s'.\", class (retval));\n  endif\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/default_prefix.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{prefix}, @var{archprefix} =} default_prefix (@var{global_install}, @var{desc})\n## Undocumented internal function.\n## @end deftypefn\n\n## FIXME: second input \"desc\" does not appear to be used.\nfunction [prefix, archprefix] = default_prefix (global_install, desc)\n\n  if (global_install)\n    prefix = fullfile (OCTAVE_HOME (), \"share\", \"octave\", \"packages\");\n    if (nargin == 2)\n      archprefix = fullfile (__octave_config_info__ (\"libdir\"), \"octave\",\n                             \"packages\", [desc.name \"-\" desc.version]);\n    else\n      archprefix = fullfile (__octave_config_info__ (\"libdir\"), \"octave\",\n                             \"packages\");\n    endif\n  else\n    prefix = fullfile (user_data_dir (), \"octave\", ...\n                       __octave_config_info__ (\"api_version\"), \"packages\");\n    archprefix = prefix;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/describe.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{pkg_desc_list}, @var{flag}] =} describe (@var{pkgnames}, @var{verbose}, @var{local_list}, @var{global_list})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [pkg_desc_list, flag] = describe (pkgnames, verbose, local_list, global_list)\n\n  ## Get the list of installed packages.\n  installed_pkgs_lst = installed_packages (local_list, global_list);\n  num_packages = length (installed_pkgs_lst);\n  ## Add inverse dependencies to \"installed_pkgs_lst\"\n  installed_pkgs_lst = get_inverse_dependencies (installed_pkgs_lst);\n\n  if (isempty (pkgnames))\n    describe_all = true;\n    flag(1:num_packages) = {\"Not Loaded\"};\n    num_pkgnames = num_packages;\n  else\n    describe_all = false;\n    num_pkgnames = length (pkgnames);\n    flag(1:num_pkgnames) = {\"Not installed\"};\n  endif\n\n  for i = 1:num_packages\n    curr_name = installed_pkgs_lst{i}.name;\n    if (describe_all)\n      name_pos = i;\n    else\n      name_pos = find (strcmp (curr_name, pkgnames));\n    endif\n\n    if (! isempty (name_pos))\n      if (installed_pkgs_lst{i}.loaded)\n        flag{name_pos} = \"Loaded\";\n      else\n        flag{name_pos} = \"Not loaded\";\n      endif\n\n      pkg_desc_list{name_pos}.name = installed_pkgs_lst{i}.name;\n      pkg_desc_list{name_pos}.version = installed_pkgs_lst{i}.version;\n      pkg_desc_list{name_pos}.date = installed_pkgs_lst{i}.date;\n      pkg_desc_list{name_pos}.description = installed_pkgs_lst{i}.description;\n      ## Get URLs for package repository and bug tracker, otherwise use a\n      ## default URL pointing to Octave Packages index.\n      if (isfield (installed_pkgs_lst{i}, \"url\"))\n        pkg_desc_list{name_pos}.url = installed_pkgs_lst{i}.url;\n      else\n        ## Note: This is currently (March 2025) hosted on GitHub,\n        ## but the service provider can always change in future, so we try to\n        ## future-proof it a bit by using `packages.octave.org` instead.\n        url = \"https://packages.octave.org/%s\";\n        pkg_desc_list{name_pos}.url = sprintf (url, installed_pkgs_lst{i}.name);\n      endif\n      ## Check for bug tracker, otherwise use the repository's URL.\n      if (isfield (installed_pkgs_lst{i}, \"tracker\"))\n        pkg_desc_list{name_pos}.tracker = installed_pkgs_lst{i}.tracker;\n      else\n        pkg_desc_list{name_pos}.tracker = pkg_desc_list{name_pos}.url;\n      endif\n      pkg_desc_list{name_pos}.depends = installed_pkgs_lst{i}.depends;\n      pkg_desc_list{name_pos}.invdeps = unique (installed_pkgs_lst{i}.invdeps);\n      ## Only if requested (improve speed)\n      if (verbose || nargout > 0)\n        pkg_desc_list{name_pos}.provides = parse_pkg_idx (installed_pkgs_lst{i}.dir);\n      else\n        pkg_desc_list{name_pos}.provides = {};\n      endif\n\n    endif\n  endfor\n\n  non_inst = find (strcmp (flag, \"Not installed\"));\n  if (! isempty (non_inst))\n    if (nargout < 2)\n      non_inst_str = sprintf (\" %s \", pkgnames{non_inst});\n      error (\"some packages are not installed: %s\", non_inst_str);\n    else\n      pkg_desc_list{non_inst} = struct (\"name\", {}, \"description\",\n                                        {}, \"provides\", {});\n    endif\n  endif\n\n  if (nargout == 0)\n    for i = 1:num_pkgnames\n      print_package_description (pkg_desc_list{i}.name,\n                                 pkg_desc_list{i}.version,\n                                 pkg_desc_list{i}.date,\n                                 pkg_desc_list{i}.description,\n                                 pkg_desc_list{i}.url,\n                                 pkg_desc_list{i}.tracker,\n                                 pkg_desc_list{i}.depends,\n                                 pkg_desc_list{i}.invdeps,\n                                 flag{i}, pkg_desc_list{i}.provides);\n    endfor\n  endif\n\nendfunction\n\n\n## Read an INDEX file.\nfunction pkg_idx_struct = parse_pkg_idx (packdir)\n\n  index_file = fullfile (packdir, \"packinfo\", \"INDEX\");\n\n  if (! exist (index_file, \"file\"))\n    error (\"could not find any INDEX file in directory %s, try 'pkg rebuild all' to generate missing INDEX files\", packdir);\n  endif\n\n\n  [fid, msg] = fopen (index_file, \"r\");\n  if (fid == -1)\n    error (\"the INDEX file %s could not be read: %s\",\n           index_file, msg);\n  endif\n\n  cat_num = 1;\n  pkg_idx_struct{1}.category = \"Uncategorized\";\n  pkg_idx_struct{1}.functions = {};\n\n  line = fgetl (fid);\n  while (isempty (strfind (line, \">>\")) && ! feof (fid))\n    line = fgetl (fid);\n  endwhile\n\n  while (! feof (fid) || line != -1)\n    if (! any (! isspace (line)) || line(1) == \"#\" || any (line == \"=\"))\n      ## Comments, blank lines, or comments about unimplemented functions:\n      ## Do nothing\n      ## FIXME: probably comments and pointers to external functions\n      ## could be treated better when printing to screen?\n    elseif (! isempty (strfind (line, \">>\")))\n      ## Skip package name and description as they are in DESCRIPTION\n      ## already.\n    elseif (! isspace (line(1)))\n      ## Category.\n      if (! isempty (pkg_idx_struct{cat_num}.functions))\n        pkg_idx_struct{++cat_num}.functions = {};\n      endif\n      pkg_idx_struct{cat_num}.category = deblank (line);\n    else\n      ## Function names.\n      while (any (! isspace (line)))\n        [fun_name, line] = strtok (line);\n        pkg_idx_struct{cat_num}.functions{end+1} = deblank (fun_name);\n      endwhile\n    endif\n    line = fgetl (fid);\n  endwhile\n  fclose (fid);\n\nendfunction\n\n\nfunction print_package_description (pkg_name, pkg_ver, pkg_date, pkg_desc,\n                                    pkg_url, pkg_tracker, pkg_deps, pkg_invd,\n                                    status, pkg_idx_struct)\n\n  printf (\"---\\nPackage name:\\n\\t%s\\n\", pkg_name);\n  printf (\"Version (date):\\n\\t%s (%s)\\n\", pkg_ver, pkg_date);\n  printf (\"Short description:\\n\\t%s\\n\", pkg_desc);\n  printf (\"Package repository:\\n\\t%s\\n\", pkg_url);\n  printf (\"Please report any issues with the %s package at:\\n\\t%s\\n\",\n          pkg_name, pkg_tracker);\n\n  if (! isempty (pkg_deps))\n    pkg_deps = cellfun (@(d) sprintf (\"%s %s %s\", struct2cell (d){:}), pkg_deps,\n                        \"UniformOutput\", false);\n    pkg_deps = strjoin (pkg_deps, \"\\n\\t\");\n    printf (\"Depends on:\\n\\t%s\\n\", pkg_deps);\n  endif\n\n  pkg_invd = strjoin (pkg_invd, \"\\n\\t\");\n  printf (\"Depended on by:\\n\\t%s\\n\", pkg_invd);\n\n  printf (\"Status:\\n\\t%s\\n\", status);\n  if (! isempty (pkg_idx_struct))\n    printf (\"---\\nProvides:\\n\");\n    for i = 1:length (pkg_idx_struct)\n      if (! isempty (pkg_idx_struct{i}.functions))\n        printf (\"%s\\n\", pkg_idx_struct{i}.category);\n        for j = 1:length (pkg_idx_struct{i}.functions)\n          printf (\"\\t%s\\n\", pkg_idx_struct{i}.functions{j});\n        endfor\n      endif\n    endfor\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/dirempty.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{emp} =} dirempty (@var{nm}, @var{ign})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction emp = dirempty (nm, ign)\n\n  if (isfolder (nm))\n    if (nargin < 2)\n      ign = {\".\", \"..\"};\n    else\n      ign = [{\".\", \"..\"}, ign];\n    endif\n    l = dir (nm);\n    for i = 1:length (l)\n      found = false;\n      for j = 1:length (ign)\n        if (strcmp (l(i).name, ign{j}))\n          found = true;\n          break;\n        endif\n      endfor\n      if (! found)\n        emp = false;\n        return;\n      endif\n    endfor\n    emp = true;\n  else\n    emp = true;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/expand_rel_paths.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{pkg_list} =} expand_rel_paths (@var{pkg_list})\n## Internal undocumented function.\n## @end deftypefn\n\nfunction pkg_list = expand_rel_paths (pkg_list)\n\n  ## Prepend location of OCTAVE_HOME to install directories\n  loc = regexptranslate (\"escape\", OCTAVE_HOME ());\n  for i = 1:numel (pkg_list)\n    ## Be sure to only prepend OCTAVE_HOME to pertinent package paths\n    pkg_list{i}.dir = regexprep (pkg_list{i}.dir, \"^__OH__\", loc);\n    pkg_list{i}.archprefix = regexprep (pkg_list{i}.archprefix, ...\n                                        \"^__OH__\", loc);\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/get_description.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{desc} =} get_description (@var{filename})\n## Undocumented internal function.\n## @end deftypefn\n\n## Parse the DESCRIPTION file.\nfunction desc = get_description (filename)\n\n  [fid, msg] = fopen (filename, \"r\");\n  if (fid == -1)\n    error (\"the DESCRIPTION file %s could not be read: %s\", filename, msg);\n  endif\n\n  desc = struct ();\n\n  line = fgetl (fid);\n  while (line != -1)\n    if (line(1) == \"#\")\n      ## Comments, do nothing.\n    elseif (isspace (line(1)))\n      ## Continuation lines\n      if (exist (\"keyword\", \"var\") && isfield (desc, keyword))\n        desc.(keyword) = [desc.(keyword) \" \" deblank(line)];\n      endif\n    else\n      ## Keyword/value pair\n      colon = find (line == \":\");\n      if (length (colon) == 0)\n        warning (\"pkg: skipping invalid line in DESCRIPTION file\");\n      else\n        colon = colon(1);\n        keyword = lower (strtrim (line(1:colon-1)));\n        value = strtrim (line (colon+1:end));\n        if (length (value) == 0)\n            fclose (fid);\n            error (\"The keyword '%s' of the package '%s' has an empty value\",\n                    keyword, desc.name);\n        endif\n        if (isfield (desc, keyword))\n          warning ('pkg: duplicate keyword \"%s\" in DESCRIPTION, ignoring',\n                   keyword);\n        else\n          desc.(keyword) = value;\n        endif\n      endif\n    endif\n    line = fgetl (fid);\n  endwhile\n  fclose (fid);\n\n  ## Make sure all is okay.\n  needed_fields = {\"name\", \"version\", \"date\", \"title\", ...\n                   \"author\", \"maintainer\", \"description\"};\n  for f = needed_fields\n    if (! isfield (desc, f{1}))\n      error (\"description is missing needed field %s\", f{1});\n    endif\n  endfor\n\n  if (! is_valid_pkg_version_string (desc.version))\n    error (\"invalid version string '%s'\", desc.version);\n  endif\n\n  if (isfield (desc, \"depends\"))\n    desc.depends = fix_depends (desc.depends);\n  else\n    desc.depends = {};\n  endif\n  desc.name = lower (desc.name);\n\nendfunction\n\n\n## Make sure the depends field is of the right format.\n## This function returns a cell of structures with the following fields:\n##   package, version, operator\nfunction deps_cell = fix_depends (depends)\n\n  deps = strtrim (ostrsplit (lower (depends), \",\"));\n  deps_cell = cell (1, length (deps));\n  dep_pat = ...\n  '\\s*(?<name>[-\\w]+)\\s*(\\(\\s*(?<op>[<>=]+)\\s*(?<ver>\\d+\\.\\d+(\\.\\d+)*)\\s*\\))*\\s*';\n\n  ## For each dependency.\n  for i = 1:length (deps)\n    dep = deps{i};\n    [start, nm] = regexp (dep, dep_pat, 'start', 'names');\n    ## Is the dependency specified\n    ## in the correct format?\n    if (! isempty (start))\n      package = lower (strtrim (nm.name));\n      ## Does the dependency specify a version\n      ## Example: package(>= version).\n      if (! isempty (nm.ver))\n        operator = nm.op;\n        if (! any (strcmp (operator, {\">\", \">=\", \"<=\", \"<\", \"==\"})))\n          error (\"unsupported operator: %s\", operator);\n        endif\n        if (! is_valid_pkg_version_string (nm.ver))\n          error (\"invalid dependency version string '%s'\", nm.ver);\n        endif\n      else\n        ## If no version is specified for the dependency\n        ## we say that the version should be greater than\n        ## or equal to \"0.0.0\".\n        package = lower (strtrim (dep));\n        operator = \">=\";\n        nm.ver  = \"0.0.0\";\n      endif\n      deps_cell{i} = struct (\"package\", package,\n                             \"operator\", operator,\n                             \"version\", nm.ver);\n    else\n      error (\"incorrect syntax for dependency '%s' in the DESCRIPTION file\\n\",\n             dep);\n    endif\n  endfor\n\nendfunction\n\nfunction valid = is_valid_pkg_version_string (str)\n\n  ## We are limiting ourselves to this set of characters because the\n  ## version will appear on the filepath.  The portable character, according to\n  ## http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_278\n  ## is [A-Za-z0-9\\.\\_\\-].  However, this is very limited.  We specially\n  ## want to support a \"+\" so we can support \"pkgname-2.1.0+\" during\n  ## development.  So we use Debian's character set for version strings\n  ## https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version\n  ## with the exception of \":\" (colon) because that's the PATH separator.\n  ##\n  ## Debian does not include \"_\" because it is used to separate the name,\n  ## version, and arch in their deb files.  While the actual filenames are\n  ## never parsed to get that information, it is important to have a unique\n  ## separator character to prevent filename clashes.  For example, if we\n  ## used hyhen as separator, \"signal-2-1-rc1\" could be \"signal-2\" version\n  ## \"1-rc1\" or \"signal\" version \"2-1-rc1\".  A package file for both must be\n  ## able to co-exist in the same directory, e.g., during package install or\n  ## in a flat level package repository.\n  valid = numel (regexp (str, '[^0-9a-zA-Z\\.\\+\\-\\~]')) == 0;\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/get_inverse_dependencies.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{installed_pkgs_list} =} get_inverse_dependencies (@var{installed_pkgs_lst})\n## Find inverse dependencies, if any, for each package, and store in\n## the struct field @qcode{\"invdeps\"}.\n##\n## @end deftypefn\n\nfunction installed_pkgs_lst = get_inverse_dependencies (installed_pkgs_lst)\n\n  for i = 1:numel (installed_pkgs_lst)\n    installed_pkgs_lst{i}.invdeps = {};  # initialize invdeps field\n  endfor\n\n  for i = 1:numel (installed_pkgs_lst)\n    pdeps = installed_pkgs_lst{i}.depends;\n    for j = 1:numel (pdeps)\n      pdep_nm = pdeps{j}.package;\n      if (! strcmpi (pdep_nm, \"octave\"))\n        idx = cellfun (@(S) strcmpi (S.name, pdep_nm), installed_pkgs_lst);\n        if (any (idx))\n          installed_pkgs_lst{idx}.invdeps(end+1) = {installed_pkgs_lst{i}.name};\n        endif\n      endif\n    endfor\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/get_pkg_info.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{ver}, @var{url}] =} get_pkg_info (@var{name})\n## @deftypefnx {} {[@var{ver}, @var{url}] =} get_pkg_info (@var{name}, @var{verbose})\n## Return the current version and URL of the Octave package @var{name}.\n##\n## If @var{verbose} is true, print diagnostic messages.\n## @end deftypefn\n\nfunction [ver, url, sha256] = get_pkg_info (name, verbose = false)\n\n  ## Verify that name is valid.\n  if (! (ischar (name) && rows (name) == 1 && ndims (name) == 2))\n    error (\"get_pkg_info: package NAME must be a string\");\n  elseif (! all (isalnum (name) | name == \"-\" | name == \".\" | name == \"_\"))\n    error (\"get_pkg_info: invalid package NAME: %s\", name);\n  endif\n\n  name = lower (name);\n\n  __pkg__ = get_validated_pkg_list (false, verbose);\n  pkgnames = fieldnames (__pkg__);  # all the different packages\n\n  if (any (strcmp (pkgnames, name)))  # named package does exist\n\n    ## If multiple versions, then versions(1) is the most recent version.\n    tmp = convert_possible_cell_to_struct (__pkg__.(name).versions(1));\n    ver = tmp.id;\n    url = tmp.url;\n    sha256 = tmp.sha256;\n\n  else  # no such package in list; offer suggestions with error message.\n\n    ## Try a simplistic method to determine similar names.\n    function d = fdist (x)\n\n      len1 = numel (name);\n      len2 = numel (x);\n      lo = min (len1, len2);\n      excess = max (len1, len2) - lo;\n      d = sum (abs (lower (name(1:lo)) - lower (x(1:lo)))) + excess * 23;\n\n    endfunction\n\n    dist = cellfun (\"fdist\", pkgnames);\n    [~, i] = min (dist);\n    error (\"get_pkg_info: package not found: \"\"%s\"\".  Did you mean \"\"%s\"\"?\", ...\n           name, pkgnames{i});\n\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/get_unsatisfied_deps.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{bad_deps} =} get_unsatisfied_deps (@var{desc}, @var{installed_pkgs_lst}, @var{uninstall_flag})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction bad_deps = get_unsatisfied_deps (desc, installed_pkgs_lst,\n                                          uninstall_flag = false)\n\n  bad_deps = {};\n\n  ## For each dependency.\n  for i = 1:length (desc.depends)\n    dep = desc.depends{i};\n\n    ## Is the current dependency Octave?\n    if (strcmp (dep.package, \"octave\"))\n      if (! compare_versions (OCTAVE_VERSION, dep.version, dep.operator))\n        bad_deps{end+1} = dep;\n      endif\n      ## Is the current dependency not Octave?\n    else\n      ok = xor (false, uninstall_flag);\n      for i = 1:length (installed_pkgs_lst)\n        cur_name = installed_pkgs_lst{i}.name;\n        cur_version = installed_pkgs_lst{i}.version;\n        if (strcmp (dep.package, cur_name)\n            && compare_versions (cur_version, dep.version, dep.operator))\n          ok = xor (true, uninstall_flag);\n          break;\n        endif\n      endfor\n      if (! ok)\n        bad_deps{end+1} = dep;\n      endif\n    endif\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/get_validated_pkg_list.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{__pkg__} =} get_validated_pkg_list ()\n## @deftypefnx {} {@var{__pkg__} =} get_validated_pkg_list (@var{force_refresh})\n## @deftypefnx {} {@var{__pkg__} =} get_validated_pkg_list (@var{force_refresh}, @var{verbose})\n## Download or load cached list of current packages and validate that it fits\n## expected patterns.\n##\n## If @var{force_refresh} is true, always download fresh data from the server\n## and update the cache.\n##\n## If @var{verbose} is true, print diagnostic messages about cache operations.\n##\n## Return @code{__pkg__} struct used by other functions.\n## @end deftypefn\n\nfunction retval = get_validated_pkg_list (force_refresh = false, verbose = false)\n\n  ## The __pkg__ struct is what we return with all the package information.\n  ## We make it persistent to avoid querying the server each time.\n  persistent __pkg__;\n\n  if (! isempty (__pkg__) && ! force_refresh)\n    ## This function has been called already and __pkg__ exists.\n    ## No need to query the server again unless refresh is forced.\n    retval = __pkg__;\n    return;\n  endif\n\n  ## Define cache directory location\n  cache_dir = fullfile (user_config_dir (), \"octave\");\n\n  ## Cache files use timestamped names: packages_yyyymmddHHMM.json\n  ## This makes age visible and provides natural history/rollback\n  cache_pattern = \"packages_*.json\";\n\n  ## Maximum number of old cache files to keep (for history/rollback)\n  max_cache_files = 3;\n\n  ## Find most recent cache file\n  cache_file = \"\";\n\n  if (exist (cache_dir, \"dir\"))\n    cache_files = dir (fullfile (cache_dir, cache_pattern));\n    if (! isempty (cache_files))\n      if (verbose)\n        printf (\"pkg: searching for cached package database in %s\\n\", cache_dir);\n      endif\n\n      ## Find most recent cache by parsing timestamps from filenames\n      most_recent_time = 0;\n      for i = 1:numel (cache_files)\n        fname = cache_files(i).name;\n        ## Extract timestamp: packages_yyyymmddHHMM.json\n        if (length (fname) == 26 && strcmp (fname(1:9), \"packages_\") &&\n            strcmp (fname(22:26), \".json\"))\n          timestamp_str = fname(10:21);\n\n          try\n            ## Use datenum with format string\n            file_time = datenum (timestamp_str, \"yyyymmddHHMM\");\n\n            if (file_time > most_recent_time)\n              most_recent_time = file_time;\n              cache_file = fullfile (cache_dir, fname);\n            endif\n          catch\n            ## Skip malformed timestamp\n            if (verbose)\n              warning (\"pkg: skipping cache file with malformed timestamp: %s\", fname);\n            endif\n          end_try_catch\n        endif\n      endfor\n\n      ## Calculate age if we found a cache file\n      if (! isempty (cache_file))\n        cache_age_days = (now () - most_recent_time);\n        if (verbose)\n          printf (\"pkg: found cached database from %s (%.1f days old)\\n\",\n                  datestr (most_recent_time, \"yyyy-mm-dd HH:MM\"),\n                  cache_age_days);\n        endif\n      endif\n    endif\n  endif\n\n  ## Download fresh data from server\n  downloaded_fresh_data = false;\n\n  if (verbose || force_refresh)\n    printf (\"pkg: downloading latest package database from packages.octave.org...\\n\");\n    if (! verbose)\n      printf (\"pkg: this may take a moment, please wait...\\n\");\n    endif\n  endif\n\n  ## Try primary URL first, then fallback\n  primary_url = \"https://packages.octave.org/packages.json\";\n  fallback_url = \"https://gnu-octave.github.io/packages/packages.json\";\n\n  [list, succ] = urlread (primary_url, 'Timeout', 6);\n\n  if (! succ)\n    ## Primary failed, try fallback\n    if (verbose)\n      printf (\"pkg: primary repository unavailable, trying gnu-octave.github.io/packages...\\n\");\n    endif\n    [list, succ] = urlread (fallback_url, 'Timeout', 9);\n  endif\n\n  if (! succ)\n    ## Could not download - try to use cache as fallback\n    if (verbose)\n      warning (\"pkg: download failed, attempting to use cached data\");\n    endif\n\n    if (! isempty (cache_file))\n      warning (\"pkg: could not download package list, using cached package index (%.1f days old)\\n\", ...\n               cache_age_days);\n      try\n        fid = fopen (cache_file, \"rt\");\n        if (fid >= 0)\n          unwind_protect\n            list = fread (fid, Inf, \"*char\")';\n          unwind_protect_cleanup\n            fclose (fid);\n          end_unwind_protect\n\n          __pkg__ = jsondecode (list, \"makeValidName\", false);\n\n          if (isstruct (__pkg__))\n            if (verbose)\n              printf (\"pkg: successfully fell back to cached data (%d packages) from %s\\n\",\n                      numel (fieldnames (__pkg__)), cache_file);\n            endif\n            retval = __pkg__;\n            return;\n          endif\n        endif\n      catch\n        error (\"pkg: could not read URL and cached package index is unreadable, please verify internet connection\");\n      end_try_catch\n    else\n      error (\"pkg: could not read URL and no cached package index available, please verify internet connection\");\n    endif\n  else\n    ## Download succeeded - capture timestamp\n    ## This reflects actual data freshness, not when we started trying\n    download_time = now ();\n    downloaded_fresh_data = true;\n  endif\n\n  if (verbose)\n    printf (\"pkg: download complete, parsing package database...\\n\");\n  endif\n\n  __pkg__ = jsondecode (list, \"makeValidName\", false);\n\n  ## A sanity check before the calling location uses this.\n  if (! isstruct (__pkg__))\n    error (\"pkg: server returned data of unknown format\");\n  endif\n\n  if (verbose)\n    printf (\"pkg: successfully parsed %d packages\\n\", numel (fieldnames (__pkg__)));\n  endif\n\n  ## Save to cache with timestamp in filename (only if we downloaded fresh data)\n  if (downloaded_fresh_data)\n    try\n      ## Create cache directory if it doesn't exist\n      if (! exist (cache_dir, \"dir\"))\n        if (verbose)\n          printf (\"pkg: creating cache directory: %s\\n\", cache_dir);\n        endif\n        [success, msg] = mkdir (cache_dir);\n        if (! success)\n          warning (\"pkg: could not create cache directory: %s\", msg);\n        endif\n      endif\n\n      ## Generate timestamped filename using datestr\n      ## Format: packages_yyyymmddHHMM.json\n      ## Use download_time, not current time, so timestamp reflects data age\n      timestamp_str = datestr (download_time, \"yyyymmddHHMM\");\n      new_cache_file = fullfile (cache_dir, [\"packages_\" timestamp_str \".json\"]);\n\n      if (verbose)\n        printf (\"pkg: saving package database to cache: %s\\n\", new_cache_file);\n      endif\n\n      ## Write new cache\n      fid = fopen (new_cache_file, \"wt\");\n      if (fid >= 0)\n        unwind_protect\n          fwrite (fid, list);\n        unwind_protect_cleanup\n          fclose (fid);\n        end_unwind_protect\n\n        if (verbose)\n          printf (\"pkg: cache file saved successfully\\n\");\n        endif\n\n        ## Clean up old cache files (keep only max_cache_files most recent)\n        cache_files = dir (fullfile (cache_dir, cache_pattern));\n        if (numel (cache_files) > max_cache_files)\n          if (verbose)\n            printf (\"pkg: cleaning up old cache files (keeping %d most recent)...\\n\",\n                    max_cache_files);\n          endif\n          ## Sort by modification time\n          [~, idx] = sort ([cache_files.datenum], \"descend\");\n          ## Remove oldest files\n          for i = (max_cache_files + 1):numel (idx)\n            old_file = fullfile (cache_dir, cache_files(idx(i)).name);\n            try\n              unlink (old_file);\n              if (verbose)\n                printf (\"pkg: deleted old cache file: %s\\n\", cache_files(idx(i)).name);\n              endif\n            catch\n              warning (\"pkg: could not delete old cache file: %s\", old_file);\n            end_try_catch\n          endfor\n        endif\n      else\n        warning (\"pkg: could not write to cache file\");\n      endif\n    catch\n      warning (\"pkg: error updating cache: %s\", lasterr ());\n    end_try_catch\n  endif  ## if (downloaded_fresh_data)\n\n  retval = __pkg__;\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/getarch.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{arch} =} getarch ()\n## Undocumented internal function.\n## @end deftypefn\n\nfunction arch = getarch ()\n  persistent _arch = [__octave_config_info__(\"canonical_host_type\"), \"-\", ...\n                      __octave_config_info__(\"api_version\")];\n\n  arch = _arch;\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/getarchdir.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{archdir} =} getarchdir (@var{desc})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction archdir = getarchdir (desc)\n  archdir = fullfile (desc.archprefix, getarch ());\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/install.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} install (@var{files}, @var{handle_deps}, @var{prefix}, @var{archprefix}, @var{verbose}, @var{local_list}, @var{global_list}, @var{global_install})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction install (files, handle_deps, prefix, archprefix, verbose,\n                  local_list, global_list, global_install)\n\n  ## Check that the directory in prefix exist.  If it doesn't: create it!\n  if (! isfolder (prefix))\n    warning (\"creating installation directory %s\", prefix);\n    [status, msg] = mkdir (prefix);\n    if (status != 1)\n      error (\"could not create installation directory: %s\", msg);\n    endif\n  endif\n\n  ## Get the list of installed packages.\n  [local_packages, global_packages] = installed_packages (local_list,\n                                                          global_list);\n\n  installed_pkgs_lst = {local_packages{:}, global_packages{:}};\n\n  if (global_install)\n    packages = global_packages;\n  else\n    packages = local_packages;\n  endif\n\n  if (ispc ())\n    oct_glob = @__wglob__;\n  else\n    oct_glob = @glob;\n  endif\n\n  ## Uncompress the packages and read the DESCRIPTION files.\n  tmpdirs = packdirs = descriptions = {};\n  try\n    ## Warn about non existent files.\n    for i = 1:length (files)\n      if (isempty (oct_glob (files{i})))\n        warning (\"file %s does not exist\", files{i});\n      endif\n    endfor\n\n    ## Unpack the package files and read the DESCRIPTION files.\n    files = oct_glob (files);\n    packages_to_uninstall = [];\n    for i = 1:length (files)\n      tgz = files{i};\n\n      if (exist (tgz, \"file\"))\n        ## Create a temporary directory.\n        tmpdir = tempname ();\n        tmpdirs{end+1} = tmpdir;\n        if (verbose)\n          printf (\"mkdir (%s)\\n\", tmpdir);\n        endif\n        [status, msg] = mkdir (tmpdir);\n        if (status != 1)\n          error (\"couldn't create temporary directory: %s\", msg);\n        endif\n\n        ## Uncompress the package.\n        [~, ~, ext] = fileparts (tgz);\n        if (strcmpi (ext, \".zip\"))\n          func_uncompress = @unzip;\n        else\n          func_uncompress = @untar;\n        endif\n        if (verbose)\n          printf (\"%s (%s, %s)\\n\", func2str (func_uncompress), tgz, tmpdir);\n        endif\n        func_uncompress (tgz, tmpdir);\n\n        ## Get the name of the directories produced by tar.\n        [dirlist, err, msg] = readdir (tmpdir);\n        if (err)\n          error (\"couldn't read directory produced by tar: %s\", msg);\n        endif\n\n        if (length (dirlist) > 3)\n          error (\"bundles of packages are not allowed\");\n        endif\n      endif\n\n      ## The filename pointed to an uncompressed package to begin with.\n      if (isfolder (tgz))\n        dirlist = {\".\", \"..\", tgz};\n      endif\n\n      if (exist (tgz, \"file\") || isfolder (tgz))\n        ## The two first entries of dirlist are \".\" and \"..\".\n        if (exist (tgz, \"file\"))\n          packdir = fullfile (tmpdir, dirlist{3});\n        else\n          packdir = fullfile (pwd (), dirlist{3});\n        endif\n        packdirs{end+1} = packdir;\n\n        ## Make sure the package contains necessary files.\n        verify_directory (packdir);\n\n        ## Read the DESCRIPTION file.\n        filename = fullfile (packdir, \"DESCRIPTION\");\n        desc = get_description (filename);\n\n        ## Set default installation directory.\n        desc.dir = fullfile (prefix, [desc.name \"-\" desc.version]);\n\n        ## Set default architecture-dependent installation directory.\n        desc.archprefix = fullfile (archprefix, [desc.name \"-\" desc.version]);\n\n        ## Save desc.\n        descriptions{end+1} = desc;\n\n        ## Are any of the new packages already installed?\n        ## If so we'll remove the old version.\n        for j = 1:length (packages)\n          if (strcmp (packages{j}.name, desc.name))\n            packages_to_uninstall(end+1) = j;\n          endif\n        endfor\n      endif\n    endfor\n  catch\n    ## Something went wrong, delete tmpdirs.\n    for i = 1:length (tmpdirs)\n      sts = rmdir (tmpdirs{i}, \"s\");\n    endfor\n    rethrow (lasterror ());\n  end_try_catch\n\n  ## Check dependencies.\n  if (handle_deps)\n    ok = true;\n    error_text = \"\";\n    for i = 1:length (descriptions)\n      desc = descriptions{i};\n      idx2 = setdiff (1:length (descriptions), i);\n      if (global_install)\n        ## Global installation is not allowed to have dependencies on locally\n        ## installed packages.\n        idx1 = setdiff (1:length (global_packages), packages_to_uninstall);\n        pseudo_installed_packages = {global_packages{idx1}, ...\n                                     descriptions{idx2}};\n      else\n        idx1 = setdiff (1:length (local_packages), packages_to_uninstall);\n        pseudo_installed_packages = {local_packages{idx1}, ...\n                                     global_packages{:}, ...\n                                     descriptions{idx2}};\n      endif\n      bad_deps = get_unsatisfied_deps (desc, pseudo_installed_packages);\n      ## Are there any unsatisfied dependencies?\n      if (! isempty (bad_deps))\n        ok = false;\n        for i = 1:length (bad_deps)\n          dep = bad_deps{i};\n          error_text = [error_text \" \" desc.name \" needs \" ...\n                        dep.package \" \" dep.operator \" \" dep.version \"\\n\"];\n        endfor\n      endif\n    endfor\n\n    ## Did we find any unsatisfied dependencies?\n    if (! ok)\n      error (\"the following dependencies were unsatisfied:\\n  %s\", error_text);\n    endif\n  endif\n\n  ## Prepare each package for installation.\n  try\n    for i = 1:length (descriptions)\n      desc = descriptions{i};\n      pdir = packdirs{i};\n      prepare_installation (desc, pdir);\n      configure_make (desc, pdir, verbose);\n      copy_built_files (desc, pdir, verbose);\n    endfor\n  catch\n    ## Something went wrong, delete tmpdirs.\n    for i = 1:length (tmpdirs)\n      sts = rmdir (tmpdirs{i}, \"s\");\n    endfor\n    rethrow (lasterror ());\n  end_try_catch\n\n  ## Uninstall the packages that will be replaced.\n  try\n    for i = packages_to_uninstall\n      if (global_install)\n        uninstall ({global_packages{i}.name}, false, verbose, local_list,\n                   global_list, global_install);\n      else\n        uninstall ({local_packages{i}.name}, false, verbose, local_list,\n                   global_list, global_install);\n      endif\n    endfor\n  catch\n    ## Something went wrong, delete tmpdirs.\n    for i = 1:length (tmpdirs)\n      sts = rmdir (tmpdirs{i}, \"s\");\n    endfor\n    rethrow (lasterror ());\n  end_try_catch\n\n  ## Install each package.\n  try\n    for i = 1:length (descriptions)\n      desc = descriptions{i};\n      pdir = packdirs{i};\n      copy_files (desc, pdir, global_install);\n      create_pkgadddel (desc, pdir, \"PKG_ADD\", global_install, verbose);\n      create_pkgadddel (desc, pdir, \"PKG_DEL\", global_install, verbose);\n      finish_installation (desc, pdir, global_install);\n      generate_lookfor_cache (desc, verbose);\n    endfor\n  catch\n    ## Something went wrong, delete tmpdirs.\n    for i = 1:length (tmpdirs)\n      sts = rmdir (tmpdirs{i}, \"s\");\n    endfor\n    for i = 1:length (descriptions)\n      sts = rmdir (descriptions{i}.dir, \"s\");\n      sts = rmdir (getarchdir (descriptions{i}), \"s\");\n    endfor\n    rethrow (lasterror ());\n  end_try_catch\n\n  ## Check if the installed directory is empty.  If it is remove it\n  ## from the list.\n  for i = length (descriptions):-1:1\n    if (dirempty (descriptions{i}.dir, {\"packinfo\", \"doc\"})\n        && dirempty (getarchdir (descriptions{i})))\n      warning (\"package %s is empty\\n\", descriptions{i}.name);\n      sts = rmdir (descriptions{i}.dir, \"s\");\n      sts = rmdir (getarchdir (descriptions{i}), \"s\");\n      descriptions(i) = [];\n    endif\n  endfor\n\n  ## Add the packages to the package list.\n  try\n    if (global_install)\n      idx = setdiff (1:length (global_packages), packages_to_uninstall);\n      global_packages = save_order ({global_packages{idx}, descriptions{:}});\n      if (ispc)\n        ## On Windows ensure LFN paths are saved rather than 8.3 style paths\n        global_packages = standardize_paths (global_packages);\n      endif\n      global_packages = make_rel_paths (global_packages);\n      save (global_list, \"global_packages\");\n      installed_pkgs_lst = {local_packages{:}, global_packages{:}};\n    else\n      idx = setdiff (1:length (local_packages), packages_to_uninstall);\n      local_packages = save_order ({local_packages{idx}, descriptions{:}});\n      if (ispc)\n        local_packages = standardize_paths (local_packages);\n      endif\n      if (! exist (fileparts (local_list), \"dir\")\n          && ! mkdir (fileparts (local_list)))\n        error (\"Octave:pkg:install:local-dir\", ...\n               \"pkg: Could not create directory for local package configuration\");\n      endif\n      save (local_list, \"local_packages\");\n      installed_pkgs_lst = {local_packages{:}, global_packages{:}};\n    endif\n  catch\n    ## Something went wrong, delete tmpdirs.\n    for i = 1:length (tmpdirs)\n      sts = rmdir (tmpdirs{i}, \"s\");\n    endfor\n    for i = 1:length (descriptions)\n      sts = rmdir (descriptions{i}.dir, \"s\");\n    endfor\n    if (global_install)\n      printf (\"error: couldn't append to %s\\n\", global_list);\n    else\n      printf (\"error: couldn't append to %s\\n\", local_list);\n    endif\n    rethrow (lasterror ());\n  end_try_catch\n\n  ## All is well, let's clean up.\n  for i = 1:length (tmpdirs)\n    [status, msg] = rmdir (tmpdirs{i}, \"s\");\n    if (status != 1 && isfolder (tmpdirs{i}))\n      warning (\"couldn't clean up after my self: %s\\n\", msg);\n    endif\n  endfor\n\n  ## Also check if desc exists because it is possible to get to this point\n  ## without creating it such as giving an invalid filename for the package.\n  if (exist (\"desc\", \"var\"))\n    ## If there is a NEWS file, mention it.\n    if (exist (fullfile (desc.dir, \"packinfo\", \"NEWS\"), \"file\"))\n    printf ([\"For information about changes from previous versions \" ...\n             \"of the %s package, run 'news %s'.\\n\"],\n            desc.name, desc.name);\n    endif\n    ## If there is a tracker or repository url in the DESCRIPTION file, prompt\n    ## users to use it for reporting issues instead of savannah bug tracker.\n    if (isfield (desc, \"tracker\"))\n      printf (\"Please report any issues with the %s package at \"\"%s\"\"\\n\",\n              desc.name, desc.tracker);\n    elseif (isfield (desc, \"url\"))\n      printf (\"Please report any issues with the %s package at \"\"%s\"\"\\n\",\n              desc.name, desc.url);\n    endif\n  endif\n\nendfunction\n\n\nfunction pkg = extract_pkg (nm, pat)\n\n  fid = fopen (nm, \"rt\", \"n\", mfile_encoding ());\n  pkg = \"\";\n  if (fid >= 0)\n    while (! feof (fid))\n      ln = __u8_validate__ (fgetl (fid));\n      if (ln > 0)\n        t = regexp (ln, pat, \"tokens\");\n        if (! isempty (t))\n          pkg = [pkg \"\\n\" t{1}{1}];\n        endif\n      endif\n    endwhile\n    if (! isempty (pkg))\n      pkg = [pkg \"\\n\"];\n    endif\n    fclose (fid);\n  endif\n\nendfunction\n\n\n## Make sure the package contains the essential files.\nfunction verify_directory (dir)\n\n  needed_files = {\"COPYING\", \"DESCRIPTION\"};\n  for f = needed_files\n    if (! exist (fullfile (dir, f{1}), \"file\"))\n      error (\"package is missing file: %s\", f{1});\n    endif\n  endfor\n\nendfunction\n\n\nfunction prepare_installation (desc, packdir)\n\n  ## Is there a pre_install to call?\n  if (exist (fullfile (packdir, \"pre_install.m\"), \"file\"))\n    wd = pwd ();\n    try\n      cd (packdir);\n      pre_install (desc);\n      cd (wd);\n    catch\n      cd (wd);\n      rethrow (lasterror ());\n    end_try_catch\n  endif\n\n  ## If the directory \"inst\" doesn't exist, we create it.\n  inst_dir = fullfile (packdir, \"inst\");\n  if (! isfolder (inst_dir))\n    [status, msg] = mkdir (inst_dir);\n    if (status != 1)\n      sts = rmdir (desc.dir, \"s\");\n      error (\"the 'inst' directory did not exist and could not be created: %s\",\n             msg);\n    endif\n  endif\n\nendfunction\n\n\nfunction copy_built_files (desc, packdir, verbose)\n\n  src = fullfile (packdir, \"src\");\n  if (! isfolder (src))\n    return;\n  endif\n\n  ## Copy files to \"inst\" and \"inst/arch\" (this is instead of 'make install').\n  files = fullfile (src, \"FILES\");\n  instdir = fullfile (packdir, \"inst\");\n  archdir = fullfile (packdir, \"inst\", getarch ());\n\n  ## Get filenames.\n  if (exist (files, \"file\"))\n    [fid, msg] = fopen (files, \"r\");\n    if (fid < 0)\n      error (\"couldn't open %s: %s\", files, msg);\n    endif\n    filenames = char (fread (fid))';\n    fclose (fid);\n    if (filenames(end) == \"\\n\")\n      filenames(end) = [];\n    endif\n    filenames = strtrim (ostrsplit (filenames, \"\\n\"));\n    delete_idx = [];\n    for i = 1:length (filenames)\n      if (! all (isspace (filenames{i})))\n        filenames{i} = fullfile (src, filenames{i});\n      else\n        delete_idx(end+1) = i;\n      endif\n    endfor\n    filenames(delete_idx) = [];\n  else\n    m = dir (fullfile (src, \"*.m\"));\n    oct = dir (fullfile (src, \"*.oct\"));\n    mex = dir (fullfile (src, \"*.mex\"));\n    tst = dir (fullfile (src, \"*tst\"));\n    doc = dir (fullfile (src, \"doc-cache\"));\n\n    filenames = cellfun (@(x) fullfile (src, x),\n                         {m.name, oct.name, mex.name, tst.name, doc.name},\n                         \"uniformoutput\", false);\n  endif\n\n  ## Split into architecture dependent and independent files.\n  if (isempty (filenames))\n    idx = [];\n  else\n    idx = cellfun (\"is_architecture_dependent\", filenames);\n  endif\n  archdependent = filenames(idx);\n  archindependent = filenames(! idx);\n\n  ## Copy the files.\n  if (! all (isspace ([filenames{:}])))\n      if (! isfolder (instdir))\n        mkdir (instdir);\n      endif\n      if (! all (isspace ([archindependent{:}])))\n        if (verbose)\n          printf (\"copyfile\");\n          printf (\" %s\", archindependent{:});\n          printf (\" %s\\n\", instdir);\n        endif\n        [status, output] = copyfile (archindependent, instdir);\n        if (status != 1)\n          sts = rmdir (desc.dir, \"s\");\n          error (\"Couldn't copy files from 'src' to 'inst': %s\", output);\n        endif\n      endif\n      if (! all (isspace ([archdependent{:}])))\n        if (verbose)\n          printf (\"copyfile\");\n          printf (\" %s\", archdependent{:});\n          printf (\" %s\\n\", archdir);\n        endif\n        if (! isfolder (archdir))\n          mkdir (archdir);\n        endif\n        [status, output] = copyfile (archdependent, archdir);\n        if (status != 1)\n          sts = rmdir (desc.dir, \"s\");\n          error (\"Couldn't copy files from 'src' to 'inst': %s\", output);\n        endif\n      endif\n  endif\n\nendfunction\n\n\nfunction dep = is_architecture_dependent (nm)\n\n  persistent archdepsuffix = {\".oct\", \".mex\", \".a\", \".lib\", \".so\", ...\n                              \"tst\", \".so.*\", \".dll\", \"dylib\"};\n\n  ## doc-cache file for built sources is special.  It has no extension, but\n  ## must be placed in architecture-dependent directory.\n  if (strfind (nm, \"doc-cache\"))\n    dep = true;\n    return;\n  endif\n\n  dep = false;\n  for i = 1 : length (archdepsuffix)\n    ext = archdepsuffix{i};\n    if (ext(end) == \"*\")\n      isglob = true;\n      ext(end) = [];\n    else\n      isglob = false;\n    endif\n    pos = strfind (nm, ext);\n    if (pos)\n      if (! isglob && (length (nm) - pos(end) != length (ext) - 1))\n        continue;\n      endif\n      dep = true;\n      break;\n    endif\n  endfor\n\nendfunction\n\n\nfunction copy_files (desc, packdir, global_install)\n\n  ## Create the installation directory.\n  if (! isfolder (desc.dir))\n    [status, output] = mkdir (desc.dir);\n    if (status != 1)\n      error (\"couldn't create installation directory %s : %s\",\n             desc.dir, output);\n    endif\n  endif\n\n  octfiledir = getarchdir (desc);\n\n  ## Copy the files from \"inst\" to installdir.\n  instdir = fullfile (packdir, \"inst\");\n  if (! dirempty (instdir))\n    [status, output] = copyfile (fullfile (instdir, \"*\"), desc.dir);\n    if (status != 1)\n      sts = rmdir (desc.dir, \"s\");\n      error (\"couldn't copy files to the installation directory\");\n    endif\n    if (isfolder (fullfile (desc.dir, getarch ()))\n        && ! is_same_file (fullfile (desc.dir, getarch ()), octfiledir))\n      if (! isfolder (octfiledir))\n        ## Can be required to create up to three levels of dirs.\n        octm1 = fileparts (octfiledir);\n        if (! isfolder (octm1))\n          octm2 = fileparts (octm1);\n          if (! isfolder (octm2))\n            octm3 = fileparts (octm2);\n            if (! isfolder (octm3))\n              [status, output] = mkdir (octm3);\n              if (status != 1)\n                sts = rmdir (desc.dir, \"s\");\n                error (\"couldn't create installation directory %s : %s\",\n                       octm3, output);\n              endif\n            endif\n            [status, output] = mkdir (octm2);\n            if (status != 1)\n              sts = rmdir (desc.dir, \"s\");\n              error (\"couldn't create installation directory %s : %s\",\n                     octm2, output);\n            endif\n          endif\n          [status, output] = mkdir (octm1);\n          if (status != 1)\n            sts = rmdir (desc.dir, \"s\");\n            error (\"couldn't create installation directory %s : %s\",\n                   octm1, output);\n          endif\n        endif\n        [status, output] = mkdir (octfiledir);\n        if (status != 1)\n          sts = rmdir (desc.dir, \"s\");\n          error (\"couldn't create installation directory %s : %s\",\n                 octfiledir, output);\n        endif\n      endif\n      [status, output] = movefile (fullfile (desc.dir, getarch (), \"*\"),\n                                   octfiledir);\n      sts = rmdir (fullfile (desc.dir, getarch ()), \"s\");\n\n      if (status != 1)\n        sts = rmdir (desc.dir, \"s\");\n        sts = rmdir (octfiledir, \"s\");\n        error (\"couldn't copy files to the installation directory\");\n      endif\n    endif\n\n  endif\n\n  ## Create the \"packinfo\" directory.\n  packinfo = fullfile (desc.dir, \"packinfo\");\n  [status, msg] = mkdir (packinfo);\n  if (status != 1)\n    sts = rmdir (desc.dir, \"s\");\n    sts = rmdir (octfiledir, \"s\");\n    error (\"couldn't create packinfo directory: %s\", msg);\n  endif\n\n  packinfo_copy_file (\"DESCRIPTION\", \"required\", packdir, packinfo, desc, octfiledir);\n  packinfo_copy_file (\"COPYING\", \"required\", packdir, packinfo, desc, octfiledir);\n  packinfo_copy_file (\"CITATION\", \"optional\", packdir, packinfo, desc, octfiledir);\n  packinfo_copy_file (\"NEWS\", \"optional\", packdir, packinfo, desc, octfiledir);\n  packinfo_copy_file (\"ONEWS\", \"optional\", packdir, packinfo, desc, octfiledir);\n  packinfo_copy_file (\"ChangeLog\", \"optional\", packdir, packinfo, desc, octfiledir);\n\n  ## Is there an INDEX file to copy or should we generate one?\n  index_file = fullfile (packdir, \"INDEX\");\n  if (exist (index_file, \"file\"))\n    packinfo_copy_file (\"INDEX\", \"required\", packdir, packinfo, desc, octfiledir);\n  else\n    try\n      write_index (desc, fullfile (packdir, \"inst\"),\n                   fullfile (packinfo, \"INDEX\"), global_install);\n    catch\n      sts = rmdir (desc.dir, \"s\");\n      sts = rmdir (octfiledir, \"s\");\n      rethrow (lasterror ());\n    end_try_catch\n  endif\n\n  ## Is there an 'on_uninstall.m' to install?\n  packinfo_copy_file (\"on_uninstall.m\", \"optional\", packdir, packinfo, desc, octfiledir);\n\n  ## Is there a doc/ directory that needs to be installed?\n  docdir = fullfile (packdir, \"doc\");\n  if (isfolder (docdir) && ! dirempty (docdir))\n    [status, output] = copyfile (docdir, desc.dir);\n  endif\n\n  ## Is there a bin/ directory that needs to be installed?\n  ## FIXME: Need to treat architecture dependent files in bin/\n  bindir = fullfile (packdir, \"bin\");\n  if (isfolder (bindir) && ! dirempty (bindir))\n    [status, output] = copyfile (bindir, desc.dir);\n  endif\n\nendfunction\n\n\nfunction packinfo_copy_file (filename, requirement, packdir, packinfo, desc, octfiledir)\n\n  filepath = fullfile (packdir, filename);\n  if (! exist (filepath, \"file\") && strcmpi (requirement, \"optional\"))\n    ## do nothing, it's still OK\n  else\n    [status, output] = copyfile (filepath, packinfo);\n    if (status != 1)\n      sts = rmdir (desc.dir, \"s\");\n      sts = rmdir (octfiledir, \"s\");\n      error (\"Couldn't copy %s file: %s\", filename, output);\n    endif\n  endif\n\nendfunction\n\n\n## Create an INDEX file for a package that doesn't provide one.\n##   'desc'  describes the package.\n##   'dir'   is the 'inst' directory in temporary directory.\n##   'index_file' is the name (including path) of resulting INDEX file.\nfunction write_index (desc, dir, index_file, global_install)\n\n  ## Get names of functions in dir\n  [files, err, msg] = readdir (dir);\n  if (err)\n    error (\"couldn't read directory %s: %s\", dir, msg);\n  endif\n\n  ## Get classes in dir\n  class_idx = find (strncmp (files, '@', 1));\n  for k = 1:length (class_idx)\n    class_name = files {class_idx(k)};\n    class_dir = fullfile (dir, class_name);\n    if (isfolder (class_dir))\n      [files2, err, msg] = readdir (class_dir);\n      if (err)\n        error (\"couldn't read directory %s: %s\", class_dir, msg);\n      endif\n      files2 = strcat (class_name, filesep (), files2);\n      files = [files; files2];\n    endif\n  endfor\n\n  ## Check for architecture dependent files.\n  tmpdir = getarchdir (desc);\n  if (isfolder (tmpdir))\n    [files2, err, msg] = readdir (tmpdir);\n    if (err)\n      error (\"couldn't read directory %s: %s\", tmpdir, msg);\n    endif\n    files = [files; files2];\n  endif\n\n  functions = {};\n  for i = 1:length (files)\n    file = files{i};\n    lf = length (file);\n    if (lf > 2 && strcmp (file(end-1:end), \".m\"))\n      functions{end+1} = file(1:end-2);\n    elseif (lf > 4 && strcmp (file(end-3:end), \".oct\"))\n      functions{end+1} = file(1:end-4);\n    endif\n  endfor\n\n  ## Does desc have a categories field?\n  if (! isfield (desc, \"categories\"))\n    error (\"the DESCRIPTION file must have a Categories field, when no INDEX file is given\");\n  endif\n  categories = strtrim (strsplit (desc.categories, \",\"));\n  if (length (categories) < 1)\n    error (\"the Category field is empty\");\n  endif\n\n  ## Write INDEX.\n  fid = fopen (index_file, \"w\");\n  if (fid == -1)\n    error (\"couldn't open %s for writing\", index_file);\n  endif\n  fprintf (fid, \"%s >> %s\\n\", desc.name, desc.title);\n  fprintf (fid, \"%s\\n\", categories{1});\n  fprintf (fid, \"  %s\\n\", functions{:});\n  fclose (fid);\n\nendfunction\n\n\nfunction create_pkgadddel (desc, packdir, nm, global_install, verbose)\n\n  if (verbose)\n    printf (\"creating file %s\\n\", nm);\n  endif\n\n  instpkg = fullfile (desc.dir, nm);\n  instfid = fopen (instpkg, \"at\"); # append to support PKG_ADD at inst/\n  ## If it is exists, most of the PKG_* file should go into the\n  ## architecture dependent directory so that the autoload/mfilename\n  ## commands work as expected.  The only part that doesn't is the\n  ## part in the main directory.\n  archdir = fullfile (getarchprefix (desc, global_install),\n                      [desc.name \"-\" desc.version], getarch ());\n  if (isfolder (getarchdir (desc)))\n    archpkg = fullfile (getarchdir (desc), nm);\n    archfid = fopen (archpkg, \"at\");\n  else\n    archpkg = instpkg;\n    archfid = instfid;\n  endif\n\n  if (archfid >= 0 && instfid >= 0)\n    if (ispc ())\n      oct_glob = @__wglob__;\n    else\n      oct_glob = @glob;\n    endif\n\n    ## Search all dot-m files for PKG commands.\n    lst = oct_glob (fullfile (packdir, \"inst\", \"*.m\"));\n    for i = 1:length (lst)\n      nam = lst{i};\n      fwrite (instfid, extract_pkg (nam, ['^[#%][#%]* *' nm ': *(.*)$']));\n    endfor\n\n    ## Search all C++ source files for PKG commands.\n    cc_lst = oct_glob (fullfile (packdir, \"src\", \"*.cc\"));\n    cpp_lst = oct_glob (fullfile (packdir, \"src\", \"*.cpp\"));\n    cxx_lst = oct_glob (fullfile (packdir, \"src\", \"*.cxx\"));\n    lst = [cc_lst; cpp_lst; cxx_lst];\n    for i = 1:length (lst)\n      nam = lst{i};\n      fwrite (archfid, extract_pkg (nam, ['^//* *' nm ': *(.*)$']));\n      fwrite (archfid, extract_pkg (nam, ['^/\\** *' nm ': *(.*) *\\*/$']));\n    endfor\n\n    ## Add developer included PKG commands.\n    packdirnm = fullfile (packdir, nm);\n    if (exist (packdirnm, \"file\"))\n      fid = fopen (packdirnm, \"rt\");\n      if (fid >= 0)\n        while (! feof (fid))\n          ln = fgets (fid);\n          if (ln > 0)\n            fwrite (archfid, ln);\n          endif\n        endwhile\n        fclose (fid);\n      endif\n    endif\n\n    ## If the files is empty remove it.\n    fclose (instfid);\n    t = dir (instpkg);\n    if (t.bytes <= 0)\n      unlink (instpkg);\n    endif\n\n    if (instfid != archfid)\n      fclose (archfid);\n      t = dir (archpkg);\n      if (t.bytes <= 0)\n        unlink (archpkg);\n      endif\n    endif\n  endif\n\nendfunction\n\n\nfunction archprefix = getarchprefix (desc, global_install)\n\n  if (global_install)\n    [~, archprefix] = default_prefix (global_install, desc);\n  else\n    archprefix = desc.dir;\n  endif\n\nendfunction\n\n\nfunction finish_installation (desc, packdir, global_install)\n\n  ## Is there a post-install to call?\n  if (exist (fullfile (packdir, \"post_install.m\"), \"file\"))\n    wd = pwd ();\n    try\n      cd (packdir);\n      post_install (desc);\n      cd (wd);\n    catch\n      cd (wd);\n      sts = rmdir (desc.dir, \"s\");\n      sts = rmdir (getarchdir (desc), \"s\");\n      rethrow (lasterror ());\n    end_try_catch\n  endif\n\nendfunction\n\n\nfunction generate_lookfor_cache (desc, verbose)\n\n  dirs = strtrim (ostrsplit (genpath (desc.dir), pathsep ()));\n  if (ispc)\n    dirs = cellfun ('canonicalize_file_name', dirs, \"uniformoutput\", false);\n  endif\n  for i = 1 : numel (dirs)\n\n    docfile = fullfile (dirs{i}, \"doc-cache\");\n    if (exist (docfile, 'file'))\n      ## Package maintainer already built doc-cache file, validate.\n      if (verbose)\n        printf (\"using package-provided doc-cache file for directory %s\\n\", dirs{i});\n      endif\n      try\n        cache = load (docfile).cache;\n      catch\n        if (verbose)\n          printf (\"unable to read doc-cache file; creating a new one\\n\");\n        endif\n        doc_cache_create (docfile, dirs{i});\n        continue;\n      end_try_catch\n\n      if (! iscellstr (cache) || ndims (cache) != 2 || rows (cache) != 3)\n        if (verbose)\n          printf (\"invalid doc-cache file; creating a new one\\n\");\n        endif\n        doc_cache_create (docfile, dirs{i});\n        continue;\n      endif\n    else\n      ## No doc-cache file, create one.\n      if (verbose)\n        printf (\"creating file doc-cache for directory %s\\n\", dirs{i});\n      endif\n      doc_cache_create (docfile, dirs{i});\n    endif\n\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/installed_packages.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{out1}, @var{out2}] =} installed_packages (@var{local_list}, @var{global_list}, @var{pkgname})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [out1, out2] = installed_packages (local_list, global_list, pkgname = {})\n\n  ## Get the list of installed packages.\n  try\n    local_packages = load (local_list).local_packages;\n  catch\n    local_packages = {};\n  end_try_catch\n  try\n    global_packages = load (global_list).global_packages;\n    global_packages = expand_rel_paths (global_packages);\n    if (ispc)\n      ## On Windows ensure 8.3 style paths are turned into LFN paths\n      global_packages = standardize_paths (global_packages);\n    endif\n  catch\n    global_packages = {};\n  end_try_catch\n  installed_pkgs_lst = {local_packages{:}, global_packages{:}};\n\n  ## Eliminate duplicates in the installed package list.\n  ## Locally installed packages take precedence.\n  installed_names = cellfun (@(x) x.name, installed_pkgs_lst,\n                             \"uniformoutput\", false);\n  [~, idx] = unique (installed_names, \"first\");\n  installed_names = installed_names(idx);\n  installed_pkgs_lst = installed_pkgs_lst(idx);\n\n  ## Check whether info on a particular package was requested\n  if (! isempty (pkgname))\n    idx = [];\n    for i = 1 : numel (pkgname)\n      idx = [idx, find(strcmp (pkgname{i}, installed_names))];\n    endfor\n    if (isempty (idx))\n      installed_names = {};\n      installed_pkgs_lst = {};\n    else\n      installed_names = installed_names(idx);\n      installed_pkgs_lst = installed_pkgs_lst(idx);\n    endif\n  endif\n\n  ## Now check if the package is loaded.\n  ## FIXME: Couldn't dir_in_loadpath() be used here?\n  tmppath = path ();\n  for i = 1:numel (installed_pkgs_lst)\n    if (strfind (tmppath, installed_pkgs_lst{i}.dir))\n      installed_pkgs_lst{i}.loaded = true;\n    else\n      installed_pkgs_lst{i}.loaded = false;\n    endif\n  endfor\n  for i = 1:numel (local_packages)\n    if (strfind (tmppath, local_packages{i}.dir))\n      local_packages{i}.loaded = true;\n    else\n      local_packages{i}.loaded = false;\n    endif\n  endfor\n  for i = 1:numel (global_packages)\n    if (strfind (tmppath, global_packages{i}.dir))\n      global_packages{i}.loaded = true;\n    else\n      global_packages{i}.loaded = false;\n    endif\n  endfor\n\n  ## Should we return something?\n  if (nargout == 1)\n    out1 = installed_pkgs_lst;\n  elseif (nargout > 1)\n    out1 = local_packages;\n    out2 = global_packages;\n  else\n    ## Don't return anything, instead we'll print something.\n    num_packages = numel (installed_pkgs_lst);\n    if (num_packages == 0)\n      if (isempty (pkgname))\n        printf (\"no packages installed.\\n\");\n      else\n        printf (\"package %s is not installed.\\n\", pkgname{1});\n      endif\n      return;\n    endif\n\n    ## Compute the maximal lengths of name, version, and dir.\n    h1 = \"Package Name\";\n    h2 = \"Version\";\n    h3 = \"Installation directory\";\n    max_name_length = max ([length(h1), cellfun('length', installed_names)]);\n    version_lengths = cellfun (@(x) length (x.version), installed_pkgs_lst);\n    max_version_length = max ([length(h2), version_lengths]);\n    ncols = terminal_size ()(2);\n    max_dir_length = ncols - max_name_length - max_version_length - 7;\n    if (max_dir_length < 20)\n      max_dir_length = Inf;\n    endif\n\n    h1 = postpad (h1, max_name_length + 1, \" \");\n    h2 = postpad (h2, max_version_length, \" \");\n\n    ## Print a header.\n    header = sprintf (\"%s | %s | %s\\n\", h1, h2, h3);\n    printf (header);\n    tmp = sprintf (repmat (\"-\", 1, length (header) - 1));\n    tmp(length (h1)+2) = \"+\";\n    tmp(length (h1)+length (h2)+5) = \"+\";\n    printf (\"%s\\n\", tmp);\n\n    ## Print the packages.\n    format = sprintf (\"%%%ds %%1s| %%%ds | %%s\\n\",\n                      max_name_length, max_version_length);\n    for i = 1:num_packages\n      cur_name = installed_pkgs_lst{i}.name;\n      cur_version = installed_pkgs_lst{i}.version;\n      cur_dir = installed_pkgs_lst{i}.dir;\n      if (length (cur_dir) > max_dir_length)\n        first_char = length (cur_dir) - max_dir_length + 4;\n        first_filesep = strfind (cur_dir(first_char:end), filesep ());\n        if (! isempty (first_filesep))\n          cur_dir = [\"...\" cur_dir((first_char + first_filesep(1) - 1):end)];\n        else\n          cur_dir = [\"...\" cur_dir(first_char:end)];\n        endif\n      endif\n      if (installed_pkgs_lst{i}.loaded)\n        cur_loaded = \"*\";\n      else\n        cur_loaded = \" \";\n      endif\n      printf (format, cur_name, cur_loaded, cur_version, cur_dir);\n    endfor\n    printf (\"%d packages installed\\n\", num_packages);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/load_packages.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} load_packages (@var{files}, @var{handle_deps}, @var{local_list}, @var{global_list})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction load_packages (files, handle_deps, local_list, global_list)\n\n  installed_pkgs_lst = installed_packages (local_list, global_list);\n  num_packages = length (installed_pkgs_lst);\n\n  ## Read package names and installdirs into a more convenient format.\n  pnames = pdirs = cell (1, num_packages);\n  for i = 1:num_packages\n    pnames{i} = installed_pkgs_lst{i}.name;\n    pdirs{i} = installed_pkgs_lst{i}.dir;\n  endfor\n\n  idx = [];\n  for i = 1:length (files)\n    idx2 = find (strcmp (pnames, files{i}));\n    if (! any (idx2))\n      error (\"package %s is not installed\", files{i});\n    endif\n    idx(end + 1) = idx2;\n  endfor\n\n  ## Load the packages, but take care of the ordering of dependencies.\n  load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, true);\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/load_packages_and_dependencies.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} load_packages_and_dependencies (@var{idx}, @var{handle_deps}, @var{installed_pkgs_lst}, @var{global_install})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst,\n                                         global_install)\n\n  idx = load_package_dirs (idx, [], handle_deps, installed_pkgs_lst);\n  dirs = {};\n  qt_help_files = {};\n  execpath = EXEC_PATH ();\n  for i = idx\n    name = installed_pkgs_lst{i}.name;\n    ndir = installed_pkgs_lst{i}.dir;\n    dirs{end+1} = ndir;\n    if (isfolder (fullfile (dirs{end}, \"bin\")))\n      execpath = [execpath pathsep() fullfile(dirs{end}, \"bin\")];\n    endif\n    qt_help = fullfile (dirs{end}, \"doc\", [name,\".qch\"]);\n    if (exist (qt_help, \"file\"))\n      qt_help_files{end+1} = qt_help;\n    endif\n    tmpdir = getarchdir (installed_pkgs_lst{i});\n    if (isfolder (tmpdir))\n      dirs{end + 1} = tmpdir;\n      if (isfolder (fullfile (dirs{end}, \"bin\")))\n        execpath = [execpath pathsep() fullfile(dirs{end}, \"bin\")];\n      endif\n    endif\n  endfor\n\n  ## Dependencies are sorted before their dependers in \"dirs\". Add them\n  ## consecutively in a for loop to the path to make sure dependencies are\n  ## added before their dependers (bug #57403).\n  for ii = 1:numel (dirs)\n    addpath (dirs{ii});\n  endfor\n\n  ## Add the binaries to exec_path.\n  if (! strcmp (EXEC_PATH, execpath))\n    EXEC_PATH (execpath);\n  endif\n\n  ## Update lexer for autocompletion if necessary\n  if (isguirunning && (length (idx) > 0))\n    __event_manager_update_gui_lexer__;\n  endif\n\n  ## Register Qt help files\n  if (isguirunning)\n    for (ii = 1:numel (qt_help_files))\n      try\n        if exist(\"__event_manager_register_documentation__\")\n          __event_manager_register_documentation__ (qt_help_files{ii});\n        endif\n      catch\n        # do nothing\n      end_try_catch\n    endfor\n  endif\n\nendfunction\n\n\nfunction idx = load_package_dirs (lidx, idx, handle_deps, installed_pkgs_lst)\n\n  for i = lidx\n    if (isfield (installed_pkgs_lst{i}, \"loaded\")\n        && installed_pkgs_lst{i}.loaded)\n      continue;\n    else\n      ## Insert this package at the front before recursing over dependencies.\n      if (! any (idx == i))\n        idx = [i, idx];\n      endif\n\n      if (handle_deps)\n        deps = installed_pkgs_lst{i}.depends;\n        if ((length (deps) > 1)\n            || (length (deps) == 1 && ! strcmp (deps{1}.package, \"octave\")))\n          tmplidx = [];\n          for k = 1 : length (deps)\n            for j = 1 : length (installed_pkgs_lst)\n              if (strcmp (installed_pkgs_lst{j}.name, deps{k}.package))\n                if (! any (idx == j))\n                  tmplidx(end + 1) = j;\n                  break;\n                endif\n              endif\n            endfor\n          endfor\n          idx = load_package_dirs (tmplidx, idx, handle_deps,\n                                 installed_pkgs_lst);\n        endif\n      endif\n    endif\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/make_rel_paths.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## Octave is free software: you can redistribute it and/or modify\n## it under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful,\n## but WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{pkg_list} =} make_rel_paths (@var{pkg_list})\n## Internal undocumented function.\n## @end deftypefn\n\nfunction pkg_list = make_rel_paths (pkg_list)\n\n  ptn = [\"^\" strrep(canonicalize_file_name (OCTAVE_HOME), '\\', '\\\\')];\n\n  ## Strip pkg install directories from OCTAVE_HOME\n  for i = 1:numel (pkg_list)\n    pkg_list{i}.dir = canonicalize_file_name (pkg_list{i}.dir);\n    pkg_list{i}.dir = regexprep (pkg_list{i}.dir, ptn, \"__OH__\");\n    pkg_list{i}.archprefix = canonicalize_file_name (pkg_list{i}.archprefix);\n    pkg_list{i}.archprefix = regexprep (pkg_list{i}.archprefix, ptn, \"__OH__\");\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/rebuild.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{descriptions} =} rebuild (@var{prefix}, @var{archprefix}, @var{list}, @var{files}, @var{verbose})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction descriptions = rebuild (prefix, archprefix, list, files, verbose)\n\n  if (isempty (files))\n    if (! exist (prefix, \"dir\"))\n      dirlist = [];\n    else\n      [dirlist, err, msg] = readdir (prefix);\n      if (err)\n        error (\"couldn't read directory %s: %s\", prefix, msg);\n      endif\n      ## the two first entries of dirlist are \".\" and \"..\"\n      dirlist([1,2]) = [];\n    endif\n  else\n    old_descriptions = installed_packages (list, list);\n    wd = pwd ();\n    unwind_protect\n      cd (prefix);\n      if (ispc ())\n        dirlist = __wglob__ (strcat (files, '-*'));\n      else\n        dirlist = glob (strcat (files, '-*'));\n      endif\n    unwind_protect_cleanup\n      cd (wd);\n    end_unwind_protect\n  endif\n\n  descriptions = {};\n  for k = 1:length (dirlist)\n    descfile = fullfile (prefix, dirlist{k}, \"packinfo\", \"DESCRIPTION\");\n    if (verbose)\n      printf (\"recreating package description from %s\\n\", dirlist{k});\n    endif\n    if (exist (descfile, \"file\"))\n      desc = get_description (descfile);\n      desc.dir = fullfile (prefix, dirlist{k});\n      desc.archprefix = fullfile (archprefix, [desc.name \"-\" desc.version]);\n      descriptions{end + 1} = desc;\n    elseif (verbose)\n      warning (\"directory %s is not a valid package\", dirlist{k});\n    endif\n  endfor\n\n  if (! isempty (files))\n    ## We are rebuilding for a particular package(s) so we should take\n    ## care to keep the other untouched packages in the descriptions\n    descriptions = {descriptions{:}, old_descriptions{:}};\n\n    dup = [];\n    for i = 1:length (descriptions)\n      if (any (dup == i))\n        continue;\n      endif\n      for j = (i+1):length (descriptions)\n        if (any (dup == j))\n          continue;\n        endif\n        if (strcmp (descriptions{i}.name, descriptions{j}.name))\n          dup = [dup, j];\n        endif\n      endfor\n    endfor\n    if (! isempty (dup))\n      descriptions(dup) = [];\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/save_order.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{newdesc} =} save_order (@var{desc})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction newdesc = save_order (desc)\n\n  newdesc = {};\n  for i = 1 : length (desc)\n    deps = desc{i}.depends;\n    if (isempty (deps)\n        || (length (deps) == 1 && strcmp (deps{1}.package, \"octave\")))\n      newdesc{end + 1} = desc{i};\n    else\n      tmpdesc = {};\n      for k = 1 : length (deps)\n        for j = 1 : length (desc)\n          if (strcmp (desc{j}.name, deps{k}.package))\n            tmpdesc{end+1} = desc{j};\n            break;\n          endif\n        endfor\n      endfor\n      if (! isempty (tmpdesc))\n        newdesc = {newdesc{:}, save_order(tmpdesc){:}, desc{i}};\n      else\n        newdesc{end+1} = desc{i};\n      endif\n    endif\n  endfor\n\n  ## Eliminate the duplicates.\n  idx = [];\n  for i = 1 : length (newdesc)\n    for j = (i + 1) : length (newdesc)\n      if (strcmp (newdesc{i}.name, newdesc{j}.name))\n        idx(end + 1) = j;\n      endif\n    endfor\n  endfor\n  newdesc(idx) = [];\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/search_packages.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{retval} =} search_packages (@var{searchterms}, @var{allpackages})\n## @deftypefnx {} {@var{retval} =} search_packages (@var{searchterms}, @var{allpackages}, @var{verbose})\n## Search for all packages on the Octave Packages repository whose\n## descriptions include @var{searchterms}, then either display the search\n## results with brief descriptions, or return the list of matching packages\n## that can also be installed with @code{pkg install}.  If an output variable\n## @var{retval} is provided, then return the list, otherwise display it.\n##\n## If @var{allpackages} is true, then return / display all packages,\n## with no filtering for @var{searchterms}.\n##\n## If @var{verbose} is true, print diagnostic messages.\n## @end deftypefn\n\nfunction retval = search_packages (searchterms, allpackages, verbose = false)\n\n  __pkg__ = get_validated_pkg_list (false, verbose);\n\n  pkgnames = fieldnames (__pkg__);\n\n  prettyprint = (nargout == 0);  # do further string formatting for display\n\n  retval = \"\";\n\n  ## Examine each package in turn and check for search terms and installability\n  installable = false (1, numel (pkgnames));\n  has_search_terms = true (1, numel (pkgnames));\n\n  for i = numel (pkgnames) : -1 : 1\n\n    this = char (pkgnames(i));\n\n    ## Filter based on search term(s) being present in the description.\n    ## If multiple search terms were given, we do a boolean AND over them,\n    ## which returns the set intersection of the search results for the\n    ## individual terms.\n    str = __pkg__.(this).description;\n    if (! allpackages)  # search terms are provided, so we need to filter\n      j = 0;\n      while (has_search_terms(i) && ++j <= numel (searchterms))\n        has_search_terms(i) &= any (regexpi (str, searchterms{j}, 'once'));\n      endwhile\n    endif\n\n    if (! has_search_terms(i))  # no need to examine this package further\n      continue;\n    endif\n\n    ## If we are here, has_search_terms(i) = true.\n\n    ## Determine whether each package can be installed by \"pkg install\".\n    ## This is possible if \"pkg\" is listed as a prerequisite for that package.\n    ## In the case of multiple versions, versions(1) is the most recent.\n    prereq = convert_possible_cell_to_struct (__pkg__.(this).versions(1)).depends;\n    installable(i) = any (strcmp (prereq, \"pkg\"));\n\n    if (prettyprint)  # add more descriptive text to output\n\n      ## Add version number\n      v = convert_possible_cell_to_struct (__pkg__.(this).versions(1)).id;\n      vers(i, 1:numel (v)) = v;\n\n      ## Add description\n      str = __pkg__.(this).description;\n\n      if (! allpackages)  # search terms provided, so favor those parts\n        idx = cell2mat (regexpi (str, searchterms));\n        sp = find (isspace (str));\n        splo = max (sp(sp < min (idx) - 5));\n        if (! isempty (splo))\n          str(1:splo) = [];\n          str = [\"...\", str];\n        endif\n\n        idx = cell2mat (regexpi (str, searchterms));\n        sp = find (isspace (str));\n        sphi = min (sp(sp > max (idx) + 60));\n        if (! isempty (sphi))\n          str(sphi:end) = [];\n          str = [str, \"...\"];\n        endif\n      endif\n\n      if (numel (str) > 80)\n        str(81:end) = [];\n        idx = find (isspace (str), 1, \"last\");\n        str(idx:end) = [];\n        str = [str, \"...\"];\n      endif\n\n      desc(i, 1:numel (str)) = str;\n\n    endif\n\n  endfor\n\n  if (! prettyprint)  # we want only the package names not the versions.\n\n    ## Return only those packages that match the given search terms\n    ## and can also be installed with \"pkg install\".\n    retval = char (pkgnames(has_search_terms & installable));\n\n  else  # pretty print on screen\n\n    if (! any (has_search_terms))  # no search results\n      printf (\"No packages were found with the given search term(s)\\n\");\n      return;\n    endif\n\n    vers(vers == 0) = ' ';\n    desc(desc == 0) = ' ';\n    special = false;\n\n    printf (\"Search found %d results\\n\", nnz (has_search_terms));\n    printf (\"              Package Name | Version | Description\\n\");\n    printf (\"---------------------------+---------+------------------------------------\\n\");\n\n    for i = find (has_search_terms)  # restrict attention to search results only\n      str = char (pkgnames(i));\n      if (! installable(i))\n        str = [str, \" (!)\"];\n        special = true;\n      endif\n      printf (\"%26s | %7s | %s\\n\", str, vers(i, :), desc(i, :));\n    endfor\n\n    if (special)\n      printf (\"(!) These packages have special installation instructions.\\n\");\n    endif\n\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/standardize_paths.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{pkg_list} =} standardize_paths (@var{pkg_list})\n## Convert pathnames in various representations to unique strings.\n##\n## The input @var{pkg_list} must be a cell array of strings.\n##\n## This function is particularly necessary on Windows platforms where pathnames\n## may differ in case (@file{file1} vs.@: @file {FILE1}), file separator\n## (@samp{\\} vs.@: @samp{/}), and format (@file{A~spaces.txt} (8.3 convention)\n## vs.@: @file{A filename with spaces.txt}).\n##\n## @seealso{canonicalize_file_name}\n## @end deftypefn\n\nfunction pkg_list = standardize_paths (pkg_list)\n\n  for i = 1:numel (pkg_list)\n    pkg_list{i}.dir = canonicalize_file_name (pkg_list{i}.dir);\n    pkg_list{i}.archprefix = canonicalize_file_name (pkg_list{i}.archprefix);\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/uninstall.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} uninstall (@var{pkgnames}, @var{handle_deps}, @var{verbose}, @var{local_list}, @var{global_list}, @var{global_install})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction uninstall (pkgnames, handle_deps, verbose, local_list,\n                    global_list, global_install)\n\n  ## Get the list of installed packages.\n  [local_packages, global_packages] = installed_packages (local_list,\n                                                          global_list);\n  if (global_install)\n    installed_pkgs_lst = global_packages;\n  else\n    installed_pkgs_lst = local_packages;\n  endif\n\n  all_pkgs_list = [local_packages, global_packages];\n  all_installed_pkgs_lst = cellfun (@(x) x.name, all_pkgs_list, ...\n                                    \"uniformoutput\", false);\n  num_packages = numel (installed_pkgs_lst);\n  delete_idx = [];\n  available_packages = intersect (all_installed_pkgs_lst, pkgnames);\n\n  for i = 1:num_packages\n    cur_name = installed_pkgs_lst{i}.name;\n    if (any (strcmp (cur_name, pkgnames)))\n      delete_idx(end+1) = i;\n    endif\n  endfor\n\n  ## Are all the packages that should be uninstalled already installed?\n  if (numel (available_packages) != numel (pkgnames))\n    pkgs_not_installed = setxor (available_packages, pkgnames);\n    for idx = 1:numel (pkgs_not_installed)\n      warning (\"package %s is not installed\\n\", pkgs_not_installed{idx});\n    endfor\n  endif\n\n  ## inform user if any global packages can't be uninstalled\n  if (! global_install)\n    for i_global = 1:numel (global_packages)\n      global_pkg_hits = strcmp (global_packages{i_global}.name, pkgnames);\n      for i_global_hit = find (global_pkg_hits)\n        for i_local = 1:numel (local_packages)\n          if (strcmp (pkgnames{i_global_hit},\n                      local_packages{i_local}.name))\n            global_pkg_hits(i_global_hit) = false;\n            warning (\"package %s will remain being installed globally\\n\", ...\n              global_packages{i_global}.name);\n          endif\n        endfor\n      endfor\n      if (any (global_pkg_hits))\n        error (\"%s is a global package and cannot be removed locally\\n\", ...\n          global_packages{i_global}.name);\n      endif\n    endfor\n  endif\n\n  if (isempty (delete_idx))\n    warning (\"no packages will be uninstalled\");\n  else\n\n    ## Compute the packages that will remain installed.\n    idx = setdiff (1:num_packages, delete_idx);\n    remaining_packages = installed_pkgs_lst(idx);\n    to_delete_packages = installed_pkgs_lst(delete_idx);\n\n    ## Check dependencies.\n    if (handle_deps)\n      error_text = \"\";\n      for i = 1:numel (remaining_packages)\n        desc = remaining_packages{i};\n        bad_deps = get_unsatisfied_deps (desc, to_delete_packages, true);\n\n        ## Will the uninstallation break any dependencies?\n        if (! isempty (bad_deps))\n          for i = 1:numel (bad_deps)\n            dep = bad_deps{i};\n            error_text = [error_text \" \" desc.name \" needs \" ...\n                          dep.package \" \" dep.operator \" \" dep.version \"\\n\"];\n          endfor\n        endif\n      endfor\n\n      if (! isempty (error_text))\n        error (\"the following dependencies would be unsatisfied (consider '-nodeps'):\\n  %s\", error_text);\n      endif\n    endif\n\n    ## Delete the directories containing the packages.\n    for i = delete_idx\n      desc = installed_pkgs_lst{i};\n      ## If an 'on_uninstall.m' exist, call it!\n      if (exist (fullfile (desc.dir, \"packinfo\", \"on_uninstall.m\"), \"file\"))\n        wd = pwd ();\n        cd (fullfile (desc.dir, \"packinfo\"));\n        on_uninstall (desc);\n        cd (wd);\n      endif\n      ## Do the actual deletion.\n      if (desc.loaded)\n        rmpath (desc.dir);\n        if (isfolder (getarchdir (desc)))\n          rmpath (getarchdir (desc));\n        endif\n      endif\n      if (isfolder (desc.dir))\n        ## FIXME: If first call to rmdir fails, then error() will\n        ##        stop further processing of getarchdir & archprefix.\n        ##        If this is, in fact, correct, then calls should\n        ##        just be shortened to rmdir (...) and let rmdir()\n        ##        report failure and reason for failure.\n        [status, msg] = rmdir (desc.dir, \"s\");\n        if (status != 1 && isfolder (desc.dir))\n          error (\"couldn't delete directory %s: %s\", desc.dir, msg);\n        endif\n        [status, msg] = rmdir (getarchdir (desc), \"s\");\n        if (status != 1 && isfolder (getarchdir (desc)))\n          error (\"couldn't delete directory %s: %s\", getarchdir (desc), msg);\n        endif\n        if (dirempty (desc.archprefix))\n          sts = rmdir (desc.archprefix, \"s\");\n        endif\n      else\n        warning (\"directory %s previously lost\", desc.dir);\n      endif\n    endfor\n\n    ## Write a new ~/.octave_packages.\n    if (global_install)\n      if (numel (remaining_packages) == 0)\n        [~] = unlink (global_list);\n      else\n        global_packages = save_order (remaining_packages);\n        if (ispc)\n          ## On Windows ensure LFN paths are saved rather than 8.3 style paths\n          global_packages = standardize_paths (global_packages);\n        endif\n        global_packages = make_rel_paths (global_packages);\n        save (global_list, \"global_packages\");\n      endif\n    else\n      if (numel (remaining_packages) == 0)\n        [~] = unlink (local_list);\n      else\n        local_packages = save_order (remaining_packages);\n        if (ispc)\n          local_packages = standardize_paths (local_packages);\n        endif\n        save (local_list, \"local_packages\");\n      endif\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/pkg/private/unload_packages.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} unload_packages (@var{files}, @var{handle_deps}, @var{local_list}, @var{global_list})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction unload_packages (files, handle_deps, local_list, global_list)\n\n  installed_pkgs_lst = installed_packages (local_list, global_list);\n  num_packages = numel (installed_pkgs_lst);\n  ## Add inverse dependencies to field \"invdeps\" of installed_pkgs_lst\n  installed_pkgs_lst = get_inverse_dependencies (installed_pkgs_lst);\n\n  ## Read package names and installdirs into a more convenient format.\n  pnames = cellfun (@(x) x.name, installed_pkgs_lst, \"UniformOutput\", false);\n  pdirs = cellfun (@(x) x.dir, installed_pkgs_lst, \"UniformOutput\", false);\n\n  ## Get the current octave path.\n  p = strtrim (ostrsplit (path (), pathsep ()));\n\n  ## Unload package_name1 ...\n  dirs = {};\n  desc = {};\n  idx = find (ismember (pnames, files));\n  missing_pkgs = setdiff (files, pnames(idx));\n  if (! isempty (missing_pkgs))\n    missing_pkgs = strjoin (missing_pkgs, \" & \");\n    error (\"pkg: package(s): %s not installed\", missing_pkgs);\n  endif\n  dirs = pdirs(idx);\n  desc = installed_pkgs_lst(idx);\n  names = pnames(idx);\n\n  if (handle_deps)\n    ## Check for loaded inverse dependencies of packages to be unloaded.\n    ## First create a list of loaded packages.\n    jdx = find (cellfun (@(x) x.loaded, installed_pkgs_lst));\n\n    ## Exclude packages requested to be unloaded\n    jdx = setdiff (jdx, idx);\n    loaded_pkgs = installed_pkgs_lst(jdx);\n    lpnames = pnames(jdx);\n    p2unload = pnames(idx);\n    linvdeps = {};\n    for i = 1:numel (desc)\n      ## Which inverse dependencies depend on this package-to-be-unloaded?\n      linvdeps = [linvdeps, get_inv_deps(desc{i}, loaded_pkgs, lpnames){:}];\n    endfor\n    if (! isempty (linvdeps))\n      linvdeps = unique (linvdeps);\n      txt = strjoin (linvdeps, \"\\n\\t - \");\n      error ([\"pkg: the following loaded package(s):\\n\", ...\n              \"\\t - %s\\n\", ...\n              \"depend on the one(s) you want to unload.\\n\", ...\n              \"Either unload any depender package(s), or use the '-nodeps' flag.\\n\", ...\n              \"Note: the '-nodeps' flag may affect functionality of these packages.\\n\"],\n             txt);\n    endif\n  endif\n\n  ## Check for architecture dependent directories.\n  archdirs = {};\n  for i = 1:numel (dirs)\n    tmpdir = getarchdir (desc{i});\n    if (isfolder (tmpdir))\n      archdirs{end+1} = dirs{i};\n      archdirs{end+1} = tmpdir;\n    else\n      archdirs{end+1} = dirs{i};\n    endif\n  endfor\n\n  ## Unload the packages.\n  for i = 1:numel (archdirs)\n    d = archdirs{i};\n    idx = strcmp (p, d);\n    if (any (idx))\n      rmpath (d);\n      ## FIXME: We should also check if we need to remove items from EXEC_PATH.\n      if (isguirunning)\n        __event_manager_update_gui_lexer__;\n      endif\n    endif\n  endfor\n\n  ## Unregister Qt help files\n  if (isguirunning)\n    for (ii = 1:numel (dirs))\n      qt_help_file = fullfile (dirs{ii}, \"doc\", [names{ii},\".qch\"]);\n      try\n        if (exist (qt_help_file, \"file\") &&\n            exist(\"__event_manager_unregister_documentation__\"))\n          __event_manager_unregister_documentation__ (qt_help_file);\n        endif\n      catch\n        # do nothing\n      end_try_catch\n    endfor\n  endif\n\nendfunction\n\n\nfunction linvdeps = get_inv_deps (desc, loaded_pkgs, lpnames)\n\n  ## Which nested loaded inverse dependencies depend on the package in desc?\n  linvdeps = intersect (desc.invdeps, lpnames);\n  for i = 1:numel (linvdeps)\n    kdx = find (ismember (lpnames, linvdeps{i}));\n    linvdeps = [ linvdeps (get_inv_deps (loaded_pkgs{kdx}, ...\n                                         loaded_pkgs, lpnames)){:} ];\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/appearance/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/plot/appearance/__clabel__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} __clabel__ (@var{c}, @var{v}, @var{hparent}, @var{label_spacing}, @var{z}, @var{varargin})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction h = __clabel__ (c, v, hparent, label_spacing, z, varargin)\n\n  hax = ancestor (hparent, \"axes\");\n  units = get (hax, \"units\");\n  set (hax, \"units\", \"points\");\n  axpos = get (hax, \"position\");\n  set (hax, \"units\", units);\n  lims = axis (hax);\n  xspacing = axpos(3) / (lims(2) - lims (1));\n  yspacing = axpos(4) / (lims(4) - lims (3));\n\n  if (isscalar (hparent) && isgraphics (hparent, \"hggroup\"))\n    x = get (hparent, \"xdata\");\n    xmin = min (x(:));\n    xmax = max (x(:));\n    y = get (hparent, \"ydata\");\n    ymin = min (y(:));\n    ymax = max (y(:));\n  else\n    xmin = xmax = ymin = ymax = NaN;\n    i = 1;\n    while (i < length (c))\n      clen = c(2,i);\n      data = c(:, i+(1:clen));\n\n      xmin = min ([xmin, data(1,:)]);\n      xmax = max ([xmax, data(1,:)]);\n      ymin = min ([ymin, data(2,:)]);\n      ymax = max ([ymax, data(2,:)]);\n\n      i += clen+1;\n    endwhile\n  endif\n\n  ## Decode contourc output format and place labels.\n  h = [];\n  i = 1;\n  while (i < length (c))\n    clev = c(1,i);\n    clen = c(2,i);\n\n    if (! isempty (v) && ! any (v == clev))\n      i += clen+1;\n      continue;\n    endif\n\n    p = bsxfun (@times, c(:, i+(1:clen)), [xspacing; yspacing]);\n    d = sqrt (sumsq (diff (p, 1, 2)));\n    cumd = cumsum (d);\n    td = cumd(end);\n    ntag = ceil (td / label_spacing);\n\n    if (all (c(:,i+1) == c(:,i+clen)))\n      ## Closed contour\n      ## FIXME: This spreads the tags uniformly around the contour which\n      ## looks nice, but it does not respect the label_spacing attribute.\n      ## Should we follow user input, which can result in two labels being\n      ## quite close to each other?\n      spacing = td / ntag;\n      pos = spacing/2 + spacing*[0:ntag-1];\n    else\n      ## Open contour\n      pos = zeros (1, ntag);\n      pos(1) = (td - label_spacing*(ntag - 1)) / 2;\n      pos(2:ntag) = pos(1) + label_spacing*[1:ntag-1];\n    endif\n\n    tlabel = sprintf (\"%.5g\", clev);\n\n    for tagpos = pos\n\n      j = find (cumd > tagpos, 1);\n      if (isempty (j))\n        j = clen;\n      endif\n      tpos = sum (c(:,i+j:i+j+1), 2) / 2;\n\n      if (   tpos(1) != xmin && tpos(1) != xmax\n          && tpos(2) != ymin && tpos(2) != ymax)\n        trot = 180 / pi * atan2 (diff (c(2,i+j:i+j+1)) * yspacing,\n                                 diff (c(1,i+j:i+j+1)) * xspacing);\n        if (abs (trot) > 90)\n          trot += 180;\n        endif\n\n        if (ischar (z))\n          tpos = [tpos.' clev];\n        elseif (! isempty (z))\n          tpos = [tpos.' z];\n        else\n          tpos = [tpos.' 0];\n        endif\n\n        ht = __go_text__ (hparent, \"position\", tpos, \"string\", tlabel, ...\n                                   \"rotation\", trot, \"clipping\", \"on\", ...\n                                   \"horizontalalignment\", \"center\", ...\n                                   \"userdata\", clev, varargin{:});\n        h = [h; ht];\n      endif\n    endfor\n    i += clen+1;\n  endwhile\n\nendfunction\n\n\n## No test needed for internal helper function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/plot/appearance/__getlegenddata__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{hplots}, @var{strings}] =} __getlegenddata__ (@var{hlegend})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [hplots, text_strings] = __getlegenddata__ (hlegend)\n\n  hplots = [];\n  text_strings = {};\n  ca = getappdata (hlegend, \"__axes_handle__\");\n  if (numel (ca) == 1)\n    kids = get (ca, \"children\");\n  else\n    kids = cell2mat (get (ca, \"children\"));\n  endif\n\n  for i = numel (kids):-1:1\n    typ = get (kids(i), \"type\");\n    if (any (strcmp (typ, {\"line\", \"patch\", \"surface\", \"hggroup\"})))\n      dname = get (kids(i), \"DisplayName\");\n      if (! isempty (dname))\n        hplots(end+1) = kids(i);\n        text_strings(end+1) = dname;\n      endif\n    endif\n  endfor\n\nendfunction\n\n\n## No test needed for internal helper function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/plot/appearance/__rotate_around_axis__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{xr}, @var{yr}, @var{zr}] =} __rotate_around_axis__ (@var{x}, @var{y}, @var{z}, @var{angle}, @var{dir}, @var{origin})\n## Rotate the points given by @var{x}, @var{y}, @var{z} about an axis by\n## @var{angle} degrees.\n##\n## The axis is specified by the vector @var{dir} and the point @var{origin}.\n## @end deftypefn\n\nfunction [xr, yr, zr] = __rotate_around_axis__ (x, y, z, angle, dir, origin)\n\n  dir /= norm (dir);\n  u = dir(1);\n  v = dir(2);\n  w = dir(3);\n\n  a = origin(1);\n  b = origin(2);\n  c = origin(3);\n\n  sa = sind (angle);\n  ca = cosd (angle);\n\n  if (a == 0 && b == 0 && c == 0)\n    tmp = (u*x + v*y + w*z) * (1 - ca);\n\n    xr = u*tmp + x*ca + (-w*y + v*z)*sa;\n    yr = v*tmp + y*ca + (w*x - u*z)*sa;\n    zr = w*tmp + z*ca + (-v*x + u*y)*sa;\n  else\n    one_m_ca = 1 - ca;\n    tmp = u*x + v*y + w*z;\n\n    xr = ((a*(v^2 + w^2) - u*(b*v + c*w - tmp))*one_m_ca\n          + x*ca + (-c*v + b*w - w*y + v*z)*sa);\n    yr = ((b*(u^2 + w^2) - v*(a*u + c*w - tmp))*one_m_ca\n          + y*ca + (c*u - a*w + w*x - u*z)*sa);\n    zr = ((c*(u^2 + v^2) - w*(a*u + b*v - tmp))*one_m_ca\n          + z*ca + (-b*u + a*v - v*x + u*y)*sa);\n  endif\n\nendfunction\n\n\n## No test needed for internal helper function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/plot/appearance/annotation.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} annotation (@var{type})\n## @deftypefnx {} {} annotation (\"line\", @var{x}, @var{y})\n## @deftypefnx {} {} annotation (\"arrow\", @var{x}, @var{y})\n## @deftypefnx {} {} annotation (\"doublearrow\", @var{x}, @var{y})\n## @deftypefnx {} {} annotation (\"textarrow\", @var{x}, @var{y})\n## @deftypefnx {} {} annotation (\"textbox\", @var{pos})\n## @deftypefnx {} {} annotation (\"rectangle\", @var{pos})\n## @deftypefnx {} {} annotation (\"ellipse\", @var{pos})\n## @deftypefnx {} {} annotation (@dots{}, @var{prop}, @var{val})\n## @deftypefnx {} {} annotation (@var{hf}, @dots{})\n## @deftypefnx {} {@var{h} =} annotation (@dots{})\n## Draw annotations to emphasize parts of a figure.\n##\n## You may build a default annotation by specifying only the @var{type}\n## of the annotation.\n##\n## Otherwise you can select the type of annotation and then set its position\n## using either @var{x} and @var{y} coordinates for line-based annotations or a\n## position vector @var{pos} for others.  In either case, coordinates are\n## interpreted using the @qcode{\"units\"} property of the annotation object.\n## The default is @qcode{\"normalized\"}, which means the lower left hand corner\n## of the figure has coordinates @samp{[0 0]} and the upper right hand corner\n## @samp{[1 1]}.\n##\n## If the first argument @var{hf} is a figure handle, then plot into this\n## figure, rather than the current figure returned by @code{gcf}.\n##\n## Further arguments can be provided in the form of @var{prop}/@var{val} pairs\n## to customize the annotation appearance.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## annotation object.  This can be used with the @code{set} function to\n## customize an existing annotation object.\n##\n## All annotation objects share two properties:\n##\n## @itemize\n## @item @qcode{\"units\"}: the units in which coordinates are interpreted.@*\n## Its value may be one of @qcode{\"centimeters\"} | @qcode{\"characters\"} |\n## @qcode{\"inches\"} | @qcode{\"@{normalized@}\"} | @qcode{\"pixels\"} |\n## @qcode{\"points\"}.\n##\n## @item @qcode{\"position\"}: a four-element vector [x0 y0 width height].@*\n## The vector specifies the coordinates (x0,y0) of the origin of the annotation\n## object, its width, and its height.  The width and height may be negative,\n## depending on the orientation of the object.\n##\n## @end itemize\n##\n## Valid annotation types and their specific properties are described\n## below:\n##\n## @table @asis\n## @item @qcode{\"line\"}\n## Constructs a line.  @var{x} and @var{y} must be two-element vectors\n## specifying the x and y coordinates of the two ends of the line.\n##\n## The line can be customized using @qcode{\"linewidth\"}, @qcode{\"linestyle\"},\n## and @qcode{\"color\"} properties the same way as for @code{line} objects.\n##\n## @item @qcode{\"arrow\"}\n## Construct an arrow.  The second point in vectors @var{x} and @var{y}\n## specifies the arrowhead coordinates.\n##\n## Besides line properties, the arrowhead can be customized using\n## @qcode{\"headlength\"}, @qcode{\"headwidth\"}, and @qcode{\"headstyle\"}\n## properties.  Supported values for @qcode{\"headstyle\"} property are:\n## [@qcode{\"diamond\"} | @qcode{\"ellipse\"} | @qcode{\"plain\"} |\n## @qcode{\"rectangle\"} | @qcode{\"vback1\"} | @qcode{\"@{vback2@}\"} |\n## @qcode{\"vback3\"}]\n##\n## @item @qcode{\"doublearrow\"}\n## Construct a double arrow.  Vectors @var{x} and @var{y} specify the\n## arrowhead coordinates.\n##\n## The line and the arrowhead can be customized as for arrow annotations, but\n## some property names are duplicated:\n## @qcode{\"head1length\"}/@qcode{\"head2length\"},\n## @qcode{\"head1width\"}/@qcode{\"head2width\"}, etc.  The index 1 marks the\n## properties of the arrowhead at the first point in @var{x} and @var{y}\n## coordinates.\n##\n## @item @qcode{\"textarrow\"}\n## Construct an arrow with a text label at the opposite end from the arrowhead.\n##\n## Use the @qcode{\"string\"} property to change the text string.\n## The line and the arrowhead can be customized as for arrow annotations, and\n## the text can be customized using the same properties as @code{text} graphics\n## objects.  Note, however, that some text property names are prefixed with\n## \"text\" to distinguish them from arrow properties:\n## @qcode{\"textbackgroundcolor\"}, @qcode{\"textcolor\"},\n## @qcode{\"textedgecolor\"}, @qcode{\"textlinewidth\"},\n## @qcode{\"textmargin\"}, @qcode{\"textrotation\"}.\n##\n## @item @qcode{\"textbox\"}\n## Construct a box with text inside.  @var{pos} specifies the\n## @qcode{\"position\"} property of the annotation.\n##\n## Use the @qcode{\"string\"} property to change the text string.\n## You may use @qcode{\"backgroundcolor\"}, @qcode{\"edgecolor\"},\n## @qcode{\"linestyle\"}, and @qcode{\"linewidth\"} properties to customize\n## the box background color and edge appearance.  A limited set of @code{text}\n## objects properties are also available; Besides @qcode{\"font@dots{}\"}\n## properties, you may also use @qcode{\"horizontalalignment\"} and\n## @qcode{\"verticalalignment\"} to position the text inside the box.\n##\n## Finally, the @qcode{\"fitboxtotext\"} property controls the actual extent of\n## the box.  If @qcode{\"on\"} (the default) the box limits are fitted to the\n## text extent.\n##\n## @item @qcode{\"rectangle\"}\n## Construct a rectangle.  @var{pos} specifies the @qcode{\"position\"} property\n## of the annotation.\n##\n## You may use @qcode{\"facecolor\"}, @qcode{\"color\"}, @qcode{\"linestyle\"}, and\n## @qcode{\"linewidth\"} properties to customize the rectangle background color\n## and edge appearance.\n##\n## @item @qcode{\"ellipse\"}\n## Construct an ellipse.  @var{pos} specifies the @qcode{\"position\"} property\n## of the annotation.\n##\n## See @qcode{\"rectangle\"} annotations for customization.\n## @end table\n##\n## @seealso{xlabel, ylabel, zlabel, title, text, gtext, legend, colorbar}\n## @end deftypefn\n\nfunction h = annotation (varargin)\n\n  nargin = numel (varargin);\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  objtype = \"\";\n  hf = [];\n  lims = [];\n  x = y = [];\n  opts = {};\n\n  ## Parent figure\n  if (isfigure (varargin{1}))\n    hf = varargin{1};\n    varargin(1) = [];  nargin -= 1;\n  endif\n\n  ## Annotation type\n  if (! ischar (varargin{1}))\n    print_usage ();\n  endif\n  objtype = varargin{1};\n  varargin(1) = [];  nargin -= 1;\n\n  switch (objtype)\n\n    case {\"line\", \"arrow\", \"doublearrow\", \"textarrow\"}\n      if (nargin == 0)\n        lims = [];\n      elseif (nargin >= 2)\n        x = varargin{1};\n        y = varargin{2};\n        varargin(1:2) = [];\n\n        if (! (isnumeric (x) && isnumeric (y)\n               && numel (x) == 2 && numel (y) == 2))\n          error (\"annotation: X and Y must be 2-element vectors\");\n        endif\n        lims = [x(1), y(1), diff(x), diff(y)];\n      else\n        print_usage ();\n      endif\n\n    case {\"textbox\", \"ellipse\", \"rectangle\"}\n      if (nargin == 0)\n        lims = [];\n      else\n        lims = varargin{1};\n        varargin(1) = [];\n\n        if (! isvector (lims) || numel (lims) != 4)\n          error (\"annotation: POS must be a 4-element vector\");\n        endif\n      endif\n\n    otherwise\n      error (\"annotation: unknown annotation TYPE %s\", objtype);\n\n  endswitch\n\n  ## options\n  opts = varargin;\n  if (! isempty (opts))\n    if (mod (numel (opts), 2) != 0 || ! all (cellfun ('ischar', opts(1:2:end))))\n      warning (\"annotation: couldn't parse PROP/VAL pairs, skipping\");\n      opts = {};\n    endif\n  endif\n\n  ## Create annotation\n  showhidden = get (0, \"showhiddenhandles\");\n  set (0, \"showhiddenhandles\", \"on\");\n\n  unwind_protect\n    if (isempty (hf))\n      hf = gcf ();\n    endif\n\n    ## Axes\n    hca = get (hf, \"currentaxes\");\n\n    hax = findall (hf, \"-depth\", 1, \"tag\", \"scribeoverlay\");\n    if (isempty (hax))\n      hax = buildoverlay (hf);\n    else\n      ## Make sure the annotations are on top of other axes\n      axes (hax);\n    endif\n\n    ## Build annotation\n    htmp = buildannot (hax, objtype, lims);\n\n    ## Set user defined properties\n    if (! isempty (opts))\n      set (htmp, opts{:});\n    endif\n\n  unwind_protect_cleanup\n    set (0, \"showhiddenhandles\", showhidden);\n    set (hf, \"currentaxes\", hca);\n  end_unwind_protect\n\n  if (nargout != 0)\n    h = htmp;\n  endif\n\nendfunction\n\nfunction hax = buildoverlay (hf)\n\n  hax = axes (\"parent\", hf, \"visible\", \"off\", \"tag\", \"scribeoverlay\", ...\n              \"position\", [0 0 1 1], \"xlim\", [0 1], \"ylim\", [0 1], ...\n              \"handlevisibility\", \"off\");\n\n  ## Hidden property to store figure size in absolute (points) coordinates.\n  addproperty (\"figsize_points\", hax, \"axesxminortickvalues\", []);\n  update_figsize_points (hf, {}, hax);\n\n  listener = {@update_figsize_points, hax};\n  addlistener (hf, \"position\", listener);\n\n  delfcn = @(~, ~) dellistener (hf, \"position\", listener);\n  set (hax, \"deletefcn\", delfcn);\n\nendfunction\n\nfunction update_figsize_points (hf, ~, hax)\n\n  persistent recursive = false;\n\n  if (! recursive)\n    recursive = true;\n    units = get (hf, \"units\");\n    set (hf, \"units\", \"points\");\n    pos = get (hf, \"position\");\n    set (hf, \"units\", units);\n\n    set (hax, \"figsize_points\", pos(3:4));\n    recursive = false;\n  endif\n\nendfunction\n\nfunction h = buildannot (hax, objtype, pos)\n\n  ## Base hggroup\n  h = hggroup (hax);\n\n  ## Base context menu\n  hui = uicontextmenu (get (hax, \"parent\"));\n\n  ## Add common properties\n  if (strcmp (graphics_toolkit (), \"gnuplot\"))\n    ## FIXME: this is a workaround for bug #39394 (gnuplot toolkit)\n    defprops = {\"position\", \"axesposition\", [0.3 0.3 0.1 0.1], ...\n                \"units\", \"textunits\", \"data\"};\n  else\n    defprops = {\"position\", \"axesposition\", [0.3 0.3 0.1 0.1], ...\n                \"units\", \"axesunits\", \"normalized\"};\n  endif\n  addbaseprops (h, defprops);\n  setappdata (h, \"__former_units__\", \"normalized\");\n\n  ## Add common menus\n  prop = \"units\";\n  vals = set (h, prop);\n  addbasemenu (hui, h, prop, vals, \"Units\");\n\n  ## Common updaters\n  listener = {@update_position, h, true};\n\n  addlistener (hax, \"figsize_points\", listener);\n\n  delfcn = @(~, ~) dellistener (hax, \"figsize_points\", listener);\n  set (h, \"deletefcn\", delfcn);\n\n  addlistener (h, \"units\", {@update_position, h});\n\n  ## Now work with normalized coordinates\n  if (! isempty (pos))\n    set (h, \"position\", pos);\n  endif\n  pos = getnormpos (h);\n\n  ## Build annotation object and its specific properties/updaters\n  switch (objtype)\n    case {\"line\", \"arrow\", \"doublearrow\", \"textarrow\"}\n      ## Add properties\n      proptable = lineprops ();\n      if (strcmp (objtype, \"arrow\"))\n        proptable = [proptable arrowprops()];\n      elseif (strcmp (objtype, \"doublearrow\"))\n        proptable = [proptable dblarrowprops()];\n      elseif (strcmp (objtype, \"textarrow\"))\n        proptable = [proptable arrowprops()];\n        proptable = [proptable textprops()];\n      endif\n\n      addbaseprops (h, proptable);\n\n      ## create line\n      hli = line ([pos(1); (pos(1) + pos(3))],\n                  [pos(2); (pos(2) + pos(4))],\n                  \"color\", get (h, \"color\"),\n                  \"linestyle\", get (h, \"linestyle\"),\n                  \"linewidth\", get (h, \"linewidth\"),\n                  \"parent\", h);\n\n      linemenu (hui, h);\n      set (hli, \"uicontextmenu\", hui);\n\n      ## create patch(s) and text\n      if (strcmp (objtype, \"arrow\"))\n        [x, y] = arrowcoordinates (h);\n        hpa = patch (x, y, get (h, \"color\"), \"edgecolor\", get (h, \"color\"),\n                     \"parent\", h);\n        update_arrow (h, {}, \"position\", hpa);\n\n        arrowmenu (hui, h);\n        set (hpa, \"uicontextmenu\", hui);\n\n      elseif (strcmp (objtype, \"doublearrow\"))\n        [x, y] = arrowcoordinates (h, 1);\n        hpa = patch (x, y, get (h, \"color\"), \"edgecolor\", get (h, \"color\"),\n                     \"parent\", h);\n\n        [x, y] = arrowcoordinates (h, 2);\n        hpa(2) = patch (x, y, get (h, \"color\"), \"edgecolor\", get (h, \"color\"),\n                        \"parent\", h);\n\n        update_arrow (h, {}, \"position\", hpa);\n\n        dblarrowmenu (hui, h);\n        set (hpa, \"uicontextmenu\", hui);\n\n      elseif (strcmp (objtype, \"textarrow\"))\n        [x, y] = arrowcoordinates (h);\n        hpa = patch (x, y, get (h, \"color\"), \"edgecolor\", get (h, \"color\"),\n                     \"parent\", h);\n        update_arrow (h, {}, \"position\", hpa);\n\n        hte = text (get (h, \"position\")(1),\n                    get (h, \"position\")(2),\n                    get (h, \"string\"),\n                    \"color\", get (h, \"color\"), \"parent\", h);\n        propnames = textprops (\"names\");\n        for i = 1 : numel (propnames)\n          update_text (h, {}, propnames{i}, hte);\n        endfor\n        update_text (h, {}, \"position\", hte);\n\n        arrowmenu (hui, h);\n        textmenu (hui, h);\n        set (hpa, \"uicontextmenu\", hui);\n        set (hte, \"uicontextmenu\", hui);\n\n      endif\n\n      ## updaters\n      addlistener (h, \"color\", {@update_line, \"color\", hli});\n      addlistener (h, \"linestyle\", {@update_line, \"linestyle\", hli});\n      addlistener (h, \"linewidth\", {@update_line, \"linewidth\", hli});\n      addlistener (h, \"x\", {@update_line, \"x\", hli});\n      addlistener (h, \"y\", {@update_line, \"y\", hli});\n      addlistener (h, \"position\", {@update_line, \"position\", hli});\n\n      if (strcmp (objtype, \"arrow\"))\n        addlistener (h, \"position\", {@update_arrow, \"position\", hpa});\n        addlistener (h, \"headwidth\", {@update_arrow, \"position\", hpa});\n        addlistener (h, \"headstyle\", {@update_arrow, \"position\", hpa});\n        addlistener (h, \"headlength\", {@update_arrow, \"position\", hpa});\n        addlistener (h, \"color\", {@update_arrow, \"color\", hpa});\n\n      elseif (strcmp (objtype, \"doublearrow\"))\n        addlistener (h, \"position\", {@update_arrow, \"position\", hpa});\n        addlistener (h, \"head1width\",\n                     {@update_arrow, \"position\", [hpa(1), 0]});\n        addlistener (h, \"head2width\",\n                     {@update_arrow, \"position\", [0, hpa(2)]});\n        addlistener (h, \"head1style\",\n                     {@update_arrow, \"position\", [hpa(1), 0]});\n        addlistener (h, \"head2style\",\n                     {@update_arrow, \"position\", [0, hpa(2)]});\n        addlistener (h, \"head1length\",\n                     {@update_arrow, \"position\", [hpa(1), 0]});\n        addlistener (h, \"head2length\",\n                     {@update_arrow, \"position\", [0, hpa(2)]});\n        addlistener (h, \"color\", {@update_arrow, \"color\", hpa});\n\n      elseif (strcmp (objtype, \"textarrow\"))\n        addlistener (h, \"position\", {@update_arrow, \"position\", hpa});\n        addlistener (h, \"headwidth\", {@update_arrow, \"position\", hpa});\n        addlistener (h, \"headstyle\", {@update_arrow, \"position\", hpa});\n        addlistener (h, \"headlength\", {@update_arrow, \"position\", hpa});\n        addlistener (h, \"color\", {@update_arrow, \"color\", hpa});\n        propnames = textprops (\"names\");\n        for i = 1 : numel (propnames)\n          addlistener (h, propnames{i},\n                       {@update_text, propnames{i}, hte});\n          if (any (strcmp (propnames{i},\n                           {\"fontangle\", \"fontname\", ...\n                            \"fontsize\", \"fontweight\", ...\n                            \"horizontalalignment\", \"string\", ...\n                            \"textmargin\", \"textrotation\", ...\n                            \"verticalalignment\"})))\n            addlistener (h, propnames{i}, {@update_text, \"position\", hte});\n          endif\n        endfor\n        addlistener (h, \"position\", {@update_text, \"position\", hte});\n        addlistener (h, \"color\", {@update_text, \"color\", hte});\n      endif\n\n    case {\"rectangle\", \"ellipse\"}\n\n      ## Add properties\n      addbaseprops (h, rectprops ());\n\n      ## Create rectangle/ellipse\n      if (strcmp (objtype, \"rectangle\"))\n        [x, y] = pos2rect (pos);\n      else\n        [x, y] = pos2ell (pos);\n      endif\n\n      hr = patch (x, y, \"parent\", h);\n\n      propnames = rectprops (\"names\");\n      for i = 1 : numel (propnames)\n        update_rect (h, {}, propnames{i}, hr, objtype);\n      endfor\n\n      rectmenu (hui, h);\n      set (hr, \"uicontextmenu\", hui);\n\n      ## Updaters\n      addlistener (h, \"position\", {@update_rect, \"position\", hr, objtype});\n      for i = 1 : numel (propnames)\n        addlistener (h, propnames{i},\n                     {@update_rect, propnames{i}, hr, objtype});\n      endfor\n\n    case \"textbox\"\n\n      ## Add properties\n      addbaseprops (h, textboxprops());\n\n      ## Create textbox\n      hpa = patch (\"parent\", h);\n      hte = text (pos(1), pos(2), get (h, \"string\"),\n                  \"color\", get (h, \"color\"), \"parent\", h);\n      update_textbox (h, {}, \"position\", [hte hpa]);\n\n      propnames = textboxprops (\"names\");\n      for i = 1 : numel (propnames)\n        update_textbox (h, {}, propnames{i}, [hte hpa]);\n      endfor\n\n      textboxmenu (hui, h);\n      set (hpa, \"uicontextmenu\", hui);\n      set (hte, \"uicontextmenu\", hui);\n\n      ## Updaters\n      addlistener (h, \"position\", {@update_textbox, \"position\", [hte hpa]});\n      for i = 1 : numel (propnames)\n        addlistener (h, propnames{i},\n                     {@update_textbox, propnames{i}, [hte hpa]});\n      endfor\n      addlistener (h, \"horizontalalignment\",\n                   {@update_textbox, \"position\", [hte hpa]});\n      addlistener (h, \"verticalalignment\",\n                   {@update_textbox, \"position\", [hte hpa]});\n\n  endswitch\n\nendfunction\n\nfunction props = lineprops (varargin)\n\n  ## FIXME: Use \"axesx(y)lim\" instead of \"linex(y)data\"\n  props = {\"color\", \"color\", [0 0 0], ...\n           \"linestyle\",  \"linelinestyle\", \"-\", ...\n           \"linewidth\", \"linelinewidth\", 0.5, ...\n           \"x\", \"linexdata\", [0.3 0.4], ...\n           \"y\", \"lineydata\", [0.3 0.4]};\n  if (strcmp (varargin, \"names\"))\n    props = props(1:3:end);\n  endif\n\nendfunction\n\nfunction col = basecolors ()\n  col = {\"blue\", \"black\", \"cyan\", \"green\", \"magenta\", \"red\", ...\n         \"white\", \"yellow\", \"none\"};\nendfunction\n\nfunction linemenu (hui, hpar)\n\n  hm = uimenu (\"parent\", hui, \"label\", \"Line\");\n\n  ## Color\n  vals = basecolors ();\n  addbasemenu (hm, hpar, \"Color\", vals);\n\n  ## Linestyle\n  vals = set (hpar, \"linestyle\");\n  addbasemenu (hm, hpar, \"Linestyle\", vals);\n\n  ## Linewidth\n  vals = [0.5 1 1.5 2];\n  addbasemenu (hm, hpar, \"Linewidth\", vals);\n\nendfunction\n\nfunction props = arrowprops (varargin)\n\n  props = {\"headlength\", \"data\", 10, ...\n           \"headstyle\",  \"radio\", \"diamond|ellipse|none|plain|rectangle|vback1|{vback2}|vback3\", ...\n           \"headwidth\",  \"data\", 10};\n  if (strcmp (varargin, \"names\"))\n    props = props(1:3:end);\n  endif\n\nendfunction\n\nfunction arrowmenu (hui, hpar)\n\n  hm = uimenu (\"parent\", hui, \"label\", \"Arrowhead\");\n\n  ## Headlength/width\n  vals = 6:2:16;\n  addbasemenu (hm, hpar, \"headlength\", vals, \"Length\");\n  addbasemenu (hm, hpar, \"headwidth\", vals, \"Width\");\n\n  ## Headstyle\n  vals = set (hpar, \"headstyle\");\n  addbasemenu (hm, hpar, \"Headstyle\", vals);\n\nendfunction\n\nfunction props = dblarrowprops (varargin)\n\n  props = {\"head1length\", \"data\", 10, ...\n           \"head1style\",  \"radio\", \"diamond|ellipse|none|plain|rectangle|vback1|{vback2}|vback3\", ...\n           \"head1width\",  \"data\", 10, ...\n           \"head2length\", \"data\", 10, ...\n           \"head2style\",  \"radio\", \"diamond|ellipse|none|plain|rectangle|vback1|{vback2}|vback3\", ...\n           \"head2width\", \"data\", 10};\n  if (strcmp (varargin, \"names\"))\n    props = props(1:3:end);\n  endif\n\nendfunction\n\nfunction dblarrowmenu (hui, hpar)\n\n  hm1 = uimenu (\"parent\", hui, \"label\", \"Arrowhead #1\");\n  hm2 = uimenu (\"parent\", hui, \"label\", \"Arrowhead #2\");\n\n  ## Headlength/width\n  vals = 6:2:16;\n  addbasemenu (hm1, hpar, \"head1length\", vals, \"Length\");\n  addbasemenu (hm1, hpar, \"head1width\", vals, \"Width\");\n  addbasemenu (hm2, hpar, \"head2length\", vals, \"Length\");\n  addbasemenu (hm2, hpar, \"head2width\", vals, \"Width\");\n\n  ## Headstyle\n  vals = set (hpar, \"head1style\");\n  addbasemenu (hm1, hpar, \"head1style\", vals, \"Headstyle\");\n  addbasemenu (hm2, hpar, \"head2style\", vals, \"Headstyle\");\n\nendfunction\n\nfunction props = textprops (varargin)\n\n  props = {\"fontangle\", \"textfontangle\", \"normal\", ...\n           \"fontname\",  \"textfontname\", \"*\", ...\n           \"fontsize\", \"textfontsize\", 10, ...\n           \"fontunits\", \"textfontunits\", \"points\", ...\n           \"fontweight\",  \"textfontweight\", \"normal\", ...\n           \"horizontalalignment\", \"texthorizontalalignment\", \"left\", ...\n           \"interpreter\", \"textinterpreter\", \"tex\", ...\n           \"string\", \"textstring\", \"\", ...\n           \"textbackgroundcolor\", \"textbackgroundcolor\", \"none\", ...\n           \"textcolor\", \"textcolor\", \"k\", ...\n           \"textedgecolor\", \"textedgecolor\", \"none\", ...\n           \"textlinewidth\", \"textlinewidth\",0.5, ...\n           \"textmargin\", \"textmargin\", 5, ...\n           \"textrotation\", \"textrotation\", 0, ...\n           \"verticalalignment\", \"textverticalalignment\", \"middle\"};\n  if (strcmp (varargin, \"names\"))\n    props = props(1:3:end);\n  endif\n\nendfunction\n\nfunction stringdlg (hpar, prop)\n\n  def = get (hpar, prop);\n  if (iscell (def))\n    prompt = arrayfun (@(n) sprintf (\"Line #%d:\", n), 1 : numel (def),\n                       \"uniformoutput\", false);\n  else\n    prompt = \"\";\n    def = {def};\n  endif\n\n  cstr = inputdlg (prompt, prop, 1, def);\n\n  if (! isempty (cstr))\n    set (hpar, prop, cstr);\n  endif\n\nendfunction\n\nfunction textmenu (hui, hpar)\n\n  hm = uimenu (\"parent\", hui, \"label\", \"Text\");\n\n  ## String;\n  prop = \"String\";\n  fcn = @(~, ~) stringdlg (hpar, prop);\n  uimenu (hm, \"label\", prop, \"callback\", fcn);\n\n  ## Font properties\n  prop = \"textcolor\";\n  vals = basecolors ();\n  addbasemenu (hm, hpar, prop, vals, \"Color\");\n  prop = \"fontsize\";\n  vals = 8:2:20;\n  addbasemenu (hm, hpar, prop, vals, \"Size\");\n  prop = \"fontangle\";\n  vals = set (hpar, prop);\n  addbasemenu (hm, hpar, prop, vals, \"Angle\");\n  prop = \"fontweight\";\n  vals = set (hpar, prop);\n  addbasemenu (hm, hpar, prop, vals, \"Weight\");\n  prop = \"textrotation\";\n  vals = 0:90:270;\n  addbasemenu (hm, hpar, prop, vals, \"Rotation\");\n\n  prop = \"horizontalalignment\";\n  vals = set (hpar, prop);\n  addbasemenu (hm, hpar, prop, vals, \"Horizontal Alignment\", ...\n               \"separator\", \"on\");\n  prop = \"verticalalignment\";\n  vals = set (hpar, prop);\n  addbasemenu (hm, hpar, prop, vals, \"Vertical Alignment\");\n\n  ## FIXME: Add text background properties (Bug #57407).\n\n  prop = \"interpreter\";\n  vals = set (hpar, prop);\n  addbasemenu (hm, hpar, prop, vals, \"Interpreter\", ...\n               \"separator\", \"on\");\n\nendfunction\n\nfunction props = textboxprops (varargin)\n\n  props = {\"backgroundcolor\", \"patchfacecolor\", \"none\", ...\n           \"color\", \"textcolor\", [0 0 0], ...\n           \"edgecolor\", \"patchedgecolor\", [0 0 0], ...\n           \"facealpha\", \"patchfacealpha\", 1, ...\n           \"fontangle\", \"textfontangle\", \"normal\", ...\n           \"fontname\",  \"textfontname\", \"*\", ...\n           \"fontsize\", \"textfontsize\", 10, ...\n           \"fontunits\", \"textfontunits\", \"points\", ...\n           \"fontweight\",  \"textfontweight\", \"normal\", ...\n           \"horizontalalignment\", \"texthorizontalalignment\", \"left\", ...\n           \"interpreter\", \"textinterpreter\", \"tex\", ...\n           \"linestyle\",  \"linelinestyle\", \"-\", ...\n           \"linewidth\", \"linelinewidth\", 0.5, ...\n           \"string\", \"textstring\", \"\", ...\n           \"fitboxtotext\", \"radio\", \"{on}|off\", ...\n           \"margin\", \"data\", 5, ...\n           \"verticalalignment\", \"textverticalalignment\", \"top\"};\n  if (strcmp (varargin, \"names\"))\n    props = props(1:3:end);\n  endif\n\nendfunction\n\nfunction textboxmenu (hui, hpar)\n\n  ## Text properties\n  hm1 = uimenu (\"parent\", hui, \"label\", \"Text\");\n\n  prop = \"String\";\n  fcn = @(~, ~) stringdlg (hpar, prop);\n  uimenu (hm1, \"label\", prop, \"callback\", fcn);\n\n  prop = \"Color\";\n  vals = basecolors ();\n  addbasemenu (hm1, hpar, prop, vals);\n  prop = \"fontsize\";\n  vals = 8:2:20;\n  addbasemenu (hm1, hpar, prop, vals, \"Size\");\n  prop = \"fontangle\";\n  vals = set (hpar, prop);\n  addbasemenu (hm1, hpar, prop, vals, \"Angle\");\n  prop = \"fontweight\";\n  vals = set (hpar, prop);\n  addbasemenu (hm1, hpar, prop, vals, \"Weight\");\n\n  prop = \"horizontalalignment\";\n  vals = set (hpar, prop);\n  addbasemenu (hm1, hpar, prop, vals, \"Horizontal Alignment\", ...\n               \"separator\", \"on\");\n  prop = \"verticalalignment\";\n  vals = set (hpar, prop);\n  addbasemenu (hm1, hpar, prop, vals, \"Vertical Alignment\");\n  prop = \"Margin\";\n  vals = 2:2:10;\n  addbasemenu (hm1, hpar, prop, vals);\n\n  prop = \"interpreter\";\n  vals = set (hpar, prop);\n  addbasemenu (hm1, hpar, prop, vals, \"Interpreter\", ...\n               \"separator\", \"on\");\n\n  ## Background properties\n  hm2 = uimenu (\"parent\", hui, \"label\", \"Background\");\n\n  prop = \"fitboxtotext\";\n  vals = set (hpar, prop);\n  addbasemenu (hm2, hpar, prop, vals, \"Fit box to text\");\n  prop = \"backgroundcolor\";\n  vals = basecolors ();\n  addbasemenu (hm2, hpar, prop, vals, \"Face Color\");\n  prop = \"edgecolor\";\n  vals = basecolors ();\n  addbasemenu (hm2, hpar, prop, vals, \"Edge Color\");\n  prop = \"linestyle\";\n  vals = set (hpar, prop);\n  addbasemenu (hm2, hpar, prop, vals, \"Line Style\");\n  prop = \"linewidth\";\n  vals = 0.5:.5:2;\n  addbasemenu (hm2, hpar, prop, vals, \"Line Width\");\n\nendfunction\n\nfunction props = rectprops (varargin)\n\n  props = {\"color\", \"patchedgecolor\", \"k\", ...\n           \"facealpha\", \"patchfacealpha\", 1, ...\n           \"facecolor\", \"patchfacecolor\", \"none\", ...\n           \"linestyle\", \"patchlinestyle\", \"-\", ...\n           \"linewidth\", \"patchlinewidth\", 0.5};\n  if (strcmp (varargin, \"names\"))\n    props = props(1:3:end);\n  endif\n\nendfunction\n\nfunction rectmenu (hui, hpar)\n\n  prop = \"facecolor\";\n  vals = basecolors ();\n  addbasemenu (hui, hpar, prop, vals, \"Face Color\");\n  prop = \"color\";\n  vals = basecolors ();\n  addbasemenu (hui, hpar, prop, vals, \"Edge Color\");\n  prop = \"linestyle\";\n  vals = set (hpar, prop);\n  addbasemenu (hui, hpar, prop, vals, \"Line Style\");\n  prop = \"linewidth\";\n  vals = 0.5:.5:2;\n  addbasemenu (hui, hpar, prop, vals, \"Line Width\");\n\nendfunction\n\nfunction addbaseprops (h, proptable)\n  cellfun (@(pname, ptype, parg) addproperty (pname, h, ptype, parg),\n           proptable(1:3:end), proptable(2:3:end), proptable(3:3:end));\nendfunction\n\n## FIXME: there are some calls to addbasemenu with option-like arguments but\n## we don't do anything with varargin here.  What is the right thing to do?\nfunction addbasemenu (hm, hpar, pname, vals, mainlabel = \"\", varargin)\n\n  if (isempty (mainlabel))\n    mainlabel = pname;\n  endif\n\n  h = uimenu (\"parent\", hm, \"label\", mainlabel);\n\n  is_numeric = ! iscell (vals);\n  nv = numel (vals);\n  htmp = zeros (1, nv);\n  for i = 1:nv\n    if (! is_numeric)\n      val = label = vals{i};\n    else\n      val = vals(i);\n      label = disp (val);\n      ## Delete newline character added by disp().  See bug #67976.\n      label(end) = [];\n    endif\n\n    fcn = @(~, ~) set (hpar, pname, val);\n    htmp(i) = uimenu (h, \"label\", label, \"callback\", fcn);\n  endfor\n\n  handle_check (hpar, {}, htmp, pname, is_numeric);\n  addlistener (hpar, pname, {@handle_check, htmp, pname, is_numeric});\n\nendfunction\n\nfunction handle_check (h, ~, hmenus, prop, is_numeric)\n\n  vals = get (hmenus, \"label\");\n  current = get (h, prop);\n  if (is_numeric)\n    current = disp (current);\n    ## Delete newline character added by disp().  See bug #67976.\n    current(end) = [];\n  endif\n\n  idx = strcmp (vals, current);\n  set (hmenus(idx), \"checked\", \"on\");\n  set (hmenus(! idx), \"checked\", \"off\");\n\nendfunction\n\nfunction update_position (h1, ~, h, force = false)\n\n  if (! force)\n    pos = convertposition (h, getappdata (h, \"__former_units__\"),\n                           get (h, \"units\"));\n    setappdata (h, \"__former_units__\", get (h, \"units\"));\n    set (h, \"position\", pos);\n  else\n    ## FIXME: Inefficient trick to force all objects to be redrawn\n    set (h, \"position\", [0 0 .5 .5], \"position\", get (h, \"position\"));\n  endif\n\nendfunction\n\nfunction update_line (h, ~, prop, hli)\n  persistent recursive = false;\n\n  if (! recursive)\n    switch (prop)\n      case \"color\"\n        set (hli, \"color\", get (h, \"color\"));\n\n      case \"linestyle\"\n        set (hli, \"linestyle\", get (h, \"linestyle\"));\n\n      case \"linewidth\"\n        set (hli, \"linewidth\", get (h, \"linewidth\"));\n\n      case \"x\"\n        ## Update position\n        x = get (h, \"x\");\n        pos = get (h, \"position\");\n        pos(1) = x(1);\n        pos(3) = diff (x);\n        recursive = true;\n        set (h, \"position\", pos);\n        recursive = false;\n\n        ## Draw in normalized coordinates\n        pos = getnormpos (h);\n        x = [pos(1) (pos(1) + pos(3))];\n        set (hli, \"xdata\", x);\n\n      case \"y\"\n       ## Update position\n        y = get (h, \"y\");\n        pos = get (h, \"position\");\n        pos(2) = y(1);\n        pos(4) = diff (y);\n        recursive = true;\n        set (h, \"position\", pos);\n        recursive = false;\n\n        ## Draw in normalized coordinates\n        pos = getnormpos (h);\n        y = [pos(2) (pos(2) + pos(4))];\n        set (hli, \"ydata\", y);\n\n      case \"position\"\n        ## Update x and y\n        pos = get (h, \"position\");\n        x = [pos(1) (pos(1) + pos(3))];\n        y = [pos(2) (pos(2) + pos(4))];\n\n        recursive = true;\n        set (h, \"x\", x, \"y\", y);\n        recursive = false;\n\n        ## Draw in normalized coordinates\n        pos = getnormpos (h);\n        x = [pos(1) (pos(1) + pos(3))];\n        y = [pos(2) (pos(2) + pos(4))];\n        set (hli, \"xdata\", x, \"ydata\", y);\n\n    endswitch\n  endif\n\nendfunction\n\nfunction [x, y] = arrowcoordinates (h, nar = [])\n\n  pos = getnormpos (h);\n  ppos = norm2pts (h, pos(3:4).');\n  ang = angle (complex (ppos(1), ppos(2)));\n\n  if (isempty (nar))\n    ln = get (h, \"headlength\");   # in points\n    wd = get (h, \"headwidth\");\n    headstyle = get (h, \"headstyle\");\n    pos = pos(1:2) + pos(3:4);\n  elseif (nar == 1)\n    ln = get (h, \"head1length\");  # in points\n    wd = get (h, \"head1width\");\n    headstyle = get (h, \"head1style\");\n    pos = pos(1:2);\n    ang += pi;\n  elseif (nar == 2)\n    ln = get (h, \"head2length\");  # in points\n    wd = get (h, \"head2width\");\n    headstyle = get (h, \"head2style\");\n    pos = pos(1:2) + pos(3:4);\n  else\n    error (\"annotation: %d, no such arrow number\");\n  endif\n\n  switch (headstyle)\n    case \"diamond\"\n      x = [0 -ln/2 -ln -ln/2 0];\n      y = [0 -wd/2 0 wd/2 0];\n\n    case \"ellipse\"\n      pts = linspace (0, 2*pi, 12);\n      x = ln/2 * (cos (pts) - 1);\n      y = wd/2 * sin (pts);\n\n    case \"rectangle\"\n      x = [0 0 -ln -ln 0];\n      y = [wd/2 -wd/2 -wd/2 wd/2 wd/2];\n\n    case \"vback1\"\n      x = [0 -ln -0.85*ln -ln 0];\n      y = [0 wd/2 0 -wd/2 0];\n\n    case \"vback2\"\n      x = [0 -ln -0.65*ln -ln 0];\n      y = [0 wd/2 0 -wd/2 0];\n\n    case \"vback3\"\n      x = [0 -ln -0.2*ln -ln 0];\n      y = [0 wd/2 0 -wd/2 0];\n\n    case \"plain\"\n      x = [0 -ln -ln -ln 0];\n      y = [0 wd/2 0 -wd/2 0];\n\n    case \"none\"\n      x = [0 0 0];\n      y = [0 0 0];\n\n    otherwise\n      ## FIXME: This code is not reachable (12/13/2019)\n      error ('annotation: \"%s\" headstyle not implemented', headstyle);\n  endswitch\n\n  R = [cos(ang), -sin(ang);\n       sin(ang),  cos(ang)];\n  XY = R * [x; y];\n  XY = pts2norm (h, XY);\n  XY = pos(1:2).' + XY;\n\n  x = XY(1,:).';\n  y = XY(2,:).';\n\nendfunction\n\nfunction update_arrow (h, ~, prop, hpa = [])\n\n  nar = [];\n  for i = 1 : numel (hpa)\n    if (numel (hpa) == 2)\n      nar = i;\n    endif\n    if (hpa(i))\n      switch (prop)\n        case \"position\"\n          [x, y] = arrowcoordinates (h, nar);\n          set (hpa(i), \"xdata\", x, \"ydata\", y);\n\n        case \"color\"\n          set (hpa(i), \"facecolor\", get (h, \"color\"),\n                        \"edgecolor\", get (h, \"color\"));\n      endswitch\n    endif\n  endfor\n\nendfunction\n\nfunction update_text (h, ~, prop, hte)\n  persistent recursive = false;\n\n  if (! recursive)\n    switch (prop)\n      case \"position\"\n        if (isempty (get (h, \"string\")))\n          return;\n        endif\n\n        pos = getnormpos (h);\n\n        set (hte, \"position\", [textcoordinates(hte, pos) 0]);\n\n      otherwise\n        if (strncmp (prop, \"text\", 4))\n          set (hte, prop(5:end), get (h, prop));\n        else\n          set (hte, prop, get (h, prop));\n        endif\n\n    endswitch\n  endif\n\nendfunction\n\nfunction update_textbox (h, ~, prop, htb)\n  persistent recursive = false;\n\n  hte = htb(1);\n  hpa = htb(2);\n\n  if (! recursive)\n    switch (prop)\n      case {\"edgecolor\", \"facealpha\", \"linestyle\", \"linewidth\"}\n        set (hpa, prop, get (h, prop));\n\n      case {\"backgroundcolor\"}\n        set (hpa, \"facecolor\", get (h, prop));\n\n      otherwise\n        if (! any (strcmp (prop, {\"fitboxtotext\", \"position\"})))\n          set (hte, prop, get (h, prop));\n        endif\n\n        pos = getnormpos (h);\n\n        if (strcmp (get (h, \"fitboxtotext\"), \"on\"))\n          pos(3:4) = get (hte, \"extent\")(3:4) .* sign (pos(3:4));\n        endif\n\n        [x, y] = pos2rect (pos);\n        set (hpa, \"xdata\", x', \"ydata\", y');\n\n        switch (get (h, \"horizontalalignment\"))\n          case \"left\"\n            x = x(1);\n          case \"center\"\n            x = mean (x(1:2));\n          case \"right\"\n            x = x(2);\n        endswitch\n\n        switch (get (h, \"verticalalignment\"))\n          case {\"top\", \"cap\"}\n            y = y(3);\n          case \"middle\"\n            y = mean (y(2:3));\n          case {\"bottom\", \"baseline\"}\n            y = y(2);\n        endswitch\n        set (hte, \"position\", [x y 0]);\n\n    endswitch\n  endif\n\nendfunction\n\nfunction XY = textcoordinates (hte, pos)\n\n  ## Get the \"tight\" extent of the text object in points units\n  textpos = get (hte, \"position\");\n  rot = get (hte, \"rotation\");\n  units = get (hte, \"units\");\n\n  set (hte, \"rotation\", 0, \"units\", \"points\", \"position\", [0 0 0]);\n  ext = get (hte, \"extent\");\n  set (hte, \"rotation\", rot, \"units\", units, \"position\", textpos);\n\n  ## Find which one of the 8 following points we should align the\n  ## arrow with\n  ##  8-----7-----6\n  ##  1  text box 5\n  ##  2-----3-----4\n\n  ## FIXME: Matlab's horizontal/verticalalignment properties are\n  ## interpreted differently: horizontalalignment is passed to the\n  ## underlying text object whereas the verticalalignement controls\n  ## the vertical alignment of the arrow.\n\n  ang = angle (complex (pos(3), pos(4)));\n  rot *= pi / 180;\n\n  [~, pt] = min (abs ((-pi:pi/4:pi) - ang));\n  pt -= floor (rot / (pi/4));\n  if (pt <= 0)\n    pt = rem (pt, 8) + 8;\n  elseif (pt > 8)\n    pt = rem (pt, 8);\n  endif\n\n  ## Compute the actual text \"position\" property and move the text object\n  ## 2 points away from the arrow.\n  dx = ext(3)/2;\n  dy = ext(4)/2;\n  XY = [-dx-2, -dx-2, 0, dx+2, dx+2, dx+2, 0, -dx-2;\n        0, -dy-2, -dy-2, -dy-2, 0, dy+2, dy+2, dy+2];\n\n  switch (get (hte, \"horizontalalignment\"))\n    case \"left\"\n      XY(1,:) += dx;\n    case \"right\"\n      XY(1,:) -= dx;\n  endswitch\n\n  switch (get (hte, \"verticalalignment\"))\n    case {\"baseline\", \"bottom\"}\n      XY(2,:) += dy;\n    case {\"cap\", \"top\"}\n      XY(2,:) -= dy;\n  endswitch\n\n  R = [cos(rot), -sin(rot);\n       sin(rot),  cos(rot)];\n  XY = R * XY;\n  XY = pts2norm (get (hte, \"parent\"), XY);\n  XY = pos(1:2) - XY(:,pt).';\n\nendfunction\n\nfunction nXY = pts2norm (h, pXY)\n  sz = get (get (h, \"parent\"), \"figsize_points\");\n\n  nXY(1,:) = pXY(1,:) ./ sz(1);\n  nXY(2,:) = pXY(2,:) ./ sz(2);\nendfunction\n\nfunction pXY = norm2pts (h, nXY)\n  sz = get (get (h, \"parent\"), \"figsize_points\");\n\n  pXY(1,:) = nXY(1,:) .* sz(1);\n  pXY(2,:) = nXY(2,:) .* sz(2);\nendfunction\n\nfunction pos = convertposition (h, from, to)\n\n  ## FIXME: handle \"characters\" units\n  pos = get (h, \"position\");\n\n  ## First convert to normalized coordinates\n  sz = get (get (h, \"parent\"), \"figsize_points\");\n  switch (from)\n    case \"centimeters\"\n      pos /= 2.54;\n      pos *= 72;\n      pos(1:2:end) /= sz(1);\n      pos(2:2:end) /= sz(2);\n\n    case \"inches\"\n      pos *= 72;\n      pos(1:2:end) /= sz(1);\n      pos(2:2:end) /= sz(2);\n\n    case \"pixels\"\n      pos /= get (0, \"screenpixelsperinch\");\n      pos *= 72;\n      pos(1:2:end) /= sz(1);\n      pos(2:2:end) /= sz(2);\n\n  endswitch\n\n  ## Then convert to requested coordinates\n  switch (to)\n    case \"centimeters\"\n      sz /= 72;\n      sz *= 2.54;\n      pos(1:2:end) *= sz(1);\n      pos(2:2:end) *= sz(2);\n\n    case \"inches\"\n      sz /= 72;\n      pos(1:2:end) *= sz(1);\n      pos(2:2:end) *= sz(2);\n\n    case \"pixels\"\n      sz /= 72;\n      sz *= get (0, \"screenpixelsperinch\");\n      pos(1:2:end) *= sz(1);\n      pos(2:2:end) *= sz(2);\n\n  endswitch\n\nendfunction\n\nfunction pos = getnormpos (h)\n  units = get (h, \"units\");\n  pos = convertposition (h, units, \"normalized\");\nendfunction\n\nfunction [x, y] = pos2rect (pos)\n  x = [pos(1) pos(1)+pos(3) pos(1)+pos(3) pos(1)];\n  y = [pos(2) pos(2) pos(2)+pos(4) pos(2)+pos(4)];\nendfunction\n\nfunction [x, y] = pos2ell (pos)\n\n  a = pos(3)/2;\n  b = pos(4)/2;\n\n  ## Arbitrarily use 100 points when it is spread over\n  ang = linspace (0, 2*pi, 100);\n\n  x = a * cos (ang);\n  y = b * sin (ang);\n\n  x += pos(1) + a;\n  y += pos(2) + b;\n\nendfunction\n\nfunction update_rect (h, ~, prop, hre, typ)\n  persistent recursive = false;\n\n  if (! recursive)\n    switch (prop)\n      case \"position\"\n        pos = getnormpos (h);\n        if (strcmp (typ, \"rectangle\"))\n          [x, y] = pos2rect (pos);\n        else\n          [x, y] = pos2ell (pos);\n        endif\n        set (hre, \"xdata\", x, \"ydata\", y);\n\n      case \"color\"\n        set (hre, \"edgecolor\", get (h, prop));\n\n      otherwise\n        set (hre, prop, get (h, prop));\n\n    endswitch\n  endif\n\nendfunction\n\n\n## FIXME: the additional regular axes is necessary for fltk to draw the\n##        annotation axes.\n%!demo\n%! clf; axes (\"visible\", \"off\");\n%! annotation (\"textbox\", [.25 .9 .5 .09], \"string\", ...\n%!             {\"Right Click on annotation objects\", ...\n%!              \"to customize their appearance\"}, ...\n%!             \"horizontalalignment\", \"center\", \"fitboxtotext\", \"off\");\n%! annotation (\"ellipse\", [.2 .2 .6 .6], \"linewidth\", 4);\n%! ang = pi/2:-pi/2:-pi;\n%! lab = {\"N\", \"W\", \"S\", \"E\"};\n%! x0 = 0.5;\n%! y0 = 0.5;\n%! r = 0.3;\n%! for i = 1:4\n%!   x = r * cos (ang(i)) + x0;\n%!   y = r * sin (ang(i)) + y0;\n%!   annotation (\"textarrow\", [x x0], [y y0], ...\n%!               \"string\", lab{i},  \"fontsize\", 20);\n%! endfor\n%!\n%! h = annotation (\"doublearrow\", [x0 x0], [y0-r y0+r], ...\n%!                 \"head1style\", \"diamond\", \"head1length\", 60, ...\n%!                 \"head2style\", \"diamond\", \"head2length\", 60);\n\n%!demo\n%! clf; axes (\"visible\", \"off\");\n%! plot (1:10);\n%! xlabel (\"X-LABEL\");\n%! ylabel (\"LARGE Y-LABEL\", \"fontsize\", 20);\n%! title (\"FIGURE LAYOUT\", \"fontsize\", 24);\n%!\n%! ti = get (gca, \"tightinset\");\n%! pos = get (gca, \"position\");\n%! pos(1:2) = pos(1:2) - ti(1:2);\n%! pos(3) = pos(3) + ti (1) + ti (3);\n%! pos(4) = pos(4) + ti (2) + ti (4);\n%!\n%! ht = annotation (\"textbox\", pos, \"string\", \" Position + tighinset\", ...\n%!                  \"fitboxtotext\", \"off\", \"linestyle\", \"--\", ...\n%!                  \"edgecolor\", \"g\", \"linewidth\", 3, \"color\", \"g\", ...\n%!                  \"verticalalignment\", \"bottom\", \"fontsize\", 15);\n%!\n%! ho = annotation (\"textbox\", get (gca, \"outerposition\"), ...\n%!                  \"string\", \" Outerposition\",\"fitboxtotext\", \"off\", ...\n%!                  \"linestyle\", \"--\", \"edgecolor\", \"r\", ...\n%!                  \"linewidth\", 3, \"color\", \"r\", ...\n%!                  \"verticalalignment\", \"bottom\", \"fontsize\", 15);\n%!\n%! hi = annotation (\"textbox\", get (gca, \"position\"), ...\n%!                  \"string\", \" Position\",\"fitboxtotext\", \"off\", ...\n%!                  \"linestyle\", \"--\", \"edgecolor\", \"b\", ...\n%!                  \"linewidth\", 3, \"color\", \"b\", ...\n%!                  \"verticalalignment\", \"bottom\", \"fontsize\", 15);\n\n%!demo\n%! clf; axes (\"visible\", \"off\");\n%! h = annotation (\"arrow\");\n%!\n%! ## Get allowed headstyles\n%! styles = set (h, \"headstyle\");\n%! delete (h);\n%!\n%! ## Textbox for the title\n%! annotation (\"textbox\", [0.1 0 0.8 1], \"string\", ...\n%!             '\"headstyle\" property:', ...\n%!             \"backgroundcolor\", [0.7 0.7 0.7], \"fontsize\", 20, ...\n%!             \"fitboxtotext\", \"off\", \"verticalalignment\", \"top\", ...\n%!             \"horizontalalignment\", \"center\");\n%!\n%! ## Textarrows\n%! ns = numel (styles);\n%! nrows = ceil (ns/2);\n%! dy = 1/nrows;\n%! y = 1 - dy/2;\n%!\n%! jj = 1;\n%! for i = 1:nrows\n%!   annotation (\"textarrow\", [0.3 0.5], [y y], ...\n%!               \"string\", styles{jj}, \"fontsize\", 15, ...\n%!               \"headstyle\", styles{jj}, \"textcolor\", \"b\");\n%!   jj = jj + 1;\n%!   if (jj <= ns)\n%!     annotation (\"textarrow\", [0.7 0.5], [y y], ...\n%!                 \"string\", styles{jj}, \"fontsize\", 15, ...\n%!                 \"headstyle\", styles{jj}, \"textcolor\", \"b\");\n%!   jj = jj + 1;\n%!   endif\n%!   y = y - dy;\n%! endfor\n%! annotation (\"line\", [0.5 0.5], [dy/2 1-dy/2], \"linestyle\", \"-.\");\n\n%!demo\n%! clf; axes (\"visible\", \"off\");\n%!\n%! ## Textbox for the title\n%! annotation (\"textbox\", [0.1 0 0.8 1], \"string\", ...\n%!             \"Text arrows: text rotation\", ...\n%!             \"backgroundcolor\", [0.7 0.7 0.7], \"fontsize\", 20, ...\n%!             \"fitboxtotext\", \"off\", \"verticalalignment\", \"top\", ...\n%!             \"horizontalalignment\", \"center\");\n%!\n%! ## Textarrows\n%! for i = 1:10\n%!   rot = floor (rand (1) * 360 / 90) * 90;\n%!   annotation (\"textarrow\", 0.5 + [(0.6 * (rand(1) - .5)) 0], ...\n%!               0.5 + [(0.6 * (rand(1) - .5)) 0], ...\n%!               \"string\", \"A text\", ...\n%!               \"headstyle\", \"none\", \"textrotation\", rot);\n%! endfor\n\n%!demo\n%! clf; axes (\"visible\", \"off\");\n%!\n%! ## Textbox for the title\n%! annotation (\"textbox\", [0.1 0 0.8 1], \"string\", ...\n%!             \"Text arrows: text alignment\", ...\n%!             \"backgroundcolor\", [0.7 0.7 0.7], \"fontsize\", 20, ...\n%!             \"fitboxtotext\", \"off\", \"verticalalignment\", \"top\", ...\n%!             \"horizontalalignment\", \"center\");\n%!\n%! ## Textarrows\n%! halig = {\"right\", \"center\", \"left\"};\n%! i = 1;\n%! for x = .3:.2:.7\n%!   annotation (\"textarrow\", [x .5], [.5 .9], ...\n%!               \"string\", {\"Multiple lines\", \"text\"}, ...\n%!               \"headstyle\", \"none\", \"horizontalalignment\", halig{i});\n%!   i = i + 1;\n%! endfor\n\n%!demo\n%! clf; axes (\"visible\", \"off\");\n%!\n%! x = 0:0.01:2*pi;\n%! y = sin (x);\n%! plot (x, y);\n%!\n%! ## Extrema\n%! x0 = [pi/2 3*pi/2];\n%! y0 = [1 -1];\n%!\n%! ## Convert axes coordinates into normalized coordinates\n%! xl = xlim ();\n%! yl = [-1.2 1.5];\n%! ylim (yl);\n%! x0 = (x0 - xl(1)) / diff (xl);\n%! y0 = (y0 - yl(1)) / diff (yl);\n%!\n%! pos = get (gca (), \"position\");\n%! x0 = x0*pos(3) + pos(1);\n%! y0 = y0*pos(4) + pos(2);\n%!\n%!\n%! ## Textarrows\n%! for i = 1:2\n%!   annotation (\"doublearrow\", [(x0(i) - .05) (x0(i) + .05)], ...\n%!               [y0(i) y0(i)], \"head1style\", \"vback3\", ...\n%!               \"head2style\", \"vback3\", ...\n%!               \"head1width\", 4, \"head2width\", 4)\n%!   h = annotation (\"textarrow\", [0.5 x0(i)], [.85 y0(i)], ...\n%!                   \"linestyle\", \"--\", \"headstyle\", \"none\");\n%! endfor\n%! set (h, \"string\", \"Extrema\", \"fontsize\", 15);\n%! title (\"annotation() demo of TextArrows\");\n\n## test line properties\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = axes ();\n%! unwind_protect\n%!   h = annotation (\"line\", [0.2 0.7], [0.2 0.7], \"linewidth\", 2,\n%!                   \"linestyle\", \"--\", \"color\", \"r\");\n%!   hli = get (h, \"children\");\n%!   assert (get (hli, \"linewidth\"), 2);\n%!   assert (get (hli, \"linestyle\"), \"--\");\n%!   assert (get (hli, \"color\"), [1 0 0]);\n%!   assert (gca (), hax);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test textarrow properties\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = annotation (\"textarrow\", [0.2 0.7], [0.2 0.7],\n%!                   \"string\", \"Hello!\", \"fontsize\", 20,\n%!                   \"textrotation\", 90, \"textcolor\", \"r\");\n%!   hte = findobj (h, \"-depth\", 1, \"type\", \"text\");\n%!   assert (get (hte, \"string\"), \"Hello!\");\n%!   assert (get (hte, \"fontsize\"), 20);\n%!   assert (get (hte, \"rotation\"), 90);\n%!   assert (get (hte, \"color\"), [1 0 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test textbox properties\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = annotation (\"textbox\", [0.2 0.2 0.7 0.3], \"string\", \"Hello!\",\n%!                   \"horizontalalignment\", \"left\",\n%!                   \"verticalalignment\", \"bottom\",\n%!                   \"backgroundcolor\", \"r\");\n%!   hte = findobj (h, \"-depth\", 1, \"type\", \"text\");\n%!   hpa = findobj (h, \"-depth\", 1, \"type\", \"patch\");\n%!   assert (get (hte, \"string\"), \"Hello!\");\n%!   assert (get (hte, \"verticalalignment\"), \"bottom\");\n%!   assert (get (hte, \"horizontalalignment\"), \"left\");\n%!   assert (get (hpa, \"facecolor\"), [1 0 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test rectangle properties\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = axes ();\n%! unwind_protect\n%!   h = annotation (\"rectangle\", [0.2 0.7 0.2 0.2], \"linewidth\", 2,\n%!                   \"linestyle\", \"--\", \"color\", \"r\", \"facecolor\", \"b\",\n%!                   \"facealpha\", .6, \"units\", \"normalized\");\n%!   hpa = get (h, \"children\");\n%!   assert (get (hpa, \"xdata\"), [0.2; 0.4; 0.4; 0.2], eps);\n%!   assert (get (hpa, \"ydata\"), [0.7; 0.7; 0.9; 0.9], eps);\n%!   assert (get (hpa, \"linewidth\"), 2);\n%!   assert (get (hpa, \"linestyle\"), \"--\");\n%!   assert (get (hpa, \"edgecolor\"), [1 0 0]);\n%!   assert (get (hpa, \"edgecolor\"), get (h, \"color\"));\n%!   assert (get (hpa, \"facecolor\"), [0 0 1]);\n%!   assert (get (hpa, \"facealpha\"), .6);\n%!\n%!   assert (gca (), hax);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test units conversion\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = annotation (\"arrow\", [0.1 0.2],  [0.5 0.2]);\n%!   set (h, \"units\", \"inches\");\n%!   pos = get (h, \"position\");\n%!   x = get (h, \"x\");\n%!   y = get (h, \"y\");\n%!   set (h, \"units\", \"centimeters\");\n%!   assert (get (h, \"position\"), pos * 2.54, 20*eps);\n%!   assert (get (h, \"x\"), x * 2.54, 20*eps);\n%!   assert (get (h, \"y\"), y * 2.54, 20*eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test annotated figure\n%!test\n%! hf1 = figure (\"visible\", \"off\");\n%! hf2 = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = annotation (hf1, \"doublearrow\");\n%!   assert (ancestor (h, \"figure\"), hf1);\n%!   assert (gcf (), hf2);\n%! unwind_protect_cleanup\n%!   close (hf1);\n%!   close (hf2);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> annotation ()\n%!error <Invalid call to annotation> annotation ({\"line\"}, 1:2, 1:2)\n%!error <X and Y must be 2-element vectors> annotation (\"line\", {1:2}, 1:2)\n%!error <X and Y must be 2-element vectors> annotation (\"line\", 1:2, {1:2})\n%!error <X and Y must be 2-element vectors> annotation (\"line\", 1:3, 1:2)\n%!error <X and Y must be 2-element vectors> annotation (\"line\", 1:2, 1:3)\n%!error <Invalid call to annotation> annotation (\"line\", 1:2)\n%!error <POS must be a 4-element vector> annotation (\"textbox\", ones (4,4))\n%!error <POS must be a 4-element vector> annotation (\"textbox\", 1:3)\n%!error <unknown annotation TYPE foo> annotation (\"foo\")\n%!warning <couldn't parse PROP/VAL pairs, skipping>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   annotation (\"line\", 1:2, 1:2, \"color\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n%!error <unknown annotation TYPE foo> annotation (\"foo\")\n"
  },
  {
    "path": "scripts/plot/appearance/axis.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} axis ()\n## @deftypefnx {} {} axis ([@var{x_lo} @var{x_hi}])\n## @deftypefnx {} {} axis ([@var{x_lo} @var{x_hi} @var{y_lo} @var{y_hi}])\n## @deftypefnx {} {} axis ([@var{x_lo} @var{x_hi} @var{y_lo} @var{y_hi} @var{z_lo} @var{z_hi}])\n## @deftypefnx {} {} axis ([@var{x_lo} @var{x_hi} @var{y_lo} @var{y_hi} @var{z_lo} @var{z_hi} @var{c_lo} @var{c_hi}])\n## @deftypefnx {} {} axis (@var{option})\n## @deftypefnx {} {} axis (@var{option1}, @var{option2}, @dots{})\n## @deftypefnx {} {} axis (@var{hax}, @dots{})\n## @deftypefnx {} {@var{limits} =} axis ()\n## Set axis limits and appearance.\n##\n## The argument @var{limits} should be a 2-, 4-, 6-, or 8-element vector.  The\n## first and second elements specify the lower and upper limits for the\n## x-axis.  The third and fourth specify the limits for the y-axis, the fifth\n## and sixth specify the limits for the z-axis, and the seventh and eighth\n## specify the limits for the color axis.  The special values @code{-Inf} and\n## @code{Inf} may be used to indicate that the limit should be automatically\n## computed based on the data in the axes.\n##\n## Without any arguments, @code{axis} turns autoscaling on.\n##\n## With one output argument, @code{@var{limits} = axis} returns the current\n## axis limits.\n##\n## The vector argument specifying limits is optional, and additional string\n## arguments may be used to specify various axis properties.\n##\n## The following options control the aspect ratio of the axes.\n##\n## @table @asis\n## @item @qcode{\"equal\"}\n## Force x-axis unit distance to equal y-axis (and z-axis) unit distance.\n##\n## @item @qcode{\"square\"}\n## Force a square axis aspect ratio.\n##\n## @item @nospell{@qcode{\"vis3d\"}}\n## Set aspect ratio modes (@qcode{\"DataAspectRatio\"},\n## @qcode{\"PlotBoxAspectRatio\"}) to @qcode{\"manual\"} for rotation without\n## stretching.\n##\n## @item  @qcode{\"normal\"}\n## @itemx @qcode{\"fill\"}\n## Restore default automatically computed aspect ratios.\n## @end table\n##\n## @noindent\n## The following options control the way axis limits are interpreted.\n##\n## @table @asis\n## @item  @qcode{\"auto\"}\n## @itemx @qcode{\"auto[xyz]\"}\n## @itemx @qcode{\"auto [xyz]\"}\n## Set nice auto-computed limits around the data for all axes, or only\n## the specified axes.\n##\n## @item @qcode{\"manual\"}\n## Fix the current axes limits.\n##\n## @item @qcode{\"tickaligned\"}\n## Fix axes to the limits of the closest ticks.\n##\n## @item @qcode{\"tight\"}\n## Fix axes to the limits of the data.\n##\n## @item @qcode{\"padded\"}\n## Fix axes to the limits of the data plus margins of about 7% of the\n## data extent.\n##\n## @item @qcode{\"image\"}\n## Equivalent to @qcode{\"tight\"} and @qcode{\"equal\"}.\n##\n## @end table\n##\n## @noindent\n## The following options affect the appearance of tick marks.\n##\n## @table @asis\n## @item  @qcode{\"tic\"}\n## @itemx @qcode{\"tic[xyz]\"}\n## @itemx @qcode{\"tic [xyz]\"}\n## Turn tick marks on for all axes, or turn them on for the specified axes and\n## off for the remainder.\n##\n## @item  @qcode{\"label\"}\n## @itemx @qcode{\"label[xyz]\"}\n## @itemx @qcode{\"label [xyz]\"}\n## Turn tick labels on for all axes, or turn them on for the specified axes\n## and off for the remainder.\n##\n## @item @qcode{\"nolabel\"}\n## Turn tick labels off for all axes.\n## @end table\n##\n## @noindent\n## The following options affect the direction of increasing values on the axes.\n##\n## @table @asis\n## @item @qcode{\"xy\"}\n## Default y-axis, larger values are near the top.\n##\n## @item @qcode{\"ij\"}\n## Reverse y-axis, smaller values are near the top.\n## @end table\n##\n## @noindent\n## The following options affects the visibility of the axes.\n##\n## @table @asis\n## @item @qcode{\"on\"}\n## Make the axes visible.\n##\n## @item @qcode{\"off\"}\n## Hide the axes.\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then operate on this\n## axes rather than the current axes returned by @code{gca}.\n##\n## Example 1: set X/Y limits and force a square aspect ratio\n##\n## @example\n## axis ([1, 2, 3, 4], \"square\");\n## @end example\n##\n## Example 2: enable tick marks on all axes,\n##            enable tick mark labels only on the y-axis\n##\n## @example\n## axis (\"tic\", \"labely\");\n## @end example\n##\n## @seealso{xlim, ylim, zlim, clim, daspect, pbaspect, box, grid}\n## @end deftypefn\n\nfunction limits = axis (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"axis\", varargin{:});\n\n  oldfig = [];\n  if (! isempty (hax))\n    oldfig = get (0, \"currentfigure\");\n  endif\n  unwind_protect\n    if (isempty (hax))\n      hax = gca ();\n    endif\n    if (nargin == 0)\n      limits = __axis__ (hax, varargin{:});\n    else\n      __axis__ (hax, varargin{:});\n    endif\n  unwind_protect_cleanup\n    if (! isempty (oldfig))\n      set (0, \"currentfigure\", oldfig);\n    endif\n  end_unwind_protect\n\nendfunction\n\nfunction limits = __axis__ (ca, varargin)\n\n  if (nargin == 1)\n    if (nargout == 0)\n      set (ca, \"xlimmode\", \"auto\", \"ylimmode\", \"auto\", \"zlimmode\", \"auto\");\n    else\n      xlim = get (ca, \"xlim\");\n      ylim = get (ca, \"ylim\");\n      view = get (ca, \"view\");\n      if (view(2) == 90)\n        limits = [xlim, ylim];\n      else\n        zlim = get (ca, \"zlim\");\n        limits = [xlim, ylim, zlim];\n      endif\n    endif\n    return;\n  endif\n\n  for arg = varargin\n    opt = arg{1};\n\n    if (ischar (opt))\n      len = length (opt);\n\n      ## 'matrix mode' to reverse the y-axis\n      if (strcmpi (opt, \"ij\"))\n        set (ca, \"ydir\", \"reverse\");\n      elseif (strcmpi (opt, \"xy\"))\n        set (ca, \"ydir\", \"normal\");\n\n      ## aspect ratio\n      elseif (strcmpi (opt, \"image\"))\n        __axis__ (ca, \"equal\");\n        set (ca, \"plotboxaspectratiomode\", \"auto\", ...\n                 \"xlimmode\", \"auto\", \"ylimmode\", \"auto\", ...\n                 \"zlimmode\", \"auto\", ...\n                 \"xlimitmethod\", \"tight\", \"ylimitmethod\", \"tight\");\n      elseif (strcmpi (opt, \"square\"))\n        set (ca, \"dataaspectratiomode\", \"auto\",\n                 \"plotboxaspectratio\", [1, 1, 1]);\n      elseif (strcmp (opt, \"equal\"))\n        is2dview = (get (ca, \"view\")(2) == 90);\n        if (is2dview)\n          ## Save & later restore axes aspect ratio\n          ca_units = get (ca, \"units\");\n          set (ca, \"units\", \"pixels\");\n          axis_pos = get (ca, \"position\");\n          set (ca, \"units\", ca_units);\n          pbratio = [axis_pos(3), axis_pos(4), axis_pos(4)];\n        endif\n\n        daratio = get (ca, \"dataaspectratio\");\n        if (all (daratio != [1, 1, 1]))\n          set (ca, \"dataaspectratio\", [1, 1, 1]);\n        else\n          set (ca, \"dataaspectratio\", [1+eps, 1, 1],\n                   \"dataaspectratio\", [1, 1, 1]);\n        endif\n\n        ## Matlab only adjusts plotboxaspectratio for 2-D figures, but\n        ## Octave needs to do it for 3-D as well.\n        if (is2dview)\n          set (ca, \"plotboxaspectratio\", pbratio);\n        else\n          pbratio = get (ca, \"plotboxaspectratio\");\n          if (all (pbratio != [1, 1, 1]))\n            set (ca, \"plotboxaspectratio\", [1, 1, 1]);\n          else\n            set (ca, \"plotboxaspectratio\", [1+eps, 1, 1],\n                     \"plotboxaspectratio\", [1, 1, 1]);\n          endif\n        endif\n      elseif (strcmpi (opt, \"vis3d\"))\n        ## Fix aspect ratio modes for rotation without stretching.\n        set (ca, \"dataaspectratiomode\", \"manual\",\n                 \"plotboxaspectratiomode\", \"manual\");\n      elseif (strcmpi (opt, \"normal\") || strcmpi (opt, \"fill\"))\n        ## Set plotboxaspectratio to something obtuse so that switching\n        ## back to \"auto\" will force a re-calculation.\n        set (ca, \"plotboxaspectratio\", [3 2 1]);\n        set (ca, \"plotboxaspectratiomode\", \"auto\",\n                 \"dataaspectratiomode\", \"auto\");\n\n      ## axis limits\n      elseif (strncmpi (opt, \"auto\", 4))\n        if (len == 4)\n          set (ca, \"xlimmode\", \"auto\", \"ylimmode\", \"auto\", \"zlimmode\", \"auto\");\n        else\n          if (any (opt == \"x\"))\n            set (ca, \"xlimmode\", \"auto\");\n          endif\n          if (any (opt == \"y\"))\n            set (ca, \"ylimmode\", \"auto\");\n          endif\n          if (any (opt == \"z\"))\n            set (ca, \"zlimmode\", \"auto\");\n          endif\n        endif\n      elseif (strcmpi (opt, \"manual\"))\n        ## fixes the axis limits\n        set (ca, \"xlimmode\", \"manual\", \"ylimmode\", \"manual\",\n                 \"zlimmode\", \"manual\");\n      elseif (strcmpi (opt, \"tickaligned\"))\n        ## sets the axis limits to closest ticks.\n        set (ca, \"xlimmode\", \"auto\", \"ylimmode\", \"auto\", ...\n                 \"zlimmode\", \"auto\", ...\n                 \"xlimitmethod\", \"tickaligned\", ...\n                 \"ylimitmethod\", \"tickaligned\", ...\n                 \"zlimitmethod\", \"tickaligned\");\n      elseif (strcmpi (opt, \"tight\"))\n        ## sets the axis limits to the min and max of all data.\n        set (ca, \"xlimmode\", \"auto\", \"ylimmode\", \"auto\", ...\n                 \"zlimmode\", \"auto\", ...\n                 \"xlimitmethod\", \"tight\", \"ylimitmethod\", \"tight\",\n                 \"zlimitmethod\", \"tight\");\n      elseif (strcmpi (opt, \"padded\"))\n        ## sets the axis limits to the min and max of all data plus padding.\n        set (ca, \"xlimmode\", \"auto\", \"ylimmode\", \"auto\", ...\n                 \"zlimmode\", \"auto\", ...\n                 \"xlimitmethod\", \"padded\", ...\n                 \"ylimitmethod\", \"padded\", ...\n                 \"zlimitmethod\", \"padded\");\n      ## visibility\n      elseif (strcmpi (opt, \"on\"))\n        set (ca, \"visible\", \"on\");\n      elseif (strcmpi (opt, \"off\"))\n        set (ca, \"visible\", \"off\");\n\n      ## tick marks\n      elseif (strcmpi (opt, \"tic\"))\n        set (ca, \"xtickmode\", \"auto\", \"ytickmode\", \"auto\", \"ztickmode\", \"auto\",\n                 \"visible\", \"on\");\n      elseif (strncmpi (opt, \"tic\", 3))\n        if (any (opt == \"x\"))\n          set (ca, \"xtickmode\", \"auto\");\n        else\n          set (ca, \"xtick\", []);\n        endif\n        if (any (opt == \"y\"))\n          set (ca, \"ytickmode\", \"auto\");\n        else\n          set (ca, \"ytick\", []);\n        endif\n        if (any (opt == \"z\"))\n          set (ca, \"ztickmode\", \"auto\");\n        else\n          set (ca, \"ztick\", []);\n        endif\n\n      ## labels\n      elseif (strcmpi (opt, \"label\"))\n        set (ca, \"xticklabelmode\", \"auto\", \"yticklabelmode\", \"auto\",\n                 \"zticklabelmode\", \"auto\");\n      elseif (strcmpi (opt, \"nolabel\"))\n        set (ca, \"xticklabel\", {}, \"yticklabel\", {}, \"zticklabel\", {})\n      elseif (strncmpi (opt, \"label\", 5))\n        if (any (opt == \"x\"))\n          set (ca, \"xticklabelmode\", \"auto\");\n        else\n          set (ca, \"xticklabel\", \"\");\n        endif\n        if (any (opt == \"y\"))\n          set (ca, \"yticklabelmode\", \"auto\");\n        else\n          set (ca, \"yticklabel\", \"\");\n        endif\n        if (any (opt == \"z\"))\n          set (ca, \"zticklabelmode\", \"auto\");\n        else\n          set (ca, \"zticklabel\", \"\");\n        endif\n\n      else\n        warning (\"axis: unknown option '%s'\", opt);\n      endif\n\n    elseif (isnumeric (opt) && isvector (opt))\n\n      nel = numel (opt);\n\n      if (nel != 2 && nel != 4 && nel != 6 && nel != 8)\n        error (\"axis: LIMITS vector must have 2, 4, 6, or 8 elements\");\n      endif\n\n      for i = 1:2:nel\n        if (opt(i) >= opt(i+1))\n          error (\"axis: LIMITS(%d) must be less than LIMITS(%d)\", i, i+1);\n        endif\n      endfor\n\n      if (nel > 1)\n        xlim (ca, opt(1:2));\n      endif\n\n      if (nel > 3)\n        ylim (ca, opt(3:4));\n      endif\n\n      if (nel > 5)\n        zlim (ca, opt(5:6));\n      endif\n\n      if (nel > 7)\n        clim (ca, opt(7:8));\n      endif\n\n    else\n      error (\"axis: expecting no args, or a numeric vector with 2, 4, 6, or 8 elements\");\n    endif\n\n  endfor\n\nendfunction\n\n\n%!demo\n%! clf;\n%! t = 0:0.01:2*pi;\n%! x = sin (t);\n%!\n%! subplot (221);\n%!  plot (t, x);\n%!  title (\"normal plot\");\n%!\n%! subplot (222);\n%!  plot (t, x);\n%!  title (\"axis square\");\n%!  axis (\"square\");\n%!\n%! subplot (223);\n%!  plot (t, x);\n%!  title (\"axis equal\");\n%!  axis (\"equal\");\n%!\n%! subplot (224);\n%!  plot (t, x);\n%!  title (\"normal plot again\");\n%!  axis (\"normal\");\n\n%!demo\n%! clf;\n%! t = 0:0.01:2*pi;\n%! x = sin (t);\n%!\n%! subplot (121);\n%!  plot (t, x);\n%!  title ({\"axis ij\", \"Y-axis reversed\"});\n%!  axis (\"ij\");\n%!  legend (\"sine\");\n%!\n%! subplot (122);\n%!  plot (t, x);\n%!  title (\"axis xy\");\n%!  title ({\"axis ij\", \"Y-axis normal\"});\n%!  axis (\"xy\");\n%!  legend (\"sine\");\n\n%!demo\n%! clf;\n%! def_ticklen = get (0, \"DefaultAxesTickLength\");\n%! set (0, \"DefaultAxesTickLength\", [.028, .025]);\n%! t = 0:0.01:2*pi;\n%! x = sin (t);\n%!\n%! subplot (331);\n%!  plot (t, x);\n%!  title (\"x ticks and labels\");\n%!  axis (\"ticx\");\n%!\n%! subplot (332);\n%!  plot (t, x);\n%!  title (\"y ticks and labels\");\n%!  axis (\"ticy\");\n%!\n%! subplot (333);\n%!  plot (t, x);\n%!  title (\"axis off\");\n%!  axis (\"off\");\n%!\n%! subplot (334);\n%!  plot (t, x);\n%!  title (\"x and y ticks, x labels\");\n%!  axis (\"labelx\",\"tic\");\n%!\n%! subplot (335);\n%!  plot (t, x);\n%!  title (\"x and y ticks, y labels\");\n%!  axis (\"labely\",\"tic\");\n%!\n%! subplot (336);\n%!  plot (t, x);\n%!  title (\"all ticks but no labels\");\n%!  axis (\"nolabel\",\"tic\");\n%!\n%! subplot (337);\n%!  plot (t, x);\n%!  title (\"x ticks, no labels\");\n%!  axis (\"nolabel\",\"ticx\");\n%!\n%! subplot (338);\n%!  plot (t, x);\n%!  title (\"y ticks, no labels\");\n%!  axis (\"nolabel\",\"ticy\");\n%!\n%! subplot (339);\n%!  plot (t, x);\n%!  title (\"all ticks and labels\");\n%!  axis (\"on\");\n%!\n%! set (0, \"DefaultAxesTickLength\", def_ticklen);\n\n%!demo\n%! clf;\n%! t = 0:0.01:2*pi;\n%! x = sin (t);\n%!\n%! subplot (321);\n%!  plot (t, x);\n%!  title (\"axes at [0 3 0 1]\");\n%!  axis ([0,3,0,1]);\n%!\n%! subplot (322);\n%!  plot (t, x);\n%!  title (\"auto\");\n%!  axis (\"auto\");\n%!\n%! subplot (323);\n%!  plot (t, x, \";sine [0:2pi];\"); hold on;\n%!  plot (-3:3,-3:3, \";line (-3,-3)->(3,3);\"); hold off;\n%!  title (\"manual\");\n%!  axis (\"manual\");\n%!\n%! subplot (324);\n%!  plot (t, x, \";sine [0:2pi];\");\n%!  title (\"axes at [0 3 0 1], then autox\");\n%!  axis ([0,3,0,1]);\n%!  axis (\"autox\");\n%!\n%! subplot (325);\n%!  plot (t, x, \";sine [0:2pi];\");\n%!  title (\"axes at [3 6 0 1], then autoy\");\n%!  axis ([3,6,0,1]);\n%!  axis (\"autoy\");\n%!\n%! subplot (326);\n%!  plot (t, sin (t), t, -2*sin (t/2));\n%!  axis (\"tight\");\n%!  title (\"tight\");\n\n%!demo\n%! clf;\n%! x = 0:0.1:10;\n%! plot (x, sin (x));\n%! axis image;\n%! title ({\"image\", 'equivalent to \"tight\" & \"equal\"'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x,y,z] = peaks (50);\n%! x1 = max (x(:));\n%! pcolor (x-x1, y-x1/2, z);\n%! hold on;\n%! [x,y,z] = sombrero ();\n%! s = x1 / max (x(:));\n%! pcolor (s*x+x1, s*y+x1/2, 5*z);\n%! axis tight;\n%! title ('\"tight\" when two axes objects exist');\n\n%!demo\n%! clf;\n%! loglog (1:20, \"-s\");\n%! axis tight;\n%! title ('\"tight\" on loglog plot');\n\n%!demo\n%! clf;\n%! x = y = 0.5:0.5:12;\n%! subplot (3,1,1);\n%! plot (x, y, \"-s\");\n%! axis tickaligned\n%! title (\"tickaligned\");\n%! subplot (3,1,2);\n%! plot (x, y, \"-s\");\n%! axis padded\n%! title (\"padded\");\n%! subplot (3,1,3);\n%! plot (x, y, \"-s\");\n%! axis tight\n%! title (\"tight\");\n\n%!demo\n%! clf;\n%! x = y = 0.5:0.5:12;\n%! subplot (3,1,1);\n%! loglog (x, y, \"-s\");\n%! axis tickaligned\n%! title (\"tickaligned\");\n%! subplot (3,1,2);\n%! loglog (x, y, \"-s\");\n%! axis padded\n%! title (\"padded\");\n%! subplot (3,1,3);\n%! loglog (x, y, \"-s\");\n%! axis tight\n%! title (\"tight\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (11:20, [21:24, NaN, -Inf, 27:30]);\n%!   hold on;\n%!   plot (11:20, 25.5 + rand (10));\n%!   axis tight;\n%!   assert (axis (), [11 20 21 30]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   a = logspace (-5, 1, 10);\n%!   loglog (a, -a);\n%!   axis tight;\n%!   ## Compare to powers of 10 rather than exponential literals because of an\n%!   ## upstream bug in mingw-w64: https://sourceforge.net/p/mingw-w64/bugs/466/\n%!   assert (axis (), [10^-5, 10, -10, -10^-5]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test 'axis tight' with differently oriented, differently numbered data vecs\n%!test <*40036>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   Z = peaks (linspace (-3, 3, 49), linspace (-2, 2, 29));\n%!   surf (Z);\n%!   axis tight;\n%!   assert (axis (), [1 49 1 29 min(Z(:)) max(Z(:))]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test 'axis tight' remains after addition of new data\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10)\n%!   axis tight;\n%!   assert (axis (), [1 10 1 10]);\n%!   hold on;\n%!   plot (1:11)\n%!   assert (axis (), [1 11 1 11]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Even on errors, axis can display a figure.\n%!error <LIMITS vector must have .* elements>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   axis (1:5)\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <LIMITS\\(3\\) must be less than LIMITS\\(4\\)>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   axis ([1 2 4 3])\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <expecting no args, or a numeric vector with .* elements>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   axis ({1,2})\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/box.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} box\n## @deftypefnx {} {} box on\n## @deftypefnx {} {} box off\n## @deftypefnx {} {} box (@var{hax}, @dots{})\n## Control display of the axes border.\n##\n## The argument may be either @qcode{\"on\"} or @qcode{\"off\"}.  If it is\n## omitted, the current box state is toggled.\n##\n## If the first argument @var{hax} is an axes handle, then operate on this\n## axes rather than the current axes returned by @code{gca}.\n## @seealso{axis, grid}\n## @end deftypefn\n\nfunction box (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"box\", varargin{:});\n\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (nargin == 0)\n    box_state = get (hax, \"box\");\n    if (strcmp (box_state, \"on\"))\n      box_state = \"off\";\n    else\n      box_state = \"on\";\n    endif\n  else\n    state = varargin{1};\n    if (! ischar (state))\n      error ('box: argument must be \"on\" or \"off\"');\n    endif\n    if (strcmpi (state, \"off\"))\n      box_state = \"off\";\n    elseif (strcmpi (state, \"on\"))\n      box_state = \"on\";\n    else\n      error ('box: argument must be \"on\" or \"off\"');\n    endif\n  endif\n\n  set (hax, \"box\", box_state);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! plot (1:10, \"o-\");\n%! box off;\n%! title (\"box off\");\n\n%!demo\n%! clf;\n%! plot (1:10, \"o-\");\n%! box on;\n%! title (\"box on\");\n\n%!demo\n%! clf;\n%! z = [0:0.05:5];\n%! plot3 (cos (2*pi*z), sin (2*pi*z), z);\n%! box off;\n%! title (\"box off\");\n\n%!demo\n%! clf;\n%! z = [0:0.05:5];\n%! plot3 (cos (2*pi*z), sin (2*pi*z), z);\n%! box on;\n%! set (gca, \"boxstyle\", \"back\");\n%! title ({\"box on\", 'boxstyle = \"back\"'});\n\n%!demo\n%! clf;\n%! z = [0:0.05:5];\n%! plot3 (cos (2*pi*z), sin (2*pi*z), z);\n%! box on;\n%! set (gca, \"boxstyle\", \"full\");\n%! title ({\"box on\", 'boxstyle = \"full\"'});\n"
  },
  {
    "path": "scripts/plot/appearance/camlookat.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} camlookat ()\n## @deftypefnx {} {} camlookat (@var{h})\n## @deftypefnx {} {} camlookat (@var{handle_list})\n## @deftypefnx {} {} camlookat (@var{hax})\n## Move the camera and adjust its properties to look at objects.\n##\n## When the input is a handle @var{h}, the camera is set to point toward the\n## center of the bounding box of @var{h}.  The camera's position is adjusted so\n## the bounding box approximately fills the field of view.\n##\n## This command fixes the camera's viewing direction\n## (@code{camtarget() - campos()}), camera up vector\n## (@pxref{XREFcamup,,@code{camup}}) and viewing angle\n## (@pxref{XREFcamva,,@code{camva}}).  The camera target\n## (@pxref{XREFcamtarget,,@code{camtarget}}) and camera position\n## (@pxref{XREFcampos,,@code{campos}}) are changed.\n##\n## If the argument is a list @var{handle_list}, then a single bounding box for\n## all the objects is computed and the camera is then adjusted as above.\n##\n## If the argument is an axis object @var{hax}, then the children of the axis\n## are used as @var{handle_list}.  When called with no inputs, it uses the\n## current axis (@pxref{XREFgca,,@code{gca}}).\n##\n## @seealso{camorbit, camzoom, camroll}\n## @end deftypefn\n\n\nfunction camlookat (h)\n\n  if (nargin == 0)\n    hax = gca ();\n    h = get (hax, \"children\");\n  else\n    if (isaxes (h))\n      hax = h;\n      h = get (hax, \"children\");\n    elseif (all (ishghandle (h)))\n      hax = ancestor (h, \"axes\");\n      if (numel (hax) > 1)\n        hax = unique ([hax{:}]);\n      endif\n      if (numel (hax) > 1)\n        error (\"camlookat: HANDLE_LIST must be children of the same axes\");\n      endif\n    endif\n  endif\n\n  if (isempty (h))\n    return;\n  endif\n\n  x0 = x1 = y0 = y1 = z0 = z1 = [];\n  for i = 1:numel (h)\n    hi = h(i);\n\n    if (! ishghandle (hi))\n      error (\"camlookat: inputs must be graphic handles\");\n    endif\n\n    x0_ = min (get (hi, \"xdata\")(:));\n    x1_ = max (get (hi, \"xdata\")(:));\n    y0_ = min (get (hi, \"ydata\")(:));\n    y1_ = max (get (hi, \"ydata\")(:));\n    z0_ = min (get (hi, \"zdata\")(:));\n    z1_ = max (get (hi, \"zdata\")(:));\n\n    if (i == 1)\n      x0 = x0_;  x1 = x1_;\n      y0 = y0_;  y1 = y1_;\n      z0 = z0_;  z1 = z1_;\n    else\n      x0 = min (x0, x0_);  x1 = max (x1, x1_);\n      y0 = min (y0, y0_);  y1 = max (y1, y1_);\n      z0 = min (z0, z0_);  z1 = max (z1, z1_);\n    endif\n  endfor\n\n  dar = daspect (hax);\n\n  ## current view direction\n  curdir = (camtarget (hax) - campos (hax)) ./ dar;\n  curdir /= norm (curdir);\n\n  ## target to middle of bounding box\n  mid = [x0+x1, y0+y1, z0+z1]/2 ./ dar;\n\n  ## vertices of the bounding box\n  bb = [x0 y0 z0;\n        x0 y0 z1;\n        x0 y1 z0;\n        x0 y1 z1;\n        x1 y0 z0;\n        x1 y0 z1;\n        x1 y1 z0;\n        x1 y1 z1] ./ dar;\n\n  ## Find corner of bounding box with maximum opening angle.\n  ## Make sure temporary pov is well outside boundary of bounding box.\n  bb_diag = norm ([x0-x1, y0-y1, z0-z1] ./ dar);\n  cp_test = mid - 2*bb_diag*curdir;\n  bb_cp = bb - cp_test;\n  bb_cp ./= norm (bb_cp, 2, \"rows\");\n  aperture = norm (curdir .* bb_cp, 2, \"rows\");\n  max_corner = find (aperture == max (aperture), 1, \"first\");\n\n  ## projection of corner on line of sight\n  sz = curdir * (bb(max_corner,:) - mid)';\n  bb_proj = mid + sz * curdir;\n\n  ## Calculate distance for which that corner appears at camva/2\n  dist = norm (bb(max_corner,:) - bb_proj) / tand (camva () / 2);\n\n  ## Is bb_proj in front of or behind mid?\n  if (curdir * (mid - bb_proj)' > 0)\n    cp = bb_proj - dist * curdir;\n  else\n    cp = 2*mid - bb_proj - dist * curdir;\n  endif\n\n  ## set camera properties\n  camva (hax, \"manual\");  # avoid auto-adjusting\n  camtarget (hax, mid .* dar);\n  campos (hax, cp .* dar);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x, y, z] = peaks ();\n%! surf (x, y, z/5);\n%! hold on\n%! [x, y, z] = sphere ();\n%! s1 = surf (x/2, y/2+1.5, z/2+2);\n%! s2 = surf (x/5+0.2, y/5-2, z/5+1);\n%! axis equal\n%! axis tight\n%! title (\"camlookat() demo #1\");\n%! pause (1);\n%! camlookat (s1);\n%! pause (1);\n%! camlookat (s2);\n%! pause (1);\n%! camlookat ([s1 s2]);\n\n\n%!test\n%! ## not an error (does nothing)\n%! camlookat ([]);\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   camlookat ();\n%!   assert (camva (\"mode\"), \"manual\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## direction is preserved\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   [x y z] = sphere ();\n%!   h1 = surf (x + 1, y, z);\n%!   hold on\n%!   h2 = surf (x - 1, y + 2, z + 1);\n%!   dir = camtarget () - campos ();\n%!   dir /= norm (dir);\n%!   camlookat (h1);\n%!   dir2 = camtarget () - campos ();\n%!   dir2 /= norm (dir2);\n%!   assert (dir, dir2, -4*eps);\n%!   camlookat (h2);\n%!   dir2 = camtarget () - campos ();\n%!   dir2 /= norm (dir2);\n%!   assert (dir, dir2, -4*eps);\n%!   camlookat ([h1 h2]);\n%!   dir2 = camtarget () - campos ();\n%!   dir2 /= norm (dir2);\n%!   assert (dir, dir2, -4*eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## look at axes not same as default auto view\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   zlim ([0 10]);\n%!   xlim ([0 5]);\n%!   A = camtarget ();\n%!   assert (A, [2.5 0 5]);\n%!   camlookat ();\n%!   B = camtarget ();\n%!   assert (B, [0 0 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## list, empty and hax input give same results\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   [x y z] = sphere ();\n%!   h1 = surf (x + 1, y, z);\n%!   hold on\n%!   h2 = surf (x - 1, y + 2, z + 1);\n%!   camlookat ();\n%!   T1 = camtarget ();\n%!   P1 = campos ();\n%!   camtarget (\"auto\");\n%!   campos (\"auto\");\n%!   camlookat ([h1 h2]);\n%!   T2 = camtarget ();\n%!   P2 = campos ();\n%!   assert (T1, T2, -10*eps);\n%!   assert (P1, P2, -10*eps);\n%!   camtarget (\"auto\");\n%!   campos (\"auto\");\n%!   camlookat (gca ());\n%!   T3 = camtarget ();\n%!   P3 = campos ();\n%!   assert (T1, T3, -10*eps);\n%!   assert (P1, P3, -10*eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## act on given axes\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   [x, y, z] = sphere ();\n%!   hax1 = subplot (1, 2, 1);\n%!   hs11 = surf (hax1, x, y, z);\n%!   hold on\n%!   hs12 = surf (hax1, x, y+2, z+3);\n%!   hax2 = subplot (1, 2, 2);\n%!   hs21 = surf (hax2, x, y, z);\n%!   hold on\n%!   hs22 = surf (hax2, x, y+2, z+3);\n%!   ct2 = camtarget (hax2);\n%!   camlookat (hs11);\n%!   assert (camtarget (hax1), [0 0 0]);\n%!   assert (camtarget (hax2), ct2);\n%!   camlookat (hs22);\n%!   assert (camtarget (hax1), [0 0 0]);\n%!   assert (camtarget (hax2), [0 2 3]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## compare to Matlab R2016a output\n%!test <61532>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   [x, y, z] = peaks ();\n%!   s3 = surf (x, y, z/5);\n%!   hold on\n%!   [x, y, z] = sphere ();\n%!   s2 = surf (x/2, y/2+1.5, z/2+2);\n%!   s1 = mesh (x/2-4, 3*y, z/2 - 1);\n%!   axis equal\n%!   axis tight\n%!   camlookat (s1);\n%!   assert (camtarget (), [-4 0 -1], -eps);\n%!   assert (campos (), [-22.806319527015962 -24.508872777366225 16.835942167146133], -1e-7);\n%!   camlookat (s2);\n%!   assert (camtarget (), [0 1.5 2], -eps);\n%!   assert (campos (), [-5.8209352826617424 -6.0859905540313779 7.5205839138865720], -1e-7);\n%!   camlookat (s3);\n%!   assert (camtarget (), [0 0 0.15285290208388014], 1e-10);\n%!   assert (campos (), [-30.372839208265287 -39.582654701437512 28.958500003444449], -1e-7);\n%!   camlookat ();\n%!   assert (camtarget (), [-0.75 0 0.5], -eps);\n%!   assert (campos (), [-35.795562033972338 -45.672265648153193 33.737264567111389], -1e-7);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <called with too many inputs> camlookat (1, 2)\n%!error <must be graphic handles> camlookat (\"a\")\n%!error <children of the same axes>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   [x, y, z] = sphere ();\n%!   hax1 = subplot (1, 2, 1);\n%!   hs1 = surf (hax1, x, y, z);\n%!   hax2 = subplot (1, 2, 2);\n%!   hs2 = surf (hax2, x, y, z);\n%!   camlookat ([hs1 hs2]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/camorbit.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} camorbit (@var{theta}, @var{phi})\n## @deftypefnx {} {} camorbit (@var{theta}, @var{phi}, @var{coorsys})\n## @deftypefnx {} {} camorbit (@var{theta}, @var{phi}, @var{coorsys}, @var{dir})\n## @deftypefnx {} {} camorbit (@var{theta}, @var{phi}, \"data\")\n## @deftypefnx {} {} camorbit (@var{theta}, @var{phi}, \"data\", \"z\")\n## @deftypefnx {} {} camorbit (@var{theta}, @var{phi}, \"data\", \"x\")\n## @deftypefnx {} {} camorbit (@var{theta}, @var{phi}, \"data\", \"y\")\n## @deftypefnx {} {} camorbit (@var{theta}, @var{phi}, \"data\", [@var{x} @var{y} @var{z}])\n## @deftypefnx {} {} camorbit (@var{theta}, @var{phi}, \"camera\")\n## @deftypefnx {} {} camorbit (@var{hax}, @dots{})\n## Rotate the camera up/down and left/right around its target.\n##\n## Move the camera @var{phi} degrees up and @var{theta} degrees to the right,\n## as if it were in an orbit around its target.\n## Example:\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## sphere ()\n## camorbit (30, 20)\n## @end group\n## @end example\n##\n## These rotations are centered around the camera target\n## (@pxref{XREFcamtarget,,@code{camtarget}}).\n## First the camera position is pitched up or down by rotating it @var{phi}\n## degrees around an axis orthogonal to both the viewing direction\n## (specifically @code{camtarget() - campos()}) and the camera ``up vector''\n## (@pxref{XREFcamup,,@code{camup}}).\n## Example:\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## camorbit (0, 20)\n## @end group\n## @end example\n##\n## The second rotation depends on the coordinate system @var{coorsys} and\n## direction @var{dir} inputs.\n## The default for @var{coorsys} is @qcode{\"data\"}.  In this case, the camera\n## is yawed left or right by rotating it @var{theta} degrees around an axis\n## specified by @var{dir}.\n## The default for @var{dir} is @qcode{\"z\"}, corresponding to the vector\n## @code{[0, 0, 1]}.\n## Example:\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## camorbit (30, 0)\n## @end group\n## @end example\n##\n## When @var{coorsys} is set to @qcode{\"camera\"}, the camera is moved left or\n## right by rotating it around an axis parallel to the camera up vector\n## (@pxref{XREFcamup,,@code{camup}}).\n## The input @var{dir} should not be specified in this case.\n## Example:\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## camorbit (30, 0, \"camera\")\n## @end group\n## @end example\n##\n## (Note: the rotation by @var{phi} is unaffected by @qcode{\"camera\"}.)\n##\n## The @code{camorbit} command modifies two camera properties:\n## @ref{XREFcampos,,@code{campos}} and @ref{XREFcamup,,@code{camup}}.\n##\n## By default, this command affects the current axis; alternatively, an axis\n## can be specified by the optional argument @var{hax}.\n##\n## @seealso{camzoom, camroll, camlookat}\n## @end deftypefn\n\n\nfunction camorbit (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"camorbit\", varargin{:});\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n  endif\n\n  theta = varargin{1};\n  phi = varargin{2};\n  if (! (isnumeric (theta) && isscalar (theta)\n         && isnumeric (phi) && isscalar (phi)))\n    error (\"camorbit: THETA and PHI must be numeric scalars\");\n  endif\n\n  if (nargin < 3)\n    coorsys = \"data\";\n  else\n    coorsys = varargin{3};\n    if (! any (strcmpi (coorsys, {\"data\", \"camera\"})))\n      error (\"camorbit: COORSYS must be 'data' or 'camera'\");\n    endif\n  endif\n\n  if (nargin < 4)\n    dir = \"z\";\n  else\n    if (strcmpi (coorsys, \"camera\"))\n      error (\"camorbit: DIR can not be used with 'camera' COORSYS\");\n    endif\n    dir = varargin{4};\n  endif\n\n  if (ischar (dir))\n    switch (lower (dir))\n      case \"x\"\n        dir = [1 0 0];\n      case \"y\"\n        dir = [0 1 0];\n      case \"z\"\n        dir = [0 0 1];\n      otherwise\n        error (\"camorbit: DIR must be 'x', 'y', 'z' or a numeric 3-element vector\");\n    endswitch\n  endif\n  if (! (isnumeric (dir) && numel (dir) == 3))\n    error (\"camorbit: DIR must be 'x', 'y', 'z' or a numeric 3-element vector\");\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  view_ax = camtarget (hax) - campos (hax);\n  view_ax /= norm (view_ax);\n  ## orthogonalize the camup vector\n  up = camup (hax) - view_ax*dot (camup (hax), view_ax);\n  up /= norm (up);\n  pitch_ax = cross (up, view_ax);\n\n  if (strcmpi (coorsys, \"camera\"))\n    yaw_ax = up;\n  else\n    yaw_ax = dir;\n  endif\n\n  ## First pitch up then yaw right (order matters)\n  pos = num2cell (campos (hax));\n  [pos{:}] = __rotate_around_axis__ (pos{:}, phi, pitch_ax, camtarget (hax));\n  [pos{:}] = __rotate_around_axis__ (pos{:}, theta, yaw_ax, camtarget (hax));\n  pos = [pos{:}];\n\n  up = num2cell (up);\n  [up{:}] = __rotate_around_axis__ (up{:}, phi, pitch_ax, [0 0 0]);\n  [up{:}] = __rotate_around_axis__ (up{:}, theta, yaw_ax, [0 0 0]);\n  up = [up{:}];\n\n  camup (hax, up)\n  campos (hax, pos)\n\nendfunction\n\n\n%!demo\n%! clf;\n%! peaks ();\n%! title (\"camorbit() demo #1\");\n%! ## rotate the camera upwards\n%! camorbit (0, 30);\n%! ## rotate the camera right\n%! camorbit (20, 0);\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   campos ([20 0 0]);\n%!   camorbit (0, 60);\n%!   p = campos ();\n%!   u = camup ();\n%!   assert (p, [10 0 sqrt(3)*10], -eps);\n%!   assert (u, [-sqrt(3)/2 0 0.5], -eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   camorbit (20, 30, \"camera\")\n%!   p = campos ();\n%!   u = camup ();\n%!   ## Matlab 2008a\n%!   pm = [-0.72497293219048453 -9.3722459659600944 14.547694655894309];\n%!   um = [ 0.37563433931679546 0.77045096344496944 0.51507684480352300];\n%!   assert (p, pm, -5e-15);\n%!   assert (u, um, -5e-15);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   camorbit(20, 30, \"data\", [1 2 3]);\n%!   p = campos ();\n%!   u = camup ();\n%!   ## Matlab 2014a\n%!   pm = [-0.21577267252509916 -9.0492661542881496 14.766997806685227];\n%!   um = [ 0.41305819997282633 0.77380119822661142 0.48022351989284007];\n%!   assert (p, pm, -2e-14);  # FIXME: looser tolerance needed on i386\n%!   assert (u, um, -5e-15);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   camorbit (54, 37);\n%!   p = campos ();\n%!   u = camup ();\n%!   va = camva ();\n%!   ## Matlab 2016a\n%!   pm = [ 1.92211976102821500 -6.48896756467585330 15.943611747933700];\n%!   um = [-0.26143750325492854  0.88259821953215356 0.39073112848927383];\n%!   vam = 10.127485041473481;\n%!   assert (p, pm, -5e-15);\n%!   assert (u, um, -5e-15);\n%!   assert (va, vam, -5e-15);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## another figure, test hax\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = subplot (1, 2, 1);\n%!   sphere (hax);\n%!   x = campos ();\n%!   camorbit (20, 30)\n%!   subplot (1, 2, 2);\n%!   sphere ();\n%!   camorbit (hax, -20, -30)\n%!   y = campos (hax);\n%!   assert (x, y, -2*eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <numeric scalars> camorbit ([1 2], [3 4])\n%!error <Invalid call> camorbit (1, 2, \"data\", \"z\", 42)\n%!error <DIR must be> camorbit (1, 2, \"data\", \"meh\")\n%!error <DIR must be> camorbit (1, 2, \"data\", [1 2 3 4])\n%!error <DIR can not be> camorbit (1, 2, \"camera\", \"x\")\n%!error <COORSYS must be> camorbit (1, 2, \"meh\")\n"
  },
  {
    "path": "scripts/plot/appearance/campos.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{p} =} campos ()\n## @deftypefnx {} {} campos ([@var{x} @var{y} @var{z}])\n## @deftypefnx {} {@var{mode} =} campos (\"mode\")\n## @deftypefnx {} {} campos (@var{mode})\n## @deftypefnx {} {} campos (@var{hax}, @dots{})\n## Get or set the camera position.\n##\n## The default camera position is determined automatically based on the scene.\n## For example, to get the camera position:\n##\n## @example\n## @group\n## hf = figure();\n## peaks()\n## p = campos ()\n##   @xresult{} p =\n##       -27.394  -35.701   64.079\n## @end group\n## @end example\n##\n## We can then move the camera further up the z-axis:\n##\n## @example\n## @group\n## campos (p + [0 0 10])\n## campos ()\n##   @xresult{} ans =\n##       -27.394  -35.701   74.079\n## @end group\n## @end example\n##\n## Having made that change, the camera position @var{mode} is now manual:\n##\n## @example\n## @group\n## campos (\"mode\")\n##   @xresult{} manual\n## @end group\n## @end example\n##\n## We can set it back to automatic:\n##\n## @example\n## @group\n## campos (\"auto\")\n## campos ()\n##   @xresult{} ans =\n##       -27.394  -35.701   64.079\n## close (hf)\n## @end group\n## @end example\n##\n## By default, these commands affect the current axis; alternatively, an axis\n## can be specified by the optional argument @var{hax}.\n##\n## @seealso{camup, camtarget, camva}\n## @end deftypefn\n\n\nfunction p = campos (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"campos\", varargin{:});\n\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  prop = \"cameraposition\";\n  if (nargin == 0)\n    p = get (hax, prop);\n  elseif (nargin == 1 && isnumeric (varargin{1}) && numel (varargin{1}) == 3)\n    set (hax, prop, varargin{1});\n  elseif (nargin == 1 && ischar (varargin{1}))\n    s = varargin{1};\n    if (strcmp (s, \"mode\"))\n      p = get (hax, [prop \"mode\"]);\n    else\n      set (hax, [prop \"mode\"], s);\n    endif\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! sphere ();\n%! title (\"campos() demo #1\");\n%! ## where is camera located?\n%! x1 = campos ()\n%! ## move the camera upwards\n%! campos (x1 + [0 0 2]);\n%! x2 = campos ()\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   sphere (hax);\n%!   x = campos ();\n%!   campos ([1 2 3]);\n%!   y = campos ();\n%!   assert (y, [1 2 3]);\n%!   campos (x);\n%!   x2 = campos ();\n%!   assert (x, x2);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   p_orig = campos ();\n%!   m = campos (\"mode\");\n%!   assert (strcmp (m, \"auto\"));\n%!\n%!   campos ([1 2 3]);\n%!   m = campos (\"mode\");\n%!   assert (strcmp (m, \"manual\"));\n%!\n%!   campos (\"auto\");\n%!   p = campos ();\n%!   assert (p, p_orig);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n## test hax input by creating another axis\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!  subplot (1, 2, 1); sphere (); hax1 = gca ();\n%!  subplot (1, 2, 2); peaks (); hax2 = gca ();\n%!  campos (hax1, [20 0 0]);\n%!  subplot (1, 2, 1);\n%!  x = campos ();\n%!  z = campos (hax2);\n%!  subplot (1, 2, 2);\n%!  y = campos ();\n%!  assert (x, [20 0 0]);\n%!  assert (norm (y - [20 0 0]) > 1);\n%!  assert (y, z);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> campos (1, 2)\n%!error <invalid value>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!  campos (\"mod\");\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/camroll.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} camroll (@var{theta})\n## @deftypefnx {} {} camroll (@var{hax}, @var{theta})\n## Roll the camera.\n##\n## Roll the camera clockwise by @var{theta} degrees.\n## For example, the following command will roll the camera by\n## 30 degrees clockwise (to the right); this will cause the scene\n## to appear to roll by 30 degrees to the left:\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## peaks ()\n## camroll (30)\n## @end group\n## @end example\n##\n## Roll the camera back:\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## camroll (-30)\n## @end group\n## @end example\n##\n## The following command restores the default camera roll:\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## camup (\"auto\")\n## @end group\n## @end example\n##\n## By default, these commands affect the current axis; alternatively, an axis\n## can be specified by the optional argument @var{hax}.\n##\n## @seealso{camzoom, camorbit, camlookat, camup}\n## @end deftypefn\n\n\nfunction camroll (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"camroll\", varargin{:});\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  a = varargin{1};\n\n  if (! (isnumeric (a) && isscalar (a) ))\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  dar = get (hax, \"dataaspectratio\");\n\n  view_ax = (camtarget (hax) - campos (hax)) ./ dar;\n  view_ax /= norm (view_ax);\n  ## orthogonalize the camup vector\n  up = camup (hax) ./ dar;\n  up = up - view_ax * dot (up, view_ax);\n  up /= norm (up);\n\n  ## rotate the modified camup vector around the view axis\n  up = num2cell (up);\n  [up{:}] = __rotate_around_axis__ (up{:}, a, view_ax, [0 0 0]);\n  up = [up{:}] .* dar;\n  camup (hax, up / norm (up))\n\nendfunction\n\n\n%!demo\n%! clf;\n%! peaks ();\n%! camroll (30);\n%! title (\"camroll() demo #1\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere (10);\n%!   campos ([10 0 0]);\n%!   camroll (30);\n%!   p = camup ();\n%!   assert (p, [0 1/2 sqrt(3)/2], eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test rolling, then rolling back\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   peaks ();\n%!   p = camup (hax);\n%!   assert (p, [0 0 1], eps);\n%!   camroll (hax, 30);\n%!   p = camup (hax);\n%!   ## from Matlab R2017b\n%!   q = [0.33969638129660373 0.02014238382998192 0.94031944194919104];\n%!   assert (p, q, 10*eps);\n%!   camroll (hax, -30);\n%!   ## Note: It does not go back to [0 0 1]: instead orthog to camera view:\n%!   p = camup (hax);\n%!   ## The \"cameraupvector\" is now perpendicular to the viewing vector\n%!   dar = get (hax, \"dataaspectratio\");\n%!   ## FIXME: looser tolerance needed on i386 for assert below\n%!   assert (dot (p./dar, (camtarget (hax) - campos (hax))./dar), 0, 32*eps);\n%!   ## from Matlab R2017b\n%!   q = [0.14033891839365262 0.18289323924769943 0.97306477226420207];\n%!   assert (p, q, 10*eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test hax input by creating another axis\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax1 = subplot (1, 2, 1);\n%!   sphere (hax1);\n%!   hax2 = subplot (1, 2, 2);\n%!   sphere (hax2);\n%!   camroll (hax1, 30);\n%!   x = camup (hax1);\n%!   y = camup (hax2);\n%!   ## from Matlab R2016a\n%!   assert (x, [0.66027810132845211 0.03915135893036471 0.75000000000000022],\n%!           -1e-5);\n%!   assert (y, [0 0 1]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> camroll (1, 2, 3)\n%!error <Invalid call> camroll (\"mod\")\n%!error <Invalid call> camroll (1, [1 2])\n"
  },
  {
    "path": "scripts/plot/appearance/camtarget.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{t} =} camtarget ()\n## @deftypefnx {} {} camtarget ([@var{x} @var{y} @var{z}])\n## @deftypefnx {} {@var{mode} =} camtarget (\"mode\")\n## @deftypefnx {} {} camtarget (@var{mode})\n## @deftypefnx {} {} camtarget (@var{hax}, @dots{})\n## Get or set where the camera is pointed.\n##\n## The camera target is a point in space where the camera is pointing.\n## Usually, it is determined automatically based on the scene:\n##\n## @example\n## @group\n## hf = figure();\n## sphere (36)\n## v = camtarget ()\n##   @xresult{} v =\n##       0   0   0\n## @end group\n## @end example\n##\n## We can turn the camera to point at a new target:\n##\n## @example\n## @group\n## camtarget ([1 1 1])\n## camtarget ()\n##   @xresult{}   1   1   1\n## @end group\n## @end example\n##\n## Having done so, the camera target @var{mode} is manual:\n##\n## @example\n## @group\n## camtarget (\"mode\")\n##   @xresult{} manual\n## @end group\n## @end example\n##\n## This means, for example, adding new objects to the scene will not retarget\n## the camera:\n##\n## @example\n## @group\n## hold on;\n## peaks ()\n## camtarget ()\n##   @xresult{}   1   1   1\n## @end group\n## @end example\n##\n## We can reset it to be automatic:\n##\n## @example\n## @group\n## @c doctest: +XFAIL\n## @c https://savannah.gnu.org/bugs/?44503\n## camtarget (\"auto\")\n## camtarget ()\n##   @xresult{}   0   0   0.76426\n## close (hf)\n## @end group\n## @end example\n##\n## By default, these commands affect the current axis; alternatively, an axis\n## can be specified by the optional argument @var{hax}.\n##\n## @seealso{campos, camup, camva}\n## @end deftypefn\n\n\nfunction t = camtarget (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"camtarget\", varargin{:});\n\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  prop = \"cameratarget\";\n  if (nargin == 0)\n    t = get (hax, prop);\n  elseif (nargin == 1 && isnumeric (varargin{1}) && numel (varargin{1}) == 3)\n    set (hax, prop, varargin{1});\n  elseif (nargin == 1 && ischar (varargin{1}))\n    s = varargin{1};\n    if (strcmp (s, \"mode\"))\n      t = get (hax, [prop \"mode\"]);\n    else\n      set (hax, [prop \"mode\"], s);\n    endif\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! sphere ();\n%! title (\"camtarget() demo #1\");\n%! ## where is camera pointing?\n%! x1 = camtarget ()\n%! ## point the camera upwards\n%! camtarget (x1 + [0 0 1]);\n%! x2 = camtarget ()\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   x = camtarget ();\n%!   camtarget ([1 2 3]);\n%!   y = camtarget ();\n%!   assert (y, [1 2 3]);\n%!   camtarget (x);\n%!   x2 = camtarget ();\n%!   assert (x, x2);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   x_orig = camtarget ();\n%!   m = camtarget (\"mode\");\n%!   assert (strcmp (m, \"auto\"));\n%!\n%!   camtarget ([1 2 3]);\n%!   m = camtarget (\"mode\");\n%!   assert (strcmp (m, \"manual\"));\n%!\n%!   camtarget (\"auto\");\n%!   x = camtarget ();\n%!   assert (x, x_orig);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n## test hax input by creating another axis\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   subplot (1, 2, 1); sphere (); hax1 = gca ();\n%!   subplot (1, 2, 2); peaks (); hax2 = gca ();\n%!   camtarget (hax1, [0.1 0.2 0.3]);\n%!   subplot (1, 2, 1);\n%!   x = camtarget ();\n%!   z = camtarget (hax2);\n%!   subplot (1, 2, 2);\n%!   y = camtarget ();\n%!   assert (x, [0.1 0.2 0.3]);\n%!   assert (norm (y - [0.1 0.2 0.3]) > 0.1);\n%!   assert (y, z);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid> camtarget (1, 2)\n%!error <invalid value>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!  camtarget (\"mod\");\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/camup.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{up} =} camup ()\n## @deftypefnx {} {} camup ([@var{x} @var{y} @var{z}])\n## @deftypefnx {} {@var{mode} =} camup (\"mode\")\n## @deftypefnx {} {} camup (@var{mode})\n## @deftypefnx {} {} camup (@var{hax}, @dots{})\n## Get or set the camera up vector.\n##\n## By default, the camera is oriented so that ``up'' corresponds to the\n## positive z-axis:\n##\n## @example\n## @group\n## hf = figure ();\n## sphere (36)\n## v = camup ()\n##   @xresult{} v =\n##       0   0   1\n## @end group\n## @end example\n##\n## Specifying a new ``up vector'' rolls the camera and sets the mode to manual:\n##\n## @example\n## @group\n## camup ([1 1 0])\n## camup ()\n##   @xresult{}   1   1   0\n## camup (\"mode\")\n##   @xresult{} manual\n## @end group\n## @end example\n##\n## Modifying the up vector does not modify the camera target\n## (@pxref{XREFcamtarget,,@code{camtarget}}).  Thus, the camera up vector might\n## not be orthogonal to the direction of the camera's view:\n##\n## @example\n## @group\n## camup ([1 2 3])\n## dot (camup (), camtarget () - campos ())\n##   @xresult{} 6...\n## @end group\n## @end example\n##\n## A consequence is that ``pulling back'' on the up vector does not pitch the\n## camera view (as that would require changing the target).  Setting the up\n## vector is thus typically used only to roll the camera.  A more intuitive\n## command for this purpose is @ref{XREFcamroll,,@code{camroll}}.\n##\n## Finally, we can reset the up vector to automatic mode:\n##\n## @example\n## @group\n## camup (\"auto\")\n## camup ()\n##   @xresult{}   0   0   1\n## close (hf)\n## @end group\n## @end example\n##\n## By default, these commands affect the current axis; alternatively, an axis\n## can be specified by the optional argument @var{hax}.\n##\n## @seealso{campos, camtarget, camva}\n## @end deftypefn\n\n\nfunction up = camup (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"camup\", varargin{:});\n\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  prop = \"cameraupvector\";\n  if (nargin == 0)\n    up = get (hax, prop);\n  elseif (nargin == 1 && isnumeric (varargin{1}) && numel (varargin{1}) == 3)\n    set (hax, prop, varargin{1});\n  elseif (nargin == 1 && ischar (varargin{1}))\n    s = varargin{1};\n    if (strcmp (s, \"mode\"))\n      up = get (hax, [prop \"mode\"]);\n    else\n      set (hax, [prop \"mode\"], s);\n    endif\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! sphere ();\n%! title (\"camup() demo #1\");\n%! ## what direction is \"up\" for the camera?\n%! x1 = camup ()\n%! ## re-orient the camera with a new up-vector\n%! camup ([1 0 0]);\n%! x2 = camup ()\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   x = camup ();\n%!   camup ([1 2 3]);\n%!   y = camup ();\n%!   assert (y, [1 2 3]);\n%!   camup (x);\n%!   x2 = camup ();\n%!   assert (x, x2);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   p_orig = camup ();\n%!   m = camup (\"mode\");\n%!   assert (strcmp (m, \"auto\"));\n%!\n%!   camup ([1 2 3]);\n%!   m = camup (\"mode\");\n%!   assert (strcmp (m, \"manual\"));\n%!\n%!   camup (\"auto\");\n%!   p = camup ();\n%!   assert (p, p_orig);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test hax input by creating another axis\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   subplot (1, 2, 1); sphere (); hax1 = gca ();\n%!   subplot (1, 2, 2); peaks (); hax2 = gca ();\n%!   camup (hax1, [1 0 0]);\n%!   subplot (1, 2, 1);\n%!   x = camup ();\n%!   z = camup (hax2);\n%!   subplot (1, 2, 2);\n%!   y = camup ();\n%!   assert (x, [1 0 0]);\n%!   assert (norm (y - [1 0 0]) > 0.1);\n%!   assert (y, z);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> camup (1, 2)\n%!error <invalid value>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!  camup (\"mod\")\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/camva.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{a} =} camva ()\n## @deftypefnx {} {} camva (@var{a})\n## @deftypefnx {} {@var{mode} =} camva (\"mode\")\n## @deftypefnx {} {} camva (@var{mode})\n## @deftypefnx {} {} camva (@var{hax}, @dots{})\n## Get or set the camera viewing angle.\n##\n## The camera has a viewing angle which determines how much can be seen.  By\n## default this is:\n##\n## @example\n## @group\n## hf = figure();\n## sphere (36)\n## a = camva ()\n##   @xresult{} a =  10.340\n## @end group\n## @end example\n##\n## To get a wider-angle view, we could double the viewing angle.  This will\n## also set the mode to manual:\n##\n## @example\n## @group\n## camva (2*a)\n## camva (\"mode\")\n##   @xresult{} manual\n## @end group\n## @end example\n##\n## We can set it back to automatic:\n##\n## @example\n## @group\n## camva (\"auto\")\n## camva (\"mode\")\n##   @xresult{} auto\n## camva ()\n##   @xresult{} ans =  10.340\n## close (hf)\n## @end group\n## @end example\n##\n## By default, these commands affect the current axis; alternatively, an axis\n## can be specified by the optional argument @var{hax}.\n##\n## @seealso{campos, camtarget, camup}\n## @end deftypefn\n\n\nfunction a = camva (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"camva\", varargin{:});\n\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  prop = \"cameraviewangle\";\n  if (nargin == 0)\n    a = get (hax, prop);\n  elseif (nargin == 1 && isnumeric (varargin{1}) && isscalar (varargin{1}))\n    set (hax, prop, varargin{1});\n  elseif (nargin == 1 && ischar (varargin{1}))\n    s = varargin{1};\n    if (strcmp (s, \"mode\"))\n      a = get (hax, [prop \"mode\"]);\n    else\n      set (hax, [prop \"mode\"], s);\n    endif\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! peaks ();\n%! title (\"camva() demo #1\");\n%! ## query the viewing angle\n%! a1 = camva ()\n%! ## get a close-up view by decreasing the viewing angle:\n%! camva (0.5*a1);\n%! a2 = camva ()\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   x = camva ();\n%!   camva (5);\n%!   y = camva ();\n%!   assert (y, 5);\n%!   camva (x);\n%!   x2 = camva ();\n%!   assert (x, x2);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   a_orig = camva ();\n%!   m = camva (\"mode\");\n%!   assert (strcmp (m, \"auto\"));\n%!\n%!   camva (15);\n%!   m = camva (\"mode\");\n%!   assert (strcmp (m, \"manual\"));\n%!\n%!   camva (\"auto\");\n%!   a = camva ();\n%!   assert (a, a_orig);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test hax input by creating another axis\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   subplot (1, 2, 1); sphere (); hax1 = gca ();\n%!   subplot (1, 2, 2); sphere (); hax2 = gca ();\n%!   camva (hax1, 5);\n%!   subplot (1, 2, 1);\n%!   x = camva ();\n%!   z = camva (hax2);\n%!   subplot (1, 2, 2);\n%!   y = camva ();\n%!   assert (x, 5);\n%!   assert (abs (z - 5) > 1);\n%!   assert (y, z);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> camva (1, 2)\n%!error <invalid value>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!  camva (\"mod\")\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/camzoom.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} camzoom (@var{zf})\n## @deftypefnx {} {} camzoom (@var{hax}, @var{zf})\n## Zoom the camera in or out.\n##\n## A value of @var{zf} larger than 1 ``zooms in'' such that the scene appears\n## magnified:\n##\n## @example\n## @group\n## hf = figure ();\n## sphere (36)\n## camzoom (1.2)\n## @end group\n## @end example\n##\n## A value smaller than 1 ``zooms out'' so the camera can see more of the\n## scene:\n##\n## @example\n## @group\n## camzoom (0.5)\n## @end group\n## @end example\n##\n## Technically speaking, zooming affects the ``viewing angle''.  The following\n## command resets to the default zoom:\n##\n## @example\n## @group\n## camva (\"auto\")\n## close (hf)\n## @end group\n## @end example\n##\n## By default, these commands affect the current axis; alternatively, an axis\n## can be specified by the optional argument @var{hax}.\n##\n## @seealso{camroll, camorbit, camlookat, camva}\n## @end deftypefn\n\n\nfunction camzoom (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"camva\", varargin{:});\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  zf = varargin{1};\n\n  if (! (isnumeric (zf) && isscalar (zf) ))\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  va = 2 * atand (tand (camva (hax)/2) / zf);\n  camva (hax, va);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! peaks ();\n%! camzoom (2);\n%! title (\"camzoom() demo #1\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   x = camva ();\n%!   camzoom (5);\n%!   assert (tand (x/2) / tand (camva ()/2), 5);\n%!   camzoom (1/5);\n%!   y = camva ();\n%!   assert (x, y, eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   x = camva ();\n%!   camzoom (2);\n%!   y = camva ();\n%!   ## Matlab 2016a\n%!   xm = 10.339584907201974;\n%!   ym = 5.1803362845094822;\n%!   assert (tand (x/2) / tand (y/2), tand (xm/2) / tand (ym/2), 2e-14);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   peaks ();\n%!   campos ([20, 30, 50]);\n%!   camtarget ([0 0 1]);\n%!   x = camva ();\n%!   camzoom (5);\n%!   y = camva ();\n%!   ## Matlab 2014a\n%!   xm = 13.074668029506947;\n%!   ym = 2.6258806698721222;\n%!   assert (tand (x/2) / tand (y/2), tand (xm/2) / tand (ym/2), 2e-14);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## test hax input by creating another axis\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax1 = subplot (1, 2, 1);\n%!   sphere (hax1);\n%!   hax2 = subplot (1, 2, 2);\n%!   sphere (hax2);\n%!   camzoom (hax1, 2)\n%!   x = camva (hax1);\n%!   y = camva (hax2);\n%!   assert (tand (y/2) / tand (x/2), 2, 2*eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> camzoom (1, 2, 3)\n%!error <Invalid call> camzoom (1, [2, 3])\n%!error <Invalid call> camzoom (\"string\")\n"
  },
  {
    "path": "scripts/plot/appearance/clabel.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} clabel (@var{c}, @var{h})\n## @deftypefnx {} {} clabel (@var{c}, @var{h}, @var{v})\n## @deftypefnx {} {} clabel (@var{c}, @var{h}, \"manual\")\n## @deftypefnx {} {} clabel (@var{c})\n## @deftypefnx {} {} clabel (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {@var{hlabels} =} clabel (@dots{})\n## Add labels to the contours of a contour plot.\n##\n## The contour levels are specified by the contour matrix @var{c} which is\n## returned by @code{contour}, @code{contourc}, @code{contourf}, and\n## @code{contour3}.  Contour labels are rotated to match the local line\n## orientation and centered on the line.  The position of labels along the\n## contour line is chosen randomly.\n##\n## If the argument @var{h} is a handle to a contour group object, then label\n## this plot rather than the one in the current axes returned by @code{gca}.\n##\n## By default, all contours are labeled.  However, the contours to label can be\n## specified by the vector @var{v}.  If the @qcode{\"manual\"} argument is\n## given then the contours to label can be selected with the mouse.\n##\n## Additional property/value pairs that are valid properties of text objects\n## can be given and are passed to the underlying text objects.  Moreover,\n## the contour group property @qcode{\"LabelSpacing\"} is available which\n## determines the spacing between labels on a contour to be specified.  The\n## default is 144 points, or 2 inches.\n##\n## The optional return value @var{hlabels} is a vector of graphics handles to\n## the text objects representing each label.\n## The @qcode{\"userdata\"} property of the text objects contains the numerical\n## value of the contour label.\n##\n## The full list of text object properties is documented at\n## @ref{Text Properties}.\n##\n## @example\n## @group\n## [c, h] = contour (peaks (), -4 : 6);\n## clabel (c, h, -4:2:6, \"fontsize\", 12);\n## @end group\n## @end example\n##\n## @seealso{contour, contourf, contour3, meshc, surfc, text}\n## @end deftypefn\n\nfunction hlabels = clabel (c, varargin)\n\n  have_hg = false;\n  have_labelspacing = false;\n  label_spacing = 144;  # 2 inches in points\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    hparent = gca ();\n  else\n    arg = varargin{1};\n    if (isscalar (arg) && isgraphics (arg, \"hggroup\"))\n      try\n        get (arg, \"contourmatrix\");\n      catch\n        error (\"clabel: H must be a handle to a contour group\");\n      end_try_catch\n      have_hg = true;\n      hg = arg;\n      varargin(1) = [];\n    else\n      hparent = gca ();\n    endif\n  endif\n\n  if (numel (varargin) > 0 && isnumeric (varargin{1}))\n    v = varargin{1}(:);\n    varargin(1) = [];\n  else\n    v = [];\n  endif\n\n  idx = strcmpi (varargin(1:2:end), \"manual\");\n  if (any (idx))\n    error ('clabel: \"manual\" contour mode is not supported');\n  endif\n\n  idx = find (strcmpi (varargin(1:2:end), \"labelspacing\"), 1);\n  if (! isempty (idx))\n    have_labelspacing = true;\n    label_spacing = varargin{2*idx};\n    varargin(2*idx+(-1:0)) = [];\n  endif\n\n  if (have_hg)\n    if (! isempty (v))\n      if (have_labelspacing)\n        set (hg, \"textlistmode\", \"manual\", \"textlist\", v,\n                 \"labelspacing\", label_spacing, \"showtext\", \"on\");\n      else\n        set (hg, \"textlistmode\", \"manual\", \"textlist\", v, \"showtext\", \"on\");\n      endif\n    else\n      if (have_labelspacing)\n        set (hg, \"showtext\", \"on\", \"labelspacing\", label_spacing);\n      else\n        set (hg, \"showtext\", \"on\");\n      endif\n    endif\n    htmp = findobj (hg, \"type\", \"text\");\n    if (! isempty (varargin))\n      set (htmp, varargin{:});\n    endif\n  else\n    htmp = __clabel__ (c, v, hparent, label_spacing, [], varargin{:});\n  endif\n\n  if (nargout > 0)\n    hlabels = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [c, h] = contour (peaks (), -4:6);\n%! clabel (c, h, -4:2:6, \"fontsize\", 12);\n%! title (\"clabel() labeling every other contour\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [c, h] = contourf (peaks (), -7:6);\n%! clabel (c, h, -6:2:6, \"fontsize\", 12);\n%! title (\"clabel() labeling every other contour\");\n"
  },
  {
    "path": "scripts/plot/appearance/clim.m",
    "content": "########################################################################\n##\n## Copyright (C) 2024-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} clim ([cmin cmax])\n## @deftypefnx {} {} clim (\"auto\")\n## @deftypefnx {} {} clim (\"manual\")\n## @deftypefnx {} {} clim (@var{hax}, @dots{})\n## @deftypefnx {} {@var{limits} =} clim ()\n## Query or set color axis limits for plots.\n##\n## The limits argument should be a 2-element vector specifying the lower and\n## upper limits to assign to the first and last value in the colormap.  Data\n## values outside this range are clamped to the first and last colormap\n## entries.\n##\n## If the @qcode{\"auto\"} option is given then automatic colormap limits are\n## applied.  The automatic algorithm sets @var{cmin} to the minimum data value\n## and @var{cmax} to the maximum data value.  If @qcode{\"manual\"} is specified\n## then the @qcode{\"climmode\"} property is set to @qcode{\"manual\"} and the\n## numeric values in the @qcode{\"clim\"} property are used for limits.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## Called without arguments the current color axis limits are returned.\n##\n## Programming Note: The color axis affects the display of image, patch, and\n## surface graphics objects, but @strong{only} if the @qcode{\"cdata\"} property\n## has indexed data and the @qcode{\"cdatamapping\"} property is set to\n## @qcode{\"scaled\"}.  Graphic objects with true color @code{cdata}, or\n## @qcode{\"direct\"} @code{cdatamapping} are not affected.\n## @seealso{colormap, axis}\n## @end deftypefn\n\nfunction limits = clim (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"clim\", varargin{:});\n\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  oldfig = [];\n  if (! isempty (hax))\n    oldfig = get (0, \"currentfigure\");\n  endif\n  unwind_protect\n    if (isempty (hax))\n      hax = gca ();\n    endif\n    if (nargin == 0)\n      limits = get (hax, \"clim\");\n    else\n      arg1 = varargin{1};\n      if (ischar (arg1))\n        if (strcmpi (arg1, \"auto\"))\n          set (hax, \"climmode\", \"auto\");\n        elseif (strcmpi (arg1, \"manual\"))\n          set (hax, \"climmode\", \"manual\");\n        else\n          error (\"clim: invalid mode '%s'\", arg1);\n        endif\n      elseif (isvector (arg1))\n        if (numel (arg1) != 2 || ! isnumeric (arg1) || arg1(1) >= arg1(2))\n          error (\"clim: LIMITS must be a numeric 2-element vector where LIM1 < LIM2\");\n        endif\n        set (hax, \"clim\", arg1);\n      else\n        print_usage ();\n      endif\n    endif\n  unwind_protect_cleanup\n    if (! isempty (oldfig))\n      set (0, \"currentfigure\", oldfig);\n    endif\n  end_unwind_protect\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   clim ([e, pi]);\n%!   assert (clim (), [e, pi]);\n%!   clim (hax, [-1, 1]);\n%!   assert (clim (hax), [-1, 1]);\n%!   assert (get (hax, \"climmode\"), \"manual\");\n%!   clim (\"auto\");\n%!   assert (get (hax, \"climmode\"), \"auto\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error clim (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   fail (\"clim ('foo')\", \"invalid mode 'foo'\");\n%!   fail (\"clim ([1 2 3])\", \"2-element vector\");\n%!   fail (\"clim ({1 2 3})\", \"numeric 2-element vector\");\n%!   fail (\"clim ([1 0])\", \"LIM1 < LIM2\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/daspect.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{data_aspect_ratio} =} daspect ()\n## @deftypefnx {} {} daspect (@var{data_aspect_ratio})\n## @deftypefnx {} {} daspect (@var{mode})\n## @deftypefnx {} {@var{data_aspect_ratio_mode} =} daspect (\"mode\")\n## @deftypefnx {} {} daspect (@var{hax}, @dots{})\n## Query or set the data aspect ratio of the current axes.\n##\n## The aspect ratio is a normalized 3-element vector representing the span of\n## the x, y, and z-axis limits.\n##\n## @code{daspect (@var{mode})}\n##\n## Set the data aspect ratio mode of the current axes.  @var{mode} is\n## either @qcode{\"auto\"} or @qcode{\"manual\"}.\n##\n## @code{daspect (@qcode{\"mode\"})}\n##\n## Return the data aspect ratio mode of the current axes.\n##\n## @code{daspect (@var{hax}, @dots{})}\n##\n## Operate on the axes in handle @var{hax} instead of the current axes.\n##\n## @seealso{axis, pbaspect, xlim, ylim, zlim}\n## @end deftypefn\n\nfunction daratio = daspect (varargin)\n\n  ## Grab axes handle if present\n  if (nargin > 0)\n    if (isscalar (varargin{1}) && isaxes (varargin{1}))\n      hax = varargin{1};\n      varargin = varargin(2:end);\n    else\n      hax = gca ();\n    endif\n  else\n    hax = gca ();\n  endif\n\n  nargin = numel (varargin);\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  if (nargin == 0)\n    daratio = get (hax, \"dataaspectratio\");\n  else\n    arg = varargin{1};\n    if (isnumeric (arg))\n      if (numel (arg) == 2)\n        set (hax, \"dataaspectratio\", [arg, 1]);\n      elseif (numel (arg) == 3)\n        set (hax, \"dataaspectratio\", arg);\n      else\n        error (\"daspect: DATA_ASPECT_RATIO must be a 2- or 3-element vector\");\n      endif\n    elseif (ischar (arg))\n      arg = lower (arg);\n      switch (arg)\n        case \"auto\"\n          set (hax, \"dataaspectratiomode\", \"auto\");\n        case \"manual\"\n          set (hax, \"dataaspectratiomode\", \"manual\");\n        case \"mode\"\n          daratio = get (hax, \"dataaspectratiomode\");\n        otherwise\n          error (\"daspect: Invalid MODE <%s>\", arg);\n      endswitch\n    else\n      print_usage ();\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = 0:0.01:4;\n%! plot (x,cos (x), x,sin (x));\n%! axis square;\n%! daspect ([1 1 1]);\n%! title (\"square plot box with axis limits [0, 4, -2, 2]\");\n\n%!demo\n%! clf;\n%! x = 0:0.01:4;\n%! plot (x,cos (x), x,sin (x));\n%! axis ([0 4 -1 1]);\n%! daspect ([2 1 1]);\n%! title (\"square plot box with axis limits [0, 4, -1, 1]\");\n\n%!demo\n%! clf;\n%! x = 0:0.01:4;\n%! plot (x,cos (x), x,sin (x));\n%! daspect ([1 2 1]);\n%! pbaspect ([2 1 1]);\n%! title (\"2x1 plot box with axis limits [0, 4, -2, 2]\");\n\n%!demo\n%! clf;\n%! x = 0:0.01:4;\n%! plot (x,cos (x), x, sin (x));\n%! axis square;\n%! set (gca, \"positionconstraint\", \"innerposition\");\n%! daspect ([1 1 1]);\n%! title (\"square plot box with axis limits [0, 4, -2, 2]\");\n\n%!demo\n%! clf;\n%! x = 0:0.01:4;\n%! plot (x,cos (x), x,sin (x));\n%! axis ([0 4 -1 1]);\n%! set (gca, \"positionconstraint\", \"innerposition\");\n%! daspect ([2 1 1]);\n%! title (\"square plot box with axis limits [0, 4, -1, 1]\");\n\n## FIXME: need some input validation tests\n"
  },
  {
    "path": "scripts/plot/appearance/datetick.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} datetick ()\n## @deftypefnx {} {} datetick (@var{axis_str})\n## @deftypefnx {} {} datetick (@var{date_format})\n## @deftypefnx {} {} datetick (@var{axis_str}, @var{date_format})\n## @deftypefnx {} {} datetick (@dots{}, \"keeplimits\")\n## @deftypefnx {} {} datetick (@dots{}, \"keepticks\")\n## @deftypefnx {} {} datetick (@var{hax}, @dots{})\n## Add date-formatted tick labels to an axis.\n##\n## The axis to apply the ticks to is determined by @var{axis_str} which can\n## take the values @qcode{\"x\"}, @qcode{\"y\"}, or @qcode{\"z\"}.  The default\n## value is @qcode{\"x\"}.\n##\n## The formatting of the labels is determined by the variable\n## @var{date_format}, which can either be a string or positive integer that\n## @code{datestr} accepts.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## @seealso{datenum, datestr}\n## @end deftypefn\n\nfunction datetick (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"datetick\", varargin{:});\n\n  oldfig = [];\n  if (! isempty (hax))\n    oldfig = get (0, \"currentfigure\");\n  else\n    hax = gca ();\n  endif\n\n  unwind_protect\n    ## FIXME: This will bring the axes to the top of the stack.\n    ##        This may not be desirable if there are multiple axes objects,\n    ##        such as can occur with plotyy.\n    axes (hax);\n    __datetick__ (varargin{:});\n  unwind_protect_cleanup\n    if (! isempty (oldfig))\n      set (0, \"currentfigure\", oldfig);\n    endif\n  end_unwind_protect\n\nendfunction\n\n\n%!demo\n%! clf;\n%! yr = 1900:10:2000;\n%! pop = [76.094, 92.407, 106.461, 123.077 131.954, 151.868, 179.979, ...\n%!        203.984, 227.225, 249.623, 282.224];\n%! plot (datenum (yr, 1, 1), pop);\n%! xlabel (\"Year\");\n%! ylabel (\"US population (millions)\");\n%! title (\"datetick() with 4-digit year format\");\n%! datetick (\"x\", \"YYYY\");\n\n%!demo\n%! clf;\n%! yr = 1988:2:2002;\n%! yr = datenum (yr,1,1);\n%! pr = [12.1 13.3 12.6 13.1 13.3 14.1 14.4 15.2];\n%! plot (yr, pr, \"-o\");\n%! xlabel (\"year\");\n%! ylabel (\"average price\");\n%! title (\"datetick() with MM/DD/YY format\");\n%! ax = gca ();\n%! set (ax, \"xtick\", datenum (1990:5:2005,1,1));\n%! datetick (\"x\", 2, \"keepticks\");\n%! set (ax, \"ytick\", 12:16);\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   plot ([213:364 0:28], randn (1,181));\n%!   datetick (\"x\", 3);\n%!   xticks = get (hax, \"xtick\");\n%!   assert (xticks, [-30 32 92 153 214 275 336 398]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\nfunction __datetick__ (varargin)\n\n  keeplimits = false;\n  idx = strcmpi (varargin, \"keeplimits\");\n  if (any (idx))\n    keeplimits = true;\n    varargin = varargin(! idx);\n  endif\n  keepticks = false;\n  idx = strcmpi (varargin, \"keepticks\");\n  if (any (idx))\n    keepticks = true;\n    varargin = varargin(! idx);\n  endif\n\n  nargin = numel (varargin);\n  form = [];\n  ax = \"x\";\n\n  if (nargin != 0)\n    arg = varargin{1};\n    if (ischar (arg) && any (strcmpi (arg, {\"x\", \"y\", \"z\"})))\n      ax = lower (arg);\n      if (nargin > 1)\n        form = varargin{2};\n        varargin(1:2) = [];\n      else\n        varargin(1) = [];\n      endif\n    else\n      form = arg;\n      varargin(1) = [];\n    endif\n  endif\n\n  ## Don't publish the existence of this variable for use with dateaxis\n  if (numel (varargin) > 0)\n    startdate = varargin{1};\n  else\n    startdate = [];\n  endif\n\n  if (! isempty (form))\n    if (isnumeric (form))\n      if (! isscalar (form) || form < 0 || form != fix (form))\n        error (\"datetick: FORM argument must be a positive integer\");\n      endif\n    elseif (! ischar (form))\n      error (\"datetick: FORM argument must be a valid date format string\");\n    endif\n  endif\n\n  if (keepticks)\n    ticks = get (gca (), [ax \"tick\"]);\n  else\n    ## Need to do our own axis tick position calculation as\n    ## year, etc., don't fall back to nice datenum values.\n    if (keeplimits)\n      limits = get (gca (), [ax \"lim\"]);\n      xmin = limits(1);\n      xmax = limits(2);\n    else\n      objs = findall (gca ());\n      xmin = xmax = NaN;\n      for i = 1 : numel (objs)\n        fld = get (objs(i));\n        if (isfield (fld, [ax \"data\"]))\n          xdata = getfield (fld, [ax \"data\"])(:);\n          xmin = min (xmin, min (xdata));\n          xmax = max (xmax, max (xdata));\n        endif\n      endfor\n    endif\n\n    if (isnan (xmin) || isnan (xmax))\n      xmin = 0;\n      xmax = 1;\n    elseif (xmin == xmax)\n      xmax = xmin + 1;\n    endif\n\n    N = 3;\n    if (xmax - xmin < N)\n      ## Day scale or less\n      if (xmax - xmin < N / 24 / 60 / 60)\n        scl = 1 / 24 / 60 / 60;\n      elseif (xmax - xmin < N / 24 / 60)\n        scl = 1 / 24 / 60;\n      else\n        scl = 1 / 24;\n      endif\n      sep = __calc_tick_sep__ (xmin / scl , xmax / scl);\n      xmin = sep * floor (xmin / scl / sep);\n      xmax = sep * ceil (xmax / scl / sep);\n      nticks = (xmax - xmin) / sep + 1;\n      xmin *= scl;\n      xmax *= scl;\n      ticks = xmin + [0 : nticks - 1] / (nticks - 1) * (xmax - xmin);\n    else\n      [ymin, mmin, dmin] = datevec (xmin);\n      [ymax, mmax, dmax] = datevec (xmax);\n      minyear = ymin + (mmin - 1) / 12 + (dmin - 1) / 12 / 30.5;\n      maxyear = ymax + (mmax - 1) / 12 + (dmax - 1) / 12 / 30.5;\n      minmonth = mmin + (dmin - 1) / 30.5;\n      maxmonth = (ymax  - ymin) * 12 + mmax + (dmax - 1) / 30.5;\n\n      if (maxmonth - minmonth < N)\n        sep = __calc_tick_sep__ (xmin, xmax);\n        xmin = sep * floor (xmin / sep);\n        xmax = sep * ceil (xmax / sep);\n        nticks = (xmax - xmin) / sep + 1;\n        ticks = xmin + [0 : nticks - 1] / (nticks - 1) * (xmax - xmin);\n      elseif (maxyear - minyear < N)\n        sep = __calc_tick_sep__ (minmonth, maxmonth);\n        minyear = floor (minyear);\n        minmonth = sep * floor (minmonth / sep);\n        minmonth = ifelse (minmonth == 0, 1, minmonth);\n        maxmonth = sep * ceil (maxmonth / sep);\n        rangemonth = (minmonth:sep:maxmonth)';\n        tickdays = round (1 + 28*mod (rangemonth, 1));\n        ticks = datenum ([repmat(minyear, size(rangemonth)), ...\n                          floor(rangemonth), ...\n                          tickdays]);\n      else\n        sep = __calc_tick_sep__ (minyear, maxyear);\n        minyear = sep * floor (minyear / sep);\n        maxyear = sep * ceil (maxyear / sep);\n        rangeyear = (minyear:sep:maxyear)';\n        tickmonth = round (1 + 12*mod (rangeyear, 1));\n        ticks = datenum ([floor(rangeyear), ...\n                          tickmonth, ...\n                          ones(rows (rangeyear), 1)]);\n      endif\n    endif\n  endif\n\n  if (isempty (form))\n    r = max (ticks) - min (ticks);\n    if (r < 10/60/24)\n      ## minutes and seconds\n      form = 13;\n    elseif (r < 2)\n      ## hours\n      form = 15;\n    elseif (r < 15)\n      ## days\n      form = 8;\n    elseif (r < 365)\n      ## FIXME: FORM should be 19 for European users who use dd/mm\n      ## instead of mm/dd.  How can that be determined automatically?\n      ## months\n      form = 6;\n    elseif (r < 90*12)\n      ## quarters\n      form = 27;\n    else\n      ## years\n      form = 10;\n    endif\n  endif\n\n  if (numel (ticks) == 6)\n    ## Careful that its not treated as a datevec\n    if (! isempty (startdate))\n      sticks = strvcat (datestr (ticks(1:end-1) - ticks(1) + startdate, form),\n      datestr (ticks(end) - ticks(1) + startdate, form));\n    else\n      sticks = strvcat (datestr (ticks(1:end-1), form),\n      datestr (ticks(end), form));\n    endif\n  else\n    if (! isempty (startdate))\n      sticks = datestr (ticks - ticks(1) + startdate, form);\n    else\n      sticks = datestr (ticks, form);\n    endif\n  endif\n\n  sticks = mat2cell (sticks, ones (rows (sticks), 1), columns (sticks));\n\n  if (keepticks)\n    if (keeplimits)\n      set (gca (), [ax \"ticklabel\"], sticks);\n    else\n      set (gca (), [ax \"ticklabel\"], sticks,\n                   [ax \"lim\"], [min(ticks), max(ticks)]);\n    endif\n  else\n    if (keeplimits)\n      set (gca (), [ax \"tick\"], ticks, [ax \"ticklabel\"], sticks);\n    else\n      set (gca (), [ax \"tick\"], ticks, [ax \"ticklabel\"], sticks,\n                   [ax \"lim\"], [min(ticks), max(ticks)]);\n    endif\n  endif\n\nendfunction\n\nfunction [a, b] = __magform__ (x)\n\n  if (x == 0)\n    a = b = 0;\n  else\n    l = log10 (abs (x));\n    r = rem (l, 1);\n    a = 10 .^ r;\n    b = fix (l - r);\n    if (a < 1)\n      a *= 10;\n      b -= 1;\n    endif\n    if (x < 0)\n      a = -a;\n    endif\n  endif\n\nendfunction\n\n## A translation from Tom Holoryd's python code at\n## http://kurage.nimh.nih.gov/tomh/tics.py\nfunction sep = __calc_tick_sep__ (lo, hi)\n  persistent sqrt_2  = sqrt (2.0);\n  persistent sqrt_10 = sqrt (10.0);\n  persistent sqrt_50 = sqrt (50.0);\n\n  ticint = 5;\n\n  ## Reference: C.R. Lewart, \"Algorithms SCALE1, SCALE2, and\n  ## SCALE3 for Determination of Scales on Computer Generated\n  ## Plots\", Communications of the ACM, 10, pp. 639-640, 1973.\n  ## Also cited as ACM Algorithm 463.\n\n  [a, b] = __magform__ ((hi - lo) / ticint);\n\n  if (a < sqrt_2)\n    x = 1;\n  elseif (a < sqrt_10)\n    x = 2;\n  elseif (a < sqrt_50)\n    x = 5;\n  else\n    x = 10;\n  endif\n\n  sep = x * 10 .^ b;\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/appearance/diffuse.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{d} =} diffuse (@var{sx}, @var{sy}, @var{sz}, @var{lv})\n## Calculate the diffuse reflection strength of a surface defined by the normal\n## vector elements @var{sx}, @var{sy}, @var{sz}.\n##\n## The light source location vector @var{lv} can be given as a 2-element vector\n## [azimuth, elevation] in degrees or as a 3-element vector [x, y, z].\n## @seealso{specular, surfl}\n## @end deftypefn\n\nfunction d = diffuse (sx, sy, sz, lv)\n\n  if (nargin != 4)\n    print_usage ();\n  endif\n\n  ## Check normal vectors\n  if (! size_equal (sx, sy, sz))\n    error (\"diffuse: SX, SY, and SZ must be the same size\");\n  endif\n\n  ## Check light vector (lv) argument\n  if (! isvector (lv) || numel (lv) < 2 || numel (lv) > 3)\n    error (\"diffuse: light vector LV must be a 2- or 3-element vector\");\n  elseif (numel (lv) == 2)\n    [lv(1), lv(2), lv(3)] = sph2cart (lv(1) * pi/180, lv(2) * pi/180, 1.0);\n  endif\n\n  ## Normalize view and light vector.\n  if (sum (abs (lv)) > 0)\n    lv /= norm (lv);\n  endif\n\n  ns = sqrt (sx.^2 + sy.^2 + sz.^2);\n  d = (sx * lv(1) + sy * lv(2) + sz * lv(3)) ./ ns;\n  d(d < 0) = 0;\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/appearance/grid.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} grid\n## @deftypefnx {} {} grid on\n## @deftypefnx {} {} grid off\n## @deftypefnx {} {} grid minor\n## @deftypefnx {} {} grid minor on\n## @deftypefnx {} {} grid minor off\n## @deftypefnx {} {} grid (@var{hax}, @dots{})\n## Control the display of plot grid lines.\n##\n## The function state input may be either @qcode{\"on\"} or @qcode{\"off\"}.\n## If it is omitted, the current grid state is toggled.\n##\n## When the first argument is @qcode{\"minor\"} all subsequent commands\n## modify the minor grid rather than the major grid.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## To control the grid lines for an individual axes use the @code{set}\n## function.  For example:\n##\n## @example\n## set (gca, \"ygrid\", \"on\");\n## @end example\n## @seealso{axis, box}\n## @end deftypefn\n\nfunction grid (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"grid\", varargin{:});\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  ## Must be after gca (), since grid with no plot should create one.\n  if (nargin > 2)\n    print_usage ();\n  endif\n\n  grid_on = any (strcmp (get (hax, {\"xgrid\", \"ygrid\", \"zgrid\"}), \"on\"));\n\n  minor_on = ...\n    any (strcmp (get (hax, {\"xminorgrid\", \"yminorgrid\", \"zminorgrid\"}), \"on\")\n         & ! strcmp (get (hax, {\"xscale\", \"yscale\", \"zscale\"}), \"log\"));\n\n  minor_auto = true;\n  if (nargin == 0)\n    grid_on = ! grid_on;\n    if (! grid_on)\n      minor_auto = false;\n    endif\n  else\n    arg1 = varargin{1};\n    if (! ischar (arg1))\n      error (\"grid: argument 1 must be an axis handle or a string\");\n    endif\n    if (strcmpi (arg1, \"off\"))\n      grid_on = false;\n      minor_on = false;\n      minor_auto = false;\n    elseif (strcmpi (arg1, \"on\"))\n      grid_on = true;\n      minor_auto = true;\n    elseif (strcmpi (arg1, \"minor\"))\n      minor_auto = false;\n      if (nargin == 2)\n        arg2 = varargin{2};\n        if (strcmpi (arg2, \"on\"))\n          minor_on = true;\n        elseif (strcmpi (arg2, \"off\"))\n          minor_on = false;\n        else\n          print_usage ();\n        endif\n      else\n        minor_on = ! minor_on;\n      endif\n    else\n      print_usage ();\n    endif\n  endif\n\n  if (grid_on)\n    set (hax, \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  else\n    set (hax, \"xgrid\", \"off\", \"ygrid\", \"off\", \"zgrid\", \"off\");\n  endif\n\n  if (minor_on)\n    set (hax, \"xminorgrid\", \"on\", \"yminorgrid\", \"on\", \"zminorgrid\", \"on\");\n  elseif (minor_auto)\n    xmg = ifelse (strcmp (get (hax, \"xscale\"), \"log\"), \"on\", \"off\");\n    ymg = ifelse (strcmp (get (hax, \"yscale\"), \"log\"), \"on\", \"off\");\n    zmg = ifelse (strcmp (get (hax, \"zscale\"), \"log\"), \"on\", \"off\");\n    set (hax, \"xminorgrid\", xmg, \"yminorgrid\", ymg, \"zminorgrid\", zmg);\n  else\n    set (hax, \"xminorgrid\", \"off\", \"yminorgrid\", \"off\", \"zminorgrid\", \"off\");\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! subplot (3, 2, 1);\n%!  plot (1:100);\n%!  grid off;\n%!  title (\"grid off\");\n%! subplot (3, 2, 2);\n%!  plot (1:100);\n%!  grid on;\n%!  title (\"grid on\");\n%! subplot (3, 2, 3);\n%!  plot (1:100);\n%!  set (gca, \"xgrid\", \"on\");\n%!  title (\"xgrid on\");\n%! subplot (3, 2, 4);\n%!  plot (1:100);\n%!  set (gca, \"ygrid\", \"on\");\n%!  title (\"ygrid on\");\n%! subplot (3, 2, 5);\n%!  plot (1:100);\n%!  grid minor;\n%!  title (\"grid minor\");\n%! subplot (3, 2, 6);\n%!  plot (1:100);\n%!  set (gca, \"yminorgrid\", \"on\");\n%!  title (\"yminorgrid on\");\n\n%!demo\n%! clf;\n%! subplot (2,2,1);\n%!  semilogy (1:100);\n%!  grid off;\n%!  title (\"grid off\");\n%! subplot (2,2,2);\n%!  semilogy (1:100);\n%!  grid on;\n%!  title (\"grid on\");\n%! subplot (2,2,3);\n%!  semilogy (1:100);\n%!  grid off;\n%!  title (\"no grid\");\n%! subplot (2,2,4);\n%!  semilogy (1:100);\n%!  grid minor;\n%!  title (\"grid minor\");\n\n%!demo\n%! ## Display minor grid lines at major ticks\n%! clf;\n%! subplot (1,2,1)\n%!  plot (1:10);\n%!  set (gca, \"xminorgrid\", \"on\");\n%!  set (gca, \"yminorgrid\", \"on\");\n%!  title ({\"major grid disabled\",\n%!          \"minor grid displayed at major ticks\"});\n%! subplot (1,2,2)\n%!  semilogy (1:100);\n%!  set (gca, \"xminorgrid\", \"on\");\n%!  set (gca, \"yminorgrid\", \"on\");\n%!  title ({\"major grid disabled\",\n%!          \"minor grid displayed at major ticks\"});\n\n%!demo\n%! clf;\n%! plot3 (1:10, 1:10, 1:10);\n%! set (gca, \"xtick\", [0, pi/2, 4.7, 8, 10]);\n%! set (gca, \"ytick\", [0, 1, pi, 7.3, 10]);\n%! set (gca, \"ztick\", [0, exp(1), 5, 9.1, 10]);\n%! set (gca, \"xminorgrid\", \"on\");\n%! set (gca, \"yminorgrid\", \"on\");\n%! set (gca, \"zminorgrid\", \"on\");\n%! view (3);\n%! title (\"Minor grid adapts to xticks (bug #45850)\")\n\n## linear scaling\n%!test <*48533>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   plot (1:10);\n%!   grid on\n%!   assert (get (hax, \"xgrid\"), \"on\");\n%!   assert (get (hax, \"ygrid\"), \"on\");\n%!   assert (get (hax, \"zgrid\"), \"on\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"off\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%!   grid minor\n%!   assert (get (hax, \"xgrid\"), \"on\");\n%!   assert (get (hax, \"ygrid\"), \"on\");\n%!   assert (get (hax, \"zgrid\"), \"on\");\n%!   assert (get (hax, \"xminorgrid\"), \"on\");\n%!   assert (get (hax, \"yminorgrid\"), \"on\");\n%!   assert (get (hax, \"zminorgrid\"), \"on\");\n%!   grid off\n%!   assert (get (hax, \"xgrid\"), \"off\");\n%!   assert (get (hax, \"ygrid\"), \"off\");\n%!   assert (get (hax, \"zgrid\"), \"off\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"off\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%!   grid minor\n%!   assert (get (hax, \"xgrid\"), \"off\");\n%!   assert (get (hax, \"ygrid\"), \"off\");\n%!   assert (get (hax, \"zgrid\"), \"off\");\n%!   assert (get (hax, \"xminorgrid\"), \"on\");\n%!   assert (get (hax, \"yminorgrid\"), \"on\");\n%!   assert (get (hax, \"zminorgrid\"), \"on\");\n%!   grid minor\n%!   assert (get (hax, \"xgrid\"), \"off\");\n%!   assert (get (hax, \"ygrid\"), \"off\");\n%!   assert (get (hax, \"zgrid\"), \"off\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"off\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%!   grid\n%!   assert (get (hax, \"xgrid\"), \"on\");\n%!   assert (get (hax, \"ygrid\"), \"on\");\n%!   assert (get (hax, \"zgrid\"), \"on\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"off\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%!   grid\n%!   assert (get (hax, \"xgrid\"), \"off\");\n%!   assert (get (hax, \"ygrid\"), \"off\");\n%!   assert (get (hax, \"zgrid\"), \"off\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"off\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## semilog scaling\n%!test <*48533>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   semilogy (1:100);\n%!   grid on\n%!   assert (get (hax, \"xgrid\"), \"on\");\n%!   assert (get (hax, \"ygrid\"), \"on\");\n%!   assert (get (hax, \"zgrid\"), \"on\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"on\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%!   grid on\n%!   assert (get (hax, \"xgrid\"), \"on\");\n%!   assert (get (hax, \"ygrid\"), \"on\");\n%!   assert (get (hax, \"zgrid\"), \"on\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"on\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%!   grid minor\n%!   assert (get (hax, \"xgrid\"), \"on\");\n%!   assert (get (hax, \"ygrid\"), \"on\");\n%!   assert (get (hax, \"zgrid\"), \"on\");\n%!   assert (get (hax, \"xminorgrid\"), \"on\");\n%!   assert (get (hax, \"yminorgrid\"), \"on\");\n%!   assert (get (hax, \"zminorgrid\"), \"on\");\n%!   grid off\n%!   assert (get (hax, \"xgrid\"), \"off\");\n%!   assert (get (hax, \"ygrid\"), \"off\");\n%!   assert (get (hax, \"zgrid\"), \"off\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"off\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%!   grid minor\n%!   assert (get (hax, \"xgrid\"), \"off\");\n%!   assert (get (hax, \"ygrid\"), \"off\");\n%!   assert (get (hax, \"zgrid\"), \"off\");\n%!   assert (get (hax, \"xminorgrid\"), \"on\");\n%!   assert (get (hax, \"yminorgrid\"), \"on\");\n%!   assert (get (hax, \"zminorgrid\"), \"on\");\n%!   grid minor\n%!   assert (get (hax, \"xgrid\"), \"off\");\n%!   assert (get (hax, \"ygrid\"), \"off\");\n%!   assert (get (hax, \"zgrid\"), \"off\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"off\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%!   grid\n%!   assert (get (hax, \"xgrid\"), \"on\");\n%!   assert (get (hax, \"ygrid\"), \"on\");\n%!   assert (get (hax, \"zgrid\"), \"on\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"on\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%!   grid\n%!   assert (get (hax, \"xgrid\"), \"off\");\n%!   assert (get (hax, \"ygrid\"), \"off\");\n%!   assert (get (hax, \"zgrid\"), \"off\");\n%!   assert (get (hax, \"xminorgrid\"), \"off\");\n%!   assert (get (hax, \"yminorgrid\"), \"off\");\n%!   assert (get (hax, \"zminorgrid\"), \"off\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/gtext.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} gtext (@var{s})\n## @deftypefnx {} {} gtext (@{@var{s1}, @var{s2}, @dots{}@})\n## @deftypefnx {} {} gtext (@{@var{s1}; @var{s2}; @dots{}@})\n## @deftypefnx {} {} gtext (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {@var{h} =} gtext (@dots{})\n## Place text on the current figure using the mouse.\n##\n## The string argument @var{s} may be a character array or a cell array\n## of strings.  If @var{s} has more than one row, each row is used\n## to create a separate text object after a mouse click.  For example:\n##\n## Place a single string after one mouse click\n##\n## @example\n## gtext (\"I clicked here\")\n## @end example\n##\n## Place two strings after two mouse clicks\n##\n## @example\n## gtext (@{\"I clicked here\"; \"and there\"@})\n## @end example\n##\n## Place two strings, each with two lines, after two mouse clicks\n##\n## @example\n## gtext (@{\"I clicked\", \"here\"; \"and\", \"there\"@})\n## @end example\n##\n## Optional @var{property}/@var{value} pairs are passed directly to the\n## underlying text objects.\n##\n## The full list of text object properties is documented at\n## @ref{Text Properties}.\n##\n## The optional return value @var{h} holds the graphics handle(s) to the\n## created text object(s).\n## @seealso{ginput, text}\n## @end deftypefn\n\nfunction h = gtext (s, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (ischar (s) || iscellstr (s)))\n    error (\"gtext: S must a character array or cell array of strings\");\n  endif\n\n  htmp = [];\n  if (! isempty (s))\n    for i = 1:rows (s)\n      [x, y] = ginput (1);\n      htmp = [htmp, text(x, y, s(i,:), varargin{:})];\n    endfor\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n## Remove from test statistics.  No real tests possible.\n%!assert (1)\n"
  },
  {
    "path": "scripts/plot/appearance/hidden.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} hidden\n## @deftypefnx {} {} hidden on\n## @deftypefnx {} {} hidden off\n## @deftypefnx {} {@var{mode} =} hidden (@dots{})\n## Control mesh hidden line removal.\n##\n## When called with no argument the hidden line removal state is toggled.\n##\n## When called with one of the modes @qcode{\"on\"} or @qcode{\"off\"} the state\n## is set accordingly.\n##\n## The optional output argument @var{mode} is the current state.\n##\n## Hidden Line Removal determines what graphic objects behind a mesh plot\n## are visible.  The default is for the mesh to be opaque and lines behind\n## the mesh are not visible.  If hidden line removal is turned off then\n## objects behind the mesh can be seen through the faces (openings) of the\n## mesh, although the mesh grid lines are still opaque.\n##\n## @seealso{mesh, meshc, meshz, ezmesh, ezmeshc, trimesh, waterfall}\n## @end deftypefn\n\nfunction state = hidden (mode = \"toggle\")\n\n  if (nargin == 1)\n    if (! ischar (mode))\n      error (\"hidden: MODE must be a string\");\n    elseif (! any (strcmpi (mode, {\"on\", \"off\"})))\n      error ('hidden: MODE must be \"on\" or \"off\"');\n    endif\n  endif\n\n  for h = (get (gca (), \"children\")).'\n    [htype, htag] = get (h, {\"type\", \"tag\"}){:};\n    if (strcmp (htype, \"surface\") || strcmp (htag, \"trimesh\"))\n      fc = get (h, \"facecolor\");\n      if ((! ischar (fc) && is_white (fc))\n          || (ischar (fc) && strcmp (fc, \"none\")))\n        switch (mode)\n          case \"on\"\n            set (h, \"facecolor\", \"w\");\n          case \"off\"\n            set (h, \"facecolor\", \"none\");\n          case \"toggle\"\n            if (ischar (fc))\n              set (h, \"facecolor\", \"w\");\n              mode = \"on\";\n            else\n              set (h, \"facecolor\", \"none\");\n              mode = \"off\";\n            endif\n        endswitch\n      endif\n    endif\n  endfor\n\n  if (nargout > 0)\n    state = mode;\n  endif\n\nendfunction\n\nfunction retval = is_white (color)\n  retval = all (color == 1);\nendfunction\n"
  },
  {
    "path": "scripts/plot/appearance/legend.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} legend ()\n## @deftypefnx {} {} legend @var{command}\n## @deftypefnx {} {} legend (@var{str1}, @var{str2}, @dots{})\n## @deftypefnx {} {} legend (@var{charmat})\n## @deftypefnx {} {} legend (@{@var{cellstr}@})\n## @deftypefnx {} {} legend (@dots{}, @var{property}, @var{value}, @dots{})\n## @deftypefnx {} {} legend (@var{hobjs}, @dots{})\n## @deftypefnx {} {} legend (\"@var{command}\")\n## @deftypefnx {} {} legend (@var{hax}, @dots{})\n## @deftypefnx {} {} legend (@var{hleg}, @dots{})\n## @deftypefnx {} {@var{hleg} =} legend (@dots{})\n##\n## Display a legend for the current axes using the specified strings as labels.\n##\n## Legend entries may be specified as individual character string arguments,\n## a character array, or a cell array of character strings.  When label names\n## might be confused with legend properties, or @var{command} arguments,\n## the labels should be protected by specifying them as a cell array of\n## strings.\n##\n## If the first argument @var{hax} is an axes handle, then add a legend to this\n## axes, rather than the current axes returned by @code{gca}.\n##\n## If the first argument @var{hleg} is a legend handle, then operate on this\n## legend rather than the legend of the current axes.\n##\n## Legend labels are associated with the axes' children; The first label is\n## assigned to the first object that was plotted in the axes, the second label\n## to the next object plotted, etc.  To label specific data objects, without\n## labeling all objects, provide their graphic handles in the input\n## @var{hobjs}.\n##\n## The following customizations are available using @var{command}:\n##\n## @table @asis\n## @item @qcode{\"show\"}\n##   Show legend on the plot\n##\n## @item @qcode{\"hide\"}\n##   Hide legend on the plot\n##\n## @item @qcode{\"toggle\"}\n##   Toggle between @qcode{\"hide\"} and @qcode{\"show\"}\n##\n## @item @qcode{\"boxon\"}\n##   Show a box around legend (default)\n##\n## @item @qcode{\"boxoff\"}\n##   Hide the box around legend\n##\n## @item @qcode{\"right\"}\n##   Place label text to the right of the keys (default)\n##\n## @item @qcode{\"left\"}\n##   Place label text to the left of the keys\n##\n## @item @qcode{\"off\"}\n##   Delete the legend object\n## @end table\n##\n## The @code{legend} function creates a graphics object which has various\n## properties that can be manipulated with @code{get}/@code{set}.\n## Alternatively, properties can be set directly when calling @code{legend} by\n## including @var{property}/@var{value} pairs.  If using this calling form, the\n## labels must be specified as a cell array of strings.  Graphics object\n## properties are documented in detail at @ref{Graphics Object Properties}.\n##\n## Following is a subset of supported legend properties:\n## @c The following table is obtained by copying the output of\n## @c genpropdoc (\"legend\", \"\", {\"autoupdate\", \"box\", \"location\", \"numcolumns\", \"orientation\", \"string\", \"textcolor\"})\n##\n## @table @asis\n##\n## @item @code{autoupdate}: @qcode{\"off\"} | @{@qcode{\"on\"}@}\n## Control whether the number of legend items is updated automatically when\n## objects are added to (or deleted from) the peer axes.  For example:\n##\n## @example\n## @group\n## ## Create a single plot with its legend.\n## figure ();\n## plot (1:10);\n## legend (\"Slope 1\");\n## ## Add another plot and specify its displayname so that\n## ## the legend is correctly updated.\n## hold on;\n## plot ((1:10) * 2, \"displayname\", \"Slope 2\");\n## ## Stop automatic updates for further plots.\n## legend (\"autoupdate\", \"off\");\n## plot ((1:10) * 3);\n## @end group\n## @end example\n##\n## @item @code{box}: @qcode{\"off\"} | @{@qcode{\"on\"}@}\n## Control whether the legend has a surrounding box.\n##\n## @item @code{location}: @qcode{\"best\"} | @qcode{\"bestoutside\"} |\n## @qcode{\"east\"} | @qcode{\"eastoutside\"} | @qcode{\"none\"} | @qcode{\"north\"} |\n## @{@qcode{\"northeast\"}@} | @qcode{\"northeastoutside\"} |\n## @qcode{\"northoutside\"} | @qcode{\"northwest\"}| @qcode{\"northwestoutside\"} |\n## @qcode{\"south\"} | @qcode{\"southeast\"} | @qcode{\"southeastoutside\"} |\n## @qcode{\"southoutside\"} | @qcode{\"southwest\"} | @qcode{\"southwestoutside\"} |\n## @qcode{\"west\"} | @qcode{\"westoutside\"}\n## Control the location of the legend.\n##\n## @item @code{numcolumns}: scalar interger, def. @code{1}\n## Control the number of columns used in the layout of the legend items.\n## For example:\n##\n## @example\n## @group\n## figure ();\n## plot (rand (30));\n## legend (\"numcolumns\", 3);\n## @end group\n## @end example\n##\n## Setting @code{numcolumns} also forces the @code{numcolumnsmode} property\n## to be set to @qcode{\"manual\"}.\n##\n## @item @code{orientation}: @qcode{\"horizontal\"} | @{@qcode{\"vertical\"}@}\n## Control whether the legend items are arranged vertically (column-wise) or\n## horizontally (row-wise).\n##\n## @item @code{string}: string | cell array of strings\n## List of labels for the legend items.  For example:\n##\n## @example\n## @group\n## figure ();\n## plot (rand (20));\n## ## Let legend choose names automatically\n## hl = legend ();\n## ## Selectively change some names\n## str = get (hl, \"string\");\n## str(1:5:end) = \"Garbage\";\n## set (hl, \"string\", str);\n## @end group\n## @end example\n##\n## @item @code{textcolor}: colorspec, def. @code{[0   0   0]}\n## Control the color of the text strings for legend item.\n##\n## @end table\n##\n## The full list of supported legend specific properties can be found at\n## @ref{Legend Properties}.\n##\n## A legend is implemented as an additional axes object with the @code{tag}\n## property set to @qcode{\"legend\"}.  Properties of the legend object may be\n## manipulated directly by using @code{set}.\n##\n## The optional output value @var{hleg} is a handle to the legend object.\n##\n## Implementation Note: The legend label text is either provided in the call to\n## @code{legend} or is taken from the @code{DisplayName} property of the\n## graphics objects.  Only data objects, such as line, patch, and surface, have\n## this property whereas axes, figures, etc.@: do not so they are never present\n## in a legend.  If no labels or @code{DisplayName} properties are available,\n## then the label text is simply @qcode{\"data1\"}, @qcode{\"data2\"}, @dots{},\n## @nospell{@qcode{\"dataN\"}}.\n##\n## The legend @code{FontSize} property is initially set to 90% of the axes\n## @code{FontSize} to which it is attached.  Use @code{set} to override this\n## if necessary.\n## @end deftypefn\n\nfunction [hleg, hleg_obj, hplot, labels] = legend (varargin)\n\n  ## Use the old legend code to handle gnuplot toolkit\n  if (strcmp (graphics_toolkit (), \"gnuplot\"))\n    if (nargout > 0)\n      [hleg, hleg_obj, hplot, labels] = __gnuplot_legend__ (varargin{:});\n    else\n      __gnuplot_legend__ (varargin{:});\n    endif\n    return;\n  endif\n\n  ## FIXME: This function needs to be locked to avoid bug #59439.  Remove this\n  ##        lock once that bug is properly fixed.\n  mlock ();\n\n  ## legend() requires root property to be invisible.\n  if (strcmp (get (groot, 'showhiddenhandles'), 'on'))\n    cleanup = onCleanup (@() set (groot, 'showhiddenhandles', 'on'));\n    set (groot, 'showhiddenhandles', 'off');\n  endif\n\n  opts = parse_opts (varargin{:});\n\n  hl = opts.legend_handle;\n\n  ## Fix property/value pairs\n  pval = opts.propval(:)';\n\n  if (! isempty (opts.action))\n\n    do_set_box = isempty (hl);\n\n    switch (opts.action)\n      case \"boxoff\"\n        tmp_pval = {\"box\", \"off\"};\n        do_set_box = false;\n\n      case \"boxon\"\n        tmp_pval = {\"box\", \"on\"};\n        do_set_box = false;\n\n      case \"hide\"\n        tmp_pval = {\"visible\", \"off\"};\n\n      case \"show\"\n        tmp_pval = {\"visible\", \"on\"};\n\n      case \"toggle\"\n        if (! isempty (hl))\n          if (strcmp (get (hl, \"visible\"), \"on\"))\n            tmp_pval = {\"visible\", \"off\"};\n          else\n            tmp_pval = {\"visible\", \"on\"};\n          endif\n        endif\n\n      case \"left\"\n          tmp_pval = {\"textposition\", \"left\"};\n\n      case \"right\"\n          tmp_pval = {\"textposition\", \"right\"};\n\n      case \"off\"\n        if (! isempty (hl))\n          delete (hl);\n        endif\n        return;\n\n    endswitch\n\n    pval = [tmp_pval, pval];\n    if (do_set_box)\n      pval = [pval, \"box\", \"on\"];\n    endif\n\n  endif\n\n  if (isempty (hl))\n\n    hl = axes (\"parent\", get (opts.axes_handles(1), \"parent\"), ...\n               \"tag\", \"legend\", \"handlevisibility\", \"off\", ...\n               \"ydir\", \"reverse\", \"position\", [.5 .5 .3 .3], ...\n               \"fontsize\", 0.9 * get (opts.axes_handles(1), \"fontsize\"), ...\n               \"clim\", get (opts.axes_handles(1), \"clim\"), ...\n               \"colormap\", get (opts.axes_handles(1), \"colormap\"), ...\n               \"xtick\", [], \"ytick\", [], \"box\", \"on\");\n\n    ## FIXME: Use the axes appdata to store its peer legend handle\n    ## rather that adding a public property and change all uses.\n    for htmp = opts.axes_handles\n      try\n        addproperty (\"__legend_handle__\", htmp, \"handle\", hl);\n      catch\n        set (htmp, \"__legend_handle__\", hl);\n      end_try_catch\n    endfor\n\n    ## Add and update legend specific properties\n    addproperties (hl);\n    try\n      set (hl, \"string\", opts.obj_labels, pval{:});\n    catch ee\n      delete (hl);\n      set (opts.axes_handles, \"__legend_handle__\", []);\n      rethrow (ee);\n    end_try_catch\n\n    ## Update legend layout\n    setappdata (hl, \"__axes_handle__\", opts.axes_handles,\n                    \"__next_label_index__\", opts.next_idx,\n                    \"__peer_objects__\", opts.obj_handles);\n    update_location_cb (hl, [], false);\n    update_edgecolor_cb (hl);\n    update_numchild_cb (hl);\n    update_layout_cb (hl, [], true);\n\n    ## Dummy invisible object that deletes the legend when \"newplot\" is called\n    ht = __go_text__ (opts.axes_handles(1), \"tag\", \"__legend_watcher__\",\n                      \"visible\", \"off\", \"handlevisibility\", \"off\",\n                      \"deletefcn\", {@reset_cb, hl});\n\n    ## Listeners to foreign objects properties are stored for later\n    ## deletion in \"reset_cb\"\n    hax = opts.axes_handles(1);\n    hf = ancestor (hax, \"figure\");\n\n    add_safe_listener (hl, hf, \"colormap\", ...\n                       @(~, ~) set (hl, \"colormap\", get (hax, \"colormap\")));\n\n    add_safe_listener (hl, hax, \"position\", {@maybe_update_layout_cb, hl});\n    add_safe_listener (hl, hax, \"tightinset\", ...\n                       @(h, ~) update_layout_cb (get (h, \"__legend_handle__\")));\n    add_safe_listener (hl, hax, \"clim\", ...\n                       @(hax, ~) set (hl, \"clim\", get (hax, \"clim\")));\n    add_safe_listener (hl, hax, \"colormap\", ...\n                       @(hax, ~) set (hl, \"colormap\", get (hax, \"colormap\")));\n    add_safe_listener (hl, hax, \"fontsize\", ...\n                       @(hax, ~) set (hl, \"fontsize\", 0.9*get (hax, \"fontsize\")));\n    add_safe_listener (hl, hax, \"children\", {@legend_autoupdate_cb, hl});\n\n    ## Listeners to legend properties\n    props = {\"fontsize\", \"fontweight\", \"fontname\", \"interpreter\", ...\n             \"textposition\", \"numcolumnsmode\", \"numcolumns\", \"orientation\"};\n\n    for ii = 1:numel (props)\n      addlistener (hl, props{ii}, {@update_layout_cb, true});\n    endfor\n\n    addlistener (hl, \"autoupdate\", @update_numchild_cb);\n\n    addlistener (hl, \"beingdeleted\", @delete_legend_cb);\n\n    addlistener (hl, \"box\", @update_box_cb);\n\n    addlistener (hl, \"edgecolor\", @update_edgecolor_cb);\n\n    addlistener (hl, \"location\", @update_location_cb);\n\n    addlistener (hl, \"position\", @update_position_cb);\n\n    addlistener (hl, \"string\", @update_string_cb);\n\n    addlistener (hl, \"textcolor\", ...\n                 @(h, ~) set (findobj (h, \"type\", \"text\"), ...\n                              \"color\", get (hl, \"textcolor\")));\n\n    addlistener (hl, \"visible\", @update_visible_cb);\n\n  else\n\n    ## FIXME: This will trigger the execution of update_layout_cb for each\n    ## watched property.  Should we suspend its execution with yet another\n    ## appdata bool property for performance?\n\n    ## Update properties\n    setappdata (hl, \"__peer_objects__\", opts.obj_handles);\n    if (! isempty (opts.obj_labels))\n      set (hl ,\"string\", opts.obj_labels, pval{:})\n    elseif (! isempty (pval))\n      set (hl, pval{:});\n    endif\n\n  endif\n\n  if (nargout > 0)\n    hleg = hl;\n    ## These ones are needed for backward compatibility\n    hleg_obj = get (hl, \"children\");\n    hplot = getappdata (hl, \"__peer_objects__\");\n    labels = get (hl, \"string\");\n  endif\n\n  set (hl, \"handlevisibility\", \"on\");\n\nendfunction\n\nfunction update_box_cb (hl, ~)\n\n  if (strcmp (get (hl, \"box\"), \"on\"))\n    if (strcmp (get (hl, \"color\"), \"none\"))\n      set (hl, \"color\", \"w\");\n    endif\n  else\n    set (hl, \"color\", \"none\");\n  endif\n\nendfunction\n\nfunction update_location_cb (hl, ~, do_layout = true)\n\n  if (strcmp (get (hl, \"location\"), \"best\"))\n    warning (\"Octave:legend:unimplemented-location\",\n             [\"legend: 'best' not yet implemented for location \", ...\n              \"specifier, using 'northeast' instead\\n\"]);\n  endif\n\n  if (do_layout)\n    update_layout_cb (hl);\n  endif\n\nendfunction\n\nfunction update_edgecolor_cb (hl, ~)\n\n  ecolor = get (hl, \"edgecolor\");\n  set (hl, \"xcolor\", ecolor, \"ycolor\", ecolor);\n\nendfunction\n\nfunction update_position_cb (hl, ~)\n\n  updating = getappdata (hl, \"__updating_layout__\");\n  if (isempty (updating) || ! updating)\n    if (! strcmp (get (hl, \"location\"), \"none\"))\n      set (hl, \"location\", \"none\");\n    else\n      update_layout_cb (hl);\n    endif\n  endif\n\nendfunction\n\nfunction update_string_cb (hl, ~)\n\n  ## Check that the number of legend item and the number of labels match\n  ## before calling update_layout_cb.\n  persistent updating = false;\n\n  if (! updating)\n    updating = true;\n    unwind_protect\n      str = get (hl, \"string\");\n      nstr = numel (str);\n\n      obj = getappdata (hl, \"__peer_objects__\");\n      nobj = numel (obj);\n\n      if (ischar (str) && nobj != 1)\n        setappdata (hl, \"__peer_objects__\", obj(1));\n      elseif (iscellstr (str) && nobj != nstr)\n        if (nobj > nstr)\n          setappdata (hl, \"__peer_objects__\", obj(1:nstr));\n        elseif (nobj == 1)\n          set (hl, \"string\", str{1});\n        else\n          set (hl, \"string\", str(1:nobj));\n        endif\n      endif\n      update_layout_cb (hl, [], true);\n    unwind_protect_cleanup\n      updating = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\nfunction update_visible_cb (hl, ~)\n\n  location = get (hl, \"location\");\n  if (strcmp (location(end:-1:end-3), \"edis\"))\n    update_layout_cb (hl);\n  endif\n\nendfunction\n\nfunction reset_cb (ht, ~, hl, deletelegend = true)\n\n  if (ishghandle (hl))\n    listeners = getappdata (hl, \"__listeners__\");\n    for ii = 1:numel (listeners)\n      if (ishghandle (listeners{ii}{1}))\n        dellistener (listeners{ii}{:});\n      endif\n    endfor\n\n    if (deletelegend)\n      delete (hl);\n    endif\n  endif\n\nendfunction\n\nfunction delete_legend_cb (hl, ~)\n\n  reset_cb ([], [], hl, false);\n\n  hax = getappdata (hl, \"__axes_handle__\");\n  for h = hax(:)'\n    units = get (h, \"units\");\n    set (h, \"units\", getappdata (hl, \"__original_units__\"), ...\n            \"looseinset\", getappdata (hl, \"__original_looseinset__\"), ...\n            \"units\", units, \"__legend_handle__\", []);\n  endfor\n\nendfunction\n\nfunction add_safe_listener (hl, varargin)\n\n  addlistener (varargin{:});\n\n  lsn = getappdata (hl, \"__listeners__\");\n  lsn = [lsn, {varargin}];\n  setappdata (hl, \"__listeners__\", lsn);\n\nendfunction\n\nfunction addproperties (hl)\n\n  persistent default_locs = ...\n    strjoin ({\"north\", \"northoutside\", ...\n              \"south\", \"southoutside\", ...\n              \"east\", \"eastoutside\", ...\n              \"west\", \"westoutside\", ...\n              \"{northeast}\", \"northeastoutside\", ...\n              \"northwest\", \"northwestoutside\", ...\n              \"southeast\", \"southeastoutside\", ...\n              \"southwest\", \"southwestoutside\", ...\n              \"best\", \"bestoutside\", ...\n              \"none\"}, \"|\");\n\n  addproperty (\"location\", hl, \"radio\", default_locs);\n\n  addproperty (\"orientation\", hl, \"radio\", \"{vertical}|horizontal\");\n\n  addproperty (\"numcolumns\", hl, \"double\", 1);\n\n  addproperty (\"numcolumnsmode\", hl, \"radio\", \"{auto}|manual\");\n\n  addlistener (hl, \"numcolumns\", @(h, ~) set (h, \"numcolumnsmode\", \"manual\"));\n\n  addproperty (\"autoupdate\", hl, \"radio\", \"{on}|off\");\n\n  addproperty (\"string\", hl, \"textstring\", {});\n\n  addproperty (\"interpreter\", hl, \"textinterpreter\");\n\n  addproperty (\"edgecolor\", hl, \"color\", [.15 .15 .15]);\n\n  addproperty (\"textcolor\", hl, \"color\", get (0, 'DefaultTextColor'));\n\n  addproperty (\"textposition\", hl, \"radio\", \"left|{right}\");\n\n  addproperty (\"itemhitfcn\", hl, \"axesbuttondownfcn\");\n\nendfunction\n\nfunction maybe_update_layout_cb (h, ~, hl)\n\n  persistent updating = false;\n\n  if (! updating)\n\n    unwind_protect\n      updating = true;\n      units = get (h, \"units\");\n      set (h, \"units\", \"points\");\n      pos = get (h, \"position\");\n      set (h, \"units\", units);\n      old_pos = getappdata (hl, \"__peer_axes_position__\");\n\n      if (! all (pos == old_pos))\n        update_layout_cb (hl);\n        setappdata (hl, \"__peer_axes_position__\", pos);\n      endif\n    unwind_protect_cleanup\n      updating = false;\n    end_unwind_protect\n\n  endif\n\nendfunction\n\nfunction update_numchild_cb (hl, ~)\n\n  if (strcmp (get (hl, \"autoupdate\"), \"on\"))\n\n    hax = getappdata (hl, \"__axes_handle__\");\n    kids = get (hax, \"children\");\n    if (iscell (kids))\n      nkids = numel (cell2mat (get (hax, \"children\")));\n    else\n      nkids = numel (get (hax, \"children\"));\n    endif\n\n    setappdata (hl, \"__total_num_children__\", nkids);\n\n  endif\n\nendfunction\n\nfunction legend_autoupdate_cb (hax, ~, hl)\n\n  ## Get all current children including eventual peer plotyy axes children\n  try\n    hax = get (hax, \"__plotyy_axes__\");\n    kids = cell2mat (get (hax, \"children\"));\n  catch\n    kids = get (hax, \"children\");\n  end_try_catch\n\n  is_deletion = (getappdata (hl, \"__total_num_children__\") > numel (kids));\n  setappdata (hl, \"__total_num_children__\", numel (kids));\n\n  ## Remove item for deleted object\n  current_obj = getappdata (hl, \"__peer_objects__\");\n  [~, iold, inew] = setxor (current_obj, kids);\n  current_obj(iold) = [];\n\n  if (isempty (current_obj))\n    delete (hl);\n    return;\n  endif\n\n  if (! is_deletion && strcmp (get (hl, \"autoupdate\"), \"on\"))\n\n    ## We only expect 1 new child\n    kids = kids(min (inew));\n\n    ## FIXME: if the latest child is an hggroup, we cannot label it since this\n    ## function is called before the hggroup has been properly populated.\n    persistent valid_types = {\"line\", \"patch\", \"scatter\", \"surface\"};\n    if (! any (strcmp (get (kids, \"type\"), valid_types)))\n      kids = [];\n    endif\n\n  else\n    kids = [];\n  endif\n\n  if (any (iold) || any (kids))\n    setappdata (hl, \"__peer_objects__\", [current_obj; kids]);\n    set (hl, \"string\", displayname_or_default ([current_obj; kids], hl));\n  endif\n\nendfunction\n\nfunction opts = parse_opts (varargin)\n\n  action = \"\";\n  legend_handle = [];\n  axes_handles = [];\n  obj_handles = [];\n  obj_labels = {};\n\n  nargs = numel (varargin);\n\n  ## Find peer axes\n  if (nargs > 0)\n    if (! ishghandle (varargin{1}))\n      [axes_handles, varargin, nargs] = __plt_get_axis_arg__ (\"legend\",\n                                                              varargin{:});\n    elseif (strcmp (get (varargin{1}, \"type\"), \"axes\"))\n      if (strcmp (get (varargin{1}, \"tag\"), \"legend\"))\n        legend_handle = varargin{1};\n        varargin(1) = [];\n        nargs--;\n        axes_handles = getappdata (legend_handle, \"__axes_handle__\");\n      else\n        [axes_handles, varargin, nargs] = __plt_get_axis_arg__ (\"legend\",\n                                                                varargin{:});\n      endif\n    endif\n    if (isempty (axes_handles))\n      axes_handles = gca ();\n    endif\n  else\n    axes_handles = gca ();\n  endif\n\n  ## Special handling for plotyy which has two axes objects\n  if (isprop (axes_handles, \"__plotyy_axes__\"))\n    axes_handles = [axes_handles get(axes_handles, \"__plotyy_axes__\").'];\n    ## Remove duplicates while preserving order\n    [~, n] = unique (axes_handles, \"first\");\n    axes_handles = axes_handles(sort (n));\n  endif\n\n  ## Find any existing legend object associated with axes\n  if (isempty (legend_handle))\n    try\n      legend_handle = get (axes_handles, \"__legend_handle__\");\n      if (iscell (legend_handle))\n        legend_handle = unique (cell2mat (legend_handle));\n      endif\n    end_try_catch\n  endif\n\n  ## Legend actions\n  actions = {\"show\", \"hide\", \"toggle\", \"boxon\", ...\n             \"boxoff\", \"right\", \"left\", \"off\"};\n  if (nargs > 0 && ischar (varargin{1})\n      && any (strcmp (varargin{1}, actions)))\n    action = varargin{1};\n    if (nargs > 1)\n      warning (\"Octave:legend:ignoring-extra-argument\",\n               'legend: ignoring extra arguments after \"%s\"', action);\n    endif\n    nargs = 0;\n  endif\n\n  ## Now remove property-value pairs for compatibility.\n  propval = {};\n  warn_propval = \"\";\n  persistent legend_props = {\"location\", \"orientation\", \"numcolumns\", ...\n                             \"numcolumnsmode\", \"textposition\", ...\n                             \"position\", \"units\", \"autoupdate\", ...\n                             \"string\", \"title\", \"interpreter\", ...\n                             \"fontname\", \"fontsize\", \"fontweight\", ...\n                             \"fontangle\", \"textcolor\", \"color\", ...\n                             \"edgecolor\", \"box\", \"linewidth\", ...\n                             \"visible\", \"uicontextmenu\", \"selected\", ...\n                             \"selectionhighlight\", \"itemhitfcn\", ...\n                             \"buttondownfcn\", \"createfcn\", \"deletefcn\" ...\n                             \"interruptible\", \"busyaction\", ...\n                             \"pickableparts\", \"hittest\", ...\n                             \"beingdeleted\", \"parent\", \"children\", ...\n                             \"handlevisibility\", \"tag\", \"type\", ...\n                             \"userdata\"};\n  isprp = @(prop) (ischar (prop) && any (strcmpi (legend_props, prop)));\n  idx = find (cellfun (isprp, varargin));\n  if (! isempty (idx))\n    idx = idx(1);\n    propval = varargin(idx:end);\n    warn_propval = varargin{idx};\n    varargin(idx:end) = [];\n    nargs = idx-1;\n  endif\n\n  ## List plot objects that can be handled\n  warn_extra_obj = false;\n  persistent valid_types = {\"hggroup\", \"line\", \"patch\", \"scatter\", \"surface\"};\n\n  if (nargs > 0 && all (ishghandle (varargin{1})))\n\n    ## List of plot objects to label given as first argument\n    obj_handles = varargin{1};\n    types = get (obj_handles, \"type\");\n    if (! iscell (types))\n      types = {types};\n    endif\n\n    idx = cellfun (@(s) any (strcmp (s, valid_types)), types);\n    if (! all (idx))\n      error (\"Octave:legend:bad-object\",\n             \"legend: objects of type \\\"%s\\\" can't be labeled\",\n             types(! idx){1});\n    endif\n    varargin(1) = [];\n    nargs--;\n    warn_extra_obj = true;\n\n  elseif (nargs > 0 || isempty (legend_handle))\n\n    ## Find list of plot objects from axes \"children\"\n    if (isscalar (axes_handles))\n      obj_handles = flipud (get (axes_handles, \"children\")(:));\n    else\n      tmp = get (axes_handles(:), \"children\");\n      obj_handles = [flipud(tmp{1}); flipud(tmp{2})];\n    endif\n\n    if (isempty (obj_handles))\n      error (\"Octave:legend:no-object\", \"legend: no valid object to label\");\n    endif\n\n    idx = arrayfun (@(h) any (strcmp (get (h, \"type\"), valid_types)), ...\n                              obj_handles);\n    obj_handles(! idx) = [];\n\n    if (isempty (obj_handles))\n      error (\"Octave:legend:no-object\", \"legend: no valid object to label\");\n    endif\n\n  else\n    obj_handles = getappdata (legend_handle, \"__peer_objects__\");\n  endif\n\n  nobj = numel (obj_handles);\n\n  ## List labels\n  next_idx = 1;\n  if (nargs > 0)\n\n    if (iscellstr (varargin{1}))\n      obj_labels = varargin{1};\n      varargin(1) = [];\n      nargs--;\n    elseif (ischar (varargin{1}) && rows (varargin{1}) > 1)\n      obj_labels = cellstr (varargin{1});\n      varargin(1) = [];\n      nargs--;\n    elseif (all (cellfun ('ischar', varargin)))\n      obj_labels = varargin;\n      varargin = {};\n      nargs = 0;\n    endif\n\n    if (nargs > 0)\n      print_usage (\"legend\");\n    endif\n\n    nlab = numel (obj_labels);\n    if (nlab != nobj)\n      if (nobj > nlab)\n        obj_handles = obj_handles(1:nlab);\n\n        msg = \"legend: ignoring extra objects.\";\n        if (! isempty (warn_propval))\n          msg = [msg ' \"' warn_propval '\" interpreted as a property ' , ...\n                 \"name.  Use a cell array of strings to specify labels \", ...\n                 \"that match a legend property name.\"];\n        endif\n        if (warn_extra_obj)\n          warning (\"Octave:legend:object-label-mismatch\", msg);\n        endif\n      else\n        obj_labels = obj_labels(1:nobj);\n        warning (\"Octave:legend:object-label-mismatch\",\n                 \"legend: ignoring extra labels.\");\n      endif\n    endif\n  else\n    [tmp_labels, next_idx] = displayname_or_default (obj_handles,\n                                                     legend_handle);\n    if (isempty (legend_handle)\n        || ! isequal (tmp_labels, get (legend_handle, \"string\")))\n      obj_labels = tmp_labels;\n    endif\n\n  endif\n\n  opts.action = action;\n  opts.axes_handles = axes_handles;\n  opts.obj_handles = obj_handles;\n  opts.obj_labels = obj_labels;\n  opts.legend_handle = legend_handle;\n  opts.propval = propval;\n  opts.next_idx = next_idx;\n\nendfunction\n\nfunction [labels, next_idx] = displayname_or_default (hplots, hl = [])\n\n  next_idx = 1;\n  if (! isempty (hl))\n    next_idx = getappdata (hl, \"__next_label_index__\");\n  endif\n\n  ## Use the displayname property\n  labels = get (hplots, \"displayname\");\n  if (! iscell (labels))\n    labels = {labels};\n  endif\n\n  ## Fallback to automatic names for empty labels\n  empty_label_idx = cellfun ('isempty', labels);\n\n  if (any (empty_label_idx) && ! isempty (hl))\n    ## Empty strings must not be blindly replaced by data%d.  If there exist\n    ## an old text object that was affected an empty string, keep it as is.\n    kids = get (hl, \"children\");\n    htext = kids(strcmp (get (kids, \"type\"), \"text\"));\n    old_objects = get (htext, \"peer_object\");\n    if (iscell (old_objects))\n      old_objects = cell2mat (old_objects);\n    endif\n\n    for h = hplots(empty_label_idx).'\n      idx = (h == old_objects);\n      if (any (idx))\n        labels(hplots == h) = get (htext(idx), \"string\");\n        empty_label_idx(hplots == h) = false;\n      endif\n    endfor\n\n  endif\n\n  if (any (empty_label_idx))\n    default = arrayfun (@(ii) sprintf (\"data%d\", ii), ...\n                        [next_idx:(next_idx + sum (empty_label_idx) - 1)], ...\n                        \"uniformoutput\", false)(:);\n    labels(empty_label_idx) = default;\n  endif\n\n  next_idx += sum (empty_label_idx);\n\n  if (! isempty (hl))\n    setappdata (hl, \"__next_label_index__\", next_idx);\n  endif\n\nendfunction\n\nfunction update_layout_cb (hl, ~, update_item = false)\n\n  updating = getappdata (hl, \"__updating_layout__\");\n  if (! isempty (updating) && updating)\n    return;\n  endif\n\n  setappdata (hl, \"__updating_layout__\", true);\n\n  ## Scale limits so that item positions are expressed in points, from\n  ## top to bottom and from left to right or reverse depending on textposition\n  units = get (hl, \"units\");\n  set (hl, \"units\", \"points\");\n\n  unwind_protect\n\n    pos = get (hl, \"position\");\n\n    if (update_item)\n      set (hl, \"xlim\",  [0, pos(3)], \"ylim\",  [0, pos(4)]);\n      textright = strcmp (get (hl, \"textposition\"), \"right\");\n      set (hl, \"ydir\", \"reverse\", ...\n               \"xdir\", ifelse (textright, \"normal\", \"reverse\"));\n\n      ## Create or reuse text and icon graphics objects\n      objlist = texticon_objects (hl, textright);\n      nitem = rows (objlist);\n\n      ## Prepare the array of text/icon pairs and update their position\n      sz = update_texticon_position (hl, objlist);\n    else\n      sz = getappdata (hl, \"__item_bouding_box__\");\n    endif\n\n    ## Place the legend\n    if (! strcmp (get (hl, \"location\"), \"none\"))\n      update_legend_position (hl, sz);\n    else\n      ## Custom location: Adapt width and height if necessary.\n      [x0, y0, x1, y1] = deal (0, 0, sz(1), sz(2));\n\n      if (sz(1) > pos(3))\n        pos(3) = sz(1);\n      else\n        dx = pos(3)-sz(1);\n        x0 -= dx/2;\n        x1 += dx/2;\n      endif\n\n      if (sz(2) > pos(4))\n        pos(4) = sz(2);\n      else\n        dy = pos(4)-sz(2);\n        y0 -= dy/2;\n        y1 += dy/2;\n      endif\n\n      set (hl, \"position\", pos, \"xlim\", [x0 x1], \"ylim\", [y0 y1]);\n    endif\n\n  unwind_protect_cleanup\n    set (hl, \"units\", units);\n    setappdata (hl, \"__updating_layout__\", false);\n  end_unwind_protect\n\nendfunction\n\nfunction objlist = texticon_objects (hl, textright)\n\n  ## Delete or set invisible obsolete or unused text/icon objects.\n  old_kids = get (hl, \"children\")(:).';\n  old_peer_objects = cell2mat (get (old_kids, \"peer_object\"))(:).';\n  unused = ! ishghandle (old_peer_objects);\n  delete (old_kids(unused));\n  old_kids(unused) = [];\n  old_peer_objects(unused) = [];\n\n  new_peer_objects = getappdata (hl, \"__peer_objects__\")(:).';\n\n  unused = arrayfun (@(h) ! any (h == new_peer_objects), old_peer_objects);\n  set (old_kids(unused), \"visible\", \"off\");\n\n  ## Text properties\n  string = get (hl , \"string\");\n  if (! iscell (string))\n    string = {string};\n  endif\n\n  txtprops = {\"textcolor\", \"fontsize\", \"fontweight\", \"fontname\", ...\n              \"interpreter\"};\n  txtvals = get (hl, txtprops);\n  txtprops{1} = \"color\";\n  txtprops = [txtprops, \"horizontalalignment\"];\n  txtvals = [txtvals, ifelse(textright, \"left\", \"right\")];\n\n  ## Create or reuse text/icon objects as needed\n  nitem = numel (new_peer_objects);\n  objlist = NaN (nitem, 2);\n\n  for ii = 1:nitem\n\n    str = string{ii};\n    hplt = new_peer_objects(ii);\n\n    idx = (old_peer_objects == hplt);\n\n    if (any (idx))\n      tmp = old_kids(idx);\n      idx = strcmp (get (tmp, \"type\"), \"text\");\n\n      htxt = tmp(idx);\n      hicon = tmp(! idx);\n\n      set (htxt, \"visible\", \"on\", \"string\", str, ...\n                 [txtprops(:)'; txtvals(:)']{:});\n      set (hicon, \"visible\", \"on\");\n\n    else\n      [htxt, hicon] = create_item (hl, str, [txtprops(:)'; txtvals(:)'], hplt);\n      add_safe_listener (hl, hplt, \"displayname\", {@update_displayname_cb, hl});\n    endif\n\n    set (hplt, \"displayname\", str);\n\n    objlist(ii,:) = [htxt, hicon];\n  endfor\n\nendfunction\n\nfunction [htxt, hicon] = create_item (hl, str, txtpval, hplt)\n\n  typ = get (hplt, \"type\");\n\n  ## For unknown hggroups use the first child that can be labeled\n  persistent known_creators = {\"__contour__\", \"__errplot__\", \"__quiver__\", ...\n                               \"__stem__\"};\n  base_hplt = hplt;\n\n  if (strcmp (typ, \"hggroup\"))\n    creator = getappdata (hplt, \"__creator__\");\n    kids = get (hplt, \"children\");\n    if (any (strcmp (known_creators, creator)))\n      typ = creator;\n      switch (creator)\n        case \"__contour__\"\n          ## Eliminate eventual text objects created by clabel\n          kids(strcmp (get (kids, \"type\"), \"text\")) = [];\n          hplt = [kids(end), kids(1)];\n        case {\"__errplot__\", \"__quiver__\", \"__stem__\"}\n          hplt = kids(2:-1:1);\n        otherwise\n          hplt = kids(1);\n      endswitch\n    else\n      types = get (kids, \"type\");\n      if (! iscell (types))\n        types = {types};\n      endif\n\n      idx = cellfun (@(s) any (strcmp (s, {\"line\", \"patch\", \"surface\"})), ...\n                     types);\n      hplt = kids(idx)(1);\n      typ = types(idx){1};\n    endif\n  endif\n\n  persistent lprops = {\"color\", \"linestyle\", \"linewidth\"};\n  persistent mprops = {\"color\", \"linewidth\", \"marker\", \"markeredgecolor\", ...\n                       \"markerfacecolor\", \"markersize\"};\n  persistent pprops = {\"edgecolor\", \"facecolor\", \"facealpha\", ...\n                       \"linestyle\", \"linewidth\", ...\n                       \"marker\", \"markeredgecolor\", ...\n                       \"markerfacecolor\", \"markersize\"};\n  persistent sprops = {\"marker\", \"markeredgecolor\", ...\n                       \"markerfacecolor\"};\n\n  switch (typ)\n    case {\"line\", \"__errplot__\", \"__quiver__\", \"__stem__\"}\n\n      ## Main line\n      vals = get (hplt(1), lprops);\n      hicon = __go_line__ (hl, [lprops; vals]{:}, ...\n                           \"pickableparts\", \"all\", ...\n                           \"buttondownfcn\", ...\n                           {@execute_itemhit, hl, hplt, \"icon\"});\n\n      addproperty (\"markerxdata\", hicon, \"double\", 0);\n      addproperty (\"markerydata\", hicon, \"double\", 0);\n\n      ## Additional line for the marker\n      vals = get (hplt(end), mprops);\n      hmarker = __go_line__ (hl, \"handlevisibility\", \"off\", ...\n                             \"xdata\", 0, \"ydata\", 0, [mprops; vals]{:}, ...\n                             \"pickableparts\", \"all\", ...\n                             \"buttondownfcn\", ...\n                             {@execute_itemhit, hl, hplt, \"icon\"});\n      addproperty (\"markertruesize\", hmarker, \"double\", NaN);\n      update_marker_cb (hmarker);\n\n      ## Listeners\n      safe_property_link (hplt(1), hicon, lprops);\n      safe_property_link (hplt(end), hmarker, mprops);\n      addlistener (hicon, \"ydata\", ...\n                   @(h, ~) set (hmarker, \"ydata\", get (h, \"markerydata\")));\n      addlistener (hicon, \"xdata\", ...\n                   @(h, ~) set (hmarker, \"xdata\", get (h, \"markerxdata\")));\n      addlistener (hicon, \"visible\", ...\n                   @(h, ~) set (hmarker, \"visible\", get (h, \"visible\")));\n      addlistener (hmarker, \"markersize\", {@update_marker_cb, true});\n      addlistener (hmarker, \"marker\", {@update_marker_cb, false});\n      add_safe_listener (hl, hplt(1), \"beingdeleted\",\n                         @(~, ~) delete ([hicon hmarker]))\n      if (! strcmp (typ, \"__errplot__\"))\n        setappdata (hicon, \"__creator__\", typ);\n      else\n        setappdata (hicon, \"__creator__\", typ, ...\n                    \"__format__\", get (base_hplt, \"format\"));\n      endif\n\n    case {\"patch\", \"surface\"}\n\n      vals = get (hplt, pprops);\n      cdata = get (hplt, \"cdata\");\n\n      hicon = __go_patch__ (hl, [pprops; vals]{:}, ...\n                            \"cdata\", median (median (cdata, 1), 2));\n\n      ## Listeners\n      safe_property_link (hplt(1), hicon, pprops);\n      addlistener (hplt, \"cdata\", ...\n                   @(h, ~) set (hicon, \"cdata\", ...\n                                median (median (get (h, \"cdata\"), 1), 2)));\n\n      setappdata (hicon, \"__creator__\", typ);\n\n    case \"scatter\"\n\n      all_sprops = [sprops, \"sizedata\", \"cdata\"];\n\n      vals = get (hplt, all_sprops);\n\n      ## sizedata and cdata may be N-by-1 vectors or N-by-3 (RGB) martrices.\n      ## Take the average for the icon.\n      vals {end-1} = mean (vals {end-1}, 1);\n      vals {end} = mean (vals {end}, 1);\n\n      hicon = __go_scatter__ (hl, [all_sprops; vals]{:}, ...\n                              \"pickableparts\", \"all\", ...\n                              \"buttondownfcn\", ...\n                              {@execute_itemhit, hl, hplt, \"icon\"});\n\n      ## Simple Listeners\n      safe_property_link (hplt(1), hicon, sprops);\n\n      ## Listener to sizedata\n      lsn = {hplt(1), \"sizedata\", @(h, ~) set (hicon, \"sizedata\", ...\n                                               mean (get (h, \"sizedata\")))};\n      addlistener (lsn{:});\n      addlistener (hicon, \"beingdeleted\", @(~, ~) dellistener (lsn{:}));\n\n      ## Listener to cdata\n      lsn = {hplt(1), \"cdata\", @(h, ~) set (hicon, \"cdata\", ...\n                                            mean (get (h, \"cdata\"), 1))};\n      addlistener (lsn{:});\n      addlistener (hicon, \"beingdeleted\", @(~, ~) dellistener (lsn{:}));\n\n      setappdata (hicon, \"__creator__\", typ);\n\n    case \"__contour__\"\n\n      ## Main patch\n\n      vals = get (hplt(1), pprops);\n      cdata = get (hplt(1), \"cdata\");\n      hicon = __go_patch__ (hl, \"cdata\", cdata, ...\n                            [pprops; vals]{:}, ...\n                            \"pickableparts\", \"all\", ...\n                            \"buttondownfcn\", ...\n                            {@execute_itemhit, hl, hplt, \"icon\"});\n\n      addproperty (\"innerxdata\", hicon, \"any\", 0);\n      addproperty (\"innerydata\", hicon, \"any\", 0);\n\n      ## Additional patch for the inner contour\n      vals = get (hplt(end), pprops);\n      cdata = get (hplt(end), \"cdata\");\n      htmp =  __go_patch__ (hl, \"handlevisibility\", \"off\", ...\n                            \"xdata\", 0, \"ydata\", 0, \"cdata\", cdata, ...\n                            [pprops; vals]{:}, ...\n                            \"pickableparts\", \"all\", ...\n                            \"buttondownfcn\", ...\n                            {@execute_itemhit, hl, hplt, \"icon\"});\n\n      ## Listeners\n      safe_property_link (hplt(1), hicon, [{\"cdata\"}, pprops]);\n      safe_property_link (hplt(end), htmp, [{\"cdata\"}, pprops]);\n      addlistener (hicon, \"ydata\", ...\n                   @(h, ~) set (htmp, \"ydata\", get (h, \"innerydata\")));\n      addlistener (hicon, \"xdata\", ...\n                   @(h, ~) set (htmp, \"xdata\", get (h, \"innerxdata\")));\n      addlistener (hicon, \"visible\", ...\n                   @(h, ~) set (htmp, \"visible\", get (h, \"visible\")));\n      add_safe_listener (hl, hplt(1), \"beingdeleted\",\n                         @(~, ~) delete ([hicon htmp]))\n\n      setappdata (hicon, \"__creator__\", typ);\n\n  endswitch\n\n  htxt = __go_text__ (hl, txtpval{:}, \"string\", str, ...\n                      \"pickableparts\", \"all\", ...\n                      \"buttondownfcn\", {@execute_itemhit, hl, hplt, \"label\"});\n\n  set (htxt, \"buttondownfcn\", {@execute_itemhit, hl, hplt, \"label\"});\n\n  addproperty (\"peer_object\", htxt, \"double\", base_hplt);\n  addproperty (\"peer_object\", hicon, \"double\", base_hplt);\n\nendfunction\n\nfunction execute_itemhit (h, ~, hl, hplt, region)\n\n  fcn = get (hl, \"itemhitfcn\");\n\n  if (! isempty (fcn))\n    evt = struct (\"Peer\", hplt, \"Region\", region, ...\n                  \"SelectionType\", get (gcbf (), \"selectiontype\"), ...\n                  \"Source\", hl, \"EventName\", \"ItemHit\");\n    fcn (hl, evt)\n  endif\n\nendfunction\n\nfunction safe_property_link (h1, h2, props)\n\n  for ii = 1:numel (props)\n    prop = props{ii};\n    lsn = {h1, prop, @(h, ~) set (h2, prop, get (h, prop))};\n    addlistener (lsn{:});\n    addlistener (h2, \"beingdeleted\", @(~, ~) safe_dellistener (lsn{:}));\n  endfor\n\nendfunction\n\nfunction safe_dellistener (h, prop, fcn)\n\n  if (ishghandle (h))\n    dellistener (h, prop, fcn);\n  endif\n\nendfunction\n\nfunction update_displayname_cb (h, ~, hl)\n\n  updating = getappdata (hl, \"__updating_layout__\");\n  if (! isempty (updating) && updating)\n    return;\n  endif\n\n  str = get (hl, \"string\");\n  if (! iscell (str))\n    str = {str};\n  endif\n\n  idx = h == getappdata (hl, \"__peer_objects__\");\n  if (any (idx))\n    str{idx} = get (h, \"displayname\");\n    set (hl ,\"string\", str);\n  endif\n\nendfunction\n\n## Enforce maximum size of marker so it doesn't overflow legend key\nfunction update_marker_cb (h, ~, sz_updated = true)\n  persistent is_updating = false;\n\n  if (is_updating)\n    return;\n  endif\n\n  if (sz_updated)\n    ## Size was changed\n    sz = get (h, \"markersize\");\n    set (h, \"markertruesize\", sz);  # store true marker size\n\n    if (sz > 8)\n      is_updating = true;\n\n      mark = get (h, \"marker\");\n      if (strcmp (mark, '.'))\n        set (h, \"markersize\", min ([sz, 24]));\n      else\n        set (h, \"markersize\", 8);\n      endif\n\n      is_updating = false;\n    endif\n\n  else\n    ## Marker style was changed\n    sz = get (h, \"markertruesize\");\n    if (sz > 8)\n      is_updating = true;\n\n      mark = get (h, \"marker\");\n      if (strcmp (mark, '.'))\n        set (h, \"markersize\", min ([sz, 24]));\n      else\n        set (h, \"markersize\", 8);\n      endif\n\n      is_updating = false;\n    endif\n  endif\n\nendfunction\n\nfunction sz = update_texticon_position (hl, objlist)\n\n  ## margins in points\n  persistent hmargin = 3;\n  persistent vmargin = 3;\n  persistent icon_width = 15;\n\n  units = get (hl, \"fontunits\");\n  set (hl, \"fontunits\", \"points\");\n  icon_height = 0.7 * get (hl, \"fontsize\");\n  set (hl, \"fontunits\", units);\n\n  types = get (objlist(:,2), \"type\");\n  ext = get (objlist(:,1), \"extent\");\n  markers = get (objlist(:,2), \"marker\");\n\n  is_scatter = strcmp (types, \"scatter\");\n  if (! any (is_scatter))\n    markersz = get (objlist(:,2), \"markersize\");\n  elseif (rows (objlist) == 1)\n    markersz = mean (get (objlist(1,2), \"sizedata\").^0.5);\n  else\n    markersz = cell (rows (objlist), 1);\n    for ii = 1:rows (objlist)\n      if (! is_scatter(ii))\n        markersz{ii} = get (objlist(ii,2), \"markersize\");\n      else\n        markersz{ii} = mean (get (objlist(ii,2), \"sizedata\").^0.5);\n      endif\n    endfor\n  endif\n\n  ## Simple case of 1 text/icon pair\n  nitem = rows (objlist);\n  txticon = zeros (nitem, 4);\n  if (nitem == 1)\n    ext = abs (ext(:,3:4));\n    types = {types};\n    markers = {markers};\n    markersz = {markersz};\n  else\n    ext = abs (cell2mat (ext)(:,3:4));\n  endif\n\n  autolayout = strcmp (get (hl, \"numcolumnsmode\"), \"auto\");\n  xmax = ymax = 0;\n  iter = 1;\n\n  if (strcmp (get (hl, \"orientation\"), \"vertical\"))\n\n    if (autolayout)\n      ncol = 1;\n    else\n      ncol = min (nitem, get (hl, \"numcolumns\"));\n    endif\n\n    nrow = ceil (nitem / ncol);\n\n    rowheights = arrayfun (@(idx) max([icon_height;\n                                       ext(idx:nrow:end, 2);\n                                       vertcat(markersz(idx:nrow:end){:})]), ...\n                           1:nrow);\n    x = hmargin;\n    for ii = 1:ncol\n      y = vmargin;\n      for jj = 1:nrow\n        if (iter > nitem)\n          continue;\n        endif\n\n        hg = rowheights(jj);\n        dx = 0;\n        if (! strcmp (markers{iter}, \"none\"))\n          dx = markersz{iter}/2;\n        endif\n\n        ybase = y + hg / 2;\n        y0 = ybase - max (icon_height, dx)/2 + dx;\n        y1 = ybase + max (icon_height, dx)/2 - dx;\n\n        update_icon_position (objlist(iter,2), [x+dx, x+icon_width-dx], ...\n                              [y0, y1]);\n\n        set (objlist(iter,1), \"position\", [x+icon_width+hmargin, ybase, 0]);\n\n        xmax = max ([xmax, x+icon_width+2*hmargin+ext(iter,1)]);\n        y += (vmargin + hg);\n        iter++;\n      endfor\n      ymax = max ([ymax, y]);\n      x = xmax + 2*hmargin;\n    endfor\n\n  else\n\n    if (autolayout)\n      ncol = nitem;\n    else\n      ncol = min (nitem, get (hl, \"numcolumns\"));\n    endif\n\n    nrow = ceil (nitem / ncol);\n\n    colwidth = arrayfun (@(idx) max (ext(idx:ncol:end, 1)),\n                         1:ncol);\n    y = vmargin;\n    for ii = 1:nrow\n      x = hmargin;\n\n      endidx = min (iter+ncol-1, nitem);\n      hg = max ([icon_height; ext(iter:endidx,2); ...\n                 vertcat(markersz{:})]);\n\n      for jj = 1:ncol\n        if (iter > nitem)\n          continue;\n        endif\n\n        wd = colwidth(jj);\n\n        dx = 0;\n        if (! strcmp (markers{iter}, \"none\"))\n          dx = markersz{iter}/2;\n        endif\n\n        ybase = y + hg / 2;\n        y0 = ybase - max (icon_height, dx)/2 + dx;\n        y1 = ybase + max (icon_height, dx)/2 - dx;\n\n        update_icon_position (objlist(iter,2), [x+dx, x+icon_width-dx], ...\n                              [y0, y1]);\n\n        set (objlist(iter,1), \"position\", [x+icon_width+hmargin, ybase, 0]);\n\n        ymax = max ([ymax, ybase+hg/2+vmargin]);\n        x += (3*hmargin + icon_width + wd);\n        iter++;\n      endfor\n      xmax = max ([xmax, x-hmargin]);\n      y = ymax + vmargin;\n    endfor\n\n  endif\n\n  sz = [xmax, ymax];\n  setappdata (hl, \"__item_bouding_box__\", sz);\n\nendfunction\n\nfunction update_icon_position (hicon, xdata, ydata)\n\n  creator = getappdata (hicon, \"__creator__\");\n  switch (creator)\n    case \"line\"\n      set (hicon, \"markerxdata\", mean (xdata), \"markerydata\", mean (ydata), ...\n           \"xdata\", xdata, \"ydata\", [mean(ydata), mean(ydata)]);\n    case {\"patch\", \"surface\"}\n      set (hicon, ...\n           \"xdata\", [xdata, fliplr(xdata)], ...\n           \"ydata\", [ydata; ydata](:).');\n    case \"__contour__\"\n      ## Draw two patches\n      x0 = xdata(1);\n      x1 = xdata(2);\n      xm = mean (xdata);\n      y0 = ydata(1);\n      y1 = ydata(2);\n      ym = mean (ydata);\n\n      xdata = [x0, x1, x1, x0];\n      ydata = [y0, y0, y1, y1];\n      set (hicon, ...\n           \"innerxdata\", (xdata-xm) * 0.6 + xm, ...\n           \"innerydata\", (ydata-ym) * 0.4 + ym, ...\n           \"xdata\", xdata, \"ydata\", ydata);\n    case \"__errplot__\"\n      x0 = xdata(1);\n      x1 = xdata(2);\n      xm = mean (xdata);\n      y0 = ydata(1);\n      y1 = ydata(2);\n      ym = mean (ydata);\n\n      fmt = getappdata (hicon, \"__format__\");\n      if (strcmp (fmt, \"yerr\"))\n        xdata = [xm, xm, xm-2, xm+2, xm, xm, xm-2, xm+2];\n        ydata = [ym, y0, y0, y0, y0, y1, y1, y1];\n      elseif (strcmp (fmt, \"xerr\"))\n        xdata = [x0+2, x0+2, x0+2, x1-2, x1-2, x1-2, x1-2];\n        ydata = [ym+2, ym-2, ym, ym, ym+2, ym-2, ym];\n      elseif (strcmp (fmt, \"xyerr\"))\n        xdata = [x0+2, x0+2, x0+2, x1-2, x1-2, x1-2, x1-2, ...\n                 xm, xm, xm-2, xm+2, xm, xm, xm-2, xm+2];\n        ydata = [ym+2, ym-2, ym, ym, ym+2, ym-2, ym, ...\n                 ym, y0, y0, y0, y0, y1, y1, y1];\n      elseif (strncmp (fmt, \"box\", 3))\n        xdata = [x0+2, x1-2, x1-2, x0+2, x0+2];\n        ydata = [y0, y0, y1, y1, y0];\n      else\n        xdata = [x0, x1];\n        ydata = [ym, ym];\n      endif\n\n      set (hicon, \"markerxdata\", xm, \"markerydata\", ym, ...\n           \"xdata\", xdata, \"ydata\", ydata);\n\n    case \"__quiver__\"\n      ## Draw an arrow\n      x0 = xdata(1);\n      x1 = xdata(2);\n      y0 = mean (ydata);\n      xdata = [x0, x1, x1-2, x1, x1-2];\n      ydata = [y0, y0, y0+2, y0, y0-2];\n      set (hicon, \"markerxdata\", x0, \"markerydata\", y0, ...\n           \"xdata\", xdata, \"ydata\", ydata);\n    case \"scatter\"\n      set (hicon, \"xdata\", mean (xdata), \"ydata\", mean (ydata));\n    case \"__stem__\"\n      xdata(2) -= (get (get (hicon, \"peer_object\"), \"markersize\") / 2);\n      set (hicon, \"markerxdata\", xdata(2), \"markerydata\", mean (ydata), ...\n           \"xdata\", xdata, \"ydata\", [mean(ydata), mean(ydata)]);\n  endswitch\n\nendfunction\n\nfunction pos = boxposition (axpos, pba, pbam, dam)\n\n  pos = axpos;\n\n  if (strcmp (pbam, \"auto\") && strcmp (dam, \"auto\"))\n    return;\n  endif\n\n  pbratio = pba(1)/pba(2);\n  posratio = axpos(3)/axpos(4);\n\n  if (pbratio != posratio)\n    if (posratio < pbratio)\n      pos(4) = pos(3) / pbratio;\n      pos(2) += (axpos(4) - pos(4)) / 2;\n    else\n      pos(3) = pos(4) * pbratio;\n      pos(1) += (axpos(3) - pos(3)) / 2;\n    endif\n  endif\n\nendfunction\n\nfunction update_legend_position (hl, sz)\n\n  persistent hmargin = 6;\n  persistent vmargin = 6;\n\n  location = get (hl, \"location\");\n  outside = strcmp (location(end-3:end), \"side\");\n  if (outside)\n    location = location(1:end-7);\n  endif\n\n  if (strcmp (location, \"best\"))\n    orientation = get (hl, \"orientation\");\n    if (outside)\n      if (strcmp (orientation, \"vertical\"))\n        location = \"northeast\";\n      else\n        location = \"south\";\n      endif\n    else\n      ## FIXME: implement \"best\" inside properly\n      location = \"northeast\";\n    endif\n  endif\n\n  haxes = getappdata (hl, \"__axes_handle__\");\n  hax = haxes(end);\n  units = get (hax, \"units\");\n\n  unwind_protect\n    ## Restore the original looseinset first and set units to points.\n    li = getappdata (hl, \"__original_looseinset__\");\n    if (isempty (li))\n      li = get (hax, \"looseinset\");\n      setappdata (hl, \"__original_looseinset__\", li);\n      setappdata (hl, \"__original_units__\", units);\n    endif\n\n    if (strcmp (get (hl, \"visible\"), \"on\"))\n      set (hax, \"units\", getappdata (hl, \"__original_units__\"),\n                \"looseinset\", li,\n                \"units\", \"points\");\n    else\n      ## Return early for invible legends\n      set (hax, \"units\", getappdata (hl, \"__original_units__\"),\n                \"looseinset\", li,\n                \"units\", units);\n      return;\n    endif\n\n    [li, axpos, pbam, pba, dam] = get (hax, {\"looseinset\", \"position\", ...\n                                             \"plotboxaspectratiomode\", ...\n                                             \"plotboxaspectratio\", ...\n                                             \"dataaspectratiomode\"}){:};\n\n    axpos = boxposition (axpos, pba, pbam, dam);\n\n    lpos = [get(hl, \"position\")(1:2), sz];\n\n    if (! outside)\n\n      switch (location)\n        case \"southwest\"\n          lpos(1) = axpos(1) + hmargin;\n          lpos(2) = axpos(2) + vmargin;\n        case \"west\"\n          lpos(1) = axpos(1) + hmargin;\n          lpos(2) = axpos(2) + axpos(4)/2 - lpos(4)/2;\n        case \"northwest\"\n          lpos(1) = axpos(1) + hmargin;\n          lpos(2) = axpos(2) + axpos(4) - lpos(4) - vmargin;\n        case \"north\"\n          lpos(1) = axpos(1) + axpos(3)/2 - lpos(3)/2;\n          lpos(2) = axpos(2) + axpos(4) - lpos(4) - vmargin;\n        case \"northeast\"\n          lpos(1) = axpos(1) + axpos(3) - lpos(3) - hmargin;\n          lpos(2) = axpos(2) + axpos(4) - lpos(4) - vmargin;\n        case \"east\"\n          lpos(1) = axpos(1) + axpos(3) - lpos(3) - hmargin;\n          lpos(2) = axpos(2) + axpos(4)/2 - lpos(4)/2;\n        case \"southeast\"\n          lpos(1) = axpos(1) + axpos(3) - lpos(3) - hmargin;\n          lpos(2) = axpos(2) + vmargin;\n        case \"south\"\n          lpos(1) = axpos(1) + axpos(3)/2 - lpos(3)/2;\n          lpos(2) = axpos(2) + vmargin;\n      endswitch\n\n    else\n\n      ## FIXME: Is there a simpler way to know the size of the box\n      ##        enclosing labels than temporarily changing the\n      ##        plotboxaspectratiomode\n      if (strcmp (pbam, \"auto\"))\n        ti = get (haxes, \"tightinset\");\n      else\n        set (haxes, \"plotboxaspectratiomode\", \"auto\");\n        ti = get (haxes, \"tightinset\");\n        set (haxes, \"plotboxaspectratio\", pba);\n      endif\n\n      if (iscell (ti))\n        ti = max (cell2mat (ti));\n      endif\n\n      switch (location)\n        case \"southwest\"\n          dx = lpos(3) + hmargin + ti(1);\n          if (axpos(1) < (dx + hmargin))\n            li(1) = min (dx + hmargin, 0.95 * (axpos(1) + axpos(3)));\n            set (hax, \"looseinset\", li);\n            axpos = boxposition (get (hax, \"position\"), pba, pbam, dam);\n          endif\n          lpos(1) = axpos(1) - dx;\n          lpos(2) = axpos(2);\n        case \"west\"\n          dx = lpos(3) + hmargin + ti(1);\n          if (axpos(1) < (dx + hmargin))\n            li(1) = min (dx + hmargin, 0.95 * (axpos(1) + axpos(3)));\n            set (hax, \"looseinset\", li);\n            axpos = boxposition (get (hax, \"position\"), pba, pbam, dam);\n          endif\n          lpos(1) = axpos(1) - dx;\n          lpos(2) = axpos(2) + axpos(4)/2 - lpos(4)/2;\n        case \"northwest\"\n          dx = lpos(3) + hmargin + ti(1);\n          if (axpos(1) < (dx + hmargin))\n            li(1) = min (dx + hmargin, 0.95 * (axpos(1) + axpos(3)));\n            set (hax, \"looseinset\", li);\n            axpos = boxposition (get (hax, \"position\"), pba, pbam, dam);\n          endif\n          lpos(1) = axpos(1) - dx;\n          lpos(2) = axpos(2) + axpos(4) - lpos(4);\n        case \"north\"\n          dy = lpos(4) + vmargin + ti(4);\n          if (li(4) < (dy + vmargin))\n            li(4) = min (dy + vmargin, axpos(4));\n            set (hax, \"looseinset\", li);\n            axpos = boxposition (get (hax, \"position\"), pba, pbam, dam);\n          endif\n          lpos(1) = axpos(1) + axpos(3)/2 - lpos(3)/2;\n          lpos(2) = axpos(2) + axpos(4) + vmargin + ti(4);\n        case \"northeast\"\n          dx = lpos(3) + hmargin + ti(3);\n          if (li(3) < (dx + hmargin))\n            li(3) = min (dx + hmargin, axpos(3));\n            set (hax, \"looseinset\", li);\n            axpos = boxposition (get (hax, \"position\"), pba, pbam, dam);\n          endif\n          lpos(1) = axpos(1) + axpos(3) + hmargin + ti(3);\n          lpos(2) = axpos(2) + axpos(4) - lpos(4);\n        case \"east\"\n          dx = lpos(3) + hmargin + ti(3);\n          if (li(3) < (dx + hmargin))\n            li(3) = min (dx + hmargin, axpos(3));\n            set (hax, \"looseinset\", li);\n            axpos = boxposition (get (hax, \"position\"), pba, pbam, dam);\n          endif\n          lpos(1) = axpos(1) + axpos(3) + hmargin + ti(3);\n          lpos(2) = axpos(2) + axpos(4)/2 - lpos(4)/2;\n        case \"southeast\"\n          dx = lpos(3) + hmargin + ti(3);\n          if (li(3) < (dx + hmargin))\n            li(3) = min (dx + hmargin, axpos(3));\n            set (hax, \"looseinset\", li);\n            axpos = boxposition (get (hax, \"position\"), pba, pbam, dam);\n          endif\n          lpos(1) = axpos(1) + axpos(3) + hmargin + ti(3);\n          lpos(2) = axpos(2);\n        case \"south\"\n          dy = lpos(4) + vmargin + ti(2);\n          if (li(2) < (dy + vmargin))\n            li(2) = min (dy + vmargin, 0.95 * (axpos(2) + axpos(4)));\n            set (hax, \"looseinset\", li);\n            axpos = boxposition (get (hax, \"position\"), pba, pbam, dam);\n          endif\n          lpos(1) = axpos(1) + axpos(3)/2 - lpos(3)/2;\n          lpos(2) = axpos(2) - lpos(4) - vmargin - ti(2);\n      endswitch\n    endif\n\n    set (hl, \"xlim\", [0, sz(1)], \"ylim\", [0, sz(2)], ...\n             \"position\", lpos);\n\n    setappdata (hl, \"__peer_axes_position__\", axpos);\n\n  unwind_protect_cleanup\n    set (hax, \"units\", units);\n  end_unwind_protect\n\nendfunction\n\n\n%!demo\n%! clf;\n%! plot (rand (2));\n%! title (\"legend called with string inputs for labels\");\n%! h = legend (\"foo\", \"bar\");\n%! set (h, \"fontsize\", 20, \"location\", \"northeastoutside\");\n\n%!demo\n%! clf;\n%! plot (rand (2));\n%! title (\"legend called with cell array of strings\");\n%! h = legend ({\"cellfoo\", \"cellbar\"});\n%! set (h, \"fontsize\", 20, \"location\", \"northeast\");\n\n%!demo\n%! clf;\n%! plot (rand (3));\n%! title (\"legend () without inputs creates default labels\");\n%! h = legend ();\n\n%!demo\n%! clf;\n%! x = 0:1;\n%! hline = plot (x,x,\";I am Blue;\", x,2*x, x,3*x,\";I am Yellow;\");\n%! h = legend ();\n%! set (h, \"location\", \"northeastoutside\");\n%! ## Placing legend inside returns axes to original size\n%! set (h, \"location\", \"northeast\");\n%! title (\"Blue and Yellow keys, with Orange missing\");\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"incline is blue and decline is orange\");\n%! legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend hide\n%! legend show\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"Legend with keys in horizontal orientation\");\n%! legend ({\"I am blue\", \"I am orange\"}, ...\n%!         \"location\", \"east\", \"orientation\", \"horizontal\");\n%! legend boxoff\n%! legend boxon\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"Legend with box off\");\n%! legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend boxoff\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"Legend with text to the left of key\");\n%! legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend left\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title ({\"Use properties to place legend text to the left of key\", ...\n%!         \"Legend text color is magenta\"});\n%! h = legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend (\"right\");\n%! set (h, \"textposition\", \"left\");\n%! set (h, \"textcolor\", [1, 0, 1]);\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"Legend is hidden\");\n%! legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend hide\n\n%!demo\n%! clf;\n%! x = 0:1;\n%! plot (x,x,\";I am Blue;\", x,2*x,\";I am Orange;\", x,3*x,\";I am Yellow;\");\n%! title ({\"Labels are embedded in call to plot\", ...\n%!         \"Legend is hidden and then shown\"});\n%! legend boxon\n%! legend hide\n%! legend show\n\n%!demo\n%! clf;\n%! x = 0:1;\n%! plot (x,x,  x,2*x,  x,3*x);\n%! title (\"Labels with interpreted Greek text\");\n%! h = legend ('\\alpha', '\\beta=2\\alpha', '\\gamma=3\\alpha');\n%! set (h, \"interpreter\", \"tex\");\n\n%!demo\n%! clf;\n%! plot (rand (2));\n%! title (\"Labels with TeX interpreter turned off\");\n%! h = legend (\"Hello_World\", \"foo^bar\");\n%! set (h, \"interpreter\", \"none\");\n\n%!demo\n%! clf;\n%! labels = {};\n%! colororder = get (gca, \"colororder\");\n%! for i = 1:5\n%!   h = plot (1:100, i + rand (100,1)); hold on;\n%!   set (h, \"color\", colororder(i,:));\n%!   labels = {labels{:}, [\"Signal \", num2str(i)]};\n%! endfor\n%! hold off;\n%! title ({\"Signals with random offset and uniform noise\";\n%!         \"Legend shown below and outside of plot\"});\n%! xlabel (\"Sample Nr [k]\"); ylabel (\"Amplitude [V]\");\n%! legend (labels, \"location\", \"southoutside\");\n\n%!demo\n%! clf;\n%! x = linspace (0, 10);\n%! plot (x, x);\n%! hold on;\n%! stem (x, x.^2, \"g\");\n%! title (\"First created object gets first label\");\n%! legend (\"linear\");\n%! hold off;\n\n%!demo\n%! clf;\n%! x = linspace (0, 10);\n%! plot (x, x, x, x.^2);\n%! title (\"First created object gets first label\");\n%! legend (\"linear\");\n\n%!demo\n%! clf;\n%! x = linspace (0, 10);\n%! plot (x, x, x, x.^2);\n%! title (\"Labels are applied in order of object creation\");\n%! legend (\"linear\", \"quadratic\");\n\n%!demo\n%! clf;\n%! subplot (2,1,1);\n%! rand_2x3_data1 = [0.341447, 0.171220, 0.284370; 0.039773, 0.731725, 0.779382];\n%! bar (rand_2x3_data1);\n%! ylim ([0, 1.0]);\n%! title (\"legend() works for bar graphs (hggroups)\");\n%! legend ({\"1st Bar\", \"2nd Bar\", \"3rd Bar\"}, \"location\", \"northwest\");\n%! subplot (2,1,2);\n%! x = linspace (0, 10, 20);\n%! stem (x, 0.5+x.*rand (size (x))/max (x), \"markeredgecolor\", [0, 0.7, 0]);\n%! hold on;\n%! stem (x+10/(2*20), x.*(1.0+rand (size (x)))/max (x));\n%! xlim ([0, 10+10/(2*20)]);\n%! title (\"legend() works for stem plots (hggroups)\");\n%! legend ({\"Multicolor\", \"Unicolor\"}, \"location\", \"northwest\");\n\n%!demo\n%! clf;\n%! colormap (cool (64));\n%! surf (peaks ());\n%! legend (\"peaks()\");\n%! title (\"legend() works for surface objects too\");\n\n%!demo\n%! clf;\n%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);\n%! val = (x.^2 + y.^2 + z.^2);\n%!\n%! h_axes = axes ();\n%! view (3);\n%! fv = isosurface (x, y, z, val, .039, z);\n%! h_patch = patch (fv, \"FaceColor\", \"flat\", \"EdgeColor\", \"none\");\n%! view (3);\n%! axis tight\n%! axis equal\n%! legend ({\"colored patch\"});\n\n%!demo\n%! clf reset;  # needed to undo colormap assignment in previous demo\n%! rand_2x3_data2 = [0.44804, 0.84368, 0.23012; 0.72311, 0.58335, 0.90531];\n%! bar (rand_2x3_data2);\n%! ylim ([0, 1.2]);\n%! title ('\"left\" option places colors to the left of text label');\n%! legend (\"1st Bar\", \"2nd Bar\", \"3rd Bar\");\n%! legend left;\n\n%!demo\n%! clf;\n%! x = 0:0.1:7;\n%! h = plot (x,sin (x), x,cos (x), x,sin (x.^2/10), x,cos (x.^2/10));\n%! title (\"Only the sin() objects have keylabels\");\n%! legend (h([1, 3]), {\"sin (x)\", \"sin (x^2/10)\"}, \"location\", \"southwest\");\n\n%!demo\n%! clf;\n%! x = 0:0.1:10;\n%! plot (x, sin (x), \";sin (x);\");\n%! hold on;\n%! plot (x, cos (x), \";cos (x);\");\n%! hold off;\n%! title (\"legend constructed from multiple plot calls\");\n\n%!demo\n%! clf;\n%! x = 0:0.1:10;\n%! plot (x, sin (x), \";sin (x);\");\n%! hold on;\n%! plot (x, cos (x), \";cos (x);\");\n%! hold off;\n%! title (\"Specified label text overrides previous labels\");\n%! legend ({\"Sine\", \"Cosine\"}, \"location\", \"northeastoutside\");\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! plot (x, rand (11));\n%! axis ([0, 10, 0, 1]);\n%! xlabel (\"Indices\");\n%! ylabel (\"Random Values\");\n%! title ('Legend \"off\" deletes the legend');\n%! legend (cellstr (num2str ((0:10)')), \"location\", \"northeastoutside\");\n%! pause (1);\n%! legend off;\n\n%!demo\n%! clf;\n%! x = (1:5)';\n%! subplot (2,2,1);\n%!  plot (x, rand (numel (x)));\n%!  legend (cellstr (num2str (x)), \"location\", \"northwestoutside\");\n%! subplot (2,2,2);\n%!  plot (x, rand (numel (x)));\n%!  legend (cellstr (num2str (x)), \"location\", \"northeastoutside\");\n%! subplot (2,2,3);\n%!  plot (x, rand (numel (x)));\n%!  legend (cellstr (num2str (x)), \"location\", \"southwestoutside\");\n%! subplot (2,2,4);\n%!  plot (x, rand (numel (x)));\n%!  legend (cellstr (num2str (x)), \"location\", \"southeastoutside\");\n%! ## Legend works on a per axes basis for each subplot\n\n%!demo\n%! clf;\n%! plot (rand (2));\n%! title (\"legend() will warn if extra labels are specified\");\n%! legend (\"Hello\", \"World\", \"foo\", \"bar\");\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! y1 = rand (size (x));\n%! y2 = rand (size (x));\n%! [ax, h1, h2] = plotyy (x, y1, x, y2);\n%! title ({\"plotyy legend test #1\", \"Blue label to left axis, Orange label to right axis\"});\n%! drawnow ();\n%! legend (\"Blue\", \"Orange\", \"location\", \"south\");\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! y1 = rand (size (x));\n%! y2 = rand (size (x));\n%! [ax, h1, h2] = plotyy (x, y1, x, y2);\n%! ylabel (ax(1), {\"Blue\", \"Y\", \"Axis\"});\n%! title ('plotyy legend test #2: \"westoutside\" adjusts to ylabel');\n%! drawnow ();\n%! legend ([h1, h2], {\"Blue\", \"Orange\"}, \"location\", \"westoutside\");\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! y1 = rand (size (x));\n%! y2 = rand (size (x));\n%! [ax, h1, h2] = plotyy (x, y1, x, y2);\n%! ylabel (ax(2), {\"Orange\", \"Y\", \"Axis\"});\n%! title ('plotyy legend test #3: \"eastoutside\" adjusts to ylabel');\n%! drawnow ();\n%! legend ([h1, h2], {\"Blue\", \"Orange\"}, \"location\", \"eastoutside\");\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10);\n%! title (\"a very long label can sometimes cause problems\");\n%! legend (\"hello very big world\", \"location\", \"northeastoutside\");\n\n%!demo  # bug 36408\n%! clf;\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  xlabel xlabel;\n%!  ylabel ylabel;\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northeastoutside\");\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  xlabel xlabel;\n%!  ylabel ylabel;\n%!  legend ({\"1234567890\"}, \"location\", \"eastoutside\");\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  xlabel xlabel;\n%!  ylabel ylabel;\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southeastoutside\");\n\n%!demo  # bug 36408\n%! clf;\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northwestoutside\");\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  legend ({\"1234567890\"}, \"location\", \"westoutside\");\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southwestoutside\");\n\n%!demo  # bug 36408\n%! clf;\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northeastoutside\");\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"1234567890\"}, \"location\", \"eastoutside\");\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southeastoutside\");\n\n%!demo  # bug 36408\n%! clf;\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northwestoutside\");\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"1234567890\"}, \"location\", \"westoutside\");\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southwestoutside\");\n\n%!demo  # bug 36408;\n%! clf;\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  set (gca (), \"xaxislocation\", \"top\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northwestoutside\");\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  set (gca (), \"xaxislocation\", \"top\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"1234567890\"}, \"location\", \"westoutside\");\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  set (gca (), \"xaxislocation\", \"top\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southwestoutside\");\n\n%!demo  # bug 39697\n%! clf;\n%! plot (1:10);\n%! legend (\"Legend Text\");\n%! title ({\"Multi-line\", \"titles\", \"are *not* a\", \"problem\"});\n\n%!demo  # bug 61814\n%! clf;\n%! data = [ [1:5]' , [5:-1:1]', 2.5*ones(5,1) ];\n%! hp = plot (data);\n%! set (hp(1), \"marker\", 'x', \"markersize\", 15);\n%! set (hp(2), \"marker\", 'o', \"markersize\", 30);\n%! set (hp(3), \"marker\", '.', \"markersize\", 30);\n%! legend ({\"data1\", \"data2\", \"data3\"}, \"location\", \"north\");\n%! set (hp(2), \"marker\", '.');\n%! set (hp(3), \"marker\", 'o');\n%! title (\"Marker sizes do not overflow legend box\");\n\n## Test input validation\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   try\n%!     legend ();\n%!   catch\n%!     [~, id] = lasterr ();\n%!     assert (id, \"Octave:legend:no-object\");\n%!   end_try_catch\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   axes ();\n%!   try\n%!     legend ();\n%!   catch\n%!     [~, id] = lasterr ();\n%!     assert (id, \"Octave:legend:no-object\");\n%!   end_try_catch\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   axes ();\n%!   light ();\n%!   try\n%!     legend ();\n%!   catch\n%!     [~, id] = lasterr ();\n%!     assert (id, \"Octave:legend:no-object\");\n%!   end_try_catch\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   axes ();\n%!   hli = light ();\n%!   try\n%!     legend (hli);\n%!   catch\n%!     [~, id] = lasterr ();\n%!     assert (id, \"Octave:legend:bad-object\");\n%!   end_try_catch\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   axes ();\n%!   hplot = plot (rand (3));\n%!   try\n%!     legend (hplot, struct);\n%!   catch\n%!     [~, id] = lasterr ();\n%!     assert (id, \"Octave:invalid-fun-call\");\n%!   end_try_catch\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   axes ();\n%!   hplot = plot (rand (3));\n%!   try\n%!     legend (\"a\", \"b\", \"c\", hplot);\n%!   catch\n%!     [~, id] = lasterr ();\n%!     assert (id, \"Octave:invalid-fun-call\");\n%!   end_try_catch\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test bugs in previous implementation\n%!testif ; any (strcmp (graphics_toolkit (), {\"fltk\", \"qt\"})) <*39697>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   axes (\"units\", \"normalized\");\n%!   plot (1:10);\n%!   hl = legend (\"Legend Text\", \"units\", \"normalized\");\n%!   title ({'Multi-line', 'titles', 'are a', 'problem'});\n%!   pos = get (gca, \"position\");\n%!   axtop = sum (pos(2:2:4));\n%!   pos = get (hl, \"position\");\n%!   legtop = sum (pos(2:2:4));\n%!   assert (legtop < axtop);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!testif HAVE_FREETYPE <*40333>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"units\", \"normalized\", \"fontsize\", 10);\n%!   hold on;  # preserve properties of hax in call to plot()\n%!   plot (hax, 1:10);\n%!   hl = legend (\"Legend Text\", \"units\", \"normalized\");\n%!   pos = get (gca, \"position\");\n%!   set (hf, \"position\", [0, 0, 200, 200]);\n%!   set (hl, \"fontsize\", 20);\n%!   assert (get (gca, \"position\"), pos, 2*eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Verify alpha parameter inherited by legend patch objects.\n## Only facealpha currently implemented.\n%!testif ; any (strcmp (graphics_toolkit (), {\"fltk\", \"qt\"})) <*66314>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hp = patch (hax);\n%!   set (hp, \"facealpha\", 0.5);\n%!   hl = legend (hax);\n%!   assert (get (findobj (hl, \"type\", \"patch\"), \"facealpha\"), 0.5);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n"
  },
  {
    "path": "scripts/plot/appearance/lighting.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} lighting (@var{type})\n## @deftypefnx {} {} lighting (@var{hax}, @var{type})\n## Set the lighting of patch or surface graphic objects.\n##\n## Valid arguments for @var{type} are\n##\n## @table @asis\n## @item @qcode{\"flat\"}\n## Draw objects with faceted lighting effects.\n##\n## @item @qcode{\"gouraud\"}\n## Draw objects with linear interpolation of the lighting effects between the\n## vertices.\n##\n## @item @qcode{\"none\"}\n## Draw objects without light and shadow effects.\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then change the lighting\n## effects of objects in this axes, rather than the current axes returned by\n## @code{gca}.\n##\n## The lighting effects are only visible if at least one light object is\n## present and visible in the same axes.\n##\n## @seealso{light, fill, mesh, patch, pcolor, surf, surface, shading}\n## @end deftypefn\n\nfunction lighting (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"lighting\", varargin{:});\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  mode = varargin{1};\n  if (! ischar (mode))\n    error (\"lighting: MODE must be a string\");\n  elseif (! any (strcmpi (mode, {\"flat\", \"gouraud\", \"none\"})))\n    error ('lighting: Invalid MODE \"%s\"', mode);\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  ## Find all patch and surface objects that are descendants of hax\n  ## and which are not part of a contour plot hggroup.\n  hlist = [];\n  kids = get (hax, \"children\");\n  while (! isempty (kids))\n    types = get (kids, \"type\");\n    hlist = [hlist; kids(strcmp(types, \"patch\"))];\n    hlist = [hlist; kids(strcmp(types, \"surface\"))];\n    parents = kids(strcmp (types, \"axes\"));\n    hglist = kids(strcmp (types, \"hggroup\"));\n\n    kids = get (parents, \"children\");\n    for i = 1 : numel (hglist)\n      props = get (hglist(i));\n      if (! isfield (props, \"levelstep\"))\n        kids = [kids; get(hglist(i), \"children\")];\n      endif\n    endfor\n\n  endwhile\n\n  ## FIXME: This is the old, simple code.\n  ##        Unfortunately, it also lights contour plots which is not desirable.\n  ## hp = findobj (hax, \"type\", \"patch\");\n  ## hs = findobj (hax, \"type\", \"surface\");\n  ## hlist = [hp(:); hs(:)];\n\n  if (isempty (hlist))\n    return;\n  endif\n\n  ## Change \"EdgeLighting\" for meshes instead of \"FaceLighting\"\n  fc = get (hlist, \"facecolor\");\n  is_mesh = strcmp (fc, \"none\");\n  if (! iscell (fc))\n    fc = {fc};\n  endif\n  bc = get (hax, \"color\");\n  if (strcmp (bc, \"none\"))\n    if (isprop (get (hax, \"parent\"), \"color\"))\n      bc = get (get (hax, \"parent\"), \"color\");\n    endif\n    if (isempty (bc) || strcmp (bc, \"none\"))\n      bc = [1 1 1];\n    endif\n  endif\n  is_mesh = is_mesh | cellfun (@(x) isequal (x, bc), fc);\n\n  set (hlist(! is_mesh), \"facelighting\", mode, \"edgelighting\", \"none\");\n  set (hlist(is_mesh), \"edgelighting\", mode, \"facelighting\", \"none\");\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! sombrero ();\n%! shading flat\n%! lighting flat\n%! light ();\n%! title (\"shading flat - lighting flat\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! sombrero ();\n%! shading interp\n%! lighting gouraud\n%! light ();\n%! title (\"shading interp - lighting gouraud\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! pcolor (peaks ());\n%! shading flat\n%! lighting flat\n%! light ();\n%! view (3)\n%! title (\"shading flat - lighting flat\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! pcolor (peaks ());\n%! shading interp\n%! lighting gouraud\n%! light ();\n%! view (3)\n%! title (\"shading interp - lighting gouraud\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! mesh (sombrero ());\n%! shading flat\n%! lighting flat\n%! light ();\n%! title (\"shading flat - lighting flat\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! mesh (sombrero ());\n%! shading interp\n%! lighting gouraud\n%! light ();\n%! title (\"shading interp - lighting gouraud\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ha = axes ();\n%!   hm = mesh (sombrero ());\n%!   hp = patch ();\n%!   hs = surface ();\n%!   lighting flat\n%!   assert (get (hp, \"facelighting\"), \"flat\");\n%!   assert (get (hs, \"facelighting\"), \"flat\");\n%!   assert (get (hp, \"edgelighting\"), \"none\");\n%!   assert (get (hs, \"edgelighting\"), \"none\");\n%!   assert (get (hm, \"edgelighting\"), \"flat\");\n%!   lighting gouraud\n%!   assert (get (hp, \"facelighting\"), \"gouraud\");\n%!   assert (get (hs, \"facelighting\"), \"gouraud\");\n%!   assert (get (hp, \"edgelighting\"), \"none\");\n%!   assert (get (hs, \"edgelighting\"), \"none\");\n%!   assert (get (hm, \"edgelighting\"), \"gouraud\");\n%!   lighting none\n%!   assert (get (hp, \"facelighting\"), \"none\");\n%!   assert (get (hs, \"facelighting\"), \"none\");\n%!   assert (get (hp, \"edgelighting\"), \"none\");\n%!   assert (get (hs, \"edgelighting\"), \"none\");\n%!   assert (get (hm, \"edgelighting\"), \"none\");\n%!   lighting (ha, \"flat\")\n%!   assert (get (hp, \"facelighting\"), \"flat\");\n%!   assert (get (hs, \"facelighting\"), \"flat\");\n%!   assert (get (hp, \"edgelighting\"), \"none\");\n%!   assert (get (hs, \"edgelighting\"), \"none\");\n%!   assert (get (hm, \"edgelighting\"), \"flat\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test on axes which has no patch or mesh objects\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   lighting flat\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <Invalid call> lighting ()\n%!error lighting (1, 2, \"flat\")\n%!error <MODE must be a string> lighting (-1)\n%!error <MODE must be a string> lighting ({})\n%!error <Invalid MODE \"foo\"> lighting foo\n%!error <Invalid call to lighting> lighting (-1, \"flat\")\n"
  },
  {
    "path": "scripts/plot/appearance/material.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} material shiny\n## @deftypefnx {} {} material dull\n## @deftypefnx {} {} material metal\n## @deftypefnx {} {} material default\n## @deftypefnx {} {} material ([@var{as}, @var{ds}, @var{ss}])\n## @deftypefnx {} {} material ([@var{as}, @var{ds}, @var{ss}, @var{se}])\n## @deftypefnx {} {} material ([@var{as}, @var{ds}, @var{ss}, @var{se}, @var{scr}])\n## @deftypefnx {} {} material (@var{hlist}, @dots{})\n## @deftypefnx {} {@var{mtypes} =} material ()\n## @deftypefnx {} {@var{refl_props} =} material (@var{mtype_string})\n## Set reflectance properties for the lighting of surfaces and patches.\n##\n## This function changes the ambient, diffuse, and specular strengths, as well\n## as the specular exponent and specular color reflectance, of all\n## @code{patch} and @code{surface} objects in the current axes.  This can be\n## used to simulate, to some extent, the reflectance properties of certain\n## materials when used with @code{light}.\n##\n## When called with a string, the aforementioned properties are set\n## according to the values in the following table:\n##\n## @multitable @columnfractions .16 .16 .16 .16 .16 .16\n## @headitem @var{mtype} @tab ambient- strength @tab diffuse-\n## strength @tab specular- strength @tab specular- exponent @tab specular-\n## color- reflectance\n## @item @qcode{\"shiny\"} @tab 0.3 @tab 0.6 @tab 0.9 @tab 20 @tab 1.0\n## @item @qcode{\"dull\"} @tab 0.3 @tab 0.8 @tab 0.0 @tab 10 @tab 1.0\n## @item @qcode{\"metal\"} @tab 0.3 @tab 0.3 @tab 1.0 @tab 25 @tab 0.5\n## @item @qcode{\"default\"} @tab @qcode{\"default\"} @tab @qcode{\"default\"} @tab @qcode{\"default\"}\n## @tab @qcode{\"default\"} @tab @qcode{\"default\"}\n## @end multitable\n##\n## When called with a vector of three elements, the ambient, diffuse, and\n## specular strengths of all @code{patch} and @code{surface} objects in the\n## current axes are updated.  An optional fourth vector element updates the\n## specular exponent, and an optional fifth vector element updates the\n## specular color reflectance.\n##\n## A list of graphic handles can also be passed as the first argument.  In\n## this case, the properties of these handles and all child @code{patch} and\n## @code{surface} objects will be updated.\n##\n## Additionally, @code{material} can be called with a single output argument.\n## If called without input arguments, a column cell vector @var{mtypes} with\n## the strings for all available materials is returned.  If the one input\n## argument @var{mtype_string} is the name of a material, a 1x5 cell vector\n## @var{refl_props} with the reflectance properties of that material is\n## returned.  In both cases, no graphic properties are changed.\n##\n## @seealso{light, fill, mesh, patch, pcolor, surf, surface}\n## @end deftypefn\n\nfunction retval = material (varargin)\n\n  if (! ((nargout == 0 && (nargin == 1 || nargin == 2))\n         || (nargout == 1 && (nargin == 0 || nargin == 1))))\n    print_usage ();\n  endif\n\n  ## resolve input\n  hax = [];\n  if (nargout == 0)\n    ## Check whether first argument is list of graphics handles.\n    if (all (ishghandle (varargin{1})))\n      hax = varargin{1};\n      varargin(1) = [];\n    endif\n\n    ## There must be one (additional) argument.\n    if (numel (varargin) != 1)\n      if (nargin == 2)\n        error ([\"material: When called with two arguments, the first argument \" ...\n                \"must be a list of handles to graphics objects.\"]);\n      else\n        print_usage ();\n      endif\n    endif\n  elseif (nargin == 0)\n    ## Return name of materials.\n    retval = {\"shiny\"; \"dull\"; \"metal\"; \"default\"};\n    return;\n  endif\n\n  mtype = varargin{1};\n\n  se = [];\n  scr = [];\n\n  ## check material type\n  if (ischar (mtype))\n    switch (lower (mtype))\n      case \"shiny\"\n        as = 0.3;\n        ds = 0.6;\n        ss = 0.9;\n        se = 20;\n        scr = 1.0;\n\n      case \"dull\"\n        as = 0.3;\n        ds = 0.8;\n        ss = 0.0;\n        se = 10;\n        scr = 1.0;\n\n      case \"metal\"\n        as = 0.3;\n        ds = 0.3;\n        ss = 1.0;\n        se = 25;\n        scr = .5;\n\n      case \"default\"\n        as = \"default\";\n        ds = \"default\";\n        ss = \"default\";\n        se = \"default\";\n        scr = \"default\";\n\n      otherwise\n        error (\"material: unknown material type '%s'\", mtype);\n\n    endswitch\n\n    if (nargout == 1)\n      ## Return 1x5 cell vector with reflectance properties.\n      retval = {as, ds, ss, se, scr};\n      return;\n    endif\n\n  elseif (nargout == 1)\n    ## If we reach here with one output argument, the input was wrong.\n    print_usage ();\n\n  elseif (isvector (mtype))\n    num_mtype = numel (mtype);\n    if (num_mtype < 3 || num_mtype > 5)\n      error (\"material: incorrect number of elements in material vector\");\n    endif\n    as = mtype(1);\n    ds = mtype(2);\n    ss = mtype(3);\n    if (num_mtype >= 4)\n      se = mtype(4);\n      if (num_mtype == 5)\n        scr = mtype(5);\n      endif\n    endif\n\n  else\n    error (\"material: MTYPE must be a named material or a vector\");\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n  ## find all patch and surface objects in current axes\n  hps = findobj (hax, \"Type\", \"patch\", \"-or\", \"Type\", \"surface\");\n\n  ## set properties\n  set (hps,\n       \"ambientstrength\", as, \"diffusestrength\", ds, \"specularstrength\", ss);\n\n  if (! isempty (se))\n    set (hps, \"specularexponent\", se);\n    if (! isempty (scr))\n      set (hps, \"specularcolorreflectance\", scr);\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! ## patch\n%! [x,y,z] = meshgrid (-2:0.2:2, -2:0.2:2, -2:0.2:2);\n%! val = x.^2 + y.^2 + z.^2;\n%! fv1 = isosurface (x, y, z, val, 1);\n%! h_patch = patch (fv1, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%! isonormals (x, y, z, val, h_patch);\n%! axis equal;  axis tight;\n%! view (3);\n%! box off;\n%! drawnow ();\n%! light ();\n%! material ([0 0.5 1 10 .5]);\n%! title (\"material() with numeric input\");\n\n%!demo\n%! clf;\n%! ## surface\n%! hax = axes ();\n%! surf (hax, peaks, \"LineStyle\", \"none\", \"FaceLighting\", \"Gouraud\");\n%! view (3);\n%! light ();\n%! material metal;\n%! title (\"material metal\");\n\n%!test\n%! hf = figure (\"Visible\", \"off\");\n%! unwind_protect\n%!   hp = patch ();\n%!   hs = surface ();\n%!   material dull\n%!   assert (get (hp, \"ambientstrength\"), 0.3);\n%!   assert (get (hs, \"ambientstrength\"), 0.3);\n%!   assert (get (hp, \"diffusestrength\"), 0.8);\n%!   assert (get (hs, \"diffusestrength\"), 0.8);\n%!   assert (get (hp, \"specularstrength\"), 0.0);\n%!   assert (get (hs, \"specularstrength\"), 0.0);\n%!   assert (get (hp, \"specularexponent\"), 10);\n%!   assert (get (hs, \"specularexponent\"), 10);\n%!   assert (get (hp, \"specularcolorreflectance\"), 1.0);\n%!   assert (get (hs, \"specularcolorreflectance\"), 1.0);\n%!   material default\n%!   assert (get (hp, \"ambientstrength\"),\n%!           get (0, \"defaultpatchambientstrength\"));\n%!   assert (get (hs, \"ambientstrength\"),\n%!           get (0, \"defaultsurfaceambientstrength\"));\n%!   assert (get (hp, \"diffusestrength\"),\n%!           get (0, \"defaultpatchdiffusestrength\"));\n%!   assert (get (hs, \"diffusestrength\"),\n%!           get (0, \"defaultsurfacediffusestrength\"));\n%!   assert (get (hp, \"specularstrength\"),\n%!           get (0, \"defaultpatchspecularstrength\"));\n%!   assert (get (hs, \"specularstrength\"),\n%!           get (0, \"defaultsurfacespecularstrength\"));\n%!   assert (get (hp, \"specularexponent\"),\n%!           get (0, \"defaultpatchspecularexponent\"));\n%!   assert (get (hs, \"specularexponent\"),\n%!           get (0, \"defaultsurfacespecularexponent\"));\n%!   assert (get (hp, \"specularcolorreflectance\"),\n%!           get (0, \"defaultpatchspecularcolorreflectance\"));\n%!   assert (get (hs, \"specularcolorreflectance\"),\n%!           get (0, \"defaultsurfacespecularcolorreflectance\"));\n%!   material ([0.5 0.6 0.7 20 0.8])\n%!   assert (get (hp, \"ambientstrength\"), 0.5);\n%!   assert (get (hs, \"ambientstrength\"), 0.5);\n%!   assert (get (hp, \"diffusestrength\"), 0.6);\n%!   assert (get (hs, \"diffusestrength\"), 0.6);\n%!   assert (get (hp, \"specularstrength\"), 0.7);\n%!   assert (get (hs, \"specularstrength\"), 0.7);\n%!   assert (get (hp, \"specularexponent\"), 20);\n%!   assert (get (hs, \"specularexponent\"), 20);\n%!   assert (get (hp, \"specularcolorreflectance\"), 0.8);\n%!   assert (get (hs, \"specularcolorreflectance\"), 0.8);\n%!   material (hp, \"shiny\")\n%!   assert (get (hp, \"ambientstrength\"), 0.3);\n%!   assert (get (hs, \"ambientstrength\"), 0.5);\n%!   assert (get (hp, \"diffusestrength\"), 0.6);\n%!   assert (get (hs, \"diffusestrength\"), 0.6);\n%!   assert (get (hp, \"specularstrength\"), 0.9);\n%!   assert (get (hs, \"specularstrength\"), 0.7);\n%!   assert (get (hp, \"specularexponent\"), 20);\n%!   assert (get (hs, \"specularexponent\"), 20);\n%!   assert (get (hp, \"specularcolorreflectance\"), 1.0);\n%!   assert (get (hs, \"specularcolorreflectance\"), 0.8);\n%!   material (hf, \"metal\")\n%!   assert (get (hp, \"ambientstrength\"), 0.3);\n%!   assert (get (hs, \"ambientstrength\"), 0.3);\n%!   assert (get (hp, \"diffusestrength\"), 0.3);\n%!   assert (get (hs, \"diffusestrength\"), 0.3);\n%!   assert (get (hp, \"specularstrength\"), 1.0);\n%!   assert (get (hs, \"specularstrength\"), 1.0);\n%!   assert (get (hp, \"specularexponent\"), 25);\n%!   assert (get (hs, \"specularexponent\"), 25);\n%!   assert (get (hp, \"specularcolorreflectance\"), 0.5);\n%!   assert (get (hs, \"specularcolorreflectance\"), 0.5);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! mtypes = material ();\n%! assert (iscell (mtypes));\n%! assert (columns (mtypes), 1);\n%! assert (all (cellfun ('ischar', mtypes)));\n\n%!test\n%! refl_props = material (\"metal\");\n%! assert (refl_props, {0.3, 0.3, 1, 25, 0.5});\n\n## Test input validation\n%!error <Invalid call to material> material ()\n%!error <Invalid call to material> material (-1, 2, 3)\n%!error <Invalid call to material> a = material (-1)\n%!error <Invalid call to material> a = material (-1, 2)\n%!error <Invalid call to material> a = material ({})\n%!error <Invalid call to material> a = material ([.3 .4 .5])\n%!error <called with too many outputs> [a, b] = material ()\n%!error <first argument must be a list of handles> material (-1, \"metal\")\n%!error <unknown material type 'foo'> material foo\n%!error <incorrect number of elements in material vector> material (-1)\n%!error <incorrect number of elements in material vector> material ([1 2 3 4 5 6])\n%!error <MTYPE must be a named material or a vector> material ({})\n\n%!error <Invalid call to material.>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   material (hf);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__axis_label__.m \\\n  %reldir%/private/__axis_limits__.m \\\n  %reldir%/private/__gnuplot_legend__.m \\\n  %reldir%/private/__tickangle__.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/__clabel__.m \\\n  %reldir%/__getlegenddata__.m \\\n  %reldir%/__rotate_around_axis__.m \\\n  %reldir%/annotation.m \\\n  %reldir%/axis.m \\\n  %reldir%/box.m \\\n  %reldir%/camlookat.m \\\n  %reldir%/camorbit.m \\\n  %reldir%/campos.m \\\n  %reldir%/camroll.m \\\n  %reldir%/camtarget.m \\\n  %reldir%/camup.m \\\n  %reldir%/camva.m \\\n  %reldir%/camzoom.m \\\n  %reldir%/clabel.m \\\n  %reldir%/clim.m \\\n  %reldir%/daspect.m \\\n  %reldir%/datetick.m \\\n  %reldir%/diffuse.m \\\n  %reldir%/grid.m \\\n  %reldir%/gtext.m \\\n  %reldir%/hidden.m \\\n  %reldir%/legend.m \\\n  %reldir%/lighting.m \\\n  %reldir%/material.m \\\n  %reldir%/orient.m \\\n  %reldir%/pbaspect.m \\\n  %reldir%/rticks.m \\\n  %reldir%/rticklabels.m \\\n  %reldir%/shading.m \\\n  %reldir%/specular.m \\\n  %reldir%/text.m \\\n  %reldir%/thetaticks.m \\\n  %reldir%/thetaticklabels.m \\\n  %reldir%/title.m \\\n  %reldir%/view.m \\\n  %reldir%/whitebg.m \\\n  %reldir%/xlabel.m \\\n  %reldir%/xlim.m \\\n  %reldir%/xtickangle.m \\\n  %reldir%/xticks.m \\\n  %reldir%/xticklabels.m \\\n  %reldir%/ylabel.m \\\n  %reldir%/ylim.m \\\n  %reldir%/yticks.m \\\n  %reldir%/ytickangle.m \\\n  %reldir%/yticklabels.m \\\n  %reldir%/zlabel.m \\\n  %reldir%/zlim.m \\\n  %reldir%/zticks.m \\\n  %reldir%/ztickangle.m \\\n  %reldir%/zticklabels.m\n\n%canon_reldir%dir = $(fcnfiledir)/plot/appearance\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/plot/appearance/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/plot/appearance/orient.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} orient (@var{orientation})\n## @deftypefnx {} {} orient (@var{hfig}, @var{orientation})\n## @deftypefnx {} {@var{orientation} =} orient ()\n## @deftypefnx {} {@var{orientation} =} orient (@var{hfig})\n## Query or set the print orientation for figure @var{hfig}.\n##\n## Valid values for @var{orientation} are @qcode{\"portrait\"},\n## @qcode{\"landscape\"}, and @qcode{\"tall\"}.\n##\n## The @qcode{\"landscape\"} option changes the orientation so the plot width\n## is larger than the plot height.  The @qcode{\"paperposition\"} is also\n## modified so that the plot fills the page, while leaving a 0.25 inch border.\n##\n## The @qcode{\"tall\"} option sets the orientation to @qcode{\"portrait\"} and\n## fills the page with the plot, while leaving a 0.25 inch border.\n##\n## The @qcode{\"portrait\"} option (default) changes the orientation so the plot\n## height is larger than the plot width.  It also restores the default\n## @qcode{\"paperposition\"} property.\n##\n## When called with no arguments, return the current print orientation.\n##\n## If the argument @var{hfig} is omitted, then operate on the current figure\n## returned by @code{gcf}.\n## @seealso{print, saveas}\n## @end deftypefn\n\nfunction orientation = orient (hfig, paporient)\n\n  if (nargin == 0)\n    cf = gcf ();\n  elseif (nargin == 1)\n    if (isscalar (hfig) && isfigure (hfig))\n      cf = hfig;\n    elseif (ischar (hfig))\n      cf = gcf ();\n      paporient = hfig;\n    else\n      print_usage ();\n    endif\n  else  # nargin == 2\n    if (! (isscalar (hfig) && isfigure (hfig)))\n      print_usage ();\n    elseif (! ischar (paporient))\n      print_usage ();\n    endif\n  endif\n      \n  paperunits = get (cf, \"paperunits\");\n  unwind_protect\n    set (cf, \"paperunits\", \"inches\");  # All Matlab calculations assume inches.\n\n    if (nargin == 0)\n      orientation = get (cf, \"paperorientation\");\n      if (strcmp (orientation, \"portrait\"))\n        papersize = get (cf, \"papersize\");\n        paperposition = get (cf, \"paperposition\");\n        if (paperposition == [0.25 0.25 (papersize - 0.5)])\n          orientation = \"tall\";\n        endif\n      endif\n    else\n      if (any (strcmpi (paporient, {\"landscape\", \"portrait\"})))\n        if (! strcmpi (get (cf, \"paperorientation\"), paporient))\n          ## FIXME: with the proper listeners in place there won't be a need to\n          ##        set the papersize and paperposition here.\n          papersize = get (cf, \"papersize\");\n          paperposition = get (cf, \"paperposition\");\n          set (cf, \"paperorientation\", paporient,\n                   \"papersize\", papersize([2, 1]),\n                   \"paperposition\", paperposition([2, 1, 4, 3]));\n        endif\n        if (strcmpi (paporient, \"portrait\"))\n          ## portrait restores the default\n          ## FIXME: Should use \"default\" here, but Octave complains\n          ##        that \"paperposition\" is not a default property.\n          set (cf, \"paperposition\", \"factory\");\n        else\n          ## landscape also sets the plot to occupy the entire page\n          papersize = get (cf, \"papersize\");\n          set (cf, \"paperposition\", [0.25, 0.25, (papersize - 0.5)]);\n        endif\n      elseif (strcmpi (paporient, \"tall\"))\n        orient (\"portrait\");\n        papersize = get (cf, \"papersize\");\n        set (cf, \"paperposition\", [0.25, 0.25, (papersize - 0.5)]);\n      else\n        error (\"orient: unknown ORIENTATION '%s'\", paporient);\n      endif\n    endif\n\n  unwind_protect_cleanup\n    set (cf, \"paperunits\", paperunits);\n  end_unwind_protect\n\nendfunction\n\n\n%!test\n%! papersize = [8.5, 11];\n%! paperposition = [1.342185258002766, 3.319138943502075, 5.815629483994468, 4.361722112995850];\n%! fullpaperposition = [0.25, 0.25, (papersize-0.5)];\n%! hfig = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (hfig, \"paperunits\", \"inches\");\n%!   set (hfig, \"paperorientation\", \"portrait\");\n%!   set (hfig, \"papersize\", papersize);\n%!   set (hfig, \"paperposition\", paperposition);\n%!\n%!   orient portrait;\n%!   assert (orient, \"portrait\");  # default\n%!   assert (get (hfig, \"papersize\"), papersize);\n%!   assert (get (hfig, \"paperposition\"), paperposition);\n%!\n%!   orient landscape;\n%!   assert (orient,\"landscape\");  # change to landscape\n%!   assert (get (hfig, \"papersize\"), papersize([2, 1]));\n%!   assert (get (hfig, \"paperposition\"), fullpaperposition([1, 2, 4, 3]));\n%!\n%!   orient portrait   # change back to portrait\n%!   assert (orient, \"portrait\");\n%!   assert (get (hfig, \"papersize\"), papersize);\n%!   assert (get (hfig, \"paperposition\"), paperposition);\n%!\n%!   orient landscape;\n%!   orient tall;\n%!   assert (orient, \"tall\");\n%!   assert (get (hfig, \"papersize\"), papersize);\n%!   assert (get (hfig, \"paperposition\"), fullpaperposition);\n%!\n%!   orient portrait   # errors don't change the state\n%!   assert (orient, \"portrait\");\n%!   assert (get (hfig, \"papersize\"), papersize);\n%!   assert (get (hfig, \"paperposition\"), paperposition);\n%! unwind_protect_cleanup\n%!   close (hfig);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> orient ({1})\n%!error <Invalid call> orient (1.73, 'portrait')\n%!error <unknown ORIENTATION 'foobar'>\n%! hfig = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   orient (\"foobar\");\n%! unwind_protect_cleanup\n%!   close (hfig);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/pbaspect.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{plot_box_aspect_ratio} =} pbaspect ( )\n## @deftypefnx {} {} pbaspect (@var{plot_box_aspect_ratio})\n## @deftypefnx {} {} pbaspect (@var{mode})\n## @deftypefnx {} {@var{plot_box_aspect_ratio_mode} =} pbaspect (\"mode\")\n## @deftypefnx {} {} pbaspect (@var{hax}, @dots{})\n##\n## Query or set the plot box aspect ratio of the current axes.\n##\n## The aspect ratio is a normalized 3-element vector representing the rendered\n## lengths of the x, y, and z axes.\n##\n## @code{pbaspect(@var{mode})}\n##\n## Set the plot box aspect ratio mode of the current axes.  @var{mode} is\n## either @qcode{\"auto\"} or @qcode{\"manual\"}.\n##\n## @code{pbaspect (\"mode\")}\n##\n## Return the plot box aspect ratio mode of the current axes.\n##\n## @code{pbaspect (@var{hax}, @dots{})}\n##\n## Operate on the axes in handle @var{hax} instead of the current axes.\n##\n## @seealso{axis, daspect, xlim, ylim, zlim}\n## @end deftypefn\n\nfunction pbratio = pbaspect (varargin)\n\n  ## Grab axes handle if present\n  if (nargin > 0)\n    if (isscalar (varargin{1}) && isaxes (varargin{1}))\n      hax = varargin{1};\n      varargin = varargin(2:end);\n    else\n      hax = gca ();\n    endif\n  else\n    hax = gca ();\n  endif\n\n  nargin = numel (varargin);\n  if (nargin > 1)\n    print_usage ();\n  endif\n\n  if (nargin == 0)\n    pbratio = get (hax, \"plotboxaspectratio\");\n  else\n    arg = varargin{1};\n    if (isnumeric (arg))\n      if (numel (arg) == 2)\n        set (hax, \"plotboxaspectratio\", [arg, 1]);\n      elseif (numel (arg) == 3)\n        set (hax, \"plotboxaspectratio\", arg);\n      else\n        error (\"pbaspect: PLOT_BOX_ASPECT_RATIO must be a 2- or 3-element vector\");\n      endif\n    elseif (ischar (arg))\n      arg = lower (arg);\n      switch (arg)\n        case \"auto\"\n          set (hax, \"plotboxaspectratiomode\", \"auto\");\n        case \"manual\"\n          set (hax, \"plotboxaspectratiomode\", \"manual\");\n        case \"mode\"\n          pbratio = get (hax, \"plotboxaspectratiomode\");\n        otherwise\n          error (\"pbaspect: Invalid MODE <%s>\", arg);\n      endswitch\n    else\n      print_usage ();\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = 0:0.01:4;\n%! plot (x,cos (x), x,sin (x));\n%! pbaspect ([1 1 1]);\n%! title (\"plot box is square\");\n\n%!demo\n%! clf;\n%! x = 0:0.01:4;\n%! plot (x,cos (x), x,sin (x));\n%! pbaspect ([2 1 1]);\n%! title (\"plot box aspect ratio is 2x1\");\n\n%!demo\n%! clf;\n%! x = 0:0.01:4;\n%! plot (x,cos (x), x,sin (x));\n%! daspect ([1 1 1]);\n%! pbaspect ([2 1 1]);\n%! title (\"plot box is 2x1, and axes [0 4 -1 1]\");\n"
  },
  {
    "path": "scripts/plot/appearance/private/__axis_label__.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} __axis_label__ (@var{hax}, @var{caller}, @var{txt}, @dots{})\n## @deftypefnx {} {@var{h} =} __axis_label__ (@dots{})\n## Internal function with common code for axis labeling functions.\n## @seealso{xlabel, ylabel, zlabel, title}\n## @end deftypefn\n\nfunction retval = __axis_label__ (hax, caller, txt, varargin)\n\n  h = get (hax, caller);\n\n  ## Set other prop/values first in case they influence appearance of string.\n  set (h, varargin{:}, \"string\", txt);\n\n  if (nargout > 0)\n    retval = h;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/appearance/private/__axis_limits__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{limits} =} __axis_limits__ (@var{fcn})\n## @deftypefnx {} {@var{xmode} =} __axis_limits__ (@var{fcn}, \"mode\")\n## @deftypefnx {} {@var{xmethod} =} __axis_limits__ (@var{fcn}, \"method\")\n## @deftypefnx {} {} __axis_limits__ (@var{fcn}, [@var{x_lo} @var{x_hi}])\n## @deftypefnx {} {} __axis_limits__ (@var{fcn}, \"auto\")\n## @deftypefnx {} {} __axis_limits__ (@var{fcn}, \"manual\")\n## @deftypefnx {} {} __axis_limits__ (@var{fcn}, \"tickaligned\")\n## @deftypefnx {} {} __axis_limits__ (@var{fcn}, \"tight\")\n## @deftypefnx {} {} __axis_limits__ (@var{fcn}, \"padded\")\n## @deftypefnx {} {} __axis_limits__ (@var{fcn}, @var{hax}, @dots{})\n## @deftypefn {} {@var{old_limits} =} __axis_limits__ (@var{fcn}, @dots{})\n## Internal function that implements common code to query or set the axis\n## limits for a plot.\n## @seealso{xlim, ylim, zlim, title}\n## @end deftypefn\n\nfunction retval = __axis_limits__ (fcn, varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (fcn, varargin{:});\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (nargin == 0)\n    retval = get (hax, fcn);\n  else\n    retval = [];\n    arg = varargin{1};\n    if (ischar (arg))\n      if (strcmpi (arg, \"mode\"))\n        retval = get (hax, [fcn \"mode\"]);\n      elseif (strcmpi (arg, \"method\"))\n        retval = get (hax, [fcn \"itmethod\"]);\n      elseif (any (strcmpi (arg, {\"auto\", \"manual\"})))\n        set (hax, [fcn \"mode\"], arg);\n      elseif (any (strcmpi (arg, {\"tickaligned\", \"tight\", \"padded\"})))\n        set (hax, [fcn \"itmethod\"], arg);\n      else\n        error ('%s: unrecognized argument \"%s\"', fcn, arg);\n      endif\n    else\n      if (! isnumeric (arg) || any (size (arg(:)) != [2, 1]))\n        error (\"%s: LIMITS must be a 2-element vector\", fcn);\n      elseif (arg(1) >= arg(2))\n        error (\"%s: axis limits must be increasing\", fcn);\n      endif\n      set (hax, fcn, arg(:));\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/appearance/private/__gnuplot_legend__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} legend ()\n## @deftypefnx {} {} legend (@var{str1}, @var{str2}, @dots{})\n## @deftypefnx {} {} legend (@var{charmat})\n## @deftypefnx {} {} legend (@{@var{cellstr}@})\n## @deftypefnx {} {} legend (@dots{}, \"location\", @var{pos})\n## @deftypefnx {} {} legend (@dots{}, \"orientation\", @var{orient})\n## @deftypefnx {} {} legend (@var{hax}, @dots{})\n## @deftypefnx {} {} legend (@var{hobjs}, @dots{})\n## @deftypefnx {} {} legend (@var{hax}, @var{hobjs}, @dots{})\n## @deftypefnx {} {} legend (\"@var{option}\")\n## @deftypefnx {} {} legend (@dots{}, @{@var{cellstr}@}, @var{property}, @var{value}, @dots{})\n## @deftypefnx {} {[@var{hleg}, @var{hleg_obj}, @var{hplot}, @var{labels}] =} legend (@dots{})\n##\n## Display a legend for the current axes using the specified strings as labels.\n##\n## Legend entries may be specified as individual character string arguments,\n## a character array, or a cell array of character strings.  When label names\n## might be confused with options to @code{legend}, the labels should be\n## protected by specifying them as a cell array of strings.\n##\n## If the first argument @var{hax} is an axes handle, then add a legend to this\n## axes, rather than the current axes returned by @code{gca}.\n##\n## Legend labels are associated with the axes' children; The first label is\n## assigned to the first object that was plotted in the axes, the second label\n## to the next object plotted, etc.  To label specific data objects, without\n## labeling all objects, provide their graphic handles in the input\n## @var{hobjs}.\n##\n## The optional parameter @var{pos} specifies the location of the legend as\n## follows:\n##\n## @multitable @columnfractions 0.06 0.14 0.80\n## @headitem @tab pos @tab location of the legend\n## @item @tab north @tab center top\n## @item @tab south @tab center bottom\n## @item @tab east @tab right center\n## @item @tab west @tab left center\n## @item @tab northeast @tab right top (default)\n## @item @tab northwest @tab left top\n## @item @tab southeast @tab right bottom\n## @item @tab southwest @tab left bottom\n## @sp 1\n## @item @tab outside @tab can be appended to any location string @*\n## @item @tab         @tab which will place the legend outside the axes\n## @end multitable\n##\n## The optional parameter @var{orient} determines if the legend elements are\n## placed vertically or horizontally.  The allowed values are\n## @qcode{\"vertical\"} (default) or @qcode{\"horizontal\"}.\n##\n## The following customizations are available using @var{option}:\n##\n## @table @asis\n## @item @qcode{\"show\"}\n##   Show legend on the plot\n##\n## @item @qcode{\"hide\"}\n##   Hide legend on the plot\n##\n## @item @qcode{\"toggle\"}\n##   Toggle between @qcode{\"hide\"} and @qcode{\"show\"}\n##\n## @item @qcode{\"boxon\"}\n##   Show a box around legend (default)\n##\n## @item @qcode{\"boxoff\"}\n##   Hide the box around legend\n##\n## @item @qcode{\"right\"}\n##   Place label text to the right of the keys (default)\n##\n## @item @qcode{\"left\"}\n##   Place label text to the left of the keys\n##\n## @item @qcode{\"off\"}\n##   Delete the legend object\n## @end table\n##\n## The @code{legend} function creates a graphics object which has various\n## properties that can be manipulated with @code{get}/@code{set}.\n## Alternatively, properties can be set directly when calling @code{legend} by\n## including @var{property}/@var{value} pairs.  If using this calling form, the\n## labels must be specified as a cell array of strings.  Graphics object\n## properties are documented in detail at @ref{Graphics Object Properties}.\n##\n## The optional output values are\n##\n## @table @var\n## @item hleg\n##   The graphics handle of the legend object.\n##\n## @item hleg_obj\n##   Graphics handles to the text, patch, and line objects which form the\n##   legend.\n##\n## @item hplot\n##   Graphics handles to the plot objects which were used in making the legend.\n##\n## @item labels\n##   A cell array of strings of the labels in the legend.\n## @end table\n##\n## Implementation Note: The legend label text is either provided in the call to\n## @code{legend} or is taken from the @code{DisplayName} property of the\n## graphics objects.  Only data objects, such as line, patch, and surface, have\n## this property whereas axes, figures, etc.@: do not so they are never present\n## in a legend.  If no labels or @code{DisplayName} properties are available,\n## then the label text is simply @qcode{\"data1\"}, @qcode{\"data2\"}, @dots{},\n## @nospell{@qcode{\"dataN\"}}.  No more than 20 data labels will be\n## automatically generated.  To label more, call @code{legend} explicitly and\n## provide all labels.\n##\n## The legend @code{FontSize} property is initially set to 90% of the axes\n## @code{FontSize} to which it is attached.  Use @code{set} to override this\n## if necessary.\n##\n## A legend is implemented as an additional axes object with the @code{tag}\n## property set to @qcode{\"legend\"}.  Properties of the legend object may be\n## manipulated directly by using @code{set}.\n## @end deftypefn\n\nfunction [hleg, hleg_obj, hplot, labels] = __gnuplot_legend__ (varargin)\n\n  if (nargin > 0\n      && (! ishghandle (varargin{1})\n          || (strcmp (get (varargin{1}, \"type\"), \"axes\")\n              && ! strcmp (get (varargin{1}, \"tag\"), \"legend\"))))\n    [ca, varargin, nargin] = __plt_get_axis_arg__ (\"legend\", varargin{:});\n    if (isempty (ca))\n      ca = gca ();\n    endif\n    hfig = ancestor (ca, \"figure\");\n  else\n    hfig = get (0, \"currentfigure\");\n    if (isempty (hfig))\n      hfig = gcf ();\n    endif\n    ca = gca ();\n  endif\n\n  ## Special handling for plotyy which has two axes objects\n  if (isprop (ca, \"__plotyy_axes__\"))\n    plty = get (ca, \"__plotyy_axes__\");\n    ca = [ca, plty.'];\n    ## Remove duplicates while preserving order\n    [~, n] = unique (ca, \"first\");\n    ca = ca(sort (n));\n  endif\n\n  if (nargin > 0 && all (ishghandle (varargin{1})))\n    ## List of plot objects to label given as first argument\n    kids = flipud (varargin{1}(:));\n    varargin(1) = [];\n  else\n    ## Find list of plot objects from axes \"children\"\n    kids = ca;\n    kids(strcmp (get (ca, \"tag\"), \"legend\")) = [];\n    if (isscalar (kids))\n      kids = get (kids, \"children\")(:);\n    else\n      kids = vertcat (flipud (get (kids, \"children\")){:});\n    endif\n  endif\n  nargs = numel (varargin);\n  nkids = numel (kids);\n\n  ## Find any existing legend object associated with axes\n  hlegend = [];\n  for hax = ca\n    try\n      hlegend = get (hax, \"__legend_handle__\");\n      if (! isempty (hlegend))\n        break;\n      endif\n    end_try_catch\n  endfor\n\n  orientation = \"default\";\n  location = \"default\";\n  show = \"create\";\n  textpos = \"default\";\n  box = \"default\";\n  delete_leg = false;\n  find_leg_hdl = (nargs == 0);  # possibly overridden\n  propvals = {};\n\n  ## Find \"location\", \"orientation\", \"textposition\" property/value pairs\n  foundpos = foundorient = foundtextpos = false;\n  i = nargs - 1;\n  while (i > 0)\n    pos = varargin{i};\n    str = varargin{i+1};\n    if (strcmpi (pos, \"location\") && ischar (str))\n      if (! foundpos)\n        location = lower (str);\n        foundpos = true;\n      endif\n      varargin(i:i+1) = [];\n      nargs -= 2;\n    elseif (strcmpi (pos, \"orientation\") && ischar (str))\n      if (! foundorient)\n        orientation = lower (str);\n        foundorient = true;\n      endif\n      varargin(i:i+1) = [];\n      nargs -= 2;\n    elseif (strcmpi (pos, \"textposition\") && ischar (str))\n      if (! foundtextpos)\n        textpos = lower (str);\n        foundtextpos = true;\n      endif\n      varargin(i:i+1) = [];\n      nargs -= 2;\n    endif\n    i -= 2;\n  endwhile\n\n  ## Validate the orientation\n  if (! any (strcmp (orientation, {\"vertical\", \"horizontal\", \"default\"})))\n    error (\"legend: unrecognized legend orientation\");\n  endif\n\n  ## Validate the texposition\n  if (! any (strcmp (textpos, {\"left\", \"right\", \"default\"})))\n    error (\"legend: unrecognized legend textposition\");\n  endif\n\n  ## Validate the location type\n  outside = false;\n  inout = strfind (location, \"outside\");\n  if (! isempty (inout))\n    outside = true;\n    location = location(1:inout-1);\n  else\n    outside = false;\n  endif\n\n  switch (location)\n    case {\"north\", \"south\", \"east\", \"west\", \"northeast\", \"northwest\", ...\n          \"southeast\", \"southwest\", \"default\"}\n      ## These are all valid locations, do nothing.\n\n    case \"best\"\n      if (outside)\n        if (strcmp (orientation, \"horizontal\"))\n          location = \"south\";\n        else\n          location = \"northeast\";\n        endif\n      else\n        warning (\"legend: 'best' not yet implemented for location specifier, using 'northeast' instead\\n\");\n        location = \"northeast\";\n      endif\n\n    case \"none\"\n      ## FIXME: Should there be any more error checking on this?\n\n    otherwise\n      error (\"legend: unrecognized legend location\");\n  endswitch\n\n  ## Finish input processing based on number of inputs\n  if (nargs == 0)\n    ## No labels given, create a new legend or return existing one\n    if (isempty (hlegend))\n      show = \"create\";\n      textpos = \"right\";\n      find_leg_hdl = false;\n    endif\n\n  elseif (nargs == 1)\n    ## Either OPTION value, single string label, or cellstr of labels.\n    arg = varargin{1};\n    if (ischar (arg))\n      if (rows (arg) == 1)\n        str = lower (strtrim (arg));\n        switch (str)\n          case \"off\"\n            delete_leg = true;\n          case \"hide\"\n            show = \"off\";\n            nargs -= 1;\n          case \"show\"\n            if (! isempty (hlegend))\n              show = \"on\";\n            else\n              show = \"create\";\n              textpos = \"right\";\n            endif\n            nargs -= 1;\n          case \"toggle\"\n            if (isempty (hlegend))\n              show = \"create\";\n              textpos = \"right\";\n            elseif (strcmp (get (hlegend, \"visible\"), \"off\"))\n              show = \"on\";\n            else\n              show = \"off\";\n            endif\n            nargs -= 1;\n          case \"boxon\"\n            box = \"on\";\n            nargs -= 1;\n          case \"boxoff\"\n            box = \"off\";\n            nargs -= 1;\n          case \"left\"\n            textpos = \"left\";\n            nargs -= 1;\n          case \"right\"\n            textpos = \"right\";\n            nargs -= 1;\n        endswitch\n      else\n        ## Character matrix of labels\n        varargin = cellstr (arg);\n        nargs = numel (varargin);\n      endif\n    elseif (iscellstr (arg))\n      ## Cell array of labels\n      varargin = arg;\n      nargs = numel (varargin);\n    else\n      error (\"Octave:invalid-fun-call\",\n             \"legend: single argument must be a string or cellstr\");\n    endif\n\n  elseif (nargs > 1 && iscellstr (varargin{1}))\n    ## Cell array of labels followed by property/value pairs\n    propvals = varargin(2:end);\n    if (rem (numel (propvals), 2) != 0)\n      error (\"legend: PROPERTY/VALUE arguments must occur in pairs\");\n    endif\n    varargin = {varargin{1}{:}};\n    nargs = numel (varargin);\n  endif\n\n  have_labels = (nargs > 0);\n  hobjects = [];\n  hplots = [];\n  text_strings = {};\n\n  if (delete_leg)\n    delete (hlegend);\n    hlegend = [];\n  elseif (find_leg_hdl)\n    ## Don't change anything about legend.\n    ## hleg output will be assigned hlegend value at end of function.\n  elseif (strcmp (show, \"off\"))\n    if (! isempty (hlegend))\n      set (hlegend, \"visible\", \"off\");\n      hlegend = [];\n    endif\n  elseif (strcmp (show, \"on\"))\n    if (! isempty (hlegend))\n      set (hlegend, \"visible\", \"on\");\n      ## NOTE: Matlab sets both \"visible\" and \"box\" to \"on\" for \"show on\"\n      ## set (hlegend, \"box\", \"on\");\n    endif\n  elseif (strcmp (box, \"on\"))\n    if (! isempty (hlegend))\n      set (hlegend, \"box\", \"on\");\n    endif\n  elseif (strcmp (box, \"off\"))\n    if (! isempty (hlegend))\n      set (hlegend, \"box\", \"off\");\n    endif\n  elseif (! have_labels && ! isempty (hlegend)\n          && ! (strcmp (location, \"default\")\n                && strcmp (orientation, \"default\")))\n    ## Changing location or orientation of existing legend\n    if (strcmp (location, \"default\"))\n      set (hlegend, \"orientation\", orientation);\n    elseif (strcmp (orientation, \"default\"))\n      if (outside)\n        set (hlegend, \"location\", [location \"outside\"]);\n      else\n        set (hlegend, \"location\", location);\n      endif\n    else\n      if (outside)\n        set (hlegend, \"location\", [location \"outside\"],\n                      \"orientation\", orientation);\n      else\n        set (hlegend, \"location\", location,\n                      \"orientation\", orientation);\n      endif\n    endif\n  else\n    ## Create or modify legend object\n\n    if (! isempty (hlegend))\n      ## Disable callbacks while modifying an existing legend\n      setappdata (hlegend, \"nocallbacks\", true);\n    endif\n\n    if (have_labels)\n      ## Check for valid data that can be labeled.\n      have_data = false;\n      have_dname = false;\n      for hkid = kids.'\n        typ = get (hkid, \"type\");\n        if (any (strcmp (typ, {\"line\", \"patch\", \"surface\", \"hggroup\"})))\n          have_data = true;\n          break;\n        endif\n      endfor\n\n      if (! have_data)\n        warning (\"legend: plot data is empty; setting key labels has no effect\");\n      endif\n    else\n      ## No labels.  Search for DisplayName property.\n      have_dname = false;\n      n_dname = 0;\n      for hkid = kids.'\n        typ = get (hkid, \"type\");\n        if (any (strcmp (typ, {\"line\", \"patch\", \"surface\", \"hggroup\"})))\n          n_dname += 1;  # count of objects which could be labeled\n          if (! isempty (get (hkid, \"displayname\")))\n            have_dname = true;\n            break;\n          endif\n        endif\n      endfor\n      have_data = n_dname > 0;\n    endif\n\n    if (have_labels || ! have_dname)\n      k = nkids;\n      if (! have_labels)\n        ## No labels or DisplayName.  Create set of \"dataX\" labels.\n        if (n_dname > 20)\n          warning (\"legend: labeling only first 20 data objects\");\n          n_dname = 20;\n        endif\n        nargs = n_dname;\n        varargin = arrayfun (@(x) sprintf (\"data%d\", x), [1:nargs]',\n                             \"uniformoutput\", false);\n        have_labels = true;\n      endif\n      for i = 1 : nargs\n        label = varargin{i};\n        if (! ischar (label))\n          error (\"Octave:invalid-fun-call\",\n                 \"legend: expecting label to be a string\");\n        endif\n        ## Locate an object which can be labeled\n        while (k > 0)\n          typ = get (kids(k), \"type\");\n          if (any (strcmp (typ, {\"line\",\"patch\",\"surface\",\"hggroup\"})))\n            break;\n          endif\n          k--;\n        endwhile\n        if (k > 0)\n          set (kids(k), \"displayname\", label);\n          hplots(end+1) = kids(k);\n          text_strings(end+1) = label;\n          k--;\n        else\n          if (have_data)\n            warning (\"legend: ignoring extra labels\");\n          endif\n          break;  # k = 0, no further handles to process\n        endif\n      endfor\n\n    else\n      ## No labels specified but objects have DisplayName property set.\n      k = nkids;\n      while (k > 0)\n        ## Locate object to label\n        while (k > 0)\n          typ = get (kids(k), \"type\");\n          if (any (strcmp (typ, {\"line\",\"patch\",\"surface\",\"hggroup\"})))\n            break;\n          endif\n          k--;\n        endwhile\n        if (k > 0)\n          dname = get (kids(k), \"displayname\");\n          if (! isempty (dname))\n            hplots(end+1) = kids(k);\n            text_strings(end+1) = dname;\n          endif\n          k--;\n        endif\n      endwhile\n    endif\n\n    if (isempty (hplots))\n      ## Nothing to label\n      if (! isempty (hlegend))\n        delete (hlegend);\n        hlegend = [];\n        hobjects = [];\n        hplots = [];\n        text_strings = {};\n      endif\n    else\n      ## Preserve the old legend if it exists\n      if (! isempty (hlegend))\n        if (strcmp (textpos, \"default\"))\n          textpos = get (hlegend, \"textposition\");\n        endif\n        if (strcmp (location, \"default\"))\n          location = get (hlegend, \"location\");\n          inout = strfind (location, \"outside\");\n          if (! isempty (inout))\n            outside = true;\n            location = location(1:inout-1);\n          else\n            outside = false;\n          endif\n        endif\n        if (strcmp (orientation, \"default\"))\n          orientation = get (hlegend, \"orientation\");\n        endif\n        box = get (hlegend, \"box\");\n      else\n        if (strcmp (textpos, \"default\"))\n          textpos = \"right\";\n        endif\n        if (strcmp (location, \"default\"))\n          location = \"northeast\";\n        endif\n        if (strcmp (orientation, \"default\"))\n          orientation = \"vertical\";\n        endif\n        box = \"on\";\n      endif\n\n      ## Use axis which is appropriate for legend location.\n      ## This is only necessary for plotyy figures where there are two axes.\n      if (numel (ca) == 1)\n        cax = ca(1);\n      elseif (strfind (location, \"east\"))\n        cax = ca(2);\n      else\n        cax = ca(1);\n      endif\n      ## Get axis size and fontsize in points.\n      ## Rely on listener to handle conversion.\n      units = get (cax, \"units\");\n      unwind_protect\n        set (cax, \"units\", \"points\", \"fontunits\", \"points\");\n        if (isempty (hlegend) || ! isprop (hlegend, \"unmodified_axes_position\"))\n          unmodified_axes_position = get (cax, \"position\");\n          unmodified_axes_outerposition = get (cax, \"outerposition\");\n        else\n          unmodified_axes_position = get (hlegend, \"unmodified_axes_position\");\n          unmodified_axes_outerposition = get (hlegend, ...\n                                               \"unmodified_axes_outerposition\");\n        endif\n        ca_pos = unmodified_axes_position;\n        ca_outpos = unmodified_axes_outerposition;\n        tightinset = get (ca(1), \"tightinset\");\n        for i = 2 : numel (ca)\n          tightinset = max (tightinset, get (ca(i), \"tightinset\"));\n        endfor\n      unwind_protect_cleanup\n        set (cax, \"units\", units);\n      end_unwind_protect\n\n      ## Padding between legend entries horizontally and vertically\n      ## measured in points.\n      ## FIXME: 3*xpad must be integer or strange off-by-1 pixel issues\n      ##        with lines in OpenGL.\n      xpad = 2 + 1/3;\n      ypad = 4;\n\n      bpad = 8;  # padding of legend box from surrounding axes\n\n      linelength = 15;\n\n      ## Preamble code to restore figure and axes after legend creation\n      origfig = get (0, \"currentfigure\");\n      if (origfig != hfig)\n        set (0, \"currentfigure\", hfig);\n      else\n        origfig = [];\n      endif\n      origaxes = get (hfig, \"currentaxes\");\n      unwind_protect\n        ud = ancestor (hplots, \"axes\");\n        if (! isscalar (ud))\n          ud = unique ([ud{:}]);\n        endif\n        hpar = get (ud(1), \"parent\");\n\n        if (isempty (hlegend))\n          ## Create a legend object (axes + new properties)\n          addprops = true;\n          hlegend = axes (\"parent\", hpar, \"tag\", \"legend\",\n                          \"box\", box,\n                          \"xtick\", [], \"ytick\", [],\n                          \"xlim\", [0, 1], \"ylim\", [0, 1],\n                          \"positionconstraint\", \"innerposition\");\n          setappdata (hlegend, \"__axes_handle__\", ud);\n          try\n            addproperty (\"__legend_handle__\", ud(1), \"handle\", hlegend);\n          catch\n            set (ud(1), \"__legend_handle__\", hlegend);\n          end_try_catch\n\n          ## Inherit fontsize from current axis\n          ## \"fontunits\" should be first because it affects interpretation\n          ## of \"fontsize\" property.\n          [fontunits, fontsz] = get (ca(1), {\"fontunits\", \"fontsize\"}){:};\n          fontsz *= 0.90;  # Reduce legend fontsize to 90% of axes fontsize\n          set (hlegend, {\"fontunits\", \"fontsize\"}, {fontunits, fontsz});\n          set (hlegend, \"fontunits\", \"points\");  # legend always works in pts.\n          ## Also inherit colormap from axes if it is different than figure\n          cax_cmap = get (cax, \"colormap\");\n          if (! isequal (cax_cmap, get (hpar, \"colormap\")))\n            set (hlegend, \"colormap\", cax_cmap);\n          endif\n          old_hplots = [];\n        else\n          ## Re-use existing legend.\n          addprops = false;\n          axes (hlegend);\n          delete (get (hlegend, \"children\"));\n          ## Hack: get list of hplots for which addlistener has been called.\n          old_hplots = get (hlegend, \"deletefcn\"){6};\n        endif\n\n        if (addprops)\n          ## Only required for a newly created legend object\n          ## FIXME: \"autoupdate\" is not implemented.\n          addproperty (\"autoupdate\", hlegend, \"radio\", \"{on}|off\");\n          addproperty (\"edgecolor\", hlegend, \"color\", [0.15, 0.15, 0.15]);\n          addproperty (\"textcolor\", hlegend, \"color\", [0, 0, 0]);\n          locations = {\"north\", \"south\", \"east\", \"west\", ...\n                       \"{northeast}\", \"southeast\", \"northwest\", \"southwest\", ...\n                       \"northoutside\", \"southoutside\", ...\n                       \"eastoutside\", \"westoutside\", ...\n                       \"northeastoutside\", \"southeastoutside\", ...\n                       \"northwestoutside\", \"southwestoutside\", \"best\", ...\n                       \"bestoutside\", \"none\"};\n          addproperty (\"location\", hlegend, \"radio\", strjoin (locations, \"|\"));\n          addproperty (\"orientation\", hlegend, \"radio\",\n                       \"{vertical}|horizontal\");\n          addproperty (\"string\", hlegend, \"any\", text_strings);\n          addproperty (\"interpreter\", hlegend, \"textinterpreter\");\n          addproperty (\"textposition\", hlegend, \"radio\", \"left|{right}\");\n        endif\n\n        ## Apply any PROPERTY/VALUE pairs given as arguments\n        if (! isempty (propvals))\n          set (hlegend, propvals{:});\n        endif\n\n        ## Special case of PROPERTY \"edgecolor\" (bug #56968)\n        ec_idx = find (strcmpi (propvals, \"edgecolor\"), 1, \"last\");\n        if (! isempty (ec_idx))\n          ec_color = propvals{ec_idx + 1};\n          set (hlegend, \"xcolor\", ec_color, \"ycolor\", ec_color);\n        endif\n\n        ## Text objects in key inherit visual properties from legend object\n        legprops = { \"fontunits\", \"fontangle\", \"fontname\", \"fontsize\", ...\n                     \"fontweight\", \"interpreter\", \"textcolor\" };\n\n        txtprops = { \"fontunits\", [], \"fontangle\", [] \"fontname\", [], ...\n                     \"fontsize\", [], \"fontweight\", [] \"interpreter\", [], ...\n                     \"color\", [] };\n        propvals = get (hlegend, legprops);\n        txtprops(2:2:end) = propvals;\n\n        ## Add text labels to the axes first and check their extents\n        nentries = numel (hplots);\n        texthandle = [];\n        maxwidth = maxheight = 0;\n        for k = 1 : nentries\n          halign = ifelse (strcmp (textpos, \"right\"), \"left\", \"right\");\n          texthandle(k) = text (0, 0, text_strings{k},\n                                \"units\", \"points\",\n                                \"horizontalalignment\", halign,\n                                txtprops{:});\n          setappdata (texthandle(k), \"handle\", hplots(k));\n          extents = get (texthandle(k), \"extent\");\n          maxwidth = max (maxwidth, extents(3));\n          maxheight = max (maxheight, extents(4));\n        endfor\n        ## Restore units which were forced to points\n        set (texthandle, \"units\", get (0, \"DefaultTextUnits\"));\n\n        num1 = nentries;\n        if (strcmp (orientation, \"vertical\"))\n          height = nentries * (ypad + maxheight);\n          if (outside)\n            if (height > ca_pos(4))\n              ## Avoid shrinking the height of the axis to zero if outside\n              num1 = ca_pos(4) / (maxheight + ypad) / 2;\n            endif\n          else\n            if (height > 0.9 * ca_pos(4))\n              num1 = 0.9 * ca_pos(4) / (maxheight + ypad);\n            endif\n          endif\n        else\n          width = nentries * (ypad + maxwidth);\n          if (outside)\n            if (width > ca_pos(3))\n              ## Avoid shrinking the width of the axis to zero if outside\n              num1 = ca_pos(3) / (maxwidth + ypad) / 2;\n            endif\n          else\n            if (width > 0.9 * ca_pos(3))\n              num1 = 0.9 * ca_pos(3) / (maxwidth + ypad);\n            endif\n          endif\n        endif\n        num2 = ceil (nentries / num1);\n\n        ## Layout is [xpad, linelength, xpad, maxwidth, xpad]\n        xstep = 3 * xpad + (maxwidth + linelength);\n        if (strcmp (textpos, \"right\"))\n          xoffset = xpad;\n          txoffset = 2 * xpad + linelength;\n        else\n          xoffset = 2 * xpad + maxwidth;\n          txoffset = xpad + maxwidth;\n        endif\n        ystep = (ypad + maxheight);\n        yoffset = ystep / 2;\n\n        ## Place the legend in the desired location\n        if (strcmp (orientation, \"vertical\"))\n          lpos = [0, 0, num2 * xstep, num1 * ystep];\n        else\n          lpos = [0, 0, num1 * xstep, num2 * ystep];\n        endif\n\n        gnuplot = strcmp (get (hfig, \"__graphics_toolkit__\"), \"gnuplot\");\n        if (gnuplot)\n          ## gnuplot places the key (legend) at edge of the figure window.\n          ## OpenGL places the legend box at edge of the unmodified axes\n          ## position.\n          if (isempty (strfind (location, \"east\")))\n            gnuplot_offset = unmodified_axes_outerposition(1) ...\n                           + unmodified_axes_outerposition(3) ...\n                           - unmodified_axes_position(1) ...\n                           - unmodified_axes_position(3);\n          else\n            gnuplot_offset = unmodified_axes_position(1) ...\n                           - unmodified_axes_outerposition(1);\n          endif\n          ## FIXME: The \"fontsize\" is added to match the behavior of OpenGL.\n          ## This implies that a change in fontsize should trigger a listener\n          ## to update the legend.  The \"2\" was determined using a long legend\n          ## key in the absence of any subplots.\n          gnuplot_offset -= 2 * get (hlegend, \"fontsize\");\n        else\n          gnuplot_offset = 0;\n        endif\n\n        ## For legend's outside the associated axes position,\n        ## align their edge to the unmodified_axes_outerposition,\n        ## and adjust the axes position accordingly.\n        switch (location)\n          case \"north\"\n            if (outside)\n              lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ...\n                      ca_outpos(2) + ca_outpos(4) - lpos(4) - bpad/2, ...\n                      lpos(3), lpos(4)];\n\n              new_pos = [ca_pos(1), ca_pos(2), ca_pos(3), ca_pos(4) - lpos(4)];\n            else\n              lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ...\n                      ca_pos(2) + ca_pos(4) - lpos(4) - bpad, ...\n                      lpos(3), lpos(4)];\n            endif\n          case \"south\"\n            if (outside)\n              lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ...\n                      ca_outpos(2) + bpad/2, lpos(3), lpos(4)];\n              new_pos = [ca_pos(1), ...\n                         lpos(2) + lpos(4) + bpad/2 + tightinset(2), ...\n                         ca_pos(3), ca_pos(4) - lpos(4)];\n            else\n              lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ...\n                      ca_pos(2) + bpad, lpos(3), lpos(4)];\n            endif\n          case \"east\"\n            if (outside)\n              lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3) - bpad/2, ...\n                      ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, ...\n                      lpos(3), lpos(4)];\n              new_pos = [ca_pos(1), ca_pos(2), ...\n                         lpos(1) - bpad - tightinset(3) - ca_pos(1), ...\n                         ca_pos(4)];\n              new_pos(3) += gnuplot_offset;\n            else\n              lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - bpad, ...\n                      ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)];\n            endif\n          case \"west\"\n            if (outside)\n              lpos = [ca_outpos(1) + bpad/2, ...\n                      ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, ...\n                      lpos(3), lpos(4)];\n              new_pos = [lpos(1) + lpos(3) + bpad/2 + tightinset(1), ...\n                         ca_pos(2), ca_pos(3) - lpos(3) - bpad/2, ca_pos(4)];\n              new_pos([1, 3]) += [-gnuplot_offset, gnuplot_offset];\n            else\n              lpos = [ca_pos(1) + bpad, ...\n                      ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)];\n            endif\n          case \"northeast\"\n            if (outside)\n              lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3) - bpad/2, ...\n                      ca_pos(2) + ca_pos(4) - lpos(4), ...\n                      lpos(3), lpos(4)];\n              new_pos = [ca_pos(1), ca_pos(2), ...\n                         lpos(1) - bpad - tightinset(3) - ca_pos(1), ...\n                         ca_pos(4)];\n              new_pos(3) += gnuplot_offset;\n            else\n              lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - bpad, ...\n                      ca_pos(2) + ca_pos(4) - lpos(4) - bpad, ...\n                      lpos(3), lpos(4)];\n            endif\n          case \"northwest\"\n            if (outside)\n              lpos = [ca_outpos(1) + bpad/2, ...\n                      ca_pos(2) + ca_pos(4) - lpos(4), ...\n                      lpos(3), lpos(4)];\n              new_pos = [lpos(1) + lpos(3) + bpad/2 + tightinset(1), ...\n                         ca_pos(2), ca_pos(3) - lpos(3) - bpad/2, ca_pos(4)];\n              new_pos([1, 3]) += [-gnuplot_offset, gnuplot_offset];\n            else\n              lpos = [ca_pos(1) + bpad, ...\n                      ca_pos(2) + ca_pos(4) - lpos(4) - bpad, ...\n                      lpos(3), lpos(4)];\n            endif\n          case \"southeast\"\n            if (outside)\n              lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3) - bpad/2, ...\n                      ca_pos(2), lpos(3), lpos(4)];\n              new_pos = [ca_pos(1), ca_pos(2), ...\n                         lpos(1) - bpad - ca_pos(1) - tightinset(3), ...\n                         ca_pos(4)];\n              new_pos(3) += gnuplot_offset;\n            else\n              lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - bpad, ...\n                      ca_pos(2) + bpad, lpos(3), lpos(4)];\n            endif\n          case \"southwest\"\n            if (outside)\n              lpos = [ca_outpos(1) + bpad/2, ca_pos(2), lpos(3), lpos(4)];\n              new_pos = [lpos(1) + lpos(3) + bpad/2 + tightinset(1), ...\n                         ca_pos(2), ca_pos(3) - lpos(3) - bpad/2, ca_pos(4)];\n              new_pos([1, 3]) += [-gnuplot_offset, gnuplot_offset];\n            else\n              lpos = [ca_pos(1) + bpad, ca_pos(2) + bpad, lpos(3), lpos(4)];\n            endif\n        endswitch\n\n        units = get (hlegend, \"units\");\n        unwind_protect\n          set (hlegend, \"units\", \"points\", \"position\", lpos);\n        unwind_protect_cleanup\n          set (hlegend, \"units\", units);\n        end_unwind_protect\n\n        ## Now write the line segments and place the text objects correctly\n        xk = yk = 0;\n        for k = 1 : numel (hplots)\n          hobjects(end+1) = texthandle(k);\n          hplt = hplots(k);\n          typ = get (hplt, \"type\");\n          ## For an hggroup, find an underlying primitive object\n          if (strcmp (typ, \"hggroup\"))\n            for hgkid = get (hplt, \"children\").'\n              hgkid_type = get (hgkid, \"type\");\n              if (any (strcmp (hgkid_type, {\"line\",\"patch\",\"surface\"})))\n                typ = hgkid_type;\n                hplt = hgkid;\n                break;\n              endif\n            endfor\n          endif\n\n          switch (typ)\n\n            case \"line\"\n              color = get (hplt, \"color\");\n              style = get (hplt, \"linestyle\");\n              lwidth = min (get (hplt, \"linewidth\"), 5);\n              if (! strcmp (style, \"none\"))\n                l1 = __go_line__ (hlegend, ...\n                       \"xdata\", ([xoffset, xoffset + linelength] + xk * xstep) / lpos(3), ...\n                       \"ydata\", [1, 1] .* (lpos(4) - yoffset - yk * ystep) / lpos(4), ...\n                       \"color\", color, \"linestyle\", style, ...\n                       \"linewidth\", lwidth, \"marker\", \"none\");\n                setappdata (l1, \"handle\", hplt);\n                hobjects(end+1) = l1;\n              endif\n              marker = get (hplt, \"marker\");\n              if (! strcmp (marker, \"none\"))\n                l1 = __go_line__ (hlegend, ...\n                       \"xdata\", (xoffset + 0.5 * linelength  + xk * xstep) / lpos(3), ...\n                       \"ydata\", (lpos(4) - yoffset - yk * ystep) / lpos(4), ...\n                       \"color\", color, \"linestyle\", \"none\", ...\n                       \"linewidth\", lwidth, \"marker\", marker, ...\n                       \"markeredgecolor\", get (hplt, \"markeredgecolor\"), ...\n                       \"markerfacecolor\", get (hplt, \"markerfacecolor\"), ...\n                       \"markersize\", min (get (hplt, \"markersize\"),10));\n                setappdata (l1, \"handle\", hplt);\n                hobjects(end+1) = l1;\n              endif\n\n              ## Newly labeled objects have listeners added\n              if (! any (hplt == old_hplots))\n                addlistener (hplt, \"color\",\n                             {@cb_line_listener, hlegend, linelength, false});\n                addlistener (hplt, \"linestyle\",\n                             {@cb_line_listener, hlegend, linelength, false});\n                addlistener (hplt, \"linewidth\",\n                             {@cb_line_listener, hlegend, linelength, false});\n                addlistener (hplt, \"marker\",\n                             {@cb_line_listener, hlegend, linelength, false});\n                addlistener (hplt, \"markeredgecolor\",\n                             {@cb_line_listener, hlegend, linelength, false});\n                addlistener (hplt, \"markerfacecolor\",\n                             {@cb_line_listener, hlegend, linelength, false});\n                addlistener (hplt, \"markersize\",\n                             {@cb_line_listener, hlegend, linelength, false});\n                addlistener (hplt, \"displayname\",\n                             {@cb_line_listener, hlegend, linelength, true});\n              endif\n\n            case \"patch\"\n              facecolor = get (hplt, \"facecolor\");\n              edgecolor = get (hplt, \"edgecolor\");\n              cdata = get (hplt, \"cdata\");\n              if (! strcmp (facecolor, \"none\") || ! strcmp (edgecolor, \"none\"))\n                p1 = patch (\"xdata\", ([0, linelength, linelength, 0] +\n                                      xoffset + xk * xstep) / lpos(3),\n                            \"ydata\", (lpos(4) - yoffset -\n                                      [yk-0.3, yk-0.3, yk+0.3, yk+0.3] .* ystep) / lpos(4),\n                            \"facecolor\", facecolor, \"edgecolor\", edgecolor,\n                            \"cdata\", cdata);\n                setappdata (p1, \"handle\", hplt);\n              else\n                ## non-standard patch only making use of marker styles\n                ## such as scatter plot.\n                p1 = patch (\"xdata\", (xoffset + 0.5 * linelength  + xk * xstep) / lpos(3),\n                            \"ydata\", (lpos(4) - yoffset - yk * ystep) / lpos(4),\n                            \"marker\", get (hplt, \"marker\"),\n                            \"markeredgecolor\",get (hplt,\"markeredgecolor\"),\n                            \"markerfacecolor\",get (hplt,\"markerfacecolor\"),\n                            \"markersize\", min (get (hplt,\"markersize\"),10),\n                            \"cdata\", cdata);\n                setappdata (p1, \"handle\", hplt);\n              endif\n              hobjects(end+1) = p1;\n              ## Copy clim from axes so that colors work out.\n              set (hlegend, \"clim\", get (ca(1), \"clim\"));\n\n              ## FIXME: Need listeners, as for line objects.\n              ##        Changing clim, for example, won't update colors\n\n            case \"surface\"\n              facecolor = get (hplt, \"facecolor\");\n              edgecolor = get (hplt, \"edgecolor\");\n              cdata = sum (get (ca(1), \"clim\")) / 2;\n              if (! strcmp (facecolor, \"none\") || ! strcmp (edgecolor, \"none\"))\n                p1 = patch (\"xdata\", ([0, linelength, linelength, 0] +\n                                      xoffset + xk * xstep) / lpos(3),\n                            \"ydata\", (lpos(4) - yoffset -\n                                      [yk-0.3, yk-0.3, yk+0.3, yk+0.3] .* ystep) / lpos(4),\n                            \"facecolor\", facecolor, \"edgecolor\", edgecolor,\n                            \"cdata\", cdata);\n                setappdata (p1, \"handle\", hplt);\n                hobjects(end+1) = p1;\n              endif\n              ## FIXME: Need listeners, as for line objects.\n\n          endswitch\n\n          set (texthandle(k), \"position\",\n                              [(txoffset + xk * xstep) / lpos(3), ...\n                               (lpos(4) - yoffset - yk * ystep) / lpos(4)]);\n          if (strcmp (orientation, \"vertical\"))\n            yk += 1;\n            if (yk > num1)\n              yk = 0;\n              xk += 1;\n            endif\n          else\n            xk += 1;\n            if (xk > num1)\n              xk = 0;\n              yk += 1;\n            endif\n          endif\n        endfor\n\n        ## Add an invisible text object to original axis\n        ## that, when it is destroyed, will remove the legend.\n        htdel = findall (ca(1), \"-depth\", 1, \"tag\", \"deletelegend\",\n                                \"type\", \"text\");\n        if (isempty (htdel))\n          htdel = text (0, 0, \"\", \"parent\", ca(1), \"tag\", \"deletelegend\",\n                        \"visible\", \"off\", \"handlevisibility\", \"off\",\n                        \"xliminclude\", \"off\", \"yliminclude\", \"off\",\n                        \"zliminclude\", \"off\");\n          set (htdel, \"deletefcn\", {@cb_axes_deleted, ca, hlegend});\n        endif\n        if (isprop (hlegend, \"unmodified_axes_position\"))\n          set (hlegend, \"unmodified_axes_position\",\n                         unmodified_axes_position,\n                        \"unmodified_axes_outerposition\",\n                         unmodified_axes_outerposition);\n        else\n          addproperty (\"unmodified_axes_position\", hlegend,\n                       \"data\", unmodified_axes_position);\n          addproperty (\"unmodified_axes_outerposition\", hlegend,\n                       \"data\", unmodified_axes_outerposition);\n        endif\n\n        ## Resize the axis that the legend is attached to if the legend is\n        ## \"outside\" the plot and create a listener to resize axis to original\n        ## size if the legend is deleted, hidden, or shown.\n        if (outside)\n          for i = 1 : numel (ca)\n            units = get (ca(i), \"units\");\n            unwind_protect\n              set (ca(i), \"units\", \"points\");\n              if (gnuplot && numel (ca) == 1)\n                ## Let gnuplot handle the positioning of the keybox.\n                ## This violates strict Matlab compatibility, but reliably\n                ## renders an aesthetic result.\n                set (ca(i), \"position\", unmodified_axes_position,\n                            \"positionconstraint\", \"outerposition\");\n              else\n                ## numel (ca) > 1 for axes overlays (like plotyy)\n                set (ca(i), \"position\", new_pos);\n              endif\n            unwind_protect_cleanup\n              set (ca(i), \"units\", units);\n            end_unwind_protect\n          endfor\n\n          set (hlegend, \"deletefcn\", {@cb_restore_axes, ca, ...\n                                      unmodified_axes_position, ...\n                                      unmodified_axes_outerposition, ...\n                                      htdel, hplots});\n          addlistener (hlegend, \"visible\", {@cb_legend_hideshow, ca, ...\n                                            unmodified_axes_position, ...\n                                            new_pos});\n        else\n          set (hlegend, \"deletefcn\", {@cb_restore_axes, ca, [], [], ...\n                                      htdel, hplots});\n        endif\n\n        if (! addprops)\n          ## Remove listeners on existing legend temporarily to stop recursion.\n          dellistener (hlegend, \"location\");\n          dellistener (hlegend, \"orientation\");\n          dellistener (hlegend, \"string\");\n          dellistener (hlegend, \"textposition\");\n        endif\n\n        if (! addprops)\n          set (hlegend, \"string\", text_strings);\n        endif\n\n        if (outside)\n          set (hlegend, \"location\", [location \"outside\"],\n                        \"orientation\", orientation, \"textposition\", textpos);\n        else\n          set (hlegend, \"location\", location, \"orientation\", orientation,\n                        \"textposition\", textpos);\n        endif\n\n        if (addprops)\n          addlistener (cax, \"colormap\", {@cb_legend_colormap_update, hlegend});\n          addlistener (hlegend, \"edgecolor\", @cb_legend_text_update);\n          addlistener (hlegend, \"fontangle\", @cb_legend_text_update);\n          addlistener (hlegend, \"fontname\", @cb_legend_text_update);\n          addlistener (hlegend, \"fontweight\", @cb_legend_text_update);\n          addlistener (hlegend, \"textcolor\", @cb_legend_text_update);\n          ## Properties which could change size of box, such as fontsize,\n          ## require legend to be redrawn.\n          ## FIXME: fontsize is changed by print.m function during the\n          ##        production of a plot for output.  This screws things up\n          ##        because legend tries to return the axes size to what it\n          ##        was when the figure was created, versus what it is now\n          ##        when the figure is being printed.  Temporary hack is\n          ##        good enough for generating the Octave manual which still\n          ##        relies on gnuplot for generating images.  See bug #40333.\n          if (! gnuplot)\n            addlistener (hlegend, \"fontsize\", @cb_legend_update);\n          endif\n          addlistener (hlegend, \"fontunits\", @cb_legend_update);\n          addlistener (hlegend, \"interpreter\", @cb_legend_update);\n          addlistener (hlegend, \"location\", @cb_legend_location);\n          addlistener (hlegend, \"orientation\", @cb_legend_update);\n          addlistener (hlegend, \"string\", @cb_legend_update);\n          addlistener (hlegend, \"textposition\", @cb_legend_update);\n          ## FIXME: need to add listeners for tightinset and position\n          ##        addlistener (ca, \"tightinset\", @update????);\n          ##        addlistener (ca, \"position\", @update????);\n        else\n          ## Restore listeners temporarily disabled during reconstruction.\n          addlistener (hlegend, \"location\", @cb_legend_update);\n          addlistener (hlegend, \"orientation\", @cb_legend_update);\n          addlistener (hlegend, \"string\", @cb_legend_update);\n          addlistener (hlegend, \"textposition\", @cb_legend_update);\n        endif\n\n      unwind_protect_cleanup\n        set (hfig, \"currentaxes\", origaxes);\n        if (! isempty (origfig))\n          set (0, \"currentfigure\", origfig);\n        endif\n      end_unwind_protect\n    endif\n  endif\n\n  ## Restore operation of callbacks\n  setappdata (hlegend, \"nocallbacks\", false);\n\n  if (nargout > 0)\n    hleg = hlegend;\n    hleg_obj = hobjects;\n    hplot = hplots;\n    labels = text_strings;\n  endif\n\nendfunction\n\n## Colormap of the base axes has changed.\nfunction cb_legend_colormap_update (cax, ~, hlegend)\n  set (hlegend, \"colormap\", get (cax, \"colormap\"));\nendfunction\n\n## A non-text property of legend has changed requiring an update.\nfunction cb_legend_update (hleg, ~)\n  persistent recursive = false;\n\n  if (! recursive)\n    recursive = true;\n    unwind_protect\n      hax = getappdata (hleg, \"__axes_handle__\");\n      ## Hack.  Maybe store this somewhere else such as appdata.\n      hplots = get (hleg, \"deletefcn\"){6};\n      text_strings = get (hleg, \"string\");\n      position = get (hleg, \"unmodified_axes_position\");\n      outerposition = get (hleg, \"unmodified_axes_outerposition\");\n      units = get (hax, \"units\");\n      set (hax, \"units\", \"points\");\n      switch (get (hax, \"positionconstraint\"))\n        case \"innerposition\"\n          set (hax, \"outerposition\", outerposition, \"position\", position);\n        case \"outerposition\"\n          set (hax, \"position\", position, \"outerposition\", outerposition);\n      endswitch\n      if (isscalar (hax))\n        set (hax, \"units\", units);\n      else\n        set (hax, {\"units\"}, units);\n      endif\n\n      hleg = legend (hax(1), hplots, text_strings);\n    unwind_protect_cleanup\n      recursive = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\n## A text property of legend, such as fontname, has changed.\nfunction cb_legend_text_update (hleg, ~)\n\n  kids = get (hleg, \"children\");\n  htext = kids(strcmp (get (kids, \"type\"), \"text\"));\n\n  tprops = {\"fontangle\", \"fontname\", \"fontweight\", \"color\"};\n  lprops = {\"fontangle\", \"fontname\", \"fontweight\", \"textcolor\"};\n  set (htext, tprops, get (hleg, lprops));\n\n  ec = get (hleg, \"edgecolor\");\n  set (hleg, \"xcolor\", ec, \"ycolor\", ec);\n\nendfunction\n\n## The legend \"visible\" property has changed.\nfunction cb_legend_hideshow (hleg, ~, ca, orig_pos, new_pos)\n\n  isvisible = strcmp (get (hleg, \"visible\"), \"on\");\n\n  ## FIXME: Can't use a single set() call because of linked axes and\n  ##        listeners on plotyy graphs.\n  ca = ca(isaxes (ca));\n  for cax = ca(:).'\n    units = get (cax, \"units\");\n    unwind_protect\n      set (cax, \"units\", \"points\");\n      if (isvisible)\n        set (cax, \"position\", new_pos);\n      else\n        set (cax, \"position\", orig_pos);\n      endif\n    unwind_protect_cleanup\n      set (cax, \"units\", units);\n    end_unwind_protect\n  endfor\n\nendfunction\n\n## The legend \"location\" property has changed.\nfunction cb_legend_location (hleg, ~)\n\n  ## If it isn't \"none\", which means manual positioning, then rebuild.\n  if (! strcmp (get (hleg, \"location\"), \"none\"))\n    cb_legend_update (hleg, []);\n  endif\n\nendfunction\n\n## Axes to which legend was attached is being deleted/reset.  Delete legend.\nfunction cb_axes_deleted (~, ~, ca, hlegend)\n\n  if (isaxes (hlegend))\n    if (strcmp (get (ca(1), \"beingdeleted\"), \"on\"))\n      ## Axes are being deleted.  Disable call to cb_restore_axes.\n      set (hlegend, \"deletefcn\", []);\n    endif\n    delete (hlegend);\n  endif\n\nendfunction\n\n## Restore position of axes object when legend is deleted.\nfunction cb_restore_axes (~, ~, ca, pos, outpos, htdel, hplots)\n\n  hf = ancestor (ca(1), \"figure\");\n  if (strcmp (get (hf, \"beingdeleted\"), \"on\")\n      || strcmp (get (ca(1), \"beingdeleted\"), \"on\"))\n    ## Skip restoring axes if entire figure or axes is being destroyed.\n    return;\n  endif\n\n  ## Remove text object used to trigger legend delete when axes is deleted\n  if (ishghandle (htdel))\n    set (htdel, \"deletefcn\", []);\n    delete (htdel);\n  endif\n\n  ## Restore original axes positions\n  if (! isempty (pos))\n    ## FIXME: can't use single call to set() because of weirdness w/plotyy\n    for cax = ca(:).'\n      if (isaxes (cax))\n        units = get (cax, \"units\");\n        unwind_protect\n          set (cax, \"units\", \"points\", \"position\", pos);\n        unwind_protect_cleanup\n          set (cax, \"units\", units);\n        end_unwind_protect\n      endif\n    endfor\n  endif\n\n  ## Remove listeners from plot objects\n  for i = 1 : numel (hplots)\n    if (isgraphics (hplots(i), \"line\"))\n      dellistener (hplots(i), \"color\");\n      dellistener (hplots(i), \"linestyle\");\n      dellistener (hplots(i), \"linewidth\");\n      dellistener (hplots(i), \"marker\");\n      dellistener (hplots(i), \"markeredgecolor\");\n      dellistener (hplots(i), \"markerfacecolor\");\n      dellistener (hplots(i), \"markersize\");\n      dellistener (hplots(i), \"displayname\");\n    endif\n  endfor\n\n  ## Nullify legend link (can't delete properties yet)\n  set (ca(1), \"__legend_handle__\", []);\n\nendfunction\n\n## Update legend item because underlying plot line object has changed.\nfunction cb_line_listener (h, ~, hlegend, linelength, update_name)\n\n  ## Don't execute callbacks when legend is under construction\n  legdata = getappdata (hlegend);\n  if (legdata.nocallbacks)\n    return;\n  endif\n\n  if (update_name)\n    ## When string changes, have to rebuild legend completely\n    [hplots, text_strings] = __getlegenddata__ (hlegend);\n    if (isempty (hplots))\n      delete (hlegend);\n    else\n      legend (legdata.handle(1), hplots, text_strings);\n    endif\n  else\n    kids = get (hlegend, \"children\");\n    kids = kids([getappdata(kids, \"handle\"){:}] == h);\n    kids = kids(strcmp (get (kids, \"type\"), \"line\"));\n    idx = strcmp (get (kids, \"marker\"), \"none\");\n    ll = kids (idx);\n    lm = kids (! idx);\n\n    [linestyle, marker, displayname] = ...\n      get (h, {\"linestyle\", \"marker\", \"displayname\"}){:};\n\n    if (! isempty (ll))\n      [xpos1, ypos1] = get (ll, {\"xdata\", \"ydata\"}){:};\n      xpos2 = sum (xpos1) / 2;\n      ypos2 = ypos1(1);\n      delete (ll);\n      if (! isempty (lm))\n        delete (lm);\n      endif\n    else\n      [xpos2, ypos2] = get (lm, {\"xdata\", \"ydata\"}){:};\n      xpos1 = xpos2 + [-0.5, 0.5] * linelength;\n      ypos1 = [ypos2, ypos2];\n      delete (lm);\n    endif\n\n    if (! strcmp (linestyle, \"none\"))\n      hl = __go_line__ (hlegend, \"xdata\", xpos1, \"ydata\", ypos1,\n                        \"color\", get (h, \"color\"),\n                        \"linestyle\", get (h, \"linestyle\"),\n                        \"linewidth\", min (get (h, \"linewidth\"), 5),\n                        \"marker\", \"none\");\n      setappdata (hl, \"handle\", h);\n    endif\n    if (! strcmp (marker, \"none\"))\n      hl = __go_line__ (hlegend, \"xdata\", xpos2, \"ydata\", ypos2, ...\n                        \"color\", get (h, \"color\"), ...\n                        \"marker\", marker, ...\n                        \"markeredgecolor\", get (h, \"markeredgecolor\"), ...\n                        \"markerfacecolor\", get (h, \"markerfacecolor\"), ...\n                        \"markersize\", min (get (h, \"markersize\"), 10), ...\n                        \"linestyle\", \"none\", ...\n                        \"linewidth\", min (get (h, \"linewidth\"), 5));\n      setappdata (hl, \"handle\", h);\n    endif\n  endif\n\nendfunction\n\n\n## FIXME: demo blocks can not be run for files in private/ directories.\n%!demo\n%! clf;\n%! plot (rand (2));\n%! title (\"legend called with string inputs for labels\");\n%! h = legend (\"foo\", \"bar\");\n%! legend (h, \"location\", \"northeastoutside\");\n%! set (h, \"fontsize\", 20);\n\n%!demo\n%! clf;\n%! plot (rand (2));\n%! title (\"legend called with cell array of strings\");\n%! h = legend ({\"cellfoo\", \"cellbar\"});\n%! legend (h, \"location\", \"northeast\");\n%! set (h, \"fontsize\", 20);\n\n%!demo\n%! clf;\n%! plot (rand (3));\n%! title (\"legend () without inputs creates default labels\");\n%! h = legend ();\n\n%!demo\n%! clf;\n%! x = 0:1;\n%! plot (x,x,\";I am Blue;\", x,2*x, x,3*x,\";I am yellow;\");\n%! h = legend (\"location\", \"northeastoutside\");\n%! ## Placing legend inside returns axes to original size\n%! legend (h, \"location\", \"northeast\");\n%! title (\"Blue and Yellow keys, with Orange missing\");\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"incline is blue and decline is orange\");\n%! legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend hide\n%! legend show\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"Legend with keys in horizontal orientation\");\n%! legend ({\"I am blue\", \"I am orange\"}, ...\n%!         \"location\", \"east\", \"orientation\", \"horizontal\");\n%! legend boxoff\n%! legend boxon\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"Legend with box off\");\n%! legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend boxoff\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"Legend with text to the left of key\");\n%! legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend left\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title ({\"Use properties to place legend text to the left of key\", ...\n%!         \"Legend text color is magenta\"});\n%! h = legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend (\"right\");\n%! set (h, \"textposition\", \"left\");\n%! set (h, \"textcolor\", [1 0 1]);\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10, 1:10, fliplr (1:10));\n%! title (\"Legend is hidden\");\n%! legend ({\"I am blue\", \"I am orange\"}, \"location\", \"east\");\n%! legend hide\n\n%!demo\n%! clf;\n%! x = 0:1;\n%! plot (x,x,\";I am Blue;\", x,2*x,\";I am Orange;\", x,3*x,\";I am Yellow;\");\n%! title ({\"Labels are embedded in call to plot\", ...\n%!         \"Legend is hidden and then shown\"});\n%! legend boxon\n%! legend hide\n%! legend show\n\n%!demo\n%! clf;\n%! x = 0:1;\n%! plot (x,x,  x,2*x,  x,3*x);\n%! title (\"Labels with interpreted Greek text\");\n%! h = legend ('\\alpha', '\\beta=2\\alpha', '\\gamma=3\\alpha');\n%! set (h, \"interpreter\", \"tex\");\n\n%!demo\n%! clf;\n%! plot (rand (2));\n%! title (\"Labels with TeX interpreter turned off\");\n%! h = legend (\"Hello_World\", \"foo^bar\");\n%! set (h, \"interpreter\", \"none\");\n\n%!demo\n%! clf;\n%! labels = {};\n%! colororder = get (gca, \"colororder\");\n%! for i = 1:5\n%!   h = plot (1:100, i + rand (100,1)); hold on;\n%!   set (h, \"color\", colororder(i,:));\n%!   labels = {labels{:}, [\"Signal \", num2str(i)]};\n%! endfor\n%! hold off;\n%! title ({\"Signals with random offset and uniform noise\";\n%!         \"Legend shown below and outside of plot\"});\n%! xlabel (\"Sample Nr [k]\"); ylabel (\"Amplitude [V]\");\n%! legend (labels, \"location\", \"southoutside\");\n\n%!demo\n%! clf;\n%! x = linspace (0, 10);\n%! plot (x, x);\n%! hold on;\n%! stem (x, x.^2, \"g\");\n%! title (\"First created object gets first label\");\n%! legend (\"linear\");\n%! hold off;\n\n%!demo\n%! clf;\n%! x = linspace (0, 10);\n%! plot (x, x, x, x.^2);\n%! title (\"First created object gets first label\");\n%! legend (\"linear\");\n\n%!demo\n%! clf;\n%! x = linspace (0, 10);\n%! plot (x, x, x, x.^2);\n%! title (\"Labels are applied in order of object creation\");\n%! legend (\"linear\", \"quadratic\");\n\n%!demo\n%! clf;\n%! subplot (2,1,1);\n%! rand_2x3_data1 = [0.341447, 0.171220, 0.284370; 0.039773, 0.731725, 0.779382];\n%! bar (rand_2x3_data1);\n%! ylim ([0 1.0]);\n%! title (\"legend() works for bar graphs (hggroups)\");\n%! legend ({\"1st Bar\", \"2nd Bar\", \"3rd Bar\"}, \"location\", \"northwest\");\n%! subplot (2,1,2);\n%! x = linspace (0, 10, 20);\n%! stem (x, 0.5+x.*rand (size (x))/max (x), \"markeredgecolor\", [0 0.7 0]);\n%! hold on;\n%! stem (x+10/(2*20), x.*(1.0+rand (size (x)))/max (x));\n%! xlim ([0 10+10/(2*20)]);\n%! title (\"legend() works for stem plots (hggroups)\");\n%! legend ({\"Multicolor\", \"Unicolor\"}, \"location\", \"northwest\");\n\n%!demo\n%! clf;\n%! colormap (cool (64));\n%! surf (peaks ());\n%! legend (\"peaks()\");\n%! title (\"legend() works for surface objects too\");\n\n%!demo\n%! clf reset;  # needed to undo colormap assignment in previous demo\n%! rand_2x3_data2 = [0.44804, 0.84368, 0.23012; 0.72311, 0.58335, 0.90531];\n%! bar (rand_2x3_data2);\n%! ylim ([0 1.2]);\n%! title ('\"left\" option places colors to the left of text label');\n%! legend (\"1st Bar\", \"2nd Bar\", \"3rd Bar\");\n%! legend left;\n\n%!demo\n%! clf;\n%! x = 0:0.1:7;\n%! h = plot (x,sin (x), x,cos (x), x,sin (x.^2/10), x,cos (x.^2/10));\n%! title (\"Only the sin() objects have keylabels\");\n%! legend (h([1, 3]), {\"sin (x)\", \"sin (x^2/10)\"}, \"location\", \"southwest\");\n\n%!demo\n%! clf;\n%! x = 0:0.1:10;\n%! plot (x, sin (x), \";sin (x);\");\n%! hold on;\n%! plot (x, cos (x), \";cos (x);\");\n%! hold off;\n%! title (\"legend constructed from multiple plot calls\");\n\n%!demo\n%! clf;\n%! x = 0:0.1:10;\n%! plot (x, sin (x), \";sin (x);\");\n%! hold on;\n%! plot (x, cos (x), \";cos (x);\");\n%! hold off;\n%! title (\"Specified label text overrides previous labels\");\n%! legend ({\"Sine\", \"Cosine\"}, \"location\", \"northeastoutside\");\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! plot (x, rand (11));\n%! axis ([0, 10, 0, 1]);\n%! xlabel (\"Indices\");\n%! ylabel (\"Random Values\");\n%! title ('Legend \"off\" deletes the legend');\n%! legend (cellstr (num2str ((0:10)')), \"location\", \"northeastoutside\");\n%! pause (1);\n%! legend off;\n\n%!demo\n%! clf;\n%! x = (1:5)';\n%! subplot (2,2,1);\n%!  plot (x, rand (numel (x)));\n%!  legend (cellstr (num2str (x)), \"location\", \"northwestoutside\");\n%! subplot (2,2,2);\n%!  plot (x, rand (numel (x)));\n%!  legend (cellstr (num2str (x)), \"location\", \"northeastoutside\");\n%! subplot (2,2,3);\n%!  plot (x, rand (numel (x)));\n%!  legend (cellstr (num2str (x)), \"location\", \"southwestoutside\");\n%! subplot (2,2,4);\n%!  plot (x, rand (numel (x)));\n%!  legend (cellstr (num2str (x)), \"location\", \"southeastoutside\");\n%! ## Legend works on a per axes basis for each subplot\n\n%!demo\n%! clf;\n%! plot (rand (2));\n%! title (\"legend() will warn if extra labels are specified\");\n%! legend (\"Hello\", \"World\", \"interpreter\", \"foobar\");\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! y1 = rand (size (x));\n%! y2 = rand (size (x));\n%! [ax, h1, h2] = plotyy (x, y1, x, y2);\n%! title ({\"plotyy legend test #1\", \"Blue label to left axis, Orange label to right axis\"});\n%! drawnow ();\n%! legend (\"Blue\", \"Orange\", \"location\", \"south\");\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! y1 = rand (size (x));\n%! y2 = rand (size (x));\n%! [ax, h1, h2] = plotyy (x, y1, x, y2);\n%! ylabel (ax(1), {\"Blue\", \"Y\", \"Axis\"});\n%! title ('plotyy legend test #2: \"westoutside\" adjusts to ylabel');\n%! drawnow ();\n%! legend ([h1, h2], {\"Blue\", \"Orange\"}, \"location\", \"westoutside\");\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! y1 = rand (size (x));\n%! y2 = rand (size (x));\n%! [ax, h1, h2] = plotyy (x, y1, x, y2);\n%! ylabel (ax(2), {\"Orange\", \"Y\", \"Axis\"});\n%! title ('plotyy legend test #3: \"eastoutside\" adjusts to ylabel');\n%! drawnow ();\n%! legend ([h1, h2], {\"Blue\", \"Orange\"}, \"location\", \"eastoutside\");\n\n%!demo\n%! clf;\n%! plot (1:10, 1:10);\n%! title (\"a very long label can sometimes cause problems\");\n%! legend (\"hello very big world\", \"location\", \"northeastoutside\");\n\n%!demo  # bug 36408\n%! clf;\n%! option = \"right\";\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  xlabel xlabel;\n%!  ylabel ylabel;\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northeastoutside\");\n%!  legend (option);\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  xlabel xlabel;\n%!  ylabel ylabel;\n%!  legend ({\"1234567890\"}, \"location\", \"eastoutside\");\n%!  legend (option);\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  xlabel xlabel;\n%!  ylabel ylabel;\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southeastoutside\");\n%!  legend (option);\n\n%!demo  # bug 36408\n%! clf;\n%! option = \"right\";\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northwestoutside\");\n%!  legend (option);\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  legend ({\"1234567890\"}, \"location\", \"westoutside\");\n%!  legend (option);\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southwestoutside\");\n%!  legend (option);\n\n%!demo  # bug 36408\n%! clf;\n%! option = \"right\";\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northeastoutside\");\n%!  legend (option);\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"1234567890\"}, \"location\", \"eastoutside\");\n%!  legend (option);\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southeastoutside\");\n%!  legend (option);\n\n%!demo  # bug 36408\n%! clf;\n%! option = \"right\";\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northwestoutside\");\n%!  legend (option);\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"1234567890\"}, \"location\", \"westoutside\");\n%!  legend (option);\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  set (gca (), \"yaxislocation\", \"right\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southwestoutside\");\n%!  legend (option);\n\n%!demo  # bug 36408;\n%! clf;\n%! option = \"right\";\n%! subplot (3,1,1);\n%!  plot (rand (1,4));\n%!  set (gca (), \"xaxislocation\", \"top\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  title (\"Subplots adjust to the legend placed outside\");\n%!  legend ({\"1\"}, \"location\", \"northwestoutside\");\n%!  legend (option);\n%! subplot (3,1,2);\n%!  plot (rand (1,4));\n%!  set (gca (), \"xaxislocation\", \"top\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"1234567890\"}, \"location\", \"westoutside\");\n%!  legend (option);\n%! subplot (3,1,3);\n%!  plot (rand (1,4));\n%!  set (gca (), \"xaxislocation\", \"top\");\n%!  xlabel (\"xlabel\");\n%!  ylabel (\"ylabel\");\n%!  legend ({\"12345678901234567890\"}, \"location\", \"southwestoutside\");\n%!  legend (option);\n\n%!demo  # bug 39697\n%! clf;\n%! plot (1:10);\n%! legend (\"Legend Text\");\n%! title ({\"Multi-line\", \"titles\", \"are a\", \"problem\", \"See bug #39697\"});\n\n%!testif ; any (strcmp (\"gnuplot\", available_graphics_toolkits ()))\n%! toolkit = graphics_toolkit (\"gnuplot\");\n%! h = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   position = get (h, \"position\");\n%!   plot (rand (3));\n%!   legend ();\n%!   filename = sprintf (\"%s.eps\", tempname ());\n%!   print (filename);\n%!   unlink (filename);\n%!   assert (get (h, \"position\"), position);\n%! unwind_protect_cleanup\n%!   close (h);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n%!test <*42035>\n%! h = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax1 = subplot (1,2,1);\n%!   plot (1:10);\n%!   hax2 = subplot (1,2,2);\n%!   plot (1:10);\n%!   hleg1 = legend (hax1, \"foo\");\n%!   assert (getappdata (hleg1, \"__axes_handle__\"), hax1);\n%!   assert (gca (), hax2);\n%!   hleg2 = legend (\"bar\");\n%!   assert (getappdata (hleg2, \"__axes_handle__\"), gca ());\n%! unwind_protect_cleanup\n%!   close (h);\n%! end_unwind_protect\n\n%!test\n%! ## Difficult example from plotyy demo #1\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   x = 0:0.1:2*pi;\n%!   y1 = sin (x);\n%!   y2 = exp (x - 1);\n%!   hax = plotyy (x,y1, x-1,y2, @plot, @semilogy);\n%!   text (0.5, 0.5, \"Left Axis\", \"parent\", hax(1));\n%!   text (4.5, 80, \"Right Axis\", \"parent\", hax(2));\n%!   hleg = legend (\"show\");\n%!   assert (get (hleg, \"string\"), {\"data1\", \"data2\"});\n%!   fail (\"legend ('foo', 'bar', 'baz')\", \"warning\", \"ignoring extra labels\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Test warnings about objects to label\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"legend ('foobar')\", \"warning\", \"plot data is empty\");\n%!   ht = text (0.5, 0.5, \"Hello World\");\n%!   fail (\"legend ('foobar')\", \"warning\", \"plot data is empty\");\n%!   lastwarn (\"\");   # clear warning\n%!   hleg = legend ();\n%!   assert (isempty (hleg) && isempty (lastwarn ()));\n%!   fail (\"legend ('foobar')\", \"warning\", \"plot data is empty\");\n%!   hln = line ([0 1], [0 1]);\n%!   fail (\"legend ('foo', 'bar')\", \"warning\", \"ignoring extra labels\");\n%!   plot (rand (2, 21));\n%!   fail (\"legend ()\", \"warning\", \"labeling only first 20 data objects\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Test warnings about unsupported features\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   fail (\"legend ('location','best')\", \"warning\", \"'best' not yet implemented\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/private/__tickangle__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{retval} =} __tickangle__ (@var{caller}, @var{hax}, @var{angle})\n## Undocumented internal function.\n## @seealso{xtickangle, ytickangle, ztickangle}\n## @end deftypefn\n\nfunction retval = __tickangle__ (caller, hax, angle)\n\n  ax = lower (caller(1));\n  switch (nargin)\n    case 1\n      retval = get (gca (), [ax, \"ticklabelrotation\"]);\n      return;\n\n    case 2\n      if (isaxes (hax))\n        retval = get (hax, [ax, \"ticklabelrotation\"]);\n        return;\n      else\n        angle = hax;\n        hax = [];\n      endif\n\n    case 3\n      if (! isaxes (hax))\n        error ([caller, \": HAX must be a handle to an axes object\"]);\n      endif\n\n  endswitch\n\n  if (! (isscalar (angle) && isnumeric (angle) && isfinite (angle)))\n    error ([caller \": ANGLE must be a finite, numeric, scalar value\"]);\n  elseif (nargout > 0)\n    error ([caller \": function called with output query and input set value\"]);\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  set (hax, [ax, \"ticklabelrotation\"], angle);\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/appearance/rticklabels.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{labels} =} rticklabels\n## @deftypefnx {} {} rticklabels (@var{tickval})\n## @deftypefnx {} {@dots{} =} rticklabels (@var{hax}, @dots{})\n## Query or set the tick labels on the r-axis of a polar plot.\n##\n## When called without an argument, return a cell array of strings of the\n## current rtick labels.\n##\n## When called with the argument @var{tickval} being a vector of numbers or\n## a cell array of strings and/or numbers, the labels will be changed to\n## match these new values.  Note that the center point of the plots made by\n## @code{polar} are never labeled, so the first specified label will be\n## applied to the second rtick location and subsequent labels will progress\n## outward.\n##\n## If fewer labels are specified than the current number of tick marks, those\n## labels will be applied starting with the innermost tick labels, and blank\n## labels will be appended to the remainder.  If the specified label count\n## exceeds the number of tick labels, the excess labels are ignored.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{rticklabels} to set a property\n## value will result in an error.\n##\n## Compatibility Note: The @qcode{'mode'} property for rticklabels has not yet\n## been implemented.\n##\n## @seealso{polar, rticks, thetaticklabels, xticklabels, yticklabels,\n## zticklabels, get, set}\n## @end deftypefn\n\n## FIXME: Octave's polar plot implementation does not currently create the\n##        properties rticklabel, rticklabelmode, and rtickmode.  Fully\n##        implemented versions of those proporties could simplify much of the\n##        code below, which could then mimick much the behavior of the\n##        equivalent Cartesian functions.\n\nfunction labels = rticklabels (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"rticklabels\", varargin{:});\n\n  if (nargin > 1)\n    print_usage;\n  endif\n\n  returnlabels = true;\n\n  if (nargin > 0)\n    ## Single remaining input must be tick labels and should be a numeric\n    ## vector or a cell vector of numbers and strings.\n\n    ## Error if trying to request and set values simultaneously.\n    if (nargout > 0)\n      error (\"rticklabels: cannot set and return labels simultaneously\");\n    endif\n\n    returnlabels = false;\n    arg = varargin{1};\n\n    if (isnumeric (arg))\n      ## All inputs handled the same way as cells. (:) permits nonvectors.\n      cellarg_num = ones (1, numel (arg));\n      cellarg_char = zeros (1, numel (arg));\n      arg = num2cell (arg(:));\n\n    elseif (iscell (arg))\n      if (! all (  (cellarg_num = cellfun ('isnumeric', arg))\n                 | (cellarg_char = cellfun ('ischar', arg))))\n        error (\"rticklabels: TICKVAL cell must contain numbers or strings\");\n      endif\n    else\n      error (\"rticklabels: TICKVAL must be numeric or a cell containing numbers and strings\");\n    endif\n\n    ## Finish converting TICKVAL into a cellstr.\n    ## Convert numeric elements to characters and make it a 1-D cell array.\n    arg(cellarg_num) = cellfun ('num2str', arg(cellarg_num), ...\n                                \"UniformOutput\", false);\n    arg = arg(:);\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  ## Error if hax does not point to a polar plot.\n  polarhandle = findall (hax, \"tag\", \"polar_grid\");\n  if (isempty (polarhandle))\n    error (\"rticklabels: rticklabels can only be used on a polar plot\");\n  elseif (! isfield (get (hax), \"rtick\") )\n    error (\"rticklabels: rtick property not defined for current axes\");\n  endif\n\n  ## Get count of radius and theta curves.\n  nr = numel (get (hax, \"rtick\")); # Must check if it includes unlabeled center.\n  nt = numel (get (hax, \"ttick\"));\n  rt_label_handles = get (polarhandle, \"children\");\n\n  ## Center is never labeled in polar plots.\n  ## If rtick does not include unlabled center, label_count = 2*nr+2*nt-1,\n  ## otherwise label_count = 2*nr+2*nt+1 and nr should be reduced by 1\n  ## to prevent attempts to get label value from nonlabel handle.\n  if (2 * (nr + nt) + 1 > numel (rt_label_handles))\n    nr--;\n  endif\n\n  ## rtick and ttick object ordering:\n  ##  1:nt = text handles containing theta labels (reverse order)\n  ##  nt+1:2*nt = line object handles for ttick radial grid lines\n  ##  2*nt+1:2*nt+nr = text handles containing nr rtick labels (reverse order)\n  ##  2*nt+nr+1:2*nt+2*nr = line object handles for rtick circles\n  ##  end = patch object handle for darker outside border\n  rlabelrange = 2*nt + [nr:-1:1];  # Flip back to increasing order.\n\n  if (nargin == 0)\n    ## Get radius labels.\n    labels = get (rt_label_handles(rlabelrange), \"string\");\n\n  else\n    ## Set new label values.\n\n    if (isempty (arg))\n      ## If an empty cell or array is set, set all labels to \"\".\n      arg = cell (nr, 1);\n      arg(:) = {\"\"};\n\n    else\n      ## Pad and trim arg as needed to match number of labels.\n      if (nr < numel (arg))\n        arg (nr + 1 : end) = [];\n      else\n        arg(end + 1 : nr) = {\"\"};\n      endif\n    endif\n\n    ## Replace labels with values from arg, ensure column vector.\n    set (rt_label_handles(rlabelrange), {\"string\"}, arg(:));\n  endif\n\nendfunction\n\n\n%!test\n%! t = [0:15:180] * pi / 180;\n%! r = sin (t);\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hp = polar (t, r);\n%!   hax = gca ();\n%!   rticks (hax, [0, 0.5, 1]);\n%!   assert (rticklabels (hax), {\"0.5\"; \"1\"});\n%!   rticklabels (hax, [1 2]);\n%!   assert (rticklabels (hax), {\"1\"; \"2\"});\n%!   rticklabels (hax, [3 4]');\n%!   assert (rticklabels (hax), {\"3\"; \"4\"});\n%!   rticklabels (hax, {5, 6});\n%!   assert (rticklabels (hax), {\"5\"; \"6\"});\n%!   rticklabels (hax, {\"a\", \"bee\"});\n%!   assert (rticklabels (hax), {\"a\"; \"bee\"});\n%!   rticklabels (hax, {1, \"two\"});\n%!   assert (rticklabels (hax), {\"1\"; \"two\"});\n%!   rticklabels (hax, {1, 2, 3, 4});\n%!   assert (rticklabels (hax), {\"1\"; \"2\"});\n%!   rticklabels (hax, [5, 6, 7, 8]);\n%!   assert (rticklabels (hax), {\"5\"; \"6\"});\n%!   rticklabels (hax, {1});\n%!   assert (rticklabels (hax), {\"1\"; \"\"});\n%!   rticklabels (hax, {1,2});\n%!   assert (rticklabels (hax), {\"1\"; \"2\"});\n%!   rticklabels (hax, []);\n%!   assert (rticklabels (hax), {\"\"; \"\"});\n%!   rticklabels (hax, {1,2});\n%!   assert (rticklabels (hax), {\"1\"; \"2\"});\n%!   rticklabels (hax, {});\n%!   assert (rticklabels (hax), {\"\"; \"\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n\n## Test input validation\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"rticklabels (1,2,3)\", \"Invalid call\");\n%!   fail (\"rticklabels (-1, 2)\", \"Invalid call\");\n%!   fail (\"rticklabels (hax, 2, 3)\", \"Invalid call\");\n%!   fail (\"rticklabels (hf, 2)\", \"Invalid call\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"tmp = rticklabels ([1, 2, 3])\", \"cannot set and return labels simultaneously\");\n%!   fail (\"tmp = rticklabels (hax, [1, 2, 3])\", \"cannot set and return labels simultaneously\");\n%!   fail (\"rticklabels (hax, {{1}, 'two', 3})\", \"TICKVAL cell must contain numbers or strings\");\n%!   fail (\"rticklabels (hax, {1, 'two', false})\", \"TICKVAL cell must contain numbers or strings\");\n%!   fail (\"rticklabels (hax, {1, struct()})\", \"TICKVAL cell must contain numbers or strings\");\n%!   fail (\"rticklabels (hax, struct())\", \"TICKVAL must be numeric or a cell containing\");\n%!   fail (\"rticklabels (hax, [true false])\", \"TICKVAL must be numeric or a cell containing\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! t = [0:45:180] * pi / 180;\n%! r = sin (t);\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hp = plot (t, r);\n%!   hax = gca ();\n%!   fail (\"rticklabels (hax, 1)\", \"rticklabels can only be used on a polar plot\");\n%!   fail (\"rticklabels ({1})\", \"rticklabels can only be used on a polar plot\");\n%!   hp = polar (t, r);\n%!   hax = gca ();\n%!   delete (findall (hax, \"tag\", \"polar_grid\"));\n%!   fail (\"rticklabels (hax, 1)\", \"rticklabels can only be used on a polar plot\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/rticks.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tickval} =} rticks\n## @deftypefnx {} {} rticks (@var{tickval})\n## @deftypefnx {} {@dots{} =} rticks (@var{hax}, @dots{})\n## Query or set the tick values on the r-axis of the current axis.\n##\n## When called without argument, return the current tick locations as specified\n## in the @qcode{\"rtick\"} axes property.  These locations can be changed by\n## calling @code{rticks} with a vector of tick values.  Note: ascending order\n## is not required.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{rticks} to set a property value\n## will result in an error.\n##\n## NOTE: Octave does not currently implement polaraxes objects.  It is\n## therefore not possible to query or set a @qcode{\"mode\"} for the\n## @qcode{\"rtick\"} property as can be done with the equivalent functions for\n## @var{x}, @var{y}, and @var{z} axes.\n##\n## @seealso{thetaticks, xticks, yticks, zticks, polar, get, set}\n## @end deftypefn\n\nfunction tickval = rticks (varargin)\n\n  hax = [];\n  switch (nargin)\n    case 0\n      tickval = get (gca (), \"rtick\");  # will error if no rtick exists.\n      return;\n\n    case 1\n      if (isaxes (varargin{1}))\n        tickval = get (varargin{1}, \"rtick\");\n        return;\n      else\n        arg = varargin{1};\n      endif\n\n    case 2\n      if (! isaxes (varargin{1}))\n        error (\"rticks: HAX must be a handle to an axes object\");\n      endif\n      hax = varargin{1};\n      arg = varargin{2};\n\n    otherwise\n      print_usage ();\n\n  endswitch\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (isnumeric (arg))\n    if (nargout > 0)\n      error (\"rticks: too many output arguments requested\");\n    endif\n    ## NOTE: Matlab errors if tick points are not in ascending order.  Octave\n    ## permits out of order tick points, so no error is produced.\n    set (hax, \"rtick\", arg);\n\n  elseif (ischar (arg))\n    error (\"rticks: MODE is not yet implemented for the rtick property\");\n\n    ## FIXME: Enable mode args if/when they are available in polar/polarplot\n    ## arg = lower (arg);\n    ## switch (arg)\n    ##   case \"mode\"\n    ##     tickval = get (hax, \"rtickmode\");\n    ##\n    ##   case {\"auto\", \"manual\"}\n    ##     if (nargout > 0)\n    ##       error ([\"rticks: \" ...\n    ##               \"too many output arguments requested for arg: \", arg]);\n    ##     endif\n    ##     set (hax, \"rtickmode\", arg);\n    ##\n    ##   otherwise\n    ##     error (\"rticks: invalid option: %s\", arg);\n    ##\n    ## endswitch\n\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   polar (linspace (0, pi, 20), rand (20,1));\n%!   hax = gca ();\n%!   ticks = rticks;\n%!   assert (rticks (hax), ticks);\n%!   rticks (hax, [0 0.25 0.75 1 2]);\n%!   assert (rticks (hax), [0 0.25 0.75 1 2]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error rticks (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   polar (linspace (0, pi, 20), 1:20);\n%!   hax = gca ();\n%!   fail (\"rticks (-1, [0 1])\", \"HAX must be a handle to an axes\");\n%!   fail (\"tmp = rticks (hax, [0 1])\", \"too many output arguments\");\n%!   fail (\"tmp = rticks (hax, 'mode')\", \"MODE is not yet implemented\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/shading.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} shading (@var{type})\n## @deftypefnx {} {} shading (@var{hax}, @var{type})\n## Set the shading of patch or surface graphic objects.\n##\n## Valid arguments for @var{type} are\n##\n## @table @asis\n## @item @qcode{\"flat\"}\n## Single colored patches with invisible edges.\n##\n## @item @qcode{\"faceted\"}\n## Single colored patches with black edges.\n##\n## @item @qcode{\"interp\"}\n## Colors between patch vertices are interpolated and the patch edges are\n## invisible.\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n## @seealso{fill, mesh, patch, pcolor, surf, surface, hidden, lighting}\n## @end deftypefn\n\nfunction shading (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"shading\", varargin{:});\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  mode = varargin{1};\n  if (! ischar (mode))\n    error (\"shading: MODE must be a valid string\");\n  elseif (! any (strcmpi (mode, {\"flat\", \"interp\", \"faceted\"})))\n    error ('shading: Invalid MODE \"%s\"', mode);\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  ## Find all patch and surface objects that are descendants of hax\n  ## and which are not part of a contour plot hggroup.\n  hlist = [];\n  kids = get (hax, \"children\");\n  while (! isempty (kids))\n    types = get (kids, \"type\");\n    hlist = [hlist; kids(strcmp(types, \"patch\"))];\n    hlist = [hlist; kids(strcmp(types, \"surface\"))];\n    parents = kids(strcmp (types, \"axes\"));\n    hglist = kids(strcmp (types, \"hggroup\"));\n    for i = 1 : numel (hglist)\n      props = get (hglist(i));\n      if (! isfield (props, \"levelstep\"))\n        parents(end+1) = hglist(i);\n      endif\n    endfor\n    if (numel (parents) <= 1)\n      kids = get (parents, \"children\");\n    else\n      ## See bug #55993 where multiple hggroups caused failure.\n      kids = get (parents, \"children\");\n      kids = [kids{:}](:);  # convert cell array to column vector of handles\n    endif\n\n  endwhile\n\n  ## NOTE: This is the old, simple code.\n  ##       Unfortunately, it also shades contour plots which is not desirable.\n  ## hp = findobj (hax, \"type\", \"patch\");\n  ## hs = findobj (hax, \"type\", \"surface\");\n  ## hlist = [hp(:); hs(:)];\n\n  if (isempty (hlist))\n    return;\n  endif\n\n  ## Change \"EdgeColor\" for meshes instead of \"FaceColor\"\n  fc = get (hlist, \"facecolor\");\n  is_mesh = strcmp (fc, \"none\");\n  if (! iscell (fc))\n    fc = {fc};\n  endif\n  bg = get (hax, \"color\");\n  if (strcmp (bg, \"none\"))\n    if (isprop (get (hax, \"parent\"), \"color\"))\n      bg = get (get (hax, \"parent\"), \"color\");\n    endif\n    if (isempty (bg) || strcmp (bg, \"none\"))\n      bg = [1 1 1];\n    endif\n  endif\n  is_mesh |= cellfun (@(x) isequal (x, bg), fc);\n\n  ec = \"none\";\n  if (strcmpi (mode, \"faceted\"))\n    ec = [0 0 0];\n    mode = \"flat\";\n  endif\n\n  set (hlist(! is_mesh), \"facecolor\", mode, \"edgecolor\", ec);\n  set (hlist(is_mesh), \"edgecolor\", mode);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! sombrero ();\n%! shading faceted;\n%! title ('shading ''faceted''');\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! sombrero ();\n%! shading faceted;\n%! h = findobj (gca (), \"type\", \"surface\");\n%! facecolor = get (h, \"facecolor\");\n%! edgecolor = get (h, \"edgecolor\");\n%! set (h, \"edgecolor\", facecolor, \"facecolor\", edgecolor);\n%! title ({'shading ''faceted''', 'with \"edgecolor\" and \"facecolor\" reversed'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! sombrero ();\n%! shading flat;\n%! title ('shading ''flat''');\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! sombrero ();\n%! shading flat;\n%! h = findobj (gca (), \"type\", \"surface\");\n%! facecolor = get (h, \"facecolor\");\n%! edgecolor = get (h, \"edgecolor\");\n%! set (h, \"edgecolor\", facecolor, \"facecolor\", edgecolor);\n%! title ({'shading ''flat''', 'with \"edgecolor\" and \"facecolor\" reversed'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! sombrero ();\n%! shading interp;\n%! title ('shading ''interp''');\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! sombrero ();\n%! shading interp;\n%! h = findobj (gca (), \"type\", \"surface\");\n%! facecolor = get (h, \"facecolor\");\n%! edgecolor = get (h, \"edgecolor\");\n%! set (h, \"edgecolor\", facecolor, \"facecolor\", edgecolor);\n%! title ({'shading ''interp''', 'with \"edgecolor\" and \"facecolor\" reversed'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! peaks ();\n%! shading interp;\n%! h = findobj (gca (), \"type\", \"surface\");\n%! set (h, \"edgecolor\", \"k\");\n%! title ({'shading ''interp''', 'with \"edgecolor\" set to black'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! pcolor (peaks ());\n%! shading faceted;\n%! title ('shading ''faceted''');\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! pcolor (peaks ());\n%! shading faceted;\n%! h = findobj (gca (), \"type\", \"surface\");\n%! facecolor = get (h, \"facecolor\");\n%! edgecolor = get (h, \"edgecolor\");\n%! set (h, \"edgecolor\", facecolor, \"facecolor\", edgecolor);\n%! title ({'shading ''faceted''', 'with \"edgecolor\" and \"facecolor\" reversed'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! pcolor (peaks ());\n%! shading flat;\n%! title ('shading ''flat''');\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! pcolor (peaks ());\n%! shading flat;\n%! h = findobj (gca (), \"type\", \"surface\");\n%! facecolor = get (h, \"facecolor\");\n%! edgecolor = get (h, \"edgecolor\");\n%! set (h, \"edgecolor\", facecolor, \"facecolor\", edgecolor);\n%! title ({'shading ''flat''', 'with \"edgecolor\" and \"facecolor\" reversed'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! pcolor (peaks ());\n%! shading interp;\n%! title ('shading ''interp''');\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! pcolor (peaks ());\n%! shading interp;\n%! h = findobj (gca (), \"type\", \"surface\");\n%! facecolor = get (h, \"facecolor\");\n%! edgecolor = get (h, \"edgecolor\");\n%! set (h, \"edgecolor\", facecolor, \"facecolor\", edgecolor);\n%! title ({'shading ''interp''', 'with \"edgecolor\" and \"facecolor\" reversed'});\n\n%!demo\n%! clf;\n%! colormap ('default');\n%! mesh (sombrero ());\n%! shading interp;\n%! title ('mesh with shading ''interp''');\n\n%!demo\n%! clf;\n%! colormap ('default');\n%! mesh (sombrero ());\n%! shading flat;\n%! title ('mesh with shading ''flat''');\n\n%!test\n%! hf = figure (\"Visible\", \"off\");\n%! unwind_protect\n%!   ha = axes ();\n%!   hm = mesh (sombrero ());\n%!   hp = patch ();\n%!   hs = surface ();\n%!   shading interp;\n%!   assert (get (hp, \"facecolor\"), \"interp\");\n%!   assert (get (hs, \"facecolor\"), \"interp\");\n%!   assert (get (hp, \"edgecolor\"), \"none\");\n%!   assert (get (hs, \"edgecolor\"), \"none\");\n%!   assert (get (hm, \"edgecolor\"), \"interp\");\n%!   shading faceted;\n%!   assert (get (hp, \"facecolor\"), \"flat\");\n%!   assert (get (hs, \"facecolor\"), \"flat\");\n%!   assert (get (hp, \"edgecolor\"), [0 0 0]);\n%!   assert (get (hs, \"edgecolor\"), [0 0 0]);\n%!   assert (get (hm, \"edgecolor\"), \"flat\");\n%!   shading (ha, \"interp\");\n%!   assert (get (hp, \"facecolor\"), \"interp\");\n%!   assert (get (hs, \"facecolor\"), \"interp\");\n%!   assert (get (hp, \"edgecolor\"), \"none\");\n%!   assert (get (hs, \"edgecolor\"), \"none\");\n%!   assert (get (hm, \"edgecolor\"), \"interp\");\n%!   set (hp, \"edgecolor\", \"k\");\n%!   set (hs, \"edgecolor\", \"k\");\n%!   shading flat;\n%!   assert (get (hp, \"facecolor\"), \"flat\");\n%!   assert (get (hs, \"facecolor\"), \"flat\");\n%!   assert (get (hp, \"edgecolor\"), \"none\");\n%!   assert (get (hs, \"edgecolor\"), \"none\");\n%!   assert (get (hm, \"edgecolor\"), \"flat\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test on axes which has no patch or mesh objects\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   shading flat\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <Invalid call> shading ()\n%!error shading (1, 2, \"flat\")\n%!error <MODE must be a valid string> shading (-1)\n%!error <MODE must be a valid string> shading ({})\n%!error <Invalid MODE \"foo\"> shading foo\n"
  },
  {
    "path": "scripts/plot/appearance/specular.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{refl} =} specular (@var{sx}, @var{sy}, @var{sz}, @var{lv}, @var{vv})\n## @deftypefnx {} {@var{refl} =} specular (@var{sx}, @var{sy}, @var{sz}, @var{lv}, @var{vv}, @var{se})\n## Calculate the specular reflection strength of a surface defined by the\n## normal vector elements @var{sx}, @var{sy}, @var{sz} using Phong's\n## approximation.\n##\n## The light source location and viewer location vectors are specified using\n## parameters @var{lv} and @var{vv} respectively.  The location vectors can\n## given as 2-element vectors [azimuth, elevation] in degrees or as 3-element\n## vectors [x, y, z].\n##\n## An optional sixth argument specifies the specular exponent (spread)\n## @var{se}.  If not given, @var{se} defaults to 10.\n## @seealso{diffuse, surfl}\n## @end deftypefn\n\nfunction refl = specular (sx, sy, sz, lv, vv, se)\n\n  if (nargin < 5)\n    print_usage ();\n  endif\n\n  ## Check normal vectors\n  if (! size_equal (sx, sy, sz))\n    error (\"specular: SX, SY, and SZ must be the same size\");\n  endif\n\n  ## Check light vector (lv) argument\n  if (! isvector (lv) || numel (lv) < 2 || numel (lv) > 3)\n    error (\"specular: light vector LV must be a 2- or 3-element vector\");\n  elseif (numel (lv) == 2)\n    [lv(1), lv(2), lv(3)] = sph2cart (lv(1) * pi/180, lv(2) * pi/180, 1.0);\n  endif\n\n  ## Check view vector (vv) argument\n  if (! isvector (vv) || numel (vv) < 2 || numel (lv) > 3)\n    error (\"specular: view vector VV must be a 2- or 3-element vector\");\n  elseif (numel (vv) == 2)\n    [vv(1), vv(2), vv(3)] = sph2cart (vv(1) * pi / 180, vv(2) * pi / 180, 1.0);\n  endif\n\n  ## Check specular exponent (se) argument\n  if (nargin < 6)\n    se = 10;\n  elseif (! (isnumeric (se) && isscalar (se) && se > 0))\n    error (\"specular: exponent SE must be a positive scalar\");\n  endif\n\n  ## Normalize view and light vectors\n  if (sum (abs (lv)) > 0)\n    lv /= norm (lv);\n  endif\n  if (sum (abs (vv)) > 0)\n    vv /= norm (vv);\n  endif\n\n  ## Calculate normal vector lengths and dot-products\n  ns = sqrt (sx.^2 + sy.^2 + sz.^2);\n  l_dot_n = (sx * lv(1) + sy * lv(2) + sz * lv(3)) ./ ns;\n  v_dot_n = (sx * vv(1) + sy * vv(2) + sz * vv(3)) ./ ns;\n\n  ## Calculate specular reflection using Phong's approximation\n  refl = 2 * l_dot_n .* v_dot_n - dot (lv, vv);\n\n  ## Set reflectance to zero if light is on the other side\n  refl(l_dot_n < 0) = 0;\n\n  ## Allow positive values only\n  refl(refl < 0) = 0;\n  refl .^= se;\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/appearance/text.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} text (@var{x}, @var{y}, @var{string})\n## @deftypefnx {} {} text (@var{x}, @var{y}, @var{z}, @var{string})\n## @deftypefnx {} {} text (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} text (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} text (@dots{})\n## Create a text object with text @var{string} at position @var{x}, @var{y},\n## (@var{z}) on the current axes.\n##\n## Multiple locations can be specified if @var{x}, @var{y}, (@var{z}) are\n## vectors.  Multiple strings can be specified with a character matrix or\n## a cell array of strings.\n##\n## Optional property/value pairs may be used to control the appearance of the\n## text.\n##\n## If the first argument @var{hax} is an axes handle, then add text to this\n## axes, rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of graphics handles to the\n## created text objects.\n##\n## Example 1 : multi-line text via 3 different methods\n##\n## @example\n## @group\n## text (0.5, 0.8, @{\"Line 1\", \"Line 2\"@})\n## text (0.5, 0.6, [\"Line 1\"; \"Line 2\"])\n## text (0.5, 0.4, \"Line 1\\nLine 2\")\n## @end group\n## @end example\n##\n## Example 2 : text at multiple locations\n##\n## @example\n## @group\n## text ([0.2, 0.2], [0.8, 0.6], \"Same text at two locations\")\n## text ([0.4, 0.4], [0.8, 0.6], @{\"Point 1 Text\", \"Point 2 text\"@})\n## text ([0.6, 0.6], [0.8, 0.6], @{@{\"Point 1 Line 1\", \"Point 1 Line 2@},\n##                                \"Point 2 text\"@})\n## @end group\n## @end example\n##\n## Example 2 : adjust appearance using text properties\n##\n## @example\n## @group\n## ht = text (0.5, 0.5, \"Hello World\", \"fontsize\", 20);\n## set (ht, \"color\", \"red\");\n## @end group\n## @end example\n##\n## Programming Notes: The full list of properties is documented at\n## @ref{Text Properties}.\n##\n## Any numeric entries in a cell array will be converted to text using\n## @code{sprintf (\"%g\")}.  For more precise control of the appearance convert\n## any numeric entries to strings using @code{num2str}, @code{sprintf}, etc.,\n## before calling @code{text}.\n## @seealso{gtext, title, xlabel, ylabel, zlabel}\n## @end deftypefn\n\n## Caution: The following code is rigged for Matlab compatibility and is\n##          full of hidden assumptions.  Be very wary when modifying.\n\nfunction h = text (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"text\", varargin{:});\n\n  offset = 0;\n\n  if (nargin > 2 && isnumeric (varargin{1}) && isnumeric (varargin{2}))\n    x = varargin{1};\n    y = varargin{2};\n\n    if (nargin > 3 && isnumeric (varargin{3}))\n      z = varargin{3};\n      offset = 4;\n    else\n      z = zeros (size (x));\n      offset = 3;\n    endif\n\n    string = varargin{offset};\n    varargin(1:offset) = [];\n\n    nx = numel (x);\n    ny = numel (y);\n    nz = numel (z);\n    if (nx != ny || nx != nz)\n      error (\"text: number of X, Y, and Z coordinates must match\");\n    endif\n\n  else  # Only PROP/VALUE pairs\n    x = y = z = 0;\n    nx = ny = nz = 1;\n    string = \"\";\n  endif\n\n  ## Any remaining inputs must occur as PROPERTY/VALUE pairs\n  if (rem (numel (varargin), 2) != 0)\n    print_usage ();\n  endif\n\n  ## String argument may be in PROP/VAL pair\n  idx = find (strcmpi (varargin, \"string\"), 1);\n  if (idx)\n    string = varargin{idx+1};\n    varargin(idx:idx+1) = [];\n  endif\n\n  ## Position argument may be in PROP/VAL pair\n  idx = find (strcmpi (varargin, \"position\"), 1);\n  if (idx)\n    pos = varargin{idx+1};\n    varargin(idx:idx+1) = [];\n  else\n    pos = [x(:), y(:), z(:)];\n  endif\n\n  ## Validate string argument\n  if (ischar (string))\n\n    do_keyword_repl = true;\n    nt = rows (string);\n    if (nx == 1 && (nt == 1 || nt == 0))\n      ## Single text object with one line or empty line\n      string = {string};\n      nt = 1;\n    elseif (nx == 1 && nt > 1)\n      ## Single text object with multiple lines\n      ## FIXME: \"default\" or \"factory\" as first row\n      ##        should be escaped to \"\\default\" or \"\\factory\"\n      ##        Other rows do not require escaping.\n      do_keyword_repl = false;\n      string = {string};\n    elseif (nx > 1 && nt == nx)\n      ## Multiple text objects with different strings\n      string = cellstr (string);\n    elseif (nx > 1 && nt == 1)\n      ## Multiple text objects with same string\n      string = repmat ({string}, [nx, 1]);\n      nt = nx;\n    else\n      error (\"text: invalid combination of points and text strings\");\n    endif\n\n    ## Escape special keywords\n    if (do_keyword_repl)\n      string = regexprep (string, '^(default|factory)$', '\\\\$1');\n    endif\n\n  elseif (iscell (string))\n\n    if (! iscellstr (string))\n      ## Matlab compatibility: convert any numeric cells to strings\n      string = cell2cellstr (string);\n    endif\n\n    nt = numel (string);\n    if (nx == 1)\n      ## Single text object with one or more lines\n      string = {string};\n      nt = 1;\n    elseif (nx > 1 && nt == nx)\n      ## Multiple text objects with different strings\n    elseif (nx > 1 && nt == 1)\n      ## Multiple text objects with same string\n      string = repmat ({cellstr(string)}, [nx, 1]);\n      nt = nx;\n    else\n      error (\"text: invalid combination of points and text strings\");\n    endif\n\n  else\n\n    error (\"text: STRING must be a character string or cell array of character strings\");\n\n  endif\n\n  ## Select the correct axes\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  ## Call __go_text__ to do the work\n  htmp = zeros (nt, 1);\n  if (nx == 1)\n    ## Set varargin first, in case it changes units or interpreter properties.\n    htmp = __go_text__ (hax, varargin{:}, \"position\", pos,\n                             \"string\", string{1});\n  else\n    for n = 1:nt\n      htmp(n) = __go_text__ (hax, varargin{:}, \"position\", pos(n,:),\n                                  \"string\", string{n});\n    endfor\n    __request_drawnow__ ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n## Helper function converts any numeric entries to strings\nfunction cstr = cell2cellstr (c)\n  cstr = c;\n  idx = cellfun ('isnumeric', c);\n  cstr(idx) = cellfun (@(x) sprintf (\"%g\", x), c(idx), \"uniformoutput\", false);\nendfunction\n\n\n%!demo\n%! clf;\n%! ha = {\"left\", \"center\", \"right\"};\n%! va = {\"bottom\", \"middle\", \"top\"};\n%! x = [0.25 0.5 0.75];\n%! y = x;\n%! for t = 0:30:359\n%!   for nh = 1:numel (ha)\n%!     for nv = 1:numel (va)\n%!       text (x(nh), y(nv), \"Hello World\", ...\n%!             \"rotation\", t, ...\n%!             \"horizontalalignment\", ha{nh}, ...\n%!             \"verticalalignment\", va{nv});\n%!     endfor\n%!   endfor\n%! endfor\n%! set (gca, \"xtick\", [0.25, 0.5, 0.75], ...\n%!           \"xticklabel\", ha, ...\n%!           \"ytick\", [0.25, 0.5, 0.75], ...\n%!           \"yticklabel\", va);\n%! axis ([0 1 0 1]);\n%! xlabel (\"horizontal alignment\");\n%! ylabel (\"vertical alignment\");\n%! title (\"text alignment and rotation (0:30:360 degrees)\");\n\n%!demo\n%! clf;\n%! h = mesh (peaks, \"edgecolor\", 0.7 * [1 1 1], ...\n%!                  \"facecolor\", \"none\", ...\n%!                  \"facealpha\", 0);\n%! colors = jet (9);\n%! ii = 1;\n%! for t = 0:45:359\n%!   ii = ii +1;\n%!   text (25, 25, 0, \"Vertical Alignment = Bottom\", ...\n%!                    \"rotation\", t, ...\n%!                    \"horizontalalignment\", \"left\", ...\n%!                    \"backgroundcolor\", colors(ii,:), ...\n%!                    \"edgecolor\", \"k\", ...\n%!                    \"verticalalignment\", \"bottom\");\n%! endfor\n%! clim ([-100 100]);\n%! title (\"Vertically Aligned at Bottom\");\n\n%!demo\n%! clf;\n%! axis ([0 8 0 8]);\n%! title ([\"1st title\";\"2nd title\"]);\n%! xlabel ([\"1st xlabel\";\"2nd xlabel\"]);\n%! ylabel ([\"1st ylabel\";\"2nd ylabel\"]);\n%! text (4, 4, {\"Hello\", \"World\"}, ...\n%!       \"horizontalalignment\", \"center\", ...\n%!       \"verticalalignment\", \"middle\");\n%! grid on;\n\n%!demo\n%! clf;\n%! h = mesh (peaks (), \"edgecolor\", 0.7 * [1 1 1], ...\n%!                     \"facecolor\", \"none\", ...\n%!                     \"facealpha\", 0);\n%! title ([\"1st title\";\"2nd title\"]);\n%! xlabel ([\"1st xlabel\";\"2nd xlabel\"]);\n%! ylabel ([\"1st ylabel\";\"2nd ylabel\"]);\n%! zlabel ([\"1st zlabel\";\"2nd zlabel\"]);\n%! text (0, 0, 5, {\"Hello\", \"World\"}, ...\n%!       \"horizontalalignment\", \"center\", ...\n%!       \"verticalalignment\", \"middle\");\n%! hold on;\n%! plot3 (0, 0, 5, \"+k\");\n\n%!demo\n%! clf;\n%! h = text (0.5, 0.3, \"char\");\n%! h = text (0.5, 0.4, [\"char row 1\"; \"char row 2\"]);\n%! h = text (0.5, 0.6, {\"cell2str (1,1)\", \"cell2str (1,2)\"; \"cell2str (2,1)\", \"cell2str (2,2)\"});\n%! h = text (0.5, 0.8, \"foobar\");\n%! set (h, \"string\", 1:3);\n%! h = text ([0.1, 0.1], [0.3, 0.4], \"one string & two objects\");\n%! h = text ([0.1, 0.1], [0.5, 0.6], {\"one cellstr & two objects\"});\n%! h = text ([0.1, 0.1], [0.7, 0.8], {\"cellstr 1 object 1\", \"cellstr 2 object 2\"});\n%! h = text ([0.1, 0.1], [0.1, 0.2], [\"1st string & 1st object\"; \"2nd string & 2nd object\"]);\n%! h = text (0.7, 0.6, \"single string\");\n%! h = text (0.7, 0.5, {\"single cell-string\"});\n%! xlabel (1:2);\n%! ylabel (1:2);\n%! title (1:2);\n\n%!demo\n%! clf;\n%! title (\"Use of the \\\"interpreter\\\" property\")\n%! xlim ([0 1])\n%! ylim ([-1 1])\n%! text (0.1, 0.5, \"\\\"none\\\": erf(x) = (2/\\\\pi^{1/2})\\\\int_0^x e^{y^2}dy\", ...\n%!       \"interpreter\", \"none\", ...\n%!       \"fontsize\", 20, ...\n%!       \"backgroundcolor\", \"r\");\n%! text (0.1, 0, \"\\\"tex\\\"(def.): erf(x) = (2/\\\\pi^{1/2})\\\\int_0^x e^{y^2}dy\", ...\n%!       \"fontsize\", 20, ...\n%!       \"backgroundcolor\", \"r\");\n%! text (0.1, -0.5, \"``latex'': $erf(x) = (2/\\\\pi^{1/2})\\\\int_0^x e^{y^2}dy$\", ...\n%!       \"interpreter\", \"latex\", ...\n%!       \"fontsize\", 20, ...\n%!       \"backgroundcolor\", \"r\");\n%! grid on;\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ## Single object with one line\n%!   h = text (0.5, 0.5, \"single object with one line\");\n%!   obs = get (h, \"string\");\n%!   assert (class (obs), \"char\");\n%!   assert (obs, \"single object with one line\");\n%!\n%!   ## Single object with multiple lines\n%!   h = text (0.5, 0.3, [\"char row 1\"; \"char row 2\"]);\n%!   obs = get (h, \"string\");\n%!   assert (class (obs), \"char\");\n%!   assert (obs, [\"char row 1\"; \"char row 2\"]);\n%!\n%!   ## Multiple objects with single line\n%!   h = text ([0.1, 0.1], [0.3, 0.4], \"two objects with same string\");\n%!   assert (class (get (h(1), \"string\")), \"char\");\n%!   assert (class (get (h(2), \"string\")), \"char\");\n%!   assert (get (h(1), \"string\"), \"two objects with same string\");\n%!   assert (get (h(2), \"string\"), \"two objects with same string\");\n%!\n%!   ## Multiple objects with multiple lines\n%!   h = text ([0.7, 0.7], [0.3, 0.4], [\"string1\"; \"string2\"]);\n%!   assert (class (get (h(1), \"string\")), \"char\");\n%!   assert (class (get (h(2), \"string\")), \"char\");\n%!   assert (get (h(1), \"string\"), \"string1\");\n%!   assert (get (h(2), \"string\"), \"string2\");\n%!\n%!   ## Test special keyword processing\n%!   h = text (0.5, 0.5, \"default\");\n%!   assert (get (h, \"string\"), \"default\");\n%!   h = text (0.5, 0.5, \"factory\");\n%!   assert (get (h, \"string\"), \"factory\");\n%!\n%!   ## Test special null (\"\") string\n%!   h = text (0.5, 0.5, \"\");\n%!   assert (get (h, \"string\"), \"\");\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Tests repeated with cell input ##\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ## Single object with one line\n%!   h = text (0.5, 0.5, {\"single object with one line\"});\n%!   obs = get (h, \"string\");\n%!   assert (class (obs), \"cell\");\n%!   assert (obs, {\"single object with one line\"});\n%!\n%!   # Single object with multiple lines\n%!   h = text (0.5, 0.3, {\"cell2str (1,1)\", \"cell2str (1,2)\";\n%!                        \"cell2str (2,1)\", \"cell2str (2,2)\"});\n%!   obs = get (h, \"string\");\n%!   assert (class (obs), \"cell\");\n%!   assert (obs, {\"cell2str (1,1)\"; \"cell2str (2,1)\";\n%!                 \"cell2str (1,2)\"; \"cell2str (2,2)\"});\n%!\n%!   ## Single object with multiple lines including empty cell\n%!   h = text (0.5, 0.9, {\"Line1\"; []; \"Line3\"});\n%!   obs = get (h, \"string\");\n%!   assert (class (obs), \"cell\");\n%!   assert (obs, {\"Line1\"; \"\"; \"Line3\"});\n%!\n%!   ## Multiple objects with single line\n%!   h = text ([0.1, 0.1], [0.5, 0.6], {\"two objects with same cellstr\"});\n%!   assert (class (get (h(1), \"string\")), \"cell\");\n%!   assert (class (get (h(2), \"string\")), \"cell\");\n%!   assert (get (h(1), \"string\"), {\"two objects with same cellstr\"});\n%!   assert (get (h(2), \"string\"), {\"two objects with same cellstr\"});\n%!\n%!   ## Multiple objects with multiple lines\n%!   h = text ([0.1, 0.1], [0.7, 0.8], {\"cellstr1\", \"cellstr2\"});\n%!   assert (class (get (h(1), \"string\")), \"char\");\n%!   assert (class (get (h(2), \"string\")), \"char\");\n%!   assert (get (h(1), \"string\"), \"cellstr1\");\n%!   assert (get (h(2), \"string\"), \"cellstr2\");\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*54067>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ht = text (\"String\", \"Hello\", \"Position\", [0.5, 0.5], \"FontSize\", 16);\n%!   assert (get (ht, \"String\"), \"Hello\");\n%!   assert (get (ht, \"FontSize\"), 16);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*54109>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ht = text ();\n%!   assert (get (ht, \"string\"), \"\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*56395>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ht = text (.3, .8, {\"Hello\", 'world', [], 1e7});\n%!   assert (get (ht, \"string\"), {\"Hello\"; \"world\"; \"\"; \"1e+07\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <X, Y, and Z coordinates must match> text (1, [2 3], \"foobar\")\n%!error <X, Y, and Z coordinates must match> text (1, 2, [3 4], \"foobar\")\n%!error <Invalid call to text> text (1,2, \"text\", \"opt1\")\n%!error <invalid combination> text ([1 2], [3, 4], ['a'; 'b'; 'c'])\n%!error <invalid combination> text ([1 2], [3, 4], {'a', 'b', 'c'})\n%!error <STRING must be a character string> text (1, 2, 3)\n"
  },
  {
    "path": "scripts/plot/appearance/thetaticklabels.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{labels} =} thetaticklabels\n## @deftypefnx {} {} thetaticklabels (@var{tickval})\n## @deftypefnx {} {@dots{} =} thetaticklabels (@var{hax}, @dots{})\n## Query or set the tick labels on the theta-axis of a polar plot.\n##\n## When called without an argument, return a cell array of strings of the\n## current ttick labels.\n##\n## When called with the argument @var{tickval} being a vector of numbers or\n## a cell array of strings and/or numbers, the labels will be changed to\n## match these new values.  Values will be applied starting with the\n## zero-degree tick mark and will progress counterclockwise.\n##\n## If fewer labels are specified than the current number of theta tick marks,\n## those labels will be applied starting at the zero-degree tick mark and\n## blank labels will be appended to the remainder.  If the specified label\n## count exceeds the number of tick labels, the excess labels are ignored.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{thetaticklabels} to set a\n## property value will result in an error.\n##\n## Compatibility Note: The @qcode{'mode'} property for thetaticklabels has not\n## yet been implemented.\n##\n## @seealso{polar, thetaticks, rticklabels, xticklabels, yticklabels,\n## zticklabels, get, set}\n## @end deftypefn\n\n## FIXME: Octave's polar plot implementation does not currently create the\n##        properties tticklabel, tticklabelmode, and ttickmode.  Fully\n##        implemented versions of those proporties could simplify much of the\n##        code below, which could then mimick much the behavior of the\n##        equivalent Cartesian functions.\n\nfunction labels = thetaticklabels (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"thetaticklabels\", varargin{:});\n\n  if (nargin > 1)\n    print_usage;\n  endif\n\n  returnlabels = true;\n\n  ## Check first input for axes handle and remove from argument list.\n  if (nargin > 0)\n    ## Single remaining input must be tick labels and should be a numeric\n    ## vector or a cell vector of numbers and strings.\n\n    ## Error if trying to request and set values simultaneously.\n    if (nargout > 0)\n      error (\"thetaticklabels: cannot set and return labels simultaneously\");\n    endif\n\n    returnlabels = false;\n    arg = varargin{1};\n\n    if (isnumeric (arg))\n      ## All inputs handled the same way as cells. (:) permits nonvectors.\n      cellarg_num = ones (1, numel (arg));\n      cellarg_char = zeros (1, numel (arg));\n      arg = num2cell (arg(:));\n\n    elseif (iscell (arg))\n      if (! all (  (cellarg_num = cellfun ('isnumeric', arg))\n                 | (cellarg_char = cellfun ('ischar', arg))))\n        error (\"thetaticklabels: TICKVAL cell must contain numbers or strings\");\n      endif\n\n    else\n      error (\"thetaticklabels: TICKVAL must be numeric or a cell containing numbers and strings\");\n    endif\n\n  ## Finish converting TICKVAL into a cellstr.\n  ## Convert numeric elements to characters and make it a 1-D cell array.\n  arg(cellarg_num) = cellfun ('num2str', arg(cellarg_num),\n                              \"UniformOutput\", false);\n  arg = arg(:);\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  ## Error if hax does not point to a polar plot.\n  polarhandle = findall (hax, \"tag\", \"polar_grid\");\n  if (isempty (polarhandle))\n    error (\"thetaticklabels: function can only be used on a polar plot\");\n  elseif (! isfield (get (hax), \"ttick\") )\n    error (\"thetaticklabels: ttick property not defined for current axes\");\n  endif\n\n  ## Get theta curves count.\n  nt = numel (get (hax, \"ttick\"));\n\n  ## rtick and ttick object ordering:\n  ##  1:nt = text handles containing theta labels (reverse order)\n  ##  nt+1:2*nt = line object handles for ttick radial grid lines\n  ##  2*nt+1:2*nt+nr = text handles containing nr rtick labels (reverse order)\n  ##  2*nt+nr+1:2*nt+2*nr = line object handles for rtick circles\n  ##  end = patch object handle for darker outside border\n\n  ## Get theta label handles, reverse order so output is in increasing.\n  tlabel_handles = get (polarhandle, \"children\")(nt:-1:1);\n\n  if (nargin == 0)\n    ## Just return theta labels.\n    labels = get (tlabel_handles, \"string\");\n\n  else\n    ## Set new label values.\n\n    if (isempty (arg))\n      ## If an empty cell or array is set, set all labels to \"\".\n      arg = cell (nt, 1);\n      arg(:) = {\"\"};\n\n    else\n      ## Pad and trim arg as needed to match number of labels.\n      if (nt < numel (arg))\n        arg (nt + 1 : end) = [];\n      else\n        arg(end + 1 : nt) = {\"\"};\n      endif\n    endif\n\n    ## Replace labels with values from arg, ensure column vector.\n    set (tlabel_handles, {\"string\"}, arg(:));\n  endif\n\nendfunction\n\n\n%!test\n%! t = [0:15:180] * pi / 180;\n%! r = sin (t);\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hp = polar (t, r);\n%!   hax = gca ();\n%!   thetaticks (hax, [0:60:300]);\n%!   assert (thetaticklabels (hax), {\"0\"; \"60\"; \"120\"; \"180\"; \"240\"; \"300\"});\n%!   thetaticklabels (hax, [0:20:100]);\n%!   assert (thetaticklabels (hax), {\"0\"; \"20\"; \"40\"; \"60\"; \"80\"; \"100\"});\n%!   thetaticklabels (hax, [0:-20:-100]');\n%!   assert (thetaticklabels (hax), {\"0\"; \"-20\"; \"-40\"; \"-60\"; \"-80\"; \"-100\"});\n%!   thetaticklabels (hax, {1, 2, 3, 4, 5 ,6});\n%!   assert (thetaticklabels (hax), {\"1\"; \"2\"; \"3\"; \"4\"; \"5\"; \"6\"});\n%!   thetaticklabels (hax, {\"a\", \"bee\", \"c\", \"d\", \"eeee\", \"f\"});\n%!   assert (thetaticklabels (hax), {\"a\"; \"bee\"; \"c\"; \"d\"; \"eeee\"; \"f\"});\n%!   thetaticklabels (hax, {1, \"two\", 3, \"4\", 5, \"six\"}');\n%!   assert (thetaticklabels (hax), {\"1\"; \"two\"; \"3\"; \"4\"; \"5\"; \"six\"});\n%!   thetaticklabels (hax, {1, 2, 3, 4, 5 ,6, 7});\n%!   assert (thetaticklabels (hax), {\"1\"; \"2\"; \"3\"; \"4\"; \"5\"; \"6\"});\n%!   thetaticklabels (hax, [5, 6, 7, 8, 9, 10, 11]);\n%!   assert (thetaticklabels (hax), {\"5\"; \"6\"; \"7\"; \"8\"; \"9\"; \"10\"});\n%!   thetaticklabels (hax, {1});\n%!   assert (thetaticklabels (hax), {\"1\"; \"\"; \"\"; \"\"; \"\"; \"\"});\n%!   thetaticklabels (hax, {1, 2, 3, 4, 5 ,6});\n%!   assert (thetaticklabels (hax), {\"1\"; \"2\"; \"3\"; \"4\"; \"5\"; \"6\"});\n%!   thetaticklabels (hax, []);\n%!   assert (thetaticklabels (hax), {\"\"; \"\"; \"\"; \"\"; \"\"; \"\"});\n%!   thetaticklabels (hax, {1, 2, 3, 4, 5 ,6});\n%!   assert (thetaticklabels (hax), {\"1\"; \"2\"; \"3\"; \"4\"; \"5\"; \"6\"});\n%!   thetaticklabels (hax, {});\n%!   assert (thetaticklabels (hax), {\"\"; \"\"; \"\"; \"\"; \"\"; \"\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n\n## Test input validation\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"thetaticklabels (1,2,3)\", \"Invalid call\");\n%!   fail (\"thetaticklabels (-1, 2)\", \"Invalid call\");\n%!   fail (\"thetaticklabels (hax, 2, 3)\", \"Invalid call\");\n%!   fail (\"thetaticklabels (hf, 2)\", \"Invalid call\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"tmp = thetaticklabels ([1, 2, 3])\", \"cannot set and return labels simultaneously\");\n%!   fail (\"tmp = thetaticklabels (hax, [1, 2, 3])\", \"cannot set and return labels simultaneously\");\n%!   fail (\"thetaticklabels (hax, {{1}, 'two', 3})\", \"TICKVAL cell must contain numbers or strings\");\n%!   fail (\"thetaticklabels (hax, {1, 'two', false})\", \"TICKVAL cell must contain numbers or strings\");\n%!   fail (\"thetaticklabels (hax, {1, struct()})\", \"TICKVAL cell must contain numbers or strings\");\n%!   fail (\"thetaticklabels (hax, struct())\", \"TICKVAL must be numeric or a cell containing\");\n%!   fail (\"thetaticklabels (hax, [true false])\", \"TICKVAL must be numeric or a cell containing\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! t = [0:45:180] * pi / 180;\n%! r = sin (t);\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hp = plot (t, r);\n%!   hax = gca ();\n%!   fail (\"thetaticklabels (hax, 1)\", \"function can only be used on a polar plot\");\n%!   fail (\"thetaticklabels ({1})\", \"function can only be used on a polar plot\");\n%!   hp = polar (t, r);\n%!   hax = gca ();\n%!   delete (findall (hax, \"tag\", \"polar_grid\"));\n%!   fail (\"thetaticklabels (hax, 1)\", \"function can only be used on a polar plot\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/thetaticks.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tickval} =} thetaticks\n## @deftypefnx {} {} thetaticks (@var{tickval})\n## @deftypefnx {} {@dots{} =} thetaticks (@var{hax}, @dots{})\n## Query or set the tick values on the theta-axis of the current axis.\n##\n## When called without argument, return the current tick locations as specified\n## in the @qcode{\"ttick\"} axes property.  These locations can be changed by\n## calling @code{thetaticks} with a vector of tick values.  Note: ascending\n## order is not required.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{thetaticks} to set a property\n## value will result in an error.\n##\n## NOTE: Octave does not currently implement polaraxes objects.  It is\n## therefore not possible to query or set a @qcode{\"mode\"} for the\n## @qcode{\"thetatick\"} property as can be done with the equivalent functions\n## for @var{x}, @var{y}, and @var{z} axes.\n##\n## @seealso{rticks, xticks, yticks, zticks, polar, get, set}\n## @end deftypefn\n\nfunction tickval = thetaticks (varargin)\n\n  ## FIXME: Update function to work with polaraxes objects once that function\n  ##        is implemented in Octave.  For compatibility with Matlab this may\n  ##        need to function with both the property names ttick and thetatick.\n\n  hax = [];\n  switch (nargin)\n    case 0\n      tickval = get (gca , \"ttick\");  # will error if no ttick exists.\n      return;\n\n    case 1\n      if (isaxes (varargin{1}))\n        tickval = get (varargin{1}, \"ttick\");\n        return;\n      else\n        arg = varargin{1};\n      endif\n\n    case 2\n      if (! ishghandle (varargin{1}))\n        error (\"thetaticks: HAX must be a handle to an axes object\");\n      endif\n      hax = varargin{1};\n      arg = varargin{2};\n\n    otherwise\n      print_usage ();\n\n  endswitch\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (isnumeric (arg))\n    if (nargout > 0)\n      error (\"thetaticks: too many output arguments requested\");\n    endif\n    ## NOTE: Matlab errors if tick points are not in ascending order.  Octave\n    ## permits out of order tick points, so error is not produced.\n    set (hax, \"ttick\", arg);\n\n  elseif (ischar (arg))\n    error (\"thetaticks: MODE is not yet implemented for the ttick property\");\n\n    ## FIXME: Enable mode args if/when they are available in polar/polarplot\n    ##    arg = lower (arg);\n    ## switch (arg)\n    ##   case \"mode\"\n    ##     tickval = get (hax, \"ttickmode\");\n    ##\n    ##   case {\"auto\", \"manual\"}\n    ##     if (nargout > 0)\n    ##       error ([\"thetaticks: \" ...\n    ##               \"too many output arguments requested for arg: \", arg]);\n    ##     endif\n    ##     set (hax, \"ttickmode\", arg);\n    ##\n    ##   otherwise\n    ##     error (\"thetaticks: invalid option: %s\", arg);\n    ##\n    ## endswitch\n\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%! polar (linspace (0, pi, 20), rand (20,1));\n%!   hax = gca ();\n%!   ticks = thetaticks;\n%!   assert (thetaticks (hax), ticks);\n%!   thetaticks (hax, [0 45 90 135 180]);\n%!   assert (thetaticks (hax), [0 45 90 135 180]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error thetaticks (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   polar (linspace (0, pi, 20), 1:20);\n%!   hax = gca ();\n%!   fail (\"thetaticks (-1, [0 1])\", \"HAX must be a handle to an axes\");\n%!   fail (\"tmp = thetaticks (hax, [0 1])\", \"too many output arguments\");\n%!   fail (\"tmp = thetaticks (hax, 'mode')\", \"MODE is not yet implemented\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/title.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} title (@var{string})\n## @deftypefnx {} {} title (@var{string}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} title (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} title (@dots{})\n## Specify the string used as a title for the current axis.\n##\n## An optional list of @var{property}/@var{value} pairs can be used to change\n## the appearance of the created title text object.\n##\n## If the first argument @var{hax} is an axes or legend handle, then add a\n## title to this object, rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created text\n## object.\n## @seealso{xlabel, ylabel, zlabel, text}\n## @end deftypefn\n\nfunction h = title (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"title\", varargin{:});\n\n  if (isempty (hax))\n    if (! isempty (varargin) && isscalar (varargin{1})\n        && ishghandle (varargin{1})\n        && strcmp (get (varargin{1}, \"tag\"), \"legend\"))\n        hax = varargin{1};\n        varargin(1) = [];\n        nargin--;\n    else\n      hax = gca ();\n    endif\n  endif\n\n  if (rem (nargin, 2) != 1)\n    print_usage ();\n  endif\n\n  htmp = __axis_label__ (hax, \"title\", varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! title (\"Test Title Text\");\n\n%!demo\n%! clf;\n%! title ({\"Multi-line\"; \"Title\"; \"Text\"});\n\n%!demo\n%! clf;\n%! plot3 ([0,1], [0,1], [0,1]);\n%! title (\"Test FontSize Property\", \"fontsize\", 16);\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   title (\"Test Title Text\");\n%!   h = get (gca, \"title\");\n%!   assert (get (h, \"string\"), \"Test Title Text\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   title ({\"Multi-line\"; \"Title\"; \"Text\"});\n%!   h = get (gca, \"title\");\n%!   assert (get (h, \"string\"), {\"Multi-line\"; \"Title\"; \"Text\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"fontsize\", 5, \"titlefontsizemultiplier\", 3);\n%!   ht = title (\"title_string\", \"color\", \"r\");\n%!   assert (get (ht, \"fontsize\"), 15);\n%!   assert (get (ht, \"color\"), [1 0 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot3 ([0,1], [0,1], [0,1]);\n%!   title (\"Test FontSize Property\", \"fontsize\", 16);\n%!   h = get (gca, \"title\");\n%!   assert (get (h, \"string\"), \"Test FontSize Property\");\n%!   assert (get (h, \"fontsize\"), 16);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*49469>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ht = title (\"Test FontSize Property\");\n%!   set (gca, \"fontname\", \"Liberation Serif\");\n%!   set (gca, \"fontsize\", 13);\n%!   assert (get (ht, \"fontname\"), \"Liberation Serif\");\n%!   assert (get (ht, \"fontsize\"), 13 * get (gca, \"titlefontsizemultiplier\"));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*57372>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   hl = legend (\"legend text\");\n%!   ht = title (hl, \"Legend Title\");\n%!   assert (get (ht, \"string\"), \"Legend Title\");\n%!   assert (get (ht, \"parent\"), hl);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/view.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} view (@var{azimuth}, @var{elevation})\n## @deftypefnx {} {} view ([@var{azimuth} @var{elevation}])\n## @deftypefnx {} {} view ([@var{x} @var{y} @var{z}])\n## @deftypefnx {} {} view (2)\n## @deftypefnx {} {} view (3)\n## @deftypefnx {} {} view (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{azimuth}, @var{elevation}] =} view ()\n## Query or set the viewpoint for the current axes.\n##\n## The parameters @var{azimuth} and @var{elevation} can be given as two\n## arguments or as 2-element vector.  The viewpoint can also be specified with\n## Cartesian coordinates @var{x}, @var{y}, and @var{z}.\n##\n## The call @code{view (2)} sets the viewpoint to\n## @w{@var{azimuth} = 0}@ and @w{@var{elevation} = 90}, which is the default\n## for 2-D graphs.\n##\n## The call @code{view (3)} sets the viewpoint to\n## @w{@var{azimuth} = -37.5}@ and @w{@var{elevation} = 30}, which is the\n## default for 3-D graphs.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## If no inputs are given, return the current @var{azimuth} and\n## @var{elevation}.\n## @end deftypefn\n\nfunction [azimuth, elevation] = view (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"view\", varargin{:});\n\n  if (nargin > 2)\n    print_usage ();\n  endif\n\n  if (nargout > 0 && nargin > 0)\n    error (\"view: cannot simultaneously get and set viewpoint\");\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (nargin == 0)\n    vw = get (hax, \"view\");\n    az = vw(1);\n    el = vw(2);\n  elseif (numel (varargin) == 1)\n    x = varargin{1};\n    if (numel (x) == 2)\n      az = x(1);\n      el = x(2);\n    elseif (numel (x) == 3)\n      if (x(2) == 0)\n        ## special case for negative 0\n        [az, el] = cart2sph (x(2), x(1), x(3));\n\n        if (x(1) == 0)\n          ## Matlab Compatibility: Force +0 azimuth instead of +/-0 or\n          ## +/-180deg azimuth for z-aligned vector.\n          az = 0;\n        endif\n\n      else\n        [az, el] = cart2sph (-x(2), x(1), x(3));\n      endif\n      az *= 180/pi;\n      el *= 180/pi;\n    elseif (x == 2)\n      az = 0;\n      el = 90;\n    elseif (x == 3)\n      az = -37.5;\n      el = 30;\n    else\n      print_usage ();\n    endif\n  elseif (numel (varargin) == 2)\n    az = varargin{1};\n    el = varargin{2};\n  endif\n\n  if (nargin > 0)\n    set (hax, \"view\", [az, el]);\n  else\n    if (nargout == 1)\n      azimuth = [az, el];\n    elseif (nargout == 2)\n      azimuth = az;\n      elevation = el;\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot3 ([0,1], [0,1], [0,1]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [-37.5, 30], eps);\n%!   view (2);\n%!   [az, el] = view ();\n%!   assert ([az, el], [0, 90], eps);\n%!   view ([1 1 0]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [135, 0], eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   line ();\n%!   [az, el] = view ();\n%!   assert ([az, el], [0, 90], eps);\n%!   view (3);\n%!   [az, el] = view ();\n%!   assert ([az, el], [-37.5, 30], eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*57800>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot3 ([0,1], [0,1], [0,1]);\n%!   view ([0, 0, 1]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [0, 90], eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*65641>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot3 ([0,1], [0,1], [0,1]);\n%!   view ([1, 0, 0]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [90, 0], eps);\n%!   view ([-1, 0, 0]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [-90, 0], eps);\n%!   view ([0, 1, 0]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [180, 0], eps);\n%!   view ([0, -1, 0]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [0, 0], eps);\n%!   view ([0, 0, 1]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [0, 90], eps);\n%!   view ([0, 0, -1]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [0, -90], eps);\n%!   view ([1, 0.001, 0]);\n%!   [az, el] = view ();\n%!   assert ([az, el], [90 + 0.001*180/pi, 0], eps (\"single\"));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*65641> # Verify compatible z-vector viewpoint.\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ml_out = [0, 90, Inf] .* ones (8, 1);\n%!   ml_out(1:2:end-1, 2) = -90;\n%!   output = NaN (8, 3);\n%!   plot3 ([0,1], [0,1], [0,1]);\n%!   idx = 1;\n%!   for x1 = [-0, 0]\n%!     for x2 = [-0, 0]\n%!       for x3 = [-1, 1]\n%!         view ([x1, x2, x3]);\n%!         [az, el] = view ();\n%!         output(idx, :) = [az, el, 1/az];\n%!         idx++;\n%!       endfor\n%!     endfor\n%!   endfor\n%!   assert (isequaln (output, ml_out));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n\n## Test input validation\n%!error <Invalid call> view (0, 0, 1)\n%!error <cannot simultaneously get and set> [a, b] = view ([1, 1, 1])\n"
  },
  {
    "path": "scripts/plot/appearance/whitebg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} whitebg ()\n## @deftypefnx {} {} whitebg (@var{color})\n## @deftypefnx {} {} whitebg (\"none\")\n## @deftypefnx {} {} whitebg (@var{hfig})\n## @deftypefnx {} {} whitebg (@var{hfig}, @var{color})\n## @deftypefnx {} {} whitebg (@var{hfig}, \"none\")\n## Invert the colors in the current color scheme.\n##\n## The root properties are also inverted such that all subsequent plots will\n## use the new color scheme.\n##\n## If the optional argument @var{color} is present then the background color\n## is set to @var{color} rather than inverted.  @var{color} may be a string\n## representing one of the eight known colors or an RGB triplet.  The special\n## string argument @qcode{\"none\"} restores the plot to the factory default\n## colors.\n##\n## If the first argument @var{hfig} is a figure handle or list of figure\n## handles, then operate on these figures rather than the current figure\n## returned by @code{gcf}.  The root properties will not be changed unless 0\n## is in the list of figures.\n##\n## Programming Note: @code{whitebg} operates by changing the color properties\n## of the children of the specified figures.  Only objects with a single color\n## are affected.  For example, a patch with a single @qcode{\"FaceColor\"} will\n## be changed, but a patch with shading (@qcode{\"interp\"}) will not be\n## modified.  For inversion, the new color is simply the inversion in RGB\n## space: @code{@var{cnew} = [1-@var{R} 1-@var{G} 1-@var{B}]}.  When a color\n## is specified, the axes and figure are set to the new color, and the color\n## of child objects are then adjusted to have some contrast (visibility)\n## against the new background.\n## @seealso{reset, get, set}\n## @end deftypefn\n\n## FIXME: It's not clear whether Matlab also changes color properties\n## of the figure object itself, or only the children.  However, visually,\n## it looks better to change the figure along with the axes background.\n\nfunction whitebg (varargin)\n\n  if (nargin > 2)\n    print_usage ();\n  endif\n\n  h = 0;\n  color = NaN;\n  have_fig = false;\n\n  if (nargin > 0)\n    if (all (ishghandle (varargin{1})))\n      h = varargin{1};\n      have_fig = true;\n      if (nargin == 2)\n        color = varargin{2};\n      endif\n    elseif (nargin == 1)\n      color = varargin{1};\n    else\n      print_usage ();\n    endif\n  endif\n\n  if (! have_fig)\n    fig = gcf ();\n    do_root = true;\n  elseif (all (isfigure (h) | h == 0))\n    fig = h(h != 0);\n    do_root = any (h == 0);\n  else\n    error (\"whitebg: HFIG must be a valid figure handle\");\n  endif\n\n  if (isnan (color))\n    if (do_root)\n      ## Set the default axes and figure properties on root\n      ## so that subsequent plots have the new color scheme\n      fac = get (0, \"factory\");\n      fields = fieldnames (fac);\n      idx = ! cellfun (\"isempty\", regexp (fields,\n                                          '^factory(axes|figure).*color$'));\n\n      ## Use default value in place of factory value if specified.\n      for field = fields(idx)'\n        defaultfield = strrep (field{1}, \"factory\", \"default\");\n        try\n          defaultvalue = 1 - get (0, defaultfield);\n        catch\n          defaultvalue = 1 - fac.(field{1});\n        end_try_catch\n        set (0, defaultfield, defaultvalue);\n      endfor\n    endif\n\n    ## The sort is necessary so that child legend objects are acted on\n    ## before the legend axes object.\n    hlist = sort (findobj (fig));\n\n    for h = hlist'\n      props = get (h);\n      fields = fieldnames (props);\n      ## Find all fields with the word color in them and invert.\n      idx = find (! cellfun (\"isempty\", regexp (fields, 'color$')));\n      for field = fields(idx)'\n        c = props.(field{1});\n        if (! ischar (c) && columns (c) == 3)\n          set (h, field{1}, 1 - c);\n        endif\n      endfor\n    endfor\n\n  else  # 2nd argument such as a color or \"none\"\n\n    if (! strcmp (color, \"none\"))\n      ## Set the specified color on the figure and all axes objects\n      hlist = [fig; findobj(fig, \"type\", \"axes\")];\n      set (hlist, \"color\", color);\n      if (do_root)\n        defs = get (0, \"default\");\n        if (isfield (defs, \"defaultaxescolor\")\n            && strcmp (defs.defaultaxescolor, \"none\"))\n          set (0, \"defaultaxescolor\", color);\n        endif\n      endif\n\n      ## Adjust colors of remaining objects to have some contrast\n      bg = rgb2hsv (get (fig, \"color\"));\n      ## List of children without the figure and axes objects already changed\n      hlist = setdiff (findobj (fig), hlist);\n      for h = hlist'\n        props = get (h);\n        fields = fieldnames (props);\n        ## Find all fields with the word color in them and adjust HSV.\n        idx = find (! cellfun (\"isempty\", regexp (fields, 'color$')));\n        for field = fields(idx)'\n          c = props.(field{1});\n          if (! ischar (c) && columns (c) == 3)\n            set (h, field{1}, calc_contrast_color (bg, c));\n          endif\n        endfor\n      endfor\n\n    else\n      ## Reset colors to factory defaults\n      if (do_root)\n        fac = get (0, \"factory\");\n        fields = fieldnames (fac);\n        idx = ! cellfun (\"isempty\", regexp (fields,\n                                            '^factory(axes|figure).*color$'));\n        for field = fields(idx)'\n          factoryfield = field{1};\n          factoryvalue = fac.(factoryfield);\n          if (strncmp (factoryfield, \"factoryfigure\", 13))\n            ## Strip off \"factoryfigure\" part of fieldname before applying\n            set (fig, factoryfield(14:end), factoryvalue);\n          endif\n          ## Remove applied default from root\n          defaultfield = strrep (factoryfield, \"factory\", \"default\");\n          set (0, defaultfield, \"remove\");\n        endfor\n      endif\n\n      hlist = sort (findobj (fig));\n      for h = hlist'\n        props = get (h);\n        fields = fieldnames (props);\n        ## Find all fields with the word color in them and restore to factory.\n        idx = find (! cellfun (\"isempty\", regexp (fields, 'color$')));\n        for field = fields(idx)'\n          set (h, field{1}, \"factory\");\n        endfor\n      endfor\n    endif\n  endif\n\nendfunction\n\n## Calculate a new color which contrasts with the supplied bg color and is\n## perceptually related to the original color.\n##\n## Input color bg must be in HSV space.  Input color corig is in RGB space.\n##\n## FIXME: Calculation is segregated into its own function in case anyone wants\n## to try and improve the selection of a \"contrasting\" color.\n##\n## This algorithm maintains at least 90 degrees separation between corig and bg\n## in Hue rotation space.  No modifications are done for saturation or value.\nfunction cnew = calc_contrast_color (bg, corig)\n\n  hsv = rgb2hsv (corig);\n  contrast_hue = mod (bg(1) + 0.5, 1);  # Generate a contrasting bg color\n\n  ## If close to existing contrast color, leave alone\n  delta = abs (hsv(1) - contrast_hue);\n  if (delta < 0.25 || delta > 0.75)\n    cnew(1) = hsv(1);\n  else\n    cnew(1) = mod (hsv(1) + 0.5, 1);\n  endif\n\n  ## No modifications to saturation or value.\n  cnew(2:3) = hsv(2:3);\n\n  cnew = hsv2rgb (cnew);\n\nendfunction\n\n\n%!test\n%! dac = get (0, \"defaultaxescolor\");\n%! dfc = get (0, \"defaultfigurecolor\");\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hl = line (\"Color\", \"r\");\n%!   assert (get (hf, \"color\"), dfc);\n%!   assert (get (gca, \"color\"), dac);\n%!   assert (get (hl, \"color\"), [1 0 0]);\n%!   whitebg (hf);\n%!   assert (get (hf, \"color\"), 1 - dfc);\n%!   assert (get (gca, \"color\"), 1 - dac);\n%!   assert (get (hl, \"color\"), [0 1 1]);\n%!   c = [0.2 0.2 0.2];\n%!   whitebg (hf, c);\n%!   assert (get (hf, \"color\"), c);\n%!   assert (get (gca, \"color\"), c);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error whitebg (1,2,3)\n%!error whitebg ({1}, 2)\n"
  },
  {
    "path": "scripts/plot/appearance/xlabel.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} xlabel (@var{string})\n## @deftypefnx {} {} xlabel (@var{string}, @var{property}, @var{val}, @dots{})\n## @deftypefnx {} {} xlabel (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} xlabel (@dots{})\n## Specify the string used to label the x-axis of the current axis.\n##\n## An optional list of @var{property}/@var{value} pairs can be used to change\n## the properties of the created text label.\n##\n## The full list of text object properties is documented at\n## @ref{Text Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created text\n## object.\n## @seealso{ylabel, zlabel, datetick, title, text}\n## @end deftypefn\n\nfunction h = xlabel (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"xlabel\", varargin{:});\n\n  if (rem (nargin, 2) != 1)\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  htmp = __axis_label__ (hax, \"xlabel\", varargin{1},\n                              \"color\", get (hax, \"xcolor\"),\n                              varargin{2:end});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hx = xlabel (\"xlabel_string\");\n%!   assert (get (gca, \"xlabel\"), hx);\n%!   assert (get (hx, \"type\"), \"text\");\n%!   assert (get (hx, \"visible\"), \"on\");\n%!   assert (get (hx, \"string\"), \"xlabel_string\");\n%!   assert (get (hx, \"color\"), get (0, \"defaultaxesxcolor\"));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"fontsize\", 5, \"labelfontsizemultiplier\", 3);\n%!   hx = xlabel (\"xlabel_string\", \"color\", \"r\");\n%!   assert (get (hx, \"fontsize\"), 15);\n%!   assert (get (hx, \"color\"), [1 0 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/xlim.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{xlimits} =} xlim ()\n## @deftypefnx {} {@var{xmode} =} xlim (\"mode\")\n## @deftypefnx {} {@var{xmethod} =} xlim (\"method\")\n## @deftypefnx {} {} xlim ([@var{x_lo} @var{x_hi}])\n## @deftypefnx {} {} xlim (\"mode\")\n## @deftypefnx {} {} xlim (\"method\")\n## @deftypefnx {} {} xlim (@var{hax}, @dots{})\n## Query or set the limits of the x-axis for the current plot.\n##\n## Called without arguments @code{xlim} returns the x-axis limits of the\n## current plot.\n##\n## With the input query @qcode{\"mode\"}, return the current x-limit calculation\n## mode which is either @qcode{\"auto\"} or @qcode{\"manual\"}.\n##\n## With the input query @qcode{\"method\"}, return the current x-limit\n## calculation method which is either @qcode{\"tickaligned\"}, @qcode{\"tight\"},\n## or @qcode{\"padded\"}.\n##\n## If passed a 2-element vector [@var{x_lo} @var{x_hi}], the limits of the\n## x-axis are set to these values and the mode is set to @qcode{\"manual\"}.\n## The special values -Inf and Inf can be used to indicate that either\n## the lower axis limit or upper axis limit should be automatically calculated.\n##\n## The current limit calculation @qcode{\"mode\"} may be one of\n##\n## @table @asis\n## @item @qcode{\"auto\"} (default)\n## Automatically calculate limits based on the plot data and the currently\n## specified limit calculation method.\n##\n## @item @qcode{\"manual\"}\n## Fix axis limits at current values.\n## @end table\n##\n## The current limit calculation method may be one of\n##\n## @table @asis\n## @item @qcode{\"tickaligned\"} (default)\n## Calculate limits that encompass all of the data and extend outwards to the\n## nearest tick mark.\n##\n## @item @qcode{\"tight\"}\n## Calculate limits that exactly fit the data range.\n##\n## @item @qcode{\"padded\"}\n## Calculate limits that leave a margin around the data of approximately 7% of\n## the data range.\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## Programming Note: The @code{xlim} function operates by modifying the\n## @qcode{\"xlim\"}, @qcode{\"xlimmode\"}, and @qcode{\"xlimitmethod\"} properties of\n## an axes object.  These properties can be directly inspected and altered with\n## @code{get}/@code{set}.\n## @seealso{ylim, zlim, axis, set, get, gca}\n## @end deftypefn\n\nfunction xlimits = xlim (varargin)\n\n  lims = __axis_limits__ (\"xlim\", varargin{:});\n\n  if (! isempty (lims))\n    xlimits = lims;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! line ();\n%! xlim ([0.2, 0.8]);\n%! title (\"xlim is [0.2, 0.8]\");\n\n%!demo\n%! clf;\n%! line ();\n%! xlim auto;\n%! title (\"xlim is auto\");\n\n%!demo\n%! clf;\n%! plot3 ([0,1], [0,1], [0,1]);\n%! xlim ([0.2, 0.8]);\n%! title (\"xlim is [0.2, 0.8]\");\n\n%!demo\n%! clf;\n%! plot3 ([0,1], [0,1], [0,1]);\n%! xlim (\"auto\");\n%! title (\"xlim is auto\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot3 ([0,1], [0,1], [0,1]);\n%!   xlim ([0, 1.1]);\n%!   assert (get (gca, \"xlim\"), [0, 1.1], eps);\n%!   assert (xlim (\"mode\"), \"manual\");\n%!   xlim ('padded');\n%!   assert (get (gca, \"xlimitmethod\"), 'padded');\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = plot3 ([0,1.1], [0,1], [0, 1]);\n%!   assert (get (gca, \"xlim\"), [0, 1.4], eps);\n%!   assert (xlim (\"mode\"), \"auto\");\n%!   assert (xlim (\"method\"), \"tickaligned\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Test input validation, done only in xlim since it is common to ylim,zlim.\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = plot3 ([0,1.1], [0,1], [0, 1]);\n%!   fail (\"xlim ('foobar')\", 'unrecognized argument \"foobar\"');\n%!   fail (\"xlim ({1, 2})\", \"LIMITS must be a 2-element vector\");\n%!   fail (\"xlim ([1, 2, 3])\", \"LIMITS must be a 2-element vector\");\n%!   fail (\"xlim ([2, 1])\", \"axis limits must be increasing\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/xtickangle.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{angle} =} xtickangle ()\n## @deftypefnx {} {@var{angle} =} xtickangle (@var{hax})\n## @deftypefnx {} {} xtickangle (@var{angle})\n## @deftypefnx {} {} xtickangle (@var{hax}, @var{angle})\n## Query or set the rotation angle of the tick labels on the x-axis of the\n## current axes.\n##\n## When called without an argument, return the rotation angle in degrees of the\n## tick labels as specified in the axes property @qcode{\"XTickLabelRotation\"}.\n## When called with a numeric scalar @var{angle}, rotate the tick labels\n## counterclockwise to @var{angle} degrees.\n##\n## If the first argument @var{hax} is an axes handle, then operate on this axes\n## rather than the current axes returned by @code{gca}.\n##\n## Programming Notes:\n## @enumerate\n## @item\n## The @qcode{\"XTickLabelRotation\"} property is @emph{not} currently\n## implemented in Octave.  The property can be set and queried, but has no\n## effect on the plot.\n##\n## @item\n## Requesting a return value while also setting a specified rotation will\n## result in an error.\n## @end enumerate\n##\n## @seealso{ytickangle, ztickangle, get, set}\n## @end deftypefn\n\nfunction angle = xtickangle (hax, angle)\n\n  switch (nargin)\n    case 0\n      angle = __tickangle__ (mfilename ());\n\n    case 1\n      if (nargout > 0)\n        angle = __tickangle__ (mfilename (), hax);\n      else\n        __tickangle__ (mfilename (), hax);\n      endif\n\n    case 2\n      if (nargout > 0)\n        angle = __tickangle__ (mfilename (), hax, angle);\n      else\n        __tickangle__ (mfilename (), hax, angle);\n      endif\n\n  endswitch\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = axes (hf);\n%! unwind_protect\n%!   xtickangle (45);\n%!   assert (xtickangle (), 45);\n%!   xtickangle (hax, 90);\n%!   a1 = xtickangle ();\n%!   a2 = xtickangle (hax);\n%!   assert (a1, a2);\n%!   assert (a1, 90);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <HAX must be a handle to an axes object> xtickangle (0, 45)\n%!error <ANGLE must be .* scalar> xtickangle (eye (2))\n%!error <ANGLE must be .* numeric> xtickangle ({90})\n%!error <ANGLE must be .* finite> xtickangle (Inf)\n%!error <called with output query and input set value> ang = xtickangle (45)\n"
  },
  {
    "path": "scripts/plot/appearance/xticklabels.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{labels} =} xticklabels\n## @deftypefnx {} {@var{mode} =} xticklabels (\"mode\")\n## @deftypefnx {} {} xticklabels (@var{tickval})\n## @deftypefnx {} {} xticklabels (\"auto\")\n## @deftypefnx {} {} xticklabels (\"manual\")\n## @deftypefnx {} {@dots{} =} xticklabels (@var{hax}, @dots{})\n## Query or set the tick labels on the x-axis of the current axis.\n##\n## When called without an argument, return a cell array of strings of the\n## current tick labels as specified in the @qcode{\"xticklabel\"} axes property.\n## These labels can be changed by calling @code{xticklabels} with a cell array\n## of strings.  Note: a vector of numbers will be mapped to a cell array of\n## strings.  If fewer labels are specified than the current number of ticks,\n## blank labels will be appended to the array.\n##\n## When called with argument @qcode{\"mode\"}, @code{xticklabels} returns the\n## current value of the axes property @qcode{\"xticklabelmode\"}.  This property\n## can be changed by calling @code{xticklabels} with either @qcode{\"auto\"}\n## (algorithm determines tick labels) or @qcode{\"manual\"} (tick labels remain\n## fixed).  Note: Specifying xticklabel values will also set the\n## @qcode{\"xticklabelmode\"} and @qcode{\"xticks\"} properties to\n## @qcode{\"manual\"}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{xticklabels} to set a property\n## value will result in an error.\n##\n## @seealso{xticks, yticklabels, zticklabels, get, set}\n## @end deftypefn\n\nfunction labels = xticklabels (varargin)\n\n  hax = [];\n  switch (nargin)\n    case 0\n      labels = get (gca , \"xticklabel\");  # will error if no xticklabel exists.\n      return;\n\n    case 1\n      if (isaxes (varargin{1}))\n        labels = get (varargin{1}, \"xticklabel\");\n        return;\n      else\n        arg = varargin{1};\n      endif\n\n    case 2\n      if (! isaxes (varargin{1}))\n        error (\"xticklabels: HAX must be a handle to an axes object\");\n      endif\n      hax = varargin{1};\n      arg = varargin{2};\n\n    otherwise\n      print_usage ();\n\n  endswitch\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (! (iscell (arg) || isnumeric (arg) || ischar (arg)))\n    print_usage ();\n  endif\n\n  if (isempty (arg))\n    arg = {};  # Either '' or [] are converted empty cell array\n  endif\n\n  if (iscell (arg) || isnumeric (arg))\n    if (nargout > 0)\n      error (\"xticklabels: too many output arguments requested\");\n    endif\n\n    if (isnumeric (arg))\n      ## NOTE: Matlab accepts a cell array, but a non-vector numeric array will\n      ## simply produce a black set of labels without error or warning.\n      ## This implementation allows for a numeric array, which is handled in\n      ## the same order as Matlab handles a cell array\n      arg = num2cell (arg(:));\n    endif\n\n    ## Convert any numeric elements to characters, make it a 1-D cell array.\n    arg = cellfun ('num2str', arg, \"UniformOutput\", false)(:);\n\n    ## Pad with blank cell entries if needed.\n    arg((numel (arg) + 1):(numel (get (hax, \"xtick\")))) = {\"\"};\n\n    ## Setting labels sets both ticklabel and tick mode to manual.\n    set (hax, \"xticklabel\", arg,\n              \"xticklabelmode\", \"manual\",\n              \"xtickmode\", \"manual\");\n\n  elseif (ischar (arg))\n    switch (lower (arg))\n      case \"mode\"\n        labels = get (hax, \"xticklabelmode\");\n\n      case {\"auto\", \"manual\"}\n        if (nargout > 0)\n          error ([\"xticklabels: \" ...\n                  \"too many output arguments requested for arg: \", arg]);\n        endif\n        set (hax, \"xticklabelmode\", arg);\n\n      otherwise\n        error (\"xticklabels: invalid option: %s\", arg);\n\n    endswitch\n\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"xticklabelmode\", \"auto\");\n%!   hax = gca ();\n%!   vals1 = xticklabels;\n%!   assert (xticklabels (hax), vals1);\n%!   mode1 = xticklabels (\"mode\");\n%!   assert (xticklabels (hax, \"mode\"), mode1);\n%!   xticklabels (hax, \"manual\");\n%!   assert (xticklabels (hax, \"mode\"), \"manual\");\n%!   xticklabels (hax, \"auto\");\n%!   assert (xticks (hax, \"mode\"), \"auto\");\n%!   xticklabels (hax, {\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"});\n%!   assert (xticklabels (hax), {\"1\"; \"2\"; \"3\"; \"4\"; \"5\"; \"6\"});\n%!   assert (xticklabels (hax, \"mode\"), \"manual\");\n%!   assert (xticks (hax, \"mode\"), \"manual\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error xticklabels (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"xticklabels (-1, {})\", \"HAX must be a handle to an axes\");\n%!   fail (\"tmp = xticklabels (hax, {'A','B'})\", \"too many output arguments\");\n%!   fail (\"tmp = xticklabels (hax, [0, 1])\", \"too many output arguments\");\n%!   fail (\"tmp = xticklabels (hax, 'auto')\", \"too many .* for arg: auto\");\n%!   fail (\"tmp = xticklabels (hax, 'foo')\", \"invalid option: foo\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/xticks.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tickval} =} xticks\n## @deftypefnx {} {@var{mode} =} xticks (\"mode\")\n## @deftypefnx {} {} xticks (@var{tickval})\n## @deftypefnx {} {} xticks (\"auto\")\n## @deftypefnx {} {} xticks (\"manual\")\n## @deftypefnx {} {@dots{} =} xticks (@var{hax}, @dots{})\n## Query or set the tick values on the x-axis of the current axis.\n##\n## When called without an argument, return the current tick locations as\n## specified in the @qcode{\"xtick\"} axes property.  These locations can be\n## changed by calling @code{xticks} with a vector of tick values.  Note:\n## ascending order is not required.\n##\n## When called with argument @qcode{\"mode\"}, @code{xticks} returns the current\n## value of the axes property @qcode{\"xtickmode\"}.  This property can be\n## changed by calling @code{xticks} with either @qcode{\"auto\"} (algorithm\n## determines tick positions) or @qcode{\"manual\"} (tick values remain fixed\n## regardless of axes resizing or rotation).  Note: Specifying xtick values\n## will also set the property @qcode{\"xtickmode\"} to @qcode{\"manual\"}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{xticks} to set a property value\n## will result in an error.\n##\n## @seealso{xticklabels, yticks, zticks, rticks, thetaticks, get, set}\n## @end deftypefn\n\nfunction tickval = xticks (varargin)\n\n  hax = [];\n  switch (nargin)\n    case 0\n      tickval = get (gca, \"xtick\");  # will error if no xtick exists.\n      return;\n\n    case 1\n      if (isaxes (varargin{1}))\n        tickval = get (varargin{1}, \"xtick\");\n        return;\n      else\n        arg = varargin{1};\n      endif\n\n    case 2\n      if (! isaxes (varargin{1}))\n        error (\"xticks: HAX must be a handle to an axes object\");\n      endif\n      hax = varargin{1};\n      arg = varargin{2};\n\n    otherwise\n      print_usage ();\n\n  endswitch\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (isnumeric (arg))\n    if (nargout > 0)\n      error (\"xticks: too many output arguments requested\");\n    endif\n    ## NOTE: Matlab errors if tick points are not in ascending order.  Octave\n    ## permits out of order tick points, so error is not produced.\n    set (hax, \"xtick\", arg);\n\n  elseif (ischar (arg))\n    arg = lower (arg);\n    switch (arg)\n      case \"mode\"\n        tickval = get (hax, \"xtickmode\");\n\n      case {\"auto\", \"manual\"}\n        if (nargout > 0)\n          error (\"xticks: too many output arguments requested for arg: %s\",\n                                                                       arg);\n        endif\n        set (hax, \"xtickmode\", arg);\n\n      otherwise\n        error (\"xticks: invalid option: %s\", arg);\n\n    endswitch\n\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"xtickmode\", \"auto\");\n%!   hax = gca ();\n%!   vals1 = xticks;\n%!   assert (xticks (hax), vals1);\n%!   mode1 = xticks (\"mode\");\n%!   assert (xticks (hax, \"mode\"), mode1);\n%!   xticks (hax, \"manual\");\n%!   assert (xticks (hax, \"mode\"), \"manual\");\n%!   xticks (hax, \"auto\");\n%!   assert (xticks (hax, \"mode\"), \"auto\");\n%!   xticks (hax, [1 2 3 4]);\n%!   assert (xticks (hax), [1 2 3 4]);\n%!   assert (xticks (hax, \"mode\"), \"manual\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error xticks (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"xticks (-1, [0 1])\", \"HAX must be a handle to an axes\");\n%!   fail (\"tmp = xticks (hax, [0 1])\", \"too many output arguments\");\n%!   fail (\"tmp = xticks (hax, 'auto')\", \"too many .* for arg: auto\");\n%!   fail (\"tmp = xticks (hax, 'foo')\", \"invalid option: foo\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/ylabel.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ylabel (@var{string})\n## @deftypefnx {} {} ylabel (@var{string}, @var{property}, @var{val}, @dots{})\n## @deftypefnx {} {} ylabel (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ylabel (@dots{})\n## Specify the string used to label the y-axis of the current axis.\n##\n## If @var{hax} is specified then label the axis defined by @var{hax}.\n##\n## An optional list of @var{property}/@var{value} pairs can be used to change\n## the properties of the created text label.\n##\n## The full list of text object properties is documented at\n## @ref{Text Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created text\n## object.\n## @seealso{xlabel, zlabel, datetick, title, text}\n## @end deftypefn\n\nfunction h = ylabel (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"ylabel\", varargin{:});\n\n  if (rem (nargin, 2) != 1)\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  htmp = __axis_label__ (hax, \"ylabel\", varargin{1},\n                              \"color\", get (hax, \"ycolor\"),\n                              varargin{2:end});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hy = ylabel (\"ylabel_string\");\n%!   assert (get (gca, \"ylabel\"), hy);\n%!   assert (get (hy, \"type\"), \"text\");\n%!   assert (get (hy, \"visible\"), \"on\");\n%!   assert (get (hy, \"string\"), \"ylabel_string\");\n%!   assert (get (hy, \"color\"), get (0, \"defaultaxesycolor\"));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"fontsize\", 5, \"labelfontsizemultiplier\", 3);\n%!   hy = ylabel (\"ylabel_string\", \"color\", \"r\");\n%!   assert (get (hy, \"fontsize\"), 15);\n%!   assert (get (hy, \"color\"), [1 0 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/ylim.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{ylimits} =} ylim ()\n## @deftypefnx {} {@var{ymode} =} ylim (\"mode\")\n## @deftypefnx {} {@var{ymethod} =} ylim (\"method\")\n## @deftypefnx {} {} ylim ([@var{y_lo} @var{y_hi}])\n## @deftypefnx {} {} ylim (\"mode\")\n## @deftypefnx {} {} ylim (\"method\")\n## @deftypefnx {} {} ylim (@var{hax}, @dots{})\n## Query or set the limits of the y-axis for the current plot.\n##\n## Called without arguments @code{ylim} returns the y-axis limits of the\n## current plot.\n##\n## With the input query @qcode{\"mode\"}, return the current y-limit calculation\n## mode which is either @qcode{\"auto\"} or @qcode{\"manual\"}.\n##\n## With the input query @qcode{\"method\"}, return the current y-limit\n## calculation method which is either @qcode{\"tickaligned\"}, @qcode{\"tight\"},\n## or @qcode{\"padded\"}.\n##\n## If passed a 2-element vector [@var{y_lo} @var{y_hi}], the limits of the\n## y-axis are set to these values and the mode is set to @qcode{\"manual\"}.\n## The special values -Inf and Inf can be used to indicate that either\n## the lower axis limit or upper axis limit should be automatically calculated.\n##\n## The current limit calculation @qcode{\"mode\"} may be one of\n##\n## @table @asis\n## @item @qcode{\"auto\"} (default)\n## Automatically calculate limits based on the plot data and the currently\n## specified limit calculation method.\n##\n## @item @qcode{\"manual\"}\n## Fix axis limits at current values.\n## @end table\n##\n## The current limit calculation method may be one of\n##\n## @table @asis\n## @item @qcode{\"tickaligned\"} (default)\n## Calculate limits that encompass all of the data and extend outwards to the\n## nearest tick mark.\n##\n## @item @qcode{\"tight\"}\n## Calculate limits that exactly fit the data range.\n##\n## @item @qcode{\"padded\"}\n## Calculate limits that leave a margin around the data of approximately 7% of\n## the data range.\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## Programming Note: The @code{ylim} function operates by modifying the\n## @qcode{\"ylim\"}, @qcode{\"ylimmode\"}, and @qcode{\"ylimitmethod\"} properties of\n## an axes object.  These properties can be directly inspected and altered with\n## @code{get}/@code{set}.\n## @seealso{xlim, zlim, axis, set, get, gca}\n## @end deftypefn\n\nfunction ylimits = ylim (varargin)\n\n  lims = __axis_limits__ (\"ylim\", varargin{:});\n\n  if (! isempty (lims))\n    ylimits = lims;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! line ();\n%! ylim ([0.2, 0.8]);\n%! title (\"ylim is [0.2, 0.8]\");\n\n%!demo\n%! clf;\n%! line ();\n%! ylim auto;\n%! title (\"ylim is auto\");\n\n%!demo\n%! clf;\n%! plot3 ([0,1], [0,1], [0,1]);\n%! ylim ([0.2, 0.8]);\n%! title (\"ylim is [0.2, 0.8]\");\n\n%!demo\n%! clf;\n%! plot3 ([0,1], [0,1], [0,1]);\n%! ylim (\"auto\");\n%! title (\"ylim is auto\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   limy = [0, 1.1];\n%!   plot3 ([0,1], [0,1], [0,1]);\n%!   ylim (limy);\n%!   assert (get (gca, \"ylim\"), limy, eps);\n%!   assert (ylim (\"mode\"), \"manual\");\n%!   ylim ('padded');\n%!   assert (get (gca, \"ylimitmethod\"), 'padded');\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot3 ([0,1], [0,1.1], [0, 1]);\n%!   assert (get (gca, \"ylim\"), [0, 1.4], eps);\n%!   assert (ylim (\"mode\"), \"auto\");\n%!   assert (ylim (\"method\"), \"tickaligned\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/ytickangle.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{angle} =} ytickangle ()\n## @deftypefnx {} {@var{angle} =} ytickangle (@var{hax})\n## @deftypefnx {} {} ytickangle (@var{angle})\n## @deftypefnx {} {} ytickangle (@var{hax}, @var{angle})\n## Query or set the rotation angle of the tick labels on the y-axis of the\n## current axes.\n##\n## When called without an argument, return the rotation angle in degrees of the\n## tick labels as specified in the axes property @qcode{\"YTickLabelRotation\"}.\n## When called with a numeric scalar @var{angle}, rotate the tick labels\n## counterclockwise to @var{angle} degrees.\n##\n## If the first argument @var{hax} is an axes handle, then operate on this axes\n## rather than the current axes returned by @code{gca}.\n##\n## Programming Notes:\n## @enumerate\n## @item\n## The @qcode{\"YTickLabelRotation\"} property is @emph{not} currently\n## implemented in Octave.  The property can be set and queried, but has no\n## effect on the plot.\n##\n## @item\n## Requesting a return value while also setting a specified rotation will\n## result in an error.\n## @end enumerate\n##\n## @seealso{xtickangle, ztickangle, get, set}\n## @end deftypefn\n\nfunction angle = ytickangle (hax, angle)\n\n  switch (nargin)\n    case 0\n      angle = __tickangle__ (mfilename ());\n\n    case 1\n      if (nargout > 0)\n        angle = __tickangle__ (mfilename (), hax);\n      else\n        __tickangle__ (mfilename (), hax);\n      endif\n\n    case 2\n      if (nargout > 0)\n        angle = __tickangle__ (mfilename (), hax, angle);\n      else\n        __tickangle__ (mfilename (), hax, angle);\n      endif\n\n  endswitch\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = axes (hf);\n%! unwind_protect\n%!   ytickangle (45);\n%!   assert (ytickangle (), 45);\n%!   ytickangle (hax, 90);\n%!   a1 = ytickangle ();\n%!   a2 = ytickangle (hax);\n%!   assert (a1, a2);\n%!   assert (a1, 90);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <HAX must be a handle to an axes object> ytickangle (0, 45)\n%!error <ANGLE must be .* scalar> ytickangle (eye (2))\n%!error <ANGLE must be .* numeric> ytickangle ({90})\n%!error <ANGLE must be .* finite> ytickangle (Inf)\n%!error <called with output query and input set value> ang = ytickangle (45)\n"
  },
  {
    "path": "scripts/plot/appearance/yticklabels.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{labels} =} yticklabels\n## @deftypefnx {} {@var{mode} =} yticklabels (\"mode\")\n## @deftypefnx {} {} yticklabels (@var{tickval})\n## @deftypefnx {} {} yticklabels (\"auto\")\n## @deftypefnx {} {} yticklabels (\"manual\")\n## @deftypefnx {} {@dots{} =} yticklabels (@var{hax}, @dots{})\n## Query or set the tick labels on the x-axis of the current axis.\n##\n## When called without an argument, return a cell array of strings of the\n## current tick labels as specified in the @qcode{\"yticklabel\"} axes property.\n## These labels can be changed by calling @code{yticklabels} with a cell array\n## of strings.  Note: a vector of numbers will be mapped to a cell array of\n## strings.  If fewer labels are specified than the current number of ticks,\n## blank labels will be appended to the array.\n##\n## When called with argument @qcode{\"mode\"}, @code{yticklabels} returns the\n## current value of the axes property @qcode{\"yticklabelmode\"}.  This property\n## can be changed by calling @code{yticklabels} with either @qcode{\"auto\"}\n## (algorithm determines tick labels) or @qcode{\"manual\"} (tick labels remain\n## fixed).  Note: Specifying yticklabel values will also set the\n## @qcode{\"yticklabelmode\"} and @qcode{\"yticks\"} properties to\n## @qcode{\"manual\"}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{xticklabels} to set a property\n## value will result in an error.\n##\n## @seealso{yticks, xticklabels, zticklabels, get, set}\n## @end deftypefn\n\nfunction labels = yticklabels (varargin)\n\n  hax = [];\n  switch (nargin)\n    case 0\n      labels = get (gca , \"yticklabel\"); # will error if no yticklabel exists.\n      return;\n\n    case 1\n      if (isaxes (varargin{1}))\n        labels = get (varargin{1}, \"yticklabel\");\n        return;\n      else\n        arg = varargin{1};\n      endif\n\n    case 2\n      if (! isaxes (varargin{1}))\n        error (\"yticklabels: HAX must be a handle to an axes object\");\n      endif\n      hax = varargin{1};\n      arg = varargin{2};\n\n    otherwise\n      print_usage ();\n\n  endswitch\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (! (iscell (arg) || isnumeric (arg) || ischar (arg)))\n    print_usage ();\n  endif\n\n  if (isempty (arg))\n    arg = {};  # Either '' or [] are converted empty cell array\n  endif\n\n  if (iscell (arg) || isnumeric (arg))\n    if (nargout > 0)\n      error (\"yticklabels: too many output arguments requested\");\n    endif\n\n    if (isnumeric (arg))\n      ## NOTE: Matlab accepts a cell array, but a non-vector numeric array will\n      ## simply produce a black set of labels without error or warning.\n      ## This implementation allows for a numeric array, which is handled in\n      ## the same order as Matlab handles a cell array\n      arg = num2cell (arg(:));\n    endif\n\n    ## Convert any numeric elements to characters, make it a 1-D cell array.\n    arg = cellfun ('num2str', arg, \"UniformOutput\", false)(:);\n\n    ## Pad with blank cell entries if needed.\n    arg((numel (arg) + 1):(numel (get (hax, \"ytick\")))) = {\"\"};\n\n    ## Setting labels sets both ticklabel and tick mode to manual.\n    set (hax, \"yticklabel\", arg,\n              \"yticklabelmode\", \"manual\",\n              \"ytickmode\", \"manual\");\n\n  else\n    switch (lower (arg))\n      case \"mode\"\n        labels = get (hax, \"yticklabelmode\");\n\n      case {\"auto\", \"manual\"}\n        if (nargout > 0)\n          error ([\"yticklabels: \" ...\n                  \"too many output arguments requested for arg: \", arg]);\n        endif\n        set (hax, \"yticklabelmode\", arg);\n\n      otherwise\n        error (\"yticklabels: invalid option: %s\", arg);\n\n    endswitch\n\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"yticklabelmode\", \"auto\");\n%!   hax = gca ();\n%!   vals1 = yticklabels;\n%!   assert (yticklabels (hax), vals1);\n%!   mode1 = yticklabels (\"mode\");\n%!   assert (yticklabels (hax, \"mode\"), mode1);\n%!   yticklabels (hax, \"manual\");\n%!   assert (yticklabels (hax, \"mode\"), \"manual\");\n%!   yticklabels (hax, \"auto\");\n%!   assert (yticks (hax, \"mode\"), \"auto\");\n%!   yticklabels (hax, {\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"});\n%!   assert (yticklabels (hax), {\"1\"; \"2\"; \"3\"; \"4\"; \"5\"; \"6\"});\n%!   assert (yticklabels (hax, \"mode\"), \"manual\");\n%!   assert (yticks (hax, \"mode\"), \"manual\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error yticklabels (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"yticklabels (-1, {})\", \"HAX must be a handle to an axes\");\n%!   fail (\"tmp = yticklabels (hax, {'A','B'})\", \"too many output arguments\");\n%!   fail (\"tmp = yticklabels (hax, [0, 1])\", \"too many output arguments\");\n%!   fail (\"tmp = yticklabels (hax, 'auto')\", \"too many .* for arg: auto\");\n%!   fail (\"tmp = yticklabels (hax, 'foo')\", \"invalid option: foo\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/yticks.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tickval} =} yticks\n## @deftypefnx {} {@var{mode} =} yticks (\"mode\")\n## @deftypefnx {} {} yticks (@var{tickval})\n## @deftypefnx {} {} yticks (\"auto\")\n## @deftypefnx {} {} yticks (\"manual\")\n## @deftypefnx {} {@dots{} =} yticks (@var{hax}, @dots{})\n## Query or set the tick values on the y-axis of the current axis.\n##\n## When called without an argument, return the current tick locations as\n## specified in the @qcode{\"ytick\"} axes property.  These locations can be\n## changed by calling @code{yticks} with a vector of tick values.  Note:\n## ascending order is not required.\n##\n## When called with argument @qcode{\"mode\"}, @code{yticks} returns the current\n## value of the axes property @qcode{\"ytickmode\"}.  This property can be\n## changed by calling @code{yticks} with either @qcode{\"auto\"} (algorithm\n## determines tick positions) or @qcode{\"manual\"} (tick values remain fixed\n## regardless of axes resizing or rotation).  Note: Specifying ytick values\n## will also set the property @qcode{\"ytickmode\"} to @qcode{\"manual\"}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{yticks} to set a property value\n## will result in an error.\n##\n## @seealso{yticklabels, xticks, zticks, rticks, thetaticks, get, set}\n## @end deftypefn\n\nfunction tickval = yticks (varargin)\n\n  hax = [];\n  switch (nargin)\n    case 0\n      tickval = get (gca , \"ytick\");  # will error if no ytick exists.\n      return;\n\n    case 1\n      if (isaxes (varargin{1}))\n        tickval = get (varargin{1}, \"ytick\");\n        return;\n      else\n        arg = varargin{1};\n      endif\n\n    case 2\n      if (! isaxes (varargin{1}))\n        error (\"yticks: HAX must be a handle to an axes object\");\n      endif\n      hax = varargin{1};\n      arg = varargin{2};\n\n    otherwise\n      print_usage ();\n\n  endswitch\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (isnumeric (arg))\n    if (nargout > 0)\n      error (\"yticks: too many output arguments requested\");\n    else\n     ## NOTE: Matlab errors if tick points are not in ascending order.  Octave\n     ## permits out of order tick points, so error is not produced.\n     set (hax, \"ytick\", arg);\n\n    endif\n\n  elseif (ischar (arg))\n    arg = lower (arg);\n    switch (arg)\n      case \"mode\"\n        tickval = get (hax, \"ytickmode\");\n\n      case {\"auto\", \"manual\"}\n        if (nargout > 0)\n          error (\"yticks: too many output arguments requested for arg: %s\",\n                                                                       arg);\n        endif\n        set (hax, \"ytickmode\", arg);\n\n      otherwise\n        error (\"yticks: invalid option: %s\", arg);\n\n    endswitch\n\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"ytickmode\", \"auto\");\n%!   hax = gca ();\n%!   vals1 = yticks;\n%!   assert (yticks (hax), vals1);\n%!   mode1 = yticks (\"mode\");\n%!   assert (yticks (hax, \"mode\"), mode1);\n%!   yticks (hax, \"manual\");\n%!   assert (yticks (hax, \"mode\"), \"manual\");\n%!   yticks (hax, \"auto\");\n%!   assert (yticks (hax, \"mode\"), \"auto\");\n%!   yticks (hax, [1 2 3 4]);\n%!   assert (yticks (hax), [1 2 3 4]);\n%!   assert (yticks (hax, \"mode\"), \"manual\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error yticks (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"yticks (-1, [0 1])\", \"HAX must be a handle to an axes\");\n%!   fail (\"tmp = yticks (hax, [0 1])\", \"too many output arguments\");\n%!   fail (\"tmp = yticks (hax, 'auto')\", \"too many .* for arg: auto\");\n%!   fail (\"tmp = yticks (hax, 'foo')\", \"invalid option: foo\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/zlabel.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} zlabel (@var{string})\n## @deftypefnx {} {} zlabel (@var{string}, @var{property}, @var{val}, @dots{})\n## @deftypefnx {} {} zlabel (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} zlabel (@dots{})\n## Specify the string used to label the z-axis of the current axis.\n##\n## An optional list of @var{property}/@var{value} pairs can be used to change\n## the properties of the created text label.\n##\n## The full list of text object properties is documented at\n## @ref{Text Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created text\n## object.\n## @seealso{xlabel, ylabel, datetick, title, text}\n## @end deftypefn\n\nfunction h = zlabel (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"zlabel\", varargin{:});\n\n  if (rem (nargin, 2) != 1)\n    print_usage ();\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  htmp = __axis_label__ (hax, \"zlabel\", varargin{1},\n                              \"color\", get (hax, \"zcolor\"),\n                              varargin{2:end});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   hz = zlabel (hax, \"zlabel_string\");\n%!   assert (get (hax, \"zlabel\"), hz);\n%!   assert (get (hz, \"type\"), \"text\");\n%!   assert (get (hz, \"string\"), \"zlabel_string\");\n%!   assert (get (hz, \"color\"), get (0, \"defaultaxeszcolor\"));\n%!   ## The z-label is invisible in 2D\n%!   view (2)\n%!   assert (get (hz, \"visible\"), \"off\");\n%!   ## The z-label is visible in 3D\n%!   view (3)\n%!   assert (get (hz, \"visible\"), \"on\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"fontsize\", 5, \"labelfontsizemultiplier\", 3);\n%!   hz = zlabel (\"zlabel_string\", \"color\", \"r\");\n%!   assert (get (hz, \"fontsize\"), 15);\n%!   assert (get (hz, \"color\"), [1 0 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/zlim.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{zlimits} =} zlim ()\n## @deftypefnx {} {@var{zmode} =} zlim (\"mode\")\n## @deftypefnx {} {@var{zmethod} =} zlim (\"method\")\n## @deftypefnx {} {} zlim ([@var{z_lo} @var{z_hi}])\n## @deftypefnx {} {} zlim (\"mode\")\n## @deftypefnx {} {} zlim (\"method\")\n## @deftypefnx {} {} zlim (@var{hax}, @dots{})\n## Query or set the limits of the z-axis for the current plot.\n##\n## Called without arguments @code{zlim} returns the z-axis limits of the\n## current plot.\n##\n## With the input query @qcode{\"mode\"}, return the current z-limit calculation\n## mode which is either @qcode{\"auto\"} or @qcode{\"manual\"}.\n##\n## With the input query @qcode{\"method\"}, return the current z-limit\n## calculation method which is either @qcode{\"tickaligned\"}, @qcode{\"tight\"},\n## or @qcode{\"padded\"}.\n##\n## If passed a 2-element vector [@var{z_lo} @var{z_hi}], the limits of the\n## z-axis are set to these values and the mode is set to @qcode{\"manual\"}.\n## The special values -Inf and Inf can be used to indicate that either\n## the lower axis limit or upper axis limit should be automatically calculated.\n##\n## The current limit calculation @qcode{\"mode\"} may be one of\n##\n## @table @asis\n## @item @qcode{\"auto\"} (default)\n## Automatically calculate limits based on the plot data and the currently\n## specified limit calculation method.\n##\n## @item @qcode{\"manual\"}\n## Fix axis limits at current values.\n## @end table\n##\n## The current limit calculation method may be one of\n##\n## @table @asis\n## @item @qcode{\"tickaligned\"} (default)\n## Calculate limits that encompass all of the data and extend outwards to the\n## nearest tick mark.\n##\n## @item @qcode{\"tight\"}\n## Calculate limits that exactly fit the data range.\n##\n## @item @qcode{\"padded\"}\n## Calculate limits that leave a margin around the data of approximately 7% of\n## the data range.\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n##\n## Programming Note: The @code{zlim} function operates by modifying the\n## @qcode{\"zlim\"}, @qcode{\"zlimmode\"}, and @qcode{\"zlimitmethod\"} properties of\n## an axes object.  These properties can be directly inspected and altered with\n## @code{get}/@code{set}.\n## @seealso{xlim, ylim, axis, set, get, gca}\n## @end deftypefn\n\nfunction zlimits = zlim (varargin)\n\n  lims = __axis_limits__ (\"zlim\", varargin{:});\n\n  if (! isempty (lims))\n    zlimits = lims;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! line ();\n%! zlim ([0.2, 0.8]);\n%! title (\"zlim is [0.2, 0.8]\");\n\n%!demo\n%! clf;\n%! line ();\n%! zlim (\"auto\");\n%! title (\"zlim is auto\");\n\n%!demo\n%! clf;\n%! plot3 ([0,1], [0,1], [0,1]);\n%! zlim ([0.2, 0.8]);\n%! title (\"zlim is [0.2, 0.8]\");\n\n%!demo\n%! clf;\n%! plot3 ([0,1], [0,1], [0,1]);\n%! zlim auto;\n%! title (\"zlim is auto\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   limz = [0, 1.1];\n%!   plot3 ([0,1], [0,1], [0,1]);\n%!   zlim (limz);\n%!   assert (get (gca, \"zlim\"), limz, eps);\n%!   assert (zlim (\"mode\"), \"manual\");\n%!   zlim ('padded');\n%!   assert (get (gca, \"zlimitmethod\"), 'padded');\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot3 ([0,1], [0,1], [0, 1.1]);\n%!   assert (get (gca, \"zlim\"), [0, 1.4], eps);\n%!   assert (zlim (\"mode\"), \"auto\");\n%!   assert (zlim (\"method\"), \"tickaligned\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/ztickangle.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{angle} =} ztickangle ()\n## @deftypefnx {} {@var{angle} =} ztickangle (@var{hax})\n## @deftypefnx {} {} ztickangle (@var{angle})\n## @deftypefnx {} {} ztickangle (@var{hax}, @var{angle})\n## Query or set the rotation angle of the tick labels on the z-axis of the\n## current axes.\n##\n## When called without an argument, return the rotation angle in degrees of the\n## tick labels as specified in the axes property @qcode{\"ZTickLabelRotation\"}.\n## When called with a numeric scalar @var{angle}, rotate the tick labels\n## counterclockwise to @var{angle} degrees.\n##\n## If the first argument @var{hax} is an axes handle, then operate on this axes\n## rather than the current axes returned by @code{gca}.\n##\n## Programming Notes:\n## @enumerate\n## @item\n## The @qcode{\"ZTickLabelRotation\"} property is @emph{not} currently\n## implemented in Octave.  The property can be set and queried, but has no\n## effect on the plot.\n##\n## @item\n## Requesting a return value while also setting a specified rotation will\n## result in an error.\n## @end enumerate\n##\n## @seealso{xtickangle, ytickangle, get, set}\n## @end deftypefn\n\nfunction angle = ztickangle (hax, angle)\n\n  switch (nargin)\n    case 0\n      angle = __tickangle__ (mfilename ());\n\n    case 1\n      if (nargout > 0)\n        angle = __tickangle__ (mfilename (), hax);\n      else\n        __tickangle__ (mfilename (), hax);\n      endif\n\n    case 2\n      if (nargout > 0)\n        angle = __tickangle__ (mfilename (), hax, angle);\n      else\n        __tickangle__ (mfilename (), hax, angle);\n      endif\n\n  endswitch\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = axes (hf);\n%! unwind_protect\n%!   ztickangle (45);\n%!   assert (ztickangle (), 45);\n%!   ztickangle (hax, 90);\n%!   a1 = ztickangle ();\n%!   a2 = ztickangle (hax);\n%!   assert (a1, a2);\n%!   assert (a1, 90);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <HAX must be a handle to an axes object> ztickangle (0, 45)\n%!error <ANGLE must be .* scalar> ztickangle (eye (2))\n%!error <ANGLE must be .* numeric> ztickangle ({90})\n%!error <ANGLE must be .* finite> ztickangle (Inf)\n%!error <called with output query and input set value> ang = ztickangle (45)\n"
  },
  {
    "path": "scripts/plot/appearance/zticklabels.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{labels} =} zticklabels\n## @deftypefnx {} {@var{mode} =} zticklabels (\"mode\")\n## @deftypefnx {} {} zticklabels (@var{tickval})\n## @deftypefnx {} {} zticklabels (\"auto\")\n## @deftypefnx {} {} zticklabels (\"manual\")\n## @deftypefnx {} {@dots{} =} zticklabels (@var{hax}, @dots{})\n## Query or set the tick labels on the x-axis of the current axis.\n##\n## When called without an argument, return a cell array of strings of the\n## current tick labels as specified in the @qcode{\"zticklabel\"} axes property.\n## These labels can be changed by calling @code{zticklabels} with a cell array\n## of strings.  Note: a vector of numbers will be mapped to a cell array of\n## strings.  If fewer labels are specified than the current number of ticks,\n## blank labels will be appended to the array.\n##\n## When called with argument @qcode{\"mode\"}, @code{zticklabels} returns the\n## current value of the axes property @qcode{\"zticklabelmode\"}.  This property\n## can be changed by calling @code{zticklabels} with either @qcode{\"auto\"}\n## (algorithm determines tick labels) or @qcode{\"manual\"} (tick labels remain\n## fixed).  Note: Specifying zticklabel values will also set the\n## @qcode{\"zticklabelmode\"} and @qcode{\"zticks\"} properties to\n## @qcode{\"manual\"}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{xticklabels} to set a property\n## value will result in an error.\n##\n## @seealso{zticks, xticklabels, zticklabels, get, set}\n## @end deftypefn\n\nfunction labels = zticklabels (varargin)\n\n  hax = [];\n  switch (nargin)\n    case 0\n      labels = get (gca , \"zticklabel\"); # will error if no zticklabel exists.\n      return;\n\n    case 1\n      if (isaxes (varargin{1}))\n        labels = get (varargin{1}, \"zticklabel\");\n        return;\n      else\n        arg = varargin{1};\n      endif\n\n    case 2\n      if (! isaxes (varargin{1}))\n        error (\"zticklabels: HAX must be a handle to an axes object\");\n      endif\n      hax = varargin{1};\n      arg = varargin{2};\n\n    otherwise\n      print_usage ();\n\n  endswitch\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (! (iscell (arg) || isnumeric (arg) || ischar (arg)))\n    print_usage ();\n  endif\n\n  if (isempty (arg))\n    arg = {};  # Either '' or [] are converted empty cell array\n  endif\n\n  if (iscell (arg) || isnumeric (arg))\n    if (nargout > 0)\n      error (\"zticklabels: too many output arguments requested\");\n    endif\n\n    if (isnumeric (arg))\n      ## NOTE: Matlab accepts a cell array, but a non-vector numeric array will\n      ## simply produce a black set of labels without error or warning.\n      ## This implementation allows for a numeric array, which is handled in\n      ## the same order as Matlab handles a cell array\n      arg = num2cell (arg(:));\n    endif\n\n    ## Convert any numeric elements to characters, make it a 1-D cell array.\n    arg = cellfun ('num2str', arg, \"UniformOutput\", false)(:);\n\n    ## Pad with blank cell entries if needed.\n    arg((numel (arg) + 1):(numel (get (hax, \"ztick\")))) = {\"\"};\n\n    ## Setting labels sets both ticklabel and tick mode to manual.\n    set (hax, \"zticklabel\", arg,\n              \"zticklabelmode\", \"manual\",\n              \"ztickmode\", \"manual\");\n\n  elseif (ischar (arg))\n    switch (lower (arg))\n      case \"mode\"\n        labels = get (hax, \"zticklabelmode\");\n\n      case {\"auto\", \"manual\"}\n        if (nargout > 0)\n          error ([\"zticklabels: \" ...\n                  \"too many output arguments requested for arg: \", arg]);\n        endif\n        set (hax, \"zticklabelmode\", arg);\n\n      otherwise\n        error (\"zticklabels: invalid option: %s\", arg);\n\n    endswitch\n\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"zticklabelmode\", \"auto\");\n%!   hax = gca ();\n%!   vals1 = zticklabels;\n%!   assert (zticklabels (hax), vals1);\n%!   mode1 = zticklabels (\"mode\");\n%!   assert (zticklabels (hax, \"mode\"), mode1);\n%!   zticklabels (hax, \"manual\");\n%!   assert (zticklabels (hax, \"mode\"), \"manual\");\n%!   zticklabels (hax, \"auto\");\n%!   assert (zticks (hax, \"mode\"), \"auto\");\n%!   zticklabels (hax, {\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"});\n%!   assert (zticklabels (hax), {\"1\"; \"2\"; \"3\"; \"4\"; \"5\"; \"6\"});\n%!   assert (zticklabels (hax, \"mode\"), \"manual\");\n%!   assert (zticks (hax, \"mode\"), \"manual\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error zticklabels (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"zticklabels (-1, {})\", \"HAX must be a handle to an axes\");\n%!   fail (\"tmp = zticklabels (hax, {'A','B'})\", \"too many output arguments\");\n%!   fail (\"tmp = zticklabels (hax, [0, 1])\", \"too many output arguments\");\n%!   fail (\"tmp = zticklabels (hax, 'auto')\", \"too many .* for arg: auto\");\n%!   fail (\"tmp = zticklabels (hax, 'foo')\", \"invalid option: foo\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/appearance/zticks.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tickval} =} zticks\n## @deftypefnx {} {@var{mode} =} zticks (\"mode\")\n## @deftypefnx {} {} zticks (@var{tickval})\n## @deftypefnx {} {} zticks (\"auto\")\n## @deftypefnx {} {} zticks (\"manual\")\n## @deftypefnx {} {@dots{} =} zticks (@var{hax}, @dots{})\n## Query or set the tick values on the z-axis of the current axis.\n##\n## When called without an argument, return the current tick locations as\n## specified in the @qcode{\"ztick\"} axes property.  These locations can be\n## changed by calling @code{zticks} with a vector of tick values.  Note:\n## ascending order is not required.\n##\n## When called with argument @qcode{\"mode\"}, @code{zticks} returns the current\n## value of the axes property @qcode{\"ztickmode\"}.  This property can be\n## changed by calling @code{zticks} with either @qcode{\"auto\"} (algorithm\n## determines tick positions) or @qcode{\"manual\"} (tick values remain fixed\n## regardless of axes resizing or rotation).  Note: Specifying ztick values\n## will also set the property @qcode{\"ztickmode\"} to @qcode{\"manual\"}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axis rather than the current axes returned by @code{gca}.\n##\n## Requesting a return value when calling @code{zticks} to set a property value\n## will result in an error.\n##\n## @seealso{zticklabels, xticks, yticks, rticks, thetaticks, get, set}\n## @end deftypefn\n\nfunction tickval = zticks (varargin)\n\n  hax = [];\n  switch (nargin)\n    case 0\n      tickval = get (gca , \"ztick\");  # will error if no ztick exists.\n      return;\n\n    case 1\n      if (isaxes (varargin{1}))\n        tickval = get (varargin{1}, \"ztick\");\n        return;\n      else\n        arg = varargin{1};\n      endif\n\n    case 2\n      if (! isaxes (varargin{1}))\n        error (\"zticks: HAX must be a handle to an axes object\");\n      endif\n      hax = varargin{1};\n      arg = varargin{2};\n\n    otherwise\n      print_usage ();\n\n  endswitch\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (isnumeric (arg))\n    if (nargout > 0)\n      error (\"zticks: too many output arguments requested\");\n    endif\n    ## NOTE: Matlab errors if tick points are not in ascending order.  Octave\n    ## permits out of order tick points, so error is not produced.\n    set (hax, \"ztick\", arg);\n\n  elseif (ischar (arg))\n    arg = lower (arg);\n    switch (arg)\n      case \"mode\"\n        tickval = get (hax, \"ztickmode\");\n\n      case {\"auto\", \"manual\"}\n        if (nargout > 0)\n          error (\"zticks: too many output arguments requested for arg: %s\",\n                                                                       arg);\n        endif\n        set (hax, \"ztickmode\", arg);\n\n      otherwise\n        error (\"zticks: invalid option: %s\", arg);\n\n    endswitch\n\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (gca, \"ztickmode\", \"auto\");\n%!   hax = gca ();\n%!   vals1 = zticks;\n%!   assert (zticks (hax), vals1);\n%!   mode1 = zticks (\"mode\");\n%!   assert (zticks (hax, \"mode\"), mode1);\n%!   zticks (hax, \"manual\");\n%!   assert (zticks (hax, \"mode\"), \"manual\");\n%!   zticks (hax, \"auto\");\n%!   assert (zticks (hax, \"mode\"), \"auto\");\n%!   zticks (hax, [1 2 3 4]);\n%!   assert (zticks (hax), [1 2 3 4]);\n%!   assert (zticks (hax, \"mode\"), \"manual\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error zticks (1,2,3)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"zticks (-1, [0 1])\", \"HAX must be a handle to an axes\");\n%!   fail (\"tmp = zticks (hax, [0 1])\", \"too many output arguments\");\n%!   fail (\"tmp = zticks (hax, 'auto')\", \"too many .* for arg: auto\");\n%!   fail (\"tmp = zticks (hax, 'foo')\", \"invalid option: foo\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/plot/draw/area.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} area (@var{y})\n## @deftypefnx {} {} area (@var{x}, @var{y})\n## @deftypefnx {} {} area (@dots{}, @var{lvl})\n## @deftypefnx {} {} area (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} area (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} area (@dots{})\n## Area plot of the columns of @var{y}.\n##\n## This plot shows the contributions of each column value to the row sum.\n## It is functionally similar to @code{plot (@var{x}, cumsum (@var{y}, 2))},\n## except that the area under the curve is shaded.\n##\n## If the @var{x} argument is omitted it defaults to @code{1:rows (@var{y})}.\n## A value @var{lvl} can be defined that determines where the base level of\n## the shading under the curve should be defined.  The default level is 0.\n##\n## Additional property/value pairs are passed directly to the underlying patch\n## object.  The full list of properties is documented at @ref{Patch Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the hggroup\n## object comprising the area patch objects.  The @qcode{\"BaseValue\"} property\n## of the hggroup can be used to adjust the level where shading begins.\n##\n## Example: Verify identity sin^2 + cos^2 = 1\n##\n## @example\n## @group\n## t = linspace (0, 2*pi, 100)';\n## y = [sin(t).^2, cos(t).^2];\n## area (t, y);\n## legend (\"sin^2\", \"cos^2\", \"location\", \"NorthEastOutside\");\n## @end group\n## @end example\n## @seealso{plot, patch}\n## @end deftypefn\n\nfunction h = area (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"area\", varargin{:});\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  x = y = [];\n  bv = 0;\n\n  num_numeric = find (cellfun (\"isclass\", varargin, \"char\"), 1) - 1;\n  if (isempty (num_numeric))\n    num_numeric = nargin;\n  endif\n\n  switch (num_numeric)\n    case 1\n      y = varargin{1};\n    case 2\n      if (isscalar (varargin{2}))\n        y = varargin{1};\n        bv = varargin{2};\n      else\n        x = varargin{1};\n        y = varargin{2};\n      endif\n    case 3\n      x = varargin{1};\n      y = varargin{2};\n      bv = varargin{3};\n    otherwise\n      print_usage ();\n  endswitch\n\n  if (! isreal (x) || ! isreal (y))\n    error (\"area: X and Y must be real vectors or matrices\");\n  endif\n  if (! isreal (bv) || ! isscalar (bv))\n    error (\"area: LVL must be a real scalar\");\n  endif\n\n  if (isvector (y))\n    y = y(:);\n  endif\n  if (isempty (x))\n    x = repmat ([1:rows(y)]', 1, columns (y));\n  elseif (isvector (x))\n    x = repmat (x(:), 1, columns (y));\n  endif\n\n  hax = newplot (hax);\n  htmp = __area__ (hax, x, y, bv, varargin{num_numeric+1:end});\n\n  if (! ishold (hax))\n    set (hax, \"box\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\nfunction retval = __area__ (ax, x, y, bv, varargin)\n\n  y0 = bv * ones (1, rows (y));\n  y0 = zeros (1, rows (y));\n  retval = [];\n  for i = 1: columns (y)\n\n    lc = __next_line_color__ (ax);\n\n    ## Must occur after __next_line_color__ in order to work correctly.\n    hg = hggroup (ax);\n    retval = [retval; hg];\n    args = __add_datasource__ (\"area\", hg, {\"x\", \"y\"}, varargin{:});\n\n    x1 = x(:, 1)';\n    y1 = y(:, i)';\n    addproperty (\"xdata\", hg, \"data\", x1);\n    addproperty (\"ydata\", hg, \"data\", y1);\n\n    addlistener (hg, \"xdata\", @update_data);\n    addlistener (hg, \"ydata\", @update_data);\n\n    if (i == 1)\n      h = patch (ax, [x1(1), x1, fliplr(x1)], [bv, y1, bv*ones(1, length(y1))],\n                     lc, \"parent\", hg);\n    else\n      y1 = y0 + y1;\n      h = patch (ax, [x1(1), x1, fliplr(x1)], [y0(1), y1, fliplr(y0)],\n                     lc, \"parent\", hg);\n    endif\n\n    y0 = y1;\n\n    addproperty (\"basevalue\", hg, \"data\", bv);\n    addlistener (hg, \"basevalue\", @move_baseline);\n\n    addproperty (\"edgealpha\", hg, \"patchedgealpha\", get (h, \"edgealpha\"));\n    addproperty (\"edgecolor\", hg, \"patchedgecolor\", get (h, \"edgecolor\"));\n    addproperty (\"facealpha\", hg, \"patchfacealpha\", get (h, \"facealpha\"));\n    addproperty (\"facecolor\", hg, \"patchfacecolor\", get (h, \"facecolor\"));\n    addproperty (\"linestyle\", hg, \"patchlinestyle\", get (h, \"linestyle\"));\n    addproperty (\"linewidth\", hg, \"patchlinewidth\", get (h, \"linewidth\"));\n\n    addlistener (hg, \"edgealpha\", {@update_prop, \"edgealpha\"});\n    addlistener (hg, \"edgecolor\", {@update_prop, \"edgecolor\"});\n    addlistener (hg, \"facealpha\", {@update_prop, \"facealpha\"});\n    addlistener (hg, \"facecolor\", {@update_prop, \"facecolor\"});\n    addlistener (hg, \"linestyle\", {@update_prop, \"linestyle\"});\n    addlistener (hg, \"linewidth\", {@update_prop, \"linewidth\"});\n\n    addproperty (\"areagroup\", hg, \"data\");\n    set (retval, \"areagroup\", retval);\n\n    ## Deprecated Matlab property which Octave does not implement.\n    addproperty (\"hittestarea\", hg, \"radio\", \"on|{off}\", \"off\");\n\n    if (! isempty (args))\n      set (hg, args{:});\n    endif\n  endfor\n\nendfunction\n\nfunction update_prop (h, ~, prop)\n  kids = get (h, \"children\");\n  set (kids, prop, get (h, prop));\nendfunction\n\nfunction move_baseline (h, ~)\n  persistent recursion = false;\n\n  ## Don't allow recursion\n  if (! recursion)\n    unwind_protect\n      recursion = true;\n      hlist = get (h, \"areagroup\");\n      b0 = get (h, \"basevalue\");\n\n      for hh = hlist(:)'\n        if (hh != h)\n          b1 = get (hh, \"basevalue\");\n          if (b1 != b0)\n            set (hh, \"basevalue\", b0);\n          endif\n        endif\n      endfor\n      update_data (h, []);\n    unwind_protect_cleanup\n      recursion = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\nfunction update_data (h, ~)\n\n  hlist = get (h, \"areagroup\");\n  bv = get (h, \"basevalue\");\n  for i = 1 : length (hlist)\n    hh = hlist(i);\n    x1 = get (hh, \"xdata\")(:);\n    y1 = get (hh, \"ydata\")(:);\n\n    set (get (hh, \"children\"), \"xdata\", [x1(1); x1; flipud(x1)]);\n    if (i == 1)\n      set (get (hh, \"children\"), \"ydata\", [bv; y1; bv*ones(length(y1), 1)]);\n    else\n      y1 = y0 + y1;\n      set (get (hh, \"children\"), \"ydata\", [y0(1); y1; flipud(y0)]);\n    endif\n\n    y0 = y1;\n  endfor\n\nendfunction\n\n\n%!demo\n%! ## Verify identity sin^2 + cos^2 = 1\n%! clf;\n%! t = linspace (0, 2*pi, 100)';\n%! y = [sin(t).^2, cos(t).^2];\n%! area (t, y);\n%! axis tight\n%! legend (\"sin^2\", \"cos^2\", \"location\", \"NorthEastOutside\");\n%! title (\"area() plot\");\n\n%!demo\n%! ## Show effects of setting BaseValue\n%! clf;\n%! x = [-2:0.1:2]';\n%! y = x.^2 - 1;\n%! subplot (1, 2, 1)\n%!  area (x, y);\n%!  title ({\"Parabola y = x^2 -1\";\"BaseValue = 0\"});\n%! subplot (1, 2, 2)\n%!  h = area (x, y);\n%!  set (h, \"basevalue\", -1);\n%!  title ({\"Parabola y = x^2 -1\";\"BaseValue = -1\"});\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! y = rand (size (x));\n%! h = area (x, y);\n%! set (h, \"ydata\", sort (get (h, \"ydata\")));\n%! title (\"area() plot of sorted data\");\n\n## Test input validation\n%!error <Invalid call> area ()\n%!error area (1,2,3,4)\n%!error <X and Y must be real vectors or matrices> area ({1})\n%!error <X and Y must be real vectors or matrices> area (1+i)\n%!error <X and Y must be real vectors or matrices> area (1:2, {1, 2})\n%!error <X and Y must be real vectors or matrices> area (1:2, [1 1+i])\n%!error <LVL must be a real scalar> area (1, i)\n%!error <LVL must be a real scalar> area (1, 2, ones (2,2))\n"
  },
  {
    "path": "scripts/plot/draw/bar.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} bar (@var{y})\n## @deftypefnx {} {} bar (@var{x}, @var{y})\n## @deftypefnx {} {} bar (@dots{}, @var{w})\n## @deftypefnx {} {} bar (@dots{}, @var{style})\n## @deftypefnx {} {} bar (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} bar (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} bar (@dots{}, @var{prop}, @var{val}, @dots{})\n## Produce a bar graph from two vectors of X-Y data.\n##\n## If only one argument is given, @var{y}, it is taken as a vector of Y values\n## and the X coordinates are the range @code{1:numel (@var{y})}.\n##\n## The optional input @var{w} controls the width of the bars.  A value of\n## 1.0 will cause each bar to exactly touch any adjacent bars.\n## The default width is 0.8.\n##\n## If @var{y} is a matrix, then each column of @var{y} is taken to be a\n## separate bar graph plotted on the same graph.  By default the columns\n## are plotted side-by-side.  This behavior can be changed by the @var{style}\n## argument which can take the following values:\n##\n## @table @asis\n## @item @qcode{\"grouped\"} (default)\n## Side-by-side bars with a gap between bars and centered over the\n## X-coordinate.\n##\n## @item  @qcode{\"stacked\"}\n## Bars are stacked so that each X value has a single bar composed of\n## multiple segments.\n##\n## @item @qcode{\"hist\"}\n## Side-by-side bars with no gap between bars and centered over the\n## X-coordinate.\n##\n## @item @qcode{\"histc\"}\n## Side-by-side bars with no gap between bars and left-aligned to the\n## X-coordinate.\n## @end table\n##\n## Optional property/value pairs are passed directly to the underlying patch\n## objects.  The full list of properties is documented at\n## @ref{Patch Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of handles to the created\n## \"bar series\" hggroups with one handle per column of the variable @var{y}.\n## This series makes it possible to change a common element in one bar series\n## object and have the change reflected in the other \"bar series\".\n## For example,\n##\n## @example\n## @group\n## h = bar (rand (5, 10));\n## set (h(1), \"basevalue\", 0.5);\n## @end group\n## @end example\n##\n## @noindent\n## changes the position on the base of all of the bar series.\n##\n## The following example modifies the face and edge colors using\n## property/value pairs.\n##\n## @example\n## bar (randn (1, 100), \"facecolor\", \"r\", \"edgecolor\", \"b\");\n## @end example\n##\n## @noindent\n## The default color for bars is taken from the axes' @qcode{\"ColorOrder\"}\n## property.  The default color for bars when a histogram option\n## (@qcode{\"hist\"}, @qcode{\"histc\"} is used is the @qcode{\"Colormap\"} property\n## of either the axes or figure.  The color of bars can also be set manually\n## using the @qcode{\"facecolor\"} property as shown below.\n##\n## @example\n## @group\n## h = bar (rand (10, 3));\n## set (h(1), \"facecolor\", \"r\")\n## set (h(2), \"facecolor\", \"g\")\n## set (h(3), \"facecolor\", \"b\")\n## @end group\n## @end example\n##\n## @seealso{barh, hist, pie, plot, patch}\n## @end deftypefn\n\nfunction varargout = bar (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  varargout = cell (nargout, 1);\n  [varargout{:}] = __bar__ (\"bar\", true, varargin{:});\n\nendfunction\n\n\n%!demo\n%! clf;\n%! y = rand (11, 1);\n%! h = bar (y);\n%! set (h, \"ydata\", sort (rand (11, 1)));\n%! title (\"bar() graph\");\n\n%!demo\n%! clf;\n%! h = bar (rand (5, 3));\n%! set (h(1), \"facecolor\", \"r\");\n%! set (h(2), \"facecolor\", \"g\");\n%! set (h(3), \"facecolor\", \"b\");\n%! title (\"bar() graph w/multiple bars\");\n\n%!demo\n%! clf;\n%! h = bar (rand (5, 3), \"stacked\");\n%! title (\"bar() graph with stacked style\");\n\n%!demo\n%! clf;\n%! y = -rand (3) .* eye (3) + rand (3) .* (! eye (3));\n%! h = bar (y, \"stacked\");\n%! title (\"stacked bar() graph including intermingled negative values\");\n\n## Tests bar geometry without plotting, using undocumented [x, y] output form.\n%!test\n%! [x, y] = bar (1:3);\n%! assert (x, [0.6, 1.6, 2.6; 0.6, 1.6, 2.6; 1.4, 2.4, 3.4; 1.4, 2.4, 3.4], eps);\n%! assert (y, [0, 0, 0; 1, 2, 3; 1, 2, 3; 0, 0, 0]);\n\n%!test\n%! [x, y] = bar (1:3, 2:4);\n%! assert (x, [0.6, 1.6, 2.6; 0.6, 1.6, 2.6; 1.4, 2.4, 3.4; 1.4, 2.4, 3.4], eps);\n%! assert (y, [0, 0, 0; 2, 3, 4; 2, 3, 4; 0, 0, 0]);\n\n%!test\n%! [x, y] = bar (1:3, 2);\n%! assert (x, [0, 1, 2; 0, 1, 2; 2, 3, 4; 2, 3, 4]);\n%! assert (y, [0, 0, 0; 1, 2, 3; 1, 2, 3; 0, 0, 0]);\n\n%!test\n%! [x, y] = bar (-1:1:1);\n%! assert (x, [0.6, 1.6, 2.6; 0.6, 1.6, 2.6; 1.4, 2.4, 3.4; 1.4, 2.4, 3.4], eps);\n%! assert (y, [0, 0, 0; -1, 0, 1; -1, 0, 1; 0, 0, 0]);\n\n%!test\n%! [x, y] = bar ([1, 2; 3, 4]);\n%! assert (x, cat (3, [0.68, 1.68; 0.68, 1.68; 0.96, 1.96; 0.96, 1.96], ...\n%!                 [1.04, 2.04; 1.04, 2.04; 1.32, 2.32; 1.32, 2.32]), 2*eps);\n%! assert (y, cat (3, [0, 0; 1, 3; 1, 3; 0, 0], [0, 0; 2, 4; 2, 4; 0, 0]));\n\n%!test\n%! [x, y] = bar ([1:3; 4:6]);\n%! assert (x, cat (3, [2, 5; 2, 5; ; 64/25, 139/25; 64/25, 139/25]/3, ...\n%!                 [68 143; 68 143; 82, 157; 82, 157]/75, ...\n%!                 [86/25, 161/25; 86/25, 161/25; 4, 7; 4, 7]/3), 2*eps);\n%! assert (y, cat (3, [0, 0; 1, 4; 1, 4; 0, 0], ...\n%!                    [0, 0; 2, 5; 2, 5; 0, 0], ...\n%!                    [0, 0; 3, 6; 3, 6; 0, 0]));\n\n## Test styles\n%!test\n%! [x, y] = bar ([1:3, 4:6]);\n%! [x1, y1] = bar ([1:3, 4:6], \"grouped\");\n%! assert (x, x1);\n%! assert (y, y1);\n\n%!test\n%! [x, y] = bar ([1:3; 4:6], \"stacked\");\n%! assert (x, cat (3, [0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4], ...\n%!                    [0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4], ...\n%!                    [0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4]), eps);\n%! assert (y, cat (3, [0, 0; 1, 4; 1, 4; 0, 0], ...\n%!                    [1, 4; 3, 9; 3, 9; 1, 4], ...\n%!                    [3, 9; 6, 15; 6, 15; 3, 9]));\n\n%!test\n%! [x, y] = bar ([1:6], \"hist\");\n%! assert (x, [0.5:1:5.5; 0.5:1:5.5; 1.5:1:6.5; 1.5:1:6.5], eps);\n%! assert (y, [zeros(1, 6); 1:6; 1:6; zeros(1, 6)]);\n\n%!test\n%! [x, y] = bar ([1:3; 4:6], \"hist\");\n%! assert (x, cat (3, [17, 42; 17, 42; 67/3, 142/3; 67/3, 142/3]/25, ...\n%!                    [67, 142; 67, 142; 83, 158; 83, 158]/75, ...\n%!                    [83/3, 158/3; 83/3, 158/3; 33, 58; 33, 58]/25), 2*eps);\n%! assert (y, cat (3, [0, 0; 1, 4; 1, 4; 0, 0], ...\n%!                    [0, 0; 2, 5; 2, 5; 0, 0], ...\n%!                    [0, 0; 3, 6; 3, 6; 0, 0]));\n\n%!test\n%! [x, y] = bar ([1:6], \"histc\");\n%! assert (x, [1:6; 1:6; 2:7; 2:7], eps);\n%! assert (y, [zeros(1, 6); 1:6; 1:6; zeros(1, 6)]);\n\n%!test\n%! [x, y] = bar ([1:3; 4:6], \"histc\");\n%! assert (x, cat (3, [75, 150; 75, 150; 91, 166; 91, 166]/75, ...\n%!                    [91, 166; 91, 166; 107, 182; 107, 182]/75, ...\n%!                    [107/3, 182/3; 107/3, 182/3; 41, 66; 41, 66]/25), 2*eps);\n%! assert (y, cat (3, [0, 0; 1, 4; 1, 4; 0, 0], ...\n%!                    [0, 0; 2, 5; 2, 5; 0, 0], ...\n%!                    [0, 0; 3, 6; 3, 6; 0, 0]));\n\n## Test plotting\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!   axesdata = get (hax);\n%!\n%!   assert (isfield (bardata, \"bargroup\"));\n%!   assert (isfield (bardata, \"barlayout\"));\n%!   assert (isfield (bardata, \"barwidth\"));\n%!   assert (isfield (bardata, \"baseline\"));\n%!   assert (isfield (bardata, \"basevalue\"));\n%!   assert (isfield (bardata, \"horizontal\"));\n%!   assert (isfield (bardata, \"showbaseline\"));\n%!   assert (isfield (bardata, \"xdata\"));\n%!   assert (isfield (bardata, \"ydata\"));\n%!\n%!   assert (bardata.parent, hax);\n%!   assert (bardata.bargroup, hb);\n%!   assert (bardata.type, \"hggroup\");\n%!   assert (bardata.barlayout, \"grouped\");\n%!   assert (bardata.barwidth, 0.8);\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.horizontal, \"off\");\n%!   assert (bardata.showbaseline, \"on\");\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!\n%!   assert (baselinedata.type, \"line\");\n%!   assert (baselinedata.ydata, [0, 0]);\n%!   assert (diff (baselinedata.xdata) > 0);\n%!   assert (baselinedata.color, [0, 0, 0]);\n%!   assert (baselinedata.linestyle, \"-\");\n%!\n%!   assert (patchdata.type, \"patch\");\n%!   assert (patchdata.xdata, [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!   assert (patchdata.ydata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (size (patchdata.faces), [3, 4]);\n%!   assert (size (patchdata.vertices), [12, 2]);\n%!\n%!   assert (axesdata.xscale, \"linear\");\n%!   assert (axesdata.xlim, [0.5, 3.5]);\n%!   assert (axesdata.xtick, 1:3);\n%!   assert (get(hax, \"xticklabel\"), {\"1\"; \"2\"; \"3\"});\n%!   assert (axesdata.yscale, \"linear\");\n%!   assert (axesdata.ylim, [0, 4]);\n%!   assert (axesdata.ytick, 0:4);\n%!   assert (axesdata.yticklabel, {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"});\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Style \"stacked\" (no difference for single group).\n%!test\n%! hf1 = figure (\"visible\", \"off\");\n%! hf2 = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax1 = axes (\"parent\", hf1);\n%!   hb1 = bar (hax1, 2:4, \"grouped\");\n%!   bardata1 = get (hb1);\n%!   hl1 = bardata1.baseline;\n%!   baselinedata1 = get (hl1);\n%!   hp1 = bardata1.children;\n%!   patchdata1 = get (hp1);\n%!\n%!   hax2 = axes (\"parent\", hf2);\n%!   hb2 = bar (hax2, 2:4, \"stacked\");\n%!   bardata2 = get (hb2);\n%!   hl2 = bardata2.baseline;\n%!   baselinedata2 = get (hl2);\n%!   hp2 = bardata2.children;\n%!   patchdata2 = get (hp2);\n%!\n%!   assert (bardata1.barlayout, \"grouped\");\n%!   assert (bardata2.barlayout, \"stacked\");\n%!   bardata1.bargroup = [];\n%!   bardata1.barlayout = [];\n%!   bardata1.baseline = [];\n%!   bardata1.children = [];\n%!   bardata1.parent = [];\n%!\n%!   bardata2.bargroup = [];\n%!   bardata2.barlayout = [];\n%!   bardata2.baseline = [];\n%!   bardata2.children = [];\n%!   bardata2.parent = [];\n%!\n%!   baselinedata1.parent = [];\n%!   baselinedata2.parent = [];\n%!   baselinedata1.deletefcn = [];\n%!   baselinedata2.deletefcn = [];\n%!\n%!   patchdata1.parent = [];\n%!   patchdata2.parent = [];\n%!\n%!   assert (isequaln (bardata1, bardata2));\n%!   assert (isequaln (baselinedata1, baselinedata2));\n%!   assert (isequaln (patchdata1, patchdata2));\n%!\n%! unwind_protect_cleanup\n%!   close (hf1);\n%!   close (hf2);\n%! end_unwind_protect\n\n## Style \"hist\".\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4, \"hist\");\n%!   bardata = get (hb);\n%!   assert (isempty (bardata.children));\n%!   assert (! isfield (bardata, \"baseline\"));\n%!   assert (! isfield (bardata, \"barlayout\"));\n%!   assert (! isfield (bardata, \"barwidth\"));\n%!   assert (bardata.type, \"patch\");\n%!   assert (bardata.xdata,  [0.5, 1.5, 2.5;\n%!                            0.5, 1.5, 2.5;\n%!                            1.5, 2.5, 3.5;\n%!                            1.5, 2.5, 3.5], eps);\n%!   assert (bardata.ydata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (size (bardata.faces), [3, 4]);\n%!   assert (size (bardata.vertices), [12, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Style \"histc\".\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4, \"histc\");\n%!   bardata = get (hb);\n%!   assert (isempty (bardata.children));\n%!   assert (! isfield (bardata, \"baseline\"));\n%!   assert (! isfield (bardata, \"barlayout\"));\n%!   assert (! isfield (bardata, \"barwidth\"));\n%!   assert (bardata.type, \"patch\");\n%!   assert (bardata.xdata,  [1:3; 1:3; 2:4; 2:4]);\n%!   assert (bardata.ydata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (size (bardata.faces), [3, 4]);\n%!   assert (size (bardata.vertices), [12, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Bar groups grouped.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, [1:3; 4:6]);\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (numel (hb), 3);\n%!   assert (numel (hp), 3);\n%!   assert (all (strcmp ({bardata.type}, \"hggroup\")));\n%!   assert (bardata(1).baseline, bardata(2).baseline);  # Common baseline\n%!   assert (bardata(1).baseline, bardata(3).baseline);  # Common baseline\n%!   assert (bardata(1).bargroup, bardata(2).bargroup);  # Common hggroup\n%!   assert (bardata(1).bargroup, bardata(3).bargroup);  # Common hggroup\n%!   assert (all (strcmp ({bardata.barlayout}, \"grouped\")));\n%!   assert (all (strcmp ({bardata.horizontal}, \"off\")));\n%!   assert ([bardata.basevalue], [0, 0, 0]);\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [1, 2, 3; 4, 5, 6]);\n%!\n%!   assert (all (strcmp ({patchdata.type}, \"patch\")));\n%!   assert (patchdata(1).xdata, [2, 5;\n%!                                2, 5;\n%!                                64/25, 139/25;\n%!                                64/25, 139/25]/3, eps);\n%!   assert (patchdata(1).ydata, [0, 0; 1, 4; 1, 4; 0, 0]);\n%!   assert (size (patchdata(1).faces), [2, 4]);\n%!   assert (size (patchdata(1).vertices), [8, 2]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Bar groups stacked.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, [1:3; 4:6], \"stacked\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (numel (hb), 3);\n%!   assert (numel (hp), 3);\n%!   assert (all (strcmp ({bardata.type}, \"hggroup\")));\n%!   assert (bardata(1).baseline, bardata(2).baseline);  # Common baseline\n%!   assert (bardata(1).baseline, bardata(3).baseline);  # Common baseline\n%!   assert (bardata(1).bargroup, bardata(2).bargroup);  # Common hggroup\n%!   assert (bardata(1).bargroup, bardata(3).bargroup);  # Common hggroup\n%!   assert (all (strcmp ({bardata.barlayout}, \"stacked\")));\n%!   assert (all (strcmp ({bardata.horizontal}, \"off\")));\n%!\n%!   assert ([bardata.basevalue], [0, 0, 0]);\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [1, 2, 3; 4, 5, 6]);\n%!\n%!   assert (all (strcmp ({patchdata.type}, \"patch\")));\n%!   assert (all (cellfun ('isequal', {patchdata.xdata}, ...\n%!                        {[0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4]})));\n%!   assert (patchdata(1).ydata, [0, 0; 1, 4; 1, 4; 0, 0]);\n%!   assert (patchdata(2).ydata, [1, 4; 3, 9; 3, 9; 1, 4]);\n%!   assert (patchdata(3).ydata, [3, 9; 6, 15; 6, 15; 3, 9]);\n%!   assert (size (patchdata(1).faces), [2, 4]);\n%!   assert (size (patchdata(1).vertices), [8, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Stacked with negative values.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, [-2, 1, 3; 4, -5, 6], \"stacked\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (numel (hb), 3);\n%!   assert (numel (hp), 3);\n%!   assert (all (strcmp ({bardata.type}, \"hggroup\")));\n%!   assert (bardata(1).baseline, bardata(2).baseline);  # Common baseline\n%!   assert (bardata(1).baseline, bardata(3).baseline);  # Common baseline\n%!   assert (bardata(1).bargroup, bardata(2).bargroup);  # Common hggroup\n%!   assert (bardata(1).bargroup, bardata(3).bargroup);  # Common hggroup\n%!   assert (all (strcmp ({bardata.barlayout}, \"stacked\")));\n%!   assert (all (strcmp ({bardata.horizontal}, \"off\")));\n%!\n%!   assert ([bardata.basevalue], [0, 0, 0]);\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [-2, 1, 3; 4, -5, 6]);\n%!\n%!   assert (all (strcmp ({patchdata.type}, \"patch\")));\n%!   assert (all (cellfun ('isequal', {patchdata.xdata}, ...\n%!                        {[0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4]})));\n%!   assert (patchdata(1).ydata, [0, 0; -2, 4; -2, 4; 0, 0]);\n%!   assert (patchdata(2).ydata, [0, 0; 1, -5; 1, -5; 0, 0]);\n%!   assert (patchdata(3).ydata, [1, 4; 4, 10; 4, 10; 1, 4]);\n%!   assert (size (patchdata(1).faces), [2, 4]);\n%!   assert (size (patchdata(1).vertices), [8, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test plot property settings/updates\n## Note: Not testing plot and children visibile settings to avoid creating\n##       test suite artifacts.\n\n## Switch from grouped to stacked.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, [1:3; 4:6], \"grouped\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   ## Verify base behavior.\n%!   assert (all (strcmp ({bardata.barlayout}, \"grouped\")));\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [1, 2, 3; 4, 5, 6]);\n%!   assert (patchdata(1).xdata, [2, 5;\n%!                                2, 5;\n%!                                64/25, 139/25;\n%!                                64/25, 139/25]/3, eps);\n%!   assert (patchdata(1).ydata, [0, 0; 1, 4; 1, 4; 0, 0]);\n%!\n%!   ## Verify changed behavior.\n%!   set (hb, \"barlayout\", \"stacked\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (all (strcmp ({bardata.barlayout}, \"stacked\")));\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [1, 2, 3; 4, 5, 6]);\n%!   assert (all (cellfun ('isequal', {patchdata.xdata}, ...\n%!                        {[0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4]})));\n%!   assert (patchdata(1).ydata, [0, 0; 1, 4; 1, 4; 0, 0]);\n%!   assert (patchdata(2).ydata, [1, 4; 3, 9; 3, 9; 1, 4]);\n%!   assert (patchdata(3).ydata, [3, 9; 6, 15; 6, 15; 3, 9]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Nonzero baseline.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4, \"basevalue\", 3);\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!\n%!   assert (bardata.basevalue, 3);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!\n%!   assert (baselinedata.ydata, [3, 3]);\n%!   assert (diff (baselinedata.xdata) > 0);\n%!\n%!   assert (patchdata.xdata, [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!   assert (patchdata.ydata, [3, 3, 3; 2:4; 2:4; 3, 3, 3]);\n%!   assert (size (patchdata.faces), [3, 4]);\n%!   assert (size (patchdata.vertices), [12, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Color settings.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4, \"facecolor\", \"r\", \"edgecolor\", \"g\");\n%!   bardata = get (hb);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!\n%!   assert (bardata.facecolor, [1, 0, 0]);\n%!   assert (bardata.edgecolor, [0, 1, 0]);\n%!   assert (patchdata.facecolor, [1, 0, 0]);\n%!   assert (patchdata.edgecolor, [0, 1, 0]);\n%!\n%!   set (hb, \"facecolor\", \"b\");\n%!   assert (get (hb, \"facecolor\"), [0, 0, 1]);\n%!   assert (get (hp, \"facecolor\"), [0, 0, 1]);\n%!   set (hb, \"edgecolor\", \"k\");\n%!   assert (get (hb, \"edgecolor\"), [0, 0, 0]);\n%!   assert (get (hp, \"edgecolor\"), [0, 0, 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, [1:3; 4:6], \"facecolor\", \"r\", \"edgecolor\", \"g\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (all (vertcat (bardata.facecolor) == [1, 0, 0]));\n%!   assert (all (vertcat (bardata.edgecolor) == [0, 1, 0]));\n%!   assert (all (vertcat (patchdata.facecolor) == [1, 0, 0]));\n%!   assert (all (vertcat (patchdata.edgecolor) == [0, 1, 0]));\n%!\n%!   set (hb, \"facecolor\", \"b\");\n%!   set (hb, \"edgecolor\", \"k\");\n%!   bardata = get (hb);\n%!   patchdata = get (hp);\n%!   assert (all (vertcat (bardata.facecolor) == [0, 0, 1]));\n%!   assert (all (vertcat (bardata.edgecolor) == [0, 0, 0]));\n%!   assert (all (vertcat (patchdata.facecolor) == [0, 0, 1]));\n%!   assert (all (vertcat (patchdata.edgecolor) == [0, 0, 0]));\n%!\n%!   set (hb(2), \"facecolor\", \"w\");\n%!   set (hb(2), \"edgecolor\", \"r\");\n%!   bardata = get (hb);\n%!   patchdata = get (hp);\n%!   assert (all (vertcat (bardata([1,3]).facecolor) == [0, 0, 1]));\n%!   assert (all (vertcat (bardata([1,3]).edgecolor) == [0, 0, 0]));\n%!   assert (all (vertcat (patchdata([1,3]).facecolor) == [0, 0, 1]));\n%!   assert (all (vertcat (patchdata([1,3]).edgecolor) == [0, 0, 0]));\n%!   assert (bardata(2).facecolor, [1, 1, 1]);\n%!   assert (bardata(2).edgecolor, [1, 0, 0]);\n%!   assert (patchdata(2).facecolor, [1, 1, 1]);\n%!   assert (patchdata(2).edgecolor, [1, 0, 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Switch from vertical to horizontal.\n\n%!test <*65671>  # Baseline should change to horizontal with bars.\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!\n%!   set (hb, \"horizontal\", \"on\");\n%!\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!\n%!   assert (bardata.horizontal, \"on\");\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!\n%!   assert (baselinedata.xdata, [0, 0]);\n%!   assert (diff (baselinedata.ydata) > 0);\n%!\n%!   assert (patchdata.ydata, [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!   assert (patchdata.xdata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (size (patchdata.faces), [3, 4]);\n%!   assert (size (patchdata.vertices), [12, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*65734>  # Axis ticks after change to horizontal should match barh.\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!\n%!   set (hb, \"horizontal\", \"on\");\n%!\n%!   bardata = get (hb);\n%!   axesdata = get (hax);\n%!\n%!   assert (bardata.horizontal, \"on\");\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!\n%!   assert (axesdata.yscale, \"linear\");\n%!   assert (axesdata.ylim, [0.5, 3.5]);\n%!   assert (axesdata.ytick, 1:3);\n%!   assert (get(hax, \"yticklabel\"), {\"1\"; \"2\"; \"3\"});\n%!   assert (axesdata.xscale, \"linear\");\n%!   assert (axesdata.xlim, [0, 4]);\n%!   assert (axesdata.xtick, 0:4);\n%!   assert (axesdata.xticklabel, {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"});\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check baseline updating subfunctions.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!   assert (baselinedata.ydata, [0, 0]);\n%!   assert (baselinedata.xdata, [0.5, 3.5], eps);\n%!   assert (patchdata.xdata, [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!   assert (patchdata.ydata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!\n%!   set (hax, \"xlim\", [0, 5]);  # Change axes limits, verify baseline match.\n%!   assert (get (hl, \"xdata\"), [0, 5]);\n%!\n%!   set (hb, \"basevalue\", 2);  # Change line position through bar object.\n%!   axesdata = get (hax);\n%!   assert (get (hb, \"basevalue\"), 2);\n%!   assert (get (hl, \"ydata\"), [2, 2]);\n%!   assert (axesdata.ylim, [2, 4]);\n%!   assert (axesdata.ytick, [2:0.5:4], eps);\n%!   assert (axesdata.yticklabel, {\"2\"; \"2.5\"; \"3\"; \"3.5\"; \"4\"});\n%!   assert (get (hp, \"ydata\"), [2, 2, 2; 2:4; 2:4; 2, 2, 2]);\n%!\n%!   set (hl, \"ydata\", [-1 -1]);  # Change line position directly.\n%!   axesdata = get (hax);\n%!   assert (get (hb, \"basevalue\"), -1);\n%!   assert (get (hl, \"ydata\"), [-1, -1]);\n%!   assert (axesdata.ylim, [-1, 4]);\n%!   assert (axesdata.ytick, [-1:4], eps);\n%!   assert (axesdata.yticklabel, {\"-1\"; \"0\"; \"1\"; \"2\"; \"3\"; \"4\"});\n%!   assert (get (hp, \"ydata\"), [-1, -1, -1; 2:4; 2:4; -1, -1, -1]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Change linear/log scale and move baseline/patch values if needed.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!   assert (baselinedata.ydata, [0, 0]);\n%!   assert (baselinedata.xdata, [0.5, 3.5], eps);\n%!   assert (get (hax, \"yscale\"), \"linear\");\n%!   assert (get (hp, \"ydata\"), [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!\n%!   warning (\"off\", \"Octave:negative-data-log-axis\", \"local\");\n%!   set (hax, \"yscale\", \"log\");\n%!   assert (get (hax, \"yscale\"), \"log\");\n%!   assert (get (hb, \"basevalue\"), 1);\n%!   assert (get (hl, \"ydata\"), [1, 1]);\n%!   assert (get (hp, \"ydata\"), [1, 1, 1; 2:4; 2:4; 1, 1, 1]);\n%!\n%!   set (hax, \"yscale\", \"linear\");\n%!   assert (get (hax, \"yscale\"), \"linear\");\n%!   assert (get (hb, \"basevalue\"), 0);\n%!   assert (get (hl, \"ydata\"), [0, 0]);\n%!   assert (get (hp, \"ydata\"), [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Updating base plot xdata.\n%!test <*65734>  # Changing xdata should update xlim/ticks for new locations.\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   xd = [0.6, 1.6, 2.6; 0.6, 1.6, 2.6; 1.4, 2.4, 3.4; 1.4, 2.4, 3.4];\n%!\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   ## Verify base behavior.\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hp, \"xdata\"), xd, eps);\n%!   assert (get (hax, \"xlim\"), [0.5, 3.5], eps);\n%!   assert (get (hax, \"xtick\"), 1:3);\n%!   assert (get (hax, \"xticklabel\"), {\"1\"; \"2\"; \"3\"});\n%!\n%!   ## Verify changed behavior.\n%!   set (hb, \"xdata\", [3:5]');\n%!   assert (get (hb, \"xdata\"), [3:5]');\n%!   assert (get (hp, \"xdata\"), xd + 2, eps);\n%!   assert (get (hax, \"xlim\"), [0.5, 3.5] + 2, eps);\n%!   assert (get (hax, \"xtick\"), 3:5);\n%!   assert (get (hax, \"xticklabel\"), {\"3\"; \"4\"; \"5\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Updating base plot ydata.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   ## Verify base behavior.\n%!   assert (get (hb, \"ydata\"), [2:4]');\n%!   assert (get (hp, \"ydata\"), [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (get (hax, \"ylim\"), [0, 4]);\n%!   assert (get (hax, \"ytick\"), 0:4);\n%!   assert (get (hax, \"yticklabel\"), {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"});\n%!\n%!   ## Verify changed behavior.\n%!   set (hb, \"ydata\", [-2, 1, 3]');\n%!   assert (get (hb, \"ydata\"), [-2, 1, 3]');\n%!   assert (get (hp, \"ydata\"), [0, 0, 0; -2, 1, 3; -2, 1, 3; 0, 0, 0]);\n%!   assert (get (hax, \"ylim\"), [-2, 3]);\n%!   assert (get (hax, \"ytick\"), -2:3);\n%!   assert (get (hax, \"yticklabel\"), {\"-2\"; \"-1\"; \"0\"; \"1\"; \"2\"; \"3\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Updating barwidth.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   ## Verify base behavior.\n%!   assert (get (hb, \"barwidth\"), 0.8, eps);\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hp, \"xdata\"), [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!\n%!   ## Verify changed behavior.\n%!   set (hb, \"barwidth\", 0.5);\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hp, \"xdata\"), [0.75, 1.75, 2.75;\n%!                               0.75, 1.75, 2.75;\n%!                               1.25, 2.25, 3.25;\n%!                               1.25, 2.25, 3.25], eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Ensure x tick labels are updated with xdata changes.\n%!test <*65734>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[0.5, 3.5], 1:3, {\"1\"; \"2\"; \"3\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[0, 4], [0:4], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"}});\n%!\n%!   set (hb, \"xdata\", [3:5]');  # column vector input.\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[2.5, 5.5], 3:5, {\"3\"; \"4\"; \"5\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[0, 4], [0:4], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"}});\n%!\n%!   set (hb, \"xdata\", [9:11]);  # row vector input.\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[8.5, 11.5], 9:11, {\"9\"; \"10\"; \"11\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[0, 4], [0:4], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"}});\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Ensure y tick labels are updated with ydata changes.\n%!test <*65734>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[0.5, 3.5], 1:3, {\"1\"; \"2\"; \"3\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[0, 4], [0:4], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"}});\n%!\n%!   set (hb, \"ydata\", [5:7]');  # column vector input.\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[0.5, 3.5], 1:3, {\"1\"; \"2\"; \"3\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[0, 7], [0:7], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"; \"5\"; \"6\"; \"7\"}});\n%!\n%!   set (hb, \"ydata\", [-4:-2]);  # row vector input.\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[0.5, 3.5], 1:3, {\"1\"; \"2\"; \"3\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[-4, 0], [-4:0], {\"-4\"; \"-3\"; \"-2\"; \"-1\"; \"0\"}});\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Ensure no errors on plot replacement.\n%!test <*67006>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = bar (hax, 2:4);\n%!   hb = bar (hax, 5:7);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%% Test input validation\n%!error <Invalid call> bar ()\n%!error <Y must be numeric> bar (\"foo\")\n%!error <X must be a vector> bar ([1 2; 3 4], [1 2 3 4])\n%!error <X vector values must be unique> bar ([1 2 3 3], [1 2 3 4])\n%!error <length of X and Y must be equal> bar ([1 2 3], [1 2 3 4])\n%!error <length of X and Y must be equal> bar ([1 2 3 4], [1 2 3])\n"
  },
  {
    "path": "scripts/plot/draw/barh.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} barh (@var{y})\n## @deftypefnx {} {} barh (@var{x}, @var{y})\n## @deftypefnx {} {} barh (@dots{}, @var{w})\n## @deftypefnx {} {} barh (@dots{}, @var{style})\n## @deftypefnx {} {} barh (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} barh (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} barh (@dots{}, @var{prop}, @var{val}, @dots{})\n## Produce a horizontal bar graph from two vectors of X-Y data.\n##\n## If only one argument is given, it is taken as a vector of Y values\n## and the X coordinates are the range @code{1:numel (@var{y})}.\n##\n## The optional input @var{w} controls the width of the bars.  A value of\n## 1.0 will cause each bar to exactly touch any adjacent bars.\n## The default width is 0.8.\n##\n## If @var{y} is a matrix, then each column of @var{y} is taken to be a\n## separate bar graph plotted on the same graph.  By default the columns\n## are plotted side-by-side.  This behavior can be changed by the @var{style}\n## argument which can take the following values:\n##\n## @table @asis\n## @item @qcode{\"grouped\"} (default)\n## Side-by-side bars with a gap between bars and centered over the\n## Y-coordinate.\n##\n## @item  @qcode{\"stacked\"}\n## Bars are stacked so that each Y value has a single bar composed of\n## multiple segments.\n##\n## @item @qcode{\"hist\"}\n## Side-by-side bars with no gap between bars and centered over the\n## Y-coordinate.\n##\n## @item @qcode{\"histc\"}\n## Side-by-side bars with no gap between bars and left-aligned to the\n## Y-coordinate.\n## @end table\n##\n## Optional property/value pairs are passed directly to the underlying patch\n## objects.  The full list of properties is documented at\n## @ref{Patch Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## bar series hggroup.  For a description of the use of the\n## bar series, @pxref{XREFbar,,@code{bar}}.\n## @seealso{bar, hist, pie, plot, patch}\n## @end deftypefn\n\nfunction varargout = barh (varargin)\n  if (nargin < 1)\n    print_usage;\n  endif\n  varargout = cell (nargout, 1);\n  [varargout{:}] = __bar__ (\"barh\", false, varargin{:});\nendfunction\n\n\n%!demo\n%! clf;\n%! x = rand (10, 1);\n%! barh (x);\n%! title (\"barh() graph\");\n\n%!demo\n%! clf;\n%! h = barh (rand (5, 3));\n%! set (h(1), \"facecolor\", \"r\");\n%! set (h(2), \"facecolor\", \"g\");\n%! set (h(3), \"facecolor\", \"b\");\n%! title (\"barh() graph w/multiple bars\");\n\n%!demo\n%! clf;\n%! x = -rand (3) .* eye (3) + rand (3) .* (! eye (3));\n%! h = barh (x, \"stacked\");\n%! title (\"stacked barh() graph including intermingled negative values\");\n\n## Tests of bar geometry without plotting, using undocumented [x, y] output\n%!test\n%! [x, y] = barh (1:3);\n%! assert (y, [0.6, 1.6, 2.6; 0.6, 1.6, 2.6; 1.4, 2.4, 3.4; 1.4, 2.4, 3.4], eps);\n%! assert (x, [0, 0, 0; 1, 2, 3; 1, 2, 3; 0, 0, 0]);\n\n%!test\n%! [x, y] = barh (1:3, 2:4);\n%! assert (y, [0.6, 1.6, 2.6; 0.6, 1.6, 2.6; 1.4, 2.4, 3.4; 1.4, 2.4, 3.4], eps);\n%! assert (x, [0, 0, 0; 2, 3, 4; 2, 3, 4; 0, 0, 0]);\n\n%!test\n%! [x, y] = barh (1:3, 2);\n%! assert (y, [0, 1, 2; 0, 1, 2; 2, 3, 4; 2, 3, 4]);\n%! assert (x, [0, 0, 0; 1, 2, 3; 1, 2, 3; 0, 0, 0]);\n\n%!test\n%! [x, y] = barh (-1:1:1);\n%! assert (y, [0.6, 1.6, 2.6; 0.6, 1.6, 2.6; 1.4, 2.4, 3.4; 1.4, 2.4, 3.4], eps);\n%! assert (x, [0, 0, 0; -1, 0, 1; -1, 0, 1; 0, 0, 0]);\n\n%!test\n%! [x, y] = barh ([1, 2; 3, 4]);\n%! assert (y, cat (3, [0.68, 1.68; 0.68, 1.68; 0.96, 1.96; 0.96, 1.96], ...\n%!                 [1.04, 2.04; 1.04, 2.04; 1.32, 2.32; 1.32, 2.32]), 2*eps);\n%! assert (x, cat (3, [0, 0; 1, 3; 1, 3; 0, 0], [0, 0; 2, 4; 2, 4; 0, 0]));\n\n%!test\n%! [x, y] = barh ([1:3; 4:6]);\n%! assert (y, cat (3, [2, 5; 2, 5; ; 64/25, 139/25; 64/25, 139/25]/3, ...\n%!                 [68 143; 68 143; 82, 157; 82, 157]/75, ...\n%!                 [86/25, 161/25; 86/25, 161/25; 4, 7; 4, 7]/3), 2*eps);\n%! assert (x, cat (3, [0, 0; 1, 4; 1, 4; 0, 0], ...\n%!                    [0, 0; 2, 5; 2, 5; 0, 0], ...\n%!                    [0, 0; 3, 6; 3, 6; 0, 0]));\n\n## Test styles grouped staced hist histc\n%!test\n%! [x, y] = barh ([1:3, 4:6]);\n%! [x1, y1] = barh ([1:3, 4:6], \"grouped\");\n%! assert (x, x1);\n%! assert (y, y1);\n\n%!test\n%! [x, y] = barh ([1:3; 4:6], \"stacked\");\n%! assert (y, cat (3, [0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4], ...\n%!                    [0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4], ...\n%!                    [0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4]), eps);\n%! assert (x, cat (3, [0, 0; 1, 4; 1, 4; 0, 0], ...\n%!                    [1, 4; 3, 9; 3, 9; 1, 4], ...\n%!                    [3, 9; 6, 15; 6, 15; 3, 9]));\n\n%!test\n%! [x, y] = barh ([1:6], \"hist\");\n%! assert (y, [0.5:1:5.5; 0.5:1:5.5; 1.5:1:6.5; 1.5:1:6.5], eps);\n%! assert (x, [zeros(1, 6); 1:6; 1:6; zeros(1, 6)]);\n\n%!test\n%! [x, y] = barh ([1:3; 4:6], \"hist\");\n%! assert (y, cat (3, [17, 42; 17, 42; 67/3, 142/3; 67/3, 142/3]/25, ...\n%!                    [67, 142; 67, 142; 83, 158; 83, 158]/75, ...\n%!                    [83/3, 158/3; 83/3, 158/3; 33, 58; 33, 58]/25), 2*eps);\n%! assert (x, cat (3, [0, 0; 1, 4; 1, 4; 0, 0], ...\n%!                    [0, 0; 2, 5; 2, 5; 0, 0], ...\n%!                    [0, 0; 3, 6; 3, 6; 0, 0]));\n\n%!test\n%! [x, y] = barh ([1:6], \"histc\");\n%! assert (y, [1:6; 1:6; 2:7; 2:7], eps);\n%! assert (x, [zeros(1, 6); 1:6; 1:6; zeros(1, 6)]);\n\n%!test\n%! [x, y] = barh ([1:3; 4:6], \"histc\");\n%! assert (y, cat (3, [75, 150; 75, 150; 91, 166; 91, 166]/75, ...\n%!                    [91, 166; 91, 166; 107, 182; 107, 182]/75, ...\n%!                    [107/3, 182/3; 107/3, 182/3; 41, 66; 41, 66]/25), 2*eps);\n%! assert (x, cat (3, [0, 0; 1, 4; 1, 4; 0, 0], ...\n%!                    [0, 0; 2, 5; 2, 5; 0, 0], ...\n%!                    [0, 0; 3, 6; 3, 6; 0, 0]));\n\n\n## Test plotting\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!   axesdata = get (hax);\n%!\n%!   assert (isfield (bardata, \"bargroup\"));\n%!   assert (isfield (bardata, \"barlayout\"));\n%!   assert (isfield (bardata, \"barwidth\"));\n%!   assert (isfield (bardata, \"baseline\"));\n%!   assert (isfield (bardata, \"basevalue\"));\n%!   assert (isfield (bardata, \"horizontal\"));\n%!   assert (isfield (bardata, \"showbaseline\"));\n%!   assert (isfield (bardata, \"xdata\"));\n%!   assert (isfield (bardata, \"ydata\"));\n%!\n%!   assert (bardata.parent, hax);\n%!   assert (bardata.bargroup, hb);\n%!   assert (bardata.type, \"hggroup\");\n%!   assert (bardata.barlayout, \"grouped\");\n%!   assert (bardata.barwidth, 0.8);\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.horizontal, \"on\");\n%!   assert (bardata.showbaseline, \"on\");\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!\n%!   assert (patchdata.type, \"patch\");\n%!   assert (patchdata.ydata, [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!   assert (patchdata.xdata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (size (patchdata.faces), [3, 4]);\n%!   assert (size (patchdata.vertices), [12, 2]);\n%!\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Baseline must be vertical for barh.\n%!test <*65671>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   hl = get (hb, \"baseline\");\n%!   baselinedata = get (hl);\n%!\n%!   assert (baselinedata.type, \"line\");\n%!   assert (baselinedata.xdata, [0, 0]);\n%!   assert (diff (baselinedata.ydata) > 0);\n%!   assert (baselinedata.color, [0, 0, 0]);\n%!   assert (baselinedata.linestyle, \"-\");\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## barh axes limits and labels should match inverse of bar.\n%!test <65671>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   axesdata = get (hax);\n%!   assert (axesdata.ylim, [0.5, 3.5]);\n%!   assert (axesdata.ytick, 1:3);\n%!   assert (axesdata.yticklabel, {\"1\"; \"2\"; \"3\"});\n%!   assert (axesdata.xscale, \"linear\");\n%!   assert (axesdata.xlim, [0, 4]);\n%!   assert (axesdata.xtick, 0:4);\n%!   assert (axesdata.xticklabel, {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"});\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Style \"stacked\" (no difference for single group).\n%!test\n%! hf1 = figure (\"visible\", \"off\");\n%! hf2 = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax1 = axes (\"parent\", hf1);\n%!   hb1 = barh (hax1, 2:4, \"grouped\");\n%!   bardata1 = get (hb1);\n%!   hl1 = bardata1.baseline;\n%!   baselinedata1 = get (hl1);\n%!   hp1 = bardata1.children;\n%!   patchdata1 = get (hp1);\n%!\n%!   hax2 = axes (\"parent\", hf2);\n%!   hb2 = barh (hax2, 2:4, \"stacked\");\n%!   bardata2 = get (hb2);\n%!   hl2 = bardata2.baseline;\n%!   baselinedata2 = get (hl2);\n%!   hp2 = bardata2.children;\n%!   patchdata2 = get (hp2);\n%!\n%!   assert (bardata1.barlayout, \"grouped\");\n%!   assert (bardata2.barlayout, \"stacked\");\n%!   bardata1.bargroup = [];\n%!   bardata1.barlayout = [];\n%!   bardata1.baseline = [];\n%!   bardata1.children = [];\n%!   bardata1.parent = [];\n%!\n%!   bardata2.bargroup = [];\n%!   bardata2.barlayout = [];\n%!   bardata2.baseline = [];\n%!   bardata2.children = [];\n%!   bardata2.parent = [];\n%!\n%!   baselinedata1.parent = [];\n%!   baselinedata2.parent = [];\n%!   baselinedata1.deletefcn = [];\n%!   baselinedata2.deletefcn = [];\n%!\n%!   patchdata1.parent = [];\n%!   patchdata2.parent = [];\n%!\n%!   assert (isequaln (bardata1, bardata2));\n%!   assert (isequaln (baselinedata1, baselinedata2));\n%!   assert (isequaln (patchdata1, patchdata2));\n%!\n%! unwind_protect_cleanup\n%!   close (hf1);\n%!   close (hf2);\n%! end_unwind_protect\n\n## Style \"hist\"\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4, \"hist\");\n%!   bardata = get (hb);\n%!   assert (isempty (bardata.children));\n%!   assert (! isfield (bardata, \"baseline\"));\n%!   assert (! isfield (bardata, \"barlayout\"));\n%!   assert (! isfield (bardata, \"barwidth\"));\n%!   assert (bardata.type, \"patch\");\n%!   assert (bardata.ydata,  [0.5, 1.5, 2.5;\n%!                            0.5, 1.5, 2.5;\n%!                            1.5, 2.5, 3.5;\n%!                            1.5, 2.5, 3.5], eps);\n%!   assert (bardata.xdata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (size (bardata.faces), [3, 4]);\n%!   assert (size (bardata.vertices), [12, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Style \"histc\"\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4, \"histc\");\n%!   bardata = get (hb);\n%!   assert (isempty (bardata.children));\n%!   assert (! isfield (bardata, \"baseline\"));\n%!   assert (! isfield (bardata, \"barlayout\"));\n%!   assert (! isfield (bardata, \"barwidth\"));\n%!   assert (bardata.type, \"patch\");\n%!   assert (bardata.ydata,  [1:3; 1:3; 2:4; 2:4]);\n%!   assert (bardata.xdata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (size (bardata.faces), [3, 4]);\n%!   assert (size (bardata.vertices), [12, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Bar groups grouped.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, [1:3; 4:6]);\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (numel (hb), 3);\n%!   assert (numel (hp), 3);\n%!   assert (all (strcmp ({bardata.type}, \"hggroup\")));\n%!   assert (bardata(1).baseline, bardata(2).baseline);  # Common baseline\n%!   assert (bardata(1).baseline, bardata(3).baseline);  # Common baseline\n%!   assert (bardata(1).bargroup, bardata(2).bargroup);  # Common hggroup\n%!   assert (bardata(1).bargroup, bardata(3).bargroup);  # Common hggroup\n%!   assert (all (strcmp ({bardata.barlayout}, \"grouped\")));\n%!   assert (all (strcmp ({bardata.horizontal}, \"on\")));\n%!   assert ([bardata.basevalue], [0, 0, 0]);\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [1, 2, 3; 4, 5, 6]);\n%!\n%!   assert (all (strcmp ({patchdata.type}, \"patch\")));\n%!   assert (patchdata(1).ydata, [2, 5;\n%!                                2, 5;\n%!                                64/25, 139/25;\n%!                                64/25, 139/25]/3, eps);\n%!   assert (patchdata(1).xdata, [0, 0; 1, 4; 1, 4; 0, 0]);\n%!   assert (size (patchdata(1).faces), [2, 4]);\n%!   assert (size (patchdata(1).vertices), [8, 2]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Bar groups stacked.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, [1:3; 4:6], \"stacked\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (numel (hb), 3);\n%!   assert (numel (hp), 3);\n%!   assert (all (strcmp ({bardata.type}, \"hggroup\")));\n%!   assert (bardata(1).baseline, bardata(2).baseline);  # Common baseline\n%!   assert (bardata(1).baseline, bardata(3).baseline);  # Common baseline\n%!   assert (bardata(1).bargroup, bardata(2).bargroup);  # Common hggroup\n%!   assert (bardata(1).bargroup, bardata(3).bargroup);  # Common hggroup\n%!   assert (all (strcmp ({bardata.barlayout}, \"stacked\")));\n%!   assert (all (strcmp ({bardata.horizontal}, \"on\")));\n%!\n%!   assert ([bardata.basevalue], [0, 0, 0]);\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [1, 2, 3; 4, 5, 6]);\n%!\n%!   assert (all (strcmp ({patchdata.type}, \"patch\")));\n%!   assert (all (cellfun ('isequal', {patchdata.ydata}, ...\n%!                        {[0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4]})));\n%!   assert (patchdata(1).xdata, [0, 0; 1, 4; 1, 4; 0, 0]);\n%!   assert (patchdata(2).xdata, [1, 4; 3, 9; 3, 9; 1, 4]);\n%!   assert (patchdata(3).xdata, [3, 9; 6, 15; 6, 15; 3, 9]);\n%!   assert (size (patchdata(1).faces), [2, 4]);\n%!   assert (size (patchdata(1).vertices), [8, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Stacked with negative values.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, [-2, 1, 3; 4, -5, 6], \"stacked\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (numel (hb), 3);\n%!   assert (numel (hp), 3);\n%!   assert (all (strcmp ({bardata.type}, \"hggroup\")));\n%!   assert (bardata(1).baseline, bardata(2).baseline);  # Common baseline\n%!   assert (bardata(1).baseline, bardata(3).baseline);  # Common baseline\n%!   assert (bardata(1).bargroup, bardata(2).bargroup);  # Common hggroup\n%!   assert (bardata(1).bargroup, bardata(3).bargroup);  # Common hggroup\n%!   assert (all (strcmp ({bardata.barlayout}, \"stacked\")));\n%!   assert (all (strcmp ({bardata.horizontal}, \"on\")));\n%!\n%!   assert ([bardata.basevalue], [0, 0, 0]);\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [-2, 1, 3; 4, -5, 6]);\n%!\n%!   assert (all (strcmp ({patchdata.type}, \"patch\")));\n%!   assert (all (cellfun ('isequal', {patchdata.ydata}, ...\n%!                        {[0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4]})));\n%!   assert (patchdata(1).xdata, [0, 0; -2, 4; -2, 4; 0, 0]);\n%!   assert (patchdata(2).xdata, [0, 0; 1, -5; 1, -5; 0, 0]);\n%!   assert (patchdata(3).xdata, [1, 4; 4, 10; 4, 10; 1, 4]);\n%!   assert (size (patchdata(1).faces), [2, 4]);\n%!   assert (size (patchdata(1).vertices), [8, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test plot property settings/updates\n## Note: Not testing plot and children visibility settings to avoid creating\n##       test suite artifacts.\n\n## Switch from grouped to stacked.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, [1:3; 4:6], \"grouped\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   ## Verify base behavior.\n%!   assert (all (strcmp ({bardata.barlayout}, \"grouped\")));\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [1, 2, 3; 4, 5, 6]);\n%!   assert (patchdata(1).ydata, [2, 5;\n%!                                2, 5;\n%!                                64/25, 139/25;\n%!                                64/25, 139/25]/3, eps);\n%!   assert (patchdata(1).xdata, [0, 0; 1, 4; 1, 4; 0, 0]);\n%!\n%!   ## Verify changed behavior.\n%!   set (hb, \"barlayout\", \"stacked\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (all (strcmp ({bardata.barlayout}, \"stacked\")));\n%!   assert ([bardata.xdata], [1, 1, 1; 2, 2, 2]);\n%!   assert ([bardata.ydata], [1, 2, 3; 4, 5, 6]);\n%!   assert (all (cellfun ('isequal', {patchdata.ydata}, ...\n%!                        {[0.6, 1.6; 0.6, 1.6; 1.4, 2.4; 1.4, 2.4]})));\n%!   assert (patchdata(1).xdata, [0, 0; 1, 4; 1, 4; 0, 0]);\n%!   assert (patchdata(2).xdata, [1, 4; 3, 9; 3, 9; 1, 4]);\n%!   assert (patchdata(3).xdata, [3, 9; 6, 15; 6, 15; 3, 9]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Nonzero baseline\n%!test <*65671>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4, \"basevalue\", 3);\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!\n%!   assert (bardata.basevalue, 3);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!\n%!   assert (baselinedata.xdata, [3, 3]);\n%!   assert (diff (baselinedata.ydata) > 0);\n%!\n%!   assert (patchdata.ydata, [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!   assert (patchdata.xdata, [3, 3, 3; 2:4; 2:4; 3, 3, 3]);\n%!   assert (size (patchdata.faces), [3, 4]);\n%!   assert (size (patchdata.vertices), [12, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Color setting and changing:\n%!test  # Single group\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4, \"facecolor\", \"r\", \"edgecolor\", \"g\");\n%!   bardata = get (hb);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!\n%!   assert (bardata.facecolor, [1, 0, 0]);\n%!   assert (bardata.edgecolor, [0, 1, 0]);\n%!   assert (patchdata.facecolor, [1, 0, 0]);\n%!   assert (patchdata.edgecolor, [0, 1, 0]);\n%!\n%!   set (hb, \"facecolor\", \"b\");\n%!   assert (get (hb, \"facecolor\"), [0, 0, 1]);\n%!   assert (get (hp, \"facecolor\"), [0, 0, 1]);\n%!   set (hb, \"edgecolor\", \"k\");\n%!   assert (get (hb, \"edgecolor\"), [0, 0, 0]);\n%!   assert (get (hp, \"edgecolor\"), [0, 0, 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test # Multiple groups\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, [1:3; 4:6], \"facecolor\", \"r\", \"edgecolor\", \"g\");\n%!   bardata = get (hb);\n%!   hp = [bardata.children](:);\n%!   patchdata = get (hp);\n%!\n%!   assert (all (vertcat (bardata.facecolor) == [1, 0, 0]));\n%!   assert (all (vertcat (bardata.edgecolor) == [0, 1, 0]));\n%!   assert (all (vertcat (patchdata.facecolor) == [1, 0, 0]));\n%!   assert (all (vertcat (patchdata.edgecolor) == [0, 1, 0]));\n%!\n%!   set (hb, \"facecolor\", \"b\");\n%!   set (hb, \"edgecolor\", \"k\");\n%!   bardata = get (hb);\n%!   patchdata = get (hp);\n%!   assert (all (vertcat (bardata.facecolor) == [0, 0, 1]));\n%!   assert (all (vertcat (bardata.edgecolor) == [0, 0, 0]));\n%!   assert (all (vertcat (patchdata.facecolor) == [0, 0, 1]));\n%!   assert (all (vertcat (patchdata.edgecolor) == [0, 0, 0]));\n%!\n%!   set (hb(2), \"facecolor\", \"w\");\n%!   set (hb(2), \"edgecolor\", \"r\");\n%!   bardata = get (hb);\n%!   patchdata = get (hp);\n%!   assert (all (vertcat (bardata([1,3]).facecolor) == [0, 0, 1]));\n%!   assert (all (vertcat (bardata([1,3]).edgecolor) == [0, 0, 0]));\n%!   assert (all (vertcat (patchdata([1,3]).facecolor) == [0, 0, 1]));\n%!   assert (all (vertcat (patchdata([1,3]).edgecolor) == [0, 0, 0]));\n%!   assert (bardata(2).facecolor, [1, 1, 1]);\n%!   assert (bardata(2).edgecolor, [1, 0, 0]);\n%!   assert (patchdata(2).facecolor, [1, 1, 1]);\n%!   assert (patchdata(2).edgecolor, [1, 0, 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Change from horizontal:\n%!test <*65671>  # Baseline should change to/from horizontal with bars.\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!\n%!   set (hb, \"horizontal\", \"off\");\n%!\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!\n%!   assert (bardata.horizontal, \"off\");\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!\n%!   assert (baselinedata.ydata, [0, 0]);\n%!   assert (diff (baselinedata.xdata) > 0);\n%!\n%!   assert (patchdata.xdata, [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!   assert (patchdata.ydata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (size (patchdata.faces), [3, 4]);\n%!   assert (size (patchdata.vertices), [12, 2]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*65734>  # Axis ticks after change from horizontal should match bar.\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!\n%!   set (hb, \"horizontal\", \"off\");\n%!\n%!   bardata = get (hb);\n%!   axesdata = get (hax);\n%!\n%!   assert (bardata.horizontal, \"off\");\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!\n%!   assert (axesdata.xscale, \"linear\");\n%!   assert (axesdata.xlim, [0.5, 3.5]);\n%!   assert (axesdata.xtick, 1:3);\n%!   assert (axesdata.xticklabel, {\"1\"; \"2\"; \"3\"});\n%!   assert (axesdata.yscale, \"linear\");\n%!   assert (axesdata.ylim, [0, 4]);\n%!   assert (axesdata.ytick, 0:4);\n%!   assert (axesdata.yticklabel, {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"});\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Change linear/log scale and move baseline/patch values if needed.\n%!test <*65671>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!   assert (baselinedata.xdata, [0, 0]);\n%!   assert (baselinedata.ydata, [0.5, 3.5], eps);\n%!   assert (get (hax, \"xscale\"), \"linear\");\n%!   assert (get (hp, \"xdata\"), [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!\n%!   warning (\"off\", \"Octave:negative-data-log-axis\", \"local\");\n%!   set (hax, \"xscale\", \"log\");\n%!   assert (get (hax, \"xscale\"), \"log\");\n%!   assert (get (hb, \"basevalue\"), 1);\n%!   assert (get (hl, \"xdata\"), [1, 1]);\n%!   assert (get (hp, \"xdata\"), [1, 1, 1; 2:4; 2:4; 1, 1, 1]);\n%!\n%!   set (hax, \"xscale\", \"linear\");\n%!   assert (get (hax, \"xscale\"), \"linear\");\n%!   assert (get (hb, \"basevalue\"), 0);\n%!   assert (get (hl, \"xdata\"), [0, 0]);\n%!   assert (get (hp, \"xdata\"), [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check baseline updating subfunctions\n%!test <*65671>  # Baseline move or basevalue change: update line, bar, patch.\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   bardata = get (hb);\n%!   hl = bardata.baseline;\n%!   baselinedata = get (hl);\n%!   hp = bardata.children;\n%!   patchdata = get (hp);\n%!\n%!   assert (bardata.basevalue, 0);\n%!   assert (bardata.xdata, [1; 2; 3]);\n%!   assert (bardata.ydata, [2; 3; 4]);\n%!   assert (baselinedata.xdata, [0, 0]);\n%!   assert (baselinedata.ydata, [0.5, 3.5], eps);\n%!   assert (patchdata.xdata, [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (patchdata.ydata, [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!\n%!   set (hax, \"ylim\", [0, 5]); # Change axes limits, verify baseline match.\n%!   assert (get (hl, \"ydata\"), [0, 5]);\n%!\n%!   set (hb, \"basevalue\", 2); # Change line position through bar object.\n%!   axesdata = get (hax);\n%!   assert (get (hb, \"basevalue\"), 2);\n%!   assert (get (hl, \"xdata\"), [2, 2]);\n%!   assert (axesdata.xlim, [2, 4]);\n%!   assert (axesdata.xtick, [2:0.5:4], eps);\n%!   assert (axesdata.xticklabel, {\"2\"; \"2.5\"; \"3\"; \"3.5\"; \"4\"});\n%!   assert (get (hp, \"xdata\"), [2, 2, 2; 2:4; 2:4; 2, 2, 2]);\n%!\n%!   set (hl, \"xdata\", [-1 -1]);  # Change line position directly.\n%!   axesdata = get (hax);\n%!   assert (get (hb, \"basevalue\"), -1);\n%!   assert (get (hl, \"xdata\"), [-1, -1]);\n%!   assert (axesdata.xlim, [-1, 4]);\n%!   assert (axesdata.xtick, [-1:4]);\n%!   assert (axesdata.xticklabel, {\"-1\"; \"0\"; \"1\"; \"2\"; \"3\"; \"4\"});\n%!   assert (get (hp, \"xdata\"), [-1, -1, -1; 2:4; 2:4; -1, -1, -1]);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Updating base plot ydata.\n%!test <*65734>  # Changing xdata should update xlim/ticks for new locations.\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   yd = [0.6, 1.6, 2.6; 0.6, 1.6, 2.6; 1.4, 2.4, 3.4; 1.4, 2.4, 3.4];\n%!\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   ## Verify base behavior.\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hp, \"ydata\"), yd, eps);\n%!   assert (get (hax, \"ylim\"), [0.5, 3.5], eps);\n%!   assert (get (hax, \"ytick\"), 1:3);\n%!   assert (get (hax, \"yticklabel\"), {\"1\"; \"2\"; \"3\"});\n%!\n%!   ## Verify changed behavior.\n%!   set (hb, \"xdata\", [3:5]');\n%!   assert (get (hb, \"xdata\"), [3:5]');\n%!   assert (get (hp, \"ydata\"), yd + 2, eps);\n%!   assert (get (hax, \"ylim\"), [0.5, 3.5] + 2, eps);\n%!   assert (get (hax, \"ytick\"), 3:5);\n%!   assert (get (hax, \"yticklabel\"), {\"3\"; \"4\"; \"5\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Updating base plot xdata.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   ## Verify base behavior.\n%!   assert (get (hb, \"ydata\"), [2:4]');\n%!   assert (get (hp, \"xdata\"), [0, 0, 0; 2:4; 2:4; 0, 0, 0]);\n%!   assert (get (hax, \"xlim\"), [0, 4]);\n%!   assert (get (hax, \"xtick\"), 0:4);\n%!   assert (get (hax, \"xticklabel\"), {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"});\n%!\n%!   ## Verify changed behavior.\n%!   set (hb, \"ydata\", [-2, 1, 3]');\n%!   assert (get (hb, \"ydata\"), [-2, 1, 3]');\n%!   assert (get (hp, \"xdata\"), [0, 0, 0; -2, 1, 3; -2, 1, 3; 0, 0, 0]);\n%!   assert (get (hax, \"xlim\"), [-2, 3]);\n%!   assert (get (hax, \"xtick\"), -2:3);\n%!   assert (get (hax, \"xticklabel\"), {\"-2\"; \"-1\"; \"0\"; \"1\"; \"2\"; \"3\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Updating barwidth.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   ## Verify base behavior.\n%!   assert (get (hb, \"barwidth\"), 0.8, eps);\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hp, \"ydata\"), [0.6, 1.6, 2.6;\n%!                             0.6, 1.6, 2.6;\n%!                             1.4, 2.4, 3.4;\n%!                             1.4, 2.4, 3.4], eps);\n%!\n%!   ## Verify changed behavior.\n%!   set (hb, \"barwidth\", 0.5);\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hp, \"ydata\"), [0.75, 1.75, 2.75;\n%!                               0.75, 1.75, 2.75;\n%!                               1.25, 2.25, 3.25;\n%!                               1.25, 2.25, 3.25], eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Ensure x tick labels are updated with xdata changes.\n%!test <*65734>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[0, 4], [0:4], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[0.5, 3.5], 1:3, {\"1\"; \"2\"; \"3\"}});\n%!\n%!   set (hb, \"xdata\", [3:5]');  # column vector input.\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[0, 4], [0:4], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[2.5, 5.5], 3:5, {\"3\"; \"4\"; \"5\"}});\n%!\n%!   set (hb, \"xdata\", [9:11]);  # row vector input.\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[0, 4], [0:4], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[8.5, 11.5], 9:11, {\"9\"; \"10\"; \"11\"}});\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n#### Ensure y tick labels are updated with ydata changes.\n%!test <*65734>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   hp = get (hb, \"children\");\n%!\n%!   assert (get (hb, \"xdata\"), [1:3]');\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[0, 4], [0:4], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[0.5, 3.5], 1:3, {\"1\"; \"2\"; \"3\"}});\n%!\n%!   set (hb, \"ydata\", [5:7]');  # column vector input.\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[0, 7], [0:7], {\"0\"; \"1\"; \"2\"; \"3\"; \"4\"; \"5\"; \"6\"; \"7\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[0.5, 3.5], 1:3, {\"1\"; \"2\"; \"3\"}});%!\n%!\n%!   set (hb, \"ydata\", [-4:-2]);  # row vector input.\n%!   assert (get (hax, {\"xlim\", \"xtick\",\"xticklabel\"}), ...\n%!           {[-4, 0], [-4:0], {\"-4\"; \"-3\"; \"-2\"; \"-1\"; \"0\"}});\n%!   assert (get (hax, {\"ylim\", \"ytick\", \"yticklabel\"}), ...\n%!           {[0.5, 3.5], 1:3, {\"1\"; \"2\"; \"3\"}});\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Ensure no errors on plot replacement.\n%!test <*67006>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hb = barh (hax, 2:4);\n%!   hb = barh (hax, 5:7);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%% Test input validation\n%!error <Invalid call> bar ()\n%!error <Y must be numeric> barh (\"foo\")\n%!error <X must be a vector> barh ([1 2; 3 4], [1 2 3 4])\n%!error <X vector values must be unique> barh ([1 2 3 3], [1 2 3 4])\n%!error <length of X and Y must be equal> barh ([1 2 3], [1 2 3 4])\n%!error <length of X and Y must be equal> barh ([1 2 3 4], [1 2 3])\n"
  },
  {
    "path": "scripts/plot/draw/camlight.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} camlight {}\n## @deftypefnx {} {} camlight right\n## @deftypefnx {} {} camlight left\n## @deftypefnx {} {} camlight headlight\n## @deftypefnx {} {} camlight (@var{az}, @var{el})\n## @deftypefnx {} {} camlight (@dots{}, @var{style})\n## @deftypefnx {} {} camlight (@var{hl}, @dots{})\n## @deftypefnx {} {} camlight (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} camlight (@dots{})\n## Add a light object to a figure using a simple interface.\n##\n## When called with no arguments, a light object is added to the current plot\n## and is placed slightly above and to the right of the camera's current\n## position: this is equivalent to @code{camlight right}.  The commands\n## @code{camlight left} and @code{camlight headlight} behave similarly with\n## the placement being either left of the camera position or centered on the\n## camera position.\n##\n## For more control, the light position can be specified by an azimuthal\n## rotation @var{az} and an elevation angle @var{el}, both in degrees,\n## relative to the current properties of the camera.\n##\n## The optional string @var{style} specifies whether the light is a local point\n## source (@qcode{\"local\"}, the default) or placed at infinite distance\n## (@qcode{\"infinite\"}).\n##\n## If the first argument @var{hl} is a handle to a light object, then act on\n## this light object rather than creating a new object.\n##\n## If the first argument @var{hax} is an axes handle, then create a new light\n## object in this axes, rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the light object.\n## This can be used to move or further change properties of the light object.\n##\n## Examples:\n##\n## Add a light object to a plot\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## sphere (36);\n## camlight\n## @end group\n## @end example\n##\n## Position the light source exactly\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## camlight (45, 30);\n## @end group\n## @end example\n##\n## Here the light is first pitched upwards (@pxref{XREFcamup,,@code{camup}})\n## from the camera position (@pxref{XREFcampos,,@code{campos}}) by 30\n## degrees.  It is then yawed by 45 degrees to the right.  Both rotations\n## are centered around the camera target\n## (@pxref{XREFcamtarget,,@code{camtarget}}).\n##\n## Return a handle to further manipulate the light object\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## clf\n## sphere (36);\n## hl = camlight (\"left\");\n## set (hl, \"color\", \"r\");\n## @end group\n## @end example\n##\n## @seealso{light}\n## @end deftypefn\n\nfunction h = camlight (varargin)\n\n  if (nargin > 4)\n    print_usage ();\n  endif\n\n  ## Note: There is a very small chance of a collision between a numeric double\n  ## specifying azimuth and a light handle object (also a numeric double).\n  ## We don't worry about that.\n  if (numel (varargin) > 0 && numel (varargin{1}) == 1\n      && ishghandle (varargin{1}))\n    typ = get (varargin{1}, \"type\");\n    if (strcmp (typ, \"light\"))\n      hl  = varargin{1};\n      hax = get (hl, \"parent\");\n    elseif (strcmp (typ, \"axes\"))\n      hax = varargin{1};\n      hl  = [];\n    else\n      error (\"camlight: HL must be a handle to an axes or light object\");\n    endif\n    varargin(1) = [];\n    nargin = nargin - 1;\n  else\n    hl  = [];\n    hax = [];\n  endif\n\n  style = \"local\";\n  where = \"\";\n\n  if (nargin == 0)\n    where = \"right\";\n\n  elseif (nargin == 1 && ischar (varargin{1}))\n    arg1 = varargin{1};\n    if (strcmpi (arg1, \"local\") || strcmpi (arg1, \"infinite\"))\n      style = arg1;\n      where = \"right\";\n    else\n      where = arg1;\n    endif\n\n  elseif (nargin == 2)\n    arg1 = varargin{1};\n    arg2 = varargin{2};\n    if (isnumeric (arg1) && isscalar (arg1)\n        && isnumeric (arg2) && isscalar (arg2))\n      az = arg1;\n      el = arg2;\n    elseif (ischar (arg1) && ischar (arg2))\n      where = arg1;\n      style = arg2;\n    else\n      print_usage ();\n    endif\n\n  elseif (nargin == 3 && ischar (varargin{3})\n          && isnumeric (varargin{1}) && isscalar (varargin{1})\n          && isnumeric (varargin{2}) && isscalar (varargin{2}))\n    [az, el, style] = varargin{1:3};\n\n  else\n    print_usage ();\n  endif\n\n  if (! isempty (where))\n    switch (lower (where))\n      case \"left\"\n        az = -30;\n        el = 30;\n\n      case \"right\"\n        az = 30;\n        el = 30;\n\n      case \"headlight\"\n        az = 0;\n        el = 0;\n\n      otherwise\n        error (\"camlight: invalid light position '%s'\", where);\n\n    endswitch\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n  cam_up = get (hax, \"cameraupvector\");\n  cam_pos = get (hax, \"cameraposition\");\n  cam_target = get (hax, \"cameratarget\");\n\n  view_ax = cam_target - cam_pos;\n  view_ax /= norm (view_ax);\n  ## Orthogonalize the camup vector\n  yaw_ax = cam_up - view_ax*dot (cam_up, view_ax);\n  pitch_ax = cross (cam_up, view_ax);\n\n  ## First pitch up by 'el', then yaw by 'az'\n  ## (order matters, this matches experiments with Matlab).\n  pos = num2cell (cam_pos);\n  [pos{:}] = __rotate_around_axis__ (pos{:}, el, pitch_ax, cam_target);\n  [pos{:}] = __rotate_around_axis__ (pos{:}, az, yaw_ax, cam_target);\n  pos = [pos{:}];\n\n  if (isempty (hl))\n    hl = light (hax, \"Position\", pos, \"style\", style);\n  else\n    set (hl, \"Position\", pos, \"style\", style);\n  endif\n\n  if (nargout > 0)\n    h = hl;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! ## Adding lights to a scene\n%! sphere (64);\n%! camlight\n%!\n%! ## Add a second light\n%! camlight left\n%!\n%! title ({\"camlight()\", \"lights are left and right\"});\n\n%!demo\n%! clf;\n%! sphere (48);\n%! title ({\"camlight()\", \"light in fixed position ignores camera change\"});\n%! axis equal;\n%! shading flat;\n%! view (30, 30);\n%!\n%! camlight\n%!\n%! for a = 30:2:390\n%!   view (a, 30);\n%!   drawnow ();\n%!   pause (0.01);\n%! endfor\n\n%!demo\n%! clf;\n%! sphere (48);\n%! title ({\"camlight()\", \"update light position with camera change\"});\n%! axis equal;  shading flat\n%! view (30, 30);\n%!\n%! hl = camlight ();          # keep a handle to the light\n%!\n%! for a = 30:2:390\n%!   view (a, 30);\n%!   camlight (hl, \"right\");  # update light position\n%!   drawnow ();\n%!   pause (0.01);\n%! endfor\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere (24);\n%!   set (gca (), \"cameraposition\", [8 12 7.3]);\n%!   set (gca (), \"cameraupvector\", [0 2 2]);\n%!   set (gca (), \"cameratarget\", [0.5 -0.3 -0.3]);\n%!   h = camlight (45, 20);\n%!   A = get (h, \"position\");\n%!   ## From  Matlab R2016a for Windows:\n%!   B = [-3.3012070881570281 15.474861455795915 1.1158286348951763];\n%!   assert (A, B, -20*eps);\n%!\n%!   h = camlight (300, -190);\n%!   A = get (h, \"position\");\n%!   B = [-11.054849015640565 2.9313301431006460 -11.315623892092516];\n%!   assert (A, B, -20*eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Move a light\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   h1 = camlight (\"left\");\n%!   h2 = camlight ();\n%!   p2 = get (h2, \"position\");\n%!   camlight (h1, \"right\")\n%!   p1 = get (h1, \"position\");\n%!   assert (p1, p2);\n%!   camlight (h1);\n%!   p1 = get (h1, \"position\");\n%!   assert (p1, p2);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Updating style also moves light\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere ();\n%!   h1 = camlight (\"right\");\n%!   h  = camlight (\"headlight\");\n%!   p1 = get (h1, \"position\");\n%!   h2 = camlight (h, \"local\");\n%!   p2 = get (h2, \"position\");\n%!   assert (h, h2);\n%!   assert (p1, p2);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test an axes handle as first argument\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax1 = subplot (1, 2, 1);\n%!   hax2 = subplot (1, 2, 2);\n%!   hl1  = camlight ();\n%!   hl2  = camlight (hax1);\n%!   assert (get (hl1, \"Parent\"), hax2);\n%!   assert (get (hl2, \"Parent\"), hax1);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error camlight (1,2,3,4,5)\n%!error <HL must be a handle to an axes or light object> camlight (0, \"left\")\n%!error <Invalid call> camlight ({1}, {2})\n%!error <Invalid call> camlight (rand (), 1, 2, 3)\n%!error <invalid light position 'foobar'> camlight (\"foobar\")\n%!error <invalid light position 'foobar'> camlight (\"foobar\", \"local\")\n"
  },
  {
    "path": "scripts/plot/draw/colorbar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} colorbar\n## @deftypefnx {} {} colorbar (@var{loc}, @dots{})\n## @deftypefnx {} {} colorbar (@var{delete_option})\n## @deftypefnx {} {} colorbar (@var{hcb}, @dots{})\n## @deftypefnx {} {} colorbar (@var{hax}, @dots{})\n## @deftypefnx {} {} colorbar (@dots{}, \"location\", @var{loc}, @dots{})\n## @deftypefnx {} {} colorbar (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {@var{h} =} colorbar (@dots{})\n## Add a colorbar to the current axes.\n##\n## A colorbar displays the current colormap along with numerical rulings so\n## that the color scale can be interpreted.\n##\n## The optional input @nospell{@var{loc}} determines the location of the\n## colorbar.  If present, it must be the first argument to @code{colorbar}.\n## Valid values for @nospell{@var{loc}} are\n##\n## @table @asis\n## @item @qcode{\"EastOutside\"}\n## Place the colorbar outside the plot to the right.  This is the default.\n##\n## @item @qcode{\"East\"}\n## Place the colorbar inside the plot to the right.\n##\n## @item @qcode{\"WestOutside\"}\n## Place the colorbar outside the plot to the left.\n##\n## @item @qcode{\"West\"}\n## Place the colorbar inside the plot to the left.\n##\n## @item @qcode{\"NorthOutside\"}\n## Place the colorbar above the plot.\n##\n## @item @qcode{\"North\"}\n## Place the colorbar at the top of the plot.\n##\n## @item @qcode{\"SouthOutside\"}\n## Place the colorbar under the plot.\n##\n## @item @qcode{\"South\"}\n## Place the colorbar at the bottom of the plot.\n## @end table\n##\n## To remove a colorbar from a plot use any one of the following keywords for\n## the @var{delete_option}: @qcode{\"off\"}, @qcode{\"delete\"}, @qcode{\"hide\"}.\n##\n## If the first argument @var{hax} is an axes handle, then the colorbar is\n## added to this axes, rather than the current axes returned by @code{gca}.\n##\n## If the first argument @var{hcb} is a handle to a colorbar object, then\n## operate on this colorbar directly.\n##\n## Additional property/value pairs are passed directly to the underlying axes\n## object.  The full list of properties is documented at @ref{Axes Properties}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## colorbar object.\n##\n## Implementation Note: A colorbar is created as an additional axes object with\n## the @qcode{\"tag\"} property set to @qcode{\"colorbar\"}.  The created object\n## has the extra property @qcode{\"location\"} which controls the positioning of\n## the colorbar.\n##\n## If the argument @qcode{\"peer\"} is given, then the following argument is\n## treated as the axes handle in which to add the colorbar.  The @qcode{\"peer\"}\n## calling syntax may be removed in the future and is not recommended.\n## @seealso{colormap}\n## @end deftypefn\n\nfunction h = colorbar (varargin)\n\n  [hcb, varargin, nargin] = __plt_get_axis_arg__ (\"colorbar\", varargin{:});\n\n  if (hcb && ! strcmp (get (hcb, \"tag\"), \"colorbar\"))\n    hax = hcb;\n    hcb = [];\n  else\n    hax = [];\n  endif\n  loc = \"\";\n  cbpos = [];\n  args = {};\n  delete_cbar = false;\n\n  i = 1;\n  while (i <= nargin)\n    arg = varargin{i++};\n    if (! ischar (arg))\n      error (\"colorbar: expected string argument at position %d\", i-1);\n    endif\n\n    switch (lower (arg))\n      case {\"north\", \"south\", \"east\", \"west\", ...\n            \"northoutside\", \"southoutside\", \"eastoutside\", \"westoutside\"}\n        if (i != 2)\n          error (\"colorbar: LOC specification must occur as first argument\");\n        endif\n        loc = lower (arg);\n\n      case \"location\"\n        if (i > nargin)\n          error ('colorbar: missing value after \"location\"');\n        endif\n        loc = lower (varargin{i++});\n\n      case {\"delete\", \"hide\", \"off\"}\n        delete_cbar = true;\n\n      case \"peer\"\n        if (i > nargin)\n          error ('colorbar: missing axes handle after \"peer\"');\n        endif\n        hax = varargin{i++};\n        if (! isscalar (hax) || ! isaxes (hax))\n          error ('colorbar: invalid axes handle following \"peer\"');\n        endif\n\n      otherwise\n        ## Property/Value pair\n        if (i > nargin)\n          error (\"colorbar: PROP/VAL inputs must occur in pairs\");\n        endif\n        args{end+1} = arg;\n        args{end+1} = varargin{i++};\n        if (strcmpi (arg, \"position\"))\n          loc = \"manual\";\n          cbpos = args{end};\n        endif\n\n    endswitch\n  endwhile\n\n  if (isempty (loc))\n    loc = \"eastoutside\";\n  else\n    ## Validate location\n    if (! any (strcmp (loc, {\"eastoutside\"; \"east\"; \"westoutside\"; \"west\";\n                             \"northoutside\"; \"north\"; \"southoutside\"; \"south\";\n                             \"manual\"})))\n      error (\"colorbar: unrecognized colorbar location '%s'\", loc);\n    endif\n  endif\n\n  ## Handle deletion case early and return\n  if (delete_cbar)\n    if (isempty (hcb))\n      if (isempty (hax))\n        hax = get (get (0, \"currentfigure\"), \"currentaxes\");\n      endif\n      try\n        hcb = get (hax, \"__colorbar_handle__\");\n      end_try_catch\n    endif\n\n    delete (hcb);\n\n    if (nargout > 0)\n      h = [];\n    endif\n    return;\n  endif\n\n  ## Handle changes to specified colorbar\n  if (! isempty (hcb))\n    ## FIXME: No listener on location property so have to re-create\n    ##        colorbar whenever an option changes.\n    ##        re-instate this code if listener is developed.\n    ## if (! isempty (loc))\n    ##   set (hcb, \"location\", loc);\n    ## endif\n    ## if (! isempty (args))\n    ##   set (hcb, args{:});\n    ## endif\n    hax = get (hcb, \"__axes_handle__\");\n  else\n    ## Find any colorbar associated with this axes\n    if (isempty (hax))\n      hax = gca ();\n    endif\n    try\n      hcb = get (hax, \"__colorbar_handle__\");\n    end_try_catch\n  endif\n\n  ## New or existing colorbar?\n  new_colorbar = isempty (hcb);\n\n  if (! new_colorbar)\n    ## Restore original axes position before applying new colorbar settings\n    orig_props = get (hcb, \"deletefcn\"){3};\n    units = get (hax, \"units\");\n    set (hax, \"units\", orig_props.units,\n              \"position\", orig_props.position,\n              \"outerposition\", orig_props.outerposition,\n              \"positionconstraint\", orig_props.positionconstraint);\n    set (hax, \"units\", units);\n  endif\n\n  ## Create a colorbar\n\n  ## Special handling for plotyy which has two axes objects\n  if (isprop (hax, \"__plotyy_axes__\"))\n    hyy = get (hax, \"__plotyy_axes__\");\n\n    ## Use axis which is appropriate for legend location;\n    ## Necessary for plotyy figures where there are two axes.\n    if (strfind (loc, \"east\"))\n      hax = hyy(2);\n    else\n      hax = hyy(1);\n    endif\n  endif\n\n  ## Preamble code to restore figure and axes after colorbar creation\n  hfig = ancestor (hax, \"figure\");\n  origfig = get (0, \"currentfigure\");\n  if (origfig != hfig)\n    set (0, \"currentfigure\", hfig);\n  else\n    origfig = [];\n  endif\n  origaxes = get (hfig, \"currentaxes\");\n  unwind_protect\n    ## FIXME: Matlab does not require the \"position\" property to be active.\n    ##        Is there a way to determine the plotbox position for the\n    ##        gnuplot graphics toolkit when the outerposition is active?\n    set (hax, \"positionconstraint\", \"innerposition\");\n    props = get (hax);\n    props.__axes_handle__ = hax;\n    position = props.position;\n\n    cmap = get (hax, \"colormap\");\n    clen = rows (cmap);\n    cext = get (hax, \"clim\");\n    cdiff = (cext(2) - cext(1)) / clen / 2;\n    cmin = cext(1) + cdiff;\n    cmax = cext(2) - cdiff;\n\n    hpar = get (hax, \"parent\");\n\n    if (isempty (cbpos))\n      ## auto positioning\n      [axpos, cbpos, vertical, mirror] = ...\n        calc_cbar_position (loc, props, ancestor (hpar, \"figure\"));\n      set (hax, \"position\", axpos);\n    else\n      ## colorbar position specified.\n      ## 1) Don't shrink existing plot axes,\n      ## 2) Use default \"EastOutside\" orientation\n      vertical = true;\n      mirror = true;\n    endif\n\n    ## Create colorbar axes if necessary\n    if (new_colorbar)\n      hcb = axes (\"parent\", hpar, \"tag\", \"colorbar\",\n                  \"positionconstraint\", \"innerposition\",\n                  \"units\", get (hax, \"units\"), \"position\", cbpos,\n                  \"colormap\", cmap,\n                  \"box\", \"on\", \"xdir\", \"normal\", \"ydir\", \"normal\");\n\n      addproperty (\"axislocation\", hcb, \"radio\", \"{out}|in\");\n      addproperty (\"axislocationmode\", hcb, \"radio\", \"{auto}|manual\");\n      addproperty (\"direction\", hcb, \"AxesYdir\", \"normal\");\n      addproperty (\"label\", hcb, \"handle\", get (hcb, \"ylabel\"));\n      addproperty (\"limits\", hcb, \"AxesYlim\");\n      addproperty (\"limitsmode\", hcb, \"AxesYlimMode\", \"auto\");\n      addproperty (\"location\", hcb, \"radio\",\n                   \"{eastoutside}|east|westoutside|west|northoutside|north|southoutside|south|manual\",\n                   loc);\n      addproperty (\"tickdirection\", hcb, \"AxesTickdir\", \"in\");\n      addproperty (\"ticklabels\", hcb, \"AxesYtickLabel\");\n      addproperty (\"ticklabelsmode\", hcb, \"AxesYtickLabelMode\", \"auto\");\n      addproperty (\"ticks\", hcb, \"AxesYtick\");\n      addproperty (\"ticksmode\", hcb, \"AxesYtickMode\", \"auto\");\n      ## FIXME: Matlab uses just a scalar for ticklength, but axes already\n      ##        has a 2-element ticklength property which cannot be overridden.\n      ## addproperty (\"ticklength\", hcb, \"double\", 0.01);\n\n      ## Add a pointer from colorbar directly to axes\n      addproperty (\"__axes_handle__\", hcb, \"handle\", hax);\n      ## Also add a pointer back from axes to this colorbar\n      try\n        addproperty (\"__colorbar_handle__\", hax, \"handle\", hcb);\n      catch\n        set (hax, \"__colorbar_handle__\", hcb);\n      end_try_catch\n      addproperty (\"__vertical__\", hcb, \"boolean\", vertical);\n      ## Use low-level form to avoid calling newplot which changes axes\n      hi = image (hcb, \"xdata\", [0,1], \"ydata\", [cmin, cmax],\n                       \"cdata\", [1 : clen]');\n    else\n      ## Change settings of existing colorbar\n      set (hcb, \"parent\", hpar, \"position\", cbpos, \"location\", loc);\n      ## Fetch image handle from existing colorbar\n      hi = get (hcb, \"children\");\n    endif\n\n    if (vertical)\n      set (hi, \"xdata\", [0,1], \"ydata\", [cmin, cmax], \"cdata\", [1 : clen]');\n      if (mirror)\n        set (hcb, \"xtick\", [], \"xlim\", [-0.5, 1.5],\n                  \"ytickmode\", \"auto\", \"ylim\", cext,\n                  \"yaxislocation\", \"right\", \"label\", get (hcb, \"ylabel\"),\n                  \"__vertical__\", vertical,\n                  \"layer\", \"top\");\n      else\n        set (hcb, \"xtick\", [], \"xlim\", [-0.5, 1.5],\n                  \"ytickmode\", \"auto\", \"ylim\", cext,\n                  \"yaxislocation\", \"left\", \"label\", get (hcb, \"ylabel\"),\n                  \"__vertical__\", vertical,\n                  \"layer\", \"top\");\n      endif\n    else\n      set (hi, \"xdata\", [cmin, cmax], \"ydata\", [0,1], \"cdata\", [1 : clen]);\n      if (mirror)\n        set (hcb, \"ytick\", [], \"ylim\", [-0.5, 1.5],\n                  \"xtickmode\", \"auto\", \"xlim\", cext,\n                  \"xaxislocation\", \"top\", \"label\", get (hcb, \"xlabel\"),\n                  \"__vertical__\", vertical,\n                  \"layer\", \"top\");\n      else\n        set (hcb, \"ytick\", [], \"ylim\", [-0.5, 1.5],\n                  \"xtickmode\", \"auto\", \"xlim\", cext,\n                  \"xaxislocation\", \"bottom\", \"label\", get (hcb, \"xlabel\"),\n                  \"__vertical__\", vertical,\n                  \"layer\", \"top\");\n      endif\n    endif\n\n    ## Add listeners, but only to a new colorbar\n    if (new_colorbar)\n      ## Dummy object placed on axes to delete colorbar when axes is deleted.\n      ctext = text (0, 0, \"\", \"tag\", \"colorbar\", \"parent\", hax,\n                    \"visible\", \"off\", \"handlevisibility\", \"off\",\n                    \"xliminclude\", \"off\", \"yliminclude\", \"off\",\n                    \"zliminclude\", \"off\",\n                    \"deletefcn\", {@cb_axes_deleted, hax, hcb});\n\n      set (hcb, \"deletefcn\", {@cb_restore_axes, hax, props});\n\n      addlistener (hcb, \"axislocation\", {@cb_axislocation});\n      addlistener (hcb, \"direction\", {@cb_direction});\n      addlistener (hcb, \"tickdirection\", @cb_tickdirection);\n      addlistener (hcb, \"ticks\", {@cb_ticks});\n      addlistener (hcb, \"ticksmode\", {@cb_ticksmode});\n      addlistener (hcb, \"ticklabels\", {@cb_ticklabels});\n      addlistener (hcb, \"ticklabelsmode\", {@cb_ticklabelsmode});\n      addlistener (hcb, \"xscale\", {@cb_error_on_logscale, \"xscale\"});\n      addlistener (hcb, \"yscale\", {@cb_error_on_logscale, \"yscale\"});\n\n      if (strcmp (get (hpar, \"type\"), \"figure\"))\n        addlistener (hpar, \"colormap\", {@cb_colormap, ...\n                                        hax, hcb, hi, clen});\n      endif\n      addlistener (hax, \"colormap\", {@cb_colormap, hax, hcb, hi, clen});\n      addlistener (hax, \"clim\", {@cb_clim, hcb, hi});\n      addlistener (hax, \"dataaspectratio\", {@cb_colorbar_axis, hcb, props});\n      addlistener (hax, \"dataaspectratiomode\", {@cb_colorbar_axis, ...\n                                                hcb, props});\n      addlistener (hax, \"plotboxaspectratio\", {@cb_colorbar_axis, hcb, props});\n      addlistener (hax, \"plotboxaspectratiomode\", {@cb_colorbar_axis, ...\n                                                   hcb, props});\n      addlistener (hax, \"position\", {@cb_colorbar_axis, hcb, props});\n\n      ## FIXME: Need listeners for limits, limitsmode, location.\n    endif\n\n  ## Called after listeners have been installed\n  if (! isempty (args))\n    set (hcb, args{:});\n  endif\n\n  unwind_protect_cleanup\n    set (hfig, \"currentaxes\", origaxes);\n    if (! isempty (origfig))\n      set (0, \"currentfigure\", origfig);\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    h = hcb;\n  endif\n\nendfunction\n\n## Axes to which colorbar was attached is being deleted/reset.  Delete colorbar.\nfunction cb_axes_deleted (~, ~, hax, hcb)\n  if (isaxes (hcb))\n    if (strcmp (get (hax, \"beingdeleted\"), \"on\"))\n      ## Axes are being deleted.  Disable call to cb_restore_axes.\n      set (hcb, \"deletefcn\", []);\n    endif\n    delete (hcb);\n  endif\nendfunction\n\n## Error on attempt to set logscale on colorbar axes\nfunction cb_error_on_logscale (hcb, ~, scale)\n  if (strcmp (get (hcb, scale), \"log\"))\n    set (hcb, scale, \"linear\");\n    error (\"colorbar: Only linear colorbars are possible\");\n  endif\nendfunction\n\n## colorbar property \"AxisLocation\" which maps to axes \"[X|Y]AxisLocation\".\nfunction cb_axislocation (hcb, ~)\n  vertical = strcmp (get (hcb, '__vertical__'), 'on');\n  location = get (hcb, 'axislocation');\n  if (vertical)\n    location = ifelse (strcmp (location, 'in'), 'left', 'right');\n    set (hcb, 'yaxislocation', location);\n  else\n    location = ifelse (strcmp (location, 'in'), 'top', 'bottom');\n    set (hcb, 'xaxislocation', location);\n  endif\nendfunction\n\n## colorbar property \"Direction\" which maps to axes \"YDir\" or \"XDir\".\nfunction cb_direction (hcb, ~)\n  vertical = strcmp (get (hcb, '__vertical__'), 'on');\n  direction = get (hcb, 'direction');\n  if (vertical)\n    set (hcb, 'ydir', direction);\n  else\n    set (hcb, 'xdir', direction);\n  endif\nendfunction\n\n## colorbar property \"Ticks\" which maps to axes \"YTick\" or \"XTick\".\nfunction cb_ticks (hcb, ~)\n  vertical = strcmp (get (hcb, '__vertical__'), 'on');\n  ticks = get (hcb, 'ticks');\n  if (vertical)\n    set (hcb, 'YTick', ticks);\n  else\n    set (hcb, 'XTick', ticks);\n  endif\n  set (hcb, 'ticksmode', 'manual');\nendfunction\n\n## colorbar property \"TicksMode\" which maps to axes \"[Y|X]TickMode\".\nfunction cb_ticksmode (hcb, ~)\n  mode = get (hcb, 'ticksmode');\n  if (strcmp (mode, 'auto'))\n    vertical = strcmp (get (hcb, '__vertical__'), 'on');\n    if (vertical)\n      set (hcb, 'YTickMode', 'auto');\n    else\n      set (hcb, 'XTickMode', 'auto');\n    endif\n  endif\nendfunction\n\n## colorbar property \"TickLabels\" which maps to axes \"[Y|X]TickLabel\".\nfunction cb_ticklabels (hcb, ~)\n  vertical = strcmp (get (hcb, '__vertical__'), 'on');\n  ticklabels = get (hcb, 'ticklabels');\n  if (vertical)\n    set (hcb, 'YTickLabel', ticklabels);\n  else\n    set (hcb, 'XTickLabel', ticklabels);\n  endif\n  set (hcb, 'ticklabelsmode', 'manual');\nendfunction\n\n## colorbar property \"TickLabelsMode\" which maps to axes \"[Y|X]TickLabelMode\".\nfunction cb_ticklabelsmode (hcb, ~)\n  mode = get (hcb, 'ticklabelsmode');\n  if (strcmp (mode, 'auto'))\n    vertical = strcmp (get (hcb, '__vertical__'), 'on');\n    if (vertical)\n      set (hcb, 'YTickLabelMode', 'auto');\n    else\n      set (hcb, 'XTickLabelMode', 'auto');\n    endif\n  endif\nendfunction\n\n## colorbar property \"TickDirection\" which maps to axes property \"TickDir\".\nfunction cb_tickdirection (hcb, ~)\n  set (hcb, \"tickdir\", get (hcb, \"tickdirection\"));\nendfunction\n\n## Restore position of axes object when colorbar is deleted.\nfunction cb_restore_axes (hcb, ~, hax, orig_props)\n\n  hf = ancestor (hax, \"figure\");\n  if (strcmp (get (hf, \"beingdeleted\"), \"on\"))\n    ## Skip restoring axes if entire figure is being destroyed.\n    return;\n  endif\n\n  if (isaxes (hax))\n    ## FIXME: It is wrong to delete every listener for colormap on figure,\n    ##        but we don't have a way of deleting just this instance.\n    dellistener (hf, \"colormap\");\n    dellistener (hax, \"colormap\");\n    dellistener (hax, \"clim\");\n    dellistener (hax, \"dataaspectratio\");\n    dellistener (hax, \"dataaspectratiomode\");\n    dellistener (hax, \"plotboxaspectratio\");\n    dellistener (hax, \"plotboxaspectratiomode\");\n    dellistener (hax, \"position\");\n\n    ## Restore original axes position\n    units = get (hax, \"units\");\n    set (hax, \"units\", orig_props.units,\n              \"position\", orig_props.position,\n              \"outerposition\", orig_props.outerposition,\n              \"positionconstraint\", orig_props.positionconstraint);\n    set (hax, \"units\", units);\n\n    ## Nullify colorbar link (can't delete properties yet)\n    set (hax, \"__colorbar_handle__\", []);\n  endif\n\nendfunction\n\n## Update colorbar when clim has changed\nfunction cb_clim (hax, ~, hcb, hi)\n\n  if (isaxes (hax) && isaxes (hcb))\n    clen = rows (get (hax, \"colormap\"));\n    cext = get (hax, \"clim\");\n    cdiff = (cext(2) - cext(1)) / clen / 2;\n    cmin = cext(1) + cdiff;\n    cmax = cext(2) - cdiff;\n\n    if (strcmp (get (hcb, \"__vertical__\"), \"on\"))\n      set (hi, \"ydata\", [cmin, cmax]);\n      set (hcb, \"ylim\", cext);\n    else\n      set (hi, \"xdata\", [cmin, cmax]);\n      set (hcb, \"xlim\", cext);\n    endif\n  endif\n\nendfunction\n\n## Update colorbar when changes to axes or figure colormap have occurred.\nfunction cb_colormap (h, ~, hax, hcb, hi, init_sz)\n  persistent sz = init_sz;\n\n  if (ishghandle (h))\n    cmap = get (h, \"colormap\");\n    set (hcb, \"colormap\", cmap);\n    clen = rows (cmap);\n    if (clen != sz)\n      if (strcmp (get (hcb, \"__vertical__\"), \"on\"))\n        set (hi, \"cdata\", [1:clen]');\n      else\n        set (hi, \"cdata\", [1:clen]);\n      endif\n      sz = clen;\n      ## Also update limits on colorbar axes or there will be white gaps\n      cb_clim (hax, [], hcb, hi);\n    endif\n  endif\n\nendfunction\n\n## Update positioning of colorbar when original axes has changed position.\nfunction cb_colorbar_axis (hax, ~, hcb, orig_props)\n\n  if (isaxes (hcb))\n    loc = get (hcb, \"location\");\n    if (strcmp (loc, \"manual\"))\n      return;  # Use user-specified positioning\n    endif\n\n    props = get (hax);\n    props.__axes_handle__ = hax;\n    props.position = orig_props.position;\n    props.outerposition = orig_props.outerposition;\n    [axpos, cbpos, vertical, mirror] = ...\n      calc_cbar_position (loc, props, ancestor (hax, \"figure\"));\n\n    set (hcb, \"position\", cbpos);\n  endif\n\nendfunction\n\n## FIXME: The algorithm for positioning in legend.m is much more sophisticated\n##        and should be borrowed for colorbar.  One problem is that colorbar\n##        positioning does not take in to account multi-line axes labels.\nfunction [axpos, cbpos, vertical, mirror] = calc_cbar_position (loc, props, cf)\n\n  ## This will always represent the position prior to adding the colorbar.\n  axpos = props.position;\n  sz = axpos(3:4);\n\n  if (strcmp (props.plotboxaspectratiomode, \"manual\")\n      || strcmp (props.dataaspectratiomode, \"manual\"))\n    if (isempty (strfind (loc, \"outside\")))\n      scale = 1.0;\n    else\n      scale = 0.8;\n    endif\n    if (isempty (strfind (loc, \"east\")) && isempty (strfind (loc, \"west\")))\n      scale = [1, scale];\n    else\n      scale = [scale, 1];\n    endif\n    if (strcmp (get (cf, \"__graphics_toolkit__\"), \"gnuplot\")\n        && strcmp (props.positionconstraint, \"outerposition\"))\n      props.outerposition = props.outerposition .* [1, 1, scale];\n      off = 0.5 * (props.outerposition (3:4) - __actual_axis_position__ (props)(3:4));\n    else\n      props.position = props.position .* [1, 1, scale];\n      off = 0.5 * (props.position (3:4) - __actual_axis_position__ (props)(3:4));\n    endif\n  else\n    off = 0.0;\n  endif\n\n  switch (loc)\n    case \"northoutside\"\n      origin = axpos(1:2) + [0., 0.9] .* sz + [1, -1] .* off;\n      sz .*= [1.0, 0.06];\n      axpos(4) = 0.8 * axpos(4);\n      mirror = true;\n      vertical = false;\n    case \"north\"\n      origin = axpos(1:2) + [0.05, 0.9] .* sz + [1, -1] .* off;\n      sz .*= [1.0, 0.06] * 0.9;\n      mirror = false;\n      vertical = false;\n    case \"southoutside\"\n      origin = axpos(1:2) + off;\n      sz .*= [1.0, 0.06];\n      axpos(2) = axpos(2) + axpos(4) * 0.2;\n      axpos(4) = 0.8 * axpos(4);\n      mirror = false;\n      vertical = false;\n    case \"south\"\n      origin = axpos(1:2) + [0.05, 0.05] .* sz + off;\n      sz .*= [1.0, 0.06] * 0.9;\n      mirror = true;\n      vertical = false;\n    case \"eastoutside\"\n      origin = axpos(1:2) + [0.9, 0] .* sz + [-1, 1] .* off;\n      sz .*= [0.06, 1.0];\n      axpos(3) = 0.8 * axpos(3);\n      mirror = true;\n      vertical = true;\n    case \"east\"\n      origin = axpos(1:2) + [0.9, 0.05] .* sz + [-1, 1] .* off;\n      sz .*= [0.06, 1.0] * 0.9;\n      mirror = false;\n      vertical = true;\n    case \"westoutside\"\n      origin = axpos(1:2) + off;\n      sz .*= [0.06, 1.0];\n      axpos(1) = axpos(1) + axpos(3) * 0.2;\n      axpos(3) = 0.8 * axpos(3);\n      mirror = false;\n      vertical = true;\n    case \"west\"\n      origin = axpos(1:2) + [0.05, 0.05] .* sz + off;\n      sz .*= [0.06, 1.0] .* 0.9;\n      mirror = true;\n      vertical = true;\n  endswitch\n\n  cbpos = [origin, sz];\n\n  if (strcmp (props.plotboxaspectratiomode, \"manual\")\n      || strcmp (props.dataaspectratiomode, \"manual\"))\n    props.position = axpos;\n    actual_pos = __actual_axis_position__ (props);\n    if (strfind (loc, \"outside\"))\n      scale = 1.0;\n    else\n      scale = 0.9;\n    endif\n    if (sz(1) > sz(2))\n      ## Ensure north or south colorbars are the proper length\n      dx = (1-scale)*actual_pos(3);\n      cbpos(1) = actual_pos(1) + dx/2;\n      cbpos(3) = actual_pos(3) - dx;\n    else\n      ## Ensure east or west colorbars are the proper height\n      dy = (1-scale)*actual_pos(4);\n      cbpos(2) = actual_pos(2) + dy/2;\n      cbpos(4) = actual_pos(4) - dy;\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! imagesc (x);\n%! colorbar ();\n%! title (\"colorbar() example\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! imagesc (x);\n%! colorbar (\"westoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! imagesc (x);\n%! colorbar (\"peer\", gca, \"northoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! imagesc (x);\n%! colorbar (\"southoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! contour (peaks ());\n%! colorbar (\"west\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! subplot (2,2,1);\n%!  contour (peaks ());\n%!  colorbar (\"east\");\n%! subplot (2,2,2);\n%!  contour (peaks ());\n%!  colorbar (\"west\");\n%! subplot (2,2,3);\n%!  contour (peaks ());\n%!  colorbar (\"north\");\n%! subplot (2,2,4);\n%!  contour (peaks ());\n%!  colorbar (\"south\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (2,2,1);\n%!  imagesc (x);\n%!  colorbar ();\n%! subplot (2,2,2);\n%!  imagesc (x);\n%!  colorbar (\"westoutside\");\n%! subplot (2,2,3);\n%!  imagesc (x);\n%!  colorbar (\"northoutside\");\n%! subplot (2,2,4);\n%!  imagesc (x);\n%!  colorbar (\"southoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (1,2,1);\n%!  imagesc (x);\n%!  axis square;\n%!  colorbar ();\n%! subplot (1,2,2);\n%!  imagesc (x);\n%!  axis square;\n%!  colorbar (\"westoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (1,2,1);\n%!  imagesc (x);\n%!  axis square;\n%!  colorbar (\"northoutside\");\n%! subplot (1,2,2);\n%!  imagesc (x);\n%!  axis square;\n%!  colorbar (\"southoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (2,1,1);\n%!  imagesc (x);\n%!  axis square;\n%!  colorbar ();\n%! subplot (2,1,2);\n%!  imagesc (x);\n%!  axis square;\n%!  colorbar (\"westoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (2,1,1);\n%!  imagesc (x);\n%!  axis square;\n%!  colorbar (\"northoutside\");\n%! subplot (2,1,2);\n%!  imagesc (x);\n%!  axis square;\n%!  colorbar (\"southoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (1,2,1);\n%!  imagesc (x);\n%!  colorbar ();\n%! subplot (1,2,2);\n%!  imagesc (x);\n%!  colorbar (\"westoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (1,2,1);\n%!  imagesc (x);\n%!  colorbar (\"northoutside\");\n%! subplot (1,2,2);\n%!  imagesc (x);\n%!  colorbar (\"southoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (2,1,1);\n%!  imagesc (x);\n%!  colorbar ();\n%! subplot (2,1,2);\n%!  imagesc (x);\n%!  colorbar (\"westoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (2,1,1);\n%!  imagesc (x);\n%!  colorbar (\"northoutside\");\n%! subplot (2,1,2);\n%!  imagesc (x);\n%!  colorbar (\"southoutside\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! subplot (1,2,1);\n%!  contour (x);\n%!  axis square;\n%!  colorbar (\"east\");\n%!  xlim ([1, 64]);\n%!  ylim ([1, 64]);\n%! subplot (1,2,2);\n%!  contour (x);\n%!  colorbar (\"west\");\n%!  xlim ([1, 64]);\n%!  ylim ([1, 64]);\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! contour (x);\n%! xlim ([1, 64]);\n%! ylim ([1, 64]);\n%! colorbar ();\n%! colorbar off;\n%! title (\"colorbar off\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 64; x = kron (1:n, ones (n,1)); x = abs (x - x.');\n%! contour (x);\n%! xlim ([1, 64]);\n%! ylim ([1, 64]);\n%! colorbar ();\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! imagesc (log10 (1 ./ hilb (99)));\n%! h = colorbar ();\n%! ytick = get (h, \"ytick\");\n%! set (h, \"yticklabel\", sprintf (\"10^{%g}|\", ytick));\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 5; x = linspace (0,5,n); y = linspace (0,1,n);\n%! imagesc (1 ./ hilb (n));\n%! axis equal;\n%! colorbar ();\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 5; x = linspace (0,5,n); y = linspace (0,1,n);\n%! imagesc (x, y, 1 ./ hilb (n));\n%! axis equal;\n%! colorbar ();\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! n = 5; x = linspace (0,5,n); y = linspace (0,1,n);\n%! imagesc (y, x, 1 ./ hilb (n));\n%! axis equal;\n%! colorbar ();\n\n## This requires that the axes position be properly determined for \"axis equal\"\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! axes ();\n%! colorbar ();\n%! hold on;\n%! contour (peaks ());\n%! hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! plot ([0, 2]);\n%! colorbar (\"east\");\n%! axis square;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! plot ([0, 2]);\n%! colorbar (\"eastoutside\");\n%! axis square;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! pcolor (peaks (20));\n%! shading interp;\n%! axis (\"tight\", \"square\");\n%! colorbar ();\n#%! axes (\"color\", \"none\", \"box\", \"on\", \"positionconstraint\", \"innerposition\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! plot ([0, 2]);\n%! colorbar (\"east\");\n%! axis equal;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! plot ([0, 2]);\n%! colorbar (\"eastoutside\");\n%! axis equal;\n\n## FIXME: need many BIST tests for colorbar\n\n%!test <*64287>\n%! unwind_protect\n%!   hf = figure (\"visible\", \"off\");\n%!   h = subplot (1, 1, 1);\n%!   imagesc (reshape (1:100, 10, 10));\n%!   colorbar;\n%!   lasterror (\"reset\");\n%!   colormap (h, flip (gray (10)));\n%!   assert (isempty (lasterr));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <expected string argument at position 1> colorbar (-pi)\n%!error <LOC specification must occur as first arg> colorbar (\"p\", \"v\", \"east\")\n%!error <missing value after \"location\"> colorbar (\"location\")\n%!error <missing axes handle after \"peer\"> colorbar (\"peer\")\n%!error <invalid axes handle following \"peer\"> colorbar (\"peer\", -1)\n%!error <PROP/VAL inputs must occur in pairs> colorbar (\"PROP\")\n%!error <unrecognized colorbar location> colorbar (\"location\", \"foobar\")\n"
  },
  {
    "path": "scripts/plot/draw/comet.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} comet (@var{y})\n## @deftypefnx {} {} comet (@var{x}, @var{y})\n## @deftypefnx {} {} comet (@var{x}, @var{y}, @var{p})\n## @deftypefnx {} {} comet (@var{hax}, @dots{})\n## Produce a simple comet style animation along the trajectory provided by\n## the input coordinate vectors (@var{x}, @var{y}).\n##\n## If @var{x} is not specified it defaults to the indices of @var{y}.\n##\n## The speed of the comet may be controlled by @var{p}, which represents the\n## time each point is displayed before moving to the next one.  The default for\n## @var{p} is @code{5 / numel (@var{y})}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n## @seealso{comet3}\n## @end deftypefn\n\nfunction comet (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"comet\", varargin{:});\n\n  if (nargin == 0 || nargin > 3)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    y = varargin{1};\n    x = 1:numel (y);\n    p = 5 / numel (y);\n  elseif (nargin == 2)\n    x = varargin{1};\n    y = varargin{2};\n    p = 5 / numel (y);\n  elseif (nargin == 3)\n    x = varargin{1};\n    y = varargin{2};\n    p = varargin{3};\n  endif\n\n  hax = newplot (hax);\n  limits = [min(x), max(x), min(y), max(y)];\n  num = numel (y);\n  dn = round (num/10);\n\n  hl = plot (hax, x(1), y(1), \"color\", \"r\", \"marker\", \"none\",\n                  x(1), y(1), \"color\", \"g\", \"marker\", \"none\",\n                  x(1), y(1), \"color\", \"b\", \"marker\", \"o\");\n  axis (hax, limits);  # set manual limits to speed up plotting\n\n  ## Initialize the timer\n  t = p;\n  timerid = tic ();\n\n  for n = 2:(num+dn)\n    m = n - dn;\n    m = max ([m, 1]);\n    k = min ([n, num]);\n    set (hl(1), \"xdata\", x(1:m), \"ydata\", y(1:m));\n    set (hl(2), \"xdata\", x(m:k), \"ydata\", y(m:k));\n    set (hl(3), \"xdata\", x(k),   \"ydata\", y(k));\n\n    pause (t - toc (timerid));\n    t += p;\n  endfor\n\nendfunction\n\n\n%!demo\n%! clf;\n%! title (\"comet() animation\");\n%! hold on;\n%! t = 0:.1:2*pi;\n%! x = cos (2*t) .* (cos (t).^2);\n%! y = sin (2*t) .* (sin (t).^2);\n%! comet (x, y, .05);\n%! hold off;\n"
  },
  {
    "path": "scripts/plot/draw/comet3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} comet3 (@var{z})\n## @deftypefnx {} {} comet3 (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} comet3 (@var{x}, @var{y}, @var{z}, @var{p})\n## @deftypefnx {} {} comet3 (@var{hax}, @dots{})\n## Produce a simple comet style animation along the trajectory provided by\n## the input coordinate vectors (@var{x}, @var{y}, @var{z}).\n##\n## If only @var{z} is specified then @var{x}, @var{y} default to the indices\n## of @var{z}.\n##\n## The speed of the comet may be controlled by @var{p}, which represents the\n## time each point is displayed before moving to the next one.  The default for\n## @var{p} is @code{5 / numel (@var{z})}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n## @seealso{comet}\n## @end deftypefn\n\nfunction comet3 (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"comet3\", varargin{:});\n\n  if (nargin == 0 || nargin == 2 || nargin > 4)\n    print_usage ();\n  elseif (nargin == 1)\n    z = varargin{1};\n    x = y = 1:numel (z);\n    p = 5 / numel (z);\n  elseif (nargin == 3)\n    x = varargin{1};\n    y = varargin{2};\n    z = varargin{3};\n    p = 5 / numel (z);\n  elseif (nargin == 4)\n    x = varargin{1};\n    y = varargin{2};\n    z = varargin{3};\n    p = varargin{4};\n  endif\n\n  hax = newplot (hax);\n  limits = [min(x), max(x), min(y), max(y), min(z), max(z)];\n  num = numel (y);\n  dn = round (num/10);\n\n  hl = plot3 (hax, x(1), y(1), z(1), \"color\", \"r\", \"marker\", \"none\",\n                   x(1), y(1), z(1), \"color\", \"g\", \"marker\", \"none\",\n                   x(1), y(1), z(1), \"color\", \"b\", \"marker\", \"o\");\n  axis (hax, limits);  # set manual limits to speed up plotting\n\n  ## Initialize the timer\n  t = p;\n  timerid = tic ();\n\n  for n = 2:(num+dn)\n    m = n - dn;\n    m = max ([m, 1]);\n    k = min ([n, num]);\n    set (hl(1), \"xdata\", x(1:m), \"ydata\", y(1:m), \"zdata\", z(1:m));\n    set (hl(2), \"xdata\", x(m:k), \"ydata\", y(m:k), \"zdata\", z(m:k));\n    set (hl(3), \"xdata\", x(k)  , \"ydata\", y(k)  , \"zdata\", z(k));\n\n    pause (t - toc (timerid));\n    t += p;\n  endfor\n\nendfunction\n\n\n%!demo\n%! clf;\n%! title (\"comet3() animation\");\n%! view (3); hold on;\n%! t = 0:pi/20:5*pi;\n%! comet3 (cos (t), sin (t), t);\n%! hold off;\n"
  },
  {
    "path": "scripts/plot/draw/compass.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} compass (@var{u}, @var{v})\n## @deftypefnx {} {} compass (@var{z})\n## @deftypefnx {} {} compass (@dots{}, @var{style})\n## @deftypefnx {} {} compass (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} compass (@dots{})\n##\n## Plot the @code{(@var{u}, @var{v})} components of a vector field emanating\n## from the origin of a polar plot.\n##\n## The arrow representing each vector has one end at the origin and the tip at\n## [@var{u}(i), @var{v}(i)].  If a single complex argument @var{z} is given,\n## then @code{@var{u} = real (@var{z})} and @code{@var{v} = imag (@var{z})}.\n##\n## The style to use for the plot can be defined with a line style @var{style}\n## of the same format as the @code{plot} command.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of graphics handles to the\n## line objects representing the drawn vectors.\n##\n## @example\n## @group\n## a = toeplitz ([1;randn(9,1)], [1,randn(1,9)]);\n## compass (eig (a));\n## @end group\n## @end example\n##\n## @seealso{polar, feather, quiver, rose, plot}\n## @end deftypefn\n\nfunction h = compass (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"compass\", varargin{:});\n\n  if (nargin == 0 || nargin > 3)\n    print_usage ();\n  endif\n\n  if (nargin == 1 || (nargin == 2 && ! isnumeric (varargin{2})))\n    z = varargin{1}(:).';\n    u = real (z);\n    v = imag (z);\n    have_line_spec = (nargin == 2);\n  elseif (nargin >= 2 && isnumeric (varargin{2}))\n    u = varargin{1}(:).';\n    v = varargin{2}(:).';\n    have_line_spec = (nargin == 3);\n  else\n    print_usage ();\n  endif\n\n  arrowsize = 0.20;\n  line_spec = \"-b\";\n\n  if (have_line_spec)\n    arg = varargin{end};\n    if (! (ischar (arg) || iscellstr (arg)))\n      error (\"compass: invalid linestyle STYLE\");\n    endif\n    [~, valid] = __pltopt__ (\"compass\", arg, false);\n    if (! valid)\n      error (\"compass: invalid linestyle STYLE\");\n    endif\n    line_spec = arg;\n  endif\n\n  ## Matlab draws compass plots with the arrow head as one continuous line,\n  ## and each arrow separately.  This is completely different from quiver\n  ## and quite ugly.\n  n = length (u);\n  xend = u;\n  xtmp = u .* (1 - arrowsize);\n  yend = v;\n  ytmp = v .* (1 - arrowsize);\n  x = [zeros(1, n); xend; xtmp - v * arrowsize / 3; xend; ...\n       xtmp + v * arrowsize / 3];\n  y = [zeros(1, n); yend; ytmp + u * arrowsize / 3; yend; ...\n       ytmp - u * arrowsize / 3];\n  [r, p] = cart2pol (x, y);\n\n  hax = newplot (hax);\n  htmp = polar (hax, r, p, line_spec);\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! randn_9x1_data = [-2.555884; 0.394974; -0.191871; -1.147024; 1.355425; -0.437335; -0.014370; -0.941312; 1.240300];\n%! randn_1x9_data = [1.42934, -1.10821, -1.70404, 0.63357, -0.68337, -1.19771, -0.96502, -1.12810, 0.22457];\n%! a = toeplitz ([1;randn_9x1_data], [1,randn_1x9_data]);\n%! compass (eig (a));\n%! title (\"compass() example\");\n\n## Test input validation\n%!error <Invalid call> compass ()\n%!error <Invalid call> compass (1,2,3,4)\n%!error compass (1, \"-r\", 2)\n%!error <invalid linestyle STYLE> compass (1, \"abc\")\n%!error <invalid linestyle STYLE> compass (1, {1})\n"
  },
  {
    "path": "scripts/plot/draw/contour.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} contour (@var{z})\n## @deftypefnx {} {} contour (@var{z}, @var{vn})\n## @deftypefnx {} {} contour (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} contour (@var{x}, @var{y}, @var{z}, @var{vn})\n## @deftypefnx {} {} contour (@dots{}, @var{style})\n## @deftypefnx {} {} contour (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{c}, @var{h}] =} contour (@dots{})\n## Create a 2-D contour plot.\n##\n## Plot level curves (contour lines) of the matrix @var{z}, using the\n## contour matrix @var{c} computed by @code{contourc} from the same\n## arguments; see the latter for their interpretation.\n##\n## The appearance of contour lines can be defined with a line style @var{style}\n## in the same manner as @code{plot}.  Only line style and color are used;\n## Any markers defined by @var{style} are ignored.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional output @var{c} contains the contour levels in @code{contourc}\n## format.\n##\n## The optional return value @var{h} is a graphics handle to the hggroup\n## comprising the contour lines.\n##\n## Example:\n##\n## @example\n## @group\n## x = 0:3;\n## y = 0:2;\n## z = y' * x;\n## contour (x, y, z, 2:3)\n## @end group\n## @end example\n##\n## @seealso{ezcontour, contourc, contourf, contour3, clabel, meshc, surfc,\n## clim, colormap, plot}\n##\n## @end deftypefn\n\nfunction [c, h] = contour (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"contour\", varargin{:});\n\n  hax = newplot (hax);\n\n  [ctmp, htmp] = __contour__ (hax, \"none\", varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"box\", \"on\");\n  endif\n\n  if (nargout > 0)\n    c = ctmp;\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = peaks ();\n%! contour (x, y, z);\n%! title ({\"contour() plot (isolines of constant Z)\"; \"Z = peaks()\"});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [theta, r] = meshgrid (linspace (0,2*pi,64), linspace (0,1,64));\n%! [X, Y] = pol2cart (theta, r);\n%! Z = sin (2*theta) .* (1-r);\n%! contour (X, Y, abs (Z), 10);\n%! title ({\"contour() plot\"; \"polar fcn: Z = sin (2*theta) * (1-r)\"});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! z = peaks ();\n%! contour (z, [0 0]);\n%! title ({\"contour() plot with single isoline at Z == 0\"; \"Z = peaks()\"});\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! clf (hf);\n%! unwind_protect\n%!   [x, y, z] = peaks ();\n%!   [c, h] = contour (x, y, z);\n%!   levellist = -6:6;\n%!   set (h, \"levellist\", levellist);\n%!   assert (get (h, \"levellist\"), levellist);\n%!   assert (get (h, \"levellistmode\"), \"manual\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! clf (hf);\n%! unwind_protect\n%!   [x, y, z] = peaks ();\n%!   [c, h] = contour (x, y, z);\n%!   levelstep = 3;\n%!   set (h, \"levelstep\", levelstep);\n%!   assert (get (h, \"levelstep\"), levelstep);\n%!   assert (get (h, \"levelstepmode\"), \"manual\");\n%!   assert (get (h, \"levellist\"), -6:levelstep:6);\n%!   assert (get (h, \"levellistmode\"), \"auto\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/contour3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} contour3 (@var{z})\n## @deftypefnx {} {} contour3 (@var{z}, @var{vn})\n## @deftypefnx {} {} contour3 (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} contour3 (@var{x}, @var{y}, @var{z}, @var{vn})\n## @deftypefnx {} {} contour3 (@dots{}, @var{style})\n## @deftypefnx {} {} contour3 (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{c}, @var{h}] =} contour3 (@dots{})\n## Create a 3-D contour plot.\n##\n## @code{contour3} plots level curves (contour lines) of the matrix @var{z}\n## at a Z level corresponding to each contour.  This is in contrast to\n## @code{contour} which plots all of the contour lines at the same Z level\n## and produces a 2-D plot.\n##\n## The level curves are taken from the contour matrix @var{c} computed by\n## @code{contourc} for the same arguments; see the latter for their\n## interpretation.\n##\n## The appearance of contour lines can be defined with a line style @var{style}\n## in the same manner as @code{plot}.  Only line style and color are used;\n## Any markers defined by @var{style} are ignored.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional output @var{c} are the contour levels in @code{contourc}\n## format.\n##\n## The optional return value @var{h} is a graphics handle to the hggroup\n## comprising the contour lines.\n##\n## Example:\n##\n## @example\n## @group\n## contour3 (peaks (19));\n## colormap cool;\n## hold on;\n## surf (peaks (19), \"facecolor\", \"none\", \"edgecolor\", \"black\");\n## @end group\n## @end example\n##\n## @seealso{contour, contourc, contourf, clabel, meshc, surfc, clim, colormap,\n## plot}\n## @end deftypefn\n\nfunction [c, h] = contour3 (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"contour3\", varargin{:});\n\n  hax = newplot (hax);\n\n  [ctmp, htmp] = __contour__ (hax, \"auto\", varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30], \"box\", \"on\",\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  endif\n\n  if (nargout > 0)\n    c = ctmp;\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (cool (64));\n%! surf (peaks (19), \"facecolor\", \"none\", \"edgecolor\", [0.85 0.85 0.85]);\n%! hold on;\n%! contour3 (peaks (19));\n%! hold off;\n%! axis tight;\n%! zlim auto;\n%! view (315, 17);\n%! title ({\"contour3 of peaks() function\", \"gray surf() shows peaks function\"});\n"
  },
  {
    "path": "scripts/plot/draw/contourc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} contourc (@var{z})\n## @deftypefnx {} {@var{c} =} contourc (@var{z}, @var{vn})\n## @deftypefnx {} {@var{c} =} contourc (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {@var{c} =} contourc (@var{x}, @var{y}, @var{z}, @var{vn})\n## @deftypefnx {} {[@var{c}, @var{lev}] =} contourc (@dots{})\n## Compute contour lines (isolines of constant Z value).\n##\n## The matrix @var{z} contains height values above the rectangular grid\n## determined by @var{x} and @var{y}.  If only a single input @var{z} is\n## provided then @var{x} is taken to be @code{1:columns (@var{z})} and @var{y}\n## is taken to be @code{1:rows (@var{z})}.  The minimum data size is 2x2.\n##\n## The optional input @var{vn} is either a scalar denoting the number of\n## contour lines to compute or a vector containing the Z values where lines\n## will be computed.  When @var{vn} is a vector the number of contour lines\n## is @code{numel (@var{vn})}.  However, to compute a single contour line\n## at a given value use @code{@var{vn} = [val, val]}.  If @var{vn} is omitted\n## it defaults to 10.\n##\n## The return value @var{c} is a 2x@var{n} matrix containing the contour lines\n## in the following format\n##\n## @example\n## @group\n## @var{c} = [lev1, x1, x2, @dots{}, levn, x1, x2, ...\n##      len1, y1, y2, @dots{}, lenn, y1, y2, @dots{}]\n## @end group\n## @end example\n##\n## @noindent\n## in which contour line @var{n} has a level (height) of @var{levn} and length\n## of @var{lenn}.\n##\n## The optional return value @var{lev} is a vector with the Z values of the\n## contour levels.\n##\n## Example:\n##\n## @smallexample\n## @group\n## x = 0:2;\n## y = x;\n## z = x' * y;\n## c = contourc (x, y, z, 2:3)\n##   @xresult{} c =\n##         2.0000   1.0000   1.0000   2.0000   2.0000   3.0000   1.5000   2.0000\n##         4.0000   2.0000   2.0000   1.0000   1.0000   2.0000   2.0000   1.5000\n## @end group\n## @end smallexample\n## @seealso{contour, contourf, contour3, clabel}\n## @end deftypefn\n\nfunction [c, lev] = contourc (varargin)\n\n  if (nargin < 1 || nargin > 4)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    z = varargin{1};\n    x = 1:columns (z);\n    y = 1:rows (z);\n    vn = 10;\n  elseif (nargin == 2)\n    z = varargin{1};\n    x = 1:columns (z);\n    y = 1:rows (z);\n    vn = varargin{2};\n  elseif (nargin == 3)\n    x = varargin{1};\n    y = varargin{2};\n    z = varargin{3};\n    vn = 10;\n  elseif (nargin == 4)\n    x = varargin{1};\n    y = varargin{2};\n    z = varargin{3};\n    vn = varargin{4};\n  endif\n\n  if (! (isnumeric (z) && isnumeric (x) && isnumeric (y))\n      || ! (ismatrix (z) && ismatrix (x) && ismatrix (y))\n      || ! (isreal (z) && isreal (x) && isreal (y)))\n    error (\"contourc: X, Y, and Z must be real numeric matrices\");\n  endif\n\n  if (rows (z) < 2 || columns (z) < 2)\n    error (\"contourc: Z data must have at least 2 rows and 2 columns\");\n  endif\n\n  if (isscalar (vn))\n    lev = linspace (min (z(:)), max (z(:)), vn+2)(2:end-1);\n  else\n    lev = unique (sort (vn));\n  endif\n\n  if (isvector (x) && isvector (y))\n    c = __contourc__ (x(:)', y(:)', z, lev);\n  elseif (! any (bsxfun (@minus, x, x(1,:))(:))\n          && ! any (bsxfun (@minus, y, y(:,1))(:)))\n    ## x,y are uniform grid (such as from meshgrid)\n    c = __contourc__ (x(1,:), y(:,1)', z, lev);\n  else\n    ## Data is sampled over non-uniform mesh.\n    ## Algorithm calculates contours for uniform grid\n    ## and then interpolates values back to the non-uniform mesh.\n\n    ## Uniform grid for __contourc__.\n    [nr, nc] = size (z);\n    ii = 1:nc;\n    jj = 1:nr;\n\n    c = __contourc__ (ii, jj, z, lev);\n\n    ## Map the contour lines from index space (i,j)\n    ## back to the original grid (x,y)\n    i = 1;\n\n    while (i < columns (c))\n      clen = c(2, i);\n      idx = i + (1:clen);\n\n      ci = c(1, idx);\n      cj = c(2, idx);\n\n      ## Due to rounding errors, some elements of ci and cj can fall out of the\n      ## range of ii and jj and interp2 would return NA for those values.\n      ## The permitted range is enforced here:\n\n      ci = max (ci, 1); ci = min (ci, nc);\n      cj = max (cj, 1); cj = min (cj, nr);\n\n      c(1, idx) = interp2 (ii, jj, x, ci, cj);\n      c(2, idx) = interp2 (ii, jj, y, ci, cj);\n\n      i += (clen + 1);\n    endwhile\n  endif\n\nendfunction\n\n\n%!test\n%! x = 0:2;\n%! y = x;\n%! z = x' * y;\n%! c_exp = [2, 1, 1, 2, 2, 3, 1.5, 2; 4, 2, 2, 1, 1, 2, 2, 1.5];\n%! lev_exp = [2 3];\n%! [c_obs, lev_obs] = contourc (x, y, z, 2:3);\n%! assert (c_obs, c_exp, eps);\n%! assert (lev_obs, lev_exp, eps);\n\n## Test input validation\n%!error <Invalid call> contourc ()\n%!error <Invalid call> contourc (1,2,3,4,5)\n%!error <X, Y, and Z must be .* numeric> contourc ({3})\n%!error <X, Y, and Z must be .* numeric> contourc ({1}, 2, 3)\n%!error <X, Y, and Z must be .* numeric> contourc (1, {2}, 3)\n%!error <X, Y, and Z must be .* matrices> contourc (ones (3,3,3))\n%!error <X, Y, and Z must be .* matrices> contourc (ones (3,3,3), 2, 3)\n%!error <X, Y, and Z must be .* matrices> contourc (1, ones (3,3,3), 3)\n%!error <X, Y, and Z must be real> contourc (3i)\n%!error <X, Y, and Z must be real> contourc (1i, 2, 3)\n%!error <X, Y, and Z must be real> contourc (1, 2i, 3)\n%!error <Z data must have at least 2 rows> contourc ([1, 2])\n%!error <Z data must have at least .* 2 columns> contourc ([1; 2])\n"
  },
  {
    "path": "scripts/plot/draw/contourf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} contourf (@var{z})\n## @deftypefnx {} {} contourf (@var{z}, @var{vn})\n## @deftypefnx {} {} contourf (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} contourf (@var{x}, @var{y}, @var{z}, @var{vn})\n## @deftypefnx {} {} contourf (@dots{}, @var{style})\n## @deftypefnx {} {} contourf (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{c}, @var{h}] =} contourf (@dots{})\n## Create a 2-D contour plot with filled intervals.\n##\n## Plot level curves (contour lines) of the matrix @var{z} and fill the region\n## between lines with colors from the current colormap.\n##\n## The level curves are taken from the contour matrix @var{c} computed by\n## @code{contourc} for the same arguments; see the latter for their\n## interpretation.\n##\n## The appearance of contour lines can be defined with a line style @var{style}\n## in the same manner as @code{plot}.  Only line style and color are used;\n## Any markers defined by @var{style} are ignored.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional output @var{c} contains the contour levels in @code{contourc}\n## format.\n##\n## The optional return value @var{h} is a graphics handle to the hggroup\n## comprising the contour lines.\n##\n## The following example plots filled contours of the @code{peaks} function.\n##\n## @example\n## @group\n## [x, y, z] = peaks (50);\n## contourf (x, y, z, -7:9)\n## @end group\n## @end example\n## @seealso{ezcontourf, contour, contourc, contour3, clabel, meshc, surfc,\n## clim, colormap, plot}\n## @end deftypefn\n\nfunction [c, h] = contourf (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"contour\", varargin{:});\n\n  hax = newplot (hax);\n\n  [ctmp, htmp] = __contour__ (hax, \"none\", \"fill\", \"on\",\n                                   \"linecolor\", \"black\", varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"box\", \"on\");\n  endif\n\n  if (nargout > 0)\n    c = ctmp;\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = peaks (50);\n%! contourf (x, y, z, -7:9);\n%! title ({\"contourf() plot (filled contour lines)\"; \"Z = peaks()\"});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [theta, r] = meshgrid (linspace (0,2*pi,64), linspace (0,1,64));\n%! [X, Y] = pol2cart (theta, r);\n%! Z = sin (2*theta) .* (1-r);\n%! contourf (X, Y, abs (Z), 10);\n%! title ({\"contourf() plot\"; \"polar fcn: Z = sin (2*theta) * (1-r)\"});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! x = linspace (-2, 2);\n%! [x, y] = meshgrid (x);\n%! z = sqrt (x.^2 + y.^2) ./ (x.^2 + y.^2 + 1);\n%! contourf (x, y, z, [0.4, 0.4]);\n%! title (\"Hole should be filled with the background color\");\n"
  },
  {
    "path": "scripts/plot/draw/cylinder.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} cylinder\n## @deftypefnx {} {} cylinder (@var{r})\n## @deftypefnx {} {} cylinder (@var{r}, @var{n})\n## @deftypefnx {} {} cylinder (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} cylinder (@dots{})\n## Plot a 3-D unit cylinder.\n##\n## The optional input @var{r} is a vector specifying the radius along the\n## unit z-axis.  The default is [1 1] indicating radius 1 at @code{Z == 0}\n## and at @code{Z == 1}.\n##\n## The optional input @var{n} determines the number of faces around the\n## circumference of the cylinder.  The default value is 20.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## If outputs are requested @code{cylinder} returns three matrices in\n## @code{meshgrid} format, such that @code{surf (@var{x}, @var{y}, @var{z})}\n## generates a unit cylinder.\n##\n## Example:\n##\n## @example\n## @group\n## [x, y, z] = cylinder (10:-1:0, 50);\n## surf (x, y, z);\n## title (\"a cone\");\n## @end group\n## @end example\n## @seealso{ellipsoid, rectangle, sphere}\n## @end deftypefn\n\nfunction [x, y, z] = cylinder (varargin)\n\n  [hax, args, nargs] = __plt_get_axis_arg__ (\"cylinder\", varargin{:});\n\n  if (nargs > 2)\n    print_usage ();\n  elseif (nargs == 0)\n    r = [1, 1];\n    n = 20;\n  elseif (nargs == 1)\n    r = args{1};\n    n = 20;\n  else\n    r = args{1};\n    n = args{2};\n  endif\n\n  if (! isvector (r))\n    error (\"cylinder: R must be a scalar or vector\");\n  endif\n  if (isscalar (r))\n    r .*= [1 1];  # expand single radius specification to required 2-term form\n  endif\n\n  phi = linspace (0, 2*pi, n+1);\n  idx = 1:length (r);\n  [phi, idx] = meshgrid (phi, idx);\n  zz = (idx - 1) / (length (r) - 1);\n  r = r(idx);\n  [xx, yy] = pol2cart (phi, r);\n\n  if (nargout > 0)\n    x = xx;\n    y = yy;\n    z = zz;\n  else\n    hax = newplot (hax);\n    surf (hax, xx, yy, zz);\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = cylinder (10:-1:0, 50);\n%! surf (x, y, z);\n%! title (\"cylinder() with linearly shrinking radius produces a cone\");\n\n## Test input validation\n%!error <Invalid call> cylinder (1,2,3)\n%!error <R must be a scalar> cylinder ([])\n%!error <R must be a scalar or vector> cylinder (ones (2,2))\n"
  },
  {
    "path": "scripts/plot/draw/ellipsoid.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ellipsoid (@var{xc}, @var{yc}, @var{zc}, @var{xr}, @var{yr}, @var{zr})\n## @deftypefnx {} {} ellipsoid (@dots{}, @var{n})\n## @deftypefnx {} {} ellipsoid (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} ellipsoid (@dots{})\n## Plot a 3-D ellipsoid.\n##\n## The inputs @var{xc}, @var{yc}, @var{zc} specify the center of the ellipsoid.\n## The inputs @var{xr}, @var{yr}, @var{zr} specify the semi-major axis lengths.\n##\n## The optional input @var{n} determines the number of faces around the\n## circumference of the cylinder.  The default value is 20.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## If outputs are requested @code{ellipsoid} returns three matrices in\n## @code{meshgrid} format, such that @code{surf (@var{x}, @var{y}, @var{z})}\n## generates the ellipsoid.\n## @seealso{cylinder, rectangle, sphere}\n## @end deftypefn\n\nfunction [x, y, z] = ellipsoid (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"ellipsoid\", varargin{:});\n\n  if (nargin != 6 && nargin != 7)\n    print_usage ();\n  endif\n\n  xc = varargin{1};\n  yc = varargin{2};\n  zc = varargin{3};\n  xr = varargin{4};\n  yr = varargin{5};\n  zr = varargin{6};\n\n  if (nargin == 6)\n    n = 20;\n  else\n    n = varargin{7};\n    if (! (isreal (n) && isscalar (n) && n > 0))\n      error (\"ellipsoid: N must be a real scalar > 0\");\n    endif\n    n = floor (n);\n  endif\n\n  theta = linspace (0, 2 * pi, n + 1);\n  phi = linspace (-pi / 2, pi / 2, n + 1);\n  [theta, phi] = meshgrid (theta, phi);\n\n  xx = xr .* cos (phi) .* cos (theta) + xc;\n  yy = yr .* cos (phi) .* sin (theta) + yc;\n  zz = zr .* sin (phi) + zc;\n\n  if (nargout > 0)\n    x = xx;\n    y = yy;\n    z = zz;\n  else\n    hax = newplot (hax);\n\n    surf (hax, xx, yy, zz);\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! ellipsoid (0, 0, 1, 2, 3, 4, 20);\n%! title (\"ellipsoid()\");\n\n%!test <*64468> # No return if nargout = 0\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   1 + 1;\n%!   assert (ans, 2);\n%!   ellipsoid (hax, 0, 0, 0, 1, 1, 1);\n%!   assert (ans, 2);\n%!\n%!  unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> ellipsoid (1,2,3,4,5)\n%!error <Invalid call> ellipsoid (1,2,3,4,5,6,7,8)\n%!error <N must be a real scalar> ellipsoid (1,2,3,4,5,6, 2i)\n%!error <N must be a real scalar> ellipsoid (1,2,3,4,5,6, ones (2,2))\n%!error <N must be a real scalar . 0> ellipsoid (1,2,3,4,5,6, -1)\n"
  },
  {
    "path": "scripts/plot/draw/errorbar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} errorbar (@var{y}, @var{ey})\n## @deftypefnx {} {} errorbar (@var{y}, @dots{}, @var{fmt})\n## @deftypefnx {} {} errorbar (@var{x}, @var{y}, @var{ey})\n## @deftypefnx {} {} errorbar (@var{x}, @var{y}, @var{err}, @var{fmt})\n## @deftypefnx {} {} errorbar (@var{x}, @var{y}, @var{lerr}, @var{uerr}, @var{fmt})\n## @deftypefnx {} {} errorbar (@var{x}, @var{y}, @var{ex}, @var{ey}, @var{fmt})\n## @deftypefnx {} {} errorbar (@var{x}, @var{y}, @var{lx}, @var{ux}, @var{ly}, @var{uy}, @var{fmt})\n## @deftypefnx {} {} errorbar (@var{x1}, @var{y1}, @dots{}, @var{fmt}, @var{xn}, @var{yn}, @dots{})\n## @deftypefnx {} {} errorbar (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} errorbar (@dots{})\n## Create a 2-D plot with errorbars.\n##\n## Many different combinations of arguments are possible.  The simplest form is\n##\n## @example\n## errorbar (@var{y}, @var{ey})\n## @end example\n##\n## @noindent\n## where the first argument is taken as the set of @var{y} coordinates, the\n## second argument @var{ey} are the errors around the @var{y} values, and the\n## @var{x} coordinates are taken to be the indices of the elements\n## (@code{1:numel (@var{y})}).\n##\n## The general form of the function is\n##\n## @example\n## errorbar (@var{x}, @var{y}, @var{err1}, @dots{}, @var{fmt}, @dots{})\n## @end example\n##\n## @noindent\n## After the @var{x} and @var{y} arguments there can be 1, 2, or 4\n## parameters specifying the error values depending on the nature of the error\n## values and the plot format @var{fmt}.\n##\n## @table @asis\n## @item @var{err} (scalar)\n## When the error is a scalar all points share the same error value.\n## The errorbars are symmetric and are drawn from @var{data}-@var{err} to\n## @var{data}+@var{err}.\n## The @var{fmt} argument determines whether @var{err} is in the x-direction,\n## y-direction (default), or both.\n##\n## @item @var{err} (vector or matrix)\n## Each data point has a particular error value.\n## The errorbars are symmetric and are drawn from @var{data}(n)-@var{err}(n) to\n## @var{data}(n)+@var{err}(n).\n##\n## @item @var{lerr}, @var{uerr} (scalar)\n## The errors have a single low-side value and a single upper-side value.\n## The errorbars are not symmetric and are drawn from @var{data}-@var{lerr} to\n## @var{data}+@var{uerr}.\n##\n## @item @var{lerr}, @var{uerr} (vector or matrix)\n## Each data point has a low-side error and an upper-side error.\n## The errorbars are not symmetric and are drawn from\n## @var{data}(n)-@var{lerr}(n) to @var{data}(n)+@var{uerr}(n).\n## @end table\n##\n## Any number of data sets (@var{x1},@var{y1}, @var{x2},@var{y2}, @dots{}) may\n## appear as long as they are separated by a format string @var{fmt}.\n##\n## If @var{y} is a matrix, @var{x} and the error parameters must also be\n## matrices having the same dimensions.  The columns of @var{y} are plotted\n## versus the corresponding columns of @var{x} and errorbars are taken from\n## the corresponding columns of the error parameters.\n##\n## If @var{fmt} is missing, the yerrorbars (\"~\") plot style is assumed.\n##\n## If the @var{fmt} argument is supplied then it is interpreted, as in normal\n## plots, to specify the line style, marker, and color.  In addition,\n## @var{fmt} may include an errorbar style which @strong{must precede} the\n## ordinary format codes.  The following errorbar styles are supported:\n##\n## @table @samp\n## @item ~\n## Set yerrorbars plot style (default).\n##\n## @item >\n## Set xerrorbars plot style.\n##\n## @item ~>\n## Set xyerrorbars plot style.\n##\n## @item #~\n## Set yboxes plot style.\n##\n## @item #\n## Set xboxes plot style.\n##\n## @item #~>\n## Set xyboxes plot style.\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a handle to the hggroup object\n## representing the data plot and errorbars.\n##\n## Note: For compatibility with @sc{matlab} a line is drawn through all data\n## points.  However, most scientific errorbar plots are a scatter plot of\n## points with errorbars.  To accomplish this, add a marker style to the\n## @var{fmt} argument such as @qcode{\".\"}.  Alternatively, remove the line\n## by modifying the returned graphic handle with\n## @code{set (h, \"linestyle\", \"none\")}.\n##\n## Examples:\n##\n## @example\n## errorbar (@var{x}, @var{y}, @var{ex}, \">.r\")\n## @end example\n##\n## @noindent\n## produces an xerrorbar plot of @var{y} versus @var{x} with @var{x}\n## errorbars drawn from @var{x}-@var{ex} to @var{x}+@var{ex}.  The marker\n## @qcode{\".\"} is used so no connecting line is drawn and the errorbars\n## appear in red.\n##\n## @example\n## @group\n## errorbar (@var{x}, @var{y1}, @var{ey}, \"~\",\n##           @var{x}, @var{y2}, @var{ly}, @var{uy})\n## @end group\n## @end example\n##\n## @noindent\n## produces yerrorbar plots with @var{y1} and @var{y2} versus @var{x}.\n## Errorbars for @var{y1} are drawn from @var{y1}-@var{ey} to\n## @var{y1}+@var{ey}, errorbars for @var{y2} from @var{y2}-@var{ly} to\n## @var{y2}+@var{uy}.\n##\n## @example\n## @group\n## errorbar (@var{x}, @var{y}, @var{lx}, @var{ux},\n##           @var{ly}, @var{uy}, \"~>\")\n## @end group\n## @end example\n##\n## @noindent\n## produces an xyerrorbar plot of @var{y} versus @var{x} in which\n## @var{x} errorbars are drawn from @var{x}-@var{lx} to @var{x}+@var{ux}\n## and @var{y} errorbars from @var{y}-@var{ly} to @var{y}+@var{uy}.\n## @seealso{semilogxerr, semilogyerr, loglogerr, plot}\n## @end deftypefn\n\nfunction h = errorbar (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"errorbar\", varargin{:});\n\n  hax = newplot (hax);\n\n  htmp = __errplot__ (\"errorbar\", hax, varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"box\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! rand_1x11_data1 = [0.82712, 0.50325, 0.35613, 0.77089, 0.20474, 0.69160, 0.30858, 0.88225, 0.35187, 0.14168, 0.54270];\n%! rand_1x11_data2 = [0.506375, 0.330106, 0.017982, 0.859270, 0.140641, 0.327839, 0.275886, 0.162453, 0.807592, 0.318509, 0.921112];\n%! errorbar (0:10, rand_1x11_data1, 0.25*rand_1x11_data2);\n%! title (\"errorbar() with Y errorbars\");\n\n%!demo\n%! clf;\n%! rand_1x11_data3 = [0.423650, 0.142331, 0.213195, 0.129301, 0.975891, 0.012872, 0.635327, 0.338829, 0.764997, 0.401798, 0.551850];\n%! rand_1x11_data4 = [0.682566, 0.456342, 0.132390, 0.341292, 0.108633, 0.601553, 0.040455, 0.146665, 0.309187, 0.586291, 0.540149];\n%! errorbar (0:10, rand_1x11_data3, rand_1x11_data4, \">\");\n%! title (\"errorbar() with X errorbars\");\n\n%!demo\n%! clf;\n%! x = 0:0.5:2*pi;\n%! err = x/30;\n%! y1 = sin (x);\n%! y2 = cos (x);\n%! errorbar (x, y1, err, \"~\", x, y2, err, \">\");\n%! legend (\"Y errbar\", \"X errbar\");\n%! title (\"errorbar() with 2 datasets\");\n\n%!demo\n%! clf;\n%! x = 0:0.5:2*pi;\n%! err = x/30;\n%! y1 = sin (x);\n%! y2 = cos (x);\n%! errorbar (x, y1, err, err, \"#r\", x, y2, err, err, \"#~\");\n%! legend (\"X errbox\", \"Y errbox\");\n%! title (\"errorbar() with error boxes\");\n\n%!demo\n%! clf;\n%! x = 0:0.5:2*pi;\n%! err = x/30;\n%! y1 = sin (x);\n%! y2 = cos (x);\n%! errorbar (x, y1, err, err, err, err, \"~>\", ...\n%!           x, y2, err, err, err, err, \"#~>-*\");\n%! legend (\"X-Y errbars\", \"X-Y errboxes\");\n%! title (\"errorbar() with X-Y errorbars and error boxes\");\n\n## Invisible figure used for tests\n%!shared hf, hax\n%! hf = figure (\"visible\", \"off\");\n%! hax = axes ();\n\n%!error errorbar ()\n%!error errorbar (1)\n%!error <data argument 1 must be numeric> errorbar (hax, {1}, 2)\n%!error <data argument 2 must be numeric> errorbar (hax, 1, {2})\n%!error <size of argument 2 does not match others> errorbar (hax, 1, 1:2)\n%!error <size of argument 3 does not match others> errorbar (hax, 1, 2, 3:4)\n%!error <too many arguments to plot> errorbar (1,2,3,4,5,6,7)\n\n%!error <2 column errorplot is only valid for xerr> errorbar (1,2, \"~>\")\n%!error <6 columns only valid for xyerr and boxxy> errorbar (1,2,3,4,5,6, \"~\")\n%!error <error plot requires 2, 3, 4, or 6 arguments> errorbar (1,2,3,4,5)\n\n## Close figure used for testing\n%!test\n%! close (hf);\n"
  },
  {
    "path": "scripts/plot/draw/ezcontour.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ezcontour (@var{f})\n## @deftypefnx {} {} ezcontour (@dots{}, @var{dom})\n## @deftypefnx {} {} ezcontour (@dots{}, @var{n})\n## @deftypefnx {} {} ezcontour (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ezcontour (@dots{})\n##\n## Plot the contour lines of a function.\n##\n## @var{f} is a string, inline function, or function handle with two arguments\n## defining the function.  By default the plot is over the meshed domain\n## @code{-2*pi <= @var{x} | @var{y} <= 2*pi} with 60 points in each dimension.\n##\n## If @var{dom} is a two element vector, it represents the minimum and maximum\n## values of both @var{x} and @var{y}.  If @var{dom} is a four element vector,\n## then the minimum and maximum values are @code{[xmin xmax ymin ymax]}.\n##\n## @var{n} is a scalar defining the number of points to use in each dimension.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n##\n## Example:\n##\n## @example\n## @group\n## f = @@(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n## ezcontour (f, [-3, 3]);\n## @end group\n## @end example\n##\n## @seealso{contour, ezcontourf, ezplot, ezmeshc, ezsurfc}\n## @end deftypefn\n\nfunction h = ezcontour (varargin)\n\n  [htmp, needusage] = __ezplot__ (\"contour\", varargin{:});\n\n  if (needusage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! f = @(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n%! ezcontour (f, [-3, 3]);\n"
  },
  {
    "path": "scripts/plot/draw/ezcontourf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ezcontourf (@var{f})\n## @deftypefnx {} {} ezcontourf (@dots{}, @var{dom})\n## @deftypefnx {} {} ezcontourf (@dots{}, @var{n})\n## @deftypefnx {} {} ezcontourf (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ezcontourf (@dots{})\n##\n## Plot the filled contour lines of a function.\n##\n## @var{f} is a string, inline function, or function handle with two arguments\n## defining the function.  By default the plot is over the meshed domain\n## @code{-2*pi <= @var{x} | @var{y} <= 2*pi} with 60 points in each dimension.\n##\n## If @var{dom} is a two element vector, it represents the minimum and maximum\n## values of both @var{x} and @var{y}.  If @var{dom} is a four element vector,\n## then the minimum and maximum values are @code{[xmin xmax ymin ymax]}.\n##\n## @var{n} is a scalar defining the number of points to use in each dimension.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n##\n## Example:\n##\n## @example\n## @group\n## f = @@(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n## ezcontourf (f, [-3, 3]);\n## @end group\n## @end example\n##\n## @seealso{contourf, ezcontour, ezplot, ezmeshc, ezsurfc}\n## @end deftypefn\n\nfunction h = ezcontourf (varargin)\n\n  [htmp, needusage] = __ezplot__ (\"contourf\", varargin{:});\n\n  if (needusage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! f = @(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n%! ezcontourf (f, [-3, 3]);\n"
  },
  {
    "path": "scripts/plot/draw/ezmesh.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ezmesh (@var{f})\n## @deftypefnx {} {} ezmesh (@var{fx}, @var{fy}, @var{fz})\n## @deftypefnx {} {} ezmesh (@dots{}, @var{dom})\n## @deftypefnx {} {} ezmesh (@dots{}, @var{n})\n## @deftypefnx {} {} ezmesh (@dots{}, \"circ\")\n## @deftypefnx {} {} ezmesh (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ezmesh (@dots{})\n##\n## Plot the mesh defined by a function.\n##\n## @var{f} is a string, inline function, or function handle with two arguments\n## defining the function.  By default the plot is over the meshed domain\n## @code{-2*pi <= @var{x} | @var{y} <= 2*pi} with 60 points in each dimension.\n##\n## If three functions are passed, then plot the parametrically defined\n## function @code{[@var{fx}(@var{s}, @var{t}), @var{fy}(@var{s}, @var{t}),\n## @var{fz}(@var{s}, @var{t})]}.\n##\n## If @var{dom} is a two element vector, it represents the minimum and maximum\n## values of both @var{x} and @var{y}.  If @var{dom} is a four element vector,\n## then the minimum and maximum values are @code{[xmin xmax ymin ymax]}.\n##\n## @var{n} is a scalar defining the number of points to use in each dimension.\n##\n## If the argument @qcode{\"circ\"} is given, then the function is plotted over\n## a disk centered on the middle of the domain @var{dom}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## Example 1: 2-argument function\n##\n## @example\n## @group\n## f = @@(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n## ezmesh (f, [-3, 3]);\n## @end group\n## @end example\n##\n## Example 2: parametrically defined function\n##\n## @example\n## @group\n## fx = @@(s,t) cos (s) .* cos (t);\n## fy = @@(s,t) sin (s) .* cos (t);\n## fz = @@(s,t) sin (t);\n## ezmesh (fx, fy, fz, [-pi, pi, -pi/2, pi/2], 20);\n## @end group\n## @end example\n##\n## @seealso{mesh, ezmeshc, ezplot, ezsurf, ezsurfc, hidden}\n## @end deftypefn\n\nfunction h = ezmesh (varargin)\n\n  [htmp, needusage] = __ezplot__ (\"mesh\", varargin{:});\n\n  if (needusage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! f = @(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n%! ezmesh (f, [-3, 3]);\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! fx = @(s,t) cos (s) .* cos (t);\n%! fy = @(s,t) sin (s) .* cos (t);\n%! fz = @(s,t) sin (t);\n%! ezmesh (fx, fy, fz, [-pi,pi,-pi/2,pi/2], 20);\n"
  },
  {
    "path": "scripts/plot/draw/ezmeshc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ezmeshc (@var{f})\n## @deftypefnx {} {} ezmeshc (@var{fx}, @var{fy}, @var{fz})\n## @deftypefnx {} {} ezmeshc (@dots{}, @var{dom})\n## @deftypefnx {} {} ezmeshc (@dots{}, @var{n})\n## @deftypefnx {} {} ezmeshc (@dots{}, \"circ\")\n## @deftypefnx {} {} ezmeshc (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ezmeshc (@dots{})\n##\n## Plot the mesh and contour lines defined by a function.\n##\n## @var{f} is a string, inline function, or function handle with two arguments\n## defining the function.  By default the plot is over the meshed domain\n## @code{-2*pi <= @var{x} | @var{y} <= 2*pi} with 60 points in each dimension.\n##\n## If three functions are passed, then plot the parametrically defined\n## function @code{[@var{fx}(@var{s}, @var{t}), @var{fy}(@var{s}, @var{t}),\n## @var{fz}(@var{s}, @var{t})]}.\n##\n## If @var{dom} is a two element vector, it represents the minimum and maximum\n## values of both @var{x} and @var{y}.  If @var{dom} is a four element vector,\n## then the minimum and maximum values are @code{[xmin xmax ymin ymax]}.\n##\n## @var{n} is a scalar defining the number of points to use in each dimension.\n##\n## If the argument @qcode{\"circ\"} is given, then the function is plotted over\n## a disk centered on the middle of the domain @var{dom}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a 2-element vector with a graphics\n## handle for the created mesh plot and a second handle for the created contour\n## plot.\n##\n## Example: 2-argument function\n##\n## @example\n## @group\n## f = @@(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n## ezmeshc (f, [-3, 3]);\n## @end group\n## @end example\n##\n## @seealso{meshc, ezmesh, ezplot, ezsurf, ezsurfc, hidden}\n## @end deftypefn\n\nfunction h = ezmeshc (varargin)\n\n  [htmp, needusage] = __ezplot__ (\"meshc\", varargin{:});\n\n  if (needusage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! f = @(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n%! ezmeshc (f, [-3, 3]);\n"
  },
  {
    "path": "scripts/plot/draw/ezplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ezplot (@var{f})\n## @deftypefnx {} {} ezplot (@var{f2v})\n## @deftypefnx {} {} ezplot (@var{fx}, @var{fy})\n## @deftypefnx {} {} ezplot (@dots{}, @var{dom})\n## @deftypefnx {} {} ezplot (@dots{}, @var{n})\n## @deftypefnx {} {} ezplot (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ezplot (@dots{})\n##\n## Plot the 2-D curve defined by the function @var{f}.\n##\n## The function @var{f} may be a string, inline function, or function handle\n## and can have either one or two variables.  If @var{f} has one variable, then\n## the function is plotted over the domain @code{-2*pi < @var{x} < 2*pi}\n## with 500 points.\n##\n## If @var{f2v} is a function of two variables then the implicit function\n## @code{@var{f}(@var{x},@var{y}) = 0} is calculated over the meshed domain\n## @code{-2*pi <= @var{x} | @var{y} <= 2*pi} with 60 points in each dimension.\n##\n## For example:\n##\n## @example\n## ezplot (@@(@var{x}, @var{y}) @var{x}.^2 - @var{y}.^2 - 1)\n## @end example\n##\n## If two functions are passed as inputs then the parametric function\n##\n## @example\n## @group\n## @var{x} = @var{fx} (@var{t})\n## @var{y} = @var{fy} (@var{t})\n## @end group\n## @end example\n##\n## @noindent\n## is plotted over the domain @code{-2*pi <= @var{t} <= 2*pi} with 500 points.\n##\n## If @var{dom} is a two element vector, it represents the minimum and maximum\n## values of both @var{x} and @var{y}, or @var{t} for a parametric plot.  If\n## @var{dom} is a four element vector, then the minimum and maximum values are\n## @code{[xmin xmax ymin ymax]}.\n##\n## @var{n} is a scalar defining the number of points to use in plotting\n## the function.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of graphics handles to\n## the created line objects.\n##\n## @seealso{plot, ezplot3, ezpolar, ezcontour, ezcontourf, ezmesh, ezmeshc,\n## ezsurf, ezsurfc}\n## @end deftypefn\n\nfunction h = ezplot (varargin)\n\n  [htmp, needusage] = __ezplot__ (\"plot\", varargin{:});\n\n  if (needusage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! ## sinc function using function handle\n%! clf;\n%! f = @(x) sin (pi*x) ./ (pi*x);\n%! ezplot (f);\n\n%!demo\n%! ## example of a function string and explicit limits\n%! clf;\n%! ezplot (\"1/x\", [-2 2]);\n\n%!demo\n%! ## parameterized function example over -2*pi <= t <= +2*pi\n%! clf;\n%! ezplot (@cos, @sin);\n\n%!demo\n%! ## implicit function of 2 variables\n%! clf;\n%! ezplot (inline (\"x^2 - y^2 - 1\"));\n\n%!test <*66563>\n%! ## ezplot of a constant function should not fail\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ezplot (@(x) 2*5 + 1);\n%!   assert (ylim (), [10 12], -1e-2);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/ezplot3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ezplot3 (@var{fx}, @var{fy}, @var{fz})\n## @deftypefnx {} {} ezplot3 (@dots{}, @var{dom})\n## @deftypefnx {} {} ezplot3 (@dots{}, @var{n})\n## @deftypefnx {} {} ezplot3 (@dots{}, \"animate\")\n## @deftypefnx {} {} ezplot3 (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ezplot3 (@dots{})\n##\n## Plot a parametrically defined curve in three dimensions.\n##\n## @var{fx}, @var{fy}, and @var{fz} are strings, inline functions,\n## or function handles with one argument defining the function.  By\n## default the plot is over the domain @code{0 <= @var{t} <= 2*pi}\n## with 500 points.\n##\n## If @var{dom} is a two element vector, it represents the minimum and maximum\n## values of @var{t}.\n##\n## @var{n} is a scalar defining the number of points to use in plotting the\n## function.\n##\n## If the @qcode{\"animate\"} option is given then the plotting is animated\n## in the style of @code{comet3}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n##\n## @example\n## @group\n## fx = @@(t) cos (t);\n## fy = @@(t) sin (t);\n## fz = @@(t) t;\n## ezplot3 (fx, fy, fz, [0, 10*pi], 100);\n## @end group\n## @end example\n##\n## @seealso{plot3, comet3, ezplot, ezmesh, ezsurf}\n## @end deftypefn\n\nfunction h = ezplot3 (varargin)\n\n  [htmp, needusage] = __ezplot__ (\"plot3\", varargin{:});\n\n  if (needusage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! fx = @(t) cos (t);\n%! fy = @(t) sin (t);\n%! fz = @(t) t;\n%! ezplot3 (fx, fy, fz, [0, 10*pi]);\n\n%!demo\n%! clf;\n%! fx = @(t) cos (t);\n%! fy = @(t) sin (t);\n%! fz = @(t) t;\n%! ezplot3 (fx, fy, fz, [0, 5*pi], \"animate\");\n"
  },
  {
    "path": "scripts/plot/draw/ezpolar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ezpolar (@var{f})\n## @deftypefnx {} {} ezpolar (@dots{}, @var{dom})\n## @deftypefnx {} {} ezpolar (@dots{}, @var{n})\n## @deftypefnx {} {} ezpolar (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ezpolar (@dots{})\n##\n## Plot a 2-D function in polar coordinates.\n##\n## The function @var{f} is a string, inline function, or function handle with\n## a single argument.  The expected form of the function is\n## @code{@var{rho} = @var{f}(@var{theta})}.\n## By default the plot is over the domain @code{0 <= @var{theta} <= 2*pi}\n## with 500 points.\n##\n## If @var{dom} is a two element vector, it represents the minimum and maximum\n## values of @var{theta}.\n##\n## @var{n} is a scalar defining the number of points to use in plotting\n## the function.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n##\n## Example:\n##\n## @example\n## ezpolar (@@(t) sin (5/4 * t), [0, 8*pi]);\n## @end example\n##\n## @seealso{polar, ezplot}\n## @end deftypefn\n\nfunction h = ezpolar (varargin)\n\n  [htmp, needusage] = __ezplot__ (\"polar\", varargin{:});\n\n  if (needusage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! ezpolar (@(t) sin (5/4 * t), [0, 8*pi]);\n"
  },
  {
    "path": "scripts/plot/draw/ezsurf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ezsurf (@var{f})\n## @deftypefnx {} {} ezsurf (@var{fx}, @var{fy}, @var{fz})\n## @deftypefnx {} {} ezsurf (@dots{}, @var{dom})\n## @deftypefnx {} {} ezsurf (@dots{}, @var{n})\n## @deftypefnx {} {} ezsurf (@dots{}, \"circ\")\n## @deftypefnx {} {} ezsurf (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ezsurf (@dots{})\n##\n## Plot the surface defined by a function.\n##\n## @var{f} is a string, inline function, or function handle with two arguments\n## defining the function.  By default the plot is over the meshed domain\n## @code{-2*pi <= @var{x} | @var{y} <= 2*pi} with 60 points in each dimension.\n##\n## If three functions are passed, then plot the parametrically defined\n## function @code{[@var{fx}(@var{s}, @var{t}), @var{fy}(@var{s}, @var{t}),\n## @var{fz}(@var{s}, @var{t})]}.\n##\n## If @var{dom} is a two element vector, it represents the minimum and maximum\n## values of both @var{x} and @var{y}.  If @var{dom} is a four element vector,\n## then the minimum and maximum values are @code{[xmin xmax ymin ymax]}.\n##\n## @var{n} is a scalar defining the number of points to use in each dimension.\n##\n## If the argument @qcode{\"circ\"} is given, then the function is plotted over\n## a disk centered on the middle of the domain @var{dom}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## Example 1: 2-argument function\n##\n## @example\n## @group\n## f = @@(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n## ezsurf (f, [-3, 3]);\n## @end group\n## @end example\n##\n## Example 2: parametrically defined function\n##\n## @example\n## @group\n## fx = @@(s,t) cos (s) .* cos (t);\n## fy = @@(s,t) sin (s) .* cos (t);\n## fz = @@(s,t) sin (t);\n## ezsurf (fx, fy, fz, [-pi, pi, -pi/2, pi/2], 20);\n## @end group\n## @end example\n##\n## @seealso{surf, ezsurfc, ezplot, ezmesh, ezmeshc, shading}\n## @end deftypefn\n\nfunction h = ezsurf (varargin)\n\n  [htmp, needusage] = __ezplot__ (\"surf\", varargin{:});\n\n  if (needusage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! f = @(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n%! ezsurf (f, [-3, 3]);\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! fx = @(s,t) cos (s) .* cos (t);\n%! fy = @(s,t) sin (s) .* cos (t);\n%! fz = @(s,t) sin (t);\n%! ezsurf (fx, fy, fz, [-pi,pi,-pi/2,pi/2], 20);\n%! axis equal;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! f = @(x,y) x.^2 + y.^2;\n%! subplot (1,2,1);\n%!  ezsurf (f, [-2,2]);\n%!  title ({\"x^2 + y^2\"; \"plotted over rectangular grid (default)\"});\n%! subplot (1,2,2);\n%!  ezsurf (f, [-2,2], \"circ\");\n%!  title ({\"x^2 + y^2\"; 'plotted over circular disk with \"circ\"'});\n"
  },
  {
    "path": "scripts/plot/draw/ezsurfc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ezsurfc (@var{f})\n## @deftypefnx {} {} ezsurfc (@var{fx}, @var{fy}, @var{fz})\n## @deftypefnx {} {} ezsurfc (@dots{}, @var{dom})\n## @deftypefnx {} {} ezsurfc (@dots{}, @var{n})\n## @deftypefnx {} {} ezsurfc (@dots{}, \"circ\")\n## @deftypefnx {} {} ezsurfc (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ezsurfc (@dots{})\n##\n## Plot the surface and contour lines defined by a function.\n##\n## @var{f} is a string, inline function, or function handle with two arguments\n## defining the function.  By default the plot is over the meshed domain\n## @code{-2*pi <= @var{x} | @var{y} <= 2*pi} with 60 points in each dimension.\n##\n## If three functions are passed, then plot the parametrically defined\n## function @code{[@var{fx}(@var{s}, @var{t}), @var{fy}(@var{s}, @var{t}),\n## @var{fz}(@var{s}, @var{t})]}.\n##\n## If @var{dom} is a two element vector, it represents the minimum and maximum\n## values of both @var{x} and @var{y}.  If @var{dom} is a four element vector,\n## then the minimum and maximum values are @code{[xmin xmax ymin ymax]}.\n##\n## @var{n} is a scalar defining the number of points to use in each dimension.\n##\n## If the argument @qcode{\"circ\"} is given, then the function is plotted over\n## a disk centered on the middle of the domain @var{dom}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a 2-element vector with a graphics\n## handle for the created surface plot and a second handle for the created\n## contour plot.\n##\n## Example:\n##\n## @example\n## @group\n## f = @@(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n## ezsurfc (f, [-3, 3]);\n## @end group\n## @end example\n##\n## @seealso{surfc, ezsurf, ezplot, ezmesh, ezmeshc, shading}\n## @end deftypefn\n\nfunction h = ezsurfc (varargin)\n\n  [htmp, needusage] = __ezplot__ (\"surfc\", varargin{:});\n\n  if (needusage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! f = @(x,y) sqrt (abs (x .* y)) ./ (1 + x.^2 + y.^2);\n%! ezsurfc (f, [-3, 3]);\n"
  },
  {
    "path": "scripts/plot/draw/feather.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} feather (@var{u}, @var{v})\n## @deftypefnx {} {} feather (@var{z})\n## @deftypefnx {} {} feather (@dots{}, @var{style})\n## @deftypefnx {} {} feather (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} feather (@dots{})\n##\n## Plot the @code{(@var{u}, @var{v})} components of a vector field emanating\n## from equidistant points on the x-axis.\n##\n## If a single complex argument @var{z} is given, then\n## @code{@var{u} = real (@var{z})} and @code{@var{v} = imag (@var{z})}.\n##\n## The style to use for the plot can be defined with a line style @var{style}\n## of the same format as the @code{plot} command.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of graphics handles to the\n## line objects representing the drawn vectors.\n##\n## @example\n## @group\n## phi = [0 : 15 : 360] * pi/180;\n## feather (sin (phi), cos (phi));\n## @end group\n## @end example\n##\n## @seealso{plot, quiver, compass}\n## @end deftypefn\n\nfunction h = feather (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"feather\", varargin{:});\n\n  if (nargin == 0 || nargin > 3)\n    print_usage ();\n  endif\n\n  if (nargin == 1 || (nargin == 2 && ! isnumeric (varargin{2})))\n    z = varargin{1}(:).';\n    u = real (z);\n    v = imag (z);\n    have_line_spec = (nargin == 2);\n  elseif (nargin >= 2 && isnumeric (varargin{2}))\n    ioff = 3;\n    u = varargin{1}(:).';\n    v = varargin{2}(:).';\n    have_line_spec = (nargin == 3);\n  else\n    print_usage ();\n  endif\n\n  arrowsize = 0.20;\n  line_spec = \"-b\";\n\n  if (have_line_spec)\n    arg = varargin{end};\n    if (! (ischar (arg) || iscellstr (arg)))\n      error (\"feather: invalid linestyle STYLE\");\n    endif\n    [~, valid] = __pltopt__ (\"feather\", arg, false);\n    if (! valid)\n      error (\"feather: invalid linestyle STYLE\");\n    endif\n    line_spec = arg;\n  endif\n\n  ## Matlab draws feather plots, with the arrow head as one continuous line,\n  ## and each arrow separately.  This is completely different from quiver and\n  ## quite ugly.\n  n = length (u);\n  xend = [1 : n] + u;\n  xtmp = [1 : n] + u .* (1 - arrowsize);\n  yend = v;\n  ytmp = v .* (1 - arrowsize);\n  x = [[1 : n]; xend; xtmp - v * arrowsize / 3; xend; ...\n       xtmp + v * arrowsize / 3];\n  y = [zeros(1, n); yend; ytmp + u * arrowsize / 3; yend; ...\n       ytmp - u * arrowsize / 3];\n\n  hax = newplot (hax);\n  htmp = plot (hax, x, y, line_spec, [1, n], [0, 0], line_spec);\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! phi = [0 : 15 : 360] * pi/180;\n%! feather (sin (phi), cos (phi));\n%! axis tight;\n%! title (\"feather plot\");\n\n## Test input validation\n%!error <Invalid call> feather ()\n%!error <Invalid call> feather (1,2,3,4)\n%!error feather (1, \"-r\", 2)\n%!error <invalid linestyle STYLE> feather (1, \"abc\")\n%!error <invalid linestyle STYLE> feather (1, {1})\n"
  },
  {
    "path": "scripts/plot/draw/fill.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} fill (@var{x}, @var{y}, @var{c})\n## @deftypefnx {} {} fill (@var{x1}, @var{y1}, @var{c1}, @var{x2}, @var{y2}, @var{c2})\n## @deftypefnx {} {} fill (@dots{}, @var{prop}, @var{val})\n## @deftypefnx {} {} fill (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} fill (@dots{})\n## Create one or more filled 2-D polygons.\n##\n## The inputs @var{x} and @var{y} are the coordinates of the polygon vertices.\n## If the inputs are matrices then the rows represent different vertices and\n## each column produces a different polygon.  @code{fill} will close any open\n## polygons before plotting.\n##\n## The input @var{c} determines the color of the polygon.  The simplest form\n## is a single color specification such as a @code{plot} format or an\n## RGB-triple.  In this case the polygon(s) will have one unique color.  If\n## @var{c} is a vector or matrix then the color data is first scaled using\n## @code{clim} and then indexed into the current colormap.  A vector will color\n## each polygon (a column from matrices @var{x} and @var{y}) with a single\n## computed color.  A matrix @var{c} of the same size as @var{x} and @var{y}\n## will compute the color of each vertex and then interpolate the face color\n## between the vertices.\n##\n## Multiple property/value pairs for the underlying patch object may be\n## specified, but they must appear in pairs.  The full list of properties is\n## documented at @ref{Patch Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of graphics handles to the\n## created patch objects.\n##\n## Example: red square\n##\n## @example\n## @group\n## vertices = [0 0\n##             1 0\n##             1 1\n##             0 1];\n## fill (vertices(:,1), vertices(:,2), \"r\");\n## axis ([-0.5 1.5, -0.5 1.5])\n## axis equal\n## @end group\n## @end example\n##\n## @seealso{patch, fill3, clim, colormap}\n## @end deftypefn\n\nfunction h = fill (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"fill\", varargin{:});\n\n  hlist = [];\n  iargs = __find_patches__ (varargin{:});\n\n  opts = {};\n  if (numel (varargin) > iargs(end) + 2)\n    opts = varargin(iargs(end)+3 : end);\n  endif\n\n  if (! all (cellfun (@(x) iscolorspec (x), varargin(iargs + 2))))\n    error (\"fill: invalid color specification C\");\n  endif\n\n  hax = newplot (hax);\n  old_nxtplt = get (hax, \"nextplot\");\n  if (! ishold (hax))\n    set (hax, \"box\", \"on\");\n  endif\n  unwind_protect\n    set (hax, \"nextplot\", \"add\");\n\n    for i = 1 : numel (iargs)\n      x = varargin{iargs(i)};\n      y = varargin{iargs(i) + 1};\n      cdata = varargin{iargs(i) + 2};\n\n      ## FIXME: Probably should validate that x, y, cdata are 2-D.\n\n      if (isrow (x))\n        x = x(:);\n      endif\n      if (isrow (y))\n        y = y(:);\n      endif\n\n      if (! size_equal (x, y))\n        if (iscolumn (x))\n          rx = rows (x);\n          [ry, cy] = size (y);\n          if (rx == ry)\n            x = repmat (x, [1, cy]);\n          elseif (rx == cy)\n            y = y.';\n            x = repmat (x, [1, ry]);\n          else\n            error (\"fill: vector X and matrix Y must have a length which matches along one dimension\");\n          endif\n        elseif (iscolumn (y))\n          ry = rows (y);\n          [rx, cx] = size (x);\n          if (ry == rx)\n            y = repmat (y, [1, cx]);\n          elseif (ry == cx)\n            x = x.';\n            y = repmat (y, [1, rx]);\n          else\n            error (\"fill: matrix X and vector Y must have a length which matches along one dimension\");\n          endif\n        else\n          error (\"fill: matrices X and Y must be the same size\");\n        endif\n      endif\n\n      ## Test for color specification as text ('r') or RGB triple.\n      if (ischar (cdata) ||\n          (all (size (cdata) == [1, 3]) && all (cdata >= 0 & cdata <= 1)))\n        one_color = true;\n      else\n        one_color = false;\n      endif\n\n      ## Manage cdata to ensure for loop below works\n      if (! one_color && isvector (cdata))\n        if (numel (cdata) == columns (x))\n          ## One color per polygon\n          cdata = cdata(:).';\n        elseif (numel (cdata) == rows (x))\n          ## Vertex colors.  Replicate cdata to match size of data.\n          cdata = repmat (cdata(:), [1, columns(x)]);\n        else\n          error (\"fill: invalid format for color data C\");\n        endif\n      endif\n\n      ## For Matlab compatibility, return 1 patch object for each column\n      for j = 1 : columns (x)\n        if (one_color)\n          htmp = __patch__ (hax, x(:,j), y(:,j), cdata, opts{:});\n        else\n          htmp = __patch__ (hax, x(:,j), y(:,j), cdata(:,j), opts{:});\n        endif\n        hlist(end+1, 1) = htmp;\n      endfor\n\n    endfor\n\n  unwind_protect_cleanup\n    if (! strcmp (old_nxtplt, \"add\"))\n      set (hax, \"nextplot\", old_nxtplt);\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    h = hlist;\n  endif\n\nendfunction\n\nfunction iargs = __find_patches__ (varargin)\n  iargs = 1:3:nargin;\n  optidx = find (! cellfun ('isnumeric', varargin(iargs)), 1);\n  iargs(optidx:end) = [];\nendfunction\n\nfunction retval = iscolorspec (arg)\n\n  retval = false;\n  if (ischar (arg))\n    persistent colors = {\"y\", \"yellow\", \"r\", \"red\", \"m\", \"magenta\", ...\n                         \"c\", \"cyan\", \"g\", \"green\", \"b\", \"blue\", ...\n                         \"w\", \"white\", \"k\", \"black\"};\n    if (any (strcmpi (arg, colors)))\n      retval = true;\n    endif\n  elseif (isnumeric (arg))\n    ## Assume any numeric argument is correctly formatted cdata.\n    ## Let patch worry about the multiple different input formats.\n    retval = true;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! t1 = (1/16:1/8:1) * 2*pi;\n%! t2 = ((1/16:1/8:1) + 1/32) * 2*pi;\n%! x1 = sin (t1) - 0.8;\n%! y1 = cos (t1);\n%! x2 = sin (t2) + 0.8;\n%! y2 = cos (t2);\n%! h = fill (x1,y1,\"r\", x2,y2,\"g\");\n%! title ({\"fill() function\"; \"cdata specified with string\"});\n\n%!demo\n%! clf;\n%! t1 = (1/16:1/8:1) * 2*pi;\n%! t2 = ((1/16:1/8:1) + 1/32) * 2*pi;\n%! x1 = sin (t1) - 0.8;\n%! y1 = cos (t1);\n%! x2 = sin (t2) + 0.8;\n%! y2 = cos (t2);\n%! h = fill (x1,y1,1, x2,y2,2);\n%! title ({\"fill() function\"; 'cdata = row vector produces FaceColor = \"flat\"'});\n\n%!demo\n%! clf;\n%! x = [0 0\n%!      1 0.5\n%!      1 0.5\n%!      0 0];\n%! y = [0 0\n%!      0 0\n%!      1 0.5\n%!      1 0.5];\n%! c = [1 2 3 4]';\n%! fill (x, y, [c c]);\n%! title ({\"fill() function\"; 'cdata = column vector produces FaceColor = \"interp\"'});\n"
  },
  {
    "path": "scripts/plot/draw/fill3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} fill3 (@var{x}, @var{y}, @var{z}, @var{c})\n## @deftypefnx {} {} fill3 (@var{x1}, @var{y1}, @var{z1}, @var{c1}, @var{x2}, @var{y2}, @var{z2}, @var{c2})\n## @deftypefnx {} {} fill3 (@dots{}, @var{prop}, @var{val})\n## @deftypefnx {} {} fill3 (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} fill3 (@dots{})\n## Create one or more filled 3-D polygons.\n##\n## The inputs @var{x}, @var{y}, and @var{z} are the coordinates of the polygon\n## vertices.  If the inputs are matrices then the rows represent different\n## vertices and each column produces a different polygon.  @code{fill3} will\n## close any open polygons before plotting.\n##\n## The input @var{c} determines the color of the polygon.  The simplest form\n## is a single color specification such as a @code{plot} format or an\n## RGB-triple.  In this case the polygon(s) will have one unique color.  If\n## @var{c} is a vector or matrix then the color data is first scaled using\n## @code{clim} and then indexed into the current colormap.  A vector will color\n## each polygon (a column from matrices @var{x}, @var{y}, and @var{z}) with a\n## single computed color.  A matrix @var{c} of the same size as @var{x},\n## @var{y}, and @var{z} will compute the color of each vertex and then\n## interpolate the face color between the vertices.\n##\n## Multiple property/value pairs for the underlying patch object may be\n## specified, but they must appear in pairs.  The full list of properties is\n## documented at @ref{Patch Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of graphics handles to\n## the created patch objects.\n##\n## Example: oblique red rectangle\n##\n## @example\n## @group\n## vertices = [0 0 0\n##             1 1 0\n##             1 1 1\n##             0 0 1];\n## fill3 (vertices(:,1), vertices(:,2), vertices(:,3), \"r\");\n## axis ([-0.5 1.5, -0.5 1.5, -0.5 1.5]);\n## axis equal\n## grid on\n## view (-80, 25);\n## @end group\n## @end example\n##\n## @seealso{patch, fill, clim, colormap}\n## @end deftypefn\n\nfunction h = fill3 (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"fill3\", varargin{:});\n\n  hlist = [];\n  iargs = __find_patches__ (varargin{:});\n\n  opts = {};\n  if (numel (varargin) > iargs(end) + 3)\n    opts = varargin(iargs(end)+4 : end);\n  endif\n\n  if (! all (cellfun (@(x) iscolorspec (x), varargin(iargs + 3))))\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n  old_nxtplt = get (hax, \"nextplot\");\n  if (! ishold (hax))\n    set (hax, \"box\", \"off\", \"view\", [-37.5, 30]);\n  endif\n  unwind_protect\n    set (hax, \"nextplot\", \"add\");\n\n    for i = 1 : numel (iargs)\n      x = varargin{iargs(i)};\n      y = varargin{iargs(i) + 1};\n      z = varargin{iargs(i) + 2};\n      cdata = varargin{iargs(i) + 3};\n\n      ## FIXME: Probably should validate that x, y, z, cdata are 2-D.\n      if (isrow (x))\n        x = x(:);\n      endif\n      if (isrow (y))\n        y = y(:);\n      endif\n      if (isrow (z))\n        z = z(:);\n      endif\n\n      ## Stupidly complex code to orient vectors and matrices if they\n      ## have a dimension in common.  Required for Matlab compatibility.\n      while (! size_equal (x, y, z))\n        if (iscolumn (x))\n          if (! isvector (y))\n            rx = rows (x);\n            [ry, cy] = size (y);\n            if (rx == ry)\n              x = repmat (x, [1, cy]);\n            elseif (rx == cy)\n              y = y.';\n              x = repmat (x, [1, ry]);\n            else\n              error (\"fill: vector X and matrix Y must have a length which matches along one dimension\");\n            endif\n          elseif (! isvector (z))\n            rx = rows (x);\n            [rz, cz] = size (z);\n            if (rx == rz)\n              x = repmat (x, [1, cz]);\n            elseif (rx == cz)\n              z = z.';\n              x = repmat (x, [1, rz]);\n            else\n              error (\"fill: vector X and matrix Z must have a length which matches along one dimension\");\n            endif\n          endif\n\n          continue;  # X vector expanded, restart size_equal loop\n\n        elseif (iscolumn (y))\n          ry = rows (y); \n          [rx, cx] = size (x);\n          if (ry != rx)\n            error (\"fill: matrix X and vector Y must have a length which matches along one dimension\");\n          endif\n          y = repmat (y, [1, cx]);\n\n          continue;  # Y vector expanded, restart size_equal loop\n\n        elseif (iscolumn (z))\n          rz = rows (z); \n          [rx, cx] = size (x);\n          if (rz != rx)\n            error (\"fill: matrix X and vector Z must have a length which matches along one dimension\");\n          endif\n          z = repmat (z, [1, cx]);\n\n          continue;  # Z vector expanded, restart size_equal loop\n\n        else\n          ## All vectors expanded, but matrices still mismatch\n          error (\"fill: incompatible sizes of X, Y, and Z\");\n        endif\n\n      endwhile\n\n      ## Test for color specification as text ('r') or RGB triple.\n      if (ischar (cdata) ||\n          (all (size (cdata) == [1, 3]) && all (cdata >= 0 & cdata <= 1)))\n        one_color = true;\n      else\n        one_color = false;\n      endif\n\n      ## Manage cdata to ensure for loop below works\n      if (! one_color && isvector (cdata))\n        if (numel (cdata) == columns (x))\n          ## One color per polygon\n          cdata = cdata(:).';\n        elseif (numel (cdata) == rows (x))\n          ## Vertex colors.  Replicate cdata to match size of data.\n          cdata = repmat (cdata(:), [1, columns(x)]);\n        else\n          error (\"fill: invalid format for color data C\");\n        endif\n      endif\n\n      ## For Matlab compatibility, return 1 patch object for each column\n      for j = 1 : columns (x)\n        if (one_color)\n          htmp = __patch__ (hax, x(:,j), y(:,j), z(:,j), cdata, opts{:});\n        else\n          htmp = __patch__ (hax, x(:,j), y(:,j), z(:,j), cdata(:,j), opts{:});\n        endif\n        hlist(end+1, 1) = htmp;\n      endfor\n    endfor\n\n  unwind_protect_cleanup\n    if (! strcmp (old_nxtplt, \"add\"))\n      set (hax, \"nextplot\", old_nxtplt);\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    h = hlist;\n  endif\n\nendfunction\n\nfunction iargs = __find_patches__ (varargin)\n  iargs = 1:4:nargin;\n  optidx = find (! cellfun ('isnumeric', varargin(iargs)), 1);\n  iargs(optidx:end) = [];\nendfunction\n\nfunction retval = iscolorspec (arg)\n\n  retval = false;\n  if (ischar (arg))\n    persistent colors = {\"y\", \"yellow\", \"r\", \"red\", \"m\", \"magenta\", ...\n                         \"c\", \"cyan\", \"g\", \"green\", \"b\", \"blue\", ...\n                         \"w\", \"white\", \"k\", \"black\"};\n    if (any (strcmpi (arg, colors)))\n      retval = true;\n    endif\n  elseif (isnumeric (arg))\n    ## Assume any numeric argument is correctly formatted cdata.\n    ## Let patch worry about the multiple different input formats.\n    retval = true;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! t1 = (1/16:1/8:1) * 2*pi;\n%! t2 = ((1/16:1/8:1) + 1/32) * 2*pi;\n%! x1 = sin (t1) - 0.8;\n%! y1 = cos (t1);\n%! z1 = sin (t1);\n%! x2 = sin (t2) + 0.8;\n%! y2 = cos (t2);\n%! z2 = sin (t2);\n%! h = fill3 (x1,y1,z1,\"r\", x2,y2,z2,\"g\");\n%! title ({\"fill3() function\"; \"cdata specified with string\"});\n%! grid (\"on\");\n\n%!demo\n%! clf;\n%! t1 = (1/16:1/8:1) * 2*pi;\n%! t2 = ((1/16:1/8:1) + 1/32) * 2*pi;\n%! x1 = sin (t1) - 0.8;\n%! y1 = cos (t1);\n%! z1 = sin (t1);\n%! x2 = sin (t2) + 0.8;\n%! y2 = cos (t2);\n%! z2 = sin (t2);\n%! h = fill3 (x1,y1,z1,1, x2,y2,z2,2);\n%! title ({\"fill3() function\"; 'cdata = row vector produces FaceColor = \"flat\"'});\n%! grid (\"on\");\n\n%!demo\n%! clf;\n%! x = [0 0\n%!      1 0.5\n%!      1 0.5\n%!      0 0];\n%! y = [0 0\n%!      0 0\n%!      1 0.5\n%!      1 0.5];\n%! z = y;\n%! z(:,2) += 1e-4;\n%! c = [1 2 3 4]';\n%! fill3 (x, y, z, [c c]);\n%! title ({\"fill3() function\"; 'cdata = column vector produces FaceColor = \"interp\"'});\n%! grid (\"on\");\n"
  },
  {
    "path": "scripts/plot/draw/fplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} fplot (@var{fcn})\n## @deftypefnx {} {} fplot (@var{fcn}, @var{limits})\n## @deftypefnx {} {} fplot (@dots{}, @var{tol})\n## @deftypefnx {} {} fplot (@dots{}, @var{n})\n## @deftypefnx {} {} fplot (@dots{}, @var{fmt})\n## @deftypefnx {} {} fplot (@dots{}, @var{property}, @var{value}, @dots{})\n## @deftypefnx {} {} fplot (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{y}] =} fplot (@dots{})\n## Plot a function @var{fcn} within the range defined by @var{limits}.\n##\n## @var{fcn} is a function handle, inline function, or string containing the\n## name of the function to evaluate.\n##\n## The limits of the plot are of the form @w{@code{[@var{xlo}, @var{xhi}]}}@ or\n## @w{@code{[@var{xlo}, @var{xhi}, @var{ylo}, @var{yhi}]}}.  If no limits\n## are specified the default is @code{[-5, 5]}.\n##\n## The next three arguments are all optional and any number of them may be\n## given in any order.\n##\n## @var{tol} is the relative tolerance to use for the plot and defaults\n## to 2e-3 (.2%).\n##\n## @var{n} is the minimum number of points to use.  When @var{n} is specified,\n## the maximum stepsize will be @code{(@var{xhi} - @var{xlo}) / @var{n}}.  More\n## than @var{n} points may still be used in order to meet the relative\n## tolerance requirement.\n##\n## The @var{fmt} argument specifies the linestyle to be used by the plot\n## command.\n##\n## Multiple property-value pairs may also be specified, but they must appear\n## in pairs.  These arguments are applied to the line objects drawn by\n## @code{plot}.\n##\n## The full list of line properties is documented at @ref{Line Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## With no output arguments, the results are immediately plotted.  With two\n## output arguments, the 2-D plot data is returned.  The data can subsequently\n## be plotted manually with @code{plot (@var{x}, @var{y})}.\n##\n## Example:\n##\n## @example\n## @group\n## fplot (@@cos, [0, 2*pi])\n## fplot (\"[cos(x), sin(x)]\", [0, 2*pi])\n## @end group\n## @end example\n##\n## Programming Notes:\n##\n## @code{fplot} works best with continuous functions.  Functions with\n## discontinuities are unlikely to plot well.  This restriction may be removed\n## in the future.\n##\n## @code{fplot} performance is better when the function accepts and returns a\n## vector argument.  Consider this when writing user-defined functions and use\n## element-by-element operators such as @code{.*}, @code{./}, etc.\n##\n## @seealso{ezplot, plot}\n## @end deftypefn\n\nfunction [X, Y] = fplot (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"fplot\", varargin{:});\n\n  if (nargin < 1 || nargin > 5)\n    print_usage ();\n  endif\n\n  fcn = varargin{1};\n  if (isa (fcn, \"inline\"))\n    ## Don't warn about intentional use of inline functions (Bug #62682)\n    warning (\"off\", \"Octave:legacy-function\", \"local\");\n    fcn = vectorize (inline (fcn));\n    nam = formula (fcn);\n  elseif (is_function_handle (fcn))\n    nam = func2str (fcn);\n  elseif (all (isalnum (fcn)))\n    nam = fcn;\n  elseif (ischar (fcn))\n    ## Don't warn about intentional use of inline functions (Bug #62682)\n    warning (\"off\", \"Octave:legacy-function\", \"local\");\n    fcn = vectorize (inline (fcn));\n    nam = formula (fcn);\n  else\n    error (\"fplot: FCN must be a function handle, inline function, or string\");\n  endif\n\n  if (nargin > 1 && isnumeric (varargin{2}))\n    limits = varargin{2};\n    if (iscomplex (limits) || (numel (limits) != 2 && numel (limits) != 4))\n      error (\"fplot: LIMITS must be a real vector with 2 or 4 elements\");\n    endif\n    i = 3;\n  else\n    limits = [-5, 5];\n    i = 2;\n  endif\n\n  n = 5;\n  tol = 2e-3;\n  fmt = {};\n  prop_vals = {};\n  while (i <= numel (varargin))\n    arg = varargin{i};\n    if (ischar (arg))\n      [~, valid_fmt] = __pltopt__ (\"fplot\", arg, false);\n      if (valid_fmt)\n        fmt(end+1) = arg;\n      else\n        if (i == numel (varargin))\n          error (\"fplot: bad input in position %d\", i);\n        endif\n        prop_vals(end+(1:2)) = varargin([i, i+1]);\n        i++;  # Skip PROPERTY.\n      endif\n    elseif (isnumeric (arg) && isscalar (arg) && arg > 0)\n      if (arg == fix (arg))\n        n = arg;\n      else\n        tol = arg;\n      endif\n    else\n      error (\"fplot: bad input in position %d\", i);\n    endif\n    i++;\n  endwhile\n\n  if (n != 5)\n    ## n was specified\n    x0 = linspace (limits(1), limits(2), n/2 + 1)';\n  else\n    x0 = linspace (limits(1), limits(2), 5)';\n    n = 8;\n  endif\n\n  try\n    y0 = feval (fcn, x0);\n    if (isscalar (y0))\n      warning (\"fplot: FCN is not a vectorized function which reduces performance\");\n      fcn = @(x) arrayfun (fcn, x);  # Create a new fcn that accepts vectors\n      y0 = feval (fcn, x0);\n    endif\n  catch\n    ## feval failed, maybe it is because the function is not vectorized?\n    fcn = @(x) arrayfun (fcn, x);  # Create a new fcn that accepts vectors\n    y0 = feval (fcn, x0);\n    warning (\"fplot: FCN is not a vectorized function which reduces performance\");\n  end_try_catch\n\n  x = linspace (limits(1), limits(2), n)';\n  y = feval (fcn, x);\n\n  if (rows (x0) == rows (y0))\n    fcn_transpose = false;\n  elseif (rows (x0) == columns (y0))\n    fcn_transpose = true;\n    y0 = y0.';\n    y = y.';\n  else\n    error (\"fplot: invalid function FCN (# of outputs not equal to inputs)\");\n  endif\n\n  err0 = Inf;\n\n  ## FIXME: This algorithm should really use adaptive scaling as\n  ##        the numerical quadrature algorithms do so that extra points are\n  ##        used where they are needed and not spread evenly over the entire\n  ##        x-range.  Try any function with a discontinuity, such as\n  ##        fplot (@tan, [-2, 2]) or fplot (\"1./x\", [-3, 2]), to see the\n  ##        problems with the current solution.\n\n  while (n < 2^18)    # Something is wrong if we need more than 250K points\n    yi = interp1 (x0, y0, x, \"linear\");\n    ## relative error calculation using average of [yi,y] as reference\n    ## since neither estimate is known a priori to be better than the other.\n    err = 0.5 * max (abs ((yi - y) ./ (yi + y + eps))(:));\n    if (err < tol || abs (err - err0) < tol/2)\n      ## Either relative tolerance has been met OR\n      ## algorithm has stopped making any reasonable progress per iteration.\n      break;\n    endif\n    x0 = x;\n    y0 = y;\n    err0 = err;\n    n = 2 * (n - 1) + 1;\n    x = linspace (limits(1), limits(2), n)';\n    y = feval (fcn, x);\n    if (fcn_transpose)\n      y = y.';\n    endif\n  endwhile\n\n  if (nargout == 2)\n    X = x;\n    Y = y;\n  else\n    if (isempty (hax))\n      hax = gca ();\n    endif\n    hl = plot (hax, x, y, fmt{:});\n    if (isempty (get (hl(1), \"displayname\")))\n      ## Set displayname for legend if FMT did not contain a name.\n      if (isvector (y))\n        set (hl, \"displayname\", nam);\n      else\n        for i = 1:columns (y)\n          nams{i} = sprintf (\"%s(:,%i)\", nam, i);\n        endfor\n        set (hl, {\"displayname\"}, nams(:));\n      endif\n    endif\n    ## Properties passed as input arguments override other properties.\n    if (! isempty (prop_vals))\n      set (hl, prop_vals{:});\n    endif\n    axis (hax, limits);\n    legend (hax, \"show\");\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! fplot (@cos, [0, 2*pi]);\n%! title (\"fplot() single function\");\n\n%!demo\n%! clf;\n%! fplot (\"[cos(x), sin(x)]\", [0, 2*pi]);\n%! title (\"fplot() multiple functions\");\n\n%!demo\n%! clf;\n%! fh = @(x) sin (pi*x) ./ (pi*x);\n%! fplot (fh, [-5, 5]);\n%! title (\"fplot() sinc function (possible division by 0, near 0)\");\n\n%!test\n%! ## Multi-valued function\n%! [x, y] = fplot (\"[cos(x), sin(x)]\", [0, 2*pi]);\n%! assert (columns (y) == 2);\n%! assert (rows (x) == rows (y));\n%! assert (y, [cos(x), sin(x)], -2e-3);\n\n%!test\n%! ## Function requiring transpose\n%! fcn = @(x) 2 * x(:).';\n%! [x, y] = fplot (fcn, [-1, 1]);\n%! assert (columns (y) == 1);\n%! assert (rows (x) == rows (y));\n%! assert (y, 2*x);\n\n%!test\n%! ## Constant value function\n%! fcn = @(x) 0;\n%! [x, y] = fplot (fcn, [-1, 1]);\n%! assert (columns (y) == 1);\n%! assert (rows (x) == rows (y));\n%! assert (y, repmat ([0], size (x)));\n\n%!test <*59274>\n%! ## Manual displayname overrides automatic legend entry\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   fplot (@sin, [0, 3], \"displayname\", \"mysin\");\n%!   hl = legend ();\n%!   assert (get (hl, \"string\"), {\"mysin\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*59274>\n%! ## displayname in format string overrides automatic legend entry\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   fplot (@sin, [0, 3], \"+;mysin;\");\n%!   hl = legend ();\n%!   assert (get (hl, \"string\"), {\"mysin\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> fplot ()\n%!error <Invalid call> fplot (1,2,3,4,5,6)\n%!error <FCN must be a function handle> fplot (1, [0 1])\n%!error <LIMITS must be a real vector> fplot (@cos, [i, 2*i])\n%!error <LIMITS must be a real vector with 2 or 4> fplot (@cos, [1])\n%!error <LIMITS must be a real vector with 2 or 4> fplot (@cos, [1 2 3])\n%!error <bad input in position 2> fplot (@cos, \"linewidth\")\n%!error <bad input in position 3> fplot (@cos, [-1,1], {1})\n%!warning <FCN is not a vectorized function>\n%! fcn = @(x) 0;\n%! [x,y] = fplot (fcn, [-1,1]);\n%!error <invalid function FCN>\n%! fcn = @(x) [x;x];\n%! fplot (fcn, [-1,1]);\n"
  },
  {
    "path": "scripts/plot/draw/hist.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} hist (@var{y})\n## @deftypefnx {} {} hist (@var{y}, @var{nbins})\n## @deftypefnx {} {} hist (@var{y}, @var{x})\n## @deftypefnx {} {} hist (@var{y}, @var{x}, @var{norm})\n## @deftypefnx {} {} hist (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} hist (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{nn}, @var{xx}] =} hist (@dots{})\n## Produce histogram counts or plots.\n##\n## With one vector input argument, @var{y}, plot a histogram of the values\n## with 10 bins.  The range of the histogram bins is determined by the\n## range of the data (difference between maximum and minimum value in @var{y}).\n## Extreme values are lumped into the first and last bins.  If @var{y} is a\n## matrix then plot a histogram where each bin contains one bar per input\n## column of @var{y}.\n##\n## If the optional second argument is a scalar, @var{nbins}, it defines the\n## number of bins.\n##\n## If the optional second argument is a vector, @var{x}, it defines the centers\n## of the bins.  The width of the bins is determined from the adjacent values\n## in the vector.  The total number of bins is @code{numel (@var{x})}.\n##\n## If a third argument @var{norm} is provided, the histogram is normalized.\n## In case @var{norm} is a positive scalar, the resulting bars are normalized\n## to @var{norm}.  If @var{norm} is a vector of positive scalars of length\n## @code{columns (@var{y})}, then the resulting bar of @code{@var{y}(:,i)} is\n## normalized to @code{@var{norm}(i)}.\n##\n## @example\n## @group\n## [nn, xx] = hist (rand (10, 3), 5, [1 2 3]);\n## sum (nn, 1)\n## @xresult{} ans =\n##       1   2   3\n## @end group\n## @end example\n##\n## The histogram's appearance may be modified by specifying property/value\n## pairs to the underlying patch object.  For example, the face and edge color\n## may be modified:\n##\n## @example\n## @group\n## hist (randn (1, 100), 25, \"facecolor\", \"r\", \"edgecolor\", \"b\");\n## @end group\n## @end example\n##\n## @noindent\n## The full list of patch properties is documented at @ref{Patch Properties}.\n## property.  If not specified, the default colors for the histogram are taken\n## from the @qcode{\"Colormap\"} property of the axes or figure.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## If an output is requested then no plot is made.  Instead, return the values\n## @var{nn} (numbers of elements) and @var{xx} (bin centers) such that\n## @code{bar (@var{xx}, @var{nn})} will plot the histogram.  If @var{y} is a\n## vector, @var{nn} and @var{xx} will be row vectors.  If @var{y} is an array,\n## @var{nn} will be a 2-D array with one column of element counts for each\n## column in @var{y}, and @var{xx} will be a column vector of bin centers.\n##\n## @seealso{histc, bar, pie, rose}\n## @end deftypefn\n\nfunction [nn, xx] = hist (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"hist\", varargin{:});\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Process Y argument\n  iarg = 1;\n  y = varargin{iarg++};\n\n  if (! isreal (y))\n    error (\"hist: Y must be real-valued\");\n  endif\n\n  arg_is_vector = isvector (y);\n  if (arg_is_vector)\n    y = y(:);\n  endif\n\n  yfinite = y(isfinite (y))(:);\n  max_val = max (yfinite);\n  min_val = min (yfinite);\n  ## Do not convert if input is of class single (or if already is double).\n  if (! isfloat (y))\n    max_val = double (max_val);\n    min_val = double (min_val);\n  endif\n\n  ## Equidistant entries allow much more efficient algorithms.\n  equal_bin_spacing = true;\n\n  ## Process possible second argument\n  if (nargin == 1 || ischar (varargin{iarg}))\n    n = 10;\n    ## Use integer range values and perform division last to preserve\n    ## accuracy.  If max - min is less than 20*eps, treat as if min = max to\n    ## avoid bug #65714 error.\n    if (min_val != max_val && diff ([min_val, max_val]) > 20 * eps)\n      x = 1:2:2*n;\n      x = ((max_val - min_val) * x + 2*n*min_val) / (2*n);\n    else\n      x = (-floor ((n-1)/2):ceil ((n-1)/2)) + min_val;\n    endif\n    x = x.';  # Convert to matrix\n  else\n    ## Parse bin specification argument\n    x = varargin{iarg++};\n    if (! isreal (x))\n      error (\"hist: bin specification must be a numeric scalar or vector\");\n    endif\n\n    ## Convert integer types or a single specification of N bins to double\n    if (! isfloat (x) || isscalar (x))\n      x = double (x);\n    endif\n\n    if (isscalar (x))\n      n = fix (x);\n      if (n <= 0)\n        error (\"hist: number of bins NBINS must be positive\");\n      endif\n      ## Use integer range values and perform division last to preserve\n      ## accuracy.  If max - min is less than 20*eps, treat as if min = max\n      ## to avoid bug #65714 error.\n      if (min_val != max_val && diff ([min_val, max_val]) > 20 * eps)\n        x = 1:2:2*n;\n        x = ((max_val - min_val) * x + 2*n*min_val) / (2*n);\n      else\n        x = (-floor ((n-1)/2):ceil ((n-1)/2)) + min_val;\n      endif\n      x = x.';  # Convert to matrix\n    elseif (isvector (x))\n      equal_bin_spacing = ! isempty (strfind (typeinfo (x), \"range\"));\n      if (! equal_bin_spacing)\n        diffs = diff (x);\n        if (! any (abs ((diffs - diffs(1))) > eps (max (abs (x)))))\n          equal_bin_spacing = true;\n        endif\n      endif\n      x = x(:);\n      if (! issorted (x))\n        warning (\"hist: bin values X not sorted on input\");\n        x = sort (x);\n      endif\n    else\n      error (\"hist: bin specification must be a scalar or vector\");\n    endif\n  endif\n\n  ## Check for third argument (normalization)\n  norm = false;\n  if (nargin > 2 && ! ischar (varargin{iarg}))\n    norm = varargin{iarg++};\n    if (! isnumeric (norm) || ! all (norm > 0))\n      error (\"hist: NORM must be a numeric constant > 0\");\n    endif\n    if (! isvector (norm) ...\n        || ! (length (norm) == 1 || length (norm) == columns (y)))\n      error (\"hist: NORM must be scalar or vector of length 'columns (Y)'\");\n    endif\n    norm = norm (:).';  # Ensure vector orientation.\n  endif\n\n  ## Flatten y from N-D to 2-D array\n  if (ndims (y) > 2)\n    y = y(:,:);\n  endif\n\n  ## Perform histogram calculation\n  cutoff = (x(1:end-1,:) + x(2:end,:)) / 2;\n\n  n = rows (x);\n  y_nc = columns (y);\n\n  if (n < 11 * (1 + (! equal_bin_spacing)))\n    ## The following algorithm works fastest for small n.\n    nanidx = isnan (y);\n    chist = zeros (n+1, y_nc);\n    for i = 1:n-1\n      chist(i+1,:) = sum (y <= cutoff(i));\n    endfor\n    chist(n+1,:) = sum (! nanidx);\n\n    freq = diff (chist);\n  else\n    ## Lookup is more efficient if y is sorted, but sorting costs.\n    if (! equal_bin_spacing && n > sqrt (rows (y) * 1e4))\n      y = sort (y);\n    endif\n\n    nanidx = isnan (y);\n    y(nanidx) = 0;\n    freq = zeros (n, y_nc);\n    if (equal_bin_spacing)\n      if (n < 3)\n        d = 1;\n      else\n        d = (x(end) - x(1)) / (length (x) - 1);\n      endif\n      cutlen = length (cutoff);\n      for j = 1:y_nc\n        freq(:,j) = accumarray (1 + max (0, min (cutlen, ceil ((double (y(:,j))\n                                                         - cutoff(1)) / d))),\n                                double (! nanidx(:,j)),\n                                [n, 1]);\n      endfor\n    else\n      for j = 1:y_nc\n        i = lookup (cutoff, y(:,j));\n        i = 1 + i - (cutoff(max (i, 1)) == y(:,j));\n        freq(:,j) = accumarray (i, double (! nanidx(:,j)), [n, 1]);\n      endfor\n    endif\n  endif\n\n  if (norm)\n    ## Normalize the histogram\n    freq .*= norm ./ sum (! nanidx);\n  endif\n\n  if (nargout == 0)\n    if (isempty (hax))\n      hax = gca ();\n    endif\n    bar (hax, x, freq, \"hist\", varargin{iarg:end});\n  else\n    if (arg_is_vector)\n      ## Matlab compatibility requires a row vector return\n      nn = freq.';\n      xx = x.';\n    else\n      nn = freq;\n      xx = x;\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! [nn,xx] = hist ([1:4], 3);\n%! assert (xx, [1.5,2.5,3.5]);\n%! assert (nn, [2,1,1]);\n%!test\n%! [nn,xx] = hist ([1:4]', 3);\n%! assert (xx, [1.5,2.5,3.5]);\n%! assert (nn, [2,1,1]);\n%!test\n%! [nn,xx] = hist ([1 1 1 NaN NaN NaN 2 2 3], [1, 2, 3]);\n%! assert (xx, [1,2,3]);\n%! assert (nn, [3,2,1]);\n%!test\n%! [nn,xx] = hist ([1 1 1 NaN NaN NaN 2 2 3], [1, 2, 3], 6);\n%! assert (xx, [1,2,3]);\n%! assert (nn, [3,2,1]);\n%!test  # Multiple columns\n%! [nn,xx] = hist ([[1:4]', [1:4]'], 3);\n%! assert (xx, [1.5;2.5;3.5]);\n%! assert (nn, [[2,1,1]', [2,1,1]']);\n%!test\n%! for n = [10, 30, 100, 1000]\n%!   assert (sum (hist ([1:n], n)), n);\n%!   assert (sum (hist ([1:n], [2:n-1])), n);\n%!   assert (sum (hist ([1:n], [1:n])), n);\n%!   assert (sum (hist ([1:n], 29)), n);\n%!   assert (sum (hist ([1:n], 30)), n);\n%! endfor\n%!assert (hist (1,1), 1)\n%!test <*54326> # All values identical\n%! [nn,xx] = hist (ones (1,5), 3);\n%! assert (nn, [0,5,0]);\n%! assert (xx, [0,1,2]);\n%!assert (size (hist (randn (750,240), 200)), [200, 240])\n\n## Test normalization\n%!assert <*42394> (isempty (hist (rand (10,2), 0:5, 1)), false)\n%!assert <*42394> (isempty (hist (rand (10,2), 0:5, [1 1])), false)\n%!test <*60783>\n%! [nn, xx] = hist (reshape (1:30, 10, 3), 5, 1);\n%! assert (sum (nn, 1), [1 1 1]);\n%! [nn, xx] = hist (reshape (1:30, 10, 3), 5, [1 2 3]);\n%! assert (sum (nn, 1), [1 2 3]);\n%! [nn, xx] = hist (reshape (1:30, 10, 3), 5, [1 2 3]');\n%! assert (sum (nn, 1), [1 2 3]);\n\n%!test <*47707>\n%! y = [1  9  2  2  9  3  8  9  1  7  1  1  3  2  4  4  8  2  1  9  4  1 ...\n%!      2  3  1  1  6  5  5  3  9  9  1  1  8  7  7  2  4  1];\n%! [n, x] = hist (y, 10);\n%! [nn, xx] = hist (uint8 (y), 10);\n%! assert (nn, n);\n%! assert (xx, x);\n%!\n%! ## test again with N > 26 because there's a special case for it\n%! [n, x] = hist (y, 30);\n%! [nn, xx] = hist (uint8 (y), 30);\n%! assert (nn, n);\n%! assert (xx, x);\n\n## Test logical input\n%!test\n%! y = [0  1  0  0  1  0  1  1  0  1  0  0  0  0  0  0  1  0];\n%! [n, x] = hist (y, 10);\n%! [nn, xx] = hist (logical (y), 10);\n%! assert (nn, n);\n%! assert (xx, x);\n%!\n%! ## test again with N > 26 because there's a special case for it\n%! [n, x] = hist (y, 30);\n%! [nn, xx] = hist (logical (y), 30);\n%! assert (nn, n);\n%! assert (xx, x);\n\n## Second output argument must be of class single if data is class single.\n%!assert (class (nthargout (2, @hist, rand (10, 1, \"single\"))), \"single\")\n\n## Handle second argument correctly, even when it's class integer\n%!test\n%! y = [2.4, 2.5, 2.6, 5.4, 5.5, 5.6];\n%! n = [2, 3, 1];\n%! x = [1, 4, 7];\n%! [nn, xx] = hist (y, uint8 ([1 4 7]));\n%! assert (nn, n);\n%! assert (xx, x);\n\n## Test bin centers\n%!test\n%! y = [2.4, 2.5, 2.6, 5.4, 5.5, 5.6];\n%! s = (5.6 - 2.4) / 6;\n%! x = [2.4+s, 4.0, 5.6-s];\n%! n = [3, 0, 3];\n%!\n%! [nn, xx] = hist (y, 3);\n%! assert (nn, n);\n%! assert (xx, x, 2*eps);\n%!\n%! [nn, xx] = hist (y, uint8 (3));\n%! assert (nn, n);\n%! assert (xx, x, 2*eps);\n%!\n%! [nn, xx] = hist (y, single (3));\n%! assert (nn, n);\n%! assert (xx, single (x), 2*eps (\"single\"));\n\n%!test <*53199>\n%! a = [  1,  2,  3,  4, 0;\n%!        5,  4,  6,  7, 8;\n%!        9, 12, 11, 10, 0;\n%!       13, 16, 15, 14, 0;\n%!       17, 20, 19, 18, 0;\n%!       21, 22, 23,  2, 0;\n%!       24, 27, 26, 25, 0;\n%!       28, 31, 30, 29, 0;\n%!       32, 35, 34, 33, 0;\n%!       36, 39, 38, 37, 0;\n%!       40, 43, 42, 41, 0;\n%!       44, 47, 46, 45, 0;\n%!       48, 51, 50, 49, 0;\n%!       52, 55, 54, 53, 0];\n%! n = max (a(:));\n%! [cnt1, ctr1] = hist(a(:), 1:n);\n%! [cnt2, ctr2] = hist(a(:), n);\n%! assert (cnt1, cnt2);\n%! assert (ctr1, 1:n);\n%! assert (ctr2, 0.5:n);\n\n## Test Infinite values and calculation of bins\n%!test\n%! y = [-Inf, NaN, 10, Inf, 0];\n%! [nn, xx] = hist (y);\n%! assert (nn, [2 0 0 0 0 0 0 0 0 2]);\n%! assert (xx, 0.5:10);\n\n## Test return class of second output\n%!test <*56465>\n%! [nn, xx] = hist (double (1:10), single (7));\n%! assert (isa (xx, \"double\"));\n%! [nn, xx] = hist (single (1:10), double (7));\n%! assert (isa (xx, \"single\"));\n%! [nn, xx] = hist (single (1:10), double ([1, 5, 10]));\n%! assert (isa (xx, \"double\"));\n%! [nn, xx] = hist (double (1:10), single ([1, 5, 10]));\n%! assert (isa (xx, \"single\"));\n\n## Test N-D arrays produce the same result as 2-D arrays\n%!test <*65478>  # Small n\n%! a = magic (4);\n%! b = permute (a, [1, 3, 2]);\n%! [na, xa] = hist (a);\n%! [nb, xb] = hist (b);\n%! assert ({na, xa}, {nb, xb});\n\n%!test <*65478>  # Large n\n%! a = magic (4);\n%! b = permute (a, [1, 3, 2]);\n%! [na, xa] = hist (a, 30);\n%! [nb, xb] = hist (b, 30);\n%! assert ({na, xa}, {nb, xb});\n\n%!test <*65714> # Avoid error if diff(y) is very small.\n%! a = [1, 1+eps, 1+ 15*eps];\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hist (hax, a);\n%!   hp = get (hax, \"children\");\n%!   assert (max (get (hp, \"ydata\")(:)), 3);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test <*65714> # Avoid error if diff(y) is very small, with specified X.\n%! a = [1, 1+eps, 1+ 15*eps];\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hist (hax, a, 5);\n%!   hp = get (hax, \"children\");\n%!   assert (max (get (hp, \"ydata\")(:)), 3);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n\n## Test input validation\n%!error <Invalid call> hist ()\n%!error <Y must be real-valued> hist (2+i)\n%!error <bin specification must be a numeric> hist (1, {0,1,2})\n%!error <number of bins NBINS must be positive> hist (1, 0)\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   fail (\"hist (hax, 1, [2 1 0])\", \"warning\", \"bin values X not sorted\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n%!error <bin specification must be a scalar or vector> hist (1, ones (2,2))\n%!error <NORM must be a numeric constant> hist (1,1, {1})\n%!error <NORM must be a numeric constant . 0> hist (1,1, -1)\n%!error <NORM must be scalar or vector> hist (1,1, ones (4))\n"
  },
  {
    "path": "scripts/plot/draw/isocaps.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{fvc} =} isocaps (@var{v}, @var{isoval})\n## @deftypefnx {} {@var{fvc} =} isocaps (@var{v})\n## @deftypefnx {} {@var{fvc} =} isocaps (@var{x}, @var{y}, @var{z}, @var{v}, @var{isoval})\n## @deftypefnx {} {@var{fvc} =} isocaps (@var{x}, @var{y}, @var{z}, @var{v})\n## @deftypefnx {} {@var{fvc} =} isocaps (@dots{}, @var{which_caps})\n## @deftypefnx {} {@var{fvc} =} isocaps (@dots{}, @var{which_plane})\n## @deftypefnx {} {@var{fvc} =} isocaps (@dots{}, @qcode{\"verbose\"})\n## @deftypefnx {} {[@var{faces}, @var{vertices}, @var{fvcdata}] =} isocaps (@dots{})\n## @deftypefnx {} {} isocaps (@dots{})\n##\n## Create end-caps for isosurfaces of 3-D data.\n##\n## This function places caps at the open ends of isosurfaces.\n##\n## The input argument @var{v} is a three-dimensional array that contains data\n## sampled over a volume.\n##\n## The input @var{isoval} is a scalar that specifies the value for the\n## isosurface.  If @var{isoval} is omitted or empty, a @nospell{\"good\"} value\n## for an isosurface is determined from @var{v}.\n##\n## When called with a single output argument, @code{isocaps} returns a\n## structure array @var{fvc} with the fields: @code{faces}, @code{vertices},\n## and @code{facevertexcdata}.  The results are computed at the points\n## @code{[@var{x}, @var{y}, @var{z}] = meshgrid (1:l, 1:m, 1:n)} where\n## @code{[l, m, n] = size (@var{v})}.  The output @var{fvc} can be used\n## directly as input to the @code{patch} function.\n##\n## If called with additional input arguments @var{x}, @var{y}, and @var{z}\n## that are three-dimensional arrays with the same size as @var{v} or\n## vectors with lengths corresponding to the dimensions of @var{v}, then the\n## volume data is taken at the specified points.  If @var{x}, @var{y}, or\n## @var{z} are empty, the grid corresponds to the indices (@code{1:n}) in\n## the respective direction (@pxref{XREFmeshgrid,,@code{meshgrid}}).\n##\n## The optional parameter @var{which_caps} can have one of the following\n## string values which defines how the data will be enclosed:\n##\n## @table @asis\n## @item @qcode{\"above\"}, @qcode{\"a\"} (default)\n## for end-caps that enclose the data above @var{isoval}.\n##\n## @item @qcode{\"below\"}, @qcode{\"b\"}\n## for end-caps that enclose the data below @var{isoval}.\n## @end table\n##\n## The optional parameter @var{which_plane} can have one of the following\n## string values to define which end-cap should be drawn:\n##\n## @table @asis\n## @item @qcode{\"all\"} (default)\n## for all of the end-caps.\n##\n## @item @qcode{\"xmin\"}\n## for end-caps at the lower x-plane of the data.\n##\n## @item @qcode{\"xmax\"}\n## for end-caps at the upper x-plane of the data.\n##\n## @item @qcode{\"ymin\"}\n## for end-caps at the lower y-plane of the data.\n##\n## @item @qcode{\"ymax\"}\n## for end-caps at the upper y-plane of the data.\n##\n## @item @qcode{\"zmin\"}\n## for end-caps at the lower z-plane of the data.\n##\n## @item @qcode{\"zmax\"}\n## for end-caps at the upper z-plane of the data.\n## @end table\n##\n## The string input argument @qcode{\"verbose\"} is supported for @sc{matlab}\n## compatibility, but has no effect.\n##\n## If called with two or three output arguments, the data for faces\n## @var{faces}, vertices @var{vertices}, and the color data\n## @var{facevertexcdata} are returned in separate arrays instead of a single\n## structure.\n##\n## If called with no output argument, the end-caps are drawn directly in the\n## current figure with the @code{patch} command.\n##\n## @seealso{isosurface, isonormals, patch}\n## @end deftypefn\n\nfunction varargout = isocaps (varargin)\n\n  if (nargin < 1 || nargin > 8)\n    print_usage ();\n  endif\n\n  faces = vertices = fvcdata = [];\n\n  [x, y, z, v, isoval, which_caps, which_plane, verbose] = ...\n                                     __get_check_isocaps_args__ (varargin{:});\n\n  ## select type of cap (above or below iso value)\n  data_min = min ([v(:); isoval]);\n  data_max = max ([v(:); isoval]);\n  switch (lower (which_caps))\n    case {\"a\", \"above\"}\n      pad_val = data_min - 1;\n\n    case {\"b\", \"below\"}\n      pad_val = data_max + 1;\n\n    otherwise\n      error (\"isocaps: unknown WHICH_CAPS option '%s'\", which_caps);\n\n  endswitch\n\n  ## create patches for caps\n  if (strcmpi (which_plane, \"all\"))\n    ## get patches for all planes\n    [f_xmin, v_xmin] = __get_isocaps_patches__ (x, y, z, v, isoval, ...\n                                                pad_val, \"xmin\", verbose);\n    [f_xmax, v_xmax] = __get_isocaps_patches__ (x, y, z, v, isoval, ...\n                                                pad_val, \"xmax\", verbose);\n    [f_ymin, v_ymin] = __get_isocaps_patches__ (x, y, z, v, isoval, ...\n                                                pad_val, \"ymin\", verbose);\n    [f_ymax, v_ymax] = __get_isocaps_patches__ (x, y, z, v, isoval, ...\n                                                pad_val, \"ymax\", verbose);\n    [f_zmin, v_zmin] = __get_isocaps_patches__ (x, y, z, v, isoval, ...\n                                                pad_val, \"zmin\", verbose);\n    [f_zmax, v_zmax] = __get_isocaps_patches__ (x, y, z, v, isoval, ...\n                                                pad_val, \"zmax\", verbose);\n    vertices = [v_xmin; v_xmax; v_ymin; v_ymax; v_zmin; v_zmax];\n    v_nums = [rows(v_xmin), rows(v_xmax), ...\n              rows(v_ymin), rows(v_ymax), rows(v_zmin)];\n    f_offset = cumsum (v_nums);\n    faces = [f_xmin; f_xmax + f_offset(1); ...\n             f_ymin + f_offset(2); f_ymax + f_offset(3); ...\n             f_zmin + f_offset(4); f_zmax + f_offset(5)];\n  else  # only one plane specified\n    [faces, vertices] = __get_isocaps_patches__ (x, y, z, v, isoval,\n                                                 pad_val, which_plane,\n                                                 verbose);\n  endif\n\n  if (! isempty (vertices))\n    ## interpolate data at the vertices for coloring of the end-cap\n    fvcdata = interp3 (x, y, z, v,\n                       vertices(:,1), vertices(:,2), vertices(:,3));\n  endif\n\n  switch (nargout)\n    case 0\n      hp = patch (\"Faces\", faces, \"Vertices\", vertices, ...\n                  \"FaceVertexCData\", fvcdata, ...\n                  \"FaceColor\", \"interp\", \"EdgeColor\", \"none\");\n\n    case 1\n      vfc.vertices = vertices;\n      vfc.faces = faces;\n      vfc.facevertexcdata = fvcdata;\n      varargout = {vfc};\n\n    otherwise\n      varargout{1} = faces;\n      varargout{2} = vertices;\n      varargout{3} = fvcdata;\n\n  endswitch\n\nendfunction\n\n## get arguments from input and check values\nfunction [x, y, z, v, isoval, which_caps, which_plane, verbose] = ...\n                                  __get_check_isocaps_args__ (varargin)\n\n  x = y = z = [];\n  v = [];\n  isoval = [];\n\n  ## default values\n  which_caps = \"above\";\n  which_plane = \"all\";\n  verbose = \"\";\n\n  ## check whether last 3 input arguments are strings and assign parameters\n  num_string_inputs = 0;\n  for (i_arg = nargin:-1:nargin-2)\n    if (! ischar (varargin{i_arg}) || i_arg < 1)\n      break;  # no string arguments at end, exit checking\n    endif\n    switch (lower (varargin{i_arg}))\n      case {\"v\", \"verbose\"}\n        verbose = \"verbose\";\n        num_string_inputs++;\n\n      case {\"all\", \"xmin\", \"xmax\", \"ymin\", \"ymax\", \"zmin\", \"zmax\"}\n        which_plane = lower (varargin{i_arg});\n        num_string_inputs++;\n\n      case {\"above\", \"a\", \"below\", \"b\"}\n        which_caps = lower (varargin{i_arg});\n        num_string_inputs++;\n\n      otherwise\n        error (\"isocaps: parameter '%s' not supported\", varargin{i_arg});\n\n    endswitch\n  endfor\n\n  ## assign arguments\n  switch (nargin - num_string_inputs)\n    case 1  # isocaps (v, ...)\n      v = varargin{1};\n\n    case 2  # isocaps (v, isoval, ...)\n      v = varargin{1};\n      isoval = varargin{2};\n\n    case 4  # isocaps (x, y, z, v, ...)\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      v = varargin{4};\n\n    case 5  # isocaps (x, y, z, v, isoval, ...)\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      v = varargin{4};\n      isoval = varargin{5};\n\n    otherwise\n      error (\"isocaps: incorrect number of input arguments\");\n\n  endswitch\n\n  ## check dimensions of data\n  v_sz = size (v);\n  if (ndims (v) != 3 || any (v_sz(1:3) < 2))\n    error (\"isocaps: V must be a non-singleton 3-dimensional matrix\");\n  endif\n\n  if (isempty (x))\n    x = 1:v_sz(2);\n  endif\n  if (isempty (y))\n    y = 1:v_sz(1);\n  endif\n  if (isempty (z))\n    z = 1:v_sz(3);\n  endif\n\n  ## check x\n  if (isvector (x) && length (x) == v_sz(2))\n    x = repmat (x(:).', [v_sz(1) 1 v_sz(3)]);\n  elseif (! size_equal (v, x))\n    error (\"isocaps: X must match the size of V\");\n  endif\n\n  ## check y\n  if (isvector (y) && length (y) == v_sz(1))\n    y = repmat (y(:), [1 v_sz(2) v_sz(3)]);\n  elseif (! size_equal (v, y))\n    error (\"isocaps: Y must match the size of V\");\n  endif\n\n  ## check z\n  if (isvector (z) && length (z) == v_sz(3))\n    z = repmat (reshape (z(:), [1 1 length(z)]), ...\n                [v_sz(1) v_sz(2) 1]);\n  elseif (! size_equal (v, z))\n    error (\"isocaps: Z must match the size of V\");\n  endif\n\n  ## check isoval\n  if (isempty (isoval))\n    ## calculate \"good\" isoval value from v\n    isoval = __calc_isovalue_from_data__ (v);\n  endif\n\n  if (! isscalar (isoval) || ! isnumeric (isoval))\n    error (\"isocaps: ISOVAL must be a scalar number\");\n  endif\n\nendfunction\n\n## calculate patches for end-caps\nfunction [faces, vertices] = __get_isocaps_patches__ (x, y, z, v, isoval,\n                                                      pad_val, which_plane,\n                                                      verbose)\n\n  v_sz = size (v);\n  is_lower_cap = strcmp (which_plane(2:end), \"min\");\n  switch (which_plane(1))\n    case \"y\"\n      coor = 2;\n      capdata = zeros (2, v_sz(2), v_sz(3));\n      if (is_lower_cap)\n        cap_idx = 1;\n      else\n        cap_idx = v_sz(1);\n      endif\n      coor_val = y(cap_idx,1,1);\n      cap_data(2,:,:) = v(cap_idx,:,:);\n      cap_data(1,:,:) = pad_val;\n\n    case \"x\"\n      coor = 1;\n      cap_data = zeros (v_sz(1), 2, v_sz(3));\n      if (is_lower_cap)\n        cap_idx = 1;\n      else\n        cap_idx = v_sz(2);\n      endif\n      coor_val = x(1,cap_idx,1);\n      cap_data(:,2,:) = v(:,cap_idx,:);\n      cap_data(:,1,:) = pad_val;\n\n    case \"z\"\n      coor = 3;\n      cap_data = zeros (v_sz(1), v_sz(2), 2);\n      if (is_lower_cap)\n        cap_idx = 1;\n      else\n        cap_idx = v_sz(3);\n      endif\n      coor_val = z(1,1,cap_idx);\n      cap_data(:,:,2) = v(:,:,cap_idx);\n      cap_data(:,:,1) = pad_val;\n\n    otherwise\n      error (\"isocaps: invalid plane '%s'\", which_plane);\n\n  endswitch\n\n  n_cap = size (cap_data);\n  x_iso = x(1:n_cap(1),1:n_cap(2),1:n_cap(3));\n  y_iso = y(1:n_cap(1),1:n_cap(2),1:n_cap(3));\n  z_iso = z(1:n_cap(1),1:n_cap(2),1:n_cap(3));\n\n  [faces, vertices] = isosurface (x_iso, y_iso, z_iso, cap_data, isoval,\n                                  verbose);\n\n  if (! isempty (vertices))\n    vertices(:,coor) = coor_val;\n  endif\n\nendfunction\n\n\n%!demo\n%! isoval = .4;\n%! lin = linspace (0, 1.2, 15);\n%! [x, y, z] = meshgrid (lin, lin, lin);\n%! v = abs ((x-0.45).^2 + (y-0.55).^2 + (z-0.8).^2);\n%! hf = clf;\n%! ha = axes ();\n%! view (3);  box off;\n%! fvc_iso = isosurface (x, y, z, v, isoval);\n%! cmap = get (hf, \"Colormap\");\n%! p_iso = patch (fvc_iso, \"FaceLighting\", \"gouraud\", ...\n%!                \"FaceColor\", cmap(end,:), \"EdgeColor\", \"none\");\n%! isonormals (x, y, z, v, p_iso);\n%! fvc_xmin = isocaps (x, y, z, v, isoval, \"xmin\", \"b\");\n%! patch (fvc_xmin, \"FaceColor\", \"interp\", \"EdgeColor\", \"none\", ...\n%!        \"FaceLighting\", \"gouraud\");\n%! fvc_ymin = isocaps (x, y, z, v, isoval, \"ymin\", \"b\");\n%! patch (fvc_ymin, \"FaceColor\", \"interp\", \"EdgeColor\", \"none\", ...\n%!        \"FaceLighting\", \"gouraud\");\n%! fvc_zmax = isocaps (x, y, z, v, isoval, \"zmax\", \"b\");\n%! patch (fvc_zmax, \"FaceColor\", \"interp\", \"EdgeColor\", \"none\", ...\n%!        \"FaceLighting\", \"gouraud\");\n%! axis equal;\n%! light ();\n%! title ({\"isocaps()\", \"sphere with 3 end-caps\"});\n\n%!demo\n%! v = smooth3 (rand (6, 8, 4));\n%! isoval = .5;\n%! x = 1:3:22;  y = -14:5:11;  z = linspace (16, 18, 4);\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! clf;\n%! ## two arguments, no output\n%! subplot (2, 2, 1);\n%!  isocaps (v, isoval);\n%!  view (3);\n%! ## five arguments, no output (x, y, z are vectors)\n%! subplot (2, 2, 2);\n%!  isocaps (x, y, z, v, isoval);\n%!  view (3);\n%! ## five arguments, no output (x, y, z are matrices)\n%! subplot (2, 2, 3);\n%!  isocaps (xx, yy, zz, v, isoval);\n%!  view (3);\n%! ## five arguments, no output (mixed x, y, z)\n%! subplot (2, 2, 4);\n%!  isocaps (x, yy, z, v, isoval);\n%!  view (3);\n%!\n%! annotation (\"textbox\", [0.41 0.9 0.9 0.1], ...\n%!     \"String\", \"isocaps() called 4 ways\", ...\n%!     \"HorizontalAlignment\", \"center\", ...\n%!     \"FontSize\", 12);\n%! annotation (\"textbox\", [0.1 0.47 0.9 0.1], ...\n%!     \"String\", [\"Apart from the first plot having a different scale, \" ...\n%!     \"all four plots must look the same.\"], ...\n%!     \"HorizontalAlignment\", \"left\", ...\n%!     \"FontSize\", 12);\n\n%!shared x, y, z, xx, yy, zz, val, iso\n%! x = 1:3:22;  y = -14:5:11;  z = linspace (16, 18, 4);\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! val = rand (6, 8, 4);\n%! iso = .5;\n\n## check results for differently shaped input coordinates\n%!test\n%! fvc_vectors = isocaps (x, y, z, val, iso);\n%! fvc_matrices = isocaps (xx, yy, zz, val, iso);\n%! fvc_mixed = isocaps (xx, y, zz, val, iso);\n%! assert (fvc_vectors, fvc_matrices);\n%! assert (fvc_vectors, fvc_mixed);\n\n## two arguments, one output\n%!test\n%! fvc = isocaps (val, iso);\n%! assert (isfield (fvc, \"vertices\"));\n%! assert (isfield (fvc, \"faces\"));\n%! assert (isfield (fvc, \"facevertexcdata\"));\n\n## one argument (undocumented Matlab)\n%!test\n%! fvc = isocaps (val);\n%! fvc2 = isocaps (val, []);\n%! assert (fvc, fvc2);\n%! assert (isfield (fvc, \"vertices\"));\n%! assert (isfield (fvc, \"faces\"));\n%! assert (isfield (fvc, \"facevertexcdata\"));\n\n## four arguments (undocumented Matlab)\n%!test\n%! fvc = isocaps (x, [], z, val);\n%! assert (isfield (fvc, \"vertices\"));\n%! assert (isfield (fvc, \"faces\"));\n%! assert (isfield (fvc, \"facevertexcdata\"));\n\n## five arguments, two outputs\n%!test\n%! [faces, vertices] = isocaps ([], y, z, val, iso);\n%! assert (columns (faces), 3);\n%! assert (columns (vertices), 3);\n\n## five arguments, three outputs\n%!test\n%! [faces, vertices, fvcdata] = isocaps (x, y, [], val, iso);\n%! assert (columns (faces), 3);\n%! assert (columns (vertices), 3);\n%! assert (columns (fvcdata), 1);\n%! assert (rows (vertices), rows (fvcdata));\n\n## two arguments + one string, one output\n%!test\n%! fvc = isocaps (val, iso, \"below\");\n%! assert (isfield (fvc, \"vertices\"));\n%! assert (isfield (fvc, \"faces\"));\n%! assert (isfield (fvc, \"facevertexcdata\"));\n\n## two arguments + two strings, one output\n%!test\n%! fvc = isocaps (val, iso, \"b\", \"ymax\");\n%! assert (isfield (fvc, \"vertices\"));\n%! assert (isfield (fvc, \"faces\"));\n%! assert (isfield (fvc, \"facevertexcdata\"));\n\n## two arguments + three strings, one output\n%!test\n%! fvc = isocaps (val, iso, \"a\", \"ymin\", \"verbose\");\n%! assert (isfield (fvc, \"vertices\"));\n%! assert (isfield (fvc, \"faces\"));\n%! assert (isfield (fvc, \"facevertexcdata\"));\n\n## five arguments + one string, three outputs\n%!test\n%! [faces, vertices, fvcdata] = isocaps (x, y, z, val, iso, \"xmin\");\n%! assert (columns (faces), 3);\n%! assert (columns (vertices), 3);\n%! assert (columns (fvcdata), 1);\n%! assert (rows (vertices), rows (fvcdata));\n\n## five arguments + one string, three outputs\n%!test\n%! [faces, vertices, fvcdata] = isocaps (x, y, z, val, iso, \"verbose\");\n%! assert (columns (faces), 3);\n%! assert (columns (vertices), 3);\n%! assert (columns (fvcdata), 1);\n%! assert (rows (vertices), rows (fvcdata));\n\n## five arguments + two strings, three outputs\n%!test\n%! [faces, vertices, fvcdata] = isocaps (x, y, z, val, iso, \"xmax\", \"above\");\n%! assert (columns (faces), 3);\n%! assert (columns (vertices), 3);\n%! assert (columns (fvcdata), 1);\n%! assert (rows (vertices), rows (fvcdata));\n\n## five arguments + three strings, three outputs\n%!test\n%! [faces, vertices, fvcdata] = isocaps (x, y, z, val, iso,\n%!                                       \"zmin\", \"b\", \"verbose\");\n%! assert (columns (faces), 3);\n%! assert (columns (vertices), 3);\n%! assert (columns (fvcdata), 1);\n%! assert (rows (vertices), rows (fvcdata));\n\n## five arguments + three strings (different order), three outputs\n%!test\n%! [faces, vertices, fvcdata] = isocaps (x, y, z, val, iso,\n%!                                       \"below\", \"v\", \"zmax\");\n%! assert (columns (faces), 3);\n%! assert (columns (vertices), 3);\n%! assert (columns (fvcdata), 1);\n%! assert (rows (vertices), rows (fvcdata));\n\n## test for each error\n%!error <Invalid call> isocaps ()\n%!error <Invalid call> isocaps (1,2,3,4,5,6,7,8,9)\n%!error <parameter 'foo' not supported> isocaps (val, iso, \"foo\")\n%!error <incorrect number of input arguments> isocaps (x, val, iso)\n%!error <incorrect number of input arguments> isocaps (xx, yy, zz, val, iso, 5)\n%!error <V must be a non-singleton 3-dimensional matrix>\n%! v2 = reshape (1:6*8, [6 8]);\n%! fvc = isocaps (v2, iso);\n%!error <V must be a non-singleton 3-dimensional matrix>\n%! v3 = reshape (1:6*8, [6 1 8]);\n%! fvc = isocaps (v3, iso);\n%!error <X must match the size of V>\n%! x = 1:2:24;\n%! fvc = isocaps (x, y, z, val, iso);\n%!error <Y must match the size of V>\n%! y = -14:6:11;\n%! fvc = isocaps (x, y, z, val, iso);\n%!error <Z must match the size of V>\n%! z = linspace (16, 18, 5);\n%! fvc = isocaps (x, y, z, val, iso);\n%!error <X must match the size of V>\n%! x = 1:2:24;\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! fvc = isocaps (xx, yy, zz, val, iso);\n%!error <X must match the size of V>\n%! y = -14:6:11;\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! fvc = isocaps (xx, yy, zz, val, iso);\n%!error <X must match the size of V>\n%! z = linspace (16, 18, 3);\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! fvc = isocaps (xx, yy, zz, val, iso);\n%!error <ISOVAL must be a scalar> isocaps (val, [iso iso])\n%!error <ISOVAL must be a scalar> isocaps (val, {iso})\n"
  },
  {
    "path": "scripts/plot/draw/isocolors.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{cdat} =} isocolors (@var{c}, @var{v})\n## @deftypefnx {} {@var{cdat} =} isocolors (@var{x}, @var{y}, @var{z}, @var{c}, @var{v})\n## @deftypefnx {} {@var{cdat} =} isocolors (@var{x}, @var{y}, @var{z}, @var{r}, @var{g}, @var{b}, @var{v})\n## @deftypefnx {} {@var{cdat} =} isocolors (@var{r}, @var{g}, @var{b}, @var{v})\n## @deftypefnx {} {@var{cdat} =} isocolors (@dots{}, @var{hp})\n## @deftypefnx {} {} isocolors (@dots{}, @var{hp})\n##\n## Compute isosurface colors.\n##\n## If called with one output argument, and the first input argument @var{c}\n## is a three-dimensional array that contains indexed color values, and the\n## second input argument @var{v} are the vertices of an isosurface geometry,\n## then return a matrix @var{cdat} with color data information for the geometry\n## at computed points @code{[x, y, z] = meshgrid (1:l, 1:m, 1:n)}.  The output\n## argument @var{cdat} can be used to manually set the\n## @qcode{\"FaceVertexCData\"} property of an isosurface patch object.\n##\n## If called with additional input arguments @var{x}, @var{y} and @var{z} which\n## are three-dimensional arrays of the same size as @var{c} then the\n## color data is taken at those specified points.\n##\n## Instead of indexed color data @var{c}, @code{isocolors} can also be called\n## with RGB values @var{r}, @var{g}, @var{b}.  If input arguments @var{x},\n## @var{y}, @var{z} are not given then @code{meshgrid} computed values are\n## used.\n##\n## Optionally, a patch handle @var{hp} can be given as the last input argument\n## to all function call variations and the vertex data will be extracted\n## from the isosurface patch object.  Finally, if no output argument is given\n## then the colors of the patch given by the patch handle @var{hp} are changed.\n##\n## @seealso{isosurface, isonormals}\n## @end deftypefn\n\nfunction cdat = isocolors (varargin)\n\n  calc_rgb = false;\n  switch (nargin)\n    case 2\n      c = varargin{1};\n      vp = varargin{2};\n      x = 1:columns (c);\n      y = 1:rows (c);\n      z = 1:size (c, 3);\n    case 4\n      calc_rgb = true;\n      R = varargin{1};\n      G = varargin{2};\n      B = varargin{3};\n      vp = varargin{4};\n      x = 1:rows (R);\n      y = 1:columns (R);\n      z = 1:size (R, 3);\n    case 5\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      c = varargin{4};\n      vp = varargin{5};\n    case 7\n      calc_rgb = true;\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      R = varargin{4};\n      G = varargin{5};\n      B = varargin{6};\n      vp = varargin{7};\n    otherwise\n      print_usage ();\n  endswitch\n\n  if (isnumeric (vp) && columns (vp) == 3)\n    hp = [];\n    v = vp;\n  elseif (isgraphics (vp, \"patch\"))\n    hp = vp;\n    v = get (hp, \"Vertices\");\n  else\n    error (\"isocolors: last argument must be a vertex list or patch handle\");\n  endif\n\n  if (calc_rgb)\n    new_colors = zeros (rows (v), 3);\n    new_colors(:,1) = __interp_cube__ (\"isocolors\", x, y, z, R, v, \"values\");\n    new_colors(:,2) = __interp_cube__ (\"isocolors\", x, y, z, G, v, \"values\");\n    new_colors(:,3) = __interp_cube__ (\"isocolors\", x, y, z, B, v, \"values\");\n  else\n    new_colors = __interp_cube__ (\"isocolors\", x, y, z, c, v, \"values\");\n  endif\n\n  if (nargout == 0)\n    if (! isempty (hp))\n      set (hp, \"FaceVertexCData\", new_colors);\n    endif\n  else\n    cdat = new_colors;\n  endif\n\nendfunction\n\n\n%!demo\n%! function isofinish (p)\n%!   set (gca, \"PlotBoxAspectRatioMode\", \"manual\", ...\n%!             \"PlotBoxAspectRatio\", [1 1 1]);\n%!   set (p, \"FaceColor\", \"interp\");\n%!   set (p, \"FaceLighting\", \"flat\");\n%!   light (\"Position\", [1 1 5]);\n%! endfunction\n%!\n%! N = 15;    # Increase number of vertices in each direction\n%! iso = .4;  # Change isovalue to .1 to display a sphere\n%! lin = linspace (0, 2, N);\n%! [x, y, z] = meshgrid (lin, lin, lin);\n%! c = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);\n%! clf;\n%!\n%! subplot (2,2,1);\n%!  view (-38, 20);\n%!  [f, v] = isosurface (x, y, z, c, iso);\n%!  p = patch (\"Faces\", f, \"Vertices\", v, \"EdgeColor\", \"none\");\n%!  cdat = rand (size (c));       # Compute random color data\n%!  isocolors (x, y, z, cdat, p); # Directly set colors of patch\n%!  title (\"random colors for patch handle\");\n%!  isofinish (p);\n%!\n%! subplot (2,2,2);\n%!  view (-38, 20);\n%!  p = patch (\"Faces\", f, \"Vertices\", v, \"EdgeColor\", \"none\");\n%!  [r, g, b] = meshgrid (lin, 2-lin, 2-lin);\n%!  cdat = isocolors (x, y, z, c, v); # Compute color data vertices\n%!  set (p, \"FaceVertexCData\", cdat); # Set color data manually\n%!  title ('random colors for \"FaceVertexCData\"');\n%!  isofinish (p);\n%!\n%! subplot (2,2,3);\n%!  view (-38, 20);\n%!  p = patch (\"Faces\", f, \"Vertices\", v, \"EdgeColor\", \"none\");\n%!  cdat = isocolors (r, g, b, c, p); # Compute color data for patch\n%!  set (p, \"FaceVertexCData\", cdat); # Set color data manually\n%!  title ('random RGB colors for \"FaceVertexCData\"');\n%!  isofinish (p);\n%!\n%! subplot (2,2,4);\n%!  view (-38, 20);\n%!  p = patch (\"Faces\", f, \"Vertices\", v, \"EdgeColor\", \"none\");\n%!  r = g = b = repmat ([1:N] / N, [N, 1, N]); # Black to white\n%!  cdat = isocolors (x, y, z, r, g, b, v);\n%!  set (p, \"FaceVertexCData\", cdat);\n%!  title ('gray shades for \"FaceVertexCData\"');\n%!  isofinish (p);\n\n%!test\n%! [x, y, z] = meshgrid (0:.5:2, 0:.5:2, 0:.5:2);\n%! c = (x-.5).^2 + (y-.5).^2 + (z-.5).^2;\n%! [f, v] = isosurface (x, y, z, c, .4);\n%! cdat = isocolors (x, y, z, c, v);\n%! assert (rows (cdat) == rows (v));\n\n## Test input validation\n%!error <Invalid call> isocolors ()\n%!error <Invalid call> isocolors (1)\n%!error <Invalid call> isocolors (1,2,3)\n%!error <Invalid call> isocolors (1,2,3,4,5,6)\n%!error <Invalid call> isocolors (1,2,3,4,5,6,7,8)\n%!error <last argument must be a vertex list> isocolors (1, {1})\n%!error <last argument must be a vertex list> isocolors (1, [1 2 3 4])\n%!error <last argument must be a .*patch handle> isocolors (1, 0)\n"
  },
  {
    "path": "scripts/plot/draw/isonormals.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{vn} =} isonormals (@var{val}, @var{vert})\n## @deftypefnx {} {@var{vn} =} isonormals (@var{val}, @var{hp})\n## @deftypefnx {} {@var{vn} =} isonormals (@var{x}, @var{y}, @var{z}, @var{val}, @var{vert})\n## @deftypefnx {} {@var{vn} =} isonormals (@var{x}, @var{y}, @var{z}, @var{val}, @var{hp})\n## @deftypefnx {} {@var{vn} =} isonormals (@dots{}, \"negate\")\n## @deftypefnx {} {} isonormals (@var{val}, @var{hp})\n## @deftypefnx {} {} isonormals (@var{x}, @var{y}, @var{z}, @var{val}, @var{hp})\n## @deftypefnx {} {} isonormals (@dots{}, \"negate\")\n##\n## Calculate normals to an isosurface.\n##\n## The vertex normals @var{vn} are calculated from the gradient of the\n## 3-dimensional array @var{val} (size: lxmxn) containing the data for an\n## isosurface geometry.  The normals point towards smaller values in @var{val}.\n##\n## If called with one output argument @var{vn}, and the second input argument\n## @var{vert} holds the vertices of an isosurface, then the normals @var{vn}\n## are calculated at the vertices @var{vert} on a grid given by\n## @code{[x, y, z] = meshgrid (1:l, 1:m, 1:n)}.  The output argument\n## @var{vn} has the same size as @var{vert} and can be used to set the\n## @qcode{\"VertexNormals\"} property of the corresponding patch.\n##\n## If called with additional input arguments @var{x}, @var{y}, and @var{z},\n## which are 3-dimensional arrays with the same size as @var{val},\n## then the volume data is taken at these points.  Instead of the vertex data\n## @var{vert}, a patch handle @var{hp} can be passed to the function.\n##\n## If the last input argument is the string @qcode{\"negate\"}, compute the\n## reverse vector normals of an isosurface geometry (i.e., pointed towards\n## larger values in @var{val}).\n##\n## If no output argument is given, the property @qcode{\"VertexNormals\"} of\n## the patch associated with the patch handle @var{hp} is changed directly.\n##\n## @seealso{isosurface, isocolors, smooth3}\n## @end deftypefn\n\nfunction vn = isonormals (varargin)\n\n  narg = nargin;\n  negate = false;\n  if (nargin > 2)\n    if (ischar (varargin{end}))\n      if (strcmpi (varargin{end}, \"negate\"))\n        negate = true;\n        narg -= 1;\n      else\n        error (\"isonormals: Unknown option '%s'\", varargin{end});\n      endif\n    endif\n  endif\n\n  switch (narg)\n    case 2\n      val = varargin{1};\n      vp = varargin{2};\n      x = 1:columns (val);\n      y = 1:rows (val);\n      z = 1:size (val, 3);\n\n    case 5\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      val = varargin{4};\n      vp = varargin{5};\n\n    otherwise\n      print_usage ();\n\n  endswitch\n\n  if (isnumeric (vp) && columns (vp) == 3)\n    hp = [];\n    v = vp;\n  elseif (isgraphics (vp, \"patch\"))\n    hp = vp;\n    v = get (hp, \"Vertices\");\n  else\n    error (\"isonormals: input must be a list of vertices or a patch handle\");\n  endif\n\n  if (negate)\n    normals = __interp_cube__ (\"isonormals\", x, y, z, val, v, \"normals\");\n  else\n    normals = -__interp_cube__ (\"isonormals\", x, y, z, val, v, \"normals\");\n  endif\n\n  if (nargout == 0)\n    if (! isempty (hp))\n      set (hp, \"VertexNormals\", normals);\n    endif\n  else\n    vn = normals;\n  endif\n\nendfunction\n\n\n%!demo\n%! function isofinish (hp)\n%!   axis equal;\n%!   set (hp, \"VertexNormals\", -get (hp, \"VertexNormals\"));  # Revert normals\n%!   shading interp;\n%!   lighting gouraud;\n%!   set (hp, \"BackFaceLighting\", \"lit\");\n%!   light ();\n%! endfunction\n%!\n%! N = 15;    # Increase number of vertices in each direction\n%! iso = .4;  # Change isovalue to .1 to display a sphere\n%! lin = linspace (0, 2, N);\n%! [x, y, z] = meshgrid (lin, lin, lin);\n%! val = (x-.5).^2 + (y-.5).^2 + (z-.5).^2;\n%! clf;\n%!\n%! subplot (2,2,1);\n%!  view (-38, 20);\n%!  [fac, vert, cdat] = isosurface (x, y, z, val, iso, y);\n%!  hp = patch (\"Faces\", fac, \"Vertices\", vert, \"FaceVertexCData\", cdat);\n%!  title (\"without isonormals\");\n%!  isofinish (hp);\n%!  set (hp, \"VertexNormalsMode\", \"auto\");  # for Matlab compatibility\n%!\n%! subplot (2,2,2);\n%!  view (-38, 20);\n%!  hp = patch (\"Faces\", fac, \"Vertices\", vert, \"FaceVertexCData\", cdat);\n%!  title (\"patch modified by isonormals\");\n%!  isonormals (x, y, z, val, hp);  # Directly modify patch\n%!  isofinish (hp);\n%!\n%! subplot (2,2,3);\n%!  view (-38, 20);\n%!  hp = patch (\"Faces\", fac, \"Vertices\", vert, \"FaceVertexCData\", cdat);\n%!  vn = isonormals (x, y, z, val, vert);  # Compute normals of isosurface\n%!  set (hp, \"VertexNormals\", vn);         # Manually set vertex normals\n%!  title ('set \"VertexNormals\" from isonormals');\n%!  isofinish (hp);\n%!\n%! subplot (2,2,4);\n%!  view (-38, 20);\n%!  hp = patch (\"Faces\", fac, \"Vertices\", vert, \"FaceVertexCData\", cdat);\n%!  isonormals (x, y, z, val, hp, \"negate\");  # Use reverse directly\n%!  title ('patch modified by isonormals (..., \"negate\")');\n%!  isofinish (hp);\n\n%!shared x,y,z,val,vert\n%! [x, y, z] = meshgrid (0:.5:2, 0:.5:2, 0:.5:2);\n%! val = abs ((x-.5).^2 + (y-.3).^2 + (z-.4).^2);\n%! [fac, vert, cdat] = isosurface (x, y, z, val, .4, y);\n\n%!test\n%! vn = isonormals (x, y, z, val, vert);\n%! assert (size (vert), size (vn));\n\n%!test\n%! np = isonormals (x, y, z, val, vert);\n%! nn = isonormals (x, y, z, val, vert, \"negate\");\n%! assert (np, -nn);\n\n%!test\n%! [x,y,z] = meshgrid (-2:1:2, -2:1:2, -2:1:2);\n%! val = x.^2 + y.^2 + z.^2;\n%! [f,vert] = isosurface (x, y, z, val, 1);\n%! vn = isonormals (x, y, z, val, vert);\n%! dirn = vert ./ vn;\n%! assert (all (dirn(isfinite (dirn)) <= 0));\n\n## Test input validation\n%!error <Invalid call> isonormals ()\n%!error <Invalid call> isonormals (1)\n%!error <Invalid call> isonormals (1,2,3)\n%!error <Invalid call> isonormals (1,2,3,4)\n%!error <Invalid call> isonormals (1,2,3,4,5,6)\n%!error <Unknown option 'foo'> isonormals (x, y, z, val, vert, \"foo\")\n%!error <must be a list of vertices> isonormals (1, {1})\n%!error <must be a list of vertices> isonormals (1, [1 2 3 4])\n%!error <must be a .* patch handle> isonormals (x, y, z, val, x)\n## Test validation of private function __interp_cube__\n%!error <X, Y, Z have unequal dimensions> isonormals ({x}, y, z, val, vert)\n%!error <X, Y, Z have unequal dimensions> isonormals (x, {y}, z, val, vert)\n%!error <X, Y, Z have unequal dimensions> isonormals (x, y, {z}, val, vert)\n%!error <X, Y, Z have unequal dimensions> isonormals (x, y, z(1), val, vert)\n%!error <X, Y, Z have unequal dimensions> isonormals (x(:), y(:), z, val, vert)\n%!error <VAL dimensions must match those of X, Y, and Z> isonormals (1, 2, 3, val, vert)\n"
  },
  {
    "path": "scripts/plot/draw/isosurface.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{fv} =} isosurface (@var{v}, @var{isoval})\n## @deftypefnx {} {@var{fv} =} isosurface (@var{v})\n## @deftypefnx {} {@var{fv} =} isosurface (@var{x}, @var{y}, @var{z}, @var{v}, @var{isoval})\n## @deftypefnx {} {@var{fv} =} isosurface (@var{x}, @var{y}, @var{z}, @var{v})\n## @deftypefnx {} {@var{fvc} =} isosurface (@dots{}, @var{col})\n## @deftypefnx {} {@var{fv} =} isosurface (@dots{}, \"noshare\")\n## @deftypefnx {} {@var{fv} =} isosurface (@dots{}, \"verbose\")\n## @deftypefnx {} {[@var{f}, @var{v}] =} isosurface (@dots{})\n## @deftypefnx {} {[@var{f}, @var{v}, @var{c}] =} isosurface (@dots{})\n## @deftypefnx {} {} isosurface (@dots{})\n##\n## Calculate isosurface of 3-D volume data.\n##\n## An isosurface connects points with the same value and is analogous to a\n## contour plot, but in three dimensions.\n##\n## The input argument @var{v} is a three-dimensional array that contains data\n## sampled over a volume.\n##\n## The input @var{isoval} is a scalar that specifies the value for the\n## isosurface.  If @var{isoval} is omitted or empty, a @nospell{\"good\"} value\n## for an isosurface is determined from @var{v}.\n##\n## When called with a single output argument @code{isosurface} returns a\n## structure array @var{fv} that contains the fields @var{faces} and\n## @var{vertices} computed at the points\n## @code{[@var{x}, @var{y}, @var{z}] = meshgrid (1:l, 1:m, 1:n)} where\n## @code{[l, m, n] = size (@var{v})}.  The output @var{fv} can be\n## used directly as input to the @code{patch} function.\n##\n## If called with additional input arguments @var{x}, @var{y}, and @var{z}\n## that are three-dimensional arrays with the same size as @var{v} or\n## vectors with lengths corresponding to the dimensions of @var{v}, then the\n## volume data is taken at the specified points.  If @var{x}, @var{y}, or\n## @var{z} are empty, the grid corresponds to the indices (@code{1:n}) in\n## the respective direction (@pxref{XREFmeshgrid,,@code{meshgrid}}).\n##\n## The optional input argument @var{col}, which is a three-dimensional array\n## of the same size as @var{v}, specifies coloring of the isosurface.  The\n## color data is interpolated, as necessary, to match @var{isoval}.  The\n## output structure array, in this case, has the additional field\n## @var{facevertexcdata}.\n##\n## If given the string input argument @qcode{\"noshare\"}, vertices may be\n## returned multiple times for different faces.  The default behavior is to\n## eliminate vertices shared by adjacent faces.\n##\n## The string input argument @qcode{\"verbose\"} is supported for @sc{matlab}\n## compatibility, but has no effect.\n##\n## Any string arguments must be passed after the other arguments.\n##\n## If called with two or three output arguments, return the information about\n## the faces @var{f}, vertices @var{v}, and color data @var{c} as separate\n## arrays instead of a single structure array.\n##\n## If called with no output argument, the isosurface geometry is directly\n## plotted with the @code{patch} command and a light object is added to\n## the axes if not yet present.\n##\n## For example,\n##\n## @example\n## @group\n## [x, y, z] = meshgrid (1:5, 1:5, 1:5);\n## v = rand (5, 5, 5);\n## isosurface (x, y, z, v, .5);\n## @end group\n## @end example\n##\n## @noindent\n## will directly draw a random isosurface geometry in a graphics window.\n##\n## An example of an isosurface geometry with different additional coloring:\n## @c Set example in small font to prevent overfull line\n##\n## @smallexample\n## N = 15;    # Increase number of vertices in each direction\n## iso = .4;  # Change isovalue to .1 to display a sphere\n## lin = linspace (0, 2, N);\n## [x, y, z] = meshgrid (lin, lin, lin);\n## v = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);\n## figure ();\n##\n## subplot (2,2,1); view (-38, 20);\n## [f, vert] = isosurface (x, y, z, v, iso);\n## p = patch (\"Faces\", f, \"Vertices\", vert, \"EdgeColor\", \"none\");\n## pbaspect ([1 1 1]);\n## isonormals (x, y, z, v, p)\n## set (p, \"FaceColor\", \"green\", \"FaceLighting\", \"gouraud\");\n## light (\"Position\", [1 1 5]);\n##\n## subplot (2,2,2); view (-38, 20);\n## p = patch (\"Faces\", f, \"Vertices\", vert, \"EdgeColor\", \"blue\");\n## pbaspect ([1 1 1]);\n## isonormals (x, y, z, v, p)\n## set (p, \"FaceColor\", \"none\", \"EdgeLighting\", \"gouraud\");\n## light (\"Position\", [1 1 5]);\n##\n## subplot (2,2,3); view (-38, 20);\n## [f, vert, c] = isosurface (x, y, z, v, iso, y);\n## p = patch (\"Faces\", f, \"Vertices\", vert, \"FaceVertexCData\", c, ...\n##            \"FaceColor\", \"interp\", \"EdgeColor\", \"none\");\n## pbaspect ([1 1 1]);\n## isonormals (x, y, z, v, p)\n## set (p, \"FaceLighting\", \"gouraud\");\n## light (\"Position\", [1 1 5]);\n##\n## subplot (2,2,4); view (-38, 20);\n## p = patch (\"Faces\", f, \"Vertices\", vert, \"FaceVertexCData\", c, ...\n##            \"FaceColor\", \"interp\", \"EdgeColor\", \"blue\");\n## pbaspect ([1 1 1]);\n## isonormals (x, y, z, v, p)\n## set (p, \"FaceLighting\", \"gouraud\");\n## light (\"Position\", [1 1 5]);\n## @end smallexample\n##\n## @seealso{isonormals, isocolors, isocaps, smooth3, reducevolume, reducepatch,\n## patch}\n## @end deftypefn\n\n## FIXME: Add support for string input argument \"verbose\"\n##        (needs changes to __marching_cube__.m)\n\nfunction varargout = isosurface (varargin)\n\n  if (nargin < 1 || nargin > 8)\n    print_usage ();\n  endif\n\n  [x, y, z, v, isoval, colors, noshare, verbose] = ...\n      __get_check_isosurface_args__ (nargout, varargin{:});\n\n  calc_colors = ! isempty (colors);\n  if (calc_colors)\n    [fvc.faces, fvc.vertices, fvc.facevertexcdata] = ...\n        __marching_cube__ (x, y, z, v, isoval, colors);\n  else\n    [fvc.faces, fvc.vertices] = __marching_cube__ (x, y, z, v, isoval);\n  endif\n\n  if (isempty (fvc.vertices) || isempty (fvc.faces))\n    warning (\"isosurface: triangulation is empty\");\n  endif\n\n  ## remove faces for which at least one of the vertices is NaN\n  vert_nan = 1:size (fvc.vertices, 1);\n  vert_nan(any (isnan (fvc.vertices), 2)) = NaN;\n  fvc.faces = vert_nan(fvc.faces);\n  fvc.faces(any (isnan (fvc.faces), 2), :) = [];\n\n  if (! noshare)\n    [fvc.faces, fvc.vertices, J] = __unite_shared_vertices__ (fvc.faces,\n                                                              fvc.vertices);\n\n    if (calc_colors)\n      fvc.facevertexcdata = fvc.facevertexcdata(J);  # share very close vertices\n    endif\n  endif\n\n  switch (nargout)\n    case 0\n      ## plot the calculated surface\n      if (calc_colors)\n        fc = fvc.facevertexcdata;\n      else\n        fc = isoval;\n      endif\n      ## Matlab uses \"EdgeColor\", \"none\", but that looks odd in gnuplot.\n      hax = gca ();\n      if (strcmp (get (gcf, \"__graphics_toolkit__\"), \"gnuplot\"))\n        ec = \"k\";\n      else\n        ec = \"none\";\n      endif\n      pa = patch (\"Faces\", fvc.faces, \"Vertices\", fvc.vertices,\n                  \"FaceVertexCData\", fc,\n                  \"FaceColor\", \"flat\", \"EdgeColor\", ec,\n                  \"FaceLighting\", \"gouraud\");\n      if (! ishold (hax))\n        set (hax, \"View\", [-37.5, 30]);\n      endif\n      isonormals (x, y, z, v, pa);\n      lights = findobj (hax, \"Type\", \"light\");\n      if (isempty (lights))\n        camlight ();\n      endif\n\n    case 1\n      varargout = {fvc};\n\n    case 2\n      varargout = {fvc.faces, fvc.vertices};\n\n    otherwise  # 3 args or more\n      varargout = {fvc.faces, fvc.vertices, fvc.facevertexcdata};\n\n  endswitch\n\nendfunction\n\nfunction [x, y, z, v, isoval, colors, noshare, verbose] = __get_check_isosurface_args__ (nout, varargin)\n\n  ## get arguments from input and check values\n  x = y = z = [];\n  v = [];\n  isoval = [];\n  colors = [];\n\n  ## default values\n  noshare = false;\n  verbose = false;\n\n  nin = length (varargin);\n  num_string_inputs = 0;\n\n  ## check whether last 2 input arguments are strings and assign parameters\n  for i_arg = (nin:-1:nin-1)\n    if (! ischar (varargin{i_arg}) || i_arg < 1)\n      break;  # no string arguments at end, exit checking\n    endif\n    switch (lower (varargin{i_arg}))\n      case {\"v\", \"verbose\"}\n        verbose = true;\n        num_string_inputs++;\n\n      case {\"n\", \"noshare\"}\n        noshare = true;\n        num_string_inputs++;\n\n      case \"\"\n        num_string_inputs++;\n        ## silently ignore empty strings\n\n      otherwise\n        error (\"isosurface: parameter '%s' not supported\", varargin{i_arg});\n\n    endswitch\n  endfor\n\n  ## assign arguments\n  switch (nin - num_string_inputs)\n    case 1  # isosurface (v, ...)\n      v = varargin{1};\n\n    case 2  # isosurface (v, isoval, ...) or isosurface (v, col, ...)\n      v = varargin{1};\n      if (isscalar (varargin{2}) || isempty (varargin{2}))\n        isoval = varargin{2};\n      else\n        colors = varargin{2};\n      endif\n\n    case 3  # isosurface (v, isoval, col, ...)\n      v = varargin{1};\n      isoval = varargin{2};\n      colors = varargin{3};\n\n    case 4  # isosurface (x, y, z, v, ...)\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      v = varargin{4};\n\n    case 5  # isosurface (x, y, z, v, isoval, ...) or\n            # isosurface (x, y, z, v, col, ...)\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      v = varargin{4};\n      if (isscalar (varargin{5}) || isempty (varargin{5}))\n        isoval = varargin{5};\n      else\n        colors = varargin{5};\n      endif\n\n    case 6  # isosurface (x, y, z, v, isoval, col, ...)\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      v = varargin{4};\n      isoval = varargin{5};\n      colors = varargin{6};\n\n    otherwise\n      error (\"isosurface: incorrect number of input arguments\");\n\n  endswitch\n\n  ## check dimensions of v\n  v_sz = size (v);\n  if (ndims (v) != 3 || any (v_sz(1:3) < 2))\n    error (\"isosurface: V must be a non-singleton 3-dimensional matrix\");\n  endif\n\n  if (isempty (x))\n    x = 1:columns (v);\n  endif\n  if (isempty (y))\n    y = 1:rows (v);\n  endif\n  if (isempty (z))\n    z = 1:size (v, 3);\n  endif\n\n  ## check x\n  if (isvector (x) && length (x) == v_sz(2))\n    x = repmat (x(:)', [v_sz(1) 1 v_sz(3)]);\n  elseif (! size_equal (v, x))\n    error (\"isosurface: X must match the size of V\");\n  endif\n\n  ## check y\n  if (isvector (y) && length (y) == v_sz(1))\n    y = repmat (y(:), [1 v_sz(2) v_sz(3)]);\n  elseif (! size_equal (v, y))\n    error (\"isosurface: Y must match the size of V\");\n  endif\n\n  ## check z\n  if (isvector (z) && length (z) == v_sz(3))\n    z = repmat (reshape (z(:), [1 1 length(z)]), [v_sz(1) v_sz(2) 1]);\n  elseif (! size_equal (v, z))\n    error (\"isosurface: Z must match the size of V\");\n  endif\n\n  ## check isoval\n  if (isempty (isoval))\n    ## calculate \"good\" isoval value from v\n    isoval = __calc_isovalue_from_data__ (v);\n  endif\n\n  if (! isscalar (isoval))\n    error (\"isosurface: ISOVAL must be a scalar\");\n  endif\n\n  ## check colors\n  if (! isempty (colors))\n    if (! size_equal (v, colors))\n      error (\"isosurface: COL must match the size of V\");\n    endif\n    if (nout == 2)\n      warning (\"isosurface: colors will be calculated, but no output argument to receive it\");\n    endif\n  elseif (nout >= 3)\n    error (\"isosurface: COL must be passed to return C\");\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2);\n%! v = x.^2 + y.^2 + z.^2;\n%! isosurface (x, y, z, v, 1);\n%! axis equal;\n%! title (\"isosurface() of a sphere\");\n\n%!demo\n%! clf;\n%! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2);\n%! v = x.^2 + y.^2 + z.^2;\n%! isosurface (x, y, z, v, 3);\n%! isosurface (x, y, z, v, 5);\n%! axis equal;\n%! title (\"isosurface() of two nested spheres\");\n\n%!demo\n%! clf;\n%! x = 0:2;\n%! y = 0:3;\n%! z = 0:1;\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! v        = [0, 0, 0; 0, 0, 0; 0, 0, 1; 0, 0, 1];\n%! v(:,:,2) = [0, 0, 0; 0, 0, 1; 0, 1, 2; 0, 1, 2];\n%! iso = 0.8;\n%!\n%! ## Three arguments, no output\n%! subplot (2, 2, 1);\n%!  fvc = isosurface (v, iso, yy);\n%!  patch (fvc);\n%!  shading faceted;\n%!  view (110, 40);\n%! ## six arguments, no output (x, y, z are vectors)\n%! subplot (2, 2, 2);\n%!  fvc = isosurface (x, y, z, v, iso, yy);\n%!  patch (fvc);\n%!  shading faceted;\n%!  view (110, 40);\n%! ## six arguments, no output (x, y, z are matrices)\n%! subplot (2, 2, 3);\n%!  fvc = isosurface (xx, yy, zz, v, iso, yy);\n%!  patch (fvc);\n%!  shading faceted;\n%!  view (110, 40);\n%! ## six arguments, no output (mixed x, y, z) and option \"noshare\"\n%! subplot (2, 2, 4);\n%!  fvc = isosurface (x, yy, z, v, iso, yy, \"noshare\");\n%!  patch (fvc);\n%!  shading faceted;\n%!  view (110, 40);\n%!  annotation (\"textbox\", [0.41 0.9 0.9 0.1], ...\n%!      \"String\", \"isosurface() called 4 ways\", ...\n%!      \"HorizontalAlignment\", \"center\", ...\n%!      \"FontSize\", 12);\n%!  annotation (\"textbox\", [0.1 0.45 0.9 0.1], ...\n%!      \"String\", {[\"Apart from the first plot having a different scale, \" ...\n%!                  \"all four plots must look the same.\"],\n%!                 [\"The last plot might have different colors but must \" ...\n%!                  \"have the same shape.\"]}, ...\n%!      \"HorizontalAlignment\", \"left\", ...\n%!      \"FontSize\", 12);\n\n%!shared x, y, z, xx, yy, zz, val, iso\n%! x = 0:2;\n%! y = 0:3;\n%! z = 0:1;\n%! [xx, yy, zz]  = meshgrid (x, y, z);\n%! val        = [0, 0, 0; 0, 0, 0; 0, 0, 1; 0, 0, 1];\n%! val(:,:,2) = [0, 0, 0; 0, 0, 1; 0, 1, 2; 0, 1, 2];\n%! iso = 0.8;\n\n## one argument, one output\n%!test\n%! fv = isosurface (val);\n%! assert (isfield (fv, \"vertices\"), true);\n%! assert (isfield (fv, \"faces\"), true);\n%! assert (size (fv.vertices), [5 3]);\n%! assert (size (fv.faces), [3 3]);\n\n## two arguments (second is ISO), one output\n%!test\n%! fv = isosurface (val, iso);\n%! assert (isfield (fv, \"vertices\"), true);\n%! assert (isfield (fv, \"faces\"), true);\n%! assert (size (fv.vertices), [11 3]);\n%! assert (size (fv.faces), [10 3]);\n\n## two arguments (second is COL), one output\n%!test\n%! fvc = isosurface (val, yy);\n%! assert (isfield (fvc, \"vertices\"), true);\n%! assert (isfield (fvc, \"faces\"), true);\n%! assert (isfield (fvc, \"facevertexcdata\"), true);\n%! assert (size (fvc.vertices), [5 3]);\n%! assert (size (fvc.faces), [3 3]);\n%! assert (size (fvc.facevertexcdata), [5 1]);\n\n## three arguments, one output\n%!test\n%! fvc = isosurface (val, iso, yy);\n%! assert (isfield (fvc, \"vertices\"), true);\n%! assert (isfield (fvc, \"faces\"), true);\n%! assert (isfield (fvc, \"facevertexcdata\"), true);\n%! assert (size (fvc.vertices), [11 3]);\n%! assert (size (fvc.faces), [10 3]);\n%! assert (size (fvc.facevertexcdata), [11 1]);\n\n## four arguments, one output\n%!test\n%! fv = isosurface (x, [], z, val);\n%! assert (isfield (fv, \"vertices\"), true);\n%! assert (isfield (fv, \"faces\"), true);\n%! assert (size (fv.vertices), [5 3]);\n%! assert (size (fv.faces), [3 3]);\n\n## five arguments (fifth is ISO), one output\n%!test\n%! fv = isosurface (xx, y, [], val, iso);\n%! assert (isfield (fv, \"vertices\"), true);\n%! assert (isfield (fv, \"faces\"), true);\n%! assert (size (fv.vertices), [11 3]);\n%! assert (size (fv.faces), [10 3]);\n\n## five arguments (fifth is COL), one output\n%!test\n%! fvc = isosurface ([], yy, z, val, yy);\n%! assert (isfield (fvc, \"vertices\"), true);\n%! assert (isfield (fvc, \"faces\"), true);\n%! assert (isfield (fvc, \"facevertexcdata\"), true);\n%! assert (size (fvc.vertices), [5 3]);\n%! assert (size (fvc.faces), [3 3]);\n%! assert (size (fvc.facevertexcdata), [5 1]);\n\n## six arguments, one output\n%!test\n%! fvc = isosurface (xx, yy, zz, val, iso, yy);\n%! assert (isfield (fvc, \"vertices\"), true);\n%! assert (isfield (fvc, \"faces\"), true);\n%! assert (isfield (fvc, \"facevertexcdata\"), true);\n%! assert (size (fvc.vertices), [11 3]);\n%! assert (size (fvc.faces), [10 3]);\n%! assert (size (fvc.facevertexcdata), [11 1]);\n\n## five arguments (fifth is ISO), two outputs\n%!test\n%! [f, v] = isosurface (x, y, z, val, iso);\n%! assert (size (f), [10 3]);\n%! assert (size (v), [11 3]);\n\n## six arguments, three outputs\n%!test\n%! [f, v, c] = isosurface (x, y, z, val, iso, yy);\n%! assert (size (f), [10 3]);\n%! assert (size (v), [11 3]);\n%! assert (size (c), [11 1]);\n\n## two arguments (second is ISO) and one string, one output\n%!test\n%! fv = isosurface (val, iso, \"verbose\");\n%! assert (isfield (fv, \"vertices\"), true);\n%! assert (isfield (fv, \"faces\"), true);\n%! assert (size (fv.vertices), [11 3]);\n%! assert (size (fv.faces), [10 3]);\n\n## six arguments and two strings, one output\n%!test\n%! fvc = isosurface (xx, yy, zz, val, iso, yy, \"v\", \"noshare\");\n%! assert (isfield (fvc, \"vertices\"), true);\n%! assert (isfield (fvc, \"faces\"), true);\n%! assert (isfield (fvc, \"facevertexcdata\"), true);\n%! assert (size (fvc.vertices), [20 3]);\n%! assert (size (fvc.faces), [10 3]);\n%! assert (size (fvc.facevertexcdata), [20 1]);\n\n## five arguments (fifth is COL) and two strings (different order), one output\n%!test\n%! fvc = isosurface (xx, yy, zz, val, yy, \"n\", \"v\");\n%! assert (isfield (fvc, \"vertices\"), true);\n%! assert (isfield (fvc, \"faces\"), true);\n%! assert (isfield (fvc, \"facevertexcdata\"), true);\n%! assert (size (fvc.vertices), [7 3]);\n%! assert (size (fvc.faces), [3 3]);\n%! assert (size (fvc.facevertexcdata), [7 1]);\n\n## test for each error and warning\n%!error <Invalid call> isosurface ()\n%!error <Invalid call> isosurface (1,2,3,4,5,6,7,8,9)\n%!error <parameter 'foobar' not supported>\n%! fvc = isosurface (val, iso, \"foobar\");\n%!error <incorrect number of input arguments>\n%! fvc = isosurface (xx, yy, zz, val, iso, yy, 5);\n%!error <V must be a non-singleton 3-dimensional matrix>\n%! v = reshape (1:6*8, [6 8]);\n%! fvc = isosurface (v, iso);\n%!error <V must be a non-singleton 3-dimensional matrix>\n%! v = reshape(1:6*8, [6 1 8]); fvc = isosurface (v, iso);\n%!error <X must match the size of V>\n%! x = 1:2:24;\n%! fvc = isosurface (x, y, z, val, iso);\n%!error <Y must match the size of V>\n%! y = -14:6:11;\n%! fvc = isosurface (x, y, z, val, iso);\n%!error <Z must match the size of V>\n%! z = linspace (16, 18, 5);\n%! fvc = isosurface (x, y, z, val, iso);\n%!error <X must match the size of V>\n%! x = 1:2:24;\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! fvc = isosurface (xx, yy, zz, val, iso);\n%!error <X must match the size of V>\n%! y = -14:6:11;\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! fvc = isosurface (xx, yy, zz, val, iso);\n%!error <X must match the size of V>\n%! z = linspace (16, 18, 3);\n%! [xx, yy, zz] = meshgrid (x, y, z);\n%! fvc = isosurface (xx, yy, zz, val, iso);\n%!error <ISOVAL must be a scalar> fvc = isosurface (val, [iso iso], yy)\n%!error <COL must match the size of V> fvc = isosurface (val, [iso iso])\n%!error <COL must be passed to return C> [f, v, c] = isosurface (val, iso)\n%!warning <colors will be calculated, but no output argument to receive it>\n%! [f, v] = isosurface (val, iso, yy);\n"
  },
  {
    "path": "scripts/plot/draw/light.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} light ()\n## @deftypefnx {} {} light (@dots{}, \"@var{prop}\", @var{val}, @dots{})\n## @deftypefnx {} {} light (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} light (@dots{})\n## Create a light object in the current axes or for axes @var{hax}.\n##\n## When a light object is present in an axes object, and the properties\n## @qcode{\"EdgeLighting\"} or @qcode{\"FaceLighting\"} of a @code{patch} or\n## @code{surface} object are set to a value other than @qcode{\"none\"}, these\n## objects are drawn with lighting effects.  Supported values for Lighting\n## properties are @qcode{\"none\"} (no lighting effects), @qcode{\"flat\"} (faceted\n## look of the objects), and @qcode{\"gouraud\"} (linear interpolation of the\n## lighting effects between the vertices).  If the lighting mode is set to\n## @qcode{\"flat\"}, the @qcode{\"FaceNormals\"} property is used for lighting.\n## For @qcode{\"gouraud\"}, the @qcode{\"VertexNormals\"} property is used.\n##\n## Up to eight light objects are supported per axes.  (Implementation\n## dependent)\n##\n## Lighting is only supported for OpenGL graphic toolkits (i.e., @qcode{\"fltk\"}\n## and @qcode{\"qt\"}).\n##\n## A light object has the following properties which alter the appearance of\n## the plot.\n##\n## @table @asis\n## @item @qcode{\"Color\":} The color of the light can be passed as an\n## RGB-vector (e.g., @code{[1 0 0]} for red) or as a string (e.g., @qcode{\"r\"}\n## for red).  The default color is white (@code{[1 1 1]}).\n##\n## @item @qcode{\"Position\":} The direction from which the light emanates as a\n## 1x3-vector.  The default direction is @code{[1 0 1]}.\n##\n## @item @qcode{\"Style\":} This string defines whether the light emanates from a\n## light source at infinite distance (@qcode{\"infinite\"}) or from a local point\n## source (@qcode{\"local\"}).  The default is @qcode{\"infinite\"}.\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then add the light object\n## to this axes, rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created light\n## object.\n##\n## Programming Note: The full list of properties is documented at\n## @ref{Light Properties}.\n## @seealso{lighting, material, patch, surface}\n## @end deftypefn\n\nfunction h = light (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"light\", varargin{:});\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  htmp = __go_light__ (hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Demonstrate effects of lighting\n%! clf;\n%! ## patches\n%! h_axes1 = subplot (2, 2, 1);\n%!  [x,y,z] = meshgrid (-2:0.2:2, -2:0.2:2, -2:0.2:2);\n%!  val = x.^2 + y.^2 + z.^2;\n%!  fv1 = isosurface (x, y, z, val, 1);\n%!  h_patch1 = patch (fv1, \"FaceColor\", \"c\", \"EdgeColor\", \"none\", ...\n%!                         \"FaceLighting\", \"Gouraud\");\n%!  isonormals (x, y, z, val, h_patch1);\n%!  fv2 = isosurface (x, y+3, z, val, 1);\n%!  h_patch2 = patch (fv2, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                         \"FaceLighting\", \"Gouraud\");\n%!  isonormals (x, y+3, z, val, h_patch2);\n%!  view (3);\n%!  axis equal;  axis tight;\n%!  title (\"Patch with lighting\");\n%!  h_light1 = light ();\n%!\n%! h_axes2 = subplot (2, 2, 2);\n%!  patch (fv1, \"FaceColor\", \"c\", \"EdgeColor\", \"none\");\n%!  patch (fv2, \"FaceColor\", \"r\", \"EdgeColor\", \"none\");\n%!  view (3);\n%!  axis equal;  axis tight;\n%!  title (\"Patch without lighting\");\n%!\n%! ## surfaces\n%! h_axes3 = subplot (2, 2, 3);\n%!  h_surf1 = surf (h_axes3, peaks, \"LineStyle\", \"none\", ...\n%!                                  \"FaceLighting\", \"Gouraud\");\n%!  title (\"Surface with lighting\");\n%!  view (3);\n%!  h_light2 = light ();\n%!\n%! h_axes3 = subplot (2, 2, 4);\n%!  h_surf2 = surf (h_axes3, peaks, \"LineStyle\", \"none\");\n%!  view (3);\n%!  title (\"Surface without lighting\");\n\n%!demo\n%! ## Lighting modes on patches\n%! clf;\n%! [x,y,z] = meshgrid (-.2:0.05:.2, -.2:0.05:.2, -.2:0.05:.2);\n%! val = (x.^2 + y.^2 + z.^2);\n%!\n%! h_axes1 = axes ();\n%! fv = isosurface (x, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"none\");\n%! fv = isosurface (x+.5, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"flat\");\n%! fv = isosurface (x+1, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! axis tight\n%! axis equal\n%! view (2);\n%! light (\"Position\", [-1 1 1]);\n%! title ({\"FaceLighting on patches\", \"none - flat - gouraud\"});\n\n%!demo\n%! ## Lighting modes on surfaces\n%! clf;\n%! Z = peaks ();\n%! [X, Y] = meshgrid (1:columns (Z), 1:rows (Z));\n%!\n%! h_axes1 = axes ();\n%! surf (X, Y, Z, \"LineStyle\", \"none\", \"FaceLighting\", \"none\");\n%! hold on;\n%! surf (X + round (1.2 * columns (Z)), Y, Z, \"LineStyle\", \"none\", ...\n%!       \"FaceLighting\", \"flat\");\n%! surf (X + round (2.4 * columns (Z)), Y, Z, \"LineStyle\", \"none\", ...\n%!       \"FaceLighting\", \"gouraud\");\n%! axis tight\n%! axis equal\n%! grid off\n%! view (2);\n%! light (\"Position\", [-1 1 1]);\n%! title ({\"FaceLighting on surfaces\", \"none - flat - gouraud\"});\n\n%!demo\n%! ## multiple lights\n%! clf;\n%! h_axes = subplot (1, 2, 1);\n%!  [x,y,z] = meshgrid (-2:0.1:2, -2:0.1:2, -2:0.1:2);\n%!  val = x.^2 + y.^2 + z.^2;\n%!  fv = isosurface (x, y, z, val, 1);\n%!  h_patch = patch (fv, \"FaceColor\", \"w\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  isonormals (x, y, z, val, h_patch);\n%!  view (3);\n%!  axis equal;  axis tight;\n%!  title (\"Patch with one light\");\n%!  h_light = light (\"Color\", \"g\");\n%!\n%! h_axes2 = subplot (1, 2, 2);\n%!  h_patch2 = patch (fv, \"FaceColor\", \"w\", \"EdgeColor\", \"none\", ...\n%!                        \"FaceLighting\", \"Gouraud\");\n%!  isonormals (x, y, z, val, h_patch2);\n%!  view (3);\n%!  axis equal;  axis tight;\n%!  title (\"Patch with three lights\");\n%!  h_light1 = light (\"Color\", \"r\");\n%!  h_light2 = light (\"Position\", [0 1 1], \"Color\", \"b\");\n%!  h_light3 = light (\"Position\", [-1 -1 2], \"Color\", \"g\");\n\n%!demo\n%! ## Diffuse and specular reflection\n%! clf;\n%! h_axes = axes ();\n%! rng = linspace (-0.2, +0.2, 12);\n%! [x,y,z] = meshgrid (rng);\n%! val = (x.^2 + y.^2 + z.^2);\n%!\n%! fv = isosurface (x, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"DiffuseStrength\", 0, \"SpecularStrength\", 0);\n%! isonormals (x, y, z, val, h_patch);\n%! fv = isosurface (x+.5, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"DiffuseStrength\", 0, \"SpecularStrength\", .5);\n%! isonormals (x+.5, y, z, val, h_patch);\n%! fv = isosurface (x+1, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"DiffuseStrength\", 0, \"SpecularStrength\", 1);\n%! isonormals (x+1, y, z, val, h_patch);\n%!\n%! fv = isosurface (x, y+.5, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"DiffuseStrength\", 0.5, \"SpecularStrength\", 0);\n%! isonormals (x, y+.5, z, val, h_patch);\n%! fv = isosurface (x+.5, y+.5, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"DiffuseStrength\", 0.5, \"SpecularStrength\", .5);\n%! isonormals (x+.5, y+.5, z, val, h_patch);\n%! fv = isosurface (x+1, y+.5, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"DiffuseStrength\", 0.5, \"SpecularStrength\", 1);\n%! isonormals (x+1, y+.5, z, val, h_patch);\n%!\n%! fv = isosurface (x, y+1, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"DiffuseStrength\", 1, \"SpecularStrength\", 0);\n%! isonormals (x, y+1, z, val, h_patch);\n%! fv = isosurface (x+.5, y+1, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"DiffuseStrength\", 1, \"SpecularStrength\", .5);\n%! isonormals (x+.5, y+1, z, val, h_patch);\n%! fv = isosurface (x+1, y+1, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"DiffuseStrength\", 1, \"SpecularStrength\", 1);\n%! isonormals (x+1, y+1, z, val, h_patch);\n%!\n%! view (2);\n%! axis equal\n%! h_light = light (\"Position\", [-1 1 1]);\n%!\n%! xlabel (\"SpecularStrength\");\n%! ylabel (\"DiffuseStrength\");\n%! title (\"Effects of SpecularStrength and DiffuseStrength\");\n\n%!demo\n%! ## Ambient Strength and Ambient Light Color\n%! clf;\n%! [x,y,z] = meshgrid (-.2:0.05:.2, -.2:0.05:.2, -.2:0.05:.2);\n%! val = (x.^2 + y.^2 + z.^2);\n%!\n%! h_axes1 = subplot (3,1,3);\n%!  set (h_axes1, \"AmbientLightColor\", \"g\");\n%!  fv = isosurface (x, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  set (h_patch, \"AmbientStrength\", 0);\n%!  isonormals (x, y, z, val, h_patch);\n%!  fv = isosurface (x+.5, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  set (h_patch, \"AmbientStrength\", .7);\n%!  isonormals (x+.5, y, z, val, h_patch);\n%!  fv = isosurface (x+1, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  set (h_patch, \"AmbientStrength\", 1);\n%!  isonormals (x+1, y, z, val, h_patch);\n%!  h_light = light (\"Position\", [-1 1 1]);\n%!  view (2);\n%!  axis tight\n%!  axis equal\n%!  xlabel (\"AmbientStrength\");\n%!  ylabel ({\"AmbientLightColor\", \"[0 1 0]\"});\n%!\n%! h_axes2 = subplot (3,1,2);\n%!  set (h_axes2, \"AmbientLightColor\", [.5 0 1]);\n%!  fv = isosurface (x, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  set (h_patch, \"AmbientStrength\", 0);\n%!  isonormals (x, y, z, val, h_patch);\n%!  fv = isosurface (x+.5, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  set (h_patch, \"AmbientStrength\", .7);\n%!  isonormals (x+.5, y, z, val, h_patch);\n%!  fv = isosurface (x+1, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  set (h_patch, \"AmbientStrength\", 1);\n%!  isonormals (x+1, y, z, val, h_patch);\n%!  h_light = light (\"Position\", [-1 1 1]);\n%!  view (2);\n%!  axis tight\n%!  axis equal\n%!  ylabel ({\"AmbientLightColor\", \"[.5 0 1]\"});\n%!\n%! h_axes3 = subplot (3,1,1);\n%!  set (h_axes3, \"AmbientLightColor\", \"w\");\n%!  fv = isosurface (x, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  set (h_patch, \"AmbientStrength\", 0);\n%!  isonormals (x, y, z, val, h_patch);\n%!  fv = isosurface (x+.5, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  set (h_patch, \"AmbientStrength\", .7);\n%!  isonormals (x+.5, y, z, val, h_patch);\n%!  fv = isosurface (x+1, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                       \"FaceLighting\", \"Gouraud\");\n%!  set (h_patch, \"AmbientStrength\", 1);\n%!  isonormals (x+1, y, z, val, h_patch);\n%!  h_light = light (\"Position\", [-1 1 1]);\n%!  view (2);\n%!  axis tight\n%!  axis equal\n%!  ylabel ({\"AmbientLightColor\", \"[1 1 1]\"});\n%!  title (\"Effects of AmbientLightColor and AmbientStrength\");\n\n%!demo\n%! ## Specular Exponent\n%! clf;\n%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);\n%! val = (x.^2 + y.^2 + z.^2);\n%!\n%! h_axes = axes ();\n%! fv = isosurface (x, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"SpecularExponent\", 15);\n%! isonormals (x, y, z, val, h_patch);\n%! fv = isosurface (x+.5, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"SpecularExponent\", 5);\n%! isonormals (x+.5, y, z, val, h_patch);\n%! fv = isosurface (x+1, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"SpecularExponent\", 1);\n%! isonormals (x+1, y, z, val, h_patch);\n%! h_light = light (\"Position\", [-1 1 1]);\n%! view (2);\n%! axis tight\n%! axis equal\n%! xlabel (\"SpecularExponent\");\n%! title (\"Effects of SpecularExponent\");\n\n%!demo\n%! ## SpecularColorReflectance\n%! clf;\n%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);\n%! val = (x.^2 + y.^2 + z.^2);\n%!\n%! h_axes = axes ();\n%! fv = isosurface (x, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"SpecularColorReflectance\", 0);\n%! isonormals (x, y, z, val, h_patch);\n%! fv = isosurface (x+.5, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"SpecularColorReflectance\", 0.5);\n%! isonormals (x+.5, y, z, val, h_patch);\n%! fv = isosurface (x+1, y, z, val, .039);\n%! h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"SpecularColorReflectance\", 1);\n%! isonormals (x+1, y, z, val, h_patch);\n%! view (2);\n%! h_light = light (\"Position\", [-1 1 1]);\n%! axis tight\n%! axis equal\n%! xlabel (\"SpecularColorReflectance\");\n%! title (\"Effects of SpecularColorReflectance\");\n\n%!demo\n%! ## BackFaceLighting\n%! clf;\n%! [x,y,z] = meshgrid (-.5:0.1:2, -2:0.1:2, -2:0.1:2);\n%! val = x.^2 + y.^2 + z.^2;\n%! fv = isosurface (x, y, z, val, 1);\n%! vn = isonormals (x, y, z, val, fv.vertices);\n%! h_axes1 = subplot (1, 3, 1);\n%! h_patch = patch (fv, \"FaceColor\", \"c\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\", \"VertexNormals\", vn);\n%! set (h_patch, \"BackFaceLighting\", \"reverselit\");\n%! h_light = light ();\n%! view (h_axes1, [-50 30]);\n%! title (\"reverselit\");\n%! axis equal\n%!\n%! h_axes2 = subplot (1, 3, 2);\n%! h_patch = patch (fv, \"FaceColor\", \"c\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\", \"VertexNormals\", -vn);\n%! set (h_patch, \"BackFaceLighting\", \"lit\");\n%! h_light = light ();\n%! view (h_axes2, [-50 30]);\n%! axis equal\n%! title (\"lit\");\n%!\n%! h_axes3 = subplot (1, 3, 3);\n%! h_patch = patch (fv, \"FaceColor\", \"c\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\", \"VertexNormals\", -vn);\n%! set (h_patch, \"BackFaceLighting\", \"unlit\");\n%! h_light = light ();\n%! view (h_axes3, [-50 30]);\n%! axis equal\n%! title (\"unlit\");\n\n%!demo\n%! ## BackFaceLighting 2\n%! ## Matlab fails for \"reverselit\" with negated isonormals and for \"unlit\"\n%! clf;\n%! N = 30; iso = .8;\n%! lin = linspace (-1, 1, N);\n%! [x, y, z] = meshgrid (1.2*lin, 1.2*lin, lin);\n%! val = (x).^2 + (y).^2 - iso/2.7*cos (2*pi*z);\n%! val(x>0 & (y-x)>0) = NaN;\n%! fv = isosurface (x, y, z, val, iso);\n%! vn = isonormals (x, y, z, val, fv.vertices);\n%!\n%! subplot (2, 3, 1);\n%!  view (140, 20);\n%!  axis equal\n%!  hp = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!              \"BackFaceLighting\", \"reverselit\", \"VertexNormals\", -vn);\n%!  hl = light (\"Position\", [1 0 .5]);\n%!  lighting gouraud\n%!  title ({\"BackFaceLighting\", '\"reverselit\"', 'isonormals(...,\"negate\")'});\n%!\n%! subplot (2, 3, 2);\n%!  view (140, 20);\n%!  axis equal\n%!  hp = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!              \"BackFaceLighting\", \"lit\", \"VertexNormals\", -vn);\n%!  hl = light (\"Position\", [1 0 .5]);\n%!  lighting gouraud\n%!  title ({\"BackFaceLighting\", '\"lit\"', 'isonormals(...,\"negate\")'});\n%!\n%! subplot (2, 3, 3);\n%!  view (140, 20);\n%!  axis equal\n%!  hp = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!              \"BackFaceLighting\", \"unlit\", \"VertexNormals\", -vn);\n%!  hl = light (\"Position\", [1 0 .5]);\n%!  lighting gouraud\n%!  title ({\"BackFaceLighting\", '\"unlit\"', 'isonormals(...,\"negate\")'});\n%!\n%! subplot (2, 3, 4);\n%!  view (140, 20);\n%!  axis equal\n%!  hp = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!              \"BackFaceLighting\", \"reverselit\", \"VertexNormals\", vn);\n%!  hl = light (\"Position\", [1 0 .5]);\n%!  lighting gouraud\n%!  title ({\"BackFaceLighting\", '\"reverselit\"', \"isonormals(...)\"});\n%!\n%! subplot (2, 3, 5);\n%!  view (140, 20);\n%!  axis equal\n%!  hp = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!              \"BackFaceLighting\", \"lit\", \"VertexNormals\", vn);\n%!  hl = light (\"Position\", [1 0 .5]);\n%!  lighting gouraud\n%!  title ({\"BackFaceLighting\", '\"lit\"', \"isonormals(...)\"});\n%!\n%! subplot (2, 3, 6);\n%!  view (140, 20);\n%!  axis equal\n%!  hp = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\", ...\n%!              \"BackFaceLighting\", \"unlit\", \"VertexNormals\", vn);\n%!  hl = light (\"Position\", [1 0 .5]);\n%!  lighting gouraud\n%!  title ({\"BackFaceLighting\", '\"unlit\"', \"isonormals(...)\"});\n\n%!demo\n%! ## Colored patch\n%! clf;\n%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);\n%! val = (x.^2 + y.^2 + z.^2);\n%!\n%! h_axes = axes ();\n%! view (3);\n%! fv = isosurface (x, y, z, val, .039, z);\n%! h_patch = patch (fv, \"FaceColor\", \"flat\", \"EdgeColor\", \"none\", ...\n%!                      \"FaceLighting\", \"Gouraud\");\n%! set (h_patch, \"SpecularExponent\", 15);\n%! isonormals (x, y, z, val, h_patch);\n%! h_light = light (\"Position\", [-1 1 1]);\n%! view (3);\n%! axis tight\n%! axis equal\n%! title (\"Colored patch\");\n\n%!demo\n%! ## Colored mesh (patch)\n%! clf;\n%! [x,y,z] = meshgrid (-.2:0.05:.2, -.2:0.05:.2, -.2:0.05:.2);\n%! val = (x.^2 + y.^2 + z.^2);\n%!\n%! h_axes = axes ();\n%! fv = isosurface (x, y, z, val, .039, z);\n%! h_patch = patch (fv, \"FaceColor\", \"w\", \"EdgeColor\", \"interp\");\n%! isonormals (x, y, z, val, h_patch);\n%! h_light = light ();\n%! lighting gouraud\n%! view (3);\n%! axis tight;\n%! axis equal;\n%! box off;\n%! title (\"Colored mesh (patch)\");\n\n%!demo\n%! ## Colored mesh (surface)\n%! clf;\n%! h_mesh = mesh (peaks);\n%! title (\"Colored mesh (surface)\");\n%! h_light = light ();\n%! lighting gouraud\n\n%!demo\n%! ## Light in hggroup\n%! clf;\n%! h_mesh = mesh (peaks);\n%! h_hg = hggroup ();\n%! title (\"Light in hggroup\");\n%! h_light = light (\"Parent\", h_hg);\n%! lighting gouraud\n\n%!demo\n%! ## Style local/infinite\n%! clf;\n%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);\n%! val = (x.^2 + y.^2 + z.^2);\n%!\n%! h_axes1 = subplot (1,2,1);\n%!  fv = isosurface (x, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\");\n%!  isonormals (x, y, z, val, h_patch);\n%!  title ('\"Style\" = \"infinite\" (default)');\n%!  h_light = light (\"Position\", [.3 0 .3]);\n%!  lighting gouraud\n%!  view (3);\n%!  axis equal\n%!\n%! h_axes2 = subplot (1,2,2);\n%!  fv = isosurface (x, y, z, val, .039);\n%!  h_patch = patch (fv, \"FaceColor\", \"r\", \"EdgeColor\", \"none\");\n%!  isonormals (x, y, z, val, h_patch);\n%!  title ('\"Style\" = \"local\"');\n%!  h_light = light (\"Style\", \"local\", \"Position\", [.3 0 .3]);\n%!  lighting gouraud\n%!  view (3);\n%!  axis equal\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = light ();\n%!   assert (findobj (hf, \"Type\", \"light\"), h);\n%!   assert (get (h, \"Position\"), [1, 0, 1]);\n%!   assert (get (h, \"Color\"), [1, 1, 1]);\n%!   assert (get (h, \"Style\"), \"infinite\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! ha = gca ();\n%! unwind_protect\n%!   h = light (ha, \"Position\", [1 2 3], \"Color\", \"r\");\n%!   assert (get (h, \"Position\"), [1 2 3]);\n%!   assert (get (h, \"Color\"), [1 0 0]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/lightangle.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} lightangle (@var{az}, @var{el})\n## @deftypefnx {} {} lightangle (@var{hax}, @var{az}, @var{el})\n## @deftypefnx {} {} lightangle (@var{hl}, @var{az}, @var{el})\n## @deftypefnx {} {@var{hl} =} lightangle (@dots{})\n## @deftypefnx {} {[@var{az}, @var{el}] =} lightangle (@var{hl})\n## Add a light object to the current axes using spherical coordinates.\n##\n## The light position is specified by an azimuthal rotation @var{az} and an\n## elevation angle @var{el}, both in degrees.\n##\n## If the first argument @var{hax} is an axes handle, then create a new light\n## object in this axes, rather than the current axes returned by @code{gca}.\n##\n## If the first argument @var{hl} is a handle to a light object, then act on\n## this light object rather than creating a new object.\n##\n## The optional return value @var{hl} is a graphics handle to the light object.\n##\n## Example:\n##\n## Add a light object to a plot\n##\n## @example\n## @group\n## @c doctest: +SKIP\n## clf;\n## sphere (36);\n## lightangle (45, 30);\n## @end group\n## @end example\n##\n## @seealso{light, view, camlight}\n## @end deftypefn\n\nfunction varargout = lightangle (varargin)\n\n  if (nargin == 0 || nargin > 3 || nargout > 2 || (nargin > 1 && nargout > 1))\n    print_usage ();\n  endif\n\n  hl = hax = az = el = [];\n\n  if (nargin == 1)\n    hl = varargin{1};\n    if (! isscalar (hl) || ! isgraphics (hl, \"light\"))\n      error (\"lightangle: HL must be a handle to a light object\");\n    endif\n  elseif (nargin == 2)\n    az = varargin{1};\n    el = varargin{2};\n  elseif (nargin == 3)\n    h = varargin{1};\n    if (isscalar (h) && isaxes (h))\n      hax = h;\n    elseif (isscalar (h) && isgraphics (h, \"light\"))\n      hl = h;\n    else\n      error (\"lightangle: H must be a handle to an axes or light object\");\n    endif\n    az = varargin{2};\n    el = varargin{3};\n  endif\n\n  if (nargin == 1)\n    pos = get (hl, \"Position\");\n    [az, el] = cart2sph (pos(1), pos(2), pos(3));\n    az = rad2deg (az) + 90;  # see view.m\n    el = rad2deg (el);\n    varargout = { az, el };\n    return;\n  endif\n\n  if (! isscalar (az) || ! isnumeric (az)\n      || ! isscalar (el) || ! isnumeric (el))\n    error (\"lightangle: AZ and EL must be numeric scalars\");\n  endif\n\n  if (! isempty (hl))\n    hax = ancestor (hl, \"axes\");\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  if (isempty (hl))\n    hl = light (hax);\n  endif\n\n  pos = get (hl, \"Position\");\n\n  az = deg2rad (az - 90);\n  el = deg2rad (el);\n\n  if (strcmp (get (hl, \"Style\"), \"local\"))\n    pos -= get (hax, \"CameraTarget\");\n  endif\n\n  [pos(1), pos(2), pos(3)] = sph2cart (az, el, norm (pos));\n\n  if (strcmp (get (hl, \"Style\"), \"local\"))\n    pos += get (hax, \"CameraTarget\");\n  endif\n\n  set (hl, \"Position\", pos);\n\n  if (nargout == 1)\n    varargout = { hl };\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! sphere (36);\n%! lightangle (45, 30);\n%! title (\"lightangle() demo #1\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   sphere (24);\n%!   hl = lightangle (45, 20);\n%!   assert (isgraphics (hl, \"light\"));\n%!   [az, el] = lightangle (hl);\n%!   assert ([45, 20], [az, el], -20*eps);\n%!   lightangle (hl, 90, 45);\n%!   [az, el] = lightangle (hl);\n%!   assert ([90, 45], [az, el], -20*eps);\n%!   pos = get (hl, \"Position\");\n%!   assert ([1, 0, 1], pos, -20*eps);\n%!   hl = lightangle (gca (), 45, 20);\n%!   assert (isgraphics (hl, \"light\"));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> lightangle ()\n%!error <Invalid call> lightangle (1, 2, 3, 4)\n%!error <Invalid call> [a, b, c] = lightangle (45, 30)\n%!error <Invalid call> [a, b] = lightangle (45, 30)\n%!error <HL must be a handle to a light object> lightangle (0)\n%!error <H must be a handle to an axes or light object> lightangle (0, 90, 45)\n%!error <AZ and EL must be numeric scalars> lightangle ([1 2], 0)\n%!error <AZ and EL must be numeric scalars> lightangle ({1}, 0)\n%!error <AZ and EL must be numeric scalars> lightangle (0, [1 2])\n%!error <AZ and EL must be numeric scalars> lightangle (0, {1})\n"
  },
  {
    "path": "scripts/plot/draw/line.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} line ()\n## @deftypefnx {} {} line (@var{x}, @var{y})\n## @deftypefnx {} {} line (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} line (\"xdata\", @var{x}, \"ydata\", @var{y})\n## @deftypefnx {} {} line (\"xdata\", @var{x}, \"ydata\", @var{y}, \"zdata\", @var{z})\n## @deftypefnx {} {} line (@dots{}, @var{property}, @var{value})\n## @deftypefnx {} {} line (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} line (@dots{})\n## Create a line object from @var{x} and @var{y} (and possibly @var{z}) and\n## insert it in the current axes.\n##\n## In the standard calling form the data @var{x}, @var{y}, and @var{z} may be\n## scalars, vectors, or matrices.  In the case of matrix inputs, @code{line}\n## will attempt to orient scalars and vectors so the results can be plotted.\n## This requires that one of the dimensions of the vector match either the\n## number of rows or the number of columns of the matrix.\n##\n## In the low-level calling form (50% higher performance) where the data is\n## specified by name (@code{line (\"xdata\", @var{x}, @dots{})}) the data must be\n## vectors.  If no data is specified (@code{line ()}) then\n## @w{@code{@var{x} == @var{y} = [0, 1]}}.\n##\n## Multiple property-value pairs may be specified for the line object, but they\n## must appear in pairs.\n##\n## If called with only @var{property}/@var{value} pairs then any unspecified\n## properties use their default values as specified on the root object.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle (or vector of\n## handles) to the line objects created.\n##\n## Programming Note: The full list of properties is documented at\n## @ref{Line Properties}.\n##\n## The function @code{line} differs from @code{plot} in that line objects are\n## inserted in to the current axes without first clearing the plot.\n## @seealso{image, patch, rectangle, surface, text}\n## @end deftypefn\n\nfunction h = line (varargin)\n\n  ## Get axis argument which may be in a 'parent' PROP/VAL pair\n  [hax, varargin] = __plt_get_axis_arg__ (\"line\", varargin{:});\n\n  if (isempty (hax))\n    hax = gca ();\n    oldfig = [];\n  else\n    hax = hax(1);\n    oldfig = get (0, \"currentfigure\");\n    set (0, \"currentfigure\", ancestor (hax, \"figure\"));\n  endif\n\n  unwind_protect\n    htmp = __line__ (hax, varargin{:});\n  unwind_protect_cleanup\n    if (! isempty (oldfig))\n      set (0, \"currentfigure\", oldfig);\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! line ([0 1], [0.8 0.8], \"linestyle\", \"-\", \"color\", \"b\");\n%! line ([0 1], [0.6 0.6], \"linestyle\", \"--\", \"color\", \"g\");\n%! line ([0 1], [0.4 0.4], \"linestyle\", \":\", \"color\", \"r\");\n%! line ([0 1], [0.2 0.2], \"linestyle\", \"-.\", \"color\", \"k\");\n%! ylim ([0 1]);\n%! title (\"line() with various linestyles\");\n%! legend ('\"-\"', '\"--\"', '\":\"', '\"-.\"', 'location', 'eastoutside');\n\n%!demo\n%! clf;\n%! x = 0:0.3:10;\n%! y1 = cos (x);\n%! y2 = sin (x);\n%! subplot (3,1,1);\n%!  args = {\"color\", \"b\", \"marker\", \"s\"};\n%!  line ([x(:), x(:)], [y1(:), y2(:)], args{:});\n%!  title (\"Test broadcasting for line()\");\n%! subplot (3,1,2);\n%!  line (x(:), [y1(:), y2(:)], args{:});\n%! subplot (3,1,3);\n%!  line ([x(:), x(:)+pi/2], y1(:), args{:});\n%!  xlim ([0 10]);\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = line ();\n%!   assert (findobj (hf, \"type\", \"line\"), h);\n%!   assert (get (h, \"xdata\"), [0 1], eps);\n%!   assert (get (h, \"ydata\"), [0 1], eps);\n%!   assert (get (h, \"type\"), \"line\");\n%!   assert (get (h, \"color\"), get (0, \"defaultlinecolor\"));\n%!   assert (get (h, \"linestyle\"), get (0, \"defaultlinelinestyle\"));\n%!   assert (get (h, \"linewidth\"), get (0, \"defaultlinelinewidth\"), eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/loglog.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} loglog (@var{y})\n## @deftypefnx {} {} loglog (@var{x}, @var{y})\n## @deftypefnx {} {} loglog (@var{x}, @var{y}, @var{prop}, @var{value}, @dots{})\n## @deftypefnx {} {} loglog (@var{x}, @var{y}, @var{fmt})\n## @deftypefnx {} {} loglog (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} loglog (@dots{})\n## Produce a 2-D plot using logarithmic scales for both axes.\n##\n## See the documentation of @code{plot} for a description of the arguments\n## that @code{loglog} will accept.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n## @seealso{plot, semilogx, semilogy}\n## @end deftypefn\n\nfunction h = loglog (varargin)\n\n  [hax, varargin, nargs] = __plt_get_axis_arg__ (\"loglog\", varargin{:});\n\n  if (nargs < 1)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n\n  set (hax, \"xscale\", \"log\", \"yscale\", \"log\");\n  if (! ishold (hax))\n    set (hax, \"xminortick\", \"on\", \"yminortick\", \"on\", \"box\", \"on\");\n  endif\n\n  htmp = __plt__ (\"loglog\", hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! t = 1:0.01:10;\n%! x = sort ((t .* (1 + rand (size (t)))) .^ 2);\n%! y = (t .* (1 + rand (size (t)))) .^ 2;\n%! loglog (x, y);\n%! title ({\"loglog() plot\", \"Both axes are logarithmic\"});\n\n%!demo\n%! clf;\n%! a = logspace (-5, 1, 10);\n%! b =-logspace (-5, 1, 10);\n%!\n%! subplot (1,2,1);\n%!  loglog (a, b);\n%!  title (\"loglog (a, b)\");\n%!\n%! subplot (1,2,2);\n%!  loglog (a, abs (b));\n%!  set (gca, \"ydir\", \"reverse\");\n%!  title (\"loglog (a, abs (b))\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   a = logspace (-5, 1, 10);\n%!   b = logspace (-5, 1, 10);\n%!   loglog (a, b);\n%!   assert (get (gca, \"yscale\"), \"log\");\n%!   assert (get (gca, \"xscale\"), \"log\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   a = logspace (-5, 1, 10);\n%!   b =-logspace (-5, 1, 10);\n%!   loglog (a, b);\n%!   axis tight;\n%!   assert (all (get (gca, \"ytick\") < 0));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/loglogerr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} loglogerr (@var{y}, @var{ey})\n## @deftypefnx {} {} loglogerr (@var{y}, @dots{}, @var{fmt})\n## @deftypefnx {} {} loglogerr (@var{x}, @var{y}, @var{ey})\n## @deftypefnx {} {} loglogerr (@var{x}, @var{y}, @var{err}, @var{fmt})\n## @deftypefnx {} {} loglogerr (@var{x}, @var{y}, @var{lerr}, @var{uerr}, @var{fmt})\n## @deftypefnx {} {} loglogerr (@var{x}, @var{y}, @var{ex}, @var{ey}, @var{fmt})\n## @deftypefnx {} {} loglogerr (@var{x}, @var{y}, @var{lx}, @var{ux}, @var{ly}, @var{uy}, @var{fmt})\n## @deftypefnx {} {} loglogerr (@var{x1}, @var{y1}, @dots{}, @var{fmt}, @var{xn}, @var{yn}, @dots{})\n## @deftypefnx {} {} loglogerr (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} loglogerr (@dots{})\n## Produce 2-D plots on a double logarithm axis with errorbars.\n##\n## Many different combinations of arguments are possible.  The most common\n## form is\n##\n## @example\n## loglogerr (@var{x}, @var{y}, @var{ey}, @var{fmt})\n## @end example\n##\n## @noindent\n## which produces a double logarithm plot of @var{y} versus @var{x} with errors\n## in the @var{y}-scale defined by @var{ey} and the plot format defined by\n## @var{fmt}.  @xref{XREFerrorbar,,errorbar}, for available formats and\n## additional information.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n## @seealso{errorbar, semilogxerr, semilogyerr}\n## @end deftypefn\n\nfunction h = loglogerr (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"loglogerr\", varargin{:});\n\n  hax = newplot (hax);\n\n  set (hax, \"xscale\", \"log\", \"yscale\", \"log\");\n  if (! ishold (hax))\n    set (hax, \"xminortick\", \"on\", \"yminortick\", \"on\", \"box\", \"on\");\n  endif\n\n  htmp = __errplot__ (\"loglogerr\", hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = exp (log (0.01):0.2:log (10));\n%! wblpdf = @(x, scl, shp) shp*(scl^-shp) .* x.^(shp-1) .* exp (-(x/scl).^shp);\n%! y = wblpdf (x, 3, 2);\n%! eyu = 2*rand (size (y)) .* y;\n%! eyl = 0.5*rand (size (y)) .* y;\n%! loglogerr (x, y, eyl, eyu, \"#~x-\");\n%! xlim (x([1, end]));\n%! title ({\"loglogerr(): loglog() plot with errorbars\", ...\n%!         \"Both axes are logarithmic\"});\n"
  },
  {
    "path": "scripts/plot/draw/mesh.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} mesh (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} mesh (@var{z})\n## @deftypefnx {} {} mesh (@dots{}, @var{c})\n## @deftypefnx {} {} mesh (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} mesh (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} mesh (@dots{})\n## Plot a 3-D wireframe mesh.\n##\n## The wireframe mesh is plotted using rectangles.  The vertices of the\n## rectangles [@var{x}, @var{y}] are typically the output of @code{meshgrid}.\n## over a 2-D rectangular region in the x-y plane.  @var{z} determines the\n## height above the plane of each vertex.  If only a single @var{z} matrix is\n## given, then it is plotted over the meshgrid\n## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})}.\n## Thus, columns of @var{z} correspond to different @var{x} values and rows\n## of @var{z} correspond to different @var{y} values.\n##\n## The color of the mesh is computed by linearly scaling the @var{z} values\n## to fit the range of the current colormap.  Use @code{clim} and/or\n## change the colormap to control the appearance.\n##\n## Optionally, the color of the mesh can be specified independently of @var{z}\n## by supplying a color matrix, @var{c}.\n##\n## Any property/value pairs are passed directly to the underlying surface\n## object.  The full list of properties is documented at\n## @ref{Surface Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## @seealso{ezmesh, meshc, meshz, trimesh, contour, surf, surface, meshgrid,\n## hidden, shading, colormap, clim}\n## @end deftypefn\n\nfunction h = mesh (varargin)\n\n  if (! all (cellfun (\"isreal\", varargin)))\n    error (\"mesh: X, Y, Z, C arguments must be real\");\n  endif\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"mesh\", varargin{:});\n\n  hax = newplot (hax);\n\n  mesh_props = {\"facecolor\", \"w\", \"edgecolor\", \"flat\", ...\n                \"facelighting\", \"none\", \"edgelighting\", \"flat\"};\n  chararg = find (cellfun (\"isclass\", varargin, \"char\"), 1);\n  if (isempty (chararg))\n    htmp = surface (hax, varargin{:}, mesh_props{:});\n  else\n    htmp = surface (hax, varargin{1:chararg-1}, mesh_props{:},\n                         varargin{chararg:end});\n  endif\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = logspace (0,1,11);\n%! z = x'*x;\n%! mesh (x, x, z);\n%! xlabel \"X-axis\";\n%! ylabel \"Y-axis\";\n%! zlabel \"Z-axis\";\n%! title (\"mesh() with color proportional to height\");\n\n%!demo\n%! clf;\n%! x = logspace (0,1,11);\n%! z = x'*x;\n%! mesh (x, x, z, z.^2);\n%! xlabel \"X-axis\";\n%! ylabel \"Y-axis\";\n%! zlabel \"linear scale\";\n%! title (\"mesh() with color proportional to Z^2\");\n\n%!demo\n%! clf;\n%! x = logspace (0,1,11);\n%! z = x'*x;\n%! mesh (x, x, z, z.^2);\n%! set (gca, \"zscale\", \"log\");\n%! xlabel \"X-axis\";\n%! ylabel \"Y-axis\";\n%! zlabel \"log scale\";\n%! title ({\"mesh() with color proportional to Z^2\", \"Z-axis is log scale\"});\n%! try\n%!   if (strcmp (get (gcf, \"__graphics_toolkit__\"), \"gnuplot\"))\n%!     title ({\"Gnuplot: mesh color is wrong\", \"This is a Gnuplot bug\"});\n%!   endif\n%! catch\n%! end_try_catch\n\n%!demo\n%! clf;\n%! x = logspace (0,1,11);\n%! z = x'*x;\n%! mesh (x, x, z, \"facecolor\", \"none\", \"edgecolor\", \"c\");\n%! xlabel \"X-axis\";\n%! ylabel \"Y-axis\";\n%! zlabel \"Z-axis\";\n%! title ({\"mesh() default properties overridden\", ...\n%!         \"transparent mesh with cyan color\"});\n"
  },
  {
    "path": "scripts/plot/draw/meshc.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} meshc (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} meshc (@var{z})\n## @deftypefnx {} {} meshc (@dots{}, @var{c})\n## @deftypefnx {} {} meshc (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} meshc (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} meshc (@dots{})\n## Plot a 3-D wireframe mesh with underlying contour lines.\n##\n## The wireframe mesh is plotted using rectangles.  The vertices of the\n## rectangles [@var{x}, @var{y}] are typically the output of @code{meshgrid}.\n## over a 2-D rectangular region in the x-y plane.  @var{z} determines the\n## height above the plane of each vertex.  If only a single @var{z} matrix is\n## given, then it is plotted over the meshgrid\n## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})}.\n## Thus, columns of @var{z} correspond to different @var{x} values and rows\n## of @var{z} correspond to different @var{y} values.\n##\n## The color of the mesh is computed by linearly scaling the @var{z} values\n## to fit the range of the current colormap.  Use @code{clim} and/or\n## change the colormap to control the appearance.\n##\n## Optionally the color of the mesh can be specified independently of @var{z}\n## by supplying a color matrix, @var{c}.\n##\n## Any property/value pairs are passed directly to the underlying surface\n## object.  The full list of properties is documented at\n## @ref{Surface Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a 2-element vector with a graphics\n## handle to the created surface object and to the created contour plot.\n##\n## @seealso{ezmeshc, mesh, meshz, contour, surfc, surface, meshgrid, hidden,\n## shading, colormap, clim}\n## @end deftypefn\n\nfunction h = meshc (varargin)\n\n  if (! all (cellfun (\"isreal\", varargin)))\n    error (\"meshc: X, Y, Z, C arguments must be real\");\n  endif\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"meshc\", varargin{:});\n\n  hax = newplot (hax);\n\n  ## FIXME: gnuplot does not support a filled surface and a\n  ##        non-filled contour.  3-D filled patches are also not supported.\n  ##        Thus, the facecolor will be transparent for the gnuplot backend.\n  mesh_props = {\"facecolor\", \"w\", \"edgecolor\", \"flat\", ...\n                \"facelighting\", \"none\", \"edgelighting\", \"flat\"};\n  chararg = find (cellfun (\"isclass\", varargin, \"char\"), 1);\n  if (isempty (chararg))\n    htmp = surface (hax, varargin{:}, mesh_props{:});\n  else\n    htmp = surface (hax, varargin{1:chararg-1}, mesh_props{:},\n                         varargin{chararg:end});\n  endif\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\",\n              \"xlimmode\", \"manual\", \"ylimmode\", \"manual\");\n  endif\n\n  drawnow ();\n\n  zmin = get (hax, \"zlim\")(1);\n  [~, htmp2] = __contour__ (hax, zmin, varargin{:});\n\n  htmp = [htmp; htmp2];\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [X, Y] = meshgrid (linspace (-3, 3, 40));\n%! Z = sqrt (abs (X .* Y)) ./ (1 + X.^2 + Y.^2);\n%! meshc (X, Y, Z);\n%! title (\"meshc() combines mesh/contour plots\");\n"
  },
  {
    "path": "scripts/plot/draw/meshz.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} meshz (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} meshz (@var{z})\n## @deftypefnx {} {} meshz (@dots{}, @var{c})\n## @deftypefnx {} {} meshz (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} meshz (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} meshz (@dots{})\n## Plot a 3-D wireframe mesh with a surrounding curtain.\n##\n## The wireframe mesh is plotted using rectangles.  The vertices of the\n## rectangles [@var{x}, @var{y}] are typically the output of @code{meshgrid}.\n## over a 2-D rectangular region in the x-y plane.  @var{z} determines the\n## height above the plane of each vertex.  If only a single @var{z} matrix is\n## given, then it is plotted over the meshgrid\n## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})}.\n## Thus, columns of @var{z} correspond to different @var{x} values and rows\n## of @var{z} correspond to different @var{y} values.\n##\n## The color of the mesh is computed by linearly scaling the @var{z} values\n## to fit the range of the current colormap.  Use @code{clim} and/or\n## change the colormap to control the appearance.\n##\n## Optionally the color of the mesh can be specified independently of @var{z}\n## by supplying a color matrix, @var{c}.\n##\n## Any property/value pairs are passed directly to the underlying surface\n## object.  The full list of properties is documented at\n## @ref{Surface Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## @seealso{mesh, meshc, contour, surf, surface, waterfall, meshgrid, hidden,\n## shading, colormap, clim}\n## @end deftypefn\n\nfunction h = meshz (varargin)\n\n  if (! all (cellfun (\"isreal\", varargin)))\n    error (\"meshz: X, Y, Z, C arguments must be real\");\n  endif\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"meshz\", varargin{:});\n\n  ## Find where property/value pairs start\n  charidx = find (cellfun (\"isclass\", varargin, \"char\"), 1);\n\n  if (isempty (charidx))\n    charidx = nargin + 1;\n  endif\n\n  if (nargin == 1)\n    z = varargin{1};\n    [m, n] = size (z);\n    x = 1:n;\n    y = (1:m).';\n    c = z;\n  elseif (nargin == 2)\n    z = varargin{1};\n    [m, n] = size (z);\n    x = 1:n;\n    y = (1:m).';\n    c = varargin{2};\n  elseif (charidx == 4)\n    x = varargin{1};\n    y = varargin{2};\n    z = varargin{3};\n    c = z;\n  else\n    x = varargin{1};\n    y = varargin{2};\n    z = varargin{3};\n    c = varargin{4};\n  endif\n\n  ## Create a border of one rectangle (2 points) as the curtain around\n  ## the data and draw it with the mean (max + min / 2) color of the data.\n\n  if (isvector (x) && isvector (y))\n    x = [x(1), x(1), x(:).', x(end), x(end)];\n    y = [y(1); y(1); y(:); y(end); y(end)];\n  else\n    x = [x(1,1), x(1,1), x(1,:), x(1,end), x(1,end);\n         x(1,1), x(1,1), x(1,:), x(1,end), x(1,end);\n         x(:,1), x(:,1), x, x(:,end), x(:,end);\n         x(end,1), x(end,1), x(end,:), x(end,end), x(end,end);\n         x(end,1), x(end,1), x(end,:), x(end,end), x(end,end) ];\n    y = [y(1,1), y(1,1), y(1,:), y(1,end), y(1,end);\n         y(1,1), y(1,1), y(1,:), y(1,end), y(1,end);\n         y(:,1), y(:,1), y, y(:,end), y(:,end);\n         y(end,1), y(end,1), y(end,:), y(end,end), y(end,end);\n         y(end,1), y(end,1), y(end,:), y(end,end), y(end,end) ];\n  endif\n\n  zref = min (z(isfinite (z)));\n  z = [zref .* ones(1, columns(z) + 4);\n       zref .* ones(1, 2), z(1,:), zref .* ones(1, 2);\n       zref .* ones(rows(z), 1), z(:,1),z, z(:,end), zref .* ones(rows(z), 1);\n       zref .* ones(1, 2), z(end,:), zref .* ones(1, 2);\n       zref .* ones(1, columns(z) + 4)];\n\n  cdat = c(isfinite (c(:)));\n  cref = (min (cdat) + max (cdat)) / 2;\n  c = [cref .* ones(2, columns(c) + 4);\n       cref .* ones(rows(c), 2), c, cref .* ones(rows(c), 2);\n       cref .* ones(2, columns(c) + 4)];\n\n  hax = newplot (hax);\n  htmp = mesh (hax, x, y, z, c, varargin{charidx:end});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! Z = peaks ();\n%! meshz (Z);\n%! title (\"meshz() plot of peaks() function\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! Z = peaks ();\n%! subplot (1,2,1)\n%!  mesh (Z);\n%!  daspect ([2.5, 2.5, 1]);\n%!  title (\"mesh() plot\");\n%! subplot (1,2,2)\n%!  meshz (Z);\n%!  daspect ([2.5, 2.5, 1]);\n%!  title (\"meshz() plot\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [X,Y,Z] = peaks ();\n%! [fx, fy] = gradient (Z);\n%! C = sqrt (fx.^2 + fy.^2);\n%! meshz (X,Y,Z,C);\n%! title (\"meshz() plot with color determined by gradient\");\n"
  },
  {
    "path": "scripts/plot/draw/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__add_datasource__.m \\\n  %reldir%/private/__bar__.m \\\n  %reldir%/private/__calc_isovalue_from_data__.m \\\n  %reldir%/private/__contour__.m \\\n  %reldir%/private/__errplot__.m \\\n  %reldir%/private/__ezplot__.m \\\n  %reldir%/private/__gnuplot_scatter__.m \\\n  %reldir%/private/__interp_cube__.m \\\n  %reldir%/private/__line__.m \\\n  %reldir%/private/__marching_cube__.m \\\n  %reldir%/private/__patch__.m \\\n  %reldir%/private/__pie__.m \\\n  %reldir%/private/__plt__.m \\\n  %reldir%/private/__quiver__.m \\\n  %reldir%/private/__scatter__.m \\\n  %reldir%/private/__stem__.m \\\n  %reldir%/private/__unite_shared_vertices__.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/area.m \\\n  %reldir%/bar.m \\\n  %reldir%/barh.m \\\n  %reldir%/camlight.m \\\n  %reldir%/colorbar.m \\\n  %reldir%/comet.m \\\n  %reldir%/comet3.m \\\n  %reldir%/compass.m \\\n  %reldir%/contour.m \\\n  %reldir%/contour3.m \\\n  %reldir%/contourc.m \\\n  %reldir%/contourf.m \\\n  %reldir%/cylinder.m \\\n  %reldir%/ellipsoid.m \\\n  %reldir%/errorbar.m \\\n  %reldir%/ezcontour.m \\\n  %reldir%/ezcontourf.m \\\n  %reldir%/ezmesh.m \\\n  %reldir%/ezmeshc.m \\\n  %reldir%/ezplot.m \\\n  %reldir%/ezplot3.m \\\n  %reldir%/ezpolar.m \\\n  %reldir%/ezsurf.m \\\n  %reldir%/ezsurfc.m \\\n  %reldir%/feather.m \\\n  %reldir%/fill.m \\\n  %reldir%/fill3.m \\\n  %reldir%/fplot.m \\\n  %reldir%/hist.m \\\n  %reldir%/isocaps.m \\\n  %reldir%/isocolors.m \\\n  %reldir%/isonormals.m \\\n  %reldir%/isosurface.m \\\n  %reldir%/light.m \\\n  %reldir%/lightangle.m \\\n  %reldir%/line.m \\\n  %reldir%/loglog.m \\\n  %reldir%/loglogerr.m \\\n  %reldir%/mesh.m \\\n  %reldir%/meshc.m \\\n  %reldir%/meshz.m \\\n  %reldir%/ostreamtube.m \\\n  %reldir%/pareto.m \\\n  %reldir%/patch.m \\\n  %reldir%/pcolor.m \\\n  %reldir%/peaks.m \\\n  %reldir%/pie.m \\\n  %reldir%/pie3.m \\\n  %reldir%/plot.m \\\n  %reldir%/plot3.m \\\n  %reldir%/plotmatrix.m \\\n  %reldir%/plotyy.m \\\n  %reldir%/polar.m \\\n  %reldir%/quiver.m \\\n  %reldir%/quiver3.m \\\n  %reldir%/rectangle.m \\\n  %reldir%/reducepatch.m \\\n  %reldir%/reducevolume.m \\\n  %reldir%/ribbon.m \\\n  %reldir%/rose.m \\\n  %reldir%/scatter.m \\\n  %reldir%/scatter3.m \\\n  %reldir%/semilogx.m \\\n  %reldir%/semilogxerr.m \\\n  %reldir%/semilogy.m \\\n  %reldir%/semilogyerr.m \\\n  %reldir%/shrinkfaces.m \\\n  %reldir%/slice.m \\\n  %reldir%/smooth3.m \\\n  %reldir%/sombrero.m \\\n  %reldir%/sphere.m \\\n  %reldir%/stairs.m \\\n  %reldir%/stem.m \\\n  %reldir%/stem3.m \\\n  %reldir%/stemleaf.m \\\n  %reldir%/stream2.m \\\n  %reldir%/stream3.m \\\n  %reldir%/streamline.m \\\n  %reldir%/streamribbon.m \\\n  %reldir%/streamtube.m \\\n  %reldir%/surf.m \\\n  %reldir%/surface.m \\\n  %reldir%/surfc.m \\\n  %reldir%/surfl.m \\\n  %reldir%/surfnorm.m \\\n  %reldir%/tetramesh.m \\\n  %reldir%/trimesh.m \\\n  %reldir%/triplot.m \\\n  %reldir%/trisurf.m \\\n  %reldir%/xline.m \\\n  %reldir%/yline.m \\\n  %reldir%/waterfall.m\n\n%canon_reldir%dir = $(fcnfiledir)/plot/draw\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/plot/draw/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/plot/draw/ostreamtube.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ostreamtube (@var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} ostreamtube (@var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} ostreamtube (@var{xyz}, @var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w})\n## @deftypefnx {} {} ostreamtube (@dots{}, @var{options})\n## @deftypefnx {} {} ostreamtube (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ostreamtube (@dots{})\n## Calculate and display streamtubes.\n##\n## Streamtubes are approximated by connecting circular crossflow areas\n## along a streamline.  The expansion of the flow is determined by the local\n## crossflow divergence.\n##\n## The vector field is given by @code{[@var{u}, @var{v}, @var{w}]} and is\n## defined over a rectangular grid given by @code{[@var{x}, @var{y}, @var{z}]}.\n## The streamtubes start at the seed points\n## @code{[@var{sx}, @var{sy}, @var{sz}]}.\n##\n## The tubes are colored based on the local vector field strength.\n##\n## The input parameter @var{options} is a 2-D vector of the form\n## @code{[@var{scale}, @var{n}]}.  The first parameter scales the start radius\n## of the streamtubes (default 1).  The second parameter specifies the number\n## of vertices that are used to construct the tube circumference (default 20).\n##\n## @code{ostreamtube} can be called with a cell array containing pre-computed\n## streamline data.  To do this, @var{xyz} must be created with the\n## @code{stream3} function.  This option is useful if you need to alter the\n## integrator step size or the maximum number of vertices of the streamline.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the plot\n## objects created for each streamtube.\n##\n## Example:\n##\n## @example\n## @group\n## [x, y, z] = meshgrid (-1:0.1:1, -1:0.1:1, -3:0.1:0);\n## u = -x / 10 - y;\n## v = x - y / 10;\n## w = - ones (size (x)) / 10;\n## ostreamtube (x, y, z, u, v, w, 1, 0, 0);\n## @end group\n## @end example\n##\n## @seealso{stream3, streamline, streamribbon, streamtube}\n## @end deftypefn\n\n## References:\n##\n## @inproceedings{\n##    title = {Visualization of 3-D vector fields - Variations on a stream},\n##    author = {Dave Darmofal and Robert Haimes},\n##    year = {1992}\n## }\n##\n## @article{\n##    title = {Efficient streamline, streamribbon, and streamtube constructions on unstructured grids},\n##    author = {Ueng, Shyh-Kuang and Sikorski, C. and Ma, Kwan-Liu},\n##    year = {1996},\n##    month = {June},\n##    publisher = {IEEE Transactions on Visualization and Computer Graphics},\n## }\n\nfunction h = ostreamtube (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"ostreamtube\", varargin{:});\n\n  options = [];\n  xyz = [];\n  switch (nargin)\n    case 6\n      [u, v, w, spx, spy, spz] = varargin{:};\n      [m, n, p] = size (u);\n      [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n    case 7\n      if (iscell (varargin{1}))\n        [xyz, x, y, z, u, v, w] = varargin{:};\n      else\n        [u, v, w, spx, spy, spz, options] = varargin{:};\n        [m, n, p] = size (u);\n        [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n      endif\n    case 8\n      [xyz, x, y, z, u, v, w, options] = varargin{:};\n    case 9\n      [x, y, z, u, v, w, spx, spy, spz] = varargin{:};\n    case 10\n      [x, y, z, u, v, w, spx, spy, spz, options] = varargin{:};\n    otherwise\n      print_usage ();\n  endswitch\n\n  scale = 1;\n  num_circum = 20;\n  if (! isempty (options))\n    switch (numel (options))\n      case 1\n        scale = options(1);\n      case 2\n        scale = options(1);\n        num_circum = options(2);\n      otherwise\n        error (\"ostreamtube: OPTIONS must be a 1- or 2-element vector\");\n    endswitch\n\n    if (! isreal (scale) || scale <= 0)\n      error (\"ostreamtube: SCALE must be a real scalar > 0\");\n    endif\n    if (! isreal (num_circum) || num_circum < 3)\n      error (\"ostreamtube: number of tube vertices N must be greater than 2\");\n    endif\n    num_circum = fix (num_circum);\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  if (isempty (xyz))\n    xyz = stream3 (x, y, z, u, v, w, spx, spy, spz, 0.2);\n  endif\n\n  div = divergence (x, y, z, u, v, w);\n\n  ## Use the bounding box diagonal to determine the starting radius\n  mxx = mnx = mxy = mny = mxz = mnz = [];\n  j = 1;\n  for i = 1 : length (xyz)\n    sl = xyz{i};\n    if (! isempty (sl))\n      slx = sl(:,1); sly = sl(:,2); slz = sl(:,3);\n      mxx(j) = max (slx); mnx(j) = min (slx);\n      mxy(j) = max (sly); mny(j) = min (sly);\n      mxz(j) = max (slz); mnz(j) = min (slz);\n      j += 1;\n    endif\n  endfor\n  dx = max (mxx) - min (mnx);\n  dy = max (mxy) - min (mny);\n  dz = max (mxz) - min (mnz);\n  rstart = scale * sqrt (dx*dx + dy*dy + dz*dz) / 25;\n\n  h = [];\n  for i = 1 : length (xyz)\n    sl = xyz{i};\n    num_vertices = rows (sl);\n    if (! isempty (sl) && num_vertices > 2)\n\n      usl = interp3 (x, y, z, u, sl(:,1), sl(:,2), sl(:,3));\n      vsl = interp3 (x, y, z, v, sl(:,1), sl(:,2), sl(:,3));\n      wsl = interp3 (x, y, z, w, sl(:,1), sl(:,2), sl(:,3));\n      vv = sqrt (usl.*usl + vsl.*vsl + wsl.*wsl);\n\n      div_sl = interp3 (x, y, z, div, sl(:,1), sl(:,2), sl(:,3));\n      is_singular_div = find (isnan (div_sl), 1, \"first\");\n\n      if (! isempty (is_singular_div))\n        max_vertices = is_singular_div - 1;\n      else\n        max_vertices = num_vertices;\n      endif\n\n      if (max_vertices > 2)\n\n        htmp = plottube (hax, sl, div_sl, vv, max_vertices, ...\n                         rstart, num_circum);\n        h = [h; htmp];\n\n      endif\n    endif\n  endfor\n\nendfunction\n\nfunction h = plottube (hax, sl, div_sl, vv, max_vertices, rstart, num_circum)\n\n  phi = linspace (0, 2*pi, num_circum);\n  cp = cos (phi);\n  sp = sin (phi);\n\n  ## 1st streamline segment\n  X0 = sl(1,:);\n  X1 = sl(2,:);\n  R = X1 - X0;\n  RE = R / norm (R);\n\n  ## Guide point and its rotation to create a segment\n  KE = get_normal1 (RE);\n  K = rstart * KE;\n  XS0 = rotation (K, RE, cp, sp) + repmat (X0.', 1, num_circum);\n\n  ## End of first segment\n  ract = rstart * exp (0.5 * div_sl(2) * norm (R) / vv(2)) * ...\n                  sqrt (vv(1) / vv(2));\n  rold = ract;\n  K = ract * KE;\n  XS = rotation (K, RE, cp, sp) + repmat (X1.', 1, num_circum);\n\n  px = zeros (num_circum, max_vertices);\n  py = zeros (num_circum, max_vertices);\n  pz = zeros (num_circum, max_vertices);\n  pc = zeros (num_circum, max_vertices);\n\n  px(:,1) = XS0(1,:).';\n  py(:,1) = XS0(2,:).';\n  pz(:,1) = XS0(3,:).';\n  pc(:,1) = vv(1) * ones (num_circum, 1);\n\n  px(:,2) = XS(1,:).';\n  py(:,2) = XS(2,:).';\n  pz(:,2) = XS(3,:).';\n  pc(:,2) = vv(2) * ones (num_circum, 1);\n\n  for i = 3 : max_vertices\n\n    ## Next streamline segment\n    X0 = X1;\n    X1 = sl(i,:);\n    R = X1 - X0;\n    RE = R / norm (R);\n\n    ## Tube radius\n    ract = rold * exp (0.5 * div_sl(i) * norm (R) / vv(i)) * ...\n                  sqrt (vv(i-1) / vv(i));\n    rold = ract;\n\n    ## Project KE onto RE and get the difference in order to transport\n    ## the normal vector KE along the vertex array\n    Kp = KE - RE * dot (KE, RE);\n    KE = Kp / norm (Kp);\n    K = ract * KE;\n\n    ## Rotate around RE and collect surface patches\n    XS = rotation (K, RE, cp, sp) + repmat (X1.', 1, num_circum);\n\n    px(:,i) = XS(1,:).';\n    py(:,i) = XS(2,:).';\n    pz(:,i) = XS(3,:).';\n    pc(:,i) = vv(i) * ones (num_circum, 1);\n\n  endfor\n\n  h = surface (hax, px, py, pz, pc);\n\nendfunction\n\n## Arbitrary N normal to X\nfunction N = get_normal1 (X)\n\n  if ((X(3) == 0) && (X(1) == -X(2)))\n    N = [(- X(2) - X(3)), X(1), X(1)];\n  else\n    N = [X(3), X(3), (- X(1) - X(2))];\n  endif\n\n  N /= norm (N);\n\nendfunction\n\n## Rotate X around U where |U| = 1\n## cp = cos (angle), sp = sin (angle)\nfunction Y = rotation (X, U, cp, sp)\n\n  ux = U(1);\n  uy = U(2);\n  uz = U(3);\n\n  Y(1,:) = X(1) * (cp + ux * ux * (1 - cp)) + ...\n           X(2) * (ux * uy * (1 - cp) - uz * sp) + ...\n           X(3) * (ux * uz * (1 - cp) + uy * sp);\n\n  Y(2,:) = X(1) * (uy * ux * (1 - cp) + uz * sp) + ...\n           X(2) * (cp + uy * uy * (1 - cp)) + ...\n           X(3) * (uy * uz * (1 - cp) - ux * sp);\n\n  Y(3,:) = X(1) * (uz * ux * (1 - cp) - uy * sp) + ...\n           X(2) * (uz * uy * (1 - cp) + ux * sp) + ...\n           X(3) * (cp + uz * uz * (1 - cp));\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x, y, z] = meshgrid (-1:0.1:1, -1:0.1:1, -3.5:0.1:0);\n%! a = 0.1;\n%! b = 0.1;\n%! u = - a * x - y;\n%! v = x - a * y;\n%! w = - b * ones (size (x));\n%! sx = 1.0;\n%! sy = 0.0;\n%! sz = 0.0;\n%! ostreamtube (x, y, z, u, v, w, sx, sy, sz, [1.2, 30]);\n%! colormap (jet);\n%! shading interp;\n%! view ([-47, 24]);\n%! camlight ();\n%! lighting gouraud;\n%! grid on;\n%! view (3);\n%! axis equal;\n%! set (gca, \"cameraviewanglemode\", \"manual\");\n%! title (\"Spiral Sink\");\n\n%!demo\n%! clf;\n%! [x, y, z] = meshgrid (-2:0.5:2);\n%! t = sqrt (1.0./(x.^2 + y.^2 + z.^2)).^3;\n%! u = - x.*t;\n%! v = - y.*t;\n%! w = - z.*t;\n%! [sx, sy, sz] = meshgrid (-2:4:2);\n%! xyz = stream3 (x, y, z, u, v, w, sx, sy, sz, [0.1, 60]);\n%! ostreamtube (xyz, x, y, z, u, v, w, [2, 50]);\n%! colormap (jet);\n%! shading interp;\n%! view ([-47, 24]);\n%! camlight ();\n%! lighting gouraud;\n%! grid on;\n%! view (3);\n%! axis equal;\n%! set (gca, \"cameraviewanglemode\", \"manual\");\n%! title (\"Integration Towards Sink\");\n\n## Test input validation\n%!error <Invalid call> ostreamtube ()\n%!error <Invalid call> ostreamtube (1)\n%!error <Invalid call> ostreamtube (1,2)\n%!error <Invalid call> ostreamtube (1,2,3)\n%!error <Invalid call> ostreamtube (1,2,3,4)\n%!error <Invalid call> ostreamtube (1,2,3,4,5)\n%!error <OPTIONS must be a 1- or 2-element> ostreamtube (1,2,3,4,5,6,[1,2,3])\n%!error <SCALE must be a real scalar . 0> ostreamtube (1,2,3,4,5,6,[1i])\n%!error <SCALE must be a real scalar . 0> ostreamtube (1,2,3,4,5,6,[0])\n%!error <N must be greater than 2> ostreamtube (1,2,3,4,5,6,[1,1i])\n%!error <N must be greater than 2> ostreamtube (1,2,3,4,5,6,[1,2])\n"
  },
  {
    "path": "scripts/plot/draw/pareto.m",
    "content": "########################################################################\n##\n## Copyright (C) 2003-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} pareto (@var{y})\n## @deftypefnx {} {} pareto (@var{y}, @var{x})\n## @deftypefnx {} {} pareto (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} pareto (@dots{})\n## Draw a Pareto chart.\n##\n## A Pareto chart is a bar graph that arranges information in such a way\n## that priorities for process improvement can be established; It organizes\n## and displays information to show the relative importance of data.  The chart\n## is similar to the histogram or bar chart, except that the bars are arranged\n## in decreasing magnitude from left to right along the x-axis.\n##\n## The fundamental idea (Pareto principle) behind the use of Pareto\n## diagrams is that the majority of an effect is due to a small subset of the\n## causes.  For quality improvement, the first few contributing causes\n## (leftmost bars as presented on the diagram) to a problem usually account for\n## the majority of the result.  Thus, targeting these \"major causes\" for\n## elimination results in the most cost-effective improvement scheme.\n##\n## Typically only the magnitude data @var{y} is present in which case\n## @var{x} is taken to be the range @code{1 : length (@var{y})}.  If @var{x}\n## is given it may be a string array, a cell array of strings, or a numerical\n## vector.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a 2-element vector with a graphics\n## handle for the created bar plot and a second handle for the created line\n## plot.\n##\n## An example of the use of @code{pareto} is\n##\n## @example\n## @group\n## Cheese = @{\"Cheddar\", \"Swiss\", \"Camembert\", ...\n##           \"Munster\", \"Stilton\", \"Blue\"@};\n## Sold = [105, 30, 70, 10, 15, 20];\n## pareto (Sold, Cheese);\n## @end group\n## @end example\n## @seealso{bar, barh, hist, pie, plot}\n## @end deftypefn\n\nfunction h = pareto (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"pareto\", varargin{:});\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  endif\n\n  y = varargin{1}(:).';\n  if (nargin == 2)\n    x = varargin{2}(:).';\n    if (! iscell (x))\n      if (ischar (x))\n        x = cellstr (x);\n      else\n        x = cellstr (num2str (x(:)));\n      endif\n    endif\n  else\n    x = cellstr (int2str ([1:numel(y)]'));\n  endif\n\n  [y, idx] = sort (y, \"descend\");\n  x = x(idx);\n  cdf = cumsum (y);\n  maxcdf = cdf(end);\n  cdf ./= maxcdf;\n  idx95 = find (cdf < 0.95, 1, \"last\") + 1;\n\n  if (isempty (hax))\n    [ax, hbar, hline] = plotyy (1 : idx95, y(1:idx95),\n                                1 : length (cdf), 100 * cdf,\n                                @bar, @plot);\n  else\n    [ax, hbar, hline] = plotyy (hax, 1 : idx95, y(1:idx95),\n                                     1 : length (cdf), 100 * cdf,\n                                     @bar, @plot);\n  endif\n\n  axis (ax(1), [1 - 0.6, idx95 + 0.6, 0, maxcdf]);\n  axis (ax(2), [1 - 0.6, idx95 + 0.6, 0, 100]);\n  set (ax(2), \"ytick\", [0, 20, 40, 60, 80, 100],\n              \"yticklabel\", {\"0%\", \"20%\", \"40%\", \"60%\", \"80%\", \"100%\"},\n              \"ycolor\", get (ax(1), \"ycolor\"));\n  set (hline, \"color\", get (ax(1), \"colororder\")(1,:));\n  set (ax(1:2), \"xtick\", 1:idx95, \"xticklabel\", x(1:idx95));\n\n  if (nargout > 0)\n    h = [hbar; hline];\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (jet (64));\n%! Cheese = {\"Cheddar\", \"Swiss\", \"Camembert\", \"Munster\", \"Stilton\", \"Blue\"};\n%! Sold = [105, 30, 70, 10, 15, 20];\n%! pareto (Sold, Cheese);\n%! title (\"pareto() demo #1\");\n\n%!demo\n%! clf;\n%! ## Suppose that we want establish which products makes 80% of turnover.\n%! Codes = {\"AB4\",\"BD7\",\"CF8\",\"CC5\",\"AD11\",\"BB5\",\"BB3\",\"AD8\",\"DF3\",\"DE7\"};\n%! Value = [2.35 7.9 2.45 1.1 0.15 13.45 5.4 2.05 0.85 1.65]';\n%! SoldUnits = [54723 41114 16939 1576091 168000 687197 120222 168195, ...\n%!              1084118 55576]';\n%! pareto (Value.*SoldUnits, Codes);\n%! title (\"pareto() demo #2\");\n"
  },
  {
    "path": "scripts/plot/draw/patch.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} patch ()\n## @deftypefnx {} {} patch (@var{x}, @var{y}, @var{c})\n## @deftypefnx {} {} patch (@var{x}, @var{y}, @var{z}, @var{c})\n## @deftypefnx {} {} patch (\"Faces\", @var{faces}, \"Vertices\", @var{verts}, @dots{})\n## @deftypefnx {} {} patch (@dots{}, \"@var{prop}\", @var{val}, @dots{})\n## @deftypefnx {} {} patch (@dots{}, @var{propstruct}, @dots{})\n## @deftypefnx {} {} patch (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} patch (@dots{})\n## Create patch object in the current axes with vertices at locations\n## (@var{x}, @var{y}) and of color @var{c}.\n##\n## If the vertices are matrices of size @nospell{MxN} then each polygon patch\n## has M vertices and a total of N polygons will be created.  If some polygons\n## do not have M vertices use NaN to represent \"no vertex\".  If the @var{z}\n## input is present then 3-D patches will be created.\n##\n## The color argument @var{c} can take many forms.  To create polygons\n## which all share a single color use a string value (e.g., @qcode{\"r\"} for\n## red), a scalar value which is scaled by @code{clim} and indexed into the\n## current colormap, or a 3-element RGB vector with the precise TrueColor.\n##\n## If @var{c} is a vector of length N then the ith polygon will have a color\n## determined by scaling entry @var{c}(i) according to @code{clim} and then\n## indexing into the current colormap.  More complicated coloring situations\n## require directly manipulating patch property/value pairs.\n##\n## Instead of specifying polygons by matrices @var{x} and @var{y}, it is\n## possible to present a unique list of vertices and then a list of polygon\n## faces created from those vertices.  In this case the\n## @qcode{\"Vertices\"} matrix will be an @nospell{Nx2} (2-D patch) or\n## @nospell{Nx3} (3-D patch).  The @nospell{MxN} @qcode{\"Faces\"} matrix\n## describes M polygons having N vertices---each row describes a\n## single polygon and each column entry is an index into the\n## @qcode{\"Vertices\"} matrix to identify a vertex.  The patch object\n## can be created by directly passing the property/value pairs\n## @qcode{\"Vertices\"}/@var{verts}, @qcode{\"Faces\"}/@var{faces} as\n## inputs.\n##\n## Instead of using property/value pairs, any property can be set by passing a\n## structure @var{propstruct} with the respective field names.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created patch\n## object.\n##\n## Programming Notes:\n## @enumerate\n## @item\n## The full list of properties is documented at @ref{Patch Properties}.\n## Useful patch properties include: @qcode{\"edgecolor\"}, @qcode{\"facecolor\"},\n## @qcode{\"faces\"}, @qcode{\"vertices\"}, and @qcode{\"facevertexcdata\"}.\n##\n## @item\n## Unexpected geometry results can occur from mixing x-y-z and\n## face-vertex forms of defining geometry.\n##\n## @item\n## Unexpected patch color results can occur from using @qcode{\"cdata\"} color\n## definitions with face-vertex defined geometry or @qcode{\"facevertexcdata\"}\n## color definitions with x-y-z defined geometry.\n## @end enumerate\n## @seealso{fill, get, set}\n## @end deftypefn\n\nfunction h = patch (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"patch\", varargin{:});\n\n  if (! isempty (hax))\n    hax = hax(1);\n  endif\n\n  htmp = __patch__ (hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! t1 = (1/16:1/8:1)' * 2*pi;\n%! t2 = ((1/16:1/8:1)' + 1/32) * 2*pi;\n%! x1 = sin (t1) - 0.8;\n%! y1 = cos (t1);\n%! x2 = sin (t2) + 0.8;\n%! y2 = cos (t2);\n%! patch ([x1,x2], [y1,y2], \"r\");\n%! title (\"patches with same number of vertices\");\n\n%!demo\n%! clf;\n%! t1 = (1/16:1/8:1)' * 2*pi;\n%! t2 = ((1/16:1/16:1)' + 1/32) * 2*pi;\n%! x1 = sin (t1) - 0.8;\n%! y1 = cos (t1);\n%! x2 = sin (t2) + 0.8;\n%! y2 = cos (t2);\n%! patch ([[x1;NaN(8,1)],x2], [[y1;NaN(8,1)],y2], \"r\");\n%! title (\"Unclosed patch by using NaN\");\n\n%!demo\n%! clf;\n%! t1 = (1/16:1/8:1)' * 2*pi;\n%! t2 = ((1/16:1/16:1)' + 1/32) * 2*pi;\n%! x1 = sin (t1) - 0.8;\n%! y1 = cos (t1);\n%! x2 = sin (t2) + 0.8;\n%! y2 = cos (t2);\n%! vert = [x1, y1; x2, y2];\n%! fac = [1:8,NaN(1,8);9:24];\n%! patch (\"Faces\",fac, \"Vertices\",vert, \"FaceColor\",\"r\");\n%! title (\"patch() with separate specification of Faces and Vertices\");\n\n%!demo\n%! clf;\n%! t1 = (1/16:1/8:1)' * 2*pi;\n%! t2 = ((1/16:1/16:1)' + 1/32) * 2*pi;\n%! x1 = sin (t1) - 0.8;\n%! y1 = cos (t1);\n%! x2 = sin (t2) + 0.8;\n%! y2 = cos (t2);\n%! vert = [x1, y1; x2, y2];\n%! p.Faces = [1:8,NaN(1,8);9:24];\n%! p.FaceColor = \"flat\";\n%! patch (p, 'Vertices', vert, 'FaceVertexCData', [0, 1, 0; 0, 0, 1]);\n%! title (\"patch() with specification of color for each vertex\");\n\n%!demo\n%! ## Property change on multiple patches\n%! clf;\n%! t1 = (1/16:1/8:1)' * 2*pi;\n%! t2 = ((1/16:1/8:1)' + 1/32) * 2*pi;\n%! x1 = sin (t1) - 0.8;\n%! y1 = cos (t1);\n%! x2 = sin (t2) + 0.8;\n%! y2 = cos (t2);\n%! h = patch ([x1,x2], [y1,y2], cat (3, [0,0],[1,0],[0,1]));\n%! pause (1);\n%! set (h, \"FaceColor\", \"r\");\n%! title (\"change color on multiple patch() objects\");\n\n%!demo\n%! clf;\n%! vertices = [0, 0, 0;\n%!             1, 0, 0;\n%!             1, 1, 0;\n%!             0, 1, 0;\n%!             0.5, 0.5, 1];\n%! faces = [1, 2, 5;\n%!          2, 3, 5;\n%!          3, 4, 5;\n%!          4, 1, 5];\n%! patch (\"Vertices\", vertices, \"Faces\", faces, ...\n%!        \"FaceVertexCData\", jet (4), \"FaceColor\", \"flat\");\n%! view (-37.5, 30);\n%! box off;\n%! title ('\"FaceColor\" = \"flat\"');\n\n%!demo\n%! clf;\n%! vertices = [0, 0, 0;\n%!             1, 0, 0;\n%!             1, 1, 0;\n%!             0, 1, 0;\n%!             0.5, 0.5, 1];\n%! faces = [1, 2, 5;\n%!          2, 3, 5;\n%!          3, 4, 5;\n%!          4, 1, 5];\n%! patch  (\"Vertices\", vertices, \"Faces\", faces, ...\n%!        \"FaceVertexCData\", jet (5), \"FaceColor\", \"interp\");\n%! view (-37.5, 30);\n%! box off;\n%! title ('\"FaceColor\" = \"interp\"');\n\n%!demo\n%! clf;\n%! colormap (jet (64));\n%! x = [0 1 1 0];\n%! y = [0 0 1 1];\n%! subplot (2,1,1);\n%!  title (\"Blue, Light Green, and Red Horizontal Bars\");\n%!  patch (x, y + 0, 1);\n%!  patch (x, y + 1, 2);\n%!  patch (x, y + 2, 3);\n%! subplot (2,1,2);\n%!  title (\"Blue, Light Green, and Red Vertical Bars\");\n%!  patch (x + 0, y, 1 * ones (size (x)));\n%!  patch (x + 1, y, 2 * ones (size (x)));\n%!  patch (x + 2, y, 3 * ones (size (x)));\n\n%!demo\n%! clf;\n%! colormap (jet (64));\n%! x = [0 1 1 0];\n%! y = [0 0 1 1];\n%! subplot (2,1,1);\n%!  title (\"Blue horizontal bars: Dark to Light\");\n%!  patch (x, y + 0, 1, \"cdatamapping\", \"direct\");\n%!  patch (x, y + 1, 9, \"cdatamapping\", \"direct\");\n%!  patch (x, y + 2, 17, \"cdatamapping\", \"direct\");\n%! subplot (2,1,2);\n%!  title (\"Blue vertical bars: Dark to Light\");\n%!  patch (x + 0, y, 1 * ones (size (x)), \"cdatamapping\", \"direct\");\n%!  patch (x + 1, y, 9 * ones (size (x)), \"cdatamapping\", \"direct\");\n%!  patch (x + 2, y, 17 * ones (size (x)), \"cdatamapping\", \"direct\");\n\n%!demo\n%! clf;\n%! colormap (jet (64));\n%! x = [ 0 0; 1 1; 1 0 ];\n%! y = [ 0 0; 0 1; 1 1 ];\n%! p = patch (x, y, \"b\");\n%! set (p, \"cdatamapping\", \"direct\", \"facecolor\", \"flat\", \"cdata\", [1 32]);\n%! title (\"Direct mapping of colors: Light-Green UL and Blue LR triangles\");\n\n%!demo\n%! clf;\n%! colormap (jet (64));\n%! x = [ 0 0; 1 1; 1 0 ];\n%! y = [ 0 0; 0 1; 1 1 ];\n%! p = patch (x, y, [1 32]);\n%! title (\"Autoscaling of colors: Red UL and Blue LR triangles\");\n\n%!demo\n%! clf;\n%! vertices = [0 0 0; 0.5 -0.5 0; 1 0 0; 1 1 0; 0 1 1; 1 0 1; 0 -1 0] + 3;\n%! faces = [1 2 3 4 5 6 7];\n%! ha = axes ();\n%! hp = patch (\"Vertices\", vertices, \"Faces\", faces, \"FaceColor\", \"g\");\n%! xlabel (\"x\"), ylabel (\"y\"), zlabel (\"z\");\n%! view (3);\n%! set (ha, \"XTick\", [], \"YTick\", [], \"ZTick\", []);\n%! text (vertices(1,1), vertices(1,2), vertices(1,3), \"1\");\n%! text (vertices(2,1), vertices(2,2), vertices(2,3), \"2\");\n%! text (vertices(3,1), vertices(3,2), vertices(3,3), \"3\");\n%! text (vertices(4,1), vertices(4,2), vertices(4,3), \"4\");\n%! text (vertices(5,1), vertices(5,2), vertices(5,3), \"5\");\n%! text (vertices(6,1), vertices(6,2), vertices(6,3), \"6\");\n%! text (vertices(7,1), vertices(7,2), vertices(7,3), \"7\");\n%! title (\"Non-coplanar patch\");\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = patch ();\n%!   assert (findobj (hf, \"type\", \"patch\"), h);\n%!   assert (get (h, \"xdata\"), [0; 1; 0], eps);\n%!   assert (get (h, \"ydata\"), [1; 1; 0], eps);\n%!   assert (isempty (get (h, \"zdata\")));\n%!   assert (isempty (get (h, \"cdata\")));\n%!   assert (get (h, \"faces\"), [1, 2, 3], eps);\n%!   assert (get (h, \"vertices\"), [0 1; 1 1; 0 0], eps);\n%!   assert (get (h, \"facenormalsmode\"), \"auto\");\n%!   assert (get (h, \"facenormals\"), get (0, \"defaultpatchfacenormals\"));\n%!   assert (get (h, \"vertexnormalsmode\"), \"auto\");\n%!   assert (get (h, \"vertexnormals\"), get (0, \"defaultpatchvertexnormals\"));\n%!   assert (get (h, \"type\"), \"patch\");\n%!   assert (get (h, \"facecolor\"), [0 0 0]);\n%!   assert (get (h, \"linestyle\"), get (0, \"defaultpatchlinestyle\"));\n%!   assert (get (h, \"linewidth\"), get (0, \"defaultpatchlinewidth\"), eps);\n%!   assert (get (h, \"marker\"), get (0, \"defaultpatchmarker\"));\n%!   assert (get (h, \"markersize\"), get (0, \"defaultpatchmarkersize\"));\n%!   hl = light ();\n%!   assert (get (h, \"facelighting\"), \"flat\");\n%!   assert (get (h, \"facenormals\"), [0 0 1], eps);\n%!   assert (get (h, \"vertexnormals\"), []);\n%!   set (h, \"facelighting\", \"gouraud\");\n%!   assert (get (h, \"vertexnormals\"), [0 0 1; 0 0 1; 0 0 1], eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! c = 0.9;\n%! unwind_protect\n%!   h = patch ([0 1 0], [0 1 1], c);\n%!   assert (get (gca, \"clim\"), [c - 1, c + 1]);\n%!   h = patch ([0 1 0], [0 1 1], 2 * c);\n%!   assert (get (gca, \"clim\"), [c, 2 * c]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <invalid color specification C> patch (1, 1, 'x')\n%!error <invalid TrueColor data C> patch (1, 1, rand (1,2,3))\n%!error <size of X, Y, and C must be equal> patch (1, 1, [1, 2])\n%!error <invalid color specification C> patch (1, 1, {1})\n"
  },
  {
    "path": "scripts/plot/draw/pcolor.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} pcolor (@var{x}, @var{y}, @var{c})\n## @deftypefnx {} {} pcolor (@var{c})\n## @deftypefnx {} {} pcolor (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} pcolor (@dots{})\n## Produce a 2-D density plot.\n##\n## A @code{pcolor} plot draws rectangles with colors from the matrix @var{c}\n## over the two-dimensional region represented by the matrices @var{x} and\n## @var{y}.  @var{x} and @var{y} are the coordinates of the mesh's vertices\n## and are typically the output of @code{meshgrid}.  If @var{x} and @var{y} are\n## vectors, then a typical vertex is (@var{x}(j), @var{y}(i), @var{c}(i,j)).\n## Thus, columns of @var{c} correspond to different @var{x} values and rows\n## of @var{c} correspond to different @var{y} values.\n##\n## The values in @var{c} are scaled to span the range of the current\n## colormap.  Limits may be placed on the color axis by the command\n## @code{clim}, or by setting the @code{clim} property of the parent axis.\n##\n## The face color of each cell of the mesh is determined by interpolating\n## the values of @var{c} for each of the cell's vertices; Contrast this with\n## @code{imagesc} which renders one cell for each element of @var{c}.\n##\n## @code{shading} modifies an attribute determining the manner by which the\n## face color of each cell is interpolated from the values of @var{c},\n## and the visibility of the cells' edges.  By default the attribute is\n## @qcode{\"faceted\"}, which renders a single color for each cell's face with\n## the edge visible.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## @seealso{clim, shading, meshgrid, contour, imagesc}\n## @end deftypefn\n\nfunction h = pcolor (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"pcolor\", varargin{:});\n\n  if (nargin == 1)\n    c = varargin{1};\n    [nr, nc] = size (c);\n    x = 1:nc;\n    y = 1:nr;\n    z = zeros (nr, nc);\n  elseif (nargin == 3)\n    x = varargin{1};\n    y = varargin{2};\n    c = varargin{3};\n    z = zeros (size (c));\n  else\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n  htmp = surface (hax, x, y, z, c);\n\n  set (htmp, \"facecolor\", \"flat\");\n  if (! ishold (hax))\n    set (hax, \"view\", [0, 90], \"box\", \"on\");\n    set (hax, \"xlimmode\", \"auto\", \"ylimmode\", \"auto\", \"zlimmode\", \"auto\",\n              \"xlimitmethod\", \"tight\", \"ylimitmethod\", \"tight\",\n              \"zlimitmethod\", \"tight\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! Z = peaks ();\n%! pcolor (Z);\n%! title (\"pcolor() of peaks with facet shading\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [X,Y,Z] = sombrero ();\n%! [Fx,Fy] = gradient (Z);\n%! pcolor (X,Y,Fx+Fy);\n%! shading interp;\n%! axis tight;\n%! title (\"pcolor() of peaks with interp shading\");\n"
  },
  {
    "path": "scripts/plot/draw/peaks.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} peaks ()\n## @deftypefnx {} {} peaks (@var{n})\n## @deftypefnx {} {} peaks (@var{x}, @var{y})\n## @deftypefnx {} {@var{z} =} peaks (@dots{})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} peaks (@dots{})\n## Plot a function with lots of local maxima and minima.\n##\n## The function has the form\n## @tex\n## $$f(x,y) = 3 (1 - x) ^ 2 e ^ {\\left(-x^2 - (y+1)^2\\right)} - 10 \\left({x \\over 5} - x^3 - y^5\\right) - {1 \\over 3} e^{\\left(-(x+1)^2 - y^2\\right)}$$\n## @end tex\n## @ifnottex\n## @verbatim\n## f(x,y) = 3*(1-x)^2*exp(-x^2 - (y+1)^2) ...\n##          - 10*(x/5 - x^3 - y^5)*exp(-x^2-y^2) ...\n##          - 1/3*exp(-(x+1)^2 - y^2)\n## @end verbatim\n## @end ifnottex\n##\n## Called without a return argument, @code{peaks} plots the surface of the\n## above function using @code{surf}.\n##\n## If @var{n} is a scalar, @code{peaks} plots the value of the above\n## function on an @var{n}-by-@var{n} mesh over the range [-3,3].  The\n## default value for @var{n} is 49.\n##\n## If @var{n} is a vector, then it represents the grid values over which\n## to calculate the function.  If @var{x} and @var{y} are specified then\n## the function value is calculated over the specified grid of vertices.\n##\n## When called with output arguments, return the data for the function\n## evaluated over the meshgrid.  This can subsequently be plotted with\n## @code{surf (@var{x}, @var{y}, @var{z})}.\n##\n## @seealso{sombrero, meshgrid, mesh, surf}\n## @end deftypefn\n\n## Reference: Expression for peaks function was taken from the following paper:\n## http://www.control.hut.fi/Kurssit/AS-74.115/Material/GENALGgoga.pdf\n\nfunction [X_out, Y_out, Z_out] = peaks (x, y)\n\n  if (nargin == 0)\n    x = y = linspace (-3, 3, 49);\n  elseif (nargin == 1)\n    if (length (x) > 1)\n      y = x;\n    else\n      x = y = linspace (-3, 3, x);\n    endif\n  endif\n\n  if (isvector (x) && isvector (y))\n    [X, Y] = meshgrid (x, y);\n  else\n    X = x;\n    Y = y;\n  endif\n\n  Z = 3 * (1 - X) .^ 2 .* exp (- X .^ 2 - (Y + 1) .^ 2) ...\n      - 10 * (X / 5 - X .^ 3 - Y .^ 5) .* exp (- X .^ 2 - Y .^ 2) ...\n      - 1 / 3 * exp (- (X + 1) .^ 2 - Y .^ 2);\n\n  if (nargout == 0)\n    surf (x, y, Z);\n    Z_max = max (Z(:));\n    Z_min = min (Z(:));\n    axis ([-3, 3, -3, 3, Z_min, Z_max]);\n  elseif (nargout == 1)\n    X_out = Z;\n  else\n    X_out = X;\n    Y_out = Y;\n    Z_out = Z;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/pie.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} pie (@var{x})\n## @deftypefnx {} {} pie (@dots{}, @var{explode})\n## @deftypefnx {} {} pie (@dots{}, @var{labels})\n## @deftypefnx {} {} pie (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} pie (@dots{})\n## Plot a 2-D pie chart.\n##\n## When called with a single vector argument, produce a pie chart of the\n## elements in @var{x}.  The size of the ith slice is the percentage that the\n## element @var{x}i represents of the total sum of @var{x}:\n## @code{pct = @var{x}(i) / sum (@var{x})}.\n##\n## The optional input @var{explode} is a vector of the same length as @var{x}\n## that, if nonzero, \"explodes\" the slice from the pie chart.\n##\n## The optional input @var{labels} is a cell array of strings of the same\n## length as @var{x} specifying the label for each slice.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a list of handles to the patch\n## and text objects generating the plot.\n##\n## Note: If @code{sum (@var{x}) @leq{} 1} then the elements of @var{x} are\n## interpreted as percentages directly and are not normalized by @code{sum\n## (x)}.  Furthermore, if the sum is less than 1 then there will be a missing\n## slice in the pie plot to represent the missing, unspecified percentage.\n##\n## @seealso{pie3, bar, hist, rose}\n## @end deftypefn\n\n## Very roughly based on pie.m from Octave Forge whose author was\n## Daniel Heiserer <Daniel.heiserer@physik.tu-muenchen.de>\n\nfunction h = pie (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"pie\", varargin{:});\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! all (isfinite (varargin{1})))\n    error (\"pie: all data in X must be finite\");\n  endif\n\n  hax = newplot (hax);\n  htmp = __pie__ (\"pie\", hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! pie ([3, 2, 1], [0, 0, 1]);\n%! colormap ([1,0,0;0,1,0;0,0,1;1,1,0;1,0,1;0,1,1]);\n%! title (\"pie() with exploded wedge\");\n\n%!demo\n%! clf;\n%! pie ([3, 2, 1], [0, 0, 1], {\"Cheddar\", \"Swiss\", \"Camembert\"});\n%! colormap ([1,0,0;0,1,0;0,0,1;1,1,0;1,0,1;0,1,1]);\n%! axis ([-2,2,-2,2]);\n%! title (\"pie() with labels\");\n\n\n%!demo\n%! clf;\n%! pie ([0.17, 0.34, 0.41], {\"Cheddar\", \"Swiss\", \"Camembert\"});\n%! colormap ([1,0,0;0,1,0;0,0,1;1,1,0;1,0,1;0,1,1]);\n%! axis ([-2,2,-2,2]);\n%! title (\"pie() with missing slice\");\n\n## Test input validation\n%!error <Invalid call> pie ()\n%!error <all data in X must be finite> pie ([1 2 Inf])\n%!error <all data in X must be finite> pie ([1 2 NaN])\n"
  },
  {
    "path": "scripts/plot/draw/pie3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} pie3 (@var{x})\n## @deftypefnx {} {} pie3 (@dots{}, @var{explode})\n## @deftypefnx {} {} pie3 (@dots{}, @var{labels})\n## @deftypefnx {} {} pie3 (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} pie3 (@dots{})\n## Plot a 3-D pie chart.\n##\n## Called with a single vector argument, produces a 3-D pie chart of the\n## elements in @var{x}.  The size of the ith slice is the percentage that the\n## element @var{x}i represents of the total sum of @var{x}:\n## @code{pct = @var{x}(i) / sum (@var{x})}.\n##\n## The optional input @var{explode} is a vector of the same length as @var{x}\n## that, if nonzero, \"explodes\" the slice from the pie chart.\n##\n## The optional input @var{labels} is a cell array of strings of the same\n## length as @var{x} specifying the label for each slice.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a list of graphics handles to the\n## patch, surface, and text objects generating the plot.\n##\n## Note: If @code{sum (@var{x}) @leq{} 1} then the elements of @var{x} are\n## interpreted as percentages directly and are not normalized by @code{sum\n## (x)}.  Furthermore, if the sum is less than 1 then there will be a missing\n## slice in the pie plot to represent the missing, unspecified percentage.\n##\n## @seealso{pie, bar, hist, rose}\n## @end deftypefn\n\n## Very roughly based on pie.m from Octave Forge whose author was\n## Daniel Heiserer <Daniel.heiserer@physik.tu-muenchen.de>\n\nfunction h = pie3 (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"pie3\", varargin{:});\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! all (isfinite (varargin{1})))\n    error (\"pie3: all data in X must be finite\");\n  endif\n\n  hax = newplot (hax);\n  htmp = __pie__ (\"pie3\", hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! pie3 ([5:-1:1], [0, 0, 1, 0, 0]);\n%! colormap ([1,0,0;0,1,0;0,0,1;1,1,0;1,0,1;0,1,1]);\n%! title (\"pie3() with exploded wedge\");\n\n%!demo\n%! clf;\n%! pie3 ([3, 2, 1], [0, 0, 1], {\"Cheddar\", \"Swiss\", \"Camembert\"});\n%! colormap ([1,0,0;0,1,0;0,0,1;1,1,0;1,0,1;0,1,1]);\n%! axis ([-2,2,-2,2]);\n%! title (\"pie3() with labels\");\n\n%!demo\n%! clf;\n%! pie3 ([0.17, 0.34, 0.41], {\"Cheddar\", \"Swiss\", \"Camembert\"});\n%! colormap ([1,0,0;0,1,0;0,0,1;1,1,0;1,0,1;0,1,1]);\n%! axis ([-2,2,-2,2]);\n%! title (\"pie3() with missing slice\");\n\n## Test input validation\n%!error <Invalid call> pie3 ()\n%!error <all data in X must be finite> pie3 ([1 2 Inf])\n%!error <all data in X must be finite> pie3 ([1 2 NaN])\n"
  },
  {
    "path": "scripts/plot/draw/plot.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} plot (@var{y})\n## @deftypefnx {} {} plot (@var{x}, @var{y})\n## @deftypefnx {} {} plot (@var{x}, @var{y}, @var{fmt})\n## @deftypefnx {} {} plot (@dots{}, @var{property}, @var{value}, @dots{})\n## @deftypefnx {} {} plot (@var{x1}, @var{y1}, @dots{}, @var{xn}, @var{yn})\n## @deftypefnx {} {} plot (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} plot (@dots{})\n## Produce 2-D plots.\n##\n## Many different combinations of arguments are possible.  The simplest\n## form is\n##\n## @example\n## plot (@var{y})\n## @end example\n##\n## @noindent\n## where the argument is taken as the set of @var{y} coordinates and the\n## @var{x} coordinates are taken to be the range @code{1:numel (@var{y})}.\n##\n## If more than one argument is given, they are interpreted as\n##\n## @example\n## plot (@var{y}, @var{property}, @var{value}, @dots{})\n## @end example\n##\n## @noindent\n## or\n##\n## @example\n## plot (@var{x}, @var{y}, @var{property}, @var{value}, @dots{})\n## @end example\n##\n## @noindent\n## or\n##\n## @example\n## plot (@var{x}, @var{y}, @var{fmt}, @dots{})\n## @end example\n##\n## @noindent\n## and so on.  Any number of argument sets may appear.  The @var{x} and\n## @var{y} values are interpreted as follows:\n##\n## @itemize @bullet\n## @item\n## If a single data argument is supplied, it is taken as the set of @var{y}\n## coordinates and the @var{x} coordinates are taken to be the indices of\n## the elements, starting with 1.\n##\n## @item\n## If @var{x} and @var{y} are scalars, a single point is plotted.\n##\n## @item\n## @code{squeeze()} is applied to arguments with more than two dimensions,\n## but no more than two singleton dimensions.\n##\n## @item\n## If either @var{x} or @var{y} is a scalar and the other is a vector, a\n## series of points are plotted at the coordinates defined by the scalar and\n## each element of the vector.\n##\n## @item\n## If both arguments are vectors, the elements of @var{y} are plotted versus\n## the elements of @var{x}.\n##\n## @item\n## If @var{x} is a vector and @var{y} is a matrix, then\n## the columns (or rows) of @var{y} are plotted versus @var{x}.\n## (using whichever combination matches, with columns tried first.)\n##\n## @item\n## If the @var{x} is a matrix and @var{y} is a vector,\n## @var{y} is plotted versus the columns (or rows) of @var{x}.\n## (using whichever combination matches, with columns tried first.)\n##\n## @item\n## If both arguments are matrices, the columns of @var{y} are plotted\n## versus the columns of @var{x}.  In this case, both matrices must have\n## the same number of rows and columns and no attempt is made to transpose\n## the arguments to make the number of rows match.\n## @end itemize\n##\n## Multiple property-value pairs may be specified, but they must appear in\n## pairs.  These arguments are applied to the line objects drawn by @code{plot}.\n## Useful properties to modify are @qcode{\"linestyle\"}, @qcode{\"linewidth\"},\n## @qcode{\"color\"}, @qcode{\"marker\"}, @qcode{\"markersize\"},\n## @qcode{\"markeredgecolor\"}, @qcode{\"markerfacecolor\"}.  The full list of\n## properties is documented at @ref{Line Properties}.\n##\n## The @var{fmt} format argument can also be used to control the plot style.\n## It is a string composed of four optional parts:\n## \"<linestyle><marker><color><;displayname;>\".\n## When a marker is specified, but no linestyle, only the markers are\n## plotted.  Similarly, if a linestyle is specified, but no marker, then\n## only lines are drawn.  If both are specified then lines and markers will\n## be plotted.  If no @var{fmt} and no @var{property}/@var{value} pairs are\n## given, then the default plot style is solid lines with no markers and the\n## color determined by the @qcode{\"colororder\"} property of the current axes.\n##\n## Format arguments:\n##\n## @table @asis\n## @item linestyle\n##\n## @multitable @columnfractions 0.06 0.94\n## @item @samp{-}  @tab Use solid lines (default).\n## @item @samp{--} @tab Use dashed lines.\n## @item @samp{:}  @tab Use dotted lines.\n## @item @samp{-.} @tab Use dash-dotted lines.\n## @end multitable\n##\n## @item marker\n##\n## @multitable @columnfractions 0.06 0.94\n## @item @samp{+} @tab crosshair\n## @item @samp{o} @tab circle\n## @item @samp{*} @tab star\n## @item @samp{.} @tab point\n## @item @samp{x} @tab cross\n## @item @samp{|} @tab vertical line\n## @item @samp{_} @tab horizontal line\n## @item @samp{s} @tab square\n## @item @samp{d} @tab diamond\n## @item @samp{^} @tab upward-facing triangle\n## @item @samp{v} @tab downward-facing triangle\n## @item @samp{>} @tab right-facing triangle\n## @item @samp{<} @tab left-facing triangle\n## @item @samp{p} @tab pentagram\n## @item @samp{h} @tab hexagram\n## @end multitable\n##\n## @item color\n##\n## @multitable @columnfractions 0.21 0.79\n## @item @samp{k}, @qcode{\"black\"}   @tab blacK\n## @item @samp{r}, @qcode{\"red\"}     @tab Red\n## @item @samp{g}, @qcode{\"green\"}   @tab Green\n## @item @samp{b}, @qcode{\"blue\"}    @tab Blue\n## @item @samp{y}, @qcode{\"yellow\"}  @tab Yellow\n## @item @samp{m}, @qcode{\"magenta\"} @tab Magenta\n## @item @samp{c}, @qcode{\"cyan\"}    @tab Cyan\n## @item @samp{w}, @qcode{\"white\"}   @tab White\n## @end multitable\n##\n## @item @qcode{\";displayname;\"}\n## The text between semicolons is used to set the @qcode{\"displayname\"}\n## property which determines the label used for the plot legend.\n##\n## @end table\n##\n## The @var{fmt} argument may also be used to assign legend labels.\n## To do so, include the desired label between semicolons after the\n## formatting sequence described above, e.g., @qcode{\"+b;Data Series 3;\"}.\n## Note that the last semicolon is required and Octave will generate\n## an error if it is left out.\n##\n## Here are some plot examples:\n##\n## @example\n## plot (x, y, \"or\", x, y2, x, y3, \"m\", x, y4, \"+\")\n## @end example\n##\n## This command will plot @code{y} with red circles, @code{y2} with solid\n## lines, @code{y3} with solid magenta lines, and @code{y4} with points\n## displayed as @samp{+}.\n##\n## @example\n## plot (b, \"*\", \"markersize\", 10)\n## @end example\n##\n## This command will plot the data in the variable @code{b},\n## with points displayed as @samp{*} and a marker size of 10.\n##\n## @example\n## @group\n## t = 0:0.1:6.3;\n## plot (t, cos(t), \"-;cos(t);\", t, sin(t), \"-b;sin(t);\");\n## @end group\n## @end example\n##\n## This will plot the cosine and sine functions and label them accordingly\n## in the legend.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of graphics handles to\n## the created line objects.\n##\n## To save a plot, in one of several image formats such as PostScript\n## or PNG, use the @code{print} command.\n##\n## @seealso{axis, box, grid, hold, legend, title, xlabel, ylabel, xlim, ylim,\n## ezplot, errorbar, fplot, line, plot3, polar, loglog, semilogx, semilogy,\n## subplot}\n## @end deftypefn\n\nfunction h = plot (varargin)\n\n  [hax, varargin, nargs] = __plt_get_axis_arg__ (\"plot\", varargin{:});\n\n  if (nargs < 1)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n  htmp = __plt__ (\"plot\", hax, varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"box\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = 1:5;  y = 1:5;\n%! plot (x,y,\"g\");\n%! title (\"plot() of green line at 45 degrees\");\n\n%!demo\n%! clf;\n%! x = 1:5;  y = 1:5;\n%! plot (x,y,\"g*\");\n%! title (\"plot() of green stars along a line at 45 degrees\");\n\n%!demo\n%! clf;\n%! x1 = 1:5;  y1 = 1:5;\n%! x2 = 5:9; y2 = 5:-1:1;\n%! plot (x1,y1,\"bo-\", x2,y2,\"rs-\");\n%! axis (\"tight\");\n%! title ({\"plot() of blue circles ascending and red squares descending\";\n%!         \"connecting lines drawn\"});\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! plot (x, rand (numel (x), 3));\n%! axis ([0 10 0 1]);\n%! title ({\"Three random variables\", \"x[1x11], y[11x3]\"});\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! plot (x, rand (3, numel (x)));\n%! axis ([0 10 0 1]);\n%! title ({\"Three random variables\", \"x[1x11], y[3x11]\"});\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! plot (repmat (x, 2, 1), rand (2, numel (x)), \"-s\");\n%! axis ([0 10 0 1]);\n%! title ({\"Vertical lines with random height and lengths\", ...\n%!         \"x[2x11], y[2,11]\"});\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! plot (repmat (x(:), 1, 2), rand (numel (x), 2));\n%! axis ([0 10 0 1]);\n%! title ({\"Two random variables\", \"x[11x2], y[11x2]\"});\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! shape = [1, 1, numel(x), 2];\n%! x = reshape (repmat (x(:), 1, 2), shape);\n%! y = rand (shape);\n%! plot (x, y);\n%! axis ([0 10 0 1]);\n%! title ({\"Two random variables\", \"squeezed from 4-D arrays\"});\n"
  },
  {
    "path": "scripts/plot/draw/plot3.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} plot3 (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} plot3 (@var{x}, @var{y}, @var{z}, @var{prop}, @var{value}, @dots{})\n## @deftypefnx {} {} plot3 (@var{x}, @var{y}, @var{z}, @var{fmt})\n## @deftypefnx {} {} plot3 (@var{x}, @var{cplx})\n## @deftypefnx {} {} plot3 (@var{cplx})\n## @deftypefnx {} {} plot3 (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} plot3 (@dots{})\n## Produce 3-D plots.\n##\n## Many different combinations of arguments are possible.  The simplest\n## form is\n##\n## @example\n## plot3 (@var{x}, @var{y}, @var{z})\n## @end example\n##\n## @noindent\n## in which the arguments are taken to be the vertices of the points to\n## be plotted in three dimensions.  If all arguments are vectors of the\n## same length, then a single continuous line is drawn.  If all arguments\n## are matrices, then each column of is treated as a separate line.  No attempt\n## is made to transpose the arguments to make the number of rows match.\n##\n## If only two arguments are given, as\n##\n## @example\n## plot3 (@var{x}, @var{cplx})\n## @end example\n##\n## @noindent\n## the real and imaginary parts of the second argument are used\n## as the @var{y} and @var{z} coordinates, respectively.\n##\n## If only one argument is given, as\n##\n## @example\n## plot3 (@var{cplx})\n## @end example\n##\n## @noindent\n## the real and imaginary parts of the argument are used as the @var{y}\n## and @var{z} values, and they are plotted versus their index.\n##\n## Arguments may also be given in groups of three as\n##\n## @example\n## plot3 (@var{x1}, @var{y1}, @var{z1}, @var{x2}, @var{y2}, @var{z2}, @dots{})\n## @end example\n##\n## @noindent\n## in which each set of three arguments is treated as a separate line or\n## set of lines in three dimensions.\n##\n## To plot multiple one- or two-argument groups, separate each group\n## with an empty format string, as\n##\n## @example\n## plot3 (@var{x1}, @var{c1}, \"\", @var{c2}, \"\", @dots{})\n## @end example\n##\n## Multiple property-value pairs may be specified which will affect the line\n## objects drawn by @code{plot3}.  If the @var{fmt} argument is supplied it will\n## format the line objects in the same manner as @code{plot}.  The full list of\n## properties is documented at @ref{Line Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n##\n## Example:\n##\n## @example\n## @group\n## z = [0:0.05:5];\n## plot3 (cos (2*pi*z), sin (2*pi*z), z, \";helix;\");\n## plot3 (z, exp (2i*pi*z), \";complex sinusoid;\");\n## @end group\n## @end example\n## @seealso{ezplot3, plot}\n## @end deftypefn\n\nfunction h = plot3 (varargin)\n\n  [hax, varargin, nargs] = __plt_get_axis_arg__ (\"plot3\", varargin{:});\n\n  if (nargs < 1)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n\n  x_set = 0;\n  y_set = 0;\n  z_set = 0;\n  property_set = 0;\n  fmt_set = 0;\n  properties = {};\n  tlgnd = {};\n  hlgnd = [];\n  htmp = [];\n  idx = 0;\n\n  ## Gather arguments, decode format, and plot lines.\n  arg = 0;\n  while (arg++ < nargs)\n    new = varargin{arg};\n    new_cell = varargin(arg);\n\n    if (property_set)\n      properties = [properties, new_cell];\n      property_set = 0;\n      continue;\n    endif\n\n    if (ischar (new))\n      if (! z_set)\n        if (! y_set)\n          if (! x_set)\n            error (\"plot3: needs X, [ Y, [ Z ] ]\");\n          else\n            y = real (x);\n            z = imag (x);\n            y_set = 1;\n            z_set = 1;\n            if (rows (x) > 1)\n              x = repmat ((1:rows (x))', 1, columns (x));\n            else\n              x = 1:columns (x);\n            endif\n          endif\n        else\n          z = imag (y);\n          y = real (y);\n          z_set = 1;\n        endif\n      endif\n\n      if (! fmt_set)\n        [options, valid] = __pltopt__ (\"plot3\", new, false);\n        if (! valid)\n          properties = [properties, new_cell];\n          property_set = 1;\n          continue;\n        else\n          fmt_set = 1;\n          while (arg < nargs && ischar (varargin{arg+1}))\n            if (nargs - arg < 2)\n              error (\"plot3: properties must appear followed by a value\");\n            endif\n            properties = [properties, varargin(arg+1:arg+2)];\n            arg += 2;\n          endwhile\n        endif\n      else\n        properties = [properties, new_cell];\n        property_set = 1;\n        continue;\n      endif\n\n      if (isvector (x) && isvector (y))\n        if (isvector (z))\n          x = x(:);\n          y = y(:);\n          z = z(:);\n        elseif (length (x) == rows (z) && length (y) == columns (z))\n          [x, y] = meshgrid (x, y);\n        else\n          error (\"plot3: [length(X), length(Y)] must match size (Z)\");\n        endif\n      endif\n\n      if (! size_equal (x, y, z))\n        error (\"plot3: X, Y, and Z must have the same shape\");\n      elseif (ndims (x) > 2)\n        error (\"plot3: X, Y, and Z must not have more than two dimensions\");\n      endif\n\n      for i = 1 : columns (x)\n        linestyle = options.linestyle;\n        marker = options.marker;\n        if (isempty (marker) && isempty (linestyle))\n          if (isscalar (x))\n            ## If unspecified, marker for a point is always \".\"\n            linestyle = \"-\";\n            marker = \".\";\n          else\n            [linestyle, marker] = __next_line_style__ (hax);\n          endif\n        endif\n        color = options.color;\n        if (isempty (color))\n          color = __next_line_color__ (hax);\n        endif\n\n        htmp(++idx) = __go_line__ (hax, \"xdata\", x(:, i), \"ydata\", y(:, i),\n                                   \"zdata\", z(:, i),\n                                   \"color\", color, \"linestyle\", linestyle,\n                                   \"marker\", marker, properties{:});\n        key = options.key;\n        if (! isempty (key))\n          hlgnd = [hlgnd, htmp(idx)];\n          tlgnd = {tlgnd{:}, key};\n        endif\n      endfor\n\n      x_set = 0;\n      y_set = 0;\n      z_set = 0;\n      fmt_set = 0;\n      properties = {};\n    elseif (! x_set)\n      x = new;\n      x_set = 1;\n    elseif (! y_set)\n      y = new;\n      y_set = 1;\n    elseif (! z_set)\n      z = new;\n      z_set = 1;\n    else\n      if (isvector (x) && isvector (y))\n        if (isvector (z))\n          x = x(:);\n          y = y(:);\n          z = z(:);\n        elseif (length (x) == rows (z) && length (y) == columns (z))\n          [x, y] = meshgrid (x, y);\n        else\n          error (\"plot3: [length(X), length(Y)] must match size (Z)\");\n        endif\n      endif\n\n      if (! size_equal (x, y, z))\n        error (\"plot3: X, Y, and Z must have the same shape\");\n      elseif (ndims (x) > 2)\n        error (\"plot3: X, Y, and Z must not have more than two dimensions\");\n      endif\n\n      options = __default_plot_options__ ();\n      for i = 1 : columns (x)\n        linestyle = options.linestyle;\n        marker = options.marker;\n        if (isempty (marker) && isempty (linestyle))\n          if (isscalar (x))\n            ## If unspecified, marker for a point is always \".\"\n            linestyle = \"-\";\n            marker = \".\";\n          else\n            [linestyle, marker] = __next_line_style__ (hax);\n          endif\n        endif\n        color = options.color;\n        if (isempty (color))\n          color = __next_line_color__ (hax);\n        endif\n\n        htmp(++idx) = __go_line__ (hax, \"xdata\", x(:, i), \"ydata\", y(:, i),\n                                   \"zdata\", z(:, i),\n                                   \"color\", color, \"linestyle\", linestyle,\n                                   \"marker\", marker, properties{:});\n        key = options.key;\n        if (! isempty (key))\n          hlgnd = [hlgnd, htmp(idx)];\n          tlgnd = {tlgnd{:}, key};\n        endif\n      endfor\n\n      x = new;\n      y_set = 0;\n      z_set = 0;\n      fmt_set = 0;\n      properties = {};\n    endif\n\n  endwhile\n\n  if (property_set)\n    error (\"plot3: properties must appear followed by a value\");\n  endif\n\n  ## Handle last plot.\n\n  if (x_set)\n    if (y_set)\n      if (! z_set)\n        z = imag (y);\n        y = real (y);\n        z_set = 1;\n      endif\n    else\n      y = real (x);\n      z = imag (x);\n      y_set = 1;\n      z_set = 1;\n      if (rows (x) > 1)\n        x = repmat ((1:rows (x))', 1, columns (x));\n      else\n        x = 1:columns (x);\n      endif\n    endif\n\n    if (isvector (x) && isvector (y))\n      if (isvector (z))\n        x = x(:);\n        y = y(:);\n        z = z(:);\n      elseif (length (x) == rows (z) && length (y) == columns (z))\n        [x, y] = meshgrid (x, y);\n      else\n        error (\"plot3: [length(X), length(Y)] must match size (Z)\");\n      endif\n    endif\n\n    if (! size_equal (x, y, z))\n      error (\"plot3: X, Y, and Z must have the same shape\");\n    elseif (ndims (x) > 2)\n      error (\"plot3: X, Y, and Z must not have more than two dimensions\");\n    endif\n\n    options = __default_plot_options__ ();\n\n    for i = 1 : columns (x)\n      linestyle = options.linestyle;\n      marker = options.marker;\n      if (isempty (marker) && isempty (linestyle))\n        if (isscalar (x))\n          ## If unspecified, marker for a point is always \".\"\n          linestyle = \"-\";\n          marker = \".\";\n        else\n          [linestyle, marker] = __next_line_style__ (hax);\n        endif\n      endif\n      color = options.color;\n      if (isempty (color))\n        color = __next_line_color__ (hax);\n      endif\n\n      htmp(++idx) = __go_line__ (hax, \"xdata\", x(:, i), \"ydata\", y(:, i),\n                                 \"zdata\", z(:, i),\n                                 \"color\", color, \"linestyle\", linestyle,\n                                 \"marker\", marker, properties{:});\n      key = options.key;\n      if (! isempty (key))\n        hlgnd = [hlgnd, htmp(idx)];\n        tlgnd = {tlgnd{:}, key};\n      endif\n    endfor\n  endif\n\n  if (! isempty (hlgnd))\n    legend (hax, hlgnd, tlgnd);\n  endif\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30]);\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! z = [0:0.05:5];\n%! plot3 (cos (2*pi*z), sin (2*pi*z), z);\n%! legend (\"helix\");\n%! title (\"plot3() of a helix\");\n\n%!demo\n%! clf;\n%! z = [0:0.05:5];\n%! plot3 (z, exp (2i*pi*z));\n%! legend (\"complex sinusoid\");\n%! title (\"plot3() with complex input\");\n"
  },
  {
    "path": "scripts/plot/draw/plotmatrix.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} plotmatrix (@var{x}, @var{y})\n## @deftypefnx {} {} plotmatrix (@var{x})\n## @deftypefnx {} {} plotmatrix (@dots{}, @var{style})\n## @deftypefnx {} {} plotmatrix (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{h}, @var{ax}, @var{bigax}, @var{p}, @var{pax}] =} plotmatrix (@dots{})\n## Scatter plot of the columns of one matrix against another.\n##\n## Given the arguments @var{x} and @var{y} that have a matching number of\n## rows, @code{plotmatrix} plots a set of axes corresponding to\n##\n## @example\n## plot (@var{x}(:, i), @var{y}(:, j))\n## @end example\n##\n## When called with a single argument @var{x} this is equivalent to\n##\n## @example\n## plotmatrix (@var{x}, @var{x})\n## @end example\n##\n## @noindent\n## except that the diagonal of the set of axes will be replaced with the\n## histogram @code{hist (@var{x}(:, i))}.\n##\n## The marker to use can be changed with the @var{style} argument, that is a\n## string defining a marker in the same manner as the @code{plot} command.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} provides handles to the individual\n## graphics objects in the scatter plots, whereas @var{ax} returns the\n## handles to the scatter plot axes objects.\n##\n## @var{bigax} is a hidden axes object that surrounds the other axes, such\n## that the commands @code{xlabel}, @code{title}, etc., will be associated\n## with this hidden axes.\n##\n## Finally, @var{p} returns the graphics objects associated with the histogram\n## and @var{pax} the corresponding axes objects.\n##\n## Example:\n##\n## @example\n## plotmatrix (randn (100, 3), \"g+\")\n## @end example\n##\n## @seealso{scatter, plot}\n## @end deftypefn\n\nfunction [h, ax, bigax, p, pax] = plotmatrix (varargin)\n\n  [bigax2, varargin, nargin] = __plt_get_axis_arg__ (\"plotmatrix\", varargin{:});\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  bigax2 = newplot (bigax2);\n\n  [h2, ax2, p2, pax2] = __plotmatrix__ (bigax2, varargin{:});\n\n  axes (bigax2);\n  ctext = text (bigax2, 0, 0, \"\", \"visible\", \"off\",\n                \"handlevisibility\", \"off\", \"xliminclude\", \"off\",\n                \"yliminclude\", \"off\", \"zliminclude\", \"off\",\n                \"deletefcn\", {@plotmatrixdelete, [ax2; pax2]});\n  set (bigax2, \"visible\", \"off\");\n\n  if (nargout > 0)\n    h = h2;\n    ax = ax2;\n    bigax = bigax2;\n    p = p2;\n    pax = pax2;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! plotmatrix (randn (100, 3), \"g+\");\n%! title (\"plotmatrix() demo #1\");\n\n\nfunction plotmatrixdelete (h, ~, ax)\n\n  for i = 1 : numel (ax)\n    hc = ax(i);\n    if (isaxes (hc) && strcmpi (get (hc, \"beingdeleted\"), \"off\"))\n      parent = get (hc, \"parent\");\n      ## If the parent is invalid or being deleted, then do nothing\n      if (ishghandle (parent) && strcmpi (get (parent, \"beingdeleted\"), \"off\"))\n        delete (hc);\n      endif\n    endif\n  endfor\n\nendfunction\n\nfunction [h, ax, p, pax] = __plotmatrix__ (bigax, varargin)\n\n  have_line_spec = false;\n  have_hist = false;\n  parent = get (bigax, \"parent\");\n  narg = nargin ();\n  for i = 1 : narg - 1\n    arg = varargin{i};\n    if (ischar (arg) || iscellstr (arg))\n      ## __pltopt__ will error and stop function if linespec is invalid\n      __pltopt__ (\"plotmatrix\", varargin{i});\n      have_line_spec = true;\n      linespec = varargin(i);\n      varargin(i) = [];\n      narg -= 1;\n      break;\n    endif\n  endfor\n\n  if (narg == 2)\n    X = varargin{1};\n    Y = X;\n    have_hist = true;\n  elseif (narg == 3)\n    X = varargin{1};\n    Y = varargin{2};\n  else\n    print_usage (\"plotmatrix\");\n  endif\n\n  if (rows (X) != rows (Y))\n    error (\"plotmatrix: dimension mismatch in the arguments\");\n  endif\n\n  m = columns (X);\n  n = columns (Y);\n\n  h = [];\n  ax = [];\n  p = [];\n  pax = [];\n\n  xsize = 0.9 / m;\n  ysize = 0.9 / n;\n  xoff = 0.05;\n  yoff = 0.05;\n  border = [0.130, 0.110, 0.225, 0.185] .* [xsize, ysize, xsize, ysize];\n  border(3:4) = - border(3:4) - border(1:2);\n\n  for i = 1 : m\n    for j = 1 : n\n      pos = [xsize * (i - 1) + xoff, ysize * (n - j) + yoff, xsize, ysize];\n      hax = axes (\"outerposition\", pos, \"position\", pos + border,\n                  \"parent\", parent);\n      if (i == j && have_hist)\n        pax = [pax ; hax];\n        [nn, xx] = hist (hax, X(:, i));\n        htmp = bar (hax, xx, nn, 1.0);\n        p = [p; htmp];\n      else\n        ax = [ax ; hax];\n        if (have_line_spec)\n          htmp = plot (hax, X(:, i), Y(:, j), linespec);\n        else\n          htmp = plot (hax, X(:, i), Y(:, j), \".\");\n        endif\n        h = [h ; htmp];\n      endif\n    endfor\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/plotyy.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} plotyy (@var{x1}, @var{y1}, @var{x2}, @var{y2})\n## @deftypefnx {} {} plotyy (@dots{}, @var{fcn})\n## @deftypefnx {} {} plotyy (@dots{}, @var{fun1}, @var{fun2})\n## @deftypefnx {} {} plotyy (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{ax}, @var{h1}, @var{h2}] =} plotyy (@dots{})\n## Plot two sets of data with independent y-axes and a common x-axis.\n##\n## The arguments @var{x1} and @var{y1} define the arguments for the first plot\n## and @var{x1} and @var{y2} for the second.\n##\n## By default the arguments are evaluated with\n## @code{feval (@@plot, @var{x}, @var{y})}.  However the type of plot can be\n## modified with the @var{fcn} argument, in which case the plots are\n## generated by @code{feval (@var{fcn}, @var{x}, @var{y})}.  @var{fcn} can be\n## a function handle, an inline function, or a string of a function name.\n##\n## The function to use for each of the plots can be independently defined\n## with @var{fun1} and @var{fun2}.\n##\n## The first argument @var{hax} can be an axes handle to the principal axes in\n## which to plot the @var{x1} and @var{y1} data.  It can also be a two-element\n## vector with the axes handles to the primary and secondary axes (see output\n## @var{ax}).\n##\n## The return value @var{ax} is a vector with the axes handles of the two\n## y-axes.  @var{h1} and @var{h2} are handles to the objects generated by the\n## plot commands.\n##\n## @example\n## @group\n## x = 0:0.1:2*pi;\n## y1 = sin (x);\n## y2 = exp (x - 1);\n## ax = plotyy (x, y1, x - 1, y2, @@plot, @@semilogy);\n## xlabel (\"X\");\n## ylabel (ax(1), \"Axis 1\");\n## ylabel (ax(2), \"Axis 2\");\n## @end group\n## @end example\n##\n## When using @code{plotyy} in conjunction with @code{subplot} make sure to\n## call @code{subplot} first and pass the resulting axes handle to\n## @code{plotyy}.  Do not call @code{subplot} with any of the axes handles\n## returned by @code{plotyy} or the other axes will be removed.\n##\n## @seealso{plot, subplot}\n## @end deftypefn\n\nfunction [ax, h1, h2] = plotyy (varargin)\n\n  ## Check if first argument is axes handle(s).\n  hax = [];\n  if (numel (varargin) > 0)\n    if (isscalar (varargin{1}))\n      [hax, varargin] = __plt_get_axis_arg__ (\"plotyy\", varargin{:});\n    elseif (numel (varargin{1}) == 2 && all (isaxes (varargin{1})))\n      ## First argument might be vector with the two handles to plotyy axes.\n      hax = varargin{1}(1);\n      varargin(1) = [];\n    endif\n  endif\n\n  nargin = numel (varargin);\n  if (nargin < 4 || nargin > 6)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n\n  ## FIXME: Second conditional test shouldn't be required.\n  ##        'cla reset' needs to delete user properties like __plotyy_axes__.\n  if (isprop (hax, \"__plotyy_axes__\")\n      && isaxes (get (hax, \"__plotyy_axes__\")) == [true; true])\n    hax = get (hax, \"__plotyy_axes__\");\n  else\n    hax = [hax; axes(\"nextplot\", get (hax(1), \"nextplot\"), ...\n                     \"parent\", get (hax(1), \"parent\"))];\n  endif\n\n  [axtmp, h1tmp, h2tmp] = __plotyy__ (hax, varargin{:});\n\n  ## FIXME: Is this correct?  Can there be any other parent besides a figure?\n  set (get (hax(1), 'parent'), \"currentaxes\", hax(1));\n\n  if (nargout > 0)\n    ax = axtmp;\n    h1 = h1tmp;\n    h2 = h2tmp;\n  endif\n\nendfunction\n\nfunction [ax, h1, h2] = __plotyy__ (ax, x1, y1, x2, y2, fun1 = @plot, fun2)\n\n  if (nargin < 7)\n    fun2 = fun1;\n  endif\n\n  xlim = [min([x1(:); x2(:)]), max([x1(:); x2(:)])];\n\n  axes (ax(1));\n\n  h1 = feval (fun1, x1, y1);\n\n  set (ax(1), \"xlim\", xlim);\n  if (isscalar (h1))\n    ## Coloring y-axis only makes sense if plot contains exactly one line\n    set (ax(1), \"ycolor\", getcolor (h1));\n  endif\n\n  set (gcf (), \"nextplot\", \"add\");\n\n  axes (ax(2));\n\n  if (strcmp (get (ax(1), \"nextplot\"), \"replace\"))\n    ## Reset axes here because we don't want it to reset later after we set\n    ## some properties in preparation for the plot in the secondary axes.\n    reset (ax(2));\n  endif\n\n  colors = get (ax(1), \"colororder\");\n  set (ax(2), \"colororder\", circshift (colors, -numel (h1), 1));\n\n  if (strcmp (get (ax(1), \"__autopos_tag__\"), \"subplot\"))\n    set (ax(2), \"__autopos_tag__\", \"subplot\");\n  elseif (strcmp (graphics_toolkit (), \"gnuplot\"))\n    set (ax, \"positionconstraint\", \"innerposition\");\n  else\n    set (ax, \"positionconstraint\", \"outerposition\");\n  endif\n\n  ## Don't replace axis which has colororder property already modified\n  if (strcmp (get (ax(1), \"nextplot\"), \"replace\"))\n    set (ax(2), \"nextplot\", \"replacechildren\");\n  endif\n  h2 = feval (fun2, x2, y2);\n\n  set (ax(2), \"yaxislocation\", \"right\", \"color\", \"none\", \"box\", \"off\",\n              \"xlim\", xlim);\n  if (isscalar (h2))\n    ## Coloring y-axis only makes sense if plot contains exactly one line\n    set (ax(2), \"ycolor\", getcolor (h2));\n  endif\n\n  set (ax(2), \"units\", get (ax(1), \"units\"));\n  if (strcmp (get (ax(1), \"positionconstraint\"), \"innerposition\"))\n    set (ax(2), \"position\", get (ax(1), \"position\"));\n  else\n    set (ax(2), {\"outerposition\", \"looseinset\"},\n                get (ax(1), {\"outerposition\", \"looseinset\"}));\n  endif\n\n  ## Restore nextplot value by copying value from axis #1\n  set (ax(2), \"nextplot\", get (ax(1), \"nextplot\"));\n\n  ## Add invisible text objects that when destroyed,\n  ## also remove the other axis\n  t1 = text (0, 0, \"\", \"parent\", ax(1), \"tag\", \"plotyy\",\n             \"visible\", \"off\", \"handlevisibility\", \"off\",\n             \"xliminclude\", \"off\", \"yliminclude\", \"off\",\n             \"zliminclude\", \"off\");\n\n  t2 = text (0, 0, \"\", \"parent\", ax(2), \"tag\", \"plotyy\",\n             \"visible\", \"off\", \"handlevisibility\", \"off\",\n             \"xliminclude\", \"off\", \"yliminclude\", \"off\",\n             \"zliminclude\", \"off\");\n\n  set (t1, \"deletefcn\", {@deleteplotyy, ax(2), t2});\n  set (t2, \"deletefcn\", {@deleteplotyy, ax(1), t1});\n\n  ## Add cross-listeners so a change in one axes' attributes updates the other.\n  props = {\"units\", \"looseinset\", \"position\", \"xlim\", \"view\", ...\n           \"plotboxaspectratio\", \"plotboxaspectratiomode\", \"nextplot\"};\n\n  for ii = 1:numel (props)\n    addlistener (ax(1), props{ii}, {@update_prop, ax(2), props{ii}});\n    addlistener (ax(2), props{ii}, {@update_prop, ax(1), props{ii}});\n  endfor\n\n  ## Store the axes handles for the sister axes.\n  if (! isprop (ax(1), \"__plotyy_axes__\"))\n    addproperty (\"__plotyy_axes__\", ax(1), \"data\");\n  endif\n  set (ax(1), \"__plotyy_axes__\", ax);\n  if (! isprop (ax(2), \"__plotyy_axes__\"))\n    addproperty (\"__plotyy_axes__\", ax(2), \"data\");\n  endif\n  set (ax(2), \"__plotyy_axes__\", ax);\n\n  ## Call position property listener explicitly\n  update_prop (ax(1), [], ax(2), \"position\");\n\nendfunction\n\nfunction deleteplotyy (h, ~, ax2, t2)\n  if (isaxes (ax2) && ! any (strcmp({dbstack().name}, \"plotyy\")))\n    set (t2, \"deletefcn\", []);\n    delete (ax2);\n  endif\nendfunction\n\nfunction update_nextplot (h, ~, ax2)\n  persistent recursion = false;\n\n  if (! recursion)\n    unwind_protect\n      recursion = true;\n      set (ax2, \"nextplot\", get (h, \"nextplot\"));\n    unwind_protect_cleanup\n      recursion = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\nfunction update_prop (h, ~, ax2, prop)\n  persistent recursion = false;\n\n  ## Don't allow recursion\n  if (! recursion && all (ishghandle ([h, ax2])))\n    unwind_protect\n      recursion = true;\n      val = get (h, prop);\n      if (strcmpi (prop, \"position\") || strcmpi (prop, \"outerposition\"))\n        ## Save/restore \"positionconstraint\"\n        constraint = get (ax2, \"positionconstraint\");\n        set (ax2, prop, get (h, prop), \"positionconstraint\", constraint);\n      else\n        set (ax2, prop, get (h, prop));\n      endif\n    unwind_protect_cleanup\n      recursion = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\nfunction color = getcolor (ax)\n\n  obj = get (ax);\n  if (isfield (obj, \"color\"))\n    color = obj.color;\n  elseif (isfield (obj, \"facecolor\") && ! ischar (obj.facecolor))\n    color = obj.facecolor;\n  elseif (isfield (obj, \"edgecolor\") && ! ischar (obj.edgecolor))\n    color = obj.edgecolor;\n  else\n    color = [0, 0, 0];\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = 0:0.1:2*pi;\n%! y1 = sin (x);\n%! y2 = exp (x - 1);\n%! ax = plotyy (x,y1, x-1,y2, @plot, @semilogy);\n%! xlabel (\"X\");\n%! ylabel (ax(1), \"Axis 1\");\n%! ylabel (ax(2), \"Axis 2\");\n%! colororder = get (gca, \"ColorOrder\");\n%! lcolor = colororder(1,:);\n%! rcolor = colororder(2,:);\n%! text (0.5, 0.5, \"Left Axis\", ...\n%!       \"color\", lcolor, \"horizontalalignment\", \"center\", \"parent\", ax(1));\n%! text (4.5, 80, \"Right Axis\", ...\n%!       \"color\", rcolor, \"horizontalalignment\", \"center\", \"parent\", ax(2));\n%! title ({\"plotyy() example\"; \"left axis uses @plot, right axis uses @semilogy\"});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! x = linspace (-1, 1, 201);\n%! subplot (2,2,1);\n%!  plotyy (x,sin (pi*x), x,10*cos (pi*x));\n%!  title (\"plotyy() in subplot\");\n%! subplot (2,2,2);\n%!  surf (peaks (25));\n%! subplot (2,2,3);\n%!  contour (peaks (25));\n%! subplot (2,2,4);\n%!  plotyy (x,10*sin (2*pi*x), x,cos (2*pi*x));\n%!  title (\"plotyy() in subplot\");\n%!  axis square;\n"
  },
  {
    "path": "scripts/plot/draw/polar.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} polar (@var{theta}, @var{rho})\n## @deftypefnx {} {} polar (@var{theta}, @var{rho}, @var{fmt})\n## @deftypefnx {} {} polar (@var{cplx})\n## @deftypefnx {} {} polar (@var{cplx}, @var{fmt})\n## @deftypefnx {} {} polar (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} polar (@dots{})\n## Create a 2-D plot from polar coordinates @var{theta} and @var{rho}.\n##\n## The input @var{theta} is assumed to be radians and is converted to degrees\n## for plotting.  If you have degrees then you must convert\n## (@pxref{XREFcart2pol,,@code{cart2pol}}) to radians before passing the\n## data to this function.\n##\n## If a single complex input @var{cplx} is given then the real part is used\n## for @var{theta} and the imaginary part is used for @var{rho}.\n##\n## The optional argument @var{fmt} specifies the line format in the same way\n## as @code{plot}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n##\n## Implementation Note: The polar axis is drawn using line and text objects\n## encapsulated in an hggroup.  The hggroup properties are linked to the\n## original axes object such that altering an appearance property, for example\n## @code{fontname}, will update the polar axis.  Two new properties are\n## added to the original axes--@code{rtick}, @code{ttick}--which replace\n## @code{xtick}, @code{ytick}.  The first is a list of tick locations in the\n## radial (rho) direction; The second is a list of tick locations in the\n## angular (theta) direction specified in degrees, i.e., in the range 0--359.\n## @seealso{rose, compass, plot, cart2pol}\n## @end deftypefn\n\nfunction h = polar (varargin)\n\n  [hax, varargin, nargs] = __plt_get_axis_arg__ (\"polar\", varargin{:});\n\n  if (nargs < 1)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n\n  if (nargs == 3)\n    if (! ischar (varargin{3}))\n      error (\"polar: FMT argument must be a string\");\n    endif\n    htmp = __plr2__ (hax, varargin{:});\n    maxr = max (abs (varargin{2}(:)));\n  elseif (nargs == 2)\n    if (ischar (varargin{2}))\n      htmp = __plr1__ (hax, varargin{:});\n      if (iscomplex (varargin{1}))\n        maxr = max (abs (imag (varargin{1})(:)));\n      else\n        maxr = max (abs (varargin{1}(:)));\n      endif\n    else\n      fmt = \"\";\n      htmp = __plr2__ (hax, varargin{:}, fmt);\n      maxr = max (abs (varargin{2}(:)));\n    endif\n  elseif (nargs == 1)\n    fmt = \"\";\n    htmp = __plr1__ (hax, varargin{:}, fmt);\n    if (iscomplex (varargin{1}))\n      maxr = max (abs (imag (varargin{1})(:)));\n    else\n      maxr = max (abs (varargin{1}(:)));\n    endif\n  else\n    print_usage ();\n  endif\n\n  if (! ishold (hax))\n    hg = hggroup (hax, \"tag\", \"polar_grid\", \"handlevisibility\", \"off\");\n\n    set (hax, \"visible\", \"off\", \"plotboxaspectratio\", [1, 1, 1],\n              \"zlim\", [-1 1], \"tag\", \"polaraxes\");\n\n    if (! isprop (hax, \"rtick\"))\n      addproperty (\"rtick\", hax, \"data\");\n    endif\n\n    set (hax, \"rtick\", __calc_rtick__ (hax, maxr));\n\n    ## add t(heta)tick\n    if (! isprop (hax, \"ttick\"))\n      addproperty (\"ttick\", hax, \"data\");\n    endif\n\n    ## theta(angular) ticks in degrees\n    set (hax, \"ttick\", 0:30:330);\n\n    __update_polar_grid__ (hax, [], hg);\n\n    set (hg, \"deletefcn\", {@resetaxis, hax});\n\n    addlistener (hax, \"rtick\", {@__update_polar_grid__, hg});\n    addlistener (hax, \"ttick\", {@__update_polar_grid__, hg});\n    addlistener (hax, \"color\", {@__update_patch__, hg});\n    addlistener (hax, \"fontangle\", {@__update_text__, hg, \"fontangle\"});\n    addlistener (hax, \"fontname\", {@__update_text__, hg, \"fontname\"});\n    addlistener (hax, \"fontsize\", {@__update_text__, hg, \"fontsize\"});\n    addlistener (hax, \"fontunits\", {@__update_text__, hg, \"fontunits\"});\n    addlistener (hax, \"fontweight\", {@__update_text__, hg, \"fontweight\"});\n    addlistener (hax, \"ticklabelinterpreter\",\n                 {@__update_text__, hg, \"interpreter\", ...\n                  \"ticklabelinterpreter\"});\n    addlistener (hax, \"layer\", {@__update_layer__, hg});\n    addlistener (hax, \"gridlinestyle\",{@__update_lines__,hg,\"gridlinestyle\"});\n    addlistener (hax, \"linewidth\", {@__update_lines__, hg, \"linewidth\"});\n  else\n    hg = findall (hax, \"tag\", \"polar_grid\");\n    if (! isempty (hg))\n      oldrtick = max (get (hax, \"rtick\"));\n      if (maxr > oldrtick)\n        set (hax, \"rtick\", __calc_rtick__ (hax, maxr));\n      endif\n    endif\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\nfunction rtick = __calc_rtick__ (hax, maxr)\n\n  ## FIXME: workaround: calculate r(ho)tick from xtick\n  ##        It would be better to just calculate the values,\n  ##        but that code is deep in the C++ for the plot engines.\n  saved_lims = get (hax, {\"xlim\", \"ylim\"});\n  set (hax, \"xlim\", [-maxr maxr], \"ylim\", [-maxr maxr]);\n\n  xtick = get (hax, \"xtick\");\n  minidx = find (xtick >= 0, 1);\n  maxidx = find (xtick >= maxr, 1);\n  if (! isempty (maxidx))\n    rtick = xtick(minidx:maxidx);\n  else\n    ## Add one more tick through linear interpolation\n    rtick = xtick(minidx:end);\n    rtick(end+1) = xtick(end) + diff (xtick(end-1:end));\n  endif\n\n  set (hax, {\"xlim\", \"ylim\"}, saved_lims);\n\nendfunction\n\nfunction retval = __plr1__ (h, theta, fmt)\n\n  theta = theta(:);\n  if (iscomplex (theta))\n    rho = imag (theta);\n    theta = real (theta);\n  else\n    rho = theta;\n    theta = (1:rows (rho))';\n  endif\n\n  retval = __plr2__ (h, theta, rho, fmt);\n\nendfunction\n\nfunction retval = __plr2__ (h, theta, rho, fmt)\n\n  if (ndims (theta) > 2 || ndims (rho) > 2)\n    error (\"polar: THETA and RHO must be 2-D objects\");\n  endif\n\n  theta = real (theta);\n  rho = real (rho);\n\n  if (isscalar (theta))\n    if (isscalar (rho))\n      x = rho * cos (theta);\n      y = rho * sin (theta);\n      retval = __plt__ (\"polar\", h, x, y, fmt);\n    else\n      error (\"polar: Can't plot constant THETA with varying RHO\");\n    endif\n  elseif (isvector (theta))\n    if (isvector (rho))\n      if (length (theta) != length (rho))\n        error (\"polar: THETA and RHO vector lengths must match\");\n      endif\n      rho = rho(:);\n      theta = theta(:);\n      x = rho .* cos (theta);\n      y = rho .* sin (theta);\n      retval = __plt__ (\"polar\", h, x, y, fmt);\n    elseif (ismatrix (rho))\n      theta = theta(:);\n      t_nr = rows (theta);\n      [r_nr, r_nc] = size (rho);\n      if (t_nr != r_nr)\n        rho = rho';\n        r_nr = r_nc;\n      endif\n      if (t_nr != r_nr)\n        error (\"polar: THETA vector and RHO matrix sizes must match\");\n      endif\n      x = diag (cos (theta)) * rho;\n      y = diag (sin (theta)) * rho;\n      retval = __plt__ (\"polar\", h, x, y, fmt);\n    else\n      error (\"polar: invalid data for plotting\");\n    endif\n  elseif (ismatrix (theta))\n    if (isvector (rho))\n      rho = rho(:);\n      r_nr = rows (rho);\n      [t_nr, t_nc] = size (theta);\n      if (r_nr != t_nr)\n        theta = theta';\n        t_nr = t_nc;\n      endif\n      if (r_nr != t_nr)\n        error (\"polar: THETA matrix and RHO vector sizes must match\");\n      endif\n      diag_r = diag (rho);\n      x = diag_r * cos (theta);\n      y = diag_r * sin (theta);\n      retval = __plt__ (\"polar\", h, x, y, fmt);\n    elseif (ismatrix (rho))\n      if (! size_equal (rho, theta))\n        error (\"polar: THETA and RHO matrix dimensions must match\");\n      endif\n      x = rho .* cos (theta);\n      y = rho .* sin (theta);\n      retval = __plt__ (\"polar\", h, x, y, fmt);\n    else\n      error (\"polar: invalid data for plotting\");\n    endif\n  else\n    error (\"polar: invalid data for plotting\");\n  endif\n\nendfunction\n\n## Callback functions for listeners\n\nfunction __update_text__ (hax, ~, hg, prop, axprop = \"\")\n\n  if (isempty (axprop))\n    axprop = prop;\n  endif\n\n  kids = get (hg, \"children\");\n  idx = strcmp (get (kids, \"type\"), \"text\");\n  set (kids(idx).', prop, get (hax, axprop));\n\nendfunction\n\nfunction __update_lines__ (hax, ~, hg, prop)\n\n  kids = get (hg, \"children\");\n  idx = strcmp (get (kids, \"type\"), \"line\");\n  lprop = prop;\n  if (strcmp (prop, \"gridlinestyle\"))\n    lprop = \"linestyle\";\n  endif\n  set (kids(idx).', lprop, get (hax, prop));\n\nendfunction\n\nfunction __update_patch__ (hax, ~, hg)\n\n  kids = get (hg, \"children\");\n  idx = strcmp (get (kids, \"type\"), \"patch\");\n  set (kids(idx).', \"facecolor\", get (hax, \"color\"));\n\nendfunction\n\nfunction __update_layer__ (hax, ~, hg)\n\n  ## FIXME: This re-implements allchild() because setting the \"children\"\n  ##        property needs to preserve all children (titles, xlabels, etc.).\n  shh = get (0, \"showhiddenhandles\");\n  unwind_protect\n    set (0, \"showhiddenhandles\", \"on\");\n    kids = get (hax, \"children\");\n    if (strcmp (get (hax, \"layer\"), \"bottom\"))\n      set (hax, \"children\", [kids(kids != hg); hg]);\n    else\n      set (hax, \"children\", [hg; kids(kids != hg)]);\n    endif\n  unwind_protect_cleanup\n    set (0, \"showhiddenhandles\", shh);\n  end_unwind_protect\n\nendfunction\n\nfunction __update_polar_grid__ (hax, ~, hg)\n\n  ## Delete existing polar grid\n  delete (get (hg, \"children\"));\n\n  rtick = unique (get (hax, \"rtick\")(:)');\n  rtick = rtick(rtick > 0);\n  if (isempty (rtick))\n    rtick = [0.5, 1];\n  endif\n\n  ttick = unique (get (hax, \"ttick\")(:)');\n  ttick = ttick(ttick >= 0);\n  if (isempty (ttick))\n    ttick = 0:30:330;\n  endif\n\n  lprops = {\"linestyle\", get(hax, \"gridlinestyle\"), ...\n            \"linewidth\", get(hax, \"linewidth\"), ...\n            \"color\", min(5.8167 * get(hax, \"xcolor\"), 1)};\n  ## \"fontunits\" should be first because it affects \"fontsize\" property.\n  tprops(1:2:12) = {\"fontunits\", \"fontangle\", \"fontname\", \"fontsize\", ...\n                    \"fontweight\", \"ticklabelinterpreter\"};\n  tprops(2:2:12) = get (hax, tprops(1:2:12));\n  tprops(1:2:12) = strrep (tprops(1:2:12), \"ticklabelinterpreter\",\n                           \"interpreter\");\n\n  ## The number of points used for a circle\n  circle_points = 50;\n  t = linspace (0, 2*pi, circle_points)';\n  x = kron (cos (t), rtick);\n  y = kron (sin (t), rtick);\n\n  ## Draw colored disk in the Z=0 plane for solid background and border.\n  ## FIXME: Patch solid border is not visible through polar plot lines.  If\n  ##        solid border visibility is needed without obscuring other plot\n  ##        features additional line objects may be needed.\n  patch (x(:,end), y(:,end), zeros (circle_points, 1),\n         get (hax, \"color\"), \"parent\", hg);\n\n  ## Plot grid circles\n  line (x(:,1:end-1), y(:,1:end-1), lprops{:}, \"parent\", hg);\n\n  ## Outer circle (axes \"box\") is always drawn solid\n  line (x(:,end), y(:,end), lprops{:}, \"linestyle\", \"-\", \"parent\", hg);\n\n  ## Add radial labels\n  ## Labels are arranged along a radius with an angle of 75 degrees.\n  ## 2% addition puts a small visual gap between grid circle and label.\n  [x, y] = pol2cart (0.42 * pi, rtick + (.02 * max (rtick(:))));\n  text (x, y, num2cell (rtick), \"verticalalignment\", \"bottom\", tprops{:},\n        \"parent\", hg);\n\n  ## Add radial lines\n  [x, y] = pol2cart (deg2rad (ttick), rtick(end));\n  x = [zeros(1, numel (ttick)); x];\n  y = [zeros(1, numel (ttick)); y];\n  line (x, y, \"linestyle\", \":\", lprops{:}, \"parent\", hg);\n\n  ## Add angular labels\n  tticklabel = num2cell (ttick);\n  ## FIXME: The 1.08 factor does not work as fontsize increases\n  [x, y] = pol2cart (deg2rad (ttick), 1.08 * rtick(end));\n  text (x, y, tticklabel, \"horizontalalignment\", \"center\", tprops{:},\n        \"parent\", hg);\n\n  lim = 1.1 * rtick(end);\n  set (hax, \"xlim\", [-lim, lim], \"ylim\", [-lim, lim]);\n\n  ## Put polar grid behind or ahead of plot\n  __update_layer__ (hax, [], hg);\n\nendfunction\n\nfunction resetaxis (~, ~, hax)\n\n  if (isaxes (hax))\n    dellistener (hax, \"rtick\");\n    dellistener (hax, \"ttick\");\n    dellistener (hax, \"color\");\n    dellistener (hax, \"fontangle\");\n    dellistener (hax, \"fontname\");\n    dellistener (hax, \"fontsize\");\n    dellistener (hax, \"fontunits\");\n    dellistener (hax, \"fontweight\");\n    dellistener (hax, \"ticklabelinterpreter\");\n    dellistener (hax, \"layer\");\n    dellistener (hax, \"gridlinestyle\");\n    dellistener (hax, \"linewidth\");\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! theta = linspace (0,2*pi,1000);\n%! rho = sin (7*theta);\n%! polar (theta, rho);\n%! title (\"polar() plot\");\n\n%!demo\n%! clf;\n%! theta = linspace (0,2*pi,1000);\n%! cplx = theta + i*sin (7*theta);\n%! polar (cplx, \"g\");\n%! title (\"polar() plot of complex data\");\n\n%!demo\n%! clf;\n%! theta = linspace (0,2*pi,1000);\n%! rho = sin (2*theta).*cos (2*theta);\n%! polar (theta, rho, \"--r\");\n%! set (gca, \"rtick\", 0.1:0.1:0.6, \"ttick\", 0:20:340);\n%! title (\"polar() plot with finer grid\");\n\n%!demo\n%! clf;\n%! theta = linspace (0,2*pi,1000);\n%! rho = sin (2*theta).*cos (2*theta);\n%! polar (theta, rho, \"--b\");\n%! set (gca, \"fontsize\", 12, \"linewidth\", 2, \"color\", [0.8 0.8 0.8]);\n%! title (\"polar() plot with modified axis appearance\");\n\n%!demo\n%! clf;\n%! theta = linspace (0,8*pi,1000);\n%! rho = sin (5/4*theta);\n%! polar (theta, rho);\n%! set (gca, \"rtick\", 0.2:0.2:1);\n%! title (\"polar() plot\");\n\n%!demo\n%! clf;\n%! theta = linspace (0,8*pi,1000);\n%! rho = sin (5/4*theta);\n%! polar (theta, rho);\n%! view (90, -90);\n%! title (\"polar() plot with modified axis orientation\");\n\n## Test correct handle type (line) returned by polar.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!  hax = gca ();\n%!  h = polar (hax, 1, 2);\n%!  h_data = get (h);\n%!  assert (h_data.parent, hax);\n%!  assert (h_data.type, \"line\");\n%!\n%!  h = polar (hax, [1 2 3; 4 5 6], [1 2 3; 4 5 6]);\n%!  h_data = get (h);\n%!  assert (numel (h_data), 3);\n%!  assert (h_data(1).parent, hax);\n%!  assert (isequal (h_data.parent));\n%!  assert (all (strcmp ({h_data.type}, \"line\")));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test scalar/vector/matrix data inputs\n%!test # Scalar inputs\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = polar (hax, 0, 0);\n%!   linedata = get (h);\n%!   assert (linedata.xdata, 0);\n%!   assert (linedata.ydata, 0);\n%!   assert (linedata.zdata, []);\n%!   h = polar (hax, 1, 2);\n%!   linedata = get (h);\n%!   assert (linedata.xdata, 2 * cos (1), eps);\n%!   assert (linedata.ydata, 2 * sin (1), eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test # Vector inputs and orientation independence\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = polar (hax, [1 2 3], [4 5 6]);\n%!   linedata = get (h);\n%!   assert (linedata.xdata, [4 5 6] .* cos ([1 2 3]), eps);\n%!   assert (linedata.ydata, [4 5 6] .* sin ([1 2 3]), eps);\n%!   assert (linedata.zdata, []);\n%!   h = polar (hax, [1 2 3], [4 5 6]');\n%!   linedata = get (h);\n%!   assert (linedata.xdata, [4 5 6] .* cos ([1 2 3]), eps);\n%!   assert (linedata.ydata, [4 5 6] .* sin ([1 2 3]), eps);\n%!   assert (linedata.zdata, []);\n%!   h = polar (hax, [1 2 3]', [4 5 6]);\n%!   linedata = get (h);\n%!   assert (linedata.xdata, [4 5 6] .* cos ([1 2 3]), eps);\n%!   assert (linedata.ydata, [4 5 6] .* sin ([1 2 3]), eps);\n%!   assert (linedata.zdata, []);\n%!   h = polar (hax, [1 2 3]', [4 5 6]');\n%!   linedata = get (h);\n%!   assert (linedata.xdata, [4 5 6] .* cos ([1 2 3]), eps);\n%!   assert (linedata.ydata, [4 5 6] .* sin ([1 2 3]), eps);\n%!   assert (linedata.zdata, []);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test # Matrix inputs\n%! t = [1 2 3; 4 5 6];\n%! r = [7 8 9; 10 11 12];\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = polar (hax, t, r);\n%!   linedata = get (h);\n%!   assert (numel (linedata), 3);\n%!   assert (vertcat (linedata.xdata)', r .* cos (t), eps);\n%!   assert (vertcat (linedata.ydata)', r .* sin (t), eps);\n%!   assert (isempty (vertcat (linedata.zdata)));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test # Mixed Vector/matrix inputs\n%! tv1 = [1 2];\n%! tv2 = [1 2 3];\n%! tm = [1 2 3; 4 5 6];\n%! rv1 = [7 8];\n%! rv2 = [7 8 9];\n%! rm = [7 8 9; 10 11 12];\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!\n%!   h = polar (hax, tv1, rm);\n%!   linedata = get (h);\n%!   assert (numel (linedata), 3);\n%!   assert (vertcat (linedata.xdata)', rm .* cos (tv1'), eps);\n%!   assert (vertcat (linedata.ydata)', rm .* sin (tv1'), eps);\n%!   assert (isempty (vertcat (linedata.zdata)));\n%!\n%!   h = polar (hax, tv1', rm);  # Verify orientation independence.\n%!   linedata = get (h);\n%!   assert (numel (linedata), 3);\n%!   assert (vertcat (linedata.xdata)', rm .* cos (tv1'), eps);\n%!   assert (vertcat (linedata.ydata)', rm .* sin (tv1'), eps);\n%!   assert (isempty (vertcat (linedata.zdata)));\n%!\n%!   h = polar (hax, tv2, rm);\n%!   linedata = get (h);\n%!   assert (numel (linedata), 2);\n%!   assert (vertcat (linedata.xdata), rm .* cos (tv2), eps);\n%!   assert (vertcat (linedata.ydata), rm .* sin (tv2), eps);\n%!   assert (isempty (vertcat (linedata.zdata)));\n%!\n%!   h = polar (hax, tv2', rm);  # Verify orientation independence.\n%!   linedata = get (h);\n%!   assert (numel (linedata), 2);\n%!   assert (vertcat (linedata.xdata), rm .* cos (tv2), eps);\n%!   assert (vertcat (linedata.ydata), rm .* sin (tv2), eps);\n%!   assert (isempty (vertcat (linedata.zdata)));\n%!\n%!   h = polar (hax, tm, rv1);\n%!   linedata = get (h);\n%!   assert (numel (linedata), 3);\n%!   assert (vertcat (linedata.xdata)', rv1' .* cos (tm), eps);\n%!   assert (vertcat (linedata.ydata)', rv1' .* sin (tm), eps);\n%!   assert (isempty (vertcat (linedata.zdata)));\n%!\n%!   h = polar (hax, tm, rv1');  # Verify orientation independence.\n%!   linedata = get (h);\n%!   assert (vertcat (linedata.xdata)', rv1' .* cos (tm), eps);\n%!   assert (vertcat (linedata.ydata)', rv1' .* sin (tm), eps);\n%!   assert (isempty (vertcat (linedata.zdata)));\n%!\n%!   h = polar (hax, tm, rv2);\n%!   linedata = get (h);\n%!   assert (numel (linedata), 2);\n%!   assert (vertcat (linedata.xdata), rv2 .* cos (tm), eps);\n%!   assert (vertcat (linedata.ydata), rv2 .* sin (tm), eps);\n%!   assert (isempty (vertcat (linedata.zdata)));\n%!\n%!   h = polar (hax, tm, rv2');  # Verify orientation independence.\n%!   linedata = get (h);\n%!   assert (numel (linedata), 2);\n%!   assert (vertcat (linedata.xdata), rv2 .* cos (tm), eps);\n%!   assert (vertcat (linedata.ydata), rv2 .* sin (tm), eps);\n%!   assert (isempty (vertcat (linedata.zdata)));\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check that complex input produces identical output to (theta,rho) input\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = polar (hax, [1+2i, 3+4i]);\n%!   haxcplx = get (hax);\n%!   linecplx = get (h);\n%!   h = polar (hax, [1, 3], [2, 4]);\n%!   haxtr = get (hax);\n%!   linetr = get (h);\n%!\n%!   haxtr.children = [];  # Clear child handles that should be unique.\n%!   haxtr.xlabel= [];\n%!   haxtr.ylabel= [];\n%!   haxtr.zlabel= [];\n%!   haxtr.title= [];\n%!   haxcplx.children = [];\n%!   haxcplx.xlabel = [];\n%!   haxcplx.ylabel = [];\n%!   haxcplx.zlabel = [];\n%!   haxcplx.title = [];\n%!\n%!   assert (isequaln (haxcplx, haxtr));    # Check parent objects.\n%!   assert (isequaln (linecplx, linetr));  # Check actual data objects.\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n##Test rtick, ttick being set - including the unlabeled 0 (bug #64991)\n%!test <*64991>\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   polar (hax, [1 2 3], [4 5 6]);\n%!   haxdata = get (hax);\n%!   assert (haxdata.rtick, [0 2 4 6]);\n%!   assert (haxdata.ttick, [0:30:330]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test FMT string inputs\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = polar (hax, [1 2 3], [4 5 6]);\n%!   linedata = get (h);\n%!   assert (linedata.color, [0 0.447 0.741], eps);\n%!   assert (linedata.marker, \"none\");\n%!   assert (linedata.linestyle, \"-\");\n%!   h = polar (hax, [1 2 3], [4 5 6], \"r\");\n%!   linedata = get (h);\n%!   assert (linedata.color, [1 0 0]);\n%!   assert (linedata.marker, \"none\");\n%!   assert (linedata.linestyle, \"-\");\n%!   h = polar (hax, [1 2 3], [4 5 6], \"--\");\n%!   linedata = get (h);\n%!   assert (linedata.color, [0 0.447 0.741], eps);\n%!   assert (linedata.marker, \"none\");\n%!   assert (linedata.linestyle, \"--\");\n%!   h = polar (hax, [1 2 3], [4 5 6], \"*--r\");\n%!   linedata = get (h);\n%!   assert (linedata.color, [1 0 0], eps);\n%!   assert (linedata.marker, \"*\");\n%!   assert (linedata.linestyle, \"--\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> polar ()\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   fail (\"polar (hax, 1, 2, 3)\", \"FMT argument must be a string\");\n%!   fail (\"polar (hax, cat (3, 1, 2, 3), [1 2 3])\", \"THETA and RHO must be 2-D objects\");\n%!   fail (\"polar (hax, [1 2 3], cat (3, 1, 2, 3))\", \"THETA and RHO must be 2-D objects\");\n%!   fail (\"polar (hax, 1, [1 2 3])\", \"Can't plot constant THETA with varying RHO\");\n%!   fail (\"polar (hax, [1 2 3], 1)\", \"THETA and RHO vector lengths must match\");\n%!   fail (\"polar (hax, [1 2 3],[1 2])\", \"THETA and RHO vector lengths must match\");\n%!   fail (\"polar (hax, [1 2 3], [1 2; 3 4])\", \"THETA vector and RHO matrix sizes must match\");\n%!   fail (\"polar (hax, [1 2; 3 4], [1 2 3])\", \"THETA matrix and RHO vector sizes must match\");\n%!   fail (\"polar (hax, [1 2; 3 4], [1 2 3; 4 5 6])\", \"THETA and RHO matrix dimensions must match\");\n%!   h = polar (hax, 1, 2);  # Generates line object handle.\n%!   fail (\"polar (h, 1, 2)\", \"first argument must be axes handle\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/private/__add_datasource__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{newargs} =} __add_datasource__ (@var{fcn}, @var{h}, @var{data}, @var{varargin})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction newargs = __add_datasource__ (fcn, h, data, varargin)\n\n  if (ischar (data))\n    data = {data};\n  endif\n\n  for i = 1 : numel (data)\n    addproperty ([data{i} \"datasource\"], h, \"string\", \"\");\n  endfor\n\n  i = 0;\n  newargs = {};\n  while (i < numel (varargin))\n    arg = varargin{++i};\n    if (i != numel (varargin) && ischar (arg)\n        && length (arg) > 9 && strcmpi (arg(end-9:end), \"datasource\"))\n      arg = lower (arg);\n      val = varargin{++i};\n      if (ischar (val))\n        set (h, arg, val);\n      else\n        error (\"%s: datasource must be a string\", fcn);\n      endif\n    else\n      newargs{end + 1} = arg;\n    endif\n  endwhile\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__bar__.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{varargout} =} __bar__ (@var{fcn}, @var{vertical}, @dots{})\n## Internal function with common code to implement @code{bar} and @code{barh}\n## plots.\n## @seealso{bar, barh}\n## @end deftypefn\n\nfunction varargout = __bar__ (fcn, vertical, varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (fcn, varargin{:});\n\n  if (! isnumeric (varargin{1}))\n    error (\"%s: Y must be numeric\", fcn);\n  endif\n\n  width = 0.8;\n  group = true;\n  stacked = false;\n  histc = NA;\n  ## BaseValue\n  if (strcmp (get (hax, \"yscale\"), \"log\"))\n    bv = 1;\n  else\n    bv = 0;\n  endif\n\n  if (nargin > 1 && isnumeric (varargin{2}))\n    x = varargin{1};\n    if (isvector (x))\n      x = x(:);\n    endif\n    y = varargin{2};\n    if (isvector (y))\n      y = y(:);\n    endif\n    if (isscalar (y) && ! isscalar (x))\n      ## \"y\" is actually \"width\" argument\n      y = x;\n      x = [1:rows(y)]';\n      idx = 2;\n    else\n      if (! isvector (x))\n        error (\"%s: X must be a vector\", fcn);\n      elseif (numel (unique (x)) != numel (x))\n        error (\"%s: X vector values must be unique\", fcn);\n      endif\n      idx = 3;\n    endif\n  else\n    y = varargin{1};\n    if (isvector (y))\n      y = y(:);\n    endif\n    x = [1:rows(y)]';\n    idx = 2;\n  endif\n\n  newargs = {};\n  have_line_spec = false;\n  while (idx <= nargin)\n    if (ischar (varargin{idx}) && strcmpi (varargin{idx}, \"grouped\"))\n      group = true;\n      idx += 1;\n    elseif (ischar (varargin{idx}) && strcmpi (varargin{idx}, \"stacked\"))\n      stacked = true;\n      group = false;\n      idx += 1;\n    elseif (ischar (varargin{idx}) && strcmpi (varargin{idx}, \"histc\"))\n      group = true;\n      histc = true;\n      idx += 1;\n    elseif (ischar (varargin{idx}) && strcmpi (varargin{idx}, \"hist\"))\n      group = true;\n      histc = false;\n      idx += 1;\n    else\n      if ((ischar (varargin{idx}) || iscellstr (varargin{idx}))\n          && ! have_line_spec)\n        [linespec, valid] = __pltopt__ (fcn, varargin{idx}, false);\n        if (valid)\n          have_line_spec = true;\n          ## FIXME: strange parse error requires semicolon to be spaced\n          ##        away from closing ']' on next line.\n          newargs = [{\"facecolor\", linespec.color}, newargs] ;\n          idx += 1;\n          continue;\n        endif\n      endif\n      if (isscalar (varargin{idx}))\n        width = varargin{idx++};\n      elseif (idx == nargin)\n        newargs = [newargs, varargin(idx++)];\n      elseif (ischar (varargin{idx})\n              && strcmpi (varargin{idx}, \"basevalue\")\n              && isscalar (varargin{idx+1}))\n        bv = varargin{idx+1};\n        idx += 2;\n      else\n        newargs = [newargs, varargin(idx:idx+1)];\n        idx += 2;\n      endif\n    endif\n  endwhile\n\n  ishist = islogical (histc);\n  ngrp = rows (x);\n\n  if (isvector (y) && ngrp != rows (y))\n    y = y.';\n  endif\n  if (ngrp != rows (y))\n    error (\"%s: length of X and Y must be equal\", fcn);\n  endif\n\n  nbars = columns (y);\n\n  ## Column width is 1 for 'hist*' styles (bars touch).\n  if (ishist)\n    cwidth = 1;\n    if (nbars == 1)\n      gwidth = 1;\n    else\n      gwidth = width^2;\n    endif\n  elseif (nbars == 1)\n    cwidth = 1;\n    gwidth = width;\n  else\n    cwidth = gwidth = width;\n  endif\n\n  ## Complicated algorithm sizes bars with unitless parameter width.\n  ## If width is 1.0, adjacent bars in a group are touching.\n  ## Otherwise, bar size is cwidth and the remaining space is split evenly on\n  ## either side of the bar.  For the default 0.8, spacing is [0.1 0.8 0.1].\n  ## Groups of bars are spaced by gwidth.  If gwidth is 1.0 then adjacent\n  ## groups will just touch.\n  if (numel (x) > 1)\n    cutoff = min (diff (double (x))) / 2;\n  else\n    cutoff = 1;\n  endif\n  if (group)\n    gdelta = cutoff * gwidth / nbars;\n    cdelta = repmat ((1 - ((1 - cwidth) / 2)) * gdelta, size (x));\n  else\n    cdelta = repmat (cutoff * gwidth, size (x));\n  endif\n  x1 = (x - cdelta)(:)';\n  x2 = (x + cdelta)(:)';\n  xb = repmat ([x1; x1; x2; x2](:), 1, nbars);\n\n  if (group)\n    if (ishist && histc)\n      offset = 2*cdelta * [0:(nbars-1)] + cdelta(1);  # not centered\n    else\n      offset = 2*cdelta * [-(nbars - 1) / 2 : (nbars - 1) / 2];\n    endif\n\n    xb(1:4:4*ngrp,:) += offset + (1-cwidth) / 2 * (2 * gdelta);\n    xb(2:4:4*ngrp,:) += offset + (1-cwidth) / 2 * (2 * gdelta);\n    xb(3:4:4*ngrp,:) += offset - (1-cwidth) / 2 * (2 * gdelta);\n    xb(4:4:4*ngrp,:) += offset - (1-cwidth) / 2 * (2 * gdelta);\n\n    y0 = zeros (size (y)) + bv;\n    y1 = y;\n  else\n    if (stacked && any (y(:) < 0))\n      ypos = (y >= 0);\n      yneg = (y <  0);\n\n      y1p =  cumsum (y .* ypos, 2);\n      y1n =  cumsum (y .* yneg, 2);\n      y1 = y1p .* ypos + y1n .* yneg;\n\n      y0p = [zeros(ngrp,1)+bv, y1p(:,1:end-1)];\n      y0n = [zeros(ngrp,1)+bv, y1n(:,1:end-1)];\n      y0 = y0p .* ypos + y0n .* yneg;\n\n    else\n      y1 = cumsum (y,2);\n      y0 = [zeros(ngrp,1)+bv, y1(:,1:end-1)];\n    endif\n  endif\n\n  yb = zeros (4*ngrp, nbars);\n  yb(1:4:4*ngrp,:) = y0;\n  yb(2:4:4*ngrp,:) = y1;\n  yb(3:4:4*ngrp,:) = y1;\n  yb(4:4:4*ngrp,:) = y0;\n\n  xb = reshape (xb, [4, ngrp, nbars]);\n  yb = reshape (yb, [4, ngrp, nbars]);\n\n  if (nargout < 2)\n    hax = newplot (hax);\n    htmp = bars (hax, ishist, vertical, x, y, xb, yb, gwidth, group,\n                 have_line_spec, bv, newargs{:});\n    if (! ishold (hax))\n      update_axes_limits (hax, x, vertical, ishist && histc);\n    endif\n\n    if (nargout == 1)\n      varargout{1} = htmp;\n    endif\n  else\n    if (vertical)\n      varargout{1} = xb;\n      varargout{2} = yb;\n    else\n      varargout{1} = yb;\n      varargout{2} = xb;\n    endif\n  endif\n\nendfunction\n\nfunction hglist = bars (hax, ishist, vertical, x, y, xb, yb, width, group,\n                        have_color_spec, base_value, varargin)\n\n  hglist = [];\n  nbars = columns (y);\n\n  if (ishist)\n    ## Special case for Matlab compatibility.  For 'hist', 'histc' arguments,\n    ## return Patch objects rather than hggroup Bar object.\n    for i = 1:nbars\n\n      if (vertical)\n        h = patch (hax, xb(:,:,i), yb(:,:,i),\n                   \"cdata\", i, \"FaceColor\", \"flat\");\n      else\n        h = patch (hax, yb(:,:,i), xb(:,:,i),\n                   \"cdata\", i, \"FaceColor\", \"flat\");\n      endif\n\n      if (! isempty (varargin))\n        set (h, varargin{:});\n      endif\n\n      hglist = [hglist; h];\n    endfor\n    return;  # return immediately, rest of function creates Bar object.\n  endif\n\n  ## Code to create hggroup Bar object\n  for i = 1:nbars\n    hg = hggroup (hax);\n    hglist = [hglist; hg];\n    args = __add_datasource__ (\"bar\", hg, {\"x\", \"y\"}, varargin{:});\n\n    if (vertical)\n      if (! have_color_spec)\n        color = __next_line_color__ (hax);\n        h = patch (hax, xb(:,:,i), yb(:,:,i), \"FaceColor\", color, \"parent\", hg);\n      else\n        h = patch (hax, xb(:,:,i), yb(:,:,i), \"cdata\", i, \"parent\", hg);\n      endif\n    else\n      if (! have_color_spec)\n        color = __next_line_color__ (hax);\n        h = patch (hax, yb(:,:,i), xb(:,:,i), \"FaceColor\", color, \"parent\", hg);\n      else\n        h = patch (hax, yb(:,:,i), xb(:,:,i), \"cdata\", i, \"parent\", hg);\n      endif\n    endif\n\n    if (i == 1)\n      ## Add baseline object the first time through loop\n      ## Undocumented x/yliminclude property prevents baseline from affecting\n      ## x/ylim perpendicular to bar direction, but x/ylim parallel to bar\n      ## direction must be sensitive to baseline position.\n      if (vertical)\n        x_axis_range = get (hax, \"xlim\");\n        baseline = __go_line__ (hg, \"xdata\", x_axis_range,\n                                    \"ydata\", [base_value, base_value],\n                                    \"color\", [0, 0, 0]);\n        set (baseline, \"handlevisibility\", \"off\", \"xliminclude\", \"off\");\n      else\n        y_axis_range = get (hax, \"ylim\");\n        baseline = __go_line__ (hg, \"ydata\", y_axis_range,\n                                    \"xdata\", [base_value, base_value],\n                                    \"color\", [0, 0, 0]);\n        set (baseline, \"handlevisibility\", \"off\", \"yliminclude\", \"off\");\n      endif\n    endif\n\n    ## Setup the hggroup and listeners\n    addproperty (\"showbaseline\", hg, \"radio\", \"{on}|off\");\n    addproperty (\"basevalue\", hg, \"data\", base_value);\n    addproperty (\"baseline\", hg, \"data\", baseline);\n\n    addlistener (hg, \"showbaseline\", {@show_baseline, \"showbl\"});\n    addlistener (hg, \"visible\", {@show_baseline, \"visib\"});\n    addlistener (hg, \"basevalue\", @move_baseline);\n\n    addproperty (\"barwidth\", hg, \"data\", width);\n    if (group)\n      addproperty (\"barlayout\", hg, \"radio\", \"stacked|{grouped}\", \"grouped\");\n    else\n      addproperty (\"barlayout\", hg, \"radio\", \"{stacked}|grouped\", \"stacked\");\n    endif\n\n    if (vertical)\n      addproperty (\"horizontal\", hg, \"radio\", \"on|{off}\", \"off\");\n    else\n      addproperty (\"horizontal\", hg, \"radio\", \"{on}|off\", \"on\");\n    endif\n\n    addlistener (hg, \"barwidth\", @update_group);\n    addlistener (hg, \"barlayout\", @update_group);\n    addlistener (hg, \"horizontal\", @update_group);\n\n    addproperty (\"edgecolor\", hg, \"patchedgecolor\", get (h, \"edgecolor\"));\n    addproperty (\"facecolor\", hg, \"patchfacecolor\", get (h, \"facecolor\"));\n    addproperty (\"linestyle\", hg, \"patchlinestyle\", get (h, \"linestyle\"));\n    addproperty (\"linewidth\", hg, \"patchlinewidth\", get (h, \"linewidth\"));\n\n    addlistener (hg, \"edgecolor\", @update_props);\n    addlistener (hg, \"facecolor\", @update_props);\n    addlistener (hg, \"linestyle\", @update_props);\n    addlistener (hg, \"linewidth\", @update_props);\n\n    addproperty (\"xdata\", hg, \"data\", x);\n    addproperty (\"ydata\", hg, \"data\", y(:, i));\n\n    addlistener (hg, \"xdata\", @update_data);\n    addlistener (hg, \"ydata\", @update_data);\n\n    addproperty (\"bargroup\", hg, \"data\");\n    set (hglist, \"bargroup\", hglist);\n\n    ## Matlab property, although Octave does not implement it.\n    addproperty (\"hittestarea\", hg, \"radio\", \"on|{off}\", \"off\");\n\n    if (! isempty (args))\n      set (hg, args{:});\n    endif\n  endfor\n\n  update_baseline_lim (hax, [], hglist(1));\n\n  ## Add listeners outside of for loop to prevent constant updating during\n  ## creation of plot when patch objects are added.\n  ubll = {@update_baseline_lim, hglist(1)};\n  ubvls = {@update_basevalue_logscale, hglist(1)};\n  ## Add delete function on baseline to remove all listeners from axes\n  ## properties when the bar plot is cleared.\n  set (baseline, \"deletefcn\", {@rm_axes_listeners, hax, ubll, ubvls});\n  addlistener (hax, \"xlim\", ubll);\n  addlistener (hax, \"yscale\", ubvls);\n  addlistener (baseline, \"ydata\", {@update_baseline, hglist(1)});\n\n  addlistener (hax, \"ylim\", ubll);\n  addlistener (hax, \"xscale\", ubvls);\n  addlistener (baseline, \"xdata\", {@update_baseline, hglist(1)});\n\n  addlistener (baseline, \"visible\", {@update_baseline, hglist(1)});\n\nendfunction\n\n## Good practice to remove listeners to external objects when deleted.\n## Required to avoid error in update_baseline_lim callback (bug #67004).\nfunction rm_axes_listeners (~, ~, hax, ubll, ubvls)\n  dellistener (hax, \"xlim\", ubll);\n  dellistener (hax, \"yscale\", ubvls);\n  dellistener (hax, \"ylim\", ubll);\n  dellistener (hax, \"xscale\", ubvls);\nendfunction\n\nfunction update_baseline_lim (hax, ~, hg)\n\n  ## set baseline extents to match current axes limits\n  [xlim, ylim] = get (hax, {\"xlim\", \"ylim\"}){:};\n  vertical = strcmp (get (hg, \"horizontal\"), \"off\");\n  hl = get (hg, \"baseline\");\n\n  if (vertical)\n    if (any (get (hl, \"xdata\") != xlim))\n      set (hl, \"xdata\", xlim);\n    endif\n  else\n    if (any (get (hl, \"ydata\") != ylim))\n      set (hl, \"ydata\", ylim);\n    endif\n  endif\n\nendfunction\n\n\nfunction update_basevalue_logscale (hax, ~, hg)\n\n  if (strcmp (get (hg, \"horizontal\"), \"off\"))\n    axisscale = \"yscale\";\n  else\n    axisscale = \"xscale\";\n  endif\n\n  if (strcmp (get (hax, axisscale), \"log\"))\n    warning (\"off\", \"Octave:negative-data-log-axis\", \"local\");\n    if (get (hg, \"basevalue\") == 0)\n      set (hg, \"basevalue\", 1);\n    endif\n  else\n    if (get (hg, \"basevalue\") == 1)\n      set (hg, \"basevalue\", 0);\n    endif\n  endif\n\nendfunction\n\n\nfunction update_baseline (hl, ~, hg)\n\n  visible = get (hl, \"visible\");\n\n  if (strcmp (get (hg, \"horizontal\"), \"off\"))\n    data = get (hl, \"ydata\")(1);\n  else\n    data = get (hl, \"xdata\")(1);\n  endif\n\n  set (hg, \"showbaseline\", visible, \"basevalue\", data);\n\nendfunction\n\n\nfunction show_baseline (hg, ~, prop)\n\n  persistent recursion = false;\n\n  ## Don't allow recursion\n  if (! recursion)\n    unwind_protect\n      recursion = true;\n      hlist = get (hg, \"bargroup\");\n      if (strcmp (prop, \"showbl\"))\n        showbaseline = get (hg, \"showbaseline\");\n        hlist = hlist(hlist != hg);  # remove current handle being updated\n        set (hlist, \"showbaseline\", showbaseline);\n      elseif (strcmp (prop, \"visib\"))\n        showbaseline = \"on\";\n        if (all (strcmp (get (hlist, \"visible\"), \"off\")))\n          showbaseline = \"off\";\n        endif\n      endif\n      set (get (hg, \"baseline\"), \"visible\", showbaseline);\n    unwind_protect_cleanup\n      recursion = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\n\nfunction move_baseline (hg, ~)\n\n  persistent recursion = false;\n  ## Don't allow recursion\n  if (! recursion)\n\n    recursion = true;\n    unwind_protect\n      [b0, bl] = get (hg, {\"basevalue\", \"baseline\"}){:};\n\n      if (strcmp (get (hg, \"horizontal\"), \"off\"))  # if (vertical)\n        set (bl, \"ydata\", [b0, b0]);\n      else\n        set (bl, \"xdata\", [b0, b0]);\n      endif\n\n      if (strcmp (get (hg, \"barlayout\"), \"grouped\"))\n        update_data (hg);\n      endif\n    unwind_protect_cleanup\n      recursion = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\n\nfunction update_props (hg, ~)\n  kids = get (hg, \"children\");\n  set (kids, {\"edgecolor\", \"linewidth\", \"linestyle\", \"facecolor\"},\n       get (hg, {\"edgecolor\", \"linewidth\", \"linestyle\", \"facecolor\"}));\nendfunction\n\n\nfunction update_data (hg, ~)\n\n  persistent recursion = false;\n  ## Don't allow recursion\n  if (! recursion)\n    unwind_protect\n      recursion = true;\n      hlist = get (hg, \"bargroup\");\n      x = get (hg, \"xdata\");\n      if (! isvector (x))\n        x = x(:);\n      endif\n      ydat = get (hlist, \"ydata\");\n      if (iscell (ydat))\n        y = cell2mat (ydat.');\n      elseif (isvector (ydat))\n        y = ydat(:);\n      else\n        y = ydat;\n      endif\n\n      [b0, bl, bw, blo, horiz, hax] = ...\n        get (hg, {\"basevalue\", \"baseline\", \"barwidth\", \"barlayout\", ...\n                  \"horizontal\", \"parent\"}){:};\n      [xb, yb] = bar (x, y, bw, blo, \"basevalue\", b0);\n\n      vertical = strcmp (horiz, \"off\");\n      for i = 1:columns (y)\n        hp = get (hlist(i), \"children\");\n        if (vertical)\n          set (hp, \"xdata\", xb(:,:,i), \"ydata\", yb(:,:,i));\n        else\n          set (hp, \"xdata\", yb(:,:,i), \"ydata\", xb(:,:,i));\n        endif\n      endfor\n\n      ## Update baseline properties affecting x/ylim\n      if (vertical)\n        set (bl, {\"xliminclude\", \"yliminclude\"}, {\"off\", \"on\"});\n        set (bl, \"ydata\", [b0, b0]);\n      else\n        set (bl, {\"xliminclude\", \"yliminclude\"}, {\"on\", \"off\"});\n        set (bl, \"xdata\", [b0, b0]);\n      endif\n\n      if (! ishold (hax))\n        update_axes_limits (hax, x, vertical, strcmpi (blo, \"histc\"));\n      endif\n\n      ## Update baseline extents to x/ylim.\n      if (vertical)\n        set (bl, \"xdata\", get (hax, \"xlim\"));\n      else\n        set (bl, \"ydata\", get (hax, \"ylim\"));\n      endif\n\n    unwind_protect_cleanup\n      recursion = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\n\nfunction update_group (hg, ~)\n\n  persistent recursion = false;\n  ## Don't allow recursion\n  if (! recursion)\n    unwind_protect\n      recursion = true;\n      hlist = get (hg, \"bargroup\");\n      barwidth = get (hg, \"barwidth\");\n      barlayout = get (hg, \"barlayout\");\n      horizontal = get (hg, \"horizontal\");\n\n      hlist = hlist(hlist != hg);  # remove current handle being updated\n      set (hlist, \"barwidth\", barwidth, \"barlayout\", barlayout,\n                  \"horizontal\", horizontal);\n      update_data (hg);\n    unwind_protect_cleanup\n      recursion = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\n\nfunction update_axes_limits (hax, x, vertical, ishistc)\n\n  if (numel (x(:,1)) <= 15 && all (x(:,1) == fix (x(:,1))))\n    ## Set manual ticks, rather than relying on autoselection, when ticks are\n    ## a small number of integers.\n    ## Then temporarily set to auto to reset limits around patch elements and\n    ## baseline component parallel to bars.\n\n    ## Vector x inputs to bar are forced to be column vectors.  x inputs from\n    ## set command may be forced to row vectors.  Ensure column vector for\n    ## bar tick processing.  See bug #65734.\n    if (isrow (x))\n      x = x(:);\n    endif\n\n    if (vertical)\n      set (hax, \"xtick\", x(:,1));\n      set (hax, \"xlimmode\", \"auto\");\n      set (hax, \"ytickmode\", \"auto\");\n    else\n      set (hax, \"ytick\", x(:,1));\n      set (hax, \"ylimmode\", \"auto\");\n      set (hax, \"xtickmode\", \"auto\");\n    endif\n  endif\n\n  if (ishistc)\n    set (hax, \"climmode\", \"auto\");\n  endif\n\n  set (hax, \"box\", \"on\", \"layer\", \"top\");\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__calc_isovalue_from_data__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{isoval} =} __calc_isovalue_from_data__ (@var{data})\n## Calculate a @nospell{\"good\"} iso value from histogram of data.\n## @end deftypefn\n\n## called from isocaps, isosurface\n\nfunction isoval = __calc_isovalue_from_data__ (data)\n\n  ## use a maximum of 10,000-20,000 samples to limit runtime of hist\n  step = 1;\n  ndata = numel (data);\n  if (ndata > 20_000)\n    step = floor (ndata / 10_000);\n    data = data(1:step:end);\n    ndata = numel (data);\n  endif\n\n  num_bins = 100;\n  [bin_count, bin_centers] = hist (data(:), num_bins);\n\n  ## if one of the first two bins contains more than 10 times the count as\n  ## compared to equally distributed data, remove both (zero-padded + noise)\n  if (any (bin_count(1:2) > 10 * (ndata / num_bins)))\n    bin_count(1:2) = [];\n    bin_centers(1:2) = [];\n  endif\n\n  ## if bins have low counts, remove them (but keep them if we would lose\n  ## more than 90% of bins)\n  bins_to_remove = find (bin_count < max (bin_count)/50);\n  if (length (bins_to_remove) < .9 * num_bins)\n    bin_centers(bins_to_remove) = [];\n  endif\n\n  ## select middle bar of histogram with previous conditions\n  isoval = bin_centers(floor (numel (bin_centers) / 2));\n\nendfunction\n\n\n%!assert (__calc_isovalue_from_data__ (1:5), 3.02)\n"
  },
  {
    "path": "scripts/plot/draw/private/__contour__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{c}, @var{hg}] =} __contour__ (@dots{})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [c, hg] = __contour__ (varargin)\n\n  ax = varargin{1};\n  zlevel = varargin{2};\n  filled = \"off\";\n\n  linespec.color = \"auto\";\n  linespec.linestyle = \"-\";\n  opts = {};\n  i = 3;\n  while (i <= length (varargin))\n    if (ischar (varargin{i}) || iscellstr (varargin{i}))\n      arg = varargin{i};\n      if (i < length (varargin))\n        if (strcmpi (arg, \"fill\"))\n          filled = varargin{i+1};\n          varargin(i:i+1) = [];\n          continue;\n        elseif (strcmpi (arg, \"linecolor\"))\n          linespec.color = varargin{i+1};\n          varargin(i:i+1) = [];\n          continue;\n        endif\n      endif\n\n      [lspec, valid] = __pltopt__ (\"__contour__\", arg, false);\n      if (valid)\n        varargin(i) = [];\n        if (! isempty (lspec.color))\n          linespec.color = lspec.color;\n        endif\n        if (! isempty (lspec.linestyle))\n          linespec.linestyle = lspec.linestyle;\n        endif\n      else  # unrecognized option, pass unmodified in opts cell array\n        if (i >= numel (varargin))\n          error (\"__contour__: Uneven number of PROP/VAL pairs\");\n        endif\n        opts(end+(1:2)) = varargin(i:i+1);\n        varargin(i:i+1) = [];\n      endif\n\n    else  # skip numeric arguments\n      i += 1;\n    endif\n  endwhile\n\n  if (length (varargin) < 5)\n    z1 = varargin{3};\n    x1 = 1 : columns (z1);\n    y1 = 1 : rows (z1);\n    if (! ismatrix (z1))\n      error (\"__contour__: Z must be a 2-D matrix\");\n    endif\n  else\n    x1 = varargin{3};\n    y1 = varargin{4};\n    z1 = varargin{5};\n    if (! ismatrix (z1) || ! ismatrix (x1) || ! ismatrix (y1))\n      error (\"__contour__: X, Y, and Z must be matrices\");\n    endif\n    if (isvector (x1))\n      if (columns (z1) != length (x1))\n        error (\"__contour__: size of X must match number of columns in Z\");\n      endif\n    else\n      if (! size_equal (x1, z1))\n        error (\"__contour__: size of X and Z must match\");\n      endif\n    endif\n    if (isvector (y1))\n      if (rows (z1) != length (y1))\n        error (\"__contour__: size of Y must match number of rows in Z\");\n      endif\n    else\n      if (! size_equal (y1, z1))\n        error (\"__contour__: size of Y and Z must match\");\n      endif\n    endif\n  endif\n\n  if (length (varargin) == 4 || length (varargin) == 6)\n    vn = varargin{end};\n    vnauto = false;\n  else\n    vn = 10;\n    vnauto = true;\n  endif\n\n  if (isscalar (vn))\n    ## FIXME: The levels should be determined similarly to {x,y,z}ticks\n    ##        so that they aren't set at extremely odd values.\n    lvl = linspace (min (z1(! isinf (z1))), max (z1(! isinf (z1))), vn + 2);\n    ## Strip off max outlier, min must stay for contourf hole algorithm.\n    lvl = lvl(1:end-1);\n  else\n    lvl = sort (vn);\n  endif\n\n  if (strcmpi (filled, \"on\"))\n    if (isvector (x1) || isvector (y1))\n      [x1, y1] = meshgrid (x1, y1);\n    endif\n    [nr, nc] = size (z1);\n    x0 = prepad (x1, nc+1, 2 * x1(1, 1) - x1(1, 2), 2);\n    x0 = postpad (x0, nc+2, 2 * x1(1, nc) - x1(1, nc - 1), 2);\n    x0 = [x0(1, :); x0; x0(1, :)];\n    y0 = prepad (y1, nr+1, 2 * y1(1, 1) - y1(2, 1), 1);\n    y0 = postpad (y0, nr+2, 2 * y1(nr, 1) - y1(nr - 1, 1));\n    y0 = [y0(:, 1), y0, y0(:, 1)];\n    z0 = -Inf (nr+2, nc+2);\n    z0(2:nr+1, 2:nc+1) = z1;\n    [c, lev] = contourc (x0, y0, z0, lvl);\n  else\n    [c, lev] = contourc (x1, y1, z1, lvl);\n  endif\n\n  hg = hggroup (ax, \"__appdata__\", struct (\"__creator__\", \"__contour__\"));\n  opts = __add_datasource__ (\"__countour__\", hg, {\"x\", \"y\", \"z\"}, opts{:});\n\n  addproperty (\"xdata\", hg, \"data\", x1);\n  addproperty (\"ydata\", hg, \"data\", y1);\n  addproperty (\"zdata\", hg, \"data\", z1);\n  addproperty (\"contourmatrix\", hg, \"data\", c);\n\n  addlistener (hg, \"xdata\", @update_data);\n  addlistener (hg, \"ydata\", @update_data);\n  addlistener (hg, \"zdata\", @update_data);\n  addlistener (hg, \"contourmatrix\", @update_data);\n\n  addproperty (\"fill\", hg, \"radio\", \"on|{off}\", filled);\n\n  ## The properties zlevel and zlevelmode don't exist in matlab, but allow the\n  ## use of contourgroups with the contour3, meshc, and surfc functions.\n  if (isnumeric (zlevel))\n    addproperty (\"zlevelmode\", hg, \"radio\", \"{none}|auto|manual\", \"manual\");\n    addproperty (\"zlevel\", hg, \"data\", zlevel);\n  else\n    addproperty (\"zlevelmode\", hg, \"radio\", \"{none}|auto|manual\", zlevel);\n    addproperty (\"zlevel\", hg, \"data\", 0.);\n  endif\n\n  lvlstep = sum (diff (lvl)) / (length (lvl) - 1);\n\n  addproperty (\"levellist\", hg, \"data\", lev);\n  addproperty (\"levelstep\", hg, \"double\", lvlstep);\n  if (vnauto)\n    addproperty (\"levellistmode\", hg, \"radio\", \"{auto}|manual\", \"auto\");\n    addproperty (\"levelstepmode\", hg, \"radio\", \"{auto}|manual\", \"auto\");\n  elseif (isscalar (vn))\n    addproperty (\"levellistmode\", hg, \"radio\", \"{auto}|manual\", \"auto\");\n    addproperty (\"levelstepmode\", hg, \"radio\", \"{auto}|manual\", \"manual\");\n  else\n    addproperty (\"levellistmode\", hg, \"radio\", \"{auto}|manual\", \"manual\");\n    addproperty (\"levelstepmode\", hg, \"radio\", \"{auto}|manual\", \"auto\");\n  endif\n\n  addproperty (\"labelspacing\", hg, \"double\", 144);\n  addproperty (\"textlist\", hg, \"data\", lev);\n  addproperty (\"textlistmode\", hg, \"radio\", \"{auto}|manual\", \"auto\");\n  addproperty (\"textstep\", hg, \"double\", lvlstep);\n  addproperty (\"textstepmode\", hg, \"radio\", \"{auto}|manual\", \"auto\");\n  addproperty (\"showtext\", hg, \"radio\", \"on|{off}\", \"off\");\n\n  addproperty (\"linecolor\", hg, \"color\", linespec.color, \"{auto}|none\");\n  addproperty (\"linestyle\", hg, \"linelinestyle\", linespec.linestyle);\n  addproperty (\"linewidth\", hg, \"linelinewidth\", 0.5);\n\n  ## Matlab property just for compatibility (bug #60513).\n  addproperty (\"facecolor\", hg, \"patchfacecolor\", \"none\");\n\n  ## Matlab property, although Octave does not implement it.\n  addproperty (\"hittestarea\", hg, \"radio\", \"on|{off}\", \"off\");\n\n  addlistener (hg, \"fill\", {@update_data, \"fill\"});\n\n  addlistener (hg, \"zlevelmode\", @update_zlevel);\n  addlistener (hg, \"zlevel\", @update_zlevel);\n\n  addlistener (hg, \"levellist\", {@update_data, \"levellist\"});\n  addlistener (hg, \"levelstep\", {@update_data, \"levelstep\"});\n  addlistener (hg, \"levellistmode\", @update_data);\n  addlistener (hg, \"levelstepmode\", @update_data);\n\n  addlistener (hg, \"labelspacing\", @update_text);\n  addlistener (hg, \"textlist\", {@update_text, \"textlist\"});\n  addlistener (hg, \"textlistmode\", @update_text);\n  addlistener (hg, \"textstep\", {@update_text, \"textstep\"});\n  addlistener (hg, \"textstepmode\", @update_text);\n  addlistener (hg, \"showtext\", @update_text);\n\n  addlistener (hg, \"linecolor\", @update_line);\n  addlistener (hg, \"linestyle\", @update_line);\n  addlistener (hg, \"linewidth\", @update_line);\n\n  ## Set axis before adding patches so that each new patch does not trigger\n  ## new axis calculation.  No need if mode is already \"manual\".\n  if (all (strcmp (get (ax, {\"xlimmode\", \"ylimmode\"}), \"auto\")))\n    axis (ax, [min(x1(:)) max(x1(:)) min(y1(:)) max(y1(:))]);\n  endif\n\n  add_patch_children (ax, hg);\n\n  if (! isempty (opts))\n    set (hg, opts{:});\n  endif\n\nendfunction\n\nfunction add_patch_children (ca, hg)\n\n  if (isempty (ca))\n    ca = gca ();\n  endif\n  c = get (hg, \"contourmatrix\");\n  lev = get (hg, \"levellist\");\n  fill = get (hg, \"fill\");\n  zlev = get (hg, \"zlevel\");\n  zmode = get (hg, \"zlevelmode\");\n  lc = get (hg, \"linecolor\");\n  lw = get (hg, \"linewidth\");\n  ls = get (hg, \"linestyle\");\n  filled = get (hg, \"fill\");\n\n  ## Turn off automatic updating of clim while adding patches\n  climmode = get (ca, \"climmode\");\n  set (ca, \"climmode\", \"manual\");\n\n  if (strcmp (lc, \"auto\"))\n    lc = \"flat\";\n  endif\n\n  if (strcmp (filled, \"on\"))\n\n    lvl_eps = get_lvl_eps (lev);\n\n    ## Decode contourc output format.\n    i = 1;\n    ncont = 0;\n    while (i < columns (c))\n      ncont += 1;\n      cont_lev(ncont) = c(1, i);\n      cont_len(ncont) = c(2, i);\n      cont_idx(ncont) = i+1;\n      ii = i + (1:cont_len(ncont));\n      cont_area(ncont) = polyarea (c(1, ii), c(2, ii));\n      i += cont_len(ncont) + 1;\n    endwhile\n\n    ## Handle for each level the case where we have (a) hole(s) in a patch.\n    ## Those are to be filled with the color of level below or with the\n    ## background color.\n    for k = 1:numel (lev)\n      lvl_idx = find (abs (cont_lev - lev(k)) < lvl_eps);\n      len = numel (lvl_idx);\n      if (len > 1)\n        mark = false (size (lvl_idx));\n        a = 1;\n        while (a < len)\n          ## take 1st patch\n          pa_idx = lvl_idx(a);\n          ## get pointer to contour start, and contour length\n          curr_ct_idx = cont_idx(pa_idx);\n          curr_ct_len = cont_len(pa_idx);\n          ## get contour\n          curr_ct = c(:, curr_ct_idx:curr_ct_idx+curr_ct_len-1);\n          b_vec = (a+1):len;\n          next_ct_pt_vec = c(:, cont_idx(lvl_idx(b_vec)));\n          in = inpolygon (next_ct_pt_vec(1,:), next_ct_pt_vec(2,:),\n                          curr_ct(1, :), curr_ct(2, :));\n          mark(b_vec(in)) = ! mark(b_vec(in));\n          a += 1;\n        endwhile\n        if (numel (mark) > 0)\n          ## All marked contours describe a hole in a larger contour of\n          ## the same level and must be filled with color of level below.\n          ma_idx = lvl_idx(mark);\n          if (k > 1)\n            ## Find color of level below.\n            tmp = find (abs (cont_lev - lev(k - 1)) < lvl_eps);\n            lvl_bel_idx = tmp(1);\n            ## Set color of patches found.\n            cont_lev(ma_idx) = cont_lev(lvl_bel_idx);\n          else\n            ## Set lowest level contour to NaN.\n            cont_lev(ma_idx) = NaN;\n          endif\n        endif\n      endif\n    endfor\n\n    ## The algorithm can create patches with the size of the plotting\n    ## area, we would like to draw only the patch with the highest level.\n    del_idx = [];\n    max_idx = find (cont_area == max (cont_area));\n    if (numel (max_idx) > 1)\n      ## delete double entries\n      del_idx = max_idx(1:end-1);\n      cont_area(del_idx) = cont_lev(del_idx) = [];\n      cont_len(del_idx) = cont_idx(del_idx) = [];\n    endif\n\n    ## Now we have everything together and can start plotting the patches\n    ## beginning with largest area.\n    [~, svec] = sort (cont_area);\n    len = ncont - numel (del_idx);\n    h = [];\n    for n = len:-1:1\n      idx = svec(n);\n      ctmp = c(:, cont_idx(idx):cont_idx(idx) + cont_len(idx) - 1);\n      if (all (ctmp(:,1) == ctmp(:,end)))\n        ## patch() doesn't need/want closed contour.  It will do it itself.\n        ctmp(:,end) = [];\n      endif\n      if (isnan (cont_lev(idx)))\n        fc = get (ca, \"color\");\n        if (strcmp (fc, \"none\"))\n          fc = get (ancestor (ca, \"figure\"), \"color\");\n        endif\n      else\n        fc = \"flat\";\n      endif\n      h = [h; __go_patch__(ca, \"xdata\", ctmp(1, :)(:), \"ydata\", ctmp(2, :)(:),\n                           \"vertices\", ctmp.', \"faces\", 1:(cont_len(idx)-1),\n                           \"facevertexcdata\", cont_lev(idx), \"facecolor\", fc,\n                           \"cdata\", cont_lev(idx), \"edgecolor\", lc,\n                           \"linestyle\", ls, \"linewidth\", lw,\n                           \"parent\", hg)];\n    endfor\n\n    if (min (lev) == max (lev))\n      set (ca, \"clim\", [min(lev)-1, max(lev)+1], \"layer\", \"top\");\n    else\n      set (ca, \"clim\", [min(lev), max(lev)], \"layer\", \"top\");\n    endif\n  else\n    ## Decode contourc output format.\n    h = [];\n    i = 1;\n    while (i < length (c))\n      clev = c(1,i);\n      clen = c(2,i);\n\n      if (all (c(:,i+1) == c(:,i+clen)))\n        p = c(:, i+1:i+clen-1).';\n      else\n        p = [c(:, i+1:i+clen), NaN(2, 1)].';\n      endif\n\n      switch (zmode)\n        case \"none\"\n          h = [h; __go_patch__(ca, \"xdata\", p(:,1), \"ydata\", p(:,2),\n                               \"zdata\", [],\n                               \"vertices\", p, \"faces\", 1:rows (p),\n                               \"facevertexcdata\", clev, \"facecolor\", \"none\",\n                               \"cdata\", clev, \"edgecolor\", lc,\n                               \"linestyle\", ls, \"linewidth\", lw,\n                               \"parent\", hg)];\n        case \"auto\"\n          h = [h; __go_patch__(ca, \"xdata\", p(:,1), \"ydata\", p(:,2),\n                               \"zdata\", clev * ones (rows (p),1),\n                               \"vertices\", [p, clev * ones(rows(p),1)],\n                               \"faces\", 1:rows (p),\n                               \"facevertexcdata\", clev, \"facecolor\", \"none\",\n                               \"cdata\", clev, \"edgecolor\", lc,\n                               \"linestyle\", ls, \"linewidth\", lw,\n                               \"parent\", hg)];\n        otherwise\n          h = [h; __go_patch__(ca, \"xdata\", p(:,1), \"ydata\", p(:,2),\n                               \"zdata\", zlev * ones (rows (p), 1),\n                               \"vertices\", [p, zlev * ones(rows(p),1)],\n                               \"faces\", 1:rows (p),\n                               \"facevertexcdata\", clev, \"facecolor\", \"none\",\n                               \"cdata\", clev, \"edgecolor\", lc,\n                               \"linestyle\", ls, \"linewidth\", lw,\n                               \"parent\", hg)];\n      endswitch\n      i += clen + 1;\n    endwhile\n  endif\n\n  set (ca, \"climmode\", climmode);\n\nendfunction\n\nfunction update_zlevel (h, ~)\n\n  z = get (h, \"zlevel\");\n  zmode = get (h, \"zlevelmode\");\n  kids = get (h, \"children\");\n\n  switch (zmode)\n    case \"none\"\n      set (kids, \"zdata\", []);\n    case \"auto\"\n      for i = 1 : length (kids)\n        set (kids(i), \"zdata\", get (kids(i), \"cdata\") .*\n             ones (size (get (kids(i), \"xdata\"))));\n      endfor\n    otherwise\n      for i = 1 : length (kids)\n        set (kids(i), \"zdata\", z .* ones (size (get (kids(i), \"xdata\"))));\n      endfor\n  endswitch\n\nendfunction\n\nfunction update_line (h, ~)\n\n  lc = get (h, \"linecolor\");\n  if (strcmp (lc, \"auto\"))\n    lc = \"flat\";\n  endif\n  set (findobj (h, \"type\", \"patch\"), \"edgecolor\", lc,\n       \"linewidth\", get (h, \"linewidth\"), \"linestyle\", get (h, \"linestyle\"));\n\nendfunction\n\nfunction update_data (h, ~, prop = \"\")\n  persistent recursive = false;\n\n  if (! recursive)\n    recursive = true;\n\n    delete (get (h, \"children\"));\n\n    switch (prop)\n      case \"levellist\"\n        set (h, \"levellistmode\", \"manual\");\n      case \"levelstep\"\n        set (h, \"levelstepmode\", \"manual\");\n      case \"fill\"\n        ## Switching from filled ('k' linespec) to unfilled, reset linecolor\n        if (strcmp (get (h, \"fill\"), \"off\"))\n          set (h, \"linecolor\", \"auto\");\n        else\n          set (h, \"linecolor\", \"black\");\n        endif\n    endswitch\n\n    if (strcmp (get (h, \"levellistmode\"), \"manual\")\n        && ! strcmp (prop, \"levelstep\"))\n      lvl = get (h, \"levellist\");\n    elseif (strcmp (get (h, \"levelstepmode\"), \"manual\"))\n      z = get (h, \"zdata\");\n      lvs = get (h, \"levelstep\");\n      lvl(1) = ceil (min (z(:)) / lvs) * lvs;\n      lvl(2) = floor (max (z(:)) / lvs) * lvs;\n      if (lvl(1) >= lvl(2))\n        lvl = median (z(:));\n      else\n        lvl = lvl(1) : lvs : lvl(2);\n      endif\n      set (h, \"levellist\", lvl, \"levellistmode\", \"auto\");\n    else\n      z = get (h, \"zdata\");\n      ## FIXME: The levels should be determined similarly to {x,y,z}ticks\n      ##        so that they aren't set at extremely odd values.\n      lvl = linspace (min (z(! isinf (z))), max (z(! isinf (z))), 10 + 2);\n      ## Strip off max outlier, min must stay for contourf hole algorithm.\n      lvl = lvl(1:end-1);\n    endif\n\n    if (strcmp (get (h, \"fill\"), \"on\"))\n      X = get (h, \"xdata\");\n      Y = get (h, \"ydata\");\n      Z = get (h, \"zdata\");\n      if (isvector (X) || isvector (Y))\n        [X, Y] = meshgrid (X, Y);\n      endif\n      [nr, nc] = size (Z);\n      X0 = prepad (X, nc+1, 2 * X(1, 1) - X(1, 2), 2);\n      X0 = postpad (X0, nc+2, 2 * X(1, nc) - X(1, nc - 1), 2);\n      X0 = [X0(1, :); X0; X0(1, :)];\n      Y0 = prepad (Y, nr+1, 2 * Y(1, 1) - Y(2, 1), 1);\n      Y0 = postpad (Y0, nr+2, 2 * Y(nr, 1) - Y(nr - 1, 1));\n      Y0 = [Y0(:, 1), Y0, Y0(:, 1)];\n      Z0 = -Inf (nr+2, nc+2);\n      Z0(2:nr+1, 2:nc+1) = Z;\n      [c, lev] = contourc (X0, Y0, Z0, lvl);\n    else\n      [c, lev] = contourc (get (h, \"xdata\"), get (h, \"ydata\"),\n                           get (h, \"zdata\"), lvl);\n    endif\n    set (h, \"contourmatrix\", c);\n\n    if (strcmp (get (h, \"levellistmode\"), \"manual\"))\n      ## Do nothing\n    elseif (strcmp (get (h, \"levelstepmode\"), \"manual\"))\n      set (h, \"levellist\", lev);\n    else\n      set (h, \"levellist\", lev);\n      lvlstep = sum (diff (lvl)) / (length (lvl) - 1);\n      set (h, \"levelstep\", lvlstep);\n    endif\n\n    add_patch_children ([], h);\n    update_text (h);\n    recursive = false;\n  endif\n\nendfunction\n\nfunction update_text (h, ~, prop = \"\")\n  persistent recursive = false;\n\n  if (! recursive)\n    recursive = true;\n\n    delete (findobj (h, \"type\", \"text\"));\n\n    switch (prop)\n      case \"textlist\"\n        set (h, \"textlistmode\", \"manual\");\n      case \"textstep\"\n        set (h, \"textstepmode\", \"manual\");\n    endswitch\n\n    if (strcmp (get (h, \"textlistmode\"), \"manual\"))\n      lvl = get (h, \"textlist\");\n    elseif (strcmp (get (h, \"textstepmode\"), \"manual\"))\n      lev = get (h, \"levellist\");\n\n      lvl_eps = get_lvl_eps (lev);\n\n      stp = get (h, \"textstep\");\n      t = [0, floor(cumsum(diff (lev)) / (abs(stp) - lvl_eps))];\n      lvl = lev([true, t(1:end-1) != t(2:end)]);\n      set (h, \"textlist\", lvl);\n    else\n      lvl = get (h, \"levellist\");\n      set (h, \"textlist\", lvl, \"textstep\", get (h, \"levelstep\"));\n    endif\n\n    if (strcmp (get (h, \"showtext\"), \"on\"))\n      switch (get (h, \"zlevelmode\"))\n        case \"manual\"\n          __clabel__ (get (h, \"contourmatrix\"), lvl, h,\n                      get (h, \"labelspacing\"), get (h, \"zlevel\"));\n        case \"auto\"\n          __clabel__ (get (h, \"contourmatrix\"), lvl, h,\n                      get (h, \"labelspacing\"), \"auto\");\n        otherwise\n          __clabel__ (get (h, \"contourmatrix\"), lvl, h,\n                      get (h, \"labelspacing\"), []);\n      endswitch\n    endif\n\n    recursive = false;\n  endif\n\nendfunction\n\nfunction lvl_eps = get_lvl_eps (lev)\n\n  ## FIXME: is this the right thing to do for this tolerance?  Should\n  ## it be an absolute or relative tolerance, or switch from one to the\n  ## other depending on the value of lev?\n  if (isscalar (lev))\n    lvl_eps = abs (lev) * sqrt (eps) + sqrt (eps);\n  else\n    tmp = min (abs (diff (lev)));\n    if (tmp < 10*eps)\n      lvl_eps = sqrt (eps);\n    else\n      lvl_eps = tmp / 1000.0;\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__errplot__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} __errplot__ (@var{caller}, @var{hax}, @dots{})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction retval = __errplot__ (caller, hax, varargin)\n\n  if (nargin < 4)\n    print_usage (caller);\n  endif\n\n  retval = [];\n  data = cell (6,1);\n  nargs = numel (varargin);\n  k = 1;\n  while (k <= nargs)\n    arg = varargin{k++};\n    if (! isnumeric (arg))\n      error (\"%s: data argument %d must be numeric\", caller, k-1);\n    endif\n    if (isvector (arg))\n      arg = arg(:);\n    endif\n    sz = size (arg);\n    ndata = 1;\n    data{ndata} = arg;\n    while (k <= nargs)\n      arg = varargin{k++};\n      if (ischar (arg) || iscellstr (arg))\n        retval = [retval; __do_errplot__(arg, hax, data{1:ndata})];\n        break;\n      endif\n      if (! isnumeric (arg))\n        error (\"%s: data argument %d must be numeric\", caller, k-1);\n      endif\n      if (isvector (arg))\n        arg = arg(:);\n      endif\n      if (! isscalar (arg) && ((isvector (arg) && numel (arg) != prod (sz))\n          || any (size (arg) != sz)))\n        error (\"%s: size of argument %d does not match others\", caller, k-1);\n      endif\n      data{++ndata} = arg;\n      if (ndata > 6)\n        error (\"%s: too many arguments to plot\", caller);\n      endif\n    endwhile\n  endwhile\n\n  ## No format code found, use yerrorbar\n  if (! (ischar (arg) || iscellstr (arg)))\n    retval = [retval; __do_errplot__(\"~\", hax, data{1:ndata})];\n  endif\n\n  drawnow ();\n\nendfunction\n\nfunction h = __do_errplot__ (fstr, hax, varargin)\n\n  fmt = __pltopt__ (\"__do_errplot__\", fstr);\n\n  ## Set the plot type based on linestyle.\n  switch (fmt.errorstyle)\n    case \"~\"\n      ifmt = \"yerr\";\n    case \">\"\n      ifmt = \"xerr\";\n    case \"~>\"\n      ifmt = \"xyerr\";\n    case \"#\"\n      ifmt = \"box\";\n    case \"#~\"\n      ifmt = \"boxy\";\n    case \"#~>\"\n      ifmt = \"boxxy\";\n    otherwise\n      ifmt = \"yerr\";\n  endswitch\n\n  h = [];\n  nplots = ifelse (isempty (varargin{1}), 0, columns (varargin{1}));\n  for i = 1:nplots\n\n    if (isempty (fmt.color))\n      lc = __next_line_color__ (hax);\n    else\n      lc = fmt.color;\n    endif\n    if (isempty (fmt.marker) && isempty (fmt.linestyle))\n      [ls, mk] = __next_line_style__ (hax);\n    else\n      ls = fmt.linestyle;\n      mk = fmt.marker;\n    endif\n\n    ## Must occur after __next_line_color__ in order to work correctly.\n    hg = hggroup (\"parent\", hax, ...\n                  \"__appdata__\", struct (\"__creator__\", \"__errplot__\"));\n    h = [h; hg];\n    args = __add_datasource__ (\"__do_errplot__\", hg,\n                               {\"x\", \"y\", \"l\", \"u\", \"xl\", \"xu\"});\n\n    ## Use a single data point for line rather than default data of [0, 1].\n    ## The real data will be applied to the line object later.  See bug #60959.\n    hl = [__line__(hg, \"xdata\", 1, \"ydata\", 1,\n                       \"color\", lc, \"linestyle\", \"-\", \"marker\", \"none\"),\n          __line__(hg, \"xdata\", 1, \"ydata\", 1,\n                       \"color\", lc, \"linestyle\", ls, \"marker\", mk)];\n\n    switch (numel (varargin))\n      case 2\n        ydata = varargin{1}(:,i);\n        xdata = 1:numel (ydata);\n        if (strcmp (ifmt, \"yerr\") || strcmp (ifmt, \"boxy\"))\n          ldata  = varargin{2}(:,i);\n          udata  = ldata;\n          xldata = [];\n          xudata = [];\n        elseif (strcmp (ifmt, \"xerr\") || strcmp (ifmt, \"box\"))\n          xldata = varargin{2}(:,i);\n          xudata = ldata;\n          ldata  = [];\n          udata  = [];\n        else\n          error (\"errorbar: 2 column errorplot is only valid for xerr or yerr\");\n        endif\n      case 3\n        if (strcmp (ifmt, \"yerr\") || strcmp (ifmt, \"boxy\"))\n          xdata  = varargin{1}(:,i);\n          ydata  = varargin{2}(:,i);\n          ldata  = varargin{3}(:,i);\n          udata  = ldata;\n          xldata = [];\n          xudata = [];\n        elseif (strcmp (ifmt, \"xyerr\") || strcmp (ifmt, \"boxxy\"))\n          ydata  = varargin{1}(:,i);\n          xdata  = 1:numel (ydata);\n          xldata = varargin{2}(:,i);\n          xudata = xldata;\n          ldata  = varargin{3}(:,i);\n          udata  = ldata;\n        else  # xerr or box\n          xdata  = varargin{1}(:,i);\n          ydata  = varargin{2}(:,i);\n          xldata = varargin{3}(:,i);\n          xudata = xldata;\n          ldata  = [];\n          udata  = [];\n        endif\n      case 4\n        if (strcmp (ifmt, \"yerr\") || strcmp (ifmt, \"boxy\"))\n          xdata  = varargin{1}(:,i);\n          ydata  = varargin{2}(:,i);\n          ldata  = varargin{3}(:,i);\n          udata  = varargin{4}(:,i);\n          xldata = [];\n          xudata = [];\n        elseif (strcmp (ifmt, \"xyerr\") || strcmp (ifmt, \"boxxy\"))\n          xdata  = varargin{1}(:,i);\n          ydata  = varargin{2}(:,i);\n          xldata = varargin{3}(:,i);\n          xudata = xldata;\n          ldata  = varargin{4}(:,i);\n          udata  = ldata;\n        else  # xerr or box\n          xdata  = varargin{1}(:,i);\n          ydata  = varargin{2}(:,i);\n          xldata = varargin{3}(:,i);\n          xudata = varargin{4}(:,i);\n          ldata  = [];\n          udata  = [];\n        endif\n      case 6  # xyerr, boxxy\n        if (strcmp (ifmt, \"xyerr\") || strcmp (ifmt, \"boxxy\"))\n          xdata  = varargin{1}(:,i);\n          ydata  = varargin{2}(:,i);\n          xldata = varargin{3}(:,i);\n          xudata = varargin{4}(:,i);\n          ldata  = varargin{5}(:,i);\n          udata  = varargin{6}(:,i);\n        else\n          error (\"errorbar: error plot with 6 columns only valid for xyerr and boxxy\");\n        endif\n      otherwise\n        error (\"errorbar: error plot requires 2, 3, 4, or 6 arguments\");\n    endswitch\n\n    addproperty (\"xdata\", hg, \"data\", xdata(:));\n    addproperty (\"ydata\", hg, \"data\", ydata(:));\n    addproperty (\"ldata\", hg, \"data\", ldata(:));\n    addproperty (\"udata\", hg, \"data\", udata(:));\n    addproperty (\"xldata\", hg, \"data\", xldata(:));\n    addproperty (\"xudata\", hg, \"data\", xudata(:));\n    addproperty (\"format\", hg, \"string\", ifmt);\n\n    addproperty (\"color\", hg, \"linecolor\", get (hl(2), \"color\"));\n    addproperty (\"linestyle\", hg, \"linelinestyle\", get (hl(2), \"linestyle\"));\n    addproperty (\"linewidth\", hg, \"linelinewidth\", get (hl(2), \"linewidth\"));\n    addproperty (\"marker\", hg, \"linemarker\", get (hl(2), \"marker\"));\n    addproperty (\"markeredgecolor\", hg, \"linemarkerfacecolor\",\n                 get (hl(2), \"markeredgecolor\"));\n    addproperty (\"markerfacecolor\", hg, \"linemarkerfacecolor\",\n                 get (hl(2), \"markerfacecolor\"));\n    addproperty (\"markersize\", hg, \"linemarkersize\",\n                 get (hl(2), \"markersize\"));\n\n    ## Matlab property, although Octave does not implement it.\n    addproperty (\"hittestarea\", hg, \"radio\", \"on|{off}\", \"off\");\n\n    fcn = {@update_props, hl};\n    addlistener (hg, \"color\", fcn);\n    addlistener (hg, \"linestyle\", fcn);\n    addlistener (hg, \"linewidth\", fcn);\n    addlistener (hg, \"marker\", fcn);\n    addlistener (hg, \"markeredgecolor\", fcn);\n    addlistener (hg, \"markerfacecolor\", fcn);\n    addlistener (hg, \"markersize\", fcn);\n\n    fcn = {@update_data, hl};\n    addlistener (hg, \"xdata\", fcn);\n    addlistener (hg, \"ydata\", fcn);\n    addlistener (hg, \"ldata\", fcn);\n    addlistener (hg, \"udata\", fcn);\n    addlistener (hg, \"xldata\", fcn);\n    addlistener (hg, \"xudata\", fcn);\n    addlistener (hg, \"format\", fcn);\n\n    addlistener (hax, \"xscale\", fcn);\n    addlistener (hax, \"yscale\", fcn);\n\n    update_data (hg, [], hl);\n\n  endfor\n\n  ## Process legend key\n  if (! isempty (fmt.key) && nplots > 0)\n    try\n      hlegend = get (hax, \"__legend_handle__\");\n    catch\n      hlegend = [];\n    end_try_catch\n\n    if (isempty (hlegend))\n      hlgnd = [];\n      tlgnd = {};\n    else\n      [hlgnd, tlgnd] = __getlegenddata__ (hlegend);\n    endif\n\n    hlgnd(end+1) = hg;\n    tlgnd(end+1) = fmt.key;\n\n    legend (gca (), hlgnd, tlgnd);\n  endif\n\nendfunction\n\nfunction [xdata, ydata] = errorbar_data (xdata, ydata, ldata, udata,\n                                         xldata, xudata, ifmt,\n                                         xscale, yscale)\n\n  if (strcmp (xscale, \"linear\"))\n    dx = 0.01 * (max (xdata(:)) - min (xdata(:)));\n    if (dx == 0)\n      dx = .1;\n    endif\n    xlo = xdata - dx;\n    xhi = xdata + dx;\n  else\n    n = xdata > 0;\n    if (! any (n))\n      n = xdata < 0;\n    endif\n    logdata = log (abs (xdata(n)));\n    rx = exp (0.01 * (max (logdata) - min (logdata)));\n    xlo = xdata/rx;\n    xhi = xdata*rx;\n  endif\n  if (strcmp (yscale, \"linear\"))\n    dy = 0.01 * (max (ydata(:)) - min (ydata(:)));\n    if (dy == 0)\n      dy = .1;\n    endif\n    ylo = ydata - dy;\n    yhi = ydata + dy;\n  else\n    n = ydata > 0;\n    if (! any (n))\n      n = ydata < 0;\n    endif\n    logdata = log (abs (ydata(n)));\n    ry = exp (0.01 * (max (logdata) - min (logdata)));\n    ylo = ydata/ry;\n    yhi = ydata*ry;\n  endif\n\n  nans = NaN + xdata(:);  # fast way to do NaN (size (xdata(:)))\n  if (strcmp (ifmt, \"yerr\"))\n    xdata = [xdata, xdata, nans, ...\n             xlo, xhi, nans, ...\n             xlo, xhi, nans];\n    ydata = [ydata-ldata, ydata+udata, nans, ...\n             ydata+udata, ydata+udata, nans, ...\n             ydata-ldata, ydata-ldata, nans];\n  elseif (strcmp (ifmt, \"xerr\"))\n    xdata = [xdata-xldata, xdata+xudata, nans, ...\n             xdata+xudata, xdata+xudata, nans, ...\n             xdata-xldata, xdata-xldata, nans];\n    ydata = [ydata, ydata, nans, ...\n             ylo, yhi, nans, ...\n             ylo, yhi, nans];\n  elseif (strcmp (ifmt, \"boxy\"))\n    dx = 0.01 * (max (xdata(:)) - min (xdata(:)));\n    xdata = [xlo, xhi, xhi, xlo, xlo, nans];\n    ydata = [ydata-ldata, ydata-ldata, ydata+udata, ydata+udata, ...\n             ydata-ldata, nans];\n  elseif (strcmp (ifmt, \"box\"))\n    dy = 0.01 * (max (ydata(:)) - min (ydata(:)));\n    xdata = [xdata-xldata, xdata+xudata, xdata+xudata, xdata-xldata, ...\n             xdata-xldata, nans];\n    ydata = [ylo, ylo, yhi, yhi, ylo, nans];\n  elseif (strcmp (ifmt, \"boxxy\"))\n    xdata = [xdata-xldata, xdata+xudata, xdata+xudata, xdata-xldata, ...\n             xdata-xldata, nans];\n    ydata = [ydata-ldata, ydata-ldata, ydata+udata, ydata+udata, ...\n             ydata-ldata, nans];\n  elseif (strcmp (ifmt, \"xyerr\"))\n    [x1, y1] = errorbar_data (xdata, ydata, ldata, udata,\n                              xldata, xudata, \"xerr\", xscale, yscale);\n    [x2, y2] = errorbar_data (xdata, ydata, ldata, udata,\n                              xldata, xudata, \"yerr\", xscale, yscale);\n    xdata = [x1; x2];\n    ydata = [y1; y2];\n    return;\n  else\n    error (\"errorbar: valid error bar types are xerr, yerr, xyerr, box, boxy, boxxy\");\n  endif\n\n  xdata = xdata.'(:);\n  ydata = ydata.'(:);\n\nendfunction\n\nfunction update_props (hg, ~, hl)\n\n  set (hl, \"color\", get (hg, \"color\"),\n           \"linewidth\", get (hg, \"linewidth\"));\n  set (hl(2), \"linestyle\", get (hg, \"linestyle\"),\n              \"marker\", get (hg, \"marker\"),\n              \"markeredgecolor\", get (hg, \"markeredgecolor\"),\n              \"markerfacecolor\", get (hg, \"markerfacecolor\"),\n              \"markersize\", get (hg, \"markersize\"));\n\nendfunction\n\nfunction update_data (hg, ~, hl)\n\n  if (strcmp (get (hg, \"type\"), \"axes\"))\n    hax = hg;\n    hg = ancestor (hl(2), \"hggroup\");\n  else\n    hax = ancestor (hg, \"axes\");\n  endif\n  xscale = get (hax, \"xscale\");\n  yscale = get (hax, \"yscale\");\n\n  xdata  = get (hg, \"xdata\");\n  ydata  = get (hg, \"ydata\");\n  ldata  = get (hg, \"ldata\");\n  udata  = get (hg, \"udata\");\n  xldata = get (hg, \"xldata\");\n  xudata = get (hg, \"xudata\");\n  ifmt = get (hg, \"format\");\n\n  set (hl(2), \"xdata\", xdata, \"ydata\", ydata);\n\n  [errorbar_xdata, errorbar_ydata] = ...\n          errorbar_data (xdata, ydata, ldata, udata, xldata, xudata, ...\n                         ifmt, xscale, yscale);\n\n  set (hl(1), \"xdata\", errorbar_xdata, \"ydata\", errorbar_ydata);\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__ezplot__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{h}, @var{needusage}] =} __ezplot__ (@var{pltfcn}, @var{varargin})\n## Undocumented internal function.\n## @end deftypefn\n\n## Overview: This function is the back-end for the 9 ez* plot functions.\n##           As such, most of the function is actually dedicated to sorting\n##           out the inputs and verifying that the particular ez* function\n##           called was called correctly.  The actual plotting occurs near\n##           the end in an unwind_protect block.\n\nfunction [h, needusage] = __ezplot__ (pltfcn, varargin)\n\n  ezfcn = [\"ez\" pltfcn];\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (ezfcn, varargin{:});\n\n  ## Define outputs early in case of shorting out of function with return;\n  h = [];\n  needusage = false;\n  if (nargin < 1)\n    needusage = true;\n    return;\n  endif\n\n  iscontour = strncmp (pltfcn, \"contour\", 7);\n\n  ## Defaults for ezplot\n  isplot  = true;\n  isplot3 = false;\n  ispolar = false;\n  nargs = 1;\n  switch (pltfcn)\n    case \"plot\"\n      ## defaults already set\n\n    case \"plot3\"\n      isplot  = false;\n      isplot3 = true;\n\n    case \"polar\"\n      isplot  = false;\n      ispolar = true;\n\n    otherwise\n      ## contour, mesh, surf plots\n      isplot  = false;\n      nargs = 2;\n\n  endswitch\n\n  parametric = false;\n  fcn = varargin{1};\n  ## Don't warn about intentional use of inline functions (Bug #62682)\n  warning (\"off\", \"Octave:legacy-function\", \"local\");\n  if (ischar (fcn))\n    if (exist (fcn, \"file\") || exist (fcn, \"builtin\"))\n      fcn = str2func (fcn);            # convert to function handle\n    else\n      fcn = vectorize (inline (fcn));  # convert to inline function\n    endif\n  endif\n\n  if (isa (fcn, \"inline\"))\n    argids = argnames (fcn);\n    if (isplot && length (argids) == 2)\n      nargs = 2;\n    elseif (numel (argids) != nargs)\n      error (\"%s: expecting a function of %d arguments\", ezfcn, nargs);\n    endif\n    fcn = vectorize (fcn);\n    fstr = formula (fcn);\n    if (isplot)\n      xarg = argids{1};\n      if (nargs == 2)\n        yarg = argids{2};\n      else\n        yarg = \"\";\n      endif\n    elseif (isplot3)\n      xarg = \"x\";\n      yarg = \"y\";\n    elseif (isplot || ispolar)\n      xarg = \"\";\n      yarg = \"\";\n    else\n      xarg = argids{1};\n      yarg = argids{2};\n    endif\n  elseif (is_function_handle (fcn))\n    fstr = func2str (fcn);\n    idx = index (fstr, ')');\n    if (idx != 0)\n      args = regexp (fstr(3:(idx-1)), '\\w+', 'match');\n      fstr = fstr(idx+2:end);  # remove '@(x) ' from string name\n    else\n      args = {\"x\"};\n      try\n        if (builtin (\"nargin\", fcn) == 2)\n          args{2} = \"y\";\n        endif\n      end_try_catch\n    endif\n    if (isplot && length (args) == 2)\n      nargs = 2;\n    elseif (numel (args) != nargs)\n      error (\"%s: expecting a function of %d arguments\", ezfcn, nargs);\n    endif\n    if (isplot)\n      xarg = args{1};\n      if (nargs == 2)\n        yarg = args{2};\n      else\n        yarg = \"\";\n      endif\n    elseif (isplot3)\n      xarg = \"x\";\n      yarg = \"y\";\n    elseif (ispolar)\n      xarg = \"\";\n      yarg = \"\";\n    else\n      xarg = args{1};\n      yarg = args{2};\n    endif\n  else\n    error (\"%s: F must be a string or function handle\", ezfcn);\n  endif\n\n  if (nargin > 2 || (nargin == 2 && isplot))\n    funx = fcn;\n    fstrx = fstr;\n    funy = varargin{2};\n    if (ischar (funy) && ! strcmp (funy, \"circ\") && ! strcmp (funy, \"animate\"))\n      parametric = true;\n      if (exist (funy, \"file\") || exist (funy, \"builtin\"))\n        funy = inline ([funy \"(t)\"]);\n      else\n        funy = vectorize (inline (funy));\n      endif\n      if (numel (argnames (funy)) != nargs)\n        error (\"%s: expecting a function of %d arguments\", ezfcn, nargs);\n      endif\n      fstry = formula (funy);\n    elseif (isa (funy, \"inline\"))\n      parametric = true;\n      if (numel (argnames (funy)) != nargs)\n        error (\"%s: expecting a function of %d arguments\", ezfcn, nargs);\n      endif\n      funy = vectorize (funy);\n      fstry = formula (funy);\n    elseif (is_function_handle (funy))\n      parametric = true;\n      fstry = func2str (funy);\n      idx = index (fstry, ')');\n      if (idx != 0)\n        args = regexp (fstry(3:(idx-1)), '\\w+', 'match');\n        fstry = fstry(idx+2:end);  # remove '@(x) ' from string name\n      else\n        args = {\"y\"};\n      endif\n      if (numel (args) != nargs)\n        error (\"%s: expecting a function of %d arguments\", ezfcn, nargs);\n      endif\n    endif\n\n    if (! parametric && isplot3)\n      needusage = true;  # Can't call non-parametric ezplot3\n      return;\n    elseif (parametric && isplot)\n      if (nargs == 2)\n        error (\"%s: can not define a parametric function in this manner\", ezfcn);\n      else\n        xarg = \"x\";\n        yarg = \"y\";\n      endif\n    elseif (parametric)\n      funz = varargin{3};\n      if (ischar (funz) && ! strcmp (funz, \"circ\")\n          && ! strcmp (funz, \"animate\"))\n        if (exist (funz, \"file\") || exist (funz, \"builtin\"))\n          funz = inline ([funz \"(t)\"]);\n        else\n          funz = vectorize (inline (funz));\n        endif\n        if (numel (argnames (funz)) > nargs)\n          error (\"%s: expecting a function of %d arguments\", ezfcn, nargs);\n        endif\n        fstrz = formula (funz);\n      elseif (isa (funz, \"inline\"))\n        if (numel (argnames (funz)) != nargs)\n          error (\"%s: expecting a function of %d arguments\", ezfcn, nargs);\n        endif\n        funz = vectorize (funz);\n        fstrz = formula (funz);\n      elseif (is_function_handle (funz))\n        fstrz = func2str (funz);\n        idx = index (fstrz, ')');\n        if (idx != 0)\n          args = regexp (fstrz(3:(idx-1)), '\\w+', 'match');\n          fstrz = fstrz(idx+2:end);  # remove '@(x) ' from string name\n        else\n          args = {\"z\"};\n        endif\n        if (numel (args) != nargs)\n          error (\"%s: expecting a function of %d arguments\", ezfcn, nargs);\n        endif\n      else\n        error (\"%s: parametric plots require 3 functions\", ezfcn);\n      endif\n    endif\n  endif\n\n  if ((isplot && nargs != 2) || isplot3 || ispolar)\n    n = 500;   # default for point-style functions like plot\n  else\n    n = 60;    # default for meshgrid style functions like contour, surf\n  endif\n  domain = [];\n  circ = false;\n  animate = false;\n  if (parametric)\n    if (isplot)\n      iarg = 3;\n    else\n      iarg = 4;\n    endif\n  else\n    iarg = 2;\n  endif\n  while (iarg <= nargin)\n    arg = varargin{iarg++};\n    if (ischar (arg) && strcmp (arg, \"circ\"))\n      circ = true;\n    elseif (ischar (arg) && strcmp (arg, \"animate\"))\n      animate = true;\n    elseif (isscalar (arg) && (n == 60 || n == 500))\n      n = arg;\n    elseif (numel (arg) == 2 && isempty (domain))\n      domain = [arg(1) arg(2) arg(1) arg(2)];\n    elseif (numel (arg) == 4 && isempty (domain))\n      domain = arg(:).';\n    else\n      error (\"%s: expecting scalar N, or 2-/4-element vector DOM\", ezfcn);\n    endif\n  endwhile\n\n  if (circ && (iscontour || isplot3 || isplot))\n    needusage = true;\n    return;\n  elseif (circ && parametric)\n    error (\"%s: can not have both circular domain and parametric function\",\n           ezfcn);\n  endif\n\n  if (animate && ! isplot3)\n    error (\"%s: animate option only valid for ezplot3\", ezfcn);\n  endif\n\n  if (parametric)\n    ## Make the label strings pretty by removing extra spaces between base\n    ## and exponent, the '.' in vectorized code, and the '*' for multiply.\n    fstrx = regexprep (regexprep (regexprep (fstrx,\n           '\\s*\\.?(?:\\^|\\*\\*)\\s*','^'), '\\.([/+-])', '$1'), '\\s*\\.?\\*\\s*', ' ');\n    fstry = regexprep (regexprep (regexprep (fstry,\n           '\\s*\\.?(?:\\^|\\*\\*)\\s*','^'), '\\.([/+-])', '$1'), '\\s*\\.?\\*\\s*', ' ');\n    if (isplot)\n      fstr = [\"x = \" fstrx \", y = \" fstry];\n    else\n      fstrz = regexprep (regexprep (regexprep (fstrz,\n           '\\s*\\.?(?:\\^|\\*\\*)\\s*','^'), '\\.([/+-])', '$1'), '\\s*\\.?\\*\\s*', ' ');\n      fstr = [\"x = \" fstrx \", y = \" fstry \", z = \" fstrz];\n    endif\n  else\n    fstr = regexprep (regexprep (regexprep (fstr,\n           '\\s*\\.?(?:\\^|\\*\\*)\\s*','^'), '\\.([/+-])', '$1'), '\\s*\\.?\\*\\s*', ' ');\n    if (isplot && nargs == 2)\n      fstr = [fstr \" = 0\"];  # make title string of implicit function\n    elseif (ispolar)\n      fstr = [\"r = \" fstr];\n    endif\n  endif\n\n  if (isempty (domain))\n    auto_domain = true;\n    if (isplot3 || ispolar)\n      domain = [0, 2*pi, 0, 2*pi];\n    else\n      domain = [-2*pi, 2*pi, -2*pi, 2*pi];\n    endif\n  else\n    auto_domain = false;\n  endif\n\n  auto_domain_done = false;\n  do\n    domain_ok = true;\n\n    if ((isplot && nargs == 1) || isplot3 || ispolar)\n      X = linspace (domain(1), domain(2), n);\n    elseif (isplot && numel (domain) == 2)\n      x = linspace (domain(1), domain(2), n);\n      [X, Y] = meshgrid (x, x);\n    elseif (circ)\n      ## To plot on circular domain develop grid in polar coordinates\n      ## and then switch these to Cartesian coordinates.\n      cent = [domain(1) + domain(2), domain(3) + domain(4)] / 2;\n      rmax = sqrt ((domain(2) - cent(1))^2 + (domain(4) - cent(2))^2);\n      r = linspace (0, rmax, n);\n      t = linspace (0, 2*pi, n);\n      [T, R] = meshgrid (t, r);\n      X = R .* cos (T) + cent(1);\n      Y = R .* sin (T) + cent(2);\n      domain = [-rmax+cent(1), +rmax+cent(1), -rmax+cent(2), +rmax+cent(2)];\n    else  # contour, mesh, surf plots\n      x = linspace (domain(1), domain(2), n);\n      y = linspace (domain(3), domain(4), n);\n      [X, Y] = meshgrid (x, y);\n    endif\n\n    if (parametric)\n      if (isplot)\n        XX = feval (funx, X);\n        Z = feval (funy, X);\n        X = XX;\n      elseif (isplot3)\n        Z = feval (funz, X);\n        XX = feval (funx, X);\n        YY = feval (funy, X);\n        X = XX;\n        Y = YY;\n      else\n        Z = feval (funz, X, Y);\n        XX = feval (funx, X, Y);\n        YY = feval (funy, X, Y);\n        X = XX;\n        Y = YY;\n\n        ## Eliminate the singularities\n        X = __eliminate_sing__ (X);\n        Y = __eliminate_sing__ (Y);\n        Z = __eliminate_sing__ (Z);\n      endif\n    else  # non-parametric plots\n      if (isplot && nargs == 2)\n        Z = feval (fcn, X, Y);\n\n        ## Matlab returns line objects for this case and so can't call\n        ## contour directly as it returns patch objects to allow colormaps\n        ## to work with contours.  Therefore recreate the lines from the\n        ## output for contourc, and store in cell arrays.\n        [c, ~] = contourc (X, Y, Z, [0, 0]);\n\n        i = 1;\n        XX = YY = {};\n        while (i < length (c))\n          clev = c(1,i);\n          clen = c(2,i);\n          XX = [XX, {c(1, i+1:i+clen)}];\n          YY = [YY, {c(2, i+1:i+clen)}];\n          i += clen+1;\n        endwhile\n      else\n        if (ispolar)\n          Z = feval (fcn, X);\n          if (isscalar (Z))\n            ## Handle exceptional case of constant function\n            Z *= ones (size (X));\n          endif\n          ## FIXME: Why aren't singularities eliminated for polar plots?\n        elseif (isplot)\n          Z = feval (fcn, X);\n          if (isscalar (Z))\n            ## Handle exceptional case of constant function\n            Z *= ones (size (X));\n          endif\n          ## Eliminate the singularities\n          Z = __eliminate_sing__ (Z);\n          domain = find_valid_domain (X, [], Z);\n        elseif (iscontour)\n          Z = feval (fcn, X, Y);\n          Z = __eliminate_sing__ (Z);\n        else  #  mesh, surf plots\n          Z = feval (fcn, X, Y);\n          Z = __eliminate_sing__ (Z);\n          if (circ)\n            ## Use domain calculated at the start.\n            ## The X, Y grids are non-monotonic after conversion from polar\n            ## coordinates and find_valid_domain fails.\n\n          elseif (auto_domain && ! auto_domain_done)\n            valid_domain = find_valid_domain (X, Y, Z);\n            domain_ok = all (domain == valid_domain);\n            domain = valid_domain;\n            auto_domain_done = true;  # ensures only 1 round of do loop done\n          else\n            if (! auto_domain_done)\n              domain = find_valid_domain (X, Y, Z);\n            endif\n          endif\n        endif\n      endif\n    endif\n  until (domain_ok)\n\n  ## Now, actually call the correct plot function with valid data and domain.\n  hax = newplot (hax);\n  if (iscontour)\n    [~, h] = feval (pltfcn, hax, X, Y, Z);\n  elseif (isplot && nargs == 2)\n    h = zeros (length (XX), 1);\n    hold_state = get (hax, \"nextplot\");\n    for i = 1 : length (XX)\n      if (i == 1)\n        h(1) = plot (hax, XX{1}, YY{1});\n        set (hax, \"nextplot\", \"add\");\n        color = get (h(1), \"color\");\n      else\n        h(i) = plot (hax, XX{i}, YY{i}, \"color\", color);\n      endif\n    endfor\n    set (hax, \"nextplot\", hold_state);\n    axis (hax, domain);\n  elseif (isplot || ispolar)\n    h = feval (pltfcn, hax, X, Z);\n    if (isplot)\n      if (! parametric)\n        axis (hax, domain);\n      else\n        axis (hax, \"equal\");\n      endif\n    endif\n  elseif (isplot3)\n    if (animate)\n      comet3 (hax, X, Y, Z);\n    else\n      h = feval (pltfcn, hax, X, Y, Z);\n    endif\n    grid (hax, \"on\");\n    zlabel (hax, \"z\");\n  else  # mesh and surf plots\n    h = feval (pltfcn, hax, X, Y, Z);\n    ## FIXME: surf, mesh should really do a better job of setting zlim\n    if (! parametric)\n      axis (hax, domain);\n    endif\n  endif\n  xlabel (hax, xarg);\n  ylabel (hax, yarg);\n  title (hax, fstr);\n\nendfunction\n\n## Eliminate bad data (complex values, infinities, singularities)\nfunction x = __eliminate_sing__ (x)\n\n  if (iscomplex (x))\n    x(imag (x) != 0) = NaN;\n  endif\n  x(isinf (x)) = NaN;\n  ## High rates of curvature are treated as singularities\n  threshold = 0.2 * (max (x(:)) - min (x(:)));\n  x(abs (del2 (x)) > threshold) = NaN;\n\nendfunction\n\n## Find: 1) range of function where there are not NaN values,\n##       2) function is changing (not just flat surface)\nfunction domain = find_valid_domain (X, Y, Z)\n\n  if (isvector (Z))\n    ## 2-D data for isplot\n    domain = [X(1) X(end)];\n\n    ## Guess a range which includes the \"mass\" of the data by using a\n    ## median-based approach.  The center 3/4 of the data is used to\n    ## determine the range of the data.\n    ## This seems to be vaguely what Matlab does, but can't be sure.\n    XX = sort (Z(isfinite (Z)));\n    if (length (X) > 4)\n      irlo = XX(fix (1/8 * length (XX)));\n      irhi = XX(fix (7/8 * length (XX)));\n      d = irhi - irlo;\n      domain(3) = max (XX(1) - d/8, irlo - d);\n      domain(4) = min (XX(end) + d/8, irhi + d);\n    else\n      domain(3:4) = [XX(1), XX(end)];\n    endif\n\n    ## Handle exceptional case of constant function\n    if (domain(3) == domain(4))\n      domain(3) -= 1;\n      domain(4) += 1;\n    endif\n\n  else\n    ## 3-D data such as mesh, surf\n    Zfinite = ! isnan (Z);\n    Zrows = any (Zfinite, 2);\n    rmin = find (Zrows, 1, \"first\");\n    rmax = find (Zrows, 1, \"last\");\n    Zcols = any (Zfinite, 1);\n    cmin = find (Zcols, 1, \"first\");\n    cmax = find (Zcols, 1, \"last\");\n\n    ## Handle nasty case of all NaNs\n    if (isempty (rmin))\n      rmin = 1; rmax = rows (Z);\n    endif\n    if (isempty (cmin))\n      cmin = 1; cmax = columns (Z);\n    endif\n\n    if (   ! any (isnan (Z([rmin, rmax],:)(:)))\n        && ! any (isnan (Z(:, [cmin, cmax])(:))))\n      ## Exclude surfaces along borders which are flat (gradient =~ 0).\n      ## Technically, this calculation might be better done with actual\n      ## deltaX, deltaY values.  But, data is usually meshgridded\n      ## (constant spacing) so working with deltaROW#, deltaCOL# is fine.\n      [Zx, Zy] = gradient (Z(rmin:rmax, cmin:cmax));\n      Zgrad = sqrt (Zx.^2 + Zy.^2);\n      slope = ((max (Z(:)) - min (Z(:)))\n                / sqrt ((rmax - rmin)^2 + (cmax - cmin)^2));\n      slope /= 125;  # threshold for discarding points.\n      Zrows = any (Zgrad > slope, 2);\n      rmin += find (Zrows, 1, \"first\") - 1;\n      rmax += find (Zrows, 1, \"last\") - rows (Zrows);\n      Zcols = any (Zgrad > slope, 1);\n      cmin += find (Zcols, 1, \"first\") - 1;\n      cmax += find (Zcols, 1, \"last\") - columns (Zcols);\n    endif\n\n    domain = [X(1,cmin) X(1,cmax) Y(rmin,1) Y(rmax,1)];\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__gnuplot_scatter__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{hg} =} __gnuplot_scatter__ (@dots{})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction hg = __gnuplot_scatter__ (hax, fcn, x, y, z, c, s, marker, filled, newargs)\n\nif (isempty (c))\n  c = __next_line_color__ (hax);\nendif\n\n## Must occur after __next_line_color__ in order to work correctly.\nhg = hggroup (hax, \"__appdata__\", struct (\"__creator__\", \"__scatter__\"));\nnewargs = __add_datasource__ (fcn, hg, {\"x\", \"y\", \"z\", \"c\", \"size\"},\n                              newargs{:});\n\naddproperty (\"xdata\", hg, \"data\", x);\naddproperty (\"ydata\", hg, \"data\", y);\naddproperty (\"zdata\", hg, \"data\", z);\nif (ischar (c))\n  ## For single explicit color, cdata is unused\n  addproperty (\"cdata\", hg, \"data\", []);\nelse\n  addproperty (\"cdata\", hg, \"data\", c);\nendif\naddproperty (\"sizedata\", hg, \"data\", s);\naddlistener (hg, \"xdata\", @update_data);\naddlistener (hg, \"ydata\", @update_data);\naddlistener (hg, \"zdata\", @update_data);\naddlistener (hg, \"cdata\", @update_data);\naddlistener (hg, \"sizedata\", @update_data);\n\none_explicit_color = ischar (c) || isequal (size (c), [1, 3]);\ns = sqrt (s);  # size adjustment for visual compatibility w/Matlab\n\nif (numel (x) <= 100)\n\n  ## For small number of points, we'll construct an object for each point.\n\n  if (numel (s) == 1)\n    s = repmat (s, numel (x), 1);\n  endif\n\n  if (one_explicit_color)\n    for i = 1 : numel (x)\n      if (filled)\n        __go_patch__ (hg, \"facecolor\", \"none\", \"edgecolor\", \"none\",\n                      \"xdata\", x(i), \"ydata\", y(i), \"zdata\", z(i,:),\n                      \"faces\", 1, \"vertices\", [x(i), y(i), z(i,:)],\n                      \"marker\", marker,  \"markersize\", s(i),\n                      \"markeredgecolor\", c, \"markerfacecolor\", c,\n                      \"linestyle\", \"none\");\n      else\n        __go_patch__ (hg, \"facecolor\", \"none\", \"edgecolor\", \"none\",\n                      \"xdata\", x(i), \"ydata\", y(i), \"zdata\", z(i,:),\n                      \"faces\", 1, \"vertices\", [x(i), y(i), z(i,:)],\n                      \"marker\", marker,  \"markersize\", s(i),\n                      \"markeredgecolor\", c, \"markerfacecolor\", \"none\",\n                      \"linestyle\", \"none\");\n      endif\n    endfor\n  else\n    if (rows (c) == 1)\n      c = repmat (c, rows (x), 1);\n    endif\n    for i = 1 : numel (x)\n      if (filled)\n        __go_patch__ (hg, \"facecolor\", \"none\", \"edgecolor\", \"none\",\n                      \"xdata\", x(i), \"ydata\", y(i), \"zdata\", z(i,:),\n                      \"faces\", 1, \"vertices\", [x(i), y(i), z(i,:)],\n                      \"marker\", marker, \"markersize\", s(i),\n                      \"markeredgecolor\", \"none\",\n                      \"markerfacecolor\", \"flat\",\n                      \"cdata\", c(i,:), \"facevertexcdata\", c(i,:),\n                      \"linestyle\", \"none\");\n      else\n        __go_patch__ (hg, \"facecolor\", \"none\", \"edgecolor\", \"none\",\n                      \"xdata\", x(i), \"ydata\", y(i), \"zdata\", z(i,:),\n                      \"faces\", 1, \"vertices\", [x(i), y(i), z(i,:)],\n                      \"marker\", marker, \"markersize\", s(i),\n                      \"markeredgecolor\", \"flat\",\n                      \"markerfacecolor\", \"none\",\n                      \"cdata\", c(i,:), \"facevertexcdata\", c(i,:),\n                      \"linestyle\", \"none\");\n      endif\n    endfor\n  endif\n\nelse\n\n  ## For larger numbers of points, we use one single object.\n  vert = [x, y, z];\n  render_size_color (hg, vert, s, c, marker, filled, true);\n\nendif\n\nif (! ischar (c) && rows (c) > 1)\n  ax = get (hg, \"parent\");\n  clim = get (ax, \"clim\");\n  if (min (c(:)) < clim(1))\n    clim(1) = min (c(:));\n    set (ax, \"clim\", clim);\n  endif\n  if (max (c(:)) > clim(2))\n    set (ax, \"clim\", [clim(1), max(c(:))]);\n  endif\nendif\n\naddproperty (\"linewidth\", hg, \"patchlinewidth\", 0.5);\naddproperty (\"marker\", hg, \"patchmarker\", marker);\nif (filled)\n  addproperty (\"markeredgecolor\", hg, \"patchmarkeredgecolor\", \"none\");\n  if (one_explicit_color)\n    addproperty (\"markerfacecolor\", hg, \"patchmarkerfacecolor\", c);\n  else\n    addproperty (\"markerfacecolor\", hg, \"patchmarkerfacecolor\", \"flat\");\n  endif\nelse\n  addproperty (\"markerfacecolor\", hg, \"patchmarkerfacecolor\", \"none\");\n  if (one_explicit_color)\n    addproperty (\"markeredgecolor\", hg, \"patchmarkeredgecolor\", c);\n  else\n    addproperty (\"markeredgecolor\", hg, \"patchmarkeredgecolor\", \"flat\");\n  endif\nendif\naddlistener (hg, \"linewidth\", @update_props);\naddlistener (hg, \"marker\", @update_props);\naddlistener (hg, \"markerfacecolor\", @update_props);\naddlistener (hg, \"markeredgecolor\", @update_props);\n\n## Matlab property, although Octave does not implement it.\naddproperty (\"hittestarea\", hg, \"radio\", \"on|{off}\", \"off\");\n\nif (! isempty (newargs))\n  set (hg, newargs{:});\nendif\n\nendfunction\n\nfunction render_size_color (hg, vert, s, c, marker, filled, isflat)\n\n  if (isempty (c))\n    c = __next_line_color__ (hax);\n  endif\n\n  if (isscalar (s))\n    x = vert(:,1);\n    y = vert(:,2);\n    z = vert(:,3:end);\n    toolkit = get (ancestor (hg, \"figure\"), \"__graphics_toolkit__\");\n    ## Does gnuplot only support triangles with different vertex colors ?\n    ## FIXME: Verify gnuplot can only support one color.  If RGB triplets\n    ##        can be assigned to each vertex, then fix __gnuplot_draw_axes__.m\n    gnuplot_hack = (numel (x) > 1 && columns (c) == 3\n                    && strcmp (toolkit, \"gnuplot\"));\n    if (ischar (c) || ! isflat || gnuplot_hack)\n      if (filled)\n        ## \"facecolor\" and \"edgecolor\" must be set before any other properties\n        ## to skip co-planarity check (see bug #55751).\n        __go_patch__ (hg, \"facecolor\", \"none\", \"edgecolor\", \"none\",\n                          \"xdata\", x, \"ydata\", y, \"zdata\", z,\n                          \"faces\", 1:numel (x), \"vertices\", vert,\n                          \"marker\", marker,\n                          \"markeredgecolor\", \"none\",\n                          \"markerfacecolor\", c(1,:),\n                          \"markersize\", s, \"linestyle\", \"none\");\n      else\n        __go_patch__ (hg, \"facecolor\", \"none\", \"edgecolor\", \"none\",\n                          \"xdata\", x, \"ydata\", y, \"zdata\", z,\n                          \"faces\", 1:numel (x), \"vertices\", vert,\n                          \"marker\", marker,\n                          \"markeredgecolor\", c(1,:),\n                          \"markerfacecolor\", \"none\",\n                          \"markersize\", s, \"linestyle\", \"none\");\n      endif\n    else\n      if (filled)\n        __go_patch__ (hg, \"facecolor\", \"none\", \"edgecolor\", \"none\",\n                          \"xdata\", x, \"ydata\", y, \"zdata\", z,\n                          \"faces\", 1:numel (x), \"vertices\", vert,\n                          \"marker\", marker, \"markersize\", s,\n                          \"markeredgecolor\", \"none\",\n                          \"markerfacecolor\", \"flat\",\n                          \"cdata\", c, \"facevertexcdata\", c,\n                          \"linestyle\", \"none\");\n      else\n        __go_patch__ (hg, \"facecolor\", \"none\", \"edgecolor\", \"none\",\n                          \"xdata\", x, \"ydata\", y, \"zdata\", z,\n                          \"faces\", 1:numel (x), \"vertices\", vert,\n                          \"marker\", marker, \"markersize\", s,\n                          \"markeredgecolor\", \"flat\",\n                          \"markerfacecolor\", \"none\",\n                          \"cdata\", c, \"facevertexcdata\", c,\n                          \"linestyle\", \"none\");\n      endif\n    endif\n  else\n    ## Round size to one decimal place.\n    [ss, ~, s_to_ss] = unique (ceil (s*10) / 10);\n    for i = 1:rows (ss)\n      idx = (i == s_to_ss);\n      render_size_color (hg, vert(idx,:), ss(i), c,\n                             marker, filled, isflat);\n    endfor\n  endif\n\nendfunction\n\nfunction update_props (h, ~)\n\n  lw = get (h, \"linewidth\");\n  m  = get (h, \"marker\");\n  fc = get (h, \"markerfacecolor\");\n  ec = get (h, \"markeredgecolor\");\n  kids = get (h, \"children\");\n\n  set (kids, \"linewidth\", lw, \"marker\", m,\n             \"markerfacecolor\", fc, \"markeredgecolor\", ec);\n\nendfunction\n\n## FIXME: This callback routine doesn't handle the case where N > 100.\nfunction update_data (h, ~)\n\n  x = get (h, \"xdata\");\n  y = get (h, \"ydata\");\n  z = get (h, \"zdata\");\n  if (numel (x) > 100)\n    error (\"scatter: cannot update data with more than 100 points.  Call scatter (x, y, ...) with new data instead.\");\n  endif\n  c = get (h, \"cdata\");\n  one_explicit_color = ischar (c) || isequal (size (c), [1, 3]);\n  if (! one_explicit_color)\n    if (rows (c) == 1)\n      c = repmat (c, numel (x), 1);\n    endif\n  endif\n  filled = ! strcmp (get (h, \"markerfacecolor\"), \"none\");\n  s = get (h, \"sizedata\");\n  ## Size adjustment for visual compatibility with Matlab.\n  s = sqrt (s);\n  if (numel (s) == 1)\n    s = repmat (s, numel (x), 1);\n  endif\n  hlist = get (h, \"children\");\n\n  if (one_explicit_color)\n    if (filled)\n      if (isempty (z))\n        for i = 1 : length (hlist)\n          set (hlist(i), \"vertices\", [x(i), y(i)],\n                         \"markersize\", s(i),\n                         \"markeredgecolor\", c, \"markerfacecolor\", c);\n\n        endfor\n      else\n        for i = 1 : length (hlist)\n          set (hlist(i), \"vertices\", [x(i), y(i), z(i)],\n                         \"markersize\", s(i),\n                         \"markeredgecolor\", c, \"markerfacecolor\", c);\n        endfor\n      endif\n    else\n      if (isempty (z))\n        for i = 1 : length (hlist)\n          set (hlist(i), \"vertices\", [x(i), y(i)],\n                         \"markersize\", s(i),\n                         \"markeredgecolor\", c, \"markerfacecolor\", \"none\");\n\n        endfor\n      else\n        for i = 1 : length (hlist)\n          set (hlist(i), \"vertices\", [x(i), y(i), z(i)],\n                         \"markersize\", s(i),\n                         \"markeredgecolor\", c, \"markerfacecolor\", \"none\");\n        endfor\n      endif\n    endif\n  else\n    if (filled)\n      if (isempty (z))\n        for i = 1 : length (hlist)\n          set (hlist(i), \"vertices\", [x(i), y(i)],\n                         \"markersize\", s(i),\n                         \"markeredgecolor\", \"none\", \"markerfacecolor\", \"flat\",\n                         \"cdata\", reshape (c(i,:),[1, size(c)(2:end)]),\n                         \"facevertexcdata\", c(i,:));\n        endfor\n      else\n        for i = 1 : length (hlist)\n          set (hlist(i), \"vertices\", [x(i), y(i), z(i)],\n                         \"markersize\", s(i),\n                         \"markeredgecolor\", \"none\", \"markerfacecolor\", \"flat\",\n                         \"cdata\", reshape (c(i,:),[1, size(c)(2:end)]),\n                         \"facevertexcdata\", c(i,:));\n        endfor\n      endif\n    else\n      if (isempty (z))\n        for i = 1 : length (hlist)\n          set (hlist(i), \"vertices\", [x(i), y(i)],\n                         \"markersize\", s(i),\n                         \"markeredgecolor\", \"flat\", \"markerfacecolor\", \"none\",\n                         \"cdata\", reshape (c(i,:),[1, size(c)(2:end)]),\n                         \"facevertexcdata\", c(i,:));\n        endfor\n      else\n        for i = 1 : length (hlist)\n          set (hlist(i), \"vertices\", [x(i), y(i), z(i)],\n                         \"markersize\", s(i),\n                         \"markeredgecolor\", \"flat\", \"markerfacecolor\", \"none\",\n                         \"cdata\", reshape (c(i,:),[1, size(c)(2:end)]),\n                         \"facevertexcdata\", c(i,:));\n        endfor\n      endif\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__interp_cube__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n##\n## -*- texinfo -*-\n## @deftypefn {} {[@var{vxyz}, @var{idx}, @var{frac}] =} __interp_cube__ (@var{caller}, @var{x}, @var{y}, @var{z}, @var{val}, @var{v}, @var{req})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [Vxyz, idx, frac] = __interp_cube__ (caller, x, y, z, val, v,\n                                              req = \"values\")\n\n  if (isnumeric (x) && ndims (x) == 3 && isnumeric (y) && isnumeric (z)\n      && size_equal (x, y, z, val))\n    x = squeeze (x(1,:,1))(:);\n    y = squeeze (y(:,1,1))(:);\n    z = squeeze (z(1,1,:))(:);\n  elseif (isvector (x) && isvector (y) && isvector (z))\n    x = x(:);\n    y = y(:);\n    z = z(:);\n  else\n    error ([caller \": X, Y, Z have unequal dimensions\"]);\n  endif\n\n  if (size (val) != [length(x), length(y), length(z)])\n    error ([caller \": VAL dimensions must match those of X, Y, and Z\"]);\n  endif\n  if (columns (v) != 3)\n    error ([caller \": V must be an Nx3 matrix\"]);\n  endif\n\n  if (isempty (v))\n    Vxyz = idx = frac = [];\n    return;\n  endif\n\n  switch (req)\n    case \"normals\"\n      [idx, frac] = cube_idx (x, y, z, v);\n\n      dx = x(2:end) - x(1:end-1);\n      dy = y(2:end) - y(1:end-1);\n      dz = z(2:end) - z(1:end-1);\n      dx = 0.5 .* [dx;dx(end)](idx(:,2));\n      dy = 0.5 .* [dy;dy(end)](idx(:,1));\n      dz = 0.5 .* [dz;dz(end)](idx(:,3));\n\n      p000 = [v(:, 1) - dx, v(:, 2) - dy, v(:, 3) - dz];\n      p100 = [v(:, 1) + dx, v(:, 2) - dy, v(:, 3) - dz];\n      p010 = [v(:, 1) - dx, v(:, 2) + dy, v(:, 3) - dz];\n      p001 = [v(:, 1) - dx, v(:, 2) - dy, v(:, 3) + dz];\n      p011 = [v(:, 1) - dx, v(:, 2) + dy, v(:, 3) + dz];\n      p101 = [v(:, 1) + dx, v(:, 2) - dy, v(:, 3) + dz];\n      p110 = [v(:, 1) + dx, v(:, 2) + dy, v(:, 3) - dz];\n      p111 = [v(:, 1) + dx, v(:, 2) + dy, v(:, 3) + dz];\n\n      v000 = interp_cube_trilin (x, y, z, val, p000);\n      v100 = interp_cube_trilin (x, y, z, val, p100);\n      v010 = interp_cube_trilin (x, y, z, val, p010);\n      v001 = interp_cube_trilin (x, y, z, val, p001);\n      v011 = interp_cube_trilin (x, y, z, val, p011);\n      v101 = interp_cube_trilin (x, y, z, val, p101);\n      v110 = interp_cube_trilin (x, y, z, val, p110);\n      v111 = interp_cube_trilin (x, y, z, val, p111);\n\n      Dx = -v000 + v100 - v010 - v001 - v011 + v101 + v110 + v111;\n      Dy = -v000 - v100 + v010 - v001 + v011 - v101 + v110 + v111;\n      Dz = -v000 - v100 - v010 + v001 + v011 + v101 - v110 + v111;\n      Vxyz = 0.5 .* [Dx./dx, Dy./dy, Dz./dz];\n\n    case \"normals8\"\n      [idx, frac] = cube_idx (x, y, z, v);\n\n      dx = x(2:end) - x(1:end-1);\n      dy = y(2:end) - y(1:end-1);\n      dz = z(2:end) - z(1:end-1);\n      dx = [dx;dx(end)](idx(:,2));\n      dy = [dy;dy(end)](idx(:,1));\n      dz = [dz;dz(end)](idx(:,3));\n      [Dx, Dy, Dz, idx, frac] = interp_cube_trilin_grad (x, y, z, val, v);\n      Vxyz = [Dx./dx, Dy./dy, Dz./dz];\n\n    case \"values\"\n      [Vxyz, idx, frac] = interp_cube_trilin (x, y, z, val, v);\n\n   otherwise\n     error ([caller ': Invalid request type \"%s\", use \"values\", \"normals\" or \"normals8\"'], req);\n\n  endswitch\n\nendfunction\n\nfunction [Vxyz, idx, frac] = interp_cube_trilin (x, y, z, val, v)\n\n  [idx, frac] = cube_idx (x(:), y(:), z(:), v);\n  sval = size (val);\n  i000 = sub2ind (sval, idx(:, 1), idx(:, 2), idx(:, 3));\n  i100 = sub2ind (sval, idx(:, 1)+1, idx(:, 2), idx(:, 3));\n  i010 = sub2ind (sval, idx(:, 1), idx(:, 2)+1, idx(:, 3));\n  i001 = sub2ind (sval, idx(:, 1), idx(:, 2), idx(:, 3)+1);\n  i101 = sub2ind (sval, idx(:, 1)+1, idx(:, 2), idx(:, 3)+1);\n  i011 = sub2ind (sval, idx(:, 1), idx(:, 2)+1, idx(:, 3)+1);\n  i110 = sub2ind (sval, idx(:, 1)+1, idx(:, 2)+1, idx(:, 3));\n  i111 = sub2ind (sval, idx(:, 1)+1, idx(:, 2)+1, idx(:, 3)+1 );\n  Bx = frac(:, 1);\n  By = frac(:, 2);\n  Bz = frac(:, 3);\n  Vxyz = ...\n    val( i000 ) .* (1 - Bx) .* (1 - By) .* (1 - Bz) + ...\n    val( i100 ) .* Bx .* (1 - By) .* (1 - Bz) + ...\n    val( i010 ) .* (1 - Bx) .* By .* (1 - Bz) + ...\n    val( i001 ) .* (1 - Bx) .* (1 - By) .* Bz + ...\n    val( i011 ) .* (1 - Bx) .* By .* Bz + ...\n    val( i101 ) .* Bx .* (1 - By) .* Bz + ...\n    val( i110 ) .* Bx .* By .* (1 - Bz) + ...\n    val( i111 ) .* Bx .* By .* Bz;\n\nendfunction\n\nfunction [Dx, Dy, Dz, idx, frac] = interp_cube_trilin_grad (x, y, z, val, v)\n\n  [idx, frac] = cube_idx (x(:), y(:), z(:), v);\n  sval = size (val);\n  i000 = sub2ind (sval, idx(:, 1), idx(:, 2), idx(:, 3));\n  i100 = sub2ind (sval, idx(:, 1)+1, idx(:, 2), idx(:, 3));\n  i010 = sub2ind (sval, idx(:, 1), idx(:, 2)+1, idx(:, 3));\n  i001 = sub2ind (sval, idx(:, 1), idx(:, 2), idx(:, 3)+1);\n  i101 = sub2ind (sval, idx(:, 1)+1, idx(:, 2), idx(:, 3)+1);\n  i011 = sub2ind (sval, idx(:, 1), idx(:, 2)+1, idx(:, 3)+1);\n  i110 = sub2ind (sval, idx(:, 1)+1, idx(:, 2)+1, idx(:, 3));\n  i111 = sub2ind (sval, idx(:, 1)+1, idx(:, 2)+1, idx(:, 3)+1 );\n  Bx = frac(:, 1);\n  By = frac(:, 2);\n  Bz = frac(:, 3);\n  Dx = ...\n    val( i000 ) .* -1 .* (1 - By) .* (1 - Bz) + ...\n    val( i100 ) .* (1 - By) .* (1 - Bz) + ...\n    val( i010 ) .* -1 .* By .* (1 - Bz) + ...\n    val( i001 ) .* -1 .* (1 - By) .* Bz + ...\n    val( i011 ) .* -1 .* By .* Bz + ...\n    val( i101 ) .* (1 - By) .* Bz + ...\n    val( i110 ) .* By .* (1 - Bz) + ...\n    val( i111 ) .* By .* Bz;\n  Dy = ...\n    val( i000 ) .* (1 - Bx) .* -1 .* (1 - Bz) + ...\n    val( i100 ) .* Bx .* -1 .* (1 - Bz) + ...\n    val( i010 ) .* (1 - Bx) .* (1 - Bz) + ...\n    val( i001 ) .* (1 - Bx) .* -1 .* Bz + ...\n    val( i011 ) .* (1 - Bx) .* Bz + ...\n    val( i101 ) .* Bx .* -1 .* Bz + ...\n    val( i110 ) .* Bx .* (1 - Bz) + ...\n    val( i111 ) .* Bx .* Bz;\n  Dz = ...\n    val( i000 ) .* (1 - Bx) .* (1 - By) .* -1 + ...\n    val( i100 ) .* Bx .* (1 - By) .* -1 + ...\n    val( i010 ) .* (1 - Bx) .* By .* -1 + ...\n    val( i001 ) .* (1 - Bx) .* (1 - By) + ...\n    val( i011 ) .* (1 - Bx) .* By + ...\n    val( i101 ) .* Bx .* (1 - By) + ...\n    val( i110 ) .* Bx .* By .* -1 + ...\n    val( i111 ) .* Bx .* By;\n\nendfunction\n\nfunction [idx, frac] = cube_idx (x, y, z, v)\n\n  idx = zeros (size (v));\n  frac = zeros (size (v));\n  idx(:, 2) = lookup (x(2:end-1), v(:, 1)) + 1;\n  frac(:, 2) = (v(:, 1) - x(idx(:, 2)) )...\n      ./ (x(idx(:, 2)+1) - x(idx(:, 2)));\n  idx(:, 1) = lookup (y(2:end-1), v(:, 2)) + 1;\n  frac(:, 1) = (v(:, 2) - y(idx(:, 1))) ...\n      ./ (y(idx(:, 1)+1) - y(idx(:, 1)));\n  idx(:, 3) = lookup (z(2:end-1), v(:, 3)) + 1;\n  frac(:, 3) = (v(:, 3) - z(idx(:, 3))) ...\n      ./ (z(idx(:, 3)+1) - z(idx(:, 3)));\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__line__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} __line__ (@var{hp}, @dots{})\n## Create line object with parent handle @var{hp}.\n##\n## Return handle @var{h} to created line objects.\n## @end deftypefn\n\n## __line__ (hp, x, y, z)\n## Create line object from x, y, and z with parent p.\n## Return handle to line object.\n\nfunction h = __line__ (hp, varargin)\n\n  nvargs = nargin - 1;     # remove argument 'hp'\n  have_data_prop = false;\n  if (nvargs > 1 && ! ischar (varargin{1}) && ! ischar (varargin{2}))\n    if (nvargs > 2 && ! ischar (varargin{3}))\n      num_data_args = 3;\n    else\n      num_data_args = 2;\n    endif\n  else\n    num_data_args = 0;\n    if (any (strcmpi (\"xdata\", varargin(1:2:end))))\n      have_data_prop = true;\n    endif\n  endif\n\n  if (rem (nvargs - num_data_args, 2) != 0)\n    error (\"line: invalid number of PROPERTY / VALUE pairs\");\n  endif\n\n  other_args = {};\n  if (nvargs > num_data_args)\n    other_args = varargin(num_data_args+1:end);\n  endif\n\n  if (num_data_args == 0)\n    if (have_data_prop)\n      ## Low-level calling form with a single line\n      handles(1) = __go_line__ (hp, other_args{:});\n    else\n      ## line called without any data, use default data.\n      handles(1) = __go_line__ (hp, \"xdata\", [0, 1], \"ydata\", [0, 1],\n                                    other_args{:});\n    endif\n  else\n    ## Normal case, extract and validate input data args\n    ismat = false (1,3);\n\n    ## Initialize loop variables\n    tmpdata = varargin{1}(:,:);  # N-D arrays -> 2-D arrays\n    if (isvector (tmpdata))\n      tmpdata = tmpdata(:);      # Use column vectors by default\n    else\n      ismat(1) = true;\n    endif\n    [nr, nc] = size (tmpdata);\n    if (islogical (tmpdata))\n      tmpdata = uint8 (tmpdata);\n    elseif (iscomplex (tmpdata))\n      tmpdata = real (tmpdata);\n    endif\n    varargin{1} = tmpdata;\n    reorient_done = false;\n\n    for i = 2:num_data_args\n      tmpdata = varargin{i}(:,:);  # N-D arrays -> 2-D arrays\n\n      if (isvector (tmpdata))\n        tmpdata = tmpdata(:);      # Use column vectors by default\n        [r, c] = size (tmpdata);\n        if (nr == r)\n          ## Do nothing, properly oriented\n        elseif (nc == r && nc > 1 && ! reorient_done)\n          ## Re-orient first matrix\n          varargin{i-1} = varargin{i-1}.';\n          [nr, nc] = deal (nc, nr);  # swap rows and columns.\n          reorient_done = true;\n        else\n          error (\"line: number of X, Y, and Z points must be equal\");\n        endif\n      else\n        ismat(i) = true;\n        [r, c] = size (tmpdata);\n        if (nr == r && (nc == c || nc == 1))\n          ## Do nothing, properly oriented\n          nc = max (nc, c);\n        elseif (nr == c)\n          tmpdata = tmpdata.';\n          [nr, nc] = deal (c, r);  # swap rows and columns.\n        else\n          error (\"line: number of X, Y, and Z points must be equal\");\n        endif\n      endif\n\n      ## Convert logical or complex inputs\n    if (islogical (tmpdata))\n        tmpdata = uint8 (tmpdata);\n      elseif (iscomplex (tmpdata))\n        tmpdata = real (tmpdata);\n      endif\n      varargin{i} = tmpdata;\n\n    endfor\n\n    nlines = nc;\n\n    data = cell (1, 3);\n    data(1:num_data_args) = varargin(1:num_data_args);\n    data_args = {\"xdata\", data{1}, \"ydata\", data{2}, \"zdata\", data{3}};\n    mask = [false, ismat(1), false, ismat(2), false, ismat(3)];\n\n    [colororder_idx, styleorder_idx] = get (hp, {\"ColorOrderIndex\",\n                                                 \"LinestyleOrderIndex\"}){:};\n\n    unwind_protect\n      handles = zeros (nlines, 1);\n      for i = 1:nlines\n        data_args(mask) = cellindexmat (data(ismat), \":\", i);\n\n        ## FIXME: It would be potentially more efficient to write code to\n        ##        cycle line styles and colors within __line__.m itself.\n        ##        However, these are not easy routines to get exactly right,\n        ##        and then there would be duplicate code.  For the time being,\n        ##        use an unwind_protect block to restore any values we may\n        ##        have modified.  Testing shows only 4 millisecond extra delay\n        ##        when plotting 53 lines.\n        [linestyle, marker] = __next_line_style__ (hp);\n        if (nr == 1)\n          ## Marker for a single point is always '.' (bug #38825).\n          marker = '.';\n        endif\n        color = __next_line_color__ (hp);\n\n        handles(i) = __go_line__ (hp, data_args{:},\n                                  \"color\", color, \"linestyle\", linestyle,\n                                  \"marker\", marker, other_args{:});\n      endfor\n    unwind_protect_cleanup\n      set (hp, {\"ColorOrderIndex\", \"LinestyleOrderIndex\"},\n               {colororder_idx, styleorder_idx});\n    end_unwind_protect\n\n  endif\n\n  if (nargout > 0)\n    h = handles;\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__marching_cube__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{t}, @var{p}] =} __marching_cube__ (@var{xx}, @var{yy}, @var{zz}, @var{val}, @var{iso})\n## @deftypefnx {} {[@var{t}, @var{p}, @var{c}] =} __marching_cube__ (@var{xx}, @var{yy}, @var{zz}, @var{v}, @var{iso}, @var{colors})\n##\n## Return the triangulation information @var{t} at points @var{p} for the\n## isosurface values resp.@: the volume data @var{v} and the iso level\n## @var{iso}.  It is considered that the volume data @var{v} is given at\n## the points @var{xx}, @var{yy}, and @var{zz} which are of type\n## three-dimensional numeric arrays.  The orientation of the triangles is\n## chosen such that the normals point from the higher values to the lower\n## values.\n##\n## Optionally the color data @var{colors} can be passed to this function\n## whereas computed vertices color data @var{c} is returned as third\n## argument.\n##\n## The marching cube algorithm is well known and described, for example, at\n## Wikipedia.  The triangulation lookup table and the edge table used here\n## are based on Cory Gene Bloyd's implementation and can be found beyond\n## other surface and geometry stuff at Paul Bourke's website\n## @uref{http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise}.\n##\n## For example:\n##\n## @example\n## @group\n## N = 20;\n## lin = linspace (0, 2, N);\n## [xx, yy, zz] = meshgrid (lin, lin, lin);\n##\n## v = (xx-.5).^2 + (yy-.5).^2 + (zz-.5).^2;\n## [t, p] = __marching_cube__ (xx, yy, zz, v, .5);\n##\n## figure ();\n## trimesh (t, p(:,1), p(:,2), p(:,3));\n## @end group\n## @end example\n##\n## Instead of the @code{trimesh} function the @code{patch} function can be\n## used to visualize the geometry.  For example:\n##\n## @example\n## @group\n## figure ();\n## view (-38, 20);\n## pa = patch (\"Faces\", t, \"Vertices\", p, \"FaceVertexCData\", p,\n##             \"FaceColor\", \"interp\", \"EdgeColor\", \"none\");\n##\n## ## Revert normals\n## set (pa, \"VertexNormals\", -get (pa, \"VertexNormals\"));\n##\n## ## Set lighting\n## set (pa, \"FaceLighting\", \"gouraud\");\n## light ( \"Position\", [1 1 5]);\n## @end group\n## @end example\n##\n## @end deftypefn\n\nfunction [T, p, col] = __marching_cube__ (xx, yy, zz, v, iso, colors)\n\n  persistent edge_table = [];\n  persistent tri_table = [];\n\n  calc_cols = false;\n  lindex = 4;\n\n  if (isempty (tri_table) || isempty (edge_table))\n    [edge_table, tri_table] = init_mc ();\n  endif\n\n  if (! isnumeric (xx) || ! isnumeric (yy) || ! isnumeric (zz)\n      || ! isnumeric (v) || ndims (xx) != 3 || ndims (yy) != 3\n      || ndims (zz) != 3 || ndims (v) != 3)\n    error (\"__marching_cube__: XX, YY, ZZ, v must be 3-D matrices\");\n  endif\n\n  if (! size_equal (xx, yy, zz, v))\n    error (\"__marching_cube__: XX, YY, ZZ, v must be of equal size\");\n  endif\n\n  if (any (size (xx) < [2 2 2]))\n    error (\"__marching_cube__: grid size must be at least 2x2x2\");\n  endif\n\n  if (! isscalar (iso))\n    error (\"__marching_cube__: ISO must be scalar value\");\n  endif\n\n  if (nargin == 6)\n    if (! isnumeric (colors) || ndims (colors) != 3 || ! size_equal (colors, v))\n      error ( \"COLORS must be a 3-D matrix with the same size as v\" );\n    endif\n    calc_cols = true;\n    lindex = 5;\n  endif\n\n  n = size (v) - 1;\n\n  ## phase I: assign information to each voxel which edges are intersected by\n  ## the isosurface.\n  cc = zeros (n(1), n(2), n(3), \"uint16\");\n  cedge = zeros (size (cc), \"uint16\");\n\n  vertex_idx = {1:n(1), 1:n(2), 1:n(3); ...\n                2:n(1)+1, 1:n(2), 1:n(3); ...\n                2:n(1)+1, 2:n(2)+1, 1:n(3); ...\n                1:n(1), 2:n(2)+1, 1:n(3); ...\n                1:n(1), 1:n(2), 2:n(3)+1; ...\n                2:n(1)+1, 1:n(2), 2:n(3)+1; ...\n                2:n(1)+1, 2:n(2)+1, 2:n(3)+1; ...\n                1:n(1), 2:n(2)+1, 2:n(3)+1 };\n\n  ## calculate which vertices have values higher than iso\n  for ii = 1:8\n    idx = v(vertex_idx{ii, :}) > iso;\n    cc(idx) = bitset (cc(idx), ii);\n  endfor\n\n  cedge = edge_table(cc+1);  # assign the info about intersected edges\n  id = find (cedge);         # select only voxels which are intersected\n  if (isempty (id))\n    T = p = col = [];\n    return;\n  endif\n\n  ## phase II: calculate the list of intersection points\n  xyz_off = [1, 1, 1; 2, 1, 1; 2, 2, 1; 1, 2, 1; 1, 1, 2; 2, 1, 2; 2, 2, 2; 1, 2, 2];\n  edges = [1 2; 2 3; 3 4; 4 1; 5 6; 6 7; 7 8; 8 5; 1 5; 2 6; 3 7; 4 8];\n  offset = sub2ind (size (v), xyz_off(:, 1), xyz_off(:, 2), xyz_off(:, 3)) - 1;\n  pp = zeros (length (id), lindex, 12);\n  ccedge = [vec(cedge(id)), id];\n  ix_offset=0;\n  for jj = 1:12\n    ## Make sure \"id__\" is logical egardless of \"bitget\" return type.\n    id__ = logical (bitget (ccedge(:, 1), jj));\n    id_ = ccedge(id__, 2);\n    [ix iy iz] = ind2sub (size (cc), id_);\n    id_c = sub2ind (size (v), ix, iy, iz);\n    id1 = id_c + offset(edges(jj, 1));\n    id2 = id_c + offset(edges(jj, 2));\n    if (calc_cols)\n      pp(id__, 1:5, jj) = [vertex_interp(iso, xx(id1), yy(id1), zz(id1), ...\n        xx(id2), yy(id2), zz(id2), v(id1), v(id2), colors(id1), colors(id2)), ...\n        (1:rows (id_))' + ix_offset ];\n    else\n      pp(id__, 1:4, jj) = [vertex_interp(iso, xx(id1), yy(id1), zz(id1), ...\n        xx(id2), yy(id2), zz(id2), v(id1), v(id2)), ...\n        (1:rows (id_))' + ix_offset ];\n    endif\n    ix_offset += rows (id_);\n  endfor\n\n  ## phase III: calculate the triangulation from the point list\n  T = [];\n  tri = tri_table(cc(id)+1, :);\n  for jj = 1:3:15\n    id_ = find (tri(:, jj) > 0);\n    p = [id_, lindex*ones(rows (id_), 1), tri(id_, jj:jj+2)];\n    if (! isempty (p))\n      p1 = sub2ind (size (pp), p(:,1), p(:,2), p(:,3));\n      p2 = sub2ind (size (pp), p(:,1), p(:,2), p(:,4));\n      p3 = sub2ind (size (pp), p(:,1), p(:,2), p(:,5));\n      T = [T; pp(p1), pp(p2), pp(p3)];\n    endif\n  endfor\n\n  p = [];\n  col = [];\n  for jj = 1:12\n    idp = pp(:, lindex, jj) > 0;\n    if (any (idp))\n      p(pp(idp, lindex, jj), 1:3) = pp(idp, 1:3, jj);\n      if (calc_cols)\n        col(pp(idp, lindex, jj),1) = pp(idp, 4, jj);\n      endif\n    endif\n  endfor\n\nendfunction\n\nfunction p = vertex_interp (isolevel, p1x, p1y, p1z,\n                            p2x, p2y, p2z,valp1,valp2, col1, col2)\n\n  if (nargin == 9)\n    p = zeros (length (p1x), 3);\n  elseif (nargin == 11)\n    p = zeros (length (p1x), 4);\n  else\n    ## FIXME: Do we need input validation on internal functions?\n    error (\"__marching_cube__: wrong number of arguments\");\n  endif\n\n  id = abs (valp1-valp2) < (10*eps) .* (abs (valp1) + abs (valp2));\n  if (any (id))\n    p(id, 1:3) = [ p1x(id), p1y(id), p1z(id) ];\n    if (nargin == 11)\n      p(id, 4) = col1(id);\n    endif\n  endif\n\n  mu = zeros (length (p1x), 1);\n  nid = ! id;\n  if (any (nid))\n    mu(nid) = (isolevel - valp1(nid)) ./ (valp2(nid) - valp1(nid));\n    p(nid, 1:3) = [p1x(nid) + mu(nid) .* (p2x(nid) - p1x(nid)), ...\n      p1y(nid) + mu(nid) .* (p2y(nid) - p1y(nid)), ...\n      p1z(nid) + mu(nid) .* (p2z(nid) - p1z(nid))];\n    if (nargin == 11)\n      p(nid, 4) = col1(nid) + mu(nid) .* (col2(nid) - col1(nid));\n    endif\n  endif\n\nendfunction\n\nfunction [edge_table, tri_table] = init_mc ()\n\n  edge_table = double ([\n    0x0000, 0x0109, 0x0203, 0x030a, 0x0406, 0x050f, 0x0605, 0x070c, ...\n    0x080c, 0x0905, 0x0a0f, 0x0b06, 0x0c0a, 0x0d03, 0x0e09, 0x0f00, ...\n    0x0190, 0x0099, 0x0393, 0x029a, 0x0596, 0x049f, 0x0795, 0x069c, ...\n    0x099c, 0x0895, 0x0b9f, 0x0a96, 0x0d9a, 0x0c93, 0x0f99, 0x0e90, ...\n    0x0230, 0x0339, 0x0033, 0x013a, 0x0636, 0x073f, 0x0435, 0x053c, ...\n    0x0a3c, 0x0b35, 0x083f, 0x0936, 0x0e3a, 0x0f33, 0x0c39, 0x0d30, ...\n    0x03a0, 0x02a9, 0x01a3, 0x00aa, 0x07a6, 0x06af, 0x05a5, 0x04ac, ...\n    0x0bac, 0x0aa5, 0x09af, 0x08a6, 0x0faa, 0x0ea3, 0x0da9, 0x0ca0, ...\n    0x0460, 0x0569, 0x0663, 0x076a, 0x0066, 0x016f, 0x0265, 0x036c, ...\n    0x0c6c, 0x0d65, 0x0e6f, 0x0f66, 0x086a, 0x0963, 0x0a69, 0x0b60, ...\n    0x05f0, 0x04f9, 0x07f3, 0x06fa, 0x01f6, 0x00ff, 0x03f5, 0x02fc, ...\n    0x0dfc, 0x0cf5, 0x0fff, 0x0ef6, 0x09fa, 0x08f3, 0x0bf9, 0x0af0, ...\n    0x0650, 0x0759, 0x0453, 0x055a, 0x0256, 0x035f, 0x0055, 0x015c, ...\n    0x0e5c, 0x0f55, 0x0c5f, 0x0d56, 0x0a5a, 0x0b53, 0x0859, 0x0950, ...\n    0x07c0, 0x06c9, 0x05c3, 0x04ca, 0x03c6, 0x02cf, 0x01c5, 0x00cc, ...\n    0x0fcc, 0x0ec5, 0x0dcf, 0x0cc6, 0x0bca, 0x0ac3, 0x09c9, 0x08c0, ...\n    0x08c0, 0x09c9, 0x0ac3, 0x0bca, 0x0cc6, 0x0dcf, 0x0ec5, 0x0fcc, ...\n    0x00cc, 0x01c5, 0x02cf, 0x03c6, 0x04ca, 0x05c3, 0x06c9, 0x07c0, ...\n    0x0950, 0x0859, 0x0b53, 0x0a5a, 0x0d56, 0x0c5f, 0x0f55, 0x0e5c, ...\n    0x015c, 0x0055, 0x035f, 0x0256, 0x055a, 0x0453, 0x0759, 0x0650, ...\n    0x0af0, 0x0bf9, 0x08f3, 0x09fa, 0x0ef6, 0x0fff, 0x0cf5, 0x0dfc, ...\n    0x02fc, 0x03f5, 0x00ff, 0x01f6, 0x06fa, 0x07f3, 0x04f9, 0x05f0, ...\n    0x0b60, 0x0a69, 0x0963, 0x086a, 0x0f66, 0x0e6f, 0x0d65, 0x0c6c, ...\n    0x036c, 0x0265, 0x016f, 0x0066, 0x076a, 0x0663, 0x0569, 0x0460, ...\n    0x0ca0, 0x0da9, 0x0ea3, 0x0faa, 0x08a6, 0x09af, 0x0aa5, 0x0bac, ...\n    0x04ac, 0x05a5, 0x06af, 0x07a6, 0x00aa, 0x01a3, 0x02a9, 0x03a0, ...\n    0x0d30, 0x0c39, 0x0f33, 0x0e3a, 0x0936, 0x083f, 0x0b35, 0x0a3c, ...\n    0x053c, 0x0435, 0x073f, 0x0636, 0x013a, 0x0033, 0x0339, 0x0230, ...\n    0x0e90, 0x0f99, 0x0c93, 0x0d9a, 0x0a96, 0x0b9f, 0x0895, 0x099c, ...\n    0x069c, 0x0795, 0x049f, 0x0596, 0x029a, 0x0393, 0x0099, 0x0190, ...\n    0x0f00, 0x0e09, 0x0d03, 0x0c0a, 0x0b06, 0x0a0f, 0x0905, 0x080c, ...\n    0x070c, 0x0605, 0x050f, 0x0406, 0x030a, 0x0203, 0x0109, 0x0000 ]);\n\n  tri_table = [\n  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1;\n  3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1;\n  3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1;\n  3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1;\n  9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1;\n  1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1;\n  9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1;\n  2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1;\n  8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1;\n  9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1;\n  4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1;\n  3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1;\n  1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1;\n  4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1;\n  4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1;\n  9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1;\n  1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1;\n  5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1;\n  2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1;\n  9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1;\n  0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1;\n  2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1;\n  10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1;\n  4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1;\n  5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1;\n  5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1;\n  9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1;\n  0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1;\n  1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1;\n  10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1;\n  8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1;\n  2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1;\n  7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1;\n  9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1;\n  2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1;\n  11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1;\n  9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1;\n  5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1;\n  11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1;\n  11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1;\n  1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1;\n  9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1;\n  5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1;\n  2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1;\n  0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1;\n  5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1;\n  6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1;\n  0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1;\n  3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1;\n  6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1;\n  5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1;\n  1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1;\n  10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1;\n  6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1;\n  1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1;\n  8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1;\n  7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1;\n  3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1;\n  5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1;\n  0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1;\n  9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1;\n  8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1;\n  5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1;\n  0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1;\n  6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1;\n  10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1;\n  10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1;\n  8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1;\n  1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1;\n  3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1;\n  0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1;\n  10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1;\n  0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1;\n  3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1;\n  6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1;\n  9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1;\n  8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1;\n  3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1;\n  6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1;\n  0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1;\n  10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1;\n  10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1;\n  1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1;\n  2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1;\n  7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1;\n  7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1;\n  2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1;\n  1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1;\n  11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1;\n  8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1;\n  0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1;\n  7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1;\n  10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1;\n  2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1;\n  6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1;\n  7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1;\n  2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1;\n  1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1;\n  10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1;\n  10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1;\n  0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1;\n  7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1;\n  6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1;\n  8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1;\n  9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1;\n  6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1;\n  1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1;\n  4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1;\n  10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1;\n  8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1;\n  0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1;\n  1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1;\n  8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1;\n  10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1;\n  4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1;\n  10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1;\n  5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1;\n  11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1;\n  9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1;\n  6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1;\n  7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1;\n  3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1;\n  7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1;\n  9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1;\n  3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1;\n  6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1;\n  9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1;\n  1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1;\n  4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1;\n  7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1;\n  6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1;\n  3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1;\n  0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1;\n  6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1;\n  1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1;\n  0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1;\n  11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1;\n  6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1;\n  5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1;\n  9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1;\n  1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1;\n  1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1;\n  10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1;\n  0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1;\n  5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1;\n  10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1;\n  11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1;\n  0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1;\n  9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1;\n  7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1;\n  2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1;\n  8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1;\n  9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1;\n  9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1;\n  1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1;\n  9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1;\n  9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1;\n  5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1;\n  0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1;\n  10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1;\n  2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1;\n  0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1;\n  0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1;\n  9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1;\n  5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1;\n  3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1;\n  5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1;\n  8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1;\n  0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1;\n  9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1;\n  0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1;\n  1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1;\n  3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1;\n  4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1;\n  9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1;\n  11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1;\n  11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1;\n  2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1;\n  9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1;\n  3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1;\n  1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1;\n  4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1;\n  4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1;\n  0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1;\n  3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1;\n  3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1;\n  0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1;\n  9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1;\n  1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;\n  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ] + 1;\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__patch__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{h}, @var{fail}] =} __patch__ (@var{p}, @dots{})\n## Undocumented internal function.\n## @end deftypefn\n\n## __patch__ (p, x, y, c)\n## Create patch object from x and y with color c and parent p.\n## Return handle to patch object.\n\nfunction h = __patch__ (p, varargin)\n\n  h = NaN;\n  nargin = nargin - 1;\n\n  is_numeric_arg = cellfun ('isnumeric', varargin);\n\n  if (isempty (varargin))\n    args = {};\n  elseif (is_numeric_arg(1))\n    if (nargin < 3 || ! is_numeric_arg(2))\n      print_usage (\"patch\");\n    endif\n\n    if (nargin >= 4 && all (is_numeric_arg(1:4)))\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      c = varargin{4};\n      iarg = 5;\n    elseif (nargin >= 3 && all (is_numeric_arg(1:3)))\n      x = varargin{1};\n      y = varargin{2};\n      if (nargin > 3 && iscolorspec (varargin{4}))\n        z = varargin{3};\n        c = varargin{4};\n        iarg = 5;\n      else\n        z = [];\n        c = varargin{3};\n        iarg = 4;\n      endif\n    elseif (nargin >= 3 && all (is_numeric_arg(1:2)))\n      x = varargin{1};\n      y = varargin{2};\n      z = [];\n      if (iscolorspec (varargin{3}))\n        c = varargin{3};\n        iarg = 4;\n      elseif (nargin == 3)\n        error (\"patch: invalid color specification C\");\n      else\n        c = [];\n        iarg = 3;\n      endif\n    endif\n\n    if (isvector (x))\n      x = x(:);\n      y = y(:);\n      z = z(:);\n      if (isnumeric (c))\n        if (isvector (c))\n          if (isequal (size (c), [1, 3]))\n            ## Do nothing, this is a single RGB color specification\n          elseif (numel (c) == numel (x))\n            c = c(:);\n          endif\n        elseif (rows (c) != numel (x) && columns (c) == numel (x))\n          c = c.';\n        endif\n      endif\n    endif\n    args{1} = \"xdata\";\n    args{2} = x;\n    args{3} = \"ydata\";\n    args{4} = y;\n    args{5} = \"zdata\";\n    args{6} = z;\n\n    if (isnumeric (c) && ! isempty (c))\n\n      if (ndims (c) == 3 && columns (c) == 1)\n        c = permute (c, [1, 3, 2]);\n      endif\n\n      if (isvector (c) && numel (c) == columns (x))\n        ## One color per face\n        if (isnan (c))\n          args{7} = \"facecolor\";\n          args{8} = [1, 1, 1];\n        else\n          args{7} = \"facecolor\";\n          args{8} = \"flat\";\n        endif\n        args{9} = \"facevertexcdata\";\n        args{10} = c(:);\n      elseif (isrow (c) && numel (c) == 3)\n        ## One RGB color\n        args{7} = \"facecolor\";\n        args{8} = c;\n        args{9} = \"cdata\";\n        args{10} = [];\n      elseif (ndims (c) == 3 && size (c, 3) == 3)\n        ## CDATA is specified as 3-D RGB data\n        if ((rows (c) == 1 && columns (c) == 1) ...\n            || (rows (c) == 1 && columns (c) == columns (x)))\n          ## Single patch color or per-face color\n          args{7} = \"facecolor\";\n          args{8} = \"flat\";\n          args{9} = \"cdata\";\n          args{10} = c;\n        elseif (rows (c) == rows (x) && columns (c) == columns (x))\n          ## Per-vertex color\n          args{7} = \"facecolor\";\n          args{8} = \"interp\";\n          args{9} = \"cdata\";\n          args{10} = c;\n        else\n          error (\"patch: invalid TrueColor data C\");\n        endif\n      else\n        ## Color vectors\n        if (isempty (c))\n          args{7} = \"facecolor\";\n          args{8} = \"interp\";\n          args{9} = \"cdata\";\n          args{10} = [];\n        elseif (size_equal (c, x) && size_equal (c, y))\n          args{7} = \"facecolor\";\n          args{8} = \"interp\";\n          args{9} = \"cdata\";\n          args{10} = c;\n        else\n          error (\"patch: size of X, Y, and C must be equal\");\n        endif\n      endif\n    elseif (iscolorspec (c))\n      ## Color specification is a string\n      args{7} = \"facecolor\";\n      args{8} = lower (c);\n      args{9} = \"cdata\";\n      args{10} = [];\n    elseif (! isempty (c))\n      error (\"patch: invalid color specification C\");\n    endif\n\n    args = [args, varargin(iarg:end)];\n\n  else\n    ## \"Property\"/Value pair input\n    args = varargin;\n  endif\n\n  if (isempty (p))\n    p = gca ();\n  endif\n  h = __go_patch__ (p, args{:});\n\nendfunction\n\nfunction retval = iscolorspec (arg)\n\n  retval = false;\n  if (ischar (arg))\n    persistent colors = {\"y\", \"yellow\", \"r\", \"red\", \"m\", \"magenta\", ...\n                         \"c\", \"cyan\", \"g\", \"green\", \"b\", \"blue\", ...\n                         \"w\", \"white\", \"k\", \"black\"};\n    if (any (strcmpi (arg, colors)))\n      retval = true;\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__pie__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{hlist} =} __pie__ (caller, @dots{})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction hlist = __pie__ (caller, varargin)\n\n  h = varargin{1};\n  x = abs (varargin{2});\n  iarg = 3;\n\n  if (! isvector (x))\n    error (\"%s: X must be a vector\", caller);\n  endif\n\n  len = length (x);\n\n  have_explode = false;\n  have_labels = false;\n\n  while (iarg <= nargin - 1)\n    arg = varargin{iarg++};\n    if (iscell (arg))\n      labels = arg;\n      have_labels = true;\n      if (numel (x) != numel (labels))\n        error (\"%s: mismatch in number of labels and data\", caller);\n      endif\n    elseif (isnumeric (arg) || islogical (arg))\n      explode = arg;\n      have_explode = true;\n      if (! size_equal (x, explode))\n        error (\"%s: mismatch in number of elements in explode and data\",\n               caller);\n      endif\n    else\n      error (\"%s: %s is invalid as an optional argument\", caller, class (arg));\n    endif\n  endwhile\n\n  if (! have_explode)\n    explode = zeros (size (x));\n  endif\n\n  normalize = true;\n  if (sum (x(:)) < 1)\n    normalize = false;\n  endif\n\n  if (! have_labels)\n    if (normalize)\n      xp = round (100 * x ./ sum (x));\n    else\n      xp = round (100 * x);\n    endif\n    for i = 1:len\n      labels{i} = sprintf (\"%d%%\", xp(i));\n    endfor\n  endif\n\n  hlist = [];\n  refinement = 90;\n  phi = 0:refinement:360;\n  if (normalize)\n    xphi = cumsum (x / sum (x) * 360);\n  else\n    xphi = cumsum (x * 360);\n  endif\n\n  for i = 1:len\n    if (i == 1)\n      xn = 0 : 360 / refinement : xphi(i);\n    else\n      xn = xphi(i-1) : 360 / refinement : xphi(i);\n    endif\n\n    if (xn(end) != xphi(i))\n      xn = [xn, xphi(i)];\n    endif\n\n    xn2 = (xn(1) + xn(end)) / 2;\n    if (explode (i))\n      xoff = - 0.1 * sind (xn2);\n      yoff = 0.1 * cosd (xn2);\n    else\n      xoff = 0;\n      yoff = 0;\n    endif\n    xt = - 1.2 * sind (xn2);\n    yt = 1.2 * cosd (xn2);\n\n    if (len == 1)\n      set (h, \"clim\", [1, 2]);\n    else\n      set (h, \"clim\", [1, len]);\n    endif\n\n    if (strcmp (caller, \"pie3\"))\n      ln = length (xn);\n      zlvl = 0.35;\n      sx = repmat (xoff + [0, -sind(xn), 0], [2, 1]);\n      sy = repmat (yoff + [0, cosd(xn), 0], [2, 1]);\n      sz = [zeros(1, ln + 2); zlvl * ones(1, ln + 2)];\n      sc = i * ones (size (sz));\n\n      hlist = [hlist;\n        patch(h, xoff + [0, -sind(xn)], yoff + [0, cosd(xn)], zeros (1, ln + 1), i);\n        surface(h, sx, sy, sz, sc);\n        patch(h, xoff + [0, -sind(xn)], yoff + [0, cosd(xn)], zlvl * ones (1, ln + 1), i);\n        text(h, xt, yt, zlvl, labels{i})];\n\n    elseif (strcmp (caller, \"pie\"))\n      if (xt > 0)\n        align = \"left\";\n      elseif (xt < 0)\n        align = \"right\";\n      else\n        align = \"center\";\n      endif\n\n      hlist = [hlist; patch(h, xoff + [0, -sind(xn)], yoff + [0, cosd(xn)], i);\n               text(h, xt, yt, labels{i}, \"horizontalalignment\", align)];\n\n    else\n      error (\"__pie__: unknown caller '%s'\", caller);\n    endif\n  endfor\n\n  addlistener (h, \"view\", {@update_text_pos, hlist});\n\n  if (strcmp (caller, \"pie3\"))\n    axis (h, [-1.25, 1.25, -1.25, 1.25, -0.05, 0.4], \"equal\", \"off\");\n    view (h, -37.5, 30);\n  elseif (strcmp (caller, \"pie\"))\n    axis (h, [-1.5, 1.5, -1.5, 1.5], \"square\", \"off\");\n  endif\n\nendfunction\n\nfunction update_text_pos (~, ~, all_handles)\n\n  ## Text objects in the foreground should be at the base level.\n  ## Text objects in the background should be at the top level.\n  ## Text objects on the right side should be aligned to the right\n  ## and on the left side to the left.\n  tobj = findobj (all_handles, \"type\", \"text\");\n\n  ## check if we are called from pie3\n  s = findobj (all_handles, \"type\", \"surface\");\n  is_pie3 = false;\n  if (length (s) > 0)\n    is_pie3 = true;\n  endif\n\n  if (length (tobj) > 0)\n    ax = get (tobj(1), \"parent\");\n    azel = get (ax, \"view\");\n    pos = get (tobj, \"position\");\n    if (iscell (pos))\n      pos = cell2mat (pos);\n    endif\n    phi = atand (pos(:,1) ./ pos(:,2));\n    [theta, r] = cart2pol (pos(:,1), pos(:,2));\n    theta *= 180/pi;\n    theta -= azel(1);\n    theta = mod (theta, 360);\n    ud_mask = (theta > 180);\n    lr_mask = (theta > 90) & (theta < 270);\n    for i = 1 : length (tobj)\n      if (is_pie3)\n        if (ud_mask(i))\n          set (tobj(i), \"position\", [pos(i,1), pos(i,2), -0.05]);\n        else\n          set (tobj(i), \"position\", [pos(i,1), pos(i,2), 0.40]);\n        endif\n      endif\n\n      if (lr_mask(i))\n        set (tobj(i), \"horizontalalignment\", \"right\");\n      else\n        set (tobj(i), \"horizontalalignment\", \"left\");\n      endif\n    endfor\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__plt__.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} __plt__ (@var{caller}, @var{hp}, @var{varargin})\n## Internal function with common code to implement several 2-D plot types.\n## @seealso{plot, polar, loglog, semilogx, semilogy}\n## @end deftypefn\n\nfunction retval = __plt__ (caller, hp, varargin)\n\n  persistent warned_callers = {};\n  nargs = nargin - 2;\n\n  if (nargs < 1)\n    error (\"__plt__: invalid number of arguments\");\n  endif\n\n  k = 1;\n\n  x_set = false;\n  y_set = false;\n  property_set = false;\n  properties = {};\n\n  ## Find any legend associated with this axes\n  try\n    hlegend = get (hp, \"__legend_handle__\");\n  catch\n    hlegend = [];\n  end_try_catch\n\n  setlgnd = false;\n  if (isempty (hlegend))\n    hlgnd = [];\n    tlgnd = {};\n  else\n    [hlgnd, tlgnd] = __getlegenddata__ (hlegend);\n  endif\n\n  ## Gather arguments, decode format, gather plot strings, and plot lines.\n\n  retval = [];\n\n  while (nargs > 0 || x_set)\n\n    if (nargs == 0)\n      ## Force the last plot when input variables run out.\n      next_cell = {};\n      next_arg = {\"\"};\n    else\n      next_cell = varargin(k);\n      next_arg = varargin{k++};\n    endif\n\n    if (isnumeric (next_arg) && ndims (next_arg) > 2\n        && any (size (next_arg) == 1))\n      next_arg = squeeze (next_arg);\n      if (! any (strcmp (caller, warned_callers)) && ndims (next_arg) < 3)\n        warning ([\"%s: N-D inputs have been squeezed to less than \" ...\n                  \"three dimensions\"], caller);\n        warned_callers(end+1) = caller;\n      endif\n    endif\n    if (isnumeric (next_arg) && ndims (next_arg) > 2)\n      error (\"%s: plot arrays must have less than 2 dimensions\", caller);\n    endif\n\n    nargs -= 1;\n\n    if (ischar (next_arg) || iscellstr (next_arg))\n      if (x_set)\n        [options, valid] = __pltopt__ (caller, next_arg, false);\n        if (! valid)\n          if (nargs == 0)\n            error (\"%s: properties must appear followed by a value\", caller);\n          endif\n          properties = [properties, [next_cell, varargin(k++)]];\n          nargs -= 1;\n          continue;\n        else\n          while (nargs > 0 && ischar (varargin{k}))\n            if (nargs < 2)\n              error (\"%s: properties must appear followed by a value\",\n                     caller);\n            endif\n            properties = [properties, varargin(k:k+1)];\n            k += 2;\n            nargs -= 2;\n          endwhile\n        endif\n        if (y_set)\n          htmp = __plt2__ (hp, x, y, options, properties);\n          [hlgnd, tlgnd, setlgnd] = ...\n            __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);\n          properties = {};\n          retval = [retval; htmp];\n        else\n          htmp = __plt1__ (hp, x, options, properties);\n          [hlgnd, tlgnd, setlgnd] = ...\n             __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);\n          properties = {};\n          retval = [retval; htmp];\n        endif\n        x_set = false;\n        y_set = false;\n      else\n        error (\"plot: no data to plot\");\n      endif\n    elseif (x_set)\n      if (y_set)\n        options = __pltopt__ (caller, {\"\"});\n        htmp = __plt2__ (hp, x, y, options, properties);\n        [hlgnd, tlgnd, setlgnd] = ...\n          __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);\n        retval = [retval; htmp];\n        x = next_arg;\n        y_set = false;\n        properties = {};\n      else\n        y = next_arg;\n        y_set = true;\n      endif\n    else\n      x = next_arg;\n      x_set = true;\n    endif\n\n  endwhile\n\n  if (setlgnd)\n    legend (gca (), hlgnd, tlgnd);\n  endif\n\nendfunction\n\nfunction [hlgnd, tlgnd, setlgnd] = __plt_key__ (hp, options,\n                                                hlgnd, tlgnd, setlgnd)\n\n  n = numel (hp);\n  if (numel (options) == 1)\n    options = repmat (options(:), n, 1);\n  endif\n\n  for i = 1 : n\n    key = options(i).key;\n    if (! isempty (key))\n      hlgnd = [hlgnd(:); hp(i)];\n      tlgnd = {tlgnd{:}, key};\n      setlgnd = true;\n    endif\n  endfor\n\nendfunction\n\nfunction retval = __plt1__ (hp, x1, options, properties = {})\n\n  if (nargin < 3 || isempty (options))\n    options = __default_plot_options__ ();\n  endif\n\n  if (! isstruct (options))\n    error (\"__plt1__: options must be a struct array\");\n  endif\n\n  [nr, nc] = size (x1);\n  if (nr == 1)\n    x1 = x1.';\n    [nr, nc] = deal (nc, nr);   # Swap rows and columns\n  endif\n  if (iscomplex (x1))\n    x1_i = imag (x1);\n    if (any ((x1_i(:))))\n      x2 = x1_i;\n      x1 = real (x1);\n    else\n      x2 = x1;\n      x1 = (1:nr)';\n    endif\n  else\n    x2 = x1;\n    x1 = (1:nr)';\n  endif\n\n  retval = __plt2__ (hp, x1, x2, options, properties);\n\nendfunction\n\nfunction retval = __plt2__ (hp, x1, x2, options, properties = {})\n\n  if (nargin < 4 || isempty (options))\n    options = __default_plot_options__ ();\n  endif\n\n  if (! isstruct (options))\n    error (\"__plt2__: options must be a struct array\");\n  endif\n\n  if (islogical (x1))\n    x1 = int8 (x1);\n  elseif (iscomplex ((x1)))\n    x1 = real (x1);\n  endif\n\n  if (islogical (x2))\n    x2 = int8 (x2);\n  elseif (iscomplex (x2))\n    x2 = real (x2);\n  endif\n\n  h_set = false;\n  if (isempty (x1) && isempty (x2))\n    retval = zeros (0, 1);\n  elseif (isscalar (x1))\n    if (isscalar (x2))\n      retval = __plt2ss__ (hp, x1, x2, options, properties);\n    elseif (isvector (x2))\n      retval = __plt2sv__ (hp, x1, x2, options, properties);\n    else\n      error (\"__plt2__: invalid data for plotting\");\n    endif\n  elseif (isvector (x1))\n    if (isscalar (x2))\n      retval = __plt2vs__ (hp, x1, x2, options, properties);\n    elseif (isvector (x2))\n      retval = __plt2vv__ (hp, x1, x2, options, properties);\n    elseif (ismatrix (x2))\n      retval = __plt2vm__ (hp, x1, x2, options, properties);\n    else\n      error (\"__plt2__: invalid data for plotting\");\n    endif\n  elseif (ismatrix (x1))\n    if (isvector (x2))\n      retval = __plt2mv__ (hp, x1, x2, options, properties);\n    elseif (ismatrix (x2))\n      retval = __plt2mm__ (hp, x1, x2, options, properties);\n    else\n      error (\"__plt2__: invalid data for plotting\");\n    endif\n  else\n    error (\"__plt2__: invalid data for plotting\");\n  endif\n\nendfunction\n\nfunction retval = __plt2mm__ (hp, x, y, options, properties = {})\n\n  if (nargin < 4 || isempty (options))\n    options = __default_plot_options__ ();\n  endif\n\n  [x_nr, x_nc] = size (x);\n  [y_nr, y_nc] = size (y);\n\n  if (x_nr != y_nr && x_nc != y_nc)\n    error (\"__plt2mm__: matrix dimensions must match\");\n  endif\n\n  if (numel (options) == 1)\n    options = repmat (options(:), x_nc, 1);\n  endif\n  retval = zeros (x_nc, 1);\n  for i = 1:x_nc\n    linestyle = options(i).linestyle;\n    marker = options(i).marker;\n    if (isempty (marker) && isempty (linestyle))\n      [linestyle, marker] = __next_line_style__ (hp);\n    endif\n    color = options(i).color;\n    if (isempty (color))\n      color = __next_line_color__ (hp);\n    endif\n\n    retval(i) = __go_line__ (hp, \"xdata\", x(:,i), \"ydata\", y(:,i),\n                             \"color\", color, \"linestyle\", linestyle,\n                             \"marker\", marker, properties{:});\n  endfor\n\nendfunction\n\nfunction retval = __plt2mv__ (hp, x, y, options, properties = {})\n\n  if (nargin < 4 || isempty (options))\n    options = __default_plot_options__ ();\n  endif\n\n  y = y(:);\n  [y_nr, y_nc] = size (y);\n  [x_nr, x_nc] = size (x);\n\n  if (x_nr == y_nr)\n    ## Correctly oriented.  Do nothing.\n  elseif (x_nc == y_nr)\n    x = x.';\n    [x_nr, x_nc] = deal (x_nc, x_nr);\n  else\n    error (\"__plt2mv__: matrix dimensions must match\");\n  endif\n\n  if (numel (options) == 1)\n    options = repmat (options(:), x_nc, 1);\n  endif\n  retval = zeros (x_nc, 1);\n  for i = 1:x_nc\n    linestyle = options(i).linestyle;\n    marker = options(i).marker;\n    if (isempty (marker) && isempty (linestyle))\n      [linestyle, marker] = __next_line_style__ (hp);\n    endif\n    color = options(i).color;\n    if (isempty (color))\n      color = __next_line_color__ (hp);\n    endif\n\n    retval(i) = __go_line__ (hp, \"xdata\", x(:,i), \"ydata\", y,\n                             \"color\", color, \"linestyle\", linestyle,\n                             \"marker\", marker, properties{:});\n  endfor\n\nendfunction\n\nfunction retval = __plt2ss__ (hp, x, y, options, properties = {})\n\n  if (nargin < 4 || isempty (options))\n    options = __default_plot_options__ ();\n  endif\n\n  if (numel (options) > 1)\n    options = options(1);\n  endif\n\n  linestyle = options.linestyle;\n  marker = options.marker;\n  if (isempty (marker) && isempty (linestyle))\n    ## If unspecified, marker for a single point is always \".\"\n    linestyle = \"-\";\n    marker = \".\";\n  endif\n  color = options.color;\n  if (isempty (color))\n    color = __next_line_color__ (hp);\n  endif\n\n  retval = __go_line__ (hp, \"xdata\", x, \"ydata\", y,\n                        \"color\", color, \"linestyle\", linestyle,\n                        \"marker\", marker, properties{:});\n\nendfunction\n\nfunction retval = __plt2sv__ (hp, x, y, options, properties = {})\n\n  if (nargin < 4 || isempty (options))\n    options = __default_plot_options__ ();\n  endif\n\n  len = numel (y);\n  if (numel (options) == 1)\n    options = repmat (options(:), len, 1);\n  endif\n  retval = zeros (len, 1);\n  for i = 1:len\n    linestyle = options(i).linestyle;\n    marker = options(i).marker;\n    if (isempty (marker) && isempty (linestyle))\n      ## If unspecified, marker for a point is always \".\"\n      linestyle = \"-\";\n      marker = \".\";\n    endif\n    color = options(i).color;\n    if (isempty (color))\n      color = __next_line_color__ (hp);\n    endif\n\n    retval(i) = __go_line__ (hp, \"xdata\", x, \"ydata\", y(i),\n                             \"color\", color, \"linestyle\", linestyle,\n                             \"marker\", marker, properties{:});\n  endfor\n\nendfunction\n\nfunction retval = __plt2vm__ (hp, x, y, options, properties = {})\n\n  if (nargin < 4 || isempty (options))\n    options = __default_plot_options__ ();\n  endif\n\n  x = x(:);\n  [x_nr, x_nc] = size (x);\n  [y_nr, y_nc] = size (y);\n\n  if (x_nr == y_nr)\n    ## Correctly oriented.  Do nothing.\n  elseif (x_nr == y_nc)\n    y = y.';\n    [y_nr, y_nc] = deal (y_nc, y_nr);\n  else\n    error (\"__plt2vm__: matrix dimensions must match\");\n  endif\n\n  if (numel (options) == 1)\n    options = repmat (options(:), y_nc, 1);\n  endif\n  retval = zeros (y_nc, 1);\n  for i = 1:y_nc\n    linestyle = options(i).linestyle;\n    marker = options(i).marker;\n    if (isempty (marker) && isempty (linestyle))\n      [linestyle, marker] = __next_line_style__ (hp);\n    endif\n    color = options(i).color;\n    if (isempty (color))\n      color = __next_line_color__ (hp);\n    endif\n\n    retval(i) = __go_line__ (hp, \"xdata\", x, \"ydata\", y(:,i),\n                             \"color\", color, \"linestyle\", linestyle,\n                             \"marker\", marker, properties{:});\n  endfor\n\nendfunction\n\nfunction retval = __plt2vs__ (hp, x, y, options, properties = {})\n\n  if (nargin < 4 || isempty (options))\n    options = __default_plot_options__ ();\n  endif\n\n  len = numel (x);\n  if (numel (options) == 1)\n    options = repmat (options(:), len, 1);\n  endif\n  retval = zeros (len, 1);\n  for i = 1:len\n    linestyle = options(i).linestyle;\n    marker = options(i).marker;\n    if (isempty (marker) && isempty (linestyle))\n      ## If unspecified, marker for a point is always \".\"\n      linestyle = \"-\";\n      marker = \".\";\n    endif\n    color = options(i).color;\n    if (isempty (color))\n      color = __next_line_color__ (hp);\n    endif\n\n    retval(i) = __go_line__ (hp, \"xdata\", x(i), \"ydata\", y,\n                             \"color\", color, \"linestyle\", linestyle,\n                             \"marker\", marker, properties{:});\n  endfor\n\nendfunction\n\nfunction retval = __plt2vv__ (hp, x, y, options, properties = {})\n\n  if (nargin < 4 || isempty (options))\n    options = __default_plot_options__ ();\n  endif\n\n  if (numel (options) > 1)\n    options = options(1);\n  endif\n\n  x = x(:);\n  y = y(:);\n\n  if (length (x) != length (y))\n    error (\"__plt2vv__: vector lengths must match\");\n  endif\n\n  linestyle = options.linestyle;\n  marker = options.marker;\n  if (isempty (marker) && isempty (linestyle))\n    [linestyle, marker] = __next_line_style__ (hp);\n  endif\n  color = options.color;\n  if (isempty (color))\n    color = __next_line_color__ (hp);\n  endif\n\n  retval = __go_line__ (hp, \"xdata\", x, \"ydata\", y,\n                        \"color\", color, \"linestyle\", linestyle,\n                        \"marker\", marker, properties{:});\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__quiver__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{hg} =} __quiver__ (@dots{})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [hax, hg]= __quiver__ (varargin)\n\n  hax = varargin{1};\n  is3d = varargin{2};\n\n  autoscale = 0.9;\n  ## Matlab uses 0.2, but Octave's algorithm produces equivalent visual\n  ## results if arrowsize=0.33.  Since this is just a non-dimensional\n  ## scaling factor we scale the arrowsize property value by 0.33/0.20\n  ## in order to get equivalent visual results while keeping equivalent\n  ## property values.\n  arrowsize = 0.20;\n  lastnumeric = find (cellfun (\"ischar\", varargin(3:nargin)), 1) - 1;\n\n  if (isempty (lastnumeric))\n    lastnumeric = nargin;\n    ## Recast non-float inputs as doubles to avoid erroneous plots.\n    varargin(3:end) = cellfun ('double', varargin(3:end), ...\n                               \"UniformOutput\", false);\n  else\n\n    lastnumeric += 2;\n    ## Recast non-float inputs as doubles to avoid erroneous plots.\n    varargin(3:lastnumeric) = cellfun ('double',\n                    varargin(3:lastnumeric), \"UniformOutput\", false);\n\n    ## Check for scaling factor \"off\" and set it to 0.\n    if ((nargin > lastnumeric) && strcmpi (varargin{lastnumeric+1}, \"off\"))\n      varargin(++lastnumeric) = 0;\n    endif\n  endif\n\n  if (is3d)\n    ## quiver3 3-D input validation.\n    switch (lastnumeric)\n      case {6,7}\n        [z, u, v, w] = deal (varargin{3:6});\n        if (isvector (z) && ! isvector (u))\n          if (! size_equal (u, v, w))\n            error (\"quiver3: U, V, and W must be the same size\");\n          elseif (numel (z) != size (u, 3))\n            error ([\"quiver3: Z vector length must equal size of \", ...\n                        \"U, V, and W in dim 3\"]);\n          endif\n          [x, y, z] = meshgrid (1 : columns (u), 1 : rows (u), z);\n        else\n          if (! size_equal (z, u, v, w))\n            error (\"quiver3: Z, U, V, and W must be the same size\");\n          endif\n          [x, y] = meshgrid (1 : columns (u), 1 : rows (u), 1:size (u, 3));\n        endif\n\n      case {8,9}\n        [x, y, z, u, v, w] = deal (varargin{3:8});\n        if (isvector (x) && isvector (y) && isvector (z) && ! isvector (u))\n          if (! size_equal (u, v, w))\n            error (\"quiver3: U, V, and W must be the same size\");\n          elseif (numel (x) != columns (u))\n            error ([\"quiver3: X vector length must equal number of \", ...\n                        \"columns in U, V, and W\"]);\n          elseif (numel (y) != rows (u))\n            error ([\"quiver3: Y vector length must equal number of \", ...\n                        \"rows in U, V, and W\"]);\n          elseif (numel (z) != size (u, 3))\n            error ([\"quiver3: Z vector length must equal size of \", ...\n                        \"U, V, and W in dim 3\"]);\n          endif\n          [x, y, z] = meshgrid (x, y, z);\n\n        elseif (! size_equal (x, y, z, u, v, w))\n          error (\"quiver3: X, Y, Z, U, V, and W must be the same size\");\n        endif\n      otherwise\n        ## too few or too many numeric inputs before first style input\n        print_usage (\"quiver3\");\n    endswitch\n\n  else\n    ## quiver 2-D input validation.\n    switch (lastnumeric)\n      case {4,5}\n        [u, v] = deal (varargin{3:4});\n        if (! size_equal (u, v))\n          error (\"quiver: U and V must be the same size\");\n        endif\n        [x, y] = meshgrid (1:columns (u), 1:rows (u));\n\n      case {6,7} #\n        [x, y, u, v] = deal (varargin{3:6});\n\n        if (isvector (x) && isvector (y) && ...\n                (! isvector (u) || ! isvector (v) ))\n           if (! size_equal (u, v))\n              error (\"quiver: U and V must be the same size\");\n           elseif (numel (x) != columns (u))\n              error ([\"quiver: X vector length must equal number of \", ...\n                        \"columns in U and V\"]);\n           elseif (numel (y) != rows (u))\n              error ([\"quiver: Y vector length must equal number of \", ...\n                        \"rows in U and V\"]);\n           endif\n          [x, y] = meshgrid (x, y);\n        elseif (! size_equal (x, y, u, v))\n          error (\"quiver: X, Y, U, and V must be the same size\");\n        endif\n      otherwise\n        ## too few or too many numeric inputs before first style input\n        print_usage (\"quiver\");\n    endswitch\n  endif\n\n  if (rem (lastnumeric, 2))\n    autoscale = varargin{lastnumeric}; # Last odd input is scale factor.\n\n    if (autoscale < 0 || ! isscalar (autoscale))\n      if (is3d)\n        error ([\"quiver3: scaling factor must be a non-negative scalar \", ...\n                 \"or 'off'\"]);\n      else\n        error ([\"quiver: scaling factor must be a non-negative scalar \", ...\n                 \"or 'off'\"]);\n      endif\n    endif\n  endif\n\n  ioff = lastnumeric + 1;\n  have_filled = false;\n  have_line_spec = false;\n  args = {};\n  while (ioff <= nargin)\n    arg = varargin{ioff++};\n    if (ischar (arg) && strcmpi (arg, \"filled\"))\n      have_filled = true;\n    elseif ((ischar (arg) || iscellstr (arg))\n            && ! have_line_spec)\n      [linespec, valid] = __pltopt__ (\"quiver\", arg, false);\n      if (valid)\n        have_line_spec = true;\n        if (isempty (linespec.linestyle) || strcmp (linespec.linestyle, \"none\"))\n          linespec.linestyle = \"-\";\n        endif\n      else\n        args{end+1} = arg;\n        if (ioff <= nargin)\n          args{end+1} = varargin{ioff++};\n        endif\n      endif\n    else\n      args{end+1} = arg;\n      if (ioff <= nargin)\n        args{end+1} = varargin{ioff++};\n      endif\n    endif\n  endwhile\n\n  ## Normalize 0.20 to 1/3 for plotting\n  arrowsize /= 0.20 * 3;\n\n  ## Scale the arrows to fit in the grid\n  uu = u;\n  vv = v;\n  if (is3d)\n    ww = w;\n    len = max (sqrt (u(:).^2 + v(:).^2 + w(:).^2));\n  else\n    len = max (sqrt (u(:).^2 + v(:).^2));\n  endif\n  if (len > 0 && autoscale && numel (u) >= 1)\n    if (isvector (x))\n      nx = ny = sqrt (length (x));\n    else\n      [ny, nx] = size (x);  # assume meshgrid fmt, x in columns, y in rows\n    endif\n    dx = (max (x(:)) - min (x(:))) / nx;\n    dy = (max (y(:)) - min (y(:))) / ny;\n    if (is3d)\n      dz = (max (z(:)) - min (z(:))) / max (nx, ny);\n    else\n      dz = 0;\n    endif\n    sd = sqrt (dx.^2 + dy.^2 + dz.^2) / len;\n    if (sd != 0)\n      s = autoscale * sd;\n    else  # special case of identical points with multiple vectors\n      s = autoscale;\n    endif\n    uu = s * u;\n    vv = s * v;\n    if (is3d)\n      ww = s * w;\n    endif\n  endif\n\n  hax = newplot (hax);\n  hstate = get (hax, \"nextplot\");\n  unwind_protect\n    if (have_line_spec)\n      ls = linespec.linestyle;\n      lc = linespec.color;\n      if (isempty (lc))\n        lc = __next_line_color__ (hax);\n      endif\n    else\n      ls = \"-\";\n      lc = __next_line_color__ (hax);\n    endif\n\n    ## Must occur after __next_line_color__ in order to work correctly.\n    hg = hggroup (hax, \"__appdata__\", struct (\"__creator__\", \"__quiver__\"));\n    if (is3d)\n      args = __add_datasource__ (\"quiver3\", hg,\n                                 {\"x\", \"y\", \"z\", \"u\", \"v\", \"w\"}, args{:});\n    else\n      args = __add_datasource__ (\"quiver\", hg,\n                                 {\"x\", \"y\", \"z\", \"u\", \"v\", \"w\"}, args{:});\n    endif\n\n    hold (hax, \"on\");\n\n    addproperty (\"xdata\", hg, \"data\", x);\n    addproperty (\"ydata\", hg, \"data\", y);\n\n    addproperty (\"udata\", hg, \"data\", u);\n    addproperty (\"vdata\", hg, \"data\", v);\n    if (is3d)\n      addproperty (\"zdata\", hg, \"data\", z);\n      addproperty (\"wdata\", hg, \"data\", w);\n    else\n      addproperty (\"zdata\", hg, \"data\", []);\n      addproperty (\"wdata\", hg, \"data\", []);\n    endif\n\n    addlistener (hg, \"xdata\", @update_data);\n    addlistener (hg, \"ydata\", @update_data);\n    addlistener (hg, \"zdata\", @update_data);\n    addlistener (hg, \"udata\", @update_data);\n    addlistener (hg, \"vdata\", @update_data);\n    addlistener (hg, \"wdata\", @update_data);\n\n    x = x(:);\n    y = y(:);\n    xend = x + uu(:);\n    yend = y + vv(:);\n    if (is3d)\n      z = z(:);\n      zend = z + ww(:);\n    endif\n\n    ## Draw arrow shaft as one line object\n    if (is3d)\n      h1 = plot3 (hax, [x.'; xend.'; NaN(1, length (x))](:),\n                       [y.'; yend.'; NaN(1, length (y))](:),\n                       [z.'; zend.'; NaN(1, length (z))](:),\n                       \"linestyle\", ls, \"color\", lc, \"parent\", hg);\n    else\n      h1 = plot (hax, [x.'; xend.'; NaN(1, length (x))](:),\n                      [y.'; yend.'; NaN(1, length (y))](:),\n                      \"linestyle\", ls, \"color\", lc, \"parent\", hg);\n    endif\n\n    xtmp = x + uu(:) * (1 - arrowsize);\n    ytmp = y + vv(:) * (1 - arrowsize);\n\n    if (is3d)\n      xydist = sqrt (uu(:).^2 + vv(:).^2 + ww(:).^2) ./ ...\n                 (sqrt (uu(:).^2 + vv(:).^2) + eps);\n      xarrw1 = xtmp + vv(:) .* xydist * arrowsize / 4;\n      xarrw2 = xtmp - vv(:) .* xydist * arrowsize / 4;\n      yarrw1 = ytmp - uu(:) .* xydist * arrowsize / 4;\n      yarrw2 = ytmp + uu(:) .* xydist * arrowsize / 4;\n      zarrw1 = zarrw2 = zend - ww(:) * arrowsize;\n    else\n      xarrw1 = xtmp + vv(:) * arrowsize / 3;\n      xarrw2 = xtmp - vv(:) * arrowsize / 3;\n      yarrw1 = ytmp - uu(:) * arrowsize / 3;\n      yarrw2 = ytmp + uu(:) * arrowsize / 3;\n    endif\n\n    ## Draw arrowhead as one line object\n\n    ## Arrowhead is constructed, but NOT displayed, when marker is present.\n    if (have_line_spec)\n      if (! isempty (linespec.marker) && ! strcmp (linespec.marker, \"none\"))\n        ls = \"none\";\n      endif\n    endif\n\n    if (is3d)\n      h2 = plot3 (hax, [xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),\n                       [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),\n                       [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),\n                       \"linestyle\", ls, \"color\", lc, \"parent\", hg);\n    else\n      h2 = plot (hax, [xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),\n                      [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),\n                      \"linestyle\", ls, \"color\", lc, \"parent\", hg);\n    endif\n\n    ## Draw arrow base marker as a third line object\n    if (! have_line_spec || isempty (linespec.marker))\n      mk = \"none\";\n    else\n      mk = linespec.marker;\n    endif\n    if (is3d)\n      h3 = plot3 (hax, x, y, z, \"linestyle\", \"none\", \"color\", lc, \"marker\", mk,\n                                \"parent\", hg);\n    else\n      h3 = plot (hax, x, y, \"linestyle\", \"none\", \"color\", lc, \"marker\", mk,\n                            \"parent\", hg);\n    endif\n    if (have_filled)\n      set (h3, \"markerfacecolor\", lc);\n    endif\n\n    ## Set up the hggroup properties and listeners\n    if (autoscale)\n      addproperty (\"autoscale\", hg, \"radio\", \"{on}|off\", \"on\");\n      addproperty (\"autoscalefactor\", hg, \"data\", autoscale);\n    else\n      addproperty (\"autoscale\", hg, \"radio\", \"{on}|off\", \"off\");\n      addproperty (\"autoscalefactor\", hg, \"data\", 1.0);\n    endif\n    addlistener (hg, \"autoscale\", @update_data);\n    addlistener (hg, \"autoscalefactor\", @update_data);\n\n    addproperty (\"maxheadsize\", hg, \"data\", arrowsize * .20*3);\n    addlistener (hg, \"maxheadsize\", @update_data);\n\n    addproperty (\"showarrowhead\", hg, \"radio\", \"{on}|off\", \"on\");\n    addlistener (hg, \"showarrowhead\", @update_props);\n\n    addproperty (\"color\", hg, \"linecolor\", get (h1, \"color\"));\n    addproperty (\"linestyle\", hg, \"linelinestyle\", get (h1, \"linestyle\"));\n    addproperty (\"linewidth\", hg, \"linelinewidth\", get (h1, \"linewidth\"));\n    addproperty (\"marker\", hg, \"linemarker\", get (h3, \"marker\"));\n    addproperty (\"markerfacecolor\", hg, \"linemarkerfacecolor\",\n                 get (h3, \"markerfacecolor\"));\n    addproperty (\"markersize\", hg, \"linemarkersize\", get (h3, \"markersize\"));\n\n    addlistener (hg, \"color\", @update_props);\n    addlistener (hg, \"linestyle\", @update_props);\n    addlistener (hg, \"linewidth\", @update_props);\n    addlistener (hg, \"marker\", @update_props);\n    addlistener (hg, \"markerfacecolor\", @update_props);\n    addlistener (hg, \"markersize\", @update_props);\n\n    ## Matlab property, although Octave does not implement it.\n    addproperty (\"hittestarea\", hg, \"radio\", \"on|{off}\", \"off\");\n\n    if (! isempty (args))\n      set (hg, args{:});\n      if (have_line_spec && ! isempty (linespec.marker) && ...\n            ! strcmp (linespec.marker, \"none\"))\n        set (h2, \"linestyle\", \"none\");\n      endif\n    endif\n\n  unwind_protect_cleanup\n    set (hax, \"nextplot\", hstate);\n  end_unwind_protect\n\nendfunction\n\nfunction update_data (h, ~)\n\n  x = get (h, \"xdata\");\n  y = get (h, \"ydata\");\n  z = get (h, \"zdata\");\n\n  u = get (h, \"udata\");\n  v = get (h, \"vdata\");\n  w = get (h, \"wdata\");\n\n  s = get (h, \"autoscalefactor\");\n  arrowsize = get (h, \"maxheadsize\");\n  arrowsize /= 0.20 * 3;\n\n  kids = get (h, \"children\");\n\n  if (isempty (z) || isempty (w))\n    is3d = false;\n  else\n    is3d = true;\n  endif\n\n  if (strcmp (get (h, \"autoscale\"), \"on\") && s != 0)\n    ## Scale the arrows to fit in the grid\n    if (isvector (x))\n      nx = ny = sqrt (length (x));\n    else\n      [ny, nx] = size (x);\n    endif\n    dx = (max (x(:)) - min (x(:))) / nx;\n    dy = (max (y(:)) - min (y(:))) / ny;\n    if (is3d)\n      dz = (max (z(:)) - min (z(:))) / max (nx, ny);\n      len = max (sqrt (u(:).^2 + v(:).^2 + w(:).^2));\n    else\n      dz = 0;\n      len = max (sqrt (u(:).^2 + v(:).^2));\n    endif\n    if (len > 0)\n      sd = sqrt (dx.^2 + dy.^2 + dz.^2) / len;\n      if (sd != 0)\n        s *= sd;\n      endif\n      u = s * u;\n      v = s * v;\n      if (is3d)\n        w = s * w;\n      endif\n    endif\n  endif\n\n  x = x(:);\n  y = y(:);\n  xend = x + u(:);\n  yend = y + v(:);\n  if (is3d)\n    z = z(:);\n    zend = z + w(:);\n  endif\n\n  set (kids(3), \"xdata\", [x.'; xend.'; NaN(1, length (x))](:),\n                \"ydata\", [y.'; yend.'; NaN(1, length (y))](:));\n  if (is3d)\n    set (kids(3), \"zdata\", [z.'; zend.'; NaN(1, length (z))](:));\n  endif\n\n  xtmp = x + u(:) * (1 - arrowsize);\n  ytmp = y + v(:) * (1 - arrowsize);\n\n  if (is3d)\n    xydist = sqrt (u(:).^2 + v(:).^2 + w(:).^2) ./ ...\n               (sqrt (u(:).^2 + v(:).^2) + eps);\n    xarrw1 = xtmp + v(:) .* xydist * arrowsize / 4;\n    xarrw2 = xtmp - v(:) .* xydist * arrowsize / 4;\n    yarrw1 = ytmp - u(:) .* xydist * arrowsize / 4;\n    yarrw2 = ytmp + u(:) .* xydist * arrowsize / 4;\n    zarrw1 = zarrw2 = zend - w(:) * arrowsize;\n  else\n    xarrw1 = xtmp + v(:) * arrowsize / 3;\n    xarrw2 = xtmp - v(:) * arrowsize / 3;\n    yarrw1 = ytmp - u(:) * arrowsize / 3;\n    yarrw2 = ytmp + u(:) * arrowsize / 3;\n  endif\n\n  set (kids(2), \"xdata\", [x.'; xend.'; NaN(1, length (x))](:),\n                \"ydata\", [y.'; yend.'; NaN(1, length (y))](:));\n  if (is3d)\n    set (kids(2), \"zdata\", [z.'; zend.'; NaN(1, length (z))](:));\n  endif\n\n  set (kids(2), \"xdata\", [xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),\n                \"ydata\", [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));\n  if (is3d)\n    set (kids(2), \"zdata\", [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:));\n  endif\n\n  set (kids(1), \"xdata\", x, \"ydata\", y);\n  if (is3d)\n    set (kids(1), \"zdata\", z);\n  endif\n\nendfunction\n\nfunction update_props (h, ~)\n\n  kids = get (h, \"children\");\n\n  set (kids([3 2]), {\"color\", \"linestyle\", \"linewidth\"},\n            get (h, {\"color\", \"linestyle\", \"linewidth\"}));\n  set (kids(2), \"visible\", get (h, \"showarrowhead\"));\n  set (kids(1), {\"color\", \"marker\", \"markerfacecolor\", \"markersize\", ...\n            \"linewidth\"}, get (h, {\"color\", \"marker\", \"markerfacecolor\", ...\n            \"markersize\", \"linewidth\"}));\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__scatter__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{hs} =} __scatter__ (@dots{})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction hs = __scatter__ (varargin)\n\n  hax = varargin{1};\n  nd  = varargin{2};\n  fcn = varargin{3};\n  x   = varargin{4}(:);\n  y   = varargin{5}(:);\n\n  if (nd == 2)\n    istart = 6;\n  else\n    z = varargin{6}(:);\n    istart = 7;\n  endif\n\n  ## Force mixtures of int and float data to be float (Bug #4116).\n  if (xor (isfloat (x), isfloat (y)))\n    if (isfloat (x))\n      y = cast (y, class (x));\n    else\n      x = cast (x, class (y));\n    endif\n  endif\n  if (nd != 2)\n    if (xor (isfloat (x), isfloat (z)))\n      if (isfloat (x))\n        z = cast (z, class (x));\n      else\n        x = cast (x, class (z));\n        y = cast (y, class (z));\n      endif\n    endif\n  endif\n\n  if (istart <= nargin)\n    s = varargin{istart}(:);\n    if (isempty (s) || ischar (s))\n      s = 36;\n    endif\n    if (! ischar (varargin{istart}))\n      istart += 1;\n    endif\n  else\n    s = 36;\n  endif\n\n  firstnonnumeric = find (! cellfun (\"isnumeric\", varargin(istart:nargin)), 1);\n  if (isempty (firstnonnumeric))\n    firstnonnumeric = Inf;\n  else\n    firstnonnumeric += istart - 1;\n  endif\n\n  if (istart <= nargin && firstnonnumeric > istart)\n    c = varargin{istart};\n    if (isvector (c) && columns (c) != 3)\n      c = c(:);\n    endif\n  elseif (firstnonnumeric == istart && ischar (varargin{istart})\n          && any (lower (varargin{istart}(1)) == \"ymcrgbwk\"))\n    [linespec, valid] = __pltopt__ (fcn, varargin{istart}, false);\n    if (valid)\n      c = varargin{istart};\n      firstnonnumeric += 1;\n    else\n      c = [];\n    endif\n  else\n    c = [];\n  endif\n\n  ## Remove NaNs\n  idx = isnan (x) | isnan (y) | isnan (s);\n  if (nd == 3)\n    idx |= isnan (z);\n    z(idx) = [];\n  endif\n  x(idx) = [];\n  y(idx) = [];\n  if (nd == 2)\n    z = zeros (numel (x), 0);\n  endif\n  if (numel (s) > 1)\n    s(idx) = [];\n  endif\n  if (rows (c) > 1)\n    c(idx,:) = [];\n  endif\n\n  ## Validate inputs\n  if (nd == 2 && ! size_equal (x, y))\n    error ([fcn \": X and Y must have the same size\"]);\n  elseif (nd == 3 && ! size_equal (x, y, z))\n    error ([fcn \": X, Y, and Z must have the same size\"]);\n  endif\n\n  if (! isscalar (s) && ! size_equal (x, s))\n    error ([fcn \": size of S must match X, Y, and Z\"]);\n  endif\n\n  if (rows (c) > 1 && rows (c) != rows (x))\n    error ([fcn \": number of colors in C must match number of points in X\"]);\n  endif\n\n  newargs = {};\n  filled = false;\n  have_marker = false;\n  marker = \"o\";\n  iarg = firstnonnumeric;\n  while (iarg <= nargin)\n    arg = varargin{iarg++};\n    if (ischar (arg) && (strcmpi (arg, \"filled\") || strcmpi (arg, \"fill\")))\n      filled = true;\n    elseif ((ischar (arg) || iscellstr (arg)) && ! have_marker)\n      [linespec, valid] = __pltopt__ (fcn, arg, false);\n      if (valid)\n        ## Valid linestyle, but possibly not valid marker\n        have_marker = true;\n        marker = linespec.marker;\n        if (strcmp (marker, \"none\"))\n          marker = \"o\";\n        elseif (isempty (marker))\n          have_marker = false;\n          marker = \"o\";\n        endif\n      else\n        ## Prop/Val pair\n        newargs{end+1} = arg;\n        if (iarg <= nargin)\n          newargs{end+1} = varargin{iarg++};\n        endif\n      endif\n    else\n      ## Prop/Val pair\n      newargs{end+1} = arg;\n      if (iarg <= nargin)\n        newargs{end+1} = varargin{iarg++};\n      endif\n    endif\n  endwhile\n\n  if (strcmp (\"gnuplot\", graphics_toolkit ()))\n    ## Legacy code using patch for gnuplot toolkit\n    hs = __gnuplot_scatter__ (hax, fcn, x, y, z, c, s, marker, filled, newargs);\n\n  else\n    ## Use OpenGL rendering for \"qt\" and \"fltk\" graphics toolkits\n    if (isempty (x))\n      c = x;\n    endif\n    if (ischar (c))\n      c = str2rgb (c);\n    endif\n    if (isempty (c))\n      cdata_args = {};\n    else\n      cdata_args = {\"cdata\", c};\n    endif\n    if (filled)\n      filled_args = {\"markeredgecolor\", \"none\", \"markerfacecolor\", \"flat\"};\n    else\n      filled_args = {};\n    endif\n\n    hs = __go_scatter__ (hax, \"xdata\", x(:), \"ydata\", y(:), \"zdata\", z(:),\n                         cdata_args{:}, \"sizedata\", s(:), \"marker\", marker,\n                         filled_args{:}, newargs{:});\n  endif\n\nendfunction\n\n## Convert a color code to the corresponding RGB values\nfunction rgb = str2rgb (str)\n\n  rgb = [];\n\n  switch (str)\n    case 'b'\n      rgb = [0, 0, 1];\n    case 'k'\n      rgb = [0, 0, 0];\n    case 'r'\n      rgb = [1, 0, 0];\n    case 'g'\n      rgb = [0, 1, 0];\n    case 'y'\n      rgb = [1, 1, 0];\n    case 'm'\n      rgb = [1, 0, 1];\n    case 'c'\n      rgb = [0, 1, 1];\n    case 'w'\n      rgb = [1, 1, 1];\n  endswitch\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__stem__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} __stem__ (@var{have_z}, @var{varargin})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction h = __stem__ (have_z, varargin)\n\n  if (have_z)\n    caller = \"stem3\";\n  else\n    caller = \"stem\";\n  endif\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (caller, varargin{:});\n\n  [x, y, z, dofill, llc, ls, mmc, ms, varargin] = ...\n                                           check_stem_arg (have_z, varargin{:});\n\n  hax = newplot (hax);\n  hold_state = get (hax, \"nextplot\");\n  set (hax, \"nextplot\", \"add\");\n\n  h = [];\n  nx = rows (x);\n  h_baseline = [];\n\n  for i = 1 : columns (x)\n    if (have_z)\n      xt = x(:)';\n      xt = [xt; xt; NaN(1, nx)](:);\n      yt = y(:)';\n      yt = [yt; yt; NaN(1, nx)](:);\n      zt = z(:)';\n      zt = [zeros(1, nx); zt; NaN(1, nx)](:);\n    else\n      xt = x(:, i)';\n      xt = [xt; xt; NaN(1, nx)](:);\n      yt = y(:, i)';\n      yt = [zeros(1, nx); yt; NaN(1, nx)](:);\n    endif\n\n    if (isempty (llc))\n      lc = __next_line_color__ (hax);\n    else\n      lc = llc;\n    endif\n\n    if (isempty (mmc))\n      mc = lc;\n    else\n      mc = mmc;\n    endif\n\n    if (dofill)\n      fc = mc;\n    else\n      fc = \"none\";\n    endif\n\n    ## Must occur after __next_line_color__ in order to work correctly.\n    hg = hggroup (hax, \"__appdata__\", struct (\"__creator__\", \"__stem__\"));\n    h = [h; hg];\n    args = __add_datasource__ (caller, hg, {\"x\", \"y\", \"z\"}, varargin{:});\n\n    if (have_z)\n      __line__ (hax, xt, yt, zt, \"color\", lc, \"linestyle\", ls, \"parent\", hg);\n      __line__ (hax, x, y, z, \"color\", mc, \"linestyle\", \"none\",\n                     \"marker\", ms, \"markerfacecolor\", fc, \"parent\", hg);\n    else\n      __line__ (hax, xt, yt, \"color\", lc, \"linestyle\", ls, \"parent\", hg);\n      __line__ (hax, x(:,i), y(:, i), \"color\", mc, \"linestyle\", \"none\",\n                     \"marker\", ms, \"markerfacecolor\", fc, \"parent\", hg);\n\n      x_axis_range = get (hax, \"xlim\");\n      if (isempty (h_baseline))\n        h_baseline = __go_line__ (hax, \"xdata\", x_axis_range,\n                                       \"ydata\", [0, 0],\n                                       \"color\", [0, 0, 0]);\n        set (h_baseline, \"handlevisibility\", \"off\", \"xliminclude\", \"off\");\n        addproperty (\"basevalue\", h_baseline, \"data\", 0);\n      else\n        set (h_baseline, \"xdata\", x_axis_range);\n      endif\n    endif\n\n    ## Setup the hggroup and listeners.\n    addproperty (\"showbaseline\", hg, \"radio\", \"{on}|off\");\n    addproperty (\"baseline\", hg, \"data\", h_baseline);\n    addproperty (\"basevalue\", hg, \"data\", 0);\n\n    addproperty (\"color\", hg, \"linecolor\", lc);\n    addproperty (\"linestyle\", hg, \"linelinestyle\", ls);\n    addproperty (\"linewidth\", hg, \"linelinewidth\", 0.5);\n    addproperty (\"marker\", hg, \"linemarker\", ms);\n    addproperty (\"markeredgecolor\", hg, \"linemarkerfacecolor\", mc);\n    addproperty (\"markerfacecolor\", hg, \"linemarkerfacecolor\", fc);\n    addproperty (\"markersize\", hg, \"linemarkersize\", 6);\n\n    addlistener (hg, \"color\", @update_props);\n    addlistener (hg, \"linestyle\", @update_props);\n    addlistener (hg, \"linewidth\", @update_props);\n    addlistener (hg, \"marker\", @update_props);\n    addlistener (hg, \"markeredgecolor\", @update_props);\n    addlistener (hg, \"markerfacecolor\", @update_props);\n    addlistener (hg, \"markersize\", @update_props);\n\n    if (islogical (x))\n      x = double (x);\n    endif\n    addproperty (\"xdata\", hg, \"data\", x(:, i));\n    if (islogical (y))\n      y = double (y);\n    endif\n    addproperty (\"ydata\", hg, \"data\", y(:, i));\n    if (have_z)\n      addproperty (\"zdata\", hg, \"data\", z(:, i));\n    else\n      addproperty (\"zdata\", hg, \"data\", []);\n    endif\n\n    addlistener (hg, \"xdata\", @update_data);\n    addlistener (hg, \"ydata\", @update_data);\n    addlistener (hg, \"zdata\", @update_data);\n\n    ## Matlab property, although Octave does not implement it.\n    addproperty (\"hittestarea\", hg, \"radio\", \"on|{off}\", \"off\");\n\n  endfor\n\n  ## baseline listeners\n  if (! isempty (h_baseline))\n    fcn_handle = @update_xlim;\n    addlistener (hax, \"xlim\", fcn_handle);\n    set (h_baseline, \"deletefcn\", {@rm_xlim_listener, hax, fcn_handle});\n\n    for hg = h'\n      addlistener (hg, \"showbaseline\", @show_baseline);\n      addlistener (hg, \"visible\", {@show_baseline, h});\n      addlistener (hg, \"basevalue\", @move_baseline);\n    endfor\n\n    addlistener (h_baseline, \"basevalue\", {@update_baseline, 0});\n    addlistener (h_baseline, \"ydata\", {@update_baseline, 1});\n    addlistener (h_baseline, \"visible\", {@update_baseline, 2});\n    set (h_baseline, \"parent\", get (hg(1), \"parent\"));\n  endif\n\n  ## property/value pairs\n  if (! isempty (args))\n      set (h, args{:});\n  endif\n\n  if (! strcmp (hold_state, \"add\"))\n    if (! have_z)\n      set (hax, \"box\", \"on\");\n    else\n      set (hax, \"view\", [-37.5 30],\n                \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n    endif\n  endif\n  set (hax, \"nextplot\", hold_state);\n\nendfunction\n\nfunction [x, y, z, dofill, lc, ls, mc, ms, args] = check_stem_arg (have_z, varargin)\n\n  if (have_z)\n    caller = \"stem3\";\n  else\n    caller = \"stem\";\n  endif\n  nargin = nargin () - 1;  # account for have_z argument\n\n  num_numeric = find (cellfun (\"isclass\", varargin, \"char\"), 1) - 1;\n  if (isempty (num_numeric))\n    num_numeric = nargin;\n  endif\n\n  if (num_numeric < 1 || num_numeric > 3)\n    print_usage (caller);\n  endif\n\n  x = y = z = [];\n  if (num_numeric == 1)\n    if (have_z)\n      z = varargin{1};\n    else\n      y = varargin{1};\n    endif\n  elseif (num_numeric == 2)\n    if (have_z)\n      error (\"stem3: must define X, Y, and Z\");\n    else\n      x = varargin{1};\n      y = varargin{2};\n    endif\n  else  # nun_numeric == 3\n    if (have_z)\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n    else\n      error (\"stem: can not define Z for 2-D stem plot\");\n    endif\n  endif\n\n  ## Validate numeric data\n  if (have_z)\n    if (isempty (x))\n      [nr, nc] = size (z);\n      if (nr >= nc)\n        x = repmat ([1:nc], nr, 1);\n        y = repmat ([1:nr]', 1, nc);\n      else\n        x = repmat ([1:nc], nr, 1);\n        y = repmat ([1:nr]', 1, nc);\n      endif\n    endif\n    if (! (isnumeric (x) || islogical (x))\n        || ! (isnumeric (y) || islogical (y))\n        || ! (isnumeric (z) || islogical (z)))\n      error (\"stem3: X, Y, and Z must be numeric\");\n    endif\n  else\n    if (isempty (x))\n      if (isvector (y))\n        x = 1:length (y);\n      elseif (ismatrix (y))\n        x = 1:rows (y);\n      else\n        error (\"stem: Y must be a vector or 2-D array\");\n      endif\n    endif\n    if (! (isnumeric (x) || islogical (x))\n        || ! (isnumeric (y) || islogical (y)))\n      error (\"stem: X and Y must be numeric\");\n    endif\n  endif\n\n  ## Check sizes of x, y and z.\n  if (have_z)\n    if (! size_equal (x, y, z))\n      error (\"stem3: inconsistent sizes for X, Y, and Z\");\n    endif\n    x = x(:);\n    y = y(:);\n    z = z(:);\n  else\n    if (isvector (x))\n      x = x(:);\n      if (isvector (y))\n        if (length (x) != length (y))\n          error (\"stem: inconsistent sizes for X and Y\");\n        endif\n        y = y(:);\n      else\n        if (length (x) == rows (y))\n          x = repmat (x(:), 1, columns (y));\n        else\n          error (\"stem: inconsistent sizes for X and Y\");\n        endif\n      endif\n    elseif (! size_equal (x, y))\n      error (\"stem: inconsistent sizes for X and Y\");\n    endif\n  endif\n\n  dofill = false;\n  have_line_spec = false;\n  ## set specifiers to default values.\n  [lc, ls, mc, ms] = set_default_values ();\n\n  args = {};\n  ioff = num_numeric + 1;\n  while (ioff <= nargin)\n    arg = varargin{ioff++};\n    if (ischar (arg) && any (strcmpi (arg, {\"fill\", \"filled\"})))\n      dofill = true;\n    elseif ((ischar (arg) || iscellstr (arg)) && ! have_line_spec)\n      [linespec, valid] = __pltopt__ (caller, arg, false);\n      if (valid)\n        have_line_spec = true;\n        [lc, ls, mc, ms] = stem_line_spec (linespec);\n      else\n        args{end+1} = arg;\n        if (ioff > nargin)\n          error ('%s: No value specified for property \"%s\"', caller, arg);\n        endif\n        args{end+1} = varargin{ioff++};\n      endif\n    else\n      args{end+1} = arg;\n      if (ioff > nargin)\n        error ('%s: No value specified for property \"%s\"', caller, arg);\n      endif\n      args{end+1} = varargin{ioff++};\n    endif\n  endwhile\n\nendfunction\n\nfunction [lc, ls, mc, ms] = stem_line_spec (lspec)\n\n  [lc, ls, mc, ms] = set_default_values ();\n\n  if (! isempty (lspec.color))\n    lc = mc = lspec.color;\n  endif\n\n  if (! isempty (lspec.linestyle) && ! strcmp (lspec.linestyle, \"none\"))\n    ls = lspec.linestyle;\n  endif\n\n  if (! isempty (lspec.marker) && ! strcmp (lspec.marker, \"none\"))\n    ms = lspec.marker;\n  endif\n\nendfunction\n\nfunction [lc, ls, mc, ms] = set_default_values ()\n  mc = [];\n  lc = [];\n  ls = \"-\";\n  ms = \"o\";\nendfunction\n\nfunction update_xlim (h, ~)\n\n  kids = get (h, \"children\");\n  xlim = get (h, \"xlim\");\n\n  for i = 1 : length (kids)\n    obj = get (kids(i));\n    if (strcmp (obj.type, \"hggroup\") && isfield (obj, \"baseline\"))\n      if (any (get (obj.baseline, \"xdata\") != xlim))\n        set (obj.baseline, \"xdata\", xlim);\n      endif\n    endif\n  endfor\n\nendfunction\n\n## Good practice to remove listeners when object is deleted.\n## In this case, required to avoid error in update_xlim callback (bug #57391).\nfunction rm_xlim_listener (~, ~, hax, fcn_handle)\n  dellistener (hax, \"xlim\", fcn_handle);\nendfunction\n\nfunction update_baseline (h, ~, src)\n\n  visible = get (h, \"visible\");\n  if (src == 0)\n    basevalue = get (h, \"basevalue\");\n  else\n    basevalue = get (h, \"ydata\")(1);\n  endif\n\n  kids = get (get (h, \"parent\"), \"children\");\n  for i = 1 : length (kids)\n    obj = get (kids(i));\n    if (strcmp (obj.type, \"hggroup\") && isfield (obj, \"baseline\")\n        && obj.baseline == h)\n      ## Avoid lots of unnecessary listener updates\n      if (! strcmp (get (kids(i), \"showbaseline\"), visible))\n        set (kids(i), \"showbaseline\", visible);\n      endif\n      if (get (kids(i), \"basevalue\") != basevalue)\n        set (kids(i), \"basevalue\", basevalue);\n      endif\n    endif\n  endfor\n\nendfunction\n\nfunction show_baseline (h, ~, hg = [])\n\n  if (isempty (hg))\n    set (get (h, \"baseline\"), \"visible\", get (h, \"showbaseline\"));\n  else\n    if (all (strcmp (get (hg, \"visible\"), \"off\")))\n      set (get (h, \"baseline\"), \"visible\", \"off\");\n    else\n      set (get (h, \"baseline\"), \"visible\", \"on\");\n    endif\n  endif\n\nendfunction\n\nfunction move_baseline (h, ~)\n\n  b0 = get (h, \"basevalue\");\n  bl = get (h, \"baseline\");\n\n  set (bl, \"ydata\", [b0, b0], \"basevalue\", b0);\n\n  kids = get (h, \"children\");\n  yt = get (h, \"ydata\")(:)';\n  ny = length (yt);\n  yt = [b0 * ones(1, ny); yt; NaN(1, ny)](:);\n  set (kids(2), \"ydata\", yt);\n\nendfunction\n\nfunction update_props (h, ~)\n\n  kids = get (h, \"children\");\n  set (kids(2), \"color\", get (h, \"color\"),\n                \"linestyle\", get (h, \"linestyle\"),\n                \"linewidth\", get (h, \"linewidth\"));\n  set (kids(1), \"color\", get (h, \"markeredgecolor\"),\n                \"marker\", get (h, \"marker\"),\n                \"markerfacecolor\", get (h, \"markerfacecolor\"),\n                \"markersize\", get (h, \"markersize\"));\n\nendfunction\n\nfunction update_data (h, ~)\n\n  x = get (h, \"xdata\");\n  y = get (h, \"ydata\");\n  z = get (h, \"zdata\");\n\n  if (! isempty (z) && size_equal (x, y, z))\n    sz = min ([size(x); size(y); size(z)]);\n    x = x(1:sz(1),1:sz(2));\n    y = y(1:sz(1),1:sz(2));\n    z = z(1:sz(1),1:sz(2));\n  elseif (numel (x) != numel (y))\n    sz = min ([size(x); size(y)]);\n    x = x(1:sz(1),1:sz(2));\n    y = y(1:sz(1),1:sz(2));\n  endif\n  bl = get (h, \"basevalue\");\n  nx = numel (x);\n  x = x(:)';\n  xt = [x; x; NaN(1, nx)](:);\n  if (! isempty (z))\n    y = y(:)';\n    yt = [y; y; NaN(1, nx)](:);\n    z = z(:)';\n    zt = [bl * ones(1, nx); z; NaN(1, nx)](:);\n  else\n    y = y(:)';\n    yt = [bl * ones(1, nx); y; NaN(1, nx)](:);\n    zt = [];\n  endif\n\n  kids = get (h, \"children\");\n  set (kids(2), \"xdata\", xt, \"ydata\", yt, \"zdata\", zt);\n  set (kids(1), \"xdata\", x, \"ydata\", y, \"zdata\", z);\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/private/__unite_shared_vertices__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{faces}, @var{vertices}, @var{J}] =} __unite_shared_vertices__ (@var{faces}, @var{vertices})\n##\n## Detect and unite shared vertices in patches.\n##\n## Vertices of neighboring faces are detected and united to shared vertices.\n## For this, the mutual squared distances between all vertices are\n## calculated.  If all coordinates are closer than\n## @code{2 * eps (max (abs (vertices(:))))}, the vertices are united to one.\n##\n## @var{J} holds the indices of the remaining vertices.\n##\n## @seealso{isosurface, reducepatch}\n## @end deftypefn\n\nfunction [faces, vertices, J] = __unite_shared_vertices__ (faces, vertices)\n\n  nan_vertices = any (isnan (vertices), 2);\n  lut = (1:rows (vertices))';\n  J = lut;\n  for di = 1:3\n    [v, idx] = sortrows (vertices, 1 + mod ((0:2)+di, 3));\n    Js = [true;\n          any(abs (diff (v, 1, 1)) > eps * abs (v(2:end,:)+v(1:end-1,:)), 2)];\n    vertices = v(Js,:);\n    J = J(idx(Js));\n    l(idx) = cumsum (Js);\n    lut = l(lut);\n  endfor\n  [J, idx] = sort (J);\n  j(idx) = 1:length (idx);\n  vertices = vertices(idx,:);\n  if (any (nan_vertices))\n    j(end+1) = length (idx) + 1;\n    vertices(end+1,:) = NaN;\n    lut(nan_vertices) = rows (vertices);\n  endif\n  faces = j(lut(faces));\n\n  ## Eliminate faces with zero area\n  faces = faces(all (faces - faces(:, [2 3 1]) != 0, 2), :);\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/draw/quiver.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} quiver (@var{u}, @var{v})\n## @deftypefnx {} {} quiver (@var{x}, @var{y}, @var{u}, @var{v})\n## @deftypefnx {} {} quiver (@dots{}, @var{s})\n## @deftypefnx {} {} quiver (@dots{}, @var{style})\n## @deftypefnx {} {} quiver (@dots{}, \"filled\")\n## @deftypefnx {} {} quiver (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} quiver (@dots{})\n##\n## Plot a 2-D vector field with arrows.\n##\n## Plot the (@var{u}, @var{v}) components of a vector field at the grid points\n## defined by (@var{x}, @var{y}).  If the grid is uniform then @var{x} and\n## @var{y} can be specified as grid vectors and @code{meshgrid} is used to\n## create the 2-D grid.\n##\n## If @var{x} and @var{y} are not given they are assumed to be\n## @code{(1:@var{m}, 1:@var{n})} where\n## @code{[@var{m}, @var{n}] = size (@var{u})}.\n##\n## The optional input @var{s} is a scalar defining a scaling factor to use for\n## the arrows of the field relative to the mesh spacing.  A value of 1.0 will\n## result in the longest vector exactly filling one grid square.  A value of 0\n## or @qcode{\"off\"} disables all scaling.  The default value is 0.9.\n##\n## The style to use for the plot can be defined with a line style, @var{style},\n## of the same format as the @code{plot} command.  If a marker is specified\n## then the markers are drawn at the origin of the vectors (which are the grid\n## points defined by @var{x} and @var{y}).  When a marker is specified, the\n## arrowhead is not drawn.  If the argument @qcode{\"filled\"} is given then the\n## markers are filled.  If name-value plot style properties are used, they must\n## appear in pairs and follow any other plot style arguments.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to a quiver object.\n## A quiver object regroups the components of the quiver plot (body, arrow,\n## and marker), and allows them to be changed together.\n##\n## Example:\n##\n## @example\n## @group\n## [x, y] = meshgrid (1:2:20);\n## h = quiver (x, y, sin (2*pi*x/10), sin (2*pi*y/10));\n## set (h, \"maxheadsize\", 0.33);\n## @end group\n## @end example\n##\n## @seealso{quiver3, compass, feather, plot}\n## @end deftypefn\n\nfunction h = quiver (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"quiver\", varargin{:});\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  [hax, htmp] = __quiver__ (hax, false, varargin{:});\n\n  ## FIXME: This should be moved into __quiver__ when problem with\n  ##        re-initialization of title object is fixed.\n  if (! ishold (hax))\n    set (hax, \"box\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x,y] = meshgrid (1:2:20);\n%! h = quiver (x,y, sin (2*pi*x/10), sin (2*pi*y/10));\n%! title (\"quiver() plot w/arrowheads (default)\");\n\n%!demo\n%! clf;\n%! [x,y] = meshgrid (1:2:20);\n%! h = quiver (x,y, sin (2*pi*x/10), sin (2*pi*y/10), \"o\");\n%! title (\"quiver() plot w/origin markers\");\n\n%!demo\n%! clf;\n%! [x,y] = meshgrid (1:2:20);\n%! h = quiver (x,y, sin (2*pi*x/10), sin (2*pi*y/10));\n%! set (h, \"marker\", \"o\");\n%! title (\"quiver() plot w/origin markers and arrowheads\");\n\n%!demo\n%! clf;\n%! x = linspace (0, 3, 80);\n%! y = sin (2*pi*x);\n%! theta = 2*pi*x + pi/2;\n%! quiver (x, y, sin (theta)/10, cos (theta)/10, 0.4);\n%! axis equal tight;\n%! hold on; plot (x,y,\"r\"); hold off;\n%! title (\"quiver() with scaled arrows\");\n\n## Check standard inputs, single arrow.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = quiver (hax, 1, 2);\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{stemchild}(1), 1, eps);\n%!   assert (childxdata{stemchild}(2), 1 + 1*0.9, eps);\n%!   assert (isnan (childxdata{stemchild}(3)));\n%!   assert (childxdata{arrowheadchild}(2), 1 + 1*0.9, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(4)));\n%!\n%!   h = quiver (hax, 1, 2, 0.5);\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{stemchild}(1), 1, eps);\n%!   assert (childxdata{stemchild}(2), 1 + 1*0.5, eps);\n%!   assert (isnan (childxdata{stemchild}(3)));\n%!   assert (childxdata{arrowheadchild}(2), 1 + 1*0.5, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(4)));\n%!\n%!   h = quiver (hax, 0, 1, 2, 3);\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{stemchild}(1), 0, eps);\n%!   assert (childxdata{stemchild}(2), 0 + 2*0.9, eps);\n%!   assert (isnan (childxdata{stemchild}(3)));\n%!   assert (childxdata{arrowheadchild}(2), 0 + 2*0.9, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(4)));\n%!\n%!   h = quiver (hax, 0, 1, 2, 3, 0.5);\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{stemchild}(1), 0, eps);\n%!   assert (childxdata{stemchild}(2), 0 + 2*0.5, eps);\n%!   assert (isnan (childxdata{stemchild}(3)));\n%!   assert (childxdata{arrowheadchild}(2), 0 + 2*0.5, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(4)));\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check arrowhead size\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = quiver (hax, 0, 0, 0, 1, 1); # up\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{arrowheadchild}, [1/9 0 -1/9 NaN], eps);\n%!   assert (childydata{arrowheadchild}, [2/3 1 2/3 NaN], eps);\n%!\n%!   h = quiver (hax, 0, 0, 0, -1, 1); # down\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{arrowheadchild}, [-1/9 0 1/9 NaN], eps);\n%!   assert (childydata{arrowheadchild}, [-2/3 -1 -2/3 NaN], eps);\n%!\n%!   h = quiver (hax, 0, 0, -1, 0, 1); # left\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{arrowheadchild}, [-2/3 -1 -2/3 NaN], eps);\n%!   assert (childydata{arrowheadchild}, [1/9 0 -1/9 NaN], eps);\n%!\n%!   h = quiver (hax, 0, 0, 1, 0, 1); # right\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{arrowheadchild}, [2/3 1 2/3 NaN], eps);\n%!   assert (childydata{arrowheadchild}, [-1/9 0 1/9 NaN], eps);\n%!\n%!   h = quiver (hax, 0, 0, 1, 1, 1); # 45 deg - symmetric\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{arrowheadchild}, [7/9 1 5/9 NaN], eps);\n%!   assert (childydata{arrowheadchild}, [5/9 1 7/9 NaN], eps);\n%!\n%!   h = quiver (hax, 0, 0, sqrt (3), 1, 1); # 30 deg\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{arrowheadchild}, [(6*sqrt(3)+1)/9, sqrt(3), (6*sqrt(3)-1)/9, NaN], eps);\n%!   assert (childydata{arrowheadchild}, [(6-sqrt(3))/9, 1, (6+sqrt(3))/9, NaN], eps);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check standard inputs, multiple arrows.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   [x,y] = meshgrid (0:1);\n%!   u = [0 1; 1 -2];\n%!   v = [1 0; 1 -2];\n%!   numpts = 4;\n%!   h = quiver (hax, u, v, 1);  # assumes [x,y] = meshgrid (1:2)\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   basechild = find (cellfun ('numel', childxdata) == 1*numpts);\n%!   stemchild = find (cellfun ('numel', childxdata) == 3*numpts);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4*numpts);\n%!   assert (childxdata{basechild}, [1 1 2 2]);\n%!   assert (childxdata{stemchild}, [1,1,NaN,1,1.25,NaN,2,2.25,NaN,2,1.5,NaN], eps);\n%!   assert (childxdata{arrowheadchild}([2, 6, 10, 14]), [1, 1.25, 2.25, 1.5], eps);\n%!   assert (childxdata{arrowheadchild}([4, 8, 12, 16]), NaN(1,4), eps);\n%!\n%!   h = quiver (hax, x, y, u, v, 1);\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   basechild = find (cellfun ('numel', childxdata) == 1*numpts);\n%!   stemchild = find (cellfun ('numel', childxdata) == 3*numpts);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4*numpts);\n%!   assert (childxdata{basechild}, [0 0 1 1]);\n%!   assert (childxdata{stemchild}, [0,0,NaN,0,0.25,NaN,1,1.25,NaN,1,0.5,NaN], eps);\n%!   assert (childxdata{arrowheadchild}([2, 6, 10, 14]), [0, 0.25, 1.25, 0.5], eps);\n%!   assert (childxdata{arrowheadchild}([4, 8, 12, 16]), NaN(1,4), eps);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check multiple arrows, vector inputs identical to array inputs.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   [x,y] = meshgrid (0:1);\n%!   u = [0 1; 1 -2];\n%!   v = [1 0; 1 -2];\n%!   h = quiver (hax, x, y, u, v, 1);  # arrayinput\n%!   haxarray = get (hax);\n%!   haxarray.children = [];\n%!   haxarray.xlabel = [];\n%!   haxarray.ylabel = [];\n%!   haxarray.zlabel = [];\n%!   haxarray.title = [];\n%!   parentarray = get (h);\n%!   parentarray.children = [];\n%!   childrenarray = get (get (h, \"children\"));\n%!   [childrenarray.parent] = deal ([]);\n%!   h = quiver (hax, [0:1], [0:1], u, v, 1);\n%!   haxvect1 = get (hax);\n%!   haxvect1.children = [];\n%!   haxvect1.xlabel= [];\n%!   haxvect1.ylabel= [];\n%!   haxvect1.zlabel= [];\n%!   haxvect1.title= [];\n%!   parentvect1 = get (h);\n%!   parentvect1.children = [];\n%!   childrenvect1 = get (get (h, \"children\"));\n%!   [childrenvect1.parent] = deal ([]);\n%!   assert (isequaln (haxarray, haxvect1));\n%!   assert (isequaln (parentarray, parentvect1));\n%!   assert (isequaln (childrenarray, childrenvect1));\n%!   h = quiver (hax, [0:1], [0:1]', u, v, 1);\n%!   haxvect2 = get (hax);\n%!   haxvect2.children = [];\n%!   haxvect2.xlabel= [];\n%!   haxvect2.ylabel= [];\n%!   haxvect2.zlabel= [];\n%!   haxvect2.title= [];\n%!   parentvect2 = get (h);\n%!   parentvect2.children = [];\n%!   childrenvect2 = get (get (h, \"children\"));\n%!   [childrenvect2.parent] = deal ([]);\n%!   assert (isequaln (haxvect1, haxvect2));\n%!   assert (isequaln (parentvect1, parentvect2));\n%!   assert (isequaln (childrenvect1, childrenvect2));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check scale factor \"off\" is identical to scale factor = 0.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = quiver (hax, 1, 2, 0);\n%!   haxzero = get (hax);\n%!   haxzero.children = [];\n%!   haxzero.xlabel = [];\n%!   haxzero.ylabel = [];\n%!   haxzero.zlabel = [];\n%!   haxzero.title = [];\n%!   parentzero = get (h);\n%!   parentzero.children = [];\n%!   childrenzero = get (get (h, \"children\"));\n%!   [childrenzero.parent] = deal ([]);\n%!   h = quiver (hax, 1, 2, \"off\");\n%!   haxoff = get(hax);\n%!   haxoff.children = [];\n%!   haxoff.xlabel= [];\n%!   haxoff.ylabel= [];\n%!   haxoff.zlabel= [];\n%!   haxoff.title= [];\n%!   parentoff = get(h);\n%!   parentoff.children = [];\n%!   childrenoff = get (get (h, \"children\"));\n%!   [childrenoff.parent] = deal ([]);\n%!   assert (isequaln (haxzero, haxoff));\n%!   assert (isequaln (parentzero, parentoff));\n%!   assert (isequaln (childrenzero, childrenoff));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check input styles.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = quiver (hax, 0, 1, 2, 3, \"-o\"); # Linestyle\n%!   parent = get (h);\n%!   assert (parent.marker, \"o\");\n%!   assert (parent.markerfacecolor, \"none\");\n%!   childdata = get (parent.children);\n%!   basechild = find (cellfun ('numel', {childdata.xdata}) == 1);\n%!   arrowheadchild = find (cellfun ('numel', {childdata.xdata}) == 4);\n%!   assert (childdata(basechild).marker, \"o\");\n%!   assert (childdata(basechild).markerfacecolor, \"none\");\n%!   assert (childdata(basechild).linestyle, \"none\");\n%!   assert (childdata(arrowheadchild).marker, \"none\");\n%!   assert (childdata(arrowheadchild).markerfacecolor, \"none\");\n%!   assert (childdata(arrowheadchild).linestyle, \"none\");\n%!\n%!   h = quiver (hax, 0, 1, 2, 3, \"-o\", \"filled\");  # Linestyle + filled.\n%!   parent = get (h);\n%!   assert (parent.marker, \"o\");\n%!   assert (numel (parent.markerfacecolor), 3);\n%!   childdata = get (parent.children);\n%!   basechild = find (cellfun ('numel', {childdata.xdata}) == 1);\n%!   arrowheadchild = find (cellfun ('numel', {childdata.xdata}) == 4);\n%!   assert (childdata(basechild).marker, \"o\");\n%!   assert (numel (childdata(basechild).markerfacecolor), 3);\n%!   assert (childdata(basechild).linestyle, \"none\");\n%!   assert (childdata(arrowheadchild).marker, \"none\");\n%!   assert (childdata(arrowheadchild).markerfacecolor, \"none\");\n%!   assert (childdata(arrowheadchild).linestyle, \"none\");\n%!\n%!   h = quiver (hax, 0, 1, 2, 3, \"linewidth\", 10); # Name/value pair.\n%!   parent = get (h);\n%!   assert (parent.marker, \"none\");\n%!   assert (parent.markerfacecolor, \"none\");\n%!   assert (parent.linestyle, \"-\");\n%!   assert (parent.linewidth, 10);\n%!   childdata = get (parent.children);\n%!   basechild = find (cellfun ('numel', {childdata.xdata}) == 1);\n%!   stemchild = find (cellfun ('numel', {childdata.xdata}) == 3);\n%!   arrowheadchild = find (cellfun ('numel', {childdata.xdata}) == 4);\n%!   assert (childdata(basechild).marker, \"none\");\n%!   assert (childdata(basechild).markerfacecolor, \"none\");\n%!   assert (childdata(basechild).linestyle, \"none\");\n%!   assert (childdata(stemchild).marker, \"none\");\n%!   assert (childdata(stemchild).markerfacecolor, \"none\");\n%!   assert (childdata(stemchild).linestyle, \"-\");\n%!   assert (childdata(stemchild).linewidth, 10);\n%!   assert (childdata(arrowheadchild).marker, \"none\");\n%!   assert (childdata(arrowheadchild).markerfacecolor, \"none\");\n%!   assert (childdata(arrowheadchild).linestyle, \"-\");\n%!   assert (childdata(arrowheadchild).linewidth, 10);\n%!\n%!  unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test both Linestyle with marker + name/value pair suppress arrowhead\n%!test <*64143>\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = quiver (hax, 0, 1, 2, 3, \"-o\", \"linewidth\", 10);\n%!   parent = get (h);\n%!   assert (parent.marker, \"o\");\n%!   assert (parent.markerfacecolor, \"none\");\n%!   assert (parent.linestyle, \"-\");\n%!   assert (parent.linewidth, 10);\n%!   childdata = get (parent.children);\n%!   basechild = find (cellfun ('numel', {childdata.xdata}) == 1);\n%!   stemchild = find (cellfun ('numel', {childdata.xdata}) == 3);\n%!   arrowheadchild = find (cellfun ('numel', {childdata.xdata}) == 4);\n%!   assert (childdata(basechild).marker, \"o\");\n%!   assert (childdata(basechild).markerfacecolor, \"none\");\n%!   assert (childdata(basechild).linestyle, \"none\");\n%!   assert (childdata(stemchild).marker, \"none\");\n%!   assert (childdata(stemchild).markerfacecolor, \"none\");\n%!   assert (childdata(stemchild).linestyle, \"-\");\n%!   assert (childdata(stemchild).linewidth, 10);\n%!   assert (childdata(arrowheadchild).marker, \"none\");\n%!   assert (childdata(arrowheadchild).markerfacecolor, \"none\");\n%!   assert (childdata(arrowheadchild).linestyle, \"none\");\n%!   assert (childdata(arrowheadchild).linewidth, 10);\n%!\n%!  unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test that linewidth and color but not linestyle are passed to base marker\n%!test <*64143>\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca();\n%! unwind_protect\n%!   h = quiver (hax, 0, 1, 2, 3, \"--o\", \"linewidth\", 10, \"color\", [1 0 0]);\n%!   parent = get (h);\n%!   assert (parent.marker, \"o\");\n%!   assert (parent.markerfacecolor, \"none\");\n%!   assert (parent.linestyle, \"--\");\n%!   assert (parent.linewidth, 10);\n%!   childdata = get (parent.children);\n%!   basechild = find (cellfun ('numel', {childdata.xdata}) == 1);\n%!   stemchild = find (cellfun ('numel', {childdata.xdata}) == 3);\n%!   arrowheadchild = find (cellfun ('numel', {childdata.xdata}) == 4);\n%!   assert (childdata(basechild).marker, \"o\");\n%!   assert (childdata(basechild).markerfacecolor, \"none\");\n%!   assert (childdata(basechild).linestyle, \"none\");\n%!   assert (childdata(basechild).color, [1 0 0]);\n%!   assert (childdata(basechild).linewidth, 10);\n%!   assert (childdata(stemchild).marker, \"none\");\n%!   assert (childdata(stemchild).markerfacecolor, \"none\");\n%!   assert (childdata(stemchild).linestyle, \"--\");\n%!   assert (childdata(stemchild).linewidth, 10);\n%!   assert (childdata(stemchild).color, [1 0 0]);\n%!   assert (childdata(arrowheadchild).marker, \"none\");\n%!   assert (childdata(arrowheadchild).markerfacecolor, \"none\");\n%!   assert (childdata(arrowheadchild).linestyle, \"none\");\n%!   assert (childdata(arrowheadchild).linewidth, 10);\n%!   assert (childdata(arrowheadchild).color, [1 0 0]);\n%!\n%!  unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check arrow length, scale factor adjustment, one arrow.\n%!test <*39552>\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   [x,y] = meshgrid (1:2);\n%!   u = [0 1; 2 3];\n%!   v = [1 2; 3 4];\n%!   numpts = numel (x);\n%!   sf = 0.5;\n%!\n%!   ## Check single arrow.\n%!   h = quiver (hax, x(4), y(4), u(4), v(4), 1);\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3);\n%!   xendpoint = childxdata{stemchild}(2);\n%!   assert (xendpoint, x(4) + u(4), eps);\n%!\n%!   h = quiver (hax, x(4), y(4), u(4), v(4), sf);\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3);\n%!   xendpoint = childxdata{stemchild}(2);\n%!   assert (xendpoint, x(4) + sf*u(4), eps);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check arrow length, scale factor adjustment, multiple arrows.\n%!test <*39552>\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   [x,y] = meshgrid (1:2);\n%!   u = [0 1; 2 3];\n%!   v = [1 2; 3 4];\n%!   numpts = numel (x);\n%!   sf = 0.5;\n%!\n%!   ## Check multiple arrows.\n%!   h = quiver (hax, x, y, u, v, 1);\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3*numpts);\n%!   xendpoint1 = childxdata{stemchild}(5);\n%!   xendpoint2 = childxdata{stemchild}(11);\n%!   assert (xendpoint1, x(2) + (sqrt (2)/10)*u(2), eps);\n%!   assert (xendpoint2, x(4) + (sqrt (2)/10)*u(4), eps);\n%!\n%!   h = quiver (hax, x, y, u, v, sf);\n%!   childxdata = get (get (h, \"children\"), \"xdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3*numpts);\n%!   xendpoint1 = childxdata{stemchild}(5);\n%!   xendpoint2 = childxdata{stemchild}(11);\n%!   assert (xendpoint1, x(2) + sf*(sqrt (2)/10)*u(2), eps);\n%!   assert (xendpoint2, x(4) + sf*(sqrt (2)/10)*u(4), eps);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check for proper plotting with non-float inputs.\n%!test <*59695>\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!   h = quiver (int32(1), int32(1), int32(1), int32(1), double(0.5));\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   assert (all (strcmp (cellfun (...\n%!                 'class', childxdata, 'UniformOutput', false), \"double\")));\n%!   assert (all (strcmp (cellfun (...\n%!                 'class', childydata, 'UniformOutput', false), \"double\")));\n%!   assert (childxdata{2}(2) , 1.5, eps);\n%!   assert (childxdata{3}(2) , 1.5, eps);\n%!   assert (childydata{2}(2) , 1.5, eps);\n%!   assert (childydata{3}(2) , 1.5, eps);\n%!\n%!   h = quiver (0.5, 0.5, 0.5, 0.5, int32(1));\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   assert (all (strcmp (cellfun (...\n%!                 'class', childxdata, 'UniformOutput', false), \"double\")));\n%!   assert (all (strcmp (cellfun (...\n%!                 'class', childydata, 'UniformOutput', false), \"double\")));\n%!   assert (childxdata{2}(2) , 1, eps);\n%!   assert (childxdata{3}(2) , 1, eps);\n%!   assert (childydata{2}(2) , 1, eps);\n%!   assert (childydata{3}(2) , 1, eps);\n%!\n%!   h = quiver (false, true, false, true, true);\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   assert (all (strcmp (cellfun (...\n%!                 'class', childxdata, 'UniformOutput', false), \"double\")));\n%!   assert (all (strcmp (cellfun (...\n%!                 'class', childydata, 'UniformOutput', false), \"double\")));\n%!   assert (childxdata{2}(2) , 0, eps);\n%!   assert (childxdata{3}(2) , 0, eps);\n%!   assert (childydata{2}(2) , 2, eps);\n%!   assert (childydata{3}(2) , 2, eps);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> quiver ()\n%!error <Invalid call> quiver (1.1)\n%!error <Invalid call> quiver (1.1, \"foo\")\n%!error <Invalid call> quiver (1.1, 2, 3, 4, 5, 6, \"foo\")\n%!error <U and V must be the same size> quiver ([1, 2], 3)\n%!error <U and V must be the same size> quiver (1.1, [2, 3])\n%!error <U and V must be the same size> quiver (1.1, 2, eye(2), 4)\n%!error <U and V must be the same size> quiver (1.1, 2, 3, eye(2))\n%!error <X vector length must equal> quiver (1.1, [2 3], eye(2), eye(2))\n%!error <Y vector length must equal> quiver ([1, 2], 3, eye(2), eye(2))\n%!error <X, Y, U, and V must be the same size> quiver (eye(3), eye(2), eye(2), eye(2))\n%!error <X, Y, U, and V must be the same size> quiver (eye(2), eye(3), eye(2), eye(2))\n%!error <X, Y, U, and V must be the same size> quiver (eye(2), eye(2), eye(3), eye(2))\n%!error <X, Y, U, and V must be the same size> quiver (eye(2), eye(2), eye(2), eye(3))\n%!error <scaling factor must be> quiver (10, 20, -5)\n%!error <scaling factor must be> quiver (10, 20, [1 2])\n%!error <scaling factor must be> quiver (10, 20, 30, 40, -5)\n%!error <scaling factor must be> quiver (10, 20, 30, 40, [1 2])\n"
  },
  {
    "path": "scripts/plot/draw/quiver3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} quiver3 (@var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w})\n## @deftypefnx {} {} quiver3 (@var{z}, @var{u}, @var{v}, @var{w})\n## @deftypefnx {} {} quiver3 (@dots{}, @var{s})\n## @deftypefnx {} {} quiver3 (@dots{}, @var{style})\n## @deftypefnx {} {} quiver3 (@dots{}, \"filled\")\n## @deftypefnx {} {} quiver3 (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} quiver3 (@dots{})\n##\n## Plot a 3-D vector field with arrows.\n##\n## Plot the (@var{u}, @var{v}, @var{w}) components of a vector field at the\n## grid points defined by (@var{x}, @var{y}, @var{z}).  If the grid is uniform\n## then @var{x}, @var{y}, and @var{z} can be specified as grid vectors and\n## @code{meshgrid} is used to create the 3-D grid.\n##\n## If @var{x} and @var{y} are not given they are assumed to be\n## @code{(1:@var{m}, 1:@var{n})} where\n## @code{[@var{m}, @var{n}] = size (@var{u})}.\n##\n## The optional input @var{s} is a scalar defining a scaling factor to use for\n## the arrows of the field relative to the mesh spacing.  A value of 1.0 will\n## result in the longest vector exactly filling one grid cube.  A value of 0\n## or @qcode{\"off\"} disables all scaling.  The default value is 0.9.\n##\n## The style to use for the plot can be defined with a line style @var{style}\n## of the same format as the @code{plot} command.  If a marker is specified\n## then the markers are drawn at the origin of the vectors (which are the grid\n## points defined by @var{x}, @var{y}, @var{z}).  When a marker is specified,\n## the arrowhead is not drawn.  If the argument @qcode{\"filled\"} is given then\n## the markers are filled.  If name-value plot style properties are used, they\n## must appear in pairs and follow any other plot style arguments.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to a quiver object.\n## A quiver object regroups the components of the quiver plot (body, arrow,\n## and marker), and allows them to be changed together.\n##\n## @example\n## @group\n## [x, y, z] = peaks (25);\n## surf (x, y, z);\n## hold on;\n## [u, v, w] = surfnorm (x, y, z / 10);\n## h = quiver3 (x, y, z, u, v, w);\n## set (h, \"maxheadsize\", 0.33);\n## @end group\n## @end example\n##\n## @seealso{quiver, compass, feather, plot}\n## @end deftypefn\n\nfunction h = quiver3 (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"quiver3\", varargin{:});\n\n  if (nargin < 4)\n    print_usage ();\n  endif\n\n  [hax, htmp] = __quiver__ (hax, true, varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = peaks (25);\n%! surf (x, y, z);\n%! hold on;\n%! [u, v, w] = surfnorm (x, y, z / 10);\n%! h = quiver3 (x, y, z, u, v, w);\n%! set (h, \"maxheadsize\", 0.25);\n%! hold off;\n%! title (\"quiver3() of surface normals to peaks() function\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = peaks (25);\n%! surf (x, y, z);\n%! hold on;\n%! [u, v, w] = surfnorm (x, y, z / 10);\n%! h = quiver3 (x, y, z, u, v, w);\n%! set (h, \"maxheadsize\", 0.25);\n%! hold off;\n%! shading interp;\n%! title ({\"quiver3() of surface normals to peaks() function\"; ...\n%!         'shading \"interp\"'});\n\n## Check standard inputs, single arrow.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!\n%!   h = quiver3 (hax, 0, 1, 2, 3);\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   childzdata = get (children, \"zdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{stemchild}(1), 1, eps);\n%!   assert (childxdata{stemchild}(2), 1 + 1*0.9, eps);\n%!   assert (isnan (childxdata{stemchild}(3)));\n%!   assert (childxdata{arrowheadchild}(2), 1 + 1*0.9, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(4)));\n%!   assert (childydata{stemchild}(1), 1, eps);\n%!   assert (childydata{stemchild}(2), 1 + 2*0.9, eps);\n%!   assert (isnan (childydata{stemchild}(3)));\n%!   assert (childydata{arrowheadchild}(2), 1 + 2*0.9, eps);\n%!   assert (isnan (childydata{arrowheadchild}(4)));\n%!   assert (childzdata{stemchild}(1), 0, eps);\n%!   assert (childzdata{stemchild}(2), 0 + 3*0.9, eps);\n%!   assert (isnan (childzdata{stemchild}(3)));\n%!   assert (childzdata{arrowheadchild}(2), 0 + 3*0.9, eps);\n%!   assert (isnan (childzdata{arrowheadchild}(4)));\n%!\n%!   h = quiver3 (hax, 1, 1, 0, 1, 2, 3);\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   childzdata = get (children, \"zdata\");\n%!   stemchild = find (cellfun ('numel', childxdata) == 3);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == 4);\n%!   assert (childxdata{stemchild}(1), 1, eps);\n%!   assert (childxdata{stemchild}(2), 1 + 1*0.9, eps);\n%!   assert (isnan (childxdata{stemchild}(3)));\n%!   assert (childxdata{arrowheadchild}(2), 1 + 1*0.9, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(4)));\n%!   assert (childydata{stemchild}(1), 1, eps);\n%!   assert (childydata{stemchild}(2), 1 + 2*0.9, eps);\n%!   assert (isnan (childydata{stemchild}(3)));\n%!   assert (childydata{arrowheadchild}(2), 1 + 2*0.9, eps);\n%!   assert (isnan (childydata{arrowheadchild}(4)));\n%!   assert (childzdata{stemchild}(1), 0, eps);\n%!   assert (childzdata{stemchild}(2), 0 + 3*0.9, eps);\n%!   assert (isnan (childzdata{stemchild}(3)));\n%!   assert (childzdata{arrowheadchild}(2), 0 + 3*0.9, eps);\n%!   assert (isnan (childzdata{arrowheadchild}(4)));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Check standard inputs, multiple arrows.\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! hax = gca ();\n%! unwind_protect\n%!\n%!   a = reshape (1:12,2,3,2);\n%!   x = 1:3; y = 1:2; z = 1:2;\n%!   [xx,yy,zz] = meshgrid (x,y,z);\n%!   numpts = 12;\n%!   sf= sqrt(sumsq([1/3 1/2 11/6])/432); # Actual internal scale factor, z=a.\n%!   sf2= sqrt(sumsq([1/3 1/2 1/6])/432); # z vector internal scale factor.\n%!\n%!   h = quiver3 (hax, a, a, a, a, 1); # No x,y input.\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   childzdata = get (children, \"zdata\");\n%!   basechild = find (cellfun ('numel', childxdata) == numpts);\n%!   stemchild = find (cellfun ('numel', childxdata) == numpts*3);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == numpts*4);\n%!   ## Check all bases.\n%!   assert (childxdata{basechild}, [1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3]);\n%!   assert (childydata{basechild}, [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]);\n%!   assert (childzdata{basechild}, [1:12]);\n%!   ## Check first arrow.\n%!   assert (childxdata{stemchild}(1), 1, eps);\n%!   assert (childxdata{stemchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childxdata{stemchild}(3)));\n%!   assert (childxdata{arrowheadchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(4)));\n%!   assert (childydata{stemchild}(1), 1, eps);\n%!   assert (childydata{stemchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childydata{stemchild}(3)));\n%!   assert (childydata{arrowheadchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childydata{arrowheadchild}(4)));\n%!   assert (childzdata{stemchild}(1), 1, eps);\n%!   assert (childzdata{stemchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childzdata{stemchild}(3)));\n%!   assert (childzdata{arrowheadchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childzdata{arrowheadchild}(4)));\n%!   ## Check last arrow.\n%!   assert (childxdata{stemchild}(numpts*3-2), 3, eps);\n%!   assert (childxdata{stemchild}(numpts*3-1), 3 + 12*sf, eps);\n%!   assert (isnan (childxdata{stemchild}(end)));\n%!   assert (childxdata{arrowheadchild}(numpts*4-2), 3 + 12*sf, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(end)));\n%!   assert (childydata{stemchild}(numpts*3-2), 2, eps);\n%!   assert (childydata{stemchild}(numpts*3-1), 2 + 12*sf, eps);\n%!   assert (isnan (childydata{stemchild}(end)));\n%!   assert (childydata{arrowheadchild}(numpts*4-2), 2 + 12*sf, eps);\n%!   assert (isnan (childydata{arrowheadchild}(end)));\n%!   assert (childzdata{stemchild}(numpts*3-2), 12, eps);\n%!   assert (childzdata{stemchild}(numpts*3-1), 12 + 12*sf, eps);\n%!   assert (isnan (childzdata{stemchild}(end)));\n%!   assert (childzdata{arrowheadchild}(numpts*4-2), 12 + 12*sf, eps);\n%!   assert (isnan (childzdata{arrowheadchild}(end)));\n%!\n%!   h = quiver3 (hax, xx, yy, a, a, a, a, 1); # x,y input as matrices.\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   childzdata = get (children, \"zdata\");\n%!   basechild = find (cellfun ('numel', childxdata) == numpts);\n%!   stemchild = find (cellfun ('numel', childxdata) == numpts*3);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == numpts*4);\n%!   ## Check all bases.\n%!   assert (childxdata{basechild}, [1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3]);\n%!   assert (childydata{basechild}, [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]);\n%!   assert (childzdata{basechild}, [1:12]);\n%!   ## Check first arrow.\n%!   assert (childxdata{stemchild}(1), 1, eps);\n%!   assert (childxdata{stemchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childxdata{stemchild}(3)));\n%!   assert (childxdata{arrowheadchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(4)));\n%!   assert (childydata{stemchild}(1), 1, eps);\n%!   assert (childydata{stemchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childydata{stemchild}(3)));\n%!   assert (childydata{arrowheadchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childydata{arrowheadchild}(4)));\n%!   assert (childzdata{stemchild}(1), 1, eps);\n%!   assert (childzdata{stemchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childzdata{stemchild}(3)));\n%!   assert (childzdata{arrowheadchild}(2), 1 + 1*sf, eps);\n%!   assert (isnan (childzdata{arrowheadchild}(4)));\n%!   ## Check last arrow.\n%!   assert (childxdata{stemchild}(numpts*3-2), 3, eps);\n%!   assert (childxdata{stemchild}(numpts*3-1), 3 + 12*sf, eps);\n%!   assert (isnan (childxdata{stemchild}(end)));\n%!   assert (childxdata{arrowheadchild}(numpts*4-2), 3 + 12*sf, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(end)));\n%!   assert (childydata{stemchild}(numpts*3-2), 2, eps);\n%!   assert (childydata{stemchild}(numpts*3-1), 2 + 12*sf, eps);\n%!   assert (isnan (childydata{stemchild}(end)));\n%!   assert (childydata{arrowheadchild}(numpts*4-2), 2 + 12*sf, eps);\n%!   assert (isnan (childydata{arrowheadchild}(end)));\n%!   assert (childzdata{stemchild}(numpts*3-2), 12, eps);\n%!   assert (childzdata{stemchild}(numpts*3-1), 12 + 12*sf, eps);\n%!   assert (isnan (childzdata{stemchild}(end)));\n%!   assert (childzdata{arrowheadchild}(numpts*4-2), 12 + 12*sf, eps);\n%!   assert (isnan (childzdata{arrowheadchild}(end)));\n%!\n%!   h = quiver3 (hax, x, y, z, a, a, a, 1); # x,y z input as vectors.\n%!   children = get (h, \"children\");\n%!   childxdata = get (children, \"xdata\");\n%!   childydata = get (children, \"ydata\");\n%!   childzdata = get (children, \"zdata\");\n%!   basechild = find (cellfun ('numel', childxdata) == numpts);\n%!   stemchild = find (cellfun ('numel', childxdata) == numpts*3);\n%!   arrowheadchild = find (cellfun ('numel', childxdata) == numpts*4);\n%!   ## Check all bases.\n%!   assert (childxdata{basechild}, [1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3]);\n%!   assert (childydata{basechild}, [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]);\n%!   assert (childzdata{basechild}, [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2]);\n%!   ## Check first arrow.\n%!   assert (childxdata{stemchild}(1), 1, eps);\n%!   assert (childxdata{stemchild}(2), 1 + 1*sf2, eps);\n%!   assert (isnan (childxdata{stemchild}(3)));\n%!   assert (childxdata{arrowheadchild}(2), 1 + 1*sf2, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(4)));\n%!   assert (childydata{stemchild}(1), 1, eps);\n%!   assert (childydata{stemchild}(2), 1 + 1*sf2, eps);\n%!   assert (isnan (childydata{stemchild}(3)));\n%!   assert (childydata{arrowheadchild}(2), 1 + 1*sf2, eps);\n%!   assert (isnan (childydata{arrowheadchild}(4)));\n%!   assert (childzdata{stemchild}(1), 1, eps);\n%!   assert (childzdata{stemchild}(2), 1 + 1*sf2, eps);\n%!   assert (isnan (childzdata{stemchild}(3)));\n%!   assert (childzdata{arrowheadchild}(2), 1 + 1*sf2, eps);\n%!   assert (isnan (childzdata{arrowheadchild}(4)));\n%!   ## Check last arrow.\n%!   assert (childxdata{stemchild}(numpts*3-2), 3, eps);\n%!   assert (childxdata{stemchild}(numpts*3-1), 3 + 12*sf2, eps);\n%!   assert (isnan (childxdata{stemchild}(end)));\n%!   assert (childxdata{arrowheadchild}(numpts*4-2), 3 + 12*sf2, eps);\n%!   assert (isnan (childxdata{arrowheadchild}(end)));\n%!   assert (childydata{stemchild}(numpts*3-2), 2, eps);\n%!   assert (childydata{stemchild}(numpts*3-1), 2 + 12*sf2, eps);\n%!   assert (isnan (childydata{stemchild}(end)));\n%!   assert (childydata{arrowheadchild}(numpts*4-2), 2 + 12*sf2, eps);\n%!   assert (isnan (childydata{arrowheadchild}(end)));\n%!   assert (childzdata{stemchild}(numpts*3-2), 2, eps);\n%!   assert (childzdata{stemchild}(numpts*3-1), 2 + 12*sf2, eps);\n%!   assert (isnan (childzdata{stemchild}(end)));\n%!   assert (childzdata{arrowheadchild}(numpts*4-2), 2 + 12*sf2, eps);\n%!   assert (isnan (childzdata{arrowheadchild}(end)));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n##Test input validation\n%!error <Invalid call> quiver3 ()\n%!error <Invalid call> quiver3 (1.1)\n%!error <Invalid call> quiver3 (1.1, 2)\n%!error <Invalid call> quiver3 (1.1, 2, 3)\n%!error <Invalid call> quiver3 (1.1, 2, 3, \"foo\")\n%!error <Invalid call> quiver3 (1.1, 2, 3, 4, 5, 6, 7, 8, \"foo\")\n%!error <U, V, and W must be the same> quiver3 (30, [40 50], 60, 70)\n%!error <Z vector length must equal size of> quiver3 ([30 40], eye(3), eye(3), eye(3))\n%!error <Z, U, V, and W must be the same> quiver3 ([30 40], 50, 60, 70)\n%!error <Z, U, V, and W must be the same> quiver3 (eye(2), eye(3), eye(2), eye(2))\n%!error <Z, U, V, and W must be the same> quiver3 (eye(2), eye(2), eye(3), eye(2))\n%!error <Z, U, V, and W must be the same> quiver3 (eye(2), eye(2), eye(2), eye(3))\n%!error <U, V, and W must be the same size> quiver3 ([1:2], [1:2], 1, eye(3), eye(2), eye(2))\n%!error <U, V, and W must be the same size> quiver3 ([1:2], [1:2], 1, eye(2), eye(3), eye(2))\n%!error <U, V, and W must be the same size> quiver3 ([1:2], [1:2], 1, eye(2), eye(2), eye(3))\n%!error <X vector length must equal number of> quiver3 ([1:3], [1:2], 1, eye(2), eye(2), eye(2))\n%!error <Y vector length must equal number of> quiver3 ([1:2], [1:3], 1, eye(2), eye(2), eye(2))\n%!error <Z vector length must equal size of> quiver3 ([1:2], [1:2], [1:2], eye(2), eye(2), eye(2))\n%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(3), eye(2), eye(2), eye(2), eye(2), eye(2))\n%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(3), eye(2), eye(2), eye(2), eye(2))\n%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(2), eye(3), eye(2), eye(2), eye(2))\n%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(2), eye(2), eye(3), eye(2), eye(2))\n%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(2), eye(2), eye(2), eye(3), eye(2))\n%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(2), eye(2), eye(2), eye(2), eye(3))\n%!error <scaling factor must be> quiver3 (10, 20, 30, 40, -5)\n%!error <scaling factor must be> quiver3 (10, 20, 30, 40, [1 2])\n%!error <scaling factor must be> quiver3 (10, 20, 30, 40, 50, 60, -5)\n%!error <scaling factor must be> quiver3 (10, 20, 30, 40, 50, 60, [1 2])\n"
  },
  {
    "path": "scripts/plot/draw/rectangle.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} rectangle ()\n## @deftypefnx {} {} rectangle (@dots{}, \"Position\", @var{pos})\n## @deftypefnx {} {} rectangle (@dots{}, \"Curvature\", @var{curv})\n## @deftypefnx {} {} rectangle (@dots{}, \"EdgeColor\", @var{ec})\n## @deftypefnx {} {} rectangle (@dots{}, \"FaceColor\", @var{fc})\n## @deftypefnx {} {} rectangle (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} rectangle (@dots{})\n## Draw a rectangular patch defined by @var{pos} and @var{curv}.\n##\n## The variable @code{@var{pos}(1:2)} defines the lower left-hand corner of\n## the patch and @code{@var{pos}(3:4)} defines its width and height.  By\n## default, the value of @var{pos} is @code{[0, 0, 1, 1]}.\n##\n## The variable @var{curv} defines the curvature of the sides of the rectangle\n## and may be a scalar or two-element vector with values between 0 and 1.\n## A value of 0 represents no curvature of the side, whereas a value of 1\n## means that the side is entirely curved into the arc of a circle.\n## If @var{curv} is a two-element vector, then the first element is the\n## curvature along the x-axis of the patch and the second along y-axis.\n##\n## If @var{curv} is a scalar, it represents the curvature of the shorter of the\n## two sides of the rectangle and the curvature of the other side is defined\n## by\n##\n## @example\n## min (pos(1:2)) / max (pos(1:2)) * curv\n## @end example\n##\n## Additional property/value pairs are passed to the underlying patch command.\n## The full list of properties is documented at @ref{Patch Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## rectangle object.\n## @seealso{patch, line, cylinder, ellipsoid, sphere}\n## @end deftypefn\n\nfunction h = rectangle (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"rectangle\", varargin{:});\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  oldfig = [];\n  if (! isempty (hax))\n    oldfig = get (0, \"currentfigure\");\n  endif\n  unwind_protect\n    htmp = __rectangle__ (hax, varargin{:});\n  unwind_protect_cleanup\n    if (! isempty (oldfig))\n      set (0, \"currentfigure\", oldfig);\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\nfunction hg = __rectangle__ (hax, varargin)\n\n  iarg = 1;\n  pos = [0, 0, 1, 1];\n  curv2 = [0, 0];\n  ec = [0, 0, 0];\n  fc = \"none\";\n  parent = [];\n\n  while (iarg < length (varargin))\n    arg = varargin{iarg};\n    if (ischar (arg))\n      if (strcmpi (arg, \"position\"))\n        pos = varargin{iarg+1};\n        varargin(iarg:iarg+1) = [];\n        if (! isvector (pos) || numel (pos) != 4)\n          error (\"rectangle: position must be a 4-element vector\");\n        endif\n      elseif (strcmpi (arg, \"curvature\"))\n        curv2 = varargin{iarg+1};\n        varargin(iarg:iarg+1) = [];\n        if (! isnumeric (curv2) || (numel (curv2) != 1 && numel (curv2) != 2))\n          error (\"rectangle: curvature must be a 2-element vector or a scalar\");\n        endif\n        if (any (curv2 < 0) || any (curv2 > 1))\n          error (\"rectangle: curvature values must be between 0 and 1\");\n        endif\n      elseif (strcmpi (arg, \"edgecolor\"))\n        ec = varargin{iarg+1};\n        varargin(iarg:iarg+1) = [];\n      elseif (strcmpi (arg, \"facecolor\"))\n        fc = varargin{iarg+1};\n        varargin(iarg:iarg+1) = [];\n      elseif (strcmpi (arg, \"parent\"))\n        parent = varargin{iarg+1};\n        varargin(iarg:iarg+1) = [];\n      else\n        iarg += 1;\n      endif\n    else\n      iarg += 1;\n    endif\n  endwhile\n\n  if (numel (curv2) == 1)\n    [a, ai] = min (pos(3:4));\n    [b, bi] = max (pos(3:4));\n    if (ai < bi)\n      curv = [curv2, curv2 .* a ./ b];\n    else\n      curv = [curv2 .* a ./ b, curv2];\n    endif\n  else\n    curv = curv2;\n  endif\n\n  if (all (curv < 0.01))\n    ## Special case : no curvature\n    x = [pos(1), pos(1) + pos(3), pos(1) + pos(3), pos(1), pos(1)];\n    y = [pos(2), pos(2), pos(2) + pos(4), pos(2) + pos(4), pos(2)];\n  else\n    p = pi / 2 * [0 : 15] / 15;\n    c = curv .* pos(3:4) / 2;\n    cx = c(1) * sin (p) - c(1);\n    cy = c(2) * cos (p) - c(2);\n    x = [pos(1) - fliplr(cx), pos(1) + pos(3) + cx, ...\n         pos(1) + pos(3) + fliplr(cx), pos(1) - cx, pos(1)];\n    y = [pos(2) - fliplr(cy), pos(2) - cy, pos(2) + pos(4) + fliplr(cy), ...\n         pos(2) + pos(4) + cy, pos(2) + c(2)];\n  endif\n\n  if (! isempty (parent))\n    hg = hggroup (\"parent\", parent);\n  else\n    hg = hggroup (\"parent\", hax);\n  endif\n\n  h = patch (\"xdata\", x(:), \"ydata\", y(:), \"facecolor\", fc, \"edgecolor\", ec,\n             \"parent\", hg, varargin{:});\n\n  addproperty (\"curvature\", hg, \"data\", curv2);\n  addproperty (\"position\",  hg, \"data\", pos);\n  addproperty (\"edgecolor\", hg, \"patchedgecolor\", get (h, \"edgecolor\"));\n  addproperty (\"linewidth\", hg, \"patchlinewidth\", get (h, \"linewidth\"));\n  addproperty (\"linestyle\", hg, \"patchlinestyle\", get (h, \"linestyle\"));\n  addproperty (\"facecolor\", hg, \"patchfacecolor\", get (h, \"facecolor\"));\n\n  addlistener (hg, \"curvature\", @update_data);\n  addlistener (hg, \"position\",  @update_data);\n  addlistener (hg, \"edgecolor\", @update_props);\n  addlistener (hg, \"linewidth\", @update_props);\n  addlistener (hg, \"linestyle\", @update_props);\n  addlistener (hg, \"facecolor\", @update_props);\n\nendfunction\n\nfunction update_data (h, ~)\n  persistent recursion = false;\n\n  ## Don't allow recursion\n  if (! recursion)\n    unwind_protect\n      recursion = true;\n\n      kids = get (h, \"children\");\n      pos = get (h, \"position\");\n      curv2 = get (h, \"curvature\");\n\n      if (numel (curv2) == 1)\n        [a, ai] = min (pos(3:4));\n        [b, bi] = max (pos(3:4));\n        if (ai < bi)\n          curv = [curv2, curv2 .* a ./ b];\n        else\n          curv = [curv2 .* a ./ b, curv2];\n        endif\n      else\n        curv = curv2;\n      endif\n\n      if (all (curv < 0.01))\n        ## Special case : no curvature\n        x = [pos(1), pos(1) + pos(3), pos(1) + pos(3), pos(1), pos(1)];\n        y = [pos(2), pos(2), pos(2) + pos(4), pos(2) + pos(4), pos(2)];\n      else\n        p = pi / 2 * [0 : 15] / 15;\n        c = curv .* pos(3:4) / 2;\n        cx = c(1) * sin (p) - c(1);\n        cy = c(2) * cos (p) - c(2);\n        x = [pos(1) - fliplr(cx), pos(1) + pos(3) + cx, ...\n             pos(1) + pos(3) + fliplr(cx), pos(1) - cx, pos(1)];\n        y = [pos(2) - fliplr(cy), pos(2) - cy, pos(2) + pos(4) + fliplr(cy), ...\n             pos(2) + pos(4) + cy, pos(2) + c(2)];\n      endif\n\n      set (kids, \"xdata\", x, \"ydata\", y);\n    unwind_protect_cleanup\n      recursion = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\nfunction update_props (h, ~)\n  kids = get (h, \"children\");\n  set (kids, {\"edgecolor\", \"linewidth\", \"linestyle\", \"facecolor\"},\n     get (h, {\"edgecolor\", \"linewidth\", \"linestyle\", \"facecolor\"}));\nendfunction\n\n\n%!demo\n%! clf;\n%! axis equal;\n%! rectangle (\"Position\", [0.05, 0.05, 0.9, 0.9], \"Curvature\", [0.5, 0.5]);\n%! title (\"rectangle() with corners curved\");\n\n%!demo\n%! clf;\n%! axis equal;\n%! rectangle (\"Position\", [0.05, 0.05, 0.9, 0.4], \"Curvature\", 1.0);\n%! title (\"rectangle() with sides as complete arcs\");\n\n%!demo\n%! clf;\n%! axis equal;\n%! h = rectangle (\"Position\", [0.05, 0.05, 0.9, 0.4], \"Curvature\", 1.0);\n%! set (h, \"FaceColor\", [0, 1, 0]);\n%! title (\"rectangle() with FaceColor = green\");\n"
  },
  {
    "path": "scripts/plot/draw/reducepatch.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{reduced_fv} =} reducepatch (@var{fv})\n## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@var{faces}, @var{vertices})\n## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@var{patch_handle})\n## @deftypefnx {} {} reducepatch (@var{patch_handle})\n## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@dots{}, @var{reduction_factor})\n## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@dots{}, \"fast\")\n## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@dots{}, \"verbose\")\n## @deftypefnx {} {[@var{reduced_faces}, @var{reduces_vertices}] =} reducepatch (@dots{})\n##\n## Reduce the number of faces and vertices in a patch object while retaining\n## the overall shape of the patch.\n##\n## The input patch can be represented by a structure @var{fv} with the\n## fields @code{faces} and @code{vertices}, by two matrices @var{faces} and\n## @var{vertices} (see, e.g., the result of @code{isosurface}), or by a\n## handle to a patch object @var{patch_handle}\n## (@pxref{XREFpatch,,@code{patch}}).\n##\n## The number of faces and vertices in the patch is reduced by iteratively\n## collapsing the shortest edge of the patch to its midpoint (as discussed,\n## e.g., here:\n## @url{https://libigl.github.io/libigl/tutorial/tutorial.html#meshdecimation}).\n##\n## Currently, only patches consisting of triangles are supported.  The\n## resulting patch also consists only of triangles.\n##\n## If @code{reducepatch} is called with a handle to a valid patch\n## @var{patch_handle}, and without any output arguments, then the given\n## patch is updated immediately.\n##\n## If the @var{reduction_factor} is omitted, the resulting structure\n## @var{reduced_fv} includes approximately 50% of the faces of the original\n## patch.  If @var{reduction_factor} is a fraction between 0 (excluded) and 1\n## (excluded), a patch with approximately the corresponding fraction of faces\n## is determined.\n## If @var{reduction_factor} is an integer greater than or equal to 1, the\n## resulting patch has approximately @var{reduction_factor} faces.  Depending\n## on the geometry of the patch, the resulting number of faces can differ from\n## the given value of @var{reduction_factor}.  This is especially true when\n## many shared vertices are detected.\n##\n## For the reduction, it is necessary that vertices of touching faces are\n## shared.  Shared vertices are detected automatically.  This detection can be\n## skipped by passing the optional string argument @qcode{\"fast\"}.\n##\n## With the optional string arguments @qcode{\"verbose\"}, additional status\n## messages are printed to the command window.\n##\n## Any string input arguments must be passed after all other arguments.\n##\n## If called with one output argument, the reduced faces and vertices are\n## returned in a structure @var{reduced_fv} with the fields @code{faces} and\n## @code{vertices} (see the one output option of @code{isosurface}).\n##\n## If called with two output arguments, the reduced faces and vertices are\n## returned in two separate matrices @var{reduced_faces} and\n## @var{reduced_vertices}.\n##\n## @seealso{isosurface, isonormals, reducevolume, patch}\n## @end deftypefn\n\n## FIXME: Convert faces to only triangles if necessary\n\nfunction varargout = reducepatch (varargin)\n\n  if (nargin < 1 || nargin > 5)\n    print_usage ();\n  endif\n\n  [faces, vertices, max_faces, patch_handle, fast, verbose] = ...\n                          __get_check_reducepatch_args__ (varargin{:});\n\n  if (verbose)\n    printf ([\"reducepatch: before reduction of faces:           \", ...\n             \"%5d faces, %5d vertices\\n\"], rows (faces), rows (vertices));\n  endif\n\n  if (max_faces >= rows (faces))\n    faces_reduced = faces;\n    vertices_reduced = vertices;\n  else\n    if (! fast)\n      [faces, vertices] = __unite_shared_vertices__ (faces, vertices);\n\n      if (verbose)\n        printf ([\"reducepatch: after detection of shared vertices:  \", ...\n                 \"%5d faces, %5d vertices\\n\"], rows (faces), rows (vertices));\n      endif\n    endif\n\n    [faces_reduced, vertices_reduced] = ...\n        __reducepatch__ (vertices, faces, max_faces, verbose);\n  endif\n\n  if (verbose)\n    printf ([\"reducepatch: after reduction of faces:            \", ...\n             \"%5d faces, %5d vertices\\n\"],                         ...\n            rows (faces_reduced), rows (vertices_reduced));\n  endif\n\n  ## output\n  if (! isempty (patch_handle) && nargout == 0)\n    ## update patch object\n    set (patch_handle, \"Faces\", faces_reduced, \"Vertices\", vertices_reduced);\n  elseif (nargout == 2)  # faces, vertices\n    varargout{1} = faces_reduced;\n    varargout{2} = vertices_reduced;\n  else  # fv structure\n    varargout{1}.faces = faces_reduced;\n    varargout{1}.vertices = vertices_reduced;\n  endif\n\nendfunction\n\n## assign input parameters and check their validity\nfunction [faces, vertices, max_faces, patch_handle, fast, verbose] = ...\n              __get_check_reducepatch_args__ (varargin)\n\n  ## default values\n  faces = vertices = max_faces = patch_handle = [];\n  reduction_factor = 0.5;\n  fast = verbose = false;\n\n  num_string_inputs = 0;\n  ## check whether last 2 input arguments are strings and assign parameters\n  valid_vals = nargin:-1:nargin-1;\n  valid_vals(valid_vals < 1) = [];\n  for arg = varargin(valid_vals)\n    if (! ischar (arg{1}))\n      break;  # no string arguments at end, exit checking\n    endif\n    switch (lower (arg{1}))\n      case {\"f\", \"fast\"}\n        fast = true;\n        num_string_inputs += 1;\n\n      case {\"v\", \"verbose\"}\n        verbose = true;\n        num_string_inputs += 1;\n\n      case \"\"\n        num_string_inputs++;\n        ## silently ignore empty strings\n\n      otherwise\n        error (\"reducepatch: parameter '%s' not supported\", arg{1});\n\n    endswitch\n  endfor\n\n  ## get faces and vertices\n  i_fv = 1;\n  arg1 = varargin{1};\n  if (isstruct (arg1))\n    if (all (isfield (arg1, {\"vertices\", \"faces\"})))\n      vertices = arg1.vertices;\n      faces = arg1.faces;\n    else\n      error ([\"reducepatch: struct FV must contain the fields \", ...\n              \"'vertices' and 'faces'.\"]);\n    endif\n  elseif (isscalar (arg1))\n    patch_handle = arg1;\n    if (isgraphics (patch_handle, \"patch\"))\n      vertices = get (patch_handle, \"Vertices\");\n      faces = get (patch_handle, \"Faces\");\n    else\n      error (\"reducepatch: PATCH_HANDLE must be a valid handle to a patch\");\n    endif\n  elseif (ismatrix (arg1))\n    faces = arg1;\n    if (nargin - num_string_inputs > 1 && ismatrix (varargin{2}))\n      vertices = varargin{2};\n      i_fv = 2;\n    else\n      error ([\"reducepatch: If first argument is a matrix containing \", ...\n             \"FACES, second argument must be a matrix containing VERTICES\"]);\n    endif\n  else\n    print_usage (\"reducepatch\");\n  endif\n\n  ## get reduction_factor\n  if (nargin - num_string_inputs > i_fv)\n    reduction_factor = varargin{i_fv + 1};\n    if (! isscalar (reduction_factor) || reduction_factor <= 0)\n      error (\"reducepatch: REDUCTION_FACTOR must be a positive scalar\");\n    endif\n  endif\n\n  ## check faces and vertices\n  if (columns (vertices) != 3)\n    error (\"reducepatch: VERTICES must be an Mx3 matrix\");\n  endif\n  if (columns (faces) != 3)\n    ## FIXME: Convert faces to only triangles if necessary\n    error (\"reducepatch: Currently patches must consist of triangles only\");\n  endif\n  if (any (mod (faces(:), 1)) || any (faces(:) < 1))\n    error (\"reducepatch: FACES must consist of positive integer indices only\");\n  endif\n  if (max (faces(:)) > rows (vertices))\n    error (\"reducepatch: not enough VERTICES for given FACES\");\n  endif\n\n  ## get max_faces\n  num_faces = rows (faces);\n  if (reduction_factor < 1)\n    max_faces = floor (num_faces * reduction_factor);\n  else\n    max_faces = reduction_factor;\n  endif\n\nendfunction\n\n## actual function to reduce number of faces\nfunction [faces_reduced, vertices_reduced] = ...\n              __reducepatch__ (vertices, faces, max_faces, verbose)\n\n  num_faces = rows (faces);\n  faces = sort (faces, 2);\n\n  ## get all unique edges\n  all_edges = sort ([faces(:,1) faces(:,2);\n                     faces(:,2) faces(:,3);\n                     faces(:,3) faces(:,1)], 2);\n  edges = unique (all_edges, \"rows\");\n  num_edges = rows (edges);\n\n  ## calculate length of edges\n  edge_length = norm (vertices(edges(:,1),:) - vertices(edges(:,2),:), ...\n                      2, \"rows\");\n\n  if (verbose)\n    printf (\"reducepatch: reducing number of faces\");\n    ## do not spam the command window with dots if many faces are collapsed\n    verbose_stepwidth = (num_faces - max_faces) / 100;  # max. 100 dots\n    verbose_counter = 0;\n  endif\n\n  ## reduce number of faces\n  clean_finish = true;\n  do\n    ## find shortest edge\n    i_shortest_edge = find (edge_length == min (edge_length), 1, \"first\");\n    if (any (isinf (vertices(edges(i_shortest_edge,:),:))))\n      warning ([\"reducepatch: shortest edge is marked as deleted.  \", ...\n                \"This should never happen.\"])\n      clean_finish = false;\n      break;\n    endif\n\n    start_point_idx = edges(i_shortest_edge,1);\n    end_point_idx = edges(i_shortest_edge,2);\n\n    ## collapse the edge to its midpoint\n    vertices(start_point_idx,:) = 0.5 * ...\n        (vertices(start_point_idx,:) + vertices(end_point_idx,:));\n    ## endpoint will be deleted later\n\n    ## remove collapsed edge info\n    edges(i_shortest_edge,:) = [];\n    edge_length(i_shortest_edge) = [];\n\n    ## unite collapsed edges of neighboring faces to one edge\n    faces_with_collapsed_edge = any (faces == start_point_idx, 2) & ...\n                                any (faces == end_point_idx, 2);\n    edges_of_collapsed_faces = faces(faces_with_collapsed_edge,:);\n    ## get other vertex of collapsed faces\n    third_vertices = ...\n        edges_of_collapsed_faces(...\n            faces(faces_with_collapsed_edge,:) != start_point_idx & ...\n            faces(faces_with_collapsed_edge,:) != end_point_idx);\n    if (! isempty (third_vertices))\n      ## delete edge of the collapsed faces which also has end_point\n      ## (keep the one with start_point)\n      edges_to_delete = any (edges == end_point_idx, 2) & ...\n          any (any (bsxfun (@eq, edges, ...\n                            reshape (third_vertices, 1, 1, [])), 3), 2);\n      edges(edges_to_delete,:) = [];\n      edge_length(edges_to_delete) = [];\n    endif\n\n    ## mark the faces that collapsed for later removal\n    faces(faces_with_collapsed_edge,:) = Inf;\n\n    ## update the lengths of the moved edges\n    edges_with_moved_point = any (edges == start_point_idx, 2);\n    edge_length(edges_with_moved_point) = ...\n        norm (vertices(edges(edges_with_moved_point,1),:) - ...\n              vertices(edges(edges_with_moved_point,2),:), 2, \"rows\");\n\n    ## replace all vertices that use end_point to use start_point\n    if (start_point_idx != end_point_idx)\n      edges(edges == end_point_idx) = start_point_idx;\n      faces(faces == end_point_idx) = start_point_idx;\n      vertices(end_point_idx,:) = Inf; # mark vertex for later removal\n    endif\n\n    ## Pretty print a row of dots while performing calculation\n    if (verbose && ++verbose_counter > verbose_stepwidth)\n      printf (\".\");\n      verbose_counter = 0;\n    endif\n\n  until (max_faces > num_faces - sum (isinf (faces(:,1))))\n\n  if (verbose)\n    printf (\"\\n\");\n  endif\n\n  if (! clean_finish)\n    ## FIXME: What should be done in this case?\n    ## continue anyway?\n  endif\n\n  ## finally, remove vertices and faces\n  removed_vertices = isinf (vertices(:,1));\n  vertices_reduced = vertices(! removed_vertices,:);\n\n  faces_reduced = faces(! isinf (faces(:,1)),:);\n\n  ## renumber vertices in faces with subsequent numbers\n  vertex_renum = ones (rows (vertices), 1);\n  vertex_renum(removed_vertices) = 0;\n  vertex_renum = cumsum (vertex_renum);\n  faces_reduced = vertex_renum(faces_reduced);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2);\n%! val = x.^2 + y.^2 + z.^2;\n%! fv = isosurface (x, y, z, val, 1);\n%! ax1 = subplot (1, 2, 1);\n%! patch (fv, \"FaceColor\", \"g\");\n%! view (3);  axis equal;\n%! title (\"Sphere with all faces\");\n%! ax2 = subplot (1, 2, 2);\n%! patch (reducepatch (fv, 72), \"FaceColor\", \"g\");\n%! view (3);  axis equal;\n%! title (\"Sphere with reduced number of faces\");\n%! linkprop ([ax1, ax2], {\"CameraPosition\", \"CameraUpVector\"});\n\n%!shared faces, vertices, fv, num_faces\n%! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2);\n%! val = x.^2 + y.^2 + z.^2;\n%! [faces, vertices] = isosurface (x, y, z, val, 1);\n%! fv.faces = faces;  fv.vertices = vertices;\n%! num_faces = rows (faces);\n\n## one input (structure), one output\n%!test\n%! fv_reduced = reducepatch (fv);\n%! assert (size (fv_reduced.faces, 1), num_faces * .5, 3);\n%! assert (size (fv_reduced.faces, 2), 3);\n%! assert (size (fv_reduced.vertices, 2), 3);\n\n## two inputs (faces, vertices), one output\n%!test\n%! fv_reduced = reducepatch (faces, vertices);\n%! assert (size (fv_reduced.faces, 1), num_faces * .5, 3);\n%! assert (size (fv_reduced.faces, 2), 3);\n%! assert (size (fv_reduced.vertices, 2), 3);\n\n## two inputs (structure, reduction_factor > 1), two outputs\n%!test\n%! [faces_reduced, vertices_reduced] = reducepatch (fv, 20);\n%! assert (rows (faces_reduced), 20, 3);\n%! assert (columns (faces_reduced), 3);\n%! assert (columns (vertices_reduced), 3);\n\n## three inputs (faces, vertices, reduction_factor < 1), two outputs\n%!test\n%! [faces_reduced, vertices_reduced] = reducepatch (faces, vertices, .5);\n%! assert (rows (faces_reduced), num_faces * .5, 3);\n%! assert (columns (faces_reduced), 3);\n%! assert (columns (vertices_reduced), 3);\n\n## two inputs (structure, reduction_factor < 1) + one string, no outputs\n## (update patch object in figure)\n%!test\n%! h_fig = figure (\"visible\", \"off\");\n%! p = patch (fv);\n%! reducepatch (p, .35, \"f\");\n%! assert (size (get (p, \"Faces\"), 1), num_faces * .35, 3);\n%! assert (size (get (p, \"Faces\"), 2), 3);\n%! assert (size (get (p, \"Vertices\"), 2), 3);\n%! close (h_fig);\n\n## three inputs (faces, vertices, reduction_factor > 1) + one empty\n## string, one output\n%!test\n%! fv_reduced = reducepatch (faces, vertices, 52, \"\");\n%! assert (size (fv_reduced.faces, 1), 52, 3);\n%! assert (size (fv_reduced.faces, 2), 3);\n%! assert (size (fv_reduced.vertices, 2), 3);\n\n## two inputs (structure, reduction_factor < 1) + one string, two outputs\n%!test\n%! [faces_reduced, vertices_reduced] = reducepatch (fv, .4, \"fast\");\n%! assert (rows (faces_reduced), num_faces * .4, 3);\n%! assert (columns (faces_reduced), 3);\n%! assert (columns (vertices_reduced), 3);\n\n## one input (structure) + two (empty) strings, two outputs\n%!test\n%! [faces_reduced, vertices_reduced] = reducepatch (fv, \"f\", \"\");\n%! assert (rows (faces_reduced), num_faces * .5, 3);\n%! assert (columns (faces_reduced), 3);\n%! assert (columns (vertices_reduced), 3);\n\n## test for each error\n%!error <Invalid call> reducepatch ()\n%!error <Invalid call> reducepatch (fv, faces, vertices, .5, \"f\", \"v\")\n%!error <reducepatch: parameter 'foo' not supported>\n%! fv_reduced = reducepatch (faces, vertices, .7, \"foo\");\n%!error <struct FV must contain the fields 'vertices' and 'faces'>\n%! fv_incomplete.faces = faces;\n%! reducepatch (fv_incomplete, .7);\n%!error <PATCH_HANDLE must be a valid handle to a patch> reducepatch (pi, .7)\n%!error <If first argument is a matrix containing FACES, second argument must be a matrix containing VERTICES> reducepatch (faces)\n%!error <REDUCTION_FACTOR must be a positive scalar> reducepatch (fv, [.7 .5])\n%!error <REDUCTION_FACTOR must be a positive scalar> reducepatch (fv, -5)\n%!error <VERTICES must be an Mx3 matrix> reducepatch (faces, .7, \"v\")\n%!error <reducepatch: Currently patches must consist of triangles only>\n%! faces_new = NaN (rows (faces), 4);\n%! faces_new(:,1:3) = faces;\n%! faces_new(1,4) = 5;\n%! reducepatch (faces_new, vertices);\n%!error <reducepatch: not enough VERTICES for given FACES>\n%! faces_new = faces;\n%! faces_new(1,3) = rows (vertices) + 1;\n%! reducepatch (faces_new, vertices);\n"
  },
  {
    "path": "scripts/plot/draw/reducevolume.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{nx}, @var{ny}, @var{nz}, @var{nv}] =} reducevolume (@var{v}, @var{r})\n## @deftypefnx {} {[@var{nx}, @var{ny}, @var{nz}, @var{nv}] =} reducevolume (@var{x}, @var{y}, @var{z}, @var{v}, @var{r})\n## @deftypefnx {} {@var{nv} =} reducevolume (@dots{})\n##\n## Reduce the volume of the dataset in @var{v} according to the values in\n## @var{r}.\n##\n## @var{v} is a matrix that is non-singleton in the first 3 dimensions.\n##\n## @var{r} can either be a vector of 3 elements representing the reduction\n## factors in the x-, y-, and z-directions or a scalar, in which case the same\n## reduction factor is used in all three dimensions.\n##\n## @code{reducevolume} reduces the number of elements of @var{v} by taking\n## only every @var{r}-th element in the respective dimension.\n##\n## Optionally, @var{x}, @var{y}, and @var{z} can be supplied to represent the\n## set of coordinates of @var{v}.  They can either be matrices of the same size\n## as @var{v} or vectors with sizes according to the dimensions of @var{v}, in\n## which case they are expanded to matrices\n## (@pxref{XREFmeshgrid,,@code{meshgrid}}).\n##\n## If @code{reducevolume} is called with two arguments then @var{x}, @var{y},\n## and @var{z} are assumed to match the respective indices of @var{v}.\n##\n## The reduced matrix is returned in @var{nv}.\n##\n## Optionally, the reduced set of coordinates are returned in @var{nx},\n## @var{ny}, and @var{nz}, respectively.\n##\n## Examples:\n##\n## @example\n## @group\n## @var{v} = reshape (1:6*8*4, [6 8 4]);\n## @var{nv} = reducevolume (@var{v}, [4 3 2]);\n## @end group\n## @end example\n##\n## @example\n## @group\n## @var{v} = reshape (1:6*8*4, [6 8 4]);\n## @var{x} = 1:3:24;  @var{y} = -14:5:11;  @var{z} = linspace (16, 18, 4);\n## [@var{nx}, @var{ny}, @var{nz}, @var{nv}] = reducevolume (@var{x}, @var{y}, @var{z}, @var{v}, [4 3 2]);\n## @end group\n## @end example\n##\n## @seealso{isosurface, isonormals}\n## @end deftypefn\n\nfunction [nx, ny, nz, nv] = reducevolume (varargin)\n\n  if (nargin < 2 || nargin > 5)\n    print_usage ();\n  endif\n\n  [x, y, z, v, r] = __get_check_reducevolume_args__ (nargout, varargin{:});\n\n  [nx, ny, nz, nv] = __reducevolume__ (x, y, z, v, r);\n\n  if (nargout <= 1)\n    nx = nv;\n  endif\n\nendfunction\n\nfunction [x, y, z, v, r] = __get_check_reducevolume_args__ (naout, varargin)\n\n  x = y = z = [];\n\n  switch (nargin)\n    case 3\n      v = varargin{1};\n      r = varargin{2};\n\n    case 6\n      if (naout == 4)\n        x = varargin{1};\n        y = varargin{2};\n        z = varargin{3};\n      endif\n      v = varargin{4};\n      r = varargin{5};\n\n    otherwise\n      error (\"reducevolume: incorrect number of arguments\");\n\n  endswitch\n\n  ## Check reduction values R\n  if (isscalar (r))\n    r = [r, r, r];\n  elseif (numel (r) != 3)\n    error ([\"reducevolume: reduction value R must be a scalar or \" ...\n            \"a vector of length 3\"]);\n  endif\n\n  if (any (r < 1 | r != fix (r)))\n    error (\"reducevolume: reduction values R must be positive integers\");\n  endif\n\n  ## Check dimensions of data\n  if (ndims (v) < 3)\n    error (\"reducevolume: data V must have at least 3 dimensions\");\n  endif\n\n  v_sz = size (v);\n  if (any (v_sz(1:3) < 2))\n    error (\"reducevolume: data must be a non-singleton 3-dimensional matrix\");\n  endif\n\n  if (naout == 4)\n    if (isempty (x))\n      x = 1:columns (v);\n    endif\n    if (isempty (y))\n      y = 1:rows (v);\n    endif\n    if (isempty (z))\n      z = 1:size (v, 3);\n    endif\n\n    ## check x\n    if (isvector (x) && length (x) == v_sz(2))\n      x = repmat (x(:)', [v_sz(1) 1 v_sz(3)]);\n    elseif (! size_equal (v, x))\n      error (\"reducevolume: X must match the size of data V\");\n    endif\n\n    ## check y\n    if (isvector (y) && length (y) == v_sz(1))\n      y = repmat (y(:), [1 v_sz(2) v_sz(3)]);\n    elseif (! size_equal (v, y))\n      error (\"reducevolume: Y must match the size of data V\");\n    endif\n\n    ## check z\n    if (isvector (z) && length (z) == v_sz(3))\n      z = repmat (reshape (z(:), [1 1 length(z)]), ...\n                  [v_sz(1) v_sz(2) 1]);\n    elseif (! size_equal (v, z))\n      error (\"reducevolume: Z must match the size of data V\");\n    endif\n\n  endif\n\nendfunction\n\nfunction [nx, ny, nz, nv] = __reducevolume__ (x, y, z, v, r)\n\n  v_sz = size (v);\n  nv = v(1:r(2):end, 1:r(1):end, 1:r(3):end, :);\n  nv_sz = size (nv);\n  if (length (nv_sz) < 3 || min (nv_sz) < 2)\n    error (\"reducevolume: reduction value R is too high\");\n  endif\n  if (length (v_sz) > 3)\n    nv = reshape (nv, [nv_sz(1:3) v_sz(4:end)]);\n  endif\n\n  if (isempty (x))\n    nx = ny = nz = [];\n  else\n    nx = x(1:r(2):end, 1:r(1):end, 1:r(3):end);\n    ny = y(1:r(2):end, 1:r(1):end, 1:r(3):end);\n    nz = z(1:r(2):end, 1:r(1):end, 1:r(3):end);\n  endif\n\nendfunction\n\n\n%!shared v, x, y, z, xx, yy, zz\n%! v = reshape (1:6*8*4, [6 8 4]);\n%! x = 1:3:22;  y = -14:5:11;  z = linspace (16, 18, 4);\n%! [xx, yy, zz] = meshgrid (x, y, z);\n\n## two inputs, one output\n%!test\n%! nv = reducevolume (v, [4 3 2]);\n%! nv_expected = [1 25; 4 28];  nv_expected(:,:,2) = [97 121; 100 124];\n%! assert (nv, nv_expected);\n\n## two inputs, four outputs\n%!test\n%! [nx, ny, nz, nv] = reducevolume (v, [4 3 2]);\n%! nx_expected(1:2,1,1:2) = 1;  nx_expected(:,2,:) = 5;\n%! ny_expected(1,1:2,1:2) = 1;  ny_expected(2,:,:) = 4;\n%! nz_expected(1:2,1:2,1) = 1;  nz_expected(:,:,2) = 3;\n%! nv_expected = [1 25; 4 28];  nv_expected(:,:,2) = [97 121; 100 124];\n%! assert (nx, nx_expected);\n%! assert (ny, ny_expected);\n%! assert (nz, nz_expected);\n%! assert (nv, nv_expected);\n\n## five inputs, one output\n%!test\n%! nv = reducevolume (x, y, z, v, [4 3 2]);\n%! nv_expected = [1 25; 4 28];  nv_expected(:,:,2) = [97 121; 100 124];\n%! assert (nv, nv_expected);\n\n## five inputs, four outputs (coordinates are vectors)\n%!test\n%! [nx, ny, nz, nv] = reducevolume (x, y, z, v, [4 3 2]);\n%! nx_expected(1:2,1,1:2) = x(1); nx_expected(:,2,:) = x(5);\n%! ny_expected(1,1:2,1:2) = y(1); ny_expected(2,:,:) = y(4);\n%! nz_expected(1:2,1:2,1) = z(1); nz_expected(:,:,2) = z(3);\n%! nv_expected = [1 25; 4 28]; nv_expected(:,:,2) = [97 121; 100 124];\n%! assert (nx, nx_expected);\n%! assert (ny, ny_expected);\n%! assert (nz, nz_expected);\n%! assert (nv, nv_expected);\n\n## five inputs, four outputs (coordinates are matrices)\n%!test\n%! [nx, ny, nz, nv] = reducevolume (xx, yy, zz, v, [4 3 2]);\n%! nx_expected(1:2,1,1:2) = x(1); nx_expected(:,2,:) = x(5);\n%! ny_expected(1,1:2,1:2) = y(1); ny_expected(2,:,:) = y(4);\n%! nz_expected(1:2,1:2,1) = z(1); nz_expected(:,:,2) = z(3);\n%! nv_expected = [1 25; 4 28]; nv_expected(:,:,2) = [97 121; 100 124];\n%! assert (nx, nx_expected);\n%! assert (ny, ny_expected);\n%! assert (nz, nz_expected);\n%! assert (nv, nv_expected);\n\n## five inputs, four outputs (coordinates are matrices, R is scalar)\n%!test\n%! [nx, ny, nz, nv] = reducevolume (xx, yy, zz, v, 3);\n%! nx_expected(1:2,1,1:2) = x(1); nx_expected(:,2,:) = x(4);\n%! nx_expected(:,3,:) = x(7);\n%! ny_expected(1,1:3,1:2) = y(1); ny_expected(2,:,:) = y(4);\n%! nz_expected(1:2,1:3,1) = z(1); nz_expected(:,:,2) = z(4);\n%! nv_expected = [1 19 37; 4 22 40];\n%! nv_expected(:,:,2) = [145 163 181; 148 166 184];\n%! assert (nx, nx_expected);\n%! assert (ny, ny_expected);\n%! assert (nz, nz_expected);\n%! assert (nv, nv_expected);\n\n## Test for each error\n%!test\n%!error <Invalid call> reducevolume ()\n%!error <Invalid call> reducevolume (1)\n%!error <Invalid call> reducevolume (1,2,3,4,5,6)\n%!error <incorrect number of arguments> reducevolume (1, 2, 3)\n%!error <R must be a scalar or a vector of length 3> reducevolume (v, [])\n%!error <R must be a scalar or a vector of length 3> reducevolume (v, [1 2])\n%!error <reduction values R must be positive integers> reducevolume (v, 0)\n%!error <reduction values R must be positive integers> reducevolume (v, 1.5)\n%!error <data V must have at least 3 dimensions>\n%! v = reshape(1:6*8, [6 8]);\n%! [nv] = reducevolume (v, [4 3 2]);\n%!error <data must be a non-singleton 3-dimensional matrix>\n%! v = reshape(1:6*8, [6 1 8]);\n%! nv = reducevolume (v, [4 3 2]);\n%!error <X must match the size of data V>\n%! x = 1:2:24;\n%! [nx, ny, nz, nv] = reducevolume (x, y, z, v, [4 3 2]);\n%!error <Y must match the size of data V>\n%! y = -14:6:11;\n%! [nx, ny, nz, nv] = reducevolume (x, y, z, v, [4 3 2]);\n%!error <Z must match the size of data V>\n%! z = linspace (16, 18, 5);\n%! [nx, ny, nz, nv] = reducevolume (x, y, z, v, [4 3 2]);\n%!error <reduction value R is too high> [nv] = reducevolume (v, 5)\n%!error <reduction value R is too high> [nv] = reducevolume (v, [4 7 2])\n"
  },
  {
    "path": "scripts/plot/draw/ribbon.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} ribbon (@var{y})\n## @deftypefnx {} {} ribbon (@var{x}, @var{y})\n## @deftypefnx {} {} ribbon (@var{x}, @var{y}, @var{width})\n## @deftypefnx {} {} ribbon (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} ribbon (@dots{})\n## Draw a ribbon plot for the columns of @var{y} vs.@: @var{x}.\n##\n## If @var{x} is omitted, a vector containing the row numbers is assumed\n## (@code{1:rows (Y)}).  Alternatively, @var{x} can also be a vector with\n## same number of elements as rows of @var{y} in which case the same\n## @var{x} is used for each column of @var{y}.\n##\n## The optional parameter @var{width} specifies the width of a single ribbon\n## (default is 0.75).\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of graphics handles to\n## the surface objects representing each ribbon.\n## @seealso{surface, waterfall}\n## @end deftypefn\n\nfunction h = ribbon (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"ribbon\", varargin{:});\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    y = varargin{1};\n    if (isvector (y))\n      y = y(:);\n    endif\n    x = 1:rows (y);\n    width = 0.75;\n  elseif (nargin == 2)\n    x = varargin{1};\n    y = varargin{2};\n    width = 0.75;\n  else\n    x = varargin{1};\n    y = varargin{2};\n    width = varargin{3};\n  endif\n\n  if (! size_equal (x, y))\n    if (! isvector (x) || rows (y) != numel (x))\n      error ([\"ribbon: X must have the same dimensions as Y or be a \"  ...\n              \"vector with the same number of rows as Y\"]);\n    endif\n    x = repmat (x(:), 1, columns (y));\n  endif\n\n  hax = newplot (hax);\n\n  [nr, nc] = size (y);\n  htmp = zeros (nc, 1);\n\n  for c = nc:-1:1\n    zz = [y(:,c), y(:,c)];\n    yy = x(:,c);\n    xx = [c - width / 2, c + width / 2];\n    [xx, yy] = meshgrid (xx, yy);\n    cc = repmat (c, size (zz));\n    htmp(c) = surface (hax, xx, yy, zz, cc);\n  endfor\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = sombrero ();\n%! ribbon (y, z);\n%! title (\"ribbon() plot of sombrero ()\");\n\n%!FIXME: Could have some input validation tests here\n"
  },
  {
    "path": "scripts/plot/draw/rose.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} rose (@var{theta})\n## @deftypefnx {} {} rose (@var{theta}, @var{nbins})\n## @deftypefnx {} {} rose (@var{theta}, @var{bins})\n## @deftypefnx {} {} rose (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} rose (@dots{})\n## @deftypefnx {} {[@var{th}, @var{r}] =} rose (@dots{})\n## Plot an angular histogram.\n##\n## With one vector argument, @var{th}, plot the histogram with 20 angular bins.\n## If @var{th} is a matrix then each column of @var{th} produces a separate\n## histogram.\n##\n## If @var{nbins} is given and is a scalar, then the histogram is produced with\n## @var{nbin} bins.  If @var{bins} is a vector, then the center of each bin is\n## defined by the values in @var{bins} and the number of bins is\n## given by the number of elements in @var{bins}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a vector of graphics handles to the\n## line objects representing each histogram.\n##\n## If two output arguments are requested then no plot is made and\n## the polar vectors necessary to plot the histogram are returned instead.\n##\n## Example\n##\n## @example\n## @group\n## [th, r] = rose ([2*randn(1e5,1), pi + 2*randn(1e5,1)]);\n## polar (th, r);\n## @end group\n## @end example\n##\n## @seealso{hist, polar}\n## @end deftypefn\n\n## Programming note: Ranges are calculated in degrees and then converted to\n## radians because the use of integers prevents accumulation of small errors\n## that result when using floating point directly.\n## The histogram counts are calculated using histc().  See the documentation.\n## The final count from histc() contains any values *exactly* equal to the\n## last bin edge which is always 2*pi.  Because the input mapping of\n## \"mod (th, 2*pi)\" changes any 2*pi values to 0, this last bin should always\n## be zero and can be safely deleted.\n\nfunction [thout, rout] = rose (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"rose\", varargin{:});\n\n  if (nargin < 1 || nargin > 2)\n    print_usage ();\n  endif\n\n  ## FIXME: Need input validation.  No check that inputs are even numeric!\n\n  ## Force theta to range [0,2*pi)\n  th = mod (varargin{1}, 2*pi);\n\n  custom_bins = false;\n  if (nargin == 1)\n    bins = [9 : 18 : 360] / 180 * pi;\n  else\n    bins = varargin{2};\n    if (isscalar (bins))\n      bins = [180/bins : 360/bins : 360] / 180 * pi;\n    else\n      custom_bins = true;\n      ## Force custom bins to [0,2*pi) range\n      bins = mod (bins, 2*pi);\n      bins = unique (bins);  # de-duplicate and sort bins\n      bins = bins(:).';      # Force row vector\n    endif\n  endif\n\n  binedge = bins(1:end-1) + diff (bins) / 2;  # halfway between bin centers\n  if (! custom_bins)\n    binedge = [0, binedge, 2*pi];  # Add implicit edges at 0, 2*pi\n    counts = histc (th, binedge);\n  else\n    last_binedge = bins(end) + diff ([bins(end), 2*pi+bins(1)]) / 2;\n    if (last_binedge >= 2*pi)\n      wraparound = true;\n      binedge = [0, last_binedge - 2*pi, binedge, 2*pi];\n      counts = histc (th, binedge);\n    else\n      wraparound = false;\n      binedge = [0, binedge, last_binedge, 2*pi];\n      counts = histc (th, binedge);\n    endif\n  endif\n\n  ## Use column vectors unless input contains multiple data series\n  if (isrow (counts))\n    counts = counts(:);\n  endif\n  counts(end,:) = [];              # remove overflow bin\n\n  if (custom_bins)\n    counts(end,:) += counts(1,:);  # Add first bin to wraparound bin\n    counts(1, :) = [];             # Remove first bin\n  endif\n\n  th = zeros (4 * rows (counts), 1);\n  if (! custom_bins)\n    binedge(end) = [];      # Remove inserted edge at 2*pi\n    th(2:4:end) = binedge;\n    th(3:4:end) = circshift (binedge, -1);\n  else\n    binedge([1,end]) = [];  # Remove inserted edges at 0, 2*pi\n    th(2:4:end) = binedge;\n    th(3:4:end) = circshift (binedge, -1);\n  endif\n  th(end-1) += 2*pi;        # For Matlab compatibility, wrap final edge\n\n  r = zeros (4 * rows (counts), columns (counts));\n  r(2:4:end, :) = counts;\n  r(3:4:end, :) = counts;\n\n  if (nargout < 2)\n    if (any (diff (bins) >= pi))\n      warning (\"rose: bin sizes >= pi will not plot correctly\");\n    endif\n\n    hax = newplot (hax);\n    htmp = polar (hax, th, r);\n\n    if (nargout > 0)\n      thout = htmp;\n    endif\n  else\n    thout = th;\n    rout = r;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! rose (2*randn (1e5, 1), 8);\n%! title (\"rose() angular histogram plot with 8 bins\");\n\n%!demo\n%! clf;\n%! rose ([2*randn(1e5, 1), pi + 2*randn(1e5, 1)]);\n%! title (\"rose() angular histogram plot with 2 data series\");\n\n%!demo\n%! clf;\n%! rose ([0, 2, 3, 5], [0, pi/2, pi, 3*pi/2]);\n%! title (\"rose() angular histogram plot with specified bins\");\n\n## Test mapping inputs to [0, 2*pi), 2*pi mapped to bin 1.\n%!test\n%! [t, r] = rose ([1:1:360]/180*pi + 2*pi);\n%! assert (diff (t(2:4:end)), 2*pi/20 * ones (19, 1));\n%! assert (r(2:4:end), 18*ones (20, 1));\n\n## Custom # of bins, values exactly at 0 and 2*pi go to bin 1\n%!test\n%! [t,r] = rose ([0, 2*pi], 4);\n%! assert (size (t), [16, 1]);\n%! assert (size (r), [16, 1]);\n%! assert ([t(2); t(3:4:end)], [0; pi/2; pi; 3*pi/2; 2*pi]);\n%! assert (r(2:4:end), [2; 0; 0; 0]);\n\n## Custom bin centers, values exactly at 0 and 2*pi go to bin 1\n%!test\n%! [t,r] = rose ([0,2*pi], deg2rad (45:90:360));\n%! assert (size (t), [16, 1]);\n%! assert (size (r), [16, 1]);\n%! assert (r(2:4:end), [2; 0; 0; 0]);\n%! assert ([t(2); t(3:4:end)], [0; pi/2; pi; 3*pi/2; 2*pi]);\n\n## Custom bins, synthesized bin1 edge is exactly 36 degrees (wraparound)\n%!test\n%! [t,r] = rose (deg2rad ([35, 36]), deg2rad ([90, 180, 270, 342]));\n%! assert (r(2:4:end), [1; 0; 0; 1]);\n%! assert (rad2deg (t(2:4:end)), [36; 135; 225; 306]);\n%! assert (rad2deg (t(end-1)), 396);\n\n## Custom bins, synthesized bin1 cut-off is exactly -36 degrees (no wrap)\n%!test\n%! [t,r] = rose (deg2rad ([-36, -37, 360]), deg2rad ([18, 90, 180, 270]));\n%! assert (r(2:4:end), [0; 0; 1; 2]);\n%! assert (rad2deg (t(2:4:end)), [54; 135; 225; 324]);\n%! assert (rad2deg (t(end-1)), 414);\n\n%!test <*67280>\n%! d = deg2rad (0:359) + 4*eps;  # uniformly spaced data around unit circle\n%! d = [d, repmat(deg2rad(4), [1,30])];  # Add 30 data points at 4 degrees\n%! [t,r] = rose (d, 30);\n%! assert (r(2), 42);   # All 30 data points went into bin 1.\n%! assert (t(2:3), [0; .2094], 1e-4);  # bin 1 starts at 0\n%! [t,r] = rose (d, deg2rad (0:12:348));\n%! assert (r(end-2), 42);   # All 30 data points went into last bin.\n%! assert (t(end-([2,1])), [6.1785; 6.3879], 1e-4);  # last bin centered at 0\n\n## Test input validation8\n%!error <Invalid call> rose ()\n%!error <Invalid call> rose (1,2,3)\n"
  },
  {
    "path": "scripts/plot/draw/scatter.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} scatter (@var{x}, @var{y})\n## @deftypefnx {} {} scatter (@var{x}, @var{y}, @var{s})\n## @deftypefnx {} {} scatter (@var{x}, @var{y}, @var{s}, @var{c})\n## @deftypefnx {} {} scatter (@dots{}, @var{style})\n## @deftypefnx {} {} scatter (@dots{}, \"filled\")\n## @deftypefnx {} {} scatter (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} scatter (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} scatter (@dots{})\n## Draw a 2-D scatter plot.\n##\n## A marker is plotted at each point defined by the coordinates in the vectors\n## @var{x} and @var{y}.\n##\n## The size of the markers is determined by @var{s}, which can be a scalar\n## or a vector of the same length as @var{x} and @var{y}.  If @var{s}\n## is not given, or is an empty matrix, then a default value of 36 square\n## points is used (The marker size itself is @code{sqrt (s)}).\n##\n## The color of the markers is determined by @var{c}, which can be a string\n## defining a fixed color; a 3-element vector giving the red, green, and blue\n## components of the color; a vector of the same length as @var{x} that gives\n## a scaled index into the current colormap; or an @nospell{Nx3} matrix\n## defining the RGB color of each marker individually.\n##\n## The marker to use can be changed with the @var{style} argument; it is a\n## string defining a marker in the same manner as the @code{plot} command.\n## If no marker is specified it defaults to @qcode{\"o\"} or circles.\n## If the argument @qcode{\"filled\"} is given then the markers are filled.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## scatter object.\n##\n## Example:\n##\n## @example\n## @group\n## x = randn (100, 1);\n## y = randn (100, 1);\n## scatter (x, y, [], sqrt (x.^2 + y.^2));\n## @end group\n## @end example\n##\n## Programming Note: The full list of properties is documented at\n## @ref{Scatter Properties}.\n## @seealso{scatter3, patch, plot}\n## @end deftypefn\n\nfunction h = scatter (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"scatter\", varargin{:});\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n\n  htmp = __scatter__ (hax, 2, \"scatter\", varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = randn (100, 1);\n%! y = randn (100, 1);\n%! scatter (x, y, \"r\");\n%! title (\"scatter() plot with red bubbles\");\n\n%!demo\n%! clf;\n%! x = randn (100, 1);\n%! y = randn (100, 1);\n%! c = x .* y;\n%! scatter (x, y, 50, c, \"filled\");\n%! title (\"scatter() with colored filled bubbles\");\n\n%!demo\n%! clf;\n%! x = randn (100, 1);\n%! y = randn (100, 1);\n%! scatter (x, y, [], sqrt (x.^2 + y.^2));\n%! title ({\"scatter() plot\"; ...\n%!         \"bubble color determined by distance from origin\"});\n\n%!demo\n%! clf;\n%! rand_10x1_data5 = [0.777753, 0.093848, 0.183162, 0.399499, 0.337997, 0.686724, 0.073906, 0.651808, 0.869273, 0.137949];\n%! rand_10x1_data6 = [0.37460, 0.25027, 0.19510, 0.51182, 0.54704, 0.56087, 0.24853, 0.75443, 0.42712, 0.44273];\n%! x = rand_10x1_data5;\n%! y = rand_10x1_data6;\n%! h = scatter (x, y, [], \"r\", \"s\");\n%! title ({\"scatter() plot\"; ...\n%!         \"color is red, marker is square\"});\n\n%!demo\n%! clf;\n%! rand_10x1_data3 = [0.42262, 0.51623, 0.65992, 0.14999, 0.68385, 0.55929, 0.52251, 0.92204, 0.19762, 0.93726];\n%! rand_10x1_data4 = [0.020207, 0.527193, 0.443472, 0.061683, 0.370277, 0.947349, 0.249591, 0.666304, 0.134247, 0.920356];\n%! x = rand_10x1_data3;\n%! y = rand_10x1_data4;\n%! h = scatter (x, y, [], \"r\", \"s\", \"filled\");\n%! title ({\"scatter() plot\"; ...\n%!         \"color is red, marker is square, marker is filled\"});\n\n%!demo\n%! clf;\n%! rand_10x1_data1 = [0.171577, 0.404796, 0.025469, 0.335309, 0.047814, 0.898480, 0.639599, 0.700247, 0.497798, 0.737940];\n%! rand_10x1_data2 = [0.75495, 0.83991, 0.80850, 0.73603, 0.19360, 0.72573, 0.69371, 0.74388, 0.13837, 0.54143];\n%! x = rand_10x1_data1;\n%! y = rand_10x1_data2;\n%! s = 36 - 30*log (x.^2 + y.^2);\n%! h = scatter (x, y, s, s, \"s\", \"filled\");\n%! title ({\"scatter() plot with filled square markers\", ...\n%!         \"size and color of markers determined by algorithm\"});\n\n%!demo\n%! clf;\n%! k = 1;\n%! for m = [1, 3]\n%!   for n = [101, 50, 1]\n%!     x = rand (n, 1);\n%!     y = rand (n, 1);\n%!     if (m > 1)\n%!       str = \"Three Colors\";\n%!       idx = ceil (rand (n, 1) * 3);\n%!       colors = eye (3);\n%!       colors = colors(idx, :);\n%!     else\n%!       str = \"Random Colors\";\n%!       colors = rand (n, m);\n%!     endif\n%!     if (n == 1)\n%!       str = sprintf (\"%s: 1 point\", str);\n%!     elseif (n < 100)\n%!       str = sprintf (\"%s: < 100 points\", str);\n%!     else\n%!       str = sprintf (\"%s: > 100 points\", str);\n%!     endif\n%!     subplot (2,3,k);\n%!     k = k + 1;\n%!     scatter (x, y, [], colors, \"filled\");\n%!     axis ([0 1 0 1]);\n%!     title (str);\n%!   endfor\n%! endfor\n\n%!demo\n%! clf;\n%! k = 1;\n%! for m = [1, 3]\n%!   for n = [101, 50, 1]\n%!     x = rand (n, 1);\n%!     y = rand (n, 1);\n%!     if (m > 1)\n%!       str = \"Three Colors\";\n%!       idx = ceil (rand (n, 1) * 3);\n%!       colors = eye (3);\n%!       colors = colors(idx, :);\n%!     else\n%!       str = \"Random Colors\";\n%!       colors = rand (n, m);\n%!     endif\n%!     if (n == 1)\n%!       str = sprintf (\"%s: 1 point\", str);\n%!     elseif (n < 100)\n%!       str = sprintf (\"%s: < 100 points\", str);\n%!     else\n%!       str = sprintf (\"%s: > 100 points\", str);\n%!     endif\n%!     subplot (2,3,k);\n%!     k = k + 1;\n%!     scatter (x, y, [], colors);\n%!     axis ([0 1 0 1]);\n%!     title (str);\n%!   endfor\n%! endfor\n\n\n%!testif ; ! strcmp (graphics_toolkit (), \"gnuplot\")\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hs = scatter ([], []);\n%!   assert (get (hs, \"type\"), \"scatter\");\n%!   assert (isempty (get (hs, \"xdata\")));\n%!   assert (isempty (get (hs, \"ydata\")));\n%!   assert (isempty (get (hs, \"zdata\")));\n%!   assert (get (hs, \"cdata\"), [0, 0.4470, 0.7410]);\n%!   assert (get (hs, \"cdatamode\"), \"auto\");\n%!   assert (get (hs, \"sizedata\"), 36);\n%!   assert (get (hs, \"linewidth\"), 0.5);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/scatter3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} scatter3 (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} scatter3 (@var{x}, @var{y}, @var{z}, @var{s})\n## @deftypefnx {} {} scatter3 (@var{x}, @var{y}, @var{z}, @var{s}, @var{c})\n## @deftypefnx {} {} scatter3 (@dots{}, @var{style})\n## @deftypefnx {} {} scatter3 (@dots{}, \"filled\")\n## @deftypefnx {} {} scatter3 (@dots{}, @var{prop}, @var{val})\n## @deftypefnx {} {} scatter3 (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} scatter3 (@dots{})\n## Draw a 3-D scatter plot.\n##\n## A marker is plotted at each point defined by the coordinates in the vectors\n## @var{x}, @var{y}, and @var{z}.\n##\n## The size of the markers is determined by @var{s}, which can be a scalar\n## or a vector of the same length as @var{x}, @var{y}, and @var{z}.  If @var{s}\n## is not given, or is an empty matrix, then a default value of 8 points is\n## used.\n##\n## The color of the markers is determined by @var{c}, which can be a string\n## defining a fixed color; a 3-element vector giving the red, green, and blue\n## components of the color; a vector of the same length as @var{x} that gives\n## a scaled index into the current colormap; or an @nospell{Nx3} matrix\n## defining the RGB color of each marker individually.\n##\n## The marker to use can be changed with the @var{style} argument, that is a\n## string defining a marker in the same manner as the @code{plot} command.\n## If no marker is specified it defaults to @qcode{\"o\"} or circles.\n## If the argument @qcode{\"filled\"} is given then the markers are filled.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the scatter\n## object representing the points.\n##\n## @example\n## @group\n## [x, y, z] = peaks (20);\n## scatter3 (x(:), y(:), z(:), [], z(:));\n## @end group\n## @end example\n##\n## Programming Note: The full list of properties is documented at\n## @ref{Scatter Properties}.\n## @seealso{scatter, patch, plot}\n## @end deftypefn\n\nfunction h = scatter3 (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"scatter3\", varargin{:});\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n\n  htmp = __scatter__ (hax, 3, \"scatter3\", varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x, y, z] = peaks (20);\n%! scatter3 (x(:), y(:), z(:), [], z(:));\n%! title ({\"Default scatter3() plot\", ...\n%!         \"constant size bubbles and color determined by Z\"});\n\n%!demo\n%! clf;\n%! x = rand (20,1);  y = rand (20,1);  z = rand (20,1);\n%! scatter3 (x(:), y(:), z(:), 10, z(:), \"s\");\n%! title ({\"scatter3() plot\", ...\n%!         \"marker is square, size is 10, color determined by Z\"});\n\n%!demo\n%! clf;\n%! x = rand (20,1);  y = rand (20,1);  z = rand (20,1);\n%! scatter3 (x(:), y(:), z(:), 20*z(:), [], \"s\");\n%! title ({\"scatter3() plot\", ...\n%!         \"marker is square, size is determined by Z\"});\n\n%!demo\n%! clf;\n%! x = rand (20,1);  y = rand (20,1);  z = rand (20,1);\n%! scatter3 (x(:), y(:), z(:), 20*z(:), z(:), \"s\");\n%! title ({\"scatter3() plot\", ...\n%!         \"marker is square, size and color determined by Z\"});\n"
  },
  {
    "path": "scripts/plot/draw/semilogx.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} semilogx (@var{y})\n## @deftypefnx {} {} semilogx (@var{x}, @var{y})\n## @deftypefnx {} {} semilogx (@var{x}, @var{y}, @var{property}, @var{value}, @dots{})\n## @deftypefnx {} {} semilogx (@var{x}, @var{y}, @var{fmt})\n## @deftypefnx {} {} semilogx (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} semilogx (@dots{})\n## Produce a 2-D plot using a logarithmic scale for the x-axis.\n##\n## See the documentation of @code{plot} for a description of the\n## arguments that @code{semilogx} will accept.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n## @seealso{plot, semilogy, loglog}\n## @end deftypefn\n\nfunction h = semilogx (varargin)\n\n  [hax, varargin, nargs] = __plt_get_axis_arg__ (\"semilogx\", varargin{:});\n\n  if (nargs < 1)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n\n  set (hax, \"xscale\", \"log\");\n  if (! ishold (hax))\n    set (hax, \"xminortick\", \"on\", \"box\", \"on\");\n  endif\n\n  htmp = __plt__ (\"semilogx\", hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = 1:0.01:10;\n%! y = (x .* (1 + rand (size (x)))) .^ 2;\n%! semilogx (y, x);\n%! title ({\"semilogx() plot\", \"X-axis is logarithmic\"});\n\n%!demo\n%! clf;\n%! x = logspace (-5, 1, 10);\n%! y = logspace (-5, 1, 10);\n%!\n%! subplot (1,2,1);\n%!  semilogx (x, y);\n%!  title (\"semilogx (x, y)\");\n%!\n%! subplot (1,2,2);\n%!  semilogx (-x, y);\n%!  title (\"semilogx (-x, y)\");\n\n%!demo\n%! clf;\n%! x = logspace (-5, 1, 10);\n%! y = logspace (-5, 1, 10);\n%!\n%! subplot (1,2,1);\n%!  semilogx (x, y);\n%!  set (gca, \"xdir\", \"reverse\", \"positionconstraint\", \"outerposition\");\n%!  title ({\"semilogx (x, y)\", \"xdir = reversed\"});\n%!\n%! subplot (1,2,2);\n%!  semilogx (-x, y);\n%!  set (gca, \"xdir\", \"reverse\", \"positionconstraint\", \"outerposition\");\n%!  title ({\"semilogx (-x, y)\", \"xdir = reversed\"});\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   a = logspace (-5, 1, 10);\n%!   b = logspace (-5, 1, 10);\n%!   semilogx (a, b);\n%!   assert (get (gca, \"xscale\"), \"log\");\n%!   assert (get (gca, \"yscale\"), \"linear\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   a =-logspace (-5, 1, 10);\n%!   b = logspace (-5, 1, 10);\n%!   semilogx (a, b);\n%!   axis tight;\n%!   assert (all (get (gca, \"xtick\") < 0));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/semilogxerr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} semilogxerr (@var{y}, @var{ey})\n## @deftypefnx {} {} semilogxerr (@var{y}, @dots{}, @var{fmt})\n## @deftypefnx {} {} semilogxerr (@var{x}, @var{y}, @var{ey})\n## @deftypefnx {} {} semilogxerr (@var{x}, @var{y}, @var{err}, @var{fmt})\n## @deftypefnx {} {} semilogxerr (@var{x}, @var{y}, @var{lerr}, @var{uerr}, @var{fmt})\n## @deftypefnx {} {} semilogxerr (@var{x}, @var{y}, @var{ex}, @var{ey}, @var{fmt})\n## @deftypefnx {} {} semilogxerr (@var{x}, @var{y}, @var{lx}, @var{ux}, @var{ly}, @var{uy}, @var{fmt})\n## @deftypefnx {} {} semilogxerr (@var{x1}, @var{y1}, @dots{}, @var{fmt}, @var{xn}, @var{yn}, @dots{})\n## @deftypefnx {} {} semilogxerr (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} semilogxerr (@dots{})\n## Produce 2-D plots using a logarithmic scale for the x-axis and errorbars\n## at each data point.\n##\n## Many different combinations of arguments are possible.  The most common\n## form is\n##\n## @example\n## semilogxerr (@var{x}, @var{y}, @var{ey}, @var{fmt})\n## @end example\n##\n## @noindent\n## which produces a semi-logarithmic plot of @var{y} versus @var{x} with errors\n## in the @var{y}-scale defined by @var{ey} and the plot format defined by\n## @var{fmt}.  @xref{XREFerrorbar,,errorbar}, for available formats and\n## additional information.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## @seealso{errorbar, semilogyerr, loglogerr}\n## @end deftypefn\n\nfunction h = semilogxerr (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"semilogxerr\", varargin{:});\n\n  hax = newplot (hax);\n\n  set (hax, \"xscale\", \"log\");\n  if (! ishold (hax))\n    set (hax, \"xminortick\", \"on\");\n  endif\n\n  htmp = __errplot__ (\"semilogxerr\", hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = exp (log (0.01):0.2:log (10));\n%! wblpdf = @(x, scl, shp) shp*(scl^-shp) .* x.^(shp-1) .* exp (-(x/scl).^shp);\n%! y = wblpdf (x, 2, 2);\n%! ey = 0.5*rand (size (y)) .* y;\n%! semilogxerr (x, y, ey, \"#~x-\");\n%! xlim (x([1, end]));\n%! title ({\"semilogxerr(): semilogx() plot with errorbars\", ...\n%!         \"X-axis is logarithmic\"});\n"
  },
  {
    "path": "scripts/plot/draw/semilogy.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} semilogy (@var{y})\n## @deftypefnx {} {} semilogy (@var{x}, @var{y})\n## @deftypefnx {} {} semilogy (@var{x}, @var{y}, @var{property}, @var{value}, @dots{})\n## @deftypefnx {} {} semilogy (@var{x}, @var{y}, @var{fmt})\n## @deftypefnx {} {} semilogy (@var{h}, @dots{})\n## @deftypefnx {} {@var{h} =} semilogy (@dots{})\n## Produce a 2-D plot using a logarithmic scale for the y-axis.\n##\n## See the documentation of @code{plot} for a description of the\n## arguments that @code{semilogy} will accept.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created plot.\n## @seealso{plot, semilogx, loglog}\n## @end deftypefn\n\nfunction h = semilogy (varargin)\n\n  [hax, varargin, nargs] = __plt_get_axis_arg__ (\"semilogy\", varargin{:});\n\n  if (nargs < 1)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n\n  set (hax, \"yscale\", \"log\");\n  if (! ishold (hax))\n    set (hax, \"yminortick\", \"on\", \"box\", \"on\");\n  endif\n\n  htmp = __plt__ (\"semilogy\", hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = 1:0.01:10;\n%! y = (x .* (1 + rand (size (x)))) .^ 2;\n%! semilogy (x, y);\n%! title ({\"semilogx() plot\", \"Y-axis is logarithmic\"});\n\n%!demo\n%! clf;\n%! x = logspace (-5, 1, 10);\n%! y = logspace (-5, 1, 10);\n%!\n%! subplot (2,1,1);\n%!  semilogy (x, y);\n%!  title (\"semilogy (x, y)\");\n%!\n%! subplot (2,1,2);\n%!  semilogy (x, -y);\n%!  title (\"semilogy (x, -y)\");\n\n%!demo\n%! clf;\n%! x = logspace (-5, 1, 10);\n%! y = logspace (-5, 1, 10);\n%!\n%! subplot (2,1,1);\n%!  semilogy (x, y);\n%!  set (gca, \"ydir\", \"reverse\", \"positionconstraint\", \"outerposition\");\n%!  title ({\"semilogy (x, y)\", \"ydir = reversed\"});\n%!\n%! subplot (2,1,2);\n%!  semilogy (x, -y);\n%!  set (gca, \"ydir\", \"reverse\", \"positionconstraint\", \"outerposition\");\n%!  title ({\"semilogy (x, -y)\", \"ydir = reversed\"});\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   a = logspace (-5, 1, 10);\n%!   b = logspace (-5, 1, 10);\n%!   semilogy (a, b);\n%!   assert (get (gca, \"yscale\"), \"log\");\n%!   assert (get (gca, \"xscale\"), \"linear\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   a = logspace (-5, 1, 10);\n%!   b =-logspace (-5, 1, 10);\n%!   semilogy (a, b);\n%!   axis tight;\n%!   assert (all (get (gca, \"ytick\") < 0));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/semilogyerr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} semilogyerr (@var{y}, @var{ey})\n## @deftypefnx {} {} semilogyerr (@var{y}, @dots{}, @var{fmt})\n## @deftypefnx {} {} semilogyerr (@var{x}, @var{y}, @var{ey})\n## @deftypefnx {} {} semilogyerr (@var{x}, @var{y}, @var{err}, @var{fmt})\n## @deftypefnx {} {} semilogyerr (@var{x}, @var{y}, @var{lerr}, @var{uerr}, @var{fmt})\n## @deftypefnx {} {} semilogyerr (@var{x}, @var{y}, @var{ex}, @var{ey}, @var{fmt})\n## @deftypefnx {} {} semilogyerr (@var{x}, @var{y}, @var{lx}, @var{ux}, @var{ly}, @var{uy}, @var{fmt})\n## @deftypefnx {} {} semilogyerr (@var{x1}, @var{y1}, @dots{}, @var{fmt}, @var{xn}, @var{yn}, @dots{})\n## @deftypefnx {} {} semilogyerr (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} semilogyerr (@dots{})\n## Produce 2-D plots using a logarithmic scale for the y-axis and errorbars\n## at each data point.\n##\n## Many different combinations of arguments are possible.  The most common\n## form is\n##\n## @example\n## semilogyerr (@var{x}, @var{y}, @var{ey}, @var{fmt})\n## @end example\n##\n## @noindent\n## which produces a semi-logarithmic plot of @var{y} versus @var{x} with errors\n## in the @var{y}-scale defined by @var{ey} and the plot format defined by\n## @var{fmt}.  @xref{XREFerrorbar,,errorbar}, for available formats and\n## additional information.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## @seealso{errorbar, semilogxerr, loglogerr}\n## @end deftypefn\n\nfunction h = semilogyerr (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"semilogyerr\", varargin{:});\n\n  hax = newplot (hax);\n\n  set (hax, \"yscale\", \"log\");\n  if (! ishold (hax))\n    set (hax, \"yminortick\", \"on\");\n  endif\n\n  htmp = __errplot__ (\"semilogyerr\", hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = 0.25:0.25:10;\n%! wblpdf = @(x, scl, shp) shp*(scl^-shp) .* x.^(shp-1) .* exp (-(x/scl).^shp);\n%! y = wblpdf (x, 4, 2);\n%! eyu = rand (size (y));\n%! eyl = 1.0 - 1./(1+eyu);\n%! semilogyerr (x, y, eyl.*y, eyu.*y, \"~-d\");\n%! xlim ([0 10]);\n%! title ({\"semilogyerr(): semilogy() plot with errorbars\", ...\n%!         \"Y-axis is logarithmic\"});\n"
  },
  {
    "path": "scripts/plot/draw/shrinkfaces.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} shrinkfaces (@var{p}, @var{sf})\n## @deftypefnx {} {@var{nfv} =} shrinkfaces (@var{p}, @var{sf})\n## @deftypefnx {} {@var{nfv} =} shrinkfaces (@var{fv}, @var{sf})\n## @deftypefnx {} {@var{nfv} =} shrinkfaces (@var{f}, @var{v}, @var{sf})\n## @deftypefnx {} {[@var{nf}, @var{nv}] =} shrinkfaces (@dots{})\n##\n## Reduce the size of faces in a patch by the shrink factor @var{sf}.\n##\n## The patch object can be specified by a graphics handle (@var{p}), a patch\n## structure (@var{fv}) with the fields @qcode{\"faces\"} and @qcode{\"vertices\"},\n## or as two separate matrices (@var{f}, @var{v}) of faces and vertices.\n##\n## The shrink factor @var{sf} is a positive number specifying the percentage\n## of the original area the new face will occupy.  If no factor is given the\n## default is 0.3 (a reduction to 30% of the original size).  A factor greater\n## than 1.0 will result in the expansion of faces.\n##\n## Given a patch handle as the first input argument and no output parameters,\n## perform the shrinking of the patch faces in place and redraw the patch.\n##\n## If called with one output argument, return a structure with fields\n## @qcode{\"faces\"}, @qcode{\"vertices\"}, and @qcode{\"facevertexcdata\"}\n## containing the data after shrinking.  This structure can be used directly\n## as an input argument to the @code{patch} function.\n##\n## @strong{Caution:}: Performing the shrink operation on faces which are not\n## convex can lead to undesirable results.\n##\n## Example: a triangulated 3/4 circle and the corresponding shrunken version.\n##\n## @example\n## @group\n## [phi r] = meshgrid (linspace (0, 1.5*pi, 16), linspace (1, 2, 4));\n## tri = delaunay (phi(:), r(:));\n## v = [r(:).*sin(phi(:)) r(:).*cos(phi(:))];\n## clf ()\n## p = patch (\"Faces\", tri, \"Vertices\", v, \"FaceColor\", \"none\");\n## fv = shrinkfaces (p);\n## patch (fv)\n## axis equal\n## grid on\n## @end group\n## @end example\n##\n## @seealso{patch}\n## @end deftypefn\n\nfunction [nf, nv] = shrinkfaces (varargin)\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  sf = 0.3;\n  colors = [];\n  p = varargin{1};\n\n  if (isscalar (p) && isgraphics (p, \"patch\") && nargin < 3)\n    faces = get (p, \"Faces\");\n    vertices = get (p, \"Vertices\");\n    colors = get (p, \"FaceVertexCData\");\n    if (nargin == 2)\n      sf = varargin{2};\n    endif\n  elseif (isstruct (p) && nargin < 3)\n    faces = p.faces;\n    vertices = p.vertices;\n    if (isfield (p, \"facevertexcdata\"))\n      colors = p.facevertexcdata;\n    endif\n    if (nargin == 2)\n      sf = varargin{2};\n    endif\n  elseif (ismatrix (p) && nargin >= 2 && ismatrix (varargin{2}))\n    faces = p;\n    vertices = varargin{2};\n    if (nargin == 3)\n      sf = varargin{3};\n    endif\n  else\n    print_usage ();\n  endif\n\n  if (! isscalar (sf) || sf <= 0)\n    error (\"shrinkfaces: scale factor must be a positive scalar\");\n  endif\n\n  nc = columns (vertices);\n  if (nc < 2 || nc > 3)\n    error (\"shrinkfaces: only 2-D and 3-D patches are supported\");\n  endif\n\n  m = columns (faces);\n  if (m < 3)\n    error (\"shrinkfaces: faces must consist of at least 3 vertices\");\n  endif\n\n  v = vertices(faces'(:), :);\n  if (isempty (colors) || rows (colors) == rows (faces))\n    c = colors;\n  elseif (rows (colors) == rows (vertices))\n    c = colors(faces'(:), :);\n  else\n    c = [];  # Discard inconsistent color data.\n  endif\n  sv = rows (v);\n  ## We have to deal with a possibly very large number of vertices, so use\n  ## sparse as midpoint (1/m, ..., 1/m) in generalized barycentric coordinates.\n  midpoints = full (kron (speye (sv / m), ones (m, m) / m) * sparse (v));\n  v = sqrt (sf) * (v - midpoints) + midpoints;\n  f = reshape (1:sv, m, sv / m)';\n\n  switch (nargout)\n    case 0\n      if (ishghandle (p))\n        ## avoid exceptions\n        set (p, \"FaceVertexCData\", [], \"CData\", [],\n                \"Vertices\", v, \"Faces\", f, \"FaceVertexCData\", c);\n      else\n        nf = struct (\"faces\", f, \"vertices\", v, \"facevertexcdata\", c);\n      endif\n    case 1\n      nf = struct (\"faces\", f, \"vertices\", v, \"facevertexcdata\", c);\n    case 2\n      nf = f;\n      nv = v;\n  endswitch\n\nendfunction\n\n\n%!demo\n%! clf;\n%! faces = [1 2 3; 1 3 4];\n%! vertices = [0 0; 1 0; 1 1; 0 1];\n%! patch (\"Faces\", faces, \"Vertices\", vertices, \"FaceColor\", \"none\");\n%! fv = shrinkfaces (faces, vertices, 0.25);\n%! patch (fv);\n%! axis auto;   # Kludge required for Octave\n%! axis equal;\n%! title (\"shrinkfaces() on triangular shapes\");\n\n%!demo\n%! clf;\n%! faces = [1 2 3 4; 5 6 7 8];\n%! vertices = [0 0; 1 0; 2 1; 1 1; 2 0; 3 0; 4 1; 3.5 1];\n%! patch (\"Faces\", faces, \"Vertices\", vertices, \"FaceColor\", \"none\");\n%! fv = shrinkfaces (faces, vertices, 0.25);\n%! patch (fv);\n%! axis auto;   # Kludge required for Octave\n%! axis equal;\n%! grid on;\n%! title (\"shrinkfaces() on rhomboid shapes\");\n\n%!demo\n%! clf;\n%! faces = [1 2 3 4];\n%! vertices = [-1 2; 0 0; 1 2; 0 1];\n%! patch (\"Faces\", faces, \"Vertices\", vertices, \"FaceColor\", \"none\");\n%! fv = shrinkfaces (faces, vertices, 0.25);\n%! patch (fv);\n%! axis auto;   # Kludge required for Octave\n%! axis equal;\n%! grid on;\n%! title (\"shrinkfaces() does not work on concave shapes\");\n\n%!demo\n%! clf;\n%! [phi r] = meshgrid (linspace (0, 1.5*pi, 16), linspace (1, 2, 4));\n%! tri = delaunay (phi(:), r(:));\n%! v = [r(:).*sin(phi(:)) r(:).*cos(phi(:))];\n%! p = patch (\"Faces\", tri, \"Vertices\", v, \"FaceColor\", \"none\");\n%! fv = shrinkfaces (p);\n%! patch (fv);\n%! axis auto;   # Kludge required for Octave\n%! axis equal;\n%! grid on;\n%! title (\"shrinkfaces() on 2-D complex shapes tessellated with triangles\");\n\n%!demo\n%! clf;\n%! N = 10;  # N intervals per axis\n%! [x, y, z] = meshgrid (linspace (-4,4,N+1));\n%! val = x.^3 + y.^3 + z.^3;\n%! fv = isosurface (x, y, z, val, 3, z, \"noshare\");\n%!\n%! p = patch (\"Faces\", fv.faces, \"Vertices\", fv.vertices, \"FaceVertexCData\", ...\n%!            fv.facevertexcdata, \"FaceColor\", \"interp\", \"EdgeColor\", \"black\");\n%! axis auto;   # Kludge required for Octave\n%! axis equal;\n%! view (115, 30);\n%! drawnow ();\n%! shrinkfaces (p, 0.6);\n%! title (\"shrinkfaces() on 3-D complex shapes\");\n\n%!shared faces, vertices, nfv, nfv2\n%! faces = [1 2 3];\n%! vertices = [0 0 0; 1 0 0; 1 1 0];\n%! nfv = shrinkfaces (faces, vertices, 0.7);\n%! nfv2 = shrinkfaces (nfv, 1/0.7);\n%!assert (isfield (nfv, \"faces\"))\n%!assert (isfield (nfv, \"vertices\"))\n%!assert (size (nfv.faces), [1 3])\n%!assert (size (nfv.vertices), [3 3])\n%!assert (norm (nfv2.vertices - vertices), 0, 2*eps)\n\n## Test input validation\n%!error <Invalid call> shrinkfaces ()\n%!error <Invalid call> shrinkfaces (1,2,3,4)\n%!error [a,b,c] = shrinkfaces (1)\n%!error <scale factor must be a positive scalar> shrinkfaces (nfv, ones (2))\n%!error <scale factor must be a positive scalar> shrinkfaces (nfv, 0)\n%!error <only 2-D and 3-D patches are supported> shrinkfaces (faces, ones (3,1))\n%!error <only 2-D and 3-D patches are supported> shrinkfaces (faces, ones (3,4))\n%!error <faces must consist of at least 3 vertices> shrinkfaces (faces(1:2), vertices)\n"
  },
  {
    "path": "scripts/plot/draw/slice.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} slice (@var{x}, @var{y}, @var{z}, @var{v}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} slice (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi})\n## @deftypefnx {} {} slice (@var{v}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} slice (@var{v}, @var{xi}, @var{yi}, @var{zi})\n## @deftypefnx {} {} slice (@dots{}, @var{method})\n## @deftypefnx {} {} slice (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} slice (@dots{})\n## Plot slices of 3-D data/scalar fields.\n##\n## Each element of the 3-dimensional array @var{v} represents a scalar value at\n## a location given by the parameters @var{x}, @var{y}, and @var{z}.  The\n## parameters @var{x}, @var{y}, and @var{z} are either 3-dimensional arrays of\n## the same size as the array @var{v} in the @qcode{\"meshgrid\"} format or\n## vectors.  The parameters @var{xi}, etc.@: respect a similar format to\n## @var{x}, etc., and they represent the points at which the array @var{vi}\n## is interpolated using interp3.  The vectors @var{sx}, @var{sy}, and\n## @var{sz} contain points of orthogonal slices of the respective axes.\n##\n## If @var{x}, @var{y}, @var{z} are omitted, they are assumed to be\n## @code{x = 1:size (@var{v}, 2)}, @code{y = 1:size (@var{v}, 1)} and\n## @code{z = 1:size (@var{v}, 3)}.\n##\n## @var{method} is one of:\n##\n## @table @asis\n## @item @qcode{\"nearest\"}\n## Return the nearest neighbor.\n##\n## @item @qcode{\"linear\"}\n## Linear interpolation from nearest neighbors.\n##\n## @item @qcode{\"cubic\"}\n## Cubic interpolation from four nearest neighbors (not implemented yet).\n##\n## @item @qcode{\"spline\"}\n## Cubic spline interpolation---smooth first and second derivatives\n## throughout the curve.\n## @end table\n##\n## The default method is @qcode{\"linear\"}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## Examples:\n##\n## @example\n## @group\n## [x, y, z] = meshgrid (linspace (-8, 8, 32));\n## v = sin (sqrt (x.^2 + y.^2 + z.^2)) ./ (sqrt (x.^2 + y.^2 + z.^2));\n## slice (x, y, z, v, [], 0, []);\n##\n## [xi, yi] = meshgrid (linspace (-7, 7));\n## zi = xi + yi;\n## slice (x, y, z, v, xi, yi, zi);\n## @end group\n## @end example\n## @seealso{interp3, surface, pcolor}\n## @end deftypefn\n\nfunction h = slice (varargin)\n\n  [hax, varargin, nargs] = __plt_get_axis_arg__ (\"slice\", varargin{:});\n\n  method = \"linear\";\n\n  if (ischar (varargin{end}))\n    method = varargin{end};\n    nargs -= 1;\n  endif\n\n  if (nargs == 4)\n    v = varargin{1};\n    if (ndims (v) != 3)\n      error (\"slice: V must be a 3-dimensional array of values\");\n    endif\n    [nx, ny, nz] = size (v);\n    [x, y, z] = meshgrid (1:nx, 1:ny, 1:nz);\n    sx = varargin{2};\n    sy = varargin{3};\n    sz = varargin{4};\n  elseif (nargs == 7)\n    v = varargin{4};\n    if (ndims (v) != 3)\n      error (\"slice: V must be a 3-dimensional array of values\");\n    endif\n    x = varargin{1};\n    y = varargin{2};\n    z = varargin{3};\n    if (isvector (x) && isvector (y) && isvector (z))\n      [x, y, z] = meshgrid (x, y, z);\n    elseif (ndims (x) == 3 && size_equal (x, y, z))\n      ## Do nothing.\n    else\n      error (\"slice: X, Y, Z size mismatch\");\n    endif\n    sx = varargin{5};\n    sy = varargin{6};\n    sz = varargin{7};\n  else\n    print_usage ();\n  endif\n\n  if (any ([isvector(sx), isvector(sy), isvector(sz)]))\n    have_sval = true;\n  elseif (ndims (sx) == 2 && size_equal (sx, sy, sz))\n    have_sval = false;\n  else\n    error (\"slice: dimensional mismatch for (XI, YI, ZI) or (SX, SY, SZ)\");\n  endif\n\n  hax = newplot (hax);\n\n  sidx = 1;\n  minv = min (v(:));\n  maxv = max (v(:));\n  set (hax, \"clim\", double ([minv, maxv]));\n\n  if (have_sval)\n    ns = length (sx) + length (sy) + length (sz);\n    hs = zeros (ns,1);\n    [ny, nx, nz] = size (v);\n    if (length (sz) > 0)\n      for i = 1:length (sz)\n        [xi, yi, zi] = meshgrid (squeeze (x(1,:,1)),\n                                 squeeze (y(:,1,1)), sz(i));\n        vz = squeeze (interp3 (x, y, z, v, xi, yi, zi, method));\n        htmp(sidx++) = surface (hax, xi, yi, sz(i) * ones (size (yi)), vz);\n      endfor\n    endif\n\n    if (length (sy) > 0)\n      for i = length (sy):-1:1\n        [xi, yi, zi] = meshgrid (squeeze (x(1,:,1)),\n                                 sy(i),\n                                 squeeze (z(1,1,:)));\n        vy = squeeze (interp3 (x, y, z, v, xi, yi, zi, method));\n        htmp(sidx++) = surface (hax, squeeze (xi),\n                                     squeeze (sy(i) * ones (size (zi))),\n                                     squeeze (zi), vy);\n      endfor\n    endif\n\n    if (length (sx) > 0)\n      for i = length (sx):-1:1\n        [xi, yi, zi] = meshgrid (sx(i), squeeze (y(:,1,1)), squeeze (z(1,1,:)));\n        vx = squeeze (interp3 (x, y, z, v, xi, yi, zi, method));\n        htmp(sidx++) = surface (hax, squeeze (sx(i) * ones (size (zi))),\n                                     squeeze (yi), squeeze (zi), vx);\n      endfor\n    endif\n  else\n    vi = interp3 (x, y, z, v, sx, sy, sz);\n    htmp = surface (hax, sx, sy, sz, vi);\n  endif\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30.0],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = meshgrid (linspace (-8, 8, 32));\n%! v = sin (sqrt (x.^2 + y.^2 + z.^2)) ./ (sqrt (x.^2 + y.^2 + z.^2));\n%! slice (x, y, z, v, [], 0, []);\n%! title (\"slice() demo #1\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = meshgrid (linspace (-8, 8, 32));\n%! v = sin (sqrt (x.^2 + y.^2 + z.^2)) ./ (sqrt (x.^2 + y.^2 + z.^2));\n%! [xi, yi] = meshgrid (linspace (-7, 7));\n%! zi = xi + yi;\n%! slice (x, y, z, v, xi, yi, zi);\n%! title (\"slice() demo #2\");\n"
  },
  {
    "path": "scripts/plot/draw/smooth3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{smoothed_data} =} smooth3 (@var{data})\n## @deftypefnx {} {@var{smoothed_data} =} smooth3 (@var{data}, @var{method})\n## @deftypefnx {} {@var{smoothed_data} =} smooth3 (@var{data}, @var{method}, @var{sz})\n## @deftypefnx {} {@var{smoothed_data} =} smooth3 (@var{data}, @var{method}, @var{sz}, @var{std_dev})\n## Smooth values of 3-dimensional matrix @var{data}.\n##\n## This function may be used, for example, to reduce the impact of noise in\n## @var{data} before calculating isosurfaces.\n##\n## @var{data} must be a non-singleton 3-dimensional matrix.  The output\n## @var{smoothed_data} is a matrix of the same size as @var{data}.\n##\n## The option input @var{method} determines which convolution kernel is used\n## for the smoothing process.  Possible choices:\n##\n## @table @asis\n## @item @qcode{\"box\"}, @qcode{\"b\"} (default)\n## a convolution kernel with sharp edges.\n##\n## @item @qcode{\"gaussian\"}, @qcode{\"g\"}\n## a convolution kernel that is represented by a non-correlated trivariate\n## normal distribution function.\n## @end table\n##\n## @var{sz} is either a 3-element vector specifying the size of the\n## convolution kernel in the x-, y- and z-directions, or a scalar.  In the\n## scalar case the same size is used for all three dimensions\n## (@code{[@var{sz}, @var{sz}, @var{sz}]}).  The default value is 3.\n##\n## If @var{method} is @qcode{\"gaussian\"} then the optional input @var{std_dev}\n## defines the standard deviation of the trivariate normal distribution\n## function.  @var{std_dev} is either a 3-element vector specifying the\n## standard deviation of the Gaussian convolution kernel in x-, y- and\n## z-directions, or a scalar.  In the scalar case the same value is used for\n## all three dimensions.  The default value is 0.65.\n##\n## @seealso{isosurface, isonormals, patch}\n## @end deftypefn\n\nfunction smoothed_data = smooth3 (data, method = \"box\", sz = 3, std_dev = 0.65)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  [data, kernel, sz, std_dev] = ...\n                        __parse_smooth3_args__ (data, method, sz, std_dev);\n\n  ## Manually pad data by replicating the values at the edges.\n  ## (convn would pad with zeros)\n  idx = cell (3, 1);\n  for i_dim = 1:3\n    sz_dim = size (data, i_dim);\n    pad_vec = ones (1, (sz(i_dim)-1)/2);\n    idx{i_dim} = [pad_vec 1:sz_dim sz_dim*pad_vec];\n  endfor\n  data_padded = data(idx{:});\n\n  smoothed_data = convn (data_padded, kernel, \"valid\");\n\nendfunction\n\nfunction [data, conv_kernel, sz, std_dev] = __parse_smooth3_args__ (data, method, sz, std_dev)\n\n  if (ndims (data) != 3)\n    error (\"smooth3: DATA must be a 3-D numeric matrix\");\n  endif\n\n  if (! isnumeric (data))\n    if (isinteger (data) || islogical (data))\n      data = double (data);\n    else\n      error (\"smooth3: DATA must be a 3-D numeric matrix\");\n    endif\n  endif\n\n  if (! ischar (method))\n    error (\"smooth3: METHOD must be a string\");\n  endif\n\n  if (! isreal (sz))\n    error (\"smooth3: SZ must be a real scalar or 3-element vector\");\n  elseif (isscalar (sz))\n    sz(1:3) = sz;\n  elseif (numel (sz) != 3)\n    error ([\"smooth3: SZ of the convolution kernel must be \" ...\n            \"a scalar or 3-element vector\"]);\n  endif\n  if (any (sz < 1) || any (rem (sz, 2) != 1))\n    error ([\"smooth3: SZ of the convolution kernel must consist \" ...\n            \"of positive odd integers\"]);\n  endif\n\n  switch (lower (method))\n    case {\"b\", \"box\"}\n      conv_kernel = ones (sz) / prod (sz);\n\n    case {\"g\", \"gaussian\"}\n      ## check std_dev\n      if (! isreal (std_dev))\n        error (\"smooth3: STD_DEV must be a real scalar or 3-element vector\");\n      elseif (isscalar (std_dev))\n        std_dev(1:3) = std_dev;\n      elseif (numel (std_dev) != 3)\n        error ([\"smooth3: STD_DEV of the Gaussian convolution kernel \" ...\n                \"must be scalar or 3-element vector\"]);\n      endif\n\n      conv_kernel = __smooth3_gaussian3__ (sz, std_dev);\n\n    otherwise\n      error (\"smooth3: invalid METHOD '%s'\", method);\n\n  endswitch\n\nendfunction\n\nfunction gaussian3 = __smooth3_gaussian3__ (sz, std_dev)\n\n  ## trivariate non-correlated Gaussian distribution function\n  x = (-(sz(2)-1)/2:(sz(2)-1)/2) / std_dev(2);\n  y = (-(sz(1)-1)/2:(sz(1)-1)/2) / std_dev(1);\n  z = (-(sz(3)-1)/2:(sz(3)-1)/2) / std_dev(3);\n\n  [xx, yy, zz] = meshgrid (x, y, z);\n\n  gaussian3 = exp (-(xx.^2 + yy.^2 + zz.^2)/2);\n\n  gaussian3 /= sum (gaussian3(:));  # normalize\n\nendfunction\n\n\n%!demo\n%! hf = clf;\n%! [x, y, z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);\n%! data = (x.^2 + y.^2 + z.^2) + randn (size (x)) * 0.003;\n%! hax(1) = subplot (1, 2, 1, \"parent\", hf);\n%! patch (hax(1), isosurface (data, .035), ...\n%!        \"facecolor\", \"g\", \"edgecolor\", \"none\");\n%! title (hax(1), \"Original data (including random noise)\");\n%! axis (hax(1), \"vis3d\");\n%! grid (hax(1), \"on\");\n%! light (hax(1));\n%!\n%! smoothed_data = smooth3 (data, \"g\");\n%! hax(2) = subplot (1, 2, 2, \"parent\", hf);\n%! patch (hax(2), isosurface (smoothed_data, .035), ...\n%!         \"facecolor\", \"g\", \"edgecolor\", \"none\");\n%! title (hax(2), \"Smoothed data\");\n%! axis (hax(2), \"vis3d\");\n%! grid (hax(2), \"on\");\n%! light (hax(2));\n%!\n%! hlink = linkprop (hax, \"view\");\n%! set (hax(1), \"userdata\", hlink);  # keep hlink until figure is closed\n%! view (hax(1), 3);\n%! rotate3d (hf, \"on\");\n\n## one input argument (method: \"box\")\n%!test\n%! a = rand (10, 8, 7);\n%! b = smooth3 (a);\n%! assert (size_equal (a, b), true);\n\n## data type of first input argument\n%!test <*57276>\n%! dt_a = {\"double\", \"single\", \"uint8\", \"int8\", \"uint16\", \"int16\", ...\n%!         \"uint32\", \"int32\", \"uint64\", \"int64\", \"logical\"};\n%! dt_b = {\"double\", \"single\", \"double\", \"double\", \"double\", \"double\", ...\n%!         \"double\", \"double\", \"double\", \"double\", \"double\"};\n%! for i = 1 : numel (dt_a)\n%!   a = ones (3, 4, 5, dt_a{i});\n%!   b = smooth3 (a);\n%!   assert (class (b), dt_b{i});\n%! endfor\n\n## two input argument (method: \"gaussian\")\n%!test\n%! a = rand (5, 8, 7);\n%! b = smooth3 (a, \"gaussian\");\n%! assert (size_equal (a, b), true);\n\n## three input argument (method: \"box\")\n%!test\n%! a = rand (3, 8, 7);\n%! b = smooth3 (a, \"box\", 5);\n%! assert (size_equal (a, b), true);\n\n## three input argument (method: \"gaussian\")\n%!test\n%! a = rand (3, 8, 7);\n%! b = smooth3 (a, \"gaussian\", 7);\n%! assert (size_equal (a, b), true);\n\n## size of convolution kernel = 1: no smoothing (method: \"box\")\n%!test\n%! a = rand (9, 8, 7);\n%! b = smooth3 (a, \"box\", 1);\n%! assert (a, b);\n\n## size of convolution kernel = 1: no smoothing (method: \"gaussian\")\n%!test\n%! a = rand (9, 8, 7);\n%! b = smooth3 (a, \"gaussian\", 1);\n%! assert (a, b);\n\n## four input arguments (method: \"gaussian\")\n%!test\n%! a = rand (3, 8, 7);\n%! b = smooth3 (a, \"gaussian\", 7, .5);\n%! assert (size_equal (a, b), true);\n\n## size of convolution kernel is different in x, y and z (method: \"box\")\n%!test\n%! a = rand (3, 8, 7);\n%! b = smooth3 (a, \"box\", [5 3 7]);\n%! assert (size_equal (a, b), true);\n\n## size of convolution kernel is different in x, y and z (method: \"gaussian\")\n%!test\n%! a = rand (3, 8, 7);\n%! b = smooth3 (a, \"gaussian\", [5 3 7]);\n%! assert (size_equal (a, b), true);\n\n## size and width of gaussian convolution kernel is different in x, y and z\n## (method: \"gaussian\")\n%!test\n%! a = rand (3, 8, 7);\n%! b = smooth3 (a, \"gaussian\", [7 3 5], [.3 .5 .4]);\n%! assert (size_equal (a, b), true);\n\n## Test input validation\n%!error <Invalid call> smooth3 ()\n%!error <DATA must be a 3-D numeric matrix> smooth3 (cell (2,2,2))\n%!error <DATA must be a 3-D numeric matrix> smooth3 (1)\n%!error <METHOD must be a string> smooth3 (ones (2,2,2), {3})\n%!error <SZ must be a real> smooth3 (ones (2,2,2), \"b\", {3})\n%!error <SZ .* must be .* 3-element vector> smooth3 (ones (2,2,2), :, [3 5])\n%!error <SZ .* must .* positive .* integers> smooth3 (ones (2,2,2), :, [3 0 5])\n%!error <SZ .* must .* odd integers> smooth3 (ones (2,2,2), :, [3 2 5])\n%!error <STD_DEV must be a real> smooth3 (ones (2,2,2), \"g\", :, {0.65})\n%!error <STD_DEV .* must be .* 3-element> smooth3 (ones (2,2,2), \"g\", :, [1 2])\n%!error <invalid METHOD 'foobar'> smooth3 (ones (2,2,2), \"foobar\")\n"
  },
  {
    "path": "scripts/plot/draw/sombrero.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} sombrero ()\n## @deftypefnx {} {} sombrero (@var{n})\n## @deftypefnx {} {@var{z} =} sombrero (@dots{})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} sombrero (@dots{})\n## Plot the familiar 3-D sombrero function.\n##\n## The function plotted is\n## @tex\n## $$z = { \\rm{sin} (\\sqrt {(x^2 + y^2)}) \\over \\sqrt {(x^2 + y^2)} }$$\n## @end tex\n## @ifnottex\n##\n## @example\n## z = sin (sqrt (x^2 + y^2)) / (sqrt (x^2 + y^2))\n## @end example\n##\n## @end ifnottex\n## Called without a return argument, @code{sombrero} plots the surface of the\n## above function over the meshgrid [-8,8] using @code{surf}.\n##\n## If @var{n} is a scalar the plot is made with @var{n} grid lines.\n## The default value for @var{n} is 41.\n##\n## When called with output arguments, return the data for the function\n## evaluated over the meshgrid.  This can subsequently be plotted with\n## @code{surf (@var{x}, @var{y}, @var{z})}.\n##\n## @seealso{peaks, meshgrid, mesh, surf}\n## @end deftypefn\n\nfunction [x, y, z] = sombrero (n = 41)\n\n  if (n <= 1)\n    error (\"sombrero: number of grid lines N must be greater than 1\");\n  endif\n\n  [xx, yy] = meshgrid (linspace (-8, 8, n));\n  r = sqrt (xx.^2 + yy.^2) + eps;  # eps prevents div/0 errors\n  zz = sin (r) ./ r;\n\n  if (nargout == 0)\n    surf (xx, yy, zz);\n  elseif (nargout == 1)\n    x = zz;\n  else\n    x = xx;\n    y = yy;\n    z = zz;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! sombrero ();\n%! title (\"sombrero() function\");\n\n## Test input validation\n%!error sombrero (1,2,3)\n%!error <N must be greater than 1> sombrero (1)\n"
  },
  {
    "path": "scripts/plot/draw/sphere.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} sphere ()\n## @deftypefnx {} {} sphere (@var{n})\n## @deftypefnx {} {} sphere (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} sphere (@dots{})\n## Plot a 3-D unit sphere.\n##\n## The optional input @var{n} determines the number of faces around the\n## circumference of the sphere.  The default value is 20.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## If outputs are requested @code{sphere} returns three matrices in\n## @code{meshgrid} format such that @code{surf (@var{x}, @var{y}, @var{z})}\n## generates a unit sphere.\n##\n## Example:\n##\n## @example\n## @group\n## [x, y, z] = sphere (40);\n## surf (3*x, 3*y, 3*z);\n## axis equal;\n## title (\"sphere of radius 3\");\n## @end group\n## @end example\n## @seealso{cylinder, ellipsoid, rectangle}\n## @end deftypefn\n\nfunction [x, y, z] = sphere (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"sphere\", varargin{:});\n\n  if (nargin > 1)\n    print_usage ();\n  elseif (nargin == 1)\n    n = varargin{1};\n    if (! (isreal (n) && isscalar (n) && n > 0))\n      error (\"sphere: N must be a real scalar > 0\");\n    endif\n  else\n    n = 20;\n  endif\n\n  theta = linspace (0, 2*pi, n+1);\n  phi = linspace (-pi/2, pi/2, n+1);\n  [theta, phi] = meshgrid (theta, phi);\n\n  xx = cos (phi) .* cos (theta);\n  yy = cos (phi) .* sin (theta);\n  zz = sin (phi);\n\n  if (nargout > 0)\n    x = xx;\n    y = yy;\n    z = zz;\n  else\n    hax = newplot (hax);\n\n    surf (hax, xx, yy, zz);\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = sphere (40);\n%! surf (3*x, 3*y, 3*z);\n%! axis equal;\n%! title (\"sphere of radius 3\");\n\n## Test input validation\n%!error <Invalid call> sphere (-1,1)\n%!error <N must be a real scalar> sphere (2i)\n%!error <N must be a real scalar> sphere ([])\n%!error <N must be a real scalar> sphere (ones (2,2))\n%!error <N must be a real scalar . 0> sphere (-1)\n"
  },
  {
    "path": "scripts/plot/draw/stairs.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} stairs (@var{y})\n## @deftypefnx {} {} stairs (@var{x}, @var{y})\n## @deftypefnx {} {} stairs (@dots{}, @var{style})\n## @deftypefnx {} {} stairs (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} stairs (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} stairs (@dots{})\n## @deftypefnx {} {[@var{xstep}, @var{ystep}] =} stairs (@dots{})\n## Produce a stairstep plot.\n##\n## The arguments @var{x} and @var{y} may be vectors or matrices.\n## If only one argument is given, it is taken as a vector of Y values\n## and the X coordinates are taken to be the indices of the elements\n## (@code{@var{x} = 1:numel (@var{y})}).\n##\n## The style to use for the plot can be defined with a line style @var{style}\n## of the same format as the @code{plot} command.\n##\n## Multiple property/value pairs may be specified, but they must appear in\n## pairs.  The full list of properties is documented at @ref{Line Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## If one output argument is requested, return a graphics handle to the\n## created plot.  If two output arguments are specified, the data are generated\n## but not plotted.  For example,\n##\n## @example\n## stairs (x, y);\n## @end example\n##\n## @noindent\n## and\n##\n## @example\n## @group\n## [xs, ys] = stairs (x, y);\n## plot (xs, ys);\n## @end group\n## @end example\n##\n## @noindent\n## are equivalent.\n## @seealso{bar, hist, plot, stem}\n## @end deftypefn\n\nfunction [xstep, ystep] = stairs (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"stairs\", varargin{:});\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargout < 2)\n    hax = newplot (hax);\n    htmp = __stairs__ (true, hax, varargin{:});\n\n    if (! ishold (hax))\n      set (hax, \"box\", \"on\");\n    endif\n\n    if (nargout == 1)\n      xstep = htmp;\n    endif\n  else\n    [~, xstep, ystep] = __stairs__ (false, [], varargin{:});\n  endif\n\nendfunction\n\nfunction [h, xs, ys] = __stairs__ (doplot, hax, varargin)\n\n  if (nargin == 3 || ischar (varargin{2}))\n    y = varargin{1};\n    varargin(1) = [];\n    if (! isnumeric (y) || ndims (y) > 2)\n      error (\"stairs: Y must be a numeric 2-D vector or matrix\");\n    endif\n    if (isvector (y))\n      y = y(:);\n    endif\n    x = 1:rows (y);\n  else\n    x = varargin{1};\n    y = varargin{2};\n    varargin(1:2) = [];\n    if (! isnumeric (x) || ! isnumeric (y) || ndims (x) > 2 || ndims (y) > 2)\n      error (\"stairs: X and Y must be numeric 2-D vectors or matrices\");\n    endif\n  endif\n\n  vec_x = isvector (x);\n  if (vec_x)\n    x = x(:);\n  endif\n\n  if (isvector (y))\n    y = y(:);\n  elseif (isnumeric (y) && vec_x)\n    x = repmat (x, [1, columns(y)]);\n  endif\n\n  if (! size_equal (x, y))\n    error (\"stairs: X and Y sizes must match\");\n  endif\n\n  [nr, nc] = size (y);\n\n  len = 2*nr - 1;\n\n  xs = ys = zeros (len, nc);\n\n  xs(1,:) = x(1,:);\n  ys(1,:) = y(1,:);\n\n  xtmp = x(2:nr,:);\n  ridx = 2:2:len-1;\n  xs(ridx,:) = xtmp;\n  ys(ridx,:) = y(1:nr-1,:);\n\n  ridx = 3:2:len;\n  xs(ridx,:) = xtmp;\n  ys(ridx,:) = y(2:nr,:);\n\n  have_line_spec = false;\n  for i = 1:2:numel (varargin)\n    arg = varargin{i};\n    if (ischar (arg) || iscellstr (arg))\n      [linespec, valid] = __pltopt__ (\"stairs\", arg, false);\n      if (valid)\n        have_line_spec = true;\n        varargin(i) = [];\n        break;\n      endif\n    endif\n  endfor\n\n  if (doplot)\n    h = [];\n    hold_state = get (hax, \"nextplot\");\n    unwind_protect\n      for i = 1 : columns (y)\n\n        if (have_line_spec)\n          lc = linespec.color;\n          if (isempty (lc))\n            lc = __next_line_color__ (hax);\n          endif\n          ls = linespec.linestyle;\n          if (isempty (ls))\n            ls = \"-\";\n          endif\n          mk = linespec.marker;\n          if (isempty (mk))\n            mk = \"none\";\n          endif\n        else\n          lc = __next_line_color__ (hax);\n          ls = \"-\";\n          mk = \"none\";\n        endif\n\n        ## Must occur after __next_line_color__ in order to work correctly.\n        hg = hggroup (hax);\n        h = [h; hg];\n        args = __add_datasource__ (\"stairs\", hg, {\"x\", \"y\"}, varargin{:});\n\n        addproperty (\"xdata\", hg, \"data\", x(:,i).');\n        addproperty (\"ydata\", hg, \"data\", y(:,i).');\n\n        addlistener (hg, \"xdata\", @update_data);\n        addlistener (hg, \"ydata\", @update_data);\n\n        htmp = line (hax, xs(:,i).', ys(:,i).', \"color\", lc, \"linestyle\", ls,\n                                                \"marker\", mk, \"parent\", hg);\n\n        addproperty (\"color\", hg, \"linecolor\", get (htmp, \"color\"));\n        addproperty (\"linestyle\", hg, \"linelinestyle\", get (htmp, \"linestyle\"));\n        addproperty (\"linewidth\", hg, \"linelinewidth\", get (htmp, \"linewidth\"));\n\n        addproperty (\"marker\", hg, \"linemarker\", get (htmp, \"marker\"));\n        addproperty (\"markeredgecolor\", hg, \"linemarkeredgecolor\",\n                     get (htmp, \"markeredgecolor\"));\n        addproperty (\"markerfacecolor\", hg, \"linemarkerfacecolor\",\n                     get (htmp, \"markerfacecolor\"));\n        addproperty (\"markersize\", hg, \"linemarkersize\",\n                     get (htmp, \"markersize\"));\n\n        addlistener (hg, \"color\", @update_props);\n        addlistener (hg, \"linestyle\", @update_props);\n        addlistener (hg, \"linewidth\", @update_props);\n        addlistener (hg, \"marker\", @update_props);\n        addlistener (hg, \"markeredgecolor\", @update_props);\n        addlistener (hg, \"markerfacecolor\", @update_props);\n        addlistener (hg, \"markersize\", @update_props);\n\n        ## Matlab property, although Octave does not implement it.\n        addproperty (\"hittestarea\", hg, \"radio\", \"on|{off}\", \"off\");\n\n        if (! isempty (args))\n          set (hg, args{:});\n        endif\n      endfor\n    unwind_protect_cleanup\n      set (hax, \"nextplot\", hold_state);\n    end_unwind_protect\n  else\n    h = 0;\n  endif\n\nendfunction\n\nfunction update_props (h, ~)\n  set (get (h, \"children\"),\n       {\"color\", \"linestyle\", \"linewidth\", \"marker\", ...\n        \"markeredgecolor\", \"markerfacecolor\", \"markersize\"},\n       get (h, {\"color\", \"linestyle\", \"linewidth\", \"marker\", ...\n                \"markeredgecolor\", \"markerfacecolor\", \"markersize\"}));\nendfunction\n\nfunction update_data (h, ~)\n\n  x = get (h, \"xdata\");\n  y = get (h, \"ydata\");\n\n  sz = min ([size(x); size(y)]);\n  x = x(1:sz(1), 1:sz(2));\n  y = y(1:sz(1), 1:sz(2));\n\n  nr = length (x);\n  len = 2 * nr - 1;\n  xs = ys = zeros (1, len);\n\n  xs(1) = x(1);\n  ys(1) = y(1);\n\n  xtmp = x(2:nr);\n  ridx = 2:2:len-1;\n  xs(ridx) = xtmp;\n  ys(ridx) = y(1:nr-1);\n\n  ridx = 3:2:len;\n  xs(ridx) = xtmp;\n  ys(ridx) = y(2:nr);\n\n  set (get (h, \"children\"), \"xdata\", xs, \"ydata\", ys);\n\nendfunction\n\n\n%!demo\n%! clf;\n%! rand_1x10_data1 = [0.073, 0.455, 0.837, 0.124, 0.426, 0.781, 0.004, 0.024, 0.519, 0.698];\n%! y = rand_1x10_data1;\n%! stairs (y);\n%! title ('stairs() plot of y-data');\n\n%!demo\n%! clf;\n%! x = 1:10;\n%! rand_1x10_data2 = [0.014, 0.460, 0.622, 0.394, 0.531, 0.378, 0.466, 0.788, 0.342, 0.893];\n%! y = rand_1x10_data2;\n%! [xs, ys] = stairs (x, y);\n%! plot (xs, ys);\n%! title (\"plot() of stairs() generated data\");\n\n%!demo\n%! clf;\n%! stairs (1:9, \"-o\");\n%! title (\"stairs() plot with linespec to modify marker\");\n\n%!demo\n%! clf;\n%! stairs (9:-1:1, \"marker\", \"s\", \"markersize\", 10, \"markerfacecolor\", \"m\");\n%! title (\"stairs() plot with prop/val pairs to modify appearance\");\n\n%!demo\n%! clf;\n%! N = 11;\n%! x = 0:(N-1);\n%! y = rand (1, N);\n%! hs = stairs (x(1), y(1));\n%! axis ([1, N-1 0, 1]);\n%! title (\"stairs plot data modified through handle\");\n%! for k = 2:N\n%!   set (hs, \"xdata\", x(1:k), \"ydata\", y(1:k));\n%!   drawnow ();\n%!   pause (0.2);\n%! endfor\n\n## Invisible figure used for tests\n%!shared hf, hax\n%! hf = figure (\"visible\", \"off\");\n%! hax = axes ();\n\n%!error <Invalid call> stairs ()\n%!error <Y must be a numeric 2-D vector> stairs (hax, {1})\n%!error <Y must be a numeric 2-D vector> stairs (ones (2,2,2))\n%!error <X and Y must be numeric 2-D vector> stairs ({1}, 1)\n%!error <X and Y must be numeric 2-D vector> stairs (1, {1})\n%!error <X and Y must be numeric 2-D vector> stairs (ones (2,2,2), 1)\n%!error <X and Y must be numeric 2-D vector> stairs (1, ones (2,2,2))\n%!error <X and Y sizes must match> stairs (1:2, 1:3)\n\n## Close figure used for testing\n%!test\n%! close (hf);\n"
  },
  {
    "path": "scripts/plot/draw/stem.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} stem (@var{y})\n## @deftypefnx {} {} stem (@var{x}, @var{y})\n## @deftypefnx {} {} stem (@dots{}, @var{linespec})\n## @deftypefnx {} {} stem (@dots{}, \"filled\")\n## @deftypefnx {} {} stem (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} stem (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} stem (@dots{})\n## Plot a 2-D stem graph.\n##\n## If only one argument is given, it is taken as the y-values and the\n## x-coordinates are taken from the indices of the elements.\n##\n## If @var{y} is a matrix, then each column of the matrix is plotted as\n## a separate stem graph.  In this case @var{x} can either be a vector,\n## the same length as the number of rows in @var{y}, or it can be a\n## matrix of the same size as @var{y}.\n##\n## The default color is @qcode{\"b\"} (blue), the default line style is\n## @qcode{\"-\"}, and the default marker is @qcode{\"o\"}.  The line style can\n## be altered by the @var{linespec} argument in the same manner as the\n## @code{plot} command.  If the @qcode{\"filled\"} argument is present the\n## markers at the top of the stems will be filled in.  For example,\n##\n## @example\n## @group\n## x = 1:10;\n## y = 2*x;\n## stem (x, y, \"r\");\n## @end group\n## @end example\n##\n## @noindent\n## plots 10 stems with heights from 2 to 20 in red;\n##\n## Optional property/value pairs may be specified to control the appearance\n## of the plot.  The full list of properties is documented at\n## @ref{Line Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a handle to a @nospell{\"stem series\"}\n## hggroup.  The single hggroup handle has all of the graphical elements\n## comprising the plot as its children; This allows the properties of\n## multiple graphics objects to be changed by modifying just a single\n## property of the @nospell{\"stem series\"} hggroup.\n##\n## For example,\n##\n## @example\n## @group\n## x = [0:10]';\n## y = [sin(x), cos(x)]\n## h = stem (x, y);\n## set (h(2), \"color\", \"g\");\n## set (h(1), \"basevalue\", -1)\n## @end group\n## @end example\n##\n## @noindent\n## changes the color of the second @nospell{\"stem series\"} and moves the base\n## line of the first.\n##\n## Stem Series Properties\n##\n## @table @asis\n## @item linestyle\n## The linestyle of the stem.  (Default: @qcode{\"-\"})\n##\n## @item linewidth\n## The width of the stem.  (Default: 0.5)\n##\n## @item color\n## The color of the stem, and if not separately specified, the marker.\n## (Default: @qcode{\"b\"} [blue])\n##\n## @item marker\n## The marker symbol to use at the top of each stem.  (Default: @qcode{\"o\"})\n##\n## @item markeredgecolor\n## The edge color of the marker.  (Default: @qcode{\"color\"} property)\n##\n## @item markerfacecolor\n## The color to use for @nospell{\"filling\"} the marker.\n## (Default: @qcode{\"none\"} [unfilled])\n##\n## @item markersize\n## The size of the marker.  (Default: 6)\n##\n## @item baseline\n## The handle of the line object which implements the baseline.  Use @code{set}\n## with the returned handle to change graphic properties of the baseline.\n##\n## @item basevalue\n## The y-value where the baseline is drawn.  (Default: 0)\n## @end table\n## @seealso{stem3, bar, hist, plot, stairs}\n## @end deftypefn\n\nfunction h = stem (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  htmp = __stem__ (false, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! y = 1:10;\n%! stem (y);\n%! title (\"stem plot of y-values only\");\n\n%!demo\n%! clf;\n%! x = 1:10;\n%! y = 2*x;\n%! stem (x, y);\n%! title (\"stem plot of x and y-values\");\n\n%!demo\n%! clf;\n%! x = 1:10;\n%! y = 2*x;\n%! h = stem (x, y, \"r\");\n%! title (\"stem plot with modified color\");\n\n%!demo\n%! clf;\n%! x = 1:10;\n%! y = 2*x;\n%! h = stem (x, y, \"-.k\");\n%! title (\"stem plot with modified line style and color\");\n\n%!demo\n%! clf;\n%! x = 1:10;\n%! y = 2*x;\n%! h = stem (x, y, \"-.ks\");\n%! title (\"stem plot with modified line style, color, and marker\");\n\n%!demo\n%! clf;\n%! x = 1:10;\n%! y = 2*x;\n%! h = stem (x, y, \"filled\");\n%! title ('stem plot with \"filled\" markers');\n\n%!demo\n%! clf;\n%! x = 1:10;\n%! y = 2*x;\n%! h = stem (x, y, \"markerfacecolor\", [1 0 1]);\n%! title (\"stem plot modified with property/value pair\");\n\n%!demo\n%! clf;\n%! x = (0 : 10)';\n%! y = [sin(x), cos(x)];\n%! h = stem (x, y);\n%! set (h(2), \"color\", \"g\");\n%! set (h(1), \"basevalue\", -0.75);\n%! title (\"stem plots modified through hggroup handle\");\n\n%!demo\n%! clf;\n%! N = 11;\n%! x = 0:(N-1);\n%! y = rand (1, N);\n%! hs = stem (x(1), y(1));\n%! set (gca (), \"xlim\", [1, N-1], \"ylim\", [0, 1]);\n%! title (\"stem plot data modified through hggroup handle\");\n%! for k=2:N\n%!   set (hs, \"xdata\", x(1:k), \"ydata\", y(1:k));\n%!   drawnow ();\n%!   pause (0.2);\n%! endfor\n\n%!test\n%! ## stemseries share the same baseline and basevalue\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = stem ([1 2; 1.5 2.5], [1 1;2 2]);\n%!   assert (get (h(1), \"baseline\"), get (h(2), \"baseline\"));\n%!   bv = 0.3;\n%!   set (h(1), \"basevalue\", bv);\n%!   assert (get (get (h(1), \"baseline\"), \"basevalue\"), bv);\n%!   assert (get (h(1), \"basevalue\"), bv);\n%!   assert (get (h(2), \"basevalue\"), bv);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> stem ()\n%!error <can not define Z for 2-D stem plot> stem (1,2,3)\n%!error <Y must be a vector or 2-D array> stem (ones (2,2,2))\n%!error <X and Y must be numeric> stem ({1})\n%!error <X and Y must be numeric> stem (1, {1})\n%!error <inconsistent sizes for X and Y> stem (1:2, 1:3)\n%!error <inconsistent sizes for X and Y> stem (1:2, ones (3,3))\n%!error <inconsistent sizes for X and Y> stem (ones (2,2), ones (3,3))\n%!error <No value specified for property \"FOO\"> stem (1, \"FOO\")\n"
  },
  {
    "path": "scripts/plot/draw/stem3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} stem3 (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} stem3 (@dots{}, @var{linespec})\n## @deftypefnx {} {} stem3 (@dots{}, \"filled\")\n## @deftypefnx {} {} stem3 (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} stem3 (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} stem3 (@dots{})\n## Plot a 3-D stem graph.\n##\n## Stems are drawn from the height @var{z} to the location in the x-y plane\n## determined by @var{x} and @var{y}.  The default color is @qcode{\"b\"} (blue),\n## the default line style is @qcode{\"-\"}, and the default marker is\n## @qcode{\"o\"}.\n##\n## The line style can be altered by the @var{linespec} argument in the same\n## manner as the @code{plot} command.  If the @qcode{\"filled\"} argument is\n## present the markers at the top of the stems will be filled in.\n##\n## Optional property/value pairs may be specified to control the appearance\n## of the plot.  The full list of properties is documented at\n## @ref{Line Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a handle to the @nospell{\"stem series\"}\n## hggroup containing the line and marker objects used for the plot.\n## @xref{XREFstem,,stem}, for a description of the @nospell{\"stem series\"}\n## object.\n##\n## Example:\n##\n## @example\n## @group\n## theta = 0:0.2:6;\n## stem3 (cos (theta), sin (theta), theta);\n## @end group\n## @end example\n##\n## @noindent\n## plots 31 stems with heights from 0 to 6 lying on a circle.\n##\n## Implementation Note: Color definitions with RGB-triples are not valid.\n## @seealso{stem, bar, hist, plot}\n## @end deftypefn\n\nfunction h = stem3 (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  htmp = __stem__ (true, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! theta = 0:0.2:6;\n%! stem3 (cos (theta), sin (theta), theta);\n%! title (\"stem3() plot\");\n\n%!error <Invalid call> stem3 ()\n%!error <must define X, Y, and Z> stem3 (1,2)\n%!error <X, Y, and Z must be numeric> stem3 ({1}, 1, 1)\n%!error <X, Y, and Z must be numeric> stem3 (1, {1}, 1)\n%!error <X, Y, and Z must be numeric> stem3 (1, 1, {1})\n%!error <inconsistent sizes for X, Y, and Z> stem3 (ones (2,2), 1, 1)\n%!error <inconsistent sizes for X, Y, and Z> stem3 (1, ones (2,2), 1)\n%!error <inconsistent sizes for X, Y, and Z> stem3 (1, 1, ones (2,2))\n%!error <No value specified for property \"FOO\"> stem3 (1, \"FOO\")\n"
  },
  {
    "path": "scripts/plot/draw/stemleaf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} stemleaf (@var{x}, @var{caption})\n## @deftypefnx {} {} stemleaf (@var{x}, @var{caption}, @var{stem_sz})\n## @deftypefnx {} {@var{plotstr} =} stemleaf (@dots{})\n## Compute and display a stem and leaf plot of the vector @var{x}.\n##\n## The input @var{x} should be a vector of integers.  Any non-integer values\n## will be converted to integer by @code{@var{x} = fix (@var{x})}.  By default\n## each element of @var{x} will be plotted with the last digit of the element\n## as a leaf value and the remaining digits as the stem.  For example, 123\n## will be plotted with the stem @samp{12} and the leaf @samp{3}.  The second\n## argument, @var{caption}, should be a character array which provides a\n## description of the data.  It is included as a heading for the output.\n##\n## The optional input @var{stem_sz} sets the width of each stem.\n## The stem width is determined by @code{10^(@var{stem_sz} + 1)}.\n## The default stem width is 10.\n##\n## The output of @code{stemleaf} is composed of two parts: a\n## \"Fenced Letter Display\", followed by the stem-and-leaf plot itself.\n## The Fenced Letter Display is described in @cite{Exploratory Data Analysis}.\n## Briefly, the entries are as shown:\n##\n## @example\n## @group\n##\n##         Fenced Letter Display\n## #% nx|___________________     nx = numel (x)\n## M% mi|       md         |     mi median index, md median\n## H% hi|hl              hu| hs  hi lower hinge index, hl,hu hinges,\n## 1    |x(1)         x(nx)|     hs h_spreadx(1), x(nx) first\n##            _______            and last data value.\n##      ______|step |_______     step 1.5*h_spread\n##     f|ifl            ifh|     inner fence, lower and higher\n##      |nfl            nfh|     no.\\ of data points within fences\n##     F|ofl            ofh|     outer fence, lower and higher\n##      |nFl            nFh|     no.\\ of data points outside outer\n##                               fences\n## @end group\n## @end example\n##\n## The stem-and-leaf plot shows on each line the stem value followed by the\n## string made up of the leaf digits.  If the @var{stem_sz} is not 1 the\n## successive leaf values are separated by \",\".\n##\n## With no return argument, the plot is immediately displayed.  If an output\n## argument is provided, the plot is returned as an array of strings.\n##\n## The leaf digits are not sorted.  If sorted leaf values are desired, use\n## @code{@var{xs} = sort (@var{x})} before calling @code{stemleaf (@var{xs})}.\n##\n## The stem and leaf plot and associated displays are described in:\n## Chapter 3, @cite{Exploratory Data Analysis} by @nospell{J. W. Tukey},\n## Addison-Wesley, 1977.\n## @seealso{hist, printd}\n## @end deftypefn\n\nfunction plotstr = stemleaf (x, caption, stem_sz)\n\n  ## Compute and display a stem and leaf plot of the vector x.  The x\n  ## vector is converted to integer by x = fix(x).  If an output argument\n  ## is provided, the plot is returned as an array of strings.  The\n  ## first element is the heading followed by an element for each stem.\n  ##\n  ## The default stem step is 10.  If stem_sz is provided the stem\n  ## step is set to: 10^(stem_sz+1).  The x vector should be integers.\n  ## It will be treated so that the last digit is the leaf value and the\n  ## other digits are the stems.\n  ##\n  ## When we first implemented stem and leaf plots in the early 1960's\n  ## there was some discussion about sorting vs. leaving the leaf\n  ## entries in the original order in the data.  We decided in favor of\n  ## sorting the leaves for most purposes.  This is the choice\n  ## implemented in the SNAP/IEDA system that was written at that time.\n  ##\n  ## SNAP/IEDA, and particularly its stem and leaf plotting, were further\n  ## developed by Hale Trotter, David Hoagland (at Princeton and MIT),\n  ## and others.\n  ##\n  ## Tukey, in EDA, generally uses unsorted leaves.  In addition, he\n  ## described a wide range of additional display formats.  This\n  ## implementation does not sort the leaves, but if the x vector is\n  ## sorted then the leaves come out sorted.  A simple display format is\n  ## used.\n  ##\n  ## I doubt if providing other options is worthwhile.  The code can\n  ## quite easily be modified to provide specific display results.  Or,\n  ## the returned output string can be edited.  The returned output is an\n  ## array of strings with each row containing a line of the plot\n  ## preceded by the lines of header text as the first row.  This\n  ## facilitates annotation.\n  ##\n  ## Note that the code has some added complexity due to the need to\n  ## distinguish both + and - 0 stems.  The +- stem values are essential\n  ## for all plots which span 0.  After dealing with +-0 stems, the added\n  ## complexity of putting +- data values in the correct stem is minor,\n  ## but the sign of 0 leaves must be checked.  And, the cases where the\n  ## stems start or end at +- 0 must also be considered.\n  ##\n  ## The fact that IEEE floating point defines +- 0 helps make this\n  ## easier.\n  ##\n  ## Michael D. Godfrey   January 2013\n\n  ## More could be implemented for better data scaling.  And, of course,\n  ## other options for the kinds of plots described by Tukey could be\n  ## provided.  This may best be left to users.\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! isvector (x))\n    error (\"stemleaf: X must be a vector\");\n  endif\n\n  if (isinteger (x))\n    ## Avoid use of integers because rounding rules do not use fix():\n    ## Example: floor (int32 (-44)/10) == -4, floor (int32 (-46)/10) = -5 !!!\n    x = single (x);\n  elseif (isfloat (x))\n    xint = fix (x);\n    if (any (x != xint))\n      warning (\"stemleaf: X truncated to integer values\");\n      x = xint;\n    endif\n  else\n    error (\"stemleaf: X must be a numeric vector\");\n  endif\n\n  if (! ischar (caption))\n    error (\"stemleaf: CAPTION must be a character array\");\n  endif\n\n  if (nargin == 2)\n    stem_step = 10;\n  else\n    if (! (isscalar (stem_sz) && stem_sz >= 0 && isreal (stem_sz)))\n      error (\"stemleaf: STEM_SZ must be a real integer >= 0\");\n    endif\n    stem_sz = fix (stem_sz);\n    stem_step = 10^(stem_sz+1);\n  endif\n\n  ## Note that IEEE 754 states that -+ 0 should compare equal.  This has\n  ## led to C sort (and therefore Octave) treating them as equal.  Thus,\n  ## sort([-1 0 -0 1]) yields [-1 0 -0 1], and sort([-1 -0 0 1])\n  ## yields: [-1 -0 0 1].  This means that stem-and-leaf plotting cannot\n  ## rely on sort to order the data as needed for display.\n  ## This also applies to min()/max() so these routines can't be relied\n  ## upon if the max or min is -+ 0.\n\n  ## Compute hinges and fences based on ref: EDA pgs. 33 and 44.\n  ## Note that these outlier estimates are meant to be \"distribution free\".\n\n  nx = numel (x);\n  xs = sort (x);                # Note that sort preserves -0\n  mdidx = fix ((nx + 1)/2);     # median index\n  hlidx = fix ((mdidx + 1)/2);  # lower hinge index\n  huidx = fix (nx + 1 - hlidx); # upper hinge index\n  md = xs(mdidx);               # median\n  hl = xs(hlidx);               # lower hinge\n  hu = xs(huidx);               # upper hinge\n  h_spread = hu - hl;           # h_spread: difference between hinges\n  step = fix (1.5*h_spread);    # step: 1.5 * h_spread\n  i_fence_l = hl - step;        # inner fences: outside hinges + step\n  o_fence_l = hl - 2*step;      # outer fences: outside hinges + 2*step\n  i_fence_h = hu + step;\n  o_fence_h = hu + 2*step;\n  n_out_l   = sum (x<i_fence_l) - sum (x<o_fence_l);\n  n_out_h   = sum (x>i_fence_h) - sum (x>o_fence_h);\n  n_far_l   = sum (x<o_fence_l);\n  n_far_h   = sum (x>o_fence_h);\n\n  ## display table similar to that on pg. 33\n  plot_out = sprintf (\"       Data: %s\", caption);\n  plot_out = [plot_out; sprintf(\" \")];\n  plot_out = [plot_out; sprintf(\"         Fenced Letter Display\")];\n  plot_out = [plot_out; sprintf(\" \")];\n  plot_out = [plot_out; sprintf(\"     #%3d|___________________\", nx)];\n  plot_out = [plot_out; sprintf(\"     M%3d|       %5d      |\", mdidx, md)];\n  plot_out = [plot_out; sprintf(\"     H%3d|%5d        %5d|   %d\", hlidx, hl, hu, h_spread)];\n  plot_out = [plot_out; sprintf(\"     1   |%5d        %5d|\", xs(1), xs(nx))];\n  plot_out = [plot_out; sprintf(\"               _______\")];\n  plot_out = [plot_out; sprintf(\"         ______|%5d|_______\",step)];\n  plot_out = [plot_out; sprintf(\"        f|%5d        %5d|\", i_fence_l, i_fence_h)];\n  plot_out = [plot_out; sprintf(\"         |%5d        %5d|  out\", n_out_l, n_out_h)];\n  plot_out = [plot_out; sprintf(\"        F|%5d        %5g|\", o_fence_l, o_fence_h)];\n  plot_out = [plot_out; sprintf(\"         |%5d        %5d|  far\",n_far_l,n_far_h)];\n  plot_out = [plot_out; \" \"];\n\n  ## Determine stem values\n  min_x = min (x);\n  max_x = max (x);\n  if (min_x > 0)      # all stems > 0\n    stems = [fix(min(x)/stem_step) : (fix(max(x)/stem_step)+1)];\n  elseif (max_x < 0)  # all stems < 0\n    stems = [(fix(min_x/stem_step)-1) : fix(max_x/stem_step)];\n  elseif (min_x < 0 && max_x > 0)  # range crosses 0\n    stems = [(fix(min_x/stem_step)-1) : -0, 0 : fix(max_x/stem_step)+1 ];\n  else   # one endpoint is a zero which may be +0 or -0\n    if (min_x == 0)\n      if (any (x == 0 & signbit (x)))\n        min_x = -0;\n      else\n        min_x = +0;\n      endif\n    endif\n    if (max_x == 0)\n      if (any (x == 0 & ! signbit (x)))\n        max_x = +0;\n      else\n        max_x = -0;\n      endif\n    endif\n    stems = [];\n    if (signbit (min_x))\n      stems = [(fix(min_x/stem_step)-1) : -0];\n    endif\n    if (! signbit (max_x))\n      stems = [stems, 0 : fix(max_x/stem_step)+1 ];\n    endif\n  endif\n\n  ## Vectorized version provided by Rik Wehbring (rik@octave.org)\n  ## Determine leaves for each stem:\n  new_line = 1;\n  for kx = 2 : numel (stems)\n\n    stem_sign = signbit (stems(kx));\n    if (stems(kx) <= 0)\n      idx = ((x <= stems(kx)*stem_step) & (x > (stems(kx-1)*stem_step))\n              & (signbit (x) == stem_sign));\n      xlf = abs (x(idx) - stems(kx)*stem_step);\n    else\n      idx = ((x < stems(kx)*stem_step) & (x >= (stems(kx-1)*stem_step))\n              & (signbit (x) == stem_sign));\n      xlf = abs (x(idx) - stems(kx-1)*stem_step);\n    endif\n    ## Convert leaves to a string\n    if (stem_step == 10)\n      lf_str = sprintf (\"%d\", xlf);\n    else\n      lf_str = \"\";\n      if (! isempty (xlf))\n        lf_str = sprintf (\"%d\", xlf(1));\n        if (numel (xlf) > 1)\n          lf_str = [lf_str sprintf(\",%d\", xlf(2:end))];\n        endif\n      endif\n    endif\n\n    ## Set correct -0\n    if (stems(kx) == 0 && signbit (stems(kx)))\n      line = sprintf (\"  -0 | %s\",  lf_str);  # -0 stem.\n    elseif (stems(kx) < 0)\n      line = sprintf (\"%4d | %s\", stems(kx), lf_str);\n    elseif (stems(kx) > 0)\n      line = sprintf (\"%4d | %s\", stems(kx-1), lf_str);\n    else\n      line = \"\";\n    endif\n\n    if (! isempty (lf_str) || stems(kx) == 0 || stems(kx-1) == 0)\n      plot_out = [plot_out; line];\n      new_line = 1;\n    else\n      if (new_line == 1)\n        plot_out = [plot_out; \"     :\"];  # just print one : if no leaves\n        new_line = 0;\n      endif\n    endif\n\n  endfor    # kx = 2: numel (stems)\n\n  if (nargout == 0)\n    disp (plot_out);\n  else\n    plotstr = plot_out;\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Unsorted plot:\n%! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44];\n%! stemleaf (x, \"Unsorted plot\");\n\n%!demo\n%! ## Sorted leaves:\n%! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44];\n%! y = sort (x);\n%! stemleaf (y, \"Sorted leaves\");\n\n%!demo\n%! ## Sorted leaves (large dataset):\n%! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48     ...\n%!      127 36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119   ...\n%!      58 109 23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 ...\n%!      121 58 114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7   ...\n%!      68 40 31 115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40    ...\n%!      119 47 105 57 122 109 124 115 43 120 43 27 27 18 28 48 125 107 114   ...\n%!      34 133 45 120 30 127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20  ...\n%!      0];\n%! y = sort (x);\n%! stemleaf (y, \"Sorted leaves (large dataset)\");\n\n%!demo\n%! ## Gaussian leaves:\n%! x = fix (30 * randn (300,1));\n%! stemleaf (x, \"Gaussian leaves\");\n\n%!test\n%! ## test minus to plus\n%! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127   ...\n%!      36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109  ...\n%!      23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58   ...\n%!      114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31   ...\n%!      115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57 ...\n%!      122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30  ...\n%!      127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0];\n%! x = sort (x);\n%! rexp = char (\n%! \"       Data: test minus to plus\"    ,\n%! \" \"                                  ,\n%! \"         Fenced Letter Display\"     ,\n%! \" \"                                  ,\n%! \"     #138|___________________\"      ,\n%! \"     M 69|          52      |\"      ,\n%! \"     H 35|   30          116|   86\" ,\n%! \"     1   |  -28          146|\"      ,\n%! \"               _______\"             ,\n%! \"         ______|  129|_______\"      ,\n%! \"        f|  -99          245|\"      ,\n%! \"         |    0            0|  out\" ,\n%! \"        F| -228          374|\"      ,\n%! \"         |    0            0|  far\" ,\n%! \" \"                                  ,\n%! \"  -2 | 82\"                          ,\n%! \"  -1 | 3\"                           ,\n%! \"  -0 | 2\"                           ,\n%! \"   0 | 00177\"                       ,\n%! \"   1 | 00112288\"                    ,\n%! \"   2 | 001133577777899\"             ,\n%! \"   3 | 000111123456777889\"          ,\n%! \"   4 | 00122233344456788\"           ,\n%! \"   5 | 223788\"                      ,\n%! \"   6 | 138\"                         ,\n%! \"   7 | 11\"                          ,\n%! \"     : \"                            ,\n%! \"   9 | 69\"                          ,\n%! \"  10 | 04555567999\"                 ,\n%! \"  11 | 0133344455566667777899\"      ,\n%! \"  12 | 0011223444555677788\"         ,\n%! \"  13 | 1239\"                        ,\n%! \"  14 | 16\"                          );\n%! r = stemleaf (x, \"test minus to plus\", 0);\n%! assert (r, rexp);\n\n%!test\n%! ## positive values above 0\n%! x = [5 22 12 28 52 39 12 11 11 42 38 44 18 44];\n%! rexp = char (\n%! \"       Data: positive values above 0\",\n%! \" \"                                   ,\n%! \"         Fenced Letter Display\"      ,\n%! \" \"                                   ,\n%! \"     # 14|___________________\"       ,\n%! \"     M  7|          22      |\"       ,\n%! \"     H  4|   12           42|   30\"  ,\n%! \"     1   |    5           52|\"       ,\n%! \"               _______\"              ,\n%! \"         ______|   45|_______\"       ,\n%! \"        f|  -33           87|\"       ,\n%! \"         |    0            0|  out\"  ,\n%! \"        F|  -78          132|\"       ,\n%! \"         |    0            0|  far\"  ,\n%! \" \"                                   ,\n%! \"   0 | 5\"                            ,\n%! \"   1 | 22118\"                        ,\n%! \"   2 | 28\"                           ,\n%! \"   3 | 98\"                           ,\n%! \"   4 | 244\"                          ,\n%! \"   5 | 2\"                            );\n%! r = stemleaf (x, \"positive values above 0\");\n%! assert (r, rexp);\n\n%!test\n%! ## negative values below 0\n%! x = [5 22 12 28 52 39 12 11 11 42 38 44 18 44];\n%! x = -x;\n%! rexp = char (\n%! \"       Data: negative values below 0\",\n%! \" \"                                   ,\n%! \"         Fenced Letter Display\"      ,\n%! \" \"                                   ,\n%! \"     # 14|___________________\"       ,\n%! \"     M  7|         -28      |\"       ,\n%! \"     H  4|  -42          -12|   30\"  ,\n%! \"     1   |  -52           -5|\"       ,\n%! \"               _______\"              ,\n%! \"         ______|   45|_______\"       ,\n%! \"        f|  -87           33|\"       ,\n%! \"         |    0            0|  out\"  ,\n%! \"        F| -132           78|\"       ,\n%! \"         |    0            0|  far\"  ,\n%! \" \"                                   ,\n%! \"  -5 | 2\"                            ,\n%! \"  -4 | 244\"                          ,\n%! \"  -3 | 98\"                           ,\n%! \"  -2 | 28\"                           ,\n%! \"  -1 | 22118\"                        ,\n%! \"  -0 | 5\"                            );\n%! r = stemleaf (x, \"negative values below 0\");\n%! assert (r, rexp);\n\n%!test\n%! ## positive values from 0\n%! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44];\n%! rexp = char (\n%! \"       Data: positive values from 0\",\n%! \" \"                                  ,\n%! \"         Fenced Letter Display\"     ,\n%! \" \"                                  ,\n%! \"     # 15|___________________\"      ,\n%! \"     M  8|          22      |\"      ,\n%! \"     H  4|   11           42|   31\" ,\n%! \"     1   |    0           52|\"      ,\n%! \"               _______\"             ,\n%! \"         ______|   46|_______\"      ,\n%! \"        f|  -35           88|\"      ,\n%! \"         |    0            0|  out\" ,\n%! \"        F|  -81          134|\"      ,\n%! \"         |    0            0|  far\" ,\n%! \" \"                                  ,\n%! \"   0 | 20\"                          ,\n%! \"   1 | 22118\"                       ,\n%! \"   2 | 28\"                          ,\n%! \"   3 | 98\"                          ,\n%! \"   4 | 244\"                         ,\n%! \"   5 | 2\"                           );\n%! r = stemleaf (x, \"positive values from 0\");\n%! assert (r, rexp);\n\n%!test\n%! ## negative values from 0\n%! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44];\n%! x = -x;\n%! rexp = char (\n%! \"       Data: negative values from 0\",\n%! \" \"                                  ,\n%! \"         Fenced Letter Display\"     ,\n%! \" \"                                  ,\n%! \"     # 15|___________________\"      ,\n%! \"     M  8|         -22      |\"      ,\n%! \"     H  4|  -42          -11|   31\" ,\n%! \"     1   |  -52            0|\"      ,\n%! \"               _______\"             ,\n%! \"         ______|   46|_______\"      ,\n%! \"        f|  -88           35|\"      ,\n%! \"         |    0            0|  out\" ,\n%! \"        F| -134           81|\"      ,\n%! \"         |    0            0|  far\" ,\n%! \" \"                                  ,\n%! \"  -5 | 2\"                           ,\n%! \"  -4 | 244\"                         ,\n%! \"  -3 | 98\"                          ,\n%! \"  -2 | 28\"                          ,\n%! \"  -1 | 22118\"                       ,\n%! \"  -0 | 20\"                          );\n%! r = stemleaf (x, \"negative values from 0\");\n%! assert (r, rexp);\n\n%!test\n%! ## both +0 and -0 present\n%! x = [-9 -7 -0 0 -0];\n%! rexp = char (\n%! \"       Data: both +0 and -0 present\",\n%! \" \"                                  ,\n%! \"         Fenced Letter Display\"     ,\n%! \" \"                                  ,\n%! \"     #  5|___________________\"      ,\n%! \"     M  3|           0      |\"      ,\n%! \"     H  2|   -7            0|   7\"  ,\n%! \"     1   |   -9            0|\"      ,\n%! \"               _______\"             ,\n%! \"         ______|   10|_______\"      ,\n%! \"        f|  -17           10|\"      ,\n%! \"         |    0            0|  out\" ,\n%! \"        F|  -27           20|\"      ,\n%! \"         |    0            0|  far\" ,\n%! \" \"                                  ,\n%! \"  -0 | 9700\"                        ,\n%! \"   0 | 0\"                           );\n%! r = stemleaf (x, \"both +0 and -0 present\");\n%! assert (r, rexp);\n\n%!test\n%! ## both <= 0 and -0 present\n%! x = [-9 -7 0 -0];\n%! rexp = char (\n%! \"       Data: both <= 0 and -0 present\",\n%! \" \"                                    ,\n%! \"         Fenced Letter Display\"       ,\n%! \" \"                                    ,\n%! \"     #  4|___________________\"        ,\n%! \"     M  2|          -7      |\"        ,\n%! \"     H  1|   -9            0|   9\"    ,\n%! \"     1   |   -9            0|\"        ,\n%! \"               _______\"               ,\n%! \"         ______|   13|_______\"        ,\n%! \"        f|  -22           13|\"        ,\n%! \"         |    0            0|  out\"   ,\n%! \"        F|  -35           26|\"        ,\n%! \"         |    0            0|  far\"   ,\n%! \" \"                                    ,\n%! \"  -0 | 970\"                           ,\n%! \"   0 | 0\"                             );\n%! r = stemleaf (x, \"both <= 0 and -0 present\");\n%! assert (r, rexp);\n\n%!test\n%! ##   Example from EDA: Chevrolet Prices pg. 30\n%! x = [150 250 688 695 795 795 895 895 895 ...\n%!      1099 1166 1333 1499 1693 1699 1775 1995];\n%! rexp = char (\n%! \"       Data: Chevrolet Prices EDA pg.30\",\n%! \" \"                                      ,\n%! \"         Fenced Letter Display\"         ,\n%! \" \"                                      ,\n%! \"     # 17|___________________\"          ,\n%! \"     M  9|         895      |\"          ,\n%! \"     H  5|  795         1499|   704\"    ,\n%! \"     1   |  150         1995|\"          ,\n%! \"               _______\"                 ,\n%! \"         ______| 1056|_______\"          ,\n%! \"        f| -261         2555|\"          ,\n%! \"         |    0            0|  out\"     ,\n%! \"        F|-1317         3611|\"          ,\n%! \"         |    0            0|  far\"     ,\n%! \" \"                                      ,\n%! \"   1 | 50\"                              ,\n%! \"   2 | 50\"                              ,\n%! \"     :\"                                 ,\n%! \"   6 | 88,95\"                           ,\n%! \"   7 | 95,95\"                           ,\n%! \"   8 | 95,95,95\"                        ,\n%! \"     :\"                                 ,\n%! \"  10 | 99\"                              ,\n%! \"  11 | 66\"                              ,\n%! \"     :\"                                 ,\n%! \"  13 | 33\"                              ,\n%! \"  14 | 99\"                              ,\n%! \"     :\"                                 ,\n%! \"  16 | 93,99\"                           ,\n%! \"  17 | 75\"                              ,\n%! \"     :\"                                 ,\n%! \"  19 | 95\"                              );\n%! r = stemleaf (x, \"Chevrolet Prices EDA pg.30\", 1);\n%! assert (r, rexp);\n\n## Test input validation\n%!error <Invalid call> stemleaf ()\n%!error <X must be a vector> stemleaf (ones (2,2), \"\")\n%!warning <X truncated to integer values> tmp = stemleaf ([0 0.5 1],\"\");\n%!error <X must be a numeric vector> stemleaf (\"Hello World\", \"data\")\n%!error <CAPTION must be a character array> stemleaf (1, 2)\n%!error <STEM_SZ must be a real integer> stemleaf (1, \"\", ones (2,2))\n%!error <STEM_SZ must be a real integer> stemleaf (1, \"\", -1)\n%!error <STEM_SZ must be a real integer> stemleaf (1, \"\", 1+i)\n"
  },
  {
    "path": "scripts/plot/draw/stream2.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{xy} =} stream2 (@var{x}, @var{y}, @var{u}, @var{v}, @var{sx}, @var{sy})\n## @deftypefnx {} {@var{xy} =} stream2 (@var{u}, @var{v}, @var{sx}, @var{sy})\n## @deftypefnx {} {@var{xy} =} stream2 (@dots{}, @var{options})\n## Compute 2-D streamline data.\n##\n## Calculates streamlines of a vector field given by @code{[@var{u}, @var{v}]}.\n## The vector field is defined over a rectangular grid given by\n## @code{[@var{x}, @var{y}]}.  The streamlines start at the seed points\n## @code{[@var{sx}, @var{sy}]}.  The returned value @var{xy} contains a cell\n## array of vertex arrays.  If the starting point is outside the vector field,\n## @code{[]} is returned.\n##\n## The input parameter @var{options} is a 2-D vector of the form\n## @code{[@var{stepsize}, @var{max_vertices}]}.  The first parameter\n## specifies the step size used for trajectory integration (default 0.1).  A\n## negative value is allowed which will reverse the direction of integration.\n## The second parameter specifies the maximum number of segments used to\n## create a streamline (default 10,000).\n##\n## The return value @var{xy} is a @nospell{nverts x 2} matrix containing the\n## coordinates of the field line segments.\n##\n## Example:\n##\n## @example\n## @group\n## [x, y] = meshgrid (0:3);\n## u = 2 * x;\n## v = y;\n## xy = stream2 (x, y, u, v, 1.0, 0.5);\n## @end group\n## @end example\n##\n## @seealso{streamline, stream3}\n## @end deftypefn\n\n## References:\n##\n## @article{\n##    title = {Particle Tracing Algorithms for 3D Curvilinear Grids},\n##    year = {2000},\n##    author = {Nielson, Gregory and Uller, H. and Sadarjoen, I. and Walsum, Theo and Hin, Andrea and Post, Frits}\n## }\n##\n## @article{\n##    title = {Sources of error in the graphical analysis of CFD results},\n##    publisher = {Journal of Scientific Computing},\n##    year = {1988},\n##    volume = {3},\n##    number = {2},\n##    pages = {149--164},\n##    author = {Buning, Pieter G.},\n## }\n\nfunction xy = stream2 (varargin)\n\n  options = [];\n  switch (numel (varargin))\n    case {4,5}\n      if (numel (varargin) == 4)\n        [u, v, spx, spy] = varargin{:};\n      else\n        [u, v, spx, spy, options] = varargin{:};\n      endif\n      [m, n] = size (u);\n      [x, y] = meshgrid (1:n, 1:m);\n    case 6\n      [x, y, u, v, spx, spy] = varargin{:};\n    case 7\n      [x, y, u, v, spx, spy, options] = varargin{:};\n    otherwise\n      print_usage ();\n  endswitch\n\n  stepsize = 0.1;\n  max_vertices = 10_000;\n  if (! isempty (options))\n    switch (numel (options))\n      case 1\n        stepsize = options(1);\n      case 2\n        stepsize = options(1);\n        max_vertices = options(2);\n      otherwise\n        error (\"stream2: OPTIONS must be a 1- or 2-element vector\");\n    endswitch\n\n    if (! isreal (stepsize) || stepsize == 0)\n      error (\"stream2: STEPSIZE must be a real scalar != 0\");\n    endif\n    if (! isreal (max_vertices) || max_vertices < 1)\n      error (\"stream2: MAX_VERTICES must be an integer > 0\");\n    endif\n    max_vertices = fix (max_vertices);\n  endif\n\n  if (! (size_equal (u, v, x, y) && size_equal (spx, spy)))\n    error (\"stream2: matrix dimensions must match\");\n  endif\n  if (iscomplex (u) || iscomplex (v) || iscomplex (x) || iscomplex (y)\n      || iscomplex (spx) || iscomplex (spy))\n    error (\"stream2: all inputs must be real-valued\");\n  endif\n\n  gx = x(1,:);\n  gy = y(:,1).';\n\n  ## Jacobian Matrix\n  dx = diff (gx);\n  dy = diff (gy);\n  ## \"<\" used to check if the mesh is ascending\n  if (any (dx <= 0) || any (dy <= 0)\n      || any (isnan (dx)) || any (isnan (dy)))\n    error (\"stream2: non-monotonically increasing or NaN values found in mesh\");\n  endif\n  tx = 1 ./ dx;\n  ty = 1 ./ dy;\n  ## \"Don't cares\" used for handling points located on the border\n  tx(end + 1) = 0;\n  ty(end + 1) = 0;\n  dx(end + 1) = 0;\n  dy(end + 1) = 0;\n\n  px = spx(:);\n  py = spy(:);\n\n  for nseed = 1 : numel (px)\n\n    xp = px(nseed);\n    yp = py(nseed);\n    idx = find (diff (gx <= xp), 1);\n    if (gx(end) == xp)\n      idx = numel (gx);\n    endif\n    idy = find (diff (gy <= yp), 1);\n    if (gy(end) == yp)\n      idy = numel (gy);\n    endif\n\n    if (isempty (idx) || isempty (idy))\n      xy{nseed} = [];\n    else\n      ## Transform seed from P coordinates to C coordinates\n      zeta = (idx - 1) + (xp - gx(idx)) * tx(idx);\n      xi = (idy - 1) + (yp - gy(idy)) * ty(idy);\n\n      C = __streameuler2d__ (u, v, tx, ty, zeta, xi, stepsize, max_vertices);\n\n      ## Transform from C coordinates to P coordinates\n      idu = floor (C(:,1));\n      idv = floor (C(:,2));\n      xy{nseed} = [gx(idu + 1).' + (C(:,1) - idu).*(dx(idu + 1).'), ...\n                   gy(idv + 1).' + (C(:,2) - idv).*(dy(idv + 1).')];\n    endif\n\n  endfor\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x, y] = meshgrid (-5:5, -4:4);\n%! u = x - 2 * y;\n%! v = 2 * x - 3 * y;\n%! sx = [3, 0, -1, -2, -3, 0, 1, 2];\n%! sy = [3, 3, 3, 3, -3, -3, -3, -3];\n%! h = streamline (x, y, u, v, sx, sy, 0.05);\n%! set (h, \"color\", \"r\");\n%! hold on;\n%! quiver (x, y, u, v);\n%! scatter (sx(:), sy(:), 20, \"filled\", \"o\", \"markerfacecolor\", \"r\");\n%! grid on;\n%! title (\"Asymptotically Stable Equilibrium\");\n%! axis equal;\n\n%!test\n%! xy = stream2 ([1,1,1;2,2,2;3,3,3], [1,1,1;2,2,2;3,3,3], 1, 1, [0.01,5]);\n%! assert (numel (xy{:}), 10);\n\n## Test input validation\n%!error <Invalid call> stream2 ()\n%!error <Invalid call> stream2 (1)\n%!error <Invalid call> stream2 (1,2)\n%!error <Invalid call> stream2 (1,2,3)\n%!error <OPTIONS must be a 1- or 2-element> stream2 (1,2,3,4, [1,2,3])\n%!error <STEPSIZE must be a real scalar != 0> stream2 (1,2,3,4, [1i])\n%!error <STEPSIZE must be a real scalar != 0> stream2 (1,2,3,4, [0])\n%!error <MAX_VERTICES must be an integer> stream2 (1,2,3,4, [1, 1i])\n%!error <MAX_VERTICES must be an integer> stream2 (1,2,3,4, [1, 0])\n%!error <matrix dimensions must match> stream2 ([1 1],2,3,4)\n%!error <matrix dimensions must match> stream2 (1,[2 2],3,4)\n%!error <matrix dimensions must match> stream2 (1,2,[3 3],4)\n%!error <matrix dimensions must match> stream2 (1,2,3,[4 4])\n%!error <all inputs must be real-valued> stream2 (1i,2,3,4)\n%!error <all inputs must be real-valued> stream2 (1,2i,3,4)\n%!error <all inputs must be real-valued> stream2 (1,2,3i,4)\n%!error <all inputs must be real-valued> stream2 (1,2,3,4i)\n%!error <non-monotonically increasing or NaN values found in mesh>\n%! stream2 ([2 1], [1 2], [1 1], [2 2], [3 3], [4 4]);\n%!error <non-monotonically increasing or NaN values found in mesh>\n%! stream2 ([1 NaN], [1 2], [1 1], [2 2], [3 3], [4 4]);\n## FIXME: vectors representing x, y mesh are not accepted.\n%#!error <non-monotonically increasing or NaN values found in mesh>\n%! stream2 ([1 2], [2 1], [1 1], [2 2], [3 3], [4 4]);\n%#!error <non-monotonically increasing or NaN values found in mesh>\n%! stream2 ([1 2], [1 NaN], [1 1], [2 2], [3 3], [4 4]);\n"
  },
  {
    "path": "scripts/plot/draw/stream3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{xyz} =} stream3 (@var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {@var{xyz} =} stream3 (@var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {@var{xyz} =} stream3 (@dots{}, @var{options})\n## Compute 3-D streamline data.\n##\n## Calculate streamlines of a vector field given by @code{[@var{u}, @var{v},\n## @var{w}]}.  The vector field is defined over a rectangular grid given by\n## @code{[@var{x}, @var{y}, @var{z}]}.  The streamlines start at the seed\n## points @code{[@var{sx}, @var{sy}, @var{sz}]}.  The returned value @var{xyz}\n## contains a cell array of vertex arrays.  If the starting point is outside\n## the vector field, @code{[]} is returned.\n##\n## The input parameter @var{options} is a 2-D vector of the form\n## @code{[@var{stepsize}, @var{max_vertices}]}.  The first parameter\n## specifies the step size used for trajectory integration (default 0.1).  A\n## negative value is allowed which will reverse the direction of integration.\n## The second parameter specifies the maximum number of segments used to\n## create a streamline (default 10,000).\n##\n## The return value @var{xyz} is a @nospell{nverts x 3} matrix containing the\n## coordinates of the field line segments.\n##\n## Example:\n##\n## @example\n## @group\n## [x, y, z] = meshgrid (0:3);\n## u = 2 * x;\n## v = y;\n## w = 3 * z;\n## xyz = stream3 (x, y, z, u, v, w, 1.0, 0.5, 0.0);\n## @end group\n## @end example\n##\n## @seealso{stream2, streamline, streamribbon, streamtube, ostreamtube}\n## @end deftypefn\n\n## References:\n##\n## @article{\n##    title = {Particle Tracing Algorithms for 3D Curvilinear Grids},\n##    year = {2000},\n##    author = {Nielson, Gregory and Uller, H. and Sadarjoen, I. and Walsum, Theo and Hin, Andrea and Post, Frits}\n## }\n##\n## @article{\n##    title = {Sources of error in the graphical analysis of CFD results},\n##    publisher = {Journal of Scientific Computing},\n##    year = {1988},\n##    volume = {3},\n##    number = {2},\n##    pages = {149--164},\n##    author = {Buning, Pieter G.},\n## }\n\nfunction xyz = stream3 (varargin)\n\n  options = [];\n  switch (numel (varargin))\n    case {6,7}\n      if (numel (varargin) == 6)\n        [u, v, w, spx, spy, spz] = varargin{:};\n      else\n        [u, v, w, spx, spy, spz, options] = varargin{:};\n      endif\n      [m, n, p] = size (u);\n      [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n    case 9\n      [x, y, z, u, v, w, spx, spy, spz] = varargin{:};\n    case 10\n      [x, y, z, u, v, w, spx, spy, spz, options] = varargin{:};\n    otherwise\n      print_usage ();\n  endswitch\n\n  stepsize = 0.1;\n  max_vertices = 10_000;\n  if (! isempty (options))\n    switch (numel (options))\n      case 1\n        stepsize = options(1);\n      case 2\n        stepsize = options(1);\n        max_vertices = options(2);\n      otherwise\n        error (\"stream3: OPTIONS must be a 1- or 2-element vector\");\n    endswitch\n\n    if (! isreal (stepsize) || stepsize == 0)\n      error (\"stream2: STEPSIZE must be a real scalar != 0\");\n    endif\n    if (! isreal (max_vertices) || max_vertices < 1)\n      error (\"stream2: MAX_VERTICES must be an integer > 0\");\n    endif\n    max_vertices = fix (max_vertices);\n  endif\n\n  if (! (size_equal (u, v, w, x, y, z) && size_equal (spx, spy, spz)))\n    error (\"stream3: matrix dimensions must match\");\n  endif\n  if (iscomplex (u) || iscomplex (v) || iscomplex (w)\n      || iscomplex (x) || iscomplex (y) || iscomplex (z)\n      || iscomplex (spx) || iscomplex (spy) || iscomplex (spz))\n    error (\"stream3: all inputs must be real-valued\");\n  endif\n\n  gx = x(1, :, 1);\n  gy = y(:, 1, 1).';\n  tmp = z(1, 1, :);\n  gz = tmp(:).';\n\n  ## Jacobian Matrix\n  dx = diff (gx);\n  dy = diff (gy);\n  dz = diff (gz);\n  ## \"<\" used to check if the mesh is ascending\n  if (any (dx <= 0) || any (dy <= 0) || any (dz <= 0)\n      || any (isnan (dx)) || any (isnan (dy)) || any (isnan (dz)))\n    error (\"stream3: non-monotonically increasing or NaN values found in mesh\");\n  endif\n  tx = 1 ./ dx;\n  ty = 1 ./ dy;\n  tz = 1 ./ dz;\n  ## \"Don't cares\" used for handling points located on the border\n  tx(end + 1) = 0;\n  ty(end + 1) = 0;\n  tz(end + 1) = 0;\n  dx(end + 1) = 0;\n  dy(end + 1) = 0;\n  dz(end + 1) = 0;\n\n  px = spx(:);\n  py = spy(:);\n  pz = spz(:);\n\n  for nseed = 1 : numel (px)\n\n    xp = px(nseed);\n    yp = py(nseed);\n    zp = pz(nseed);\n    idx = find (diff (gx <= xp), 1);\n    if (gx(end) == xp)\n      idx = numel (gx);\n    endif\n    idy = find (diff (gy <= yp), 1);\n    if (gy(end) == yp)\n      idy = numel (gy);\n    endif\n    idz = find (diff (gz <= zp), 1);\n    if (gz(end) == zp)\n      idz = numel (gz);\n    endif\n\n    if (isempty (idx) || isempty (idy) || isempty (idz))\n      xyz{nseed} = [];\n    else\n      ## Transform seed from P coordinates to C coordinates\n      zeta = (idx - 1) + (xp - gx(idx)) * tx(idx);\n      xi = (idy - 1) + (yp - gy(idy)) * ty(idy);\n      rho = (idz - 1) + (zp - gz(idz)) * tz(idz);\n\n      C = __streameuler3d__ (u, v, w, tx, ty, tz, zeta, xi, rho, ...\n                             stepsize, max_vertices);\n\n      ## Transform from C coordinates to P coordinates\n      idu = floor (C(:, 1));\n      idv = floor (C(:, 2));\n      idw = floor (C(:, 3));\n      xyz{nseed} = [gx(idu + 1).' + (C(:, 1) - idu).*(dx(idu + 1).'), ...\n                    gy(idv + 1).' + (C(:, 2) - idv).*(dy(idv + 1).'), ...\n                    gz(idw + 1).' + (C(:, 3) - idw).*(dz(idw + 1).')];\n    endif\n\n  endfor\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x, y, z] = meshgrid (-30:1:30, -30:1:30, 0:1:50);\n%! s = 10;\n%! b = 8 / 3;\n%! r = 28;\n%! u = s * (y - x);\n%! v = r * x - y - x.*z;\n%! w = x.*y - b * z;\n%! hold on;\n%! sx = 0.1;\n%! sy = 0.1;\n%! sz = 0.1;\n%! plot3 (sx, sy, sz, \".r\", \"markersize\", 15);\n%! h = streamline (x, y, z, u, v, w, sx, sy, sz, [0.1, 50000]);\n%! set (h, \"color\", \"r\");\n%! view (3);\n%! title (\"Lorenz System\");\n%! grid on;\n%! axis equal;\n\n%!test\n%! [u, v, w] = meshgrid (0:3, 0:3, 0:3);\n%! xyz = stream3 (u, v, w, 2, 2, 2, [0.01,5]);\n%! assert (numel (xyz{:}), 15);\n\n## Test input validation\n%!error <Invalid call> stream3 ()\n%!error <Invalid call> stream3 (1)\n%!error <Invalid call> stream3 (1,2)\n%!error <Invalid call> stream3 (1,2,3)\n%!error <Invalid call> stream3 (1,2,3,4)\n%!error <Invalid call> stream3 (1,2,3,4,5)\n%!error <Invalid call> stream3 (1,2,3,4,5,6,7,8)\n%!error <OPTIONS must be a 1- or 2-element> stream3 (1,2,3,4,5,6, [1,2,3])\n%!error <STEPSIZE must be a real scalar != 0> stream3 (1,2,3,4,5,6, [1i])\n%!error <STEPSIZE must be a real scalar != 0> stream3 (1,2,3,4,5,6, [0])\n%!error <MAX_VERTICES must be an integer> stream3 (1,2,3,4,5,6, [1, 1i])\n%!error <MAX_VERTICES must be an integer> stream3 (1,2,3,4,5,6, [1, 0])\n%!error <matrix dimensions must match> stream3 ([1 1],2,3,4,5,6)\n%!error <matrix dimensions must match> stream3 (1,[2 2],3,4,5,6)\n%!error <matrix dimensions must match> stream3 (1,2,[3 3],4,5,6)\n%!error <matrix dimensions must match> stream3 (1,2,3,[4 4],5,6)\n%!error <matrix dimensions must match> stream3 (1,2,3,4,[5 5],6)\n%!error <matrix dimensions must match> stream3 (1,2,3,4,5,[6 6])\n%!error <all inputs must be real-valued> stream3 (1i,2,3,4,5,6)\n%!error <all inputs must be real-valued> stream3 (1,2i,3,4,5,6)\n%!error <all inputs must be real-valued> stream3 (1,2,3i,4,5,6)\n%!error <all inputs must be real-valued> stream3 (1,2,3,4i,5,6)\n%!error <all inputs must be real-valued> stream3 (1,2,3,4,5i,6)\n%!error <all inputs must be real-valued> stream3 (1,2,3,4,5,6i)\n%!error <non-monotonically increasing or NaN values found in mesh>\n%! stream3 ([2 1], [1 2], [3 3], [4 4], [5 5], [6 6], [7 7], [8 8], [9 9]);\n%!error <non-monotonically increasing or NaN values found in mesh>\n%! stream3 ([1 NaN], [1 2], [3 3], [4 4], [5 5], [6 6], [7 7], [8 8], [9 9]);\n## FIXME: vectors representing x, y, z mesh are not accepted.\n%#!error <non-monotonically increasing or NaN values found in mesh>\n%! stream3 ([1 2], [2 1], [3 3], [4 4], [5 5], [6 6], [7 7], [8 8], [9 9]);\n%#!error <non-monotonically increasing or NaN values found in mesh>\n%! stream3 ([1 2], [1 NaN], [3 3], [4 4], [5 5], [6 6], [7 7], [8 8], [9 9]);\n%#!error <non-monotonically increasing or NaN values found in mesh>\n%! stream3 ([1 2], [1 2], [2 1], [4 4], [5 5], [6 6], [7 7], [8 8], [9 9]);\n%#!error <non-monotonically increasing or NaN values found in mesh>\n%! stream3 ([1 2], [1 2], [1 NaN], [4 4], [5 5], [6 6], [7 7], [8 8], [9 9]);\n"
  },
  {
    "path": "scripts/plot/draw/streamline.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} streamline (@var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} streamline (@var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} streamline (@dots{}, @var{options})\n## @deftypefnx {} {} streamline (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} streamline (@dots{})\n## Plot streamlines of 2-D or 3-D vector fields.\n##\n## Plot streamlines of a 2-D or 3-D vector field given by\n## @code{[@var{u}, @var{v}]} or @code{[@var{u}, @var{v}, @var{w}]}.  The vector\n## field is defined over a rectangular grid given by @code{[@var{x}, @var{y}]}\n## or @code{[@var{x}, @var{y}, @var{z}]}.  The streamlines start at the seed\n## points @code{[@var{sx}, @var{sy}]} or @code{[@var{sx}, @var{sy}, @var{sz}]}.\n##\n## The input parameter @var{options} is a 2-D vector of the form\n## @code{[@var{stepsize}, @var{max_vertices}]}.  The first parameter\n## specifies the step size used for trajectory integration (default 0.1).  A\n## negative value is allowed which will reverse the direction of integration.\n## The second parameter specifies the maximum number of segments used to\n## create a streamline (default 10,000).\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the hggroup\n## comprising the field lines.\n##\n## Example:\n##\n## @example\n## @group\n## [x, y] = meshgrid (-1.5:0.2:2, -1:0.2:2);\n## u = - x / 4 - y;\n## v = x - y / 4;\n## streamline (x, y, u, v, 1.7, 1.5);\n## @end group\n## @end example\n##\n## @seealso{stream2, stream3, streamribbon, streamtube, ostreamtube}\n## @end deftypefn\n\nfunction h = streamline (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"streamline\", varargin{:});\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  nd = ndims (varargin{1});\n  if (nd > 3)\n    error (\"streamline: input data must be 2-D or 3-D\");\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  h = [];\n  if (nd == 2)\n    xy = stream2 (varargin{:});\n    for i = 1 : length (xy)\n      sl = xy{i};\n      if (! isempty (sl))\n        htmp = line (hax, \"xdata\", sl(:, 1), \"ydata\", sl(:, 2), \"color\", \"b\");\n        h = [h; htmp];\n      endif\n    endfor\n  else\n    xyz = stream3 (varargin{:});\n    for i = 1 : length (xyz)\n      sl = xyz{i};\n      if (! isempty (sl))\n        htmp = line (hax,\n                     \"xdata\", sl(:, 1), \"ydata\", sl(:, 2), \"zdata\", sl(:, 3),\n                     \"color\", \"b\");\n        h = [h; htmp];\n      endif\n    endfor\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x, y] = meshgrid (-2:0.5:2);\n%! u = - y - x / 2;\n%! v = x - y / 2;\n%! [sx, sy] = meshgrid (-2:2:2);\n%! h = streamline (x, y, u, v, sx, sy);\n%! set (h, \"color\", \"r\");\n%! hold on;\n%! quiver (x, y, u, v);\n%! scatter (sx(:), sy(:), 20, \"filled\", \"o\", \"markerfacecolor\", \"r\");\n%! title (\"Spiral Sink\");\n%! grid on;\n%! axis equal;\n\n%!demo\n%! clf;\n%! [x, y, z] = meshgrid (-3:3);\n%! u = - x / 2 - y;\n%! v = x - y / 2;\n%! w = - z;\n%! [sx, sy, sz] = meshgrid (3, 0:1.5:1.5, 0:1.5:3);\n%! h = streamline (x, y, z, u, v, w, sx, sy, sz);\n%! set (h, \"color\", \"r\");\n%! hold on;\n%! quiver3 (x, y, z, u, v, w);\n%! scatter3 (sx(:), sy(:), sz(:), 20, \"filled\", \"o\", \"markerfacecolor\", \"r\");\n%! view (3);\n%! title (\"Spiral Sink\");\n%! grid on;\n%! axis equal;\n\n%!demo\n%! clf;\n%! [x, y, z] = meshgrid (-1:0.4:1, -1:0.4:1, -3:0.3:0);\n%! a = 0.08;\n%! b = 0.04;\n%! u = - a * x - y;\n%! v = x - a * y;\n%! w = - b * ones (size (x));\n%! hold on;\n%! sx = 1.0;\n%! sy = 0.0;\n%! sz = 0.0;\n%! plot3 (sx, sy, sz, \".r\", \"markersize\", 15);\n%! t = linspace (0, 12 * 2 * pi (), 500);\n%! tx = exp (-a * t).*cos (t);\n%! ty = exp (-a * t).*sin (t);\n%! tz = - b * t;\n%! plot3 (tx, ty, tz, \"-b\");\n%! h = streamline (x, y, z, u, v, w, sx, sy, sz);\n%! set (h, \"color\", \"r\");\n%! view (3);\n%! title (\"Heuns Scheme (red) vs. Analytical Solution (blue)\");\n%! grid on;\n%! axis equal tight;\n\n## Test input validation\n%!error <Invalid call> streamline ()\n%!error <Invalid call to streamline>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   streamline (hax);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n%!error <input data must be 2-D or 3-D> streamline (ones (2,2,2,2))\n"
  },
  {
    "path": "scripts/plot/draw/streamribbon.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} streamribbon (@var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} streamribbon (@var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} streamribbon (@var{xyz}, @var{x}, @var{y}, @var{z}, @var{anlr_spd}, @var{lin_spd})\n## @deftypefnx {} {} streamribbon (@var{xyz}, @var{anlr_spd}, @var{lin_spd})\n## @deftypefnx {} {} streamribbon (@var{xyz}, @var{anlr_rot})\n## @deftypefnx {} {} streamribbon (@dots{}, @var{width})\n## @deftypefnx {} {} streamribbon (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} streamribbon (@dots{})\n## Calculate and display streamribbons.\n##\n## The streamribbon is constructed by rotating a normal vector around a\n## streamline according to the angular rotation of the vector field.\n##\n## The vector field is given by @code{[@var{u}, @var{v}, @var{w}]} and is\n## defined over a rectangular grid given by @code{[@var{x}, @var{y}, @var{z}]}.\n## The streamribbons start at the seed points\n## @code{[@var{sx}, @var{sy}, @var{sz}]}.\n##\n## @code{streamribbon} can be called with a cell array that contains\n## pre-computed streamline data.  To do this, @var{xyz} must be created with\n## the @code{stream3} function.  @var{lin_spd} is the linear speed of the\n## vector field and can be calculated from @code{[@var{u}, @var{v}, @var{w}]}\n## by the square root of the sum of the squares.  The angular speed\n## @var{anlr_spd} is the projection of the angular velocity onto the velocity\n## of the normalized vector field and can be calculated with the @code{curl}\n## command.  This option is useful if you need to alter the integrator step\n## size or the maximum number of streamline vertices.\n##\n## Alternatively, ribbons can be created from an array of vertices @var{xyz} of\n## a path curve.  @var{anlr_rot} contains the angles of rotation around the\n## edges between adjacent vertices of the path curve.\n##\n## The input parameter @var{width} sets the width of the streamribbons.\n##\n## Streamribbons are colored according to the total angle of rotation along the\n## ribbon.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the plot objects\n## created for each streamribbon.\n##\n## Example:\n##\n## @example\n## @group\n## [x, y, z] = meshgrid (0:0.2:4, -1:0.2:1, -1:0.2:1);\n## u = - x + 10;\n## v = 10 * z.*x;\n## w = - 10 * y.*x;\n## streamribbon (x, y, z, u, v, w, [0, 0], [0, 0.6], [0, 0]);\n## view (3);\n## @end group\n## @end example\n##\n## @seealso{streamline, stream3, streamtube, ostreamtube}\n##\n## @end deftypefn\n\n## References:\n##\n## @inproceedings{\n##    title = {Feature Detection from Vector Quantities in a Numerically Simulated Hypersonic Flow Field in Combination with Experimental Flow Visualization},\n##    author = {Pagendarm, Hans-Georg and Walter, Birgit},\n##    year = {1994},\n##    publisher = {IEEE Computer Society Press},\n##    booktitle = {Proceedings of the Conference on Visualization ’94},\n##    pages = {117–123},\n## }\n##\n## @article{\n##    title = {Efficient streamline, streamribbon, and streamtube constructions on unstructured grids},\n##    author = {Ueng, Shyh-Kuang and Sikorski, C. and Ma, Kwan-Liu},\n##    year = {1996},\n##    month = {June},\n##    publisher = {IEEE Transactions on Visualization and Computer Graphics},\n## }\n##\n## @inproceedings{\n##    title = {Visualization of 3-D vector fields - Variations on a stream},\n##    author = {Dave Darmofal and Robert Haimes},\n##    year = {1992}\n## }\n##\n## @techreport{\n##    title = {Parallel Transport Approach to Curve Framing},\n##    author = {Andrew J. Hanson and Hui Ma},\n##    year = {1995}\n## }\n##\n## @article{\n##    title = {There is More than One Way to Frame a Curve},\n##    author = {Bishop, Richard},\n##    year = {1975},\n##    month = {03},\n##    volume = {82},\n##    publisher = {The American Mathematical Monthly}\n## }\n\nfunction h = streamribbon (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"streamribbon\", varargin{:});\n\n  width = [];\n  xyz = [];\n  anlr_spd = [];\n  lin_spd = [];\n  anlr_rot = [];\n  switch (nargin)\n    case 2\n      [xyz, anlr_rot] = varargin{:};\n    case 3\n      if (numel (varargin{3}) == 1)\n        [xyz, anlr_rot, width] = varargin{:};\n      else\n        [xyz, anlr_spd, lin_spd] = varargin{:};\n        [m, n, p] = size (anlr_spd);\n        [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n      endif\n    case 4\n      [xyz, anlr_spd, lin_spd, width] = varargin{:};\n      [m, n, p] = size (anlr_spd);\n      [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n    case 6\n      if (iscell (varargin{1}))\n        [xyz, x, y, z, anlr_spd, lin_spd] = varargin{:};\n      else\n        [u, v, w, spx, spy, spz] = varargin{:};\n        [m, n, p] = size (u);\n        [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n      endif\n    case 7\n      if (iscell (varargin{1}))\n        [xyz, x, y, z, anlr_spd, lin_spd, width] = varargin{:};\n      else\n        [u, v, w, spx, spy, spz, width] = varargin{:};\n        [m, n, p] = size (u);\n        [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n      endif\n    case 9\n      [x, y, z, u, v, w, spx, spy, spz] = varargin{:};\n    case 10\n      [x, y, z, u, v, w, spx, spy, spz, width] = varargin{:};\n    otherwise\n      print_usage ();\n  endswitch\n\n  if (isempty (xyz))\n    xyz = stream3 (x, y, z, u, v, w, spx, spy, spz);\n    anlr_spd = curl (x, y, z, u, v, w);\n    lin_spd = sqrt (u.*u + v.*v + w.*w);\n  endif\n\n  ## Derive scale factor from the bounding box diagonal\n  if (isempty (width))\n    mxx = mnx = mxy = mny = mxz = mnz = [];\n    j = 1;\n    for i = 1 : length (xyz)\n      sl = xyz{i};\n      if (! isempty (sl))\n        slx = sl(:,1); sly = sl(:,2); slz = sl(:,3);\n        mxx(j) = max (slx); mnx(j) = min (slx);\n        mxy(j) = max (sly); mny(j) = min (sly);\n        mxz(j) = max (slz); mnz(j) = min (slz);\n        j += 1;\n      endif\n    endfor\n    dx = max (mxx) - min (mnx);\n    dy = max (mxy) - min (mny);\n    dz = max (mxz) - min (mnz);\n    width = sqrt (dx*dx + dy*dy + dz*dz) / 25;\n  elseif (! isreal (width) || width <= 0)\n    error (\"streamribbon: WIDTH must be a real scalar > 0\");\n  endif\n\n  if (! isempty (anlr_rot))\n    for i = 1 : length (xyz)\n      if (rows (anlr_rot{i}) != rows (xyz{i}))\n        error (\"streamribbon: ANLR_ROT must have same length as XYZ\");\n      endif\n    endfor\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  ## Angular speed of a paddle wheel spinning around a streamline in a fluid\n  ## flow \"V\":\n  ## dtheta/dt = 0.5 * <curl(V), V/norm(V)>\n  ##\n  ## Integration along a streamline segment with the length \"h\" yields the\n  ## rotation angle:\n  ## theta = 0.25 * h * <curl(V), V(0)/norm(V(0))^2) + V(h)/norm(V(h))^2)>\n  ##\n  ## Alternative approach using the curl angular speed \"c = curl()\":\n  ## theta = 0.5 * h * (c(0)/norm(V(0)) + c(h)/norm(V(h)))\n  ##\n  ## Hints:\n  ## i. ) For integration use trapezoidal rule\n  ## ii.) \"V\" can be assumend to be piecewise linear and curl(V) to be\n  ##      piecewise constant because of the used linear interpolation\n\n  h = [];\n  for i = 1 : length (xyz)\n    sl = xyz{i};\n    num_vertices = rows (sl);\n    if (! isempty (sl) && num_vertices > 1)\n      if (isempty (anlr_rot))\n        ## Plot from vector field\n        ## Interpolate onto streamline vertices\n        [lin_spd_sl, anlr_spd_sl, max_vertices] = ...\n                                  interp_sl (x, y, z, lin_spd, anlr_spd, sl);\n        if (max_vertices > 1)\n          ## Euclidean distance between two adjacent vertices\n          stepsize = vecnorm (diff (sl(1:max_vertices, :)), 2, 2);\n          ## Angular rotation around edges between two adjacent sl-vertices\n          ## Note: Potential \"division by zero\" is checked in interp_sl()\n          anlr_rot_sl = 0.5 * stepsize.*(anlr_spd_sl(1:max_vertices - 1)./ ...\n                                         lin_spd_sl(1:max_vertices - 1) + ...\n                                         anlr_spd_sl(2:max_vertices)./ ...\n                                         lin_spd_sl(2:max_vertices));\n\n          htmp = plotribbon (hax, sl, anlr_rot_sl, max_vertices, 0.5 * width);\n          h = [h; htmp];\n        endif\n      else\n          ## Plot from vertice array\n          anlr_rot_sl = anlr_rot{i};\n\n          htmp = plotribbon (hax, sl, anlr_rot_sl, num_vertices, 0.5 * width);\n          h = [h; htmp];\n      endif\n    endif\n  endfor\n\nendfunction\n\nfunction h = plotribbon (hax, sl, anlr_rot_sl, max_vertices, width2)\n\n  total_angle = cumsum (anlr_rot_sl);\n  total_angle = [0; total_angle];\n\n  ## 1st streamline segment\n  X0 = sl(1,:);\n  X1 = sl(2,:);\n  R = X1 - X0;\n  RE = R / norm (R);\n\n  ## Initial vector KE which is to be transported along the vertice array\n  KE = get_normal2 (RE);\n  XS10 = - width2 * KE + X0;\n  XS20 = width2 * KE + X0;\n\n  ## Apply angular rotation\n  cp = cos (anlr_rot_sl(1));\n  sp = sin (anlr_rot_sl(1));\n  KE = rotation (KE, RE, cp, sp).';\n\n  XS1 = - width2 * KE + X1;\n  XS2 = width2 * KE + X1;\n\n  px = zeros (2, max_vertices);\n  py = zeros (2, max_vertices);\n  pz = zeros (2, max_vertices);\n  pc = zeros (2, max_vertices);\n\n  px(:,1) = [XS10(1); XS20(1)];\n  py(:,1) = [XS10(2); XS20(2)];\n  pz(:,1) = [XS10(3); XS20(3)];\n  pc(:,1) = total_angle(1) * [1; 1];\n\n  px(:,2) = [XS1(1); XS2(1)];\n  py(:,2) = [XS1(2); XS2(2)];\n  pz(:,2) = [XS1(3); XS2(3)];\n  pc(:,2) = total_angle(2) * [1; 1];\n\n  for i = 3 : max_vertices\n\n    ## Next streamline segment\n    X0 = X1;\n    X1 = sl(i,:);\n    R = X1 - X0;\n    RE = R / norm (R);\n\n    ## Project KE onto RE and get the difference in order to transport\n    ## the normal vector KE along the vertex array\n    Kp = KE - RE * dot (KE, RE);\n    KE = Kp / norm (Kp);\n\n    ## Apply angular rotation to KE\n    cp = cos (anlr_rot_sl(i - 1));\n    sp = sin (anlr_rot_sl(i - 1));\n    KE = rotation (KE, RE, cp, sp).';\n\n    XS1 = - width2 * KE + X1;\n    XS2 = width2 * KE + X1;\n\n    px(:,i) = [XS1(1); XS2(1)];\n    py(:,i) = [XS1(2); XS2(2)];\n    pz(:,i) = [XS1(3); XS2(3)];\n    pc(:,i) = total_angle(i) * [1; 1];\n\n  endfor\n\n  h = surface (hax, px, py, pz, pc);\n\nendfunction\n\n## Interpolate speed and divergence onto the streamline vertices and\n## return the first chunck of valid samples until a singularity /\n## zero is hit or the streamline vertex array \"sl\" ends\nfunction [lin_spd_sl, anlr_spd_sl, max_vertices] = ...\n                               interp_sl (x, y, z, lin_spd, anlr_spd, sl)\n\n  anlr_spd_sl = interp3 (x, y, z, anlr_spd, sl(:,1), sl(:,2), sl(:,3));\n  lin_spd_sl = interp3 (x, y, z, lin_spd, sl(:,1), sl(:,2), sl(:,3));\n\n  is_singular_anlr_spd = find (isnan (anlr_spd_sl), 1, \"first\");\n  is_zero_lin_spd = find (lin_spd_sl == 0, 1, \"first\");\n\n  max_vertices = rows (sl);\n  if (! isempty (is_singular_anlr_spd))\n    max_vertices = min (max_vertices, is_singular_anlr_spd - 1);\n  endif\n  if (! isempty (is_zero_lin_spd))\n    max_vertices = min (max_vertices, is_zero_lin_spd - 1);\n  endif\n\nendfunction\n\n## N normal to X, so that N is in span ([0 0 1], X)\n## If not possible then span ([1 0 0], X)\nfunction N = get_normal2 (X)\n\n  if ((X(1) == 0) && (X(2) == 0))\n    A = [1, 0, 0];\n  else\n    A = [0, 0, 1];\n  endif\n\n  ## Project A onto X and get the difference\n  N = A - X * dot (A, X) / (norm (X)^2);\n  N /= norm (N);\n\nendfunction\n\n## Rotate X around U where |U| = 1\n## cp = cos (angle), sp = sin (angle)\nfunction Y = rotation (X, U, cp, sp)\n\n  ux = U(1);\n  uy = U(2);\n  uz = U(3);\n\n  Y(1,:) = X(1) * (cp + ux * ux * (1 - cp)) + ...\n           X(2) * (ux * uy * (1 - cp) - uz * sp) + ...\n           X(3) * (ux * uz * (1 - cp) + uy * sp);\n\n  Y(2,:) = X(1) * (uy * ux * (1 - cp) + uz * sp) + ...\n           X(2) * (cp + uy * uy * (1 - cp)) + ...\n           X(3) * (uy * uz * (1 - cp) - ux * sp);\n\n  Y(3,:) = X(1) * (uz * ux * (1 - cp) - uy * sp) + ...\n           X(2) * (uz * uy * (1 - cp) + ux * sp) + ...\n           X(3) * (cp + uz * uz * (1 - cp));\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x, y, z] = meshgrid (0:0.2:4, -1:0.2:1, -1:0.2:1);\n%! u = - x + 10;\n%! v = 10 * z.*x;\n%! w = - 10 * y.*x;\n%! sx = [0, 0];\n%! sy = [0, 0.6];\n%! sz = [0, 0];\n%! streamribbon (x, y, z, u, v, w, sx, sy, sz);\n%! hold on;\n%! quiver3 (x, y, z, u, v, w);\n%! colormap (jet);\n%! shading interp;\n%! camlight (\"headlight\");\n%! view (3);\n%! axis tight equal off;\n%! set (gca, \"cameraviewanglemode\", \"manual\");\n%! hcb = colorbar;\n%! title (hcb, \"Angle\");\n%! title (\"Streamribbon\");\n\n%!demo\n%! clf;\n%! t = (0:pi/50:2*pi).';\n%! xyz{1} = [cos(t), sin(t), 0*t];\n%! twist{1} = ones (numel (t), 1) * pi / (numel (t) - 1);\n%! streamribbon (xyz, twist, 0.5);\n%! colormap (jet);\n%! view (3);\n%! camlight (\"headlight\");\n%! axis tight equal off;\n%! title (\"Moebius Strip\");\n\n## Test input validation\n%!error <Invalid call> streamribbon ()\n%!error <Invalid call> streamribbon (1)\n%!error <Invalid call> streamribbon (1,2,3,4,5)\n%!error <Invalid call> streamribbon (1,2,3,4,5,6,7,8)\n%!error <Invalid call> streamribbon (1,2,3,4,5,6,7,8,9,10,11)\n%!error <WIDTH must be a real scalar . 0> streamribbon (1,2,3,1i)\n%!error <WIDTH must be a real scalar . 0> streamribbon (1,2,3,0)\n%!error <WIDTH must be a real scalar . 0> streamribbon (1,2,3,-1)\n%!error <ANLR_ROT must have same length as XYZ> streamribbon ({[1,1,1;2,2,2]},{[1,1,1]})\n"
  },
  {
    "path": "scripts/plot/draw/streamtube.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} streamtube (@var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} streamtube (@var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})\n## @deftypefnx {} {} streamtube (@var{xyz}, @var{x}, @var{y}, @var{z}, @var{div})\n## @deftypefnx {} {} streamtube (@var{xyz}, @var{div})\n## @deftypefnx {} {} streamtube (@var{xyz}, @var{dia})\n## @deftypefnx {} {} streamtube (@dots{}, @var{options})\n## @deftypefnx {} {} streamtube (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} streamtube (@dots{})\n## Plot tubes scaled by the divergence along streamlines.\n##\n## @code{streamtube} draws tubes whose diameter is scaled by the divergence of\n## a vector field.  The vector field is given by\n## @code{[@var{u}, @var{v}, @var{w}]} and is defined over a rectangular grid\n## given by @code{[@var{x}, @var{y}, @var{z}]}.  The tubes start at the\n## seed points @code{[@var{sx}, @var{sy}, @var{sz}]} and are plot along\n## streamlines.\n##\n## @code{streamtube} can also be called with a cell array containing\n## pre-computed streamline data.  To do this, @var{xyz} must be created with\n## the @code{stream3} command.  @var{div} is used to scale the tubes.\n## In order to plot tubes scaled by the vector field divergence, @var{div}\n## must be calculated with the @code{divergence} command.\n##\n## A tube diameter of zero corresponds to the smallest scaling value along the\n## streamline and the largest tube diameter corresponds to the largest scaling\n## value.\n##\n## It is also possible to draw a tube along an arbitrary array of vertices\n## @var{xyz}.  The tube diameter can be specified by the vertex array @var{dia}\n## or by a constant.\n##\n## The input parameter @var{options} is a 2-D vector of the form\n## @code{[@var{scale}, @var{n}]}.  The first parameter scales the tube\n## diameter (default 1).  The second parameter specifies the number of vertices\n## that are used to construct the tube circumference (default 20).\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the plot objects\n## created for each tube.\n##\n## @seealso{stream3, streamline, streamribbon, ostreamtube}\n## @end deftypefn\n\nfunction h = streamtube (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"streamtube\", varargin{:});\n\n  options = [];\n  xyz = [];\n  div = [];\n  dia = [];\n  switch (nargin)\n    case 2\n      ## \"dia\" can be a cell array or a constant\n      if (iscell (varargin{2}) || numel (varargin{2}) == 1)\n        [xyz, dia] = varargin{:};\n      else\n        [xyz, div] = varargin{:};\n        [m, n, p] = size (div);\n        [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n      endif\n    case 3\n      if (iscell (varargin{2}))\n        [xyz, dia, options] = varargin{:};\n      else\n        [xyz, div, options] = varargin{:};\n        [m, n, p] = size (div);\n        [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n      endif\n    case 5\n        [xyz, x, y, z, div] = varargin{:};\n    case 6\n      if (iscell (varargin{1}))\n        [xyz, x, y, z, div, options] = varargin{:};\n      else\n        [u, v, w, spx, spy, spz] = varargin{:};\n        [m, n, p] = size (u);\n        [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n      endif\n    case 7\n      [u, v, w, spx, spy, spz, options] = varargin{:};\n      [m, n, p] = size (u);\n      [x, y, z] = meshgrid (1:n, 1:m, 1:p);\n    case 9\n      [x, y, z, u, v, w, spx, spy, spz] = varargin{:};\n    case 10\n      [x, y, z, u, v, w, spx, spy, spz, options] = varargin{:};\n    otherwise\n      print_usage ();\n  endswitch\n\n  scale = 1;\n  num_circum = 20;\n  if (! isempty (options))\n    switch (numel (options))\n      case 1\n        scale = options(1);\n      case 2\n        scale = options(1);\n        num_circum = options(2);\n      otherwise\n        error (\"streamtube: OPTIONS must be a 1- or 2-element vector\");\n    endswitch\n\n    if (! isreal (scale) || scale <= 0)\n      error (\"streamtube: SCALE must be a real scalar > 0\");\n    endif\n    if (! isreal (num_circum) || num_circum < 3)\n      error (\"streamtube: number of tube vertices N must be greater than 2\");\n    endif\n    num_circum = fix (num_circum);\n  endif\n\n  if (isempty (xyz))\n    xyz = stream3 (x, y, z, u, v, w, spx, spy, spz, 0.2);\n  endif\n\n  if (isempty (div) && isempty (dia))\n    div = divergence (x, y, z, u, v, w);\n  endif\n\n  if (! isempty (dia) && iscell (dia))\n    for i = 1 : length (xyz)\n      if (rows (dia{i}) != rows (xyz{i}))\n        error (\"streamtube: DIA must have same length then XYZ\");\n      endif\n    endfor\n  endif\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  ## Derive final scale factor from the bounding box diagonal\n  mxx = mnx = mxy = mny = mxz = mnz = [];\n  j = 1;\n  for i = 1 : length (xyz)\n    sl = xyz{i};\n    if (! isempty (sl))\n      slx = sl(:,1); sly = sl(:,2); slz = sl(:,3);\n      mxx(j) = max (slx); mnx(j) = min (slx);\n      mxy(j) = max (sly); mny(j) = min (sly);\n      mxz(j) = max (slz); mnz(j) = min (slz);\n      j += 1;\n    endif\n  endfor\n  dx = max (mxx) - min (mnx);\n  dy = max (mxy) - min (mny);\n  dz = max (mxz) - min (mnz);\n  clen = scale * sqrt (dx*dx + dy*dy + dz*dz) / 40;\n\n  h = [];\n  for i = 1 : length (xyz)\n    sl = xyz{i};\n    num_vertices = rows (sl);\n    if (! isempty (sl) && num_vertices > 1)\n      if (isempty (dia))\n\n        ## Plot a tube based on normalized divergence\n        [div_sl, max_vertices] = interp_sl (x, y, z, div, sl);\n        if (max_vertices > 1)\n          ## Nomalize the divergence along the streamline\n          mn = min (div_sl);\n          mx = max (div_sl);\n          if (mn == mx)\n            radius_sl = clen * ones (max_vertices, 1);\n          else\n            radius_sl = clen * (div_sl - mn) / (mx - mn);\n          endif\n          htmp = plottube (hax, sl, radius_sl, max_vertices, num_circum);\n          h = [h; htmp];\n        endif\n\n      else\n\n        ## Plot a tube from external data (vertex array or constant)\n        if (iscell (dia))\n          radius_sl = 0.5 * scale * dia{i};\n        else\n          radius_sl = 0.5 * scale * dia * ones (1, num_vertices);\n        endif\n        htmp = plottube (hax, sl, radius_sl, num_vertices, num_circum);\n        h = [h; htmp];\n\n      endif\n    endif\n  endfor\n\nendfunction\n\nfunction h = plottube (hax, sl, radius_sl, max_vertices, num_circum)\n\n  phi = linspace (0, 2*pi, num_circum);\n  cp = cos (phi);\n  sp = sin (phi);\n\n  ## 1st streamline segment\n  X0 = sl(1,:);\n  X1 = sl(2,:);\n  R = X1 - X0;\n  RE = R / norm (R);\n\n  ## Guide point and its rotation to create a segment\n  KE = get_normal1 (RE);\n  K = radius_sl(1) * KE;\n  XS0 = rotation (K, RE, cp, sp) + repmat (X0.', 1, num_circum);\n  K = radius_sl(2) * KE;\n  XS = rotation (K, RE, cp, sp) + repmat (X1.', 1, num_circum);\n\n  px = zeros (num_circum, max_vertices);\n  py = zeros (num_circum, max_vertices);\n  pz = zeros (num_circum, max_vertices);\n\n  px(:,1) = XS0(1,:).';\n  py(:,1) = XS0(2,:).';\n  pz(:,1) = XS0(3,:).';\n\n  px(:,2) = XS(1,:).';\n  py(:,2) = XS(2,:).';\n  pz(:,2) = XS(3,:).';\n\n  for i = 3 : max_vertices\n\n    ## Next streamline segment\n    X0 = X1;\n    X1 = sl(i,:);\n    R = X1 - X0;\n    RE = R / norm (R);\n\n    ## Project KE onto RE and get the difference in order to transport\n    ## the normal vector KE along the vertex array\n    Kp = KE - RE * dot (KE, RE);\n    KE = Kp / norm (Kp);\n    K = radius_sl(i) * KE;\n\n    ## Rotate around RE and collect surface patches\n    XS = rotation (K, RE, cp, sp) + repmat (X1.', 1, num_circum);\n\n    px(:,i) = XS(1,:).';\n    py(:,i) = XS(2,:).';\n    pz(:,i) = XS(3,:).';\n\n  endfor\n\n  h = surface (hax, px, py, pz);\n\nendfunction\n\n## Interpolate onto the streamline vertices and return the first chunck of\n## valid samples until a singularity is hit (NaN or +-Inf) or\n## the streamline vertex array \"sl\" ends\nfunction [div_sl_crop, max_vertices] = interp_sl (x, y, z, div, sl)\n\n  div_sl = interp3 (x, y, z, div, sl(:,1), sl(:,2), sl(:,3));\n  is_nan = find (isnan (div_sl), 1, \"first\");\n  is_inf = find (isinf (div_sl), 1, \"first\");\n\n  max_vertices = rows (sl);\n  if (! isempty (is_nan))\n    max_vertices = min (max_vertices, is_nan - 1);\n  endif\n  if (! isempty (is_inf))\n    max_vertices = min (max_vertices, is_inf - 1);\n  endif\n\n  div_sl_crop = div_sl(1 : max_vertices);\n\nendfunction\n\n## Arbitrary N normal to X\nfunction N = get_normal1 (X)\n\n  if ((X(3) == 0) && (X(1) == -X(2)))\n    N = [(- X(2) - X(3)), X(1), X(1)];\n  else\n    N = [X(3), X(3), (- X(1) - X(2))];\n  endif\n\n  N /= norm (N);\n\nendfunction\n\n## Rotate X around U where |U| = 1\n## cp = cos (angle), sp = sin (angle)\nfunction Y = rotation (X, U, cp, sp)\n\n  ux = U(1);\n  uy = U(2);\n  uz = U(3);\n\n  Y(1,:) = X(1) * (cp + ux * ux * (1 - cp)) + ...\n           X(2) * (ux * uy * (1 - cp) - uz * sp) + ...\n           X(3) * (ux * uz * (1 - cp) + uy * sp);\n\n  Y(2,:) = X(1) * (uy * ux * (1 - cp) + uz * sp) + ...\n           X(2) * (cp + uy * uy * (1 - cp)) + ...\n           X(3) * (uy * uz * (1 - cp) - ux * sp);\n\n  Y(3,:) = X(1) * (uz * ux * (1 - cp) - uy * sp) + ...\n           X(2) * (uz * uy * (1 - cp) + ux * sp) + ...\n           X(3) * (cp + uz * uz * (1 - cp));\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [x, y, z] = meshgrid (-3:0.15:3, -1:0.1:1, -1:0.1:1);\n%! u = 2 + 8 * exp (-2.0*x.*x);\n%! v = zeros (size (x));\n%! w = zeros (size (x));\n%! h = streamtube (x, y, z, u, v, w, -3, 0, 0, [5, 60]);\n%! set (h, \"facecolor\", \"r\", \"edgecolor\", \"none\");\n%! hold on;\n%! camlight ();\n%! lighting gouraud;\n%! view (3);\n%! grid on;\n%! quiver3 (x, y, z, u, v, w);\n%! axis tight equal;\n%! title (\"Divergence Plot\");\n\n%!demo\n%! clf;\n%! t = 0:.15:15;\n%! xyz{1} = [cos(t)', sin(t)', (t/3)'];\n%! dia{1} = cos(t)';\n%! streamtube (xyz, dia);\n%! grid on;\n%! axis tight equal;\n%! colormap (jet);\n%! shading interp;\n%! camlight ();\n%! lighting gouraud;\n%! view (3);\n%! title (\"Plot Arbitrary Tube\");\n\n## Test input validation\n%!error <Invalid call> streamtube ()\n%!error <Invalid call> streamtube (1)\n%!error <Invalid call> streamtube (1,2,3,4)\n%!error <Invalid call> streamtube (1,2,3,4,5,6,7,8)\n%!error <Invalid call> streamtube (1,2,3,4,5,6,7,8,9,10,11)\n%!error <OPTIONS must be a 1- or 2-element vector> streamtube (1,2,[1,2,3])\n%!error <SCALE must be a real scalar . 0> streamtube (1,2,[1i])\n%!error <SCALE must be a real scalar . 0> streamtube (1,2,[0])\n%!error <SCALE must be a real scalar . 0> streamtube (1,2,[-1])\n%!error <N must be greater than 2> streamtube (1,2,[1,1i])\n%!error <N must be greater than 2> streamtube (1,2,[1,2])\n%!error <DIA must have same length then XYZ> streamtube ({[1,1,1;2,2,2]},{[1,1,1]})\n"
  },
  {
    "path": "scripts/plot/draw/surf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} surf (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} surf (@var{z})\n## @deftypefnx {} {} surf (@dots{}, @var{c})\n## @deftypefnx {} {} surf (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} surf (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} surf (@dots{})\n## Plot a 3-D surface mesh.\n##\n## The surface mesh is plotted using shaded rectangles.  The vertices of the\n## rectangles [@var{x}, @var{y}] are typically the output of @code{meshgrid}.\n## over a 2-D rectangular region in the x-y plane.  @var{z} determines the\n## height above the plane of each vertex.  If only a single @var{z} matrix is\n## given, then it is plotted over the meshgrid\n## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})}.\n## Thus, columns of @var{z} correspond to different @var{x} values and rows\n## of @var{z} correspond to different @var{y} values.\n##\n## The color of the surface is computed by linearly scaling the @var{z} values\n## to fit the range of the current colormap.  Use @code{clim} and/or\n## change the colormap to control the appearance.\n##\n## Optionally, the color of the surface can be specified independently of\n## @var{z} by supplying a color matrix, @var{c}.\n##\n## Any property/value pairs are passed directly to the underlying surface\n## object.  The full list of properties is documented at\n## @ref{Surface Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## Note: The exact appearance of the surface can be controlled with the\n## @code{shading} command or by using @code{set} to control surface object\n## properties.\n## @seealso{ezsurf, surfc, surfl, surfnorm, trisurf, contour, mesh, surface,\n## meshgrid, hidden, shading, colormap, clim}\n## @end deftypefn\n\nfunction h = surf (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"surf\", varargin{:});\n\n  hax = newplot (hax);\n\n  htmp = surface (hax, varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! Z = peaks ();\n%! surf (Z);\n%! title ({\"surf() plot of peaks() function\"; \"color determined by height Z\"});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! Z = sombrero ();\n%! [Fx,Fy] = gradient (Z);\n%! surf (Z, Fx+Fy);\n%! shading interp;\n%! title ({\"surf() plot of peaks() function\"; ...\n%!         \"facecolor is interpolated, color determined by gradient of Z\"});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [X,Y,Z] = sombrero ();\n%! [~,Fy] = gradient (Z);\n%! surf (X, Y, Z, Fy);\n%! shading interp;\n%! title ({\"surf() plot of peaks() function\"; ...\n%!         \"facecolor is interpolated, color determined by Y-gradient of Z\"});\n"
  },
  {
    "path": "scripts/plot/draw/surface.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} surface (@var{x}, @var{y}, @var{z}, @var{c})\n## @deftypefnx {} {} surface (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} surface (@var{z}, @var{c})\n## @deftypefnx {} {} surface (@var{z})\n## @deftypefnx {} {} surface (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} surface (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} surface (@dots{})\n## Create a surface graphic object given matrices @var{x} and @var{y} from\n## @code{meshgrid} and a matrix of values @var{z} corresponding to the\n## @var{x} and @var{y} coordinates of the surface.\n##\n## If @var{x} and @var{y} are vectors, then a typical vertex is\n## (@var{x}(j), @var{y}(i), @var{z}(i,j)).  Thus, columns of @var{z} correspond\n## to different @var{x} values and rows of @var{z} correspond to different\n## @var{y} values.  If only a single input @var{z} is given then @var{x} is\n## taken to be @code{1:columns (@var{z})} and @var{y} is\n## @code{1:rows (@var{z})}.\n##\n## Any property/value input pairs are assigned to the surface object.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## Programming Note: The full list of properties is documented at\n## @ref{Surface Properties}.\n## @seealso{surf, mesh, patch, line}\n## @end deftypefn\n\nfunction h = surface (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"surface\", varargin{:});\n\n  if (isempty (hax))\n    hax = gca ();\n  else\n    hax = hax(1);\n  endif\n\n  [htmp, bad_usage] = __surface__ (hax, varargin{:});\n\n  if (bad_usage)\n    print_usage ();\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\nfunction [h, bad_usage] = __surface__ (ax, varargin)\n\n  h = 0;\n  bad_usage = false;\n  firststring = find (cellfun (\"isclass\", varargin, \"char\"), 1);\n  if (isempty (firststring))\n    firststring = nargin;\n  endif\n\n  switch (firststring)\n    case 5\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      c = varargin{4};\n\n      if (iscomplex (x) || iscomplex (y) || iscomplex (z) || iscomplex (c))\n        error (\"mesh: X, Y, Z, C arguments must be real\");\n      endif\n\n      [z_nr, z_nc] = size (z);\n      [c_nr, c_nc, c_np] = size (c);\n      if (! (z_nr == c_nr && z_nc == c_nc && (c_np == 1 || c_np == 3)))\n        error (\"surface: Z and C must have the same size\");\n      endif\n\n      if (isvector (x) && isvector (y) && ismatrix (z))\n        if (rows (z) == length (y) && columns (z) == length (x))\n          x = x(:)';\n          y = y(:);\n        else\n          error (\"surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)\");\n        endif\n      elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))\n        if (! size_equal (x, y, z))\n          error (\"surface: X, Y, and Z must have the same dimensions\");\n        endif\n      else\n        error (\"surface: X and Y must be vectors and Z must be a matrix\");\n      endif\n\n    case 4\n      x = varargin{1};\n      y = varargin{2};\n      z = varargin{3};\n      c = z;\n\n      if (iscomplex (x) || iscomplex (y) || iscomplex (z))\n        error (\"mesh: X, Y, Z arguments must be real\");\n      endif\n\n      if (isvector (x) && isvector (y) && ismatrix (z))\n        if (rows (z) == length (y) && columns (z) == length (x))\n          x = x(:)';\n          y = y(:);\n        else\n          error (\"surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)\");\n        endif\n      elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))\n        if (! size_equal (x, y, z))\n          error (\"surface: X, Y, and Z must have the same dimensions\");\n        endif\n      else\n        error (\"surface: X and Y must be vectors and Z must be a matrix\");\n      endif\n\n    case 3\n      z = varargin{1};\n      c = varargin{2};\n\n      if (iscomplex (z) || iscomplex (c))\n        error (\"mesh: X, C arguments must be real\");\n      endif\n\n      if (ismatrix (z) && ! isvector (z) && ! isscalar (z))\n        [nr, nc] = size (z);\n        x = 1:nc;\n        y = (1:nr)';\n      else\n        error (\"surface: Z argument must be a matrix\");\n      endif\n\n    case 2\n      z = varargin{1};\n      c = z;\n\n      if (iscomplex (z))\n        error (\"mesh: Z argument must be real\");\n      endif\n\n      if (ismatrix (z) && ! isvector (z) && ! isscalar (z))\n        [nr, nc] = size (z);\n        x = 1:nc;\n        y = (1:nr)';\n      else\n        error (\"surface: Z argument must be a matrix\");\n      endif\n\n    case 1\n      x = 1:3;\n      y = x';\n      c = z = eye (3);\n\n    otherwise\n      bad_usage = true;\n      return;\n\n  endswitch\n\n  if (firststring < nargin)\n    other_args = varargin(firststring:end);\n  else\n    other_args = {};  # make a default surface object.\n  endif\n  h = __go_surface__ (ax, \"xdata\", x, \"ydata\", y, \"zdata\", z, \"cdata\", c,\n                      other_args{:});\n\n  ## FIXME: ishold called this way is very slow.\n  if (! ishold (ax))\n    set (ax, \"view\", [0, 90]);\n  endif\n\nendfunction\n\n\n## Functional tests for surface() are in surf.m, surfc.m, surfl.m, and pcolor.m\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = surface ();\n%!   assert (findobj (hf, \"type\", \"surface\"), h);\n%!   assert (get (h, \"xdata\"), 1:3, eps);\n%!   assert (get (h, \"ydata\"), (1:3)', eps);\n%!   assert (get (h, \"zdata\"), eye (3));\n%!   assert (get (h, \"cdata\"), eye (3));\n%!   assert (get (h, \"type\"), \"surface\");\n%!   assert (get (h, \"linestyle\"), get (0, \"defaultsurfacelinestyle\"));\n%!   assert (get (h, \"linewidth\"), get (0, \"defaultsurfacelinewidth\"), eps);\n%!   assert (get (h, \"marker\"), get (0, \"defaultsurfacemarker\"));\n%!   assert (get (h, \"markersize\"), get (0, \"defaultsurfacemarkersize\"));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/draw/surfc.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} surfc (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} surfc (@var{z})\n## @deftypefnx {} {} surfc (@dots{}, @var{c})\n## @deftypefnx {} {} surfc (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} surfc (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} surfc (@dots{})\n## Plot a 3-D surface mesh with underlying contour lines.\n##\n## The surface mesh is plotted using shaded rectangles.  The vertices of the\n## rectangles [@var{x}, @var{y}] are typically the output of @code{meshgrid}.\n## over a 2-D rectangular region in the x-y plane.  @var{z} determines the\n## height above the plane of each vertex.  If only a single @var{z} matrix is\n## given, then it is plotted over the meshgrid\n## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})}.\n## Thus, columns of @var{z} correspond to different @var{x} values and rows\n## of @var{z} correspond to different @var{y} values.\n##\n## The color of the surface is computed by linearly scaling the @var{z} values\n## to fit the range of the current colormap.  Use @code{clim} and/or\n## change the colormap to control the appearance.\n##\n## Optionally, the color of the surface can be specified independently of\n## @var{z} by supplying a color matrix, @var{c}.\n##\n## Any property/value pairs are passed directly to the underlying surface\n## object.  The full list of properties is documented at\n## @ref{Surface Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## Note: The exact appearance of the surface can be controlled with the\n## @code{shading} command or by using @code{set} to control surface object\n## properties.\n## @seealso{ezsurfc, surf, surfl, surfnorm, trisurf, contour, mesh, surface,\n## meshgrid, hidden, shading, colormap, clim}\n## @end deftypefn\n\nfunction h = surfc (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"surfc\", varargin{:});\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  hax = newplot (hax);\n\n  surfc_props = {\"facecolor\", \"flat\"};\n  chararg = find (cellfun (\"isclass\", varargin, \"char\"), 1);\n  if (isempty (chararg))\n    htmp = surface (hax, varargin{:}, surfc_props{:});\n  else\n    htmp = surface (hax, varargin{1:chararg-1}, surfc_props{:},\n                         varargin{chararg:end});\n  endif\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\",\n              \"xlimmode\", \"manual\", \"ylimmode\", \"manual\");\n  endif\n\n  drawnow ();\n\n  ## don't pass string arguments to __contour__()\n  stop_idx = find (cellfun (\"isclass\", varargin, \"char\"), 1);\n  if (isempty (stop_idx))\n    stop_idx = nargin;\n  else\n    stop_idx -= 1;\n  endif\n\n  if (stop_idx - 1 == 1 || stop_idx - 1 == 3)\n    ## Don't pass a color matrix c to __contour__\n    stop_idx -= 1;\n  endif\n\n  zmin = get (hax, \"zlim\")(1);\n  [~, htmp2] = __contour__ (hax, zmin, varargin{1:stop_idx});\n\n  htmp = [htmp; htmp2];\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! Z = peaks ();\n%! surfc (Z);\n%! title (\"surfc() combines surf/contour plots\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! Z = sombrero ();\n%! [Fx,Fy] = gradient (Z);\n%! surfc (Z, Fx+Fy);\n%! shading interp;\n%! title ({\"surfc() plot of sombrero() function\"; ...\n%!         \"facecolor is interpolated, color determined by gradient of Z\"});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [X,Y,Z] = sombrero ();\n%! [~,Fy] = gradient (Z);\n%! surfc (X,Y,Z,Fy);\n%! shading interp;\n%! title ({\"surfc() plot of peaks() function\"; ...\n%!         \"facecolor is interpolated, color determined by Y-gradient of Z\"});\n"
  },
  {
    "path": "scripts/plot/draw/surfl.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} surfl (@var{z})\n## @deftypefnx {} {} surfl (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} surfl (@dots{}, @var{lsrc})\n## @deftypefnx {} {} surfl (@var{x}, @var{y}, @var{z}, @var{lsrc}, @var{P})\n## @deftypefnx {} {} surfl (@dots{}, \"cdata\")\n## @deftypefnx {} {} surfl (@dots{}, \"light\")\n## @deftypefnx {} {} surfl (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} surfl (@dots{})\n## Plot a 3-D surface using shading based on various lighting models.\n##\n## The surface mesh is plotted using shaded rectangles.  The vertices of the\n## rectangles [@var{x}, @var{y}] are typically the output of @code{meshgrid}.\n## over a 2-D rectangular region in the x-y plane.  @var{z} determines the\n## height above the plane of each vertex.  If only a single @var{z} matrix is\n## given, then it is plotted over the meshgrid\n## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})}.\n## Thus, columns of @var{z} correspond to different @var{x} values and rows\n## of @var{z} correspond to different @var{y} values.\n##\n## The default lighting mode @qcode{\"cdata\"}, changes the cdata property of the\n## surface object to give the impression of a lighted surface.\n##\n## The alternate mode @qcode{\"light\"} creates a light object to illuminate the\n## surface.\n##\n## The light source location may be specified using @var{lsrc} which can be\n## a 2-element vector [azimuth, elevation] in degrees, or a 3-element vector\n## [lx, ly, lz].  The default value is rotated 45 degrees counterclockwise to\n## the current view.\n##\n## The material properties of the surface can specified using a 4-element\n## vector @var{P} = [@var{AM} @var{D} @var{SP} @var{exp}] which defaults to\n## @var{p} = [0.55 0.6 0.4 10].\n##\n## @table @asis\n## @item @qcode{\"AM\"} strength of ambient light\n##\n## @item @qcode{\"D\"} strength of diffuse reflection\n##\n## @item @qcode{\"SP\"} strength of specular reflection\n##\n## @item @qcode{\"EXP\"} specular exponent\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## Example:\n##\n## @example\n## @group\n## colormap (bone (64));\n## surfl (peaks);\n## shading interp;\n## @end group\n## @end example\n## @seealso{diffuse, specular, surf, shading, colormap, clim}\n## @end deftypefn\n\nfunction h = surfl (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"surfl\", varargin{:});\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  ## Check for lighting type.\n  use_cdata = true;\n  if (ischar (varargin{end}))\n    switch (lower (varargin{end}))\n      case \"light\"\n        use_cdata = false;\n      case \"cdata\"\n        use_cdata = true;\n      otherwise\n        error (\"surfl: unknown lighting method\");\n    endswitch\n    varargin(end) = [];\n  endif\n\n  ## Check for reflection properties argument.\n  ##\n  ## r = [ambient light strength,\n  ##      diffuse reflection strength,\n  ##      specular reflection strength,\n  ##      specular shine]\n  if (isnumeric (varargin{end}) && isvector (varargin{end})\n      && (numel (varargin{end}) == 4))\n    r = varargin{end};\n    varargin(end) = [];\n  else\n    ## Default values.\n    r = [0.55, 0.6, 0.4, 10];\n  endif\n\n  ## Check for light vector (lv) argument.\n  have_lv = false;\n  if (isnumeric (varargin{end}) && isvector (varargin{end}))\n    len = numel (varargin{end});\n    lastarg = varargin{end};\n    if (len == 3)\n      lv = lastarg;\n      varargin(end) = [];\n      have_lv = true;\n    elseif (len == 2)\n      [lv(1), lv(2), lv(3)] = sph2cart ((lastarg(1) - 90) * pi/180,\n                                         lastarg(2) * pi/180,\n                                         1.0);\n      varargin(end) = [];\n      have_lv = true;\n    endif\n  endif\n\n  hax = newplot (hax);\n\n  htmp = surface (hax, varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  endif\n\n  ## Get view vector (vv).\n  [az, el] = view (hax);\n  [vv(1), vv(2), vv(3)] = sph2cart ((az - 90) * pi/180.0, el * pi/180.0, 1.0);\n\n  if (! have_lv)\n    ## Calculate light vector (lv) from view vector.\n    phi = pi / 4;  # 45 degrees\n    R = [cos(phi), -sin(phi), 0;\n         sin(phi),  cos(phi), 0;\n         0,         0,        1];\n    lv = (R * vv.').';\n  endif\n\n  if (use_cdata)\n    set (hax, \"clim\", [0 1]);\n\n    __update_normals__ (htmp);\n    vn = get (htmp, \"vertexnormals\");\n    dar = get (hax, \"dataaspectratio\");\n    vn(:,:,1) *= dar(1);\n    vn(:,:,2) *= dar(2);\n    vn(:,:,3) *= dar(3);\n\n    ## Normalize vn.\n    vn ./= repmat (sqrt (sumsq (vn, 3)), [1, 1, 3]);\n    [nr, nc] = size (get (htmp, \"zdata\"));\n\n    ## Ambient, diffuse, and specular term.\n    cdata = (  r(1) * ones (nr, nc)\n             + r(2) * diffuse  (vn(:,:,1), vn(:,:,2), vn(:,:,3), lv)\n             + r(3) * specular (vn(:,:,1), vn(:,:,2), vn(:,:,3), lv, vv, r(4)));\n    cdata ./= sum (r(1:3));\n\n    set (htmp, \"cdata\", cdata);\n  else\n    light (hax, \"position\", lv);\n    set (htmp, \"ambientstrength\", r(1), \"diffusestrength\", r(2), ...\n               \"specularstrength\", r(3), \"specularexponent\", r(4));\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! [X,Y,Z] = sombrero ();\n%! colormap (copper (64));\n%! surfl (X,Y,Z);\n%! shading interp;\n%! title (\"surfl() with defaults\");\n\n%!demo\n%! clf;\n%! [X,Y,Z] = sombrero ();\n%! colormap (copper (64));\n%! surfl (X,Y,Z, [62.50,30], [0.2 0.6 0.4 25]);\n%! shading interp;\n%! title (\"surfl() with lighting vector and material properties\");\n\n%!demo\n%! clf;\n%! [X, Y] = meshgrid (-3:1/8:3);\n%! Z = peaks (X, Y);\n%! surfl (X, Y, Z, \"light\");\n%! shading interp;\n%! title (\"surfl() with light object\");\n"
  },
  {
    "path": "scripts/plot/draw/surfnorm.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} surfnorm (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} surfnorm (@var{z})\n## @deftypefnx {} {} surfnorm (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} surfnorm (@var{hax}, @dots{})\n## @deftypefnx {} {[@var{Nx}, @var{Ny}, @var{Nz}] =} surfnorm (@dots{})\n## Find the vectors normal to a meshgridded surface.\n##\n## If @var{x} and @var{y} are vectors, then a typical vertex is\n## (@var{x}(j), @var{y}(i), @var{z}(i,j)).  Thus, columns of @var{z} correspond\n## to different @var{x} values and rows of @var{z} correspond to different\n## @var{y} values.  If only a single input @var{z} is given then @var{x} is\n## taken to be @code{1:columns (@var{z})} and @var{y} is\n## @code{1:rows (@var{z})}.\n##\n## If no return arguments are requested, a surface plot with the normal\n## vectors to the surface is plotted.\n##\n## Any property/value input pairs are assigned to the surface object.  The full\n## list of properties is documented at @ref{Surface Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## If output arguments are requested then the components of the normal\n## vectors are returned in @var{Nx}, @var{Ny}, and @var{Nz} and no plot is\n## made.  The normal vectors are unnormalized (magnitude != 1).  To normalize,\n## use\n##\n## @example\n## @group\n## len = sqrt (nx.^2 + ny.^2 + nz.^2);\n## nx ./= len;  ny ./= len;  nz ./= len;\n## @end group\n## @end example\n##\n## An example of the use of @code{surfnorm} is\n##\n## @example\n## surfnorm (peaks (25));\n## @end example\n##\n## Algorithm: The normal vectors are calculated by taking the cross product\n## of the diagonals of each of the quadrilateral faces in the meshgrid to find\n## the normal vectors at the center of each face.  Next, for each meshgrid\n## point the four nearest normal vectors are averaged to obtain the final\n## normal to the surface at the meshgrid point.\n##\n## For surface objects, the @qcode{\"VertexNormals\"} property contains\n## equivalent information, except possibly near the boundary of the surface\n## where different interpolation schemes may yield slightly different values.\n##\n## @seealso{isonormals, quiver3, surf, meshgrid}\n## @end deftypefn\n\nfunction [Nx, Ny, Nz] = surfnorm (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"surfnorm\", varargin{:});\n\n  if (nargin == 0 || nargin == 2)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    z = varargin{1};\n    [x, y] = meshgrid (1:columns (z), 1:rows (z));\n    ioff = 2;\n  else\n    x = varargin{1};\n    y = varargin{2};\n    z = varargin{3};\n    ioff = 4;\n  endif\n\n  if (iscomplex (z) || iscomplex (x) || iscomplex (y))\n    error (\"surfnorm: X, Y, and Z must be 2-D real matrices\");\n  endif\n  if (! size_equal (x, y, z))\n    error (\"surfnorm: X, Y, and Z must have the same dimensions\");\n  endif\n\n  ## FIXME: Matlab uses a bicubic interpolation, not linear, along the boundary.\n  ## Do a linear extrapolation for mesh points on the boundary so that the mesh\n  ## is increased by 1 on each side.  This allows each original meshgrid point\n  ## to be surrounded by four quadrilaterals and the same calculation can be\n  ## used for interior and boundary points.  The extrapolation works badly for\n  ## closed surfaces like spheres.\n  xx = [2 * x(:,1) - x(:,2), x, 2 * x(:,end) - x(:,end-1)];\n  xx = [2 * xx(1,:) - xx(2,:); xx; 2 * xx(end,:) - xx(end-1,:)];\n  yy = [2 * y(:,1) - y(:,2), y, 2 * y(:,end) - y(:,end-1)];\n  yy = [2 * yy(1,:) - yy(2,:); yy; 2 * yy(end,:) - yy(end-1,:)];\n  zz = [2 * z(:,1) - z(:,2), z, 2 * z(:,end) - z(:,end-1)];\n  zz = [2 * zz(1,:) - zz(2,:); zz; 2 * zz(end,:) - zz(end-1,:)];\n\n  u.x = xx(1:end-1,1:end-1) - xx(2:end,2:end);\n  u.y = yy(1:end-1,1:end-1) - yy(2:end,2:end);\n  u.z = zz(1:end-1,1:end-1) - zz(2:end,2:end);\n  v.x = xx(1:end-1,2:end) - xx(2:end,1:end-1);\n  v.y = yy(1:end-1,2:end) - yy(2:end,1:end-1);\n  v.z = zz(1:end-1,2:end) - zz(2:end,1:end-1);\n\n  c = cross ([u.x(:), u.y(:), u.z(:)], [v.x(:), v.y(:), v.z(:)]);\n  w.x = reshape (c(:,1), size (u.x));\n  w.y = reshape (c(:,2), size (u.y));\n  w.z = reshape (c(:,3), size (u.z));\n\n  ## Create normal vectors as mesh vectices from normals at mesh centers\n  nx = (w.x(1:end-1,1:end-1) + w.x(1:end-1,2:end) +\n        w.x(2:end,1:end-1) + w.x(2:end,2:end)) / 4;\n  ny = (w.y(1:end-1,1:end-1) + w.y(1:end-1,2:end) +\n        w.y(2:end,1:end-1) + w.y(2:end,2:end)) / 4;\n  nz = (w.z(1:end-1,1:end-1) + w.z(1:end-1,2:end) +\n        w.z(2:end,1:end-1) + w.z(2:end,2:end)) / 4;\n\n  if (nargout == 0)\n    hax = newplot (hax);\n\n    surf (hax, x, y, z, varargin{ioff:end});\n    old_hold_state = get (hax, \"nextplot\");\n    unwind_protect\n      set (hax, \"nextplot\", \"add\");\n\n      ## Normalize the normal vectors\n      nmag = sqrt (nx.^2 + ny.^2 + nz.^2);\n\n      ## And correct for the aspect ratio of the display\n      daratio = daspect (hax);\n      damag = sqrt (sumsq (daratio));\n\n      ## FIXME: May also want to normalize the vectors relative to the size\n      ##        of the diagonal.\n\n      nx ./= nmag / (daratio(1)^2 / damag);\n      ny ./= nmag / (daratio(2)^2 / damag);\n      nz ./= nmag / (daratio(3)^2 / damag);\n\n      plot3 (hax, [x(:).'; x(:).' + nx(:).' ; NaN(size(x(:).'))](:),\n                  [y(:).'; y(:).' + ny(:).' ; NaN(size(y(:).'))](:),\n                  [z(:).'; z(:).' + nz(:).' ; NaN(size(z(:).'))](:),\n                  \"r\");\n\n    unwind_protect_cleanup\n      set (hax, \"nextplot\", old_hold_state);\n    end_unwind_protect\n\n  else\n    Nx = nx;\n    Ny = ny;\n    Nz = nz;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! surfnorm (peaks (19));\n%! shading faceted;\n%! title ({\"surfnorm() shows surface and normals at each vertex\", ...\n%!         \"peaks() function with 19 faces\"});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! [x, y, z] = sombrero (10);\n%! surfnorm (x, y, z);\n%! title ({\"surfnorm() shows surface and normals at each vertex\", ...\n%!         \"sombrero() function with 10 faces\"});\n\n## Test input validation\n%!error <Invalid call> surfnorm ()\n%!error <Invalid call> surfnorm (1,2)\n%!error <X, Y, and Z must be 2-D real matrices> surfnorm (i)\n%!error <X, Y, and Z must be 2-D real matrices> surfnorm (i, 1, 1)\n%!error <X, Y, and Z must be 2-D real matrices> surfnorm (1, i, 1)\n%!error <X, Y, and Z must be 2-D real matrices> surfnorm (1, 1, i)\n%!error <X, Y, and Z must have the same dimensions> surfnorm ([1 2], 1, 1)\n%!error <X, Y, and Z must have the same dimensions> surfnorm (1, [1 2], 1)\n%!error <X, Y, and Z must have the same dimensions> surfnorm (1, 1, [1 2])\n"
  },
  {
    "path": "scripts/plot/draw/tetramesh.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} tetramesh (@var{T}, @var{X})\n## @deftypefnx {} {} tetramesh (@var{T}, @var{X}, @var{C})\n## @deftypefnx {} {} tetramesh (@dots{}, @var{property}, @var{val}, @dots{})\n## @deftypefnx {} {@var{h} =} tetramesh (@dots{})\n## Display the tetrahedrons defined in the m-by-4 matrix @var{T} as 3-D\n## patches.\n##\n## @var{T} is typically the output of a Delaunay triangulation of a 3-D set\n## of points.  Every row of @var{T} contains four indices into the n-by-3\n## matrix @var{X} of the vertices of a tetrahedron.  Every row in @var{X}\n## represents one point in 3-D space.\n##\n## The vector @var{C} specifies the color of each tetrahedron as an index\n## into the current colormap.  The default value is 1:m where m is the number\n## of tetrahedrons; the indices are scaled to map to the full range of the\n## colormap.  If there are more tetrahedrons than colors in the colormap then\n## the values in @var{C} are cyclically repeated.\n##\n## Calling @code{tetramesh (@dots{}, \"property\", \"value\", @dots{})} passes all\n## property/value pairs directly to the patch function as additional arguments.\n## The full list of properties is documented at @ref{Patch Properties}.\n##\n## The optional return value @var{h} is a vector of patch handles where each\n## handle represents one tetrahedron in the order given by @var{T}.\n## A typical use case for @var{h} is to turn the respective patch\n## @qcode{\"visible\"} property @qcode{\"on\"} or @qcode{\"off\"}.\n##\n## Type @code{demo tetramesh} to see examples on using @code{tetramesh}.\n## @seealso{trimesh, delaunay, delaunayn, patch}\n## @end deftypefn\n\nfunction h = tetramesh (varargin)\n\n  [reg, prop] = parseparams (varargin);\n\n  if (numel (reg) < 2 || numel (reg) > 3)\n    print_usage ();\n  endif\n\n  T = reg{1};\n  X = reg{2};\n\n  if (! ismatrix (T) || columns (T) != 4)\n    error (\"tetramesh: T must be an n-by-4 matrix\");\n  elseif (! ismatrix (X) || columns (X) != 3)\n    error (\"tetramesh: X must be an n-by-3 matrix\");\n  endif\n\n  size_T = rows (T);\n  cmap = colormap ();\n\n  if (length (reg) < 3)\n    size_cmap = rows (cmap);\n    C = mod ((1:size_T)' - 1, size_cmap) + 1;\n    if (size_T < size_cmap && size_T > 1)\n      ## expand to the available range of colors\n      C = floor ((C - 1) * (size_cmap - 1) / (size_T - 1)) + 1;\n    endif\n  else\n    C = reg{3};\n    if (! isvector (C) || size_T != length (C))\n      error (\"tetramesh: C must be a vector of the same length as T\");\n    endif\n  endif\n\n  hax = newplot ();\n\n  hvec = zeros (size_T, 1);\n  if (strcmp (graphics_toolkit (), \"gnuplot\"))\n    ## Tiny reduction of the tetrahedron size to help gnuplot by\n    ## avoiding identical faces with different colors\n    for i = 1:size_T\n      [th, p] = __shrink__ ([1 2 3 4], X(T(i, :), :), 1 - 1e-7);\n      hvec(i) = patch (\"Faces\", th, \"Vertices\", p,\n                       \"FaceColor\", cmap(C(i), :), \"FaceAlpha\", 0.9,\n                       prop{:});\n    endfor\n  else\n    ## FLTK does not support FaceAlpha.\n    for i = 1:size_T\n      th = [1 2 3; 2 3 4; 3 4 1; 4 1 2];\n      hvec(i) = patch (\"Faces\", th, \"Vertices\", X(T(i, :), :),\n                       \"FaceColor\", cmap(C(i), :), \"FaceAlpha\", 1.0,\n                       prop{:});\n    endfor\n  endif\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30]);\n  endif\n\n  if (nargout > 0)\n    h = hvec;\n  endif\n\nendfunction\n\n## shrink the tetrahedron relative to its center of gravity\nfunction [tri, p] = __shrink__ (T, X, sf)\n  midpoint = repmat (sum (X(T, :), 1) / 4, 12, 1);\n  p = [X([1 2 3], :); X([2 3 4], :); X([3 4 1], :); X([4 1 2], :)];\n  p = sf * (p - midpoint) + midpoint;\n  tri = reshape (1:12, 3, 4)';\nendfunction\n\n\n%!demo\n%! clf;\n%! d = [-1 1];\n%! [x,y,z] = meshgrid (d, d, d);\n%! x = [x(:); 0];\n%! y = [y(:); 0];\n%! z = [z(:); 0];\n%! tetra = delaunay (x, y, z);\n%! X = [x(:) y(:) z(:)];\n%! colormap (jet (64));\n%! h = tetramesh (tetra, X);\n%! set (h(1:2:end), \"visible\", \"off\");\n%! axis equal;\n%! view (30, 20);\n%! title ({\"tetramesh() plot\", ...\n%!         \"colormap = jet (64), every other tetrahedron invisible\"});\n\n%!demo\n%! clf;\n%! d = [-1 1];\n%! [x,y,z] = meshgrid (d, d, d);\n%! x = [x(:); 0];\n%! y = [y(:); 0];\n%! z = [z(:); 0];\n%! tetra = delaunay (x, y, z);\n%! X = [x(:) y(:) z(:)];\n%! colormap (gray (256));\n%! tetramesh (tetra, X, 21:20:241, \"EdgeColor\", \"w\");\n%! axis equal;\n%! view (30, 20);\n%! title ({\"tetramesh() plot\", ...\n%!         \"colormap = gray (256) with white edges\"});\n"
  },
  {
    "path": "scripts/plot/draw/trimesh.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} trimesh (@var{tri}, @var{x}, @var{y}, @var{z}, @var{c})\n## @deftypefnx {} {} trimesh (@var{tri}, @var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} trimesh (@var{tri}, @var{x}, @var{y})\n## @deftypefnx {} {} trimesh (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {@var{h} =} trimesh (@dots{})\n## Plot a 3-D triangular wireframe mesh.\n##\n## In contrast to @code{mesh}, which plots a mesh using rectangles,\n## @code{trimesh} plots the mesh using triangles.\n##\n## @var{tri} is typically the output of a Delaunay triangulation over the\n## grid of @var{x}, @var{y}.  Every row of @var{tri} represents one triangle\n## and contains three indices into [@var{x}, @var{y}] which are the\n## vertices of the triangles in the x-y plane.  @var{z} determines the\n## height above the plane of each vertex.  If no @var{z} input is given then\n## the triangles are plotted as a 2-D figure.\n##\n## The color of the trimesh is computed by linearly scaling the @var{z} values\n## to fit the range of the current colormap.  Use @code{clim} and/or\n## change the colormap to control the appearance.\n##\n## Optionally, the color of the mesh can be specified independently of @var{z}\n## by supplying @var{c}, which is a vector for colormap data, or a matrix with\n## three columns for RGB data.  The number of colors specified in @var{c} must\n## either equal the number of vertices in @var{z} or the number of triangles\n## in @var{tri}.\n##\n## Any property/value pairs are passed directly to the underlying patch object.\n## The full list of properties is documented at @ref{Patch Properties}.\n##\n## The optional return value @var{h} is a graphics handle to the created patch\n## object.\n## @seealso{mesh, tetramesh, triplot, trisurf, delaunay, patch, hidden}\n## @end deftypefn\n\nfunction h = trimesh (tri, x, y, z, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  if (nargin == 3)\n    htmp = triplot (tri, x, y);\n  elseif (ischar (z))\n    htmp = triplot (tri, x, y, z, varargin{:});\n  else\n    ## Process color argument\n    if (nargin > 4 && isnumeric (varargin{1}))\n      c = varargin{1};\n      varargin(1) = [];\n      if (isvector (c))\n        c = c(:);\n      endif\n      if (rows (c) != numel (z) && rows (c) != rows (tri))\n        error (\"trimesh: the numbers of colors specified in C must equal the number of vertices in Z or the number of triangles in TRI\");\n      elseif (columns (c) != 1 && columns (c) != 3)\n        error (\"trimesh: TrueColor C matrix must have 3 columns\");\n      endif\n    else\n      c = z(:);\n    endif\n\n    hax = newplot ();\n\n    ## Tag object as \"trimesh\" so that hidden() can find it.\n    htmp = patch (\"Faces\", tri, \"Vertices\", [x(:), y(:), z(:)],\n                  \"FaceVertexCdata\", c, \"EdgeColor\", \"flat\", \"FaceColor\", \"w\",\n                  \"FaceLighting\", \"none\", \"EdgeLighting\", \"flat\",\n                  \"Tag\", \"trimesh\", varargin{:});\n\n    if (! ishold (hax))\n      set (hax, \"view\", [-37.5, 30],\n                \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n    endif\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 10);\n%! N = 10;\n%! x = 3 - 6 * rand (N, N);\n%! y = 3 - 6 * rand (N, N);\n%! z = peaks (x, y);\n%! tri = delaunay (x(:), y(:));\n%! trimesh (tri, x(:), y(:), z(:));\n%! title (\"trimesh() plot of sparsely-sampled peaks() function\");\n\n## Test input validation\n%!error <Invalid call> trimesh ()\n%!error <Invalid call> trimesh (1)\n%!error <Invalid call> trimesh (1,2)\n%!error <the numbers of colors> trimesh (1,2,3,4,[5 6])\n%!error <the numbers of colors> trimesh (1,2,3,4,[5 6]')\n%!error <the numbers of colors> trimesh ([1;1],[2;2],[3;3],[4;4], zeros (3,3))\n%!error <TrueColor C matrix must have 3 columns>\n%! trimesh ([1;1],[2;2],[3;3],[4;4],zeros (2,2))\n"
  },
  {
    "path": "scripts/plot/draw/triplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} triplot (@var{tri}, @var{x}, @var{y})\n## @deftypefnx {} {} triplot (@var{tri}, @var{x}, @var{y}, @var{linespec})\n## @deftypefnx {} {@var{h} =} triplot (@dots{})\n## Plot a 2-D triangular mesh.\n##\n## @var{tri} is typically the output of a Delaunay triangulation over the\n## grid of @var{x}, @var{y}.  Every row of @var{tri} represents one triangle\n## and contains three indices into [@var{x}, @var{y}] which are the\n## vertices of the triangles in the x-y plane.\n##\n## The linestyle to use for the plot can be defined with the argument\n## @var{linespec} of the same format as the @code{plot} command.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## patch object.\n## @seealso{plot, trimesh, trisurf, delaunay}\n## @end deftypefn\n\nfunction h = triplot (tri, x, y, varargin)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  idx = tri(:, [1, 2, 3, 1]).';\n  nt = rows (tri);\n  htmp = plot ([x(idx); NaN(1, nt)](:),\n               [y(idx); NaN(1, nt)](:), varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 2);\n%! N = 20;\n%! x = rand (N, 1);\n%! y = rand (N, 1);\n%! tri = delaunay (x, y);\n%! triplot (tri, x, y);\n%! title (\"triplot() of random 2-D Delaunay triangulation\");\n"
  },
  {
    "path": "scripts/plot/draw/trisurf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} trisurf (@var{tri}, @var{x}, @var{y}, @var{z}, @var{c})\n## @deftypefnx {} {} trisurf (@var{tri}, @var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} trisurf (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {@var{h} =} trisurf (@dots{})\n## Plot a 3-D triangular surface.\n##\n## In contrast to @code{surf}, which plots a surface mesh using rectangles,\n## @code{trisurf} plots the mesh using triangles.\n##\n## @var{tri} is typically the output of a Delaunay triangulation over the\n## grid of @var{x}, @var{y}.  Every row of @var{tri} represents one triangle\n## and contains three indices into [@var{x}, @var{y}] which are the vertices of\n## the triangles in the x-y plane.  @var{z} determines the height above the\n## plane of each vertex.\n##\n## The color of the trisurf is computed by linearly scaling the @var{z} values\n## to fit the range of the current colormap.  Use @code{clim} and/or change\n## the colormap to control the appearance.\n##\n## Optionally, the color of the mesh can be specified independently of @var{z}\n## by supplying @var{c}, which is a vector for colormap data, or a matrix with\n## three columns for RGB data.  The number of colors specified in @var{c} must\n## either equal the number of vertices in @var{z} or the number of triangles\n## in @var{tri}.  When specifying the color at each vertex the triangle will\n## be colored according to the color of the first vertex only (see patch\n## documentation and the @qcode{\"FaceColor\"} property when set to\n## @qcode{\"flat\"}).\n##\n## Any property/value pairs are passed directly to the underlying patch object.\n##  The full list of properties is documented at @ref{Patch Properties}.\n##\n## The optional return value @var{h} is a graphics handle to the created patch\n## object.\n## @seealso{surf, triplot, trimesh, delaunay, patch, shading}\n## @end deftypefn\n\nfunction h = trisurf (tri, x, y, z, varargin)\n\n  if (nargin < 4)\n    print_usage ();\n  endif\n\n  if (nargin > 4 && isnumeric (varargin{1}))\n    c = varargin{1};\n    varargin(1) = [];\n    if (isvector (c))\n      c = c(:);\n    endif\n    if (rows (c) != numel (z) && rows (c) != rows (tri))\n      error (\"trisurf: the numbers of colors specified in C must equal the number of vertices in Z or the number of triangles in TRI\");\n    elseif (columns (c) != 1 && columns (c) != 3)\n      error (\"trisurf: TrueColor C matrix must have 3 columns\");\n    endif\n  else\n    c = z(:);\n  endif\n  ## For Matlab compatibility:\n  if (! any (strcmpi (varargin, \"FaceColor\")))\n    varargin(end+(1:2)) = {\"FaceColor\", \"flat\"};\n  endif\n\n  hax = newplot ();\n\n  htmp = patch (\"Faces\", tri, \"Vertices\", [x(:), y(:), z(:)],\n                \"FaceVertexCData\", c, varargin{:});\n\n  if (! ishold (hax))\n    set (hax, \"view\", [-37.5, 30],\n              \"xgrid\", \"on\", \"ygrid\", \"on\", \"zgrid\", \"on\");\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! N = 31;\n%! [x, y] = meshgrid (1:N);\n%! tri = delaunay (x(:), y(:));\n%! z = peaks (N);\n%! h = trisurf (tri, x, y, z, \"facecolor\", \"flat\");\n%! axis tight;\n%! zlim auto;\n%! title ({\"trisurf() of peaks() function\", 'facecolor = \"flat\"'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! N = 31;\n%! [x, y] = meshgrid (1:N);\n%! tri = delaunay (x(:), y(:));\n%! z = peaks (N);\n%! h = trisurf (tri, x, y, z, \"facecolor\", \"interp\");\n%! axis tight;\n%! zlim auto;\n%! title ({\"trisurf() of peaks() function\", 'facecolor = \"interp\"'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 10);\n%! N = 10;\n%! x = 3 - 6 * rand (N, N);\n%! y = 3 - 6 * rand (N, N);\n%! z = peaks (x, y);\n%! tri = delaunay (x(:), y(:));\n%! trisurf (tri, x(:), y(:), z(:));\n%! title (\"trisurf () of sparsely-sampled triangulation of peaks ()\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! x = rand (100, 1);\n%! y = rand (100, 1);\n%! z = x.^2 + y.^2;\n%! tri = delaunay (x, y);\n%! trisurf (tri, x, y, z);\n%! title ({\"trisurf() of random data\", 'default \"facecolor\" = \"flat\", \"edgecolor\" = \"black\"'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! x = rand (100, 1);\n%! y = rand (100, 1);\n%! z = x.^2 + y.^2;\n%! tri = delaunay (x, y);\n%! trisurf (tri, x, y, z, \"facecolor\", \"interp\");\n%! title ({\"trisurf() of random data\", '\"facecolor\" = \"interp\"'});\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! x = rand (100, 1);\n%! y = rand (100, 1);\n%! z = x.^2 + y.^2;\n%! tri = delaunay (x, y);\n%! trisurf (tri, x, y, z, \"facecolor\", \"interp\", \"edgecolor\", \"w\");\n%! title ({\"trisurf() of random data\", '\"facecolor\" = \"interp\", \"edgecolor\" = \"white\"'});\n\n## Test input validation\n%!error <Invalid call> trisurf ()\n%!error <Invalid call> trisurf (1)\n%!error <Invalid call> trisurf (1,2)\n%!error <Invalid call> trisurf (1,2,3)\n%!error <the numbers of colors> trisurf (1,2,3,4,[5 6])\n%!error <the numbers of colors> trisurf (1,2,3,4,[5 6]')\n%!error <the numbers of colors> trisurf ([1;1],[2;2],[3;3],[4;4], zeros (3,3))\n%!error <TrueColor C matrix must have 3 columns>\n%! trisurf ([1;1],[2;2],[3;3],[4;4], zeros (2,2))\n"
  },
  {
    "path": "scripts/plot/draw/waterfall.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} waterfall (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {} waterfall (@var{z})\n## @deftypefnx {} {} waterfall (@dots{}, @var{c})\n## @deftypefnx {} {} waterfall (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} waterfall (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} waterfall (@dots{})\n## Plot a 3-D waterfall plot.\n##\n## A waterfall plot is similar to a @code{meshz} plot except only\n## mesh lines for the rows of @var{z} (x-values) are shown.\n##\n## The wireframe mesh is plotted using rectangles.  The vertices of the\n## rectangles [@var{x}, @var{y}] are typically the output of @code{meshgrid}.\n## over a 2-D rectangular region in the x-y plane.  @var{z} determines the\n## height above the plane of each vertex.  If only a single @var{z} matrix is\n## given, then it is plotted over the meshgrid\n## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})}.\n## Thus, columns of @var{z} correspond to different @var{x} values and rows\n## of @var{z} correspond to different @var{y} values.\n##\n## The color of the mesh is computed by linearly scaling the @var{z} values\n## to fit the range of the current colormap.  Use @code{clim} and/or\n## change the colormap to control the appearance.\n##\n## Optionally the color of the mesh can be specified independently of @var{z}\n## by supplying a color matrix, @var{c}.\n##\n## Any property/value pairs are passed directly to the underlying surface\n## object.  The full list of properties is documented at\n## @ref{Surface Properties}.\n##\n## If the first argument @var{hax} is an axes handle, then plot into this axes,\n## rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## surface object.\n##\n## @seealso{meshz, mesh, meshc, contour, surf, surface, ribbon, meshgrid,\n## hidden, shading, colormap, clim}\n## @end deftypefn\n\nfunction h = waterfall (varargin)\n\n  htmp = meshz (varargin{:});\n\n  set (htmp, \"meshstyle\", \"row\");\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! Z = peaks ();\n%! waterfall (Z);\n%! title (\"waterfall() plot of peaks() function\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! Z = peaks ();\n%! subplot (1,2,1)\n%!  meshz (Z);\n%!  daspect ([2.5, 2.5, 1]);\n%!  title (\"meshz() plot\");\n%! subplot (1,2,2)\n%!  waterfall (Z);\n%!  daspect ([2.5, 2.5, 1]);\n%!  title (\"waterfall() plot\");\n"
  },
  {
    "path": "scripts/plot/draw/xline.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} xline (@var{x})\n## @deftypefnx {} {} xline (@var{x}, @var{linespec})\n## @deftypefnx {} {} xline (@var{x}, @var{linespec}, @var{labels})\n## @deftypefnx {} {} xline (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} xline (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} xline (@dots{})\n## Create vertical lines at x-coordinates specified by @var{x}.\n##\n## @var{x} is a scalar or vector of x-coordinates where vertical lines\n## are to be drawn.\n##\n## The optional @var{linespec} argument specifies the line style and color\n## using the same format as @code{plot}.  For example, @qcode{\"r\"} for a red\n## solid line, @qcode{\"--b\"} for a blue dashed line, or @qcode{\":k\"} for a\n## black dotted line.  If not specified, a solid black line is used.\n##\n## The optional @var{labels} argument specifies labels for the lines.  It can\n## be a single string, a cell array of strings for a multiline label (when\n## @var{x} is scalar), or a cell array with one element per line (when @var{x}\n## is a vector).\n##\n## Additional property/value pairs are passed directly to the underlying line\n## object.  The full list of line properties is documented at\n## @ref{Line Properties}.  Commonly used properties include:\n##\n## @table @code\n## @item Color\n## Line color specified as an RGB triplet, a color name, or a short name.\n##\n## @item LineStyle\n## Line style: @qcode{\"-\"} (solid, default), @qcode{\"--\"} (dashed),\n## @qcode{\":\"} (dotted), or @qcode{\"-.\"} (dash-dot).\n##\n## @item LineWidth\n## Width of the line (default is 0.5).\n##\n## @item Alpha\n## Line transparency (0 = fully transparent, 1 = fully opaque).\n##\n## @item Label\n## Text label to display on the line.\n##\n## @item LabelHorizontalAlignment\n## Horizontal alignment of label relative to the line: @qcode{\"left\"} (label\n## left of line), @qcode{\"center\"}, or @qcode{\"right\"} (label right of line,\n## default).\n##\n## @item LabelVerticalAlignment\n## Vertical alignment of label: @qcode{\"top\"} (default), @qcode{\"middle\"}, or\n## @qcode{\"bottom\"}.\n##\n## @item LabelOrientation\n## Orientation of label text: @qcode{\"aligned\"} (rotated 90@textdegree{}, default)\n## or @qcode{\"horizontal\"}.\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then draw the lines\n## in this axes, rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle (or vector of\n## handles for multiple lines) to the created constant line objects.\n##\n## Example:\n##\n## @example\n## @group\n## plot (rand (1, 10) * 10, 1:10);\n## xline (5, \"--r\", \"Threshold\");\n## @end group\n## @end example\n##\n## @example\n## @group\n## plot (1:100);\n## xline ([25, 50, 75], \":\", @{\"Q1\", \"Median\", \"Q3\"@});\n## @end group\n## @end example\n##\n## @seealso{yline, line, plot}\n## @end deftypefn\n\nfunction h = xline (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"xline\", varargin{:});\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Get x values\n  xval = varargin{1};\n  if (! isnumeric (xval) || ! isreal (xval))\n    error (\"xline: X must be a real numeric scalar or vector\");\n  endif\n  if (! isvector (xval) && ! isempty (xval))\n    error (\"xline: X must be a scalar or vector, not a matrix\");\n  endif\n  if (isempty (xval))\n    ## Nothing to plot\n    if (nargout > 0)\n      h = zeros (0, 1);\n    endif\n    return;\n  endif\n  xval = xval(:).';  # ensure row vector\n\n  ## Filter out NaN and Inf values\n  valid_idx = isfinite (xval);\n  if (! all (valid_idx))\n    warning (\"xline: ignoring non-finite values in X\");\n    xval = xval(valid_idx);\n    if (isempty (xval))\n      if (nargout > 0)\n        h = zeros (0, 1);\n      endif\n      return;\n    endif\n  endif\n\n  ## Parse remaining arguments\n  linespec = \"\";\n  labels = {};\n  propargs = {};\n\n  idx = 2;\n  if (nargin >= 2 && ischar (varargin{2}))\n    ## Check if it's a linespec or a property name\n    [lstyle, valid] = __pltopt__ (\"xline\", varargin{2}, false);\n    if (valid)\n      linespec = varargin{2};\n      idx = 3;\n    endif\n  endif\n\n  ## Check for labels\n  if (nargin >= idx)\n    arg = varargin{idx};\n    if (ischar (arg) || iscellstr (arg))\n      ## Could be labels or property name\n      ## If next arg exists and is not a string, this is likely a property name\n      if (nargin > idx && ! ischar (varargin{idx + 1}))\n        ## This is a property name (like \"Color\" followed by a value)\n        propargs = varargin(idx:end);\n      elseif (ischar (arg) && nargin > idx && ischar (varargin{idx + 1}))\n        ## Two consecutive strings - first could be labels, or could be prop/val\n        ## Check if it looks like a known property\n        if (__is_graphics_property__ (arg))\n          propargs = varargin(idx:end);\n        else\n          ## Treat as label\n          labels = {arg};\n          idx += 1;\n          propargs = varargin(idx:end);\n        endif\n      elseif (iscellstr (arg))\n        labels = arg;\n        idx += 1;\n        propargs = varargin(idx:end);\n      elseif (ischar (arg))\n        if (__is_graphics_property__ (arg))\n          propargs = varargin(idx:end);\n        else\n          labels = {arg};\n          idx += 1;\n          propargs = varargin(idx:end);\n        endif\n      endif\n    else\n      propargs = varargin(idx:end);\n    endif\n  endif\n\n  ## Process property/value pairs to extract xline-specific properties\n  ## Standard line properties will be passed to the line object\n  labelhalign = \"right\";\n  labelvalign = \"top\";\n  labelorient = \"aligned\";\n  alpha = 1;\n\n  i = 1;\n  lineprops = {};\n  while (i <= numel (propargs))\n    prop = propargs{i};\n    if (! ischar (prop))\n      error (\"xline: property name must be a string\");\n    endif\n\n    if (i == numel (propargs))\n      error (\"xline: property '%s' requires a value\", prop);\n    endif\n    val = propargs{i + 1};\n\n    switch (lower (prop))\n      case \"label\"\n        if (ischar (val))\n          labels = {val};\n        elseif (iscellstr (val))\n          labels = val;\n        else\n          error (\"xline: Label must be a string or cell array of strings\");\n        endif\n      case \"labelhorizontalalignment\"\n        val = lower (val);\n        if (strcmp (val, \"middle\"))\n          val = \"center\";  # accept \"middle\" as alias for \"center\"\n        endif\n        if (! any (strcmp (val, {\"left\", \"center\", \"right\"})))\n          error (\"xline: LabelHorizontalAlignment must be 'left', 'center', or 'right'\");\n        endif\n        labelhalign = val;\n      case \"labelverticalalignment\"\n        val = lower (val);\n        if (strcmp (val, \"center\"))\n          val = \"middle\";  # accept \"center\" as alias for \"middle\"\n        endif\n        if (! any (strcmp (val, {\"top\", \"middle\", \"bottom\"})))\n          error (\"xline: LabelVerticalAlignment must be 'top', 'middle', or 'bottom'\");\n        endif\n        labelvalign = val;\n      case \"labelorientation\"\n        labelorient = val;\n      case \"alpha\"\n        alpha = val;\n      otherwise\n        lineprops{end+1} = prop;\n        lineprops{end+1} = val;\n    endswitch\n    i += 2;\n  endwhile\n\n  ## Parse linespec for color and linestyle\n  linecolor = [0, 0, 0];  # default black\n  linestyle = \"-\";        # default solid\n\n  if (! isempty (linespec))\n    [lstyle, ~] = __pltopt__ (\"xline\", linespec, false);\n    if (! isempty (lstyle.color))\n      linecolor = lstyle.color;\n    endif\n    if (! isempty (lstyle.linestyle))\n      linestyle = lstyle.linestyle;\n    endif\n  endif\n\n  ## Override with explicit property values\n  for i = 1:2:numel (lineprops)\n    switch (lower (lineprops{i}))\n      case \"color\"\n        linecolor = lineprops{i + 1};\n      case \"linestyle\"\n        linestyle = lineprops{i + 1};\n    endswitch\n  endfor\n\n  ## Validate labels\n  ## For a single x-value, a cell array with multiple elements is a multiline label\n  ## For multiple x-values, cell array elements map to each line\n  if (! isempty (labels))\n    if (numel (xval) == 1)\n      ## Single x-value\n      if (numel (labels) > 1)\n        ## Multiple labels means multiline - wrap for consistent indexing\n        labels = {labels};\n      endif\n      ## Single label - already in correct format {\"Label\"}, don't wrap again\n    elseif (numel (labels) == 1)\n      ## Single label for multiple x-values: replicate\n      labels = repmat (labels, 1, numel (xval));\n    elseif (numel (labels) != numel (xval))\n      error (\"xline: number of labels must match number of x-values\");\n    endif\n  endif\n\n  ## Get or create axes\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  ## Get current y-axis limits\n  ylim = get (hax, \"ylim\");\n\n  ## Store current hold state and set hold on\n  holdstate = ishold (hax);\n\n  ## Create lines\n  htmp = zeros (numel (xval), 1);\n\n  unwind_protect\n    hold (hax, \"on\");\n\n    for i = 1:numel (xval)\n      ## Create an hggroup to hold the line and optional label\n      hg = hggroup (\"parent\", hax, ...\n                    \"__appdata__\", struct (\"__creator__\", \"xline\"));\n      htmp(i) = hg;\n\n      ## Calculate label position and create text first (to get extent for centering)\n      ht = [];\n      text_extent = [];\n      if (! isempty (labels))\n        ## Calculate padding based on font size\n        fontsize = get (hax, \"fontsize\");  # in points\n        axpos = get (hax, \"position\");     # normalized units\n        figpos = get (ancestor (hax, \"figure\"), \"position\");  # pixels\n\n        ## Horizontal padding: ~1 character width\n        axes_width_pixels = axpos(3) * figpos(3);\n        xlim = get (hax, \"xlim\");\n        xrange = diff (xlim);\n        char_width_data = (0.6 * fontsize / axes_width_pixels) * xrange;\n\n        ## Vertical padding: ~1/3 character height\n        yrange = diff (ylim);\n        axes_height_pixels = axpos(4) * figpos(4);\n        char_height_data = (fontsize / axes_height_pixels) * yrange;\n        ypadding = char_height_data / 3;\n\n        ## Determine label x-position with horizontal offset from line\n        switch (lower (labelhalign))\n          case \"left\"\n            labelx = xval(i) - char_width_data;\n            text_halign = \"right\";  # text right-aligned so it appears left of line\n          case \"center\"\n            labelx = xval(i);\n            text_halign = \"center\";\n          case \"right\"\n            labelx = xval(i) + char_width_data;\n            text_halign = \"left\";   # text left-aligned so it appears right of line\n          otherwise\n            labelx = xval(i) + char_width_data;\n            text_halign = \"left\";\n        endswitch\n\n        ## Determine label y-position and alignment based on labelvalign\n        ## For rotated text, horizontalalignment controls vertical extent\n        switch (lower (labelvalign))\n          case \"top\"\n            labely = ylim(2) - ypadding;\n          case \"middle\"\n            labely = mean (ylim);\n          case \"bottom\"\n            labely = ylim(1) + ypadding;\n          otherwise\n            labely = ylim(2) - ypadding;\n        endswitch\n\n        ## Set text alignment based on rotation\n        if (strcmp (lower (labelorient), \"aligned\"))\n          ## For 90° rotated text, alignments swap roles:\n          ## - horizontalalignment controls vertical extent\n          ## - verticalalignment controls horizontal extent\n          switch (lower (labelvalign))\n            case \"top\"\n              rot_text_halign = \"right\";  # anchor at top, text extends down\n            case \"middle\"\n              rot_text_halign = \"center\";\n            case \"bottom\"\n              rot_text_halign = \"left\";   # anchor at bottom, text extends up\n            otherwise\n              rot_text_halign = \"right\";\n          endswitch\n\n          switch (lower (labelhalign))\n            case \"left\"\n              rot_text_valign = \"bottom\";  # anchor at right, text extends left\n            case \"center\"\n              rot_text_valign = \"middle\";\n            case \"right\"\n              rot_text_valign = \"top\";     # anchor at left, text extends right\n            otherwise\n              rot_text_valign = \"top\";\n          endswitch\n\n          ht = text (\"parent\", hg, ...\n                     \"position\", [labelx, labely, 0], ...\n                     \"string\", labels{i}, ...\n                     \"horizontalalignment\", rot_text_halign, ...\n                     \"verticalalignment\", rot_text_valign, ...\n                     \"rotation\", 90, ...\n                     \"color\", linecolor, ...\n                     \"clipping\", \"off\");\n        else\n          ## Non-rotated text uses standard alignment\n          ht = text (\"parent\", hg, ...\n                     \"position\", [labelx, labely, 0], ...\n                     \"string\", labels{i}, ...\n                     \"horizontalalignment\", text_halign, ...\n                     \"verticalalignment\", labelvalign, ...\n                     \"color\", linecolor, ...\n                     \"clipping\", \"off\");\n        endif\n      endif\n\n      ## Create the vertical line(s)\n      ## Split line if label is horizontally centered on the line\n      if (! isempty (labels) && strcmp (lower (labelhalign), \"center\"))\n        ## Calculate gap from font metrics\n        str = labels{i};\n        if (iscell (str))\n          num_lines = numel (str);\n          max_len = max (cellfun (@numel, str));\n        else\n          num_lines = 1;\n          max_len = numel (str);\n        endif\n\n        ## For rotated text (aligned), width becomes height and vice versa\n        if (strcmp (lower (labelorient), \"aligned\"))\n          ## Text is rotated 90 degrees, so character width contributes to vertical extent\n          text_visual_height = max_len * char_width_data * 1.2;\n        else\n          ## Text is horizontal\n          text_visual_height = num_lines * char_height_data * 1.2;\n        endif\n\n        ## Gap is centered at label y-position\n        gap_bottom = labely - text_visual_height / 2 - ypadding;\n        gap_top = labely + text_visual_height / 2 + ypadding;\n\n        ## Bottom segment\n        if (ylim(1) < gap_bottom)\n          hl1 = __go_line__ (hg, \"xdata\", [xval(i), xval(i)], ...\n                                 \"ydata\", [ylim(1), gap_bottom], ...\n                                 \"color\", linecolor, \"linestyle\", linestyle);\n          set (hl1, \"yliminclude\", \"off\");\n          for j = 1:2:numel (lineprops)\n            try\n              set (hl1, lineprops{j}, lineprops{j + 1});\n            catch\n            end_try_catch\n          endfor\n        endif\n\n        ## Top segment\n        if (gap_top < ylim(2))\n          hl2 = __go_line__ (hg, \"xdata\", [xval(i), xval(i)], ...\n                                 \"ydata\", [gap_top, ylim(2)], ...\n                                 \"color\", linecolor, \"linestyle\", linestyle);\n          set (hl2, \"yliminclude\", \"off\");\n          for j = 1:2:numel (lineprops)\n            try\n              set (hl2, lineprops{j}, lineprops{j + 1});\n            catch\n            end_try_catch\n          endfor\n        endif\n      else\n        ## Single continuous line\n        hl = __go_line__ (hg, \"xdata\", [xval(i), xval(i)], \"ydata\", ylim, ...\n                              \"color\", linecolor, \"linestyle\", linestyle);\n        set (hl, \"yliminclude\", \"off\");\n\n        for j = 1:2:numel (lineprops)\n          try\n            set (hl, lineprops{j}, lineprops{j + 1});\n          catch\n            ## Ignore properties that don't apply to line objects\n          end_try_catch\n        endfor\n      endif\n\n      ## Setup properties for the hggroup\n      ## Get linewidth from first line child\n      line_kids = findobj (hg, \"type\", \"line\");\n      if (! isempty (line_kids))\n        lw = get (line_kids(1), \"linewidth\");\n      else\n        lw = 0.5;  # default\n      endif\n\n      addproperty (\"value\", hg, \"data\", xval(i));\n      addproperty (\"color\", hg, \"linecolor\", linecolor);\n      addproperty (\"linestyle\", hg, \"linelinestyle\", linestyle);\n      addproperty (\"linewidth\", hg, \"linelinewidth\", lw);\n      addproperty (\"alpha\", hg, \"data\", alpha);\n\n      if (! isempty (labels))\n        addproperty (\"label\", hg, \"any\", labels{i});\n      else\n        addproperty (\"label\", hg, \"string\", \"\");\n      endif\n\n      addproperty (\"labelhorizontalalignment\", hg, \"string\", labelhalign);\n      addproperty (\"labelverticalalignment\", hg, \"string\", labelvalign);\n      addproperty (\"labelorientation\", hg, \"string\", labelorient);\n\n      ## Add listeners for property updates\n      addlistener (hg, \"color\", @update_line_props);\n      addlistener (hg, \"linestyle\", @update_line_props);\n      addlistener (hg, \"linewidth\", @update_line_props);\n      addlistener (hg, \"value\", @update_line_data);\n\n      ## Add listener for ylim changes to update line extent\n      ylim_listener = {@update_ylim, hg};\n      addlistener (hax, \"ylim\", ylim_listener);\n\n      ## Add delete function to clean up listener\n      set (hg, \"deletefcn\", {@cleanup_listeners, hax, ylim_listener});\n\n    endfor\n\n  unwind_protect_cleanup\n    if (! holdstate)\n      hold (hax, \"off\");\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n## Check if a string is a known graphics property\nfunction retval = __is_graphics_property__ (str)\n  known_props = {\"color\", \"linestyle\", \"linewidth\", \"alpha\", \"label\", ...\n                 \"labelhorizontalalignment\", \"labelverticalalignment\", ...\n                 \"labelorientation\", \"parent\", \"visible\", \"handlevisibility\", ...\n                 \"displayname\", \"tag\", \"userdata\"};\n  retval = any (strcmpi (str, known_props));\nendfunction\n\n\n## Callback to update line properties\nfunction update_line_props (hg, ~)\n  kids = get (hg, \"children\");\n  for i = 1:numel (kids)\n    if (strcmp (get (kids(i), \"type\"), \"line\"))\n      set (kids(i), \"color\", get (hg, \"color\"), ...\n                    \"linestyle\", get (hg, \"linestyle\"), ...\n                    \"linewidth\", get (hg, \"linewidth\"));\n    elseif (strcmp (get (kids(i), \"type\"), \"text\"))\n      set (kids(i), \"color\", get (hg, \"color\"));\n    endif\n  endfor\nendfunction\n\n\n## Callback to update line x-coordinate\nfunction update_line_data (hg, ~)\n  xval = get (hg, \"value\");\n  kids = get (hg, \"children\");\n  for i = 1:numel (kids)\n    if (strcmp (get (kids(i), \"type\"), \"line\"))\n      set (kids(i), \"xdata\", [xval, xval]);\n    elseif (strcmp (get (kids(i), \"type\"), \"text\"))\n      pos = get (kids(i), \"position\");\n      pos(1) = xval;\n      set (kids(i), \"position\", pos);\n    endif\n  endfor\nendfunction\n\n\n## Callback to update line y-extent when axes limits change\nfunction update_ylim (hax, ~, hg)\n  if (! ishghandle (hg))\n    return;\n  endif\n  ylim = get (hax, \"ylim\");\n  kids = get (hg, \"children\");\n  labelvalign = get (hg, \"labelverticalalignment\");\n\n  ## Calculate vertical padding based on font size\n  fontsize = get (hax, \"fontsize\");\n  axpos = get (hax, \"position\");\n  figpos = get (ancestor (hax, \"figure\"), \"position\");\n  axes_height_pixels = axpos(4) * figpos(4);\n  yrange = diff (ylim);\n  char_height_data = (fontsize / axes_height_pixels) * yrange;\n  ypadding = char_height_data / 4;\n\n  ## Find text and line children\n  text_kid = [];\n  line_kids = [];\n  for i = 1:numel (kids)\n    if (strcmp (get (kids(i), \"type\"), \"text\"))\n      text_kid = kids(i);\n    elseif (strcmp (get (kids(i), \"type\"), \"line\"))\n      line_kids(end+1) = kids(i);\n    endif\n  endfor\n\n  ## Update text position\n  if (! isempty (text_kid))\n    pos = get (text_kid, \"position\");\n    switch (lower (labelvalign))\n      case \"top\"\n        pos(2) = ylim(2) - ypadding;\n      case \"middle\"\n        pos(2) = mean (ylim);\n      case \"bottom\"\n        pos(2) = ylim(1) + ypadding;\n    endswitch\n    set (text_kid, \"position\", pos);\n  endif\n\n  ## Update line(s)\n  labelhalign = get (hg, \"labelhorizontalalignment\");\n  if (strcmp (lower (labelhalign), \"center\") && ! isempty (text_kid) ...\n      && numel (line_kids) >= 2)\n    ## Split line case - calculate gap around text from font metrics\n    str = get (text_kid, \"string\");\n    if (iscell (str))\n      num_lines = numel (str);\n      max_len = max (cellfun (@numel, str));\n    else\n      num_lines = 1;\n      max_len = numel (str);\n    endif\n\n    ## Calculate char width in data units\n    axes_width_pixels = axpos(3) * figpos(3);\n    xrange = diff (get (hax, \"xlim\"));\n    char_width_data = (0.6 * fontsize / axes_width_pixels) * xrange;\n\n    ## Check if text is rotated\n    rotation = get (text_kid, \"rotation\");\n    if (abs (rotation - 90) < 1 || abs (rotation - 270) < 1)\n      ## Text is rotated 90 degrees, so character width contributes to vertical extent\n      text_visual_height = max_len * char_width_data * 1.2;\n    else\n      ## Text is horizontal\n      text_visual_height = num_lines * char_height_data * 1.2;\n    endif\n\n    ## Gap is centered at text position\n    text_pos = get (text_kid, \"position\");\n    gap_bottom = text_pos(2) - text_visual_height / 2 - ypadding;\n    gap_top = text_pos(2) + text_visual_height / 2 + ypadding;\n\n    ## Identify which segment is bottom and which is top by current position\n    for i = 1:numel (line_kids)\n      ydata = get (line_kids(i), \"ydata\");\n      ymid = mean (ydata);\n      if (ymid < mean (ylim))\n        ## This is the bottom segment\n        set (line_kids(i), \"ydata\", [ylim(1), gap_bottom]);\n      else\n        ## This is the top segment\n        set (line_kids(i), \"ydata\", [gap_top, ylim(2)]);\n      endif\n    endfor\n  else\n    ## Single continuous line or non-centered label\n    for i = 1:numel (line_kids)\n      set (line_kids(i), \"ydata\", ylim);\n    endfor\n  endif\nendfunction\n\n\n## Cleanup function to remove listeners when line is deleted\nfunction cleanup_listeners (hg, ~, hax, ylim_listener)\n  try\n    dellistener (hax, \"ylim\", ylim_listener);\n  catch\n    ## Ignore errors if axes no longer exists\n  end_try_catch\nendfunction\n\n\n%!demo\n%! clf;\n%! plot (rand (1, 10) * 10, 1:10);\n%! xline (5, \"--r\", \"Threshold\");\n%! title (\"xline() with label\");\n\n%!demo\n%! clf;\n%! plot (1:100);\n%! xline ([25, 50, 75], \":\", {\"Q1\", \"Median\", \"Q3\"});\n%! title (\"xline() with multiple lines and labels\");\n\n%!demo\n%! clf;\n%! x = linspace (0, 2*pi, 100);\n%! plot (x, sin (x));\n%! xline (pi, \"-k\", \"pi\", \"LabelVerticalAlignment\", \"middle\");\n%! xline ([pi/2, 3*pi/2], \"--b\", {\"pi/2\", \"3pi/2\"}, ...\n%!        \"LabelVerticalAlignment\", \"bottom\");\n%! title (\"xline() showing sine wave key points\");\n\n%!demo\n%! clf;\n%! plot (1:10);\n%! xline (5, \"-r\", {\"Horizontal\", \"Label\"}, \"LabelOrientation\", \"horizontal\");\n%! title (\"xline() with horizontal (non-rotated) label\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = xline (5);\n%!   assert (ishghandle (h));\n%!   assert (get (h, \"value\"), 5);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = xline ([2, 5, 8]);\n%!   assert (numel (h), 3);\n%!   assert (get (h(1), \"value\"), 2);\n%!   assert (get (h(2), \"value\"), 5);\n%!   assert (get (h(3), \"value\"), 8);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = xline (5, \"--r\");\n%!   kids = get (h, \"children\");\n%!   hline = kids(strcmp (get (kids, \"type\"), \"line\"));\n%!   assert (get (hline, \"linestyle\"), \"--\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Test with label\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = xline (5, \"-b\", \"Test Label\");\n%!   assert (get (h, \"label\"), \"Test Label\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Test empty x returns empty handle\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = xline ([]);\n%!   assert (isempty (h));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Test multiline label\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = xline (5, \"-\", {\"Line 1\", \"Line 2\"});\n%!   assert (iscell (get (h, \"label\")));\n%!   assert (numel (get (h, \"label\")), 2);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <X must be a real numeric> xline (\"invalid\")\n%!error <X must be a real numeric> xline (1+i)\n%!error <X must be a scalar or vector> xline ([1 2; 3 4])\n"
  },
  {
    "path": "scripts/plot/draw/yline.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} yline (@var{y})\n## @deftypefnx {} {} yline (@var{y}, @var{linespec})\n## @deftypefnx {} {} yline (@var{y}, @var{linespec}, @var{labels})\n## @deftypefnx {} {} yline (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {} yline (@var{hax}, @dots{})\n## @deftypefnx {} {@var{h} =} yline (@dots{})\n## Create horizontal lines at y-coordinates specified by @var{y}.\n##\n## @var{y} is a scalar or vector of y-coordinates where horizontal lines\n## are to be drawn.\n##\n## The optional @var{linespec} argument specifies the line style and color\n## using the same format as @code{plot}.  For example, @qcode{\"r\"} for a red\n## solid line, @qcode{\"--b\"} for a blue dashed line, or @qcode{\":k\"} for a\n## black dotted line.  If not specified, a solid black line is used.\n##\n## The optional @var{labels} argument specifies labels for the lines.  It can\n## be a single string, a cell array of strings for a multiline label (when\n## @var{y} is scalar), or a cell array with one element per line (when @var{y}\n## is a vector).\n##\n## Additional property/value pairs are passed directly to the underlying line\n## object.  The full list of line properties is documented at\n## @ref{Line Properties}.  Commonly used properties include:\n##\n## @table @code\n## @item Color\n## Line color specified as an RGB triplet, a color name, or a short name.\n##\n## @item LineStyle\n## Line style: @qcode{\"-\"} (solid, default), @qcode{\"--\"} (dashed),\n## @qcode{\":\"} (dotted), or @qcode{\"-.\"} (dash-dot).\n##\n## @item LineWidth\n## Width of the line (default is 0.5).\n##\n## @item Alpha\n## Line transparency (0 = fully transparent, 1 = fully opaque).\n##\n## @item Label\n## Text label to display on the line.\n##\n## @item LabelHorizontalAlignment\n## Horizontal alignment of label: @qcode{\"left\"}, @qcode{\"center\"}, or\n## @qcode{\"right\"} (default).\n##\n## @item LabelVerticalAlignment\n## Vertical alignment of label relative to the line: @qcode{\"top\"} (label\n## above line, default), @qcode{\"middle\"}, or @qcode{\"bottom\"} (label below\n## line).\n##\n## @item LabelOrientation\n## Orientation of label text: @qcode{\"aligned\"} or @qcode{\"horizontal\"}\n## (default).\n## @end table\n##\n## If the first argument @var{hax} is an axes handle, then draw the lines\n## in this axes, rather than the current axes returned by @code{gca}.\n##\n## The optional return value @var{h} is a graphics handle (or vector of\n## handles for multiple lines) to the created constant line objects.\n##\n## Example:\n##\n## @example\n## @group\n## plot (1:10, rand (1, 10));\n## yline (0.5, \"--r\", \"Threshold\");\n## @end group\n## @end example\n##\n## @example\n## @group\n## plot (1:10, rand (1, 10) * 100);\n## yline ([25, 50, 75], \":\", @{\"Q1\", \"Median\", \"Q3\"@});\n## @end group\n## @end example\n##\n## @seealso{xline, line, plot}\n## @end deftypefn\n\nfunction h = yline (varargin)\n\n  [hax, varargin, nargin] = __plt_get_axis_arg__ (\"yline\", varargin{:});\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Get y values\n  yval = varargin{1};\n  if (! isnumeric (yval) || ! isreal (yval))\n    error (\"yline: Y must be a real numeric scalar or vector\");\n  endif\n  if (! isvector (yval) && ! isempty (yval))\n    error (\"yline: Y must be a scalar or vector, not a matrix\");\n  endif\n  if (isempty (yval))\n    ## Nothing to plot\n    if (nargout > 0)\n      h = zeros (0, 1);\n    endif\n    return;\n  endif\n  yval = yval(:).';  # ensure row vector\n\n  ## Filter out NaN and Inf values\n  valid_idx = isfinite (yval);\n  if (! all (valid_idx))\n    warning (\"yline: ignoring non-finite values in Y\");\n    yval = yval(valid_idx);\n    if (isempty (yval))\n      if (nargout > 0)\n        h = zeros (0, 1);\n      endif\n      return;\n    endif\n  endif\n\n  ## Parse remaining arguments\n  linespec = \"\";\n  labels = {};\n  propargs = {};\n\n  idx = 2;\n  if (nargin >= 2 && ischar (varargin{2}))\n    ## Check if it's a linespec or a property name\n    [lstyle, valid] = __pltopt__ (\"yline\", varargin{2}, false);\n    if (valid)\n      linespec = varargin{2};\n      idx = 3;\n    endif\n  endif\n\n  ## Check for labels\n  if (nargin >= idx)\n    arg = varargin{idx};\n    if (ischar (arg) || iscellstr (arg))\n      ## Could be labels or property name\n      ## If next arg exists and is not a string, this is likely a property name\n      if (nargin > idx && ! ischar (varargin{idx + 1}))\n        ## This is a property name (like \"Color\" followed by a value)\n        propargs = varargin(idx:end);\n      elseif (ischar (arg) && nargin > idx && ischar (varargin{idx + 1}))\n        ## Two consecutive strings - first could be labels, or could be prop/val\n        ## Check if it looks like a known property\n        if (__is_graphics_property__ (arg))\n          propargs = varargin(idx:end);\n        else\n          ## Treat as label\n          labels = {arg};\n          idx += 1;\n          propargs = varargin(idx:end);\n        endif\n      elseif (iscellstr (arg))\n        labels = arg;\n        idx += 1;\n        propargs = varargin(idx:end);\n      elseif (ischar (arg))\n        if (__is_graphics_property__ (arg))\n          propargs = varargin(idx:end);\n        else\n          labels = {arg};\n          idx += 1;\n          propargs = varargin(idx:end);\n        endif\n      endif\n    else\n      propargs = varargin(idx:end);\n    endif\n  endif\n\n  ## Process property/value pairs to extract yline-specific properties\n  ## Standard line properties will be passed to the line object\n  labelhalign = \"right\";\n  labelvalign = \"top\";\n  labelorient = \"horizontal\";\n  alpha = 1;\n\n  i = 1;\n  lineprops = {};\n  while (i <= numel (propargs))\n    prop = propargs{i};\n    if (! ischar (prop))\n      error (\"yline: property name must be a string\");\n    endif\n\n    if (i == numel (propargs))\n      error (\"yline: property '%s' requires a value\", prop);\n    endif\n    val = propargs{i + 1};\n\n    switch (lower (prop))\n      case \"label\"\n        if (ischar (val))\n          labels = {val};\n        elseif (iscellstr (val))\n          labels = val;\n        else\n          error (\"yline: Label must be a string or cell array of strings\");\n        endif\n      case \"labelhorizontalalignment\"\n        val = lower (val);\n        if (strcmp (val, \"middle\"))\n          val = \"center\";  # accept \"middle\" as alias for \"center\"\n        endif\n        if (! any (strcmp (val, {\"left\", \"center\", \"right\"})))\n          error (\"yline: LabelHorizontalAlignment must be 'left', 'center', or 'right'\");\n        endif\n        labelhalign = val;\n      case \"labelverticalalignment\"\n        val = lower (val);\n        if (strcmp (val, \"center\"))\n          val = \"middle\";  # accept \"center\" as alias for \"middle\"\n        endif\n        if (! any (strcmp (val, {\"top\", \"middle\", \"bottom\"})))\n          error (\"yline: LabelVerticalAlignment must be 'top', 'middle', or 'bottom'\");\n        endif\n        labelvalign = val;\n      case \"labelorientation\"\n        labelorient = val;\n      case \"alpha\"\n        alpha = val;\n      otherwise\n        lineprops{end+1} = prop;\n        lineprops{end+1} = val;\n    endswitch\n    i += 2;\n  endwhile\n\n  ## Parse linespec for color and linestyle\n  linecolor = [0, 0, 0];  # default black\n  linestyle = \"-\";        # default solid\n\n  if (! isempty (linespec))\n    [lstyle, ~] = __pltopt__ (\"yline\", linespec, false);\n    if (! isempty (lstyle.color))\n      linecolor = lstyle.color;\n    endif\n    if (! isempty (lstyle.linestyle))\n      linestyle = lstyle.linestyle;\n    endif\n  endif\n\n  ## Override with explicit property values\n  for i = 1:2:numel (lineprops)\n    switch (lower (lineprops{i}))\n      case \"color\"\n        linecolor = lineprops{i + 1};\n      case \"linestyle\"\n        linestyle = lineprops{i + 1};\n    endswitch\n  endfor\n\n  ## Validate labels\n  ## For a single y-value, a cell array with multiple elements is a multiline label\n  ## For multiple y-values, cell array elements map to each line\n  if (! isempty (labels))\n    if (numel (yval) == 1)\n      ## Single y-value\n      if (numel (labels) > 1)\n        ## Multiple labels means multiline - wrap for consistent indexing\n        labels = {labels};\n      endif\n      ## Single label - already in correct format {\"Label\"}, don't wrap again\n    elseif (numel (labels) == 1)\n      ## Single label for multiple y-values: replicate\n      labels = repmat (labels, 1, numel (yval));\n    elseif (numel (labels) != numel (yval))\n      error (\"yline: number of labels must match number of y-values\");\n    endif\n  endif\n\n  ## Get or create axes\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  ## Get current x-axis limits\n  xlim = get (hax, \"xlim\");\n\n  ## Store current hold state and set hold on\n  holdstate = ishold (hax);\n\n  ## Create lines\n  htmp = zeros (numel (yval), 1);\n\n  unwind_protect\n    hold (hax, \"on\");\n\n    for i = 1:numel (yval)\n      ## Create an hggroup to hold the line and optional label\n      hg = hggroup (\"parent\", hax, ...\n                    \"__appdata__\", struct (\"__creator__\", \"yline\"));\n      htmp(i) = hg;\n\n      ## Calculate label position and create text first (to get extent for centering)\n      ht = [];\n      text_extent = [];\n      labelx = [];\n      if (! isempty (labels))\n        ## Calculate padding based on font size\n        fontsize = get (hax, \"fontsize\");  # in points\n        axpos = get (hax, \"position\");     # normalized units\n        figpos = get (ancestor (hax, \"figure\"), \"position\");  # pixels\n\n        ## Horizontal padding: ~1 character width\n        axes_width_pixels = axpos(3) * figpos(3);\n        xrange = diff (xlim);\n        char_width_data = (0.6 * fontsize / axes_width_pixels) * xrange;\n\n        ## Vertical padding: ~1/4 character height\n        ylim_ax = get (hax, \"ylim\");\n        yrange = diff (ylim_ax);\n        axes_height_pixels = axpos(4) * figpos(4);\n        char_height_data = (fontsize / axes_height_pixels) * yrange;\n        ypadding = char_height_data / 4;\n\n        ## Determine label y-position with vertical offset\n        ## and map to text object's verticalalignment\n        switch (lower (labelvalign))\n          case \"top\"\n            labely = yval(i) + ypadding;  # label above line\n            text_valign = \"bottom\";       # text anchored at bottom\n          case \"middle\"\n            labely = yval(i);\n            text_valign = \"middle\";\n          case \"bottom\"\n            labely = yval(i) - ypadding;  # label below line\n            text_valign = \"top\";          # text anchored at top\n          otherwise\n            labely = yval(i) + ypadding;  # default: above line\n            text_valign = \"bottom\";\n        endswitch\n\n        ## Determine label x-position with horizontal offset\n        switch (lower (labelhalign))\n          case \"left\"\n            labelx = xlim(1) + char_width_data;\n          case \"center\"\n            labelx = mean (xlim);\n          case \"right\"\n            labelx = xlim(2) - char_width_data;\n          otherwise\n            labelx = xlim(2) - char_width_data;\n        endswitch\n\n        ht = text (\"parent\", hg, ...\n                   \"position\", [labelx, labely, 0], ...\n                   \"string\", labels{i}, ...\n                   \"horizontalalignment\", labelhalign, ...\n                   \"verticalalignment\", text_valign, ...\n                   \"color\", linecolor, ...\n                   \"clipping\", \"off\");\n\n        if (strcmp (lower (labelorient), \"aligned\"))\n          set (ht, \"rotation\", 0);  # horizontal line, so 0 rotation\n        endif\n      endif\n\n      ## Create the horizontal line(s)\n      ## Split line if label is vertically centered on the line\n      if (! isempty (labels) && strcmp (lower (labelvalign), \"middle\"))\n        ## Calculate gap from font metrics (not text_extent for consistency)\n        str = labels{i};\n        if (iscell (str))\n          max_len = max (cellfun (@numel, str));\n        else\n          max_len = numel (str);\n        endif\n\n        ## Text width\n        text_width = max_len * char_width_data;\n\n        ## Gap is centered at label x-position (accounting for alignment)\n        switch (lower (labelhalign))\n          case \"left\"\n            text_center_x = labelx + text_width / 2;\n          case \"center\"\n            text_center_x = labelx;\n          case \"right\"\n            text_center_x = labelx - text_width / 2;\n          otherwise\n            text_center_x = labelx;\n        endswitch\n\n        gap_left = text_center_x - text_width / 2 - char_width_data / 2;\n        gap_right = text_center_x + text_width / 2 + char_width_data / 2;\n\n        ## Left segment\n        if (xlim(1) < gap_left)\n          hl1 = __go_line__ (hg, \"xdata\", [xlim(1), gap_left], ...\n                                 \"ydata\", [yval(i), yval(i)], ...\n                                 \"color\", linecolor, \"linestyle\", linestyle);\n          set (hl1, \"xliminclude\", \"off\");\n          for j = 1:2:numel (lineprops)\n            try\n              set (hl1, lineprops{j}, lineprops{j + 1});\n            catch\n            end_try_catch\n          endfor\n        endif\n\n        ## Right segment\n        if (gap_right < xlim(2))\n          hl2 = __go_line__ (hg, \"xdata\", [gap_right, xlim(2)], ...\n                                 \"ydata\", [yval(i), yval(i)], ...\n                                 \"color\", linecolor, \"linestyle\", linestyle);\n          set (hl2, \"xliminclude\", \"off\");\n          for j = 1:2:numel (lineprops)\n            try\n              set (hl2, lineprops{j}, lineprops{j + 1});\n            catch\n            end_try_catch\n          endfor\n        endif\n      else\n        ## Single continuous line\n        hl = __go_line__ (hg, \"xdata\", xlim, \"ydata\", [yval(i), yval(i)], ...\n                              \"color\", linecolor, \"linestyle\", linestyle);\n        set (hl, \"xliminclude\", \"off\");\n\n        for j = 1:2:numel (lineprops)\n          try\n            set (hl, lineprops{j}, lineprops{j + 1});\n          catch\n            ## Ignore properties that don't apply to line objects\n          end_try_catch\n        endfor\n      endif\n\n      ## Setup properties for the hggroup\n      ## Get linewidth from first line child\n      line_kids = findobj (hg, \"type\", \"line\");\n      if (! isempty (line_kids))\n        lw = get (line_kids(1), \"linewidth\");\n      else\n        lw = 0.5;  # default\n      endif\n\n      addproperty (\"value\", hg, \"data\", yval(i));\n      addproperty (\"color\", hg, \"linecolor\", linecolor);\n      addproperty (\"linestyle\", hg, \"linelinestyle\", linestyle);\n      addproperty (\"linewidth\", hg, \"linelinewidth\", lw);\n      addproperty (\"alpha\", hg, \"data\", alpha);\n\n      if (! isempty (labels))\n        addproperty (\"label\", hg, \"any\", labels{i});\n      else\n        addproperty (\"label\", hg, \"string\", \"\");\n      endif\n\n      addproperty (\"labelhorizontalalignment\", hg, \"string\", labelhalign);\n      addproperty (\"labelverticalalignment\", hg, \"string\", labelvalign);\n      addproperty (\"labelorientation\", hg, \"string\", labelorient);\n\n      ## Add listeners for property updates\n      addlistener (hg, \"color\", @update_line_props);\n      addlistener (hg, \"linestyle\", @update_line_props);\n      addlistener (hg, \"linewidth\", @update_line_props);\n      addlistener (hg, \"value\", @update_line_data);\n\n      ## Add listener for xlim changes to update line extent\n      xlim_listener = {@update_xlim, hg};\n      addlistener (hax, \"xlim\", xlim_listener);\n\n      ## Add delete function to clean up listener\n      set (hg, \"deletefcn\", {@cleanup_listeners, hax, xlim_listener});\n\n    endfor\n\n  unwind_protect_cleanup\n    if (! holdstate)\n      hold (hax, \"off\");\n    endif\n  end_unwind_protect\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n## Check if a string is a known graphics property\nfunction retval = __is_graphics_property__ (str)\n  known_props = {\"color\", \"linestyle\", \"linewidth\", \"alpha\", \"label\", ...\n                 \"labelhorizontalalignment\", \"labelverticalalignment\", ...\n                 \"labelorientation\", \"parent\", \"visible\", \"handlevisibility\", ...\n                 \"displayname\", \"tag\", \"userdata\"};\n  retval = any (strcmpi (str, known_props));\nendfunction\n\n\n## Callback to update line properties\nfunction update_line_props (hg, ~)\n  kids = get (hg, \"children\");\n  for i = 1:numel (kids)\n    if (strcmp (get (kids(i), \"type\"), \"line\"))\n      set (kids(i), \"color\", get (hg, \"color\"), ...\n                    \"linestyle\", get (hg, \"linestyle\"), ...\n                    \"linewidth\", get (hg, \"linewidth\"));\n    elseif (strcmp (get (kids(i), \"type\"), \"text\"))\n      set (kids(i), \"color\", get (hg, \"color\"));\n    endif\n  endfor\nendfunction\n\n\n## Callback to update line y-coordinate\nfunction update_line_data (hg, ~)\n  yval = get (hg, \"value\");\n  kids = get (hg, \"children\");\n  for i = 1:numel (kids)\n    if (strcmp (get (kids(i), \"type\"), \"line\"))\n      set (kids(i), \"ydata\", [yval, yval]);\n    elseif (strcmp (get (kids(i), \"type\"), \"text\"))\n      pos = get (kids(i), \"position\");\n      pos(2) = yval;\n      set (kids(i), \"position\", pos);\n    endif\n  endfor\nendfunction\n\n\n## Callback to update line x-extent when axes limits change\nfunction update_xlim (hax, ~, hg)\n  if (! ishghandle (hg))\n    return;\n  endif\n  xlim = get (hax, \"xlim\");\n  kids = get (hg, \"children\");\n  labelhalign = get (hg, \"labelhorizontalalignment\");\n\n  ## Calculate horizontal padding based on font size\n  fontsize = get (hax, \"fontsize\");\n  axpos = get (hax, \"position\");\n  figpos = get (ancestor (hax, \"figure\"), \"position\");\n  axes_width_pixels = axpos(3) * figpos(3);\n  xrange = diff (xlim);\n  char_width_data = (0.6 * fontsize / axes_width_pixels) * xrange;\n\n  ## Find text and line children\n  text_kid = [];\n  line_kids = [];\n  for i = 1:numel (kids)\n    if (strcmp (get (kids(i), \"type\"), \"text\"))\n      text_kid = kids(i);\n    elseif (strcmp (get (kids(i), \"type\"), \"line\"))\n      line_kids(end+1) = kids(i);\n    endif\n  endfor\n\n  ## Update text position\n  if (! isempty (text_kid))\n    pos = get (text_kid, \"position\");\n    switch (lower (labelhalign))\n      case \"left\"\n        pos(1) = xlim(1) + char_width_data;\n      case \"center\"\n        pos(1) = mean (xlim);\n      case \"right\"\n        pos(1) = xlim(2) - char_width_data;\n    endswitch\n    set (text_kid, \"position\", pos);\n  endif\n\n  ## Update line(s)\n  labelvalign = get (hg, \"labelverticalalignment\");\n  if (strcmp (lower (labelvalign), \"middle\") && ! isempty (text_kid) ...\n      && numel (line_kids) >= 2)\n    ## Split line case - calculate gap around text from font metrics\n    ## Estimate text width based on longest line\n    str = get (text_kid, \"string\");\n    if (iscell (str))\n      max_len = max (cellfun (@numel, str));\n    else\n      max_len = numel (str);\n    endif\n\n    ## Text width\n    text_width = max_len * char_width_data;\n\n    ## Gap is centered at text position (accounting for alignment)\n    text_pos = get (text_kid, \"position\");\n    switch (lower (labelhalign))\n      case \"left\"\n        text_center_x = text_pos(1) + text_width / 2;\n      case \"center\"\n        text_center_x = text_pos(1);\n      case \"right\"\n        text_center_x = text_pos(1) - text_width / 2;\n      otherwise\n        text_center_x = text_pos(1);\n    endswitch\n\n    gap_left = text_center_x - text_width / 2 - char_width_data / 2;\n    gap_right = text_center_x + text_width / 2 + char_width_data / 2;\n\n    ## Identify which segment is left and which is right by current position\n    for i = 1:numel (line_kids)\n      xdata = get (line_kids(i), \"xdata\");\n      xmid = mean (xdata);\n      if (xmid < mean (xlim))\n        ## This is the left segment\n        set (line_kids(i), \"xdata\", [xlim(1), gap_left]);\n      else\n        ## This is the right segment\n        set (line_kids(i), \"xdata\", [gap_right, xlim(2)]);\n      endif\n    endfor\n  else\n    ## Single continuous line or non-middle label\n    for i = 1:numel (line_kids)\n      set (line_kids(i), \"xdata\", xlim);\n    endfor\n  endif\nendfunction\n\n\n## Cleanup function to remove listeners when line is deleted\nfunction cleanup_listeners (hg, ~, hax, xlim_listener)\n  try\n    dellistener (hax, \"xlim\", xlim_listener);\n  catch\n    ## Ignore errors if axes no longer exists\n  end_try_catch\nendfunction\n\n\n%!demo\n%! clf;\n%! plot (1:10, rand (1, 10));\n%! yline (0.5, \"--r\", \"Threshold\");\n%! title (\"yline() with label\");\n\n%!demo\n%! clf;\n%! plot (1:10, rand (1, 10) * 100);\n%! yline ([25, 50, 75], \":\", {\"Q1\", \"Median\", \"Q3\"});\n%! title (\"yline() with multiple lines and labels\");\n\n%!demo\n%! clf;\n%! x = linspace (0, 2*pi, 100);\n%! plot (x, sin (x));\n%! yline (0, \"-k\");\n%! yline ([-1, 1], \"--b\", {\"Min\", \"Max\"}, \"LabelHorizontalAlignment\", \"left\");\n%! axis padded;\n%! title (\"yline() showing sine wave bounds\");\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = yline (5);\n%!   assert (ishghandle (h));\n%!   assert (get (h, \"value\"), 5);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = yline ([2, 5, 8]);\n%!   assert (numel (h), 3);\n%!   assert (get (h(1), \"value\"), 2);\n%!   assert (get (h(2), \"value\"), 5);\n%!   assert (get (h(3), \"value\"), 8);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = yline (5, \"--r\");\n%!   kids = get (h, \"children\");\n%!   hline = kids(strcmp (get (kids, \"type\"), \"line\"));\n%!   assert (get (hline, \"linestyle\"), \"--\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Test with label\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = yline (5, \"-b\", \"Test Label\");\n%!   assert (get (h, \"label\"), \"Test Label\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Test empty y returns empty handle\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = yline ([]);\n%!   assert (isempty (h));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! ## Test multiline label\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   h = yline (5, \"-\", {\"Line 1\", \"Line 2\"});\n%!   assert (iscell (get (h, \"label\")));\n%!   assert (numel (get (h, \"label\")), 2);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <Y must be a real numeric> yline (\"invalid\")\n%!error <Y must be a real numeric> yline (1+i)\n%!error <Y must be a scalar or vector> yline ([1 2; 3 4])\n"
  },
  {
    "path": "scripts/plot/util/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/plot/util/__actual_axis_position__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{pos} =} __actual_axis_position__ (@var{h})\n## @deftypefnx {} {@var{pos} =} __actual_axis_position__ (@var{axis_struct})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction pos = __actual_axis_position__ (h)\n\n  if (ishghandle (h))\n    axis_obj = get (h);\n  elseif (isstruct (h))\n    axis_obj = h;\n    h = axis_obj.__axes_handle__;\n  endif\n\n  ## Get figure size in pixels\n  orig_fig_units = get (axis_obj.parent, \"units\");\n  orig_fig_position = get (axis_obj.parent, \"position\");\n  unwind_protect\n    set (axis_obj.parent, \"units\", \"pixels\");\n    fig_position = get (axis_obj.parent, \"position\");\n  unwind_protect_cleanup\n    set (axis_obj.parent, \"units\", orig_fig_units,\n                          \"position\", orig_fig_position);\n  end_unwind_protect\n  ## Get axes size in pixels\n  if (strcmp (get (axis_obj.parent, \"__graphics_toolkit__\"), \"gnuplot\")\n      && strcmp (axis_obj.positionconstraint, \"outerposition\"))\n    pos_in_pixels = axis_obj.outerposition .* fig_position([3, 4, 3, 4]);\n  else\n    pos_in_pixels = axis_obj.position .* fig_position([3, 4, 3, 4]);\n  endif\n\n  nd = __calc_dimensions__ (h);\n\n  if (strcmp (axis_obj.plotboxaspectratiomode, \"manual\")\n      || strcmp (axis_obj.dataaspectratiomode, \"manual\"))\n    ## When using {rltb}margin, Gnuplot does not handle the specified\n    ## aspect ratio properly, so handle it here.\n    if (nd == 2 || all (mod (axis_obj.view, 90) == 0))\n      aspect_ratio_2d = axis_obj.plotboxaspectratio(1:2);\n    else\n      ## FIXME: This works for \"axis square\", but has not been\n      ##        thoroughly tested for other aspect ratios.\n      aspect_ratio_2d = [max(axis_obj.plotboxaspectratio(1:2)), ...\n                             axis_obj.plotboxaspectratio(3)/sqrt(2)];\n    endif\n    orig_aspect_ratio_2d = pos_in_pixels(3:4);\n    rel_aspect_ratio_2d = aspect_ratio_2d ./ orig_aspect_ratio_2d;\n    rel_aspect_ratio_2d ./= max (rel_aspect_ratio_2d);\n    if (rel_aspect_ratio_2d(1) < rel_aspect_ratio_2d(2))\n      dx = (1.0 - rel_aspect_ratio_2d(1)) * pos_in_pixels(3);\n      pos_in_pixels += dx*[0.5, 0.0, -1.0, 0.0];\n    elseif (rel_aspect_ratio_2d(1) > rel_aspect_ratio_2d(2))\n      dy = (1.0 - rel_aspect_ratio_2d(2)) * pos_in_pixels(4);\n      pos_in_pixels += dy*[0.0, 0.5, 0.0, -1.0];\n    endif\n    pos = pos_in_pixels ./ fig_position([3, 4, 3, 4]);\n  elseif (strcmp (get (axis_obj.parent, \"__graphics_toolkit__\"), \"gnuplot\")\n          && strcmp (axis_obj.positionconstraint, \"outerposition\"))\n    pos = axis_obj.outerposition;\n  else\n    pos = axis_obj.position;\n  endif\n\nendfunction\n\n\n## No test coverage for internal function.  It is tested through calling fcn.\n%!assert (1)\n"
  },
  {
    "path": "scripts/plot/util/__check_rendering_capability__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} __check_rendering_capability__ (@var{who}, @var{fig})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction __check_rendering_capability__ (who, fig)\n\n  if (strcmp (get (fig, \"visible\"), \"on\"))\n    return;\n  endif\n\n  toolkit = get (fig, \"__graphics_toolkit__\");\n\n  if (strcmp (toolkit, \"qt\"))\n    return;\n  endif\n\n  error (\"%s: rendering with %s toolkit requires visible figure (DISPLAY='%s')\",\n         who, toolkit, getenv (\"DISPLAY\"));\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/__default_plot_options__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{options} =} __default_plot_options__ ()\n## Return a plot options structure @var{options} with default values\n## for all fields.\n## @end deftypefn\n\nfunction options = __default_plot_options__ ()\n\n  options = struct (\"key\", \"\",\n                    \"color\", [],\n                    \"linestyle\", [],\n                    \"marker\", [],\n                    \"errorstyle\", []);\n\nendfunction\n\n\n%!test\n%! options = __default_plot_options__ ();\n%! assert (isfield (options, \"key\"));\n%! assert (options.key, \"\");\n%! assert (options.color, []);\n%! assert (options.linestyle, []);\n%! assert (options.marker, []);\n%! assert (options.errorstyle, []);\n"
  },
  {
    "path": "scripts/plot/util/__gnuplot_drawnow__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} __gnuplot_drawnow__ (@var{h}, @var{term}, @var{file}, @var{debug_file})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction __gnuplot_drawnow__ (h, term, file, debug_file)\n\n  if (nargin < 1 || nargin == 2)\n    print_usage ();\n  endif\n\n  if (nargin >= 3 && nargin <= 4)\n    ## Produce various output formats, or redirect gnuplot stream to a\n    ## debug file.\n    plot_stream = [];\n    fid = [];\n    default_plot_stream = get (h, \"__plot_stream__\");\n    unwind_protect\n      plot_stream = __gnuplot_open_stream__ (2, h);\n      gnuplot_supports_term = __gnuplot_has_terminal__ (term, plot_stream);\n      if (gnuplot_supports_term)\n        enhanced = gnuplot_set_term (plot_stream(1), true, h, term, file);\n        __gnuplot_draw_figure__ (h, plot_stream(1), enhanced);\n        if (nargin == 4)\n          fid = fopen (debug_file, \"wb\");\n          enhanced = gnuplot_set_term (fid, true, h, term, file);\n          __gnuplot_draw_figure__ (h, fid, enhanced);\n        endif\n      else\n        error ('__gnuplot_drawnow__: the gnuplot terminal, \"%s\", is not available',\n               gnuplot_trim_term (term));\n      endif\n    unwind_protect_cleanup\n      set (h, \"__plot_stream__\", default_plot_stream);\n      if (! isempty (plot_stream))\n        pclose (plot_stream(1));\n        if (numel (plot_stream) > 1)\n          pclose (plot_stream(2));\n        endif\n        if (numel (plot_stream) > 2)\n          waitpid (plot_stream(3));\n        endif\n      endif\n      if (! isempty (fid))\n        fclose (fid);\n      endif\n    end_unwind_protect\n  else  # nargin == 1\n    ##  Graphics terminal for display.\n    plot_stream = get (h, \"__plot_stream__\");\n    if (isempty (plot_stream))\n      plot_stream = __gnuplot_open_stream__ (2, h);\n      new_stream = true;\n    else\n      new_stream = false;\n    endif\n    term = gnuplot_default_term (plot_stream);\n    if (strcmp (term, \"dumb\"))\n      ## popen2 eats stdout of gnuplot, use temporary file instead\n      dumb_tmp_file = tempname ();\n      enhanced = gnuplot_set_term (plot_stream(1), new_stream, h,\n                                   term, dumb_tmp_file);\n    else\n      enhanced = gnuplot_set_term (plot_stream(1), new_stream, h, term);\n    endif\n    __gnuplot_draw_figure__ (h, plot_stream(1), enhanced);\n    fflush (plot_stream(1));\n    if (strcmp (term, \"dumb\"))\n      fid = -1;\n      while (fid < 0)\n        pause (0.1);\n        fid = fopen (dumb_tmp_file, 'r');\n      endwhile\n      ## reprint the plot on screen\n      [a, count] = fscanf (fid, '%c', Inf);\n      fclose (fid);\n      if (count > 0)\n        if (a(1) == 12)\n          a = a(2:end);  # avoid ^L at the beginning\n        endif\n        puts (a);\n      endif\n      unlink (dumb_tmp_file);\n    endif\n  endif\n\nendfunction\n\nfunction enhanced = gnuplot_set_term (plot_stream, new_stream, h, term, file)\n\n  ## Generate the gnuplot \"set terminal <term> ...\" command.\n  ## When \"term\" originates from print.m, it may include other options.\n  if (nargin < 4)\n    ## This supports the gnuplot graphics toolkit.\n    term = gnuplot_default_term (plot_stream);\n    opts_str = \"\";\n  else\n    ## Get the one word terminal id and save the remaining as options to be\n    ## passed on to gnuplot.  The terminal may respect the graphics toolkit.\n    [term, opts_str] = gnuplot_trim_term (term);\n    term = lower (term);\n    if (strcmp (term, \"lua\"))\n      ## Replace \"lua tikz\" with just \"tikz\"\n      term = \"tikz\";\n      opts_str = strrep (opts_str, \"tikz\", \"\");\n    endif\n  endif\n\n  if (strfind (opts_str, \"noenhanced\"))\n    enhanced = false;\n  else\n    enhanced = gnuplot_is_enhanced_term (plot_stream, term);\n  endif\n\n  ## Set the terminal.\n  if (! isempty (term))\n\n    if (enhanced)\n      enh_str = \"enhanced\";\n    else\n      enh_str = \"\";\n    endif\n\n    if (! isempty (h) && isfigure (h))\n\n      ## Generate gnuplot title string for plot windows.\n      if (output_to_screen (term) && ! strcmp (term, \"dumb\"))\n        fig.numbertitle = get (h, \"numbertitle\");\n        fig.name = strrep (get (h, \"name\"), '\"', '\\\"');\n        if (! isempty (get (h, \"number\"))\n            && strcmp (get (h, \"numbertitle\"), \"on\"))\n          title_str = sprintf (\"Figure %d\", h);\n          if (! isempty (fig.name))\n            title_str = sprintf (\"%s: %s\", title_str, fig.name);\n          endif\n        elseif (! isempty (fig.name))\n          title_str = fig.name;\n        else\n          title_str = \" \";\n        endif\n        if (! isempty (title_str))\n          title_str = sprintf ('title \"%s\"', title_str);\n        endif\n        if (strcmp (term, \"aqua\"))\n          ## Adjust axes-label and tick-label spacing.\n          opts_str = sprintf ('%s font \"%s,%d\"', opts_str,\n                              get (0, \"defaultaxesfontname\"),\n                              get (0, \"defaultaxesfontsize\") / 1.5);\n        endif\n      else\n        title_str = \"\";\n      endif\n\n      if (! (any (strfind (opts_str, \" size \") > 0)\n          || any (strfind (opts_str, \"size \") == 1)))\n        ## Get figure size in pixels.  Rely on listener to handle coversion.\n        units = get (h, \"units\");\n        unwind_protect\n          set (h, \"units\", \"pixels\");\n          position_in_pixels = get (h, \"position\");\n        unwind_protect_cleanup\n          set (h, \"units\", units);\n        end_unwind_protect\n        gnuplot_pos = position_in_pixels(1:2);\n        gnuplot_size = position_in_pixels(3:4);\n        if (! (output_to_screen (term)\n               || any (strcmp (term, {\"canvas\", \"emf\", \"gif\", \"jpeg\", ...\n                                      \"pbm\", \"png\", \"pngcairo\", \"svg\"}))))\n          ## Convert to inches\n          gnuplot_pos = gnuplot_pos / 72;\n          gnuplot_size = gnuplot_size / 72;\n        endif\n        if (all (gnuplot_size > 0))\n          terminals_with_size = {\"cairolatex\", \"canvas\", \"eepic\", \"emf\", ...\n                                 \"epscairo\", \"epslatex\", \"fig\", \"gif\", ...\n                                 \"jpeg\", \"latex\", \"pbm\", \"pdf\", \"pdfcairo\", ...\n                                 \"png\", \"pngcairo\", \"postscript\", ...\n                                 \"pslatex\",\"pstex\", \"svg\", \"tikz\", ...\n                                 \"windows\", \"wxt\", \"x11\"};\n          if (__gnuplot_has_feature__ (\"qt_terminal\"))\n            terminals_with_size{end+1} = \"qt\";\n          endif\n          switch (term)\n            case terminals_with_size\n              size_str = sprintf (\"size %.12g,%.12g\", gnuplot_size);\n            case {\"aqua\", \"fig\", \"corel\"}\n              size_str = sprintf (\"size %g %g\", gnuplot_size);\n            case \"dumb\"\n              new_stream = 1;\n              if (! isempty (getenv (\"COLUMNS\"))\n                  && ! isempty (getenv (\"LINES\")))\n                ## Let dumb use full text screen size (minus prompt lines).\n                n = sprintf (\"%i\",\n                             -2 - length (find (sprintf (\"%s\", PS1) == \"\\n\")));\n                ## n = the number of times \\n appears in PS1\n                size_str = [\"size \" getenv(\"COLUMNS\") \",\" getenv(\"LINES\") n];\n              else\n                ## Use the gnuplot default.\n                size_str = \"\";\n              endif\n            case \"dxf\"\n              size_str = \"\";  # dxf supposedly supports \"set size\" in 5.0\n            case \"tikz\"\n              size_str = sprintf (\"size %gin,%gin\", gnuplot_size);\n            otherwise\n              size_str = \"\";\n          endswitch\n          if (strcmp (term, \"x11\") || strcmp (term, \"windows\")\n              || (strcmp (term, \"wxt\")\n                  && __gnuplot_has_feature__ (\"wxt_figure_position\"))\n              || (strcmp (term, \"qt\")\n                  && __gnuplot_has_feature__ (\"qt_figure_position\")))\n            ## X11/Windows/qt/wxt (=> ver 5) allows the window to be positioned.\n            units = get (0, \"units\");\n            unwind_protect\n              set (0, \"units\", \"pixels\");\n              screen_size = get (0, \"screensize\")(3:4);\n            unwind_protect_cleanup\n              set (0, \"units\", units);\n            end_unwind_protect\n            if (all (screen_size > 0))\n              ## Set the figure position as well as the size.  gnuplot position\n              ## is UL, Octave's is LL (same for screen/window)\n              gnuplot_pos(2) = screen_size(2) - gnuplot_pos(2) - gnuplot_size(2);\n              gnuplot_pos = max (gnuplot_pos, 1);\n              size_str = sprintf (\"%s position %d,%d\", size_str,\n                                  gnuplot_pos(1), gnuplot_pos(2));\n            endif\n          endif\n        else\n          size_str = \"\";\n          warning (\"gnuplot_set_term: size is zero\");\n        endif\n      else\n        ## A specified size take priority over the figure properties.\n        size_str = \"\";\n      endif\n    else\n      if (isempty (h))\n        disp (\"gnuplot_set_term: figure handle is empty\");\n      elseif (! isfigure (h))\n        disp (\"gnuplot_set_term: not a figure handle\");\n      endif\n      title_str = \"\";\n      size_str = \"\";\n    endif\n\n    ## Set the gnuplot terminal (type, enhanced, title, options & size).\n    term_str = [\"set encoding utf8;\\nset terminal \" term];\n    if (__gnuplot_has_feature__ (\"needs_color_with_postscript\") ...\n        && strcmp (term, \"postscript\"))\n      term_str = [term_str, \" color\"];\n    endif\n    if (! isempty (enh_str))\n      term_str = [term_str \" \" enh_str];\n    endif\n    if (! isempty (title_str))\n      term_str = [term_str \" \" title_str];\n    endif\n    if (isempty (strfind (term, \"corel\")))\n      if (! isempty (size_str) && new_stream)\n        ## size_str comes after other options to permit specification of\n        ## the canvas size for terminals cdr/corel.\n        term_str = [term_str \" \" size_str];\n      endif\n      if (nargin > 3 && ischar (opts_str))\n        ## Options must go last.\n        term_str = [term_str \" \" opts_str];\n      endif\n    else\n      if (nargin > 3 && ischar (opts_str))\n        ## Options must go last.\n        term_str = [term_str \" \" opts_str];\n      endif\n      if (! isempty (size_str) && new_stream)\n        ## size_str comes after other options to permit specification of\n        ## the canvas size for terminals cdr/corel.\n        term_str = [term_str \" \" size_str];\n      endif\n    endif\n    if (any (strcmp (term, {\"aqua\", \"wxt\"})))\n      term_str = [term_str, \" \", \"dashlength 1\"];\n    elseif (any (strcmp (term, {\"epslatex\", \"postscript\", \"pslatex\"})))\n      term_str = [term_str, \" \", \"dashlength 2\"];\n    endif\n\n    ## Work around the gnuplot feature of growing the x11 window and\n    ## flickering window (x11, windows, & wxt) when the mouse and\n    ## multiplot are set in gnuplot.\n    fputs (plot_stream, \"unset multiplot;\\n\");\n    flickering_terms = {\"x11\", \"windows\", \"wxt\", \"dumb\"};\n    if (! any (strcmp (term, flickering_terms))\n        || have_non_legend_axes (h)\n        || numel (findall (h, \"type\", \"image\")) > 0)\n      fprintf (plot_stream, \"%s\\n\", term_str);\n      if (nargin == 5)\n        if (! isempty (file))\n          fprintf (plot_stream, \"set output '%s';\\n\", file);\n        endif\n      endif\n      fputs (plot_stream, \"set multiplot;\\n\");\n    elseif (any (strcmp (term, flickering_terms)))\n      fprintf (plot_stream, \"%s\\n\", term_str);\n      if (nargin == 5)\n        if (! isempty (file))\n          fprintf (plot_stream, \"set output '%s';\\n\", file);\n        endif\n      endif\n    endif\n    if (! __gnuplot_has_feature__ (\"dashtype\"))\n      fprintf (plot_stream, \"set termoption dashed\\n\");\n    endif\n  else\n    ## gnuplot will pick up the GNUTERM environment variable itself\n    ## so no need to set the terminal type if not also setting the\n    ## figure title, enhanced mode, or position.\n  endif\n\nendfunction\n\nfunction term = gnuplot_default_term (plot_stream)\n\n  term = lower (getenv (\"GNUTERM\"));\n  ## If not specified, guess the terminal type.\n  if (isempty (term) || ! __gnuplot_has_terminal__ (term, plot_stream))\n    if (isguirunning () && __gnuplot_has_terminal__ (\"qt\", plot_stream))\n      term = \"qt\";\n    elseif (ismac ())\n      term = \"aqua\";\n    elseif (! isunix ())\n      term = \"windows\";\n    elseif (have_window_system ())\n      term = \"x11\";\n    else\n      term = \"dumb\";\n    endif\n  endif\n\nendfunction\n\nfunction [term, opts] = gnuplot_trim_term (string)\n\n  ## Extract the terminal type and terminal options (from print.m)\n  string = strtrim (string);\n  [term, opts] = strtok (string, ' ');\n  if (! isempty (opts))\n    opts(1) = \"\";  # trim extra space from strtok\n  endif\n\nendfunction\n\nfunction have_enhanced = gnuplot_is_enhanced_term (plot_stream, term)\n\n  ## Don't include pstex, pslatex or epslatex here as the TeX commands\n  ## should not be interpreted in that case.\n  persistent enhanced_terminals = {\"aqua\", \"canvas\", \"dumb\", \"emf\", \"gif\", ...\n                                   \"jpeg\", \"pdf\", \"pdfcairo\", \"pm\", \"png\", ...\n                                   \"pngcairo\", \"postscript\", \"qt\", \"svg\",  ...\n                                   \"windows\", \"wxt\", \"x11\"};\n\n  if (nargin < 2)\n    ## Determine the default gnuplot terminal.\n    term = gnuplot_default_term (plot_stream);\n  endif\n  have_enhanced = any (strcmp (term, enhanced_terminals));\n\nendfunction\n\nfunction ret = output_to_screen (term)\n  ret = any (strcmp (term,\n                     {\"aqua\", \"dumb\", \"pm\", \"qt\", \"windows\", \"wxt\", \"x11\"}));\nendfunction\n\nfunction retval = have_non_legend_axes (h)\n\n  retval = false;\n\n  all_axes = findall (h, \"type\", \"axes\");\n  if (! isempty (all_axes))\n    n_all_axes = numel (all_axes);\n    all_axes_tags = get (all_axes, \"tag\");\n    legend_axes = strcmp (all_axes_tags, \"legend\");\n    if (! isempty (legend_axes))\n      n_legend_axes = sum (legend_axes);\n      retval = (n_all_axes - n_legend_axes) > 1;\n    endif\n  endif\n\nendfunction\n\n\n## No test needed for internal helper function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/plot/util/__next_line_color__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{rgb} =} __next_line_color__ (@var{hax})\n## Undocumented internal function.\n## @end deftypefn\n\n## Return the next line color in the rotation.\n\nfunction rgb = __next_line_color__ (hax)\n\n  if (nargin == 1)\n    ca = hax;\n  else\n    ca = gca ();\n  endif\n\n  colororder = get (ca, \"colororder\");\n  if (isempty (colororder))\n    rgb = [0 0 0];   # black\n    return;\n  endif\n\n  color_idx = fix (get (ca, \"colororderindex\"));\n  num_colors = rows (colororder);\n  color_idx = mod (color_idx, num_colors);\n  if (color_idx == 0)\n    color_idx = num_colors;\n  elseif (color_idx < 0)\n    color_idx = 1;\n  endif\n\n  rgb = colororder(color_idx, :);\n\n  if (++color_idx > num_colors)\n    color_idx = mod (color_idx, num_colors);\n    if (color_idx == 0)\n      color_idx = 1;\n    endif\n    ## Rollover through all colors also switches to next linestyle.\n    style_idx = fix (get (ca, \"linestyleorderindex\"));\n    set (ca, \"linestyleorderindex\", ++style_idx);\n  endif\n  set (ca, \"colororderindex\", color_idx);\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   set (hax, \"colororder\", [1 0 0; 0 1 0; 0 0 1]);\n%!   hold on;\n%!   h = plot (1:2,1:2,\"o\", 2:3,2:3,\"x\", 3:4,3:4,\"d\");\n%!   assert (get (h, \"color\"), {[1 0 0]; [0 1 0]; [0 0 1]});\n%!   cla (hax);\n%!   hold on;\n%!   h1 = plot (1:2,1:2, \"o\");\n%!   h2 = plot (2:3,2:3, \"x\");\n%!   h3 = plot (3:4,3:4, \"d\");\n%!   assert (get ([h1;h2;h3], \"color\"), {[1 0 0]; [0 1 0]; [0 0 1]});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/__next_line_style__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{style} =} __next_line_style__ (@var{hax})\n## Undocumented internal function.\n## @end deftypefn\n\n## Return the next line style in the rotation.\n\n\nfunction [linestyle, marker] = __next_line_style__ (hax)\n\n  if (nargin == 1)\n    ca = hax;\n  else\n    ca = gca ();\n  endif\n\n  styleorder = get (ca, \"linestyleorder\");\n  if (isempty (styleorder))\n    linestyle = \"-\";   # basic line\n    marker = \"none\";   # no marker\n    return;\n  endif\n\n  if (ischar (styleorder))\n    styleorder = cellstr (styleorder);\n  endif\n\n  style_idx = fix (get (ca, \"linestyleorderindex\"));\n  num_styles = rows (styleorder);\n  style_idx = mod (style_idx, num_styles);\n  if (style_idx == 0)\n    style_idx = num_styles;\n  elseif (style_idx < 0)\n    style_idx = 1;\n  endif\n\n  options = __pltopt__ (\"__next_line_style__\", styleorder{style_idx});\n  linestyle = options.linestyle;\n  marker = options.marker;\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   set (hax, \"colororder\", [0 0 1]);\n%!   set (hax, \"linestyleorder\", {\"-\", \":\", \"--\"});\n%!   hold on;\n%!   h = plot (1:2,1:2, 2:3,2:3, 3:4,3:4);\n%!   assert (get (h, \"linestyle\"), {\"-\"; \":\"; \"--\"});\n%!   cla (hax);\n%!   hold on;\n%!   h1 = plot (1:2,1:2);\n%!   h2 = plot (2:3,2:3);\n%!   h3 = plot (3:4,3:4);\n%!   assert (get ([h1;h2;h3], \"linestyle\"), {\"-\"; \":\"; \"--\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/__opengl_info__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} __opengl_info__\n## @deftypefnx {} {@var{retval} =} __opengl_info__ ()\n##\n## Get OpenGL driver information.\n##\n## If no output values are requested, display information about the\n## OpenGL subsystem.  If an output is requested, return the information\n## in a structure.\n##\n## Fields in the structure are:\n##\n## @table @asis\n## @item version\n## OpenGL Driver version string\n##\n## @item vendor\n## OpenGL Driver vendor string\n##\n## @item renderer\n## OpenGL renderer string\n##\n## @item extensions\n## List of enabled extensions for the OpenGL driver.\n## @end table\n##\n## Example Code:\n##\n## @example\n## glinfo = __opengl_info__ ();\n## @end example\n##\n## @end deftypefn\n\nfunction retval = __opengl_info__ ()\n\n  [info, msg] = gl_info ();\n\n  if (! isempty (msg))\n    warning (msg);\n  else\n    if (nargout == 0)\n      printf (\"   version: %s\\n\", info.version);\n      printf (\"    vendor: %s\\n\", info.vendor);\n      printf (\"  renderer: %s\\n\", info.renderer);\n      printf (\"extensions:\\n\");\n      printf (\"  %s\\n\", info.extensions{:});\n    else\n      retval = info;\n    endif\n  endif\n\nendfunction\n\nfunction info = fig_gl_info (h)\n\n  info = [];\n\n  if (ishghandle (h) && strcmp (get (h, \"renderer\"), \"opengl\"))\n    vend = get (h, \"__gl_vendor__\");\n    if (isempty (vend))\n      return;\n    endif\n    info.vendor   = vend;\n    info.version  = get (h, \"__gl_version__\");\n    info.renderer = get (h, \"__gl_renderer__\");\n    info.extensions = strsplit (strtrim (get (h, \"__gl_extensions__\")));\n  endif\n\nendfunction\n\nfunction [info, msg] = gl_info ()\n\n  info = [];\n  msg = \"\";\n\n  ## If we have any open figures, take a look there for OpenGL info.\n  figs = findall (0, \"type\", \"figure\");\n\n  for hf = figs.'\n    info = fig_gl_info (hf);\n    if (! isempty (info))\n      break;\n    endif\n  endfor\n\n  ## If no info yet, try open a figure to get the info.\n  attempts = 1;\n  while (isempty (info) && attempts++ <= 3)\n    ## Need to create a figure, place an OpenGL object, and force drawing.\n    hf = figure (\"position\", [0,0,1,1], \"toolbar\", \"none\", \"menubar\", \"none\");\n    hax = axes ();\n    ## FIXME: Race condition means this delay may not always work.\n    pause (0.1 * attempts);\n    refresh (hf);\n    info = fig_gl_info (hf);\n    close (hf);\n  endwhile\n\n  if (isempty (info))\n    msg = \"__opengl_info__: can not obtain OpenGL information\";\n  endif\n\nendfunction\n\n\n## FIXME: This is really an internal function as indicated by the leading and\n## trailing underscores.  As such, it doesn't require tests.  In addition,\n## during the running of the test suite this function will throw up a figure\n## which is undesirable.  The tests have been commented out, but are still\n## available in case someone wants to hand-test the function by executing the\n## code.\n\n%!#testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp (\"fltk\", available_graphics_toolkits ()))\n%! old_toolkit = graphics_toolkit ();\n%! unwind_protect\n%!   graphics_toolkit (\"fltk\");\n%!   a = __opengl_info__ ();\n%! unwind_protect_cleanup\n%!   graphics_toolkit (old_toolkit);\n%! end_unwind_protect\n%! assert (! isempty (a));\n%! assert (isfield (a, \"version\"));\n\n%!#testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! old_toolkit = graphics_toolkit ();\n%! unwind_protect\n%!   graphics_toolkit (\"qt\");\n%!   a = __opengl_info__ ();\n%! unwind_protect_cleanup\n%!   graphics_toolkit (old_toolkit);\n%! end_unwind_protect\n%! assert (! isempty (a));\n%! assert (isfield (a, \"version\"));\n\n%!error __opengl_info (\"foobar\")\n"
  },
  {
    "path": "scripts/plot/util/__plt_get_axis_arg__.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{h}, @var{varargin}, @var{narg}] =} __plt_get_axis_arg__ (@var{caller}, @var{varargin})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [h, varargin, narg] = __plt_get_axis_arg__ (caller, varargin)\n\n  h = [];\n\n  ## Look for a scalar which is a graphics handle but not the\n  ## root object (0) or an ordinary figure (integer).\n  if (! isempty (varargin) && isscalar (varargin{1})\n      && ishghandle (varargin{1}) && varargin{1} != 0\n      && ! isfigure (varargin{1}))\n    htmp = varargin{1};\n    if (! isaxes (htmp))\n      error (\"%s: first argument must be axes handle\", caller);\n    endif\n    if (! strcmp (get (htmp, \"tag\"), \"legend\"))\n      h = htmp;\n      varargin(1) = [];\n    endif\n  ## Look for \"parent\"/axis prop/value pair\n  elseif (numel (varargin) > 1)\n    ## FIXME: This can be fooled by any string \"parent\" such as\n    ##        the prop/val pair \"tag\"/\"parent\".\n    ## varargin may contain char arrays.  Silence respective warning.\n    warning (\"off\", \"Octave:charmat-truncated\", \"local\");\n    parent = find (strcmpi (varargin, \"parent\"), 1, \"last\");\n    if (! isempty (parent))\n      if (parent == numel (varargin) || ! ishghandle (varargin{parent+1}))\n        error ('%s: \"parent\" value must be an axes handle', caller);\n      endif\n      htmp = varargin{parent+1};\n      if (isaxes (htmp) && ! strcmp (get (htmp, \"tag\"), \"legend\"))\n        h = htmp;\n        varargin(parent:parent+1) = [];\n      else\n        ## \"parent\" property for some other type like hggroup\n        h = ancestor (htmp, \"axes\");\n      endif\n    endif\n  endif\n\n  narg = length (varargin);\n\nendfunction\n\n\n## No test needed for internal helper function.\n%!assert (1)\n"
  },
  {
    "path": "scripts/plot/util/__pltopt__.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{options}, @var{valid}] =} __pltopt__ (@var{caller}, @var{opt}, @var{err_on_invalid})\n##\n## Decode plot option strings.\n##\n## @var{opt} can currently be some combination of the following:\n##\n## @table @asis\n## @item @qcode{\"-\"}\n## For solid linestyle (default).\n##\n## @item @qcode{\"--\"}\n## For dashed line style.\n##\n## @item @qcode{\"-.\"}\n## For linespoints plot style.\n##\n## @item @qcode{\":\"}\n## For dots plot style.\n##\n## @item  @qcode{\"r\"}\n## @itemx @qcode{\"red\"}\n## Red line color.\n##\n## @item  @qcode{\"g\"}\n## @itemx @qcode{\"green\"}\n## Green line color.\n##\n## @item  @qcode{\"b\"}\n## @itemx @qcode{\"blue\"}\n## Blue line color.\n##\n## @item  @qcode{\"c\"}\n## @itemx @qcode{\"cyan\"}\n## Cyan line color.\n##\n## @item  @qcode{\"m\"}\n## @itemx @qcode{\"magenta\"}\n## Magenta line color.\n##\n## @item  @qcode{\"y\"}\n## @itemx @qcode{\"yellow\"}\n## Yellow line color.\n##\n## @item  @qcode{\"k\"}\n## @itemx @qcode{\"black\"}\n## Black line color.\n##\n## @item  @qcode{\"w\"}\n## @itemx @qcode{\"white\"}\n## White line color.\n##\n## @item @qcode{\";displayname;\"}\n## The text between semicolons is used to set the @qcode{\"displayname\"}\n## property which determines the label used for the plot legend.\n##\n## @item  @qcode{\"+\"}\n## @itemx @qcode{\"o\"}\n## @itemx @qcode{\"*\"}\n## @itemx @qcode{\".\"}\n## @itemx @qcode{\"x\"}\n## @itemx @qcode{\"|\"}\n## @itemx @qcode{\"_\"}\n## @itemx @qcode{\"s\"}\n## @itemx @qcode{\"d\"}\n## @itemx @qcode{\"^\"}\n## @itemx @qcode{\"v\"}\n## @itemx @qcode{\">\"}\n## @itemx @qcode{\"<\"}\n## @itemx @qcode{\"p\"}\n## @itemx @qcode{\"h\"}\n## Used in combination with the points or linespoints styles, set the point\n## style.\n## @end table\n##\n## @end deftypefn\n\nfunction [options, valid] = __pltopt__ (caller, opt, err_on_invalid = true)\n\n  if (ischar (opt))\n    opt = cellstr (opt);\n  elseif (! iscellstr (opt))\n    ## FIXME: This is an internal function.  Can't we rely on valid input?\n    error (\"__pltopt__: argument must be a character string or cell array of character strings\");\n  endif\n\n  nel = numel (opt);\n\n  if (nel)\n    for i = nel:-1:1\n      [options(i), valid] = decode_linespec (caller, opt{i}, err_on_invalid);\n      if (! err_on_invalid && ! valid)\n        return;\n      endif\n    endfor\n  else\n    options = __default_plot_options__ ();\n    valid = true;\n  endif\n\nendfunction\n\n## Really decode plot option strings.\nfunction [options, valid] = decode_linespec (caller, opt, err_on_invalid)\n\n  persistent default_options = __default_plot_options__ ();\n\n  options = default_options;\n  valid = true;\n\n  have_linestyle = false;\n  have_marker = false;\n\n  ## If called by __errplot__, extract the linestyle before proceeding.\n  if (strcmp (caller, \"__do_errplot__\"))\n    if (strncmp (opt, \"#~>\", 3))\n      n = 3;\n    elseif (strncmp (opt, \"#~\", 2) || strncmp (opt, \"~>\", 2))\n      n = 2;\n    elseif (strncmp (opt, \"~\", 1) || strncmp (opt, \">\", 1)\n            || strncmp (opt, \"#\", 1))\n      n = 1;\n    else\n      n = 0;\n    endif\n    options.errorstyle = opt(1:n);\n    opt(1:n) = [];\n  else\n    options.errorstyle = \"~\";\n  endif\n\n  while (! isempty (opt))\n    topt = opt(1);\n    n = 1;\n\n    ## LineStyles\n    if (strncmp (opt, \"--\", 2) || strncmp (opt, \"-.\", 2))\n      options.linestyle = opt(1:2);\n      have_linestyle = true;\n      n = 2;\n    elseif (topt == \"-\" || topt == \":\")\n      have_linestyle = true;\n      options.linestyle = topt;\n    ## Markers\n    elseif (any (topt == \"+o*.x|_sd^v><ph\"))\n      have_marker = true;\n      ## Check for long form marker styles\n      if (any (topt == \"sdhp\"))\n        if (strncmp (opt, \"square\", 6))\n          n = 6;\n        elseif (strncmp (opt, \"diamond\", 7))\n          n = 7;\n        elseif (strncmp (opt, \"hexagram\", 8))\n          n = 8;\n        elseif (strncmp (opt, \"pentagram\", 9))\n          n = 9;\n        endif\n      endif\n      ## Backward compatibility.  Leave undocumented.\n      if (topt == \"@\")\n        warning (\"Octave:deprecated-option\", ...\n                 \"%s: marker type '@' is deprecated.  Use '+' instead.\", ...\n                 caller);\n        topt = \"+\";\n      endif\n      options.marker = topt;\n    elseif (topt == \"k\")\n      options.color = [0, 0, 0];\n    elseif (topt == \"r\")\n      if (strncmp (opt, \"red\", 3))\n        n = 3;\n      endif\n      options.color = [1, 0, 0];\n    elseif (topt == \"g\")\n      if (strncmp (opt, \"green\", 5))\n        n = 5;\n      endif\n      options.color = [0, 1, 0];\n    elseif (topt == \"b\")\n      if (strncmp (opt, \"black\", 5))\n        options.color = [0, 0, 0];\n        n = 5;\n      elseif (strncmp (opt, \"blue\", 4))\n        options.color = [0, 0, 1];\n        n = 4;\n      else\n        options.color = [0, 0, 1];\n      endif\n    elseif (topt == \"y\")\n      if (strncmp (opt, \"yellow\", 6))\n        n = 6;\n      endif\n      options.color = [1, 1, 0];\n    elseif (topt == \"m\")\n      if (strncmp (opt, \"magenta\", 7))\n        n = 7;\n      endif\n      options.color = [1, 0, 1];\n    elseif (topt == \"c\")\n      if (strncmp (opt, \"cyan\", 4))\n        n = 4;\n      endif\n      options.color = [0, 1, 1];\n    elseif (topt == \"w\")\n      if (strncmp (opt, \"white\", 5))\n        n = 5;\n      endif\n      options.color = [1, 1, 1];\n    elseif (isspace (topt))\n      ## Do nothing.\n    elseif (topt == \";\")\n      t = index (opt(2:end), \";\");\n      if (t)\n        options.key = opt(2:t);\n        n = t+1;\n      else\n        ## Note: err_on_invalid is not applied here.  The calling code pattern\n        ## uses this parameter to detect a linespec versus a property name.\n        ## Here, a linespec has been found, but it is badly constructed.\n        error (\"%s: key label missing terminating ';'\", caller);\n      endif\n    else\n      if (err_on_invalid)\n        error (\"%s: unrecognized format character: '%s'\", caller, topt);\n      else\n        valid = false;\n        options = default_options;\n        return;\n      endif\n    endif\n\n    opt(1:n) = [];  # Delete decoded portion\n  endwhile\n\n  if (! have_linestyle && have_marker)\n    options.linestyle = \"none\";\n  endif\n\n  if (have_linestyle && ! have_marker)\n    options.marker = \"none\";\n  endif\n\nendfunction\n\n\n## Only cursory testing.  Real testing done by appearance of plots.\n%!test\n%! opts = __pltopt__ (\"abc\", \"\");\n%! assert (opts.color, []);\n%! assert (opts.linestyle, []);\n%! assert (opts.marker, []);\n%! assert (opts.key, \"\");\n%!test\n%! opts = __pltopt__ (\"abc\", \"r:x\");\n%! assert (opts.color, [1 0 0]);\n%! assert (opts.linestyle, \":\");\n%! assert (opts.marker, \"x\");\n%!test\n%! opts = __pltopt__ (\"abc\", \"-.blackx\");\n%! assert (opts.color, [0 0 0]);\n%! assert (opts.linestyle, \"-.\");\n%! assert (opts.marker, \"x\");\n%!test\n%! opts = __pltopt__ (\"abc\", \"gsquare\");\n%! assert (opts.color, [0 1 0]);\n%! assert (opts.linestyle, \"none\");\n%! assert (opts.marker, \"s\");\n%!test\n%! opts = __pltopt__ (\"abc\", \";Title;\");\n%! assert (opts.key, \"Title\");\n%! assert (opts.color, []);\n%! assert (opts.linestyle, []);\n%! assert (opts.marker, []);\n%!test\n%! opts = __pltopt__ (\"__do_errplot__\", \"~>r\");\n%! assert (opts.errorstyle, \"~>\");\n%! assert (opts.color, [1 0 0 ]);\n%! assert (opts.linestyle, []);\n%! assert (opts.marker, []);\n\n## Test input validation\n%!error <argument must be a character string or cell array> __pltopt__ (\"abc\", 1)\n%!error <missing terminating ';'> __pltopt__ (\"abc\", \"rx;my_title\", true)\n%!error <unrecognized format character: 'u'> __pltopt__ (\"abc\", \"u\", true)\n"
  },
  {
    "path": "scripts/plot/util/allchild.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} allchild (@var{handles})\n## Find all children, including hidden children, of a graphics object.\n##\n## This function is similar to @code{get (h, \"children\")}, but also returns\n## hidden objects (HandleVisibility = @qcode{\"off\"}).\n##\n## If @var{handles} is a scalar, @var{h} will be a vector.  Otherwise,\n## @var{h} will be a cell matrix of the same size as @var{handles} and each\n## cell will contain a vector of handles.\n## @seealso{findall, findobj, get, set}\n## @end deftypefn\n\nfunction h = allchild (handles)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  shh = get (0, \"showhiddenhandles\");\n  unwind_protect\n    set (0, \"showhiddenhandles\", \"on\");\n    h = get (handles, \"children\");\n  unwind_protect_cleanup\n    set (0, \"showhiddenhandles\", shh);\n  end_unwind_protect\n\nendfunction\n\n\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! toolkit = graphics_toolkit (\"qt\");\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   l = line ();\n%!   kids = allchild (hf);\n%!   assert (get (kids, \"type\"), ...\n%!           {\"axes\"; \"uitoolbar\"; \"uimenu\"; \"uimenu\"; \"uimenu\"});\n%! unwind_protect_cleanup\n%!   close (hf);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n%!error <Invalid call> allchild ()\n"
  },
  {
    "path": "scripts/plot/util/ancestor.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{parent} =} ancestor (@var{h}, @var{type})\n## @deftypefnx {} {@var{parent} =} ancestor (@var{h}, @var{type}, \"toplevel\")\n## Return the first ancestor of handle object @var{h} whose type matches\n## @var{type}, where @var{type} is a character string.\n##\n## If @var{type} is a cell array of strings, return the first parent whose\n## type matches any of the given type strings.\n##\n## If the handle object @var{h} itself is of type @var{type}, return @var{h}.\n##\n## If @qcode{\"toplevel\"} is given as a third argument, return the highest\n## parent in the object hierarchy that matches the condition, instead\n## of the first (nearest) one.\n## @seealso{findobj, findall, allchild}\n## @end deftypefn\n\nfunction p = ancestor (h, type, toplevel)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (ischar (type))\n    type = { type };\n  elseif (! iscellstr (type))\n    error (\"ancestor: TYPE must be a string or cell array of strings\");\n  endif\n\n  find_first = true;\n  if (nargin == 3)\n    if (ischar (toplevel) && strcmpi (toplevel, \"toplevel\"))\n      find_first = false;\n    else\n      error ('ancestor: third argument must be \"toplevel\"');\n    endif\n  endif\n\n  if (isempty (h))\n    p = [];\n  else\n    p = cell (numel (h), 1);\n    h = num2cell (h);\n    for nh = 1:numel (h)\n      while (true)\n        if (isempty (h{nh}) || ! ishghandle (h{nh}))\n          break;\n        endif\n        if (any (strcmpi (get (h{nh}, \"type\"), type)))\n          p{nh} = h{nh};\n          if (find_first)\n            break;\n          endif\n        endif\n        h{nh} = get (h{nh}, \"parent\");\n      endwhile\n    endfor\n    if (nh == 1)\n      p = p{1};\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hl = line ();\n%!   assert (ancestor (hl, \"axes\"), gca);\n%!   assert (ancestor (hl, \"figure\"), hf);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!    hg1 = hggroup (\"parent\", gca);\n%!    hg2 = hggroup (\"parent\", hg1);\n%!    hl = line (\"parent\", hg2);\n%!    assert (ancestor (hl, \"line\"), hl);\n%!    assert (ancestor (hl, \"axes\"), gca);\n%!    assert (ancestor (hl, \"figure\"), hf);\n%!    assert (ancestor (hl, \"hggroup\"), hg2);\n%!    assert (ancestor (hl, \"hggroup\", \"toplevel\"), hg1);\n%!    assert (ancestor (hl, {\"hggroup\", \"axes\"}), hg2);\n%!    assert (ancestor (hl, {\"hggroup\", \"axes\"}, \"toplevel\"), gca);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!assert (ancestor ([], \"axes\"), [])\n\n%!error <Invalid call> ancestor ()\n%!error <TYPE must be a string> ancestor (1,2)\n%!error <third argument must be \"toplevel\"> ancestor (1, \"axes\", \"foo\")\n"
  },
  {
    "path": "scripts/plot/util/axes.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} axes ()\n## @deftypefnx {} {} axes (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {} axes (@var{hpar}, @var{property}, @var{value}, @dots{})\n## @deftypefnx {} {} axes (@var{hax})\n## @deftypefnx {} {@var{h} =} axes (@dots{})\n## Create a Cartesian axes object and return a handle to it, or set the current\n## axes to @var{hax}.\n##\n## Called without any arguments, or with @var{property}/@var{value} pairs,\n## construct a new axes.  The optional argument @var{hpar} is a graphics handle\n## specifying the parent for the new axes and may be a figure, uipanel, or\n## uitab.\n##\n## Called with a single axes handle argument @var{hax}, the function makes\n## @var{hax} the current axes (as returned by @code{gca}).  It also makes\n## the figure which contains @var{hax} the current figure (as returned by\n## @code{gcf}).  Finally, it restacks the parent object's @code{children}\n## property so that the axes @var{hax} appears before all other axes handles\n## in the list.  This causes @var{hax} to be displayed on top of any other axes\n## objects (Z-order stacking).  In addition it restacks any legend or colorbar\n## objects associated with @var{hax} so that they are also visible.\n##\n## Programming Note: The full list of properties is documented at\n## @ref{Axes Properties}.\n## @seealso{gca, set, get}\n## @end deftypefn\n\nfunction h = axes (varargin)\n\n  htmp = hpar = [];\n  if (nargin > 0)\n    if (ishghandle (varargin{1}(1)))\n      htmp = varargin{1};\n      if (! isscalar (htmp))\n        error (\"axes: H must be a scalar handle\");\n      endif\n      typ = get (htmp, \"type\");\n      if (strcmp (typ, \"axes\") && nargin == 1)\n        cf = ancestor (htmp, \"figure\");\n        if (__is_handle_visible__ (htmp))\n          set (0, \"currentfigure\", cf);\n          set (cf, \"currentaxes\", htmp);\n        endif\n        restack_axes (htmp, get (htmp, \"parent\"));\n\n        if (nargout > 0)\n          h = htmp;\n        endif\n        return;\n\n      elseif (any (strcmp (typ, {\"figure\", \"uipanel\", \"uitab\"})))\n        hpar = htmp;\n        htmp = [];\n        varargin(1) = [];\n\n      else\n        error (\"axes: H must be a handle to an axes or container\");\n      endif\n    endif\n  endif\n\n  if (isempty (hpar))\n    ## Find a parent if not given as first argument.\n    idx = find (strcmpi (varargin(1:2:end), \"parent\"), 1, \"first\");\n    if (! isempty (idx) && numel (varargin) >= 2*idx)\n      hpar = varargin{2*idx};\n      varargin([2*idx-1, 2*idx]) = [];\n    else\n      hpar = gcf ();\n    endif\n  endif\n\n  ## If there is an annotation axes currently on top of the children stack,\n  ## then it must be placed back on top.\n  ## FIXME: It may be necessary to keep uiXXX objects above all axes objects\n  ##        including even the transparent scribe axes layer.\n  ch = allchild (hpar);\n  h_annotation = ch(strcmp (get (ch, \"tag\"), \"scribeoverlay\"));\n\n  ## Create an axes object.\n  htmp = __go_axes__ (hpar, varargin{:});\n  if (__is_handle_visible__ (htmp))\n    set (ancestor (hpar, \"figure\"), \"currentaxes\", htmp);\n  endif\n\n  ## Restack annotation object if necessary\n  if (! isempty (h_annotation))\n    ## FIXME: This will put annotation layer first, above even uicontrol\n    ## objects.  May need to keep annotation layer above all axes only.\n    shh = get (0, \"ShowHiddenHandles\");\n    unwind_protect\n      set (0, \"ShowHiddenHandles\", \"on\");\n      ch(ch == h_annotation) = htmp;\n      ch = [h_annotation; ch];\n      set (hpar, \"children\", ch);\n    unwind_protect_cleanup\n      set (0, \"ShowHiddenHandles\", shh);\n    end_unwind_protect\n  endif\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\nfunction restack_axes (h, hpar)\n\n  shh = get (0, \"ShowHiddenHandles\");\n  unwind_protect\n    set (0, \"ShowHiddenHandles\", \"on\");\n    ch = get (hpar, \"children\");\n    axidx = strcmp (get (ch, \"type\"), \"axes\");\n    ## Strip out any annotation axes layer, unless h itself is annotation axes.\n    if (! strcmp (get (h, \"tag\"), \"scribeoverlay\"))\n      axidx(axidx) = ! strcmp (get (ch(axidx), \"tag\"), \"scribeoverlay\");\n    endif\n    hax = ch(axidx);  # List of axes\n\n    ## Find and stack any legend belonging to this axes above this axes.\n    try\n      hleg = get (h, \"__legend_handle__\");\n    catch\n      hleg = false;\n    end_try_catch\n\n    ## Find and stack any colorbar belonging to this axes above this axes.\n    try\n      hcb = get (h, \"__colorbar_handle__\");\n    catch\n      hcb = false;\n    end_try_catch\n\n    ## Preserve order of colorbars and legends above this axes\n    if (hleg || hcb)\n      if (hleg && ! hcb)\n        h = [hleg; h];\n      elseif (hcb && ! hleg)\n        h = [hcb; h];\n      else\n        hcb_idx = find (hcb == hax);\n        hleg_idx = find (hleg == hax);\n        if (hleg_idx < hcb_idx)\n          h = [hleg; hcb; h];\n        else\n          h = [hcb; hleg; h];\n        endif\n      endif\n    endif\n\n    ## FIXME: ismember call is very slow (2/3rds of runtime for function)\n    ch(axidx) = [h; hax(! ismember (hax, h))];\n    set (hpar, \"children\", ch);\n\n  unwind_protect_cleanup\n    set (0, \"ShowHiddenHandles\", shh);\n  end_unwind_protect\n\nendfunction\n\n\n## FIXME: These demos actually just show how axes objects behave.\n##        They do not show how the axes() function itself works.\n%!demo\n%! clf;\n%! x = -10:10;\n%! plot (x,x, x,-x);\n%! set (gca, \"yscale\", \"log\");\n%! legend ({\"x >= 1\", \"x <= 1\"}, \"location\", \"north\");\n%! title ({\"log axes discard negative data\", \"ylim = [1, 10]\"});\n\n%!demo\n%! clf;\n%! x = -10:0.1:10;\n%! y = sin (x)./(1 + abs (x)) + 0.1*x - 0.4;\n%! plot (x, y);\n%! set (gca, \"xaxislocation\", \"origin\");\n%! set (gca, \"yaxislocation\", \"origin\");\n%! box off;\n%! title ({\"no plot box\", \"xaxislocation = origin, yaxislocation = origin\"});\n\n%!demo\n%! clf;\n%! x = -10:0.1:10;\n%! y = sin (x)./(1+abs (x)) + 0.1*x - 0.4;\n%! plot (x, y);\n%! set (gca, \"xaxislocation\", \"origin\");\n%! set (gca, \"yaxislocation\", \"left\");\n%! box off;\n%! title ({\"no plot box\", \"xaxislocation = origin, yaxislocation = left\"});\n\n%!demo\n%! clf;\n%! x = -10:0.1:10;\n%! y = sin (x)./(1+abs (x)) + 0.1*x - 0.4;\n%! plot (x, y);\n%! title (\"no plot box\");\n%! set (gca, \"xaxislocation\", \"origin\");\n%! set (gca, \"yaxislocation\", \"right\");\n%! box off;\n%! title ({\"no plot box\", \"xaxislocation = origin, yaxislocation = right\"});\n\n%!demo\n%! clf;\n%! x = -10:0.1:10;\n%! y = sin (x)./(1+abs (x)) + 0.1*x - 0.4;\n%! plot (x, y);\n%! set (gca, \"xaxislocation\", \"bottom\");\n%! set (gca, \"yaxislocation\", \"origin\");\n%! box off;\n%! title ({\"no plot box\", \"xaxislocation = bottom, yaxislocation = origin\"});\n\n%!demo\n%! clf;\n%! x = -10:0.1:10;\n%! y = sin (x)./(1+abs (x)) + 0.1*x - 0.4;\n%! plot (x, y);\n%! set (gca, \"xaxislocation\", \"top\");\n%! set (gca, \"yaxislocation\", \"origin\");\n%! box off;\n%! title ({\"no plot box\", \"xaxislocation = top, yaxislocation = origin\"});\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax1 = axes (\"tag\", \"axes1\");\n%!   plot (1:10, \"b\");\n%!   hleg1 = legend (\"leg1\", \"location\", \"east\");\n%!   hcb1 = colorbar (\"location\", \"east\");\n%!   hanno = annotation (\"arrow\");\n%!   hscribe = get (hanno, \"parent\");\n%!\n%!   hax2 = axes (\"tag\", \"axes2\");\n%!   plot (10:-1:1, \"r\");\n%!   hcb2 = colorbar (\"location\", \"east\");\n%!   hleg2 = legend (\"hax2\");\n%!\n%!   ## Verify base configuration\n%!   ch = allchild (hf);\n%!   hax = ch(isaxes (ch));\n%!   hax1pos = find (hax1 == hax);\n%!   hax2pos = find (hax2 == hax);\n%!   hleg1pos = find (hleg1 == hax);\n%!   hleg2pos = find (hleg2 == hax);\n%!   hcb1pos = find (hcb1 == hax);\n%!   hcb2pos = find (hcb2 == hax);\n%!   hscribepos = find (hscribe == hax);\n%!\n%!   assert (all (hscribepos < ...\n%!                [hax1pos, hax2pos, hleg1pos, hleg2pos, hcb1pos, hcb2pos]));\n%!   assert (hax2pos < hax1pos);\n%!   assert (hleg2pos < hcb2pos && hcb2pos < hax2pos);\n%!   assert (hcb1pos < hleg1pos && hleg1pos < hax1pos);\n%!\n%!   ## Restack axes1 on top\n%!   axes (hax1);\n%!   ch = allchild (hf);\n%!   hax = ch(isaxes (ch));\n%!   hax1pos = find (hax1 == hax);\n%!   hax2pos = find (hax2 == hax);\n%!   hleg1pos = find (hleg1 == hax);\n%!   hleg2pos = find (hleg2 == hax);\n%!   hcb1pos = find (hcb1 == hax);\n%!   hcb2pos = find (hcb2 == hax);\n%!   hscribepos = find (hscribe == hax);\n%!\n%!   assert (all (hscribepos < ...\n%!                [hax1pos, hax2pos, hleg1pos, hleg2pos, hcb1pos, hcb2pos]));\n%!   assert (hax1pos < hax2pos);\n%!   assert (hcb1pos < hleg1pos && hleg1pos < hax1pos);\n%!   assert (hleg2pos < hcb2pos && hcb2pos < hax2pos);\n%!\n%!   ## Restack axes2 on top\n%!   axes (hax2);\n%!   ch = allchild (hf);\n%!   hax = ch(isaxes (ch));\n%!   hax1pos = find (hax1 == hax);\n%!   hax2pos = find (hax2 == hax);\n%!   hleg1pos = find (hleg1 == hax);\n%!   hleg2pos = find (hleg2 == hax);\n%!   hcb1pos = find (hcb1 == hax);\n%!   hcb2pos = find (hcb2 == hax);\n%!   hscribepos = find (hscribe == hax);\n%!\n%!   assert (all (hscribepos < ...\n%!                [hax1pos, hax2pos, hleg1pos, hleg2pos, hcb1pos, hcb2pos]));\n%!   assert (hax2pos < hax1pos);\n%!   assert (hleg2pos < hcb2pos && hcb2pos < hax2pos);\n%!   assert (hcb1pos < hleg1pos && hleg1pos < hax1pos);\n%!\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <H must be a scalar handle> axes ([0, 0])\n%!error <H must be a handle to an axes or container> axes (0)\n"
  },
  {
    "path": "scripts/plot/util/cla.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} cla\n## @deftypefnx {} {} cla reset\n## @deftypefnx {} {} cla (@var{hax})\n## @deftypefnx {} {} cla (@var{hax}, \"reset\")\n## Clear the current or specified (@var{hax}) axes object.\n##\n## @code{cla} operates by deleting child graphic objects with visible\n## handles (@code{HandleVisibility} = @qcode{\"on\"}).  This typically clears the\n## axes of any visual objects, but leaves in place axes limits, tick marks and\n## labels, camera view, etc.  In addition, the automatic coloring and styling\n## of lines is reset by changing the axes properties @code{ColorOrderIndex},\n## @code{LinestyleOrderIndex} to 1.\n##\n## If the optional argument @qcode{\"reset\"} is specified, delete all child\n## objects, including those with hidden handles, and reset all axes properties\n## to their defaults.  However, the following properties are not reset:\n## @code{Position}, @code{Units}.\n##\n## If the first argument @var{hax} is an axes handle, then operate on\n## this axes rather than the current axes returned by @code{gca}.\n## @seealso{clf, delete, reset}\n## @end deftypefn\n\nfunction cla (hax, do_reset = false)\n\n  if (nargin == 0)\n    hax = gca ();\n  elseif (nargin == 1)\n    if (isscalar (hax) && isaxes (hax))\n      ## Normal case : cla (hax) without reset\n    elseif (ischar (hax) && strcmpi (hax, \"reset\"))\n      hax = gca ();\n      do_reset = true;\n    else\n      print_usage ();\n    endif\n  else\n    if (isscalar (hax) && isaxes (hax)\n        && ischar (do_reset) && strcmpi (do_reset, \"reset\"))\n      do_reset = true;\n    else\n      print_usage ();\n    endif\n  endif\n\n  if (! do_reset)\n    delete (get (hax, \"children\"));\n    set (hax, \"colororderindex\", 1, \"linestyleorderindex\", 1);\n  else\n    delete (allchild (hax));\n    reset (hax);\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   assert (! isempty (get (gca, \"children\")));\n%!   cla ();\n%!   assert (isempty (get (gca, \"children\")));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = gca ();\n%!   plot (hax, 1:10);\n%!   assert (get (hax, \"colororderindex\"), 2);\n%!   set (hax, \"ticklabelinterpreter\", \"none\");\n%!   cla (hax);\n%!   kids = get (hax, \"children\");\n%!   assert (numel (kids), 0);\n%!   assert (get (hax, \"colororderindex\"), 1);\n%!   assert (get (hax, \"ticklabelinterpreter\"), \"none\");\n%!\n%!   hp = plot (hax, 1:10, \"handlevisibility\", \"off\");\n%!   cla (hax);\n%!   assert (ishghandle (hp), true);\n%!\n%!   cla (hax, \"reset\");\n%!   kids = get (hax, \"children\");\n%!   assert (numel (kids), 0);\n%!   assert (ishghandle (hp), false);\n%!   assert (get (hax, \"ticklabelinterpreter\"), \"tex\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/clf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} clf\n## @deftypefnx {} {} clf reset\n## @deftypefnx {} {} clf (@var{hfig})\n## @deftypefnx {} {} clf (@var{hfig}, \"reset\")\n## @deftypefnx {} {@var{h} =} clf (@dots{})\n## Clear the current figure window.\n##\n## @code{clf} operates by deleting child graphics objects with visible\n## handles (HandleVisibility = @qcode{\"on\"}).\n##\n## If the optional argument @qcode{\"reset\"} is specified, delete all child\n## objects including those with hidden handles and reset all figure\n## properties to their defaults.  However, the following properties are not\n## reset: Position, Units, PaperPosition, PaperUnits.\n##\n## If the first argument @var{hfig} is a figure handle, then operate on\n## this figure rather than the current figure returned by @code{gcf}.\n##\n## The optional return value @var{h} is the graphics handle of the figure\n## window that was cleared.\n## @seealso{cla, close, delete, reset}\n## @end deftypefn\n\nfunction h = clf (varargin)\n\n  if (nargin > 2)\n    print_usage ();\n  elseif (nargin == 0)\n    hfig = gcf ();\n    do_reset = false;\n  elseif (nargin == 1)\n    if (isscalar (varargin{1}) && isfigure (varargin{1}))\n      hfig = varargin{1};\n      do_reset = false;\n    elseif (ischar (varargin{1}) && strcmpi (varargin{1}, \"reset\"))\n      hfig = gcf ();\n      do_reset = true;\n    else\n      print_usage ();\n    endif\n  else\n    if (isscalar (varargin{1}) && isfigure (varargin{1})\n        && ischar (varargin{2}) && strcmpi (varargin{2}, \"reset\"))\n      hfig = varargin{1};\n      do_reset = true;\n    else\n      print_usage ();\n    endif\n  endif\n\n  if (do_reset)\n    ## Delete all the children, including the ones with hidden handles,\n    ## except default menus and toolbar.\n\n    kids = allchild (hfig);\n\n    if (! isempty (kids))\n      tags = get (kids, \"tag\");\n      ## It's possible for a figure to have just one child and then get\n      ## will return a single value instead of a cell array.\n      if (! iscell (tags))\n        tags = {tags};\n      endif\n      ismenu = cellfun (@(s) strncmp (s, \"__default_menu_\", 15), tags);\n      istoolbar = cellfun (@(s) strncmp (s, \"__default_toolbar_menu_\", 18), tags);\n      delete (kids(! ismenu & ! istoolbar));\n    endif\n\n    reset (hfig);\n\n    if (! isempty (kids))\n      ## Recover figure listeners which have been deleted\n      __add_default_menu__ (hfig, kids(ismenu), kids(istoolbar));\n    endif\n\n    __set_default_mouse_modes__ (hfig);\n  else\n    ## Select only the chilren with visible handles.\n    delete (get (hfig, \"children\"));\n\n    ## Also delete the annotation axes\n    hover = findall (hfig, \"-depth\", 1, \"tag\", \"scribeoverlay\");\n    delete (hover);\n  endif\n\n  if (nargout > 0)\n    h = hfig;\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   l = line ();\n%!   assert (! isempty (get (gcf, \"children\")));\n%!   clf;\n%!   assert (isempty (get (gcf, \"children\")));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   clf;\n%!   assert (isempty (get (gcf, \"children\")));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! set (0, \"defaultfigurevisible\", \"off\");\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   plot (1:10);\n%!   set (hf, \"papertype\", \"tabloid\");\n%!   clf (hf);\n%!   assert (isempty (get (gcf, \"children\")));\n%!   assert (get (hf, \"papertype\"), \"tabloid\");\n%!   plot (1:10);\n%!   clf (hf, \"reset\");\n%!   kids = get (hf, \"children\");\n%!   assert (isempty (get (gcf, \"children\")));\n%!   assert (get (hf, \"papertype\"), \"usletter\");\n%! unwind_protect_cleanup\n%!   set (0, \"defaultfigurevisible\", \"remove\");\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/close.m",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} close\n## @deftypefnx {} {} close (@var{h})\n## @deftypefnx {} {} close @var{figname}\n## @deftypefnx {} {} close all\n## @deftypefnx {} {} close all hidden\n## @deftypefnx {} {} close all force\n## @deftypefnx {} {@var{status} =} close (@dots{})\n## Close figure window(s).\n##\n## When called with no arguments, close the current figure.  This is equivalent\n## to @code{close (gcf)}.  If the input @var{h} is a graphic handle, or vector\n## of graphics handles, then close each figure in @var{h}.  The figure to\n## close may also be specified by name @var{figname} which is matched against\n## the @qcode{\"Name\"} property of all figures.\n##\n## If the argument @qcode{\"all\"} is given then all figures with visible handles\n## (HandleVisibility = @qcode{\"on\"}) are closed.\n##\n## If the additional argument @qcode{\"hidden\"} is given then all figures,\n## including hidden ones, are closed.\n##\n## If the additional argument @qcode{\"force\"} is given then figures are closed\n## even when @qcode{\"closerequestfcn\"} has been altered to prevent closing the\n## window.\n##\n## If the optional output @var{status} is requested then Octave returns 1 if\n## the figure windows were closed successfully.\n##\n## Implementation Note: @code{close} operates by making the handle @var{h} the\n## current figure, and then calling the function specified by the\n## @qcode{\"closerequestfcn\"} property of the figure.  By default, the function\n## @code{closereq} is used.  It is possible that the function invoked will\n## delay or abort removing the figure.  To remove a figure without executing\n## any callback functions use @code{delete}.  When writing a callback function\n## to close a window do not use @code{close} to avoid recursion.\n##\n## @seealso{closereq, delete}\n## @end deftypefn\n\nfunction status = close (arg1, arg2)\n\n  figs = [];\n\n  if (nargin == 0)\n    ## Close current figure.\n    ## Can't use gcf because it opens a new plot window if one does not exist.\n    figs = get (0, \"currentfigure\");\n    if (figs == 0)  # don't call close on root object\n      figs = [];\n    endif\n  elseif (nargin == 1)\n    if (ischar (arg1))\n      if (strcmpi (arg1, \"all\"))\n        figs = get (0, \"children\");\n        figs = figs(isfigure (figs));\n      else\n        figs = findall (\"-depth\", 1, \"name\", arg1, \"type\", \"figure\");\n      endif\n    elseif (any (isfigure (arg1)))\n      figs = arg1(isfigure (arg1));\n    elseif (isempty (arg1))\n      figs = [];  # Silently accept null argument for Matlab compatibility\n    else\n      error ('close: first argument must be \"all\", a figure handle, or a figure name');\n    endif\n  elseif (ischar (arg2)\n          && (strcmpi (arg2, \"hidden\") || strcmpi (arg2, \"force\")))\n    if (ischar (arg1))\n      if (strcmpi (arg1, \"all\"))\n        figs = allchild (0);\n        figs = figs(isfigure (figs));\n      else\n        figs = findall (\"-depth\", 1, \"name\", arg1, \"type\", \"figure\");\n      endif\n    elseif (any (isfigure (arg1)))\n      figs = arg1(isfigure (arg1));\n    elseif (isempty (arg1))\n      figs = [];  # Silently accept null argument for Matlab compatibility\n    else\n      error ('close: first argument must be \"all\", a figure handle, or a figure name');\n    endif\n    if (strcmpi (arg2, \"force\"))\n      delete (figs);\n      return;\n    endif\n  else\n    error ('close: second argument must be \"hidden\" or \"force\"');\n  endif\n\n  ## Save and restore current figure\n  cf = get (0, \"currentfigure\");\n\n  for hfig = figs(:).'\n    set (0, \"currentfigure\", hfig);  # make figure current\n    __go_execute_callback__ (hfig, \"closerequestfcn\");\n  endfor\n\n  if (isfigure (cf))\n    set (0, \"currentfigure\", cf);\n  endif\n\n  if (nargout > 0)\n    status = 1;\n  endif\n\nendfunction\n\n\n%!test\n%! ## Test closing gcf\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   close ();\n%!   assert (! isfigure (hf));\n%! unwind_protect_cleanup\n%!   if (isfigure (hf))\n%!     delete (hf);\n%!   endif\n%! end_unwind_protect\n\n%!test\n%! ## Test closing specified numeric figure handle\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   close (hf);\n%!   assert (! isfigure (hf));\n%! unwind_protect_cleanup\n%!   if (isfigure (hf))\n%!     delete (hf);\n%!   endif\n%! end_unwind_protect\n\n%!test\n%! ## Test closing specified named figure handle\n%! hf = figure (\"visible\", \"off\", \"name\", \"__foobar__\");\n%! unwind_protect\n%!   close __foobar__;\n%!   assert (! isfigure (hf));\n%! unwind_protect_cleanup\n%!   if (isfigure (hf))\n%!     delete (hf);\n%!   endif\n%! end_unwind_protect\n\n%!test\n%! ## Test forcing the close of a figure\n%! hf = figure (\"visible\", \"off\", \"closerequestfcn\", []);\n%! unwind_protect\n%!   close (hf);\n%!   assert (isfigure (hf));    # figure not deleted\n%!   close (hf, \"force\");\n%!   assert (! isfigure (hf));  # figure finally deleted\n%! unwind_protect_cleanup\n%!   if (isfigure (hf))\n%!     delete (hf);\n%!   endif\n%! end_unwind_protect\n\n## Test input validation\n%!error <first argument must be \"all\", a figure handle> close ({\"all\"})\n%!error <first argument must be \"all\", a figure handle> close (-1)\n%!error <second argument must be \"hidden\"> close all hid\n%!error <second argument must be \"hidden\"> close all for\n"
  },
  {
    "path": "scripts/plot/util/closereq.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} closereq ()\n## Close the current figure and delete all graphics objects associated with it.\n##\n## By default, the @qcode{\"closerequestfcn\"} property of a new plot figure\n## points to this function.\n## @seealso{close, delete}\n## @end deftypefn\n\nfunction closereq ()\n\n  ## Get current figure, but don't use gcf to avoid creating a new figure.\n  cf = get (0, \"currentfigure\");\n  if (isfigure (cf))\n    delete (cf);\n  endif\n\nendfunction\n\n\n## No BIST tests required.  Testing done in close.m.\n%!assert (1)\n"
  },
  {
    "path": "scripts/plot/util/colstyle.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{style}, @var{color}, @var{marker}, @var{msg}] =} colstyle (@var{style})\n## Parse the line specification @var{style} and return the line style, color,\n## and markers given.\n##\n## In the case of an error, the string @var{msg} will return the text of the\n## error.\n## @end deftypefn\n\nfunction [l, c, m, msg] = colstyle (style)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (style))\n    error (\"colstyle: STYLE must be a string\");\n  endif\n\n  try\n    opt = __pltopt__ (\"colstyle\", style);\n    l = opt.linestyle;\n    switch (opt.color)\n      case [0 0 0]\n        c = \"k\";\n      case [1 0 0]\n        c = \"r\";\n      case [0 1 0]\n        c = \"g\";\n      case [0 0 1]\n        c = \"b\";\n      case [1 1 0]\n        c = \"y\";\n      case [1 0 1]\n        c = \"m\";\n      case [0 1 1]\n        c = \"c\";\n      case [0 1 1]\n        c = \"w\";\n      otherwise\n        c = opt.color;\n    endswitch\n    m = opt.marker;\n    msg = [];\n  catch\n    l = c = m = [];\n    msg = lasterr ();\n  end_try_catch\n\nendfunction\n\n\n%!test\n%! [l, c, m, msg] = colstyle (\"r:x\");\n%! assert (isempty (msg));\n%! assert (l, \":\");\n%! assert (c, \"r\");\n%! assert (m, \"x\");\n\n%!test\n%! [l, c, m, msg] = colstyle (\".\");\n%! assert (isempty (msg));\n%! assert (l, \"none\");\n%! assert (c, []);\n%! assert (m, \".\");\n\n%!test\n%! [l, c, m, msg] = colstyle (\"~\");\n%! assert (msg, \"colstyle: unrecognized format character: '~'\");\n\n## Test input validation\n%!error <Invalid call> colstyle ()\n%!error colstyle (1, 2)\n%!error <STYLE must be a string> colstyle (1.5)\n"
  },
  {
    "path": "scripts/plot/util/copyobj.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hnew} =} copyobj (@var{horig})\n## @deftypefnx {} {@var{hnew} =} copyobj (@var{horig}, @var{hparent})\n## Construct a copy of the graphic objects associated with the handles\n## @var{horig} and return new handles @var{hnew} to the new objects.\n##\n## If a parent handle @var{hparent} (root, figure, axes, or hggroup) is\n## specified, the copied object will be created as a child of @var{hparent}.\n##\n## If @var{horig} is a vector of handles, and @var{hparent} is a scalar,\n## then each handle in the vector @var{hnew} has its @qcode{\"Parent\"} property\n## set to @var{hparent}.  Conversely, if @var{horig} is a scalar and\n## @var{hparent} a vector, then each parent object will receive a copy of\n## @var{horig}.  If @var{horig} and @var{hparent} are both vectors with the\n## same number of elements then @code{@var{hnew}(i)} will have parent\n## @code{@var{hparent}(i)}.\n## @seealso{struct2hdl, hdl2struct, findobj}\n## @end deftypefn\n\nfunction hnew = copyobj (horig, hparent = 0)\n\n  partypes = {\"root\", \"figure\", \"axes\", \"hggroup\"};\n  othertypes = {\"line\", \"patch\", \"surface\", \"image\", \"text\", \"uicontrol\"};\n  alltypes = [partypes othertypes];\n\n  if (! ishghandle (horig))\n    print_usage ();\n  elseif (! ishghandle (hparent))\n    hparent = figure (fix (hparent));\n  else\n    for hp = hparent(:)'\n      if (! any (strcmpi (get (hp, \"type\"), partypes)))\n        print_usage ();\n      endif\n    endfor\n  endif\n\n  if (numel (horig) != numel (hparent)\n      && ! (isscalar (hparent) || isscalar (horig)))\n    error (\"copyobj: size of HORIG and HPARENT must match, or one must be a scalar\");\n  endif\n\n  ## current figure and axes\n  cf = gcf ();\n  ca = get (cf, \"currentaxes\");\n\n  ## compatibility of input handles\n  for i = 1:numel (horig)\n    kididx(i) = find (strcmp (alltypes, get (horig(i), \"type\")));\n  endfor\n\n  for i = 1:numel (hparent)\n    paridx(i) = find (strcmp (alltypes, get (hparent(i), \"type\")));\n  endfor\n\n  if (kididx <= paridx)\n    error (\"copyobj: %s object can't be a child of %s\",\n           alltypes{kididx}, alltypes{paridx});\n  endif\n\n  ## loop over vector inputs\n  if (nargin == 1)\n    ## No parent specified\n    for i = numel (horig)\n      str = hdl2struct (horig(i));\n      hnew(i) = struct2hdl (str);\n    endfor\n  elseif (isscalar (hparent))\n    for i = 1:numel (horig)\n      str = hdl2struct (horig(i));\n      hnew(i) = struct2hdl (str, hparent);\n    endfor\n  elseif (isscalar (horig))\n    str = hdl2struct (horig);\n    for i = 1:numel (hparent)\n      hnew(i) = struct2hdl (str, hparent(i));\n    endfor\n  else\n    for i = 1:numel (horig)\n      str = hdl2struct (horig(i));\n      hnew(i) = struct2hdl (str, hparent(i));\n    endfor\n  endif\n\n  ## reset current figure (and eventually axes) to original\n  set (0, \"currentfigure\", cf);\n  if (ancestor (hnew(1), \"figure\") == cf && ! isempty (ca))\n    set (cf, \"currentaxes\", ca);\n  endif\n\nendfunction\n\n\n## Absurd number of drawnow() function calls in demos is due to problem\n## with FLTK backend which is not respecting the set (\"position\") call.\n\n%!demo\n%! hobj = clf;\n%! set (hobj, \"name\", \"Original\", \"numbertitle\", \"off\");\n%! hold on;\n%! x = 1:10;\n%! y = x.^2;\n%! dy = 2 * (.2 * x);\n%! y2 = (x - 3).^2;\n%! hg = errorbar (x, y, dy);\n%! set (hg, \"marker\", \"^\", \"markerfacecolor\", rand (1,3));\n%! plot (x, y2, \"ok-\");\n%! legend (\"errorbar\", \"line\");\n%! drawnow ();\n%! pos = get (hobj, \"position\");\n%! scrn = get (0, \"screensize\");\n%! set (hobj, \"position\", [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);\n%! drawnow ();\n%! hnew = copyobj (hobj, groot);\n%! drawnow ();\n%! set (hnew, \"name\", \"Copyobj\");\n%! drawnow ();\n%! set (hnew, \"position\", [scrn(3)/2, scrn(4)/2-pos(4)/2, pos(3:4)]);\n%! drawnow ();\n\n%!demo\n%! hobj = clf;\n%! set (hobj, \"name\", \"Original\", \"numbertitle\", \"off\");\n%! subplot (2,2,1);\n%!  hold on;\n%!  contourf (rand (10, 10));\n%!  colorbar ();\n%! subplot (2,2,2);\n%!  quiver (rand (10, 10), rand (10, 10));\n%! subplot (2,2,3);\n%!  colormap (jet (64));\n%!  hold on;\n%!  sombrero ();\n%!  colorbar (\"NorthOutside\", \"peer\", gca);\n%! subplot (2,2,4);\n%!  imagesc (rand (30, 30));\n%!  text (15, 15, \"Rotated text\", ...\n%!        \"HorizontAlalignment\", \"Center\", \"Rotation\", 30);\n%! drawnow ();\n%! pos = get (hobj, \"position\");\n%! scrn = get (0, \"screensize\");\n%! set (hobj, \"position\", [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);\n%! drawnow ();\n%! hnew = copyobj (hobj, groot);\n%! drawnow ();\n%! set (hnew, \"name\", \"Copyobj\");\n%! drawnow ();\n%! set (hnew, \"position\", [scrn(3)/2, scrn(4)/2-pos(4)/2, pos(3:4)]);\n%! drawnow ();\n\n%!demo\n%! hobj = clf;\n%! set (hobj, \"name\", \"Original\", \"numbertitle\", \"off\");\n%! x = 0:0.1:2*pi;\n%! y1 = sin (x);\n%! y2 = exp (x - 1);\n%! ax = plotyy (x,y1, x-1,y2, @plot, @semilogy);\n%! xlabel (\"X\");\n%! ylabel (ax(1), \"Axis 1\");\n%! ylabel (ax(2), \"Axis 2\");\n%! colororder = get (gca, \"ColorOrder\");\n%! lcolor = colororder(1,:);\n%! rcolor = colororder(2,:);\n%! text (0.5, 0.5, \"Left Axis\", ...\n%!       \"color\", lcolor, \"horizontalalignment\", \"center\", \"parent\", ax(1));\n%! text (4.5, 80, \"Right Axis\", ...\n%!       \"color\", rcolor, \"horizontalalignment\", \"center\", \"parent\", ax(2));\n%! title ({\"plotyy() example\"; \"left axis uses @plot, right axis uses @semilogy\"});\n%! drawnow ();\n%! pos = get (hobj, \"position\");\n%! scrn = get (0, \"screensize\");\n%! set (hobj, \"position\", [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);\n%! drawnow ();\n%! hnew = copyobj (hobj, groot);\n%! drawnow ();\n%! set (hnew, \"name\", \"Copyobj\");\n%! drawnow ();\n%! set (hnew, \"position\", [scrn(3)/2, scrn(4)/2-pos(4)/2, pos(3:4)]);\n%! drawnow ();\n\n%!testif HAVE_MAGICK; (have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ())));\n%! toolkit = graphics_toolkit ();\n%! graphics_toolkit (\"qt\");\n%! unwind_protect\n%!   h1 = figure (\"visible\", \"off\", \"paperposition\", [0.25, 2.5, 8.0, 6.0]);\n%!   x = 0:0.1:2*pi;\n%!   y1 = sin (x);\n%!   y2 = exp (x - 1);\n%!   ax = plotyy (x,y1, x-1,y2, @plot, @semilogy);\n%!   xlabel (\"X\");\n%!   ylabel (ax(1), \"Axis 1\");\n%!   ylabel (ax(2), \"Axis 2\");\n%!   axes (ax(1));\n%!   text (0.5, 0.5, \"Left Axis\", ...\n%!         \"color\", [0 0 1], \"horizontalalignment\", \"center\");\n%!   axes (ax(2));\n%!   text (4.5, 80, \"Right Axis\", ...\n%!         \"color\", [0 0.5 0], \"horizontalalignment\", \"center\");\n%!   s1 = hdl2struct (h1);\n%!   h2 = struct2hdl (s1);\n%!   png1 = [tempname() \".png\"];\n%!   png2 = [tempname() \".png\"];\n%!   unwind_protect\n%!     print (h1, png1);\n%!     [img1, map1, alpha1] = imread (png1);\n%!     print (h2, png2);\n%!     [img2, map2, alpha2] = imread (png2);\n%!   unwind_protect_cleanup\n%!     unlink (png1);\n%!     unlink (png2);\n%!   end_unwind_protect\n%!   assert (img1, img2);\n%!   assert (map1, map2);\n%!   assert (alpha1, alpha2);\n%! unwind_protect_cleanup\n%!   close (h1);\n%!   close (h2);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n%!test\n%! unwind_protect\n%!   tag = \"foo\";\n%!   hf = figure (\"visible\", \"off\");\n%!   hax = axes (\"tag\", tag);\n%!   hpa = patch ();\n%!   set (hpa, \"facecolor\", [.5 .5 .5], \"tag\", tag);\n%!   hax2 = copyobj (hax, hf);\n%!   assert (get (hax2, \"tag\"), tag);\n%!   hpa2 = get (hax2, \"children\");\n%!   assert (get (hpa2, \"facecolor\"), [.5 .5 .5]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/figure.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} figure\n## @deftypefnx {} {} figure @var{n}\n## @deftypefnx {} {} figure (@var{n})\n## @deftypefnx {} {} figure (@dots{}, \"@var{property}\", @var{value}, @dots{})\n## @deftypefnx {} {@var{h} =} figure (@dots{})\n## Create a new figure window for plotting.\n##\n## If no arguments are specified, a new figure with the next available number\n## is created.\n##\n## If called with an integer @var{n}, and no such numbered figure exists, then\n## a new figure with the specified number is created.  If the figure already\n## exists then it is made visible and becomes the current figure for plotting.\n##\n## Multiple property-value pairs may be specified for the figure object, but\n## they must appear in pairs.\n##\n## The optional return value @var{h} is a graphics handle to the created figure\n## object.\n##\n## Programming Note: The full list of properties is documented at\n## @ref{Figure Properties}.\n## @seealso{axes, gcf, shg, clf, close}\n## @end deftypefn\n\nfunction h = figure (varargin)\n\n  nargs = nargin;\n\n  init_new_figure = true;\n  if (nargs == 0)\n    f = NaN;\n  else\n    arg = varargin{1};\n    if (nargs == 1 && ischar (arg))\n      arg = str2double (arg);\n      if (isnan (arg))\n        arg = varargin{1};\n      endif\n    endif\n    if (isscalar (arg) && isnumeric (arg))\n      if (isfigure (arg))\n        f = arg;\n        init_new_figure = false;\n        varargin(1) = [];\n        nargs -= 1;\n      elseif (arg > 0 && arg == fix (arg))\n        f = arg;\n        varargin(1) = [];\n        nargs -= 1;\n      else\n        error (\"figure: N must be figure handle or figure number\");\n      endif\n    else\n      f = NaN;\n    endif\n  endif\n\n  ## Check to see if we already have a figure on the screen.  If we do,\n  ## then update it if it is different from the figure we are creating\n  ## or switching to.\n  cf = get (0, \"currentfigure\");   # Can't use gcf() because it calls figure()\n  if (! isempty (cf) && cf != 0)\n    if (init_new_figure || cf != f)\n      drawnow ();\n    endif\n  endif\n\n  if (init_new_figure)\n    f = __go_figure__ (f, varargin{:});\n    __add_default_menu__ (f);\n    __set_default_mouse_modes__ (f);\n  elseif (nargs > 0)\n    set (f, varargin{:});\n  endif\n\n  if (strcmp (get (f, \"handlevisibility\"), \"on\"))\n    set (0, \"currentfigure\", f);\n  endif\n\n  ## When switching to figure N, make figure visible and on top of stack,\n  ## unless visibility is explicitly switched off.\n  if (! init_new_figure)\n    vis_on = true;\n    idx = find (strcmpi (varargin(1:2:end), \"visible\"), 1) * 2 - 1;\n    if (! isempty (idx))\n      if (idx < numel (varargin) && strcmpi (varargin{idx+1}, \"off\"))\n        vis_on = false;\n      endif\n    endif\n    if (vis_on)\n      set (f, \"visible\", \"on\");\n    endif\n    __show_figure__ (f);\n  endif\n\n  if (nargout > 0)\n    h = f;\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   assert (hf, gcf);\n%!   assert (isfigure (hf));\n%!   hf2 = figure (hf, \"visible\", \"off\");\n%!   assert (hf, hf2);\n%!   assert (hf2, gcf);\n%!   assert (isfigure (hf2));\n%!   assert (get (hf2, \"visible\"), \"off\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <N must be figure handle or figure number> figure (-1)\n%!error <N must be figure handle or figure number> figure (1.5)\n"
  },
  {
    "path": "scripts/plot/util/findall.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} findall ()\n## @deftypefnx {} {@var{h} =} findall (@var{prop_name}, @var{prop_value}, @dots{})\n## @deftypefnx {} {@var{h} =} findall (@var{prop_name}, @var{prop_value}, \"-@var{logical_op}\", @var{prop_name}, @var{prop_value})\n## @deftypefnx {} {@var{h} =} findall (\"-property\", @var{prop_name})\n## @deftypefnx {} {@var{h} =} findall (\"-regexp\", @var{prop_name}, @var{pattern})\n## @deftypefnx {} {@var{h} =} findall (@var{hlist}, @dots{})\n## @deftypefnx {} {@var{h} =} findall (@var{hlist}, \"flat\", @dots{})\n## @deftypefnx {} {@var{h} =} findall (@var{hlist}, \"-depth\", @var{d}, @dots{})\n## Find graphics object, including hidden ones, with specified properties.\n##\n## The return value @var{h} is a list of handles to the found graphic objects.\n##\n## @code{findall} performs the same search as @code{findobj}, but it\n## includes hidden objects (HandleVisibility = @qcode{\"off\"}).  For full\n## documentation, @pxref{XREFfindobj,,@code{findobj}}.\n## @seealso{findobj, allchild, get, set}\n## @end deftypefn\n\nfunction h = findall (varargin)\n\n  unwind_protect\n    shh = get (0, \"showhiddenhandles\");\n    set (0, \"showhiddenhandles\", \"on\");\n    h = findobj (varargin{:});\n  unwind_protect_cleanup\n    set (0, \"showhiddenhandles\", shh);\n  end_unwind_protect\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = findall (hf);\n%!   types = {\"uitoolbar\"};\n%!   htb = uitoolbar (hf);\n%!   types = [types {\"uimenu\", \"uimenu\", \"uimenu\", ...\n%!                   \"uimenu\", \"uimenu\", \"uimenu\"}];\n%!   hm1 = uimenu (hf, \"label\", \"menu1\", \"handlevisibility\", \"off\");\n%!   uimenu (hm1, \"label\", \"menu1\");\n%!   hm2 = uimenu (hf, \"label\", \"menu2\", \"handlevisibility\", \"off\");\n%!   uimenu (hm2, \"label\", \"menu2\");\n%!   hm3 = uimenu (hf, \"label\", \"menu3\");\n%!   uimenu (hm3, \"label\", \"menu3\");\n%!   types = [types {\"uipushtool\", \"uitoggletool\", \"uipushtool\"}];\n%!   uipushtool (htb, \"handlevisibility\", \"off\");\n%!   uitoggletool (htb);\n%!   uipushtool (htb);\n%!   h = setxor (findall (hf), h);\n%!   assert (get (h, \"type\"), types(:));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/findfigs.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} findfigs ()\n## Find all visible figures that are currently off the screen and move them\n## onto the screen.\n## @seealso{allchild, figure, get, set}\n## @end deftypefn\n\nfunction findfigs ()\n\n  hfigs = allchild (0);\n  units = get (0, \"units\");\n  unwind_protect\n    set (0, \"units\", \"pixels\");\n    screensize = get (0, \"screensize\");\n  unwind_protect_cleanup\n    set (0, \"units\", units);\n  end_unwind_protect\n\n  ## give the monitor a margin so that the figure must not just\n  ## marginally be on the monitor.\n  margin = 30;\n  screensize(1:2) += margin;\n  screensize(3:4) -= margin;\n\n  hfigs = hfigs(strcmp (get (hfigs, \"visible\"), \"on\"));\n  for hf = hfigs'\n    units = get (hf, \"units\");\n    unwind_protect\n      set (hf, \"units\", \"pixels\");\n      pos = get (hf, \"position\");\n      ## Test if (in order):\n      ## The left side is outside the right side of the screen\n      ## The bottom is above the top of the screen\n      ## The right side is outside the left of the screen\n      ## the top is below the bottom of the screen\n      if (pos(1) > screensize(3)\n          || pos(2) > screensize(4)\n          || pos(1)+pos(3) < screensize(1)\n          || pos(2)+pos(4) < screensize(2))\n\n        ## the new position will be at the top left of the screen\n        ## (all moved figures will overlap).  The bottom left is chosen\n        ## instead of the top left because that allows for the unknown\n        ## amount of space for the menu bar and the title bar.\n        pos(1) = screensize(1);\n        pos(2) = screensize(2);\n        set (hf, \"position\", pos);\n      endif\n    unwind_protect_cleanup\n      set (hf, \"units\", units);\n    end_unwind_protect\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/findobj.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} findobj ()\n## @deftypefnx {} {@var{h} =} findobj (@var{prop_name}, @var{prop_value}, @dots{})\n## @deftypefnx {} {@var{h} =} findobj (@var{prop_name}, @var{prop_value}, \"-@var{logical_op}\", @var{prop_name}, @var{prop_value})\n## @deftypefnx {} {@var{h} =} findobj (\"-property\", @var{prop_name})\n## @deftypefnx {} {@var{h} =} findobj (\"-regexp\", @var{prop_name}, @var{pattern})\n## @deftypefnx {} {@var{h} =} findobj (@var{hlist}, @dots{})\n## @deftypefnx {} {@var{h} =} findobj (@var{hlist}, \"flat\", @dots{})\n## @deftypefnx {} {@var{h} =} findobj (@var{hlist}, \"-depth\", @var{d}, @dots{})\n## Find graphics objects with specified properties.\n##\n## When called without arguments, return all graphic objects beginning with the\n## root object (0) and including all of its descendants.\n##\n## The simplest form for narrowing the results is\n##\n## @example\n## findobj (@var{prop_name}, @var{prop_value})\n## @end example\n##\n## @noindent\n## which returns the handles of all objects which have a property named\n## @var{prop_name} that has the value @var{prop_value}.  If multiple\n## property/value pairs are specified then only objects meeting all of the\n## conditions (equivalent to @code{-and}) are returned.\n##\n## The search can be limited to a particular set of objects and their\n## descendants, by passing a handle or set of handles @var{hlist} as the first\n## argument.\n##\n## The depth of the object hierarchy to search can be limited with the\n## @qcode{\"-depth\"} argument.  An example of searching through only three\n## generations of children is:\n##\n## @example\n## findobj (@var{hlist}, \"-depth\", 3, @var{prop_name}, @var{prop_value})\n## @end example\n##\n## Specifying a depth @var{d} of 0 limits the search to the set of objects\n## passed in @var{hlist}.  A depth of 0 is also equivalent to the\n## @qcode{\"flat\"} argument.  The default depth value is @code{Inf} which\n## includes all descendants.\n##\n## A specified logical operator may be used between @var{prop_name},\n## @var{prop_value} pairs.  The supported logical operators are:\n## @qcode{\"-and\"}, @qcode{\"-or\"}, @qcode{\"-xor\"}, @qcode{\"-not\"}.  Example code\n## to locate all figure and axes objects is\n##\n## @example\n## findobj (\"type\", \"figure\", \"-or\", \"type\", \"axes\")\n## @end example\n##\n## Objects may also be matched by comparing a regular expression to the\n## property values, where property values that match\n## @code{regexp (@var{prop_value}, @var{pattern})} are returned.\n##\n## Finally, objects which have a property name can be found with the\n## @qcode{\"-property\"} option.  For example, code to locate objects with a\n## @qcode{\"meshstyle\"} property is\n##\n## @example\n## findobj (\"-property\", \"meshstyle\")\n## @end example\n##\n## Implementation Note: The search only includes objects with visible handles\n## (@w{HandleVisibility} = @qcode{\"on\"}).  @xref{XREFfindall,,findall}, to\n## search for all objects including hidden ones.\n## @seealso{findall, allchild, get, set}\n## @end deftypefn\n\nfunction h = findobj (varargin)\n\n  depth = NaN;\n  if (nargin == 0)\n    handles = 0;\n    n1 = 0;\n  else\n    if (isempty (varargin{1}))\n      ## Return [](0x1) for compatibility.\n      h = zeros (0, 1);\n      return;\n    endif\n    arg1 = varargin{1};\n    if (isnumeric (arg1))\n      if (! all (ishghandle (arg1)))\n        error (\"findobj: invalid graphics handles in input HLIST\");\n      endif\n      handles = arg1;\n      n1 = 2;\n    else\n      handles = 0;\n      n1 = 1;\n    endif\n    if (n1 <= nargin)\n      if (! ischar (varargin{n1}))\n        error (\"findobj: properties and options must be strings\");\n      endif\n      if (strcmpi (varargin{n1}, \"flat\"))\n        depth = 0;\n        n1 += 1;\n      endif\n    endif\n  endif\n\n  if (n1 <= nargin && nargin > 0)\n    args = varargin(n1 : nargin);\n  else\n    args = {};\n  endif\n\n  regularexpression = [];\n  property          = [];\n  logicaloperator   = {};\n  extranegation     = [];\n  pname             = {};\n  pvalue            = {};\n  np = 1;\n  na = 1;\n  operatorprecedence = {\"-not\", \"-and\", \"-or\", \"-xor\"};\n\n  while (na <= numel (args))\n    regularexpression(np) = 0;\n    property(np) = 0;\n    if (numel (extranegation) < np)\n      extranegation(np) = false;\n    endif\n    logicaloperator{np} = \"and\";\n    if (ischar (args{na}))\n      if (strcmpi (args{na}, \"-property\"))\n        if (na + 1 <= numel (args))\n          na += 1;\n          property(np) = 1;\n          pname{np} = args{na};\n          na += 1;\n          pvalue{np} = [];\n          np += 1;\n        else\n          error (\"findobj: inconsistent number of arguments\");\n        endif\n      elseif (strcmpi (args{na}, \"-regexp\"))\n        if (na + 2 <= numel (args))\n          regularexpression(np) = 1;\n          na += 1;\n          pname{np} = args{na};\n          na += 1;\n          pvalue{np} = args{na};\n          na += 1;\n          np += 1;\n        else\n          error (\"findobj: inconsistent number of arguments\");\n        endif\n      elseif (strcmpi (args{na}, \"-depth\"))\n        if (na + 1 <= numel (args))\n          na += 1;\n          depth = args{na};\n          na += 1;\n        else\n          error (\"findobj: inconsistent number of arguments\");\n        endif\n      elseif (! strcmp (args{na}(1), \"-\"))\n        ## Parameter/value pairs.\n        if (na + 1 <= numel (args))\n          pname{np} = args{na};\n          na += 1;\n          pvalue{np} = args{na};\n          na += 1;\n          if (na <= numel (args))\n            if (ischar (args{na}))\n              if (any (strcmpi (args{na}, operatorprecedence)))\n                logicaloperator{np} = args{na}(2:end);\n                na += 1;\n              endif\n            else\n              error (\"findobj: properties and options must be strings\");\n            endif\n          else\n            logicaloperator{np} = \"and\";\n          endif\n          np += 1;\n        else\n          error (\"findobj: inconsistent number of arguments\");\n        endif\n      else\n        if (strcmpi (args{na}, \"-not\"))\n          extranegation(np) = true;\n        endif\n        na += 1;\n      endif\n    else\n      error (\"findobj: properties and options must be strings\");\n    endif\n  endwhile\n\n  numpairs = np - 1;\n  if (! isempty (logicaloperator))\n    logicaloperator = circshift (logicaloperator, 1);\n  endif\n\n  ## Load all objects which qualify for being searched.\n  idepth = 0;\n  h = handles(:);\n  while (numel (handles) && ! (idepth >= depth))\n    children = [];\n    for n = 1 : numel (handles)\n      children = [children; get(handles(n), \"children\")];\n    endfor\n    handles = children;\n    h = [h; children];\n    idepth += 1;\n  endwhile\n\n  if (numpairs > 0)\n    match = true (numel (h), numpairs);\n    for nh = 1 : numel (h)\n      p = __get__ (h(nh));\n      for np = 1 : numpairs\n        fields = fieldnames (p);\n        fieldindex = find (strcmpi (fields, pname{np}), 1);\n        if (numel (fieldindex))\n          pname{np} = fields{fieldindex};\n          if (property(np))\n            match(nh,np) = true;\n          else\n            if (regularexpression(np))\n              found = regexp (p.(pname{np}), pvalue{np}, \"once\");\n              if (isempty (found))\n                match(nh,np) = false;\n              else\n                match(nh,np) = true;\n              endif\n            elseif (numel (p.(pname{np})) == numel (pvalue{np}))\n              if (ischar (p.(pname{np})))\n                match(nh,np) = strcmpi (pvalue{np}, p.(pname{np}));\n              elseif (isnumeric (pvalue{np}) && isnumeric (p.(pname{np})))\n                match(nh,np) = all ((pvalue{np} == p.(pname{np}))(:));\n              else\n                match(nh,np) = isequal (pvalue{np}, p.(pname{np}));\n              endif\n            else\n              match(nh,np) = false;\n            endif\n          endif\n        else\n          match(nh,np) = false;\n        endif\n        if (extranegation(np))\n          match(nh,np) = ! match(nh,np);\n        endif\n      endfor\n    endfor\n\n    if (numpairs > 1)\n      for no = 1 : numel (operatorprecedence)\n        pairs = find (strcmp (logicaloperator(2:end), ...\n                              operatorprecedence{no}(2:end)));\n        for np = sort (pairs, \"descend\")\n          if (no == 1)\n            match(:,np+1) = ! match(:,np+1);\n            logicaloperator(np+1) = {\"and\"};\n          else\n            match(:,np) = feval (logicaloperator{np+1}, match(:,np), ...\n                                 match(:,np+1));\n            logicaloperator(np+1) = [];\n            match(:,np+1) = [];\n            numpairs -= 1;\n          endif\n          if (numpairs < 2)\n            break;\n          endif\n        endfor\n        if (numpairs < 2)\n          break;\n        endif\n      endfor\n    endif\n  else\n    match = true (numel (h), 1);\n  endif\n\n  if (! any (match))\n    h = [];\n  else\n    h = h(match);\n    h = h(:);\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = findobj (gca (), \"-property\", \"foo\");\n%!   assert (isempty (h));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = plot (1:10, \"b\");\n%!   set (h, \"tag\", \"foobar\");\n%!   g = findobj (gcf (), \"tag\", \"foobar\", \"type\", \"line\", \"color\", [0 0 1]);\n%!   assert (g, h);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   l = line ();\n%!   obj = findobj (hf, \"type\", \"line\");\n%!   assert (l, obj);\n%!   assert (gca, findobj (hf, \"type\", \"axes\"));\n%!   assert (hf, findobj (hf, \"type\", \"figure\"));\n%!   assert (isempty (findobj (hf, \"type\", \"xyzxyz\")));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   subplot (2,2,1);\n%!    imagesc (rand (10));\n%!   subplot (2,2,2);\n%!    surf (peaks);\n%!   subplot (2,2,3);\n%!    contour (peaks);\n%!   subplot (2,2,4);\n%!    plot (peaks);\n%!   h1 = findobj (gcf (), \"-regexp\", \"Type\", \"image|surface|hggroup\");\n%!   h2 = findobj (gcf (), \"Type\", \"image\",\n%!                  \"-or\", \"Type\", \"surface\",\n%!                  \"-or\", \"Type\", \"hggroup\");\n%!   assert (h2, h1);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h1 = subplot (2,2,1);\n%!   h2 = subplot (2,2,2);\n%!   h3 = subplot (2,2,3, \"userdata\", struct (\"foo\", \"bar\"));\n%!   h4 = subplot (2,2,4);\n%!   h = findobj (hf, \"userdata\", struct (\"foo\", \"bar\"));\n%!   assert (h, h3);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h1 = subplot (2,2,1, \"tag\", \"1\");\n%!   h2 = subplot (2,2,2, \"tag\", \"2\");\n%!   h3 = subplot (2,2,3, \"tag\", \"3\");\n%!   h4 = subplot (2,2,4, \"tag\", \"4\");\n%!   h = findobj (hf, \"type\", \"axes\", \"-not\", \"tag\", \"1\");\n%!   assert (h, [h4; h3; h2]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h1 = subplot (2, 2, 1);\n%!   set (h1, \"userdata\", struct (\"column\", 1, \"row\", 1));\n%!   h2 = subplot (2, 2, 2);\n%!   set (h2, \"userdata\", struct (\"column\", 2, \"row\", 1));\n%!   h3 = subplot (2, 2, 3);\n%!   set (h3, \"userdata\", struct (\"column\", 1, \"row\", 2));\n%!   h4 = subplot (2, 2, 4);\n%!   set (h4, \"userdata\", struct (\"column\", 2, \"row\", 2));\n%!   h = findobj (hf, \"type\", \"axes\",\n%!                \"-not\", \"userdata\", struct (\"column\", 1, \"row\", 1));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n%! assert (h, [h4; h3; h2]);\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ha = axes ();\n%!   plot (1:10);\n%!   h = findobj (hf, \"type\", \"figure\",\n%!                \"-or\", \"parent\", hf,\n%!                \"-and\", \"type\", \"axes\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n%! assert (h, [hf; ha]);\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   set (hf, \"tag\", \"foo\");\n%!   h1 = subplot (2,2,1, \"tag\", \"foo\");\n%!   h2 = subplot (2,2,2, \"tag\", \"bar\");\n%!   h3 = subplot (2,2,3, \"tag\", \"foo\");\n%!   h4 = subplot (2,2,4, \"tag\", \"bar\");\n%!   h = findobj (hf, \"type\", \"axes\", \"-xor\", \"tag\", \"foo\");\n%!   assert (h, [hf; h4; h2]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax1 = subplot (2,1,1);\n%!    hl1 = plot (rand (10,1));\n%!   hax2 = subplot (2,1,2);\n%!    hl2 = plot (rand (10,1));\n%!   hobj = findobj (hf);\n%!   assert (hobj, [hf; hax2; hax1; hl2; hl1]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   ind = findobj (0, \"tag\", []);\n%!   assert (ind, []);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (3, \"visible\", \"off\");\n%! unwind_protect\n%!   ind = findobj (0, \"tag\", \"\");\n%!   assert (ind, [0; 3]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\", \"tag\", \"A\");\n%! unwind_protect\n%!   ind = findobj (0, \"tag\", 65);\n%!   assert (ind, []);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test input validation\n%!error <invalid graphics handles in input HLIST> findobj ([0 1 10], \"flat\")\n%!error <properties and options must be strings> findobj ({0}, \"flat\")\n"
  },
  {
    "path": "scripts/plot/util/gca.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} gca ()\n## Return a handle to the current axes object.\n##\n## The current axes is the default target for graphics output.  In the case\n## of a figure with multiple axes, @code{gca} returns the last created axes\n## or the last axes that was clicked on with the mouse.\n##\n## If no current axes object exists, create one and return its handle.  The\n## handle may then be used to examine or set properties of the axes.  For\n## example,\n##\n## @example\n## @group\n## ax = gca ();\n## set (ax, \"position\", [0.5, 0.5, 0.5, 0.5]);\n## @end group\n## @end example\n##\n## @noindent\n## creates an empty axes object and then changes its location and size in the\n## figure window.\n##\n## Note: To find the current axes without creating a new axes object if it\n## does not exist, query the @qcode{\"CurrentAxes\"} property of a figure.\n##\n## @example\n## get (gcf, \"currentaxes\");\n## @end example\n## @seealso{gcf, gco, gcbf, gcbo, get, set}\n## @end deftypefn\n\nfunction h = gca ()\n\n  h = get (gcf (), \"currentaxes\");\n  if (isempty (h))\n    h = axes ();\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! ax = axes ();\n%! unwind_protect\n%!   assert (gca, ax);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/gcbf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{fig} =} gcbf ()\n## Return a handle to the figure containing the object whose callback is\n## currently executing.\n##\n## If no callback is executing, this function returns the empty matrix.  The\n## handle returned by this function is the same as the second output argument\n## of @code{gcbo}.\n##\n## @seealso{gcbo, gcf, gco, gca, get, set}\n## @end deftypefn\n\nfunction fig = gcbf ()\n\n  [~, fig] = gcbo ();\n\nendfunction\n\n\n%!assert (isempty (gcbf))\n"
  },
  {
    "path": "scripts/plot/util/gcbo.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} gcbo ()\n## @deftypefnx {} {[@var{h}, @var{fig}] =} gcbo ()\n## Return a handle to the object whose callback is currently executing.\n##\n## If no callback is executing, this function returns the empty matrix.  This\n## handle is obtained from the root object property @qcode{\"CallbackObject\"}.\n##\n## When called with a second output argument, return the handle of the figure\n## containing the object whose callback is currently executing.  If no callback\n## is executing the second output is also set to the empty matrix.\n##\n## @seealso{gcbf, gco, gca, gcf, get, set}\n## @end deftypefn\n\nfunction [h, fig] = gcbo ()\n\n  h = get (0, \"callbackobject\");\n  fig = [];\n\n  if (! isempty (h) && nargout > 1)\n    fig = ancestor (h, \"figure\");\n  endif\n\nendfunction\n\n\n%!test\n%! assert (isempty (gcbo));\n"
  },
  {
    "path": "scripts/plot/util/gcf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} gcf ()\n## Return a handle to the current figure.\n##\n## The current figure is the default target for graphics output.  If multiple\n## figures exist, @code{gcf} returns the last created figure or the last figure\n## that was clicked on with the mouse.\n##\n## If a current figure does not exist, create one and return its handle.  The\n## handle may then be used to examine or set properties of the figure.  For\n## example,\n##\n## @example\n## @group\n## fplot (@@sin, [-10, 10]);\n## fig = gcf ();\n## set (fig, \"numbertitle\", \"off\", \"name\", \"sin plot\")\n## @end group\n## @end example\n##\n## @noindent\n## plots a sine wave, finds the handle of the current figure, and then\n## renames the figure window to describe the contents.\n##\n## Note: To find the current figure without creating a new one if it does not\n## exist, query the @qcode{\"CurrentFigure\"} property of the root graphics\n## object.\n##\n## @example\n## get (groot, \"currentfigure\");\n## @end example\n##\n## @seealso{gca, gco, gcbf, gcbo, get, set}\n## @end deftypefn\n\nfunction h = gcf ()\n\n  h = get (0, \"currentfigure\");\n  if (isempty (h) || h == 0)\n    ## We only have a root object, so create a new figure object\n    ## and make it the current figure.\n    h = figure ();\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   assert (gcf, hf);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/gco.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} gco ()\n## @deftypefnx {} {@var{h} =} gco (@var{hfig})\n## Return a handle to the current object of the current figure, or a handle\n## to the current object of the figure with handle @var{hfig}.\n##\n## The current object of a figure is the object that was last clicked on.  It\n## is stored in the @qcode{\"CurrentObject\"} property of the target figure.\n##\n## If the last mouse click did not occur on any child object of the figure,\n## then the current object is the figure itself.\n##\n## If no mouse click occurred in the target figure, this function returns an\n## empty matrix.\n##\n## Programming Note: The value returned by this function is not necessarily the\n## same as the one returned by @code{gcbo} during callback execution.  An\n## executing callback can be interrupted by another callback and the current\n## object may be changed.\n##\n## @seealso{gcbo, gca, gcf, gcbf, get, set}\n## @end deftypefn\n\nfunction h = gco (hfig)\n\n  if (nargin == 1)\n    if (! isfigure (hfig))\n      error (\"gco: HFIG must be a graphics handle to a figure object\");\n    endif\n  else\n    hfig = get (0, \"currentfigure\");\n  endif\n\n  h = get (hfig, \"currentobject\");\n\nendfunction\n\n\n## Test input invalidation\n%!error <HFIG must be a graphics handle> gco (-1)\n"
  },
  {
    "path": "scripts/plot/util/ginput.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{x}, @var{y}, @var{buttons}] =} ginput (@var{n})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{buttons}] =} ginput ()\n## Return the position and type of mouse button clicks and/or key strokes\n## in the current figure window.\n##\n## If @var{n} is defined, then capture @var{n} events before returning.\n## When @var{n} is not defined @code{ginput} will loop until the return key\n## @key{RET} is pressed.\n##\n## The return values @var{x}, @var{y} are the coordinates where the mouse\n## was clicked in the units of the current axes.  The return value @var{button}\n## is 1, 2, or 3 for the left, middle, or right button.  If a key is pressed\n## the ASCII value is returned in @var{button}.\n##\n## Implementation Note: @code{ginput} is intenteded for 2-D plots.  For 3-D\n## plots see the @var{currentpoint} property of the current axes which can be\n## transformed with knowledge of the current @code{view} into data units.\n## @seealso{gtext, waitforbuttonpress}\n## @end deftypefn\n\nfunction varargout = ginput (n = -1)\n\n  ## Create an axis, if necessary.\n  fig = gcf ();\n  ax = gca ();\n  drawnow ();\n\n  if (isempty (ax))\n    error (\"ginput: must have at least one axes\");\n  endif\n\n  toolkit = get (fig, \"__graphics_toolkit__\");\n  toolkit_fcn = sprintf (\"__%s_ginput__\", toolkit);\n\n  if (exist (toolkit_fcn))\n    varargout = cell (1, nargout);\n    if (nargin == 0)\n      [varargout{:}] = feval (toolkit_fcn, fig);\n    else\n      [varargout{:}] = feval (toolkit_fcn, fig, n);\n    endif\n    return;\n  endif\n\n  x = y = button = [];\n  ginput_accumulator (0, 0, 0, 0);  # initialize accumulator\n\n  orig_windowbuttondownfcn = get (fig, \"windowbuttondownfcn\");\n  orig_keypressfcn = get (fig, \"keypressfcn\");\n  orig_closerequestfcn = get (fig, \"closerequestfcn\");\n  orig_mousemode = get (fig, \"__mouse_mode__\");\n  orig_pointer = get (fig, \"pointer\");\n\n  unwind_protect\n\n    set (fig, \"windowbuttondownfcn\", @ginput_windowbuttondownfcn, ...\n         \"keypressfcn\", @ginput_keypressfcn, ...\n         \"closerequestfcn\", {@ginput_closerequestfcn, orig_closerequestfcn}, ...\n         \"pointer\", \"crosshair\", \"__mouse_mode__\", \"none\");\n\n    do\n      if (strcmp (toolkit, \"fltk\"))\n        __fltk_check__ ();\n      endif\n\n      ## Release CPU.\n      pause (0.01);\n\n      [x, y, n0, button] = ginput_accumulator (-1, 0, 0, 0);\n    until ((n > -1 && n0 >= n) || n0 < 0)\n\n    if (n0 > n)\n      ## More clicks than requested due to double-click or too fast clicking\n      x = x(1:n);\n      y = y(1:n);\n      button = button(1:n);\n    endif\n\n  unwind_protect_cleanup\n    if (isfigure (fig))\n      ## Only execute if window still exists\n      set (fig, \"windowbuttondownfcn\", orig_windowbuttondownfcn, ...\n           \"keypressfcn\", orig_keypressfcn, ...\n           \"closerequestfcn\", orig_closerequestfcn, ...\n           \"pointer\", orig_pointer, \"__mouse_mode__\", orig_mousemode);\n    endif\n  end_unwind_protect\n\n  varargout = {x, y, button};\n\nendfunction\n\nfunction [rx, ry, rn, rbutton] = ginput_accumulator (mode, xn, yn, btn)\n  persistent x y n button;\n\n  if (mode == 0)\n    ## Initialize.\n    x = y = button = [];\n    n = 0;\n  elseif (mode == 1)\n    ## Append mouse button or key press.\n    x = [x; xn];\n    y = [y; yn];\n    button = [button; btn];\n    n += 1;\n  elseif (mode == 2)\n    ## The end due to Enter.\n    n = -1;\n  endif\n\n  rx = x;\n  ry = y;\n  rn = n;\n  rbutton = button;\n\nendfunction\n\nfunction ginput_windowbuttondownfcn (~, button)\n  point = get (gca (), \"currentpoint\");\n  ginput_accumulator (1, point(1,1), point(1,2), button);\nendfunction\n\nfunction ginput_keypressfcn (~, evt)\n\n  point = get (gca (), \"currentpoint\");\n  if (strcmp (evt.Key, \"return\") || strcmp (evt.Key, \"enter\"))\n    ## <Return> or <Enter> on numeric keypad stops ginput.\n    ginput_accumulator (2, NaN, NaN, NaN);\n  else\n    character = evt.Character;\n    if (! isempty (character))\n      ginput_accumulator (1, point(1,1), point(1,2), uint8 (character(1)));\n    endif\n  endif\n\nendfunction\n\nfunction ginput_closerequestfcn (hfig, ~, orig_closerequestfcn)\n  ginput_accumulator (2, NaN, NaN, NaN);  # Stop ginput\n  feval (orig_closerequestfcn);           # Close window with original fcn\nendfunction\n\n\n## Remove from test statistics.  No real tests possible.\n%!test\n%! assert (1);\n"
  },
  {
    "path": "scripts/plot/util/gnuplot_binary.in.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{prog}, @var{args}] =} gnuplot_binary ()\n## @deftypefnx {} {[@var{old_prog}, @var{old_args}] =} gnuplot_binary (@var{new_prog})\n## @deftypefnx {} {[@var{old_prog}, @var{old_args}] =} gnuplot_binary (@var{new_prog}, @var{arg1}, @dots{})\n## Query or set the name of the program invoked by the plot command when the\n## graphics toolkit is set to @qcode{\"gnuplot\"}.\n##\n## Additional arguments to pass to the external plotting program may also be\n## given.  The default value is @qcode{\"gnuplot\"} with no additional arguments.\n## @xref{Installing Octave}.\n## @seealso{graphics_toolkit}\n## @end deftypefn\n\nfunction [prog, args] = gnuplot_binary (new_prog, varargin)\n\n  mlock ();\n  persistent gp_binary = %OCTAVE_CONF_GNUPLOT%;\n  persistent gp_args = {};\n\n  if (nargout > 0 || nargin == 0)\n    prog = gp_binary;\n    args = gp_args;\n  endif\n\n  if (nargin > 0)\n    if (! ischar (new_prog) || isempty (new_prog))\n      error (\"gnuplot_binary: NEW_PROG must be a non-empty string\");\n    endif\n    gp_binary = new_prog;\n    gp_args = {};\n  endif\n\n  if (nargin > 1)\n    if (! iscellstr (varargin))\n      error (\"gnuplot_binary: arguments must be character strings\");\n    endif\n    gp_args = varargin;\n  endif\n\nendfunction\n\n\n%!test\n%! [orig_val, orig_args] = gnuplot_binary ();\n%! unwind_protect\n%!   [old_val, old_args] = gnuplot_binary (\"__foobar__\", \"-opt1\");\n%!   assert (orig_val, old_val);\n%!   assert (orig_args, old_args);\n%!   assert (gnuplot_binary (), \"__foobar__\");\n%!   [~, new_args] = gnuplot_binary ();\n%!   assert (new_args, {\"-opt1\"});\n%! unwind_protect_cleanup\n%!   gnuplot_binary (orig_val, orig_args{:});\n%! end_unwind_protect\n%! assert (gnuplot_binary (), orig_val);\n"
  },
  {
    "path": "scripts/plot/util/graphics_toolkit.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tkit} =} graphics_toolkit ()\n## @deftypefnx {} {@var{tkit} =} graphics_toolkit (@var{hlist})\n## @deftypefnx {} {} graphics_toolkit (@var{name})\n## @deftypefnx {} {} graphics_toolkit (@var{hlist}, @var{name})\n## Query or set the default graphics toolkit which is assigned to new figures.\n##\n## With no inputs, return the current default graphics toolkit.  If the input\n## is a list of figure graphic handles, @var{hlist}, then return the name\n## of the graphics toolkit in use for each figure.\n##\n## When called with a single input @var{name} set the default graphics toolkit\n## to @var{name}.  If the toolkit is not already loaded, it is initialized by\n## calling the function @code{__init_@var{name}__}.  If the first input\n## is a list of figure handles, @var{hlist}, then the graphics toolkit is set\n## to @var{name} for these figures only.\n##\n## @seealso{available_graphics_toolkits}\n## @end deftypefn\n\nfunction tkit = graphics_toolkit (name, hlist = [])\n\n  if (nargout > 0 || nargin == 0)\n    tkit = get (0, \"defaultfigure__graphics_toolkit__\");\n    ## Handle case where graphics_toolkit has been called before any plotting\n    if (isempty (tkit))\n      toolkits = available_graphics_toolkits ();\n      if (any (strcmp (\"qt\", toolkits)))\n        tkit = \"qt\";\n      elseif (any (strcmp (\"fltk\", toolkits)))\n        tkit = \"fltk\";\n      elseif (! isempty (toolkits))\n        tkit = toolkits{1};\n      endif\n    endif\n  endif\n\n  if (nargin == 0)\n    return;\n  elseif (nargin == 1)\n    if (all (isfigure (name)))\n      hlist = name;\n      tkit = get (hlist, \"__graphics_toolkit__\");\n      return;\n    elseif (! ischar (name))\n      error (\"graphics_toolkit: invalid graphics toolkit NAME\");\n    endif\n  elseif (nargin == 2)\n    ## Swap input arguments\n    [hlist, name] = deal (name, hlist);\n    if (! all (isfigure (hlist)))\n      error (\"graphics_toolkit: invalid figure handle list HLIST\");\n    elseif (! ischar (name))\n      error (\"graphics_toolkit: invalid graphics toolkit NAME\");\n    endif\n  endif\n\n  if (! any (strcmp (available_graphics_toolkits (), name)))\n    error (\"graphics_toolkit: %s toolkit is not available\", name);\n  endif\n\n  if (! any (strcmp (loaded_graphics_toolkits (), name)))\n    if (strcmp (name, \"gnuplot\"))\n      valid_version = __gnuplot_has_feature__ (\"minimum_version\");\n      if (valid_version != 1)\n        error (\"graphics_toolkit: gnuplot version too old\");\n      endif\n    endif\n    feval ([\"__init_\", name, \"__\"]);\n    if (! any (strcmp (loaded_graphics_toolkits (), name)))\n      error (\"graphics_toolkit: %s toolkit was not correctly loaded\", name);\n    endif\n  endif\n\n  if (isempty (hlist))\n    set (0, \"defaultfigure__graphics_toolkit__\", name);\n  else\n    set (hlist, \"__graphics_toolkit__\", name);\n  endif\n\nendfunction\n\n\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! unwind_protect\n%!   hf = figure (\"visible\", \"off\");\n%!   toolkit = graphics_toolkit ();\n%!   assert (get (0, \"defaultfigure__graphics_toolkit__\"), toolkit);\n%!   graphics_toolkit (hf, \"qt\");\n%!   assert (graphics_toolkit (hf), \"qt\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp (\"gnuplot\", available_graphics_toolkits ())) && any (strcmp (\"qt\", available_graphics_toolkits ()))\n%! old_toolkit = graphics_toolkit ();\n%! switch (old_toolkit)\n%!   case {\"gnuplot\"}\n%!     new_toolkit = \"qt\";\n%!   otherwise\n%!     new_toolkit = \"gnuplot\";\n%! endswitch\n%! assert (graphics_toolkit (new_toolkit), old_toolkit);\n%! assert (graphics_toolkit (old_toolkit), new_toolkit);\n"
  },
  {
    "path": "scripts/plot/util/groot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} groot ()\n## Return a handle to the root graphics object.\n##\n## The root graphics object is the ultimate parent of all graphics objects.\n##\n## In addition, the root object contains information about the graphics\n## system as a whole such as the @code{ScreenSize}.  Use\n## @w{@code{get (groot)}}@ to find out what information is available.\n##\n## Defaults for the graphic system as a whole are specified by setting\n## properties of the root graphics object that begin with @qcode{\"Default\"}.\n## For example, to set the default font for all text objects to FreeSans use\n##\n## @example\n## set (groot, \"DefaultTextFontName\", \"FreeSans\")\n## @end example\n##\n## Default properties can be deleted by using @code{set} with the special\n## property value of @qcode{\"remove\"}.  To undo the default font assignment\n## above use\n##\n## @example\n## set (groot, \"DefaultTextFontName\", \"remove\")\n## @end example\n##\n## Programming Note: The root graphics object is identified by the special\n## handle value of 0.  At some point this unique value may change, but code can\n## be made resistant to future changes by using @code{groot} which is\n## guaranteed to always return the root graphics object.\n## @seealso{gcf, gca, get, set}\n## @end deftypefn\n\nfunction h = groot ()\n\n  h = 0;\n\nendfunction\n\n\n%!assert (groot (), 0)\n"
  },
  {
    "path": "scripts/plot/util/gui_mainfcn.m",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This filename is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n## your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the filename COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{@dots{}}] =} gui_mainfcn (@var{gui_state}, @dots{})\n## Compatibility function for figures created with @sc{matlab}'s Guide.\n##\n## This function is undocumented and users should not use it in new code.\n##\n## @seealso{openfig, hgload, struct2hdl}\n## @end deftypefn\n\nfunction varargout = gui_mainfcn (gui_state, varargin)\n\n  if (nargin == 1 || isempty (gui_state.gui_Callback))\n    ## Open figure\n    copies = ifelse (gui_state.gui_Singleton, \"reuse\", \"new\");\n    if (isempty (gui_state.gui_LayoutFcn))\n      filename = file_in_loadpath ([gui_state.gui_Name \".fig\"]);\n      H = openfig (filename, copies, \"invisible\");\n    else\n      H = feval (gui_LayoutFcn, copies);\n    endif\n\n    ## Set figure properties from input\n    for i = 1:2:numel (varargin)\n      try\n        set (H, varargin{i}, varargin{i+1});\n      catch\n        break;\n      end_try_catch\n    endfor\n\n    ## Store graphics handles in guidata\n    handles = guihandles (H);\n    guidata (H, handles);\n\n    ## Execute opening function\n    ## FIXME: According to comments in auto-generated examples, the opening\n    ## function may block (with \"uiwait\").  But also the opening function should\n    ## execute just before the figure is made visible.  How is this supposed to\n    ## work?\n    feval (gui_state.gui_OpeningFcn, H, [], handles, varargin{:});\n    set (H, \"visible\", \"on\");\n    handles = guidata (H);\n\n    ## Execute output function\n    varargout{1} = feval (gui_state.gui_OutputFcn, H, [], handles);\n  else\n    [varargout{1:nargout}] = feval (gui_state.gui_Callback, varargin{2:end});\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/hdl2struct.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{s} =} hdl2struct (@var{h})\n## Return a structure, @var{s}, whose fields describe the properties\n## of the object, and its children, associated with the handle, @var{h}.\n##\n## The fields of the structure @var{s} are @qcode{\"type\"}, @qcode{\"handle\"},\n## @qcode{\"properties\"}, @qcode{\"children\"}, and @qcode{\"special\"}.\n## @seealso{struct2hdl, hgsave, findobj}\n## @end deftypefn\n\nfunction s = hdl2struct (h)\n\n  if (nargin < 1 || ! ishghandle (h))\n    print_usage ();\n  endif\n\n  hiddenh = get (0, \"showhiddenhandles\");\n  unwind_protect\n    set (0, \"showhiddenhandles\", \"off\");\n\n    ## main object\n    s.handle = h;\n    s.type = get (h, \"type\");\n    s.properties = getprops (h);\n    s.children = [];\n    s.special = [];\n\n    ## Process, in reverse order, all children except for\n    ## legends, colorbars, uimenu, and hggroup children.\n    ii = 0;\n    allkids = get (h, \"children\");\n    if (! strcmp (s.type, \"hggroup\"))\n      hnot = findobj (h, \"-depth\", 1, \"tag\", \"legend\", \"-or\", \"tag\", \"colorbar\",\n                                      \"-or\", \"type\", \"uimenu\");\n      kids = allkids(! ismember (allkids, hnot));\n      if (strcmp (s.type, \"axes\"))\n        ## Check for polar plots with special \"polar_grid\" object\n        ## FIXME: A hack to fix bug #62093.\n        kids = [kids; findall(h, \"tag\", \"polar_grid\")];\n\n        ## Add legend markers which are normally hidden\n        if (strcmp (s.properties.tag, \"legend\"))\n          kids = [kids; findall(h, \"-depth\", 1, \"type\", \"line\", \"-property\", \"markertruesize\")];\n        endif\n      endif\n\n      nkids = length (kids);\n      for i = nkids:-1:1\n        s.children(++ii) = hdl2struct (kids(i));\n      endfor\n    endif\n\n    ## Add non \"children\" children objects (title, xlabel, ...) and\n    ## hggroup children and tag them in \"special\".\n    if (strcmp (s.type, \"hggroup\"))\n      special = allkids;\n    else\n      special = [];\n    endif\n    special = [special getspecial(h)];\n    nsp = length (special);\n    while (nsp)\n      ii += 1;\n      s.children(ii) = hdl2struct (special(nsp));\n      s.special(nsp) = ii;\n      nsp -= 1;\n    endwhile\n\n    if (strcmp (s.type, \"axes\") ...\n        && ! any (strcmp (get (h, \"tag\"), {'colorbar', 'legend'})))\n      ## Look for legends and colorbars among axes brothers and add them\n      ## to the children list.\n      try\n        lg = get (h, \"__legend_handle__\");\n      catch\n        lg = [];\n      end_try_catch\n      nlg = length (lg);\n      if (nlg == 1)\n        ii += 1;\n        s.children(ii) = hdl2struct (lg);\n      elseif (nlg > 1)\n        ## FIXME: Unreachable code now.  Delete?\n        error (\"hdl2struct: more than one legend found\");\n      endif\n\n      try\n        cb = get (h, \"__colorbar_handle__\");\n      catch\n        cb = [];\n      end_try_catch\n      ncb = length (cb);\n      if (ncb == 1)\n        ii += 1;\n        s.children(ii) = hdl2struct (cb);\n      elseif (ncb > 1)\n        ## FIXME: Unreachable code now.  Delete?\n        error (\"hdl2struct: more than one colorbar found\");\n      endif\n    endif\n\n  unwind_protect_cleanup\n    set (0, \"showhiddenhandles\", hiddenh);\n  end_unwind_protect\n\nendfunction\n\nfunction hlist = getspecial (h)\n\n  ## return handles to special children\n  hlist = [];\n\n  regkids = get (h, \"children\");\n  ## inline version of allchild() for performance\n  set (0, \"showhiddenhandles\", \"on\");\n  allkids = get (h, \"children\");\n  set (0, \"showhiddenhandles\", \"off\");\n  speckids = ! ismember (allkids, regkids);\n  hlist = allkids(speckids);\n  hlist = hlist(:).';  # return row vector\n\nendfunction\n\nfunction propstruct = getprops (h)\n\n  persistent excluded;\n\n  if (isempty (excluded))\n    excluded = cell2struct (repmat ({[]}, 1, 4),\n                            {\"beingdeleted\", \"children\", \"parent\", \"type\"}, 2);\n  endif\n\n  obj = get (h);\n  ## get useful properties rejecting readonly, children, handles ...\n  fields = fieldnames (obj);\n  tf = isfield (excluded, fields);\n  propstruct = rmfield (obj, fields(tf));\n\n  ## hidden properties\n  hidden_props = {\"__appdata__\", \"__autopos_tag__\", \"looseinset\", ...\n                  \"positionmode\", \"rotationmode\", ...\n                  \"horizontalalignmentmode\", \"verticalalignmentmode\"};\n  for prop = hidden_props\n    try\n      val = get (h, prop{1});\n      propstruct.(prop{1}) = val;\n    end_try_catch\n  endfor\n\nendfunction\n\n\n## FIXME: need validation tests\n\n## FIXME: Need to test code for legends, colorbars.\n"
  },
  {
    "path": "scripts/plot/util/hggroup.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} hggroup ()\n## @deftypefnx {} {} hggroup (@var{hax})\n## @deftypefnx {} {} hggroup (@dots{}, @var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{h} =} hggroup (@dots{})\n## Create handle graphics group object with axes parent @var{hax}.\n##\n## If no parent is specified, the group is created in the current axes.\n##\n## Multiple property/value pairs may be specified for the hggroup, but they\n## must appear in pairs.  The full list of properties is documented at\n## @ref{Axes Properties}.\n##\n## The optional return value @var{h} is a graphics handle to the created\n## hggroup object.\n##\n## Programming Note: An hggroup is a way to group base graphics objects such\n## as line objects or patch objects into a single unit which can react\n## appropriately.  For example, the individual lines of a contour plot are\n## collected into a single hggroup so that they can be made visible/invisible\n## with a single command, @code{set (hg_handle, \"visible\", \"off\")}.\n##\n## @seealso{addproperty, addlistener}\n## @end deftypefn\n\nfunction h = hggroup (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"hggroup\", varargin{:});\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  htmp = __go_hggroup__ (hax, varargin{:});\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h = hggroup ();\n%!   assert (findobj (hf, \"type\", \"hggroup\"), h);\n%!   assert (get (h, \"type\"), \"hggroup\");\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/hgload.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} hgload (@var{filename})\n## @deftypefnx {} {[@var{h}, @var{old_prop}] =} hgload (@var{filename}, @var{prop_struct})\n## Load the graphics objects in @var{filename} into a vector of graphics\n## handles @var{h}.\n##\n## If @var{filename} has no extension, Octave will try to find the file with\n## and without the default extension @file{.ofig}.\n##\n## If provided, the elements of structure @var{prop_struct} will be used to\n## override the properties of top-level objects stored in @var{filename}, and\n## the saved values from @var{filename} will be stored in @var{old_prop}.\n## @var{old_prop} is a cell array matching the size of @var{h}; each cell\n## contains a structure of the existing property names and values before being\n## overridden.\n##\n## @seealso{openfig, hgsave, struct2hdl}\n## @end deftypefn\n\nfunction [h, old_prop] = hgload (filename, prop_struct = struct ())\n\n  ## Check number of input arguments\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  ## Check type of second input argument\n  if (! isstruct (prop_struct))\n    error (\"hgload: PROP_STRUCT must be a struct\");\n  endif\n\n  ## Check file existence\n  [~, ~, ext] = fileparts (filename);\n  if (isempty (ext))\n    if (! isempty (file_in_loadpath ([filename \".ofig\"])))\n      filename = [filename \".ofig\"];\n    elseif (isempty (file_in_loadpath (filename)))\n      error (\"hgload: unable to locate file %s\", filename);\n    endif\n  else\n    if (isempty (file_in_loadpath (filename)))\n      error (\"hgload: unable to locate file %s\", filename);\n    endif\n  endif\n\n  ## Load the handle structure\n  hgs = {\"s_oct40\", \"hgS_050200\", \"hgS_070000\"};\n  hg = load (filename);\n  fig_file_version = isfield (hg, hgs);\n  if (nnz (fig_file_version) != 1)\n    error (\"hgload: could not load hgsave-formatted object in file %s\", filename);\n  endif\n  hg = hg.(hgs{fig_file_version});\n\n  ## Override properties of top-level objects\n  calc_old_prop = false;\n  if (nargout > 1)\n    calc_old_prop = true;\n    old_prop = repmat ({[]}, 1, numel (hg));\n  endif\n  fn_new = fieldnames (prop_struct);\n  if (! isempty (fn_new))\n    for i = 1:numel (hg)\n      fn_old = fieldnames (hg(i).properties);\n      for j = 1:numel (fn_new)\n        idx = ismember (lower (fn_old), lower (fn_new{j}));\n        if (any (idx))\n          if (calc_old_prop)\n            old_prop{i}.(fn_new{j}) = hg(i).properties.(fn_old{idx});\n          endif\n          hg(i).properties.(fn_old{idx}) = prop_struct.(fn_new{j});\n        endif\n      endfor\n    endfor\n  endif\n\n  ## Build the graphics handle object\n  h = zeros (1, numel (hg));\n  for i = 1:numel (hg)\n    h(i) = struct2hdl (hg(i));\n  endfor\n\nendfunction\n\n\n## Functional test for hgload/hgsave pair is in hgsave.m\n\n## Test overriding saved properties with second input\n%!test\n%! unwind_protect\n%!   h1 = figure (\"visible\", \"off\");\n%!   col = get (h1, \"color\");\n%!   ftmp = [tempname() \".ofig\"];\n%!   hgsave (h1, ftmp);\n%!   close (h1);\n%!   [h2, old] = hgload (ftmp);\n%!   assert (old, {[]});\n%!   [h3, old] = hgload (ftmp, struct (\"color\", [1 0 0]));\n%!   assert (get (h3, \"color\"), [1 0 0]);\n%!   assert (iscell (old) && numel (old) == 1);\n%!   assert (isstruct (old{1}) && isfield (old{1}, \"color\"));\n%!   assert (old{1}.color, col);\n%! unwind_protect_cleanup\n%!   unlink (ftmp);\n%!   try, close (h1); end_try_catch\n%!   try, close (h2); end_try_catch\n%!   try, close (h3); end_try_catch\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> hgload ()\n%!error <PROP_STRUCT must be a struct> hgload (1, {})\n%!error <unable to locate file> hgload (\"%%_A_REALLY_UNLIKELY_FILENAME_%%\")\n%!error <unable to locate file> hgload (\"%%_A_REALLY_UNLIKELY_FILENAME_%%.fig\")\n"
  },
  {
    "path": "scripts/plot/util/hgsave.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} hgsave (@var{filename})\n## @deftypefnx {} {} hgsave (@var{h}, @var{filename})\n## @deftypefnx {} {} hgsave (@var{h}, @var{filename}, @var{fmt})\n## Save the graphics handle(s) @var{h} to the file @var{filename} in the format\n## @var{fmt}.\n##\n## If unspecified, @var{h} is the current figure as returned by @code{gcf}.\n##\n## When @var{filename} does not have an extension the default filename\n## extension @file{.ofig} will be appended.\n##\n## If present, @var{fmt} must be one of the following:\n##\n## @itemize @bullet\n## @item @option{-binary}, @option{-float-binary}\n##\n## @item @option{-hdf5}, @option{-float-hdf5}\n##\n## @item @option{-V7}, @option{-v7}, @option{-7}, @option{-mat7-binary}\n##\n## @item @option{-V6}, @option{-v6}, @option{-6}, @option{-mat6-binary}\n##\n## @item @option{-text}\n##\n## @item @option{-zip}, @option{-z}\n## @end itemize\n##\n## The default format is @option{-binary} to minimize storage.\n##\n## Programming Note: When producing graphics for final publication use\n## @code{print} or @code{saveas}.  When it is important to be able to continue\n## to edit a figure as an Octave object, use @code{hgsave}/@code{hgload}.\n## @seealso{hgload, hdl2struct, savefig, saveas, print}\n## @end deftypefn\n\nfunction hgsave (h, filename, fmt = \"-binary\")\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Check input arguments\n  if (nargin == 1 && ischar (h))\n    filename = h;\n    h = get (0, \"currentfigure\");\n    if (isempty (h))\n      error (\"hgsave: no current figure to save\");\n    endif\n  elseif (! (all (ishghandle (h)) && ischar (filename)))\n    print_usage ();\n  endif\n\n  ## Check file extension\n  [~, ~, ext] = fileparts (filename);\n  if (isempty (ext))\n    filename = [filename \".ofig\"];\n  endif\n\n  for i = 1:numel (h)\n    s_oct40(i) = hdl2struct (h(i));\n  endfor\n  save (fmt, filename, \"s_oct40\");\n\nendfunction\n\n\n%!testif HAVE_MAGICK; (have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ())));\n%! toolkit = graphics_toolkit ();\n%! graphics_toolkit (\"qt\");\n%! h1 = figure (\"visible\", \"off\", \"paperposition\", [0.25, 2.5, 8.0, 6.0]);\n%! unwind_protect\n%!   x = 0:0.1:2*pi;\n%!   y1 = sin (x);\n%!   y2 = exp (x - 1);\n%!   ax = plotyy (x,y1, x-1,y2, @plot, @semilogy);\n%!   xlabel (\"X\");\n%!   ylabel (ax(1), \"Axis 1\");\n%!   ylabel (ax(2), \"Axis 2\");\n%!   axes (ax(1));\n%!   text (0.5, 0.5, \"Left Axis\", ...\n%!         \"color\", [0 0 1], \"horizontalalignment\", \"center\");\n%!   axes (ax(2));\n%!   text (4.5, 80, \"Right Axis\", ...\n%!         \"color\", [0 0.5 0], \"horizontalalignment\", \"center\");\n%!   ftmp = [tempname() \".ofig\"];\n%!   png1 = [tempname() \".png\"];\n%!   png2 = [tempname() \".png\"];\n%!   unwind_protect\n%!     hgsave (h1, ftmp);\n%!     print (h1, png1);\n%!     [img1, map1, alpha1] = imread (png1);\n%!     h2 = hgload (ftmp);\n%!     print (h2, png2);\n%!     [img2, map2, alpha2] = imread (png2);\n%!   unwind_protect_cleanup\n%!     unlink (ftmp);\n%!     unlink (png1);\n%!     unlink (png2);\n%!   end_unwind_protect\n%!   assert (img1, img2);\n%!   assert (map1, map2);\n%!   assert (alpha1, alpha2);\n%! unwind_protect_cleanup\n%!   close (h1);\n%!   close (h2);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> hgsave ()\n%!error <no current figure to save>\n%! unwind_protect\n%!  old_fig = get (0, \"currentfigure\");\n%!  set (0, \"currentfigure\", []);\n%!  hgsave (\"foobar\");\n%! unwind_protect_cleanup\n%!  set (0, \"currentfigure\", old_fig);\n%! end_unwind_protect\n%!error hgsave ([0, -1], \"foobar\")\n%!error hgsave (0, { \"foobar\" })\n"
  },
  {
    "path": "scripts/plot/util/hgtransform.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} hgtransform ()\n## @deftypefnx {} {@var{h} =} hgtransform (@var{property}, @var{value}, @dots{})\n## @deftypefnx {} {@var{h} =} hgtransform (@var{hax}, @dots{})\n##\n## Create a graphics transform object.\n##\n## FIXME: Need to write documentation.\n## FIXME: Add <makehgtform> to seealso list when it is implemented.\n## @seealso{hggroup}\n## @end deftypefn\n\n## FIXME: hgtransform should be a C++ graphics object, not an m-file.\n##        For the moment (3/7/17), it is quicker to implement something in\n##        an m-file.  But, this approach requires double the memory (original\n##        and transformed data), and a system of listeners and callbacks.\n##        In OpenGL toolkits it should be possible to simply insert a transform\n##        somewhere in gl-render.cc to have this done on the fly.\n\nfunction h = hgtransform (varargin)\n\n  [hax, varargin] = __plt_get_axis_arg__ (\"hgtransform\", varargin{:});\n\n  if (isempty (hax))\n    hax = gca ();\n  endif\n\n  htmp = hggroup (hax);\n\n  addproperty (\"matrix\", htmp, \"data\", eye (4));\n  addproperty (\"__orig_data__\", htmp, \"any\", struct (\"h\", {}));\n  if (! isempty (varargin))\n    set (htmp, varargin{:});\n  endif\n  addlistener (htmp, \"matrix\", @matrix_cb);\n  addlistener (htmp, \"children\", @children_cb);\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\nfunction matrix_cb (hgt, ~)\n\n  M = get (hgt, \"matrix\");\n  ## FIXME: Need better input validation on transform matrix M.\n  ##        Disallow shear, perspective transforms.\n  if (! isreal (M) || ! ismatrix (M) || rows (M) != 4 || columns (M) != 4)\n    error (\"hgtransform: transform must be 4x4 real matrix\");\n  endif\n\n  hkids = get (hgt, \"children\");\n  xform_data (hgt, hkids);\n\nendfunction\n\nfunction xform_data (hgt, hlist)\n\n  M = get (hgt, \"matrix\");\n  orig_data = get (hgt, \"__orig_data__\");\n\n  for hk = hlist.'\n\n    ## FIXME: Add support for light and rectangle objects\n    type = get (hk, \"type\");\n    if (! any (strcmp (type, {\"line\", \"patch\", \"surface\", \"image\", \"text\"})))\n      continue;  # Unsupported type.  Silently skip.\n    endif\n\n    idx = find (hk == [orig_data.h]);\n    if (! idx)\n      warning (\"hgtransform: original data not found for %f\", hk);\n      continue;\n    endif\n\n    if (strcmp (type, \"text\"))\n      pos = orig_data(idx).position;\n      xd = pos(1);\n      yd = pos(2);\n      zd = pos(3);\n    else\n      ## FIXME: Rotations for \"image\" objects are not handled correctly.\n      xd = double (orig_data(idx).xdata);\n      xsz = size (xd);\n\n      yd = double (orig_data(idx).ydata);\n      ysz = size (yd);\n\n      if (strcmp (type, \"image\"))\n        zd = [];\n      else\n        zd = double (orig_data(idx).zdata);\n        zsz = size (zd);\n      endif\n      z_empty = isempty (zd);\n\n      if (z_empty)\n        ## Common case of 2-D data.\n        zd = zeros (numel (xd), 1);\n      elseif (isvector (xd) && isvector (yd))\n        ## Handle surface data which may be a vector/matrix combination\n        if (isvector (zd))\n          ## Do nothing.  All data will be forced to row vectors below\n        elseif (length (xd) == rows (zd) && length (yd) == columns (zd))\n          [xd, yd] = meshgrid (xd, yd);\n          xsz = size (xd);\n          ysz = size (yd);\n        endif\n      endif\n\n      ## Force row vectors for later concatenation\n      xd = xd(:).';\n      yd = yd(:).';\n      zd = zd(:).';\n\n    endif\n\n    ## FIXME: To minimize memory, better to construct data matrix in-place?\n    data = [xd; yd; zd; ones(1, columns(xd))];\n    tol = 2 * max (eps (data(1:3,:)));\n    data = M * data;\n    ## Need to trim or rotations which produce values near 0 will be strange.\n    data(abs (data) < tol) = 0;\n\n    if (strcmp (type, \"text\"))\n      set (hk, \"position\", [data(1), data(2), data(3)]);\n    else\n      set (hk, \"xdata\", reshape (data(1,:), xsz),\n               \"ydata\", reshape (data(2,:), ysz));\n      if (! z_empty)\n        set (hk, \"zdata\", reshape (data(3,:), zsz));\n      endif\n    endif\n\n  endfor\n\nendfunction\n\nfunction children_cb (hgt, ~)\n\n  hkids = get (hgt, \"children\");\n  orig_data = get (hgt, \"__orig_data__\");\n  hlist = [orig_data.h];\n\n  ## Delete any children that have been removed\n  hdel = setdiff (hlist, hkids);\n  if (! isempty (hdel))\n    for hk = hdel.'\n      idx = find (hk == hlist);\n      if (ishghandle (hk))\n        ## child was re-parented to something else, restore data\n        switch (get (hk, \"type\"))\n\n          case {\"line\", \"patch\", \"surface\"}\n            set (hk, \"xdata\", orig_data(idx).xdata,\n                     \"ydata\", orig_data(idx).ydata,\n                     \"zdata\", orig_data(idx).zdata);\n\n          case \"image\"\n            set (hk, \"xdata\", orig_data(idx).xdata,\n                     \"ydata\", orig_data(idx).ydata);\n\n          case \"text\"\n            set (hk, \"position\", orig_data(idx).position);\n\n          otherwise\n            ## Unsupported type.  No data was saved.\n\n        endswitch\n      endif\n    endfor\n    orig_data = orig_data(hlist != hdel);\n    hlist = hlist(hlist != hdel);\n  endif\n\n  ## Add new children\n  hnew = setdiff (hkids, hlist);\n  for hk = hnew.'\n\n    orig_data(end+1).h = hk;\n    type = get (hk, \"type\");\n    orig_data(end).type = type;\n\n    switch (type)\n\n      case {\"line\", \"patch\", \"surface\"}\n        orig_data(end).xdata = get (hk, \"xdata\");\n        orig_data(end).ydata = get (hk, \"ydata\");\n        orig_data(end).zdata = get (hk, \"zdata\");\n\n      case \"image\"\n        orig_data(end).xdata = get (hk, \"xdata\");\n        orig_data(end).ydata = get (hk, \"ydata\");\n\n      case \"text\"\n        orig_data(end).position = get (hk, \"position\");\n\n      case \"light\"\n        warning (\"hgtransform: %s objects are not yet supported\", type);\n\n      case \"hggroup\"\n        try\n          get (hk, \"curvature\");\n          is_rectangle = true;\n        catch\n          is_rectangle = false;\n        end_try_catch\n        if (is_rectangle)\n          warning (\"hgtransform: rectangle objects are not yet supported\");\n        else\n          error (\"hgtransform: hggroup cannot be a child of an hgtransform\");\n        endif\n\n      otherwise\n        error (\"hgtransform: %s cannot be a child of an hgtransform\", type);\n\n    endswitch\n\n  endfor\n\n  set (hgt, \"__orig_data__\", orig_data);\n\n  ## Update data of new children only\n  xform_data (hgt, hnew);\n\nendfunction\n\n\n## Need BIST tests here\n"
  },
  {
    "path": "scripts/plot/util/hold.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} hold\n## @deftypefnx {} {} hold on\n## @deftypefnx {} {} hold off\n## @deftypefnx {} {} hold (@var{hax}, @dots{})\n## Toggle or set the @qcode{\"hold\"} state of the plotting engine which\n## determines whether new graphic objects are added to the plot or replace\n## the existing objects.\n##\n## @table @code\n## @item hold on\n## Retain plot data and settings so that subsequent plot commands are displayed\n## on a single graph.  Line color and line style are advanced for each new plot\n## added.\n##\n## @item hold all (deprecated)\n## Equivalent to @code{hold on}.\n##\n## @item hold off\n## Restore default graphics settings which clear the graph and reset axes\n## properties before each new plot command.  (default).\n##\n## @item hold\n## Toggle the current hold state.\n## @end table\n##\n## When given the additional argument @var{hax}, the hold state is modified\n## for this axes rather than the current axes returned by @code{gca}.\n##\n## To query the current hold state use the @code{ishold} function.\n## @seealso{ishold, cla, clf, newplot}\n## @end deftypefn\n\nfunction hold (varargin)\n\n  have_axes_arg = false;\n  if (nargin > 0 && isscalar (varargin{1}) && isaxes (varargin{1}))\n    have_axes_arg = true;\n    hax = varargin{1};\n    varargin(1) = [];\n    nargs = numel (varargin);\n    hfig = ancestor (hax, \"figure\");\n  elseif (nargin > 0 && numel (varargin{1}) > 1 && ishghandle (varargin{1}))\n    print_usage ();\n  else\n    hax = gca ();\n    hfig = gcf ();\n    nargs = numel (varargin);\n  endif\n\n  hold_all = false;\n  if (nargs == 0)\n    turn_hold_off = ishold (hax);\n    state_str = ifelse (turn_hold_off, \"off\", \"on\");\n    axes_str = ifelse (have_axes_arg, \"specified\", \"current\");\n    printf (\"hold is now %s for %s axes\\n\", state_str, axes_str);\n  elseif (nargs == 1)\n    state = lower (varargin{1});\n    switch (state)\n      case \"off\"\n        turn_hold_off = true;\n      case \"all\"\n        turn_hold_off = false;\n        hold_all = true;\n      case \"on\"\n        turn_hold_off = false;\n      otherwise\n        error (\"hold: invalid hold STATE\");\n    endswitch\n  else\n    print_usage ();\n  endif\n\n  if (turn_hold_off)\n    set (hax, \"nextplot\", \"replace\");\n  else\n    set (hax, \"nextplot\", \"add\");\n    set (hfig, \"nextplot\", \"add\");\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! t = linspace (0, 2*pi, 100);\n%! plot (t, sin (t));\n%! hold on;\n%! plot (t, cos (t));\n%! title ({\"hold on\", \"2 plots shown on same graph\"});\n%! hold off;\n\n%!demo\n%! clf;\n%! A = rand (100);\n%! [X, Y] = find (A > 0.95);\n%! imshow (A);\n%! hold on;\n%! plot (X, Y, \"o\");\n%! hold off;\n%! title (\"hold with image and plot\");\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! hold on;\n%! imagesc (1 ./ hilb (4));\n%! plot (1:4, \"-s\");\n%! title (\"hold with image and plot\");\n%! hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! hold on;\n%! imagesc (1 ./ hilb (2));\n%! imagesc (1 ./ hilb (4));\n%! title ({\"hold with two images\", \"only second image is visible\"});\n%! hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! hold on;\n%! plot (1:4, \"-s\");\n%! imagesc (1 ./ hilb (4));\n%! title ({\"hold with plot and image\", \"only image is visible\"});\n%! hold off;\n\n%!demo\n%! clf;\n%! colormap (\"default\");\n%! t = linspace (-3, 3, 50);\n%! [x, y] = meshgrid (t, t);\n%! z = peaks (x, y);\n%! contourf (x, y, z, 10);\n%! hold on;\n%! plot (x(:), y(:), \"^\");\n%! patch ([-1.0 1.0 1.0 -1.0 -1.0], [-1.0 -1.0 1.0 1.0 -1.0], \"red\");\n%! xlim ([-2.0 2.0]);\n%! ylim ([-2.0 2.0]);\n%! colorbar (\"SouthOutside\");\n%! title (\"hold with line, surface, and patch objects\");\n\n## hold on test\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   p = plot ([0 1]);\n%!   assert (! ishold);\n%!   hold on;\n%!   assert (ishold);\n%!   p1 = fill ([0 1 1], [0 0 1], \"black\");\n%!   p2 = fill ([0 1 0], [0 1 1], \"red\");\n%!   assert (length (get (hf, \"children\")), 1);\n%!   assert (length (get (gca, \"children\")), 3);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## hold off test\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   p = plot ([0 1]);\n%!   assert (! ishold);\n%!   hold on;\n%!   assert (ishold);\n%!   p1 = fill ([0 1 1], [0 0 1], \"black\");\n%!   hold off;\n%!   p2 = fill ([0 1 0], [0 1 1], \"red\");\n%!   assert (length (get (hf, \"children\")), 1);\n%!   assert (length (get (gca, \"children\")), 1);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/isaxes.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isaxes (@var{h})\n## Return true if @var{h} is an axes graphics handle and false otherwise.\n##\n## If @var{h} is a matrix then return a logical array which is true where the\n## elements of @var{h} are axes graphics handles and false where they are not.\n## @seealso{isfigure, ishghandle, isgraphics}\n## @end deftypefn\n\nfunction tf = isaxes (h)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = ishghandle (h);\n\n  if (any (tf))\n    tf(tf) = strcmp (get (h(tf), \"type\"), \"axes\");\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   assert (isaxes (hax));\n%!   assert (! isaxes (-hax));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes ();\n%!   assert (isaxes ([hax NaN]), [true false]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <Invalid call> isaxes ()\n"
  },
  {
    "path": "scripts/plot/util/isfigure.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isfigure (@var{h})\n## Return true if @var{h} is a figure graphics handle and false otherwise.\n##\n## If @var{h} is a matrix then return a logical array which is true where the\n## elements of @var{h} are figure graphics handles and false where they are\n## not.\n## @seealso{isaxes, ishghandle, isgraphics}\n## @end deftypefn\n\nfunction tf = isfigure (h)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = ishghandle (h);\n\n  if (any (tf))\n    tf(tf) = strcmp (get (h(tf), \"type\"), \"figure\");\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   assert (isfigure (hf));\n%!   assert (! isfigure (-hf));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   assert (isfigure ([hf NaN]), [true false]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!error <Invalid call> isfigure ()\n"
  },
  {
    "path": "scripts/plot/util/isgraphics.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} isgraphics (@var{h})\n## @deftypefnx {} {@var{tf} =} isgraphics (@var{h}, @var{type})\n## Return true if @var{h} is a graphics handle (of type @var{type}) and false\n## otherwise.\n##\n## When no @var{type} is specified the function is equivalent to\n## @code{ishghandle}.\n## @seealso{ishghandle, ishandle, isaxes, isfigure}\n## @end deftypefn\n\nfunction tf = isgraphics (h, type = \"\")\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 2 && ! (ischar (type) && isrow (type)))\n    error (\"isgraphics: TYPE must be a string\");\n  endif\n\n  ## Octave has no Simulink equivalent so it is sufficient to call ishghandle.\n  tf = ishghandle (h);\n\n  if (nargin == 2 && any (tf))\n    tf(tf) = strcmpi (get (h(tf), \"type\"), type);\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   assert (isgraphics (hf));\n%!   assert (isgraphics (hf, \"figure\"));\n%!   assert (! isgraphics (-hf));\n%!   assert (! isgraphics (hf, \"foo\"));\n%!   l = line ();\n%!   ax = gca ();\n%!   assert (isgraphics (ax));\n%!   assert (isgraphics (ax, \"axes\"));\n%!   assert (! isgraphics (-ax));\n%!   assert (! isgraphics (ax, \"foo\"));\n%!   assert (isgraphics (l));\n%!   assert (isgraphics (l, \"line\"));\n%!   assert (! isgraphics (-l));\n%!   assert (! isgraphics (l, \"foo\"));\n%!   p = patch ();\n%!   assert (isgraphics (p));\n%!   assert (isgraphics (p, \"patch\"));\n%!   assert (! isgraphics (-p));\n%!   assert (! isgraphics (p, \"foo\"));\n%!   s = surface ();\n%!   assert (isgraphics (s));\n%!   assert (isgraphics (s, \"surface\"));\n%!   assert (! isgraphics (-s));\n%!   assert (! isgraphics (s, \"foo\"));\n%!   t = text ();\n%!   assert (isgraphics (t));\n%!   assert (isgraphics (t, \"text\"));\n%!   assert (! isgraphics (-t));\n%!   assert (! isgraphics (t, \"foo\"));\n%!   i = image ([1]);\n%!   assert (isgraphics (i));\n%!   assert (isgraphics (i, \"image\"));\n%!   assert (! isgraphics (-i));\n%!   assert (! isgraphics (i, \"foo\"));\n%!   hg = hggroup ();\n%!   assert (isgraphics (hg));\n%!   assert (isgraphics (hg, \"hggroup\"));\n%!   assert (! isgraphics (-hg));\n%!   assert (! isgraphics (hg, \"foo\"));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!test\n%! assert (isgraphics ([-1 0]), [false true]);\n%! assert (isgraphics ([-1 0], \"root\"), [false true]);\n%! assert (isgraphics ([-1 0], \"foobar\"), [false false]);\n\n## Test input validation\n%!error <Invalid call> isgraphics ()\n%!error <TYPE must be a string> isgraphics (0, 1)\n%!error <TYPE must be a string> isgraphics (0, {1})\n"
  },
  {
    "path": "scripts/plot/util/ishandle.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} ishandle (@var{h})\n## Return true if @var{h} is a handle to a graphics or Java object and false\n## otherwise.\n##\n## @var{h} may also be a matrix of handles in which case a logical array is\n## returned that is true where the elements of @var{h} are handles to graphics\n## or Java objects and false where they are not.\n##\n## Programming Note: It is often more useful to test for a specific object\n## type.  To determine if a handle belongs to a graphics object use\n## @code{ishghandle} or @code{isgraphics}.  To determine if a handle belongs\n## to a Java object use @code{isjava}.\n## @seealso{ishghandle, isgraphics, isjava}\n## @end deftypefn\n\nfunction tf = ishandle (h)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = ishghandle (h) | isjava (h);\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   assert (ishandle (hf));\n%!   assert (! ishandle (-hf));\n%!   ax = gca ();\n%!   l = line ();\n%!   assert (ishandle (ax));\n%!   assert (! ishandle (-ax));\n%!   assert (ishandle ([l, -1, ax, hf]), logical ([1, 0, 1, 1]));\n%!   assert (ishandle ([l, -1, ax, hf]'), logical ([1, 0, 1, 1]'));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n%!assert (ishandle ([-1 0]), [false true])\n\n%!testif HAVE_JAVA; usejava (\"jvm\")\n%! jobj = javaObject (\"java.lang.Double\", 1.0);\n%! assert (ishandle (jobj));\n\n## Test input validation\n%!error <Invalid call> ishandle ()\n"
  },
  {
    "path": "scripts/plot/util/ishold.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} ishold\n## @deftypefnx {} {@var{tf} =} ishold (@var{hax})\n## @deftypefnx {} {@var{tf} =} ishold (@var{hfig})\n## Return true if the next plot will be added to the current plot, or\n## false if the plot device will be cleared before drawing the next plot.\n##\n## If the first argument is an axes handle @var{hax} or figure handle\n## @var{hfig} then operate on this plot rather than the current one.\n## @seealso{hold, newplot}\n## @end deftypefn\n\nfunction tf = ishold (h)\n\n  if (nargin == 0)\n    hfig = gcf ();\n    hax = get (hfig, \"currentaxes\");\n  else\n    if (! ishghandle (h))\n      error (\"ishold: H must be an axes or figure graphics handle\");\n    endif\n\n    switch (get (h, \"type\"))\n      case \"figure\"\n        hfig = h;\n        hax = get (hfig, \"currentaxes\");\n\n      case \"axes\"\n        hax = h;\n        hfig = ancestor (hax, \"figure\");\n\n      otherwise\n        error (\"ishold: H must be an axes or figure graphics handle\");\n\n    endswitch\n  endif\n\n  tf = (strcmp (get (hfig, \"nextplot\"), \"add\")\n        && ! isempty (hax) && strcmp (get (hax, \"nextplot\"), \"add\"));\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   assert (! ishold);\n%!   assert (isempty (get (hf, \"currentaxes\")));\n%!   assert (get (hf, \"NextPlot\"), \"add\");\n%!   l = plot ([0 1]);\n%!   assert (! ishold);\n%!   assert (! ishold (gca));\n%!   assert (get (gca, \"NextPlot\"), \"replace\");\n%!   assert (get (hf, \"NextPlot\"), \"add\");\n%!   hold on;\n%!   assert (ishold);\n%!   assert (ishold (gca));\n%!   assert (get (gca, \"NextPlot\"), \"add\");\n%!   assert (get (hf, \"NextPlot\"), \"add\");\n%!   p = fill ([0 1 1], [0 0 1],\"black\");\n%!   assert (numel (get (hf, \"children\")), 1);\n%!   assert (numel (get (gca, \"children\")), 2);\n%!   set (hf, \"NextPlot\", \"new\");\n%!   assert (! ishold);\n%!   assert (! ishold (gca));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/isprop.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{res} =} isprop (@var{obj}, \"@var{prop}\")\n## Return true if @var{prop} is a property of the object @var{obj}.\n##\n## @var{obj} may also be an array of objects in which case @var{res} will be a\n## logical array indicating whether each handle has the property @var{prop}.\n##\n## For plotting, @var{obj} is a handle to a graphics object.  Otherwise,\n## @var{obj} should be an instance of a class.  @code{isprop} reports whether\n## the class defines a property, but @code{Access} permissions or visibility\n## restrictions (@code{Hidden = true}) may prevent use by the programmer.\n## @seealso{get, set, properties, ismethod, isobject}\n## @end deftypefn\n\nfunction res = isprop (obj, prop)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! ischar (prop))\n    error (\"isprop: PROP name must be a string\");\n  endif\n\n  if (isobject (obj))\n    ## Separate code for classdef objects because Octave doesn't handle arrays\n    ## of objects and so can't use the generic code.\n    warning (\"off\", \"Octave:classdef-to-struct\", \"local\");\n\n    all_props = __fieldnames__ (obj);\n    res = any (strcmp (prop, all_props));\n  else\n    warning (\"error\", \"Octave:abbreviated-property-match\", \"local\");\n\n    res = false (size (obj));\n    for i = 1:numel (res)\n      if (ishghandle (obj(i)))\n        try\n          get (obj(i), prop);\n          res(i) = true;\n        end_try_catch\n      endif\n    endfor\n  endif\n\nendfunction\n\n\n%!assert (isprop (0, \"foobar\"), false)\n%!assert (isprop (0, \"screenpixelsperinch\"), true)\n%!assert (isprop (zeros (2, 3), \"visible\"), true (2, 3))\n%!assert (isprop ([-2, -1, 0], \"visible\"), [false, false, true])\n\n%!test\n%! m = containers.Map ();\n%! assert (isprop (m, \"KeyType\"));\n%! assert (! isprop (m, \"FooBar\"));\n\n%!error <Invalid call> isprop ()\n%!error <Invalid call> isprop (1)\n%!error <PROP name must be a string> isprop (0, {\"visible\"})\n"
  },
  {
    "path": "scripts/plot/util/linkaxes.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} linkaxes (@var{hax})\n## @deftypefnx {} {} linkaxes (@var{hax}, @var{optstr})\n## Link the axis limits of 2-D plots such that a change in one is propagated\n## to the others.\n##\n## The axes handles to be linked are passed as the first argument @var{hax}.\n##\n## The optional second argument is a string which defines which axis limits\n## will be linked.  The possible values for @var{optstr} are:\n##\n## @table @asis\n## @item @qcode{\"x\"}\n## Link x-axes\n##\n## @item @qcode{\"y\"}\n## Link y-axes\n##\n## @item @qcode{\"xy\"} (default)\n## Link both axes\n##\n## @item @qcode{\"off\"}\n## Turn off linking\n## @end table\n##\n## If unspecified the default is to link both X and Y axes.\n##\n## When linking, the limits from the first axes in @var{hax} are applied to the\n## other axes in the list.  Subsequent changes to any one of the axes will be\n## propagated to the others.\n##\n## @seealso{linkprop, addproperty}\n## @end deftypefn\n\nfunction linkaxes (hax, optstr = \"xy\")\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (numel (hax) < 2)\n    error (\"linkaxes: HAX must contain at least 2 handles\");\n  elseif (! all (isaxes (hax(:))))\n    error (\"linkaxes: HAX must be a vector of axes handles\");\n  endif\n\n  ## Check if axes are linked already and clear if found.\n  ## Otherwise, add the necessary linkaxes_data property.\n  for i = 1:length (hax)\n    if (isprop (hax(i), \"linkaxes_data\"))\n      hld = get (hax(i), \"linkaxes_data\");\n      try\n        rmappdata (hld, \"linkprop_data\");\n      end_try_catch\n    else\n      addproperty (\"linkaxes_data\", hax(i), \"any\");\n    endif\n  endfor\n\n  switch (optstr)\n    case \"x\"\n      hlink = linkprop (hax, \"xlim\");\n    case \"y\"\n      hlink = linkprop (hax, \"ylim\");\n    case \"xy\"\n      hlink = linkprop (hax, {\"xlim\" \"ylim\"});\n    case \"off\"\n      ## do nothing - link already deleted\n      hlink = [];\n    otherwise\n      error (\"linkaxes: unrecognized OPTSTR '%s'\", optstr);\n  endswitch\n\n  if (! isempty (hlink))\n    setappdata (hax(1), \"linkprop_data\", hlink);\n    set (hax, \"linkaxes_data\", hax(1));\n  else\n    set (hax, \"linkaxes_data\", []);\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! hax1 = subplot (3,1,1);\n%! bar (rand (4, 1), \"facecolor\", \"r\");\n%! hax2 = subplot (3,1,2);\n%! bar (5*rand (4, 1), \"facecolor\", \"g\");\n%! hax3 = subplot (3,1,3);\n%! bar (10*rand (4, 1), \"facecolor\", \"b\");\n%! input (\"Press <enter> to link axes: \");\n%! linkaxes ([hax1, hax2, hax3]);\n%! input (\"Press <enter> to change ylim: \");\n%! ylim (hax3, [0 10]);\n\n%!test\n%! hf1 = figure (\"visible\", \"off\");\n%! hax1 = axes ();\n%! plot (1:10);\n%! hf2 = figure (\"visible\", \"off\");\n%! hax2 = axes ();\n%! plot (10:-1:1, \"-*g\");\n%! hf3 = figure (\"visible\", \"off\");\n%! hax3 = axes ();\n%! plot (1:10:100, \"-xb\");\n%!  unwind_protect\n%!   linkaxes ([hax1, hax2, hax3]);\n%!   ## Test initial values taken from first object in list\n%!   assert (xlim (hax3), [0 10]);\n%!   assert (ylim (hax3), [0 10]);\n%!   ## Test linking\n%!   xlim (hax2, [2 8]);\n%!   assert (xlim (hax1), [2 8]);\n%!   assert (xlim (hax3), [2 8]);\n%!   ylim (hax3, \"auto\");\n%!   assert (ylim (hax1), [0 100]);\n%!   assert (ylim (hax2), [0 100]);\n%!   ## Test re-linking removes old link\n%!   linkaxes ([hax1, hax2]);\n%!   ylim (hax3, [0 50]);\n%!   assert (ylim (hax1), [0 100]);\n%!   assert (ylim (hax2), [0 100]);\n%!   xlim (hax1, [0 4]);\n%!   assert (xlim (hax2), [0 4]);\n%!   ## Test linking of remaining objects after deletion of one object\n%!   linkaxes ([hax1, hax2, hax3]);\n%!   xlim (hax2, [0 1]);\n%!   assert (xlim (hax1), [0 1]);\n%!   assert (xlim (hax3), [0 1]);\n%!   delete (hax2);\n%!   xlim (hax3, [0 2]);\n%!   assert (xlim (hax1), [0 2]);\n%!   ## Test deletion of link\n%!   linkaxes ([hax1, hax3], \"off\");\n%!   xlim (hax3, [0 3]);\n%!   assert (xlim (hax1), [0 2]);\n%!  unwind_protect_cleanup\n%!   close ([hf1 hf2 hf3]);\n%!  end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> linkaxes ()\n%!error <HAX must be a vector of axes handles> linkaxes ([pi, e])\n"
  },
  {
    "path": "scripts/plot/util/linkprop.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hlink} =} linkprop (@var{h}, \"@var{prop}\")\n## @deftypefnx {} {@var{hlink} =} linkprop (@var{h}, @{\"@var{prop1}\", \"@var{prop2}\", @dots{}@})\n## Link graphic object properties, such that a change in one is propagated to\n## the others.\n##\n## The input @var{h} is a vector of graphic handles to link.\n##\n## @var{prop} may be a string when linking a single property, or a cell array\n## of strings for multiple properties.  During the linking process all\n## properties in @var{prop} will initially be set to the values that exist on\n## the first object in the list @var{h}.\n##\n## The function returns @var{hlink} which is a special object describing the\n## link.  As long as the reference @var{hlink} exists, the link between graphic\n## objects will be active.  This means that @var{hlink} must be preserved in\n## a workspace variable, a global variable, or otherwise stored using a\n## function such as @code{setappdata} or @code{guidata}.  To unlink properties,\n## execute @code{clear @var{hlink}}.\n##\n## An example of the use of @code{linkprop} is\n##\n## @example\n## @group\n## x = 0:0.1:10;\n## subplot (1,2,1);\n## h1 = plot (x, sin (x));\n## subplot (1,2,2);\n## h2 = plot (x, cos (x));\n## hlink = linkprop ([h1, h2], @{\"color\",\"linestyle\"@});\n## set (h1, \"color\", \"green\");\n## set (h2, \"linestyle\", \"--\");\n## @end group\n## @end example\n##\n## @seealso{linkaxes, addlistener}\n## @end deftypefn\n\nfunction hlink = linkprop (h, prop)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (numel (h) < 2)\n    error (\"linkprop: H must contain at least 2 handles\");\n  elseif (! all (ishghandle (h(:))))\n    error (\"linkprop: invalid graphic handle in input H\");\n  endif\n\n  if (ischar (prop))\n    prop = {prop};\n  elseif (! iscellstr (prop))\n    error (\"linkprop: PROP must be a string or cell string array\");\n  endif\n\n  h = h(:);\n  ## Match all objects to the first one in the list before linking\n  for j = 1 : numel (prop)\n    set (h(2:end), prop{j}, get (h(1), prop{j}));\n  endfor\n\n  ## FIXME: This file needs to be locked to avoid bug #59439.  Remove this\n  ##        lock once that bug is properly fixed.\n  mlock ();\n\n  ## Add listeners to all objects\n  for i = 1 : numel (h)\n    for j = 1 : numel (prop)\n      addlistener (h(i), prop{j},\n                   {@cb_sync_prop, [h(1:i-1); h(i+1:end)], prop{j}});\n    endfor\n  endfor\n\n  hlink = onCleanup (@() unlink_linkprop (h, prop));\n\nendfunction\n\nfunction cb_sync_prop (h, ~, hlist, prop)\n  persistent recursion = false;\n\n  ## Don't allow recursion\n  if (! recursion)\n    unwind_protect\n      recursion = true;\n      set (hlist(ishghandle (hlist)), prop, get (h, prop));\n    unwind_protect_cleanup\n      recursion = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\nfunction unlink_linkprop (hlist, prop)\n\n  hlist = hlist(ishghandle (hlist));\n  for i = 1 : numel (hlist)\n    for j = 1 : numel (prop)\n      dellistener (hlist(i), prop{j});\n    endfor\n  endfor\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = 0:0.1:10;\n%! subplot (1,2,1);\n%!  h1 = plot (x, sin (x), \"r\");\n%! subplot (1,2,2);\n%!  h2 = plot (x, cos (x), \"b\");\n%!\n%! input (\"Press <enter> to link plots: \");\n%! hlink = linkprop ([h1, h2], {\"color\", \"linestyle\"});\n%! input (\"Press <enter> to change color: \");\n%! set (h1, \"color\", \"green\");\n%! input (\"Press <enter> to change linestyle: \");\n%! set (h2, \"linestyle\", \"--\");\n\n%!test\n%! hf1 = figure (\"visible\", \"off\");\n%! hl1 = plot (1:10, \"or\");\n%! hf2 = figure (\"visible\", \"off\");\n%! hl2 = plot (1:10, \"-*g\");\n%! hf3 = figure (\"visible\", \"off\");\n%! hl3 = plot (1:10, \"-xb\");\n%! unwind_protect\n%!   hlink = linkprop ([hl1, hl2, hl3], {\"color\", \"linestyle\"});\n%!   ## Test initial values taken from first object in list\n%!   assert (get (hl2, \"color\"), [1 0 0]);\n%!   assert (get (hl3, \"linestyle\"), \"none\");\n%!   ## Test linking\n%!   set (hl2, \"color\", \"b\");\n%!   assert (get (hl1, \"color\"), [0 0 1]);\n%!   assert (get (hl3, \"color\"), [0 0 1]);\n%!   set (hl3, \"linestyle\", \"--\");\n%!   assert (get (hl1, \"linestyle\"), \"--\");\n%!   assert (get (hl2, \"linestyle\"), \"--\");\n%!   ## Test linking of remaining objects after deletion of one object\n%!   delete (hl2);\n%!   set (hl1, \"linestyle\", \":\");\n%!   assert (get (hl3, \"linestyle\"), \":\");\n%!   ## Test deletion of link\n%!   clear hlink;\n%!   set (hl1, \"color\", \"g\");\n%!   assert (get (hl3, \"color\"), [0 0 1]);\n%! unwind_protect_cleanup\n%!   close ([hf1 hf2 hf3]);\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> linkprop ()\n%!error <Invalid call> linkprop (1)\n%!error <H must contain at least 2 handles> linkprop (1, \"color\")\n%!error <invalid graphic handle in input H> linkprop ([pi, e], \"color\")\n%!error <PROP must be a string or cell string array> linkprop ([0, 0], 1)\n"
  },
  {
    "path": "scripts/plot/util/meshgrid.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{xx}, @var{yy}] =} meshgrid (@var{x}, @var{y})\n## @deftypefnx {} {[@var{xx}, @var{yy}, @var{zz}] =} meshgrid (@var{x}, @var{y}, @var{z})\n## @deftypefnx {} {[@var{xx}, @var{yy}] =} meshgrid (@var{x})\n## @deftypefnx {} {[@var{xx}, @var{yy}, @var{zz}] =} meshgrid (@var{x})\n## Given vectors of @var{x} and @var{y} coordinates, return matrices @var{xx}\n## and @var{yy} corresponding to a full 2-D grid.\n##\n## The rows of @var{xx} are copies of @var{x}, and the columns of @var{yy} are\n## copies of @var{y}.  If @var{y} is omitted, then it is assumed to be the same\n## as @var{x}.\n##\n## If the optional @var{z} input is given, or @var{zz} is requested, then the\n## output will be a full 3-D grid.  If @var{z} is omitted and @var{zz} is\n## requested, it is assumed to be the same as @var{y}.\n##\n## @code{meshgrid} is most frequently used to produce input for a 2-D or 3-D\n## function that will be plotted.  The following example creates a surface\n## plot of the ``sombrero'' function.\n##\n## @example\n## @group\n## f = @@(x,y) sin (sqrt (x.^2 + y.^2)) ./ sqrt (x.^2 + y.^2);\n## range = linspace (-8, 8, 41);\n## [@var{X}, @var{Y}] = meshgrid (range, range);\n## Z = f (X, Y);\n## surf (X, Y, Z);\n## @end group\n## @end example\n##\n## Programming Note: @code{meshgrid} is restricted to 2-D or 3-D grid\n## generation.  The @code{ndgrid} function will generate 1-D through N-D\n## grids.  However, the functions are not completely equivalent.  If @var{x}\n## is a vector of length M and @var{y} is a vector of length N, then\n## @code{meshgrid} will produce an output grid which is NxM@.  @code{ndgrid}\n## will produce an output which is @nospell{MxN} (transpose) for the same\n## input.  Some core functions expect @code{meshgrid} input and others expect\n## @code{ndgrid} input.  Check the documentation for the function in question\n## to determine the proper input format.\n## @seealso{ndgrid, mesh, contour, surf}\n## @end deftypefn\n\nfunction [xx, yy, zz] = meshgrid (x, y, z)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  if (nargin < 2)\n    y = x;\n  endif\n\n  ## Use repmat to ensure that result values have the same type as the inputs\n\n  if (nargout < 3 && nargin < 3)\n    if (! (isvector (x) && isvector (y)))\n      error (\"meshgrid: X and Y must be vectors\");\n    endif\n    xx = repmat (x(:).', length (y), 1);\n    yy = repmat (y(:), 1, length (x));\n  else\n    if (nargin < 3)\n      z = y;\n    endif\n    if (! (isvector (x) && isvector (y) && isvector (z)))\n      error (\"meshgrid: X, Y, and Z must be vectors\");\n    endif\n    lenx = length (x);\n    leny = length (y);\n    lenz = length (z);\n    xx = repmat (repmat (x(:).', leny, 1), [1, 1, lenz]);\n    yy = repmat (repmat (y(:), 1, lenx), [1, 1, lenz]);\n    zz = reshape (repmat (z(:).', lenx*leny, 1)(:), leny, lenx, lenz);\n  endif\n\nendfunction\n\n\n%!test\n%! x = 1:2;\n%! y = 1:3;\n%! z = 1:4;\n%! [XX, YY, ZZ] = meshgrid (x, y, z);\n%! assert (size_equal (XX, YY, ZZ));\n%! assert (ndims (XX), 3);\n%! assert (size (XX), [3, 2, 4]);\n%! assert (XX(1) * YY(1) * ZZ(1), x(1) * y(1) * z(1));\n%! assert (XX(end) * YY(end) * ZZ(end), x(end) * y(end) * z(end));\n\n%!test\n%! x = 1:2;\n%! y = 1:3;\n%! [XX, YY] = meshgrid (x, y);\n%! assert (size_equal (XX, YY));\n%! assert (ndims (XX), 2);\n%! assert (size (XX), [3, 2]);\n%! assert (XX(1) * YY(1), x(1) * y(1));\n%! assert (XX(end) * YY(end), x(end) * y(end));\n\n%!test\n%! x = 1:3;\n%! [XX1, YY1] = meshgrid (x, x);\n%! [XX2, YY2] = meshgrid (x);\n%! assert (size_equal (XX1, XX2, YY1, YY2));\n%! assert (ndims (XX1), 2);\n%! assert (size (XX1), [3, 3]);\n%! assert (XX1, XX2);\n%! assert (YY1, YY2);\n\n%!test\n%! x = 1:2;\n%! y = 1:3;\n%! z = 1:4;\n%! [XX, YY] = meshgrid (x, y, z);\n%! assert (size_equal (XX, YY));\n%! assert (ndims (XX), 3);\n%! assert (size (XX), [3, 2, 4]);\n%! assert (XX(1) * YY(1), x(1) * y(1));\n%! assert (XX(end) * YY(end), x(end) * y(end));\n\n## Test input validation\n%!error <Invalid call> meshgrid ()\n%!error <X and Y must be vectors> meshgrid (ones (2,2), 1:3)\n%!error <X and Y must be vectors> meshgrid (1:3, ones (2,2))\n%!error <X, Y, and Z must be vectors> [X,Y,Z] = meshgrid (1:3, 1:3, ones (2,2))\n"
  },
  {
    "path": "scripts/plot/util/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_GEN_FCN_FILES = \\\n  %reldir%/gnuplot_binary.m\n\nGEN_FCN_FILES += $(%canon_reldir%_GEN_FCN_FILES)\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__add_default_menu__.m \\\n  %reldir%/private/__ghostscript__.m \\\n  %reldir%/private/__gnuplot_draw_axes__.m \\\n  %reldir%/private/__gnuplot_draw_figure__.m \\\n  %reldir%/private/__gnuplot_get_var__.m \\\n  %reldir%/private/__gnuplot_ginput__.m \\\n  %reldir%/private/__gnuplot_has_feature__.m \\\n  %reldir%/private/__gnuplot_has_terminal__.m \\\n  %reldir%/private/__gnuplot_open_stream__.m \\\n  %reldir%/private/__gnuplot_print__.m \\\n  %reldir%/private/__gnuplot_version__.m \\\n  %reldir%/private/__opengl_print__.m \\\n  %reldir%/private/__print_parse_opts__.m \\\n  %reldir%/private/__set_default_mouse_modes__.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/__actual_axis_position__.m \\\n  %reldir%/__check_rendering_capability__.m \\\n  %reldir%/__default_plot_options__.m \\\n  %reldir%/__gnuplot_drawnow__.m \\\n  %reldir%/__next_line_color__.m \\\n  %reldir%/__next_line_style__.m \\\n  %reldir%/__opengl_info__.m \\\n  %reldir%/__plt_get_axis_arg__.m \\\n  %reldir%/__pltopt__.m \\\n  %reldir%/allchild.m \\\n  %reldir%/ancestor.m \\\n  %reldir%/axes.m \\\n  %reldir%/cla.m \\\n  %reldir%/clf.m \\\n  %reldir%/close.m \\\n  %reldir%/closereq.m \\\n  %reldir%/colstyle.m \\\n  %reldir%/copyobj.m \\\n  %reldir%/figure.m \\\n  %reldir%/findall.m \\\n  %reldir%/findfigs.m \\\n  %reldir%/findobj.m \\\n  %reldir%/gca.m \\\n  %reldir%/gcbf.m \\\n  %reldir%/gcbo.m \\\n  %reldir%/gcf.m \\\n  %reldir%/gco.m \\\n  %reldir%/ginput.m \\\n  %reldir%/graphics_toolkit.m \\\n  %reldir%/groot.m \\\n  %reldir%/gui_mainfcn.m \\\n  %reldir%/hdl2struct.m \\\n  %reldir%/hggroup.m \\\n  %reldir%/hgload.m \\\n  %reldir%/hgsave.m \\\n  %reldir%/hgtransform.m \\\n  %reldir%/hold.m \\\n  %reldir%/isaxes.m \\\n  %reldir%/isfigure.m \\\n  %reldir%/isgraphics.m \\\n  %reldir%/ishandle.m \\\n  %reldir%/ishold.m \\\n  %reldir%/isprop.m \\\n  %reldir%/linkaxes.m \\\n  %reldir%/linkprop.m \\\n  %reldir%/meshgrid.m \\\n  %reldir%/ndgrid.m \\\n  %reldir%/newplot.m \\\n  %reldir%/openfig.m \\\n  %reldir%/pan.m \\\n  %reldir%/print.m \\\n  %reldir%/printd.m \\\n  %reldir%/refresh.m \\\n  %reldir%/refreshdata.m \\\n  %reldir%/rotate.m \\\n  %reldir%/rotate3d.m \\\n  %reldir%/saveas.m \\\n  %reldir%/savefig.m \\\n  %reldir%/shg.m \\\n  %reldir%/struct2hdl.m \\\n  %reldir%/subplot.m \\\n  %reldir%/zoom.m\n\n%canon_reldir%dir = $(fcnfiledir)/plot/util\n\n%canon_reldir%_DATA = \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_GEN_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/plot/util/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/plot/util/ndgrid.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{y1}, @var{y2}, @dots{}, @var{y}n] =} ndgrid (@var{x1}, @var{x2}, @dots{}, @var{x}n)\n## @deftypefnx {} {[@var{y1}, @var{y2}, @dots{}, @var{y}n] =} ndgrid (@var{x})\n## Given n vectors @var{x1}, @dots{}, @var{x}n, @code{ndgrid} returns n\n## arrays of dimension n.\n##\n## The elements of the i-th output argument contains the elements of the\n## vector @var{x}i repeated over all dimensions different from the i-th\n## dimension.  Calling ndgrid with only one input argument @var{x} is\n## equivalent to calling ndgrid with all n input arguments equal to @var{x}:\n##\n## [@var{y1}, @var{y2}, @dots{}, @var{y}n] = ndgrid (@var{x}, @dots{}, @var{x})\n##\n## Programming Note: @code{ndgrid} is very similar to the function\n## @code{meshgrid} except that the first two dimensions are transposed in\n## comparison to @code{meshgrid}.  Some core functions expect @code{meshgrid}\n## input and others expect @code{ndgrid} input.  Check the documentation for\n## the function in question to determine the proper input format.\n## @seealso{meshgrid}\n## @end deftypefn\n\nfunction varargout = ndgrid (varargin)\n\n  if (nargin == 0)\n    print_usage ();\n  elseif (nargin == 1)\n    nd = max (nargout, 1);\n    ## If only one input argument is given, repeat it nd-times\n    varargin(1:nd) = varargin(1);\n  elseif (nargin >= nargout)\n    nd = max (nargin, 1);\n  else\n    error (\"ndgrid: wrong number of input arguments\");\n  endif\n\n  ## Determine the size of the output arguments\n  shape = zeros (1, nd);\n  for i = 1:nd\n    if (! isvector (varargin{i}) && ! isempty (varargin{i}))\n      error (\"ndgrid: arguments must be vectors\");\n    endif\n    shape(i) = length (varargin{i});\n  endfor\n\n  if (nd == 1)\n    ## Special case, single input vector\n    varargout{1} = varargin{1}(:);\n  else\n    for i = 1:nd\n      ## size for reshape\n      r = ones (1, nd+1);\n      r(i) = shape(i);\n\n      ## size for repmat\n      s = shape;\n      s(i) = 1;\n\n      varargout{i} = repmat (reshape (varargin{i}, r), s);\n    endfor\n  endif\n\nendfunction\n\n\n%!test\n%! x = 1:3;\n%! assert (isequal (ndgrid (x), x(:)));\n\n%!test\n%! x = 1:3;\n%! [XX, YY] = ndgrid (x);\n%! assert (size_equal (XX, YY));\n%! assert (isequal (XX, repmat (x(:), 1, numel (x))));\n%! assert (isequal (YY, repmat (x, numel (x), 1)));\n\n%!test\n%! x = 1:2;\n%! y = 1:3;\n%! z = 1:4;\n%! [XX, YY, ZZ] = ndgrid (x, y, z);\n%! assert (size_equal (XX, YY, ZZ));\n%! assert (ndims (XX), 3);\n%! assert (size (XX), [2, 3, 4]);\n%! assert (XX(1) * YY(1) * ZZ(1), x(1) * y(1) * z(1));\n%! assert (XX(end) * YY(end) * ZZ(end), x(end) * y(end) * z(end));\n\n%!test\n%! x = 1:2;\n%! y = 1:3;\n%! [XX1, YY1] = meshgrid (x, y);\n%! [XX2, YY2] = ndgrid (x, y);\n%! assert (size_equal (XX1, YY1));\n%! assert (size_equal (XX2, YY2));\n%! assert (ndims (XX1), 2);\n%! assert (size (XX1), [3, 2]);\n%! assert (size (XX2), [2, 3]);\n%! assert (XX2(1) * YY2(1), x(1) * y(1));\n%! assert (XX2(end) * YY2(end), x(end) * y(end));\n%! assert (XX1, XX2.');\n%! assert (YY1, YY2.');\n\n%!assert (ndgrid ([]), zeros (0,1))\n%!assert (ndgrid ([], []), zeros(0,0))\n\n## Test input validation\n%!error <Invalid call> ndgrid ()\n%!error <wrong number of input arguments> [a,b,c] = ndgrid (1:3,1:3)\n%!error <arguments must be vectors> ndgrid (ones (2,2))\n"
  },
  {
    "path": "scripts/plot/util/newplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} newplot ()\n## @deftypefnx {} {} newplot (@var{hfig})\n## @deftypefnx {} {} newplot (@var{hax})\n## @deftypefnx {} {@var{hax} =} newplot (@dots{})\n## Prepare graphics engine to produce a new plot.\n##\n## This function is called at the beginning of all high-level plotting\n## functions.  It is not normally required in user programs.  @code{newplot}\n## queries the @qcode{\"NextPlot\"} field of the current figure and axes to\n## determine what to do.\n##\n## @multitable @columnfractions .25 .75\n## @headitem Figure NextPlot @tab Action\n## @item @qcode{\"add\"} (default) @tab Add new graphic objects to the current\n## figure.\n##\n## @item @qcode{\"new\"} @tab Create a new figure and make it the current figure.\n##\n## @item @qcode{\"replace\"} @tab Delete all child objects of the figure and\n## reset all figure properties to their defaults.  However, the following\n## four properties are not reset: Position, Units, PaperPosition, PaperUnits.\n## In addition, the NextPlot property is set to @qcode{\"add\"} regardless of\n## user-defined defaults.  This is equivalent to @code{clf reset}.\n##\n## @item @qcode{\"replacechildren\"} @tab Delete child objects whose\n## HandleVisibility is set to @qcode{\"on\"}.  Set NextPlot property to\n## @qcode{\"add\"}.  This typically clears a figure, but leaves in place hidden\n## objects such as menubars.  This is equivalent to @code{clf}.\n## @end multitable\n##\n## @multitable @columnfractions .25 .75\n## @headitem Axes NextPlot @tab Action\n## @item @qcode{\"add\"} @tab Add new graphic objects to the current axes.  This\n## is equivalent to @code{hold on}.\n##\n## @item @qcode{\"replace\"} (default) @tab Delete all child objects of the\n## axes and reset all axes properties to their defaults.  However, the\n## following properties are not reset: Position, Units.  This is equivalent\n## to @code{cla reset}.\n##\n## @c FIXME: Uncomment when \"replaceall\" property value added to axes\n## @c @item @qcode{\"replaceall\"} @tab For plots with one y-axis this is equivalent\n## @c to @qcode{\"replace\"}.  For plots created with @code{plotyy}, operate on both\n## @c axes rather than just the single axes object @code{hax}.\n##\n## @item @qcode{\"replacechildren\"} @tab Delete child objects whose\n## HandleVisibility is set to @qcode{\"on\"}, but leave axes properties\n## unmodified except for ColorOrderIndex and LineStyleOrderIndex which are set\n## to 1.  This typically clears a plot, but preserves special settings such as\n## log scaling for axes.  This is equivalent to @code{cla}.\n##\n## @end multitable\n##\n## If the optional input @var{hfig} or @var{hax} is given then prepare the\n## specified figure or axes rather than the current figure and axes.\n##\n## The optional return value @var{hax} is a graphics handle to the created\n## axes object (not figure).\n## @end deftypefn\n\nfunction hax = newplot (hg = [])\n\n  old_cf = [];\n  cf = ca = [];\n\n  if (! isempty (hg))\n    if (! isscalar (hg))\n      error (\"newplot: first argument must be scalar graphics handle\");\n    endif\n\n    if (isaxes (hg))\n      ca = hg;\n      cf = ancestor (ca, \"figure\", \"toplevel\");\n    elseif (isfigure (hg))\n      cf = hg;\n    else\n      error (\"newplot: first argument must be an axes or figure handle\");\n    endif\n  endif\n\n  do_reset = true;\n  if (isempty (cf))\n    ## get current figure, or create a new one if necessary\n    old_cf = get (0, \"currentfigure\");\n    if (isempty (old_cf))\n      cf = figure ();\n      do_reset = false;\n    else\n      cf = old_cf;\n    endif\n  else\n    ## switch to figure provided without causing other updates\n    old_cf = get (0, \"currentfigure\");\n    set (0, \"currentfigure\", cf);\n  endif\n\n  fnp = get (cf, \"nextplot\");\n  switch (fnp)\n\n    case \"add\"\n      ## Default case.  Doesn't require action.\n\n    case \"new\"\n      ## Ordinarily, create a new figure to hold plot.\n      ## But, if user has requested preparing a specific axis, then\n      ## use the existing figure to hold the requested axis.\n      if (isempty (ca))\n        cf = figure ();\n      endif\n\n    case \"replace\"\n      if (do_reset)\n        kids = allchild (cf);\n        if (! isempty (ca))\n          kids(kids == ca) = [];\n        endif\n        delete (kids);\n        reset (cf);\n      endif\n      set (cf, \"nextplot\", \"add\");  # Matlab compatibility\n\n    case \"replacechildren\"\n      kids = get (cf, \"children\");\n      if (! isempty (ca))\n        kids(kids == ca) = [];\n      endif\n      delete (kids);\n      set (cf, \"nextplot\", \"add\");  # Matlab compatibility\n\n  endswitch\n\n  do_reset = true;\n  if (isempty (ca))\n    ca = get (cf, \"currentaxes\");\n    if (isempty (ca))\n      ca = axes ();\n      do_reset = false;\n    endif\n  else\n    ## FIXME: Does ca need to be re-parented as well?\n    set (cf, \"currentaxes\", ca);\n  endif\n\n  anp = get (ca, \"nextplot\");\n  switch (anp)\n    case \"add\"\n      ## Default case.  Doesn't require action.\n\n    case \"replace\"\n      if (isprop (ca, \"__plotyy_axes__\") ...\n          && ! any (strcmp({dbstack().name}, \"plotyy\")))\n        ## Hack for bug #44246.  There is no way to reset or remove a property\n        ## created with addproperty short of deleting the object.\n        old_units = get (ca, \"units\");\n        old_position = get (ca, \"position\");\n        delete (ca);\n        ca = axes (\"units\", old_units, \"position\", old_position);\n      elseif (do_reset)\n        rcn = getappdata (ca, \"__subplotrcn__\");\n        delete (allchild (ca));\n        reset (ca);\n        ## Reinstall listeners for subplot\n        if (! isempty (rcn))\n          subplot (rcn{:}, ca)\n        endif\n      endif\n\n    ## FIXME: Uncomment when \"replaceall\" property value added to axes\n    #{\n    ## Only difference over \"replace\" is that both axes of plotyy are cleared\n    case \"replaceall\"\n      if (isprop (ca, \"__plotyy_axes__\") ...\n          && ! any (strcmp({dbstack().name}, \"plotyy\")))\n        ## Hack for bug #44246.  There is no way to reset or remove a property\n        ## created with addproperty short of deleting the object.\n        ca2 = get (ca, '__plotyy_axes__');\n        ca2(ca2 == ca) = [];\n        old_units = get (ca, \"units\");\n        old_position = get (ca, \"position\");\n        delete (ca);\n        ca = axes (\"units\", old_units, \"position\", old_position);\n        old_units = get (ca2, \"units\");\n        old_position = get (ca2, \"position\");\n        delete (ca2);\n        axes (\"units\", old_units, \"position\", old_position);\n      elseif (do_reset)\n        rcn = getappdata (ca, \"__subplotrcn__\");\n        delete (allchild (ca));\n        reset (ca);\n        ## Reinstall listeners for subplot\n        if (! isempty (rcn))\n          subplot (rcn{:}, ca)\n        endif\n      endif\n    #}\n\n    case \"replacechildren\"\n      delete (get (ca, \"children\"));\n      set (ca, \"colororderindex\", 1, \"linestyleorderindex\", 1);\n\n  endswitch\n\n  ## Restore figure and axes if necessary\n  if (! isempty (old_cf))\n    set (0, 'currentfigure', old_cf);\n    cf = old_cf;\n  endif\n\n  if (nargout > 0)\n    hax = ca;\n  endif\n\nendfunction\n\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   p = plot ([0, 1]);\n%!   hax = newplot ();\n%!   assert (hax, gca);\n%!   assert (isempty (get (gca, \"children\")));\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test double axes with plotyy\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"units\", \"normalized\", \"position\", [0.1, 0.1, 0.8, 0.3]);\n%!   plotyy (hax, 1:4, 1:4, 1:4, 4:-1:1);\n%!   hax2 = newplot ();\n%!   assert (get (hax2, \"units\"), \"normalized\");\n%!   assert (get (hax2, \"position\"), [0.1, 0.1, 0.8, 0.3]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\n## Test that current figure is preserved\n%!test\n%! hf1 = figure ('visible', 'off');\n%! hax1 = axes ();\n%! hf2 = figure ('visible', 'off');\n%! hax2 = axes;\n%! unwind_protect\n%!   cf = gcf ();\n%!   ca = gca ();\n%!   hax = newplot (hax1);\n%!   assert (gcf (), cf);\n%!   assert (gca (), ca);\n%!   assert (hax, hax1);\n%! unwind_protect_cleanup\n%!   close ([hf1, hf2]);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/openfig.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This filename is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n## your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the filename COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} openfig\n## @deftypefnx {} {} openfig (@var{filename})\n## @deftypefnx {} {} openfig (@dots{}, @var{copies})\n## @deftypefnx {} {} openfig (@dots{}, @var{visibility})\n## @deftypefnx {} {@var{h} =} openfig (@dots{})\n## Read saved figure window(s) from @var{filename} and return graphics\n## handle(s) @var{h}.\n##\n## By default, @var{filename} is @qcode{\"Untitled.fig\"}.  If a full path is not\n## specified, the file opened will be the first one encountered in the load\n## path.  If @var{filename} is not found and does not have an extension, a\n## search will take place for the first file in the load path with extension\n## @qcode{\".fig\"} or @qcode{\".ofig\"}, in that order.\n##\n## @var{copies} is an optional input indicating whether a new figure should\n## be created (@qcode{\"new\"}) or whether an existing figure may be reused\n## (@qcode{\"reuse\"}).  An existing figure may be reused if the\n## @qcode{\"FileName\"} property matches the specified input @var{filename}.\n## When a figure is reused it becomes the active figure and is shown on top\n## of other figures.  If the figure was offscreen, it is re-positioned to be\n## onscreen.  The default value for @var{copies} is @qcode{\"new\"}.\n##\n## @var{visibility} is an optional input indicating whether to show the figure\n## (@qcode{\"visible\"}) or not (@qcode{\"invisible\"}).  When @var{visibility} is\n## specified as an input to @code{openfig} it overrides the visibility setting\n## stored in @var{filename}.\n##\n## @seealso{open, hgload, savefig, struct2hdl}\n## @end deftypefn\n\nfunction h = openfig (filename = \"Untitled.fig\", varargin)\n\n  if (nargin > 3)\n    print_usage ();\n  endif\n\n  ## Check input filename\n  if (isempty (file_in_loadpath (filename)))\n    [d,n,ext] = fileparts (filename);\n    if (isempty (ext))\n      filename = fullfile (d, [n \".fig\"]);\n      if (isempty (file_in_loadpath (filename)))\n        filename = fullfile (d, [n \".ofig\"]);\n        if (isempty (file_in_loadpath (filename)))\n          error (\"openfig: cannot find file '%s'\", filename);\n        endif\n      endif\n    else\n      error (\"openfig: cannot find file '%s'\", filename);\n    endif\n  endif\n  filename = file_in_loadpath (filename);\n\n  ## Process optional arguments\n  copies = true;\n  visibility = {};\n  for i = 1:numel (varargin)\n    if (! ischar (varargin{i}))\n      error (\"openfig: input argument %d must be a string\", i+1);\n    endif\n    switch (lower (varargin{i}))\n      case \"reuse\"\n        copies = false;\n      case \"new\"\n        copies = true;\n      case \"visible\"\n        visibility = {\"visible\", \"on\"};\n      case \"invisible\"\n        visibility = {\"visible\", \"off\"};\n      otherwise\n        error (\"openfig: unknown option '%s'\", varargin{i});\n    endswitch\n  endfor\n\n  ## Reuse an existing figure?\n  if (! copies)\n    htmp = findobj (allchild (0), \"type\", \"figure\", \"FileName\", filename);\n    if (! isempty (htmp))\n      htmp = htmp(end);\n      if (! isempty (visibility))\n        set (htmp, visibility{:});\n      endif\n      movegui (htmp, \"onscreen\");\n      if (nargout > 0)\n        h = htmp;\n      endif\n      return;\n    endif\n  endif\n\n  ## Load graphics objects from file\n  prop_struct = cell2struct (visibility(2:2:end), visibility(1:2:end), 2);\n  htmp = hgload (filename, prop_struct);\n  set (htmp, \"FileName\", filename);\n\n  if (nargout > 0)\n    h = htmp;\n  endif\n\nendfunction\n\n\n%!test\n%! unwind_protect\n%!   h1 = figure (\"visible\", \"off\");\n%!   ftmp = [tempname() \".ofig\"];\n%!   hgsave (h1, ftmp);\n%!   close (h1);\n%!   h2 = openfig (ftmp, \"new\", \"invisible\");\n%!   h3 = openfig (ftmp, \"reuse\");\n%!   assert (h2 == h3);\n%!   close (h2);\n%! unwind_protect_cleanup\n%!   unlink (ftmp);\n%!   try, close (h1); end_try_catch\n%!   try, close (h2); end_try_catch\n%!   try, close (h3); end_try_catch\n%! end_unwind_protect\n\n%!error openfig (1, 2, 3, 4)\n%!error <cannot find file> openfig (\"%%_A_REALLY_UNLIKELY_FILENAME_%%\")\n%!error <cannot find file> openfig (\"%%_A_REALLY_UNLIKELY_FILENAME_%%.fig\")\n%!error <input argument 3 must be a string>\n%! unwind_protect\n%!   h = figure (\"visible\", \"off\");\n%!   ftmp = [tempname() \".ofig\"];\n%!   hgsave (h, ftmp);\n%!   openfig (ftmp, \"new\", [1, 2, 3]);\n%! unwind_protect_cleanup\n%!   unlink (ftmp);\n%!   close (h);\n%! end_unwind_protect\n%!error <unknown option 'foobar'>\n%! unwind_protect\n%!   h = figure (\"visible\", \"off\");\n%!   ftmp = [tempname() \".ofig\"];\n%!   hgsave (h, ftmp);\n%!   openfig (ftmp, \"foobar\");\n%! unwind_protect_cleanup\n%!   unlink (ftmp);\n%!   close (h);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/pan.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} pan\n## @deftypefnx {} {} pan on\n## @deftypefnx {} {} pan off\n## @deftypefnx {} {} pan xon\n## @deftypefnx {} {} pan yon\n## @deftypefnx {} {} pan (@var{hfig}, @var{option})\n## Control the interactive panning mode of a figure in the GUI.\n##\n## Given the option @qcode{\"on\"} or @qcode{\"off\"}, set the interactive\n## pan mode on or off.\n##\n## With no arguments, toggle the current pan mode on or off.\n##\n## Given the option @qcode{\"xon\"} or @qcode{\"yon\"}, enable pan mode\n## for the x-axis or y-axis only.\n##\n## If the first argument @var{hfig} is a figure, then operate on the given\n## figure rather than the current figure as returned by @code{gcf}.\n##\n## @seealso{rotate3d, zoom}\n## @end deftypefn\n\nfunction pan (hfig, option)\n\n  ## FIXME: Presumably should implement this for Matlab compatibility.\n  if (nargin == 1 && nargout > 0 && isfigure (hfig))\n    error (\"pan: syntax 'handle = pan (hfig)' not implemented\");\n  endif\n\n  if (nargin == 0)\n    hfig = gcf ();\n  else\n    if (nargin == 1)\n      option = hfig;\n      hfig = gcf ();\n    else\n      if (! isfigure (hfig))\n        error (\"pan: invalid figure handle HFIG\");\n      endif\n    endif\n\n    if (! ischar (option))\n      error (\"pan: OPTION must be a string\");\n    endif\n  endif\n\n  if (nargin == 0)\n    pm = get (hfig, \"__pan_mode__\");\n    if (strcmp (pm.Enable, \"on\"))\n      pm.Enable = \"off\";\n    else\n      pm.Enable = \"on\";\n    endif\n    set (hfig, \"__pan_mode__\", pm);\n    update_mouse_mode (hfig, pm.Enable);\n  else\n    switch (option)\n      case {\"on\", \"off\", \"xon\", \"yon\"}\n        pm = get (hfig, \"__pan_mode__\");\n        switch (option)\n          case {\"on\", \"off\"}\n            pm.Enable = option;\n            pm.Motion = \"both\";\n          case \"xon\"\n            pm.Enable = \"on\";\n            pm.Motion = \"horizontal\";\n          case \"yon\"\n            pm.Enable = \"on\";\n            pm.Motion = \"vertical\";\n        endswitch\n        set (hfig, \"__pan_mode__\", pm);\n        update_mouse_mode (hfig, option);\n      otherwise\n        error (\"pan: unrecognized OPTION '%s'\", option);\n    endswitch\n  endif\n\nendfunction\n\nfunction update_mouse_mode (hfig, arg)\n\n  if (strcmp (arg, \"off\"))\n    set (hfig, \"__mouse_mode__\", \"none\");\n  else\n    ## FIXME: Is there a better way other than calling these functions\n    ##        to set the other mouse mode Enable fields to \"off\"?\n    rotate3d (hfig, \"off\");\n    zoom (hfig, \"off\");\n    set (hfig, \"__mouse_mode__\", \"pan\");\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/print.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} print ()\n## @deftypefnx {} {} print (@var{options})\n## @deftypefnx {} {} print (@var{filename}, @var{options})\n## @deftypefnx {} {} print (@var{hfig}, @dots{})\n## @deftypefnx {} {@var{RGB} =} print (@qcode{\"-RGBImage\"}, @dots{})\n## Format a figure for printing and either save it to a file, send it to a\n## printer, or return an RGB image.\n##\n## @var{filename} defines the name of the output file.  If the filename has\n## no suffix then one is inferred from the specified device and appended to the\n## filename.  When neither a filename nor the @qcode{\"-RGBImage\"} option is\n## present, the output is sent to the printer.  The various options and\n## filename arguments may be given in any order, except for the figure handle\n## argument @var{hfig} which must be first if it is present.\n##\n## Example: Print to a file using PDF and JPEG formats.\n##\n## @example\n## @group\n## figure (1);\n## clf ();\n## surf (peaks);\n## print figure1.pdf    # The extension specifies the format\n## print -djpg figure1  # Will produce \"figure1.jpg\" file\n## @end group\n## @end example\n##\n## If the first argument is a handle @var{hfig} to a figure object then it\n## specifies the figure to print.  By default, the current figure returned\n## by @code{gcf} is printed.\n##\n## For outputs to paged formats, for example, PostScript and PDF, the page size\n## is specified by the figure's @code{papersize} property together with the\n## @code{paperunits} property.  The location and size of the plot on the page\n## are specified by the figure's @code{paperposition} property.  The\n## orientation of the page is specified by the figure's @code{paperorientation}\n## property.\n##\n## For non-page formats---for example, image formats like JPEG---the width and\n## height of the output are specified by the figure's @code{paperposition(3:4)}\n## property values.\n##\n## The @code{print} command supports many @var{options}:\n##\n## @table @code\n## @item -f@var{h}\n##   Specify the handle, @var{h}, of the figure to be printed.\n##\n## Example: Print figure 1.\n##\n## @example\n## @group\n## figure (1);\n## clf ();\n## surf (peaks);\n## figure (2);\n## print -f1 figure1.pdf\n## ## Equivalent functional form:\n## print (1, \"figure1.pdf\")\n## @end group\n## @end example\n##\n## @item -P@var{printer}\n##   Set the @var{printer} name to which the plot is sent if no @var{filename}\n## is specified.\n##\n## Example: Print to printer named PS_printer using PostScript format.\n##\n## @example\n## @group\n## clf ();\n## surf (peaks);\n## print -dpswrite -PPS_printer\n## @end group\n## @end example\n##\n## @item -RGBImage\n##   Return an M-by-N-by-3 RGB image of the figure.  The size of the image\n## depends on the formatting options.  This is similar to taking a screen\n## capture of the plot, but formatting options may be changed such as the\n## resolution or monochrome/color.\n##\n## Example: Get the pixels of a figure image.\n##\n## @example\n## @group\n## clf ();\n## surf (peaks);\n## @var{rgb} = print (\"-RGBImage\");\n## @end group\n## @end example\n##\n## @item  -image | -opengl\n## @itemx -vector | -painters\n##   Specifies whether the pixel-based renderer (@option{-image} or\n## @option{-opengl}) or vector-based renderer (@option{-vector} or\n## @option{-painters}) is used.  This is equivalent to changing the figure's\n## @qcode{\"Renderer\"} property.  When the figure\n## @nospell{@qcode{\"RendererMode\"}} property is @qcode{\"auto\"} (the default)\n## Octave will use the @qcode{\"opengl\"} renderer for raster formats (e.g.,\n## JPEG) and @qcode{\"painters\"} for vector formats (e.g., PDF)@.  These options\n## are only supported for the \"qt\" graphics toolkit.\n##\n## @item  -svgconvert (default)\n## @itemx -nosvgconvert\n##   When using the @option{-painters} renderer, this enables or disables the\n## SVG based backend toolchain with enhanced characteristics:\n##\n## @table @asis\n## @item Font handling:\n## For interpreters \"none\" and \"tex\", the actual font is embedded in the output\n## file which allows for printing arbitrary characters and fonts in all vector\n## formats.\n##\n## Strings using the @qcode{\"latex\"} interpreter, are rendered using path\n## objects.  This looks good but note that textual info (font,\n## characters@dots{}) are lost.\n##\n## @item Output Simplification:\n## By default, the option @option{-painters} renders patch and surface objects\n## using assemblies of triangles.  This may lead to anti-aliasing artifacts\n## when viewing the file.  The @option{-svgconvert} option reconstructs\n## polygons in order to avoid those artifacts (particularly for 2-D figures).\n##\n## @item Transparency:\n## Allows for printing transparent graphics objects in PDF format.\n## For PostScript formats the presence of any transparent object will cause the\n## output to be rasterized.\n## @end table\n##\n## Caution: If Octave was built against Qt version earlier than 5.13,\n## @option{-svgconvert} may lead to inaccurate rendering of image objects.\n##\n## @item  -polymerge\n## @itemx -nopolymerge\n## @itemx -polymerge-all\n##   When using the SVG based backend @option{-svgconvert}, faces are rendered\n## as triangles.  In some cases, some viewers might display fine lines where\n## those triangles share an edge.  These options control whether all triangles\n## that share edges are merged into polygons (@option{-polymerge-all} which\n## might take some time for graphics consisting of many triangles -- including\n## line markers), only consecutive polygons are merged (@option{-polymerge}),\n## or no triangles are merged at all (@option{-no-polymerge}).  By default,\n## only consecutive triangles sharing an edge are merged, unless the printed\n## figure contains patch or surface graphics objects in which case all\n## triangles that are sharing an edge are merged.\n##\n## @item  -portrait\n## @itemx -landscape\n##   Specify the orientation of the plot for printed output.\n## For non-printed output the aspect ratio of the output corresponds to the\n## plot area defined by the @qcode{\"paperposition\"} property in the\n## orientation specified.  This option is equivalent to changing the figure's\n## @qcode{\"paperorientation\"} property.\n##\n## @item  -fillpage\n## @itemx -bestfit\n##   When using a page-based format (PDF, PostScript, printer) ignore the\n## @qcode{\"paperposition\"} property and have the plot occupy the entire page.\n## The option @option{-fillpage} will stretch the plot to occupy the page with\n## 0.25 inch margins all around.  The option @option{-bestfit} will expand the\n## plot to take up as much room as possible on the page @strong{without}\n## distorting the original aspect ratio of the plot.\n##\n## @item  -color\n## @itemx -mono\n##   Color or monochrome output.\n##\n## @item  -solid\n## @itemx -dashed\n##   Force all lines to be solid or dashed, respectively.\n##\n## @item -noui\n##   Don't print uicontrol objects such as pushbuttons which may overlay the\n## plot.  This is the default behavior and it is not possible to include\n## uicontrol objects in the output without using an external screen capture\n## tool.\n##\n## @item -r@var{NUM}\n##   Resolution of bitmaps in dots per inch (DPI).  For both metafiles and SVG\n## the default is the screen resolution; for other formats the default is 150\n## DPI@.  To specify screen resolution, use @qcode{\"-r0\"}.\n##\n## Example: high resolution raster output.\n##\n## @example\n## @group\n## clf ();\n## surf (peaks (), \"facelighting\", \"gouraud\");\n## light ();\n## print (\"-r600\", \"lit_peaks.png\");\n## @end group\n## @end example\n##\n## @item -S@var{xsize},@var{ysize}\n##   Plot size in pixels for raster formats including PNG, JPEG, PNG, and\n## @emph{unusually} SVG@.  For all vector formats, including PDF, PS, and EPS,\n## the plot size is specified in points.  This option is equivalent to changing\n## the width and height of the output by setting the figure property\n## @code{paperposition(3:4)}.  When using the command form of the print\n## function you must quote the @var{xsize},@var{ysize} option to prevent the\n## Octave interpreter from recognizing the embedded comma (',').  For example,\n## by writing @w{\"-S640,480\"}.\n##\n## @item  -tight\n## @itemx -loose\n##   Force a tight or loose bounding box for EPS files.  The default is tight.\n##\n## @item -@var{preview}\n##   Add a preview to EPS files.  Supported formats are:\n##\n##   @table @code\n##   @item -interchange\n##     Provide an interchange preview.\n##\n##   @item -metafile\n##     Provide a metafile preview.\n##\n##   @item -pict\n##     Provide a pict preview.\n##\n##   @item -tiff\n##     Provide a TIFF preview.\n##   @end table\n##\n## @item -append\n##   Append PostScript or PDF output to an existing file of the same type.\n##\n## @item  -F@var{fontname}\n## @itemx -F@var{fontname}:@var{size}\n## @itemx -F:@var{size}\n##   Use @var{fontname} and/or @var{fontsize} for all text.\n## @var{fontname} is ignored for some devices: fig, etc.\n##\n## @item -d@var{device}\n##   The available output format is specified by the option @var{device}, and\n## is one of the following (devices marked with a @qcode{'*'} are only\n## available with the Gnuplot toolkit):\n##\n## Vector Formats\n##\n##   @table @code\n##   @item svg\n##     Scalable Vector Graphics.\n##\n##   @item  pdf\n##   @itemx pdfcrop\n##     Portable Document Format.  The @code{pdf} device formats the figure for\n## printing on paper.  The size of the surrounding page and the position of the\n## figure inside the page are defined by the\n## @ref{XREFfigurepaperorientation,,paper* figure properties}.\n##\n## Use @code{pdfcrop} if you don't want the surrounding page.\n##\n## Caution: with @option{-nosvgconvert} option, PDF inherits the same\n## limitations as PostScript (limited set of fonts and lack of transparency).\n##\n##   @item  eps(2)\n##   @itemx epsc(2)\n##     Encapsulated PostScript (level 1 and 2, mono and color).\n##\n## The OpenGL-based graphics toolkits always generate PostScript level 3.0.\n## They have limited support for text unless using the @option{-svgconvert}\n## option (the default).\n## Limitations include using only ASCII characters (e.g., no Greek letters)\n## and support for just three base PostScript fonts: Helvetica (the default),\n## Times, or Courier.  Any other font will be replaced by Helvetica.\n##\n##   @item  ps(2)\n##   @itemx psc(2)\n##     Same as @code{eps} except that the figure is formatted for printing on\n## paper.  The size of the surrounding page and position of the figure inside\n## the page are defined by the\n## @ref{XREFfigurepaperorientation,,paper* figure properties}.\n##\n##   @item  pslatex\n##   @itemx epslatex\n##   @itemx pdflatex\n##   @itemx pslatexstandalone\n##   @itemx epslatexstandalone\n##   @itemx pdflatexstandalone\n##     Generate a @LaTeX{} file @file{@var{filename}.tex} for the text portions\n## of a plot and a file @file{@var{filename}.(ps|eps|pdf)} for the remaining\n## graphics.  The graphics file suffix .ps|eps|pdf is determined by the\n## specified device type.  The @LaTeX{} file produced by the @samp{standalone}\n## option can be processed directly by @LaTeX{}.  The file generated without\n## the @samp{standalone} option is intended to be included from another\n## @LaTeX{} document.  In either case, the @LaTeX{} file contains an\n## @code{\\includegraphics} command so that the generated graphics file is\n## automatically included when the @LaTeX{} file is processed.  The text that\n## is written to the @LaTeX{} file contains the strings @strong{exactly} as\n## they were specified in the plot.  If any special characters of the @TeX{}\n## mode interpreter were used, the file must be edited before @LaTeX{}\n## processing.  Specifically, the special characters must be enclosed with\n## dollar signs @w{(@code{$ @dots{} $})}, and other characters that are\n## recognized by @LaTeX{} may also need editing (e.g., braces).  The\n## @samp{pdflatex} device, and any of the @samp{standalone} formats, are not\n## available with the Gnuplot toolkit.\n##\n##   @item  epscairo*\n##   @itemx pdfcairo*\n##   @itemx epscairolatex*\n##   @itemx pdfcairolatex*\n##   @itemx epscairolatexstandalone*\n##   @itemx pdfcairolatexstandalone*\n##     Generate output with Cairo renderer.  The devices @code{epscairo} and\n## @code{pdfcairo} are synonymous with the @code{epsc} device.  The @LaTeX{}\n## variants generate a @LaTeX{} file, @file{@var{filename}.tex}, for the text\n## portions of a plot, and an image file, @file{@var{filename}.(eps|pdf)}, for\n## the graph portion of the plot.  The @samp{standalone} variants behave as\n## described for @samp{epslatexstandalone} above.\n##\n##   @item canvas*\n##     Javascript-based drawing on an HTML5 canvas viewable in a web browser.\n##\n##   @item  emf\n##   @itemx meta\n##     Microsoft Enhanced Metafile\n##\n##   @item fig\n##     XFig.  For the Gnuplot graphics toolkit, the additional options\n## @option{-textspecial} or @option{-textnormal} (default) can be used to\n## control whether the special flag should be set for the text in the figure.\n##\n##   @item  latex*\n##   @itemx eepic*\n##     @LaTeX{} picture environment and extended picture environment.\n##\n##   @item  tikz\n##   @itemx tikzstandalone*\n##     Generate a @LaTeX{} file using PGF/TikZ format.  The OpenGL-based\n## toolkits create a PGF file while Gnuplot creates a TikZ file.  The\n## @samp{tikzstandalone} device produces a @LaTeX{} document which includes the\n## TikZ file.\n##\n##   @end table\n##\n## Raster Formats\n##\n##   @table @code\n##   @item png\n##     Portable Network Graphics\n##\n##   @item  jpg\n##   @itemx jpeg\n##     JPEG image\n##\n##   @item  tif\n##   @itemx tiff\n##   @itemx tiffn\n##     TIFF image with LZW compression (@nospell{tif}, tiff) or uncompressed\n## (@nospell{tiffn}).\n##\n##   @item gif\n##     GIF image\n##\n##   @item pbm\n##     PBMplus\n##\n##   @item dumb*\n##     ASCII art\n##\n##   @end table\n##\n##   If the device is omitted, it is inferred from the file extension,\n## or if there is no filename then it is sent to the printer as PostScript.\n##\n## @item -d@var{ghostscript_device}\n##   Additional devices are supported by Ghostscript.\n## Some examples are:\n##\n##   @table @code\n##   @item ljet2p\n##     HP LaserJet @nospell{IIP}\n##\n##   @item pcx24b\n##     24-bit color PCX file format\n##\n##   @item ppm\n##     Portable Pixel Map file format\n##   @end table\n##\n##   For a complete list of available formats and devices type\n## @kbd{system (\"gs -h\")}.\n##\n##   When Ghostscript output is sent to a printer the size is determined by\n## the figure's @qcode{\"papersize\"} property.  When the output is sent to a\n## file the size is determined by the plot box defined by the figure's\n## @qcode{\"paperposition\"} property.\n##\n## @item -G@var{ghostscript_command}\n##   Specify the command for calling Ghostscript.  For Unix the default is\n## @qcode{\"gs\"} and for Windows it is @qcode{\"gswin32c\"}.\n##\n## @item  -TextAlphaBits=@var{n}\n## @itemx -GraphicsAlphaBits=@var{n}\n##   Octave is able to produce output for various printers, bitmaps, and\n## vector formats by using Ghostscript.  For bitmap and printer output\n## anti-aliasing is applied using Ghostscript's TextAlphaBits and\n## GraphicsAlphaBits options.  The default number of bits are 4 and 1\n## respectively.  Allowed values for @var{N} are 1, 2, or 4.\n##\n## @item -no-append-file-extension\n##   With this option, @var{filename} is used verbatim.  That means no file\n## extension matching the file format is appended automatically.\n## @end table\n##\n## @seealso{saveas, getframe, savefig, hgsave, orient, figure}\n## @end deftypefn\n\nfunction RGB = print (varargin)\n\n  opts = __print_parse_opts__ (varargin{:});\n\n  ## Check the requested file is writable\n  if (! opts.rgb_output)\n    folder = fileparts (opts.name);\n    if (! isempty (folder) && ! isfolder (folder))\n      error (\"print: directory %s does not exist\", folder);\n    endif\n\n    do_unlink = (exist (opts.name, \"file\") != 2);\n    fid = fopen (opts.name, \"a\");\n    if (fid == -1)\n      error (\"print: cannot open file %s for writing\", opts.name);\n    endif\n    fclose (fid);\n    if (do_unlink)\n      unlink (opts.name);\n    endif\n  endif\n\n  opts.pstoedit_cmd = @pstoedit;\n  opts.fig2dev_cmd = @fig2dev;\n  opts.latex_standalone = @latex_standalone;\n  opts.lpr_cmd = @lpr;\n  opts.epstool_cmd = @epstool;\n  opts.svgconvert_cmd = @svgconvert;\n\n  if (isempty (opts.figure) || ! isfigure (opts.figure))\n    error (\"print: no figure to print\");\n  endif\n\n  if (isempty (findall (opts.figure, \"-depth\", 1, \"type\", \"axes\")))\n    error (\"print: no axes object in figure to print\");\n  endif\n\n  orig_figure = get (0, \"currentfigure\");\n  set (0, \"currentfigure\", opts.figure);\n\n  if (opts.append_to_file)\n    [~, ~, ext] = fileparts (opts.ghostscript.output);\n    opts.ghostscript.prepend = [tempname() ext];\n    copyfile (opts.ghostscript.output, opts.ghostscript.prepend);\n  endif\n\n  unwind_protect\n\n    ## Modify properties as specified by options\n    tk = get (opts.figure, \"__graphics_toolkit__\");\n    props = [];\n    nfig = 0;\n\n    drawnow ();\n\n    ## Set the __printing__ property first\n    props(1).h = opts.figure;\n    props(1).name = \"__printing__\";\n    props(1).value = {\"off\"};\n    set (opts.figure, \"__printing__\", \"on\");\n    nfig += 1;\n\n    ## print() requires children of axes to have units = \"normalized\" or \"data\"\n    ## FIXME: Bug #59015.  The only graphics object type to which this\n    ## requirement applies seems to be 'text' objects.  It is simpler, and\n    ## clearer, to just select those objects.  The old code is left commented\n    ## out until sufficient testing has been done.\n    ## Change made: 2020/09/02.\n    ##hobj = findall (opts.figure, \"-not\", \"type\", \"figure\", ...\n    ##                \"-not\", \"type\", \"axes\", \"-not\", \"type\", \"hggroup\", ...\n    ##                \"-property\", \"units\", ...\n    ##                \"-not\", \"units\", \"normalized\", \"-not\", \"units\", \"data\");\n    ##hobj(strncmp (get (hobj, \"type\"), \"ui\", 2)) = [];\n\n    hobj = findall (opts.figure, \"type\", \"text\",\n                    \"-not\", \"units\", \"normalized\", \"-not\", \"units\", \"data\");\n    for n = 1:numel (hobj)\n      props(end+1).h = hobj(n);\n      props(end).name = \"units\";\n      props(end).value = {get(hobj(n), \"units\")};\n      set (hobj(n), \"units\", \"data\");\n      nfig += 1;\n    endfor\n\n    if (strcmp (opts.renderer, \"opengl\"))\n      ## Scale the figure to reach the required resolution\n      scale = opts.ghostscript.resolution / 72;\n      if (scale != 1)\n        props(end+1).h = opts.figure;\n        props(end).name = \"__device_pixel_ratio__\";\n        props(end).value{1} = get (opts.figure, \"__device_pixel_ratio__\");\n        set (opts.figure, \"__device_pixel_ratio__\", scale);\n        nfig += 1;\n      endif\n    elseif (strcmp (tk, \"qt\"))\n      ## Don't account for the actual pixel density\n      props(end+1).h = opts.figure;\n      props(end).name = \"__device_pixel_ratio__\";\n      props(end).value = {get(opts.figure, \"__device_pixel_ratio__\")};\n      set (opts.figure, \"__device_pixel_ratio__\", 1);\n      nfig += 1;\n    endif\n\n    ## print() requires axes units = \"normalized\"\n    hax = findall (opts.figure, \"-depth\", 1, \"type\", \"axes\", ...\n      \"-not\", \"units\", \"normalized\");\n    for n = 1:numel (hax)\n      props(end+1).h = hax(n);\n      props(end).name = \"units\";\n      props(end).value = {get(hax(n), \"units\")};\n      set (hax(n), \"units\", \"normalized\");\n      nfig += 1;\n    endfor\n\n    ## With the -painters (gl2ps) renderer, line transparency is only\n    ## handled for svg and pdf outputs using svgconvert.\n    ## Otherwise, switch grid lines color to light gray so that the image\n    ## output approximately matches on-screen experience.\n    hax = findall (opts.figure, \"type\", \"axes\");\n    if (! strcmp (tk, \"gnuplot\") && ! strcmp (opts.renderer, \"opengl\")\n        && ! (opts.svgconvert && strcmp (opts.devopt, \"pdfwrite\"))\n        && ! strcmp (opts.devopt, \"svg\"))\n      for n = 1:numel (hax)\n        if (strcmp (get (hax(n), \"gridcolormode\"), \"auto\"))\n          props(end+1).h = hax(n);\n          props(end).name = \"gridcolormode\";\n          props(end).value = {\"auto\"};\n          props(end+1).h = hax(n);\n          props(end).name = \"gridcolor\";\n          props(end).value = {get(hax(n), \"gridcolor\")};\n          set (hax(n), \"gridcolor\", [0.85 0.85 0.85]);\n          nfig += 2;\n        endif\n        if (strcmp (get (hax(n), \"gridalphamode\"), \"auto\"))\n          props(end+1).h = hax(n);\n          props(end).name = \"gridalphamode\";\n          props(end).value = {\"auto\"};\n          props(end+1).h = hax(n);\n          props(end).name = \"gridalpha\";\n          props(end).value = {get(hax(n), \"gridalpha\")};\n          set (hax(n), \"gridalpha\", 1);\n          nfig += 2;\n        endif\n\n        if (strcmp (get (hax(n), \"minorgridcolormode\"), \"auto\"))\n          props(end+1).h = hax(n);\n          props(end).name = \"minorgridcolormode\";\n          props(end).value = {\"auto\"};\n          props(end+1).h = hax(n);\n          props(end).name = \"minorgridcolor\";\n          props(end).value = {get(hax(n), \"minorgridcolor\")};\n          set (hax(n), \"minorgridcolor\", [0.75 0.75 0.75]);\n          nfig += 2;\n        endif\n        if (strcmp (get (hax(n), \"minorgridalphamode\"), \"auto\"))\n          props(end+1).h = hax(n);\n          props(end).name = \"minorgridalphamode\";\n          props(end).value = {\"auto\"};\n          props(end+1).h = hax(n);\n          props(end).name = \"minorgridalpha\";\n          props(end).value = {get(hax(n), \"minorgridalpha\")};\n          set (hax(n), \"minorgridalpha\", 1);\n          nfig += 2;\n        endif\n      endfor\n    endif\n\n    ## print() requires figure units to be \"pixels\"\n    props(end+1).h = opts.figure;\n    props(end).name = \"units\";\n    props(end).value = {get(opts.figure, \"units\")};\n    set (opts.figure, \"units\", \"pixels\");\n    nfig += 1;\n\n    ## graphics toolkit translates figure position to eps bbox (points)\n    fpos = get (opts.figure, \"position\");\n    props(end+1).h = opts.figure;\n    props(end).name = \"position\";\n    props(end).value = {fpos};\n    fpos(3:4) = opts.canvas_size;\n    set (opts.figure, \"position\", fpos);\n    nfig += 1;\n\n    ## Implement InvertHardCopy option\n    do_hardcopy = strcmp (get (opts.figure, \"inverthardcopy\"), \"on\");\n\n    if (do_hardcopy)\n      ## Set figure background to white.\n      props(end+1).h = opts.figure;\n      props(end).name = \"color\";\n      props(end).value{1} = get (opts.figure, \"color\");\n      set (opts.figure, \"color\", \"white\");\n      nfig += 1;\n    endif\n\n    if (do_hardcopy)\n      ## Set background to white for all top-level axes objects\n      hax = findall (opts.figure, \"-depth\", 1, \"type\", \"axes\",\n                                  \"-not\", \"tag\", \"legend\",\n                                  \"-not\", \"color\", \"none\");\n      if (! isempty (hax))\n        for n = 1:numel (hax)\n          props(end+1).h = hax(n);\n          props(end).name = \"color\";\n          props(end).value{1} = get(hax(n), \"color\");\n          set (hax(n), \"color\", \"white\");\n          nfig += 1;\n        endfor\n      endif\n    endif\n\n    if (opts.force_solid != 0)\n      h = findall (opts.figure, \"-property\", \"linestyle\");\n      m = numel (props);\n      for n = 1:numel (h)\n        props(m+n).h = h(n);\n        props(m+n).name = \"linestyle\";\n        props(m+n).value = {get(h(n), \"linestyle\")};\n      endfor\n      if (opts.force_solid > 0)\n        linestyle = \"-\";\n      else\n        linestyle = \"--\";\n      endif\n      set (h, \"linestyle\", linestyle);\n    endif\n\n    if (opts.use_color < 0)\n      color_props = {\"color\", \"facecolor\", \"edgecolor\", \"colormap\"};\n      for c = 1:numel (color_props)\n        h = findall (opts.figure, \"-property\", color_props{c});\n        hnone = findall (opts.figure, color_props{c}, \"none\");\n        h = setdiff (h, hnone);\n        m = numel (props);\n        for n = 1:numel (h)\n          if (ishghandle (h(n)))\n            ## Need to verify objects exist since callbacks may delete objects\n            ## as the colors for others are modified.\n            rgb = get (h(n), color_props{c});\n            props(end+1).h = h(n);\n            props(end).name = color_props{c};\n            props(end).value = {get(h(n), color_props{c})};\n            if (isnumeric (rgb))\n              ## convert RGB color to RGB gray scale\n              xfer = repmat ([0.30, 0.59, 0.11], rows (rgb), 1);\n              ggg = repmat (sum (xfer .* rgb, 2), 1, 3);\n              set (h(n), color_props{c}, ggg);\n            endif\n          endif\n        endfor\n      endfor\n    endif\n\n    do_font = ! isempty (opts.font);\n    do_scalefontsize =  ! isempty (opts.scalefontsize) && opts.scalefontsize != 1;\n    do_fontsize = ! isempty (opts.fontsize) || do_scalefontsize;\n    if (do_font || do_fontsize)\n      h = findall (opts.figure, \"-property\", \"fontname\");\n      m = numel (props);\n      for n = 1:numel (h)\n        if (ishghandle (h(n)))\n          if (do_font)\n            props(end+1).h = h(n);\n            props(end).name = \"fontname\";\n            props(end).value = {get(h(n), \"fontname\")};\n          endif\n          if (do_fontsize)\n            props(end+1).h = h(n);\n            props(end).name = \"fontsize\";\n            props(end).value = {get(h(n), \"fontsize\")};\n          endif\n        endif\n      endfor\n      if (do_font)\n        set (h(ishghandle (h)), \"fontname\", opts.font);\n      endif\n      if (do_fontsize)\n        if (! isempty (opts.fontsize))\n          ## Changing all fontsizes to a fixed value\n          if (ischar (opts.fontsize))\n            fontsize = str2double (opts.fontsize);\n          else\n            fontsize = opts.fontsize;\n          endif\n          if (do_scalefontsize)\n            ## This is done to work around the bbox being whole numbers.\n            fontsize *= opts.scalefontsize;\n          endif\n\n          ## FIXME: legend child objects need to be acted on first.\n          ##        or legend fontsize callback will destroy them.\n          hlist = h(ishghandle (h));\n          haxes = strcmp (get (hlist, \"type\"), \"axes\");\n          set (hlist(! haxes), \"fontsize\", fontsize);\n          set (hlist(haxes), \"fontsize\", fontsize);\n\n        else\n          ## Scaling fonts\n          ## FIXME: legend child objects need to be acted on first.\n          ##        or legend fontsize callback will destroy them.\n          hlist = h(ishghandle (h));\n          haxes = strcmp (get (hlist, \"type\"), \"axes\");\n          for h = hlist(! haxes).'\n            fontsz = get (h, \"fontsize\");\n            set (h, \"fontsize\", fontsz * opts.scalefontsize);\n          endfor\n          for h = hlist(haxes).'\n            fontsz = get (h, \"fontsize\");\n            set (h, \"fontsize\", fontsz * opts.scalefontsize);\n          endfor\n\n        endif\n      endif\n    endif\n\n    ## When exporting latex files use \"latex\" for the ticklabelinterpreter.\n    ## It will format tick labels in log axes correctly\n    if (strfind (opts.devopt, \"latex\"))\n      ## Disable warnings about Latex being unsupported since Octave will be\n      ## passing Latex code directly to interpreter with no rendering.\n      warning (\"off\", \"Octave:text_interpreter\", \"local\");\n      h = findall (opts.figure, \"type\", \"axes\");\n      for n = 1:numel (h)\n        if (ishghandle (h(n)))\n          props(end+1).h = h(n);\n          props(end).name = \"ticklabelinterpreter\";\n          props(end).value = {get(h(n), \"ticklabelinterpreter\")};\n          set (h(n), \"ticklabelinterpreter\", \"latex\");\n        endif\n      endfor\n    endif\n\n    ## call the graphics toolkit print script\n    switch (tk)\n      case \"gnuplot\"\n        opts = __gnuplot_print__ (opts);\n      otherwise\n        if (strcmp (opts.renderer, \"opengl\"))\n          if (opts.rgb_output)\n            RGB = __get_frame__ (opts.figure);\n          else\n            compression = \"none\";\n\n            if (strcmp (opts.devopt, \"tiff\"))\n              compression = \"lzw\";\n            elseif (strcmp (opts.devopt, \"tiffn\"))\n              opts.devopt = \"tiff\";\n            endif\n\n            imwrite (__get_frame__ (opts.figure), opts.name, ...\n                     opts.devopt, \"Compression\", compression);\n          endif\n        else\n          opts = __opengl_print__ (opts);\n        endif\n    endswitch\n\n  unwind_protect_cleanup\n    ## restore modified properties\n    if (isstruct (props))\n      ## Restore figure position and units first\n      for n = nfig:-1:1\n        if (ishghandle (props(n).h))\n          set (props(n).h, props(n).name, props(n).value{1});\n        endif\n      endfor\n      for n = numel (props):-1:(nfig + 1)\n        if (ishghandle (props(n).h))\n          set (props(n).h, props(n).name, props(n).value{1});\n        endif\n      endfor\n    endif\n\n    ## Avoid a redraw since the figure should not have changed\n    ## FIXME: Bug #57552, marker sizes, requires that redraw be done.\n    ## set (gcf, \"__modified__\", \"off\");\n\n    ## Unlink temporary files\n    for n = 1:numel (opts.unlink)\n      [status, output] = unlink (opts.unlink{n});\n      if (status != 0)\n        warning (\"Octave:print:unlinkerror\", ...\n                 \"print: %s, '%s'\", output, opts.unlink{n});\n      endif\n    endfor\n  end_unwind_protect\n\n  if (isfigure (orig_figure))\n    set (0, \"currentfigure\", orig_figure);\n  endif\n\nendfunction\n\n## Print to file with and without file extension\n%!testif ; (have_window_system () && any (strcmp (\"qt\", available_graphics_toolkits ())))\n%! toolkit = graphics_toolkit ();\n%! graphics_toolkit (\"qt\");\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   x = 0:0.1:1;\n%!   hax = axes (hf);\n%!   plot (hax, x, x);\n%!   tmp_name = tempname ();\n%!   print (hf, tmp_name, \"-dpng\");\n%!   assert (isfile ([tmp_name \".png\"]));\n%!   unlink ([tmp_name \".png\"]);\n%!   print (hf, tmp_name, \"-dpng\", \"-no-append-file-extension\");\n%!   assert (isfile (tmp_name));\n%!   unlink (tmp_name);\n%! unwind_protect_cleanup\n%!   close (hf);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n%!error <a graphics handle>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   x = 0:0.1:1;\n%!   y1 = x;\n%!   y2 = 2*x;\n%!   ax = plotyy (x, y1, x, y2);\n%!   saveas (ax, [tempname(), \".png\"]);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n\nfunction cmd = epstool (opts, filein, fileout)\n\n  ## As epstool does not work with pipes, a subshell is used to\n  ## permit piping.  Since this solution does not work with the DOS\n  ## command shell, the -tight and -preview options are disabled if\n  ## output must be piped.\n\n  ## DOS Shell:\n  ##   gs.exe [...] -sOutputFile=<filein> - & epstool -bbox -preview-tiff <filein> <fileout> & del <filein>\n  ## Unix Shell:\n  ##   cat > <filein> ; epstool -bbox -preview-tiff <filein> <fileout> ; rm <filein>\n\n  dos_shell = (ispc () && ! isunix ());\n\n  ## HACK: Keep track of whether ghostscript supports epswrite or eps2write.\n  persistent epsdevice;\n  if (dos_shell && isempty (epsdevice))\n    if (isempty (opts.ghostscript.binary))\n      error (\"Octave:print:nogs\",\n             \"print: 'gs' (Ghostscript) is required for specified output format, but binary is not available in PATH\");\n    endif\n\n    [status, devlist] = system (sprintf (\"%s -h\", opts.ghostscript.binary));\n    if (isempty (strfind (devlist, \"eps2write\")))\n      epsdevice = \"epswrite\";\n    else\n      epsdevice = \"eps2write\";\n    endif\n  endif\n\n  cleanup = \"\";\n  if (nargin < 3)\n    fileout = opts.name;\n  elseif (isempty (fileout))\n    fileout = \"-\";\n  endif\n\n  if (nargin < 2 || strcmp (filein, \"-\") || isempty (filein))\n    pipein = true;\n    filein = [tempname() \".eps\"];\n    if (dos_shell)\n      cleanup = sprintf ('& del \"%s\" ', strrep (filein, '/', '\\'));\n    else\n      cleanup = sprintf ('; rm \"%s\" ', filein);\n    endif\n  else\n    pipein = false;\n    filein = [\"'\" strtrim(filein) \"'\"];\n  endif\n  if (strcmp (fileout, \"-\"))\n    pipeout = true;\n    fileout = [tempname() \".eps\"];\n    if (dos_shell)\n      cleanup = [cleanup, sprintf('& del \"%s\" ', strrep (fileout, '/', '\\'))];\n    else\n      cleanup = [cleanup, sprintf('; rm \"%s\" ', fileout)];\n    endif\n  else\n    pipeout = false;\n    fileout = [\"'\" strtrim(fileout) \"'\"];\n  endif\n\n  if (! isempty (opts.preview) && opts.tight)\n    warning (\"Octave:print:previewandtight\",\n             \"print: eps preview may not be combined with -tight\");\n  endif\n  if (! isempty (opts.preview) || opts.tight)\n\n    if (isempty (opts.epstool_binary))\n      error (\"Octave:print:noepstool\", \"print: 'epstool' is required for specified output format, but binary is not available in PATH\");\n    endif\n\n    if (opts.tight)\n      cmd = \"--copy --bbox\";\n    elseif (! isempty (opts.preview))\n      switch (opts.preview)\n        case \"tiff\"\n          cmd = sprintf (\"--add-%s-preview --device tiffg3\", opts.preview);\n        case {\"tiff6u\", \"tiff6p\", \"metafile\"}\n          cmd = sprintf (\"--add-%s-preview --device bmpgray\", opts.preview);\n        case {\"tiff4\", \"interchange\"}\n          cmd = sprintf (\"--add-%s-preview\", opts.preview);\n        case \"pict\"\n          cmd = sprintf (\"--add-%s-preview --mac-single\", opts.preview);\n        otherwise\n          error (\"Octave:print:invalidpreview\",\n                 \"print: epstool cannot include preview for format '%s'\",\n                 opts.preview);\n      endswitch\n      if (! isempty (opts.ghostscript.resolution))\n        cmd = sprintf (\"%s --dpi %d\", cmd, fix (opts.ghostscript.resolution));\n      endif\n    else\n      cmd = \"\";\n    endif\n    if (! isempty (cmd))\n      if (dos_shell)\n        ## ghostscript expects double, not single, quotes\n        fileout(fileout == \"'\") = '\"';\n        ## epstool implicitly uses ghostscript and it needs the command name\n        cmd = sprintf (\"%s --gs %s --quiet %s %s %s \", opts.epstool_binary,\n                       opts.ghostscript.binary, cmd, filein, fileout);\n      else\n        cmd = sprintf (\"%s --quiet %s %s %s \", opts.epstool_binary,\n                       cmd, filein, fileout);\n      endif\n    endif\n    if (pipein)\n      if (dos_shell)\n        filein(filein==\"'\") = '\"';\n        gs_cmd = __ghostscript__ (\"binary\", opts.ghostscript.binary,\n                                  \"device\", epsdevice,\n                                  \"source\", \"-\",\n                                  \"output\", filein);\n        cmd = sprintf (\"%s %s & %s\", gs_cmd, filein, cmd);\n      else\n        cmd = sprintf (\"cat > %s ; %s\", filein, cmd);\n      endif\n    endif\n    if (pipeout)\n      if (dos_shell)\n        cmd = sprintf (\"%s & type %s\", cmd, fileout);\n      else\n        cmd = sprintf (\"%s ; cat %s\", cmd, fileout);\n      endif\n    endif\n    if (! isempty (cleanup))\n      if (pipeout && dos_shell)\n        error (\"Octave:print:epstoolpipe\",\n               \"print: cannot pipe output of 'epstool' for DOS shell\");\n      elseif (pipeout)\n        cmd = sprintf (\"( %s %s )\", cmd, cleanup);\n      else\n        cmd = sprintf (\"%s %s\", cmd, cleanup);\n      endif\n    endif\n  else\n    if (pipein && pipeout)\n      if (dos_shell)\n        cmd = __ghostscript__ (\"binary\", opts.ghostscript.binary,\n                               \"device\", epsdevice,\n                               \"source\", \"-\",\n                               \"output\", \"-\");\n      else\n        cmd = \" cat \";\n      endif\n    elseif (pipein && ! pipeout)\n      if (dos_shell)\n        ## ghostscript expects double, not single, quotes\n        fileout(fileout==\"'\") = '\"';\n        cmd = __ghostscript__ (\"binary\", opts.ghostscript.binary,\n                               \"device\", epsdevice,\n                               \"source\", \"-\",\n                               \"output\", fileout);\n      else\n        cmd = sprintf (\" cat > %s \", fileout);\n      endif\n    elseif (! pipein && pipeout)\n      if (dos_shell)\n        cmd = sprintf (\" type %s \", filein);\n      else\n        cmd = sprintf (\" cat %s \", filein);\n      endif\n    else\n      if (dos_shell)\n        cmd = sprintf (\" copy %s %s \", filein, fileout);\n      else\n        cmd = sprintf (\" cp %s %s \", filein, fileout);\n      endif\n    endif\n  endif\n  if (opts.debug)\n    fprintf (\"epstool command: '%s'\\n\", cmd);\n  endif\n\nendfunction\n\nfunction cmd = fig2dev (opts, devopt)\n\n  if (nargin < 2)\n    devopt = opts.devopt;\n  endif\n\n  if (isempty (opts.fig2dev_binary))\n    error (\"Octave:print:nofig2dev\", \"print: 'fig2dev' is required for specified output format, but binary is not available in PATH\");\n  endif\n\n  dos_shell = (ispc () && ! isunix ());\n  if (dos_shell)\n    ## FIXME: Is this the right thing to do for DOS?\n    cmd = sprintf (\"%s -L %s 2> NUL\", opts.fig2dev_binary, devopt);\n  else\n    cmd = sprintf (\"%s -L %s 2> /dev/null\", opts.fig2dev_binary, devopt);\n  endif\n\n  if (opts.debug)\n    fprintf (\"fig2dev command: '%s'\\n\", cmd);\n  endif\n\nendfunction\n\nfunction latex_standalone (opts)\n\n  n = find (opts.name == \".\", 1, \"last\");\n  if (! isempty (n))\n    opts.name = opts.name(1:n-1);\n  endif\n  latexfile = [opts.name \".tex\"];\n\n  switch (opts.devopt)\n    case {\"pdflatexstandalone\"}\n      packages = \"\\\\usepackage{graphicx,color}\";\n    case {\"pslatexstandalone\"}\n      packages = \"\\\\usepackage{epsfig,color}\";\n    otherwise\n      packages = \"\\\\usepackage{epsfig,color}\";\n  endswitch\n\n  packages = {packages \"\\\\usepackage[utf8]{inputenc}\"};\n\n  papersize = sprintf (\"\\\\usepackage[papersize={%.2fbp,%.2fbp},text={%.2fbp,%.2fbp}]{geometry}\",\n                       fix (opts.canvas_size), fix (opts.canvas_size));\n\n  prepend = {\"\\\\documentclass{minimal}\", packages{:}, papersize, ...\n             \"\\\\begin{document}\", \"\\\\centering\"};\n  postpend = {\"\\\\end{document}\"};\n\n  fid = fopen (latexfile, \"r\");\n  if (fid < 0)\n    error (\"Octave:print:erroropeningfile\",\n           \"print: error opening file '%s'\", latexfile);\n  endif\n  latex = fscanf (fid, \"%c\", Inf);\n  status = fclose (fid);\n  if (status != 0)\n    error (\"Octave:print:errorclosingfile\",\n           \"print: error closing file '%s'\", latexfile);\n  endif\n\n  fid = fopen (latexfile, \"w\");\n  if (fid >= 0)\n    fprintf (fid, \"%s\\n\", prepend{:});\n    fprintf (fid, \"%s\", latex);\n    fprintf (fid, \"%s\\n\", postpend{:});\n    status = fclose (fid);\n    if (status != 0)\n      error (\"Octave:print:errorclosingfile\",\n             \"print: error closing file '%s'\", latexfile);\n    endif\n  else\n    error (\"Octave:print:erroropeningfile\",\n           \"print: error opening file '%s'\", latexfile);\n  endif\n\nendfunction\n\nfunction cmd = lpr (opts)\n\n  if (nargin < 2)\n    devopt = opts.devopt;\n  endif\n\n  if (! isempty (opts.lpr_binary))\n    cmd = opts.lpr_binary;\n    if (! isempty (opts.lpr_options))\n      cmd = sprintf (\"%s %s\", cmd, opts.lpr_options);\n    endif\n    if (! isempty (opts.printer))\n      cmd = sprintf (\"%s %s\", cmd, opts.printer);\n    endif\n  elseif (isempty (opts.lpr_binary))\n    error (\"Octave:print:nolpr\", \"print: 'lpr' not found in PATH\");\n  endif\n  if (opts.debug)\n    fprintf (\"lpr command: '%s'\\n\", cmd);\n  endif\n\nendfunction\n\nfunction cmd = pstoedit (opts, devopt, do_svg = true)\n\n  if (nargin < 2)\n    devopt = opts.devopt;\n  endif\n\n  if (isempty (opts.pstoedit_binary))\n    error (\"Octave:print:nopstoedit\", ...\n           \"print: 'pstoedit' is required for specified output format, but binary is not available in PATH\");\n  endif\n\n  dos_shell = (ispc () && ! isunix ());\n\n  if (! do_svg)\n    if (dos_shell)\n      cmd = sprintf (\"%s -f %s 2> NUL\", opts.pstoedit_binary, devopt);\n    else\n      cmd = sprintf (\"%s -f %s 2> /dev/null\", opts.pstoedit_binary, devopt);\n    endif\n  else\n    cmd = svgconvert (opts, devopt);\n    if (dos_shell)\n      cmd = sprintf ('%s & %s -ssp -f %s \"%%s\" 2> NUL', cmd, ...\n                     undo_string_escapes (opts.pstoedit_binary), ...\n                     undo_string_escapes (devopt));\n    else\n      cmd = sprintf ('%s ; %s -ssp -f %s \"%%s\" 2> /dev/null', cmd,  ...\n                     opts.pstoedit_binary, devopt);\n    endif\n  endif\n\n  if (opts.debug)\n    fprintf (\"pstoedit command: '%s'\\n\", cmd);\n  endif\n\nendfunction\n\nfunction cmd = svgconvert (opts, devopt)\n\n  cmd = \"\";\n\n  if (nargin < 2)\n    devopt = opts.devopt;\n  endif\n\n  if (isempty (opts.svgconvert_binary))\n    warning (\"Octave:print:nosvgconvert\", ...\n             [\"print: unable to find octave-svgconvert, \", ...\n              \"falling back to eps conversion\"]);\n  else\n    fontdir = getenv (\"OCTAVE_FONTS_DIR\");\n\n    if (isempty (fontdir))\n      fontdir = __octave_config_info__ (\"octfontsdir\");\n    endif\n\n    cmd = sprintf ('%s - %%s %3.2f \"%s\" %d \"%%s\"', ...\n                   undo_string_escapes (opts.svgconvert_binary), ...\n                   get (0, \"screenpixelsperinch\"), ...\n                   undo_string_escapes (fullfile (fontdir, \"FreeSans.otf\")),\n                   opts.polymerge);\n\n    if (opts.debug)\n      fprintf (\"svgconvert command: '%s'\\n\", cmd);\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/printd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} printd (@var{obj}, @var{filename})\n## @deftypefnx {} {@var{out_file} =} printd (@dots{})\n##\n## Convert any object acceptable to @code{disp} into the format selected by\n## the suffix of @var{filename}.\n##\n## If the optional output @var{out_file} is requested, the name of the created\n## file is returned.\n##\n## This function is intended to facilitate manipulation of the output of\n## functions such as @code{stemleaf}.\n## @seealso{stemleaf}\n## @end deftypefn\n\nfunction pr_out = printd (obj, filename)\n\n  ## Convert any object acceptable to disp() into various display formats.\n  ## obj is the input object.\n  ## filename is the output file (with required suffix).\n\n  ## Extract .suffix from filename\n  if ((sufix = rindex (filename, \".\")) <= 0)\n    error (\"printd: output FILENAME '%s' requires a suffix.\\nOptions are: pdf ps eps txt jpg jpeg\", filename);\n  endif\n  opt = substr (filename, sufix+1);\n  [pf, tempf, mag] = mkstemp (fullfile (tempdir (), \"oct-XXXXXX\"), true);\n  fprintf (pf, \"%s\", disp (obj));\n  frewind (pf);\n\n  ## It seems best to only use convert for image output.  Its ps and pdf\n  ## are badly rendered.\n  opt = lower (opt);\n  switch (opt)\n    case \"pdf\"\n      enscr = sprintf (\"enscript --no-header -o %s.ps %s ; ps2pdf %s.ps %s.pdf; mv %s.pdf %s;exit\", ...\n                       tempf, tempf, tempf, tempf, tempf, filename);\n      system (enscr);\n      delete ([tempf \".ps\"]);\n    case \"ps\"\n      enscr = sprintf (\"enscript --no-header -o %s %s ; exit\", filename, tempf);\n      system (enscr);\n    case \"eps\"\n      enscr = sprintf (\"enscript --no-header -o %s.ps %s ; ps2eps --ignoreBB %s.ps; mv %s.eps %s; exit\", ...\n                       tempf, tempf, tempf, tempf, filename);\n      system (enscr);\n      delete ([tempf \".ps\"]);\n    case \"txt\"\n      enscr = sprintf (\"cp %s %s\", tempf, filename);\n      system (enscr);\n    case {\"jpg\", \"jpeg\"}\n      enscr = sprintf (\"convert -trim txt:%s  jpg:%s\", tempf, filename);\n      system (enscr);\n    otherwise\n      fclose (pf);\n      delete (tempf);\n      error (\"printd: unknown conversion type: %s.\\nOptions are: pdf ps eps txt jpg jpeg\", opt);\n\n  endswitch\n  fclose (pf);\n  delete (tempf);\n  pr_out = sprintf (\"%s file %s written\\n\", opt, filename);\n\nendfunction\n\n\n%!demo\n%! r2 = char ( ...\n%! \"stem step: 10, data: unsorted.\", ...\n%! \"Hinges:    lo: 12, hi: 42\"     , ...\n%! \"   1 | 22118\"                  , ...\n%! \"   2 | 28\"                     , ...\n%! \"   3 | 98\"                     , ...\n%! \"   4 | 244\"                    , ...\n%! \"   5 | 2\"                      );\n%! printd (r2, \"test_p.txt\");\n%! type (\"test_p.txt\");\n%! unlink (\"test_p.txt\");\n\n%!test\n%! r2 = char (\n%! \"stem step: 10, data: unsorted.\",\n%! \"Hinges:    lo: 12, hi: 42\"     ,\n%! \"   1 | 22118\"                  ,\n%! \"   2 | 28\"                     ,\n%! \"   3 | 98\"                     ,\n%! \"   4 | 244\"                    ,\n%! \"   5 | 2\"                      );\n%! unwind_protect\n%!   filename = [tempname() \".txt\"];\n%!   printd (r2, filename);\n%!   r4 = fileread (filename);\n%!   r2 = disp (r2);\n%!   assert (r4, r2);\n%! unwind_protect_cleanup\n%!   unlink (filename);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/private/__add_default_menu__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} __add_default_menu__ (@var{hf})\n## @deftypefnx {} {} __add_default_menu__ (@var{hf}, @var{hmenu})\n## @deftypefnx {} {} __add_default_menu__ (@var{hf}, @var{hmenu}, @var{htb})\n## Add default menu and listeners to figure.\n##\n## @var{hf} is a figure handle.\n## @var{hmenu} is a uimenu handle.\n## @var{htb} is a uitoolbar handle.\n##\n## All uimenu handles have their @qcode{\"HandleVisibility\"} property set to\n## @qcode{\"off\"}.\n## @end deftypefn\n\nfunction __add_default_menu__ (hf, hmenu = [], htb = [])\n\n  ## Gnuplot doesn't handle uimenu and uitoolbar objects\n  if (strcmp (graphics_toolkit (), \"gnuplot\"))\n    return;\n  endif\n\n  ## Create\n  if (isempty (hmenu))\n    ## File menu\n    hui = uimenu (hf, \"label\", \"&File\", \"tag\", \"__default_menu__File\", ...\n                      \"handlevisibility\", \"off\");\n    uimenu (hui, \"label\", \"&Open...\", \"menuselectedfcn\", @open_cb, ...\n                 \"accelerator\", \"o\");\n    uimenu (hui, \"label\", \"&Save\", \"menuselectedfcn\", {@save_cb, \"save\"}, ...\n                 \"accelerator\", \"s\");\n    uimenu (hui, \"label\", \"Save &As...\", ...\n                 \"menuselectedfcn\", {@save_cb, \"saveas\"}, ...\n                 \"accelerator\", \"S\");\n    uimenu (hui, \"label\", \"&Close\", \"menuselectedfcn\", @close_cb, ...\n                 \"accelerator\", \"w\", \"separator\", \"on\");\n    hmenu(1) = hui;\n\n    ## Edit menu\n    hui = uimenu (hf, \"label\", \"&Edit\", \"handlevisibility\", \"off\", ...\n                      \"tag\", \"__default_menu__Edit\");\n    uimenu (hui, \"label\", \"&New Figure\", \"menuselectedfcn\", \"figure ();\", ...\n                 \"accelerator\", \"n\");\n    uimenu (hui, \"label\", \"&Duplicate Figure\",\n                 \"menuselectedfcn\", \"copyobj (gcbf (), groot ());\", ...\n                 \"accelerator\", \"d\");\n    uimenu (hui, \"label\", \"Clea&r Figure\",\n                 \"menuselectedfcn\", \"clf (gcbf ());\");\n    uimenu (hui, \"label\", \"Reset Figure\",\n                 \"menuselectedfcn\", \"reset (gcbf ());\");\n    uimenu (hui, \"label\", \"Copy Figure to Clipboard\", ...\n                 \"menuselectedfcn\", @clipboard_cb, \"separator\", \"on\", ...\n                 \"accelerator\", \"c\");\n    hmenu(2) = hui;\n\n    ## Tools menu\n    hui = uimenu (hf, \"label\", \"&Tools\", \"handlevisibility\", \"off\", ...\n                      \"tag\", \"__default_menu__Tools\");\n    uimenu (hui, \"label\", \"Toggle &Grid on All Axes\", \"tag\", \"toggle\", ...\n                 \"menuselectedfcn\", @grid_cb);\n    uimenu (hui, \"label\", \"Show Grid on All Axes\", \"tag\", \"on\", ...\n                 \"menuselectedfcn\", @grid_cb);\n    uimenu (hui, \"label\", \"Hide Grid on All Axes\", \"tag\", \"off\", ...\n                 \"menuselectedfcn\", @grid_cb);\n    uimenu (hui, \"label\", \"Auto&scale All Axes\",\n                 \"menuselectedfcn\", @autoscale_cb);\n\n    hui2 = uimenu (hui, \"label\", \"GUI &Mode (on All Axes)\");\n    uimenu (hui2, \"label\", \"Pan X and Y\", \"tag\", \"pan_on\", ...\n                  \"menuselectedfcn\", @guimode_cb);\n    uimenu (hui2, \"label\", \"Pan X Only\", \"tag\", \"pan_xon\", ...\n                  \"menuselectedfcn\", @guimode_cb);\n    uimenu (hui2, \"label\", \"Pan Y Only\", \"tag\", \"pan_yon\", ...\n                  \"menuselectedfcn\", @guimode_cb);\n    uimenu (hui2, \"label\", \"Rotate On\", \"tag\", \"rotate3d\", ...\n                  \"menuselectedfcn\", @guimode_cb);\n    uimenu (hui2, \"label\", \"Disable Pan and Rotate\", \"tag\", ...\n                  \"no_pan_rotate\", \"menuselectedfcn\", @guimode_cb);\n    uimenu (hui2, \"label\", \"Enable Mousezoom\", \"tag\", \"zoom_on\", ...\n                  \"menuselectedfcn\", @guimode_cb);\n    uimenu (hui2, \"label\", \"Disable Mousezoom\", \"tag\", \"zoom_off\", ...\n                  \"menuselectedfcn\", @guimode_cb);\n    hmenu(3) = hui;\n\n    ## Default toolbar\n    init_mouse_tools (hf);\n    htb = uitoolbar (hf, \"tag\", \"__default_toolbar__\", ...\n                         \"handlevisibility\", \"off\", \"visible\", \"off\");\n\n    ht(1) = uitoggletool (htb, \"tooltipstring\", \"Pan\", ...\n                               \"tag\", \"__default_button_pan__\", ...\n                               \"__named_icon__\", \"figure-pan\");\n    ht(2) = uitoggletool (htb, \"tooltipstring\", \"Rotate\", ...\n                               \"tag\", \"__default_button_rotate__\", ...\n                               \"__named_icon__\", \"figure-rotate\");\n\n    ht(3) = uitoggletool (htb, \"tooltipstring\", \"Zoom in\", ...\n                               \"tag\", \"__default_button_zoomin__\", ...\n                               \"__named_icon__\", \"figure-zoom-in\", ...\n                               \"separator\", \"on\");\n    ht(4) = uitoggletool (htb, \"tooltipstring\", \"Zoom out\", ...\n                               \"tag\", \"__default_button_zoomout__\", ...\n                               \"__named_icon__\", \"figure-zoom-out\");\n    uipushtool (htb, \"tooltipstring\", \"Automatic limits for current axes\", ...\n                     \"clickedcallback\", @auto_cb, ...\n                     \"__named_icon__\", \"figure-zoom-original\");\n\n    ht(5) = uitoggletool (htb, \"tooltipstring\", \"Insert text\", ...\n                               \"tag\", \"__default_button_text__\", ...\n                               \"separator\", \"on\", ...\n                               \"__named_icon__\", \"figure-text\");\n\n    uipushtool (htb, \"tooltipstring\", \"Toggle current axes visibility\", ...\n                     \"clickedcallback\", @axes_cb, \"separator\", \"on\", ...\n                     \"__named_icon__\", \"figure-axes\");\n    uipushtool (htb, \"tooltipstring\", \"Toggle current axes grid visibility\", ...\n                     \"clickedcallback\", @grid_cb, ...\n                     \"__named_icon__\", \"figure-grid\");\n\n    set (ht(1), \"oncallback\", {@mouse_tools_cb, ht, \"pan\"}, ...\n                \"offcallback\", {@mouse_tools_cb, ht, \"pan\"});\n    set (ht(2), \"oncallback\", {@mouse_tools_cb, ht, \"rotate\"}, ...\n                \"offcallback\", {@mouse_tools_cb, ht, \"rotate\"});\n    set (ht(3), \"oncallback\", {@mouse_tools_cb, ht, \"zoomin\"}, ...\n                \"offcallback\", {@mouse_tools_cb, ht, \"zoomin\"});\n    set (ht(4), \"oncallback\", {@mouse_tools_cb, ht, \"zoomout\"}, ...\n                \"offcallback\", {@mouse_tools_cb, ht, \"zoomout\"});\n    set (ht(5), \"oncallback\", {@mouse_tools_cb, ht, \"text\"}, ...\n                \"offcallback\", {@mouse_tools_cb, ht, \"text\"});\n  endif\n\n  if (! exist (\"ht\", \"var\"))\n    ht = get (htb, \"children\")(end:-1:1);\n    istoggletool = strcmp (get (ht, \"type\"), \"uitoggletool\");\n    ht(! istoggletool) = [];\n  endif\n\n  ## Add/Restore figure listeners\n  toggle_visibility_cb (hf, [], hmenu, htb);\n  addlistener (hf, \"menubar\", {@toggle_visibility_cb, hmenu, htb});\n  addlistener (hf, \"toolbar\", {@toggle_visibility_cb, hmenu, htb});\n  addlistener (hf, \"__mouse_mode__\", {@mouse_tools_cb, ht, \"mode\"});\n  addlistener (hf, \"__zoom_mode__\", {@mouse_tools_cb, ht, \"mode\"});\n\nendfunction\n\nfunction toggle_visibility_cb (hf, ~, hmenu, htb)\n\n  menu_state = ifelse (strcmp (get (hf, \"menubar\"), \"figure\"), \"on\", \"off\");\n  toolbar_state = \"on\";\n  if (strcmp (get (hf, \"toolbar\"), \"auto\"))\n    toolbar_state = menu_state;\n  elseif (strcmp (get (hf, \"toolbar\"), \"none\"))\n    toolbar_state = \"off\";\n  endif\n\n  set (hmenu, \"visible\", menu_state);\n  set (htb, \"visible\", toolbar_state);\n\nendfunction\n\nfunction open_cb (~, ~)\n  [filename, filedir] = uigetfile ({\"*.ofig;*.fig\", \"Figure Files\"}, ...\n                                   \"Open Figure\");\n  if (filename != 0)\n    fname = fullfile (filedir, filename);\n    openfig (fname);\n  endif\nendfunction\n\nfunction save_cb (h, ~, action)\n\n  hfig = gcbf ();\n  fname = get (hfig, \"filename\");\n\n  if (strcmp (action, \"save\"))\n    if (isempty (fname))\n      __save_as__ (hfig);\n    else\n      saveas (hfig, fname);\n    endif\n  elseif (strcmp (action, \"saveas\"))\n    __save_as__ (hfig, fname);\n  endif\n\nendfunction\n\nfunction __save_as__ (hf, fname = \"\")\n\n  if (! isempty (fname))\n    def = fname;\n  else\n    def = fullfile (pwd (), \"untitled.ofig\");\n  endif\n  filter = {\"*.ofig\", \"Octave Figure\";\n            \"*.eps\",  \"Encapsulated PostScript\";\n            \"*.pdf\",  \"Portable Document Format\";\n            \"*.ps\",   \"PostScript\";\n            \"*.svg\",  \"Scalable Vector Graphics\";\n            \"*.gif\",  \"GIF Image\";\n            \"*.jpg\",  \"JPEG Image\";\n            \"*.png\",  \"Portable Network Graphics Image\";\n            \"*.tiff\", \"TIFF Image\"};\n  ## Reorder filters to have current first\n  [~, ~, ext] = fileparts (def);\n  idx = strcmp (filter(:,1), [\"*\" lower(ext)]);\n  filter = [filter(idx,:); filter(! idx,:)];\n\n  [filename, filedir, filteridx] = uiputfile (filter, \"Save Figure\", def);\n\n  if (filename != 0)\n    fname = fullfile (filedir, filename);\n    [~, ~, ext] = fileparts (fname);\n    if (filteridx > rows (filter))\n      ## \"All Files\" option\n      if (isempty (ext))\n        fmt = \"\";\n      else\n        fmt = ext(2:end);\n      endif\n    else\n      fmt = filter{filteridx,1}(3:end);\n      if (isempty (ext))\n        fname = [fname \".\" fmt];\n      endif\n    endif\n    set (hf, \"filename\", fname);\n    saveas (hf, fname, fmt);\n  endif\n\nendfunction\n\nfunction close_cb (~, ~)\n  close (gcbf ());\nendfunction\n\nfunction [hax, fig] = __get_axes__ (h)\n  ## Get parent figure\n  fig = ancestor (h, \"figure\");\n\n  ## Find all axes which aren't legends\n  hax = findobj (fig, \"type\", \"axes\", \"-not\", \"tag\", \"legend\");\nendfunction\n\nfunction autoscale_cb (h, ~)\n  hax = __get_axes__ (h);\n  arrayfun (@(h) axis (h, \"auto\"), hax);\n  drawnow ();\nendfunction\n\nfunction init_mouse_tools (hf)\n\n  set (hf, \"__pan_mode__\", struct (\"Enable\", \"off\",\n                                   \"Motion\", \"both\",\n                                   \"FigureHandle\", hf),\n           \"__rotate_mode__\", struct (\"Enable\", \"off\",\n                                      \"RotateStyle\", \"box\",\n                                      \"FigureHandle\", hf),\n           \"__zoom_mode__\", struct (\"Enable\", \"off\",\n                                    \"Motion\", \"both\",\n                                    \"Direction\", \"in\",\n                                    \"FigureHandle\", hf));\n\nendfunction\n\nfunction guimode_cb (h, ~)\n\n  [hax, fig] = __get_axes__ (h);\n  id = get (h, \"tag\");\n  switch (id)\n    case \"pan_on\"\n      pan (fig, \"on\");\n    case \"pan_xon\"\n      pan (fig, \"xon\");\n    case \"pan_yon\"\n      pan (fig, \"yon\");\n    case \"rotate3d\"\n      rotate3d (fig, \"on\");\n    case \"no_pan_rotate\"\n      pan (fig, \"off\");\n      rotate3d (fig, \"off\");\n    case \"zoom_on\"\n      arrayfun (@(h) set (h, \"mousewheelzoom\", 0.05), hax);\n    case \"zoom_off\"\n      arrayfun (@(h) set (h, \"mousewheelzoom\", 0.0), hax);\n  endswitch\n\nendfunction\n\nfunction mouse_tools_cb (h, ~, htools, typ = \"\")\n\n  persistent recursion = false;\n\n  if (! recursion)\n    recursion = true;\n\n    hf = gcbf ();\n\n    if (strcmp (typ, \"mode\"))\n      ## The mouse mode has been changed from outside this callback,\n      ## change the buttons state accordingly\n      mode = get (hf, \"__mouse_mode__\");\n      state = \"on\";\n\n      switch (mode)\n        case \"zoom\"\n          zm = get (hf, \"__zoom_mode__\");\n          if (strcmp (zm.Direction, \"in\"))\n            htool = htools(3);\n          else\n            htool = htools(4);\n          endif\n        case \"pan\"\n          htool = htools(1);\n        case \"rotate\"\n          htool = htools(2);\n        case \"text\"\n          htool = htools(5);\n        case \"none\"\n          state = \"off\";\n          htool = htools;\n      endswitch\n\n      set (htool, \"state\", state);\n      if (strcmp (state, \"on\"))\n        set (htools(htools != htool), \"state\", \"off\");\n      endif\n\n    else\n      ## Update the mouse mode according to the button state\n      state = get (h, \"state\");\n\n      switch (typ)\n        case {\"zoomin\", \"zoomout\"}\n          prop = \"__zoom_mode__\";\n          val = get (hf, prop);\n\n          if (strcmp (state, \"on\"))\n            if (strcmp (typ, \"zoomin\"))\n              val.Direction = \"in\";\n            else\n              val.Direction = \"out\";\n            endif\n            set (hf, \"__mouse_mode__\", \"zoom\");\n          endif\n          val.Enable = state;\n          set (hf, prop, val);\n\n        case {\"pan\", \"rotate\"}\n          prop = [\"__\", typ, \"_mode__\"];\n          val = get (hf, prop);\n          if (strcmp (state, \"on\"))\n            set (hf, \"__mouse_mode__\", typ);\n          endif\n          val.Enable = state;\n          set (hf, prop, val);\n\n        case {\"text\", \"select\"}\n          if (strcmp (state, \"on\"))\n            set (hf, \"__mouse_mode__\", typ);\n          endif\n      endswitch\n\n      if (strcmp (state, \"on\"))\n        set (htools(htools != h), \"state\", \"off\");\n      elseif (! any (strcmp (get (htools, \"state\"), \"on\")))\n        set (hf, \"__mouse_mode__\", \"none\");\n      endif\n    endif\n\n    recursion = false;\n  endif\n\nendfunction\n\nfunction axes_cb (h, ~)\n\n  hax = get (gcbf (), \"currentaxes\");\n  if (! isempty (hax))\n    if (strcmp (get (hax, \"visible\"), \"on\"))\n      set (hax, \"visible\", \"off\");\n    else\n      set (hax, \"visible\", \"on\");\n    endif\n  endif\n\nendfunction\n\nfunction grid_cb (h, ~)\n\n  hax = get (gcbf (), \"currentaxes\");\n  if (! isempty (hax))\n    if (strcmp (get (hax, \"xgrid\"), \"on\") && strcmp (get (hax, \"ygrid\"), \"on\"))\n      grid (hax, \"off\");\n    else\n      grid (hax, \"on\");\n    endif\n  endif\n\nendfunction\n\nfunction auto_cb (h, ~)\n  hax = get (gcbf (), \"currentaxes\");\n  if (! isempty (hax))\n    axis (hax, \"auto\");\n  endif\nendfunction\n\nfunction clipboard_cb (h, ~)\n\n  hf = gcbf ();\n  fname = tempname ();\n  props = {\"inverthardcopy\", \"paperposition\", \"paperpositionmode\"};\n  values = get (hf, props);\n  set (hf, \"inverthardcopy\", \"off\", \"paperpositionmode\", \"auto\");\n  unwind_protect\n    print (\"-r0\", \"-dpng\", \"-svgconvert\", fname);\n    __event_manager_copy_image_to_clipboard__ (fname);\n  unwind_protect_cleanup\n    set (hf, props, values);\n  end_unwind_protect\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__ghostscript__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{gs_cmd}, @var{cleanup_cmd}] =} __ghostscript__ (@var{@dots{}})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [gs_cmd, cleanup_cmd] = __ghostscript__ (varargin)\n\n  dos_shell = (ispc () && ! isunix ());\n\n  opts.binary = \"\";\n  opts.source = \"-\";\n  opts.output = \"-\";\n  opts.device = \"\";\n  opts.epscrop = false;\n  opts.antialiasing = false;\n  opts.antialiasing_textalphabits = 4;\n  opts.antialiasing_graphicsalphabits = 1;\n  opts.resolution = 150;\n  opts.papersize = \"\";\n  opts.pageoffset = [0 0];\n  opts.debug = false;\n  opts.level = [];\n  opts.prepend = \"\";\n\n  offsetfile = \"\";\n  offset_ps = {};\n  cleanup_cmd = \"\";\n\n  args = varargin;\n  n = find (cellfun (\"isclass\", args, \"struct\"));\n  if (! isempty (n))\n    f = fieldnames (args{n});\n    for m = 1:numel (f)\n      opts.(f{m}) = args{n}.(f{m});\n    endfor\n    args(n) = [];\n  endif\n  for n = 1:2:numel (args)\n    opts.(args{n}) = args{n+1};\n  endfor\n\n  if (isempty (opts.binary))\n    error (\"Octave:print:nogs\", \"__ghostscript__: 'gs' (Ghostscript) binary is required for specified output format, but binary is not available in PATH\");\n  endif\n\n  if (isempty (opts.papersize))\n    format_for_printer = false;\n  else\n    format_for_printer = true;\n  endif\n\n  gs_opts = [\"-dQUIET -dNOPAUSE -dBATCH -dSAFER -dAutoRotatePages=/None -sDEVICE=\" opts.device];\n\n  if (! isempty (opts.level) && ismember (opts.level, [1, 2, 3]))\n    gs_opts = sprintf (\"%s -dLanguageLevel=%d\", gs_opts, opts.level);\n  endif\n\n  if (strfind (opts.device, \"tiffscaled\"))\n    gs_opts = [gs_opts \" -sCompression=lzw\"];\n  endif\n\n  if (opts.antialiasing && isempty (strfind (opts.device, \"write\")))\n    ## Apply anti-aliasing to all bitmap formats/devices\n    gs_opts = sprintf (\"%s -dTextAlphaBits=%d -dGraphicsAlphaBits=%d\",\n                       gs_opts, fix (opts.antialiasing_textalphabits),\n                       fix (opts.antialiasing_graphicsalphabits));\n    gs_opts = sprintf (\"%s -r%dx%d\", gs_opts, fix ([1, 1] * opts.resolution));\n  elseif (any (strcmp (opts.device, {\"pswrite\", \"ps2write\", \"pdfwrite\"})))\n    gs_opts = sprintf (\"%s -dEmbedAllFonts=true\", gs_opts);\n    if (strcmp (opts.device, \"pdfwrite\"))\n      ## Optimize for loading\n      gs_opts = sprintf (\"%s -dOptimize=true\", gs_opts);\n    endif\n  endif\n\n  if (opts.epscrop)\n    ## papersize is specified by the eps bbox\n    gs_opts = sprintf (\"%s -dEPSCrop\", gs_opts);\n  endif\n  if (format_for_printer)\n    if (ischar (opts.papersize))\n      gs_opts = sprintf (\"%s -sPAPERSIZE=%s\", gs_opts, opts.papersize);\n    elseif (isnumeric (opts.papersize) && numel (opts.papersize) == 2)\n      gs_opts = sprintf (\"%s -dDEVICEWIDTHPOINTS=%d -dDEVICEHEIGHTPOINTS=%d\",\n                         gs_opts, fix (opts.papersize));\n      if (opts.papersize(1) > opts.papersize(2))\n        ## Lanscape mode: This option will result in automatic rotation of the\n        ##                document page if the requested page size matches one\n        ##                of the default page sizes\n        gs_opts = sprintf (\"%s -dNORANGEPAGESIZE\", gs_opts);\n      endif\n    else\n      error (\"Octave:print:badpapersize\", \"__ghostscript__.m: invalid 'papersize'\");\n    endif\n    gs_opts = sprintf (\"%s -dFIXEDMEDIA\", gs_opts);\n    ## \"pageoffset\" is relative to the coordinates, not the BBox LLHC.\n    str = sprintf (\"%s [%d %d] %s\", \"<< /Margins [0 0] /.HWMargins [0 0 0 0] /PageOffset\",\n                   fix (opts.pageoffset), \">> setpagedevice\");\n    offset_ps = {\"%!PS-Adobe-3.0\", str, \"%%EOF\"};\n    if (isfield (opts, \"offsetfile\"))\n      offsetfile = opts.offsetfile;\n      cleanup_cmd = \"\";\n    else\n      offsetfile = [tempname() \".ps\"];\n      if (dos_shell)\n        cleanup_cmd = sprintf ('del \"%s\"', strrep (offsetfile, '/', '\\'));\n      else\n        cleanup_cmd = sprintf ('rm \"%s\"', offsetfile);\n      endif\n    endif\n    unwind_protect\n      fid = fopen (offsetfile, \"w\");\n      if (fid == -1)\n        error (\"Octave:print:fopenfailed\", \"__ghostscript__.m: fopen () failed\");\n      endif\n      fprintf (fid, \"%s\\n\", offset_ps{:});\n    unwind_protect_cleanup\n      status = fclose (fid);\n      if (status == -1)\n        error (\"Octave:print:fclosefailed\", \"__ghostscript__.m: fclose () failed\");\n      endif\n    end_unwind_protect\n    if (opts.debug)\n      fprintf (\"---- begin %s ----\\n\", offsetfile);\n      fprintf (\"%s\\n\", offset_ps{:});\n      fprintf (\"----- end %s -----\\n\", offsetfile);\n    endif\n  endif\n\n  if (isempty (opts.output))\n    cmd = sprintf (\"%s %s\", opts.binary, gs_opts);\n  else\n    cmd = sprintf ('%s %s -sOutputFile=\"%s\"',\n                   opts.binary, gs_opts, opts.output);\n  endif\n  if (! isempty (opts.prepend)\n      && any (strcmpi (opts.device, {\"pswrite\", \"ps2write\", \"pdfwrite\"})))\n    ## FIXME: Fonts get may be mangled when appending ps/ps2.\n    ##        See \"How to concatenate several PS files\" at the link,\n    ##        http://en.wikibooks.org/wiki/PostScript_FAQ\n    cmd = sprintf (\"%s %s\", cmd, opts.prepend);\n    if (isempty (cleanup_cmd))\n      if (dos_shell)\n        cleanup_cmd = [\"del \" strrep(opts.prepend, '/', '\\')];\n      else\n        cleanup_cmd = [\"rm \" opts.prepend];\n      endif\n    else\n      if (dos_shell)\n        cleanup_cmd = sprintf (\"%s & del %s\", cleanup_cmd,\n                               strrep (opts.prepend, '/', '\\'));\n      else\n        cleanup_cmd = sprintf (\"%s ; rm %s\", cleanup_cmd, opts.prepend);\n      endif\n    endif\n  endif\n  if (! isempty (offsetfile) && format_for_printer)\n    cmd = sprintf ('%s \"%s\"', cmd, offsetfile);\n  endif\n  if (! isempty (opts.source))\n    cmd = sprintf (\"%s %s\", cmd, opts.source);\n  endif\n\n  if (opts.debug)\n    fprintf (\"Ghostscript command: '%s'\\n\", cmd);\n  endif\n\n  gs_cmd = cmd;\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__gnuplot_draw_axes__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} __gnuplot_draw_axes__ (@var{h}, @var{plot_stream}, @var{enhanced}, @var{bg_is_set}, @var{fg_is_set}, @var{hlgnd})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction __gnuplot_draw_axes__ (h, plot_stream, enhanced, bg_is_set,\n                                fg_is_set, hlgnd)\n\n  showhiddenhandles = get (0, \"showhiddenhandles\");\n  unwind_protect\n    set (0, \"showhiddenhandles\", \"on\");\n    axis_obj = __get__ (h);\n  unwind_protect_cleanup\n    set (0, \"showhiddenhandles\", showhiddenhandles);\n  end_unwind_protect\n\n  parent_figure_obj = get (axis_obj.parent);\n  gnuplot_term = __gnuplot_get_var__ (axis_obj.parent, \"GPVAL_TERM\");\n\n  ## Set to false for plotyy axes.\n  ymirror = true;\n  if (isfield (axis_obj, \"__plotyy_axes__\"))\n    if (all (ishghandle (axis_obj.__plotyy_axes__)))\n      ymirror = false;\n    else\n      h = axis_obj.__plotyy_axes__;\n      h = h(ishghandle (h));\n      h = h(isprop (h, \"__plotyy_axes__\"));\n      rmappdata (h, \"__plotyy_axes__\");\n    endif\n  endif\n\n  nd = __calc_dimensions__ (h);\n  if (nd == 2 && (any (get (h, \"view\") != [0, 90])))\n    ## view() only works correctly on 3-D axes in gnuplot (bug #58526).\n    nd = 3;\n  endif\n\n  if (strcmp (axis_obj.dataaspectratiomode, \"manual\")\n      && strcmp (axis_obj.xlimmode, \"manual\")\n      && strcmp (axis_obj.ylimmode, \"manual\"))\n    ## All can't be \"manual\"\n    axis_obj.plotboxaspectratiomode = \"auto\";\n  endif\n\n  if (strcmp (axis_obj.dataaspectratiomode, \"manual\")\n      && strcmp (axis_obj.xlimmode, \"manual\")\n      && strcmp (axis_obj.ylimmode, \"manual\")\n      && (nd == 2 || all (mod (axis_obj.view, 90) == 0)))\n    ## FIXME: adjust plotboxaspectratio to respect other\n    fpos = get (axis_obj.parent, \"position\");\n    apos = axis_obj.position;\n  endif\n\n  pos = __actual_axis_position__ (h);\n\n  if (strcmp (axis_obj.dataaspectratiomode, \"manual\"))\n    dr = axis_obj.dataaspectratio;\n    if (nd == 2 || all (mod (axis_obj.view, 90) == 0))\n      dr = dr(1) / dr(2);\n    else\n      ## FIXME: need to properly implement 3-D\n      dr = mean (dr(1:2)) / dr(3);\n    endif\n  else\n    dr = 1;\n  endif\n\n  if (strcmp (axis_obj.positionconstraint, \"innerposition\"))\n    if (nd == 2 || all (mod (axis_obj.view, 90) == 0))\n      x = [1, 1];\n    else\n      ## 3-D plots need to be sized down to fit in the window.\n      x = 1.0 ./ sqrt ([2, 2.5]);\n    endif\n    fprintf (plot_stream, \"set tmargin screen %.15g;\\n\",\n             pos(2)+pos(4)/2+x(2)*pos(4)/2);\n    fprintf (plot_stream, \"set bmargin screen %.15g;\\n\",\n             pos(2)+pos(4)/2-x(2)*pos(4)/2);\n    fprintf (plot_stream, \"set lmargin screen %.15g;\\n\",\n             pos(1)+pos(3)/2-x(1)*pos(3)/2);\n    fprintf (plot_stream, \"set rmargin screen %.15g;\\n\",\n             pos(1)+pos(3)/2+x(1)*pos(3)/2);\n    sz_str = \"\";\n  else  # positionconstraint == outerposition\n    fprintf (plot_stream, \"unset tmargin;\\n\");\n    fprintf (plot_stream, \"unset bmargin;\\n\");\n    fprintf (plot_stream, \"unset lmargin;\\n\");\n    fprintf (plot_stream, \"unset rmargin;\\n\");\n    fprintf (plot_stream, \"set origin %g, %g;\\n\", pos(1:2));\n    if (strcmp (axis_obj.dataaspectratiomode, \"manual\"))\n      sz_str = sprintf (\"ratio %g\", -dr);\n    else\n      sz_str = \"noratio\";\n    endif\n    sz_str = sprintf (\"set size %s %g, %g;\\n\", sz_str, pos(3:4));\n  endif\n  if (! isempty (sz_str))\n    fputs (plot_stream, sz_str);\n  endif\n\n  ## Code above uses axis size for the data aspect ratio, which isn't\n  ## quite correct.  The only fine control is to set all axes units equal.\n  if (nd == 3\n      && strcmp (axis_obj.dataaspectratiomode, \"manual\")\n      && axis_obj.dataaspectratio(1) == axis_obj.dataaspectratio(2))\n    if (axis_obj.dataaspectratio(1) == axis_obj.dataaspectratio(3))\n      zstr = \"z\";\n    else\n      zstr = \"\";\n    endif\n    fprintf (plot_stream, \"set view equal xy%s;\\n\", zstr);\n  endif\n\n  ## Reset all labels, axis-labels, tick-labels, and title\n  ## FIXME: We should have an function to initialize the axis.\n  ##        Presently, this is dispersed in this function.\n  fputs (plot_stream, \"unset label;\\n\");\n  fputs (plot_stream, \"unset arrow;\\n\");\n  fputs (plot_stream, \"unset xtics;\\n\");\n  fputs (plot_stream, \"unset ytics;\\n\");\n  fputs (plot_stream, \"unset ztics;\\n\");\n  fputs (plot_stream, \"unset x2tics;\\n\");\n  fputs (plot_stream, \"unset y2tics;\\n\");\n\n  if (isempty (axis_obj.title) || isempty (get (axis_obj.title, \"string\")))\n    fputs (plot_stream, \"unset title;\\n\");\n  else\n    if (nd == 2)\n      t = get (axis_obj.title);\n      colorspec = get_text_colorspec (t.color);\n      [tt, f, s] = __maybe_munge_text__ (enhanced, t, \"string\", ...\n                                         t.interpreter, gnuplot_term);\n      fontspec = create_fontspec (f, s, gnuplot_term);\n      fprintf (plot_stream, ['set title \"%s\" %s %s %s;' \"\\n\"],\n               tt, fontspec, colorspec, __do_enhanced_option__ (enhanced, t));\n    else\n      ## Change meaning of \"normalized\", but it at least gives user some control\n      if (! strcmp (get (axis_obj.title, \"units\"), \"normalized\"))\n        unwind_protect\n          set (axis_obj.title, \"units\", \"normalized\",\n                               \"position\", [0.5 1.02 0.5]);\n        unwind_protect_cleanup\n        end_unwind_protect\n      endif\n      t = get (axis_obj.title);\n      axispos = axis_obj.position;\n      screenpos = t.position;\n      screenpos(1) = axispos(1)+screenpos(1)*axispos(3);\n      screenpos(2) = axispos(2)+screenpos(2)*axispos(4);\n      fputs (plot_stream, \"unset title;\\n\");\n      do_text (plot_stream, gnuplot_term, enhanced, t, h, screenpos);\n    endif\n  endif\n\n  if (! isempty (axis_obj.xlabel))\n    t = get (axis_obj.xlabel);\n    angle = t.rotation;\n    colorspec = get_text_colorspec (t.color);\n    if (isempty (t.string))\n      fprintf (plot_stream, \"unset xlabel;\\n\");\n      fprintf (plot_stream, \"unset x2label;\\n\");\n    else\n      [tt, f, s] = __maybe_munge_text__ (enhanced, t, \"string\", ...\n                                         t.interpreter, gnuplot_term);\n      fontspec = create_fontspec (f, s, gnuplot_term);\n      if (strcmp (axis_obj.xaxislocation, \"top\"))\n        fprintf (plot_stream, 'set x2label \"%s\" %s %s %s',\n                 tt, colorspec, fontspec, __do_enhanced_option__ (enhanced, t));\n      else\n        fprintf (plot_stream, 'set xlabel \"%s\" %s %s %s',\n                 tt, colorspec, fontspec, __do_enhanced_option__ (enhanced, t));\n      endif\n      fprintf (plot_stream, \" rotate by %f;\\n\", angle);\n      if (strcmp (axis_obj.xaxislocation, \"top\"))\n        fprintf (plot_stream, \"unset xlabel;\\n\");\n      else\n        fprintf (plot_stream, \"unset x2label;\\n\");\n      endif\n    endif\n  endif\n\n  if (! isempty (axis_obj.ylabel))\n    t = get (axis_obj.ylabel);\n    angle = t.rotation;\n    colorspec = get_text_colorspec (t.color);\n    if (isempty (t.string))\n      fprintf (plot_stream, \"unset ylabel;\\n\");\n      fprintf (plot_stream, \"unset y2label;\\n\");\n    else\n      [tt, f, s] = __maybe_munge_text__ (enhanced, t, \"string\", ...\n                                         t.interpreter, gnuplot_term);\n      fontspec = create_fontspec (f, s, gnuplot_term);\n      if (strcmp (axis_obj.yaxislocation, \"right\"))\n        fprintf (plot_stream, 'set y2label \"%s\" %s %s %s',\n                 tt, colorspec, fontspec, __do_enhanced_option__ (enhanced, t));\n      else\n        fprintf (plot_stream, 'set ylabel \"%s\" %s %s %s',\n                 tt, colorspec, fontspec, __do_enhanced_option__ (enhanced, t));\n      endif\n      fprintf (plot_stream, \" rotate by %f;\\n\", angle);\n      if (strcmp (axis_obj.yaxislocation, \"right\"))\n        fprintf (plot_stream, \"unset ylabel;\\n\");\n      else\n        fprintf (plot_stream, \"unset y2label;\\n\");\n      endif\n    endif\n  endif\n\n  if (! isempty (axis_obj.zlabel))\n    t = get (axis_obj.zlabel);\n    angle = t.rotation;\n    colorspec = get_text_colorspec (t.color);\n    if (isempty (t.string))\n      fputs (plot_stream, \"unset zlabel;\\n\");\n    else\n      [tt, f, s] = __maybe_munge_text__ (enhanced, t, \"string\", ...\n                                         t.interpreter, gnuplot_term);\n      fontspec = create_fontspec (f, s, gnuplot_term);\n      fprintf (plot_stream, 'set zlabel \"%s\" %s %s %s',\n               tt, colorspec, fontspec, __do_enhanced_option__ (enhanced, t));\n      fprintf (plot_stream, \" rotate by %f;\\n\", angle);\n    endif\n  endif\n\n  if (strcmp (axis_obj.xaxislocation, \"top\"))\n    xaxisloc = \"x2\";\n    xaxisloc_using = \"x2\";\n  else\n    xaxisloc = \"x\";\n    xaxisloc_using = \"x1\";\n    if (strcmp (axis_obj.xaxislocation, \"origin\"))\n      fputs (plot_stream, \"set xzeroaxis;\\n\");\n    endif\n  endif\n  if (strcmp (axis_obj.yaxislocation, \"right\"))\n    yaxisloc = \"y2\";\n    yaxisloc_using = \"y2\";\n  else\n    yaxisloc = \"y\";\n    yaxisloc_using = \"y1\";\n    if (strcmp (axis_obj.yaxislocation, \"origin\"))\n      fputs (plot_stream, \"set yzeroaxis;\\n\");\n    endif\n  endif\n\n  have_major_grid = false;\n  have_minor_grid = false;\n  visible_gls = ! strcmp (axis_obj.gridlinestyle, \"none\") ...\n                && ! strcmp (axis_obj.gridcolor, \"none\");\n  visible_mgls = ! strcmp (axis_obj.minorgridlinestyle, \"none\") ...\n                 && ! strcmp (axis_obj.minorgridcolor, \"none\");\n\n  if (strcmp (axis_obj.xgrid, \"on\") && visible_gls)\n    have_major_grid = true;\n    fprintf (plot_stream, \"set grid %stics;\\n\", xaxisloc);\n  else\n    fprintf (plot_stream, \"set grid no%stics;\\n\", xaxisloc);\n  endif\n\n  if (strcmp (axis_obj.ygrid, \"on\") && visible_gls)\n    have_major_grid = true;\n    fprintf (plot_stream, \"set grid %stics;\\n\", yaxisloc);\n  else\n    fprintf (plot_stream, \"set grid no%stics;\\n\", yaxisloc);\n  endif\n\n  if (strcmp (axis_obj.zgrid, \"on\") && visible_gls)\n    have_major_grid = true;\n    fputs (plot_stream, \"set grid ztics;\\n\");\n  else\n    fputs (plot_stream, \"set grid noztics;\\n\");\n  endif\n\n  if (strcmp (axis_obj.xminorgrid, \"on\") && visible_mgls)\n    have_minor_grid = true;\n    if (strcmp (axis_obj.xscale, \"log\"))\n      m = 10;\n    else\n      m = 5;\n    endif\n    fprintf (plot_stream, \"set m%stics %d;\\n\", xaxisloc, m);\n    fprintf (plot_stream, \"set grid m%stics;\\n\", xaxisloc);\n  else\n    fprintf (plot_stream, \"set grid nom%stics;\\n\", xaxisloc);\n  endif\n\n  if (strcmp (axis_obj.yminorgrid, \"on\") && visible_mgls)\n    have_minor_grid = true;\n    if (strcmp (axis_obj.yscale, \"log\"))\n      m = 10;\n    else\n      m = 5;\n    endif\n    fprintf (plot_stream, \"set m%stics %d;\\n\", yaxisloc, m);\n    fprintf (plot_stream, \"set grid m%stics;\\n\", yaxisloc);\n  else\n    fprintf (plot_stream, \"set grid nom%stics;\\n\", yaxisloc);\n  endif\n\n  if (strcmp (axis_obj.zminorgrid, \"on\") && visible_mgls)\n    have_minor_grid = true;\n    if (strcmp (axis_obj.zscale, \"log\"))\n      m = 10;\n    else\n      m = 5;\n    endif\n    fprintf (plot_stream, \"set mztics %d;\\n\", m);\n    fputs (plot_stream, \"set grid mztics;\\n\");\n  else\n    fputs (plot_stream, \"set grid nomztics;\\n\");\n  endif\n\n  ## The grid front/back/layerdefault option also controls the\n  ## appearance of tics, so it is used even if the grid is absent.\n  if (strcmp (axis_obj.layer, \"top\"))\n    fputs (plot_stream, \"set grid front;\\n\");\n    fputs (plot_stream, \"set border front;\\n\");\n  else\n    fputs (plot_stream, \"set grid layerdefault;\\n\");\n  endif\n\n  xlogscale = strcmp (axis_obj.xscale, \"log\");\n  ylogscale = strcmp (axis_obj.yscale, \"log\");\n  zlogscale = strcmp (axis_obj.zscale, \"log\");\n\n  ## Detect logscale and negative lims\n  if (xlogscale && all (axis_obj.xlim < 0))\n    axis_obj.xsgn = -1;\n    if (strcmp (axis_obj.xdir, \"reverse\"))\n      axis_obj.xdir = \"normal\";\n    elseif (strcmp (axis_obj.xdir, \"normal\"))\n      axis_obj.xdir = \"reverse\";\n    endif\n    axis_obj.xtick = -flip (axis_obj.xtick);\n    axis_obj.xticklabel = flip (axis_obj.xticklabel);\n    axis_obj.xlim = -flip (axis_obj.xlim);\n  else\n    axis_obj.xsgn = 1;\n  endif\n  if (ylogscale && all (axis_obj.ylim < 0))\n    axis_obj.ysgn = -1;\n    if (strcmp (axis_obj.ydir, \"reverse\"))\n      axis_obj.ydir = \"normal\";\n    elseif (strcmp (axis_obj.ydir, \"normal\"))\n      axis_obj.ydir = \"reverse\";\n    endif\n    axis_obj.ytick = -flip (axis_obj.ytick);\n    axis_obj.yticklabel = flip (axis_obj.yticklabel);\n    axis_obj.ylim = -flip (axis_obj.ylim);\n  else\n    axis_obj.ysgn = 1;\n  endif\n  if (zlogscale && all (axis_obj.zlim < 0))\n    axis_obj.zsgn = -1;\n    if (strcmp (axis_obj.zdir, \"reverse\"))\n      axis_obj.zdir = \"normal\";\n    elseif (strcmp (axis_obj.zdir, \"normal\"))\n      axis_obj.zdir = \"reverse\";\n    endif\n    axis_obj.ztick = -flip (axis_obj.ztick);\n    axis_obj.zticklabel = flip (axis_obj.zticklabel);\n    axis_obj.zlim = -flip (axis_obj.zlim);\n  else\n    axis_obj.zsgn = 1;\n  endif\n\n  xlim = axis_obj.xlim;\n  ylim = axis_obj.ylim;\n  zlim = axis_obj.zlim;\n  clim = axis_obj.clim;\n\n  do_tics (axis_obj, plot_stream, ymirror, gnuplot_term);\n\n  fputs (plot_stream, \"unset logscale;\\n\");\n  if (xlogscale)\n    fprintf (plot_stream, \"set logscale %s;\\n\", xaxisloc);\n  endif\n  if (ylogscale)\n    fprintf (plot_stream, \"set logscale %s;\\n\", yaxisloc);\n  endif\n  if (zlogscale)\n    fputs (plot_stream, \"set logscale z;\\n\");\n  endif\n\n  xautoscale = strcmp (axis_obj.xlimmode, \"auto\");\n  yautoscale = strcmp (axis_obj.ylimmode, \"auto\");\n  zautoscale = strcmp (axis_obj.zlimmode, \"auto\");\n  cautoscale = strcmp (axis_obj.climmode, \"auto\");\n\n  fputs (plot_stream, \"set clip two;\\n\");\n\n  kids = axis_obj.children;\n  ## Remove the axis labels and title from the children, and\n  ## preserved the original order.\n  [jnk, k] = setdiff (kids, [axis_obj.xlabel; axis_obj.ylabel; ...\n                             axis_obj.zlabel; axis_obj.title]);\n  kids = kids(sort (k));\n\n  if (nd == 3)\n    fputs (plot_stream, \"set parametric;\\n\");\n    fputs (plot_stream, \"set style data lines;\\n\");\n    fputs (plot_stream, \"set surface;\\n\");\n    fputs (plot_stream, \"unset contour;\\n\");\n  endif\n\n  data_idx = 0;\n  data = cell ();\n  is_image_data = [];\n  hidden_removal = NaN;\n  view_map = false;\n\n  if (cautoscale)\n    ## First pass to get cdata limits, maybe general graphics should do this\n    kids1 = kids;\n    clim = [Inf -Inf];\n\n    while (! isempty (kids1))\n      obj = get (kids1(end));\n      kids1 = kids1(1:(end-1));\n\n      switch (obj.type)\n        case {\"image\", \"patch\", \"surface\"}\n          if (isfield (obj, \"cdatamapping\")\n              && strcmp (obj.cdatamapping, \"scaled\")\n              && isfield (obj, \"cdata\")\n              && ! isempty (obj.cdata))\n            clim(1) = min (clim(1), min (obj.cdata(:)));\n            clim(2) = max (clim(2), max (obj.cdata(:)));\n          endif\n\n        case \"hggroup\"\n          ## Push group children into the kid list.\n          if (isempty (kids1))\n            kids1 = obj.children;\n          elseif (! isempty (obj.children))\n            kids1 = [kids1; obj.children];\n          endif\n      endswitch\n    endwhile\n\n    if (clim(1) == Inf)\n      clim = axis_obj.clim;\n    endif\n\n  elseif (clim(1) == clim(2))\n    clim(2)++;\n  endif\n\n  if (rows (parent_figure_obj.colormap) != 2)\n    kids1 = kids;\n    while (! isempty (kids1))\n      obj = get (kids1(end));\n      kids1 = kids1(1:(end-1));\n\n      switch (obj.type)\n        case \"hggroup\"\n          ## Push group children into the kid list.\n          if (isempty (kids1))\n            kids1 = obj.children;\n          elseif (! isempty (obj.children))\n            kids1 = [kids1; obj.children];\n          endif\n      endswitch\n    endwhile\n  endif\n\n  cmap = axis_obj.colormap;\n  cmap_sz = rows (cmap);\n  addedcmap = [];\n\n  ximg_data = {};\n  ximg_data_idx = 0;\n\n  if (! isempty (hlgnd))\n    hlgndntrp = hlgnd.interpreter;\n  else\n    hlgndntrp = \"none\";\n  endif\n\n  while (! isempty (kids))\n\n    h_obj = kids(end);\n    kids = kids(1:(end-1));\n\n    obj = get (h_obj);\n\n    if (isfield (obj, \"xdata\"))\n      obj.xdata = double (obj.xdata);\n    endif\n    if (isfield (obj, \"ydata\"))\n      obj.ydata = double (obj.ydata);\n    endif\n    if (isfield (obj, \"zdata\"))\n      obj.zdata = double (obj.zdata);\n    endif\n\n    if (strcmp (obj.type, \"text\"))\n      units = obj.units;\n      unwind_protect\n        set (h_obj, \"units\", \"data\");\n        obj = get (h_obj);\n      unwind_protect_cleanup\n        set (h_obj, \"units\", units);\n      end_unwind_protect\n    endif\n\n    if (strcmp (obj.visible, \"off\"))\n      continue;\n    endif\n\n    if (xlogscale && isfield (obj, \"xdata\"))\n      obj.xdata = axis_obj.xsgn * obj.xdata;\n      obj.xdata(obj.xdata<=0) = NaN;\n    endif\n    if (ylogscale && isfield (obj, \"ydata\"))\n      obj.ydata = axis_obj.ysgn * obj.ydata;\n      obj.ydata(obj.ydata<=0) = NaN;\n    endif\n    if (zlogscale && isfield (obj, \"zdata\"))\n      obj.zdata = axis_obj.zsgn * obj.zdata;\n      obj.zdata(obj.zdata<=0) = NaN;\n    endif\n\n    switch (obj.type)\n      case \"image\"\n        img_data = mapcdata (obj.cdata, obj.cdatamapping, clim, cmap_sz);\n        img_xdata = obj.xdata;\n        img_ydata = obj.ydata;\n\n        data_idx += 1;\n        is_image_data(data_idx) = true;\n        parametric(data_idx) = false;\n        have_cdata(data_idx) = false;\n        have_3d_patch(data_idx) = false;\n\n        if (img_xdata(2) < img_xdata(1))\n          img_xdata = img_xdata(2:-1:1);\n          img_data = img_data(:,end:-1:1,:);\n        elseif (img_xdata(1) == img_xdata(2))\n          img_xdata = img_xdata(1) + [0, columns(img_data)-1];\n        endif\n        if (img_ydata(2) < img_ydata(1))\n          img_ydata = img_ydata(2:-1:1);\n          img_data = img_data(end:-1:1,:,:);\n        elseif (img_ydata(1) == img_ydata(2))\n          img_ydata = img_ydata(1) + [0, rows(img_data)-1];\n        endif\n\n        x_origin = min (img_xdata);\n        y_origin = min (img_ydata);\n\n        [y_dim, x_dim] = size (img_data(:,:,1));\n        if (x_dim > 1)\n          dx = abs (img_xdata(2)-img_xdata(1))/(x_dim-1);\n        else\n          x_dim = 2;\n          img_data = [img_data, img_data];\n          dx = abs (img_xdata(2)-img_xdata(1));\n          if (dx < 1)\n            ## Correct gnuplot string for 1-D images\n            dx       = 0.5;\n            x_origin = 0.75;\n          endif\n        endif\n        if (y_dim > 1)\n          dy = abs (img_ydata(2)-img_ydata(1))/(y_dim-1);\n        else\n          y_dim = 2;\n          img_data = [img_data; img_data];\n          dy = abs (img_ydata(2)-img_ydata(1));\n          if (dy < 1)\n            ## Correct gnuplot string for 1-D images\n            dy       = 0.5;\n            y_origin = 0.75;\n          endif\n        endif\n\n        if (ndims (img_data) == 3)\n          data{data_idx} = permute (img_data, [3, 1, 2])(:);\n          format = \"1:2:3\";\n          imagetype = \"rgbimage\";\n        else\n          data{data_idx} = img_data(:);\n          format = \"1\";\n          imagetype = \"image\";\n        endif\n\n        titlespec{data_idx} = 'title \"\"';\n        usingclause{data_idx} = sprintf (\"binary array=%dx%d scan=yx origin=(%.15g,%.15g) dx=%.15g dy=%.15g using %s\",\n            x_dim, y_dim, x_origin, y_origin, dx, dy, format);\n        withclause{data_idx} = sprintf (\"with %s\", imagetype);\n\n      case \"line\"\n        if (strcmp (get (obj.parent, \"type\"), \"hggroup\"))\n          hg = get (obj.parent, \"children\");\n          if (hg(1) == h_obj && ! isempty (get (obj.parent, \"displayname\")))\n            data_idx += 1;\n            is_image_data(data_idx) = false;\n            parametric(data_idx) = false;\n            have_cdata(data_idx) = false;\n            have_3d_patch(data_idx) = false;\n            tmpdispname = obj.displayname;\n            obj.displayname = get (obj.parent, \"displayname\");\n            tmp = __maybe_munge_text__ (enhanced, obj, \"displayname\", ...\n                                        hlgndntrp, gnuplot_term);\n            titlespec{data_idx} = ['title \"' tmp '\"'];\n            obj.displayname = tmpdispname;\n            if (! isempty (findobj (obj.parent, \"-property\", \"format\", \"-depth\", 0)))\n              ## Place phantom errorbar data for legend\n              data{data_idx} = NaN (4,1);\n              usingclause{data_idx} = sprintf (\"record=1 using ($1):($2):($3):($4)\");\n              switch (get (obj.parent, \"format\"))\n                case {\"box\" \"boxy\" \"boxxy\"}\n                  errbars = \"boxxy\";\n                case \"xyerr\"\n                  errbars = \"xyerrorbars\";\n                case \"yerr\"\n                  errbars = \"yerrorbars\";\n                case \"xerr\"\n                  errbars = \"xerrorbars\";\n                otherwise\n                  errbars = \"xerrorbars\";\n              endswitch\n              withclause{data_idx} = sprintf (\"with %s linestyle %d\", ...\n                                              errbars, sidx(1));\n            else\n              ## Place phantom stemseries data for legend\n              data{data_idx} = NaN (2,1);\n              usingclause{data_idx} = sprintf (\"record=1 using ($1):($2)\");\n              hgobj = get (obj.parent);\n              [hgstyle, hgsidx] = do_linestyle_command (hgobj, hgobj.color, ...\n                                                        data_idx, plot_stream);\n              withclause{data_idx} = sprintf (\"with %s linestyle %d\",\n                                              hgstyle{1}, hgsidx(1));\n            endif\n          endif\n        endif\n\n        if (strcmp (obj.linestyle, \"none\")\n            && (! isfield (obj, \"marker\")\n                || (isfield (obj, \"marker\")\n                    && strcmp (obj.marker, \"none\"))))\n          continue;\n        endif\n        data_idx += 1;\n        is_image_data(data_idx) = false;\n        parametric(data_idx) = true;\n        have_cdata(data_idx) = false;\n        have_3d_patch(data_idx) = false;\n        if (isempty (obj.displayname))\n          titlespec{data_idx} = 'title \"\"';\n        else\n          tmp = __maybe_munge_text__ (enhanced, obj, \"displayname\", ...\n                                      hlgndntrp, gnuplot_term);\n          titlespec{data_idx} = ['title \"' tmp '\"'];\n        endif\n        usingclause{data_idx} = sprintf (\"record=%d\", numel (obj.xdata));\n        if (nd == 3)\n          xdat = obj.xdata(:);\n          ydat = obj.ydata(:);\n          if (! isempty (obj.zdata))\n            zdat = obj.zdata(:);\n          else\n            zdat = zeros (size (xdat));\n          endif\n          data{data_idx} = [xdat, ydat, zdat]';\n          usingclause{data_idx} = sprintf (\"record=%d using ($1):($2):($3)\",\n                                           numel (xdat));\n          ## fputs (plot_stream, \"set parametric;\\n\");\n        else\n          xdat = obj.xdata(:);\n          ydat = obj.ydata(:);\n          data{data_idx} = [xdat, ydat]';\n          usingclause{data_idx} = ...\n            sprintf (\"record=%d using ($1):($2) axes %s%s\",\n                     rows (xdat), xaxisloc_using, yaxisloc_using);\n        endif\n\n        [style, sidx] = do_linestyle_command (obj, obj.color, data_idx,\n                                              plot_stream);\n\n        if (isempty (style{1}))\n          style{1} = \"points\";\n          data{data_idx} = {};\n        endif\n        withclause{data_idx} = sprintf (\"with %s linestyle %d\",\n                                        style{1}, sidx(1));\n\n        if (length (style) > 1)\n          data_idx += 1;\n          is_image_data(data_idx) = is_image_data(data_idx - 1);\n          parametric(data_idx) = parametric(data_idx - 1);\n          have_cdata(data_idx) = have_cdata(data_idx - 1);\n          have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);\n          titlespec{data_idx} = 'title \"\"';\n          usingclause{data_idx} = usingclause{data_idx - 1};\n          data{data_idx} = data{data_idx - 1};\n          withclause{data_idx} = sprintf (\"with %s linestyle %d\",\n                                          style{2}, sidx(2));\n        endif\n        if (length (style) > 2)\n          data_idx += 1;\n          is_image_data(data_idx) = is_image_data(data_idx - 1);\n          parametric(data_idx) = parametric(data_idx - 1);\n          have_cdata(data_idx) = have_cdata(data_idx - 1);\n          have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);\n          titlespec{data_idx} = 'title \"\"';\n          usingclause{data_idx} = usingclause{data_idx - 1};\n          data{data_idx} = data{data_idx - 1};\n          withclause{data_idx} = sprintf (\"with %s linestyle %d\",\n                                          style{3}, sidx(3));\n        endif\n\n      case \"patch\"\n        persistent do_interp_warning = true;\n\n        if (strcmp (get (obj.parent, \"type\"), \"hggroup\"))\n          obj.displayname = get (obj.parent, \"displayname\");\n        endif\n\n        [nr, nc] = size (obj.xdata);\n\n        if (! isempty (obj.cdata))\n          cdat = obj.cdata;\n        else\n          cdat = [];\n        endif\n\n        data_3d_idx = NaN;\n        for i = 1:nc\n          xcol = obj.xdata(:,i);\n          ycol = obj.ydata(:,i);\n          if (nd == 3)\n            if (! isempty (obj.zdata))\n              zcol = obj.zdata(:,i);\n            else\n              zcol = zeros (size (xcol));\n            endif\n          endif\n\n          if (! isnan (xcol) && ! isnan (ycol))\n            ## Is the patch closed or not\n            if (! strcmp (obj.facecolor, \"none\"))\n              hidden_removal = true;\n              if (nd == 3)\n                if (numel (xcol) > 3)\n                  error (\"__gnuplot_draw_axes__: gnuplot (as of v4.2) only supports 3-D filled triangular patches\");\n                else\n                  if (isnan (data_3d_idx))\n                    data_idx += 1;\n                    data_3d_idx = data_idx;\n                    is_image_data(data_idx) = false;\n                    parametric(data_idx) = false;\n                    have_cdata(data_idx) = true;\n                    have_3d_patch(data_idx) = true;\n                    withclause{data_3d_idx} = sprintf (\"with pm3d\");\n                    usingclause{data_3d_idx} =  \"using 1:2:3:4\";\n                    data{data_3d_idx} = [];\n                  endif\n                  local_idx = data_3d_idx;\n                  ccdat = NaN;\n                endif\n              else\n                data_idx += 1;\n                local_idx = data_idx;\n                is_image_data(data_idx) = false;\n                parametric(data_idx) = false;\n                have_cdata(data_idx) = false;\n                have_3d_patch(data_idx) = false;\n              endif\n\n              if (i > 1 || isempty (obj.displayname))\n                titlespec{local_idx} = 'title \"\"';\n              else\n                tmp = __maybe_munge_text__ (enhanced, obj, \"displayname\", ...\n                                            hlgndntrp, gnuplot_term);\n                titlespec{local_idx} = ['title \"' tmp '\"'];\n              endif\n              if (isfield (obj, \"facecolor\"))\n                if ((strcmp (obj.facecolor, \"flat\")\n                    || strcmp (obj.facecolor, \"interp\"))\n                    && isfield (obj, \"cdata\"))\n                  if (ndims (obj.cdata) == 2\n                      && (columns (obj.cdata) == nc\n                          && (rows (obj.cdata) == 1\n                              || rows (obj.cdata) == 3)))\n                    ccol = cdat(:, i);\n                  elseif (ndims (obj.cdata) == 2\n                      && (rows (obj.cdata) == nc\n                          && (columns (obj.cdata) == 1\n                              || columns (obj.cdata) == 3)))\n                    ccol = cdat(i, :);\n                  elseif (ndims (obj.cdata) == 3)\n                    ccol = permute (cdat (:, i, :), [1, 3, 2]);\n                  else\n                    ccol = cdat;\n                  endif\n                  if (strcmp (obj.facecolor, \"flat\"))\n                    if (isequal (size (ccol), [1, 3]))\n                      ## RGB Triplet\n                      color = ccol;\n                    else\n                      ccdat = mapcdata (ccol, obj.cdatamapping, clim, cmap_sz);\n                      if (nd == 3 && numel (xcol) == 3)\n                        color = cmap(ccdat(1), :);\n                      else\n                        color = cmap(ccdat, :);\n                      endif\n                    endif\n                  elseif (strcmp (obj.facecolor, \"interp\"))\n                    if (nd == 3 && numel (xcol) == 3)\n                      ccdat = ccol;\n                      if (! isvector (ccdat))\n                        tmp = cmap_sz + rows (addedcmap) + ...\n                             [1 : rows(ccdat)];\n                        addedcmap = [addedcmap; ccdat];\n                        ccdat = tmp(:);\n                      else\n                        ccdat = mapcdata (ccdat(:), obj.cdatamapping, clim, cmap_sz);\n                      endif\n                    else\n                      if (do_interp_warning && sum (diff (ccol)))\n                        warning ('\"interp\" not supported, using 1st entry of cdata');\n                        do_interp_warning = false;\n                      endif\n                      r = mapcdata (ccol, obj.cdatamapping, clim, cmap_sz);\n                      color = cmap(r(1),:);\n                    endif\n                  endif\n                elseif (isnumeric (obj.facecolor))\n                  color = obj.facecolor;\n                else\n                  color = [0, 1, 0];\n                endif\n              else\n                color = [0, 1, 0];\n              endif\n\n              if (nd == 3 && numel (xcol) == 3)\n                if (isnan (ccdat))\n                  ccdat = (cmap_sz + rows (addedcmap) + 1) * ones (3, 1);\n                  addedcmap = [addedcmap; reshape(color, 1, 3)];\n                elseif (numel (ccdat) == 1)\n                  ccdat = ccdat * ones (size (zcol));\n                elseif (numel (ccdat) < 1)\n                  ccdat = zcol;\n                endif\n                data{data_3d_idx} = [data{data_3d_idx}, ...\n                                     [[xcol; xcol(end)], [ycol; ycol(end)], ...\n                                     [zcol; zcol(end)], [ccdat; ccdat(end)]]'];\n              else\n                if (isscalar (obj.facealpha))\n                  colorspec = sprintf ('lc rgb \"#%02x%02x%02x\" fillstyle transparent solid %f',\n                                       round (255*color), obj.facealpha);\n                else\n                  colorspec = sprintf ('lc rgb \"#%02x%02x%02x\"',\n                                       round (255*color));\n                endif\n\n                withclause{data_idx} = sprintf (\"with filledcurve %s\",\n                                              colorspec);\n                data{data_idx} = [xcol, ycol]';\n                usingclause{data_idx} = sprintf (\"record=%d using ($1):($2)\",\n                                                 numel (xcol));\n              endif\n            endif\n          endif\n\n          ## patch outline\n          if (!(strcmp (obj.edgecolor, \"none\")\n                 && (strcmp (obj.marker, \"none\")\n                     || (strcmp (obj.markeredgecolor, \"none\")\n                         && strcmp (obj.markerfacecolor, \"none\")))))\n\n            data_idx += 1;\n            is_image_data(data_idx) = false;\n            parametric(data_idx) = false;\n            have_cdata(data_idx) = false;\n            have_3d_patch(data_idx) = false;\n            titlespec{data_idx} = 'title \"\"';\n            usingclause{data_idx} = sprintf (\"record=%d\", numel (obj.xdata));\n\n            if (isfield (obj, \"markersize\"))\n              mdat = obj.markersize / 3;\n            endif\n\n            if (isfield (obj, \"edgecolor\"))\n              ## FIXME: This is the wrong thing to do as edgecolor,\n              ## markeredgecolor and markerfacecolor can have different values\n              ## and we should treat them separately.  However, the code below\n              ## allows the scatter functions to work as expected, where only\n              ## one of these values is set.\n              if (strcmp (obj.edgecolor, \"none\"))\n                if (strcmp (obj.markeredgecolor, \"none\"))\n                  ec = obj.markerfacecolor;\n                else\n                  ec = obj.markeredgecolor;\n                endif\n              else\n                ec = obj.edgecolor;\n              endif\n\n              if ((strcmp (ec, \"flat\") || strcmp (ec, \"interp\"))\n                  && isfield (obj, \"cdata\"))\n                if (ndims (obj.cdata) == 2\n                    && (columns (obj.cdata) == nc\n                        && (rows (obj.cdata) == 1\n                            || rows (obj.cdata) == 3)))\n                  ccol = cdat(:, i);\n                elseif (ndims (obj.cdata) == 2\n                        && (rows (obj.cdata) == nc\n                            && (columns (obj.cdata) == 1\n                                || columns (obj.cdata) == 3)))\n                  ccol = cdat(i, :);\n                elseif (ndims (obj.cdata) == 3)\n                  ccol = permute (cdat (:, i, :), [1, 3, 2]);\n                else\n                  ccol = cdat;\n                endif\n                if (strcmp (ec, \"flat\"))\n                  if (isequal (size (ccol), [1, 3]))\n                    color = ccol;\n                  else\n                    if (columns (ccol) != 3)\n                      ccol = mapcdata (ccol, obj.cdatamapping, clim, cmap_sz);\n                    endif\n                    if (isscalar (ccol))\n                      ccol = repmat (ccol, numel (xcol), 1);\n                    endif\n                    color = \"flat\";\n                    have_cdata(data_idx) = true;\n                  endif\n                elseif (strcmp (ec, \"interp\"))\n                  if (do_interp_warning && numel (ccol) == 3)\n                    warning ('\"interp\" not supported, using 1st entry of cdata');\n                    do_interp_warning = false;\n                    color = mapcdata (ccol(:), obj.cdatamapping, clim, cmap_sz);\n                  else\n                    if (isscalar (ccol))\n                      ccol = repmat (ccol, numel (xcol), 1);\n                    endif\n                    color = \"interp\";\n                    have_cdata(data_idx) = true;\n                  endif\n                  ccol = mapcdata (ccol, obj.cdatamapping, clim, cmap_sz);\n                endif\n              elseif (isnumeric (ec))\n                color = ec;\n              else\n                color = [0, 0, 0];\n              endif\n            else\n              color = [0, 0, 0];\n            endif\n\n            lt = gnuplot_linestyletype (obj);\n\n            if (isfield (obj, \"linewidth\"))\n              lw = sprintf (\"linewidth %f\", obj.linewidth);\n            else\n              lw = \"\";\n            endif\n\n            [pt, pt2, obj] = gnuplot_pointtype (obj);\n            if (! isempty (pt))\n              pt = sprintf (\"pointtype %s\", pt);\n            endif\n            if (! isempty (pt2))\n              pt2 = sprintf (\"pointtype %s\", pt2);\n            endif\n\n            if (ischar (color))\n              if (columns (ccol) == 1)\n                colorspec = \"palette\";\n              elseif (columns (ccol) == 3)\n                colorspec = \"lc rgb variable\";\n                ccol = 255*ccol*double ([0x00_00_01; 0x00_01_00; 0x01_00_00]);\n              endif\n            else\n              colorspec = sprintf ('lc rgb \"#%02x%02x%02x\"',\n                                   uint8 (255*color));\n            endif\n\n            sidx = 1;\n            if (isempty (lt))\n              style = \"\";\n            else\n              style = \"lines\";\n            endif\n            tmpwith = {};\n\n            facesame = true;\n            if (! isequal (pt, pt2) && isfield (obj, \"markerfacecolor\")\n                && ! strcmp (obj.markerfacecolor, \"none\"))\n              if (strcmp (obj.markerfacecolor, \"auto\")\n                  || ! isnumeric (obj.markerfacecolor)\n                  || (isnumeric (obj.markerfacecolor)\n                      && isequal (color, obj.markerfacecolor)))\n                style = [style \"points\"];\n                if (isfield (obj, \"markersize\"))\n                  if (length (mdat) == nc)\n                    m = mdat(i);\n                  else\n                    m = mdat;\n                  endif\n                  ps = sprintf (\"pointsize %f\", m / 3);\n                else\n                  ps = \"\";\n                endif\n\n                tmpwith{sidx} = sprintf (\"with %s %s %s %s %s %s\",\n                                         style, lw, pt2, lt, ps,\n                                         colorspec);\n              else\n                facesame = false;\n                if (! isempty (style))\n                  tmpwith{sidx} = sprintf (\"with %s %s %s %s\",\n                                           style, lw, lt,\n                                           colorspec);\n                  sidx += 1;\n                endif\n                if (isnumeric (obj.markerfacecolor))\n                  colorspec = sprintf ('lc rgb \"#%02x%02x%02x\"',\n                                       round (255*obj.markerfacecolor));\n                endif\n                style = \"points\";\n                if (isfield (obj, \"markersize\"))\n                  if (length (mdat) == nc)\n                    m = mdat(i);\n                  else\n                    m = mdat;\n                  endif\n                  ps = sprintf (\"pointsize %f\", m / 3);\n                else\n                  ps = \"\";\n                endif\n                tmpwith{sidx} = sprintf (\"with %s %s %s %s %s %s\",\n                                         style, lw, pt2, lt, ps,\n                                         colorspec);\n              endif\n            endif\n\n            if (isfield (obj, \"markeredgecolor\")\n                && ! strcmp (obj.markeredgecolor, \"none\"))\n              if (facesame && ! isempty (pt)\n                  && (strcmp (obj.markeredgecolor, \"auto\")\n                      || ! isnumeric (obj.markeredgecolor)\n                      || (isnumeric (obj.markeredgecolor)\n                          && isequal (color, obj.markeredgecolor))))\n                if (sidx == 1 && ((length (style) == 5\n                         && strncmp (style, \"lines\", 5))\n                        || isempty (style)))\n                  style = [style, \"points\"];\n                  if (isfield (obj, \"markersize\"))\n                    if (length (mdat) == nc)\n                      m = mdat(i);\n                    else\n                      m = mdat;\n                    endif\n                    ps = sprintf (\"pointsize %f\", m / 3);\n                  else\n                    ps = \"\";\n                  endif\n                  tmpwith{sidx} = sprintf (\"with %s %s %s %s %s %s\",\n                                           style, lw, pt, lt, ps,\n                                           colorspec);\n                endif\n              else\n                if (! isempty (style))\n                  if (length (tmpwith) < sidx || isempty (tmpwith{sidx}))\n                    tmpwith{sidx} = sprintf (\"with %s %s %s %s\",\n                                             style, lw, lt,\n                                             colorspec);\n                  endif\n                  sidx += 1;\n                endif\n\n                if (! isempty (pt))\n                  if (strcmp (obj.markeredgecolor, \"auto\"))\n                    colorspec = sprintf ('lc rgb \"#%02x%02x%02x\"',\n                                         round (255*color));\n                  elseif (isnumeric (obj.markeredgecolor))\n                    colorspec = sprintf ('lc rgb \"#%02x%02x%02x\"',\n                                         round (255*obj.markeredgecolor));\n                  endif\n                  style = \"points\";\n                  if (isfield (obj, \"markersize\"))\n                    if (length (mdat) == nc)\n                      m = mdat(i);\n                    else\n                      m = mdat;\n                    endif\n                    ps = sprintf (\"pointsize %f\", m / 3);\n                  else\n                    ps = \"\";\n                  endif\n                  tmpwith{sidx} = sprintf (\"with %s %s %s %s %s %s\",\n                                           style, lw, pt, lt, ps,\n                                           colorspec);\n                endif\n              endif\n            endif\n\n            if (! isempty (tmpwith))\n              withclause{data_idx} = tmpwith{1};\n            else\n              if (! isempty (style))\n                withclause{data_idx} = sprintf (\"with %s %s %s %s %s\",\n                                                style, lw, pt, lt,\n                                                colorspec);\n              else\n                withclause{data_idx} = \"\";\n              endif\n            endif\n            if (nd == 3)\n              if (ischar (color))\n                if (! isnan (xcol) && ! isnan (ycol) && ! isnan (zcol))\n                  data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)], ...\n                                    [zcol; zcol(1)], [ccol; ccol(1)]]';\n                else\n                  data{data_idx} = [xcol, ycol, zcol, ccol]';\n                endif\n                usingclause{data_idx} = sprintf (\"record=%d using ($1):($2):($3):($4)\", columns (data{data_idx}));\n              else\n                if (! isnan (xcol) && ! isnan (ycol) && ! isnan (zcol))\n                  data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)], ...\n                                    [zcol; zcol(1)]]';\n                else\n                  data{data_idx} = [xcol, ycol, zcol]';\n                endif\n                usingclause{data_idx} = sprintf (\"record=%d using ($1):($2):($3)\", columns (data{data_idx}));\n              endif\n            else\n              if (ischar (color))\n                if (! isnan (xcol) && ! isnan (ycol))\n                  data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)], ...\n                                    [ccol; ccol(1)]]';\n                else\n                  data{data_idx} = [xcol, ycol, ccol]';\n                endif\n                usingclause{data_idx} = sprintf (\"record=%d using ($1):($2):($3)\", columns (data{data_idx}));\n              else\n                if (! isnan (xcol) && ! isnan (ycol))\n                  data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)]]';\n                else\n                  data{data_idx} = [xcol, ycol]';\n                endif\n                usingclause{data_idx} = sprintf (\"record=%d using ($1):($2)\", columns (data{data_idx}));\n              endif\n            endif\n\n            if (length (tmpwith) > 1)\n              data_idx += 1;\n              is_image_data(data_idx) = is_image_data(data_idx - 1);\n              parametric(data_idx) = parametric(data_idx - 1);\n              have_cdata(data_idx) = have_cdata(data_idx - 1);\n              have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);\n              titlespec{data_idx} = 'title \"\"';\n              usingclause{data_idx} = usingclause{data_idx - 1};\n              data{data_idx} = data{data_idx - 1};\n              withclause{data_idx} = tmpwith{2};\n            endif\n            if (length (tmpwith) > 2)\n              data_idx += 1;\n              is_image_data(data_idx) = is_image_data(data_idx - 1);\n              parametric(data_idx) = parametric(data_idx - 1);\n              have_cdata(data_idx) = have_cdata(data_idx - 1);\n              have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);\n              titlespec{data_idx} = 'title \"\"';\n              usingclause{data_idx} = usingclause{data_idx - 1};\n              data{data_idx} = data{data_idx - 1};\n              withclause{data_idx} = tmpwith{3};\n            endif\n          endif\n        endfor\n\n      case \"surface\"\n        view_map = true;\n        tspec = 'title \"\"';\n        if (! isempty (obj.displayname))\n          ## Place phantom line data for approximate legend symbol\n          data_idx += 1;\n          is_image_data(data_idx) = false;\n          parametric(data_idx) = false;\n          have_cdata(data_idx) = false;\n          have_3d_patch(data_idx) = false;\n          tmp = __maybe_munge_text__ (enhanced, obj, \"displayname\", ...\n                                      hlgndntrp, gnuplot_term);\n          titlespec{data_idx} = ['title \"' tmp '\"'];\n          data{data_idx} = NaN (3,1);\n          usingclause{data_idx} = sprintf (\"record=1 using ($1):($2):($3)\");\n          withclause{data_idx} = sprintf ('with line linewidth 10 linecolor rgb \"#%02x%02x%02x\"',\n                                          round (255*cmap(end/2,:)));\n        endif\n\n        xdat = obj.xdata;\n        ydat = obj.ydata;\n        zdat = obj.zdata;\n        cdat = mapcdata (obj.cdata, obj.cdatamapping, clim, cmap_sz);\n        err = false;\n        if (! size_equal (zdat, cdat))\n          err = true;\n        endif\n        if (isvector (xdat) && isvector (ydat) && ismatrix (zdat))\n          if (rows (zdat) == length (ydat)\n              && columns (zdat) == length (xdat))\n            [xdat, ydat] = meshgrid (xdat, ydat);\n          else\n            err = true;\n          endif\n        elseif (ismatrix (xdat) && ismatrix (ydat) && ismatrix (zdat))\n          if (! size_equal (xdat, ydat, zdat))\n            err = true;\n          endif\n        else\n          err = true;\n        endif\n        if (err)\n          error (\"__gnuplot_draw_axes__: invalid grid data\");\n        endif\n        xlen = columns (zdat);\n        ylen = rows (zdat);\n\n        if (! strcmp (obj.facecolor, \"none\"))\n          data_idx += 1;\n          is_image_data(data_idx) = false;\n          parametric(data_idx) = false;\n          have_cdata(data_idx) = true;\n          have_3d_patch(data_idx) = false;\n\n          titlespec{data_idx} = tspec;\n          tspec = 'title \"\"';\n\n          flat_interp_face = (strcmp (obj.facecolor, \"flat\")\n                              || strcmp (obj.facecolor, \"interp\"));\n\n          if (xlen == columns (xdat) && xlen == columns (ydat)\n              && ylen == rows (xdat) && ylen == rows (ydat))\n            len = 4 * xlen;\n            zz = zeros (ylen, len);\n            if (! flat_interp_face)\n              addedcmap = [addedcmap; obj.facecolor];\n            endif\n            k = 1;\n            for kk = 1:4:len\n              zz(:,kk)   = xdat(:,k);\n              zz(:,kk+1) = ydat(:,k);\n              zz(:,kk+2) = zdat(:,k);\n              if (flat_interp_face)\n                zz(:,kk+3) = cdat(:,k);\n              else\n                zz(:,kk+3) = cmap_sz + rows (addedcmap);\n              endif\n              k += 1;\n            endfor\n            data{data_idx} = zz.';\n          endif\n\n          doing_interp_color = strcmp (obj.facecolor, \"interp\");\n          if (doing_interp_color)\n            interp_str = \"interpolate 0, 0\";\n          else\n            ## No interpolation of facecolors.\n            interp_str = \"\";\n          endif\n          usingclause{data_idx} = sprintf (\"record=%dx%d using ($1):($2):($3):($4)\", ylen, xlen);\n\n          fputs (plot_stream, \"unset pm3d\\n\");\n          fputs (plot_stream, \"set style increment default;\\n\");\n          hidden_removal = true;\n          withclause{data_idx} = sprintf (\"with pm3d\");\n\n          if (doing_interp_color)\n            ## \"depthorder\" interferes with interpolation of colors.\n            dord = \"scansautomatic\";\n          else\n            dord = \"depthorder\";\n          endif\n\n          if (isscalar (obj.facealpha))\n            fprintf (plot_stream,\n                     \"set style fill transparent solid %f;\\n\",\n                     obj.facealpha);\n          endif\n          fprintf (plot_stream,\n                   \"set pm3d explicit at s %s %s corners2color c3;\\n\",\n                   interp_str, dord);\n        endif\n\n        draw_surf_line = ! strcmp (obj.linestyle, \"none\") && ! strcmp (obj.edgecolor, \"none\");\n        draw_surf_marker = (! strcmp (obj.marker, \"none\")\n                             && ! (strcmp (obj.markeredgecolor, \"none\")\n                                   && strcmp (obj.markerfacecolor, \"none\")));\n        if (draw_surf_line || draw_surf_marker)\n          flat_interp_edge = (strcmp (obj.edgecolor, \"flat\")\n                              || strcmp (obj.edgecolor, \"interp\"));\n          flat_marker = (strcmp (obj.markeredgecolor, \"flat\") || strcmp (obj.markerfacecolor, \"flat\")\n                         || strcmp (obj.markeredgecolor, \"auto\") || strcmp (obj.markerfacecolor, \"auto\"));\n          [style, sidx] = do_linestyle_command (obj, obj.edgecolor,\n                                                data_idx,\n                                                plot_stream);\n          domeshcolumn = (strcmp (obj.meshstyle, \"column\")\n                          || strcmp (obj.meshstyle, \"both\"));\n          domeshrow = (strcmp (obj.meshstyle, \"row\")\n                       || strcmp (obj.meshstyle, \"both\"));\n          num_pass = 0;\n          num_cols = 0;\n          if (domeshcolumn)\n            num_pass += xlen;\n            num_cols = xlen;\n          endif\n          if (domeshrow)\n            num_pass += ylen;\n          endif\n\n          for np = 1:num_pass\n            for i_stl = 1:length (style)\n              has_ccol = ((strncmp (style{i_stl}, \"lines\", 5)\n                           && flat_interp_edge)\n                          || (strncmp (style{i_stl}, \"points\", 6)\n                              && flat_marker));\n              if (has_ccol)\n                ccol = \":($4)\";\n                N_tup = 4;\n              else\n                ccol = \"\";\n                N_tup = 3;\n              endif\n              sopt = sprintf (\"ls %d\", sidx (i_stl));\n\n              if (np <= num_cols)\n                k = np;\n                yrec = ylen;\n                zz = zeros (ylen, N_tup);\n                zz(:,1) = xdat(:,k);\n                zz(:,2) = ydat(:,k);\n                zz(:,3) = zdat(:,k);\n                if (has_ccol)\n                  zz(:,4) = cdat(:,k);\n                endif\n              else\n                j = np - num_cols;\n                yrec = xlen;\n                zz = zeros (xlen, N_tup);\n                zz(:,1) = xdat(j,:)';\n                zz(:,2) = ydat(j,:)';\n                zz(:,3) = zdat(j,:)';\n                if (has_ccol)\n                  zz(:,4) = cdat(j,:)';\n                endif\n              endif\n\n              zz = zz.';\n\n              data_idx += 1;\n              is_image_data(data_idx) = false;\n              parametric(data_idx) = false;\n              if (has_ccol)\n                have_cdata(data_idx) = true;\n              else\n                have_cdata(data_idx) = false;\n              endif\n              have_3d_patch(data_idx) = false;\n              titlespec{data_idx} = tspec;\n              usingclause{data_idx} = sprintf (\"record=%dx1 using ($1):($2):($3)%s\",\n                                               yrec, ccol);\n              if (isempty (style{i_stl}))\n                style{i_stl} = \"points\";\n                data{data_idx} = {};\n              else\n                data{data_idx} = zz;\n              endif\n              withclause{data_idx} = sprintf (\"with %s %s\",\n                                              style{i_stl}, sopt);\n            endfor\n          endfor\n        endif\n\n      case \"text\"\n        do_text (plot_stream, gnuplot_term, enhanced, obj, h);\n\n      case \"hggroup\"\n        ## Push group children into the kid list.\n        if (isempty (kids))\n          kids = obj.children;\n        elseif (! isempty (obj.children))\n          kids = [kids; obj.children];\n        endif\n\n      case \"light\"\n        ## ignore it\n\n      otherwise\n        error (\"__gnuplot_draw_axes__: unknown object class, %s\", obj.type);\n    endswitch\n\n  endwhile\n\n  ## This is needed to prevent warnings for rotations in 3-D plots, while\n  ## allowing colorbars with contours.\n  if (nd == 2 || (data_idx > 1 && ! view_map))\n    fputs (plot_stream, \"set pm3d implicit;\\n\");\n  else\n    fputs (plot_stream, \"set pm3d explicit;\\n\");\n  endif\n\n  if (! isnan (hidden_removal) && hidden_removal)\n    fputs (plot_stream, \"set hidden3d front nooffset;\\n\");\n  else\n    fputs (plot_stream, \"unset hidden3d;\\n\");\n  endif\n\n  have_data = (! (isempty (data) || all (cellfun (\"isempty\", data))));\n\n  ## Note we don't use the [xy]2range of gnuplot as we don't use the\n  ## dual axis plotting features of gnuplot.\n  if (isempty (xlim))\n    return;\n  endif\n  if (strcmp (axis_obj.xdir, \"reverse\"))\n    xlim = flip (xlim);\n  endif\n\n  fprintf (plot_stream, \"set xrange [%.15e:%.15e];\\n\", xlim);\n  if (strcmp (axis_obj.xaxislocation, \"top\"))\n    fprintf (plot_stream, \"set x2range [%.15e:%.15e];\\n\", xlim);\n  endif\n\n  if (isempty (ylim))\n    return;\n  endif\n  if (strcmp (axis_obj.ydir, \"reverse\"))\n    ylim = flip (ylim);\n  endif\n  fprintf (plot_stream, \"set yrange [%.15e:%.15e];\\n\", ylim);\n  if (strcmp (axis_obj.yaxislocation, \"right\"))\n    fprintf (plot_stream, \"set y2range [%.15e:%.15e];\\n\", ylim);\n  endif\n\n  if (nd == 3)\n    if (isempty (zlim))\n      return;\n    endif\n    if (strcmp (axis_obj.zdir, \"reverse\"))\n      zlim = flip (zlim);\n    endif\n    fprintf (plot_stream, \"set zrange [%.15e:%.15e];\\n\", zlim);\n  endif\n\n  if (! any (isinf (clim)))\n    if (rows (addedcmap) > 0)\n      fprintf (plot_stream, \"set cbrange [1:%.15e];\\n\",\n               cmap_sz + rows (addedcmap));\n    else\n      fprintf (plot_stream, \"set cbrange [1:%.15e];\\n\", max ([cmap_sz 2]));\n    endif\n  endif\n\n  if (strcmp (axis_obj.visible, \"off\"))\n    fputs (plot_stream, \"unset border; unset tics\\n\");\n  else\n    fputs (plot_stream, \"unset border\\n\");\n    axis_idx = data_idx;\n    if (strcmp (axis_obj.box, \"on\"))\n      if (nd == 3)\n        do_border_tick_3d (axis_obj, plot_stream);\n      else\n        axis_idx = do_border_2d (axis_obj, plot_stream, axis_idx);\n      endif\n    else\n      if (nd == 3)\n        do_border_tick_3d (axis_obj, plot_stream);\n      else\n        axis_idx = do_border_2d (axis_obj, plot_stream, axis_idx);\n        if (isempty (axis_obj.xtick))\n        elseif (strcmp (axis_obj.xaxislocation, \"top\"))\n          fprintf (plot_stream, \"set x2tics %s nomirror\\n\", axis_obj.tickdir);\n        else # xaxislocation == \"bottom\" or \"origin\"\n          fprintf (plot_stream, \"set xtics %s nomirror\\n\", axis_obj.tickdir);\n        endif\n        if (isempty (axis_obj.ytick))\n        elseif (strcmp (axis_obj.yaxislocation, \"right\"))\n          fprintf (plot_stream, \"set y2tics %s nomirror\\n\", axis_obj.tickdir);\n        else # yaxislocation == \"left\" or \"origin\"\n          fprintf (plot_stream, \"set ytics %s nomirror\\n\",  axis_obj.tickdir);\n        endif\n      endif\n    endif\n  endif\n\n  if (! have_major_grid && ! have_minor_grid)\n    fputs (plot_stream, \"unset grid;\\n\");\n  else\n    if (exist (\"axis_idx\", \"var\"))\n      grid_idx = axis_idx;\n    else\n      grid_idx = data_idx;\n    endif\n    if (have_major_grid)\n      grid_idx += 1;\n      grid_obj.linestyle = axis_obj.gridlinestyle;\n      grid_obj.linewidth = axis_obj.linewidth;\n      grid_obj.alpha = axis_obj.gridalpha;\n      [style, sidx_major] = do_linestyle_command (grid_obj, axis_obj.gridcolor,\n                                                  grid_idx, plot_stream);\n    else\n      sidx_major = 0;\n    endif\n    if (have_minor_grid)\n      grid_idx += 1;\n      grid_obj.linestyle = axis_obj.minorgridlinestyle;\n      grid_obj.linewidth = axis_obj.linewidth;\n      grid_obj.alpha = axis_obj.minorgridalpha;\n      [style, sidx_minor] = do_linestyle_command (grid_obj,\n                                                  axis_obj.minorgridcolor,\n                                                  grid_idx, plot_stream);\n    else\n      sidx_minor = 0;\n    endif\n    fprintf (plot_stream, \"set grid linestyle %d, linestyle %d;\\n\",\n             sidx_major, sidx_minor);\n  endif\n\n  if (! isempty (hlgnd) && strcmp (hlgnd.visible, \"on\")\n      && ! isempty (hlgnd.children)\n      && any (strcmp (get ([getappdata(hlgnd.children, \"handle\"){:}], \"visible\"),\n                      \"on\")))\n\n    if (strcmp (hlgnd.box, \"on\"))\n      box = \"box\";\n    else\n      box = \"nobox\";\n    endif\n    if (strcmp (hlgnd.orientation, \"vertical\"))\n      horzvert = \"vertical\";\n    else\n      horzvert = \"horizontal\";\n    endif\n    if (strcmp (hlgnd.textposition, \"right\"))\n      reverse = \"reverse Left\";\n    else\n      reverse = \"noreverse Right\";\n    endif\n    inout = \"inside\";\n    keypos = hlgnd.location;\n    if (ischar (keypos))\n      keypos = lower (keypos);\n      keyout = strfind (keypos, \"outside\");\n      if (! isempty (keyout))\n        inout = \"outside\";\n        keypos = keypos(1:keyout-1);\n      endif\n    endif\n    switch (keypos)\n      case \"north\"\n        pos = \"center top\";\n      case \"south\"\n        pos = \"center bottom\";\n      case \"east\"\n        pos = \"right center\";\n      case \"west\"\n        pos = \"left center\";\n      case \"northeast\"\n        pos = \"right top\";\n      case \"northwest\"\n        pos = \"left top\";\n      case \"southeast\"\n        pos = \"right bottom\";\n      case \"southwest\"\n        pos = \"left bottom\";\n      case \"best\"\n        pos = \"\";\n        warning (\"legend: 'Best' not yet implemented for location specifier.\\n\");\n        ## Least conflict with data in plot.\n        ## Least unused space outside plot.\n      otherwise\n        pos = \"\";\n    endswitch\n    [fontname, fontsize] = get_fontname_and_size (hlgnd);\n    fontspacespec = [create_spacingspec(fontname, fontsize, gnuplot_term),...\n                     ' ', create_fontspec(fontname, fontsize, gnuplot_term)];\n    textcolors = get (findobj (hlgnd.children, \"type\", \"text\"), \"color\");\n    if (iscell (textcolors))\n      textcolors = cell2mat (textcolors);\n      textcolors = unique (textcolors, \"rows\");\n    endif\n    if (rows (textcolors) > 1)\n      ## Gnuplot is unable to assign arbitrary colors to each text entry\n      ## for the key/legend.  But, the text color can be set to match the\n      ## color of the plot object.\n      colorspec = \"textcolor variable\";\n    else\n      colorspec = get_text_colorspec (textcolors);\n    endif\n    fprintf (plot_stream, \"set key %s %s;\\nset key %s %s %s %s %s %s;\\n\",\n             inout, pos, box, reverse, horzvert, fontspacespec, colorspec,\n             __do_enhanced_option__ (enhanced, hlgnd));\n  else\n    fputs (plot_stream, \"unset key;\\n\");\n  endif\n  fputs (plot_stream, \"set style data lines;\\n\");\n\n  cmap = [cmap; addedcmap];\n  cmap_sz += rows (addedcmap);\n  if (cmap_sz == 1)        # bug #48083, illegal one-element colormap\n    cmap = [cmap; cmap];\n    cmap_sz = 2;\n  endif\n  if (length (cmap) > 0)\n    fprintf (plot_stream,\n             \"set palette positive color model RGB maxcolors %i;\\n\",\n             cmap_sz);\n    fprintf (plot_stream,\n             ['set palette file \"-\" binary record=%d using 1:2:3:4;' \"\\n\"],\n             cmap_sz);\n    fwrite (plot_stream, [1:cmap_sz; cmap.'], \"float32\");\n    fwrite (plot_stream, \"\\n\");\n  endif\n\n  fputs (plot_stream, \"unset colorbox;\\n\");\n\n  if (have_data)\n    for i = 1:data_idx\n      ## Images can be obscured by background or foreground image\n      if (is_image_data (i))\n        if (bg_is_set)\n          fputs (plot_stream, ['if (GPVAL_TERM eq \"qt\") unset obj 1;' \"\\n\"]);\n          bg_is_set = false;\n        endif\n        if (fg_is_set)\n          fputs (plot_stream, \"unset obj 2; \\\\\\n\");\n          fg_is_set = false;\n        endif\n        break;\n      endif\n    endfor\n    if (nd == 2)\n      plot_cmd = \"plot\";\n    else\n      plot_cmd = \"splot\";\n      ## Wrap view correctly to match Matlab\n      if (axis_obj.view(2) <= 90)\n        rot_x = 90 - axis_obj.view(2);\n      else\n        rot_x = axis_obj.view(2) - 90;\n      endif\n      rot_x = mod (rot_x, 360);\n      while (rot_x < 0)\n        rot_x += 360;\n      endwhile\n      if (axis_obj.view(2) <= 90)\n        rot_z = axis_obj.view(1);\n      else\n        rot_z = axis_obj.view(1) + 180;\n      endif\n      rot_z = mod (rot_z, 360);\n      while (rot_z < 0)\n        rot_z += 360;\n      endwhile\n      fputs (plot_stream, \"set ticslevel 0;\\n\");\n      if (view_map && rot_x == 0 && rot_z == 0)\n        fputs (plot_stream, \"set view map;\\n\");\n      else\n        fprintf (plot_stream, \"set view %.15g, %.15g;\\n\", rot_x, rot_z);\n      endif\n    endif\n    if (have_3d_patch (1))\n      fputs (plot_stream, \"set pm3d depthorder\\n\");\n      ## FIXME: Must leave strings ending in '\\', CHAR in double quotes.\n      ## Otherwise, fprintf routine tries to do escape processing and fails.\n      fprintf (plot_stream, \"%s \\\"-\\\" %s %s %s \\\\\\n\", plot_cmd,\n               usingclause{1}, titlespec{1}, withclause{1});\n    elseif (is_image_data (1))\n      fprintf (plot_stream, \"%s \\\"-\\\" %s %s %s \\\\\\n\", plot_cmd,\n               usingclause{1}, titlespec{1}, withclause{1});\n    else\n      fprintf (plot_stream, \"%s \\\"-\\\" binary format='%%float64' %s %s %s \\\\\\n\",\n               plot_cmd, usingclause{1}, titlespec{1}, withclause{1});\n    endif\n    for i = 2:data_idx\n      if (have_3d_patch (i))\n        fprintf (plot_stream, \", \\\"-\\\" %s %s %s \\\\\\n\",\n                 usingclause{i}, titlespec{i}, withclause{i});\n      elseif (is_image_data (i))\n        fprintf (plot_stream, \"%s \\\"-\\\" %s %s %s \\\\\\n\", \",\",\n                 usingclause{i}, titlespec{i}, withclause{i});\n      else\n        fprintf (plot_stream, \", \\\"-\\\" binary format='%%float64' %s %s %s \\\\\\n\",\n                 usingclause{i}, titlespec{i}, withclause{i});\n      endif\n    endfor\n    fputs (plot_stream, \";\\n\");\n    for i = 1:data_idx\n      if (have_3d_patch (i))\n        ## Can't write 3-D patch data as binary as can't plot more than\n        ## a single patch at a time and have to plot all patches together\n        ## so that the gnuplot depth ordering is done correctly\n        for j = 1 : 4 : columns (data{i})\n          if (j != 1)\n            fputs (plot_stream, \"\\n\\n\");\n          endif\n          fprintf (plot_stream, \"%.15g %.15g %.15g %.15g\\n\", data{i}(:,j).');\n          fprintf (plot_stream, \"%.15g %.15g %.15g %.15g\\n\\n\", data{i}(:,j+1).');\n          fprintf (plot_stream, \"%.15g %.15g %.15g %.15g\\n\", data{i}(:,j+2).');\n          fprintf (plot_stream, \"%.15g %.15g %.15g %.15g\\n\", data{i}(:,j+3).');\n        endfor\n        fputs (plot_stream, \"e\\n\");\n      elseif (is_image_data(i))\n        fwrite (plot_stream, data{i}, \"float32\");\n      else\n        __gnuplot_write_data__ (plot_stream, data{i}, nd, parametric(i),\n                                have_cdata(i));\n      endif\n    endfor\n    fputs (plot_stream, \"\\n\");\n  else\n    fputs (plot_stream, \"plot \\\"-\\\";\\nInf Inf\\ne\\n\");\n  endif\n\n  ## Needed to allow mouse rotation if gnuplot was put in map view.\n  if (view_map && rot_x == 0 && rot_z == 0)\n    fputs (plot_stream, \"set view 0,0;\\n\");\n  endif\n\n  ## Undo the aspect ratio lock imposed by the gnuplot command sequence:\n  ##   \"set view equal xy; set view map\"\n  ## See bug #40686: \"Incorrect colorbar size\"\n  if (nd == 3\n      && strcmp (axis_obj.dataaspectratiomode, \"manual\")\n      && axis_obj.dataaspectratio(1) == axis_obj.dataaspectratio(2))\n    fprintf (plot_stream, \"set size noratio;\\n\");\n  endif\n\n  if (bg_is_set)\n    fputs (plot_stream, ['if (GPVAL_TERM eq \"qt\") unset obj 1;' \"\\n\"]);\n    bg_is_set = false;\n  endif\n\n  fflush (plot_stream);\n\nendfunction\n\nfunction x = flip (x)\n\n  if (rows (x) == 1)\n    x = fliplr (x);\n  elseif (columns (x) == 1 || ischar (x))\n    x = flipud (x);\n  else\n    x = flipud (fliplr (x));\n  endif\n\nendfunction\n\nfunction spacing_spec = create_spacingspec (f, s, gp_term)\n\n  ## The gnuplot default font size is 10, and default spacing is 1.25.\n  ## gnuplot has a concept of a figure global font, and sizes everything\n  ## appropriate to that, including the legend spacing.\n  ##\n  ## This means that if an alternative size is used, gnuplot will use an\n  ## inappropriate spacing in the legend by default.\n  ##\n  ## FIXME: Are fractional spacing specifications allowed?  Or should this\n  ##        number be rounded?\n  spc = s / 10 * 1.25;\n  spacing_spec = sprintf (\"spacing %d\", spc);\n\nendfunction\n\nfunction fontspec = create_fontspec (f, s, gp_term)\n\n  if (isempty (f) || strcmp (f, \"*\") || strcmp (gp_term, \"tikz\"))\n    fontspec = sprintf ('font \",%d\"', s);\n  else\n    fontspec = sprintf ('font \"%s,%d\"', f, s);\n  endif\n\nendfunction\n\nfunction idx = do_border_2d (obj, plot_stream, idx)\n\n  fprintf (plot_stream, \"set border 0\\n\");\n  fprintf (plot_stream, \"unset arrow\\n\");\n\n  if (strcmp (obj.box, \"on\") || strcmp (obj.xaxislocation, \"bottom\"))\n    arrow (1, obj.xcolor, obj.linewidth, [0,0,0], [1,0,0]);\n  endif\n  if (strcmp (obj.box, \"on\") || strcmp (obj.xaxislocation, \"top\"))\n    arrow (2, obj.xcolor, obj.linewidth, [0,1,0], [1,1,0]);\n  endif\n  if (strcmp (obj.box, \"on\") || strcmp (obj.yaxislocation, \"left\"))\n    arrow (3, obj.ycolor, obj.linewidth, [0,0,0], [0,1,0]);\n  endif\n  if (strcmp (obj.box, \"on\") || strcmp (obj.yaxislocation, \"right\"))\n    arrow (4, obj.ycolor, obj.linewidth, [1,0,0], [1,1,0]);\n  endif\n\n  if (strcmp (obj.xaxislocation, \"origin\"))\n    idx = zeroaxis (idx, obj.xcolor, \"x\");\n  endif\n  if (strcmp (obj.yaxislocation, \"origin\"))\n    idx = zeroaxis (idx, obj.ycolor, \"y\");\n  endif\n\n  function idx = zeroaxis (idx, lc, ax)\n    idx = idx + 1;\n    [~, ltidx] = do_linestyle_command (obj, lc, idx, plot_stream);\n    fprintf (plot_stream, \"set %szeroaxis ls %d \", ax, ltidx);\n    fprintf (plot_stream, \"lw %.3f\\n\", obj.linewidth);\n  endfunction\n\n  function arrow (idx, lc, lw, from, to)\n    fprintf (plot_stream, \"set arrow %d \", idx);\n    fprintf (plot_stream, \"nohead nofilled front \");\n    fprintf (plot_stream, \"lc rgb \"\"#%02x%02x%02x\"\" \", round (255 * lc));\n    fprintf (plot_stream, \"linewidth %.3f \", obj.linewidth);\n    fprintf (plot_stream, \"from graph %d,%d,%d \", from);\n    fprintf (plot_stream, \"to graph %d,%d,%d\\n\", to);\n  endfunction\n\nendfunction\n\nfunction idx = do_border_tick_3d (obj, plot_stream, idx)\n\n  ## axis location has no effect\n\n  if (strcmp (obj.box, \"on\"))\n    fputs (plot_stream, \"set border 0xFFF;\\n\");\n    mirrorstr = \"mirror\";\n  else\n    fputs (plot_stream, \"set border 0x15;\\n\");\n    mirrorstr = \"nomirror\";\n  endif\n\n  tick ('x', obj.xcolor, obj.tickdir, mirrorstr);\n  tick ('y', obj.ycolor, obj.tickdir, mirrorstr);\n  tick ('z', obj.zcolor, obj.tickdir, mirrorstr);\n\n  function tick (axischar, color, tickdir, mirrorstr)\n\n    if (isnumeric (color))\n      if (length (color) == 3)\n        colorspec = sprintf ('rgb \"#%02x%02x%02x\"', round (255*color));\n      else\n        colorspec = sprintf (\"palette %d\", round (color));\n      endif\n    else\n      colorspec = sprintf ('\"%s\"', color);\n    endif\n    fprintf (plot_stream, \"set %ctics %s %s textcolor %s\\n\",\n             axischar, tickdir, mirrorstr, colorspec);\n\n  endfunction\n\nendfunction\n\nfunction [style, ltidx] = do_linestyle_command (obj, linecolor, idx,\n                                                plot_stream)\n\n  idx = idx + 8;\n  style = {};\n  ltidx = [];\n\n  fprintf (plot_stream, \"set style line %d default;\\n\", idx);\n  fprintf (plot_stream, \"set style line %d\", idx);\n\n  found_style = false;\n  if (isnumeric (linecolor))\n    color = linecolor;\n    if (isfield (obj, \"alpha\")\n        &&  __gnuplot_has_feature__ (\"alphablend_linecolor\"))\n      alphastr = sprintf (\"%02x\", round (255*(1-obj.alpha)));\n    else\n      alphastr = \"\";\n    endif\n    fprintf (plot_stream, ' linecolor rgb \"#%s%02x%02x%02x\"',\n             alphastr, round (255*color));\n  else\n    color = [0, 0, 0];\n    flat_interp_edge = (strcmp (obj.edgecolor, \"flat\")\n                        || strcmp (obj.edgecolor, \"interp\"));\n    if (flat_interp_edge)\n        fprintf (plot_stream, \" palette\");\n    endif\n  endif\n\n  lt = gnuplot_linestyletype (obj);\n  if (! isempty (lt))\n    fprintf (plot_stream, \" %s\", lt);\n  endif\n\n  if (isfield (obj, \"linewidth\"))\n    fprintf (plot_stream, \" linewidth %f\", obj.linewidth);\n    found_style = true;\n  endif\n\n  [pt, pt2, obj] = gnuplot_pointtype (obj);\n\n  if (! isempty (pt))\n    found_style = true;\n  endif\n\n  sidx = 1;\n  if (isempty (lt))\n    style{sidx} = \"\";\n  else\n    style{sidx} = \"lines\";\n  endif\n  ltidx(sidx) = idx;\n\n  facesame = true;\n  if (! isequal (pt, pt2) && isfield (obj, \"markerfacecolor\")\n      && ! strcmp (obj.markerfacecolor, \"none\"))\n    if (strcmp (obj.markerfacecolor, \"auto\")\n        || (isnumeric (obj.markerfacecolor)\n            && isequal (color, obj.markerfacecolor)))\n      if (! isempty (pt2))\n        fprintf (plot_stream, \" pointtype %s\", pt2);\n        style{sidx} = [style{sidx} \"points\"];\n      endif\n      if (isfield (obj, \"markersize\"))\n        fprintf (plot_stream, \" pointsize %f\", obj.markersize / 3);\n      endif\n    else\n      facesame = false;\n      if (! found_style)\n        fputs (plot_stream, \" default\");\n      endif\n      fputs (plot_stream, \";\\n\");\n      if (! isempty (style{sidx}))\n        sidx += 1;\n        idx += 1;\n      else\n        fputs (plot_stream, \";\\n\");\n      endif\n      fprintf (plot_stream, \"set style line %d default;\\n\", idx);\n      fprintf (plot_stream, \"set style line %d\", idx);\n      if (isnumeric (obj.markerfacecolor))\n        fprintf (plot_stream, ' linecolor rgb \"#%02x%02x%02x\"',\n                 round (255*obj.markerfacecolor));\n      else\n        fprintf (plot_stream, \" palette\");\n      endif\n      if (! isempty (pt2))\n        style{sidx} = \"points\";\n        ltidx(sidx) = idx;\n        fprintf (plot_stream, \" pointtype %s\", pt2);\n      endif\n      if (isfield (obj, \"markersize\"))\n        fprintf (plot_stream, \" pointsize %f\", obj.markersize / 3);\n      endif\n    endif\n  endif\n  if (! isempty (pt) && isfield (obj, \"markeredgecolor\")\n      && ! strcmp (obj.markeredgecolor, \"none\"))\n    if (facesame && (strcmp (obj.markeredgecolor, \"auto\")\n        || (isnumeric (obj.markeredgecolor)\n            && isequal (color, obj.markeredgecolor))))\n      if (sidx == 1 && ((length (style{sidx}) == 5\n          && strncmp (style{sidx}, \"lines\", 5)) || isempty (style{sidx})))\n        style{sidx} = [style{sidx} \"points\"];\n        fprintf (plot_stream, \" pointtype %s\", pt);\n        if (isfield (obj, \"markersize\"))\n          fprintf (plot_stream, \" pointsize %f\", obj.markersize / 3);\n        endif\n      endif\n    else\n      if (! found_style)\n        fputs (plot_stream, \" default\");\n      endif\n      fputs (plot_stream, \";\\n\");\n      if (! isempty (style{sidx}))\n        sidx += 1;\n        idx += 1;\n      else\n        fputs (plot_stream, \";\\n\");\n      endif\n      fprintf (plot_stream, \"set style line %d default;\\n\", idx);\n      fprintf (plot_stream, \"set style line %d\", idx);\n      if (isnumeric (obj.markeredgecolor) || strcmp (obj.markeredgecolor, \"auto\"))\n        if (isnumeric (obj.markeredgecolor))\n          edgecolor = obj.markeredgecolor;\n        else\n          edgecolor = obj.color;\n        endif\n        fprintf (plot_stream, ' linecolor rgb \"#%02x%02x%02x\"',\n                 round (255*edgecolor));\n      else\n        fprintf (plot_stream, \" palette\");\n      endif\n      style{sidx} = \"points\";\n      ltidx(sidx) = idx;\n      fprintf (plot_stream, \" pointtype %s\", pt);\n      if (isfield (obj, \"markersize\"))\n        fprintf (plot_stream, \" pointsize %f\", obj.markersize / 3);\n      endif\n    endif\n  endif\n\n  if (! found_style && isempty (style{1}))\n    fputs (plot_stream, \" default\");\n  endif\n\n  fputs (plot_stream, \";\\n\");\n\nendfunction\n\nfunction lt = gnuplot_linestyletype (obj)\n\n  if (isfield (obj, \"linestyle\"))\n    if (__gnuplot_has_feature__ (\"dashtype\"))\n      opt = \"dashtype\";\n      switch (obj.linestyle)\n        case \"-\"\n          lt = \"solid\";\n        case \"--\"\n          lt = \"'_ '\";\n        case \":\"\n          lt = \"'. '\";\n        case \"-.\"\n          lt = \"'-. '\";\n        case \"none\"\n          lt = \"\";\n        otherwise\n          lt = \"\";\n      endswitch\n    else\n      opt = \"linetype\";\n      switch (obj.linestyle)\n        case \"-\"\n          lt = \"1\";\n        case \"--\"\n          lt = \"2\";\n        case \":\"\n          lt = \"3\";\n        case \"-.\"\n          lt = \"6\";\n        case \"none\"\n          lt = \"\";\n        otherwise\n          lt = \"\";\n      endswitch\n    endif\n    if (! isempty (lt))\n      lt = sprintf (\"%s %s\", opt, lt);\n    endif\n  else\n    lt = \"\";\n  endif\n\nendfunction\n\nfunction [pt, pt2, obj] = gnuplot_pointtype (obj)\n\n  if (isfield (obj, \"marker\"))\n    switch (obj.marker)\n      case \"+\"\n        pt = pt2 = \"1\";\n      ## FIXME: It's not clear how to add support for these markers in gnuplot\n      #{\n      case \"|\"\n        pt = \"1\";\n        pt2 = \"1\";\n      case \"_\"\n        pt = \"1\";\n        pt2 = \"1\";\n      #}\n      case \"o\"\n        pt = \"6\";\n        pt2 = \"7\";\n      case \"*\"\n        pt = pt2 = \"3\";\n      case \".\"\n        pt = pt2 = \"7\";\n        if (isfield (obj, \"markersize\"))\n          obj.markersize /= 3;\n        else\n          obj.markersize = 5;\n        endif\n      case \"x\"\n        pt = pt2 = \"2\";\n      case {\"square\", \"s\"}\n        pt = \"4\";\n        pt2 = \"5\";\n      case {\"diamond\", \"d\"}\n        pt = \"12\";\n        pt2 = \"13\";\n      case \"^\"\n        pt = \"8\";\n        pt2 = \"9\";\n      case \"v\"\n        pt = \"10\";\n        pt2 = \"11\";\n      case \">\"\n        ## FIXME: Should be triangle pointing right, use triangle pointing up\n        pt = \"8\";\n        pt2 = \"9\";\n      case \"<\"\n        ## FIXME: Should be triangle pointing left, use triangle pointing down\n        pt = \"10\";\n        pt2 = \"11\";\n      case {\"pentagram\", \"p\"}\n        ## FIXME: Should be pentagram, using pentagon\n        pt = \"14\";\n        pt2 = \"15\";\n      case {\"hexagram\", \"h\"}\n        ## FIXME: Should be 6 pt start, using \"*\" instead\n        pt = pt2 = \"3\";\n      case \"none\"\n        pt = pt2 = \"-1\";\n      otherwise\n        pt = pt2 = \"\";\n    endswitch\n  else\n    pt = pt2 = \"\";\n  endif\n\nendfunction\n\nfunction __gnuplot_write_data__ (plot_stream, data, nd, parametric, cdata)\n\n  ## DATA is already transposed.\n\n  ## Convert NA elements to normal NaN values because fprintf writes\n  ## \"NA\" and that confuses gnuplot.\n  data(isna (data)) = NaN;\n\n  if (nd == 2)\n    fwrite (plot_stream, data, \"float64\");\n  elseif (nd == 3)\n    if (parametric)\n      fwrite (plot_stream, data, \"float64\");\n    else\n      nr = rows (data);\n      if (cdata)\n        for j = 1:4:nr\n          fwrite (plot_stream, data(j:j+3,:), \"float64\");\n        endfor\n      else\n        for j = 1:3:nr\n          fwrite (plot_stream, data(j:j+2,:), \"float64\");\n        endfor\n      endif\n    endif\n  endif\n\nendfunction\n\nfunction do_tics (obj, plot_stream, ymirror, gnuplot_term)\n\n  obj.xticklabel = ticklabel_to_cell (obj.xticklabel);\n  obj.yticklabel = ticklabel_to_cell (obj.yticklabel);\n  obj.zticklabel = ticklabel_to_cell (obj.zticklabel);\n\n  if (strcmp (obj.xminorgrid, \"on\"))\n    obj.xminortick = \"on\";\n  endif\n  if (strcmp (obj.yminorgrid, \"on\"))\n    obj.yminortick = \"on\";\n  endif\n  if (strcmp (obj.zminorgrid, \"on\"))\n    obj.zminortick = \"on\";\n  endif\n\n  [fontname, fontsize] = get_fontname_and_size (obj);\n  fontspec = create_fontspec (fontname, fontsize, gnuplot_term);\n\n  ## A Gnuplot tic scale of 69 is equivalent to Octave's 0.5.\n  ticklength = sprintf (\"scale %4.1f\", (69/0.5)*obj.ticklength(1));\n\n  if (strcmp (obj.xaxislocation, \"top\"))\n    do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,\n               obj.xticklabel, obj.xcolor, \"x2\", plot_stream, true,\n               \"border\", obj.tickdir, ticklength, fontname, fontspec,\n               obj.ticklabelinterpreter, obj.xscale, obj.xsgn, gnuplot_term);\n    do_tics_1 (\"manual\", [], \"off\", obj.xticklabelmode, obj.xticklabel,\n               obj.xcolor, \"x\", plot_stream, true, \"border\",\n               \"\", \"\", fontname, fontspec, obj.ticklabelinterpreter,\n               obj.xscale, obj.xsgn, gnuplot_term);\n  elseif (strcmp (obj.xaxislocation, \"origin\"))\n    do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,\n               obj.xticklabel, obj.xcolor, \"x\", plot_stream, true,\n               \"axis\", obj.tickdir, ticklength, fontname, fontspec,\n               obj.ticklabelinterpreter, obj.xscale, obj.xsgn, gnuplot_term);\n    do_tics_1 (\"manual\", [], \"off\", obj.xticklabelmode, obj.xticklabel,\n               obj.xcolor, \"x2\", plot_stream, true, \"axis\",\n               \"\", \"\", fontname, fontspec, obj.ticklabelinterpreter,\n               obj.xscale, obj.xsgn, gnuplot_term);\n  else\n    do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,\n               obj.xticklabel, obj.xcolor, \"x\", plot_stream, true,\n               \"border\", obj.tickdir, ticklength, fontname, fontspec,\n               obj.ticklabelinterpreter, obj.xscale, obj.xsgn, gnuplot_term);\n    do_tics_1 (\"manual\", [], \"off\", obj.xticklabelmode, obj.xticklabel,\n               obj.xcolor, \"x2\", plot_stream, true, \"border\",\n               \"\", \"\", fontname, fontspec, obj.ticklabelinterpreter,\n               obj.xscale, obj.xsgn, gnuplot_term);\n  endif\n  if (strcmp (obj.yaxislocation, \"right\"))\n    do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,\n               obj.yticklabel, obj.ycolor, \"y2\", plot_stream, ymirror,\n               \"border\", obj.tickdir, ticklength, fontname, fontspec,\n               obj.ticklabelinterpreter, obj.yscale, obj.ysgn, gnuplot_term);\n    do_tics_1 (\"manual\", [], \"off\", obj.yticklabelmode, obj.yticklabel,\n               obj.ycolor, \"y\", plot_stream, ymirror, \"border\",\n               \"\", \"\", fontname, fontspec, obj.ticklabelinterpreter,\n               obj.yscale, obj.ysgn, gnuplot_term);\n  elseif (strcmp (obj.yaxislocation, \"origin\"))\n    do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,\n               obj.yticklabel, obj.ycolor, \"y\", plot_stream, ymirror,\n               \"axis\", obj.tickdir, ticklength, fontname, fontspec,\n               obj.ticklabelinterpreter, obj.yscale, obj.ysgn, gnuplot_term);\n    do_tics_1 (\"manual\", [], \"off\", obj.yticklabelmode, obj.yticklabel,\n               obj.ycolor, \"y2\", plot_stream, ymirror, \"axis\",\n               \"\", \"\", fontname, fontspec, obj.ticklabelinterpreter,\n               obj.yscale, obj.ysgn, gnuplot_term);\n  else\n    do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,\n               obj.yticklabel, obj.ycolor, \"y\", plot_stream, ymirror,\n               \"border\", obj.tickdir, ticklength, fontname, fontspec,\n               obj.ticklabelinterpreter, obj.yscale, obj.ysgn, gnuplot_term);\n    do_tics_1 (\"manual\", [], \"off\", obj.yticklabelmode, obj.yticklabel,\n               obj.ycolor, \"y2\", plot_stream, ymirror, \"border\",\n               \"\", \"\", fontname, fontspec, obj.ticklabelinterpreter,\n               obj.yscale, obj.ysgn, gnuplot_term);\n  endif\n  do_tics_1 (obj.ztickmode, obj.ztick, obj.zminortick, obj.zticklabelmode,\n             obj.zticklabel, obj.zcolor, \"z\", plot_stream, true,\n             \"border\", obj.tickdir, ticklength, fontname, fontspec,\n             obj.ticklabelinterpreter, obj.zscale, obj.zsgn, gnuplot_term);\n\nendfunction\n\nfunction do_tics_1 (ticmode, tics, mtics, labelmode, labels, color, ax,\n                    plot_stream, mirror, axispos, tickdir, ticklength,\n                    fontname, fontspec, interpreter, scale, sgn, gnuplot_term)\n  persistent warned_latex = false;\n\n  ## Avoid emitting anything if the tics are empty, because this undoes the\n  ## effect of the previous unset xtics and thereby adds back in the tics.\n  if (isempty (tics))\n    return;\n  endif\n\n  if (mirror)\n    mirror = \"mirror\";\n  else\n    mirror = \"nomirror\";\n  endif\n  if (strcmp (interpreter, \"tex\"))\n    for n = 1 : numel (labels)\n      labels{n} = __tex2enhanced__ (labels{n}, fontname, false, false, ...\n                                    gnuplot_term);\n    endfor\n  elseif (strcmp (interpreter, \"latex\"))\n    if (! warned_latex)\n      do_warn = (warning (\"query\", \"Octave:text_interpreter\")).state;\n      if (strcmp (do_warn, \"on\"))\n        warning (\"Octave:text_interpreter\",\n                 \"latex markup not supported for tick marks\");\n        warned_latex = true;\n      endif\n    endif\n  endif\n  if (strcmp (scale, \"log\"))\n    num_mtics = 10;\n    if (any (strcmp (gnuplot_term, {\"cairolatex\", \"eepic\", \"epslatex\", ...\n        \"latex\", \"pslatex\", \"pstex\", \"pstricks\", \"texdraw\", \"tikz\"})))\n      fmt = \"$10^{%T}$\";\n    else\n      fmt = \"10^{%T}\";\n    endif\n    if (sgn < 0)\n      fmt = [\"-\" fmt];\n    endif\n  else\n    fmt = \"%g\";\n    num_mtics = 5;\n  endif\n  colorspec = get_text_colorspec (color);\n  fprintf (plot_stream, ['set format %s \"%s\";' \"\\n\"], ax, fmt);\n  if (strcmp (ticmode, \"manual\") && isempty (tics))\n    fprintf (plot_stream, \"unset %stics;\\nunset m%stics;\\n\", ax, ax);\n    return;\n  else\n    k = 1;\n    ntics = numel (tics);\n    labels(end+1:1) = {\"\"};\n    labels = repmat (labels(:), ceil (ntics/numel (labels)), 1);\n    fprintf (plot_stream, \"set %stics %s %s %s %s (\", ax,\n             tickdir, ticklength, axispos, mirror);\n    labels = strrep (labels, \"%\", \"%%\");\n    for i = 1:ntics\n      fprintf (plot_stream, ' \"%s\" %.15f', labels{k++}, tics(i));\n      if (i < ntics)\n        fputs (plot_stream, \", \");\n      endif\n    endfor\n    fprintf (plot_stream, \") %s %s;\\n\", colorspec, fontspec);\n  endif\n  if (strcmp (mtics, \"on\"))\n    fprintf (plot_stream, \"set m%stics %d;\\n\", ax, num_mtics);\n  else\n    fprintf (plot_stream, \"unset m%stics;\\n\", ax);\n  endif\n\nendfunction\n\nfunction ticklabel = ticklabel_to_cell (ticklabel)\n\n  if (ischar (ticklabel))\n    ticklabel = cellstr (ticklabel);\n  elseif (iscellstr (ticklabel))\n    ticklabel = ticklabel;\n  else\n    error (\"__gnuplot_draw_axes__: unsupported type of ticklabel\");\n  endif\n\nendfunction\n\nfunction colorspec = get_text_colorspec (color)\n  colorspec = sprintf ('textcolor rgb \"#%02x%02x%02x\"', round (255*color));\nendfunction\n\nfunction [f, s, fnt, it, bld] = get_fontname_and_size (t)\n\n  if (isempty (t.fontname) || strcmp (t.fontname, \"*\"))\n    if (ispc ())\n      ## FIXME: Should really test for \"windows\" terminal which is the\n      ## only terminal to have a problem with a null font specification.\n      ## See Bug #49135.\n      fnt = \"Arial\";\n    else\n      fnt = \"\";\n    endif\n  else\n    fnt = t.fontname;\n  endif\n\n  f = fnt;\n  it = false;\n  bld = false;\n  if (! isempty (t.fontweight) && strcmp (t.fontweight, \"bold\"))\n    if (! isempty (t.fontangle)\n        && (strcmp (t.fontangle, \"italic\")\n            || strcmp (t.fontangle, \"oblique\")))\n      if (__gnuplot_has_feature__ (\"fontspec_5\"))\n        f = [f \":Bold:Italic\"];\n      else\n        f = [f \"-bolditalic\"];\n      endif\n\n      it = true;\n      bld = true;\n    else\n      if (__gnuplot_has_feature__ (\"fontspec_5\"))\n        f = [f \":Bold\"];\n      else\n        f = [f \"-bold\"];\n      endif\n\n      bld = true;\n    endif\n  elseif (! isempty (t.fontangle)\n          && (strcmp (t.fontangle, \"italic\")\n              || strcmp (t.fontangle, \"oblique\")))\n    if (__gnuplot_has_feature__ (\"fontspec_5\"))\n      f = [f \":Italic\"];\n    else\n      f = [f \"-italic\"];\n    endif\n\n    it = true;\n  endif\n\n  if (isempty (t.fontsize))\n    s = 10;\n  else\n    s = t.fontsize;\n  endif\n\nendfunction\n\nfunction [str, f, s] = __maybe_munge_text__ (enhanced, obj, fld, ntrp, ...\n                                             gnuplot_term)\n  persistent warned_latex = false;\n\n  if (strcmp (fld, \"string\"))\n    [f, s, fnt, it, bld] = get_fontname_and_size (obj);\n  else\n    f = \"Helvetica\";\n    s = 10;\n    fnt = f;\n    it = false;\n    bld = false;\n  endif\n\n  ## The text object may be multiline, and may be of any class\n  str = getfield (obj, fld);\n  if (ischar (str) && rows (str) > 1)\n    str = cellstr (str);\n  elseif (isnumeric (str))\n    str = cellstr (num2str (str(:)));\n  endif\n  if (iscellstr (str))\n    for n = 1:numel (str)\n      if (isnumeric (str{n}))\n        str{n} = num2str (str{n});\n      endif\n    endfor\n    str = sprintf (\"%s\\n\", str{:})(1:end-1);\n  endif\n\n  if (enhanced)\n    str = regexprep (str, '(?<!\\\\)@', '\\\\@');\n  endif\n\n  if (enhanced)\n    if (strcmp (ntrp, \"tex\"))\n      if (iscellstr (str))\n        for n = 1:numel (str)\n          str{n} = __tex2enhanced__ (str{n}, fnt, it, bld, gnuplot_term);\n        endfor\n      else\n        str = __tex2enhanced__ (str, fnt, it, bld, gnuplot_term);\n      endif\n    elseif (strcmp (ntrp, \"latex\"))\n      if (! warned_latex)\n        do_warn = (warning (\"query\", \"Octave:text_interpreter\")).state;\n        if (strcmp (do_warn, \"on\"))\n          warning (\"Octave:text_interpreter\",\n                   \"latex markup not supported for text objects\");\n          warned_latex = true;\n        endif\n      endif\n    endif\n  endif\n\nendfunction\n\nfunction str = __tex2enhanced__ (str, fnt, it, bld, gnuplot_term)\n  persistent sym = __setup_sym_table__ ();\n  persistent flds = fieldnames (sym);\n\n  if (any (strcmp (gnuplot_term, {\"postscript\", \"epscairo\"})))\n    symtype = 1;\n  else\n    symtype = 2;\n  endif\n\n  [s, e, m] = regexp (str, \"\\\\\\\\([a-zA-Z]+|0)\", \"start\", \"end\", \"matches\");\n\n  for i = length (s) : -1 : 1\n    ## special case for \"\\0\"  and replace with empty set equivalent\n    if (strncmp (m{i}, '\\0', 2))\n      str = [str(1:s(i) - 1) sym.emptyset{symtype} str(s(i) + 2:end)];\n    else\n      f = m{i}(2:end);\n      if (isfield (sym, f))\n        g = sym.(f){symtype};\n        ## FIXME: The symbol font doesn't seem to support bold or italic\n        ##if (bld)\n        ##  if (it)\n        ##    g = strrep (g, '/Symbol', '/Symbol-bolditalic');\n        ##  else\n        ##    g = strrep (g, '/Symbol', '/Symbol-bold');\n        ##  endif\n        ##elseif (it)\n        ##  g = strrep (g, '/Symbol', '/Symbol-italic');\n        ##endif\n        str = [str(1:s(i) - 1) g str(e(i) + 1:end)];\n      elseif (strncmp (f, \"rm\", 2))\n        bld = false;\n        it = false;\n        str = [str(1:s(i) - 1) '{/' fnt ' ' str(s(i) + 3:end) '}'];\n      elseif (strncmp (f, \"it\", 2) || strncmp (f, \"sl\", 2))\n        it = true;\n        if (__gnuplot_has_feature__ (\"fontspec_5\"))\n          if (bld)\n            str = [str(1:s(i)-1) '{/' fnt ':Bold:Italic ' str(s(i)+3:end) '}'];\n          else\n            str = [str(1:s(i)-1) '{/' fnt ':Italic ' str(s(i)+3:end) '}'];\n          endif\n        else\n          if (bld)\n            str = [str(1:s(i)-1) '{/' fnt '-bolditalic ' str(s(i)+3:end) '}'];\n          else\n            str = [str(1:s(i)-1) '{/' fnt '-italic ' str(s(i)+3:end) '}'];\n          endif\n        endif\n      elseif (strncmp (f, \"bf\", 2))\n        bld = true;\n        if (__gnuplot_has_feature__ (\"fontspec_5\"))\n          if (it)\n            str = [str(1:s(i)-1) '{/' fnt ':Bold:Italic ' str(s(i)+3:end) '}'];\n          else\n            str = [str(1:s(i)-1) '{/' fnt ':Bold ' str(s(i)+3:end) '}'];\n          endif\n        else\n          if (it)\n            str = [str(1:s(i)-1) '{/' fnt '-bolditalic ' str(s(i)+3:end) '}'];\n          else\n            str = [str(1:s(i)-1) '{/' fnt '-bold ' str(s(i)+3:end) '}'];\n          endif\n        endif\n      elseif (strcmp (f, \"color\"))\n        ## FIXME: Ignore \\color but remove trailing {} block as well\n        d = strfind (str(e(i) + 1:end),'}');\n        if (isempty (d))\n          warning ('syntax error in \\color argument');\n        else\n          str = [str(1:s(i) - 1) str(e(i) + d + 1:end)];\n        endif\n      elseif (strcmp (f, \"fontname\"))\n        b1 = strfind (str(e(i) + 1:end),'{');\n        b2 = strfind (str(e(i) + 1:end),'}');\n        if (isempty (b1) || isempty (b2))\n          warning ('syntax error in \\fontname argument');\n        else\n          str = [str(1:s(i) - 1), '/', str(e(i)+b1(1) + 1:e(i)+b2(1)-1), ...\n                 '{}', str(e(i) + b2(1) + 1:end)];\n        endif\n      elseif (strcmp (f, \"fontsize\"))\n        b1 = strfind (str(e (i) + 1:end),'{');\n        b2 = strfind (str(e (i) + 1:end),'}');\n        if (isempty (b1) || isempty (b2))\n          warning ('syntax error in \\fontname argument');\n        else\n          str = [str(1:s(i) - 1), '/=', str(e(i)+b1(1) + 1:e(i)+b2(1)-1), ...\n                 '{}', str(e(i) + b2(1) + 1:end)];\n        endif\n      else\n        ## Last desperate attempt to treat the symbol.  Look for things\n        ## like \\pix, that should be translated to the symbol Pi and x\n        for j = 1 : length (flds)\n          if (strncmp (flds{j}, f, length (flds{j})))\n            g = sym.(flds{j}){symtype};\n            ## FIXME: The symbol font doesn't seem to support bold or italic\n            ##if (bld)\n            ##  if (it)\n            ##    g = strrep (g, '/Symbol', '/Symbol-bolditalic');\n            ##  else\n            ##    g = strrep (g, '/Symbol', '/Symbol-bold');\n            ##  endif\n            ##elseif (it)\n            ##  g = strrep (g, '/Symbol', '/Symbol-italic');\n            ##endif\n            str = [str(1:s(i) - 1) g str(s(i) + length (flds{j}) + 1:end)];\n            break;\n          endif\n        endfor\n      endif\n    endif\n  endfor\n\n  ## Prepend @ to things like _0^x or _{-100}^{100} for alignment.\n  ## But need to put the shorter of the two arguments first.\n  ## Careful of nested {} and unprinted characters when defining\n  ## shortest..  Don't have to worry about things like ^\\theta as they\n  ## are already converted.\n\n  ## FIXME: This is a mess.  Is it worth it just for a \"@\" character?\n\n  [s, m] = regexp (str,'[_\\^]','start','matches');\n  i = 1;\n  p = 0;\n  while (i < length (s))\n    if (i < length (s))\n      if (str(s(i) + p + 1) == \"{\")\n        s1 = strfind (str(s(i) + p + 2:end),'{');\n        si = 1;\n        l1 = strfind (str(s(i) + p + 1:end),'}');\n        li = 1;\n        while (li <= length (l1) && si <= length (s1))\n          if (l1(li) < s1(si))\n            if (li == si)\n              break;\n            endif\n            li += 1;\n          else\n            si += 1;\n          endif\n        endwhile\n        l1 = l1(min (length (l1), si));\n        if (s(i) + l1 + 1 == s(i+1))\n          if (str(s(i + 1) + p + 1) == \"{\")\n            s2 = strfind (str(s(i + 1) + p + 2:end),'{');\n            si = 1;\n            l2 = strfind (str(s(i + 1) + p + 1:end),'}');\n            li = 1;\n            while (li <= length (l2) && si <= length (s2))\n              if (l2(li) < s2(si))\n                if (li == si)\n                  break;\n                endif\n                li += 1;\n              else\n                si += 1;\n              endif\n            endwhile\n            l2 = l2(min (length (l2), si));\n            if (length_string (str(s(i)+p+2:s(i)+p+l1-1)) <=\n                length_string (str(s(i+1)+p+2:s(i+1)+p+l2-1)))\n              ## Shortest already first!\n              str = [str(1:s(i)+p-1) \"@\" str(s(i)+p:end)];\n            else\n              ## Have to swap sub/super-script to get shortest first.\n              str = [str(1:s(i)+p-1), \"@\", str(s(i+1)+p:s(i+1)+p+l2), ...\n                     str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+l2+1:end)];\n            endif\n          else\n            ## Have to swap sub/super-script to get shortest first.\n            str = [str(1:s(i)+p-1), \"@\", str(s(i+1)+p:s(i+1)+p+1), ...\n                   str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+2:end)];\n          endif\n          i += 2;\n          p += 1;\n        else\n          i += 1;\n        endif\n      else\n        if (s(i+1) == s(i) + 2)\n          ## Shortest already first!\n          str = [str(1:s(i)+p-1) \"@\" str(s(i)+p:end)];\n          p += 1;\n          i += 2;\n        else\n          i += 1;\n        endif\n      endif\n    else\n      i += 1;\n    endif\n  endwhile\n\nendfunction\n\nfunction l = length_string (s)\n\n  l = length (s) - length (strfind (s,'{')) - length (strfind (s,'}'));\n  m = regexp (s, '/([\\w-]+|[\\w-]+=\\d+)', 'matches');\n  if (! isempty (m))\n    l -= sum (cellfun (\"length\", m));\n  endif\n\nendfunction\n\nfunction sym = __setup_sym_table__ ()\n\n  ## Setup the translation table for TeX to gnuplot enhanced mode.\n  sym.forall = {'{/Symbol \\042}', '∀'};\n  sym.exists = {'{/Symbol \\044}', '∃'};\n  sym.ni = {'{/Symbol \\047}', '∋'};\n  sym.cong = {'{/Symbol \\100}', '≅'};\n  sym.Delta = {'{/Symbol D}', 'Δ'};\n  sym.Phi = {'{/Symbol F}', 'Φ'};\n  sym.Gamma = {'{/Symbol G}', 'Γ'};\n  sym.vartheta = {'{/Symbol J}', 'ϑ'};\n  sym.Lambda = {'{/Symbol L}', 'Λ'};\n  sym.Pi = {'{/Symbol P}', 'Π'};\n  sym.Theta = {'{/Symbol Q}', 'Θ'};\n  sym.Sigma = {'{/Symbol S}', 'Σ'};\n  sym.varsigma = {'{/Symbol V}', 'ς'};\n  sym.Omega = {'{/Symbol W}', 'Ω'};\n  sym.Xi = {'{/Symbol X}', 'Ξ'};\n  sym.Psi = {'{/Symbol Y}', 'Ψ'};\n  sym.perp = {'{/Symbol \\136}', '⊥'};\n  sym.alpha = {'{/Symbol a}', 'α'};\n  sym.beta = {'{/Symbol b}', 'β'};\n  sym.chi = {'{/Symbol c}', 'χ'};\n  sym.delta = {'{/Symbol d}', 'δ'};\n  sym.epsilon = {'{/Symbol e}', 'ε'};\n  sym.phi = {'{/Symbol f}', 'ϕ'};\n  sym.gamma = {'{/Symbol g}', 'γ'};\n  sym.eta = {'{/Symbol h}', 'η'};\n  sym.iota = {'{/Symbol i}', 'ι'};\n  sym.varphi = {'{/Symbol j}', 'φ'};              # Not in OpenGL\n  sym.kappa = {'{/Symbol k}', 'κ'};\n  sym.lambda = {'{/Symbol l}', 'λ'};\n  sym.mu = {'{/Symbol m}', 'μ'};\n  sym.nu = {'{/Symbol n}', 'ν'};\n  sym.o = {'{/Symbol o}', 'ο'};\n  sym.pi = {'{/Symbol p}', 'π'};\n  sym.theta = {'{/Symbol q}', 'θ'};\n  sym.rho = {'{/Symbol r}', 'ρ'};\n  sym.sigma = {'{/Symbol s}', 'σ'};\n  sym.tau = {'{/Symbol t}', 'τ'};\n  sym.upsilon = {'{/Symbol u}', 'υ'};\n  sym.varpi = {'{/Symbol v}', 'ϖ'};\n  sym.omega = {'{/Symbol w}', 'ω'};\n  sym.xi = {'{/Symbol x}', 'ξ'};\n  sym.psi = {'{/Symbol y}', 'ψ'};\n  sym.zeta = {'{/Symbol z}', 'ζ'};\n  sym.sim = {'{/Symbol \\176}', '∼'};\n  sym.Upsilon = {'{/Symbol \\241}', 'Υ'};\n  sym.prime = {'{/Symbol \\242}', '′'};\n  sym.leq = {'{/Symbol \\243}', '≤'};\n  sym.infty = {'{/Symbol \\245}', '∞'};\n  sym.clubsuit = {'{/Symbol \\247}', '♣'};\n  sym.diamondsuit = {'{/Symbol \\250}', '♢'};\n  sym.heartsuit = {'{/Symbol \\251}', '♡'};\n  sym.spadesuit = {'{/Symbol \\252}', '♠'};\n  sym.leftrightarrow = {'{/Symbol \\253}', '↔'};\n  sym.leftarrow = {'{/Symbol \\254}', '←'};\n  sym.uparrow = {'{/Symbol \\255}', '↑'};\n  sym.rightarrow = {'{/Symbol \\256}', '→'};\n  sym.downarrow = {'{/Symbol \\257}', '↓'};\n  sym.circ = {'{/Symbol \\260}', '∘'};\n  ## degree symbol, not circ as in FLTK\n  sym.deg = {'{/Symbol \\260}', '°'};\n  sym.ast = {'{/Symbol *}', '∗'};\n  sym.pm = {'{/Symbol \\261}', '±'};\n  sym.geq = {'{/Symbol \\263}', '≥'};\n  sym.times = {'{/Symbol \\264}', '×'};\n  sym.propto = {'{/Symbol \\265}', '∝'};\n  sym.partial = {'{/Symbol \\266}', '∂'};\n  sym.bullet = {'{/Symbol \\267}', '∙'};\n  sym.div = {'{/Symbol \\270}', '÷'};\n  sym.neq = {'{/Symbol \\271}', '≠'};\n  sym.equiv = {'{/Symbol \\272}', '≡'};\n  sym.approx = {'{/Symbol \\273}', '≈'};\n  sym.ldots = {'{/Symbol \\274}', '…'};\n  sym.mid = {'{/Symbol \\275}', '∣'};\n  sym.aleph = {'{/Symbol \\300}', 'ℵ'};\n  sym.Im = {'{/Symbol \\301}', 'ℑ'};\n  sym.Re = {'{/Symbol \\302}', 'ℜ'};\n  sym.wp = {'{/Symbol \\303}', '℘'};\n  sym.otimes = {'{/Symbol \\304}', '⊗'};\n  sym.oplus = {'{/Symbol \\305}', '⊕'};\n  ## empty set, not circled slash division operator as in FLTK.\n  sym.oslash = {'{/Symbol \\306}', '⊘'};\n  sym.emptyset = {'{/Symbol \\306}', '∅'};\n  sym.cap = {'{/Symbol \\307}', '∩'};\n  sym.cup = {'{/Symbol \\310}', '∪'};\n  sym.supset = {'{/Symbol \\311}', '⊃'};\n  sym.supseteq = {'{/Symbol \\312}', '⊇'};\n  sym.subset = {'{/Symbol \\314}', '⊂'};\n  sym.subseteq = {'{/Symbol \\315}', '⊑'};\n  sym.in = {'{/Symbol \\316}', '∈'};\n  sym.notin = {'{/Symbol \\317}', '∋'};            # Not in OpenGL\n  sym.angle = {'{/Symbol \\320}', '∠'};\n  sym.bigtriangledown = {'{/Symbol \\321}', '▽'};  # Not in OpenGL\n  sym.langle = {'{/Symbol \\341}', '〈'};\n  sym.rangle = {'{/Symbol \\361}', '〉'};\n  sym.nabla = {'{/Symbol \\321}', '∇'};\n  sym.prod = {'{/Symbol \\325}', '∏'};             # Not in OpenGL\n  sym.surd = {'{/Symbol \\326}', '√'};\n  sym.cdot = {'{/Symbol \\327}', '⋅'};\n  sym.neg = {'{/Symbol \\330}', '¬'};\n  sym.wedge = {'{/Symbol \\331}', '∧'};\n  sym.vee = {'{/Symbol \\332}', '∨'};\n  sym.Leftrightarrow = {'{/Symbol \\333}', '⇔'};   # Not in OpenGL\n  sym.Leftarrow = {'{/Symbol \\334}', '⇐'};\n  sym.Uparrow = {'{/Symbol \\335}', '⇑'};          # Not in OpenGL\n  sym.Rightarrow = {'{/Symbol \\336}', '⇒'};\n  sym.Downarrow = {'{/Symbol \\337}', '⇓'};        # Not in OpenGL\n  sym.diamond = {'{/Symbol \\340}', '⋄'};          # Not in OpenGL\n  sym.copyright = {'{/Symbol \\343}', '©'};\n  sym.lfloor = {'{/Symbol \\353}', '⌊'};\n  sym.lceil = {'{/Symbol \\351}', '⌈'};\n  sym.rfloor = {'{/Symbol \\373}', '⌋'};\n  sym.rceil = {'{/Symbol \\371}', '⌉'};\n  sym.int = {'{/Symbol \\362}', '∫'};\n\nendfunction\n\nfunction retval = __do_enhanced_option__ (enhanced, obj)\n\n  retval = \"\";\n  if (enhanced)\n    if (strcmp (obj.interpreter, \"none\"))\n      retval = \"noenhanced\";\n    else\n      retval = \"enhanced\";\n    endif\n  endif\n\nendfunction\n\nfunction do_text (stream, gpterm, enhanced, obj, hax, screenpos)\n\n  [label, f, s] = __maybe_munge_text__ (enhanced, obj, \"string\", ...\n                                        obj.interpreter, gpterm);\n  fontspec = create_fontspec (f, s, gpterm);\n  lpos = obj.position;\n  halign = obj.horizontalalignment;\n  valign = obj.verticalalignment;\n  angle = obj.rotation;\n  units = obj.units;\n  color = obj.color;\n  if (nargin > 5)\n    units = \"screen\";\n    lpos = screenpos;\n  elseif (strcmp (units, \"normalized\"))\n    units = \"graph\";\n  elseif (strcmp (get (hax, \"yaxislocation\"), \"right\")\n          && strcmp (units, \"data\"))\n    units = \"second\";\n  else\n    units = \"\";\n  endif\n\n  if (isnumeric (color))\n    colorspec = get_text_colorspec (color);\n  endif\n\n  if (ischar (obj.string))\n    num_lines = rows (obj.string);\n    num_lines += numel (strfind (obj.string, \"\\n\"));\n  else\n    num_lines = numel (obj.string);\n  endif\n  switch (valign)\n    ## Text offset in characters.  Relies on gnuplot for font metrics.\n    case \"top\"\n      dy = -0.5;\n    case \"cap\"\n      dy = -0.5;\n    case \"middle\"\n      dy = 0.5 * (num_lines - 1);\n    case \"baseline\"\n      dy = 0.5 + (num_lines - 1);\n    case \"bottom\"\n      dy = 0.5 + (num_lines - 1);\n  endswitch\n  ## Gnuplot's Character units are different for x/y and vary with\n  ## fontsize.  The aspect ratio of 1:1.7 was determined by experiment\n  ## to work for eps/ps/etc.  For the MacOS aqua terminal a value of 2.5\n  ## is needed.  However, the difference is barely noticeable.\n  dx_and_dy = [(-dy * sind (angle)), (dy * cosd (angle))] .* [1.7 1];\n\n  ## FIXME: Multiline text produced the gnuplot\n  ##        \"warning: ft_render: skipping glyph\"\n  if (__calc_dimensions__ (hax) == 3)\n    zstr = sprintf (\",%.15e\", lpos(3));\n  else\n    zstr = \"\";\n  endif\n  fprintf (stream,\n           ['set label \"%s\" at %s %.15e,%.15e%s %s rotate by %f offset character %f,%f %s %s front %s;' \"\\n\"],\n           label, units, lpos(1), lpos(2), zstr, halign, angle, dx_and_dy,\n           fontspec, __do_enhanced_option__ (enhanced, obj), colorspec);\n\nendfunction\n\nfunction cdata = mapcdata (cdata, mode, clim, cmap_sz)\n\n  if (ndims (cdata) == 3)\n    ## True Color, clamp data to 8-bit\n    clim = double (clim);\n    cdata = double (cdata);\n    clim_rng = clim(2) - clim(1);\n    if (clim_rng != 0)\n      cdata = 255 * (cdata - clim(1)) / clim_rng;\n      cdata(cdata < 0) = 0;  cdata(cdata > 255) = 255;\n    else\n      cdata(:) = fix (255 / 2);\n    endif\n  else\n    if (strcmp (mode, \"scaled\"))\n      clim = double (clim);\n      cdata = double (cdata);\n      clim_rng = clim(2) - clim(1);\n      if (clim_rng != 0)\n        cdata = 1 + fix (cmap_sz * (cdata - clim(1)) / clim_rng);\n      else\n        cdata(:) = 1 + fix (cmap_sz / 2);\n      endif\n    else\n      if (islogical (cdata) || isinteger (cdata))\n        cdata += 1;\n      else\n        cdata = fix (cdata);\n      endif\n    endif\n    cdata = max (1, min (cdata, cmap_sz));\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__gnuplot_draw_figure__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} __gnuplot_draw_figure__ (@var{h}, @var{plot_stream}, @var{enhanced})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction __gnuplot_draw_figure__ (h, plot_stream, enhanced)\n\n  htype = get (h, \"type\");\n  if (strcmp (htype, \"figure\"))\n    ## Get complete list of children.\n    kids = allchild (h);\n    nkids = length (kids);\n\n    if (nkids > 0)\n      fputs (plot_stream, \"\\nreset;\\n\");\n      fputs (plot_stream, \"set autoscale keepfix;\\n\");\n      fputs (plot_stream, \"set origin 0, 0\\n\");\n      fputs (plot_stream, \"set size 1, 1\\n\");\n      bg = get (h, \"color\");\n      if (isnumeric (bg))\n        fprintf (plot_stream, ['if (GPVAL_TERM eq \"qt\") set obj 1 rectangle from screen 0,0 to screen 1,1 behind fc rgb \"#%02x%02x%02x\" fs solid noborder;' \"\\n\"], round (255 * bg));\n        bg_is_set = true;\n      else\n        bg_is_set = false;\n      endif\n      fg_was_set = false;\n\n      for i = nkids:-1:1\n        type = get (kids(i), \"type\");\n        switch (type)\n          case \"axes\"\n            if (strcmp (get (kids(i), \"tag\"), \"legend\"))\n              ## This is so ugly.  If there was a way of getting\n              ## gnuplot to give us the text extents of strings\n              ## then we could get rid of this mess.\n              lh = getappdata (kids(i), \"__axes_handle__\");\n              if (isscalar (lh))\n                ## We have a legend with a single parent.  It'll be handled\n                ## below as a gnuplot key to the axis it corresponds to.\n                continue;\n              else\n                ca = lh(1);\n                ## Rely upon listener to convert axes position\n                ## to \"normalized\" units.\n                legend_axes_units = get (kids(i), \"units\");\n                legend_axes_position = get (kids(i), \"position\");\n                legend_axes_outerposition = get (kids(i), \"outerposition\");\n                legend_axes_box = get (kids(i), \"box\");\n                legend_axes_ylim = get (kids(i), \"ylim\");\n                orig_axes_units = get (ca, \"units\");\n                hlgnd = get (kids(i));\n\n                unwind_protect\n                  set (ca, \"units\", \"normalized\");\n                  set (kids(i), \"units\", \"normalized\", \"box\", \"off\",\n                       \"ylim\", [-2, -1], \"position\", get (ca(1), \"position\"),\n                       \"outerposition\", get (ca(1), \"outerposition\"));\n\n                  ## Create a new set of lines with the appropriate\n                  ## displaynames, etc\n                  toberm = [];\n                  hobj = get (kids(i), \"children\");\n                  for j = numel (hobj) : -1 : 1\n                    if (! strcmp (get (hobj(j), \"type\"), \"text\"))\n                      continue;\n                    endif\n                    displayname = get (hobj(j), \"string\");\n                    ll = [];\n                    lm = [];\n                    for k = numel (hobj) : -1 : 1\n                      if (! strcmp (get (hobj(k), \"type\"), \"line\"))\n                        continue;\n                      endif\n                      if (getappdata (hobj(j), \"handle\")\n                          != getappdata (hobj(k), \"handle\"))\n                        continue;\n                      endif\n                      if (! strcmp (get (hobj(k), \"linestyle\"), \"none\"))\n                        ll = hobj(k);\n                      endif\n                      if (! strcmp (get (hobj(k), \"marker\"), \"none\"))\n                        lm = hobj(k);\n                      endif\n                    endfor\n\n                    if (! isempty (ll))\n                      if (! isempty (lm))\n                        toberm = [toberm, line(\"xdata\",[0,0],\"ydata\",[0,0], \"color\", get(lm,\"color\"), \"linestyle\", get(ll,\"linestyle\"), \"marker\", get(lm,\"marker\"), \"markeredgecolor\", get(lm,\"markeredgecolor\"), \"markerfacecolor\", get(lm,\"markerfacecolor\"), \"markersize\", get (lm, \"markersize\"), \"displayname\", displayname, \"parent\", kids(i))];\n                      else\n                        toberm = [toberm, line(\"xdata\",[0,0],\"ydata\",[0,0], \"color\", get(ll,\"color\"), \"linestyle\", get(ll,\"linestyle\"), \"marker\", \"none\", \"displayname\", displayname, \"parent\", kids(i))];\n                      endif\n                    elseif (! isempty (lm))\n                      toberm = [toberm, line(\"xdata\",[0,0],\"ydata\",[0,0], \"color\", get(lm,\"color\"), \"linestyle\", \"none\", \"marker\", get(lm,\"marker\"), \"markeredgecolor\", get(lm,\"markeredgecolor\"), \"markerfacecolor\", get(lm,\"markerfacecolor\"), \"markersize\", get (lm, \"markersize\"), \"displayname\", displayname, \"parent\", kids(i))];\n                    endif\n                  endfor\n                  if (bg_is_set)\n                    fprintf (plot_stream, ['set border linecolor rgb \"#%02x%02x%02x\"' \"\\n\"], round (255 * (1 - bg)));\n                  endif\n                  __gnuplot_draw_axes__ (kids(i), plot_stream, enhanced,\n                                    bg_is_set, false, hlgnd);\n                unwind_protect_cleanup\n                  ## Return axes \"units\" and \"position\" back to\n                  ## their original values.\n                  set (ca, \"units\", orig_axes_units);\n                  set (kids(i), \"units\", legend_axes_units,\n                       \"box\", legend_axes_box,\n                       \"ylim\", legend_axes_ylim,\n                       \"position\", legend_axes_position,\n                       \"outerposition\", legend_axes_outerposition);\n                  delete (toberm);\n                  bg_is_set = false;\n                end_unwind_protect\n              endif\n            else\n              ## Rely upon listener to convert axes position\n              ## to \"normalized\" units.\n              orig_axes_units = get (kids(i), \"units\");\n              orig_axes_position = get (kids(i), \"position\");\n              unwind_protect\n                set (kids(i), \"units\", \"normalized\");\n                fg = get (kids(i), \"color\");\n                if (isnumeric (fg) && strcmp (get (kids(i), \"visible\"), \"on\"))\n                  fprintf (plot_stream, ['set obj 2 rectangle from graph 0,0 to graph 1,1 behind fc rgb \"#%02x%02x%02x\" fs solid noborder' \"\\n\"], round (255 * fg));\n                  fg_is_set = true;\n                  fg_was_set = true;\n                elseif (fg_was_set)\n                  fprintf (plot_stream, \"unset obj 2\\n\");\n                  fg_is_set = false;\n                  fg_was_set = false;\n                else\n                  fg_is_set = false;\n                endif\n                if (bg_is_set)\n                  fprintf (plot_stream, ['set border linecolor rgb \"#%02x%02x%02x\"' \"\\n\"], round (255 * (1 - bg)));\n                endif\n                ## Find if this axes has an associated legend axes and pass it\n                ## to __gnuplot_draw_axes__\n                try\n                  hlegend = get (kids(i), \"__legend_handle__\");\n                  hlegend = get (hlegend);\n                catch\n                  hlegend = [];\n                end_try_catch\n                __gnuplot_draw_axes__ (kids(i), plot_stream, enhanced,\n                                       bg_is_set, fg_is_set, hlegend);\n              unwind_protect_cleanup\n                ## Return axes \"units\" and \"position\" back to\n                ## their original values.\n                set (kids(i), \"units\", orig_axes_units,\n                              \"position\", orig_axes_position);\n                bg_is_set = false;\n                fg_is_set = false;\n              end_unwind_protect\n            endif\n          case {\"uimenu\", \"uicontextmenu\", \"uitoolbar\"}\n            ## ignore uimenu objects\n            kids(i) = [];\n          otherwise\n            error (\"__gnuplot_draw_figure__: unknown object class, %s\", type);\n        endswitch\n      endfor\n      if (isempty (kids))\n        fputs (plot_stream, \"\\nreset; clear;\\n\");\n        fflush (plot_stream);\n      else\n        fputs (plot_stream, \"\\nunset multiplot;\\n\");\n      endif\n    else\n      fputs (plot_stream, \"\\nreset; clear;\\n\");\n      fflush (plot_stream);\n    endif\n  else\n    error (\"__gnuplot_draw_figure__: expecting figure object, found '%s'\",\n           htype);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__gnuplot_get_var__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{value} =} __gnuplot_get_var__ (@var{h}, @var{gp_var_name}, @var{fmt})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction gp_var_value = __gnuplot_get_var__ (h, gp_var_name, fmt = \"\")\n\n  if (numel (h) == 1 && isfigure (h))\n    if (isempty (get (h, \"__plot_stream__\")))\n      ostream = __gnuplot_open_stream__ (2, h);\n    else\n      ostream = get (h, \"__plot_stream__\");\n    endif\n  else\n    ostream = h;\n  endif\n  if (numel (ostream) < 1)\n    error (\"__gnuplot_get_var__: stream to gnuplot not open\");\n  elseif (ispc ())\n    if (numel (ostream) == 1)\n      error (\"__gnuplot_get_var__: Need mkfifo that is not implemented under Windows\");\n    endif\n    use_mkfifo = false;\n    istream = ostream(2);\n    ostream = ostream(1);\n  else\n    use_mkfifo = true;\n    ostream = ostream(1);\n  endif\n\n  if (use_mkfifo)\n    gpin_name = tempname ();\n\n    [err, msg] = mkfifo (gpin_name, 600);\n\n    if (err)\n      error (\"__gnuplot_get_var__: Can not make FIFO (%s)\", msg);\n    endif\n  endif\n\n  gp_var_name = strtrim (gp_var_name);\n  n = min (strfind (gp_var_name, \" \"), strfind (gp_var_name, \",\")) - 1;\n  if (isempty (n))\n    n = numel (gp_var_name);\n  endif\n\n  unwind_protect\n\n    ## Notes: Variables may be undefined if user closes gnuplot by \"q\"\n    ## or Alt-F4.  Further, this abrupt close also requires the leading\n    ## \"\\n\" on the next line.\n    if (use_mkfifo)\n      fprintf (ostream, [\"\\n\" 'set print \"%s\";' \"\\n\"], gpin_name);\n      fflush (ostream);\n      [gpin, err] = fopen (gpin_name, \"r\");\n      if (err)\n        ## Try a second time, and then give an error.\n        [gpin, err] = fopen (gpin_name, \"r\");\n      endif\n      if (err)\n        error (\"__gnuplot_get_var__: can not open FIFO\");\n      endif\n      gp_cmd = sprintf ([\"\\n\" 'if (exists(\"%s\")) print %s; else print NaN' \"\\n\"],\n                        gp_var_name(1:n), gp_var_name);\n      fputs (ostream, gp_cmd);\n\n      ## Close output file, to force it to be flushed\n      fputs (ostream, \"set print;\\n\");\n      fflush (ostream);\n\n      ## Now read from fifo.\n      reading = true;\n      str = {};\n      while (reading)\n        str{end+1} = fgets (gpin);\n        if (isnumeric (str{end}) && (str{end} == -1))\n          reading = false;\n          str = str(1:(end-1));\n        endif\n      endwhile\n      str = strcat (str{:});\n      fclose (gpin);\n    else\n      ## Direct gnuplot to print to <STDOUT>\n      fprintf (ostream, ['set print \"-\";' \"\\n\"]);\n      fflush (ostream);\n      gp_cmd = sprintf ([\"\\n\" 'if (exists(\"%s\")) print \"OCTAVE: \", %s, ' ...\n                        '\" :END_OCTAVE\"; else print NaN' \"\\n\"],\n                        gp_var_name(1:n), gp_var_name);\n      fputs (ostream, gp_cmd);\n      fflush (ostream);\n      ## Direct gnuplot to print to <STDERR>\n      fputs (ostream, \"set print;\\n\");\n      fflush (ostream);\n\n      str = \"\";\n      t_start = tic ();\n      while (toc (t_start) < 10)\n        str = [str, fread(istream, \"*char\")'];\n        if (! isempty (str))\n          re_str = regexp (str, \"OCTAVE: (.*) :END_OCTAVE\", \"tokens\");\n          if (! isempty (re_str))\n            str = re_str{end}{1};\n            break;\n          endif\n        endif\n        fclear (istream);\n      endwhile\n    endif\n\n    ## Strip out EOLs and the continuation character \"|\"\n    str(str==\"\\n\" | str==\"\\r\") = \"\";\n    n_continue = strfind (str, \" \\\\ \");\n    if (! isempty (n_continue))\n      str(n_continue+1) = \"\";\n    endif\n\n    if (isempty (fmt))\n      gp_var_value = strtrim (str);\n    else\n      gp_var_value = sscanf (str, fmt);\n    endif\n\n  unwind_protect_cleanup\n    if (use_mkfifo)\n      unlink (gpin_name);\n    endif\n  end_unwind_protect\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__gnuplot_ginput__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{x}, @var{y}, @var{buttons}] =} __gnuplot_ginput__ (@var{f}, @var{n})\n## Undocumented internal function.\n## @end deftypefn\n\n## This is ginput.m implementation for gnuplot and X11.\n## It requires gnuplot 4.1 and later.\n\n## This file initially bore the copyright statement\n## Petr Mikulik\n## History: June 2006; August 2005; June 2004; April 2004\n## License: public domain\n\nfunction [x, y, button] = __gnuplot_ginput__ (f, n)\n\n  if (compare_versions (__gnuplot_version__ (), \"4.0\", \"<=\"))\n    error (\"ginput: version %s of gnuplot not supported\", gnuplot_version ());\n  endif\n\n  ostream = get (f, \"__plot_stream__\");\n  if (numel (ostream) < 1)\n    error (\"ginput: stream to gnuplot not open\");\n  elseif (ispc ())\n    if (numel (ostream) == 1)\n      error (\"ginput: Need mkfifo that is not implemented under Windows\");\n    endif\n    use_mkfifo = false;\n    istream = ostream(2);\n    ostream = ostream(1);\n  else\n    use_mkfifo = true;\n    ostream = ostream(1);\n  endif\n\n  if (nargin == 1)\n    x = zeros (100, 1);\n    y = zeros (100, 1);\n    button = zeros (100, 1);\n  else\n    x = zeros (n, 1);\n    y = zeros (n, 1);\n    button = zeros (n, 1);\n  endif\n\n  if (use_mkfifo)\n    gpin_name = tempname ();\n\n    [err, msg] = mkfifo (gpin_name, 600);\n\n    if (err)\n      error (\"ginput: Can not open fifo (%s)\", msg);\n    endif\n  endif\n\n  unwind_protect\n\n    k = 0;\n    while (true)\n      k += 1;\n\n      ## Notes: MOUSE_* can be undefined if user closes gnuplot by \"q\"\n      ## or Alt-F4.  Further, this abrupt close also requires the leading\n      ## \"\\n\" on the next line.\n      if (use_mkfifo)\n        fprintf (ostream, ['set print \"%s\";' \"\\n\"], gpin_name);\n        fflush (ostream);\n        [gpin, err] = fopen (gpin_name, \"r\");\n        if (err)\n          error (\"ginput: Can not open FIFO (%s)\", msg);\n        endif\n        fputs (ostream, \"pause mouse any;\\n\\n\");\n        fputs (ostream, [\"\\n\" 'if (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"' \"\\n\"]);\n\n        ## Close output file, to force it to be flushed\n        fputs (ostream, \"set print;\\n\");\n        fflush (ostream);\n\n        ## Now read from fifo.\n        [x(k), y(k), button(k), count] = fscanf (gpin, \"%f %f %d\", \"C\");\n        fclose (gpin);\n      else\n        fputs (ostream, ['set print \"-\";' \"\\n\"]);\n        fflush (ostream);\n        fputs (ostream, \"pause mouse any;\\n\\n\");\n        fputs (ostream, [\"\\n\" 'if (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) key = (MOUSE_KEY==1063 ? 1 : MOUSE_KEY); print \"OCTAVE: \", MOUSE_X, MOUSE_Y, key; else print \"0 0 -1\"' \"\\n\"]);\n\n        ## Close output file, to force it to be flushed\n        fputs (ostream, \"set print;\\n\");\n        fflush (ostream);\n\n        str = {};\n        while (isempty (str))\n          str = fread (istream, \"*char\")';\n          if (isempty (str))\n            pause (0.05);\n          else\n            str = regexp (str, 'OCTAVE:\\s+[-+.\\d]+\\s+[-+.\\d]+\\s+\\d*', 'match');\n          endif\n          fclear (istream);\n        endwhile\n        [x(k), y(k), button(k), count] = ...\n          sscanf (str{end}(8:end), \"%f %f %d\", \"C\");\n      endif\n\n      if ([x(k), y(k), button(k)] == [0, 0, -1])\n        ## Mousing not active (no plot yet).\n        break;\n      endif\n\n      if (button(k) == 0x0D || button(k) == 0x0A)\n        ## Stop when hitting a RETURN or ENTER key.\n        x(k:end) = [];\n        y(k:end) = [];\n        button(k:end) = [];\n        break;\n      endif\n      if (nargin > 1 && k == n)\n        ## Input argument n was given, stop when k == n.\n        break;\n      endif\n\n    endwhile\n\n  unwind_protect_cleanup\n    if (use_mkfifo)\n      unlink (gpin_name);\n    endif\n  end_unwind_protect\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__gnuplot_has_feature__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{has_feature} =} __gnuplot_has_feature__ (@var{feature})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction res = __gnuplot_has_feature__ (feature)\n  persistent features = {\"minimum_version\",\n                         \"needs_color_with_postscript\",\n                         \"dashtype\",\n                         \"alphablend_linecolor\",\n                         \"qt_terminal\",\n                         \"wxt_figure_position\",\n                         \"qt_figure_position\",\n                         \"fontspec_5\"};\n\n  persistent has_features;\n\n  if (isempty (has_features))\n    gnuplot_version = __gnuplot_version__ ();\n    versions  = {\"4.4\", \"4.6\", \"5.0\", \"4.6\", \"4.6\", \"5.0\", \"5.0\", \"5.0\"};\n    operators = {\">=\" , \">=\" , \">=\" , \">=\" , \">=\" , \">=\" , \">=\" , \">=\" };\n    have_features = false (size (features));\n    for n = 1 : numel (have_features)\n      has_features(n) = compare_versions (gnuplot_version, versions{n}, operators{n});\n    endfor\n  endif\n\n  n = find (strcmpi (feature, features));\n  if (isempty (n))\n    res = NaN;\n  else\n    res = has_features(n);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__gnuplot_has_terminal__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{has_terminal} =} __gnuplot_has_terminal__ (@var{term})\n## @deftypefnx {} {@var{has_terminal} =} __gnuplot_has_terminal__ (@var{term}, @var{plot_stream})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction gnuplot_supports_term = __gnuplot_has_terminal__ (term, plot_stream)\n\n  term = strtrim (term);\n  term = lower (strtok (term, \" \"));\n\n  if (nargin < 2)\n    plot_stream = __gnuplot_open_stream__ (2);\n  endif\n  available_terminals = __gnuplot_get_var__ (plot_stream, \"GPVAL_TERMINALS\");\n  available_terminals = regexp (available_terminals, '\\w+', \"match\");\n  if (nargin < 2 && ! isempty (plot_stream))\n    pclose (plot_stream(1));\n    if (numel (plot_stream) > 1)\n      pclose (plot_stream(2));\n    endif\n    if (numel (plot_stream) > 2)\n      waitpid (plot_stream(3));\n    endif\n  endif\n\n  gnuplot_supports_term = any (strcmp (term, available_terminals));\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__gnuplot_open_stream__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{stream} =} __gnuplot_open_stream__ (@var{npipes}, @var{h})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction plot_stream = __gnuplot_open_stream__ (npipes, h)\n\n  [prog, args] = gnuplot_binary ();\n\n  if (npipes > 1)\n    [plot_stream(1), plot_stream(2), pid] = popen2 (prog, args{:});\n    if (pid < 0)\n      error (\"__gnuplot_open_stream__: failed to open connection to gnuplot\");\n    else\n      plot_stream(3) = pid;\n    endif\n  else\n    plot_stream = popen (sprintf (\"%s \", prog, args{:}), \"w\");\n    if (plot_stream < 0)\n      error (\"__gnuplot_open_stream__: failed to open connection to gnuplot\");\n    endif\n  endif\n\n  if (nargin > 1)\n    set (h, \"__plot_stream__\", plot_stream);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__gnuplot_print__.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{opts} =} __gnuplot_print__ (@var{@dots{}})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction opts = __gnuplot_print__ (opts)\n\n  dos_shell = (ispc () && ! isunix ());\n\n  if (isempty (opts.fontsize))\n    ## If no fontsize, determine the nominal axes fontsize.\n    defaultfontsize = get (0, \"defaultaxesfontsize\");\n    axesfontsize = get (findobj (opts.figure, \"type\", \"axes\"), \"fontsize\");\n    if (iscell (axesfontsize))\n      axesfontsize = round (median (cell2mat (axesfontsize)));\n    endif\n    if (isempty (axesfontsize))\n      opts.fontsize = defaultfontsize;\n    else\n      opts.fontsize = axesfontsize;\n    endif\n  endif\n  ## The axes-label and tick-label spacing is determined by\n  ## the font spec given in \"set terminal ...\"\n  gp_opts = font_spec (opts);\n  if (! any (strcmpi (opts.devopt, {\"fig\", \"dxf\", \"hpgl\", \"mf\", \"pstricks\", ...\n                                    \"texdraw\", \"latex\", \"eepic\"})))\n    bg = get (opts.figure, \"color\");\n    if (isnumeric (bg))\n      gp_opts = sprintf ('%s background rgb \"#%02x%02x%02x\"',\n                         gp_opts, round (255 * bg));\n    else\n      gp_opts = sprintf (\"%s nobackground\", gp_opts);\n    endif\n  endif\n\n  pipeline = \"\";\n\n  switch (lower (opts.devopt))\n    case {\"eps\", \"eps2\", \"epsc\", \"epsc2\"}\n      if (any (strcmp (opts.devopt, {\"eps\", \"epsc\"})))\n        gp_opts = [gp_opts \" level1\"];\n      endif\n      if (opts.tight || ! isempty (opts.preview))\n        tmp_file = [tempname() \".eps\"];\n        eps_drawnow (opts, tmp_file, gp_opts);\n        if (dos_shell)\n          cleanup = [\" & del \" strrep(tmp_file, '/', '\\')];\n        else\n          cleanup = [\" ; rm \" tmp_file];\n        endif\n        pipeline = {sprintf(\"%s %s\",\n                            opts.epstool_cmd (opts, tmp_file, opts.name),\n                            cleanup)};\n      else\n        eps_drawnow (opts, opts.name, gp_opts);\n      endif\n    case {\"epslatex\", \"pslatex\", \"pstex\", \"epslatexstandalone\"}\n      dot = find (opts.name == \".\", 1, \"last\");\n      n = find (opts.devopt == \"l\", 1);\n      suffix = opts.devopt(1:n-1);\n      [ndir, name, ext] = fileparts (opts.name);\n      if (isempty (ext))\n        ext = \"tex\";\n      else\n        ext = ext(2:end);  # remove leading '.'\n      endif\n      if (any (strcmpi (ext, {suffix, \"tex\"})))\n        name = fullfile (ndir, name);\n        if (any (strcmpi (ext, {\"eps\", \"ps\", \"pdf\"})))\n          suffix = ext;  # If user provides eps/ps/pdf suffix, use it.\n        endif\n      else\n        error (\"Octave:print:invalid-suffix\",\n               \"invalid suffix '%s' for device '%s'.\",\n               ext, lower (opts.devopt));\n      endif\n      suffix = \"tex\";\n      if (strfind (opts.devopt, \"standalone\"))\n        gp_opts = sprintf (\"standalone %s\", gp_opts);\n        term = strrep (opts.devopt, \"standalone\", \"\");\n      else\n        term = sprintf (\"%s \", opts.devopt);\n      endif\n      local_drawnow ([term \" \" gp_opts],\n                     [name \".\" suffix], opts);\n    case {\"tikz\", \"tikzstandalone\"}\n      if (strfind (opts.devopt, \"standalone\"))\n        gp_opts = sprintf (\"standalone %s\", gp_opts);\n      endif\n      if (__gnuplot_has_terminal__ (\"tikz\"))\n        local_drawnow ([\"tikz \" gp_opts], opts.name, opts);\n      else\n        error (sprintf (\"print:no%soutput\", opts.devopt),\n               \"print: '%s' output is not available for gnuplot-%s\",\n               upper (opts.devopt), __gnuplot_version__ ());\n      endif\n    case \"svg\"\n      local_drawnow ([\"svg dynamic \" gp_opts], opts.name, opts);\n    case {\"eepic\"}\n      local_drawnow ([opts.devopt \" color rotate \" gp_opts], opts.name, opts);\n    case {\"aifm\", \"corel\", \"emf\", \"fig\"}\n      local_drawnow ([opts.devopt \" \" gp_opts], opts.name, opts);\n    case {\"cairolatex\", \"epscairo\", \"epscairolatex\", ...\n          \"epscairolatexstandalone\", \"pdfcairo\", \"pdfcairolatex\", ...\n          \"pdfcairolatexstandalone\", \"pngcairo\", ...\n          \"pdflatexstandalone\", \"pdflatex\"}\n      term = opts.devopt;\n      if (strfind (term, \"standalone\"))\n        gp_opts = sprintf (\"standalone %s\", gp_opts);\n        term = strrep (term, \"standalone\", \"\");\n      endif\n      if (strfind (term, \"epscairolatex\"))\n        gp_opts = sprintf (\"eps %s\", gp_opts);\n        term = strrep (term, \"epscairolatex\", \"cairolatex\");\n      elseif (strfind (term, \"pdfcairolatex\") || strfind (term, \"pdflatex\"))\n        gp_opts = sprintf (\"pdf %s\", gp_opts);\n        term = strrep (term, \"pdfcairolatex\", \"cairolatex\");\n        term = strrep (term, \"pdflatex\", \"cairolatex\");\n      endif\n      if (__gnuplot_has_terminal__ (term))\n        local_drawnow ([term \" \" gp_opts], opts.name, opts);\n      else\n        error (sprintf (\"print:no%soutput\", opts.devopt),\n               \"print: '%s' output is not available for gnuplot-%s\",\n               upper (opts.devopt), __gnuplot_version__ ());\n      endif\n    case {\"canvas\", \"cgm\", \"dxf\", \"hpgl\", \"latex\", \"mf\", \"gif\", ...\n          \"pstricks\", \"texdraw\"}\n      if (__gnuplot_has_terminal__ (opts.devopt))\n        local_drawnow ([opts.devopt \" \" gp_opts], opts.name, opts);\n      else\n        error (sprintf (\"print:no%soutput\", opts.devopt),\n               \"print: '%s' output is not available for gnuplot-%s\",\n               upper (opts.devopt), __gnuplot_version__ ());\n      endif\n    case \"dumb\"\n      local_drawnow (\"dumb size 72,24\", opts.name, opts);\n    case opts.ghostscript.device\n      gp_opts = font_spec (opts, \"devopt\", \"eps\");\n      opts.ghostscript.output = opts.name;\n      opts.ghostscript.source = [tempname() \".eps\"];\n      eps_drawnow (opts, opts.ghostscript.source, gp_opts);\n      [cmd_gs, cmd_cleanup] = __ghostscript__ (opts.ghostscript);\n      if (opts.send_to_printer || isempty (opts.name))\n        cmd_lpr = opts.lpr_cmd (opts);\n        cmd = [cmd_gs \" | \" cmd_lpr];\n      else\n        cmd = cmd_gs;\n      endif\n      if (dos_shell)\n        cmd = sprintf (\"%s & del %s\", cmd,\n                       strrep (opts.ghostscript.source, '/', '\\'));\n      else\n        cmd = sprintf (\"%s ; rm %s\", cmd, opts.ghostscript.source);\n      endif\n      if (! isempty (cmd_cleanup))\n        if (dos_shell)\n          pipeline = {[cmd \" & \" cmd_cleanup]};\n        else\n          pipeline = {[cmd \" ; \" cmd_cleanup]};\n        endif\n      else\n        pipeline = {cmd};\n      endif\n    otherwise\n      error (sprintf (\"print:no%soutput\", opts.devopt),\n             \"print: %s output is not available for the Gnuplot graphics toolkit\",\n             upper (opts.devopt));\n  endswitch\n\n\n  opts.pipeline = pipeline;\n\n  for n = 1:numel (pipeline)\n    if (opts.debug)\n      fprintf (\"gnuplot-pipeline: '%s'\\n\", pipeline{n});\n    endif\n    [status, output] = system (pipeline{n});\n    if (status)\n      fprintf (\"%s\\n%s\\n%s\\n\",\n               \"---------- output begin ----------\",\n               output,\n               \"----------- output end -----------\");\n      error (\"Octave:gnuplot:failedpipe\", \"print: failed to print\");\n    endif\n  endfor\n\nendfunction\n\n\nfunction eps_drawnow (opts, epsfile, gp_opts)\n\n  [h, fontsize] = get_figure_text_objs (opts);\n  unwind_protect\n    fontsize_2x = cellfun ('times', {2}, fontsize, \"uniformoutput\", false);\n    set (h, {\"fontsize\"}, fontsize_2x);\n    local_drawnow ([\"postscript eps \" gp_opts], epsfile, opts);\n  unwind_protect_cleanup\n    set (h, {\"fontsize\"}, fontsize);\n  end_unwind_protect\n\nendfunction\n\n\nfunction local_drawnow (term, file, opts)\n\n  set (0, \"currentfigure\", opts.figure);\n  if (isempty (opts.debug_file) || ! opts.debug)\n    drawnow (term, file);\n  else\n    drawnow (term, file, opts.debug_file);\n  endif\n  if (opts.debug)\n    fprintf (\"Expanded gnuplot terminal = '%s'\\n\", term);\n  endif\n\nendfunction\n\n\nfunction f = font_spec (opts, varargin)\n\n  for n = 1:2:numel (varargin)\n    opts.(varargin{n}) = varargin{n+1};\n  endfor\n  f = \"\";\n  switch (opts.devopt)\n    case \"cgm\"\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, opts.fontsize);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize);\n      endif\n    case {\"eps\", \"eps2\", \"epsc\", \"epsc2\"}\n      ## Gnuplot renders fonts as half their specification, which\n      ## results in a tight spacing for the axes-labels and tick-labels.\n      ## Compensate for the half scale.  This will produce the proper\n      ## spacing for the requested fontsize.\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, 2 * opts.fontsize);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', 2 * opts.fontsize);\n      endif\n    case \"svg\"\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, opts.fontsize * 0.75);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize * 0.75);\n      endif\n    case \"pdf\"\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, opts.fontsize);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize);\n      endif\n    case {\"cairolatex\", \"epscairo\", \"epscairolatex\", ...\n          \"epscairolatexstandalone\", \"pdfcairo\", \"pdfcairolatex\", ...\n          \"pdfcairolatexstandalone\", \"pngcairo\", ...\n          \"pdflatexstandalone\", \"pdflatex\"}\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, opts.fontsize);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize);\n      endif\n    case {\"epslatex\", \"epslatexstandalone\"}\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, opts.fontsize);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize);\n      endif\n    case \"pslatex\"\n      if (! isempty (opts.fontsize))\n        f = sprintf (\"%d\", opts.fontsize);\n      endif\n    case {\"gif\", \"jpeg\", \"png\"}\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, opts.fontsize);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize);\n      endif\n    case \"emf\"\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, opts.fontsize);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize);\n      endif\n    case \"canvas\"\n      if (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize);\n      endif\n    case {\"aifm\", \"corel\"}\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, opts.fontsize);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize);\n      endif\n    case \"fig\"\n      if (! isempty (opts.font) && ! isempty (opts.fontsize))\n        f = sprintf ('font \"%s,%d\"', opts.font, opts.fontsize);\n      elseif (! isempty (opts.font))\n        f = sprintf ('font \"%s\"', opts.font);\n      elseif (! isempty (opts.fontsize))\n        f = sprintf ('font \",%d\"', opts.fontsize);\n      endif\n  endswitch\n\nendfunction\n\n\nfunction [h, fontsize] = get_figure_text_objs (opts)\n\n  h = findall (opts.figure, \"-property\", \"fontsize\");\n  hp = get (h, \"parent\");\n  if (iscell (hp))\n    hp = cell2mat (hp);\n  endif\n  ## Do not change the text objects fontsizes for the children of a\n  ## legend axes.  These will be handled by the fontsize listener.\n  is_legend_key_string = strcmp (get (hp, \"tag\"), \"legend\") ...\n                         & strcmp (get (hp, \"type\"), \"axes\");\n  h(is_legend_key_string) = [];\n  fontsize = get (h, \"fontsize\");\n  switch (numel (fontsize))\n    case 0\n      fontsize = {};\n    case 1\n      fontsize = {fontsize};\n  endswitch\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__gnuplot_version__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{version} =} __gnuplot_version__ ()\n## Undocumented internal function.\n## @end deftypefn\n\n## Return the version of gnuplot we are using.  Note that we do not\n## attempt to handle the case of the user switching to different\n## versions of gnuplot during the same session.\n\nfunction version = __gnuplot_version__ ()\n\n  persistent __version__ = \"\";\n\n  if (isempty (__version__))\n    [status, output] = system (sprintf ('\"%s\" --version', gnuplot_binary ()));\n    if (status != 0)\n      ## This message ends in a newline so that the traceback messages\n      ## are skipped and people might actually see the message, read it,\n      ## comprehend it, take the advice it gives, and stop asking us\n      ## why plotting fails when gnuplot is not found.\n      error (\"The gnuplot executable '%s' was not found or does not work.  If you have gnuplot installed in a non-standard location, see the 'gnuplot_binary' function\\n\", gnuplot_binary ());\n    endif\n    output = strrep (output, \"gnuplot\", \"\");\n    output = strrep (output, \"patchlevel\", \".\");\n    output = strrep (output, \"\\n\", \"\");\n    output = strrep (output, \"\\r\", \"\");\n    __version__ = strrep (output, \" \", \"\");\n  endif\n\n  version = __version__;\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__opengl_print__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{opts} =} __opengl_print__ (@var{@dots{}})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction opts = __opengl_print__ (opts)\n\n  dos_shell = (ispc () && ! isunix ());\n\n  if (! isempty (opts.fig2dev_binary))\n    ## fig2dev is preferred for conversion to emf\n    fig2dev_devices = {\"pstex\", \"mf\", \"emf\"};\n  else\n    fig2dev_devices = {\"pstex\", \"mf\"};\n  endif\n\n  gl2ps_device = {};\n  pipeline = {};\n  switch (lower (opts.devopt))\n    case {\"eps\", \"eps2\", \"epsc\", \"epsc2\"}\n      ## format GL2PS_EPS\n      gl2ps_device = {\"eps\"};\n      ## FIXME: use epstool to tighten bbox and provide preview.\n      pipeline = {opts.epstool_cmd(opts, \"-\", opts.name)};\n    case {\"epslatex\", \"pslatex\", \"pdflatex\", \"epslatexstandalone\", ...\n          \"pslatexstandalone\", \"pdflatexstandalone\"}\n      ## format GL2PS_TEX\n      n = find (opts.devopt == \"l\", 1);\n      suffix = opts.devopt(1:n-1);\n      [ndir, name, ext] = fileparts (opts.name);\n      if (isempty (ext))\n        ext = \"tex\";\n      else\n        ext = ext(2:end);  # remove leading '.'\n      endif\n      if (any (strcmpi (ext, {suffix, \"tex\"})))\n        name = fullfile (ndir, name);\n        if (any (strcmpi (ext, {\"eps\", \"ps\", \"pdf\"})))\n          suffix = ext;  # If user provides eps/ps/pdf suffix, use it.\n        endif\n      else\n        error (\"Octave:print:invalid-suffix\",\n               \"invalid suffix '%s' for device '%s'.\",\n               ext, lower (opts.devopt));\n      endif\n      gl2ps_device = {sprintf(\"%snotxt\", lower (suffix))};\n      gl2ps_device{2} = \"tex\";\n      if (dos_shell)\n        pipeline = {sprintf('findstr . > \"%s-inc.%s\"', name, suffix)};\n        pipeline{2} = sprintf ('findstr . > \"%s.tex\"', name);\n      else\n        pipeline = {sprintf('cat > \"%s-inc.%s\"', name, suffix)};\n        pipeline{2} = sprintf ('cat > \"%s.tex\"', name);\n      endif\n    case \"tikz\"\n      ## format GL2PS_PGF\n      gl2ps_device = {\"pgf\"};\n      pipeline = {sprintf('cat > \"%s\"', opts.name)};\n    case \"svg\"\n      ## format GL2PS_SVG\n      gl2ps_device = {\"svg\"};\n      svgcmd = \"\";\n      if (opts.svgconvert)\n        svgcmd = opts.svgconvert_cmd (opts, opts.ghostscript.device);\n      endif\n      if (! isempty (svgcmd))\n        pipeline = {sprintf(svgcmd, \"svg\", opts.name)};\n      else\n        pipeline = {sprintf('cat > \"%s\"', opts.name)};\n      endif\n    case fig2dev_devices\n      cmd_fig2dev = opts.fig2dev_cmd (opts, opts.devopt);\n      if (strcmp (opts.devopt, \"pstex\"))\n        cmd_pstoedit = opts.pstoedit_cmd (opts, \"fig\", false);\n        [~, ~, ext] = fileparts (opts.name);\n        if (any (strcmpi (ext, {\".ps\", \".tex\", \".\"})))\n          opts.name = opts.name(1:end-numel (ext));\n        endif\n        opts.name = [opts.name \".ps\"];\n        cmd = sprintf ('%s | %s > \"%s\"', cmd_pstoedit, cmd_fig2dev, opts.name);\n        gl2ps_device = {\"eps\"};\n        pipeline = {cmd};\n        cmd_fig2dev = opts.fig2dev_cmd (opts, \"pstex_t\");\n        gl2ps_device{2} = \"eps\";\n        pipeline{2} = sprintf ('%s | %s > \"%s\"', cmd_pstoedit,\n                               cmd_fig2dev, strrep (opts.name, \".ps\", \".tex\"));\n      else\n        ## Using svgconvert\n        tmp = tempname ();\n        opts.unlink = [opts.unlink tmp];\n        cmd_pstoedit = sprintf (opts.pstoedit_cmd (opts, \"fig\"), ...\n                                \"pdf\", tmp, tmp);\n        tmp = [tempname(), \".fig\"];\n        opts.unlink = [opts.unlink tmp];\n        if (ispc ())\n          cmd = sprintf ('%s \"%s\" & %s \"%s\" \"%s\"', cmd_pstoedit, tmp, cmd_fig2dev, tmp, opts.name);\n        else\n          cmd = sprintf ('%s \"%s\" ; %s \"%s\" \"%s\"', cmd_pstoedit, tmp, cmd_fig2dev, tmp, opts.name);\n        endif\n        gl2ps_device = {\"svg\"};\n        pipeline = {cmd};\n      endif\n    case \"aifm\"\n      tmp = tempname ();\n      opts.unlink = [opts.unlink tmp];\n      cmd = sprintf (opts.pstoedit_cmd (opts, \"ps2ai\"), \"pdf\", tmp, tmp);\n      gl2ps_device = {\"svg\"};\n      pipeline = {sprintf(\"%s > %s\", cmd, opts.name)};\n    case {\"dxf\", \"emf\", \"fig\", \"hpgl\"}\n      tmp = tempname ();\n      opts.unlink = [opts.unlink tmp];\n      cmd = sprintf (opts.pstoedit_cmd (opts), \"pdf\", tmp, tmp);\n      gl2ps_device = {\"svg\"};\n      pipeline = {sprintf('%s \"%s\"', cmd, opts.name)};\n    case opts.ghostscript.device\n      svgcmd = \"\";\n      if (opts.svgconvert)\n        svgcmd = opts.svgconvert_cmd (opts, opts.ghostscript.device);\n      endif\n      dosvg = ! isempty (svgcmd);\n      if (! dosvg)\n        opts.ghostscript.source = \"-\";\n      else\n        tmp = tempname ();\n        opts.ghostscript.source = tmp;\n        opts.unlink = [opts.unlink tmp];\n        svgcmd = sprintf (svgcmd, \"pdf\", tmp);\n      endif\n\n      opts.ghostscript.output = opts.name;\n      if (opts.send_to_printer)\n        opts.unlink(strcmp (opts.unlink, opts.ghostscript.output)) = [];\n        opts.ghostscript.output = \"-\";\n      endif\n\n      [cmd_gs, cmd_cleanup] = __ghostscript__ (opts.ghostscript);\n      if (opts.send_to_printer || isempty (opts.name))\n        cmd_lpr = opts.lpr_cmd (opts);\n        cmd = sprintf (\"%s | %s\", cmd_gs, cmd_lpr);\n      elseif (dosvg)\n        if (dos_shell)\n          cmd = sprintf (\"%s & %s\", svgcmd, cmd_gs);\n        else\n          cmd = sprintf (\"%s ; %s\", svgcmd, cmd_gs);\n        endif\n      else\n        cmd = sprintf (\"%s\", cmd_gs);\n      endif\n\n      if (dosvg)\n        gl2ps_device = {\"svg\"};\n      else\n        gl2ps_device = {\"eps\"};\n      endif\n\n      if (! isempty (cmd_cleanup))\n        if (dos_shell)\n          pipeline = {sprintf(\"%s & %s\", cmd, cmd_cleanup)};\n        else\n          pipeline = {sprintf(\"%s ; %s\", cmd, cmd_cleanup)};\n        endif\n      else\n        pipeline = {cmd};\n      endif\n    otherwise\n      error (sprintf (\"print:no%soutput\", opts.devopt),\n             \"print: %s output is not available for OpenGL toolkits\",\n             upper (opts.devopt));\n  endswitch\n\n  opts.pipeline = pipeline;\n\n  for n = 1:numel (pipeline)\n    if (opts.debug)\n      fprintf (\"opengl-pipeline: '%s'\\n\", pipeline{n});\n    endif\n\n    __check_rendering_capability__ (\"print\", opts.figure);\n\n    ## Use toolkits \"print_figure\" method\n    drawnow (gl2ps_device{n}, [\"| \" pipeline{n}]);\n  endfor\n\n  if (! isempty (strfind (opts.devopt, \"standalone\")))\n    opts.latex_standalone (opts);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__print_parse_opts__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{args} =} __print_parse_opts__ (@var{propname}, @var{propvalue})\n## @deftypefnx {} {@var{args} =} __print_parse_opts__ (@var{struct})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction arg_st = __print_parse_opts__ (varargin)\n\n  persistent warn_on_missing_ghostscript = true;\n\n  arg_st.append_to_file = false;\n  arg_st.canvas_size = [];\n  arg_st.debug = false;\n  arg_st.debug_file = \"octave-print-commands.log\";\n  arg_st.devopt = \"\";\n  arg_st.epstool_binary = __quote_path__ (__find_binary__ (\"epstool\"));\n  arg_st.figure = get (0, \"currentfigure\");\n  arg_st.fig2dev_binary = __quote_path__ (__find_binary__ (\"fig2dev\"));\n  arg_st.fontsize = [];\n  arg_st.font = \"\";\n  arg_st.scalefontsize = 1;\n  arg_st.force_solid = 0; # 0=default, -1=dashed, +1=solid\n  arg_st.formatted_for_printing = false;\n  arg_st.ghostscript.binary = __quote_path__ (__ghostscript_binary__ ());\n  arg_st.ghostscript.debug = false;\n  arg_st.ghostscript.device = \"\";\n  arg_st.ghostscript.epscrop = true;\n  arg_st.ghostscript.level = 2;\n  arg_st.ghostscript.output = \"\";\n  arg_st.ghostscript.papersize = \"letter\";\n  arg_st.ghostscript.pageoffset = [];\n  arg_st.ghostscript.resolution = 150;\n  arg_st.ghostscript.antialiasing = false;\n  arg_st.ghostscript.antialiasing_textalphabits = 4;\n  arg_st.ghostscript.antialiasing_graphicsalphabits = 1;\n  arg_st.lpr_binary = __quote_path__ (__find_binary__ (\"lpr\"));\n  arg_st.polymerge = 1;\n  arg_st.name = \"\";\n  arg_st.append_file_extension = true;\n  arg_st.orientation = \"\";\n  arg_st.pstoedit_binary = __quote_path__ (__find_binary__ (\"pstoedit\"));\n  arg_st.preview = \"\";\n  arg_st.printer = \"\";\n  arg_st.renderer = \"auto\";\n  arg_st.resize_flag = \"\";\n  arg_st.rgb_output = false;\n  arg_st.send_to_printer = false;\n  arg_st.special_flag = \"textnormal\";\n  arg_st.svgconvert = true;\n  arg_st.svgconvert_binary = __quote_path__ (__svgconv_binary__ ());\n  arg_st.tight = true;\n  arg_st.use_color = 0; # 0=default, -1=mono, +1=color\n\n  if (isunix ())\n    arg_st.lpr_options = \"-l\";\n  elseif (ispc ())\n    arg_st.lpr_options = \"-o l\";\n  else\n    arg_st.lpr_options = \"\";\n  endif\n  arg_st.unlink = {};\n\n  if (nargin > 0 && isfigure (varargin{1}))\n    arg_st.figure = varargin{1};\n    varargin(1) = [];\n  endif\n\n  if (! isempty (findall (arg_st.figure, \"type\", \"patch\", ...\n                          \"-or\", \"type\", \"surface\")))\n    arg_st.polymerge = 2;\n  endif\n\n  for i = 1:numel (varargin)\n    if (! ischar (varargin{i}) && ! iscellstr (varargin{i}))\n      error (\"print: input arguments must be a graphics handle or strings.\");\n    endif\n    arg = strtrim (varargin{i});\n    if (ischar (arg))\n      if (isempty (arg))\n        continue;\n      elseif (strcmp (arg, \"-color\"))\n        arg_st.use_color = 1;\n      elseif (strcmp (arg, \"-append\"))\n        arg_st.append_to_file = true;\n      elseif (strcmp (arg, \"-mono\"))\n        arg_st.use_color = -1;\n      elseif (strcmp (arg, \"-solid\"))\n        arg_st.force_solid = 1;\n      elseif (strcmp (arg, \"-dashed\"))\n        arg_st.force_solid = -1;\n      elseif (any (strcmp (arg, {\"-opengl\", \"-painters\"})))\n        arg_st.renderer = arg(2:end);\n      elseif (strcmp (arg, \"-image\"))\n        arg_st.renderer = \"opengl\";\n      elseif (strcmp (arg, \"-vector\"))\n        arg_st.renderer = \"painters\";\n      elseif (strcmp (arg, \"-RGBImage\"))\n        arg_st.rgb_output = true;\n        arg_st.renderer = \"opengl\";\n      elseif (strncmp (arg, \"-portrait\", length (arg)))\n        arg_st.orientation = \"portrait\";\n      elseif (strncmp (arg, \"-landscape\", length (arg)))\n        arg_st.orientation = \"landscape\";\n      elseif (strcmp (arg, \"-loose\"))\n        arg_st.tight = false;\n      elseif (strcmp (arg, \"-tight\"))\n        arg_st.tight = true;\n      elseif (strcmp (arg, \"-svgconvert\"))\n        arg_st.svgconvert = true;\n      elseif (strcmp (arg, \"-nosvgconvert\"))\n        arg_st.svgconvert = false;\n      elseif (strcmp (arg, \"-polymerge\"))\n        arg_st.polymerge = 1;\n      elseif (strcmp (arg, \"-nopolymerge\"))\n        arg_st.polymerge = 0;\n      elseif (strcmp (arg, \"-polymerge-all\"))\n        arg_st.polymerge = 2;\n      elseif (strcmp (arg, \"-textspecial\"))\n        arg_st.special_flag = \"textspecial\";\n      elseif (strcmp (arg, \"-fillpage\"))\n        arg_st.resize_flag = \"fillpage\";\n      elseif (strcmp (arg, \"-bestfit\"))\n        arg_st.resize_flag = \"bestfit\";\n      elseif (any (strcmp (arg,\n                           {\"-interchange\", \"-metafile\", \"-pict\", \"-tiff\"})))\n        arg_st.preview = arg(2:end);\n      elseif (strcmp (arg, \"-no-append-file-extension\"))\n        arg_st.append_file_extension = false;\n      elseif (strncmp (arg, \"-debug\", 6))\n        arg_st.debug = true;\n        arg_st.ghostscript.debug = true;\n        if (length (arg) > 7)\n          arg_st.debug_file = arg(8:end);\n        endif\n      elseif (length (arg) > 2 && arg(1:2) == \"-d\")\n        arg_st.devopt = lower (arg(3:end));\n      elseif (length (arg) > 2 && arg(1:2) == \"-P\")\n        arg_st.printer = arg;\n      elseif (strncmp (arg, \"-EPSTOOL:\", 9))\n        arg_st.epstool_binary = arg(10:end);\n      elseif (strncmp (arg, \"-FIG2DEV:\", 9))\n        arg_st.fig2dev_binary = arg(10:end);\n      elseif (strncmp (arg, \"-PSTOEDIT:\", 9))\n        arg_st.pstoedit_binary = arg(10:end);\n      elseif (strncmpi (arg, \"-textalphabits=\", 15))\n        if (length (arg) == 16 && any (arg(end) == \"124\"))\n          arg_st.ghostscript.antialiasing_textalphabits = str2double (arg(end));\n        else\n          error (\"print: improper syntax, or value, for TextAlphaBits\");\n        endif\n      elseif (strncmpi (arg, \"-graphicsalphabits=\", 19))\n        if (numel (arg) == 20 && any (arg(end) == \"124\"))\n          arg_st.ghostscript.antialiasing_graphicsalphabits = str2double (arg(end));\n        else\n          error (\"print: improper syntax, or value, for GraphicsAlphaBits\");\n        endif\n      elseif (length (arg) > 2 && arg(1:2) == \"-G\")\n        arg_st.ghostscript.binary = file_in_path (getenv (\"PATH\"), arg(3:end));\n        if (isempty (arg_st.ghostscript.binary))\n          error ('print: Ghostscript binary \"%s\" not found in PATH',\n                 arg(3:end));\n        endif\n        arg_st.ghostscript.binary = __quote_path__ (arg_st.ghostscript.binary);\n      elseif (length (arg) > 2 && arg(1:2) == \"-F\")\n        idx = rindex (arg, \":\");\n        if (idx)\n          arg_st.font = arg(3:idx-1);\n          arg_st.fontsize = str2double (arg(idx+1:end));\n        else\n          arg_st.font = arg(3:end);\n        endif\n      elseif (length (arg) > 2 && arg(1:2) == \"-S\")\n        arg_st.canvas_size = str2double (strsplit (arg(3:end), \",\"));\n      elseif (length (arg) > 2 && arg(1:2) == \"-r\")\n        arg_st.ghostscript.resolution = str2double (arg(3:end));\n      elseif (length (arg) > 2 && arg(1:2) == \"-f\")\n        arg_st.figure = str2double (arg(3:end));\n      elseif (strcmp (arg, \"-noui\"))\n        ## Accepted, but nothing needs to be done since Octave already\n        ## excludes uicontrol objects when printing.\n      elseif (length (arg) >= 1 && arg(1) == \"-\")\n        error (\"print: unknown option '%s'\", arg);\n      elseif (length (arg) > 0)\n        arg_st.name = tilde_expand (arg);\n      endif\n    elseif (isfigure (arg))\n      arg_st.figure = arg;\n    else\n      error (\"print: first argument must be string or figure handle\");\n    endif\n  endfor\n\n  ## Resolution\n  if (arg_st.ghostscript.resolution == 0)\n    ## Do as Matlab does.\n    arg_st.ghostscript.resolution = get (0, \"screenpixelsperinch\");\n  endif\n\n  ## Orientation\n  if (isempty (arg_st.orientation))\n    if (isfigure (arg_st.figure))\n      arg_st.orientation = get (arg_st.figure, \"paperorientation\");\n    else\n      ## Allows tests to be run without error.\n      arg_st.orientation = \"portrait\";\n    endif\n  endif\n\n  ## The device is infered from extension if not provided\n  dot = rindex (arg_st.name, \".\");\n  if (isempty (arg_st.devopt))\n    if (arg_st.rgb_output)\n      arg_st.devopt = \"png\";\n    elseif (dot == 0 || ! arg_st.append_file_extension)\n      arg_st.devopt = \"psc\";\n    else\n      arg_st.devopt = lower (arg_st.name(dot+1:end));\n    endif\n  endif\n\n  ## Warn about deprecated output formats\n  persistent unsupported = {\"aifm\", \"ill\",\"cdr\", \"corel\", ...\n                            \"hpgl\", \"mf\", \"cgm\", \"dxf\"}\n\n  if (any (strcmp (unsupported, arg_st.devopt)))\n    warning ('Octave:print:deprecated-format',\n             'print: \"%s\" format is no longer officially supported',\n             arg_st.devopt);\n  endif\n\n  ## By default, use the \"opengl\" renderer for all raster outputs\n  ## supported by \"imwrite\".\n  fmts = imformats ();\n  persistent gl_devlist = [fmts(! cellfun ('isempty', {fmts.write})).ext, ...\n                           \"tiffn\"];\n  opengl_ok = any (strcmp (gl_devlist, arg_st.devopt));\n\n  if (strcmp (arg_st.renderer, \"auto\")\n      && strcmp (get (arg_st.figure, \"renderermode\"), \"manual\"))\n    arg_st.renderer = get (arg_st.figure, \"renderer\");\n  endif\n\n  if (strcmp (arg_st.renderer, \"auto\"))\n    if (opengl_ok && strcmp (graphics_toolkit (arg_st.figure), \"qt\"))\n      arg_st.renderer = \"opengl\";\n    else\n      arg_st.renderer = \"painters\";\n    endif\n  elseif (strcmp (arg_st.renderer, \"opengl\") && ! opengl_ok)\n    arg_st.renderer = \"painters\";\n    warning (['print: unsupported output format \"%s\" for renderer ', ...\n              '\"opengl\".'], arg_st.devopt);\n  elseif (! strcmp (graphics_toolkit (arg_st.figure), \"qt\")\n          && strcmp (arg_st.renderer, \"opengl\"))\n    ## The opengl renderer only works with the \"qt\" toolkit\n    arg_st.renderer = \"painters\";\n    warning ('Octave:print:unsupported-renderer',\n             'print: \"opengl\" renderer unsupported for \"%s\" toolkit',\n             graphics_toolkit (arg_st.figure));\n  endif\n\n\n  if (arg_st.use_color == 0)\n    if (any (strcmp ({\"ps\", \"ps2\", \"eps\", \"eps2\"}, arg_st.devopt)))\n      arg_st.use_color = -1;\n    else\n      arg_st.use_color = 1;\n    endif\n  endif\n\n  if (strcmp (arg_st.devopt, \"tex\"))\n    arg_st.devopt = \"epslatex\";\n  elseif (strcmp (arg_st.devopt, \"ill\"))\n    arg_st.devopt = \"aifm\";\n  elseif (strcmp (arg_st.devopt, \"cdr\"))\n    arg_st.devopt = \"corel\";\n  elseif (strcmp (arg_st.devopt, \"meta\"))\n    arg_st.devopt = \"emf\";\n  elseif (strcmp (arg_st.devopt, \"jpg\"))\n    arg_st.devopt = \"jpeg\";\n  elseif (strcmp (arg_st.devopt, \"tif\"))\n    arg_st.devopt = \"tiff\";\n  elseif (strcmp (arg_st.devopt, \"pdfcrop\"))\n    arg_st.devopt = \"pdfwrite\";\n  endif\n\n  persistent dev_list = [{\"aifm\", \"corel\", \"dumb\", \"fig\", \"png\", \"jpeg\", ...\n              \"gif\", \"pbm\", \"pbmraw\", \"dxf\", \"mf\", ...\n              \"svg\", \"hpgl\", \"ps\", \"ps2\", \"psc\", ...\n              \"psc2\", \"eps\", \"eps2\", \"epsc\", \"epsc2\", ...\n              \"emf\", \"pdf\", \"pslatex\", \"epslatex\", \"epslatexstandalone\", ...\n              \"pslatexstandalone\", \"pdflatexstandalone\", ...\n              \"pstex\", \"tiff\", \"tiffn\", \"tikz\", \"tikzstandalone\", \"pcxmono\", ...\n              \"pcx24b\", \"pcx256\", \"pcx16\", \"pgm\", \"pgmraw\", ...\n              \"ppm\", \"ppmraw\", \"pdflatex\", \"texdraw\", ...\n              \"epscairo\", \"pdfcairo\", \"pngcairo\", \"cairolatex\", ...\n              \"pdfcairolatex\", \"pdfcairolatexstandalone\", ...\n              \"epscairolatex\", \"epscairolatexstandalone\", \"pstricks\", ...\n              \"epswrite\", \"eps2write\", \"pswrite\", \"ps2write\", \"pdfwrite\", ...\n              \"canvas\", \"cgm\", \"latex\", \"eepic\"}, gl_devlist];\n\n  persistent suffixes = [{\"ai\", \"cdr\", \"txt\", \"fig\", \"png\", \"jpg\", ...\n              \"gif\", \"pbm\", \"pbm\", \"dxf\", \"mf\", ...\n              \"svg\", \"hpgl\", \"ps\", \"ps\", \"ps\", ...\n              \"ps\", \"eps\", \"eps\", \"eps\", \"eps\", ...\n              \"emf\", \"pdf\", \"tex\", \"tex\", \"tex\", ...\n              \"tex\", \"tex\", ...\n              \"ps\", \"tiff\", \"tiff\", \"tikz\", \"tikz\", \"pcx\", ...\n              \"pcx\", \"pcx\", \"pcx\", \"pgm\", \"pgm\", ...\n              \"ppm\", \"ppm\", \"tex\", \"tex\", ...\n              \"eps\", \"pdf\", \"png\", \"tex\", ...\n              \"tex\", \"tex\", ...\n              \"tex\", \"tex\", \"tex\", ...\n              \"eps\", \"eps\", \"ps\", \"ps\", \"pdf\", ...\n              \"js\", \"cgm\", \"tex\", \"tex\"}, gl_devlist];\n\n  if (isfigure (arg_st.figure))\n    __graphics_toolkit__ = get (arg_st.figure, \"__graphics_toolkit__\");\n  else\n    ## Allow tests when no figures are present.\n    __graphics_toolkit__ = get (0, \"defaultfigure__graphics_toolkit__\");\n  endif\n\n  if (strcmp (__graphics_toolkit__, \"gnuplot\"))\n    suffixes(strncmp (dev_list, \"epslatex\", 8)) = {\"eps\"};\n  endif\n\n  unknown_device = true;\n  default_suffix = \"\";\n  match = strcmpi (dev_list, arg_st.devopt);\n  if (any (match))\n    unknown_device = false;\n    default_suffix = suffixes{match};\n  endif\n\n  if (arg_st.append_file_extension && dot == 0 && ! isempty (arg_st.name) ...\n      && ! isempty (default_suffix))\n    arg_st.name = [arg_st.name \".\" default_suffix];\n  endif\n\n  if (arg_st.append_to_file)\n    if (isempty (arg_st.name))\n      arg_st.append_to_file = false;\n    elseif (any (strcmpi (arg_st.devopt, {\"eps\", \"eps2\", \"epsc\", \"epsc2\", ...\n                                          \"ps\", \"ps2\", \"psc\", \"psc2\", \"pdf\"})))\n      have_ghostscript = ! isempty (__ghostscript_binary__ ());\n      if (have_ghostscript)\n        file_exists = (numel (dir (arg_st.name)) == 1\n                       && ! isfolder (arg_st.name));\n        if (! file_exists)\n          arg_st.append_to_file = false;\n        endif\n      else\n        arg_st.append_to_file = false;\n        warning (\"print: appended output requires Ghostscript to be installed\");\n      endif\n    else\n      warning (\"print: appended output is not supported for device '%s'\",\n               arg_st.devopt);\n      arg_st.append_to_file = false;\n    endif\n  endif\n\n  if (arg_st.rgb_output)\n    if (! isempty (arg_st.printer) || ! isempty (arg_st.name))\n      warning (\"Octave:print:ignored_argument\",\n               \"print: ignoring file name and printer argument when using -RGBImage option\");\n    endif\n  elseif (! isempty (arg_st.printer) || isempty (arg_st.name))\n    arg_st.send_to_printer = true;\n  endif\n\n  if (any (strcmp (arg_st.devopt, {\"ps\", \"ps2\", \"psc\", \"psc2\", \"pdf\"})))\n    arg_st.formatted_for_printing = true;\n  endif\n\n  aliases = gs_aliases (arg_st.svgconvert);\n  if (any (strcmp (arg_st.devopt, fieldnames (aliases)))\n      && ! strcmp (arg_st.renderer, \"opengl\"))\n    arg_st.devopt = aliases.(arg_st.devopt);\n    unknown_device = false;\n  endif\n\n  if ((any (strcmp (arg_st.devopt, gs_device_list))\n       && ! arg_st.formatted_for_printing)\n      || any (strcmp (arg_st.devopt, {\"pswrite\", \"ps2write\", \"pdfwrite\"})))\n    unknown_device = false;\n    ## Use ghostscript for graphic formats\n    arg_st.ghostscript.device = arg_st.devopt;\n    arg_st.ghostscript.output = arg_st.name;\n    arg_st.ghostscript.antialiasing = true;\n    if (arg_st.formatted_for_printing)\n      arg_st.ghostscript.epscrop = arg_st.tight;\n    else\n      ## pstoedit throws errors if the EPS file isn't cropped\n      arg_st.ghostscript.epscrop = true;\n    endif\n  elseif (all (! strcmp (arg_st.devopt, dev_list)))\n    ## Assume we are formatting output for a printer\n    arg_st.formatted_for_printing = true;\n    arg_st.ghostscript.device = arg_st.devopt;\n    arg_st.ghostscript.output = arg_st.name;\n    arg_st.ghostscript.antialiasing = false;\n    arg_st.ghostscript.epscrop = arg_st.tight;\n  endif\n\n  if (unknown_device)\n    error (\"print: unknown device %s\", arg_st.devopt);\n  endif\n\n  if (arg_st.resize_flag)\n    if (! (arg_st.send_to_printer || arg_st.formatted_for_printing\n           || strncmp (arg_st.devopt, \"pdf\", 3)\n           || strncmp (arg_st.devopt, \"ps\", 2)))\n      error (\"print: the '%s' option is only valid for page formats and printers\", arg_st.resize_flag);\n    endif\n  endif\n\n  if (arg_st.send_to_printer)\n    if (isempty (arg_st.name))\n      ## Pipe the ghostscript output\n      arg_st.name = \"-\";\n    else\n      error (\"print: a filename may not specified when spooling to a printer\");\n    endif\n    if (! any (strcmp (arg_st.devopt, gs_device_list)))\n      ## Only supported ghostscript devices\n      error (\"print: format must be a valid Ghostscript format for spooling to a printer\");\n    endif\n  elseif (isempty (arg_st.name) && ! arg_st.rgb_output)\n    error (\"print: an output filename must be specified\");\n  endif\n\n  if (isempty (arg_st.canvas_size))\n    if (isfigure (arg_st.figure))\n      [arg_st.ghostscript.papersize, papersize_points, paperposition] = ...\n                           gs_papersize (arg_st.figure, arg_st.orientation);\n    else\n      ## allows BIST tests to be run\n      arg_st.ghostscript.papersize = \"letter\";\n      paperposition = [0.25, 2.50, 8.00, 6.00] * 72;\n      papersize_points = [8.5, 11.0] * 72;\n    endif\n\n    ## resize paper\n    if (arg_st.resize_flag)\n      if (strcmp (arg_st.resize_flag, \"fillpage\"))\n        ## leave a 0.25 inch margin on all sides of the page.\n        paperposition = [0.25 * 72, 0.25 * 72, ...\n                         papersize_points(1) - 0.5*72, ...\n                         papersize_points(2) - 0.5*72];\n      elseif (strcmp (arg_st.resize_flag, \"bestfit\"))\n        ## leaves a minimum page margin of 0.25 inches\n        if (paperposition(3) > paperposition(4))\n          fit_scale = papersize_points(1) / paperposition(3);\n        else\n          fit_scale = papersize_points(2) / paperposition(4);\n        endif\n        paperposition = [(papersize_points(1) - fit_scale*paperposition(3)) * 0.5, ...\n                        (papersize_points(2) - fit_scale*paperposition(4)) * 0.5, ...\n                        fit_scale * paperposition(3), ...\n                        fit_scale * paperposition(4)];\n      endif\n    endif\n\n    arg_st.canvas_size = paperposition(3:4);\n    if (strcmp (__graphics_toolkit__, \"gnuplot\")\n        && ! arg_st.ghostscript.epscrop)\n      arg_st.ghostscript.pageoffset = paperposition(1:2) - 50;\n    else\n      arg_st.ghostscript.pageoffset = paperposition(1:2);\n    endif\n  else\n    ## Size specified with -S option\n    if (arg_st.ghostscript.resolution != 150)\n      warning (\"print: '-Sxsize,ysize' overrides resolution option -r\\n\");\n    endif\n    arg_st.scalefontsize = arg_st.canvas_size(1) / ...\n                           6 / get (0, \"screenpixelsperinch\");\n    arg_st.ghostscript.resolution = 72;\n    arg_st.ghostscript.papersize = arg_st.canvas_size;\n    papersize_points = arg_st.canvas_size * 72;\n    arg_st.ghostscript.epscrop = true;\n    arg_st.ghostscript.pageoffset = [0, 0];\n    paperposition = [0, 0];\n  endif\n\n  if (arg_st.formatted_for_printing)\n    arg_st.ghostscript.resolution = [];\n\n    ## Warn if the figure is too large for the selected paper size\n    if (any (papersize_points < (arg_st.canvas_size + paperposition(1:2)))\n        || any (paperposition(1:2) < 0))\n      warning (\"Octave:print:figure-too-large\", ...\n               ['print: given the current \"paperposition\" and ', ...\n                '\"papersize\" properties, the figure is too large ', ...\n                \"and will be cropped to fit on the output page.\"]);\n    endif\n  else\n    arg_st.ghostscript.papersize = \"\";\n    arg_st.ghostscript.pageoffset = [0, 0];\n  endif\n\n  if (warn_on_missing_ghostscript)\n    if (isempty (arg_st.ghostscript.binary))\n      warning (\"print:nogs\", ...\n               \"print: 'gs' (Ghostscript) binary is not available.  Many formats may not be available\\n\");\n    endif\n    warn_on_missing_ghostscript = false;\n  endif\n\nendfunction\n\n\n## Test blocks are not allowed (and not needed) for private functions\n%!#test\n%! opts = __print_parse_opts__ ();\n%! assert (opts.devopt, \"pswrite\");\n%! assert (opts.use_color, 1);\n%! assert (opts.send_to_printer, true);\n%! assert (opts.canvas_size, [576, 432]);\n%! assert (opts.ghostscript.device, \"pswrite\");\n\n%!#test\n%! opts = __print_parse_opts__ (\"test.pdf\", \"-S640,480\");\n%! assert (opts.canvas_size, [307.2, 230.4], 0.1);\n\n%!#test\n%! opts = __print_parse_opts__ (\"-dpsc\", \"-append\", \"-loose\");\n%! assert (opts.devopt, \"pswrite\");\n%! assert (opts.send_to_printer, true);\n%! assert (opts.use_color, 1);\n%! assert (opts.append_to_file, false);\n%! assert (opts.ghostscript.device, \"pswrite\");\n%! assert (opts.ghostscript.epscrop, false);\n\n%!#test\n%! opts = __print_parse_opts__ (\"-deps\", \"-tight\");\n%! assert (opts.tight, true);\n%! assert (opts.send_to_printer, true);\n%! assert (opts.use_color, -1);\n%! assert (opts.ghostscript.device, \"\");\n\n%!#test\n%! opts = __print_parse_opts__ (\"-djpg\", \"foobar\", \"-mono\", \"-loose\");\n%! assert (opts.devopt, \"jpeg\");\n%! assert (opts.name, \"foobar.jpg\");\n%! assert (opts.ghostscript.device, \"jpeg\");\n%! assert (opts.ghostscript.epscrop, true);\n%! assert (opts.ghostscript.papersize, \"\");\n%! assert (opts.ghostscript.pageoffset, [0, 0]);\n%! assert (opts.send_to_printer, false);\n%! assert (opts.printer, \"\");\n%! assert (opts.use_color, -1);\n\n%!#test\n%! opts = __print_parse_opts__ (\"-ddeskjet\", \"foobar\", \"-mono\", \"-Pmyprinter\");\n%! assert (opts.ghostscript.output, \"foobar.deskjet\");\n%! assert (opts.ghostscript.device, \"deskjet\");\n%! assert (opts.devopt, \"deskjet\");\n%! assert (opts.send_to_printer, true);\n%! assert (opts.printer, \"-Pmyprinter\");\n%! assert (opts.use_color, -1);\n\n%!#test\n%! opts = __print_parse_opts__ (\"-f5\", \"-dljet3\");\n%! assert (opts.ghostscript.device, \"ljet3\");\n%! assert (strfind (opts.ghostscript.output, \".ljet3\"));\n%! assert (opts.devopt, \"ljet3\");\n%! assert (opts.send_to_printer, true);\n%! assert (opts.figure, 5);\n\nfunction cmd = __quote_path__ (cmd)\n\n  if (! isempty (cmd))\n    is_quoted = all (cmd([1, end]) == \"'\");\n    if (! is_quoted)\n      dos_shell = ispc () && ! isunix ();\n      if (dos_shell && any (cmd == \"/\"))\n        cmd = strrep (cmd, '/', '\\');\n      endif\n      if (any (cmd == \" \"))\n        cmd = ['\"' strrep(cmd, '\"', '\"\"') '\"'];\n      endif\n    endif\n  endif\n\nendfunction\n\nfunction gs = __ghostscript_binary__ ()\n\n  persistent ghostscript_binary = \"\";\n  persistent warn_on_bad_gsc = true;\n\n  if (isempty (ghostscript_binary))\n    GSC = getenv (\"GSC\");\n    if (exist (GSC, \"file\")\n        || (! isempty (GSC) && file_in_path (getenv (\"PATH\"), GSC)))\n      gs_binaries = {GSC};\n    elseif (! isempty (GSC) && warn_on_bad_gsc)\n      warning (\"Octave:print:badgscenv\",\n               \"print: GSC environment variable not set properly\");\n      warn_on_bad_gsc = false;\n      gs_binaries = {};\n    else\n      gs_binaries = {};\n    endif\n\n    if (isunix ())\n      ## Unix - Includes Mac OSX and Cygwin.\n      gs_binaries = [gs_binaries, {\"gs\", \"gs.exe\"}];\n    else\n      ## pc - Includes Win32 and mingw.\n      gs_binaries = [gs_binaries, ...\n                     {\"gs.exe\", \"gswin32c.exe\", \"gswin64c.exe\", \"mgs.exe\"}];\n    endif\n    n = 0;\n    while (n < numel (gs_binaries) && isempty (ghostscript_binary))\n      ghostscript_binary = file_in_path (getenv (\"PATH\"), gs_binaries{++n});\n    endwhile\n  endif\n\n  gs = ghostscript_binary;\n\nendfunction\n\nfunction bin = __svgconv_binary__ ()\n\n  persistent binary = \"\";\n\n  if (isempty (binary))\n    ## default installation location is the archlib directory\n    bindir = getenv (\"OCTAVE_ARCHLIBDIR\");\n    if (isempty (bindir))\n      bindir = __octave_config_info__ (\"archlibdir\");\n    endif\n\n    binary = fullfile (bindir, ...\n                       [\"octave-svgconvert\", ...\n                        __octave_config_info__(\"EXEEXT\")]);\n\n    if (! exist (binary, \"file\"))\n      binary = \"\";\n    endif\n  endif\n\n  bin = binary;\n\nendfunction\n\nfunction bin = __find_binary__ (binary)\n\n  persistent data = struct ();\n\n  if (! isfield (data, binary))\n    data.(binary).bin = \"\";\n  endif\n\n  if (isempty (data.(binary).bin))\n    if (isunix ())\n      ## Unix - Includes Mac OSX and Cygwin.\n      binaries = strcat (binary, {\"\", \".exe\"});\n    else\n      ## pc - Includes Win32 and mingw.\n      binaries = strcat (binary, {\".exe\"});\n    endif\n    n = 0;\n    while (n < numel (binaries) && isempty (data.(binary).bin))\n      data.(binary).bin = file_in_path (getenv (\"PATH\"), binaries{++n});\n    endwhile\n  endif\n\n  bin = data.(binary).bin;\n\nendfunction\n\nfunction [papersize, papersize_points, paperposition] = gs_papersize (hfig, paperorientation)\n  persistent papertypes papersizes;\n\n  if (isempty (papertypes))\n    papertypes = {\"usletter\", \"uslegal\",     \"a0\",     \"a1\", ...\n                        \"a2\",      \"a3\",     \"a4\",     \"a5\", ...\n                        \"b0\",      \"b1\",     \"b2\",     \"b3\", ...\n                        \"b4\",      \"b5\", \"arch-a\", \"arch-b\", ...\n                    \"arch-c\",  \"arch-d\", \"arch-e\",      \"a\", ...\n                         \"b\",       \"c\",      \"d\",      \"e\", ...\n                   \"tabloid\"};\n    papersizes = [ 8.5, 11.0;  8.5, 14.0; 33.1, 46.8; 23.4, 33.1;\n                  16.5, 23.4; 11.7, 16.5;  8.3, 11.7;  5.8,  8.3;\n                  39.4, 55.7; 27.8, 39.4; 19.7, 27.8; 13.9, 19.7;\n                   9.8, 13.9;  6.9,  9.8;  9.0, 12.0; 12.0, 18.0;\n                  18.0, 24.0; 24.0, 36.0; 36.0, 48.0;  8.5, 11.0;\n                  11.0, 17.0; 18.0, 24.0; 24.0, 36.0; 36.0, 48.0;\n                  11.0, 17.0] * 72;\n  endif\n\n  papertype = get (hfig, \"papertype\");\n  paperunits = get (hfig, \"paperunits\");\n  paperposition = get (hfig, \"paperposition\");\n  if (strcmp (papertype, \"<custom>\"))\n    papersize = get (hfig, \"papersize\");\n    papersize = convert2points (papersize, paperunits);\n  else\n    papersize = papersizes(strcmp (papertypes, papertype), :);\n  endif\n\n  if (strcmp (paperunits, \"normalized\"))\n    paperposition .*= papersize([1,2,1,2]);\n  else\n    paperposition = convert2points (paperposition, paperunits);\n  endif\n\n  ## FIXME: This will be obsoleted by listeners for paper properties.\n  ##        papersize is tall when portrait, and wide when landscape.\n  if ((papersize(1) > papersize(2) && strcmpi (paperorientation, \"portrait\"))\n      || (papersize(1) < papersize(2) && strcmpi (paperorientation, \"landscape\")))\n    papersize = papersize([2,1]);\n  endif\n\n  ## papersize is now [h,w] and measured in points.\n  ## Return it for possible resize outside of this function.\n  papersize_points = papersize;\n\n  if (! strcmp (papertype, \"<custom>\")\n      && (strcmp (paperorientation, \"portrait\")))\n    ## For portrait use the ghostscript name\n    papersize = papertype;\n    papersize(papersize==\"-\") = \"\";\n    papersize = strrep (papersize, \"us\", \"\");\n    switch (papersize)\n      case \"a\"\n        papersize = \"letter\";\n      case {\"b\", \"tabloid\"}\n        papersize = \"11x17\";\n      case {\"c\", \"d\", \"e\"}\n        papersize = [\"arch\" papersize];\n    endswitch\n    if (strncmp (papersize, \"arch\", 4))\n      papersize(end) = upper (papersize(end));\n    endif\n  endif\n\nendfunction\n\nfunction value = convert2points (value, units)\n\n  switch (units)\n    case \"inches\"\n      value *= 72;\n    case \"centimeters\"\n      value *= (72 / 2.54);\n    case \"normalized\"\n      error (\"Octave:print:customnormalized\",\n             \"print: papersize=='<custom>' and paperunits='normalized' may not be combined\");\n  endswitch\n\nendfunction\n\nfunction device_list = gs_device_list ()\n\n  ## Graphics formats/languages, not printers.\n  device_list = {\"bmp16\"; \"bmp16m\"; \"bmp256\"; \"bmp32b\"; \"bmpgray\"; ...\n                 \"epswrite\"; \"eps2write\"; \"jpeg\"; \"jpegcymk\"; \"jpeggray\";\n                 \"pbm\"; \"pbmraw\"; \"pcx16\"; \"pcx24b\"; \"pcx256\"; \"pcx2up\"; ...\n                 \"pcxcmyk\"; \"pcxgray\"; \"pcxmono\"; \"pdfwrite\"; \"pgm\"; ...\n                 \"pgmraw\"; \"pgnm\"; \"pgnmraw\"; \"png16\"; \"png16m\"; ...\n                 \"png256\"; \"png48\"; \"pngalpha\"; \"pnggray\"; \"pngmono\"; ...\n                 \"pnm\"; \"pnmraw\"; \"ppm\"; \"ppmraw\"; \"pswrite\"; \"ps2write\"; ...\n                 \"tiff12nc\"; \"tiff24nc\"; \"tiff32nc\"; \"tiff48nc\"; ...\n                 \"tiff64nc\"; \"tiffcrle\"; \"tiffg3\"; \"tiffg32d\"; \"tiffg4\"; ...\n                 \"tiffgray\"; \"tifflzw\"; \"tiffpack\"; \"tiffscaled\"; ...\n                 \"tiffscaled24\"; \"tiffscaled32\"; \"tiffscaled4\"; ...\n                 \"tiffscaled8\"; \"tiffsep\"; \"tiffsep1\" };\n\nendfunction\n\nfunction aliases = gs_aliases (do_eps)\n\n  ## Ghostscript device names\n  aliases.bmp   = \"bmp32b\";\n  aliases.pdf   = \"pdfwrite\";\n  aliases.png   = \"png16m\";\n  aliases.ps    = \"ps2write\";\n  aliases.ps2   = \"ps2write\";\n  aliases.psc   = \"ps2write\";\n  aliases.psc2  = \"ps2write\";\n  aliases.tiff  = \"tiffscaled24\";\n  aliases.tiffn = \"tiff24nc\";\n\n  if (do_eps)\n    aliases.eps   = \"eps2write\";\n    aliases.eps2  = \"eps2write\";\n    aliases.epsc  = \"eps2write\";\n    aliases.epsc2 = \"eps2write\";\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/private/__set_default_mouse_modes__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} __set_default_mouse_modes__.m (@var{fig})\n## Set mouse mode properties of figure to default values.\n##\n## @end deftypefn\n\nfunction __set_default_mouse_modes__ (fig)\n\n  set (fig, \"__pan_mode__\", struct (\"Enable\", \"off\",\n                                    \"Motion\", \"both\",\n                                    \"FigureHandle\", fig),\n            \"__rotate_mode__\", struct (\"Enable\", \"off\",\n                                       \"RotateStyle\", \"box\",\n                                       \"FigureHandle\", fig),\n            \"__zoom_mode__\", struct (\"Enable\", \"off\",\n                                     \"Motion\", \"both\",\n                                     \"Direction\", \"in\",\n                                     \"FigureHandle\", fig));\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/refresh.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} refresh ()\n## @deftypefnx {} {} refresh (@var{h})\n## Refresh a figure, forcing it to be redrawn.\n##\n## When called without an argument the current figure is redrawn.  Otherwise,\n## the figure with graphic handle @var{h} is redrawn.\n## @seealso{drawnow}\n## @end deftypefn\n\nfunction refresh (h)\n\n  if (nargin == 1)\n    if (! isfigure (h))\n      error (\"refresh: H must be a valid figure handle\");\n    endif\n  else\n    h = gcf ();\n  endif\n\n  set (h, \"__modified__\", \"on\");\n  drawnow ();\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/refreshdata.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} refreshdata ()\n## @deftypefnx {} {} refreshdata (@var{h})\n## @deftypefnx {} {} refreshdata (@var{h}, @var{workspace})\n## Evaluate any @samp{datasource} properties of the current figure and update\n## the plot if the corresponding data has changed.\n##\n## If the first argument @var{h} is a list of graphics handles to figure, axes,\n## or graphic objects with a DataSource property, then operate on these objects\n## rather than the current figure returned by @code{gcf}.\n##\n## The optional second argument @var{workspace} can take the following values:\n##\n## @table @asis\n## @item @qcode{\"base\"}\n## Evaluate the datasource properties in the base workspace.  (default).\n##\n## @item @qcode{\"caller\"}\n## Evaluate the datasource properties in the workspace of the function\n## that called @code{refreshdata}.\n## @end table\n##\n## An example of the use of @code{refreshdata} is:\n##\n## @example\n## @group\n## x = 0:0.1:10;\n## y = sin (x);\n## plot (x, y, \"ydatasource\", \"y\");\n## for i = 1 : 100\n##   pause (0.1);\n##   y = sin (x + 0.1*i);\n##   refreshdata ();\n## endfor\n## @end group\n## @end example\n##\n## Programming Note: For performance, specify @var{h} as the actual object(s)\n## to be updated.  If no object is supplied then Octave must search through\n## all graphic objects of the current figure and determine which ones have\n## DataSource properties that are not empty.\n## @end deftypefn\n\nfunction refreshdata (h, workspace)\n\n  if (nargin == 0)\n    h = gcf ();\n    workspace = \"base\";\n  else\n    ## Matlab compatibility requires accepting cell array of handles\n    if (iscell (h))\n      h = [h{:}];\n    endif\n    if (! all (ishghandle (h)))\n      error (\"refreshdata: H must be a list of graphic object handles\");\n    endif\n    if (nargin == 1)\n      workspace = \"base\";\n    else\n      if (! ischar (workspace)\n          || ! any (strcmpi (workspace, {\"base\", \"caller\"})))\n        error ('refreshdata: WORKSPACE must be \"base\" or \"caller\"');\n      endif\n      workspace = lower (workspace);\n    endif\n  endif\n\n  h = findall (h);\n\n  for hg = h(:).'\n    obj = get (hg);\n    flds = fieldnames (obj);\n    ## regexp() is proper way to do searching, but is 3X slower.\n    ## Pretty unlikely that people are going to be adding DataSource\n    ## properties that are not, in fact, DataSources.\n    ## m = regexp (flds, '^.+datasource$');\n    idx = strfind (flds, 'datasource');\n    dsources = flds(! cellfun ('isempty', idx));\n    for i = 1 : numel (dsources)\n      if (isempty (obj.(dsources{i})))\n        continue;  # DataSource field doesn't point to anything\n      endif\n      expr = obj.(dsources{i});       # DataSource field\n      val = evalin (workspace, expr);\n      pdname = dsources{i}(1:end-6);  # property data name without \"Source\"\n      set (hg, pdname, val);\n    endfor\n  endfor\n\nendfunction\n\n\n%!demo\n%! clf;\n%! x = 0:0.1:10;\n%! y = sin (x);\n%! h = plot (x, y, \"ydatasource\", \"y\");\n%! title (\"refreshdata() showing moving sine curve\");\n%! axis manual;\n%! for i = 1 : 100\n%!   pause (0.01);\n%!   y = sin (x + 0.1 * i);\n%!   refreshdata (h, \"caller\");\n%! endfor\n"
  },
  {
    "path": "scripts/plot/util/rotate.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} rotate (@var{h}, @var{direction}, @var{alpha})\n## @deftypefnx {} {} rotate (@dots{}, @var{origin})\n## Rotate the plot object @var{h} through @var{alpha} degrees around the line\n## with direction @var{direction} and origin @var{origin}.\n##\n## The default value of @var{origin} is the center of the axes object that is\n## the parent of @var{h}.\n##\n## If @var{h} is a vector of handles, they must all have the same parent axes\n## object.\n##\n## Graphics objects that may be rotated are lines, surfaces, patches, and\n## images.\n## @end deftypefn\n\nfunction rotate (h, direction, alpha, origin)\n\n  ## Note in doc string about compatibility issues with calculation of\n  ## default origin due to possible differences in the auto-scaling\n  ## algorithm between Octave and Matlab.\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  is_h = ishghandle (h);\n  if (is_h)\n    ax_list = get (h, \"parent\");\n    if (iscell (ax_list))\n      ax_list = cell2mat (ax_list);\n    endif\n    if (ax_list == ax_list(1))\n      ax = ax_list(1);\n    else\n       error (\"rotate: all handles must be children of the same axes object\");\n    endif\n  else\n    error (\"rotate: H must be an array of one or more graphics handles\");\n  endif\n\n  if (! (isnumeric (direction) && numel (direction) == 3))\n    error (\"rotate: invalid DIRECTION\");\n  endif\n\n  if (! (isnumeric (alpha) && isscalar (alpha)))\n    error (\"rotate: invalid rotation angle\");\n  endif\n\n  t = get (h, \"type\");\n\n  is_image = strcmp (t, \"image\");\n  is_line = strcmp (t, \"line\");\n  is_patch = strcmp (t, \"patch\");\n  is_surface = strcmp (t, \"surface\");\n\n  if (! all (is_image | is_line | is_patch | is_surface))\n    error (\"rotate: expecting image, line, patch, or surface objects\");\n  endif\n\n  if (nargin == 4)\n    if (! (isnumeric (origin) && numel (origin) == 3))\n       error (\"rotate: invalid ORIGIN\");\n    endif\n  else\n    ## Should Z limit be considered when computing origin?\n\n    use_zlim = any (is_patch | is_surface);\n\n    if (! use_zlim && any (is_line))\n      idx = find (is_line)';\n      for i = idx\n        if (! isempty (get (h(i), \"zdata\")))\n          use_zlim = true;\n          break;\n        endif\n      endfor\n    endif\n\n    xlim = get (ax, \"xlim\");\n    ylim = get (ax, \"ylim\");\n\n    a = (xlim(1) + xlim(2)) / 2;\n    b = (ylim(1) + ylim(2)) / 2;\n\n    if (use_zlim)\n      zlim = get (ax, \"zlim\");\n      c = (zlim(1) + zlim(2)) / 2;\n    else\n      c = 0;\n    endif\n\n    origin = [a, b, c];\n  endif\n\n  direction /= norm (direction);\n\n  u = direction(1);\n  v = direction(2);\n  w = direction(3);\n\n  a = origin(1);\n  b = origin(2);\n  c = origin(3);\n\n  sa = sind (alpha);\n  ca = cosd (alpha);\n\n  for i = 1:numel (h)\n    x = get (h(i), \"xdata\");\n    y = get (h(i), \"ydata\");\n\n    if (is_image(i))\n      z = zeros (size (x));\n    else\n      z = get (h(i), \"zdata\");\n      if (isempty (z))\n        z = zeros (size (x));\n      elseif (isvector (x) && isvector (y) && ! isvector (z))\n        [x, y] = meshgrid (x, y);\n      endif\n    endif\n\n    if (a == 0 && b == 0 && c == 0)\n      tmp = (u*x + v*y + w*z) * (1 - ca);\n\n      xr = u*tmp + x*ca + (-w*y + v*z)*sa;\n      yr = v*tmp + y*ca + (w*x - u*z)*sa;\n      zr = w*tmp + z*ca + (-v*x + u*y)*sa;\n    else\n      one_m_ca = 1 - ca;\n      tmp = u*x + v*y + w*z;\n\n      xr = ((a*(v^2 + w^2) - u*(b*v + c*w - tmp))*one_m_ca\n            + x*ca + (-c*v + b*w - w*y + v*z)*sa);\n      yr = ((b*(u^2 + w^2) - v*(a*u + c*w - tmp))*one_m_ca\n            + y*ca + (c*u - a*w + w*x - u*z)*sa);\n      zr = ((c*(u^2 + v^2) - w*(a*u + b*v - tmp))*one_m_ca\n            + z*ca + (-b*u + a*v - v*x + u*y)*sa);\n    endif\n\n    set (h(i), \"xdata\", xr, \"ydata\", yr);\n\n    if (! is_image(i))\n      set (h(i), \"zdata\", zr);\n    endif\n  endfor\n\nendfunction\n\n\n## Test input validation\n%!shared h1, h2, o1, o2, o3\n%! h1 = figure (\"visible\", \"off\");\n%! o1 = line ();\n%! h2 = figure (\"visible\", \"off\");\n%! o2 = line ();\n%! o3 = text (0, 0, \"foobar\");\n\n%!error <Invalid call> rotate ()\n%!error <Invalid call> rotate (o1)\n%!error <Invalid call> rotate (o1, [0,0,0])\n%!error <all handles must be children of the same axes object> rotate ([o1, o2], [0,0,0], 90)\n%!error <invalid DIRECTION> rotate (o1, \"foo\", 90)\n%!error <invalid rotation angle> rotate (o1, [0,0,0], \"foo\")\n%!error <invalid ORIGIN> rotate (o1, [0,0,0], 90, \"foo\")\n%!error rotate (o1, [0,0,0], 90, [0,0,0], 1)\n%!error <H must be an array of one or more graphics handles> rotate (NaN, [0,0,0], 90)\n%!error <expecting image, line, patch, or surface objects> rotate (o3, [0,0,0], 90)\n%!test\n%! close (h1);\n%! close (h2);\n"
  },
  {
    "path": "scripts/plot/util/rotate3d.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} rotate3d\n## @deftypefnx {} {} rotate3d on\n## @deftypefnx {} {} rotate3d off\n## @deftypefnx {} {} rotate3d (@var{hfig}, @var{option})\n## Control the interactive 3-D rotation mode of a figure in the GUI.\n##\n## Given the option @qcode{\"on\"} or @qcode{\"off\"}, set the interactive\n## rotate mode on or off.\n##\n## With no arguments, toggle the current rotate mode on or off.\n##\n## If the first argument @var{hfig} is a figure, then operate on the given\n## figure rather than the current figure as returned by @code{gcf}.\n##\n## @seealso{pan, zoom}\n## @end deftypefn\n\nfunction rotate3d (hfig, option)\n\n  ## FIXME: Presumably should implement this for Matlab compatibility.\n  if (nargin == 1 && nargout > 0 && isfigure (hfig))\n    error (\"rotate3d: syntax 'handle = rotate3d (hfig)' not implemented\");\n  endif\n\n  if (nargin == 0)\n    hfig = gcf ();\n  else\n    if (nargin == 1)\n      option = hfig;\n      hfig = gcf ();\n    else\n      if (! isfigure (hfig))\n        error (\"rotate3d: invalid figure handle HFIG\");\n      endif\n    endif\n\n    if (! ischar (option))\n      error (\"rotate3d: OPTION must be a string\");\n    endif\n  endif\n\n  if (nargin == 0)\n    rm = get (hfig, \"__rotate_mode__\");\n    if (strcmp (rm.Enable, \"on\"))\n      rm.Enable = \"off\";\n    else\n      rm.Enable = \"on\";\n    endif\n    set (hfig, \"__rotate_mode__\", rm);\n    update_mouse_mode (hfig, rm.Enable);\n  else\n    switch (option)\n      case {\"on\", \"off\"}\n        rm = get (hfig, \"__rotate_mode__\");\n        rm.Enable = option;\n        rm.Motion = \"both\";\n        set (hfig, \"__rotate_mode__\", rm);\n        update_mouse_mode (hfig, option);\n      otherwise\n        error (\"rotate3d: unrecognized OPTION '%s'\", option);\n    endswitch\n  endif\n\nendfunction\n\nfunction update_mouse_mode (hfig, arg)\n\n  if (strcmp (arg, \"off\"))\n    set (hfig, \"__mouse_mode__\", \"none\");\n  else\n    ## FIXME: Is there a better way other than calling these functions\n    ##        to set the other mouse mode Enable fields to \"off\"?\n    pan (hfig, \"off\");\n    zoom (hfig, \"off\");\n    set (hfig, \"__mouse_mode__\", \"rotate\");\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/saveas.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} saveas (@var{h}, @var{filename})\n## @deftypefnx {} {} saveas (@var{h}, @var{filename}, @var{fmt})\n## Save graphics object @var{h} to the file @var{filename} in graphics format\n## @var{fmt}.\n##\n## If @var{h} is the handle to a figure object, that figure object is saved.\n## If @var{h} is the handle to a different graphics object, the figure\n## containing that graphics object is saved.\n##\n## All device formats accepted by @code{print} may be used.  Common formats\n## are:\n##\n## @table @code\n##\n##   @item ofig\n##     Octave figure file format (default)\n##\n##   @item mfig\n##     Two files: Octave m-file @file{filename.m} containing code\n##     to open Octave figure file @file{filename.ofig}\n##\n##   @item ps\n##     PostScript\n##\n##   @item eps\n##     Encapsulated PostScript\n##\n##   @item pdf\n##     Portable Document Format\n##\n##   @item jpg\n##     JPEG Image\n##\n##   @item png\n##     Portable Network Graphics image\n##\n##   @item emf\n##     Enhanced MetaFile\n##\n##   @item tif\n##     TIFF Image, compressed\n##\n## @end table\n##\n## If @var{fmt} is omitted it is extracted from the extension of\n## @var{filename}.  The default format when there is no extension is\n## @qcode{\"ofig\"}.\n##\n## @example\n## @group\n## clf ();\n## surf (peaks);\n## saveas (1, \"figure1.png\");\n## @end group\n## @end example\n##\n## @seealso{print, savefig, hgsave, orient}\n## @end deftypefn\n\nfunction saveas (h, filename, fmt)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! ishghandle (h))\n    error (\"saveas: H must be a graphics handle\");\n  endif\n  if (! ischar (filename))\n    error (\"saveas: FILENAME must be a string\");\n  endif\n\n  if (isfigure (h))\n    fig = h;\n  else\n    fig = ancestor (h, \"figure\");\n  endif\n\n  default_fmt = \"ofig\";\n\n  if (nargin == 2)\n    ## Attempt to infer format from filename\n    [~, ~, ext] = fileparts (filename);\n    if (isempty (ext))\n      ext = [\".\" default_fmt];\n      filename = [filename ext];\n    endif\n    fmt = ext(2:end);\n  endif\n\n  if (nargin == 3)\n    if (! ischar (fmt))\n      error (\"saveas: FMT must be a string\");\n    elseif (isempty (fmt))\n      fmt = default_fmt;\n    endif\n    [~, ~, ext] = fileparts (filename);\n    if (isempty (ext))\n      ext = [\".\" fmt];\n      filename = [filename ext];\n    endif\n  endif\n\n  fmt = lower (fmt);\n\n  if (any (strcmp (fmt, {\"ofig\", \"fig\"})))\n    savefig (fig, filename);\n  elseif (any (strcmp (fmt, {\"m\", \"mfig\"})))\n    [d, n] = fileparts (filename);\n    mfilename = fullfile (d, [n \".m\"]);\n    figfilename = fullfile (d, [n \".ofig\"]);\n\n    savefig (fig, figfilename);\n\n    fid = fopen (mfilename, \"wt\");\n    if (fid < 0)\n      error (\"saveas: could not open '%s' for writing\", mfilename);\n    endif\n    fprintf (fid, ['h = openfig (\"' figfilename '\");' \"\\n\"]);\n    fclose (fid);\n  else\n    prt_opt = [\"-d\" fmt];\n\n    print (fig, filename, prt_opt);\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> saveas ()\n%!error <Invalid call> saveas (1)\n%!error <H must be a graphics handle> saveas (Inf, \"tst.pdf\")\n%!error <FILENAME must be a string> saveas (0, 1)\n%!error <FMT must be a string> saveas (0, \"tst.pdf\", 1)\n"
  },
  {
    "path": "scripts/plot/util/savefig.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n## your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the filename COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} savefig ()\n## @deftypefnx {} {} savefig (@var{h})\n## @deftypefnx {} {} savefig (@var{filename})\n## @deftypefnx {} {} savefig (@var{h}, @var{filename})\n## @deftypefnx {} {} savefig (@var{h}, @var{filename}, @qcode{\"compact\"})\n## Save figure windows specified by graphics handle(s) @var{h} to file\n## @var{filename}.\n##\n## If unspecified, @var{h} is the current figure returned by @code{gcf}.\n##\n## If unspecified, @var{filename} is set to @file{\"Untitled.fig\"}.  If\n## @var{filename} does not have an extension then the default extension\n## @file{\".fig\"} will be added.\n##\n## If the optional third input @qcode{\"compact\"} is present then the data\n## will be compressed to save more space.\n##\n## @seealso{hgsave, hdl2struct, openfig}\n## @end deftypefn\n\nfunction savefig (varargin)\n\n  if (nargin > 3)\n    print_usage ();\n  endif\n\n  ## Default values for input arguments\n  h = [];\n  filename = \"Untitled.fig\";\n  fmt = \"-binary\";\n\n  ## Check input arguments\n  if (nargin == 1)\n    if (all (isfigure (varargin{1})))\n      h = varargin{1};\n    elseif (ischar (varargin{1}))\n      filename = varargin{1};\n    else\n      error (\"savefig: first argument must be a figure handle or filename\");\n    endif\n  else\n    if (! all (isfigure (varargin{1})))\n      error (\"savefig: H must be a valid figure handle\");\n    endif\n    h = varargin{1};\n    if (! ischar (varargin{2}))\n      error (\"savefig: FILENAME must be a string\");\n    endif\n    filename = varargin{2};\n    if (nargin == 3)\n      if (strcmpi (varargin{3}, \"compact\"))\n        fmt = \"-zip\";\n      else\n        warning (\"savefig: unrecognized option '%s'\", varargin{3});\n      endif\n    endif\n  endif\n\n  ## Check figure handle input\n  if (isempty (h))\n    h = gcf ();\n  endif\n\n  ## Check filename extension\n  [~, ~, ext] = fileparts (filename);\n  if (isempty (ext))\n    filename = [filename \".fig\"];\n  endif\n\n  ## Save handles to file\n  hgsave (h, filename, fmt);\n\nendfunction\n\n\n%!test\n%! unwind_protect\n%!   h = figure (\"visible\", \"off\");\n%!   ftmp = [tempname() \".fig\"];\n%!   savefig (h, ftmp);\n%!   savefig (ftmp);\n%! unwind_protect_cleanup\n%!   close (h);\n%!   unlink (ftmp);\n%! end_unwind_protect\n\n%!testif HAVE_ZLIB\n%! unwind_protect\n%!   h = figure (\"visible\", \"off\");\n%!   ftmp = [tempname() \".fig\"];\n%!   savefig (h, ftmp, \"compact\");\n%! unwind_protect_cleanup\n%!   close (h);\n%!   unlink (ftmp);\n%! end_unwind_protect\n\n## Test input validation\n%!error savefig (1,2,3,4)\n%!error <must be a figure handle or filename> savefig (struct ())\n%!error <H must be a valid figure handle> savefig ([0, -1], \"foobar\")\n%!error <FILENAME must be a string>\n%! unwind_protect\n%!   h = figure (\"visible\", \"off\");\n%!   savefig (h, -1);\n%! unwind_protect_cleanup\n%!   close (h);\n%! end_unwind_protect\n%!warning <unrecognized option 'foobar'>\n%! unwind_protect\n%!   h = figure (\"visible\", \"off\");\n%!   ftmp = [tempname() \".fig\"];\n%!   savefig (h, ftmp, \"foobar\");\n%! unwind_protect_cleanup\n%!   close (h);\n%!   unlink (ftmp);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/shg.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} shg\n## Show the graph window.\n##\n## This function makes the current figure visible, and places it on top of\n## of all other plot windows.\n##\n## Programming Note: @code{shg} is equivalent to @code{figure (gcf)} assuming\n## that a current figure exists.\n## @seealso{figure, drawnow, gcf}\n## @end deftypefn\n\nfunction shg ()\n\n  if (nargin != 0)\n    warning (\"shg: ignoring extra arguments\");\n  endif\n\n  hf = get (0, \"currentfigure\");\n  if (! isempty (hf))\n    set (hf, \"visible\", \"on\");\n    __show_figure__ (hf);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/plot/util/struct2hdl.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} struct2hdl (@var{s})\n## @deftypefnx {} {@var{h} =} struct2hdl (@var{s}, @var{p})\n## @deftypefnx {} {@var{h} =} struct2hdl (@var{s}, @var{p}, @var{hilev})\n## Construct a graphics handle object @var{h} from the structure @var{s}.\n##\n## The structure must contain the fields @qcode{\"handle\"}, @qcode{\"type\"},\n## @qcode{\"children\"}, @qcode{\"properties\"}, and @qcode{\"special\"}.\n##\n## If the handle of an existing figure or axes is specified, @var{p}, the new\n## object will be created as a child of that object.  If no parent handle is\n## provided then a new figure and the necessary children will be constructed\n## using the default values from the root object.\n##\n## A third boolean argument @var{hilev} can be passed to specify whether the\n## function should preserve listeners/callbacks, e.g., for legends or\n## hggroups.  The default is false.\n## @seealso{hdl2struct, hgload, findobj}\n## @end deftypefn\n\nfunction [h, pout] = struct2hdl (s, p=[], hilev = false)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  fields = {\"handle\", \"type\", \"children\", \"properties\", \"special\"};\n  partypes = {\"root\", \"figure\", \"axes\", \"hggroup\"};\n  othertypes = {\"line\", \"patch\", \"scatter\", \"surface\", \"image\", \"text\"};\n  alltypes = [partypes othertypes];\n\n  if (! isstruct (s))\n    print_usage ();\n  elseif (! all (isfield (s, fields)))\n    print_usage ();\n  elseif (isscalar (p))\n    if (! ishghandle (p))\n      error (\"struct2hdl: P is not a handle to a graphic object\");\n    endif\n    if (any (strcmp (get (p).type, partypes)))\n      paridx = find (strcmp (get (p).type, alltypes));\n      kididx = find (strcmp (s.type, alltypes));\n      if (kididx <= paridx)\n        error (\"struct2hdl: incompatible input handles\");\n      endif\n    else\n      error (\"struct2hdl: %s object can't be parent object\", get (p).type);\n    endif\n    hpar = p;\n    p = [NaN; hpar];\n    ## create appropriate parent if needed\n    if (any (strcmp (s.type, othertypes)))\n      for ii = (paridx+1) : (numel (partypes)-1)\n        eval ([\"hpar = \" partypes{ii} '(\"parent\", hpar);']);\n        p = [p [NaN; hpar]];\n      endfor\n    elseif (any (strcmp (s.type, {\"hggroup\", \"axes\"})))\n      for ii = (paridx+1) : (kididx-1)\n        eval ([\"hpar = \" partypes{ii} '(\"parent\", hpar);']);\n        p = [p [NaN; hpar]];\n      endfor\n    else\n      par = NaN;\n    endif\n  elseif (isempty (p))\n    if (any (strcmp (s.type, othertypes)))\n      par = axes ();\n    elseif (any (strcmp (s.type, {\"hggroup\", \"axes\"})))\n      par = figure ();\n    else\n      par = NaN;\n    endif\n    p = [NaN; par];\n  endif\n  ## read parent (last column) in p and remove it if duplicate\n  par = p(2,end);\n  tst = find (p(2,:) == par);\n  if (numel (tst) > 1)\n    p = p(1:2, 1:(tst(end)-1));\n  endif\n\n  ## Use lowercase for all properties\n  s.properties = cell2struct (struct2cell (s.properties), ...\n                              lower (fieldnames (s.properties)));\n\n  ## Place the \"*mode\" properties at the end to avoid having the updaters\n  ## change the mode to \"manual\" when the value is \"auto\".\n  names = fieldnames (s.properties);\n  n = strncmp (cellfun ('fliplr', names, \"uniformoutput\", false), \"edom\", 4);\n  n = (n | strcmp (names, \"positionconstraint\"));\n  names = [names(! n); names(n)];\n  n_pos = find (strcmp (names, \"position\") | strcmp (names, \"outerposition\"));\n  if (strcmp (s.type, \"axes\") && numel (n_pos) == 2)\n    if (isfield (s.properties, \"positionconstraint\"))\n      positionconstraint = s.properties.positionconstraint;\n    else\n      ## loading old figure file before \"positionconstraint\" property was added\n      positionconstraint = s.properties.activepositionproperty;\n    endif\n    if (strcmp (positionconstraint, \"outerposition\"))\n      names{n_pos(1)} = \"position\";\n      names{n_pos(2)} = \"outerposition\";\n    else\n      names{n_pos(1)} = \"outerposition\";\n      names{n_pos(2)} = \"position\";\n    endif\n  endif\n  ## Set \"units\" property early\n  n = strcmp (names, \"units\");\n  names = [names(n); names(! n)];\n  ## Reorder the properties\n  s.properties = orderfields (s.properties, names);\n\n  ## Silence deprecation warnings\n  warning (\"off\", \"Octave:deprecated-property\", \"local\");\n\n  ## Translate field names for Matlab .fig files\n  ## FIXME: Is it ok to do this unconditionally?\n  if (isfield (s.properties, \"applicationdata\"))\n    s.properties.__appdata__ = s.properties.applicationdata;\n    s.properties = rmfield (s.properties, \"applicationdata\");\n  endif\n\n  ## Create object\n  if (strcmp (s.type, \"root\"))\n    h = 0;\n    s.properties = rmfield (s.properties, ...\n                              {\"callbackobject\", \"commandwindowsize\", ...\n                               \"monitorpositions\", \"pointerwindow\", ...\n                               \"screendepth\", \"screenpixelsperinch\", ...\n                               \"screensize\"});\n  elseif (strcmp (s.type, \"figure\"))\n    [h, s] = createfigure (s);\n  elseif (strcmp (s.type, \"axes\"))\n    ## legends and colorbars are \"transformed\" in to normal axes\n    ## if hilev is not requested.\n    if (! hilev && isfield (s.properties, \"tag\"))\n      if (strcmp (s.properties.tag, \"legend\"))\n        s.properties.tag = \"\";\n        s.properties.userdata = [];\n        par = gcf ();\n      elseif (strcmp (s.properties.tag, \"colorbar\"))\n        s.properties.tag = \"\";\n        s.properties.userdata = [];\n        par = gcf ();\n      endif\n    endif\n    ## remove read only properties\n    ## FIXME: Remove \"interactions\", \"layout\", \"legend\", \"toolbar\", \"xaxis\",\n    ## \"yaxis\", and \"zaxis\" from this list once they are implemented.\n    ro_props = {\"interactions\", \"layout\", \"legend\", \"nextseriesindex\", ...\n                \"tightinset\", \"toolbar\", \"xaxis\", \"yaxis\", \"zaxis\"};\n    has_ro_props = cellfun (@(x) isfield (s.properties, x), ro_props);\n    if (any (has_ro_props))\n      s.properties = rmfield (s.properties, ro_props(has_ro_props));\n    endif\n    [h, s] = createaxes (s, p, par);\n  elseif (strcmp (s.type, \"line\"))\n    h = createline (s, par);\n  elseif (strcmp (s.type, \"patch\"))\n    [h, s] = createpatch (s, par);\n  elseif (strcmp (s.type, \"scatter\"))\n    [h, s] = createscatter (s, par);\n  elseif (strcmp (s.type, \"text\"))\n    if (isfield (s.properties, \"extent\"))\n      s.properties = rmfield (s.properties, \"extent\");\n    endif\n    h = createtext (s, par);\n  elseif (strcmp (s.type, \"image\"))\n    h = createimage (s, par);\n  elseif (strcmp (s.type, \"surface\"))\n    h = createsurface (s, par);\n  elseif (strcmp (s.type, \"light\"))\n    h = createlight (s, par);\n  elseif (strcmp (s.type, \"hggroup\"))\n    [h, s, p] = createhg (s, p, par, hilev);\n  elseif (any (strcmp (s.type, {\"uimenu\", \"uicontextmenu\",...\n                                \"uicontrol\", \"uipanel\", \"uibuttongroup\",...\n                                \"uitoolbar\", \"uipushtool\", \"uitoggletool\"...\n                                \"uitable\"})))\n    if (isfield (s.properties, \"extent\"))\n      s.properties = rmfield (s.properties, \"extent\");\n    endif\n    [h, s] = createui (s, par);\n    if (strcmp (s.type, \"uicontextmenu\"))\n      set (p(2, ismember (p(1,:), s.special)), 'UIContextMenu', h);\n    endif\n  else\n    error (\"struct2hdl: %s objects are not implemented yet\", s.type);\n  endif\n\n  ## children\n  p = [p [s.handle; h]];  # [original; new]\n  kids = s.children;\n  nkids = length (kids);\n  ii = 0;\n  while (nkids)\n    ii += 1;\n    if (! any (ii == s.special))\n      [h2, p] = struct2hdl (s.children(ii), [p [s.handle; h]], hilev);\n    endif\n    nkids -= 1;\n  endwhile\n\n  ## paste properties\n  setprops (s, h, p, hilev);\n\n  pout = p;\n\nendfunction\n\nfunction [h, sout] = createfigure (s)\n\n  ## Create figure initially invisible to speed up loading.\n  opts = {\"visible\", \"off\"};\n  if (isfield (s.properties, \"integerhandle\"))  # see also bug #53342.\n    opts = [opts {\"integerhandle\", s.properties.integerhandle}];\n    s.properties = rmfield (s.properties, \"integerhandle\");\n  endif\n  h = figure (opts{:});\n  rmprops = {\"currentaxes\", \"currentcharacter\", \"currentobject\", ...\n             \"currentpoint\", \"number\"};\n  rmprops (! isfield (s.properties, rmprops)) = [];\n  s.properties = rmfield (s.properties, rmprops);\n  if (! isfield (s.properties, \"visible\"))\n    s.properties.visible = \"on\";\n  endif\n  addmissingprops (h, s.properties);\n  sout = s;\n\nendfunction\n\nfunction [h, sout] = createaxes (s, p, par)\n\n  if (! isfield (s.properties, \"tag\")\n      || ! any (strcmpi (s.properties.tag, {\"colorbar\", \"legend\"})))\n    ## regular axes\n    propval = {\"position\", s.properties.position};\n    hid = {\"__autopos_tag__\", \"looseinset\"};\n    for ii = 1:numel (hid)\n      prop = hid{ii};\n      if (isfield (s.properties, prop))\n        val = s.properties.(prop);\n        propval = [propval, prop, val];\n      endif\n    endfor\n    ## set hold \"on\" until all axes children have been added\n    h = axes (propval{:}, \"parent\", par, \"nextplot\", \"add\");\n\n    if (isfield (s.properties, \"__plotyy_axes__\"))\n      plty = s.properties.__plotyy_axes__;\n      addproperty (\"__plotyy_axes__\", h, \"data\");\n      tmp = [p [s.handle; h]];\n      tst = ismember (tmp(1,:), plty);\n      if (sum (tst) == numel (plty))\n        for ii = 1:numel (plty)\n          plty(ii) = tmp(2, find (tmp(1,:) == plty(ii)));\n        endfor\n        for ii = 1:numel (plty)\n          set (plty(ii), \"__plotyy_axes__\", plty);\n        endfor\n      endif\n      s.properties = rmfield (s.properties, \"__plotyy_axes__\");\n    endif\n\n    ## delete non-default and already set properties\n    fields = fieldnames (s.properties);\n    tst = cellfun (@(x) isprop (h, x), fields);\n    s.properties = rmfield (s.properties, fields(find (tst == 0)));\n\n  elseif (strcmp (s.properties.tag, \"legend\"))\n    ## legends\n    oldax = s.properties.userdata.handle;\n    idx = find (p == oldax);\n    newax = p(idx+1);\n    strings = {};\n    kids = s.children;\n    kids(s.special) = [];\n    oldh = unique (arrayfun (@(x) x.properties.userdata(end), kids));\n    for ii = 1:length (oldh)\n      idx = find (p(1:2:end) == oldh(ii)) * 2;\n      if (! isempty (idx))\n        newh(ii) = p(idx);\n        if (! strcmp (get (newh(ii), \"type\"), \"hggroup\"))\n          str = get (newh(ii), \"displayname\");\n          strings = [strings str];\n        else\n          str = get (get (newh(ii), \"children\")(1), \"displayname\");\n          strings = [strings str];\n        endif\n      else\n        error (\"struct2hdl: didn't find a legend item\");\n      endif\n    endfor\n    location = s.properties.location;\n    orientation = s.properties.orientation;\n    textpos = s.properties.textposition;\n    box = s.properties.box;\n\n    h = legend (newax, newh, strings, \"location\", location, ...\n                \"orientation\", orientation);\n    set (h, \"textposition\", textpos); # bug makes \"textposition\"\n                                      # redefine the legend\n    h = legend (newax, newh, strings, \"location\", location, ...\n                \"orientation\", orientation);\n    ## box\n    if (strcmp (box, \"on\"))\n      legend (\"boxon\");\n    endif\n\n    ## visibility\n    tst = arrayfun (@(x) strcmp (x.properties.visible, \"on\"), kids);\n    if (! any (tst))\n      legend (\"hide\");\n    endif\n\n    ## remove all properties such as \"textposition\" that redefine\n    ## the entire legend.  Also remove chidren.\n    s.properties = rmfield (s.properties, ...\n                              {\"__appdata__\", \"xlabel\",...\n                               \"ylabel\", \"zlabel\", \"location\", ...\n                               \"title\", \"string\",\"orientation\", ...\n                               \"visible\", \"textposition\"});\n\n    s.children = [];\n\n  elseif (strcmp (s.properties.tag, \"colorbar\"))\n    ## colorbar\n    oldax = s.properties.axes;\n    if (! isempty (idx = find (oldax == p)))\n      ax = p(idx+1);\n      location = s.properties.location;\n      h = colorbar (\"peer\", ax, location);\n      s.properties = rmfield (s.properties, ...\n                                {\"__appdata__\", \"xlabel\" ...\n                                 \"ylabel\", \"zlabel\", ...\n                                 \"title\", \"axes\"});\n      s.children= [];\n    else\n      error (\"hdl2struct: didn't find an object\");\n    endif\n  endif\n\n  sout = s;\n\nendfunction\n\nfunction h = createline (s, par)\n  h = line (\"parent\", par);\n  addmissingprops (h, s.properties);\nendfunction\n\nfunction [h, sout] = createpatch (s, par)\n\n  prp.faces = s.properties.faces;\n  prp.vertices = s.properties.vertices;\n  prp.facevertexcdata = s.properties.facevertexcdata;\n  h = patch (prp);\n  set (h, \"parent\", par);\n  s.properties = rmfield (s.properties,\n                          {\"faces\", \"vertices\", \"facevertexcdata\"});\n  ## Also remove derived properties.  Otherwise there is a possibility for\n  ## a segfault when 'set (h, properties)' is used to restore properties\n  ## which do not match in size the ones created with from the call to patch().\n  s.properties = rmfield (s.properties, {\"xdata\", \"ydata\", \"zdata\", \"cdata\"});\n  addmissingprops (h, s.properties);\n  sout = s;\n\nendfunction\n\nfunction [h, sout] = createscatter (s, par)\n\n  if (isempty (s.properties.zdata))\n    ## 2-D scatter\n    h = scatter (s.properties.xdata, s.properties.ydata, \"parent\", par);\n  else\n    ## 3-D scatter\n    h = scatter3 (s.properties.xdata, s.properties.ydata, s.properties.zdata, \"parent\", par);\n  endif\n\n  s.properties = rmfield (s.properties,\n                          {\"xdata\", \"ydata\", \"zdata\"});\n  addmissingprops (h, s.properties);\n  sout = s;\n\nendfunction\n\nfunction h = createtext (s, par)\n  h = text (\"parent\", par);\n  addmissingprops (h, s.properties);\nendfunction\n\nfunction h = createimage (s, par)\n  h = image (1, \"parent\", par);\n  addmissingprops (h, s.properties);\nendfunction\n\nfunction h = createsurface (s, par)\n  h = surface (\"parent\", par);\n  addmissingprops (h, s.properties);\nendfunction\n\nfunction h = createlight (s, par)\n  h = light (\"parent\", par);\n  addmissingprops (h, s.properties);\nendfunction\n\nfunction [h, s] = createui (s, par)\n  if (isfield (s.properties, \"style\") && strcmp (s.properties.style, \"frame\"))\n    s.type = \"uipanel\";  # frame is deprecated: use uipanel instead\n  endif\n  h = feval (s.type, \"parent\", par);\n  addmissingprops (h, s.properties);\nendfunction\n\nfunction [h, sout, pout] = createhg (s, p, par, hilev)\n\n  ## Here we infer from properties the type of hggroup we should build\n  ## and call the corresponding high level functions.\n  ## We manually set \"hold on\" to avoid next hggroup be deleted\n  ## the proper value of axes \"nextplot\" will finally be recovered.\n\n  hold on;\n  if (hilev)\n    [h, s, p] = createhg_hilev (s, p, par);\n    if (numel (s.children) != numel (get (h).children))\n      warning ([\"struct2hdl: could not infer the hggroup type.  \", ...\n                \"Will build objects but listener/callback functions \", ...\n                \"will be lost\"]);\n      if (isfield (h, \"bargroup\"))\n        delete (get (h).bargroup);\n      else\n        delete (h);\n      endif\n      h = hggroup (\"parent\", par);\n      addmissingprops (h, s.properties);\n      s.special = [];\n    else\n      oldkids = s.children;\n      newkids = get (h).children;\n      nkids = numel (oldkids);\n      ii = 1;\n      while (nkids)\n        p = [p [oldkids(ii++).handle; newkids(nkids--)]];\n      endwhile\n    endif\n  else\n    h = hggroup (\"parent\", par);\n    addmissingprops (h, s.properties);\n    s.special = [];\n  endif\n\n  ## Check for polar plots with special \"polar_grid\" object\n  ## FIXME: A hack to fix bug #62093.\n  if (strcmp (s.properties.tag, \"polar_grid\"))\n    s.properties.handlevisibility = \"off\";\n  endif\n\n  sout = s;\n  pout = p;\n\nendfunction\n\nfunction [h, sout, pout] = createhg_hilev (s, p, par)\n\n  fields = s.properties;\n  if (isfield (fields, \"contourmatrix\"))\n    ## contours\n    xdata = s.properties.xdata;\n    ydata = s.properties.ydata;\n    zdata = s.properties.zdata;\n    levellist = s.properties.levellist;\n    textlist = s.properties.textlist;\n\n    ## contour creation\n    if (isempty (s.children(1).properties.zdata))\n      if (strcmpi (s.properties.fill, \"on\"))\n        [cm2, h] = contourf (xdata, ydata, zdata, levellist);\n      else\n        [cm2, h] = contour (xdata, ydata, zdata, levellist);\n      endif\n\n      ## labels\n      if (strcmpi (s.properties.showtext, \"on\"))\n        clabel (cm2, h, textlist);\n      endif\n    else\n      [cm2, h] = contour3 (xdata, ydata, zdata, levellist);\n    endif\n\n    ## delete already set properties and children\n    s.properties = rmfield (s.properties, ...\n                              {\"xdata\", \"ydata\", \"zdata\", ...\n                               \"contourmatrix\", \"levellist\", ...\n                               \"fill\", \"labelspacing\", ...\n                               \"levellistmode\", \"levelstep\", ...\n                               \"levelstepmode\", \"textlist\"...\n                               \"textlistmode\" , \"textstep\", ...\n                               \"textstepmode\", \"zlevel\", ...\n                               \"zlevelmode\"});\n\n  elseif (isfield (fields, \"udata\") && isfield (fields, \"vdata\"))\n    ## quiver\n    xdata = s.properties.xdata;\n    ydata = s.properties.ydata;\n\n    udata = s.properties.udata;\n    vdata = s.properties.vdata;\n\n    h = quiver (xdata, ydata, udata, vdata);\n\n    ## delete already set properties and children\n    s.properties = rmfield (s.properties, ...\n                              {\"xdata\", \"ydata\", \"zdata\", ...\n                               \"xdatasource\", \"ydatasource\", \"zdatasource\", ...\n                               \"udata\", \"vdata\", \"wdata\", ...\n                               \"udatasource\", \"vdatasource\", \"wdatasource\"});\n\n  elseif (isfield (fields, \"format\"))\n    ## errorbar\n    form = s.properties.format;\n    xdata = s.properties.xdata;\n    ydata = s.properties.ydata;\n    xldata = s.properties.xldata;\n    ldata = s.properties.ldata;\n    xudata = s.properties.xudata;\n    udata = s.properties.udata;\n\n    switch (form)\n      case \"xerr\"\n        h = errorbar (xdata, ydata, xldata, xudata, \">\");\n      case \"yerr\"\n        h = errorbar (xdata, ydata, ldata, udata, \"~\");\n      case \"xyerr\"\n        h = errorbar (xdata, ydata, xldata, xudata, ldata, udata, \"~>\");\n      case \"box\"\n        h = errorbar (xdata, ydata, xldata, xudata, \"#\");\n      case \"boxy\"\n        h = errorbar (xdata, ydata, ldata, udata, \"#~\");\n      case \"boxxy\"\n        h = errorbar (xdata, ydata, xldata, xudata, ldata, udata, \"#~>\");\n      otherwise\n        error (\"struct2hdl: couldn't guess the errorbar format\");\n    endswitch\n    ## delete already set properties\n    s.properties = rmfield (s.properties, ...\n                              {\"xdata\", \"ydata\", ...\n                               \"xldata\", \"ldata\", ...\n                               \"xudata\", \"udata\", ...\n                               \"xldatasource\", \"ldatasource\", ...\n                               \"xudatasource\", \"udatasource\", ...\n                               \"format\"});\n\n  elseif (isfield (fields, \"bargroup\"))\n    ## bar plot\n    ## FIXME: Here we don't have access to brothers so we first create all\n    ## the barseries of the bargroup (but the last), then retrieve information,\n    ## and rebuild the whole bargroup.\n    ## The duplicate are deleted after calling \"setprops\"\n\n    bargroup = s.properties.bargroup;\n    oldh = s.handle;\n\n    temp = ismember ([p(1:2:end) oldh], bargroup);\n\n    tst = sum (temp) == length (bargroup);\n\n    if (isscalar (bargroup) || ! tst)\n      xdata = s.properties.xdata;\n      ydata = s.properties.ydata;\n\n      h = bar (xdata, ydata);\n\n      ## delete already set properties,\n      s.properties = rmfield (s.properties, ...\n                                {\"xdata\", \"ydata\", ...\n                                 \"xdatasource\", \"ydatasource\", ...\n                                 \"bargroup\", ...\n                                 \"barwidth\", \"baseline\"});\n    else\n      xdata = [];\n      ydata = [];\n\n      ## Build x/y matrix\n      nbar = length (bargroup);\n      tmp = struct (\"handle\", NaN, \"type\", \"\", \"children\", [], \"special\", []);\n      for ii = 1:(nbar - 1)\n        idx = find (p(1:2:end) == bargroup(ii)) * 2;\n        hdl = p(idx);\n        xdata = [xdata get(hdl).xdata];\n        ydata = [ydata get(hdl).ydata];\n        tmp.children(ii) = hdl2struct (hdl);\n      endfor\n\n      xdata = [xdata s.properties.xdata];\n      ydata = [ydata s.properties.ydata];\n      width = s.properties.barwidth;\n      h = bar (ydata, width);\n\n      ## replace previous handles in \"match\", copy props and delete redundant\n      for ii = 1:(nbar - 1)\n        props = tmp.children(ii).properties;\n        bl = props.baseline;\n        tmp.children(ii).properties = rmfield (props, {\"baseline\", \"bargroup\"});\n        setprops (tmp.children(ii), h(ii), p, 1);\n        delete (tmp.children(ii).handle);\n        delete (bl);\n        idxpar = find (p == tmp.children(ii).handle);\n        p(idxpar) = h(ii);\n        idxkid = idxpar - 2;\n        p(idxkid) = get (h(ii), \"children\");\n      endfor\n      p(2,((end-nbar+2):end)) = h(1:(end-1));\n      h = h(end);\n\n      ## delete already set properties ,\n      s.properties = rmfield (s.properties, ...\n                                {\"xdata\", \"ydata\", \"bargroup\"...\n                                 \"barwidth\", \"baseline\"});\n    endif\n  elseif (isfield (fields, \"baseline\"))\n    ## stem plot\n    xdata = s.properties.xdata;\n    ydata = s.properties.ydata;\n\n    h = stem (xdata, ydata);\n\n    ## delete already set properties,\n    s.properties = rmfield (s.properties, ...\n                              {\"xdata\", \"ydata\", ...\n                               \"xdatasource\", \"ydatasource\", ...\n                               \"baseline\"});\n  elseif (isfield (fields, \"basevalue\"))\n    ## area plot\n    xdata = s.properties.xdata;\n    ydata = s.properties.ydata;\n    level = s.properties.basevalue;\n\n    h = area (xdata, ydata, level);\n\n    ## delete already set properties,\n    s.properties = rmfield (s.properties, ...\n                              {\"xdata\", \"ydata\", ...\n                               \"xdatasource\", \"ydatasource\"});\n  else\n    warning (\"struct2hdl: could not infer the hggroup type.  Will build objects but listener/callback functions will be lost\");\n    h = hggroup (\"parent\", par);\n    addmissingprops (h, s.properties);\n    s.special = [];           # children will be treated as normal children\n  endif\n\n  sout = s;\n  pout = p;\n\nendfunction\n\nfunction setprops (s, h, p, hilev)\n\n  isspecial = (isfield (s.properties, \"tag\")\n               && any (strcmpi (s.properties.tag, {\"colorbar\", \"legend\"})));\n  if (! isspecial)\n    try\n      specs = s.children(s.special);\n    catch\n      specs = [];\n    end_try_catch\n    if (isempty (specs))\n      hdls = [];\n    else\n      hdls = [specs.handle];\n    endif\n    nh = length (hdls);\n    msg = \"\";\n    if (! nh)\n      set (h, s.properties);\n    else\n      ## Specials are objects that where automatically constructed with\n      ## current object.  Among them are \"x(yz)labels\", \"title\", and\n      ## high level hggroup children\n      fields = fieldnames (s.properties);\n      vals = struct2cell (s.properties);\n      idx = find (cellfun (@(x) valcomp(x, hdls) , vals));\n      s.properties = rmfield (s.properties, fields(idx));\n\n      ## set all properties but special handles\n      set (h, s.properties);\n\n      ## find props with val == (one of special handles)\n      nf = length (idx);\n      fields = fields(idx);\n      vals = vals(idx);\n      while (nf)\n        field = fields{nf};\n        idx = find (hdls == vals{nf});\n        spec = specs(idx);\n        ## FIXME: Wouldn't it be better to call struct2hdl recursively\n        ##        for this handle?  That way the function could determine\n        ##        based on type what special actions to take.\n        try\n          spec.properties = rmfield (spec.properties, \"extent\");\n        end_try_catch\n        if (isprop (h, field))\n          h2 = get (h, field);\n          addmissingprops (h2, spec.properties);\n          set (h2, spec.properties);\n        endif\n        nf -= 1;\n      endwhile\n\n      ## If hggroup children were created by high level functions,\n      ## copy only useful properties.\n      if (hilev)\n        if (strcmp (s.type, \"hggroup\"))\n          nold = numel (s.children);\n          nnew = numel (get (h).children);\n\n          if (nold == nnew)\n            hnew = get (h).children;\n            ii = 1;\n            while (ii <= nnew)\n              try\n                set (hnew (ii), \"displayname\", ...\n                     s.children(ii).properties.displayname);\n              catch\n                sprintf (\"struct2hdl: couldn't set hggroup children #%d props.\", ii);\n              end_try_catch\n              ii += 1;\n            endwhile\n\n          else\n            error (\"struct2hdl: non-conformant number of children in hgggroup\");\n          endif\n        endif\n      endif\n    endif\n\n  else\n    set (h, s.properties);\n  endif\n\nendfunction\n\nfunction out = valcomp (x, hdls)\n\n  if (isfloat (x) && isscalar (x))\n    out = any (x == hdls);\n  else\n    out = false;\n  endif\n\nendfunction\n\nfunction addmissingprops (h, props)\n\n  hid = {\"__autopos_tag__\", \"looseinset\"};\n  oldfields = fieldnames (props);\n  for ii = 1:numel (oldfields)\n    prop = oldfields{ii};\n    if (! isprop (h, prop) && ! any (strcmp (prop, hid)))\n      addproperty (prop, h, \"any\");\n    endif\n  endfor\n\nendfunction\n\n\n## Check that all axes children are restored\n%!test <*66221>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (hf);\n%!   hold (hax, \"on\");\n%!   imagesc (hax, randn (5, 3));\n%!   scatter (hax, 1:3, rand (3, 1));\n%!   hold (hax, \"off\");\n%!   n_children = numel (get (hax, \"children\"));\n%!   tmp_ofig = [tempname(), \".ofig\"];\n%!   s = hdl2struct (hf);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n%! hf_new = struct2hdl (s);\n%! unwind_protect\n%!   hax_new = findobj (hf_new, \"type\", \"axes\");\n%!   assert (numel (get (hax_new, \"children\")), n_children);\n%! unwind_protect_cleanup\n%!   close (hf_new);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/subplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} subplot (@var{rows}, @var{cols}, @var{index})\n## @deftypefnx {} {} subplot (@var{rows}, @var{cols}, @var{index}, @var{hax})\n## @deftypefnx {} {} subplot (@var{rcn})\n## @deftypefnx {} {} subplot (@var{hax})\n## @deftypefnx {} {} subplot (@dots{}, \"align\")\n## @deftypefnx {} {} subplot (@dots{}, \"replace\")\n## @deftypefnx {} {} subplot (\"position\", @var{pos})\n## @deftypefnx {} {} subplot (@dots{}, @var{prop}, @var{val}, @dots{})\n## @deftypefnx {} {@var{hax} =} subplot (@dots{})\n## Set up a plot grid with @var{rows} by @var{cols} subwindows and set the\n## current axes for plotting (@code{gca}) to the location given by @var{index}.\n##\n## If an axes handle @var{hax} is provided after the (@var{rows}, @var{cols},\n## @var{index}) arguments, the corresponding axes is turned into a\n## subplot.\n##\n## If only one numeric argument is supplied, then it must be a three digit\n## value specifying the number of rows in digit 1, the number of columns in\n## digit 2, and the plot index in digit 3.\n##\n## The plot index runs row-wise; First, all columns in a row are numbered\n## and then the next row is filled.\n##\n## For example, a plot with 2x3 grid will have plot indices running as follows:\n## @tex\n## \\vskip 10pt\n## \\hfil\\vbox{\\offinterlineskip\\hrule\n## \\halign{\\vrule#&&\\qquad\\hfil#\\hfil\\qquad\\vrule\\cr\n## height13pt&1&2&3\\cr height12pt&&&\\cr\\noalign{\\hrule}\n## height13pt&4&5&6\\cr height12pt&&&\\cr\\noalign{\\hrule}}}\n## \\hfil\n## \\vskip 10pt\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## +-----+-----+-----+\n## |  1  |  2  |  3  |\n## +-----+-----+-----+\n## |  4  |  5  |  6  |\n## +-----+-----+-----+\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @var{index} may also be a vector.  In this case, the new axes will enclose\n## the grid locations specified.  The first demo illustrates this:\n##\n## @example\n## demo (\"subplot\", 1)\n## @end example\n##\n## The index of the subplot to make active may also be specified by its axes\n## handle, @var{hax}, returned from a previous @code{subplot} command.\n##\n## If the option @qcode{\"align\"} is given then the plot boxes of the subwindows\n## will align, but this may leave no room for axes tick marks or labels.\n##\n## If the option @qcode{\"replace\"} is given then the subplot axes will be\n## reset, rather than just switching the current axes for plotting to the\n## requested subplot.\n##\n## The @qcode{\"position\"} property can be used to exactly position the subplot\n## axes within the current figure.  The option @var{pos} is a 4-element vector\n## [x, y, width, height] that determines the location and size of the axes.\n## The values in @var{pos} are normalized in the range [0,1].\n##\n## Any property/value pairs are passed directly to the underlying axes object.\n## The full list of properties is documented at @ref{Axes Properties}.\n##\n## Any previously existing axes that would be (partly) covered by the newly\n## created axes are deleted.\n##\n## If the output @var{hax} is requested, subplot returns the axes handle for\n## the subplot.  This is useful for modifying the properties of a subplot\n## using @code{set}.\n##\n## Under some circumstances, @code{subplot} might not be able to identify axes\n## that it could re-use and might replace them.  If @code{subplot} axes\n## should be referenced repeatedly, consider creating and storing their axes\n## handles beforehand instead of calling @code{subplot} repeatedly for the same\n## position.\n##\n## Example:\n##\n## @example\n## @group\n## x = 1:10;\n## y = rand (16, 10);\n## for i_plot = 1:4\n##   hax(i_plot) = subplot (2, 2, i_plot);\n##   hold (hax(i_plot), \"on\");\n##   grid (hax(i_plot), \"on\");\n## endfor\n## for i_loop = 1:2\n##   for i_plot = 1:4\n##     iy = (i_loop - 1)*4 + i_plot;\n##     plotyy (hax(i_plot), x,y(iy,:), x,y(iy+1,:));\n##   endfor\n##  endfor\n## @end group\n## @end example\n##\n## @seealso{axes, plot, gca, set}\n## @end deftypefn\n\nfunction hax = subplot (varargin)\n\n  align_axes = false;\n  replace_axes = false;\n  have_position = false;\n  initial_args_decoded = false;\n  make_subplot = false;\n  hsubplot = [];\n\n  if (nargin >= 3)\n    ## R, C, N?\n    arg1 = varargin{1};\n    arg2 = varargin{2};\n    arg3 = varargin{3};\n    if (   isnumeric (arg1) && isscalar (arg1)\n        && isnumeric (arg2) && isscalar (arg2)\n        && isnumeric (arg3))\n      rows = arg1;\n      cols = arg2;\n      index = arg3;\n      if (nargin > 3 && isaxes (varargin{4}))\n        make_subplot = true;\n        hsubplot = varargin{4};\n        varargin(1:4) = [];\n      else\n        varargin(1:3) = [];\n      endif\n      initial_args_decoded = true;\n    endif\n  endif\n\n  if (! initial_args_decoded && nargin > 1)\n    ## check for \"position\", pos, ...\n    if (strcmpi (varargin{1}, \"position\"))\n      arg = varargin{2};\n      if (isnumeric (arg) && numel (arg) == 4)\n        pos = arg;\n        varargin(1:2) = [];\n        have_position = true;\n        initial_args_decoded = true;\n      else\n        error (\"subplot: POSITION must be a 4-element numeric array\");\n      endif\n    endif\n  endif\n\n  if (! initial_args_decoded && nargin > 0)\n    arg = varargin{1};\n    if (nargin == 1 && isaxes (arg))\n      ## Axes handle\n      axes (arg);\n      cf = get (0, \"currentfigure\");\n      set (cf, \"nextplot\", \"add\");\n      return;\n    elseif (isscalar (arg) && arg >= 0)\n      ## RCN?\n      index = rem (arg, 10);\n      arg = (arg - index) / 10;\n      cols = rem (arg, 10);\n      arg = (arg - cols) / 10;\n      rows = rem (arg, 10);\n      varargin(1) = [];\n      initial_args_decoded = true;\n    else\n      error (\"subplot: invalid axes handle or RCN argument\");\n    endif\n  endif\n\n  if (! initial_args_decoded)\n    print_usage ();\n  endif\n\n  if (! have_position)\n    cols = round (cols);\n    rows = round (rows);\n    index = round (index);\n\n    if (any (index < 1) || any (index > rows*cols))\n      error (\"subplot: INDEX value must be >= 1 and <= ROWS*COLS\");\n    endif\n\n    if (rows < 1 || cols < 1 || index < 1)\n      error (\"subplot: ROWS, COLS, and INDEX must be positive\");\n    endif\n  endif\n\n  ## Process \"align\" and \"replace\" options\n  idx = strcmpi (varargin, \"align\");\n  if (any (idx))\n    align_axes = true;\n    varargin(idx) = [];\n  endif\n\n  idx = strcmpi (varargin, \"replace\");\n  if (any (idx))\n    replace_axes = true;\n    varargin(idx) = [];\n  endif\n\n  axesunits = get (0, \"defaultaxesunits\");\n  cf = gcf ();\n  figureunits = get (cf, \"units\");\n  unwind_protect\n    set (0, \"defaultaxesunits\", \"normalized\");\n    set (cf, \"units\", \"pixels\");\n\n    ## FIXME: At the moment we force gnuplot to use the aligned mode\n    ##        which will set \"positionconstraint\" to \"innerposition\".\n    ##        This can yield to text overlap between labels and titles.\n    ##        See bug #31610.\n    if (strcmp (get (cf, \"__graphics_toolkit__\"), \"gnuplot\"))\n      align_axes = true;\n    endif\n\n    if (! have_position)\n      ## Subplots that cover more that one base subplot are not updated\n      align_axes = (align_axes || (! isscalar (index)));\n      ## Normal case where subplot indices have been given\n      [pos, opos, li] = subplot_position (cf, rows, cols, index);\n    else\n      ## Position is specified by the user.\n      li = zeros (1,4);\n      align_axes = true;\n    endif\n\n    set (cf, \"nextplot\", \"add\");\n\n    if (! make_subplot)\n      found = false;\n      kids = get (cf, \"children\");\n      for child = kids(:)'\n        ## Check whether this child is still valid; this might not be the\n        ## case anymore due to the deletion of previous children (due to\n        ## \"deletefcn\" callback or for legends/colorbars that are deleted\n        ## with their corresponding axes).\n        if (! ishghandle (child))\n          continue;\n        endif\n        if (strcmp (get (child, \"type\"), \"axes\"))\n          ## Skip legend and colorbar objects.\n          if (any (strcmp (get (child, \"tag\"), {\"legend\", \"colorbar\"})))\n            continue;\n          endif\n\n          if (! replace_axes)\n            if (isappdata (child, \"__subplotposition__\"))\n              objpos = getappdata (child, \"__subplotposition__\");\n            else\n              objpos = get (child, \"position\");\n            endif\n            if (all (abs (objpos - pos) < eps))\n              ## If the new axes are in exactly the same position\n              ## as an existing axes object, or if they share the same\n              ## appdata \"__subplotposition__\", use the existing axes.\n              found = true;\n              hsubplot = child;\n            elseif (exist (\"rows\", \"var\"))\n              ## Check if this axes is a subplot with the same layout and\n              ## index as the requested one\n              rcn = getappdata (child, \"__subplotrcn__\");\n              if (all (size (rcn) == [1 3])\n                  && rcn{1} == rows && rcn{2} == cols && all (rcn{3} == index))\n                found = true;\n                hsubplot = child;\n              endif\n            endif\n          endif\n\n          if (! found)\n            ## If the new axes overlap an old axes object, delete the old axes.\n            objpos = get (child, \"position\");\n\n            x0 = pos(1);\n            x1 = x0 + pos(3);\n            y0 = pos(2);\n            y1 = y0 + pos(4);\n            objx0 = objpos(1);\n            objx1 = objx0 + objpos(3);\n            objy0 = objpos(2);\n            objy1 = objy0 + objpos(4);\n            if (! (x0 >= objx1 || x1 <= objx0 || y0 >= objy1 || y1 <= objy0))\n              delete (child);\n            endif\n          endif\n        endif\n      endfor\n    else\n      found = true;\n    endif\n\n    if (found && ! make_subplot)\n      ## Switch to existing subplot and set requested properties\n      set (cf, \"currentaxes\", hsubplot);\n      if (! isempty (varargin))\n        set (hsubplot, varargin{:});\n      endif\n    else\n      pval = [{\"positionconstraint\", \"innerposition\", ...\n               \"position\", pos, \"looseinset\", li} varargin];\n      if (! make_subplot)\n        hsubplot = axes (pval{:});\n      else\n        set (hsubplot, pval{:})\n      endif\n\n      if (! align_axes)\n        ## base position (no ticks, no annotation, no cumbersome neighbor)\n        setappdata (hsubplot, \"__subplotposition__\", pos);\n        ## max outerposition\n        setappdata (hsubplot, \"__subplotouterposition__\", opos);\n        setappdata (hsubplot, \"__subplotrcn__\", {rows, cols, index});\n        addlistener (hsubplot, \"outerposition\", @subplot_align);\n        addlistener (hsubplot, \"xaxislocation\", @subplot_align);\n        addlistener (hsubplot, \"yaxislocation\", @subplot_align);\n        addlistener (hsubplot, \"position\", {@subplot_align, true});\n        subplot_align (hsubplot);\n      endif\n\n    endif\n  unwind_protect_cleanup\n    set (0, \"defaultaxesunits\", axesunits);\n    set (cf, \"units\", figureunits);\n  end_unwind_protect\n\n  if (nargout > 0)\n    hax = hsubplot;\n  endif\n\nendfunction\n\nfunction [pos, opos, li] = subplot_position (hf, nrows, ncols, idx)\n\n  if (nrows == 1 && ncols == 1)\n    ## Trivial result for subplot (1,1,1)\n    pos = get (0, \"defaultaxesposition\");\n    opos = get (0, \"defaultaxesouterposition\");\n    li = get (0, \"defaultaxeslooseinset\");\n    return;\n  endif\n\n  ## Row/Column inside the axes array\n  row = ceil (idx / ncols);\n  col = idx - (row - 1) * ncols;\n  row = [min(row) max(row)];\n  col = [min(col) max(col)];\n\n  ## Minimal margins around subplots defined in points\n  fig_units = get (hf, \"units\");\n  set (hf, \"units\", \"points\");\n  pts_size = get (gcf, \"position\")(3:4);\n  xbasemargin = 6 / pts_size(1);\n  ybasemargin = 6 / pts_size(2);\n\n  ## Column/row separation\n  margin.column = .2 / ncols + 2 * xbasemargin;\n  margin.row = .2 / nrows + 2 * ybasemargin;\n\n  set (hf, \"units\", fig_units);\n  margin.left = xbasemargin;\n  margin.right = xbasemargin;\n  margin.bottom = ybasemargin;\n  margin.top = ybasemargin;\n\n  ## Boundary axes have default margins\n  borders = get (0, \"defaultaxesposition\");\n  if (col(1) == 1)\n    margin.left = borders(1);\n  else\n    margin.left = margin.column - margin.right;\n  endif\n  if (col(2) == ncols)\n    margin.right = 1 - borders(1) - borders(3);\n  endif\n\n\n  if (row(2) == nrows)\n    margin.bottom = borders(2);\n  else\n    margin.bottom = margin.row - margin.top;\n  endif\n  if (row(1) == 1)\n    margin.top = 1 - borders(2) - borders(4);\n  endif\n\n\n  ## Compute base width and height\n  width = (borders(3) - (ncols - 1) * margin.column) / ncols;\n  height = (borders(4) - (nrows - 1) * margin.row) /nrows;\n\n  ## Position, outerposition and looseinset\n  x0 = borders(1) + (col(1) - 1) * (width + margin.column);\n  y0 = borders(2) + (nrows - row(2)) * (height + margin.row);\n  width += diff (col) * (width + margin.column);\n  height += diff (row) * (height + margin.row);\n\n  pos = [x0 y0 width height];\n  opos = [(x0 - margin.left), (y0 - margin.bottom), ...\n          (width + margin.left + margin.right), ...\n          (height + margin.bottom + margin.top)];\n  li = [margin.left, margin.bottom, margin.right, margin.top];\n\nendfunction\n\nfunction subplot_align (h, ~, rmupdate = false)\n  persistent updating = false;\n\n  if (! updating)\n    if (rmupdate)\n      ## The \"position\" property has been changed from outside this routine.\n      ## Don't update anymore.\n      if (isappdata (h, \"__subplotposition__\"))\n        rmappdata (h, \"__subplotposition__\");\n        rmappdata (h, \"__subplotouterposition__\");\n      endif\n      return;\n    endif\n\n    unwind_protect\n      updating = true;\n      hf = ancestor (h, \"figure\");\n      children = get (hf, \"children\");\n\n      ## Base position of the subplot\n      pos = getappdata (children, \"__subplotposition__\");\n\n      if (iscell (pos))\n        do_align = ! cellfun ('isempty', pos);\n        pos = cell2mat (pos(do_align));\n      else\n        return;\n      endif\n      hsubplots = children(do_align);\n\n\n      ## There may be mixed subplot series (e.g., 2-by-6 and 1-by-6) in\n      ## the same figure.  Only subplots that have the same width and\n      ## height as this one are updated.\n      if (any (h == hsubplots))\n        width = pos(h == hsubplots, 3);\n        height = pos(h == hsubplots, 4);\n        do_align = (pos(:,3) == width) & (pos(:,4) == height);\n        hsubplots(! do_align) = [];\n        pos(! do_align,:) = [];\n      else\n        return;\n      endif\n\n      ## Reset outerpositions to their default value\n      opos = getappdata (hsubplots, \"__subplotouterposition__\");\n      if (iscell (opos))\n        opos = cell2mat (opos);\n      endif\n      for ii = 1:numel (hsubplots)\n        set (hsubplots(ii), \"outerposition\", opos(ii,:), ...\n             \"positionconstraint\", \"innerposition\");\n      endfor\n\n      ## Compare current positions to default and compute the new ones\n      curpos = get (hsubplots, \"position\");\n      if (iscell (curpos))\n        curpos = cell2mat (curpos);\n      endif\n      dx0 = max (curpos(:,1) - pos(:,1));\n      dx0(dx0<0) = 0;\n      dx1 = max ((pos(:,1) + pos(:,3)) - (curpos(:,1) + curpos(:,3)));\n      dx1(dx1<0) = 0;\n      dy0 = max (curpos(:,2) - pos(:,2));\n      dy0(dy0<0) = 0;\n      dy1 = max ((pos(:,2) + pos(:,4)) - (curpos(:,2) + curpos(:,4)));\n      dy1(dy1<0) = 0;\n\n      pos(:,1) += dx0;\n      pos(:,2) += dy0;\n      pos(:,3) -= dx0 + dx1;\n      pos(:,4) -= dy0 + dy1;\n\n      for ii = 1:numel (hsubplots)\n        set (hsubplots(ii), \"position\", pos(ii,:));\n      endfor\n\n    unwind_protect_cleanup\n      updating = false;\n    end_unwind_protect\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! r = 3;\n%! c = 3;\n%! fmt = {\"horizontalalignment\", \"center\", \"verticalalignment\", \"middle\"};\n%! for n = 1 : r*c\n%!   subplot (r, c, n);\n%!    xlabel (sprintf (\"xlabel #%d\", n));\n%!    ylabel (sprintf (\"ylabel #%d\", n));\n%!    title (sprintf (\"title #%d\", n));\n%!    text (0.5, 0.5, sprintf (\"subplot(%d,%d,%d)\", r, c, n), fmt{:});\n%!    axis ([0 1 0 1]);\n%! endfor\n%! subplot (r, c, 1:3);\n%!  xlabel (sprintf (\"xlabel #%d:%d\", 1, 3));\n%!  ylabel (sprintf (\"ylabel #%d:%d\", 1, 3));\n%!  title (sprintf (\"title #%d:%d\", 1, 3));\n%!  text (0.5, 0.5, sprintf (\"subplot(%d,%d,%d:%d)\", r, c, 1, 3), fmt{:});\n%! axis ([0 1 0 1]);\n\n%!demo\n%! clf;\n%! x = 0:1;\n%! for n = 1:4\n%!   subplot (2,2,n, \"align\");\n%!    plot (x, x);\n%!    xlabel (sprintf (\"xlabel (2,2,%d)\", n));\n%!    ylabel (sprintf (\"ylabel (2,2,%d)\", n));\n%!    title (sprintf (\"title (2,2,%d)\", n));\n%! endfor\n%! subplot (1,2,1, \"align\");\n%!  plot (x, x);\n%!  xlabel (\"xlabel (1,2,1)\");\n%!  ylabel (\"ylabel (1,2,1)\");\n%!  title (\"title (1,2,1)\");\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! ax(1) = subplot (221);\n%! set (ax(1), \"tag\", \"1\");\n%! plot (x, rand (3, 11));\n%! title (\"x & y labels & ticklabels\");\n%! xlabel xlabel;\n%! ylabel ylabel;\n%! ax(2) = subplot (222);\n%! set (ax(2), \"tag\", \"2\");\n%! plot (x, rand (3, 11));\n%! title (\"no labels\");\n%! axis (\"nolabel\",\"tic\");\n%! ax(3) = subplot (223);\n%! set (ax(3), \"tag\", \"3\");\n%! plot (x, rand (3, 11));\n%! title (\"no labels\");\n%! axis (\"nolabel\",\"tic\");\n%! ax(4) = subplot (224);\n%! set (ax(4), \"tag\", \"4\");\n%! plot (x, rand (3, 11));\n%! title (\"x & y labels & ticklabels\");\n%! xlabel xlabel;\n%! ylabel ylabel;\n\n%!demo\n%! clf;\n%! x = 0:10;\n%! subplot (221);\n%!  plot (x, rand (3, 11));\n%!  ylim ([0, 1]);\n%!  text (0.5, 0.5, \"{x,y}labels & {x,y}ticklabels\", ...\n%!                  \"horizontalalignment\", \"center\", ...\n%!                  \"units\", \"normalized\");\n%!  xlabel xlabel;\n%!  ylabel ylabel;\n%!  title title;\n%! subplot (222);\n%!  plot (x, rand (3, 11));\n%!  axis (\"labely\");\n%!  ylabel ylabel;\n%!  text (0.5, 0.5, \"no xlabels, xticklabels\", ...\n%!                  \"horizontalalignment\", \"center\", ...\n%!                  \"units\", \"normalized\");\n%! subplot (223);\n%!  plot (x, rand (3, 11));\n%!  axis (\"labelx\");\n%!  text (0.5, 0.5, \"no ylabels, yticklabels\", ...\n%!                  \"horizontalalignment\", \"center\", ...\n%!                  \"units\", \"normalized\");\n%!  xlabel xlabel;\n%!  title title;\n%! subplot (224);\n%!  plot (x, rand (3, 11));\n%!  axis (\"nolabel\", \"tic\");\n%!  text (0.5, 0.5, \"no {x,y}labels, {x,y}ticklabels\", ...\n%!                  \"horizontalalignment\", \"center\", ...\n%!                  \"units\", \"normalized\");\n\n## Test recognition/deletion of previous axes\n## Default mode\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   for ii = 1:9\n%!     hax(ii) = subplot (3,3,ii);\n%!   endfor\n%!   subplot (3,3,1);\n%!   assert (gca (), hax(1));\n%!   subplot (2,1,1);\n%!   assert (ishghandle (hax),[false(1,6), true(1,3)]);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n## Position mode\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h1 = subplot (\"position\", [0.1 0.1 0.3 0.3]);\n%!   h2 = subplot (\"position\", [0.5 0.5 0.3 0.3]);\n%!   subplot (\"position\", [0.1 0.1 0.3 0.3]);\n%!   assert (gca (), h1);\n%!   subplot (\"position\", [0.5 0.5 0.3 0.3]);\n%!   assert (gca (), h2);\n%!   subplot (\"position\", [0.5 0.5 0.3 0.2]);\n%!   assert (! ishghandle (h2));\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n## Mixed rcn and position mode\n%!test <*62526>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h1 = subplot (2, 2, 1);\n%!   h2 = subplot (\"position\", [0.5 0.5 0.3 0.3]);\n%!   h3 = subplot (223);\n%!   assert (get (hf, \"children\"), [h3; h2; h1]);\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n\n## Align mode\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   h1 = subplot (3,5,1, \"align\");\n%!   h2 = subplot (3,5,2, \"align\");\n%!   subplot (3,5,1, \"align\");\n%!   assert (gca (), h1);\n%!   subplot (3,2,1, \"align\");\n%!   assert (! ishghandle (h1));\n%!   assert (! ishghandle (h2));\n%! unwind_protect_cleanup\n%!   delete (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "scripts/plot/util/zoom.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} zoom\n## @deftypefnx {} {} zoom (@var{factor})\n## @deftypefnx {} {} zoom on\n## @deftypefnx {} {} zoom off\n## @deftypefnx {} {} zoom xon\n## @deftypefnx {} {} zoom yon\n## @deftypefnx {} {} zoom out\n## @deftypefnx {} {} zoom reset\n## @deftypefnx {} {} zoom (@var{hfig}, @var{option})\n## Zoom the current axes object or control the interactive zoom mode of a\n## figure in the GUI.\n##\n## Given a numeric argument greater than zero, zoom by the given factor.  If\n## the zoom factor is greater than one, zoom in on the plot.  If the factor\n## is less than one, zoom out.  If the zoom factor is a two- or three-element\n## vector, then the elements specify the zoom factors for the x, y, and z\n## axes respectively.\n##\n## Given the option @qcode{\"on\"} or @qcode{\"off\"}, set the interactive zoom\n## mode on or off.\n##\n## With no arguments, toggle the current zoom mode on or off.\n##\n## Given the option @qcode{\"xon\"} or @qcode{\"yon\"}, enable zoom mode for the\n## x or y-axis only.\n##\n## Given the option @qcode{\"out\"}, zoom to the initial zoom setting.\n##\n## Given the option @qcode{\"reset\"}, store the current zoom setting so that\n## @code{zoom out} will return to this zoom level.\n##\n## If the first argument @var{hfig} is a figure, then operate on the given\n## figure rather than the current figure as returned by @code{gcf}.\n##\n## @seealso{pan, rotate3d}\n## @end deftypefn\n\n## Eventually we need to also support these features:\n## @deftypefnx {} {zoom_object_handle =} zoom (@var{hfig})\n\nfunction zoom (hfig, option)\n\n  ## FIXME: Presumably should implement this for Matlab compatibility.\n  if (nargin == 1 && nargout > 0 && isfigure (hfig))\n    error (\"zoom: syntax 'handle = zoom (hfig)' not implemented\");\n  endif\n\n  if (nargin == 0)\n    hfig = gcf ();\n  else\n    if (nargin == 1)\n      option = hfig;\n      hfig = gcf ();\n    else\n      if (! isfigure (hfig))\n        error (\"zoom: invalid figure handle HFIG\");\n      endif\n    endif\n  endif\n\n  if (nargin == 0)\n    zm = get (hfig, \"__zoom_mode__\");\n    if (strcmp (zm.Enable, \"on\"))\n      zm.Enable = \"off\";\n    else\n      zm.Enable = \"on\";\n    endif\n    set (hfig, \"__zoom_mode__\", zm);\n    update_mouse_mode (hfig, zm.Enable);\n  else\n    if (isnumeric (option))\n      factor = option;\n      switch (numel (factor))\n        case 2\n          xfactor = factor(1);\n          yfactor = factor(2);\n        case 1\n          xfactor = yfactor = factor;\n        otherwise\n          error (\"zoom: FACTOR must be a 1- or 2-element vector\");\n      endswitch\n      if (xfactor <= 0 || yfactor <= 0)\n        error (\"zoom: FACTOR must be greater than 0\");\n      elseif (xfactor == 1 && yfactor == 1)\n        return;\n      endif\n      cax = get (hfig, \"currentaxes\");\n      if (! isempty (cax))\n        if (xfactor != 1)\n          if (yfactor != 1)\n            mode = \"both\";\n          else\n            mode = \"horizontal\";\n          endif\n        else\n          if (yfactor != 1)\n            mode = \"vertical\";\n          endif\n        endif\n        __zoom__ (cax, mode, factor);\n      endif\n    elseif (ischar (option))\n      switch (option)\n        case {\"on\", \"off\", \"xon\", \"yon\"}\n          zm = get (hfig, \"__zoom_mode__\");\n          switch (option)\n            case {\"on\", \"off\"}\n              zm.Enable = option;\n              zm.Motion = \"both\";\n            case \"xon\"\n              zm.Enable = \"on\";\n              zm.Motion = \"horizontal\";\n            case \"yon\"\n              zm.Enable = \"on\";\n              zm.Motion = \"vertical\";\n          endswitch\n          set (hfig, \"__zoom_mode__\", zm);\n          update_mouse_mode (hfig, option);\n        case \"out\"\n          cax = get (hfig, \"currentaxes\");\n          if (! isempty (cax))\n            __zoom__ (cax, \"out\");\n          endif\n        case \"reset\"\n          cax = get (hfig, \"currentaxes\");\n          if (! isempty (cax))\n            __zoom__ (cax, \"reset\");\n          endif\n        otherwise\n          error (\"zoom: unrecognized OPTION '%s'\", option);\n      endswitch\n    else\n      error (\"zoom: OPTION must be a number or a string\");\n    endif\n  endif\n\nendfunction\n\nfunction update_mouse_mode (hfig, arg)\n\n  if (strcmp (arg, \"off\"))\n    set (hfig, \"__mouse_mode__\", \"none\");\n  else\n    ## FIXME: Is there a better way other than calling these functions\n    ##        to set the other mouse mode Enable fields to \"off\"?\n    pan (hfig, \"off\");\n    rotate3d (hfig, \"off\");\n    set (hfig, \"__mouse_mode__\", \"zoom\");\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! sombrero ();\n%! title (\"zoom() demo #1\");\n%! pause (1);\n%! ## zoom in by a factor of 2\n%! zoom (2);\n%! pause (1);\n%! ## return to original zoom level\n%! zoom out;\n%! pause (1);\n%! ## zoom in by a factor of 2\n%! zoom (2);\n%! pause (1);\n%! ## set this zoom level as the \"initial zoom level\"\n%! ## and zoom in some more\n%! zoom reset;\n%! zoom (2);\n%! pause (1);\n%! ## return to zoom level set by last call to \"zoom reset\"\n%! zoom out;\n"
  },
  {
    "path": "scripts/polynomial/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/polynomial/compan.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{A} =} compan (@var{c})\n## Compute the companion matrix corresponding to polynomial coefficient vector\n## @var{c}.\n##\n## The companion matrix is\n## @tex\n## $$\n## A = \\left[\\matrix{\n##  -c_2/c_1 & -c_3/c_1 & \\cdots & -c_N/c_1 & -c_{N+1}/c_1\\cr\n##      1    &     0    & \\cdots &     0    &         0   \\cr\n##      0    &     1    & \\cdots &     0    &         0   \\cr\n##   \\vdots  &   \\vdots & \\ddots &  \\vdots  &      \\vdots \\cr\n##      0    &     0    & \\cdots &     1    &         0}\\right].\n## $$\n## @end tex\n## @ifnottex\n## @c Set example in small font to prevent overfull line\n##\n## @smallexample\n## @group\n##      _                                                        _\n##     |  -c(2)/c(1)   -c(3)/c(1)  @dots{}  -c(N)/c(1)  -c(N+1)/c(1)  |\n##     |       1            0      @dots{}       0             0      |\n##     |       0            1      @dots{}       0             0      |\n## A = |       .            .      .         .             .      |\n##     |       .            .       .        .             .      |\n##     |       .            .        .       .             .      |\n##     |_      0            0      @dots{}       1             0     _|\n## @end group\n## @end smallexample\n##\n## @end ifnottex\n## The eigenvalues of the companion matrix are equal to the roots of the\n## polynomial.\n## @seealso{roots, poly, eig}\n## @end deftypefn\n\nfunction A = compan (c)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  if (! isvector (c))\n    error (\"compan: C must be a vector\");\n  endif\n\n  n = length (c);\n\n  if (n == 1)\n    A = [];\n  else\n    A = diag (ones (n-2, 1), -1);\n    A(1,:) = -c(2:n) / c(1);\n  endif\n\nendfunction\n\n\n%!assert (compan ([1, 2, 3]), [-2, -3; 1, 0])\n%!assert (compan ([1; 2; 3]), [-2, -3; 1, 0])\n%!assert (isempty (compan (4)))\n%!assert (compan ([3, 2, 1]), [-2/3, -1/3; 1, 0])\n\n%!error compan ([1,2;3,4])\n%!error compan ([])\n"
  },
  {
    "path": "scripts/polynomial/conv.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} conv (@var{a}, @var{b})\n## @deftypefnx {} {@var{y} =} conv (@var{a}, @var{b}, @var{shape})\n## Convolve two vectors @var{a} and @var{b}.\n##\n## When @var{a} and @var{b} are the coefficient vectors of two polynomials, the\n## convolution represents the coefficient vector of the product polynomial.\n##\n## The size of the result is determined by the optional @var{shape} argument\n## which takes the following values\n##\n## @table @asis\n## @item @var{shape} = @qcode{\"full\"}\n## Return the full convolution.  (default)\n## The result is a vector with length equal to\n## @code{length (@var{a}) + length (@var{b}) - 1}.\n##\n## @item @var{shape} = @qcode{\"same\"}\n## Return the central part of the convolution with the same size as @var{a}.\n##\n## @item @var{shape} = @qcode{\"valid\"}\n## Return only the parts which do not include zero-padded edges.\n## The size of the result is\n## @code{max (size (@var{a}) - size (@var{b}) + 1, 0)}.\n## @end table\n##\n## @seealso{deconv, conv2, convn, fftconv}\n## @end deftypefn\n\nfunction y = conv (a, b, shape = \"full\")\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (isvector (a) && isvector (b)))\n    error (\"conv: both arguments A and B must be vectors\");\n  elseif (nargin == 3 && ! any (strcmpi (shape, {\"full\", \"same\", \"valid\"})))\n    error ('conv: SHAPE argument must be \"full\", \"same\", or \"valid\"');\n  endif\n\n  ## Column vectors perform best in Fortran code.\n  y = convn (a(:), b(:), shape);\n\n  if (strcmpi (shape, \"full\"))\n    ## Adapt the shape to the longest input argument, if necessary.\n    if ((length (a) > length (b) && isrow (a)) ...\n        || (length (a) <= length (b) && isrow (b)))\n      y = y.';\n    endif\n  elseif (isrow (a))\n    ## Adapt the shape to the first input argument, if necessary.\n    y = y.';\n  endif\n\nendfunction\n\n\n%!test\n%! x = ones (3,1);\n%! y = ones (1,3);\n%! b = 2;\n%! c = 3;\n%! assert (conv (x, x), [1; 2; 3; 2; 1]);\n%! assert (conv (y, y), [1, 2, 3, 2, 1]);\n%! assert (conv (x, y), [1, 2, 3, 2, 1]);\n%! assert (conv (y, x), [1; 2; 3; 2; 1]);\n%! assert (conv (c, x), [3; 3; 3]);\n%! assert (conv (c, y), [3, 3, 3]);\n%! assert (conv (x, c), [3; 3; 3]);\n%! assert (conv (y, c), [3, 3, 3]);\n%! assert (conv (b, c), 6);\n\n%!shared a,b\n%!test\n%! a = 1:10;\n%! b = 1:3;\n%!assert (size (conv (a,b)), [1, numel(a)+numel(b)-1])\n%!assert (size (conv (b,a)), [1, numel(a)+numel(b)-1])\n\n%!test\n%! a = (1:10).';\n%!assert (size (conv (a,b)), [numel(a)+numel(b)-1, 1])\n%!assert (size (conv (b,a)), [numel(a)+numel(b)-1, 1])\n\n%!test\n%! a = 1:10;\n%! b = (1:3).';\n%!assert (size (conv (a,b)), [1, numel(a)+numel(b)-1])\n%!assert (size (conv (b,a)), [1, numel(a)+numel(b)-1])\n\n%!test\n%! a = 1:10;\n%! b = 1:3;\n\n%!assert (conv (a,b,\"full\"), conv (a,b))\n%!assert (conv (b,a,\"full\"), conv (b,a))\n\n%!assert (conv (a,b,\"same\"), [4, 10, 16, 22, 28, 34, 40, 46, 52, 47])\n%!assert (conv (b,a,\"same\"), [28, 34, 40])\n\n%!assert (conv (a,b,\"valid\"), [10, 16, 22, 28, 34, 40, 46, 52])\n%!assert (conv (b,a,\"valid\"), zeros (1,0))\n\n\n## Test input validation\n%!error <Invalid call> conv (1)\n%!error <A and B must be vectors> conv ([1, 2; 3, 4], 3)\n%!error <A and B must be vectors> conv (3, [1, 2; 3, 4])\n%!error <SHAPE argument must be> conv (2, 3, \"INVALID_SHAPE\")\n"
  },
  {
    "path": "scripts/polynomial/deconv.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{b} =} deconv (@var{y}, @var{a})\n## @deftypefnx {} {[@var{b}, @var{r}] =} deconv (@var{y}, @var{a})\n## Deconvolve two vectors (polynomial division).\n##\n## @code{[@var{b}, @var{r}] = deconv (@var{y}, @var{a})} solves for @var{b} and\n## @var{r} such that @code{@var{y} = conv (@var{a}, @var{b}) + @var{r}}.\n##\n## If @var{y} and @var{a} are polynomial coefficient vectors, @var{b} will\n## contain the coefficients of the polynomial quotient and @var{r} will be\n## a remainder polynomial of lowest order.\n## @seealso{conv, residue}\n## @end deftypefn\n\nfunction [b, r] = deconv (y, a)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! (isvector (y) && isvector (a)))\n    error (\"deconv: Y and A must be vectors\");\n  endif\n\n  la = numel (a);\n  ly = numel (y);\n\n  if (ly < la)  # return early\n    b = 0;\n    r = y;\n    return;\n  endif\n\n  ## If here, then ly >= la.\n  ## Ensure A is oriented as Y.\n  if (isrow (y) != isrow (a))\n    a = a.';\n  endif\n\n  if (ly > la)\n    x = zeros (size (y) - size (a) + 1);\n    x(1) = 1;\n  else  # ly == la ==> set x to 1 without calling size() and zeros();\n    x = 1;\n  endif\n\n  if (nargout == 1)  # no need to calculate remainder\n\n    b = filter (y, a, x);\n\n  else  # nargout == 2 ==> calculate both quotient and remainder\n\n    [b, r] = filter (y, a, x);\n    r *= a(1);\n    r = [zeros(ly - la + 1, 1); r(1:la - 1)];\n\n    ## Respect the orientation of Y\n    if (isrow (y))\n      r = r.';\n    endif\n\n  endif\n\nendfunction\n\n\n%!test\n%! [b, r] = deconv ([3, 6, 9, 9], [1, 2, 3]);\n%! assert (b, [3, 0]);\n%! assert (r, [0, 0, 0, 9]);\n\n%!test\n%! [b, r] = deconv ([3, 6], [1, 2, 3]);\n%! assert (b, 0);\n%! assert (r, [3, 6]);\n\n%!test\n%! [b, r] = deconv ([3, 6], [1; 2; 3]);\n%! assert (b, 0);\n%! assert (r, [3, 6]);\n\n%!test\n%! [b,r] = deconv ([3; 6], [1; 2; 3]);\n%! assert (b, 0);\n%! assert (r, [3; 6]);\n\n%!test\n%! [b, r] = deconv ([3; 6], [1, 2, 3]);\n%! assert (b, 0);\n%! assert (r, [3; 6]);\n\n%!assert (deconv ((1:3)',[1, 1]), [1; 1])\n\n## Test input validation\n%!error deconv (1)\n%!error deconv (1,2,3)\n%!error <Y .* must be vector> deconv ([3, 6], [1, 2; 3, 4])\n%!error <A must be vector> deconv ([3, 6], [1, 2; 3, 4])\n\n%!test\n%! y = (10:-1:1);\n%! a = (4:-1:1);\n%! [b, r] = deconv (y, a);\n%! assert (conv (a, b) + r, y, eps);\n\n%!test <*51221>\n%! a = [1.92306958582241e+15, 3.20449986572221e+24, 1.34271290136344e+32, ...\n%!     2.32739765751038e+38];\n%! b = [7.33727670161595e+27, 1.05919311870816e+36, 4.56169848520627e+42];\n%! [div, rem] = deconv (a, b);\n%! assert (rem, [0, 0, -2.89443678763879e+32  -1.58695290534499e+39], -10*eps);\n%! a(2) = 3.204499865722215e+24;\n%! [div, rem] = deconv (a, b);\n%! assert (rem, [0, 0, -2.89443678763879e+32  -1.58695290534499e+39], -10*eps);\n\n%!test\n%! [b, r] = deconv ([1, 1], 1);\n%! assert (r, [0, 0]);\n\n%!test\n%! [b, r] = deconv ([1; 1], 1);\n%! assert (r, [0; 0]);\n"
  },
  {
    "path": "scripts/polynomial/mkpp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{pp} =} mkpp (@var{breaks}, @var{coefs})\n## @deftypefnx {} {@var{pp} =} mkpp (@var{breaks}, @var{coefs}, @var{d})\n##\n## Construct a piecewise polynomial (pp) structure from sample points\n## @var{breaks} and coefficients @var{coefs}.\n##\n## @var{breaks} must be a vector of strictly increasing values.  The number of\n## intervals is given by @code{@var{ni} = length (@var{breaks}) - 1}.\n##\n## When @var{m} is the polynomial order @var{coefs} must be of size:\n## @w{@var{ni}-by-(@var{m} + 1)}.\n##\n## The i-th row of @var{coefs}, @code{@var{coefs}(@var{i},:)}, contains the\n## coefficients for the polynomial over the @var{i}-th interval, ordered from\n## highest (@var{m}) to lowest (@var{0}) degree.\n##\n## @var{coefs} may also be a multi-dimensional array, specifying a\n## vector-valued or array-valued polynomial.  In that case the polynomial\n## order @var{m} is defined by the length of the last dimension of @var{coefs}.\n## The size of first dimension(s) are given by the scalar or vector @var{d}.\n## If @var{d} is not given it is set to @code{1}.  In this case\n## @code{@var{p}(@var{r}, @var{i}, :)} contains the coefficients for the\n## @var{r}-th polynomial defined on interval @var{i}.  In any case @var{coefs}\n## is reshaped to a 2-D matrix of size @code{[@var{ni}*prod(@var{d}) @var{m}]}.\n##\n## Programming Note: @code{ppval} evaluates polynomials at\n## @code{@var{xi} - @var{breaks}(i)}, i.e., it subtracts the lower endpoint of\n## the current interval from @var{xi}.  This must be taken into account when\n## creating piecewise polynomials objects with @code{mkpp}.\n## @seealso{unmkpp, ppval, spline, pchip, ppder, ppint, ppjumps}\n## @end deftypefn\n\nfunction pp = mkpp (breaks, coefs, d)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  ## Check BREAKS\n  if (! isvector (breaks))\n    error (\"mkpp: BREAKS must be a vector\");\n  elseif (length (breaks) < 2)\n    error (\"mkpp: BREAKS must have at least one interval\");\n  endif\n\n  len = length (breaks) - 1;\n\n  pp = struct (\"form\", \"pp\",\n               \"breaks\", breaks(:).',\n               \"coefs\", [],\n               \"pieces\", len,\n               \"order\", prod (size (coefs)) / len,\n               \"dim\", 1);\n\n  if (nargin == 3)\n    pp.dim = d;\n    pp.order /= prod (d);\n  endif\n\n  dim_vec = [pp.pieces * prod(pp.dim), pp.order];\n  pp.coefs = reshape (coefs, dim_vec);\n\nendfunction\n\n\n%!demo # linear interpolation\n%! x = linspace (0, pi, 5)';\n%! t = [sin(x), cos(x)];\n%! m = diff (t) ./ (x(2)-x(1));\n%! b = t(1:4,:);\n%! pp = mkpp (x, [m(:),b(:)]);\n%! xi = linspace (0, pi, 50);\n%! plot (x, t, \"x\", xi, ppval (pp,xi));\n%! legend (\"control\", \"interp\");\n\n%!demo # piecewise polynomial shape\n%! breaks = [0 1 2 3];\n%! dim = 2;\n%! coefs = zeros (dim, length (breaks) - 1, 4);\n%! # 1st edge of the shape (x, x^2)\n%! coefs(1,1,:) = [0 0 1 0];\n%! coefs(2,1,:) = [0 1 0 0];\n%! # 2nd edge of the shape (-3x, 1)\n%! coefs(1,2,:) = [0 0 -3 1];\n%! coefs(2,2,:) = [0 0 0 1];\n%! # 3rd edge of the shape (2x - 2, -4(x -1/2)^3 + 1/2)\n%! coefs(1,3,:) = [0 0 2 -2];\n%! coefs(2,3,:) = [-4 6 -3 1];\n%! pp = mkpp (breaks, coefs, dim);\n%! t = linspace (0, 3, 100).';\n%! xy = ppval (pp, t).';\n%! patch (xy(:,1), xy(:,2), 'r');\n\n%!shared b,c,pp\n%! b = 1:3; c = 1:24; pp = mkpp (b,c);\n%!assert (pp.pieces, 2)\n%!assert (pp.order, 12)\n%!assert (pp.dim, 1)\n%!assert (size (pp.coefs), [2,12])\n%! pp = mkpp (b,c,2);\n%!assert (pp.pieces, 2)\n%!assert (pp.order, 6)\n%!assert (pp.dim, 2)\n%!assert (size (pp.coefs), [4,6])\n%! pp = mkpp (b,c,3);\n%!assert (pp.pieces, 2)\n%!assert (pp.order, 4)\n%!assert (pp.dim, 3)\n%!assert (size (pp.coefs), [6,4])\n%! pp = mkpp (b,c,[2,3]);\n%!assert (pp.pieces, 2)\n%!assert (pp.order, 2)\n%!assert (pp.dim, [2,3])\n%!assert (size (pp.coefs), [12,2])\n"
  },
  {
    "path": "scripts/polynomial/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__splinefit__.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/compan.m \\\n  %reldir%/conv.m \\\n  %reldir%/deconv.m \\\n  %reldir%/mkpp.m \\\n  %reldir%/mpoles.m \\\n  %reldir%/padecoef.m \\\n  %reldir%/pchip.m \\\n  %reldir%/poly.m \\\n  %reldir%/polyaffine.m \\\n  %reldir%/polyder.m \\\n  %reldir%/polyeig.m \\\n  %reldir%/polyfit.m \\\n  %reldir%/polygcd.m \\\n  %reldir%/polyint.m \\\n  %reldir%/polyout.m \\\n  %reldir%/polyreduce.m \\\n  %reldir%/polyval.m \\\n  %reldir%/polyvalm.m \\\n  %reldir%/ppder.m \\\n  %reldir%/ppint.m \\\n  %reldir%/ppjumps.m \\\n  %reldir%/ppval.m \\\n  %reldir%/residue.m \\\n  %reldir%/roots.m \\\n  %reldir%/spline.m \\\n  %reldir%/splinefit.m \\\n  %reldir%/unmkpp.m\n\n%canon_reldir%dir = $(fcnfiledir)/polynomial\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/polynomial/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/polynomial/mpoles.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{multp}, @var{idxp}] =} mpoles (@var{p})\n## @deftypefnx {} {[@var{multp}, @var{idxp}] =} mpoles (@var{p}, @var{tol})\n## @deftypefnx {} {[@var{multp}, @var{idxp}] =} mpoles (@var{p}, @var{tol}, @var{reorder})\n## Identify unique poles in @var{p} and their associated multiplicity.\n##\n## By default, the output is ordered from the pole with the largest magnitude\n## to the smallest magnitude.\n##\n## Two poles are considered to be multiples if the difference between them\n## is less than the relative tolerance @var{tol}.\n##\n## @example\n## abs (@var{p1} - @var{p0}) / abs (@var{p0}) < @var{tol}\n## @end example\n##\n## If the pole is 0 then no scaling is done and @var{tol} is interpreted as an\n## absolute tolerance.  The default value for @var{tol} is 0.001.\n##\n## If the optional parameter @var{reorder} is false/zero, poles are not\n## sorted.\n##\n## The output @var{multp} is a vector specifying the multiplicity of the poles.\n## @code{@var{multp}(n)} refers to the multiplicity of the Nth pole\n## @code{@var{p}(@var{idxp}(n))}.\n##\n## For example:\n##\n## @example\n## @group\n## p = [2 3 1 1 2];\n## [m, n] = mpoles (p)\n##    @xresult{} m = [1; 1; 2; 1; 2]\n##    @xresult{} n = [2; 5; 1; 4; 3]\n##    @xresult{} p(n) = [3, 2, 2, 1, 1]\n## @end group\n## @end example\n##\n## @seealso{residue, poly, roots, conv, deconv}\n## @end deftypefn\n\nfunction [multp, idxp] = mpoles (p, tol, reorder)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isfloat (p))\n    error (\"mpoles: P must be a single or double floating point vector\");\n  endif\n\n  if (nargin < 2 || isempty (tol))\n    tol = 0.001;\n  elseif (! (isscalar (tol) && isreal (tol) && tol > 0))\n    error (\"mpoles: TOL must be a real scalar greater than 0\");\n  endif\n\n  if (nargin < 3 || isempty (reorder))\n    reorder = true;\n  elseif (! (isscalar (reorder) && isreal (reorder)))\n    error (\"mpoles: REORDER must be a numeric or logical scalar\");\n  endif\n\n  Np = numel (p);\n  p = p(:);  # force poles to be a column vector\n\n  if (reorder)\n    ## sort with largest magnitude first\n    [~, order] = sort (abs (p), \"descend\");\n    p = p(order);\n  else\n    order = (1:Np).';\n  endif\n\n  ## Create vector of tolerances for use in algorithm.\n  vtol = zeros (Np, 1, class (p));\n  p_nz = (p != 0);     # nonzero poles\n  vtol(! p_nz) = tol;  # use absolute tolerance for zero poles\n\n  ## Find pole multiplicity by comparing relative difference of poles.\n  multp = zeros (Np, 1, class (p));\n  idxp = [];\n  n = find (multp == 0, 1);\n  while (n)\n    dp = abs (p - p(n));\n    vtol(p_nz) = tol * abs (p(n));\n    k = find (dp < vtol);\n    ## Poles can only be members of one multiplicity group.\n    if (numel (idxp))\n      k = k(! ismember (k, idxp));\n    endif\n    m = 1:numel (k);\n    multp(k) = m;\n    idxp = [idxp; k];\n    n = find (multp == 0, 1);\n  endwhile\n  multp = multp(idxp);\n  idxp = order(idxp);\n\nendfunction\n\n\n%!test\n%! [mp, ip] = mpoles ([0 0], 0.01);\n%! assert (mp, [1; 2]);\n\n%!test\n%! [mp, ip] = mpoles ([-1e4, -0.1, 0]);\n%! assert (mp, [1; 1; 1]);\n%! assert (ip, [1; 2; 3]);\n\n## Test single inputs\n%!test\n%! [mp, ip] = mpoles (single ([-1e4, -0.1, 0]));\n%! assert (mp, single ([1; 1; 1]));\n%! assert (ip, [1; 2; 3]);\n\n## Test relative tolerance criteria\n%!test\n%! [mp, ip] = mpoles ([1, 1.1, 1.3], .1/1.1);\n%! assert (mp, [1; 1; 1]);\n%! [mp, ip] = mpoles ([1, 1.1, 1.3], .1/1.1 + eps);\n%! assert (mp, [1; 1; 2]);\n\n## Test absolute tolerance criteria with a zero pole\n%!test\n%! [mp, ip] = mpoles ([0, -0.1, 0.3], .1);\n%! assert (mp, [1; 1; 1]);\n%! [mp, ip] = mpoles ([0, -0.1, 0.3], .1 + eps);\n%! assert (mp, [1; 1; 2]);\n\n## Test input validation\n%!error <Invalid call> mpoles ()\n%!error <P must be a single or double floating point vector> mpoles (uint8 (1))\n%!error <TOL must be a real scalar greater than 0> mpoles (1, [1, 2])\n%!error <TOL must be a real scalar greater than 0> mpoles (1, 1i)\n%!error <TOL must be a real scalar greater than 0> mpoles (1, 0)\n%!error <REORDER must be a numeric or logical scalar> mpoles (1, 1, [1, 2])\n%!error <REORDER must be a numeric or logical scalar> mpoles (1, 1, {1})\n"
  },
  {
    "path": "scripts/polynomial/padecoef.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{num}, @var{den}] =} padecoef (@var{T})\n## @deftypefnx {} {[@var{num}, @var{den}] =} padecoef (@var{T}, @var{N})\n## Compute the @var{N}th-order Pad@'e approximant of the continuous-time\n## delay @var{T} in transfer function form.\n## @tex\n## The Pad\\'e approximant of $e^{-sT}$ is defined by the following equation\n## $$ e^{-sT} \\approx {P_n(s) \\over Q_n(s)} $$\n## where both $P_n(s)$ and $Q_n(s)$ are $N^{th}$-order rational functions\n## defined by the following expressions\n## $$ P_n(s)=\\sum_{k=0}^N {(2N - k)!N!\\over (2N)!k!(N - k)!}(-sT)^k $$\n## $$ Q_n(s) = P_n(-s) $$\n## @end tex\n## @ifnottex\n## The Pad@'e approximant of @nospell{@code{exp (-sT)}} is defined by the\n## following equation\n##\n## @example\n## @group\n##              Pn(s)\n## exp (-sT) ~ -------\n##              Qn(s)\n## @end group\n## @end example\n##\n## Where both @nospell{Pn(s) and Qn(s)} are @var{N}th-order rational functions\n## defined by the following expressions\n##\n## @example\n## @group\n##          N    (2N - k)!N!        k\n## Pn(s) = SUM --------------- (-sT)\n##         k=0 (2N)!k!(N - k)!\n##\n## Qn(s) = Pn(-s)\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## The inputs @var{T} and @var{N} must be non-negative numeric scalars.  If\n## @var{N} is unspecified it defaults to 1.\n##\n## The output row vectors @var{num} and @var{den} contain the numerator and\n## denominator coefficients in descending powers of s.  Both are\n## @var{N}th-order polynomials.\n##\n## For example:\n##\n## @smallexample\n## @group\n## t = 0.1;\n## n = 4;\n## [num, den] = padecoef (t, n)\n## @xresult{} num =\n##\n##       1.0000e-04  -2.0000e-02   1.8000e+00  -8.4000e+01   1.6800e+03\n##\n## @xresult{} den =\n##\n##       1.0000e-04   2.0000e-02   1.8000e+00   8.4000e+01   1.6800e+03\n## @end group\n## @end smallexample\n## @end deftypefn\n\nfunction [num, den] = padecoef (T, N = 1)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (T) && isnumeric (T) && T >= 0))\n    error (\"padecoef: T must be a non-negative scalar\");\n  elseif (! (isscalar (N) && isnumeric (N) && N >= 0))\n    error (\"padecoef: N must be a non-negative scalar\");\n  endif\n\n  N = round (N);\n  k = N : -1 : 0;\n  num = prod (linspace ((N - k + 1), (2 * N - k), N)', 1) ...\n        / prod (N + 1 : 2 * N) ./ factorial (k);\n  num /= num(1);\n  den = num .* (T .^ k);\n  num .*= ((-T) .^ k);\n\nendfunction\n\n\n%!test\n%! T = 1;\n%! [n_obs, d_obs] = padecoef (T);\n%! n_exp = [1, 2] .* [-T, 1];\n%! d_exp = [1, 2] .* [T, 1];\n%! assert ([n_obs, d_obs], [n_exp, d_exp], eps);\n\n%!test\n%! T = 0.1;\n%! [n_obs, d_obs] = padecoef (T);\n%! n_exp = [1, 2] .* [-T, 1];\n%! d_exp = [1, 2] .* [T, 1];\n%! assert ([n_obs, d_obs], [n_exp, d_exp], eps);\n\n%!test\n%! T = 1;\n%! N = 2;\n%! k = N : -1 : 0;\n%! [n_obs, d_obs] = padecoef (T, N);\n%! n_exp = [1, 6, 12] .* ((-T) .^ k);\n%! d_exp = [1, 6, 12] .* (T .^ k);\n%! assert ([n_obs, d_obs], [n_exp, d_exp], eps);\n\n%!test\n%! T = 0.25;\n%! N = 2;\n%! k = N : -1 : 0;\n%! [n_obs, d_obs] = padecoef (T, 2);\n%! n_exp = [1, 6, 12] .* ((-T) .^ k);\n%! d_exp = [1, 6, 12] .* (T .^ k);\n%! assert ([n_obs, d_obs], [n_exp, d_exp], eps);\n\n%!test\n%! T = 0.47;\n%! N = 3;\n%! k = N : -1 : 0;\n%! [n_obs, d_obs] = padecoef (T, N);\n%! n_exp = [1, 12, 60, 120] .* ((-T) .^ k);\n%! d_exp = [1, 12, 60, 120] .* (T .^ k);\n%! assert ([n_obs, d_obs], [n_exp, d_exp], eps);\n\n%!test\n%! T = 1;\n%! N = 7;\n%! i = 0 : 2 * N;\n%! b = ((-T) .^ i) ./ factorial (i);\n%! A = [[eye(N + 1); zeros(N, N + 1)], ...\n%!      [zeros(1, N); toeplitz(-b(1 : 2 * N), [-b(1), zeros(1, N-1)])]];\n%! x = A \\ b';\n%! k = N : -1 : 0;\n%! d_exp = [flipud(x(N + 2 : 2 * N + 1)); 1]';\n%! n_exp = flipud (x(1 : N + 1))';\n%! n_exp ./= d_exp(1);\n%! d_exp ./= d_exp(1);\n%! [n_obs, d_obs] = padecoef (T, N);\n%! assert ([n_obs, d_obs], [n_exp, d_exp], 1e-2);\n\n## For checking in Wolfram Alpha (look at Alternate forms -> more):\n## PadeApproximant[Exp[-x * T], {x, 0, {n, n}}]\n\n## Test input validation\n%!error <Invalid call> padecoef ()\n%!error <T must be a non-negative scalar> padecoef ([1,2])\n%!error <T must be a non-negative scalar> padecoef ({1})\n%!error <T must be a non-negative scalar> padecoef (-1)\n%!error <N must be a non-negative scalar> padecoef (1, [1,2])\n%!error <N must be a non-negative scalar> padecoef (1, {1})\n%!error <N must be a non-negative scalar> padecoef (1, -1)\n"
  },
  {
    "path": "scripts/polynomial/pchip.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{pp} =} pchip (@var{x}, @var{y})\n## @deftypefnx {} {@var{yi} =} pchip (@var{x}, @var{y}, @var{xi})\n## Return the Piecewise Cubic Hermite Interpolating Polynomial (pchip) of\n## points @var{x} and @var{y}.\n##\n## If called with two arguments, return the piecewise polynomial @var{pp}\n## that may be used with @code{ppval} to evaluate the polynomial at specific\n## points.\n##\n## When called with a third input argument, @code{pchip} evaluates the pchip\n## polynomial at the points @var{xi}.  The third calling form is equivalent to\n## @code{ppval (pchip (@var{x}, @var{y}), @var{xi})}.\n##\n## The variable @var{x} must be a strictly monotonic vector (either increasing\n## or decreasing) of length @var{n}.\n##\n## @var{y} can be either a vector or array.  If @var{y} is a vector then it\n## must be the same length @var{n} as @var{x}.  If @var{y} is an array then\n## the size of @var{y} must have the form\n## @tex\n## $$[s_1, s_2, \\cdots, s_k, n]$$\n## @end tex\n## @ifnottex\n## @code{[@var{s1}, @var{s2}, @dots{}, @var{sk}, @var{n}]}\n## @end ifnottex\n## The array is reshaped internally to a matrix where the leading dimension is\n## given by\n## @tex\n## $$s_1 s_2 \\cdots s_k$$\n## @end tex\n## @ifnottex\n## @code{@var{s1} * @var{s2} * @dots{} * @var{sk}}\n## @end ifnottex\n## and each row of this matrix is then treated separately.  Note that this is\n## exactly opposite to @code{interp1} but is done for @sc{matlab}\n## compatibility.\n##\n## @seealso{spline, ppval, mkpp, unmkpp}\n## @end deftypefn\n\n## Algorithm:\n## S_k = a_k + b_k*x + c_k*x^2 + d_k*x^3; (spline polynomial)\n##\n## 4 conditions:\n## S_k(x_k) = y_k;\n## S_k(x_k+1) = y_k+1;\n## S_k'(x_k) = y_k';\n## S_k'(x_k+1) = y_k+1';\n\nfunction ret = pchip (x, y, xi)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  ## make row vector\n  x = x(:).';\n  n = length (x);\n\n  ## Check the size and shape of y\n  if (isvector (y))\n    y = y(:).';  # force row vector\n    szy = size (y);\n    if (! size_equal (x, y))\n      error (\"pchip: length of X and Y must match\");\n    endif\n  else\n    szy = size (y);\n    if (n != szy(end))\n      error (\"pchip: length of X and last dimension of Y must match\");\n    endif\n    y = reshape (y, [prod(szy(1:end-1)), szy(end)]);\n  endif\n\n  h = diff (x);\n  if (all (h < 0))\n    x = fliplr (x);\n    h = diff (x);\n    y = fliplr (y);\n  elseif (any (h <= 0))\n    error (\"pchip: X must be strictly monotonic\");\n  endif\n\n  f1 = y(:, 1:n-1);\n\n  ## Compute derivatives.\n  d = __pchip_deriv__ (x, y, 2);\n  d1 = d(:, 1:n-1);\n  d2 = d(:, 2:n);\n\n  ## This is taken from SLATEC.\n  h = diag (h);\n\n  delta = diff (y, 1, 2) / h;\n  del1 = (d1 - delta) / h;\n  del2 = (d2 - delta) / h;\n  c3 = del1 + del2;\n  c2 = -c3 - del1;\n  c3 /= h;\n  coeffs = cat (3, c3, c2, d1, f1);\n\n  ret = mkpp (x, coeffs, szy(1:end-1));\n\n  if (nargin == 3)\n    ret = ppval (ret, xi);\n  endif\n\nendfunction\n\n\n%!demo\n%! x = 0:8;\n%! y = [1, 1, 1, 1, 0.5, 0, 0, 0, 0];\n%! xi = 0:0.01:8;\n%! yspline = spline (x,y,xi);\n%! ypchip = pchip (x,y,xi);\n%! title (\"pchip and spline fit to discontinuous function\");\n%! plot (xi,yspline, xi,ypchip,\"-\", x,y,\"+\");\n%! legend (\"spline\", \"pchip\", \"data\");\n%! %-------------------------------------------------------------------\n%! % confirm that pchip agreed better to discontinuous data than spline\n\n%!shared x, y, y2, pp, yi1, yi2, yi3\n%! x = 0:8;\n%! y = [1, 1, 1, 1, 0.5, 0, 0, 0, 0];\n%!assert (pchip (x,y,x), y)\n%!assert (pchip (x,y,x'), y')\n%!assert (pchip (x',y',x'), y')\n%!assert (pchip (x',y',x), y)\n%!assert (isempty (pchip (x',y',[])))\n%!assert (isempty (pchip (x,y,[])))\n%!assert (pchip (x,[y;y],x), [pchip(x,y,x);pchip(x,y,x)])\n%!assert (pchip (x,[y;y],x'), [pchip(x,y,x);pchip(x,y,x)])\n%!assert (pchip (x',[y;y],x), [pchip(x,y,x);pchip(x,y,x)])\n%!assert (pchip (x',[y;y],x'), [pchip(x,y,x);pchip(x,y,x)])\n%!test\n%! x = (0:8)*pi/4; y = [sin(x); cos(x)];\n%! y2(:,:,1) = y; y2(:,:,2) = y+1; y2(:,:,3) = y-1;\n%! pp = pchip (x, shiftdim (y2,2));\n%! yi1 = ppval (pp, (1:4)*pi/4);\n%! yi2 = ppval (pp, repmat ((1:4)*pi/4, [5,1]));\n%! yi3 = ppval (pp, [pi/2,pi]);\n%!assert (size (pp.coefs), [48,4])\n%!assert (pp.pieces, 8)\n%!assert (pp.order, 4)\n%!assert (pp.dim, [3,2])\n%!assert (ppval (pp,pi), [0,-1;1,0;-1,-2], 1e-14)\n%!assert (yi3(:,:,2), ppval (pp,pi), 1e-14)\n%!assert (yi3(:,:,1), [1,0;2,1;0,-1], 1e-14)\n%!assert (squeeze (yi1(1,2,:)), [1/sqrt(2); 0; -1/sqrt(2);-1], 1e-14)\n%!assert (size (yi2), [3,2,5,4])\n%!assert (squeeze (yi2(1,2,3,:)), [1/sqrt(2); 0; -1/sqrt(2);-1], 1e-14)\n\n%!error pchip (1,2)\n%!error pchip (1,2,3)\n"
  },
  {
    "path": "scripts/polynomial/poly.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} poly (@var{A})\n## @deftypefnx {} {@var{y} =} poly (@var{x})\n## If @var{A} is a square @math{N}-by-@math{N} matrix, @code{poly (@var{A})}\n## is the row vector of the coefficients of @code{det (z * eye (N) - A)},\n## the characteristic polynomial of @var{A}.\n##\n## For example, the following code finds the eigenvalues of @var{A} which are\n## the roots of @code{poly (@var{A})}.\n##\n## @example\n## @group\n## roots (poly (eye (3)))\n##     @xresult{} 1.00001 + 0.00001i\n##        1.00001 - 0.00001i\n##        0.99999 + 0.00000i\n## @end group\n## @end example\n##\n## In fact, all three eigenvalues are exactly 1 which emphasizes that for\n## numerical performance the @code{eig} function should be used to compute\n## eigenvalues.\n##\n## If @var{x} is a vector, @code{poly (@var{x})} is a vector of the\n## coefficients of the polynomial whose roots are the elements of @var{x}.\n## That is, if @var{c} is a polynomial, then the elements of\n## @code{@var{d} = roots (poly (@var{c}))} are contained in @var{c}.  The\n## vectors @var{c} and @var{d} are not identical, however, due to sorting and\n## numerical errors.\n## @seealso{roots, eig}\n## @end deftypefn\n\nfunction y = poly (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x))\n    error (\"poly: input must be numeric, not type %s\", class (x));\n  elseif (ndims (x) > 2)\n    error (\"poly: input must be a vector or a square matrix\");\n  elseif (isempty (x))\n    y = 1;\n    return;\n  elseif (isvector (x))\n    n = numel (x);\n    v = x;\n  elseif (! issquare (x))\n    error (\"poly: input matrix must be square\");\n  else\n    n = size (x,1);\n    v = eig (x);\n  endif\n\n  y = zeros (1, n+1);\n  y(1) = 1;\n  for j = 1:n\n    y(2:(j+1)) -= v(j) .* y(1:j);\n  endfor\n\n  ## Real, or complex conjugate inputs, should result in real output\n  if (isreal (x))\n    y = real (y);\n  else\n    pos_imag = sort (v(imag (v) > 0));\n    neg_imag = sort (conj (v(imag (v) < 0)));\n    if (size_equal (pos_imag, neg_imag))\n      is_equal = (pos_imag == neg_imag);\n      if (! isempty (is_equal) && all (is_equal))\n        y = real (y);\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!assert (poly ([]), 1)\n%!assert (poly ([1, 2, 3]), [1, -6, 11, -6])\n%!assert (poly ([1, 2; 3, 4]), [1, -5, -2], sqrt (eps))\n\n%!test <*53897>\n%! x = [1, sqrt(2)/2+sqrt(2)/2*i, 1i, -sqrt(2)/2+sqrt(2)/2*i, -1, ...\n%!      -sqrt(2)/2-sqrt(2)/2*i, -1i, sqrt(2)/2-sqrt(2)/2*i];\n%! y = poly (x);\n%! assert (isreal (y), true);\n\n%!test <*53897>\n%! x = [1 + 1i, 1 + 2i, 3, 4];\n%! y = poly (x);\n%! assert (y, [1 + 0i, -9 - 3i, 25 + 24i, -17 - 57i, -12 + 36i]);\n\n%!error <Invalid call> poly ()\n%!error <input must be numeric> poly (\"foo\")\n%!error <input must be numeric> poly ({1, \"foo\"; \"bar\", 1})\n%!error <input must be a vector or a square matrix> poly (ones (2, 2, 2))\n%!error <matrix must be square> poly ([1, 2, 3; 4, 5, 6])\n"
  },
  {
    "path": "scripts/polynomial/polyaffine.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{g} =} polyaffine (@var{f}, @var{mu})\n## Return the coefficients of the polynomial vector @var{f} after an affine\n## transformation.\n##\n## If @var{f} is the vector representing the polynomial f(x), then\n## @code{@var{g} = polyaffine (@var{f}, @var{mu})} is the vector representing:\n##\n## @example\n## g(x) = f( (x - @var{mu}(1)) / @var{mu}(2) )\n## @end example\n##\n## @seealso{polyval, polyfit}\n## @end deftypefn\n\nfunction g = polyaffine (f, mu)\n\n   if (nargin != 2)\n      print_usage ();\n   endif\n\n   if (! isvector (f))\n      error (\"polyaffine: F must be a vector\");\n   endif\n\n   if (! isvector (mu) || length (mu) != 2)\n      error (\"polyaffine: MU must be a two-element vector\");\n   endif\n\n   lf = length (f);\n\n   ## Ensure that f is a row vector\n   if (rows (f) > 1)\n      f = f.';\n   endif\n\n   g = f;\n\n   ## Scale.\n   if (mu(2) != 1)\n     g ./= mu(2) .^ (lf-1:-1:0);\n   endif\n\n   ## Translate.\n   if (mu(1) != 0)\n     w = (-mu(1)) .^ (0:lf-1);\n     ii = lf:-1:1;\n     g = g(ii) * (toeplitz (w) .* pascal (lf, -1));\n     g = g(ii);\n   endif\n\nendfunction\n\n\n%!demo\n%! f = [1/5 4/5 -7/5 -2];\n%! g = polyaffine (f, [1, 1.2]);\n%! x = linspace (-4,4,100);\n%! plot (x,polyval (f, x), x,polyval (g, x));\n%! legend (\"original\", \"affine\");\n%! axis ([-4 4 -3 5]);\n%! grid on;\n\n%!test\n%! f = [1/5 4/5 -7/5 -2];\n%! mu = [1, 1.2];\n%! g = polyaffine (f, mu);\n%! x = linspace (-4,4,100);\n%! assert (polyval (f, x, [], mu), polyval (g, x), 1e-10);\n"
  },
  {
    "path": "scripts/polynomial/polyder.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{k} =} polyder (@var{p})\n## @deftypefnx {} {@var{k} =} polyder (@var{a}, @var{b})\n## @deftypefnx {} {[@var{q}, @var{d}] =} polyder (@var{b}, @var{a})\n## Return the coefficients of the derivative of the polynomial whose\n## coefficients are given by the vector @var{p}.\n##\n## If a pair of polynomials is given, return the derivative of the product\n## @math{@var{a}*@var{b}}.\n##\n## If two inputs and two outputs are given, return the derivative of the\n## polynomial quotient @math{@var{b}/@var{a}}.  The quotient numerator is\n## in @var{q} and the denominator in @var{d}.\n## @seealso{polyint, polyval, polyreduce}\n## @end deftypefn\n\nfunction [q, d] = polyder (p, a)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isvector (p))\n    error (\"polyder: argument must be a vector\");\n  endif\n  if (nargin == 2)\n    if (! isvector (a))\n      error (\"polyder: argument must be a vector\");\n    endif\n    if (nargout == 1)\n      ## derivative of p*a returns a single polynomial\n      q = polyder (conv (p, a));\n    else\n      ## derivative of p/a returns numerator and denominator\n      d = conv (a, a);\n      if (numel (p) == 1)\n        q = -p * polyder (a);\n      elseif (numel (a) == 1)\n        q = a * polyder (p);\n      else\n        q = conv (polyder (p), a) - conv (p, polyder (a));\n        q = polyreduce (q);\n      endif\n\n      ## remove common factors from numerator and denominator\n      x = polygcd (q, d);\n      if (length (x) != 1)\n        q = deconv (q, x);\n        d = deconv (d, x);\n      endif\n\n      ## move all the gain into the numerator\n      q /= d(1);\n      d /= d(1);\n    endif\n  else\n    lp = numel (p);\n    if (lp == 1)\n      q = 0;\n      return;\n    elseif (lp == 0)\n      q = [];\n      return;\n    endif\n\n    ## Force P to be a row vector.\n    p = p(:).';\n\n    q = p(1:(lp-1)) .* [(lp-1):-1:1];\n  endif\n\nendfunction\n\n\n%!assert (polyder ([1, 2, 3], [2, 2]))\n%!assert (polyder (13), 0)\n\n%!error polyder ([])\n%!error polyder (1,2,3)\n%!error <argument must be a vector> polyder ([1, 2; 3, 4])\n"
  },
  {
    "path": "scripts/polynomial/polyeig.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{z} =} polyeig (@var{C0}, @var{C1}, @dots{}, @var{Cl})\n## @deftypefnx {} {[@var{v}, @var{z}] =} polyeig (@var{C0}, @var{C1}, @dots{}, @var{Cl})\n##\n## Solve the polynomial eigenvalue problem of degree @var{l}.\n##\n## Given an @var{n}x@var{n} matrix polynomial\n##\n## @code{@var{C}(@var{s}) = @var{C0} + @var{C1} @var{s} + @dots{} + @var{Cl}\n## @var{s}^@var{l}}\n##\n## @code{polyeig} solves the eigenvalue problem\n##\n## @code{(@var{C0} + @var{C1} @var{z} + @dots{} + @var{Cl} @var{z}^@var{l})\n## @var{v} = 0}.\n##\n## Note that the eigenvalues @var{z} are the zeros of the matrix polynomial.\n## @var{z} is a row vector with @code{@var{n}*@var{l}} elements.  @var{v} is a\n## matrix (@var{n} x @var{n}*@var{l}) with columns that correspond to the\n## eigenvectors.\n##\n## @seealso{eig, eigs, compan}\n## @end deftypefn\n\nfunction [z, v] = polyeig (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  n = rows (varargin{1});\n\n  for i = 1 : nargin\n    if (! issquare (varargin{i}))\n      error (\"polyeig: coefficients must be square matrices\");\n    endif\n    if (rows (varargin{i}) != n)\n      error (\"polyeig: coefficients must have the same dimensions\");\n    endif\n  endfor\n\n  ## matrix polynomial degree\n  l = nargin - 1;\n\n  ## form needed matrices\n  C = [ zeros(n * (l - 1), n), eye(n * (l - 1));\n       -cell2mat(varargin(1:end-1)) ];\n\n  D = [ eye(n * (l - 1)), zeros(n * (l - 1), n);\n        zeros(n, n * (l - 1)), varargin{end} ];\n\n  ## solve generalized eigenvalue problem\n  if (nargout < 2)\n    z = eig (C, D);\n  else\n    [z, v] = eig (C, D);\n    v = diag (v);\n    ## return n-element eigenvectors normalized so that the infinity-norm = 1\n    z = z(1:n,:);\n    t = max (z);    # max() takes the abs if complex.\n    z ./= t;\n  endif\n\nendfunction\n\n\n%!shared C0, C1\n%! C0 = [8, 0; 0, 4];\n%! C1 = [1, 0; 0, 1];\n\n%!test\n%! z = polyeig (C0, C1);\n%! assert (z, [-8; -4]);\n\n%!test\n%! [v,z] = polyeig (C0, C1);\n%! assert (z, [-8; -4]);\n%! z = diag (z);\n%! d = C0*v + C1*v*z;\n%! assert (norm (d), 0.0);\n\n## Test input validation\n%!error <Invalid call> polyeig ()\n%!error <coefficients must be square matrices> polyeig (ones (3,2))\n%!error <coefficients must have the same dimensions>\n%! polyeig (ones (3,3), ones (2,2))\n"
  },
  {
    "path": "scripts/polynomial/polyfit.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{p} =} polyfit (@var{x}, @var{y}, @var{n})\n## @deftypefnx {} {[@var{p}, @var{s}] =} polyfit (@var{x}, @var{y}, @var{n})\n## @deftypefnx {} {[@var{p}, @var{s}, @var{mu}] =} polyfit (@var{x}, @var{y}, @var{n})\n## Return the coefficients of a polynomial @var{p}(@var{x}) of degree @var{n}\n## that minimizes the least-squares-error of the fit to the points\n## @code{[@var{x}(:), @var{y}(:)]}.\n##\n## @var{n} is typically an integer @geq{} 0 specifying the degree of the\n## approximating polynomial.  If @var{n} is a logical vector, it is used as a\n## mask to selectively force the corresponding polynomial coefficients to be\n## used or ignored.\n##\n## The polynomial coefficients are returned in the row vector @var{p}.  The\n## output @var{p} may be directly used with @code{polyval} to estimate values\n## using the fitted polynomial.\n##\n## The optional output @var{s} is a structure containing the following fields:\n##\n## @table @samp\n##\n## @item yf\n## The values of the polynomial for each value of @var{x}.\n##\n## @item V\n## The @nospell{Vandermonde} matrix used to compute the polynomial\n## coefficients.\n##\n## @item X (deprecated, will be removed in Octave 13)\n## The @nospell{Vandermonde} matrix used to compute the polynomial\n## coefficients.\n##\n## @item R\n## Triangular factor R from the QR@tie{}decomposition.\n##\n## @item C\n## The unscaled covariance matrix, formally equal to the inverse of\n## @var{v'}*@var{v}, but computed in a way minimizing roundoff error\n## propagation.\n##\n## @item df\n## The degrees of freedom.\n##\n## @item normr\n## The norm of the residuals.\n##\n## @item rsquared\n## Coefficient of determination, or R-squared.\n## @end table\n##\n## The second output may be used by @code{polyval} to calculate the statistical\n## error limits of the predicted values.  In particular, the standard deviation\n## of @var{p} coefficients is given by\n##\n## @code{sqrt (diag (@var{s.C})/@var{s.df}) * @var{s.normr}}.\n##\n## When the third output, @var{mu}, is present the original data is centered\n## and scaled which can improve the numerical stability of the fit.  The\n## coefficients @var{p} are associated with a polynomial in\n##\n## @code{@var{xhat} = (@var{x} - @var{mu}(1)) / @var{mu}(2)} @*\n## where @var{mu}(1) = mean (@var{x}), and @var{mu}(2) = std (@var{x}).\n##\n## Example 1 : logical @var{n} and integer @var{n}\n##\n## @example\n## @group\n## f = @@(x) x.^2 + 5;   # data-generating function\n## x = 0:5;\n## y = f (x);\n## ## Fit data to polynomial A*x^3 + B*x^1\n## p = polyfit (x, y, logical ([1, 0, 1, 0]))\n## @xresult{} p = [ 0.0680, 0, 4.2444, 0 ]\n## ## Fit data to polynomial using all terms up to x^3\n## p = polyfit (x, y, 3)\n## @xresult{} p = [ -4.9608e-17, 1.0000e+00, -1.6906e-15, 5.0000e+00 ]\n## @end group\n## @end example\n##\n## Programming Note: If the desired polynomial degree @var{n} @geq{} number\n## of data points, the solution is not unique.  Instead, the fitting calculates\n## @code{@var{m} = numel (@var{x}) - 1} terms.  The return polynomial has\n## coefficients for @var{x}^@var{n}, @var{x}^@var{n}-1, @dots{},\n## @var{x}^@var{n}-@var{m}, and the constant term @var{x}^0, with all other\n## coefficients set to 0.\n## @seealso{polyval, polyaffine, roots, vander, zscore}\n## @end deftypefn\n\nfunction [p, s, mu] = polyfit (x, y, n)\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  scale_x = (nargout == 3);\n  y_is_row_vector = isrow (y);\n\n  ## Reshape x and y into column vectors.\n  x = x(:);\n  y = y(:);\n\n  nx = numel (x);\n  ny = numel (y);\n  if (nx != ny)\n    error (\"polyfit: X and Y must have the same number of points\");\n  endif\n\n  if (scale_x)\n    ## Center and scale the x values.\n    mu = [mean(x), std(x)];\n    x = (x - mu(1)) / mu(2);\n  endif\n\n  ## n is the polynomial degree (an input, or deduced from the polymask size).\n  ## m is the effective number of coefficients (accounts for insufficient data).\n  if (islogical (n))\n    polymask = n(:).';          # force to row vector\n    n = numel (polymask) - 1;\n    m = sum (polymask) - 1;\n    pad_output = true;\n  else\n    if (! (isscalar (n) && n >= 0 && ! isinf (n) && n == fix (n)))\n      error (\"polyfit: N must be a non-negative integer\");\n    endif\n    polymask = true (1, n+1);\n    m = n;\n    pad_output = false;\n  endif\n\n  if (m >= nx)\n    warning (\"polyfit: degree of polynomial N is >= number of data points; solution is not unique.\");\n    m = nx;\n    pad_output = true;\n    if (scale_x && nx < 3)\n      error (\"polyfit: number of data points must be > 2 when scaling input X\");\n    endif\n    ## Keep the highest m-1 entries and the constant term in polymask\n    polymask(:) = false;\n    if (m == 1)\n      polymask(1) = true;\n    else\n      polymask([1:m-1,end]) = true;\n    endif\n  endif\n\n  ## Construct the Vandermonde matrix.\n  v = vander (x, n+1);\n  ## Reduce columns of matrix, rather than zero them, to improve qr results.\n  v = v(:, polymask);\n\n  ## Solve by QR decomposition.\n  [q, r, k] = qr (v, 0);  # Use '0' to create 'econ' factoring.\n  p = r \\ (q' * y);\n  p(k) = p;\n\n  if (nargout > 1)\n    yf = v*p;\n    if (y_is_row_vector)\n      s.yf = yf.';\n    else\n      s.yf = yf;\n    endif\n\n    ## r.'*r is positive definite if matrix v is of full rank.  Invert it by\n    ## cholinv to avoid taking the square root of squared quantities.\n    ## If cholinv fails, then v is rank deficient and not invertible.\n    try\n      C = cholinv (r.'*r)(k, k);\n    catch\n      C = NaN (m, m);\n    end_try_catch\n\n    if (pad_output)\n      s.V = zeros (rows (v), n+1); s.V(:, polymask) = v;\n      ## FIXME: Deprecated.  Remove in Octave 13.\n      s.X = s.V;\n      s.R = zeros (rows (r), n+1); s.R(:, polymask) = r;\n      s.C = zeros (rows (C), n+1); s.C(:, polymask) = C;\n    else\n      s.V = v;\n      ## FIXME: Deprecated.  Remove in Octave 13.\n      s.X = s.V;\n      s.R = r;\n      s.C = C;\n    endif\n\n    s.df = max (0, nx - m - 1);\n    resid = sumsq (yf - y);\n    s.normr = sqrt (resid);\n    s.rsquared = 1 - resid / sumsq (y - mean (y));\n  endif\n\n  if (pad_output)\n    ## Zero pad output\n    p_nonzero = p;\n    p = zeros (n+1, 1);\n    p(polymask) = p_nonzero;\n  endif\n  p = p.';  # Return a row vector.\n\nendfunction\n\n\n%!shared x\n%! x = [-2, -1, 0, 1, 2];\n\n%!assert (polyfit (x, 3*x.^2 + 2*x + 1, 2), [3, 2, 1], 10*eps)\n%!assert (polyfit (x, 3*x.^2 + 2*x + 1, logical ([1 1 1])), [3, 2, 1], 10*eps)\n%!assert (polyfit (x, x.^2 + 2*x + 3, 3), [0, 1, 2, 3], 10*eps)\n%!assert (polyfit (x, x.^2 + 2*x + 3, logical ([0 1 1 1])), [0 1 2 3], 10*eps)\n\n## Test logical input N\n%!test\n%! x = [0:5];\n%! y = 3*x.^3 + 2*x.^2 + 4;\n%! [p, s] = polyfit (x, y, logical ([1, 0, 1, 1]));\n%! assert (p(2), 0);\n%! assert (all (p([1, 3, 4])));\n%! assert (s.df, 3);\n\n## Test difficult case where scaling is really needed.  This example\n## demonstrates the rather poor result which occurs when the dependent\n## variable is not normalized properly.\n## Also check the usage of 2nd & 3rd output arguments.\n%!test\n%! warning (\"off\", \"Octave:nearly-singular-matrix\", \"local\");\n%! x = [ -1196.4, -1195.2, -1194, -1192.8, -1191.6, -1190.4, -1189.2, -1188, ...\n%!       -1186.8, -1185.6, -1184.4, -1183.2, -1182];\n%! y = [ 315571.7086, 315575.9618, 315579.4195, 315582.6206, 315585.4966, ...\n%!       315588.3172, 315590.9326, 315593.5934, 315596.0455, 315598.4201, ...\n%!       315600.7143, 315602.9508, 315605.1765 ];\n%! [p1, s1] = polyfit (x, y, 10);\n%! [p2, s2, mu] = polyfit (x, y, 10);\n%! assert (s2.normr < s1.normr);\n\n%!test\n%! warning (\"off\", \"Octave:nearly-singular-matrix\", \"local\");\n%! x = 1000 + (-5:5);\n%! xn = (x - mean (x)) / std (x);\n%! pn = ones (1,5);\n%! y = polyval (pn, xn);\n%! n = numel (pn) - 1;\n%! [p, s, mu] = polyfit (x, y, n);\n%! [p2, s2] = polyfit (x, y, n);\n%! assert (p, pn, s.normr);\n%! assert (s.yf, y, s.normr);\n%! assert (mu, [mean(x), std(x)]);\n%! assert (s.normr/s2.normr < sqrt (eps));\n\n## Complex polynomials\n%!test\n%! x = 1:4;\n%! p0 = [1i, 0, 2i, 4];\n%! y = polyval (p0, x);\n%! n = numel (p0) - 1;\n%! p = polyfit (x, y, n);\n%! assert (p, p0, 1000*eps);\n\n## Matrix input\n%!test\n%! x = [1, 2, 3; 4, 5, 6];\n%! y = [0, 0, 1; 1, 0, 0];\n%! p = polyfit (x, y, 5);\n%! expected = [0, 1, -14, 65, -112, 60] / 12;\n%! assert (p, expected, sqrt (eps));\n\n## Orientation of output is always row vector\n%!test\n%! x = 0:5;\n%! y = x.^4 + 2*x + 5;\n%! [p, s] = polyfit (x, y, 3);\n%! assert (isrow (s.yf));\n%! [p, s] = polyfit (x, y.', 3);\n%! assert (iscolumn (s.yf));\n\n## Insufficient data for fit\n%!test <*57964>\n%! ## Disable warnings entirely because there is not a specific ID to disable.\n%! wstate = warning ();\n%! unwind_protect\n%!   warning (\"off\", \"all\");\n%!   x = [1, 2];\n%!   y = [1.5, 9];\n%!   [p,s] = polyfit (x, y, 4);\n%! unwind_protect_cleanup\n%!   warning (wstate);\n%! end_unwind_protect\n%! assert (p, [0.5, 0, 0, 0, 1], 12*eps);\n%! assert (size (s.V), [2, 5]);\n%! assert (s.V(:,2:4), zeros (2,3));\n%! assert (size (s.R), [2, 5]);\n%! assert (s.R(:,2:4), zeros (2,3));\n%! assert (size (s.C), [2, 5]);\n%! assert (s.C(:,2:4), zeros (2,3));\n%! assert (s.df, 0);\n%! assert (s.normr, 0, 20*eps);\n%! assert (s.rsquared, 1, 20*eps);\n\n%!test\n%! wstate = warning ();\n%! unwind_protect\n%!   warning (\"off\", \"all\");\n%!   x = [1, 2, 3];\n%!   y = 2*x + 1;\n%!   p0 = polyfit (x, y, logical ([1, 1, 1, 0, 1]));\n%!   [p1, s, mu] = polyfit (x, y, logical ([1, 1, 1, 0, 1]));\n%! unwind_protect_cleanup\n%!   warning (wstate);\n%! end_unwind_protect\n%! assert (p0(3:4), [0, 0]);\n%! assert (p1, [0, 2, 0, 0, 5], 10*eps);\n%! assert (size (s.V), [3, 5]);\n%! assert (s.V(:,3:4), zeros (3,2));\n%! assert (size (s.R), [3, 5]);\n%! assert (s.R(:,3:4), zeros (3,2));\n%! assert (size (s.C), [3, 5]);\n%! assert (s.C(:,3:4), zeros (3,2));\n%! assert (s.df, 0);\n%! assert (mu, [2, 1]);\n\n%!test <*57964>\n%! ## Disable warnings entirely because there is not a specific ID to disable.\n%! wstate = warning ();\n%! unwind_protect\n%!   warning (\"off\", \"all\");\n%!   [p, s] = polyfit ([1,2], [3,4], 2);\n%! unwind_protect_cleanup\n%!   warning (wstate);\n%! end_unwind_protect\n%! assert (p, [1/3, 0, 8/3], 6*eps);\n%! assert (size (s.V), [2, 3]);\n%! assert (s.V(:,2), [0; 0]);\n%! assert (size (s.R), [2, 3]);\n%! assert (s.R(:,2), [0; 0]);\n%! assert (size (s.C), [2, 3]);\n%! assert (s.C(:,2), [0; 0]);\n\n## Verify Matlab-compatible return of upper powers\n%!test <*67296>\n%! wstate = warning ();\n%! unwind_protect\n%!   warning (\"off\", \"all\");\n%!   x = 1:3;\n%!   y = [0.9, 0.2, 0.3];\n%!   p3 = polyfit (x, y, 3);\n%!   p4 = polyfit (x, y, 4);\n%! unwind_protect_cleanup\n%!   warning (wstate);\n%! end_unwind_protect\n%! assert (p3, [0.1727, -0.6364, 0, 1.3636], 1e-4);\n%! assert (p4, [0.0824, -0.2765, 0, 0, 1.0941], 1e-4);\n\n## Verify Matlab-compatible corner case with only one output term\n%!test <*67296>\n%! wstate = warning ();\n%! unwind_protect\n%!   warning (\"off\", \"all\");\n%!   p = polyfit (1,2,3);\n%! unwind_protect_cleanup\n%!   warning (wstate);\n%! end_unwind_protect\n%! assert (p, [2 0 0 0]);\n\n## Test input validation\n%!error <Invalid call> polyfit ()\n%!error <Invalid call> polyfit (1)\n%!error <Invalid call> polyfit (1,2)\n%!error <X and Y must have the same number of points> polyfit ([1, 2], 1, 1)\n%!error <X and Y must have the same number of points> polyfit (1, [1, 2], 1)\n%!error <N must be a non-negative integer> polyfit (1, 2, [1,2])\n%!error <N must be a non-negative integer> polyfit (1, 2, -1)\n%!error <N must be a non-negative integer> polyfit (1, 2, Inf)\n%!error <N must be a non-negative integer> polyfit (1, 2, 1.5)\n%!test <*57964>\n%! fail (\"p = polyfit ([1,2], [3,4], 4)\", \"warning\", \"solution is not unique\");\n%!error <data points must be . 2 when scaling> [p,s,mu] = polyfit (1,2,3)\n%!error <data points must be . 2 when scaling>\n%! [p,s,mu] = polyfit ([1 2], [3 4], 3)\n"
  },
  {
    "path": "scripts/polynomial/polygcd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} polygcd (@var{b}, @var{a})\n## @deftypefnx {} {@var{q} =} polygcd (@var{b}, @var{a}, @var{tol})\n##\n## Find the greatest common divisor of two polynomials.\n##\n## This is equivalent to the polynomial found by multiplying together all the\n## common roots.  Together with deconv, you can reduce a ratio of two\n## polynomials.\n##\n## The tolerance @var{tol} defaults to @code{sqrt (eps)}.\n##\n## @strong{Caution:} This is a numerically unstable algorithm and should not\n## be used on large polynomials.\n##\n## Example code:\n##\n## @example\n## @group\n## polygcd (poly (1:8), poly (3:12)) - poly (3:8)\n## @xresult{} [ 0, 0, 0, 0, 0, 0, 0 ]\n## deconv (poly (1:8), polygcd (poly (1:8), poly (3:12))) - poly (1:2)\n## @xresult{} [ 0, 0, 0 ]\n## @end group\n## @end example\n## @seealso{poly, roots, conv, deconv, residue}\n## @end deftypefn\n\nfunction x = polygcd (b, a, tol)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (nargin == 2)\n    if (isa (a, \"single\") || isa (b, \"single\"))\n      tol = sqrt (eps (\"single\"));\n    else\n      tol = sqrt (eps);\n    endif\n  endif\n  ## FIXME: No input validation of tol if it was user-supplied\n\n\n  if (length (a) == 1 || length (b) == 1)\n    if (a == 0)\n      x = b;\n    elseif (b == 0)\n      x = a;\n    else\n      x = 1;\n    endif\n  else\n    a /= a(1);\n    while (1)\n      [d, r] = deconv (b, a);\n      nz = find (abs (r) > tol);\n      if (isempty (nz))\n        x = a;\n        break;\n      else\n        r = r(nz(1):length (r));\n      endif\n      b = a;\n      a = r / r(1);\n    endwhile\n  endif\n\nendfunction\n\n\n%!test\n%! poly1 = [1 6 11 6]; # (x+1)(x+2)(x+3);\n%! poly2 = [1 3 2];    # (x+1)(x+2);\n%! poly3 = polygcd (poly1, poly2);\n%! assert (poly3, poly2, sqrt (eps));\n\n%!assert (polygcd (poly (1:8), poly (3:12)), poly (3:8), sqrt (eps))\n%!assert (deconv (poly (1:8), polygcd (poly (1:8), poly (3:12))),\n%!        poly (1:2), sqrt (eps))\n\n%!test\n%! for ii=1:100\n%!   ## Exhibits numerical problems for multipliers of ~4 and greater.\n%!   p  = (unique (randn (10, 1)) * 3).';\n%!   p1 = p(3:end);\n%!   p2 = p(1:end-2);\n%!   assert (polygcd (poly (-p1), poly (-p2)),\n%!           poly (- intersect (p1, p2)), sqrt (eps));\n%! endfor\n"
  },
  {
    "path": "scripts/polynomial/polyint.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} polyint (@var{p})\n## @deftypefnx {} {@var{q} =} polyint (@var{p}, @var{k})\n## Return the coefficients of the integral of the polynomial whose\n## coefficients are represented by the vector @var{p}.\n##\n## The variable @var{k} is the constant of integration, which by default is\n## set to zero.\n## @seealso{polyder, polyval}\n## @end deftypefn\n\nfunction q = polyint (p, k)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    k = 0;\n  elseif (! isscalar (k))\n    error (\"polyint: the constant of integration must be a scalar\");\n  endif\n\n  if (! (isvector (p) || isempty (p)))\n    error (\"polyint: argument must be a vector\");\n  endif\n\n  lp = length (p);\n\n  if (lp == 0)\n    q = [];\n    return;\n  endif\n\n  if (rows (p) > 1)\n    ## Convert to column vector\n    p = p.';\n  endif\n\n  q = [(p ./ [lp:-1:1]), k];\n\nendfunction\n\n\n%!test\n%! A = [3, 2, 1];\n%! assert (polyint (A), polyint (A,0));\n%! assert (polyint (A), polyint (A'));\n%! assert (polyint (A), [1, 1, 1, 0]);\n%! assert (polyint (A,1), ones (1,4));\n\n%!test\n%! A = ones (1,8);\n%! B = [length(A):-1:1];\n%! assert (polyint (A), [1./B, 0]);\n\n%!error <Invalid call> polyint ()\n%!error polyint (ones (2,2))\n"
  },
  {
    "path": "scripts/polynomial/polyout.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} polyout (@var{c})\n## @deftypefnx {} {} polyout (@var{c}, @var{x})\n## @deftypefnx {} {@var{str} =} polyout (@dots{})\n## Display a formatted version of the polynomial @var{c}.\n##\n## The formatted polynomial\n## @tex\n## $$ c(x) = c_1 x^n + \\ldots + c_n x + c_{n+1} $$\n## @end tex\n## @ifnottex\n##\n## @example\n## c(x) = c(1) * x^n + @dots{} + c(n) x + c(n+1)\n## @end example\n##\n## @end ifnottex\n## is returned as a string or written to the screen if @code{nargout} is zero.\n##\n## The second argument @var{x} specifies the variable name to use for each term\n## and defaults to the string @qcode{\"s\"}.\n## @seealso{polyreduce}\n## @end deftypefn\n\nfunction str = polyout (c, x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isvector (c))\n    error (\"polyout: first argument must be a vector\");\n  endif\n\n  if (nargin == 1)\n    x = \"s\";\n  elseif (! ischar (x))\n    error (\"polyout: second argument must be a string\");\n  endif\n\n  n = length (c);\n  if (n > 0)\n    n1 = n+1;\n\n    s = coeff (c(1));\n    for i = 2:n\n      if (real (c(i)) < 0)\n        ns = \" - \";\n        c(i) = -c(i);\n      else\n        ns = \" + \";\n      endif\n\n      s = sprintf (\"%s*%s^%d%s%s\", s, x, n1-i, ns, coeff (c(i)));\n\n    endfor\n  else\n    s = \" \";\n  endif\n\n  if (nargout == 0)\n    disp (s);\n  else\n    str = s;\n  endif\n\nendfunction\n\nfunction str = coeff (c)\n\n  if (imag (c))\n    if (real (c))\n      str = sprintf (\"(%s)\", num2str (c, 5));\n    else\n      str = num2str (c, 5);\n    endif\n  else\n    str = num2str (c, 5);\n  endif\n\nendfunction\n\n\n%!assert (polyout ([3 2 1]), \"3*s^2 + 2*s^1 + 1\")\n%!assert (polyout ([3 2 1], \"x\"), \"3*x^2 + 2*x^1 + 1\")\n%!assert (polyout ([3 2 1], \"wxyz\"), \"3*wxyz^2 + 2*wxyz^1 + 1\")\n%!assert (polyout ([5 4 3 2 1], \"1\"),\"5*1^4 + 4*1^3 + 3*1^2 + 2*1^1 + 1\")\n\n%!error polyout ([])\n"
  },
  {
    "path": "scripts/polynomial/polyreduce.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{p} =} polyreduce (@var{c})\n## Reduce a polynomial coefficient vector to a minimum number of terms by\n## stripping off any leading zeros.\n## @seealso{polyout}\n## @end deftypefn\n\nfunction p = polyreduce (c)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! isvector (c) || isempty (c))\n    error (\"polyreduce: C must be a non-empty vector\");\n  endif\n\n  idx = find (c != 0, 1);\n\n  if (isempty (idx))\n    p = 0;\n  else\n    p = c(idx:end);\n  endif\n\nendfunction\n\n\n%!assert (polyreduce ([0, 0, 1, 2, 3]), [1, 2, 3])\n%!assert (polyreduce ([1, 2, 3, 0, 0]), [1, 2, 3, 0, 0])\n%!assert (polyreduce ([1, 0, 3]), [1, 0, 3])\n%!assert (polyreduce ([0, 0, 0]), 0)\n\n%!error <Invalid call> polyreduce ()\n%!error <C must be a non-empty vector> polyreduce ([1, 2; 3, 4])\n%!error <C must be a non-empty vector> polyreduce ([])\n"
  },
  {
    "path": "scripts/polynomial/polyval.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} polyval (@var{p}, @var{x})\n## @deftypefnx {} {@var{y} =} polyval (@var{p}, @var{x}, [], @var{mu})\n## @deftypefnx {} {[@var{y}, @var{dy}] =} polyval (@var{p}, @var{x}, @var{s})\n## @deftypefnx {} {[@var{y}, @var{dy}] =} polyval (@var{p}, @var{x}, @var{s}, @var{mu})\n##\n## Evaluate the polynomial @var{p} at the specified values of @var{x}.\n##\n## If @var{x} is a vector or matrix, the polynomial is evaluated for each of\n## the elements of @var{x}.\n##\n## When @var{mu} is present, evaluate the polynomial for\n## @w{(@var{x} - @var{mu}(1)) / @var{mu}(2)}.\n##\n## In addition to evaluating the polynomial, the second output represents the\n## prediction interval, @var{y} +/- @var{dy}, which contains at least 50% of\n## the future predictions.  To calculate the prediction interval, the\n## structured variable @var{s}, originating from @code{polyfit}, must be\n## supplied.\n##\n## @seealso{polyvalm, polyaffine, polyfit, roots, poly}\n## @end deftypefn\n\nfunction [y, dy] = polyval (p, x, s = [], mu)\n\n  if (nargin < 2 || (nargout == 2 && nargin < 3))\n    print_usage ();\n  endif\n\n  ## Algorithm requires floating point values\n  if (! isfloat (p) || (! isvector (p) && ! isempty (p)))\n    error (\"polyval: P must be a numeric floating point vector\");\n  endif\n  if (! isfloat (x))\n    error (\"polyval: X must be numeric floating point\");\n  endif\n\n  if (nargout > 1)\n    if (isempty (s))\n      error (\"polyval: S input is required for DY output argument\");\n    elseif (isstruct (s))\n      if (! all (ismember ({\"R\", \"normr\", \"df\"}, fieldnames (s))))\n        error (\"polyval: S input is missing required fields\");\n      endif\n    else\n      error (\"polyval: S input must be a structure\");\n    endif\n  endif\n\n  if (nargin == 4 && (! isfloat (mu) || numel (mu) < 2))\n    error (\"polyval: MU must be numeric floating point with 2 values\");\n  endif\n\n  if (isempty (p) || isempty (x))\n    if (isa (p, \"single\") || isa (x, \"single\"))\n      y = zeros (size (x), \"single\");\n    else\n      y = zeros (size (x));\n    endif\n    return;\n  endif\n\n  if (nargin == 4)\n    x = (x - mu(1)) / mu(2);\n  endif\n\n  n = numel (p) - 1;\n  y = p(1) * ones (size (x), class (x));\n  for i = 2:n+1\n    y = y .* x + p(i);\n  endfor\n\n  if (nargout > 1)\n    ## Note: the F-Distribution is generally considered to be single-sided.\n    ## http://www.itl.nist.gov/div898/handbook/eda/section3/eda3673.htm\n    ##   t = finv (1-alpha, s.df, s.df);\n    ##   dy = t * sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df)\n    ## If my inference is correct, then t must equal 1 for polyval.\n    ## This is because finv (0.5, n, n) = 1.0 for any n.\n    k = numel (x);\n    A = (x(:) * ones (1, n+1)) .^ (ones (k, 1) * (n:-1:0));\n    dy = sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df);\n    dy = reshape (dy, size (x));\n  endif\n\nendfunction\n\n\n%!test\n%! r = 0:10:50;\n%! p = poly (r);\n%! p = p / max (abs (p));\n%! x = linspace (0,50,11);\n%! y = polyval (p,x) + 0.25*sin (100*x);\n%! [pf, s] = polyfit (x, y, numel (r));\n%! [y1, delta] = polyval (pf, x, s);\n%! expected = [0.37235, 0.35854, 0.32231, 0.32448, 0.31328, ...\n%!             0.32036, 0.31328, 0.32448, 0.32231, 0.35854, 0.37235];\n%! assert (delta, expected, 0.00001);\n\n%!test\n%! x = 10 + (-2:2);\n%! y = [0, 0, 1, 0, 2];\n%! p = polyfit (x, y, numel (x) - 1);\n%! [pn, s, mu] = polyfit (x, y, numel (x) - 1);\n%! y1 = polyval (p, x);\n%! yn = polyval (pn, x, [], mu);\n%! assert (y1, y, sqrt (eps));\n%! assert (yn, y, sqrt (eps));\n\n%!test\n%! p = [0, 1, 0];\n%! x = 1:10;\n%! assert (x, polyval (p,x), eps);\n%! x = x(:);\n%! assert (x, polyval (p,x), eps);\n%! x = reshape (x, [2, 5]);\n%! assert (x, polyval (p,x), eps);\n%! x = reshape (x, [5, 2]);\n%! assert (x, polyval (p,x), eps);\n%! x = reshape (x, [1, 1, 5, 2]);\n%! assert (x, polyval (p,x), eps);\n\n%!test\n%! p = [1];\n%! x = 1:10;\n%! y = ones (size (x));\n%! assert (y, polyval (p,x), eps);\n%! x = x(:);\n%! y = ones (size (x));\n%! assert (y, polyval (p,x), eps);\n%! x = reshape (x, [2, 5]);\n%! y = ones (size (x));\n%! assert (y, polyval (p,x), eps);\n%! x = reshape (x, [5, 2]);\n%! y = ones (size (x));\n%! assert (y, polyval (p,x), eps);\n%! x = reshape (x, [1, 1, 5, 2]);\n\n## Test empty combinations\n%!assert (polyval ([], 1:10), zeros (1, 10))\n%!assert (class (polyval (single ([]), 1:10)), \"single\")\n%!assert (class (polyval ([], single (1:10))), \"single\")\n%!assert (polyval (1, []), [])\n%!assert (polyval ([], []), [])\n%!assert (polyval (1, zeros (0,3)), zeros (0, 3))\n%!assert (class (polyval (single (1), [])), \"single\")\n%!assert (class (polyval (1, single ([]))), \"single\")\n%!assert (class (polyval (single ([]), [])), \"single\")\n%!assert (class (polyval ([], single ([]))), \"single\")\n\n## Test input validation\n%!error <Invalid call> polyval ()\n%!error <Invalid call> polyval (1)\n%!error <Invalid call> [y, dy] = polyval (1, 2)\n%!error <P must be a numeric floating point vector> polyval ({1, 0}, 0:10)\n%!error <P must be a numeric floating point vector> polyval (int8 ([1]), 0:10)\n%!error <P must be a numeric floating point vector> polyval ([1,0;0,1], 0:10)\n%!error <X must be numeric floating point> polyval ([1,0], {0:10})\n%!error <X must be numeric floating point> polyval ([1,0], int8 (0:10))\n%!error <S input is required> [y, dy] = polyval (1, 1, [])\n%!error <S input is missing required fields>\n%! [y, dy] = polyval (1, 1, struct (\"T\", 0, \"normr\", 1, \"df\", 2));\n%!error <S input must be a structure> [y, dy] = polyval (1, 1, 2)\n%!error <MU must be numeric floating point with 2 values>\n%! polyval (1, 1, [], {1, 2});\n%!error <MU must be numeric floating point with 2 values>\n%! polyval (1, 1, [], int8 ([1,2]));\n%!error <MU must be numeric floating point with 2 values>\n%! polyval (1, 1, [], [1]);\n"
  },
  {
    "path": "scripts/polynomial/polyvalm.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} polyvalm (@var{c}, @var{x})\n## Evaluate a polynomial in the matrix sense.\n##\n## @code{polyvalm (@var{c}, @var{x})} will evaluate the polynomial in the\n## matrix sense, i.e., matrix multiplication is used instead of element by\n## element multiplication as used in @code{polyval}.\n##\n## The argument @var{x} must be a square matrix.\n## @seealso{polyval, roots, poly}\n## @end deftypefn\n\nfunction y = polyvalm (c, x)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! (isvector (c) || isempty (c)))\n    error (\"polyvalm: first argument must be a vector\");\n  endif\n\n  if (! issquare (x))\n    error (\"polyvalm: second argument must be a square matrix\");\n  endif\n\n  n = length (c);\n  if (n == 0)\n    y = zeros (rows (x), class (x));\n  else\n    id = eye (rows (x), class (x));\n    y = c(1) * id;\n    for i = 2:n\n      y = y * x + c(i) * id;\n    endfor\n  endif\n\nendfunction\n\n\n%!assert (! any (polyvalm ([], [1, 2; 3, 4]))(:))\n%!assert (polyvalm ([1, 2, 3, 4], [3, -4, 1; -2, 0, 2; -1, 4, -3]),\n%!        [117, -124, 11; -70, 36, 38; -43, 92, -45])\n\n%!error <must be a square matrix> polyvalm ([1, 1, 1], [1, 2; 3, 4; 5, 6])\n"
  },
  {
    "path": "scripts/polynomial/ppder.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {ppd =} ppder (pp)\n## @deftypefnx {} {ppd =} ppder (pp, m)\n## Compute the piecewise @var{m}-th derivative of a piecewise polynomial\n## struct @var{pp}.\n##\n## If @var{m} is omitted the first derivative is calculated.\n## @seealso{mkpp, ppval, ppint}\n## @end deftypefn\n\nfunction ppd = ppder (pp, m = 1)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isstruct (pp) && strcmp (pp.form, \"pp\")))\n    error (\"ppder: PP must be a structure\");\n  endif\n\n  [x, p, n, k, d] = unmkpp (pp);\n\n  if (k - m <= 0)\n    x = [x(1) x(end)];\n    pd = zeros (prod (d), 1);\n  else\n    f = k : -1 : 1;\n    ff = bincoeff (f, m + 1) .* factorial (m + 1) ./ f;\n    k -= m;\n    pd = p(:,1:k) * diag (ff(1:k));\n  endif\n\n  ppd = mkpp (x, pd, d);\n\nendfunction\n\n\n%!shared x,y,pp,ppd\n%! x = 0:8;\n%! y = [x.^2; x.^3+1];\n%! pp = spline (x, y);\n%! ppd = ppder (pp);\n%!assert (ppval (ppd, x), [2*x; 3*x.^2], 1e-14)\n%!assert (ppd.order, 3)\n%! ppd = ppder (pp, 2);\n%!assert (ppval (ppd, x), [2*ones(size (x)); 6*x], 1e-14)\n%!assert (ppd.order, 2)\n%! ppd = ppder (pp, 3);\n%!assert (ppd.order, 1)\n%!assert (ppd.pieces, 8)\n%!assert (size (ppd.coefs), [16, 1])\n%! ppd = ppder (pp, 4);\n%!assert (ppd.order, 1)\n%!assert (ppd.pieces, 1)\n%!assert (size (ppd.coefs), [2, 1])\n%!assert (ppval (ppd,x), zeros (size (y)), 1e-14)\n"
  },
  {
    "path": "scripts/polynomial/ppint.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{ppi} =} ppint (@var{pp})\n## @deftypefnx {} {@var{ppi} =} ppint (@var{pp}, @var{c})\n## Compute the integral of the piecewise polynomial struct @var{pp}.\n##\n## @var{c}, if given, is the constant of integration.\n## @seealso{mkpp, ppval, ppder}\n## @end deftypefn\n\nfunction ppi = ppint (pp, c)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n  if (! (isstruct (pp) && strcmp (pp.form, \"pp\")))\n    error (\"ppint: PP must be a structure\");\n  endif\n\n  [x, p, n, k, d] = unmkpp (pp);\n  p = reshape (p, [], k);\n\n  ## Get piecewise antiderivatives\n  pi = p / diag (k:-1:1);\n  k += 1;\n  if (nargin == 1)\n    pi(:, k) = 0;\n  else\n    pi(:, k) = repmat (c(:), n, 1);\n  endif\n\n  ppi = mkpp (x, pi, d);\n\n  tmp = -cumsum (ppjumps (ppi), length (d) + 1);\n  ppi.coefs(prod (d)+1 : end, k) = tmp(:);\n\nendfunction\n\n\n%!shared x,y,pp,ppi\n%! x = 0:8;\n%! y = [ ones(size(x)); x+1 ];\n%! pp = spline (x, y);\n%! ppi = ppint (pp);\n%!assert (ppval (ppi, x), [x; 0.5*x.^2 + x], 1e-14)\n%!assert (ppi.order, 5)\n"
  },
  {
    "path": "scripts/polynomial/ppjumps.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{jumps} =} ppjumps (@var{pp})\n## Evaluate the boundary jumps of a piecewise polynomial.\n##\n## If there are @math{n} intervals, and the dimensionality of @var{pp} is\n## @math{d}, the resulting array has dimensions @code{[d, n-1]}.\n## @seealso{mkpp}\n## @end deftypefn\n\nfunction jumps = ppjumps (pp)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isstruct (pp) && strcmp (pp.form, \"pp\")))\n    error (\"ppjumps: PP must be a structure\");\n  endif\n\n  ## Extract info.\n  [x, P, n, k, d] = unmkpp (pp);\n  nd = length (d) + 1;\n\n  ## Offsets.\n  dx = diff (x(1:n));\n  dx = repmat (dx, [prod(d), 1]);\n  dx = reshape (dx, [d, n-1]);\n  dx = shiftdim (dx, nd - 1);\n\n  ## Use Horner scheme.\n  if (k>1)\n    llim = shiftdim (reshape (P(1:(n-1) * prod (d), 1), [d, n-1]), nd - 1);\n  endif\n\n  for i = 2 : k\n    llim .*= dx;\n    llim += shiftdim (reshape (P(1:(n-1) * prod (d), i), [d, n-1]), nd - 1);\n  endfor\n\n  rlim = shiftdim (ppval (pp, x(2:end-1)), nd - 1);\n  jumps = shiftdim (rlim - llim, 1);\n\nendfunction\n\n\n%!test\n%! p = [1 6 11 6];\n%! x = linspace (5, 6, 4);\n%! y = polyval (p, x);\n%! pp = spline (x, y);\n%! jj = ppjumps (pp);\n%! assert (jj, [0 0], eps);\n\n%!test\n%! breaks = [0 1 2];\n%! pp1 = poly (-[1 2 3]);\n%! pp2 = poly (-([1 2 3]+1));\n%! pp = mkpp (breaks, [pp1;pp2]);\n%! assert (ppjumps (pp), 0, eps);\n\n%!test\n%! breaks = [0 1 2];\n%! pp1 = poly (-[1 2 3]);\n%! pp2 = poly (([1 2 3]+1));\n%! pp = mkpp (breaks, [pp1;pp2]);\n%! j  = - 2 * polyval (pp1, 1);\n%! assert (ppjumps (pp), j, eps);\n"
  },
  {
    "path": "scripts/polynomial/ppval.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{yi} =} ppval (@var{pp}, @var{xi})\n## Evaluate the piecewise polynomial structure @var{pp} at the points @var{xi}.\n##\n## If @var{pp} describes a scalar polynomial function, the result is an array\n## of the same shape as @var{xi}.  Otherwise, the size of the result is\n## @code{[pp.dim, length(@var{xi})]} if @var{xi} is a vector, or\n## @code{[pp.dim, size(@var{xi})]} if it is a multi-dimensional array.\n## @seealso{mkpp, unmkpp, spline, pchip}\n## @end deftypefn\n\nfunction yi = ppval (pp, xi)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n  if (! (isstruct (pp) && isfield (pp, \"form\") && strcmp (pp.form, \"pp\")))\n    error (\"ppval: first argument must be a pp-form structure\");\n  endif\n\n  ## Extract info.\n  [x, P, n, k, d] = unmkpp (pp);\n\n  ## dimension checks\n  sxi = size (xi);\n  if (isvector (xi))\n    xi = xi(:).';\n  endif\n\n  nd = length (d);\n\n  ## Determine intervals.\n  xn = numel (xi);\n  idx = lookup (x, xi, \"lr\");\n\n  P = reshape (P, [d, n * k]);\n  P = shiftdim (P, nd);\n  P = reshape (P, [n, k, d]);\n  Pidx = P(idx(:), :);  # 2-D matrix size: x = coefs*prod (d), y = prod (sxi)\n\n  if (isvector (xi))\n    Pidx = reshape (Pidx, [xn, k, d]);\n    Pidx = shiftdim (Pidx, 1);\n    dimvec = [d, xn];\n  else\n    Pidx = reshape (Pidx, [sxi, k, d]);\n    Pidx = shiftdim (Pidx, length (sxi));\n    dimvec = [d, sxi];\n  endif\n  ndv = length (dimvec);\n\n  ## Offsets.\n  dx = (xi - x(idx))(:)';\n  dx = repmat (dx, [prod(d), 1]);\n  dx = reshape (dx, dimvec);\n  dx = shiftdim (dx, ndv - 1);\n\n  ## Use Horner scheme.\n  if (k > 1)\n    yi = shiftdim (reshape (Pidx(1,:), dimvec), ndv - 1);\n  else\n    yi = shiftdim (reshape (Pidx, dimvec), ndv - 1);\n  endif\n\n  for i = 2 : k\n    yi .*= dx;\n    yi += shiftdim (reshape (Pidx(i,:), dimvec), ndv - 1);\n  endfor\n\n  ## Adjust shape.\n  if ((numel (xi) > 1) || (length (d) == 1))\n    yi = reshape (shiftdim (yi, 1), dimvec);\n  endif\n\n  if (isvector (xi) && (d == 1))\n    yi = reshape (yi, sxi);\n  elseif (isfield (pp, \"orient\") && strcmp (pp.orient, \"first\"))\n    yi = shiftdim (yi, nd);\n  endif\n\n  if (d == 1)\n    yi = reshape (yi, sxi);\n  endif\n\nendfunction\n\n\n%!shared b, c, pp, pp2, xi, abserr\n%! b = 1:3;\n%! c = ones (2);\n%! pp = mkpp (b, c);\n%! abserr = 1e-14;\n%! pp2 = mkpp (b, [c;c], 2);\n%! xi = [1.1 1.3 1.9 2.1];\n%!\n%!assert (ppval (pp, 1.1), 1.1, abserr)\n%!assert (ppval (pp, 2.1), 1.1, abserr)\n%!assert (ppval (pp, xi), [1.1 1.3 1.9 1.1], abserr)\n%!assert (ppval (pp, xi.'), [1.1 1.3 1.9 1.1].', abserr)\n%!assert (ppval (pp2, 1.1), [1.1;1.1], abserr)\n%!assert (ppval (pp2, 2.1), [1.1;1.1], abserr)\n%!assert (ppval (pp2, xi), [1.1 1.3 1.9 1.1;1.1 1.3 1.9 1.1], abserr)\n%!assert (ppval (pp2, xi'), [1.1 1.3 1.9 1.1;1.1 1.3 1.9 1.1], abserr)\n%!assert (size (ppval (pp2, [xi;xi])), [2 2 4])\n%!assert (ppval (mkpp([0 1],1), magic (3)), ones(3,3))\n%!\n%!test\n%! breaks = [0, 1, 2, 3];\n%! coefs = rand (6, 4);\n%! pp = mkpp (breaks, coefs, 2);\n%! ret = zeros (2, 4, 2);\n%! ret(:,:,1) = ppval (pp, breaks');\n%! ret(:,:,2) = ppval (pp, breaks');\n%! assert (ppval (pp, [breaks',breaks']), ret);\n\n## Test input validation\n%!error <Invalid call> ppval ()\n%!error <Invalid call> ppval (1)\n%!error <argument must be a pp-form structure> ppval (1,2)\n%!error <argument must be a pp-form structure> ppval (struct (\"a\", 1), 2)\n%!error <argument must be a pp-form structure> ppval (struct (\"form\", \"ab\"), 2)\n"
  },
  {
    "path": "scripts/polynomial/private/__splinefit__.m",
    "content": "## This function is private because it is maintained by Jonas Lundgren\n## separately from Octave.  Please do not reformat to match Octave coding\n## conventions as that would make it harder to integrate upstream changes.\n\n% Copyright (c) 2010, Jonas Lundgren\n% All rights reserved.\n%\n% Redistribution and use in source and binary forms, with or without\n% modification, are permitted provided that the following conditions are\n% met:\n%\n%     * Redistributions of source code must retain the above copyright\n%       notice, this list of conditions and the following disclaimer.\n%     * Redistributions in binary form must reproduce the above copyright\n%       notice, this list of conditions and the following disclaimer in\n%       the documentation and/or other materials provided with the distribution\n%\n% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n% POSSIBILITY OF SUCH DAMAGE.\nfunction pp = __splinefit__(varargin)\n%SPLINEFIT Fit a spline to noisy data.\n%   PP = SPLINEFIT(X,Y,BREAKS) fits a piecewise cubic spline with breaks\n%   (knots) BREAKS to the noisy data (X,Y). X is a vector and Y is a vector\n%   or an ND array. If Y is an ND array, then X(j) and Y(:,...,:,j) are\n%   matched. Use PPVAL to evaluate PP.\n%\n%   PP = SPLINEFIT(X,Y,P) where P is a positive integer interpolates the\n%   breaks linearly from the sorted locations of X. P is the number of\n%   spline pieces and P+1 is the number of breaks.\n%\n%   OPTIONAL INPUT\n%   Argument places 4 to 8 are reserved for optional input.\n%   These optional arguments can be given in any order:\n%\n%   PP = SPLINEFIT(...,'p') applies periodic boundary conditions to\n%   the spline. The period length is MAX(BREAKS)-MIN(BREAKS).\n%\n%   PP = SPLINEFIT(...,'r') uses robust fitting to reduce the influence\n%   from outlying data points. Three iterations of weighted least squares\n%   are performed. Weights are computed from previous residuals.\n%\n%   PP = SPLINEFIT(...,BETA), where 0 < BETA < 1, sets the robust fitting\n%   parameter BETA and activates robust fitting ('r' can be omitted).\n%   Default is BETA = 1/2. BETA close to 0 gives all data equal weighting.\n%   Increase BETA to reduce the influence from outlying data. BETA close\n%   to 1 may cause instability or rank deficiency.\n%\n%   PP = SPLINEFIT(...,N) sets the spline order to N. Default is a cubic\n%   spline with order N = 4. A spline with P pieces has P+N-1 degrees of\n%   freedom. With periodic boundary conditions the degrees of freedom are\n%   reduced to P.\n%\n%   PP = SPLINEFIT(...,CON) applies linear constraints to the spline.\n%   CON is a structure with fields 'xc', 'yc' and 'cc':\n%       'xc', x-locations (vector)\n%       'yc', y-values (vector or ND array)\n%       'cc', coefficients (matrix).\n%\n%   Constraints are linear combinations of derivatives of order 0 to N-2\n%   according to\n%\n%     cc(1,j)*y(x) + cc(2,j)*y'(x) + ... = yc(:,...,:,j),  x = xc(j).\n%\n%   The maximum number of rows for 'cc' is N-1. If omitted or empty 'cc'\n%   defaults to a single row of ones. Default for 'yc' is a zero array.\n%\n%   EXAMPLES\n%\n%       % Noisy data\n%       x = linspace(0,2*pi,100);\n%       y = sin(x) + 0.1*randn(size(x));\n%       % Breaks\n%       breaks = [0:5,2*pi];\n%\n%       % Fit a spline of order 5\n%       pp = splinefit(x,y,breaks,5);\n%\n%       % Fit a spline of order 3 with periodic boundary conditions\n%       pp = splinefit(x,y,breaks,3,'p');\n%\n%       % Constraints: y(0) = 0, y'(0) = 1 and y(3) + y\"(3) = 0\n%       xc = [0 0 3];\n%       yc = [0 1 0];\n%       cc = [1 0 1; 0 1 0; 0 0 1];\n%       con = struct('xc',xc,'yc',yc,'cc',cc);\n%\n%       % Fit a cubic spline with 8 pieces and constraints\n%       pp = splinefit(x,y,8,con);\n%\n%       % Fit a spline of order 6 with constraints and periodicity\n%       pp = splinefit(x,y,breaks,con,6,'p');\n%\n%   See also SPLINE, PPVAL, PPDIFF, PPINT\n\n%   2009-05-06  Original SPLINEFIT.\n%   2010-06-23  New version of SPLINEFIT based on B-splines.\n%   2010-09-01  Robust fitting scheme added.\n%   2010-09-01  Support for data containing NaNs.\n%   2011-07-01  Robust fitting parameter added.\n\n% Check number of arguments\nnarginchk(3,7);\n\n% Check arguments\n[x,y,dim,breaks,n,periodic,beta,constr] = arguments(varargin{:});\n\n% Evaluate B-splines\nbase = splinebase(breaks,n);\npieces = base.pieces;\nA = ppval(base,x);\n\n% Bin data\n[junk,ibin] = histc(x,[-inf,breaks(2:end-1),inf]); %#ok\n\n% Sparse system matrix\nmx = numel(x);\nii = [ibin; ones(n-1,mx)];\nii = cumsum(ii,1);\njj = repmat(1:mx,n,1);\nif periodic\n    ii = mod(ii-1,pieces) + 1;\n    A = sparse(ii,jj,A,pieces,mx);\nelse\n    A = sparse(ii,jj,A,pieces+n-1,mx);\nend\n\n% Don't use the sparse solver for small problems\nif pieces < 20*n/log(1.7*n)\n    A = full(A);\nend\n\n% Solve\nif isempty(constr)\n    % Solve Min norm(u*A-y)\n    u = lsqsolve(A,y,beta);\nelse\n    % Evaluate constraints\n    B = evalcon(base,constr,periodic);\n    % Solve constraints\n    [Z,u0] = solvecon(B,constr);\n    % Solve Min norm(u*A-y), subject to u*B = yc\n    y -= u0*A;\n    A = Z*A;\n    v = lsqsolve(A,y,beta);\n    u = u0 + v*Z;\nend\n\n% Periodic expansion of solution\nif periodic\n    jj = mod(0:pieces+n-2,pieces) + 1;\n    u = u(:,jj);\nend\n\n% Compute polynomial coefficients\nii = [repmat(1:pieces,1,n); ones(n-1,n*pieces)];\nii = cumsum(ii,1);\njj = repmat(1:n*pieces,n,1);\nC = sparse(ii,jj,base.coefs,pieces+n-1,n*pieces);\ncoefs = u*C;\ncoefs = reshape(coefs,[],n);\n\n% Make piecewise polynomial\npp = mkpp(breaks,coefs,dim);\n\n\n%--------------------------------------------------------------------------\nfunction [x,y,dim,breaks,n,periodic,beta,constr] = arguments(varargin)\n%ARGUMENTS Lengthy input checking\n%   x           Noisy data x-locations (1 x mx)\n%   y           Noisy data y-values (prod(dim) x mx)\n%   dim         Leading dimensions of y\n%   breaks      Breaks (1 x (pieces+1))\n%   n           Spline order\n%   periodic    True if periodic boundary conditions\n%   beta        Robust fitting parameter, no robust fitting if beta = 0\n%   constr      Constraint structure\n%   constr.xc   x-locations (1 x nx)\n%   constr.yc   y-values (prod(dim) x nx)\n%   constr.cc   Coefficients (?? x nx)\n\n% Reshape x-data\nx = varargin{1};\nmx = numel(x);\nx = reshape(x,1,mx);\n\n% Remove trailing singleton dimensions from y\ny = varargin{2};\ndim = size(y);\nwhile numel(dim) > 1 && dim(end) == 1\n    dim(end) = [];\nend\nmy = dim(end);\n\n% Leading dimensions of y\nif numel(dim) > 1\n    dim(end) = [];\nelse\n    dim = 1;\nend\n\n% Reshape y-data\npdim = prod(dim);\ny = reshape(y,pdim,my);\n\n% Check data size\nif mx ~= my\n    mess = 'Last dimension of array y must equal length of vector x.';\n    error('arguments:datasize',mess)\nend\n\n% Treat NaNs in x-data\ninan = find(isnan(x));\nif ~isempty(inan)\n    x(inan) = [];\n    y(:,inan) = [];\n    mess = 'All data points with NaN as x-location will be ignored.';\n    warning('arguments:nanx',mess)\nend\n\n% Treat NaNs in y-data\ninan = find(any(isnan(y),1));\nif ~isempty(inan)\n    x(inan) = [];\n    y(:,inan) = [];\n    mess = 'All data points with NaN in their y-value will be ignored.';\n    warning('arguments:nany',mess)\nend\n\n% Check number of data points\nmx = numel(x);\nif mx == 0\n    error('arguments:nodata','There must be at least one data point.')\nend\n\n% Sort data\nif any(diff(x) < 0)\n    [x,isort] = sort(x);\n    y = y(:,isort);\nend\n\n% Breaks\nif isscalar(varargin{3})\n    % Number of pieces\n    p = varargin{3};\n    if ~isreal(p) || ~isfinite(p) || p < 1 || fix(p) < p\n        mess = 'Argument #3 must be a vector or a positive integer.';\n        error('arguments:breaks1',mess)\n    end\n    if x(1) < x(end)\n        % Interpolate breaks linearly from x-data\n        dx = diff(x);\n        ibreaks = linspace(1,mx,p+1);\n        [junk,ibin] = histc(ibreaks,[0,2:mx-1,mx+1]); %#ok\n        breaks = x(ibin) + dx(ibin).*(ibreaks-ibin);\n    else\n        breaks = x(1) + linspace(0,1,p+1);\n    end\nelse\n    % Vector of breaks\n    breaks = reshape(varargin{3},1,[]);\n    if isempty(breaks) || min(breaks) == max(breaks)\n        mess = 'At least two unique breaks are required.';\n        error('arguments:breaks2',mess);\n    end\nend\n\n% Unique breaks\nif any(diff(breaks) <= 0)\n    breaks = unique(breaks);\nend\n\n% Optional input defaults\nn = 4;                      % Cubic splines\nperiodic = false;           % No periodic boundaries\nrobust = false;             % No robust fitting scheme\nbeta = 0.5;                 % Robust fitting parameter\nconstr = [];                % No constraints\n\n% Loop over optional arguments\nfor k = 4:nargin\n    a = varargin{k};\n    if ischar(a) && isscalar(a) && lower(a) == 'p'\n        % Periodic conditions\n        periodic = true;\n    elseif ischar(a) && isscalar(a) && lower(a) == 'r'\n        % Robust fitting scheme\n        robust = true;\n    elseif isreal(a) && isscalar(a) && isfinite(a) && a > 0 && a < 1\n        % Robust fitting parameter\n        beta = a;\n        robust = true;\n    elseif isreal(a) && isscalar(a) && isfinite(a) && a > 0 && fix(a) == a\n        % Spline order\n        n = a;\n    elseif isstruct(a) && isscalar(a)\n        % Constraint structure\n        constr = a;\n    else\n        error('arguments:nonsense','Failed to interpret argument #%d.',k)\n    end\nend\n\n% No robust fitting\nif ~robust\n    beta = 0;\nend\n\n% Check exterior data\nh = diff(breaks);\nxlim1 = breaks(1) - 0.01*h(1);\nxlim2 = breaks(end) + 0.01*h(end);\nif x(1) < xlim1 || x(end) > xlim2\n    if periodic\n        % Move data inside domain\n        P = breaks(end) - breaks(1);\n        x = mod(x-breaks(1),P) + breaks(1);\n        % Sort\n        [x,isort] = sort(x);\n        y = y(:,isort);\n    else\n        mess = 'Some data points are outside the spline domain.';\n        warning('arguments:exteriordata',mess)\n    end\nend\n\n% Return\nif isempty(constr)\n    return;\nend\n\n% Unpack constraints\nxc = [];\nyc = [];\ncc = [];\nnames = fieldnames(constr);\nfor k = 1:numel(names)\n    switch names{k}\n        case {'xc'}\n            xc = constr.xc;\n        case {'yc'}\n            yc = constr.yc;\n        case {'cc'}\n            cc = constr.cc;\n        otherwise\n            mess = 'Unknown field ''%s'' in constraint structure.';\n            warning('arguments:unknownfield',mess,names{k})\n    end\nend\n\n% Check xc\nif isempty(xc)\n    mess = 'Constraints contains no x-locations.';\n    error('arguments:emptyxc',mess)\nelse\n    nx = numel(xc);\n    xc = reshape(xc,1,nx);\nend\n\n% Check yc\nif isempty(yc)\n    % Zero array\n    yc = zeros(pdim,nx);\nelseif numel(yc) == 1\n    % Constant array\n    yc = zeros(pdim,nx) + yc;\nelseif numel(yc) ~= pdim*nx\n    % Malformed array\n    error('arguments:ycsize','Cannot reshape yc to size %dx%d.',pdim,nx)\nelse\n    % Reshape array\n    yc = reshape(yc,pdim,nx);\nend\n\n% Check cc\nif isempty(cc)\n    cc = ones(size(xc));\nelseif numel(size(cc)) ~= 2\n    error('arguments:ccsize1','Constraint coefficients cc must be 2-D.')\nelseif size(cc,2) ~= nx\n    mess = 'Last dimension of cc must equal length of xc.';\n    error('arguments:ccsize2',mess)\nend\n\n% Check high order derivatives\nif size(cc,1) >= n\n    if any(any(cc(n:end,:)))\n        mess = 'Constraints involve derivatives of order %d or larger.';\n        error('arguments:difforder',mess,n-1)\n    end\n    cc = cc(1:n-1,:);\nend\n\n% Check exterior constraints\nif min(xc) < xlim1 || max(xc) > xlim2\n    if periodic\n        % Move constraints inside domain\n        P = breaks(end) - breaks(1);\n        xc = mod(xc-breaks(1),P) + breaks(1);\n    else\n        mess = 'Some constraints are outside the spline domain.';\n        warning('arguments:exteriorconstr',mess)\n    end\nend\n\n% Pack constraints\nconstr = struct('xc',xc,'yc',yc,'cc',cc);\n\n\n%--------------------------------------------------------------------------\nfunction pp = splinebase(breaks,n)\n%SPLINEBASE Generate B-spline base PP of order N for breaks BREAKS\n\nbreaks = breaks(:);     % Breaks\nbreaks0 = breaks';      % Initial breaks\nh = diff(breaks);       % Spacing\npieces = numel(h);      % Number of pieces\ndeg = n - 1;            % Polynomial degree\n\n% Extend breaks periodically\nif deg > 0\n    if deg <= pieces\n        hcopy = h;\n    else\n        hcopy = repmat(h,ceil(deg/pieces),1);\n    end\n    % to the left\n    hl = hcopy(end:-1:end-deg+1);\n    bl = breaks(1) - cumsum(hl);\n    % and to the right\n    hr = hcopy(1:deg);\n    br = breaks(end) + cumsum(hr);\n    % Add breaks\n    breaks = [bl(deg:-1:1); breaks; br];\n    h = diff(breaks);\n    pieces = numel(h);\nend\n\n% Initiate polynomial coefficients\ncoefs = zeros(n*pieces,n);\ncoefs(1:n:end,1) = 1;\n\n% Expand h\nii = [1:pieces; ones(deg,pieces)];\nii = cumsum(ii,1);\nii = min(ii,pieces);\nH = h(ii(:));\n\n% Recursive generation of B-splines\nfor k = 2:n\n    % Antiderivatives of splines\n    for j = 1:k-1\n        coefs(:,j) = coefs(:,j).*H/(k-j);\n    end\n    Q = sum(coefs,2);\n    Q = reshape(Q,n,pieces);\n    Q = cumsum(Q,1);\n    c0 = [zeros(1,pieces); Q(1:deg,:)];\n    coefs(:,k) = c0(:);\n    % Normalize antiderivatives by max value\n    fmax = repmat(Q(n,:),n,1);\n    fmax = fmax(:);\n    for j = 1:k\n        coefs(:,j) = coefs(:,j)./fmax;\n    end\n    % Diff of adjacent antiderivatives\n    coefs(1:end-deg,1:k) = coefs(1:end-deg,1:k) - coefs(n:end,1:k);\n    coefs(1:n:end,k) = 0;\nend\n\n% Scale coefficients\nscale = ones(size(H));\nfor k = 1:n-1\n    scale = scale./H;\n    coefs(:,n-k) = scale.*coefs(:,n-k);\nend\n\n% Reduce number of pieces\npieces -= 2*deg;\n\n% Sort coefficients by interval number\nii = [n*(1:pieces); deg*ones(deg,pieces)];\nii = cumsum(ii,1);\ncoefs = coefs(ii(:),:);\n\n% Make piecewise polynomial\npp = mkpp(breaks0,coefs,n);\n\n\n%--------------------------------------------------------------------------\nfunction B = evalcon(base,constr,periodic)\n%EVALCON Evaluate linear constraints\n\n% Unpack structures\nbreaks = base.breaks;\npieces = base.pieces;\nn = base.order;\nxc = constr.xc;\ncc = constr.cc;\n\n% Bin data\n[junk,ibin] = histc(xc,[-inf,breaks(2:end-1),inf]); %#ok\n\n% Evaluate constraints\nnx = numel(xc);\nB0 = zeros(n,nx);\nfor k = 1:size(cc,1)\n    if any(cc(k,:))\n        B0 += repmat(cc(k,:),n,1).*ppval(base,xc);\n    end\n    % Differentiate base\n    coefs = base.coefs(:,1:n-k);\n    for j = 1:n-k-1\n        coefs(:,j) = (n-k-j+1)*coefs(:,j);\n    end\n    base.coefs = coefs;\n    base.order = n-k;\nend\n\n% Sparse output\nii = [ibin; ones(n-1,nx)];\nii = cumsum(ii,1);\njj = repmat(1:nx,n,1);\nif periodic\n    ii = mod(ii-1,pieces) + 1;\n    B = sparse(ii,jj,B0,pieces,nx);\nelse\n    B = sparse(ii,jj,B0,pieces+n-1,nx);\nend\n\n\n%--------------------------------------------------------------------------\nfunction [Z,u0] = solvecon(B,constr)\n%SOLVECON Find a particular solution u0 and null space Z (Z*B = 0)\n%         for constraint equation u*B = yc.\n\nyc = constr.yc;\ntol = 1000*eps;\n\n% Remove blank rows\nii = any(B,2);\nB2 = full(B(ii,:));\n\n% Null space of B2\nif isempty(B2)\n    Z2 = [];\nelse\n    % QR decomposition with column permutation\n    [Q,R,dummy] = qr(B2); %#ok\n    R = abs(R);\n    jj = all(R < R(1)*tol, 2);\n    Z2 = Q(:,jj)';\nend\n\n% Sizes\n[m,ncon] = size(B);\nm2 = size(B2,1);\nnz = size(Z2,1);\n\n% Sparse null space of B\nZ = sparse(nz+1:nz+m-m2,find(~ii),1,nz+m-m2,m);\nZ(1:nz,ii) = Z2;\n\n% Warning rank deficient\nif nz + ncon > m2\n\tmess = 'Rank deficient constraints, rank = %d.';\n\twarning('solvecon:deficient',mess,m2-nz);\nend\n\n% Particular solution\nu0 = zeros(size(yc,1),m);\nif any(yc(:))\n    % Non-homogeneous case\n\tu0(:,ii) = yc/B2;\n    % Check solution\n\tif norm(u0*B - yc,'fro') > norm(yc,'fro')*tol\n        mess = 'Inconsistent constraints. No solution within tolerance.';\n        error('solvecon:inconsistent',mess)\n\tend\nend\n\n\n%--------------------------------------------------------------------------\nfunction u = lsqsolve(A,y,beta)\n%LSQSOLVE Solve Min norm(u*A-y)\n\n% Avoid sparse-complex limitations\nif issparse(A) && ~isreal(y)\n    A = full(A);\nend\n\n% Solution\nu = y/A;\n\n% Robust fitting\nif beta > 0\n    [m,n] = size(y);\n    alpha = 0.5*beta/(1-beta)/m;\n    for k = 1:3\n        % Residual\n        r = u*A - y;\n        rr = r.*conj(r);\n        rrmean = sum(rr,2)/n;\n        rrmean(~rrmean) = 1;\n        rrhat = (alpha./rrmean)'*rr;\n        % Weights\n        w = exp(-rrhat);\n        spw = spdiags(w',0,n,n);\n        % Solve weighted problem\n        u = (y*spw)/(A*spw);\n    end\nend\n"
  },
  {
    "path": "scripts/polynomial/residue.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{r}, @var{p}, @var{k}, @var{e}] =} residue (@var{b}, @var{a})\n## @deftypefnx {} {[@var{b}, @var{a}] =} residue (@var{r}, @var{p}, @var{k})\n## @deftypefnx {} {[@var{b}, @var{a}] =} residue (@var{r}, @var{p}, @var{k}, @var{e})\n## The first calling form computes the partial fraction expansion for the\n## quotient of the polynomials, @var{b} and @var{a}.\n##\n## The quotient is defined as\n## @tex\n## $$\n## {B(s)\\over A(s)} = \\sum_{m=1}^M {r_m\\over (s-p_m)^e_m}\n##   + \\sum_{i=1}^N k_i s^{N-i}.\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## B(s)    M       r(m)        N\n## ---- = SUM ------------- + SUM k(i)*s^(N-i)\n## A(s)   m=1 (s-p(m))^e(m)   i=1\n## @end group\n## @end example\n##\n## @end ifnottex\n## @noindent\n## where @math{M} is the number of poles (the length of the @var{r}, @var{p},\n## and @var{e}), the @var{k} vector is a polynomial of order @math{N-1}\n## representing the direct contribution, and the @var{e} vector specifies the\n## multiplicity of the m-th residue's pole.\n##\n## For example,\n##\n## @example\n## @group\n## b = [1, 1, 1];\n## a = [1, -5, 8, -4];\n## [r, p, k, e] = residue (b, a)\n##    @xresult{} r = [-2; 7; 3]\n##    @xresult{} p = [2; 2; 1]\n##    @xresult{} k = [](0x0)\n##    @xresult{} e = [1; 2; 1]\n## @end group\n## @end example\n##\n## @noindent\n## which represents the following partial fraction expansion\n## @tex\n## $$\n## {s^2+s+1\\over s^3-5s^2+8s-4} = {-2\\over s-2} + {7\\over (s-2)^2} + {3\\over s-1}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##         s^2 + s + 1       -2        7        3\n##    ------------------- = ----- + ------- + -----\n##    s^3 - 5s^2 + 8s - 4   (s-2)   (s-2)^2   (s-1)\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## The second calling form performs the inverse operation and computes the\n## reconstituted quotient of polynomials, @var{b}(s)/@var{a}(s), from the\n## partial fraction expansion; represented by the residues, poles, and a direct\n## polynomial specified by @var{r}, @var{p} and @var{k}, and the pole\n## multiplicity @var{e}.\n##\n## If the multiplicity, @var{e}, is not explicitly specified the multiplicity\n## is determined by the function @code{mpoles}.\n##\n## For example:\n##\n## @example\n## @group\n## r = [-2; 7; 3];\n## p = [2; 2; 1];\n## k = [1, 0];\n## [b, a] = residue (r, p, k)\n##    @xresult{} b = [1, -5, 9, -3, 1]\n##    @xresult{} a = [1, -5, 8, -4]\n##\n## where mpoles is used to determine e = [1; 2; 1]\n## @end group\n## @end example\n##\n## Alternatively the multiplicity may be defined explicitly, for example,\n##\n## @example\n## @group\n## r = [7; 3; -2];\n## p = [2; 1; 2];\n## k = [1, 0];\n## e = [2; 1; 1];\n## [b, a] = residue (r, p, k, e)\n##    @xresult{} b = [1, -5, 9, -3, 1]\n##    @xresult{} a = [1, -5, 8, -4]\n## @end group\n## @end example\n##\n## @noindent\n## which represents the following partial fraction expansion\n## @tex\n## $$\n## {-2\\over s-2} + {7\\over (s-2)^2} + {3\\over s-1} + s = {s^4-5s^3+9s^2-3s+1\\over s^3-5s^2+8s-4}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##  -2        7        3         s^4 - 5s^3 + 9s^2 - 3s + 1\n## ----- + ------- + ----- + s = --------------------------\n## (s-2)   (s-2)^2   (s-1)          s^3 - 5s^2 + 8s - 4\n## @end group\n## @end example\n##\n## @end ifnottex\n## @seealso{mpoles, poly, roots, conv, deconv}\n## @end deftypefn\n\nfunction [r, p, k, e] = residue (b, a, varargin)\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n  endif\n\n  tol = .001;\n\n  if (nargin >= 3)\n    if (nargin >= 4)\n      e = varargin{2};\n    else\n      e = [];\n    endif\n    ## The inputs are the residue, pole, and direct part.\n    ## Solve for the corresponding numerator and denominator polynomials.\n    [r, p] = rresidue (b, a, varargin{1}, tol, e);\n    return;\n  endif\n\n  ## Make sure both polynomials are in reduced form, and scaled.\n  a = polyreduce (a);\n  b = polyreduce (b);\n\n  b /= a(1);\n  a /= a(1);\n\n  la = length (a);\n  lb = length (b);\n\n  ## Handle special cases here.\n  if (la == 0 || lb == 0)\n    k = r = p = e = [];\n    return;\n  elseif (la == 1)\n    k = b / a;\n    r = p = e = [];\n    return;\n  endif\n\n  ## Find the poles.\n  p = roots (a);\n  lp = length (p);\n\n  ## Sort poles so that multiplicity loop will work.\n  [e, idx] = mpoles (p, tol, 1);\n  p = p(idx);\n\n  ## For each group of pole multiplicity, set the value of each\n  ## pole to the average of the group.  This reduces the error in\n  ## the resulting poles.\n  p_group = cumsum (e == 1);\n  for ng = 1:p_group(end)\n    m = find (p_group == ng);\n    p(m) = mean (p(m));\n  endfor\n\n  ## Find the direct term if there is one.\n  if (lb >= la)\n    ## Also return the reduced numerator.\n    [k, b] = deconv (b, a);\n    lb = length (b);\n  else\n    k = [];\n  endif\n\n  ## Determine if the poles are (effectively) zero.\n  small = max (abs (p));\n  if (isa (a, \"single\") || isa (b, \"single\"))\n    small = max ([small, 1]) * eps (\"single\") * 1e4 * (1 + numel (p))^2;\n  else\n    small = max ([small, 1]) * eps * 1e4 * (1 + numel (p))^2;\n  endif\n  p(abs (p) < small) = 0;\n\n  ## Determine if the poles are (effectively) real, or imaginary.\n  idx = (abs (imag (p)) < small);\n  p(idx) = real (p(idx));\n  idx = (abs (real (p)) < small);\n  p(idx) = 1i * imag (p(idx));\n\n  ## The remainder determines the residues.  The case of one pole is trivial.\n  if (lp == 1)\n    r = polyval (b, p);\n    return;\n  endif\n\n  ## Determine the order of the denominator and remaining numerator.\n  ## With the direct term removed, the potential order of the numerator\n  ## is one less than the order of the denominator.\n  aorder = numel (a) - 1;\n  border = aorder - 1;\n\n  ## Construct a system of equations relating the individual\n  ## contributions from each residue to the complete numerator.\n  A = zeros (border+1, border+1);\n  B = prepad (reshape (b, [numel(b), 1]), border+1, 0);\n  for ip = 1:numel (p)\n    ri = zeros (size (p));\n    ri(ip) = 1;\n    A(:,ip) = prepad (rresidue (ri, p, [], tol), border+1, 0).';\n  endfor\n\n  ## Solve for the residues.\n  ## FIXME: Use a pre-conditioner d to make A \\ B work better (bug #53869).\n  ##        It would be better to construct A and B so they are not close to\n  ##        singular in the first place.\n  d = max (abs (A), [], 2);\n  r = (diag (d) \\ A) \\ (B ./ d);\n\nendfunction\n\n## Reconstitute the numerator and denominator polynomials\n## from the residues, poles, and direct term.\nfunction [pnum, pden, e] = rresidue (r, p, k = [], tol = [], e = [])\n\n  if (! isempty (e))\n    idx = 1:numel (p);\n  else\n    [e, idx] = mpoles (p, tol, 0);\n    p = p(idx);\n    r = r(idx);\n  endif\n\n  idx = 1:numel (p);\n  for n = idx\n    pn = [1, -p(n)];\n    if (n == 1)\n      pden = pn;\n    else\n      pden = conv (pden, pn);\n    endif\n  endfor\n\n  ## D is the order of the denominator\n  ## K is the order of the direct polynomial\n  ## N is the order of the resulting numerator\n  ## pnum(1:(N+1)) is the numerator's polynomial\n  ## pden(1:(D+1)) is the denominator's polynomial\n  ## pm is the multiple pole for the nth residue\n  ## pn is the numerator contribution for the nth residue\n\n  D = numel (pden) - 1;\n  K = numel (k) - 1;\n  N = K + D;\n  pnum = zeros (1, N+1);\n  for n = idx(abs (r) > 0)\n    p1 = [1, -p(n)];\n    pn = 1;\n    for j = 1:n - 1\n      pn = conv (pn, [1, -p(j)]);\n    endfor\n    for j = n + 1:numel (p)\n      pn = conv (pn, [1, -p(j)]);\n    endfor\n    for j = 1:e(n) - 1\n      pn = deconv (pn, p1);\n    endfor\n    pn = r(n) * pn;\n    pnum += prepad (pn, N+1, 0, 2);\n  endfor\n\n  ## Add the direct term.\n  if (numel (k))\n    pnum += conv (pden, k);\n  endif\n\n  pnum = polyreduce (pnum);\n  pden = polyreduce (pden);\n\nendfunction\n\n\n%!test\n%! b = [1, 1, 1];\n%! a = [1, -5, 8, -4];\n%! [r, p, k, e] = residue (b, a);\n%! assert (r, [-2; 7; 3], 1e-12);\n%! assert (p, [2; 2; 1], 1e-12);\n%! assert (isempty (k));\n%! assert (e, [1; 2; 1]);\n%! k = [1 0];\n%! b = conv (k, a) + prepad (b, numel (k) + numel (a) - 1, 0);\n%! a = a;\n%! [br, ar] = residue (r, p, k);\n%! assert (br, b, 1e-12);\n%! assert (ar, a, 1e-12);\n%! [br, ar] = residue (r, p, k, e);\n%! assert (br, b, 1e-12);\n%! assert (ar, a, 1e-12);\n\n%!test\n%! b = [1, 0, 1];\n%! a = [1, 0, 18, 0, 81];\n%! [r, p, k, e] = residue (b, a);\n%! r1 = [-5i; 12; +5i; 12]/54;\n%! p1 = [+3i; +3i; -3i; -3i];\n%! assert (r, r1, 1e-12);\n%! assert (p, p1, 1e-12);\n%! assert (isempty (k));\n%! assert (e, [1; 2; 1; 2]);\n%! [br, ar] = residue (r, p, k);\n%! assert (br, b, 1e-12);\n%! assert (ar, a, 1e-12);\n\n%!test\n%! r = [7; 3; -2];\n%! p = [2; 1; 2];\n%! k = [1 0];\n%! e = [2; 1; 1];\n%! [b, a] = residue (r, p, k, e);\n%! assert (b, [1, -5, 9, -3, 1], 1e-12);\n%! assert (a, [1, -5, 8, -4], 1e-12);\n%! [rr, pr, kr, er] = residue (b, a);\n%! [~, m] = mpoles (rr);\n%! [~, n] = mpoles (r);\n%! assert (rr(m), r(n), 1e-12);\n%! assert (pr(m), p(n), 1e-12);\n%! assert (kr, k, 1e-12);\n%! assert (er(m), e(n), 1e-12);\n\n%!test\n%! b = [1];\n%! a = [1, 10, 25];\n%! [r, p, k, e] = residue (b, a);\n%! r1 = [0; 1];\n%! p1 = [-5; -5];\n%! assert (r, r1, 1e-12);\n%! assert (p, p1, 1e-12);\n%! assert (isempty (k));\n%! assert (e, [1; 2]);\n%! [br, ar] = residue (r, p, k);\n%! assert (br, b, 1e-12);\n%! assert (ar, a, 1e-12);\n\n## The following test is due to Bernard Grung\n%!test <*34266>\n%! z1 =  7.0372976777e6;\n%! p1 = -3.1415926536e9;\n%! p2 = -4.9964813512e8;\n%! r1 = -(1 + z1/p1)/(1 - p1/p2)/p2/p1;\n%! r2 = -(1 + z1/p2)/(1 - p2/p1)/p2/p1;\n%! r3 = (1 + (p2 + p1)/p2/p1*z1)/p2/p1;\n%! r4 = z1/p2/p1;\n%! r = [r1; r2; r3; r4];\n%! p = [p1; p2; 0; 0];\n%! k = [];\n%! e = [1; 1; 1; 2];\n%! b = [1, z1];\n%! a = [1, -(p1 + p2), p1*p2, 0, 0];\n%! [br, ar] = residue (r, p, k, e);\n%! assert (br, [0,0,b], 1e-7);\n%! assert (ar, a, 1e-8);\n\n%!test <*49291>\n%! rf = [1e3, 2e3, 1e3, 2e3];\n%! cf = [316.2e-9, 50e-9, 31.6e-9, 5e-9];\n%! [num, den] = residue (1./cf,-1./(rf.*cf),0);\n%! assert (numel (num), 4);\n%! assert (numel (den), 5);\n%! assert (den(1), 1);\n\n%!test <*51148>\n%! r = [1.0000e+18, 3.5714e+12, 2.2222e+11, 2.1739e+10];\n%! pin = [-1.9231e+15, -1.6234e+09, -4.1152e+07, -1.8116e+06];\n%! k = 0;\n%! [p, q] = residue (r, pin, k);\n%! assert (p(4), 4.6828e+42, -1e-5);\n\n%!test <*60384>\n%! B = [1315.789473684211];\n%! A = [1, 1.100000536842105e+04, 1.703789473684211e+03, 0];\n%! poles1 = roots (A);\n%! [r, p, k, e] = residue (B, A);\n%! [B1, A1] = residue (r, p, k, e);\n%! assert (B, B1);\n%! assert (A, A1);\n"
  },
  {
    "path": "scripts/polynomial/roots.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{r} =} roots (@var{c})\n##\n## Compute the roots of the polynomial @var{c}.\n##\n## For a vector @var{c} with @math{N} components, return the roots of the\n## polynomial\n## @tex\n## $$\n## c_1 x^{N-1} + \\cdots + c_{N-1} x + c_N.\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## c(1) * x^(N-1) + @dots{} + c(N-1) * x + c(N)\n## @end example\n##\n## @end ifnottex\n##\n## As an example, the following code finds the roots of the quadratic\n## polynomial\n## @tex\n## $$ p(x) = x^2 - 5. $$\n## @end tex\n## @ifnottex\n##\n## @example\n## p(x) = x^2 - 5.\n## @end example\n##\n## @end ifnottex\n##\n## @example\n## @group\n## c = [1, 0, -5];\n## roots (c)\n## @xresult{}  2.2361\n## @xresult{} -2.2361\n## @end group\n## @end example\n##\n## Note that the true result is\n## @tex\n## $\\pm \\sqrt{5}$\n## @end tex\n## @ifnottex\n## @math{+/- sqrt(5)}\n## @end ifnottex\n## which is roughly\n## @tex\n## $\\pm 2.2361$.\n## @end tex\n## @ifnottex\n## @math{+/- 2.2361}.\n## @end ifnottex\n## @seealso{poly, compan, fzero}\n## @end deftypefn\n\nfunction r = roots (c)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! isnumeric (c) || (! isvector (c) && ! isempty (c)))\n    error (\"roots: C must be a numeric vector\");\n  elseif (any (! isfinite (c)))\n    error (\"roots: C must not contain Inf or NaN\");\n  endif\n\n  c = c(:);\n  n = numel (c);\n\n  ## If c = [ 0 ... 0 c(k+1) ... c(k+l) 0 ... 0 ],\n  ## we can remove the leading k zeros,\n  ## and n - k - l roots of the polynomial are zero.\n\n  c_max = max (abs (c));\n  if (isempty (c) || c_max == 0)\n    r = [];\n    return;\n  endif\n\n  f = find (c ./ c_max);\n  m = numel (f);\n\n  c = c(f(1):f(m));\n  l = numel (c);\n  if (l > 1)\n    A = diag (ones (1, l-2), -1);\n    A(1,:) = -c(2:l) ./ c(1);\n    r = eig (A);\n    if (f(m) < n)\n      r = [r; zeros(n - f(m), 1)];\n    endif\n  else\n    r = zeros (n - f(m), 1);\n  endif\n\nendfunction\n\n\n%!test\n%! p = [poly([3 3 3 3]), 0 0 0 0];\n%! r = sort (roots (p));\n%! assert (r, [0; 0; 0; 0; 3; 3; 3; 3], 0.001);\n\n%!assert (isempty (roots ([])))\n%!assert (isempty (roots ([0 0])))\n%!assert (isempty (roots (1)))\n%!assert (roots ([1, -6, 11, -6]), [3; 2; 1], sqrt (eps))\n\n%!assert (roots ([1e-200, -1e200, 1]), 1e-200)\n%!assert (roots ([1e-200, -1e200 * 1i, 1]), -1e-200 * 1i)\n\n%!error <Invalid call> roots ()\n%!error <C must be a numeric> roots ('ABC')\n%!error <C must be a .* vector> roots ([1, 2; 3, 4])\n%!error <C must not contain Inf or NaN> roots ([1 Inf 1])\n%!error <C must not contain Inf or NaN> roots ([1 NaN 1])\n"
  },
  {
    "path": "scripts/polynomial/spline.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{pp} =} spline (@var{x}, @var{y})\n## @deftypefnx {} {@var{yi} =} spline (@var{x}, @var{y}, @var{xi})\n## Return the cubic spline interpolant of points @var{x} and @var{y}.\n##\n## When called with two arguments, return the piecewise polynomial @var{pp}\n## that may be used with @code{ppval} to evaluate the polynomial at specific\n## points.\n##\n## When called with a third input argument, @code{spline} evaluates the spline\n## at the points @var{xi}.  The third calling form\n## @code{spline (@var{x}, @var{y}, @var{xi})} is equivalent to\n## @code{ppval (spline (@var{x}, @var{y}), @var{xi})}.\n##\n## The variable @var{x} must be a vector of length @var{n}.\n##\n## @var{y} can be either a vector or array.  If @var{y} is a vector it must\n## have a length of either @var{n} or @code{@var{n} + 2}.  If the length of\n## @var{y} is @var{n}, then the @qcode{\"not-a-knot\"} end condition is used.\n## If the length of @var{y} is @code{@var{n} + 2}, then the first and last\n## values of the vector @var{y} are the values of the first derivative of the\n## cubic spline at the endpoints.\n##\n## If @var{y} is an array, then the size of @var{y} must have the form\n## @tex\n## $$[s_1, s_2, \\cdots, s_k, n]$$\n## @end tex\n## @ifnottex\n## @code{[@var{s1}, @var{s2}, @dots{}, @var{sk}, @var{n}]}\n## @end ifnottex\n## or\n## @tex\n## $$[s_1, s_2, \\cdots, s_k, n + 2].$$\n## @end tex\n## @ifnottex\n## @code{[@var{s1}, @var{s2}, @dots{}, @var{sk}, @var{n} + 2]}.\n## @end ifnottex\n## The array is reshaped internally to a matrix where the leading\n## dimension is given by\n## @tex\n## $$s_1 s_2 \\cdots s_k$$\n## @end tex\n## @ifnottex\n## @code{@var{s1} * @var{s2} * @dots{} * @var{sk}}\n## @end ifnottex\n## and each row of this matrix is then treated separately.  Note that this is\n## exactly the opposite of @code{interp1} but is done for @sc{matlab}\n## compatibility.\n##\n## @seealso{pchip, ppval, mkpp, unmkpp}\n## @end deftypefn\n\n## This code is based on csape.m from Octave Forge, but has been\n## modified to use the sparse solver code in octave that itself allows\n## special casing of tri-diagonal matrices, modified for NDArrays and\n## for the treatment of vectors y 2 elements longer than x as complete\n## splines.\n\nfunction ret = spline (x, y, xi)\n\n  x = x(:);\n  n = length (x);\n  if (n < 2)\n    error (\"spline: requires at least 2 points\");\n  endif\n\n  ## Check the size and shape of y\n  ndy = ndims (y);\n  szy = size (y);\n  if (ndy == 2 && (any (szy == n) || any (szy == n+2)))\n    if (szy(2) == n || szy(2) == n+2)\n      a = y.';\n    else\n      a = y;\n      szy = szy([2 1]);\n    endif\n  else\n    a = shiftdim (reshape (y, [prod(szy(1:end-1)), szy(end)]), 1);\n  endif\n\n  for k = (1:columns (a))(any (isnan (a)))\n    ok = ! isnan (a(:,k));\n    a(! ok,k) = spline (x(ok), a(ok,k), x(! ok));\n  endfor\n\n  complete = false;\n  if (rows (a) == n + 2)\n    complete = true;\n    dfs = a(1,:);\n    dfe = a(end,:);\n    a = a(2:end-1,:);\n  endif\n\n  if (! issorted (x))\n    [x, idx] = sort (x);\n    a = a(idx,:);\n  endif\n\n  b = c = zeros (size (a));\n  h = diff (x);\n  idx = ones (columns (a), 1);\n\n  if (complete)\n\n    if (n == 2)\n      d = (dfs + dfe) / (x(2) - x(1)) ^ 2 + ...\n          2 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 3;\n      c = (-2 * dfs - dfe) / (x(2) - x(1)) - ...\n          3 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 2;\n      b = dfs;\n      a = a(1,:);\n    else\n      g(1,:) = (a(2,:) - a(1,:)) / h(1) - dfs;\n      g(2:n-1,:) = (a(3:n,:) - a(2:n-1,:)) ./ h(2:n-1) - ...\n                   (a(2:n-1,:) - a(1:n-2,:)) ./ h(1:n-2);\n      g(n,:) = dfe - (a(n,:) - a(n-1,:)) / h(n-1);\n      c = spdiags ([[h/6;0],[h(1)/3;(h(1:n-2)+h(2:n-1))/3;h(n-1)/3],[0;h/6]],...\n                   [-1,0,1],n,n) \\ (g / 2);\n      b = diff (a) ./ h(1:n-1, idx) ...\n          - h(1:n-1,idx) / 3 .* (c(2:n,:) + 2 * c(1:n-1,:));\n      d = diff (c) ./ (3 * h(1:n-1, idx));\n\n      d = d.'(:);\n      c = c(1:n-1,:).'(:);\n      b = b.'(:);\n      a = a(1:n-1,:).'(:);\n    endif\n  else\n\n    if (n == 2)\n      b = (a(2,:) - a(1,:)) / (x(2) - x(1));\n      a = a(1,:);\n      d = [];\n      c = [];\n    elseif (n == 3)\n\n      n = 2;\n      c = (a(1,:) - a(3,:)) / ((x(3) - x(1)) * (x(2) - x(3))) ...\n          + (a(2,:) - a(1,:)) / ((x(2) - x(1)) * (x(2) - x(3)));\n      b = (a(2,:) - a(1,:)) * (x(3) - x(1)) ...\n          / ((x(2) - x(1)) * (x(3) - x(2))) ...\n          + (a(1,:) - a(3,:)) * (x(2) - x(1)) ...\n          / ((x(3) - x(1)) * (x(3) - x(2)));\n      a = a(1,:);\n      d = [];\n      x = [min(x), max(x)];\n    else\n\n      g = zeros (n-2, columns (a));\n      g(1,:) = 3 / (h(1) + h(2)) ...\n          * (a(3,:) - a(2,:) - h(2) / h(1) * (a(2,:) - a(1,:)));\n      g(n-2,:) = 3 / (h(n-1) + h(n-2)) ...\n          * (h(n-2) / h(n-1) * (a(n,:) - a(n-1,:)) - (a(n-1,:) - a(n-2,:)));\n\n      if (n > 4)\n\n        g(2:n - 3,:) = 3 * diff (a(3:n-1,:)) ./ h(3:n-2,idx) ...\n            - 3 * diff (a(2:n-2,:)) ./ h(2:n - 3,idx);\n\n        dg = 2 * (h(1:n-2) + h(2:n-1));\n        dg(1) = dg(1) - h(1);\n        dg(n-2) = dg(n-2) - h(n-1);\n\n        ldg = udg = h(2:n-2);\n        udg(1) = udg(1) - h(1);\n        ldg(n - 3) = ldg(n-3) - h(n-1);\n        c(2:n-1,:) = spdiags ([[ldg(:); 0], dg, [0; udg(:)]],\n                              [-1, 0, 1], n-2, n-2) \\ g;\n\n      elseif (n == 4)\n\n        dg = [h(1) + 2 * h(2); 2 * h(2) + h(3)];\n        ldg = h(2) - h(3);\n        udg = h(2) - h(1);\n        c(2:n-1,:) = spdiags ([[ldg(:);0], dg, [0; udg(:)]],\n                              [-1, 0, 1], n-2, n-2) \\ g;\n\n      endif\n\n      c(1,:) = c(2,:) + h(1) / h(2) * (c(2,:) - c(3,:));\n      c(n,:) = c(n-1,:) + h(n-1) / h(n-2) * (c(n-1,:) - c(n-2,:));\n      b = diff (a) ./ h(1:n-1, idx) ...\n          - h(1:n-1, idx) / 3 .* (c(2:n,:) + 2 * c(1:n-1,:));\n      d = diff (c) ./ (3 * h(1:n-1, idx));\n\n      d = d.'(:);\n      c = c(1:n-1,:).'(:);\n      b = b.'(:);\n      a = a(1:n-1,:).'(:);\n    endif\n\n  endif\n  ret = mkpp (x, cat (2, d, c, b, a), szy(1:end-1));\n\n  if (nargin == 3)\n    ret = ppval (ret, xi);\n  endif\n\nendfunction\n\n\n%!demo\n%! x = 0:10; y = sin (x);\n%! xspline = 0:0.1:10;  yspline = spline (x,y,xspline);\n%! title (\"spline fit to points from sin (x)\");\n%! plot (xspline,sin (xspline),\"r\", xspline,yspline,\"g-\", x,y,\"b+\");\n%! legend (\"original\", \"interpolation\", \"interpolation points\", ...\n%!         \"location\", \"north\");\n%! %--------------------------------------------------------\n%! % confirm that interpolated function matches the original\n\n%!shared x,y,abserr\n%! x = [0:10]; y = sin (x); abserr = 1e-14;\n%!assert (spline (x,y,x), y, abserr)\n%!assert (spline (x,y,x'), y', abserr)\n%!assert (spline (x',y',x'), y', abserr)\n%!assert (spline (x',y',x), y, abserr)\n%!assert (isempty (spline (x',y',[])))\n%!assert (isempty (spline (x,y,[])))\n%!assert (spline (x,[y;y],x), [spline(x,y,x);spline(x,y,x)], abserr)\n%!assert (spline (x,[y;y],x'), [spline(x,y,x);spline(x,y,x)], abserr)\n%!assert (spline (x',[y;y],x), [spline(x,y,x);spline(x,y,x)], abserr)\n%!assert (spline (x',[y;y],x'), [spline(x,y,x);spline(x,y,x)], abserr)\n%! y = cos (x) + i*sin (x);\n%!assert (spline (x,y,x), y, abserr)\n%!assert (real (spline (x,y,x)), real (y), abserr)\n%!assert (real (spline (x,y,x.')), real (y).', abserr)\n%!assert (real (spline (x.',y.',x.')), real (y).', abserr)\n%!assert (real (spline (x.',y,x)), real (y), abserr)\n%!assert (imag (spline (x,y,x)), imag (y), abserr)\n%!assert (imag (spline (x,y,x.')), imag (y).', abserr)\n%!assert (imag (spline (x.',y.',x.')), imag (y).', abserr)\n%!assert (imag (spline (x.',y,x)), imag (y), abserr)\n%!test\n%! xnan = 5;\n%! y(x==xnan) = NaN;\n%! ok = ! isnan (y);\n%! assert (spline (x, y, x(ok)), y(ok), abserr);\n%!test\n%! ok = ! isnan (y);\n%! assert (! isnan (spline (x, y, x(! ok))));\n%!test\n%! x = [1,2];\n%! y = [1,4];\n%! assert (spline (x,y,x), [1,4], abserr);\n%!test\n%! x = [2,1];\n%! y = [1,4];\n%! assert (spline (x,y,x), [1,4], abserr);\n%!test\n%! x = [1,2];\n%! y = [1,2,3,4];\n%! pp = spline (x,y);\n%! [x,P] = unmkpp (pp);\n%! assert (P, [3,-3,1,2], abserr);\n%!test\n%! x = [2,1];\n%! y = [1,2,3,4];\n%! pp = spline (x,y);\n%! pp2 = spline (x', y');\n%! [x,P] = unmkpp (pp);\n%! assert (P, [7,-9,1,3], abserr);\n%! assert (pp2, pp);\n%!test\n%! x = [0,1,2];\n%! y = [0,0,1,0,0];\n%! pp = spline (x,y);\n%! pp2 = spline (x', y');\n%! [x,P] = unmkpp (pp);\n%! assert (P, [-2,3,0,0;2,-3,0,1], abserr);\n%! assert (pp2, pp);\n%!test\n%! x = [0,1,2,3];\n%! y = [0,0,1,1,0,0];\n%! pp = spline (x,y);\n%! pp2 = spline (x', y');\n%! [x,P] = unmkpp (pp);\n%! assert (P, [-1,2,0,0;0,-1,1,1;1,-1,-1,1], abserr);\n%! assert (pp2, pp);\n"
  },
  {
    "path": "scripts/polynomial/splinefit.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{pp} =} splinefit (@var{x}, @var{y}, @var{breaks})\n## @deftypefnx {} {@var{pp} =} splinefit (@var{x}, @var{y}, @var{p})\n## @deftypefnx {} {@var{pp} =} splinefit (@dots{}, \"periodic\", @var{periodic})\n## @deftypefnx {} {@var{pp} =} splinefit (@dots{}, \"robust\", @var{robust})\n## @deftypefnx {} {@var{pp} =} splinefit (@dots{}, \"beta\", @var{beta})\n## @deftypefnx {} {@var{pp} =} splinefit (@dots{}, \"order\", @var{order})\n## @deftypefnx {} {@var{pp} =} splinefit (@dots{}, \"constraints\", @var{constraints})\n##\n## Fit a piecewise cubic spline with breaks (knots) @var{breaks} to the\n## noisy data, @var{x} and @var{y}.\n##\n## @var{x} is a vector, and @var{y} is a vector or N-D array.  If @var{y} is an\n## N-D array, then @var{x}(j) is matched to @var{y}(:,@dots{},:,j).\n##\n## @var{p} is a positive integer defining the number of intervals along\n## @var{x}, and @var{p}+1 is the number of breaks.  The number of points in\n## each interval differ by no more than 1.\n##\n## The optional property @var{periodic} is a logical value which specifies\n## whether a periodic boundary condition is applied to the spline.  The\n## length of the period is @code{max (@var{breaks}) - min (@var{breaks})}.\n## The default value is @code{false}.\n##\n## The optional property @var{robust} is a logical value which specifies\n## if robust fitting is to be applied to reduce the influence of outlying\n## data points.  Three iterations of weighted least squares are performed.\n## Weights are computed from previous residuals.  The sensitivity of outlier\n## identification is controlled by the property @var{beta}.  The value of\n## @var{beta} is restricted to the range, 0 < @var{beta} < 1.  The default\n## value is @var{beta} = 1/2.  Values close to 0 give all data equal\n## weighting.  Increasing values of @var{beta} reduce the influence of\n## outlying data.  Values close to unity may cause instability or rank\n## deficiency.\n##\n## The fitted spline is returned as a piecewise polynomial, @var{pp}, and\n## may be evaluated using @code{ppval}.\n##\n## The splines are constructed of polynomials with degree @var{order}.\n## The default is a cubic, @var{order}=3.  A spline with P pieces has\n## P+@var{order} degrees of freedom.  With periodic boundary conditions\n## the degrees of freedom are reduced to P.\n##\n## The optional property, @var{constraints}, is a structure specifying linear\n## constraints on the fit.  The structure has three fields, @qcode{\"xc\"},\n## @qcode{\"yc\"}, and @qcode{\"cc\"}.\n##\n## @table @asis\n## @item @qcode{\"xc\"}\n## Vector of the x-locations of the constraints.\n##\n## @item @qcode{\"yc\"}\n## Constraining values at the locations @var{xc}.\n## The default is an array of zeros.\n##\n## @item @qcode{\"cc\"}\n## Coefficients (matrix).  The default is an array of ones.  The number of\n## rows is limited to the order of the piecewise polynomials, @var{order}.\n## @end table\n##\n## Constraints are linear combinations of derivatives of order 0 to\n## @var{order}-1 according to\n##\n## @example\n## @group\n## @tex\n## $cc(1,j) \\cdot y(xc(j)) + cc(2,j) \\cdot y\\prime(xc(j)) + ... = yc(:,\\dots,:,j)$.\n## @end tex\n## @ifnottex\n## cc(1,j) * y(xc(j)) + cc(2,j) * y'(xc(j)) + ... = yc(:,...,:,j).\n## @end ifnottex\n## @end group\n## @end example\n##\n## @seealso{interp1, unmkpp, ppval, spline, pchip, ppder, ppint, ppjumps}\n## @end deftypefn\n\nfunction pp = splinefit (x, y, breaks, varargin)\n\n  if (nargin > 3)\n    n = cellfun (\"isclass\", varargin, \"char\");\n    varargin(n) = lower (varargin(n));\n    try\n      props = struct (varargin{:});\n    catch\n      print_usage ();\n    end_try_catch\n  else\n    props = struct ();\n  endif\n\n  fields = fieldnames (props);\n  for f = 1:numel (fields)\n    if (! any (strcmp (fields{f},\n                       {\"periodic\", \"robust\", \"beta\", \"order\", \"constraints\"})))\n      error (\"Octave:splinefit:invalidproperty\",\n             \"unrecognized property '%s'\", fields{f});\n    endif\n  endfor\n\n  args = {};\n  if (isfield (props, \"periodic\") && props.periodic)\n    args{end+1} = \"p\";\n  endif\n  if (isfield (props, \"robust\") && props.robust)\n    args{end+1} = \"r\";\n  endif\n  if (isfield (props, \"beta\"))\n    if (0 < props.beta && props.beta < 1)\n      args{end+1} = props.beta;\n    else\n      error (\"Octave:splinefit:invalidbeta\", \"invalid beta parameter (0 < BETA < 1)\");\n    endif\n  endif\n  if (isfield (props, \"order\"))\n    if (props.order >= 0)\n      args{end+1} = props.order + 1;\n    else\n      error (\"Octave:splinefit:invalidorder\", \"invalid ORDER\");\n    endif\n  endif\n  if (isfield (props, \"constraints\"))\n    args{end+1} = props.constraints;\n  endif\n  if (nargin < 3)\n    print_usage ();\n  elseif (! isnumeric (breaks) || ! isvector (breaks))\n    print_usage ();\n  endif\n\n  pp = __splinefit__ (x, y, breaks, args{:});\n\nendfunction\n\n\n%!demo\n%! % Noisy data\n%! x = linspace (0, 2*pi, 100);\n%! y = sin (x) + 0.1 * randn (size (x));\n%! % Breaks\n%! breaks = [0:5, 2*pi];\n%! % Fit a spline of order 5\n%! pp = splinefit (x, y, breaks, \"order\", 4);\n%! clf;\n%! plot (x, y, \"s\", x, ppval (pp, x), \"r\", breaks, ppval (pp, breaks), \"+r\");\n%! xlabel (\"Independent Variable\");\n%! ylabel (\"Dependent Variable\");\n%! title (\"Fit a piecewise polynomial of order 4\");\n%! legend ({\"data\", \"fit\", \"breaks\"});\n%! axis tight\n%! ylim auto\n\n%!demo\n%! % Noisy data\n%! x = linspace (0,2*pi, 100);\n%! y = sin (x) + 0.1 * randn (size (x));\n%! % Breaks\n%! breaks = [0:5, 2*pi];\n%! % Fit a spline of order 3 with periodic boundary conditions\n%! pp = splinefit (x, y, breaks, \"order\", 2, \"periodic\", true);\n%! clf;\n%! plot (x, y, \"s\", x, ppval (pp, x), \"r\", breaks, ppval (pp, breaks), \"+r\");\n%! xlabel (\"Independent Variable\");\n%! ylabel (\"Dependent Variable\");\n%! title (\"Fit a periodic piecewise polynomial of order 2\");\n%! legend ({\"data\", \"fit\", \"breaks\"});\n%! axis tight\n%! ylim auto\n\n%!demo\n%! % Noisy data\n%! x = linspace (0, 2*pi, 100);\n%! y = sin (x) + 0.1 * randn (size (x));\n%! % Breaks\n%! breaks = [0:5, 2*pi];\n%! % Constraints: y(0) = 0, y'(0) = 1 and y(3) + y\"(3) = 0\n%! xc = [0 0 3];\n%! yc = [0 1 0];\n%! cc = [1 0 1; 0 1 0; 0 0 1];\n%! con = struct (\"xc\", xc, \"yc\", yc, \"cc\", cc);\n%! % Fit a cubic spline with 8 pieces and constraints\n%! pp = splinefit (x, y, 8, \"constraints\", con);\n%! clf;\n%! plot (x, y, \"s\", x, ppval (pp, x), \"r\", breaks, ppval (pp, breaks), \"+r\");\n%! xlabel (\"Independent Variable\");\n%! ylabel (\"Dependent Variable\");\n%! title (\"Fit a cubic spline with constraints\");\n%! legend ({\"data\", \"fit\", \"breaks\"});\n%! axis tight\n%! ylim auto\n\n%!demo\n%! % Noisy data\n%! x = linspace (0, 2*pi, 100);\n%! y = sin (x) + 0.1 * randn (size (x));\n%! % Breaks\n%! breaks = [0:5, 2*pi];\n%! xc = [0 0 3];\n%! yc = [0 1 0];\n%! cc = [1 0 1; 0 1 0; 0 0 1];\n%! con = struct (\"xc\", xc, \"yc\", yc, \"cc\", cc);\n%! % Fit a spline of order 6 with constraints and periodicity\n%! pp = splinefit (x, y, breaks, \"constraints\", con, \"order\", 5, \"periodic\", true);\n%! clf;\n%! plot (x, y, \"s\", x, ppval (pp, x), \"r\", breaks, ppval (pp, breaks), \"+r\");\n%! xlabel (\"Independent Variable\");\n%! ylabel (\"Dependent Variable\");\n%! title (\"Fit a 5th order piecewise periodic polynomial with constraints\");\n%! legend ({\"data\", \"fit\", \"breaks\"});\n%! axis tight\n%! ylim auto\n\n%!shared xb, yb, x\n%! xb = 0:2:10;\n%! yb = 2*rand (size (xb)) - 1;\n%! x = 0:0.1:10;\n\n%!test\n%! y = interp1 (xb, yb, x, \"linear\");\n%! assert (ppval (splinefit (x, y, xb, \"order\", 1), x), y, 20 * eps ());\n%!test\n%! y = interp1 (xb, yb, x, \"spline\");\n%! assert (ppval (splinefit (x, y, xb, \"order\", 3), x), y, 20 * eps ());\n%!test\n%! y = interp1 (xb, yb, x, \"spline\");\n%! assert (ppval (splinefit (x, y, xb), x), y, 20 * eps ());\n"
  },
  {
    "path": "scripts/polynomial/unmkpp.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{x}, @var{p}, @var{n}, @var{k}, @var{d}] =} unmkpp (@var{pp})\n##\n## Extract the components of a piecewise polynomial structure @var{pp}.\n##\n## This function is the inverse of @code{mkpp}: it extracts the inputs to\n## @code{mkpp} needed to create the piecewise polynomial structure @var{pp}.\n## The code below makes this relation explicit:\n##\n## @example\n## @group\n## [breaks, coefs, numinter, order, dim] = unmkpp (pp);\n## pp2  = mkpp (breaks, coefs, dim);\n## @end group\n## @end example\n##\n## The piecewise polynomial structure @code{pp2} obtained in this way, is\n## identical to the original @code{pp}.  The same can be obtained by directly\n## accessing the fields of the structure @code{pp}.\n##\n## The components are:\n##\n## @table @asis\n## @item @var{x}\n## Sample points or breaks.\n##\n## @item @var{p}\n## Polynomial coefficients for points in sample interval.\n## @code{@var{p}(@var{i}, :)} contains the coefficients for the polynomial\n## over interval @var{i} ordered from highest to lowest degree.\n## If @code{@var{d} > 1}, then @var{p} is a matrix of size\n## @code{[@var{n}*prod(@var{d}) @var{m}]}, where the\n## @code{@var{i} + (1:@var{d})} rows are the coefficients of all the @var{d}\n## polynomials in the interval @var{i}.\n##\n## @item @var{n}\n## Number of polynomial pieces or intervals,\n## @code{@var{n} = length (@var{x}) - 1}.\n##\n## @item @var{k}\n## Order of the polynomial plus 1.\n##\n## @item @var{d}\n## Number of polynomials defined for each interval.\n## @end table\n##\n## @seealso{mkpp, ppval, spline, pchip}\n## @end deftypefn\n\nfunction [x, P, n, k, d] = unmkpp (pp)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n  if (! (isstruct (pp) && isfield (pp, \"form\") && strcmp (pp.form, \"pp\")))\n    error (\"unmkpp: PP must be a piecewise polynomial structure\");\n  endif\n  x = pp.breaks;\n  P = pp.coefs;\n  n = pp.pieces;\n  k = pp.order;\n  d = pp.dim;\n\nendfunction\n\n\n%!test\n%! b = 1:3;\n%! c = 1:24;\n%! pp = mkpp (b,c);\n%! [x, P, n, k, d] = unmkpp (pp);\n%! assert (x, b);\n%! assert (P, reshape (c, [2 12]));\n%! assert (n, 2);\n%! assert (k, 12);\n%! assert (d, 1);\n\n## Test input validation\n%!error <Invalid call> unmkpp ()\n%!error <piecewise polynomial structure> unmkpp (1)\n%!error <piecewise polynomial structure> unmkpp (struct (\"field1\", \"pp\"))\n%!error <piecewise polynomial structure> unmkpp (struct (\"form\", \"not_a_pp\"))\n"
  },
  {
    "path": "scripts/prefs/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/prefs/addpref.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} addpref (\"@var{group}\", \"@var{pref}\", @var{val})\n## @deftypefnx {} {} addpref (\"@var{group}\", @{\"@var{pref1}\", \"@var{pref2}\", @dots{}@}, @{@var{val1}, @var{val2}, @dots{}@})\n## Add the preference @var{pref} and associated value @var{val} to the named\n## preference group @var{group}.\n##\n## The named preference group must be a string.\n##\n## The preference @var{pref} may be a string or a cell array of strings.  An\n## error will be issued if the preference already exists.\n##\n## The corresponding value @var{val} may be any Octave value, .e.g., double,\n## struct, cell array, object, etc.  Or, if @var{pref} is a cell array of\n## strings then @var{val} must be a cell array of values with the same size as\n## @var{pref}.\n## @seealso{setpref, getpref, ispref, rmpref}\n## @end deftypefn\n\nfunction addpref (group, pref, val)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (! ischar (group))\n    error (\"addpref: GROUP must be a string\");\n  elseif (! (ischar (pref) || iscellstr (pref)))\n    error (\"addpref: PREF must be a string or cellstr\");\n  endif\n\n  prefs = loadprefs ();\n\n  if (ischar (pref))\n    if (isfield (prefs, group) && isfield (prefs.(group), pref))\n      error (\"addpref: preference %s already exists in GROUP %s\", pref, group);\n    else\n      prefs.(group).(pref) = val;\n    endif\n  else\n    if (! size_equal (pref, val))\n      error (\"addpref: size mismatch for PREF and VAL\");\n    endif\n    for i = 1:numel (pref)\n      if (isfield (prefs, group) && isfield (prefs.(group), pref{i}))\n        error (\"addpref: preference %s already exists in GROUP %s\",\n               pref{i}, group);\n      else\n        prefs.(group).(pref{i}) = val{i};\n      endif\n    endfor\n  endif\n\n  saveprefs (prefs);\n\nendfunction\n\n\n%!test\n%! HOME = getenv (\"HOME\");\n%! tmpdir = tempname ();\n%! save_default_options (\"-binary\", \"local\");\n%! unwind_protect\n%!   mkdir (tmpdir);\n%!   setenv (\"HOME\", tmpdir);\n%!\n%!   addpref (\"group1\", \"pref1\", [1 2 3]);\n%!   assert (getpref (\"group1\", \"pref1\"), [1 2 3]);\n%!\n%!   addpref (\"group2\", {\"prefA\", \"prefB\"}, {\"StringA\", {\"StringB\"}});\n%!   assert (getpref (\"group2\", \"prefA\"), \"StringA\");\n%!   assert (getpref (\"group2\", \"prefB\"), {\"StringB\"});\n%!\n%!   fail ('addpref (\"group1\", \"pref1\", 4)', ...\n%!         \"preference pref1 already exists in GROUP group1\");\n%!   fail ('setpref (\"group1\", {\"p1\", \"p2\"}, 1)', ...\n%!         \"size mismatch for PREF and VAL\");\n%!   fail ('addpref (\"group2\", {\"prefC\", \"prefA\"}, {1, 2})',\n%!         \"preference prefA already exists in GROUP group2\");\n%!\n%! unwind_protect_cleanup\n%!   unlink (fullfile (tmpdir, \".octave_prefs\"));\n%!   rmdir (tmpdir);\n%!   if (isempty (HOME))\n%!     unsetenv (\"HOME\");\n%!   else\n%!     setenv (\"HOME\", HOME);\n%!   endif\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> addpref ()\n%!error <Invalid call> addpref (1)\n%!error <Invalid call> addpref (1,2)\n%!error <GROUP must be a string> addpref (1, \"pref1\", 2)\n%!error <PREF must be a string> addpref (\"group1\", 1, 2)\n"
  },
  {
    "path": "scripts/prefs/getpref.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{val} =} getpref (\"@var{group}\", \"@var{pref}\")\n## @deftypefnx {} {@var{val} =} getpref (\"@var{group}\", \"@var{pref}\", @var{default})\n## @deftypefnx {} {@{@var{val1}, @var{val2}, @dots{}@} =} getpref (\"@var{group}\", @{\"@var{pref1}\", \"@var{pref2\"}, @dots{}@})\n## @deftypefnx {} {@var{prefstruct} =} getpref (\"@var{group}\")\n## @deftypefnx {} {@var{prefstruct} =} getpref ()\n## Return the preference value corresponding to the named preference @var{pref}\n## in the preference group @var{group}.\n##\n## The named preference group must be a string.\n##\n## If @var{pref} does not exist in @var{group} and @var{default} is specified,\n## create the preference with value @var{default} and return @var{default}.\n##\n## The preference @var{pref} may be a string or cell array of strings.  If it\n## is a cell array of strings then a cell array of preferences is returned.\n##\n## The corresponding default value @var{default} may be any Octave value,\n## .e.g., double, struct, cell array, object, etc.  Or, if @var{pref} is a cell\n## array of strings then @var{default} must be a cell array of values with the\n## same size as @var{pref}.\n##\n## If neither @var{pref} nor @var{default} are specified, return a structure\n## of preferences for the preference group @var{group}.\n##\n## If no arguments are specified, return a structure containing all groups of\n## preferences and their values.\n## @seealso{addpref, setpref, ispref, rmpref}\n## @end deftypefn\n\nfunction retval = getpref (group, pref, default)\n\n  if (nargin == 0)\n    retval = loadprefs ();\n  elseif (nargin == 1)\n    if (! ischar (group))\n      error (\"getpref: GROUP must be a string\");\n    endif\n    prefs = loadprefs ();\n    if (isfield (prefs, group))\n      retval = prefs.(group);\n    else\n      ## FIXME: Is this the right behavior, or should it produce an error?\n      retval = [];\n    endif\n  else\n    if (! (ischar (pref) || iscellstr (pref)))\n      error (\"getpref: PREF must be a string or cellstr\");\n    endif\n\n    grp = getpref (group);\n\n    if (ischar (pref))\n      if (isfield (grp, pref))\n        retval = grp.(pref);\n      elseif (nargin == 3)\n        addpref (group, pref, default);\n        retval = default;\n      else\n        error (\"getpref: preference %s does not exist in GROUP %s\",\n               pref, group);\n      endif\n    else\n      if (nargin != 2 && ! size_equal (pref, default))\n        error (\"getpref: size mismatch for PREF and DEFAULT\");\n      endif\n\n      for i = 1:numel (pref)\n        if (isfield (grp, pref{i}))\n          retval{i} = grp.(pref{i});\n        elseif (nargin == 3)\n          addpref (group, pref{i}, default{i});\n          retval{i} = default{i};\n        else\n          error (\"getpref: preference %s does not exist in GROUP %s\",\n                 pref{i}, group);\n        endif\n      endfor\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! HOME = getenv (\"HOME\");\n%! tmp_home = tempname ();\n%! save_default_options (\"-binary\", \"local\");\n%! unwind_protect\n%!   mkdir (tmp_home);\n%!   setenv (\"HOME\", tmp_home);\n%!\n%!   addpref (\"group1\", \"pref1\", [1 2 3]);\n%!   addpref (\"group2\", {\"prefA\", \"prefB\"}, {\"StringA\", {\"StringB\"}});\n%!\n%!   exp.group1.pref1 = [1 2 3];\n%!   exp.group2.prefA = \"StringA\";\n%!   exp.group2.prefB = {\"StringB\"};\n%!   obs = getpref ();\n%!   assert (obs, exp);\n%!\n%!   assert (getpref (\"group1\"), exp.group1);\n%!   assert (getpref (\"group2\"), exp.group2);\n%!   assert (getpref (\"group3\"), []);\n%!\n%!   assert (getpref (\"group1\", \"pref1\"), [1 2 3]);\n%!   assert (getpref (\"group2\", \"prefA\"), \"StringA\");\n%!   assert (getpref (\"group2\", \"prefB\"), {\"StringB\"});\n%!   assert (getpref (\"group1\", \"pref2\", \"New_Value\"), \"New_Value\");\n%!   assert (getpref (\"group1\", \"pref2\"), \"New_Value\");\n%!   fail ('getpref (\"group1\", \"no_such_pref\")', ...\n%!         \"preference no_such_pref does not exist in GROUP group1\");\n%!\n%!   assert (getpref (\"group2\", {\"prefA\", \"prefB\"}), {\"StringA\", {\"StringB\"}});\n%!   assert (getpref (\"group2\", {\"prefA\", \"prefC\"}, {1, \"StringC\"}),\n%!           {\"StringA\", \"StringC\"});\n%!   assert (getpref (\"group2\", \"prefC\"), \"StringC\");\n%!   fail ('getpref (\"group1\", {\"p1\", \"p2\"}, 1)', ...\n%!         \"size mismatch for PREF and DEFAULT\");\n%!   fail ('getpref (\"group2\", {\"prefA\", \"prefD\"})',\n%!         \"preference prefD does not exist in GROUP group2\");\n%!\n%! unwind_protect_cleanup\n%!   unlink (fullfile (tmp_home, \".octave_prefs\"));\n%!   sts = rmdir (tmp_home);\n%!   if (isempty (HOME))\n%!     unsetenv (\"HOME\");\n%!   else\n%!     setenv (\"HOME\", HOME);\n%!   endif\n%! end_unwind_protect\n\n%!error <GROUP must be a string> getpref (1)\n%!error <PREF must be a string> getpref (\"group1\", 1, 2)\n"
  },
  {
    "path": "scripts/prefs/ispref.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} ispref (\"@var{group}\", \"@var{pref}\")\n## @deftypefnx {} {@var{tf} =} ispref (\"@var{group}\", @{\"@var{pref1}\", \"@var{pref2\"}, @dots{}@})\n## @deftypefnx {} {@var{tf} =} ispref (\"@var{group}\")\n## Return true if the named preference @var{pref} exists in the preference\n## group @var{group}.\n##\n## The named preference group must be a string.\n##\n## The preference @var{pref} may be a string or a cell array of strings.\n##\n## If @var{pref} is not specified, return true if the preference group\n## @var{group} exists.\n## @seealso{getpref, addpref, setpref, rmpref}\n## @end deftypefn\n\nfunction tf = ispref (group, pref = \"\")\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  if (! ischar (group))\n    error (\"ispref: GROUP must be a string\");\n  endif\n  if (! (ischar (pref) || iscellstr (pref)))\n    error (\"ispref: PREF must be a string or cellstr\");\n  endif\n\n  if (nargin == 1)\n    tf = isfield (loadprefs (), group);\n  else\n    prefs = loadprefs ();\n    if (isfield (prefs, group))\n      tf = isfield (prefs.(group), pref);\n    else\n      if (ischar (pref))\n        tf = false;\n      else\n        tf = false (size (pref));\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! HOME = getenv (\"HOME\");\n%! save_default_options (\"-binary\", \"local\");\n%! unwind_protect\n%!   setenv (\"HOME\", P_tmpdir ());\n%!   addpref (\"group1\", \"pref1\", [1 2 3]);\n%!   addpref (\"group2\", {\"prefA\", \"prefB\"}, {\"StringA\", {\"StringB\"}});\n%!\n%!   assert (ispref (\"group1\"));\n%!   assert (! ispref (\"group3\"));\n%!\n%!   assert (ispref (\"group2\", \"prefB\"));\n%!   assert (! ispref (\"group2\", \"prefC\"));\n%!\n%!   assert (ispref (\"group2\", {\"prefB\", \"prefC\"}), [true, false]);\n%!\n%!   assert (ispref (\"group3\", \"prefB\"), false);\n%!   assert (ispref (\"group3\", {\"prefB\", \"prefC\"}), [false, false]);\n%!\n%! unwind_protect_cleanup\n%!   unlink (fullfile (P_tmpdir (), \".octave_prefs\"));\n%!   if (isempty (HOME))\n%!     unsetenv (\"HOME\");\n%!   else\n%!     setenv (\"HOME\", HOME);\n%!   endif\n%! end_unwind_protect\n\n%!error <Invalid call> ispref ()\n%!error <GROUP must be a string> ispref (1, \"pref1\")\n%!error <PREF must be a string> ispref (\"group1\", 1)\n"
  },
  {
    "path": "scripts/prefs/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/loadprefs.m \\\n  %reldir%/private/prefsfile.m \\\n  %reldir%/private/saveprefs.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/addpref.m \\\n  %reldir%/getpref.m \\\n  %reldir%/ispref.m \\\n  %reldir%/prefdir.m \\\n  %reldir%/preferences.m \\\n  %reldir%/rmpref.m \\\n  %reldir%/setpref.m\n\n%canon_reldir%dir = $(fcnfiledir)/prefs\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/prefs/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/prefs/prefdir.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{dir} =} prefdir\n## @deftypefnx {} {@var{dir} =} prefdir (1)\n## Return the directory that holds the preferences for Octave.\n##\n## Examples:\n##\n## Display the preferences directory\n##\n## @example\n## prefdir\n## @end example\n##\n## Change to the preferences folder\n##\n## @example\n## cd (prefdir)\n## @end example\n##\n## If called with an argument, the preferences directory is created if it\n## doesn't already exist.\n## @seealso{getpref, setpref, addpref, rmpref, ispref}\n## @end deftypefn\n\nfunction dir = prefdir ()\n\n  dir = get_home_directory ();\n\n  if (nargin > 0)\n    if (! isfolder (dir))\n      mkdir (dir);\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/prefs/preferences.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} preferences\n## Display the GUI preferences dialog window for Octave.\n## @end deftypefn\n\nfunction preferences ()\n\n  if (isguirunning ())\n    __event_manager_show_preferences__ ();\n  else\n    warning (\"preferences: GUI must be running to use preferences dialog\");\n  endif\n\nendfunction\n\n\n%!test\n%! if (isguirunning ())\n%!   return;\n%! endif\n%! fail (\"preferences ()\", \"warning\", \"GUI must be running\");\n"
  },
  {
    "path": "scripts/prefs/private/loadprefs.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{prefs} =} loadprefs ()\n## Return a structure containing all user configured preferences.\n## @end deftypefn\n\nfunction retval = loadprefs ()\n\n  file = prefsfile ();\n\n  s = stat (file);\n\n  if (isstruct (s) && S_ISREG (s.mode))\n    tmp = load (file);\n    retval = tmp.prefs;\n  else\n    retval = [];\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/prefs/private/prefsfile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{fname} =} prefsfile ()\n## Return the full path and name of the file containing Octave preferences.\n## @end deftypefn\n\nfunction fname = prefsfile ()\n\n  fname = [prefdir() filesep() \".octave_prefs\"];\n\nendfunction\n"
  },
  {
    "path": "scripts/prefs/private/saveprefs.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} saveprefs (@var{s})\n## Save user preferences in the structure @var{s} to Octave's preference file.\n## @end deftypefn\n\nfunction saveprefs (s)\n\n  prefs = s;\n\n  save (prefsfile (), \"prefs\");\n\nendfunction\n"
  },
  {
    "path": "scripts/prefs/rmpref.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} rmpref (\"@var{group}\", \"@var{pref}\")\n## @deftypefnx {} {} rmpref (\"@var{group}\", @{\"@var{pref1}\", \"@var{pref2}\", @dots{}@})\n## @deftypefnx {} {} rmpref (\"@var{group}\")\n## Remove the named preference @var{pref} from the preference group\n## @var{group}.\n##\n## The named preference group must be a string.\n##\n## The preference @var{pref} may be a string or cell array of strings.\n##\n## If @var{pref} is not specified, remove the preference group @var{group}.\n##\n## It is an error to remove a nonexistent preference or group.\n## @seealso{addpref, ispref, setpref, getpref}\n## @end deftypefn\n\nfunction rmpref (group, pref)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! ischar (group))\n    error (\"rmpref: GROUP must be a string\");\n  elseif (nargin == 2 && ! (ischar (pref) || iscellstr (pref)))\n    error (\"rmpref: PREF must be a string or cell array of strings\");\n  endif\n\n  if (nargin == 1)\n    if (! ispref (group))\n      error (\"rmpref: GROUP %s does not exist\", group);\n    endif\n    prefs = loadprefs ();\n    prefs = rmfield (prefs, group);\n    saveprefs (prefs);\n  else\n    valid = ispref (group, pref);\n    if (all (valid))\n      prefs = loadprefs ();\n      prefs.(group) = rmfield (prefs.(group), pref);\n      saveprefs (prefs);\n    else\n      if (! ispref (group))\n        error (\"rmpref: GROUP %s does not exist\", group);\n      elseif (ischar (pref))\n        error (\"rmpref: preference %s does not exist\", pref);\n      else\n        idx = find (! valid, 1);\n        error (\"rmpref: preference %s does not exist\", pref{idx});\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! HOME = getenv (\"HOME\");\n%! save_default_options (\"-binary\", \"local\");\n%! unwind_protect\n%!   setenv (\"HOME\", P_tmpdir ());\n%!   addpref (\"group1\", \"pref1\", [1 2 3]);\n%!   addpref (\"group2\", {\"prefA\", \"prefB\", \"prefC\"}, {\"strA\", \"strB\", \"strC\"});\n%!\n%!   assert (ispref (\"group1\"));\n%!   rmpref (\"group1\");\n%!   assert (! ispref (\"group1\"));\n%!\n%!   assert (ispref (\"group2\", \"prefB\"));\n%!   rmpref (\"group2\", \"prefB\");\n%!   assert (! ispref (\"group2\", \"prefB\"));\n%!\n%!   fail ('rmpref (\"group3\")', ...\n%!         \"GROUP group3 does not exist\");\n%!   fail ('rmpref (\"group3\", \"prefA\")', ...\n%!         \"GROUP group3 does not exist\");\n%!   fail ('rmpref (\"group2\", \"prefB\")',\n%!         \"preference prefB does not exist\");\n%!   fail ('rmpref (\"group2\", {\"prefA\", \"prefB\"})',\n%!         \"preference prefB does not exist\");\n%!\n%! unwind_protect_cleanup\n%!   unlink (fullfile (P_tmpdir (), \".octave_prefs\"));\n%!   if (isempty (HOME))\n%!     unsetenv (\"HOME\");\n%!   else\n%!     setenv (\"HOME\", HOME);\n%!   endif\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> rmpref ()\n%!error <GROUP must be a string> rmpref (1)\n%!error <PREF must be a string> rmpref (\"group1\", 1)\n"
  },
  {
    "path": "scripts/prefs/setpref.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} setpref (\"@var{group}\", \"@var{pref}\", @var{val})\n## @deftypefnx {} {} setpref (\"@var{group}\", @{\"@var{pref1}\", \"@var{pref2}\", @dots{}@}, @{@var{val1}, @var{val2}, @dots{}@})\n## Set the preference @var{pref} to the given @var{val} in the named preference\n## group @var{group}.\n##\n## The named preference group must be a string.\n##\n## The preference @var{pref} may be a string or a cell array of strings.\n##\n## The corresponding value @var{val} may be any Octave value, .e.g., double,\n## struct, cell array, object, etc.  Or, if @var{pref} is a cell array of\n## strings then @var{val} must be a cell array of values with the same size as\n## @var{pref}.\n##\n## If the named preference or group does not exist, it is added.\n## @seealso{addpref, getpref, ispref, rmpref}\n## @end deftypefn\n\nfunction setpref (group, pref, val)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (! ischar (group))\n    error (\"setpref: GROUP must be a string\");\n  endif\n  if (! (ischar (pref) || iscellstr (pref)))\n    error (\"setpref: PREF must be a string or cellstr\");\n  endif\n\n  prefs = loadprefs ();\n\n  if (ischar (pref))\n    prefs.(group).(pref) = val;\n  else\n    if (! size_equal (pref, val))\n      error (\"setpref: size mismatch for PREF and VAL\");\n    endif\n\n    for i = 1:numel (pref)\n      prefs.(group).(pref{i}) = val{i};\n    endfor\n  endif\n\n  saveprefs (prefs);\n\nendfunction\n\n\n%!test\n%! HOME = getenv (\"HOME\");\n%! tmp_home = tempname ();\n%! unwind_protect\n%!   mkdir (tmp_home);\n%!   setenv (\"HOME\", tmp_home);\n%!\n%!   setpref (\"group1\", \"pref1\", [1 2 3]);\n%!   assert (getpref (\"group1\", \"pref1\"), [1 2 3]);\n%!\n%!   setpref (\"group2\", {\"prefA\", \"prefB\"}, {\"StringA\", {\"StringB\"}});\n%!   assert (getpref (\"group2\", \"prefA\"), \"StringA\");\n%!   assert (getpref (\"group2\", \"prefB\"), {\"StringB\"});\n%!\n%!   setpref (\"group1\", {\"pref1\", \"pref2\"}, {1, 2});\n%!   assert (getpref (\"group1\", \"pref1\"), 1);\n%!   assert (getpref (\"group1\", \"pref2\"), 2);\n%!\n%!   fail ('setpref (\"group1\", {\"p1\", \"p2\"}, 1)', ...\n%!         \"size mismatch for PREF and VAL\");\n%! unwind_protect_cleanup\n%!   unlink (fullfile (tmp_home, \".octave_prefs\"));\n%!   sts = rmdir (tmp_home);\n%!   if (isempty (HOME))\n%!     unsetenv (\"HOME\");\n%!   else\n%!     setenv (\"HOME\", HOME);\n%!   endif\n%! end_unwind_protect\n\n## Test input validation\n%!error <Invalid call> setpref ()\n%!error <Invalid call> setpref (1)\n%!error <Invalid call> setpref (1,2)\n%!error <GROUP must be a string> setpref (1, \"pref1\", 2)\n%!error <PREF must be a string> setpref (\"group1\", 1, 2)\n"
  },
  {
    "path": "scripts/profiler/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/profiler/html/flat-entry.html",
    "content": "<tr>\n  <td><a href=\"function-%num.html\">%name</a></td>\n  <td>%timeabs</td>\n  <td>%timerel</td>\n  <td>%calls</td>\n</tr>\n"
  },
  {
    "path": "scripts/profiler/html/flat.html",
    "content": "<!-- This file was generated by GNU Octave's profiler.  -->\n<!DOCTYPE html>\n<html>\n  <head>\n    <title>%title</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  </head>\n  <body>\n    <h1>Flat %title</h1>\n    <p><a href=\"hierarchy-1.html\">hierarchical profile</a></p>\n    <table>\n      <thead>\n        <tr>\n          <th>Function</th>\n          <th>Time (s)</th>\n          <th>Time (%)</th>\n          <th>Calls</th>\n        </tr>\n      </thead>\n      <tbody>\n%entries\n      </tbody>\n    </table>\n  </body>\n</html>\n"
  },
  {
    "path": "scripts/profiler/html/function.html",
    "content": "<!-- This file was generated by GNU Octave's profiler.  -->\n<!DOCTYPE html>\n<html>\n  <head>\n    <title>%title</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  </head>\n  <body>\n    <h1>Function %name</h1>\n    <p><a href=\"index.html\">flat profile</a></p>\n    <dl>\n      <dt>Attributes:</dt>\n      <dd>%attr</dd>\n      <dt>Total time:</dt>\n      <dd>%timeabs seconds</dd>\n      <dt>Number of calls:</dt>\n      <dd>%calls</dd>\n      <dt>Called by:</dt>\n      <dd>%parents</dd>\n      <dt>Calling:</dt>\n      <dd>%children</dd>\n    </dl>\n  </body>\n</html>\n"
  },
  {
    "path": "scripts/profiler/html/hierarchical-entry.html",
    "content": "<tr>\n  <td><a href=\"hierarchy-%cnt.html\">%name</a></td>\n  <td>%total</td>\n  <td>%self</td>\n  <td>%calls</td>\n</tr>\n"
  },
  {
    "path": "scripts/profiler/html/hierarchical.html",
    "content": "<!-- This file was generated by GNU Octave's profiler.  -->\n<!DOCTYPE html>\n<html>\n  <head>\n    <title>%title</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  </head>\n  <body>\n    <h1>Hierarchical %title</h1>\n    <p><a href=\"index.html\">flat profile</a></p>\n    <p>%parents</p>\n    <table>\n      <thead>\n        <tr>\n          <th>Function</th>\n          <th>Total (s)</th>\n          <th>Self (s)</th>\n          <th>Calls</th>\n        </tr>\n      </thead>\n      <tbody>\n%entries\n      </tbody>\n    </table>\n  </body>\n</html>\n"
  },
  {
    "path": "scripts/profiler/html/style.css",
    "content": "/*\n\nCopyright (C) 2016-2026 The Octave Project Developers\n\nSee the file COPYRIGHT.md in the top-level directory of this\ndistribution or <https://octave.org/copyright/>.\n\nThis file is part of Octave.\n\nOctave is free software: you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nOctave is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with Octave; see the file COPYING.  If not, see\n<https://www.gnu.org/licenses/>.\n\n*/\n\ntr:nth-of-type(odd)\n{\n  background-color: #ccc;\n}\n"
  },
  {
    "path": "scripts/profiler/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/profexplore.m \\\n  %reldir%/profexport.m \\\n  %reldir%/profile.m \\\n  %reldir%/profshow.m\n\n%canon_reldir%dir = $(fcnfiledir)/profiler\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_htmldir = $(octetcdir)/profiler\n\n%canon_reldir%_html_DATA = \\\n  %reldir%/html/flat.html \\\n  %reldir%/html/flat-entry.html \\\n  %reldir%/html/function.html \\\n  %reldir%/html/hierarchical.html \\\n  %reldir%/html/hierarchical-entry.html \\\n  %reldir%/html/style.css\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nscripts_EXTRA_DIST += \\\n  $(%canon_reldir%_html_DATA)\n"
  },
  {
    "path": "scripts/profiler/profexplore.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} profexplore ()\n## @deftypefnx {} {} profexplore (@var{data})\n## Interactively explore hierarchical profiler output.\n##\n## Assuming @var{data} is the structure with profile data returned by\n## @code{profile (@qcode{\"info\"})}, this command opens an interactive prompt\n## that can be used to explore the call-tree.  Type @kbd{help} to get a list\n## of possible commands.  If @var{data} is omitted, @code{profile (\"info\")}\n## is called and used in its place.\n## @seealso{profile, profshow}\n## @end deftypefn\n\nfunction profexplore (data)\n\n  if (nargin == 0)\n    data = profile (\"info\");\n  endif\n\n  ## The actual work is done by a recursive worker function, since that\n  ## is an easy way to traverse the tree datastructure.  Here, we just check\n  ## the arguments (already done) and give over to it.\n\n  __profexplore_worker (data.FunctionTable, data.Hierarchical, \"Top\\n\", \"  \");\n\nendfunction\n\n## This is the worker function.  tree is the current subtree we want to\n## display / explore.  parents is a string containing the already \"rendered\"\n## data for the parents which is displayed on top of the list of current\n## children.  prefix is the prefix to add to each line rendered; this\n## is just a string of spaces to get indentation right.\n##\n## Returning 0 indicates that the user requested to totally exit the\n## explorer, thus also all higher levels should exit immediately.  An integer\n## greater zero indicates to exit that many levels since the user wants to go\n## up (but not necessarily quit).\n\nfunction rv = __profexplore_worker (fcn_table, tree, parents, prefix)\n\n  ## Sort children by total time.\n  times = -[ tree.TotalTime ];\n  [~, p] = sort (times);\n  tree = tree(p);\n\n  while (true)\n\n    printf (\"\\n%s\", parents);\n    strings = cell (length (tree), 1);\n    for i = 1 : length (tree)\n      strings{i} = sprintf (\"%s: %d calls, %.3f total, %.3f self\", ...\n                            fcn_table(tree(i).Index).FunctionName, ...\n                            tree(i).NumCalls, ...\n                            tree(i).TotalTime, tree(i).SelfTime);\n      printf (\"%s%d) %s\\n\", prefix, i, strings{i});\n    endfor\n    printf (\"\\n\");\n\n    cmd = input (\"profexplore> \", \"s\");\n    option = fix (str2double (cmd));\n\n    if (strcmp (cmd, \"exit\") || strcmp (cmd, \"quit\"))\n      rv = 0;\n      return;\n    elseif (strcmp (cmd, \"help\"))\n      printf (\"\\nCommands for profile explorer:\\n\\n\");\n      printf (\"exit   Return to Octave prompt.\\n\");\n      printf (\"quit   Return to Octave prompt.\\n\");\n      printf (\"help   Display this help message.\\n\");\n      printf (\"up [N] Go up N levels, where N is an integer.  Default is 1.\\n\");\n      printf (\"N      Go down a level into option N.\\n\");\n    elseif (! isnan (option))\n      if (option < 1 || option > length (tree))\n        printf (\"The chosen option is out of range!\\n\");\n      else\n        newParents = sprintf (\"%s%s%s\\n\", parents, prefix, strings{option});\n        newPrefix = sprintf (\"%s  \", prefix);\n\n        rv = __profexplore_worker (fcn_table, tree(option).Children, ...\n                                   newParents, newPrefix);\n\n        if (rv == 0)\n          return;\n        elseif (rv > 1)\n          rv -= 1;\n          return;\n        else\n          assert (rv == 1);\n          ## It was requested to return to this level, so just stay.\n        endif\n      endif\n    elseif (length (cmd) >= 2 && strcmp (substr (cmd, 1, 2), \"up\"))\n      if (length (cmd) == 2)\n        rv = 1;\n        return;\n      endif\n\n      if (length (cmd) > 3 && cmd(3) == ' ')\n        opt = fix (str2double (substr (cmd, 3)));\n        if (! isnan (opt) && opt > 0)\n          rv = opt;\n          return;\n        endif\n      endif\n\n      printf (\"Invalid 'up' command.  Type 'help' for further\");\n      printf (\" information.\\n\");\n    else\n      printf (\"Unrecognized input.  Type 'help' to get a list of possible\");\n      printf (\" commands.\\n\");\n    endif\n\n  endwhile\n\nendfunction\n"
  },
  {
    "path": "scripts/profiler/profexport.m",
    "content": "########################################################################\n##\n## Copyright (C) 2015-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} profexport (@var{dir})\n## @deftypefnx {} {} profexport (@var{dir}, @var{data})\n## @deftypefnx {} {} profexport (@var{dir}, @var{name})\n## @deftypefnx {} {} profexport (@var{dir}, @var{name}, @var{data})\n##\n## Export profiler data as HTML.\n##\n## Export the profiling data in @var{data} into a series of HTML files in\n## the folder @var{dir}.  The initial file will be\n## @file{@var{data}/index.html}.\n##\n## If @var{name} is specified, it must be a string that contains a ``name''\n## for the profile being exported.  This name is included in the HTML.\n##\n## The input @var{data} is the structure returned by @code{profile (\"info\")}.\n## If unspecified, @code{profexport} will use the current profile dataset.\n##\n## @seealso{profshow, profexplore, profile}\n## @end deftypefn\n\nfunction profexport (dir, name = \"\", data)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! ischar (dir))\n    error (\"profexport: DIR must be a string\");\n  endif\n\n  if (nargin == 1)\n    data = profile (\"info\");\n  elseif (nargin == 2)\n    if (isstruct (name))\n      data = name;\n      name = \"\";\n    else\n      if (! ischar (name))\n        error (\"profexport: NAME must be a string\");\n      endif\n      data = profile (\"info\");\n    endif\n  endif\n\n  if (! isfolder (dir))\n    ok = mkdir (dir);\n    if (! ok)\n      error (\"profexport: failed to create output directory '%s'\", dir);\n    endif\n  endif\n\n  if (! copyfile (__dataFilename (\"style.css\"), dir))\n    error (\"profexport: failed to copy data file to directory '%s'\", dir);\n  endif\n\n  if (isempty (name))\n    name = \"Profile\";\n  else\n    name = [\"Profile - \" __escapeHtml(name)];\n  endif\n\n  __writeFlat (fullfile (dir, \"index.html\"), name, data.FunctionTable);\n  for i = 1 : length (data.FunctionTable)\n    __writeFunc (fullfile (dir, sprintf (\"function-%d.html\", i)), name, ...\n                 data.FunctionTable, i);\n  endfor\n\n  top = struct (\"name\", \"Top\");\n  __writeHierarchical (dir, name, data.FunctionTable, ...\n                       {top}, data.Hierarchical, 1);\n\nendfunction\n\n################################################################################\n## Write flat profile.\n\nfunction __writeFlat (file, name, table)\n\n  template = __readTemplate (\"flat.html\");\n  entryTemplate = __readTemplate (\"flat-entry.html\");\n\n  ## Construct the entries string.\n  ## This follows the same logic that is used in profshow.\n  times = [ table.TotalTime ];\n  totalTime = sum (times);\n  [~, p] = sort (times, \"descend\");\n  entries = \"\";\n  for i = 1 : length (table)\n    row = table(p(i));\n\n    cur = entryTemplate;\n    cur = strrep (cur, \"%num\", sprintf (\"%d\", p(i)));\n    cur = strrep (cur, \"%name\", __escapeHtml (row.FunctionName));\n    cur = strrep (cur, \"%timeabs\", sprintf (\"%.3f\", row.TotalTime));\n    cur = strrep (cur, \"%timerel\", ...\n                  sprintf (\"%.2f\", 100 * row.TotalTime / totalTime));\n    cur = strrep (cur,  \"%calls\", sprintf (\"%d\", row.NumCalls));\n\n    entries = [entries, cur];\n  endfor\n\n  ## Build full page content.\n  res = template;\n  res = strrep (res, \"%title\", name);\n  res = strrep (res, \"%entries\", entries);\n\n  ## Write out the file.\n  __writeToFile (file, res);\n\nendfunction\n\n################################################################################\n## Write \"function profile\" pages.\n\nfunction __writeFunc (file, name, table, ind)\n\n  template = __readTemplate (\"function.html\");\n  row = table(ind);\n\n  ## Fill in basic data.\n  res = template;\n  res = strrep (res, \"%title\", name);\n  res = strrep (res, \"%name\", __escapeHtml (row.FunctionName));\n  res = strrep (res, \"%timeabs\", sprintf (\"%.3f\", row.TotalTime));\n  res = strrep (res, \"%calls\", sprintf (\"%d\", row.NumCalls));\n\n  ## Build up attribute list.\n  attr = \"\";\n  if (row.IsRecursive)\n    attr = \"recursive\";\n  endif\n  res = strrep (res, \"%attr\", attr);\n\n  ## Add parent and child list.\n  parents = __buildParentOrChildList (table, row.Parents);\n  res = strrep (res, \"%parents\", parents);\n  children = __buildParentOrChildList (table, row.Children);\n  res = strrep (res, \"%children\", children);\n\n  ## Write out the file.\n  __writeToFile (file, res);\n\nendfunction\n\nfunction lst = __buildParentOrChildList (table, inds)\n\n  if (length (inds) == 0)\n    lst = \"none\";\n    return;\n  endif\n\n  template = \"<a href='function-%num.html'>%name</a>\";\n\n  lst = \"\";\n  for i = 1 : length (inds)\n    if (i > 1)\n      lst = [lst, \", \"];\n    endif\n\n    cur = template;\n    cur = strrep (cur, \"%num\", sprintf (\"%d\", inds(i)));\n    cur = strrep (cur, \"%name\", __escapeHtml (table(inds(i)).FunctionName));\n    lst = [lst, cur];\n  endfor\n\nendfunction\n\n################################################################################\n## Write a hierarchical profile page.\n\n## In order to generate unique filenames for the pages, we keep a running\n## counter that is passed through and updated by the recursive calls.\n## The function returns two counter values: The one that is chosen\n## for its own page (so that parent nodes can link down to them)\n## and the next value to be passed to the next call.\n\nfunction [mine, cnt] = __writeHierarchical (dir, name, funcs, ...\n                                            parents, children, cnt)\n\n  template = __readTemplate (\"hierarchical.html\");\n  entryTemplate = __readTemplate (\"hierarchical-entry.html\");\n\n  ## Fill in basic data and parent breadcrumbs.\n  res = template;\n  res = strrep (res, \"%title\", name);\n  parentsStr = __hierarchicalParents (parents);\n  res = strrep (res, \"%parents\", parentsStr);\n\n  ## Set this page's counter and update parents struct with it.\n  mine = cnt++;\n  parents{end}.cnt = mine;\n  file = sprintf (\"%s/hierarchy-%d.html\", dir, mine);\n\n  ## Sort children by time.\n  times = -[ children.TotalTime ];\n  [~, p] = sort (times);\n  children = children(p);\n\n  ## Recurse on children and construct entry list.\n  entries = \"\";\n  for i = 1 : length (children)\n    cur = children(i);\n    curName = funcs(cur.Index).FunctionName;\n\n    newParents = parents;\n    newParents{end + 1} = struct (\"name\", curName);\n    [childCnt, cnt] = __writeHierarchical (dir, name, funcs, ...\n                                           newParents, cur.Children, cnt);\n\n    str = entryTemplate;\n    str = strrep (str, \"%cnt\", sprintf (\"%d\", childCnt));\n    str = strrep (str, \"%name\", __escapeHtml (curName));\n    str = strrep (str, \"%total\", sprintf (\"%.3f\", cur.TotalTime));\n    str = strrep (str, \"%self\", sprintf (\"%.3f\", cur.SelfTime));\n    str = strrep (str, \"%calls\", sprintf (\"%d\", cur.NumCalls));\n\n    entries = [entries, str];\n  endfor\n  res = strrep (res, \"%entries\", entries);\n\n  ## Write out the file.\n  __writeToFile (file, res);\n\nendfunction\n\nfunction str = __hierarchicalParents (parents)\n\n  ## We always have at least the \"Top\" entry!\n  assert (length (parents) > 0);\n\n  template = \"<a href='hierarchy-%cnt.html'>%name</a>\";\n  lastTemplate = \"<strong>%name</strong>\";\n\n  str = \"\";\n  for i = 1 : length (parents) - 1\n    cur = template;\n    cur = strrep (cur, \"%cnt\", sprintf (\"%d\", parents{i}.cnt));\n    cur = strrep (cur, \"%name\", __escapeHtml (parents{i}.name));\n    str = [str, cur, \" > \"];\n  endfor\n\n  cur = lastTemplate;\n  cur = strrep (cur, \"%name\", __escapeHtml (parents{end}.name));\n  str = [str, cur];\n\nendfunction\n\n################################################################################\n## General helper functions.\n\nfunction __writeToFile (file, str)\n\n  fid = fopen (file, \"w\");\n  if (fid < 0)\n    error (\"profexport: failed to open '%s' for writing\", file);\n  endif\n  fputs (fid, str);\n  fclose (fid);\n\nendfunction\n\nfunction fn = __dataFilename (name)\n  etcdir = __octave_config_info__ (\"octetcdir\");\n  fn = fullfile (etcdir, \"profiler\", name);\nendfunction\n\nfunction str = __readTemplate (name)\n  fn = __dataFilename (name);\n  str = fileread (fn);\nendfunction\n\nfunction str = __escapeHtml (str)\n  str = strrep (str, '&', \"&amp;\");\n  str = strrep (str, '<', \"&lt;\");\n  str = strrep (str, '>', \"&gt;\");\n  str = strrep (str, '\"', \"&quot;\");\nendfunction\n\n################################################################################\n## Tests and demo.\n\n%!demo\n%! profile on;\n%! A = rand (100);\n%! B = expm (A);\n%! profile off;\n%! dir = tempname ();\n%! profexport (dir, \"Example Profile\");\n%! open (fullfile (dir, \"index.html\"));\n\n## Test input validation\n%!error <Invalid call> profexport ()\n%!error profexport (1)\n%!error profexport (1, 2, 3, 4)\n%!error <DIR must be a string> profexport (5)\n%!error <NAME must be a string> profexport (\"dir\", 5)\n"
  },
  {
    "path": "scripts/profiler/profile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} profile on\n## @deftypefnx {} {} profile off\n## @deftypefnx {} {} profile resume\n## @deftypefnx {} {} profile clear\n## @deftypefnx {} {@var{S} =} profile (\"status\")\n## @deftypefnx {} {@var{T} =} profile (\"info\")\n## Control the built-in profiler.\n##\n## @table @code\n## @item profile on\n## Start the profiler.  Any previously collected data is cleared.\n##\n## @item profile off\n## Stop profiling.  The collected data can later be retrieved and examined\n## with @code{T = profile (\"info\")}.\n##\n## @item profile clear\n## Clear all collected profiler data and stop profiling.\n##\n## @item profile resume\n## Restart profiling without clearing the old data.  All newly collected\n## statistics are added to the existing ones.\n##\n## @item @var{S} = profile (\"status\")\n## Return a structure with information about the current status of the\n## profiler.  At the moment, the only field is @code{ProfilerStatus} which is\n## either @qcode{\"on\"} or @qcode{\"off\"}.\n##\n## @item @var{T} = profile (\"info\")\n## Return the collected profiling statistics in the structure @var{T}.  The\n## flat profile is returned in the field @code{FunctionTable} which is an\n## array of structures, each entry corresponding to a function which was called\n## and for which profiling statistics are present.  In addition, the field\n## @code{Hierarchical} contains the hierarchical call tree.  Each node has an\n## index into the @code{FunctionTable} identifying the function it corresponds\n## to as well as data fields for number of calls and time spent at this level\n## in the call tree.\n## @end table\n##\n## @seealso{profshow, profexplore}\n## @end deftypefn\n\nfunction retval = profile (arg)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  switch (arg)\n    case \"on\"\n      if (__profiler_enable__ ())\n        __profiler_enable__ (false);\n      endif\n      __profiler_reset__ ();\n      __profiler_enable__ (true);\n\n    case \"off\"\n      __profiler_enable__ (false);\n\n    case \"clear\"\n      if (__profiler_enable__ ())\n        __profiler_enable__ (false);\n      endif\n      __profiler_reset__ ();\n\n    case \"resume\"\n      __profiler_enable__ (true);\n\n    case \"status\"\n      enabled = ifelse (__profiler_enable__ (), 'on', 'off');\n      retval = struct (\"ProfilerStatus\", enabled);\n\n    case \"info\"\n      [flat, tree] = __profiler_data__ ();\n      retval = struct (\"FunctionTable\", flat, \"Hierarchical\", tree);\n\n    otherwise\n      warning (\"profile: Unrecognized option '%s'\", arg);\n      print_usage ();\n\n  endswitch\n\nendfunction\n\n\n%!demo\n%! profile on;\n%! A = rand (100);\n%! B = expm (A);\n%! profile off;\n%! profile resume;\n%! C = sqrtm (A);\n%! profile off;\n%! T = profile (\"info\");\n%! profshow (T);\n\n%!test\n%! on_struct.ProfilerStatus = \"on\";\n%! off_struct.ProfilerStatus = \"off\";\n%! profile (\"on\");\n%! result = logm (rand (200) + 10 * eye (200));\n%! assert (profile (\"status\"), on_struct);\n%! profile (\"off\");\n%! assert (profile (\"status\"), off_struct);\n%! profile (\"resume\");\n%! result = logm (rand (200) + 10 * eye (200));\n%! profile (\"off\");\n%! assert (profile (\"status\"), off_struct);\n%! info = profile (\"info\");\n%! assert (isstruct (info));\n%! assert (size (info), [1, 1]);\n%! assert (fieldnames (info), {\"FunctionTable\"; \"Hierarchical\"});\n%! ftbl = info.FunctionTable;\n%! assert (fieldnames (ftbl), {\"FunctionName\"; \"TotalTime\"; \"NumCalls\"; \"IsRecursive\"; \"Parents\"; \"Children\"});\n%! hier = info.Hierarchical;\n%! assert (fieldnames (hier), {\"Index\"; \"SelfTime\"; \"TotalTime\"; \"NumCalls\"; \"Children\"});\n%! profile (\"clear\");\n%! info = profile (\"info\");\n%! assert (isstruct (info));\n%! assert (size (info), [1, 1]);\n%! assert (fieldnames (info), {\"FunctionTable\"; \"Hierarchical\"});\n%! ftbl = info.FunctionTable;\n%! assert (size (ftbl), [0, 1]);\n%! assert (fieldnames (ftbl), {\"FunctionName\"; \"TotalTime\"; \"NumCalls\"; \"IsRecursive\"; \"Parents\"; \"Children\"});\n%! hier = info.Hierarchical;\n%! assert (size (hier), [0, 1]);\n%! assert (fieldnames (hier), {\"Index\"; \"SelfTime\"; \"TotalTime\"; \"NumCalls\"; \"Children\"});\n\n## Test input validation\n%!error <Invalid call> profile ()\n%!error profile (\"INVALID_OPTION\")\n"
  },
  {
    "path": "scripts/profiler/profshow.m",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} profshow (@var{data})\n## @deftypefnx {} {} profshow (@var{data}, @var{n})\n## @deftypefnx {} {} profshow ()\n## @deftypefnx {} {} profshow (@var{n})\n## Display flat per-function profiler results.\n##\n## Print out profiler data (execution time, number of calls) for the most\n## critical @var{n} functions.  The results are sorted in descending order by\n## the total time spent in each function.  If @var{n} is unspecified it\n## defaults to 20.\n##\n## The input @var{data} is the structure returned by @code{profile (\"info\")}.\n## If unspecified, @code{profshow} will use the current profile dataset.\n##\n## The attribute column displays @samp{R} for recursive functions, and is blank\n## for all other function types.\n## @seealso{profexplore, profile}\n## @end deftypefn\n\nfunction profshow (data, n = 20)\n\n  if (nargin == 0)\n    data = profile (\"info\");\n  elseif (nargin == 1 && ! isstruct (data))\n    n = data;\n    data = profile (\"info\");\n  endif\n\n  n = fix (n);\n  if (! isscalar (n) || ! isreal (n) || ! (n > 0))\n    error (\"profile: N must be a positive integer\");\n  endif\n\n  m = length (data.FunctionTable);\n  n = min (n, m);\n\n  ## We want to sort by times in descending order.  For this, extract the\n  ## times to an array, then sort this, and use the resulting index permutation\n  ## to print out our table.\n  times = [ data.FunctionTable.TotalTime ];\n  totalTime = sum (times);\n\n  [~, p] = sort (times, \"descend\");\n\n  ## For printing the table, find out the maximum length of a function name\n  ## so that we can proportion the table accordingly.  Based on this,\n  ## we can build the format used for printing table rows.\n  nameLen = max (length (\"Function\"),\n                 columns (char (data.FunctionTable(p(1:n)).FunctionName)));\n  headerFormat = sprintf (\"%%4s %%%ds %%4s %%12s %%10s %%12s\\n\", nameLen);\n  rowFormat = sprintf (\"%%4d %%%ds %%4s %%12.3f %%10.2f %%12d\\n\", nameLen);\n\n  printf (headerFormat, ...\n          \"#\", \"Function\", \"Attr\", \"Time (s)\", \"Time (%)\", \"Calls\");\n  printf (\"%s\\n\", repmat (\"-\", 1, nameLen + 2 * 5 + 11 + 2 * 13));\n\n  for i = 1 : n\n    row = data.FunctionTable(p(i));\n    timePercent = 100 * row.TotalTime / totalTime;\n    attr = \"\";\n    if (row.IsRecursive)\n      attr = \"R\";\n    endif\n    printf (rowFormat, p(i), row.FunctionName, attr,\n            row.TotalTime, timePercent, row.NumCalls);\n  endfor\n\nendfunction\n\n\n%!demo\n%! profile on;\n%! A = rand (100);\n%! B = expm (A);\n%! profile off;\n%! T = profile (\"info\");\n%! profshow (T, 10);\n\n%!demo\n%! profile on;\n%! expm (rand (500) + eye (500));\n%! profile off;\n%! profshow (profile (\"info\"), 5);\n\n## Test input validation\n%!error <N must be a positive integer> profshow (struct (), ones (2))\n%!error <N must be a positive integer> profshow (struct (), 1+i)\n%!error <N must be a positive integer> profshow (struct (), -1)\n"
  },
  {
    "path": "scripts/set/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/set/intersect.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} intersect (@var{a}, @var{b})\n## @deftypefnx {} {@var{c} =} intersect (@var{a}, @var{b}, \"rows\")\n## @deftypefnx {} {@var{c} =} intersect (@dots{}, \"sorted\")\n## @deftypefnx {} {@var{c} =} intersect (@dots{}, \"stable\")\n## @deftypefnx {} {@var{c} =} intersect (@dots{}, \"legacy\")\n## @deftypefnx {} {[@var{c}, @var{ia}, @var{ib}] =} intersect (@dots{})\n##\n## Return the unique elements common to both @var{a} and @var{b}.\n##\n## If @var{a} and @var{b} are both row vectors then return a row vector;\n## Otherwise, return a column vector.  The inputs may also be cell arrays of\n## strings.\n##\n## If the optional input @qcode{\"rows\"} is given then return the common rows of\n## @var{a} and @var{b}.  The inputs must be 2-D numeric matrices to use this\n## option.\n##\n## The optional argument @qcode{\"sorted\"}/@qcode{\"stable\"} controls the order\n## in which unique values appear in the output.  The default is\n## @qcode{\"sorted\"} and values in the output are placed in ascending order.\n## The alternative @qcode{\"stable\"} preserves the order found in the input.\n##\n## If requested, return column index vectors @var{ia} and @var{ib} such that\n## @code{@var{c} = @var{a}(@var{ia})} and @code{@var{c} = @var{b}(@var{ib})}.\n##\n## Programming Note: The input flag @qcode{\"legacy\"} changes the algorithm\n## to be compatible with @sc{matlab} releases prior to R2012b.\n##\n## @seealso{unique, union, setdiff, setxor, ismember}\n## @end deftypefn\n\nfunction [c, ia, ib] = intersect (a, b, varargin)\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n  endif\n\n  [a, b] = validsetargs (\"intersect\", a, b, varargin{:});\n\n  ## Special case of empty matrices\n  if (isempty (a) || isempty (b))\n    ## Lots of type checking required for Matlab compatibility.\n    if (isnumeric (a) && isnumeric (b))\n      c = [];\n    elseif (iscell (b))\n      c = {};\n    else\n      c = \"\";\n    endif\n    ia = ib = [];\n    return;\n  endif\n\n  by_rows = any (strcmp (\"rows\", varargin));\n  optsorted = ! any (strcmp (\"stable\", varargin));\n  optlegacy = any (strcmp (\"legacy\", varargin));\n\n  if (optlegacy)\n    isrowvec = ! iscolumn (a) || ! iscolumn (b);\n  else\n    isrowvec = isrow (a) && isrow (b);\n  endif\n\n  ## Form A and B into sets\n  if (nargout > 1 || ! optsorted)\n    [a, ia] = unique (a, varargin{:});\n    ia = ia(:);\n    [b, ib] = unique (b, varargin{:});\n    ib = ib(:);\n  else\n    a = unique (a, varargin{:});\n    b = unique (b, varargin{:});\n  endif\n\n  if (by_rows)\n    c = [a; b];\n    if (nargout > 1 || ! optsorted)\n      [c, ic] = sortrows (c);\n    else\n      c = sortrows (c);\n    endif\n    match = find (all (c(1:end-1,:) == c(2:end,:), 2));\n    if (optsorted)\n      c = c(match, :);\n    else\n      c = [a; b];\n      ## FIXME: Is there a way to avoid a call to sort?\n      [c_idx, sort_idx] = sort (ic(match));\n      c = c(c_idx, :);\n    endif\n    len_a = rows (a);\n  else\n    c = [a(:); b(:)];\n    if (nargout > 1 || ! optsorted)\n      [c, ic] = sort (c);\n    else\n      c = sort (c);\n    endif\n    if (iscellstr (c))\n      match = find (strcmp (c(1:end-1), c(2:end)));\n    else\n      match = find (c(1:end-1) == c(2:end));\n    endif\n    len_a = length (a);\n    if (optsorted)\n      c = c(match);\n    else\n      c = [a(:); b(:)];\n      ## FIXME: Is there a way to avoid a call to sort?\n      [c_idx, sort_idx] = sort (ic(match));\n      c = c(c_idx);\n    endif\n\n    ## Adjust output orientation for Matlab compatibility\n    if (isrowvec)\n      c = c.';\n    endif\n  endif\n\n  if (nargout > 1)\n    ia = ia(ic(match));            # a(ia) == c\n    ib = ib(ic(match+1) - len_a);  # b(ib) == c\n    if (! optsorted)\n      ## FIXME: Is there a way to avoid a call to sort?\n      ia = sort (ia);\n      ib_ind(sort_idx) = 1:numel(sort_idx);\n      ## Change ordering to conform to unsorted c\n      ib(ib_ind) = ib;\n    endif\n    if (optlegacy && isrowvec && ! by_rows)\n      ia = ia.';\n      ib = ib.';\n    endif\n  endif\n\nendfunction\n\n\n%!assert (intersect ([1 2 3 4], [9 8 4 2]), [2, 4])\n%!assert (intersect ([1 2; 2 3; 4 5], [2 3; 3 4; 5 6], \"rows\"), [2 3])\n%!assert (intersect ([1 NaN], [NaN NaN 5]), zeros (1,0))\n\n%!test\n%! a = [1 1 1 2 2 2];\n%! b = [1 2 3 4 5 6];\n%! c = intersect (a, b);\n%! assert (c, [1,2]);\n\n## Test multi-dimensional arrays\n%!test\n%! a = rand (3,3,3);\n%! b = a;\n%! b(1,1,1) = 2;\n%! assert (intersect (a, b), sort (a(2:end)'));\n\n## Test the routine for index vectors ia and ib\n%!test\n%! a = [3 2 4 5 7 6 5 1 0 13 13];\n%! b = [3 5 12 1 1 7];\n%! [c, ia, ib] = intersect (a, b);\n%! assert (c, [1, 3, 5, 7]);\n%! assert (ia, [8; 1; 4; 5]);\n%! assert (ib, [4; 1; 2; 6]);\n%! assert (a(ia), c);\n%! assert (b(ib), c);\n\n## Test \"rows\" argument\n%!test\n%! a = [1,1,2;1,4,5;2,1,7];\n%! b = [1,4,5;2,3,4;1,1,2;9,8,7];\n%! [c,ia,ib] = intersect (a, b, \"rows\");\n%! assert (c, [1,1,2;1,4,5]);\n%! assert (ia, [1;2]);\n%! assert (ib, [3;1]);\n%! assert (a(ia,:), c);\n%! assert (b(ib,:), c);\n\n%!test\n%! a = [1 2 3 4; 5 6 7 8; 9 10 11 12];\n%! [b, ia, ib] = intersect (a, a, \"rows\");\n%! assert (b, a);\n%! assert (ia, [1:3]');\n%! assert (ib, [1:3]');\n\n## Test \"stable\" argument\n%!test\n%! a = [2 2 2 1 1 1];\n%! b = [1 2 3 4 5 6];\n%! c = intersect (a, b, \"stable\");\n%! assert (c, [2,1]);\n\n## Test \"stable\" argument\n%!test <*60347>\n%! a = [8 4 2 6]';\n%! b = [1 7 2 8]';\n%! [c, ia, ib] = intersect (a, b, \"stable\");\n%! assert (c, [8;2]);\n%! assert (ia, [1;3]);\n%! assert (ib, [4;3]);\n\n%!test\n%! a = [3 2 4 5 7 6 5 1 0 13 13];\n%! b = [3 5 12 1 1 7];\n%! [c, ia, ib] = intersect (a, b, \"stable\");\n%! assert (c, [3, 5, 7, 1]);\n%! assert (ia, [1; 4; 5; 8]);\n%! assert (ib, [1; 2; 6; 4]);\n%! assert (a(ia), c);\n%! assert (b(ib), c);\n\n%!test\n%! a = [1,4,5;1,1,2;2,1,7];\n%! b = [1,4,5;2,3,4;1,1,2;9,8,7];\n%! [c, ia, ib] = intersect (a, b, \"rows\", \"stable\");\n%! assert (c, [1,4,5; 1,1,2]);\n%! assert (ia, [1;2]);\n%! assert (ib, [1;3]);\n%! assert (a(ia,:), c);\n%! assert (b(ib,:), c);\n\n%!test\n%! a = [1 2 3 4; 5 6 7 8; 9 10 11 12];\n%! [b, ia, ib] = intersect (a, a, \"rows\", \"stable\");\n%! assert (b, a);\n%! assert (ia, [1:3]');\n%! assert (ib, [1:3]');\n\n## Test \"legacy\" argument\n%!test\n%! a = [7 1 7 7 4];\n%! b = [7 0 4 4 0];\n%! [c, ia, ib] = intersect (a, b);\n%! assert (c, [4, 7]);\n%! assert (ia, [5; 1]);\n%! assert (ib, [3; 1]);\n%! [c, ia, ib] = intersect (a, b, \"legacy\");\n%! assert (c, [4, 7]);\n%! assert (ia, [5, 4]);\n%! assert (ib, [4, 1]);\n\n%!test  # \"legacy\" + \"rows\"\n%! A = [ 1 2; 3 4; 5 6; 3 4; 7 8 ];\n%! B = [ 3 4; 7 8; 9 10 ];\n%! [c, ia, ib] = intersect (A, B, \"rows\");\n%! assert (c, [3, 4; 7, 8]);\n%! assert (ia, [2; 5]);\n%! assert (ib, [1; 2]);\n%! [c, ia, ib] = intersect (A, B, \"rows\", \"legacy\");\n%! assert (c, [3, 4; 7, 8]);\n%! assert (ia, [4; 5]);\n%! assert (ib, [1; 2]);\n\n## Test orientation of output\n%!shared a,b\n%! a = 1:4;\n%! b = 2:5;\n\n%!assert (size (intersect (a, b)), [1, 3])\n%!assert (size (intersect (a', b)), [3, 1])\n%!assert (size (intersect (a, b')), [3, 1])\n%!assert (size (intersect (a', b')), [3, 1])\n%!assert (size (intersect (a, b, \"legacy\")), [1, 3])\n%!assert (size (intersect (a', b, \"legacy\")), [1, 3])\n%!assert (size (intersect (a, b', \"legacy\")), [1, 3])\n%!assert (size (intersect (a', b', \"legacy\")), [3, 1])\n\n## Test return type of empty intersections\n%!assert (intersect (['a', 'b'], {}), {})\n%!assert (intersect ([], {'a', 'b'}), {})\n%!assert (intersect ([], {}), {})\n%!assert (intersect ({'a', 'b'}, []), {})\n%!assert (intersect ([], ['a', 'b']), \"\")\n%!assert (intersect ({}, []), {})\n%!assert (intersect (['a', 'b'], []), \"\")\n"
  },
  {
    "path": "scripts/set/ismember.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} ismember (@var{a}, @var{s})\n## @deftypefnx {} {@var{tf} =} ismember (@var{a}, @var{s}, \"rows\")\n## @deftypefnx {} {[@var{tf}, @var{s_idx}] =} ismember (@dots{})\n## @deftypefnx {} {[@var{tf}, @var{s_idx}] =} ismember (@dots{}, \"legacy\")\n##\n## Return a logical matrix @var{tf} with the same shape as @var{a} which is\n## @code{true} (@code{1}) if the element in @var{a} is found in @var{s} and\n## @code{false} (@code{0}) if it is not.\n##\n## If a second output argument is requested then the index into @var{s} of each\n## matching element is also returned.  In the case of multiple matches, the\n## index of the first match is returned.  If the input option @qcode{\"legacy\"}\n## is provided, then the behavior is changed to be compatible with that of\n## @sc{matlab} 2012b and earlier, and the last match is returned instead.\n##\n## For example:\n##\n## @example\n## @group\n## a = [3, 10, 1];\n## s = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4];\n## [tf, s_idx] = ismember (a, s)\n##      @xresult{} tf = [1, 0, 1]\n##      @xresult{} s_idx = [7, 0, 3]\n## [tf2, s_idx2] = ismember (a, s, \"legacy\")\n##      @xresult{} tf2 = [1, 0, 1]\n##      @xresult{} s_idx2 = [8, 0, 4]\n## @end group\n## @end example\n##\n## The inputs @var{a} and @var{s} may also be cell arrays.\n##\n## @example\n## @group\n## a = @{\"abc\"@};\n## s = @{\"abc\", \"def\"@};\n## [tf, s_idx] = ismember (a, s)\n##      @xresult{} tf = 1\n##      @xresult{} s_idx = 1\n## @end group\n## @end example\n##\n## If the optional argument @qcode{\"rows\"} is given then compare rows in\n## @var{a} with rows in @var{s}.  The inputs must be 2-D matrices with the\n## same number of columns to use this option.\n##\n## @example\n## @group\n## a = [1:3; 5:7; 4:6];\n## s = [0:2; 1:3; 2:4; 3:5; 4:6];\n## [tf, s_idx] = ismember (a, s, \"rows\")\n##      @xresult{} tf = logical ([1; 0; 1])\n##      @xresult{} s_idx = [2; 0; 5];\n## @end group\n## @end example\n##\n## Matlab compatibility note: The @qcode{\"legacy\"} option currently only\n## affects whether the first or last instance of a match is returned in\n## @var{s_idx}.  Other impacts, including changes to char array whitespace\n## handling and handling of certain classes are not yet implemented.\n##\n## @seealso{lookup, unique, union, intersect, setdiff, setxor, ismembertol}\n## @end deftypefn\n\nfunction [tf, s_idx] = ismember (a, s, varargin)\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n  endif\n\n  by_rows = any (strcmpi (\"rows\", varargin));\n  optlegacy = any (strcmpi (\"legacy\", varargin));\n\n  ## lookup() uses absolute values for complex input so we handle the\n  ## real and imaginary parts separately (bug #52437) unless 'rows', which\n  ## does not use lookup() so it can be handled normally.\n  if (! by_rows && (iscomplex (a) || iscomplex (s)))\n    real_argout = cell (nargout, 1);\n    imag_argout = cell (nargout, 1);\n    [real_argout{:}] = ismember (real (a), real (s), varargin{:});\n    [imag_argout{:}] = ismember (imag (a), imag (s), varargin{:});\n    tf = real_argout{1} & imag_argout{1};\n    if (nargout > 1)\n      s_idx = zeros (size (real_argout{2}));\n      if (optlegacy)\n        s_idx(tf) = min (real_argout{2}(tf), imag_argout{2}(tf));\n      else\n        s_idx(tf) = max (real_argout{2}(tf), imag_argout{2}(tf));\n      endif\n    endif\n    return;\n  endif\n\n  ## lookup() does not handle logical values\n  if (islogical (a))\n    a = uint8 (a);\n  endif\n  if (islogical (s))\n    s = uint8 (s);\n  endif\n\n  ## Matlab-compatible behavior (R2016b).  See bug #51187.\n  if (ischar (a) && rows (a) == 1 && iscell (s))\n    a = {a};\n  endif\n\n  ## Another Matlab-compatible behavior.  See bug #53924.\n  if (isnumeric (a) && ischar (s))\n    s = double (s);\n  elseif (ischar (a) && isnumeric (s))\n    a = double (a);\n  endif\n\n  if (nargin > 2 && (nargin - by_rows - optlegacy != 2))\n    error ('ismember: only \"rows\" and \"legacy\" are valid options');\n  endif\n  [a, s] = validsetargs (\"ismember\", a, s, varargin{:});\n\n  if (! by_rows)\n    s = s(:);\n    ## Check sort status, because we expect the array will often be sorted.\n    ## FIXME: currently fails for some cellstring inputs for s, as they do\n    ##  not get vectorized, and matrices cannot by issorted (bug #61765)\n    if (issorted (s))\n      is = [];\n    else\n      [s, is] = sort (s);\n    endif\n\n    ## Remove NaNs from table because lookup can't handle them\n    if (isreal (s) && ! isempty (s) && isnan (s(end)))\n      s = s(1:(end - sum (isnan (s))));\n    endif\n\n    if (nargout > 1)\n      if (! optlegacy)\n        s = s(end : -1: 1);\n        if (! (isempty (s) || isempty (a)))\n          if (isempty (is))\n            is = [numel(s) : -1 : 1];\n          else\n            is = is(1 : numel (s))(end : -1 : 1);\n          endif\n        endif\n      endif\n\n      s_idx = lookup (s, a, \"m\");\n      tf = logical (s_idx);\n      if (! isempty (is))\n        s_idx(tf) = is(s_idx(tf));\n      endif\n\n    else\n      tf = lookup (s, a, \"b\");\n    endif\n\n  else  # \"rows\" argument\n    if (isempty (a) || isempty (s))\n      tf = false (rows (a), 1);\n      if (nargout > 1)\n        s_idx = zeros (rows (a), 1);\n      endif\n\n    elseif (rows (s) == 1)\n      tf = all (a == s, 2);\n      if (nargout > 1)\n        s_idx = double (tf);\n      endif\n    else\n      ## FIXME: lookup does not support \"rows\", so we just use unique.\n      if (optlegacy)\n        [~, ii, jj] = unique ([a; s], \"rows\", \"last\");\n        na = rows (a);\n        jj = ii(jj(1:na));\n        tf = jj > na;\n        if (nargout > 1)\n          s_idx = max (0, jj - na);\n        endif\n\n      else\n        [~, ii, jj] = unique ([s; a], \"rows\", \"first\");\n        nj = rows (s) + 1;\n        jj = ii(jj(nj:end));\n        tf = jj < nj;\n        if (nargout > 1)\n          s_idx = jj;\n          s_idx(jj >= nj) = 0;\n        endif\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!assert (ismember ({\"\"}, {\"abc\", \"def\"}), false)\n%!assert (ismember (\"abc\", {\"abc\", \"def\"}), true)\n%!assert (isempty (ismember ([], [1, 2])), true)\n%!assert (isempty (ismember ({}, {'a', 'b'})), true)\n%!assert (isempty (ismember ([], 'a')), true)\n%!assert (ismember (\"\", {\"abc\", \"def\"}), false)\n%!assert (ismember (1, 'abc'), false)\n%!assert (ismember (\"abc\", 1), [false false false])\n%!assert (ismember (\"abc\", 99), [false false true])\n%!fail (\"ismember ([], {1, 2})\")\n%!fail (\"ismember ({[]}, {1, 2})\")\n%!fail (\"ismember ({}, {1, 2})\")\n%!fail (\"ismember ({1}, {'1', '2'})\")\n%!fail (\"ismember ({'1'}, {'1' '2'},'rows')\") ##MATLAB gives warning, outputs non-rows answer\n%!fail (\"ismember ([1 2 3], [5 4 3 1], 'rows')\")\n%!assert (ismember ({\"foo\", \"bar\"}, {\"foobar\"}), [false false])\n%!assert (ismember ({\"foo\"}, {\"foobar\"}), false)\n%!assert (ismember ({\"bar\"}, {\"foobar\"}), false)\n%!assert (ismember ({\"bar\"}, {\"foobar\", \"bar\"}), true)\n%!assert (ismember ({\"foo\", \"bar\"}, {\"foobar\", \"bar\"}), [false true])\n%!assert (ismember ({\"xfb\", \"f\", \"b\"}, {\"fb\", \"b\"}), [false false true])\n%!assert (ismember (\"1\", \"0123456789.\"), true)\n\n%!test\n%! [result, s_idx] = ismember ([1, 2], []);\n%! assert (result, [false false]);\n%! assert (s_idx, [0, 0]);\n\n%!test\n%! [result, s_idx] = ismember ([], [1, 2]);\n%! assert (result, logical ([]));\n%! assert (s_idx, []);\n\n%!test\n%! [result, s_idx] = ismember ({\"a\", \"b\"}, \"\");\n%! assert (result, [false false]);\n%! assert (s_idx, [0, 0]);\n\n%!test\n%! [result, s_idx] = ismember ({\"a\", \"b\"}, {});\n%! assert (result, [false false]);\n%! assert (s_idx, [0, 0]);\n\n%!test\n%! [result, s_idx] = ismember (\"\", {\"a\", \"b\"});\n%! assert (result, false);\n%! assert (s_idx, 0);\n\n%!test\n%! [result, s_idx] = ismember ({}, {\"a\", \"b\"});\n%! assert (result, logical ([]));\n%! assert (s_idx, []);\n\n%!test\n%! [result, s_idx] = ismember ([1 2 3 4 5], [3]);\n%! assert (result, logical ([0 0 1 0 0]));\n%! assert (s_idx , [0 0 1 0 0]);\n\n%!test\n%! [result, s_idx] = ismember ([1 6], [1 2 3 4 5 1 6 1]);\n%! assert (result, [true true]);\n%! assert (s_idx, [1, 7]);\n\n%!test\n%! [result, s_idx] = ismember ([3,10,1], [0,1,2,3,4,5,6,7,8,9]);\n%! assert (result, [true false true]);\n%! assert (s_idx, [4, 0, 2]);\n\n%!test\n%! [result, s_idx] = ismember (\"1.1\", \"0123456789.1\");\n%! assert (result, [true true true]);\n%! assert (s_idx, [2, 11, 2]);\n\n%!test\n%! [result, s_idx] = ismember ([1:3; 5:7; 4:6], [0:2; 1:3; 2:4; 3:5; 4:6], \"rows\");\n%! assert (result, [true; false; true]);\n%! assert (s_idx, [2; 0; 5]);\n\n%!test\n%! [result, s_idx] = ismember ([1.1,1.2,1.3; 2.1,2.2,2.3; 10,11,12], [1.1,1.2,1.3; 10,11,12; 2.12,2.22,2.32], \"rows\");\n%! assert (result, [true; false; true]);\n%! assert (s_idx, [1; 0; 2]);\n\n%!test\n%! [result, s_idx] = ismember ([1:3; 5:7; 4:6; 0:2; 1:3; 2:4], [1:3], \"rows\");\n%! assert (result, logical ([1 0 0 0 1 0]'));\n%! assert (s_idx, [1 0 0 0 1 0]');\n\n%!test\n%! A = [1 3 5 6; 2 4 6 8];\n%! B = [2 4 6 8; 1 3 5 7; 2 4 6 8];\n%! [result, s_idx] = ismember (A, B, \"rows\");\n%! assert (result, [false; true]);\n%! assert (s_idx, [0; 1]);\n\n%!test <*51187>\n%! assert (ismember ('b ', {'a ', 'b '}), true);\n\n%!test <*51187>\n%! abc = ['a '; 'b '; 'c '];\n%! assert (ismember (abc, {abc}), [false; false; false]);\n\n%!test <*52437>\n%! [tf, s_idx] = ismember ([5, 4-3j, 3+4j], [5, 4-3j, 3+4j]);\n%! assert (tf, logical ([1, 1, 1]));\n%! assert (s_idx, [1, 2, 3]);\n%!\n%! [tf, s_idx] = ismember ([5, 4-3j, 3+4j], 5);\n%! assert (tf, logical ([1, 0, 0]));\n%! assert (s_idx, [1, 0, 0]);\n%!\n%! [tf, s_idx] = ismember ([5, 5, 5], 4-3j);\n%! assert (tf, logical ([0, 0, 0]));\n%! assert (s_idx, [0, 0, 0]);\n%!\n%! [tf, s_idx] = ismember ([5, 4-3j, 3+4j; 5i, 6, 6i], [5, 6]);\n%! assert (tf, logical ([1, 0, 0; 0, 1, 0]));\n%! assert (s_idx, [1, 0, 0; 0, 2, 0]);\n%!\n%! [tf, s_idx] = ismember ([5, 4-3j, 3+4j; 5, 4-3j, 3+4j], [5, 5, 5], \"rows\");\n%! assert (tf, logical ([0; 0]));\n%! assert (s_idx, [0; 0]);\n%!\n%! [tf, s_idx] = ismember ([5, 5, 5], [5, 4-3j, 3+4j; 5, 5, 5], \"rows\");\n%! assert (tf, true);\n%! assert (s_idx, 2);\n%!\n%! tf = ismember ([5, 4-3j, 3+4j], 5);\n%! assert (tf, logical ([1, 0, 0]));\n%! [~, s_idx] = ismember ([5, 4-3j, 3+4j], 5);\n%! assert (s_idx, [1, 0, 0]);\n%!\n%! [tf, s_idx] = ismember (-1-1j, [-1-1j, -1+3j, -1+1j]);\n%! assert (tf, true);\n%! assert (s_idx, 1);\n\n%!test <*55659>\n%! A = [5 3 4 2];\n%! B = [2 4 4 4 6 8];\n%! [result, s_idx] = ismember (A, B);\n%! assert (result, [false, false, true, true]);\n%! assert (s_idx, [0, 0, 2, 1]);\n%! [result, s_idx] = ismember (A, B, \"legacy\");\n%! assert (result, [false, false, true, true]);\n%! assert (s_idx, [0, 0, 4, 1]);\n%!\n%! [result, s_idx] = ismember ([1 6], [1 2 3 4 5 1 6 1], \"legacy\");\n%! assert (result, [true true]);\n%! assert (s_idx, [8, 7]);\n%!\n%! [result, s_idx] = ismember ([5, 4-3j, 3+4j; 5i, 6, 6i], [5, 6], \"legacy\");\n%! assert (result, logical ([1, 0, 0; 0, 1, 0]));\n%! assert (s_idx, [1, 0, 0; 0, 2, 0]);\n%!\n%! [result, s_idx] = ismember ([5, 4-3j, 3+4j; 5i, 6, 6i], [5, 6, 5]);\n%! assert (result, logical ([1, 0, 0; 0, 1, 0]));\n%! assert (s_idx, [1, 0, 0; 0, 2, 0]);\n%!\n%! [result, s_idx] = ismember ([5, 4-3j, 3+4j; 5i, 6, 6i], [5, 6, 5], \"legacy\");\n%! assert (result, logical ([1, 0, 0; 0, 1, 0]));\n%! assert (s_idx, [3, 0, 0; 0, 2, 0]);\n%!\n%! [result, s_idx] = ismember ([3,10,1], [0,0,1,1,2,2,3,3,4,4]);\n%! assert (result, [true false true]);\n%! assert (s_idx, [7, 0, 3]);\n%!\n%! [result, s_idx] = ismember ([3,10,1], [0,0,1,1,2,2,3,3,4,4], \"legacy\");\n%! assert (result, [true false true]);\n%! assert (s_idx, [8, 0, 4]);\n%!\n%! [result, s_idx] = ismember ([3,10,1], [0,0,1,NaN,1,1,2,2,3,3,NaN,3,4,4]);\n%! assert (result, [true false true]);\n%! assert (s_idx, [9, 0, 3]);\n%!\n%! [result, s_idx] = ismember ([3,10,1], [0,0,1,NaN,1,1,2,2,3,3,NaN,3,4,4], \"legacy\");\n%! assert (result, [true false true]);\n%! assert (s_idx, [12, 0, 6]);\n%!\n%! [result, s_idx] = ismember (\"1.1\", \"0123456789.1\", \"legacy\");\n%! assert (result, [true true true]);\n%! assert (s_idx, [12, 11, 12]);\n%!\n%! [result, s_idx] = ismember ([1:3; 5:7; 4:6], [0:2; 1:3; 2:4; 3:5; 4:6; 1:3], \"rows\");\n%! assert (result, [true; false; true]);\n%! assert (s_idx, [2; 0; 5]);\n%!\n%! [result, s_idx] = ismember ([1:3; 5:7; 4:6], [0:2; 1:3; 2:4; 3:5; 4:6; 1:3], \"rows\", \"legacy\");\n%! assert (result, [true; false; true]);\n%! assert (s_idx, [6; 0; 5]);\n\n%!xtest <61765>\n%! ## issorted() can't handle char matrix().  Returns [1;0;0].\n%! abc = [' a'; ' b'; ' c'];\n%! [result, s_idx] = ismember (abc, {abc});\n%! assert (result, [false; false; false]);\n%! assert (s_idx, [0; 0; 0]);\n\n%!xtest <61765>\n%! ## issorted() can't handle cellstr array.\n%! ## Maybe also legacy handling of char arrays.\n%! abc = ['a '; 'b '; 'c '];\n%! [result, s_idx] = ismember (abc, {abc}, \"legacy\");\n%! assert (result, [true; true; true]);\n%! assert (s_idx, [1; 2; 3]);\n\n## Test input validation\n%!error <Invalid call> ismember ()\n%!error <Invalid call> ismember (1)\n%!error <Invalid call> ismember (1,2,3,4,5)\n%!error <only \"rows\" and \"legacy\" are valid options> ismember (1,2, \"foo\", \"legacy\")\n%!error <only \"rows\" and \"legacy\" are valid options> ismember (1,2, \"rows\", \"foo\")\n%!error <only \"rows\" and \"legacy\" are valid options> ismember (1,2, \"foo\", \"bar\")\n%!error <only \"rows\" and \"legacy\" are valid options> ismember (1,2, \"sorted\")\n%!error <only \"rows\" and \"legacy\" are valid options> ismember (1,2, \"stable\")\n"
  },
  {
    "path": "scripts/set/ismembertol.m",
    "content": "########################################################################\n##\n## Copyright (C) 2023-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} ismembertol (@var{a}, @var{s})\n## @deftypefnx {} {@var{tf} =} ismembertol (@var{a}, @var{s}, @var{tol})\n## @deftypefnx {} {@var{tf} =} ismembertol (@var{a}, @var{s}, @var{name}, @var{value})\n## @deftypefnx {} {[@var{tf}, @var{s_idx}] =} ismembertol (@dots{})\n## Check if values are members of a set within a tolerance.\n##\n## This functions returns a logical matrix @var{tf} with the same shape as\n## @var{a} which is true (1) where the element in @var{a} is close to @var{s}\n## within a tolerance @var{tol} and false (0) if it is not.  If @var{tol} is\n## not specified, a default tolerance of @code{1e-6} is used.\n##\n## If a second output argument is requested then the index into @var{s} of each\n## matching element is also returned.\n##\n## The inputs @var{a} and @var{s} must be numeric values.\n##\n## @example\n## @group\n## a = [3, 10, 1];\n## s = [0:9];\n## [tf, s_idx] = ismembertol (a, s)\n##      @xresult{} tf = [1, 0, 1]\n##      @xresult{} s_idx = [4, 0, 2]\n## @end group\n## @end example\n##\n## Optional property/value pairs may be given to change the function's\n## behavior.  The property may be one of following strings:\n##\n## @table @asis\n## @item @qcode{\"ByRows\"}\n## If set to @code{false} (default), all elements in @var{a} and @var{s} are\n## treated separately.  If set to @code{true}, @var{tf} will be @code{true}\n## for each row in @var{a} that matches a row in @var{s} within the given\n## tolerance.  Two rows, @var{u} and @var{v}, are within tolerance if they\n## fulfill the condition @code{all (abs (u-v) <= tol*max (abs ([a;s])))}.\n##\n## @item @qcode{\"OutputAllIndices\"}\n## If set to @code{false} (default), @var{s_idx} contains indices for one\n## of the matches.  If set to @code{true}, @var{s_idx} is a cell array\n## containing the indices for all elements in @var{s} that are within tolerance\n## of the corresponding value in @var{a}.\n##\n## @item @qcode{\"DataScale\"}\n## The provided value @var{DS} is used to change the scale factor in the\n## tolerance test to @code{abs (u-v) <= tol*@var{DS}}.  By default, the maximum\n## absolute value in @var{a} and @var{s} is used as the scale factor.\n## @end table\n##\n## Example:\n##\n## @example\n## @group\n## s = [1:6].' * pi;\n## a = 10.^log10 (x);\n## [tf, s_idx] = ismembertol (a, s);\n## @end group\n## @end example\n##\n## @seealso{ismember, lookup, unique, union, intersect, setdiff, setxor}\n## @end deftypefn\n\nfunction [tf, s_idx] = ismembertol (a, s, varargin)\n\n  if (nargin < 2 || nargin > 9)\n    print_usage ();\n  endif\n\n  if (nargin < 3 || ! isnumeric (varargin{1}))\n    tol = 1e-6;  # default tolerance\n  else\n    tol = varargin{1};\n    varargin(1) = [];\n  endif\n\n  if (! isnumeric (a) || ! isnumeric (s))\n    error (\"ismembertol: A and S must contain numeric values\");\n  endif\n\n  if (nargin > 2 ...\n      && (! iscellstr (varargin(1:2:end)) ...\n          || any (! ismember (lower (varargin(1:2:end)), ...\n                              {\"outputallindices\", \"byrows\", \"datascale\"}))))\n    error (\"ismembertol: unsupported property\");\n  endif\n\n  by_rows_idx = find (strcmpi (\"ByRows\", varargin));\n  by_rows = (! isempty (by_rows_idx) && logical (varargin{by_rows_idx+1}) );\n\n  if (by_rows && columns (a) != columns (s))\n    error (\"ismembertol: number of columns in A and S must match for 'ByRows'\");\n  endif\n\n  all_indices_idx = find (strcmpi (\"OutputAllIndices\", varargin));\n  all_indices = (! isempty (all_indices_idx) ...\n                 && logical (varargin{all_indices_idx+1}) );\n\n  data_scale_idx = find (strcmpi (\"DataScale\", varargin));\n  data_scale = (! isempty (data_scale_idx) ...\n                && isnumeric (varargin{data_scale_idx+1}) );\n  if (data_scale)\n    DS = varargin{data_scale_idx+1};\n  else\n    DS = max (abs ([a(:);s(:)]));\n  endif\n\n  if (! by_rows)\n    sa = size (a);\n    s = s(:);\n    a = a(:);\n    ## Check sort status, because we expect the array will often be sorted.\n    if (issorted (s))\n      is = [];\n    else\n      [s, is] = sort (s);\n    endif\n\n    ## Remove NaNs from table because lookup can't handle them\n    if (isreal (s) && ! isempty (s) && isnan (s(end)))\n      s = s(1:(end - sum (isnan (s))));\n    endif\n\n    if (! data_scale)\n      DS = max (abs ([a(:);s(:)]));\n    endif\n\n    [s_i, s_j] = find (abs (transpose (s) - a) < tol * DS);\n    if (! all_indices)\n      s_idx = zeros (size (a));\n      [~, I] = unique (s_i);\n      s_j = s_j(I);\n      s_idx(s_i(I)) = s_j;\n      tf = logical (s_idx);\n      if (! isempty (is))\n        s_idx(tf) = is(s_idx(tf));\n      endif\n      s_idx = reshape (s_idx, sa);\n      tf = reshape (tf, sa);\n    else  # all_indices\n      s_idx = cell (size (a));\n      tf = zeros (size (a));\n      C = unique (s_j);\n      for ic = C.'\n        ii = find (s_j == ic);\n        for sii = s_i(ii).'\n          if (! isempty (is))\n            s_idx{sii} = [s_idx{sii}, is(ic)];\n          else\n            s_idx{sii} = [s_idx{sii}, ic];\n          endif\n        endfor\n\n        tf(ic) = 1;\n      endfor\n    endif\n\n  else  # \"ByRows\"\n    if (isempty (a) || isempty (s))\n      tf = false (rows (a), 1);\n      s_idx = zeros (rows (a), 1);\n    else\n      if (rows (s) == 1)\n        tf = all (bsxfun (@eq, a, s), 2);\n        s_idx = double (tf);\n      else\n        ## Two rows, u and v, are within tolerance if\n        ## all(abs(u-v) <= tol*max(abs([A;B]))).\n        na = rows (a);\n        if (! all_indices)\n          s_idx = zeros (na, 1);\n        else\n          s_idx = cell (na, 1);\n        endif\n        if (length (DS) == 1)\n          DS = repmat (DS, 1, columns (a));\n        endif\n        for i = 1:na\n          if (! all_indices)\n            s_i = find ( all (abs (a(i,:) - s) < tol * DS, 2), 1);\n            if (! isempty (s_i))\n              s_idx(i) = s_i;\n            endif\n          else\n            s_i = find (all (abs (a(i,:) - s) < tol * DS, 2));\n            if (! isempty (s_i))\n              s_idx{i} = s_i;\n            endif\n          endif\n        endfor\n        if (! all_indices)\n          tf = logical (s_idx);\n        else\n          tf = cellfun (@(x) ! isempty (x) && all (x(:)!=0), s_idx);\n        endif\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Group random data\n%! A = rand (1000, 2);\n%! B = [(0:.2:1).', 0.5*ones(6,1)];\n%! [LIA, LocAllB] = ismembertol (B, A, 0.1, 'ByRows', true, 'OutputAllIndices', true, 'DataScale', [1,Inf]);\n%! plot (B(:,1), B(:,2), 'x');\n%! hold on\n%! for k = 1:length (LocAllB)\n%!   plot (A(LocAllB{k},1), A(LocAllB{k},2), '.');\n%! endfor\n\n%!assert (isempty (ismembertol ([], [1, 2])), true)\n\n%!test\n%! [result, s_idx] = ismembertol ([1; 2], []);\n%! assert (result, [false; false]);\n%! assert (s_idx, [0; 0]);\n\n%!test\n%! [result, s_idx] = ismembertol ([], [1, 2]);\n%! assert (result, logical ([]));\n%! assert (s_idx, []);\n\n%!test\n%! [result, s_idx] = ismembertol ([1 2 3 4 5], [3]);\n%! assert (result, logical ([0 0 1 0 0]));\n%! assert (s_idx , [0 0 1 0 0]);\n\n%!test\n%! [result, s_idx] = ismembertol ([1 6], [1 2 3 4 5 1 6 1]);\n%! assert (result, [true, true]);\n%! assert (s_idx(2), 7);\n\n%!test\n%! [result, s_idx] = ismembertol ([3,10,1], [0,1,2,3,4,5,6,7,8,9]);\n%! assert (result, [true, false, true]);\n%! assert (s_idx, [4, 0, 2]);\n\n%!test\n%! [result, s_idx] = ismembertol ([1:3; 5:7; 4:6], [0:2; 1:3; 2:4; 3:5; 4:6], \"ByRows\", true);\n%! assert (result, [true; false; true]);\n%! assert (s_idx, [2; 0; 5]);\n\n%!test\n%! [result, s_idx] = ismembertol ([1.1,1.2,1.3; 2.1,2.2,2.3; 10,11,12], ...\n%!                                [1.1,1.2,1.3; 10,11,12; 2.12,2.22,2.32], \"ByRows\", true);\n%! assert (result, [true; false; true]);\n%! assert (s_idx, [1; 0; 2]);\n\n%!test\n%! [result, s_idx] = ismembertol ([1:3; 5:7; 4:6; 0:2; 1:3; 2:4], [1:3], \"ByRows\", true);\n%! assert (result, logical ([1 0 0 0 1 0].'));\n%! assert (s_idx, [1 0 0 0 1 0].');\n\n%!test\n%! [tf, s_idx] = ismembertol ([5, 4-3j, 3+4j], [5, 4-3j, 3+4j]);\n%! assert (tf, logical ([1 1 1]));\n%! assert (s_idx, [1 2 3]);\n\n%!test\n%! [tf, s_idx] = ismembertol ([5, 4-3j, 3+4j], 5);\n%! assert (tf, logical ([1 0 0]));\n%! assert (s_idx, [1 0 0]);\n\n%!test\n%! [tf, s_idx] = ismembertol ([5, 5, 5], 4-3j);\n%! assert (tf, logical ([0 0 0]));\n%! assert (s_idx, [0 0 0]);\n\n%!test\n%! [tf, s_idx] = ismembertol ([5, 4-3j, 3+4j; 5, 4-3j, 3+4j], [5, 5, 5], \"ByRows\", true);\n%! assert (tf, logical ([0; 0]));\n%! assert (s_idx, [0; 0]);\n\n%!test\n%! [tf, s_idx] = ismembertol ([5, 5, 5], [5, 4-3j, 3+4j; 5, 5, 5], \"ByRows\", true);\n%! assert (tf, true);\n%! assert (s_idx, 2);\n\n%!test\n%! tf = ismembertol ([5, 4-3j, 3+4j], 5);\n%! assert (tf, logical ([1 0 0]));\n%! [~, s_idx] = ismembertol ([5, 4-3j, 3+4j], 5);\n%! assert (s_idx, [1 0 0]);\n\n%!test\n%! [tf, s_idx] = ismembertol (-1-1j, [-1-1j, -1+3j, -1+1j]);\n%! assert (tf, true);\n%! assert (s_idx, 1);\n\n%!test\n%! [tf, s_idx] = ismembertol ([0.9 1.9 3.1 4.2], [1 2 3], 0.1);\n%! assert (tf, [true true true false]);\n%! assert (s_idx, [1 2 3 0]);\n\n%!test\n%! [tf, s_idx] = ismembertol ([1:10] + 0.01 * (rand (1,10) - 0.5), [1:10], 0.01);\n%! assert (tf, true (1, 10));\n%! assert (s_idx, [1:10]);\n\n## Test input validation\n%!error <Invalid call> ismembertol ()\n%!error <Invalid call> ismembertol (1)\n%!error <unsupported property> ismembertol (1,2,3,4)\n%!error <must contain numeric values> ismembertol ([], {1, 2})\n%!error <must contain numeric values> ismembertol ({[]}, {1, 2})\n%!error <must contain numeric values> ismembertol ({}, {1, 2})\n%!error <must contain numeric values> ismembertol ({1}, {'1', '2'})\n%!error <must contain numeric values> ismembertol ({'1'}, {'1', '2'}, 'ByRows', true)\n%!error <number of columns .* must match> ismembertol ([1 2 3], [5 4 3 1], 'ByRows', true)\n"
  },
  {
    "path": "scripts/set/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/validsetargs.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/intersect.m \\\n  %reldir%/ismember.m \\\n  %reldir%/ismembertol.m \\\n  %reldir%/powerset.m \\\n  %reldir%/setdiff.m \\\n  %reldir%/setxor.m \\\n  %reldir%/union.m \\\n  %reldir%/unique.m \\\n  %reldir%/uniquetol.m\n\n%canon_reldir%dir = $(fcnfiledir)/set\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/set/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/set/powerset.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{p} =} powerset (@var{a})\n## @deftypefnx {} {@var{p} =} powerset (@var{a}, \"rows\")\n## Compute the powerset (all subsets) of the set @var{a}.\n##\n## The set @var{a} must be a numerical matrix or a cell array of strings.  The\n## output will always be a cell array of either vectors or strings.\n##\n## With the optional argument @qcode{\"rows\"}, each row of the set @var{a} is\n## considered one element of the set.  The input must be a 2-D numeric matrix\n## to use this argument.\n##\n## @seealso{unique, union, intersect, setdiff, setxor, ismember}\n## @end deftypefn\n\nfunction p = powerset (a, byrows_arg)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  byrows = false;\n  if (nargin == 2)\n    if (! strcmpi (byrows_arg, \"rows\"))\n      error ('powerset: optional second argument must be \"rows\"');\n    elseif (iscell (a))\n      error ('powerset: \"rows\" not valid for cell arrays');\n    else\n      byrows = true;\n    endif\n  endif\n\n  if (iscell (a) && ! iscellstr (a))\n    error (\"powerset: cell arrays can only be used for character strings\");\n  endif\n\n  if (byrows)\n    a = unique (a, \"rows\");\n    n = rows (a);\n  else\n    a = unique (a);\n    n = numel (a);\n  endif\n\n  if (n == 0)\n    p = {};\n  else\n    if (n > 32)\n      error (\"powerset: not implemented for more than 32 elements\");\n    endif\n\n    ## Logical rep\n    m = uint32 (0:2^n-1);\n    ## FIXME: better test for endianness?\n    if (bitunpack (uint16 (1))(1) == 0)\n      m = swapbytes (m);\n    endif\n    b = reshape (bitunpack (m), 32, 2^n)(1:n,:);\n    ## Convert to indices and lengths.\n    [i, k] = find (b);\n    k = sum (b, 1);\n\n    ## Index and split.\n    if (byrows)\n      p = mat2cell (a(i,:), k, columns (a));\n    else\n      if (rows (a) == 1)\n        p = mat2cell (a(i), 1, k);\n      else\n        p = mat2cell (a(i), k, 1);\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! c = sort (cellstr ({[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]}));\n%! p = sort (cellstr (powerset ([1, 2, 3])));\n%! assert (p, c);\n\n%!test\n%! c = sort (cellstr ({ [], [1:3], [2:4], [3:5], [1:3; 2:4], [1:3; 3:5], [2:4; 3:5], [1:3; 2:4; 3:5]}));\n%! p = sort (cellstr (powerset ([1:3;2:4;3:5], \"rows\")));\n%! assert (p,c);\n\n%!assert (powerset([]), {});  # always return a cell array\n\n## Test input validation\n%!error <Invalid call> powerset ()\n%!error <second argument must be \"rows\"> powerset (1, \"cols\")\n%!error <\"rows\" not valid for cell arrays> powerset ({1}, \"rows\")\n%!error <cell arrays can only be used for character> powerset ({1})\n%!error <not implemented for more than 32 elements> powerset (1:33)\n"
  },
  {
    "path": "scripts/set/private/validsetargs.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[x, y] =} validsetargs (@var{caller}, @var{x}, @var{y}, @var{varargin})\n## Internal function to validate arguments passed to functions operating on\n## sets.\n## @seealso{intersect, ismember, setdiff, setxor, union}\n## @end deftypefn\n\nfunction [x, y] = validsetargs (caller, x, y, varargin)\n\n  isallowedarraytype = @(x) isnumeric (x) || ischar (x) || islogical (x);\n\n  if (nargin == 3)\n    icx = iscellstr (x);\n    icy = iscellstr (y);\n    if (icx || icy)\n      if (icx && ischar (y))\n        y = cellstr (y);\n      elseif (icy && ischar (x))\n        x = cellstr (x);\n      elseif (icy && isempty (x))\n        x = {};\n      elseif (icx && isempty (y))\n        y = {};\n      elseif (! (icx && icy))\n        error (\"%s: cell array of strings cannot be combined with a nonstring value\", caller);\n      endif\n    elseif (! (isallowedarraytype (x) && isallowedarraytype (y)))\n      error (\"%s: A and B must be arrays or cell arrays of strings\", caller);\n    endif\n  else\n    optlegacy = false;\n    optsorted = false;\n    optstable = false;\n\n    for arg = varargin\n      switch (arg{1})\n        case \"legacy\"\n          optlegacy = true;\n\n        case \"rows\"\n          if (iscell (x) || iscell (y))\n            error ('%s: cells not supported with \"rows\" flag', caller);\n          elseif (! (isallowedarraytype (x) && isallowedarraytype (y)))\n            error (\"%s: A and B must be arrays or cell arrays of strings\", caller);\n          else\n            if (ndims (x) > 2 || ndims (y) > 2)\n              error ('%s: A and B must be 2-dimensional matrices with \"rows\" flag', caller);\n            elseif (columns (x) != columns (y) && ! (isempty (x) || isempty (y)))\n              error (\"%s: number of columns in A and B must match\", caller);\n            endif\n          endif\n\n        case \"sorted\"\n          optsorted = true;\n\n        case \"stable\"\n          optstable = true;\n\n        otherwise\n          error (\"%s: invalid option: %s\", caller, arg{1});\n\n      endswitch\n    endfor\n\n    if (optsorted + optstable + optlegacy > 1)\n      error ('%s: only one of \"sorted\", \"stable\", or \"legacy\" may be specified',\n             caller);\n    endif\n\n  endif\n\nendfunction\n\n\n## BIST tests for function are in union.m\n"
  },
  {
    "path": "scripts/set/setdiff.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} setdiff (@var{a}, @var{b})\n## @deftypefnx {} {@var{c} =} setdiff (@var{a}, @var{b}, \"rows\")\n## @deftypefnx {} {@var{c} =} setdiff (@dots{}, \"sorted\")\n## @deftypefnx {} {@var{c} =} setdiff (@dots{}, \"stable\")\n## @deftypefnx {} {@var{c} =} setdiff (@dots{}, \"legacy\")\n## @deftypefnx {} {[@var{c}, @var{ia}] =} setdiff (@dots{})\n## Return the unique elements in @var{a} that are not in @var{b}.\n##\n## If @var{a} is a row vector return a row vector; Otherwise, return a\n## column vector.  The inputs may also be cell arrays of strings.\n##\n## If the optional input @qcode{\"rows\"} is given then return the rows in\n## @var{a} that are not in @var{b}.  The inputs must be 2-D numeric matrices to\n## use this option.\n##\n## The optional argument @qcode{\"sorted\"}/@qcode{\"stable\"} controls the order\n## in which unique values appear in the output.  The default is\n## @qcode{\"sorted\"} and values in the output are placed in ascending order.\n## The alternative @qcode{\"stable\"} preserves the order found in the input.\n##\n## If requested, return the index vector @var{ia} such that\n## @code{@var{c} = @var{a}(@var{ia})}.\n##\n## Programming Note: The input flag @qcode{\"legacy\"} changes the algorithm\n## to be compatible with @sc{matlab} releases prior to R2012b.\n##\n## @seealso{unique, union, intersect, setxor, ismember}\n## @end deftypefn\n\nfunction [c, ia] = setdiff (a, b, varargin)\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n  endif\n\n  [a, b] = validsetargs (\"setdiff\", a, b, varargin{:});\n\n  by_rows = any (strcmp (\"rows\", varargin));\n  optlegacy = any (strcmp (\"legacy\", varargin));\n\n  if (optlegacy)\n    isrowvec = ! iscolumn (a) || ! iscolumn (b);\n  else\n    isrowvec = isrow (a);\n  endif\n\n  if (by_rows)\n    if (nargout > 1)\n      [c, ia] = unique (a, varargin{:});\n    else\n      c = unique (a, varargin{:});\n    endif\n    if (! isempty (c) && ! isempty (b))\n      ## Form A and B into combined set.\n      b = unique (b, varargin{:});\n      [csort, idx] = sortrows ([c; b]);\n      ## Eliminate those elements of A that are the same as in B.\n      dups = find (all (csort(1:end-1,:) == csort(2:end,:), 2));\n      c(idx(dups),:) = [];\n      if (nargout > 1)\n        ia(idx(dups),:) = [];\n      endif\n    endif\n  else\n    if (nargout > 1)\n      [c, ia] = unique (a, varargin{:});\n    else\n      c = unique (a, varargin{:});\n    endif\n    if (! isempty (c) && ! isempty (b))\n      ## Form a and b into combined set.\n      b = unique (b);\n      [csort, idx] = sort ([c(:); b(:)]);\n      ## Eliminate those elements of a that are the same as in b.\n      if (iscellstr (csort))\n        dups = find (strcmp (csort(1:end-1), csort(2:end)));\n      else\n        dups = find (csort(1:end-1) == csort(2:end));\n      endif\n      c(idx(dups)) = [];\n\n      ## Reshape if necessary for Matlab compatibility.\n      if (isrowvec)\n        c = c(:).';\n      else\n        c = c(:);\n      endif\n\n      if (nargout > 1)\n        ia(idx(dups)) = [];\n        if (optlegacy && isrowvec)\n          ia = ia(:).';\n        endif\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!assert (setdiff ([\"bb\";\"zz\";\"bb\";\"zz\"], [\"bb\";\"cc\";\"bb\"], \"rows\"), \"zz\")\n%!assert (setdiff ([\"b\";\"z\";\"b\";\"z\"], [\"b\";\"c\";\"b\"], \"rows\"), \"z\")\n%!assert (setdiff ([\"b\";\"z\";\"b\";\"z\"], [\"b\";\"c\";\"b\"]), \"z\")\n%!assert (setdiff ([1, 1; 2, 2; 3, 3; 4, 4], [1, 1; 2, 2; 4, 4], \"rows\"), [3 3])\n%!assert (setdiff ([1; 2; 3; 4], [1; 2; 4], \"rows\"), 3)\n%!assert (setdiff ([1, 2; 3, 4], [1, 2; 3, 6], \"rows\"), [3, 4])\n%!assert (setdiff ({\"one\",\"two\";\"three\",\"four\"}, {\"one\",\"two\";\"three\",\"six\"}),\n%!        {\"four\"})\n\n## Test multi-dimensional input\n%!test\n%! a = rand (3,3,3);\n%! b = a(1);\n%! assert (setdiff (a, b), sort (a(2:end)'));\n\n## Test \"rows\"\n%!test\n%! a = [7 9 7; 0 0 0; 7 9 7; 5 5 5; 1 4 5];\n%! b = [0 0 0; 5 5 5];\n%! [c, ia] = setdiff (a, b, \"rows\");\n%! assert (c, [1, 4 ,5; 7, 9 7]);\n%! assert (ia, [5; 1]);\n\n%!test\n%! a = [7 9 7; 0 0 0; 7 9 7; 5 5 5; 1 4 5];\n%! b = [0 0 0; 5 5 5];\n%! [c, ia] = setdiff (a, b, \"rows\", \"stable\");\n%! assert (c, [7, 9 7; 1, 4 ,5]);\n%! assert (ia, [1; 5]);\n\n## Test sorting order\n%!test\n%! a = [5, 1, 4, 1, 3];\n%! b = [1; 2; 4];\n%! [c, ia] = setdiff (a, b, \"sorted\");\n%! assert (c, [3, 5]);\n%! assert (ia, [5; 1]);\n\n%!test\n%! a = [5, 1, 4, 1, 3];\n%! b = [1; 2; 4];\n%! [c, ia] = setdiff (a, b, \"stable\");\n%! assert (c, [5, 3]);\n%! assert (ia, [1; 5]);\n\n## Test output orientation compatibility\n%!assert <*42577> (setdiff ([1:5], 2), [1,3,4,5])\n%!assert <*42577> (setdiff ([1:5]', 2), [1;3;4;5])\n%!assert <*42577> (setdiff ([1:5], [2:3]), [1,4,5])\n%!assert <*42577> (setdiff ([1:5], [2:3]'), [1,4,5])\n%!assert <*42577> (setdiff ([1:5]', [2:3]), [1;4;5])\n%!assert <*42577> (setdiff ([1:5]', [2:3]'), [1;4;5])\n\n## Test \"legacy\" option\n%!test\n%! a = [3, 6, 2, 1, 5, 1, 1];\n%! b = [2, 4, 6];\n%! [c, ia] = setdiff (a, b);\n%! assert (c, [1, 3, 5]);\n%! assert (ia, [4; 1; 5]);\n%! [c, ia] = setdiff (a, b, \"legacy\");\n%! assert (c, [1, 3, 5]);\n%! assert (ia, [7, 1, 5]);\n\n## \"legacy\" + \"rows\" compatibility\n%!test\n%! a = [7 9 7; 0 0 0; 7 9 7; 5 5 5; 1 4 5];\n%! b = [0 0 0; 5 5 5];\n%! [c, ia] = setdiff (a, b, \"rows\");\n%! assert (c, [1, 4 ,5; 7, 9 7]);\n%! assert (ia, [5; 1]);\n%! [c, ia] = setdiff (a, b, \"rows\", \"legacy\");\n%! assert (c, [1, 4 ,5; 7, 9 7]);\n%! assert (ia, [5; 3]);\n\n## Output orientation with \"legacy\" option\n%!assert (size (setdiff ([1:5], [2:3], \"legacy\")), [1, 3])\n%!assert (size (setdiff ([1:5]', [2:3], \"legacy\")), [1, 3])\n%!assert (size (setdiff ([1:5], [2:3]', \"legacy\")), [1, 3])\n%!assert (size (setdiff ([1:5]', [2:3]', \"legacy\")), [3, 1])\n"
  },
  {
    "path": "scripts/set/setxor.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} setxor (@var{a}, @var{b})\n## @deftypefnx {} {@var{c} =} setxor (@var{a}, @var{b}, \"rows\")\n## @deftypefnx {} {@var{c} =} setxor (@dots{}, \"sorted\")\n## @deftypefnx {} {@var{c} =} setxor (@dots{}, \"stable\")\n## @deftypefnx {} {@var{c} =} setxor (@dots{}, \"legacy\")\n## @deftypefnx {} {[@var{c}, @var{ia}, @var{ib}] =} setxor (@dots{})\n##\n## Return the unique elements exclusive to sets @var{a} or @var{b}.\n##\n## If @var{a} and @var{b} are both row vectors then return a row vector;\n## Otherwise, return a column vector.  The inputs may also be cell arrays of\n## strings.\n##\n## If the optional input @qcode{\"rows\"} is given then return the rows exclusive\n## to sets @var{a} and @var{b}.  The inputs must be 2-D numeric matrices to use\n## this option.\n##\n## The optional argument @qcode{\"sorted\"}/@qcode{\"stable\"} controls the order\n## in which unique values appear in the output.  The default is\n## @qcode{\"sorted\"} and values in the output are placed in ascending order.\n## The alternative @qcode{\"stable\"} preserves the order found in the input.\n##\n## The optional outputs @var{ia} and @var{ib} are column index vectors such\n## that @code{@var{a}(@var{ia})} and @code{@var{b}(@var{ib})} are disjoint sets\n## whose union is @var{c}.\n##\n## Programming Note: The input flag @qcode{\"legacy\"} changes the algorithm\n## to be compatible with @sc{matlab} releases prior to R2012b.\n##\n## @seealso{unique, union, intersect, setdiff, ismember}\n## @end deftypefn\n\nfunction [c, ia, ib] = setxor (a, b, varargin)\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n  endif\n\n  [a, b] = validsetargs (\"setxor\", a, b, varargin{:});\n\n  by_rows = any (strcmp (\"rows\", varargin));\n  optsorted = ! any (strcmp (\"stable\", varargin));\n  optlegacy = any (strcmp (\"legacy\", varargin));\n\n  if (optlegacy)\n    isrowvec = ! iscolumn (a) || ! iscolumn (b);\n  else\n    isrowvec = isrow (a) && isrow (b);\n  endif\n\n  ## Form A and B into sets.\n  if (nargout > 1 || ! optsorted)\n    [a, ia] = unique (a, varargin{:});\n    [b, ib] = unique (b, varargin{:});\n  else\n    a = unique (a, varargin{:});\n    b = unique (b, varargin{:});\n  endif\n\n  if (isempty (a))\n    c = b;\n  elseif (isempty (b))\n    c = a;\n  else\n    ## Reject duplicates.\n    if (by_rows)\n      na = rows (a);  nb = rows (b);\n      [c, i] = sortrows ([a; b]);\n      n = rows (c);\n      idx = find (all (c(1:n-1, :) == c(2:n, :), 2));\n      if (optsorted)\n        if (! isempty (idx))\n          c([idx, idx+1],:) = [];\n          i([idx, idx+1],:) = [];\n        endif\n      else\n        c = [a; b];\n        c(i([idx, idx+1]), :) = [];\n        if (nargout > 1)\n          i([idx, idx+1]) = [];\n          ## FIXME: Is there a way to avoid a call to sort?\n          i = sort (i);\n        endif\n      endif\n    else\n      na = numel (a);  nb = numel (b);\n      [c, i] = sort ([a(:); b(:)]);\n      if (iscell (c))\n        idx = find (strcmp (c(1:end-1), c(2:end)));\n      else\n        idx = find (c(1:end-1) == c(2:end));\n      endif\n      if (optsorted)\n        if (! isempty (idx))\n          c([idx, idx+1]) = [];\n          i([idx, idx+1]) = [];\n        endif\n      else\n        c = [a(:); b(:)];\n        c(i([idx, idx+1])) = [];\n        if (nargout > 1)\n          i([idx, idx+1]) = [];\n          ## FIXME: Is there a way to avoid a call to sort?\n          i = sort (i);\n        endif\n      endif\n\n      ## Adjust output orientation for Matlab compatibility\n      if (isrowvec)\n        c = c.';\n      endif\n    endif\n\n    if (nargout > 1)\n      ia = ia(i(i <= na));\n      ib = ib(i(i > na) - na);\n      if (optlegacy && isrowvec && ! by_rows)\n        ia = ia(:).';\n        ib = ib(:).';\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!assert (setxor ([3,1,2], [4,3,2]), [1,4])\n%!assert (setxor ({'a'}, {'a', 'b'}), {'b'})\n%!assert (setxor ([5, NaN, NaN], [NaN, NaN, 5]), [NaN NaN NaN NaN])\n\n%!test\n%! a = [3, 1, 4, 1, 5];\n%! b = [1; 2; 3; 4];\n%! [c, ia, ib] = setxor (a, b);\n%! assert (c, [2; 5]);\n%! assert (ia, [5]);\n%! assert (ib, [2]);\n\n## Test multi-dimensional arrays\n%!test\n%! a = rand (3,3,3);\n%! b = a;\n%! b(1,1,1) = 2;\n%! assert (intersect (a, b), sort (a(2:end)'));\n\n## Test \"rows\" input\n%!test\n%! a = [1 2; 4 5; 1 3];\n%! b = [1 1; 1 2; 4 5; 2 10];\n%! [c, ia, ib] = setxor (a, b, \"rows\");\n%! assert (c, [1 1; 1 3; 2 10]);\n%! assert (ia, [3]);\n%! assert (ib, [1; 4]);\n\n## Test \"stable\" sort order\n%!test\n%! a = [3, 1, 4, 1, 5];\n%! b = [1; 2; 3; 4];\n%! [c, ia, ib] = setxor (a, b, \"stable\");\n%! assert (c, [5; 2]);\n%! assert (ia, [5]);\n%! assert (ib, [2]);\n\n%!test\n%! a = [1 2; 4 5; 1 3];\n%! b = [1 1; 1 2; 4 5; 2 10];\n%! [c, ia, ib] = setxor (a, b, \"rows\", \"stable\");\n%! assert (c, [1 3; 1 1; 2 10]);\n%! assert (ia, [3]);\n%! assert (ib, [1; 4]);\n\n## Test various empty matrix inputs\n%!assert (setxor (1, []), 1)\n%!assert (setxor ([], 1), 1)\n\n%!test\n%! [c, ia, ib] = setxor ([3 1], []);\n%! assert (c, [1 3]);\n%! assert (ia, [2; 1]);\n%! assert (ib, []);\n%!test\n%! [c, ia, ib] = setxor ([], [3 1]);\n%! assert (c, [1 3]);\n%! assert (ia, []);\n%! assert (ib, [2; 1]);\n\n%!test\n%! a = [2 1; 4 3];  b = [];\n%! [c, ia, ib] = setxor (a, b);\n%! assert (c, [1; 2; 3; 4]);\n%! assert (ia, [3; 1; 4; 2]);\n%! assert (isempty (ib));\n\n%!test\n%! a = [];  b = [2 1; 4 3];\n%! [c, ia, ib] = setxor (a, b);\n%! assert (c, [1; 2; 3; 4]);\n%! assert (isempty (ia));\n%! assert (ib, [3; 1; 4; 2]);\n\n## Test orientation of output\n%!shared x,y\n%! x = 1:3;\n%! y = 2:5;\n\n%!assert (size (setxor (x, y)), [1 3])\n%!assert (size (setxor (x', y)), [3 1])\n%!assert (size (setxor (x, y')), [3 1])\n%!assert (size (setxor (x', y')), [3 1])\n%!assert (size (setxor (x, y, \"legacy\")), [1, 3])\n%!assert (size (setxor (x', y, \"legacy\")), [1, 3])\n%!assert (size (setxor (x, y', \"legacy\")), [1, 3])\n%!assert (size (setxor (x', y', \"legacy\")), [3, 1])\n\n## Test \"legacy\" input\n%!test\n%! a = [5 1 3 3 3];\n%! b = [4 1 2 2];\n%! [c,ia,ib] = setxor (a,b);\n%! assert (c, [2, 3, 4, 5]);\n%! assert (ia, [3; 1]);\n%! assert (ib, [3; 1]);\n%! [c,ia,ib] = setxor (a,b, \"legacy\");\n%! assert (c, [2, 3, 4, 5]);\n%! assert (ia, [5, 1]);\n%! assert (ib, [4, 1]);\n\n%!test  # \"legacy\" + \"rows\"\n%! A = [1 2; 3 4; 5 6; 3 4; 7 8];\n%! B = [3 4; 7 8; 9 10];\n%! [c, ia, ib] = setxor (A, B, \"rows\");\n%! assert (c, [1, 2; 5, 6; 9, 10]);\n%! assert (ia, [1; 3]);\n%! assert (ib, [3]);\n%! [c, ia, ib] = setxor (A, B, \"rows\", \"legacy\");\n%! assert (c, [1, 2; 5, 6; 9, 10]);\n%! assert (ia, [1; 3]);\n%! assert (ib, [3]);\n"
  },
  {
    "path": "scripts/set/union.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} union (@var{a}, @var{b})\n## @deftypefnx {} {@var{c} =} union (@var{a}, @var{b}, \"rows\")\n## @deftypefnx {} {@var{c} =} union (@dots{}, \"sorted\")\n## @deftypefnx {} {@var{c} =} union (@dots{}, \"stable\")\n## @deftypefnx {} {@var{c} =} union (@dots{}, \"legacy\")\n## @deftypefnx {} {[@var{c}, @var{ia}, @var{ib}] =} union (@dots{})\n##\n## Return the unique elements that are in either @var{a} or @var{b}.\n##\n## If @var{a} and @var{b} are both row vectors then return a row vector;\n## Otherwise, return a column vector.  The inputs may also be cell arrays of\n## strings.\n##\n## If the optional input @qcode{\"rows\"} is given then return rows that are in\n## either @var{a} or @var{b}.  The inputs must be 2-D numeric matrices to use\n## this option.\n##\n## The optional argument @qcode{\"sorted\"}/@qcode{\"stable\"} controls the order\n## in which unique values appear in the output.  The default is\n## @qcode{\"sorted\"} and values in the output are placed in ascending order.\n## The alternative @qcode{\"stable\"} preserves the order found in the input.\n##\n## The optional outputs @var{ia} and @var{ib} are column index vectors such\n## that @code{@var{a}(@var{ia})} and @code{@var{b}(@var{ib})} are disjoint sets\n## whose union is @var{c}.\n##\n## Programming Note: The input flag @qcode{\"legacy\"} changes the algorithm\n## to be compatible with @sc{matlab} releases prior to R2012b.\n##\n## @seealso{unique, intersect, setdiff, setxor, ismember}\n## @end deftypefn\n\nfunction [y, ia, ib] = union (a, b, varargin)\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n  endif\n\n  [a, b] = validsetargs (\"union\", a, b, varargin{:});\n\n  by_rows = any (strcmp (\"rows\", varargin));\n  optlegacy = any (strcmp (\"legacy\", varargin));\n\n  if (optlegacy)\n    isrowvec = ! iscolumn (a) || ! iscolumn (b);\n  else\n    isrowvec = isrow (a) && isrow (b);\n  endif\n\n  if (by_rows)\n    y = [a; b];\n  else\n    y = [a(:); b(:)];\n    ## Adjust output orientation for Matlab compatibility\n    if (isrowvec)\n      y = y.';\n    endif\n  endif\n\n  if (nargout <= 1)\n    y = unique (y, varargin{:});\n  else\n    [y, idx] = unique (y, varargin{:});\n    if (by_rows)\n      na = rows (a);\n    else\n      na = numel (a);\n    endif\n    ia = idx(idx <= na);\n    ib = idx(idx > na) - na;\n  endif\n\nendfunction\n\n\n%!assert (union ([1, 2, 4], [2, 3, 5]), [1, 2, 3, 4, 5])\n%!assert (union ([1; 2; 4], [2, 3, 5]), [1; 2; 3; 4; 5])\n%!assert (union ([1; 2; 4], [2; 3; 5]), [1; 2; 3; 4; 5])\n%!assert (union ([1, 2, 3], [5; 7; 9]), [1; 2; 3; 5; 7; 9])\n%!assert (union ([1 2; 2 3; 4 5], [2 3; 3 4; 5 6], \"rows\"),\n%!        [1 2; 2 3; 3 4; 4 5; 5 6])\n\n## Test multi-dimensional arrays\n%!test\n%! a = rand (3,3,3);\n%! b = a;\n%! b(1,1,1) = 2;\n%! assert (union (a, b), sort ([a(1:end)'; 2]));\n\n%!test\n%! a = [3, 1, 4, 1, 5];\n%! b = [1; 2; 3; 4];\n%! [y, ia, ib] = union (a, b);\n%! assert (y, [1; 2; 3; 4; 5]);\n%! assert (y, sort ([a(ia)'; b(ib)']));\n\n## Test \"stable\" sorting order\n%!assert (union ([1, 2, 4], [2, 3, 5], \"stable\"), [1, 2, 4, 3, 5])\n%!assert (union ([1, 2, 4]', [2, 3, 5], \"stable\"), [1; 2; 4; 3; 5])\n%!assert (union ([1, 2, 4], [2, 3, 5]', \"stable\"), [1; 2; 4; 3; 5])\n\n%!test\n%! a = [3, 1, 4, 1, 5];\n%! b = [1; 2; 3; 4];\n%! [y, ia, ib] = union (a, b, \"stable\");\n%! assert (y, [3; 1; 4; 5; 2]);\n%! assert (ia, [1; 2; 3; 5]);\n%! assert (ib, [2]);\n\n## Test indexing outputs\n%!test\n%! a = [1, 4, 2];\n%! b = [2, 3, 5];\n%! [~, ia, ib] = union (a, b);\n%! assert (ia, [1; 3; 2]);\n%! assert (ib, [2; 3]);\n%! [~, ia, ib] = union (a, b, \"stable\");\n%! assert (ia, [1; 2; 3]);\n%! assert (ib, [2; 3]);\n\n%!test\n%! a = [1 2; 4 5; 2 3];\n%! b = [2 3; 3 4; 5 6];\n%! [~, ia, ib] = union (a, b, \"rows\");\n%! assert (ia, [1; 3; 2]);\n%! assert ([2; 3]);\n%! [~, ia, ib] = union (a, b, \"rows\", \"stable\");\n%! assert (ia, [1; 2; 3]);\n%! assert ([2; 3]);\n\n## Test \"legacy\" option\n%!test\n%! a = [5, 7, 1];\n%! b = [3, 1, 1];\n%! [c, ia, ib] = union (a,b);\n%! assert (c, [1, 3, 5, 7]);\n%! assert (ia, [3; 1; 2]);\n%! assert (ib, [1]);\n%! [c, ia, ib] = union (a,b, \"legacy\");\n%! assert (c, [1, 3, 5, 7]);\n%! assert (ia, [1, 2]);\n%! assert (ib, [3, 1]);\n\n%!test  # \"legacy\" + \"rows\"\n%! A = [1 2; 3 4; 5 6; 3 4; 7 8];\n%! B = [3 4; 7 8; 9 10];\n%! [c, ia, ib] = union (A, B, \"rows\");\n%! assert (c, [1, 2; 3, 4; 5, 6; 7, 8; 9, 10]);\n%! assert (ia, [1; 2; 3; 5]);\n%! assert (ib, [3]);\n%! [c, ia, ib] = union (A, B, \"rows\", \"legacy\");\n%! assert (c, [1, 2; 3, 4; 5, 6; 7, 8; 9, 10]);\n%! assert (ia, [1; 3]);\n%! assert (ib, [1; 2; 3]);\n\n## Test orientation of output\n%!shared x,y\n%! x = 1:3;\n%! y = 2:5;\n\n%!assert (size (union (x, y)), [1 5])\n%!assert (size (union (x', y)), [5 1])\n%!assert (size (union (x, y')), [5 1])\n%!assert (size (union (x', y')), [5 1])\n%!assert (size (union (x, y, \"legacy\")), [1, 5])\n%!assert (size (union (x', y, \"legacy\")), [1, 5])\n%!assert (size (union (x, y', \"legacy\")), [1, 5])\n%!assert (size (union (x', y', \"legacy\")), [5, 1])\n\n## Clear shared variables\n%!shared\n\n## Test empty cell string array unions\n%!assert (union ({}, []), cell (0,1))\n%!assert (union ([], {}), cell (0,1))\n%!assert (union ([], {'a', 'b'}), {'a';'b'})\n%!assert (union ({'a', 'b'}, []), {'a';'b'})\n%!assert (union (['a', 'b'], {}), {'ab'})\n%!assert (union ({}, ['a', 'b']), {'ab'})\n\n## Test common input validation for set routines contained in validsetargs\n%!error <cell array of strings cannot be combined> union ({\"a\"}, 1)\n%!error <A and B must be arrays or cell arrays> union (@sin, 1)\n%!error <cells not supported with \"rows\"> union ({\"a\"}, {\"b\"}, \"rows\")\n%!error <cells not supported with \"rows\"> union ({\"a\"}, {\"b\"}, \"rows\",\"legacy\")\n%!error <A and B must be arrays or cell arrays> union (@sin, 1, \"rows\")\n%!error <A and B must be arrays or cell arrays> union (@sin,1,\"rows\",\"legacy\")\n%!error <A and B must be 2-dimensional matrices> union (rand (2,2,2), 1, \"rows\")\n%!error <A and B must be 2-dimensional matrices> union (1, rand (2,2,2), \"rows\")\n%!error <A and B must be 2-dimensional matrices>\n%! union (rand (2,2,2), 1, \"rows\", \"legacy\");\n%!error <A and B must be 2-dimensional matrices>\n%! union (1, rand (2,2,2), \"rows\", \"legacy\");\n%!error <number of columns in A and B must match> union ([1 2], 1, \"rows\")\n%!error <number of columns in A and B must match> union (1, [1 2], \"rows\")\n%!error <number of columns in A and B must match>\n%! union ([1 2], 1, \"rows\", \"legacy\");\n%!error <number of columns in A and B must match>\n%! union (1, [1 2], \"rows\", \"legacy\");\n%!error <invalid option: columns> union (1, 2, \"columns\")\n%!error <invalid option: columns> union (1, 2, \"legacy\", \"columns\")\n%!error <only one of \"sorted\", \"stable\", or \"legacy\" may be specified>\n%! union (1, 2, \"sorted\", \"stable\");\n%!error <only one of \"sorted\", \"stable\", or \"legacy\" may be specified>\n%! union (1, 2, \"sorted\", \"legacy\");\n"
  },
  {
    "path": "scripts/set/unique.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} unique (@var{x})\n## @deftypefnx {} {@var{y} =} unique (@var{x}, \"rows\")\n## @deftypefnx {} {@var{y} =} unique (@dots{}, \"sorted\")\n## @deftypefnx {} {@var{y} =} unique (@dots{}, \"stable\")\n## @deftypefnx {} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{})\n## @deftypefnx {} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{}, \"first\")\n## @deftypefnx {} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{}, \"last\")\n## @deftypefnx {} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{}, \"legacy\")\n## Return the unique elements of @var{x}.\n##\n## If the input @var{x} is a column vector then return a column vector;\n## Otherwise, return a row vector.  @var{x} may also be a cell array of\n## strings.\n##\n## If the optional argument @qcode{\"rows\"} is given then return the unique\n## rows of @var{x}.  The input must be a 2-D numeric matrix to use this option.\n##\n## The optional argument @qcode{\"sorted\"}/@qcode{\"stable\"} controls the order\n## in which unique values appear in the output.  The default is\n## @qcode{\"sorted\"} and values in the output are placed in ascending order.\n## The alternative @qcode{\"stable\"} preserves the order found in the input\n## @var{x}.\n##\n## If requested, return column index vectors @var{i} and @var{j} such that\n## @code{@var{y} = @var{x}(@var{i})} and @code{@var{x} = @var{y}(@var{j})}.\n##\n## Additionally, if @var{i} is a requested output then one of the flags\n## @qcode{\"first\"} or @qcode{\"last\"} may be given.  If @qcode{\"last\"} is\n## specified, return the highest possible indices in @var{i}, otherwise, if\n## @qcode{\"first\"} is specified, return the lowest.  The default is\n## @qcode{\"first\"}.\n##\n## Example 1 : sort order\n##\n## @example\n## @group\n## unique ([3, 1, 1, 2])\n## @xresult{} [1, 2, 3]\n## unique ([3, 1, 1, 2], \"stable\")\n## @xresult{} [3, 1, 2]\n## @end group\n## @end example\n##\n## Example 2 : index selection\n##\n## @example\n## @group\n## [~, @var{i}] = unique ([3, 1, 1, 2], \"first\")\n## @xresult{} @var{i} = [2; 4; 1]\n## [~, @var{i}] = unique ([3, 1, 1, 2], \"last\")\n## @xresult{} @var{i} = [3; 4; 1]\n## @end group\n## @end example\n##\n## Programming Notes: The input flag @qcode{\"legacy\"} changes the algorithm\n## to be compatible with @sc{matlab} releases prior to R2012b.  Specifically,\n## The index ordering flag is changed to @qcode{\"last\"}, and the shape of the\n## outputs @var{i}, @var{j} will follow the shape of the input @var{x} rather\n## than always being column vectors.\n##\n## @seealso{uniquetol, union, intersect, setdiff, setxor, ismember}\n## @end deftypefn\n\nfunction [y, i, j] = unique (x, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! (isnumeric (x) || islogical (x) || ischar (x) || iscellstr (x)))\n    error (\"unique: X must be an array or cell array of strings\");\n  endif\n\n  if (nargin > 1)\n    ## parse options\n    if (! iscellstr (varargin))\n      error (\"unique: options must be strings\");\n    endif\n\n    optrows   = any (strcmp (\"rows\", varargin));\n    optfirst  = any (strcmp (\"first\", varargin));\n    optlast   = any (strcmp (\"last\", varargin));\n    optsorted = any (strcmp (\"sorted\", varargin));\n    optstable = any (strcmp (\"stable\", varargin));\n    optlegacy = any (strcmp (\"legacy\", varargin));\n    if (optfirst && optlast)\n      error ('unique: cannot specify both \"first\" and \"last\"');\n    elseif (optsorted && optstable)\n      error ('unique: cannot specify both \"sorted\" and \"stable\"');\n    elseif ((optfirst || optlast) && (optsorted || optstable))\n      error ('unique: cannot specify \"first\"/\"last\" with \"sorted\"/\"stable\"');\n    elseif (optlegacy && (optsorted || optstable))\n      error ('unique: cannot specify \"sorted\" or \"stable\" with \"legacy\"');\n    elseif (optrows + optfirst + optlast + optsorted + optstable + optlegacy\n            != nargin-1)\n      error (\"unique: invalid option\");\n    endif\n\n    ## Set defaults if not set earlier.\n    if (! optfirst && ! optlast)\n      optfirst = true;\n    endif\n    if (! optsorted && ! optstable)\n      optsorted = true;\n    endif\n\n    if (optrows && iscellstr (x))\n      warning ('unique: \"rows\" is ignored for cell arrays');\n      optrows = false;\n    endif\n  else\n    optrows = false;\n    optfirst = true;\n    optsorted = true;\n    optlegacy = false;\n  endif\n\n  ## FIXME: The operations\n  ##\n  ##   match = (y(1:n-1) == y(2:n));\n  ##   y(idx) = [];\n  ##\n  ## are very slow on sparse matrices.  Until they are fixed to be as\n  ## fast as for full matrices, operate on the nonzero elements of the\n  ## sparse array as long as we are not operating on rows.\n  if (issparse (x) && ! optrows && nargout <= 1)\n    if (nnz (x) < numel (x))\n      y = unique ([0; nonzeros(x)], varargin{:});\n    else\n      ## Corner case where sparse matrix is actually full\n      y = unique (full (x), varargin{:});\n    endif\n    return;\n  endif\n\n  if (optrows)\n    n = rows (x);\n    isrowvec = false;\n  else\n    n = numel (x);\n    isrowvec = isrow (x);\n  endif\n\n  ## Special cases 0 and 1\n  if (n == 0)\n    y = x;\n    if (! optrows && any (size (x)))\n      if (iscellstr (x))\n        y = cell (0, 1);\n      else\n        y = zeros (0, 1, class (x));\n      endif\n    endif\n    i = j = [];\n    return;\n  elseif (n == 1)\n    y = x;\n    i = j = 1;\n    return;\n  endif\n\n  ## Calculate y output\n  if (optrows)\n    if (nargout > 1 || ! optsorted)\n      [y, j] = sortrows (x);\n      j = j(:);\n    else\n      y = sortrows (x);\n    endif\n    match = all (y(1:n-1,:) == y(2:n,:), 2);\n    if (optsorted)\n      y(match,:) = [];\n    else\n      y = x;\n      y(j([false; match]), :) = [];\n    endif\n  else\n    if (isvector (x))\n      y = x;\n    else\n      y = x(:);\n    endif\n    if (nargout > 1 || ! optsorted)\n      [y, j] = sort (y);\n      j = j(:);\n    else\n      y = sort (y);\n    endif\n    if (iscellstr (y))\n      match = strcmp (y(1:n-1), y(2:n));\n    else\n      match = (y(1:n-1) == y(2:n));\n    endif\n    if (optsorted)\n      y(match) = [];\n    else\n      if (isvector (x))\n        y = x;\n      else\n        y = x(:);\n      endif\n      y(j([false; match(:)])) = [];\n    endif\n  endif\n\n  ## Calculate i and j outputs (2nd and 3rd outputs)\n  if (nargout > 1)\n    if (optsorted)\n      idx = find (match);\n\n      if (! optlegacy && optfirst)\n        idx += 1;\n      endif\n\n      i = j;\n      i(idx) = [];\n\n      if (nargout > 2)\n        j(j) = cumsum (! [false; match(:)]);\n      endif\n    else\n      ## Get inverse of sort index j so that sort(x)(k) = x(j)(k) = x.\n      k = j;  # cheap way to copy dimensions\n      k(j) = 1:n;\n\n      ## Generate logical index of sorted unique value locations.\n      uniquex = ! [false; match(:)];\n\n      ## Remap unique locations to unsorted x, such that y = x(i).\n      i = find (uniquex(k));\n\n      if (nargout > 2)\n        ## Example of index mappings to obtain i and j ('stable').\n        ## x = [40,20,40,20,20,30,10]'     # input data, n = 7, m = 4\n        ## x(j) = [10,20,20,20,30,40,40]'  # sorted x\n        ## j =   [7,2,4,5,6,1,3]'          # sort index, x(j) = sort(x)\n        ## k = [6,2,7,3,4,5,1]'            # inverse idx of j, sort(x)(k) = x\n        ## y = [40,20,30,10]'              # unique x preserving ordering\n        ## uniquex = [1,1,0,0,1,1,0]'      # logical sorted idx of unique x vals\n        ## i = [1,2,6,7]'                  # unique output index, y = x(i)\n        ## u = [1,2,5,6]'                  # linear idx of unique x(j) elems.\n        ## l = [1,2,2,2,5,6,6]'            # unique elem. in full sort(x)\n        ## l(k) = [6,2,6,2,2,5,1]'         # l mapped back to unsorted x\n        ## j(l(k)) =  [1,2,1,2,2,6,7]'     # unique elem. mapped to x idx\n        ## p(i) = [1,2,#,#,#,3,4]'         # map between i and j(l(k))\n\n        ni = numel (i);\n\n        u = find (uniquex);       # Linear index of unique elements of sort(x)\n        l = u(cumsum (uniquex));  # Expand u for all elements in sort(x)\n\n        p = j;  # cheap way to copy dimensions\n        p(i) = 1:ni;  # set p to contain the vector positions of i.\n\n        j = p(j(l(k)));  # Replace j with 3rd output mapping y->x.\n      endif\n    endif\n\n    if (optlegacy && isrowvec)\n      i = i.';\n      if (nargout > 2)\n        j = j.';\n      endif\n    endif\n\n  endif\n\nendfunction\n\n\n%!assert (unique ([1 1 2; 1 2 1; 1 1 2]), [1;2])\n%!assert (unique ([1 1 2; 1 0 1; 1 1 2],\"rows\"), [1 0 1; 1 1 2])\n%!assert (unique ([]), [])\n%!assert (unique ([1]), [1])\n%!assert (unique ([1 2]), [1 2])\n%!assert (unique ([1;2]), [1;2])\n%!assert (unique ([1,NaN,Inf,NaN,Inf]), [1,Inf,NaN,NaN])\n%!assert (unique ([1,NaN,Inf,NaN,Inf], \"stable\"), [1,NaN,Inf,NaN])\n%!assert (unique ({\"Foo\",\"Bar\",\"Foo\"}), {\"Bar\",\"Foo\"})\n%!assert (unique ({\"Foo\",\"Bar\",\"Foo\"}, \"stable\"), {\"Foo\", \"Bar\"})\n%!assert (unique ({\"Foo\",\"Bar\",\"FooBar\"}'), {\"Bar\",\"Foo\",\"FooBar\"}')\n%!assert (unique (zeros (1,0)), zeros (0,1))\n%!assert (unique (zeros (1,0), \"rows\"), zeros (1,0))\n%!assert (unique (cell (1,0)), cell (0,1))\n%!assert (unique ({}), {})\n%!assert (unique ([1,2,2,3,2,4], \"rows\"), [1,2,2,3,2,4])\n%!assert (unique ([1,2,2,3,2,4]), [1,2,3,4])\n%!assert (unique ([1,2,2,3,2,4]', \"rows\"), [1;2;3;4])\n%!assert (unique (sparse ([2,0;2,0])), [0;2])\n%!assert (unique (sparse ([1,2;2,3])), [1;2;3])\n%!assert (unique ([1,2,2,3,2,4]', \"rows\"), [1;2;3;4])\n%!assert (unique (single ([1,2,2,3,2,4]), \"rows\"), single ([1,2,2,3,2,4]))\n%!assert (unique (single ([1,2,2,3,2,4])), single ([1,2,3,4]))\n%!assert (unique (single ([1,2,2,3,2,4]'), \"rows\"), single ([1;2;3;4]))\n%!assert (unique (uint8 ([1,2,2,3,2,4]), \"rows\"), uint8 ([1,2,2,3,2,4]))\n%!assert (unique (uint8 ([1,2,2,3,2,4])), uint8 ([1,2,3,4]))\n%!assert (unique (uint8 ([1,2,2,3,2,4]'), \"rows\"), uint8 ([1;2;3;4]))\n\n## Test options with numeric inputs\n%!test\n%! [y,i,j] = unique ([1,1,2,3,3,3,4], \"sorted\");\n%! assert (y, [1,2,3,4]);\n%! assert (i, [1;3;4;7]);\n%! assert (j, [1;1;2;3;3;3;4]);\n\n%!test\n%! [y,i,j] = unique ([4,4,2,2,2,3,1], \"stable\");\n%! assert (y, [4,2,3,1]);\n%! assert (i, [1;3;6;7]);\n%! assert (j, [1;1;2;2;2;3;4]);\n\n%!test\n%! [y,i,j] = unique ([1,1,2,3,3,3,4]', \"last\");\n%! assert (y, [1,2,3,4]');\n%! assert (i, [2;3;6;7]);\n%! assert (j, [1;1;2;3;3;3;4]);\n\n## Test options with cellstr inputs\n%!test\n%! [y,i,j] = unique ({\"z\"; \"z\"; \"z\"});\n%! assert (y, {\"z\"});\n%! assert (i, [1]);\n%! assert (j, [1;1;1]);\n\n%!test\n%! [y,i,~] = unique ({\"B\"; \"A\"; \"B\"}, \"stable\");\n%! assert (y, {\"B\"; \"A\"});\n%! assert (i, [1; 2]);\n\n%!test\n%! A = [1,2,3; 1,2,3];\n%! [y,i,j] = unique (A, \"rows\");\n%! assert (y, [1,2,3]);\n%! assert (A(i,:), y);\n%! assert (y(j,:), A);\n\n%!test\n%! A = [4,5,6; 1,2,3; 4,5,6];\n%! [y,i,j] = unique (A, \"rows\", \"stable\");\n%! assert (y, [4,5,6; 1,2,3]);\n%! assert (A(i,:), y);\n%! assert (y(j,:), A);\n\n## Test \"legacy\" option\n%!test\n%! [y,i,j] = unique ([1,1,2,3,3,3,4], \"legacy\");\n%! assert (y, [1,2,3,4]);\n%! assert (i, [2,3,6,7]);\n%! assert (j, [1,1,2,3,3,3,4]);\n\n%!test\n%! A = [7 9 7; 0 0 0; 7 9 7; 5 5 5; 1 4 5];\n%! [y,i,j] = unique (A, \"rows\", \"legacy\");\n%! assert (y, [0 0 0; 1 4 5; 5 5 5; 7 9 7]);\n%! assert (i, [2; 5; 4; 3]);\n%! assert (j, [4; 1; 4; 3; 2]);\n\n%!test <*65176>\n%! a = [3 2 1 2; 1 2 2 1];\n%! [o1, o2, o3] = unique (a);\n%! assert ({o1, o2, o3}, {[1;2;3], [2;3;1], [3;1;2;2;1;2;2;1]});\n%! [o1, o2, o3] = unique (a, \"stable\");\n%! assert ({o1, o2, o3}, {[3;1;2], [1;2;3], [1;2;3;3;2;3;3;2]});\n\n%!test <*65176>\n%! a = [4,2,4,2,2,3,1];\n%! [o1, o2, o3] = unique (a);\n%! assert ({o1, o2, o3}, {[1,2,3,4], [7;2;6;1], [4;2;4;2;2;3;1]});\n%! [o1, o2, o3] = unique (a, \"stable\");\n%! assert ({o1, o2, o3}, {[4,2,3,1], [1;2;6;7], [1;2;1;2;2;3;4]});\n\n%!test <*65176>\n%! a = [3 2 1 2; 2 1 2 1];\n%! [o1, o2, o3] = unique (a(1,:), \"rows\");\n%! assert ({o1, o2, o3}, {a(1,:), 1, 1});\n%! [o1, o2, o3] = unique (a(1,:), \"rows\", \"stable\");\n%! assert ({o1, o2, o3}, {a(1,:), 1, 1});\n%! [o1, o2, o3] = unique (a, \"rows\");\n%! assert ({o1, o2, o3}, {[a(2,:); a(1,:)], [2;1], [2;1]});\n%! [o1, o2, o3] = unique (a, \"rows\", \"stable\");\n%! assert ({o1, o2, o3}, {a, [1;2], [1;2]});\n%! [o1, o2, o3] = unique ([a;a], \"rows\");\n%! assert ({o1, o2, o3}, {[a(2,:); a(1,:)], [2;1], [2;1;2;1]});\n%! [o1, o2, o3] = unique ([a;a], \"rows\", \"stable\");\n%! assert ({o1, o2, o3}, {a, [1;2], [1;2;1;2]});\n\n\n%!test <*65176>\n%! a = gallery (\"integerdata\", [-100, 100], 6, 6);\n%! a = [a(2,:); a(1:5,:); a(2:6,:)];\n%! [o1, o2, o3] = unique (a);\n%! assert ({o1, o1(o3), o2, o3}, {a(:)(o2), a(:), ...\n%! [26;22;34;45;57; 6;11;17;33;28;35;15;56; 2;59; 4;66; ...\n%!  16;50;49;27;24;37;44;48;39;38;13;23; 5;12;46;55; 1], ...\n%! [34;14;34;16;30; 6;34;16;30; 6; 7;31;28;31;12;18; 8;31;12;18; 8; 2;29; ...\n%!  22;29; 1;21;10;29; 1;21;10; 9; 3;11; 3;23;27;26; 3;23;27;26;24; 4;32; ...\n%!  4; 25;20;19; 4;25;20;19;33;13; 5;13;15; 2;24;13;15; 2;24;17]});\n%! [o1, o2, o3] = unique (a, \"stable\");\n%! assert ({o1, o1(o3), o2, o3}, {a(:)(o2), a(:), ...\n%! [ 1; 2; 4; 5; 6;11;12;13;15;16;17;22;23;24;26;27;28; ...\n%!  33;34;35;37;38;39;44;45;46;48;49;50;55;56;57;59;66], ...\n%! [ 1; 2; 1; 3; 4; 5; 1; 3; 4; 5; 6; 7; 8; 7; 9;10;11; 7; 9;10;11;12;13; ...\n%!  14;13;15;16;17;13;15;16;17;18;19;20;19;21;22;23;19;21;22;23;24;25;26;...\n%!  25;27;28;29;25;27;28;29;30;31;32;31;33;12;24;31;33;12;24;34]});\n%! [o1, o2, o3] = unique (a, \"rows\");\n%! assert ({o1, o1(o3,:), o2, o3}, {a(o2,:), a, ...\n%! [6;11;2;4;5;1], [6;3;6;4;5;1;6;4;5;1;2]});\n%! [o1, o2, o3] = unique (a, \"rows\", \"stable\");\n%! assert ({o1, o1(o3,:), o2, o3}, {a(o2,:), a, ...\n%! [1;2;4;5;6;11], [1;2;1;3;4;5;1;3;4;5;6]});\n\n## Test input validation\n%!error <Invalid call> unique ()\n%!error <X must be an array or cell array of strings> unique ({1})\n%!error <options must be strings> unique (1, 2)\n%!error <cannot specify both \"first\" and \"last\"> unique (1, \"first\", \"last\")\n%!error <cannot specify both \"sorted\" and \"stable\">\n%! unique (1, \"sorted\", \"stable\");\n%!error <cannot specify \"first\"/\"last\" with \"sorted\"/\"stable\">\n%! unique (1, \"first\", \"sorted\");\n%!error <cannot specify \"first\"/\"last\" with \"sorted\"/\"stable\">\n%! unique (1, \"last\", \"stable\");\n%!error <cannot specify \"sorted\" or \"stable\" with \"legacy\">\n%! unique (1, \"sorted\", \"legacy\");\n%!error <cannot specify \"sorted\" or \"stable\" with \"legacy\">\n%! unique (1, \"stable\", \"legacy\");\n%!error <invalid option> unique (1, \"middle\")\n%!error <invalid option> unique ({\"a\", \"b\", \"c\"}, \"UnknownOption\")\n%!error <invalid option> unique ({\"a\", \"b\", \"c\"}, \"UnknownOption1\", \"UnknownOption2\")\n%!error <invalid option> unique ({\"a\", \"b\", \"c\"}, \"rows\", \"UnknownOption2\")\n%!error <invalid option> unique ({\"a\", \"b\", \"c\"}, \"UnknownOption1\", \"last\")\n%!warning <\"rows\" is ignored for cell arrays> unique ({\"1\"}, \"rows\");\n"
  },
  {
    "path": "scripts/set/uniquetol.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} uniquetol (@var{A})\n## @deftypefnx {} {@var{c} =} uniquetol (@var{A}, @var{tol})\n## @deftypefnx {} {@var{c} =} uniquetol (@dots{}, @var{property}, @var{value})\n## @deftypefnx {} {[@var{c}, @var{ia}, @var{ic}] =} uniquetol (@dots{})\n## Return the unique elements of @var{A} within tolerance @var{tol}.\n##\n## Two values, @var{x} and @var{y}, are within relative tolerance if\n## @code{abs (@var{x} - @var{y}) <= @var{tol} * max (abs (@var{A}(:)))}.\n##\n## The input @var{A} must be a real (non-complex) floating point type (double\n## or single).\n##\n## If @var{tol} is unspecified, the default tolerance is 1e-12 for double\n## precision input or 1e-6 for single precision input.\n##\n## The function may also be called with the following optional property/value\n## pairs.  Property/value pairs must be passed after other input arguments:\n##\n## @table @asis\n## @item @qcode{\"ByRows\"} (default: @code{false})\n## When true, return the unique rows of @var{A}.  @var{A} must be a 2-D array\n## to use this option.  For rows, the criteria for uniqueness is changed to\n## @code{all (abs (@var{x} - @var{y}) <= @var{tol}*max (abs (@var{A}),[],1))}\n## which compares each column component of a row against a column-specific\n## tolerance.\n##\n## @item @qcode{\"DataScale\"}\n## The tolerance test is changed to\n## @code{abs (@var{x} - @var{y}) <= @var{tol}*@var{DS}} where @var{DS} is a\n## scalar unless the property @qcode{\"ByRows\"} is true.  In that case, @var{DS}\n## can either be a scalar or a vector with a length equal to the number of\n## columns in @var{A}.  Using a value of @code{1.0} for @var{DS} will change\n## the tolerance from a relative one to an absolute tolerance.  Using a value\n## of @code{Inf} will disable testing.\n##\n## @item @qcode{\"OutputAllIndices\"} (default: @code{false})\n## When true, @var{ia} is a cell array (not a vector) that contains the indices\n## for @emph{all} elements in @var{A} that are within tolerance of a value in\n## @var{C}.  That is, each cell in @var{ia} corresponds to a single unique\n## value in @var{C}, and the values in each cell correspond to locations in\n## @var{A}.\n## @end table\n##\n## The output @var{c} is a row vector if the input @var{A} is a row vector.\n## For all other cases, a column vector is returned.\n##\n## The optional output @var{ia} is a column index vector such that\n## @code{@var{c} = @var{A}(@var{ia})}.  If the @qcode{\"ByRows\"} property is\n## true, the condition is @code{@var{c} = @var{A}(@var{ia}, :)}.  If the\n## @qcode{\"OutputAllIndices\"} property is true, then the values\n## @code{@var{A}(@var{ia}@{@var{i}@})} are all within tolerance of the unique\n## value @code{@var{c}(@var{i})}.\n##\n## The optional output @var{ic} is a column index vector such that\n## @code{@var{A} = @var{c}(@var{ic})} when @var{A} is a vector.  When @var{A}\n## is a matrix, @code{@var{A}(:) = @var{c}(@var{ic})}.  If the @qcode{\"ByRows\"}\n## property is true then @code{@var{A} = @var{c}(@var{ic},:)}.\n##\n## Example: small round-off errors require @code{uniquetol}, not @code{unique}\n##\n## @example\n## @group\n## x = [1:5];\n## ## Inverse_Function (Function (x)) should return exactly x\n## y = exp (log (x));\n## D = unique ([x, y])\n## @xresult{} [1   2   3   3   4   5   5]\n## C = uniquetol ([x, y])\n## @xresult{} [1   2   3   4   5]\n## @end group\n## @end example\n##\n## @seealso{unique, union, intersect, setdiff, setxor, ismember}\n## @end deftypefn\n\nfunction [c, ia, ic] = uniquetol (A, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isfloat (A) && isreal (A)))\n    error (\"Octave:uniquetol:unsupported-type\",\n           \"uniquetol: A must be a real floating point array\");\n  endif\n\n  if (nargin == 1 || ischar (varargin{1}))\n    tol = ifelse (isa (A, \"double\"), 1e-12, 1e-6);\n  else\n    tol = varargin{1};\n    varargin(1) = [];\n    if (! (isfloat (tol) && isreal (tol) && isscalar (tol)))\n      error (\"Octave:uniquetol:unsupported-type\",\n             \"uniquetol: TOL must be a real floating point scalar\");\n     endif\n  endif\n\n  if (mod (numel (varargin), 2))\n    error (\"uniquetol: PROPERTY/VALUE arguments must occur in pairs\");\n  endif\n\n  by_rows = false;\n  output_all_indices = false;\n  data_scale = [];\n  calc_indices = nargout > 1;\n\n  for k = 1:2:numel (varargin)\n    if (! ischar (varargin{k}))\n      error (\"uniquetol: PROPERTY must be a string\");\n    endif\n\n    if (strcmpi (varargin{k}, \"ByRows\"))\n      by_rows = logical (varargin{k+1});\n      if (by_rows && ndims (A) > 2)\n        error ('uniquetol: A must be a 2-D array when \"ByRows\" is true');\n      endif\n    elseif (strcmpi (varargin{k}, \"OutputAllIndices\"))\n      output_all_indices = logical (varargin{k+1}) & calc_indices;\n    elseif (strcmpi (varargin{k}, \"DataScale\"))\n      data_scale = varargin{k+1}(:).';\n      if (! isfloat (data_scale) || iscomplex (data_scale)\n          || any (data_scale(:) < 0) || any (isnan (data_scale(:))))\n        error (\"uniquetol: DataScale must be a positive floating point scalar or vector, without NaNs\");\n      endif\n      cols_data_scale = columns (data_scale);\n      if (cols_data_scale != 1 && cols_data_scale != columns (A))\n        error (\"uniquetol: invalid DataScale size\");\n      endif\n    else\n      error (\"uniquetol: unknown property '%s'\", varargin{k});\n    endif\n  endfor\n\n  if (isempty (A))\n    ## hack for Matlab empty input compatibility\n    sz_A = size (A);\n    if (by_rows)\n      c = A;\n      sz_A(2) = 1;\n      ia = ones (sz_A);\n      ic = ones (sz_A);\n    else\n      c = ones (0, 1, class (A));\n      if (sz_A(1) == 1)\n        c = c.';\n      endif\n      ia = ones (0, 1);\n      ic = ones (0, 1);\n    endif\n    return;\n  endif\n\n  if (isempty (data_scale))\n    data_scale = max (abs (A(! isinf (A))(:)));\n  endif\n\n  tol *= data_scale;\n\n  if (by_rows)\n    ## Start matrix in sorted order, retain sorting and inverting indices.\n    if (calc_indices)\n      [A, srtA] = sortrows (A);\n      [~, inv_srtA] = sort (srtA);\n    else\n      A = sortrows (A);\n    endif\n\n    [nr, nc] = size (A);\n    I = zeros (nr, 1);\n    ia = {};\n    J = zeros (nr, 1);\n    j = 1;\n\n    for i = 1:nr\n      if (J(i))\n        continue;  # row previously compared equal\n      endif\n\n      Arow_i = A(i,:);\n      eq_rows = all (abs (A - Arow_i) <= tol, 2);\n      eq_rows(i,1) = eq_rows(i,1) || any (! isfinite (Arow_i), 2);\n      if (output_all_indices)\n        ia_tmp = find (eq_rows);\n        ia{end+1,1} = sort (srtA(ia_tmp));\n      else\n        ia_tmp = find (eq_rows, 1);\n      endif\n      I(j) = ia_tmp(1);\n      J(eq_rows) = j;\n      j += 1;\n    endfor\n\n    I = I(1:j-1);\n    c = A(I,:);\n\n    if (calc_indices)\n      if (! output_all_indices)\n        ia = srtA(I(1:j-1));\n      endif\n      ic = J(inv_srtA);\n    endif\n\n  else\n    isrowvec = isrow (A);\n    A = A(:);\n    nr = rows (A);\n    isnanA = isnan (A);\n    anyisnanA = any (isnanA);\n    [sortA, sAi] = sort (A);\n    diffsortA = diff (sortA);\n    isinfsortA = isinf (sortA);\n    isnansortA = isnan (sortA);\n    numnan = sum (isnansortA);\n    if (any (isinfsortA))\n      sAnin = sortA(! (isinfsortA | isnansortA));\n      diffsortA(isinf (diffsortA)) = abs (sAnin(end) - sAnin(1)) + 10;\n    endif\n    csdx = cumsum (diffsortA);\n    ue = [true; diff([0; csdx-mod(csdx,tol)]) > eps(max(csdx))];\n    ueold = NaN;\n    while (any (ueold != ue))\n      ueold = ue;\n      belowtol = [false; diff(sortA(ue)) < tol];\n      if (any (belowtol))\n        needstomove = find (ue)(belowtol);\n        ue(needstomove) = false;\n        needstomove(needstomove >= nr-numnan) = [];\n        ue(needstomove+1) = true;\n      endif\n    endwhile\n    c = sortA(ue);\n    [~, sortsAi] = sort (sAi);\n    cumsumue = cumsum (ue);\n    ic = cumsumue(sortsAi);\n    if (anyisnanA)\n      findisnanA = find (isnanA);\n    else\n      findisnanA = [];\n    endif\n    if (output_all_indices)\n      nu = cumsumue(end);\n      ia = cell (nu, 1);\n      for k = 1:nu\n        ia{k} = setdiff (sAi(cumsumue==k), findisnanA);\n      endfor\n    else\n      ia = sAi(ue);\n    endif\n\n    if (anyisnanA)\n      rowsc1 = [1:sum(isnanA(:))]';\n      if (! all (isnanA))\n        rowsc1 += rows (c);\n      endif\n      c(rowsc1) = NaN;\n      ic(isnanA) = rowsc1;\n      if (output_all_indices)\n        ia(rowsc1) = num2cell (findisnanA);\n      else\n        ia(rowsc1) = findisnanA;\n      endif\n\n      ## if numel (c) was 1, appending NaNs creates a row vector instead of\n      ## expected column vector.\n      if (isrow (c))\n        c = c.';\n      endif\n    endif\n\n    ## Matlab compatibility: Outputs are column vectors unless the input\n    ## is a row vector, in which case the output c is also a row vector.\n    ## ia and ic are always column vectors. (verified Matlab 2022a)\n    if (isrowvec)\n      c = c.';\n    endif\n  endif\n\nendfunction\n\n\n%!assert (uniquetol ([1 1 2; 1 2 1; 1 1 2+10*eps]), [1;2])\n%!assert (uniquetol ([1 1 2; 1 0 1; 1 1 2+10*eps], \"byrows\", true),\n%!        [1 0 1; 1 1 2])\n%!assert (uniquetol ([1]), [1])\n%!assert (uniquetol ([2, 1]), [1, 2])\n%!assert (uniquetol ([1; 2]), [1; 2])\n%!assert (uniquetol ([-Inf, 1, NaN, Inf, NaN, Inf]), [-Inf, 1, Inf, NaN, NaN])\n%!assert (uniquetol ([1,2,2,3,2,4], \"byrows\", true), [1,2,2,3,2,4])\n%!assert (uniquetol ([1,2,2,3,2,4]), [1,2,3,4])\n%!assert (uniquetol ([1,2,2,3,2,4].', \"byrows\", true), [1;2;3;4])\n%!assert (uniquetol (sparse ([2,0;2,0])), sparse ([0;2]))\n%!assert (uniquetol (sparse ([1,2;2,3])), sparse ([1;2;3]))\n%!assert (uniquetol (single ([1,2,2,3,2,4]), \"byrows\", true),\n%!        single ([1,2,2,3,2,4]))\n%!assert (uniquetol (single ([1,2,2,3,2,4])), single ([1,2,3,4]))\n%!assert (uniquetol (single ([1,2,2,3,2,4].'), \"byrows\", true),\n%!        single ([1;2;3;4]))\n\n## Test 2-D array sorting\n%!test\n%! a = [magic(3); 2 * magic(3)];\n%! assert (uniquetol (a), [1:10,12,14,16,18]');\n%! assert (uniquetol (a, \"byrows\", true), sortrows (a));\n\n## Matlab compatibility of output\n%!test\n%! x = 1:0.045:3;\n%! y = uniquetol (x, 0.1, \"datascale\", 1);\n%! assert (y(1:4), [1, 1.135, 1.27, 1.405]);\n\n## Test index vector return arguments\n%!test\n%! [c, ia, ic] = uniquetol ([1,1,2,3,3,3,4]);\n%! assert (c, [1,2,3,4]);\n%! assert (ia, [1;3;4;7]);\n%! assert (ic, [1;1;2;3;3;3;4]);\n\n## Test index vector return arguments with \"ByRows\"\n%!test\n%! A = [2, 3, 4; 2, 3, 4];\n%! [c, ia, ic] = uniquetol (A, \"byrows\", true);\n%! assert (c, [2, 3, 4]);\n%! assert (ia, 1);\n%! assert (ic, [1;1]);\n\n%!test\n%! x = (2:7)'*pi;\n%! y = exp (log (x));\n%! C = uniquetol ([x; y]);\n%! assert (C, x, 1e-12);\n\n## Test \"ByRows\" Property\n%!test\n%! A = [0.06, 0.21, 0.38; 0.38, 0.21, 0.39; 0.54, 0.56, 0.41; 0.46, 0.52, 0.95];\n%! B = log (exp (A));\n%! C = uniquetol ([A; B], \"ByRows\", true);\n%! assert (C, sortrows (A), 10*eps);\n\n## Test \"DataScale\" Property\n%!test\n%! x = 10^11;\n%! C = uniquetol ([x, exp(log(x))], 1e-6, \"DataScale\", 1);\n%! assert (C, [x, exp(log(x))]);\n\n## Test \"OutputAllIndices\" Property\n%!test\n%! A = [.1 .2 .3 10];\n%! [C, ia, ic] = uniquetol (A, .1, \"OutputAllIndices\", true);\n%! assert (C, [.1, 10]);\n%! assert (ia, {(1:3)'; 4});\n%! assert (ic, [1; 1; 1; 2]);\n\n## Test NaN inputs\n%!assert (uniquetol (NaN), NaN)\n%!assert (uniquetol ([NaN NaN]), [NaN NaN])\n%!assert (uniquetol ([NaN NaN]'), [NaN NaN]')\n%!assert (uniquetol (NaN (2,2)), NaN (4,1))\n\n%!test\n%! a = [magic(3); 2 * magic(3)];\n%! a(4:5) = NaN;\n%! [c, ia, ic] = uniquetol (a);\n%! assert (c, [1:10,12,14,18, NaN, NaN]');\n%! assert (ia, [7,10,2,3,8,13,14,1,9,11,16,17,12,4,5]');\n%! assert (ic, [8,3,4,14,15,8,1,5,9,2,10,13,6,7,2,11,12,4]');\n%! [c, ia, ic] = uniquetol (single (a));\n%! assert (class (c), \"single\");\n%! assert (class (ia), \"double\");\n%! assert (class (ic), \"double\");\n%! [c, ia, ic] = uniquetol (a, \"ByRows\", true);\n%! assert (c, sortrows (a));\n%! assert (ia, [2,3,1,6,4,5]');\n%! assert (ic, [3,1,2,5,6,4]');\n%! [c, ia, ic] = uniquetol (single (a), \"ByRows\", true);\n%! assert (class (c), \"single\");\n%! assert (class (ia), \"double\");\n%! assert (class (ic), \"double\");\n%! [c, ia, ic] = uniquetol (a, \"OutputAllIndices\", true);\n%! assert (ia, {7;[10;15];2;[3;18];8;13;14;[1;6];9;11;16;17;12;4;5});\n%! [c, ia, ic] = uniquetol (single (a), \"OutputAllIndices\", true);\n%! assert (class (c), \"single\");\n%! assert (class (ia{1}), \"double\");\n%! assert (class (ic), \"double\");\n%! [c, ia, ic] = uniquetol (a, \"OutputAllIndices\", true, \"ByRows\", true);\n%! assert (ia, {2;3;1;6;4;5});\n%! [c, ia, ic] = uniquetol (single (a),\n%!                          \"OutputAllIndices\", true, \"ByRows\", true);\n%! assert (class (c), \"single\");\n%! assert (class (ia{1}), \"double\");\n%! assert (class (ic), \"double\");\n\n## Test empty input compatibility\n%!test\n%! [c, ia, ic] = uniquetol ([]);\n%! assert (c, ones (0,1));\n%! assert (ia, ones (0,1));\n%! assert (ic, ones (0,1));\n%!test\n%! [c, ia, ic] = uniquetol ([], \"byrows\", true);\n%! assert (c, []);\n%! assert (ia, ones (0,1));\n%! assert (ic, ones (0,1));\n%!test\n%! [c, ia, ic] = uniquetol (ones (0,1));\n%! assert (c, ones (0,1));\n%! assert (ia, ones (0,1));\n%! assert (ic, ones (0,1));\n%!test\n%! [c, ia, ic] = uniquetol (ones (0,1), \"byrows\", true);\n%! assert (c, ones (0,1));\n%! assert (ia, ones (0,1));\n%! assert (ic, ones (0,1));\n%!test\n%! [c, ia, ic] = uniquetol (ones (1,0));\n%! assert (c, ones (1,0));\n%! assert (ia, ones (0,1));\n%! assert (ic, ones (0,1));\n%!test\n%! [c, ia, ic] = uniquetol (ones (1,0), \"byrows\", true);\n%! assert (c, ones (1,0));\n%! assert (ia, 1);\n%! assert (ic, 1);\n%!test\n%! [c, ia, ic] = uniquetol (ones (1,0,2));\n%! assert (c, ones (1,0));\n%! assert (ia, ones (0,1));\n%! assert (ic, ones (0,1));\n%!test\n%! [c, ia, ic] = uniquetol (ones (0,1,2));\n%! assert (c, ones (0,1));\n%! assert (ia, ones (0,1));\n%! assert (ic, ones (0,1));\n%!test\n%! [c, ia, ic] = uniquetol (ones (1,2,0));\n%! assert (c, ones (1,0));\n%! assert (ia, ones (0,1));\n%! assert (ic, ones (0,1));\n%!test\n%! [c, ia, ic] = uniquetol (single ([]));\n%! assert (class (c), \"single\");\n%! assert (class (ia), \"double\");\n%! assert (class (ic), \"double\");\n%!test\n%! [c, ia, ic] = uniquetol (single ([]), \"byrows\", true);\n%! assert (class (c), \"single\");\n%! assert (class (ia), \"double\");\n%! assert (class (ic), \"double\");\n%!test\n%! [c, ia, ic] = uniquetol (single ([]), \"OutputAllIndices\", true);\n%! assert (class (c), \"single\");\n%! assert (class (ia), \"double\");\n%! assert (class (ic), \"double\");\n\n\n## Test input validation\n%!error <Invalid call> uniquetol ()\n%!error <A must be a real floating point array> uniquetol (int8 (1))\n%!error <A must be a real floating point array> uniquetol (1i)\n%!error <TOL must be a real floating point scalar> uniquetol (1, int8 (1))\n%!error <TOL must be a real floating point scalar> uniquetol (1, [1, 2])\n%!error <TOL must be a real floating point scalar> uniquetol (1, 1i)\n%!error <arguments must occur in pairs> uniquetol (1, 2, \"byrows\")\n%!error <PROPERTY must be a string> uniquetol (1, 2, 3, \"bar\")\n%!error <A must be a 2-D array> uniquetol (ones (2,2,2), \"byrows\", true)\n%!error <A must be a 2-D array> uniquetol (ones (0,1,2), \"byrows\", true)\n%!error <A must be a 2-D array> uniquetol (ones (1,0,2), \"byrows\", true)\n%!error <A must be a 2-D array> uniquetol (ones (1,2,0), \"byrows\", true)\n%!error <DataScale must be a .* floating point> uniquetol (1, \"DataScale\", '1')\n%!error <DataScale must be .* positive> uniquetol (1, \"DataScale\", 1i)\n%!error <DataScale must be .* positive> uniquetol (1, \"DataScale\", -1)\n%!error <DataScale must be .* without NaNs> uniquetol (1, \"DataScale\", NaN)\n%!error <invalid DataScale size> uniquetol (1, \"DataScale\", [1 2])\n%!error <unknown property 'foo'> uniquetol (1, \"foo\", \"bar\")\n%!error <unknown property 'foo'> uniquetol (1, 2, \"foo\", \"bar\")\n"
  },
  {
    "path": "scripts/signal/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/signal/__parse_movargs__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{args} =} __parse_movargs__ (@var{caller}, @var{varargin})\n##\n## Parse arguments for movXXX functions before passing to @code{movfun}.\n##\n## The input @var{caller} is a string with the name of the calling function\n## and is used to personalize any error messages.\n## @seealso{movfun}\n## @end deftypefn\n\nfunction args = __parse_movargs__ (caller, varargin)\n\n  args = {};\n\n  have_dim = have_nancond = false;\n  imax = numel (varargin);\n  idx = 1;\n  while (idx <= imax)\n    arg = varargin{idx};\n    if (ischar (arg))\n      if (any (strcmpi (arg, {\"omitnan\", \"includenan\", ...\n                               \"omitmissing\", \"includemissing\"})))\n        args(end+(1:2)) = {\"nancond\", arg};\n        have_nancond = true;\n      else\n        idx += 1;  # Prop/Val pair\n        if (idx > imax)\n          error ([caller \": property '%s' missing value argument\"], arg);\n        endif\n        args(end+(1:2)) = {arg, varargin{idx}};\n      endif\n    elseif (isnumeric (arg))\n      args(end+(1:2)) = {\"dim\", arg};\n      have_dim = true;\n    else\n      error (\"Octave:invalid-input-arg\",\n             [caller \": invalid input at position %d\"], idx);\n    endif\n\n    idx += 1;  # Advance to next element\n    if (have_nancond && have_dim)\n      args = [args, varargin(idx:end)];\n      break;\n    endif\n  endwhile\n\nendfunction\n\n\n%!test\n%! caller = \"tstblock\";\n%! vararg = {5};\n%! assert (__parse_movargs__ (caller, vararg{:}), {\"dim\", 5});\n%! vararg = {\"Endpoints\", \"shrink\", 3};\n%! assert (__parse_movargs__ (caller, vararg{:}),\n%!         {\"Endpoints\", \"shrink\", \"dim\", 3});\n%! vararg = {\"includenan\", 2};\n%! assert (__parse_movargs__ (caller, vararg{:}),\n%!         {\"nancond\", \"includenan\", \"dim\", 2});\n\n%!test\n%! caller = \"tstblock\";\n%! vararg = {\"INCLUDENAN\"};\n%! assert (__parse_movargs__ (caller, vararg{:}), {\"nancond\", \"INCLUDENAN\"});\n%! vararg = {\"Endpoints\", \"fill\", \"OMITNAN\"};\n%! assert (__parse_movargs__ (caller, vararg{:}),\n%!         {\"Endpoints\", \"fill\", \"nancond\", \"OMITNAN\"});\n%! vararg = {2, \"includenan\"};\n%! assert (__parse_movargs__ (caller, vararg{:}),\n%!         {\"dim\", 2, \"nancond\", \"includenan\"});\n\n%!test\n%! caller = \"tstblock\";\n%! vararg = {};\n%! assert (__parse_movargs__ (caller, vararg{:}), {});\n%! vararg = {\"Endpoints\", \"fill\"};\n%! assert (__parse_movargs__ (caller, vararg{:}), {\"Endpoints\", \"fill\"});\n%! vararg = {5, \"omitnan\", \"Endpoints\", \"fill\"};\n%! assert (__parse_movargs__ (caller, vararg{:}),\n%!         {\"dim\", 5, \"nancond\", \"omitnan\", \"Endpoints\", \"fill\"});\n\n%!test <*66156>\n%! caller = \"tstblock\";\n%! vararg = {\"omitmissing\"};\n%! assert (__parse_movargs__ (caller, vararg{:}), {\"nancond\", \"omitmissing\"});\n%! vararg = {\"includemissing\"};\n%! assert (__parse_movargs__ (caller, vararg{:}), {\"nancond\", \"includemissing\"});\n\n\n"
  },
  {
    "path": "scripts/signal/arch_fit.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{a}, @var{b}] =} arch_fit (@var{y}, @var{x}, @var{p}, @var{iter}, @var{gamma}, @var{a0}, @var{b0})\n## Fit an ARCH regression model to the time series @var{y} using the scoring\n## algorithm in @nospell{Engle's} original ARCH paper.\n##\n## The model is\n##\n## @example\n## @group\n## y(t) = b(1) * x(t,1) + @dots{} + b(k) * x(t,k) + e(t),\n## h(t) = a(1) + a(2) * e(t-1)^2 + @dots{} + a(p+1) * e(t-p)^2\n## @end group\n## @end example\n##\n## @noindent\n## in which @math{e(t)} is @math{N(0, h(t))}, given a time-series vector\n## @var{y} up to time @math{t-1} and a matrix of (ordinary) regressors @var{x}\n## up to @math{t}.  The order of the regression of the residual variance is\n## specified by @var{p}.\n##\n## If invoked as @code{arch_fit (@var{y}, @var{k}, @var{p})} with a positive\n## integer @var{k}, fit an ARCH(@var{k}, @var{p}) process, i.e., do the above\n## with the @math{t}-th row of @var{x} given by\n##\n## @example\n## [1, y(t-1), @dots{}, y(t-k)]\n## @end example\n##\n## Optionally, one can specify the number of iterations @var{iter}, the\n## updating factor @var{gamma}, and initial values @math{a0} and @math{b0}\n## for the scoring algorithm.\n## @end deftypefn\n\nfunction [a, b] = arch_fit (y, x, p, iter, gamma, a0, b0)\n\n  if (nargin < 3 || nargin == 6)\n    print_usage ();\n  endif\n\n  if (! (isvector (y)))\n    error (\"arch_fit: Y must be a vector\");\n  endif\n\n  T = length (y);\n  y = reshape (y, T, 1);\n  [rx, cx] = size (x);\n  if ((rx == 1) && (cx == 1))\n    x = autoreg_matrix (y, x);\n  elseif (! (rx == T))\n    error (\"arch_fit: either rows (X) == length (Y), or X is a scalar\");\n  endif\n\n  [T, k] = size (x);\n\n  if (nargin == 7)\n    a = a0;\n    b = b0;\n    e = y - x * b;\n  else\n    [b, v_b, e] = ols (y, x);\n    a = [v_b, (zeros (1, p))]';\n    if (nargin < 5)\n      gamma = 0.1;\n      if (nargin < 4)\n        iter = 50;\n      endif\n    endif\n  endif\n\n  esq = e.^2;\n  Z = autoreg_matrix (esq, p);\n\n  for i = 1 : iter\n    h   = Z * a;\n    tmp = esq ./ h.^2 - 1 ./ h;\n    s   = 1 ./ h(1:T-p);\n    for j = 1 : p\n      s -= a(j+1) * tmp(j+1:T-p+j);\n    endfor\n    r = 1 ./ h(1:T-p);\n    for j = 1:p\n      r += 2 * h(j+1:T-p+j).^2 .* esq(1:T-p);\n    endfor\n    r = sqrt (r);\n    X_tilde = x(1:T-p, :) .* (r * ones (1,k));\n    e_tilde = e(1:T-p) .*s ./ r;\n    delta_b = inv (X_tilde' * X_tilde) * X_tilde' * e_tilde;\n    b  += gamma * delta_b;\n    e   = y - x * b;\n    esq = e .^ 2;\n    Z   = autoreg_matrix (esq, p);\n    h   = Z * a;\n    f   = esq ./ h - ones (T,1);\n    Z_tilde = Z ./ (h * ones (1, p+1));\n    delta_a = inv (Z_tilde' * Z_tilde) * Z_tilde' * f;\n    a += gamma * delta_a;\n  endfor\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/arch_rnd.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} arch_rnd (@var{a}, @var{b}, @var{t})\n## Simulate an ARCH sequence of length @var{t} with AR coefficients @var{b} and\n## CH coefficients @var{a}.\n##\n## The result @math{y(t)} follows the model\n## @c Set example in small font to prevent overfull line\n##\n## @smallexample\n## y(t) = b(1) + b(2) * y(t-1) + @dots{} + b(lb) * y(t-lb+1) + e(t),\n## @end smallexample\n##\n## @noindent\n## where @math{e(t)}, given @var{y} up to time @math{t-1}, is\n## @math{N(0, h(t))}, with\n## @c Set example in small font to prevent overfull line\n##\n## @smallexample\n## h(t) = a(1) + a(2) * e(t-1)^2 + @dots{} + a(la) * e(t-la+1)^2\n## @end smallexample\n## @end deftypefn\n\nfunction y = arch_rnd (a, b, t)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (! ((min (size (a)) == 1) && (min (size (b)) == 1)))\n    error (\"arch_rnd: A and B must both be scalars or vectors\");\n  endif\n  if (! (isscalar (t) && (t > 0) && (rem (t, 1) == 0)))\n    error (\"arch_rnd: T must be a positive integer\");\n  endif\n\n  if (! (a(1) > 0))\n    error (\"arch_rnd: A(1) must be positive\");\n  endif\n  ## perhaps add a test for the roots of a(z) here ...\n\n  la = length (a);\n  a  = reshape (a, 1, la);\n  if (la == 1)\n    a  = [a, 0];\n    la += 1;\n  endif\n\n  lb = length (b);\n  b  = reshape (b, 1, lb);\n  if (lb == 1)\n    b  = [b, 0];\n    lb += 1;\n  endif\n  m = max ([la, lb]);\n\n  e = zeros (t, 1);\n  h = zeros (t, 1);\n  y = zeros (t, 1);\n\n  h(1) = a(1);\n  e(1) = sqrt (h(1)) * randn ();\n  y(1) = b(1) + e(1);\n\n  for t = 2:m\n    ta   = min ([t, la]);\n    h(t) = a(1) + a(2:ta) * e(t-ta+1:t-1).^2;\n    e(t) = sqrt (h(t)) * randn ();\n    tb   = min ([t, lb]);\n    y(t) = b(1) + b(2:tb) * y(t-tb+1:t-1) + e(t);\n  endfor\n\n  if (t > m)\n    for t = m+1:t\n      h(t) = a(1) + a(2:la) * e(t-la+1:t-1).^2;\n      e(t) = sqrt (h(t)) * randn ();\n      y(t) = b(1) + b(2:lb) * y(t-tb+1:t-1) + e(t);\n    endfor\n  endif\n\n  y = y(1:t);\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/arch_test.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{pval}, @var{lm}] =} arch_test (@var{y}, @var{x}, @var{p})\n## For a linear regression model\n##\n## @example\n## y = x * b + e\n## @end example\n##\n## @noindent\n## perform a Lagrange Multiplier (LM) test of the null hypothesis of no\n## conditional heteroscedascity against the alternative of CH(@var{p}).\n##\n## I.e., the model is\n##\n## @example\n## y(t) = b(1) * x(t,1) + @dots{} + b(k) * x(t,k) + e(t),\n## @end example\n##\n## @noindent\n## given @var{y} up to @math{t-1} and @var{x} up to @math{t},\n## @math{e}(t) is @math{N(0, h(t))} with\n##\n## @example\n## h(t) = v + a(1) * e(t-1)^2 + @dots{} + a(p) * e(t-p)^2,\n## @end example\n##\n## @noindent\n## and the null is @math{a(1)} == @dots{} == @math{a(p)} == 0.\n##\n## If the second argument is a scalar integer, @math{k}, perform the same\n## test in a linear autoregression model of order @math{k}, i.e., with\n##\n## @example\n## [1, y(t-1), @dots{}, y(t-@var{k})]\n## @end example\n##\n## @noindent\n## as the @math{t}-th row of @var{x}.\n##\n## Under the null, LM approximately has a chisquare distribution with\n## @var{p} degrees of freedom and @var{pval} is the @math{p}-value (1\n## minus the CDF of this distribution at LM) of the test.\n##\n## If no output argument is given, the @math{p}-value is displayed.\n## @end deftypefn\n\n## Description: Test for conditional heteroscedascity.\n\nfunction [pval, lm] = arch_test (y, x, p)\n\n  if (nargin != 3)\n    error (\"arch_test: 3 input arguments required\");\n  endif\n\n  if (! (isvector (y)))\n    error (\"arch_test: Y must be a vector\");\n  endif\n  T = length (y);\n  y = reshape (y, T, 1);\n  [rx, cx] = size (x);\n  if ((rx == 1) && (cx == 1))\n    x = autoreg_matrix (y, x);\n  elseif (! (rx == T))\n    error (\"arch_test: either rows (X) == length (Y), or X is a scalar\");\n  endif\n  if (! (isscalar (p) && (rem (p, 1) == 0) && (p > 0)))\n    error (\"arch_test: P must be a positive integer\");\n  endif\n\n  [b, v_b, e] = ols (y, x);\n  Z    = autoreg_matrix (e.^2, p);\n  f    = e.^2 / v_b - ones (T, 1);\n  f    = Z' * f;\n  lm   = f' * inv (Z'*Z) * f / 2;\n  pval = 1 - chi2cdf (lm, p);\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/arma_rnd.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{x} =} arma_rnd (@var{a}, @var{b}, @var{v}, @var{t}, @var{n})\n## Return a simulation of the ARMA model.\n##\n## The ARMA model is defined by\n##\n## @example\n## @group\n## x(n) = a(1) * x(n-1) + @dots{} + a(k) * x(n-k)\n##      + e(n) + b(1) * e(n-1) + @dots{} + b(l) * e(n-l)\n## @end group\n## @end example\n##\n## @noindent\n## in which @var{k} is the length of vector @var{a}, @var{l} is the length of\n## vector @var{b} and @var{e} is Gaussian white noise with variance @var{v}.\n## The function returns a vector of length @var{t}.\n##\n## The optional parameter @var{n} gives the number of dummy @var{x}(@var{i})\n## used for initialization, i.e., a sequence of length @var{t}+@var{n} is\n## generated and @var{x}(@var{n}+1:@var{t}+@var{n}) is returned.  If @var{n}\n## is omitted, @var{n} = 100 is used.\n## @end deftypefn\n\nfunction x = arma_rnd (a, b, v, t, n = 100)\n\n  if (nargin < 4)\n    print_usage ();\n  endif\n\n  if ((min (size (a)) > 1) || (min (size (b)) > 1))\n    error (\"arma_rnd: A and B must not be matrices\");\n  endif\n\n  if (! isscalar (t))\n    error (\"arma_rnd: T must be a scalar\");\n  endif\n\n  if (! isscalar (n))\n    error (\"arma_rnd: N must be a scalar\");\n  endif\n\n  ar = length (a);\n  br = length (b);\n\n  a = reshape (a, ar, 1);\n  b = reshape (b, br, 1);\n\n  ## Apply our notational convention.\n  a = [1; -a];\n  b = [1; b];\n\n  n = min (n, ar + br);\n\n  e = sqrt (v) * randn (t + n, 1);\n\n  x = filter (b, a, e);\n  x = x(n + 1 : t + n);\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/autoreg_matrix.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{x} =} autoreg_matrix (@var{y}, @var{k})\n## Given a time series (vector) @var{y}, return a matrix with ones in the first\n## column and the first @var{k} lagged values of @var{y} in the other columns.\n##\n## In other words, for @var{t} > @var{k},\n## @code{[1, @var{y}(@var{t}-1), @dots{}, @var{y}(@var{t}-@var{k})]} is the\n## t-th row of the result.\n##\n## The resulting matrix may be used as a regressor matrix in autoregressions.\n## @end deftypefn\n\nfunction x = autoreg_matrix (y, k)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! (isvector (y)))\n    error (\"autoreg_matrix: Y must be a vector\");\n  endif\n\n  T = length (y);\n  y = reshape (y, T, 1);\n  x = ones (T, k+1);\n  for j = 1 : k\n    x(:, j+1) = [(zeros (j, 1)); y(1:T-j)];\n  endfor\n\nendfunction\n\n\n%!test\n%! K = 4;\n%! A = zeros (1,K+1);\n%! A(1) = 1;\n%! B = eye (K+1);\n%! B(:,1) = 1;\n%! assert (autoreg_matrix (A,K), B);\n\n%!error <Invalid call> autoreg_matrix ()\n%!error <Invalid call> autoreg_matrix (1)\n%!error autoreg_matrix (ones (4,1), 5)\n"
  },
  {
    "path": "scripts/signal/bartlett.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{c} =} bartlett (@var{m})\n## Return the filter coefficients of a Bartlett (triangular) window of length\n## @var{m}.\n##\n## For a definition of the Bartlett window see, e.g.,\n## @nospell{A.V. Oppenheim & R. W. Schafer},\n## @cite{Discrete-Time Signal Processing}.\n## @end deftypefn\n\nfunction c = bartlett (m)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (m) && m > 0 && m == fix (m)))\n    error (\"bartlett: M must be a positive integer\");\n  endif\n\n  if (m == 1)\n    c = 1;\n  else\n    m -= 1;\n    n = fix (m / 2);\n    c = [2*(0:n)/m, 2-2*(n+1:m)/m]';\n  endif\n\nendfunction\n\n\n%!assert (bartlett (1), 1)\n%!assert (bartlett (2), zeros (2,1))\n%!assert (bartlett (15), flip (bartlett (15)), 5*eps)\n%!assert (bartlett (16), flip (bartlett (16)), 5*eps)\n%!test\n%! N = 9;\n%! A = bartlett (N);\n%! assert (A(ceil (N/2)), 1);\n\n%!error <Invalid call> bartlett ()\n%!error bartlett (0.5)\n%!error bartlett (-1)\n%!error bartlett (ones (1,4))\n"
  },
  {
    "path": "scripts/signal/blackman.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} blackman (@var{m})\n## @deftypefnx {} {@var{c} =} blackman (@var{m}, \"periodic\")\n## @deftypefnx {} {@var{c} =} blackman (@var{m}, \"symmetric\")\n## Return the filter coefficients of a @nospell{Blackman} window of length\n## @var{m}.\n##\n## If the optional argument @qcode{\"periodic\"} is given, the periodic form\n## of the window is returned.  This is equivalent to the window of length\n## @var{m}+1 with the last coefficient removed.  The optional argument\n## @qcode{\"symmetric\"} is equivalent to not specifying a second argument.\n##\n## For a definition of the @nospell{Blackman} window, see, e.g.,\n## @nospell{A.V. Oppenheim & R. W. Schafer},\n## @cite{Discrete-Time Signal Processing}.\n## @end deftypefn\n\nfunction c = blackman (m, opt)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (m) && m > 0 && m == fix (m)))\n    error (\"blackman: M must be a positive integer\");\n  endif\n\n  N = m - 1;\n  if (nargin == 2)\n    switch (opt)\n      case \"periodic\"\n        N = m;\n      case \"symmetric\"\n        ## Default option, same as no option specified.\n      otherwise\n        error ('blackman: window type must be either \"periodic\" or \"symmetric\"');\n    endswitch\n  endif\n\n  if (m == 1)\n    c = 1;\n  else\n    m -= 1;\n    k = (0 : m)' / N;\n    c = 0.42 - 0.5 * cos (2 * pi * k) + 0.08 * cos (4 * pi * k);\n  endif\n\nendfunction\n\n\n%!assert (blackman (1), 1)\n%!assert (blackman (2), zeros (2,1), 1e-6)\n%!assert (blackman (15), flip (blackman (15)), 5*eps)\n%!assert (blackman (16), flip (blackman (16)), 5*eps)\n%!test\n%! N = 9;\n%! A = blackman (N);\n%! assert (A(ceil (N/2)), 1, 1e-6);\n%! assert ([A(1), A(length (A))], zeros (1,2), 1e-6);\n\n%!assert (blackman (15), blackman (15, \"symmetric\"))\n%!assert (blackman (16)(1:15), blackman (15, \"periodic\"))\n%!test\n%! N = 16;\n%! A = blackman (N, \"periodic\");\n%! assert (A(N/2 + 1), 1, 1e-6);\n\n%!error <Invalid call> blackman ()\n%!error blackman (0.5)\n%!error blackman (-1)\n%!error blackman (ones (1,4))\n%!error blackman (1, \"invalid\")\n"
  },
  {
    "path": "scripts/signal/detrend.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} detrend (@var{x}, @var{p})\n## If @var{x} is a vector, @code{detrend (@var{x}, @var{p})} removes the\n## best fit of a polynomial of order @var{p} from the data @var{x}.\n##\n## If @var{x} is a matrix, @code{detrend (@var{x}, @var{p})} does the same\n## for each column in @var{x}.\n##\n## The second argument @var{p} is optional.  If it is not specified, a value of\n## 1 is assumed.  This corresponds to removing a linear trend.\n##\n## The order of the polynomial can also be given as a string, in which case\n## @var{p} must be either @qcode{\"constant\"} (corresponds to @code{@var{p}=0})\n## or @qcode{\"linear\"} (corresponds to @code{@var{p}=1}).\n## @seealso{polyfit}\n## @end deftypefn\n\nfunction y = detrend (x, p = 1)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x) || ndims (x) > 2)\n    error (\"detrend: X must be a numeric vector or matrix\");\n  endif\n\n  if (ischar (p) && strcmpi (p, \"constant\"))\n    p = 0;\n  elseif (ischar (p) && strcmpi (p, \"linear\"))\n    p = 1;\n  elseif (! isscalar (p) || p < 0 || p != fix (p))\n    error ('detrend: P must be \"constant\", \"linear\", or a positive integer');\n  endif\n\n  [m, n] = size (x);\n  if (m == 1)\n    x = x.';\n  endif\n\n  r = rows (x);\n  b = ((1 : r).' * ones (1, p + 1)) .^ (ones (r, 1) * (0 : p));\n  y = x - b * (b \\ x);\n\n  if (m == 1)\n    y = y.';\n  endif\n\nendfunction\n\n\n%!test\n%! N = 32;\n%! x = (0:1:N-1)/N + 2;\n%! y = detrend (x);\n%! assert (abs (y(:)) < 20*eps);\n\n%!test\n%! N = 32;\n%! t = (0:1:N-1)/N;\n%! x = t .* t + 2;\n%! y = detrend (x,2);\n%! assert (abs (y(:)) < 30*eps);\n\n%!test\n%! N = 32;\n%! t = (0:1:N-1)/N;\n%! x = [t;4*t-3].';\n%! y = detrend (x);\n%! assert (abs (y(:)) < 20*eps);\n\n%!test\n%! N = 32;\n%! x = ((0:1:N-1)/N + 2) * 1i;\n%! y = detrend (x);\n%! assert (abs (y(:)) < 20*eps);\n\n## Test input validation\n%!error <Invalid call> detrend ()\n%!error detrend (\"a\")\n%!error detrend (true)\n%!error detrend (1, \"invalid\")\n%!error detrend (1, -1)\n%!error detrend (1, 1.25)\n"
  },
  {
    "path": "scripts/signal/diffpara.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{d}, @var{dd}] =} diffpara (@var{x}, @var{a}, @var{b})\n## Return the estimator @var{d} for the differencing parameter of an\n## integrated time series.\n##\n## The frequencies from @math{[2*pi*a/t, 2*pi*b/T]} are used for the\n## estimation.  If @var{b} is omitted, the interval\n## @math{[2*pi/T, 2*pi*a/T]} is used.  If both @var{b} and @var{a} are omitted\n## then @math{a = 0.5 * sqrt (T)} and @math{b = 1.5 * sqrt (T)} is used, where\n## @math{T} is the sample size.  If @var{x} is a matrix, the differencing\n## parameter of each column is estimated.\n##\n## The estimators for all frequencies in the intervals described above is\n## returned in @var{dd}.\n##\n## The value of @var{d} is simply the mean of @var{dd}.\n##\n## Reference: @nospell{P.J. Brockwell & R.A. Davis}, @cite{Time Series:\n## Theory and Methods}, @nospell{Springer}, 1987.\n## @end deftypefn\n\nfunction [d, dd] = diffpara (x, a, b)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (isvector (x))\n    n = length (x);\n    k = 1;\n    x = reshape (x, n, 1);\n  else\n    [n, k] = size (x);\n  endif\n  if (nargin == 1)\n    a = 0.5 * sqrt (n);\n    b = 1.5 * sqrt (n);\n  elseif (nargin == 2)\n    b = a;\n    a = 1;\n  endif\n\n  if (! (isscalar (a) && isscalar (b)))\n    error (\"diffpara: A and B must be scalars\");\n  endif\n\n  dd = zeros (b - a + 1, k);\n\n  for l = 1:k\n\n    w = 2 * pi * (1 : n-1) / n;\n\n    x = 2 * log (abs (1 - exp (-i*w)));\n    y = log (periodogram (x(2:n,l)));\n\n    x = center (x);\n    y = center (y);\n\n    for m = a:b\n      dd(m-a+1) = - x(1:m) * y(1:m) / sumsq (x(1:m));\n    endfor\n\n  endfor\n\n  d = mean (dd);\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/durbinlevinson.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{newphi}, @var{newv}] =} durbinlevinson (@var{c}, @var{oldphi}, @var{oldv})\n## Perform one step of the @nospell{Durbin-Levinson} algorithm.\n##\n## The vector @var{c} specifies the autocovariances\n## @code{[gamma_0, @dots{}, gamma_t]} from lag 0 to @var{t}, @var{oldphi}\n## specifies the coefficients based on @var{c}(@var{t}-1) and @var{oldv}\n## specifies the corresponding error.\n##\n## If @var{oldphi} and @var{oldv} are omitted, all steps from 1 to @var{t} of\n## the algorithm are performed.\n## @end deftypefn\n\nfunction [newphi, newv] = durbinlevinson (c, oldphi, oldv)\n\n  if (nargin != 1 && nargin != 3)\n    print_usage ();\n  endif\n\n  if (columns (c) > 1)\n    c = c';\n  endif\n\n  newphi = 0;\n  newv = 0;\n\n  if (nargin == 3)\n\n    t = length (oldphi) + 1;\n\n    if (length (c) < t+1)\n      error (\"durbinlevinson: C too small\");\n    endif\n\n    if (oldv == 0)\n      error (\"durbinlevinson: OLDV = 0\");\n    endif\n\n    if (rows (oldphi) > 1)\n      oldphi = oldphi';\n    endif\n\n    newphi = zeros (1, t);\n    newphi(1) = (c(t+1) - oldphi * c(2:t)) / oldv;\n    for i = 2 : t\n      newphi(i) = oldphi(i-1) - newphi(1) * oldphi(t-i+1);\n    endfor\n    newv = (1 - newphi(1)^2) * oldv;\n\n  elseif (nargin == 1)\n\n    tt = length (c)-1;\n    oldphi = c(2) / c(1);\n    oldv = (1 - oldphi^2) * c(1);\n\n    for t = 2 : tt\n\n      newphi = zeros (1, t);\n      newphi(1) = (c(t+1) - oldphi * c(2:t)) / oldv;\n      for i = 2 : t\n        newphi(i) = oldphi(i-1) - newphi(1) * oldphi(t-i+1);\n      endfor\n      newv = (1 - newphi(1)^2) * oldv;\n\n      oldv = newv;\n      oldphi = newphi;\n\n    endfor\n\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/fftconv.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} fftconv (@var{x}, @var{y})\n## @deftypefnx {} {@var{c} =} fftconv (@var{x}, @var{y}, @var{n})\n## Convolve two vectors using the FFT for computation.\n##\n## @code{c = fftconv (@var{x}, @var{y})} returns a vector of length equal to\n## @code{length (@var{x}) + length (@var{y}) - 1}.  If @var{x} and @var{y}\n## are the coefficient vectors of two polynomials, the returned value is the\n## coefficient vector of the product polynomial.\n##\n## The computation uses the FFT by calling the function @code{fftfilt}.  If\n## the optional argument @var{n} is specified, an N-point FFT is used.\n## @seealso{deconv, conv, conv2}\n## @end deftypefn\n\nfunction c = fftconv (x, y, n)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (isvector (x) && isvector (y)))\n    error (\"fftconv: both A and B must be vectors\");\n  endif\n  la = length (x);\n  lb = length (y);\n  if ((la == 1) || (lb == 1))\n    c = x * y;\n  else\n    lc = la + lb - 1;\n    x(lc) = 0;\n    y(lc) = 0;\n    if (nargin == 2)\n      c = fftfilt (x, y);\n    else\n      if (! isscalar (n))\n        error (\"fftconv: N must be a scalar\");\n      endif\n      c = fftfilt (x, y, n);\n    endif\n  endif\n\nendfunction\n\n\n## FIXME: Borrow tests from conv.m.  May need tolerance on the assert stmt.\n%!testif HAVE_FFTW\n%! x = ones (3,1);\n%! y = ones (1,3);\n%! b = 2;\n%! c = 3;\n%! assert (fftconv (x, x), [1; 2; 3; 2; 1], 5*eps);\n%! assert (fftconv (y, y), [1, 2, 3, 2, 1], 5*eps);\n%! assert (fftconv (x, y), [1, 2, 3, 2, 1], 5*eps);\n%! assert (fftconv (y, x), [1; 2; 3; 2; 1], 5*eps);\n%! assert (fftconv (c, x), [3; 3; 3], 5*eps);\n%! assert (fftconv (c, y), [3, 3, 3], 5*eps);\n%! assert (fftconv (x, c), [3; 3; 3], 5*eps);\n%! assert (fftconv (y, c), [3, 3, 3], 5*eps);\n%! assert (fftconv (b, c), 6, 5*eps);\n\n%!test\n%! a = 1:10;\n%! b = 1:3;\n%! assert (size (conv (a,b)), [1, numel(a)+numel(b)-1]);\n%! assert (size (conv (b,a)), [1, numel(a)+numel(b)-1]);\n\n%! a = (1:10).';\n%! b = 1:3;\n%! assert (size (conv (a,b)), [numel(a)+numel(b)-1, 1]);\n%! assert (size (conv (b,a)), [numel(a)+numel(b)-1, 1]);\n\n%!test\n%! a = 1:10;\n%! b = (1:3).';\n%! assert (size (conv (a,b)), [1, numel(a)+numel(b)-1]);\n%! assert (size (conv (b,a)), [1, numel(a)+numel(b)-1]);\n\n## Test input validation\n%!error <Invalid call> fftconv (1)\n%!error fftconv ([1, 2; 3, 4], 3)\n%!error fftconv (2, [])\n%!error fftconv ([1,1], [2,2] , [3, 4])\n"
  },
  {
    "path": "scripts/signal/fftfilt.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} fftfilt (@var{b}, @var{x})\n## @deftypefnx {} {@var{y} =} fftfilt (@var{b}, @var{x}, @var{n})\n## Filter @var{x} with the FIR filter @var{b} using the FFT.\n##\n## If @var{x} is a matrix, filter each column of the matrix.\n##\n## Given the optional third argument, @var{n}, @code{fftfilt} uses the\n## overlap-add method to filter @var{x} with @var{b} using an N-point FFT@.\n## The FFT size must be an even power of 2 and must be greater than or equal to\n## the length of @var{b}.  If the specified @var{n} does not meet these\n## criteria, it is automatically adjusted to the nearest value that does.\n##\n## @seealso{filter, filter2}\n## @end deftypefn\n\nfunction y = fftfilt (b, x, n)\n\n  ## If N is not specified explicitly, we do not use the overlap-add\n  ## method at all because loops are really slow.  Otherwise, we only\n  ## ensure that the number of points in the FFT is the smallest power\n  ## of two larger than N and length(b).  This could result in length\n  ## one blocks, but if the user knows better ...\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  transpose = (rows (x) == 1);\n\n  if (transpose)\n    x = x.';\n  endif\n\n  [r_x, c_x] = size (x);\n  [r_b, c_b] = size (b);\n\n  if (! isvector (b))\n    error (\"fftfilt: B must be a vector\");\n  endif\n\n  if (ndims (x) != 2)\n    error (\"fftfilt: X must be a 1-D or 2-D array\");\n  endif\n\n  l_b = r_b * c_b;\n  b = reshape (b, l_b, 1);\n\n  if (nargin == 2)\n    ## Use FFT with the smallest power of 2 which is >= length (x) +\n    ## length (b) - 1 as number of points ...\n    n = 2 ^ nextpow2 (r_x + l_b - 1);\n    B = fft (b, n);\n    y = ifft (fft (x, n) .* B(:, ones (1, c_x)));\n  else\n    ## Use overlap-add method ...\n    if (! (isscalar (n)))\n      error (\"fftfilt: N has to be a scalar\");\n    endif\n    n = 2 ^ nextpow2 (max ([n, l_b]));\n    L = n - l_b + 1;\n    B = fft (b, n);\n    B = B(:, ones (c_x,1));\n    R = ceil (r_x / L);\n    y = zeros (r_x, c_x);\n    for r = 1:R\n      lo = (r - 1) * L + 1;\n      hi = min (r * L, r_x);\n      tmp = zeros (n, c_x);\n      tmp(1:(hi-lo+1),:) = x(lo:hi,:);\n      tmp = ifft (fft (tmp) .* B);\n      hi  = min (lo+n-1, r_x);\n      y(lo:hi,:) = y(lo:hi,:) + tmp(1:(hi-lo+1),:);\n    endfor\n  endif\n\n  y = y(1:r_x, :);\n\n  ## Final cleanups:\n\n  ## - If both b and x are real, y should be real.\n  ## - If b is real and x is imaginary, y should be imaginary.\n  ## - If b is imaginary and x is real, y should be imaginary.\n  ## - If both b and x are imaginary, y should be real.\n  xisreal = all (imag (x) == 0);\n  xisimag = all (real (x) == 0);\n\n  if (all (imag (b) == 0))\n    y (:,xisreal) = real (y (:,xisreal));\n    y (:,xisimag) = complex (real (y (:,xisimag)) * 0, imag (y (:,xisimag)));\n  elseif (all (real (b) == 0))\n    y (:,xisreal) = complex (real (y (:,xisreal)) * 0, imag (y (:,xisreal)));\n    y (:,xisimag) = real (y (:,xisimag));\n  endif\n\n  ## - If both x and b are integer in both real and imaginary\n  ##   components, y should be integer.\n  if (! any (b - fix (b)))\n    idx = find (! any (x - fix (x)));\n    y (:, idx) = round (y (:, idx));\n  endif\n\n  ## Transpose after cleanup, otherwise rounding fails.\n  if (transpose)\n    y = y.';\n  endif\n\nendfunction\n\n\n%!shared b, x, r\n\n%!testif HAVE_FFTW\n%! b = [1 1];\n%! x = [1, zeros(1,9)];\n%! assert (fftfilt (b,  x  ), [1 1 0 0 0 0 0 0 0 0]  );\n%! assert (fftfilt (b,  x.'), [1 1 0 0 0 0 0 0 0 0].');\n%! assert (fftfilt (b.',x  ), [1 1 0 0 0 0 0 0 0 0]  );\n%! assert (fftfilt (b.',x.'), [1 1 0 0 0 0 0 0 0 0].');\n%! assert (fftfilt (b,  [x.' x.']), [1 1 0 0 0 0 0 0 0 0].'*[1 1]);\n%! assert (fftfilt (b,  [x.'+2*eps x.']) == [1 1 0 0 0 0 0 0 0 0].'*[1 1],\n%!         [false(10, 1) true(10, 1)]);\n\n%!testif HAVE_FFTW\n%! r = sqrt (1/2) * (1+i);\n%! b = b*r;\n%! assert (fftfilt (b, x  ), r*[1 1 0 0 0 0 0 0 0 0]  , eps  );\n%! assert (fftfilt (b, r*x), r*r*[1 1 0 0 0 0 0 0 0 0], 2*eps);\n%! assert (fftfilt (b, x.'), r*[1 1 0 0 0 0 0 0 0 0].', eps  );\n\n%!testif HAVE_FFTW\n%! b  = [1 1];\n%! x  = zeros (10,3); x(1,1)=-1; x(1,2)=1;\n%! y0 = zeros (10,3); y0(1:2,1)=-1; y0(1:2,2)=1;\n%! y  = fftfilt (b, x);\n%! assert (y0, y);\n%! y  = fftfilt (b*i, x);\n%! assert (y0*i, y);\n%! y  = fftfilt (b, x*i);\n%! assert (y0*i, y);\n%! y  = fftfilt (b*i, x*i);\n%! assert (-y0, y);\n%! x  = rand (10, 1);\n%! y  = fftfilt (b, [x x*i]);\n%! assert (true, isreal (y(:,1)));\n%! assert (false, any (real (y(:,2))));\n\n%!testif HAVE_FFTW\n%! b  = rand (10, 1);\n%! x  = rand (10, 1);\n%! y0 = filter (b, 1, x);\n%! y  = fftfilt (b, x);\n%! assert (y0, y, 16*eps);\n%! y0 = filter (b*i, 1, x*i);\n%! y  = fftfilt (b*i, x*i);\n%! assert (y0, y, 16*eps);\n\n%!testif HAVE_FFTW\n%! b  = rand (10, 1) + i*rand (10, 1);\n%! x  = rand (10, 1) + i*rand (10, 1);\n%! y0 = filter (b, 1, x);\n%! y  = fftfilt (b, x);\n%! assert (y0, y, 55*eps);\n\n## Test input validation\n%!error <Invalid call> fftfilt (1)\n%!error fftfilt (ones (2), 1)\n%!error fftfilt (2, ones (3,3,3))\n%!error fftfilt (2, 1, ones (2))\n"
  },
  {
    "path": "scripts/signal/fftshift.m",
    "content": "########################################################################\n##\n## Copyright (C) 1997-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} fftshift (@var{x})\n## @deftypefnx {} {@var{y} =} fftshift (@var{x}, @var{dim})\n## Perform a shift of the vector @var{x}, for use with the @code{fft} and\n## @code{ifft} functions, in order to move the frequency 0 to the center of\n## the vector or matrix.\n##\n## If @var{x} is a vector of @math{N} elements corresponding to @math{N} time\n## samples spaced by @nospell{@math{dt}}, then\n## @code{fftshift (fft (@var{x}))} corresponds to frequencies\n##\n## @example\n## f = [ -(ceil((N-1)/2):-1:1), 0, (1:floor((N-1)/2)) ] * df\n## @end example\n##\n## @noindent\n## where @nospell{@math{df = 1 / (N * dt)}}.\n##\n## If @var{x} is a matrix, the same holds for rows and columns.  If @var{x}\n## is an array, then the same holds along each dimension.\n##\n## The optional @var{dim} argument can be used to limit the dimension along\n## which the permutation occurs.\n## @seealso{ifftshift}\n## @end deftypefn\n\nfunction y = fftshift (x, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x) || ischar (x)))\n    error (\"fftshift: X must be a vector or matrix\");\n  endif\n\n  if (nargin == 2)\n    if (! (isscalar (dim) && dim > 0 && dim == fix (dim)))\n      error (\"fftshift: dimension DIM must be a positive integer\");\n    endif\n    nd = ndims (x);\n    sz = size (x);\n    sz2 = ceil (sz(dim) / 2);\n    idx = cell ();\n    idx = repmat ({':'}, nd, 1);\n    idx{dim} = [sz2+1:sz(dim), 1:sz2];\n    y = x(idx{:});\n  else\n    if (isvector (x))\n      xl = length (x);\n      xx = ceil (xl/2);\n      y = x([xx+1:xl, 1:xx]);\n    else\n      nd = ndims (x);\n      sz = size (x);\n      sz2 = ceil (sz ./ 2);\n      idx = cell ();\n      for i = 1:nd\n        idx{i} = [sz2(i)+1:sz(i), 1:sz2(i)];\n      endfor\n      y = x(idx{:});\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! x = [0:7];\n%! y = fftshift (x);\n%! assert (y, [4 5 6 7 0 1 2 3]);\n%! assert (fftshift (y), x);\n\n%!test\n%! x = [0:6];\n%! y = fftshift (x);\n%! assert (y, [4 5 6 0 1 2 3]);\n%! assert (fftshift (y), [1 2 3 4 5 6 0]);\n\n%!test\n%! x = [0:7]';\n%! y = fftshift (x);\n%! assert (y, [4;5;6;7;0;1;2;3]);\n%! assert (fftshift (y), x);\n\n%!test\n%! x = [0:6]';\n%! y = fftshift (x);\n%! assert (y, [4;5;6;0;1;2;3]);\n%! assert (fftshift (y), [1;2;3;4;5;6;0]);\n\n%!test\n%! x = [0:3];\n%! x = [x;2*x;3*x+1;4*x+1];\n%! y = fftshift (x);\n%! assert (y, [[7 10 1 4];[9 13 1 5];[2 3 0 1];[4 6 0 2]]);\n%! assert (fftshift (y), x);\n\n%!test\n%! x = [0:3];\n%! x = [x;2*x;3*x+1;4*x+1];\n%! y = fftshift (x,1);\n%! assert (y, [[1 4 7 10];[1 5 9 13];[0 1 2 3];[0 2 4 6]]);\n%! assert (fftshift (y,1), x);\n\n%!test\n%! x = [0:3];\n%! x = [x;2*x;3*x+1;4*x+1];\n%! y = fftshift (x,2);\n%! assert (y, [[2 3 0 1];[4 6 0 2];[7 10 1 4];[9 13 1 5]]);\n%! assert (fftshift (y,2), x);\n\n%!test\n%! x = \"abcdefg\";\n%! y = fftshift (x);\n%! assert (y, \"efgabcd\");\n%! assert (fftshift (y), \"bcdefga\");\n\n## Test N-dimensional input\n%!test <*45207>\n%! x = [0:3];\n%! x = x + x' + reshape (x, [1 1 4]);\n%! y1 = [4 5 2 3; 5 6 3 4; 2 3 0 1; 3 4 1 2];\n%! y = fftshift (x);\n%! assert (y, reshape ([y1 + 2, y1 + 3, y1, y1 + 1], [4 4 4]));\n%! assert (fftshift (y), x);\n\n## Test input validation\n%!error <Invalid call> fftshift ()\n%!error fftshift (0:3, -1)\n%!error fftshift (0:3, 0:3)\n"
  },
  {
    "path": "scripts/signal/filter2.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} filter2 (@var{b}, @var{x})\n## @deftypefnx {} {@var{y} =} filter2 (@var{b}, @var{x}, @var{shape})\n## Apply the 2-D FIR filter @var{b} to @var{x}.\n##\n## If the argument @var{shape} is specified, return an array of the desired\n## shape.  Possible values are:\n##\n## @table @asis\n## @item @qcode{\"full\"}\n## pad @var{x} with zeros on all sides before filtering.\n##\n## @item @qcode{\"same\"}\n## unpadded @var{x} (default)\n##\n## @item @qcode{\"valid\"}\n## trim @var{x} after filtering so edge effects are no included.\n## @end table\n##\n## Note this is just a variation on convolution, with the parameters reversed\n## and @var{b} rotated 180 degrees.\n## @seealso{conv2}\n## @end deftypefn\n\nfunction y = filter2 (b, x, shape)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n  if (nargin < 3)\n    shape = \"same\";\n  endif\n\n  [nr, nc] = size (b);\n  y = conv2 (x, b(nr:-1:1, nc:-1:1), shape);\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/fractdiff.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{fd} =} fractdiff (@var{x}, @var{d})\n## Compute the fractional differences @math{(1-L)^d x} where @math{L}\n## denotes the lag-operator and @math{d} is greater than -1.\n## @end deftypefn\n\nfunction retval = fractdiff (x, d)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  N = 100;\n\n  if (! isvector (x))\n    error (\"fractdiff: X must be a vector\");\n  endif\n\n  if (! isscalar (d))\n    error (\"fractdiff: D must be a scalar\");\n  endif\n\n\n  if (d >= 1)\n    for k = 1 : d\n      x = x(2 : length (x)) - x(1 : length (x) - 1);\n    endfor\n  endif\n\n  if (d > -1)\n\n    d = rem (d, 1);\n\n    if (d != 0)\n      n = (0 : N)';\n      w = real (gamma (-d+n) ./ gamma (-d) ./ gamma (n+1));\n      retval = fftfilt (w, x);\n      retval = retval(1 : length (x));\n    else\n      retval = x;\n    endif\n\n  else\n    error (\"fractdiff: D must be > -1\");\n\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/freqz.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{h}, @var{w}] =} freqz (@var{b}, @var{a}, @var{n}, \"whole\")\n## @deftypefnx {} {[@var{h}, @var{w}] =} freqz (@var{b})\n## @deftypefnx {} {[@var{h}, @var{w}] =} freqz (@var{b}, @var{a})\n## @deftypefnx {} {[@var{h}, @var{w}] =} freqz (@var{b}, @var{a}, @var{n})\n## @deftypefnx {} {@var{h} =} freqz (@var{b}, @var{a}, @var{w})\n## @deftypefnx {} {[@var{h}, @var{w}] =} freqz (@dots{}, @var{Fs})\n## @deftypefnx {} {} freqz (@dots{})\n##\n## Return the complex frequency response @var{h} of the rational IIR filter\n## whose numerator and denominator coefficients are @var{b} and @var{a},\n## respectively.\n##\n## The response is evaluated at @var{n} angular frequencies between 0 and\n## @ifnottex\n## 2*pi.\n## @end ifnottex\n## @tex\n## $2\\pi$.\n## @end tex\n##\n## @noindent\n## The output value @var{w} is a vector of the frequencies.\n##\n## If @var{a} is omitted, the denominator is assumed to be 1 (this\n## corresponds to a simple FIR filter).\n##\n## If @var{n} is omitted, a value of 512 is assumed.  For fastest computation,\n## @var{n} should factor into a small number of small primes.\n##\n## If the fourth argument, @qcode{\"whole\"}, is omitted the response is\n## evaluated at frequencies between 0 and\n## @ifnottex\n## pi.\n## @end ifnottex\n## @tex\n## $\\pi$.\n## @end tex\n##\n## @code{freqz (@var{b}, @var{a}, @var{w})}\n##\n## Evaluate the response at the specific frequencies in the vector @var{w}.\n## The values for @var{w} are measured in radians.\n##\n## @code{[@dots{}] = freqz (@dots{}, @var{Fs})}\n##\n## Return frequencies in Hz instead of radians assuming a sampling rate\n## @var{Fs}.  If you are evaluating the response at specific frequencies\n## @var{w}, those frequencies should be requested in Hz rather than radians.\n##\n## @code{freqz (@dots{})}\n##\n## Plot the magnitude and phase response of @var{h} rather than returning them.\n##\n## @seealso{freqz_plot}\n## @end deftypefn\n\nfunction [h_r, f_r] = freqz (b, a, n, region, Fs)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (nargin == 1)\n    ## Response of an FIR filter.\n    a = n = region = Fs = [];\n  elseif (nargin == 2)\n    ## Response of an IIR filter\n    n = region = Fs = [];\n  elseif (nargin == 3)\n    region = Fs = [];\n  elseif (nargin == 4)\n    Fs = [];\n    if (! ischar (region) && ! isempty (region))\n      Fs = region;\n      region = [];\n    endif\n  endif\n\n  if (isempty (b))\n    b = 1;\n  elseif (! isvector (b))\n    error (\"freqz: B must be a vector\");\n  endif\n  if (isempty (a))\n    a = 1;\n  elseif (! isvector (a))\n    error (\"freqz: A must be a vector\");\n  endif\n  if (isempty (n))\n    n = 512;\n  elseif (isscalar (n) && n < 1)\n    error (\"freqz: N must be a positive integer\");\n  endif\n  if (isempty (region))\n    if (isreal (b) && isreal (a))\n      region = \"half\";\n    else\n      region = \"whole\";\n    endif\n  endif\n  if (isempty (Fs))\n    freq_norm = true;\n    if (nargout == 0)\n      Fs = 2;\n    else\n      Fs = 2*pi;\n    endif\n  else\n    freq_norm = false;\n  endif\n  plot_output = (nargout == 0);\n  whole_region = strcmp (region, \"whole\");\n\n  a = a(:);\n  b = b(:);\n\n  if (! isscalar (n))\n    ## Explicit frequency vector given\n    w = f = n;\n    if (nargin == 4)\n      ## Sampling rate Fs was specified\n      w = 2*pi*f/Fs;\n    endif\n    k = max (length (b), length (a));\n    hb = polyval (postpad (b, k), exp (j*w));\n    ha = polyval (postpad (a, k), exp (j*w));\n  else\n    ## polyval(fliplr(P),exp(jw)) is O(p n) and fft(x) is O(n log(n)),\n    ## where p is the order of the polynomial P.  For small p it\n    ## would be faster to use polyval but in practice the overhead for\n    ## polyval is much higher and the little bit of time saved isn't\n    ## worth the extra code.\n    k = max (length (b), length (a));\n    if (k > n/2 && nargout == 0)\n      ## Ensure a causal phase response.\n      n *= 2 .^ ceil (log2 (2*k/n));\n    endif\n\n    if (whole_region)\n      N = n;\n      if (plot_output)\n        f = Fs * (0:n).' / N;    # do 1 more for the plot\n      else\n        f = Fs * (0:n-1).' / N;\n      endif\n    else\n      N = 2*n;\n      if (plot_output)\n        n += 1;\n      endif\n      f = Fs * (0:n-1).' / N;\n    endif\n\n    pad_sz = N*ceil (k/N);\n    b = postpad (b, pad_sz);\n    a = postpad (a, pad_sz);\n\n    hb = zeros (n, 1);\n    ha = zeros (n, 1);\n\n    for i = 1:N:pad_sz\n      hb += fft (postpad (b(i:i+N-1), N))(1:n);\n      ha += fft (postpad (a(i:i+N-1), N))(1:n);\n    endfor\n\n  endif\n\n  h = hb ./ ha;\n\n  if (plot_output)\n    ## Plot and don't return values.\n    if (whole_region && isscalar (n))\n      h(end+1) = h(1); # Solution is periodic.  Copy first value to end.\n    endif\n    freqz_plot (f, h, freq_norm);\n  else\n    ## Return values and don't plot.\n    h_r = h;\n    f_r = f;\n  endif\n\nendfunction\n\n\n%!testif HAVE_FFTW # correct values and fft-polyval consistency\n%! ## butterworth filter, order 2, cutoff pi/2 radians\n%! b = [0.292893218813452  0.585786437626905  0.292893218813452];\n%! a = [1  0  0.171572875253810];\n%! [h,w] = freqz (b,a,32);\n%! assert (h(1),1,10*eps);\n%! assert (abs (h(17)).^2,0.5,10*eps);\n%! assert (h,freqz (b,a,w),10*eps);  # fft should be consistent with polyval\n\n%!testif HAVE_FFTW # whole-half consistency\n%! b = [1 1 1]/3; # 3-sample average\n%! [h,w] = freqz (b,1,32,\"whole\");\n%! assert (h(2:16),conj (h(32:-1:18)),20*eps);\n%! [h2,w2] = freqz (b,1,16,\"half\");\n%! assert (h(1:16),h2,20*eps);\n%! assert (w(1:16),w2,20*eps);\n\n%!testif HAVE_FFTW # Sampling frequency properly interpreted\n%! b = [1 1 1]/3; a = [1 0.2];\n%! [h,f] = freqz (b,a,16,320);\n%! assert (f,[0:15]'*10,10*eps);\n%! [h2,f2] = freqz (b,a,[0:15]*10,320);\n%! assert (f2,[0:15]*10,10*eps);\n%! assert (h,h2.',20*eps);\n%! [h3,f3] = freqz (b,a,32,\"whole\",320);\n%! assert (f3,[0:31]'*10,10*eps);\n\n## Test input validation\n## FIXME: Need to put tests here and simplify input validation in the main code.\n"
  },
  {
    "path": "scripts/signal/freqz_plot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} freqz_plot (@var{w}, @var{h})\n## @deftypefnx {} {} freqz_plot (@var{w}, @var{h}, @var{freq_norm})\n## Plot the magnitude and phase response of @var{h}.\n##\n## If the optional @var{freq_norm} argument is true, the frequency vector\n## @var{w} is in units of normalized radians.  If @var{freq_norm} is false, or\n## not given, then @var{w} is measured in Hertz.\n## @seealso{freqz}\n## @end deftypefn\n\nfunction freqz_plot (w, h, freq_norm = false)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  n = length (w);\n\n  ## ## exclude zero-frequency\n  ## h = h (2 : length (h));\n  ## w = w (2 : length (w));\n  ## n = n-1;\n\n  mag = 20 * log10 (abs (h));\n  phase = unwrap (arg (h));\n\n  if (freq_norm)\n    x_label = 'Normalized Frequency (\\times\\pi rad/sample)';\n  else\n    x_label = \"Frequency (Hz)\";\n  endif\n\n  subplot (2, 1, 1);\n  plot (w, mag);\n  grid (\"on\");\n  axis ([w(1), w(n)], \"autoy\");\n  xlabel (x_label);\n  ylabel (\"Magnitude (dB)\");\n\n  subplot (2, 1, 2);\n  plot (w, phase*360/(2*pi));\n  grid (\"on\");\n  axis ([w(1), w(n)], \"autoy\");\n  xlabel (x_label);\n  ylabel (\"Phase (degrees)\");\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/hamming.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} hamming (@var{m})\n## @deftypefnx {} {@var{c} =} hamming (@var{m}, \"periodic\")\n## @deftypefnx {} {@var{c} =} hamming (@var{m}, \"symmetric\")\n## Return the filter coefficients of a Hamming window of length @var{m}.\n##\n## If the optional argument @qcode{\"periodic\"} is given, the periodic form\n## of the window is returned.  This is equivalent to the window of length\n## @var{m}+1 with the last coefficient removed.  The optional argument\n## @qcode{\"symmetric\"} is equivalent to not specifying a second argument.\n##\n## For a definition of the Hamming window see, e.g.,\n## @nospell{A.V. Oppenheim & R. W. Schafer},\n## @cite{Discrete-Time Signal Processing}.\n## @end deftypefn\n\nfunction c = hamming (m, opt)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (m) && m > 0 && m == fix (m)))\n    error (\"hamming: M must be a positive integer\");\n  endif\n\n  N = m - 1;\n  if (nargin == 2)\n    switch (opt)\n      case \"periodic\"\n        N = m;\n      case \"symmetric\"\n        ## Default option, same as no option specified.\n      otherwise\n        error ('hamming: window type must be either \"periodic\" or \"symmetric\"');\n    endswitch\n  endif\n\n  if (m == 1)\n    c = 1;\n  else\n    m -= 1;\n    c = 0.54 - 0.46 * cos (2 * pi * (0 : m)' / N);\n  endif\n\nendfunction\n\n\n%!assert (hamming (1), 1)\n%!assert (hamming (2), (0.54 - 0.46)*ones (2,1))\n%!assert (hamming (15), flip (hamming (15)), 5*eps)\n%!assert (hamming (16), flip (hamming (16)), 5*eps)\n%!test\n%! N = 15;\n%! A = hamming (N);\n%! assert (A(ceil (N/2)), 1);\n\n%!assert (hamming (15), hamming (15, \"symmetric\"))\n%!assert (hamming (16)(1:15), hamming (15, \"periodic\"))\n%!test\n%! N = 16;\n%! A = hamming (N, \"periodic\");\n%! assert (A(N/2 + 1), 1);\n\n%!error <Invalid call> hamming ()\n%!error hamming (0.5)\n%!error hamming (-1)\n%!error hamming (ones (1,4))\n%!error hamming (1, \"invalid\")\n"
  },
  {
    "path": "scripts/signal/hanning.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} hanning (@var{m})\n## @deftypefnx {} {@var{c} =} hanning (@var{m}, \"periodic\")\n## @deftypefnx {} {@var{c} =} hanning (@var{m}, \"symmetric\")\n## Return the filter coefficients of a Hanning window of length @var{m}.\n##\n## If the optional argument @qcode{\"periodic\"} is given, the periodic form\n## of the window is returned.  This is equivalent to the window of length\n## @var{m}+1 with the last coefficient removed.  The optional argument\n## @qcode{\"symmetric\"} is equivalent to not specifying a second argument.\n##\n## For a definition of the Hanning window see, e.g.,\n## @nospell{A.V. Oppenheim & R. W. Schafer},\n## @cite{Discrete-Time Signal Processing}.\n## @end deftypefn\n\nfunction c = hanning (m, opt)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (m) && m > 0 && m == fix (m)))\n    error (\"hanning: M must be a positive integer\");\n  endif\n\n  N = m - 1;\n  if (nargin == 2)\n    switch (opt)\n      case \"periodic\"\n        N = m;\n      case \"symmetric\"\n        ## Default option, same as no option specified.\n      otherwise\n        error ('hanning: window type must be either \"periodic\" or \"symmetric\"');\n    endswitch\n  endif\n\n  if (m == 1)\n    c = 1;\n  else\n    m -= 1;\n    c = 0.5 - 0.5 * cos (2 * pi * (0 : m)' / N);\n  endif\n\nendfunction\n\n\n%!assert (hanning (1), 1)\n%!assert (hanning (2), zeros (2,1))\n%!assert (hanning (15), flip (hanning (15)), 5*eps)\n%!assert (hanning (16), flip (hanning (16)), 5*eps)\n%!test\n%! N = 15;\n%! A = hanning (N);\n%! assert (A(ceil (N/2)), 1);\n\n%!assert (hanning (15), hanning (15, \"symmetric\"))\n%!assert (hanning (16)(1:15), hanning (15, \"periodic\"))\n%!test\n%! N = 16;\n%! A = hanning (N, \"periodic\");\n%! assert (A(N/2 + 1), 1);\n\n%!error <Invalid call> hanning ()\n%!error hanning (0.5)\n%!error hanning (-1)\n%!error hanning (ones (1,4))\n%!error hanning (1, \"invalid\")\n"
  },
  {
    "path": "scripts/signal/hurst.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{H} =} hurst (@var{x})\n## Estimate the Hurst parameter of sample @var{x} via the rescaled range\n## statistic.\n##\n## If @var{x} is a matrix, the parameter is estimated for every column.\n## @end deftypefn\n\nfunction H = hurst (x)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  if (isscalar (x))\n    error (\"hurst: X must not be a scalar\");\n  elseif (isvector (x))\n    x = x(:);  # always use column vector\n  endif\n\n  [xr, xc] = size (x);\n\n  s = std (x);\n  w = cumsum (x - mean (x));\n  RS = (max (w) - min (w)) ./ s;\n  H = log (RS) / log (xr);\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/ifftshift.m",
    "content": "########################################################################\n##\n## Copyright (C) 1997-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} ifftshift (@var{y})\n## @deftypefnx {} {@var{x} =} ifftshift (@var{y}, @var{dim})\n## Undo the action of the @code{fftshift} function.\n##\n## For even length @var{x}, @code{fftshift} is its own inverse, but odd lengths\n## differ slightly.\n## @seealso{fftshift}\n## @end deftypefn\n\nfunction x = ifftshift (y, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (y) || islogical (y) || ischar (y)))\n    error (\"ifftshift: Y must be a vector or matrix\");\n  endif\n\n  if (nargin == 2)\n    if (! (isscalar (dim) && dim > 0 && dim == fix (dim)))\n      error (\"ifftshift: dimension DIM must be a positive integer\");\n    endif\n    nd = ndims (y);\n    sz = size (y);\n    sz2 = floor (sz(dim) / 2);\n    idx = repmat ({':'}, nd, 1);\n    idx{dim} = [sz2+1:sz(dim), 1:sz2];\n    x = y(idx{:});\n  else\n    if (isvector (y))\n      yl = length (y);\n      y2 = floor (yl/2);\n      x = y([y2+1:yl, 1:y2]);\n    else\n      nd = ndims (y);\n      sz = size (y);\n      sz2 = floor (sz ./ 2);\n      idx = cell ();\n      for i = 1:nd\n        idx{i} = [sz2(i)+1:sz(i), 1:sz2(i)];\n      endfor\n      x = y(idx{:});\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! x = [0:7];\n%! y = ifftshift (x);\n%! assert (y, [4 5 6 7 0 1 2 3]);\n%! assert (ifftshift (y), x);\n\n%!test\n%! x = [0:6];\n%! y = ifftshift (x);\n%! assert (y, [3 4 5 6 0 1 2]);\n%! assert (ifftshift (y), [6 0 1 2 3 4 5]);\n\n%!test\n%! x = [0:7]';\n%! y = ifftshift (x);\n%! assert (y, [4;5;6;7;0;1;2;3]);\n%! assert (ifftshift (y), x);\n\n%!test\n%! x = [0:6]';\n%! y = ifftshift (x);\n%! assert (y, [3;4;5;6;0;1;2]);\n%! assert (ifftshift (y), [6;0;1;2;3;4;5]);\n\n%!test\n%! x = [0:3];\n%! x = [x;2*x;3*x+1;4*x+1];\n%! y = ifftshift (x);\n%! assert (y, [[7 10 1 4];[9 13 1 5];[2 3 0 1];[4 6 0 2]]);\n%! assert (ifftshift (y), x);\n\n%!test\n%! x = [0:3];\n%! x = [x;2*x;3*x+1;4*x+1];\n%! y = ifftshift (x,1);\n%! assert (y, [[1 4 7 10];[1 5 9 13];[0 1 2 3];[0 2 4 6]]);\n%! assert (ifftshift (y,1), x);\n\n%!test\n%! x = [0:3];\n%! x = [x;2*x;3*x+1;4*x+1];\n%! y = ifftshift (x,2);\n%! assert (y, [[2 3 0 1];[4 6 0 2];[7 10 1 4];[9 13 1 5]]);\n%! assert (ifftshift (y,2), x);\n\n%!test\n%! x = \"efgabcd\";\n%! y = ifftshift (x);\n%! assert (y, \"abcdefg\");\n%! assert (ifftshift (y), \"defgabc\");\n\n## Test N-dimensional input\n%!test <*45207>\n%! x = [0:3];\n%! x = x + x' + reshape (x, [1 1 4]);\n%! y1 = [4 5 2 3; 5 6 3 4; 2 3 0 1; 3 4 1 2];\n%! y = ifftshift (x);\n%! assert (y, reshape ([y1 + 2, y1 + 3, y1, y1 + 1], [4 4 4]));\n%! assert (ifftshift (y), x);\n\n## Test input validation\n%!error <Invalid call> ifftshift ()\n%!error ifftshift (0:3, -1)\n%!error ifftshift (0:3, 0:3)\n"
  },
  {
    "path": "scripts/signal/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/rectangle_lw.m  \\\n  %reldir%/private/rectangle_sw.m  \\\n  %reldir%/private/triangle_lw.m  \\\n  %reldir%/private/triangle_sw.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/__parse_movargs__.m \\\n  %reldir%/arch_fit.m \\\n  %reldir%/arch_rnd.m \\\n  %reldir%/arch_test.m \\\n  %reldir%/arma_rnd.m \\\n  %reldir%/autoreg_matrix.m \\\n  %reldir%/bartlett.m \\\n  %reldir%/blackman.m \\\n  %reldir%/detrend.m \\\n  %reldir%/diffpara.m \\\n  %reldir%/durbinlevinson.m \\\n  %reldir%/fftconv.m \\\n  %reldir%/fftfilt.m \\\n  %reldir%/fftshift.m \\\n  %reldir%/filter2.m \\\n  %reldir%/fractdiff.m \\\n  %reldir%/freqz.m \\\n  %reldir%/freqz_plot.m \\\n  %reldir%/hamming.m \\\n  %reldir%/hanning.m \\\n  %reldir%/hurst.m \\\n  %reldir%/ifftshift.m \\\n  %reldir%/movfun.m \\\n  %reldir%/movslice.m \\\n  %reldir%/periodogram.m \\\n  %reldir%/sinc.m \\\n  %reldir%/sinetone.m \\\n  %reldir%/sinewave.m \\\n  %reldir%/spectral_adf.m \\\n  %reldir%/spectral_xdf.m \\\n  %reldir%/spencer.m \\\n  %reldir%/stft.m \\\n  %reldir%/synthesis.m \\\n  %reldir%/unwrap.m \\\n  %reldir%/yulewalker.m\n\n%canon_reldir%dir = $(fcnfiledir)/signal\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/signal/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/signal/movfun.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movfun (@var{fcn}, @var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movfun (@var{fcn}, @var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movfun (@dots{}, \"@var{property}\", @var{value})\n##\n## Apply function @var{fcn} to a moving window of length @var{wlen} on data\n## @var{x}.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## During calculations the data input @var{x} is reshaped into a 2-dimensional\n## @var{wlen}-by-@var{N} matrix and @var{fcn} is called on this new matrix.\n## Therefore, @var{fcn} must accept an array input argument and apply the\n## computation along dimension 1, i.e., down the columns of the array.\n##\n## When applied to an array (possibly multi-dimensional) with @var{n} columns,\n## @var{fcn} may return a result in either of two formats: @w{Format 1)}@ an\n## array of size 1-by-@var{n}-by-@var{dim3}-by-@dots{}-by-@var{dimN}.  This\n## is the typical output format from Octave core functions.  Type\n## @code{demo (\"movfun\", 5)} for an example of this use case.\n## @w{Format 2)}@ a row vector of length\n## @code{@var{n} * @var{numel_higher_dims}} where @var{numel_higher_dims} is\n## @w{@code{prod (size (@var{x})(3:end))}}.  The output of @var{fcn} for the\n## i-th input column must be found in the output at indices\n## @w{@code{i:@var{n}:(@var{n}*@var{numel_higher_dims})}}.\n## This format is useful when concatenating functions into arrays, or when\n## using @code{nthargout}.  Type @code{demo (\"movfun\", 6)} for an example of\n## this case.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs.  Valid properties are\n##\n## @table @asis\n##\n## @item @qcode{\"dim\"}\n## Operate along the dimension specified, rather than the default of the first\n## non-singleton dimension.\n##\n## @item @qcode{\"SamplePoints\"}\n##\n## This property specifies a sorted, numeric vector of unique coordinate\n## positions of the data points in @var{x}.  The default value is the vector\n## @w{@code{[1 : @var{numel (x)}]}}.  When a non-default SamplePoints vector\n## is specified, the moving window length @var{wlen} is measured\n## against the SamplePoints positions to determine which points are\n## included in each window slice.  SamplePoints need not be uniformly spaced.\n## This can result in window slices containing different numbers of points.\n##\n## @item @qcode{\"Endpoints\"}\n##\n## This property controls how results are calculated at the boundaries\n## (@w{endpoints}) of the window.  Possible values are:\n##\n## @table @asis\n## @item @qcode{\"shrink\"} (default)\n## The window is truncated at the beginning and end of the array to exclude\n## elements for which there is no source data.  For example, with a window of\n## length 3, @code{@var{y}(1) = @var{fcn} (@var{x}(1:2))}, and\n## @code{@var{y}(end) = @var{fcn} (@var{x}(end-1:end))}.\n##\n## @item @qcode{\"discard\"}\n## Any @var{y} values that use a window extending beyond the original\n## data array are deleted.  For example, with a 10-element data vector and a\n## window of length 3, the output will contain only 8 elements.  The first\n## element would require calculating the function over indices\n## @w{@code{[0, 1, 2]}}@ and is therefore discarded.  The last element would\n## require calculating the function over indices @w{@code{[9, 10, 11]}}@ and is\n## therefore discarded.\n##\n## @item @qcode{\"fill\"}\n## Any window elements outside the data array are replaced by @code{NaN}.  For\n## example, with a window of length 3,\n## @code{@var{y}(1) = @var{fcn} ([NaN, @var{x}(1:2)])}, and\n## @code{@var{y}(end) = @var{fcn} ([@var{x}(end-1:end), NaN])}.\n## This option usually results in @var{y} having @code{NaN} values at the\n## boundaries, although it is influenced by how @var{fcn} handles @code{NaN},\n## and also by the property @qcode{\"nancond\"}.\n##\n## @item @var{user_value}\n## Any window elements outside the data array are replaced by the specified\n## value @var{user_value} which must be a numeric scalar.  For example, with a\n## window of length 3,\n## @code{@var{y}(1) = @var{fcn} ([@var{user_value}, @var{x}(1:2)])}, and\n## @code{@var{y}(end) = @var{fcn} ([@var{x}(end-1:end), @var{user_value}])}.\n## A common choice for @var{user_value} is 0.\n##\n## @item @qcode{\"same\"}\n## Any window elements outside the data array are replaced by the value of\n## @var{x} at the boundary.  For example, with a window of length 3,\n## @code{@var{y}(1) = @var{fcn} ([@var{x}(1), @var{x}(1:2)])}, and\n## @code{@var{y}(end) = @var{fcn} ([@var{x}(end-1:end), @var{x}(end)])}.\n##\n## @item @qcode{\"periodic\"}\n## The window is wrapped so that any missing data elements are taken from\n## the other side of the data.  For example, with a window of length 3,\n## @code{@var{y}(1) = @var{fcn} ([@var{x}(end), @var{x}(1:2)])}, and\n## @code{@var{y}(end) = @var{fcn} ([@var{x}(end-1:end), @var{x}(1)])}.\n##\n## @end table\n##\n## Note 1: For non-uniform SamplePoint spacing, the only permitted value for\n## @qcode{\"EndPoints\"} is @qcode{\"shrink\"}.\n##\n## Note 2: For some @qcode{\"Endpoints\"} options, the window size at the\n## boundaries may not be the same as for the central part, and @var{fcn} must\n## work in these cases.\n##\n## @item @qcode{\"nancond\"}\n## Controls haw @code{NaN} and @code{NA} values affect the output of\n## @qcode{\"movfun\"}.  The value @qcode{\"includenan\"} (default) causes\n## @code{NaN} and @code{NA} values to be included in the moving window, and any\n## window slice containing @code{NaN} or @code{NA} values will return\n## @code{NaN} for that element.  The value @qcode{\"omitnan\"} causes\n## @qcode{\"movfun\"} to ignore any @code{NaN} or @code{NA} values resulting\n## in fewer elements being used to calculate the result for that window\n## slice.  If @qcode{\"omitnan\"} is specified and a window slice contains all\n## @code{NaN} or @code{NA} values, @qcode{\"movfun\"} returns the value\n## specified by the @qcode{\"nanval\"} property for that element.  The values\n## @qcode{\"includemissing\"} and @qcode{\"omitmissing\"} may be used\n## synonymously with @qcode{\"includenan\"} and @qcode{\"omitnan\"},\n## respectively.\n##\n## @item @qcode{\"nanval\"}\n## Specifies the value to return when @qcode{\"nancond\"} is set to\n## @qcode{\"omitnan\"} or @qcode{\"omitmissing\"} and all elements in a window\n## are @code{NaN} or @code{NA}.  @qcode{\"nanval\"} must be a numeric scalar\n## value or @code{NaN} (default).\n##\n## @item @qcode{\"outdim\"}\n## A row vector that selects which dimensions of the calculation will appear\n## in the output @var{y}.  This is only useful when @var{fcn} returns an\n## N-dimensional array in @w{Format 1}.  The default is to return all output\n## dimensions.\n##\n## @end table\n##\n## Programming Note: The property @qcode{\"outdim\"} can be used to save memory\n## when the output of @var{fcn} has many dimensions, or when a wrapper to the\n## base function that selects the desired outputs is too costly.  When memory\n## is not an issue, the easiest way to select output dimensions is to first\n## calculate the complete result with @code{movfun} and then filter that\n## result with indexing.  If code complexity is not an issue then a wrapper\n## can be created using anonymous functions.  For example, if @code{basefcn}\n## is a function returning a @var{K}-dimensional row output, and only\n## dimension @var{D} is desired, then the following wrapper could be used.\n##\n## @example\n## @group\n## @var{fcn} = @@(x) basefcn (x)(:,columns(x) * (@var{D}-1) + (1:columns(x)));\n## @var{y} = movfun (@@fcn, @dots{});\n## @end group\n## @end example\n##\n## @seealso{movslice, prepad, postpad, permute, reshape}\n## @end deftypefn\n\nfunction y = movfun (fcn, x, wlen, varargin)\n\n  ## FIXME: \"Samplepoints\", \"omitnan\", and some \"EndPoints\" options create\n  ## unequally sized windows/slices that don't vectorize easily, and\n  ## preprocessing to enable some vectorization in blocks and reduce looping is\n  ## expensive.  This function could see significant performance gains from\n  ## placing certain routines into a .oct file, especially sections dealing\n  ## with \"omitnan\" that will be only entered for specific, known floating\n  ## point object types.\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  valid_bc = {\"shrink\", \"discard\", \"fill\", \"same\", \"periodic\"};\n  valid_nancond = {\"includenan\", \"includemissing\", \"omitnan\", \"omitmissing\"};\n\n  ## Parse required input arguments.\n  ## Allow fcn to perform any x validation.\n  ## Most wlen validation will be done by movslice.\n\n  if (! is_function_handle (fcn))\n    error (\"movfun: FCN must be a valid function handle\");\n  endif\n\n  if (! isnumeric (wlen))\n    error (\"movfun: WLEN must be numeric\");\n  endif\n\n  ## Parse optional arguments\n  dim = [];\n  nancond = \"includenan\";\n  omitnan = false;\n  nanval = NaN;\n  outdim = [];\n  sp.samplepoints = [];\n  bc = \"shrink\";\n\n  if (nargin > 3)\n    if (mod (numel (varargin), 2))\n      error (\"movfun: Each PROPERTY must have a VALUE\");\n    endif\n\n    vargidx = 1;\n    while (vargidx < nargin - 3)\n      prop = varargin{vargidx};\n      if (! (ischar (prop) && isrow (prop)))\n        error (\"movfun: PROPERTY name must be a valid string\");\n      endif\n\n      switch (lower (prop))\n        case \"dim\"\n          dim = varargin{++vargidx};\n          if (! (isempty (dim)\n                 || (isnumeric (dim) && isscalar (dim) && isindex (dim))))\n            error (\"movfun: DIM must be a positive integer\");\n          endif\n\n        case \"endpoints\"\n          bc = varargin{++vargidx};\n\n          if (! (isnumeric (bc) && isscalar (bc)\n                 || (ischar (bc) && isrow (bc) && any (strcmpi (bc, valid_bc)))\n                 || (isscalar (bc) && strcmp (class (x), class (bc)))))\n            error (\"movfun: ENDPOINTS must be a numeric scalar, a scalar the same class as X, or a valid Endpoint method\");\n          endif\n\n        case \"nancond\"\n          nancond = varargin{++vargidx};\n          if (! (ischar (nancond) && isrow (nancond)\n                 && (any (strcmpi (nancond, valid_nancond)))))\n            error (\"movfun: NANCOND must be 'includenan', 'includemissing', 'omitnan', or 'omitmissing'\");\n          endif\n          omitnan = any (strcmpi (nancond, {\"omitnan\", \"omitmissing\"}));\n\n        case \"nanval\"\n          nanval = varargin{++vargidx};\n          if (! (isscalar (nanval) && isnumeric (nanval)))\n            error (\"movfun: NANVAL must be a numeric scalar or NaN\");\n          endif\n\n        case \"outdim\"\n          outdim = varargin{++vargidx};\n          if (! (isnumeric (outdim) && isvector (outdim) && isindex (outdim)))\n            error (\"movfun: OUTDIM must be a numeric, positive, integer-valued scalar or vector\");\n          endif\n\n        case \"samplepoints\"\n          sp.samplepoints = varargin{++vargidx};\n          if (! (isnumeric (sp.samplepoints) && isvector (sp.samplepoints)\n                 && issorted (sp.samplepoints)\n                 && all (diff (sp.samplepoints) != 0)))\n            error (\"movfun: SAMPLEPOINTS must be a sorted, non-repeating, numeric vector\");\n          endif\n          sp.samplepoints = sp.samplepoints(:);\n\n        otherwise\n          error (\"movfun: unknown PROPERTY '%s'\", prop);\n\n      endswitch\n\n      vargidx++;\n\n   endwhile\n  endif\n\n  if (isempty (x))\n    ## Nothing to do.  Return immediately with empty output the same shape and\n    ## class as x.\n    clsx = class (x);\n    if (isnumeric (x) || islogical (x))\n      y = zeros (size (x), clsx);\n    else\n      try\n       y = cast (zeros (size (x)), clsx);\n      catch err\n        err_msg = [\"cast: type conversion to '\", clsx, \"' is not supported\"];\n        if (strcmp (err.message, err_msg))\n          y = zeros (size (x));\n        else\n          rethrow (err);\n        endif\n      end_try_catch\n    endif\n\n    return;\n\n  endif\n\n  ## Finish optional parameter processing.\n\n  ## If dim was not provided find the first non-singleton dimension.\n  szx = size (x);\n  nd = length (szx);\n  if (isempty (dim))\n    (dim = find (szx > 1, 1)) || (dim = 1);\n  elseif (dim > nd)\n    szx = [szx, ones(1, dim - nd)];\n    nd = dim;\n  endif\n  N = szx(dim);\n\n  ## Perform remaining samplepoints validation or set defaults.\n  sp.uniform = true;\n  sp.standard = true;\n  sp.spacing = 1;\n\n  sp.apply = ! isempty (sp.samplepoints);\n\n  if (sp.apply)\n    if (numel (sp.samplepoints) != N)\n      error (\"movfun: SamplePoints must be the same size as x in operating dimension\");\n    endif\n\n    sp.spacing = diff (sp.samplepoints, 1, 1);\n    sp.uniform = all (sp.spacing == sp.spacing(1));\n\n    if (all (sp.spacing == 1))\n      sp.standard = true;\n      sp.apply = false;\n    else\n      sp.standard = false;\n    endif\n\n    if (sp.uniform)\n      sp.spacing = sp.spacing(1);\n    endif\n\n    if (! sp.uniform && ! strcmpi (bc, \"shrink\"))\n      error (\"movfun: when SamplePoints are not uniformly spaced the only valid EndPoints option is 'shrink'\");\n    endif\n  endif\n\n  ## Calculate slicing indices.  This call also validates WLEN input.\n  ## wlen returned in [nb, na] form for subfunction processing.\n  ## wlen integer-scalar state for inclusive/exclusive endpoint limit behavior\n  ## returned by movslice, used by endpoints depending on win and not slcidx,\n  ## which already includes the inclusive/exclusive behavior.\n  ## slc and win forms will depend on whether samplpoints is default of 1:N.\n  if (sp.standard)\n    [slc, C, Cpre, Cpos, win, wlen] = movslice (N, wlen);\n  else\n    [slc, C, Cpre, Cpos, win, wlen, sp.scalar_wlen] = ...\n                                       movslice (N, wlen, sp.samplepoints);\n    ## Note that for non-standard sp, slc points already adjusted for\n    ## scalar_wlen.  win is always inclusive showing full window extents.\n  endif\n\n  ## Move the desired DIM to dim 1 (fcn operates on 1st non-singleton dim)\n  nd    = length (szx);                 # number of dimensions\n  dperm = [dim, 1:(dim-1), (dim+1):nd]; # permutation of dimensions\n  x     = permute (x, dperm);           # permute dims to first dimension\n  ncols = prod (szx(dperm(2:end)));     # other dimensions as single column\n  x     = reshape (x, N, ncols);        # reshape input\n\n  ## Obtain function for boundary conditions.\n  if (isnumeric (bc) || (isscalar (bc) && strcmp (class (bc), class (x))))\n    bcfcn = @replaceval_bc;\n    bcfcn (true, bc);  # initialize replaceval function with value.\n\n  else\n    switch (lower (bc))\n      case \"shrink\"\n        bcfcn = @shrink_bc;\n\n      case \"discard\"\n        ## Only called if samplepoints are uniform.  Convert slcidx back\n        ## into standard form by trimming end cols and expanding center for\n        ## all elements.\n        bcfcn = [];\n        C -= length (Cpre);\n\n        if (sp.apply && sp.uniform)\n          slc(:, [Cpre, Cpos]) = [];\n          if (isempty (C))\n            y = NaN (1, 0);\n            return;\n          else\n            slc = slc(1,C) + (0: diff (slc(:, C(1)), 1, 1)).';\n          endif\n          sp.apply = false;\n        endif\n\n        Cpre = Cpos = [];\n        N = length (C);\n        szx(dperm(1)) = N;\n\n      case \"fill\"\n        bcfcn = @replaceval_bc;\n        bcfcn (true, NaN);\n\n      case \"same\"\n        bcfcn = @same_bc;\n\n      case \"periodic\"\n        bcfcn = @periodic_bc;\n\n    endswitch\n  endif\n\n  ## Validate that outdim makes sense.\n  ## Check fcn ouptut for data sampled from x.  See bug #55984.\n  if (! sp.apply)\n    fout = fcn (x(1 : min (length (win), N))(:));\n  else\n    fout = fcn (x(1 : min (max (diff (slc, 1, 1)) + 1, N))(:));\n  endif\n\n  yclass = class (fout);              # record class of fcn output\n  noutdim = length (fout);            # number of output columns\n  if (! isempty (outdim))\n    if (max (outdim) > noutdim)\n      error (\"Octave:invalid-input-arg\", ...\n             [\"movfun: output dimension OUTDIM (%d) is larger than \", ...\n              \"largest available dimension (%d)\"], ...\n             max (outdim), noutdim);\n    endif\n  else\n    outdim = 1:noutdim;\n  endif\n  soutdim = length (outdim);  # length of selected output dimensions\n\n  ## If noutdim is not one then modify function to handle multiple outputs.\n  if (noutdim > 1)\n    fcn_ = @(x) reshape (fcn (x), columns (x), noutdim)(:, outdim);\n  else\n    fcn_ = fcn;\n  endif\n\n  ## Initialize output array to appropriate size and class.\n  try\n    y = zeros (N, ncols, soutdim, yclass);\n  catch err\n    if (! strcmp (err.message, \"zeros: invalid class name\"))\n      rethrow (err);\n    endif\n    y = cast (zeros (N, ncols, soutdim), yclass);\n  end_try_catch\n\n  ## Apply processing to each column.\n  parfor i = 1:ncols\n    y(:,i,:) = movfun_oncol (fcn_, yclass, x(:,i), wlen, bcfcn, ...\n                             slc, C, Cpre, Cpos, win, soutdim, sp, ...\n                             omitnan, nanval);\n  endparfor\n\n  ## Restore shape\n  y = reshape (y, [szx(dperm), soutdim]);\n  y = ipermute (y, [dperm, nd+1]);\n  if (! isempty (y))\n    y = squeeze (y);\n  endif\n\nendfunction\n\n\nfunction y = movfun_oncol (fcn, yclass, x, wlen, bcfcn, slcidx, C, Cpre,\n                           Cpos, win, odim, sp, omitnan, nanval)\n\n  nan_x = isnan (x);\n  if (all (nan_x))\n    ## Shortcut path if all NaN and nothing to do.\n    if (! omitnan || isnan (nanval))\n      ## includenan always returns NaN for all-NaN window.  omitnan will return\n      ## nanval in same case.\n      y = NaN (length (x), odim, yclass);  # isnan true -> yclass is a float\n    else\n      y = nanval(ones (length (x), odim));\n    endif\n    return;\n  endif\n\n  any_nans = any (nan_x);\n  nan_x_idx = find (nan_x);\n  if (! any_nans)\n    ## If no NaNs, turn off slower NaN handling path for this data.\n    omitnan = false;\n  endif\n\n  ## Process center of data\n\n  ## Note: for wlen = 1 or [0, 0] with standard samplepoints, or just small\n  ## enough that window never reaches adjacent points for non-standard sp,\n  ## slcidx will be a row vector.  Passing this for vectorized processing to\n  ## some fcn will cause handling as a single vector (one slice) returning\n  ## only one value rather than handling in a columnwise fashion.  This is\n  ## handled throughout movfun by checking isrow then forcing elementwise\n  ## processing with arrayfun.  This may be slow, but it avoids needing to\n  ## place other restrictions on fcn.  Hopefully most functions will handle\n  ## as trivial or at least with low-computational overhead for N = 1.\n  ## FIXME: This could be sidestepped for most internal functions by\n  ##        specifying the operating dimension.  E.g., sum (x(slcidx), 2).\n  ##        That would require establishing separate code paths for built-in\n  ##        and general movfun calls.\n\n  if (! isempty (C))\n    N = length ([Cpre, C, Cpos]);\n\n    try\n      y = zeros (N, odim, yclass);\n    catch err\n      if (! strcmp (err.message, \"zeros: invalid class name\"))\n        rethrow (err);\n      endif\n      y = cast (zeros (N, odim), yclass);\n    end_try_catch\n\n    if (! omitnan)\n      ## With includenan any slice with a NaN returns NaN whether or not fcn\n      ## handles NaN differently.  Handle those before passing to other\n      ## subfunctions.\n\n      if (! sp.apply)\n        ## Neither omitnan or samplepoints\n        if (any_nans)\n\n          if (isrow (slcidx))\n            nancols = any (nan_x(slcidx), 2).';\n          else\n            nancols = any (nan_x(slcidx), 1);\n          endif\n          y(C(nancols), :) = NaN;\n\n          ## Process remaining cols.\n          if (! all (nancols))\n            C = C(! nancols);\n            y(C, :) = yeval_safe (y(C, :), fcn, x, slcidx(:, ! nancols));\n          endif\n\n        else\n          y(C,:) = yeval_safe (y(C,:), fcn, x, slcidx);\n        endif\n\n      else\n        ## samplepoints, not omitnan\n\n        ## Trim out NaN-containing slices.\n        if (any_nans)\n          nan_cols = any ((slcidx(1,C) <= nan_x_idx) &\n                          (slcidx(2,C) >= nan_x_idx), 1);\n          y(C(nan_cols), :) = NaN;\n          C = C(! nan_cols);\n        endif\n\n        if (! isempty (C))\n          if (sp.uniform)\n            ## Uniform samplepoints, equal slice sizes.\n            num_elems = diff (slcidx(:, C(1)), 1, 1);\n            y(C, :) = yeval_safe (y(C,:), fcn, x, slcidx(1,C), num_elems);\n\n          else\n            ## Non-uniform samplepoints, possible varying slice sizes.\n\n            [elem_cnt_grp_idx, unq_cnts] = form_idx_groups (\n                                     diff (slcidx(:,C), 1, 1));\n\n            for ii = 1 : rows (elem_cnt_grp_idx)\n              grp_cols = C(elem_cnt_grp_idx(ii,:));\n              y(grp_cols,:) = yeval_safe (y(grp_cols,:), fcn, x,\n                                          slcidx(1, grp_cols), unq_cnts(ii));\n            endfor\n          endif\n        endif\n      endif\n\n    else\n      ## omitnan - need to remove NaN elements before passing to fcn.\n\n      if (! sp.apply)\n\n        ## omitnan but not samplepoints\n        if (isrow (slcidx))\n          y(slcidx(nan_x),:) = nanval;\n          y(slcidx(! nan_x),:) = arrayfun (fcn, x(slcidx(! nan_x)));\n\n        else\n\n          ## omitnan may create columns/slices with uneven number of elements.\n          has_nan = any (nan_x(slcidx));\n          all_nan = all (nan_x(slcidx));\n          no_nan = ! has_nan;\n\n          ## First process all-NaN columns.\n          if (any (all_nan))\n            y(C(all_nan)) = nanval;\n          endif\n\n          ## Then process no-NaN columns as a block.\n          if (any (no_nan))\n              y(C(no_nan),:) = yeval_safe (y(C(no_nan),:), fcn, x,\n                                           slcidx(:, no_nan));\n          endif\n\n          ## Step through remaining columns with some NaNs creating unequal\n          ## element-count columns.\n          ## Group into equal element-count blocks.\n          has_nan &= ! all_nan;\n          if (any (has_nan))\n\n            nan_locs = nan_x(slcidx(:, has_nan));\n            [elem_cnt_grp_idx, unq_cnts] = ...\n                                         form_idx_groups (sum (! nan_locs, 1));\n\n            for ii = 1 : rows (elem_cnt_grp_idx)\n              cols_in_group = elem_cnt_grp_idx(ii,:);\n              grp_cols = C(has_nan)(cols_in_group);\n              slc_grp = slcidx(:, has_nan)(:, cols_in_group);\n              slc_grp(nan_locs(:, cols_in_group)) = [];\n              slc_grp = reshape (slc_grp, unq_cnts(ii), []);\n\n              y(grp_cols,:) = yeval_safe (y(grp_cols,:), fcn, x, slc_grp);\n\n            endfor\n          endif\n        endif\n      else\n        ## Both samplepoints and omitnan\n        elem_cnt_grp_idx = form_idx_groups (diff (slcidx(:, C), 1, 1));\n        for ii = 1: rows (elem_cnt_grp_idx)\n          y(C(elem_cnt_grp_idx(ii,:)), :) = proc_uniform_block_omitnan (\n                                    y(C(elem_cnt_grp_idx(ii,:)), :),\n                                    fcn, x, nan_x, nanval,\n                                    slcidx(:, C(elem_cnt_grp_idx(ii,:))));\n        endfor\n      endif\n    endif\n\n  else  # empty C\n    ## Large windows may create Cpre/Cpos overlap and empty C.\n    N = length (unique_endpoints (Cpre, Cpos));\n    try\n      y = zeros (N, odim, yclass);\n    catch err\n      if (! strcmp (err.message, \"zeros: invalid class name\"))\n        rethrow (err);\n      endif\n      y = cast (zeros (N, odim), yclass);\n    end_try_catch\n  endif\n\n  ## Process boundaries\n  if (! (isempty ([Cpre, Cpos])))\n    if (! omitnan && any_nans)\n      ## With includenan any NaN-containing windows return NaN.\n\n      if (sp.apply)\n        ## slcidx form for sp contains enough info to directly find\n        ## NaN-containing slices.\n        ## Handle pre and pos separately because there could be overlap.\n\n        nan_Cpre = any ((slcidx(1,Cpre) <= nan_x_idx)\n                        & (slcidx(2,Cpre) >= nan_x_idx), 1);\n\n        nan_Cpos = any ((slcidx(1,Cpos) <= nan_x_idx)\n                        & (slcidx(2,Cpos) >= nan_x_idx), 1);\n\n      else\n        ## Expand slcidx from win.\n        slctmp = Cpre + win;\n        slctmp(slctmp > 0) = nan_x(slctmp(slctmp > 0));\n        slctmp(slctmp < 0) = 0;\n        nan_Cpre = any (slctmp);\n\n        slctmp = Cpos + win;\n        slctmp(slctmp <= N) = nan_x(slctmp(slctmp <= N));\n        slctmp(slctmp > N) = 0;\n        nan_Cpos = any (slctmp);\n\n      endif\n      y([Cpre(nan_Cpre), Cpos(nan_Cpos)], :) = NaN;\n\n      Cpre = Cpre(! nan_Cpre);\n      Cpos = Cpos(! nan_Cpos);\n    endif\n\n    if (! (isempty ([Cpre,Cpos]))) # Recheck after possible trimming.\n      Cbc = unique_endpoints (Cpre, Cpos);\n      y(Cbc,:) = bcfcn (fcn, x, Cpre, Cpos, win, wlen, odim,\n                        slcidx, sp, omitnan, nanval, nan_x);\n    endif\n  endif\n\nendfunction\n\n\n## Process uniform index block removing NaN elements, idx is in 2-row\n## samplepoints form trimmed to C columns.\nfunction y = proc_uniform_block_omitnan (y, fcn, x, nan_x, nanval, slcidx)\n\n  ## expand slice index.\n  elem_cnt = diff (slcidx(:, 1), 1, 1);\n  slcidx = slcidx(1,:) + (0:elem_cnt).';\n\n  if (isrow (slcidx))\n    nan_locs = nan_x(slcidx)(:).';\n  else\n    nan_locs = nan_x(slcidx);\n  endif\n\n  has_nan = any (nan_locs, 1);\n  all_nan = all (nan_locs, 1);\n  no_nan = ! has_nan;\n\n  ## First process all-NaN columns.\n  if (any (all_nan))\n    y(all_nan, :) = nanval;\n  endif\n\n  ## Then process no-NaN columns as a block.\n  if (any (no_nan))\n    y(no_nan, :) = yeval_safe (y(no_nan,:), fcn, x, slcidx(:, no_nan));\n  endif\n\n  ## Step through remaining columns with some NaNs creating unequal\n  ## element-count columns.  Use similar approach as for samplepoints\n  ## to group into equal element-count blocks.\n\n  has_nan &= ! all_nan;\n  if (any (has_nan))\n    nan_locs = nan_locs(:, has_nan);\n    slcidx = slcidx(:, has_nan);\n\n    [elem_cnt_grp_idx, unq_cnts] = form_idx_groups (sum (! nan_locs, 1));\n\n    for ii = 1 : numel (unq_cnts)\n      grp_cols = elem_cnt_grp_idx(ii,:);\n      y_idx = find (has_nan)(grp_cols);\n      slc_grp = slcidx(:, grp_cols);\n      slc_grp(nan_locs(:, grp_cols)) = [];\n      slc_grp = reshape (slc_grp, unq_cnts(ii), []);\n\n      y(y_idx,:) = yeval_safe (y(y_idx,:), fcn, x, slc_grp);\n    endfor\n  endif\n\nendfunction\n\n\n## Utility function to take a row vector of whole numbers and split them\n## into groups that can be used for block processing.  Will return a logical\n## array.  Each row corresponds to one a (sorted ascending) value in the input\n## vector and the column indexes identify the location of the members of that\n## group.  Optional return is a row vector with the sorted unique values of\n## the input vector.  (Avoids overhead of calling unique.)\nfunction [v_grp_idx, unq_v] = form_idx_groups (v)\n  v_srt = sort (v);          # Sorted counts to build groups\n  unq_v_idx = logical ([1, diff(v_srt)]);  # Location of first of each value\n  unq_v = v_srt(unq_v_idx);  # List of unique elements, sorted\n  v_grp_idx = v == unq_v.';  # Logical group index by row\nendfunction\n\n\n## Utility function with try-catch on y = fcn(x(slc)) to catch possible\n## memory overflow on type conversion or broadcast expansion.  If caught,\n## divide into blocks then reprocess.  If 5th input \"counts\" is passed, it\n## expects slc to be a row vecor of first elements in the full slc array, and\n## performs the slc expansion with \"counts\" elements inside try-catch block.\n## Both paths check for the full slc to be a row vector and if so passes the\n## eval through arrayfun to ensure columnwise processing.\nfunction y = yeval_safe (y, fcn, x, slc, counts)\n\n  if (nargin < 5)\n    try\n      if (isrow (slc))\n        y = arrayfun (fcn, x(slc));\n      else\n        y(:,:) = fcn (x(slc));\n      endif\n\n    catch err\n      ## Operation failed, likely due to out-of-memory error for x(slcidx)\n      if (! strcmp (err.identifier, \"Octave:bad-alloc\"))\n        rethrow (err);\n      endif\n\n      ## Try divide and conquer approach with smaller slices of data.\n      N_SLICES = 8;  # configurable\n      idx = fix (linspace (1, columns (slc), N_SLICES));\n      if (isrow (slc))\n        for ii = 1 : N_SLICES-1\n          y(idx(ii):idx(ii + 1), :) = ...\n                                 arrayfun (fcn, x(slc(:, idx(ii):idx(ii + 1))));\n        endfor\n      else\n        for ii = 1 : N_SLICES-1\n          y(idx(ii):idx(ii + 1), :) = ...\n                                 fcn (x(slc(:, idx(ii):idx(ii + 1))));\n        endfor\n      endif\n\n    end_try_catch\n\n  else\n    ## slc_full expansion also in try/catch, split into blocks\n    try\n      slc_full = slc + (0:counts).';\n      if (isrow (slc_full))\n        y = arrayfun (fcn, x(slc_full));\n      else\n        y(:,:) = fcn (x(slc_full));\n      endif\n\n    catch err\n      ## Operation failed, likely due to out-of-memory error on idx expansion.\n      if (! strcmp (err.identifier, \"Octave:bad-alloc\"))\n        rethrow (err);\n      endif\n\n      ## Try divide and conquer approach with smaller slices of data.\n      N_SLICES = 8; ## configurable\n      idx = fix (linspace (1, columns (slc), N_SLICES));\n      if (counts == 0)\n        for ii = 1: N_SLICES-1\n          slc_part = slc(idx(ii):idx(ii+1)) + (0 : counts).';\n          y(idx(ii):idx(ii + 1), :) = arrayfun (fcn, x(slc_part));\n        endfor\n      else\n        for ii = 1 : N_SLICES-1\n          slc_part = slc(idx(ii):idx(ii + 1)) + (0 : counts).';\n          y(idx(ii):idx(ii + 1), :) = fcn (x(slc_part));\n        endfor\n      endif\n    end_try_catch\n  endif\n\nendfunction\n\n\n## Apply \"shrink\" boundary conditions\n## Function is not applied to any window elements outside the original data.\nfunction y = shrink_bc (fcn, x, Cpre, Cpos, win, ~, odim, idx, sp,\n                        omitnan, nanval, nan_x)\n\n  Cp_unique = unique_endpoints (Cpre, Cpos);\n  N = length (x);\n  n = length (Cp_unique);\n  y = zeros (n, odim);\n\n  if (! omitnan)\n    if (! sp.apply)\n      ## Neither samplepoints nor omitnan\n      idx = Cp_unique + win;\n      tf  = (idx > 0) & (idx <= N);  # find idx inside boundaries\n\n      ## FIXME: This nested for loop accounts for 70% of running time.\n      ##        Given that \"shrink\" is the default Endpoint value this\n      ##        code needs to be reworked.\n      ##\n      ##        Some built-in functions like sum, min, max, etc., already use\n      ##        specific fill values in place of \"shrink\" to allow vectorized\n      ##        processing (e.g., replacing \"shrink\" with\n      ##        \"'endpoints', 0\" for @sum or \"'endpoints',-Inf\" for @max), but\n      ##        such assumptions can't be made for movfun with arbitrary fcn.\n      ##\n      ##        Note 20-Aug-2024: The effort to find and extract indices for\n      ##        grouped processing looks likely to take more computation\n      ##        time than the simple loop below, and it is unlikely for the\n      ##        cost per iteration to be much less to create a useful\n      ##        breakeven point.\n      for ii = 1:n\n        k = idx(tf(:,ii), ii);\n        y(ii,:) = fcn (x(k));\n      endfor\n\n    else\n      ## Just samplepoints not omitnan\n\n      ## idx from movslice already contains \"tf-trimmed\" windows.\n      [elem_cnt_grp_idx, unq_cnts] = form_idx_groups (\n                                             diff (idx(:, Cp_unique), 1, 1));\n      for ii = 1 : rows (elem_cnt_grp_idx)\n        col_grp_idx = elem_cnt_grp_idx(ii,:);\n        k = idx(1, Cp_unique(col_grp_idx)) + (0 : unq_cnts(ii)).';\n        if (isrow (k))\n          y(col_grp_idx,:) = arrayfun (fcn, x(k));\n        else\n          y(col_grp_idx,:) = fcn (x(k));\n        endif\n      endfor\n    endif\n\n  else\n\n    if (sp.apply)\n      ## samplepoints and omitnan\n\n      elem_cnt_grp_idx = form_idx_groups (diff (idx(:, Cp_unique), 1, 1));\n      for ii = 1 : rows (elem_cnt_grp_idx)\n        col_grp_idx = elem_cnt_grp_idx(ii,:);\n        y(col_grp_idx,:) = ...\n                 proc_uniform_block_omitnan (y(col_grp_idx,:),\n                                             fcn, x, nan_x, nanval,\n                                             idx(:, Cp_unique(col_grp_idx)));\n      endfor\n\n    else\n      ## no samplepoints just omitnan\n      idx = Cp_unique + win;\n      tf  = (idx > 0) & (idx <= N);  # find idx inside boundaries\n      nan_idx = idx;\n      nan_idx(! tf) = 0;\n      nan_idx(tf) = nan_x(idx(tf));\n\n      tf = tf & ! nan_idx;\n      all_nan = all (! tf);\n\n      y(all_nan) = nanval;\n      for ii = find (! all_nan)\n        k = idx(tf(:,ii), ii);\n        y(ii,:) = fcn (x(k));\n      endfor\n\n    endif\n  endif\n\nendfunction\n\n\n## Apply replacement value boundary conditions\n## Window is padded at beginning and end with user-specified value.\nfunction y = replaceval_bc (fcn, x, Cpre, Cpos, win, wlen, odim, idx,\n                            sp, omitnan, nanval, nan_x)\n\n  persistent substitute;\n\n  ## In-band method to initialize substitute value\n  if (islogical (fcn))\n    substitute = x;\n    return;\n  endif\n\n  Cp_unique = unique_endpoints (Cpre, Cpos);\n  sz = size (x);\n  if (! sp.apply)\n    idx = Cp_unique + win;\n\n    if (idx(1) < 1)\n      ## pre-pad window, check if also post-pad\n      sz(1) = 1 - idx(1);\n      x = [substitute(ones (sz)); x];\n      if (omitnan)\n        nan_x = [false(sz); nan_x];\n      endif\n      idx = idx + wlen(1);\n    endif\n\n    N = numel (x);\n    if (idx(end) > N)\n      ## post-pad window\n      sz(1) = idx(end) - N;\n      x = [x; substitute(ones (sz))];\n      if (omitnan)\n        nan_x = [nan_x; false(sz)];\n      endif\n    endif\n\n  else\n\n    if (! isempty (Cpre))\n      sz(1) = numel ([sp.samplepoints(1) : -sp.spacing : win(1)]) - 1;\n      x = [substitute(ones (sz)); x];\n      if (omitnan)\n        nan_x = [false(sz); nan_x];\n      endif\n\n      idx += sz(1);\n      idx(1, Cpre) -= sz(1) + 1 - Cpre;\n    endif\n\n    if (! isempty (Cpos))\n      ## only post-pad window\n      pts = [sp.samplepoints(end) : sp.spacing : win(end)];\n      exclude_endpoint = pts(end) == sp.samplepoints(end) + wlen(2);\n      sz(1) = numel (pts) - 1 - (sp.scalar_wlen && exclude_endpoint);\n      idx(2, Cpos) += sz(1) + 1 - (numel (Cpos) : -1 : 1);\n      x = [x; substitute(ones (sz))];\n      if (omitnan)\n        nan_x = [nan_x; false(sz)];\n      endif\n    endif\n\n    elems = diff (idx(:, Cp_unique(1)), 1, 1);\n    idx = idx(1, Cp_unique) + (0:elems).';\n  endif\n\n  if (! omitnan)\n    y = fcn (x(idx));\n  else\n    y = proc_uniform_block_omitnan (zeros (columns (idx), odim), fcn, x,\n                                    nan_x, nanval, idx([1,end],:));\n  endif\n\nendfunction\n\n\n## Apply \"same\" boundary conditions\n## 'y' values outside window are replaced by value of 'x' at the window\n## boundary.\nfunction y = same_bc (fcn, x, Cpre, Cpos, win, wlen, odim, idx, sp,\n                      omitnan, nanval, nan_x)\n\n  N = length (x);\n\n  if (! sp.apply)\n    idx = unique_endpoints (Cpre, Cpos) + win;\n\n  else\n    sz_pre = numel ([sp.samplepoints(1) : -sp.spacing : win(1)]) - 1;\n\n    pts_post = [sp.samplepoints(end) : sp.spacing : win(end)];\n    exclude_endpoint = pts_post(end) == sp.samplepoints(end) + wlen(2);\n    sz_post = numel (pts_post) - 1 - (sp.scalar_wlen && exclude_endpoint);\n\n    idx(2, Cpos) += sz_post - (numel (Cpos) - 1 : -1 : 0);\n    idx = double (idx(:, unique_endpoints (Cpre, Cpos)));  # Allow neg values\n    idx(1, Cpre) -= sz_pre - (0 : numel (Cpre) - 1);\n\n    elems = diff (idx(:, 1), 1, 1);\n    idx = idx(1,:) + (0:elems).';\n  endif\n\n  if (! omitnan)\n    idx(idx < 1) = 1;\n    idx(idx > N) = N;\n    y = fcn (x(idx));\n\n  else\n    npre = 1 - idx(1);\n    npos = idx(end) - N;\n    szx = size (x);\n    szpre = [npre, szx(2:end)];\n    szpos = [npos, szx(2:end)];\n\n    x = [x(1)(ones (szpre)); x; x(end)(ones (szpos))];\n    nan_x = [nan_x(1)(ones (szpre)); nan_x; nan_x(end)(ones (szpos))];\n\n    idx = idx + npre;\n    y = proc_uniform_block_omitnan (zeros (columns (idx), odim), fcn, x,\n                                    nan_x, nanval, idx([1,end],:));\n  endif\n\nendfunction\n\n\n## Apply \"periodic\" boundary conditions\n## Window wraps around.  Window values outside data array are replaced with\n## data from the other end of the array.\nfunction y = periodic_bc (fcn, x, Cpre, Cpos, win, wlen, odim, idx, sp,\n                          omitnan, nanval, nan_x)\n\n  N = length (x);\n\n  if (! sp.apply)\n    idx = unique_endpoints (Cpre, Cpos) + win;\n\n  else\n    sz_pre = numel ([sp.samplepoints(1) : -sp.spacing : win(1)]) - 1;\n\n    pts_post = [sp.samplepoints(end) : sp.spacing : win(end)];\n    exclude_endpoint = pts_post(end) == sp.samplepoints(end) + wlen(2);\n    sz_post = numel (pts_post) - 1 - (sp.scalar_wlen && exclude_endpoint);\n\n    idx(2, Cpos) += sz_post + 1 - (numel (Cpos) : -1 : 1);\n    idx = double (idx(:, unique_endpoints (Cpre, Cpos)));\n    idx(1, Cpre) -= sz_pre + 1 - Cpre;\n\n    elems = diff (idx(:, 1), 1, 1);\n    idx = idx(1,:) + (0:elems).';\n  endif\n\n  if (! omitnan)\n    tfpre = idx < 1;\n    tfpos = idx > N;\n\n    premult = ceil ((1 - idx(tfpre)) / N);\n    postmult = floor ((N - idx(tfpos)) / N);\n\n    idx(tfpre) += N * premult;\n    idx(tfpos) += N * postmult;\n\n    y = fcn (x(idx));\n\n  else\n    npre = 1 - idx(1);\n    npos = idx(end) - N;\n    szx = size (x);\n\n    x_idx_pre = idx(1:npre).';\n    x_idx_pos = idx((end - npos + 1) : end).';\n\n    premult = ceil ((1 - x_idx_pre) / N);\n    postmult = floor ((N - x_idx_pos) / N);\n\n    x_idx_pre += N * premult;\n    x_idx_pos += N * postmult;\n\n    x = [x(x_idx_pre, :); x; x(x_idx_pos, :)];\n    nan_x = [nan_x(x_idx_pre, :); nan_x; nan_x(x_idx_pos, :)];\n\n    idx = idx + npre;\n    y = proc_uniform_block_omitnan (zeros (columns (idx), odim), fcn, x,\n                                    nan_x, nanval, idx([1,end],:));\n  endif\n\n\nendfunction\n\n\n## Faster unique routine to remove potential overlapping endpoint indices.\n## Assumes a and b are vectors of valid, sorted linear indices.  Either may be\n## empty.  a will have the form [1:M], b will have the form [N:P].  M must be\n## no larger than P, and N must be no smaller than 1.\nfunction c = unique_endpoints (a, b)\n\n  if (isempty (a))\n    c = b;\n  else\n    notshared = cummax (b == a(end));\n    if (any (notshared))\n      c = [a(1:end-1), b(notshared)];\n    else\n      c = [a, b];\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! clf;\n%! t  = 2 * pi * linspace (0,1,100).';\n%! x  = sin (3 * t);\n%! xn = x + 0.1 * randn (size (x));\n%! x_s = movfun (@mean, xn, 5, \"Endpoints\", \"shrink\");\n%! x_p = movfun (@mean, xn, 5, \"Endpoints\", \"periodic\");\n%! x_m = movfun (@mean, xn, 5, \"Endpoints\", \"same\");\n%! x_z = movfun (@mean, xn, 5, \"Endpoints\", 0);\n%! x_f = movfun (@mean, xn, 5, \"Endpoints\", \"fill\");\n%!\n%! h = plot (t, xn, \"o;noisy signal;\",\n%!           t, x, \"-;true;\",\n%!           t, x_s, \"-;shrink;\",\n%!           t, x_p, \"-;periodic;\",\n%!           t, x_m, \"-;same;\",\n%!           t, x_z, \"-;zero;\",\n%!           t, x_f, \"-;fill;\");\n%! set (h(1), \"markerfacecolor\", \"auto\");\n%! set (h(2:end), \"linewidth\", 3);\n%! axis tight\n%! xlabel (\"time\");\n%! ylabel (\"signal\");\n%! title (\"moving mean with different boundary conditions\");\n%! #-----------------------------------------------------------------\n%! # Moving mean of noisy sinusoidal function with different boundary\n%! # conditions.\n\n%!demo\n%! clf;\n%! t  = 2 * pi * linspace (0,1,100).';\n%! x  = sin (3 * t);\n%! xn = x + 0.1 * randn (size (x));\n%! nwin = 5;\n%! x_ = zeros (rows (x), nwin);\n%! wlen = 3 + (1:nwin) * 4;\n%! for i = 1:nwin\n%!   x_(:,i) = movfun (@mean, xn, wlen(i), \"Endpoints\", \"periodic\");\n%! endfor\n%!\n%! h = plot (t, xn, \"o\",\n%!           t, x, \"-\",\n%!           t, x_, \"-\");\n%! set (h(1), \"markerfacecolor\", \"auto\");\n%! set (h(2:end), \"linewidth\", 3);\n%! axis tight\n%! xlabel (\"time\");\n%! ylabel (\"signal\");\n%! title ({'moving mean with \"periodic\" boundary conditions',\n%!         \"and windows of different lengths\"});\n%! legend (h, {\"noisy\", \"true\", strsplit(num2str(wlen)){:}});\n%! #-----------------------------------------------------------------\n%! # Moving mean of noisy sinusoidal function with periodic boundary conditions\n%! # using windows of different lengths.\n\n%!demo\n%! clf;\n%! t  = linspace (0,1,100).';\n%! x  = exp (-(t - [0.1:0.3:1]).^2/2/0.1^2);\n%! y  = movfun (@max, x, 15);\n%!\n%! h = plot (t, x, \"-\",\n%!           t, y, \"--\");\n%! axis tight\n%! xlabel (\"time\");\n%! ylabel (\"signal\");\n%! title (\"moving max of several Gaussian functions\");\n%! #-----------------------------------------------------------------\n%! # Moving max of different Gaussian functions.\n%! # Illustrates the application of movfun() to inputs with several columns.\n\n%!demo\n%! clf;\n%! t  = linspace (0,1-1e-2,100).';\n%! w  = 2 * pi * 3;\n%! x  = sin (w * t);\n%! y  = cos (w * t);\n%! y_  = movfun (@diff, x, [1 0], \"Endpoints\", \"periodic\");\n%! ## Is the same as y_ = x(2:end) - x(1:end-1);\n%! dt = t(2) - t(1);\n%! y_  = y_ / w / dt;\n%!\n%! h = plot (t, x, \"-\",\n%!           t, y, \"-\",\n%!           t, y_, \":\");\n%! set (h, \"linewidth\", 3);\n%! axis tight\n%! xlabel (\"time\");\n%! ylabel (\"signal\");\n%! title (\"movfun with periodic boundary conditions and asymmetric window\");\n%! legend (h, {\"sin\", \"cos\", \"[nb, na]\"});\n%! #-----------------------------------------------------------------\n%! # Backward diff() of sinusoidal function with periodic boundary conditions.\n%! # Illustrates the use of asymmetric windows.\n\n%!demo\n%! clf;\n%! N    = 1e3;\n%! wlen = 99;\n%! x  = linspace (-1, 1, N).';\n%! pp = [-2 0 1 0];\n%! y  = polyval (pp, x);\n%! yn = y + 0.1 * (abs (y) + 0.5) .* exp (randn (N, 1));\n%!\n%! st = movfun (@(y) (statistics (y)).', yn, wlen);\n%!\n%! h = plot (x, y, \"-\",\n%!           x, yn, \".\",\n%!           x, st(:,[3 6]), \"-\",\n%!           x, st(:,6) + [-1 1].*st(:,7), \"-\",\n%!           x, st(:,[1 2 4 5]), \"-\");\n%! set (h([1 3:4]), \"linewidth\", 3);  # mean\n%! set (h(5:end), \"color\", \"k\");\n%! axis tight\n%! xlabel (\"x\")\n%! ylabel (\"y\")\n%! title (\"movfun() with Format 1 output data\");\n%! legend (h(1:4), {\"noiseless\", \"noisy\", \"mean\", \"median\"})\n%! #-----------------------------------------------------------------\n%! # Moving window statistics.  The plot highlights mean and median.\n%! # Black lines how minimum, first quartile, third quartile, and maximum.\n%! # Demo illustrates the use of functions with multi-dimensional output.\n\n%!demo\n%! clf;\n%! N    = 1e2;\n%! wlen = 9;\n%! x  = linspace (-1, 1, N).';\n%! pp = [-2 0 1 0];\n%! y  = polyval (pp, x);\n%! y(:,2) = y + 0.1 * (abs (y) + 0.5) .* exp (randn (N, 1));\n%! y(:,1) = -y(:,1) + 0.1 * randn (N, 1);\n%!\n%! fcn = @(y) [min(y), max(y)];\n%! st = movfun (fcn, y, wlen);\n%!\n%! h = plot (x, y, \"o\",\n%!           x, squeeze (st(:,1,:)), \"-\",\n%!           x, squeeze (st(:,2,:)), \"-\");\n%! axis tight\n%! set (h(3:4), \"color\", get (h(1), \"color\"));\n%! set (h(5:6), \"color\", get (h(2), \"color\"));\n%! xlabel (\"x\")\n%! ylabel (\"y\")\n%! title (\"movfun() with Format 2 output data\");\n%! legend (h(1:2), {\"data1\", \"data2\"})\n%! #-----------------------------------------------------------------\n%! # Moving min() and max() on the same window.\n%! # Demo illustrates the use of functions with flat multi-dimensional output.\n\n\n%!test\n%! x = (1:10).' + [-3, 0, 4];\n%! ctrfun = @(x) x(2,:);\n%! valid_bc = {\"periodic\", 0, \"fill\", \"same\"};\n%! for bc = valid_bc\n%!   assert (movfun (ctrfun, x, 3, \"Endpoints\", bc{1}), x);\n%! endfor\n%! x_ = x; x_([1 end],:) = x([2 end],:);\n%! assert (movfun (ctrfun, x, 3, \"Endpoints\", \"shrink\"), x_);\n\n%!test\n%! ## dim == 2, same as transpose\n%! x = randi (10, 3);\n%! ctrfun = @(x) x(2,:);\n%! valid_bc = {\"periodic\", 0, \"fill\", \"same\"};\n%! for bc = valid_bc\n%!   assert (movfun (ctrfun, x.', 3, \"Endpoints\", bc{1}, \"dim\", 2), x.');\n%! endfor\n%! x_ = x; x_([1 end],:) = x([2 end],:);\n%! assert (movfun (ctrfun, x.', 3, \"Endpoints\", \"shrink\", \"dim\", 2), x_.');\n\n%!test\n%! x = randi (10, 3, 10, 2);\n%! y = movfun (@(x) x(2,:), x, 3, \"Endpoints\", \"same\", \"dim\", 2);\n%! assert (x, y);\n\n%!test\n%! ## bad zero_bc\n%! x = ones (10, 1);\n%! y = x; y(1:2) = y([end end-1]) = [0.6;0.8];\n%! assert (movfun (@mean, x, 5, \"Endpoints\", 0), y);\n\n## Asymmetric windows\n%!shared x, wlen, wlen02, wlen20, ctrfun, UNO\n%! x = (1:10).' + [-3, 0, 4];\n%! wlen = [2, 1];\n%! wlen02 = [0, 2];\n%! wlen20 = [2, 0];\n%! ctrfun = @(x) x(wlen(1)+1,:);\n%! UNO = ones (7,1);\n\n%!assert (movfun (ctrfun, x, wlen, \"Endpoints\", \"periodic\"), x)\n%!assert (movfun (ctrfun, x, wlen, \"Endpoints\", 0), x)\n%!assert (movfun (ctrfun, x, wlen, \"Endpoints\", \"fill\"), x)\n%!assert (movfun (ctrfun, x, wlen, \"Endpoints\", \"same\"), x)\n## for shorter x, indexing fails\n%!error movfun (ctrfun, x, wlen, \"Endpoints\", \"shrink\")\n\n%!assert (movfun (@min, UNO, wlen, \"Endpoints\", \"shrink\"), UNO)\n%!assert (movfun (@min, UNO, wlen02, \"Endpoints\", \"shrink\"), UNO)\n%!assert (movfun (@min, UNO, wlen20, \"Endpoints\", \"shrink\"), UNO)\n\n%!assert (movfun (@min, UNO, wlen02, \"Endpoints\", \"periodic\"), UNO)\n%!assert (movfun (@min, UNO, wlen20, \"Endpoints\", \"periodic\"), UNO)\n\n%!assert (movfun (@max, UNO, wlen02, \"Endpoints\", 0), UNO)\n%!assert (movfun (@max, UNO, wlen20, \"Endpoints\", 0), UNO)\n\n%!assert (movfun (@min, UNO, wlen02, \"Endpoints\", \"fill\"), UNO)\n%!assert (movfun (@min, UNO, wlen20, \"Endpoints\", \"fill\"), UNO)\n\n%!assert (movfun (@min, UNO, wlen02, \"Endpoints\", \"same\"), UNO)\n%!assert (movfun (@min, UNO, wlen20, \"Endpoints\", \"same\"), UNO)\n\n## Multi-dimensional output\n%!assert (size (movfun (@(x) [min(x), max(x)], (1:10).', 3)), [10 2])\n%!assert (size (movfun (@(x) [min(x), max(x)], cumsum (ones (10,5),2), 3)),\n%!        [10 5 2])\n## outdim > dim\n%!error movfun (@(x) [min(x), max(x)], (1:10).', 3, \"Outdim\", 3)\n\n## Clear shared variables for remaining tests to reduce clutter on failure.\n%!shared\n\n## Test for correct return class based on output of function.\n%!test <*63802>\n%! x = single (1:10);\n%! y = movfun (@mean, x, 3);\n%! assert (class (y), 'single');\n%! y = movfun (@mean, uint8 (x), 3);\n%! assert (class (y), 'double');\n\n## Test calculation along empty dimension\n%!assert <*63802> (movfun (@mean, zeros (2, 0, 3, \"single\"), 3, 'dim', 2),\n%!                 zeros (2,0,3, \"single\"))\n%!assert <*66025> (movfun (@mean, zeros (2, 0, 3, \"double\"), 3, 'dim', 2),\n%!                 zeros (2,0,3, \"double\"))\n%!assert <*66025> (movfun (@mean, zeros (2, 0, 3, \"uint8\"), 3, 'dim', 2),\n%!                 zeros (2,0,3, \"uint8\"))\n%!assert <*66025> (movfun (@mean, zeros (2, 0, 3, \"logical\"), 3, 'dim', 2),\n%!                 zeros (2,0,3, \"logical\"))\n%!assert <*66025> (movfun (@mean, cell (2, 0, 3), 3, 'dim', 2),\n%!                 zeros (2,0,3, \"double\"))\n%!assert <*66025> (movfun (@mean, \"\", 3, 'dim', 2), \"\")\n%!assert <*66025> (movfun (@mean, '', 3, 'dim', 2), '')\n\n## Test for correct output shape for dim > 2 and ndims > 2\n%!test <*65927>\n%! a = reshape (1:30, 5, 3, 2);\n%! b1 = cat (3, [1, 6, 11], [16, 21, 26]) + [0, 0.5, 1.5, 2.5, 3.5].';\n%! b2 = cat (3, [1:5].', [16:20].') + [0, 2.5, 7.5];\n%! b3 = cat (3, [1:5].', [8.5:1:12.5].') + [0, 5, 10];\n%! assert (movfun (@mean, a, 2), b1, eps);\n%! assert (movfun (@mean, a, 2, 'dim', 1), b1, eps);\n%! assert (movfun (@mean, a, 2, 'dim', 2), b2, eps);\n%! assert (movfun (@mean, a, 2, 'dim', 3), b3, eps);\n%!\n%! a2 = repmat (a, 1, 1, 1, 4);\n%! assert (size (movfun (@mean, a2, 2)), [5, 3, 2, 4]);\n%! assert (size (movfun (@mean, a2, 2, 'dim', 1)), [5, 3, 2, 4]);\n%! assert (size (movfun (@mean, a2, 2, 'dim', 2)), [5, 3, 2, 4]);\n%! assert (size (movfun (@mean, a2, 2, 'dim', 3)), [5, 3, 2, 4]);\n%! assert (size (movfun (@mean, a2, 2, 'dim', 4)), [5, 3, 2, 4]);\n\n## Test for wlen = 1 or window length > size (x, dim)\n%!assert <*65928> (movfun (@sum, 1:10, 1), 1:10)\n%!assert <*65928> (movfun (@sum, 1:10, [0, 0]), 1:10)\n%!assert <*65928> (movfun (@sum, 1:10, 10), ...\n%!                 [15, 21, 28, 36, 45, 55, 54, 52, 49, 45])\n%!assert <*65928> (movfun (@sum, 1:10, 11),\n%!                 [21, 28, 36, 45, 55, 55, 54, 52, 49, 45])\n%!assert <*65928> (movfun (@sum, 1:10, 12),\n%!                 [21, 28, 36, 45, 55, 55, 55, 54, 52, 49])\n%!assert <*65928> (movfun (@sum, 1:10, 99), 55(ones (1, 10)))\n%!assert <*65928> (movfun (@sum, 1:10, [9, 8]), [45, 55(ones (1, 9))])\n\n## Test different values of dim\n%!assert (movfun (@sum, 1:5, 3), [3, 6, 9, 12, 9])\n%!assert (movfun (@sum, 1:5, 3, \"dim\", 2), [3, 6, 9, 12, 9])\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"dim\", 1), 1:5)\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"dim\", 3), 1:5)\n\n%!assert (movfun (@sum, magic (3), 3), [11, 6, 13; 15, 15, 15; 7, 14, 9])\n%!assert (movfun (@sum, magic (3), 3, \"dim\", 1), [11, 6, 13; 15, 15, 15; 7, 14, 9])\n%!assert (movfun (@sum, magic (3), 3, \"dim\", 2), [9, 15, 7; 8, 15, 12; 13, 15, 11])\n%!assert <*65928> (movfun (@sum, magic (3), 3, \"dim\", 3), magic (3))\n\n## Test endpoint options with window lengths exceeding size (x, dim)\n%!assert <*65928> (movfun (@sum, 1:5, 20, \"endpoints\", \"shrink\"), 15(ones (1, 5)))\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"shrink\", \"dim\", 1), 1:5)\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"shrink\", \"dim\", 3), 1:5)\n%!assert <*65928> (movfun (@sum, 1:5, 20, \"endpoints\", \"same\"), 50:4:66)\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"same\", \"dim\", 1), 3:3:15)\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"same\", \"dim\", 3), 3:3:15)\n%!assert <*65928> (movfun (@sum, 1:5, 20, \"endpoints\", \"periodic\"), 60(ones (1, 5)))\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"periodic\", \"dim\", 1), 3:3:15)\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"periodic\", \"dim\", 3), 3:3:15)\n%!assert <*65928> (movfun (@sum, 1:5, 20, \"endpoints\", 1), 30(ones (1, 5)))\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", 1, \"dim\", 1), 3:7)\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", 1, \"dim\", 3), 3:7)\n%!assert <*65928> (movfun (@sum, 1:5, 20, \"endpoints\", \"discard\"), NaN (1, 0))\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"discard\", \"dim\", 1), NaN (0, 5))\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"discard\", \"dim\", 3), NaN (1, 5, 0))\n%!assert <*65928> (movfun (@sum, 1:5, 20, \"endpoints\", \"fill\"), NaN (1, 5))\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"fill\", \"dim\", 1), NaN (1, 5))\n%!assert <*65928> (movfun (@sum, 1:5, 3, \"endpoints\", \"fill\", \"dim\", 3), NaN (1, 5))\n\n## Samplepoint tests\n## standard spacing\n%!assert <*66025> (movfun (@sum, 1:10, 4, \"samplepoints\", 1:10), movfun (@sum, 1:10, 4))\n%!assert <*66025> (movfun (@sum, 1:10, 5, \"samplepoints\", 1:10), movfun (@sum, 1:10, 5))\n%!assert <*66025> (movfun (@sum, 1:10, 4.1, \"samplepoints\", 1:10), movfun (@sum, 1:10, 4.1))\n%!assert <*66025> (movfun (@sum, 1:10, [2, 3], \"samplepoints\", 1:10), movfun (@sum, 1:10, [2, 3]))\n%!assert <*66025> (movfun (@sum, 1:10, 60, \"samplepoints\", 1:10), movfun (@sum, 1:10, 60))\n%!assert <*66025> (movfun (@sum, 1:10, [30, 30], \"samplepoints\", 1:10), movfun (@sum, 1:10, [30, 30]))\n\n## nonstandard, uniform spacing\n%!assert <*66025> (movfun (@sum, 1:10, 4, \"samplepoints\", 0.5:0.5:5), [10, 15, 21, 28, 36, 44, 52, 49, 45, 40])\n%!assert <*66025> (movfun (@sum, 1:10, 5, \"samplepoints\", 0.5:0.5:5), [15, 21, 28, 36, 45, 55, 54, 52, 49, 45])\n%!assert <*66025> (movfun (@sum, 1:10, 4.1, \"samplepoints\", 0.5:0.5:5), [15, 21, 28, 36, 45, 54, 52, 49, 45, 40])\n%!assert <*66025> (movfun (@sum, 1:10, [2, 2], \"samplepoints\", 0.5:0.5:5), [15, 21, 28, 36, 45, 54, 52, 49, 45, 40])\n%!assert <*66025> (movfun (@sum, 1:10, 2.5, \"samplepoints\", 0.25:0.25:2.5), [15, 21, 28, 36, 45, 55, 54, 52, 49, 45])\n%!assert <*66025> (movfun (@sum, 1:10, [1.25, 1.25], \"samplepoints\", 0.25:0.25:2.5), [21, 28, 36, 45, 55, 55, 54, 52, 49, 45])\n%!assert <*66025> (movfun (@sum, 1:10, 60, \"samplepoints\", 0.5:0.5:5), 55(ones (1, 10)))\n%!assert <*66025> (movfun (@sum, 1:10, [30, 30], \"samplepoints\", 0.5:0.5:5), 55(ones (1, 10)))\n\n%!assert <*66025> (movfun (@sum, 1:10, 3, \"samplepoints\", 2:2:20), 1:10)\n%!assert <*66025> (movfun (@sum, 1:10, 4, \"samplepoints\", 2:2:20), 1:2:19)\n\n\n## nonstandard, nonuniform spacing\n%!assert <*66025> (movfun (@sum, 1:10, 4, \"samplepoints\", [1:9, 11]), [3, 6, 10, 14, 18, 22, 26, 30, 24, 19])\n%!assert <*66025> (movfun (@sum, 1:10, 5, \"samplepoints\", [1:9, 11]), [6, 10, 15, 20, 25, 30, 35, 30, 34, 19])\n%!assert <*66025> (movfun (@sum, 1:10, 4.1, \"samplepoints\", [1:9, 11]), [6, 10, 15, 20, 25, 30, 35, 30, 34, 19])\n%!assert <*66025> (movfun (@sum, 1:10, [2, 2], \"samplepoints\", [1:9, 11]), [6, 10, 15, 20, 25, 30, 35, 30, 34, 19])\n%!assert <*66025> (movfun (@sum, 1:10, 60, \"samplepoints\", [1:9, 11]), 55(ones(1, 10)))\n%!assert <*66025> (movfun (@sum, 1:10, [30, 30], \"samplepoints\", [1:9, 11]), 55(ones(1, 10)))\n\n## endpoints other than \"shrink\"\n## constant\n%!assert <*66025> (movfun (@sum, 10:10:100, 4, \"samplepoints\", 0.5:0.5:5, \"endpoints\", 1), [104, 153, 212, 281, 360, 440, 520, 491, 452, 403])\n%!assert <*66025> (movfun (@sum, 10:10:100, 5, \"samplepoints\", 0.5:0.5:5, \"endpoints\", 1), [155, 214, 283, 362, 451, 550, 541, 522, 493, 454])\n%!assert <*66025> (movfun (@sum, 10:10:100, 5, \"samplepoints\", 2:2:20, \"endpoints\", 1), [31, 60:30:270, 191])\n%!assert <*66025> (movfun (@sum, 10:10:100, [2, 2], \"samplepoints\", 0.5:0.5:5, \"endpoints\", 1), [154, 213, 282, 361, 450, 540, 521, 492, 453, 404])\n%!assert <*66025> (movfun (@sum, 10:10:100, [0, 2.5], \"samplepoints\", 2:2:20, \"endpoints\", 1), [30:20:190, 101])\n%!assert <*66025> (movfun (@sum, 10:10:100, 40, \"samplepoints\", 0.5:0.5:5, \"endpoints\", 1), 620(ones (1, 10)))\n%!assert <*66025> (movfun (@sum, 10:10:100, [20, 20], \"samplepoints\", 0.5:0.5:5, \"endpoints\", 1), 621(ones (1, 10)))\n\n## fill\n%!assert <*66025> (movfun (@sum, 1:10, 4, \"samplepoints\", 0.5:0.5:5, \"endpoints\", \"fill\"), [NaN(1, 4), 36, 44, 52, NaN(1, 3)])\n%!assert <*66025> (movfun (@sum, 1:10, 5, \"samplepoints\", 0.5:0.5:5, \"endpoints\", \"fill\"), [NaN(1, 5), 55, NaN(1, 4)])\n%!assert <*66025> (movfun (@sum, 1:10, 5, \"samplepoints\", 2:2:20, \"endpoints\", \"fill\"), [NaN, 6:3:27,NaN])\n%!assert <*66025> (movfun (@sum, 1:10, [2, 2], \"samplepoints\", 0.5:0.5:5, \"endpoints\", \"fill\"), [NaN(1, 4), 45, 54, NaN(1, 4)])\n%!assert <*66025> (movfun (@sum, 1:10, [0, 2.5], \"samplepoints\", 2:2:20, \"endpoints\", \"fill\"), [3:2:19, NaN])\n%!assert <*66025> (movfun (@sum, 1:10, 40, \"samplepoints\", 0.5:0.5:5, \"endpoints\", \"fill\"), NaN (1, 10))\n%!assert <*66025> (movfun (@sum, 1:10, [20, 20], \"samplepoints\", 0.5:0.5:5, \"endpoints\", \"fill\"), NaN (1, 10))\n\n## discard\n%!assert <*66025> (movfun (@sum, 1:10, 4,'samplepoints', 0.5:0.5:5, 'endpoints', 'discard'), [36, 44, 52])\n%!assert <*66025> (movfun (@sum, 1:10, 5,'samplepoints', 0.5:0.5:5, 'endpoints', 'discard'), 55)\n%!assert <*66025> (movfun (@sum, 1:10, [2, 2],'samplepoints', 0.5:0.5:5, 'endpoints', 'discard'), [45, 54])\n%!assert <*66025> (movfun (@sum, 1:10, 40,'samplepoints', 0.5:0.5:5, 'endpoints', 'discard'), NaN (1, 0))\n%!assert <*66025> (movfun (@sum, 1:10, [20, 20],'samplepoints', 0.5:0.5:5, 'endpoints', 'discard'), NaN (1, 0))\n\n## same\n%!assert <*66025> (movfun (@sum, 1:10, 4,'samplepoints', 0.5:0.5:5, 'endpoints', 'same'), [14, 18, 23, 29, 36, 44, 52, 59, 65, 70])\n%!assert <*66025> (movfun (@sum, 1:10, 5,'samplepoints', 0.5:0.5:5, 'endpoints', 'same'), [20, 25, 31, 38, 46, 55, 64, 72, 79, 85])\n%!assert <*66025> (movfun (@sum, 1:10, 5,'samplepoints', 2:2:20, 'endpoints', 'same'), [4, 6:3:27, 29])\n%!assert <*66025> (movfun (@sum, 1:10, [2, 2],'samplepoints', 0.5:0.5:5, 'endpoints', 'same'), [19, 24, 30, 37, 45, 54, 62, 69, 75, 80])\n%!assert <*66025> (movfun (@sum, 1:10, [0, 2.5],'samplepoints', 2:2:20, 'endpoints', 'same'), [3:2:19, 20])\n%!assert <*66025> (movfun (@sum, 1:10, 40,'samplepoints', 0.5:0.5:5, 'endpoints', 'same'), [395, 404, 413, 422, 431, 440, 449, 458, 467, 476])\n%!assert <*66025> (movfun (@sum, 1:10, [20, 20],'samplepoints', 0.5:0.5:5, 'endpoints', 'same'), [405, 414, 423, 432, 441, 450, 459, 468, 477, 486])\n\n## periodic\n%!assert <*66025> (movfun (@sum, 1:10, 4,'samplepoints', 0.5:0.5:5, 'endpoints', 'periodic'), [44, 42, 40, 38, 36, 44, 52, 50, 48, 46])\n%!assert <*66025> (movfun (@sum, 1:10, 5,'samplepoints', 0.5:0.5:5, 'endpoints', 'periodic'), 55(ones (1, 10)))\n%!assert <*66025> (movfun (@sum, 1:10, 5,'samplepoints', 2:2:20, 'endpoints', 'periodic'), [13, 6:3:27, 20])\n%!assert <*66025> (movfun (@sum, 1:10, [2, 2],'samplepoints', 0.5:0.5:5, 'endpoints', 'periodic'), [49, 48, 47, 46, 45, 54, 53, 52, 51, 50])\n%!assert <*66025> (movfun (@sum, 1:10, [0, 2.5],'samplepoints', 2:2:20, 'endpoints', 'periodic'), [3:2:19,11])\n%!assert <*66025> (movfun (@sum, 1:10, 40,'samplepoints', 0.5:0.5:5, 'endpoints', 'periodic'), 440(ones (1, 10)))\n%!assert <*66025> (movfun (@sum, 1:10, [20, 20],'samplepoints', 0.5:0.5:5, 'endpoints', 'periodic'), 441:450)\n\n## endpoints with multicolumn fcn output\n%!shared fcn\n%! fcn = @(y) [sum(y), max(y)];\n\n%!assert <*66025> (movfun (fcn, 1:10, 5), [6, 10:5:40, 34, 27; 3:10, 10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"shrink\"), [6, 10:5:40, 34, 27; 3:10, 10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"discard\"), [15:5:40; 5:10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"fill\"), [NaN, NaN, 15:5:40, NaN, NaN; 3:10, 10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", 5), [16, 15, 15:5:40, 39, 37; 5, 5, 5:10, 10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"same\"), [8, 11, 15:5:40, 44, 47; 3:10, 10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"periodic\"), [25, 20, 15:5:40, 35, 30; 10, 10, 5:10, 10, 10].')\n\n## uniform samplepoints\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"shrink\", \"samplepoints\", 2:2:20), [3:3:27, 19; 2:10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"discard\", \"samplepoints\", 2:2:20), [6:3:27; 3:10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"fill\", \"samplepoints\", 2:2:20), [NaN, 6:3:27, NaN; 2:10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", 5, \"samplepoints\", 2:2:20), [8, 6:3:27, 24; 5, 3:10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"same\", \"samplepoints\", 2:2:20), [4, 6:3:27, 29; 2:10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"periodic\", \"samplepoints\", 2:2:20), [13, 6:3:27, 20; 10, 3:10, 10].')\n\n## non-uniform samplepoints\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"samplepoints\", [1:9, 11]), [6, 10:5:35, 30, 34, 19; 3:9, 9, 10, 10].')\n%!assert <*66025> (movfun (fcn, 1:10, 5, \"endpoints\", \"shrink\", \"samplepoints\", [1:9, 11]), [6, 10:5:35, 30, 34, 19; 3:9, 9, 10, 10].')\n\n## Clear shared variables for remaining tests to reduce clutter on failure.\n%!shared\n\n## verify includenan and includemissing process on no-NaN cases without error.\n%!assert <*66025> (movfun (@sum, 1:10, 5, \"nancond\", \"includenan\"), movfun (@sum, 1:10, 5))\n%!assert <*66025> (movfun (@sum, 1:10, 5, \"nancond\", \"includemissing\"), movfun (@sum, 1:10, 5))\n\n## Verify proper function with empty dim input\n%!assert <*66025> (movfun (@sum, 1:10, 5, \"dim\", []), movfun (@sum, 1:10, 5))\n\n## Test valid nonnumeric inputs\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5), \"cdefghijjj\")\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"endpoints\", \"y\"), \"cdefghijyy\")\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"endpoints\", \"discard\"), \"efghij\")\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"endpoints\", \"same\"), \"cdefghijjj\")\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"endpoints\", \"periodic\"), \"cdefghijab\")\n%!assert <*66025> (movfun (@(x) [x(1,:) x(end,:)], \"abcdefghij\", 5), [\"aaabcdefgh\";\"cdefghijjj\"].')\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"samplepoints\", 2:2:20), \"bcdefghijj\")\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"samplepoints\", 2:2:20, \"endpoints\", \"y\"), \"bcdefghijy\")\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"samplepoints\", 2:2:20, \"endpoints\", \"discard\"), \"cdefghij\")\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"samplepoints\", 2:2:20, \"endpoints\", \"same\"), \"bcdefghijj\")\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"samplepoints\", 2:2:20, \"endpoints\", \"periodic\"), \"bcdefghija\")\n%!assert <*66025> (movfun (@(x) x(1,:), char (101:110), 100), \"eeeeeeeeee\")\n%!assert <*66025> (movfun (@(x) x(end,:), \"abcdefghij\", 5, \"samplepoints\", [2:2:18,21]), \"bcdefghiij\")\n\n\n## Suppress implicit type conversion warnings for char tests.\n%!test <*66025>\n%! fcn = @(x) x(end,:);\n%! x = \"abcdefghij\";\n%! w = 5;\n%! sp = 2:2:20;\n%! warnstate = warning (\"query\", \"Octave:num-to-str\");\n%! unwind_protect\n%!   warning (\"off\", \"Octave:num-to-str\");\n%!   assert (movfun (fcn, x, w, \"endpoints\", 121), \"cdefghijyy\");\n%!   assert (double (movfun (fcn, x, w, \"endpoints\", \"fill\")), [99:106, 0, 0]);\n%!   assert (movfun (fcn, x, w, \"samplepoints\", sp, \"endpoints\", 121), \"bcdefghijy\");\n%!   assert (double (movfun (fcn, x, w, \"samplepoints\", sp, \"endpoints\", \"fill\")), [98:106, 0]);\n%! unwind_protect_cleanup\n%!   warning (warnstate);\n%! end_unwind_protect\n\n%!assert <*66025> (movfun (@all, logical ([1,1,1,0,0,0,0,1,1,1]), 5), logical ([1, zeros(1,8), 1]))\n%!assert <*66025> (movfun (@all, logical ([1,1,1,0,0,0,0,1,1,1]), 5, \"samplepoints\", 2:2:20), logical ([1, 1, zeros(1,6), 1, 1]))\n\n## Test include/omitnan\n## No-change tests\n%!assert <66156> (movfun (@sum, 1:10, 5), [6, 10:5:40, 34, 27])\n%!assert <66156> (movfun (@sum, 1:10, 5, \"nancond\", \"omitnan\"), movfun (@sum, 1:10, 5))\n%!assert <66156> (movfun (@sum, 1:10, 5, \"nancond\", \"includenan\"), movfun (@sum, 1:10, 5))\n%!assert <66156> (movfun (@sum, 1:10, 5, \"nancond\", \"omitnan\", \"samplepoints\", 1:10), movfun (@sum, 1:10, 5))\n%!assert <66156> (movfun (@sum, 1:10, 5, \"nancond\", \"includenan\", \"samplepoints\", 1:10), movfun (@sum, 1:10, 5))\n\n## Shortcut returns\n%!assert <66156> (movfun (@sum, NaN (1, 10), 5), NaN (1, 10))\n%!assert <66156> (movfun (@sum, NaN (1, 10), 5, \"nancond\", \"includenan\"), NaN (1, 10))\n%!assert <66156> (movfun (@sum, NaN (1, 10), 5, \"nancond\", \"omitnan\"), NaN (1, 10))\n%!assert <66156> (movfun (@sum, NaN (1, 10), 5, \"nancond\", \"includenan\", \"nanval\", 3), NaN (1, 10))\n%!assert <66156> (movfun (@sum, NaN (1, 10), 5, \"nancond\", \"omitnan\", \"nanval\", 3), 3(ones (1, 10)))\n%!assert <66156> (movfun (@sum, [ones(4), NaN(4, 1)], 5, \"nancond\", \"includenan\"), [3;4;4;3].*[1, 1, 1, 1, NaN])\n%!assert <66156> (movfun (@sum, [ones(4), NaN(4, 1)], 5, \"nancond\", \"omitnan\"), [3;4;4;3].*[1, 1, 1, 1, NaN])\n\n## Standard calls - includenan.  Any NaN in window should return NaN even if\n## fcn would return a value.  Note that unlike others, movmin and movmax will\n## default to 'omitnan'.  movfun defaults to 'includenan' for all fcn unless\n## otherwise specified.\n%!assert <66156> (movfun (@min, [1:4, NaN(1,5), 10], 3), [1, 1, 2, NaN(1, 7)])\n%!assert <66156> (movfun (@min, [1:4, NaN(1,5), 10], 3, \"nancond\", \"includenan\"), [1, 1, 2, NaN(1, 7)])\n%!assert <66156> (movfun (@min, single ([1:4, NaN(1,5), 10]), 3), single ([1, 1, 2, NaN(1, 7)]))\n%!assert <66156> (movfun (@min, single ([1:4, NaN(1,5), 10]), 3, \"nancond\", \"includenan\"), single ([1, 1, 2, NaN(1, 7)]))\n%!assert <66156> (movfun (@min, [1:4, NaN(1,5), 10], 1, \"nancond\", \"includenan\"), [1:4, NaN(1,5), 10])\n%!assert <66156> (movfun (@min, [1:4, NaN(1,5), 10], 3, \"samplepoints\", [2:2:20]), [1:4, NaN(1,5), 10])\n%!assert <66156> (movfun (@min, [1:4, NaN(1,5), 10], 3, \"samplepoints\", [2:2:18, 21]), [1:4, NaN(1,5), 10])\n\n%!assert <66156> (movfun (@min, [1:10], 3), [1,1:9])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"shrink\"), [NaN, NaN, 2:7, NaN, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"discard\"), [NaN, 2:7, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"fill\"), [NaN, NaN, 2:7, NaN, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", -1), [NaN, NaN, 2:7, NaN, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"periodic\"), [NaN, NaN, 2:7, NaN, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"same\"), [NaN, NaN, 2:7, NaN, NaN])\n\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 1, \"endpoints\", \"shrink\"), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 1, \"endpoints\", \"discard\"), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 1, \"endpoints\", \"fill\"), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 1, \"endpoints\", -1), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 1, \"endpoints\", \"periodic\"), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 1, \"endpoints\", \"same\"), [NaN, 2:9, NaN])\n\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"samplepoints\", 2:2:20), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"shrink\", \"samplepoints\", 2:2:20), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"discard\", \"samplepoints\", 2:2:20), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"fill\", \"samplepoints\", 2:2:20), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", -1, \"samplepoints\", 2:2:20), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"periodic\", \"samplepoints\", 2:2:20), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"endpoints\", \"same\", \"samplepoints\", 2:2:20), [NaN, 2:9, NaN])\n\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 5, \"samplepoints\", 2:2:20), [NaN, NaN, 2:7, NaN, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 5, \"endpoints\", \"shrink\", \"samplepoints\", 2:2:20), [NaN, NaN, 2:7, NaN, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 5, \"endpoints\", \"discard\", \"samplepoints\", 2:2:20), [NaN, 2:7, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 5, \"endpoints\", \"fill\", \"samplepoints\", 2:2:20), [NaN, NaN, 2:7, NaN, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 5, \"endpoints\", -1, \"samplepoints\", 2:2:20), [NaN, NaN, 2:7, NaN, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 5, \"endpoints\", \"periodic\", \"samplepoints\", 2:2:20), [NaN, NaN, 2:7, NaN, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 5, \"endpoints\", \"same\", \"samplepoints\", 2:2:20), [NaN, NaN, 2:7, NaN, NaN])\n\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 1, \"samplepoints\", [0, 2:9, 11]), [NaN, 2:9, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 3, \"samplepoints\", [0, 2:9, 11]), [NaN, 2,2:8, NaN])\n%!assert <66156> (movfun (@min, [NaN,2:9,NaN], 5, \"samplepoints\", [0, 2:9, 11]), [NaN(1,2), 2, 2:6, NaN(1,2)])\n\n## Standard calls - omitnan\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3), [NaN(1,3), 12, 15, NaN(1,4), 19])\n%!assert <66156> (movfun (@sum, single ([1, NaN, 3:6, NaN, NaN, 9, 10]), 3), single ([NaN(1,3), 12, 15, NaN(1,4), 19]))\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\"), [1, 4, 7, 12, 15, 11, 6, 9, 19, 19])\n%!assert <66156> (movfun (@sum, single ([1, NaN, 3:6, NaN, NaN, 9, 10]), 3, \"nancond\", \"omitnan\"), single ([1, 4, 7, 12, 15, 11, 6, 9, 19, 19]))\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 30, \"nancond\", \"omitnan\"), 38(ones(1,10)))\n\n## EndPoints, no samplepoints\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"shrink\"), [1, 4, 7, 12, 15, 11, 6, 9, 19, 19])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"discard\"), [4, 7, 12, 15, 11, 6, 9, 19])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"fill\"), [NaN, 4, 7, 12, 15, 11, 6, 9, 19, NaN])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", 3), [4, 4, 7, 12, 15, 11, 6, 9, 19, 22])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"same\"), [2, 4, 7, 12, 15, 11, 6, 9, 19, 29])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"periodic\"), [11, 4, 7, 12, 15, 11, 6, 9, 19, 20])\n%!assert <66156> (movfun (@sum, [1:9,NaN], [0, 2], \"nancond\", \"omitnan\", \"endpoints\", -10), [6:3:24, 17, -1, -20])\n\n## EndPoints, uniform samplepoints, wlen too small\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"shrink\", \"samplepoints\", 2:2:20), [1, NaN, 3:6, NaN, NaN, 9, 10])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"discard\", \"samplepoints\", 2:2:20), [1, NaN, 3:6, NaN, NaN, 9, 10])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"fill\", \"samplepoints\", 2:2:20), [1, NaN, 3:6, NaN, NaN, 9, 10])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", 3, \"samplepoints\", 2:2:20), [1, NaN, 3:6, NaN, NaN, 9, 10])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"same\", \"samplepoints\", 2:2:20), [1, NaN, 3:6, NaN, NaN, 9, 10])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"periodic\", \"samplepoints\", 2:2:20), [1, NaN, 3:6, NaN, NaN, 9, 10])\n\n## EndPoints, uniform samplepoints\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 5, \"nancond\", \"omitnan\", \"endpoints\", \"shrink\", \"samplepoints\", 2:2:20), [1, 4, 7, 12, 15, 11, 6, 9, 19, 19])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 5, \"nancond\", \"omitnan\", \"endpoints\", \"discard\", \"samplepoints\", 2:2:20), [4, 7, 12, 15, 11, 6, 9, 19])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 5, \"nancond\", \"omitnan\", \"endpoints\", \"fill\", \"samplepoints\", 2:2:20), [NaN, 4, 7, 12, 15, 11, 6, 9, 19, NaN])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 5, \"nancond\", \"omitnan\", \"endpoints\", 3, \"samplepoints\", 2:2:20), [4, 4, 7, 12, 15, 11, 6, 9, 19, 22])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 5, \"nancond\", \"omitnan\", \"endpoints\", \"same\", \"samplepoints\", 2:2:20), [2, 4, 7, 12, 15, 11, 6, 9, 19, 29])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 5, \"nancond\", \"omitnan\", \"endpoints\", \"periodic\", \"samplepoints\", 2:2:20), [11, 4, 7, 12, 15, 11, 6, 9, 19, 20])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 50, \"nancond\", \"omitnan\", \"endpoints\", \"periodic\", \"samplepoints\", 2:2:20), [99, 94, 89, 94, 94, 91, 96, 101, 96, 96])\n%!assert <66156> (movfun (@sum, [1:9,NaN], [0, 4], \"nancond\", \"omitnan\", \"endpoints\", -10, \"samplepoints\", 2:2:20), [6:3:24, 17, -1, -20])\n\n## EndPoints, nonuniform samplepoints\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 3, \"nancond\", \"omitnan\", \"endpoints\", \"shrink\", \"samplepoints\", [0, 2:9, 11]), [1, 3, 7, 12, 15, 11, 6, 9, 9, 10])\n%!assert <66156> (movfun (@sum, [1, NaN, 3:6, NaN, NaN, 9, 10], 5, \"nancond\", \"omitnan\", \"endpoints\", \"shrink\", \"samplepoints\", [0, 2:9, 11]), [1, 8, 12, 18, 18, 15, 20, 15, 19, 19])\n\n## Test samplepoint and omitnan calls that create 1-element deep blocks requiring arrayfun\n%!assert <66156> (movfun (@sum, 1:10, 5, \"samplepoints\", [1:3, 9, 14, 17, 20, 28:30]), [6, 6, 6, 4, 5, 6, 7, 27, 27, 27])\n\n\n## Test input validation\n%!error <Invalid call> movfun ()\n%!error <Invalid call> movfun (@min)\n%!error <Invalid call> movfun (@min, 1:5)\n%!error <FCN must be a valid function handle> movfun (1, 1:10, 3)\n%!error <FCN must be a valid function handle> movfun (true, 1:10, 3)\n%!error <FCN must be a valid function handle> movfun ({\"foo\"}, 1:10, 3)\n%!error <FCN must be a valid function handle> movfun (struct (\"a\", \"b\"), 1:10, 3)\n%!error <WLEN must be numeric> movfun (@sum, 1:10, 'f')\n%!error <WLEN must be numeric> movfun (@sum, 1:10, {1, 2})\n%!error <Each PROPERTY must have a VALUE> movfun (@sum, 1:10, 3, \"EndPoints\")\n%!error <Each PROPERTY must have a VALUE> movfun (@sum, 1:10, 3, \"EndPoints\", 3, \"dim\")\n%!error <Each PROPERTY must have a VALUE> movfun (@sum, 1:10, 3, \"EndPoints\", \"dim\", 2)\n%!error <PROPERTY name must be> movfun (@sum, 1:10, 3, 123, 3)\n%!error <PROPERTY name must be> movfun (@sum, 1:10, 3, true, 3)\n%!error <PROPERTY name must be> movfun (@sum, 1:10, 3, {\"foo\"}, 3)\n%!error <PROPERTY name must be> movfun (@sum, 1:10, 3, struct (), 3)\n%!error <PROPERTY name must be> movfun (@sum, 1:10, 3, [\"foo\"; \"bar\"], 3)\n%!error <unknown PROPERTY 'foo'> movfun (@sum, 1:10, 3, \"foo\", 3)\n%!error <DIM must be a > movfun (@sum, 1:10, 3, \"dim\", -1)\n%!error <DIM must be a > movfun (@sum, 1:10, 3, \"dim\", 0)\n%!error <DIM must be a > movfun (@sum, 1:10, 3, \"dim\", 1.5)\n%!error <DIM must be a > movfun (@sum, 1:10, 3, \"dim\", {1})\n%!error <DIM must be a > movfun (@sum, 1:10, 3, \"dim\", true)\n%!error <DIM must be a > movfun (@sum, 1:10, 3, \"dim\", \"c\")\n%!error <DIM must be a > movfun (@sum, 1:10, 3, \"dim\", [1, 2])\n%!error <ENDPOINTS must be a > movfun (@sum, 1:10, 3, \"endpoints\", [1 2])\n%!error <ENDPOINTS must be a > movfun (@sum, 1:10, 3, \"endpoints\", {1})\n%!error <ENDPOINTS must be a > movfun (@sum, 1:10, 3, \"endpoints\", true)\n%!error <ENDPOINTS must be a > movfun (@sum, 1:10, 3, \"endpoints\", \"foo\")\n%!error <ENDPOINTS must be a > movfun (@sum, 1:10, 3, \"endpoints\", \"b\")\n%!error <ENDPOINTS must be a > movfun (@sum, 1:10, 3, \"endpoints\", {\"shrink\"})\n%!error <ENDPOINTS must be a > movfun (@sum, \"abcde\", 3, \"endpoints\", true)\n%!error <ENDPOINTS must be a > movfun (@sum, \"abcde\", 3, \"endpoints\", \"ab\")\n%!error <NANCOND must be> movfun (@sum, 1:10, 3, \"nancond\", 3)\n%!error <NANCOND must be> movfun (@sum, 1:10, 3, \"nancond\", \"foo\")\n%!error <NANCOND must be> movfun (@sum, 1:10, 3, \"nancond\", {\"includenan\"})\n%!error <NANVAL must be a> movfun (@sum, 1:10, 3, \"nancond\", \"omitnan\", \"nanval\", \"a\")\n%!error <NANVAL must be a> movfun (@sum, 1:10, 3, \"nancond\", \"omitnan\", \"nanval\", true)\n%!error <NANVAL must be a> movfun (@sum, 1:10, 3, \"nancond\", \"omitnan\", \"nanval\", [1 2])\n%!error <NANVAL must be a> movfun (@sum, 1:10, 3, \"nancond\", \"omitnan\", \"nanval\", NaN (2))\n%!error <OUTDIM must be a> movfun (@sum, 1:10, 3, \"outdim\", -1)\n%!error <OUTDIM must be a> movfun (@sum, 1:10, 3, \"outdim\", 0)\n%!error <OUTDIM must be a> movfun (@sum, 1:10, 3, \"outdim\", [1 -1])\n%!error <OUTDIM must be a> movfun (@sum, 1:10, 3, \"outdim\", 1.5)\n%!error <OUTDIM must be a> movfun (@sum, 1:10, 3, \"outdim\", \"a\")\n%!error <OUTDIM must be a> movfun (@sum, 1:10, 3, \"outdim\", {1})\n%!error <OUTDIM must be a> movfun (@sum, 1:10, 3, \"outdim\", true)\n%!error <SAMPLEPOINTS must be a> movfun (@sum, [1, 2, 3], 3, \"samplepoints\", \"foo\")\n%!error <SAMPLEPOINTS must be a> movfun (@sum, [1, 2, 3], 3, \"samplepoints\", [1, 1, 3])\n%!error <SAMPLEPOINTS must be a> movfun (@sum, [1, 2, 3], 3, \"samplepoints\", [1, 3, 2])\n%!error <SAMPLEPOINTS must be a> movfun (@sum, [1, 2, 3], 3, \"samplepoints\", {1, 2, 3})\n%!error <SAMPLEPOINTS must be a> movfun (@sum, [1, 2, 3, 4], 3, \"samplepoints\", [1 3; 2 4])\n%!error <when SamplePoints are not uniformly spaced> movfun (@sum, 1:5, 3, \"SamplePoints\", [1:4, 4.5], \"EndPoints\", \"fill\")\n%!error <when SamplePoints are not uniformly spaced> movfun (@sum, 1:5, 3, \"SamplePoints\", [1:4, 4.5], \"EndPoints\", 2)\n%!error <SamplePoints must be the same size as x> movfun (@sum, 1:5, 3, \"SamplePoints\", 1:4)\n%!error <SamplePoints must be the same size as x> movfun (@sum, magic (4), 3, \"dim\", 2, \"SamplePoints\", [1, 2])\n%!error <WLEN must be numeric> movfun (@min, 1:3, \"nancond\", \"omitnan\")\n## FIXME: This test is commented out until OUTDIM validation is clarified.\n%!#error <OUTDIM \\(5\\) is larger than largest available dimension \\(3\\)>\n%! movfun (@min, ones (6,3,4), 3, \"outdim\", 5)\n\n"
  },
  {
    "path": "scripts/signal/movslice.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{slcidx} =} movslice (@var{N}, @var{wlen})\n## @deftypefnx {} {@var{slcidx} =} movslice (@var{N}, @var{wlen}, @var{samplepoints})\n## @deftypefnx {} {[@var{slcidx}, @var{C}, @var{Cpre}, @var{Cpost}, @var{win}, @var{wlen}, @var{scalar_wlen}] =} movslice (@dots{})\n## Generate indices to slice a vector of length @var{N} into windows of length\n## @var{wlen}.\n##\n## The input @var{N} must be a positive integer.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array.  The elements included in the moving window\n## will depend on the size and value of @var{wlen} as well as whether the\n## @var{samplepoints} input was specified.\n##\n## The optional input @var{samplepoints} is a sorted, numeric vector of unique\n## positions of the @var{N} data points.  The default value is the vector\n## @code{[1 : @var{N}]}.  When a non-default @var{samplepoints} vector is\n## specified, the moving window length @var{wlen} is measured\n## against the @var{samplepoints} positions to determine which points are\n## included in each window slice.  It should be noted that @var{samplepoints}\n## need not be uniformly spaced which can result in window slices containing\n## different numbers of points.  Because of this, as specified below the\n## shape and content of some @code{movslice} outputs will be different when\n## a non-default @var{samplepoints} is used.\n##\n## The moving window size and included elements will be defined as follows:\n##\n## @itemize\n## @item\n## If @var{samplepoints} has the default value of @code{1:@var{N}} (or has\n## not been specified):\n##\n## @itemize\n## @item\n## For integer-valued @var{wlen}:\n##\n## @itemize\n## @item\n## For odd, integer-valued, scalar @var{wlen} the window is symmetric and\n## includes @w{@code{(@var{wlen} - 1) / 2}}@ elements on either side of the\n## central element.  For example, the window slice at index 5 with a window\n## length of 3 will include the elements @w{@code{[4, 5, 6]}}.\n##\n## @item\n## For even, integer-valued, scalar @var{wlen} the window is asymmetric and\n## has @w{@code{@var{wlen}/2}}@ elements to the left of the central element\n## and @w{@code{@var{wlen}/2 - 1}}@ elements to the right of the central\n## element.  For example, the window slice at index 5 with a window length of\n## 4 will include the elements @w{@code{[3, 4, 5, 6]}}.\n##\n## @item\n## For integer-valued vector @var{wlen} of the form\n## @w{@code{[@var{nb}, @var{na}]}}@ where @var{nb} and @var{na} are integer\n## valued the window includes @var{nb} elements to the left of the central\n## element and @var{na} elements to the right of the central element.  For\n## example, given @w{@code{@var{wlen} = [3, 1]}}, the window slice at index 5\n## will include the elements @w{@code{[2, 3, 4, 5, 6]}}.\n## @end itemize\n##\n## @item\n## For non-integer-valued scalar @var{wlen}:\n##\n## @itemize\n## @item\n## Non-integer-valued scalar @var{wlen} will be converted to\n## two-element vector form with\n## @w{@code{@var{nb} = @var{na} = fix (@var{wlen} / 2)}}, and then processed\n## as stated above for integer-valued vectors.  For example, the window slice\n## at index 5 with @w{@code{@var{wlen} = 2.5}}@ will include the elements\n## @w{@code{[3, 4, 5, 6, 7]}}.\n##\n## @item\n## Non-integer-valued vector @var{wlen} will be truncated to integer values\n## with @w{@code{@var{wlen} = fix (@var{wlen})}}@ and then processed as\n## stated above for integer-valued vectors.  For example, the window slice\n## at index 5 with @w{@code{@var{wlen} = [1.2, 2.3]}}@ will include the\n## elements @w{@code{[4, 5, 6, 7]}}.\n## @end itemize\n## @end itemize\n##\n## @item\n## If @var{samplepoints} has been specified with a non-default vector:\n##\n## @itemize\n## @item\n## For vector @var{wlen} specified as @w{@code{[@var{nb}, @var{na}]}}, the\n## window will include all points within a distance less than or equal to\n## @var{nb} before and @var{na} after the central element's position, with\n## point positions defined by the elements of @var{samplepoints}.  For\n## example, at index 5 with @w{@code{@var{wlen} = [2, 3]}}@ and the 3rd-8th\n## elements of @var{samplepoints} being @w{@code{[1, 3, 5, 7, 8 ,9]}}, the\n## window slice will include the elements @w{@code{[4, 5, 6, 7]}}@\n## corresponding to @var{samplepoints} @w{@code{[3, 5, 7, 8]}}.\n##\n## @item\n## Scalar @var{wlen} will be converted to two-element vector form with\n## @w{@code{@var{nb} = @var{na} = @var{wlen} / 2}}.  The window will then\n## include all points within a distance of less than or equal to @var{nb}\n## before and less than, but not equal to, @var{na} after the central\n## element's position, @w{@code{[@var{nb}, @var{na})}}.  For example, at\n## index 5 with @w{@code{@var{wlen} = [2, 3]}}@ and the 3rd-8th elements of\n## @var{samplepoints} being @w{@code{[1, 3, 5, 7, 8 ,9]}}, the window slice\n## will include the elements @w{@code{[4, 5, 6]}}@ corresponding to\n## @var{samplepoints} @w{@code{[3, 5, 7]}}.\n## @end itemize\n## @end itemize\n##\n## The output @var{slcidx} is an array of indices of the slices of the vector.\n##\n## @itemize\n## @item\n## If @var{samplepoints} is default or unspecified, @var{slcidx} will contain\n## only the indices of the slices that fit fully within the vector.  Each\n## column will be the indices of one slice as the window moves from left to\n## right.  The slices will have @w{@code{fix (@var{wlen})}}@ elements for\n## scalar @var{wlen}, or @w{@code{@var{nb} + @var{na} + 1}}@ elements for array\n## valued @var{wlen}.\n##\n## @item\n## If a non-default @var{samplepoints} has been specified, @var{slcidx} will\n## be a 2x@var{N} array with the first and second rows containing the first\n## and last elements of each slice, respectively.\n## @end itemize\n##\n## Optional output @var{C} is a row vector of window center positions where\n## the window stays fully within the vector.\n##\n## Optional outputs @var{Cpre} and @var{Cpost} contain the vector elements at\n## the start and end of the vector, respectively, that result in the window\n## extending beyond the ends of the vector.\n##\n## Optional output @var{win} contains information for creating the moving\n## window.\n##\n## @itemize\n## @item\n## If @var{samplepoints} is default or unspecified, @var{win} is a column\n## vector with the same number of rows as @var{slcidx} that contains the\n## moving window defined as a center relative position stencil.\n##\n## @item\n## If a non-default @var{samplepoints} has been specified, @var{win} will\n## be a 2x@var{N} array with the first and second rows containing the left and\n## right bounds of each window slice, respectively, using the same\n## coordinates as @var{samplepoints}.  These bounds may lie outside of the\n## position vector specified by @var{samplepoints}.\n## @end itemize\n##\n## Optional output @var{wlen} returns the window length used by\n## @code{movslice} in two-element @w{@code{[@var{nb}, @var{na}]}}@ form.\n##\n## Optional logical output @var{scalar_wlen} returns the scalar or vector\n## state of the input @var{wlen} so that calling functions can determinine\n## whether the moving window should be inclusive or exclusive of the right\n## window endpoints.  I.e., inclusive @w{@code{[@var{nb}, @var{na}]}}@ for\n## vector @var{wlen} or exclusive @w{@code{[@var{nb}, @var{na})}}@ for scalar\n## @var{wlen}.\n##\n## @seealso{movfun}\n## @end deftypefn\n\nfunction [slcidx, C, Cpre, Cpost, win, wlen, scalar_wlen] = movslice (N, wlen, samplepoints = [])\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  ## Validate N\n  if (! (isnumeric (N) && isscalar (N) && isindex (N)))\n    error (\"Octave:invalid-input-arg\",\n           \"movslice: N must be a positive integer\");\n  endif\n\n  ## Validate window length\n  if (! (isnumeric (wlen) && all (wlen >= 0)))\n    error (\"Octave:invalid-input-arg\",\n           \"movslice: WLEN must be a positive scalar or 2-element array\");\n  endif\n\n  ## Validate or set default samplepoints\n  if (isempty (samplepoints))\n    samplepoints = [1:N].';\n    standard_samplepoints = true;\n  else\n    samplepoints = samplepoints(:);\n    standard_samplepoints = all (diff (samplepoints, 1, 1) == 1);\n    if (numel (samplepoints) != N)\n      error (\"Octave:invalid-input-arg\",\n             \"movslice: SamplePoints must have length N\");\n    endif\n  endif\n\n  scalar_wlen = isscalar (wlen);\n  if (all (numel (wlen) != [1, 2]))\n    error (\"Octave:invalid-input-arg\",\n           \"movslice: WLEN must be a positive scalar or 2-element array\");\n  endif\n\n  ## Process multiple forms of wlen.\n  intvalued_wlen = all (fix (wlen) == wlen);\n\n  if (standard_samplepoints && intvalued_wlen && scalar_wlen)\n    if (mod (wlen, 2) == 1)\n      ## Symmetric window\n      nb = na = (wlen - 1) / 2;\n      wlen = [nb, na];\n    else\n      ## Asymmetric window\n      nb = wlen / 2;\n      na = nb - 1;\n      wlen = [nb, na];\n    endif\n  else\n    if (scalar_wlen)\n      wlen = [wlen, wlen] / 2;\n    endif\n\n    if (standard_samplepoints)\n      wlen = fix (wlen);\n    endif\n  endif\n\n  if (standard_samplepoints)\n    Cpre  = 1 : min (wlen(1), N);     # centers that can't fit the pre-window\n    Cnf   = max (1, N - wlen(2) + 1); # first center that can't fit the post-window\n    Cpost = Cnf:N;                     # centers that can't fit centered post-window\n    C     = (wlen(1) + 1):(Cnf - 1);\n    ## Convert C to minimum unsigned integer array large enough to hold indices.\n    ## Because the size of slcidx is numel(C) x numel(win), for large N  and/or\n    ## window sizes this can save significant memory in resulting slcidx array\n    ## over using an 8 byte double.\n    if (N <= 255)\n      C = uint8 (C);\n    elseif (N <= 65535)\n      C = uint16 (C);\n    elseif (N <= 4294967295)\n      C = uint32 (C);\n    else\n      C = uint64 (C);\n    endif\n    win   = (-wlen(1):wlen(2)).';\n    slcidx = C + win;\n\n  else\n\n    sp_end_spacing = [samplepoints(2) - samplepoints(1), ...\n                      samplepoints(end) - samplepoints(end-1)];\n    Cpre = samplepoints - wlen(1) <= samplepoints(1) - sp_end_spacing(1);\n\n    if (! scalar_wlen)\n      Cpost =  samplepoints + wlen(2) >= samplepoints(end) + sp_end_spacing(2);\n    else\n      Cpost = samplepoints + wlen(2) > samplepoints(end) + sp_end_spacing(2);\n    endif\n\n    win = [samplepoints.' - wlen(1); samplepoints.' + wlen(2)];\n\n    C = ! (Cpre | Cpost);\n\n    ## Convert to linear indices.\n    Cpre = [1:N](Cpre);\n    Cpost = [1:N](Cpost);\n    C = [1:N](C);\n\n    ## Create a 2xN index of start and end samplepoint indices for each slice.\n    ## Use same uintX class assignment as above.\n    if (N <= 255)\n      slccls = \"uint8\";\n    elseif (N <= 65535)\n      slccls = \"uint16\";\n    elseif (N <= 4294967295)\n      slccls = \"uint32\";\n    else\n      slccls = \"uint64\";\n    endif\n\n    slcidx = zeros (2, N, slccls);\n    [slcidx(1,:), ~] = find (diff ([false(1, N); samplepoints >= win(1, :)], 1, 1));\n\n    if (scalar_wlen)\n      [slcidx(2,:), ~] = find (-diff ([(win(2, :) > samplepoints); false(1, N)], 1, 1));\n    else\n      [slcidx(2,:), ~] = find (diff ([(win(2, :) >= samplepoints); false(1, N)], 1, 1));\n    endif\n  endif\n\nendfunction\n\n\n%!assert (double (movslice (10, 2)), [1:9; 2:10])\n%!assert (double (movslice (10, 9)), [1:9; 2:10].')\n%!assert (double (movslice (10, [1, 0])), [1:9; 2:10])\n%!assert (double (movslice (10, [1, 1])), [1:8; 2:9; 3:10])\n%!assert (double (movslice (10, [1, 1])), [1:8; 2:9; 3:10])\n%!assert (double (movslice (10, [3, 2])), [1:5] + [0:5].')\n\n%!test\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, 4);\n%! assert (double (sl), [1:7; 2:8; 3:9; 4:10]);\n%! assert (double (c), 3:9);\n%! assert (cpre, 1:2);\n%! assert (cpost, 10);\n%! assert (win, [-2:1:1].');\n%! assert (wlen, [2, 1]);\n%! assert (sw, true);\n\n%!test\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, [2, 2]);\n%! assert (double (sl), [1:6; 2:7; 3:8; 4:9; 5:10]);\n%! assert (double (c), 3:8);\n%! assert (cpre, 1:2);\n%! assert (cpost, 9:10);\n%! assert (win, [-2:1:2].');\n%! assert (wlen, [2, 2]);\n%! assert (sw, false);\n\n%!test\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, 3);\n%! assert (double (sl), [1:8; 2:9; 3:10]);\n%! assert (double (c), 2:9);\n%! assert (cpre, 1);\n%! assert (cpost, 10);\n%! assert (win, [-1, 0, 1].');\n%! assert (wlen, [1, 1]);\n%! assert (sw, true);\n\n%!test\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, [1, 1]);\n%! assert (double (sl), [1:8; 2:9; 3:10]);\n%! assert (double (c), 2:9);\n%! assert (cpre, 1);\n%! assert (cpost, 10);\n%! assert (win, [-1, 0, 1].');\n%! assert (wlen, [1, 1]);\n%! assert (sw, false);\n\n%!test\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, 10);\n%! assert (double (sl), [1:10].');\n%! assert (double (c), 6);\n%! assert (cpre, 1:5);\n%! assert (cpost, 7:10);\n%! assert (win, [-5:1:4].');\n%! assert (wlen, [5, 4]);\n%! assert (sw, true);\n\n\n## Verify uint output.  Don't test uint64 due to excessive memory usage.\n%!test\n%! [sl, c] = movslice (10, 10);\n%! assert (class (sl), \"uint8\");\n%! assert (class (c), \"uint8\");\n%! [sl, c] = movslice (1000, 1000);\n%! assert (class (sl), \"uint16\");\n%! assert (class (c), \"uint16\");\n%! [sl, c] = movslice (100000, 100000);\n%! assert (class (sl), \"uint32\");\n%! assert (class (c), \"uint32\");\n\n## Test non-integer wlen\n%!assert <*65928> (double (movslice (10, 2.2)), [1:8; 2:9; 3:10])\n%!assert <*65928> (double (movslice (10, 9.1)), [1:9; 2:10].')\n%!assert <*65928> (double (movslice (10, 9.999)), [1:9; 2:10].')\n%!assert <*65928> (double (movslice (10, [3.2, 0])), [1:7] + [0:3].')\n%!assert <*65928> (double (movslice (10, [3.2, 2.1])), [1:5] + [0:5].')\n\n## Test wlen extending beyond N\n%!test <*65928>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, 11);\n%! assert (double (sl), zeros (11, 0));\n%! assert (double (c), zeros (1, 0));\n%! assert (cpre, 1:5);\n%! assert (cpost, 6:10);\n%! assert (win, [-5:1:5].');\n%! assert (wlen, [5, 5]);\n%! assert (sw, true);\n\n%!test <*65928>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, 99);\n%! assert (double (sl), zeros (99, 0));\n%! assert (double (c), zeros (1, 0));\n%! assert (cpre, 1:10);\n%! assert (cpost, 1:10);\n%! assert (win, [-49:1:49].');\n%! assert (wlen, [49, 49]);\n%! assert (sw, true);\n\n%!test <*65928>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, [0, 20]);\n%! assert (double (sl), zeros (21, 0));\n%! assert (double (c), zeros (1, 0));\n%! assert (cpre, zeros (1, 0));\n%! assert (cpost, 1:10);\n%! assert (win, [0:20].');\n%! assert (wlen, [0, 20]);\n%! assert (sw, false);\n\n%!test <*65928>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, [5, 6]);\n%! assert (double (sl), zeros (12, 0));\n%! assert (double (c), zeros (1, 0));\n%! assert (cpre, 1:5);\n%! assert (cpost, 5:10);\n%! assert (win, [-5:1:6].');\n%! assert (wlen, [5, 6]);\n%! assert (sw, false);\n\n## Test wlen = 1 or [0, 0]\n%!test <*65928>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, 1);\n%! assert (double (sl), 1:10);\n%! assert (double (c), 1:10);\n%! assert (cpre, zeros (1,0));\n%! assert (cpost, zeros (1,0));\n%! assert (win, 0);\n%! assert (wlen, [0, 0]);\n%! assert (sw, true);\n\n%!test <*65928>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, [0, 0]);\n%! assert (double (sl), 1:10);\n%! assert (double (c), 1:10);\n%! assert (cpre, zeros (1,0));\n%! assert (cpost, zeros (1,0));\n%! assert (win, 0);\n%! assert (wlen, [0, 0]);\n%! assert (sw, false);\n\n## Test samplepoints\n%!test <*66025> # Standard samplepoints, scalar integer wlen, no output change\n%! [sl1, c1, cpre1, cpost1, win1, wlen1, sw1] = movslice (10, 3);\n%! [sl2, c2, cpre2, cpost2, win2, wlen2, sw2] = movslice (10, 3, 1:10);\n%! assert (sl1, sl2);\n%! assert (c1, c2);\n%! assert (cpre1, cpre2);\n%! assert (cpost1, cpost2);\n%! assert (win1, win2);\n%! assert (wlen1, wlen2);\n%! assert (sw1, sw2);\n\n%!test <*66025> # Standard samplepoints, vector integer wlen, no output change\n%! [sl1, c1, cpre1, cpost1, win1, wlen1, sw1] = movslice (10, [2, 3]);\n%! [sl2, c2, cpre2, cpost2, win2, wlen2, sw2] = movslice (10, [2, 3], 1:10);\n%! assert (sl1, sl2);\n%! assert (c1, c2);\n%! assert (cpre1, cpre2);\n%! assert (cpost1, cpost2);\n%! assert (win1, win2);\n%! assert (wlen1, wlen2);\n%! assert (sw1, sw2);\n\n%!test <*66025> # Standard samplepoints, decimal wlen, no output change\n%! [sl1, c1, cpre1, cpost1, win1, wlen1, sw1] = movslice (10, 3.3);\n%! [sl2, c2, cpre2, cpost2, win2, wlen2, sw2] = movslice (10, 3.3, 1:10);\n%! assert (sl1, sl2);\n%! assert (c1, c2);\n%! assert (cpre1, cpre2);\n%! assert (cpost1, cpost2);\n%! assert (win1, win2);\n%! assert (wlen1, wlen2);\n%! assert (sw1, sw2);\n\n%!test <*66025>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, 4, 0.5:0.5:5);\n%! assert (double(sl), [1, 1, 1, 1, 1:6; 4:10, 10, 10, 10]);\n%! assert (c, 5:7);\n%! assert (cpre, 1:4);\n%! assert (cpost, 8:10);\n%! assert (win, [0.5:0.5:5] + [-2;2]);\n%! assert (wlen, [2, 2]);\n%! assert (sw, true);\n\n%!test <*66025>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, [2, 2], 0.5:0.5:5);\n%! assert (double(sl), [1, 1, 1, 1, 1:6; 5:10, 10, 10, 10, 10]);\n%! assert (c, 5:6);\n%! assert (cpre, 1:4);\n%! assert (cpost, 7:10);\n%! assert (win, [0.5:0.5:5] + [-2;2]);\n%! assert (wlen, [2, 2]);\n%! assert (sw, false);\n\n%!test <*66025>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, 4.1, 0.5:0.5:5);\n%! assert (double(sl), [1, 1, 1, 1, 1:6; 5:10, 10, 10, 10, 10]);\n%! assert (c, 5:6);\n%! assert (cpre, 1:4);\n%! assert (cpost, 7:10);\n%! assert (win, [0.5:0.5:5] + [-2.05;2.05]);\n%! assert (wlen, [2.05, 2.05]);\n%! assert (sw, true);\n\n%!test <*66025>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, 4, [1:9, 11]);\n%! assert (double(sl), [1, 1, 1:7, 9; 2:9, 9, 10]);\n%! assert (c, 3:10);\n%! assert (cpre, 1:2);\n%! assert (cpost, ones (1,0));\n%! assert (win, [1:9, 11] + [-2;2]);\n%! assert (wlen, [2, 2]);\n%! assert (sw, true);\n\n%!test <*66025>\n%! [sl, c, cpre, cpost, win, wlen, sw] = movslice (10, [2, 2], [1:9, 11]);\n%! assert (double(sl), [1, 1, 1:7, 9; 3:9, 9, 10, 10]);\n%! assert (c, 3:9);\n%! assert (cpre, 1:2);\n%! assert (cpost, 10);\n%! assert (win, [1:9, 11] + [-2;2]);\n%! assert (wlen, [2, 2]);\n%! assert (sw, false);\n\n\n## Test input validation\n%!error <Invalid call> movslice ()\n%!error <Invalid call> movslice (1)\n%!error <N must be a positive integer> movslice ([1 2], 2)\n%!error <N must be a positive integer> movslice (0, 2)\n%!error <N must be a positive integer> movslice (\"N\", 2)\n%!error <N must be a positive integer> movslice ({1}, 2)\n%!error <WLEN must be a positive scalar or 2-element array> movslice (5, {1})\n%!error <WLEN must be a positive scalar or 2-element array> movslice (5, -1)\n%!error <WLEN must be a positive scalar or 2-element array> movslice (5, \"a\")\n%!error <WLEN must be a positive scalar or 2-element array> movslice (5, [1, 2, 3])\n%!error <WLEN must be a positive scalar or 2-element array> movslice (5, [-1, 2])\n%!error <WLEN must be a positive scalar or 2-element array> movslice (5, {1, 2})\n%!error <WLEN must be a positive scalar or 2-element array> movslice (5, \"ab\")\n%!error <SamplePoints must have length N> movslice (10, 2, 1:5)\n"
  },
  {
    "path": "scripts/signal/periodogram.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{Pxx}, @var{w}] =} periodogram (@var{x})\n## @deftypefnx {} {[@var{Pxx}, @var{w}] =} periodogram (@var{x}, @var{win})\n## @deftypefnx {} {[@var{Pxx}, @var{w}] =} periodogram (@var{x}, @var{win}, @var{nfft})\n## @deftypefnx {} {[@var{Pxx}, @var{f}] =} periodogram (@var{x}, @var{win}, @var{nfft}, @var{Fs})\n## @deftypefnx {} {[@var{Pxx}, @var{f}] =} periodogram (@dots{}, \"@var{range}\")\n## @deftypefnx {} {} periodogram (@dots{})\n## Return the periodogram (Power Spectral Density) of @var{x}.\n##\n## The possible inputs are:\n##\n## @table @var\n## @item x\n##\n## data vector.  If @var{x} is real-valued a one-sided spectrum is estimated.\n## If @var{x} is complex-valued, or @qcode{\"@var{range}\"} specifies\n## @qcode{\"@nospell{twosided}\"}, the full spectrum is estimated.\n##\n## @item win\n## window weight data.  If window is empty or unspecified a default rectangular\n## window is used.  Otherwise, the window is applied to the signal\n## (@code{@var{x} .* @var{win}}) before computing the periodogram.  The window\n## data must be a vector of the same length as @var{x}.\n##\n## @item nfft\n## number of frequency bins.  The default is 256 or the next higher power of\n## 2 greater than the length of @var{x}\n## (@code{max (256, 2.^nextpow2 (length (x)))}).  If @var{nfft} is greater\n## than the length of the input then @var{x} will be zero-padded to the length\n## of @var{nfft}.\n##\n## @item Fs\n## sampling rate.  The default is 1.\n##\n## @item range\n## range of spectrum.  @qcode{\"@nospell{onesided}\"} computes spectrum from\n## [0:nfft/2+1].  @qcode{\"@nospell{twosided}\"} computes spectrum from\n## [0:nfft-1].\n## @end table\n##\n## The optional second output @var{w} are the normalized angular frequencies.\n## For a one-sided calculation @var{w} is in the range [0, pi] if @var{nfft}\n## is even and [0, pi) if @var{nfft} is odd.  Similarly, for a two-sided\n## calculation @var{w} is in the range [0, 2*pi] or [0, 2*pi) depending on\n## @var{nfft}.\n##\n## If a sampling frequency is specified, @var{Fs}, then the output frequencies\n## @var{f} will be in the range [0, @var{Fs}/2] or [0, @var{Fs}/2) for\n## one-sided calculations.  For two-sided calculations the range will be\n## [0, @var{Fs}).\n##\n## When called with no outputs the periodogram is immediately plotted in the\n## current figure window.\n## @seealso{fft}\n## @end deftypefn\n\nfunction [pxx, f] = periodogram (x, varargin)\n\n  ## check input arguments\n  if (nargin < 1 || nargin > 5)\n    print_usage ();\n  endif\n\n  nfft = fs = range = window = [];\n  j = 2;\n  for k = 1:length (varargin)\n    if (ischar (varargin{k}))\n      range = varargin{k};\n    else\n      switch (j)\n        case 2\n          window = varargin{k};\n        case 3\n          nfft   = varargin{k};\n        case 4\n          fs     = varargin{k};\n      endswitch\n      j += 1;\n    endif\n  endfor\n\n  if (! isvector (x))\n    error (\"periodogram: X must be a real or complex vector\");\n  endif\n  x = x(:);  # Use column vectors from now on\n\n  n = rows (x);\n\n  if (! isempty (window))\n    if (! isvector (window) || length (window) != n)\n      error (\"periodogram: WIN must be a vector of the same length as X\");\n    endif\n    window = window(:);\n    x .*= window;\n  endif\n\n  if (isempty (nfft))\n    nfft = max (256, 2.^nextpow2 (n));\n  elseif (! isscalar (nfft))\n    error (\"periodogram: NFFT must be a scalar\");\n  endif\n\n  use_w_freq = isempty (fs);\n  if (! use_w_freq && ! isscalar (fs))\n    error (\"periodogram: FS must be a scalar\");\n  endif\n\n  if (strcmpi (range, \"onesided\"))\n    range = 1;\n  elseif (strcmpi (range, \"twosided\"))\n    range = 2;\n  elseif (strcmpi (range, \"centered\"))\n    error ('periodogram: \"centered\" range type is not implemented');\n  else\n    range = 2-isreal (x);\n  endif\n\n  ## compute periodogram\n\n  if (n > nfft)\n    Pxx = 0;\n    rr = rem (length (x), nfft);\n    if (rr)\n      x = [x(:); zeros(nfft-rr, 1)];\n    endif\n    x = sum (reshape (x, nfft, []), 2);\n  endif\n\n  if (! isempty (window))\n    n = sumsq (window);\n  endif\n  Pxx = (abs (fft (x, nfft))) .^ 2 / n;\n\n  if (use_w_freq)\n    Pxx /= 2*pi;\n  else\n    Pxx /= fs;\n  endif\n\n  ## generate output arguments\n\n  if (range == 1)  # onesided\n    if (! rem (nfft,2))  # nfft is even\n      psd_len = nfft/2+1;\n      Pxx = Pxx(1:psd_len) + [0; Pxx(nfft:-1:psd_len+1); 0];\n    else                 # nfft is odd\n      psd_len = (nfft+1)/2;\n      Pxx = Pxx(1:psd_len) + [0; Pxx(nfft:-1:psd_len+1)];\n    endif\n  endif\n\n  if (nargout != 1)\n    if (range == 1)\n      f = (0:nfft/2)' / nfft;\n    elseif (range == 2)\n      f = (0:nfft-1)' / nfft;\n    endif\n    if (use_w_freq)\n      f *= 2*pi;  # generate w=2*pi*f\n    else\n      f *= fs;\n    endif\n  endif\n\n  if (nargout == 0)\n    if (use_w_freq)\n      plot (f/(2*pi), 10*log10 (Pxx));\n      xlabel (\"normalized frequency [x pi rad]\");\n      ylabel (\"Power density [dB/rad/sample]\");\n    else\n      plot (f, 10*log10 (Pxx));\n      xlabel (\"frequency [Hz]\");\n      ylabel (\"Power density [dB/Hz]\");\n    endif\n    grid on;\n    title (\"Periodogram Power Spectral Density Estimate\");\n  else\n    pxx = Pxx;\n  endif\n\nendfunction\n\n\n## FIXME: Need some functional tests\n\n\n## Test input validation\n%!error <Invalid call> periodogram ()\n%!error <Invalid call> periodogram (1,2,3,4,5,6)\n%!error <X must be a real or complex vector> periodogram (ones (2,2))\n%!error <WIN must be a vector.*same length> periodogram (1:5, ones (2,2))\n%!error <WIN must be a vector.*same length> periodogram (1:5, 1:6)\n%!error <NFFT must be a scalar> periodogram (1:5, 1:5, 1:5)\n%!error <FS must be a scalar> periodogram (1:5, [], [], 1:5)\n%!error <\"centered\" range type is not implemented> periodogram (1:5, \"centered\")\n"
  },
  {
    "path": "scripts/signal/private/rectangle_lw.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{c} =} rectangle_lw (@var{n}, @var{b})\n## Rectangular lag window.\n##\n## Subfunction used for spectral density estimation.\n## @seealso{spectral_adf}\n## @end deftypefn\n\nfunction c = rectangle_lw (n, b)\n\n  c = zeros (n, 1);\n  t = floor (1 / b);\n\n  c(1:t) = 1;\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/private/rectangle_sw.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{c} =} rectangle_sw (@var{n}, @var{b})\n## Rectangular spectral window.\n##\n## Subfunction used for spectral density estimation.\n## @seealso{spectral_xdf}\n## @end deftypefn\n\nfunction c = rectangle_sw (n, b)\n\n  c = zeros (n, 1);\n  c(1) = 2 / b + 1;\n\n  l = (2:n)' - 1;\n  l = 2 * pi * l / n;\n\n  c(2:n) = sin ((2/b + 1) * l / 2) ./ sin (l / 2);\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/private/triangle_lw.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{c} =} triangle_lw (@var{n}, @var{b})\n## Triangular lag window.\n##\n## Subfunction used for spectral density estimation.\n## @seealso{spectral_adf}\n## @end deftypefn\n\nfunction c = triangle_lw (n, b)\n\n  c = 1 - (0 : n-1)' * b;\n  c = max ([c'; (zeros (1, n))])';\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/private/triangle_sw.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{c} =} triangle_sw (@var{n}, @var{b})\n## Triangular spectral window.\n##\n## Subfunction used for spectral density estimation.\n## @seealso{spectral_xdf}\n## @end deftypefn\n\nfunction c = triangle_sw (n, b)\n\n  c = zeros (n,1);\n  c(1) = 1 / b;\n\n  l = (2:n)' - 1;\n  l = 2 * pi * l / n;\n\n  c(2:n) = b * (sin (l / (2*b)) ./ sin (l / 2)).^2;\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/sinc.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} sinc (@var{x})\n## Compute the sinc function.\n##\n## Return\n## @tex\n## $ \\sin (\\pi x)/(\\pi x)$.\n## @end tex\n## @ifnottex\n## sin (pi*x) / (pi*x).\n## @end ifnottex\n## @end deftypefn\n\nfunction y = sinc (x)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  y = ones (size (x));\n\n  i = (x != 0);\n\n  if (any (i(:)))\n    t = pi * x(i);\n    y(i) = sin (t) ./ t;\n  endif\n\nendfunction\n\n\n%!assert (sinc (0), 1)\n%!assert (sinc (1), 0,1e-6)\n%!assert (sinc (1/2), 2/pi, 1e-6)\n\n## Test input validation\n%!error <Invalid call> sinc ()\n"
  },
  {
    "path": "scripts/signal/sinetone.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} sinetone (@var{freq}, @var{rate}, @var{sec}, @var{ampl})\n## Return a sinetone of frequency @var{freq} with a length of @var{sec}\n## seconds at sampling rate @var{rate} and with amplitude @var{ampl}.\n##\n## The arguments @var{freq} and @var{ampl} may be vectors of common size.\n##\n## The defaults are @var{rate} = 8000, @var{sec} = 1, and @var{ampl} = 64.\n## @seealso{sinewave}\n## @end deftypefn\n\nfunction y = sinetone (freq, rate = 8000, sec = 1, ampl = 64)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  [err, freq, ampl] = common_size (freq, ampl);\n  if (err || ! isvector (freq))\n    error (\"sinetone: FREQ and AMPL must be vectors of common size\");\n  endif\n\n  if (! (isscalar (rate) && isscalar (sec)))\n    error (\"sinetone: RATE and SEC must be scalars\");\n  endif\n\n  n = length (freq);\n  ns = round (rate * sec);\n\n  y = zeros (ns, n);\n\n  for k = 1:n\n    y(:, k) = ampl(k) * sin (2 * pi * (1:ns) / rate * freq(k))';\n  endfor\n\nendfunction\n\n\n%!assert (size (sinetone (18e6, 150e6, 19550/150e6, 1)), [19550, 1])\n"
  },
  {
    "path": "scripts/signal/sinewave.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} sinewave (@var{m}, @var{n}, @var{d})\n## Return an @var{m}-element vector with @var{i}-th element given by\n## @code{sin (2 * pi * (@var{i}+@var{d}-1) / @var{n})}.\n##\n## The default value for @var{d} is 0 and the default value for @var{n} is\n## @var{m}.\n## @seealso{sinetone}\n## @end deftypefn\n\nfunction y = sinewave (m, n, d = 0)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## FIXME: No input validation of M, N, or D\n  if (nargin < 2)\n    n = m;\n  endif\n  if (nargin < 3)\n    d = 0;\n  endif\n\n  y = sin (((1 : m) + d - 1) * 2 * pi / n);\n\nendfunction\n\n\n%!assert (sinewave (1), 0)\n%!assert (sinewave (1, 4, 1), 1)\n%!assert (sinewave (1, 12, 1), 1/2, 1e-6)\n%!assert (sinewave (1, 12, 2), sqrt (3)/2, 1e-6)\n%!assert (sinewave (1, 20, 1), (sqrt (5)-1)/4, 1e-6)\n%!assert (sinewave (1), sinewave (1, 1,0))\n%!assert (sinewave (3, 4), sinewave (3, 4, 0))\n\n%!error <Invalid call> sinewave ()\n"
  },
  {
    "path": "scripts/signal/spectral_adf.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{sde} =} spectral_adf (@var{c})\n## @deftypefnx {} {@var{sde} =} spectral_adf (@var{c}, @var{win})\n## @deftypefnx {} {@var{sde} =} spectral_adf (@var{c}, @var{win}, @var{b})\n## Return the spectral density estimator given a vector of autocovariances\n## @var{c}, window name @var{win}, and bandwidth, @var{b}.\n##\n## The window name, e.g., @qcode{\"triangle\"} or @qcode{\"rectangle\"} is\n## used to search for a function called @code{@var{win}_lw}.\n##\n## If @var{win} is omitted, the triangle window is used.\n##\n## If @var{b} is omitted, @code{1 / sqrt (length (@var{x}))} is used.\n## @seealso{spectral_xdf}\n## @end deftypefn\n\nfunction sde = spectral_adf (c, win, b)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  cr = length (c);\n\n  if (columns (c) > 1)\n    c = c';\n  endif\n\n  if (nargin < 3)\n    b = 1 / ceil (sqrt (cr));\n  endif\n\n  if (nargin == 1)\n    w = triangle_lw (cr, b);\n  elseif (! ischar (win))\n    error (\"spectral_adf: WIN must be a string\");\n  else\n    win = str2func ([win \"_lw\"]);\n    w = feval (win, cr, b);\n  endif\n\n  c .*= w;\n\n  sde = 2 * real (fft (c)) - c(1);\n  sde = [(zeros (cr, 1)), sde];\n  sde(:, 1) = (0 : cr-1)' / cr;\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> spectral_adf ()\n%!error <WIN must be a string> spectral_adf (1, 2)\n%!error <unable to find function for @invalid_lw> spectral_adf (1, \"invalid\")\n"
  },
  {
    "path": "scripts/signal/spectral_xdf.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{sde} =} spectral_xdf (@var{x})\n## @deftypefnx {} {@var{sde} =} spectral_xdf (@var{x}, @var{win})\n## @deftypefnx {} {@var{sde} =} spectral_xdf (@var{x}, @var{win}, @var{b})\n## Return the spectral density estimator given a data vector @var{x}, window\n## name @var{win}, and bandwidth, @var{b}.\n##\n## The window name, e.g., @qcode{\"triangle\"} or @qcode{\"rectangle\"} is used to\n## search for a function called @code{@var{win}_sw}.\n##\n## If @var{win} is omitted, the triangle window is used.\n##\n## If @var{b} is omitted, @code{1 / sqrt (length (@var{x}))} is used.\n## @seealso{spectral_adf}\n## @end deftypefn\n\nfunction sde = spectral_xdf (x, win, b)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  xr = length (x);\n\n  if (columns (x) > 1)\n    x = x';\n  endif\n\n  if (nargin < 3)\n    b = 1 / ceil (sqrt (xr));\n  endif\n\n  if (nargin == 1)\n    w = triangle_sw (xr, b);\n  elseif (! ischar (win))\n    error (\"spectral_xdf: WIN must be a string\");\n  else\n    win = str2func ([win \"_sw\"]);\n    w = feval (win, xr, b);\n  endif\n\n  x -= sum (x) / xr;\n\n  sde = (abs (fft (x)) / xr).^2;\n  sde = real (ifft (fft (sde) .* fft (w)));\n\n  sde = [(zeros (xr, 1)), sde];\n  sde(:, 1) = (0 : xr-1)' / xr;\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> spectral_xdf ()\n%!error <WIN must be a string> spectral_xdf (1, 2)\n%!error <unable to find function for @invalid_sw> spectral_xdf (1, \"invalid\")\n"
  },
  {
    "path": "scripts/signal/spencer.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{savg} =} spencer (@var{x})\n## Return @nospell{Spencer's} 15-point moving average of each column of\n## @var{x}.\n## @end deftypefn\n\nfunction savg = spencer (x)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  [xr, xc] = size (x);\n\n  n = xr;\n  c = xc;\n\n  if (isvector (x))\n   n = length (x);\n   c = 1;\n   x = reshape (x, n, 1);\n  endif\n\n  w = [-3, -6, -5, 3, 21, 46, 67, 74, 67, 46, 21, 3, -5, -6, -3] / 320;\n\n  savg = fftfilt (w, x);\n  savg = [zeros(7,c); savg(15:n,:); zeros(7,c);];\n\n  savg = reshape (savg, xr, xc);\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/stft.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} stft (@var{x})\n## @deftypefnx {} {@var{y} =} stft (@var{x}, @var{win_size})\n## @deftypefnx {} {@var{y} =} stft (@var{x}, @var{win_size}, @var{inc})\n## @deftypefnx {} {@var{y} =} stft (@var{x}, @var{win_size}, @var{inc}, @var{num_coef})\n## @deftypefnx {} {@var{y} =} stft (@var{x}, @var{win_size}, @var{inc}, @var{num_coef}, @var{win_type})\n## @deftypefnx {} {[@var{y}, @var{c}] =} stft (@dots{})\n## Compute the short-time Fourier transform of the vector @var{x} with\n## @var{num_coef} coefficients by applying a window of @var{win_size} data\n## points and an increment of @var{inc} points.\n##\n## Before computing the Fourier transform, one of the following windows\n## is applied:\n##\n## @table @asis\n## @item @qcode{\"hanning\"}\n## win_type = 1\n##\n## @item @qcode{\"hamming\"}\n## win_type = 2\n##\n## @item @qcode{\"rectangle\"}\n## win_type = 3\n## @end table\n##\n## The window names can be passed as strings or by the @var{win_type} number.\n##\n## The following defaults are used for unspecified arguments:\n## @var{win_size} = 80, @var{inc} = 24, @var{num_coef} = 64, and\n## @var{win_type} = 1.\n##\n## @code{@var{y} = stft (@var{x}, @dots{})} returns the absolute values of the\n## Fourier coefficients according to the @var{num_coef} positive frequencies.\n##\n## @code{[@var{y}, @var{c}] = stft (@var{x}, @dots{})} returns the entire\n## STFT-matrix @var{y} and a 3-element vector @var{c} containing the window\n## size, increment, and window type, which is needed by the @code{synthesis}\n## function.\n## @seealso{synthesis}\n## @end deftypefn\n\nfunction [y, c] = stft (x, win_size = 80, inc = 24, num_coef = 64, win_type = 1)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ischar (win_type))\n    switch (lower (win_type))\n      case \"hanning\"   , win_type = 1;\n      case \"hamming\"   , win_type = 2;\n      case \"rectangle\" , win_type = 3;\n      otherwise\n        error (\"stft: unknown window type '%s'\", win_type);\n    endswitch\n  endif\n\n  ## Check whether X is a vector.\n  if (! isvector (x))\n    error (\"stft: X must be a vector\");\n  endif\n  x = x(:);\n\n  ncoef = 2 * num_coef;\n  if (win_size > ncoef)\n    win_size = ncoef;\n    printf (\"stft: window size adjusted to %f\\n\", win_size);\n  endif\n  num_win = fix ((rows (x) - win_size) / inc);\n\n  ## compute the window coefficients\n  switch (win_type)\n    case 1 , win_coef = hanning (win_size);\n    case 2 , win_coef = hamming (win_size);\n    case 3 , win_coef = ones (win_size, 1);\n  endswitch\n\n  ## Create a matrix Z whose columns contain the windowed time-slices.\n  z = zeros (ncoef, num_win + 1);\n  start = 1;\n  for i = 0:num_win\n    z(1:win_size, i+1) = x(start:start+win_size-1) .* win_coef;\n    start += inc;\n  endfor\n\n  y = fft (z);\n\n  if (nargout == 1)\n    y = abs (y(1:num_coef, :));\n  else\n    c = [win_size, inc, win_type];\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/synthesis.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{x} =} synthesis (@var{y}, @var{c})\n## Compute a signal from its short-time Fourier transform @var{y} and a\n## 3-element vector @var{c} specifying window size, increment, and window type.\n##\n## The values @var{y} and @var{c} can be derived by\n##\n## @example\n## [@var{y}, @var{c}] = stft (@var{x} , @dots{})\n## @end example\n## @seealso{stft}\n## @end deftypefn\n\nfunction x = synthesis (y, c)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (numel (c) != 3)\n    error (\"synthesis: C must contain exactly 3 elements\");\n  endif\n\n  w_size = c(1);\n  inc    = c(2);\n  w_type = c(3);\n\n  if (w_type == 1)\n    w_coeff = hanning (w_size);\n  elseif (w_type == 2)\n    w_coeff = hamming (w_size);\n  elseif (w_type == 3)\n    w_coeff = ones (w_size, 1);\n  else\n    error (\"synthesis: window_type must be 1, 2, or 3\");\n  endif\n\n  z = real (ifft (y));\n  st = fix ((w_size-inc) / 2);\n  z = z(st+1:st+inc, :);\n  w_coeff = w_coeff(st+1:st+inc);\n\n  nc = columns (z);\n  for i = 1:nc\n    z(:, i) ./= w_coeff;\n  endfor\n\n  x = reshape (z, inc * nc, 1);\n\nendfunction\n"
  },
  {
    "path": "scripts/signal/unwrap.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{b} =} unwrap (@var{x})\n## @deftypefnx {} {@var{b} =} unwrap (@var{x}, @var{tol})\n## @deftypefnx {} {@var{b} =} unwrap (@var{x}, @var{tol}, @var{dim})\n## Unwrap radian phases by adding or subtracting multiples of 2*pi as\n## appropriate to remove jumps greater than @var{tol}.\n##\n## @var{tol} defaults to pi.\n##\n## @code{unwrap} will work along the dimension @var{dim}.  If @var{dim}\n## is unspecified it defaults to the first non-singleton dimension.\n##\n## @code{unwrap} ignores all non-finite input values (Inf, NaN, NA).\n##\n## @end deftypefn\n\nfunction retval = unwrap (x, tol, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    error (\"unwrap: X must be numeric\");\n  endif\n\n  if (nargin < 2 || isempty (tol))\n    tol = pi;\n  endif\n\n  ## Don't let anyone use a negative value for TOL.\n  tol = abs (tol);\n\n  nd = ndims (x);\n  sz = size (x);\n  if (nargin == 3)\n    if (!(isnumeric (dim) && isscalar (dim) && ...\n            dim == fix (dim)) || !(1 <= dim))\n      error (\"unwrap: DIM must be an integer and a valid dimension\");\n    endif\n  else\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  endif\n\n  rng = 2*pi;\n\n  ## Handle case where we are trying to unwrap a scalar, or only have\n  ## one sample in the specified dimension (a given when dim > nd).\n  if ((dim > nd) || (m = sz(dim) == 1))\n    retval = x;\n    return;\n  endif\n\n  if (all (isfinite (x(:))))\n\n    ## Take first order difference so that wraps will show up as large values\n    ## and the sign will show direction.\n    sz(dim) = 1;\n    zero_padding = zeros (sz);\n    d = cat (dim, zero_padding, -diff (x, 1, dim));\n\n    ## Find only the peaks and multiply them by the appropriate amount\n    ## of ranges so that there are kronecker deltas at each wrap point\n    ## multiplied by the appropriate amount of range values.\n    p = round (abs (d)./rng) .* rng .* (((d > tol) > 0) - ((d < -tol) > 0));\n\n    ## Integrate this so that the deltas become cumulative steps to shift\n    ## the original data.\n    retval = cumsum (p, dim) + x;\n\n  else\n    ## Unwrap needs to skip over NaN, NA, Inf in wrapping calculations.\n\n    if (isvector (x))\n      ## Simlpified path for vector inputs.\n\n      retval = x;\n      xfin_idx = isfinite (x);\n      xfin = x(xfin_idx);\n      d = cat (dim, 0, -diff (xfin, 1, dim));\n      p = round (abs (d)./rng) .* rng .* ...\n                      (((d > tol) > 0) - ((d < -tol) > 0));\n      retval(xfin_idx) = xfin + cumsum (p, dim);\n\n    else\n      ## For N-dimensional arrays with a possibly unequal number of non-finite\n      ## values, mask entries with values that do not impact calcualation.\n\n            ## Locate nonfinite values.\n      nf_idx = ! isfinite (x);\n\n      if (all (nf_idx(:)))\n        ## Trivial case, all non-finite values\n        retval = x;\n        return;\n      endif\n\n      ## Permute all operations to occur along dim 1.  Inverse permute at end.\n      permuteflag = dim != 1;\n      if (permuteflag)\n        perm_idx = [1 : nd];\n        perm_idx([1, dim]) = [dim, 1];\n\n        x = permute (x, perm_idx);\n        nf_idx = permute (nf_idx, perm_idx);\n        sz([1, dim]) = sz([dim, 1]);\n        dim = 1;\n      endif\n\n      ## Substitute next value in dim direction for nonfinite values(ignoring\n      ## any at trailing end) to prevent calculation impact.\n\n      x_nf = x(nf_idx); # Store nonfinite values.\n\n      zero_padding = zeros ([1, sz(2:end)]);\n      x = __fill_nonfinite_columnwise__ (x, nf_idx, zero_padding, sz, nd);\n\n      d = [zero_padding; -diff(x, 1, 1)];\n\n      p = round (abs (d)./rng) .* rng .* ...\n          (((d > tol) > 0) - ((d < -tol) > 0));\n\n      retval = x + cumsum (p, 1);\n\n      ## Restore nonfinite values.\n      retval(nf_idx) = x_nf;\n\n      ## Invert permutation.\n      if (permuteflag)\n        retval = ipermute (retval, perm_idx);\n      endif\n\n    endif\n  endif\n\nendfunction\n\n\nfunction x = __fill_nonfinite_columnwise__ (x, nonfinite_loc, zero_padding, szx, ndx)\n  ## Replace non-finite values of x, as indicated by logical index\n  ## nonfinite_loc, with next values.\n\n  ## TODO: This is a streamlined version of the fillmissing 'next' method from\n  ## the statistics package.  Function calls can be replaced by:\n  ## fillmissing (x, 'next', 1, 'missinglocations', nonfinite_loc)\n  ## if/when that is added to Octave core if full function overhead is okay.\n\n  ## Build index for faster/simpler inline replacement for flipud\n  flip_idx(1:ndx) = {':'};\n  flip_idx(1) = {szx(1):-1:1};\n\n  ## Isolate nf values by location:\n  nf_front = cumprod (nonfinite_loc, 1);\n  nf_back = cumprod (nonfinite_loc(flip_idx{:}), 1)(flip_idx{:});\n  nf_middle = nonfinite_loc & ! (nf_back | nf_front);\n\n  ## Process bound/middle elements\n  locs_before = [diff(nf_middle, 1, 1); zero_padding] == 1;\n  locs_after = diff ([zero_padding; nf_middle], 1, 1) == -1;\n  mid_gap_sizes = find (locs_after) - find (locs_before) - 1;\n  x(nf_middle) = repelems (x(locs_after), ...\n                          [1 : numel(mid_gap_sizes); mid_gap_sizes'])';\n\n  ## Process front edge elements\n  nf_front = nf_front & ! all (nonfinite_loc, 1); # Remove all nf columns.\n  locs_after = diff ([zero_padding; nf_front], 1, 1) == -1;\n  front_gap_sizes = (sum (nf_front, 1))(any (nf_front, 1))(:);\n  x(nf_front) = repelems (x(locs_after), ...\n                             [1:numel(front_gap_sizes); front_gap_sizes'])';\n\nendfunction\n\n\n%!shared i, t, r, w, tol\n%! i = 0;\n%! t = [];\n%! r = [0:100];                         ## original vector\n%! w = r - 2*pi*floor ((r+pi)/(2*pi));  ## wrapped into [-pi,pi]\n%! tol = 1e3*eps;\n\n%!assert (r,  unwrap (w),  tol)\n%!assert (r', unwrap (w'), tol)\n%!assert ([r',r'], unwrap ([w',w']), tol)\n%!assert ([r; r ], unwrap ([w; w ], [], 2), tol)\n%!assert (r + 10, unwrap (10 + w), tol)\n\n%!assert (w', unwrap (w', [], 2))\n%!assert (w,  unwrap (w,  [], 1))\n%!assert ([w; w], unwrap ([w; w]))\n\n## Test that small values of tol have the same effect as tol = pi\n%!assert (r, unwrap (w, 0.1), tol)\n%!assert (r, unwrap (w, eps), tol)\n\n%!shared # Clear shared variables to avoid echo on subsequent failures.\n\n## Test that phase changes larger than 2*pi unwrap properly\n%!assert ([0;  1],        unwrap ([0;  1]))\n%!assert ([0;  4 - 2*pi], unwrap ([0;  4]))\n%!assert ([0;  7 - 2*pi], unwrap ([0;  7]))\n%!assert ([0; 10 - 4*pi], unwrap ([0; 10]))\n%!assert ([0; 13 - 4*pi], unwrap ([0; 13]))\n%!assert ([0; 16 - 6*pi], unwrap ([0; 16]))\n%!assert ([0; 19 - 6*pi], unwrap ([0; 19]))\n%!assert (max (abs (diff (unwrap (100*pi * rand (1000, 1))))) < pi)\n\n%!test\n%! A = [pi*(-4), pi*(-2+1/6), pi/4, pi*(2+1/3), pi*(4+1/2), pi*(8+2/3), pi*(16+1), pi*(32+3/2), pi*64];\n%! assert (unwrap (A), unwrap (A, pi));\n%! assert (unwrap (A, pi), unwrap (A, pi, 2));\n%! assert (unwrap (A', pi), unwrap (A', pi, 1));\n\n%!test\n%! A = [pi*(-4); pi*(2+1/3); pi*(16+1)];\n%! B = [pi*(-2+1/6); pi*(4+1/2); pi*(32+3/2)];\n%! C = [pi/4; pi*(8+2/3); pi*64];\n%! D = [pi*(-2+1/6); pi*(2+1/3); pi*(8+2/3)];\n%! E(:, :, 1) = [A, B, C, D];\n%! E(:, :, 2) = [A+B, B+C, C+D, D+A];\n%! F(:, :, 1) = [unwrap(A), unwrap(B), unwrap(C), unwrap(D)];\n%! F(:, :, 2) = [unwrap(A+B), unwrap(B+C), unwrap(C+D), unwrap(D+A)];\n%! assert (unwrap (E), F);\n\n%!test\n%! A = [0, 2*pi, 4*pi, 8*pi, 16*pi, 65536*pi];\n%! B = [pi*(-2+1/6), pi/4, pi*(2+1/3), pi*(4+1/2), pi*(8+2/3), pi*(16+1), pi*(32+3/2), pi*64];\n%! assert (unwrap (A), zeros (1, length (A)));\n%! assert (diff (unwrap (B), 1) < 2*pi, true (1, length (B)-1));\n\n## Test trivial return for m = 1 and dim > nd\n%!assert (unwrap (ones(4,1), [], 1), ones(4,1))\n%!assert (unwrap (ones(4,1), [], 2), ones(4,1))\n%!assert (unwrap (ones(4,1), [], 3), ones(4,1))\n%!assert (unwrap (ones(4,3,2), [], 99), ones(4,3,2))\n\n## Test empty input return\n%!assert (unwrap ([]), [])\n%!assert (unwrap (ones (1,0)), ones (1,0))\n%!assert (unwrap (ones (1,0), [], 1), ones (1,0))\n%!assert (unwrap (ones (1,0), [], 2), ones (1,0))\n%!assert (unwrap (ones (1,0), [], 3), ones (1,0))\n\n## Test handling of non-finite values\n%!assert <*64556> (unwrap (NaN (4,1)), NaN (4,1))\n%!assert <*64556> (unwrap (NaN (4)), NaN (4))\n\n%!test <*64556>\n%! x = pi * [-Inf, 0.5, -1, NaN, Inf, -0.5, 1];\n%! assert (unwrap (x), pi * [-Inf, 0.5, 1, NaN, Inf, 1.5, 1], eps);\n%! assert (unwrap (x.'), pi * [-Inf, 0.5, 1, NaN, Inf, 1.5, 1].', eps);\n\n%!test <*64556>\n%! x = pi * [-Inf, 0.5, -1, NaN, Inf, -0.5, 1];\n%! y = unwrap ([x; fliplr(x); NaN(1, 7)], [], 2);\n%! z = pi * [-Inf, 0.5, 1, NaN, Inf, 1.5, 1; 1, 1.5, Inf, NaN, 1, 0.5, -Inf; NaN(1,7)];\n%! assert (y, z, eps);\n\n\n## Test input validation\n%!error <Invalid call> unwrap ()\n%!error unwrap (1, 2, 3, 4)\n%!error <X must be numeric> unwrap (\"foo\")\n%!error <X must be numeric> unwrap ({1})\n%!error <X must be numeric> unwrap (struct())\n%!error <DIM must be an> unwrap (1, 2, \"foo\")\n%!error <DIM must be an> unwrap (1, 2, -1)\n%!error <DIM must be an> unwrap (1, 2, 1.5)\n%!error <DIM must be an> unwrap (1, 2, {1})\n%!error <DIM must be an> unwrap (1, 2, struct())\n"
  },
  {
    "path": "scripts/signal/yulewalker.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{a}, @var{v}] =} yulewalker (@var{c})\n## Fit an AR (p)-model with Yule-Walker estimates given a vector @var{c} of\n## autocovariances @code{[gamma_0, @dots{}, gamma_p]}.\n##\n## Returns the AR coefficients, @var{a}, and the variance of white noise,\n## @var{v}.\n## @end deftypefn\n\nfunction [a, v] = yulewalker (c)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  p = length (c) - 1;\n\n  if (columns (c) > 1)\n    c = c';\n  endif\n\n  cp = c(2 : p+1);\n  CP = zeros (p, p);\n\n  for i = 1:p\n    for j = 1:p\n      CP (i, j) = c (abs (i-j) + 1);\n    endfor\n  endfor\n\n  a = inv (CP) * cp;\n  v = c(1) - a' * cp;\n\nendfunction\n"
  },
  {
    "path": "scripts/sparse/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/sparse/bicg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} bicg (@var{A}, @var{b})\n## @deftypefnx {} {@var{x} =} bicg (@var{A}, @var{b}, @var{tol})\n## @deftypefnx {} {@var{x} =} bicg (@var{A}, @var{b}, @var{tol}, @var{maxit})\n## @deftypefnx {} {@var{x} =} bicg (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M})\n## @deftypefnx {} {@var{x} =} bicg (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M1}, @var{M2})\n## @deftypefnx {} {@var{x} =} bicg (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M}, [], @var{x0})\n## @deftypefnx {} {@var{x} =} bicg (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})\n## @deftypefnx {} {@var{x} =} bicg (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M}, [], @var{x0}, @dots{})\n## @deftypefnx {} {@var{x} =} bicg (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} bicg (@var{A}, @var{b}, @dots{})\n## Solve the linear system of equations\n## @w{@code{@var{A} * @var{x} = @var{b}}}@ by means of the Bi-Conjugate\n## Gradient iterative method.\n##\n## The input arguments are:\n##\n## @itemize\n##\n## @item @var{A} is the matrix of the linear system and it must be square.\n## @var{A} can be passed as a matrix, function handle, or inline function\n## @code{Afcn} such that @w{@code{Afcn (x, \"notransp\") = A * x}}@ and\n## @w{@code{Afcn (x, \"transp\") = A' * x}}.  Additional parameters to\n## @code{Afcn} may be passed after @var{x0}.\n##\n## @item @var{b} is the right-hand side vector.  It must be a column vector\n## with the same number of rows as @var{A}.\n##\n## @item\n## @var{tol} is the required relative tolerance for the residual error,\n## @w{@code{@var{b} - @var{A} * @var{x}}}.  The iteration stops if\n## @w{@code{norm (@var{b} - @var{A} * @var{x})} @leq{}\n## @w{@code{@var{tol} * norm (@var{b})}}}.\n## If @var{tol} is omitted or empty, then a tolerance of 1e-6 is used.\n##\n## @item\n## @var{maxit} is the maximum allowed number of iterations; if @var{maxit}\n## is omitted or empty then a value of 20 is used.\n##\n## @item\n## @var{M1}, @var{M2} are the preconditioners.  The preconditioner @var{M} is\n## given as @code{@var{M} = @var{M1} * @var{M2}}.  Both @var{M1} and @var{M2}\n## can be passed as a matrix or as a function handle or inline function\n## @code{g} such that\n## @w{@code{g (@var{x}, \"notransp\") = @var{M1} \\ @var{x}}}@ or\n## @w{@code{g (@var{x}, \"notransp\") = @var{M2} \\ @var{x}}}@ and\n## @w{@code{g (@var{x}, \"transp\") = @var{M1}' \\ @var{x}}}@ or\n## @w{@code{g (@var{x}, \"transp\") = @var{M2}' \\ @var{x}}}.\n## If @var{M1} is omitted or empty, then preconditioning is not applied.\n## The preconditioned system is theoretically equivalent to applying the\n## @code{bicg} method to the linear system\n## @code{inv (@var{M1}) * A * inv (@var{M2}) * @var{y} = inv\n## (@var{M1}) * @var{b}} and\n## @code{inv (@var{M2'}) * A' * inv (@var{M1'}) * @var{z} =\n## inv (@var{M2'}) * @var{b}} and then setting\n## @code{@var{x} = inv (@var{M2}) * @var{y}}.\n##\n## @item\n## @var{x0} is the initial guess.  If @var{x0} is omitted or empty then the\n## function sets @var{x0} to a zero vector by default.\n## @end itemize\n##\n## Any arguments which follow @var{x0} are treated as parameters, and passed in\n## an appropriate manner to any of the functions (@var{Afcn} or @var{Mfcn}) or\n## that have been given to @code{bicg}.\n##\n## The output parameters are:\n##\n## @itemize\n##\n## @item\n## @var{x} is the computed approximation to the solution of\n## @w{@code{@var{A} * @var{x} = @var{b}}}.  If the algorithm did not converge,\n## then @var{x} is the iteration which has the minimum residual.\n##\n## @item\n## @var{flag} indicates the exit status:\n##\n## @itemize\n## @item 0: The algorithm converged to within the prescribed tolerance.\n##\n## @item 1: The algorithm did not converge and it reached the maximum number of\n## iterations.\n##\n## @item 2: The preconditioner matrix is singular.\n##\n## @item 3: The algorithm stagnated, i.e., the absolute value of the\n## difference between the current iteration @var{x} and the previous is less\n## than @code{eps * norm (@var{x},2)}.\n##\n## @item 4: The algorithm could not continue because intermediate values\n## became too small or too large for reliable computation.\n## @end itemize\n##\n## @item\n## @var{relres} is the ratio of the final residual to its initial value,\n## measured in the Euclidean norm.\n##\n## @item\n## @var{iter} is the iteration which @var{x} is computed.\n##\n## @item\n## @var{resvec} is a vector containing the residual at each iteration.\n## The total number of iterations performed is given by\n## @code{length (@var{resvec}) - 1}.\n## @end itemize\n##\n## Consider a trivial problem with a tridiagonal matrix\n##\n## @smallexample\n## @group\n## n = 20;\n## A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n)) + ...\n##     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n##               sparse (1, 2, 1, 1, n) * n / 2);\n## b = A * ones (n, 1);\n## restart = 5;\n## [M1, M2] = ilu (A);  # in this tridiag case, it corresponds to lu (A)\n## M = M1 * M2;\n## Afcn = @@(x, string) strcmp (string, \"notransp\") * (A * x) + ...\n##                      strcmp (string, \"transp\") * (A' * x);\n## Mfcn = @@(x, string) strcmp (string, \"notransp\") * (M \\ x) + ...\n##                      strcmp (string, \"transp\") * (M' \\ x);\n## M1fcn = @@(x, string) strcmp (string, \"notransp\") * (M1 \\ x) + ...\n##                      strcmp (string, \"transp\") * (M1' \\ x);\n## M2fcn = @@(x, string) strcmp (string, \"notransp\") * (M2 \\ x) + ...\n##                      strcmp (string, \"transp\") * (M2' \\ x);\n## @end group\n## @end smallexample\n##\n## @sc{Example 1:} simplest usage of @code{bicg}\n##\n## @example\n## x = bicg (A, b)\n## @end example\n##\n## @sc{Example 2:} @code{bicg} with a function that computes\n## @code{@var{A}*@var{x}} and @code{@var{A'}*@var{x}}\n##\n## @example\n## x = bicg (Afcn, b, [], n)\n## @end example\n##\n## @sc{Example 3:} @code{bicg} with a preconditioner matrix @var{M}\n##\n## @example\n## x = bicg (A, b, 1e-6, n, M)\n## @end example\n##\n## @sc{Example 4:} @code{bicg} with a function as preconditioner\n##\n## @example\n## x = bicg (Afcn, b, 1e-6, n, Mfcn)\n## @end example\n##\n## @sc{Example 5:} @code{bicg} with preconditioner matrices @var{M1}\n## and @var{M2}\n##\n## @example\n## x = bicg (A, b, 1e-6, n, M1, M2)\n## @end example\n##\n## @sc{Example 6:} @code{bicg} with functions as preconditioners\n##\n## @example\n## x = bicg (Afcn, b, 1e-6, n, M1fcn, M2fcn)\n## @end example\n##\n## @sc{Example 7:} @code{bicg} with as input a function requiring an argument\n##\n## @example\n## @group\n## function y = Ap (A, x, string, z)\n##   ## compute A^z * x or (A^z)' * x\n##   y = x;\n##   if (strcmp (string, \"notransp\"))\n##     for i = 1:z\n##       y = A * y;\n##     endfor\n##   elseif (strcmp (string, \"transp\"))\n##     for i = 1:z\n##       y = A' * y;\n##     endfor\n##   endif\n## endfunction\n##\n## Apfcn = @@(x, string, p) Ap (A, x, string, p);\n## x = bicg (Apfcn, b, [], [], [], [], [], 2);\n## @end group\n## @end example\n##\n## Reference:\n##\n## @nospell{Y. Saad}, @cite{Iterative Methods for Sparse Linear Systems},\n## 2nd edition, SIAM, 2003.\n##\n## @seealso{bicgstab, cgs, gmres, pcg, qmr, tfqmr}\n## @end deftypefn\n\nfunction [x_min, flag, relres, iter_min, resvec] = ...\n         bicg (A, b, tol = [], maxit = [], M1 = [], M2 = [], x0 = [], varargin)\n\n  [Afcn, M1fcn, M2fcn] =  __alltohandles__ (A, b, M1, M2, \"bicg\");\n\n  [tol, maxit, x0] = __default__input__ ({1e-06, min(rows(b), 20), ...\n                                          zeros(rows (b),1)}, tol, maxit, x0);\n\n  if (columns (b) == 2)\n    c = b(:,2);\n    b = b(:,1);\n  else\n    c = b;\n  endif\n  norm_b = norm (b, 2);\n\n  if (norm_b == 0)  # the only (only iff det (A) == 0) solution is x = 0\n    if (nargout < 2)\n      printf (\"The right hand side vector is all zero so bicg\\n\")\n      printf (\"returned an all zero solution without iterating.\\n\")\n    endif\n    x_min = zeros (numel (b), 1);\n    flag = 0;\n    relres = 0;\n    iter_min = 0;\n    resvec = 0;\n    return;\n  endif\n\n  x = x_min = x_pr = x0;\n  iter = iter_min = 0;\n  flag = 1;  # Default flag is \"maximum number of iterations reached\"\n  resvec = zeros (maxit + 1, 1);\n  r0 = b - Afcn (x, \"notransp\", varargin{:});  # Residual of the system\n  s0 = c - Afcn (x, \"transp\", varargin{:});    # Res. of the \"dual system\"\n  resvec(1) = norm (r0, 2);\n\n  try\n    warning (\"error\", \"Octave:singular-matrix\", \"local\");\n    prec_r0 = M1fcn (r0, \"notransp\", varargin{:});  # r0 preconditioned\n    prec_s0 = s0;\n    prec_r0 = M2fcn (prec_r0, \"notransp\", varargin{:});\n    prec_s0 = M2fcn (prec_s0, \"transp\", varargin{:});\n    prec_s0 = M1fcn (prec_s0, \"transp\", varargin{:});  # s0 preconditioned\n    p = prec_r0;  # Direction of the system\n    q = prec_s0;  # Direction of the \"dual system\"\n  catch\n    flag = 2;\n  end_try_catch\n\n  while ((flag != 2) && (iter < maxit) && (resvec(iter+1) >= norm_b * tol))\n    v = Afcn (p, \"notransp\", varargin{:});\n    prod_qv = q' * v;\n    alpha = (s0' * prec_r0);\n    if (abs (prod_qv) <= eps * abs (alpha))\n      flag = 4;\n      break;\n    endif\n    alpha ./= prod_qv;\n    x += alpha * p;\n    prod_rs = (s0' * prec_r0);  # Product between r0 and s0\n    r0 -= alpha * v;\n    s0 -= conj (alpha) * Afcn (q, \"transp\", varargin{:});\n    prec_r0 = M1fcn (r0, \"notransp\", varargin{:});\n    prec_s0 = s0;\n    prec_r0 = M2fcn (prec_r0, \"notransp\", varargin{:});\n    beta = s0' * prec_r0;\n    if (abs (prod_rs) <= abs (beta))\n      flag = 4;\n      break;\n    endif\n    beta ./= prod_rs;\n    prec_s0 = M2fcn (prec_s0, \"transp\", varargin{:});\n    prec_s0 = M1fcn (prec_s0, \"transp\", varargin{:});\n    iter += 1;\n    resvec(iter+1) = norm (r0);\n    if (resvec(iter+1) <= resvec(iter_min+1))\n      x_min = x;\n      iter_min = iter;\n    endif\n    if (norm (x - x_pr) <= norm (x) * eps)\n      flag = 3;\n      break;\n    endif\n    p = prec_r0 + beta*p;\n    q = prec_s0 + conj (beta) * q;\n  endwhile\n  resvec = resvec(1:iter+1,1);\n\n  if (flag == 2)\n    relres = 1;\n  else\n    relres = resvec(iter_min+1) / norm_b;\n  endif\n\n  if ((flag == 1) && (relres <= tol))\n    flag = 0;\n  endif\n\n  if (nargout < 2)\n    switch (flag)\n      case 0\n        printf (\"bicg converged at iteration %i \", iter_min);\n        printf (\"to a solution with relative residual %e\\n\", relres);\n      case 1\n        printf (\"bicg stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the maximum number of iterations was reached.  \");\n        printf (\"The iterate returned (number %i) has \", iter_min);\n        printf (\"relative residual %e\\n\", relres);\n      case 2\n        printf (\"bicg stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the preconditioner matrix is singular.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case 3\n        printf (\"bicg stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the method stagnated.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case 4\n        printf (\"bicg stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the method can't continue.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n    endswitch\n  endif\n\nendfunction\n\n\n%!demo\n%! ## simplest use case\n%! n = 20;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n)) + ...\n%!     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n%!               sparse (1, 2, 1, 1, n) * n / 2);\n%! b = A * ones (n, 1);\n%! [M1, M2] = ilu (A + 0.1 * eye (n));\n%! M = M1 * M2;\n%! x = bicg (A, b, [], n);\n%! function y = Ap (A, x, string, z)\n%!   ## compute A^z * x or (A^z)' * x\n%!   y = x;\n%!   if (strcmp (string, \"notransp\"))\n%!     for i = 1:z\n%!       y = A * y;\n%!   endfor\n%!   elseif (strcmp (string, \"transp\"))\n%!     for i = 1:z\n%!       y = A' * y;\n%!     endfor\n%!   endif\n%! endfunction\n%!\n%! Afcn = @(x, string) Ap (A, x, string, 1);\n%! x = bicg (Afcn, b, [], n);\n%! x = bicg (A, b, 1e-6, n, M);\n%! x = bicg (A, b, 1e-6, n, M1, M2);\n%! function y = Mfcn (M, x, string)\n%!   if (strcmp (string, \"notransp\"))\n%!     y = M \\ x;\n%!   else\n%!     y = M' \\ x;\n%!   endif\n%! endfunction\n%!\n%! M1fcn = @(x, string) Mfcn (M, x, string);\n%! x = bicg (Afcn, b, 1e-6, n, M1fcn);\n%! M1fcn = @(x, string) Mfcn (M1, x, string);\n%! M2fcn = @(x, string) Mfcn (M2, x, string);\n%! x = bicg (Afcn, b, 1e-6, n, M1fcn, M2fcn);\n%! Afcn = @(x, string, p) Ap (A, x, string, p);\n%! ## Solution of A^2 * x = b\n%! x = bicg (Afcn, b, [], 2*n, [], [], [], 2);\n\n%!test\n%! ## Check that all type of inputs work\n%! A = sparse (toeplitz ([2, 1, 0, 0, 0], [2, -1, 0, 0, 0]));\n%! b = A * ones (5, 1);\n%! M1 = diag (sqrt (diag (A)));\n%! M2 = M1;\n%! Afcn = @(z, string) strcmp (string, \"notransp\") * (A * z) + ...\n%!                     strcmp (string, \"transp\") * (A' * z);\n%! M1_fcn = @(z, string) strcmp (string,\"notransp\") * (M1 \\ z) + ...\n%!                         strcmp (string, \"transp\") * (M1' \\ z);\n%! M2_fcn = @(z, string) strcmp (string, \"notransp\") * (M2 \\ z) + ...\n%!                         strcmp (string, \"transp\") * (M2' \\ z);\n%! [x, flag] = bicg (A, b);\n%! assert (flag, 0);\n%! [x, flag] = bicg (A, b, [], [], M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = bicg (A, b, [], [], M1_fcn, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = bicg (A, b,[], [], M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = bicg (A, b,[], [], M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = bicg (Afcn, b);\n%! assert (flag, 0);\n%! [x, flag] = bicg (Afcn, b,[], [], M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = bicg (Afcn, b,[], [], M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = bicg (Afcn, b,[], [], M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = bicg (Afcn, b,[], [], M1_fcn, M2_fcn);\n%! assert (flag, 0);\n\n%!test\n%! n = 100;\n%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);\n%! b = sum (A, 2);\n%! tol = 1e-8;\n%! maxit = 15;\n%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);\n%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);\n%! [x, flag, relres, iter, resvec] = bicg (A, b, tol, maxit, M1, M2);\n%! assert (norm (b - A*x) / norm (b), 0, tol);\n\n%!function y = afcn (x, t, a)\n%!  switch (t)\n%!    case \"notransp\"\n%!      y = a * x;\n%!    case \"transp\"\n%!      y = a' * x;\n%!  endswitch\n%!endfunction\n%!\n%!test\n%! n = 100;\n%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);\n%! b = sum (A, 2);\n%! tol = 1e-8;\n%! maxit = 15;\n%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);\n%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);\n%!\n%! [x, flag, relres, iter, resvec] = bicg (@(x, t) afcn (x, t, A),\n%!                                         b, tol, maxit, M1, M2);\n%! assert (x, ones (size (b)), 1e-7);\n\n%!test\n%! n = 100;\n%! tol = 1e-8;\n%! a = sprand (n, n, .1);\n%! A = a' * a + 100 * eye (n);\n%! b = sum (A, 2);\n%! [x, flag, relres, iter, resvec] = bicg (A, b, tol, [], diag (diag (A)));\n%! assert (x, ones (size (b)), 1e-7);\n\n%!test\n%! ## Check that if the preconditioner is singular, the method doesn't work\n%! A = sparse (toeplitz ([2, 1, 0, 0, 0], [2, -1, 0, 0, 0]));\n%! b = ones (5,1);\n%! M = ones (5);\n%! [x, flag] = bicg (A, b, [], [], M);\n%! assert (flag, 2);\n\n%!test\n%! ## If A singular, the algorithm doesn't work due to division by zero\n%! A = ones (5);\n%! b = [1:5]';\n%! [x, flag] = bicg (A, b);\n%! assert (flag, 4);\n\n%!test\n%! ## test for a complex linear system\n%! A = sparse (toeplitz ([2, 1, 0, 0, 0], [2, -1, 0, 0, 0]) + ...\n%!             1i * toeplitz ([2, 1, 0, 0, 0], [2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! [x, flag] = bicg (A, b);\n%! assert (flag, 0);\n\n%!test\n%! A = single (1);\n%! b = 1;\n%! [x, flag] = bicg (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = 1;\n%! b = single (1);\n%! [x, flag] = bicg (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = single (1);\n%! b = single (1);\n%! [x, flag] = bicg (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%!function y = Afcn (x, trans)\n%!  A = sparse (toeplitz ([2, 1, 0, 0], [2, -1, 0, 0]));\n%!  if (strcmp (trans, \"notransp\"))\n%!     y = A * x;\n%!  else\n%!     y = A' * x;\n%!  endif\n%!endfunction\n%!\n%! [x, flag] = bicg (\"Afcn\", [1; 2; 2; 3]);\n%! assert (x, ones (4, 1), 1e-6);\n\n%!test\n%! ## unpreconditioned residual\n%! A = sparse (toeplitz ([2, 1, 0, 0, 0], [2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M = magic (5);\n%! [x, flag, relres] = bicg (A, b, [], 2, M);\n%! assert (norm (b - A * x) / norm (b), 0, relres + eps);\n\n## Preconditioned technique\n%!testif HAVE_UMFPACK\n%! A = sparse (toeplitz ([2, 1, 0, 0, 0], [2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! [M1, M2] = lu (A + eye (5));\n%! [x, flag] = bicg (A, b, [], 1, M1, M2);\n%! ## b has two columns!\n%! [y, flag]  = bicg (M1 \\ A / M2, [M1 \\ b, M2' \\ b], [], 1);\n%! assert (x, M2 \\ y, 8 * eps);\n\n%!test <*63860>\n%! ## additional input argument\n%! n = 10;\n%! s = 1e-3;\n%! tol = 1e-6;\n%! a = ones (n, 1);\n%! a = a / norm (a);\n%! y = zeros (n, 1);\n%! y(1:2:n) = 1;\n%! Amat = @(x, type, s) x + (s * a) * (a' * x);\n%! [x, flag] = bicg (Amat, y, tol, [], [], [], y, s);\n%! assert (y, Amat (x, [], s), tol * norm (y));\n"
  },
  {
    "path": "scripts/sparse/bicgstab.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} bicgstab (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0}, @dots{})\n## @deftypefnx {} {@var{x} =} bicgstab (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M}, [], @var{x0}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} bicgstab (@var{A}, @var{b}, @dots{})\n## Solve @code{A x = b} using the stabilized Bi-conjugate gradient iterative\n## method.\n##\n## The input parameters are:\n##\n## @itemize @minus\n##\n## @item @var{A} is the matrix of the linear system and it must be square.\n## @var{A} can be passed as a matrix, function handle, or inline\n## function @code{Afcn} such that @code{Afcn(x) = A * x}.  Additional\n## parameters to @code{Afcn} are passed after @var{x0}.\n##\n## @item @var{b} is the right hand side vector.  It must be a column vector\n## with the same number of rows as @var{A}.\n##\n## @item\n## @var{tol} is the required relative tolerance for the residual error,\n## @w{@code{@var{b} - @var{A} * @var{x}}}.  The iteration stops if\n## @w{@code{norm (@var{b} - @var{A} * @var{x})} @leq{}\n## @w{@code{@var{tol} * norm (@var{b})}}}.\n## If @var{tol} is omitted or empty, then a tolerance of 1e-6 is used.\n##\n## @item @var{maxit} the maximum number of outer iterations, if not given or\n## set to [] the default value @code{min (20, numel (b))} is used.\n##\n## @item @var{M1}, @var{M2} are the preconditioners.  The preconditioner\n## @var{M} is given as @code{@var{M} = @var{M1} * @var{M2}}.\n## Both @var{M1} and @var{M2} can be passed as a matrix or as a function\n## handle or inline function @code{g} such that\n## @code{g(@var{x}) = @var{M1} \\ @var{x}} or\n## @code{g(@var{x}) = @var{M2} \\ @var{x}}.\n## The technique used is the right preconditioning, i.e., it is\n## solved @code{@var{A} * inv (@var{M}) * @var{y} = @var{b}} and then\n## @code{@var{x} = inv (@var{M}) * @var{y}}.\n##\n## @item @var{x0} the initial guess, if not given or set to [] the default\n## value @code{zeros (size (@var{b}))} is used.\n##\n## @end itemize\n##\n## The arguments which follow @var{x0} are treated as parameters, and passed in\n## a proper way to any of the functions (@var{A} or @var{M}) which are passed\n## to @code{bicstab}.\n##\n## The output parameters are:\n##\n## @itemize @minus\n##\n## @item @var{x} is the approximation computed.  If the method doesn't\n## converge then it is the iterated with the minimum residual.\n##\n## @item @var{flag} indicates the exit status:\n##\n## @itemize @minus\n## @item 0: iteration converged to the within the chosen tolerance\n##\n## @item 1: the maximum number of iterations was reached before convergence\n##\n## @item 2: the preconditioner matrix is singular\n##\n## @item 3: the algorithm reached stagnation\n##\n## @item 4: the algorithm can't continue due to a division by zero\n## @end itemize\n##\n## @item @var{relres} is the relative residual obtained with as\n## @code{(@var{A}*@var{x}-@var{b}) / @code{norm(@var{b})}}.\n##\n## @item @var{iter} is the (possibly half) iteration which @var{x} is\n## computed.  If it is an half iteration then it is @code{@var{iter} + 0.5}\n##\n## @item @var{resvec} is a vector containing the residual of each half and\n## total iteration (There are also the half iterations since @var{x} is\n## computed in two steps at each iteration).\n## Doing @code{(length(@var{resvec}) - 1) / 2} is possible to see the\n## total number of (total) iterations performed.\n##\n## @end itemize\n##\n## Let us consider a trivial problem with a tridiagonal matrix\n##\n## @example\n## @group\n## n = 20;\n## A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n##     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n##     sparse (1, 2, 1, 1, n) * n / 2);\n## b = A * ones (n, 1);\n## restart = 5;\n## [M1, M2] = ilu (A); # in this tridiag case, it corresponds to lu (A)\n## M = M1 * M2;\n## Afcn = @@(x) A * x;\n## Mfcn = @@(x) M \\ x;\n## M1fcn = @@(x) M1 \\ x;\n## M2fcn = @@(x) M2 \\ x;\n## @end group\n## @end example\n##\n## @sc{Example 1:} simplest usage of @code{bicgstab}\n##\n## @example\n## x = bicgstab (A, b, [], n)\n## @end example\n##\n## @sc{Example 2:} @code{bicgstab} with a function which computes\n## @code{@var{A} * @var{x}}\n##\n## @example\n## x = bicgstab (Afcn, b, [], n)\n## @end example\n##\n## @sc{Example 3:} @code{bicgstab} with a preconditioner matrix @var{M}\n##\n## @example\n## x = bicgstab (A, b, [], 1e-06, n, M)\n## @end example\n##\n## @sc{Example 4:} @code{bicgstab} with a function as preconditioner\n##\n## @example\n## x = bicgstab (Afcn, b, 1e-6, n, Mfcn)\n## @end example\n##\n## @sc{Example 5:} @code{bicgstab} with preconditioner matrices @var{M1}\n## and @var{M2}\n##\n## @example\n## x = bicgstab (A, b, [], 1e-6, n, M1, M2)\n## @end example\n##\n## @sc{Example 6:} @code{bicgstab} with functions as preconditioners\n##\n## @example\n## x = bicgstab (Afcn, b, 1e-6, n, M1fcn, M2fcn)\n## @end example\n##\n## @sc{Example 7:} @code{bicgstab} with as input a function requiring\n## an argument\n##\n## @example\n## @group\n## function y = Ap (A, x, z) # compute A^z * x\n##    y = x;\n##    for i = 1:z\n##      y = A * y;\n##    endfor\n##  endfunction\n## Apfcn = @@(x, string, p) Ap (A, x, string, p);\n## x = bicgstab (Apfcn, b, [], [], [], [], [], 2);\n## @end group\n## @end example\n##\n## @sc{Example 8:} explicit example to show that @code{bicgstab} uses a\n## right preconditioner\n##\n## @example\n## @group\n## [M1, M2] = ilu (A + 0.1 * eye (n)); # factorization of A perturbed\n## M = M1 * M2;\n##\n## ## reference solution computed by bicgstab after one iteration\n## [x_ref, fl] = bicgstab (A, b, [], 1, M)\n##\n## ## right preconditioning\n## [y, fl] = bicgstab (A / M, b, [], 1)\n## x = M \\ y # compare x and x_ref\n##\n## @end group\n## @end example\n##\n## Reference:\n##\n## @nospell{Y. Saad}, @cite{Iterative Methods for Sparse Linear Systems},\n## 2nd edition, SIAM, 2003.\n##\n## @seealso{bicg, cgs, gmres, pcg, qmr, tfqmr}\n##\n## @end deftypefn\n\nfunction [x_min, flag, relres, iter_min, resvec] = ...\n         bicgstab (A, b, tol = [], maxit = [], M1 = [], M2 = [], ...\n                   x0 = [], varargin)\n\n  ## Check consistency and type of A, M1, M2\n  [Afcn, M1fcn, M2fcn] =  __alltohandles__ (A, b, M1, M2, \"bicgstab\");\n\n  ## Check if input tol are empty (set them to default if necessary)\n  [tol, maxit, x0] = __default__input__ ({1e-06, min(rows(b), 20), ...\n                    zeros(rows (b), 1)}, tol, maxit, x0);\n\n  norm_b = norm (b, 2);\n  if (norm_b == 0)\n    if (nargout < 2)\n      printf (\"The right hand side vector is all zero so bicgstab \\n\")\n      printf (\"returned an all zero solution without iterating.\\n\")\n    endif\n    x_min = zeros (numel (b), 1);\n    iter_min = 0;\n    flag = 0;\n    resvec = 0;\n    relres = 0;\n    return;\n  endif\n\n  ## Double maxit to mind also the \"half iterations\"\n  d_maxit = 2 * maxit;\n  iter = iter_min = 0;\n  resvec = zeros (d_maxit,1);\n  x = x_min = x_pr = x0;\n  iter = iter_min = 0;\n  ## default setting of flag is 1 (i.e., max number of iterations reached)\n  flag = 1;\n\n  res = b - feval (Afcn, x, varargin{:});\n  rr = p = res; # rr is r_star\n  rho_1 = rr' * res;\n  resvec (1) = norm (res,2);\n  real_tol = norm_b * tol;\n\n  ## To check if the preconditioners are singular or they have some NaN\n  try\n    warning (\"error\", \"Octave:singular-matrix\", \"local\");\n    p_hat = feval (M1fcn, p, varargin{:});\n    p_hat = feval (M2fcn, p_hat, varargin{:});\n  catch\n    flag = 2;\n  end_try_catch\n\n  while (flag !=2) && (iter < d_maxit) && (resvec (iter + 1) >= real_tol)\n    v = feval (Afcn, p_hat, varargin{:});\n    prod_tmp = (rr' * v);\n    if (prod_tmp == 0)\n      flag = 4;\n      break;\n    endif\n    alpha = rho_1 / (prod_tmp);\n    x += alpha * p_hat;\n    s = res - alpha * v;\n    iter += 1;\n    resvec (iter+1) = norm (s,2);\n    if (resvec (iter + 1) <= real_tol) # reached the tol\n      x_min = x;\n      iter_min = iter;\n      break;\n    elseif (resvec (iter + 1) <= resvec (iter_min + 1)) # Found min residual\n      x_min = x;\n      iter_min = iter;\n    endif\n    s_hat = feval (M1fcn, s, varargin{:});\n    s_hat = feval (M2fcn, s_hat, varargin{:});\n    t = feval (Afcn, s_hat, varargin{:});\n    omega = (t' * s) / (t' * t);\n    if (omega == 0) # x and residual don't change and the next it will be NaN\n      flag = 4;\n      break;\n    endif\n    x += omega * s_hat;\n    res = s - omega * t;\n    iter += 1;\n    resvec (iter + 1) = norm (res);\n    if (resvec (iter + 1) <= resvec (iter_min + 1))\n      x_min = x;\n      iter_min = iter;\n    endif\n    if (norm (x - x_pr) <= norm (x) * eps)\n      flag = 3;\n      break;\n    endif\n    x_pr = x;\n    rho_2 = rho_1;\n    rho_1 = rr' * res;\n    if (rho_1 == 0) # x and residual don't change and the next it will be NaN\n      flag = 4;\n      break;\n    endif\n    beta = (rho_1 / rho_2) * (alpha / omega);\n    p = res + beta * (p - omega*  v);\n    p_hat = feval (M1fcn, p, varargin{:});\n    p_hat = feval (M2fcn, p_hat, varargin{:});\n  endwhile\n  resvec = resvec (1:iter+1,1);\n\n  relres = resvec (iter_min + 1) / norm_b;  # I set the relative residual\n  iter /=  2;\n  iter_min /= 2;\n\n  if (flag == 1) && (relres <= tol)\n    flag = 0;\n  endif\n\n  ## output strings to print when the outputs requested are less than 2\n  if (nargout < 2)\n    switch (flag)\n      case {0}\n        printf (\"bicgstab converged at iteration %i \", iter_min);\n        printf (\"to a solution with relative residual %e\\n\", relres);\n      case {1}\n        printf (\"bicgstab stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the maximum number of iterations was reached.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case {2}\n        printf (\"bicgstab stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the preconditioner matrix is singular.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case {3}\n        printf (\"bicgstab stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the method stagnated.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case {4}\n        printf (\"bicgstab stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the method can't continue.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n    endswitch\n  endif\n\nendfunction\n\n\n%!demo # simplest use\n%! n = 20;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n%!     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n%!               sparse (1, 2, 1, 1, n) * n / 2);\n%! b = A * ones (n, 1);\n%! [M1, M2] = ilu (A + 0.1 * eye (n));\n%! M = M1 * M2;\n%! x = bicgstab (A, b, [], n);\n%! Afcn = @(x) A * x;\n%! x = bicgstab (Afcn, b, [], n);\n%! x = bicgstab (A, b, 1e-6, n, M);\n%! x = bicgstab (A, b, 1e-6, n, M1, M2);\n%! Mfcn = @(z) M \\ z;\n%! x = bicgstab (Afcn, b, 1e-6, n, Mfcn);\n%! M1fcn = @(z) M1 \\ z;\n%! M2fcn = @(z) M2 \\ z;\n%! x = bicgstab (Afcn, b, 1e-6, n, M1fcn, M2fcn);\n%! function y = Ap (A, x, z)\n%!   ## compute A^z * x or (A^z)' * x\n%!   y = x;\n%!   for i = 1:z\n%!     y = A * y;\n%!   endfor\n%! endfunction\n%! Afcn = @(x, p) Ap (A, x, p);\n%! x = bicgstab (Afcn, b, [], 2 * n, [], [], [], 2); # solution of A^2 * x = b\n\n%!demo\n%! n = 10;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n%!     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n%!               sparse (1, 2, 1, 1, n) * n / 2);\n%! b = A * ones (n, 1);\n%! [M1, M2] = ilu (A + 0.3 * eye (n));  # factorization of A perturbed\n%! M = M1 * M2;\n%!\n%! ## Reference solution computed by bicgstab after one iteration\n%! [x_ref, fl] = bicgstab (A, b, [], 1, M);\n%! x_ref\n%!\n%! ## right preconditioning\n%! [y, fl] = bicgstab (A / M, b, [], 1);\n%! ## Compare x and x_ref\n%! x = M \\ y\n\n%!test\n%! ## Check that all type of inputs work\n%! A = toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M1 = diag (sqrt (diag (A)));\n%! M2 = M1;\n%! maxit = 20;\n%! Afcn = @(z) A*z;\n%! M1_fcn = @(z) M1 \\ z;\n%! M2_fcn = @(z) M2 \\ z;\n%! [x, flag] = bicgstab (A,b );\n%! assert (flag, 0);\n%! [x, flag] = bicgstab (A, b, [], maxit, M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = bicgstab (A, b, [], maxit, M1_fcn, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = bicgstab (A, b, [], maxit, M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = bicgstab (A, b, [], maxit, M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = bicgstab (Afcn, b);\n%! assert (flag, 0);\n%! [x, flag] = bicgstab (Afcn, b, [], maxit, M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = bicgstab (Afcn, b, [], maxit, M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = bicgstab (Afcn, b, [], maxit, M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = bicgstab (Afcn, b, [], maxit, M1_fcn, M2_fcn);\n%! assert (flag, 0);\n\n%!shared n, A, b, tol, maxit, M1, M2\n%! n = 100;\n%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);\n%! b = sum (A, 2);\n%! tol = 1e-8;\n%! maxit = 15;\n%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);\n%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);\n\n%!test\n%! [x, flag, relres, iter, resvec] = bicgstab (A, b, tol, maxit, M1, M2);\n%! assert (norm (b - A*x) / norm (b), 0, tol);\n\n%!function y = afcn (x, a)\n%!  y = a * x;\n%!endfunction\n%!\n%!test\n%! [x, flag, relres, iter, resvec] = bicgstab (@(x) afcn (x, A), b,\n%!                                             tol, maxit, M1, M2);\n%! assert (norm (b - A*x) / norm (b), 0, tol);\n\n%!test\n%! a = sprand (n, n, .1);\n%! A = a'*a + 100 * speye (n);\n%! b = sum (A, 2);\n%! [x, flag, relres, iter, resvec] = bicgstab (A, b, tol, [], diag (diag (A)));\n%! assert (norm (b - A*x) / norm (b), 0, tol);\n\n%!test\n%! ## bicgstab solves complex linear systems\n%! A = [1 + 1i, 1 + 1i; 2 - 1i, 2 + 1i];\n%! b = A * [1; 1];\n%! [x, flag, relres, iter, resvec] = bicgstab (A, b);\n%! assert (norm (b - A*x) / norm (b), 0, 1e-6);\n\n%!test\n%! ## test with a non-symmetric matrix\n%! A = diag (1:50);\n%! A(1,50) = 10000;\n%! b = ones (50,1);\n%! [x, flag, relres, iter, resvec] = bicgstab (A, b, [], 100);\n%! assert (flag, 0);\n%! assert (norm (b - A*x) / norm (b), 0, 1e-6);\n\n%!test\n%! ## test that bicgstab detects a singular preconditioner\n%! M = ones (50);\n%! M(1,1) = 0;\n%! [x, flag] = bicgstab (A, b, [], 100, M);\n%! assert (flag, 2);\n\n%!test\n%! A = single (1);\n%! b = 1;\n%! [x, flag] = bicgstab (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = 1;\n%! b = single (1);\n%! [x, flag] = bicgstab (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = single (1);\n%! b = single (1);\n%! [x, flag] = bicgstab (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%!function y = Afcn (x)\n%!  A = sparse (toeplitz ([2, 1, 0, 0], [2, -1, 0, 0]));\n%!  y = A * x;\n%!endfunction\n%!\n%! b = [1; 2; 2; 3];\n%! [x, flag] = bicgstab (\"Afcn\", b);\n%! assert (norm (b - A*x) / norm (b), 0, 1e-6);\n\n%!test\n%! ## unpreconditioned residual\n%! A = sparse (toeplitz ([2, 1, 0, 0, 0], [2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M = magic (5);\n%! [x, flag, relres] = bicgstab (A, b, [], 2, M);\n%! assert (norm (b - A * x) / norm (b), relres, 8*eps);\n"
  },
  {
    "path": "scripts/sparse/cgs.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} cgs (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0}, @dots{})\n## @deftypefnx {} {@var{x} =} cgs (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M}, [], @var{x0}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} cgs (@var{A}, @var{b}, @dots{})\n## Solve @code{A x = b}, where @var{A} is a square matrix, using the\n## Conjugate Gradients Squared method.\n##\n## The input arguments are:\n##\n## @itemize @minus\n##\n## @item @var{A} is the matrix of the linear system and it must be square.\n## @var{A} can be passed as a matrix, function handle, or inline\n## function @code{Afcn} such that @code{Afcn(x) = A * x}.  Additional\n## parameters to @code{Afcn} are passed after @var{x0}.\n##\n## @item @var{b} is the right hand side vector.  It must be a column vector\n## with same number of rows of @var{A}.\n##\n## @item @var{tol} is the relative tolerance, if not given or set to [] the\n## default value 1e-6 is used.\n##\n## @item @var{maxit} the maximum number of outer iterations, if not given or\n## set to [] the default value @code{min (20, numel (b))} is used.\n##\n## @item @var{M1}, @var{M2} are the preconditioners.  The preconditioner\n## matrix is given as @code{M = M1 * M2}.  Both @var{M1}\n## and @var{M2} can be passed as a matrix or as a function handle or inline\n## function @code{g} such that @code{g(x) = M1 \\ x} or @code{g(x) = M2 \\ x}.\n## If M1 is empty or not passed then no preconditioners are applied.\n## The technique used is the right preconditioning, i.e., it is solved\n## @code{@var{A}*inv(@var{M})*y = b} and then @code{@var{x} = inv(@var{M})*y}.\n##\n## @item @var{x0} the initial guess, if not given or set to [] the default\n## value @code{zeros (size (b))} is used.\n## @end itemize\n##\n## The arguments which follow @var{x0} are treated as parameters, and passed in\n## a proper way to any of the functions (@var{A} or @var{P}) which are passed\n## to @code{cgs}.\n##\n## The output parameters are:\n##\n## @itemize @minus\n##\n## @item @var{x} is the approximation computed.  If the method doesn't\n## converge then it is the iterated with the minimum residual.\n##\n## @item @var{flag} indicates the exit status:\n##\n## @itemize @minus\n## @item 0: iteration converged to the within the chosen tolerance\n##\n## @item 1: the maximum number of iterations was reached before convergence\n##\n## @item 2: the preconditioner matrix is singular\n##\n## @item 3: the algorithm reached stagnation\n##\n## @item 4: the algorithm can't continue due to a division by zero\n## @end itemize\n##\n## @item @var{relres} is the relative residual obtained with as\n## @code{(@var{A}*@var{x}-@var{b}) / @code{norm(@var{b})}}.\n##\n## @item @var{iter} is the iteration which @var{x} is computed.\n##\n## @item @var{resvec} is a vector containing the residual at each iteration.\n## Doing @code{length(@var{resvec}) - 1} is possible to see the total number\n## of iterations performed.\n## @end itemize\n##\n## Let us consider a trivial problem with a tridiagonal matrix\n##\n## @smallexample\n## @group\n## n = 20;\n## A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n##     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n##     sparse (1, 2, 1, 1, n) * n / 2);\n## b = A * ones (n, 1);\n## restart = 5;\n## [M1, M2] = ilu (A); # in this tridiag case it corresponds to chol (A)'\n## M = M1 * M2;\n## Afcn = @@(x) A * x;\n## Mfcn = @@(x) M \\ x;\n## M1fcn = @@(x) M1 \\ x;\n## M2fcn = @@(x) M2 \\ x;\n## @end group\n## @end smallexample\n##\n## @sc{Example 1:} simplest usage of @code{cgs}\n##\n## @example\n## x = cgs (A, b, [], n)\n## @end example\n##\n## @sc{Example 2:} @code{cgs} with a function which computes\n## @code{@var{A} * @var{x}}\n##\n## @example\n## x = cgs (Afcn, b, [], n)\n## @end example\n##\n## @sc{Example 3:} @code{cgs} with a preconditioner matrix @var{M}\n##\n## @example\n## x = cgs (A, b, [], 1e-06, n, M)\n## @end example\n##\n## @sc{Example 4:} @code{cgs} with a function as preconditioner\n##\n## @example\n## x = cgs (Afcn, b, 1e-6, n, Mfcn)\n## @end example\n##\n## @sc{Example 5:} @code{cgs} with preconditioner matrices @var{M1}\n## and @var{M2}\n##\n## @example\n## x = cgs (A, b, [], 1e-6, n, M1, M2)\n## @end example\n##\n## @sc{Example 6:} @code{cgs} with functions as preconditioners\n##\n## @example\n## x = cgs (Afcn, b, 1e-6, n, M1fcn, M2fcn)\n## @end example\n##\n## @sc{Example 7:} @code{cgs} with as input a function requiring an argument\n##\n## @example\n## @group\n## function y = Ap (A, x, z) # compute A^z * x\n##    y = x;\n##    for i = 1:z\n##      y = A * y;\n##    endfor\n##  endfunction\n## Apfcn = @@(x, string, p) Ap (A, x, string, p);\n## x = cgs (Apfcn, b, [], [], [], [], [], 2);\n## @end group\n## @end example\n##\n## @sc{Example 8:} explicit example to show that @code{cgs} uses a\n## right preconditioner\n##\n## @example\n## @group\n## [M1, M2] = ilu (A + 0.3 * eye (n)); # factorization of A perturbed\n## M = M1 * M2;\n##\n## ## reference solution computed by cgs after one iteration\n## [x_ref, fl] = cgs (A, b, [], 1, M)\n##\n## ## right preconditioning\n## [y, fl] = cgs (A / M, b, [], 1)\n## x = M \\ y # compare x and x_ref\n##\n## @end group\n## @end example\n##\n## References:\n##\n## @nospell{Y. Saad}, @cite{Iterative Methods for Sparse Linear Systems},\n## 2nd edition, SIAM, 2003.\n##\n## @seealso{pcg, bicgstab, bicg, gmres, qmr, tfqmr}\n## @end deftypefn\n\nfunction [x_min, flag, relres, iter_min, resvec] = ...\n         cgs (A, b, tol = [], maxit = [], M1 = [] , M2 = [], x0 = [], varargin)\n\n  [Afcn, M1fcn, M2fcn] = __alltohandles__ (A, b, M1, M2, \"cgs\");\n\n  [tol, maxit, x0] = __default__input__ ({1e-06, min( rows(b), 20), ...\n                                          zeros(size (b))}, tol, maxit, x0);\n\n  norm_b = norm (b, 2);\n  if (norm_b == 0)\n    if (nargout < 2)\n      printf (\"The right hand side vector is all zero so cgs \\n\")\n      printf (\"returned an all zero solution without iterating.\\n\")\n    endif\n    x_min = zeros (numel (b), 1);\n    iter_min = 0;\n    flag = 0;\n    resvec = 0;\n    relres = 0;\n    return;\n  endif\n\n  resvec = zeros (maxit, 1); # Preallocation of resvec\n\n  flag = 1; # Default flag is 1, i.e., maximum number of iterations reached\n  iter = iter_min = 0;\n  x = x_min = x_pr = x0;\n  ## x approximation at the actual iteration\n  ## x_min approximation with the minimum residual\n  ## x_pr approximation at the previous iteration (to check stagnation)\n\n  r0 = rr = u = p = b - feval (Afcn, x, varargin{:});\n  resvec (1) = norm (r0, 2);\n  rho_1 = rr' * r0;\n\n  try\n    warning (\"error\",\"Octave:singular-matrix\",\"local\");\n    p_hat = feval (M1fcn, p, varargin{:});\n    p_hat = feval (M2fcn, p_hat, varargin {:});\n  catch\n    flag = 2;\n  end_try_catch\n\n  while ((flag != 2) && (iter < maxit) && ...\n         (resvec (iter + 1) >= tol * norm_b))\n    v = feval (Afcn, p_hat, varargin{:});\n    prod_tmp = (rr' * v);\n    if (prod_tmp == 0)\n      flag = 4;\n      break;\n    endif\n    alpha = rho_1 / prod_tmp;\n    q = u - alpha * v;\n    u_hat = feval(M1fcn, u + q, varargin{:});\n    u_hat = feval (M2fcn, u_hat, varargin{:});\n    x += alpha*u_hat;\n    r0 -= alpha* feval (Afcn, u_hat, varargin{:});\n    iter += 1;\n    resvec (iter + 1) = norm (r0, 2);\n    if (norm (x - x_pr, 2) <= norm (x, 2) * eps) # Stagnation\n      flag = 3;\n      break;\n    endif\n    if (resvec (iter + 1) <= resvec (iter_min + 1)) # Check min residual\n      x_min = x;\n      iter_min = iter;\n    endif\n    x_pr = x;\n    rho_2 = rho_1;\n    rho_1 = rr' * r0;\n    if (rho_1 == 0)\n      flag = 4;\n      break;\n    endif\n    beta = rho_1 / rho_2;\n    u = r0 + beta * q;\n    p = u + beta * (q + beta * p);\n    p_hat = feval (M1fcn, p, varargin {:});\n    p_hat = feval (M2fcn, p_hat, varargin{:});\n  endwhile\n  resvec = resvec (1: (iter + 1));\n\n  relres = resvec (iter_min + 1) / norm_b;\n  if (relres <= tol) && (flag = 1)\n    flag = 0;\n  endif\n\n  if (nargout < 2)\n    switch (flag)\n      case {0}\n        printf (\"cgs converged at iteration %i \", iter_min);\n        printf (\"to a solution with relative residual %e\\n\", relres);\n      case {1}\n        printf (\"cgs stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the maximum number of iterations was reached.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case {2}\n        printf (\"cgs stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the preconditioner matrix is singular.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case {3}\n        printf (\"cgs stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the method stagnated.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case {4}\n        printf (\"cgs stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the method can't continue.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n    endswitch\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Solve system of A*x=b\n%! A = [5 -1 3;-1 2 -2;3 -2 3];\n%! b = [7;-1;4];\n%! [a,b,c,d,e] = cgs (A,b)\n\n%!demo\n%! ## simplest use case\n%! n = 20;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n%!     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n%!               sparse (1, 2, 1, 1, n) * n / 2);\n%! b = A * ones (n, 1);\n%! [M1, M2] = ilu (A + 0.1 * eye (n));\n%! M = M1 * M2;\n%! x = cgs (A, b, [], n);\n%! Afcn = @(x) A * x;\n%! x = cgs (Afcn, b, [], n);\n%! x = cgs (A, b, 1e-6, n, M);\n%! x = cgs (A, b, 1e-6, n, M1, M2);\n%! Mfcn = @(z) M \\ z;\n%! x = cgs (Afcn, b, 1e-6, n, Mfcn);\n%! M1fcn = @(z) M1 \\ z;\n%! M2fcn = @(z) M2 \\ z;\n%! x = cgs (Afcn, b, 1e-6, n, M1fcn, M2fcn);\n%! function y = Ap (A, x, z)\n%!   ## compute A^z * x or (A^z)' * x\n%!   y = x;\n%!   for i = 1:z\n%!     y = A * y;\n%!   endfor\n%! endfunction\n%! Afcn = @(x, p) Ap (A, x, p);\n%! x = cgs (Afcn, b, [], 2*n, [], [], [], 2); # solution of A^2 * x = b\n\n%!demo\n%! n = 10;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n%!     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n%!               sparse (1, 2, 1, 1, n) * n / 2);\n%! b = A * ones (n, 1);\n%! [M1, M2] = ilu (A + 0.3 * speye (n));  # factorization of A perturbed\n%! M = M1 * M2;\n%!\n%! ## Reference solution computed by cgs after one iteration\n%! [x_ref, fl] = cgs (A, b, [], 1, M);\n%! x_ref\n%!\n%! ## right preconditioning\n%! [y, fl] = cgs (A / M, b, [], 1);\n%! ## Compare x and x_ref\n%! x = M \\ y\n\n%!test\n%! ## Check that all type of inputs work\n%! A = sparse (toeplitz ([2, 1, 0, 0, 0], [2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M1 = diag (sqrt (diag (A)));\n%! M2 = M1;\n%! maxit = 10;\n%! Afcn = @(z) A * z;\n%! M1_fcn = @(z) M1 \\ z;\n%! M2_fcn = @(z) M2 \\ z;\n%! [x, flag] = cgs (A,b);\n%! assert (flag, 0);\n%! [x, flag] = cgs (A, b, [], maxit, M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = cgs (A, b, [], maxit, M1_fcn, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = cgs (A, b, [], maxit, M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = cgs (A, b, [], maxit, M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = cgs (Afcn, b);\n%! assert (flag, 0);\n%! [x, flag] = cgs (Afcn, b, [], maxit, M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = cgs (Afcn, b, [], maxit, M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = cgs (Afcn, b, [], maxit, M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = cgs (Afcn, b, [], maxit, M1_fcn, M2_fcn);\n%! assert (flag, 0);\n\n%!shared n, A, b, tol, maxit, M\n%!\n%!test\n%! n = 100;\n%! A = spdiags ([-ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);\n%! b = sum (A, 2);\n%! tol = 1e-8;\n%! maxit = 1000;\n%! M = 4 * eye (n);\n%! [x, flag, relres, iter, resvec] = cgs (A, b, tol, maxit, M);\n%! assert (norm (b - A*x) / norm (b), 0, tol);\n\n%!\n%!test\n%! maxit = 15;\n%! [x, flag, relres, iter, resvec] = cgs (@(x) A * x, b, tol, maxit, M);\n%! assert (norm (b - A*x) / norm (b), 0, tol);\n\n%!test\n%! a = sprand (n, n, .1);\n%! A = a'*a + 100 * eye (n);\n%! b = sum (A, 2);\n%! [x, flag, relres, iter, resvec] = cgs (A, b, tol, [], diag (diag (A)));\n%! assert (norm (b - A*x) / norm (b), 0, tol);\n\n%!test\n%! n = 5;\n%! A = sparse (toeplitz ([2, 1, 0, 0, 0], [2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M = ones (n);\n%! [x, flag] = cgs (A, b, [], [], M);\n%! assert (flag, 2);\n\n%!test\n%! A = single (1);\n%! b = 1;\n%! [x, flag] = cgs (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = 1;\n%! b = single (1);\n%! [x, flag] = cgs (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = single (1);\n%! b = single (1);\n%! [x, flag] = cgs (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%!function y = Afcn (x)\n%!  A = toeplitz ([2, 1, 0, 0], [2, -1, 0, 0]);\n%!  y = A * x;\n%!endfunction\n%! [x, flag] = cgs (\"Afcn\", [1; 2; 2; 3]);\n%! assert (norm (b - A*x) / norm (b), 0, 1e-6);\n\n%!test\n%! ## test a complex linear system\n%! A = toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0])) + ...\n%! 1i * toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! [x, flag] = cgs (A, b);\n%! assert (flag, 0);\n\n%!test\n%! ## unpreconditioned residual\n%! A = toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M = magic (5);\n%! [x, flag, relres] = cgs (A, b, [], 3, M);\n%! assert (norm (b - A * x) / norm (b), relres, 8 * eps);\n"
  },
  {
    "path": "scripts/sparse/colperm.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{p} =} colperm (@var{s})\n## Return the column permutations such that the columns of\n## @code{@var{s}(:, @var{p})} are ordered in terms of increasing number of\n## nonzero elements.\n##\n## If @var{s} is symmetric, then @var{p} is chosen such that\n## @code{@var{s}(@var{p}, @var{p})} orders the rows and columns with\n## increasing number of nonzero elements.\n## @end deftypefn\n\nfunction p = colperm (s)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  [~, p] = sort (sum (s != 0, 1));\n\nendfunction\n\n\n%!assert <*59226> (colperm ([1,0;0,0]), [2, 1])\n"
  },
  {
    "path": "scripts/sparse/eigs.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{d} =} eigs (@var{A})\n## @deftypefnx {} {@var{d} =} eigs (@var{A}, @var{k})\n## @deftypefnx {} {@var{d} =} eigs (@var{A}, @var{k}, @var{sigma})\n## @deftypefnx {} {@var{d} =} eigs (@var{A}, @var{k}, @var{sigma}, @var{opts})\n## @deftypefnx {} {@var{d} =} eigs (@var{A}, @var{B})\n## @deftypefnx {} {@var{d} =} eigs (@var{A}, @var{B}, @var{k})\n## @deftypefnx {} {@var{d} =} eigs (@var{A}, @var{B}, @var{k}, @var{sigma})\n## @deftypefnx {} {@var{d} =} eigs (@var{A}, @var{B}, @var{k}, @var{sigma}, @var{opts})\n## @deftypefnx {} {@var{d} =} eigs (@var{Af}, @var{n})\n## @deftypefnx {} {@var{d} =} eigs (@var{Af}, @var{n}, @var{k})\n## @deftypefnx {} {@var{d} =} eigs (@var{Af}, @var{n}, @var{k}, @var{sigma})\n## @deftypefnx {} {@var{d} =} eigs (@var{Af}, @var{n}, @var{k}, @var{sigma}, @var{opts})\n## @deftypefnx {} {@var{d} =} eigs (@var{Af}, @var{n}, @var{B})\n## @deftypefnx {} {@var{d} =} eigs (@var{Af}, @var{n}, @var{B}, @var{k})\n## @deftypefnx {} {@var{d} =} eigs (@var{Af}, @var{n}, @var{B}, @var{k}, @var{sigma})\n## @deftypefnx {} {@var{d} =} eigs (@var{Af}, @var{n}, @var{B}, @var{k}, @var{sigma}, @var{opts})\n## @deftypefnx {} {[@var{V}, @var{D}] =} eigs (@dots{})\n## @deftypefnx {} {[@var{V}, @var{D}, @var{flag}] =} eigs (@dots{})\n## Calculate a limited number of eigenvalues and eigenvectors based on a\n## selection criteria.\n##\n## By default, @code{eigs} solve the equation\n## @tex\n## $A \\nu = \\lambda \\nu$,\n## @end tex\n## @ifinfo\n## @code{A * v = lambda * v},\n## @end ifinfo\n## where\n## @tex\n## $\\lambda$ is a scalar representing one of the eigenvalues, and $\\nu$\n## @end tex\n## @ifinfo\n## @code{lambda} is a scalar representing one of the eigenvalues, and @code{v}\n## @end ifinfo\n## is the corresponding eigenvector.  If given the positive definite matrix\n## @var{B} then @code{eigs} solves the general eigenvalue equation\n## @tex\n## $A \\nu = \\lambda B \\nu$.\n## @end tex\n## @ifinfo\n## @code{A * v = lambda * B * v}.\n## @end ifinfo\n##\n## The input @var{A} is a square matrix of dimension @var{n}-by-@var{n}.\n## Typically, @var{A} is also large and sparse.\n##\n## The input @var{B} for the generalized eigenvalue problem is a square matrix\n## with the same size as @var{A} (@var{n}-by-@var{n}).  Typically, @var{B} is\n## also large and sparse.\n##\n## The number of eigenvalues and eigenvectors to calculate is given by @var{k}\n## and defaults to 6.\n##\n## The argument @var{sigma} determines which eigenvalues are returned.\n## @var{sigma} can be either a scalar or a string.  When @var{sigma} is a\n## scalar, the @var{k} eigenvalues closest to @var{sigma} are returned.  If\n## @var{sigma} is a string, it must be one of the following values.\n##\n## @table @asis\n## @item @nospell{@qcode{\"lm\"}}\n## Largest Magnitude (default).\n##\n## @item @nospell{@qcode{\"sm\"}}\n## Smallest Magnitude.\n##\n## @item @nospell{@qcode{\"la\"}}\n## Largest Algebraic (valid only for real symmetric problems).\n##\n## @item @nospell{@qcode{\"sa\"}}\n## Smallest Algebraic (valid only for real symmetric problems).\n##\n## @item @nospell{@qcode{\"be\"}}\n## Both Ends, with one more from the high-end if @var{k} is odd (valid only for\n## real symmetric problems).\n##\n## @item @nospell{@qcode{\"lr\"}}\n## Largest Real part (valid only for complex or unsymmetric problems).\n##\n## @item @nospell{@qcode{\"sr\"}}\n## Smallest Real part (valid only for complex or unsymmetric problems).\n##\n## @item @nospell{@qcode{\"li\"}}\n## Largest Imaginary part (valid only for complex or unsymmetric problems).\n##\n## @item @nospell{@qcode{\"si\"}}\n## Smallest Imaginary part (valid only for complex or unsymmetric problems).\n## @end table\n##\n## If @var{opts} is given, it is a structure defining possible options that\n## @code{eigs} should use.  The fields of the @var{opts} structure are:\n##\n## @table @code\n## @item issym\n## If @var{Af} is given then this flag (true/false) determines whether the\n## function @var{Af} defines a symmetric problem.  It is ignored if a matrix\n## @var{A} is given.  The default is false.\n##\n## @item isreal\n## If @var{Af} is given then this flag (true/false) determines whether the\n## function @var{Af} defines a real problem.  It is ignored if a matrix @var{A}\n## is given.  The default is true.\n##\n## @item tol\n## Defines the required convergence tolerance, calculated as\n## @code{tol * norm (A)}.  The default is @code{eps}.\n##\n## @item maxit\n## The maximum number of iterations.  The default is 300.\n##\n## @item p\n## The number of @nospell{Lanczos} basis vectors to use.  More vectors will\n## result in faster convergence, but a greater use of memory.  The optimal\n## value of @code{p} is problem dependent and should be in the range\n## @code{@var{k} + 1} to @var{n}.  The default value is @code{2 * @var{k}}.\n##\n## @item v0\n## The starting vector for the algorithm.  An initial vector close to the final\n## vector will speed up convergence.  The default is for @sc{arpack} to\n## randomly generate a starting vector.  If specified, @code{v0} must be\n## an @var{n}-by-1 vector where @code{@var{n} = rows (@var{A})}.\n##\n## @item disp\n## The level of diagnostic printout (0|1|2).  If @code{disp} is 0 then\n## diagnostics are disabled.  The default value is 0.\n##\n## @item cholB\n## If the generalized eigenvalue problem is being calculated, this flag\n## (true/false) specifies whether the @var{B} input represents\n## @code{chol (@var{B})} or simply the matrix @var{B}.  The default is false.\n##\n## @item permB\n## The permutation vector of the Cholesky@tie{}factorization for @var{B} if\n## @code{cholB} is true.  It is obtained by\n## @code{[R, ~, permB] = chol (@var{B}, @qcode{\"vector\"})}.  The default is\n## @code{1:@var{n}}.\n##\n## @end table\n##\n## It is also possible to represent @var{A} by a function denoted @var{Af}.\n## @var{Af} must be followed by a scalar argument @var{n} defining the length\n## of the vector argument accepted by @var{Af}.  @var{Af} can be a function\n## handle, an inline function, or a string.  When @var{Af} is a string it\n## holds the name of the function to use.\n##\n## @var{Af} is a function of the form @code{y = Af (x)} where the required\n## return value of @var{Af} is determined by the value of @var{sigma}.\n## The four possible forms are\n##\n## @table @code\n## @item A * x\n## if @var{sigma} is not given or is a string other than \"sm\".\n##\n## @item A \\ x\n## if @var{sigma} is 0 or \"sm\".\n##\n## @item (A - sigma * I) \\ x\n## if @var{sigma} is a scalar not equal to 0; @code{I} is the identity matrix\n## of the same size as @var{A}.\n##\n## @item (A - sigma * B) \\ x\n## for the general eigenvalue problem.\n## @end table\n##\n## The return arguments and their form depend on the number of return arguments\n## requested.  For a single return argument, a column vector @var{d} of length\n## @var{k} is returned containing the @var{k} eigenvalues that have been\n## found.  For two return arguments, @var{V} is an @var{n}-by-@var{k} matrix\n## whose columns are the @var{k} eigenvectors corresponding to the returned\n## eigenvalues.  The eigenvalues themselves are returned in @var{D} in the\n## form of a @var{k}-by-@var{k} matrix, where the elements on the diagonal\n## are the eigenvalues.\n##\n## The third return argument @var{flag} returns the status of the convergence.\n## If @var{flag} is 0 then all eigenvalues have converged.  Any other value\n## indicates a failure to converge.\n##\n## Programming Notes: For small problems, @var{n} < 500, consider using\n## @code{eig (full (@var{A}))}.\n##\n## If @sc{arpack} fails to converge consider increasing the number of\n## @nospell{Lanczos} vectors (@var{opt}.p), increasing the number of iterations\n## (@var{opt}.maxiter), or decreasing the tolerance (@var{opt}.tol).\n##\n## Reference:\n## This function is based on the @sc{arpack} package, written by\n## @nospell{R. Lehoucq, K. Maschhoff, D. Sorensen, and C. Yang}.  For more\n## information see @url{http://www.caam.rice.edu/software/ARPACK/}.\n##\n## @seealso{eig, svds}\n## @end deftypefn\n\n## Programming Note: For compatibility with Matlab, handle small matrix cases\n## and all-zero matrices in this m-file which ARPACK can not.\n\nfunction varargout = eigs (varargin)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  call_eig = false;  # flag whether to take shortcut path with eig()\n  have_A = false;\n  have_B = false;\n  offset = 0;\n  k = 6;\n  sigma = \"lm\";\n\n  ## FIXME: Input validation is split between eigs.m and __eigs__.cc.\n  ##        It would be simpler if all input validation was done in the m-file\n  ##        and then the internal function __eigs__ could be simplified to\n  ##        rely on having \"good\" inputs.\n  if (isnumeric (varargin{1}) && issquare (varargin{1}))\n    A = varargin{1};\n    have_A = true;\n    k = min (k, rows (A));  # reduce default k if necessary\n    if (nargin > 1)\n      if (! isnumeric (varargin{2}))\n        error (\"eigs: second argument must be numeric\");\n      endif\n      if (size_equal (A, varargin{2}))\n        B = varargin{2};\n        have_B = true;\n        offset = 1;\n      elseif (isempty (varargin{2}))\n        ## Special syntax to do regular eigenvalue decomposition rather\n        ## than generalized eigenvalue decomposition (B = []).\n        offset = 1;\n      endif\n    endif\n\n    if (rows (A) <= 12)  # p = 2*k criteria\n      call_eig = true;\n    endif\n\n    if (nargin > 1 + offset)\n      ## FIXME: Input validation should recognize improper inputs.\n      ##        Code below only checks for what it expects to find.\n      ##        Sample bad input: eigs (magic (5), [], {1})\n      arg = varargin{2+offset};\n      if (isnumeric (arg) && isscalar (arg) && isreal (arg)\n          && fix (arg) == arg)\n        k = arg;\n        p = 2 * k;\n      elseif (isfield (arg, \"p\"))\n        p = arg.p;\n      endif\n\n      if (nargin > 2 + offset)\n        arg = varargin{3+offset};\n        if (ischar (arg))\n          sigma = lower (arg);\n        elseif (isnumeric (arg) && isscalar (arg))\n          sigma = arg;\n        elseif (isfield (arg, \"p\"))\n          p = arg.p;\n        endif\n\n        if (nargin > 3 + offset)\n          arg = varargin{4+offset};\n          if (isfield (arg, \"p\"))\n            p = arg.p;\n          else\n            p = 2 * k;\n          endif\n        endif\n      endif\n\n      if (p >= rows (A))\n        call_eig = true;\n      else\n        call_eig = false;\n      endif\n    endif\n  endif\n\n  if (call_eig)\n    ## Special code path for small matrices which ARPACK does not handle.\n    varargout = cell (1, min (2, max (1, nargout)));\n    if (have_B)\n      real_valued = isreal (A) && isreal (B);\n      symmetric = issymmetric (A) && issymmetric (B);\n      [varargout{:}] = eig (A, B);\n    else\n      real_valued = isreal (A);\n      symmetric = issymmetric (A);\n      [varargout{:}] = eig (A);\n    endif\n    varargout = select_eig (varargout, k, sigma, real_valued, symmetric);\n    if (nargout == 3)\n      varargout{3} = 0;  # Flag value is always 0 (success) for eig() code path\n    endif\n\n  else\n    varargout = cell (1, max (1, nargout));\n    if (have_A && nnz (A) == 0)\n      ## Special case of zeros matrix which ARPACK handles badly.\n      switch (nargout)\n        case 3\n          V = diag (ones ([k,1]), rows (A), k);\n          varargout = { V, diag(zeros (k,1)), 0.0 };\n\n        case 2\n          V = diag (ones ([k,1]), rows (A), k);\n          varargout = { V, diag(zeros (k,1)) };\n\n        case {0, 1}\n          varargout = { zeros(k,1) };\n      endswitch\n    else\n      ## Call ARPACK\n      [varargout{:}] = __eigs__ (varargin{:});\n    endif\n  endif\n\nendfunction\n\n## For cases which do not go through ARPACK, but rather through eig() shortcut\n## code path, select which values to return based on input parameters and\n## number of outputs.\nfunction out = select_eig (args, k, sigma, real_valued, symmetric)\n\n  if (numel (args) == 1)\n    d = args{1};\n  else\n    d = diag (args{2});\n  endif\n\n  n = numel (d);\n  if (k > n)\n    error (\"eigs: requested number of eigenvalues K (%d) exceeds available eigenvalues (%d)\", k, n);\n  endif\n\n  if (ischar (sigma))\n    switch (sigma)\n      case \"lm\"\n        [~, idx] = sort (abs (d), \"descend\");\n\n      case \"sm\"\n        [~, idx] = sort (abs (d), \"ascend\");\n\n      case \"la\"\n        if (real_valued && symmetric)\n          [~, idx] = sort (real (d), \"descend\");\n        else\n          error ('eigs: SIGMA = \"la\" requires real symmetric problem');\n        endif\n\n      case \"sa\"\n        if (real_valued && symmetric)\n          [~, idx] = sort (real (d), \"ascend\");\n        else\n          error ('eigs: SIGMA = \"sa\" requires real symmetric problem');\n        endif\n\n      case \"be\"\n        if (real_valued && symmetric)\n          [~, idx] = sort (real (d), \"ascend\");\n        else\n          error ('eigs: SIGMA = \"be\" requires real symmetric problem');\n        endif\n\n      case \"lr\"\n        if (! (real_valued && symmetric))\n          [~, idx] = sort (real (d), \"descend\");\n        else\n          error ('eigs: SIGMA = \"lr\" requires complex or unsymmetric problem');\n        endif\n\n      case \"sr\"\n        if (! (real_valued && symmetric))\n          [~, idx] = sort (real (d), \"ascend\");\n        else\n          error ('eigs: SIGMA = \"sr\" requires complex or unsymmetric problem');\n        endif\n\n      case \"li\"\n        if (! (real_valued && symmetric))\n          [~, idx] = sort (imag (d), \"descend\");\n        else\n          error ('eigs: SIGMA = \"li\" requires complex or unsymmetric problem');\n        endif\n\n      case \"si\"\n        if (! (real_valued && symmetric))\n          [~, idx] = sort (imag (d), \"ascend\");\n        else\n          error ('eigs: SIGMA = \"si\" requires complex or unsymmetric problem');\n        endif\n\n      otherwise\n        error (\"eigs: unrecognized value for SIGMA: %s\", sigma);\n    endswitch\n  else\n    ## numeric sigma, find k closest values\n    [~, idx] = sort (abs (d - sigma));\n  endif\n\n  d = d(idx);\n\n  if (strcmp (sigma, \"be\"))\n    n1 = floor (k/2);\n    n2 = n - (k - n1) + 1;\n    selection = [1:n1, n2:n];\n  else\n    selection = 1:k;\n  endif\n\n  d = d(selection);\n\n  if (numel (args) == 1)\n    out{1} = d;\n  else\n    out{2} = diag (d);\n\n    V = args{1};\n    V = V(:,idx);\n    out{1} = V(:,selection);\n  endif\n\nendfunction\n\n\n### TRIVIAL TESTS ###\n\n%!test\n%! for i = 1:20\n%!   assert (eigs (i, 1), i, 1e-11);\n%!   assert (eigs (zeros (i), 1), 0, 1e-11);\n%!   assert (eigs (sparse (i), 1), i, 1e-11);\n%!   assert (eigs (sparse (i, i), 1), 0, 1e-11);\n%! endfor\n\n%!testif HAVE_ARPACK\n%! for i = 1:20\n%!   assert (eigs (ones (i), 1), i, 1e-11);\n%!   assert (eigs (sparse (ones (i)), 1), i, 1e-11);\n%! endfor\n\n### SPARSE MATRIX TESTS ###\n\n## Real positive definite tests, n must be even\n%!shared n, k, A, d0, d2, old_state, restore_state\n%! n = 20;\n%! k = 4;\n%! A = sparse ([3:n,1:n,1:(n-2)],[1:(n-2),1:n,3:n],[ones(1,n-2),4*ones(1,n),ones(1,n-2)]);\n%! d0 = eig (A);\n%! d2 = sort (d0);\n%! [~, idx] = sort (abs (d0));\n%! d0 = d0(idx);\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 42); # initialize generator to make eigs behavior reproducible\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k);\n%! assert (d1, d0(end:-1:(end-k+1)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k+1);\n%! assert (d1, d0(end:-1:(end-k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lm\");\n%! assert (d1, d0(end:-1:(end-k+1)), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! d1 = eigs (A, k, \"sm\");\n%! assert (d1, d0(k:-1:1), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"la\");\n%! assert (d1, d2(end:-1:(end-k+1)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"sa\");\n%! assert (d1, d2(1:k), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"be\");\n%! assert (d1, d2([1:floor(k/2), (end - ceil(k/2) + 1):end]), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k+1, \"be\");\n%! assert (d1, d2([1:floor((k+1)/2), (end - ceil((k+1)/2) + 1):end]), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! d1 = eigs (A, k, 4.1);\n%! [~, idx0] = sort (abs (d0 - 4.1));\n%! [~, idx1] = sort (abs (d1 - 4.1));\n%! assert (d1(idx1), d0(idx0(1:k)), 1e-11);\n%!testif HAVE_ARPACK, HAVE_CHOLMOD\n%! d1 = eigs (A, speye (n), k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! assert (eigs (A, k, 4.1), eigs (A, speye (n), k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, speye (n), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, speye (n)(q,q), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, speye (n), k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, speye (n)(q,q), k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! assert (eigs (A, k, 4.1), eigs (A, speye (n), k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A * x;\n%! opts.issym = 1;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, \"lm\", opts);\n%! assert (d1, d0(end:-1:(end-k+1)), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A \\ x;\n%! opts.issym = 1;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, \"sm\", opts);\n%! assert (d1, d0(k:-1:1), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! fcn = @(x) (A - 4.1 * eye (n)) \\ x;\n%! opts.issym = 1;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, 4.1, opts);\n%! assert (d1, eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK, HAVE_CHOLMOD\n%! AA = speye (10);\n%! fcn = @(x) AA * x;\n%! opts.issym = 1;  opts.isreal = 1;\n%! assert (eigs (fcn, 10, AA, 3, \"lm\", opts), [1; 1; 1], 10*eps);\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! [v1,d1] = eigs (A, k, \"sm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"la\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"sa\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"be\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n\n## Real unsymmetric tests\n%!shared n, k, A, d0, old_state, restore_state\n%! n = 20;\n%! k = 4;\n%! A = sparse ([3:n,1:n,1:(n-2)],[1:(n-2),1:n,3:n],[ones(1,n-2),1:n,-ones(1,n-2)]);\n%! d0 = eig (A);\n%! [~, idx] = sort (abs (d0));\n%! d0 = d0(idx);\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 42); # initialize generator to make eigs behavior reproducible\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k+1);\n%! assert (abs (d1), abs (d0(end:-1:(end-k))),1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! d1 = eigs (A, k, \"sm\");\n%! assert (abs (d1), abs (d0(1:k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lr\");\n%! [~, idx] = sort (real (d0));\n%! d2 = d0(idx);\n%! assert (real (d1), real (d2(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"sr\");\n%! [~, idx] = sort (real (abs (d0)));\n%! d2 = d0(idx);\n%! assert (real (d1), real (d2(1:k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"li\");\n%! [~, idx] = sort (imag (abs (d0)));\n%! d2 = d0(idx);\n%! assert (sort (imag (d1)), sort (imag (d2(end:-1:(end-k+1)))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"si\");\n%! [~, idx] = sort (imag (abs (d0)));\n%! d2 = d0(idx);\n%! assert (sort (imag (d1)), sort (imag (d2(1:k))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! d1 = eigs (A, k, 4.1);\n%! [~, idx0] = sort (abs (d0 - 4.1));\n%! [~, idx1] = sort (abs (d1 - 4.1));\n%! assert (abs (d1(idx1)), abs (d0(idx0(1:k))), 1e-11);\n%! assert (sort (imag (d1(idx1))), sort (imag (d0(idx0(1:k)))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_CHOLMOD\n%! d1 = eigs (A, speye (n), k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, speye (n), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, speye (n)(q,q), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, speye (n), k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, speye (n)(q,q), k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! assert (abs (eigs (A, k, 4.1)), abs (eigs (A, speye (n), k, 4.1)), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! assert (sort (imag (eigs (A, k, 4.1))),\n%!         sort (imag (eigs (A, speye (n), k, 4.1))), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A * x;\n%! opts.issym = 0;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A \\ x;\n%! opts.issym = 0;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, \"sm\", opts);\n%! assert (abs (d1), d0(1:k), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! fcn = @(x) (A - 4.1 * eye (n)) \\ x;\n%! opts.issym = 0;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! [v1,d1] = eigs (A, k, \"sm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lr\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"sr\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"li\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"si\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n\n\n## Complex hermitian tests\n%!shared n, k, A, d0, old_state, restore_state\n%! n = 20;\n%! k = 4;\n%! A = sparse ([3:n,1:n,1:(n-2)],[1:(n-2),1:n,3:n],[1i*ones(1,n-2),4*ones(1,n),-1i*ones(1,n-2)]);\n%! d0 = eig (A);\n%! [~, idx] = sort (abs (d0));\n%! d0 = d0(idx);\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 42); # initialize generator to make eigs behavior reproducible\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k+1);\n%! assert (abs (d1), abs (d0(end:-1:(end-k))),1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! d1 = eigs (A, k, \"sm\");\n%! assert (abs (d1), abs (d0(1:k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lr\");\n%! [~, idx] = sort (real (abs (d0)));\n%! d2 = d0(idx);\n%! assert (real (d1), real (d2(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"sr\");\n%! [~, idx] = sort (real (abs (d0)));\n%! d2 = d0(idx);\n%! assert (real (d1), real (d2(1:k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"li\");\n%! [~, idx] = sort (imag (abs (d0)));\n%! d2 = d0(idx);\n%! assert (sort (imag (d1)), sort (imag (d2(end:-1:(end-k+1)))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"si\");\n%! [~, idx] = sort (imag (abs (d0)));\n%! d2 = d0(idx);\n%! assert (sort (imag (d1)), sort (imag (d2(1:k))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! d1 = eigs (A, k, 4.1);\n%! [~, idx0] = sort (abs (d0 - 4.1));\n%! [~, idx1] = sort (abs (d1 - 4.1));\n%! assert (abs (d1(idx1)), abs (d0(idx0(1:k))), 1e-11);\n%! assert (sort (imag (d1(idx1))), sort (imag (d0(idx0(1:k)))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_CHOLMOD\n%! d1 = eigs (A, speye (n), k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, speye (n), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, speye (n)(q,q), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, speye (n), k, 4.1, opts);\n%! assert (abs (abs (d1)), abs (eigs (A, k, 4.1)), 1e-11);\n%! assert (sort (imag (abs (d1))), sort (imag (eigs (A, k, 4.1))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, speye (n)(q,q), k, 4.1, opts);\n%! assert (abs (abs (d1)), abs (eigs (A, k, 4.1)), 1e-11);\n%! assert (sort (imag (abs (d1))), sort (imag (eigs (A, k, 4.1))), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! assert (abs (eigs (A, k, 4.1)), abs (eigs (A, speye (n), k, 4.1)), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! assert (sort (imag (eigs (A, k, 4.1))),\n%!         sort (imag (eigs (A, speye (n), k, 4.1))), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A * x;\n%! opts.issym = 0;  opts.isreal = 0;\n%! d1 = eigs (fcn, n, k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A \\ x;\n%! opts.issym = 0;  opts.isreal = 0;\n%! d1 = eigs (fcn, n, k, \"sm\", opts);\n%! assert (abs (d1), d0(1:k), 1e-11);\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! fcn = @(x) (A - 4.1 * eye (n)) \\ x;\n%! opts.issym = 0;  opts.isreal = 0;\n%! d1 = eigs (fcn, n, k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! [v1,d1] = eigs (A, k, \"sm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lr\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"sr\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"li\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"si\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*speye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK, HAVE_UMFPACK, HAVE_CHOLMOD\n%! A = toeplitz (sparse (1:10));\n%! B = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, 10));\n%! [v, d] = eigs (A, B, 4, \"lm\");\n%! for i = 1:4\n%!   assert (A * v(:,i), d(i, i) * B * v(:,i), 1e-12);\n%! endfor\n%! ddiag = diag (d);\n%! [ddiag, idx] = sort (ddiag);\n%! v = v(:, idx);\n%! R = chol (B);\n%! [v1, d1] = eigs (R' \\ A / R, 4, \"lm\");\n%! d1diag = diag (d1);\n%! [d1diag, idx] = sort (d1diag);\n%! v1 = v1(:, idx);\n%! assert (abs (v), abs (R \\ v1), 1e-12);\n%!testif HAVE_ARPACK, HAVE_UMFPACK, HAVE_CHOLMOD\n%! A = spdiags ([[1./(2:11)]',[-5:-2:-23]',[1:10]'],-1:1,10,10);\n%! B = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, 10));\n%! [v, d] = eigs (A, B, 4, \"lm\");\n%! for i = 1:4\n%!   assert (A * v(:,i), d(i, i) * B * v(:,i), 1e-12);\n%! endfor\n%! ddiag = diag (d);\n%! [ddiag, idx] = sort (ddiag);\n%! v = v(:, idx);\n%! R = chol (B);\n%! [v1, d1] = eigs (R' \\ A / R, 4, \"lm\");\n%! d1diag = diag (d1);\n%! [d1diag, idx] = sort (d1diag);\n%! v1 = v1(:, idx);\n%! assert (abs (v), abs (R \\ v1), 1e-12);\n%!testif HAVE_ARPACK, HAVE_UMFPACK, HAVE_CHOLMOD\n%! A = spdiags ([[1./(2:11)]',[-5:-2:-23]',[1:10]'],-1:1,10,10) -...\n%! 1i * spdiags ([[1./(2:11)]',[-5:-2:-23]',[1:10]'],-1:1,10,10);\n%! B = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, 10));\n%! [v, d] = eigs (A, B, 4, \"lm\");\n%! for i = 1:4\n%!   assert (A * v(:,i), d(i, i) * B * v(:,i), 1e-12);\n%! endfor\n%! ddiag = diag (d);\n%! [ddiag, idx] = sort (ddiag);\n%! v = v(:, idx);\n%! R = chol (B);\n%! [v1, d1] = eigs (R' \\ A / R, 4, \"lm\");\n%! d1diag = diag (d1);\n%! [d1diag, idx] = sort (d1diag);\n%! v1 = v1(:, idx);\n%! assert (abs (v), abs (R \\ v1), 1e-12);\n%!testif HAVE_ARPACK, HAVE_UMFPACK, HAVE_CHOLMOD\n%! A = toeplitz (sparse (1:10));\n%! B = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, 10));\n%! [v, d] = eigs (A, B, 4, 1);\n%! for i = 1:4\n%!   assert (A * v(:,i), d(i, i) * B * v(:,i), 1e-12);\n%! endfor\n%! ddiag = diag (d);\n%! [ddiag, idx] = sort (ddiag);\n%! v = v(:, idx);\n%! R = chol (B);\n%! [v1, d1] = eigs (R' \\ A / R, 4, 1);\n%! d1diag = diag (d1);\n%! [d1diag, idx] = sort (d1diag);\n%! v1 = v1(:, idx);\n%! assert (abs (v), abs (R \\ v1), 1e-12);\n%!testif HAVE_ARPACK, HAVE_UMFPACK, HAVE_CHOLMOD\n%! A = spdiags ([[1./(2:11)]',[-5:-2:-23]',[1:10]'],-1:1,10,10);\n%! B = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, 10));\n%! [v, d] = eigs (A, B, 4, 1);\n%! for i = 1:4\n%!   assert (A * v(:,i), d(i, i) * B * v(:,i), 1e-12);\n%! endfor\n%! ddiag = diag (d);\n%! [ddiag, idx] = sort (ddiag);\n%! v = v(:, idx);\n%! R = chol (B);\n%! [v1, d1] = eigs (R' \\ A / R, 4, 1);\n%! d1diag = diag (d1);\n%! [d1diag, idx] = sort (d1diag);\n%! v1 = v1(:, idx);\n%! assert (abs (v), abs (R \\ v1), 1e-12);\n%!testif HAVE_ARPACK, HAVE_UMFPACK, HAVE_CHOLMOD\n%! A = spdiags ([[1./(2:11)]',[-5:-2:-23]',[1:10]'],-1:1,10,10) -...\n%! 1i * spdiags ([[1./(2:11)]',[-5:-2:-23]',[1:10]'],-1:1,10,10);\n%! B = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, 10));\n%! [v, d] = eigs (A, B, 4, 1);\n%! for i = 1:4\n%!   assert (A * v(:,i), d(i, i) * B * v(:,i), 1e-12);\n%! endfor\n%! ddiag = diag (d);\n%! [ddiag, idx] = sort (ddiag);\n%! v = v(:, idx);\n%! R = chol (B);\n%! [v1, d1] = eigs (R' \\ A / R, 4, 1);\n%! d1diag = diag (d1);\n%! [d1diag, idx] = sort (d1diag);\n%! v1 = v1(:, idx);\n%! assert (abs (v), abs (R \\ v1), 1e-12);\n%!testif HAVE_ARPACK, HAVE_UMFPACK, HAVE_CHOLMOD\n%! A = toeplitz (sparse (1:10));\n%! B = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, 10));\n%! R = chol (B);\n%! opts.cholB = true;\n%! [v, d] = eigs (A, R, 4, \"lm\", opts);\n%! for i = 1:4\n%!   assert (A * v(:,i), d(i, i) * B * v(:,i), 1e-12);\n%! endfor\n%!testif HAVE_ARPACK, HAVE_UMFPACK, HAVE_CHOLMOD\n%! A = toeplitz (sparse (1:10));\n%! B = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, 10));\n%! [R, ~, permB] = chol (B, \"vector\");\n%! opts.cholB = true;\n%! opts.permB = permB;\n%! [v, d] = eigs (A, R, 4, \"lm\", opts);\n%! for i = 1:4\n%!   assert (A * v(:,i), d(i, i) * B * v(:,i), 1e-12);\n%! endfor\n\n### FULL MATRIX TESTS ###\n\n## Real positive definite tests, n must be even\n%!shared n, k, A, d0, d2, old_state, restore_state\n%! n = 20;\n%! k = 4;\n%! A = full (sparse ([3:n,1:n,1:(n-2)],[1:(n-2),1:n,3:n],[ones(1,n-2),4*ones(1,n),ones(1,n-2)]));\n%! d0 = eig (A);\n%! d2 = sort (d0);\n%! [~, idx] = sort (abs (d0));\n%! d0 = d0(idx);\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 42); # initialize generator to make eigs behavior reproducible\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k);\n%! assert (d1, d0(end:-1:(end-k+1)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k+1);\n%! assert (d1, d0(end:-1:(end-k)),1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lm\");\n%! assert (d1, d0(end:-1:(end-k+1)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"sm\");\n%! assert (d1, d0(k:-1:1), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"la\");\n%! assert (d1, d2(end:-1:(end-k+1)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"sa\");\n%! assert (d1, d2(1:k), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"be\");\n%! assert (d1, d2([1:floor(k/2), (end - ceil(k/2) + 1):end]), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k+1, \"be\");\n%! assert (d1, d2([1:floor((k+1)/2), (end - ceil((k+1)/2) + 1):end]), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, 4.1);\n%! [~, idx0] = sort (abs (d0 - 4.1));\n%! [~, idx1] = sort (abs (d1 - 4.1));\n%! assert (d1(idx1), d0(idx0(1:k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, eye (n), k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! assert (eigs (A, k, 4.1), eigs (A, eye (n), k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, eye (n), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, eye (n)(q,q), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, eye (n), k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, eye (n)(q,q), k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! assert (eigs (A, k, 4.1), eigs (A, eye (n), k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A * x;\n%! opts.issym = 1;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, \"lm\", opts);\n%! assert (d1, d0(end:-1:(end-k+1)), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A \\ x;\n%! opts.issym = 1;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, \"sm\", opts);\n%! assert (d1, d0(k:-1:1), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) (A - 4.1 * eye (n)) \\ x;\n%! opts.issym = 1;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, 4.1, opts);\n%! assert (d1, eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"sm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"la\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"sa\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"be\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n\n## Real unsymmetric tests\n%!shared n, k, A, d0, old_state, restore_state\n%! n = 20;\n%! k = 4;\n%! A = full (sparse ([3:n,1:n,1:(n-2)],[1:(n-2),1:n,3:n],[ones(1,n-2),1:n,-ones(1,n-2)]));\n%! d0 = eig (A);\n%! [~, idx] = sort (abs (d0));\n%! d0 = d0(idx);\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 42); # initialize generator to make eigs behavior reproducible\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k+1);\n%! assert (abs (d1), abs (d0(end:-1:(end-k))),1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"sm\");\n%! assert (abs (d1), abs (d0(1:k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lr\");\n%! [~, idx] = sort (real (d0));\n%! d2 = d0(idx);\n%! assert (real (d1), real (d2(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"sr\");\n%! [~, idx] = sort (real (abs (d0)));\n%! d2 = d0(idx);\n%! assert (real (d1), real (d2(1:k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"li\");\n%! [~, idx] = sort (imag (abs (d0)));\n%! d2 = d0(idx);\n%! assert (sort (imag (d1)), sort (imag (d2(end:-1:(end-k+1)))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"si\");\n%! [~, idx] = sort (imag (abs (d0)));\n%! d2 = d0(idx);\n%! assert (sort (imag (d1)), sort (imag (d2(1:k))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, 4.1);\n%! [~, idx0] = sort (abs (d0 - 4.1));\n%! [~, idx1] = sort (abs (d1 - 4.1));\n%! assert (abs (d1(idx1)), abs (d0(idx0(1:k))), 1e-11);\n%! assert (sort (imag (d1(idx1))), sort (imag (d0(idx0(1:k)))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, eye (n), k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, eye (n), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, eye (n)(q,q), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, eye (n), k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, eye (n)(q,q), k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! assert (abs (eigs (A, k, 4.1)), abs (eigs (A, eye (n), k, 4.1)), 1e-11);\n%!testif HAVE_ARPACK\n%! assert (sort (imag (eigs (A, k, 4.1))),\n%!         sort (imag (eigs (A, eye (n), k, 4.1))), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A * x;\n%! opts.issym = 0;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A \\ x;\n%! opts.issym = 0;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, \"sm\", opts);\n%! assert (abs (d1), d0(1:k), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) (A - 4.1 * eye (n)) \\ x;\n%! opts.issym = 0;  opts.isreal = 1;\n%! d1 = eigs (fcn, n, k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"sm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lr\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"sr\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"li\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"si\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n\n## Complex hermitian tests\n%!shared n, k, A, d0, old_state, restore_state\n%! n = 20;\n%! k = 4;\n%! A = full (sparse ([3:n,1:n,1:(n-2)],[1:(n-2),1:n,3:n],[1i*ones(1,n-2),4*ones(1,n),-1i*ones(1,n-2)]));\n%! d0 = eig (A);\n%! [~, idx] = sort (abs (d0));\n%! d0 = d0(idx);\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 42); # initialize generator to make eigs behavior reproducible\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k+1);\n%! assert (abs (d1), abs (d0(end:-1:(end-k))),1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"sm\");\n%! assert (abs (d1), abs (d0(1:k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"lr\");\n%! [~, idx] = sort (real (abs (d0)));\n%! d2 = d0(idx);\n%! assert (real (d1), real (d2(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"sr\");\n%! [~, idx] = sort (real (abs (d0)));\n%! d2 = d0(idx);\n%! assert (real (d1), real (d2(1:k)), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"li\");\n%! [~, idx] = sort (imag (abs (d0)));\n%! d2 = d0(idx);\n%! assert (sort (imag (d1)), sort (imag (d2(end:-1:(end-k+1)))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, \"si\");\n%! [~, idx] = sort (imag (abs (d0)));\n%! d2 = d0(idx);\n%! assert (sort (imag (d1)), sort (imag (d2(1:k))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, k, 4.1);\n%! [~, idx0] = sort (abs (d0 - 4.1));\n%! [~, idx1] = sort (abs (d1 - 4.1));\n%! assert (abs (d1(idx1)), abs (d0(idx0(1:k))), 1e-11);\n%! assert (sort (imag (d1(idx1))), sort (imag (d0(idx0(1:k)))), 1e-11);\n%!testif HAVE_ARPACK\n%! d1 = eigs (A, eye (n), k, \"lm\");\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, eye (n), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, eye (n)(q,q), k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! d1 = eigs (A, eye (n), k, 4.1, opts);\n%! assert (abs (abs (d1)), abs (eigs (A, k, 4.1)), 1e-11);\n%! assert (sort (imag (abs (d1))), sort (imag (eigs (A, k, 4.1))), 1e-11);\n%!testif HAVE_ARPACK\n%! opts.cholB = true;\n%! q = [2:n,1];\n%! opts.permB = q;\n%! d1 = eigs (A, eye (n)(q,q), k, 4.1, opts);\n%! assert (abs (abs (d1)), abs (eigs (A, k, 4.1)), 1e-11);\n%! assert (sort (imag (abs (d1))), sort (imag (eigs (A, k, 4.1))), 1e-11);\n%!testif HAVE_ARPACK\n%! assert (abs (eigs (A, k, 4.1)), abs (eigs (A, eye (n), k, 4.1)), 1e-11);\n%!testif HAVE_ARPACK\n%! assert (sort (imag (eigs (A, k, 4.1))),\n%!         sort (imag (eigs (A, eye (n), k, 4.1))), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A * x;\n%! opts.issym = 0;  opts.isreal = 0;\n%! d1 = eigs (fcn, n, k, \"lm\", opts);\n%! assert (abs (d1), abs (d0(end:-1:(end-k+1))), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) A \\ x;\n%! opts.issym = 0;  opts.isreal = 0;\n%! d1 = eigs (fcn, n, k, \"sm\", opts);\n%! assert (abs (d1), d0(1:k), 1e-11);\n%!testif HAVE_ARPACK\n%! fcn = @(x) (A - 4.1 * eye (n)) \\ x;\n%! opts.issym = 0;  opts.isreal = 0;\n%! d1 = eigs (fcn, n, k, 4.1, opts);\n%! assert (abs (d1), eigs (A, k, 4.1), 1e-11);\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"sm\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"lr\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"sr\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"li\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"si\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n%!testif HAVE_ARPACK\n%! [v1,d1] = eigs (A, k, \"li\");\n%! d1 = diag (d1);\n%! for i=1:k\n%!   assert (max (abs ((A - d1(i)*eye (n))*v1(:,i))), 0, 1e-11);\n%! endfor\n\n%!testif HAVE_ARPACK\n%! A = 2 * diag (ones (10, 1)) - diag (ones (9, 1), 1) - diag (ones (9, 1), -1);\n%! B = eye (10);\n%! reseig = eig (A, B);\n%! [~, idx] = sort (abs (reseig), \"ascend\");\n%! assert (eigs (A, B, 4, 0), reseig (idx(4:-1:1)), 8 * eps);\n%!testif HAVE_ARPACK\n%! A = eye (9);\n%! A(1, 1) = 0;\n%! A(1, 9) = 1;\n%! [V, L] = eigs (A, 4, -1);\n%! assert (! any (isnan (diag (L))));\n%! assert (any (abs (diag (L)) <= 2 * eps));\n%!testif HAVE_ARPACK\n%! A = diag (ones (9, 1), 1);\n%! A(10,:) = [-1, zeros(1, 8), -1];\n%! opts.v0 = (1:10)';\n%! typ = \"lr\";\n%! [v, m] = eigs (A, 4, typ, opts);\n%! assert (sort (real (diag (m))), ...\n%!         [0.514038; 0.514038; 0.880290; 0.880290], 1e-4);\n%! m = eigs (A, 4, typ, opts);\n%! assert (sort (real (m)), ...\n%!         [0.514038; 0.514038; 0.880290; 0.880290], 1e-4);\n%! typ = \"li\";\n%! [v, m] = eigs (A, 4, typ, opts);\n%! assert (sort (abs (imag (diag (m)))), ...\n%!         [0.78972; 0.78972; 0.96518; 0.96518], 1e-4);\n%! m = eigs (A, 4, typ, opts);\n%! assert (sort (abs (imag (m))), ...\n%!         [0.78972; 0.78972; 0.96518; 0.96518], 1e-4);\n%! typ = \"sr\";\n%! [v, m] = eigs (A, 4, typ, opts);\n%! assert (sort (real (diag (m))), ...\n%!         [-1.12180; -1.12180; -0.69077; -0.69077], 1e-4);\n%! m = eigs (A, 4, typ, opts);\n%! assert (sort (real (m)), ...\n%!         [-1.12180; -1.12180; -0.69077; -0.69077], 1e-4);\n%! typ = \"si\";\n%! [v, m] = eigs (A, 4, typ, opts);\n%! assert (sort (abs (imag (diag (m)))), ...\n%!         [0.25552; 0.25552; 0.30282; 0.30282], 1e-4);\n%! m = eigs (A, 4, typ, opts);\n%! assert (sort (abs (imag (m))), ...\n%!         [0.25552; 0.25552; 0.30282; 0.30282], 1e-4);\n%! typ = \"lm\";\n%! [v, m] = eigs (A, 4, typ, opts);\n%! assert (sort (abs (diag (m))), ...\n%!         [1.02294;  1.02294; 1.15054; 1.15054], 1e-4);\n%! m = eigs (A, 4, typ, opts);\n%! assert (sort (abs (m)), ...\n%!         [1.02294; 1.02294; 1.15054; 1.15054], 1e-4);\n%! typ = \"sm\";\n%! [v, m] = eigs (A, 4, typ, opts);\n%! assert (sort (abs (diag (m))), ...\n%!         [0.93092; 0.93092; 0.94228; 0.94228], 1e-4);\n%! m = eigs (A, 4, typ, opts);\n%! assert (sort (abs (m)), ...\n%!         [0.93092; 0.93092; 0.94228; 0.94228], 1e-4);\n%!testif HAVE_ARPACK\n%! A = toeplitz (sparse ([2, 1, zeros(1,8)]));\n%! opts.v0 = (1:10)';\n%! [v, m] = eigs (A, 3, \"sa\", opts);\n%! assert (diag (m), [0.081014; 0.317493; 0.690279], 1e-4);\n%! m = eigs (A, 3, \"sa\", opts);\n%! assert (m, [0.081014; 0.317493; 0.690279], 1e-4);\n\n%!test\n%! X = [70 47 42 39 50 73 79 23;\n%!      19 52 61 80 36 76 63 68;\n%!      14 34 66 65 29  4 72  9;\n%!      24  8 78 49 58 54 43 33;\n%!      62 69 32 31 40 46 22 28;\n%!      48 12 45 59 10 17 15 25;\n%!      64 67 77 56 13 55 41 74;\n%!      37 38 18 21 11  3 71  7;\n%!       5 35 16  1 51 27 26 44;\n%!      30 57 60 75  2 53 20  6];\n%! Z = X * X';\n%! r = rank (Z);\n%! assert (r, 8);\n%! [V, D] = eigs (Z, r, \"lm\"); # call_eig is true\n%! ZZ = V * D * V';\n%! tmp = abs (Z - ZZ);\n%! assert (max (tmp(:)) < 5e-11);\n\n%!assert (eigs (diag (1:5), 5, \"sa\"), [1;2;3;4;5]) # call_eig is true\n%!assert (eigs (diag (1:5), 5, \"la\"), [5;4;3;2;1]) # call_eig is true\n%!assert (eigs (diag (1:5), 3, \"be\"), [1;4;5]) # call_eig is true\n%!testif HAVE_ARPACK\n%! A = toeplitz ([-2, 1, zeros(1, 8)]);\n%! A = kron (A, eye (10)) + kron (eye (10), A);\n%! opts.v0 = (1:100)';\n%! opts.maxit = 3;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (A, 4, \"lm\", opts);\n%! assert (d(3:4), [NaN; NaN]);\n%!testif HAVE_ARPACK\n%! A = toeplitz ([-2, 1, zeros(1, 8)]);\n%! A = kron (A, eye (10)) + kron (eye (10), A);\n%! opts.v0 = (1:100)';\n%! opts.maxit = 1;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (A, 4, \"sm\", opts);\n%! assert (d(4), NaN);\n%!testif HAVE_ARPACK\n%! A = toeplitz ([-2, 1, zeros(1, 8)]);\n%! A = kron (A, eye (10)) + kron (eye (10), A);\n%! Afcn = @(x) A * x;\n%! opts.v0 = (1:100)';\n%! opts.maxit = 3;\n%! opts.issym = true;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (Afcn, 100, 4, \"sm\", opts);\n%! assert (d(3:4), [NaN; NaN]);\n%!testif HAVE_ARPACK\n%! A = toeplitz ([-2, 1, zeros(1, 8)]);\n%! A = kron (A, eye (10)) + kron (eye (10), A);\n%! A(1, 2) = 10;\n%! opts.v0 = (1:100)';\n%! opts.maxit = 5;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (A, 4, \"lm\", opts);\n%! assert (d(3:4), [NaN; NaN]);\n%!testif HAVE_ARPACK\n%! A = toeplitz ([0, 1, zeros(1, 8)], [0, -1, zeros(1, 8)]);\n%! A = kron (A, eye (10)) + kron (eye (10), A);\n%! opts.v0 = (1:100)';\n%! opts.maxit = 4;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (A, 4, \"lm\", opts);\n%! assert (d(3:4), [NaN+1i*NaN; NaN+1i*NaN]);\n%!testif HAVE_ARPACK\n%! A = magic (100);\n%! opts.v0 = (1:100)';\n%! opts.maxit = 1;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (A, 10, \"lm\", opts);\n%! assert (d(9:10), [NaN; NaN]);\n%!testif HAVE_ARPACK\n%! A = toeplitz ([0, 1, zeros(1, 8)], [0, -1, zeros(1, 8)]);\n%! A(1, 1) = 1;\n%! A = kron (A, eye (10)) + kron (eye (10), A);\n%! opts.v0 = (1:100)';\n%! opts.maxit = 1;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (A, 4, \"sm\", opts);\n%! if (isreal (d))\n%!   assert (d(4), NaN);\n%! else\n%!   assert (d(4), NaN +1i*NaN);\n%! endif\n%!testif HAVE_ARPACK\n%! A = magic (100) / 10 + eye (100);\n%! opts.v0 = (1:100)';\n%! opts.maxit = 19;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (A, 10, \"sm\", opts);\n%! if (isreal (d))\n%!   assert (d(10), NaN);\n%! else\n%!   assert (d(10), NaN +1i*NaN);\n%! endif\n%!testif HAVE_ARPACK\n%! A = toeplitz ([0, 1, zeros(1, 8)], [0, -1, zeros(1, 8)]);\n%! A = kron (A, eye (10)) + kron (eye (10), A);\n%! Afcn = @(x) A * x;\n%! opts.v0 = (1:100)';\n%! opts.maxit = 4;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (Afcn, 100, 4, \"lm\", opts);\n%! assert (d(3:4), [NaN+1i*NaN; NaN+1i*NaN]);\n%!testif HAVE_ARPACK\n%! A = 1i * magic (100);\n%! opts.v0 = (1:100)';\n%! opts.maxit = 1;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (A, 5, \"lm\", opts);\n%! assert (d(5), NaN+1i*NaN);\n%!testif HAVE_ARPACK\n%! A = 1i * magic (100) + eye (100);\n%! opts.v0 = (1:100)';\n%! opts.maxit = 14;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (A, 10, \"sm\", opts);\n%! assert (d(9:10), [NaN+1i*NaN; NaN+1i*NaN]);\n%!testif HAVE_ARPACK\n%! A = 1i * magic (100);\n%! Afcn = @(x) A * x;\n%! opts.v0 = (1:100)';\n%! opts.maxit = 1;\n%! opts.isreal = false;\n%! warning (\"off\", \"Octave:eigs:UnconvergedEigenvalues\", \"local\");\n%! d = eigs (Afcn, 100, 6, \"lm\", opts);\n%! assert (d(6), NaN+1i*NaN);\n%!testif HAVE_ARPACK, HAVE_CHOLMOD\n%! A = sparse (magic (10));\n%! B = sparse (magic (10)); # not HPD\n%! fail (\"eigs (A, B, 4)\", \"eigs: The matrix B is not positive definite\")\n%!testif HAVE_ARPACK\n%! i_A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n%! j_A = [1, 2, 3, 4, 5, 6, 7,  8, 9, 10];\n%! v_A = [1, 2i, 3, 4i, 5, 6i, 7, 8, 9, 10i];\n%! A = sparse (i_A, j_A, v_A);\n%! i_B = [1,2, 3, 4, 5, 6, 7, 8, 9, 10];\n%! j_B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n%! v_B = [3, 10i, 1, 8i, 7, 6i, 5, 4i, 9, 7i];\n%! B = sparse (i_B, j_B, v_B); # not SPD\n%! [Evectors, Evalues] = eigs(A, B, 5, \"SM\"); # call_eig is true\n%! ResidualVectors = A * Evectors - B * Evectors * Evalues;\n%! RelativeErrors = norm (ResidualVectors, \"columns\") ./ ...\n%! norm (A * Evectors, \"columns\");\n%! assert (RelativeErrors, zeros (1, 5));\n%!testif HAVE_ARPACK\n%! A = rand (8);\n%! eigs (A, 6, \"lr\"); # this failed on 4.2.x\n%!testif HAVE_ARPACK\n%! M = magic (10);\n%! A = sin (M);\n%! B = cos (M);\n%! B = B * B';\n%! opts.v0 = (1:10)';\n%! [Evector, Evalues] = eigs (A, B, 4, \"LM\", opts);\n%! Afcn = @(x) A * x;\n%! [Evector_f Evalues_f] = eigs (Afcn, 10, B, 4, \"LM\", opts);\n%! assert (Evector, Evector_f);\n%! assert (Evalues, Evalues_f);\n%!testif HAVE_ARPACK\n%! M = magic (10);\n%! A = sin (M);\n%! B = cos (M);\n%! B = B * B';\n%! opts.v0 = (1:10)';\n%! [Evector, Evalues] = eigs (A, B, 4, \"SM\", opts);\n%! [L, U, P] = lu (A);\n%! Afcn = @(x) U \\ (L \\ (P * x));\n%! [Evector_f Evalues_f] = eigs (Afcn, 10, B, 4, \"SM\", opts);\n%! assert (Evector, Evector_f);\n%! assert (Evalues, Evalues_f);\n%!testif HAVE_ARPACK\n%! M = magic (10);\n%! A = sin (M);\n%! A = A * A';\n%! B = cos (M);\n%! B = B * B';\n%! opts.v0 = (1:10)';\n%! [Evector, Evalues] = eigs (A, B, 4, \"LM\", opts);\n%! Afcn = @(x) A * x;\n%! opts.issym = true;\n%! [Evector_f Evalues_f] = eigs (Afcn, 10, B, 4, \"LM\", opts);\n%! assert (Evector, Evector_f);\n%! assert (Evalues, Evalues_f);\n%!testif HAVE_ARPACK\n%! M = magic (10);\n%! A = sin (M);\n%! A = A * A';\n%! B = cos (M);\n%! B = B * B';\n%! opts.v0 = (1:10)';\n%! [Evector, Evalues] = eigs (A, B, 4, \"SM\", opts);\n%! [L, U, P] = lu (A);\n%! Afcn = @(x) U \\ (L \\ (P * x));\n%! opts.issym = true;\n%! [Evector_f Evalues_f] = eigs (Afcn, 10, B, 4, \"SM\", opts);\n%! assert (Evector, Evector_f);\n%! assert (Evalues, Evalues_f);\n%!testif HAVE_ARPACK\n%! M = magic (10);\n%! A = sin (M) + 1i * cos (M);\n%! B = cos (M) + 1i * sin (M);\n%! B = B * B';\n%! opts.v0 = (1:10)';\n%! [Evector, Evalues] = eigs (A, B, 4, \"LM\", opts);\n%! Afcn = @(x) A * x;\n%! opts.isreal = false;\n%! [Evector_f Evalues_f] = eigs (Afcn, 10, B, 4, \"LM\", opts);\n%! assert (Evector, Evector_f);\n%! assert (Evalues, Evalues_f);\n%!testif HAVE_ARPACK\n%! M = magic (10);\n%! A = sin (M) + 1i * cos (M);\n%! B = cos (M) + 1i * sin (M);\n%! B = B * B';\n%! opts.v0 = (1:10)';\n%! [Evector, Evalues] = eigs (A, B, 4, \"SM\", opts);\n%! [L, U, P] = lu (A);\n%! Afcn = @(x) U \\ (L \\ (P *x));\n%! opts.isreal = false;\n%! [Evector_f, Evalues_f] = eigs (Afcn, 10, B, 4, \"SM\", opts);\n%! assert (Evector, Evector_f);\n%! assert (Evalues, Evalues_f);\n\n%!testif HAVE_ARPACK <*57196>\n%! x = ones (10, 10);\n%! z = complex (x, x);\n%! A = [sparse(10,10), z; z', sparse(10,10)];\n%! d = eigs (A);\n%! assert (isreal (d));\n%! [~, d] = eigs (A);\n%! assert (isreal (d));\n\n%!testif HAVE_ARPACK <*59486>\n%! A = magic (5);\n%! d = eigs (A, [], 1);\n%! assert (d, 65, 5 * eps (65));\n\n%!testif HAVE_ARPACK <*59488>\n%! A = zeros (20);\n%! d = eigs (A, 4);\n%! assert (d, zeros (4, 1));\n%! [V, d, flag] = eigs (A, 4);\n%! Vexp = zeros (20, 4);\n%! Vexp(sub2ind (size (Vexp), 1:4, 1:4)) = 1;\n%! assert (V, Vexp);\n%! assert (d, diag (zeros (4,1)));\n%! assert (flag, 0.0);\n\n## Test input validation\n%!error <Invalid call> eigs ()\n%!error <second argument must be numeric> eigs (1, \"foobar\")\n%!error <requested number of eigenvalues K \\(2\\) exceeds available eigenvalues \\(1\\)>\n%! eigs (1, [], 2);\n%!error <\"la\" requires real symmetric problem> eigs ([i,0;0,1], 1, \"la\")\n%!error <\"la\" requires real symmetric problem> eigs ([1,1;0,1], 1, \"la\")\n%!error <\"sa\" requires real symmetric problem> eigs ([i,0;0,1], 1, \"sa\")\n%!error <\"sa\" requires real symmetric problem> eigs ([1,1;0,1], 1, \"sa\")\n%!error <\"be\" requires real symmetric problem> eigs ([i,0;0,1], 1, \"be\")\n%!error <\"be\" requires real symmetric problem> eigs ([1,1;0,1], 1, \"be\")\n%!error <\"lr\" requires complex or unsymmetric> eigs ([1,0;0,1], 1, \"lr\")\n%!error <\"sr\" requires complex or unsymmetric> eigs ([1,0;0,1], 1, \"sr\")\n%!error <\"li\" requires complex or unsymmetric> eigs ([1,0;0,1], 1, \"li\")\n%!error <\"si\" requires complex or unsymmetric> eigs ([1,0;0,1], 1, \"si\")\n%!error <unrecognized value for SIGMA: foobar> eigs (eye (2), 1, \"foobar\")\n%!testif HAVE_ARPACK\n%! A = rand (10);\n%! opts.v0 = ones (8, 1);\n%! fail (\"eigs (A, 4, 'sm', opts)\", \"opts.v0 must be n-by-1\");\n"
  },
  {
    "path": "scripts/sparse/etreeplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} etreeplot (@var{A})\n## @deftypefnx {} {} etreeplot (@var{A}, @var{node_style}, @var{edge_style})\n## Plot the elimination tree of the matrix @var{A} or\n## @tcode{@var{A}+@var{A}'} if @var{A} in not symmetric.\n##\n## The optional parameters @var{node_style} and @var{edge_style} define the\n## output style.\n## @seealso{treeplot, gplot}\n## @end deftypefn\n\nfunction etreeplot (A, varargin)\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  treeplot (etree (A+A'), varargin{:});\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> etreeplot ()\n%!error <Invalid call> etreeplot (1,2,3,4)\n"
  },
  {
    "path": "scripts/sparse/gmres.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} gmres (@var{A}, @var{b}, @var{restart}, @var{tol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0}, @dots{})\n## @deftypefnx {} {@var{x} =} gmres (@var{A}, @var{b}, @var{restart}, @var{tol}, @var{maxit}, @var{M}, [], @var{x0}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} gmres (@var{A}, @var{b}, @dots{})\n## Solve @code{A x = b} using the Preconditioned GMRES iterative method with\n## restart, a.k.a.@: PGMRES(restart).\n##\n## The input arguments are:\n##\n## @itemize @minus\n##\n## @item @var{A} is the matrix of the linear system and it must be square.\n## @var{A} can be passed as a matrix, function handle, or inline\n## function @code{Afcn} such that @code{Afcn(x) = A * x}.  Additional\n## parameters to @code{Afcn} are passed after @var{x0}.\n##\n## @item @var{b} is the right hand side vector.  It must be a column vector\n## with the same numbers of rows as @var{A}.\n##\n## @item @var{restart} is the number of iterations before that the\n## method restarts.  If it is [] or N = numel (b), then the restart\n## is not applied.\n##\n## @item @var{tol} is the required relative tolerance for the\n## preconditioned residual error,\n## @code{inv (@var{M}) * (@var{b} - @var{a} * @var{x})}.  The iteration\n## stops if @code{norm (inv (@var{M}) * (@var{b} - @var{a} * @var{x}))\n## @leq{} @var{tol} * norm (inv (@var{M}) * @var{B})}.  If @var{tol} is\n## omitted or empty, then a tolerance of 1e-6 is used.\n##\n## @item @var{maxit} is the maximum number of outer iterations, if not given or\n## set to [], then the default value @code{min (10, @var{N} / @var{restart})}\n## is used.\n## Note that, if @var{restart} is empty, then @var{maxit} is the maximum number\n## of iterations.  If @var{restart} and @var{maxit} are not empty, then\n## the maximum number of iterations is @code{@var{restart} * @var{maxit}}.\n## If both @var{restart} and @var{maxit} are empty, then the maximum\n## number of iterations is set to @code{min (10, @var{N})}.\n##\n## @item @var{M1}, @var{M2} are the preconditioners.  The preconditioner\n## @var{M} is given as @code{M = M1 * M2}.  Both @var{M1} and @var{M2} can\n## be passed as a matrix, function handle, or inline function @code{g} such\n## that @code{g(x) = M1 \\ x} or @code{g(x) = M2 \\ x}.  If @var{M1} is [] or not\n## given, then the preconditioner is not applied.\n## The technique used is the left-preconditioning, i.e., it is solved\n## @code{inv(@var{M}) * @var{A} * @var{x} = inv(@var{M}) * @var{b}} instead of\n## @code{@var{A} * @var{x} = @var{b}}.\n##\n## @item @var{x0} is the initial guess,\n## if not given or set to [], then the default value\n## @code{zeros (size (@var{b}))} is used.\n##\n## @end itemize\n##\n## The arguments which follow @var{x0} are treated as parameters, and passed in\n## a proper way to any of the functions (@var{A} or @var{M} or\n## @var{M1} or @var{M2}) which are passed to @code{gmres}.\n##\n## The outputs are:\n##\n## @itemize @minus\n##\n## @item @var{x} the computed approximation.  If the method does not\n## converge, then it is the iterated with minimum residual.\n##\n## @item @var{flag} indicates the exit status:\n##\n## @table @asis\n## @item 0\n## iteration converged to within the specified tolerance\n##\n## @item 1\n## maximum number of iterations exceeded\n##\n## @item 2\n## the preconditioner matrix is singular\n##\n## @item 3\n## algorithm reached stagnation (the relative difference between two\n## consecutive iterations is less than eps)\n## @end table\n##\n## @item @var{relres} is the value of the relative preconditioned\n## residual of the approximation @var{x}.\n##\n## @item @var{iter} is a vector containing the number of outer iterations and\n## inner iterations performed to compute @var{x}.  That is:\n##\n## @itemize\n## @item @var{iter(1)}: number of outer iterations, i.e., how many\n## times the method restarted.  (if @var{restart} is empty or @var{N},\n## then it is 1, if not 1 @leq{} @var{iter(1)} @leq{} @var{maxit}).\n##\n## @item @var{iter(2)}: the number of iterations performed before the\n## restart, i.e., the method restarts when\n## @code{@var{iter(2)} = @var{restart}}.  If @var{restart} is empty or\n## @var{N}, then 1 @leq{} @var{iter(2)} @leq{} @var{maxit}.\n## @end itemize\n##\n## To be more clear, the approximation @var{x} is computed at the iteration\n## @code{(@var{iter(1)} - 1) * @var{restart} + @var{iter(2)}}.\n## Since the output @var{x} corresponds to the minimal preconditioned\n## residual solution, the total number of iterations that\n## the method performed is given by @code{length (resvec) - 1}.\n##\n## @item @var{resvec} is a vector containing the preconditioned\n## relative residual at each iteration, including the 0-th iteration\n## @code{norm (@var{A} * @var{x0} - @var{b})}.\n## @end itemize\n##\n## Let us consider a trivial problem with a tridiagonal matrix\n##\n## @example\n## @group\n## n = 20;\n## A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n##     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n##     sparse (1, 2, 1, 1, n) * n / 2);\n## b = A * ones (n, 1);\n## restart = 5;\n## [M1, M2] = ilu (A); # in this tridiag case, it corresponds to lu (A)\n## M = M1 * M2;\n## Afcn = @@(x) A * x;\n## Mfcn = @@(x) M \\ x;\n## M1fcn = @@(x) M1 \\ x;\n## M2fcn = @@(x) M2 \\ x;\n## @end group\n## @end example\n##\n## @sc{Example 1:} simplest usage of @code{gmres}\n##\n## @example\n## x = gmres (A, b, [], [], n)\n## @end example\n##\n## @sc{Example 2:} @code{gmres} with a function which computes\n## @code{@var{A} * @var{x}}\n##\n## @example\n## x = gmres (Afcn, b, [], [], n)\n## @end example\n##\n## @sc{Example 3:} usage of @code{gmres} with the restart\n##\n## @example\n## x = gmres (A, b, restart);\n## @end example\n##\n## @sc{Example 4:} @code{gmres} with a preconditioner matrix @var{M}\n## with and without restart\n##\n## @example\n## @group\n## x = gmres (A, b, [], 1e-06, n, M)\n## x = gmres (A, b, restart, 1e-06, n, M)\n## @end group\n## @end example\n##\n## @sc{Example 5:} @code{gmres} with a function as preconditioner\n##\n## @example\n## x = gmres (Afcn, b, [], 1e-6, n, Mfcn)\n## @end example\n##\n## @sc{Example 6:} @code{gmres} with preconditioner matrices @var{M1}\n## and @var{M2}\n##\n## @example\n## x = gmres (A, b, [], 1e-6, n, M1, M2)\n## @end example\n##\n## @sc{Example 7:} @code{gmres} with functions as preconditioners\n##\n## @example\n## x = gmres (Afcn, b, 1e-6, n, M1fcn, M2fcn)\n## @end example\n##\n## @sc{Example 8:} @code{gmres} with as input a function requiring an argument\n##\n## @example\n## @group\n##   function y = Ap (A, x, p) # compute A^p * x\n##      y = x;\n##      for i = 1:p\n##        y = A * y;\n##      endfor\n##   endfunction\n## Apfcn = @@(x, p) Ap (A, x, p);\n## x = gmres (Apfcn, b, [], [], [], [], [], [], 2);\n## @end group\n## @end example\n##\n## @sc{Example 9:} explicit example to show that @code{gmres} uses a\n## left preconditioner\n##\n## @example\n## @group\n## [M1, M2] = ilu (A + 0.1 * eye (n)); # factorization of A perturbed\n## M = M1 * M2;\n##\n## ## reference solution computed by gmres after two iterations\n## [x_ref, fl] = gmres (A, b, [], [], 1, M)\n##\n## ## left preconditioning\n## [x, fl] = gmres (M \\ A, M \\ b, [], [], 1)\n## x # compare x and x_ref\n##\n## @end group\n## @end example\n##\n## Reference:\n##\n## @nospell{Y. Saad}, @cite{Iterative Methods for Sparse Linear Systems},\n## 2nd edition, SIAM, 2003.\n##\n## @seealso{bicg, bicgstab, cgs, pcg, pcr, qmr, tfqmr}\n## @end deftypefn\n\n\nfunction [x_min, flag, relres, it, resvec] = ...\n         gmres (A, b, restart = [], tol = [], maxit = [], M1 = [],\n                M2 = [], x0 = [], varargin)\n\n  if (strcmp (class (A), \"single\") || strcmp (class (b), \"single\"))\n    class_name = \"single\";\n  else\n    class_name = \"double\";\n  endif\n\n  [Afcn, M1fcn, M2fcn] = __alltohandles__ (A, b, M1, M2, \"gmres\");\n\n  ## Check if the inputs are empty, and in case set them\n  [tol, x0] = __default__input__ ({1e-06, zeros(size (b))}, tol, x0);\n\n  empty_restart = isempty (restart);\n  empty_maxit = isempty (maxit);\n  size_b = rows (b);\n\n  if (tol >= 1)\n    warning (\"Input tol is bigger than 1.\\nTry to use a smaller tolerance.\");\n  elseif (tol <= eps / 2)\n    warning (\"Input tol may not be achievable by gmres.\\nTry to use a bigger tolerance.\");\n  endif\n\n  ## This big \"if block\" is to set maxit and restart in the proper way\n\n  if ((empty_restart) && (empty_maxit))\n    restart = size_b;\n    maxit = 1;\n    max_iter_number = min (size_b, 10);\n  elseif (restart <= 0) || (maxit <= 0)\n    error (\"gmres: MAXIT and RESTART must be positive integers\");\n  elseif (restart < size_b) && (empty_maxit)\n    maxit = min (size_b / restart, 10);\n    max_iter_number = maxit * restart;\n  elseif (restart == size_b) && (empty_maxit)\n    maxit = 1;\n    max_iter_number = min (size_b, 10);\n  elseif (restart > size_b) && (empty_maxit)\n    warning (\"RESTART is %d but it should be bounded by SIZE(A,2).\\nSetting restart to %d.\\n\", restart, size_b);\n    restart = size_b;\n    maxit = 1;\n    max_iter_number = restart;\n  elseif (empty_restart) && (maxit <= size_b)\n    restart = size_b;\n    max_iter_number = maxit;\n  elseif (empty_restart) && (maxit > size_b)\n    warning (\"MAXIT is %d but it should be bounded by SIZE(A,2).\\nSetting MAXIT to %d\", maxit, size_b);\n    restart = size_b;\n    maxit = size_b;\n    max_iter_number = size_b;\n  elseif (restart > size_b) && (! empty_maxit)\n    warning (\"RESTART is %d but it should be bounded by SIZE(A,2).\\nSetting restart to %d.\\n\", restart, size_b);\n    restart = size_b;\n    max_iter_number = restart * maxit;\n  elseif (restart == size_b) && (maxit <= size_b)\n    max_iter_number = maxit;\n  else\n    max_iter_number = restart*maxit;\n  endif\n\n  prec_b_norm = norm (b, 2);\n  if (prec_b_norm == 0)\n    if (nargout < 2)\n      printf (\"The right hand side vector is all zero so gmres\\nreturned an all zero solution without iterating.\\n\")\n    endif\n    x_min = b;\n    flag = 0;\n    relres = 0;\n    resvec = 0;\n    it = [0, 0];\n    return;\n  endif\n\n  ## gmres: function handle case\n\n  x_old = x_pr = x_min = x = x0;\n  B = zeros (restart + 1, 1);\n  V = zeros (rows (x), restart, class_name);\n  H = zeros (restart + 1, restart);\n\n  iter = 1; # total number of iterations\n  iter_min = 0; # iteration with minimum residual\n  outer_it = 1; # number of outer iterations\n  restart_it  =  1; # number of inner iterations\n  it = zeros (1, 2);\n  resvec = zeros (max_iter_number + 1, 1);\n  flag = 1; # Default flag is maximum # of iterations exceeded\n\n  ## begin loop\n  u = feval (Afcn, x_old, varargin{:});\n  try\n    warning (\"error\", \"Octave:singular-matrix\", \"local\");\n    prec_res = feval (M1fcn, b - u, varargin{:});  # M1*(b-u)\n    prec_res = feval (M2fcn, prec_res, varargin{:});\n    presn = norm (prec_res, 2);\n    resvec(1) = presn;\n    z = feval (M1fcn, b, varargin{:});\n    z = feval (M2fcn, z, varargin{:});\n    prec_b_norm = norm (z, 2);\n    B (1) = presn;\n    V(:, 1) = prec_res / presn;\n  catch\n    flag = 2;\n  end_try_catch\n\n  while (flag != 2) && (iter <= max_iter_number) && ...\n        (presn > tol * prec_b_norm)\n    ## restart\n    if (restart_it > restart)\n      restart_it = 1;\n      outer_it += 1;\n      x_old = x;\n      u = feval (Afcn, x_old, varargin{:});\n      prec_res = feval (M1fcn, b - u, varargin{:});\n      prec_res = feval (M2fcn, prec_res, varargin{:});\n      presn = norm (prec_res, 2);\n      B(1) = presn;\n      H(:) = 0;\n      V(:, 1) = prec_res / presn;\n    endif\n    ## basic iteration\n    u = feval (Afcn, V(:, restart_it), varargin{:});\n    tmp = feval (M1fcn, u, varargin{:});\n    tmp = feval (M2fcn, tmp, varargin{:});\n    [V(:,restart_it + 1), H(1:restart_it + 1, restart_it)] = ...\n      mgorth (tmp, V(:,1:restart_it));\n    Y = (H(1:restart_it + 1, 1:restart_it) \\ B(1:restart_it + 1));\n    little_res = B(1:restart_it + 1) - ...\n                 H(1:restart_it + 1, 1:restart_it) * Y(1:restart_it);\n    presn = norm (little_res, 2);\n    x = x_old + V(:, 1:restart_it) * Y(1:restart_it);\n    resvec(iter + 1) = presn;\n    if (norm (x - x_pr) <= eps*norm (x))\n      flag = 3; # Stagnation: little change between iterations\n      break;\n    endif\n    if (resvec (iter + 1) <= resvec (iter_min + 1))\n      x_min = x;\n      iter_min = iter;\n      it = [outer_it, restart_it];\n    endif\n    x_pr = x;\n    restart_it += 1;\n    iter += 1;\n  endwhile\n\n  if (flag == 2)\n    resvec = norm (b);\n    relres = 1;\n  else\n    resvec = resvec (1:iter);\n    relres = resvec (iter) / prec_b_norm;\n  endif\n\n  if ((relres <= tol) && (flag == 1))\n    flag = 0;  # Converged to solution within tolerance\n  endif\n\n  if ((nargout < 2) && (restart != size_b)) # restart applied\n    switch (flag)\n      case {0} # gmres converged\n        printf (\"gmres (%d) converged at outer iteration %d (inner iteration %d) \",restart, it (1), it (2));\n        printf (\"to a solution with relative residual %d\\n\", relres);\n      case {1} # max number of iteration reached\n        printf (\"gmres (%d) stopped at outer iteration %d (inner iteration %d) \", restart, outer_it, restart_it-1);\n        printf (\"without converging to the desired tolerance %d \", tol);\n        printf (\"because the maximum number of iterations was reached\\n\");\n        printf (\"The iterated returned (number %d(%d)) \", it(1), it(2));\n        printf (\"has relative residual %d\\n\", relres);\n      case {2} # preconditioner singular\n        printf (\"gmres (%d) stopped at outer iteration %d (inner iteration %d) \",restart, outer_it, restart_it-1);\n        printf (\"without converging to the desired tolerance %d \", tol);\n        printf (\"because the preconditioner matrix is singular\\n\");\n        printf (\"The iterated returned (number %d(%d)) \", it(1), it(2));\n        printf (\"has relative residual %d\\n\", relres);\n      case {3} # stagnation\n        printf (\"gmres (%d) stopped at outer iteration %d (inner iteration %d) \", restart, outer_it, restart_it - 1);\n        printf (\"without converging to the desired tolerance %d\", tol);\n        printf (\"because it stagnates.\\n\");\n        printf (\"The iterated returned (number %d(%d)) \", it(1), it(2));\n        printf (\"has relative residual %d\\n\", relres);\n    endswitch\n  elseif ((nargout < 2) && (restart == size_b)) # no restart\n    switch (flag)\n      case {0} # gmres converged\n        printf (\"gmres converged at iteration %d \", it(2));\n        printf (\"to a solution with relative residual %d\\n\", relres);\n      case {1} # max number of iteration reached\n        printf (\"gmres stopped at iteration %d \", restart_it - 1);\n        printf (\"without converging to the desired tolerance %d \", tol);\n        printf (\"because the maximum number of iterations was reached\\n\");\n        printf (\"The iterated returned (number %d) \", it(2));\n        printf (\"has relative residual %d\\n\", relres);\n      case {2} # preconditioner ill-conditioned\n        printf (\"gmres stopped at iteration %d \", restart_it - 1);\n        printf (\"without converging to the desired tolerance %d \", tol);\n        printf (\"because the preconditioner matrix is singular\\n\")\n        printf (\"The iterated returned (number %d) \", it (2));\n        printf (\"has relative residual %d\\n\", relres);\n      case {3} # stagnation\n        printf (\"gmres stopped at iteration %d \", restart_it - 1);\n        printf (\"without converging at the desired tolerance %d \", tol);\n        printf (\"because it stagnates\\n\");\n        printf (\"The iterated returned (number %d) \", it(2));\n        printf (\"has relative residual %d\\n\", relres);\n    endswitch\n  endif\n\nendfunction\n\n\n%!demo\n%! dim = 20;\n%! A = spdiags ([-ones(dim,1) 2*ones(dim,1) ones(dim,1)], [-1:1], dim, dim);\n%! b = ones (dim, 1);\n%! [x, flag, relres, iter, resvec] = ...\n%!   gmres (A, b, 10, 1e-10, dim, @(x) x ./ diag (A), [], b)\n\n%!demo # simplest use\n%! n = 20;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n%!     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n%!     sparse (1, 2, 1, 1, n) * n / 2);\n%! b = A * ones (n, 1);\n%! restart = 5;\n%! [M1, M2] = ilu (A + 0.1 * eye (n));\n%! M = M1 * M2;\n%! x = gmres (A, b, [], [], n);\n%! x = gmres (A, b, restart, [], n);  # gmres with restart\n%! Afcn = @(x) A * x;\n%! x = gmres (Afcn, b, [], [], n);\n%! x = gmres (A, b, [], 1e-6, n, M);  # gmres without restart\n%! x = gmres (A, b, [], 1e-6, n, M1, M2);\n%! Mfcn = @(x) M \\ x;\n%! x = gmres (Afcn, b, [], 1e-6, n, Mfcn);\n%! M1fcn = @(x) M1 \\ x;\n%! M2fcn = @(x) M2 \\ x;\n%! x = gmres (Afcn, b, [], 1e-6, n, M1fcn, M2fcn);\n%! function y = Ap (A, x, p)  # compute A^p * x\n%!    y = x;\n%!    for i = 1:p\n%!      y = A * y;\n%!    endfor\n%!  endfunction\n%! Afcn = @(x, p) Ap (A, x, p);\n%! x = gmres (Afcn, b, [], [], n, [], [], [], 2);  # solution of A^2 * x = b\n\n%!demo\n%! n = 10;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n%!     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n%!     sparse (1, 2, 1, 1, n) * n / 2);\n%! b = A * ones (n, 1);\n%! [M1, M2] = ilu (A + 0.1 * eye (n));  # factorization of A perturbed\n%! M = M1 * M2;\n%!\n%! ## reference solution computed by gmres after one iteration\n%! [x_ref, fl] = gmres (A, b, [], [], 1, M);\n%! x_ref\n%!\n%! ## left preconditioning\n%! [x, fl] = gmres (M \\ A, M \\ b, [], [], 1);\n%! x # compare x and x_ref\n\n%!test\n%! ## Check that all type of inputs work\n%! A = toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M1 = diag (sqrt (diag (A)));\n%! M2 = M1;\n%! Afcn = @(z) A * z;\n%! M1_fcn = @(z) M1 \\ z;\n%! M2_fcn = @(z) M2 \\ z;\n%! [x, flag] = gmres (A, b);\n%! assert (flag, 0);\n%! [x, flag] = gmres (A, b, [], [], [], M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = gmres (A, b, [], [], [], M1_fcn, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = gmres (A, b, [], [], [], M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = gmres (A, b, [], [], [], M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = gmres (Afcn, b);\n%! assert (flag, 0);\n%! [x, flag] = gmres (Afcn, b, [],[],[], M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = gmres (Afcn, b, [],[],[], M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = gmres (Afcn, b, [],[],[], M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = gmres (Afcn, b, [],[],[], M1_fcn, M2_fcn);\n%! assert (flag, 0);\n\n%!test\n%! dim = 100;\n%! A = spdiags ([-ones(dim,1), 2*ones(dim,1), ones(dim,1)], [-1:1], dim, dim);\n%! b = ones (dim, 1);\n%! [x, flag] = gmres (A, b, 10, 1e-10, dim, @(x) x ./ diag (A), [], b);\n%! assert (x, A\\b, 1e-9*norm (x, Inf));\n%! [x, flag] = gmres (A, b, dim, 1e-10, 1e4, @(x) diag (diag (A)) \\ x, [], b);\n%! assert (x, A\\b, 1e-7*norm (x, Inf));\n\n%!test\n%! dim = 100;\n%! A = spdiags ([[1./(2:2:2*(dim-1)) 0]; 1./(1:2:2*dim-1); ...\n%!               [0 1./(2:2:2*(dim-1))]]', -1:1, dim, dim);\n%! A = A'*A;\n%! b = rand (dim, 1);\n%! [x, resvec] = gmres (@(x) A*x, b, dim, 1e-10, dim, ...\n%!                      @(x) x./diag (A), [], []);\n%! assert (x, A\\b, 1e-9*norm (x, Inf));\n%! [x, flag] = gmres (@(x) A*x, b, dim, 1e-10, 1e5, ...\n%!                    @(x) diag (diag (A)) \\ x, [], []);\n%! assert (x, A\\b, 1e-9*norm (x, Inf));\n%! [x, flag] = gmres (@(x) A*x, b, dim, 1e-10, 1e5, ...\n%!                    @(x) x ./ diag (A), [], []);\n%! assert (x, A\\b, 1e-7*norm (x, Inf));\n\n%!test\n%! ## gmres solves complex linear systems\n%! A = toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0])) + ...\n%!     1i * toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! [x, flag] = gmres(A, b, [], [], 5);\n%! assert (flag, 0);\n%! assert (x, ones (5, 1), -1e-6);\n\n%!test\n%! ## Maximum number of iteration reached\n%! A = hilb (100);\n%! b = sum (A, 2);\n%! [x, flag, relres, iter] = gmres (A, b, [], 1e-14);\n%! assert (flag, 1);\n\n%!test\n%! ## gmres recognizes that the preconditioner matrix is singular\n%! AA = 2 * eye (3);\n%! bb = ones (3, 1);\n%! I = eye (3);\n%! M = [1 0 0; 0 1 0; 0 0 0];  # the last row is zero\n%! [x, flag] = gmres (@(y) AA * y, bb, [], [], [], @(y) M \\ y, @(y) y);\n%! assert (flag, 2);\n\n%!test\n%! A = rand (4);\n%! A = A' * A;\n%! [x, flag] = gmres (A, zeros (4, 1), [], [], [], [], [], ones (4, 1));\n%! assert (x, zeros (4, 1));\n\n%!test\n%! A = rand (4);\n%! b = zeros (4, 1);\n%! [x, flag, relres, iter] = gmres (A, b);\n%! assert (relres, 0);\n\n%!test\n%! A = toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0]));\n%! b = A * ones (5, 1);\n%! [x, flag, relres, iter] = gmres (A, b, [], [], [], [], [], ...\n%!                                  ones (5, 1) + 1e-8);\n%! assert (iter, [0, 0]);\n\n%!test\n%! A = rand (20);\n%! b = A * ones (20, 1);\n%! [x, flag, relres, iter, resvec] = gmres (A, b, [], [], 1);\n%! assert (iter, [1, 1]);\n\n%!test\n%! A = hilb (20);\n%! b = A * ones (20, 1);\n%! [x, flag, relres, iter, resvec] = gmres (A, b ,5, 1e-14);\n%! assert (iter, [4, 5]);\n\n%!test\n%! A = single (1);\n%! b = 1;\n%! [x, flag] = gmres (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = 1;\n%! b = single (1);\n%! [x, flag] = gmres (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = single (1);\n%! b = single (1);\n%! [x, flag] = gmres (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%!function y = Afcn (x)\n%!   A = toeplitz ([2, 1, 0, 0], [2, -1, 0, 0]);\n%!   y = A * x;\n%!endfunction\n%! [x, flag] = gmres (\"Afcn\", [1; 2; 2; 3]);\n%! assert (x, ones (4, 1), 1e-6);\n\n%!test # preconditioned residual\n%! A = toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M = magic (5);\n%! [x, flag, relres] = gmres (A, b, [], [], 2, M);\n%! assert (relres, norm (M \\ (b - A * x)) / norm (M \\ b), 8 * eps);\n"
  },
  {
    "path": "scripts/sparse/gplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} gplot (@var{A}, @var{xy})\n## @deftypefnx {} {} gplot (@var{A}, @var{xy}, @var{line_style})\n## @deftypefnx {} {[@var{x}, @var{y}] =} gplot (@var{A}, @var{xy})\n## Plot a graph defined by @var{A} and @var{xy} in the graph theory sense.\n##\n## @var{A} is the adjacency matrix of the array to be plotted and @var{xy} is\n## an @var{n}-by-2 matrix containing the coordinates of the nodes of the graph.\n##\n## The optional parameter @var{line_style} defines the output style for the\n## plot.  Called with no output arguments the graph is plotted directly.\n## Otherwise, return the coordinates of the plot in @var{x} and @var{y}.\n## @seealso{treeplot, etreeplot, spy}\n## @end deftypefn\n\nfunction [x, y] = gplot (A, xy, line_style)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (nargin == 2)\n    line_style = \"-\";\n  endif\n\n  [i, j] = find (A);\n  xcoord = [xy(i,1), xy(j,1), NaN(length(i),1) ]'(:);\n  ycoord = [xy(i,2), xy(j,2), NaN(length(i),1) ]'(:);\n\n  if (nargout == 0)\n    plot (xcoord, ycoord, line_style);\n  else\n    x = xcoord;\n    y = ycoord;\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Binary Tree Representation\n%! A = [0 1 0 0 0 0 0\n%!      1 0 1 1 0 0 0\n%!      0 1 0 0 0 0 0\n%!      0 1 0 0 1 0 0\n%!      0 0 0 1 0 1 1\n%!      0 0 0 0 1 0 0\n%!      0 0 0 0 1 0 0];\n%!\n%! xy = [1  , 0\n%!       1.5, 1\n%!       2  , 0\n%!       2.5, 2\n%!       3.5, 1\n%!       3  , 0\n%!       4  , 0];\n%!\n%! clf;\n%! gplot (A, xy, \"o-\");\n%! set (get (gca, (\"children\")), \"markersize\", 12);\n%! title (\"gplot() of Binary Tree Adjacency matrix\");\n\n## Mark graphical function as tested by demo block\n%!assert (1)\n"
  },
  {
    "path": "scripts/sparse/ichol.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{L} =} ichol (@var{A})\n## @deftypefnx {} {@var{L} =} ichol (@var{A}, @var{opts})\n##\n## Compute the incomplete Cholesky factorization of the sparse square matrix\n## @var{A}.\n##\n## By default, @code{ichol} uses only the lower triangle of @var{A} and\n## produces a lower triangular factor @var{L} such that @tcode{L*L'}\n## approximates @var{A}.\n##\n## The factor given by this routine may be useful as a preconditioner for a\n## system of linear equations being solved by iterative methods such as\n## PCG (Preconditioned Conjugate Gradient).\n##\n## The factorization may be modified by passing options in a structure\n## @var{opts}.  The option name is a field of the structure and the setting\n## is the value of field.  Names and specifiers are case sensitive.\n##\n## @table @asis\n## @item type\n## Type of factorization.\n##\n## @table @asis\n## @item @qcode{\"nofill\"} (default)\n## Incomplete Cholesky factorization with no fill-in (@nospell{IC(0)}).\n##\n## @item @qcode{\"ict\"}\n## Incomplete Cholesky factorization with threshold dropping (@nospell{ICT}).\n## @end table\n##\n## @item diagcomp\n## A non-negative scalar @var{alpha} for incomplete Cholesky factorization of\n## @code{@var{A} + @var{alpha} * diag (diag (@var{A}))} instead of @var{A}.\n## This can be useful when @var{A} is not positive definite.  The default value\n## is 0.\n##\n## @item droptol\n## A non-negative scalar specifying the drop tolerance for factorization if\n## performing @nospell{ICT}@.  The default value is 0 which produces the\n## complete Cholesky factorization.\n##\n## Non-diagonal entries of @var{L} are set to 0 unless\n##\n## @code{abs (@var{L}(i,j)) >= droptol * norm (@var{A}(j:end, j), 1)}.\n##\n## @item michol\n## Modified incomplete Cholesky factorization:\n##\n## @table @asis\n## @item @qcode{\"off\"} (default)\n## Row and column sums are not necessarily preserved.\n##\n## @item @qcode{\"on\"}\n## The diagonal of @var{L} is modified so that row (and column) sums are\n## preserved even when elements have been dropped during the factorization.\n## The relationship preserved is: @code{@var{A} * e = @var{L} * @var{L}' * e},\n## where e is a vector of ones.\n## @end table\n##\n## @item shape\n##\n## @table @asis\n## @item @qcode{\"lower\"} (default)\n## Use only the lower triangle of @var{A} and return a lower triangular factor\n## @var{L} such that @tcode{L*L'} approximates @var{A}.\n##\n## @item @qcode{\"upper\"}\n## Use only the upper triangle of @var{A} and return an upper triangular factor\n## @var{U} such that @code{U'*U} approximates @var{A}.\n## @end table\n## @end table\n##\n## EXAMPLES\n##\n## The following problem demonstrates how to factorize a sample symmetric\n## positive definite matrix with the full Cholesky decomposition and with the\n## incomplete one.\n##\n## @example\n## @group\n## A = [ 0.37, -0.05,  -0.05,  -0.07;\n##      -0.05,  0.116,  0.0,   -0.05;\n##      -0.05,  0.0,    0.116, -0.05;\n##      -0.07, -0.05,  -0.05,   0.202];\n## A = sparse (A);\n## nnz (tril (A))\n## ans =  9\n## L = chol (A, \"lower\");\n## nnz (L)\n## ans =  10\n## norm (A - L * L', \"fro\") / norm (A, \"fro\")\n## ans =  1.1993e-16\n## opts.type = \"nofill\";\n## L = ichol (A, opts);\n## nnz (L)\n## ans =  9\n## norm (A - L * L', \"fro\") / norm (A, \"fro\")\n## ans =  0.019736\n## @end group\n## @end example\n##\n## Another example for decomposition is a finite difference matrix used to\n## solve a boundary value problem on the unit square.\n##\n## @example\n## @group\n## nx = 400; ny = 200;\n## hx = 1 / (nx + 1); hy = 1 / (ny + 1);\n## Dxx = spdiags ([ones(nx, 1), -2*ones(nx, 1), ones(nx, 1)],\n##                [-1 0 1 ], nx, nx) / (hx ^ 2);\n## Dyy = spdiags ([ones(ny, 1), -2*ones(ny, 1), ones(ny, 1)],\n##                [-1 0 1 ], ny, ny) / (hy ^ 2);\n## A = -kron (Dxx, speye (ny)) - kron (speye (nx), Dyy);\n## nnz (tril (A))\n## ans =  239400\n## opts.type = \"nofill\";\n## L = ichol (A, opts);\n## nnz (tril (A))\n## ans =  239400\n## norm (A - L * L', \"fro\") / norm (A, \"fro\")\n## ans =  0.062327\n## @end group\n## @end example\n##\n## References for implemented algorithms:\n##\n## [1] @nospell{Y. Saad}, \"Preconditioning Techniques\",\n## @cite{Iterative Methods for Sparse Linear Systems}, @nospell{PWS} Publishing\n## Company, 1996.\n##\n## [2] @nospell{M. Jones, P. Plassmann},\n## @cite{An Improved Incomplete Cholesky Factorization}, 1992.\n## @seealso{chol, ilu, pcg}\n## @end deftypefn\n\nfunction L = ichol (A, opts = struct ())\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (issparse (A) && issquare (A)))\n    error (\"ichol: A must be a sparse square matrix\");\n  endif\n\n  if (! isstruct (opts))\n    error (\"ichol: OPTS must be a structure\");\n  endif\n\n  ## If A is empty then return empty L for Matlab compatibility\n  if (isempty (A))\n    L = A;\n    return;\n  endif\n\n  ## Parse input options\n  if (! isfield (opts, \"type\"))\n    opts.type = \"nofill\";  # set default\n  else\n    type = lower (getfield (opts, \"type\"));\n    if (! strcmp (type, \"nofill\") && ! strcmp (type, \"ict\"))\n      error ('ichol: TYPE must be \"nofill\" or \"ict\"');\n    endif\n    opts.type = type;\n  endif\n\n  if (! isfield (opts, \"droptol\"))\n    opts.droptol = 0;      # set default\n  else\n    if (! (isreal (opts.droptol) && isscalar (opts.droptol)\n           && opts.droptol >= 0))\n      error (\"ichol: DROPTOL must be a non-negative real scalar\");\n    endif\n  endif\n\n  michol = \"\";\n  if (! isfield (opts, \"michol\"))\n    opts.michol = \"off\";   # set default\n  else\n    michol = lower (getfield (opts, \"michol\"));\n    if (! strcmp (michol, \"off\") && ! strcmp (michol, \"on\"))\n      error ('ichol: MICHOL must be \"on\" or \"off\"');\n    endif\n    opts.michol = michol;\n  endif\n\n  if (! isfield (opts, \"diagcomp\"))\n    opts.diagcomp = 0;     # set default\n  else\n    if (! (isreal (opts.diagcomp) && isscalar (opts.diagcomp)\n           && opts.diagcomp >= 0))\n      error (\"ichol: DIAGCOMP must be a non-negative real scalar\");\n    endif\n  endif\n\n  if (! isfield (opts, \"shape\"))\n    opts.shape = \"lower\";  # set default\n  else\n    shape = lower (getfield (opts, \"shape\"));\n    if (! strcmp (shape, \"lower\") && ! strcmp (shape, \"upper\"))\n      error ('ichol: SHAPE must be \"lower\" or \"upper\"');\n    endif\n    opts.shape = shape;\n  endif\n\n  ## Prepare input for specialized ICHOL\n  A_in = [];\n  if (opts.diagcomp > 0)\n    A += opts.diagcomp * diag (diag (A));\n  endif\n  if (strcmp (opts.shape, \"upper\"))\n    A_in = triu (A);\n    A_in = A_in';\n  else\n    A_in = tril (A);\n  endif\n\n  ## Delegate to specialized ICHOL\n  switch (opts.type)\n    case \"nofill\"\n      L = __ichol0__ (A_in, opts.michol);\n    case \"ict\"\n      L = __icholt__ (A_in, opts.droptol, opts.michol);\n  endswitch\n\n  if (strcmp (opts.shape, \"upper\"))\n    L = L';\n  endif\n\nendfunction\n\n\n%!shared A1, A2, A3, A4, A5, A6, A7\n%! A1 = [ 0.37, -0.05,  -0.05,  -0.07;\n%!       -0.05,  0.116,  0.0,   -0.05;\n%!       -0.05,  0.0,    0.116, -0.05;\n%!       -0.07, -0.05,  -0.05,   0.202];\n%! A1 = sparse (A1);\n%! A2 = gallery (\"poisson\", 30);\n%! A3 = gallery (\"tridiag\", 50);\n%! nx = 400; ny = 200;\n%! hx = 1 / (nx + 1); hy = 1 / (ny + 1);\n%! Dxx = spdiags ([ones(nx, 1), -2*ones(nx, 1), ones(nx, 1)],\n%!                [-1 0 1 ], nx, nx) / (hx ^ 2);\n%! Dyy = spdiags ([ones(ny, 1), -2*ones(ny, 1), ones(ny, 1)],\n%!                [-1 0 1 ], ny, ny) / (hy ^ 2);\n%! A4 = -kron (Dxx, speye (ny)) - kron (speye (nx), Dyy);\n%! A5 = [ 0.37, -0.05,         -0.05,  -0.07;\n%!       -0.05,  0.116,         0.0,   -0.05 + 0.05i;\n%!       -0.05,  0.0,           0.116, -0.05;\n%!       -0.07, -0.05 - 0.05i, -0.05,   0.202];\n%! A5 = sparse (A5);\n%! A6 = [ 0.37,     -0.05 - i, -0.05,  -0.07;\n%!       -0.05 + i,  0.116,     0.0,   -0.05;\n%!       -0.05,      0.0,       0.116, -0.05;\n%!       -0.07,     -0.05,     -0.05,   0.202];\n%! A6 = sparse (A6);\n%! A7 = A5;\n%! A7(1) = 2i;\n\n## ICHOL0 tests\n\n%!test\n%! opts.type = \"nofill\";\n%! opts.michol = \"off\";\n%! assert (nnz (tril (A1)), nnz (ichol (A1, opts)));\n%! assert (nnz (tril (A2)), nnz (ichol (A2, opts)));\n%! assert (nnz (tril (A3)), nnz (ichol (A3, opts)));\n%! assert (nnz (tril (A4)), nnz (ichol (A4, opts)));\n%! assert (nnz (tril (A5)), nnz (ichol (A5, opts)));\n%!\n%!test\n%! opts.type = \"nofill\";\n%! opts.michol = \"off\";\n%! L = ichol (A1, opts);\n%! assert (norm (A1 - L * L', \"fro\") / norm (A1, \"fro\"), 0.0197, 1e-4);\n%! opts.shape = \"upper\";\n%! U = ichol (A1, opts);\n%! assert (norm (A1 - U' * U, \"fro\") / norm (A1, \"fro\"), 0.0197, 1e-4);\n%! opts.shape = \"lower\";\n%! L = ichol (A1, opts);\n%! assert (norm (A1 - L * L', \"fro\") / norm (A1, \"fro\"), 0.0197, 1e-4);\n%!\n%!test\n%! opts.michol = \"on\";\n%! opts.shape = \"lower\";\n%! opts.type = \"nofill\";\n%! L = ichol (A1, opts);\n%! assert (norm (A1 - L * L', \"fro\") / norm (A1, \"fro\"), 0.0279, 1e-4);\n%! opts.shape = \"upper\";\n%! U = ichol (A1, opts);\n%! assert (norm (A1 - U' * U, \"fro\") / norm (A1, \"fro\"), 0.0279, 1e-4);\n%! opts.shape = \"lower\";\n%! opts.diagcomp = 3e-3;\n%! L = ichol (A1, opts);\n%! assert (norm (A1 - L * L', \"fro\") / norm (A1, \"fro\"), 0.0272, 1e-4);\n%!\n%!test\n%! opts.type = \"nofill\";\n%! opts.michol = \"off\";\n%! L = ichol (A2, opts);\n%! assert (norm (A2 - L*L', \"fro\") / norm (A2, \"fro\"), 0.0893, 1e-4);\n%! opts.michol = \"on\";\n%! L = ichol (A2, opts);\n%! assert (norm (A2 - L*L', \"fro\") / norm (A2, \"fro\"), 0.2377, 1e-4);\n%!\n%!test\n%! opts.type = \"nofill\";\n%! opts.michol = \"off\";\n%! L = ichol (A3, opts);\n%! assert (norm (A3 - L*L', \"fro\") / norm (A3, \"fro\"), eps, eps);\n%! opts.michol = \"on\";\n%! L = ichol (A3, opts);\n%! assert (norm (A3 - L*L', \"fro\") / norm (A3, \"fro\"), eps, eps);\n%!\n%!test\n%! opts.type = \"nofill\";\n%! opts.michol = \"off\";\n%! L = ichol (A4, opts);\n%! assert (norm (A4 - L*L', \"fro\") / norm (A4, \"fro\"), 0.0623, 1e-4);\n%! opts.michol = \"on\";\n%! L = ichol (A4, opts);\n%! assert (norm (A4 - L*L', \"fro\") / norm (A4, \"fro\"), 0.1664, 1e-4);\n%!\n%!test\n%! opts.type = \"nofill\";\n%! opts.michol = \"off\";\n%! L = ichol (A5, opts);\n%! assert (norm (A5 - L*L', \"fro\") / norm (A5, \"fro\"), 0.0195, 1e-4);\n%! opts.michol = \"on\";\n%! L = ichol (A5, opts);\n%! assert (norm (A5 - L*L', \"fro\") / norm (A5, \"fro\"), 0.0276, 1e-4);\n\n## Negative pivot\n%!error <negative pivot> ichol (A6)\n%!error ichol (A6)\n## Complex entry in the diagonal\n%!error <non-real pivot> ichol (A7)\n\n## ICHOLT tests\n\n%!#test\n%! opts.type = \"ict\";\n%! opts.droptol = 1e-1;\n%! opts.michol = \"off\";\n%! L = ichol (A1, opts);\n%! assert (norm (A1 - L * L', \"fro\") / norm (A1, \"fro\"), 0.2065, 1e-4);\n%! opts.shape = \"upper\";\n%! U = ichol (A1, opts);\n%! assert (norm (A1 - U' * U, \"fro\") / norm (A1, \"fro\"), 0.2065, 1e-4);\n%! opts.shape = \"lower\";\n%! L = ichol (A1, opts);\n%! assert (norm (A1 - L * L', \"fro\") / norm (A1, \"fro\"), 0.2065, 1e-4);\n\n%!#test\n%! opts.type = \"ict\";\n%! opts.droptol = 1e-1;\n%! opts.michol = \"on\";\n%! L = ichol (A1, opts);\n%! assert (norm (A1 - L * L', \"fro\") / norm (A1, \"fro\"), 0.3266, 1e-4);\n%! opts.shape = \"upper\";\n%! U = ichol (A1, opts);\n%! assert (norm (A1 - U' * U, \"fro\") / norm (A1, \"fro\"), 0.3266, 1e-4);\n%! opts.shape = \"lower\";\n%! opts.diagcomp = 3e-3;\n%! L = ichol (A1, opts);\n%! assert (norm (A1 - L * L', \"fro\") / norm (A1, \"fro\"), 0.3266, 1e-4);\n\n%!test\n%! opts.type = \"ict\";\n%! opts.droptol = 1e-1;\n%! opts.michol = \"off\";\n%! L = ichol (A2, opts);\n%! assert (norm (A2 - L*L', \"fro\") / norm (A2, \"fro\"), 0.0893, 1e-4);\n%! opts.michol = \"on\";\n%! L = ichol (A2, opts);\n%! assert (norm (A2 - L*L', \"fro\") / norm (A2, \"fro\"), 0.2377, 1e-4);\n\n%!test\n%! opts.type = \"ict\";\n%! opts.droptol = 1e-1;\n%! opts.michol = \"off\";\n%! L = ichol (A3, opts);\n%! assert (norm (A3 - L*L', \"fro\") / norm (A3, \"fro\"), eps, eps);\n%! opts.michol = \"on\";\n%! L = ichol (A3, opts);\n%! assert (norm (A3 - L*L', \"fro\") / norm (A3, \"fro\"), eps, eps);\n\n%!test\n%! opts.type = \"ict\";\n%! opts.droptol = 1e-1;\n%! opts.michol = \"off\";\n%! L = ichol (A4, opts);\n%! assert (norm (A4 - L*L', \"fro\") / norm (A4, \"fro\"), 0.1224, 1e-4);\n%! opts.michol = \"on\";\n%! L = ichol (A4, opts);\n%! assert (norm (A4 - L*L', \"fro\") / norm (A4, \"fro\"), 0.2118, 1e-4);\n\n%!test\n%! opts.type = \"ict\";\n%! opts.droptol = 1e-1;\n%! opts.michol = \"off\";\n%! L = ichol (A5, opts);\n%! assert (norm (A5 - L*L', \"fro\") / norm (A5, \"fro\"), 0.2044, 1e-4);\n%! opts.michol = \"on\";\n%! L = ichol (A5, opts);\n%! assert (norm (A5 - L*L', \"fro\") / norm (A5, \"fro\"), 0.3231, 1e-4);\n\n## Test input validation\n%!error <A must be a sparse square matrix> ichol ([])\n%!error <A must be a sparse square matrix> ichol (0)\n%!error <pivot equal to 0> ichol (sparse (0))\n%!error <pivot equal to 0> ichol (sparse (-0))\n%!error <negative pivot> ichol (sparse (-1))\n%!test\n%! opts.type = \"foo\";\n%! fail (\"ichol (A1, opts)\", 'TYPE must be \"nofill\"');\n%! opts.type = 1;\n%! fail (\"ichol (A1, opts)\", 'TYPE must be \"nofill\"');\n%! opts.type = [];\n%! fail (\"ichol (A1, opts)\", 'TYPE must be \"nofill\"');\n%!test\n%! opts.droptol = -1;\n%! fail (\"ichol (A1, opts)\", \"DROPTOL must be a non-negative real scalar\");\n%! opts.droptol = 0.5i;\n%! fail (\"ichol (A1, opts)\", \"DROPTOL must be a non-negative real scalar\");\n%! opts.droptol = [];\n%! fail (\"ichol (A1, opts)\", \"DROPTOL must be a non-negative real scalar\");\n%!test\n%! opts.michol = \"foo\";\n%! fail (\"ichol (A1, opts)\", 'MICHOL must be \"on\"');\n%! opts.michol = 1;\n%! fail (\"ichol (A1, opts)\", 'MICHOL must be \"on\"');\n%! opts.michol = [];\n%! fail (\"ichol (A1, opts)\", 'MICHOL must be \"on\"');\n%!test\n%! opts.diagcomp = -1;\n%! fail (\"ichol (A1, opts)\", \"DIAGCOMP must be a non-negative real scalar\");\n%! opts.diagcomp = 0.5i;\n%! fail (\"ichol (A1, opts)\", \"DIAGCOMP must be a non-negative real scalar\");\n%! opts.diagcomp = [];\n%! fail (\"ichol (A1, opts)\", \"DIAGCOMP must be a non-negative real scalar\");\n%!test\n%! opts.shape = \"foo\";\n%! fail (\"ichol (A1, opts)\", 'SHAPE must be \"lower\"');\n%! opts.shape = 1;\n%! fail (\"ichol (A1, opts)\", 'SHAPE must be \"lower\"');\n%! opts.shape = [];\n%! fail (\"ichol (A1, opts)\", 'SHAPE must be \"lower\"');\n"
  },
  {
    "path": "scripts/sparse/ilu.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{LUA} =} ilu (@var{A})\n## @deftypefnx {} {@var{LUA} =} ilu (@var{A}, @var{opts})\n## @deftypefnx {} {[@var{L}, @var{U}] =} ilu (@dots{})\n## @deftypefnx {} {[@var{L}, @var{U}, @var{P}] =} ilu (@dots{})\n##\n## Compute the incomplete LU factorization of the sparse square matrix @var{A}.\n##\n## @code{ilu} returns a unit lower triangular matrix @var{L}, an upper\n## triangular matrix @var{U}, and optionally a permutation matrix @var{P}, such\n## that @code{@var{L}*@var{U}} approximates @code{@var{P}*@var{A}}.\n##\n## The factors given by this routine may be useful as preconditioners for a\n## system of linear equations being solved by iterative methods such as BICG\n## (BiConjugate Gradients) or GMRES (Generalized Minimum Residual Method).\n##\n## The factorization may be modified by passing options in a structure\n## @var{opts}.  The option name is a field of the structure and the setting\n## is the value of field.  Names and specifiers are case sensitive.\n##\n## @table @code\n## @item type\n## Type of factorization.\n##\n## @table @asis\n## @item @qcode{\"nofill\"} (default)\n## ILU factorization with no fill-in (ILU(0)).\n##\n## Additional supported options: @code{milu}.\n##\n## @item @qcode{\"crout\"}\n## Crout version of ILU factorization (@nospell{ILUC}).\n##\n## Additional supported options: @code{milu}, @code{droptol}.\n##\n## @item @qcode{\"ilutp\"}\n## ILU factorization with threshold and pivoting.\n##\n## Additional supported options: @code{milu}, @code{droptol}, @code{udiag},\n## @code{thresh}.\n## @end table\n##\n## @item droptol\n## A non-negative scalar specifying the drop tolerance for factorization.  The\n## default value is 0 which produces the complete LU factorization.\n##\n## Non-diagonal entries of @var{U} are set to 0 unless\n##\n## @code{abs (@var{U}(i,j)) >= droptol * norm (@var{A}(:,j))}.\n##\n## Non-diagonal entries of @var{L} are set to 0 unless\n##\n## @code{abs (@var{L}(i,j)) >= droptol * norm (@var{A}(:,j))/@var{U}(j,j)}.\n##\n## @item milu\n## Modified incomplete LU factorization:\n##\n## @table @asis\n## @item @qcode{\"row\"}\n## Row-sum modified incomplete LU factorization.\n## The factorization preserves row sums:\n## @code{@var{A} * e = @var{L} * @var{U} * e}, where e is a vector of ones.\n##\n## @item @qcode{\"col\"}\n## Column-sum modified incomplete LU factorization.\n## The factorization preserves column sums:\n## @code{e' * @var{A} = e' * @var{L} * @var{U}}.\n##\n## @item @qcode{\"off\"} (default)\n## Row and column sums are not necessarily preserved.\n## @end table\n##\n## @item udiag\n## If true, any zeros on the diagonal of the upper triangular factor are\n## replaced by the local drop tolerance\n## @code{droptol * norm (@var{A}(:,j))/@var{U}(j,j)}.  The default is false.\n##\n## @item thresh\n## Pivot threshold for factorization.  It can range between 0 (diagonal\n## pivoting) and 1 (default), where the maximum magnitude entry in the column\n## is chosen to be the pivot.\n## @end table\n##\n## If @code{ilu} is called with just one output, the returned matrix is\n## @code{@var{L} + @var{U} - speye (size (@var{A}))}, where @var{L} is unit\n## lower triangular and @var{U} is upper triangular.\n##\n## With two outputs, @code{ilu} returns a unit lower triangular matrix @var{L}\n## and an upper triangular matrix @var{U}.  For @var{opts}.type ==\n## @qcode{\"ilutp\"}, one of the factors is permuted based on the value of\n## @var{opts}.milu.  When @var{opts}.milu == @qcode{\"row\"}, @var{U} is a\n## column permuted upper triangular factor.  Otherwise, @var{L} is a\n## row-permuted unit lower triangular factor.\n##\n## If there are three named outputs and @var{opts}.milu != @qcode{\"row\"},\n## @var{P} is returned such that @var{L} and @var{U} are incomplete factors\n## of @code{@var{P}*@var{A}}.  When @var{opts}.milu == @qcode{\"row\"}, @var{P}\n## is returned such that @var{L} and @var{U} are incomplete factors of\n## @code{@var{A}*@var{P}}.\n##\n## EXAMPLES\n##\n## @example\n## @group\n## A = gallery (\"neumann\", 1600) + speye (1600);\n## opts.type = \"nofill\";\n## nnz (A)\n## ans = 7840\n##\n## nnz (lu (A))\n## ans = 126478\n##\n## nnz (ilu (A, opts))\n## ans = 7840\n## @end group\n## @end example\n##\n## This shows that @var{A} has 7,840 nonzeros, the complete LU factorization\n## has 126,478 nonzeros, and the incomplete LU factorization, with 0 level of\n## fill-in, has 7,840 nonzeros, the same amount as @var{A}.  Taken from:\n## @url{https://www.mathworks.com/help/matlab/ref/ilu.html}\n##\n## @example\n## @group\n## A = gallery (\"wathen\", 10, 10);\n## b = sum (A, 2);\n## tol = 1e-8;\n## maxit = 50;\n## opts.type = \"crout\";\n## opts.droptol = 1e-4;\n## [L, U] = ilu (A, opts);\n## x = bicg (A, b, tol, maxit, L, U);\n## norm (A * x - b, inf)\n## @end group\n## @end example\n##\n## This example uses ILU as preconditioner for a random FEM-Matrix, which has a\n## large condition number.  Without @var{L} and @var{U} BICG would not\n## converge.\n##\n## @seealso{lu, ichol, bicg, gmres}\n## @end deftypefn\n\nfunction [L, U, P] = ilu (A, opts = struct ())\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (issparse (A) && issquare (A)))\n    error (\"ilu: A must be a sparse square matrix\");\n  endif\n\n  if (! isstruct (opts))\n    error (\"ilu: OPTS must be a structure\");\n  endif\n\n  ## If A is empty then return empty L, U and P for Matlab compatibility\n  if (isempty (A))\n    L = U = P = A;\n    return;\n  endif\n\n  ## Parse input options\n  if (! isfield (opts, \"type\"))\n    opts.type = \"nofill\";  # set default\n  else\n    type = lower (getfield (opts, \"type\"));\n    if (! any (strcmp (type, {\"nofill\", \"crout\", \"ilutp\"})))\n      error (\"ilu: invalid TYPE specified\");\n    endif\n    opts.type = type;\n  endif\n\n  if (! isfield (opts, \"droptol\"))\n    opts.droptol = 0;      # set default\n  else\n    if (! (isreal (opts.droptol) && isscalar (opts.droptol)\n           && opts.droptol >= 0))\n      error (\"ilu: DROPTOL must be a non-negative real scalar\");\n    endif\n  endif\n\n  if (! isfield (opts, \"milu\"))\n    opts.milu = \"off\";     # set default\n  else\n    milu = lower (getfield (opts, \"milu\"));\n    if (! any (strcmp (milu, {\"off\", \"col\", \"row\"})))\n      error ('ilu: MILU must be one of \"off\", \"col\", or \"row\"');\n    endif\n    opts.milu = milu;\n  endif\n\n  if (! isfield (opts, \"udiag\"))\n    opts.udiag = 0;        # set default\n  else\n    if (! isscalar (opts.udiag) || (opts.udiag != 0 && opts.udiag != 1))\n      error (\"ilu: UDIAG must be 0 or 1\");\n    endif\n  endif\n\n  if (! isfield (opts, \"thresh\"))\n    opts.thresh = 1;       # set default\n  else\n    if (! (isreal (opts.thresh) && isscalar (opts.thresh))\n        || opts.thresh < 0 || opts.thresh > 1)\n      error (\"ilu: THRESH must be a scalar in the range [0, 1]\");\n    endif\n  endif\n\n  n = length (A);\n\n  ## Delegate to specialized ILU\n  switch (opts.type)\n    case \"nofill\"\n        [L, U] = __ilu0__ (A, opts.milu);\n        if (nargout == 3)\n          P = speye (length (A));\n        endif\n    case \"crout\"\n        [L, U] = __iluc__ (A, opts.droptol, opts.milu);\n        if (nargout == 3)\n          P = speye (length (A));\n        endif\n    case \"ilutp\"\n        if (nargout == 3)\n          [L, U, P] = __ilutp__ (A, opts.droptol, opts.thresh,\n                                    opts.milu, opts.udiag);\n        else\n          [L, U] = __ilutp__ (A, opts.droptol, opts.thresh,\n                                 opts.milu, opts.udiag);\n        endif\n  endswitch\n\n  if (nargout == 1)\n    L = L + U - speye (n);\n  endif\n\nendfunction\n\n\n%!shared n, dtol, A\n%! n = 1600;\n%! dtol = 0.1;\n%! A = gallery (\"neumann\", n) + speye (n);\n\n%!test\n%! opts.type = \"nofill\";\n%! assert (nnz (ilu (A, opts)), 7840);\n\n## This test has been verified in both Matlab and Octave.\n%!test\n%! opts.type = \"crout\";\n%! opts.milu = \"row\";\n%! opts.droptol = dtol;\n%! [L, U] = ilu (A, opts);\n%! e = ones (columns (A),1);\n%! assert (norm (A*e - L*U*e), 1e-14, 1e-14);\n%!test\n%! opts.type = \"crout\";\n%! opts.droptol = dtol;\n%! [L, U] = ilu (A, opts);\n%! assert (norm (A - L * U, \"fro\") / norm (A, \"fro\"), 0.05, 1e-2);\n\n## Check if the elements in U satisfy the non-dropping condition.\n%!test\n%! opts.type = \"crout\";\n%! opts.droptol = dtol;\n%! [L, U] = ilu (A, opts);\n%! for j = 1:n\n%!   cmp_value = dtol * norm (A(:, j));\n%!   non_zeros = nonzeros (U(:, j));\n%!   assert (abs (non_zeros) >= cmp_value);\n%! endfor\n%!test\n%! opts.type = \"ilutp\";\n%! opts.droptol = dtol;\n%! [L, U] = ilu (A, opts);\n%! for j = 1:n\n%!   cmp_value = dtol * norm (A(:, j));\n%!   non_zeros = nonzeros (U(:, j));\n%!   assert (abs (non_zeros) >= cmp_value);\n%! endfor\n\n## Check that the complete LU factorisation with crout and ilutp algorithms\n## produce the same result.\n%!test\n%! opts.type = \"crout\";\n%! opts.droptol = 0;\n%! [L1, U1] = ilu (A, opts);\n%! opts.type = \"ilutp\";\n%! opts.thresh = 0;\n%! [L2, U2] = ilu (A, opts);\n%! assert (norm (L1 - L2, \"fro\") / norm (L1, \"fro\"), 0, eps);\n%! assert (norm (U1 - U2, \"fro\") / norm (U1, \"fro\"), 0, eps);\n\n## Restore rand \"state\" value\n%!shared old_rand_state, restore_state\n%! ## Save and restore the state of the random number generator that is used by\n%! ## the unit tests in this file.\n%! old_rand_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_rand_state));\n\n## Tests for real matrices of different sizes for ilu0, iluc and ilutp.\n## The difference A - L*U should be not greater than eps because with droptol\n## equal to 0, the LU complete factorization is performed.\n%!shared n_tiny, n_small, n_medium, n_large, A_tiny, A_small, A_medium, A_large\n%! n_tiny = 5;\n%! n_small = 40;\n%! n_medium = 600;\n%! n_large = 10000;\n%! A_tiny = spconvert ([1 4 2 3 3 4 2 5; 1 1 2 3 4 4 5 5; 1 2 3 4 5 6 7 8]');\n%! ## initialize generator to make behavior reproducible\n%! rand (\"state\", 42);\n%! A_small = sprand (n_small, n_small, 1/n_small) + speye (n_small);\n%! A_medium = sprand (n_medium, n_medium, 1/n_medium) + speye (n_medium);\n%! A_large = sprand (n_large, n_large, 1/n_large/10) + speye (n_large);\n\n%!test\n%! opts.type = \"nofill\";\n%! [L, U] = ilu (A_tiny);\n%! assert (norm (A_tiny - L*U, \"fro\") / norm (A_tiny, \"fro\"), 0, n_tiny * eps);\n%!test\n%! opts.type = \"nofill\";\n%! [L, U] = ilu (A_small);\n%! assert (norm (A_small - L*U, \"fro\") / norm (A_small, \"fro\"), 0, 1);\n%!test\n%! opts.type = \"nofill\";\n%! [L, U] = ilu (A_medium);\n%! assert (norm (A_medium - L*U, \"fro\") / norm (A_medium, \"fro\"), 0, 1);\n%!test\n%! opts.type = \"nofill\";\n%! [L, U] = ilu (A_large);\n%! assert (norm (A_large - L*U, \"fro\") / norm (A_large, \"fro\"), 0, 1);\n\n%!test\n%! opts.type = \"crout\";\n%! [L, U] = ilu (A_tiny, opts);\n%! assert (norm (A_tiny - L*U, \"fro\") / norm (A_tiny, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"crout\";\n%! [L, U] = ilu (A_small, opts);\n%! assert (norm (A_small - L*U, \"fro\") / norm (A_small, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"crout\";\n%! [L, U] = ilu (A_medium, opts);\n%! assert (norm (A_medium - L*U, \"fro\") / norm (A_medium, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"crout\";\n%! [L, U] = ilu (A_large, opts);\n%! assert (norm (A_large - L*U, \"fro\") / norm (A_large, \"fro\"), eps, eps);\n\n%!test\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0;\n%! opts.thresh = 0;\n%! [L, U] = ilu (A_tiny, opts);\n%! assert (norm (A_tiny - L*U, \"fro\") / norm (A_tiny, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0;\n%! opts.thresh = 0;\n%! [L, U] = ilu (A_small, opts);\n%! assert (norm (A_small - L*U, \"fro\") / norm (A_small, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0;\n%! opts.thresh = 0;\n%! [L, U] = ilu (A_medium, opts);\n%! assert (norm (A_medium - L*U, \"fro\") / norm (A_medium, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0;\n%! opts.thresh = 0;\n%! [L, U] = ilu (A_large, opts);\n%! assert (norm (A_large - L*U, \"fro\") / norm (A_large, \"fro\"), eps, eps);\n\n## Tests for complex matrices of different sizes for ilu0, iluc and ilutp.\n%!shared n_tiny, n_small, n_medium, n_large, A_tiny, A_small, A_medium, A_large\n%! n_tiny = 5;\n%! n_small = 40;\n%! n_medium = 600;\n%! n_large = 10000;\n%! A_tiny = spconvert ([1 4 2 3 3 4 2 5; 1 1 2 3 4 4 5 5; 1 2 3 4 5 6 7 8]');\n%! A_tiny(1,1) += 1i;\n%! ## initialize generator to make behavior reproducible\n%! rand (\"state\", 42);\n%! A_small = sprand (n_small, n_small, 1/n_small) + ...\n%!   i * sprand (n_small, n_small, 1/n_small) + speye (n_small);\n%! A_medium = sprand (n_medium, n_medium, 1/n_medium) + ...\n%!   i * sprand (n_medium, n_medium, 1/n_medium) + speye (n_medium);\n%! A_large = sprand (n_large, n_large, 1/n_large/10) + ...\n%!   i * sprand (n_large, n_large, 1/n_large/10) + speye (n_large);\n\n%!test\n%! opts.type = \"nofill\";\n%! [L, U] = ilu (A_tiny);\n%! assert (norm (A_tiny - L*U, \"fro\") / norm (A_tiny, \"fro\"), 0, n_tiny * eps);\n%!test\n%! opts.type = \"nofill\";\n%! [L, U] = ilu (A_small);\n%! assert (norm (A_small - L*U, \"fro\") / norm (A_small, \"fro\"), 0, 1);\n%!test\n%! opts.type = \"nofill\";\n%! [L, U] = ilu (A_medium);\n%! assert (norm (A_medium - L*U, \"fro\") / norm (A_medium, \"fro\"), 0, 1);\n%!test\n%! opts.type = \"nofill\";\n%! [L, U] = ilu (A_large);\n%! assert (norm (A_large - L*U, \"fro\") / norm (A_large, \"fro\"), 0, 1);\n\n%!test\n%! opts.type = \"crout\";\n%! [L, U] = ilu (A_tiny, opts);\n%! assert (norm (A_tiny - L*U, \"fro\") / norm (A_tiny, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"crout\";\n%! [L, U] = ilu (A_small, opts);\n%! assert (norm (A_small - L*U, \"fro\") / norm (A_small, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"crout\";\n%! [L, U] = ilu (A_medium, opts);\n%! assert (norm (A_medium - L*U, \"fro\") / norm (A_medium, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"crout\";\n%! [L, U] = ilu (A_large, opts);\n%! assert (norm (A_large - L*U, \"fro\") / norm (A_large, \"fro\"), eps, eps);\n\n%!test\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0;\n%! opts.thresh = 0;\n%! [L, U] = ilu (A_tiny, opts);\n%! assert (norm (A_tiny - L*U, \"fro\") / norm (A_tiny, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0;\n%! opts.thresh = 0;\n%! [L, U] = ilu (A_small, opts);\n%! assert (norm (A_small - L*U, \"fro\") / norm (A_small, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0;\n%! opts.thresh = 0;\n%! [L, U] = ilu (A_medium, opts);\n%! assert (norm (A_medium - L*U, \"fro\") / norm (A_medium, \"fro\"), eps, eps);\n%!test\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0;\n%! opts.thresh = 0;\n%! [L, U] = ilu (A_large, opts);\n%! assert (norm (A_large - L*U, \"fro\") / norm (A_large, \"fro\"), eps, eps);\n\n## Specific tests for ilutp\n%!shared A\n%! A = sparse ([0 0 4 3 1; 5 1 2.3 2 4.5; 0 0 0 2 1;0 0 8 0 2.2; 0 0 9 9 1 ]);\n\n%!test\n%! opts.udiag = 1;\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0.2;\n%! [L, U, P] = ilu (A, opts);\n%! assert (norm (U, \"fro\"), 17.4577, 1e-4);\n%! assert (norm (L, \"fro\"), 2.4192, 1e-4);\n\n%!error <encountered a pivot equal to 0>\n%! opts.type = \"ilutp\";\n%! opts.udiag = 0;\n%! opts.droptol = 0.2;\n%! ilu (A, opts);\n\n## Matlab R2017b doesn't error, but returns a singular L which isn't helpful.\n%!error <encountered a pivot equal to 0>\n%! A = sparse ([3 1 0 0 4; 3 1 0 0 -2;0 0 8 0 0; 0 4 0 4 -4.5; 0 -1 0 0 1]);\n%! opts.type = \"ilutp\";\n%! opts.droptol = 0;\n%! opts.thresh = 0;\n%! opts.milu = \"row\";\n%! [L, U, P] = ilu (A, opts);\n\n%!test <*53440>\n%! A = sparse (magic (4));\n%! opts.type = \"ilutp\";\n%! [L, U] = ilu (A, opts);\n%! assert (L * U, A, eps);\n\n## Tests for input validation\n%!shared A_tiny, opts\n%! A_tiny = spconvert ([1 4 2 3 3 4 2 5; 1 1 2 3 4 4 5 5; 1 2 3 4 5 6 7 8]');\n\n%!test\n%! [L, U] = ilu (sparse ([]));\n%! assert (isempty (L));\n%! assert (isempty (U));\n%! opts.type = \"crout\";\n%! [L, U] = ilu (sparse ([]), opts);\n%! assert (isempty (L));\n%! assert (isempty (U));\n%! opts.type = \"ilutp\";\n%! [L, U] = ilu (sparse ([]), opts);\n%! assert (isempty (L));\n%! assert (isempty (U));\n\n%!error <A must be a sparse square matrix> ilu (0)\n%!error <A must be a sparse square matrix> ilu ([])\n%!error <zero on the diagonal> ilu (sparse (0))\n\n%!error <invalid TYPE specified>\n%! opts.type = \"foo\";\n%! ilu (A_tiny, opts);\n%!error <invalid TYPE specified>\n%! opts.type = 1;\n%! ilu (A_tiny, opts);\n%!error <invalid TYPE specified>\n%! opts.type = [];\n%! ilu (A_tiny, opts);\n\n%!error <DROPTOL must be a non-negative real scalar>\n%! clear opts;\n%! opts.droptol = -1;\n%! ilu (A_tiny, opts);\n%!error <DROPTOL must be a non-negative real scalar>\n%! opts.droptol = 0.5i;\n%! ilu (A_tiny, opts);\n%!error <DROPTOL must be a non-negative real scalar>\n%! opts.droptol = [];\n%! ilu (A_tiny, opts);\n\n%!error <MILU must be one of \"off\", \"col\", or \"row\">\n%! clear opts;\n%! opts.milu = \"foo\";\n%! ilu (A_tiny, opts);\n%!error <MILU must be one of \"off\", \"col\", or \"row\">\n%! opts.milu = 1;\n%! ilu (A_tiny, opts);\n%!error <MILU must be one of \"off\", \"col\", or \"row\">\n%! opts.milu = [];\n%! ilu (A_tiny, opts);\n\n%!error <UDIAG must be 0 or 1>\n%! clear opts;\n%! opts.udiag = -1;\n%! ilu (A_tiny, opts);\n%!error <UDIAG must be 0 or 1>\n%! opts.udiag = 0.5i;\n%! ilu (A_tiny, opts);\n%!error <UDIAG must be 0 or 1>\n%! opts.udiag = [];\n%! ilu (A_tiny, opts);\n\n%!error <THRESH must be a scalar in the range \\[0, 1\\]>\n%! clear opts;\n%! opts.thresh = -1;\n%! ilu (A_tiny, opts);\n%!error <THRESH must be a scalar in the range \\[0, 1\\]>\n%! opts.thresh = 0.5i;\n%! ilu (A_tiny, opts);\n%!error <THRESH must be a scalar in the range \\[0, 1\\]>\n%! opts.thresh = [];\n%! ilu (A_tiny, opts);\n"
  },
  {
    "path": "scripts/sparse/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/__alltohandles__.m \\\n  %reldir%/private/__default__input__.m \\\n  %reldir%/private/__sprand__.m\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/bicg.m \\\n  %reldir%/bicgstab.m \\\n  %reldir%/cgs.m \\\n  %reldir%/colperm.m \\\n  %reldir%/eigs.m \\\n  %reldir%/etreeplot.m \\\n  %reldir%/gmres.m \\\n  %reldir%/gplot.m \\\n  %reldir%/ichol.m \\\n  %reldir%/ilu.m \\\n  %reldir%/nonzeros.m \\\n  %reldir%/pcg.m \\\n  %reldir%/pcr.m \\\n  %reldir%/qmr.m \\\n  %reldir%/spaugment.m \\\n  %reldir%/spconvert.m \\\n  %reldir%/spdiags.m \\\n  %reldir%/speye.m \\\n  %reldir%/spfun.m \\\n  %reldir%/spones.m \\\n  %reldir%/sprand.m \\\n  %reldir%/sprandn.m \\\n  %reldir%/sprandsym.m \\\n  %reldir%/spstats.m \\\n  %reldir%/spy.m \\\n  %reldir%/svds.m \\\n  %reldir%/tfqmr.m \\\n  %reldir%/treelayout.m \\\n  %reldir%/treeplot.m\n\n%canon_reldir%dir = $(fcnfiledir)/sparse\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/sparse/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/sparse/nonzeros.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{v} =} nonzeros (@var{A})\n## Return a column vector of the nonzero values of the matrix @var{A}.\n## @seealso{find, nnz}\n## @end deftypefn\n\nfunction v = nonzeros (A)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (issparse (A))\n    [~, ~, v] = find (A);\n    v = v(:);\n  else\n    v = A(find (A));\n    v = v(:);\n  endif\n\nendfunction\n\n\n%!assert (nonzeros ([1,2;3,0]), [1;3;2])\n%!assert (nonzeros ([1,2,3,0]), [1;2;3])\n%!assert (nonzeros (sparse ([1,2;3,0])), [1;3;2])\n%!assert (nonzeros (sparse ([1,2,3,0])), [1;2;3])\n\n## Test input validation\n%!error <Invalid call> nonzeros ()\n"
  },
  {
    "path": "scripts/sparse/pcg.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} pcg (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{m1}, @var{m2}, @var{x0}, @dots{})\n## @deftypefnx {} {@var{x} =} pcg (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M}, [], @var{x0}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}, @var{eigest}] =} pcg (@var{A}, @var{b}, @dots{})\n##\n## Solve the linear system of equations\n## @w{@code{@var{A} * @var{x} = @var{b}}}@ by means of the Preconditioned\n## Conjugate Gradient iterative method.\n##\n## The input arguments are:\n##\n## @itemize\n## @item @var{A} is the matrix of the linear system and it must be square.\n## @var{A} can be passed as a matrix, function handle, or inline function\n## @code{Afcn} such that @code{Afcn(x) = A * x}.  Additional parameters to\n## @code{Afcn} may be passed after @var{x0}.\n##\n## @var{A} has to be Hermitian and Positive Definite (@nospell{HPD})@.  If\n## @code{pcg} detects @var{A} not to be positive definite, a warning is printed\n## and the @var{flag} output is set.\n##\n## @item\n## @var{b} is the right-hand side vector.\n##\n## @item\n## @var{tol} is the required relative tolerance for the residual error,\n## @w{@code{@var{b} - @var{A} * @var{x}}}.  The iteration stops if\n## @w{@code{norm (@var{b} - @var{A} * @var{x})} @leq{}\n## @w{@code{@var{tol} * norm (@var{b})}}}.\n## If @var{tol} is omitted or empty, then a tolerance of 1e-6 is used.\n##\n## @item\n## @var{maxit} is the maximum allowed number of iterations; if @var{maxit}\n## is omitted or empty then a value of 20 is used.\n##\n## @item\n## @var{m} is a @nospell{HPD} preconditioning matrix.  For any decomposition\n## @code{@var{m} = @var{p1} * @var{p2}} such that\n## @w{@code{inv (@var{p1}) * @var{A} * inv (@var{p2})}}@ is @nospell{HPD}, the\n## conjugate gradient method is formally applied to the linear system\n## @w{@code{inv (@var{p1}) * @var{A} * inv (@var{p2}) * @var{y} = inv\n## (@var{p1}) * @var{b}}},\n## with @code{@var{x} = inv (@var{p2}) * @var{y}} (split preconditioning).\n## In practice, at each iteration of the conjugate gradient method a\n## linear system with matrix @var{m} is solved with @code{mldivide}.\n## If a particular factorization\n## @code{@var{m} = @var{m1} * @var{m2}} is available (for instance, an\n## incomplete Cholesky factorization of @var{a}), the two matrices\n## @var{m1} and @var{m2} can be passed and the relative linear systems\n## are solved with the @code{mldivide} operator.\n## Note that a proper choice of the preconditioner may dramatically improve\n## the overall performance of the method.  Instead of matrices @var{m1} and\n## @var{m2}, the user may pass two functions which return the results of\n## applying the inverse of @var{m1} and @var{m2} to a vector.\n## If @var{m1} is omitted or empty @code{[]}, then no preconditioning\n## is applied.  If no factorization of @var{m} is available, @var{m2}\n## can be omitted or left [], and the input variable @var{m1} can be\n## used to pass the preconditioner @var{m}.\n##\n## @item\n## @var{x0} is the initial guess.  If @var{x0} is omitted or empty then the\n## function sets @var{x0} to a zero vector by default.\n## @end itemize\n##\n## The arguments which follow @var{x0} are treated as parameters, and passed in\n## an appropriate manner to any of the functions (@var{A} or @var{m1} or\n## @var{m2}) that have been given to @code{pcg}.\n## See the examples below for further details.\n##\n## The output arguments are:\n##\n## @itemize\n## @item\n## @var{x} is the computed approximation to the solution of\n## @w{@code{@var{A} * @var{x} = @var{b}}}.  If the algorithm did not converge,\n## then @var{x} is the iteration which has the minimum residual.\n##\n## @item\n## @var{flag} reports on the convergence:\n##\n## @itemize\n## @item 0: The algorithm converged to within the prescribed tolerance.\n##\n## @item 1: The algorithm did not converge and it reached the maximum\n## number of iterations.\n##\n## @item 2: The preconditioner matrix is singular.\n##\n## @item 3: The algorithm stagnated, i.e., the absolute value of the\n## difference between the current iteration @var{x} and the previous is less\n## than @code{@var{eps} * norm (@var{x},2)}.\n##\n## @item 4: The algorithm detects that the input (preconditioned) matrix is not\n## @nospell{HPD}.\n## @end itemize\n##\n## @item\n## @var{relres} is the ratio of the final residual to its initial value,\n## measured in the Euclidean norm.\n##\n## @item\n## @var{iter} indicates the iteration of @var{x} which it was\n## computed.  Since the output @var{x} corresponds to the minimal\n## residual solution, the total number of iterations that\n## the method performed is given by @code{length(resvec) - 1}.\n##\n## @item\n## @var{resvec} describes the convergence history of the method.\n## @code{@var{resvec} (@var{i}, 1)} is the Euclidean norm of the residual, and\n## @code{@var{resvec} (@var{i}, 2)} is the preconditioned residual\n## norm, after the\n## (@var{i}-1)-th iteration, @code{@var{i} = 1, 2, @dots{}, @var{iter}+1}.\n## The preconditioned residual norm is defined as\n## @code{@var{r}' * (@var{m} \\ @var{r})} where\n## @code{@var{r} = @var{b} - @var{A} * @var{x}}, see also the\n## description of @var{m}.  If @var{eigest} is not required, only\n## @code{@var{resvec} (:, 1)} is returned.\n##\n## @item\n## @var{eigest} returns the estimate for the smallest @code{@var{eigest}(1)}\n## and largest @code{@var{eigest}(2)} eigenvalues of the preconditioned matrix\n## @w{@code{@var{P} = @var{m} \\ @var{A}}}.  In particular, if no\n## preconditioning is used, the estimates for the extreme eigenvalues of\n## @var{A} are returned.  @code{@var{eigest}(1)} is an overestimate and\n## @code{@var{eigest}(2)} is an underestimate, so that\n## @code{@var{eigest}(2) / @var{eigest}(1)} is a lower bound for\n## @code{cond (@var{P}, 2)}, which nevertheless in the limit should\n## theoretically be equal to the actual value of the condition number.\n## @end itemize\n##\n##\n## Let us consider a trivial problem with a tridiagonal matrix\n##\n## @smallexample\n## @group\n## n = 10;\n## A = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, n));\n## b = A * ones (n, 1);\n## M1 = ichol (A); # in this tridiagonal case it corresponds to chol (A)'\n## M2 = M1';\n## M = M1 * M2;\n## Afcn = @@(x) A * x;\n## Mfcn = @@(x) M \\ x;\n## M1fcn = @@(x) M1 \\ x;\n## M2fcn = @@(x) M2 \\ x;\n## @end group\n## @end smallexample\n##\n## @sc{Example 1:} Simplest use of @code{pcg}\n##\n## @example\n## x = pcg (A, b)\n## @end example\n##\n## @sc{Example 2:} @code{pcg} with a function which computes\n## @code{@var{A} * @var{x}}\n##\n## @example\n## x = pcg (Afcn, b)\n## @end example\n##\n## @sc{Example 3:} @code{pcg} with a preconditioner matrix @var{M}\n##\n## @example\n## x = pcg (A, b, 1e-06, 100, M)\n## @end example\n##\n## @sc{Example 4:} @code{pcg} with a function as preconditioner\n##\n## @example\n## x = pcg (Afcn, b, 1e-6, 100, Mfcn)\n## @end example\n##\n## @sc{Example 5:} @code{pcg} with preconditioner matrices @var{M1}\n## and @var{M2}\n##\n## @example\n## x = pcg (A, b, 1e-6, 100, M1, M2)\n## @end example\n##\n## @sc{Example 6:} @code{pcg} with functions as preconditioners\n##\n## @example\n## x = pcg (Afcn, b, 1e-6, 100, M1fcn, M2fcn)\n## @end example\n##\n## @sc{Example 7:} @code{pcg} with as input a function requiring an argument\n##\n## @example\n## @group\n##   function y = Ap (A, x, p) # compute A^p * x\n##      y = x;\n##      for i = 1:p\n##        y = A * y;\n##      endfor\n##   endfunction\n## Apfcn = @@(x, p) Ap (A, x, p);\n## x = pcg (Apfcn, b, [], [], [], [], [], 2);\n## @end group\n## @end example\n##\n## @sc{Example 8:} explicit example to show that @code{pcg} uses a\n## split preconditioner\n##\n## @example\n## @group\n## M1 = ichol (A + 0.1 * eye (n)); # factorization of A perturbed\n## M2 = M1';\n## M = M1 * M2;\n##\n## ## reference solution computed by pcg after two iterations\n## [x_ref, fl] = pcg (A, b, [], 2, M)\n##\n## ## split preconditioning\n## [y, fl] = pcg ((M1 \\ A) / M2, M1 \\ b, [], 2)\n## x = M2 \\ y # compare x and x_ref\n##\n## @end group\n## @end example\n##\n## References:\n##\n## @enumerate\n## @item\n## @nospell{C.T. Kelley},\n## @cite{Iterative Methods for Linear and Nonlinear Equations},\n## SIAM, 1995.  (the base PCG algorithm)\n##\n## @item\n## @nospell{Y. Saad}, @cite{Iterative Methods for Sparse Linear Systems},\n## @nospell{PWS}, 1996.  (condition number estimate from PCG)\n## Revised version of this book is available online at\n## @url{https://www-users.cs.umn.edu/~saad/books.html}\n## @end enumerate\n##\n## @seealso{sparse, pcr, gmres, bicg, bicgstab, cgs}\n## @end deftypefn\n\nfunction [x_min, flag, relres, iter_min, resvec, eigest] =...\n         pcg (A, b, tol = [], maxit = [], M1 = [], M2 = [], x0 = [], varargin)\n\n  ## Insert the default input (if necessary)\n  [tol, maxit, x0] = __default__input__ ({1e-6, min(rows (b), 20),...\n                                          zeros(size (b))}, tol, maxit, x0);\n\n  if (tol >= 1)\n    warning (\"Input tol is bigger than 1.\\n Try to use a smaller tolerance.\");\n  elseif (tol <= eps / 2)\n    warning (\"Input tol may not be achievable by pcg.\\n Try to use a bigger tolerance\");\n  endif\n\n  ## Check if the input data A,b,m1,m2 are consistent (i.e., if they are\n  ## matrix or function handle)\n\n  [Afcn, M1fcn, M2fcn] = __alltohandles__ (A, b, M1, M2, \"pcg\");\n\n  maxit += 2;\n  n_arg_out = nargout;\n\n  ## Set Initial data\n  b_norm = norm (b);\n  if (b_norm == 0)\n     if (n_arg_out < 2)\n       printf (\"The right hand side vector is all zero so pcg\\n\");\n       printf (\"returned an all zero solution without iterating.\\n\");\n     endif\n     x_min = b;\n     flag = 0;\n     relres = 0;\n     resvec = 0;\n     iter_min = 0;\n     eigest = [NaN, NaN];\n     return;\n  endif\n\n  x = x_pr = x_min = x0;\n\n  ## x_pr (x previous) needs to check the stagnation\n  ## x_min needs to save the iterated with minimum residual\n\n  r = b - feval (Afcn, x, varargin{:});\n  iter = 2;\n  iter_min = 0;\n  flag = 1;\n  resvec = zeros (maxit + 1, 2);\n  resvec(1, 1) = norm (r);\n  p = zeros (size (b));\n  alpha = old_tau = 1;\n\n  if (n_arg_out > 5)\n    T = zeros (maxit, maxit);\n  else\n    T = [];\n  endif\n\n  while (resvec(iter-1,1) > tol * b_norm && iter < maxit)\n    if (iter == 2) # Check whether M1 or M2 are singular\n      try\n        warning (\"error\",\"Octave:singular-matrix\",\"local\");\n        z = feval (M1fcn, r, varargin{:});\n        z = feval (M2fcn, z, varargin{:});\n      catch\n        flag = 2;\n        break;\n      end_try_catch\n    else\n      z = feval (M1fcn, r, varargin{:});\n      z = feval (M2fcn, z, varargin{:});\n    endif\n\n    tau = z' * r;\n    resvec(iter - 1, 2) = sqrt (tau);\n    beta = tau / old_tau;\n    old_tau = tau;\n    p = z + beta * p;\n    w = feval (Afcn, p, varargin{:});\n\n    ## Needed only for eigest.\n\n    old_alpha = alpha;\n    den = p' * w;\n    alpha = tau / den;\n\n    ## Check if alpha is negative and/or if it has a consistent\n    ## imaginary part: if yes then A probably is not positive definite\n    if ((abs (imag (tau)) >= abs (real (tau)) * tol) || ...\n        real (tau) <= 0 || ...\n        (abs (imag (den)) >= abs (real (den)) * tol) || ...\n        (real (den) <= 0))\n      flag = 4;\n      break;\n    endif\n\n    x += alpha * p;\n    r -= alpha * w;\n    resvec(iter, 1) = norm (r);\n    ## Check if the iterated has minimum residual\n    if (resvec (iter,1) <= resvec (iter_min + 1,1))\n      x_min = x;\n      iter_min = iter - 1;\n    endif\n    if (n_arg_out > 5 && iter > 2)\n      T(iter-1:iter, iter-1:iter) = T(iter-1:iter, iter-1:iter) + ...\n                                    [1, sqrt(beta); sqrt(beta), beta] ./ ...\n                                    old_alpha;\n    endif\n    iter += 1;\n    if (norm (x - x_pr) <= eps * norm (x)) # Check the stagnation\n      flag = 3;\n      break;\n    endif\n    x_pr = x;\n  endwhile\n\n  if (n_arg_out > 5)\n  ## Apply the preconditioner once more and finish with the precond\n  ## residual.\n    z = feval (M1fcn, r, varargin{:});\n    z = feval (M2fcn, z, varargin{:});\n  endif\n\n  ## (Eventually) computes the eigenvalue of inv(m2)*inv(m1)*A\n  if (n_arg_out > 5)\n    if (flag != 4)\n      if (iter > 3)\n        T = T(2:iter-2,2:iter-2);\n        l = eig (T);\n        eigest = [min(l), max(l)];\n      else\n        eigest = [NaN, NaN];\n        warning (\"pcg: eigenvalue estimate failed: iteration converged too fast\");\n      endif\n    else\n      eigest = [NaN, NaN];\n      warning ('pcg: eigenvalue estimate failed: matrix not positive definite?');\n    endif\n    resvec(iter - 1, 2) = sqrt (r' * z);\n    resvec  = resvec (1:(iter-1), :);\n  else\n    eigest = [NaN, NaN];\n    resvec = resvec(1:(iter-1),1);\n  endif\n\n  ## Set the last variables\n\n  if (flag == 2)\n    relres = 1;\n  elseif (resvec (1, 1) == 0)\n    relres = 0;\n  else\n    relres = resvec(iter_min+1, 1) ./ b_norm;\n  endif\n\n  iter -= 2; # compatibility\n\n  ## Set the flag in the proper way if flag not 3, 4 or 2\n  if (flag == 2)\n    flag = 2;\n  elseif (flag == 1) && (relres <= tol)\n    flag = 0;\n  endif\n\n  if (n_arg_out < 2)\n    switch (flag)\n      case {0}\n        printf (\"pcg converged at iteration %d \", iter_min);\n        printf (\"with relative residual %d\\n\", relres);\n      case {1}\n        printf (\"pcg stopped at iteration %d \", iter+1);\n        printf (\"without converging to the desired tolerance %d \", tol);\n        printf (\"because the maximum number of iteration was reached,\\n\");\n        printf (\"The iterated returned (number %d) \",iter_min);\n        printf (\"has relative residual %d\\n\", relres);\n      case {2}\n        printf (\"pcg stopped at iteration %d \", iter+1)\n        printf (\"without converging to the desired tolerance %d \", tol);\n        printf (\"because the preconditioned matrix is singular.\\n\");\n        printf (\"The iterated returned (number %d) \", iter_min);\n        printf (\"has relative residual %d\\n\", relres);\n      case {3}\n        printf (\"pcg stopped at iteration %d \", iter+1);\n        printf (\"without converging to the desired tolerance %d \", tol);\n        printf (\"because of stagnation.\\n\");\n        printf (\"The iterated returned (number %d) \", iter_min);\n        printf (\"has relative residual %d.\\n\", relres);\n      case {4}\n        printf (\"pcg stopped at iteration %d \", iter + 1);\n        printf (\"without converging to the desired tolerance %d \",tol);\n        printf (\"because the (preconditioned) matrix is not positive definite.\\n\");\n        printf (\"The iterate returned (number %d) \", iter_min);\n        printf (\"has relative residual %d\\n\", relres);\n    endswitch\n  endif\n\nendfunction\n\n\n%!demo # simplest use\n%! n = 10;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, n));\n%! b = A * ones (n, 1);\n%! M1 = ichol (A);  # for this tridiagonal case it corresponds to chol (A)'\n%! M2 = M1';\n%! M = M1 * M2;\n%! x = pcg (A, b);\n%! Afcn = @(x) A * x;\n%! x = pcg (Afcn, b);\n%! x = pcg (A, b, 1e-6, 100, M);\n%! x = pcg (A, b, 1e-6, 100, M1, M2);\n%! Mfcn = @(x) M \\ x;\n%! x = pcg (Afcn, b, 1e-6, 100, Mfcn);\n%! M1fcn = @(x) M1 \\ x;\n%! M2fcn = @(x) M2 \\ x;\n%! x = pcg (Afcn, b, 1e-6, 100, M1fcn, M2fcn);\n%! function y = Ap (A, x, p)  # compute A^p * x\n%!    y = x;\n%!    for i = 1:p\n%!      y = A * y;\n%!    endfor\n%!  endfunction\n%! Afcn = @(x, p) Ap (A, x, p);\n%! ## solution of A^2 * x = b\n%! x = pcg (Afcn, b, [], [], [], [], [], 2);\n\n%!demo\n%! n = 10;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, n));\n%! b = A * ones (n, 1);\n%! M1 = ichol (A + 0.1 * eye (n));  # Perturb the factorization of A\n%! M2 = M1';\n%! M = M1 * M2;\n%!\n%! ## Reference solution computed by pcg after two iterations\n%! [x_ref, fl] = pcg (A, b, [], 2, M);\n%! x_ref\n%!\n%! ## Split preconditioning\n%! [y, fl] = pcg ((M1 \\ A) / M2, M1 \\ b, [], 2);\n%! x = M2 \\ y  # compare x and x_ref\n%!test\n%! ## Check that all type of inputs work\n%! A = toeplitz (sparse ([2, 1 ,0, 0, 0]));\n%! b = A * ones (5, 1);\n%! M1 = diag (sqrt (diag (A)));\n%! M2 = M1;  # M1 * M2 is the Jacobi preconditioner\n%! Afcn = @(z) A*z;\n%! M1_fcn = @(z) M1 \\ z;\n%! M2_fcn = @(z) M2 \\ z;\n%! [x, flag, ~, iter] = pcg (A,b);\n%! assert (flag, 0);\n%! [x, flag, ~ , iter] = pcg (A, b, [], [], M1 * M2);\n%! assert (flag, 0);\n%! [x, flag, ~ , iter] = pcg (A, b, [], [], M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = pcg (A, b, [], [], M1_fcn, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = pcg (A, b,[],[], M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = pcg (A, b,[],[], M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = pcg (Afcn, b);\n%! assert (flag, 0);\n%! [x, flag] = pcg (Afcn, b,[],[], M1 * M2);\n%! assert (flag, 0);\n%! [x, flag] = pcg (Afcn, b,[],[], M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = pcg (Afcn, b,[],[], M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = pcg (Afcn, b,[],[], M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = pcg (Afcn, b,[],[], M1_fcn, M2_fcn);\n%! assert (flag, 0);\n\n%!test\n%! ## solve a small diagonal system\n%! N = 10;\n%! A = diag ([1:N]);  b = rand (N, 1);\n%! [x, flag] = pcg (A, b, [], N+1);\n%! assert (flag, 0);\n%! assert (norm (b - A*x) / norm (b), 0, 1e-6);\n\n%!test\n%! ## A is not positive definite\n%! ## The indefiniteness of A is detected.\n%! N = 10;\n%! A = -diag ([1:N]);  b = sum (A, 2);\n%! [x, flag] = pcg (A, b, [], N + 1);\n%! assert (flag, 4);\n\n%!test\n%! ## solve tridiagonal system, do not converge in default 20 iterations\n%! N = 100;\n%! ## Form 1-D Laplacian matrix\n%! A = 2 * eye (N,N);\n%! A(2:(N+1):end) = -1;\n%! A((N+1):(N+1):end) = -1;\n%! b = ones (N, 1);\n%! [x, flag, relres, iter, resvec, eigest] = pcg (A, b, 1e-12);\n%! assert (flag);\n%! assert (relres >= 1.0);\n\n%!warning <iteration converged too fast>\n%! ## solve tridiagonal system with \"perfect\" preconditioner which converges\n%! ## in one iteration, so the eigest does not work and issues a warning.\n%! N = 100;\n%! ## Form 1-D Laplacian matrix\n%! A = 2 * eye (N,N);\n%! A(2:(N+1):end) = -1;\n%! A((N+1):(N+1):end) = -1;\n%! b = ones (N, 1);\n%! [x, flag, relres, iter, resvec, eigest] = pcg (A, b, [], [], A, [], b);\n%! assert (flag, 0);\n%! assert (norm (b - A*x) / norm (b), 0, 1e-6);\n%!\n%! assert (isnan (eigest), isnan ([NaN, NaN]));\n\n%!test\n%! ## pcg detect a non-Hermitian matrix, with a considerable imaginary part.\n%! ## In this example, Matlab does not recognize the wrong type of matrix and\n%! ## makes iterations until it reaches maxit.\n%! N = 10;\n%! A = diag (1:N) + 1e-4*i;\n%! b = ones (N, 1);\n%! [x, flag] = pcg (A, b, []);\n%! assert (flag, 4);\n\n%!test\n%! ## The imaginary part is not influent (it is too small), so pcg doesn't stop\n%! N = 10;\n%! A = diag (1:N) + 1e-10*i;\n%! b = ones (N, 1);\n%! [x, flag] = pcg (A, b, [], N+1);\n%! assert (flag, 0);\n%! assert (norm (b - A*x) / norm (b), 0, 1e-6);\n\n%!test\n%! ## pcg solves linear system with A Hermitian positive definite\n%! N = 20;\n%! A = sparse (toeplitz ([4, 1, zeros(1, 18)])) + ...\n%!     i * sparse (toeplitz ([0, 1, zeros(1, 18)], [0, -1, zeros(1,18)]));\n%! b = A * ones (N, 1);\n%! Hermitian_A = ishermitian (A);\n%! [x, flag] = pcg (A, b, [], 2*N);\n%! assert (Hermitian_A, true);\n%! assert (flag, 0);\n%! assert (x, ones (N, 1), -1e-4);\n\n%!testif HAVE_CHOLMOD\n%! ## pcg solves preconditioned linear system with A HPD\n%! N = 20;\n%! A = sparse (toeplitz ([4, 1, zeros(1, 18)])) + ...\n%!     i * sparse (toeplitz ([0, 1, zeros(1, 18)], [0, -1, zeros(1,18)]));\n%! b = A * ones (N, 1);\n%! M2 = chol (A + 0.1 * eye (N));  # Factor of a perturbed matrix\n%! M = M2' * M2;\n%! Hermitian_A = ishermitian (A, eps);  # AVX optimization can cause matrix\n%! Hermitian_M = ishermitian (M, eps);  # to miss being Hermitian by eps.\n%! [x, flag] = pcg (A, b, [], 2*N, M);\n%! assert (Hermitian_A, true);\n%! assert (Hermitian_M, true);\n%! assert (flag, 0);\n%! assert (x, ones (N, 1), -1e-4);\n\n%!test\n%! ## pcg recognizes that the preconditioner matrix is singular\n%! N = 3;\n%! A = toeplitz ([2, 1, 0]);\n%! M = [1 0 0; 0 1 0; 0 0 0];  # the last row is zero\n%! [x, flag] = pcg (A, ones (3, 1), [], [], M);\n%! assert (flag, 2);\n\n%!test\n%! A = rand (4);\n%! A = A' * A;\n%! [x, flag] = pcg (A, zeros (4, 1), [], [], [], [], ones (4, 1));\n%! assert (x, zeros (4, 1));\n\n## Test return types\n%!test\n%! A = single (1);\n%! b = 1;\n%! [x, flag] = pcg (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = 1;\n%! b = single (1);\n%! [x, flag] = pcg (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = single (1);\n%! b = single (1);\n%! [x, flag] = pcg (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%!function y = Afcn (x)\n%!   A = toeplitz ([2, 1, 0, 0]);\n%!   y = A * x;\n%!endfunction\n%! [x, flag] = pcg (\"Afcn\", [3; 4; 4; 3]);\n%! assert (x, ones (4, 1), 1e-6);\n\n%!test\n%! ## unpreconditioned residual\n%! A = toeplitz (sparse ([4, 1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M = toeplitz (sparse ([2, 1, 0, 0, 0]));\n%! [x, flag, relres] = pcg (A, b, [], 2, M);\n%! assert (norm (b - A * x) / norm (b), relres, 8 * eps);\n\n%!test <*59776>\n%! A = [ 1.00000000  -0.00054274  -0.00066848;\n%!      -0.00054274   1.00000000  -0.00060330;\n%!      -0.00066848  -0.00060330   1.00000000];\n%! b = [1 1 1]';\n%! [x, flag, relres, iter, resvec] = pcg (A, b, 1e-6, 4, [], [], [1; 1; 1]);\n%! assert (flag, 0);\n%! assert (relres, resvec(2) / norm (b));\n%! assert (iter, 1);\n"
  },
  {
    "path": "scripts/sparse/pcr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} pcr (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{m}, @var{x0}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} pcr (@dots{})\n##\n## Solve the linear system of equations @code{@var{A} * @var{x} = @var{b}} by\n## means of the Preconditioned Conjugate Residuals iterative method.\n##\n## The input arguments are\n##\n## @itemize\n## @item\n## @var{A} can be either a square (preferably sparse) matrix or a function\n## handle, inline function or string containing the name of a function which\n## computes @code{@var{A} * @var{x}}.  In principle @var{A} should be\n## symmetric and non-singular; if @code{pcr} finds @var{A} to be numerically\n## singular, you will get a warning message and the @var{flag} output\n## parameter will be set.\n##\n## @item\n## @var{b} is the right hand side vector.\n##\n## @item\n## @var{tol} is the required relative tolerance for the residual error,\n## @code{@var{b} - @var{A} * @var{x}}.  The iteration stops if\n## @code{norm (@var{b} - @var{A} * @var{x}) <=\n##       @var{tol} * norm (@var{b} - @var{A} * @var{x0})}.\n## If @var{tol} is empty or is omitted, the function sets\n## @code{@var{tol} = 1e-6} by default.\n##\n## @item\n## @var{maxit} is the maximum allowable number of iterations; if @code{[]} is\n## supplied for @var{maxit}, or @code{pcr} has less arguments, a default\n## value equal to 20 is used.\n##\n## @item\n## @var{m} is the (left) preconditioning matrix, so that the iteration is\n## (theoretically) equivalent to solving by\n## @code{pcr} @code{@var{P} * @var{x} = @var{m} \\ @var{b}}, with\n## @code{@var{P} = @var{m} \\ @var{A}}.  Note that a proper choice of the\n## preconditioner may dramatically improve the overall performance of the\n## method.  Instead of matrix @var{m}, the user may pass a function which\n## returns the results of applying the inverse of @var{m} to a vector\n## (usually this is the preferred way of using the preconditioner).  If\n## @code{[]} is supplied for @var{m}, or @var{m} is omitted, no\n## preconditioning is applied.\n##\n## @item\n## @var{x0} is the initial guess.  If @var{x0} is empty or omitted, the\n## function sets @var{x0} to a zero vector by default.\n## @end itemize\n##\n## The arguments which follow @var{x0} are treated as parameters, and passed\n## in a proper way to any of the functions (@var{A} or @var{m}) which are\n## passed to @code{pcr}.  See the examples below for further details.\n##\n## The output arguments are\n##\n## @itemize\n## @item\n## @var{x} is the computed approximation to the solution of\n## @code{@var{A} * @var{x} = @var{b}}.\n##\n## @item\n## @var{flag} reports on the convergence.  @code{@var{flag} = 0} means the\n## solution converged and the tolerance criterion given by @var{tol} is\n## satisfied.  @code{@var{flag} = 1} means that the @var{maxit} limit for the\n## iteration count was reached.  @code{@var{flag} = 3} reports a @code{pcr}\n## breakdown, see [1] for details.\n##\n## @item\n## @var{relres} is the ratio of the final residual to its initial value,\n## measured in the Euclidean norm.\n##\n## @item\n## @var{iter} is the actual number of iterations performed.\n##\n## @item\n## @var{resvec} describes the convergence history of the method, so that\n## @code{@var{resvec} (i)} contains the Euclidean norms of the residual after\n## the (@var{i}-1)-th iteration, @code{@var{i} = 1,2, @dots{}, @var{iter}+1}.\n## @end itemize\n##\n## Let us consider a trivial problem with a diagonal matrix (we exploit the\n## sparsity of A)\n##\n## @example\n## @group\n## n = 10;\n## A = sparse (diag (1:n));\n## b = rand (N, 1);\n## @end group\n## @end example\n##\n## @sc{Example 1:} Simplest use of @code{pcr}\n##\n## @example\n## x = pcr (A, b)\n## @end example\n##\n## @sc{Example 2:} @code{pcr} with a function which computes\n## @code{@var{A} * @var{x}}.\n##\n## @example\n## @group\n## function y = apply_a (x)\n##   y = [1:10]' .* x;\n## endfunction\n##\n## x = pcr (\"apply_a\", b)\n## @end group\n## @end example\n##\n## @sc{Example 3:}  Preconditioned iteration, with full diagnostics.  The\n## preconditioner (quite strange, because even the original matrix\n## @var{A} is trivial) is defined as a function\n##\n## @example\n## @group\n## function y = apply_m (x)\n##   k = floor (length (x) - 2);\n##   y = x;\n##   y(1:k) = x(1:k) ./ [1:k]';\n## endfunction\n##\n## [x, flag, relres, iter, resvec] = ...\n##                    pcr (A, b, [], [], \"apply_m\")\n## semilogy ([1:iter+1], resvec);\n## @end group\n## @end example\n##\n## @sc{Example 4:} Finally, a preconditioner which depends on a\n## parameter @var{k}.\n##\n## @example\n## @group\n## function y = apply_m (x, varargin)\n##   k = varargin@{1@};\n##   y = x;\n##   y(1:k) = x(1:k) ./ [1:k]';\n## endfunction\n##\n## [x, flag, relres, iter, resvec] = ...\n##                    pcr (A, b, [], [], \"apply_m\"', [], 3)\n## @end group\n## @end example\n##\n## Reference:\n##\n## @nospell{W. Hackbusch}, @cite{Iterative Solution of Large Sparse Systems of\n## Equations}, section 9.5.4, @nospell{Springer}, 1994.\n##\n## @seealso{sparse, pcg}\n## @end deftypefn\n\nfunction [x, flag, relres, iter, resvec] = pcr (A, b, tol, maxit, m, x0, varargin)\n\n  breakdown = false;\n\n  if (nargin < 6 || isempty (x0))\n    x = zeros (size (b));\n  else\n    x = x0;\n  endif\n\n  if (nargin < 5)\n    m = [];\n  endif\n\n  if (nargin < 4 || isempty (maxit))\n    maxit = 20;\n  endif\n\n  maxit += 2;\n\n  if (nargin < 3 || isempty (tol))\n    tol = 1e-6;\n  endif\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  ##  init\n  if (isnumeric (A))            # is A a matrix?\n    r = b - A*x;\n  else                          # then A should be a function!\n    r = b - feval (A, x, varargin{:});\n  endif\n\n  if (isnumeric (m))            # is M a matrix?\n    if (isempty (m))            # if M is empty, use no precond\n      p = r;\n    else                        # otherwise, apply the precond\n      p = m \\ r;\n    endif\n  else                          # then M should be a function!\n    p = feval (m, r, varargin{:});\n  endif\n\n  iter = 2;\n\n  b_bot_old = 1;\n  q_old = p_old = s_old = zeros (size (x));\n\n  if (isnumeric (A))            # is A a matrix?\n    q = A * p;\n  else                          # then A should be a function!\n    q = feval (A, p, varargin{:});\n  endif\n\n  resvec(1) = abs (norm (r));\n\n  ## iteration\n  while (resvec(iter-1) > tol*resvec(1) && iter < maxit)\n\n    if (isnumeric (m))          # is M a matrix?\n      if (isempty (m))          # if M is empty, use no precond\n        s = q;\n      else                      # otherwise, apply the precond\n        s = m \\ q;\n      endif\n    else                        # then M should be a function!\n      s = feval (m, q, varargin{:});\n    endif\n    b_top = r' * s;\n    b_bot = q' * s;\n\n    if (b_bot == 0.0)\n      breakdown = true;\n      break;\n    endif\n    lambda = b_top / b_bot;\n\n    x += lambda*p;\n    r -= lambda*q;\n\n    if (isnumeric (A))          # is A a matrix?\n      t = A*s;\n    else                        # then A should be a function!\n      t = feval (A, s, varargin{:});\n    endif\n\n    alpha0 = (t'*s) / b_bot;\n    alpha1 = (t'*s_old) / b_bot_old;\n\n    p_temp = p;\n    q_temp = q;\n\n    p = s - alpha0*p - alpha1*p_old;\n    q = t - alpha0*q - alpha1*q_old;\n\n    s_old = s;\n    p_old = p_temp;\n    q_old = q_temp;\n    b_bot_old = b_bot;\n\n    resvec(iter) = abs (norm (r));\n    iter += 1;\n  endwhile\n\n  flag = 0;\n  relres = resvec(iter-1) ./ resvec(1);\n  iter -= 2;\n  if (iter >= maxit-2)\n    flag = 1;\n    if (nargout < 2)\n      warning (\"pcr: maximum number of iterations (%d) reached\\n\", iter);\n      warning (\"pcr: the initial residual norm was reduced %g times\\n\",\n               1.0/relres);\n    endif\n  elseif (nargout < 2 && ! breakdown)\n    fprintf (stderr, \"pcr: converged in %d iterations.\\n\", iter);\n    fprintf (stderr, \"pcr: the initial residual norm was reduced %g times\\n\",\n             1.0 / relres);\n  endif\n\n  if (breakdown)\n    flag = 3;\n    if (nargout < 2)\n      warning (\"pcr: breakdown occurred:\\n\");\n      warning (\"system matrix singular or preconditioner indefinite?\\n\");\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Simplest usage of PCR (see also 'help pcr')\n%!\n%! N = 20;\n%! A = diag (linspace (-3.1,3,N)); b = rand (N,1);\n%! y = A \\ b;  # y is the true solution\n%! x = pcr (A,b);\n%! printf (\"The solution relative error is %g\\n\", norm (x-y) / norm (y));\n%!\n%! ## You shouldn't be afraid if PCR issues some warning messages in this\n%! ## example: watch out in the second example, why it takes N iterations\n%! ## of PCR to converge to (a very accurate, by the way) solution.\n\n%!demo\n%! ## Full output from PCR\n%! ## We use this output to plot the convergence history\n%!\n%! N = 20;\n%! A = diag (linspace (-3.1,30,N)); b = rand (N,1);\n%! X = A \\ b;  # X is the true solution\n%! [x, flag, relres, iter, resvec] = pcr (A,b);\n%! printf (\"The solution relative error is %g\\n\", norm (x-X) / norm (X));\n%! clf;\n%! title (\"Convergence history\");\n%! xlabel (\"Iteration\"); ylabel (\"log (||b-Ax||/||b||)\");\n%! semilogy ([0:iter], resvec/resvec(1), \"o-g;relative residual;\");\n\n%!demo\n%! ## Full output from PCR\n%! ## We use indefinite matrix based on the Hilbert matrix, with one\n%! ## strongly negative eigenvalue\n%! ## Hilbert matrix is extremely ill conditioned, so is ours,\n%! ## and that's why PCR WILL have problems\n%!\n%! N = 10;\n%! A = hilb (N); A(1,1) = -A(1,1); b = rand (N,1);\n%! X = A \\ b;  # X is the true solution\n%! printf (\"Condition number of A is   %g\\n\", cond (A));\n%! [x, flag, relres, iter, resvec] = pcr (A,b,[],200);\n%! if (flag == 3)\n%!   printf (\"PCR breakdown.  System matrix is [close to] singular\\n\");\n%! endif\n%! clf;\n%! title (\"Convergence history\");\n%! xlabel (\"Iteration\"); ylabel (\"log (||b-Ax||)\");\n%! semilogy ([0:iter], resvec, \"o-g;absolute residual;\");\n\n%!demo\n%! ## Full output from PCR\n%! ## We use an indefinite matrix based on the 1-D Laplacian matrix for A,\n%! ## and here we have cond (A) = O(N^2)\n%! ## That's the reason we need some preconditioner; here we take\n%! ## a very simple and not powerful Jacobi preconditioner,\n%! ## which is the diagonal of A.\n%!\n%! ## Note that we use here indefinite preconditioners!\n%!\n%! N = 100;\n%! ## Form 1-D Laplacian matrix\n%! A = 2 * eye (N,N);\n%! A(2:(N+1):end) = -1;\n%! A((N+1):(N+1):end) = -1;\n%!\n%! A = [A, zeros(size(A)); zeros(size(A)), -A];\n%! b = rand (2*N,1);\n%! X = A \\ b;  # X is the true solution\n%! maxit = 80;\n%! printf (\"System condition number is %g\\n\", cond (A));\n%! ## No preconditioner: the convergence is very slow!\n%!\n%! [x, flag, relres, iter, resvec] = pcr (A,b,[],maxit);\n%! clf;\n%! title (\"Convergence history\");\n%! xlabel (\"Iteration\"); ylabel (\"log (||b-Ax||)\");\n%! semilogy ([0:iter], resvec, \"o-g;NO preconditioning: absolute residual;\");\n%!\n%! pause (1);\n%! ## Test Jacobi preconditioner: it will not help much!!!\n%!\n%! M = diag (diag (A)); # Jacobi preconditioner\n%! [x, flag, relres, iter, resvec] = pcr (A,b,[],maxit,M);\n%! hold on;\n%! semilogy ([0:iter],resvec,\"o-r;JACOBI preconditioner: absolute residual;\");\n%!\n%! pause (1);\n%! ## Test nonoverlapping block Jacobi preconditioner: this one should give\n%! ## some convergence speedup!\n%!\n%! M = zeros (N,N); k = 4;\n%! for i=1:k:N # get k x k diagonal blocks of A\n%!   M(i:i+k-1,i:i+k-1) = A(i:i+k-1,i:i+k-1);\n%! endfor\n%! M = [M, zeros(size (M)); zeros(size(M)), -M];\n%! [x, flag, relres, iter, resvec] = pcr (A,b,[],maxit,M);\n%! semilogy ([0:iter], resvec, \"o-b;BLOCK JACOBI preconditioner: absolute residual;\");\n%! hold off;\n\n%!test\n%! ## solve small indefinite diagonal system\n%!\n%! N = 10;\n%! A = diag (linspace (-10.1,10,N)); b = ones (N,1);\n%! X = A \\ b;  # X is the true solution\n%! [x, flag] = pcr (A,b,[],N+1);\n%! assert (norm (x-X) / norm (X) < 1e-10);\n%! assert (flag, 0);\n\n%!test\n%! ## solve tridiagonal system, do not converge in default 20 iterations\n%! ## should perform max allowable default number of iterations\n%!\n%! N = 100;\n%! ## Form 1-D Laplacian matrix\n%! A = 2 * eye (N,N);\n%! A(2:(N+1):end) = -1;\n%! A((N+1):(N+1):end) = -1;\n%! b = ones (N,1);\n%! X = A \\ b;  # X is the true solution\n%! [x, flag, relres, iter, resvec] = pcr (A,b,1e-12);\n%! assert (flag, 1);\n%! assert (relres > 0.6);\n%! assert (iter, 20);\n\n%!test\n%! ## solve tridiagonal system with \"perfect\" preconditioner\n%! ## converges in one iteration\n%!\n%! N = 100;\n%! ## Form 1-D Laplacian matrix\n%! A = 2 * eye (N,N);\n%! A(2:(N+1):end) = -1;\n%! A((N+1):(N+1):end) = -1;\n%! b = ones (N,1);\n%! X = A \\ b;  # X is the true solution\n%! [x, flag, relres, iter] = pcr (A,b,[],[],A,b);\n%! assert (norm (x-X) / norm (X) < 1e-6);\n%! assert (relres < 1e-6);\n%! assert (flag, 0);\n%! assert (iter, 1); # should converge in one iteration\n"
  },
  {
    "path": "scripts/sparse/private/__alltohandles__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {[@var{Afcn}, @var{M1fcn}, @var{M2fcn}] =} __alltohandles__ (@var{A}, @var{b}, @var{M1}, @var{M2}, @var{solver_name})\n##\n## Check if the parameters @var{A} (matrix of our linear system), @var{b}\n## (right hand side vector), @var{M1}, @var{M2} (preconditioner matrices) are\n## really matrices or functions handle, summarizing if they are void or not.\n##\n## The input parameters are:\n##\n## @itemize\n## @item @var{A} is the matrix of the linear system.\n##\n## @item @var{b} is the right hand side vector.\n##\n## @item @var{M1}, @var{M2} preconditioners.  They can be [].\n##\n## @item @var{solver_name} is the name of the solver as string.\n##\n## @end itemize\n##\n## The output parameters are:\n##\n## @itemize\n##\n## @item @var{Afcn}, @var{M1fcn}, @var{M2fcn} are the corresponding\n## function handles.\n##\n## @end itemize\n## @end deftypefn\n\nfunction [Afcn, M1fcn, M2fcn] = __alltohandles__ (A, b, M1, M2, solver_name)\n\n  A_is_numeric = false;\n  M1_is_numeric = false;\n  M2_is_numeric = false;\n\n  ## Check A and set its type\n  if (is_function_handle (A))\n     Afcn = A;\n  elseif (ischar (A))\n    Afcn = str2func (A);\n  elseif (! isnumeric (A) || ! issquare (A))\n    error ([solver_name, \": A must be a square matrix or a function handle\"]);\n  else\n    A_is_numeric = true;\n    if (columns (A) != rows (b))\n      error (\"__alltohandles__: dimension of B is not consistent with A\");\n    endif\n  endif\n\n  ## Check M1 and sets its type\n  if (isempty (M1)) # M1 empty, set to identity function\n    switch (solver_name)\n      case {\"pcg\", \"gmres\", \"bicgstab\", \"cgs\", \"tfqmr\"}\n        ## methods which do not require the transpose\n        M1fcn = @(x) x;\n      case {\"bicg\"}\n        ## methods allow a variable number of arguments\n        M1fcn = @(x, varargin) x;\n      otherwise\n        error ([\"__alltohandles__: unknown method: \", solver_name]);\n    endswitch\n  else # M1 not empty\n    if (is_function_handle (M1))\n      M1fcn = M1;\n    elseif (ischar (M1))\n      M1fcn = str2func (M1);\n    elseif (! isnumeric (M1) || ! issquare (M1))\n      error ([solver_name, \": M1 must be a square matrix or a function handle\"]);\n    else\n      M1_is_numeric = true;\n    endif\n  endif\n\n  if (isempty (M2)) # M2 empty, then I set is to the identity function\n    switch (solver_name)\n      case {\"pcg\", \"gmres\", \"bicgstab\", \"cgs\", \"tfqmr\"}\n        ## methods which do not require the transpose\n        M2fcn = @(x) x;\n      case {\"bicg\"}\n        ## methods allow a variable number of arguments\n        M2fcn = @(x, varargin) x;\n      otherwise\n        error ([\"__alltohandles__: unknown method: \", solver_name]);\n    endswitch\n  else # M2 not empty\n    if (is_function_handle (M2))\n      M2fcn = M2;\n    elseif (ischar (M2))\n      M2fcn = str2func (M2);\n    elseif (! isnumeric (M2) || ! issquare (M2))\n      error ([solver_name, \": M2 must be a square matrix or a function handle\"]);\n    else\n      M2_is_numeric = true;\n    endif\n  endif\n\n  switch (solver_name)\n    case {\"pcg\", \"gmres\", \"bicgstab\", \"cgs\", \"tfqmr\"}\n      ## methods which do not require the transpose\n      if (A_is_numeric)\n        Afcn = @(x) A * x;\n      endif\n      if (M1_is_numeric)\n        M1fcn = @(x) M1 \\ x;\n      endif\n      if (M2_is_numeric)\n        M2fcn = @(x) M2 \\ x;\n      endif\n    case {\"bicg\"}\n      ## methods which require the transpose and allow a variable number of\n      ## arguments\n      if (A_is_numeric)\n        Afcn = @(x, trans, varargin) A_sub (A, x, trans);\n      endif\n      if (M1_is_numeric)\n        M1fcn = @(x, trans, varargin) M_sub (M1, x, trans);\n      endif\n      if (M2_is_numeric)\n        M2fcn = @(x, trans, varargin) M_sub (M2, x, trans);\n      endif\n    otherwise\n      error ([\"__alltohandles__: unknown method: \", solver_name]);\n  endswitch\n\nendfunction\n\nfunction y = A_sub (A, x, trans)\n  if (strcmp (trans, \"transp\"))\n    y = A' * x;\n  else\n    y = A * x;\n  endif\nendfunction\n\nfunction y = M_sub (M, x, trans)\n  if (strcmp (trans, \"transp\"))\n    y = M' \\ x;\n  else\n    y = M \\ x;\n  endif\nendfunction\n"
  },
  {
    "path": "scripts/sparse/private/__default__input__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{varargout} =} __default__input__ (@var{def_val}, @var{varargin})\n## Check if the input arguments of a function are empty or missing.\n## If they are, use default values.\n##\n## The input arguments are:\n##\n## @itemize @minus\n## @item @var{def_val} is a cell array that contains the values to use\n## as default.\n##\n## @item @var{varargin} are the input arguments.\n## @end itemize\n##\n## The output arguments are:\n##\n## @itemize @minus\n## @item @var{varargout} are the input arguments where any empty or omitted\n## parameters have been replaced with default values.\n##\n## @end itemize\n##\n## @end deftypefn\n\nfunction varargout = __default__input__ (def_val, varargin)\n\n  m = numel (def_val);\n  n = numel (varargin);\n  count = min (m, n);\n\n  ## Check for missing values in input and replace with default value.\n  for i = 1:count\n    if (isempty (varargin{i}))\n      varargout{i} = def_val{i};\n    else\n      varargout{i} = varargin{i};\n    endif\n  endfor\n\n  ## Copy any remaining items to output\n  if (n < m)\n    varargout(n+1:m) = def_val(n+1:m);\n  elseif (m < n)\n    varargout(m+1:n) = varargin(m+1:n);\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/sparse/private/__sprand__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n##\n## Original version by Paul Kienzle distributed as free software in the\n## public domain.\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{S} =} __sprand__ (@var{s}, @var{randfcn})\n## @deftypefnx {} {@var{S} =} __sprand__ (@var{m}, @var{n}, @var{d}, @var{fcnname}, @var{randfcn})\n## @deftypefnx {} {@var{S} =} __sprand__ (@var{m}, @var{n}, @var{d}, @var{rc}, @var{fcnname}, @var{randfcn})\n## Undocumented internal function.\n## @end deftypefn\n\n## Actual implementation of sprand and sprandn happens here.\n\nfunction S = __sprand__ (varargin)\n\n  if (nargin == 2)\n    [m, randfcn] = deal (varargin{1:2});\n    [i, j] = find (m);\n    [nr, nc] = size (m);\n    S = sparse (i, j, randfcn (size (i)), nr, nc);\n  else\n    if (nargin == 5)\n      [m, n, d, fcnname, randfcn] = deal (varargin{:});\n    else\n      [m, n, d, rc, fcnname, randfcn] = deal (varargin{:});\n    endif\n\n    if (! (isscalar (m) && m == fix (m) && m >= 0))\n      error (\"%s: M must be a non-negative integer\", fcnname);\n    endif\n    if (! (isscalar (n) && n == fix (n) && n >= 0))\n      error (\"%s: N must be a non-negative integer\", fcnname);\n    endif\n    if (d < 0 || d > 1)\n      error (\"%s: density D must be between 0 and 1\", fcnname);\n    endif\n\n    if (m == 0 || n == 0)\n      S = sparse (m, n);\n      return;\n    endif\n\n    if (nargin == 5)\n      mn = m*n;\n      k = round (d*mn);\n      if (mn > sizemax ())\n        ## randperm will overflow, so use alternative methods\n\n        idx = unique (fix (rand (1.01*k, 1) * mn)) + 1;\n\n        ## idx contains random numbers in [1,mn]\n        ## Generate 1% more random values than necessary in order to reduce the\n        ## probability that there are less than k distinct values; maybe a\n        ## better strategy could be used but I don't think it's worth the price.\n\n        ## actual number of entries in S\n        k = min (length (idx), k);\n        j = floor ((idx(1:k) - 1) / m);\n        i = idx(1:k) - j * m;\n        j += 1;\n      else\n        idx = randperm (mn, k);\n        [i, j] = ind2sub ([m, n], idx);\n      endif\n\n      S = sparse (i, j, randfcn (k, 1), m, n);\n\n    elseif (nargin == 6)\n      ## Create a matrix with specified reciprocal condition number.\n\n      if (! isscalar (rc) && ! isvector (rc))\n        error (\"%s: RC must be a scalar or vector\", fcnname);\n      endif\n\n      ## We want to reverse singular valued decomposition A=U*S*V'.\n      ## First, first S is constructed and then U = U1*U2*..Un and\n      ## V' = V1*V2*..Vn are seen as Jacobi rotation matrices with angles and\n      ## planes of rotation randomized.  Repeatedly apply rotations until the\n      ## required density for A is achieved.\n\n      if (isscalar (rc))\n        if (rc < 0 || rc > 1)\n          error (\"%s: reciprocal condition number RC must be between 0 and 1\", fcnname);\n        endif\n        ## Reciprocal condition number is ratio of smallest SV to largest SV\n        ## Generate singular values randomly and sort them to build S\n        ## Random singular values in range [rc, 1].\n        v = rand (1, min (m,n)) * (1 - rc) + rc;\n        v(1) = 1;\n        v(end) = rc;\n        v = sort (v, \"descend\");\n        S = sparse (diag (v, m, n));\n      else\n        ## Only the min (m, n) greater singular values from rc vector are used.\n        if (length (rc) > min (m,n))\n          rc = rc(1:min (m, n));\n        endif\n        S = sparse (diag (sort (rc, \"descend\"), m, n));\n      endif\n\n      Uinit = speye (m);\n      Vinit = speye (n);\n      k = round (d*m*n);\n      while (nnz (S) < k)\n        if (m > 1)\n          ## Construct U randomized rotation matrix\n          rot_angleu = 2 * pi * rand ();\n          cu = cos (rot_angleu); su = sin (rot_angleu);\n          rndtmp = randperm (m, 2);\n          i = rndtmp(1); j = rndtmp(2);\n          U = Uinit;\n          U(i, i) = cu; U(i, j) = -su;\n          U(j, i) = su; U(j, j) = cu;\n          S = U * S;\n        endif\n        if (n > 1)\n          ## Construct V' randomized rotation matrix\n          rot_anglev = 2 * pi * rand ();\n          cv = cos (rot_anglev); sv = sin (rot_anglev);\n          rndtmp = randperm (n, 2);\n          i = rndtmp(1); j = rndtmp(2);\n          V = Vinit;\n          V(i, i) = cv;  V(i, j) = sv;\n          V(j, i) = -sv; V(j, j) = cv;\n          S *= V;\n        endif\n      endwhile\n    endif\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/sparse/qmr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} qmr (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})\n## @deftypefnx {} {@var{x} =} qmr (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{P})\n## @deftypefnx {} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} qmr (@var{A}, @var{b}, @dots{})\n## Solve @code{A x = b} using the Quasi-Minimal Residual iterative method\n## (without look-ahead).\n##\n## @itemize @minus\n## @item @var{rtol} is the relative tolerance, if not given or set to [] the\n## default value 1e-6 is used.\n##\n## @item @var{maxit} the maximum number of outer iterations, if not given or\n## set to [] the default value @code{min (20, numel (b))} is used.\n##\n## @item @var{x0} the initial guess, if not given or set to [] the default\n## value @code{zeros (size (b))} is used.\n## @end itemize\n##\n## @var{A} can be passed as a matrix or as a function handle or inline\n## function @code{f} such that @code{f(x, \"notransp\") = A*x} and\n## @code{f(x, \"transp\") = A'*x}.\n##\n## The preconditioner @var{P} is given as @code{P = M1 * M2}.  Both @var{M1}\n## and @var{M2} can be passed as a matrix or as a function handle or inline\n## function @code{g} such that @code{g(x, \"notransp\") = M1 \\ x} or\n## @code{g(x, \"notransp\") = M2 \\ x} and @code{g(x, \"transp\") = M1' \\ x} or\n## @code{g(x, \"transp\") = M2' \\ x}.\n##\n## If called with more than one output parameter\n##\n## @itemize @minus\n## @item @var{flag} indicates the exit status:\n##\n## @itemize @minus\n## @item 0: iteration converged to the within the chosen tolerance\n##\n## @item 1: the maximum number of iterations was reached before convergence\n##\n## @item 3: the algorithm reached stagnation\n## @end itemize\n##\n## (the value 2 is unused but skipped for compatibility).\n##\n## @item @var{relres} is the final value of the relative residual.\n##\n## @item @var{iter} is the number of iterations performed.\n##\n## @item @var{resvec} is a vector containing the residual norms at each\n##       iteration.\n## @end itemize\n##\n## References:\n##\n## @enumerate\n## @item\n## @nospell{R. Freund and N. Nachtigal}, \"QMR: a quasi-minimal residual method\n## for non-Hermitian linear systems\", @cite{@nospell{Numerische Mathematik}},\n## 60, @w{pp.@: 315}--339, 1991.\n##\n## @item\n## @nospell{R. Barrett, M. Berry, T. Chan, J. Demmel, J. Donato, J. Dongarra},\n## @nospell{V. Eijkhour, R. Pozo, C. Romine, and H. van der Vorst},\n## @cite{Templates for the solution of linear systems: Building blocks\n## for iterative methods}, SIAM, 2nd ed., 1994.\n## @end enumerate\n##\n## @seealso{bicg, bicgstab, cgs, gmres, pcg}\n## @end deftypefn\n\nfunction [x, flag, relres, iter, resvec] = qmr (A, b, rtol, maxit, M1, M2, x0)\n\n  if (nargin >= 2 && isvector (full (b)))\n\n    if (ischar (A))\n      fcn = str2func (A);\n      Ax  = @(x) feval (fcn, x, \"notransp\");\n      Atx = @(x) feval (fcn, x, \"transp\");\n    elseif (is_function_handle (A))\n      Ax  = @(x) feval (A, x, \"notransp\");\n      Atx = @(x) feval (A, x, \"transp\");\n    elseif (isnumeric (A) && issquare (A))\n      Ax  = @(x) A  * x;\n      Atx = @(x) A' * x;\n    else\n      error (\"qmr: A must be a square matrix or function\");\n    endif\n\n    if (nargin < 3 || isempty (rtol))\n      rtol = 1e-6;\n    endif\n\n    if (nargin < 4 || isempty (maxit))\n      maxit = min (rows (b), 20);\n    else\n      maxit = fix (maxit);\n    endif\n\n    if (nargin < 5 || isempty (M1))\n      M1m1x = @(x, ignore) x;\n      M1tm1x = M1m1x;\n    elseif (ischar (M1))\n      fcn = str2func (M1);\n      M1m1x  = @(x) feval (fcn, x, \"notransp\");\n      M1tm1x = @(x) feval (fcn, x, \"transp\");\n    elseif (is_function_handle (M1))\n      M1m1x  = @(x) feval (M1, x, \"notransp\");\n      M1tm1x = @(x) feval (M1, x, \"transp\");\n    elseif (isnumeric (M1) && ismatrix (M1))\n      M1m1x  = @(x) M1  \\ x;\n      M1tm1x = @(x) M1' \\ x;\n    else\n      error (\"qmr: preconditioner M1 must be a function or matrix\");\n    endif\n\n    if (nargin < 6 || isempty (M2))\n      M2m1x = @(x, ignore) x;\n      M2tm1x = M2m1x;\n    elseif (ischar (M2))\n      fcn = str2func (M2);\n      M2m1x  = @(x) feval (fcn, x, \"notransp\");\n      M2tm1x = @(x) feval (fcn, x, \"transp\");\n    elseif (is_function_handle (M2))\n      M2m1x  = @(x) feval (M2, x, \"notransp\");\n      M2tm1x = @(x) feval (M2, x, \"transp\");\n    elseif (isnumeric (M2) && ismatrix (M2))\n      M2m1x  = @(x) M2  \\ x;\n      M2tm1x = @(x) M2' \\ x;\n    else\n      error (\"qmr: preconditioner M2 must be a function or matrix\");\n    endif\n\n    if (nargin < 7 || isempty (x0))\n      x = zeros (size (b));\n    else\n      x = x0;\n    endif\n\n    r = b - Ax (x);\n\n    bnorm = norm (b);\n    res0 = norm (r);\n    if (nargout > 4)\n      resvec(1) = res0;\n    endif\n    vt = r;\n\n    y = M1m1x (vt);\n\n    rho0 = norm (y);\n    wt = r;\n\n    z = M2tm1x (wt);\n\n    xi1 = norm (z);\n    gamma0 = 1;\n    eta0 = -1;\n    flag = 1;\n    for iter=1:1:maxit\n      ## If rho0 == 0 or xi1 == 0, method fails.\n      v = vt / rho0;\n      y /= rho0;\n      w = wt / xi1;\n      z /= xi1;\n\n      delta1 = z' * y;   # If delta1 == 0, method fails.\n\n      yt = M2m1x (y);\n      zt = M1tm1x (z);\n\n      if (iter == 1)\n        p = yt;\n        q = zt;\n      else\n        p = yt - (xi1*delta1/eps0) * p;\n        q = zt - (rho0*delta1/eps0) * q;\n      endif\n      pt = Ax (p);\n\n      eps0 = q' * pt;          # If eps0 == 0, method fails.\n      beta1 = eps0 / delta1;   # If beta1 == 0, method fails.\n      vt = pt - beta1 * v;\n\n      y = M1m1x (vt);\n      rho1 = norm (y);\n      wt = Atx (q) - beta1 * w;\n      z = M2tm1x (wt);\n\n      xi1 = norm (z);\n      theta1 = rho1 / (gamma0 * abs (beta1));\n      gamma1 = 1 / sqrt (1 + theta1^2);   # If gamma1 == 0, method fails.\n      eta1 = -eta0 * rho0 * gamma1^2 / (beta1 * gamma0^2);\n\n      if (iter == 1)\n        d = eta1 * p;\n        s = eta1 * pt;\n      else\n        d = eta1 * p + (theta0*gamma1)^2 * d;\n        s = eta1 * pt + (theta0 * gamma1)^2 * s;\n      endif\n      x += d;\n      r -= s;\n\n      res1 = norm (r) / bnorm;\n      if (nargout > 4)\n        resvec(iter + 1, 1) = norm (r);\n      endif\n\n      if (res1 < rtol)\n        ## Convergence achieved.\n        flag = 0;\n        break;\n      elseif (res0 <= res1)\n        ## Stagnation encountered.\n        flag = 3;\n        break;\n      endif\n      theta0 = theta1;\n      eta0 = eta1;\n      gamma0 = gamma1;\n      rho0 = rho1;\n    endfor\n\n    relres = res1;\n    if (flag == 1)\n      if (nargout < 2)\n        printf (\"qmr stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", rtol);\n        printf (\"because the maximum number of iterations was reached.\\n\");\n        printf (\"The iterate returned (number %i) has \", maxit);\n        printf (\"relative residual %e\\n\", res1);\n      endif\n    elseif (flag == 3)\n      if (nargout < 2)\n        printf (\"qmr stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", rtol);\n        printf (\"because the method stagnated.\\n\");\n        printf (\"The iterate returned (number %i) \", iter);\n        printf (\"has relative residual %e\\n\", res1);\n      endif\n    elseif (nargout < 2)\n      printf (\"qmr converged at iteration %i \", iter);\n      printf (\"to a solution with relative residual %e\\n\", res1);\n    endif\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n%!demo\n%! % Solve system of A*x=b\n%! A = [5 -1 3;-1 2 -2;3 -2 3];\n%! b = [7;-1;4];\n%! [x, flag, relres, iter, resvec] = qmr (A, b)\n\n%!test\n%! n = 100;\n%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);\n%! b = sum (A, 2);\n%! rtol = 1e-8;\n%! maxit = 15;\n%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);\n%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);\n%! [x, flag, relres, iter, resvec] = qmr (A, b, rtol, maxit, M1, M2);\n%! assert (x, ones (size (b)), 1e-7);\n\n%!function y = afcn (x, t, a)\n%!  switch (t)\n%!    case \"notransp\"\n%!      y = a * x;\n%!    case \"transp\"\n%!      y = a' * x;\n%!  endswitch\n%!endfunction\n%!\n%!test\n%! n = 100;\n%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);\n%! b = sum (A, 2);\n%! rtol = 1e-8;\n%! maxit = 15;\n%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);\n%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);\n%!\n%! [x, flag, relres, iter, resvec] = qmr (@(x, t) afcn (x, t, A),\n%!                                         b, rtol, maxit, M1, M2);\n%! assert (x, ones (size (b)), 1e-7);\n\n%!test\n%! n = 100;\n%! rtol = 1e-8;\n%! a = sprand (n, n, .1);\n%! A = a' * a + 100 * eye (n);\n%! b = sum (A, 2);\n%! [x, flag, relres, iter, resvec] = qmr (A, b, rtol, [], diag (diag (A)));\n%! assert (x, ones (size (b)), 1e-7);\n\n%!test\n%! A = [1 + 1i, 1 + 1i; 2 - 1i, 2 + 1i];\n%! b = A * [1; 1];\n%! [x, flag, relres, iter, resvec] = qmr (A, b);\n%! assert (x, [1; 1], 1e-6);\n"
  },
  {
    "path": "scripts/sparse/spaugment.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{s} =} spaugment (@var{A}, @var{c})\n## Create the augmented matrix of @var{A}.\n##\n## This is given by\n##\n## @example\n## @group\n## [@var{c} * eye(@var{m}, @var{m}), @var{A};\n##             @var{A}', zeros(@var{n}, @var{n})]\n## @end group\n## @end example\n##\n## @noindent\n## This is related to the least squares solution of\n## @code{@var{A} \\ @var{b}}, by\n##\n## @example\n## @group\n## @var{s} * [ @var{r} / @var{c}; x] = [ @var{b}, zeros(@var{n}, columns(@var{b})) ]\n## @end group\n## @end example\n##\n## @noindent\n## where @var{r} is the residual error\n##\n## @example\n## @var{r} = @var{b} - @var{A} * @var{x}\n## @end example\n##\n## As the matrix @var{s} is symmetric indefinite it can be factorized with\n## @code{lu}, and the minimum norm solution can therefore be found without the\n## need for a @code{qr} factorization.  As the residual error will be\n## @code{zeros (@var{m}, @var{m})} for underdetermined problems, and example\n## can be\n##\n## @example\n## @group\n## m = 11; n = 10; mn = max (m, n);\n## A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],\n##              [-1, 0, 1], m, n);\n## x0 = A \\ ones (m,1);\n## s = spaugment (A);\n## [L, U, P, Q] = lu (s);\n## x1 = Q * (U \\ (L \\ (P  * [ones(m,1); zeros(n,1)])));\n## x1 = x1(end - n + 1 : end);\n## @end group\n## @end example\n##\n## To find the solution of an overdetermined problem needs an estimate of the\n## residual error @var{r} and so it is more complex to formulate a minimum norm\n## solution using the @code{spaugment} function.\n##\n## In general the left division operator is more stable and faster than using\n## the @code{spaugment} function.\n## @seealso{mldivide}\n## @end deftypefn\n\nfunction s = spaugment (A, c)\n\n  if (nargin < 2)\n    if (issparse (A))\n      c = max (max (abs (A))) / 1000;\n    else\n      if (ndims (A) != 2)\n        error (\"spaugment: A must be a 2-D matrix\");\n      else\n        c = max (abs (A(:))) / 1000;\n      endif\n    endif\n  elseif (! isscalar (c))\n    error (\"spaugment: C must be a scalar\");\n  endif\n\n  [m, n] = size (A);\n  s = [ c * speye(m, m), A; A', sparse(n, n)];\n\nendfunction\n\n\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);\n%! x0 = A \\ ones (m,1);\n%! s = spaugment (A);\n%! [L, U, P, Q] = lu (s);\n%! x1 = Q * (U \\ (L \\ (P  * [ones(m,1); zeros(n,1)])));\n%! x1 = x1(end - n + 1 : end);\n%! assert (x1, x0, 1e-6);\n"
  },
  {
    "path": "scripts/sparse/spconvert.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{x} =} spconvert (@var{m})\n## Convert a simple sparse matrix format easily generated by other programs\n## into Octave's internal sparse format.\n##\n## The input @var{m} is either a 3 or 4 column real matrix, containing the\n## row, column, real, and imaginary parts of the elements of the sparse\n## matrix.  An element with a zero real and imaginary part can be used to\n## force a particular matrix size.\n## @seealso{sparse}\n## @end deftypefn\n\nfunction s = spconvert (m)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (issparse (m))\n    s = m;\n  else\n    sz = size (m);\n    if (! ismatrix (m) || ! isreal (m)\n        || length (sz) != 2 || (sz(2) != 3 && sz(2) != 4))\n      error ([\"spconvert: argument must be sparse or real matrix\" ...\n              \"with 3 or 4 columns\"]);\n    elseif (sz(2) == 3)\n      s = sparse (m(:,1), m(:,2), m(:,3));\n    else\n      s = sparse (m(:,1), m(:,2), m(:,3) + 1i*m(:,4));\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! i = [1; 3; 5];\n%! j = [2; 4; 6];\n%! v = [7; 8; 9];\n%! s = spconvert ([i, j, v]);\n%! assert (issparse (s));\n%! [fi, fj, fv] = find (s);\n%! assert (isequal (i, fi) && isequal (j, fj) && isequal (v, fv));\n%! s = spconvert ([i, j, v, j]);\n%! [fi, fj, fv] = find (s);\n%! assert (isequal (i, fi) && isequal (j, fj) && isequal (complex (v, j), fv));\n%! assert (size (spconvert ([1, 1, 3; 5, 15, 0])), [5, 15]);\n\n## Test input validation\n%!error <Invalid call> spconvert ()\n%!error spconvert ({[1 2 3]})\n%!error spconvert ([1 2])\n%!error spconvert ([1 2 3i])\n%!error spconvert ([1 2 3 4 5])\n"
  },
  {
    "path": "scripts/sparse/spdiags.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{B} =} spdiags (@var{A})\n## @deftypefnx {} {[@var{B}, @var{d}] =} spdiags (@var{A})\n## @deftypefnx {} {@var{B} =} spdiags (@var{A}, @var{d})\n## @deftypefnx {} {@var{A} =} spdiags (@var{v}, @var{d}, @var{A})\n## @deftypefnx {} {@var{A} =} spdiags (@var{v}, @var{d}, @var{m}, @var{n})\n## A generalization of the function @code{diag}.\n##\n## Called with a single input argument, the nonzero diagonals @var{d} of\n## @var{A} are extracted.\n##\n## With two arguments the diagonals to extract are given by the vector @var{d}.\n##\n## The other two forms of @code{spdiags} modify the input matrix by replacing\n## the diagonals.  They use the columns of @var{v} to replace the diagonals\n## represented by the vector @var{d}.  If the sparse matrix @var{A} is\n## defined then the diagonals of this matrix are replaced.  Otherwise a\n## matrix of @var{m} by @var{n} is created with the diagonals given by the\n## columns of @var{v}.\n##\n## Negative values of @var{d} represent diagonals below the main diagonal, and\n## positive values of @var{d} diagonals above the main diagonal.\n##\n## For example:\n##\n## @example\n## @group\n## spdiags (reshape (1:12, 4, 3), [-1 0 1], 5, 4)\n##    @xresult{} 5 10  0  0\n##       1  6 11  0\n##       0  2  7 12\n##       0  0  3  8\n##       0  0  0  4\n## @end group\n## @end example\n##\n## @seealso{diag}\n## @end deftypefn\n\nfunction [B, d] = spdiags (v, d, m, n)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1 || nargin == 2)\n    ## extract nonzero diagonals of A into B,d\n    [nr, nc] = size (v);\n    [i, j] = find (v);\n\n    if (nargin == 1)\n      ## d contains the active diagonals\n      d = unique (j-i);\n    endif\n\n    ## FIXME: Maybe this could be done faster using [i,j,v] = find (v)\n    ##        and then massaging the indices i, j.  However, some\n    ##        benchmarking has shown that diag() written in C++ makes\n    ##        the following code faster even with the for loop.\n    Brows = min (nr, nc);\n    B = zeros (Brows, length (d));\n    for k = 1:length (d)\n      dn = d(k);\n      if (dn <= -nr || dn > nc)\n        continue;\n      endif\n      dv = diag (v, dn);\n      len = rows (dv);\n      ## Put sub/super-diagonals in the right place based on matrix size (MxN)\n      if (nr >= nc)\n        if (dn > 0)\n          offset = Brows - len + 1;\n          B(offset:Brows, k) = dv;\n        else\n          B(1:len, k) = dv;\n        endif\n      else\n        if (dn < 0)\n          offset = Brows - len + 1;\n          B(offset:Brows, k) = dv;\n        else\n          B(1:len, k) = dv;\n        endif\n      endif\n    endfor\n\n  elseif (nargin == 3)\n    ## Replace specific diagonals d of m with v,d\n    [nr, nc] = size (m);\n    A = spdiags (m, d);\n    B = m - spdiags (A, d, nr, nc) + spdiags (v, d, nr, nc);\n\n  else\n    ## Create new matrix of size mxn using v,d\n    [j, i, v] = find (v);\n    if (m >= n)\n      offset = max (min (d(:), n-m), 0);\n    else\n      offset = d(:);\n    endif\n    j = j(:) + offset(i(:));\n    i = j - d(:)(i(:));\n    idx = i > 0 & i <= m & j > 0 & j <= n;\n    B = sparse (i(idx), j(idx), v(idx), m, n);\n\n  endif\n\nendfunction\n\n\n%!test\n%! [B,d] = spdiags (magic (3));\n%! assert (d, [-2 -1 0 1 2]');\n%! assert (B, [4 3 8 0 0\n%!             0 9 5 1 0\n%!             0 0 2 7 6]);\n%! B = spdiags (magic (3), [-2 1]);\n%! assert (B, [4 0; 0 1; 0 7]);\n\n## Test zero filling for supra- and super-diagonals\n%!test\n%! ## Case 1: M = N\n%! A = sparse (zeros (3,3));\n%! A(1,3) = 13;\n%! A(3,1) = 31;\n%! [B, d] = spdiags (A);\n%! assert (d, [-2 2]');\n%! assert (B, [31 0; 0 0; 0 13]);\n%! assert (spdiags (B, d, 3,3), A);\n\n%!test\n%! ## Case 1: M > N\n%! A = sparse (zeros (4,3));\n%! A(1,3) = 13;\n%! A(3,1) = 31;\n%! [B, d] = spdiags (A);\n%! assert (d, [-2 2]');\n%! assert (B, [31 0; 0 0; 0 13]);\n%! assert (spdiags (B, d, 4,3), A);\n\n%!test\n%! ## Case 1: M < N\n%! A = sparse (zeros (3,4));\n%! A(1,3) = 13;\n%! A(3,1) = 31;\n%! [B, d] = spdiags (A);\n%! assert (d, [-2 2]');\n%! assert (B, [0 13; 0 0; 31 0]);\n%! assert (spdiags (B, d, 3,4), A);\n\n%!assert (spdiags (zeros (1,0),1,1,1), sparse (0))\n%!assert (spdiags (zeros (0,1),1,1,1), sparse (0))\n%!assert (spdiags ([0.5 -1 0.5], 0:2, 1, 1), sparse (0.5))\n\n## Test input validation\n%!error <Invalid call> spdiags ()\n"
  },
  {
    "path": "scripts/sparse/speye.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{s} =} speye ()\n## @deftypefnx {} {@var{s} =} speye (@var{n})\n## @deftypefnx {} {@var{s} =} speye (@var{m}, @var{n})\n## @deftypefnx {} {@var{s} =} speye ([@var{m}, @var{n}])\n## Return a sparse identity matrix of size @var{m}x@var{n}.\n##\n## If called with no arguments, return the sparse scalar value @code{1}.\n##\n## If invoked with a single scalar argument @var{n}, return a sparse square\n## @nospell{NxN} identity matrix.\n##\n## If supplied two scalar arguments (@var{m}, @var{n}), or a 2-element vector\n## @w{@code{[@var{m}, @var{n}]}}, return a sparse @nospell{MxN} identity matrix\n## with @var{m} rows and @var{n} columns.\n##\n## Programming Note: The implementation is significantly more efficient than\n## @w{@code{sparse (eye (@dots{}))}}@ as the full matrix is not constructed.\n## @seealso{sparse, spdiags, eye}\n## @end deftypefn\n\nfunction s = speye (m, n)\n\n  if (nargin == 0)\n    m = n = 1;\n  elseif (nargin == 1)\n    if (! isvector (m) || numel (m) > 2)\n      print_usage ();\n    endif\n\n    if (isscalar (m))\n      n = m;\n    else\n      n = m(2);\n      m = m(1);\n    endif\n  else\n    if (! (isscalar (m) && isscalar (n)))\n      error (\"speye: M and N must be scalar dimensions\");\n    endif\n  endif\n\n  ## Note: Matlab compatibility requires using 0 for negative dimensions.\n  m = ifelse (m < 0, 0, m);\n  n = ifelse (n < 0, 0, n);\n  lo = min (m, n);\n  s = sparse (1:lo, 1:lo, 1, m, n);\n\nendfunction\n\n\n%!assert (speye (), sparse (1))\n%!assert (speye (4), sparse (1:4,1:4,1))\n%!assert (speye (2,4), sparse (1:2,1:2,1,2,4))\n%!assert (speye (4,2), sparse (1:2,1:2,1,4,2))\n%!assert (speye ([4,2]), sparse (1:2,1:2,1,4,2))\n%!assert (speye (2, -3), sparse (2, 0))\n\n## Test input validation\n%!error <Invalid call> speye (ones (2,2))\n%!error <Invalid call> speye ([1, 2, 3])\n%!error <M and N must be scalar dimensions> speye ([1, 2], 3)\n%!error <M and N must be scalar dimensions> speye (1, [2, 3])\n"
  },
  {
    "path": "scripts/sparse/spfun.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} spfun (@var{f}, @var{S})\n## Compute @code{f (@var{S})} for the nonzero elements of @var{S}.\n##\n## The input function @var{f} is applied only to the nonzero elements of\n## the input matrix @var{S} which is typically sparse.  The function @var{f}\n## can be passed as a string, function handle, or inline function.\n##\n## The output @var{y} is a sparse matrix with the same sparsity structure as\n## the input @var{S}.  @code{spfun} preserves sparsity structure which is\n## different than simply applying the function @var{f} to the sparse matrix\n## @var{S} when @code{@var{f} (0) != 0}.\n##\n## Example\n##\n## Sparsity preserving @code{spfun} versus normal function application\n##\n## @example\n## @group\n## S = pi * speye (2,2)\n## S =\n##\n## Compressed Column Sparse (rows = 2, cols = 2, nnz = 2 [50%])\n##\n##   (1, 1) -> 3.1416\n##   (2, 2) -> 3.1416\n##\n## y = spfun (@@cos, S)\n## y =\n##\n## Compressed Column Sparse (rows = 2, cols = 2, nnz = 2 [50%])\n##\n##   (1, 1) -> -1\n##   (2, 2) -> -1\n## @end group\n##\n## @group\n## y = cos (S)\n## y =\n##\n## Compressed Column Sparse (rows = 2, cols = 2, nnz = 4 [100%])\n##\n##   (1, 1) -> -1\n##   (2, 1) -> 1\n##   (1, 2) -> 1\n##   (2, 2) -> -1\n##\n## @end group\n## @end example\n## @seealso{arrayfun, cellfun, structfun}\n## @end deftypefn\n\nfunction y = spfun (f, S)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! isnumeric (S))\n    error (\"spfun: S must be numeric\");\n  endif\n\n  [i, j, v] = find (S);\n  [m, n] = size (S);\n\n  y = sparse (i, j, feval (f, v), m, n);\n\nendfunction\n\n\n%!assert (spfun (\"exp\", [1,2;3,0]), sparse ([exp(1),exp(2);exp(3),0]))\n%!assert (spfun (\"exp\", sparse ([1,2;3,0])), sparse ([exp(1),exp(2);exp(3),0]))\n%!assert (spfun (@exp, [1,2;3,0]), sparse ([exp(1),exp(2);exp(3),0]))\n%!assert (spfun (@exp, sparse ([1,2;3,0])), sparse ([exp(1),exp(2);exp(3),0]))\n\n## Test input validation\n%!error <Invalid call> spfun ()\n%!error <Invalid call> spfun (@cos)\n%!error <S must be numeric> spfun (@cos, {1})\n%!error <S must be numeric> spfun (@cos, \"FooBar\")\n"
  },
  {
    "path": "scripts/sparse/spones.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{r} =} spones (@var{S})\n## Replace the nonzero entries of @var{S} with ones.\n##\n## This creates a sparse matrix with the same structure as @var{S}.\n## @seealso{sparse, sprand, sprandn, sprandsym, spfun, spy}\n## @end deftypefn\n\nfunction r = spones (S)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  [i, j, v] = find (S);\n  [m, n] = size (S);\n\n  r = sparse (i, j, 1, m, n);\n\nendfunction\n\n\n%!assert (issparse (spones ([1,2;3,0])))\n%!assert (spones ([1,2;3,0]), sparse ([1,1;1,0]))\n%!assert (spones (sparse ([1,2;3,0])), sparse ([1,1;1,0]))\n"
  },
  {
    "path": "scripts/sparse/sprand.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n##\n## Original version by Paul Kienzle distributed as free software in the\n## public domain.\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{s} =} sprand (@var{m}, @var{n}, @var{d})\n## @deftypefnx {} {@var{s} =} sprand (@var{m}, @var{n}, @var{d}, @var{rc})\n## @deftypefnx {} {@var{s} =} sprand (@var{s})\n## Generate a sparse matrix with uniformly distributed random values.\n##\n## The size of the matrix is @var{m}x@var{n} with a density of values @var{d}.\n## @var{d} must be between 0 and 1.  Values will be uniformly distributed on\n## the interval (0, 1).\n##\n## If called with a single matrix argument, a sparse matrix is generated with\n## random values wherever the matrix @var{s} is nonzero.\n##\n## If called with a scalar fourth argument @var{rc}, a random sparse matrix\n## with reciprocal condition number @var{rc} is generated.  If @var{rc} is\n## a vector, then it specifies the first singular values of the generated\n## matrix (@code{length (@var{rc}) <= min (@var{m}, @var{n})}).\n##\n## @seealso{sprandn, sprandsym, rand}\n## @end deftypefn\n\nfunction s = sprand (m, n, d, rc)\n\n  if (nargin == 1)\n    s = __sprand__ (m, @rand);\n  elseif (nargin == 3)\n    s = __sprand__ (m, n, d, \"sprand\", @rand);\n  elseif (nargin == 4)\n    s = __sprand__ (m, n, d, rc, \"sprand\", @rand);\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n## Test 3-input calling form\n%!test\n%! s = sprand (4, 10, 0.1);\n%! assert (size (s), [4, 10]);\n%! assert (nnz (s) / numel (s), 0.1);\n\n## Test 4-input calling form\n%!test\n%! d = rand ();\n%! s1 = sprand (100, 100, d, 0.4);\n%! rc = [5, 4, 3, 2, 1, 0.1];\n%! s2 = sprand (100, 100, d, rc);\n%! s3 = sprand (6, 4, d, rc);\n%! assert (svd (s2)'(1:length (rc)), rc, sqrt (eps));\n%! assert (1/cond (s1), 0.4, sqrt (eps));\n%! assert (nnz (s1) / (100*100), d, 0.02);\n%! assert (nnz (s2) / (100*100), d, 0.02);\n%! assert (svd (s3)', [5 4 3 2], sqrt (eps));\n\n## Test 1-input calling form\n%!test\n%! s = sprand (sparse ([1 2 3], [3 2 3], [2 2 2]));\n%! [i, j, v] = find (s);\n%! assert (sort (i), [1 2 3]');\n%! assert (sort (j), [2 3 3]');\n%! assert (all (v > 0 & v < 1));\n\n## Test very large, very low density matrix doesn't fail\n%!test\n%! s = sprand (1e6, 1e6, 1e-7);\n\n## Test empty array creation\n%!assert (size (sprand (0, 0, 0.5)), [0, 0])\n%!assert (size (sprand (0, 3, 0.5)), [0, 3])\n%!assert (size (sprand (3, 0, 0.5)), [3, 0])\n\n## Test input validation\n%!error <Invalid call> sprand ()\n%!error <Invalid call> sprand (1, 2)\n%!error <M must be a non-negative integer> sprand (-1, -1, 0.5)\n%!error <M must be a non-negative integer> sprand (ones (3), 3, 0.5)\n%!error <M must be a non-negative integer> sprand (3.5, 3, 0.5)\n%!error <M must be a non-negative integer> sprand (-1, 3, 0.5)\n%!error <N must be a non-negative integer> sprand (3, ones (3), 0.5)\n%!error <N must be a non-negative integer> sprand (3, 3.5, 0.5)\n%!error <N must be a non-negative integer> sprand (3, -1, 0.5)\n%!error <D must be between 0 and 1> sprand (3, 3, -1)\n%!error <D must be between 0 and 1> sprand (3, 3, 2)\n%!error <RC must be a scalar or vector> sprand (2, 2, 0.2, ones (3,3))\n%!error <RC must be between 0 and 1> sprand (2, 2, 0.2, -1)\n%!error <RC must be between 0 and 1> sprand (2, 2, 0.2, 2)\n"
  },
  {
    "path": "scripts/sparse/sprandn.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n##\n## Original version by Paul Kienzle distributed as free software in the\n## public domain.\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{s} =} sprandn (@var{m}, @var{n}, @var{d})\n## @deftypefnx {} {@var{s} =} sprandn (@var{m}, @var{n}, @var{d}, @var{rc})\n## @deftypefnx {} {@var{s} =} sprandn (@var{s})\n## Generate a sparse matrix with normally distributed random values.\n##\n## The size of the matrix is @var{m}x@var{n} with a density of values @var{d}.\n## @var{d} must be between 0 and 1.  Values will be normally distributed with a\n## mean of 0 and a variance of 1.\n##\n## If called with a single matrix argument, a sparse matrix is generated with\n## random values wherever the matrix @var{s} is nonzero.\n##\n## If called with a scalar fourth argument @var{rc}, a random sparse matrix\n## with reciprocal condition number @var{rc} is generated.  If @var{rc} is\n## a vector, then it specifies the first singular values of the generated\n## matrix (@code{length (@var{rc}) <= min (@var{m}, @var{n})}).\n##\n## @seealso{sprand, sprandsym, randn}\n## @end deftypefn\n\nfunction s = sprandn (m, n, d, rc)\n\n  if (nargin == 1)\n    s = __sprand__ (m, @randn);\n  elseif (nargin == 3)\n    s = __sprand__ (m, n, d, \"sprandn\", @randn);\n  elseif (nargin == 4)\n    s = __sprand__ (m, n, d, rc, \"sprandn\", @randn);\n  else\n    print_usage ();\n  endif\n\nendfunction\n\n\n## Test 3-input calling form\n%!test\n%! s = sprandn (4, 10, 0.1);\n%! assert (size (s), [4, 10]);\n%! assert (nnz (s) / numel (s), 0.1);\n\n## Test 4-input calling form\n%!test\n%! d = rand ();\n%! s1 = sprandn (100, 100, d, 0.4);\n%! rc = [5, 4, 3, 2, 1, 0.1];\n%! s2 = sprandn (100, 100, d, rc);\n%! s3 = sprandn (6, 4, d, rc);\n%! assert (svd (s2)'(1:length (rc)), rc, sqrt (eps));\n%! assert (1/cond (s1), 0.4, sqrt (eps));\n%! assert (nnz (s1) / (100*100), d, 0.02);\n%! assert (nnz (s2) / (100*100), d, 0.02);\n%! assert (svd (s3)', [5 4 3 2], sqrt (eps));\n\n## Test 1-input calling form\n%!test\n%! s = sprandn (sparse ([1 2 3], [3 2 3], [2 2 2]));\n%! [i, j] = find (s);\n%! assert (sort (i), [1 2 3]');\n%! assert (sort (j), [2 3 3]');\n\n## Test very large, very low density matrix doesn't fail\n%!test\n%! s = sprandn (1e6,1e6,1e-7);\n\n## Test empty array creation\n%!assert (size (sprandn (0, 0, 0.5)), [0, 0])\n%!assert (size (sprandn (0, 3, 0.5)), [0, 3])\n%!assert (size (sprandn (3, 0, 0.5)), [3, 0])\n\n## Test input validation\n%!error <Invalid call> sprandn ()\n%!error <Invalid call> sprandn (1, 2)\n%!error <M must be a non-negative integer> sprand (-1, -1, 0.5)\n%!error <M must be a non-negative integer> sprandn (ones (3), 3, 0.5)\n%!error <M must be a non-negative integer> sprandn (3.5, 3, 0.5)\n%!error <M must be a non-negative integer> sprandn (-1, 3, 0.5)\n%!error <N must be a non-negative integer> sprandn (3, ones (3), 0.5)\n%!error <N must be a non-negative integer> sprandn (3, 3.5, 0.5)\n%!error <N must be a non-negative integer> sprandn (3, -1, 0.5)\n%!error <D must be between 0 and 1> sprandn (3, 3, -1)\n%!error <D must be between 0 and 1> sprandn (3, 3, 2)\n%!error <RC must be a scalar or vector> sprandn (2, 2, 0.2, ones (3,3))\n%!error <RC must be between 0 and 1> sprandn (2, 2, 0.2, -1)\n%!error <RC must be between 0 and 1> sprandn (2, 2, 0.2, 2)\n"
  },
  {
    "path": "scripts/sparse/sprandsym.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{S} =} sprandsym (@var{n}, @var{d})\n## @deftypefnx {} {@var{S} =} sprandsym (@var{s})\n## Generate a symmetric random sparse matrix.\n##\n## The size of the matrix will be @var{n}x@var{n}, with a density of values\n## given by @var{d}.  @var{d} must be between 0 and 1 inclusive.  Values will\n## be normally distributed with a mean of zero and a variance of 1.\n##\n## If called with a single matrix argument, a random sparse matrix is generated\n## wherever the matrix @var{s} is nonzero in its lower triangular part.\n## @seealso{sprand, sprandn, spones, sparse}\n## @end deftypefn\n\nfunction S = sprandsym (n, d)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    [i, j] = find (tril (n));\n    [nr, nc] = size (n);\n    S = sparse (i, j, randn (size (i)), nr, nc);\n    S += tril (S, -1)';\n    return;\n  endif\n\n  if (!(isscalar (n) && n == fix (n) && n >= 0))\n    error (\"sprandsym: N must be a non-negative integer 0\");\n  endif\n\n  if (n == 0)\n    S = sparse (n, n);\n    return;\n  endif\n\n  if (d < 0 || d > 1)\n    error (\"sprandsym: density D must be between 0 and 1\");\n  endif\n\n  ## Actual number of nonzero entries\n  k = round (n^2*d);\n\n  ## Diagonal nonzero entries, same parity as k\n  r = pick_rand_diag (n, k);\n\n  ## Off diagonal nonzero entries\n  m = (k - r)/2;\n\n  ondiag = randperm (n, r);\n  offdiag = randperm (n*(n - 1)/2, m);\n\n  ## Row index\n  i = lookup (cumsum (0:n), offdiag - 1) + 1;\n\n  ## Column index\n  j = offdiag - (i - 1).*(i - 2)/2;\n\n  diagvals = randn (1, r);\n  offdiagvals = randn (1, m);\n\n  S = sparse ([ondiag, i, j], [ondiag, j, i],\n              [diagvals, offdiagvals, offdiagvals], n, n);\n\nendfunction\n\nfunction r = pick_rand_diag (n, k)\n\n  ## Pick a random number R of entries for the diagonal of a sparse NxN\n  ## symmetric square matrix with exactly K nonzero entries, ensuring\n  ## that this R is chosen uniformly over all such matrices.\n  ##\n  ## Let D be the number of diagonal entries and M the number of\n  ## off-diagonal entries.  Then K = D + 2*M.  Let A = N*(N-1)/2 be the\n  ## number of available entries in the upper triangle of the matrix.\n  ## Then, by a simple counting argument, there is a total of\n  ##\n  ##     T = nchoosek (N, D) * nchoosek (A, M)\n  ##\n  ## symmetric NxN matrices with a total of K nonzero entries and D on\n  ## the diagonal.  Letting D range from mod (K,2) through min (N,K), and\n  ## dividing by this sum, we obtain the probability P for D to be each\n  ## of those values.\n  ##\n  ## However, we cannot use this form for computation, as the binomial\n  ## coefficients become unmanageably large.  Instead, we use the\n  ## successive quotients Q(i) = T(i+1)/T(i), which we easily compute to\n  ## be\n  ##\n  ##               (N - D)*(N - D - 1)*M\n  ##     Q =  -------------------------------\n  ##            (D + 2)*(D + 1)*(A - M + 1)\n  ##\n  ## Then, after prepending 1, the cumprod of these quotients is\n  ##\n  ##      C = [ T(1)/T(1), T(2)/T(1), T(3)/T(1), ..., T(N)/T(1) ]\n  ##\n  ## Their sum is thus S = sum (T)/T(1), and then C(i)/S is the desired\n  ## probability P(i) for i=1:N.  The cumsum will finally give the\n  ## distribution function for computing the random number of entries on\n  ## the diagonal R.\n  ##\n  ## Thanks to Zsbán Ambrus <ambrus@math.bme.hu> for most of the ideas\n  ## of the implementation here, especially how to do the computation\n  ## numerically to avoid overflow.\n\n  ## Degenerate case\n  if (k == 1)\n    r = 1;\n    return;\n  endif\n\n  ## Compute the stuff described above\n  a = n*(n - 1)/2;\n  d = [mod(k,2):2:min(n,k)-2];\n  m = (k - d)/2;\n  q = (n - d).*(n - d - 1).*m ./ (d + 2)./(d + 1)./(a - m + 1);\n\n  ## Slight modification from discussion above: pivot around the max in\n  ## order to avoid overflow (underflow is fine, just means effectively\n  ## zero probabilities).\n  [~, midx] = max (cumsum (log (q)));\n  midx += 1;\n  lc = fliplr (cumprod (1./q(midx-1:-1:1)));\n  rc = cumprod (q(midx:end));\n\n  ## Now c = t(i)/t(midx), so c > 1 == [].\n  c = [lc, 1, rc];\n  s = sum (c);\n  p = c/s;\n\n  ## Add final d\n  d(end+1) = d(end) + 2;\n\n  ## Pick a random r using this distribution\n  r = d(sum (cumsum (p) < rand) + 1);\n\nendfunction\n\n\n%!test\n%! s = sprandsym (10, 0.1);\n%! assert (issparse (s));\n%! assert (issymmetric (s));\n%! assert (size (s), [10, 10]);\n%! assert (nnz (s) / numel (s), 0.1, .01);\n\n## Test 1-input calling form\n%!test\n%! s = sprandsym (sparse ([1 2 3], [3 2 3], [2 2 2]));\n%! [i, j] = find (s);\n%! assert (sort (i), [2 3]');\n%! assert (sort (j), [2 3]');\n\n## Test empty array creation\n%!assert (size (sprandsym (0, 0.5)), [0, 0])\n\n## Test input validation\n%!error <Invalid call> sprandsym ()\n%!error sprandsym (ones (3), 0.5)\n%!error sprandsym (3.5, 0.5)\n%!error sprandsym (-1, 0.5)\n%!error sprandsym (3, -1)\n%!error sprandsym (3, 2)\n"
  },
  {
    "path": "scripts/sparse/spstats.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{count}, @var{mean}, @var{var}] =} spstats (@var{S})\n## @deftypefnx {} {[@var{count}, @var{mean}, @var{var}] =} spstats (@var{S}, @var{j})\n## Return the stats for the nonzero elements of the sparse matrix @var{S}.\n##\n## @var{count} is the number of nonzeros in each column, @var{mean} is the mean\n## of the nonzeros in each column, and @var{var} is the variance of the\n## nonzeros in each column.\n##\n## Called with two input arguments, if @var{S} is the data and @var{j} is the\n## bin number for the data, compute the stats for each bin.  In this case,\n## bins can contain data values of zero, whereas with\n## @code{spstats (@var{S})} the zeros may disappear.\n## @end deftypefn\n\nfunction [count, mean, var] = spstats (S, j)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    [i, j, v] = find (S);\n  else\n    v = S;\n    i = 1:length (v);\n    S = sparse (i, j, v);\n  endif\n  [n, m] = size (S);\n\n  count = sum (sparse (i, j, 1, n, m));\n  if (nargout > 1)\n    mean = sum (S) ./ count;\n  endif\n  if (nargout > 2)\n    ## FIXME: Variance with count = 0 or 1?\n    diff = S - sparse (i, j, mean (j), n, m);\n    var = sum (diff .* diff) ./ (count - 1);\n  endif\n\nendfunction\n\n\n%!test\n%! [n,m,v] = spstats ([1 2 1 2 3 4],[2 2 1 1 1 1]);\n%! assert (n, sparse ([4,2]));\n%! assert (m, sparse ([10/4,3/2]), 10*eps);\n%! assert (v, sparse ([5/3,1/2]), 10*eps);\n"
  },
  {
    "path": "scripts/sparse/spy.m",
    "content": "########################################################################\n##\n## Copyright (C) 1998-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} spy (@var{x})\n## @deftypefnx {} {} spy (@dots{}, @var{markersize})\n## @deftypefnx {} {} spy (@dots{}, @var{line_spec})\n## Plot the sparsity pattern of the sparse matrix @var{x}.\n##\n## If the optional numeric argument @var{markersize} is given, it determines\n## the size of the markers used in the plot.\n##\n## If the optional string @var{line_spec} is given it is passed to @code{plot}\n## and determines the appearance of the plot.\n## @seealso{plot, gplot}\n## @end deftypefn\n\nfunction spy (x, varargin)\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  markersize = NaN;\n  if (nnz (x) < 1000)\n    line_spec = \"*\";\n  else\n    line_spec = \".\";\n  endif\n  for arg = varargin\n    arg = arg{1};\n    if (ischar (arg))\n      if (numel (arg) == 1)\n        line_spec = [line_spec, arg];\n      else\n        line_spec = arg;\n      endif\n    elseif (isreal (arg) && isscalar (arg))\n      markersize = arg;\n    else\n      error (\"spy: expected markersize or linespec\");\n    endif\n  endfor\n\n  [i, j] = find (x);\n  [m, n] = size (x);\n\n  if (isnan (markersize))\n    plot (j, i, line_spec);\n  else\n    plot (j, i, line_spec, \"markersize\", markersize);\n  endif\n\n  axis ([0, n+1, 0, m+1], \"ij\");\n  xlabel (sprintf (\"nnz = %d\", nnz (x)));\n\nendfunction\n\n\n%!demo\n%! clf;\n%! spy (sprand (10,10, 0.2));\n\n## Test input validation\n%!error <Invalid call> spy ()\n%!error <Invalid call> spy (1,2,3,4)\n"
  },
  {
    "path": "scripts/sparse/svds.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{s} =} svds (@var{A})\n## @deftypefnx {} {@var{s} =} svds (@var{A}, @var{k})\n## @deftypefnx {} {@var{s} =} svds (@var{A}, @var{k}, @var{sigma})\n## @deftypefnx {} {@var{s} =} svds (@var{A}, @var{k}, @var{sigma}, @var{opts})\n## @deftypefnx {} {[@var{u}, @var{s}, @var{v}] =} svds (@dots{})\n## @deftypefnx {} {[@var{u}, @var{s}, @var{v}, @var{flag}] =} svds (@dots{})\n##\n## Find a few singular values of the matrix @var{A}.\n##\n## The singular values are calculated using\n##\n## @example\n## @group\n## [@var{m}, @var{n}] = size (@var{A});\n## @var{s} = eigs ([sparse(@var{m}, @var{m}), @var{A};\n##                      @var{A}', sparse(@var{n}, @var{n})])\n## @end group\n## @end example\n##\n## The eigenvalues returned by @code{eigs} correspond to the singular values\n## of @var{A}.  The number of singular values to calculate is given by @var{k}\n## and defaults to 6.\n##\n## The argument @var{sigma} specifies which singular values to find.  When\n## @var{sigma} is the string @qcode{'L'}, the default, the largest singular\n## values of @var{A} are found.  Otherwise, @var{sigma} must be a real scalar\n## and the singular values closest to @var{sigma} are found.  As a corollary,\n## @code{@var{sigma} = 0} finds the smallest singular values.  Note that for\n## relatively small values of @var{sigma}, there is a chance that the\n## requested number of singular values will not be found.  In that case\n## @var{sigma} should be increased.\n##\n## @var{opts} is a structure defining options that @code{svds} will pass\n## to @code{eigs}.  The possible fields of this structure are documented in\n## @code{eigs}.  By default, @code{svds} sets the following three fields:\n##\n## @table @code\n## @item tol\n## The required convergence tolerance for the singular values.  The default\n## value is 1e-10.  @code{eigs} is passed @code{@var{tol} / sqrt (2)}.\n##\n## @item maxit\n## The maximum number of iterations.  The default is 300.\n##\n## @item disp\n## The level of diagnostic printout (0|1|2).  If @code{disp} is 0 then\n## diagnostics are disabled.  The default value is 0.\n## @end table\n##\n## If more than one output is requested then @code{svds} will return an\n## approximation of the singular value decomposition of @var{A}\n##\n## @example\n## @var{A}_approx = @var{u}*@var{s}*@var{v}'\n## @end example\n##\n## @noindent\n## where @var{A}_approx is a matrix of size @var{A} but only rank @var{k}.\n##\n## @var{flag} returns 0 if the algorithm has successfully converged, and 1\n## otherwise.  The test for convergence is\n##\n## @example\n## @group\n## norm (@var{A}*@var{v} - @var{u}*@var{s}, 1) <= @var{tol} * norm (@var{A}, 1)\n## @end group\n## @end example\n##\n## @code{svds} is best for finding only a few singular values from a large\n## sparse matrix.  Otherwise, @code{svd (full (@var{A}))} will likely be more\n## efficient.\n## @seealso{svd, eigs}\n## @end deftypefn\n\nfunction [u, s, v, flag] = svds (A, k, sigma, opts)\n\n  persistent root2 = sqrt (2);\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ndims (A) > 2)\n    error (\"svds: A must be a 2-D matrix\");\n  endif\n\n  if (nargin < 4)\n    opts.tol = 0;    # use ARPACK default\n    opts.disp = 0;\n    opts.maxit = 300;\n  else\n    if (! isstruct (opts))\n      error (\"svds: OPTS must be a structure\");\n    endif\n    if (! isfield (opts, \"tol\"))\n      opts.tol = 0;  # use ARPACK default\n    else\n      opts.tol = opts.tol / root2;\n    endif\n    if (isfield (opts, \"v0\"))\n      if (! isvector (opts.v0) || (length (opts.v0) != sum (size (A))))\n        error (\"svds: OPTS.v0 must be a vector with rows (A) + columns (A) entries\");\n      endif\n    endif\n  endif\n\n  if (nargin < 3 || strcmp (sigma, \"L\"))\n    if (isreal (A))\n      sigma = \"LA\";\n    else\n      sigma = \"LR\";\n    endif\n  elseif (isscalar (sigma) && isnumeric (sigma) && isreal (sigma))\n    if (sigma < 0)\n      error (\"svds: SIGMA must be a positive real value\");\n    endif\n  else\n    error (\"svds: SIGMA must be a positive real value or the string 'L'\");\n  endif\n\n  [m, n] = size (A);\n  max_a = max (abs (nonzeros (A)));\n  if (isempty (max_a))\n    max_a = 0;\n  endif\n  ## Must initialize variable value, otherwise it may appear to interpreter\n  ## that code is trying to call flag() colormap function.\n  flag = 0;\n\n  if (max_a == 0)\n    s = zeros (k, 1);  # special case of zero matrix\n  else\n    if (nargin < 2)\n      k = min ([6, m, n]);\n    else\n      k = min ([k, m, n]);\n    endif\n\n    ## Scale everything by the 1-norm to make things more stable.\n    b = A / max_a;\n    b_opts = opts;\n    ## Call to eigs is always a symmetric matrix by construction\n    b_opts.issym = true;\n    b_sigma = sigma;\n    if (! ischar (b_sigma))\n      b_sigma /= max_a;\n    endif\n\n    if (b_sigma == 0)\n      ## Find the smallest eigenvalues\n      ## The eigenvalues returns by eigs for sigma=0 are symmetric about 0.\n      ## As we are only interested in the positive eigenvalues, we have to\n      ## double k and then throw out the k negative eigenvalues.\n      ## Separately, if sigma is nonzero, but smaller than the smallest\n      ## singular value, ARPACK may not return k eigenvalues.  However, as\n      ## computation scales with k we'd like to avoid doubling k for all\n      ## scalar values of sigma.\n      b_k = 2 * k;\n    else\n      b_k = k;  # Normal case, find just the k largest eigenvalues\n    endif\n\n    if (nargout > 1)\n      [V, s, flag] = eigs ([sparse(m,m), b; b', sparse(n,n)],\n                           b_k, b_sigma, b_opts);\n      s = diag (s);\n    else\n      s = eigs ([sparse(m,m), b; b', sparse(n,n)], b_k, b_sigma, b_opts);\n    endif\n\n    if (ischar (sigma))\n      norma = max (s);\n    else\n      norma = normest (A);\n    endif\n    ## We wish to exclude all eigenvalues that are less than zero as these\n    ## are artifacts of the way the matrix passed to eigs is formed.  There\n    ## is also the possibility that the value of sigma chosen is exactly\n    ## a singular value, and in that case we're dead!! So have to rely on\n    ## the warning from eigs.  We exclude the singular values which are\n    ## less than or equal to zero to within some tolerance scaled by the\n    ## norm since if we don't we might end up with too many singular\n    ## values.\n    if (b_sigma == 0)\n      if (sum (s>0) < k)\n        ## It may happen that the number of positive s is less than k.\n        ## In this case, take -s (if s in an eigenvalue, so is -s),\n        ## flipped upside-down.\n        s = flipud (-s);\n      endif\n    endif\n    tol = norma * opts.tol;\n    ind = find (s > tol);\n    if (length (ind) < k)\n      ## Too few eigenvalues returned.  Add in any zero eigenvalues of B,\n      ## including the nominally negative ones.\n      zind = find (abs (s) <= tol);\n      p = min (length (zind), k - length (ind));\n      ind = [ind; zind(1:p)];\n    elseif (length (ind) > k)\n      ## Too many eigenvalues returned.  Select according to criterion.\n      if (b_sigma == 0)\n        ind = ind(end+1-k:end); # smallest eigenvalues\n      else\n        ind = ind(1:k);         # largest eigenvalues\n      endif\n    endif\n    s = s(ind);\n\n    if (length (s) < k)\n      warning (\"svds: returning fewer singular values than requested\");\n      if (! ischar (sigma))\n        warning (\"svds: try increasing the value of sigma\");\n      endif\n    endif\n\n    s *= max_a;\n  endif\n\n  if (nargout < 2)\n    u = s;\n  else\n    if (max_a == 0)\n      u = eye (m, k);\n      s = diag (s);\n      v = eye (n, k);\n    else\n      u = root2 * V(1:m,ind);\n      s = diag (s);\n      v = root2 * V(m+1:end,ind);\n    endif\n\n    if (nargout > 3)\n      flag = (flag != 0);\n    endif\n  endif\n\nendfunction\n\n\n%!shared n, k, A, u, s, v, opts, rand_state, randn_state, tol\n%! n = 100;\n%! k = 7;\n%! A = sparse ([3:n,1:n,1:(n-2)],[1:(n-2),1:n,3:n],[ones(1,n-2),0.4*n*ones(1,n),ones(1,n-2)]);\n%! [u,s,v] = svd (full (A));\n%! s = diag (s);\n%! [~, idx] = sort (abs (s));\n%! s = s(idx);\n%! u = u(:, idx);\n%! v = v(:, idx);\n%! rand_state = rand (\"state\");\n%! rand (\"state\", 42);\n%! opts.v0 = rand (2*n,1);  # Initialize eigs ARPACK starting vector\n%!                          # to guarantee reproducible results\n\n%!testif HAVE_ARPACK\n%! [u2,s2,v2,flag] = svds (A,k);\n%! s2 = diag (s2);\n%! assert (flag, ! 1);\n%! tol = 15 * eps * norm (s2, 1);\n%! assert (s2, s(end:-1:end-k+1), tol);\n\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! [u2,s2,v2,flag] = svds (A,k,0,opts);\n%! s2 = diag (s2);\n%! assert (flag, ! 1);\n%! tol = 15 * eps * norm (s2, 1);\n%! assert (s2, s(k:-1:1), tol);\n\n%!testif HAVE_ARPACK, HAVE_UMFPACK\n%! idx = floor (n/2);\n%! % Don't put sigma right on a singular value or there are convergence issues\n%! sigma = 0.99*s(idx) + 0.01*s(idx+1);\n%! [u2,s2,v2,flag] = svds (A,k,sigma,opts);\n%! s2 = diag (s2);\n%! assert (flag, ! 1);\n%! tol = 15 * eps * norm (s2, 1);\n%! assert (s2, s((idx+floor (k/2)):-1:(idx-floor (k/2))), tol);\n\n%!testif HAVE_ARPACK\n%! [u2,s2,v2,flag] = svds (zeros (10), k);\n%! assert (u2, eye (10, k));\n%! assert (s2, zeros (k));\n%! assert (v2, eye (10, 7));\n%!\n%!testif HAVE_ARPACK\n%! s = svds (speye (10));\n%! assert (s, ones (6, 1), 8*eps);\n\n%!testif HAVE_ARPACK <57185>\n%! z = complex (ones (10), ones (10));\n%! s = svds (z);\n%! assert (isreal (s));\n\n%!test\n%! ## Restore random number generator seed at end of tests\n%! rand (\"state\", rand_state);\n"
  },
  {
    "path": "scripts/sparse/tfqmr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} tfqmr (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0}, @dots{})\n## @deftypefnx {} {@var{x} =} tfqmr (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M}, [], @var{x0}, @dots{})\n## @deftypefnx {} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} tfqmr (@var{A}, @var{b}, @dots{})\n## Solve @code{A x = b} using the Transpose-Tree qmr method, based on the cgs.\n##\n## The input parameters are:\n##\n## @itemize @minus\n##\n## @item @var{A} is the matrix of the linear system and it must be square.\n## @var{A} can be passed as a matrix, function handle, or inline\n## function @code{Afcn} such that @code{Afcn(x) = A * x}.  Additional\n## parameters to @code{Afcn} are passed after @var{x0}.\n##\n## @item @var{b} is the right hand side vector.  It must be a column vector\n## with the same number of rows as @var{A}.\n##\n## @item @var{tol} is the relative tolerance, if not given or set to [] the\n## default value 1e-6 is used.\n##\n## @item @var{maxit} the maximum number of outer iterations, if not given or\n## set to [] the default value @code{min (20, numel (b))} is used.  To be\n## compatible, since the method as different behaviors in the iteration\n## number is odd or even, is considered as iteration in @code{tfqmr} the\n## entire odd-even cycle.  That is, to make an entire iteration, the algorithm\n## performs two sub-iterations: the odd one and the even one.\n##\n## @item @var{M1}, @var{M2} are the preconditioners.  The preconditioner\n## @var{M} is given as @code{M = M1 * M2}.\n## Both @var{M1} and @var{M2} can be passed as a matrix or as a function\n## handle or inline function @code{g} such that @code{g(x) = M1 \\ x} or\n## @code{g(x) = M2 \\ x}.\n## The technique used is the right-preconditioning, i.e., it is solved\n## @code{A*inv(M)*y = b} and then @code{x = inv(M)*y}, instead of\n## @code{A x = b}.\n##\n## @item @var{x0} the initial guess, if not given or set to [] the default\n## value @code{zeros (size (b))} is used.\n##\n## @end itemize\n##\n## The arguments which follow @var{x0} are treated as parameters, and passed in\n## a proper way to any of the functions (@var{A} or @var{M}) which are passed\n## to @code{tfqmr}.\n##\n## The output parameters are:\n##\n## @itemize @minus\n##\n## @item @var{x} is the approximation computed.  If the method doesn't\n## converge then it is the iterated with the minimum residual.\n##\n## @item @var{flag} indicates the exit status:\n##\n## @itemize @minus\n## @item 0: iteration converged to the within the chosen tolerance\n##\n## @item 1: the maximum number of iterations was reached before convergence\n##\n## @item 2: the preconditioner matrix is singular\n##\n## @item 3: the algorithm reached stagnation\n##\n## @item 4: the algorithm can't continue due to a division by zero\n## @end itemize\n##\n## @item @var{relres} is the relative residual obtained as\n## @code{(@var{A}*@var{x}-@var{b}) / @code{norm (@var{b})}}.\n##\n## @item @var{iter} is the iteration which @var{x} is\n## computed.\n##\n## @item @var{resvec} is a vector containing the residual at each iteration\n## (including @code{norm (b - A x0)}).\n## Doing @code{length (@var{resvec}) - 1} is possible to see the\n## total number of iterations performed.\n##\n## @end itemize\n##\n## Let us consider a trivial problem with a tridiagonal matrix\n##\n## @smallexample\n## @group\n## n = 20;\n## A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n##     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n##     sparse (1, 2, 1, 1, n) * n / 2);\n## b = A * ones (n, 1);\n## restart = 5;\n## [M1, M2] = ilu (A); # in this tridiag case it corresponds to chol (A)'\n## M = M1 * M2;\n## Afcn = @@(x) A * x;\n## Mfcn = @@(x) M \\ x;\n## M1fcn = @@(x) M1 \\ x;\n## M2fcn = @@(x) M2 \\ x;\n## @end group\n## @end smallexample\n##\n## @sc{Example 1:} simplest usage of @code{tfqmr}\n##\n## @example\n## x = tfqmr (A, b, [], n)\n## @end example\n##\n## @sc{Example 2:} @code{tfqmr} with a function which computes\n## @code{@var{A} * @var{x}}\n##\n## @example\n## x = tfqmr (Afcn, b, [], n)\n## @end example\n##\n## @sc{Example 3:} @code{tfqmr} with a preconditioner matrix @var{M}\n##\n## @example\n## x = tfqmr (A, b, [], 1e-06, n, M)\n## @end example\n##\n## @sc{Example 4:} @code{tfqmr} with a function as preconditioner\n##\n## @example\n## x = tfqmr (Afcn, b, 1e-6, n, Mfcn)\n## @end example\n##\n## @sc{Example 5:} @code{tfqmr} with preconditioner matrices @var{M1}\n## and @var{M2}\n##\n## @example\n## x = tfqmr (A, b, [], 1e-6, n, M1, M2)\n## @end example\n##\n## @sc{Example 6:} @code{tfmqr} with functions as preconditioners\n##\n## @example\n## x = tfqmr (Afcn, b, 1e-6, n, M1fcn, M2fcn)\n## @end example\n##\n## @sc{Example 7:} @code{tfqmr} with as input a function requiring an argument\n##\n## @example\n## @group\n## function y = Ap (A, x, z) # compute A^z * x\n##    y = x;\n##    for i = 1:z\n##      y = A * y;\n##    endfor\n##  endfunction\n## Apfcn = @@(x, string, p) Ap (A, x, string, p);\n## x = tfqmr (Apfcn, b, [], [], [], [], [], 2);\n## @end group\n## @end example\n##\n## @sc{Example 8:} explicit example to show that @code{tfqmr} uses a\n## right preconditioner\n##\n## @example\n## @group\n## [M1, M2] = ilu (A + 0.3 * eye (n)); # factorization of A perturbed\n## M = M1 * M2;\n##\n## ## reference solution computed by tfqmr after one iteration\n## [x_ref, fl] = tfqmr (A, b, [], 1, M)\n##\n## ## right preconditioning\n## [y, fl] = tfqmr (A / M, b, [], 1)\n## x = M \\ y # compare x and x_ref\n##\n## @end group\n## @end example\n##\n## Reference:\n##\n## @nospell{Y. Saad}, @cite{Iterative Methods for Sparse Linear Systems},\n## 2nd edition, SIAM, 2003.\n##\n## @seealso{bicg, bicgstab, cgs, gmres, pcg, qmr, pcr}\n##\n## @end deftypefn\n\nfunction [x_min, flag, relres, iter_min, resvec] = ...\n         tfqmr (A, b, tol = [], maxit = [], M1 = [], M2 = [], ...\n                x0 = [], varargin)\n\n  [Afcn, M1fcn, M2fcn] = __alltohandles__ (A, b, M1, M2, \"tfqmr\");\n\n  [tol, maxit, x0] = __default__input__ ({1e-06, 2 * min(20, rows (b)), ...\n                                          zeros(rows (b), 1)}, tol, ...\n                                         maxit, x0);\n\n  maxit = 2 * maxit; # To be compatible, since iteration = odd+even ones\n\n  norm_b = norm (b, 2);\n  if (norm_b == 0)\n    if (nargout < 2)\n      printf (\"The right hand side vector is all zero so tfqmr \\n\")\n      printf (\"returned an all zero solution without iterating.\\n\")\n    endif\n    x_min = zeros (numel (b), 1);\n    iter_min = 0;\n    flag = 0;\n    resvec = 0;\n    relres = 0;\n    return;\n  endif\n\n  x = x_pr = x_min = x0;\n  iter = iter_min = m = 0;\n  resvec = zeros (maxit, 1);\n  flag = 1;\n\n  w = u = r = r_star = b - feval (Afcn, x0, varargin{:});\n  rho_1 = (r_star' * r);\n  d = 0;\n  tau = norm (r, 2);\n  theta = eta = 0;\n  resvec (1, 1) = norm (r, 2);\n  it = 1;\n\n  try\n    warning (\"error\", \"Octave:singular-matrix\", \"local\");\n    u_hat = feval (M1fcn, u, varargin{:});\n    u_hat = feval (M2fcn, u_hat, varargin{:});\n    v = feval (Afcn, u_hat, varargin{:});\n  catch\n    flag = 2;\n  end_try_catch\n  while ((flag != 2) && (iter < maxit) && ...\n         (resvec (iter + 1, 1) >= norm_b * tol))\n    if (it > 0) # iter is even\n      v_r = r_star' * v; # inner prod between r_star and v\n      if (v_r == 0)\n        ## Essentially the next iteration doesn't change x,\n        ## and the iter after this will have a division by zero\n        flag = 4;\n        break;\n      endif\n      alpha = rho_1 / v_r;\n      u_1 = u - alpha * v;  # u at the after iteration\n    endif\n    u_hat = feval (M1fcn, u, varargin{:});\n    u_hat = feval (M2fcn, u_hat, varargin{:});\n    w -= alpha * feval (Afcn, u_hat, varargin{:});\n    d = u_hat + ((theta * theta) / alpha) * eta * d;\n    theta = norm (w, 2) / tau;\n    c = 1 / sqrt (1 + theta * theta);\n    tau *= theta * c;\n    eta = (c * c) * alpha;\n    x += eta * d;\n    r -= eta * feval (Afcn, d, varargin{:});\n    if (it < 0) # iter is odd\n      rho_2 = rho_1;\n      rho_1 = (r_star' * w);\n      if (rho_1 == 0)\n        ## Essentially the next iteration doesn't change x,\n        ## and the iter after this will have a division by zero\n        flag = 4;\n        break;\n      endif\n      beta = rho_1 / rho_2;\n      u_1 = w + beta * u; # u at the after iteration\n      u1_hat = feval (M1fcn, u_1, varargin{:});\n      u1_hat = feval (M2fcn, u1_hat, varargin{:});\n      v = feval (Afcn, u1_hat, varargin{:}) + ...\n          beta * (feval (Afcn, u_hat, varargin{:}) + beta * v);\n    endif\n    u = u_1;\n    iter += 1;\n    resvec (iter + 1, 1) = norm (r, 2);\n    if (resvec (iter + 1, 1) <= resvec (iter_min + 1, 1))\n      ## iter with min residual\n      x_min = x;\n      iter_min = iter;\n    endif\n    if (norm (x_pr - x) <= norm (x) * eps)\n      flag = 3; # Stagnation\n      break;\n    endif\n    x_pr = x;\n    it = -it;\n  endwhile\n  resvec = resvec (1: (iter + 1));\n\n  relres = resvec (iter_min + 1) / norm (b);\n  iter_min = floor (iter_min / 2); # compatibility, since it\n                                   # makes two times the effective iterations\n\n  if (relres <= tol)\n    flag = 0;\n  endif\n\n  if (nargout < 2) # Output strings\n    switch (flag)\n      case {0}\n        printf (\"tfqmr converged at iteration %i \", iter_min);\n        printf (\"to a solution with relative residual %e\\n\", relres);\n      case {1}\n        printf (\"tfqmr stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the maximum number of iterations was reached.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case {2}\n        printf (\"tfqmr stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the preconditioner matrix is singular.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case {3}\n        printf (\"tfqmr stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the method stagnated.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n      case {4}\n        printf (\"tfqmr stopped at iteration %i \", iter);\n        printf (\"without converging to the desired tolerance %e\\n\", tol);\n        printf (\"because the method can't continue.\\n\");\n        printf (\"The iterate returned (number %i) \", iter_min);\n        printf (\"has relative residual %e\\n\", relres);\n    endswitch\n  endif\n\nendfunction\n\n\n%!test\n%! ## Check that all type of inputs work\n%! A = toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M1 = diag (sqrt (diag (A)));\n%! M2 = M1;\n%! maxit = 10;\n%! Afcn = @(z) A * z;\n%! M1_fcn = @(z) M1 \\ z;\n%! M2_fcn = @(z) M2 \\ z;\n%! [x, flag] = tfqmr (A,b);\n%! assert (flag, 0);\n%! [x, flag] = tfqmr (A, b, [], maxit, M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = tfqmr (A, b, [], maxit, M1_fcn, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = tfqmr (A, b, [], maxit, M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = tfqmr (A, b, [], maxit, M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = tfqmr (Afcn, b);\n%! assert (flag, 0);\n%! [x, flag] = tfqmr (Afcn, b, [], maxit, M1, M2);\n%! assert (flag, 0);\n%! [x, flag] = tfqmr (Afcn, b, [], maxit, M1_fcn, M2);\n%! assert (flag, 0);\n%! [x, flag] = tfqmr (Afcn, b, [], maxit, M1, M2_fcn);\n%! assert (flag, 0);\n%! [x, flag] = tfqmr (Afcn, b, [], maxit, M1_fcn, M2_fcn);\n%! assert (flag, 0);\n\n%!shared A, b, n, M1, M2\n%!\n%!test\n%! n = 100;\n%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);\n%! b = sum (A, 2);\n%! tol = 1e-8;\n%! maxit = 15;\n%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);\n%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);\n%! [x, flag, relres, iter, resvec] = tfqmr (A, b, tol, maxit, M1, M2);\n%! assert (x, ones (size (b)), 1e-7);\n%!\n%!test\n%!function y = afcn (x, a)\n%!  y = a * x;\n%!endfunction\n%!\n%! tol = 1e-8;\n%! maxit = 15;\n%!\n%! [x, flag, relres, iter, resvec] = tfqmr (@(x) afcn (x, A), b,\n%!                                          tol, maxit, M1, M2);\n%! assert (x, ones (size (b)), 1e-7);\n\n%!test\n%! ## Jacobi preconditioner works\n%! n = 10;\n%! tol = 1e-8;\n%! A = hilb (n) + 1i * hilb (n);\n%! A(1,1) = 100;\n%! A(n, n) = 100;\n%! b = sum (A, 2);\n%! [x, flag, relres, iter, resvec] = tfqmr (A, b, tol);\n%! assert (x, ones (size (b)), 0.005);\n%! assert (iter, 8);\n%! [x, flag, relres, iter, resvec] = tfqmr (A, b, tol, [], diag (diag (A)));\n%! assert (x, ones (size (b)), 0.002);\n%! assert (iter, 6);\n\n%!test\n%! ## Solve complex linear system\n%! A = [1 + 1i, 1 + 1i; 2 - 1i, 2 + 1i];\n%! b = A * [1; 1];\n%! [x, flag, relres, iter, resvec] = tfqmr (A, b, [], 3);\n%! assert (x, [1; 1], 1e-6);\n\n%!test\n%! A = diag (1:50);\n%! A (1,50) = 10000;\n%! b = ones (50,1);\n%! [x, flag, relres, iter, resvec] = tfqmr (A, b, [], 100);\n%! assert (flag, 0);\n%! assert (x, A \\ b, 1e-05);\n%! ## Detects a singular preconditioner\n%! M = ones (50);\n%! M(1, 1) = 0;\n%! [x, flag] = tfqmr (A, b, [], 100, M);\n%! assert (flag, 2);\n\n%!test\n%! A = single (1);\n%! b = 1;\n%! [x, flag] = tfqmr (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = 1;\n%! b = single (1);\n%! [x, flag] = tfqmr (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%! A = single (1);\n%! b = single (1);\n%! [x, flag] = tfqmr (A, b);\n%! assert (class (x), \"single\");\n\n%!test\n%!function y = Afcn (x)\n%!  A = toeplitz ([2, 1, 0, 0], [2, -1, 0, 0]);\n%!  y = A * x;\n%!endfunction\n%! [x, flag] = tfqmr (\"Afcn\", [1; 2; 2; 3]);\n%! assert (x, ones (4, 1), 1e-6);\n\n%!test # unpreconditioned residual\n%! A = toeplitz (sparse ([2, 1, 0, 0, 0]), sparse ([2, -1, 0, 0, 0]));\n%! b = sum (A, 2);\n%! M = magic (5);\n%! [x, flag, relres] = tfqmr (A, b, [], 3, M);\n%! assert (relres, norm (b - A * x) / norm (b), 8 * eps);\n\n%!demo # simplest use\n%! n = 20;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n%!     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n%!     sparse (1, 2, 1, 1, n) * n / 2);\n%! b = A * ones (n, 1);\n%! [M1, M2] = ilu (A + 0.1 * eye (n));\n%! M = M1 * M2;\n%! x = tfqmr (A, b, [], n);\n%! Afcn = @(x) A * x;\n%! x = tfqmr (Afcn, b, [], n);\n%! x = tfqmr (A, b, 1e-6, n, M);\n%! x = tfqmr (A, b, 1e-6, n, M1, M2);\n%! Mfcn = @(z) M \\ z;\n%! x = tfqmr (Afcn, b, 1e-6, n, Mfcn);\n%! M1fcn = @(z) M1 \\ z;\n%! M2fcn = @(z) M2 \\ z;\n%! x = tfqmr (Afcn, b, 1e-6, n, M1fcn, M2fcn);\n%! function y = Ap (A, x, z) # compute A^z * x or (A^z)' * x\n%!    y = x;\n%!    for i = 1:z\n%!      y = A * y;\n%!    endfor\n%!  endfunction\n%! Afcn = @(x, p) Ap (A, x, p);\n%! x = tfqmr (Afcn, b, [], 2*n, [], [], [], 2); # solution of A^2 * x = b\n\n%!demo\n%! n = 10;\n%! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1] * n ^ 2, 1, n))  + ...\n%!     toeplitz (sparse (1, 2, -1, 1, n) * n / 2, ...\n%!     sparse (1, 2, 1, 1, n) * n / 2);\n%! b = A * ones (n, 1);\n%! [M1, M2] = ilu (A + 0.3 * eye (n)); # factorization of A perturbed\n%! M = M1 * M2;\n%!\n%! ## reference solution computed by tfqmr after one iteration\n%! [x_ref, fl] = tfqmr (A, b, [], 1, M);\n%! x_ref\n%!\n%! ## right preconditioning\n%! [y, fl] = tfqmr (A / M, b, [], 1);\n%! x = M \\ y # compare x and x_ref\n"
  },
  {
    "path": "scripts/sparse/treelayout.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{x}, @var{y}] =} treelayout (@var{tree})\n## @deftypefnx {} {[@var{x}, @var{y}] =} treelayout (@var{tree}, @var{permutation})\n## @deftypefnx {} {[@var{x}, @var{y}, @var{h}, @var{s}] =} treelayout (@dots{})\n## treelayout lays out a tree or a forest.\n##\n## The first argument @var{tree} is a vector of predecessors.\n##\n## The optional parameter @var{permutation} is a postorder permutation.\n##\n## The complexity of the algorithm is O(n) in terms of time and memory\n## requirements.\n## @seealso{etreeplot, gplot, treeplot}\n## @end deftypefn\n\nfunction [x, y, h, s] = treelayout (tree, permutation)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! isvector (tree) || rows (tree) != 1 || ! isnumeric (tree)\n          || any (tree > length (tree)) || any (tree < 0))\n    error (\"treelayout: the first input argument must be a vector of predecessors\");\n  endif\n\n  ## Make it a row vector.\n  tree = tree(:)';\n\n  ## The count of nodes of the graph.\n  num_nodes = length (tree);\n  ## The number of children.\n  num_children = zeros (1, num_nodes + 1);\n\n  ## Checking vector of predecessors.\n  for i = 1 : num_nodes\n    if (tree(i) < i)\n      ## This part of graph was checked before.\n      continue;\n    endif\n\n    ## Try to find cicle in this part of graph using modified Floyd's\n    ## cycle-finding algorithm.\n    tortoise = tree(i);\n    hare = tree(tortoise);\n\n    while (tortoise != hare)\n      ## End after finding a cicle or reaching a checked part of graph.\n\n      if (hare < i)\n        ## This part of graph was checked before.\n        break;\n      endif\n\n      tortoise = tree(tortoise);\n      ## Hare will move faster than tortoise so in cicle hare must\n      ## reach tortoise.\n      hare = tree(tree(hare));\n\n    endwhile\n\n    if (tortoise == hare)\n      ## If hare reach tortoise we found circle.\n      error (\"treelayout: vector of predecessors has bad format\");\n    endif\n\n  endfor\n  ## Vector of predecessors has right format.\n\n  for i = 1:num_nodes\n    ## vec_of_child is helping vector which is used to speed up the\n    ## choice of descendant nodes.\n\n    num_children(tree(i)+1) = num_children(tree(i)+1) + 1;\n  endfor\n\n  pos = 1;\n  start = zeros (1, num_nodes+1);\n  xhelp = zeros (1, num_nodes+1);\n  stop = zeros (1, num_nodes+1);\n  for i = 1 : num_nodes + 1\n    start(i) = pos;\n    xhelp(i) = pos;\n    pos += num_children(i);\n    stop(i) = pos;\n  endfor\n\n  if (nargin == 1)\n    for i = 1:num_nodes\n      vec_of_child(xhelp(tree(i)+1)) = i;\n      xhelp(tree(i)+1) = xhelp(tree(i)+1) + 1;\n    endfor\n  else\n    vec_of_child = permutation;\n  endif\n\n  ## The number of \"parent\" (actual) node (its descendants will be\n  ## browse in the next iteration).\n  par_number = 0;\n\n  ## The x-coordinate of the left most descendant of \"parent node\"\n  ## this value is increased in each leaf.\n  left_most = 0;\n\n  ## The level of \"parent\" node (root level is num_nodes).\n  level = num_nodes;\n\n  ## num_nodes - max_ht is the height of this graph.\n  max_ht = num_nodes;\n\n  ## Main stack - each item consists of two numbers - the number of\n  ## node and the number it's of parent node on the top of stack\n  ## there is \"parent node\".\n  stk = [-1, 0];\n\n  ## Number of vertices s in the top-level separator.\n  s = 0;\n  ## Flag which says if we are in top level separator.\n  top_level = 1;\n  ## The top of the stack.\n  while (par_number != -1)\n    if (start(par_number+1) < stop(par_number+1))\n      idx = vec_of_child(start(par_number+1) : stop(par_number+1) - 1);\n    else\n      idx = zeros (1, 0);\n    endif\n\n    ## Add to idx the vector of parent descendants.\n    stk = [stk; [idx', ones(fliplr(size(idx))) * par_number]];\n\n    ## We are in top level separator when we have one child and the\n    ## flag is 1\n    if (columns (idx) == 1 && top_level == 1)\n      s += 1;\n    else\n      ## We aren't in top level separator now.\n      top_level = 0;\n    endif\n    ## If there is not any descendant of \"parent node\":\n    if (stk(end,2) != par_number)\n     left_most += 1;\n     x_r(par_number) = left_most;\n     max_ht = min (max_ht, level);\n     if (length (stk) > 1 && find ((circshift (stk,1) - stk) == 0) > 1\n         && stk(end,2) != stk(end-1,2))\n        ## Return to the nearest branching the position to return\n        ## position is the position on the stack, where should be\n        ## started further search (there are two nodes which has the\n        ## same parent node).\n\n        position = (find ((circshift (stk(:,2), 1) - stk(:,2)) == 0))(end) + 1;\n        par_number_vec = stk(position:end,2);\n\n        ## The vector of removed nodes (the content of stack form\n        ## position to end).\n\n        level += length (par_number_vec);\n\n        ## The level have to be decreased.\n\n        x_r(par_number_vec) = left_most;\n        stk(position:end,:) = [];\n      endif\n\n      ## Remove the next node from \"searched branch\".\n\n      stk(end,:) = [];\n      ## Choose new \"parent node\".\n      par_number = stk(end,1);\n      ## If there is another branch start to search it.\n      if (par_number != -1)\n        y(par_number) = level;\n        x_l(par_number) = left_most + 1;\n      endif\n    else\n\n      ## There were descendants of \"parent nod\" choose the last of\n      ## them and go on through it.\n      level -= 1;\n      par_number = stk(end,1);\n      y(par_number) = level;\n      x_l(par_number) = left_most + 1;\n    endif\n  endwhile\n\n  ## Calculate the x coordinates (the known values are the position\n  ## of most left and most right descendants).\n  x = (x_l + x_r) / 2;\n\n  h = num_nodes - max_ht - 1;\n\nendfunction\n\n\n%!test\n%! % Compute a simple tree layout\n%! [x, y, h, s] = treelayout ([0, 1, 2, 2]);\n%! assert (x, [1.5, 1.5, 2, 1]);\n%! assert (y, [3, 2, 1, 1]);\n%! assert (h, 2);\n%! assert (s, 2);\n\n%!test\n%! % Compute a simple tree layout with defined postorder permutation\n%! [x, y, h, s] = treelayout ([0, 1, 2, 2], [1, 2, 4, 3]);\n%! assert (x, [1.5, 1.5, 1, 2]);\n%! assert (y, [3, 2, 1, 1]);\n%! assert (h, 2);\n%! assert (s, 2);\n\n%!test\n%! % Compute a simple tree layout with defined postorder permutation\n%! [x, y, h, s] = treelayout ([0, 1, 2, 2], [4, 2, 3, 1]);\n%! assert (x, [0, 0, 0, 1]);\n%! assert (y, [0, 0, 0, 3]);\n%! assert (h, 0);\n%! assert (s, 1);\n"
  },
  {
    "path": "scripts/sparse/treeplot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} treeplot (@var{tree})\n## @deftypefnx {} {} treeplot (@var{tree}, @var{node_style}, @var{edge_style})\n## Produce a graph of tree or forest.\n##\n## The first argument is a row vector of parent indices.\n##\n## The optional parameters @var{node_style} and @var{edge_style} define the\n## output plot style.\n##\n## The complexity of the algorithm is O(n) in terms of time and memory\n## requirements.\n## @seealso{etreeplot, gplot}\n## @end deftypefn\n\nfunction treeplot (tree, node_style = \"ko\", edge_style = \"r\")\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (tree) || ! isrow (tree) || any (tree > numel (tree)))\n    error (\"treeplot: TREE must be a row vector of parent indices\");\n  endif\n\n  ##  Verify node_style\n  if (nargin > 1)\n    if (isempty (regexp (node_style, '[ox+*]', 'once')))\n      node_style = [node_style, \"o\"];\n    endif\n  endif\n\n  ## The count of nodes of the graph.\n  num_nodes = numel (tree);\n\n  ## The number of children.\n  num_children = zeros (1, num_nodes+1);\n\n  ## accumarray() is faster than a for loop if num_nodes > 40.\n  for i = 1:num_nodes\n    num_children(tree(i)+1) += 1;\n  endfor\n\n  pos = 1;\n  start = zeros (1, num_nodes+1);\n  xhelp = zeros (1, num_nodes+1);\n  stop = zeros (1, num_nodes+1);\n  for i = 1:num_nodes+1\n    start(i) = pos;\n    xhelp(i) = pos;\n    pos += num_children(i);\n    stop(i) = pos;\n  endfor\n  for i = 1:num_nodes\n    ## VEC_OF_CHILD is intermediate variable used to speed up the\n    ## choice of descendant nodes.\n    vec_of_child(xhelp(tree(i)+1)) = i;\n    xhelp(tree(i)+1) = xhelp(tree(i)+1)+1;\n  endfor\n\n  ## The number of \"parent\" (actual) node.\n  ## (the descendants will be analyzed in the next iteration of loop).\n  par_number = 0;\n\n  ## The x-coordinate of the leftmost descendant of \"parent node\".\n  ## This value is increased in each leaf.\n  left_most = 0;\n\n  ## The level of \"parent\" node (root level is num_nodes).\n  level = num_nodes;\n\n  ## Num_nodes : max_ht is the height of this graph.\n  max_ht = num_nodes;\n\n  ## Main stack : each item consists of two numbers, 1) the number of\n  ## the node and 2) the number of it's parent node.\n  ## On the top of stack there is \"parent node\".\n  stk = [-1, 0];\n\n  ## Stack which is used to draw the graph edge (it has to be an\n  ## uninterrupted line).\n  skelet = 0;\n\n  ## The top of the stack.\n  while (par_number != -1)\n    if (start(par_number+1) < stop(par_number+1))\n      idx = vec_of_child(start(par_number+1):stop(par_number+1)-1);\n    else\n      idx = [];\n    endif\n    ## Add to idx the vector of parent descendants.\n    stk = [stk; [idx', ones(fliplr(size(idx)))*par_number]];\n    ## Add to stack the records relevant to parent descendants.\n    if (par_number != 0)\n      skelet = [skelet; ([ones(size(idx))*par_number; idx])(:)];\n    endif\n\n    ## If there is not any descendant of \"parent node\":\n    if (stk(end,2) != par_number)\n      left_most += 1;\n      x_coordinate_r(par_number) = left_most;\n      max_ht = min (max_ht, level);\n      if (! isempty (stk) && find ((circshift (stk,1) - stk) == 0) > 1\n          && stk(end,2) != stk(end-1,2))\n        ## Return to the nearest branching the position to return\n        ## position is the position on the stack, where should be\n        ## started further search (there are two nodes which has the\n        ## same parent node).\n        position = (find ((circshift (stk(:,2),1) - stk(:,2)) == 0))(end) + 1;\n        par_number_vec = stk(position:end,2);\n        ## The vector of removed nodes (the content of stack from\n        ## position to end).\n        skelet = [skelet; flipud(par_number_vec)];\n        level += length (par_number_vec);\n        ## The level have to be decreased.\n        x_coordinate_r(par_number_vec) = left_most;\n        stk(position:end,:) = [];\n      endif\n      ## Remove the next node from \"searched branch\".\n      stk(end,:) = [];\n      ## Choose new \"parent node\".\n      par_number = stk(end,1);\n      ## If there is another branch start to search it.\n      if (par_number != -1)\n        skelet = [skelet; stk(end,2); par_number];\n        y_coordinate(par_number) = level;\n        x_coordinate_l(par_number) = left_most + 1;\n      endif\n    else\n      ## There were descendants of \"parent node\", choose the last of\n      ## them and go through it.\n      level -= 1;\n      par_number = stk(end,1);\n      y_coordinate(par_number) = level;\n      x_coordinate_l(par_number) = left_most + 1;\n    endif\n  endwhile\n\n  ## Calculate the x coordinates (the known values are the position\n  ## of most left and most right descendants).\n  x_coordinate = (x_coordinate_l + x_coordinate_r) / 2;\n\n  ## FIXME: We should probably stuff all the arguments into a cell\n  ##        array and make a single call to plot here so we can avoid\n  ##        setting the hold state...\n\n  hold_is_on = ishold ();\n  unwind_protect\n    ## Plot graph nodes.\n    plot (x_coordinate, y_coordinate, node_style);\n\n    ## Helping command - usable for plotting edges\n    skelet = [skelet; 0];\n\n    ## Draw graph edges.\n    idx = find (skelet == 0);\n\n    hold (\"on\");\n    ## Plot each tree component in one loop.\n    for i = 2:length (idx)\n      ## Tree component start.\n      istart = idx(i-1) + 1;\n      ## Tree component end.\n      istop = idx(i) - 1;\n      if (istop - istart < 1)\n        continue;\n      endif\n      plot (x_coordinate(skelet(istart:istop)),\n            y_coordinate(skelet(istart:istop)), edge_style);\n    endfor\n\n    ## Set axis and graph size.\n    axis ([0.5, left_most+0.5, max_ht-0.5, num_nodes-0.5], \"nolabel\");\n\n  unwind_protect_cleanup\n    if (! hold_is_on)\n      hold (\"off\");\n    endif\n  end_unwind_protect\n\nendfunction\n\n\n%!demo\n%! % Plot a simple tree plot\n%! clf;\n%! treeplot ([2 4 2 0 6 4 6]);\n\n%!demo\n%! % Plot a simple tree plot defining the edge and node styles\n%! clf;\n%! treeplot ([2 4 2 0 6 4 6], \"b+\", \"g\");\n\n## Test input validation\n%!error <Invalid call> treeplot ()\n%!error <TREE must be a row vector> treeplot (\"ABC\")\n%!error <TREE must be a row vector> treeplot ([1;2;3])\n%!error <TREE must be a row vector> treeplot ([1,2,4])\n"
  },
  {
    "path": "scripts/specfun/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/specfun/beta.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} beta (@var{a}, @var{b})\n## Compute the Beta function for real inputs @var{a} and @var{b}.\n##\n## The Beta function definition is\n## @tex\n## $$\n##  B (a, b) = {\\Gamma (a) \\Gamma (b) \\over \\Gamma (a + b)}.\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## beta (a, b) = gamma (a) * gamma (b) / gamma (a + b).\n## @end example\n##\n## @end ifnottex\n##\n## The Beta function can grow quite large and it is often more useful to work\n## with the logarithm of the output rather than the function directly.\n## @xref{XREFbetaln,,betaln}, for computing the logarithm of the Beta\n## function in an efficient manner.\n## @seealso{betaln, betainc, betaincinv}\n## @end deftypefn\n\nfunction y = beta (a, b)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! isreal (a) || ! isreal (b))\n    error (\"beta: A and B must be real\");\n  elseif (! size_equal (a, b) && numel (a) != 1 && numel (b) != 1)\n    error (\"beta: A and B must have consistent sizes\");\n  endif\n\n  y = real (exp (gammaln (a) + gammaln (b) - gammaln (a+b)));\n\nendfunction\n\n\n%!test\n%! a = [1, 1.5, 2, 3];\n%! b = [4, 3, 2, 1];\n%! v1 = beta (a, b);\n%! v2 = beta (b, a);\n%! v3 = gamma (a).*gamma (b) ./ gamma (a+b);\n%! assert (v1, v2, sqrt (eps));\n%! assert (v2, v3, sqrt (eps));\n\n%!assert (beta (1, 1), 1)\n\n%!test\n%! a = 2:10;\n%! tol = 10 * max (a) * eps;\n%! assert (-a, beta (-1./a, 1), tol);\n%! assert (-a, beta (1, -1./a), tol);\n\n%!test\n%! a = 0.25 + (0:5) * 0.5;\n%! tol = 10 * max (a) * eps;\n%! assert (zeros (size (a)), beta (a, -a), tol);\n%! assert (zeros (size (a)), beta (-a, a), tol);\n\n%!error <Invalid call> beta ()\n%!error <Invalid call> beta (1)\n%!error <A and B must be real> beta (1i, 2)\n%!error <A and B must be real> beta (2, 1i)\n%!error <A and B must have consistent sizes> beta ([1 2], [1 2 3])\n%!error <A and B must have consistent sizes> beta ([1 2 3], [1 2])\n%!error <A and B must have consistent sizes> beta ([1 2 3], [1 2 3]')\n"
  },
  {
    "path": "scripts/specfun/betainc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{I} =} betainc (@var{x}, @var{a}, @var{b})\n## @deftypefnx {} {@var{I} =} betainc (@var{x}, @var{a}, @var{b}, @var{tail})\n## Compute the incomplete beta function.\n##\n## This is defined as\n## @tex\n## $$\n## I_x (a, b) = {1 \\over {B(a,b)}} \\displaystyle{\\int_0^x t^{a-1} (1-t)^{b-1} dt}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##                           x\n##                          /\n##                  1       |\n## I_x (a, b) = ----------  | t^(a-1) (1-t)^(b-1) dt\n##              beta (a,b)  |\n##                          /\n##                         0\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## with real @var{x} in the range [0,1].  The inputs @var{a} and @var{b} must\n## be real and strictly positive (> 0).  If one of the inputs is not a scalar\n## then the other inputs must be scalar or of compatible dimensions.\n##\n## By default, @var{tail} is @qcode{\"lower\"} and the incomplete beta function\n## integrated from 0 to @var{x} is computed.  If @var{tail} is @qcode{\"upper\"}\n## then the complementary function integrated from @var{x} to 1 is calculated.\n## The two choices are related by\n##\n## betainc (@var{x}, @var{a}, @var{b}, @qcode{\"upper\"}) =\n## 1 - betainc (@var{x}, @var{a}, @var{b}, @qcode{\"lower\"}).\n##\n## @code{betainc} uses a more sophisticated algorithm than subtraction to\n## get numerically accurate results when the @qcode{\"lower\"} value is small.\n##\n## Reference: @nospell{A. Cuyt, V. Brevik Petersen, B. Verdonk, H. Waadeland,\n## W.B. Jones}, @cite{Handbook of Continued Fractions for Special Functions},\n## @w{ch.@: 18}.\n##\n## @seealso{beta, betaincinv, betaln}\n## @end deftypefn\n\nfunction I = betainc (x, a, b, tail = \"lower\")\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  [err, x, a, b] = common_size (x, a, b);\n  if (err > 0)\n    error (\"betainc: X, A, and B must be of common size or scalars\");\n  endif\n\n  if (iscomplex (x) || iscomplex (a) || iscomplex (b))\n    error (\"betainc: all inputs must be real\");\n  endif\n\n  if (! (isnumeric (x) && isnumeric (a) && isnumeric (b)))\n    error (\"betainc: all inputs must be numeric\");\n  endif\n\n  ## Remember original shape of data, but convert to column vector for calcs.\n  orig_sz = size (x);\n  x = x(:);\n  a = a(:);\n  b = b(:);\n\n  switch (tolower (tail))\n    case \"lower\"\n      lower_upper_flag = true;\n    case \"upper\"\n      lower_upper_flag = false;\n    otherwise\n      error (\"betainc: invalid value for TAIL\");\n  endswitch\n\n  if (any ((x < 0) | (x > 1)))\n    error (\"betainc: X must be in the range [0, 1]\");\n  endif\n\n  if (any (a <= 0))\n    error (\"betainc: A must be strictly positive\");\n  endif\n\n  if (any (b <= 0))\n    error (\"betainc: B must be strictly positive\");\n  endif\n\n  ## Initialize output array with output class matching x, shortcut trivial\n  ## case of integer class x.\n  if (isinteger (x))\n    ## For x = 0 or 1, the output always reduces to 0 or 1.  Input validation\n    ## ensures all interger inputs must be 0 or 1.\n    I = x;\n    return;\n  else\n    I = zeros (size (x), class (x));\n  endif\n\n  ## Convert a,b to floating point if necessary.\n  if (isinteger (a))\n    a = double (a);\n  endif\n  if (isinteger (b))\n    b = double (b);\n  endif\n\n  ## If any of the arguments is single then the output should be as well.\n  if (strcmp (class (x), \"single\") || strcmp (class (a), \"single\")\n      || strcmp (class (b), \"single\"))\n    a = single (a);\n    b = single (b);\n    x = single (x);\n  endif\n\n\n  ## Trivial cases (long code here trades memory for speed)\n  x_trivial = (x == 0 | x == 1);\n  a_one = (a == 1);\n  b_one = (b == 1);\n  a_b_x_triv = (a_one & b_one) | x_trivial;\n  a_not_one = ! a_one;\n  b_not_one = ! b_one;\n  non_trivial = a_not_one & b_not_one & ! x_trivial;\n  a_one &= b_not_one | x_trivial;\n  b_one &= a_not_one | x_trivial;\n\n  if (lower_upper_flag)\n    I(a_b_x_triv) = x(a_b_x_triv);\n    ## See bug #62329.\n    ## equivalent to \"1 - (1 - x(a_one)) .^ b(a_one)\", but less roundoff error\n    I(a_one) = - expm1 (log1p (- x(a_one)) .* b(a_one));\n    I(b_one) = x(b_one) .^ a(b_one);\n  else\n    I(a_b_x_triv) = 1 - x(a_b_x_triv);\n    ## equivalent to \"(1 - x(a_one)) .^ b(a_one)\", but less roundoff error\n    I(a_one) = exp (log1p (- x(a_one)) .* b(a_one));\n    ## equivalent to \"1 - x(b_one) .^ a(b_one)\", but less roundoff error\n    I(b_one) = - expm1 (log (x(b_one)) .* a(b_one));\n  endif\n\n  ## Non-Trivial cases\n  ## In the following, we use the fact that the continued fraction Octave uses\n  ## is more efficient when x <= a / (a + b).  Moreover, to compute the upper\n  ## version, which is defined as I_x(a,b,\"upper\") = 1 - I_x(a,b) we use the\n  ## property I_x(a,b) + I_(1-x) (b,a) = 1.\n\n  x = x(non_trivial);\n  a = a(non_trivial);\n  b = b(non_trivial);\n\n  if (lower_upper_flag)\n    fflag = (x > a./(a + b));\n    x(fflag) = 1 - x(fflag);\n    [a(fflag), b(fflag)] = deal (b(fflag), a(fflag));\n  else\n    fflag = (x < (a ./ (a + b)));\n    x(! fflag) = 1 - x(! fflag);\n    [a(! fflag), b(! fflag)] = deal (b(! fflag), a(! fflag));\n  endif\n\n  f = zeros (size (x), class (x));\n\n  ## Continued fractions: CPVWJ, formula 18.5.20, modified Lentz algorithm\n  ## implemented in a separate .cc file.  This particular continued fraction\n  ## gives (B(a,b) * I_x(a,b)) / (x^a * (1-x)^b).\n\n  f = __betainc__ (x, a, b);\n\n  ## Divide continued fraction by B(a,b) / (x^a * (1-x)^b) to obtain I_x(a,b).\n  y_nt = a .* log (x) + b .* log1p (-x) ...\n         + (gammaln (a + b) - gammaln (a) - gammaln (b)) + log (f);\n  y_nt = real (exp (y_nt));\n  y_nt(fflag) = 1 - y_nt(fflag);\n\n  I(non_trivial) = y_nt;\n\n  ## Restore original shape\n  I = reshape (I, orig_sz);\n\nendfunction\n\n\n## Double precision\n%!test\n%! a = [1, 1.5, 2, 3];\n%! b = [4, 3, 2, 1];\n%! v1 = betainc (1, a, b);\n%! v2 = [1,1,1,1];\n%! x = [.2, .4, .6, .8];\n%! v3 = betainc (x, a, b);\n%! v4 = 1 - betainc (1-x, b, a);\n%! assert (v1, v2, sqrt (eps));\n%! assert (v3, v4, sqrt (eps));\n\n## Single precision\n%!test\n%! a = single ([1, 1.5, 2, 3]);\n%! b = single ([4, 3, 2, 1]);\n%! v1 = betainc (1, a, b);\n%! v2 = single ([1,1,1,1]);\n%! x = single ([.2, .4, .6, .8]);\n%! v3 = betainc (x, a, b);\n%! v4 = 1 - betainc (1-x, b, a);\n%! assert (v1, v2, sqrt (eps (\"single\")));\n%! assert (v3, v4, sqrt (eps (\"single\")));\n\n## Mixed double/single precision\n%!test\n%! a = single ([1, 1.5, 2, 3]);\n%! b = [4, 3, 2, 1];\n%! v1 = betainc (1,a,b);\n%! v2 = single ([1,1,1,1]);\n%! x = [.2, .4, .6, .8];\n%! v3 = betainc (x, a, b);\n%! v4 = 1 - betainc (1. - x, b, a);\n%! assert (v1, v2, sqrt (eps (\"single\")));\n%! assert (v3, v4, sqrt (eps (\"single\")));\n\n%!test <*51157>\n%! y = betainc ([0.00780;0.00782;0.00784],250.005,49750.995);\n%! y_ex = [0.999999999999989; 0.999999999999992; 0.999999999999995];\n%! assert (y, y_ex, -1e-14);\n\n%!assert (betainc (0.001, 20, 30), 2.750687665855991e-47, -3e-14)\n%!assert (betainc (0.0001, 20, 30), 2.819953178893307e-67, -7e-14)\n%!assert <*54383> (betainc (0.99, 20, 30, \"upper\"),\n%!                 1.5671643161872703e-47, -7e-14)\n%!assert (betainc (0.999, 20, 30, \"upper\"), 1.850806276141535e-77, -7e-14)\n%!assert (betainc (0.5, 200, 300), 0.9999964565197356, -1e-15)\n%!assert (betainc (0.5, 200, 300, \"upper\"), 3.54348026439253e-06, -3e-13)\n\n## Test trivial values\n%!test\n%! [a,b] = ndgrid (linspace (1e-4, 100, 20), linspace (1e-4, 100, 20));\n%! assert (betainc (0, a, b), zeros (20));\n%! assert (betainc (1, a, b), ones (20));\n%! assert (betainc (0, a, b, \"upper\"), ones (20));\n%! assert (betainc (1, a, b, \"upper\"), zeros (20));\n%! assert (betainc ([0 0.5 1], 2, 2), [0 0.5 1], eps);\n%! assert (betainc ([0 0.5 1], 2, 2, \"upper\"), [1 0.5 0], eps);\n\n%!test <*34405>\n%! assert (betainc (NaN, 1, 2), NaN);\n%! assert (betainc (0.5, 1, Inf), 1);\n\n%!test <*62329>\n%! assert (betainc (2e-20, 1, 0.5), 1e-20, -1e-15);\n%! assert (betainc (2e-5, 1, 0.5), 2e-5 / (1 + sqrt (1 - 2e-5)), -1e-15);\n%! assert (betainc (0.99, 1, 0.5, \"upper\"), 0.1, -1e-15);\n%! assert (betainc (0.99, 0.5, 1, \"upper\"), - expm1 (log (0.99)/2), -1e-15);\n\n## Test input validation\n%!error <Invalid call> betainc ()\n%!error <Invalid call> betainc (1)\n%!error <Invalid call> betainc (1,2)\n%!error <must be of common size or scalars> betainc (ones (2,2), ones (1,2), 1)\n%!error <all inputs must be real> betainc (0.5i, 1, 2)\n%!error <all inputs must be real> betainc (0, 1i, 1)\n%!error <all inputs must be real> betainc (0, 1, 1i)\n%!error <all inputs must be numeric> betainc (char (1), 1, 2)\n%!error <all inputs must be numeric> betainc (0, char (1), 1)\n%!error <all inputs must be numeric> betainc (0, 1, char (1))\n%!error <X must be in the range \\[0, 1\\]> betainc (-0.1,1,1)\n%!error <X must be in the range \\[0, 1\\]> betainc (1.1,1,1)\n%!error <X must be in the range \\[0, 1\\]>\n%! x = ones (1, 1, 2);\n%! x(1,1,2) = -1;\n%! betainc (x,1,1);\n%!error <A must be strictly positive> betainc (0.5,0,1)\n%!error <A must be strictly positive>\n%! a = ones (1, 1, 2);\n%! a(1,1,2) = 0;\n%! betainc (1,a,1);\n%!error <B must be strictly positive> betainc (0.5,1,0)\n%!error <B must be strictly positive>\n%! b = ones (1, 1, 2);\n%! b(1,1,2) = 0;\n%! betainc (1,1,b);\n%!error <invalid value for TAIL> betainc (1,2,3, \"foobar\")\n"
  },
  {
    "path": "scripts/specfun/betaincinv.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} betaincinv (@var{y}, @var{a}, @var{b})\n## @deftypefnx {} {@var{x} =} betaincinv (@var{y}, @var{a}, @var{b}, \"lower\")\n## @deftypefnx {} {@var{x} =} betaincinv (@var{y}, @var{a}, @var{b}, \"upper\")\n## Compute the inverse of the normalized incomplete beta function.\n##\n## The normalized incomplete beta function is defined as\n## @tex\n## $$\n##  I_x (a, b) = {1 \\over {B(a,b)}} \\displaystyle{\\int_0^x t^{a-1} (1-t)^{b-1} dt}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##                           x\n##                          /\n##                  1       |\n## I_x (a, b) = ----------  | t^(a-1) (1-t)^(b-1) dt\n##              beta (a,b)  |\n##                          /\n##                         0\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## If two inputs are scalar, then @code{betaincinv (@var{y}, @var{a}, @var{b})}\n## is returned for each of the other inputs.\n##\n## If two or more inputs are not scalar, the sizes of them must agree, and\n## @code{betaincinv} is applied element-by-element.\n##\n## The variable @var{y} must be in the interval [0,1], while @var{a} and\n## @var{b} must be real and strictly positive.\n##\n## By default, @var{tail} is @qcode{\"lower\"} and the inverse of the incomplete\n## beta function integrated from 0 to @var{x} is computed.  If @var{tail} is\n## @qcode{\"upper\"} then the complementary function integrated from @var{x} to 1\n## is inverted.\n##\n## The function is computed by standard Newton's method, by solving\n## @tex\n## $$\n##  y - I_x (a, b) = 0\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @var{y} - betainc (@var{x}, @var{a}, @var{b}) = 0\n## @end example\n##\n## @end ifnottex\n##\n## @seealso{betainc, beta, betaln}\n## @end deftypefn\n\nfunction x = betaincinv (y, a, b, tail = \"lower\")\n\n  if (nargin < 3)\n    print_usage ();\n  endif\n\n  [err, y, a, b] = common_size (y, a, b);\n  if (err > 0)\n    error (\"betaincinv: Y, A, and B must be of common size or scalars\");\n  endif\n\n  if (! (isfloat (y) && isfloat (a) && isfloat (b)\n         && isreal (y) && isreal (a) && isreal (b)))\n    error (\"betaincinv: Y, A, and B must be real, floating point values\");\n  endif\n\n  ## Remember original shape of data, but convert to column vector for calcs.\n  orig_sz = size (y);\n  y = y(:);\n  a = a(:);\n  b = b(:);\n\n  if (any ((y < 0) | (y > 1)))\n    error (\"betaincinv: Y must be in the range [0, 1]\");\n  endif\n\n  if (any (a <= 0))\n    error (\"betaincinv: A must be strictly positive\");\n  endif\n\n  if (any (b <= 0))\n    error (\"betaincinv: B must be strictly positive\");\n  endif\n\n  ## If any of the arguments is single then the output should be as well.\n  if (isa (y, \"single\") || isa (a, \"single\") || isa (b, \"single\"))\n    y = single (y);\n    a = single (a);\n    b = single (b);\n  endif\n\n  if (strcmpi (tail, \"lower\"))\n    ys = y;\n  elseif (strcmpi (tail, \"upper\"))\n    ys = 1 - y;  # only for computation of initial points, no loss of accuracy\n  else\n    error (\"betaincinv: invalid value for TAIL\");\n  endif\n\n  ## Choose starting point for Newton's Method to guarantee convergence.\n  ## If (a-1)*(b-1) > 0, F has a point of inflection at x = (a-1)/(a+b-2).\n  ## In this case, it is convex on (0,x) and concave on (x,1) if a>1; otherwise\n  ## it is the other way round.  If (a-1)*(b-1) <= 0, there is no point of\n  ## inflection, and it is everywhere convex for a>1 and concave otherwise.\n  ## We thus choose our starting x for the Newton iterations so that we stay\n  ## within a region of constant sign of curvature and on the correct side of\n  ## the eventual solution, guaranteeing convergence.  Curvatures above are to\n  ## be understood under the condition tail==\"lower\".\n\n  ## Initialize output array\n  x = x_i = y_i = zeros (size (y), class (y));\n\n  ## Have point of inflection\n  idx = find ((a - 1) .* (b - 1) > 0);\n  if (! isempty (idx))\n    x_i(idx) = (a(idx) - 1) ./ (a(idx) + b(idx) - 2);\n    y_i(idx) = betainc (x_i(idx), a(idx), b(idx));\n  endif\n\n  ## Converge outwards\n  tmpidx = find (a(idx) > 1);\n  if (! isempty (tmpidx))\n    x(idx(tmpidx)) = x_i(idx(tmpidx));\n  endif\n  ## Converge inwards\n  ## To the left of inflection point\n  tmpidx = idx(find ((a(idx) <= 1) & (y_i(idx) >= ys(idx))));\n  if (! isempty (tmpidx))\n    x(tmpidx) = (ys(tmpidx) ./ y_i(tmpidx)).^(1 ./ a(tmpidx)) .* x_i(tmpidx);\n  endif\n  ## To the right of inflection point\n  tmpidx = idx(find ((a(idx) <= 1) & (y_i(idx) < ys(idx))));\n  if (! isempty (tmpidx))\n    x(tmpidx) = 1 - ...\n                ((1 - ys(tmpidx)) ./ (1 - y_i(tmpidx))).^(1 ./ b(tmpidx)) ...\n                .* (1 - x_i(tmpidx));\n  endif\n\n  ## Have no point of inflection\n  idx = find ((a - 1) .* (b - 1) <= 0);\n\n  ## Negative curvature\n  tmpidx = idx(find (a(idx) < 1));\n  if (! isempty (tmpidx))\n    x(tmpidx) = (ys(tmpidx) .* beta (a(tmpidx), b(tmpidx)) .* a(tmpidx)) ...\n                .^ (1 ./ a(tmpidx));\n  endif\n  ## Positive curvature\n  tmpidx = idx(find (a(idx) >= 1));\n  if (! isempty (tmpidx))\n    x(tmpidx) = 1 - ...\n                ((1 - ys(tmpidx)) .* beta (a(tmpidx), b(tmpidx)) .* b(tmpidx)) ...\n                .^ (1 ./ b(tmpidx));\n  endif\n\n  ## Cleanup memory before continuing\n  clear ys x_i y_i idx tmpidx\n\n  if (strcmpi (tail, \"lower\"))\n    x(y == 0) = 0;\n    x(y == 1) = 1;\n    F = @(x, a, b, y) y - betainc (x, a, b);\n    JF = @(x, a, b, Bln) -exp ((a-1) .* log (x) + (b-1) .* log1p (-x) - Bln);\n  else\n    x(y == 0) = 1;\n    x(y == 1) = 0;\n    F = @(x, a, b, y) y - betainc (x, a, b, \"upper\");\n    JF = @(x, a, b, Bln) exp ((a-1) .* log (x) + (b-1) .* log1p (-x) - Bln);\n  endif\n\n  x = newton_method (F, JF, x, a, b, y);\n\n  ## Restore original shape\n  x = reshape (x, orig_sz);\n\nendfunction\n\nfunction x = newton_method (F, JF, x, a, b, y)\n\n  Bln = betaln (a, b);\n  ## Exclude special values that have been already computed.\n  todo = find ((y != 0) & (y != 1));\n  step = -F (x(todo), a(todo), b(todo), y(todo)) ./ ...\n         JF (x(todo), a(todo), b(todo), Bln(todo));\n  x_old = x(todo);\n  x(todo) += step;\n  dx = x(todo) - x_old;\n  idx = (dx != 0);\n  todo = todo(idx);\n  dx_old = dx(idx);\n  while (! isempty (todo))\n    step = -F (x(todo), a(todo), b(todo), y(todo)) ./ ...\n           JF (x(todo), a(todo), b(todo), Bln(todo));\n    x_old = x(todo);\n    x(todo) += step;\n    dx = x(todo) - x_old;\n    idx = (abs (dx) < abs (dx_old));  # Converging if dx is getting smaller\n    todo = todo(idx);\n    dx_old = dx(idx);\n  endwhile\n\nendfunction\n\n\n%!test\n%! x = linspace (0.1, 0.9, 11);\n%! a = [2, 3, 4];\n%! [x,a,b] = ndgrid (x,a,a);\n%! xx = betaincinv (betainc (x, a, b), a, b);\n%! assert (xx, x, 3e-15);\n\n%!test\n%! x = linspace (0.1, 0.9, 11);\n%! a = [2, 3, 4];\n%! [x,a,b] = ndgrid (x,a,a);\n%! xx = betaincinv (betainc (x, a, b, \"upper\"), a, b, \"upper\");\n%! assert (xx, x, 3e-15);\n\n%!test\n%! x = linspace (0.1, 0.9, 11);\n%! a = [0.1:0.1:1];\n%! [x,a,b] = ndgrid (x,a,a);\n%! xx = betaincinv (betainc (x, a, b), a, b);\n%! assert (xx, x, 5e-15);\n\n%!test\n%! x = linspace (0.1, 0.9, 11);\n%! a = [0.1:0.1:1];\n%! [x,a,b] = ndgrid (x,a,a);\n%! xx = betaincinv (betainc (x, a, b, \"upper\"), a, b, \"upper\");\n%! assert (xx, x, 24*eps);\n\n## Test the conservation of the input class\n%!assert (class (betaincinv (0.5, 1, 1)), \"double\")\n%!assert (class (betaincinv (single (0.5), 1, 1)), \"single\")\n%!assert (class (betaincinv (0.5, single (1), 1)), \"single\")\n%!assert (class (betaincinv (0.5, 1, single (1))), \"single\")\n\n## Extreme values for y, a, b that really test the algorithm\n%!assert (betaincinv ([0, 1], 1, 3), [0, 1])\n%!assert <*60528> (betaincinv (1e-6, 1, 3), 3.3333344444450617e-7, 2*eps)\n%!assert <*60528> (betaincinv (1-1e-6, 3, 1), 0.9999996666665555, 2*eps)\n%!assert (betainc (betaincinv (0.9, 1e-3, 1), 1e-3, 1), 0.9, 2*eps)\n%!assert (betainc (betaincinv (.01, 1, 1e-3), 1, 1e-3), .01, 6*eps)\n%!assert (betainc (betaincinv (0.5, 100, 1), 100, 1), 0.5, 8*eps)\n%!assert (betainc (betaincinv (0.5, 1, 100), 1, 100), 0.5, 22*eps)\n%!assert (betaincinv ([0, 1], 1, 3, \"upper\"), [1, 0])\n%!assert <*60528> (betaincinv (1e-6, 1, 3, \"upper\"), 0.99, 2*eps)\n%!assert <*60528> (betaincinv (1-1e-6, 3, 1,\"upper\"), .01, 250*eps)\n%!assert (betainc (betaincinv (0.1, 1e-3, 1, \"upper\"), 1e-3, 1, \"upper\"),\n%!        0.1, 2*eps)\n%!assert (betainc (betaincinv (.99, 1, 1e-3, \"upper\"), 1, 1e-3, \"upper\"),\n%!        .99, 6*eps)\n%!assert (betainc (betaincinv (0.5, 100, 1, \"upper\"), 100, 1, \"upper\"),\n%!        0.5, 8*eps)\n%!assert (betainc (betaincinv (0.5, 1, 100, \"upper\"), 1, 100, \"upper\"),\n%!        0.5, 22*eps)\n\n## Test input validation\n%!error <Invalid call> betaincinv ()\n%!error <Invalid call> betaincinv (1)\n%!error <Invalid call> betaincinv (1,2)\n%!error <must be of common size or scalars>\n%! betaincinv (ones (2,2), ones (1,2), 1);\n%!error <must be .* floating point> betaincinv ('a', 1, 2)\n%!error <must be .* floating point> betaincinv (0, int8 (1), 1)\n%!error <must be .* floating point> betaincinv (0, 1, true)\n%!error <must be real> betaincinv (0.5i, 1, 2)\n%!error <must be real> betaincinv (0, 1i, 1)\n%!error <must be real> betaincinv (0, 1, 1i)\n%!error <Y must be in the range \\[0, 1\\]> betaincinv (-0.1,1,1)\n%!error <Y must be in the range \\[0, 1\\]> betaincinv (1.1,1,1)\n%!error <Y must be in the range \\[0, 1\\]>\n%! y = ones (1, 1, 2);\n%! y(1,1,2) = -1;\n%! betaincinv (y,1,1);\n%!error <A must be strictly positive> betaincinv (0.5,0,1)\n%!error <A must be strictly positive>\n%! a = ones (1, 1, 2);\n%! a(1,1,2) = 0;\n%! betaincinv (1,a,1);\n%!error <B must be strictly positive> betaincinv (0.5,1,0)\n%!error <B must be strictly positive>\n%! b = ones (1, 1, 2);\n%! b(1,1,2) = 0;\n%! betaincinv (1,1,b);\n%!error <invalid value for TAIL> betaincinv (1,2,3, \"foobar\")\n"
  },
  {
    "path": "scripts/specfun/betaln.m",
    "content": "########################################################################\n##\n## Copyright (C) 1998-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{lnb} =} betaln (@var{a}, @var{b})\n## Compute the natural logarithm of the Beta function for real inputs @var{a}\n## and @var{b}.\n##\n## @code{betaln} is defined as\n## @tex\n## $$\n##  {\\rm betaln} (a, b) = \\ln (B (a,b)) \\equiv \\ln ({\\Gamma (a) \\Gamma (b) \\over \\Gamma (a + b)}).\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## betaln (a, b) = log (beta (a, b))\n## @end example\n##\n## @end ifnottex\n## and is calculated in a way to reduce the occurrence of underflow.\n##\n## The Beta function can grow quite large and it is often more useful to work\n## with the logarithm of the output rather than the function directly.\n## @seealso{beta, betainc, betaincinv, gammaln}\n## @end deftypefn\n\nfunction lnb = betaln (a, b)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! isreal (a) || ! isreal (b))\n    error (\"betaln: A and B must be real\");\n  endif\n\n  lnb = gammaln (a) + gammaln (b) - gammaln (a + b);\n\nendfunction\n\n\n%!assert (betaln (3,4), log (beta (3,4)), eps)\n\n## Test input validation\n%!error <Invalid call> betaln ()\n%!error <Invalid call> betaln (1)\n%!error <A and B must be real> betaln (1i, 2)\n%!error <A and B must be real> betaln (2, 1i)\n"
  },
  {
    "path": "scripts/specfun/cosint.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} cosint (@var{x})\n## Compute the cosine integral function:\n## @tex\n## $$\n## {\\rm Ci} (x) = - \\int_x^\\infty {{\\cos (t)} \\over t} dt\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##             +oo\n##            /\n## Ci (x) = - | (cos (t)) / t dt\n##            /\n##           x\n## @end group\n## @end example\n##\n## @end ifnottex\n## An equivalent definition is\n## @tex\n## $$\n## {\\rm Ci} (x) = \\gamma + \\log (x) + \\int_0^x {{\\cos (t) - 1} \\over t} dt\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##                              x\n##                             /\n##                             |  cos (t) - 1\n## Ci (x) = gamma + log (x) +  | -------------  dt\n##                             |        t\n##                             /\n##                            0\n## @end group\n## @end example\n##\n## @end ifnottex\n## Reference:\n##\n## @nospell{M. Abramowitz and I.A. Stegun},\n## @cite{Handbook of Mathematical Functions}, 1964.\n##\n## @seealso{sinint, expint, cos}\n##\n## @end deftypefn\n\nfunction y = cosint (x)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x))\n    error (\"cosint: X must be numeric\");\n  endif\n\n  ## Convert to floating point if necessary\n  if (isinteger (x))\n    x = double (x);\n  endif\n\n  ## Convert to column vector\n  orig_sz = size (x);\n  if (iscomplex (x))\n    ## Work around reshape which narrows to real (bug #52953)\n    x = complex (real (x)(:), imag (x)(:));\n  else\n    x = x(:);\n  endif\n\n  ## Initialize the result\n  y = zeros (size (x), class (x));\n  tol = eps (class (x));\n\n  todo = true (size (x));\n\n  ## Special values\n  y(x == Inf) = 0;\n  y((x == -Inf) & ! signbit (imag (x))) = 1i * pi;\n  y((x == -Inf) &  signbit (imag (x))) = -1i * pi;\n\n  todo(isinf (x)) = false;\n\n  ## For values large in modulus, but not in the range (-oo,0), we use the\n  ## relation with expint.\n\n  flag_large = (abs (x) > 2);\n  xx = x(flag_large);\n\n  ## Abramowitz, relation 5.2.20\n  ii_sw = (real (xx) <= 0 & imag (xx) < 0);\n  xx(ii_sw) = conj (xx(ii_sw));\n  ii_nw = (real (xx) < 0);\n  xx(ii_nw) *= -1;\n  yy = -0.5 * (expint (1i * xx) + expint (-1i * xx));\n  yy(ii_nw) += 1i * pi;\n  yy(ii_sw) = conj (yy(ii_sw));\n  y(todo & flag_large) = yy;\n\n  todo(flag_large) = false;\n\n  ## For values small in modulus, use the series expansion (also near (-oo, 0])\n  if (iscomplex (x))\n    ## indexing can lose imag part: if it was -0, we could end up on the\n    ## wrong right side of the branch cut along the negative real axis.\n    xx = complex (real (x)(todo), imag (x)(todo));\n  else\n    xx = x(todo);\n  endif\n  ssum = - xx .^ 2 / 4; # First term of the series expansion\n  ## FIXME: This is way more precision than a double value can hold.\n  gma = 0.57721566490153286060651209008; # Euler gamma constant\n  yy = gma + log (complex (xx)) + ssum;  # log (complex (Z)) handles signed zero\n  flag_sum = true (nnz (todo), 1);\n  it = 0;\n  maxit = 300;\n  while (any (flag_sum) && (++it < maxit))\n    ssum .*= - xx .^ 2 * (2 * it) / ((2 * it + 2) ^ 2 * (2 * it + 1));\n    yy(flag_sum) += ssum (flag_sum);\n    flag_sum = (abs (ssum) >= tol);\n  endwhile\n  y(todo) = yy;\n\n  ## Clean up values which are purely real\n  flag_neg_zero_imag = (real (x) < 0) & (imag (x) == 0) & signbit (imag (x));\n  y(flag_neg_zero_imag) = complex (real (y(flag_neg_zero_imag)), -pi);\n\n  ## Restore original shape\n  y = reshape (y, orig_sz);\n\nendfunction\n\n\n%!assert (cosint (1.1), 0.38487337742465081550, 2 * eps)\n\n%!test\n%! x = [2, 3, pi; exp(1), 5, 6];\n%! A = cosint (x);\n%! B = [0.422980828774864996, 0.119629786008000328, 0.0736679120464254860; ...\n%!      0.213958001340379779, -0.190029749656643879, -0.0680572438932471262];\n%! assert (A, B, -5e-15);\n\n%!assert (cosint (0), - Inf)\n%!assert (cosint (-0), -inf + 1i*pi)\n%!assert (cosint (complex (-0, 0)), -inf + 1i*pi)\n%!assert (cosint (complex (-0, -0)), -inf - 1i*pi)\n%!assert (cosint (inf), 0)\n%!assert (cosint (-inf), 1i * pi)\n%!assert (cosint (complex (-inf, -0)), -1i * pi)\n%!assert (isnan (cosint (NaN)))\n\n%!assert (class (cosint (single (1))), \"single\")\n\n## tests against maple\n%!assert (cosint (1), 0.337403922900968135, -2*eps)\n%!assert (cosint (-1), 0.337403922900968135 + 3.14159265358979324*I, -2*eps)\n%!assert (cosint (pi), 0.0736679120464254860, -4e-15)\n%!assert (cosint (-pi), 0.0736679120464254860 + 3.14159265358979324*I, -2*eps)\n%!assert (cosint (300), -0.00333219991859211178, -2*eps)\n%!assert (cosint (1e4), -0.0000305519167244852127, -2*eps)\n%!assert (cosint (20i), 1.28078263320282944e7 + 1.57079632679489662*I, -2*eps)\n\n%!test\n%! x = (0:4).';\n%! y_ex = [-Inf\n%!         0.337403922900968135\n%!         0.422980828774864996\n%!         0.119629786008000328\n%!         -0.140981697886930412];\n%! assert (cosint (x), y_ex, -3e-15);\n\n%!test\n%! x = -(1:4).';\n%! y_ex = [0.337403922900968135 + pi*1i\n%!         0.422980828774864996 + pi*1i\n%!         0.119629786008000328 + pi*1i\n%!         -0.140981697886930412 + pi*1i];\n%! assert (cosint (x), y_ex, -4*eps);\n\n%!test\n%! x = complex (-(1:4).', 0);\n%! y_ex = [0.337403922900968135 + pi*1i\n%!         0.422980828774864996 + pi*1i\n%!         0.119629786008000328 + pi*1i\n%!         -0.140981697886930412 + pi*1i];\n%! assert (cosint (x), y_ex, -4*eps);\n\n%!test\n%! x = complex (-(1:4).', -0);\n%! y_ex = [0.337403922900968135 - pi*1i\n%!         0.422980828774864996 - pi*1i\n%!         0.119629786008000328 - pi*1i\n%!         -0.140981697886930412 - pi*1i];\n%! assert (cosint (x), y_ex, -4*eps);\n\n%!test\n%! x = 1i * (0:4).';\n%! y_ex = [-Inf\n%!         0.837866940980208241 + 1.57079632679489662*I\n%!         2.45266692264691452 + 1.57079632679489662*I\n%!         4.96039209476560976 + 1.57079632679489662*I\n%!         9.81354755882318556 + 1.57079632679489662*I];\n%! assert (cosint (x), y_ex, -4*eps);\n\n%!test\n%! x = -1i * (1:4).';\n%! y_ex = [0.837866940980208241 - 1.57079632679489662*I\n%!         2.45266692264691452 - 1.57079632679489662*I\n%!         4.96039209476560976 - 1.57079632679489662*I\n%!         9.81354755882318556 - 1.57079632679489662*I];\n%! assert (cosint (x), y_ex, -4*eps);\n\n%!test\n%! x = [1+2i; -2+5i; 2-5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i];\n%! A = [ 2.03029639329172164 - 0.151907155175856884*I\n%!      1.61538963829107749 + 19.7257540553382650*I\n%!      1.61538963829107749 + 16.5841614017484717*I\n%!      -0.00514882514261049214\n%!      1246.11448604245441 + 1.57079632679489662*I\n%!      -8.63307471207423322 + 3.13159298695312800*I\n%!      0.0698222284673061493 - 3.11847446254772946*I ];\n%! B = cosint (x);\n%! assert (A, B, -3*eps);\n%! B = cosint (single (x));\n%! assert (A, B, -3*eps (\"single\"));\n\n## Fails along negative real axis\n%!test\n%! x = [-25; -100; -1000];\n%! yex = [-0.0068485971797025909189 + pi*1i\n%!        -0.0051488251426104921444 + pi*1i\n%!        0.000826315511090682282 + pi*1i];\n%! y = cosint (x);\n%! assert (y, yex, -5*eps);\n\n## FIXME: Need a test for bug #52953\n%#!test <*52953>\n\n## Test input validation\n%!error <Invalid call> cosint ()\n%!error <X must be numeric> cosint (\"1\")\n"
  },
  {
    "path": "scripts/specfun/ellipke.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{k} =} ellipke (@var{m})\n## @deftypefnx {} {@var{k} =} ellipke (@var{m}, @var{tol})\n## @deftypefnx {} {[@var{k}, @var{e}] =} ellipke (@dots{})\n## Compute complete elliptic integrals of the first K(@var{m}) and second\n## E(@var{m}) kind.\n##\n## @var{m} must be a scalar or real array with -Inf @leq{} @var{m} @leq{} 1.\n##\n## The optional input @var{tol} controls the stopping tolerance of the\n## algorithm and defaults to @code{eps (class (@var{m}))}.  The tolerance can\n## be increased to compute a faster, less accurate approximation.\n##\n## When called with one output only elliptic integrals of the first kind are\n## returned.\n##\n## Mathematical Note:\n##\n## Elliptic integrals of the first kind are defined as\n## @tex\n## $$\n## {\\rm K} (m) = \\int_0^1 {dt \\over \\sqrt{(1 - t^2) (1 - m t^2)}}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##          1\n##         /               dt\n## K (m) = | ------------------------------\n##         / sqrt ((1 - t^2)*(1 - m*t^2))\n##        0\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## Elliptic integrals of the second kind are defined as\n## @tex\n## $$\n## {\\rm E} (m) = \\int_0^1 {\\sqrt{1 - m t^2} \\over \\sqrt{1 - t^2}} dt\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##          1\n##         /  sqrt (1 - m*t^2)\n## E (m) = |  ------------------ dt\n##         /  sqrt (1 - t^2)\n##        0\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## Reference: @nospell{Milton Abramowitz and Irene A. Stegun},\n## @cite{Handbook of Mathematical Functions}, Chapter 17, Dover, 1965.\n## @seealso{ellipj}\n## @end deftypefn\n\nfunction [k, e] = ellipke (m, tol = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  sz = size (m);\n  if (! isreal (m))\n    error (\"ellipke: M must be real\");\n  elseif (any (m > 1))\n    error (\"ellipke: M must be <= 1\");\n  endif\n\n  if (isempty (tol))\n    tol = eps (class (m));\n  elseif (! (isreal (tol) && isscalar (tol) && tol > 0))\n    error (\"ellipke: TOL must be a real scalar > 0\");\n  endif\n\n  k = e = zeros (sz);\n\n  ## Handle extreme values\n  idx_1 = (m == 1);\n  k(idx_1) = Inf;\n  e(idx_1) = 1;\n\n  idx_neginf = (m == -Inf);\n  k(idx_neginf) = 0;\n  e(idx_neginf) = Inf;\n\n  ## Arithmetic-Geometric Mean (AGM) algorithm\n  ## ( Abramowitz and Stegun, Section 17.6 )\n  Nmax = 16;\n  idx = ! idx_1 & ! idx_neginf;\n  if (any (idx))\n    idx_neg = find (m < 0 & ! idx_neginf);\n    mult_k = 1./sqrt (1 - m(idx_neg));\n    mult_e = sqrt (1 - m(idx_neg));\n    m(idx_neg) = -m(idx_neg) ./ (1 - m(idx_neg));\n    b = sqrt (1 - m(idx));\n    a = ones (size (b));\n    c = sqrt (m(idx));\n    f = 0.5;\n    sum = f*c.^2;\n    n = 2;\n    do\n      t = (a + b)/2;\n      c = (a - b)/2;\n      b = sqrt (a .* b);\n      a = t;\n      f *= 2;\n      sum += f*c.^2;\n    until (all (c./a < tol) || (++n > Nmax))\n    if (n >= Nmax)\n      error (\"ellipke: algorithm did not converge in %d iterations\", Nmax);\n    endif\n    k(idx) = 0.5*pi ./ a;\n    e(idx) = 0.5*pi*(1 - sum) ./ a;\n    k(idx_neg) = mult_k .* k(idx_neg);\n    e(idx_neg) = mult_e .* e(idx_neg);\n  endif\n\nendfunction\n\n\n## Test complete elliptic functions of first and second kind\n## against \"exact\" solution from Mathematica 3.0\n%!test\n%! m = [0.0, 0.01; 0.1, 0.5; 0.9, 0.99; 1.0, 0.0];\n%! [k,e] = ellipke (m);\n%!\n%! k_exp = [1.5707963267948966192, 1.5747455615173559527\n%!          1.6124413487202193982, 1.8540746773013719184\n%!          2.5780921133481731882, 3.6956373629898746778\n%!          Inf                  , 1.5707963267948966192 ];\n%! e_exp = [1.5707963267948966192, 1.5668619420216682912\n%!          1.5307576368977632025, 1.3506438810476755025\n%!          1.1047747327040733261, 1.0159935450252239356\n%!          1.0                  , 1.5707963267948966192 ];\n%! assert (k, k_exp, 8*eps);\n%! assert (e, e_exp, 8*eps);\n\n## Test against A&S Table 17.1\n%!test\n%! m = [0:5:50]'/100;\n%! k_exp = [1.570796326794897;\n%!          1.591003453790792;\n%!          1.612441348720219;\n%!          1.635256732264580;\n%!          1.659623598610528;\n%!          1.685750354812596;\n%!          1.713889448178791;\n%!          1.744350597225613;\n%!          1.777519371491253;\n%!          1.813883936816983;\n%!          1.854074677301372 ];\n%! e_exp = [1.570796327;\n%!          1.550973352;\n%!          1.530757637;\n%!          1.510121831;\n%!          1.489035058;\n%!          1.467462209;\n%!          1.445363064;\n%!          1.422691133;\n%!          1.399392139;\n%!          1.375401972;\n%!          1.350643881 ];\n%! [k,e] = ellipke (m);\n%! assert (k, k_exp, 1e-15);\n%! assert (e, e_exp, 1e-8);\n\n## Test negative values against \"exact\" solution from Mathematica.\n%! m = [-0.01; -1; -5; -100; -1000; -Inf];\n%! [k,e] = ellipke (m);\n%!\n%! k_exp = [1.5668912730681963584;\n%!          1.3110287771460599052;\n%!          0.9555039270640439337;\n%!          0.3682192486091410329;\n%!          0.1530293349884987857;\n%!          0];\n%! e_exp = [1.5747159850169884130;\n%!          1.9100988945138560089;\n%!          2.8301982463458773125;\n%!          10.209260919814572009;\n%!          31.707204053711259719;\n%!          Inf ];\n%! assert (k, k_exp, 8*eps);\n%! assert (e, e_exp, 8*eps (e_exp));\n\n## Test input validation\n%!error <Invalid call> ellipke ()\n%!error <M must be real> ellipke (1i)\n%!error <M must be .= 1> ellipke (2)\n%!error <TOL must be a real scalar . 0> ellipke (1, i)\n%!error <TOL must be a real scalar . 0> ellipke (1, [1 1])\n%!error <TOL must be a real scalar . 0> ellipke (1, -1)\n"
  },
  {
    "path": "scripts/specfun/expint.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} expint (@var{x})\n## Compute the exponential integral.\n##\n## The exponential integral is defined as:\n## @tex\n## $$\n## {\\rm E_1} (x) = \\int_x^\\infty {e^{-t} \\over t} dt\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##            +oo\n##           /\n##           | exp (-t)\n## E_1 (x) = | -------- dt\n##           |    t\n##           /\n##          x\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## Note: For compatibility, this function uses the @sc{matlab} definition\n## of the exponential integral.  Most other sources refer to this particular\n## value as @math{E_1 (x)}, and the exponential integral as\n## @tex\n## $$\n## {\\rm Ei} (x) = - \\int_{-x}^\\infty {e^{-t} \\over t} dt.\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##             +oo\n##            /\n##            | exp (-t)\n## Ei (x) = - | -------- dt\n##            |    t\n##            /\n##          -x\n## @end group\n## @end example\n##\n## @end ifnottex\n## The two definitions are related, for positive real values of @var{x}, by\n## @tex\n## $\n## E_1 (-x) = -{\\rm Ei} (x) - i\\pi.\n## $\n## @end tex\n## @ifnottex\n## @w{@code{E_1 (-x) = -Ei (x) - i*pi}}.\n## @end ifnottex\n##\n## References:\n##\n## @nospell{M. Abramowitz and I.A. Stegun},\n## @cite{Handbook of Mathematical Functions}, 1964.\n##\n## @nospell{N. Bleistein and R.A. Handelsman},\n## @cite{Asymptotic expansions of integrals}, 1986.\n##\n## @seealso{cosint, sinint, exp}\n## @end deftypefn\n\nfunction E1 = expint (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x))\n    error (\"expint: X must be numeric\");\n  endif\n\n  ## Convert to floating point if necessary\n  if (isinteger (x))\n    x = double (x);\n  endif\n\n  orig_sparse = issparse (x);\n  orig_sz = size (x);\n  x = x(:);  # convert to column vector\n\n  ## Initialize the result\n  if (isreal (x) && x >= 0)\n    E1 = zeros (size (x), class (x));\n  else\n    E1 = complex (zeros (size (x), class (x)));\n  endif\n  tol = eps (class (x));\n\n  ## Divide the input into 3 regions and apply a different algorithm for each.\n  ## s = series expansion, cf = continued fraction, a = asymptotic series\n  s_idx = (((real (x) + 19.5).^ 2 ./ (20.5^2) + ...\n            imag (x).^2 ./ (10^2)) <= 1) ...\n          | (real (x) < 0 & abs (imag (x)) <= 1e-8);\n  cf_idx = ((((real (x) + 1).^2 ./ (38^2) + ...\n              imag (x).^2 ./ (40^2)) <= 1) ...\n            & (! s_idx)) & (real (x) <= 35);\n  a_idx = (! s_idx) & (! cf_idx);\n  x_s  = x(s_idx);\n  x_cf = x(cf_idx);\n  x_a  = x(a_idx);\n\n  ## Series expansion\n  ## Abramowitz, Stegun, \"Handbook of Mathematical Functions\",\n  ## formula 5.1.11, p 229.\n  ## FIXME: Why so long?  IEEE double doesn't have this much precision.\n  gm = 0.577215664901532860606512090082402431042159335;\n  e1_s = -gm - log (x_s);\n  res = -x_s;\n  ssum = res;\n  k = 1;\n  todo = true (size (res));\n  while (k < 1e3 && any (todo))\n    res(todo) .*= (k * (- x_s(todo)) / ((k + 1) ^ 2));\n    ssum(todo) += res(todo);\n    k += 1;\n    todo = (abs (res) > (tol * abs (ssum)));\n  endwhile\n  e1_s -= ssum;\n\n  ## Continued fraction expansion,\n  ## Abramowitz, Stegun, \"Handbook of Mathematical Functions\",\n  ## formula 5.1.22, p 229.\n  ## Modified Lentz's algorithm, from \"Numerical recipes in Fortran 77\" p.165.\n\n  e1_cf = exp (-x_cf) .* __expint__ (x_cf);\n\n  ## Remove spurious imaginary part if needed (__expint__ works automatically\n  ## with complex values)\n\n  if (isreal (x_cf) && x_cf >= 0)\n    e1_cf = real (e1_cf);\n  endif\n\n  ## Asymptotic series, from N. Bleistein and R.A. Handelsman\n  ## \"Asymptotic expansion of integrals\", pages 1-4.\n  e1_a = exp (-x_a) ./ x_a;\n  ssum = res = ones (size (x_a), class (x_a));\n  k = 0;\n  todo = true (size (x_a));\n  while (k < 1e3 && any (todo))\n    res(todo) ./= (- x_a(todo) / (k + 1));\n    ssum(todo) += res(todo);\n    k += 1;\n    todo = abs (x_a) > k;\n  endwhile\n  e1_a .*= ssum;\n\n  ## Combine results from each region into final output\n  E1(s_idx)  = e1_s;\n  E1(cf_idx) = e1_cf;\n  E1(a_idx)  = e1_a;\n\n  ## Restore shape and sparsity of input\n  E1 = reshape (E1, orig_sz);\n  if (orig_sparse)\n    E1 = sparse (E1);\n  endif\n\nendfunction\n\n\n## The following values were computed with the Octave symbolic package\n%!test\n%! X = [-50 - 50i  -30 - 50i  -10 - 50i    5 - 50i   15 - 50i   25 - 50i\n%!      -50 - 30i  -30 - 30i  -10 - 30i    5 - 30i   15 - 30i   25 - 30i\n%!      -50 - 10i  -30 - 10i  -10 - 10i    5 - 10i   15 - 10i   25 - 10i\n%!      -50 +  5i  -30 +  5i  -10 +  5i    5 +  5i   15 +  5i   25 +  5i\n%!      -50 + 15i  -30 + 15i  -10 + 15i    5 + 15i   15 + 15i   25 + 15i\n%!      -50 + 25i  -30 + 25i  -10 + 25i    5 + 25i   15 + 25i   25 + 25i];\n%! y_exp = [ -3.61285286166493e+19 + 6.46488018613387e+19i, ...\n%!           -4.74939752018180e+10 + 1.78647798300364e+11i, ...\n%!            3.78788822381261e+01 + 4.31742823558278e+02i, ...\n%!            5.02062497548626e-05 + 1.23967883532795e-04i, ...\n%!            3.16785290137650e-09 + 4.88866651583182e-09i, ...\n%!            1.66999261039533e-13 + 1.81161508735941e-13i;\n%!            3.47121527628275e+19 + 8.33104448629260e+19i, ...\n%!            1.54596484273693e+11 + 2.04179357837414e+11i, ...\n%!            6.33946547999647e+02 + 3.02965459323125e+02i, ...\n%!            2.19834747595065e-04 - 9.25266900230165e-06i, ...\n%!            8.49515487435091e-09 - 2.95133588338825e-09i, ...\n%!            2.96635342439717e-13 - 1.85401806861382e-13i;\n%!            9.65535916388246e+19 + 3.78654062133933e+19i, ...\n%!            3.38477774418380e+11 + 8.37063899960569e+10i, ...\n%!            1.57615042657685e+03 - 4.33777639047543e+02i, ...\n%!            2.36176542789578e-05 - 5.75861972980636e-04i, ...\n%!           -6.83624588479039e-09 - 1.47230889442175e-08i, ...\n%!           -2.93020801760942e-13 - 4.03912221595793e-13i;\n%!           -1.94572937469407e+19 - 1.03494929263031e+20i, ...\n%!           -4.22385087573180e+10 - 3.61103191095041e+11i, ...\n%!            4.89771220858552e+02 - 2.09175729060712e+03i, ...\n%!            7.26650666035639e-04 + 4.71027801635222e-04i, ...\n%!            1.02146578536128e-08 + 1.51813977370467e-08i, ...\n%!            2.41628751621686e-13 + 4.66309048729523e-13i;\n%!            5.42351559144068e+19 + 8.54503231614651e+19i, ...\n%!            1.22886461074544e+11 + 3.03555953589323e+11i, ...\n%!           -2.13050339387819e+02 + 1.23853666784218e+03i, ...\n%!           -3.68087391884738e-04 + 1.94003994408861e-04i, ...\n%!           -1.39355838231763e-08 + 6.57189276453356e-10i, ...\n%!           -4.55133112151501e-13 - 8.46035902535333e-14i;\n%!           -7.75482228205081e+19 - 5.36017490438329e+19i, ...\n%!           -1.85284579257329e+11 - 2.08761110392897e+11i, ...\n%!           -1.74210199269860e+02 - 8.09467914953486e+02i, ...\n%!            9.40470496160143e-05 - 2.44265223110736e-04i, ...\n%!            6.64487526601190e-09 - 7.87242868014498e-09i, ...\n%!            3.10273337426175e-13 - 2.28030229776792e-13i];\n%! assert (expint (X), y_exp, -1e-14);\n\n## Exceptional values (-Inf, Inf, NaN, 0, 0.37250741078)\n%!test\n%! x = [-Inf; Inf; NaN; 0; -0.3725074107813668];\n%! y_exp = [-Inf - i*pi; 0; NaN; Inf; 0 - i*pi];\n%! y = expint (x);\n%! assert (y, y_exp, 5*eps);\n\n%!test <*53351>\n%! assert (expint (32.5 + 1i),\n%!         1.181108930758065e-16 - 1.966348533426658e-16i, -4*eps);\n%! assert (expint (44 + 1i),\n%!         9.018757389858152e-22 - 1.475771020004195e-21i, -4*eps);\n\n%!test <*47738>\n%! assert (expint (10i), 0.0454564330044554 + 0.0875512674239774i, -5*eps);\n\n## Test preservation or conversion of the class\n%!assert (class (expint (single (1))), \"single\")\n%!assert (class (expint (int8 (1))), \"double\")\n%!assert (class (expint (int16 (1))), \"double\")\n%!assert (class (expint (int32 (1))), \"double\")\n%!assert (class (expint (int64 (1))), \"double\")\n%!assert (class (expint (uint8 (1))), \"double\")\n%!assert (class (expint (uint16 (1))), \"double\")\n%!assert (class (expint (uint32 (1))), \"double\")\n%!assert (class (expint (uint64 (1))), \"double\")\n%!assert (issparse (expint (sparse (1))))\n\n## Test on the correct Image set\n%!assert (isreal (expint (linspace (0, 100))))\n%!assert (! isreal (expint (-1)))\n\n## Test input validation\n%!error <Invalid call> expint ()\n%!error <X must be numeric> expint (\"1\")\n"
  },
  {
    "path": "scripts/specfun/factor.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{pf} =} factor (@var{q})\n## @deftypefnx {} {[@var{pf}, @var{n}] =} factor (@var{q})\n## Return the prime factorization of @var{q}.\n##\n## The prime factorization is defined as @code{prod (@var{pf}) == @var{q}}\n## where every element of @var{pf} is a prime number.  If @code{@var{q} == 1},\n## return 1.  The output @var{pf} is of the same numeric class as the input.\n##\n## With two output arguments, return the unique prime factors @var{pf} and\n## their multiplicities.  That is,\n## @code{prod (@var{pf} .^ @var{n}) == @var{q}}.\n##\n## Implementation Note: If the input @var{q} is @code{single} or @code{double},\n## then it must not exceed the corresponding @code{flintmax}.  For larger\n## inputs, cast them to @code{uint64} if they're less than 2^64:\n##\n## @example\n## @group\n## factor (uint64 (18446744073709011493))\n##    @xresult{}     571111    761213  42431951\n## @end group\n## @end example\n##\n## For even larger inputs, use @code{sym} if you have the Symbolic package\n## installed and loaded:\n##\n## @example\n## @group\n## factor (sym ('9444733049654361449941'))\n##    @xresult{} (sym)\n##               1           1\n##  1099511627689 ⋅8589934669\n## @end group\n## @end example\n## @seealso{gcd, lcm, isprime, primes}\n## @end deftypefn\n\nfunction [pf, n] = factor (q)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isscalar (q) || ! isreal (q) || q < 0 || q != fix (q))\n    error (\"factor: Q must be a real non-negative integer\");\n  endif\n\n  ## Special case if q is prime, because isprime() is now much faster than\n  ## factor().  This also absorbs the case of q < 4, where there are no primes\n  ## less than sqrt(q).\n  if (q < 4 || isprime (q))\n    pf = q;\n    n = 1;\n    return;\n  endif\n\n  ## If we are here, then q is composite.\n\n  cls = class (q);  # store class\n  if (isfloat (q) && q > flintmax (q))\n    error (\"factor: Q too large to factor (> flintmax)\");\n  endif\n\n  ## The overall flow is this:\n  ## 1. Divide by small primes smaller than q^0.2, if any.\n  ## 2. Use Pollard Rho to reduce the value below 1e10 if possible.\n  ## 3. Divide by primes smaller than sqrt (q), if any.\n  ## 4. At all stages, stop if the remaining value is prime.\n\n  ## First divide by primes (q ^ 0.2).\n  ## For q < 1e10, we can hard-code the primes.\n  if (q < 1e10)\n    smallprimes = feval (cls, ...\n      [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]);\n  else\n    smallprimes = primes (feval (cls, q ^ 0.2));\n  endif\n\n  ## pf is the list of prime factors returned with type of input class.\n  pf = feval (cls, []);\n  [pf, q] = reducefactors (q, pf, smallprimes);\n\n  ## pf now contains all prime factors of q within smallprimes, including\n  ## repetitions, in ascending order.\n  ##\n  ## q itself has been divided by those prime factors to become smaller,\n  ## unless q was prime to begin with.\n\n  sortflag = false;\n  if (isprime (q))\n    pf(end+1) = q;\n  elseif (q > 1)\n    ## Use Pollard Rho technique to pull factors one at a time.\n    while (q > 1e10 && ! isprime (q))\n      pr = feval (cls, __pollardrho__ (q));  # pr is a factor of q.\n\n      ## There is a small chance (13 in 1e5) that pr is not actually prime.\n      ## To guard against that, factorize pr, which will force smaller factors\n      ## to be found.  The use of isprime above guards against infinite\n      ## recursion.\n      if (! isprime (pr))\n        pr = factor (pr);\n      endif\n\n      [pf, q] = reducefactors (q, pf, pr);\n      ## q is now divided by all occurrences of factor(s) pr.\n      sortflag = true;\n    endwhile\n\n    if (isprime (q))\n      pf(end+1) = q;\n    elseif (q > 1)\n      ## If we are here, then q is composite but less than 1e10,\n      ## and that is fast enough to test by division.\n      largeprimes = primes (feval (cls, sqrt (q)));\n      [pf, q] = reducefactors (q, pf, largeprimes);\n\n      ## If q is still not 1, then it must be a prime of power 1.\n      if (q > 1)\n        pf(end+1) = q;\n      endif\n    endif\n  endif\n\n  ## The Pollard Rho technique can give factors in arbitrary order,\n  ## so we need to sort pf if that was used.\n  if (sortflag)\n    pf = sort (pf);\n  endif\n\n  ## Determine multiplicity.\n  if (nargout > 1)\n    idx = find ([0, pf] != [pf, 0]);\n    pf = pf(idx(1:length (idx)-1));\n    n = diff (idx);\n  endif\n\nendfunction\n\nfunction [pf, q] = reducefactors (qin, pfin, divisors)\n\n  pf = pfin;\n  q = qin;\n  divisors = divisors (mod (q, divisors) == 0);\n\n  for pp = divisors  # for each factor in turn\n    ## Keep extracting all occurrences of that factor before going to larger\n    ## factors.\n    while (mod (q, pp) == 0)\n      pf(end+1) = pp;\n      q /= pp;\n    endwhile\n  endfor\n\nendfunction\n\n\n## Test special case input\n%!assert (factor (1), 1)\n%!assert (factor (2), 2)\n%!assert (factor (3), 3)\n\n%!test\n%! for i = 2:20\n%!   pf = factor (i);\n%!   assert (prod (pf), i);\n%!   assert (all (isprime (pf)));\n%!   [pf, n] = factor (i);\n%!   assert (prod (pf.^n), i);\n%!   assert (all ([0,pf] != [pf,0]));\n%! endfor\n\n## Make sure that all factors returned are indeed prime, even when\n## __pollardrho__ returns a composite factor.\n%!assert (all (isprime (factor (uint64 (18446744073707633197)))))\n%!assert (all (isprime (factor (uint64 (18446744073707551733)))))\n%!assert (all (isprime (factor (uint64 (18446744073709427857)))))\n%!assert (all (isprime (factor (uint64 (18446744073709396891)))))\n%!assert (all (isprime (factor (uint64 (18446744073708666563)))))\n%!assert (all (isprime (factor (uint64 (18446744073708532009)))))\n%!assert (all (isprime (factor (uint64 (18446744073708054211)))))\n%!assert (all (isprime (factor (uint64 (18446744073707834741)))))\n%!assert (all (isprime (factor (uint64 (18446744073707298053)))))\n%!assert (all (isprime (factor (uint64 (18446744073709407383)))))\n%!assert (all (isprime (factor (uint64 (18446744073708730121)))))\n%!assert (all (isprime (factor (uint64 (18446744073708104447)))))\n%!assert (all (isprime (factor (uint64 (18446744073709011493)))))\n\n%!assert (factor (uint8 (8)), uint8 ([2 2 2]))\n%!assert (factor (single (8)), single ([2 2 2]))\n%!test\n%! [pf, n] = factor (int16 (8));\n%! assert (pf, int16 (2));\n%! assert (n, double (3));\n\n## Test input validation\n%!error <Invalid call> factor ()\n%!error <Q must be a real non-negative integer> factor ([1,2])\n%!error <Q must be a real non-negative integer> factor (6i)\n%!error <Q must be a real non-negative integer> factor (-20)\n%!error <Q must be a real non-negative integer> factor (1.5)\n%!error <Q too large to factor> factor (flintmax (\"single\") + 2)\n%!error <Q too large to factor> factor (flintmax (\"double\") + 2)\n"
  },
  {
    "path": "scripts/specfun/factorial.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{f} =} factorial (@var{n})\n## Return the factorial of @var{n} where @var{n} is a real non-negative\n## integer.\n##\n## @c FIXME: This documentation is wrong.  Apparently gamma() is used for\n## @c        calculations rather than prod().\n## If @var{n} is a scalar, this is equivalent to @code{prod (1:@var{n})}.  For\n## vector or matrix arguments, return the factorial of each element in the\n## array.\n##\n## For non-integers see the generalized factorial function @code{gamma}.\n## Note that the factorial function grows large quite quickly, and even\n## with double precision values overflow will occur if @var{n} > 171.  For\n## such cases consider @code{gammaln}.\n## @seealso{prod, gamma, gammaln}\n## @end deftypefn\n\nfunction f = factorial (n)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! isreal (n) || any (n(:) < 0 | n(:) != fix (n(:))))\n    error (\"factorial: all N must be real non-negative integers\");\n  endif\n\n  f = round (gamma (n+1));\n\n  ## FIXME: Matlab returns an output of the same type as the input.\n  ## This doesn't seem particularly worth copying--for example uint8 would\n  ## saturate for n > 5.  If desired, however, the following code could be\n  ## uncommented.\n  ## if (! isfloat (f))\n  ##   f = cast (f, class (n));\n  ## endif\n\nendfunction\n\n\n%!assert (factorial (5), prod (1:5))\n%!assert (factorial ([1,2;3,4]), [1,2;6,24])\n%!assert (factorial (70), exp (sum (log (1:70))), -128*eps)\n%!assert (factorial (0), 1)\n\n%!error <Invalid call> factorial ()\n%!error <must be real non-negative integers> factorial (2i)\n%!error <must be real non-negative integers> factorial (-3)\n%!error <must be real non-negative integers> factorial (5.5)\n"
  },
  {
    "path": "scripts/specfun/gammainc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} gammainc (@var{x}, @var{a})\n## @deftypefnx {} {@var{y} =} gammainc (@var{x}, @var{a}, @var{tail})\n## Compute the normalized incomplete gamma function.\n##\n## This is defined as\n## @tex\n## $$\n##  \\gamma (x, a) = {1 \\over {\\Gamma (a)}}\\displaystyle{\\int_0^x t^{a-1} e^{-t} dt}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##                                 x\n##                        1       /\n## gammainc (x, a) = ---------    | exp (-t) t^(a-1) dt\n##                   gamma (a)    /\n##                             t=0\n## @end group\n## @end example\n##\n## @end ifnottex\n## with the limiting value of 1 as @var{x} approaches infinity.\n## The standard notation is @math{P(a,x)}, e.g., @nospell{Abramowitz} and\n## @nospell{Stegun} (6.5.1).\n##\n## If @var{a} is scalar, then @code{gammainc (@var{x}, @var{a})} is returned\n## for each element of @var{x} and vice versa.\n##\n## If neither @var{x} nor @var{a} is scalar then the sizes of @var{x} and\n## @var{a} must agree, and @code{gammainc} is applied element-by-element.\n## The elements of @var{a} must be non-negative.\n##\n## By default, @var{tail} is @qcode{\"lower\"} and the incomplete gamma function\n## integrated from 0 to @var{x} is computed.  If @var{tail} is @qcode{\"upper\"}\n## then the complementary function integrated from @var{x} to infinity is\n## calculated.\n##\n## If @var{tail} is @qcode{\"scaledlower\"}, then the lower incomplete gamma\n## function is multiplied by\n## @tex\n## $\\Gamma(a+1)\\exp(x)x^{-a}$.\n## @end tex\n## @ifnottex\n## @math{gamma(a+1)*exp(x)/(x^a)}.\n## @end ifnottex\n## If @var{tail} is @qcode{\"scaledupper\"}, then the upper incomplete gamma\n## function is multiplied by the same quantity.\n##\n## References:\n##\n## @nospell{M. Abramowitz and I.A. Stegun},\n## @cite{Handbook of mathematical functions},\n## @nospell{Dover publications, Inc.}, 1972.\n##\n## @nospell{W. Gautschi},\n## \"A computational procedure for incomplete gamma functions\",\n## @cite{@nospell{ACM Trans.@: Math Software}}, @w{Vol.@: 5}, @w{No.@: 4},\n## @w{pp.@: 466}--481, 2012.\n##\n## @nospell{W. H. Press, S. A. Teukolsky, W. T. Vetterling, and B. P. Flannery},\n## @cite{Numerical Recipes in Fortran 77}, @w{Vol.@: 1}, @w{ch.@: 6.2}, 1992.\n##\n## @seealso{gamma, gammaincinv, gammaln}\n## @end deftypefn\n\n## P(a,x) = gamma(a,x)/Gamma(a), upper\n## 1-P(a,x)=Q(a,x)=Gamma(a,x)/Gamma(a), lower\n\nfunction y = gammainc (x, a, tail = \"lower\")\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  [err, x, a] = common_size (x, a);\n  if (err > 0)\n    error (\"gammainc: X and A must be of common size or scalars\");\n  endif\n\n  if (iscomplex (x) || iscomplex (a))\n    error (\"gammainc: all inputs must be real\");\n  endif\n\n  ## Remember original shape of data, but convert to column vector for calcs.\n  x_sz = size (x);\n  x = x(:);\n  a = a(:);\n\n  if (any (a < 0))\n    error (\"gammainc: A must be non-negative\");\n  endif\n\n  if (nargin == 3\n      && ! any (strcmpi (tail, {\"lower\",\"upper\",\"scaledlower\",\"scaledupper\"})))\n    error (\"gammainc: invalid value for TAIL\");\n  endif\n  tail = lower (tail);\n\n  ## If any of the arguments is single then the output should be as well.\n  if (strcmp (class (x), \"single\") || strcmp (class (a), \"single\"))\n    x = single (x);\n    a = single (a);\n  endif\n\n  ## Convert to floating point if necessary\n  if (isinteger (x))\n    x = double (x);\n  endif\n  if (isinteger (a))\n    a = double (a);\n  endif\n\n  ## Initialize output array\n  y = zeros (x_sz, class (x));\n\n  ## Different x, a combinations are handled by different subfunctions.\n  todo = true (size (x));  # Track which elements need to be calculated.\n\n  ## Case 0: x == Inf, a == Inf\n  idx = (x == Inf) & (a == Inf);\n  if (any (idx))\n    y(idx) = NaN;\n    todo(idx) = false;\n  endif\n\n  ## Case 1: x == 0, a == 0.\n  idx = (x == 0) & (a == 0);\n  if (any (idx))\n    y(idx) = gammainc_00 (tail);\n    todo(idx) = false;\n  endif\n\n  ## Case 2: x == 0.\n  idx = todo & (x == 0);\n  if (any (idx))\n    y(idx) = gammainc_x0 (tail);\n    todo(idx) = false;\n  endif\n\n  ## Case 3: x = Inf\n  idx = todo & (x == Inf);\n  if (any (idx))\n    y(idx) = gammainc_x_inf (tail);\n    todo(idx) = false;\n  endif\n\n  ## Case 4: a = Inf\n  idx = todo & (a == Inf);\n  if (any (idx))\n    y(idx) = gammainc_a_inf (tail);\n    todo(idx) = false;\n  endif\n\n  ## Case 5: a == 0.\n  idx = todo & (a == 0);\n  if (any (idx))\n    y(idx) = gammainc_a0 (x(idx), tail);\n    todo(idx) = false;\n  endif\n\n  ## Case 6: a == 1.\n  idx = todo & (a == 1);\n  if (any (idx))\n    y(idx) = gammainc_a1 (x(idx), tail);\n    todo(idx) = false;\n  endif\n\n  ## Case 7: positive integer a; exp (x) and a! both under 1/eps.\n  idx = (todo\n         & (a == fix (a)) & (a > 1) & (a <= 18) & (x <= 36) & (abs (x) >= .1));\n  if (any (idx))\n    y(idx) = gammainc_an (x(idx), a(idx), tail);\n    todo(idx) = false;\n  endif\n\n  ## For a < 2, x < 0, we increment a by 2 and use a recurrence formula after\n  ## the computations.\n\n  flag_a_small = todo & (abs (a) > 0) & (abs (a) < 2) & (x < 0);\n  a(flag_a_small) += 2;\n\n  flag_s = (((x + 0.25 < a) | (x < 0)) & (x > -20)) | (abs (x) < 1);\n\n  ## Case 8: x, a relatively small.\n  idx = todo & flag_s;\n  if (any (idx))\n    y(idx) = gammainc_s (x(idx), a(idx), tail);\n    todo(idx) = false;\n  endif\n\n  ## Case 9: x positive and large relative to a.\n  idx = todo;\n  if (any (idx))\n    y(idx) = gammainc_l (x(idx), a(idx), tail);\n    todo(idx) = false;\n  endif\n\n  if (any (flag_a_small))\n    if (strcmp (tail, \"lower\"))\n      y(flag_a_small) += D (x(flag_a_small), a(flag_a_small) - 1) + ...\n        D (x(flag_a_small), a(flag_a_small) - 2);\n    elseif (strcmp (tail, \"upper\"))\n      y(flag_a_small) -= D (x(flag_a_small), a(flag_a_small) - 1) + ...\n           D (x(flag_a_small), a(flag_a_small) - 2);\n    elseif (strcmp (tail, \"scaledlower\"))\n      y(flag_a_small) = y(flag_a_small) .* (x(flag_a_small) .^ 2) ./ ...\n        (a(flag_a_small) .* (a(flag_a_small) - 1)) + (x(flag_a_small) ./ ...\n          (a(flag_a_small) - 1)) + 1;\n    elseif (strcmp (tail, \"scaledupper\"))\n      y(flag_a_small) = y(flag_a_small) .* (x(flag_a_small) .^ 2) ./ ...\n        (a(flag_a_small) .* (a(flag_a_small) - 1)) - (x(flag_a_small) ./ ...\n          (a(flag_a_small) - 1)) - 1;\n     endif\n  endif\n\nendfunction\n\n## Subfunctions to handle each case:\n\n## x == 0, a == 0.\nfunction y = gammainc_00 (tail)\n\n  if (strcmp (tail, \"upper\") || strcmp (tail, \"scaledupper\"))\n    y = 0;\n  else\n    y = 1;\n  endif\n\nendfunction\n\n## x == 0.\nfunction y = gammainc_x0 (tail)\n\n  if (strcmp (tail, \"lower\"))\n    y = 0;\n  elseif (strcmp (tail, \"upper\") || strcmp (tail, \"scaledlower\"))\n    y = 1;\n  else\n    y = Inf;\n  endif\n\nendfunction\n\n## x == Inf.\nfunction y = gammainc_x_inf (tail)\n\n  if (strcmp (tail, \"lower\"))\n    y = 1;\n  elseif (strcmp (tail, \"upper\") || strcmp (tail, \"scaledupper\"))\n    y = 0;\n  else\n    y = Inf;\n  endif\n\nendfunction\n\n## a == Inf.\nfunction y = gammainc_a_inf (tail)\n\n  if (strcmp (tail, \"lower\"))\n    y = 0;\n  elseif (strcmp (tail, \"upper\") || strcmp (tail, \"scaledlower\"))\n    y = 1;\n  else\n    y = Inf;\n  endif\n\nendfunction\n\n## a == 0.\nfunction y = gammainc_a0 (x, tail)\n\n  if (strcmp (tail, \"lower\"))\n    y = 1;\n  elseif (strcmp (tail, \"scaledlower\"))\n    y = exp (x);\n  else\n    y = 0;\n  endif\n\nendfunction\n\n## a == 1.\nfunction y = gammainc_a1 (x, tail)\n\n  if (strcmp (tail, \"lower\"))\n    if (abs (x) < 1/2)\n      y = - expm1 (-x);\n    else\n      y = 1 - exp (-x);\n    endif\n  elseif (strcmp (tail, \"upper\"))\n    y = exp (-x);\n  elseif (strcmp (tail, \"scaledlower\"))\n    if (abs (x) < 1/2)\n      y = expm1 (x) ./ x;\n    else\n      y = (exp (x) - 1) ./ x;\n    endif\n  else\n    y = 1 ./ x;\n  endif\n\nendfunction\n\n## positive integer a; exp (x) and a! both under 1/eps\n## uses closed-form expressions for nonnegative integer a\n## -- http://mathworld.wolfram.com/IncompleteGammaFunction.html.\nfunction y = gammainc_an (x, a, tail)\n\n  y = t = ones (size (x), class (x));\n  i = 1;\n  while (any (a(:) > i))\n    jj = (a > i);\n    t(jj) .*= (x(jj) / i);\n    y(jj) += t(jj);\n    i++;\n  endwhile\n  if (strcmp (tail, \"lower\"))\n    y = 1 - exp (-x) .* y;\n  elseif (strcmp (tail, \"upper\"))\n    y .*= exp (-x);\n  elseif (strcmp (tail, \"scaledlower\"))\n    y = (1 - exp (-x) .* y) ./ D(x, a);\n  elseif (strcmp (tail, \"scaledupper\"))\n    y .*= exp (-x) ./ D(x, a);\n  endif\n\nendfunction\n\n## x + 0.25 < a | x < 0 | abs(x) < 1.\n## Numerical Recipes in Fortran 77 (6.2.5)\n## series\nfunction y = gammainc_s (x, a, tail)\n\n  if (strcmp (tail, \"scaledlower\") || strcmp (tail, \"scaledupper\"))\n    y = ones (size (x), class (x));\n    term = x ./ (a + 1);\n  else\n    ## Of course it is possible to scale at the end, but some tests fail.\n    ## And try gammainc (1,1000), it take 0 iterations if you scale now.\n    y = D (x,a);\n    term = y .* x ./ (a + 1);\n  endif\n  n = 1;\n  while (any (abs (term(:)) > (abs (y(:)) * eps)))\n    ## y can be zero from the beginning (gammainc (1,1000))\n    jj = abs (term) > abs (y) * eps;\n    n += 1;\n    y(jj) += term(jj);\n    term(jj) .*= x(jj) ./ (a(jj) + n);\n  endwhile\n  if (strcmp (tail, \"upper\"))\n    y = 1 - y;\n  elseif (strcmp (tail, \"scaledupper\"))\n    y = 1 ./ D (x,a) - y;\n  endif\n\nendfunction\n\n## x positive and large relative to a\n## NRF77 (6.2.7)\n## Gamma (a,x)/Gamma (a)\n## Lentz's algorithm\n## __gammainc__ in libinterp/corefcn/__gammainc__.cc\nfunction y = gammainc_l (x, a, tail)\n\n  y = __gammainc__ (x, a);\n  if (strcmp (tail,  \"lower\"))\n    y = 1 - y .* D (x, a);\n  elseif (strcmp (tail, \"upper\"))\n    y .*= D (x, a);\n  elseif (strcmp (tail, \"scaledlower\"))\n    y = 1 ./ D (x, a) - y;\n  endif\n\nendfunction\n\n## Compute exp(-x)*x^a/Gamma(a+1) in a stable way for x and a large.\n##\n## L. Knusel, Computation of the Chi-square and Poisson distribution,\n## SIAM J. Sci. Stat. Comput., 7(3), 1986\n## which quotes Section 5, Abramowitz&Stegun 6.1.40, 6.1.41.\nfunction y = D (x, a)\n\n  athresh = 10;  # FIXME: can this be better tuned?\n  y = zeros (size (x), class (x));\n\n  todo = true (size (x));\n  todo(x == 0) = false;\n\n  ii = todo & (x > 0) & (a > athresh) & (a >= x);\n  if (any (ii))\n    lnGa = log (2 * pi * a(ii)) / 2 + 1 ./ (12 * a(ii)) - ...\n           1 ./ (360 * a(ii) .^ 3) + 1 ./ (1260 * a(ii) .^ 5) - ...\n           1 ./ (1680 * a(ii) .^ 7) + 1 ./ (1188 * a(ii) .^ 9)- ...\n           691 ./ (87360 * a(ii) .^ 11) + 1 ./ (156 * a(ii) .^ 13) - ...\n           3617 ./ (122400 * a(ii) .^ 15) + ...\n           43867 ./ (244188 * a(ii) .^ 17) - 174611 ./ (125400 * a(ii) .^ 19);\n    lns = log1p ((a(ii) - x(ii)) ./ x(ii));\n    y(ii) = exp ((a(ii) - x(ii)) - a(ii) .* lns - lnGa);\n    todo(ii) = false;\n  endif\n\n  ii = todo & (x > 0) & (a > athresh) & (a < x);\n  if (any (ii))\n    lnGa = log (2 * pi * a(ii)) / 2 + 1 ./ (12 * a(ii)) - ...\n           1 ./ (360 * a(ii) .^ 3) + 1 ./ (1260 * a(ii) .^ 5) - ...\n           1 ./ (1680 * a(ii) .^ 7) + 1 ./ (1188 * a(ii) .^ 9)- ...\n           691 ./ (87360 * a(ii) .^ 11) + 1 ./ (156 * a(ii) .^ 13) - ...\n           3617 ./ (122400 * a(ii) .^ 15) + ...\n           43867 ./ (244188 * a(ii) .^ 17) - 174611 ./ (125400 * a(ii) .^ 19);\n    lns = -log1p ((x(ii) - a(ii)) ./ a(ii));\n    y(ii) = exp ((a(ii) - x(ii)) - a(ii) .* lns - lnGa);\n    todo(ii) = false;\n  endif\n\n  ii = todo & ((x <= 0) | (a <= athresh));\n  if (any (ii))  # standard formula for a not so large.\n    y(ii) = exp (a(ii) .* log (x(ii)) - x(ii) - gammaln (a(ii) + 1));\n    todo(ii) = false;\n  endif\n\n  ii = (x < 0) & (a == fix (a));\n  if (any (ii))  # remove spurious imaginary part.\n    y(ii) = real (y(ii));\n  endif\n\nendfunction\n\n\n## Test: case 1,2,5\n%!assert (gammainc ([0, 0, 1], [0, 1, 0]), [1, 0, 1])\n%!assert (gammainc ([0, 0, 1], [0, 1, 0], \"upper\"), [0, 1, 0])\n%!assert (gammainc ([0, 0, 1], [0, 1, 0], \"scaledlower\"), [1, 1, exp(1)])\n%!assert (gammainc ([0, 0, 1], [0, 1, 0], \"scaledupper\"), [0, Inf, 0])\n\n## Test: case 3,4\n%!assert (gammainc ([2, Inf], [Inf, 2]), [0, 1])\n%!assert (gammainc ([2, Inf], [Inf, 2], \"upper\"), [1, 0])\n%!assert (gammainc ([2, Inf], [Inf, 2], \"scaledlower\"), [1, Inf])\n%!assert (gammainc ([2, Inf], [Inf, 2], \"scaledupper\"), [Inf, 0])\n\n## Test: case 5\n## Matlab fails for this test\n%!assert (gammainc (-100,1,\"upper\"), exp (100), -eps)\n\n## Test: case 6\n%!assert (gammainc ([1, 2, 3], 1), 1 - exp (-[1, 2, 3]))\n%!assert (gammainc ([1, 2, 3], 1, \"upper\"), exp (- [1, 2, 3]))\n%!assert (gammainc ([1, 2, 3], 1, \"scaledlower\"), ...\n%!        (exp ([1, 2, 3]) - 1) ./ [1, 2, 3])\n%!assert (gammainc ([1, 2, 3], 1, \"scaledupper\"), 1 ./ [1, 2, 3])\n\n## Test: case 7\n%!assert (gammainc (2, 2, \"lower\"), 0.593994150290162, -2e-15)\n%!assert (gammainc (2, 2, \"upper\"), 0.406005849709838, -2e-15)\n%!assert (gammainc (2, 2, \"scaledlower\"), 2.194528049465325, -2e-15)\n%!assert (gammainc (2, 2, \"scaledupper\"), 1.500000000000000, -2e-15)\n%!assert (gammainc ([3 2 36],[2 3 18], \"upper\"), ...\n%!        [4/exp(3) 5*exp(-2) (4369755579265807723 / 2977975)/exp(36)], -eps)\n%!assert (gammainc (10, 10), 1 - (5719087 / 567) * exp (-10), -eps)\n%!assert (gammainc (10, 10, \"upper\"), (5719087 / 567) * exp (-10), -2*eps)\n\n## Test: case 8\n%!assert (gammainc (-10, 10), 3.112658265341493126871617e7, -2*eps)\n## Matlab fails this next one%!      %!\n%!assert (isreal (gammainc (-10, 10)), true)\n%!assert (gammainc (-10, 10.1, \"upper\"), ...\n%!        -2.9582761911890713293e7-1i * 9.612022339061679758e6, -30*eps)\n%!assert (gammainc (-10, 10, \"upper\"), -3.112658165341493126871616e7, ...\n%!        -2*eps)\n%!assert (gammainc (-10, 10, \"scaledlower\"), 0.5128019364747265, -1e-14)\n%!assert (gammainc (-10, 10, \"scaledupper\"), -0.5128019200000000, -1e-14)\n%!assert (gammainc (200, 201, \"upper\"), 0.518794309678684497, -2 * eps)\n%!assert (gammainc (200, 201, \"scaledupper\"),\n%!        18.4904360746560462660798514, -eps)\n## Here we are very good (no D (x,a)) involved\n%!assert (gammainc (1000, 1000.5, \"scaledlower\"), 39.48467539583672271, -2*eps)\n%!assert (gammainc (709, 1000, \"upper\"), 0.99999999999999999999999954358, -eps)\n\n## Test: case 9\n%!test <*47800>\n%! assert (gammainc (60, 6, \"upper\"), 6.18022358081160257327264261e-20,\n%!         -10*eps);\n## Matlab is better here than Octave\n%!assert (gammainc (751, 750, \"upper\"), 0.4805914320558831327179457887, -12*eps)\n%!assert (gammainc (200, 200, \"upper\"), 0.49059658199276367497217454, -6*eps)\n%!assert (gammainc (200, 200), 0.509403418007236325027825459574527043, -5*eps)\n%!assert (gammainc (200, 200, \"scaledupper\"), 17.3984438553791505135122900,\n%!       -3*eps)\n%!assert (gammainc (200, 200, \"scaledlower\"), 18.065406676779221643065, -8*eps)\n%!assert (gammainc (201, 200, \"upper\"), 0.46249244908276709524913736667,\n%!        -7*eps)\n%!assert <*54550> (gammainc (77, 2), 1)\n\n%!assert (gammainc (77, 2, \"upper\"), 0, -eps)\n%!assert (gammainc (1000, 3.1), 1)\n%!assert (gammainc (1000, 3.1, \"upper\"), 0)\n\n## Test small argument\n%!assert (gammainc ([1e-05, 1e-07,1e-10,1e-14], 0.1), ...\n%!        [0.33239840504050, 0.20972940370977, 0.10511370061022, ...\n%!        0.041846517936723], 1e-13);\n\n%!assert (gammainc ([1e-05, 1e-07,1e-10,1e-14], 0.2), ...\n%!        [0.10891226058559, 0.043358823442178, 0.010891244210402, ...\n%!        0.0017261458806785], 1e-13);\n\n%!test\n%!assert (gammainc ([1e-02, 1e-03, 1e-5, 1e-9, 1e-14], 0.9), ...\n%!        [0.016401189184068, 0.0020735998660840, 0.000032879756964708, ...\n%!        8.2590606569241e-9, 2.6117443021738e-13], -1e-12);\n\n%!test\n%!assert (gammainc ([1e-02, 1e-03, 1e-5, 1e-9, 1e-14], 2), ...\n%!        [0.0000496679133402659, 4.99666791633340e-7, 4.99996666679167e-11, ...\n%!        4.99999999666667e-19, 4.99999999999997e-29], -1e-12);\n\n%!test <*53543>\n%! y_exp = 9.995001666250085e-04;\n%! assert (gammainc (1/1000, 1), y_exp, -eps);\n\n%!test <53612>\n%! assert (gammainc (-20, 1.1, \"upper\"), ...\n%!         6.50986687074979e8 + 2.11518396291149e8*i, -1e-13);\n\n## Test conservation of the class (five tests for each subroutine).\n%!assert (class (gammainc (0, 1)) == \"double\")\n%!assert (class (gammainc (single (0), 1)) == \"single\")\n%!assert (class (gammainc (int8 (0), 1)) == \"double\")\n%!assert (class (gammainc (0, single (1))) == \"single\")\n%!assert (class (gammainc (0, int8 (1))) == \"double\")\n%!assert (class (gammainc (1, 0)) == \"double\")\n%!assert (class (gammainc (single (1), 0)) == \"single\")\n%!assert (class (gammainc (int8 (1), 0)) == \"double\")\n%!assert (class (gammainc (1, single (0))) == \"single\")\n%!assert (class (gammainc (1, int8 (0))) == \"double\")\n%!assert (class (gammainc (1, 1)) == \"double\")\n%!assert (class (gammainc (single (1), 1)) == \"single\")\n%!assert (class (gammainc (int8 (1), 1)) == \"double\")\n%!assert (class (gammainc (1, single (1))) == \"single\")\n%!assert (class (gammainc (1, int8 (1))) == \"double\")\n%!assert (class (gammainc (1, 2)) == \"double\")\n%!assert (class (gammainc (single (1), 2)) == \"single\")\n%!assert (class (gammainc (int8 (1), 2)) == \"double\")\n%!assert (class (gammainc (1, single (2))) == \"single\")\n%!assert (class (gammainc (1, int8 (2))) == \"double\")\n%!assert (class (gammainc (-1, 0.5)) == \"double\")\n%!assert (class (gammainc (single (-1), 0.5)) == \"single\")\n%!assert (class (gammainc (int8 (-1), 0.5)) == \"double\")\n%!assert (class (gammainc (-1, single (0.5))) == \"single\")\n%!assert (class (gammainc (-1, int8 (0.5))) == \"double\")\n%!assert (class (gammainc (1, 0.5)) == \"double\")\n%!assert (class (gammainc (single (1), 0.5)) == \"single\")\n%!assert (class (gammainc (int8 (1), 0.5)) == \"double\")\n%!assert (class (gammainc (1, single (0.5))) == \"single\")\n%!assert (class (gammainc (1, int8 (0.5))) == \"double\")\n\n## Test input validation\n%!error <Invalid call> gammainc ()\n%!error <Invalid call> gammainc (1)\n%!error <must be of common size or scalars> gammainc ([0, 0],[0; 0])\n%!error <must be of common size or scalars> gammainc ([1 2 3], [1 2])\n%!error <all inputs must be real> gammainc (2+i, 1)\n%!error <all inputs must be real> gammainc (1, 2+i)\n%!error <A must be non-negative> gammainc (1, [0, -1, 1])\n%!error <A must be non-negative>\n%! a = ones (2,2,2);\n%! a(1,1,2) = -1;\n%! gammainc (1, a);\n%!error <invalid value for TAIL> gammainc (1,2, \"foobar\")\n"
  },
  {
    "path": "scripts/specfun/gammaincinv.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} gammaincinv (@var{y}, @var{a})\n## @deftypefnx {} {@var{x} =} gammaincinv (@var{y}, @var{a}, @var{tail})\n## Compute the inverse of the normalized incomplete gamma function.\n##\n## The normalized incomplete gamma function is defined as\n## @tex\n## $$\n##  \\gamma (x, a) = {1 \\over {\\Gamma (a)}}\\displaystyle{\\int_0^x t^{a-1} e^{-t} dt}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##                                 x\n##                        1       /\n## gammainc (x, a) = ---------    | exp (-t) t^(a-1) dt\n##                   gamma (a)    /\n##                             t=0\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## and @code{gammaincinv (gammainc (@var{x}, @var{a}), @var{a}) = @var{x}}\n## for each non-negative value of @var{x}.  If @var{a} is scalar then\n## @code{gammaincinv (@var{y}, @var{a})} is returned for each element of\n## @var{y} and vice versa.\n##\n## If neither @var{y} nor @var{a} is scalar then the sizes of @var{y} and\n## @var{a} must agree, and @code{gammaincinv} is applied element-by-element.\n## The variable @var{y} must be in the interval @math{[0,1]} while @var{a} must\n## be real and positive.\n##\n## By default, @var{tail} is @qcode{\"lower\"} and the inverse of the incomplete\n## gamma function integrated from 0 to @var{x} is computed.  If @var{tail} is\n## @qcode{\"upper\"}, then the complementary function integrated from @var{x} to\n## infinity is inverted.\n##\n## The function is computed with Newton's method by solving\n## @tex\n## $$\n##  y - \\gamma (x, a) = 0\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @var{y} - gammainc (@var{x}, @var{a}) = 0\n## @end example\n##\n## @end ifnottex\n##\n## Reference: @nospell{A. Gil, J. Segura, and N. M. Temme}, \"Efficient and\n## accurate algorithms for the computation and inversion of the incomplete\n## gamma function ratios\", @cite{@nospell{SIAM J. Sci.@: Computing}},\n## @w{Vol.@: 34}, @w{pp.@: A2965}--A2981, 2012.\n##\n## @seealso{gammainc, gamma, gammaln}\n## @end deftypefn\n\nfunction x = gammaincinv (y, a, tail = \"lower\")\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  [err, y, a] = common_size (y, a);\n  if (err > 0)\n    error (\"gammaincinv: Y and A must be of common size or scalars\");\n  endif\n\n  if (iscomplex (y) || iscomplex (a))\n    error (\"gammaincinv: all inputs must be real\");\n  endif\n\n  ## Remember original shape of data, but convert to column vector for calcs.\n  orig_sz = size (y);\n  y = y(:);\n  a = a(:);\n\n  if (any ((y < 0) | (y > 1)))\n    error (\"gammaincinv: Y must be in the range [0, 1]\");\n  endif\n\n  if (any (a <= 0))\n    error (\"gammaincinv: A must be strictly positive\");\n  endif\n\n  ## If any of the arguments is single then the output should be as well.\n  if (strcmp (class (y), \"single\") || strcmp (class (a), \"single\"))\n    y = single (y);\n    a = single (a);\n  endif\n\n  ## Convert to floating point if necessary\n  if (isinteger (y))\n    y = double (y);\n  endif\n  if (isinteger (a))\n    a = double (a);\n  endif\n\n  ## Initialize output array\n  x = zeros (size (y), class (y));\n\n  maxit = 20;\n  tol = eps (class (y));\n\n  ## Special cases, a = 1 or y = 0, 1.\n\n  if (strcmpi (tail, \"lower\"))\n    x(a == 1) = - log1p (- y(a == 1));\n    x(y == 0) = 0;\n    x(y == 1) = Inf;\n    p = y;\n    q = 1 - p;\n  elseif (strcmpi (tail, \"upper\"))\n    x(a == 1) = - log (y(a == 1));\n    x(y == 0) = Inf;\n    x(y == 1) = 0;\n    q = y;\n    p = 1 - q;\n  else\n    error (\"gammaincinv: invalid value for TAIL\");\n  endif\n\n  todo = (a != 1) & (y != 0) & (y != 1);\n\n  ## Case 1: p small.\n\n  i_flag_1 = todo & (p < ((0.2 * (1 + a)) .^ a) ./ gamma (1 + a));\n\n  if (any (i_flag_1))\n    aa = a(i_flag_1);\n    pp = p(i_flag_1);\n\n    ## Initial guess.\n\n    r = (pp .* gamma (1 + aa)) .^ (1 ./ aa);\n\n    c2 = 1 ./ (aa + 1);\n    c3 = (3  * aa + 5) ./ (2 * (aa + 1) .^2 .* (aa + 2));\n    c4 = (8 * aa .^ 2 + 33 * aa + 31) ./ (3 * (aa + 1) .^ 3 .* (aa + 2) .* ...\n         (aa + 3));\n    c5 = (125 * aa .^ 4 + 1179 * aa .^ 3 + 3971 * aa.^2 + 5661 * aa + 2888) ...\n         ./ (24 * (1 + aa) .^4 .* (aa + 2) .^ 2 .* (aa + 3) .* (aa + 4));\n\n    ## FIXME: Would polyval() be better here for more accuracy?\n    x0 = r + c2 .* r .^ 2 + c3 .* r .^ 3 + c4 .* r .^4 + c5 .* r .^ 5;\n\n    ## For this case we invert the lower version.\n\n    F = @(p, a, x) p - gammainc (x, a, \"lower\");\n    JF = @(a, x) - exp (- gammaln (a) - x + (a - 1) .* log (x));\n    x(i_flag_1) = newton_method (F, JF, pp, aa, x0, tol, maxit);\n  endif\n\n  todo(i_flag_1) = false;\n\n  ## Case 2: q small.\n\n  i_flag_2 = (q < exp (- 0.5 * a) ./ gamma (1 + a)) & (a > 0) & (a < 10);\n  i_flag_2 &= todo;\n\n  if (any (i_flag_2))\n    aa = a(i_flag_2);\n    qq = q(i_flag_2);\n\n    ## Initial guess.\n\n    x0 = (-log (qq) - gammaln (aa));\n\n    ## For this case, we invert the upper version.\n\n    F = @(q, a, x) q - gammainc (x, a, \"upper\");\n    JF = @(a, x) exp (- gammaln (a) - x) .* x .^ (a - 1);\n    x(i_flag_2) = newton_method (F, JF, qq, aa, x0, tol, maxit);\n  endif\n\n  todo(i_flag_2) = false;\n\n  ## Case 3: a small.\n\n  i_flag_3 = todo & ((a > 0) & (a < 1));\n\n  if (any (i_flag_3))\n    aa = a(i_flag_3);\n    pp = p(i_flag_3);\n\n    ## Initial guess\n\n    xl = (pp .* gamma (aa + 1)) .^ (1 ./ aa);\n    x0 = xl;\n\n    ## For this case, we invert the lower version.\n\n    F = @(p, a, x) p - gammainc (x, a, \"lower\");\n    JF = @(a, x) - exp (-gammaln (a) - x) .* x .^ (a - 1);\n    x(i_flag_3) = newton_method (F, JF, pp, aa, x0, tol, maxit);\n  endif\n\n  todo(i_flag_3) = false;\n\n  ## Case 4: a large.\n\n  i_flag_4 = todo;\n\n  if (any (i_flag_4))\n    aa = a(i_flag_4);\n    qq = q(i_flag_4);\n\n    ## Initial guess\n\n    d = 1 ./ (9 * aa);\n    t = 1 - d + sqrt (2) * erfcinv (2 * qq) .* sqrt (d);\n    x0 = aa .* (t .^ 3);\n\n    ## For this case, we invert the upper version.\n\n    F = @(q, a, x) q - gammainc (x, a, \"upper\");\n    JF = @(a, x) exp (- gammaln (a) - x + (a - 1) .* log (x));\n    x(i_flag_4) = newton_method (F, JF, qq, aa, x0, tol, maxit);\n  endif\n\n  ## Restore original shape\n  x = reshape (x, orig_sz);\n\nendfunction\n\n## subfunction: Newton's Method\nfunction x = newton_method (F, JF, y, a, x0, tol, maxit)\n\n  l = numel (y);\n  res = -F (y, a, x0) ./ JF (a, x0);\n  todo = (abs (res) >= tol * abs (x0));\n  x = x0;\n  it = 0;\n  while (any (todo) && (it++ < maxit))\n    x(todo) += res(todo);\n    res(todo) = -F (y(todo), a(todo), x(todo)) ./ JF (a(todo), x(todo));\n    todo = (abs (res) >= tol * abs (x));\n  endwhile\n  x += res;\n\nendfunction\n\n\n%!test\n%! x = [1e-10, 1e-09, 1e-08, 1e-07];\n%! a = [2, 3, 4];\n%! [x, a] = ndgrid (x, a);\n%! xx = gammainc (gammaincinv (x, a), a);\n%! assert (xx, x, -3e-14);\n\n%!test\n%! x = [1e-10, 1e-09, 1e-08, 1e-07];\n%! a = [2, 3, 4];\n%! [x, a] = ndgrid (x, a);\n%! xx = gammainc (gammaincinv (x, a, \"upper\"), a, \"upper\");\n%! assert (xx, x, -3e-14);\n\n%!test\n%! x = linspace (0, 1)';\n%! a = [linspace(0.1, 1, 10), 2:5];\n%! [x, a] = ndgrid (x, a);\n%! xx = gammainc (gammaincinv (x, a), a);\n%! assert (xx, x, -1e-13);\n\n%!test\n%! x = linspace (0, 1)';\n%! a = [linspace(0.1, 1, 10), 2:5];\n%! [x, a] = ndgrid (x, a);\n%! xx = gammainc (gammaincinv (x, a, \"upper\"), a, \"upper\");\n%! assert (xx, x, -1e-13);\n\n%!test <*56453>\n%! assert (gammaincinv (1e-15, 1) * 2, 2e-15, -1e-15);\n%! assert (gammaincinv (1e-16, 1) * 2, 2e-16, -1e-15);\n\n## Test the conservation of the input class\n%!assert (class (gammaincinv (0.5, 1)), \"double\")\n%!assert (class (gammaincinv (single (0.5), 1)), \"single\")\n%!assert (class (gammaincinv (0.5, single (1))), \"single\")\n%!assert (class (gammaincinv (int8 (0), 1)), \"double\")\n%!assert (class (gammaincinv (0.5, int8 (1))), \"double\")\n%!assert (class (gammaincinv (int8 (0), single (1))), \"single\")\n%!assert (class (gammaincinv (single (0.5), int8 (1))), \"single\")\n\n## Test input validation\n%!error <Invalid call> gammaincinv ()\n%!error <Invalid call> gammaincinv (1)\n%!error <must be of common size or scalars>\n%! gammaincinv (ones (2,2), ones (1,2), 1);\n%!error <all inputs must be real> gammaincinv (0.5i, 1)\n%!error <all inputs must be real> gammaincinv (0, 1i)\n%!error <Y must be in the range \\[0, 1\\]> gammaincinv (-0.1,1)\n%!error <Y must be in the range \\[0, 1\\]> gammaincinv (1.1,1)\n%!error <Y must be in the range \\[0, 1\\]>\n%! y = ones (1, 1, 2);\n%! y(1,1,2) = -1;\n%! gammaincinv (y,1);\n%!error <A must be strictly positive> gammaincinv (0.5, 0)\n%!error <A must be strictly positive>\n%! a = ones (1, 1, 2);\n%! a(1,1,2) = 0;\n%! gammaincinv (1,a,1);\n%!error <invalid value for TAIL> gammaincinv (1,2, \"foobar\")\n"
  },
  {
    "path": "scripts/specfun/isprime.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isprime (@var{x})\n## Return a logical array which is true where the elements of @var{x} are prime\n## numbers and false where they are not.\n##\n## A prime number is conventionally defined as a positive integer greater than\n## 1 (e.g., 2, 3, @dots{}) which is divisible only by itself and 1.  Octave\n## extends this definition to include both negative integers and complex\n## values.  A negative integer is prime if its positive counterpart is prime.\n## This is equivalent to @code{isprime (abs (x))}.\n##\n## If @code{class (@var{x})} is complex, then primality is tested in the domain\n## of Gaussian integers (@url{https://en.wikipedia.org/wiki/Gaussian_integer}).\n## Some non-complex integers are prime in the ordinary sense, but not in the\n## domain of Gaussian integers.  For example, @math{5 = (1+2i)*(1-2i)} shows\n## that 5 is not prime because it has a factor other than itself and 1.\n## Exercise caution when testing complex and real values together in the same\n## matrix.\n##\n## Examples:\n##\n## @example\n## @group\n## isprime (1:6)\n##   @xresult{}  0  1  1  0  1  0\n## @end group\n## @end example\n##\n## @example\n## @group\n## isprime ([i, 2, 3, 5])\n##   @xresult{}  0  0  1  0\n## @end group\n## @end example\n##\n## Programming Note: @code{isprime} is suitable for all @var{x}\n## in the range abs(@var{x})\n## @tex\n## $ < 2^{64}$.\n## @end tex\n## @ifnottex\n##  < 2^64.\n## @end ifnottex\n## Cast inputs larger than @code{flintmax} to @code{uint64}.\n##\n## For larger inputs, use ‘sym’ if you have the Symbolic package installed\n## and loaded:\n##\n## @example\n## @group\n## isprime (sym ('58745389709258902525390450') + (0:4))\n##    @xresult{}  0  1  0  0  0\n## @end group\n## @end example\n##\n## Compatibility Note: @sc{matlab} does not extend the definition of prime\n## numbers and will produce an error if given negative or complex inputs.\n## @seealso{primes, factor, gcd, lcm}\n## @end deftypefn\n\nfunction tf = isprime (x)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (any (fix (x) != x))\n    error (\"isprime: X contains non-integer entries\");\n  endif\n\n  if (isempty (x))\n    tf = x;\n    return;\n  endif\n\n  if (iscomplex (x))\n    tf = isgaussianprime (x);\n    return;\n  endif\n\n  ## Code strategy is to quickly compare entries in x with small primes\n  ## using lookup(), then do direct division on larger numbers up to\n  ## a threshold, then call Miller-Rabin for numbers over the threshold.\n\n  x = abs (x);  # handle negative entries\n\n  ## Generate prime table of suitable length up to maxp.\n  ## The value of maxp needs to be at least 37,\n  ## because of the method used by __isprimelarge__ below.\n  maxp = 37;\n  pr = [2 3 5 7 11 13 17 19 23 29 31 37];\n  tf = lookup (pr, x, \"b\");  # quick search for table matches.\n\n  THRESHOLD = 18e9;\n  ## FIXME: THRESHOLD is the input value at which Miller-Rabin\n  ## becomes more efficient than direct division.  For smaller numbers,\n  ## use direct division.  For larger numbers, use Miller-Rabin.\n  ##\n  ## Last updated in Jan 2026, using this test code:\n  ##   n = THRESHOLD - (1:1e7); tic; isprime(n); toc\n  ##   n = THRESHOLD + (1:1e7); tic; isprime(n); toc\n  ##\n  ## Two notes for future programmers:\n  ##\n  ## 1. Test and tune THRESHOLD periodically so that the two times are equal.\n  ##    Miller-Rabin is only CPU-limited, while factorization by division is\n  ##    very memory-intensive.  CPU speed and RAM speed scale differently over\n  ##    time, so test and tune THRESHOLD periodically.\n  ##\n  ## 2. If you make improvements elsewhere in the code that favor one over\n  ##    the other (not symmetric), you should also retune THRESHOLD afterwards.\n  ##    If the Miller-Rabin part is sped up, the optimum THRESHOLD will\n  ##    decrease, and if factorization is sped up, it will increase.\n\n  ## Process large entries that are still suitable for direct division\n  m = x (x > maxp & x <= THRESHOLD);\n  if ( ! isempty (m))\n    ## Start by dividing through by the small primes until the remaining list\n    ## of entries is small (and most likely prime themselves).\n    pr2 = primes (sqrt (max (m)));\n    tf |= lookup (pr2, x, \"b\");\n    for p = pr2\n      m = m(rem (m, p) != 0);\n      if (numel (m) < numel (pr2) / 10)\n        break;\n      endif\n    endfor\n\n    ## Check the remaining list of possible primes against the remaining\n    ## prime factors which were not tested in the for loop.\n    ## This is just an optimization to use arrayfun over for loop.\n    pr2 = pr2 (pr2 > p);\n    mm = arrayfun (@(x) all (rem (x, pr2)), m);\n    m = m(mm);\n\n    ## Add any remaining entries, which are truly prime, to the results.\n    if ( ! isempty (m))\n      tf |= lookup (sort (m), x, \"b\");\n    endif\n  endif\n\n  ## Process remaining entries (everything above THRESHOLD) with Miller-Rabin\n  ii = (x(:)' > THRESHOLD);\n  tf(ii) = __isprimelarge__ (x(ii));\n\nendfunction\n\nfunction tf = isgaussianprime (z)\n\n  ## Assume prime unless proven otherwise\n  tf = true (size (z));\n\n  x = real (z);\n  y = imag (z);\n\n  ## If purely real or purely imaginary, ordinary prime test for\n  ## that complex part if that part is 3 mod 4.\n  xidx = y==0 & mod (x, 4) == 3;\n  yidx = x==0 & mod (y, 4) == 3;\n\n  tf(xidx) &= isprime (x(xidx));\n  tf(yidx) &= isprime (y(yidx));\n\n  ## Otherwise, prime if x^2 + y^2 is prime\n  zidx = ! (xidx | yidx);          # Skip entries that were already evaluated\n  zabs = x(zidx).^2 + y(zidx).^2;\n  tf(zidx) &= isprime (zabs);\n\nendfunction\n\n\n%!assert (isprime (3), true)\n%!assert (isprime (4), false)\n%!assert (isprime (uint64 (18446744073709551557)), true)\n%!assert (isprime (5i), false)\n%!assert (isprime (7i), true)\n%!assert (isprime ([1+2i, (2+3i)*(-1+2i)]), [true, false])\n%!assert (isprime (-2), true)\n%!assert (isprime (complex (-2)), false)\n%!assert (isprime (2i), false)\n%!assert (isprime ([i, 2, 3, 5]), [false, false, true, false])\n%!assert (isprime (0), false)\n%!assert (isprime (magic (3)), logical ([0, 0, 0; 1, 1, 1; 0, 0, 1]))\n\n## Test input validation\n%!error <Invalid call> isprime ()\n%!error <X contains non-integer entries> isprime (0.5i)\n%!error <X contains non-integer entries> isprime (0.5)\n"
  },
  {
    "path": "scripts/specfun/lcm.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{l} =} lcm (@var{x}, @var{y})\n## @deftypefnx {} {@var{l} =} lcm (@var{x}, @var{y}, @dots{})\n## Compute the least common multiple of @var{x} and @var{y}, or of the list of\n## all arguments.\n##\n## All inputs must be of the same size, or scalar.  All elements must be\n## real integer or Gaussian (complex) integer.  For complex inputs, the result\n## is unique only up to a phase factor (multiplication by +1, +i, -1, or -i),\n## and one of the four is returned arbitrarily.\n##\n## Example code:\n##\n## @example\n## @group\n## lcm (5:8, 9:12)\n##    @xresult{}  45  30  77  24\n## @end group\n## @end example\n##\n## Programming tip: To find the LCM of all the elements of a single array, use\n## @code{num2cell} instead of nested calls or a loop:\n##\n## @example\n## @group\n## x = 1:10;    # vector or array of inputs\n## lcm (num2cell (x) @{:@})\n##    @xresult{}     2520\n## @end group\n## @end example\n## @seealso{factor, gcd, isprime}\n## @end deftypefn\n\nfunction l = lcm (varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (common_size (varargin{:}) != 0)\n    error (\"lcm: all args must be the same size or scalar\");\n  elseif (! all (cellfun (\"isnumeric\", varargin)))\n    error (\"lcm: all arguments must be numeric\");\n  endif\n\n  l = varargin{1};\n  for i = 2:nargin\n    x = varargin{i};\n    msk = (l == 0 & x == 0);\n    l .*= x ./ gcd (l, x);\n    l(msk) = 0;\n  endfor\n\n  if (isfloat (l) && l > flintmax (l))\n    warning (\"Octave:lcm:large-output-float\", ...\n             \"lcm: possible loss of precision\");\n  elseif (isinteger (l) && l == intmax (l))\n    warning (\"Octave:lcm:large-output-integer\", ...\n             \"lcm: result may have saturated at intmax\");\n  endif\n\nendfunction\n\n\n%!assert (lcm (3, 5, 7, 15), 105)\n\n## Test input validation\n%!error <Invalid call> lcm ()\n%!error <Invalid call> lcm (1)\n%!error <same size or scalar> lcm ([1 2], [1 2 3])\n%!error <arguments must be numeric> lcm ([1 2], {1 2})\n%!warning <loss of precision>   lcm (num2cell (double (1:47)){:});\n%!warning <loss of precision>   lcm (num2cell (single (1:47)){:});\n%!warning <result .* saturated> lcm (num2cell (uint64 (1:47)){:});\n%!warning <result .* saturated> lcm (num2cell (uint32 (1:47)){:});\n%!warning <result .* saturated> lcm (num2cell (uint16 (1:47)){:});\n%!warning <result .* saturated> lcm (num2cell ( uint8 (1:47)){:});\n%!warning <result .* saturated> lcm (num2cell ( int64 (1:47)){:});\n%!warning <result .* saturated> lcm (num2cell ( int32 (1:47)){:});\n%!warning <result .* saturated> lcm (num2cell ( int16 (1:47)){:});\n%!warning <result .* saturated> lcm (num2cell (  int8 (1:47)){:});\n"
  },
  {
    "path": "scripts/specfun/legendre.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{l} =} legendre (@var{n}, @var{x})\n## @deftypefnx {} {@var{l} =} legendre (@var{n}, @var{x}, @var{normalization})\n## Compute the associated Legendre function of degree @var{n} and order\n## @var{m} = 0 @dots{} @var{n}.\n##\n## The value @var{n} must be a real non-negative integer.\n##\n## @var{x} is a vector with real-valued elements in the range [-1, 1].\n##\n## The optional argument @var{normalization} may be one of @qcode{\"unnorm\"},\n## @qcode{\"sch\"}, or @qcode{\"norm\"}.  The default if no normalization is given\n## is @qcode{\"unnorm\"}.\n##\n## When the optional argument @var{normalization} is @qcode{\"unnorm\"}, compute\n## the associated Legendre function of degree @var{n} and order @var{m} and\n## return all values for @var{m} = 0 @dots{} @var{n}.  The return value has one\n## dimension more than @var{x}.\n##\n## The associated Legendre function of degree @var{n} and order @var{m}:\n## @tex\n## $$\n## P^m_n(x) = (-1)^m (1-x^2)^{m/2}{d^m\\over {dx^m}}P_n (x)\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##  m         m      2  m/2   d^m\n## P(x) = (-1) * (1-x  )    * ----  P(x)\n##  n                         dx^m   n\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @noindent\n## with Legendre polynomial of degree @var{n}:\n## @tex\n## $$\n## P(x) = {1\\over{2^n n!}}\\biggl({d^n\\over{dx^n}}(x^2 - 1)^n\\biggr)\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##           1    d^n   2    n\n## P(x) = ------ [----(x - 1) ]\n##  n     2^n n!  dx^n\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @noindent\n## @code{legendre (3, [-1.0, -0.9, -0.8])} returns the matrix:\n##\n## @example\n## @group\n##  x  |   -1.0   |   -0.9   |   -0.8\n## ------------------------------------\n## m=0 | -1.00000 | -0.47250 | -0.08000\n## m=1 |  0.00000 | -1.99420 | -1.98000\n## m=2 |  0.00000 | -2.56500 | -4.32000\n## m=3 |  0.00000 | -1.24229 | -3.24000\n## @end group\n## @end example\n##\n## When the optional argument @var{normalization} is @qcode{\"sch\"}, compute\n## the Schmidt semi-normalized associated Legendre function.  The Schmidt\n## semi-normalized associated Legendre function is related to the unnormalized\n## Legendre functions by the following:\n##\n## For Legendre functions of degree @var{n} and order 0:\n## @tex\n## $$\n## SP^0_n (x) = P^0_n (x)\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##   0      0\n## SP(x) = P(x)\n##   n      n\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## For Legendre functions of degree n and order m:\n## @tex\n## $$\n## SP^m_n (x) = P^m_n (x)(-1)^m\\biggl({2(n-m)!\\over{(n+m)!}}\\biggl)^{0.5}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##   m      m         m    2(n-m)! 0.5\n## SP(x) = P(x) * (-1)  * [-------]\n##   n      n              (n+m)!\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## When the optional argument @var{normalization} is @qcode{\"norm\"}, compute\n## the fully normalized associated Legendre function.  The fully normalized\n## associated Legendre function is related to the unnormalized associated\n## Legendre functions by the following:\n##\n## For Legendre functions of degree @var{n} and order @var{m}\n## @tex\n## $$\n## NP^m_n (x) = P^m_n (x)(-1)^m\\biggl({(n+0.5)(n-m)!\\over{(n+m)!}}\\biggl)^{0.5}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##   m      m         m    (n+0.5)(n-m)! 0.5\n## NP(x) = P(x) * (-1)  * [-------------]\n##   n      n                  (n+m)!\n## @end group\n## @end example\n##\n## @end ifnottex\n## @end deftypefn\n\nfunction retval = legendre (n, x, normalization)\n\n  persistent warned_overflow = false;\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! isreal (n) || ! isscalar (n) || n < 0 || n != fix (n))\n    error (\"legendre: N must be a real non-negative integer\");\n  elseif (! isreal (x) || any (x(:) < -1 | x(:) > 1))\n    error (\"legendre: X must be real-valued vector in the range -1 <= X <= 1\");\n  endif\n\n  if (nargin == 3)\n    normalization = lower (normalization);\n  else\n    normalization = \"unnorm\";\n  endif\n\n  unnorm = false;\n  switch (normalization)\n    case \"unnorm\"\n      scale = 1;\n      unnorm = true;\n    case \"norm\"\n      scale = sqrt (n+0.5);\n    case \"sch\"\n      scale = sqrt (2);\n    otherwise\n      error ('legendre: NORMALIZATION option must be \"unnorm\", \"norm\", or \"sch\"');\n  endswitch\n\n  scale *= ones (size (x));\n\n  ## Based on the recurrence relation below\n  ##            m                 m              m\n  ## (n-m+1) * P (x) = (2*n+1)*x*P (x)  - (n+m)*P (x)\n  ##            n+1               n              n-1\n  ## https://en.wikipedia.org/wiki/Associated_Legendre_polynomials\n\n  overflow = false;\n  retval = zeros ([n+1, size(x)]);\n  for m = 1:n\n    lpm1 = scale;\n    lpm2 = (2*m-1) .* x .* scale;\n    lpm3 = lpm2;\n    for k = m+1:n\n      lpm3a = (2*k-1) .* x .* lpm2;\n      lpm3b = (k+m-2) .* lpm1;\n      lpm3 = (lpm3a - lpm3b) / (k-m+1);\n      lpm1 = lpm2;\n      lpm2 = lpm3;\n      if (! warned_overflow)\n        if (   any (abs (lpm3a) > realmax)\n            || any (abs (lpm3b) > realmax)\n            || any (abs (lpm3)  > realmax))\n          overflow = true;\n        endif\n      endif\n    endfor\n    retval(m,:) = lpm3(:);\n    if (unnorm)\n      scale *= -(2*m-1);\n    else  # normalization = \"sch\" or \"norm\"\n      scale *= (2*m-1) / sqrt ((n-m+1)*(n+m));\n    endif\n    scale .*= sqrt (1-x.^2);\n  endfor\n\n  retval(n+1,:) = scale(:);\n\n  if (isvector (x))\n    ## vector case is special\n    retval = reshape (retval, n + 1, length (x));\n  endif\n\n  if (strcmp (normalization, \"sch\"))\n    retval(1,:) ./= sqrt (2);\n  endif\n\n  if (overflow && ! warned_overflow)\n    warning (\"legendre: overflow - results may be unstable for high orders\");\n    warned_overflow = true;\n  endif\n\nendfunction\n\n\n%!test\n%! result = legendre (3, [-1.0 -0.9 -0.8]);\n%! expected = [\n%!    -1.00000  -0.47250  -0.08000\n%!     0.00000  -1.99420  -1.98000\n%!     0.00000  -2.56500  -4.32000\n%!     0.00000  -1.24229  -3.24000\n%! ];\n%! assert (result, expected, 1e-5);\n\n%!test\n%! result = legendre (3, [-1.0 -0.9 -0.8], \"sch\");\n%! expected = [\n%!    -1.00000  -0.47250  -0.08000\n%!     0.00000   0.81413   0.80833\n%!    -0.00000  -0.33114  -0.55771\n%!     0.00000   0.06547   0.17076\n%! ];\n%! assert (result, expected, 1e-5);\n\n%!test\n%! result = legendre (3, [-1.0 -0.9 -0.8], \"norm\");\n%! expected = [\n%!    -1.87083  -0.88397  -0.14967\n%!     0.00000   1.07699   1.06932\n%!    -0.00000  -0.43806  -0.73778\n%!     0.00000   0.08661   0.22590\n%! ];\n%! assert (result, expected, 1e-5);\n\n%!test\n%! result = legendre (151, 0);\n%! ## Don't compare to \"-Inf\" since it would fail on 64 bit systems.\n%! assert (result(end) < -1.7976e308 && all (isfinite (result(1:end-1))));\n\n%!test\n%! result = legendre (150, 0);\n%! ## This agrees with Matlab's result.\n%! assert (result(end), 3.7532741115719e+306, 0.0000000000001e+306);\n\n%!test\n%! result = legendre (0, 0:0.1:1);\n%! assert (result, full (ones (1,11)));\n\n%!test\n%! ## Test matrix input\n%! result = legendre (3, [-1,0,1;1,0,-1]);\n%! expected(:,:,1) = [-1,1;0,0;0,0;0,0];\n%! expected(:,:,2) = [0,0;1.5,1.5;0,0;-15,-15];\n%! expected(:,:,3) = [1,-1;0,0;0,0;0,0];\n%! assert (result, expected);\n\n%!test\n%! result = legendre (3, [-1,0,1;1,0,-1]');\n%! expected(:,:,1) = [-1,0,1;0,1.5,0;0,0,0;0,-15,0];\n%! expected(:,:,2) = [1,0,-1;0,1.5,0;0,0,0;0,-15,0];\n%! assert (result, expected);\n\n## Test input validation\n%!error <Invalid call> legendre ()\n%!error <Invalid call> legendre (1)\n%!error <must be a real non-negative integer> legendre (i, [-1, 0, 1])\n%!error <must be a real non-negative integer> legendre ([1, 2], [-1, 0, 1])\n%!error <must be a real non-negative integer> legendre (-1, [-1, 0, 1])\n%!error <must be a real non-negative integer> legendre (1.1, [-1, 0, 1])\n%!error <must be real-valued vector> legendre (1, [-1+i, 0, 1])\n%!error <in the range -1 .= X .= 1> legendre (1, [-2, 0, 1])\n%!error <in the range -1 .= X .= 1> legendre (1, [-1, 0, 2])\n%!error <NORMALIZATION option must be> legendre (1, [-1, 0, 1], \"badnorm\")\n"
  },
  {
    "path": "scripts/specfun/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/beta.m \\\n  %reldir%/betainc.m \\\n  %reldir%/betaincinv.m \\\n  %reldir%/betaln.m \\\n  %reldir%/cosint.m \\\n  %reldir%/ellipke.m \\\n  %reldir%/expint.m \\\n  %reldir%/factor.m \\\n  %reldir%/factorial.m \\\n  %reldir%/gammainc.m \\\n  %reldir%/gammaincinv.m \\\n  %reldir%/isprime.m \\\n  %reldir%/lcm.m \\\n  %reldir%/legendre.m \\\n  %reldir%/nchoosek.m \\\n  %reldir%/nthroot.m \\\n  %reldir%/primes.m \\\n  %reldir%/reallog.m \\\n  %reldir%/realpow.m \\\n  %reldir%/realsqrt.m \\\n  %reldir%/sinint.m\n\n%canon_reldir%dir = $(fcnfiledir)/specfun\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/specfun/nchoosek.m",
    "content": "########################################################################\n##\n## Copyright (C) 2001-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} nchoosek (@var{n}, @var{k})\n## @deftypefnx {} {@var{c} =} nchoosek (@var{set}, @var{k})\n##\n## Compute the binomial coefficient of @var{n} or list all possible\n## combinations of a @var{set} of items.\n##\n## If @var{n} is a scalar then calculate the binomial coefficient\n## of @var{n} and @var{k} which is defined as\n## @tex\n## $$\n##  {n \\choose k} = {n (n-1) (n-2) \\cdots (n-k+1) \\over k!}\n##                = {n! \\over k! (n-k)!}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##  /   \\\n##  | n |    n (n-1) (n-2) @dots{} (n-k+1)       n!\n##  |   |  = ------------------------- =  ---------\n##  | k |               k!                k! (n-k)!\n##  \\   /\n## @end group\n## @end example\n##\n## @end ifnottex\n## @noindent\n## This is the number of combinations of @var{n} items taken in groups of\n## size @var{k}.\n##\n## If the first argument is a vector, @var{set}, then generate all\n## combinations of the elements of @var{set}, taken @var{k} at a time, with\n## one row per combination.  The result @var{c} has @var{k} columns and\n## @w{@code{nchoosek (length (@var{set}), @var{k})}}@ rows.\n##\n## For example:\n##\n## How many ways can three items be grouped into pairs?\n##\n## @example\n## @group\n## nchoosek (3, 2)\n##    @xresult{} 3\n## @end group\n## @end example\n##\n## What are the possible pairs?\n##\n## @example\n## @group\n## nchoosek (1:3, 2)\n##    @xresult{}  1   2\n##        1   3\n##        2   3\n## @end group\n## @end example\n##\n## Programming Note: When calculating the binomial coefficient @code{nchoosek}\n## works only for non-negative, integer arguments.  Use @code{bincoeff} for\n## non-integer and negative scalar arguments, or for computing many binomial\n## coefficients at once with vector inputs for @var{n} or @var{k}.\n##\n## @seealso{bincoeff, perms}\n## @end deftypefn\n\nfunction C = nchoosek (v, k)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! isvector (v))\n    error (\"nchoosek: first argument must be a scalar or a vector\");\n  endif\n  if (! (isreal (k) && isscalar (k) && k >= 0 && k == fix (k)))\n    error (\"nchoosek: K must be an integer >= 0\");\n  endif\n  if (isscalar (v))\n    if (isnumeric (v) && (iscomplex (v) || v < k || v < 0 || v != fix (v)))\n      error (\"nchoosek: N must be a non-negative integer >= K\");\n    endif\n  endif\n\n  v = v(:).';  # convert to row vector\n  n = numel (v);\n\n  if (n == 1 && isnumeric (v))\n    ## Compute number of combinations rather than actual set combinations.\n    try\n      ## Use subtraction operation to validate combining integer data types\n      ## and for type propagation rules between integer and floating point.\n      k = min (k, v-k);\n    catch\n      error (\"nchoosek: incompatible input types for N (%s), K (%s)\", ...\n             class (v), class (k));\n    end_try_catch\n    is_int = isinteger (k);\n    if (is_int)\n      imax = intmax (k);\n    else\n      imax = flintmax (k);\n    endif\n    C = 1;\n    for i = 1:k\n      if (C * (v - k + i) >= imax)\n        ## Avoid overflow / precision loss by determining the smallest\n        ## possible factor of (C * (n-k+i)) and i via the gcd.\n        ## Note that by design in each iteration\n        ##   1) C will always increase (factor is always > 1).\n        ##   2) C will always be a whole number.\n        ## Therefore, using the gcd will always provide the best possible\n        ## solution until saturation / has the least precision loss.\n        g1 = gcd (C, i);\n        g2 = gcd (v - k + i, i/g1);\n        C /= g1;\n\n        ## In theory and (always for integers) i/(g1 * g2) is identical to 1 by\n        ## design.  Or for floats and beyond flintmax, the gcd may not be\n        ## correctly derived by the gcd function and i/(g1 * g2) may not be 1.\n        C_next = C * ((v - k + i)/g2);\n        if (is_int || (i/(g1 * g2) == 1) || ! isinf (C_next))\n          C = C_next;\n          C /= i/(g1 * g2);\n        else\n          C /= i/(g1 * g2);\n          ## We have potential precision loss by dividing (too) early, but\n          ## advantage is that we prevent possible interim overflows\n          C *= (v - k + i)/g2;\n        endif\n        if (is_int && (C == imax)) || (! is_int && isinf (C))\n          break;  # Stop here; saturation reached.\n        endif\n      else\n        C *= (v - k + i);\n        C /= i;\n      endif\n    endfor\n    if (! is_int && C > imax)\n      warning (\"Octave:nchoosek:large-output-float\", ...\n               \"nchoosek: possible loss of precision\");\n    elseif (is_int && C == imax)\n      warning (\"Octave:nchoosek:large-output-integer\", ...\n               \"nchoosek: result may have saturated at intmax\");\n    endif\n\n  ## Compute actual set combinations\n  elseif (k == 0)\n    C = v(zeros (1, 0));  # Return 1x0 object for Matlab compatibility\n  elseif (k == 1)\n    C = v(:);\n  elseif (k == n)\n    C = v;\n  elseif (k > n)\n    C = v(zeros (0, k));  # return 0xk object for Matlab compatibility\n  elseif (k == 2)\n    ## Can do it without transpose.\n    x = repelem (v(1:n-1), [n-1:-1:1]).';\n    y = cat (1, cellslices (v(:), 2:n, n*ones (1, n-1)){:});\n    C = [x, y];\n  elseif (k < n)\n    C = v(k:n);\n    l = 1:n-k+1;\n    for j = 2:k\n      c = columns (C);\n      cA = cellslices (C, l, c*ones (1, n-k+1), 2);\n      l = c-l+1;\n      b = repelem (v(k-j+1:n-j+1), l);\n      C = [b; cA{:}];\n      l = cumsum (l);\n      l = [1, 1 + l(1:n-k)];\n    endfor\n    C = C.';\n  endif\n\nendfunction\n\n\n%!assert (nchoosek (80, 10), bincoeff (80, 10))\n%!assert (nchoosek (1:5, 3),\n%!        [1:3;1,2,4;1,2,5;1,3,4;1,3,5;1,4,5;2:4;2,3,5;2,4,5;3:5])\n\n## Test basic behavior for various input types\n%!assert (nchoosek ('a':'b', 2), 'ab')\n%!assert (nchoosek (\"a\":\"b\", 2), \"ab\")\n%!assert (nchoosek ({1,2}, 2), {1,2})\n%!test\n%! s(1).a = 1;\n%! s(2).a = 2;\n%! assert (nchoosek (s, 1), s(:));\n%! assert (nchoosek (s, 2), s);\n\n## Verify Matlab compatibility of return sizes & types\n%!test\n%! x = nchoosek (1:2, 0);\n%! assert (size (x), [1, 0]);\n%! assert (isa (x, \"double\"));\n%! x = nchoosek (1:2, 3);\n%! assert (size (x), [0, 3]);\n%! assert (isa (x, \"double\"));\n\n%!test\n%! x = nchoosek (single (1:2), 0);\n%! assert (size (x), [1, 0]);\n%! assert (isa (x, \"single\"));\n%! x = nchoosek (single (1:2), 3);\n%! assert (size (x), [0, 3]);\n%! assert (isa (x, \"single\"));\n\n%!test\n%! x = nchoosek ('a':'b', 0);\n%! assert (size (x), [1, 0]);\n%! assert (is_sq_string (x));\n%! x = nchoosek ('a':'b', 3);\n%! assert (size (x), [0, 3]);\n%! assert (is_sq_string (x));\n\n%!test\n%! x = nchoosek (\"a\":\"b\", 0);\n%! assert (size (x), [1, 0]);\n%! assert (is_dq_string (x));\n%! x = nchoosek (\"a\":\"b\", 3);\n%! assert (size (x), [0, 3]);\n%! assert (is_dq_string (x));\n\n%!test\n%! x = nchoosek (uint8(1):uint8(2), 0);\n%! assert (size (x), [1, 0]);\n%! assert (isa (x, \"uint8\"));\n%! x = nchoosek (uint8(1):uint8(2), 3);\n%! assert (size (x), [0, 3]);\n%! assert (isa (x, \"uint8\"));\n\n%!test\n%! x = nchoosek ({1, 2}, 0);\n%! assert (size (x), [1, 0]);\n%! assert (iscell (x));\n%! x = nchoosek ({1, 2}, 3);\n%! assert (size (x), [0, 3]);\n%! assert (iscell (x));\n\n%!test\n%! s.a = [1 2 3];\n%! s.b = [4 5 6];\n%! x = nchoosek (s, 0);\n%! assert (size (x), [1, 0]);\n%! assert (isstruct (x));\n%! assert (fieldnames (x), {\"a\"; \"b\"});\n%! x = nchoosek (s, 3);\n%! assert (size (x), [0, 3]);\n%! assert (isstruct (x));\n%! assert (fieldnames (x), {\"a\"; \"b\"});\n\n%!test\n%! s.a = [1 2 3];\n%! s.b = [4 5 6];\n%! s(2).a = 1;  # make s a struct array rather than scalar struct\n%! s(3).b = 2;  # make s at least three elements for k == 2 test below\n%! x = nchoosek (s, 0);\n%! assert (size (x), [1, 0]);\n%! assert (isstruct (x));\n%! assert (fieldnames (x), {\"a\"; \"b\"});\n%! x = nchoosek (s, 2);\n%! assert (size (x), [3, 2]);\n%! assert (isstruct (x));\n%! assert (fieldnames (x), {\"a\"; \"b\"});\n%! x = nchoosek (s, 4);\n%! assert (size (x), [0, 4]);\n%! assert (isstruct (x));\n%! assert (fieldnames (x), {\"a\"; \"b\"});\n\n%!test <61565>\n%! x = nchoosek (uint8 (10), uint8 (5));\n%! assert (x, uint8 (252));\n%! assert (class (x), \"uint8\");\n\n## Floating point number above flintmax\n%!test <*65495>\n%! warning (\"off\", \"Octave:nchoosek:large-output-float\", \"local\");\n%! assert (! isinf (nchoosek (1024, 512)));\n\n## Test combining rules for integers and floating point\n%!test\n%! x = nchoosek (uint8 (10), single (5));\n%! assert (x, uint8 (252));\n\n%!test\n%! x = nchoosek (double (10), single (5));\n%! assert (x, single (252));\n\n%!test <*63538>\n%! x = nchoosek ([1:3]', 2);\n%! assert (x, [1 2; 1 3; 2 3]);\n\n## Test input validation\n%!error <Invalid call> nchoosek ()\n%!error <Invalid call> nchoosek (1)\n%!error <first argument must be a scalar or a vector> nchoosek (ones (3, 3), 1)\n%!error <K must be an integer .= 0> nchoosek (100, 2i)\n%!error <K must be an integer .= 0> nchoosek (100, [2 3])\n%!error <K must be an integer .= 0> nchoosek (100, -45)\n%!error <K must be an integer .= 0> nchoosek (100, 45.5)\n%!error <N must be a non-negative integer .= K> nchoosek (100i, 2)\n%!error <N must be a non-negative integer .= K> nchoosek (100, 145)\n%!error <N must be a non-negative integer .= K> nchoosek (-100, 45)\n%!error <N must be a non-negative integer .= K> nchoosek (100.5, 45)\n%!error <incompatible input types> nchoosek (uint8 (15), uint16 (5))\n%!warning <possible loss of precision> nchoosek (100, 45);\n%!warning <result .* saturated> nchoosek (uint64 (80), uint64 (40));\n%!warning <result .* saturated> nchoosek (uint32 (80), uint32 (40));\n%!warning <result .* saturated> nchoosek (uint16 (80), uint16 (40));\n%!warning <result .* saturated> nchoosek ( uint8 (80),  uint8 (40));\n%!warning <result .* saturated> nchoosek ( int64 (80),  int64 (40));\n%!warning <result .* saturated> nchoosek ( int32 (80),  int32 (40));\n%!warning <result .* saturated> nchoosek ( int16 (80),  int16 (40));\n%!warning <result .* saturated> nchoosek (  int8 (80),   int8 (40));\n"
  },
  {
    "path": "scripts/specfun/nthroot.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n##\n## Original version by Paul Kienzle distributed as free software in the\n## public domain.\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} nthroot (@var{x}, @var{n})\n##\n## Compute the real (non-complex) @var{n}-th root of @var{x}.\n##\n## @var{x} must have all real entries and @var{n} must be a scalar.\n## If @var{n} is an even integer and @var{x} has negative entries then\n## @code{nthroot} aborts and issues an error.\n##\n## Example:\n##\n## @example\n## @group\n## nthroot (-1, 3)\n## @xresult{} -1\n## (-1) ^ (1 / 3)\n## @xresult{} 0.50000 - 0.86603i\n## @end group\n## @end example\n## @seealso{realsqrt, sqrt, cbrt}\n## @end deftypefn\n\nfunction y = nthroot (x, n)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (iscomplex (x))\n    error (\"nthroot: X must not contain complex values\");\n  endif\n\n  if (! isreal (n) || ! isscalar (n) || n == 0)\n    error (\"nthroot: N must be a real nonzero scalar\");\n  endif\n\n  if (n == 3)\n    y = cbrt (x);\n  elseif (n == -3)\n    y = 1 ./ cbrt (x);\n  elseif (n < 0)\n    y = 1 ./ nthroot (x, -n);\n  else\n    ## Compute using power.\n    integer_n = n == fix (n);\n    if (integer_n && mod (n, 2) == 1)\n      y = abs (x) .^ (1/n) .* sign (x);\n    elseif (any (x(:) < 0))\n      error (\"nthroot: N must be an odd integer if X contains negative values\");\n    else\n      y = x .^ (1/n);\n    endif\n\n    if (integer_n && n > 0 && isfinite (n))\n      if (isscalar (y) && y == 0)\n        ## Don't apply correction which leads to division by zero (bug #43492)\n      else\n        ## FIXME: What is this correction for?\n        y = ((n-1)*y + x ./ (y.^(n-1))) / n;\n        y = merge (isfinite (y), y, x);\n      endif\n    endif\n  endif\n\nendfunction\n\n\n%!assert (nthroot (-32, 5), -2)\n%!assert (nthroot (81, 4), 3)\n%!assert (nthroot (Inf, 4), Inf)\n%!assert (nthroot (-Inf, 7), -Inf)\n%!assert (nthroot (-Inf, -7), 0)\n\n## This should not generate a division by zero warning\n%!test <*43492>\n%! warnmsg = lastwarn ();\n%! assert (nthroot (0, 2), 0);\n%! assert (lastwarn (), warnmsg);\n\n## Test input validation\n%!error <Invalid call> nthroot ()\n%!error <Invalid call> nthroot (1)\n%!error <X must not contain complex values> nthroot (1+j, 2)\n%!error <N must be a real nonzero scalar> nthroot (1, i)\n%!error <N must be a real nonzero scalar> nthroot (1, [1 2])\n%!error <N must be a real nonzero scalar> nthroot (1, 0)\n%!error <N must be an odd integer> nthroot (-1, 2)\n"
  },
  {
    "path": "scripts/specfun/primes.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{p} =} primes (@var{n})\n## Return all primes up to @var{n}.\n##\n## The output data class (double, single, uint32, etc.@:) is the same as the\n## input class of @var{n}.  The algorithm used is the Sieve of Eratosthenes.\n##\n## Note: For a specific number @var{n} of primes, call\n## @code{list_primes (@var{n})}.  Alternatively, call\n## @code{primes (@var{n}*log (@var{k}*@var{n}))(1:@var{n})} where @var{k} is\n## about 5 or 6.  This works because the distance from one prime to the next is\n## proportional to the logarithm of the prime, on average.  On integrating,\n## there are about @var{n} primes less than @code{@var{n} * log (5*@var{n})}.\n##\n## @seealso{list_primes, isprime}\n## @end deftypefn\n\nfunction p = primes (n)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (n) && isreal (n)))\n    error (\"primes: N must be a real scalar\");\n  endif\n  if (ischar (n))\n    n = double (n);\n  endif\n  if (! isfinite (n) && n != -Inf)\n    error (\"primes: N must be finite (not +Inf or NaN)\");\n  endif\n\n  cls = class (n);     # if n is not double, store its class\n  n = double (n);      # and use only double for internal use.\n  ## This conversion is needed for both calculation speed (twice as fast as\n  ## integer) and also for the accuracy of the sieve calculation when given\n  ## integer input, to avoid unwanted rounding in the sieve lengths.\n\n  if (n > flintmax ())\n    warning (\"primes: input exceeds flintmax.  Results may be inaccurate.\");\n  endif\n\n  if (n < 353)\n    ## Lookup table of first 70 primes\n    a = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, ...\n         53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, ...\n         109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, ...\n         173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, ...\n         233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, ...\n         293, 307, 311, 313, 317, 331, 337, 347, 349];\n    p = a(a <= n);\n  elseif (n < 100e3)\n    ## Classical Sieve algorithm\n    ## Fast, but memory scales as n/2.\n    len = floor ((n-1)/2);        # length of the sieve\n    sieve = true (1, len);        # assume every odd number is prime\n    for i = 1:(sqrt (n)-1)/2      # check up to sqrt (n)\n      if (sieve(i))               # if i is prime, eliminate multiples of i\n        sieve(3*i+1:2*i+1:len) = false; # do it\n      endif\n    endfor\n    p = [2, 1+2*find(sieve)];     # primes remaining after sieve\n  else\n    ## Sieve algorithm optimized for large n\n    ## Memory scales as n/3 or 1/6th less than classical Sieve\n    lenm = floor ((n+1)/6);       # length of the 6n-1 sieve\n    lenp = floor ((n-1)/6);       # length of the 6n+1 sieve\n    sievem = true (1, lenm);      # assume every number of form 6n-1 is prime\n    sievep = true (1, lenp);      # assume every number of form 6n+1 is prime\n\n    for i = 1:(sqrt (n)+1)/6      # check up to sqrt (n)\n      if (sievem(i))              # if i is prime, eliminate multiples of i\n        sievem(7*i-1:6*i-1:lenm) = false;\n        sievep(5*i-1:6*i-1:lenp) = false;\n      endif                       # if i is prime, eliminate multiples of i\n      if (sievep(i))\n        sievep(7*i+1:6*i+1:lenp) = false;\n        sievem(5*i+1:6*i+1:lenm) = false;\n      endif\n    endfor\n    p = sort ([2, 3, 6*find(sievem)-1, 6*find(sievep)+1]);\n  endif\n\n  ## cast back to the type of the input\n  p = cast (p, cls);\n\nendfunction\n\n\n%!assert (size (primes (350)), [1, 70])\n%!assert (primes (357)(end), 353)\n%!assert (primes (uint64 (358))(end), uint64 (353))\n%!assert (primes (int32 (1e6))(end), int32 (999983))\n%!assert (class (primes (single (10))), \"single\")\n%!assert (class (primes (uint8 (10))), \"uint8\")\n%!assert (primes (-Inf), zeros (1,0))\n\n%!error <Invalid call> primes ()\n%!error <N must be a real scalar> primes (ones (2,2))\n%!error <N must be a real scalar> primes (5i)\n%!error <N must be finite> primes (Inf)\n%!error <N must be finite> primes (NaN)\n"
  },
  {
    "path": "scripts/specfun/reallog.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} reallog (@var{x})\n## Return the real-valued natural logarithm of each element of @var{x}.\n##\n## If any element results in a complex return value @code{reallog} aborts and\n## issues an error.\n## @seealso{log, realpow, realsqrt}\n## @end deftypefn\n\nfunction y = reallog (x)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (iscomplex (x) || any (x(:) < 0))\n    error (\"reallog: produced complex result\");\n  else\n    y = log (x);\n  endif\n\nendfunction\n\n\n%!assert (reallog (1:5), log (1:5))\n%!test\n%! x = rand (10, 10);\n%! assert (reallog (x), log (x));\n\n%!error <Invalid call> reallog ()\n%!error <produced complex result> reallog (2i)\n%!error <produced complex result> reallog (-1)\n"
  },
  {
    "path": "scripts/specfun/realpow.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{z} =} realpow (@var{x}, @var{y})\n## Compute the real-valued, element-by-element power operator.\n##\n## This is equivalent to @w{@code{@var{x} .^ @var{y}}}, except that\n## @code{realpow} reports an error if any return value is complex.\n## @seealso{power, reallog, realsqrt}\n## @end deftypefn\n\nfunction z = realpow (x, y)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  z = x .^ y;\n  if (iscomplex (z))\n    error (\"realpow: produced complex result\");\n  endif\n\nendfunction\n\n\n%!assert (realpow (1:10, 0.5:0.5:5), power (1:10, 0.5:0.5:5))\n%!assert (realpow (1:10, 0.5:0.5:5), [1:10] .^ [0.5:0.5:5])\n%!test\n%! x = rand (10, 10);\n%! y = randn (10, 10);\n%! assert (x.^y, realpow (x,y));\n%!assert <47775> (realpow (1i,2), -1)\n\n%!error <Invalid call> realpow ()\n%!error <Invalid call> realpow (1)\n%!error <produced complex result> realpow (-1, 1/2)\n"
  },
  {
    "path": "scripts/specfun/realsqrt.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} realsqrt (@var{x})\n## Return the real-valued square root of each element of @var{x}.\n##\n## If any element results in a complex return value @code{realsqrt} aborts and\n## issues an error.\n## @seealso{sqrt, realpow, reallog}\n## @end deftypefn\n\nfunction y = realsqrt (x)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (iscomplex (x) || any (x(:) < 0))\n    error (\"realsqrt: produced complex result\");\n  else\n    y = sqrt (x);\n  endif\n\nendfunction\n\n\n%!assert (realsqrt (1:5), sqrt (1:5))\n%!test\n%! x = rand (10, 10);\n%! assert (realsqrt (x), sqrt (x));\n\n%!error <Invalid call> realsqrt ()\n%!error <produced complex result> realsqrt (-1)\n"
  },
  {
    "path": "scripts/specfun/sinint.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{y} =} sinint (@var{x})\n## Compute the sine integral function:\n## @tex\n## $$\n## {\\rm Si} (x) = \\int_0^x {\\sin (t) \\over t} dt\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##            x\n##           /\n## Si (x) =  | sin (t) / t dt\n##           /\n##          0\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## Reference:\n## @nospell{M. Abramowitz and I.A. Stegun},\n## @cite{Handbook of Mathematical Functions}, 1964.\n##\n## @seealso{cosint, expint, sin}\n## @end deftypefn\n\nfunction y = sinint (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x))\n    error (\"sinint: X must be numeric\");\n  endif\n\n  ## Convert to floating point if necessary\n  if (isinteger (x))\n    x = double (x);\n  endif\n\n  ## Convert to column vector\n  orig_sz = size (x);\n  x = x(:);\n  if (iscomplex (x))\n    ## Work around reshape which narrows to real (bug #52953)\n    x = complex (real (x)(:), imag (x)(:));\n  else\n    x = x(:);\n  endif\n\n  ## Initialize the result\n  y = zeros (size (x), class (x));\n  tol = eps (class (x));\n\n  todo = true (size (x));\n\n  ## Special values\n  y(x == 0) = x(x == 0);    # correctly signed zero\n  y(x == Inf) = pi / 2;\n  y(x == - Inf) = - pi / 2;\n\n  todo = ((todo) & (x != 0) & (x != Inf) & (x != - Inf));\n\n  ## For values large in modulus we use the relation with expint\n\n  flag_large = abs (x) > 2;\n  xx = x(flag_large & todo);\n  ii_neg = (real (xx) < 0);\n  xx(ii_neg) *= -1;\n  ii_conj = (real (xx) == 0) & (imag (xx) < 0);\n  xx(ii_conj) = conj (xx(ii_conj));\n  yy = -0.5i * (expint (1i * xx) - expint (-1i * xx)) + pi / 2;\n  yy(ii_neg) *= -1;\n  yy(ii_conj) = conj (yy(ii_conj));\n  y(todo & flag_large) = yy;\n\n  ## For values small in modulus we use the series expansion\n\n  todo = (todo) & (! flag_large);\n  xx = x(todo);\n  ssum = xx;  # First term of the series expansion\n  yy = ssum;\n  flag_sum = true (nnz (todo), 1);\n  it = 0;\n  maxit = 300;\n  while (any (flag_sum) && (it < maxit))\n    ssum .*= - xx .^ 2 * (2 * it + 1) / ((2 * it + 3) ^ 2 * (2 * it + 2));\n    yy(flag_sum) += ssum (flag_sum);\n    flag_sum = (abs (ssum) >= tol);\n    it++;\n  endwhile\n\n  y(todo) = yy;\n\n  y = reshape (y, orig_sz);\n\nendfunction\n\n\n%!assert (sinint (1.1), 1.02868521867373, -5e-15)\n\n%!test\n%! x = [2, 3, pi; exp(1), 5, 6];\n%! A = sinint (x);\n%! B = [1.60541297680269, 1.84865252799947, 1.85193705198247e+00; ...\n%!      1.82104026914757, 1.54993124494467, 1.42468755128051e+00];\n%! assert (A, B, -5e-15);\n\n## Test exceptional values\n%!assert (sinint (0), 0)\n%!assert (signbit (sinint (-0)))\n%!assert (sinint (Inf), pi/2)\n%!assert (sinint (-Inf), -pi/2)\n%!assert (isnan (sinint (NaN)))\n\n## Check single data type is preserved\n%!assert (class (sinint (single (1))), \"single\")\n\n## Tests against Maple\n%!assert (sinint (1)  ,  0.9460830703671830149414, -2*eps)\n%!assert (sinint (-1) , -0.9460830703671830149414, -2*eps)\n%!assert (sinint (pi) ,  1.851937051982466170361, -3*eps)\n%!assert (sinint (-pi), -1.851937051982466170361, -3*eps)\n%!assert (sinint (300),  1.5708810882137495193, -2*eps)\n%!assert (sinint (1e4),  1.5708915453859619157, -2*eps)\n%!assert (sinint (20i),  1.2807826332028294459e7*1i, -2*eps)\n\n%!test\n%! x = (0:4)';\n%! y_ex = [0\n%!         0.946083070367183015\n%!         1.60541297680269485\n%!         1.84865252799946826\n%!         1.75820313894905306];\n%! assert (sinint (x), y_ex, -4*eps);\n\n%!test\n%! x = -(0:4)';\n%! y_ex = - [0\n%!           0.946083070367183015\n%!           1.60541297680269485\n%!           1.84865252799946826\n%!           1.75820313894905306];\n%! assert (sinint (x), y_ex, -4*eps);\n\n%!test\n%! x = 1i * (0:4).';\n%! y_ex = [0\n%!         1.05725087537572851*I\n%!         2.50156743335497564*I\n%!         4.97344047585980680*I\n%!         9.81732691123303446*I];\n%! assert (sinint (x), y_ex, -4*eps);\n\n%!test\n%! x = - 1i * (0:4).';\n%! y_ex = - [0\n%!           1.05725087537572851*I\n%!           2.50156743335497564*I\n%!           4.97344047585980680*I\n%!           9.81732691123303446*I];\n%! assert (sinint (x), y_ex, -4*eps);\n\n%!test\n%! % maple:\n%! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I];\n%! % > for a in A do evalf(Si(a)) end do;\n%! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i];\n%! A = [ 1.6782404878293681180 + 2.0396845546022061045*1i\n%!      -18.154174221650281533 + 1.6146414539230479060*1i\n%!       1.5622254668890562934\n%!       1246.1144901994233444*1i\n%!      -0.000099999999944461111128 + 0.99999999833338888972e-6*1i\n%!      -1.5386156269726011209 - 0.053969388020443786229*1i ];\n%! B = sinint (x);\n%! assert (A, B, -3*eps);\n%! B = sinint (single (x));\n%! assert (A, B, -3*eps (\"single\"));\n\n## FIXME: Need a test for bug #52953\n%#!test <*52953>\n\n## Test input validation\n%!error <Invalid call> sinint ()\n%!error <X must be numeric> sinint (\"1\")\n"
  },
  {
    "path": "scripts/special-matrix/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/special-matrix/gallery.m",
    "content": "########################################################################\n##\n## Copyright (C) 1989-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} gallery (@var{name})\n## @deftypefnx {} {} gallery (@var{name}, @var{args})\n## Create interesting matrices for testing.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{c} =} gallery (\"cauchy\", @var{x})\n## @deftypefnx {} {@var{c} =} gallery (\"cauchy\", @var{x}, @var{y})\n## Create a Cauchy matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{c} =} gallery (\"chebspec\", @var{n})\n## @deftypefnx {} {@var{c} =} gallery (\"chebspec\", @var{n}, @var{k})\n## Create a Chebyshev spectral differentiation matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{c} =} gallery (\"chebvand\", @var{p})\n## @deftypefnx {} {@var{c} =} gallery (\"chebvand\", @var{m}, @var{p})\n## Create a @nospell{Vandermonde}-like matrix for the Chebyshev polynomials.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"chow\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"chow\", @var{n}, @var{alpha})\n## @deftypefnx {} {@var{a} =} gallery (\"chow\", @var{n}, @var{alpha}, @var{delta})\n## Create a Chow matrix -- a singular Toeplitz lower Hessenberg matrix.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{c} =} gallery (\"circul\", @var{v})\n## Create a circulant matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"clement\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"clement\", @var{n}, @var{k})\n## Create a tridiagonal matrix with zero diagonal entries.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{c} =} gallery (\"compar\", @var{a})\n## @deftypefnx {} {@var{c} =} gallery (\"compar\", @var{a}, @var{k})\n## Create a comparison matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"condex\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"condex\", @var{n}, @var{k})\n## @deftypefnx {} {@var{a} =} gallery (\"condex\", @var{n}, @var{k}, @var{theta})\n## Create a @nospell{\"counterexample\"} matrix to a condition estimator.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"cycol\", [@var{m} @var{n}])\n## @deftypefnx {} {@var{a} =} gallery (\"cycol\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (@dots{}, @var{k})\n## Create a matrix whose columns repeat cyclically.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {[@var{c}, @var{d}, @var{e}] =} gallery (\"dorr\", @var{n})\n## @deftypefnx {} {[@var{c}, @var{d}, @var{e}] =} gallery (\"dorr\", @var{n}, @var{theta})\n## @deftypefnx {} {@var{a} =} gallery (\"dorr\", @dots{})\n## Create a diagonally dominant, ill-conditioned, tridiagonal matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"dramadah\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"dramadah\", @var{n}, @var{k})\n## Create a (0, 1) matrix whose inverse has large integer entries.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"fiedler\", @var{c})\n## Create a symmetric @nospell{Fiedler} matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"forsythe\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"forsythe\", @var{n}, @var{alpha})\n## @deftypefnx {} {@var{a} =} gallery (\"forsythe\", @var{n}, @var{alpha}, @var{lambda})\n## Create a @nospell{Forsythe} matrix (a perturbed Jordan block).\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{f} =} gallery (\"frank\", @var{n})\n## @deftypefnx {} {@var{f} =} gallery (\"frank\", @var{n}, @var{k})\n## Create a Frank matrix (ill-conditioned eigenvalues).\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{c} =} gallery (\"gcdmat\", @var{n})\n## Create a greatest common divisor matrix.\n##\n## @var{c} is an @var{n}-by-@var{n} matrix whose values correspond to the\n## greatest common divisor of its coordinate values, i.e., @var{c}(i,j)\n## correspond @code{gcd (i, j)}.\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"gearmat\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"gearmat\", @var{n}, @var{i})\n## @deftypefnx {} {@var{a} =} gallery (\"gearmat\", @var{n}, @var{i}, @var{j})\n## Create a Gear matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{g} =} gallery (\"grcar\", @var{n})\n## @deftypefnx {} {@var{g} =} gallery (\"grcar\", @var{n}, @var{k})\n## Create a Toeplitz matrix with sensitive eigenvalues.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"hanowa\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"hanowa\", @var{n}, @var{d})\n## Create a matrix whose eigenvalues lie on a vertical line in the complex\n## plane.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{v} =} gallery (\"house\", @var{x})\n## @deftypefnx {} {[@var{v}, @var{beta}] =} gallery (\"house\", @var{x})\n## Create a householder matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"integerdata\", @var{imax}, [@var{M} @var{N} @dots{}], @var{j})\n## @deftypefnx {} {@var{a} =} gallery (\"integerdata\", @var{imax}, @var{M}, @var{N}, @dots{}, @var{j})\n## @deftypefnx {} {@var{a} =} gallery (\"integerdata\", [@var{imin}, @var{imax}], [@var{M} @var{N} @dots{}], @var{j})\n## @deftypefnx {} {@var{a} =} gallery (\"integerdata\", [@var{imin}, @var{imax}], @var{M}, @var{N}, @dots{}, @var{j})\n## @deftypefnx {} {@var{a} =} gallery (\"integerdata\", @dots{}, \"@var{class}\")\n## Create a matrix with random integers in the range [1, @var{imax}].\n## If @var{imin} is given then the integers are in the range\n## [@var{imin}, @var{imax}].\n##\n## The second input is a matrix of dimensions describing the size of the\n## output.  The dimensions can also be input as comma-separated arguments.\n##\n## The input @var{j} is an integer index in the range [0, 2^32-1].  The values\n## of the output matrix are always exactly the same (reproducibility) for a\n## given size input and @var{j} index.\n##\n## The final optional argument determines the class of the resulting matrix.\n## Possible values for @var{class}: @qcode{\"uint8\"}, @qcode{\"uint16\"},\n## @qcode{\"uint32\"}, @qcode{\"int8\"}, @qcode{\"int16\"}, int32\", @qcode{\"single\"},\n## @qcode{\"double\"}.  The default is @qcode{\"double\"}.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"invhess\", @var{x})\n## @deftypefnx {} {@var{a} =} gallery (\"invhess\", @var{x}, @var{y})\n## Create the inverse of an upper Hessenberg matrix.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"invol\", @var{n})\n## Create an involutory matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"ipjfact\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"ipjfact\", @var{n}, @var{k})\n## Create a Hankel matrix with factorial elements.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"jordbloc\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"jordbloc\", @var{n}, @var{lambda})\n## Create a Jordan block.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{u} =} gallery (\"kahan\", @var{n})\n## @deftypefnx {} {@var{u} =} gallery (\"kahan\", @var{n}, @var{theta})\n## @deftypefnx {} {@var{u} =} gallery (\"kahan\", @var{n}, @var{theta}, @var{pert})\n## Create a @nospell{Kahan} matrix (upper trapezoidal).\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"kms\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"kms\", @var{n}, @var{rho})\n## Create a @nospell{Kac-Murdock-Szego} Toeplitz matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{b} =} gallery (\"krylov\", @var{a})\n## @deftypefnx {} {@var{b} =} gallery (\"krylov\", @var{a}, @var{x})\n## @deftypefnx {} {@var{b} =} gallery (\"krylov\", @var{a}, @var{x}, @var{j})\n## Create a Krylov matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"lauchli\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"lauchli\", @var{n}, @var{mu})\n## Create a @nospell{Lauchli} matrix (rectangular).\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"lehmer\", @var{n})\n## Create a @nospell{Lehmer} matrix (symmetric positive definite).\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{t} =} gallery (\"lesp\", @var{n})\n## Create a tridiagonal matrix with real, sensitive eigenvalues.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"lotkin\", @var{n})\n## Create a @nospell{Lotkin} matrix.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"minij\", @var{n})\n## Create a symmetric positive definite matrix MIN(i,j).\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"moler\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"moler\", @var{n}, @var{alpha})\n## Create a @nospell{Moler} matrix (symmetric positive definite).\n##\n## @end deftypefn\n##\n## @deftypefn {} {[@var{a}, @var{t}] =} gallery (\"neumann\", @var{n})\n## Create a singular matrix from the discrete @nospell{Neumann} problem\n## (sparse).\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"normaldata\", [@var{M} @var{N} @dots{}], @var{j})\n## @deftypefnx {} {@var{a} =} gallery (\"normaldata\", @var{M}, @var{N}, @dots{}, @var{j})\n## @deftypefnx {} {@var{a} =} gallery (\"normaldata\", @dots{}, \"@var{class}\")\n## Create a matrix with random samples from the standard normal distribution\n## (mean = 0, std = 1).\n##\n## The first input is a matrix of dimensions describing the size of the output.\n## The dimensions can also be input as comma-separated arguments.\n##\n## The input @var{j} is an integer index in the range [0, 2^32-1].  The values\n## of the output matrix are always exactly the same (reproducibility) for a\n## given size input and @var{j} index.\n##\n## The final optional argument determines the class of the resulting matrix.\n## Possible values for @var{class}: @qcode{\"single\"}, @qcode{\"double\"}.\n## The default is @qcode{\"double\"}.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{q} =} gallery (\"orthog\", @var{n})\n## @deftypefnx {} {@var{q} =} gallery (\"orthog\", @var{n}, @var{k})\n## Create orthogonal and nearly orthogonal matrices.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"parter\", @var{n})\n## Create a @nospell{Parter} matrix (a Toeplitz matrix with singular values\n## near pi).\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{p} =} gallery (\"pei\", @var{n})\n## @deftypefnx {} {@var{p} =} gallery (\"pei\", @var{n}, @var{alpha})\n## Create a Pei matrix.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"poisson\", @var{n})\n## Create a block tridiagonal matrix from Poisson's equation (sparse).\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"prolate\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"prolate\", @var{n}, @var{w})\n## Create a prolate matrix (symmetric, ill-conditioned Toeplitz matrix).\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{h} =} gallery (\"randhess\", @var{x})\n## Create a random, orthogonal upper Hessenberg matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"rando\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"rando\", @var{n}, @var{k})\n## Create a random matrix with elements -1, 0 or 1.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"randsvd\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"randsvd\", @var{n}, @var{kappa})\n## @deftypefnx {} {@var{a} =} gallery (\"randsvd\", @var{n}, @var{kappa}, @var{mode})\n## @deftypefnx {} {@var{a} =} gallery (\"randsvd\", @var{n}, @var{kappa}, @var{mode}, @var{kl})\n## @deftypefnx {} {@var{a} =} gallery (\"randsvd\", @var{n}, @var{kappa}, @var{mode}, @var{kl}, @var{ku})\n## Create a random matrix with pre-assigned singular values.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"redheff\", @var{n})\n## Create a zero and ones matrix of @nospell{Redheffer} associated with the\n## Riemann hypothesis.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"riemann\", @var{n})\n## Create a matrix associated with the Riemann hypothesis.\n##\n## @end deftypefn\n##\n## @deftypefn {} {@var{a} =} gallery (\"ris\", @var{n})\n## Create a symmetric Hankel matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"smoke\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"smoke\", @var{n}, @var{k})\n## Create a complex matrix, with a @nospell{\"smoke ring\"} pseudospectrum.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{t} =} gallery (\"toeppd\", @var{n})\n## @deftypefnx {} {@var{t} =} gallery (\"toeppd\", @var{n}, @var{m})\n## @deftypefnx {} {@var{t} =} gallery (\"toeppd\", @var{n}, @var{m}, @var{w})\n## @deftypefnx {} {@var{t} =} gallery (\"toeppd\", @var{n}, @var{m}, @var{w}, @var{theta})\n## Create a symmetric positive definite Toeplitz matrix.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{p} =} gallery (\"toeppen\", @var{n})\n## @deftypefnx {} {@var{p} =} gallery (\"toeppen\", @var{n}, @var{a})\n## @deftypefnx {} {@var{p} =} gallery (\"toeppen\", @var{n}, @var{a}, @var{b})\n## @deftypefnx {} {@var{p} =} gallery (\"toeppen\", @var{n}, @var{a}, @var{b}, @var{c})\n## @deftypefnx {} {@var{p} =} gallery (\"toeppen\", @var{n}, @var{a}, @var{b}, @var{c}, @var{d})\n## @deftypefnx {} {@var{p} =} gallery (\"toeppen\", @var{n}, @var{a}, @var{b}, @var{c}, @var{d}, @var{e})\n## Create a pentadiagonal Toeplitz matrix (sparse).\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"tridiag\", @var{x}, @var{y}, @var{z})\n## @deftypefnx {} {@var{a} =} gallery (\"tridiag\", @var{n})\n## @deftypefnx {} {@var{a} =} gallery (\"tridiag\", @var{n}, @var{c}, @var{d}, @var{e})\n## Create a tridiagonal matrix (sparse).\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{t} =} gallery (\"triw\", @var{n})\n## @deftypefnx {} {@var{t} =} gallery (\"triw\", @var{n}, @var{alpha})\n## @deftypefnx {} {@var{t} =} gallery (\"triw\", @var{n}, @var{alpha}, @var{k})\n## Create an upper triangular matrix discussed by\n## @nospell{Kahan, Golub, and Wilkinson}.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"uniformdata\", [@var{M} @var{N} @dots{}], @var{j})\n## @deftypefnx {} {@var{a} =} gallery (\"uniformdata\", @var{M}, @var{N}, @dots{}, @var{j})\n## @deftypefnx {} {@var{a} =} gallery (\"uniformdata\", @dots{}, \"@var{class}\")\n## Create a matrix with random samples from the standard uniform distribution\n## (range [0,1]).\n##\n## The first input is a matrix of dimensions describing the size of the output.\n## The dimensions can also be input as comma-separated arguments.\n##\n## The input @var{j} is an integer index in the range [0, 2^32-1].  The values\n## of the output matrix are always exactly the same (reproducibility) for a\n## given size input and @var{j} index.\n##\n## The final optional argument determines the class of the resulting matrix.\n## Possible values for @var{class}: @qcode{\"single\"}, @qcode{\"double\"}.\n## The default is @qcode{\"double\"}.\n##\n## @end deftypefn\n##\n## @deftypefn  {} {@var{a} =} gallery (\"wathen\", @var{nx}, @var{ny})\n## @deftypefnx {} {@var{a} =} gallery (\"wathen\", @var{nx}, @var{ny}, @var{k})\n## Create the @nospell{Wathen} matrix.\n##\n## @end deftypefn\n##\n## @deftypefn {} {[@var{a}, @var{b}] =} gallery (\"wilk\", @var{n})\n## Create various specific matrices devised/discussed by Wilkinson.\n##\n## @end deftypefn\n\n## Code for most of the individual matrices (except binomial, gcdmat,\n## integerdata, leslie, normaldata, randcolu, randcorr, randjorth, sampling,\n## uniformdata) by Nicholas J. Higham <Nicholas.J.Higham@manchester.ac.uk>.\n## Adapted for Octave and into single gallery function by Carnë Draug.\n\nfunction varargout = gallery (name, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! ischar (name))\n    error (\"gallery: NAME must be a string\");\n  endif\n\n  ## NOTE: there isn't a lot of input check in the individual functions\n  ## that actually build the functions.  This is by design. The original\n  ## code by Higham did not perform it and was propagated to Matlab, so\n  ## for compatibility, we also don't make it. For example, arguments\n  ## that behave as switches, and in theory accepting a value of 0 or 1,\n  ## will use a value of 0, for any value other than 1 (only check made\n  ## is if the value is equal to 1). It will often also accept string\n  ## values instead of numeric. Only input check added was where it\n  ## would be causing an error anyway.\n\n  ## we will always want to return at least 1 output\n  n_out = nargout;\n  if (n_out == 0)\n    n_out = 1;\n  endif\n\n  switch (lower (name))\n    case \"binomial\"\n      error (\"gallery: matrix %s not implemented\", name);\n    case \"cauchy\"      , [varargout{1:n_out}] = cauchy      (varargin{:});\n    case \"chebspec\"    , [varargout{1:n_out}] = chebspec    (varargin{:});\n    case \"chebvand\"    , [varargout{1:n_out}] = chebvand    (varargin{:});\n    case \"chow\"        , [varargout{1:n_out}] = chow        (varargin{:});\n    case \"circul\"      , [varargout{1:n_out}] = circul      (varargin{:});\n    case \"clement\"     , [varargout{1:n_out}] = clement     (varargin{:});\n    case \"compar\"      , [varargout{1:n_out}] = compar      (varargin{:});\n    case \"condex\"      , [varargout{1:n_out}] = condex      (varargin{:});\n    case \"cycol\"       , [varargout{1:n_out}] = cycol       (varargin{:});\n    case \"dorr\"        , [varargout{1:n_out}] = dorr        (varargin{:});\n    case \"dramadah\"    , [varargout{1:n_out}] = dramadah    (varargin{:});\n    case \"fiedler\"     , [varargout{1:n_out}] = fiedler     (varargin{:});\n    case \"forsythe\"    , [varargout{1:n_out}] = forsythe    (varargin{:});\n    case \"frank\"       , [varargout{1:n_out}] = frank       (varargin{:});\n    case \"gearmat\"     , [varargout{1:n_out}] = gearmat     (varargin{:});\n    case \"gcdmat\"      , [varargout{1:n_out}] = gcdmat      (varargin{:});\n    case \"grcar\"       , [varargout{1:n_out}] = grcar       (varargin{:});\n    case \"hanowa\"      , [varargout{1:n_out}] = hanowa      (varargin{:});\n    case \"house\"       , [varargout{1:n_out}] = house       (varargin{:});\n    case \"integerdata\" , [varargout{1:n_out}] = integerdata (varargin{:});\n    case \"invhess\"     , [varargout{1:n_out}] = invhess     (varargin{:});\n    case \"invol\"       , [varargout{1:n_out}] = invol       (varargin{:});\n    case \"ipjfact\"     , [varargout{1:n_out}] = ipjfact     (varargin{:});\n    case \"jordbloc\"    , [varargout{1:n_out}] = jordbloc    (varargin{:});\n    case \"kahan\"       , [varargout{1:n_out}] = kahan       (varargin{:});\n    case \"kms\"         , [varargout{1:n_out}] = kms         (varargin{:});\n    case \"krylov\"      , [varargout{1:n_out}] = krylov      (varargin{:});\n    case \"lauchli\"     , [varargout{1:n_out}] = lauchli     (varargin{:});\n    case \"lehmer\"      , [varargout{1:n_out}] = lehmer      (varargin{:});\n    case \"leslie\"\n      error (\"gallery: matrix %s not implemented\", name);\n    case \"lesp\"        , [varargout{1:n_out}] = lesp        (varargin{:});\n    case \"lotkin\"      , [varargout{1:n_out}] = lotkin      (varargin{:});\n    case \"minij\"       , [varargout{1:n_out}] = minij       (varargin{:});\n    case \"moler\"       , [varargout{1:n_out}] = moler       (varargin{:});\n    case \"neumann\"     , [varargout{1:n_out}] = neumann     (varargin{:});\n    case \"normaldata\"  , [varargout{1:n_out}] = normaldata  (varargin{:});\n    case \"orthog\"      , [varargout{1:n_out}] = orthog      (varargin{:});\n    case \"parter\"      , [varargout{1:n_out}] = parter      (varargin{:});\n    case \"pei\"         , [varargout{1:n_out}] = pei         (varargin{:});\n    case \"poisson\"     , [varargout{1:n_out}] = poisson     (varargin{:});\n    case \"prolate\"     , [varargout{1:n_out}] = prolate     (varargin{:});\n    case \"randcolu\"\n      error (\"gallery: matrix %s not implemented\", name);\n    case \"randcorr\"\n      error (\"gallery: matrix %s not implemented\", name);\n    case \"randhess\"    , [varargout{1:n_out}] = randhess    (varargin{:});\n    case \"randjorth\"\n      error (\"gallery: matrix %s not implemented\", name);\n    case \"rando\"       , [varargout{1:n_out}] = rando       (varargin{:});\n    case \"randsvd\"     , [varargout{1:n_out}] = randsvd     (varargin{:});\n    case \"redheff\"     , [varargout{1:n_out}] = redheff     (varargin{:});\n    case \"riemann\"     , [varargout{1:n_out}] = riemann     (varargin{:});\n    case \"ris\"         , [varargout{1:n_out}] = ris         (varargin{:});\n    case \"sampling\"\n      error (\"gallery: matrix %s not implemented\", name);\n    case \"smoke\"       , [varargout{1:n_out}] = smoke       (varargin{:});\n    case \"toeppd\"      , [varargout{1:n_out}] = toeppd      (varargin{:});\n    case \"toeppen\"     , [varargout{1:n_out}] = toeppen     (varargin{:});\n    case \"tridiag\"     , [varargout{1:n_out}] = tridiag     (varargin{:});\n    case \"triw\"        , [varargout{1:n_out}] = triw        (varargin{:});\n    case \"uniformdata\" , [varargout{1:n_out}] = uniformdata (varargin{:});\n    case \"wathen\"      , [varargout{1:n_out}] = wathen      (varargin{:});\n    case \"wilk\"        , [varargout{1:n_out}] = wilk        (varargin{:});\n    otherwise\n      error (\"gallery: unknown matrix with NAME %s\", name);\n  endswitch\n\nendfunction\n\nfunction C = cauchy (x, y)\n\n  ## CAUCHY  Cauchy matrix.\n  ##   C = CAUCHY(X, Y), where X, Y are N-vectors, is the N-by-N matrix\n  ##   with C(i,j) = 1/(X(i)+Y(j)).   By default, Y = X.\n  ##   Special case: if X is a scalar CAUCHY(X) is the same as CAUCHY(1:X).\n  ##   Explicit formulas are known for DET(C) (which is nonzero if X and Y\n  ##   both have distinct elements) and the elements of INV(C).\n  ##   C is totally positive if 0 < X(1) < ... < X(N) and\n  ##   0 < Y(1) < ... < Y(N).\n  ##\n  ##   References:\n  ##   N.J. Higham, Accuracy and Stability of Numerical Algorithms,\n  ##     Society for Industrial and Applied Mathematics, Philadelphia, PA,\n  ##     USA, 1996; sec. 26.1.\n  ##   D.E. Knuth, The Art of Computer Programming, Volume 1,\n  ##     Fundamental Algorithms, second edition, Addison-Wesley, Reading,\n  ##     Massachusetts, 1973, p. 36.\n  ##   E.E. Tyrtyshnikov, Cauchy-Toeplitz matrices and some applications,\n  ##     Linear Algebra and Appl., 149 (1991), pp. 1-18.\n  ##     O. Taussky and M. Marcus, Eigenvalues of finite matrices, in\n  ##     Survey of Numerical Analysis, J. Todd, ed., McGraw-Hill, New York,\n  ##     pp. 279-313, 1962. (States the totally positive property on p. 295.)\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 or 2 arguments are required for cauchy matrix\");\n  elseif (! isnumeric (x))\n    error (\"gallery: X must be numeric for cauchy matrix\");\n  elseif (nargin == 2 && ! isnumeric (y))\n    error (\"gallery: Y must be numeric for cauchy matrix\");\n  endif\n\n  n = numel (x);\n  if (isscalar (x) && fix (x) == x)\n    n = x;\n    x = 1:n;\n  elseif (n > 1 && isvector (x))\n    ## do nothing\n  else\n    error (\"gallery: X be an integer or a vector for cauchy matrix\");\n  endif\n\n  if (nargin == 1)\n    y = x;\n  endif\n\n  ## Ensure x and y are column vectors\n  x = x(:);\n  y = y(:);\n  if (numel (x) != numel (y))\n    error (\"gallery: X and Y must be vectors of same length for cauchy matrix\");\n  endif\n\n  C = 1 ./ (x + y.');\n\nendfunction\n\nfunction C = chebspec (n, k = 0)\n\n  ## CHEBSPEC  Chebyshev spectral differentiation matrix.\n  ##   C = CHEBSPEC(N, K) is a Chebyshev spectral differentiation\n  ##   matrix of order N.  K = 0 (the default) or 1.\n  ##   For K = 0 ('no boundary conditions'), C is nilpotent, with\n  ##       C^N = 0 and it has the null vector ONES(N,1).\n  ##       C is similar to a Jordan block of size N with eigenvalue zero.\n  ##   For K = 1, C is nonsingular and well-conditioned, and its eigenvalues\n  ##       have negative real parts.\n  ##   For both K, the computed eigenvector matrix X from EIG is\n  ##       ill-conditioned (MESH(REAL(X)) is interesting).\n  ##\n  ##   References:\n  ##   C. Canuto, M.Y. Hussaini, A. Quarteroni and T.A. Zang, Spectral\n  ##      Methods in Fluid Dynamics, Springer-Verlag, Berlin, 1988; p. 69.\n  ##   L.N. Trefethen and M.R. Trummer, An instability phenomenon in\n  ##      spectral methods, SIAM J. Numer. Anal., 24 (1987), pp. 1008-1023.\n  ##   D. Funaro, Computing the inverse of the Chebyshev collocation\n  ##      derivative, SIAM J. Sci. Stat. Comput., 9 (1988), pp. 1050-1057.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for chebspec matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for chebspec matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a scalar for chebspec matrix\");\n  endif\n\n  ## k = 1 case obtained from k = 0 case with one bigger n.\n  switch (k)\n    case 0, # do nothing\n    case 1, n = n + 1;\n    otherwise\n      error (\"gallery: K should be either 0 or 1 for chebspec matrix\");\n  endswitch\n\n  n -= 1;\n  C = zeros (n+1);\n\n  one    = ones (n+1, 1);\n  x      = cos ((0:n)' * (pi/n));\n  d      = ones (n+1, 1);\n  d(1)   = 2;\n  d(n+1) = 2;\n\n  ## eye(size(C)) on next line avoids div by zero.\n  C = (d * (one./d)') ./ (x*one'-one*x' + eye (size (C)));\n\n  ##  Now fix diagonal and signs.\n  C(1,1) = (2*n^2+1)/6;\n  for i = 2:n+1\n    if (rem (i, 2) == 0)\n      C(:,i) = -C(:,i);\n      C(i,:) = -C(i,:);\n    endif\n    if (i < n+1)\n      C(i,i) = -x(i)/(2*(1-x(i)^2));\n    else\n      C(n+1,n+1) = -C(1,1);\n    endif\n  endfor\n\n  if (k == 1)\n    C = C(2:n+1,2:n+1);\n  endif\n\nendfunction\n\nfunction C = chebvand (m, p)\n\n  ## CHEBVAND Vandermonde-like matrix for the Chebyshev polynomials.\n  ##   C = CHEBVAND(P), where P is a vector, produces the (primal)\n  ##   Chebyshev Vandermonde matrix based on the points P,\n  ##   i.e., C(i,j) = T_{i-1}(P(j)), where T_{i-1} is the Chebyshev\n  ##   polynomial of degree i-1.\n  ##   CHEBVAND(M,P) is a rectangular version of CHEBVAND(P) with M rows.\n  ##   Special case: If P is a scalar then P equally spaced points on\n  ##                 [0,1] are used.\n  ##\n  ##   Reference:\n  ##   N.J. Higham, Stability analysis of algorithms for solving confluent\n  ##     Vandermonde-like systems, SIAM J. Matrix Anal. Appl., 11 (1990),\n  ##     pp. 23-41.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 or 2 arguments are required for chebvand matrix\");\n  endif\n\n  ## because the order of the arguments changes if nargin is 1 or 2 ...\n\n  if (nargin == 1)\n    p = m;\n  endif\n\n  n = numel (p);\n  if (! isnumeric (p))\n    error (\"gallery: P must be numeric for chebvand matrix\");\n  elseif (isscalar (p) && fix (p) == p)\n    n = p;\n    p = linspace (0, 1, n);\n  elseif (n > 1 && isvector (p))\n    ## do nothing\n  endif\n  p = p(:).'; # Ensure p is a row vector.\n\n  if (nargin == 1)\n    m = n;\n  elseif (! isnumeric (m) || ! isscalar (m))\n    error (\"gallery: M must be a scalar for chebvand matrix\");\n  endif\n\n  C = ones (m, n);\n  if (m != 1)\n    C(2,:) = p;\n    ##      Use Chebyshev polynomial recurrence.\n    for i = 3:m\n      C(i,:) = 2.*p.*C(i-1,:) - C(i-2,:);\n    endfor\n  endif\n\nendfunction\n\nfunction A = chow (n, alpha = 1, delta = 0)\n\n  ## CHOW    Chow matrix - a singular Toeplitz lower Hessenberg matrix.\n  ##   A = CHOW(N, ALPHA, DELTA) is a Toeplitz lower Hessenberg matrix\n  ##   A = H(ALPHA) + DELTA*EYE, where H(i,j) = ALPHA^(i-j+1).\n  ##   H(ALPHA) has p = FLOOR(N/2) zero eigenvalues, the rest being\n  ##   4*ALPHA*COS( k*PI/(N+2) )^2, k=1:N-p.\n  ##   Defaults: ALPHA = 1, DELTA = 0.\n  ##\n  ##   References:\n  ##   T.S. Chow, A class of Hessenberg matrices with known\n  ##      eigenvalues and inverses, SIAM Review, 11 (1969), pp. 391-395.\n  ##   G. Fairweather, On the eigenvalues and eigenvectors of a class of\n  ##      Hessenberg matrices, SIAM Review, 13 (1971), pp. 220-221.\n\n  if (nargin < 1 || nargin > 3)\n    error (\"gallery: 1 to 3 arguments are required for chow matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for chow matrix\");\n  elseif (! isnumeric (alpha) || ! isscalar (alpha))\n    error (\"gallery: ALPHA must be a scalar for chow matrix\");\n  elseif (! isnumeric (delta) || ! isscalar (delta))\n    error (\"gallery: DELTA must be a scalar for chow matrix\");\n  endif\n\n  A = toeplitz (alpha.^(1:n), [alpha 1 zeros(1, n-2)]) + delta * eye (n);\n\nendfunction\n\nfunction C = circul (v)\n\n  ## CIRCUL  Circulant matrix.\n  ##   C = CIRCUL(V) is the circulant matrix whose first row is V.\n  ##   (A circulant matrix has the property that each row is obtained\n  ##   from the previous one by cyclically permuting the entries one step\n  ##   forward; it is a special Toeplitz matrix in which the diagonals\n  ##   'wrap round'.)\n  ##   Special case: if V is a scalar then C = CIRCUL(1:V).\n  ##   The eigensystem of C (N-by-N) is known explicitly.   If t is an Nth\n  ##   root of unity, then the inner product of V with W = [1 t t^2 ... t^N]\n  ##   is an eigenvalue of C, and W(N:-1:1) is an eigenvector of C.\n  ##\n  ##   Reference:\n  ##   P.J. Davis, Circulant Matrices, John Wiley, 1977.\n\n  if (nargin != 1)\n    error (\"gallery: 1 argument is required for circul matrix\");\n  elseif (! isnumeric (v))\n    error (\"gallery: V must be numeric for circul matrix\");\n  endif\n\n  n = numel (v);\n  if (isscalar (v) && fix (v) == v)\n    n = v;\n    v = 1:n;\n  elseif (n > 1 && isvector (v))\n    ## do nothing\n  else\n    error (\"gallery: X must be a scalar or a vector for circul matrix\");\n  endif\n\n  v = v(:).';   # Make sure v is a row vector\n  C = toeplitz ([v(1) v(n:-1:2)], v);\n\nendfunction\n\nfunction A = clement (n, k = 0)\n\n  ## CLEMENT   Clement matrix - tridiagonal with zero diagonal entries.\n  ##   CLEMENT(N, K) is a tridiagonal matrix with zero diagonal entries\n  ##   and known eigenvalues.  It is singular if N is odd.  About 64\n  ##   percent of the entries of the inverse are zero.  The eigenvalues\n  ##   are plus and minus the numbers N-1, N-3, N-5, ..., (1 or 0).\n  ##   For K = 0 (the default) the matrix is unsymmetric, while for\n  ##   K = 1 it is symmetric.\n  ##   CLEMENT(N, 1) is diagonally similar to CLEMENT(N).\n  ##\n  ##   Similar properties hold for TRIDIAG(X,Y,Z) where Y = ZEROS(N,1).\n  ##   The eigenvalues still come in plus/minus pairs but they are not\n  ##   known explicitly.\n  ##\n  ##   References:\n  ##   P.A. Clement, A class of triple-diagonal matrices for test\n  ##      purposes, SIAM Review, 1 (1959), pp. 50-52.\n  ##   A. Edelman and E. Kostlan, The road from Kac's matrix to Kac's\n  ##      random polynomials. In John~G. Lewis, editor, Proceedings of\n  ##      the Fifth SIAM Conference on Applied Linear Algebra Society\n  ##      for Industrial and Applied Mathematics, Philadelphia, 1994,\n  ##      pp. 503-507.\n  ##   O. Taussky and J. Todd, Another look at a matrix of Mark Kac,\n  ##      Linear Algebra and Appl., 150 (1991), pp. 341-360.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 or 2 arguments are required for clement matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for clement matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a numeric scalar for clement matrix\");\n  endif\n\n  n -= 1;\n  x = n:-1:1;\n  z = 1:n;\n\n  if (k == 0)\n    A = diag (x, -1) + diag (z, 1);\n  elseif (k == 1)\n    y = sqrt (x.*z);\n    A = diag (y, -1) + diag (y, 1);\n  else\n    error (\"gallery: K must have a value of 0 or 1 for clement matrix\");\n  endif\n\nendfunction\n\nfunction C = compar (A, k = 0)\n\n  ## COMP    Comparison matrices.\n  ##   COMP(A) is DIAG(B) - TRIL(B,-1) - TRIU(B,1), where B = ABS(A).\n  ##   COMP(A, 1) is A with each diagonal element replaced by its\n  ##   absolute value, and each off-diagonal element replaced by minus\n  ##   the absolute value of the largest element in absolute value in\n  ##   its row.  However, if A is triangular COMP(A, 1) is too.\n  ##   COMP(A, 0) is the same as COMP(A).\n  ##   COMP(A) is often denoted by M(A) in the literature.\n  ##\n  ##   Reference (e.g.):\n  ##   N.J. Higham, A survey of condition number estimation for\n  ##   triangular matrices, SIAM Review, 29 (1987), pp. 575-596.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 or 2 arguments are required for compar matrix\");\n  elseif (! isnumeric (A) || ndims (A) != 2)\n    error (\"gallery: A must be a 2-D matrix for compar matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a numeric scalar for compar matrix\");\n  endif\n\n  [m, n] = size (A);\n  p = min (m, n);\n\n  if (k == 0)\n    ## This code uses less temporary storage than\n    ## the 'high level' definition above.\n    C = -abs (A);\n    for j = 1:p\n      C(j,j) = abs (A(j,j));\n    endfor\n\n  elseif (k == 1)\n    C = A';\n    for j = 1:p\n      C(k,k) = 0;\n    endfor\n    mx = max (abs (C));\n    C  = -mx'*ones (1, n);\n    for j = 1:p\n      C(j,j) = abs (A(j,j));\n    endfor\n    if (all (A == tril (A))), C = tril (C); endif\n    if (all (A == triu (A))), C = triu (C); endif\n\n  else\n    error (\"gallery: K must have a value of 0 or 1 for compar matrix\");\n  endif\n\nendfunction\n\nfunction A = condex (n, k = 4, theta = 100)\n\n  ## CONDEX   'Counterexamples' to matrix condition number estimators.\n  ##   CONDEX(N, K, THETA) is a 'counterexample' matrix to a condition\n  ##   estimator.  It has order N and scalar parameter THETA (default 100).\n  ##   If N is not equal to the 'natural' size of the matrix then\n  ##   the matrix is padded out with an identity matrix to order N.\n  ##   The matrix, its natural size, and the estimator to which it applies\n  ##   are specified by K (default K = 4) as follows:\n  ##       K = 1:   4-by-4,     LINPACK (RCOND)\n  ##       K = 2:   3-by-3,     LINPACK (RCOND)\n  ##       K = 3:   arbitrary,  LINPACK (RCOND) (independent of THETA)\n  ##       K = 4:   N >= 4,     SONEST (Higham 1988)\n  ##   (Note that in practice the K = 4 matrix is not usually a\n  ##    counterexample because of the rounding errors in forming it.)\n  ##\n  ##   References:\n  ##   A.K. Cline and R.K. Rew, A set of counter-examples to three\n  ##      condition number estimators, SIAM J. Sci. Stat. Comput.,\n  ##      4 (1983), pp. 602-611.\n  ##   N.J. Higham, FORTRAN codes for estimating the one-norm of a real or\n  ##      complex matrix, with applications to condition estimation\n  ##      (Algorithm 674), ACM Trans. Math. Soft., 14 (1988), pp. 381-396.\n\n  if (nargin < 1 || nargin > 3)\n    error (\"gallery: 1 to 3 arguments are required for condex matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for condex matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a numeric scalar for condex matrix\");\n  elseif (! isnumeric (theta) || ! isscalar (theta))\n    error (\"gallery: THETA must be a numeric scalar for condex matrix\");\n  endif\n\n  if (k == 1)       # Cline and Rew (1983), Example B.\n    A = [1  -1  -2*theta     0\n         0   1     theta  -theta\n         0   1   1+theta  -(theta+1)\n         0   0   0         theta];\n\n  elseif (k == 2)   # Cline and Rew (1983), Example C.\n    A = [1   1-2/theta^2  -2\n         0   1/theta      -1/theta\n         0   0             1];\n\n  elseif (k == 3)   # Cline and Rew (1983), Example D.\n    A = gallery (\"triw\", n, -1)';\n    A(n,n) = -1;\n\n  elseif (k == 4)   # Higham (1988), p. 390.\n    x = ones (n, 3);            #  First col is e\n    x(2:n,2) = zeros (n-1, 1);  #  Second col is e(1)\n\n    ## Third col is special vector b in SONEST\n    x(:, 3) = (-1).^[0:n-1]' .* ( 1 + [0:n-1]'/(n-1) );\n\n    Q = orth (x);  #  Q*Q' is now the orthogonal projector onto span(e(1),e,b)).\n    P = eye (n) - Q*Q';\n    A = eye (n) + theta*P;\n\n  else\n    error (\"gallery: unknown estimator K '%d' for condex matrix\", k);\n  endif\n\n  ## Pad out with identity as necessary.\n  m = columns (A);\n  if (m < n)\n    for i = n:-1:m+1\n      A(i,i) = 1;\n    endfor\n  endif\n\nendfunction\n\nfunction A = cycol (n, k = max (round (n(end)/4), 1))\n\n  ## CYCOL   Matrix whose columns repeat cyclically.\n  ##   A = CYCOL([M N], K) is an M-by-N matrix of the form A = B(1:M,1:N)\n  ##   where B = [C C C...] and C = RANDN(M, K).  Thus A's columns repeat\n  ##   cyclically, and A has rank at most K.   K need not divide N.\n  ##   K defaults to ROUND(N/4).\n  ##   CYCOL(N, K), where N is a scalar, is the same as CYCOL([N N], K).\n  ##\n  ##   This type of matrix can lead to underflow problems for Gaussian\n  ##   elimination: see NA Digest Volume 89, Issue 3 (January 22, 1989).\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 or 2 arguments are required for cycol matrix\");\n  elseif (! isnumeric (n) || all (numel (n) != [1 2]) || fix (n) != n)\n    error (\"gallery: N must be a 1 or 2 element integer for cycol matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a scalar for cycol matrix\");\n  endif\n\n  ## Parameter n specifies dimension: m-by-n\n  m = n(1);\n  n = n(end);\n\n  A = randn (m, k);\n  for i = 2:ceil (n/k)\n    A = [A A(:,1:k)];\n  endfor\n  A = A(:,1:n);\n\nendfunction\n\nfunction [c, d, e] = dorr (n, theta = 0.01)\n\n  ## DORR  Dorr matrix - diagonally dominant, ill conditioned, tridiagonal.\n  ##   [C, D, E] = DORR(N, THETA) returns the vectors defining a row diagonally\n  ##   dominant, tridiagonal M-matrix that is ill conditioned for small\n  ##   values of the parameter THETA >= 0.\n  ##   If only one output parameter is supplied then\n  ##   C = FULL(TRIDIAG(C,D,E)), i.e., the matrix iself is returned.\n  ##   The columns of INV(C) vary greatly in norm.  THETA defaults to 0.01.\n  ##   The amount of diagonal dominance is given by (ignoring rounding errors):\n  ##         COMP(C)*ONES(N,1) = THETA*(N+1)^2 * [1 0 0 ... 0 1]'.\n  ##\n  ##   Reference:\n  ##   F.W. Dorr, An example of ill-conditioning in the numerical\n  ##   solution of singular perturbation problems, Math. Comp., 25 (1971),\n  ##   pp. 271-283.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 or 2 arguments are required for dorr matrix\");\n  elseif (! isscalar (n) || ! isnumeric (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for dorr matrix\");\n  elseif (! isscalar (theta) || ! isnumeric (theta))\n    error (\"gallery: THETA must be a numeric scalar for dorr matrix\");\n  endif\n\n  c = zeros (n, 1);\n  e = c;\n  d = c;\n  ##  All length n for convenience.  Make c, e of length n-1 later.\n\n  h = 1/(n+1);\n  m = floor ((n+1)/2);\n  term = theta/h^2;\n\n  i = (1:m)';\n  c(i) = -term * ones (m, 1);\n  e(i) = c(i) - (0.5-i*h)/h;\n  d(i) = -(c(i) + e(i));\n\n  i = (m+1:n)';\n  e(i) = -term * ones (n-m, 1);\n  c(i) = e(i) + (0.5-i*h)/h;\n  d(i) = -(c(i) + e(i));\n\n  c = c(2:n);\n  e = e(1:n-1);\n\n  if (nargout <= 1)\n    c = tridiag (c, d, e);\n  endif\n\nendfunction\n\nfunction A = dramadah (n, k = 1)\n\n  ## DRAMADAH  A (0,1) matrix whose inverse has large integer entries.\n  ##   An anti-Hadamard matrix A is a matrix with elements 0 or 1 for\n  ##   which MU(A) := NORM(INV(A),'FRO') is maximal.\n  ##   A = DRAMADAH(N, K) is an N-by-N (0,1) matrix for which MU(A) is\n  ##   relatively large, although not necessarily maximal.\n  ##   Available types (the default is K = 1):\n  ##   K = 1: A is Toeplitz, with ABS(DET(A)) = 1, and MU(A) > c(1.75)^N,\n  ##          where c is a constant.\n  ##   K = 2: A is upper triangular and Toeplitz.\n  ##   The inverses of both types have integer entries.\n  ##\n  ##   Another interesting (0,1) matrix:\n  ##   K = 3: A has maximal determinant among (0,1) lower Hessenberg\n  ##   matrices: det(A) = the n'th Fibonacci number.  A is Toeplitz.\n  ##   The eigenvalues have an interesting distribution in the complex\n  ##   plane.\n  ##\n  ##   References:\n  ##   R.L. Graham and N.J.A. Sloane, Anti-Hadamard matrices,\n  ##      Linear Algebra and Appl., 62 (1984), pp. 113-137.\n  ##   L. Ching, The maximum determinant of an nxn lower Hessenberg\n  ##      (0,1) matrix, Linear Algebra and Appl., 183 (1993), pp. 147-153.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for dramadah matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for dramadah matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a numeric scalar for dramadah matrix\");\n  endif\n\n  switch (k)\n    case (1)  # Toeplitz\n      c = ones (n, 1);\n      for i = 2:4:n\n        m = min (1, n-i);\n        c(i:i+m) = zeros (m+1, 1);\n      endfor\n      r = zeros (n, 1);\n      r(1:4) = [1 1 0 1];\n      if (n < 4)\n        r = r(1:n);\n      endif\n      A = toeplitz (c, r);\n\n    case (2)  # Upper triangular and Toeplitz\n      c = zeros (n, 1);\n      c(1) = 1;\n      r = ones (n, 1);\n      for i= 3:2:n\n        r(i) = 0;\n      endfor\n      A = toeplitz (c, r);\n\n    case (3)  # Lower Hessenberg\n      c = ones (n, 1);\n      for i= 2:2:n\n        c(i) = 0;\n      endfor\n      A = toeplitz (c, [1 1 zeros(1,n-2)]);\n\n    otherwise\n      error (\"gallery: unknown K '%d' for dramadah matrix\", k);\n  endswitch\n\nendfunction\n\nfunction A = fiedler (c)\n\n  ## FIEDLER  Fiedler matrix - symmetric.\n  ##   FIEDLER(C), where C is an n-vector, is the n-by-n symmetric\n  ##   matrix with elements ABS(C(i)-C(j)).\n  ##   Special case: if C is a scalar, then A = FIEDLER(1:C)\n  ##               (i.e. A(i,j) = ABS(i-j)).\n  ##   Properties:\n  ##   FIEDLER(N) has a dominant positive eigenvalue and all the other\n  ##              eigenvalues are negative (Szego, 1936).\n  ##   Explicit formulas for INV(A) and DET(A) are given by Todd (1977)\n  ##   and attributed to Fiedler.  These indicate that INV(A) is\n  ##   tridiagonal except for nonzero (1,n) and (n,1) elements.\n  ##   [I think these formulas are valid only if the elements of\n  ##   C are in increasing or decreasing order---NJH.]\n  ##\n  ##   References:\n  ##   G. Szego, Solution to problem 3705, Amer. Math. Monthly,\n  ##      43 (1936), pp. 246-259.\n  ##   J. Todd, Basic Numerical Mathematics, Vol. 2: Numerical Algebra,\n  ##      Birkhauser, Basel, and Academic Press, New York, 1977, p. 159.\n\n  if (nargin != 1)\n    error (\"gallery: 1 argument is required for fiedler matrix\");\n  elseif (! isnumeric (c))\n    error (\"gallery: C must be numeric for fiedler matrix\");\n  endif\n\n  n = numel (c);\n  if (isscalar (c) && fix (c) == c)\n    n = c;\n    c = 1:n;\n  elseif (n > 1 && isvector (c))\n    ## do nothing\n  else\n    error (\"gallery: C must be an integer or a vector for fiedler matrix\");\n  endif\n  c = c(:).';           # Ensure c is a row vector.\n\n  A = abs (c - c.');\n\nendfunction\n\nfunction A = forsythe (n, alpha = sqrt (eps), lambda = 0)\n\n  ## FORSYTHE  Forsythe matrix - a perturbed Jordan block.\n  ##   FORSYTHE(N, ALPHA, LAMBDA) is the N-by-N matrix equal to\n  ##   JORDBLOC(N, LAMBDA) except it has an ALPHA in the (N,1) position.\n  ##   It has the characteristic polynomial\n  ##           DET(A-t*EYE) = (LAMBDA-t)^N - (-1)^N ALPHA.\n  ##   ALPHA defaults to SQRT(EPS) and LAMBDA to 0.\n\n  if (nargin < 1 || nargin > 3)\n    error (\"gallery: 1 to 3 arguments are required for forsythe matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for forsythe matrix\");\n  elseif (! isnumeric (alpha) || ! isscalar (alpha))\n    error (\"gallery: ALPHA must be a numeric scalar for forsythe matrix\");\n  elseif (! isnumeric (lambda) || ! isscalar (lambda))\n    error (\"gallery: LAMBDA must be a numeric scalar for forsythe matrix\");\n  endif\n\n  A = jordbloc (n, lambda);\n  A(n,1) = alpha;\n\nendfunction\n\nfunction F = frank (n, k = 0)\n\n  ## FRANK   Frank matrix---ill conditioned eigenvalues.\n  ##   F = FRANK(N, K) is the Frank matrix of order N.  It is upper\n  ##   Hessenberg with determinant 1.  K = 0 is the default; if K = 1 the\n  ##   elements are reflected about the anti-diagonal (1,N)--(N,1).\n  ##   F has all positive eigenvalues and they occur in reciprocal pairs\n  ##   (so that 1 is an eigenvalue if N is odd).\n  ##   The eigenvalues of F may be obtained in terms of the zeros of the\n  ##   Hermite polynomials.\n  ##   The FLOOR(N/2) smallest eigenvalues of F are ill conditioned,\n  ##   the more so for bigger N.\n  ##\n  ##   DET(FRANK(N)') comes out far from 1 for large N---see Frank (1958)\n  ##   and Wilkinson (1960) for discussions.\n  ##\n  ##   This version incorporates improvements suggested by W. Kahan.\n  ##\n  ##   References:\n  ##   W.L. Frank, Computing eigenvalues of complex matrices by determinant\n  ##      evaluation and by methods of Danilewski and Wielandt, J. Soc.\n  ##      Indust. Appl. Math., 6 (1958), pp. 378-392 (see pp. 385, 388).\n  ##   G.H. Golub and J.H. Wilkinson, Ill-conditioned eigensystems and the\n  ##      computation of the Jordan canonical form, SIAM Review, 18 (1976),\n  ##        pp. 578-619 (Section 13).\n  ##   H. Rutishauser, On test matrices, Programmation en Mathematiques\n  ##      Numeriques, Editions Centre Nat. Recherche Sci., Paris, 165,\n  ##      1966, pp. 349-365.  Section 9.\n  ##   J.H. Wilkinson, Error analysis of floating-point computation,\n  ##      Numer. Math., 2 (1960), pp. 319-340 (Section 8).\n  ##   J.H. Wilkinson, The Algebraic Eigenvalue Problem, Oxford University\n  ##      Press, 1965 (pp. 92-93).\n  ##   The next two references give details of the eigensystem, as does\n  ##   Rutishauser (see above).\n  ##   P.J. Eberlein, A note on the matrices denoted by B_n, SIAM J. Appl.\n  ##      Math., 20 (1971), pp. 87-92.\n  ##   J.M. Varah, A generalization of the Frank matrix, SIAM J. Sci. Stat.\n  ##      Comput., 7 (1986), pp. 835-839.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for frank matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for frank matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a numeric scalar for frank matrix\");\n  endif\n\n  p = n:-1:1;\n  F = triu (p(ones (n, 1), :) - diag (ones (n-1, 1), -1), -1);\n\n  switch (k)\n    case 0, # do nothing\n    case 1, F = F(p,p)';\n    otherwise\n      error (\"gallery: K must have a value of 0 or 1 for frank matrix\");\n  endswitch\n\nendfunction\n\nfunction c = gcdmat (n)\n\n  if (nargin != 1)\n    error (\"gallery: 1 argument is required for gcdmat matrix\");\n  elseif (! isscalar (n) || ! isnumeric (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for gcdmat matrix\");\n  endif\n  c = gcd (repmat ((1:n)', [1 n]), repmat (1:n, [n 1]));\n\nendfunction\n\nfunction A = gearmat (n, i = n, j = -n)\n\n  ## NOTE: this function was named gearm in the original Test Matrix Toolbox\n  ## GEARMAT   Gear matrix.\n  ##   A = GEARMAT(N,I,J) is the N-by-N matrix with ones on the sub- and\n  ##   super-diagonals, SIGN(I) in the (1,ABS(I)) position, SIGN(J)\n  ##   in the (N,N+1-ABS(J)) position, and zeros everywhere else.\n  ##   Defaults: I = N, j = -N.\n  ##   All eigenvalues are of the form 2*COS(a) and the eigenvectors\n  ##   are of the form [SIN(w+a), SIN(w+2a), ..., SIN(w+Na)].\n  ##   The values of a and w are given in the reference below.\n  ##   A can have double and triple eigenvalues and can be defective.\n  ##   GEARMAT(N) is singular.\n  ##\n  ##   (GEAR is a Simulink function, hence GEARMAT for Gear matrix.)\n  ##   Reference:\n  ##   C.W. Gear, A simple set of test matrices for eigenvalue programs,\n  ##   Math. Comp., 23 (1969), pp. 119-125.\n\n  if (nargin < 1 || nargin > 3)\n    error (\"gallery: 1 to 3 arguments are required for gearmat matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for gearmat matrix\");\n  elseif (! isnumeric (i) || ! isscalar (i) || i == 0 || abs (i) > n)\n    error (\"gallery: I must be a nonzero scalar, and abs (I) <= N for gearmat matrix\");\n  elseif (! isnumeric (j) || ! isscalar (j) || i == 0 || abs (j) > n)\n    error (\"gallery: J must be a nonzero scalar, and abs (J) <= N for gearmat matrix\");\n  endif\n\n  A = diag (ones (n-1, 1), -1) + diag (ones (n-1, 1), 1);\n  A(1, abs (i)) = sign (i);\n  A(n, n+1 - abs (j)) = sign (j);\n\nendfunction\n\nfunction G = grcar (n, k = 3)\n\n  ## GRCAR     Grcar matrix - a Toeplitz matrix with sensitive eigenvalues.\n  ##   GRCAR(N, K) is an N-by-N matrix with -1s on the\n  ##   subdiagonal, 1s on the diagonal, and K superdiagonals of 1s.\n  ##   The default is K = 3.  The eigenvalues of this matrix form an\n  ##   interesting pattern in the complex plane (try PS(GRCAR(32))).\n  ##\n  ##   References:\n  ##   J.F. Grcar, Operator coefficient methods for linear equations,\n  ##        Report SAND89-8691, Sandia National Laboratories, Albuquerque,\n  ##        New Mexico, 1989 (Appendix 2).\n  ##   N.M. Nachtigal, L. Reichel and L.N. Trefethen, A hybrid GMRES\n  ##        algorithm for nonsymmetric linear systems, SIAM J. Matrix Anal.\n  ##        Appl., 13 (1992), pp. 796-825.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for grcar matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for grcar matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a numeric scalar for grcar matrix\");\n  endif\n\n  G = tril (triu (ones (n)), k) - diag (ones (n-1, 1), -1);\n\nendfunction\n\nfunction A = hanowa (n, d = -1)\n\n  ## HANOWA  A matrix whose eigenvalues lie on a vertical line in the complex plane.\n  ##   HANOWA(N, d) is the N-by-N block 2x2 matrix (thus N = 2M must be even)\n  ##                 [d*EYE(M)   -DIAG(1:M)\n  ##                  DIAG(1:M)   d*EYE(M)]\n  ##   It has complex eigenvalues lambda(k) = d +/- k*i  (1 <= k <= M).\n  ##   Parameter d defaults to -1.\n  ##\n  ##   Reference:\n  ##   E. Hairer, S.P. Norsett and G. Wanner, Solving Ordinary\n  ##   Differential Equations I: Nonstiff Problems, Springer-Verlag,\n  ##   Berlin, 1987. (pp. 86-87)\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for hanowa matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for hanowa matrix\");\n  elseif (rem (n, 2) != 0)\n    error (\"gallery: N must be even for hanowa matrix\");\n  elseif (! isnumeric (d) || ! isscalar (d))\n    error (\"gallery: D must be a numeric scalar for hanowa matrix\");\n  endif\n\n  m = n/2;\n  A = [ d*eye(m)  -diag(1:m)\n        diag(1:m)  d*eye(m) ];\n\nendfunction\n\nfunction [v, beta] = house (x)\n\n  ## HOUSE   Householder matrix.\n  ##   If [v, beta] = HOUSE(x) then H = EYE - beta*v*v' is a Householder\n  ##   matrix such that Hx = -sign(x(1))*norm(x)*e_1.\n  ##   NB: If x = 0 then v = 0, beta = 1 is returned.\n  ##       x can be real or complex.\n  ##       sign(x) := exp(i*arg(x)) ( = x./abs(x) when x ~= 0).\n  ##\n  ##   Theory: (textbook references Golub & Van Loan 1989, 38-43;\n  ##            Stewart 1973, 231-234, 262; Wilkinson 1965, 48-50).\n  ##   Hx = y: (I - beta*v*v')x = -s*e_1.\n  ##   Must have |s| = norm(x), v = x+s*e_1, and\n  ##   x'y = x'Hx =(x'Hx)' real => arg(s) = arg(x(1)).\n  ##   So take s = sign(x(1))*norm(x) (which avoids cancellation).\n  ##   v'v = (x(1)+s)^2 + x(2)^2 + ... + x(n)^2\n  ##       = 2*norm(x)*(norm(x) + |x(1)|).\n  ##\n  ##   References:\n  ##   G.H. Golub and C.F. Van Loan, Matrix Computations, second edition,\n  ##      Johns Hopkins University Press, Baltimore, Maryland, 1989.\n  ##   G.W. Stewart, Introduction to Matrix Computations, Academic Press,\n  ##      New York, 1973,\n  ##   J.H. Wilkinson, The Algebraic Eigenvalue Problem, Oxford University\n  ##      Press, 1965.\n\n  if (nargin != 1)\n    error (\"gallery: 1 argument is required for house matrix\");\n  elseif (! isnumeric (x) || ! isvector (x))\n    error (\"gallery: X must be a vector for house matrix\");\n  endif\n\n  ## must be a column vector\n  x = x(:);\n\n  s = norm (x) * (sign (x(1)) + (x(1) == 0)); # Modification for sign (0) == 1.\n  v = x;\n  if (s == 0)\n    ## Quit if x is the zero vector.\n    beta = 1;\n  else\n    v(1) = v(1) + s;\n    beta = 1/(s'*v(1));                       # NB the conjugated s.\n    ##  beta = 1/(abs (s) * (abs (s) +abs(x(1)) would guarantee beta real.\n    ##  But beta as above can be non-real (due to rounding) only when x is complex.\n  endif\n\nendfunction\n\nfunction A = integerdata (varargin)\n\n  if (nargin < 3)\n    error (\"gallery: At least 3 arguments required for integerdata matrix\");\n  endif\n\n  if (isnumeric (varargin{end}))\n    jidx = varargin{end};\n    svec = [varargin{:}];\n    varargin(end) = [];\n  elseif (ischar (varargin{end}))\n    if (nargin < 4)\n      error ([\"gallery: CLASS argument requires 4 inputs \" ...\n              \"for integerdata matrix.\"]);\n    endif\n    jidx = varargin{end-1};\n    svec = [varargin{1:end-1}];\n    varargin(end-1) = [];\n  else\n    error ([\"gallery: J must be an integer in the range [0, 2^32-1] \" ...\n            \"for integerdata matrix\"]);\n  endif\n\n  if (! (isnumeric (jidx) && isscalar (jidx)\n         && jidx == fix (jidx)\n         && jidx >= 0 && jidx <= 0xFFFFFFFF))\n    error ([\"gallery: J must be an integer in the range [0, 2^32-1] \" ...\n            \"for integerdata matrix\"]);\n  endif\n\n  ## Save and restore random state.  Initialization done so that reproducible\n  ## data is available from gallery depending on the jidx and size vector.\n  randstate = rand (\"state\");\n  unwind_protect\n    rand (\"state\", svec);\n    A = randi (varargin{:});\n  unwind_protect_cleanup\n    rand (\"state\", randstate);\n  end_unwind_protect\n\nendfunction\n\nfunction A = invhess (x, y)\n\n  ## INVHESS  Inverse of an upper Hessenberg matrix.\n  ##   INVHESS(X, Y), where X is an N-vector and Y an N-1 vector,\n  ##   is the matrix whose lower triangle agrees with that of\n  ##   ONES(N,1)*X' and whose strict upper triangle agrees with\n  ##   that of [1 Y]*ONES(1,N).\n  ##   The matrix is nonsingular if X(1) ~= 0 and X(i+1) ~= Y(i)\n  ##   for all i, and its inverse is an upper Hessenberg matrix.\n  ##   If Y is omitted it defaults to -X(1:N-1).\n  ##   Special case: if X is a scalar INVHESS(X) is the same as\n  ##   INVHESS(1:X).\n  ##\n  ##   References:\n  ##   F.N. Valvi and V.S. Geroyannis, Analytic inverses and\n  ##       determinants for a class of matrices, IMA Journal of Numerical\n  ##       Analysis, 7 (1987), pp. 123-128.\n  ##   W.-L. Cao and W.J. Stewart, A note on inverses of Hessenberg-like\n  ##       matrices, Linear Algebra and Appl., 76 (1986), pp. 233-240.\n  ##   Y. Ikebe, On inverses of Hessenberg matrices, Linear Algebra and\n  ##       Appl., 24 (1979), pp. 93-97.\n  ##   P. Rozsa, On the inverse of band matrices, Integral Equations and\n  ##       Operator Theory, 10 (1987), pp. 82-95.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for invhess matrix\");\n  elseif (! isnumeric (x))\n    error (\"gallery: X must be numeric for invhess matrix\");\n  endif\n\n  if (isscalar (x) && fix (x) == x)\n    n = x;\n    x = 1:n;\n  elseif (! isscalar (x) && isvector (x))\n    n = numel (x);\n  else\n    error (\"gallery: X must be an integer scalar, or a vector for invhess matrix\");\n  endif\n\n  if (nargin < 2)\n    y = -x(1:end-1);\n  elseif (! isvector (y) || numel (y) != numel (x) -1)\n    error (\"gallery: Y must be a vector of length -1 than X for invhess matrix\");\n  endif\n\n  x = x(:);\n  y = y(:);\n\n  ##  FIXME: On next line, z = x'; A = z(ones(n,1),:) would be more efficient.\n  A = ones (n, 1) * x';\n  for j = 2:n\n    A(1:j-1,j) = y(1:j-1);\n  endfor\n\nendfunction\n\nfunction A = invol (n)\n\n  ## INVOL   An involutory matrix.\n  ##   A = INVOL(N) is an N-by-N involutory (A*A = EYE(N)) and\n  ##   ill-conditioned matrix.\n  ##   It is a diagonally scaled version of HILB(N).\n  ##   NB: B = (EYE(N)-A)/2 and B = (EYE(N)+A)/2 are idempotent (B*B = B).\n  ##\n  ##   Reference:\n  ##   A.S. Householder and J.A. Carpenter, The singular values\n  ##   of involutory and of idempotent matrices, Numer. Math. 5 (1963),\n  ##   pp. 234-237.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for invol matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for invol matrix\");\n  endif\n\n  A = hilb (n);\n\n  d = -n;\n  A(:, 1) = d * A(:, 1);\n\n  for i = 1:n-1\n    d = -(n+i)*(n-i)*d/(i*i);\n    A(i+1,:) = d * A(i+1,:);\n  endfor\n\nendfunction\n\nfunction [A, detA] = ipjfact (n, k = 0)\n\n  ## IPJFACT   A Hankel matrix with factorial elements.\n  ##   A = IPJFACT(N, K) is the matrix with\n  ##             A(i,j) = (i+j)!    (K = 0, default)\n  ##             A(i,j) = 1/(i+j)!  (K = 1)\n  ##   Both are Hankel matrices.\n  ##   The determinant and inverse are known explicitly.\n  ##   If a second output argument is present, d = DET(A) is returned:\n  ##   [A, d] = IPJFACT(N, K);\n  ##\n  ##   Suggested by P. R. Graves-Morris.\n  ##\n  ##   Reference:\n  ##   M.J.C. Gover, The explicit inverse of factorial Hankel matrices,\n  ##   Dept. of Mathematics, University of Bradford, 1993.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for ipjfact matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for ipjfact matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a numeric scalar for ipjfact matrix\");\n  endif\n\n  c = cumprod (2:n+1);\n  d = cumprod (n+1:2*n) * c(n-1);\n\n  A = hankel (c, d);\n\n  switch (k)\n    case 0, # do nothing\n    case 1, A = ones (n) ./ A;\n    otherwise\n      error (\"gallery: K must have a value of 0 or 1 for ipjfact matrix\");\n  endswitch\n\n  if (nargout == 2)\n    d = 1;\n\n    if (k == 0)\n      for i = 1:n-1\n        d *= prod (1:i+1) * prod (1:n-i);\n      endfor\n      d *= prod (1:n+1);\n\n    elseif (k == 1)\n      for i = 0:n-1\n        d *= prod (1:i) / prod (1:n+1+i);\n      endfor\n      if (rem (n*(n-1)/2, 2))\n        d = -d;\n      endif\n\n    else\n      error (\"gallery: K must have a value of 0 or 1 for ipjfact matrix\");\n    endif\n\n    detA = d;\n  endif\n\nendfunction\n\nfunction J = jordbloc (n, lambda = 1)\n\n  ## JORDBLOC  Jordan block.\n  ##   JORDBLOC(N, LAMBDA) is the N-by-N Jordan block with eigenvalue\n  ##   LAMBDA.  LAMBDA = 1 is the default.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for jordbloc matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for jordbloc matrix\");\n  elseif (! isnumeric (lambda) || ! isscalar (lambda))\n    error (\"gallery: LAMBDA must be a numeric scalar for jordbloc matrix\");\n  endif\n\n  J = lambda * eye (n) + diag (ones (n-1, 1), 1);\n\nendfunction\n\nfunction U = kahan (n, theta = 1.2, pert = 25)\n\n  ## KAHAN  Kahan matrix - upper trapezoidal.\n  ##   KAHAN(N, THETA) is an upper trapezoidal matrix\n  ##   that has some interesting properties regarding estimation of\n  ##   condition and rank.\n  ##   The matrix is N-by-N unless N is a 2-vector, in which case it\n  ##   is N(1)-by-N(2).\n  ##   The parameter THETA defaults to 1.2.\n  ##   The useful range of THETA is 0 < THETA < PI.\n  ##\n  ##   To ensure that the QR factorization with column pivoting does not\n  ##   interchange columns in the presence of rounding errors, the diagonal\n  ##   is perturbed by PERT*EPS*diag( [N:-1:1] ).\n  ##   The default is PERT = 25, which ensures no interchanges for KAHAN(N)\n  ##   up to at least N = 90 in IEEE arithmetic.\n  ##   KAHAN(N, THETA, PERT) uses the given value of PERT.\n  ##\n  ##   The inverse of KAHAN(N, THETA) is known explicitly: see\n  ##   Higham (1987, p. 588), for example.\n  ##   The diagonal perturbation was suggested by Christian Bischof.\n  ##\n  ##   References:\n  ##   W. Kahan, Numerical linear algebra, Canadian Math. Bulletin,\n  ##      9 (1966), pp. 757-801.\n  ##   N.J. Higham, A survey of condition number estimation for\n  ##      triangular matrices, SIAM Review, 29 (1987), pp. 575-596.\n\n  if (nargin < 1 || nargin > 3)\n    error (\"gallery: 1 to 3 arguments are required for kahan matrix\");\n  elseif (! isnumeric (n) || all (numel (n) != [1 2]) || fix (n) != n)\n    error (\"gallery: N must be a 1 or 2 element integer for kahan matrix\");\n  elseif (! isnumeric (theta) || ! isscalar (theta))\n    error (\"gallery: THETA must be a numeric scalar for kahan matrix\");\n  elseif (! isnumeric (pert) || ! isscalar (pert))\n    error (\"gallery: PERT must be a numeric scalar for kahan matrix\");\n  endif\n\n  ## Parameter n specifies dimension: r-by-n\n  r = n(1);\n  n = n(end);\n\n  s = sin (theta);\n  c = cos (theta);\n\n  U = eye (n) - c * triu (ones (n), 1);\n  U = diag (s.^[0:n-1]) * U + pert*eps* diag ([n:-1:1]);\n  if (r > n)\n    U(r,n) = 0;     # Extend to an r-by-n matrix\n  else\n    U = U(1:r,:);   # Reduce to an r-by-n matrix\n  endif\n\nendfunction\n\nfunction A = kms (n, rho = 0.5)\n\n  ## KMS   Kac-Murdock-Szego Toeplitz matrix.\n  ##   A = KMS(N, RHO) is the N-by-N Kac-Murdock-Szego Toeplitz matrix with\n  ##   A(i,j) = RHO^(ABS((i-j))) (for real RHO).\n  ##   If RHO is complex, then the same formula holds except that elements\n  ##   below the diagonal are conjugated.\n  ##   RHO defaults to 0.5.\n  ##   Properties:\n  ##      A has an LDL' factorization with\n  ##               L = INV(TRIW(N,-RHO,1)'),\n  ##               D(i,i) = (1-ABS(RHO)^2)*EYE(N) except D(1,1) = 1.\n  ##      A is positive definite if and only if 0 < ABS(RHO) < 1.\n  ##      INV(A) is tridiagonal.\n  ##\n  ##    Reference:\n  ##    W.F. Trench, Numerical solution of the eigenvalue problem\n  ##    for Hermitian Toeplitz matrices, SIAM J. Matrix Analysis and Appl.,\n  ##    10 (1989), pp. 135-146 (and see the references therein).\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for lauchli matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for lauchli matrix\");\n  elseif (! isscalar (rho))\n    error (\"gallery: RHO must be a scalar for lauchli matrix\");\n  endif\n\n  A = (1:n)'*ones (1,n);\n  A = abs (A - A');\n  A = rho .^ A;\n  if (imag (rho))\n    A = conj (tril (A,-1)) + triu (A);\n  endif\n\nendfunction\n\nfunction B = krylov (A, x, j)\n\n  ## KRYLOV    Krylov matrix.\n  ##   KRYLOV(A, x, j) is the Krylov matrix\n  ##        [x, Ax, A^2x, ..., A^(j-1)x],\n  ##   where A is an n-by-n matrix and x is an n-vector.\n  ##   Defaults: x = ONES(n,1), j = n.\n  ##   KRYLOV(n) is the same as KRYLOV(RANDN(n)).\n  ##\n  ##   Reference:\n  ##   G.H. Golub and C.F. Van Loan, Matrix Computations, second edition,\n  ##   Johns Hopkins University Press, Baltimore, Maryland, 1989, p. 369.\n\n  if (nargin < 1 || nargin > 3)\n    error (\"gallery: 1 to 3 arguments are required for krylov matrix\");\n  elseif (! isnumeric (A) || ! issquare (A) || ndims (A) != 2)\n    error (\"gallery: A must be a square 2-D matrix for krylov matrix\");\n  endif\n\n  n = length (A);\n  if (isscalar (A))\n    n = A;\n    A = randn (n);\n  endif\n\n  if (nargin < 2)\n    x = ones (n, 1);\n  elseif (! isvector (x) || numel (x) != n)\n    error (\"gallery: X must be a vector of length equal to A for krylov matrix\");\n  endif\n\n  if (nargin < 3)\n    j = n;\n  elseif (! isnumeric (j) || ! isscalar (j) || fix (j) != j)\n    error (\"gallery: J must be an integer for krylov matrix\");\n  endif\n\n  B = ones (n, j);\n  B(:,1) = x(:);\n  for i = 2:j\n    B(:,i) = A*B(:,i-1);\n  endfor\n\nendfunction\n\nfunction A = lauchli (n, mu = sqrt (eps))\n\n  ## LAUCHLI   Lauchli matrix - rectangular.\n  ##   LAUCHLI(N, MU) is the (N+1)-by-N matrix [ONES(1,N); MU*EYE(N))].\n  ##   It is a well-known example in least squares and other problems\n  ##   that indicates the dangers of forming A'*A.\n  ##   MU defaults to SQRT(EPS).\n  ##\n  ##   Reference:\n  ##   P. Lauchli, Jordan-Elimination und Ausgleichung nach\n  ##   kleinsten Quadraten, Numer. Math, 3 (1961), pp. 226-240.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for lauchli matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for lauchli matrix\");\n  elseif (! isscalar (mu))\n    error (\"gallery: MU must be a scalar for lauchli matrix\");\n  endif\n\n  A = [ones(1, n)\n       mu*eye(n) ];\n\nendfunction\n\nfunction A = lehmer (n)\n\n  ## LEHMER  Lehmer matrix - symmetric positive definite.\n  ##   A = LEHMER(N) is the symmetric positive definite N-by-N matrix with\n  ##                    A(i,j) = i/j for j >= i.\n  ##   A is totally nonnegative.  INV(A) is tridiagonal, and explicit\n  ##   formulas are known for its entries.\n  ##   N <= COND(A) <= 4*N*N.\n  ##\n  ##   References:\n  ##   M. Newman and J. Todd, The evaluation of matrix inversion\n  ##      programs, J. Soc. Indust. Appl. Math., 6 (1958), pp. 466-476.\n  ##   Solutions to problem E710 (proposed by D.H. Lehmer): The inverse\n  ##      of a matrix, Amer. Math. Monthly, 53 (1946), pp. 534-535.\n  ##   J. Todd, Basic Numerical Mathematics, Vol. 2: Numerical Algebra,\n  ##      Birkhauser, Basel, and Academic Press, New York, 1977, p. 154.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for lehmer matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for lehmer matrix\");\n  endif\n\n  A = ones (n, 1) * (1:n);\n  A = A./A';\n  A = tril (A) + tril (A, -1)';\n\nendfunction\n\nfunction T = lesp (n)\n\n  ## LESP   A tridiagonal matrix with real, sensitive eigenvalues.\n  ##   LESP(N) is an N-by-N matrix whose eigenvalues are real and smoothly\n  ##   distributed in the interval approximately [-2*N-3.5, -4.5].\n  ##   The sensitivities of the eigenvalues increase exponentially as\n  ##   the eigenvalues grow more negative.\n  ##   The matrix is similar to the symmetric tridiagonal matrix with\n  ##   the same diagonal entries and with off-diagonal entries 1,\n  ##   via a similarity transformation with D = diag(1!,2!,...,N!).\n  ##\n  ##   References:\n  ##   H.W.J. Lenferink and M.N. Spijker, On the use of stability regions in\n  ##        the numerical analysis of initial value problems,\n  ##        Math. Comp., 57 (1991), pp. 221-237.\n  ##   L.N. Trefethen, Pseudospectra of matrices, in Numerical Analysis 1991,\n  ##        Proceedings of the 14th Dundee Conference,\n  ##        D.F. Griffiths and G.A. Watson, eds, Pitman Research Notes in\n  ##        Mathematics, volume 260, Longman Scientific and Technical, Essex,\n  ##        UK, 1992, pp. 234-266.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for lesp matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for lesp matrix\");\n  endif\n\n  x = 2:n;\n  T = full (tridiag (ones (size (x)) ./x, -(2*[x n+1]+1), x));\n\nendfunction\n\nfunction A = lotkin (n)\n\n  ## LOTKIN  Lotkin matrix.\n  ##   A = LOTKIN(N) is the Hilbert matrix with its first row altered to\n  ##   all ones.  A is unsymmetric, ill-conditioned, and has many negative\n  ##   eigenvalues of small magnitude.\n  ##   The inverse has integer entries and is known explicitly.\n  ##\n  ##   Reference:\n  ##   M. Lotkin, A set of test matrices, MTAC, 9 (1955), pp. 153-161.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for lotkin matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for lotkin matrix\");\n  endif\n\n  A = hilb (n);\n  A(1,:) = ones (1, n);\n\nendfunction\n\nfunction A = minij (n)\n\n  ## MINIJ   Symmetric positive definite matrix MIN(i,j).\n  ##   A = MINIJ(N) is the N-by-N symmetric positive definite matrix with\n  ##   A(i,j) = MIN(i,j).\n  ##   Properties, variations:\n  ##   INV(A) is tridiagonal: it is minus the second difference matrix\n  ##               except its (N,N) element is 1.\n  ##   2*A-ONES(N) (Givens' matrix) has tridiagonal inverse and\n  ##               eigenvalues .5*sec^2([2r-1)PI/4N], r=1:N.\n  ##   (N+1)*ONES(N)-A also has a tridiagonal inverse.\n  ##\n  ##   References:\n  ##   J. Todd, Basic Numerical Mathematics, Vol. 2: Numerical Algebra,\n  ##      Birkhauser, Basel, and Academic Press, New York, 1977, p. 158.\n  ##   D.E. Rutherford, Some continuant determinants arising in physics and\n  ##      chemistry---II, Proc. Royal Soc. Edin., 63, A (1952), pp. 232-241.\n  ##      (For the eigenvalues of Givens' matrix.)\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for minij matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for minij matrix\");\n  endif\n\n  A = bsxfun (@min, 1:n, (1:n)');\n\nendfunction\n\nfunction A = moler (n, alpha = -1)\n\n  ## MOLER   Moler matrix - symmetric positive definite.\n  ##   A = MOLER(N, ALPHA) is the symmetric positive definite N-by-N matrix\n  ##   U'*U where U = TRIW(N, ALPHA).\n  ##   For ALPHA = -1 (the default) A(i,j) = MIN(i,j)-2, A(i,i) = i.\n  ##   A has one small eigenvalue.\n  ##\n  ##   Nash (1990) attributes the ALPHA = -1 matrix to Moler.\n  ##\n  ##   Reference:\n  ##   J.C. Nash, Compact Numerical Methods for Computers: Linear\n  ##   Algebra and Function Minimisation, second edition, Adam Hilger,\n  ##   Bristol, 1990 (Appendix 1).\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for moler matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for moler matrix\");\n  elseif (! isscalar (alpha))\n    error (\"gallery: ALPHA must be a scalar for moler matrix\");\n  endif\n\n  A = triw (n, alpha)' * triw (n, alpha);\n\nendfunction\n\nfunction [A, T] = neumann (n)\n\n  ## NEUMANN  Singular matrix from the discrete Neumann problem (sparse).\n  ##   NEUMANN(N) is the singular, row diagonally dominant matrix resulting\n  ##   from discretizing the Neumann problem with the usual five point\n  ##   operator on a regular mesh.\n  ##   It has a one-dimensional null space with null vector ONES(N,1).\n  ##   The dimension N should be a perfect square, or else a 2-vector,\n  ##   in which case the dimension of the matrix is N(1)*N(2).\n  ##\n  ##   Reference:\n  ##   R.J. Plemmons, Regular splittings and the discrete Neumann\n  ##   problem, Numer. Math., 25 (1976), pp. 153-161.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for neumann matrix\");\n  elseif (! isnumeric (n) || all (numel (n) != [1 2]) || fix (n) != n)\n    error (\"gallery: N must be a 1 or 2 element integer for neumann matrix\");\n  endif\n\n  if (isscalar (n))\n    m = sqrt (n);\n    if (m^2 != n)\n      error (\"gallery: N must be a perfect square for neumann matrix\");\n    endif\n    n(1) = m;\n    n(2) = m;\n  endif\n\n  T = tridiag (n(1), -1, 2, -1);\n  T(1,2) = -2;\n  T(n(1),n(1)-1) = -2;\n\n  A = kron (T, eye (n(2))) + kron (eye (n(2)), T);\n\nendfunction\n\nfunction A = normaldata (varargin)\n\n  if (nargin < 2)\n    error (\"gallery: At least 2 arguments required for normaldata matrix\");\n  endif\n  if (isnumeric (varargin{end}))\n    jidx = varargin{end};\n    svec = [varargin{:}];\n    varargin(end) = [];\n  elseif (ischar (varargin{end}))\n    if (nargin < 3)\n      error ([\"gallery: CLASS argument requires 3 inputs \" ...\n              \"for normaldata matrix.\"]);\n    endif\n    jidx = varargin{end-1};\n    svec = [varargin{1:end-1}];\n    varargin(end-1) = [];\n  else\n    error ([\"gallery: J must be an integer in the range [0, 2^32-1] \" ...\n            \"for normaldata matrix\"]);\n  endif\n\n  if (! (isnumeric (jidx) && isscalar (jidx)\n         && jidx == fix (jidx)\n         && jidx >= 0 && jidx <= 0xFFFFFFFF))\n    error ([\"gallery: J must be an integer in the range [0, 2^32-1] \" ...\n            \"for normaldata matrix\"]);\n  endif\n\n  ## Save and restore random state.  Initialization done so that reproducible\n  ## data is available from gallery depending on the jidx and size vector.\n  randstate = randn (\"state\");\n  unwind_protect\n    randn (\"state\", svec);\n    A = randn (varargin{:});\n  unwind_protect_cleanup\n    randn (\"state\", randstate);\n  end_unwind_protect\n\nendfunction\n\nfunction Q = orthog (n, k = 1)\n\n  ## ORTHOG Orthogonal and nearly orthogonal matrices.\n  ##   Q = ORTHOG(N, K) selects the K'th type of matrix of order N.\n  ##   K > 0 for exactly orthogonal matrices, K < 0 for diagonal scalings of\n  ##   orthogonal matrices.\n  ##   Available types: (K = 1 is the default)\n  ##   K = 1:  Q(i,j) = SQRT(2/(n+1)) * SIN( i*j*PI/(n+1) )\n  ##           Symmetric eigenvector matrix for second difference matrix.\n  ##   K = 2:  Q(i,j) = 2/SQRT(2*n+1)) * SIN( 2*i*j*PI/(2*n+1) )\n  ##           Symmetric.\n  ##   K = 3:  Q(r,s) = EXP(2*PI*i*(r-1)*(s-1)/n) / SQRT(n)  (i=SQRT(-1))\n  ##           Unitary, the Fourier matrix.  Q^4 is the identity.\n  ##           This is essentially the same matrix as FFT(EYE(N))/SQRT(N)!\n  ##   K = 4:  Helmert matrix: a permutation of a lower Hessenberg matrix,\n  ##           whose first row is ONES(1:N)/SQRT(N).\n  ##   K = 5:  Q(i,j) = SIN( 2*PI*(i-1)*(j-1)/n ) + COS( 2*PI*(i-1)*(j-1)/n ).\n  ##           Symmetric matrix arising in the Hartley transform.\n  ##   K = -1: Q(i,j) = COS( (i-1)*(j-1)*PI/(n-1) )\n  ##           Chebyshev Vandermonde-like matrix, based on extrema of T(n-1).\n  ##   K = -2: Q(i,j) = COS( (i-1)*(j-1/2)*PI/n) )\n  ##           Chebyshev Vandermonde-like matrix, based on zeros of T(n).\n  ##\n  ##   References:\n  ##   N.J. Higham and D.J. Higham, Large growth factors in Gaussian\n  ##        elimination with pivoting, SIAM J. Matrix Analysis and  Appl.,\n  ##        10 (1989), pp. 155-164.\n  ##   P. Morton, On the eigenvectors of Schur's matrix, J. Number Theory,\n  ##        12 (1980), pp. 122-127. (Re. ORTHOG(N, 3))\n  ##   H.O. Lancaster, The Helmert Matrices, Amer. Math. Monthly, 72 (1965),\n  ##        pp. 4-12.\n  ##   D. Bini and P. Favati, On a matrix algebra related to the discrete\n  ##        Hartley transform, SIAM J. Matrix Anal. Appl., 14 (1993),\n  ##        pp. 500-507.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for orthog matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for orthog matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a numeric scalar for orthog matrix\");\n  endif\n\n  switch (k)\n    case (1)\n      ## E'vectors second difference matrix\n      m = (1:n)'*(1:n) * (pi/(n+1));\n      Q = sin (m) * sqrt (2/(n+1));\n\n    case (2)\n      m = (1:n)'*(1:n) * (2*pi/(2*n+1));\n      Q = sin (m) * (2/ sqrt (2*n+1));\n\n    case (3)\n      ## Vandermonde based on roots of unity\n      m = 0:n-1;\n      Q = exp (m'*m*2*pi* sqrt (-1) / n) / sqrt (n);\n\n    case (4)\n      ## Helmert matrix\n      Q = tril (ones (n));\n      Q(1,2:n) = ones (1, n-1);\n      for i = 2:n\n        Q(i,i) = -(i-1);\n      endfor\n      Q = diag (sqrt ([n 1:n-1] .* [1:n])) \\ Q;\n\n    case (5)\n      ## Hartley matrix\n      m = (0:n-1)'*(0:n-1) * (2*pi/n);\n      Q = (cos (m) + sin (m)) / sqrt (n);\n\n    case (-1)\n      ##  extrema of T(n-1)\n      m = (0:n-1)'*(0:n-1) * (pi/(n-1));\n      Q = cos (m);\n\n    case (-2)\n      ## zeros of T(n)\n      m = (0:n-1)'*(.5:n-.5) * (pi/n);\n      Q = cos (m);\n\n    otherwise\n      error (\"gallery: unknown K '%d' for orthog matrix\", k);\n  endswitch\n\nendfunction\n\nfunction A = parter (n)\n\n  ## PARTER    Parter matrix - a Toeplitz matrix with singular values near PI.\n  ##   PARTER(N) is the matrix with (i,j) element 1/(i-j+0.5).\n  ##   It is a Cauchy matrix and a Toeplitz matrix.\n  ##\n  ##   At the Second SIAM Conference on Linear Algebra, Raleigh, N.C.,\n  ##   1985, Cleve Moler noted that most of the singular values of\n  ##   PARTER(N) are very close to PI.  An explanation of the phenomenon\n  ##   was given by Parter; see also the paper by Tyrtyshnikov.\n  ##\n  ##   References:\n  ##   The MathWorks Newsletter, Volume 1, Issue 1, March 1986, page 2.\n  ##   S.V. Parter, On the distribution of the singular values of Toeplitz\n  ##        matrices, Linear Algebra and Appl., 80 (1986), pp. 115-130.\n  ##   E.E. Tyrtyshnikov, Cauchy-Toeplitz matrices and some applications,\n  ##        Linear Algebra and Appl., 149 (1991), pp. 1-18.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for parter matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for parter matrix\");\n  endif\n\n  A = cauchy ((1:n) + 0.5, -(1:n));\n\nendfunction\n\nfunction P = pei (n, alpha = 1)\n\n  ## PEI    Pei matrix.\n  ##   PEI(N, ALPHA), where ALPHA is a scalar, is the symmetric matrix\n  ##   ALPHA*EYE(N) + ONES(N).\n  ##   If ALPHA is omitted then ALPHA = 1 is used.\n  ##   The matrix is singular for ALPHA = 0, -N.\n  ##\n  ##   Reference:\n  ##   M.L. Pei, A test matrix for inversion procedures,\n  ##   Comm. ACM, 5 (1962), p. 508.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for pei matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for pei matrix\");\n  elseif (! isnumeric (alpha) || ! isscalar (alpha))\n    error (\"gallery: ALPHA must be a scalar for pei matrix\");\n  endif\n\n  P = alpha * eye (n) + ones (n);\n\nendfunction\n\nfunction A = poisson (n)\n\n  ## POISSON   Block tridiagonal matrix from Poisson's equation (sparse).\n  ##   POISSON(N) is the block tridiagonal matrix of order N^2\n  ##   resulting from discretizing Poisson's equation with the\n  ##   5-point operator on an N-by-N mesh.\n  ##\n  ##   Reference:\n  ##   G.H. Golub and C.F. Van Loan, Matrix Computations, second edition,\n  ##   Johns Hopkins University Press, Baltimore, Maryland, 1989\n  ##   (Section 4.5.4).\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for poisson matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for poisson matrix\");\n  endif\n\n  S = tridiag (n, -1, 2, -1);\n  I = speye (n);\n  A = kron (I, S) + kron (S, I);\n\nendfunction\n\nfunction A = prolate (n, w = 0.25)\n\n  ## PROLATE   Prolate matrix - symmetric, ill-conditioned Toeplitz matrix.\n  ##   A = PROLATE(N, W) is the N-by-N prolate matrix with parameter W.\n  ##   It is a symmetric Toeplitz matrix.\n  ##   If 0 < W < 0.5 then\n  ##      - A is positive definite\n  ##      - the eigenvalues of A are distinct, lie in (0, 1), and\n  ##        tend to cluster around 0 and 1.\n  ##   W defaults to 0.25.\n  ##\n  ##   Reference:\n  ##   J.M. Varah. The Prolate matrix. Linear Algebra and Appl.,\n  ##   187:269--278, 1993.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for prolate matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for prolate matrix\");\n  elseif (! isnumeric (w) || ! isscalar (w))\n    error (\"gallery: W must be a scalar for prolate matrix\");\n  endif\n\n  a      = zeros (n, 1);\n  a(1)   = 2*w;\n  a(2:n) = sin (2*pi*w*(1:n-1)) ./ (pi*(1:n-1));\n\n  A = toeplitz (a);\n\nendfunction\n\nfunction H = randhess (x)\n\n  ## NOTE: this function was named ohess in the original Test Matrix Toolbox\n  ## RANDHESS  Random, orthogonal upper Hessenberg matrix.\n  ##   H = RANDHESS(N) is an N-by-N real, random, orthogonal\n  ##   upper Hessenberg matrix.\n  ##   Alternatively, H = RANDHESS(X), where X is an arbitrary real\n  ##   N-vector (N > 1) constructs H non-randomly using the elements\n  ##   of X as parameters.\n  ##   In both cases H is constructed via a product of N-1 Givens rotations.\n  ##\n  ##   Note: See Gragg (1986) for how to represent an N-by-N (complex)\n  ##   unitary Hessenberg matrix with positive subdiagonal elements in terms\n  ##   of 2N-1 real parameters (the Schur parametrization).\n  ##   This M-file handles the real case only and is intended simply as a\n  ##   convenient way to generate random or non-random orthogonal Hessenberg\n  ##   matrices.\n  ##\n  ##   Reference:\n  ##   W.B. Gragg, The QR algorithm for unitary Hessenberg matrices,\n  ##   J. Comp. Appl. Math., 16 (1986), pp. 1-8.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for randhess matrix\");\n  elseif (! isnumeric (x) || ! isreal (x))\n    error (\"gallery: N or X must be numeric real values for randhess matrix\");\n  endif\n\n  if (isscalar (x))\n    n = x;\n    x = rand (n-1, 1) * 2*pi;\n    H = eye (n);\n    H(n,n) = sign (randn);\n  elseif (isvector (x))\n    n = numel (x);\n    H = eye (n);\n    H(n,n) = sign (x(n)) + (x(n) == 0); # Second term ensures H(n,n) nonzero.\n  else\n    error (\"gallery: N or X must be a scalar or a vector for randhess matrix\");\n  endif\n\n  for i = n:-1:2\n    ## Apply Givens rotation through angle x(i-1).\n    theta = x(i-1);\n    c = cos (theta);\n    s = sin (theta);\n    H([i-1 i], :) = [ c*H(i-1,:)+s*H(i,:)\n                     -s*H(i-1,:)+c*H(i,:) ];\n  endfor\n\nendfunction\n\nfunction A = rando (n, k = 1)\n\n  ## RANDO   Random matrix with elements -1, 0 or 1.\n  ##   A = RANDO(N, K) is a random N-by-N matrix with elements from\n  ##   one of the following discrete distributions (default K = 1):\n  ##     K = 1:  A(i,j) =  0 or 1    with equal probability,\n  ##     K = 2:  A(i,j) = -1 or 1    with equal probability,\n  ##     K = 3:  A(i,j) = -1, 0 or 1 with equal probability.\n  ##   N may be a 2-vector, in which case the matrix is N(1)-by-N(2).\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for rando matrix\");\n  elseif (! isnumeric (n) || all (numel (n) != [1 2]) || fix (n) != n)\n    error (\"gallery: N must be an integer for rando matrix\");\n  elseif (! isnumeric (k) || ! isscalar (k))\n    error (\"gallery: K must be a numeric scalar for smoke matrix\");\n  endif\n\n  ## Parameter n specifies dimension: m-by-n.\n  m = n(1);\n  n = n(end);\n\n  switch (k)\n    case (1), A =   floor (  rand(m, n) + 0.5);     # {0, 1}\n    case (2), A = 2*floor (  rand(m, n) + 0.5) -1;  # {-1, 1}\n    case (3), A =   round (3*rand(m, n) - 1.5);     # {-1, 0, 1}\n    otherwise\n      error (\"gallery: unknown K '%d' for smoke matrix\", k);\n  endswitch\n\nendfunction\n\nfunction A = randsvd (n, kappa = sqrt (1/eps), mode = 3, kl = max (n) -1,\n                      ku = kl)\n\n  ## RANDSVD  Random matrix with pre-assigned singular values.\n  ##   RANDSVD(N, KAPPA, MODE, KL, KU) is a (banded) random matrix of order N\n  ##   with COND(A) = KAPPA and singular values from the distribution MODE.\n  ##   N may be a 2-vector, in which case the matrix is N(1)-by-N(2).\n  ##   Available types:\n  ##          MODE = 1:   one large singular value,\n  ##          MODE = 2:   one small singular value,\n  ##          MODE = 3:   geometrically distributed singular values,\n  ##          MODE = 4:   arithmetically distributed singular values,\n  ##          MODE = 5:   random singular values with unif. dist. logarithm.\n  ##   If omitted, MODE defaults to 3, and KAPPA defaults to SQRT(1/EPS).\n  ##   If MODE < 0 then the effect is as for ABS(MODE) except that in the\n  ##   original matrix of singular values the order of the diagonal entries\n  ##   is reversed: small to large instead of large to small.\n  ##   KL and KU are the lower and upper bandwidths respectively; if they\n  ##   are omitted a full matrix is produced.\n  ##   If only KL is present, KU defaults to KL.\n  ##   Special case: if KAPPA < 0 then a random full symmetric positive\n  ##                 definite matrix is produced with COND(A) = -KAPPA and\n  ##                 eigenvalues distributed according to MODE.\n  ##                 KL and KU, if present, are ignored.\n  ##\n  ##   Reference:\n  ##   N.J. Higham, Accuracy and Stability of Numerical Algorithms,\n  ##      Society for Industrial and Applied Mathematics, Philadelphia, PA,\n  ##      USA, 1996; sec. 26.3.\n  ##\n  ##   This routine is similar to the more comprehensive Fortran routine xLATMS\n  ##   in the following reference:\n  ##   J.W. Demmel and A. McKenney, A test matrix generation suite,\n  ##   LAPACK Working Note #9, Courant Institute of Mathematical Sciences,\n  ##   New York, 1989.\n\n  if (nargin < 1 || nargin > 5)\n    error (\"gallery: 1 to 5 arguments are required for randsvd matrix\");\n  elseif (! isnumeric (n) || all (numel (n) != [1 2]) || fix (n) != n)\n    error (\"gallery: N must be a 1 or 2 element integer vector for randsvd matrix\");\n  elseif (! isnumeric (kappa) || ! isscalar (kappa))\n    error (\"gallery: KAPPA must be a numeric scalar for randsvd matrix\");\n  elseif (abs (kappa) < 1)\n    error (\"gallery: KAPPA must larger than or equal to 1 for randsvd matrix\");\n  elseif (! isnumeric (mode) || ! isscalar (mode))\n    error (\"gallery: MODE must be a numeric scalar for randsvd matrix\");\n  elseif (! isnumeric (kl) || ! isscalar (kl))\n    error (\"gallery: KL must be a numeric scalar for randsvd matrix\");\n  elseif (! isnumeric (ku) || ! isscalar (ku))\n    error (\"gallery: KU must be a numeric scalar for randsvd matrix\");\n  endif\n\n  posdef = 0;\n  if (kappa < 0)\n    posdef = 1;\n    kappa  = -kappa;\n  endif\n\n  ## Parameter n specifies dimension: m-by-n.\n  m = n(1);\n  n = n(end);\n  p = min ([m n]);\n\n  ## If A will be a vector\n  if (p == 1)\n    A = randn (m, n);\n    A /= norm (A);\n    return;\n  endif\n\n  ##  Set up vector sigma of singular values.\n  switch (abs (mode))\n    case (1)\n      sigma = ones (p, 1) ./ kappa;\n      sigma(1) = 1;\n    case (2)\n      sigma = ones (p, 1);\n      sigma(p) = 1 / kappa;\n    case (3)\n      factor = kappa^(-1/(p-1));\n      sigma  = factor.^[0:p-1];\n    case (4)\n      sigma = ones (p, 1) - (0:p-1)'/(p-1)*(1-1/kappa);\n    case (5)\n      ## In this case cond (A) <= kappa.\n      rand (\"uniform\");\n      sigma = exp (-rand (p, 1) * log (kappa));\n    otherwise\n      error (\"gallery: unknown MODE '%d' for randsvd matrix\", mode);\n  endswitch\n\n  ##  Convert to diagonal matrix of singular values.\n  if (mode < 0)\n    sigma = sigma(p:-1:1);\n  endif\n  sigma = diag (sigma);\n\n  if (posdef)\n    ## handle case where KAPPA was negative\n    Q = qmult (p);\n    A = Q' * sigma * Q;\n    A = (A + A') / 2;  # Ensure matrix is symmetric.\n    return;\n  endif\n\n  if (m != n)\n    ## Expand to m-by-n diagonal matrix\n    sigma(m, n) = 0;\n  endif\n\n  if (kl == 0 && ku == 0)\n    ## Diagonal matrix requested - nothing more to do.\n    A = sigma;\n  else\n    ##  A = U*sigma*V, where U, V are random orthogonal matrices from the\n    ##  Haar distribution.\n    A = qmult (sigma');\n    A = qmult (A');\n\n    if (kl < n-1 || ku < n-1)\n      ## Bandwidth reduction\n      A = bandred (A, kl, ku);\n    endif\n  endif\n\nendfunction\n\nfunction A = redheff (n)\n\n  ## REDHEFF    A (0,1) matrix of Redheffer associated with the Riemann hypothesis.\n  ##   A = REDHEFF(N) is an N-by-N matrix of 0s and 1s defined by\n  ##       A(i,j) = 1 if j = 1 or if i divides j,\n  ##       A(i,j) = 0 otherwise.\n  ##   It has N - FLOOR(LOG2(N)) - 1 eigenvalues equal to 1,\n  ##   a real eigenvalue (the spectral radius) approximately SQRT(N),\n  ##   a negative eigenvalue approximately -SQRT(N),\n  ##   and the remaining eigenvalues are provably ``small''.\n  ##   Barrett and Jarvis (1992) conjecture that\n  ##     ``the small eigenvalues all lie inside the unit circle\n  ##       ABS(Z) = 1'',\n  ##   and a proof of this conjecture, together with a proof that some\n  ##   eigenvalue tends to zero as N tends to infinity, would yield\n  ##   a new proof of the prime number theorem.\n  ##   The Riemann hypothesis is true if and only if\n  ##   DET(A) = O( N^(1/2+epsilon) ) for every epsilon > 0\n  ##                                     ('!' denotes factorial).\n  ##   See also RIEMANN.\n  ##\n  ##   Reference:\n  ##   W.W. Barrett and T.J. Jarvis,\n  ##   Spectral Properties of a Matrix of Redheffer,\n  ##   Linear Algebra and Appl., 162 (1992), pp. 673-683.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for redheff matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for redheff matrix\");\n  endif\n\n  i = (1:n)' * ones (1, n);\n  A = ! rem (i', i);\n  A(:,1) = ones (n, 1);\n\nendfunction\n\nfunction A = riemann (n)\n\n  ## RIEMANN    A matrix associated with the Riemann hypothesis.\n  ##   A = RIEMANN(N) is an N-by-N matrix for which the\n  ##   Riemann hypothesis is true if and only if\n  ##   DET(A) = O( N! N^(-1/2+epsilon) ) for every epsilon > 0\n  ##                                     ('!' denotes factorial).\n  ##   A = B(2:N+1, 2:N+1), where\n  ##   B(i,j) = i-1 if i divides j and -1 otherwise.\n  ##   Properties include, with M = N+1:\n  ##      Each eigenvalue E(i) satisfies ABS(E(i)) <= M - 1/M.\n  ##      i <= E(i) <= i+1 with at most M-SQRT(M) exceptions.\n  ##      All integers in the interval (M/3, M/2] are eigenvalues.\n  ##\n  ##   See also REDHEFF.\n  ##\n  ##   Reference:\n  ##   F. Roesler, Riemann's hypothesis as an eigenvalue problem,\n  ##   Linear Algebra and Appl., 81 (1986), pp. 153-198.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for riemann matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for riemann matrix\");\n  endif\n\n  n += 1;\n  i = (2:n)' * ones (1, n-1);\n  j = i';\n  A = i .* (! rem (j, i)) - ones (n-1);\n\nendfunction\n\nfunction A = ris (n)\n\n  ## NOTE: this function was named dingdong in the original Test Matrix Toolbox\n  ## RIS       Dingdong matrix - a symmetric Hankel matrix.\n  ##   A = RIS(N) is the symmetric N-by-N Hankel matrix with\n  ##                  A(i,j) = 0.5/(N-i-j+1.5).\n  ##   The eigenvalues of A cluster around PI/2 and -PI/2.\n  ##\n  ##   Invented by F.N. Ris.\n  ##\n  ##   Reference:\n  ##   J.C. Nash, Compact Numerical Methods for Computers: Linear\n  ##   Algebra and Function Minimisation, second edition, Adam Hilger,\n  ##   Bristol, 1990 (Appendix 1).\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for ris matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for ris matrix\");\n  endif\n\n  p = -2*(1:n) + (n+1.5);\n  A = cauchy (p);\n\nendfunction\n\nfunction A = smoke (n, k = 0)\n\n  ## SMOKE     Smoke matrix - complex, with a 'smoke ring' pseudospectrum.\n  ##   SMOKE(N) is an N-by-N matrix with 1s on the\n  ##   superdiagonal, 1 in the (N,1) position, and powers of\n  ##   roots of unity along the diagonal.\n  ##   SMOKE(N, 1) is the same except for a zero (N,1) element.\n  ##   The eigenvalues of SMOKE(N, 1) are the N'th roots of unity;\n  ##   those of SMOKE(N) are the N'th roots of unity times 2^(1/N).\n  ##\n  ##   Try PS(SMOKE(32)).  For SMOKE(N, 1) the pseudospectrum looks\n  ##   like a sausage folded back on itself.\n  ##   GERSH(SMOKE(N, 1)) is interesting.\n  ##\n  ##   Reference:\n  ##   L. Reichel and L.N. Trefethen, Eigenvalues and pseudo-eigenvalues of\n  ##   Toeplitz matrices, Linear Algebra and Appl., 162-164:153-185, 1992.\n\n  if (nargin < 1 || nargin > 2)\n    error (\"gallery: 1 to 2 arguments are required for smoke matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be an integer for smoke matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n))\n    error (\"gallery: K must be a numeric scalar for smoke matrix\");\n  endif\n\n  w = exp (2*pi*i/n);\n  A = diag ( [w.^(1:n-1) 1] ) + diag (ones (n-1,1), 1);\n\n  switch (k)\n    case 0, A(n,1) = 1;\n    case 1, # do nothing\n    otherwise,\n      error (\"gallery: K must have a value of 0 or 1 for smoke matrix\");\n  endswitch\n\nendfunction\n\nfunction T = toeppd (n, m = n, w = rand (m,1), theta = rand (m,1))\n\n  ## NOTE: this function was named pdtoep in the original Test Matrix Toolbox\n  ## TOEPPD   Symmetric positive definite Toeplitz matrix.\n  ##   TOEPPD(N, M, W, THETA) is an N-by-N symmetric positive (semi-)\n  ##   definite (SPD) Toeplitz matrix, comprised of the sum of M rank 2\n  ##   (or, for certain THETA, rank 1) SPD Toeplitz matrices.\n  ##   Specifically,\n  ##           T = W(1)*T(THETA(1)) + ... + W(M)*T(THETA(M)),\n  ##   where T(THETA(k)) has (i,j) element COS(2*PI*THETA(k)*(i-j)).\n  ##   Defaults: M = N, W = RAND(M,1), THETA = RAND(M,1).\n  ##\n  ##   Reference:\n  ##   G. Cybenko and C.F. Van Loan, Computing the minimum eigenvalue of\n  ##   a symmetric positive definite Toeplitz matrix, SIAM J. Sci. Stat.\n  ##   Comput., 7 (1986), pp. 123-131.\n\n  if (nargin < 1 || nargin > 4)\n    error (\"gallery: 1 to 4 arguments are required for toeppd matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be a numeric integer for toeppd matrix\");\n  elseif (! isnumeric (m) || ! isscalar (m) || fix (m) != m)\n    error (\"gallery: M must be a numeric integer for toeppd matrix\");\n  elseif (numel (w) != m || numel (theta) != m)\n    error (\"gallery: W and THETA must be vectors of length M for toeppd matrix\");\n  endif\n\n  T = zeros (n);\n  E = 2*pi * ((1:n)' * ones (1, n) - ones (n, 1) * (1:n));\n\n  for i = 1:m\n    T += w(i) * cos (theta(i)*E);\n  endfor\n\nendfunction\n\nfunction P = toeppen (n, a = 1, b = -10, c = 0, d = 10, e = 1)\n\n  ## NOTE: this function was named pentoep in the original Test Matrix Toolbox\n  ## TOEPPEN   Pentadiagonal Toeplitz matrix (sparse).\n  ##   P = TOEPPEN(N, A, B, C, D, E) is the N-by-N pentadiagonal\n  ##   Toeplitz matrix with diagonals composed of the numbers\n  ##   A =: P(3,1), B =: P(2,1), C =: P(1,1), D =: P(1,2), E =: P(1,3).\n  ##   Default: (A,B,C,D,E) = (1,-10,0,10,1) (a matrix of Rutishauser).\n  ##             This matrix has eigenvalues lying approximately on\n  ##             the line segment 2*cos(2*t) + 20*i*sin(t).\n  ##\n  ##   Interesting plots are\n  ##   PS(FULL(TOEPPEN(32,0,1,0,0,1/4)))  - 'triangle'\n  ##   PS(FULL(TOEPPEN(32,0,1/2,0,0,1)))  - 'propeller'\n  ##   PS(FULL(TOEPPEN(32,0,1/2,1,1,1)))  - 'fish'\n  ##\n  ##   References:\n  ##   R.M. Beam and R.F. Warming, The asymptotic spectra of\n  ##      banded Toeplitz and quasi-Toeplitz matrices, SIAM J. Sci.\n  ##      Comput. 14 (4), 1993, pp. 971-1006.\n  ##   H. Rutishauser, On test matrices, Programmation en Mathematiques\n  ##      Numeriques, Editions Centre Nat. Recherche Sci., Paris, 165,\n  ##      1966, pp. 349-365.\n\n  if (nargin < 1 || nargin > 6)\n    error (\"gallery: 1 to 6 arguments are required for toeppen matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)\n    error (\"gallery: N must be a numeric integer for toeppen matrix\");\n  elseif (any (! cellfun (\"isnumeric\", {a b c d e}))\n          || any (cellfun (\"numel\", {a b c d e}) != 1))\n    error (\"gallery: A, B, C, D and E must be numeric scalars for toeppen matrix\");\n  endif\n\n  P = spdiags ([a*ones(n,1) b*ones(n,1) c*ones(n,1) d*ones(n,1) e*ones(n,1)],\n                -2:2, n, n);\n\nendfunction\n\nfunction T = tridiag (n, x = -1, y = 2, z = -1)\n\n  ## TRIDIAG  Tridiagonal matrix (sparse).\n  ##   TRIDIAG(X, Y, Z) is the tridiagonal matrix with subdiagonal X,\n  ##   diagonal Y, and superdiagonal Z.\n  ##   X and Z must be vectors of dimension one less than Y.\n  ##   Alternatively TRIDIAG(N, C, D, E), where C, D, and E are all\n  ##   scalars, yields the Toeplitz tridiagonal matrix of order N\n  ##   with subdiagonal elements C, diagonal elements D, and superdiagonal\n  ##   elements E.   This matrix has eigenvalues (Todd 1977)\n  ##            D + 2*SQRT(C*E)*COS(k*PI/(N+1)), k=1:N.\n  ##   TRIDIAG(N) is the same as TRIDIAG(N,-1,2,-1), which is\n  ##   a symmetric positive definite M-matrix (the negative of the\n  ##   second difference matrix).\n  ##\n  ##   References:\n  ##   J. Todd, Basic Numerical Mathematics, Vol. 2: Numerical Algebra,\n  ##     Birkhauser, Basel, and Academic Press, New York, 1977, p. 155.\n  ##   D.E. Rutherford, Some continuant determinants arising in physics and\n  ##     chemistry---II, Proc. Royal Soc. Edin., 63, A (1952), pp. 232-241.\n\n  if (nargin != 1 && nargin != 3 && nargin != 4)\n    error (\"gallery: 1, 3, or 4 arguments are required for tridiag matrix\");\n  elseif (nargin == 3)\n    z = y;\n    y = x;\n    x = n;\n  endif\n\n  ## Force column vectors\n  x = x(:);\n  y = y(:);\n  z = z(:);\n\n  if (isscalar (x) && isscalar (y) && isscalar (z))\n    x *= ones (n-1, 1);\n    z *= ones (n-1, 1);\n    y *= ones (n,   1);\n  elseif (numel (y) != numel (x) + 1)\n    error (\"gallery: X must have one element less than Y for tridiag matrix\");\n  elseif (numel (y) != numel (z) + 1)\n    error (\"gallery: Z must have one element less than Y for tridiag matrix\");\n  endif\n\n  ##  T = diag (x, -1) + diag (y) + diag (z, 1);  # For non-sparse matrix.\n  n = numel (y);\n  T = spdiags ([[x;0] y [0;z]], -1:1, n, n);\n\nendfunction\n\nfunction t = triw (n, alpha = -1, k = n(end) - 1)\n\n  ## TRIW   Upper triangular matrix discussed by Wilkinson and others.\n  ##   TRIW(N, ALPHA, K) is the upper triangular matrix with ones on\n  ##   the diagonal and ALPHAs on the first K >= 0 superdiagonals.\n  ##   N may be a 2-vector, in which case the matrix is N(1)-by-N(2) and\n  ##   upper trapezoidal.\n  ##   Defaults: ALPHA = -1,\n  ##             K = N - 1     (full upper triangle).\n  ##   TRIW(N) is a matrix discussed by Kahan, Golub and Wilkinson.\n  ##\n  ##   Ostrowski (1954) shows that\n  ##     COND(TRIW(N,2)) = COT(PI/(4*N))^2,\n  ##   and for large ABS(ALPHA),\n  ##     COND(TRIW(N,ALPHA)) is approximately ABS(ALPHA)^N*SIN(PI/(4*N-2)).\n  ##\n  ##   Adding -2^(2-N) to the (N,1) element makes TRIW(N) singular,\n  ##   as does adding -2^(1-N) to all elements in the first column.\n  ##\n  ##   References:\n  ##   G.H. Golub and J.H. Wilkinson, Ill-conditioned eigensystems and the\n  ##      computation of the Jordan canonical form, SIAM Review,\n  ##      18(4), 1976, pp. 578-619.\n  ##   W. Kahan, Numerical linear algebra, Canadian Math. Bulletin,\n  ##      9 (1966), pp. 757-801.\n  ##   A.M. Ostrowski, On the spectrum of a one-parametric family of\n  ##      matrices, J. Reine Angew. Math., 193 (3/4), 1954, pp. 143-160.\n  ##   J.H. Wilkinson, Singular-value decomposition---basic aspects,\n  ##      in D.A.H. Jacobs, ed., Numerical Software---Needs and Availability,\n  ##      Academic Press, London, 1978, pp. 109-135.\n\n  if (nargin < 1 || nargin > 3)\n    error (\"gallery: 1 to 3 arguments are required for triw matrix\");\n  elseif (! isnumeric (n) || all (numel (n) != [1 2]))\n    error (\"gallery: N must be a 1 or 2 elements vector for triw matrix\");\n  elseif (! isscalar (alpha))\n    error (\"gallery: ALPHA must be a scalar for triw matrix\");\n  elseif (! isscalar (k) || ! isnumeric (k) || fix (k) != k || k < 0)\n    error (\"gallery: K must be a numeric integer >= 0 for triw matrix\");\n  endif\n\n  m = n(1);              # Parameter n specifies dimension: m-by-n.\n  n = n(end);\n\n  t = tril (eye (m, n) + alpha * triu (ones (m, n), 1), k);\n\nendfunction\n\nfunction A = uniformdata (varargin)\n\n  if (nargin < 2)\n    error (\"gallery: At least 2 arguments required for uniformdata matrix\");\n  endif\n  if (isnumeric (varargin{end}))\n    jidx = varargin{end};\n    svec = [varargin{:}];\n    varargin(end) = [];\n  elseif (ischar (varargin{end}))\n    if (nargin < 3)\n      error ([\"gallery: CLASS argument requires 3 inputs \" ...\n              \"for uniformdata matrix.\"]);\n    endif\n    jidx = varargin{end-1};\n    svec = [varargin{1:end-1}];\n    varargin(end-1) = [];\n  else\n    error ([\"gallery: J must be an integer in the range [0, 2^32-1] \" ...\n            \"for uniformdata matrix\"]);\n  endif\n\n  if (! (isnumeric (jidx) && isscalar (jidx)\n         && jidx == fix (jidx)\n         && jidx >= 0 && jidx <= 0xFFFFFFFF))\n    error ([\"gallery: J must be an integer in the range [0, 2^32-1] \" ...\n            \"for uniformdata matrix\"]);\n  endif\n\n  ## Save and restore random state.  Initialization done so that reproducible\n  ## data is available from gallery depending on the jidx and size vector.\n  randstate = rand (\"state\");\n  unwind_protect\n    rand (\"state\", svec);\n    A = rand (varargin{:});\n  unwind_protect_cleanup\n    rand (\"state\", randstate);\n  end_unwind_protect\n\nendfunction\n\nfunction A = wathen (nx, ny, k = 0)\n\n  ## WATHEN returns the Wathen matrix.\n  ##\n  ## Discussion:\n  ##\n  ##   The Wathen matrix is a finite element matrix which is sparse.\n  ##\n  ##   The entries of the matrix depend in part on a physical quantity\n  ##   related to density.  That density is here assigned random values between\n  ##   0 and 100.\n  ##\n  ##   A = WATHEN ( NX, NY ) is a sparse random N-by-N finite element matrix\n  ##   where N = 3*NX*NY + 2*NX + 2*NY + 1.\n  ##\n  ##   A is the consistent mass matrix for a regular NX-by-NY\n  ##   grid of 8-node (serendipity) elements in 2 space dimensions.\n  ##\n  ##   Here is an illustration for NX = 3, NX = 2:\n  ##\n  ##    23-24-25-26-27-28-29\n  ##     |     |     |     |\n  ##    19    20    21    22\n  ##     |     |     |     |\n  ##    12-13-14-15-16-17-18\n  ##     |     |     |     |\n  ##     8     9    10    11\n  ##     |     |     |     |\n  ##     1--2--3--4--5--6--7\n  ##\n  ##   For this example, the total number of nodes is, as expected,\n  ##\n  ##     N = 3 * 3 * 2 + 2 * 2 + 2 * 3 + 1 = 29.\n  ##\n  ##   A is symmetric positive definite for any (positive) values of\n  ##   the density, RHO(NX,NY), which is chosen randomly in this routine.\n  ##\n  ##   In particular, if D = DIAG(DIAG(A)), then\n  ##     0.25 <= EIG(INV(D)*A) <= 4.5\n  ##   for any positive integers NX and NY and any densities RHO(NX,NY).\n  ##\n  ##   A = WATHEN ( NX, NY, 1 ) returns the diagonally scaled matrix.\n  ##\n  ## Modified:\n  ##\n  ##   17 September 2007\n  ##\n  ## Author:\n  ##\n  ##   Nicholas Higham\n  ##\n  ## Reference:\n  ##\n  ##   Nicholas Higham,\n  ##   Algorithm 694: A Collection of Test Matrices in MATLAB,\n  ##   ACM Transactions on Mathematical Software,\n  ##   Volume 17, Number 3, September 1991, pages 289-305.\n  ##\n  ##   Andrew Wathen,\n  ##   Realistic eigenvalue bounds for the Galerkin mass matrix,\n  ##   IMA Journal of Numerical Analysis,\n  ##   Volume 7, 1987, pages 449-457.\n  ##\n  ## Parameters:\n  ##\n  ##   Input, integer NX, NY, the number of elements in the X and Y directions\n  ##   of the finite element grid.  NX and NY must each be at least 1.\n  ##\n  ##   Optional input, integer K, is used to request that the diagonally scaled\n  ##   version of the matrix be returned.  This happens if K is specified with\n  ##   the value 1.\n  ##\n  ##   Output, sparse real A(N,N), the matrix.  The dimension N is determined by\n  ##   NX and NY, as described above.  A is stored in the MATLAB sparse matrix\n  ##   format.\n\n  if (nargin < 2 || nargin > 3)\n    error (\"gallery: 2 or 3 arguments are required for wathen matrix\");\n  elseif (! isnumeric (nx) || ! isscalar (nx) || nx < 1)\n    error (\"gallery: NX must be a positive scalar for wathen matrix\");\n  elseif (! isnumeric (ny) || ! isscalar (ny) || ny < 1)\n    error (\"gallery: NY must be a positive scalar for wathen matrix\");\n  elseif (! isscalar (k))\n    error (\"gallery: K must be a scalar for wathen matrix\");\n  endif\n\n  e1 = [ 6  -6   2  -8\n        -6  32  -6  20\n         2  -6   6  -6\n        -8  20  -6  32 ];\n\n  e2 = [ 3  -8   2  -6\n        -8  16  -8  20\n         2  -8   3  -8\n        -6  20  -8  16 ];\n\n  e = [ e1  e2\n        e2' e1] / 45;\n\n  n = 3*nx*ny + 2*nx + 2*ny + 1;\n\n  A = sparse (n, n);\n\n  rho = 100 * rand (nx, ny);\n\n  for j = 1:ny\n    for i = 1:nx\n      ##\n      ##   For the element (I,J), determine the indices of the 8 nodes.\n      ##\n      nn(1) = 3*j*nx + 2*i + 2*j + 1;\n      nn(2) = nn(1) - 1;\n      nn(3) = nn(2) - 1;\n      nn(4) = (3*j - 1) * nx + 2*j + i - 1;\n      nn(5) = 3 * (j-1) * nx + 2*i + 2*j - 3;\n      nn(6) = nn(5) + 1;\n      nn(7) = nn(6) + 1;\n      nn(8) = nn(4) + 1;\n\n      em = e * rho(i,j);\n\n      for krow = 1:8\n        for kcol = 1:8\n          A(nn(krow),nn(kcol)) = A(nn(krow),nn(kcol)) + em(krow,kcol);\n        endfor\n      endfor\n\n    endfor\n  endfor\n\n  ## If requested, return A with diagonal scaling.\n  if (k)\n    A = diag (diag (A)) \\ A;\n  endif\n\nendfunction\n\nfunction [A, b] = wilk (n)\n\n  ## WILK   Various specific matrices devised/discussed by Wilkinson.\n  ##   [A, b] = WILK(N) is the matrix or system of order N.\n  ##   N = 3: upper triangular system Ux=b illustrating inaccurate solution.\n  ##   N = 4: lower triangular system Lx=b, ill-conditioned.\n  ##   N = 5: HILB(6)(1:5,2:6)*1.8144.  Symmetric positive definite.\n  ##   N = 21: W21+, tridiagonal.   Eigenvalue problem.\n  ##\n  ##   References:\n  ##   J.H. Wilkinson, Error analysis of direct methods of matrix inversion,\n  ##      J. Assoc. Comput. Mach., 8 (1961),  pp. 281-330.\n  ##   J.H. Wilkinson, Rounding Errors in Algebraic Processes, Notes on Applied\n  ##      Science No. 32, Her Majesty's Stationery Office, London, 1963.\n  ##   J.H. Wilkinson, The Algebraic Eigenvalue Problem, Oxford University\n  ##      Press, 1965.\n\n  if (nargin < 1)\n    error (\"gallery: 1 argument is required for wilk matrix\");\n  elseif (! isnumeric (n) || ! isscalar (n))\n    error (\"gallery: N must be a numeric scalar for wilk matrix\");\n  endif\n\n  if (n == 3)\n    ## Wilkinson (1961) p.323.\n    A = [ 1e-10   0.9  -0.4\n          0       0.9  -0.4\n          0       0     1e-10 ];\n\n    b = [ 0\n          0\n          1];\n\n  elseif (n == 4)\n    ## Wilkinson (1963) p.105.\n    A = [0.9143e-4  0          0          0\n         0.8762     0.7156e-4  0          0\n         0.7943     0.8143     0.9504e-4  0\n         0.8017     0.6123     0.7165     0.7123e-4];\n\n    b = [0.6524\n         0.3127\n         0.4186\n         0.7853];\n\n  elseif (n == 5)\n    ## Wilkinson (1965), p.234.\n    A = hilb (6);\n    A = A(1:5, 2:6) * 1.8144;\n\n  elseif (n == 21)\n    ## Wilkinson (1965), p.308.\n    E = diag (ones (n-1, 1), 1);\n    m = (n-1)/2;\n    A = diag (abs (-m:m)) + E + E';\n\n  else\n    error (\"gallery: unknown N '%d' for wilk matrix\", n);\n  endif\n\nendfunction\n\n## NOTE: bandred is part of the Test Matrix Toolbox and is used by randsvd()\nfunction A = bandred (A, kl, ku)\n\n  ## BANDRED  Band reduction by two-sided unitary transformations.\n  ##   B = BANDRED(A, KL, KU) is a matrix unitarily equivalent to A\n  ##   with lower bandwidth KL and upper bandwidth KU\n  ##   (i.e. B(i,j) = 0 if i > j+KL or j > i+KU).\n  ##   The reduction is performed using Householder transformations.\n  ##   If KU is omitted it defaults to KL.\n  ##\n  ##   Called by RANDSVD.\n  ##   This is a 'standard' reduction.  Cf. reduction to bidiagonal form\n  ##   prior to computing the SVD.  This code is a little wasteful in that\n  ##   it computes certain elements which are immediately set to zero!\n  ##\n  ##   Reference:\n  ##   G.H. Golub and C.F. Van Loan, Matrix Computations, second edition,\n  ##   Johns Hopkins University Press, Baltimore, Maryland, 1989.\n  ##   Section 5.4.3.\n\n  ##  Check for special case where order of left/right transformations matters.\n  ##  Easiest approach is to work on the transpose, flipping back at the end.\n  flip = false;\n  if (ku == 0)\n    flip = true;\n    A = A';\n    [ku, kl] = deal (kl, ku);\n  endif\n\n  [m, n] = size (A);\n\n  for j = 1:min (min (m, n), max (m-kl-1, n-ku-1))\n    if (j+kl+1 <= m)\n      [v, beta] = house (A(j+kl:m,j));\n      temp = A(j+kl:m,j:n);\n      A(j+kl:m,j:n) = temp - beta*v*(v'*temp);\n      A(j+kl+1:m,j) = zeros (m-j-kl, 1);\n    endif\n\n    if (j+ku+1 <= n)\n      [v, beta] = house (A(j,j+ku:n)');\n      temp = A(j:m,j+ku:n);\n      A(j:m,j+ku:n) = temp - beta*(temp*v)*v';\n      A(j,j+ku+1:n) = zeros (1, n-j-ku);\n    endif\n  endfor\n\n  if (flip)\n    A = A';\n  endif\n\nendfunction\n\n## NOTE: qmult is part of the Test Matrix Toolbox and is used by randsvd()\nfunction B = qmult (A)\n\n  ## QMULT  Pre-multiply by random orthogonal matrix.\n  ##   QMULT(A) is Q*A where Q is a random real orthogonal matrix from\n  ##   the Haar distribution, of dimension the number of rows in A.\n  ##   Special case: if A is a scalar then QMULT(A) is the same as\n  ##   QMULT(EYE(A)).\n  ##\n  ##   Called by RANDSVD.\n  ##\n  ## Reference:\n  ##   G.W. Stewart, The efficient generation of random\n  ##   orthogonal matrices with an application to condition estimators,\n  ##   SIAM J. Numer. Anal., 17 (1980), 403-409.\n\n  [n, m] = size (A);\n\n  ##  Handle scalar A\n  if (isscalar (A))\n    n = A;\n    A = eye (n);\n  endif\n\n  d = zeros (n);\n\n  for k = n-1:-1:1\n    ## Generate random Householder transformation.\n    x = randn (n-k+1, 1);\n    s = norm (x);\n    sgn = sign (x(1)) + (x(1) == 0); # Modification for sign(1)=1.\n    s = sgn*s;\n    d(k) = -sgn;\n    x(1) = x(1) + s;\n    beta = s*x(1);\n\n    ## Apply the transformation to A.\n    y = x'*A(k:n,:);\n    A(k:n,:) = A(k:n,:) - x*(y/beta);\n  endfor\n\n  ## Tidy up signs\n  for i = 1:n-1\n    A(i,:) = d(i)*A(i,:);\n  endfor\n  A(n,:) = A(n,:) * sign (randn);\n  B = A;\n\nendfunction\n\n\n## BIST testing for just a few functions to verify that the main gallery\n## dispatch function works.\n%!assert (gallery (\"clement\", 3), [0 1 0; 2 0 2; 0 1 0])\n%!assert (gallery (\"invhess\", 2), [1 -1; 1 2])\n\n## Test input validation of main dispatch function only\n%!error <Invalid call> gallery ()\n%!error <NAME must be a string> gallery (123)\n%!error <matrix binomial not implemented> gallery (\"binomial\")\n%!error <unknown matrix with NAME foobar> gallery (\"foobar\")\n\n## BIST testing for individual gallery functions\n%!assert (gallery (\"minij\", 4), [1 1 1 1; 1 2 2 2; 1 2 3 3; 1 2 3 4])\n%!assert (gallery (\"minij\", 1), 1)\n%!assert (gallery (\"minij\", 0), [])\n%!assert (gallery (\"minij\", -1), [])\n\n%!test\n%! exp = 1 ./ [\n%!   2  3  4  5  6\n%!   3  4  5  6  7\n%!   4  5  6  7  8\n%!   5  6  7  8  9\n%!   6  7  8  9  10];\n%! assert (gallery (\"cauchy\", 5), exp);\n%! assert (gallery (\"cauchy\", 1:5), exp);\n%! assert (gallery (\"cauchy\", 1:5, 1:5), exp);\n%!\n%! exp = 1 ./ [\n%!   1  2  3  4  5\n%!   2  3  4  5  6\n%!   3  4  5  6  7\n%!   4  5  6  7  8\n%!   5  6  7  8  9];\n%! assert (gallery (\"cauchy\", 0:4, 1:5), exp);\n%! assert (gallery (\"cauchy\", 1:5, 0:4), exp);\n%! assert (gallery (\"cauchy\", 1:5, 4:-1:0), fliplr (exp));\n%!\n%! exp = 1 ./ [\n%!  -1  0  1  2  3\n%!   0  1  2  3  4\n%!   1  2  3  4  5\n%!   2  3  4  5  6\n%!   3  4  5  6  7];\n%! assert (gallery (\"cauchy\", 1:5, -2:2), exp);\n%!\n%! exp = 1 ./ [\n%!    8  18  -4  2\n%!   13  23   1  7\n%!    9  19  -3  3\n%!   15  25   3  9];\n%! assert (gallery (\"cauchy\", [-2 3 -1 5], [10 20 -2 4]), exp);\n%! assert (gallery (\"cauchy\", [-2 3 -1 5], [10 20 -2 4]'), exp);\n%! assert (gallery (\"cauchy\", [-2 3 -1 5]', [10 20 -2 4]), exp);\n\n%!assert (size (gallery (\"chebspec\", 5)), [5 5])\n%!assert (size (gallery (\"chebspec\", 5, 1)), [5 5])\n%!assert (size (gallery (\"chebspec\", 5, 0)), [5 5])\n\n%!assert (size (gallery (\"chebvand\", 7)), [7 7])\n%!assert (size (gallery (\"chebvand\", 1:7)), [7 7])\n%!assert (size (gallery (\"chebvand\", 5, 7)), [5 7])\n\n%!assert (size (gallery (\"chow\", 5)), [5 5])\n%!assert (size (gallery (\"chow\", 5, 6)), [5 5])\n%!assert (size (gallery (\"chow\", 5, 6, 7)), [5 5])\n\n%!assert (gallery (\"circul\", 3), [1 2 3; 3 1 2; 2 3 1])\n%!assert (gallery (\"circul\", [1 3 6]), [1 3 6; 6 1 3; 3 6 1])\n\n%!assert (size (gallery (\"clement\", 5)), [5 5])\n%!assert (size (gallery (\"clement\", 5, 1)), [5 5])\n%!assert (size (gallery (\"clement\", 5, 0)), [5 5])\n\n%!assert (size (gallery (\"compar\", ones (5))), [5 5])\n%!assert (size (gallery (\"compar\", ones (5), 0)), [5 5])\n%!assert (size (gallery (\"compar\", ones (5), 1)), [5 5])\n\n%!assert (size (gallery (\"condex\", 4)), [4 4])\n%!assert (size (gallery (\"condex\", 4, 1)), [4 4])\n%!assert (size (gallery (\"condex\", 4, 1, 50)), [4 4])\n\n%!assert (size (gallery (\"cycol\", [4 5])), [4 5])\n%!assert (size (gallery (\"cycol\", [4 5], 1)), [4 5])\n%!assert (size (gallery (\"cycol\", 4)), [4 4])\n%!assert (size (gallery (\"cycol\", 4, 1)), [4 4])\n\n%!assert (size (gallery (\"dorr\", 4)), [4 4])\n%!assert (cellfun ('rows', nthargout (1:3, @gallery, \"dorr\", 4)), [3 4 3])\n\n%!assert (size (gallery (\"dramadah\", 5)), [5 5])\n%!assert (size (gallery (\"dramadah\", 5, 2)), [5 5])\n\n%!test\n%! exp = [\n%!   0   1   2   3   4\n%!   1   0   1   2   3\n%!   2   1   0   1   2\n%!   3   2   1   0   1\n%!   4   3   2   1   0];\n%! assert (gallery (\"fiedler\", 5), exp);\n%! assert (gallery (\"fiedler\", 1:5), exp);\n%! assert (gallery (\"fiedler\", -2:2), exp);\n%! assert (gallery (\"fiedler\", 2:5), exp (1:4,1:4));\n\n%!assert (size (gallery (\"forsythe\", 5)), [5 5])\n%!assert (size (gallery (\"forsythe\", 5, 1, 0.5)), [5 5])\n%!assert (size (gallery (\"forsythe\", 5, 4, 7)), [5 5])\n\n%!assert (size (gallery (\"frank\", 5)), [5 5])\n%!assert (size (gallery (\"frank\", 5, 1)), [5 5])\n\n%!assert (size (gallery (\"gcdmat\", 5)), [5 5])\n\n%!assert (size (gallery (\"gearmat\", 5)), [5 5])\n%!assert (size (gallery (\"gearmat\", 5, 4)), [5 5])\n%!assert (size (gallery (\"gearmat\", 5, 4, 3)), [5 5])\n\n%!assert (size (gallery (\"grcar\", 5)), [5 5])\n%!assert (size (gallery (\"grcar\", 5, 2)), [5 5])\n\n%!error <N must be even> gallery (\"hanowa\", 5)\n%!assert (size (gallery (\"hanowa\", 6, 5)), [6 6])\n%!assert (size (gallery (\"hanowa\", 6, 5)), [6 6])\n\n%!assert (size (gallery (\"house\", [1:5]')), [5 1])\n%!assert (cellfun ('rows', nthargout (1:2, @gallery, \"house\", [1:5]')), [5 1])\n\n%!assert (size (gallery (\"integerdata\", 5, [3 2], 5)), [3 2])\n%!assert (size (gallery (\"integerdata\", 5, [3 2 6], 5)), [3 2 6])\n\n%!assert (size (gallery (\"invhess\", 1:4, 1:3)), [4 4])\n\n%!assert (size (gallery (\"invol\", 4)), [4 4])\n\n%!assert (size (gallery (\"ipjfact\", 4)), [4 4])\n%!assert (size (gallery (\"ipjfact\", 4, 0)), [4 4])\n%!assert (size (gallery (\"ipjfact\", 4, 1)), [4 4])\n\n%!assert (size (gallery (\"jordbloc\", 4)), [4 4])\n%!assert (size (gallery (\"jordbloc\", 4, 1)), [4 4])\n%!assert (size (gallery (\"jordbloc\", 4, 3)), [4 4])\n\n%!assert (size (gallery (\"kahan\", 4)), [4 4])\n%!assert (size (gallery (\"kahan\", [4 5])), [4 5])\n%!assert (size (gallery (\"kahan\", [4 5], 1)), [4 5])\n%!assert (size (gallery (\"kahan\", [4 5], 1, 30)), [4 5])\n\n%!assert (size (gallery (\"kms\", 5)), [5 5])\n%!assert (size (gallery (\"kms\", 5, 0.2)), [5 5])\n\n%!assert (size (gallery (\"krylov\", 4)), [4 4])\n%!assert (size (gallery (\"krylov\", ones (4))), [4 4])\n%!assert (size (gallery (\"krylov\", ones (4), [.2 .3 .4 .5], 3)), [4 3])\n\n%!assert (size (gallery (\"lauchli\", 5)), [6 5])\n%!assert (size (gallery (\"lauchli\", 5, 3)), [6 5])\n\n%!assert (size (gallery (\"lehmer\", 5)), [5 5])\n\n%!assert (size (gallery (\"lesp\", 5)), [5 5])\n\n%!assert (size (gallery (\"lotkin\", 5)), [5 5])\n\n%!assert (size (gallery (\"minij\", 5)), [5 5])\n\n%!assert (size (gallery (\"moler\", 5)), [5 5])\n%!assert (size (gallery (\"moler\", 5, 0.2)), [5 5])\n\n%!assert (size (gallery (\"neumann\", 4)), [4 4])\n\n%!assert (size (gallery (\"normaldata\", [5 4 6], 3)), [5 4 6])\n\n%!assert (size (gallery (\"orthog\", 5)), [5 5])\n%!assert (size (gallery (\"orthog\", 5, 2)), [5 5])\n%!assert (size (gallery (\"orthog\", 5, -2)), [5 5])\n\n%!assert (size (gallery (\"parter\", 5)), [5 5])\n\n%!assert (size (gallery (\"pei\", 5)), [5 5])\n%!assert (size (gallery (\"pei\", 5, 4)), [5 5])\n\n%!assert (size (gallery (\"poisson\", 1)), [1 1])\n%!assert (size (gallery (\"poisson\", 4)), [16 16])\n%!assert (size (gallery (\"poisson\", 5)), [25 25])\n\n%!assert (size (gallery (\"prolate\", 5)), [5 5])\n%!assert (size (gallery (\"prolate\", 5, 0.5)), [5 5])\n\n%!assert (size (gallery (\"randhess\", 5)), [5 5])\n%!assert (size (gallery (\"randhess\", 2:5)), [4 4])\n\n%!assert (size (gallery (\"rando\", 5)), [5 5])\n%!assert (size (gallery (\"rando\", 5, 2)), [5 5])\n\n%!assert (size (gallery (\"randsvd\", 5)), [5 5])\n%!assert (size (gallery (\"randsvd\", [5 3])), [5 3])\n\n%!assert (size (gallery (\"redheff\", 5)), [5 5])\n%!assert (size (gallery (\"riemann\", 5)), [5 5])\n%!assert (size (gallery (\"ris\", 5)), [5 5])\n\n%!assert (size (gallery (\"smoke\", 5)), [5 5])\n%!assert (size (gallery (\"smoke\", 5, 1)), [5 5])\n%!assert (gallery (\"smoke\", 5, 1)(5, 1), 0)\n\n%!assert (size (gallery (\"toeppd\", 5)), [5 5])\n\n%!assert (size (gallery (\"toeppen\", 5)), [5 5])\n\n%!assert (size (gallery (\"tridiag\", 5)), [5 5])\n%!assert (size (gallery (\"tridiag\", 1:4, 1:5, 1:4)), [5 5])\n%!assert (gallery (\"tridiag\", 5), gallery (\"tridiag\", 5, -1, 2, -1))\n\n%!assert (size (gallery (\"triw\", 5)), [5 5])\n\n%!assert (size (gallery (\"uniformdata\", [5 3 4], 3)), [5 3 4])\n\n%!assert (size (gallery (\"wathen\", 2, 3)), [29 29])\n\n%!assert (cellfun ('rows', nthargout (1:2, @gallery, \"wilk\", 3)), [3 3])\n%!assert (cellfun ('rows', nthargout (1:2, @gallery, \"wilk\", 4)), [4 4])\n%!assert (size (gallery (\"wilk\", 5)), [5 5])\n%!assert (size (gallery (\"wilk\", 21)), [21 21])\n"
  },
  {
    "path": "scripts/special-matrix/hadamard.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n##\n## Original version by Paul Kienzle distributed as free software in the\n## public domain.\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} hadamard (@var{n})\n## Construct a Hadamard matrix (@nospell{Hn}) of size @var{n}-by-@var{n}.\n##\n## The size @var{n} must be of the form @math{2^k * p} in which p is one of\n## 1, 12, 20 or 28.  The returned matrix is normalized, meaning\n## @w{@code{Hn(:,1) == 1}}@ and @w{@code{Hn(1,:) == 1}}.\n##\n## Some of the properties of Hadamard matrices are:\n##\n## @itemize @bullet\n## @item\n## @code{kron (Hm, Hn)} is a Hadamard matrix of size @var{m}-by-@var{n}.\n##\n## @item\n## @code{Hn * Hn' = @var{n} * eye (@var{n})}.\n##\n## @item\n## The rows of @nospell{Hn} are orthogonal.\n##\n## @item\n## @code{det (@var{A}) <= abs (det (Hn))} for all @var{A} with\n## @w{@code{abs (@var{A}(i, j)) <= 1}}.\n##\n## @item\n## Multiplying any row or column by -1 and the matrix will remain a Hadamard\n## matrix.\n## @end itemize\n## @seealso{compan, hankel, toeplitz}\n## @end deftypefn\n\n## Reference [1] contains a list of Hadamard matrices up to n=256.\n## See code for h28 in hadamard.m for an example of how to extend\n## this function for additional p.\n##\n## Reference:\n## [1] N. J. A. Sloane, \"A Library of Hadamard Matrices\",\n##     http://www.research.att.com/~njas/hadamard/\n\nfunction h = hadamard (n)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Find k if n = 2^k*p.\n  k = 0;\n  while (n > 1 && fix (n/2) == n/2)\n    k += 1;\n    n /= 2;\n  endwhile\n\n  ## Find base hadamard.\n  ## Except for n=2^k, need a multiple of 4.\n  if (n != 1)\n    k -= 2;\n  endif\n\n  ## Trigger error if not a multiple of 4.\n  if (k < 0)\n    n =- 1;\n  endif\n\n  switch (n)\n    case 1\n      h = 1;\n    case 3\n      h = h12 ();\n    case 5\n      h = h20 ();\n    case 7\n      h = h28 ();\n    otherwise\n      error (\"hadamard: N must be 2^k*p, for p = 1, 12, 20 or 28\");\n  endswitch\n\n  ## Build H(2^k*n) from kron(H(2^k),H(n)).\n  h2 = [1,1;1,-1];\n  while (true)\n    if (fix (k/2) != k/2)\n      h = kron (h2, h);\n    endif\n    k = fix (k/2);\n    if (k == 0)\n      break;\n    endif\n    h2 = kron (h2, h2);\n  endwhile\n\nendfunction\n\nfunction h = h12 ()\n  tu = [-1,+1,-1,+1,+1,+1,-1,-1,-1,+1,-1];\n  tl = [-1,-1,+1,-1,-1,-1,+1,+1,+1,-1,+1];\n  ## Note: assert (tu(2:end), tl(end:-1:2)).\n  h = ones (12);\n  h(2:end,2:end) = toeplitz (tu, tl);\nendfunction\n\nfunction h = h20 ()\n  tu = [+1,-1,-1,+1,+1,+1,+1,-1,+1,-1,+1,-1,-1,-1,-1,+1,+1,-1,-1];\n  tl = [+1,-1,-1,+1,+1,-1,-1,-1,-1,+1,-1,+1,-1,+1,+1,+1,+1,-1,-1];\n  ## Note: assert (tu(2:end), tl(end:-1:2)).\n  h = ones (20);\n  h(2:end,2:end) = fliplr (toeplitz (tu, tl));\nendfunction\n\nfunction h = h28 ()\n\n  ## Williamson matrix construction from\n  ## http://www.research.att.com/~njas/hadamard/had.28.will.txt\n  ## Normalized so that each row and column starts with +1\n  h = [1 1  1  1  1  1  1  1  1 1  1  1  1 1 1 1 1 1  1 1 1 1 1  1 1  1 1  1\n       1 1 -1 -1 -1 -1 -1 -1 -1 1 -1 -1 -1 1 1 1 1 1 -1 1 1 1 1 -1 1 -1 1 -1\n       1 -1 1 -1 -1 -1 -1 1 -1 1 1 -1 -1 1 -1 -1 -1 -1 1 1 -1 1 -1 1 1 1 1 1\n       1 -1 -1 1 -1 -1 -1 1 1 1 1 1 -1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 1 -1 1\n       1 -1 -1 -1 1 -1 -1 1 1 -1 1 1 1 1 1 -1 -1 -1 1 1 1 -1 1 -1 1 -1 -1 -1\n       1 -1 -1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 -1 -1 1 1 -1 -1 -1 1 1 1 1 1 1 -1\n       1 -1 -1 -1 -1 -1 1 -1 1 -1 -1 -1 1 -1 1 1 1 -1 1 1 1 1 -1 1 -1 1 -1 1\n       1 -1 1 1 1 1 -1 -1 1 -1 -1 -1 -1 1 1 1 -1 -1 -1 -1 1 -1 -1 1 1 1 1 -1\n       1 -1 -1 1 1 1 1 1 -1 -1 -1 -1 -1 1 -1 -1 -1 1 -1 1 1 1 1 -1 -1 1 -1 1\n       1 1 1 1 -1 -1 -1 -1 -1 -1 1 1 1 -1 1 -1 -1 -1 -1 -1 1 1 1 -1 -1 1 1 1\n       1 -1 1 1 1 -1 -1 -1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 1 1 -1 -1 1 1 -1 -1 1\n       1 -1 -1 1 1 1 -1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 1 1 -1 -1 1 -1 -1 1 1 -1\n       1 -1 -1 -1 1 1 1 -1 -1 1 1 1 -1 -1 1 1 -1 -1 -1 -1 -1 1 1 1 1 -1 -1 1\n       1 1 1 1 1 -1 -1 1 1 -1 -1 -1 -1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 1 -1 -1 1\n       1 1 -1 1 1 -1 1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 -1 1 -1 1 -1 1 -1 -1 1 -1\n       1 1 -1 1 -1 -1 1 -1 1 1 1 -1 -1 -1 -1 -1 -1 1 1 -1 1 -1 1 1 1 1 -1 -1\n       1 1 -1 1 -1 1 1 1 1 1 -1 -1 1 -1 1 -1 -1 -1 -1 1 -1 -1 -1 -1 1 -1 1 1\n       1 1 -1 1 -1 1 -1 1 -1 1 -1 1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 -1 -1\n       1 -1 1 -1 1 -1 1 1 1 1 1 -1 1 -1 -1 1 -1 1 -1 -1 1 1 -1 -1 -1 -1 1 -1\n       1 1 1 -1 1 -1 1 1 -1 1 -1 -1 1 1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 1 -1 -1\n       1 1 -1 -1 1 -1 1 -1 -1 -1 -1 1 1 1 -1 1 -1 1 1 -1 -1 -1 -1 -1 1 1 1 1\n       1 1 1 -1 -1 1 1 1 -1 -1 1 1 -1 -1 -1 1 1 -1 -1 1 1 -1 -1 -1 1 1 -1 -1\n       1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 -1 -1 1 -1 1 1 1 -1 1 -1 -1 1 -1 -1 1 1\n       1 -1 1 -1 -1 1 1 -1 1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 -1 -1 -1 1 1\n       1 1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 -1 1 1 1 -1 1 -1 -1 -1 1 -1 -1\n       1 -1 1 1 -1 1 1 -1 -1 -1 1 -1 1 1 1 -1 1 1 1 -1 -1 1 -1 -1 1 -1 -1 -1\n       1 1 1 -1 -1 1 -1 -1 1 -1 1 -1 1 1 -1 1 -1 1 -1 1 -1 -1 1 1 -1 -1 -1 1\n       1 -1 1 1 -1 -1 1 1 -1 -1 -1 1 -1 -1 1 1 -1 1 1 1 -1 -1 1 1 -1 -1 1 -1];\n\nendfunction\n\n\n%!assert (hadamard (1), 1)\n%!assert (hadamard (2), [1,1;1,-1])\n%!test\n%! for n = [1,2,4,8,12,24,48,20,28,2^9]\n%!   h = hadamard (n);\n%!   assert (norm (h*h' - n*eye (n)), 0);\n%! endfor\n\n%!error <Invalid call> hadamard ()\n%!error hadamard (1,2)\n%!error <N must be 2\\^k\\*p> hadamard (5)\n"
  },
  {
    "path": "scripts/special-matrix/hankel.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{h} =} hankel (@var{c})\n## @deftypefnx {} {@var{h} =} hankel (@var{c}, @var{r})\n## Return the Hankel matrix constructed from the first column @var{c}, and\n## (optionally) the last row @var{r}.\n##\n## If the last element of @var{c} is not the same as the first element of\n## @var{r}, the last element of @var{c} is used.  If the second argument is\n## omitted, it is assumed to be a vector of zeros with the same size as\n## @var{c}.\n##\n## A Hankel matrix formed from an m-vector @var{c}, and an n-vector @var{r},\n## has the elements\n## @tex\n## $$\n## H(i, j) = \\cases{c_{i+j-1},&$i+j-1\\le m$;\\cr r_{i+j-m},&otherwise.\\cr}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## H(i,j) = c(i+j-1),  i+j-1 <= m;\n## H(i,j) = r(i+j-m),  otherwise\n## @end group\n## @end example\n##\n## @end ifnottex\n## @seealso{hadamard, toeplitz}\n## @end deftypefn\n\nfunction h = hankel (c, r)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n\n    if (! isvector (c))\n      error (\"hankel: C must be a vector\");\n    endif\n\n    nr = length (c);\n    nc = nr;\n    data = [c(:) ; zeros(nr, 1)];\n\n  else\n\n    if (! (isvector (c) && isvector (r)))\n      error (\"hankel: C and R must be vectors\");\n    elseif (r(1) != c(end))\n      warning (\"hankel: column wins anti-diagonal conflict\");\n    endif\n\n    nr = length (c);\n    nc = length (r);\n    data = [c(:) ; r(2:end)(:)];\n\n  endif\n\n  slices = cellslices (data, 1:nc, nr:1:nc+nr-1);\n  h = horzcat (slices{:});\n\nendfunction\n\n\n%!assert (hankel (1), [1])\n%!assert (hankel ([1, 2]), [1, 2; 2, 0])\n%!assert (hankel ([1, 2], [2; -1; -3]), [1, 2, -1; 2, -1, -3])\n%!assert (hankel (1:3), [1,2,3;2,3,0;3,0,0])\n%!assert (hankel (1:3,3:6), [1,2,3,4;2,3,4,5;3,4,5,6])\n%!assert (hankel (1:3,3:4), [1,2;2,3;3,4])\n%!warning <column wins anti-diagonal conflict>\n%!  assert (hankel (1:3,4:6), [1,2,3;2,3,5;3,5,6]);\n\n%!error <Invalid call> hankel ()\n%!error <C must be a vector> hankel ([1, 2; 3, 4])\n%!error <C and R must be vectors> hankel (1:4, [1, 2; 3, 4])\n"
  },
  {
    "path": "scripts/special-matrix/hilb.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{h} =} hilb (@var{n})\n## Return the Hilbert matrix of order @var{n}.\n##\n## The @math{i,j} element of a Hilbert matrix is defined as\n## @tex\n## $$\n## H(i, j) = {1 \\over (i + j - 1)}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## H(i, j) = 1 / (i + j - 1)\n## @end example\n##\n## @end ifnottex\n##\n## Hilbert matrices are close to being singular which make them difficult to\n## invert with numerical routines.  Comparing the condition number of a random\n## matrix 5x5 matrix with that of a Hilbert matrix of order 5 reveals just how\n## difficult the problem is.\n##\n## @example\n## @group\n## cond (rand (5))\n##    @xresult{} 14.392\n## cond (hilb (5))\n##    @xresult{} 4.7661e+05\n## @end group\n## @end example\n##\n## @seealso{invhilb}\n## @end deftypefn\n\nfunction h = hilb (n)\n\n  if (nargin != 1)\n    print_usage ();\n  elseif (! isscalar (n))\n    error (\"hilb: N must be a scalar integer\");\n  endif\n\n  ## Very elegant solution by N. Higham\n  ## https://nhigham.com/2020/06/30/what-is-the-hilbert-matrix/\n  j = 1:n;\n  h = 1 ./ (j' + j - 1);\n\nendfunction\n\n\n%!assert (hilb (2), [1, 1/2; 1/2, 1/3])\n%!assert (hilb (3), [1, 1/2, 1/3; 1/2, 1/3, 1/4; 1/3, 1/4, 1/5])\n\n%!error <Invalid call> hilb ()\n%!error <N must be a scalar integer> hilb (ones (2))\n"
  },
  {
    "path": "scripts/special-matrix/invhilb.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{hinv} =} invhilb (@var{n})\n## Return the inverse of the Hilbert matrix of order @var{n}.\n##\n## This can be computed exactly using\n## @tex\n## $$\\eqalign{\n##   A_{ij} &= -1^{i+j} (i+j-1)\n##              \\left( \\matrix{n+i-1 \\cr n-j } \\right)\n##              \\left( \\matrix{n+j-1 \\cr n-i } \\right)\n##              \\left( \\matrix{i+j-2 \\cr i-2 } \\right)^2 \\cr\n##          &= { p(i)p(j) \\over (i+j-1) }\n## }$$\n## where\n## $$\n##   p(k) = -1^k \\left( \\matrix{ k+n-1 \\cr k-1 } \\right)\n##               \\left( \\matrix{ n \\cr k } \\right)\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##\n##            (i+j)         /n+i-1\\  /n+j-1\\   /i+j-2\\ 2\n## A(i,j) = -1      (i+j-1)(       )(       ) (       )\n##                          \\ n-j /  \\ n-i /   \\ i-2 /\n##\n##        = p(i) p(j) / (i+j-1)\n##\n## @end group\n## @end example\n##\n## @noindent\n## where\n##\n## @example\n## @group\n##          k  /k+n-1\\   /n\\\n## p(k) = -1  (       ) (   )\n##             \\ k-1 /   \\k/\n## @end group\n## @end example\n##\n## @end ifnottex\n## The validity of this formula can easily be checked by expanding the binomial\n## coefficients in both formulas as factorials.  It can be derived more\n## directly via the theory of Cauchy matrices.  See @nospell{J. W. Demmel},\n## @cite{Applied Numerical Linear Algebra}, @w{p.@: 92}.\n##\n## Compare this with the numerical calculation of @code{inv (hilb (n))}, which\n## suffers from the ill-conditioning of the Hilbert matrix, and the finite\n## precision of your computer's floating point arithmetic.\n## @seealso{hilb}\n## @end deftypefn\n\nfunction hinv = invhilb (n)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! isscalar (n))\n    error (\"invhilb: N must be a scalar integer\");\n  endif\n\n  ## The point about the second formula above is that when vectorized,\n  ## p(k) is evaluated for k=1:n which involves O(n) calls to bincoeff\n  ## instead of O(n^2).\n  ##\n  ## We evaluate the expression as (-1)^(i+j)*(p(i)*p(j))/(i+j-1) except\n  ## when p(i)*p(j) would overflow.  In cases where p(i)*p(j) is an exact\n  ## machine number, the result is also exact.  Otherwise we calculate\n  ## (-1)^(i+j)*p(i)*(p(j)/(i+j-1)).\n  ##\n  ## The Octave bincoeff routine uses transcendental functions (gammaln\n  ## and exp) rather than multiplications, for the sake of speed.\n  ## However, it rounds the answer to the nearest integer, which\n  ## justifies the claim about exactness made above.\n\n  hinv = zeros (n);\n  k = [1:n];\n  p = k .* bincoeff (k+n-1, k-1) .* bincoeff (n, k);\n  p(2:2:n) = -p(2:2:n);\n  if (n < 203)\n    for l = 1:n\n      hinv(l,:) = (p(l) * p) ./ [l:l+n-1];\n    endfor\n  else\n    for l = 1:n\n      hinv(l,:) = p(l) * (p ./ [l:l+n-1]);\n    endfor\n  endif\n\nendfunction\n\n\n%!assert (invhilb (1), 1)\n%!assert (invhilb (2), [4, -6; -6, 12])\n%!test\n%! result4 = [16  , -120 , 240  , -140;\n%!            -120, 1200 , -2700, 1680;\n%!            240 , -2700, 6480 , -4200;\n%!            -140, 1680 , -4200, 2800];\n%! assert (invhilb (4), result4);\n%!assert (invhilb (7) * hilb (7), eye (7), sqrt (eps))\n\n%!error <Invalid call> invhilb ()\n%!error <N must be a scalar integer> invhilb ([1, 2])\n"
  },
  {
    "path": "scripts/special-matrix/magic.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{M} =} magic (@var{n})\n##\n## Create an @var{n}-by-@var{n} magic square.\n##\n## A magic square is an arrangement of the integers @code{1:n^2} such that the\n## row sums, column sums, and diagonal sums are all equal to the same value.\n##\n## Note: @var{n} must be a scalar greater than or equal to 3.  If you supply\n## @var{n} less than 3, magic returns either a nonmagic square, or else the\n## degenerate magic squares 1 and [].\n## @end deftypefn\n\nfunction M = magic (n)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  n = fix (n);\n  if (n < 0)\n    error (\"magic: N must be non-negative\");\n  elseif (n < 1)\n    M = [];\n  elseif (mod (n, 2) == 1)\n\n    shift = floor ((0:n*n-1)/n);\n    c = mod ([1:n*n] - shift + (n-3)/2, n);\n    r = mod ([n*n:-1:1] + 2*shift, n);\n    M(c*n+r+1) = 1:n*n;\n    M = reshape (M, n, n);\n\n  elseif (mod (n, 4) == 0)\n\n    M = reshape (1:n*n, n, n)';\n    I = [1:4:n, 4:4:n];\n    J = fliplr (I);\n    M(I,I) = M(J,J);\n    I = [2:4:n, 3:4:n];\n    J = fliplr (I);\n    M(I,I) = M(J,J);\n\n  elseif (mod (n, 4) == 2)\n\n    m = n/2;\n    M = magic (m);\n    M = [M, M+2*m*m; M+3*m*m, M+m*m];\n    k = (m-1)/2;\n    if (k > 1)\n      I = 1:m;\n      J = [2:k, n-k+2:n];\n      M([I,I+m],J) = M([I+m,I],J);\n    endif\n    I = [1:k, k+2:m];\n    M([I,I+m],1) = M([I+m,I],1);\n    I = k + 1;\n    M([I,I+m],I) = M([I+m,I],I);\n\n  endif\n\nendfunction\n\n\n%!test\n%! for i = 3:30\n%!   A = magic (i);\n%!   assert (norm(diff([sum(diag(A)),sum(diag(flipud(A))),sum(A),sum(A')])),0);\n%! endfor\n\n## Not a magic square but we must return something (bug #46672).\n## While one day we may change the actual return of magic (2),\n## this properties still must be true.\n%!test <*46672>\n%! m = magic (2);\n%! assert (size (m), [2 2]);\n%! assert (m, [4 3; 1 2]);\n\n%!assert (isempty (magic (0)))\n%!assert (magic (1), 1)\n%!assert (magic (1.5), 1)\n\n## Test input validation\n%!error <Invalid call> magic ()\n%!error <N must be non-negative> magic (-5)\n"
  },
  {
    "path": "scripts/special-matrix/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/gallery.m \\\n  %reldir%/hadamard.m \\\n  %reldir%/hankel.m \\\n  %reldir%/hilb.m \\\n  %reldir%/invhilb.m \\\n  %reldir%/magic.m \\\n  %reldir%/pascal.m \\\n  %reldir%/rosser.m \\\n  %reldir%/toeplitz.m \\\n  %reldir%/vander.m \\\n  %reldir%/wilkinson.m\n\n%canon_reldir%dir = $(fcnfiledir)/special-matrix\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/special-matrix/pascal.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{P} =} pascal (@var{n})\n## @deftypefnx {} {@var{P} =} pascal (@var{n}, @var{t})\n## Return the Pascal matrix of order @var{n} if @code{@var{t} = 0}.\n##\n## The default value of @var{t} is 0.\n##\n## When @code{@var{t} = 1}, return the pseudo-lower triangular\n## Cholesky@tie{}factor of the Pascal matrix (The sign of some columns may be\n## negative).  This matrix is its own inverse, that is\n## @code{pascal (@var{n}, 1) ^ 2 == eye (@var{n})}.\n##\n## If @code{@var{t} = -1}, return the true Cholesky@tie{}factor with strictly\n## positive values on the diagonal.\n##\n## If @code{@var{t} = 2}, return a transposed and permuted version of\n## @code{pascal (@var{n}, 1)}, which is the cube root of the identity matrix.\n## That is, @code{pascal (@var{n}, 2) ^ 3 == eye (@var{n})}.\n##\n## @seealso{chol}\n## @end deftypefn\n\nfunction P = pascal (n, t = 0)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! (isscalar (n) && isscalar (t)))\n    error (\"pascal: N and T must be scalars\");\n  elseif (! any (t == [-1, 0, 1, 2]))\n    error (\"pascal: T must be -1, 0, 1, or 2, found %d\", t);\n  endif\n\n  P = zeros (n);\n  if (n > 0)\n    P(:,1) = 1;\n  endif\n\n  if (t == -1)\n    for j = 2:n\n      P(j:n,j) = cumsum (P(j-1:n-1,j-1));\n    endfor\n  else\n    for j = 2:n\n      P(j:n,j) = -cumsum (P(j-1:n-1,j-1));\n    endfor\n  endif\n\n  if (t == 0)\n    P = P*P';\n  elseif (t == 2)\n    P = rot90 (P, 3);\n    if (rem (n,2) != 1)\n      P *= -1;\n    endif\n  endif\n\nendfunction\n\n\n%!assert (pascal (3,-1), [1,0,0;1,1,0;1,2,1])\n%!assert (pascal (3,0), [1,1,1;1,2,3;1,3,6])\n%!assert (pascal (3,0), pascal (3))\n%!assert (pascal (3,1), [1,0,0;1,-1,0;1,-2,1])\n%!assert (pascal (3,2), [1,1,1;-2,-1,0;1,0,0])\n%!assert (pascal (0,2), [])\n\n## Test input validation\n%!error <Invalid call> pascal ()\n%!error <N and T must be scalars> pascal ([1 2])\n%!error <N and T must be scalars> pascal (1, [1 2])\n%!error <T must be -1> pascal (3,-2)\n%!error <T must be .* or 2> pascal (3,4)\n"
  },
  {
    "path": "scripts/special-matrix/rosser.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{R} =} rosser ()\n## Return the @nospell{Rosser} matrix.\n##\n## This is a difficult test case used to evaluate eigenvalue algorithms.\n## @seealso{wilkinson, eig}\n## @end deftypefn\n\nfunction R = rosser ()\n\n  R = [611,   196,  -192,   407,    -8,   -52,   -49,    29;\n       196,   899,   113,  -192,   -71,   -43,    -8,   -44;\n      -192,   113,   899,   196,    61,    49,     8,    52;\n       407,  -192,   196,   611,     8,    44,    59,   -23;\n        -8,   -71,    61,     8,   411,  -599,   208,   208;\n       -52,   -43,    49,    44,  -599,   411,   208,   208;\n       -49,    -8,     8,    59,   208,   208,    99,  -911;\n        29,   -44,    52,   -23,   208,   208,  -911,    99];\n\nendfunction\n\n\n%!assert (size (rosser ()), [8,8])\n%!assert (rosser ()([1, end]), [611, 99])\n\n%!error rosser (1)\n"
  },
  {
    "path": "scripts/special-matrix/toeplitz.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{T} =} toeplitz (@var{c})\n## @deftypefnx {} {@var{T} =} toeplitz (@var{c}, @var{r})\n## Return the Toeplitz matrix constructed from the first column @var{c},\n## and optionally the first row @var{r}.\n##\n## If the second argument is omitted, the first row is taken to be the\n## same as the first column.  If the first element of @var{r} is not the same\n## as the first element of @var{c}, the first element of @var{c} is used.\n##\n## A Toeplitz, or diagonal-constant, matrix has the same value along each\n## diagonal.  Although it need not be square, it often is.  An @nospell{MxN}\n## Toeplitz matrix has the form:\n## @tex\n## $$\n## \\left[\\matrix{c_1    & r_2     & r_3      & \\cdots & r_n\\cr\n##               c_2    & c_1     & r_2      & \\cdots & r_{n-1}\\cr\n##               c_3    & c_2     & c_1      & \\cdots & r_{n-2}\\cr\n##               \\vdots & \\vdots  & \\vdots   & \\ddots & \\vdots\\cr\n##               c_m    & c_{m-1} & c_{m-2} & \\ldots & c{m-n+1}}\\right]\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## c(1)  r(2)   r(3)  @dots{}  r(n)\n## c(2)  c(1)   r(2)  @dots{} r(n-1)\n## c(3)  c(2)   c(1)  @dots{} r(n-2)\n##  .     .      .   .      .\n##  .     .      .     .    .\n##  .     .      .       .  .\n## c(m) c(m-1) c(m-2) @dots{} c(m-n+1)\n## @end group\n## @end example\n##\n## @end ifnottex\n## @seealso{hankel}\n## @end deftypefn\n\nfunction T = toeplitz (c, r)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin == 1)\n    if (! isvector (c))\n      error (\"toeplitz: C must be a vector\");\n    endif\n\n    r = c;\n    nr = length (c);\n    nc = nr;\n  else\n    if (! (isvector (c) && isvector (r)))\n      error (\"toeplitz: C and R must be vectors\");\n    elseif (r(1) != c(1))\n      warning (\"toeplitz: column wins diagonal conflict\");\n    endif\n\n    nr = length (c);\n    nc = length (r);\n  endif\n\n  if (nr == 0 || nc == 0)\n    ## Empty matrix.\n    T = zeros (nr, nc, class (c));\n    return;\n  endif\n\n  ## If we have a single complex argument, we want to return a\n  ## Hermitian-symmetric matrix (actually, this will really only be\n  ## Hermitian-symmetric if the first element of the vector is real).\n  if (nargin == 1 && iscomplex (c))\n    c = conj (c);\n    c(1) = conj (c(1));\n  endif\n\n  if (issparse (c) && issparse (r))\n    c = c(:).';  # enforce row vector\n    r = r(:).';  # enforce row vector\n    cidx = find (c);\n    ridx = find (r);\n\n    ## Ignore the first element in r.\n    ridx = ridx(ridx > 1);\n\n    ## Form matrix.\n    T = spdiags (repmat (c(cidx),nr,1),1-cidx,nr,nc) + ...\n                 spdiags (repmat (r(ridx),nr,1),ridx-1,nr,nc);\n  else\n    ## Concatenate data into a single column vector.\n    data = [r(end:-1:2)(:); c(:)];\n\n    ## Get slices.\n    slices = cellslices (data, nc:-1:1, nc+nr-1:-1:nr);\n\n    ## Form matrix.\n    T = horzcat (slices{:});\n  endif\n\nendfunction\n\n\n%!assert (toeplitz (1), [1])\n%!assert (toeplitz ([1, 2, 3], [1; -3; -5]), [1, -3, -5; 2, 1, -3; 3, 2, 1])\n%!assert (toeplitz ([1, 2, 3], [1; -3i; -5i]),\n%!        [1, -3i, -5i; 2, 1, -3i; 3, 2, 1])\n\n## Test input validation\n%!error <Invalid call> toeplitz ()\n%!error <C must be a vector> toeplitz ([1, 2; 3, 4])\n%!error <C and R must be vectors> toeplitz ([1, 2; 3, 4], 1)\n%!error <C and R must be vectors> toeplitz (1, [1, 2; 3, 4])\n"
  },
  {
    "path": "scripts/special-matrix/vander.m",
    "content": "########################################################################\n##\n## Copyright (C) 1993-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{V} =} vander (@var{c})\n## @deftypefnx {} {@var{V} =} vander (@var{c}, @var{n})\n## Return the @nospell{Vandermonde} matrix whose next to last column is\n## @var{c}.\n##\n## If @var{n} is specified, it determines the number of columns; otherwise,\n## @var{n} is taken to be equal to the length of @var{c}.\n##\n## A @nospell{Vandermonde} matrix has the form:\n## @tex\n## $$\n## \\left[\\matrix{c_1^{n-1}  & \\cdots & c_1^2  & c_1    & 1      \\cr\n##               c_2^{n-1}  & \\cdots & c_2^2  & c_2    & 1      \\cr\n##               \\vdots     & \\ddots & \\vdots & \\vdots & \\vdots \\cr\n##               c_n^{n-1}  & \\cdots & c_n^2  & c_n    & 1      }\\right]\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## c(1)^(n-1) @dots{} c(1)^2  c(1)  1\n## c(2)^(n-1) @dots{} c(2)^2  c(2)  1\n##     .     .      .      .    .\n##     .       .    .      .    .\n##     .         .  .      .    .\n## c(n)^(n-1) @dots{} c(n)^2  c(n)  1\n## @end group\n## @end example\n##\n## @end ifnottex\n## @seealso{polyfit}\n## @end deftypefn\n\nfunction V = vander (c, n)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isvector (c))\n    error (\"vander: polynomial C must be a vector\");\n  endif\n\n  if (nargin == 1)\n    n = length (c);\n  elseif (! isscalar (n))\n    error (\"vander: N must be a positive scalar integer\");\n  endif\n\n  ## avoiding many ^s appears to be faster for n >= 100.\n  V = zeros (numel (c), n, class (c));\n  c = c(:);\n  d = 1;\n  for i = n:-1:1\n    V(:,i) = d;\n    d .*= c;\n  endfor\n\nendfunction\n\n\n%!test\n%! c = [0,1,2,3];\n%! expect = [0,0,0,1; 1,1,1,1; 8,4,2,1; 27,9,3,1];\n%! assert (vander (c), expect);\n\n%!assert (vander (1), 1)\n%!assert (vander ([1, 2, 3]), vander ([1; 2; 3]))\n%!assert (vander ([1, 2, 3]), [1, 1, 1; 4, 2, 1; 9, 3, 1])\n%!assert (vander ([1, 2, 3]*i), [-1, i, 1; -4, 2i, 1; -9, 3i, 1])\n\n%!assert (vander (2, 3), [4, 2, 1])\n%!assert (vander ([2, 3], 3), [4, 2, 1; 9, 3, 1])\n\n## Test input validation\n%!error <Invalid call> vander ()\n%!error <polynomial C must be a vector> vander ([1, 2; 3, 4])\n%!error <N must be a positive scalar integer> vander (1, [1, 2])\n"
  },
  {
    "path": "scripts/special-matrix/wilkinson.m",
    "content": "########################################################################\n##\n## Copyright (C) 1999-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{W} =} wilkinson (@var{n})\n## Return the Wilkinson matrix of order @var{n}.\n##\n## Wilkinson matrices are symmetric and tridiagonal with pairs of nearly, but\n## not exactly, equal eigenvalues.  They are useful in testing the behavior and\n## performance of eigenvalue solvers.\n##\n## @seealso{rosser, eig}\n## @end deftypefn\n\nfunction W = wilkinson (n)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isscalar (n) && n >= 0 && (n == fix (n))))\n    error (\"wilkinson: N must be a non-negative integer\");\n  endif\n\n  side = ones (n-1, 1);\n  center = abs (-(n-1)/2:(n-1)/2);\n  W = diag (side, -1) + diag (center) + diag (side, 1);\n\nendfunction\n\n\n%!assert (wilkinson (0), [])\n%!assert (wilkinson (1), 0)\n%!assert (wilkinson (2), [0.5,1;1,0.5])\n%!assert (wilkinson (3), [1,1,0;1,0,1;0,1,1])\n%!assert (wilkinson (4), [1.5,1,0,0;1,0.5,1,0;0,1,0.5,1;0,0,1,1.5])\n\n## Test input validation\n%!error <Invalid call> wilkinson ()\n%!error <N must be a non-negative integer> wilkinson (ones (2))\n%!error <N must be a non-negative integer> wilkinson (-1)\n%!error <N must be a non-negative integer> wilkinson (1.5)\n"
  },
  {
    "path": "scripts/startup/inputrc",
    "content": "########################################################################\n## This file configures the behavior of line-input editing for all\n## Octave users when Octave is configured to use GNU Readline library\n## for input-line editing.\n##\n## This file is NOT an Octave script.\n##\n## Do not make changes to this file unless you understand how\n## GNU Readline configuration works.\n########################################################################\n\n## history-search-backward:\n##\n##   Search backward through the history for the string of characters\n##   between the start of the current line and the point.  This is a\n##   non-incremental search.  Bound to \"\\e[A\", the ANSI escape\n##   sequence for the UP arrow.\n\n\"\\e[A\": history-search-backward\n\n## history-search-forward:\n##\n##   Search forward through the history for the string of characters\n##   between the start of the current line and the point.  This is a\n##   non-incremental search.  Bound to \"\\e[B\", the ANSI escape\n##   sequence for the DOWN arrow.\n\n\"\\e[B\": history-search-forward\n\n## Disable Ctrl+v so the usual paste shortcut will work on Windows.\n## \\C-q should still be available for quoted insert.\n\n\"\\C-v\": \"\"\n\n## On Windows, disable audible bell which is enabled by default.\n$if term=cygwin\n   set bell-style none\n$endif\n"
  },
  {
    "path": "scripts/startup/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\nSITE_STARTUP_FILE_SRC = %reldir%/site-rcfile\n\nVERSION_STARTUP_FILE_SRC = %reldir%/version-rcfile\n\nSYSTEM_INPUTRC_FILE_SRC = %reldir%/inputrc\n\nSYSTEM_PKG_LIST_FILE_SRC = %reldir%/octave_packages\n\nSTARTUP_FILE_SRC = \\\n  $(SITE_STARTUP_FILE_SRC) \\\n  $(VERSION_STARTUP_FILE_SRC) \\\n  $(SYSTEM_INPUTRC_FILE_SRC) \\\n  $(SYSTEM_PKG_LIST_FILE_SRC)\n\n%canon_reldir%dir = $(fcnfiledir)/startup\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nscripts_EXTRA_DIST += $(STARTUP_FILE_SRC)\n\ninstall-startup-files:\n\t$(MKDIR_P) $(DESTDIR)$(fcnfiledir)/startup\n\tif test -f $(DESTDIR)$(fcnfiledir)/startup/octaverc; then true; \\\n\telse \\\n\t  $(INSTALL_DATA) $(srcdir)/$(VERSION_STARTUP_FILE_SRC) \\\n\t    $(DESTDIR)$(fcnfiledir)/startup/octaverc; \\\n\tfi\n\tif test -f $(DESTDIR)$(fcnfiledir)/startup/inputrc; then true; \\\n\telse \\\n\t  $(INSTALL_DATA) $(srcdir)/$(SYSTEM_INPUTRC_FILE_SRC) \\\n\t    $(DESTDIR)$(fcnfiledir)/startup/inputrc; \\\n\tfi\n\t$(MKDIR_P) $(DESTDIR)$(localfcnfiledir)/startup\n\tif test -f $(DESTDIR)$(localfcnfiledir)/startup/octaverc; \\\n\tthen true; \\\n\telse \\\n\t  $(INSTALL_DATA) $(srcdir)/$(SITE_STARTUP_FILE_SRC) \\\n\t    $(DESTDIR)$(localfcnfiledir)/startup/octaverc; \\\n\tfi\n\t$(MKDIR_P) $(DESTDIR)$(localapipkgdir)\n\tif test -f $(DESTDIR)$(localapipkgdir)/octave_packages; \\\n\tthen true; \\\n\telse \\\n\t  $(INSTALL_DATA) $(srcdir)/$(SYSTEM_PKG_LIST_FILE_SRC) \\\n\t    $(DESTDIR)$(localapipkgdir)/octave_packages; \\\n\tfi\n.PHONY: install-startup-files\n\nuninstall-startup-files:\n\trm -f $(DESTDIR)$(fcnfiledir)/startup/octaverc\n\trm -f $(DESTDIR)$(fcnfiledir)/startup/inputrc\n\trm -f $(DESTDIR)$(localfcnfiledir)/startup/octaverc\n\trm -f $(DESTDIR)$(localapipkgdir)/octave_packages\n.PHONY: uninstall-startup-files\n"
  },
  {
    "path": "scripts/startup/octave_packages",
    "content": "## System-wide list of installed Octave packages.\n##\n## If the command \"pkg global_list FILENAME\" has been executed then FILENAME\n## will contain the list of system-wide installed packages, rather than this\n## file.\n"
  },
  {
    "path": "scripts/startup/site-rcfile",
    "content": "## System-wide startup file for Octave.\n##\n## If the environment variable OCTAVE_SITE_INITFILE is set when Octave\n## starts, then that file is executed instead of this file.\n##\n## This file contains commands that should be executed each time Octave starts\n## for every user at this site.\n\nif (ispc () && isguirunning ())\n  try\n    is_windows_console_host = ...\n      strcmp (winqueryreg (\"HKEY_CURRENT_USER\", 'Console\\%%Startup', \"DelegationConsole\"), ...\n              \"{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}\");\n  catch\n    ## The above might fail for old versions of Windows 10 where that\n    ## registry key didn't exist.  Assume that the Windows Console Host\n    ## is being used in this case.\n    is_windows_console_host = true;\n  end_try_catch\n\n  try\n    ## Windows 11 also has the 'CurrentMajorVersionNumber' set to 10.\n    windows_major_version = ...\n      winqueryreg (\"HKEY_LOCAL_MACHINE\", ...\n                   'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion', ...\n                   'CurrentMajorVersionNumber');\n  catch\n    ## Assume that this is an old version of Windows\n    windows_major_version = 9;\n  end_try_catch\n\n  ## Assume an older version of Windows 11 or 10 in case of errors below.\n  windows_build_number = 26099;\n  if (windows_major_version == 10)\n    try\n      ## Windows 11 24H2 has the build number 26100.\n      windows_build_number = ...\n        str2double (winqueryreg (\"HKEY_LOCAL_MACHINE\", ...\n                                 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion', ...\n                                 'CurrentBuild'));\n    end_try_catch\n  endif\n\n  is_working_console = is_windows_console_host ...\n    || ((windows_major_version == 10) && (windows_build_number >= 26100)) ...\n    || (windows_major_version > 10);\n\n  if (! is_working_console)\n    warn_str = [\"WARNING: You are using an incompatible Windows configuration!\\n\", ...\n                \"Microsoft's new Terminal App is not compatible with Octave.\\n\", ...\n                \"Please follow the instructions on the following page and set the \", ...\n                \"default terminal to \\\"Windows Console Host\\\":\\n\", ...\n                \"https://octave.discourse.group/t/4981/\"];\n    warning (\"octave:terminal-app\", warn_str);\n    answer = questdlg ([warn_str, \"\\n\\nWould you like to open that page in your browser?\"], ...\n                       \"Incompatible Configuration\", \"Yes\", \"No\", \"Yes\");\n    if (strcmp (answer, \"Yes\"))\n      system (\"start https://octave.discourse.group/t/4981/\");\n    endif\n    clear warn_str answer\n  endif\n\n  clear is_windows_console_host windows_major_version windows_build_number is_working_console\n\nendif\n"
  },
  {
    "path": "scripts/startup/version-rcfile",
    "content": "## System-wide startup file for Octave.\n##\n## If the environment variable OCTAVE_VERSION_INITFILE is set when Octave\n## starts, then that file is executed instead of this file.\n##\n## This file contains commands that should be executed each time Octave starts\n## for every user at this site.\n\n## Configure readline using the file inputrc in the Octave startup directory.\nreadline_read_init_file (sprintf (\"%s%s%s\",\n                                  __octave_config_info__ (\"startupfiledir\"),\n                                  filesep, \"inputrc\"));\n\n## Re-read user's personal inputrc to give precedence over Octave's default.\ninputrc = getenv (\"INPUTRC\");\nif (isempty (inputrc) && exist (\"~/.inputrc\", \"file\"))\n  inputrc = \"~/.inputrc\";\nendif\nif (! isempty (inputrc))\n  readline_read_init_file (inputrc);\nendif\nclear (\"inputrc\");\n\n## Configure LESS pager if present\nif (strcmp (PAGER (), \"less\") && isempty (getenv (\"LESS\")))\n  PAGER_FLAGS ('-e -X -P\"-- less ?pB(%pB\\\\%):--. (f)orward, (b)ack, (q)uit$\"');\nendif\n"
  },
  {
    "path": "scripts/statistics/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/statistics/bounds.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{s}, @var{l}] =} bounds (@var{x})\n## @deftypefnx {} {[@var{s}, @var{l}] =} bounds (@var{x}, @var{dim})\n## @deftypefnx {} {[@var{s}, @var{l}] =} bounds (@var{x}, @var{vecdim})\n## @deftypefnx {} {[@var{s}, @var{l}] =} bounds (@var{x}, \"all\")\n## @deftypefnx {} {[@var{s}, @var{l}] =} bounds (@dots{}, @var{nanflag})\n## Return the smallest and largest values of the input data @var{x}.\n##\n## If @var{x} is a vector, then @code{bounds (@var{x})} returns the smallest\n## and largest values of the elements in @var{x} in @var{s} and @var{l},\n## respectively.\n##\n## If @var{x} is a matrix, then @code{bounds (@var{x})} returns the smallest\n## and largest values for each column of @var{x} as row vectors @var{s} and\n## @var{l}, respectively.\n##\n## If @var{x} is an array, then @code{bounds (@var{x})} computes the smallest\n## and largest values along the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be numeric.  By default, any NaN values are\n## ignored.  The size of @var{s} and @var{l} is equal to the size of @var{x}\n## except for the operating dimension, which becomes 1.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{@var{x}}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{bounds} to\n## operate on all elements of @var{x}, and is equivalent to\n## @code{bounds (@var{x}(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"omitnan\"} which does not include NaN values in the result.  If the\n## argument @qcode{\"includenan\"} is given, and there is a NaN present, then the\n## result for both smallest (@var{s}) and largest (@var{l}) elements will be\n## NaN.\n##\n## Usage Note: The bounds are a quickly computed measure of the dispersion of a\n## data set, but are less accurate than @code{iqr} if there are outlying data\n## points.\n## @seealso{range, iqr, mad, std}\n## @end deftypefn\n\nfunction [s, l] = bounds (x, varargin)\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x)))\n    error (\"bounds: X must be a numeric array\");\n  endif\n\n  if (isempty (varargin))\n    s = min (x);\n    l = max (x);\n  else\n    s = min (x, [], varargin{:});\n    l = max (x, [], varargin{:});\n  endif\n\nendfunction\n\n\n%!test\n%! [s,l] = bounds (1:10);\n%! assert ([s,l], [1, 10]);\n%!test\n%! [s,l] = bounds ([10:-1:1]');\n%! assert ([s,l], [1, 10]);\n%!test\n%! [s,l] = bounds (single (1:10));\n%! assert ([s,l], single ([1, 10]));\n%!assert (bounds (magic (3)), [3, 1, 2])\n%!assert (bounds (magic (3), 2), [1; 3; 2])\n%!test\n%! x = magic (3);\n%! x(2,3) = NaN;\n%! assert (bounds (x), [3, 1, 2]);\n%! assert (bounds (x, \"omitnan\"), [3, 1, 2]);\n%! assert (bounds (x, \"includenan\"), [3, 1, NaN]);\n%! assert (bounds (x, 2), [1; 3; 2]);\n%! assert (bounds (x, 2, \"omitnan\"), [1; 3; 2]);\n%! assert (bounds (x, 2, \"includenan\"), [1; NaN; 2]);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! [s,l] = bounds (x, 3);\n%! assert (s, x(:,:,1));\n%! assert (l, x(:,:,3));\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! [s,l] = bounds (x, [2, 3]);\n%! assert (s, x(:,1,1));\n%! assert (l, x(:,3,3));\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! [s,l] = bounds (x, [1, 3]);\n%! assert (s, x(1,:,1));\n%! assert (l, x(3,:,3));\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! [s,l] = bounds (x, [1, 2, 3]);\n%! assert (s, 1);\n%! assert (l, 27);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! [s,l] = bounds (x, \"all\");\n%! assert (s, 1);\n%! assert (l, 27);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! [s,l] = bounds (x, \"all\");\n%! assert (s, 1);\n%! assert (l, 27);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! [s,l] = bounds (x, \"all\", \"omitnan\");\n%! assert (s, 1);\n%! assert (l, 27);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! [s,l] = bounds (x, \"all\", \"includenan\");\n%! assert (s, NaN);\n%! assert (l, NaN);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! [s,l] = bounds (x, \"includenan\");\n%! assert (s, min (x, [], \"includenan\"));\n%! assert (l, max (x, [], \"includenan\"));\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! [s,l] = bounds (x, 3, \"includenan\");\n%! assert (s, x(:,:,1));\n%! assert (l(3), NaN);\n\n## Test input validation\n%!error <Invalid call> bounds ()\n%!error <Invalid call> bounds (1, 2, 3, 4)\n%!error <bounds: X must be a numeric array> bounds (['A'; 'B'])\n%!error <bounds: X must be a numeric array> bounds ([true; false])\n%!error <bounds: X must be a numeric array> bounds ({1, 2})\n"
  },
  {
    "path": "scripts/statistics/center.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} center (@var{x})\n## @deftypefnx {} {@var{y} =} center (@var{x}, @var{dim})\n## @deftypefnx {} {@var{y} =} center (@var{x}, @var{vecdim})\n## @deftypefnx {} {@var{y} =} center (@var{x}, \"all\")\n## @deftypefnx {} {@var{y} =} center (@dots{}, @var{nanflag})\n## Center data by subtracting its mean.\n##\n## If @var{x} is a vector, then @code{center (@var{x})} computes the centered\n## data by subtracting the mean of @var{x} from each element of @var{x}.\n##\n## If @var{x} is a matrix, then @code{center (@var{x})} returns a row vector\n## with each element containing the centered data for each column of @var{x}.\n##\n## If @var{x} is an array, then @code{center (@var{x})} centers the data alonng\n## the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be numeric.  The size of @var{y} is equal to the\n## size of @var{x}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{@var{x}}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{center} to\n## compute the center of all elements of @var{x}, and is equivalent to\n## @code{center (@var{x}(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation of the mean using any of the previously\n## specified input argument combinations.  The default value for @var{nanflag}\n## is @qcode{\"includenan\"} which keeps NaN values in the calculation.  To\n## exclude NaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  Any\n## NaN value along the operating dimensions will result in all corresponding\n## element in @var{y} being NaN.\n##\n## Programming Note: @code{center} has obvious application for normalizing\n## statistical data.  It is also useful for improving the precision of general\n## numerical calculations.  Whenever there is a large value that is common\n## to a batch of data, the mean can be subtracted off, the calculation\n## performed, and then the mean added back to obtain the final answer.\n## @seealso{zscore}\n## @end deftypefn\n\nfunction y = center (x, varargin)\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x)))\n    error (\"center: X must be a numeric array\");\n  endif\n\n  if (nargin < 2)\n    ## Find the first non-singleton dimension.\n    (dim = find (size (x) != 1, 1)) || (dim = 1);\n    nanflag = \"includenan\";\n  else\n    if (any (strcmpi (varargin{1}, {\"omitnan\", \"includenan\"})))\n      (dim = find (size (x) != 1, 1)) || (dim = 1);\n      nanflag = varargin{1};\n    else\n      dim = varargin{1};\n      if (nargin > 2)\n        nanflag = varargin{2};\n        if (! any (strcmpi (nanflag, {\"omitnan\", \"includenan\"})))\n          error (\"center: NANFLAG must be either 'omitnan' or 'includenan'\");\n        endif\n      else\n        nanflag = \"includenan\";\n      endif\n    endif\n  endif\n\n  ## Expand diagonal to full matrix before computation, since broadcasting\n  ## is not supported for diagonal matrices (Bug #35787).\n  if (! issparse (x) && isdiag (x))\n    x = full (x);\n  endif\n\n  y = x - mean (x, dim, nanflag);\n\nendfunction\n\n\n%!assert (center ([1,2,3]), [-1,0,1])\n%!assert (center (single ([1,2,3])), single ([-1,0,1]))\n%!assert (center (int8 ([1,2,3])), int8([-1,0,1]))\n%!assert (center (ones (3,2,0,2)), zeros (3,2,0,2))\n%!assert (center (ones (3,2,0,2, \"single\")), zeros (3,2,0,2, \"single\"))\n%!assert (center (magic (3)), [3,-4,1;-2,0,2;-1,4,-3])\n%!assert (center ([1 2 3; 6 5 4], 2), [-1 0 1; 1 0 -1])\n%!assert (center (1, 3), 0)\n\n%!assert (center (repmat ([1, 2, 3], 5, 1)), zeros (5, 3))\n%!assert (center (repmat ([1, 2, 3], 5, 1), 2), repmat ([-1, 0, 1], 5, 1))\n\n## Test input validation\n%!error <Invalid call> center ()\n%!error <Invalid call> center (1, 2, 3, 4)\n%!error <center: X must be a numeric array> center (['A'; 'B'])\n%!error <center: X must be a numeric array> center ([true; false])\n%!error <center: X must be a numeric array> center ({1, 2})\n"
  },
  {
    "path": "scripts/statistics/corr.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{r} =} corr (@var{x})\n## @deftypefnx {} {@var{r} =} corr (@var{x}, @var{y})\n## Compute matrix of correlation coefficients.\n##\n## If each row of @var{x} and @var{y} is an observation and each column is\n## a variable, then the @w{(@var{i}, @var{j})-th}@ entry of\n## @code{corr (@var{x}, @var{y})} is the correlation between the\n## @var{i}-th variable in @var{x} and the @var{j}-th variable in @var{y}.\n## @var{x} and @var{y} must have the same number of rows (observations).  The\n## correlation coefficient is calculated for two variable vectors @var{A} and\n## @var{B} (columns of @var{x} and @var{y}) as:\n## @tex\n## $$\n## {\\rm corr}(A,B) = {{\\rm cov}(A,B) \\over {\\rm std}(A) \\, {\\rm std}(B)}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## corr (@var{A},@var{B}) = cov (@var{A},@var{B}) / (std (@var{A}) * std (@var{B}))\n## @end example\n##\n## The output variable @var{r} will have size n x m, where n and m are the\n## number of variables (columns) in @var{x} and @var{y}, respectively.  Note\n## that as the standard deviation of any scalar is zero, the correlation\n## coefficient will be returned as NaN for any scalar or single-row inputs.\n##\n## @end ifnottex\n## If called with one argument, compute @code{corr (@var{x}, @var{x})},\n## the correlation between the each pair of columns of @var{x}.\n## @seealso{cov, corrcoef}\n## @end deftypefn\n\nfunction r = corr (x, y = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    error (\"corr: X must be a numeric or logical vector or matrix\");\n  endif\n\n  ## No check for division by zero error, which happens only when\n  ## there is a constant vector and should be rare.\n\n  if (nargin == 2)\n    ## Adjust for Octave 9.1.0 compatibility behavior change in two-input cov.\n    ## cov now treats cov(x,y) as cov(x(:),y(:)), returning a 2x2 covariance\n    ## of the two univariate distributions x and y.  corr will now pass [x,y]\n    ## as cov([x,y]), which for m x n inputs will return 2n x 2n outputs, with\n    ## the off-diagonal matrix quarters containing what was previously\n    ## returned by cov(x,y).\n\n    ## FIXME: Returning a larger than needed array and discarding 3/4 of the\n    ##        information is non-ideal.  Consider implementing a more\n    ##        efficient cov here as a subfunction to corr.  At that point,\n    ##        input validation will need to be coded back into this function.\n\n    if (! (isnumeric (y) || islogical (y)))\n      error (\"corr: Y must be a numeric or logical vector or matrix\");\n    endif\n\n    ## Check for equal number of rows before concatenating inputs for cov.\n    ## This will also catch mixed orientation 2-D vectors which cov allows but\n    ## corr should not.\n    if (rows (x) != rows (y))\n      error (\"corr: X and Y must have the same number of rows\");\n    endif\n\n    rowx = isrow (x);\n    rowy = isrow (y);\n\n    if ((! rowy && ndims (x) > 2) || (! rowx && ndims (y) > 2))\n      ## For compatibility 3-D is permitted only if other input is row vector\n      ## which results in NaNs.\n        error ([\"corr: X and Y must be two-dimensional unless the other \", ...\n                \"input is a scalar or row vector\"]);\n    endif\n\n    ## Special handling for row vectors.  std=0 along dim 1 and division by 0\n    ## will return NaN, but cov will process along vector dimension.  Keep\n    ## special handling after call to cov so it handles all other input\n    ## validation and avoid duplicating validation overhead for all other\n    ## cases.\n    ncx = columns (x);\n    ncy = columns (y);\n    if (rowx || rowy)\n      if (isa (x, \"single\") || isa (y, \"single\"))\n        r = NaN (ncx, ncy, \"single\");\n      else\n        r = NaN (ncx, ncy);\n      endif\n      return;\n    endif\n\n    c = cov ([x, y]);  # Also performs input validation of x and y.\n\n    c = c(1:ncx, ncx+1:end);\n    s = std (x, [], 1)' * std (y, [], 1);\n    r = c ./ s;\n\n  else\n    c = cov (x);    # Also performs input validation of x.\n\n    if (isrow (x))  # Special handling for row vector.\n      nc = columns (x);\n      if (isa (x, \"single\"))\n        r = NaN (nc, \"single\");\n      else\n        r = NaN (nc);\n      endif\n      return;\n    endif\n\n    s = sqrt (diag (c));\n    r = c ./ (s * s');\n  endif\n\nendfunction\n\n\n%!test\n%! x = rand (10);\n%! cc1 = corr (x);\n%! cc2 = corr (x, x);\n%! assert (size (cc1) == [10, 10] && size (cc2) == [10, 10]);\n%! assert (cc1, cc2, sqrt (eps));\n\n%!test\n%! x = [1:3]';\n%! y = [3:-1:1]';\n%! assert (corr (x, y), -1, 5*eps);\n%! assert (corr (x, flipud (y)), 1, 5*eps);\n%! assert (corr ([x, y]), [1 -1; -1 1], 5*eps);\n\n%!test\n%! x = single ([1:3]');\n%! y = single ([3:-1:1]');\n%! assert (corr (x, y), single (-1), 5*eps);\n%! assert (corr (x, flipud (y)), single (1), 5*eps);\n%! assert (corr ([x, y]), single ([1 -1; -1 1]), 5*eps);\n\n## Special case: scalar\n%!assert (corr (5), NaN)\n%!assert (corr (single (5)), single (NaN))\n\n## Special case: constant vectors\n%!assert (corr ([5; 5; 5], [1; 2; 3]), NaN)\n%!assert (corr ([1; 2; 3], [5;5;5]), NaN)\n\n%!test <*64555>\n%! x = [1 2; 3 4; 5 6];\n%! y = [1 2 3]';\n%! assert (corr (x, y), [1; 1]);\n%! assert (corr (y, x), [1, 1]);\n%! assert (corr (x, [y, y]), [1 1; 1 1]);\n\n%!test <*64395>\n%! x = [1, 2, 3];\n%! assert (corr (x), NaN (3));\n%! assert (corr (x'), 1, eps);\n%! assert (corr (x, x), NaN (3));\n%! assert (corr (x', x'), 1, eps);\n\n%!test <*64395>\n%! x = single ([1, 2, 3]);\n%! assert (corr (x), single (NaN (3)));\n%! assert (corr (x'), 1, single (eps));\n%! assert (corr (x, x), single (NaN (3)));\n%! assert (corr (x', x'), 1, single (eps));\n\n%!assert <*64555> (corr (1, rand (1, 10)), NaN (1, 10))\n%!assert <*64555> (corr (rand (1, 10), 1), NaN (10, 1))\n%!assert <*64555> (corr (rand (1, 10), rand (1, 10)), NaN (10, 10))\n%!assert <*64555> (corr (rand (1, 5), rand (1, 10)), NaN (5, 10))\n%!assert <*64555> (corr (5, rand (1, 10, 5)), NaN (1, 10))\n%!assert <*64555> (corr (rand (1, 5, 5), rand (1, 10)), NaN (5, 10))\n%!assert <*64555> (corr (rand (1, 5, 5, 99), rand (1, 10)), NaN (5, 10))\n\n## Test input validation\n%!error <Invalid call> corr ()\n%!error corr (1, 2, 3)\n%!error <X must be a numeric or logical> corr (\"foo\")\n%!error <X must be a numeric or logical> corr ({123})\n%!error <Y must be a numeric or logical> corr (1, \"foo\")\n%!error <Y must be a numeric or logical> corr (1, {123})\n%!error <Y must be a numeric or logical> corr ([1; 2], [\"A\"; \"B\"])\n%!error <X and Y must have the same number of rows> corr (ones (2,2), ones (3,2))\n%!error <X and Y must have the same number of rows> corr ([1,2,3], [1,2,3]')\n%!error <X and Y must have the same number of rows> corr ([1,2,3]', [1,2,3])\n%!error <X and Y must have the same number of rows> corr (ones (2,2), ones (1,2,2))\n%!error <X and Y must be two-dimensional unless> corr (ones (2,2), ones (2,2,2))\n%!error corr (ones (2,2,2)) # Single input validation handled by corr\n"
  },
  {
    "path": "scripts/statistics/corrcoef.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{r} =} corrcoef (@var{x})\n## @deftypefnx {} {@var{r} =} corrcoef (@var{x}, @var{y})\n## @deftypefnx {} {@var{r} =} corrcoef (@dots{}, @var{param}, @var{value}, @dots{})\n## @deftypefnx {} {[@var{r}, @var{p}] =} corrcoef (@dots{})\n## @deftypefnx {} {[@var{r}, @var{p}, @var{lci}, @var{hci}] =} corrcoef (@dots{})\n## Compute a matrix of correlation coefficients.\n##\n## @var{x} is an array where each column contains a variable and each row is\n## an observation.\n##\n## If a second input @var{y} (of the same size as @var{x}) is given then\n## calculate the correlation coefficients between @var{x} and @var{y}.\n##\n## @var{param}, @var{value} are optional pairs of parameters and values which\n## modify the calculation.  Valid options are:\n##\n## @table @asis\n## @item @qcode{\"alpha\"}\n## Confidence level used for the bounds of the confidence interval, @var{lci}\n## and @var{hci}.  Default is 0.05, i.e., 95% confidence interval.\n##\n## @item @qcode{\"rows\"}\n## Determine processing of NaN values.  Acceptable values are @qcode{\"all\"},\n## @qcode{\"complete\"}, and @qcode{\"pairwise\"}.  Default is @qcode{\"all\"}.\n## With @qcode{\"complete\"}, only the rows without NaN values are considered.\n## With @qcode{\"pairwise\"}, the selection of NaN-free rows is made for each\n## pair of variables.\n## @end table\n##\n## Output @var{r} is a matrix of Pearson's product moment correlation\n## coefficients for each pair of variables.\n##\n## Output @var{p} is a matrix of pair-wise p-values testing for the null\n## hypothesis of a correlation coefficient of zero.\n##\n## Outputs @var{lci} and @var{hci} are matrices containing, respectively, the\n## lower and higher bounds of the 95% confidence interval of each correlation\n## coefficient.\n## @seealso{corr, cov, std}\n## @end deftypefn\n\n## FIXME: It would be good to add a definition of the calculation method\n## for a Pearson product moment correlation to the documentation.\n\nfunction [r, p, lci, hci] = corrcoef (x, varargin)\n\n  if (nargin < 1 || nargin > 6)\n    print_usage ();\n  endif\n\n  alpha = 0.05;\n  rows = \"all\";\n\n  if (nargin > 1)\n\n    ## Check for matrix argument y\n    if (isnumeric (varargin{1}))\n      y = varargin{1};\n      nx = numel (x);\n      ny = numel (y);\n      if (nx > 0 && ny > 0 && nx != ny)\n        error (\"corrcoef: X and Y must be the same size\");\n      endif\n      x = [x(:), y(:)];\n      varargin(1) = [];\n    endif\n\n    ## Check for Parameter/Value arguments\n    for i = 1:2:numel (varargin)\n\n      if (! ischar (varargin{i}))\n        error (\"corrcoef: parameter %d must be a string\", i);\n      endif\n      parameter = varargin{i};\n      if (i+1 > numel (varargin))\n        error ('corrcoef: parameter \"%s\" missing value', parameter);\n      endif\n      value = varargin{i+1};\n\n      switch (lower (parameter))\n        case \"alpha\"\n          if (isnumeric (value) && isscalar (value)\n              && value >= 0 && value <= 1)\n            alpha = value;\n          else\n            error ('corrcoef: \"alpha\" must be a scalar between 0 and 1');\n          endif\n\n        case \"rows\"\n          if (! ischar (value))\n            error ('corrcoef: \"rows\" value must be a string');\n          endif\n          value = lower (value);\n          switch (value)\n            case {\"all\", \"complete\", \"pairwise\"}\n              rows = value;\n            otherwise\n              error ('corrcoef: \"rows\" must be \"all\", \"complete\", or \"pairwise\"');\n          endswitch\n\n        otherwise\n          error ('corrcoef: Unknown option \"%s\"', parameter);\n\n      endswitch\n    endfor\n  endif\n\n  if (strcmp (rows, \"complete\"))\n    x(any (isnan (x), 2), :) = [];\n  endif\n\n  if (isempty (x) || isscalar (x))\n    r = p = lci = hci = NaN;\n    return;\n  endif\n\n  ## Flags for calculation\n  pairwise = strcmp (rows, \"pairwise\");\n  calc_pval = nargout > 1;\n\n  if (isrow (x))\n    x = x(:);\n  endif\n  [m, n] = size (x);\n  r = eye (n);\n  if (calc_pval)\n    p = eye (n);\n  endif\n  if (strcmp (rows, \"pairwise\"))\n    mpw = m * ones (n);\n  endif\n  for i = 1:n\n    if (! pairwise && any (isnan (x(:,i))))\n      r(i,i) = NaN;\n      if (nargout > 1)\n        p(i,i) = NaN;\n      endif\n    endif\n    for j = i+1:n\n      xi = x(:,i);\n      xj = x(:,j);\n      if (pairwise)\n        idx = any (isnan ([xi xj]), 2);\n        xi(idx) = xj(idx) = [];\n        mpw(i,j) = mpw(j,i) = m - nnz (idx);\n      endif\n      ## Adjust for Octave 9.1.0 compatability behavior change in two-input\n      ## cov, which now handles cov(x,y) as cov(x(:),y(:)) and returns a 2x2\n      ## covariance of the two univariate distributions x and y.  The previous\n      ## scalar covariance expected for r(i,j) is contained in the (1,2)\n      ## and (2,1) elements of the new array.\n\n      ## FIXME: Returning a larger than needed arary and discarding 3/4 of the\n      ##        information is nonideal, especially in this low efficiency\n      ##        for loop approach.  Consider implementing a more efficient cov\n      ##        here as a subfunction to corr, or see if vectorizing this\n      ##        entire code allows direct usage of current cov version.\n\n      r(i,j) = r(j,i) = (cov (xi, xj) ./ (std (xi) .* std (xj)))(2);\n      if (calc_pval)\n        df = m - 2;\n        stat = sqrt (df) * r(i,j) / sqrt (1 - r(i,j)^2);\n        cdf = tcdf (stat, df);\n        p(i,j) = p(j,i) = 2 * min (cdf, 1 - cdf);\n      endif\n    endfor\n  endfor\n\n  if (nargout > 2)\n    if (pairwise)\n      m = mpw;\n    endif\n    CI = sqrt (2) * erfinv (1-alpha) ./ sqrt (m-3);\n    lci = tanh (atanh (r) - CI);\n    hci = tanh (atanh (r) + CI);\n  endif\n\nendfunction\n\n\n## Compute cumulative distribution function for T distribution.\nfunction cdf = tcdf (x, n)\n\n  if (iscomplex (x))\n    error (\"tcdf: X must not be complex\");\n  endif\n\n  if (isa (x, \"single\"))\n    cdf = zeros (size (x), \"single\");\n  else\n    cdf = zeros (size (x));\n  endif\n\n  k = ! isinf (x) & (n > 0);\n\n  xx = x .^ 2;\n  x_big_abs = (xx > n);\n\n  ## deal with the case \"abs(x) big\"\n  kk = k & x_big_abs;\n  cdf(kk) = betainc (n ./ (n + xx(kk)), n/2, 1/2) / 2;\n\n  ## deal with the case \"abs(x) small\"\n  kk = k & ! x_big_abs;\n  cdf(kk) = 0.5 * (1 - betainc (xx(kk) ./ (n + xx(kk)), 1/2, n/2));\n\n  k &= (x > 0);\n  if (any (k(:)))\n    cdf(k) = 1 - cdf(k);\n  endif\n\n  k = isnan (x) | !(n > 0);\n  cdf(k) = NaN;\n\n  k = (x == Inf) & (n > 0);\n  cdf(k) = 1;\n\nendfunction\n\n\n%!test\n%! x = rand (5);\n%! r = corrcoef (x);\n%! assert (size (r) == [5, 5]);\n\n%!test\n%! x = [1, 2, 3];\n%! r = corrcoef (x);\n%! assert (size (r) == [1, 1]);\n\n%!assert (isnan (corrcoef ([])))\n%!assert (isnan (corrcoef (NaN)))\n%!assert (isnan (corrcoef (1)))\n\n%!test\n%! x = [NaN, NaN];\n%! r = corrcoef (x);\n%! assert (size(r) == [1, 1] && isnan (r));\n\n%!test\n%! x = rand (5);\n%! [r, p] = corrcoef (x);\n%! assert (size (r) == [5, 5] && size (p) == [5 5]);\n%! assert (diag (r), ones (5,1), eps);\n\n%!test\n%! x = rand (5,1);\n%! y = rand (5,1);\n%! R1 = corrcoef (x, y);\n%! R2 = corrcoef ([x, y]);\n%! assert (R1, R2);\n%! R3 = corrcoef (x.', y.');\n%! assert (R1, R3);\n\n%!test\n%! x = [1;2;3];\n%! y = [1;2;3];\n%! r = corrcoef (x, y);\n%! assert (r, ones (2,2));\n\n%!test\n%! x = [1;2;3];\n%! y = [3;2;1];\n%! r = corrcoef (x, y);\n%! assert (r, [1, -1; -1, 1]);\n\n%!test\n%! x = [1;2;3];\n%! y = [1;1;1];\n%! r = corrcoef (x, y);\n%! assert (r, [1, NaN; NaN, 1]);\n\n%!error <Invalid call> corrcoef ()\n%!error <Invalid call> corrcoef (1, 2, \"alpha\", 0.05, \"rows\", \"all\" , 1)\n%!error <parameter 1 must be a string> corrcoef (1, 2, 3)\n%!error <parameter \"alpha\" missing value> corrcoef (1, 2, \"alpha\")\n%!error <\"alpha\" must be a scalar> corrcoef (1,2, \"alpha\", \"1\")\n%!error <\"alpha\" must be a scalar> corrcoef (1,2, \"alpha\", ones (2,2))\n%!error <\"alpha\" must be a scalar between 0 and 1> corrcoef (1,2, \"alpha\", -1)\n%!error <\"alpha\" must be a scalar between 0 and 1> corrcoef (1,2, \"alpha\", 2)\n%!error <\"rows\" must be \"all\"...> corrcoef (1,2, \"rows\", \"foobar\")\n%!error <Unknown option \"foobar\"> corrcoef (1,2, \"foobar\", 1)\n"
  },
  {
    "path": "scripts/statistics/corrcov.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{r} =} corrcov (@var{c})\n## @deftypefnx {} {[@var{r}, @var{s}] =} corrcov (@var{c})\n## Convert matrix of covariance coefficients to a matrix of correlation\n## coefficients.\n##\n## Given a numeric, square, symmetric, and positive semi-definite matrix of\n## covariance coefficients, @var{c}, calculate the corresponding linear\n## correlation coefficient matrix, @var{r}, that would be produced from the\n## same variables that produced @var{c}.\n##\n## The correlation and covariance coefficients for two vectors, @var{A} and\n## @var{B}, are related by:\n##\n## @tex\n## $$\n## {\\rm corr}(A,B) = {{\\rm cov}(A,B) \\over \\sqrt{{\\rm cov}(A,A) \\cdot  {\\rm cov}(B,B)}}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## corr (@var{A},@var{B}) = cov (@var{A},@var{B}) / sqrt (cov (@var{A},@var{A}) * cov (@var{B},@var{B}))\n## @end example\n##\n## @end ifnottex\n##\n## The output @var{r} will be the same shape and type as the input, @var{c},\n## where each element @var{r}(@var{i},@var{j}) contains the correlation\n## coefficient calculated using @var{c}(@var{i},@var{j}) as described above.\n##\n## If the optional output @var{s} is requested, it will contain a column vector\n## of the standard deviations of the variables that produced the covariance\n## matrix @var{c}.  Noting that the variances of the variables are contained in\n## the main diagonal of @var{c}, this is equivalent output to\n## @w{@code{sqrt (diag ( @var{c}))}}.\n##\n## Implementation Note: A proper covariance matrix as produced by @code{cov} is\n## square, symmetric, and positive semi-definite.  @code{corrcov} only uses an\n## approximate check for the latter that may pass improper inputs with small\n## negative eigenvalues.\n##\n## @seealso{cov, corr, corrcoef}\n## @end deftypefn\n\nfunction [R, s] = corrcov (c)\n\n  if (nargin != 1)\n    print_usage;\n  endif\n\n  if (! isfloat (c))\n    error (\"corrcov: C must be a floating point numeric matrix\");\n  elseif (! (issquare (c) && issymmetric (c)))\n    error (\"corrcov: C must be square and symmetric\");\n  elseif (any (eig (c) + 10 * max (eps (c(:))) < 0))\n    error(\"corrcov: C must be positive semi-definite\");\n  endif\n\n  v = diag (c);\n  R = c ./ sqrt (v .* v.');\n\n  if (nargin > 1)\n    s = sqrt (v);\n  endif\n\nendfunction\n\n%!assert (corrcov (0), NaN)\n%!assert (corrcov (1), 1)\n%!assert (corrcov (99.999), 1, eps)\n\n%!assert (corrcov (zeros (2)), NaN (2))\n%!assert (corrcov (ones (2)), ones (2))\n%!assert (corrcov ([1, 0; 0, 1]), [1, 0; 0, 1])\n%!assert (corrcov ([1, -1; -1, 1]), [1, -1; -1, 1])\n\n%!assert (corrcov (cov ([1:8]', [8:-1:1]')), corrcoef ([1:8]', [8:-1:1]'), eps)\n%!assert (corrcov (cov ([1:8]', [1:5,3:-1:1]')), corrcoef ([1:8]', [1:5,3:-1:1]'), eps)\n\n%!assert (isa (corrcov (single (ones(2))), \"single\"))\n\n%!assert (corrcov ([]), [])\n%!assert (corrcov (ones (0, 0)), [])\n\n## Verify matrices numerically close to positive semi-definite will pass.\n%!assert (corrcov (cov (magic (4))), corrcoef (magic (4)), eps)\n\n%!error <Invalid call> corrcov ()\n%!error <C must be a floating> corrcov ([\"a, b; b, a\"])\n%!error <C must be a floating> corrcov (int32([1, 0; 0, 1]))\n%!error <C must be a floating> corrcov ({1, 0; 0, 1})\n%!error <C must be square and symmetric> corrcov (ones (0, 1))\n%!error <C must be square and symmetric> corrcov (NaN)\n%!error <C must be square and symmetric> corrcov (NaN (2, 2))\n%!error <C must be square and symmetric> corrcov (ones (2, 3))\n%!error <C must be square and symmetric> corrcov (ones (2, 2, 2))\n%!error <C must be positive semi-definite> corrcov (-ones (2))\n\n"
  },
  {
    "path": "scripts/statistics/cov.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} cov (@var{x})\n## @deftypefnx {} {@var{c} =} cov (@var{x}, @var{y})\n## @deftypefnx {} {@var{c} =} cov (@dots{}, @var{opt})\n## @deftypefnx {} {@var{c} =} cov (@dots{}, @var{nanflag})\n## Compute the covariance matrix.\n##\n## The covariance between two variable vectors @var{A} and  @var{B} is\n## calculated as:\n## @tex\n## $$\n## \\sigma_{ij} = {1 \\over N-1} \\sum_{i=1}^N (a_i - \\bar{a})(b_i - \\bar{b})\n## $$\n## where $\\bar{a}$ and $\\bar{b}$ are the mean values of $a$ and $b$ and $N$ is\n## the length of the vectors $a$ and $b$.\n## @end tex\n## @ifnottex\n##\n## @example\n## cov (@var{a},@var{b}) = 1/(N-1) * SUM_i (@var{a}(i) - mean (@var{a})) * (@var{b}(i) - mean (@var{b}))\n## @end example\n##\n## @noindent\n## where @math{N} is the length of the vectors @var{a} and @var{b}.\n## @end ifnottex\n##\n## If called with one argument, compute @code{cov (@var{x}, @var{x})}.  If\n## @var{x} is a vector, this is the scalar variance of @var{x}.  If @var{x} is\n## a matrix, each row of @var{x} is treated as an observation, and each column\n## as a variable, and the @w{(@var{i}, @var{j})-th}@ entry of\n## @code{cov (@var{x})} is the covariance between the @var{i}-th and\n## @var{j}-th columns in @var{x}.  If @var{x} has dimensions n x m, the output\n## @var{c} will be a m x m square covariance matrix.\n##\n## If called with two arguments, compute @code{cov (@var{x}, @var{y})}, the\n## covariance between two random variables @var{x} and @var{y}.  @var{x} and\n## @var{y} must have the same number of elements, and will be treated as\n## vectors with the covariance computed as\n## @code{cov (@var{x}(:), @var{y}(:))}.  The output will be a 2 x 2\n## covariance matrix.\n##\n## The optional argument @var{opt} determines the type of normalization to\n## use.  Valid values are\n##\n## @table @asis\n## @item 0 [default]:\n##   Normalize with @math{N-1}.  This provides the best unbiased estimator of\n## the covariance.\n##\n## @item 1:\n##   Normalize with @math{N}.  This provides the second moment around the\n## mean.  @var{opt} is set to 1 for N = 1.\n## @end table\n##\n## The optional argument @var{nanflag} must appear last in the argument list\n## and controls how NaN values are handled by @code{cov}.  The three valid\n## values are:\n##\n## @table @asis\n## @item includenan [default]:\n##   Leave NaN values in @var{x} and @var{y}.  Output will follow the normal\n## rules for handling NaN values in arithmetic operations.\n##\n## @item omitrows:\n##   Rows containing NaN values are trimmed from both @var{x} and @var{y}\n## prior to calculating the covariance.  A NaN in one variable will remove\n## that row from both @var{x} and @var{y}.\n##\n## @item partialrows:\n##   Rows containing NaN values are ignored from both @var{x} and @var{y}\n##   independently for each @var{i}-th and @var{j}-th covariance\n##   calculation.  This may result in a different number of observations,\n##   @math{N}, being used to calculated each element of the covariance matrix.\n## @end table\n##\n## Compatibility Note: Before Octave v9.1.0, @code{cov} treated rows\n## @var{x} and @var{y} as multivariate random variables.  Newer versions\n## attempt to maintain full compatibility with @sc{matlab} by treating\n## @var{x} and @var{y} as two univariate distributions regardless of shape,\n## resulting in a 2x2 output matrix.  Code relying on Octave's previous\n## definition will need to be modified when running this newer version of\n## @code{cov}.  The previous behavior can be obtained by using the\n## NaN package's @code{covm} function as @code{covm (@var{x}, @var{y}, \"D\")}.\n## @seealso{corr}\n## @end deftypefn\n\nfunction c = cov (x, varargin)\n\n  if (nargin < 1 || nargin > 4)\n    print_usage ();\n  endif\n\n  opt = 0;\n  is_y = false;\n  nanflag = \"includenan\";\n\n  if (! (isnumeric (x) || islogical (x)))\n      error (\"cov: X must be a numeric or logical vector or matrix\");\n  endif\n\n  if (isrow (x))\n    x = x.';\n  endif\n\n  nvarg = numel (varargin);\n\n  if (nvarg > 0)\n    switch (nvarg)\n      case 3\n        ## Only char input should be nanflag, must be last.\n        if (ischar (varargin{1}) || ischar (varargin {2}))\n          if (ischar (varargin{3}))\n            error (\"cov: only one NANFLAG parameter may be specified\");\n          else\n            error (\"cov: NANFLAG parameter must be the last input\");\n          endif\n        endif\n\n        y = varargin{1};\n        opt = double (varargin{2}); # opt should not affect output class.\n        nanflag = lower (varargin {3});\n        is_y = true;\n\n      case 2\n        if (ischar (varargin{1}))\n          error (\"cov: NANFLAG parameter must be the last input\");\n        endif\n\n        if (ischar (varargin{end}))\n          nanflag = lower (varargin{end});\n\n          if ((isnumeric (varargin{1}) || islogical (varargin{1})) && ...\n              isscalar (varargin{1}) && ...\n              (varargin{1} == 0 || varargin{1} == 1))\n            opt = double (varargin {1});\n\n          else\n            y = varargin{1};\n            is_y = true;\n          endif\n\n        else\n          y = varargin{1};\n          opt = double (varargin{2});\n          is_y = true;\n        endif\n\n      case 1\n        if (ischar (varargin{end}))\n          nanflag = lower (varargin{end});\n\n        elseif ((isnumeric (varargin{1}) || islogical (varargin{1})) && ...\n                isscalar (varargin{1}) && ...\n                (varargin{1} == 0 || varargin{1} == 1))\n          opt = double (varargin {1});\n\n        else\n          y = varargin{1};\n          is_y = true;\n        endif\n    endswitch\n\n    if (is_y)\n      if (! (isnumeric (y) || islogical (y)))\n        error (\"cov: Y must be a numeric or logical vector or matrix\");\n\n      elseif (numel (x) != numel (y))\n        error (\"cov: X and Y must have the same number of observations\");\n\n      else\n        ## Flatten to single array.  Process the same as two-column x.\n        x = [x(:), y(:)];\n      endif\n    endif\n\n    if (! any (strcmp (nanflag, {\"includenan\", \"omitrows\", \"partialrows\"})))\n        error (\"cov: unknown NANFLAG parameter '%s'\", nanflag);\n    endif\n\n    if ((opt != 0 && opt != 1) || ! isscalar (opt))\n      error (\"cov: normalization parameter OPT must be 0 or 1\");\n    endif\n  endif\n\n  if (ndims (x) > 2)\n    ## Note: Matlab requires 2-D inputs even if providing a y input results in\n    ##       reshaping for operation as cov (x(:), y(:)) (tested in 2022b).\n    ##       Octave permits arbitrarily shaped inputs for the cov(x,y) case as\n    ##       long as numel (x) == numel (y).  Only when no y is provided is X\n    ##       restricted to 2-D for consistent 2-D columnwise behavior of cov.\n    error (\"cov: X must be a 2-D matrix or vector\");\n  endif\n\n  ## Special case: empty inputs.  Output shape changes depends on number of\n  ## columns.  Inputs already verified as limited to 2-D.\n  if (isempty (x))\n    sx = size (x);\n\n    if (sx == [0, 0])\n      c = NaN;\n    elseif (sx(1) > 0)\n      c = [];\n    else\n      c = NaN (sx(2));\n    endif\n\n    if (isa (x, \"single\"))\n      c = single (c);\n    endif\n    return;\n  endif\n\n  if (! strcmp (nanflag, \"includenan\") && all (nnx = ! isnan (x)))\n    ## Avoid unnecessary slower nanflag processing.\n    nanflag = \"includenan\";\n  endif\n\n  switch (nanflag)\n    case {\"includenan\", \"omitrows\"}\n\n      if (strcmp (nanflag, \"omitrows\"))\n        ## Trim any rows in x containing a NaN.\n        x = x(all (nnx, 2), :);\n      endif\n\n      n = rows (x);\n\n      if (n < 2)\n        ## Scalars and empties force opt = 1.\n        opt = 1;\n      endif\n\n      x -= sum (x, 1) / n;\n      c = x' * x / (n - 1 + opt);\n\n    case \"partialrows\"\n      ## Find all NaN locations for adjusted processing later.  NaN's will\n      ## only be trimmed for the columns containing them when calculating\n      ## covariance involving that row.  Each output element of c might have a\n      ## unique n, opt, and mean for each of the two vectors used to calculate\n      ## that element based on the paired column total number of non-NaN rows.\n      ## Separate out simple vector case.  Project into dim3 for general case.\n\n      if (iscolumn (x))\n        x = x(nnx);\n        n = numel (x);\n        if (n < 2)\n          opt = 1;\n        endif\n        x -= sum (x, 1) / n;\n\n        ## Matrix multiplication preserves output size compatibliity if x is\n        ## trimmed to empty.\n        c = (x' * x) / (n - 1 + opt);\n      else\n\n        ## Number of elements in each column pairing.\n        n = nnx' * nnx;\n\n        ## opt for each column pairing\n        opt = opt * ones (columns (x));\n        opt (n < 2) = 1;\n\n        ## Mean for each column pairing.\n        ## Rotate x vectors into dim3, project into dim1 with non-NaN array\n        x = permute(x, [3, 2, 1]) .* permute (nnx, [2, 3, 1]);\n        mu = x;\n        mu (isnan (x)) = 0; # Exclude input NaNs from summation.\n        mu = sum (mu, 3) ./ n; # Vectors trimmed to n=0 may create more NaNs.\n        x -= mu; # Center x's.\n        x(isnan (x)) = 0; # Exclude input and mean NaNs from output.\n\n        ## Sum dim3 elements of x products to emulate x'*x.\n        c = sum (permute (x, [2,1,3]) .* x, 3) ./ (n - 1 + opt);\n\n      endif\n  endswitch\n\nendfunction\n\n\n%!test\n%! x = rand (10);\n%! cx1 = cov (x);\n%! cx2 = cov (x, x);\n%! assert (size (cx1) == [10, 10]);\n%! assert (size (cx2) == [2, 2]);\n\n%!test\n%! x = [1:3]';\n%! y = [3:-1:1]';\n%! assert (cov (x, x), [1 1; 1 1]);\n%! assert (cov (x, x), cov ([x, x]));\n%! assert (cov (x, y), [1 -1; -1 1]);\n%! assert (cov (x, y), cov ([x, y]));\n\n%!test\n%! x = [1:3]';\n%! y = [3:-1:1]';\n%! assert (cov (single (x)), single (1));\n%! assert (cov (single (x), x), single ([1 1; 1 1]));\n%! assert (cov (x, single (x)), single ([1 1; 1 1]));\n%! assert (cov (single (x), single (x)), single ([1 1; 1 1]));\n\n%!test\n%! x = [1:8];\n%! c = cov (x);\n%! assert (isscalar (c));\n%! assert (c, 6);\n\n%!test <*64395>\n%! x = [1, 2, 3];\n%! assert (cov (x), 1, eps);\n%! assert (cov (x'), 1, eps);\n%! assert (cov (x, x), ones (2), eps);\n%! assert (cov (x', x), ones (2), eps);\n%! assert (cov (x, x'), ones (2), eps);\n%! assert (cov (x', x'), ones (2), eps);\n\n%!test\n%! x = [1 0; 1 0];\n%! y = [1 2; 1 1];\n%! z = [1/3 -1/6; -1/6 0.25];\n%! assert (cov (x, y), z, eps);\n%! assert (cov (x, y(:)), z, eps);\n%! assert (cov (x, y(:)'), z, eps);\n%! assert (cov (x', y(:)), z .* [1, -1; -1, 1], eps);\n%! assert (cov (x(:), y), z, eps);\n%! assert (cov (x(:)', y), z, eps);\n\n## Test scalar inputs & class preservation\n%!assert (cov (5), 0)\n%!assert (cov (1, 0), 0)\n%!assert (cov (1, 1), 0)\n%!assert (cov (1, 0.1), [0, 0; 0, 0])\n%!assert (cov (1, 1.1), [0, 0; 0, 0])\n%!assert (cov (1, 3), [0, 0; 0, 0])\n%!assert (cov (single (5)), single (0))\n%!assert (cov (single (5), 0), single (0))\n%!assert (cov (single (5), 1), single (0))\n%!assert (cov (single (5), 1.1), single ([0, 0; 0, 0]))\n%!assert (cov (5, single (0)), double (0))\n%!assert (cov (5, single (1)), double (0))\n%!assert (cov (5, single (1.1)), single ([0, 0; 0, 0]))\n%!assert (cov (5, single (1.1), 0), single ([0, 0; 0, 0]))\n%!assert (cov (5, single (1.1), 1), single ([0, 0; 0, 0]))\n%!assert (cov (5, 1.1, single (0)), double([0, 0; 0, 0]))\n\n## Test opt\n%!test\n%! x = [1:5];\n%! c = cov (x, 0);\n%! assert (c, 2.5);\n%! c = cov (x, 1);\n%! assert (c, 2);\n%! c = cov (double (x), single (1));\n%! assert (class (c), \"double\");\n%!assert (cov (2, 4), zeros (2))\n%!assert (cov (2, 4, 0), zeros (2))\n%!assert (cov (2, 4, 1), zeros (2))\n%!assert (cov (NaN, 4), [NaN, NaN; NaN, 0])\n%!assert (cov (NaN, 4, 0), [NaN, NaN; NaN, 0])\n%!assert (cov (NaN, 4, 1), [NaN, NaN; NaN, 0])\n\n## Test logical inputs\n%!assert (cov (logical (0), logical (0)), double (0))\n%!assert (cov (0, logical (0)), double (0))\n%!assert (cov (logical (0), 0), double (0))\n%!assert (cov (logical ([0 1; 1 0]), logical ([0 1; 1 0])), double ([1 1;1 1]./3))\n%!assert (cov ([1 2 3], [3 4 5], 0), [1 1; 1 1])\n%!assert (cov ([1 2 3], [3 4 5], false), [1 1; 1 1])\n%!assert (cov ([1 2 3], [3 4 5], 1), [2/3 2/3; 2/3 2/3], eps)\n%!assert (cov ([1 2 3], [3 4 5], true), [2/3 2/3; 2/3 2/3], eps)\n\n\n## Test empty and NaN handling (bug #50583)\n%!assert <*50583> (cov ([]), NaN)\n%!assert <*50583> (cov (single ([])), single (NaN))\n%!assert <*50583> (cov ([], []), NaN (2, 2))\n%!assert <*50583> (cov (single ([]), single([])), single (NaN (2, 2)))\n%!assert <*50583> (cov ([], single ([])), single (NaN (2, 2)))\n%!assert <*50583> (cov (single ([]), []), single (NaN (2, 2)))\n%!assert <*50583> (cov (ones (1, 0)), NaN)\n%!assert <*50583> (cov (ones (2, 0)), [])\n%!assert <*50583> (cov (ones (0, 1)), NaN)\n%!assert <*50583> (cov (ones (0, 2)), NaN (2, 2))\n%!assert <*50583> (cov (ones (0, 6)), NaN (6, 6))\n%!assert <*50583> (cov (ones (2, 0), []), NaN (2, 2))\n%!assert <*50583> (cov (ones (0,6), []), NaN (2, 2))\n%!assert <*50583> (cov (NaN), NaN)\n%!assert <*50583> (cov (NaN, NaN), NaN (2, 2))\n%!assert <*50583> (cov (5, NaN), [0, NaN; NaN, NaN])\n%!assert <*50583> (cov (NaN, 5), [NaN, NaN; NaN, 0])\n%!assert <*50583> (cov (single (NaN)), single (NaN))\n%!assert <*50583> (cov (NaN (2, 2)), NaN (2, 2))\n%!assert <*50583> (cov (single (NaN (2, 2))), single (NaN (2, 2)))\n%!assert <*50583> (cov (NaN (2, 9)), NaN (9, 9))\n%!assert <*50583> (cov (NaN (9, 2)), NaN (2, 2))\n%!assert <*50583> (cov ([NaN, 1, 2, NaN]), NaN)\n%!assert <*50583> (cov ([1, NaN, 2, NaN]), NaN)\n\n## Test NaN and nanflag option (bug #50571)\n%!test <*50571>\n%! x = magic (3);\n%! y = magic (3);\n%! x(3) = NaN;\n%! assert (cov (y, \"omitrows\"), cov (y));\n%! assert (cov (y, \"partialrows\"), cov (y));\n%! assert (cov (x), [NaN, NaN, NaN; NaN, 16, -8; NaN, -8, 7]);\n%! assert (cov (x, \"omitrows\"), ...\n%!   [12.5, -10, -2.5; -10, 8, 2; -2.5, 2, 0.5], eps);\n%! assert (cov (x, \"partialrows\"),\n%!   [12.5, -10, -2.5; -10, 16, -8; -2.5, -8, 7], eps);\n%! assert (cov (x, x), NaN (2,2));\n%! assert (cov (x, y), [NaN, NaN; NaN, 7.5], eps);\n%! assert (cov (y, x), [7.5, NaN; NaN, NaN], eps);\n%! assert (cov (x, x, 'omitrows'), (471/56) * ones (2), eps);\n%! assert (cov (x, x, 'partialrows'), (471/56) * ones (2), eps);\n%! assert (cov (x, y, 'omitrows'), (471/56) * ones (2), eps);\n%! assert (cov (x, y, 'partialrows'), (471/56)*[1,1;1,0] + [0,0;0,7.5], eps);\n%! assert (cov (y, x, 'omitrows'), (471/56) * ones (2), eps);\n%! assert (cov (y, x, 'partialrows'), (471/56)*[0,1;1,1] + [7.5,0;0,0], eps);\n%! assert (cov (x, y, 0, 'omitrows'), (471/56) * ones (2), eps);\n%! assert (cov (x, y, 0, 'partialrows'), (471/56)*[1,1;1,0] + [0,0;0,7.5], eps);\n%!assert (cov ([NaN NaN NaN]), NaN)\n%!assert <*50571> (cov ([NaN NaN NaN], \"omitrows\"), NaN)\n%!assert <*50571> (cov ([NaN NaN NaN], \"partialrows\"), NaN)\n%!assert (cov (NaN (3)), NaN (3))\n%!assert <*50571> (cov (NaN (3), \"omitrows\"), NaN (3))\n%!assert <*50571> (cov (NaN (3), \"partialrows\"), NaN (3))\n%!assert (cov ([NaN NaN NaN],[1 2 3]), [NaN, NaN; NaN 1])\n%!assert <*50571> (cov ([NaN NaN NaN],[1 2 3], \"omitrows\"), [NaN, NaN; NaN NaN])\n%!assert <*50571> (cov ([NaN NaN NaN],[1 2 3], \"partialrows\"), [NaN, NaN; NaN 1])\n%!test <*50571>\n%! x = magic (3);\n%! x(4:6) = NaN;\n%! assert (cov (x), [7 NaN 1; NaN NaN NaN; 1 NaN 7]);\n%! assert (cov (x, \"omitrows\"), NaN (3));\n%! assert (cov (x, \"partialrows\"), [7 NaN 1; NaN NaN NaN; 1 NaN 7]);\n%!assert <*50571> (cov (5, NaN, \"omitrows\"), NaN (2, 2))\n%!assert <*50571> (cov (NaN, 5, \"omitrows\"), NaN (2, 2))\n%!assert <*50571> (cov (5, NaN, \"partialrows\"), [0, NaN; NaN, NaN])\n%!assert <*50571> (cov (NaN, 5, \"partialrows\"), [NaN, NaN; NaN, 0])\n%!test <*50571>\n%! x = [1:10]';\n%! y = x;\n%! x(2:2:10)=NaN;\n%! y(1:2:9)=NaN;\n%! assert (cov(x,y), NaN (2));\n%! assert (cov(x,y,'omitrows'), NaN (2));\n%! assert (cov(x,y,'partialrows'), [10 NaN; NaN, 10]);\n%! x(10) = 5;\n%! assert (cov(x,y), NaN (2));\n%! assert (cov(x,y,'omitrows'), zeros (2));\n%! assert (cov(x,y,'partialrows'), [8 0; 0, 10]);\n#!assert (cov ([NaN, NaN, 3]), NaN)\n#!assert <*50571>  (cov ([NaN, NaN, 3], 'omitrows'), 0)\n#!assert <*50571> (cov ([NaN, NaN, 3], 'partialrows'), 0)\n%!assert (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3]), NaN(3))\n%!assert <*50571> (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3], 'omitrows'), NaN(3))\n%!assert <*50571> (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3], 'partialrows'), [NaN, NaN, NaN; NaN(2,1), zeros(2)])\n%!assert <*50571> (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3], 0, 'partialrows'), [NaN, NaN, NaN; NaN(2,1), zeros(2)])\n%!assert <*50571> (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3], 1, 'partialrows'), [NaN, NaN, NaN; NaN(2,1), zeros(2)])\n%!test <*50571>\n%! x = magic (4);\n%! x([4 5 7 10 14 16]) = NaN;\n%! x1 = x(:,2);\n%! x2 = x(:,3);\n%! assert (cov(x1,x2), NaN (2));\n%! assert (cov(x1,x2, 'omitrows'), zeros (2));\n%! assert (cov(x1,x2, 'partialrows'), [4.5,0;0,39], eps);\n%! assert (cov(x1,x2,0, 'partialrows'), [4.5,0;0,39], eps);\n%! assert (cov(x1,x2,1, 'partialrows'), [2.25,0;0,26], eps);\n%! assert (cov(x), NaN (4));\n%! assert (cov(x,'omitrows'), NaN (4));\n%! assert (cov(x, 'partialrows'), [31 0 -10.5 3.5; 0 4.5 0 NaN; -10.5 0 39 -1.5; 3.5 NaN -1.5 0.5], eps);\n%! assert (cov(x, 0, 'partialrows'), [31 0 -10.5 3.5; 0 4.5 0 NaN; -10.5 0 39 -1.5; 3.5 NaN -1.5 0.5], eps);\n%! assert (cov(x, 1, 'partialrows'), [62/3 0 -5.25 1.75; 0 2.25 0 NaN; -5.25 0 26 -0.75; 1.75 NaN -0.75 0.25], eps);\n\n## Test input validation\n%!error <Invalid call> cov ()\n%!error <Invalid call> cov (1, 2, 3, 4, 5)\n%!error <X must be a numeric or logical> cov (\"foo\")\n%!error <X must be a numeric or logical> cov ({123})\n%!error <X must be a 2-D> cov (ones (2, 2, 2))\n%!error <X must be a 2-D> cov (ones (1, 0, 2))\n%!error <only one NANFLAG> cov (1, \"foo\", 0, \"includenan\")\n%!error <only one NANFLAG> cov (1, 1, \"foo\", \"includenan\")\n%!error <normalization parameter OPT must be> cov (1, 2, [])\n%!error <normalization parameter OPT must be> cov (1, 2, 1.1)\n%!error <normalization parameter OPT must be> cov (1, 2, -1)\n%!error <normalization parameter OPT must be> cov (1, 2, [0 1])\n%!error <Y must be a> cov (1, {123})\n%!error <Y must be a> cov (1, struct())\n%!error <X and Y must have the same number> cov (5,[1 2])\n%!error <X and Y must have the same number> cov (ones (2, 2), ones (2, 2, 2))\n%!error <X and Y must have the same number> cov (ones (2, 2), ones (3, 2))\n%!error <X and Y must have the same number> cov (1, [])\n%!error <X and Y must have the same number> cov ([1, 2], ones(1, 0, 2))\n%!error <unknown NANFLAG parameter 'foo'> cov (1, \"foo\")\n%!error <unknown NANFLAG parameter 'foo'> cov (1, \"foo\")\n%!error <unknown NANFLAG parameter 'foo'> cov (1, 2, \"foo\")\n%!error <unknown NANFLAG parameter 'foo'> cov (1, 2, 0, \"foo\")\n%!error <unknown NANFLAG parameter ''> cov (1, 2, 1, [])\n%!error <NANFLAG parameter must be the last> cov (1, \"includenan\", 1)\n%!error <NANFLAG parameter must be the last> cov (1, 1, \"includenan\", 1)\n"
  },
  {
    "path": "scripts/statistics/discrete_cdf.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{cdf} =} discrete_cdf (@var{x}, @var{v}, @var{p})\n## For each element of @var{x}, compute the cumulative distribution function\n## (CDF) at @var{x} of a univariate discrete distribution which assumes the\n## values in @var{v} with probabilities @var{p}.\n## @end deftypefn\n\nfunction cdf = discrete_cdf (x, v, p)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (! isvector (v))\n    error (\"discrete_cdf: V must be a vector\");\n  elseif (any (isnan (v)))\n    error (\"discrete_cdf: V must not have any NaN elements\");\n  elseif (! isvector (p) || (length (p) != length (v)))\n    error (\"discrete_cdf: P must be a vector with length (V) elements\");\n  elseif (! (all (p >= 0) && any (p)))\n    error (\"discrete_cdf: P must be a nonzero, non-negative vector\");\n  endif\n\n  p = p(:) / sum (p);   # Reshape and normalize probability vector\n\n  if (isa (x, \"single\") || isa (v, \"single\") || isa (p, \"single\"))\n    cdf = NaN (size (x), \"single\");\n  else\n    cdf = NaN (size (x));\n  endif\n\n  k = ! isnan (x);\n  [vs, vi] = sort (v);\n  cdf(k) = [0 ; cumsum(p(vi))](lookup (vs, x(k)) + 1);\n\nendfunction\n\n\n%!shared x,v,p,y\n%! x = [-1 0.1 1.1 1.9 3];\n%! v = 0.1:0.2:1.9;\n%! p = 1/length (v) * ones (1, length (v));\n%! y = [0 0.1 0.6 1 1];\n%!assert (discrete_cdf ([x, NaN], v, p), [y, NaN], eps)\n\n## Test class of input preserved\n%!assert (discrete_cdf (single ([x, NaN]), v, p),\n%!        single ([y, NaN]), 2*eps (\"single\"))\n%!assert (discrete_cdf ([x, NaN], single (v), p),\n%!        single ([y, NaN]), 2*eps (\"single\"))\n%!assert (discrete_cdf ([x, NaN], v, single (p)),\n%!        single ([y, NaN]), 2*eps (\"single\"))\n\n## Test input validation\n%!error <Invalid call> discrete_cdf ()\n%!error <Invalid call> discrete_cdf (1)\n%!error <Invalid call> discrete_cdf (1,2)\n%!error discrete_cdf (1, ones (2), ones (2,1))\n%!error discrete_cdf (1, [1 ; NaN], ones (2,1))\n%!error discrete_cdf (1, ones (2,1), ones (1,1))\n%!error discrete_cdf (1, ones (2,1), [1 -1])\n%!error discrete_cdf (1, ones (2,1), [1 NaN])\n%!error discrete_cdf (1, ones (2,1), [0 0])\n"
  },
  {
    "path": "scripts/statistics/discrete_inv.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{q} =} discrete_inv (@var{x}, @var{v}, @var{p})\n## For each element of @var{x}, compute the quantile (the inverse of the CDF)\n## at @var{x} of the univariate distribution which assumes the values in\n## @var{v} with probabilities @var{p}.\n## @end deftypefn\n\nfunction q = discrete_inv (x, v, p)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (! isvector (v))\n    error (\"discrete_inv: V must be a vector\");\n  elseif (! isvector (p) || (length (p) != length (v)))\n    error (\"discrete_inv: P must be a vector with length (V) elements\");\n  elseif (any (isnan (p)))\n    error (\"discrete_rnd: P must not have any NaN elements\");\n  elseif (! (all (p >= 0) && any (p)))\n    error (\"discrete_inv: P must be a nonzero, non-negative vector\");\n  endif\n\n  if (isa (x, \"single\") || isa (v, \"single\") || isa (p, \"single\"))\n    q = NaN (size (x), \"single\");\n  else\n    q = NaN (size (x));\n  endif\n\n  ## FIXME: This isn't elegant.  But cumsum and lookup together produce\n  ## different results when called with a single or a double.\n  if (isa (p, \"single\"))\n    p = double (p);\n  endif\n\n  [v, idx] = sort (v);\n  p = cumsum (p(idx)(:)) / sum (p);  # Reshape and normalize probability vector\n\n  k = (x == 0);\n  q(k) = v(1);\n\n  k = (x == 1);\n  q(k) = v(end);\n\n  k = (x > 0) & (x < 1);\n  q(k) = v(length (p) - lookup (sort (p, \"descend\"), x(k)) + 1);\n\nendfunction\n\n\n%!shared x,v,p,y\n%! x = [-1 0 0.1 0.5 1 2];\n%! v = 0.1:0.2:1.9;\n%! p = 1/length (v) * ones (1, length (v));\n%! y = [NaN v(1) v(1) v(end/2) v(end) NaN];\n%!assert (discrete_inv ([x, NaN], v, p), [y, NaN], eps)\n\n## Test class of input preserved\n%!assert (discrete_inv (single ([x, NaN]), v, p),\n%!        single ([y, NaN]), eps (\"single\"))\n%!assert (discrete_inv ([x, NaN], single (v), p),\n%!        single ([y, NaN]), eps (\"single\"))\n%!assert (discrete_inv ([x, NaN], v, single (p)),\n%!        single ([y, NaN]), eps (\"single\"))\n\n## Test input validation\n%!error <Invalid call> discrete_inv ()\n%!error <Invalid call> discrete_inv (1)\n%!error <Invalid call> discrete_inv (1,2)\n%!error discrete_inv (1, ones (2), ones (2,1))\n%!error discrete_inv (1, ones (2,1), ones (1,1))\n%!error discrete_inv (1, ones (2,1), [1 NaN])\n%!error discrete_inv (1, ones (2,1), [1 -1])\n%!error discrete_inv (1, ones (2,1), [0  0])\n"
  },
  {
    "path": "scripts/statistics/discrete_pdf.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{pdf} =} discrete_pdf (@var{x}, @var{v}, @var{p})\n## For each element of @var{x}, compute the probability density function (PDF)\n## at @var{x} of a univariate discrete distribution which assumes the values\n## in @var{v} with probabilities @var{p}.\n## @end deftypefn\n\nfunction pdf = discrete_pdf (x, v, p)\n\n  if (nargin != 3)\n    print_usage ();\n  endif\n\n  if (! isvector (v))\n    error (\"discrete_pdf: V must be a vector\");\n  elseif (any (isnan (v)))\n    error (\"discrete_pdf: V must not have any NaN elements\");\n  elseif (! isvector (p) || (length (p) != length (v)))\n    error (\"discrete_pdf: P must be a vector with length (V) elements\");\n  elseif (! (all (p >= 0) && any (p)))\n    error (\"discrete_pdf: P must be a nonzero, non-negative vector\");\n  endif\n\n  ## Reshape and normalize probability vector.  Values not in table get 0 prob.\n  p = [0 ; p(:)/sum(p)];\n\n  if (isa (x, \"single\") || isa (v, \"single\") || isa (p, \"single\"))\n    pdf = NaN (size (x), \"single\");\n  else\n    pdf = NaN (size (x));\n  endif\n\n  k = ! isnan (x);\n  [vs, vi] = sort (v(:));\n  pdf(k) = p([0 ; vi](lookup (vs, x(k), 'm') + 1) + 1);\n\nendfunction\n\n\n%!shared x,v,p,y\n%! x = [-1 0.1 1.1 1.9 3];\n%! v = 0.1:0.2:1.9;\n%! p = 1/length (v) * ones (1, length (v));\n%! y = [0 0.1 0.1 0.1 0];\n%!assert (discrete_pdf ([x, NaN], v, p), [y, NaN], 5*eps)\n\n## Test class of input preserved\n%!assert (discrete_pdf (single ([x, NaN]), v, p),\n%!        single ([y, NaN]), 5*eps (\"single\"))\n%!assert (discrete_pdf ([x, NaN], single (v), p),\n%!        single ([y, NaN]), 5*eps (\"single\"))\n%!assert (discrete_pdf ([x, NaN], v, single (p)),\n%!        single ([y, NaN]), 5*eps (\"single\"))\n\n## Test input validation\n%!error <Invalid call> discrete_pdf ()\n%!error <Invalid call> discrete_pdf (1)\n%!error <Invalid call> discrete_pdf (1,2)\n%!error discrete_pdf (1, ones (2), ones (2,1))\n%!error discrete_pdf (1, [1 ; NaN], ones (2,1))\n%!error discrete_pdf (1, ones (2,1), ones (1,1))\n%!error discrete_pdf (1, ones (2,1), [1 -1])\n%!error discrete_pdf (1, ones (2,1), [1 NaN])\n%!error discrete_pdf (1, ones (2,1), [0  0])\n"
  },
  {
    "path": "scripts/statistics/discrete_rnd.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{rnd} =} discrete_rnd (@var{v}, @var{p})\n## @deftypefnx {} {@var{rnd} =} discrete_rnd (@var{v}, @var{p}, @var{r})\n## @deftypefnx {} {@var{rnd} =} discrete_rnd (@var{v}, @var{p}, @var{r}, @var{c}, @dots{})\n## @deftypefnx {} {@var{rnd} =} discrete_rnd (@var{v}, @var{p}, [@var{sz}])\n## Return a matrix of random samples from the univariate distribution which\n## assumes the values in @var{v} with probabilities @var{p}.\n##\n## When called with a single size argument, return a square matrix with\n## the dimension specified.  When called with more than one scalar argument the\n## first two arguments are taken as the number of rows and columns and any\n## further arguments specify additional matrix dimensions.  The size may also\n## be specified with a vector of dimensions @var{sz}.\n##\n## If no size arguments are given then the result matrix is the common size of\n## @var{v} and @var{p}.\n## @end deftypefn\n\nfunction rnd = discrete_rnd (v, p, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! isvector (v))\n    error (\"discrete_rnd: V must be a vector\");\n  elseif (! isvector (p) || (length (p) != length (v)))\n    error (\"discrete_rnd: P must be a vector with length (V) elements\");\n  elseif (any (isnan (p)))\n    error (\"discrete_rnd: P must not have any NaN elements\");\n  elseif (! (all (p >= 0) && any (p)))\n    error (\"discrete_rnd: P must be a nonzero, non-negative vector\");\n  endif\n\n  if (nargin == 2)\n    sz = size (v);\n  elseif (nargin == 3)\n    if (isscalar (varargin{1}) && varargin{1} >= 0)\n      sz = [varargin{1}, varargin{1}];\n    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))\n      sz = varargin{1};\n    else\n      error (\"discrete_rnd: dimension vector must be row vector of non-negative integers\");\n    endif\n  elseif (nargin > 3)\n    if (any (cellfun (@(x) (! isscalar (x) || x < 0), varargin)))\n      error (\"discrete_rnd: dimensions must be non-negative integers\");\n    endif\n    sz = [varargin{:}];\n  endif\n\n  rnd = v(lookup (cumsum (p(1:end-1)) / sum (p), rand (sz)) + 1);\n  rnd = reshape (rnd, sz);\n\nendfunction\n\n\n%!assert (size (discrete_rnd (1:2, 1:2, 3)), [3, 3])\n%!assert (size (discrete_rnd (1:2, 1:2, [4 1])), [4, 1])\n%!assert (size (discrete_rnd (1:2, 1:2, 4, 1)), [4, 1])\n\n## Test class of input preserved\n%!assert (class (discrete_rnd (1:2, 1:2)), \"double\")\n%!assert (class (discrete_rnd (single (1:2), 1:2)), \"single\")\n## FIXME: Maybe this should work, maybe it shouldn't.\n%!#assert (class (discrete_rnd (1:2, single(1:2))), \"single\")\n\n## Test input validation\n%!error <Invalid call> discrete_rnd ()\n%!error <Invalid call> discrete_rnd (1)\n%!error discrete_rnd (1:2,1:2, -1)\n%!error discrete_rnd (1:2,1:2, ones (2))\n%!error discrete_rnd (1:2,1:2, [2 -1 2])\n%!error discrete_rnd (1:2,1:2, 1, ones (2))\n%!error discrete_rnd (1:2,1:2, 1, -1)\n## test v,p verification\n%!error discrete_rnd (1, ones (2), ones (2,1))\n%!error discrete_rnd (1, ones (2,1), ones (1,1))\n%!error discrete_rnd (1, ones (2,1), [1 -1])\n%!error discrete_rnd (1, ones (2,1), [1 NaN])\n%!error discrete_rnd (1, ones (2,1), [0  0])\n"
  },
  {
    "path": "scripts/statistics/empirical_cdf.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{cdf} =} empirical_cdf (@var{x}, @var{data})\n## For each element of @var{x}, compute the cumulative distribution function\n## (CDF) at @var{x} of the empirical distribution obtained from\n## the univariate sample @var{data}.\n## @end deftypefn\n\nfunction cdf = empirical_cdf (x, data)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! isvector (data))\n    error (\"empirical_cdf: DATA must be a vector\");\n  endif\n\n  cdf = discrete_cdf (x, data, ones (size (data)));\n\nendfunction\n\n\n%!shared x,v,y\n%! x = [-1 0.1 1.1 1.9 3];\n%! v = 0.1:0.2:1.9;\n%! y = [0 0.1 0.6 1 1];\n%!assert (empirical_cdf (x, v), y, eps)\n%!assert (empirical_cdf ([x(1) NaN x(3:5)], v), [0 NaN 0.6 1 1], eps)\n\n## Test class of input preserved\n%!assert (empirical_cdf ([x, NaN], v), [y, NaN], eps)\n%!assert (empirical_cdf (single ([x, NaN]), v), single ([y, NaN]), eps)\n%!assert (empirical_cdf ([x, NaN], single (v)), single ([y, NaN]), eps)\n\n## Test input validation\n%!error <Invalid call> empirical_cdf ()\n%!error <Invalid call> empirical_cdf (1)\n%!error empirical_cdf (1, ones (2))\n"
  },
  {
    "path": "scripts/statistics/empirical_inv.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{q} =} empirical_inv (@var{x}, @var{data})\n## For each element of @var{x}, compute the quantile (the inverse of the CDF)\n## at @var{x} of the empirical distribution obtained from the\n## univariate sample @var{data}.\n## @end deftypefn\n\nfunction q = empirical_inv (x, data)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! isvector (data))\n    error (\"empirical_inv: DATA must be a vector\");\n  endif\n\n  q = discrete_inv (x, data, ones (size (data)));\n\nendfunction\n\n\n%!shared x,v,y\n%! x = [-1 0 0.1 0.5 1 2];\n%! v = 0.1:0.2:1.9;\n%! y = [NaN v(1) v(1) v(end/2) v(end) NaN];\n%!assert (empirical_inv (x, v), y, eps)\n\n## Test class of input preserved\n%!assert (empirical_inv ([x, NaN], v), [y, NaN], eps)\n%!assert (empirical_inv (single ([x, NaN]), v), single ([y, NaN]), eps)\n%!assert (empirical_inv ([x, NaN], single (v)), single ([y, NaN]), eps)\n\n## Test input validation\n%!error <Invalid call> empirical_inv ()\n%!error <Invalid call> empirical_inv (1)\n%!error empirical_inv (1, ones (2))\n"
  },
  {
    "path": "scripts/statistics/empirical_pdf.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{pdf} =} empirical_pdf (@var{x}, @var{data})\n## For each element of @var{x}, compute the probability density function (PDF)\n## at @var{x} of the empirical distribution obtained from the\n## univariate sample @var{data}.\n## @end deftypefn\n\nfunction pdf = empirical_pdf (x, data)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! isvector (data))\n    error (\"empirical_pdf: DATA must be a vector\");\n  endif\n\n  uniq_vals = unique (data);\n  if (numel (data) != numel (uniq_vals))\n    ## Handle ties, multiple elements with same value\n    p = histc (data, uniq_vals);\n    data = uniq_vals;\n  else\n    p = ones (size (data));\n  endif\n\n  pdf = discrete_pdf (x, data, p);\n\nendfunction\n\n\n%!shared x,v,y\n%! x = [-1 0.1 1.1 1.9 3];\n%! v = 0.1:0.2:1.9;\n%! y = [0 0.1 0.1 0.1 0];\n%!assert (empirical_pdf (x, v), y)\n\n## Test class of input preserved\n%!assert (empirical_pdf (single (x), v), single (y))\n%!assert (empirical_pdf (x, single (v)), single (y))\n\n## Test distribution with ties\n%!assert (empirical_pdf (2, [1 2 3 2]), 0.5)\n\n## Test input validation\n%!error <Invalid call> empirical_pdf ()\n%!error <Invalid call> empirical_pdf (1)\n%!error empirical_inv (1, ones (2))\n"
  },
  {
    "path": "scripts/statistics/empirical_rnd.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{rnd} =} empirical_rnd (@var{data})\n## @deftypefnx {} {@var{rnd} =} empirical_rnd (@var{data}, @var{r})\n## @deftypefnx {} {@var{rnd} =} empirical_rnd (@var{data}, @var{r}, @var{c}, @dots{})\n## @deftypefnx {} {@var{rnd} =} empirical_rnd (@var{data}, [@var{sz}])\n## Return a matrix of random samples from the empirical distribution obtained\n## from the univariate sample @var{data}.\n##\n## When called with a single size argument, return a square matrix with\n## the dimension specified.  When called with more than one scalar argument the\n## first two arguments are taken as the number of rows and columns and any\n## further arguments specify additional matrix dimensions.  The size may also\n## be specified with a vector of dimensions @var{sz}.\n##\n## If no size arguments are given then the result matrix is a random ordering\n## of the sample @var{data}.\n## @end deftypefn\n\nfunction rnd = empirical_rnd (data, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! isvector (data))\n    error (\"empirical_rnd: DATA must be a vector\");\n  endif\n\n  rnd = discrete_rnd (data, ones (size (data)), varargin{:});\n\nendfunction\n\n\n%!assert (size (empirical_rnd (ones (3, 1))), [3, 1])\n%!assert (size (empirical_rnd (1:2, [4 1])), [4, 1])\n%!assert (size (empirical_rnd (1:2, 4, 1)), [4, 1])\n\n## Test class of input preserved\n%!assert (class (empirical_rnd (1:2, 1)), \"double\")\n%!assert (class (empirical_rnd (single (1:2), 1)), \"single\")\n\n## Test input validation\n%!error <Invalid call> empirical_rnd ()\n%!error empirical_rnd (ones (2), 1)\n%!error empirical_rnd (ones (2), 1, 1)\n"
  },
  {
    "path": "scripts/statistics/histc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{n} =} histc (@var{x}, @var{edges})\n## @deftypefnx {} {@var{n} =} histc (@var{x}, @var{edges}, @var{dim})\n## @deftypefnx {} {[@var{n}, @var{idx}] =} histc (@dots{})\n## Compute histogram counts.\n##\n## When @var{x} is a vector, the function counts the number of elements of\n## @var{x} that fall in the histogram bins defined by @var{edges}.  This\n## must be a vector of monotonically increasing values that define the edges\n## of the histogram bins.\n## @tex\n## $n(k)$\n## @end tex\n## @ifnottex\n## @code{@var{n}(k)}\n## @end ifnottex\n## contains the number of elements in @var{x} for which\n## @tex\n## $@var{edges}(k) <= @var{x} < @var{edges}(k+1)$.\n## @end tex\n## @ifnottex\n## @code{@var{edges}(k) <= @var{x} < @var{edges}(k+1)}.\n## @end ifnottex\n## The final element of @var{n} contains the number of elements of @var{x}\n## exactly equal to the last element of @var{edges}.\n##\n## When @var{x} is an @math{N}-dimensional array, the computation is carried\n## out along dimension @var{dim}.  If not specified @var{dim} defaults to the\n## first non-singleton dimension.\n##\n## When a second output argument is requested an index matrix is also returned.\n## The @var{idx} matrix has the same size as @var{x}.  Each element of\n## @var{idx} contains the index of the histogram bin in which the\n## corresponding element of @var{x} was counted.\n## @seealso{hist}\n## @end deftypefn\n\nfunction [n, idx] = histc (x, edges, dim)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! isreal (x))\n    error (\"histc: X argument must be real-valued, not complex\");\n  endif\n\n  num_edges = numel (edges);\n  if (num_edges == 0)\n    warning (\"histc: empty EDGES specified\\n\");\n    n = idx = [];\n    return;\n  endif\n\n  if (! isreal (edges))\n    error (\"histc: EDGES must be real-valued, not complex\");\n  else\n    ## Make sure 'edges' is sorted\n    edges = edges(:);\n    if (! issorted (edges) || edges(1) > edges(end))\n      warning (\"histc: edge values not sorted on input\");\n      edges = sort (edges);\n    endif\n  endif\n\n  nd = ndims (x);\n  sz = size (x);\n  if (nargin < 3)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  else\n    if (!(isscalar (dim) && dim == fix (dim))\n        || !(1 <= dim && dim <= nd))\n      error (\"histc: DIM must be an integer and a valid dimension\");\n    endif\n  endif\n\n  nsz = sz;\n  nsz(dim) = num_edges;\n\n  ## the splitting point is 3 bins\n\n  if (num_edges <= 3)\n\n    ## This is the O(M*N) algorithm.\n\n    ## Allocate the histogram\n    n = zeros (nsz);\n\n    ## Allocate 'idx'\n    if (nargout > 1)\n      idx = zeros (sz);\n    endif\n\n    ## Prepare indices\n    idx1 = cell (1, dim-1);\n    for k = 1:length (idx1)\n      idx1{k} = 1:sz(k);\n    endfor\n    idx2 = cell (length (sz) - dim);\n    for k = 1:length (idx2)\n      idx2{k} = 1:sz(k+dim);\n    endfor\n\n    ## Compute the histograms\n    for k = 1:num_edges-1\n      b = (edges(k) <= x & x < edges(k+1));\n      n(idx1{:}, k, idx2{:}) = sum (b, dim);\n      if (nargout > 1)\n        idx(b) = k;\n      endif\n    endfor\n    b = (x == edges(end));\n    n(idx1{:}, num_edges, idx2{:}) = sum (b, dim);\n    if (nargout > 1)\n      idx(b) = num_edges;\n    endif\n\n  else\n\n    ## This is the O(M*log(N) + N) algorithm.\n\n    ## Look-up indices.\n    idx = lookup (edges, x);\n    ## Zero invalid ones (including NaNs).  x < edges(1) are already zero.\n    idx(! (x <= edges(end))) = 0;\n\n    iidx = idx;\n\n    ## In case of matrix input, we adjust the indices.\n    if (! isvector (x))\n      nl = prod (sz(1:dim-1));\n      nn = sz(dim);\n      nu = prod (sz(dim+1:end));\n      if (nl != 1)\n        iidx = (iidx-1) * nl;\n        iidx += reshape (kron (ones (1, nn*nu), 1:nl), sz);\n      endif\n      if (nu != 1)\n        ne =length (edges);\n        iidx += reshape (kron (nl*ne*(0:nu-1), ones (1, nl*nn)), sz);\n      endif\n    endif\n\n    ## Select valid elements.\n    iidx = iidx(idx != 0);\n\n    ## Call accumarray to sum the indexed elements.\n    n = accumarray (iidx(:), 1, nsz);\n\n  endif\n\nendfunction\n\n\n%!test\n%! x = linspace (0, 10, 1001);\n%! n = histc (x, 0:10);\n%! assert (n, [repmat(100, 1, 10), 1]);\n\n%!test\n%! x = repmat (linspace (0, 10, 1001), [2, 1, 3]);\n%! n = histc (x, 0:10, 2);\n%! assert (n, repmat ([repmat(100, 1, 10), 1], [2, 1, 3]));\n\n## Test input validation\n%!error <Invalid call> histc ()\n%!error <Invalid call> histc (1)\n%!error histc ([1:10 1+i], 2)\n%!warning <empty EDGES specified> histc (1:10, []);\n%!error histc (1, 1, 3)\n"
  },
  {
    "path": "scripts/statistics/iqr.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{r} =} iqr (@var{x})\n## @deftypefnx {} {@var{r} =} iqr (@var{x}, @var{dim})\n## @deftypefnx {} {@var{r} =} iqr (@var{x}, @var{vecdim})\n## @deftypefnx {} {@var{r} =} iqr (@var{x}, @qcode{\"all\"})\n## @deftypefnx {} {[@var{r}, @var{q}] =} iqr (@dots{})\n## Compute the interquartile range of the input data @var{x}.\n##\n## The interquartile range is defined as the difference between the 75th and\n## 25th percentile values of @var{x} calculated using\n##\n## @example\n## quantile (x, [0.25 , 0.75])\n## @end example\n##\n## If @var{x} is a vector, then @code{iqr (@var{x})} computes the interquartile\n## range of the elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{iqr (@var{x})} returns a row vector with\n## each element containing the interquartile range of the corresponding column\n## in @var{x}.\n##\n## If @var{x} is an array, then @code{iqr (@var{x})} computes the interquartile\n## range along the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be numeric and any NaN values are ignored.  The\n## size of @var{r} is equal to the size of @var{x} except for the operating\n## dimension, which becomes 1.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{zeros (size (@var{x}))}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{iqr} to operate\n## on all elements of @var{x}, and is equivalent to @code{iqr (@var{x}(:))}.\n##\n## The optional output @var{q} contains the quantiles for the 25th and 75th\n## percentile of the data.\n##\n## Usage Note: As a measure of dispersion, the interquartile range is less\n## affected by outliers than either @code{range} or @code{std}.  The\n## interquartile range of a scalar is necessarily @code{0}.\n##\n## @seealso{bounds, mad, range, std, prctile, quantile}\n## @end deftypefn\n\nfunction [r, q] = iqr (x, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  vecdim_flag = false;\n  nd = ndims (x);\n  sz = size (x);\n  empty_x = isempty (x);\n\n  if (! (isnumeric (x)))\n    error (\"iqr: X must be a numeric array\");\n  endif\n\n  if (nargin < 2)\n    ## Find first non-singleton dimension.\n    (dim = find (sz != 1, 1)) || (dim = 1);\n\n    ## Return immediately for an empty matrix\n    if (empty_x)\n      if (nd == 2 && max (sz) <= 1)\n        ## Matlab compatibility for 0x0, 1x0, 0x1 matrices\n        sz = [1, 1];\n      else\n        ## Function operates on DIM and reduces it to 1.\n        sz(dim) = 1;\n      endif\n      r = NaN (sz);\n      q = cat (dim, r, r);\n      return;\n    endif\n\n  else\n\n    ## Check for numeric DIM/VECDIM argument\n    if (isnumeric (dim) && isvector (dim) && isindex (dim))\n\n      ## Check for proper VECDIM (more than 1 dim, no repeats)\n      nel_vecdim = numel (dim);\n      if (nel_vecdim > 1 && all (diff (sort (dim))))\n\n        if (empty_x)\n          ## Return immediately for an empty matrix\n          dim = dim(dim <= nd);  # exclude dims greater than ndims\n          sz(dim) = 1;           # opearate on VECDIMS and reduce to 1\n          r = NaN (sz);\n          ## Matlab compatibility: change only first VECDIM of q to 2.\n          sz(min (dim)) = 2;\n          q = NaN (sz);\n          return;\n        endif\n\n        ## Detect trivial case of DIM being all dimensions (same as \"all\").\n        max_dim = max (nd, max (dim));\n        if (nel_vecdim == nd && max_dim == nd)\n          x = x(:);\n          sz = size (x);\n          dim = 1;\n        else\n          ## Algorithm: Move dimensions for operation to the front, keeping the\n          ## order of the remaining dimensions.  Reshape the moved dims into a\n          ## single dimension (row).  Calculate as normal with iqr on dim1 of\n          ## X, then reshape to correct dimensions.\n\n          vecdim_flag = true;  # reshape results at end\n\n          dim = dim(:).';  # Force row vector\n\n          ## Permutation vector with DIM at front\n          perm = [1:max_dim];\n          perm(dim) = [];\n          perm = [dim, perm];\n\n          ## Reshape X to put dims to process at front.\n          x = permute (x, perm);\n          newsize = size (x);\n\n          ## Preserve trailing singletons when dim > ndims (x).\n          newsize = [newsize, ones(1, max_dim - numel (newsize))];\n\n          newshape = [prod(newsize(1:nel_vecdim)), ...\n                      ones(1, (nel_vecdim-1)), ...\n                      newsize((nel_vecdim+1):end)];\n\n          ## Size must always have 2 dimensions.\n          if (isscalar (newshape))\n            newshape = [newshape, 1];\n          endif\n\n          ## Collapse dimensions to be processsed into single column.\n          x = reshape (x, newshape);\n\n          ## Operate on rows.\n          dim = 1;\n        endif\n\n      elseif (! isscalar (dim))\n        error (\"iqr: VECDIM must contain non-repeating positive integers\");\n\n      elseif (empty_x)\n        ## Return immediately for an empty matrix\n        if (dim <= nd)\n          sz(dim) = 1;\n        endif\n        r = NaN (sz);\n        q = cat (dim, r, r);\n        return;\n      endif\n\n    elseif (strcmpi (dim, \"all\"))\n\n      ## Return immediately for an empty matrix\n      if (empty_x)\n        r = NaN;\n        q = [NaN; NaN];\n        return;\n      endif\n\n      ## \"all\" simplifies to collapsing all elements to single vector.\n      x = x(:);\n      sz = size (x);\n      dim = 1;\n\n    else\n      error (\"iqr: DIM must be a positive integer scalar, vector, or 'all'\");\n    endif\n\n  endif\n\n  if ((dim > nd || sz(dim) == 1) && all (isfinite (x)))\n    ## Shortcut, no calculation required for 1-element dimensions\n    r = zeros (sz);\n    q = cat (dim, x, x);\n  elseif (dim == 1 && iscolumn (x))\n    ## Work around quantile() where vector output orientation follows p input,\n    ## rather than x input.\n    q = quantile (x, [0.25; 0.75], 1);\n    r = abs (diff (q, [], 1));\n  else\n    q = quantile (x, [0.25, 0.75], dim);\n    r = abs (diff (q, [], dim));\n  endif\n\n  if (vecdim_flag)\n    r = ipermute (r, perm);\n    q = ipermute (q, perm);\n  endif\n\nendfunction\n\n\n## Basic tests\n%!assert (iqr (17), 0)\n%!assert (iqr (17, 1), 0)\n%!assert (iqr (17, 4), 0)\n%!assert (iqr (1:3), 1.5)\n%!assert (iqr (1:4), 2)\n%!assert (iqr (1:5), 2.5)\n%!assert (iqr (1:10), 5)\n%!assert (iqr ((1:10).'), 5)\n%!assert (iqr (1:10, 2), 5)\n%!assert (iqr (1:10, 1), zeros (1, 10))\n%!assert (iqr (1:10, 3), zeros (1, 10))\n%!assert (iqr ([1:5; 2:6], [1, 2]), 3)\n%!assert (iqr ([1:5; 2:6], \"all\"), 3)\n\n%!test\n%! x = reshape (1:6, [1, 2, 3]);\n%! assert (iqr (x), ones (1, 1, 3));\n%! assert (iqr (x, 1), zeros (1, 2, 3));\n%! assert (iqr (x, 2), ones (1, 1, 3));\n%! assert (iqr (x, 3), [3, 3]);\n\n## N-D arrays\n%!test\n%! x = magic (4); x = cat (3,x, 2*x, 3*x); x = cat (4, x, 2*x);\n%! y = cat (3, 8*[1, 1, 1, 1], 16*[1, 1, 1, 1], 24*[1, 1, 1, 1]);\n%! assert (iqr (x), cat (4, y, 2*y));\n%! assert (iqr (x, 1), cat (4, y, 2*y));\n%! y = cat (3, 4*[3, 1, 1, 3].', 8*[3, 1, 1, 3].', 12*[3, 1, 1, 3].');\n%! assert (iqr (x, 2), cat (4, y, 2*y));\n%! y = [24, 3, 4.5, 19.5; 7.5, 16.5, 15, 12; 13.5, 10.5, 9, 18; 6, 21, 22.5, 1.5];\n%! assert (iqr (x, 3), cat (4, y, 2*y));\n%! y = [16, 2, 3, 13; 5, 11, 10, 8; 9, 7, 6, 12; 4, 14, 15, 1];\n%! assert (iqr (x, 4), cat (3, y, 2*y, 3*y));\n%! assert (iqr (x, 5), zeros (size (x)));\n\n## vector dimensions\n%!assert (iqr (17, [1, 8]), 0)\n%!assert (iqr ([[1, 2, 5]; [2, 5, 6]], [1, 2]), 3)\n%!assert (iqr (cat (3, [1, 2, 5; 2, 5, 6], [1, 2, 5; 2, 5, 6]), [1, 2]), cat(3, 3, 3))\n%!assert (iqr (cat (3, [1, 2, 5; 2, 5, 6], [1, 2, 5; 2, 5, 6]), [1, 2]'), cat(3, 3, 3))\n%!test\n%! x = magic (4); x = cat (3, x, 2*x, 3*x); x = cat (4, x, 2*x);\n%! y = cat (3, 8, 16, 24);\n%! assert (iqr (x, [1, 2]), cat (4, y, 2*y));\n%! y = [14, 18.5, 17.5, 19.5];\n%! assert (iqr (x, [1, 3]), cat (4, y, 2*y));\n%! y = [10.5, 12.5, 11.5, 15];\n%! assert (iqr (x, [1, 4]), cat (3, y, 2*y, 3*y));\n%! assert (iqr (x, [1, 5]), iqr (x, 1));\n%! y = [24, 13, 12, 25.5]';\n%! assert (iqr (x, [2, 3]), cat (4, y, 2*y));\n%! y = [17.5, 9, 8, 18.5]';\n%! assert (iqr (x, [2, 4]), cat (3, y, 2*y, 3*y));\n%! assert (iqr (x, [3, 4]), [32, 4, 6, 26; 10, 22, 20, 16; 18, 14, 12, 24; 8, 28, 30, 2]);\n%! assert (iqr (x, [3, 4]), iqr (x, [4, 3]));\n%! assert (iqr (x, [1, 2, 3]), cat (4, 17.5, 35));\n%! assert (iqr (x, [2, 3, 4]), [29.5, 19.5, 23, 31]');\n%! assert (iqr (x, [1, 3, 4]), [22, 28, 22, 30.5]);\n%! assert (iqr (x, [1, 2, 4]), cat (3, 11, 22, 33));\n%! assert (iqr (x, [1, 2, 5]), iqr (x, [1, 2]));\n%! assert (iqr (x, [5, 6]), zeros (size (x)));\n\n## Inf, NaN\n%!assert (iqr (Inf), NaN)\n%!assert (iqr (-Inf), NaN)\n%!assert (iqr (NaN), NaN)\n%!assert (iqr (NaN), NaN)\n%!assert (iqr ([1, 2, Inf], 1), [0, 0, NaN])\n%!assert (iqr ([1, 2, Inf], 2), Inf)\n%!assert (iqr ([1, 2, -Inf], 1), [0, 0, NaN])\n%!assert (iqr ([1, 2, -Inf], 2), Inf)\n%!assert (iqr ([1, 2, 3, NaN], 1), [0, 0, 0, NaN])\n%!assert (iqr ([1, 2, 3, NaN], 2), 1.5)\n%!assert (iqr ([1, NaN, 2, 3], 2), 1.5)\n%!assert (iqr (NaN (2), 1), [NaN, NaN])\n%!assert (iqr (NaN (2), 2), [NaN; NaN])\n%!assert (iqr (NaN (2), 3), NaN (2))\n%!assert (iqr ([[1, 2, 5], [2, NaN, 6]], \"all\"), 3.5)\n\n## Tests for q output\n%!assert ([~,q] = iqr ([1:100]), [25.5, 75.5])\n%!assert ([~,q] = iqr ([1:100]'), [25.5; 75.5])\n%!assert ([~,q] = iqr (repmat ([1:100]', [1,2])), repmat ([25.5; 75.5], [1,2]))\n%!assert ([~,q] = iqr (repmat ([1:100], [2,1]), 2), repmat ([25.5, 75.5], [2,1]))\n%!assert ([~,q] = iqr (repmat ([1:100], [2,1]), [1 2]), [25.5; 75.5])\n%!assert ([~,q] = iqr (repmat ([1:100], [2,1]), 'all'), [25.5; 75.5])\n\n## Empty inputs\n%!assert <*65531> (iqr ([]), NaN)\n%!assert <*65531> (iqr (ones (0, 1)), NaN)\n%!assert <*65531> (iqr (ones (0, 1), 1), NaN)\n%!assert <*65531> (iqr (ones (0, 1), 2), NaN (0, 1))\n%!assert <*65531> (iqr (ones (0, 1), 3), NaN (0, 1))\n%!assert <*65531> (iqr (ones (1, 0)), NaN)\n%!assert <*65531> (iqr (ones (1, 0), 1), NaN (1, 0))\n%!assert <*65531> (iqr (ones (1, 0), 2), NaN)\n%!assert <*65531> (iqr (ones (1, 0), 3), NaN (1, 0))\n%!assert <*65531> (iqr (ones (1, 0), 9), NaN (1, 0))\n%!assert <*65531> (iqr (ones (1, 1, 0)), NaN)\n%!assert <*65531> (iqr (ones (0, 0, 1, 0)), NaN (1, 0, 1, 0))\n%!assert <*65531> (iqr (ones (1, 1, 1, 0)), NaN)\n%!assert <*65531> (iqr (ones (1, 1, 1, 0), 1), NaN (1, 1, 1, 0))\n%!assert <*65531> (iqr (ones (0, 0, 1, 0), 1), NaN (1, 0, 1, 0))\n%!assert <*65531> (iqr (ones (0, 0, 1, 0), 2), NaN (0, 1, 1, 0))\n%!assert <*65531> (iqr (ones (0, 0, 1, 0), 3), NaN (0, 0, 1, 0))\n%!assert <*65531> (iqr (ones (0, 0, 1, 0), 4), NaN (0, 0, 1, 1))\n%!assert <*65531> (iqr (ones (0, 0, 1, 0), 9), NaN (0, 0, 1, 0))\n%!assert <*65531> (iqr (ones (0, 0, 1, 0), [1, 2]), NaN (1, 1, 1, 0))\n%!assert <*65531> (iqr (ones (0, 0, 1, 0), [1, 4]), NaN (1, 0, 1, 1))\n%!assert <*65531> (iqr (ones (0, 0, 1, 0), [1, 9]), NaN (1, 0, 1, 0))\n%!assert <*65531> (iqr ([], \"all\"), NaN)\n%!assert <*65531> (iqr (ones (0, 1), \"all\"), NaN)\n%!assert <*65531> (iqr (ones (1, 0), \"all\"), NaN)\n%!assert <*65531> (iqr (ones (1, 1, 0), \"all\"), NaN)\n%!assert <*65531> (iqr (ones (0, 0, 1, 0), 'all'), NaN)\n%!assert <*65531> ([~,q] = iqr ([]), NaN (2, 1))\n%!assert <*65531> ([~,q] = iqr (ones (0, 1)), NaN (2, 1))\n%!assert <*65531> ([~,q] = iqr (ones (0, 1), 1), NaN (2, 1))\n%!assert <*65531> ([~,q] = iqr (ones (0, 1), 2), NaN (0, 2))\n%!assert <*65531> ([~,q] = iqr (ones (0, 1), 3), NaN (0, 1, 2))\n%!assert <*65531> ([~,q] = iqr (ones (1, 0)), NaN (1, 2))\n%!assert <*65531> ([~,q] = iqr (ones (1, 0), 1), NaN (2, 0))\n%!assert <*65531> ([~,q] = iqr (ones (1, 0), 2), NaN (1, 2))\n%!assert <*65531> ([~,q] = iqr (ones (1, 0), 3), NaN (1, 0, 2))\n%!assert <*65531> ([~,q] = iqr (ones (1, 0), 9), NaN (1,0,1,1,1,1,1,1,2))\n%!assert <*65531> ([~,q] = iqr (ones (1, 1, 0)), NaN (1, 1, 2))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0)), NaN (2, 0, 1, 0))\n%!assert <*65531> ([~,q] = iqr (ones (1, 1, 1, 0)), NaN (1, 1, 1, 2))\n%!assert <*65531> ([~,q] = iqr (ones (1, 1, 1, 0), 1), NaN (2, 1, 1, 0))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0), 1), NaN (2, 0, 1, 0))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0), 2), NaN (0, 2, 1, 0))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0), 3), NaN (0, 0, 2, 0))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0), 4), NaN (0, 0, 1, 2))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0), 9), NaN (0,0,1,0,1,1,1,1,2))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0), [1, 2]), NaN (2, 1, 1, 0))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0), [1, 4]), NaN (2, 0, 1, 1))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0), [1, 9]), NaN (2, 0, 1, 0))\n%!assert <*65531> ([~,q] = iqr ([], \"all\"), NaN (2, 1))\n%!assert <*65531> ([~,q] = iqr (ones (0, 1), \"all\"), NaN (2, 1))\n%!assert <*65531> ([~,q] = iqr (ones (1, 0), \"all\"), NaN (2, 1))\n%!assert <*65531> ([~,q] = iqr (ones (1, 1, 0), \"all\"), NaN (2, 1))\n%!assert <*65531> ([~,q] = iqr (ones (0, 0, 1, 0), 'all'), NaN (2, 1))\n\n## input validation\n%!error <Invalid call> iqr ()\n%!error <iqr: function called with too many inputs> iqr (1, 2, 3)\n%!error <iqr: X must be a numeric array> iqr (['A'; 'B'])\n%!error <iqr: X must be a numeric array> iqr ([true; false])\n%!error <iqr: X must be a numeric array> iqr ({1, 2})\n%!error <VECDIM must contain non-repeating> iqr ([1, 2, 3], [1, 2, 1])\n%!error <DIM must be a positive integer> iqr (1, 'A')\n%!error <DIM must be a positive integer> iqr (1, 0)\n%!error <DIM must be a positive integer> iqr (1, -2)\n%!error <DIM must be a positive integer> iqr (1, 1.4)\n%!error <DIM must be .* positive integer> iqr (1, [1, -2])\n%!error <DIM must be .* positive integer> iqr (1, [1, 1.4])\n%!error <DIM must be .* positive integer> iqr ([1, 2, 3], NaN)\n%!error <DIM must be .* positive integer> iqr ([1, 2, 3], [2, NaN])\n%!error <DIM must be .* positive integer> iqr ([1, 2, 3], Inf)\n%!error <DIM must be .* positive integer> iqr ([1, 2, 3], [2, Inf])\n%!error <DIM must be .* scalar, vector> iqr (1, [1, 2; 3, 4])\n"
  },
  {
    "path": "scripts/statistics/kendall.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tau} =} kendall (@var{x})\n## @deftypefnx {} {@var{tau} =} kendall (@var{x}, @var{y})\n## @cindex Kendall's Tau\n## Compute Kendall's\n## @tex\n## $\\tau$.\n## @end tex\n## @ifnottex\n## @var{tau}.\n## @end ifnottex\n##\n## For two data vectors @var{x}, @var{y} of common length @math{N}, Kendall's\n## @tex\n## $\\tau$\n## @end tex\n## @ifnottex\n## @var{tau}\n## @end ifnottex\n## is the correlation of the signs of all rank differences of\n## @var{x} and @var{y}; i.e., if both @var{x} and @var{y} have distinct\n## entries, then\n## @tex\n## $$ \\tau = {1 \\over N(N-1)} \\sum_{i,j} {\\rm sign}(q_i-q_j) \\, {\\rm sign}(r_i-r_j) $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##          1\n## @var{tau} = -------   SUM sign (@var{q}(i) - @var{q}(j)) * sign (@var{r}(i) - @var{r}(j))\n##       N (N-1)   i,j\n## @end group\n## @end example\n##\n## @end ifnottex\n## @noindent\n## in which the\n## @tex\n## $q_i$ and $r_i$\n## @end tex\n## @ifnottex\n## @var{q}(i) and @var{r}(i)\n## @end ifnottex\n## are the ranks of @var{x} and @var{y}, respectively.\n##\n## If @var{x} and @var{y} are drawn from independent distributions,\n## Kendall's\n## @tex\n## $\\tau$\n## @end tex\n## @ifnottex\n## @var{tau}\n## @end ifnottex\n## is asymptotically normal with mean 0 and variance\n## @tex\n## ${2 (2N+5) \\over 9N(N-1)}$.\n## @end tex\n## @ifnottex\n## @code{(2 * (2N+5)) / (9 * N * (N-1))}.\n## @end ifnottex\n##\n## @code{kendall (@var{x})} is equivalent to @code{kendall (@var{x},\n## @var{x})}.\n## @seealso{ranks, spearman}\n## @end deftypefn\n\nfunction tau = kendall (x, y = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (   ! (isnumeric (x) || islogical (x))\n      || ! (isnumeric (y) || islogical (y)))\n    error (\"kendall: X and Y must be numeric matrices or vectors\");\n  endif\n\n  if (ndims (x) != 2 || ndims (y) != 2)\n    error (\"kendall: X and Y must be 2-D matrices or vectors\");\n  endif\n\n  if (isrow (x))\n    x = x.';\n  endif\n  [n, c] = size (x);\n\n  if (nargin == 2)\n    if (isrow (y))\n      y = y.';\n    endif\n    if (rows (y) != n)\n      error (\"kendall: X and Y must have the same number of observations\");\n    else\n      x = [x, y];\n    endif\n  endif\n\n  if (isa (x, \"single\") || isa (y, \"single\"))\n    cls = \"single\";\n  else\n    cls = \"double\";\n  endif\n  r   = ranks (x);\n  m   = sign (kron (r, ones (n, 1, cls)) - kron (ones (n, 1, cls), r));\n  tau = corr (m);\n\n  if (nargin == 2)\n    tau = tau(1 : c, (c + 1) : columns (x));\n  endif\n\nendfunction\n\n\n%!test\n%! x = [1:2:10];\n%! y = [100:10:149];\n%! assert (kendall (x,y), 1, 5*eps);\n%! assert (kendall (x,fliplr (y)), -1, 5*eps);\n\n%!assert (kendall (1), NaN)\n%!assert (kendall (single (1)), single (NaN))\n\n## Test input validation\n%!error <Invalid call> kendall ()\n%!error kendall (['A'; 'B'])\n%!error kendall (ones (2,1), ['A'; 'B'])\n%!error kendall (ones (2,2,2))\n%!error kendall (ones (2,2), ones (2,2,2))\n%!error kendall (ones (2,2), ones (3,2))\n"
  },
  {
    "path": "scripts/statistics/kurtosis.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} kurtosis (@var{x})\n## @deftypefnx {} {@var{y} =} kurtosis (@var{x}, @var{flag})\n## @deftypefnx {} {@var{y} =} kurtosis (@var{x}, @var{flag}, @var{dim})\n## @deftypefnx {} {@var{y} =} kurtosis (@var{x}, @var{flag}, @var{vecdim})\n## @deftypefnx {} {@var{y} =} kurtosis (@var{x}, @var{flag}, \"all\")\n## Compute the sample kurtosis of the input data @var{x}.\n##\n## The sample kurtosis is defined as\n## @tex\n## $$\n## \\kappa_1 = {{{1 \\over N} \\sum_{i=1}^N (x_i - \\bar{x})^4} \\over \\sigma^4},\n## $$\n## where $N$ is the length of @var{x}, $\\bar{x}$ its mean, and $\\sigma$ its\n## (uncorrected) standard deviation.\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##      mean ((@var{x} - mean (@var{x})).^4)\n## k1 = ------------------------\n##             std (@var{x}).^4\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @noindent\n## The optional argument @var{flag} controls which normalization is used.\n## If @var{flag} is equal to 1 (default value, used when @var{flag} is omitted\n## or empty), return the sample kurtosis as defined above.  If @var{flag} is\n## equal to 0, return the @w{\"bias-corrected\"}@ kurtosis coefficient instead:\n## @tex\n## $$\n## \\kappa_0 = 3 + {\\scriptstyle N - 1 \\over \\scriptstyle (N - 2)(N - 3)} \\,\n##     \\left( (N + 1)\\, \\kappa_1 - 3 (N - 1) \\right)\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##               N - 1\n## k0 = 3 + -------------- * ((N + 1) * k1 - 3 * (N - 1))\n##          (N - 2)(N - 3)\n## @end group\n## @end example\n##\n## @noindent\n## where @math{N} is the length of the @var{x} vector.\n##\n## @end ifnottex\n## The bias-corrected kurtosis coefficient is obtained by replacing the sample\n## second and fourth central moments by their unbiased versions.  It is an\n## unbiased estimate of the population kurtosis for normal populations.\n##\n## If @var{x} is a vector, then @code{kurtosis (@var{x})} computes the kurtosis\n## of the data in @var{x}.\n##\n## If @var{x} is a matrix, then @code{kurtosis (@var{x})} returns a row vector\n## with each element containing the kurtosis of the data of the corresponding\n## column in @var{x}.\n##\n## If @var{x} is an array, then @code{kurtosis (@var{x})} computes the kurtosis\n## of the data along the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be numeric and any NaN values are ignored.\n## The size of @var{y} is equal to the size of @var{x} except for the operating\n## dimension, which becomes 1.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{@var{x}}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{kurtosis} to\n## operate on all elements of @var{x}, and is equivalent to\n## @code{kurtosis (@var{x}(:))}.\n##\n## @seealso{var, skewness, moment}\n## @end deftypefn\n\nfunction y = kurtosis (x, flag, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x)))\n    error (\"kurtosis: X must be a numeric array\");\n  endif\n\n  if (nargin < 2 || isempty (flag))\n    flag = 1;  # default: do not use the \"bias corrected\" version\n  else\n    if (! isscalar (flag) || (flag != 0 && flag != 1))\n      error (\"kurtosis: FLAG must be 0 or 1\");\n    endif\n  endif\n\n  if (nargin < 3)\n    (dim = find (size (x) != 1, 1)) || (dim = 1);\n  endif\n\n  n = sum (x == x, dim, \"omitnan\");\n\n  x = center (x, dim, \"omitnan\");\n  v = var (x, 1, dim, \"omitnan\");   # normalize with 1/N\n  y = sum (x .^ 4, dim, \"omitnan\");\n  y = y ./ (n .* v .^ 2);\n  idx = (v != 0);\n  y(! idx) = NaN;\n\n  ## Apply bias correction to the second and fourth central sample moment\n  if (flag == 0)\n    idx = n > 3;\n    nn = n(idx);\n    C = (nn - 1) ./ ((nn - 2) .* (nn - 3));\n    y(idx) = 3 + C .* ((nn + 1) .* y(idx) - 3 .* (nn - 1));\n    y(! idx) = NaN;\n  endif\n\nendfunction\n\n\n%!test\n%! x = [-1; 0; 0; 0; 1];\n%! y = [x, 2*x];\n%! assert (kurtosis (y), [2.5, 2.5], sqrt (eps));\n\n%!assert (kurtosis ([-3, 0, 1]) == kurtosis ([-1, 0, 3]))\n%!assert (kurtosis (ones (3, 5)), NaN (1, 5))\n%!assert (kurtosis (1, [], 3), NaN)\n\n%!assert (kurtosis ([1:5 10; 1:5 10],  0, 2),\n%!        5.4377317925288901 * [1; 1], 8 * eps)\n%!assert (kurtosis ([1:5 10; 1:5 10],  1, 2),\n%!        2.9786509002956195 * [1; 1], 8 * eps)\n%!assert (kurtosis ([1:5 10; 1:5 10], [], 2),\n%!        2.9786509002956195 * [1; 1], 8 * eps)\n\n## Test behavior on single input\n%!assert (kurtosis (single ([1:5 10])), single (2.9786513), eps (\"single\"))\n%!assert (kurtosis (single ([1 2]), 0), single (NaN))\n\n## Test dim\n%!test\n%! x(:,:,1) = [0.5377, 0.3188, 3.5784; 1.8339, -1.3077, 2.7694; ...\n%!             -2.2588, -0.4336, -1.3499; 0.8622, 0.3426, 3.0349];\n%! x(:,:,2) = [0.7254, -0.1241, 0.6715; -0.0631, 1.4897, -1.2075; ...\n%!             0.7147 1.4090 0.7172; -0.2050, 1.4172, 1.6302];\n%! y = kurtosis (x);\n%! assert (y(:,:,1), [2.1350, 1.7060, 2.2789], 1e-4);\n%! assert (y(:,:,2), [1.0542, 2.3278, 2.0996], 1e-4);\n%! y = kurtosis (x, 1, 2);\n%! assert (y(:,:,1), [1.5; 1.5; 1.5; 1.5], 8 * eps);\n%! assert (y(:,:,2), [1.5; 1.5; 1.5; 1.5], 8 * eps);\n%! y = kurtosis (x, 1, 3);\n%! assert (y, ones (4, 3), 8 * eps);\n\n## Test \"all\" and vecdim\n%!test\n%! x(:,:,1) = [0.5377, 0.3188, 3.5784; 1.8339, -1.3077, 2.7694; ...\n%!             -2.2588, -0.4336, -1.3499; 0.8622, 0.3426, 3.0349];\n%! x(:,:,2) = [0.7254, -0.1241, 0.6715; -0.0631, 1.4897, -1.2075; ...\n%!             0.7147 1.4090 0.7172; -0.2050, 1.4172, 1.6302];\n%! y = kurtosis (x, 1, \"all\");\n%! assert (y, 2.8029, 1e-4);\n%! y = kurtosis (x, 1, [1, 2]);\n%! assert (y(:,:,1), 1.9345, 1e-4);\n%! assert (y(:,:,2), 2.5877, 1e-4);\n%! y = kurtosis (x, 1, [2, 3]);\n%! assert (y, [3.8457; 1.4306; 1.7094; 2.3378], 1e-4);\n\n## Verify no warnings\n%!test\n%! lastwarn (\"\");  # clear last warning\n%! kurtosis (1);\n%! assert (lastwarn (), \"\");\n\n## Test input validation\n%!error <Invalid call> kurtosis ()\n%!error <kurtosis: function called with too many inputs> kurtosis (1, 2, 3, 4)\n%!error <kurtosis: X must be a numeric array> kurtosis (['A'; 'B'])\n%!error <kurtosis: X must be a numeric array> kurtosis ([true; false])\n%!error <kurtosis: X must be a numeric array> kurtosis ({1, 2})\n%!error <FLAG must be 0 or 1> kurtosis (1, 2)\n%!error <FLAG must be 0 or 1> kurtosis (1, [1 0])\n"
  },
  {
    "path": "scripts/statistics/mad.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{m} =} mad (@var{x})\n## @deftypefnx {} {@var{m} =} mad (@var{x}, @var{opt})\n## @deftypefnx {} {@var{m} =} mad (@var{x}, @var{opt}, @var{dim})\n## @deftypefnx {} {@var{m} =} mad (@var{x}, @var{opt}, @var{vecdim})\n## @deftypefnx {} {@var{m} =} mad (@var{x}, @var{opt}, \"all\")\n## Compute the mean or median absolute deviation (MAD) of the elements of\n## @var{x}.\n##\n## The mean absolute deviation is defined as\n##\n## @example\n## @var{mad} = mean (abs (@var{x} - mean (@var{x})))\n## @end example\n##\n## The median absolute deviation is defined as\n##\n## @example\n## @var{mad} = median (abs (@var{x} - median (@var{x})))\n## @end example\n##\n## @code{mad} excludes NaN values from calculation similar to using the\n## @code{omitnan} option in @code{mean} and @code{median}.\n##\n## If @var{x} is a vector, then @code{mad (@var{x})} returns the mean absolute\n## deviation of the elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{mad (@var{x})} returns a row vector with\n## each element containing the mean absolute deviation of the corresponding\n## column in @var{x}.\n##\n## If @var{x} is an array, then @code{mad (@var{x})} computes the mean absolute\n## deviation along the first non-singleton dimension of @var{x}.\n##\n## The optional argument @var{opt} specifies whether mean or median absolute\n## deviation is calculated.  The default is @code{0} which corresponds to mean\n## absolute deviation; a value of @code{1} corresponds to median absolute\n## deviation.  Passing an empty input @code{[]} defaults to mean absolute\n## deviation.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{zeros (size (@var{x}))}.\n##\n## Specifying the dimension as @var{vecdim}, a vector of non-repeating\n## dimensions, will return the @code{mad} over the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{mad} to operate\n## on all elements of @var{x}, and is equivalent to @code{mad (@var{x}(:))}.\n##\n## Usage Note: As a measure of dispersion, @code{mad} is less affected by\n## outliers than @code{std}.\n##\n## @seealso{bounds, range, iqr, std, mean, median}\n## @end deftypefn\n\nfunction m = mad (x, opt = 0, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    error (\"mad: X must be a numeric or logical array\");\n  endif\n\n  if (isempty (opt))\n    opt = 0;\n  elseif (! isscalar (opt) || (opt != 0 && opt != 1))\n    error (\"mad: OPT must be 0 or 1\");\n  endif\n\n  if (nargin < 3)\n    ## Dim not provided\n\n    ## First check for special empty case.\n    if (isempty (x) && ndims (x) == 2 && size (x) == [0, 0])\n      if (isa (x, \"single\"))\n        m = NaN (\"single\");\n      else\n        m = NaN;\n      endif\n      return;\n    endif\n\n    ## Then find the first non-singleton dimension.\n    (dim = find (size (x) != 1, 1)) || (dim = 1);\n  endif\n\n  if (opt == 0)\n    fcn = @mean;\n  else\n    fcn = @median;\n  endif\n\n  m = fcn (abs (x - fcn (x, dim, \"omitnan\")), dim, \"omitnan\");\n\nendfunction\n\n\n%!assert (mad (123), 0)\n%!assert (mad (Inf), NaN)\n%!assert (mad ([3, Inf]),Inf)\n%!assert (mad ([0, 0, 1, 2, 100]), 31.76)\n%!assert (mad (single ([0, 0, 1, 2, 100])), single (31.76))\n%!assert (mad ([0, 0, 1, 2, 100]'), 31.76)\n%!assert (mad ([0, 0, 1, 2, 100], 1), 1)\n%!assert (mad (single ([0, 0, 1, 2, 100]), 1), single (1))\n%!assert (mad ([0, 0, 1, 2, 100]', 1), 1)\n%!assert (mad (magic (4)), [4, 4, 4, 4])\n%!assert (mad (magic (4), [], 2), [6; 2; 2; 6])\n%!assert (mad (magic (4), 1), [2.5, 3.5, 3.5, 2.5])\n%!assert (mad (magic (4), 1, 2), [5.5; 1.5; 1.5; 5.5])\n%!assert (mad (magic (4), 0, 3), zeros (4))\n%!assert (mad (magic (4), 1, 3), zeros (4))\n%!assert (mad (cat (3, magic (4), magic (4))), 4 * ones (1, 4, 2))\n\n## Test all and vecdim options\n%!assert (mad (magic (4), 0, \"all\"), 4)\n%!assert (mad (magic (4), 1, \"all\"), 4)\n%!assert (mad (magic (4), 0, [1 2]), 4)\n%!assert (mad (magic (4), 0, [1 3]), mad (magic (4), 0, 1))\n%!assert (mad (magic (4), 0, [1 2 3]), 4)\n%!assert (mad (magic (4), 1, [1 2]), 4)\n%!assert (mad (magic (4), 1, [1 3]), mad (magic (4), 1, 1))\n%!assert (mad (magic (4), 1, [1 2 3]), 4)\n%!assert (mad (magic (4), 0, [3 4 99]), zeros (4))\n%!assert (mad (magic (4), 1, [3 4 99]), zeros (4))\n\n## Verify ignoring NaN values unless all NaN\n%!assert (mad (NaN), NaN)\n%!assert (mad (NaN (2)), NaN (1, 2))\n%!assert (mad ([1, 2; 3, NaN]), [1, 0])\n%!assert (mad ([1, 2; 3, NaN], [], 1), [1, 0])\n%!assert (mad ([1, 2; 3, NaN], [], 2), [0.5; 0], eps)\n%!assert (mad ([1, NaN; 3, NaN], [], 1), [1, NaN])\n%!assert (mad ([1, NaN; 3, NaN], [], 2), [0; 0])\n\n## Verify compatible empty handling\n%!assert (mad ([]), NaN)\n%!assert (mad ([], 0, 1), NaN (1,0))\n%!assert (mad ([], 0, 2), NaN (0,1))\n%!assert (mad ([], 0, 3), NaN (0,0))\n%!assert (mad (single ([])), NaN ('single'))\n%!assert (mad (ones (0, 1)), NaN)\n%!assert (mad (ones (0, 1), 0, 1), NaN (1, 1))\n%!assert (mad (ones (0, 1), 0, 2), NaN (0, 1))\n%!assert (mad (ones (0, 1), 0, 3), NaN (0, 1))\n%!assert (mad (ones (1, 0)), NaN)\n%!assert (mad (ones (1, 0), 0, 1), NaN (1, 0))\n%!assert (mad (ones (1, 0), 0, 2), NaN (1, 1))\n%!assert (mad (ones (1, 0), 0, 3), NaN (1, 0))\n%!assert (mad (ones (0, 0, 0)), NaN (1, 0, 0))\n%!assert (mad (ones (1, 0, 0)), NaN (1, 1, 0))\n%!assert (mad (ones (0, 1, 0)), NaN (1, 1, 0))\n%!assert (mad (ones (0, 0, 0)), NaN (1, 0, 0))\n%!assert (mad (ones (0, 1, 0), 0, 1), NaN (1, 1, 0))\n%!assert (mad (ones (0, 1, 0), 0, 2), NaN (0, 1, 0))\n%!assert (mad (ones (0, 1, 0), 0, 3), NaN (0, 1, 1))\n%!assert (mad (ones (0, 1, 0), 0, 4), NaN (0, 1, 0))\n%!assert (mad (ones (0, 2, 1, 0)), ones (1, 2, 1, 0))\n%!assert (mad (ones (2, 0, 1, 0)), ones (1, 0, 1, 0))\n\n## Test Inf handling\n%!assert (mad ([3, 4, Inf]), Inf)\n%!assert (mad ([Inf, 3, 4]), Inf)\n%!assert (mad ([3, 4, Inf], 0), Inf)\n%!assert (mad ([3, 4, Inf], 0, 1), [0, 0, NaN])\n%!assert (mad ([3, 4, Inf], 0, 2), Inf)\n%!assert (mad ([3, 4, Inf], 0, 3), [0, 0, NaN])\n%!assert (mad ([3, 4, Inf]', 0), Inf)\n%!assert (mad ([3, 4, Inf]', 0, 1), Inf)\n%!assert (mad ([3, 4, Inf]', 0, 2), [0; 0; NaN])\n%!assert (mad ([3, 4, Inf]', 0, 3), [0; 0; NaN])\n\n%!assert (mad ([Inf, 3, 4], 1), 1)\n%!assert (mad ([3, 4, Inf], 1), 1)\n%!assert (mad ([3, 4, Inf], 1, 1), [0, 0, NaN])\n%!assert (mad ([3, 4, Inf], 1, 2), 1)\n%!assert (mad ([3, 4, Inf], 1, 3), [0, 0, NaN])\n%!assert (mad ([3, 4, Inf]', 1), 1)\n%!assert (mad ([3, 4, Inf]', 1, 1), 1)\n%!assert (mad ([3, 4, Inf]', 1, 2), [0; 0; NaN])\n%!assert (mad ([3, 4, Inf]', 1, 3), [0; 0; NaN])\n\n%!assert (mad ([3, Inf, Inf], 1), Inf)\n%!assert (mad ([3, 4, 5, Inf], 1), 1)\n%!assert (mad ([3, 4, Inf, Inf], 1), Inf)\n%!assert (mad ([3, Inf, Inf, Inf], 1), Inf)\n\n%!assert <*65405> (mad ([-Inf, Inf]), NaN)\n%!assert <*65405> (mad ([-Inf, Inf], 0), NaN)\n%!assert <*65405> (mad ([-Inf, Inf], 1), NaN)\n%!assert <*65405> (mad ([-Inf, Inf]', 0), NaN)\n%!assert <*65405> (mad ([-Inf, Inf]', 1), NaN)\n%!assert <*65405> (mad ([-Inf, Inf]', 0, 1), NaN)\n%!assert <*65405> (mad ([-Inf, Inf]', 0, 2), [NaN; NaN])\n%!assert <*65405> (mad ([-Inf, Inf]', 0, 3), [NaN; NaN])\n%!assert <*65405> (mad ([-Inf, Inf]', 1, 1), NaN)\n%!assert <*65405> (mad ([-Inf, Inf]', 1, 2), [NaN; NaN])\n%!assert <*65405> (mad ([-Inf, Inf]', 1, 3), [NaN; NaN])\n%!assert <*65405> (mad (Inf (2), 0), [NaN, NaN])\n%!assert <*65405> (mad (Inf (2), 1), [NaN, NaN])\n%!assert <*65405> (mad (Inf (2), 0, 1), [NaN, NaN])\n%!assert <*65405> (mad (Inf (2), 0, 2), [NaN; NaN])\n%!assert <*65405> (mad (Inf (2), 0, 3), NaN (2))\n%!assert <*65405> (mad (Inf (2), 1, 1), [NaN, NaN])\n%!assert <*65405> (mad (Inf (2), 1, 2), [NaN; NaN])\n%!assert <*65405> (mad (Inf (2), 1, 3), NaN (2))\n\n## Test input case insensitivity\n%!assert (mad ([1 2 3], 0, \"aLL\"), 2/3, eps)\n%!assert (mad ([1 2 3], 1, \"aLL\"), 1)\n\n## Test input validation\n%!error <Invalid call> mad ()\n%!error <X must be a numeric or logical> mad (['A'; 'B'])\n%!error <OPT must be 0 or 1> mad (1, 2)\n"
  },
  {
    "path": "scripts/statistics/mape.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{E} =} mape (@var{F}, @var{A})\n## @deftypefnx {} {@var{E} =} mape (@var{F}, @var{A}, @var{dim})\n## @deftypefnx {} {@var{E} =} mape (@var{F}, @var{A}, @var{vecdim})\n## @deftypefnx {} {@var{E} =} mape (@var{F}, @var{A}, \"all\")\n## @deftypefnx {} {@var{E} =} mape (@dots{}, @var{nanflag})\n## @deftypefnx {} {@var{E} =} mape (@dots{}, @var{zeroflag})\n## @deftypefnx {} {@var{E} =} mape (@dots{}, @qcode{'Weights'}, @var{W})\n## Compute the mean absolute percentage error between arrays.\n##\n## The mean absolute percentage error is defined as\n## @tex\n## $$ {\\rm mape}(F, A) = {E} = {1\\over N} \\sum_{i=1}^N \\left| {A_i - F_i}\\over{A_i} \\right| \\times 100 $$\n## where $N$ is the number of elements in @var{F} and @var{A} after\n## broadcasting is applied to the subtraction operation.\n## @end tex\n## @ifnottex\n##\n## @example\n## mape (@var{F}, @var{A}) = SUM_i (abs ((@var{A}(i) - @var{F}(i)) / @var{A}(i))) * 100 / N\n## @end example\n##\n## @noindent\n## where @math{N} is the number of elements in @var{F} and @var{A} after\n## broadcasting is applied to the subtraction operation.\n##\n## @end ifnottex\n##\n## The weighted mean absolute percentage error is defined as\n## @tex\n## $$ {\\rm mape_w}(F, A) = {E_W} =  {{\\sum_{i=1}^N W_i\\left| {A_i - F_i}\\over{A_i} \\right| \\times 100} \\over {\\sum_{i=1}^N W_i}} $$\n## where $N$ is the number of elements in @var{F} and @var{A} after\n## broadcasting is applied to the subtraction operation.\n## @end tex\n## @ifnottex\n##\n## @example\n## weighted_mape (@var{F}, @var{A}) = SUM_i (@var{W}(i) * (abs ((@var{A}(i) - @var{F}(i)) / @var{A}(i)))) * 100 / SUM_i (@var{W}(i)\n## @end example\n##\n## @noindent\n## where @math{N} is the number of elements in @var{F} and @var{A} after\n## broadcasting is applied to the subtraction operation.\n##\n## @end ifnottex\n##\n## @var{F} and @var{A} must either be the same size or have compatible sizes.\n##\n## If @var{F} and @var{A} are vectors of the same size, then\n## @code{mape (@var{F}, @var{A})} returns a scalar with the MAPE between the\n## elements of @var{F} and @var{A}.\n##\n## If @code{@var{A} - @var{F}} is a matrix, then @code{mape (@var{F}, @var{A})}\n## returns a row vector with each element containing the MAPE between the\n## corresponding columns of @code{@var{A} - @var{F}}.\n##\n## If @code{@var{A} - @var{F}} is an array, then @code{mape (@var{F}, @var{A})}\n## computes the MAPE along the first non-singleton dimension of the difference\n## between the input arrays @var{F} and @var{A}.  The size of @var{E} along the\n## operating dimension is 1, while all other dimensions are the same as in\n## @code{@var{A} - @var{F}}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension, including any\n## dimension exceeding @code{ndims (@var{A} - @var{F})}, will return\n## @code{abs ((@var{A} - @var{F}) ./ @var{A})}.\n##\n## Specifying the dimensions as @var{vecdim}, a vector of non-repeating\n## dimensions, will return the mape over the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions in\n## @code{@var{A} - @var{F}}, then it is equivalent to the option @qcode{\"all\"}.\n## Any dimension in @var{vecdim} greater than @code{ndims (@var{A} - @var{F})}\n## is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{mape} to operate\n## on all elements of @code{@var{A} - @var{F}}, and is equivalent to\n## @code{mape ((@var{A} - @var{F})(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\n## NaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\n## will still contain NaN values if @code{@var{A} - @var{F}} consists of all\n## NaN values in the operating dimension.\n##\n## The optional variable @var{zeroflag} specifies whether to include or omit\n## zero values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{zeroflag} is\n## @qcode{\"includezero\"}, in which case the calculated MAPE is Inf, if @var{A}\n## contains one or more zeros.  To ignore any zero values in @var{A}, set the\n## value of @var{zeroflag} to @qcode{\"omitzero\"}.  If @var{A} consists of all\n## zero values in the operating dimension, then MAPE is NaN.\n##\n## The optional paired argument @code{@dots{}, \"Weights\", @var{W}} specifies a\n## weighting scheme @var{W}, which is applied on the difference of the input\n## arrays @var{F} and @var{A}, so that @code{mape} computes the weighted MAPE.\n## When operating along a single dimension, @var{W} must be a vector of the\n## same length as the operating dimension or it must have the same size as\n## @var{x}.  When operating over an array slice defined by @var{vecdim},\n## @var{W} must have the same size as the operating array slice, i.e.,\n## @code{size (@var{A} - @var{F})(@var{vecdim})}, or the same size as\n## @code{@var{A} - @var{F}}.\n##\n## @seealso{rmse, mean, abs}\n## @end deftypefn\n\nfunction E = mape (F, A, varargin)\n\n  if (nargin < 2 || nargin > 7)\n    print_usage ();\n  endif\n\n  if (! any (isa (F, {'double', 'single'})))\n    error (\"mape: F must be a floating point numeric array\");\n  endif\n\n  if (! any (isa (A, {'double', 'single'})))\n    error (\"mape: A must be a floating point numeric array\");\n  endif\n\n  ## Determine output class\n  if (isa (F, 'single') || isa (A, 'single'))\n    outtype = \"single\";\n    F = double (F);\n    A = double (A);\n  else\n    outtype = \"double\";\n  endif\n\n  ## Check F and A for compatible sizes\n  try\n    AF = A - F;\n  catch\n    error (\"mape: F and A must have compatible sizes\");\n  end_try_catch\n\n  ## Initialize flags\n  all_flag = false;\n  omitnan  = false;\n  zeroflag = false;\n  weighted = false;\n\n  ## Process paired argument for Weights\n  w_idx = find (cellfun (@(x) strcmpi (x, \"weights\"), varargin));\n  if (! isempty (w_idx))\n    if (numel (varargin) > w_idx)\n      W = varargin{w_idx+1};\n      if (! (isnumeric (W) && any (isa (W, {'double', 'single'}))))\n        error (\"mape: WEIGHTS must be single or double\");\n      endif\n      if (any (W(:) < 0))\n        error (\"mape: WEIGHTS must be nonnegative\");\n      endif\n    else\n      error (\"mape: paired input argument for 'Weights' is missing\");\n    endif\n    weighted = true;\n    varargin([w_idx, w_idx+1]) = [];\n  endif\n\n  nvarg = numel (varargin);\n  varg_chars = cellfun (\"ischar\", varargin);\n  sz_AF = size (AF);\n  nd_AF = ndims (AF);\n\n  ## Force A to the same size as AF\n  if (! isequal (size (A), sz_AF))\n    A = A .* ones (sz_AF);\n  endif\n\n  if (nvarg > 1 && ! varg_chars(2:end))\n    ## Only first varargin can be numeric\n    print_usage ();\n  endif\n\n  ## Process any other char arguments.\n  if (any (varg_chars))\n    for argin = varargin(varg_chars)\n      switch (lower (argin{:}))\n        case \"all\"\n          all_flag = true;\n\n        case \"omitnan\"\n          omitnan = true;\n\n        case \"includenan\"\n          omitnan = false;\n\n        case \"omitzero\"\n          zeroflag = true;\n\n        case \"includezero\"\n          zeroflag = false;\n\n        otherwise\n          print_usage ();\n\n      endswitch\n    endfor\n\n    varargin(varg_chars) = [];\n    nvarg = numel (varargin);\n  endif\n\n  if (nvarg == 1 && ! isnumeric (varargin{1}))\n    ## After trimming char inputs only one arg can be left, must be numeric.\n    print_usage ();\n  endif\n\n  ## Process special cases of input/output sizes.\n  if (nvarg == 0)\n    ## Single numeric input argument, no dimensions given.\n    if (all_flag)\n      AF = AF(:);\n      A = A(:);\n      n = numel (AF);\n\n      ## Process weights\n      if (weighted)\n        if (isvector (W))\n          if (numel (W) != n)\n            error (strcat (\"mape: WEIGHTS vector must have the same\", ...\n                           \" length as the operating dimension\"));\n          endif\n        elseif (! isequal (size (W), sz_AF))\n          error (strcat (\"mape: WEIGHTS array must have the same size as\", ...\n                         \" the difference of the input arrays F and A\"));\n        endif\n        W = W(:);\n        AF = W .* AF;\n        n = sum (W);\n      endif\n\n      ## Process omitnan\n      if (omitnan)\n        nanAF = isnan (AF);\n        AF(nanAF) = [];\n        if (weighted)\n          W(nanAF) = [];\n          n = sum (W);\n        else\n          n = numel (AF);\n        endif\n      endif\n\n      ## Process zeroflag\n      if (zeroflag)\n        iszero = A == 0;\n        if (any (iszero, \"all\"))\n          A(iszero) = 1;\n          AF(iszero) = 0;\n          if (weighted)\n            W(iszero) = 0;\n            n = sum (W);\n          else\n            n = n - sum (iszero);\n          endif\n        endif\n      endif\n\n      E = sum (abs (AF ./ A), \"extra\") ./ n;\n\n    else\n      ## Handle 0x0 empty input, no dimensions given\n      if (nd_AF == 2 && isempty (AF) && sz_AF == [0,0])\n        if (isa (AF, \"single\"))\n          E = NaN (\"single\");\n        else\n          E = NaN;\n        endif\n        return;\n      endif\n\n      ## Find the first non-singleton dimension.\n      (dim = find (sz_AF != 1, 1)) || (dim = 1);\n      n = sz_AF(dim);\n\n      ## Process weights\n      if (weighted)\n        if (isequal (size (W), sz_AF))\n          AF = W .* AF;\n        elseif (isvector (W))\n          if (numel (W) != n)\n            error (strcat (\"mape: WEIGHTS vector must have the same\", ...\n                           \" length as the operating dimension\"));\n          endif\n          sz_W = ones (1, nd_AF);\n          sz_W(dim) = n;\n          W = reshape (W, sz_W);\n          if (! isvector (AF))\n            sz_W = sz_AF;\n            sz_W(dim) = 1;\n            W = repmat (W, sz_W);\n          endif\n          AF = W .* AF;\n        else\n          error (strcat (\"mape: WEIGHTS array must have the same size as\", ...\n                         \" the difference of the input arrays F and A\"));\n        endif\n        n = sum (W, dim);\n      endif\n\n      ## Process omitnan\n      if (omitnan)\n        nanAF = isnan (AF);\n        AF(nanAF) = 0;\n        if (weighted)\n          W(nanAF) = 0;\n          n = sum (W, dim);\n        else\n          n = sum (! nanAF, dim);\n        endif\n      endif\n\n      ## Process zeroflag\n      if (zeroflag)\n        iszero = A == 0;\n        if (any (iszero, \"all\"))\n          A(iszero) = 1;\n          AF(iszero) = 0;\n          if (weighted)\n            W(iszero) = 0;\n            n = sum (W, dim);\n          else\n            n = n - sum (iszero, dim);\n          endif\n        endif\n      endif\n\n      E = sum (abs (AF ./ A), dim, \"extra\") ./ n;\n\n    endif\n\n  else\n    ## Two numeric input arguments, dimensions given.  Note scalar is vector!\n    vecdim = varargin{1};\n    if (isempty (vecdim) || ! (isvector (vecdim) && isindex (vecdim)))\n      error (\"mape: DIM must be a positive integer scalar or vector\");\n    endif\n\n    if (isscalar (vecdim))\n      dim = vecdim;  # alias for code readability\n\n      if (dim > nd_AF)\n\n        ## Process weights\n        if (weighted)\n          if (! isequal (size (W), sz_AF))\n             error (strcat (\"mape: WEIGHTS array must have the same size\", ...\n                            \" as 'A - F', when 'DIM > ndims (A - F)'\"));\n          endif\n        endif\n\n        ## Process zeroflag\n        if (zeroflag)\n          iszero = A == 0;\n          if (any (iszero, \"all\"))\n            A(iszero) = 1;\n            AF(iszero) = NaN;\n          endif\n        endif\n\n        E = abs (AF ./ A);\n\n      else\n        n = sz_AF(dim);\n\n        ## Process weights\n        if (weighted)\n          if (isequal (size (W), sz_AF))\n            AF = W .* AF;\n          elseif (isvector (W))\n            if (numel (W) != n)\n              error (strcat (\"mape: WEIGHTS vector must have the same\", ...\n                             \" length as the operating dimension\"));\n            endif\n            sz_W = ones (1, nd_AF);\n            sz_W(dim) = n;\n            W = reshape (W, sz_W);\n            if (! isvector (AF))\n              sz_W = sz_AF;\n              sz_W(dim) = 1;\n              W = repmat (W, sz_W);\n            endif\n            AF = W .* AF;\n          else\n          error (strcat (\"mape: WEIGHTS array must have the same size as\", ...\n                         \" the difference of the input arrays F and A\"));\n          endif\n          n = sum (W, dim);\n        endif\n\n        ## Process omitnan\n        if (omitnan)\n          nanAF = isnan (AF);\n          AF(nanAF) = 0;\n          if (weighted)\n            W(nanAF) = 0;\n            n = sum (W, dim);\n          else\n            n = sum (! nanAF, dim);\n          endif\n        endif\n\n        ## Process zeroflag\n        if (zeroflag)\n          iszero = A == 0;\n          if (any (iszero, \"all\"))\n            A(iszero) = 1;\n            AF(iszero) = 0;\n            if (weighted)\n              W(iszero) = 0;\n              n = sum (W, dim);\n            else\n              n = n - sum (iszero, dim);\n            endif\n          endif\n        endif\n\n        E = sum (abs (AF ./ A), dim, \"extra\") ./ n;\n\n      endif\n\n    else\n      vecdim = sort (vecdim);\n      if (! all (diff (vecdim)))\n        error (\"mape: VECDIM must contain non-repeating positive integers\");\n      endif\n      ## Ignore dimensions in VECDIM larger than actual array.\n      vecdim(vecdim > nd_AF) = [];\n\n      if (isempty (vecdim))\n\n        ## Process weights\n        if (weighted)\n          if (! isequal (size (W), sz_AF))\n             error (strcat (\"mape: WEIGHTS array must have the same size\", ...\n                            \" as 'A - F', when 'all (VECDIM > ndims (A - F))'\"));\n          endif\n        endif\n\n        ## Process zeroflag\n        if (zeroflag)\n          iszero = A == 0;\n          if (any (iszero, \"all\"))\n            A(iszero) = 1;\n            AF(iszero) = NaN;\n          endif\n        endif\n\n        E = abs (AF ./ A);\n\n      else\n\n        ## Calculate permutation vector\n        remdims = 1:nd_AF;       # All dimensions\n        remdims(vecdim) = [];  # Delete dimensions specified by vecdim\n        nremd = numel (remdims);\n\n        ## If all dimensions are given, it is equivalent to 'all' flag\n        if (nremd == 0)\n          AF = AF(:);\n          A = A(:);\n          n = numel (AF);\n\n          ## Process weights\n          if (weighted)\n            if (isvector (W))\n              if (numel (W) != n)\n                error (strcat (\"mape: WEIGHTS vector must have the same\", ...\n                               \" length as the operating dimension\"));\n              endif\n            elseif (! isequal (size (W), sz_AF))\n              error (strcat (\"mape: WEIGHTS array must have the same size\", ...\n                             \" as the difference of the input arrays F and A\"));\n            endif\n            W = W(:);\n            AF = W .* AF;\n            n = sum (W);\n          endif\n\n          ## Process omitnan\n          if (omitnan)\n            nanAF = isnan (AF);\n            AF(nanAF) = [];\n            if (weighted)\n              W(nanAF) = [];\n              n = sum (W);\n            else\n              n = numel (AF);\n            endif\n          endif\n\n          ## Process zeroflag\n          if (zeroflag)\n            iszero = A == 0;\n            if (any (iszero, \"all\"))\n              A(iszero) = 1;\n              AF(iszero) = 0;\n              if (weighted)\n                W(iszero) = 0;\n                n = sum (W);\n              else\n                n = n - sum (iszero);\n              endif\n            endif\n          endif\n\n          E = sum (abs (AF ./ A), \"extra\") ./ n;\n\n        else\n          ## Weights must either match vecdim page size or the size of F - A\n          if (weighted)\n            page_szw = size (W);\n            if (isequal (size (W), sz_AF))\n              AF = W .* AF;\n            elseif (isequal (page_szw, sz_AF(vecdim)))\n              ## Make W to be compatible with AF\n              tmp = ones (1, nd_AF);\n              tmp(vecdim) = page_szw;\n              W = reshape (W, tmp);\n              W = W .* ones (sz_AF);\n              AF = W .* AF;\n            else\n              error (strcat (\"mape: WEIGHTS array must have the same size\", ...\n                             \" as the operating page specified by VECDIM\", ...\n                             \" or the difference of the input arrays F and A\"));\n            endif\n          endif\n\n          ## Permute to push vecdims to back\n          perm = [remdims, vecdim];\n          AF = permute (AF, perm);\n          A = permute (A, perm);\n          if (weighted)\n            W = permute (W, perm);\n          endif\n\n          ## Reshape to squash all vecdims in final dimension\n          sznew = [sz_AF(remdims), prod(sz_AF(vecdim))];\n          AF = reshape (AF, sznew);\n          A = reshape (A, sznew);\n          if (weighted)\n            W = reshape (W, sznew);\n          endif\n\n          ## Calculate mape on final dimension\n          dim = nremd + 1;\n\n          ## Process omitnan\n          if (omitnan)\n            nanAF = isnan (AF);\n            AF(nanAF) = 0;\n            if (weighted)\n              W(nanAF) = 0;\n              n = sum (W, dim);\n            else\n              n = sum (! nanAF, dim);\n            endif\n          else\n            if (weighted)\n              n = sum (W, dim);\n            else\n              n = sznew(dim);\n            endif\n          endif\n\n          ## Process zeroflag\n          if (zeroflag)\n            iszero = A == 0;\n            if (any (iszero, \"all\"))\n              A(iszero) = 1;\n              AF(iszero) = 0;\n              if (weighted)\n                W(iszero) = 0;\n                n = sum (W, dim);\n              else\n                n = n - sum (iszero, dim);\n              endif\n            endif\n          endif\n\n          E = sum (abs (AF ./ A), dim, \"extra\") ./ n;\n\n          ## Inverse permute back to correct dimensions\n          E = ipermute (E, perm);\n\n        endif\n      endif\n    endif\n  endif\n\n  ## Multiply by 100 to complete the equation\n  E = E * 100;\n\n  ## Convert output if necessary\n  if (strcmp (outtype, 'single'))\n    E = single (E);\n  endif\n\nendfunction\n\n## Test inputs with NaN and zeros\n%!test\n%! F = [2, 11, 6];\n%! A = [3, 10, 8];\n%! assert (mape (F, A), 22.7778, 1e-4);\n%! assert (mape (F, A, 1), [33.3333, 10.0000, 25.0000], 1e-4);\n%! assert (mape (F, A, 2), 22.7778, 1e-4);\n%! assert (mape (F, A, 3), [33.3333, 10.0000, 25.0000], 1e-4);\n%! assert (mape (F, A, 'all'), 22.7778, 1e-4);\n%!test\n%! F = [3; 7; 4; NaN];\n%! A = [4; 0; 6; 4];\n%! assert (mape (F, A), NaN);\n%! assert (mape (F, A, 'omitnan'), Inf);\n%! assert (mape (F, A, 'omitzero'), NaN);\n%! assert (mape (F, A, 'omitnan', 'omitzero'), 29.1667, 1e-4);\n%! assert (mape (F, A, 1, 'omitnan', 'omitzero'), 29.1667, 1e-4);\n%! E = mape (F, A, 2, 'omitnan', 'omitzero');\n%! assert (E, [25; NaN; 33.3333; NaN], 1e-4);\n%!test\n%! F = [17, 21; 1, 5; 13, 17];\n%! A = [18, 19; 5, 4; 15, 13];\n%! assert (mape (F, A), [32.9630, 22.0985], 1e-4);\n%! assert (mape (F, A, 1), [32.9630, 22.0985], 1e-4);\n%! assert (mape (F, A, 2), [8.0409; 52.5000; 22.0513], 1e-4);\n%! assert (mape (F, A, 'all'), 27.5307, 1e-4);\n%! assert (mape (F, A, [1, 2]), 27.5307, 1e-4);\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, 2; 7, -4];\n%! A = [6, 5; 0, 3];\n%! E = mape (F, A, [1, 2]);\n%! assert (E(:,:,1), Inf);\n%! assert (E(:,:,2), Inf);\n%! E = mape (F, A, [1, 2], 'omitzero');\n%! assert (E(:,:,1), 27.7778, 1e-4);\n%! assert (E(:,:,2), 108.8889, 1e-4);\n%! assert (mape (F, A, [1, 3]), [Inf, 81.6667], 1e-4);\n%! assert (mape (F, A, [1, 3], 'omitzero'), [41.6667, 81.6667], 1e-4);\n%! assert (mape (F, A, [2, 3]), [35.8333; Inf], 1e-4);\n%! assert (mape (F, A, [2, 3], 'omitzero'), [35.8333; 133.3333], 1e-4);\n%!assert (mape ([1:4], zeros (1, 4)), Inf)\n%!assert (mape ([1:4], zeros (1, 4), \"omitzero\"), NaN)\n\n## Test Weights\n%!test\n%! F = [2, 11, 6];\n%! A = [3, 10, 8];\n%! W = [1, 2, 1];\n%! assert (mape (F, A, 'Weights', W), 19.5833, 1e-4);\n%! assert (mape (F, A, 1, 'Weights', W), [33.3333, 10, 25], 1e-4);\n%! assert (mape (F, A, 2, 'Weights', W), 19.5833, 1e-4);\n%! assert (mape (F, A, 3, 'Weights', W), [33.3333, 10, 25], 1e-4);\n%!test\n%! F = [3; 7; 4; NaN];\n%! A = [4; 0; 6; 4];\n%! W = [1, 2, 1, 2];\n%! assert (mape (F, A, 'Weights', W), NaN);\n%! assert (mape (F, A, 'omitnan', 'Weights', W), Inf);\n%! assert (mape (F, A, 'omitzero', 'Weights', W), NaN);\n%! assert (mape (F, A, 'omitnan', 'omitzero', 'Weights', W), 29.1667, 1e-4);\n%! assert (mape (F, A, 1, 'omitnan', 'omitzero', 'Weights', W), 29.1667, 1e-4);\n%!test\n%! F = [3; 7; 4; NaN];\n%! A = [4; 0; 6; 4];\n%! W = [1; 2; 1; 2];\n%! E = mape (F, A, 2, 'omitnan', 'omitzero', 'Weights', W);\n%! assert (E, [25; NaN; 33.3333; NaN], 1e-4);\n%! E = mape (F, A, 3, 'omitnan', 'omitzero', 'Weights', W);\n%! assert (E, [25; NaN; 33.3333; NaN], 1e-4);\n%!test\n%! F = [3; 7; 4; NaN];\n%! A = [4; 0; 6; 4];\n%! W = [1; 1; 2; 2];\n%! E = mape (F, A, 2, 'omitnan', 'omitzero', 'Weights', W);\n%! assert (E, [25; NaN; 33.3333; NaN], 1e-4);\n%! E = mape (F, A, 3, 'omitnan', 'omitzero', 'Weights', W);\n%! assert (E, [25; NaN; 33.3333; NaN], 1e-4);\n%! E = mape (F, A, 3, 'omitzero', 'Weights', W);\n%! assert (E, [25; NaN; 33.3333; NaN], 1e-4);\n%! E = mape (F, A, 3, 'omitnan', 'Weights', W);\n%! assert (E, [25; Inf; 33.3333; NaN], 1e-4);\n%! assert (mape (F, A, 3, 'Weights', W), [25; Inf; 33.3333; NaN], 1e-4);\n%! assert (mape (F, A, 3), [25; Inf; 33.3333; NaN], 1e-4);\n%!test\n%! F = [3; 7; 4; NaN];\n%! A = [4; 0; 6; 4];\n%! W = [1; 1; 2; 2];\n%! assert (mape (F, A, 1, 'omitnan', 'omitzero', 'Weights', W), 30.5556, 1e-4);\n%! assert (mape (F, A, 1, 'omitzero', 'Weights', W), NaN);\n%! assert (mape (F, A, 1, 'omitnan', 'Weights', W), Inf);\n%! assert (mape (F, A, 1, 'Weights', W), NaN);\n%! assert (mape (F, A, 1), NaN);\n%!test\n%! F = [3, 4; 7, 5; 4, 3; NaN, 8];\n%! A = [4; 0; 6; 4];\n%! W = [3; 1; 2; 2];\n%! E = mape (F, A, 1, 'omitnan', 'omitzero', 'Weights', W);\n%! assert (E, [28.3333, 42.8571], 1e-4);\n%! E = mape (F, A, 1, 'omitzero', 'Weights', W);\n%! assert (E, [NaN, 42.8571], 1e-4);\n%! assert (mape (F, A, 1, 'omitnan', 'Weights', W), [Inf, Inf]);\n%! assert (mape (F, A, 1, 'Weights', W), [NaN, Inf]);\n%!test\n%! F = [3, 4; 7, 5; 4, 3; NaN, 8];\n%! A = [4; 0; 6; 4];\n%! W = [3, 0.4; 1, 0.2; 2, 0.2; 2, 0.2];\n%! E = mape (F, A, 1, 'omitnan', 'omitzero', 'Weights', W);\n%! assert (E, [28.3333, 37.5000], 1e-4);\n%! E = mape (F, A, 1, 'omitzero', 'Weights', W);\n%! assert (E, [NaN, 37.5000], 1e-4);\n%! assert (mape (F, A, 1, 'omitnan', 'Weights', W), [Inf, Inf]);\n%! assert (mape (F, A, 1, 'Weights', W), [NaN, Inf]);\n\n## Test Weights with VECDIM\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, 2; 7, -4];\n%! A = [6, 5; 0, 3];\n%! W = [1, 1; 1, 1];\n%! Ew = mape (F, A, [1, 2], 'omitzero', 'Weights', W);\n%! E = mape (F, A, [1, 2], 'omitzero');\n%! assert (Ew, E);\n%! Ew = mape (F, A, [1, 3], 'omitzero', 'Weights', W);\n%! E = mape (F, A, [1, 3], 'omitzero');\n%! assert (Ew, E);\n%! Ew = mape (F, A, [2, 3], 'omitzero', 'Weights', W);\n%! E = mape (F, A, [2, 3], 'omitzero');\n%! assert (Ew, E);\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, NaN; 7, -4];\n%! A = [6, 5; 2, 3];\n%! W = [1, 1; 1, 1];\n%! Ew = mape (F, A, [1, 2], 'omitnan', 'Weights', W);\n%! E = mape (F, A, [1, 2], 'omitnan');\n%! assert (Ew, E);\n%! Ew = mape (F, A, [1, 3], 'omitnan','Weights', W);\n%! E = mape (F, A, [1, 3], 'omitnan');\n%! assert (Ew, E);\n%! Ew = mape (F, A, [2, 3], 'omitnan','Weights', W);\n%! E = mape (F, A, [2, 3], 'omitnan');\n%! assert (Ew, E);\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, 2; 7, -4];\n%! A = [6, 5; 0, 3];\n%! W = [1, 2; 1, 1];\n%! F1 = reshape (F, 1, 4, 2);\n%! A1 = reshape (A, 1, 4);\n%! W1 = reshape (W, 1, 4);\n%! E1w = mape (F1, A1, 2, 'omitzero', 'Weights', W1);\n%! assert (E1w(:,:,1), 20.8333, 1e-4);\n%! assert (E1w(:,:,2), 96.6667, 1e-4);\n%! E1 = mape (F1, A1, 2, 'omitzero');\n%! assert (E1(:,:,1), 27.7778, 1e-4);\n%! assert (E1(:,:,2), 108.8889, 1e-4);\n%! assert (mape (F, A, [1, 2], 'omitzero', 'Weights', W), E1w);\n%! assert (mape (F, A, [1, 2], 'omitzero'), E1);\n%! E1w = mape (F1, A1, 2, 'Weights', W1);\n%! assert (E1w(:,:,1), Inf);\n%! assert (E1w(:,:,2), Inf);\n%! E1 = mape (F1, A1, 2);\n%! assert (E1(:,:,1), Inf);\n%! assert (E1(:,:,2), Inf);\n%! assert (mape (F, A, [1, 2], 'Weights', W), E1w);\n%! assert (mape (F, A, [1, 2]), E1);\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, 2; 7, -4];\n%! A = [6, 5; 0, 3];\n%! W = [0.5, 2; 1, 3];\n%! F1 = reshape (F, 2, 4, 1);\n%! A1 = reshape (repmat (A, 1, 1, 2), 2, 4, 1);\n%! W1 = [0.5, 1, 2, 3; 0.5, 1, 2, 3];\n%! E1w = mape (F1, A1, 2, 'omitzero', 'Weights', W1);\n%! assert (E1w, [41.7949; 183.3333], 1e-4);\n%! E1 = mape (F1, A1, 2, 'omitzero');\n%! assert (E1, [35.8333; 133.3333], 1e-4);\n%! assert (mape (F, A, [2, 3], 'omitzero', 'Weights', W), E1w);\n%! assert (mape (F, A, [2, 3], 'omitzero'), E1);\n%! E1w = mape (F1, A1, 2, 'Weights', W1);\n%! assert (E1w, [41.7949; Inf], 1e-4);\n%! E1 = mape (F1, A1, 2);\n%! assert (E1, [35.8333; Inf], 1e-4);\n%! assert (mape (F, A, [2, 3], 'Weights', W), E1w);\n%! assert (mape (F, A, [2, 3]), E1);\n\n\n## Test input validation\n%!error <Invalid call> mape ()\n%!error <Invalid call> mape (1)\n%!error <Invalid call> mape (1, 2, 3, 4, 5, 6, 7, 8)\n%!error <F must be a floating point numeric array> mape ({1:5}, [1:5])\n%!error <F must be a floating point numeric array> mape (int32 ([1:5]), [1:5])\n%!error <A must be a floating point numeric array> mape ([1:5], {1:5})\n%!error <A must be a floating point numeric array> mape ([1:5], int32 ([1:5]))\n%!error <WEIGHTS must be single or double> mape ([1:5], [1:5], 'Weights', 'double')\n%!error <WEIGHTS must be single or double> mape ([1:5], [1:5], 'Weights', uint8 (1))\n%!error <WEIGHTS must be nonnegative> mape ([1:5], [1:5], 'Weights', -1)\n%!error <paired input argument for 'Weights' is missing> mape ([1:5], [1:5], 'Weights')\n%!error <Invalid call> mape ([1:5], [1:5], 2, 3)\n%!error <Invalid call> mape ([1:5], [1:5], \"all\", 3)\n%!error <Invalid call> mape ([1:5], [1:5], 'foobar')\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mape ([1:5], [1:5], \"all\", 'Weights', [1, 2, 3])\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mape ([1:5], 1, \"all\", 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! mape (ones (5, 3), ones (5, 3), \"all\", 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! mape (ones (5, 3), ones (1, 3), \"all\", 'Weights', ones (3, 5))\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mape ([1:5], [1:5], 'Weights', [1, 2, 3])\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mape ([1:5], 1, 'Weights', [1, 2, 3])\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mape (ones (5, 3), ones (5, 3), 'Weights', [1, 2, 3])\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mape (ones (5, 3), ones (5, 1), 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! mape (ones (5, 3), ones (5, 3), 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! mape (ones (5, 3), ones (1, 3), 'Weights', ones (3, 5))\n%!error <DIM must be a positive integer> mape ([1:5], [1:5], ones (2,2))\n%!error <DIM must be a positive integer> mape ([1:5], [1:5], 1.5)\n%!error <DIM must be a positive integer> mape ([1:5], [1:5], 0)\n%!error <DIM must be a positive integer> mape ([1:5], [1:5], [])\n%!error <DIM must be a positive integer> mape ([1:5], [1:5], -1)\n%!error <DIM must be a positive integer> mape ([1:5], [1:5], -1.5)\n%!error <DIM must be a positive integer> mape ([1:5], [1:5], NaN)\n%!error <DIM must be a positive integer> mape ([1:5], [1:5], Inf)\n%!error <DIM must be a positive integer> mape (repmat ([1:5;5:9], [5 2]), repmat ([1:5;5:9], [5 2]), -1)\n%!error <DIM must be a positive integer> mape (repmat ([1:5;5:9], [5 2]), repmat ([1:5;5:9], [5 2]), [1 -1])\n%!error <DIM must be a positive integer> mape ([1:5], [1:5], ones (1,0))\n%!error <WEIGHTS array must have the same size as 'A - F', when 'DIM> ...\n%! mape (ones (5, 1), ones (5, 1), 3, 'Weights', ones (1, 5))\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mape ([1:5], [1:5], 2, 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! mape (ones (5, 3), ones (5, 3), 2, 'Weights', ones (3, 5))\n%!error <VECDIM must contain non-repeating> mape ([1:5], [1:5], [2 2])\n%!error <WEIGHTS array must have the same size as 'A - F', when 'all> ...\n%! mape (ones (5, 1), ones (5, 1), [3, 4], 'Weights', ones (1, 5))\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mape ([1:5], [1:5], [1, 2], 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! mape (ones (5, 3), ones (5, 3), [1, 2], 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! mape (ones (5, 3), ones (1, 3), [1, 2], 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the operating page> ...\n%! mape (ones (5, 3, 2), ones (5, 3, 2), [1, 2], 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the operating page> ...\n%! mape (ones (5, 3, 2), ones (5, 1, 2), [1, 2], 'Weights', ones (3, 5))\n"
  },
  {
    "path": "scripts/statistics/mean.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{m} =} mean (@var{x})\n## @deftypefnx {} {@var{m} =} mean (@var{x}, @var{dim})\n## @deftypefnx {} {@var{m} =} mean (@var{x}, @var{vecdim})\n## @deftypefnx {} {@var{m} =} mean (@var{x}, \"all\")\n## @deftypefnx {} {@var{m} =} mean (@dots{}, @var{nanflag})\n## @deftypefnx {} {@var{m} =} mean (@dots{}, @var{outtype})\n## @deftypefnx {} {@var{m} =} mean (@dots{}, @qcode{'Weights'}, @var{w})\n## Compute the mean of the elements of @var{x}.\n##\n## The mean is defined as\n## @tex\n## $$ {\\rm mean}(x) \\equiv \\bar{x} = {1\\over N} \\sum_{i=1}^N x_i $$\n## where $N$ is the number of elements of @var{x}.\n## @end tex\n## @ifnottex\n##\n## @example\n## mean (@var{x}) = SUM_i @var{x}(i) / N\n## @end example\n##\n## @noindent\n## where @math{N} is the number of elements in @var{x}.\n##\n## @end ifnottex\n##\n## The weighted mean is defined as\n## @tex\n## $$ {\\rm mean_w}(x) \\equiv \\bar{x}_w = {\\sum_{i=1}^N w_i x_i \\over \\sum_{i=1}^N w_i} $$\n## where $N$ is the number of elements of @var{x}.\n## @end tex\n## @ifnottex\n##\n## @example\n## weighted_mean (@var{x}) = SUM_i (@var{w}(i) * @var{x}(i)) / SUM_i (@var{w}(i))\n## @end example\n##\n## @noindent\n## where @math{N} is the number of elements in @var{x}.\n##\n## @end ifnottex\n##\n## If @var{x} is a vector, then @code{mean (@var{x})} returns the mean of the\n## elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{mean (@var{x})} returns a row vector with\n## each element containing the mean of the corresponding column in @var{x}.\n##\n## If @var{x} is an array, then @code{mean (@var{x})} computes the mean along\n## the first non-singleton dimension of @var{x}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @var{x}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{mean} to operate\n## on all elements of @var{x}, and is equivalent to @code{mean (@var{x}(:))}.\n##\n## The optional input @var{outtype} specifies the data type that is returned.\n## @var{outtype} can take the following values:\n##\n## @table @asis\n## @item @qcode{'default'}\n## Output is of type double, unless the input is single in which case the\n## output is of type single.\n##\n## @item @qcode{'double'}\n## Output is of type double.\n##\n## @item @qcode{'native'}\n## Output is of the same type as the input as reported by\n## @code{class (@var{x})}, unless the input is logical in which case the output\n## is of type double.\n## @end table\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\n## NaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\n## will still contain NaN values if @var{x} consists of all NaN values in the\n## operating dimension.\n##\n## The optional argument pair @code{\"Weights\", @var{w}} specifies a weighting\n## scheme @var{w}, which is applied on input @var{x}, so that @code{mean}\n## computes the weighted mean.  When operating along a single dimension,\n## @var{w} must be a vector of the same length as the operating dimension or it\n## must have the same size as @var{x}.  When operating over an array slice\n## defined by @var{vecdim}, @var{w} must have the same size as the operating\n## array slice, i.e., @code{size (w) == size (@var{x})(@var{vecdim})}, or the\n## same size as @var{x}.\n##\n## @seealso{median, mode, movmean}\n## @end deftypefn\n\nfunction m = mean (x, varargin)\n\n  if (nargin < 1 || nargin > 6)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    error (\"mean: X must be a numeric or logical array\");\n  endif\n\n  ## Initialize flags\n  all_flag = false;\n  omitnan  = false;\n  out_flag = false;\n  weighted = false;\n\n  ## Process paired argument for Weights\n  w_idx = find (cellfun (@(x) strcmpi (x, \"weights\"), varargin));\n  if (! isempty (w_idx))\n    if (numel (varargin) > w_idx)\n      w = varargin{w_idx+1};\n      if (! (isnumeric (w) && any (isa (w, {'double', 'single'}))))\n        error (\"mean: WEIGHTS must be single or double\");\n      endif\n      if (any (w(:) < 0))\n        error (\"mean: WEIGHTS must be nonnegative\");\n      endif\n    else\n      error (\"mean: paired input argument for 'Weights' is missing\");\n    endif\n    weighted = true;\n    varargin([w_idx, w_idx+1]) = [];\n  endif\n\n  nvarg = numel (varargin);\n  varg_chars = cellfun (\"ischar\", varargin);\n  outtype = \"default\";\n  szx = size (x);\n  ndx = ndims (x);\n\n  if (nvarg > 1 && ! varg_chars(2:end))\n    ## Only first varargin can be numeric\n    print_usage ();\n  endif\n\n  ## Process any other char arguments.\n  if (any (varg_chars))\n    for argin = varargin(varg_chars)\n      switch (lower (argin{:}))\n        case \"all\"\n          all_flag = true;\n\n        case \"omitnan\"\n          omitnan = true;\n\n        case \"includenan\"\n          omitnan = false;\n\n        case \"default\"\n          if (out_flag)\n            error (\"mean: only one OUTTYPE can be specified\");\n          endif\n          if (isa (x, \"single\"))\n            outtype = \"single\";\n          else\n            outtype = \"double\";\n          endif\n          out_flag = true;\n\n        case \"native\"\n          if (out_flag)\n            error (\"mean: only one OUTTYPE can be specified\");\n          endif\n          outtype = class (x);\n          if (strcmp (outtype, \"logical\"))\n            outtype = \"double\";\n          endif\n          out_flag = true;\n\n        case \"double\"\n          if (out_flag)\n            error (\"mean: only one OUTTYPE can be specified\");\n          endif\n          outtype = \"double\";\n          out_flag = true;\n\n        otherwise\n          print_usage ();\n\n      endswitch\n    endfor\n\n    varargin(varg_chars) = [];\n    nvarg = numel (varargin);\n  endif\n\n  if (strcmp (outtype, \"default\"))\n    if (isa (x, \"single\"))\n      outtype = \"single\";\n    else\n      outtype = \"double\";\n    endif\n  endif\n\n  if (nvarg == 1 && ! isnumeric (varargin{1}))\n    ## After trimming char inputs only one arg can be left, must be numeric.\n    print_usage ();\n  endif\n\n  ## Process special cases of input/output sizes.\n  if (nvarg == 0)\n    ## Single numeric input argument, no dimensions given.\n    if (all_flag)\n      x = x(:);\n      n = numel (x);\n\n      ## Process weights\n      if (weighted)\n        if (isvector (w))\n          if (numel (w) != n)\n            error (strcat (\"mean: WEIGHTS vector must have the same\", ...\n                           \" length as the operating dimension\"));\n          endif\n        elseif (! isequal (size (w), szx))\n          error (\"mean: WEIGHTS array must have the same size as X\");\n        endif\n        w = w(:);\n        n = sum (w);\n      endif\n\n      ## Process omitnan\n      if (omitnan)\n        nanx = isnan (x);\n        x(nanx) = [];\n        if (weighted)\n          w(nanx) = [];\n          n = sum (w);\n        else\n          n = numel (x);\n        endif\n      endif\n\n      if (any (isa (x, {\"int64\", \"uint64\"})))\n        m = int64_mean (x, 1, n, outtype);\n      else\n        if (weighted)\n          m = robust_mean_sum (x, 1, n, w);\n        else\n          m = robust_mean_sum (x, 1, n);\n        endif\n      endif\n\n    else\n      ## Handle 0x0 empty input, no dimensions given\n      if (ndx == 2 && isempty (x) && szx == [0,0])\n        if (isa (x, \"single\"))\n          m = NaN (\"single\");\n        else\n          m = NaN;\n        endif\n        return;\n      endif\n\n      ## Find the first non-singleton dimension.\n      (dim = find (szx != 1, 1)) || (dim = 1);\n      n = szx(dim);\n\n      ## Process weights\n      if (weighted)\n        if (isequal (size (w), szx))\n          ## w already has the right shape\n        elseif (isvector (w))\n          if (numel (w) != n)\n            error (strcat (\"mean: WEIGHTS vector must have the same\", ...\n                           \" length as the operating dimension\"));\n          endif\n          szw = ones (1, ndx);\n          szw(dim) = n;\n          w = reshape (w, szw);\n          if (! isvector (x))\n            szw = szx;\n            szw(dim) = 1;\n            w = repmat (w, szw);\n          endif\n        else\n          error (\"mean: WEIGHTS array must have the same size as X\");\n        endif\n        n = sum (w, dim);\n      endif\n\n      ## Process omitnan\n      if (omitnan)\n        nanx = isnan (x);\n        x(nanx) = 0;\n        if (weighted)\n          w(nanx) = 0;\n          n = sum (w, dim);\n        else\n          n = sum (! nanx, dim);\n        endif\n      endif\n\n      if (any (isa (x, {\"int64\", \"uint64\"})))\n        m = int64_mean (x, dim, n, outtype);\n      else\n        if (weighted)\n          m = robust_mean_sum (x, dim, n, w);\n        else\n          m = robust_mean_sum (x, dim, n);\n        endif\n      endif\n\n    endif\n\n  else\n    ## Two numeric input arguments, dimensions given.  Note scalar is vector!\n    vecdim = varargin{1};\n    if (isempty (vecdim) || ! (isvector (vecdim) && isindex (vecdim)))\n      error (\"mean: DIM must be a positive integer scalar or vector\");\n    endif\n\n    if (isscalar (vecdim))\n      dim = vecdim;  # alias for code readability\n\n      if (dim > ndx)\n\n        ## Process weights\n        if (weighted)\n          if (! isequal (size (w), szx))\n             error (strcat (\"mean: WEIGHTS array must have the same size\", ...\n                            \" as X, when 'DIM > ndims (X)'\"));\n          endif\n        endif\n\n        m = x;\n\n      else\n        n = szx(dim);\n\n        ## Process weights\n        if (weighted)\n          if (isequal (size (w), szx))\n            ## w already has the right shape\n          elseif (isvector (w))\n            if (numel (w) != n)\n              error (strcat (\"mean: WEIGHTS vector must have the same\", ...\n                             \" length as the operating dimension\"));\n            endif\n            szw = ones (1, ndx);\n            szw(dim) = n;\n            w = reshape (w, szw);\n            if (! isvector (x))\n              szw = szx;\n              szw(dim) = 1;\n              w = repmat (w, szw);\n            endif\n          else\n            error (\"mean: WEIGHTS array must have the same dimensions with X\");\n          endif\n          n = sum (w, dim);\n        endif\n\n        ## Process omitnan\n        if (omitnan)\n          nanx = isnan (x);\n          x(nanx) = 0;\n          if (weighted)\n            w(nanx) = 0;\n            n = sum (w, dim);\n          else\n            n = sum (! nanx, dim);\n          endif\n        endif\n\n        if (any (isa (x, {\"int64\", \"uint64\"})))\n          m = int64_mean (x, dim, n, outtype);\n        else\n          if (weighted)\n            m = robust_mean_sum (x, dim, n, w);\n          else\n            m = robust_mean_sum (x, dim, n);\n          endif\n        endif\n\n      endif\n\n    else\n      vecdim = sort (vecdim);\n      if (! all (diff (vecdim)))\n         error (\"mean: VECDIM must contain non-repeating positive integers\");\n      endif\n      ## Ignore dimensions in VECDIM larger than actual array.\n      vecdim(vecdim > ndx) = [];\n\n      if (isempty (vecdim))\n\n        ## Process weights\n        if (weighted)\n          if (! isequal (size (w), szx))\n             error (strcat (\"mean: WEIGHTS array must have the same size\", ...\n                            \" as X, when 'all (VECDIM > ndims (X))'\"));\n          endif\n        endif\n\n        m = x;\n\n      else\n\n        ## Calculate permutation vector\n        remdims = 1:ndx;       # All dimensions\n        remdims(vecdim) = [];  # Delete dimensions specified by vecdim\n        nremd = numel (remdims);\n\n        ## If all dimensions are given, it is equivalent to 'all' flag\n        if (nremd == 0)\n          x = x(:);\n          n = numel (x);\n\n          ## Process weights\n          if (weighted)\n            if (isvector (w))\n              if (numel (w) != n)\n                error (strcat (\"mean: WEIGHTS vector must have the same\", ...\n                               \" length as the operating dimension\"));\n              endif\n            elseif (! isequal (size (w), szx))\n              error (\"mean: WEIGHTS array must have the same size as X\");\n            endif\n            w = w(:);\n            n = sum (w);\n          endif\n\n          ## Process omitnan\n          if (omitnan)\n            nanx = isnan (x);\n            x(nanx) = [];\n            if (weighted)\n              w(nanx) = [];\n              n = sum (w);\n            else\n              n = numel (x);\n            endif\n          endif\n\n          if (any (isa (x, {\"int64\", \"uint64\"})))\n            m = int64_mean (x, 1, n, outtype);\n          else\n            if (weighted)\n              m = robust_mean_sum (x, 1, n, w);\n            else\n              m = robust_mean_sum (x, 1, n);\n            endif\n          endif\n\n        else\n          ## Weights must either match vecdim page size or the size of X\n          if (weighted)\n            page_szw = size (w);\n            if (isequal (size (w), szx))\n              ## w already has the right shape\n            elseif (isequal (page_szw, szx(vecdim)))\n              ## Make W to be compatible with X\n              tmp = ones (1, ndx);\n              tmp(vecdim) = page_szw;\n              w = reshape (w, tmp);\n              w = w .* ones (szx);\n            else\n              error (strcat (\"mean: WEIGHTS array must have the same size\", ...\n                             \" as the operating page specified by VECDIM\", ...\n                             \" or the input array X\"));\n            endif\n          endif\n\n          ## Permute to push vecdims to back\n          perm = [remdims, vecdim];\n          x = permute (x, perm);\n          if (weighted)\n            w = permute (w, perm);\n          endif\n\n          ## Reshape to squash all vecdims in final dimension\n          sznew = [szx(remdims), prod(szx(vecdim))];\n          x = reshape (x, sznew);\n          if (weighted)\n            w = reshape (w, sznew);\n          endif\n\n          ## Calculate mean on final dimension\n          dim = nremd + 1;\n\n          ## Process omitnan\n          if (omitnan)\n            nanx = isnan (x);\n            x(nanx) = 0;\n            if (weighted)\n              w(nanx) = 0;\n              n = sum (w, dim);\n            else\n              n = sum (! nanx, dim);\n            endif\n          else\n            if (weighted)\n              n = sum (w, dim);\n            else\n              n = sznew(dim);\n            endif\n          endif\n\n          if (any (isa (x, {\"int64\", \"uint64\"})))\n            m = int64_mean (x, dim, n, outtype);\n          else\n            if (weighted)\n              m = robust_mean_sum (x, dim, n, w);\n            else\n              m = robust_mean_sum (x, dim, n);\n            endif\n          endif\n\n          ## Inverse permute back to correct dimensions\n          m = ipermute (m, perm);\n\n        endif\n      endif\n    endif\n  endif\n\n  ## Convert output if necessary\n  if (! strcmp (class (m), outtype))\n    if (! islogical (x))\n      m = feval (outtype, m);\n    endif\n  endif\n\nendfunction\n\nfunction m = int64_mean (x, dim, n, outtype)\n    ## Avoid int overflow in large ints.  Smaller ints processed as double\n    ## avoids overflow but large int64 values have floating pt error as double.\n    ## Use integer math and manual remainder correction to avoid this.\n    if (any (abs (x(:)) >= flintmax / n))\n      rmdr = double (rem (x, n)) / n;\n      rmdr_hilo = logical (int8 (rmdr)); # Integer rounding direction indicator\n\n      ## Do 'native' int summation to prevent double precision error,\n      ## then add back in lost round-up/down remainders.\n\n      m = sum (x/n, dim, \"native\");\n\n      ## rmdr.*!rmdr_hilo = remainders that were rounded down in abs val\n      ## signs retained, can be summed and added back.\n      ## rmdr.*rmdr_hilo = remainders that were rounded up in abs val.\n      ## need to add back difference between 1 and rmdr, retaining sign.\n\n      rmdr = sum (rmdr .* !rmdr_hilo, dim) - ...\n                sum ((1 - abs (rmdr)) .* rmdr_hilo .* sign (rmdr), dim);\n\n      if (any (abs (m(:)) >= flintmax))\n        ## Avoid float errors when combining for large m.\n        ## FIXME: may also need to include checking rmdr for large numel (x),\n        ##        as its value could be on the order of numel (x).\n        if (any (strcmp (outtype, {\"int64\", \"uint64\"})))\n          m += rmdr;\n        else\n          m = double (m) + rmdr;\n        endif\n\n      else\n        m = double (m) + rmdr;\n        switch (outtype)\n          case \"int64\"\n            m = int64 (m);\n          case \"uint64\"\n            m = uint64 (m);\n        endswitch\n      endif\n    else\n      m = double (sum (x, dim, \"native\")) ./ n;\n    endif\n\nendfunction\n\nfunction m = robust_mean_sum (x, dim, n, w = [])\n  ## \"Optimistic\" mean calculation with optional weights.\n  ## 1. Fast Path: standard compensated sum.\n  ## 2. Recovery Path: if result is infinite, check if scaling is needed.\n  ##\n  ## When weights w are provided, computes: sum(w .* x) / n  where n = sum(w)\n  ## When weights w are empty, computes: sum(x) / n\n\n  weighted = ! isempty (w);\n\n  ## Single precision always uses double accumulator (safe from overflow).\n  if (isa (x, \"single\"))\n    if (weighted)\n      m = sum (w .* x, dim, \"extra\") ./ n;\n    else\n      m = sum (x, dim, \"extra\") ./ n;\n    endif\n    return;\n  endif\n\n  ## 1. Fast Path\n  if (weighted)\n    m = sum (w .* double (x), dim, \"extra\") ./ n;\n  else\n    m = sum (x, dim, \"extra\") ./ n;\n  endif\n\n  ## 2. Check for overflow\n  ## If result is finite, we are done.\n  ## If result contains Inf, we must investigate (could be overflow).\n  ## If result contains only NaN or Inf, we must investigate.\n  ## NaN can occur from overflow if summation algorithm internally \n  ## computes Inf - Inf\n  if (! any (isfinite (m(:))))\n    ## Possible causes:\n    ## A. Input contained Inf/NaN (result is correct).\n    ## B. Input was finite, but sum overflowed (result needs scaling).\n\n    ## Scan x to see if inputs are the problem.\n    ## This is expensive (allocates bool array), but only happens on failure.\n    ## Use !isfinite (not isinf) because +Inf and -Inf in inputs sum to NaN.\n    if (weighted)\n      inputs_bad = any (! isfinite (x(:))) || any (! isfinite (w(:)));\n    else\n      inputs_bad = any (! isfinite (x(:)));\n    endif\n\n    if (inputs_bad)\n      ## Inputs are not finite.  The naive m is the correct answer.\n      return;\n    endif\n\n    ## Inputs are finite, but result is Inf.  This is overflow.\n    ## Re-calculate using scaling.\n\n    ## Calculate max magnitude along operating dimension.\n    ## vecnorm(x, inf, dim) computes max(abs(x)) without intermediate array.\n    max_val = vecnorm (x, inf, dim);\n\n    ## Scale x down before multiplication/summation\n    [~, e] = log2 (max_val);\n    e = e - 1;\n    scale = pow2 (e);\n    scale(max_val == 0) = 1;\n\n    ## Scale -> Sum -> Unscale\n    if (weighted)\n      m = sum (w .* (double (x) ./ scale), dim, \"extra\") .* (scale ./ n);\n    else\n      m = sum (x ./ scale, dim, \"extra\") .* (scale ./ n);\n    endif\n  endif\n\nendfunction\n\n%!test\n%! x = -10:10;\n%! y = x';\n%! z = [y, y+10];\n%! assert (mean (x), 0);\n%! assert (mean (y), 0);\n%! assert (mean (z), [0, 10]);\n\n%!assert (mean (magic (3), 1), [5, 5, 5])\n%!assert (mean (magic (3), 2), [5; 5; 5])\n%!assert (mean (logical ([1 0 1 1])), 0.75)\n%!assert (mean (single ([1 0 1 1])), single (0.75))\n%!assert (mean ([1 2], 3), [1 2])\n\n## Test outtype option\n%!test\n%! in = [1 2 3];\n%! out = 2;\n%! assert (mean (in, \"default\"), mean (in));\n%! assert (mean (in, \"default\"), out);\n%! assert (mean (in, \"double\"), out);\n%! assert (mean (in, \"native\"), out);\n\n%!test\n%! in = single ([1 2 3]);\n%! out = 2;\n%! assert (mean (in, \"default\"), mean (in));\n%! assert (mean (in, \"default\"), single (out));\n%! assert (mean (in, \"double\"), out);\n%! assert (mean (in, \"native\"), single (out));\n\n%!test\n%! in = logical ([1 0 1]);\n%! out = 2/3;\n%! assert (mean (in, \"default\"), mean (in), eps);\n%! assert (mean (in, \"default\"), out, eps);\n%! assert (mean (in, \"double\"), out, eps);\n%! assert (mean (in, \"native\"), out, eps);\n\n%!test\n%! in = uint8 ([1 2 3]);\n%! out = 2;\n%! assert (mean (in, \"default\"), mean (in));\n%! assert (mean (in, \"default\"), out);\n%! assert (mean (in, \"double\"), out);\n%! assert (mean (in, \"native\"), uint8 (out));\n\n%!test\n%! in = uint8 ([0 1 2 3]);\n%! out = 1.5;\n%! out_u8 = 2;\n%! assert (mean (in, \"default\"), mean (in), eps);\n%! assert (mean (in, \"default\"), out, eps);\n%! assert (mean (in, \"double\"), out, eps);\n%! assert (mean (in, \"native\"), uint8 (out_u8));\n%! assert (class (mean (in, \"native\")), \"uint8\");\n\n%!test # internal sum exceeding intmax\n%! in = uint8 ([3 141 141 255]);\n%! out = 135;\n%! assert (mean (in, \"default\"), mean (in));\n%! assert (mean (in, \"default\"), out);\n%! assert (mean (in, \"double\"), out);\n%! assert (mean (in, \"native\"), uint8 (out));\n%! assert (class (mean (in, \"native\")), \"uint8\");\n\n%!test # fractional answer with internal sum exceeding intmax\n%! in = uint8 ([1 141 141 255]);\n%! out = 134.5;\n%! out_u8 = 135;\n%! assert (mean (in, \"default\"), mean (in));\n%! assert (mean (in, \"default\"), out);\n%! assert (mean (in, \"double\"), out);\n%! assert (mean (in, \"native\"), uint8 (out_u8));\n%! assert (class (mean (in, \"native\")), \"uint8\");\n\n%!test <54567> # large int64 sum exceeding intmax and double precision limit\n%! in_same = uint64 ([intmax(\"uint64\") intmax(\"uint64\")-2]);\n%! out_same = intmax (\"uint64\")-1;\n%! in_opp = int64 ([intmin(\"int64\"), intmax(\"int64\")-1]);\n%! out_opp = -1;\n%! in_neg = int64 ([intmin(\"int64\") intmin(\"int64\")+2]);\n%! out_neg = intmin (\"int64\")+1;\n%!\n%! ## both positive\n%! assert (mean (in_same, \"default\"), mean (in_same));\n%! assert (mean (in_same, \"default\"), double (out_same));\n%! assert (mean (in_same, \"double\"), double (out_same));\n%! assert (mean (in_same, \"native\"), uint64 (out_same));\n%! assert (class (mean (in_same, \"native\")), \"uint64\");\n%!\n%! ## opposite signs\n%! assert (mean (in_opp, \"default\"), mean (in_opp));\n%! assert (mean (in_opp, \"default\"), double (out_opp));\n%! assert (mean (in_opp, \"double\"), double (out_opp));\n%! assert (mean (in_opp, \"native\"), int64 (out_opp));\n%! assert (class (mean (in_opp, \"native\")), \"int64\");\n%!\n%! ## both negative\n%! assert (mean (in_neg, \"default\"), mean (in_neg));\n%! assert (mean (in_neg, \"default\"), double (out_neg));\n%! assert (mean (in_neg, \"double\"), double (out_neg));\n%! assert (mean (in_neg, \"native\"), int64 (out_neg));\n%! assert (class (mean (in_neg, \"native\")), \"int64\");\n\n## Additional tests int64 and double precision limits\n%!test <54567>\n%! in = [(intmin('int64')+5), (intmax('int64'))-5];\n%! assert (mean (in, \"native\"), int64 (-1));\n%! assert (class (mean (in, \"native\")), \"int64\");\n%! assert (mean (double(in)), double (0) );\n%! assert (mean (in), double (-0.5) );\n%! assert (mean (in, \"default\"), double (-0.5) );\n%! assert (mean (in, \"double\"), double (-0.5) );\n%! assert (mean (in, \"all\", \"native\"), int64 (-1));\n%! assert (mean (in, 2, \"native\"), int64 (-1));\n%! assert (mean (in, [1 2], \"native\"), int64 (-1));\n%! assert (mean (in, [2 3], \"native\"), int64 (-1));\n%! assert (mean ([intmin(\"int64\"), in, intmax(\"int64\")]), double (-0.5));\n%! assert (mean ([in; int64([1 3])], 2, \"native\"), int64 ([-1; 2]));\n\n## Test for overflow near REALMAX\n#! test <56884>\n#! a = realmax / 2;\n#! b = 2 * (realmax / 3);\n#! c = a + (b - a) / 2;\n#! assert (mean ([a,b]), c, eps (c));\n\n## Test for underflow\n#! test <56884>\n#! a = 1 / realmax;\n#! b = 1.5 / realmax;\n#! c = a + (b - a) / 2;\n#! assert (mean ([a,b]), c, eps (c));\n\n## Test input and optional arguments \"all\", DIM, \"omitnan\".\n%!test\n%! x = [-10:10];\n%! y = [x;x+5;x-5];\n%! assert (mean (x), 0);\n%! assert (mean (y, 2), [0, 5, -5]');\n%! assert (mean (y, \"all\"), 0);\n%! y(2,4) = NaN;\n%! assert (mean (y', \"omitnan\"), [0 5.35 -5]);\n%! z = y + 20;\n%! assert (mean (z, \"all\"), NaN);\n%! assert (mean (z, \"all\", \"includenan\"), NaN);\n%! assert (mean (z, \"all\", \"omitnan\"), 20.03225806451613, 4e-14);\n%! m = [20 NaN 15];\n%! assert (mean (z'), m);\n%! assert (mean (z', \"includenan\"), m);\n%! m = [20 25.35 15];\n%! assert (mean (z', \"omitnan\"), m);\n%! assert (mean (z, 2, \"omitnan\"), m');\n%! assert (mean (z, 2, \"native\", \"omitnan\"), m');\n%! assert (mean (z, 2, \"omitnan\", \"native\"), m');\n\n## Test logical input\n%!test\n%! assert (mean (true, \"all\"), 1);\n%! assert (mean (false), 0);\n%! assert (mean ([true false true]), 2/3, 4e-14);\n%! assert (mean ([true false true], 1), [1 0 1]);\n%! assert (mean ([true false NaN], 1), [1 0 NaN]);\n%! assert (mean ([true false NaN], 2), NaN);\n%! assert (mean ([true false NaN], 2, \"omitnan\"), 0.5);\n%! assert (mean ([true false NaN], 2, \"omitnan\", \"native\"), 0.5);\n\n## Test NaN inputs\n%!test\n%! x = magic (4);\n%! x([2, 9:12]) = NaN;\n%! assert (mean (x), [NaN 8.5, NaN, 8.5], eps);\n%! assert (mean (x,1), [NaN 8.5, NaN, 8.5], eps);\n%! assert (mean (x,2), NaN (4,1), eps);\n%! assert (mean (x,3), x, eps);\n%! assert (mean (x, 'omitnan'), [29/3, 8.5, NaN, 8.5], eps);\n%! assert (mean (x, 1, 'omitnan'), [29/3, 8.5, NaN, 8.5], eps);\n%! assert (mean (x, 2, 'omitnan'), [31/3; 9.5; 28/3; 19/3], eps);\n%! assert (mean (x, 3, 'omitnan'), x, eps);\n\n## Test empty inputs\n%!assert (mean ([]), NaN (1, 1))\n%!assert (mean (single ([])), NaN (1, 1, \"single\"))\n%!assert (mean ([], 1), NaN (1, 0))\n%!assert (mean ([], 2), NaN (0, 1))\n%!assert (mean ([], 3), NaN (0, 0))\n%!assert (mean (ones (1,0)), NaN (1,1))\n%!assert (mean (ones (1,0), 1), NaN (1,0))\n%!assert (mean (ones (1,0), 2), NaN (1,1))\n%!assert (mean (ones (1,0), 3), NaN (1,0))\n%!assert (mean (ones (0,1)), NaN (1,1))\n%!assert (mean (ones (0,1), 1), NaN (1,1))\n%!assert (mean (ones (0,1), 2), NaN (0,1))\n%!assert (mean (ones (0,1), 3), NaN (0,1))\n%!assert (mean (ones (0,1,0)), NaN (1,1,0))\n%!assert (mean (ones (0,1,0), 1), NaN (1,1,0))\n%!assert (mean (ones (0,1,0), 2), NaN (0,1,0))\n%!assert (mean (ones (0,1,0), 3), NaN (0,1))\n%!assert (mean (ones (0,0,1,0)), NaN (1,0,1,0))\n%!assert (mean (ones (0,0,1,0), 1), NaN (1,0,1,0))\n%!assert (mean (ones (0,0,1,0), 2), NaN (0,1,1,0))\n%!assert (mean (ones (0,0,1,0), 3), NaN (0,0,1,0))\n\n## Test dimension indexing with vecdim in N-dimensional arrays\n%!test\n%! x = repmat ([1:20;6:25], [5 2 6 3]);\n%! assert (size (mean (x, [3 2])), [10 1 1 3]);\n%! assert (size (mean (x, [1 2])), [1 1 6 3]);\n%! assert (size (mean (x, [1 2 4])), [1 1 6]);\n%! assert (size (mean (x, [1 4 3])), [1 40]);\n%! assert (size (mean (x, [1 2 3 4])), [1 1]);\n\n## Test exceeding dimensions\n%!assert (mean (ones (2,2), 3), ones (2,2))\n%!assert (mean (ones (2,2,2), 99), ones (2,2,2))\n%!assert (mean (magic (3), 3), magic (3))\n%!assert (mean (magic (3), [1 3]), [5, 5, 5])\n%!assert (mean (magic (3), [1 99]), [5, 5, 5])\n\n## Test results with vecdim in N-dimensional arrays and \"omitnan\"\n%!test\n%! x = repmat ([1:20;6:25], [5 2 6 3]);\n%! m = repmat ([10.5;15.5], [5 1 1 3]);\n%! assert (mean (x, [3 2]), m, 4e-14);\n%! x(2,5,6,3) = NaN;\n%! m(2,1,1,3) = NaN;\n%! assert (mean (x, [3 2]), m, 4e-14);\n%! m(2,1,1,3) = 15.52301255230125;\n%! assert (mean (x, [3 2], \"omitnan\"), m, 4e-14);\n\n## Test input case insensitivity\n%!assert (mean ([1 2 3], \"aLL\"), 2)\n%!assert (mean ([1 2 3], \"OmitNan\"), 2)\n%!assert (mean ([1 2 3], \"DOUBle\"), 2)\n\n## Test limits of single precision summation limits on each code path\n%!assert <*63848> (mean (ones (80e6, 1, \"single\")), 1, eps)\n%!assert <*63848> (mean (ones (80e6, 1, \"single\"), \"all\"), 1, eps)\n%!assert <*63848> (mean (ones (80e6, 1, \"single\"), 1), 1, eps)\n%!assert <*63848> (mean (ones (80e6, 1, \"single\"), [1 2]), 1, eps)\n%!assert <*63848> (mean (ones (80e6, 1, \"single\"), [1 3]), 1, eps)\n\n## Test 'Weights' with DIM, VECDIM, and \"all\" options\n%!test\n%! x = [1, 1; 7, 9; 1, 9; 1, 9; 6, 2];\n%! w = [1; 2; 1; 2; 3];\n%! assert (mean (x, 'Weights', w), [4, 5.7778], 1e-4);\n%! assert (mean (x, 'Weights', w'), [4, 5.7778], 1e-4);\n%! assert (mean (x, 1, 'Weights', w), [4, 5.7778], 1e-4);\n%! assert (mean (x, 1, 'Weights', w'), [4, 5.7778], 1e-4);\n%! assert (mean (x', 2, 'Weights', w), [4; 5.7778], 1e-4);\n%! assert (mean (x', 2, 'Weights', w'), [4; 5.7778], 1e-4);\n%!test\n%! x = [1, 1; 7, 9; 1, 9; 1, 9; 6, 2];\n%! x = reshape (x', [1, 2, 5]);\n%! w = [1, 2, 1, 2, 3];\n%! assert (size (x)([1, 3]), size (w));\n%! assert (mean (x, [1, 3], 'Weights', w), [4, 5.7778], 1e-4);\n%!test\n%! x = [1, 1; 7, 9; 1, 9; 1, 9; 6, 2];\n%! x = reshape (x', [1, 2, 5]);\n%! w = ones (1, 2, 5);\n%! assert (size (x), size (w));\n%! assert (mean (x, 'all', 'Weights', w), mean (x, 'all'), 1e-4);\n%! assert (mean (x, [1, 2, 3], 'Weights', w), mean (x, [1, 2, 3]), 1e-4);\n\n## Test 'Weights' with 'omitnan' and outtype options\n%!test\n%! x = [1, 1; 7, 9; 1, 9; 1, 9; 6, 2];\n%! w = [1; 2; 1; 2; 3];\n%! assert (mean (x, 'omitnan', 'Weights', w), [4, 5.7778], 1e-4);\n%! assert (mean (x, 1, 'omitnan', 'Weights', w), [4, 5.7778], 1e-4);\n%! assert (mean (x', 2,'omitnan',  'Weights', w), [4; 5.7778], 1e-4);\n%!test\n%! x = [1, 1; 7, NaN; 1, 9; 1, 9; 6, 2];\n%! x = reshape (x', [1, 2, 5]);\n%! w = ones (1, 2, 5);\n%! assert (size (x), size (w));\n%! assert (mean (x, 'all', 'omitnan', 'Weights', w), mean (x, 'all', 'omitnan'), 1e-4);\n%! assert (mean (x, [1, 2, 3], 'omitnan', 'Weights', w), mean (x, [1, 2, 3], 'omitnan'), 1e-4);\n%!test\n%! x = single ([1, 1; 7, 9; 1, 9; 1, 9; 6, 2]);\n%! w = [1; 2; 1; 2; 3];\n%! assert (class (mean (x, 'Weights', w)), \"single\");\n%!test\n%! x = int32 ([1, 1; 7, 9; 1, 9; 1, 9; 6, 2]);\n%! w = [1; 2; 1; 2; 3];\n%! assert (class (mean (x, 'native', 'Weights', w)), \"int32\");\n\n## Test limits of double precision summation\n%!assert <63848> (mean ([flintmax(\"double\"), ones(1, 2^8-1, \"double\")]), ...\n%!                35184372088833-1/(2^8), eps (35184372088833))\n%!assert (mean (sparse ([flintmax(\"double\"), ones(1, 2^8-1, \"double\")])), ...\n%!        sparse (35184372088833-1/(2^8)), eps (35184372088833))\n## Test limits of double precision summation with \"all\", DIM, and VECDIM options\n%!assert (mean ([flintmax(\"double\"), ones(1, 2^8-1, \"double\")], \"all\"), ...\n%!                35184372088833-1/(2^8), eps (35184372088833))\n%!assert (mean (sparse ([flintmax(\"double\"), ones(1, 2^8-1, \"double\")]), \"all\"), ...\n%!        sparse (35184372088833-1/(2^8)), eps (35184372088833))\n%!assert (mean ([flintmax(\"double\"), ones(1, 2^8-1, \"double\")], 2), ...\n%!                35184372088833-1/(2^8), eps (35184372088833))\n%!assert (mean (sparse ([flintmax(\"double\"), ones(1, 2^8-1, \"double\")]), 2), ...\n%!        sparse (35184372088833-1/(2^8)), eps (35184372088833))\n%!assert (mean (reshape ([flintmax(\"double\"), ones(1, 2^8-1, \"double\")], ...\n%!                       1, 2, (2^8)/2), [2, 3]), ...\n%!        35184372088833-1/(2^8), eps (35184372088833))\n\n## Test sparse input\n%!test\n%! x = speye (3);\n%! assert (mean (x(:)), sparse (1/3));\n%! assert (mean (x, \"all\"), sparse (1/3));\n%! assert (mean (x, [1, 2]), sparse (1/3));\n%! assert (mean (x), sparse ([1/3, 1/3, 1/3]));\n%! assert (mean (x, 2), sparse ([1/3; 1/3; 1/3]));\n%! assert (mean (x, 3), x);\n\n## Test input validation\n%!error <Invalid call> mean ()\n%!error <Invalid call> mean (1, 2, 3, 4, 5)\n%!error <X must be a numeric or logical array> mean ({1:5})\n%!error <WEIGHTS must be single or double> mean (1, 'Weights', 'double')\n%!error <WEIGHTS must be single or double> mean (1, 'Weights', uint8 (1))\n%!error <WEIGHTS must be nonnegative> mean (1, 'Weights', -1)\n%!error <paired input argument for 'Weights' is missing> mean (1, 'Weights')\n%!error <Invalid call> mean (1, 2, 3)\n%!error <Invalid call> mean (1, \"all\", 3)\n%!error <only one OUTTYPE> mean (1, 'native', 'default')\n%!error <only one OUTTYPE> mean (1, 'default', 'native')\n%!error <only one OUTTYPE> mean (1, 'default', 'double')\n%!error <Invalid call> mean (1, 'foobar')\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mean ([1:5]', \"all\", 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as X> ...\n%! mean (ones (5, 3), \"all\", 'Weights', ones (3, 5))\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mean ([1:5]', 'Weights', [1, 2, 3])\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mean (ones (5, 3), 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as X> ...\n%! mean (ones (5, 3), 'Weights', ones (3, 5))\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! mean ([1:5]', [1, 2], 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as X> ...\n%! mean (ones (5, 3), [1, 2], 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the operating page> ...\n%! mean (ones (5, 3, 2), [1, 2], 'Weights', ones (3, 5))\n%!error <DIM must be a positive integer> mean (1, ones (2,2))\n%!error <DIM must be a positive integer> mean (1, 1.5)\n%!error <DIM must be a positive integer> mean (1, 0)\n%!error <DIM must be a positive integer> mean (1, [])\n%!error <DIM must be a positive integer> mean (1, -1)\n%!error <DIM must be a positive integer> mean (1, -1.5)\n%!error <DIM must be a positive integer> mean (1, NaN)\n%!error <DIM must be a positive integer> mean (1, Inf)\n%!error <DIM must be a positive integer> mean (repmat ([1:20;6:25], [5 2]), -1)\n%!error <DIM must be a positive integer> mean (repmat ([1:5;5:9], [5 2]), [1 -1])\n%!error <DIM must be a positive integer> mean (1, ones (1,0))\n%!error <VECDIM must contain non-repeating> mean (1, [2 2])\n"
  },
  {
    "path": "scripts/statistics/meansq.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} meansq (@var{x})\n## @deftypefnx {} {@var{y} =} meansq (@var{x}, @var{dim})\n## @deftypefnx {} {@var{y} =} meansq (@var{x}, @var{vecdim})\n## @deftypefnx {} {@var{y} =} meansq (@var{x}, \"all\")\n## @deftypefnx {} {@var{y} =} meansq (@dots{}, @var{nanflag})\n## Compute the mean square of the input data @var{x}.\n##\n## The mean square is defined as\n## @tex\n## $$\n## {\\rm meansq} (x) = {{1 \\over N} \\sum_{i=1}^N {|x_i|}^2}\n## $$\n## where $N$ is the number of elements of @var{x}.\n##\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## meansq (@var{x}) = 1/N SUM_i @var{x}(i)^2\n## @end group\n## @end example\n##\n## @noindent\n## where @math{N} is the length of the @var{x} vector.\n##\n## @end ifnottex\n## If @var{x} is a vector, then @code{meansq (@var{x})} returns the mean square\n## of the elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{meansq (@var{x})} returns a row vector\n## with each element containing the mean square of the corresponding column in\n## @var{x}.\n##\n## If @var{x} is an array, then @code{meansq (@var{x})} computes the mean\n## square along the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be numeric.  The size of @var{y} is equal to the\n## size of @var{x} except for the operating dimension, which becomes 1.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{@var{x}.^2}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{meansq} to\n## operate on all elements of @var{x}, and is equivalent to\n## @code{meansq (@var{x}(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\n## NaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\n## will still contain NaN values if @var{x} consists of all NaN values in the\n## operating dimension.\n##\n## @seealso{rms, var, std, moment}\n## @end deftypefn\n\nfunction y = meansq (x, varargin)\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x)))\n    error (\"meansq: X must be a numeric array\");\n  endif\n\n  ## Calculate sum of squares and run input validation on varargin.\n  y = sumsq (x, varargin{:});\n\n  ## Normalize\n  omitnan = strcmpi (varargin, 'omitnan');\n  if (any (omitnan))\n    ## Only call isnan() when necessary because it is slow.\n    varargin(omitnan) = [];\n    y ./= sum (! isnan (x), varargin{:});\n\n  else\n    if (isempty (varargin))\n      ## Find the first non-singleton dimension.\n      (dim = find (size (x) != 1, 1)) || (dim = 1);\n      norm = size (x, dim);\n    elseif (isnumeric (varargin{1}))\n      dim = varargin{1};\n      norm = prod (size (x, dim));\n    elseif (any (strcmpi (varargin, 'all')))\n      norm = numel (x);\n    else\n      ## String option such as 'includenan' given, but no dimension.\n      ## Find the first non-singleton dimension.\n      (dim = find (size (x) != 1, 1)) || (dim = 1);\n      norm = size (x, dim);\n    endif\n\n    y ./= norm;\n\n  endif\n\nendfunction\n\n\n%!assert (meansq (1:5), 11)\n%!assert (meansq (single (1:5)), single (11))\n%!assert (meansq (magic (4)), [94.5, 92.5, 92.5, 94.5])\n%!assert (meansq (magic (4), 2), [109.5; 77.5; 77.5; 109.5])\n%!assert (meansq ([1 2], 3), [1 4])\n\n## Test optional arguments DIM, 'all', 'omitnan'.\n%!test\n%! x = [-9:9];\n%! y = [x;x+6;x-6];\n%! assert (meansq (x), 30);\n%! assert (meansq (y, 2), [30; 66; 66]);\n%! assert (meansq (y, 'all'), 54);\n%! y = y';\n%! y(4,2) = NaN;\n%! assert (meansq (y, 'omitnan'), [30, 1254/18, 66]);\n%! assert (meansq (y, 'all'), NaN);\n%! assert (meansq (y, 'all', 'includenan'), NaN);\n%! assert (meansq (y, 'all', 'omitnan'), 3078/56);\n%! exp = [30, NaN, 66];\n%! assert (meansq (y), exp);\n%! assert (meansq (y, 'includenan'), exp);\n%! exp = [30, 1254/18, 66];\n%! assert (meansq (y, 'omitnan'), exp);\n%! assert (meansq (y', 2, 'omitnan'), exp');\n\n## Test dimension indexing with vecdim in N-dimensional arrays\n%!test\n%! x = repmat ([1:20;6:25], [5 2 6 3]);\n%! assert (size (meansq (x, [3 2])), [10 1 1 3]);\n%! assert (size (meansq (x, [1 2])), [1 1 6 3]);\n%! assert (size (meansq (x, [1 2 4])), [1 1 6]);\n%! assert (size (meansq (x, [1 4 3])), [1 40]);\n%! assert (size (meansq (x, [1 2 3 4])), [1 1]);\n\n## Test exceeding dimensions\n%!assert (meansq (2*ones (2,2), 3), 4*ones (2,2))\n%!assert (meansq (2*ones (2,2,2), 99), 4*ones (2,2,2))\n%!assert (meansq (magic (4), 3), (magic (4)).^2)\n%!assert (meansq (magic (4), [1 3]), [94.5, 92.5, 92.5, 94.5])\n%!assert (meansq (magic (4), [1 99]), [94.5, 92.5, 92.5, 94.5])\n\n## Test results with vecdim in N-dimensional arrays and \"omitnan\"\n%!test\n%! x = repmat ([1:5;11:15], [5 2 6 3]);\n%! m = repmat ([11; 171], [5 1 1 3]);\n%! assert (meansq (x, [3 2]), m);\n%! x(2,6,6,3) = NaN;\n%! m(2,1,1,3) = 10139/59;\n%! assert (meansq (x, [3 2], 'omitnan'), m);\n\n## Test input validation\n%!error <Invalid call> meansq ()\n%!error <Invalid call> meansq (1,2,3,4)\n%!error <meansq: X must be a numeric array> meansq (['A'; 'B'])\n%!error <meansq: X must be a numeric array> meansq ([true, false])\n%!error <meansq: X must be a numeric array> meansq ({1, 2})\n"
  },
  {
    "path": "scripts/statistics/median.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{m} =} median (@var{x})\n## @deftypefnx {} {@var{m} =} median (@var{x}, @var{dim})\n## @deftypefnx {} {@var{m} =} median (@var{x}, @var{vecdim})\n## @deftypefnx {} {@var{m} =} median (@var{x}, \"all\")\n## @deftypefnx {} {@var{m} =} median (@dots{}, @var{nanflag})\n## @deftypefnx {} {@var{m} =} median (@dots{}, @var{outtype})\n## Compute the median value of the elements of @var{x}.\n##\n## The median is defined on the sorted data @var{s}\n## (@w{@code{@var{s} = sort (@var{x})}}) as\n## @tex\n## $$\n## {\\rm median} (x) =\n##   \\cases{s(\\lceil N/2\\rceil), & $N$ odd;\\cr\n##           (s(N/2)+s(N/2+1))/2, & $N$ even.}\n## $$\n## where $N$ is the number of elements of @var{x}.\n##\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##              |  @var{s}(ceil (N/2))          N odd\n## median (@var{x}) = |\n##              | (@var{s}(N/2) + @var{s}(N/2+1))/2   N even\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## If @var{x} is a vector, then @code{median (@var{x})} returns the median of\n## the elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{median (@var{x})} returns a row vector\n## with each element containing the median of the corresponding column in\n## @var{x}.\n##\n## If @var{x} is an array, then @code{median (@var{x})} computes the median\n## along the first non-singleton dimension of @var{x}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @var{x}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{median} to\n## operate on all elements of @var{x}, and is equivalent to\n## @code{median (@var{x}(:))}.\n##\n## @code{median (@dots{}, @var{outtype})} returns the median with a specified\n## data type, using any of the input arguments in the previous syntaxes.\n## @var{outtype} can take the following values:\n##\n## @table @asis\n## @item @qcode{\"default\"}\n## Output is of type double, unless the input is single in which case the\n## output is of type single.\n##\n## @item @qcode{\"double\"}\n## Output is of type double.\n##\n## @item @qcode{\"native\"}.\n## Output is of the same type as the input (@code{class (@var{x})}), unless the\n## input is logical in which case the output is of type double.\n## @end table\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"includenan\"} which keeps NaN values in the calculation.  To\n## exclude NaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.\n## The output will still contain NaN values if @var{x} consists of all NaN\n## values in the operating dimension.\n##\n## @seealso{mean, mode, movmedian}\n## @end deftypefn\n\nfunction m = median (x, varargin)\n\n  if (nargin < 1 || nargin > 4)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    error (\"median: X must be either numeric or logical\");\n  endif\n\n  ## Set initial conditions\n  all_flag    = false;\n  omitnan     = false;\n  perm_flag   = false;\n  out_flag    = false;\n  vecdim_flag = false;\n  dim         = [];\n\n  nvarg = numel (varargin);\n  varg_chars = cellfun (\"ischar\", varargin);\n  szx = sz_out = size (x);\n  ndx = ndims (x);\n  outtype = class (x);\n  xsparse = issparse (x);\n\n  if (nvarg > 1 && ! varg_chars(2:end))\n    ## Only first varargin can be numeric\n    print_usage ();\n  endif\n\n  ## Process any other char arguments.\n  if (any (varg_chars))\n    for argin = varargin(varg_chars)\n      switch (lower (argin{1}))\n        case \"all\"\n          all_flag = true;\n\n        case \"omitnan\"\n          omitnan = true;\n\n        case \"includenan\"\n          omitnan = false;\n\n        case \"native\"\n          if (out_flag)\n            error (\"median: only one OUTTYPE can be specified\");\n          endif\n          if (strcmp (outtype, \"logical\"))\n            outtype = \"double\";\n          endif\n          out_flag = true;\n\n        case \"default\"\n          if (out_flag)\n            error (\"median: only one OUTTYPE can be specified\");\n          endif\n          if (! strcmp (outtype, \"single\"))\n            outtype = \"double\";\n          endif\n          out_flag = true;\n\n        case \"double\"\n          if (out_flag)\n            error (\"median: only one OUTTYPE can be specified\");\n          endif\n          outtype = \"double\";\n          out_flag = true;\n\n        otherwise\n          print_usage ();\n      endswitch\n    endfor\n\n    varargin(varg_chars) = [];\n    nvarg = numel (varargin);\n  endif\n\n  if ((nvarg == 1 && ! isnumeric (varargin{1})) || nvarg > 1)\n    ## After trimming char inputs should only be one numeric varargin left\n    print_usage ();\n  endif\n\n  ## Process special cases for in/out size\n  if (nvarg > 0)\n    ## dim or vecdim provided\n    if (all_flag)\n      error (\"median: 'all' cannot be used with DIM or VECDIM options\");\n    endif\n\n    dim = varargin{1};\n    vecdim_flag = ! isscalar (dim);\n\n    if (! (isvector (dim) && dim > 0) || any (rem (dim, 1)))\n      error (\"median: DIM must be a positive integer scalar or vector\");\n    endif\n\n    ## Adjust sz_out, account for possible dim > ndx by appending singletons\n    sz_out(ndx + 1 : max (dim)) = 1;\n    sz_out(dim(dim <= ndx)) = 1;\n    szx(ndx + 1 : max (dim)) = 1;\n\n    if (vecdim_flag)\n      ## vecdim - try to simplify first\n      dim = sort (dim);\n      if (! all (diff (dim)))\n         error (\"median: VECDIM must contain non-repeating positive integers\");\n      endif\n\n      ## dims > ndims(x) and dims only one element long don't affect median\n      sing_dim_x = find (szx != 1);\n      dim(dim > ndx | szx(dim) == 1) = [];\n\n      if (isempty (dim))\n        ## No dims left to process, return input as output\n        if (! strcmp (class (x), outtype))\n          m = feval (outtype, x);  # convert to outtype\n        else\n          m = x;\n        endif\n        return;\n      elseif (numel (dim) == numel (sing_dim_x)\n              && unique ([dim, sing_dim_x]) == dim)\n        ## If DIMs cover all nonsingleton ndims(x) it's equivalent to \"all\"\n        ##   (check lengths first to reduce unique overhead if not covered)\n        all_flag = true;\n      endif\n    endif\n\n  else\n    ## Dim not provided.  Determine scalar dimension.\n    if (all_flag)\n      ## Special case 'all': Recast input as dim1 vector, process as normal.\n      x = x(:);\n      szx = [numel(x), 1];\n      dim = 1;\n      sz_out = [1 1];\n\n    elseif (isrow (x))\n      ## Special case row vector: Avoid setting dim to 1.\n      dim = 2;\n      sz_out = [1, 1];\n\n    elseif (ndx == 2 && szx == [0, 0])\n      ## Special case []: Do not apply sz_out(dim)=1 change.\n      dim = 1;\n      sz_out = [1, 1];\n\n    else\n      ## General case: Set dim to first non-singleton, contract sz_out along dim\n      (dim = find (szx != 1, 1)) || (dim = 1);\n      sz_out(dim) = 1;\n    endif\n  endif\n\n  if (isempty (x))\n    ## Empty input - output NaN or class equivalent in pre-determined size\n    switch (outtype)\n      case {\"double\", \"single\"}\n        m = NaN (sz_out, outtype);\n        if (xsparse)\n          m = sparse (m);\n        endif\n      case (\"logical\")\n        m = false (sz_out);\n      otherwise\n        m = cast (NaN (sz_out), outtype);\n    endswitch\n    return;\n  endif\n\n  if (all (isnan (x(:))))\n    ## all NaN input, output single or double NaNs in pre-determined size\n    m = NaN (sz_out, outtype);\n    if (xsparse)\n      m = sparse (m);\n    endif\n    return;\n  endif\n\n  if (szx(dim) == 1)\n    ## Operation along singleton dimension - nothing to do\n    if (! strcmp (class (x), outtype))\n      m = feval (outtype, x);  # convert to outtype\n    else\n      m = x;\n    endif\n    return;\n  endif\n\n  ## Permute dim to simplify all operations along dim1\n  if (numel (dim) > 1 || (dim != 1 && ! isvector (x)))\n    perm = 1 : ndx;\n\n    if (! vecdim_flag)\n      ## Move dim to dim 1\n      perm([1, dim]) = [dim, 1];\n      x = permute (x, perm);\n      szx([1, dim]) = szx([dim, 1]);\n      dim = 1;\n\n    else\n      ## Move vecdims to front\n      perm(dim) = [];\n      perm = [dim, perm];\n      x = permute (x, perm);\n\n      ## Reshape all vecdims into dim1\n      num_dim = prod (szx(dim));\n      szx(dim) = [];\n      szx = [num_dim, ones(1, numel(dim)-1), szx];\n      x = reshape (x, szx);\n      dim = 1;\n    endif\n\n    perm_flag = true;\n  endif\n\n  ## Find column locations of NaNs\n  nanfree = ! any (isnan (x), dim);\n\n  if (omitnan && all (nanfree(:)))\n    ## Don't use omitnan path if no NaNs are present.  Prevents any data types\n    ## without a defined NaN from following slower omitnan codepath.\n    omitnan = false;\n  endif\n\n  ## Sparse inputs use the original sort-based code path to preserve sparsity.\n  ## Dense inputs use nth_element for O(n) selection instead of O(n log n) sort.\n\n  if (xsparse)\n    # use sort for sparse matrices to retain sparsity of output\n    x = sort (x, dim);\n\n    if (omitnan)\n      if (isvector (x))\n        x = x(! isnan (x));\n        n = numel (x);\n        k = floor ((n + 1) / 2);\n        if (n == 0)\n          m = sparse (NaN);\n        elseif (mod (n, 2))\n          m = sparse (x(k));\n        else\n          m = sparse ((x(k) + x(k + 1)) / 2);\n        endif\n      else\n        n = sum (! isnan (x), 1)(:);\n        k = floor ((n + 1) / 2);\n        odd_cols = mod (n, 2) & n;\n        even_cols = ! odd_cols & n;\n\n        m = sparse (NaN ([1, szx(2 : end)]));\n\n        if (ndims (x) > 2)\n          szx_flat = [szx(1), prod(szx(2 : end))];\n        else\n          szx_flat = szx;\n        endif\n\n        if (any (odd_cols))\n          idx = sub2ind (szx_flat, k(odd_cols), find (odd_cols));\n          m(odd_cols) = x(idx);\n        endif\n        if (any (even_cols))\n          k_even = k(even_cols);\n          idx = sub2ind (szx_flat, [k_even, k_even + 1], ...\n                         find (even_cols)(:, [1, 1]));\n          m(even_cols) = sum (x(idx), 2) / 2;\n        endif\n      endif\n\n    else\n      ## No \"omitnan\" for sparse\n      if (all (! nanfree(:)))\n        m = NaN (sz_out);\n        m = sparse (m);\n\n      else\n        if (isvector (x))\n          n = numel (x);\n          k = floor ((n + 1) / 2);\n\n          m = x(k);\n          if (! mod (n, 2))\n            if (any (isinf ([x(k), x(k+1)])))\n              m = x(k) + x(k+1);\n            else\n              m += (x(k + 1) - m) / 2;\n            endif\n          endif\n          m = sparse (m);\n\n        else\n          n = szx(1);\n          k = floor ((n + 1) / 2);\n\n          m = sparse (NaN ([1, szx(2 : end)]));\n\n          if (! mod (n, 2))\n            m(nanfree) = (x(k, nanfree) + x(k + 1, nanfree)) / 2;\n          else\n            m(nanfree) = x(k, nanfree);\n          endif\n        endif\n      endif\n    endif\n\n  else\n    ## dense: use nth_element for O(n) selection\n    if (omitnan)\n      ## Ignore any NaN's in data. \n      ## Each operating vector might have a different number of non-NaN data points.\n      if (isvector (x))\n        ## Checks above ensure either dim1 or dim2 vector\n        x = x(! isnan (x));\n        n = numel (x);\n        if (n == 0)\n          m = NaN (sz_out, outtype);\n        else\n          k = floor ((n + 1) / 2);\n          if (mod (n, 2))\n            m = nth_element (x, k);\n          else\n            vals = nth_element (x, [k, k + 1]);\n            m = mid_two_vals (vals(1), vals(2), isa (x, \"integer\"));\n          endif\n        endif\n\n      else\n        ## Columns may have different non-NaN counts; process individually.\n        n = szx(1);\n        rest_sz = szx(2 : end);\n        ncols = prod (rest_sz);\n\n        if (ndims (x) > 2)\n          x = reshape (x, [n, ncols]);\n        endif\n\n        if (isfloat (x))\n          m = NaN (1, ncols);\n        else\n          m = zeros (1, ncols, outtype);\n        endif\n\n        x = reshape (x, [n, ncols]);\n\n        for j = 1:ncols\n          col = x(:, j);\n          col = col(! isnan (col));\n          ncol = numel (col);\n\n          if (ncol == 0)\n            continue;\n          endif\n\n          k = floor ((ncol + 1) / 2);\n          if (mod (ncol, 2))\n            m(j) = nth_element (col, k);\n          else\n            vals = nth_element (col, [k, k + 1]);\n            m(j) = mid_two_vals (vals(1), vals(2), isa (x, \"integer\"));\n          endif\n        endfor\n\n        if (numel (rest_sz) > 1)\n          m = reshape (m, [1, rest_sz]);\n        endif\n      endif\n\n    else\n      ## No \"omitnan\". All types without a NaN value will use this path.\n      if (all (! nanfree(:)))\n        m = NaN (sz_out);\n\n      else\n        if (isvector (x))\n          n = numel (x);\n          k = floor ((n + 1) / 2);\n\n          if (all (! nanfree(:)))\n            m = NaN (sz_out);\n          else\n            if (mod (n, 2))\n              ## Odd\n              m = nth_element (x, k);\n            else\n              ## Even\n              vals = nth_element (x, [k, k + 1]);\n              m = mid_two_vals (vals(1), vals(2), isa (x, \"integer\"));\n            endif\n          endif\n\n        else\n          ## Nonvector, all operations were permuted to be along dim 1\n          n = szx(1);\n          k = floor ((n + 1) / 2);\n          rest_sz = szx(2 : end);\n          ncols = prod (rest_sz);\n\n          if (isfloat (x))\n            m = NaN (1, ncols);\n          else\n            m = zeros (1, ncols, outtype);\n          endif\n\n          if (ndims (x) > 2)\n            x = reshape (x, [n, ncols]);\n            nanfree = reshape (nanfree, [1, ncols]);\n          endif\n\n          if (mod (n, 2))\n            ## Odd.  Use flattened index to simplify N-D operations\n            if (any (nanfree(:)))\n              vals = nth_element (x(:, nanfree), k, 1);\n              m(nanfree) = vals;\n            endif\n          else\n            ## Even\n            if (any (nanfree(:)))\n              vals = nth_element (x(:, nanfree), [k, k + 1], 1);\n              m(nanfree) = mid_two_vals (vals(1, :), vals(2, :), isa (x, \"integer\"));\n            endif\n          endif\n\n          if (numel (rest_sz) > 1)\n            m = reshape (m, [1, rest_sz]);\n          endif\n        endif\n      endif\n    endif\n  endif\n\n  if (perm_flag)\n    ## Inverse permute back to correct dimensions\n    m = ipermute (m, perm);\n  endif\n\n  ## Convert output type as requested\n  if (! strcmp (class (m), outtype))\n    m = feval (outtype, m);\n  endif\n\nendfunction\n\n\n## Compute mean of two middle values, handling Inf and integer overflow.\nfunction m = mid_two_vals (m1, m2, is_int)\n  if (is_int)\n    samesign = sign (m1) == sign (m2);\n    m = zeros (size (m1), \"like\", m1);\n    m(samesign) = m1(samesign) + (m2(samesign) - m1(samesign)) / 2;\n    m(! samesign) = (m1(! samesign) + m2(! samesign)) / 2;\n  else\n    m = (m1 + m2) / 2;\n  endif\nendfunction\n\n\n%!assert (median (1), 1)\n%!assert (median ([1, 2, 3]), 2)\n%!assert (median ([1, 2, 3]'), 2)\n%!assert (median (cat (3, 3, 1, 2)), 2)\n%!assert (median ([3, 1, 2]), 2)\n%!assert (median ([2, 4, 6, 8]), 5)\n%!assert (median ([8, 2, 6, 4]), 5)\n%!assert (median (single ([1, 2, 3])), single (2))\n%!assert (median ([1, 2], 3), [1, 2])\n\n%!test\n%! x = [1, 2, 3, 4, 5, 6];\n%! x2 = x';\n%! y = [1, 2, 3, 4, 5, 6, 7];\n%! y2 = y';\n%!\n%! assert (median (x) == median (x2) && median (x) == 3.5);\n%! assert (median (y) == median (y2) && median (y) == 4);\n%! assert (median ([x2, 2 * x2]), [3.5, 7]);\n%! assert (median ([y2, 3 * y2]), [4, 12]);\n\n## Test outtype option\n%!test\n%! in = [1, 2, 3];\n%! out = 2;\n%! assert (median (in, \"default\"), median (in));\n%! assert (median (in, \"default\"), out);\n%!test\n%! in = single ([1, 2, 3]);\n%! out = 2;\n%! assert (median (in, \"default\"), single (median (in)));\n%! assert (median (in, \"default\"), single (out));\n%! assert (median (in, \"double\"), double (out));\n%! assert (median (in, \"native\"), single (out));\n%!test\n%! in = uint8 ([1, 2, 3]);\n%! out = 2;\n%! assert (median (in, \"default\"), double (median (in)));\n%! assert (median (in, \"default\"), double (out));\n%! assert (median (in, \"double\"), out);\n%! assert (median (in, \"native\"), uint8 (out));\n%!test\n%! in = logical ([1, 0, 1]);\n%! out = 1;\n%! assert (median (in, \"default\"), double (median (in)));\n%! assert (median (in, \"default\"), double (out));\n%! assert (median (in, \"double\"), double (out));\n%! assert (median (in, \"native\"), double (out));\n\n## Test single input and optional arguments \"all\", DIM, \"omitnan\"\n%!test\n%! x = repmat ([2 2.1 2.2 2 NaN; 3 1 2 NaN 5; 1 1.1 1.4 5 3], [1, 1, 4]);\n%! y = repmat ([2 1.1 2 NaN NaN], [1, 1, 4]);\n%! assert (median (x), y);\n%! assert (median (x, 1), y);\n%! y = repmat ([2, 1.1, 2, 3.5, 4], [1, 1, 4]);\n%! assert (median (x, \"omitnan\"), y);\n%! assert (median (x, 1, \"omitnan\"), y);\n%! y = repmat ([2.05; 2.5; 1.4], [1, 1, 4]);\n%! assert (median (x, 2, \"omitnan\"), y);\n%! y = repmat ([NaN; NaN; 1.4], [1, 1, 4]);\n%! assert (median (x, 2), y);\n%! assert (median (x, \"all\"), NaN);\n%! assert (median (x, \"all\", \"omitnan\"), 2);\n%!assert (median (cat (3, 3, 1, NaN, 2), \"omitnan\"), 2)\n%!assert (median (cat (3, 3, 1, NaN, 2), 3, \"omitnan\"), 2)\n\n## Test boolean input\n%!test\n%! assert (median (true, \"all\"), logical (1));\n%! assert (median (false), logical (0));\n%! assert (median ([true, false, true]), true);\n%! assert (median ([true, false, true], 2), true);\n%! assert (median ([true, false, true], 1), logical ([1 0 1]));\n%! assert (median ([true, false, NaN], 1), [1, 0, NaN]);\n%! assert (median ([true, false, NaN], 2), NaN);\n%! assert (median ([true, false, NaN], 2, \"omitnan\"), 0.5);\n%! assert (median ([true, false, NaN], 2, \"omitnan\", \"native\"), double (0.5));\n\n## Test dimension indexing with vecdim in N-dimensional arrays\n%!test\n%! x = repmat ([1:20; 6:25], [5, 2, 6, 3]);\n%! assert (size (median (x, [3, 2])), [10, 1, 1, 3]);\n%! assert (size (median (x, [1, 2])), [1, 1, 6, 3]);\n%! assert (size (median (x, [1, 2, 4])), [1, 1, 6]);\n%! assert (size (median (x, [1, 4, 3])), [1, 40]);\n%! assert (size (median (x, [1, 2, 3, 4])), [1, 1]);\n\n## Test exceeding dimensions\n%!assert (median (ones (2, 2), 3), ones (2, 2))\n%!assert (median (ones (2, 2, 2), 99), ones (2, 2, 2))\n%!assert (median (magic (3), 3), magic (3))\n%!assert (median (magic (3), [1, 3]), [4, 5, 6])\n%!assert (median (magic (3), [1, 99]), [4, 5, 6])\n\n## Test results with vecdim in N-dimensional arrays and \"omitnan\"\n%!test\n%! x = repmat ([2 2.1 2.2 2 NaN; 3 1 2 NaN 5; 1 1.1 1.4 5 3], [1, 1, 4]);\n%! assert (median (x, [3, 2]), [NaN, NaN, 1.4]');\n%! assert (median (x, [3, 2], \"omitnan\"), [2.05, 2.5, 1.4]');\n%! assert (median (x, [1, 3]), [2, 1.1, 2, NaN, NaN]);\n%! assert (median (x, [1, 3], \"omitnan\"), [2, 1.1, 2, 3.5, 4]);\n\n## Test empty, NaN, Inf inputs\n%!assert (median (NaN), NaN)\n%!assert (median (NaN, \"omitnan\"), NaN)\n%!assert (median (NaN (2)), [NaN, NaN])\n%!assert (median (NaN (2), \"omitnan\"), [NaN, NaN])\n%!assert (median ([1, NaN, 3]), NaN)\n%!assert (median ([1, NaN, 3], 1), [1, NaN, 3])\n%!assert (median ([1, NaN, 3], 2), NaN)\n%!assert (median ([1, NaN, 3]'), NaN)\n%!assert (median ([1, NaN, 3]', 1), NaN)\n%!assert (median ([1, NaN, 3]', 2), [1; NaN; 3])\n%!assert (median ([1, NaN, 3], \"omitnan\"), 2)\n%!assert (median ([1, NaN, 3]', \"omitnan\"), 2)\n%!assert (median ([1, NaN, 3], 1, \"omitnan\"), [1, NaN, 3])\n%!assert (median ([1, NaN, 3], 2, \"omitnan\"), 2)\n%!assert (median ([1, NaN, 3]', 1, \"omitnan\"), 2)\n%!assert (median ([1, NaN, 3]', 2, \"omitnan\"), [1; NaN; 3])\n%!assert (median ([1, 2, NaN, 3]), NaN)\n%!assert (median ([1, 2, NaN, 3], \"omitnan\"), 2)\n%!assert (median ([1,2,NaN;4,5,6;NaN,8,9]), [NaN, 5, NaN])\n%!assert <*64011> (median ([1,2,NaN;4,5,6;NaN,8,9], \"omitnan\"), [2.5, 5, 7.5], eps)\n%!assert (median ([1, 2 ; NaN, 4]), [NaN, 3])\n%!assert (median ([1, 2 ; NaN, 4], \"omitnan\"), [1, 3])\n%!assert (median ([1, 2 ; NaN, 4], 1, \"omitnan\"), [1, 3])\n%!assert (median ([1, 2 ; NaN, 4], 2, \"omitnan\"), [1.5; 4], eps)\n%!assert (median ([1, 2 ; NaN, 4], 3, \"omitnan\"), [1, 2 ; NaN, 4])\n%!assert (median ([NaN, 2 ; NaN, 4]), [NaN, 3])\n%!assert (median ([NaN, 2 ; NaN, 4], \"omitnan\"), [NaN, 3])\n%!assert (median (ones (1, 0, 3)), NaN (1, 1, 3))\n\n## Tests for per-element Inf handling in even-length median\n%!assert (median ([-Inf, 2; 1, 3], 1), [-Inf, 2.5]);\n%!assert (median ([-Inf, Inf; Inf, -Inf], 1), [NaN, NaN]);\n%!assert (median ([1, Inf, 3; 5, 7, 9], 1), [3, Inf, 6]);\n%!assert (median (int64 ([10, 20; 30, 40]), 1), int64 ([20, 30]));\n\n## Test all NaN vectors and arrays\n%!assert <*65405> (median ([NaN, NaN], 1, \"omitnan\"), [NaN, NaN])\n%!assert <*65405> (median ([NaN, NaN], 2, \"omitnan\"), NaN)\n%!assert <*65405> (median ([NaN, NaN]', 1, \"omitnan\"), NaN)\n%!assert <*65405> (median ([NaN, NaN]', 2, \"omitnan\"), [NaN; NaN])\n%!assert <*65405> (median ([NaN, NaN], \"omitnan\"), NaN)\n%!assert <*65405> (median ([NaN, NaN]', \"omitnan\"), NaN)\n%!assert <*65405> (median (NaN (1, 9), 1, \"omitnan\"), NaN (1, 9))\n%!assert <*65405> (median (NaN (1, 9), 2, \"omitnan\"), NaN)\n%!assert <*65405> (median (NaN (1, 9), 3, \"omitnan\"), NaN (1, 9))\n%!assert <*65405> (median (NaN (9, 1), 1, \"omitnan\"), NaN)\n%!assert <*65405> (median (NaN (9, 1), 2, \"omitnan\"), NaN (9, 1))\n%!assert <*65405> (median (NaN (9, 1), 3, \"omitnan\"), NaN (9, 1))\n%!assert <*65405> (median (NaN (9, 2), 1, \"omitnan\"), NaN (1, 2))\n%!assert <*65405> (median (NaN (9, 2), 2, \"omitnan\"), NaN (9, 1))\n%!assert <*65405> (median (NaN (9, 2), \"omitnan\"), NaN (1, 2))\n\n## Test single inputs\n%!assert (median (NaN (\"single\")), NaN (\"single\"))\n%!assert (median (NaN (\"single\"), \"omitnan\"), NaN (\"single\"))\n%!assert (median (NaN (\"single\"), \"double\"), NaN (\"double\"))\n%!assert (median (single ([1, 2 ; NaN, 4])), single ([NaN, 3]))\n%!assert (median (single ([1, 2 ; NaN, 4]), \"double\"), double ([NaN, 3]))\n%!assert (median (single ([1, 2 ; NaN, 4]), \"omitnan\"), single ([1, 3]))\n%!assert (median (single ([1, 2 ; NaN, 4]), \"omitnan\", \"double\"), double ([1, 3]))\n%!assert (median (single ([NaN, 2 ; NaN, 4]), \"double\"), double ([NaN 3]))\n%!assert (median (single ([NaN, 2 ; NaN, 4]), \"omitnan\"), single ([NaN 3]))\n%!assert (median (single ([NaN, 2 ; NaN, 4]), \"omitnan\", \"double\"), double ([NaN 3]))\n\n## Test omitnan with 2-D & 3-D inputs to confirm correct sub2ind orientation\n%!test <*64011>\n%! x = [magic(3), magic(3)];\n%! x([3, 7, 11, 12, 16, 17]) = NaN;\n%! ynan = [NaN, 5, NaN, NaN, 5, NaN];\n%! yomitnan = [5.5, 5, 4.5, 8, 5, 2];\n%! assert (median (x), ynan);\n%! assert (median (x, \"omitnan\"), yomitnan, eps);\n%! assert (median (cat (3, x, x)), cat (3, ynan, ynan));\n%! assert (median (cat (3, x, x), \"omitnan\"), cat (3, yomitnan, yomitnan), eps);\n\n%!assert (median (Inf), Inf)\n%!assert (median (-Inf), -Inf)\n%!assert (median ([-Inf, Inf]), NaN)\n%!assert (median ([3, Inf]), Inf)\n%!assert (median ([3, 4, Inf]), 4)\n%!assert (median ([Inf, 3, 4]), 4)\n%!assert (median ([Inf, 3, Inf]), Inf)\n\n%!assert (median ([1, 2, Inf]), 2)\n%!assert (median ([1, 2, Inf, Inf]), Inf)\n%!assert (median ([1, -Inf, Inf, Inf]), Inf)\n%!assert (median ([-Inf, -Inf, Inf, Inf]), NaN)\n%!assert (median([-Inf, Inf, Inf, Inf]), Inf)\n%!assert (median([-Inf, -Inf, -Inf, Inf]), -Inf)\n%!assert (median([-Inf, -Inf, -Inf, 2]), -Inf)\n%!assert (median([-Inf, -Inf, 1, 2]), -Inf)\n\n%!assert (median ([Inf, Inf, NaN]), NaN)\n%!assert (median ([-Inf, Inf, NaN]), NaN)\n%!assert (median ([Inf, Inf, NaN], \"omitnan\"), Inf)\n%!assert (median ([-Inf, Inf, NaN], \"omitnan\"), NaN)\n%!assert (median ([-Inf, Inf, 3, NaN], \"omitnan\"), 3)\n%!assert (median ([-Inf, Inf, 3, -Inf, NaN], \"omitnan\"), -Inf)\n\n%!assert (median ([]), NaN)\n%!assert (median (ones (1, 0)), NaN)\n%!assert (median (ones (0, 1)), NaN)\n%!assert (median ([], 1), NaN (1, 0))\n%!assert (median ([], 2), NaN (0, 1))\n%!assert (median ([], 3), NaN (0, 0))\n%!assert (median (ones (1, 0), 1), NaN (1, 0))\n%!assert (median (ones (1, 0), 2), NaN (1, 1))\n%!assert (median (ones (1, 0), 3), NaN (1, 0))\n%!assert (median (ones (0, 1), 1), NaN (1, 1))\n%!assert (median (ones (0, 1), 2), NaN (0, 1))\n%!assert (median (ones (0, 1), 3), NaN (0, 1))\n%!assert (median (ones (0, 1, 0, 1), 1), NaN (1, 1, 0))\n%!assert (median (ones (0, 1, 0, 1), 2), NaN (0, 1, 0))\n%!assert (median (ones (0, 1, 0, 1), 3), NaN (0, 1, 1))\n%!assert (median (ones (0, 1, 0, 1), 4), NaN (0, 1, 0))\n\n## Test complex inputs (should sort by abs(a))\n%!assert (median ([1, 3, 3i, 2, 1i]), 2)\n%!assert (median ([1, 2, 4i; 3, 2i, 4]), [2, 1+1i, 2+2i])\n\n## Test multi-dimensional arrays\n%!shared a, b, x, y\n%! old_state = rand (\"state\");\n%! restore_state = onCleanup (@() rand (\"state\", old_state));\n%! rand (\"state\", 2);\n%! a = rand (2, 3, 4, 5);\n%! b = rand (3, 4, 6, 5);\n%! x = sort (a, 4);\n%! y = sort (b, 3);\n%!assert <*35679> (median (a, 4), x(:, :, :, 3))\n%!assert <*35679> (median (b, 3), (y(:, :, 3, :) + y(:, :, 4, :))/2)\n%!shared   # Clear shared to prevent variable echo for any later test failures\n\n## Test N-dimensional arrays with odd non-NaN data points\n%!test\n%! x = ones (15, 1, 4);\n%! x([13,15], 1, :) = NaN;\n%! assert (median (x, 1, \"omitnan\"), ones (1, 1, 4));\n\n## Test non-floating point types\n%!assert (median ([true, false]), true)\n%!assert (median (logical ([])), false)\n%!assert (median (uint8 ([1, 3])), uint8 (2))\n%!assert (median (uint8 ([])), uint8 (NaN))\n%!assert (median (uint8 ([NaN 10])), uint8 (5))\n%!assert (median (int8 ([1, 3, 4])), int8 (3))\n%!assert (median (int8 ([])), int8 (NaN))\n%!assert (median (single ([1, 3, 4])), single (3))\n%!assert (median (single ([1, 3, NaN])), single (NaN))\n\n## Test same sign int overflow when getting mean of even number of values\n%!assert <*54567> (median (uint8 ([253, 255])), uint8 (254))\n%!assert <*54567> (median (uint8 ([253, 254])), uint8 (254))\n%!assert <*54567> (median (int8 ([127, 126, 125, 124; 1 3 5 9])), ...\n%!                 int8 ([64 65 65 67]))\n%!assert <*54567> (median (int8 ([127, 126, 125, 124; 1 3 5 9]), 2), ...\n%!                 int8 ([126; 4]))\n%!assert <*54567> (median (int64 ([intmax(\"int64\"), intmax(\"int64\")-2])), ...\n%!                 intmax (\"int64\") - 1)\n%!assert <*54567> (median ( ...\n%!                 int64 ([intmax(\"int64\"), intmax(\"int64\")-2; 1 2]), 2), ...\n%!                 int64([intmax(\"int64\") - 1; 2]))\n%!assert <*54567> (median (uint64 ([intmax(\"uint64\"), intmax(\"uint64\")-2])), ...\n%!                 intmax (\"uint64\") - 1)\n%!assert <*54567> (median ( ...\n%!                 uint64 ([intmax(\"uint64\"), intmax(\"uint64\")-2; 1 2]), 2), ...\n%!                 uint64([intmax(\"uint64\") - 1; 2]))\n\n## Test opposite sign int overflow when getting mean of even number of values\n%!assert <*54567> (median (...\n%! [intmin('int8'), intmin('int8')+5, intmax('int8')-5, intmax('int8')]), ...\n%! int8 (-1))\n%!assert <*54567> (median ([int8([1 2 3 4]); ...\n%! intmin('int8'), intmin('int8')+5, intmax('int8')-5, intmax('int8')], 2), ...\n%! int8 ([3;-1]))\n%!assert <*54567> (median (...\n%! [intmin('int64'), intmin('int64')+5, intmax('int64')-5, intmax('int64')]), ...\n%! int64 (-1))\n%!assert <*54567> (median ([int64([1, 2, 3, 4]); ...\n%! intmin('int64'), intmin('int64')+5, intmax('int64')-5, intmax('int64')], 2), ...\n%! int64 ([3;-1]))\n\n## Test int accuracy loss doing mean of close int64/uint64 values as double\n%!assert <*54567> (median ([intmax(\"uint64\"), intmax(\"uint64\")-2]), ...\n%!                 intmax (\"uint64\")-1)\n%!assert <*54567> (median ([intmax(\"uint64\"), intmax(\"uint64\")-2], \"default\"), ...\n%!                 double (intmax (\"uint64\")-1))\n%!assert <*54567> (median ([intmax(\"uint64\"), intmax(\"uint64\")-2], \"double\"), ...\n%!                 double (intmax (\"uint64\")-1))\n%!assert <*54567> (median ([intmax(\"uint64\"), intmax(\"uint64\")-2], \"native\"), ...\n%!                 intmax (\"uint64\")-1)\n\n## Test input case insensitivity\n%!assert (median ([1 2 3], \"aLL\"), 2)\n%!assert (median ([1 2 3], \"OmitNan\"), 2)\n%!assert (median ([1 2 3], \"DOUBle\"), 2)\n\n## Test sparse matrix input\n%!assert (median (sparse (magic (3))), sparse ([4, 5, 6]))\n%!assert (median (sparse (magic (3)), 1), sparse ([4, 5, 6]))\n%!assert (median (sparse (magic (3)), 1, \"omitnan\"), sparse ([4, 5, 6]))\n%!assert (median (sparse (magic (3)), 2), sparse ([6; 5; 4]))\n%!assert (median (sparse (magic (3)), 2, \"omitnan\"), sparse ([6; 5; 4]))\n%!assert (median (sparse (magic (3)), \"all\"), sparse (5))\n%!assert (median (sparse (magic (3)), \"all\", \"omitnan\"), sparse (5))\n%!assert (median (sparse (magic (3)), [1, 2]), sparse (5))\n%!assert (median (sparse (magic (3)), [1, 2], \"omitnan\"), sparse (5))\n%!assert (median (sparse (magic (3)), 3), sparse (magic (3)))\n%!assert (median (sparse (magic (3)), 3, \"omitnan\"), sparse (magic (3)))\n%!assert (median (sparse ([NaN, NaN])), sparse (NaN))\n%!assert (median (sparse ([NaN, NaN]), 1), sparse ([NaN, NaN]))\n%!assert (median (sparse ([NaN, NaN]), 2), sparse (NaN))\n%!assert (median (sparse ([])), sparse (NaN))\n%!assert (median (sparse ([]), 1), sparse (NaN (1, 0)))\n%!assert (median (sparse ([]), 2), sparse (NaN (0, 1)))\n%!assert (median (sparse ([]), 3), sparse ([]))\n\n## Test input validation\n%!error <Invalid call> median ()\n%!error <Invalid call> median (1, 2, 3)\n%!error <Invalid call> median (1, 2, 3, 4)\n%!error <Invalid call> median (1, \"all\", 3)\n%!error <Invalid call> median (1, \"b\")\n%!error <Invalid call> median (1, 1, \"foo\")\n%!error <'all' cannot be used with> median (1, 3, \"all\")\n%!error <'all' cannot be used with> median (1, [2 3], \"all\")\n%!error <X must be either numeric or logical> median ({1:5})\n%!error <X must be either numeric or logical> median (\"char\")\n%!error <only one OUTTYPE can be specified> median (1, \"double\", \"native\")\n%!error <DIM must be a positive integer> median (1, ones (2,2))\n%!error <DIM must be a positive integer> median (1, 1.5)\n%!error <DIM must be a positive integer> median (1, 0)\n%!error <DIM must be a positive integer> median ([1 2 3], [-1 1])\n%!error <VECDIM must contain non-repeating> median (1, [1 2 2])\n"
  },
  {
    "path": "scripts/statistics/mode.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{m} =} mode (@var{x})\n## @deftypefnx {} {@var{m} =} mode (@var{x}, @var{dim})\n## @deftypefnx {} {@var{m} =} mode (@var{x}, @var{vecdim})\n## @deftypefnx {} {@var{m} =} mode (@var{x}, \"all\")\n## @deftypefnx {} {[@var{m}, @var{f}, @var{c}] =} mode (@dots{})\n## Compute the most frequently occurring value in the input data @var{x}.\n##\n## @code{mode} determines the frequency of values along the first non-singleton\n## dimension and returns the value with the highest frequency.  If two, or\n## more, values have the same frequency @code{mode} returns the smallest.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @var{x}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.  If all dimensions in\n## @var{vecdim} are greater than @code{ndims (@var{x})}, then @code{mode}\n## will return @var{x}.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{mode} to operate\n## on all elements of @var{x}, and is equivalent to @code{mode (@var{x}(:))}.\n##\n## The return variable @var{f} is the number of occurrences of the mode in\n## the dataset.\n##\n## The cell array @var{c} contains all of the elements with the maximum\n## frequency.\n## @seealso{mean, median}\n## @end deftypefn\n\nfunction [m, f, c] = mode (x, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x)))\n    error (\"mode: X must be a numeric array\");\n  endif\n\n  do_perm = false;\n  nd = ndims (x);\n  sz = size (x);\n  empty_x = isempty (x);\n\n  if (nargin < 2)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz != 1, 1)) || (dim = 1);\n\n    ## Return immediately for an empty matrix.\n    if (empty_x)\n      ## Empty x produces NaN for m, 0 for f, , but m, f and c\n      ## shape depends on size of x.\n      if (nd == 2 && all (sz == 0))\n        f = 0; # f always a double even if x is single.\n        if (isa (x, \"single\"))\n          m = NaN (\"single\");\n          c = {(NaN (0, 1, \"single\"))};\n        else\n          m = NaN;\n          c = {(NaN (0, 1))};\n        endif\n      else\n        sz(dim) = 1;\n        f = zeros (sz); # f always a double even if x is single.\n        c = cell (sz);\n        if (isa (x, \"single\"))\n          m = NaN (sz, \"single\");\n          c(:) = NaN (1, 0, \"single\");\n        else\n          m = NaN (sz);\n          c(:) = NaN (1, 0);\n        endif\n      endif\n      return;\n    endif\n  endif\n\n  if (isnumeric (dim))\n\n    ## Check for DIM argument\n    if (isscalar (dim))\n      if (! (dim == fix (dim) && dim > 0))\n        error (\"mode: DIM must be a positive integer\");\n      endif\n\n      ## Return immediately for an empty matrix.\n      if (empty_x)\n        ## Ignore exceeding dimension\n        if (dim <= nd)\n          sz(dim) = 1;\n        endif\n        f = zeros (sz); # f always a double even if x is single.\n        c = cell (sz);\n        if (isa (x, \"single\"))\n          m = NaN (sz, \"single\");\n          c(:) = NaN (1, 0, \"single\");\n        else\n          m = NaN (sz);\n          c(:) = NaN (1, 0);\n        endif\n        return;\n      endif\n\n      if (dim > nd || sz(dim) == 1)\n        ## Special case of mode over singleton dimension.\n        m = x;\n        f = ones (size (x));\n        c = num2cell (x);\n        return;\n      endif\n\n    ## Check for proper VECDIM (more than 1 dim, no repeats)\n    elseif (isvector (dim) && isindex (dim) && all (diff (sort (dim))))\n\n      ## Discard exceeding dims, unless all dims > nd so keep smallest\n      vecdim = dim(dim <= nd);\n      if (isempty (vecdim))\n        dim = min (dim);\n      else\n        dim = vecdim;\n      endif\n\n      ## Return immediately for an empty matrix.\n      if (empty_x)\n        ## Ignore exceeding dimension\n        if (all (dim <= nd))\n          sz(dim) = 1;\n        endif\n        f = zeros (sz); # f always a double even if x is single.\n        c = cell (sz);\n        if (isa (x, \"single\"))\n          m = NaN (sz, \"single\");\n          c(:) = NaN (1, 0, \"single\");\n        else\n          m = NaN (sz);\n          c(:) = NaN (1, 0);\n        endif\n        return;\n      endif\n\n      ## Return numel (p) copies of X if remaining DIM > nd\n      if (any (dim > nd) || all (sz(dim) == 1))\n        ## Special case of mode over singleton dimensions.\n        m = x;\n        f = ones (size (x));\n        c = num2cell (x);\n        return;\n      endif\n\n      ## Detect trivial case of DIM being all dimensions (same as \"all\").\n      vecdims = numel (dim);\n      max_dim = max (nd, max (dim));\n      if (vecdims == nd && max_dim == nd)\n        x = x(:);\n        sz = size (x);\n        dim = 1;\n      else\n        ## Algorithm: Move dimensions for operation to the front, keeping the\n        ## order of the remaining dimensions.\n\n        dim = dim(:).';  # Force row vector\n\n        ## Permutation vector with DIM at front\n        perm = [1:max_dim];\n        perm(dim) = [];\n        perm = [dim, perm];\n        do_perm = true;\n\n        ## Reset vecdim and dim for permuted and reshaped x\n        vecdim = 1:numel (dim);\n        dim = 1;\n\n        ## Reshape X to put dims to process at front.\n        x = permute (x, perm);\n        sz = size (x);\n\n        ## Preserve trailing singletons when dim > ndims (x).\n        sx = [sz, ones(1, max_dim - numel (sz))];\n        sx = [prod(sx(1:vecdims)), ones(1, (vecdims-1)), sx((vecdims+1):end)];\n\n        ## Size must always have 2 dimensions.\n        if (isscalar (sx))\n          sx = [sx, 1];\n        endif\n\n        ## Collapse dimensions to be processsed into single column.\n        x = reshape (x, sx);\n      endif\n\n    else\n      error (\"mode: VECDIM must be a vector of non-repeating positive integers\");\n    endif\n\n  elseif (strcmpi (dim, \"all\"))\n\n    ## Return immediately for an empty matrix\n    if (empty_x)\n      f = 0; # f always a double even if x is single.\n      if (isa (x, \"single\"))\n        m = single (NaN);\n        c = {(NaN (1, 0, \"single\"))};\n      else\n        m = NaN;\n        c = {(NaN (1, 0))};\n      endif\n      return;\n    endif\n\n    ## \"all\" simplifies to collapsing all elements to single vector.\n    x = x(:);\n    sz = size (x);\n    dim = 1;\n\n  else\n    error (\"mode: DIM must be a positive integer scalar, vector, or 'all'\");\n  endif\n\n  sx = sz;\n  if (do_perm)\n    sx(vecdim) = 1;\n  else\n    sx(dim) = 1;\n  endif\n\n  if (issparse (x))\n    t2 = sparse (sz(1), sz(2));\n  else\n    t2 = zeros (sz);\n  endif\n\n  if (dim != 1)\n    perm = [dim, 1:dim-1, dim+1:nd];\n    t2 = permute (t2, perm);\n  endif\n\n  xs = sort (x, dim);\n  t = cat (dim, true (sx), diff (xs, 1, dim) != 0);\n\n  if (dim != 1)\n    t2(permute (t != 0, perm)) = diff ([find(permute (t, perm))(:); prod(sz)+1]);\n    f = max (ipermute (t2, perm), [], dim);\n    xs = permute (xs, perm);\n  else\n    t2(t) = diff ([find(t)(:); prod(sz)+1]);\n    f = max (t2, [], dim);\n  endif\n\n  c = cell (sx);\n  if (issparse (x))\n    m = sparse (sx(1), sx(2));\n  else\n    m = zeros (sx, class (x));\n  endif\n  for i = 1 : prod (sx)\n    c{i} = xs(t2(:, i) == f(i), i);\n    m(i) = c{i}(1);\n  endfor\n\n  ## Permute the 1st index back to dim.\n  if (do_perm)\n    m = ipermute (m, perm);\n    f = ipermute (f, perm);\n    c = ipermute (c, perm);\n  endif\n\nendfunction\n\n\n%!test\n%! [m, f, c] = mode (toeplitz (1:5));\n%! assert (m, [1,2,2,2,1]);\n%! assert (f, [1,2,2,2,1]);\n%! assert (c, {[1;2;3;4;5],[2],[2;3],[2],[1;2;3;4;5]});\n%!test\n%! [m, f, c] = mode (toeplitz (1:5), 2);\n%! assert (m, [1;2;2;2;1]);\n%! assert (f, [1;2;2;2;1]);\n%! assert (c, {[1;2;3;4;5];[2];[2;3];[2];[1;2;3;4;5]});\n%!test\n%! a = sprandn (32, 32, 0.05);\n%! sp0 = sparse (0);\n%! [m, f, c] = mode (a);\n%! [m2, f2, c2] = mode (full (a));\n%! assert (m, sparse (m2));\n%! assert (f, sparse (f2));\n%! c_exp(1:length (a)) = { sp0 };\n%! assert (c ,c_exp);\n%! assert (c2,c_exp);\n\n%!assert (mode ([2,3,1,2,3,4],1),[2,3,1,2,3,4])\n%!assert (mode ([2,3,1,2,3,4],2),2)\n%!assert (mode ([2,3,1,2,3,4]),2)\n%!assert (mode (single ([2,3,1,2,3,4])), single (2))\n%!assert (mode (int8 ([2,3,1,2,3,4])), int8 (2))\n\n%!assert (mode ([2;3;1;2;3;4],1),2)\n%!assert (mode ([2;3;1;2;3;4],2),[2;3;1;2;3;4])\n%!assert (mode ([2;3;1;2;3;4]),2)\n\n%!test\n%! x = magic (3);\n%! [m, f, c] = mode (x, 3);\n%! assert (m, x);\n%! assert (f, ones (3,3));\n%! assert (c, num2cell (x));\n\n%!test\n%! x = single (magic (3));\n%! [m, f, c] = mode (x, 3);\n%! assert (class (m), \"single\");\n%! assert (class (f), \"double\");\n%! assert (class (c), \"cell\");\n%! assert (class (c(1)), \"cell\");\n%! assert (class (c{1}), \"single\");\n\n%!shared x\n%! x(:,:,1) = toeplitz (1:3);\n%! x(:,:,2) = circshift (toeplitz (1:3), 1);\n%! x(:,:,3) = circshift (toeplitz (1:3), 2);\n%!test\n%! [m, f, c] = mode (x, 1);\n%! assert (reshape (m, [3, 3]), [1 1 1; 2 2 2; 1 1 1]);\n%! assert (reshape (f, [3, 3]), [1 1 1; 2 2 2; 1 1 1]);\n%! c = reshape (c, [3, 3]);\n%! assert (c{1}, [1; 2; 3]);\n%! assert (c{2}, 2);\n%! assert (c{3}, [1; 2; 3]);\n%!test\n%! [m, f, c] = mode (x, 2);\n%! assert (reshape (m, [3, 3]), [1 1 2; 2 1 1; 1 2 1]);\n%! assert (reshape (f, [3, 3]), [1 1 2; 2 1 1; 1 2 1]);\n%! c = reshape (c, [3, 3]);\n%! assert (c{1}, [1; 2; 3]);\n%! assert (c{2}, 2);\n%! assert (c{3}, [1; 2; 3]);\n%!test\n%! [m, f, c] = mode (x, 3);\n%! assert (reshape (m, [3, 3]), [1 2 1; 1 2 1; 1 2 1]);\n%! assert (reshape (f, [3, 3]), [1 2 1; 1 2 1; 1 2 1]);\n%! c = reshape (c, [3, 3]);\n%! assert (c{1}, [1; 2; 3]);\n%! assert (c{2}, [1; 2; 3]);\n%! assert (c{3}, [1; 2; 3]);\n%!shared   ## Clear shared to prevent variable echo for any later test failures\n\n## Test empty inputs\n%!test <*48690>\n%! [m, f, c] = mode ([]);\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (0, 1))});\n%!test <*48690>\n%! [m, f, c] = mode (single ([]));\n%! assert (class (m), \"single\");\n%! assert (class (f), \"double\");\n%! assert (c, {(single (NaN (0, 1)))});\n%!test <*48690>\n%! [m, f, c] = mode ([], 1);\n%! assert (m, NaN (1, 0));\n%! assert (f, zeros (1, 0));\n%! assert (c, cell (1, 0));\n%!test <*48690>\n%! [m, f, c] = mode ([], 2);\n%! assert (m, NaN (0, 1));\n%! assert (f, zeros (0, 1));\n%! assert (c, cell (0, 1));\n%!test <*48690>\n%! [m, f, c] = mode ([], 3);\n%! assert (m, []);\n%! assert (f, []);\n%! assert (c, cell (0, 0));\n%!test <*48690>\n%! [m, f, c] = mode (ones (0, 1));\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test <*48690>\n%! [m, f, c] = mode (ones (0, 1), 1);\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test <*48690>\n%! [m, f, c] = mode (ones (0, 1), 2);\n%! assert (m, NaN (0, 1));\n%! assert (f, zeros (0, 1));\n%! assert (c, cell (0, 1));\n%!test <*48690>\n%! [m, f, c] = mode (ones (0, 1), 3);\n%! assert (m, NaN (0, 1));\n%! assert (f, zeros (0, 1));\n%! assert (c, cell (0, 1));\n%!test <*48690>\n%! [m, f, c] = mode (ones (1, 0));\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test <*48690>\n%! [m, f, c] = mode (ones (1, 0), 1);\n%! assert (m, NaN (1, 0));\n%! assert (f, zeros (1, 0));\n%! assert (c, cell (1, 0));\n%!test <*48690>\n%! [m, f, c] = mode (ones (1, 0), 2);\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test <*48690>\n%! [m, f, c] = mode (ones (1, 0), 3);\n%! assert (m, NaN (1, 0));\n%! assert (f, zeros (1, 0));\n%! assert (c, cell (1, 0));\n%!test <*48690>\n%! [m, f, c] = mode (ones (0, 0, 0));\n%! assert (m, NaN (1, 0, 0));\n%! assert (f, zeros (1, 0, 0));\n%! assert (c, cell (1, 0, 0));\n%!test <*48690>\n%! [m, f, c] = mode (ones (0, 0, 0), 1);\n%! assert (m, NaN (1, 0, 0));\n%! assert (f, zeros (1, 0, 0));\n%! assert (c, cell (1, 0, 0));\n%!test <*48690>\n%! [m, f, c] = mode (ones (0, 0, 0), 2);\n%! assert (m, NaN (0, 1, 0));\n%! assert (f, zeros (0, 1, 0));\n%! assert (c, cell (0, 1, 0));\n%!test <*48690>\n%! [m, f, c] = mode (ones (0, 0, 0), 3);\n%! assert (m, NaN (0, 0, 1));\n%! assert (f, zeros (0, 0, 1));\n%! assert (c, cell (0, 0, 1));\n%!test <*48690>\n%! [m, f, c] = mode (ones (1, 5, 0), 2);\n%! assert (m, NaN (1, 1, 0));\n%! assert (f, zeros (1, 1, 0));\n%! assert (c, cell (1, 1, 0));\n%!test <*48690>\n%! [m, f, c] = mode (ones (5, 1, 0), 2);\n%! assert (m, NaN (5, 1, 0));\n%! assert (f, zeros (5, 1, 0));\n%! assert (c, cell (5, 1, 0));\n%!test <*48690>\n%! [m, f, c] = mode (ones (2, 0));\n%! assert (m, NaN (1, 0));\n%! assert (f, zeros (1, 0));\n%! assert (c, cell (1, 0));\n%!test <*48690>\n%! [m, f, c] = mode (ones (0, 2));\n%! assert (m, NaN (1, 2));\n%! assert (f, zeros (1, 2));\n%! assert (c, {(NaN (1, 0)),(NaN (1, 0))});\n%!test <*48690>\n%! [m, f, c] = mode (ones (1, 1, 1, 0));\n%! assert (m, NaN (1, 1));\n%! assert (f, zeros (1, 1));\n%! assert (c, {(NaN (1, 0))});\n%!test <*48690>\n%! [m, f, c] = mode (ones (1, 1, 1, 0), 1);\n%! assert (m, NaN (1, 1, 1, 0));\n%! assert (f, zeros (1, 1, 1, 0));\n%! assert (c, cell (1,1,1,0));\n\n## Test more ampty inputs with vecdim and \"all\"\n%!test\n%! [m, f, c] = mode ([], [2, 3]);\n%! assert (m, NaN (0, 1));\n%! assert (f, zeros (0, 1));\n%! assert (c, cell (0, 1));\n%!test\n%! [m, f, c] = mode ([], [1, 3]);\n%! assert (m, NaN (1, 0));\n%! assert (f, zeros (1, 0));\n%! assert (c, cell (1, 0));\n%!test\n%! [m, f, c] = mode (ones (1, 0), [1, 2]);\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test\n%! [m, f, c] = mode (single (ones (1, 0)), [1, 2]);\n%! assert (m, single (NaN));\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0, \"single\"))});\n%!test\n%! [m, f, c] = mode (ones (0, 2), [1, 2]);\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test\n%! [m, f, c] = mode (ones (1, 0), [1, 3]);\n%! assert (m, NaN (1, 0));\n%! assert (f, zeros (1, 0));\n%! assert (c, cell (1, 0));\n%!test\n%! [m, f, c] = mode (ones (0, 2), [1, 3]);\n%! assert (m, [NaN, NaN]);\n%! assert (f, [0, 0]);\n%! assert (c, {(NaN (1, 0)), (NaN (1, 0))});\n%!test\n%! [m, f, c] = mode (ones (1, 0), [2, 3]);\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test\n%! [m, f, c] = mode (single (ones (1, 0)), [2, 3]);\n%! assert (m, single (NaN));\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0, \"single\"))});\n%!test\n%! [m, f, c] = mode (ones (0, 2), [2, 3]);\n%! assert (m, NaN (0, 1));\n%! assert (f, zeros (0, 1));\n%! assert (c, cell (0, 1));\n%!test\n%! [m, f, c] = mode (ones (1, 0), [4, 3]);\n%! assert (m, NaN (1, 0));\n%! assert (f, zeros (1, 0));\n%! assert (c, cell (1, 0));\n%!test\n%! [m, f, c] = mode (ones (0, 2), [4, 3]);\n%! assert (m, NaN (0, 2));\n%! assert (f, zeros (0, 2));\n%! assert (c, cell (0, 2));\n%!test\n%! [m, f, c] = mode (ones (1, 1, 1, 0), [2, 3]);\n%! assert (m, NaN (1, 1, 1, 0));\n%! assert (f, zeros (1, 1, 1, 0));\n%! assert (c, cell (1, 1, 1, 0));\n%!test\n%! [m, f, c] = mode (ones (1, 1, 1, 0), [1, 3]);\n%! assert (m, NaN (1, 1, 1, 0));\n%! assert (f, zeros (1, 1, 1, 0));\n%! assert (c, cell (1, 1, 1, 0));\n%!test\n%! [m, f, c] = mode (ones (1, 1, 1, 0), [1, 2]);\n%! assert (m, NaN (1, 1, 1, 0));\n%! assert (f, zeros (1, 1, 1, 0));\n%! assert (c, cell (1, 1, 1, 0));\n%!test\n%! [m, f, c] = mode (ones (1, 1, 1, 0), [1, 4]);\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test\n%! [m, f, c] = mode (ones (3, 0), 'all');\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test\n%! [m, f, c] = mode (ones (0, 3), 'all');\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test\n%! [m, f, c] = mode (ones (1, 0, 2, 3), 'all');\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test\n%! [m, f, c] = mode (ones (0, 3, 2, 1), 'all');\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test\n%! [m, f, c] = mode ([], 'all');\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n%!test\n%! [m, f, c] = mode (ones (0, 0, 2, 1), 'all');\n%! assert (m, NaN);\n%! assert (f, 0);\n%! assert (c, {(NaN (1, 0))});\n\n## Test vecdim and \"all\"\n%!test\n%! x = repmat ([1, 2, 1, 3, 2, 4, 3, 2, 1], 3, 1, 2);\n%! assert (mode (x, [1, 2]), repmat (1, [1, 1, 2]));\n%! assert (mode (x, [1, 3]), [1, 2, 1, 3, 2, 4, 3, 2, 1]);\n%! assert (mode (x, [2, 3]), [1; 1; 1]);\n%! assert (mode (x, [1, 2, 3]), 1);\n%! assert (mode (x, \"all\"), 1);\n\n## Test input validation\n%!error <Invalid call> mode ()\n%!error <mode: X must be a numeric array> mode ({1 2 3})\n%!error <mode: X must be a numeric array> mode ([true; false])\n%!error <mode: DIM must be a positive integer> mode (1, 1.5)\n%!error <mode: DIM must be a positive integer> mode (1, 0)\n%!error <mode: VECDIM must be a vector of non-repeating positive integers> ...\n%!       mode (1, [1, 2, 2])\n%!error <mode: VECDIM must be a vector of non-repeating positive integers> ...\n%!       mode (1, [1, 2, 0])\n%!error <mode: DIM must be a positive integer scalar, vector, or 'all'> ...\n%!       mode (1, \"some\")\n"
  },
  {
    "path": "scripts/statistics/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/bounds.m \\\n  %reldir%/center.m \\\n  %reldir%/corr.m \\\n  %reldir%/corrcoef.m \\\n  %reldir%/corrcov.m \\\n  %reldir%/cov.m \\\n  %reldir%/discrete_cdf.m \\\n  %reldir%/discrete_inv.m \\\n  %reldir%/discrete_pdf.m \\\n  %reldir%/discrete_rnd.m \\\n  %reldir%/empirical_cdf.m \\\n  %reldir%/empirical_inv.m \\\n  %reldir%/empirical_pdf.m \\\n  %reldir%/empirical_rnd.m \\\n  %reldir%/histc.m \\\n  %reldir%/iqr.m \\\n  %reldir%/kendall.m \\\n  %reldir%/kurtosis.m \\\n  %reldir%/mad.m \\\n  %reldir%/mape.m \\\n  %reldir%/mean.m \\\n  %reldir%/meansq.m \\\n  %reldir%/median.m \\\n  %reldir%/mode.m \\\n  %reldir%/moment.m \\\n  %reldir%/movmad.m \\\n  %reldir%/movmax.m \\\n  %reldir%/movmean.m \\\n  %reldir%/movmedian.m \\\n  %reldir%/movmin.m \\\n  %reldir%/movprod.m \\\n  %reldir%/movstd.m \\\n  %reldir%/movsum.m \\\n  %reldir%/movvar.m \\\n  %reldir%/normalize.m \\\n  %reldir%/prctile.m \\\n  %reldir%/quantile.m \\\n  %reldir%/range.m \\\n  %reldir%/ranks.m \\\n  %reldir%/rms.m \\\n  %reldir%/rmse.m \\\n  %reldir%/run_count.m \\\n  %reldir%/runlength.m \\\n  %reldir%/skewness.m \\\n  %reldir%/spearman.m \\\n  %reldir%/statistics.m \\\n  %reldir%/std.m \\\n  %reldir%/var.m \\\n  %reldir%/zscore.m\n\n%canon_reldir%dir = $(fcnfiledir)/statistics\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/statistics/moment.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{m} =} moment (@var{x}, @var{p})\n## @deftypefnx {} {@var{m} =} moment (@var{x}, @var{p}, @var{dim})\n## @deftypefnx {} {@var{m} =} moment (@var{x}, @var{p}, @var{vecdim})\n## @deftypefnx {} {@var{m} =} moment (@var{x}, @var{p}, \"all\")\n## @deftypefnx {} {@var{m} =} moment (@var{x}, @var{p}, @dots{}, @var{type})\n## Compute the @var{p}-th central moment of the input data @var{x}.\n##\n## The @var{p}-th central moment of @var{x} is defined as:\n## @tex\n## $$\n## {{1 \\over N} \\sum_{i=1}^N (x_i - \\bar{x})^p}\n## $$\n## where $\\bar{x}$ is the mean value of @var{x} and $N$ is the number of\n## elements of @var{x}.\n##\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## 1/N SUM_i (@var{x}(i) - mean(@var{x}))^@var{p}\n## @end group\n## @end example\n##\n## @noindent\n## where @math{N} is the length of the @var{x} vector.\n##\n## @end ifnottex\n##\n## If @var{x} is a vector, then @code{moment (@var{x})} computes the @var{p}-th\n## central moment of the data in @var{x}.\n##\n## If @var{x} is a matrix, then @code{moment (@var{x})} returns a vector with\n## element containing the @var{p}-th central moment of the corresponding column\n## in @var{x}.\n##\n## If @var{x} is an array, then @code{moment (@var{x})} computes the @var{p}-th\n## central moment along the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be a non-empty numeric array and any NaN values\n## along the operating dimension will return NaN for central moment.  The size\n## of @var{m} is equal to the size of @var{x} except for the operating\n## dimension, which becomes 1.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @var{x}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.  If all dimensions in\n## @var{vecdim} are greater than @code{ndims (@var{x})}, then @code{moment}\n## will return @var{x}.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{moment} to\n## operate on all elements of @var{x}, and is equivalent to\n## @code{moment (@var{x}(:))}.\n##\n## The optional fourth input argument, @var{type}, is a string specifying the\n## type of moment to be computed.\n## Valid options are:\n##\n## @table @asis\n## @item @qcode{\"c\"}\n## Central Moment (default).\n##\n## @item  @qcode{\"a\"}\n## @itemx @qcode{\"ac\"}\n## Absolute Central Moment.  The moment about the mean ignoring sign\n## defined as\n## @tex\n## $$\n## {{1 \\over N} \\sum_{i=1}^N {| x_i - \\bar{x} |}^p}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## 1/N SUM_i (abs (@var{x}(i) - mean(@var{x})))^@var{p}\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @item @qcode{\"r\"}\n## Raw Moment.  The moment about zero defined as\n## @tex\n## $$\n## {{1 \\over N} \\sum_{i=1}^N {x_i}^p}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## moment (@var{x}) = 1/N SUM_i @var{x}(i)^@var{p}\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @item @nospell{@qcode{\"ar\"}}\n## Absolute Raw Moment.  The moment about zero ignoring sign defined as\n## @tex\n## $$\n## {{1 \\over N} \\sum_{i=1}^N {|x_i|}^p}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## 1/N SUM_i ( abs (@var{x}(i)) )^@var{p}\n## @end group\n## @end example\n##\n## @end ifnottex\n## @end table\n## @seealso{var, skewness, kurtosis}\n## @end deftypefn\n\n## Can easily be made to work for continuous distributions (using quad)\n## as well, but how does the general case work?\n\nfunction m = moment (x, p, dim = [], type = 'c')\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x) || isempty (x))\n    error (\"moment: X must be a non-empty numeric array\");\n  endif\n\n  if (! (isnumeric (p) && isscalar (p)))\n    error (\"moment: P must be a numeric scalar\");\n  endif\n\n  sz = size (x);\n  if (isempty (dim))\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  elseif (strcmp (dim, \"all\"))\n    ## Handle \"all\" option so we can get sample size\n    x = x(:);\n    dim = 1;\n  endif\n\n  if (! (ischar (type) && isvector (type)))\n    error (\"moment: TYPE must be a character vector\");\n  endif\n\n  n = prod (size (x, dim));\n\n  if (! any (type == \"r\"))\n    x = center (x, dim);\n  endif\n  if (any (type == \"a\"))\n    x = abs (x);\n  endif\n\n  m = sum (x .^ p, dim) / n;\n\nendfunction\n\n\n%!shared x, xx\n%! x = rand (10);\n%! xx = randi (10, 4, 4, 4);\n%!assert (moment (x, 1), mean (center (x)), eps)\n%!assert (moment (x, 2), meansq (center (x)), eps)\n%!assert (moment (x, 1, 2), mean (center (x, 2), 2), eps)\n%!assert (moment (x, 1, [], \"a\"), mean (abs (center (x))), eps)\n%!assert (moment (x, 1, [], \"r\"), mean (x), eps)\n%!assert (moment (x, 1, [], \"ar\"), mean (abs (x)), eps)\n%!assert (moment (x, 1, 1, \"a\"), mean (abs (center (x)), 1), eps)\n%!assert (moment (x, 1, 1, \"r\"), mean (x, 1), eps)\n%!assert (moment (x, 1, 1, \"ar\"), mean (abs (x), 1), eps)\n%!assert (moment (x, 1, 2, \"a\"), mean (abs (center (x, 2)), 2), eps)\n%!assert (moment (x, 1, 2, \"r\"), mean (x, 2), eps)\n%!assert (moment (x, 1, 2, \"ar\"), mean (abs (x), 2), eps)\n\n%!assert (moment (single ([1 2 3]), 1, [], \"r\"), single (2))\n\n## Test vecdim and \"all\"\n%!assert (moment (x, 1, [1, 2]), mean (center (x, [1, 2]), [1, 2]), eps)\n%!assert (moment (x, 2, [1, 2]), meansq (center (x, [1, 2]), [1, 2]), eps)\n%!assert (moment (x, 1, [1, 3]), mean (center (x, [1, 3]), [1, 3]), eps)\n%!assert (moment (x, 2, [1, 3]), meansq (center (x, [1, 3]), [1, 3]), eps)\n%!assert (moment (x, 1, [2, 3]), mean (center (x, [2, 3]), [2, 3]), eps)\n%!assert (moment (x, 2, [2, 3]), meansq (center (x, [2, 3]), [2, 3]), eps)\n%!assert (moment (x, 1, \"all\"), mean (center (x, \"all\"), \"all\"), eps)\n%!assert (moment (x, 2, \"all\"), meansq (center (x, \"all\"), \"all\"), eps)\n\n%!assert (moment (1, 2, 4), 0)\n\n## Test input validation\n%!error <Invalid call> moment ()\n%!error <Invalid call> moment (1)\n%!error <moment: X must be a non-empty numeric array> moment (['A'; 'B'], 2)\n%!error <moment: X must be a non-empty numeric array> moment (ones (2,0,3), 2)\n%!error <moment: X must be a non-empty numeric array> moment ([], 1)\n%!error <moment: P must be a numeric scalar> moment (1, ones (2,2))\n%!error <moment: P must be a numeric scalar> moment (1, true)\n%!error <moment: P must be a numeric scalar> moment (1, \"str\")\n%!error <moment: TYPE must be a character vector> moment (1, 2, 3, 4)\n"
  },
  {
    "path": "scripts/statistics/movmad.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movmad (@var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movmad (@var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movmad (@dots{}, @var{dim})\n## @deftypefnx {} {@var{y} =} movmad (@dots{}, @var{nancond})\n## @deftypefnx {} {@var{y} =} movmad (@dots{}, @var{property}, @var{value})\n## Calculate the moving median or mean absolute deviation over a sliding\n## window of length @var{wlen} on data @var{x}.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n##\n## The optional argument @var{nancond} is a string that controls how @code{NaN}\n## and @code{NA} values affect the output of @qcode{\"movmad\"}.  The value\n## @qcode{\"includenan\"} causes @code{NaN} and @code{NA} values to be included\n## in the moving window, and any window slice containing @code{NaN} or\n## @code{NA} values will return @code{NaN} for that element.  The value\n## @qcode{\"omitnan\"} (default) causes @qcode{\"movmad\"} to ignore any @code{NaN}\n## or @code{NA} values resulting in fewer elements being used to calculate the\n## mad for that window slice.  If @qcode{\"omitnan\"} is specified and a window\n## slice contains all @code{NaN} or @code{NA} values, @qcode{\"movmad\"} returns\n## @code{NaN} for that element.  The values @qcode{\"includemissing\"} and\n## @qcode{\"omitmissing\"} may be used synonymously with @qcode{\"includenan\"} and\n## @qcode{\"omitnan\"}, respectively.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs:\n##\n## @itemize\n## @item\n## The @qcode{\"method\"} property can take the value @qcode{\"median\"} (default)\n## or @qcode{\"mean\"} to control whether @qcode{\"movmad\"} performs median or\n## mean absolute deviation calculations on the data.\n##\n## @item\n## Additional valid properties are @qcode{\"Endpoints\"} and\n## @qcode{\"SamplePoints\"}.  For full descriptions of these properties and valid\n## options, @pxref{XREFmovfun,,@code{movfun}}.\n## @end itemize\n##\n## Programming Note: This function is a wrapper which calls @code{movfun}.  For\n## full documentation of inputs and options, @pxref{XREFmovfun,,@code{movfun}}.\n##\n## Compatibility Note: Prior to Octave 10 this function only calculated mean\n## absolute deviation.  For @sc{matlab} compatibility, the default has been\n## changed to median absolute deviation.  The @qcode{\"method\"} property is now\n## provided to enable access to both @qcode{\"mad\"} calculation methods.  This\n## property should not be expected to be functional outside of Octave code.\n##\n## @seealso{mad, movfun, movslice, movmax, movmean, movmedian, movmin,\n## movprod, movstd, movsum, movvar}\n## @end deftypefn\n\nfunction y = movmad (x, wlen, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  fcn = @(x) mad (x, 1);  # Default to median if unspecified.\n\n  varargin = __parse_movargs__ (\"movmad\", varargin{:});\n\n  ## Check for method property for user specified mean or median absolute\n  ## deviation.  If multiple, last \"method\" input takes precedence.\n  ## __parse_movargs__ should have already checked for prop/value pairing.\n  ## Use output to send Opt = 1 via anonymous function for median case, or\n  ## use default opt = 0 for mean case.  Strip method property arguments\n  ## before sending to movfun.\n\n\n  method_check = strcmpi (varargin, \"method\");\n\n  if (any (method_check))\n\n    method_loc = find (method_check);\n    method_type = varargin{method_loc(end) + 1};\n\n    switch (lower (method_type))\n      case \"mean\"\n        fcn = @mad;\n\n      case \"median\"\n        ## fcn already set for median.\n\n      otherwise\n        error (\"movmad: METHOD must be either MEAN or MEDIAN\");\n    endswitch\n\n    varargin([method_loc, method_loc+1]) = [];\n\n  endif\n\n  y = movfun (fcn, x, wlen, varargin{:});\n\nendfunction\n\n\n## mean absolute deviation tests\n%!assert (movmad (1:5, 3, \"method\", \"mean\"), [1/2, 2/3, 2/3, 2/3, 1/2], eps)\n%!assert (movmad (1:5, [1, 1], \"method\", \"mean\"), [1/2, 2/3, 2/3, 2/3, 1/2], eps)\n%!assert (movmad (1:5, 3, 2, \"method\", \"mean\"), [1/2, 2/3, 2/3, 2/3, 1/2], eps)\n%!assert <*65928> (movmad (1:5, 3, 1, \"method\", \"mean\"), zeros (1, 5))\n%!assert <*65928> (movmad (1:5, 3, 3, \"method\", \"mean\"), zeros (1, 5))\n\n%!assert (movmad (magic (4), 3, \"method\", \"mean\"), ...\n%!        [5.5, 4.5, 3.5, 2.5; 4, 28/9, 22/9, 2; ...\n%!         2, 22/9, 28/9, 4; 2.5, 3.5, 4.5, 5.5], 3*eps)\n%!assert (movmad (magic (4), 3, 1, \"method\", \"mean\"), ...\n%!        [5.5, 4.5, 3.5, 2.5; 4, 28/9, 22/9, 2; ...\n%!         2, 22/9, 28/9, 4; 2.5, 3.5, 4.5, 5.5], 3*eps)\n%!assert (movmad (magic (4), 3, 2, \"method\", \"mean\"), ...\n%!        [7, 6, 14/3, 5; 3, 22/9, 10/9, 1; ...\n%!         1, 10/9, 22/9, 3; 5, 14/3, 6, 7], 3*eps)\n%!assert <*65928> (movmad (magic (4), 3, 3, \"method\", \"mean\"), zeros (4, 4))\n\n%!assert <*55241> (movmad ((1:10).', 3, \"method\", \"mean\"), [0.5; repmat(2/3, 8, 1); 0.5], eps)\n\n%!assert <*66156> (movmad ([1:4, NaN(1,3), 8:10], 3, \"method\", \"mean\"), movmad ([1:4, NaN(1,3), 8:10], 3, \"method\", \"mean\", \"includenan\"))\n%!assert <*66156> (movmad ([1:4, NaN(1,3), 8:10], 3, \"includenan\", \"method\", \"mean\"), [1/2, 2/3, 2/3, NaN(1,5), 2/3, 1/2], eps)\n%!assert <*66156> (movmad ([1:4, NaN(1,3), 8:10], 3, \"omitnan\", \"method\", \"mean\"), [1/2, 2/3, 2/3, 1/2, 0, NaN, 0, 1/2, 2/3 1/2], eps)\n\n## median absolute deviation tests\n%!assert (movmad (1:5, 3, \"method\", \"median\"), [1/2, 1, 1, 1, 1/2], eps)\n%!assert (movmad (1:5, 3), [1/2, 1, 1, 1, 1/2], eps)\n%!assert (movmad (1:5, [1, 1]), [1/2, 1, 1, 1, 1/2], eps)\n%!assert (movmad (1:5, 3, 2), [1/2, 1, 1, 1, 1/2], eps)\n%!assert <*65928> (movmad (1:5, 3, 1), zeros (1, 5))\n%!assert <*65928> (movmad (1:5, 3, 3), zeros (1, 5))\n\n%!assert (movmad (magic (4), 3), ...\n%!       [5.5, 4.5, 3.5, 2.5; 4, 4, 3, 1; ...\n%!        1, 3, 4, 4; 2.5, 3.5, 4.5, 5.5], eps)\n%!assert (movmad (magic (4), 3, 1), ...\n%!       [5.5, 4.5, 3.5, 2.5; 4, 4, 3, 1; ...\n%!        1, 3, 4, 4; 2.5, 3.5, 4.5, 5.5], eps)\n%!assert (movmad (magic (4), 3, 2), ...\n%!       [7, 1, 1, 5; 3, 1, 1, 1; ...\n%!        1, 1, 1, 3; 5, 1, 1, 7])\n%!assert <*65928> (movmad (magic (4), 3, 3), zeros (4, 4))\n\n%!assert <*55241> (movmad ((1:10).', 3), [0.5; ones(8,1); 0.5], eps)\n\n%!assert <*66156> (movmad ([1:4, NaN(1,3), 8:10], 3), movmad ([1:4, NaN(1,3), 8:10], 3, \"includenan\"))\n%!assert <*66156> (movmad ([1:4, NaN(1,3), 8:10], 3, \"includenan\"), [1/2, 1, 1, NaN(1,5), 1, 1/2], eps)\n%!assert <*66156> (movmad ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"), [1/2, 1, 1, 1/2, 0, NaN, 0, 1/2, 1 1/2], eps)\n\n%!assert <*66256> (movmad (1:5, 3, \"method\", \"median\", \"method\", \"mean\"), (movmad (1:5, 3, \"method\", \"mean\")))\n%!assert <*66256> (movmad (1:5, 3, \"method\", \"median\", 1, \"method\", \"mean\", \"includenan\"), movmad (1:5, 3, 1, \"method\", \"mean\", \"includenan\"))\n\n## Test input validation\n%!error <Invalid call> movmad ()\n%!error <Invalid call> movmad (1)\n%!error <METHOD must be either> movmad (1:4, 3, \"method\", \"foo\")\n"
  },
  {
    "path": "scripts/statistics/movmax.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movmax (@var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movmax (@var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movmax (@dots{}, @var{dim})\n## @deftypefnx {} {@var{y} =} movmax (@dots{}, @var{nancond})\n## @deftypefnx {} {@var{y} =} movmax (@dots{}, @var{property}, @var{value})\n## Calculate the moving maximum over a sliding window of length @var{wlen} on\n## data @var{x}.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n##\n## The optional argument @var{nancond} is a string that controls how @code{NaN}\n## and @code{NA} values affect the output of @qcode{\"movmax\"}.  The value\n## @qcode{\"includenan\"} causes @code{NaN} and @code{NA} values to be\n## included in the moving window, and any window slice containing @code{NaN} or\n## @code{NA} values will return @code{NaN} for that element.  The value\n## @qcode{\"omitnan\"} (default) causes @qcode{\"movmax\"} to ignore any @code{NaN}\n## or @code{NA} values resulting in fewer elements being used to calculate the\n## maximum for that window slice.  If @qcode{\"omitnan\"} is specified and a\n## window slice contains all @code{NaN} or @code{NA} values, @qcode{\"movmax\"}\n## returns @code{NaN} for that element.  The values @qcode{\"includemissing\"}\n## and @qcode{\"omitmissing\"} may be used synonymously with\n## @qcode{\"includenan\"} and @qcode{\"omitnan\"}, respectively.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs.  Valid properties are @qcode{\"Endpoints\"} and\n## @qcode{\"SamplePoints\"}.  For full descriptions of these properties and\n## valid options, @pxref{XREFmovfun,,@code{movfun}}.\n##\n## Programming Note: This function is a wrapper which calls @code{movfun}.\n## For full documentation of inputs and options,\n## @pxref{XREFmovfun,,@code{movfun}}.\n##\n## @seealso{max, movfun, movslice, movmad, movmean, movmedian, movmin,\n## movprod, movstd, movsum, movvar}\n## @end deftypefn\n\nfunction y = movmax (x, wlen, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (any (strcmpi (varargin, \"samplepoints\")))\n    ## Avoid error mixing certain Endpoints & SamplePoints combinations.\n    y = movfun (@max, x, wlen, \"nancond\", \"omitnan\",\n                __parse_movargs__ (\"movmax\", varargin{:}){:});\n  else\n    y = movfun (@max, x, wlen, \"nancond\", \"omitnan\", \"Endpoints\", -Inf,\n                __parse_movargs__ (\"movmax\", varargin{:}){:});\n  endif\n\nendfunction\n\n\n%!assert (movmax (1:5, 3), [2:5, 5])\n%!assert (movmax (1:5, [1, 1]), [2:5, 5])\n%!assert (movmax (1:5, 3, 2), [2:5, 5])\n%!assert <*65928> (movmax (1:5, 3, 1), 1:5)\n%!assert <*65928> (movmax (1:5, 3, 3), 1:5)\n\n%!assert (movmax (magic (4), 3),\n%!        [16, 11, 10, 13; 16, 11, 10, 13; 9, 14, 15, 12; 9, 14, 15, 12])\n%!assert (movmax (magic (4), 3, 1),\n%!        [16, 11, 10, 13; 16, 11, 10, 13; 9, 14, 15, 12; 9, 14, 15, 12])\n%!assert (movmax (magic (4), 3, 2),\n%!        [16, 16, 13, 13; 11, 11, 11, 10; 9, 9, 12, 12; 14, 15, 15, 15])\n%!assert <*65928> (movmax (magic (4), 3, 3), magic (4))\n\n%!assert <*55241> (movmax ((1:10).', 3), [(2:10).'; 10])\n\n%!assert <66156> (movmax ([1:4, NaN(1,3), 8:10], 3), movmax ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"))\n%!assert <66156> (movmax ([1:4, NaN(1,3), 8:10], 3, \"includenan\"), [2:4, NaN(1,5), 10, 10])\n%!assert <66156> (movmax ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"), [2:4, 4, 4, NaN, 8, 9, 10, 10])\n\n%!assert <*66025> (movmax (1:5, 3, \"samplepoints\", [1:4, 6]), [2, 3, 4, 4, 5])\n\n## Test input validation\n%!error <Invalid call> movmax ()\n%!error <Invalid call> movmax (1)\n"
  },
  {
    "path": "scripts/statistics/movmean.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movmean (@var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movmean (@var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movmean (@dots{}, @var{dim})\n## @deftypefnx {} {@var{y} =} movmean (@dots{}, @var{nancond})\n## @deftypefnx {} {@var{y} =} movmean (@dots{}, @var{property}, @var{value})\n## Calculate the moving average over a sliding window of length @var{wlen} on\n## data @var{x}.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n##\n## The optional argument @var{nancond} is a string that controls how @code{NaN}\n## and @code{NA} values affect the output of @qcode{\"movmean\"}.  The value\n## @qcode{\"includenan\"} (default) causes @code{NaN} and @code{NA} values to be\n## included in the moving window, and any window slice containing @code{NaN} or\n## @code{NA} values will return @code{NaN} for that element.  The value\n## @qcode{\"omitnan\"} causes @qcode{\"movmean\"} to ignore any @code{NaN}\n## or @code{NA} values resulting in fewer elements being used to calculate the\n## mean for that window slice.  If @qcode{\"omitnan\"} is specified and a window\n## slice contains all @code{NaN} or @code{NA} values, @qcode{\"movmean\"} returns\n## @code{NaN} for that element.  The values @qcode{\"includemissing\"} and\n## @qcode{\"omitmissing\"} may be used synonymously with @qcode{\"includenan\"} and\n## @qcode{\"omitnan\"}, respectively.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs.  Valid properties are @qcode{\"Endpoints\"} and\n## @qcode{\"SamplePoints\"}.  For full descriptions of these properties and\n## valid options, @pxref{XREFmovfun,,@code{movfun}}.\n##\n## Programming Note: This function is a wrapper which calls @code{movfun}.\n## For full documentation of inputs and options,\n## @pxref{XREFmovfun,,@code{movfun}}.\n##\n## @seealso{mean, movfun, movslice, movmad, movmax, movmedian, movmin,\n## movprod, movstd, movsum, movvar}\n## @end deftypefn\n\nfunction y = movmean (x, wlen, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  y = movfun (@mean, x, wlen, __parse_movargs__ (\"movmean\", varargin{:}){:});\n\nendfunction\n\n\n%!assert (movmean (1:5, 3), [1.5, 2, 3, 4, 4.5], eps)\n%!assert (movmean (1:5, [1, 1]), [1.5, 2, 3, 4, 4.5], eps)\n%!assert (movmean (1:5, 3, 2), [1.5, 2, 3, 4, 4.5], eps)\n%!assert <*65928> (movmean (1:5, 3, 1), 1:5)\n%!assert <*65928> (movmean (1:5, 3, 3), 1:5)\n\n%!assert (movmean (magic (4), 3), ...\n%!        [10.5, 6.5, 6.5, 10.5; 10, 20/3, 19/3, 11; ...\n%!         6, 32/3, 31/3, 7; 6.5, 10.5, 10.5, 6.5], eps)\n%!assert (movmean (magic (4), 3, 1), ...\n%!        [10.5, 6.5, 6.5, 10.5; 10, 20/3, 19/3, 11; ...\n%!         6, 32/3, 31/3, 7; 6.5, 10.5, 10.5, 6.5], eps)\n%!assert (movmean (magic (4), 3, 2), ...\n%!        [9, 7, 6, 8; 8, 26/3, 29/3, 9; ...\n%!         8, 22/3, 25/3, 9; 9, 11, 10, 8], eps)\n%!assert <*65928> (movmean (magic (4), 3, 3), magic (4))\n\n%!assert <*55241> (movmean ((1:10).', 3), [1.5; (2:9).'; 9.5])\n\n%!assert <66156> (movmean ([1:4, NaN(1,3), 8:10], 3), movmean ([1:4, NaN(1,3), 8:10], 3, \"includenan\"))\n%!assert <66156> (movmean ([1:4, NaN(1,3), 8:10], 3, \"includenan\"), [1.5, 2, 3, NaN(1,5), 9, 9.5], eps)\n%!assert <66156> (movmean ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"), [1.5, 2, 3, 3.5, 4, NaN, 8, 8.5, 9, 9.5], eps)\n\n## Test input validation\n%!error <Invalid call> movmean ()\n%!error <Invalid call> movmean (1)\n"
  },
  {
    "path": "scripts/statistics/movmedian.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movmedian (@var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movmedian (@var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movmedian (@dots{}, @var{dim})\n## @deftypefnx {} {@var{y} =} movmedian (@dots{}, @var{nancond})\n## @deftypefnx {} {@var{y} =} movmedian (@dots{}, @var{property}, @var{value})\n## Calculate the moving median over a sliding window of length @var{wlen} on\n## data @var{x}.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n##\n## The optional argument @var{nancond} is a string that controls how @code{NaN}\n## and @code{NA} values affect the output of @qcode{\"movmedian\"}.  The value\n## @qcode{\"includenan\"} (default) causes @code{NaN} and @code{NA} values to be\n## included in the moving window, and any window slice containing @code{NaN} or\n## @code{NA} values will return @code{NaN} for that element.  The value\n## @qcode{\"omitnan\"} causes @qcode{\"movmedian\"} to ignore any @code{NaN}\n## or @code{NA} values resulting in fewer elements being used to calculate the\n## median for that window slice.  If @qcode{\"omitnan\"} is specified and a\n## window slice contains all @code{NaN} or @code{NA} values,\n## @qcode{\"movmedian\"} returns @code{NaN} for that element.  The values\n## @qcode{\"includemissing\"} and @qcode{\"omitmissing\"} may be used\n## synonymously with @qcode{\"includenan\"} and @qcode{\"omitnan\"},\n## respectively.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs.  Valid properties are @qcode{\"Endpoints\"} and\n## @qcode{\"SamplePoints\"}.  For full descriptions of these properties and\n## valid options, @pxref{XREFmovfun,,@code{movfun}}.\n##\n## Programming Note: This function is a wrapper which calls @code{movfun}.\n## For full documentation of inputs and options,\n## @pxref{XREFmovfun,,@code{movfun}}.\n##\n## @seealso{median, movfun, movslice, movmad, movmax, movmean, movmin,\n## movprod, movstd, movsum, movvar}\n## @end deftypefn\n\nfunction y = movmedian (x, wlen, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  y = movfun (@median, x, wlen, __parse_movargs__ (\"movmedian\", varargin{:}){:});\n\nendfunction\n\n\n%!assert (movmedian (1:5, 3), [1.5, 2, 3, 4, 4.5], eps)\n%!assert (movmedian (1:5, [1, 1]), [1.5, 2, 3, 4, 4.5], eps)\n%!assert (movmedian (1:5, 3, 2), [1.5, 2, 3, 4, 4.5], eps)\n%!assert <*65928> (movmedian (1:5, 3, 1), 1:5)\n%!assert <*65928> (movmedian (1:5, 3, 3), 1:5)\n\n%!assert (movmedian (magic (4), 3),\n%!        [10.5, 6.5, 6.5, 10.5; 9, 7, 6, 12; ...\n%!         5, 11, 10, 8; 6.5, 10.5, 10.5, 6.5], eps)\n%!assert (movmedian (magic (4), 3, 1),\n%!        [10.5, 6.5, 6.5, 10.5; 9, 7, 6, 12; ...\n%!         5, 11, 10, 8; 6.5, 10.5, 10.5, 6.5], eps)\n%!assert (movmedian (magic (4), 3, 2),\n%!        [9, 3, 3, 8; 8, 10, 10, 9; 8, 7, 7, 9; 9, 14, 14, 8])\n%!assert <*65928> (movmedian (magic (4), 3, 3), magic (4))\n\n%!assert <*55241> (movmedian ((1:10).', 3), [1.5; (2:9).'; 9.5], eps)\n\n%!assert <66156> (movmedian ([1:4, NaN(1,3), 8:10], 3), movmedian ([1:4, NaN(1,3), 8:10], 3, \"includenan\"))\n%!assert <66156> (movmedian ([1:4, NaN(1,3), 8:10], 3, \"includenan\"), [1.5, 2, 3, NaN(1,5), 9, 9.5], eps)\n%!assert <66156> (movmedian ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"), [1.5, 2, 3, 3.5, 4, NaN, 8, 8.5, 9, 9.5], eps)\n\n## Test input validation\n%!error <Invalid call> movmedian ()\n%!error <Invalid call> movmedian (1)\n"
  },
  {
    "path": "scripts/statistics/movmin.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movmin (@var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movmin (@var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movmin (@dots{}, @var{dim})\n## @deftypefnx {} {@var{y} =} movmin (@dots{}, @var{nancond})\n## @deftypefnx {} {@var{y} =} movmin (@dots{}, @var{property}, @var{value})\n## Calculate the moving minimum over a sliding window of length @var{wlen} on\n## data @var{x}.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n##\n## The optional argument @var{nancond} is a string that controls how @code{NaN}\n## and @code{NA} values affect the output of @qcode{\"movmin\"}.  The value\n## @qcode{\"includenan\"} causes @code{NaN} and @code{NA} values to be\n## included in the moving window, and any window slice containing @code{NaN} or\n## @code{NA} values will return @code{NaN} for that element.  The value\n## @qcode{\"omitnan\"} (default) causes @qcode{\"movmin\"} to ignore any @code{NaN}\n## or @code{NA} values resulting in fewer elements being used to calculate the\n## minimum for that window slice.  If @qcode{\"omitnan\"} is specified and a\n## window slice contains all @code{NaN} or @code{NA} values, @qcode{\"movmin\"}\n## returns @code{NaN} for that element.  The values @qcode{\"includemissing\"}\n## and @qcode{\"omitmissing\"} may be used synonymously with\n## @qcode{\"includenan\"} and @qcode{\"omitnan\"}, respectively.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs.  Valid properties are @qcode{\"Endpoints\"} and\n## @qcode{\"SamplePoints\"}.  For full descriptions of these properties and\n## valid options, @pxref{XREFmovfun,,@code{movfun}}.\n##\n## Programming Note: This function is a wrapper which calls @code{movfun}.\n## For full documentation of inputs and options,\n## @pxref{XREFmovfun,,@code{movfun}}.\n##\n## @seealso{min, movfun, movslice, movmad, movmax, movmean, movmedian,\n## movprod, movstd, movsum, movvar}\n## @end deftypefn\n\nfunction y = movmin (x, wlen, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (any (strcmpi (varargin, \"samplepoints\")))\n    ## Avoid error mixing certain Endpoints & SamplePoints combinations.\n    y = movfun (@min, x, wlen, \"nancond\", \"omitnan\",\n                __parse_movargs__ (\"movmin\", varargin{:}){:});\n  else\n    y = movfun (@min, x, wlen, \"nancond\", \"omitnan\", \"Endpoints\", Inf,\n                __parse_movargs__ (\"movmin\", varargin{:}){:});\n  endif\n\nendfunction\n\n\n%!assert (movmin (1:5, 3), [1, 1:4])\n%!assert (movmin (1:5, [1, 1]), [1, 1:4])\n%!assert (movmin (1:5, 3, 2), [1, 1:4])\n%!assert <*65928> (movmin (1:5, 3, 1), 1:5)\n%!assert <*65928> (movmin (1:5, 3, 3), 1:5)\n\n%!assert (movmin (magic (4), 3),\n%!        [5, 2, 3, 8; 5, 2, 3, 8; 4, 7, 6, 1; 4, 7, 6, 1])\n%!assert (movmin (magic (4), 3, 1),\n%!        [5, 2, 3, 8; 5, 2, 3, 8; 4, 7, 6, 1; 4, 7, 6, 1])\n%!assert (movmin (magic (4), 3, 2),\n%!        [2, 2, 2, 3; 5, 5, 8, 8; 7, 6, 6, 6; 4, 4, 1, 1])\n%!assert <*65928> (movmin (magic (4), 3, 3), magic (4))\n\n%!assert <*55241> (movmin ((1:10).', 3), [1; (1:9).'])\n\n%!assert <66156> (movmin ([1:4, NaN(1,3), 8:10], 3), movmin ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"))\n%!assert <66156> (movmin ([1:4, NaN(1,3), 8:10], 3, \"includenan\"), [1, 1:2, NaN(1,5), 8, 9])\n%!assert <66156> (movmin ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"), [1, 1:4, NaN, 8, 8, 8:9])\n\n%!assert <*66025> (movmin (1:5, 3, \"samplepoints\", [1:4, 6]), [1, 1, 2, 3, 5])\n\n## Test input validation\n%!error <Invalid call> movmin ()\n%!error <Invalid call> movmin (1)\n"
  },
  {
    "path": "scripts/statistics/movprod.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movprod (@var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movprod (@var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movprod (@dots{}, @var{dim})\n## @deftypefnx {} {@var{y} =} movprod (@dots{}, @var{nancond})\n## @deftypefnx {} {@var{y} =} movprod (@dots{}, @var{property}, @var{value})\n## Calculate the moving product over a sliding window of length @var{wlen} on\n## data @var{x}.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n##\n## The optional argument @var{nancond} is a string that controls how @code{NaN}\n## and @code{NA} values affect the output of @qcode{\"movprod\"}.  The value\n## @qcode{\"includenan\"} (default) causes @code{NaN} and @code{NA} values to be\n## included in the moving window, and any window slice containing @code{NaN} or\n## @code{NA} values will return @code{NaN} for that element.  The value\n## @qcode{\"omitnan\"} causes @qcode{\"movprod\"} to ignore any @code{NaN}\n## or @code{NA} values resulting in fewer elements being used to calculate the\n## product for that window slice.  If @qcode{\"omitnan\"} is specified and a\n## window slice contains all @code{NaN} or @code{NA} values, @qcode{\"movprod\"}\n## returns 1 for that element.  The values @qcode{\"includemissing\"} and\n## @qcode{\"omitmissing\"} may be used synonymously with @qcode{\"includenan\"} and\n## @qcode{\"omitnan\"}, respectively.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs.  Valid properties are @qcode{\"Endpoints\"} and\n## @qcode{\"SamplePoints\"}.  For full descriptions of these properties and\n## valid options, @pxref{XREFmovfun,,@code{movfun}}.\n##\n## Programming Note: This function is a wrapper which calls @code{movfun}.\n## For full documentation of inputs and options,\n## @pxref{XREFmovfun,,@code{movfun}}.\n##\n## @seealso{prod, movfun, movslice, movmad, movmax, movmean, movmedian,\n## movmin, movstd, movsum, movvar}\n## @end deftypefn\n\nfunction y = movprod (x, wlen, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (any (strcmpi (varargin, \"samplepoints\")))\n    ## Avoid error mixing certain Endpoints & SamplePoints combinations.\n    y = movfun (@prod, x, wlen, \"nanval\", 1,\n                __parse_movargs__ (\"movprod\", varargin{:}){:});\n  else\n    y = movfun (@prod, x, wlen, \"nanval\", 1, \"Endpoints\", 1,\n                __parse_movargs__ (\"movprod\", varargin{:}){:});\n  endif\n\nendfunction\n\n\n%!assert (movprod (1:5, 3), [2, 6, 24, 60, 20])\n%!assert (movprod (1:5, [1, 1]), [2, 6, 24, 60, 20])\n%!assert (movprod (1:5, 3, 2), [2, 6, 24, 60, 20])\n%!assert <*65928> (movprod (1:5, 3, 1), 1:5)\n%!assert <*65928> (movprod (1:5, 3, 3), 1:5)\n\n%!assert (movprod (magic (4), 3),\n%!        [80, 22, 30, 104; 720, 154, 180, 1248; ...\n%!         180, 1078, 900, 96; 36, 98, 90, 12])\n%!assert (movprod (magic (4), 3, 1),\n%!        [80, 22, 30, 104; 720, 154, 180, 1248; ...\n%!         180, 1078, 900, 96; 36, 98, 90, 12])\n%!assert (movprod (magic (4), 3, 2),\n%!        [32, 96, 78, 39; 55, 550, 880, 80; ...\n%!         63, 378, 504, 72; 56, 840, 210, 15])\n%!assert <*65928> (movprod (magic (4), 3, 3), magic (4))\n\n%!assert <*55241> (movprod ((1:10).', 3), ...\n%!                 [2; 6; 24; 60; 120; 210; 336; 504; 720; 90])\n\n%!assert <66156> (movprod ([1:4, NaN(1,3), 8:10], 3), movprod ([1:4, NaN(1,3), 8:10], 3, \"includenan\"))\n%!assert <66156> (movprod ([1:4, NaN(1,3), 8:10], 3, \"includenan\"), [2, 6, 24, NaN(1,5), 720, 90])\n%!assert <66156> (movprod ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"), [2, 6, 24, 12, 4, 1, 8, 72, 720, 90])\n\n%!assert <*66025> (movprod (1:5, 3, \"samplepoints\", [1:4, 6]), [2, 6, 24, 12, 5])\n\n## Test input validation\n%!error <Invalid call> movprod ()\n%!error <Invalid call> movprod (1)\n"
  },
  {
    "path": "scripts/statistics/movstd.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movstd (@var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movstd (@var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movstd (@dots{}, @var{opt})\n## @deftypefnx {} {@var{y} =} movstd (@dots{}, @var{opt}, @var{dim})\n## @deftypefnx {} {@var{y} =} movstd (@dots{}, @var{nancond})\n## @deftypefnx {} {@var{y} =} movstd (@dots{}, @var{property}, @var{value})\n## Calculate the moving standard deviation over a sliding window of length\n## @var{wlen} on data @var{x}.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## The optional argument @var{opt} determines the type of normalization to use.\n## Valid values are\n##\n## @table @asis\n## @item 0:\n##   normalize with @math{N-1}, provides the square root of the best unbiased\n## estimator of the variance [default]\n##\n## @item 1:\n##   normalize with @math{N}, this provides the square root of the second\n## moment around the mean\n## @end table\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n## The normalization argument @var{opt} must be given before the dimension.\n## To use the default value for @var{opt} you may pass an empty input\n## argument @code{[]}.\n##\n## The optional argument @var{nancond} is a string that controls how @code{NaN}\n## and @code{NA} values affect the output of @qcode{\"movstd\"}.  The value\n## @qcode{\"includenan\"} (default) causes @code{NaN} and @code{NA} values to be\n## included in the moving window, and any window slice containing @code{NaN} or\n## @code{NA} values will return @code{NaN} for that element.  The value\n## @qcode{\"omitnan\"} causes @qcode{\"movstd\"} to ignore any @code{NaN}\n## or @code{NA} values resulting in fewer elements being used to calculate the\n## standard deviation for that window slice.  If @qcode{\"omitnan\"} is specified\n## and a window slice contains all @code{NaN} or @code{NA} values,\n## @qcode{\"movstd\"} returns @code{NaN} for that element.  The values\n## @qcode{\"includemissing\"} and @qcode{\"omitmissing\"} may be used synonymously\n## with @qcode{\"includenan\"} and @qcode{\"omitnan\"}, respectively.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs.  Valid properties are @qcode{\"Endpoints\"} and\n## @qcode{\"SamplePoints\"}.  For full descriptions of these properties and\n## valid options, @pxref{XREFmovfun,,@code{movfun}}.\n##\n## Programming Note: This function is a wrapper which calls @code{movfun}.\n## For full documentation of inputs and options,\n## @pxref{XREFmovfun,,@code{movfun}}.\n##\n## @seealso{std, movfun, movslice, movmad, movmax, movmean, movmedian, movmin,\n## movprod, movsum, movvar}\n## @end deftypefn\n\nfunction y = movstd (x, wlen, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  ## Process \"opt\" normalization argument\n  if (nargin > 2 && isnumeric (varargin{1}) && ! isempty (varargin{1}))\n    if (isempty (varargin{1}))\n      fcn = @std;\n    elseif (! isscalar (varargin{1}))\n      error (\"movstd: OPT must be 0 or 1\");\n    elseif (! varargin{1})\n      fcn = @std;\n    elseif (varargin{1} == 1)\n      fcn = @(x) std (x, 1);\n    else\n      error (\"movstd: OPT must be 0 or 1\");\n    endif\n    varargin(1) = [];\n  else\n    fcn = @std;\n  endif\n\n  y = movfun (fcn, x, wlen, __parse_movargs__ (\"movstd\", varargin{:}){:});\n\nendfunction\n\n\n%!assert (movstd (1:5, 3), [1/sqrt(2), 1, 1, 1, 1/sqrt(2)], eps)\n%!assert (movstd (1:5, [1, 1]), [1/sqrt(2), 1, 1, 1, 1/sqrt(2)], eps)\n%!assert (movstd (1:5, 3, 0), [1/sqrt(2), 1, 1, 1, 1/sqrt(2)], eps)\n%!assert <*66021> (movstd (1:5, 3, []), [1/sqrt(2), 1, 1, 1, 1/sqrt(2)], eps)\n%!assert (movstd (1:5, 3, 1), sqrt ([0.25, 2/3, 2/3, 2/3, 0.25]), eps)\n%!assert <*65928> (movstd (1:5, 3, 0, 1), zeros (1, 5))\n%!assert (movstd (1:5, 3, 0, 2), [1/sqrt(2), 1, 1, 1, 1/sqrt(2)], eps)\n%!assert (movstd (1:5, 3, 1, 2), sqrt ([0.25, 2/3, 2/3, 2/3, 0.25]), eps)\n%!assert <*66021> (movstd (1:5, 3, [], 2), [1/sqrt(2), 1, 1, 1, 1/sqrt(2)], eps)\n%!assert <*65928> (movstd (1:5, 3, 0, 3), zeros (1, 5))\n\n%!assert (movstd (magic (4), 3, 0),\n%!        sqrt ([60.5, 40.5, 24.5, 12.5; 31, 61/3, 37/3, 7; ...\n%!               7, 37/3, 61/3, 31; 12.5, 24.5, 40.5, 60.5]), 2*eps)\n%!assert (movstd (magic (4), 3, 0, 1),\n%!        sqrt ([60.5, 40.5, 24.5, 12.5; 31, 61/3, 37/3, 7;...\n%!               7, 37/3, 61/3, 31; 12.5, 24.5, 40.5, 60.5]), 2*eps)\n%!assert (movstd (magic (4), 3, 0, 2),\n%!        sqrt ([98, 61, 37, 50; 18, 31/3, 7/3, 2; ...\n%!        2, 7/3, 31/3, 18; 50, 37, 61, 98]), 2*eps)\n%!assert <*65928> (movstd (magic (4), 3, 0, 3), zeros (4, 4))\n\n%!assert <*55241> (movstd ((1:10).', 3), [1/sqrt(2); ones(8,1); 1/sqrt(2)], eps)\n\n%!assert <66156> (movstd ([1:4, NaN(1,3), 8:10], 3), movstd ([1:4, NaN(1,3), 8:10], 3, \"includenan\"))\n%!assert <66156> (movstd ([1:4, NaN(1,3), 8:10], 3, \"includenan\"), [sqrt(2)/2, 1, 1, NaN(1,5), 1, sqrt(2)/2], eps)\n%!assert <66156> (movstd ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"), [sqrt(2)/2, 1, 1, sqrt(2)/2, 0, NaN,0, sqrt(2)/2, 1, sqrt(2)/2], eps)\n\n%!test <*56765>\n%! x = 1:10;\n%! y = movstd (x, 4);\n%! y0 = movstd (x, 4, 0);\n%! assert (y, y0);\n%! y1 = movstd (x, 4, 1);\n%! assert (y1(1:3), sqrt ([1/4, 2/3, 5/4]));\n\n## Test input validation\n%!error <Invalid call> movstd ()\n%!error <Invalid call> movstd (1)\n%!error <OPT must be 0 or 1> movstd (1:10, 3, -1)\n%!error <OPT must be 0 or 1> movstd (1:10, 3, 1.4)\n%!error <OPT must be 0 or 1> movstd (1:10, 3, [1, 1])\n%!error <OPT must be 0 or 1> movstd (1:10, 3, [0, 0])\n%!error <OPT must be 0 or 1> movstd (1:10, 3, [0, 1])\n%!error <OPT must be 0 or 1> movstd (1:10, 3, [1, 0])\n%!error <OPT must be 0 or 1> movstd (1:10, 3, [0, 3])\n%!error <OPT must be 0 or 1> movstd (1:10, 3, [1, 3])\n%!error <OPT must be 0 or 1> movstd (1:10, 3, [3, 0])\n%!error <OPT must be 0 or 1> movstd (1:10, 3, [3, 1])\n\n"
  },
  {
    "path": "scripts/statistics/movsum.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movsum (@var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movsum (@var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movsum (@dots{}, @var{dim})\n## @deftypefnx {} {@var{y} =} movsum (@dots{}, @var{nancond})\n## @deftypefnx {} {@var{y} =} movsum (@dots{}, @var{property}, @var{value})\n## Calculate the moving sum over a sliding window of length @var{wlen} on\n## data @var{x}.\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n##\n## The optional argument @var{nancond} is a string that controls how @code{NaN}\n## and @code{NA} values affect the output of @qcode{\"movsum\"}.  The value\n## @qcode{\"includenan\"} (default) causes @code{NaN} and @code{NA} values to be\n## included in the moving window, and any window slice containing @code{NaN} or\n## @code{NA} values will return @code{NaN} for that element.  The value\n## @qcode{\"omitnan\"} causes @qcode{\"movsum\"} to ignore any @code{NaN}\n## or @code{NA} values resulting in fewer elements being used to calculate the\n## sum for that window slice.  If @qcode{\"omitnan\"} is specified and a window\n## slice contains all @code{NaN} or @code{NA} values, @qcode{\"movsum\"} returns\n## 0 for that element.  The values @qcode{\"includemissing\"} and\n## @qcode{\"omitmissing\"} may be used synonymously with @qcode{\"includenan\"} and\n## @qcode{\"omitnan\"}, respectively.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs.  Valid properties are @qcode{\"Endpoints\"} and\n## @qcode{\"SamplePoints\"}.  For full descriptions of these properties and\n## valid options, @pxref{XREFmovfun,,@code{movfun}}.\n##\n## Programming Note: This function is a wrapper which calls @code{movfun}.\n## For full documentation of inputs and options,\n## @pxref{XREFmovfun,,@code{movfun}}.\n##\n## @seealso{sum, movfun, movslice, movmad, movmax, movmean, movmedian, movmin,\n## movprod, movstd, movvar}\n## @end deftypefn\n\nfunction y = movsum (x, wlen, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (any (strcmpi (varargin, \"samplepoints\")))\n    ## Avoid error mixing certain Endpoints & SamplePoints combinations.\n    y = movfun (@sum, x, wlen, \"nanval\", 0,\n                __parse_movargs__ (\"movsum\", varargin{:}){:});\n  else\n    y = movfun (@sum, x, wlen, \"nanval\", 0, \"Endpoints\", 0,\n                __parse_movargs__ (\"movsum\", varargin{:}){:});\n  endif\n\nendfunction\n\n\n%!assert (movsum (1:5, 3), [3, 6, 9, 12, 9])\n%!assert (movsum (1:5, [1, 1]), [3, 6, 9, 12, 9])\n%!assert (movsum (1:5, 3, 2), [3, 6, 9, 12, 9])\n%!assert <*65928> (movsum (1:5, 3, 1), 1:5)\n%!assert <*65928> (movsum (1:5, 3, 3), 1:5)\n\n%!assert (movsum (magic (4), 3),\n%!        [21, 13, 13, 21; 30, 20, 19, 33; 18, 32, 31, 21; 13, 21, 21, 13])\n%!assert (movsum (magic (4), 3, 1),\n%!        [21, 13, 13, 21; 30, 20, 19, 33; 18, 32, 31, 21; 13, 21, 21, 13])\n%!assert (movsum (magic (4), 3, 2),\n%!        [18, 21, 18, 16; 16, 26, 29, 18; 16, 22, 25, 18; 18, 33, 30, 16])\n%!assert <*65928> (movsum (magic (4), 3, 3), magic (4))\n\n%!assert <*55241> (movsum ((1:10).', 3), [(3:3:27).'; 19])\n\n%!assert <66156> (movsum ([1:4, NaN(1,3), 8:10], 3), movsum ([1:4, NaN(1,3), 8:10], 3, \"includenan\"))\n%!assert <66156> (movsum ([1:4, NaN(1,3), 8:10], 3, \"includenan\"), [3:3:9, NaN(1,5), 27, 19])\n%!assert <66156> (movsum ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"), [3:3:9, 7, 4, 0, 8, 17, 27, 19])\n\n%!assert <*66025> (movsum (1:5, 3, \"samplepoints\", [1:4, 6]), [3, 6, 9, 7, 5])\n\n## Test input validation\n%!error <Invalid call> movsum ()\n%!error <Invalid call> movsum (1)\n"
  },
  {
    "path": "scripts/statistics/movvar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} movvar (@var{x}, @var{wlen})\n## @deftypefnx {} {@var{y} =} movvar (@var{x}, [@var{nb}, @var{na}])\n## @deftypefnx {} {@var{y} =} movvar (@dots{}, @var{opt})\n## @deftypefnx {} {@var{y} =} movvar (@dots{}, @var{opt}, @var{dim})\n## @deftypefnx {} {@var{y} =} movvar (@dots{}, @var{nancond})\n## @deftypefnx {} {@var{y} =} movvar (@dots{}, @var{property}, @var{value})\n## Calculate the moving variance over a sliding window of length @var{wlen} on\n## data @var{x}.\n##\n##\n## The moving window length input @var{wlen} can either be a numeric scalar\n## or a 2-element numeric array @w{@code{[@var{nb}, @var{na}]}}.  The elements\n## included in the moving window depend on the size and value of @var{wlen}\n## as well as whether the @qcode{\"SamplePoints\"} option has been specified.\n## For full details of element inclusion,\n## @pxref{XREFmovslice,,@code{movslice}}.\n##\n## The optional argument @var{opt} determines the type of normalization to use.\n## Valid values are:\n##\n## @table @asis\n## @item 0:\n##   normalize with @math{N-1}, provides the best unbiased estimator of the\n## variance [default]\n##\n## @item 1:\n##   normalizes with @math{N}, this provides the second moment around the mean\n## @end table\n##\n## If the optional argument @var{dim} is given, operate along this dimension.\n## The normalization argument @var{opt} must be given before the dimension.\n## To use the default value for @var{opt} you may pass an empty input\n## argument @code{[]}.\n##\n## The optional argument @var{nancond} is a string that controls how @code{NaN}\n## and @code{NA} values affect the output of @qcode{\"movvar\"}.  The value\n## @qcode{\"includenan\"} (default) causes @code{NaN} and @code{NA} values to be\n## included in the moving window, and any window slice containing @code{NaN} or\n## @code{NA} values will return @code{NaN} for that element.  The value\n## @qcode{\"omitnan\"} causes @qcode{\"movvar\"} to ignore any @code{NaN}\n## or @code{NA} values resulting in fewer elements being used to calculate the\n## variance for that window slice.  If @qcode{\"omitnan\"} is specified and a\n## window slice contains all @code{NaN} or @code{NA} values, @qcode{\"movvar\"}\n## returns @code{NaN} for that element.  The values @qcode{\"includemissing\"}\n## and @qcode{\"omitmissing\"} may be used synonymously with\n## @qcode{\"includenan\"} and @qcode{\"omitnan\"}, respectively.\n##\n## The calculation can be controlled by specifying @var{property}/@var{value}\n## pairs.  Valid properties are @qcode{\"Endpoints\"} and\n## @qcode{\"SamplePoints\"}.  For full descriptions of these properties and\n## valid options, @pxref{XREFmovfun,,@code{movfun}}.\n##\n## Programming Note: This function is a wrapper which calls @code{movfun}.\n## For full documentation of inputs and options,\n## @pxref{XREFmovfun,,@code{movfun}}.\n##\n## @seealso{var, movfun, movslice, movmad, movmax, movmean, movmedian, movmin,\n## movprod, movstd, movsum}\n## @end deftypefn\n\nfunction y = movvar (x, wlen, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  ## Process \"opt\" normalization argument\n  if (nargin > 2 && isnumeric (varargin{1}) && ! isempty (varargin{1}))\n    if (isempty (varargin{1}))\n      fcn = @var;\n    elseif (! isscalar (varargin{1}))\n      error (\"movvar: OPT must be 0 or 1\");\n    elseif (! varargin{1})\n      fcn = @var;\n    elseif (varargin{1} == 1)\n      fcn = @(x) var (x, 1);\n    else\n      error (\"movvar: OPT must be 0 or 1\");\n    endif\n    varargin(1) = [];\n  else\n    fcn = @var;\n  endif\n\n  y = movfun (fcn, x, wlen, __parse_movargs__ (\"movvar\", varargin{:}){:});\n\nendfunction\n\n\n%!assert (movvar (1:5, 3), [0.5, 1, 1, 1, 0.5], eps)\n%!assert (movvar (1:5, [1, 1]), [0.5, 1, 1, 1, 0.5], eps)\n%!assert (movvar (1:5, 3, 0), [0.5, 1, 1, 1, 0.5], eps)\n%!assert <*66021> (movvar (1:5, 3, []), [0.5, 1, 1, 1, 0.5], eps)\n%!assert (movvar (1:5, 3, 1), [0.25, 2/3, 2/3, 2/3, 0.25], eps)\n%!assert <*65928> (movvar (1:5, 3, 0, 1), zeros (1, 5))\n%!assert (movvar (1:5, 3, 0, 2), [0.5, 1, 1, 1, 0.5], eps)\n%!assert (movvar (1:5, 3, 1, 2), [0.25, 2/3, 2/3, 2/3, 0.25], eps)\n%!assert <*66021> (movvar (1:5, 3, [], 2), [0.5, 1, 1, 1, 0.5], eps)\n%!assert <*65928> (movvar (1:5, 3, 0, 3), zeros (1, 5))\n\n%!assert (movvar (magic (4), 3, 0),\n%!        [60.5, 40.5, 24.5, 12.5; 31, 61/3, 37/3, 7; ...\n%!         7, 37/3, 61/3, 31; 12.5, 24.5, 40.5, 60.5], 20*eps)\n%!assert (movvar (magic (4), 3, 0, 1),\n%!        [60.5, 40.5, 24.5, 12.5; 31, 61/3, 37/3, 7; ...\n%!         7, 37/3, 61/3, 31; 12.5, 24.5, 40.5, 60.5], 20*eps)\n%!assert (movvar (magic (4), 3, 0, 2),\n%!        [98, 61, 37, 50; 18, 31/3, 7/3, 2; ...\n%!         2, 7/3, 31/3, 18; 50, 37, 61, 98], 20*eps)\n%!assert <*65928> (movvar (magic (4), 3, 0, 3), zeros (4, 4))\n\n%!assert <*55241> (movvar ((1:10).', 3), [0.5; ones(8,1); 0.5], eps)\n\n%!test <*56765>\n%! x = 1:10;\n%! y = movvar (x, 4);\n%! y0 = movvar (x, 4, 0);\n%! assert (y, y0);\n%! y1 = movvar (x, 4, 1);\n%! assert (y1(1:3), [1/4, 2/3, 5/4]);\n\n%!assert <66156> (movvar ([1:4, NaN(1,3), 8:10], 3), movvar ([1:4, NaN(1,3), 8:10], 3, \"includenan\"))\n%!assert <66156> (movvar ([1:4, NaN(1,3), 8:10], 3, \"includenan\"), [0.5, 1, 1, NaN(1,5), 1, 0.5], eps)\n%!assert <66156> (movvar ([1:4, NaN(1,3), 8:10], 3, \"omitnan\"), [0.5, 1, 1, 0.5, 0, NaN,0, 0.5, 1, 0.5], eps)\n\n\n## Test input validation\n%!error <Invalid call> movvar ()\n%!error <Invalid call> movvar (1)\n%!error <OPT must be 0 or 1> movvar (1:10, 3, -1)\n%!error <OPT must be 0 or 1> movvar (1:10, 3, 1.4)\n%!error <OPT must be 0 or 1> movvar (1:10, 3, [1, 1])\n%!error <OPT must be 0 or 1> movvar (1:10, 3, [0, 0])\n%!error <OPT must be 0 or 1> movvar (1:10, 3, [0, 1])\n%!error <OPT must be 0 or 1> movvar (1:10, 3, [1, 0])\n%!error <OPT must be 0 or 1> movvar (1:10, 3, [0, 3])\n%!error <OPT must be 0 or 1> movvar (1:10, 3, [1, 3])\n%!error <OPT must be 0 or 1> movvar (1:10, 3, [3, 0])\n%!error <OPT must be 0 or 1> movvar (1:10, 3, [3, 1])\n"
  },
  {
    "path": "scripts/statistics/normalize.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{z} =} normalize (@var{x})\n## @deftypefnx {} {@var{z} =} normalize (@var{x}, @var{dim})\n## @deftypefnx {} {@var{z} =} normalize (@dots{}, @var{method})\n## @deftypefnx {} {@var{z} =} normalize (@dots{}, @var{method}, @var{option})\n## @deftypefnx {} {@var{z} =} normalize (@dots{}, @var{scale}, @var{scaleoption}, @var{center}, @var{centeroption})\n## @deftypefnx {} {[@var{z}, @var{c}, @var{s}] =} normalize (@dots{})\n## Return a normalization of the data in @var{x} using one of several available\n## scaling and centering methods.\n##\n## @code{normalize} by default will return the @code{zscore} of @var{x},\n## defined as the number of standard deviations each element is from the mean\n## of @var{x}.  This is equivalent to centering at the mean of the data and\n## scaling by the standard deviation.  @var{x} must be a numeric array of\n## double or single floating point numbers.\n##\n## The returned value @var{z} will have the same size as @var{x}.  The optional\n## return variables @var{c} and @var{s} are the centering and scaling factors\n## used in the normalization such that:\n##\n## @example\n## @group\n##   @tcode{@var{z} = (@var{x} - @var{c}) ./ @var{s}}\n## @end group\n## @end example\n##\n## If @var{x} is a vector, @code{normalize} will operate on the data in\n## @var{x}.\n##\n## If @var{x} is a matrix, @code{normalize} will operate independently on\n## each column in @var{x}.\n##\n## If @var{x} is an N-dimensional array, @code{normalize} will operate\n## independently on the first non-singleton dimension in @var{x}.\n##\n## If the optional second argument @var{dim} is given, operate along this\n## dimension.\n##\n## @code{normalize} ignores NaN values is @var{x} similar to the behavior of\n## the omitnan option in @code{std}, @code{mean}, and @code{median}.\n##\n## The optional inputs @var{method} and @var{option} can be used to specify the\n## type of normalization performed on @var{x}.  Note that only the\n## @option{scale} and @option{center} options may be specified together using\n## any of the methods defined below.  Valid normalization methods are:\n##\n## @table @code\n## @item zscore\n## (Default) Normalizes the elements in @var{x} to the scaled distance from a\n##  central value.  Valid Options:\n##\n##    @table @code\n##    @item std\n##    (Default) Data is centered at @code{mean (@var{x})} and scaled by the\n##      standard deviation.\n##\n##    @item robust\n##    Data is centered at @code{median (@var{x})} and scaled by the median\n##    absolute deviation.\n##    @end table\n##\n## @item norm\n## @var{z} is the general vector norm of @var{x}, with @var{option} being the\n## normalization factor @var{p} that determines the vector norm type according\n## to:\n## @tex\n## $$Z = \\left (\\sum_k \\left | X_k \\right |^P  \\right )^{1/P}$$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##   @tcode{@var{z} = [sum (abs (@var{x}) .^ @var{p})] ^ (1/@var{p})}\n## @end group\n## @end example\n##\n## @end ifnottex\n## @var{p} can be any positive scalar, specific values being:\n##\n##    @table @code\n##    @item @var{p} = 1\n##    @var{x} is normalized by @code{sum (abs (@var{x}))}.\n##\n##    @item @var{p} = 2\n##    (Default) @var{x} is normalized by the Euclidian norm, or vector\n##    magnitude, of the elements.\n##\n##    @item @var{P} = Inf\n##    @var{x} is normalized by @code{max (abs (@var{x}))}.\n##    @end table\n##\n## @item scale\n## @var{x} is scaled by a factor determined by @var{option}, which can be a\n## numeric scalar or one of the following:\n##\n##    @table @code\n##    @item std\n##    (Default) @var{x} is scaled by its standard deviation.\n##\n##    @item mad\n##    @var{x} is scaled by its median absolute deviation.\n##\n##    @item first\n##    @var{x} is scaled by its first element.\n##\n##    @item iqr\n##    @var{x} is scaled by its interquartile range.\n##    @end table\n##\n## @item range\n## @var{x} is scaled to fit the range specified by @var{option} as a two\n## element scalar row vector.  The default range is [0, 1].\n##\n## @item center\n## @var{x} is shifted by an amount determined by @var{option}, which can be a\n## numeric scalar or one of the following:\n##\n##    @table @code\n##    @item mean\n##    (Default) @var{x} is shifted by @code{mean (@var{x})}.\n##\n##    @item median\n##    @var{x} is shifted by @code{median (@var{x})}.\n##    @end table\n##\n## @item medianiqr\n## @var{x} is shifted by @code{median (@var{x})} and scaled by the\n## interquartile range.\n## @end table\n##\n## Known @sc{matlab} incompatibilities:\n##\n## @enumerate\n## @item\n## The option @option{DataVariables} is only available when input @var{x} is a\n## table class, which is not yet implemented in core Octave.  See the\n## @nospell{datatypes} and @nospell{tablicious} Octave Packages for an\n## available overloaded method.\n## @end enumerate\n##\n## @seealso{zscore, iqr, norm, rescale, std, median, mean, mad}\n## @end deftypefn\n\nfunction [z, c, s] = normalize (x, varargin)\n\n  ## Input validation\n  if (nargin < 1 || nargin > 8)\n    print_usage ();\n  endif\n\n  if (! isnumeric (x))\n    error (\"normalize: X must be a numeric vector, matrix, or array\");\n  endif\n\n  if (! any (isa (x, {\"double\", \"single\"})))\n    error (\"normalize: X must be double or single data type\");\n  endif\n\n  if (nargin == 1)\n    ## Directly handle simple 1 input case.\n    [s, c] = std (x, \"omitnan\");\n\n  else\n    ## Parse input options\n    dim = [];\n    method = [];\n    methodoption = [];\n    datavar = [];\n    scale_and_center_flag = false;\n\n    vararg_idx = 1;\n    ## Only second optional input can be numeric without following a method.\n    if (isnumeric (varargin{1}))\n      dim = varargin{1};\n      ## Check for valid dimensions\n      if (! (isscalar (dim) && dim == fix (dim) && dim > 0))\n        error (\"normalize: DIM must be an integer and a valid dimension\");\n      endif\n      vararg_idx++;\n    endif\n\n    ## Parse varargin to determine methods then options.\n    n_varargin = nargin - 1;\n    while (vararg_idx <= n_varargin)\n      ## Arguments after second cannot be numeric without following a method.\n      if (isnumeric (varargin{vararg_idx}))\n        print_usage ();\n      endif\n\n      prop = lower (varargin{vararg_idx});\n\n      if (strcmp (prop, \"datavariables\"))\n        error (strcat (\"normalize: 'DataVariables' optional paired\", ...\n                       \" argument is only available for table input\"));\n      endif\n\n      if (! isempty (method))\n        ## Catch if a second method is passed\n        if (scale_and_center_flag)\n          ## if true, already specified two methods, three never possible\n          error (\"normalize: more than two methods specified\");\n\n        elseif (strcmp ({method, prop}, {\"center\", \"scale\"})\n                || strcmp ({method, prop}, {\"scale\", \"center\"}))\n          ## Only scale and center can be called together\n          scale_and_center_flag = true;\n          ## scale/center order doesn't matter, avoid overwriting first one\n          stored_method = method;\n          method = [];\n          stored_methodoption = methodoption;\n          methodoption = [];\n        else\n          ## not scale and center, throw appropriate error\n          if (any (strcmp (prop, {\"zscore\", \"norm\", \"range\", \"scale\", ...\n                                  \"center\", \"medianiqr\"})))\n            error (\"normalize: methods '%s' and '%s' may not be combined\",\n                   method, prop);\n          else\n            error (\"normalize: unknown method '%s'\", prop);\n          endif\n        endif\n      endif\n\n      ## Determine method and whether there's an appropriate option specified\n      switch (prop)\n        case \"zscore\"\n          method = \"zscore\";\n          if (vararg_idx < n_varargin)\n            nextprop = lower (varargin{vararg_idx+1});\n            if (strcmp (nextprop, \"std\") || strcmp (nextprop, \"robust\"))\n              methodoption = nextprop;\n              vararg_idx++;\n            endif\n          endif\n          if (isempty (methodoption))\n            methodoption = \"std\";\n          endif\n\n        case \"norm\"\n          method = \"norm\";\n          if (vararg_idx < n_varargin && isnumeric (varargin{vararg_idx+1}))\n            nextprop = varargin{vararg_idx+1};\n            if (isscalar (nextprop) && (nextprop > 0))\n              methodoption = nextprop;\n              vararg_idx++;\n            else\n              error (strcat (\"normalize: 'norm' must be specified as\", ...\n                             \" a positive scalar or Inf\"));\n            endif\n          endif\n          if (isempty (methodoption))\n            methodoption = 2;\n          endif\n\n        case \"range\"\n          method = \"range\";\n          if (vararg_idx < n_varargin && isnumeric (varargin{vararg_idx+1}))\n            nextprop = varargin{vararg_idx+1};\n            if (any (size (nextprop) != [1 2]))\n              error (strcat (\"normalize: 'range' must be specified\", ...\n                             \" as a 2-element row vector [a, b]\"));\n            endif\n            methodoption = nextprop;\n            vararg_idx++;\n          endif\n          if (isempty (methodoption))\n            methodoption = [0, 1];\n          endif\n\n        case \"scale\"\n          method = \"scale\";\n          if (vararg_idx < n_varargin)\n            nextprop = lower (varargin{vararg_idx+1});\n            if (isnumeric (nextprop))\n              if (! isscalar (nextprop))\n                error (\"normalize: scale value must be a scalar\");\n              else\n                methodoption = nextprop;\n                vararg_idx++;\n              endif\n            elseif (any (strcmp (nextprop, {\"std\", \"mad\", \"first\", \"iqr\"})))\n              methodoption = nextprop;\n              vararg_idx++;\n            endif\n          endif\n\n          if (isempty (methodoption))\n            methodoption = 'std';\n          endif\n\n        case \"center\"\n          method = \"center\";\n          if (vararg_idx < n_varargin)\n            nextprop = lower (varargin{vararg_idx+1});\n            if (isscalar (nextprop)\n                || any (strcmp (nextprop, {\"mean\", \"median\"})))\n              methodoption = nextprop;\n              vararg_idx++;\n            elseif (isnumeric (nextprop))\n              error (\"normalize: center shift must be a scalar value\");\n            endif\n          endif\n          if (isempty (methodoption))\n            methodoption = 'mean';\n          endif\n\n        case \"medianiqr\"\n          method = \"medianiqr\";\n\n        otherwise\n          error (\"normalize: unknown method '%s'\", prop);\n\n      endswitch\n\n      vararg_idx++;\n    endwhile\n\n    if (scale_and_center_flag)\n      method = \"scaleandcenter\";\n    endif\n\n    if (isempty (method))\n      method = 'zscore';\n      methodoption = 'std';\n    endif\n\n    if (isempty (dim))\n      ## Operate on first non-singleton dimension.\n      (dim = find (size (x) > 1, 1)) || (dim = 1);\n    endif\n\n    ## Perform normalization based on specified methods\n\n    ## Default center/scale factors:\n    c = 0;\n    s = 1;\n\n    switch (method)\n      case \"zscore\"\n        switch (methodoption)\n          case \"std\"\n            [s, c] = std (x, [], dim, \"omitnan\");\n          case \"robust\"\n            ## center/median to zero and MAD = 1\n            c = median (x, dim, \"omitnan\");\n            s = median (abs (x - c), dim, \"omitnan\");\n        endswitch\n\n      case \"norm\"\n        switch (methodoption)\n          case 1\n            s = sum (abs (x), dim, \"omitnan\");\n          case Inf\n            s = max (abs (x), [], dim);\n          otherwise\n            s = sum (abs (x) .^ methodoption, dim) .^ (1/methodoption);\n        endswitch\n\n      case \"range\"\n        ## if any range element = 0, avoid divide by zero by replacing that\n        ## range element with 1.  output will be zero+min due to x-min(x)=0.\n        x_range = range (x, dim);\n        x_range(x_range == 0) = 1;\n        z_range = methodoption(2) - methodoption(1);\n        s = x_range ./ z_range;\n        c = min (x, [], dim) - (methodoption(1) .* s);\n\n      case \"scale\"\n        s = process_scale_option (x, dim, methodoption);\n\n      case \"center\"\n        c = process_center_option (x, dim, methodoption);\n\n      case \"scaleandcenter\"\n        ## repeats scale and center using appropriate order and info\n\n        switch (stored_method)\n          case \"scale\"\n            ## stored info is scale, latest info is center\n            center_option = methodoption;\n            scale_option = stored_methodoption;\n\n          case \"center\"\n            ## stored info is center, latest info is scale\n            center_option = stored_methodoption;\n            scale_option = methodoption;\n        endswitch\n\n        s = process_scale_option (x, dim, scale_option);\n        c = process_center_option (x, dim, center_option);\n\n      case \"medianiqr\"\n        c = median (x, dim, \"omitnan\");\n        s = iqr (x, dim);\n\n    endswitch\n\n  endif\n\n  ## Divide by scale factor.  If scale = 0, divide by zero = Inf, which is OK.\n  z = (x - c) ./ s;\n\nendfunction\n\nfunction c = process_center_option (x, dim, center_option)\n\n  if (isnumeric (center_option))\n    c = center_option;\n  else\n    switch (center_option)\n      case \"mean\"\n        c = mean (x, dim, \"omitnan\");\n      case \"median\"\n        c = median (x, dim, \"omitnan\");\n    endswitch\n  endif\n\nendfunction\n\nfunction s = process_scale_option (x, dim, scale_option)\n\n  warning (\"off\", \"Octave:divide-by-zero\", \"local\");\n\n  if (isnumeric (scale_option))\n    s = scale_option;\n  else\n    switch (scale_option)\n      case \"std\"\n        s = std (x, [], dim, \"omitnan\");\n      case \"mad\"\n        s = mad (x, 1, dim);\n      case \"first\"\n        dim_vector = repmat ({':'}, ndims(x), 1);\n        dim_vector{dim} = 1;\n        s = x(dim_vector{:});\n      case \"iqr\"\n        s = iqr (x, dim);\n    endswitch\n  endif\n\nendfunction\n\n\n## no method specified, using zscore & std\n%!assert (normalize ([1,2,3]), [-1,0,1])\n%!assert (normalize ([1,2,3], 2), [-1,0,1])\n%!assert (normalize (single ([1,2,3])), single ([-1,0,1]))\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2]), [1,0,-1;0,1,0;-1,-1,1])\n%!assert (normalize (magic (3)), [[3;-2;-1]/sqrt(7),[-1;0;1],[1;2;-3]/sqrt(7)])\n%!assert (normalize (magic (3), 2), [[3 -4 1]/sqrt(13);[-1 0 1];[-1 4 -3]/sqrt(13)])\n\n## Method: zscore, [std, robust]\n%!assert (normalize ([1,2,3],\"zscore\",\"std\"), [-1,0,1])\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"zscore\",\"std\"), [1,0,-1;0,1,0;-1,-1,1])\n%!assert (normalize (magic (3),\"zscore\",\"std\"), [[3;-2;-1]/sqrt(7),[-1;0;1],[1;2;-3]/sqrt(7)])\n%!assert (normalize ([1,2,3],\"zscore\",\"robust\"), [-1,0,1])\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"zscore\",\"robust\"), [1,0,-1;0,1,0;-1,-1,1])\n%!assert (normalize (magic (3),\"zscore\",\"robust\"), [4 -1 0; -1 0 1; 0 1 -4])\n\n## Method: norm [1, 2, inf]\n%!assert (normalize ([1,2,3],\"norm\",1), [1/6 1/3 1/2])\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"norm\",1), [1,0,-1;0,1,0;-1,-1,1]/2)\n%!assert (normalize (magic (3),\"norm\",1), magic (3) / 15)\n%!assert (normalize ([1,2,3],\"norm\",2), [1 2 3]./3.741657386773941, eps)\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"norm\",2), [1,0,-1;0,1,0;-1,-1,1]*(sqrt(2)/2), eps)\n%!assert (normalize ([1,2,3],\"norm\",Inf), [1/3 2/3 1])\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"norm\",Inf), [1,0,-1;0,1,0;-1,-1,1])\n%!assert (normalize (magic (3),\"norm\",Inf), [[8;3;4]/8,[1;5;9]/9,[6;7;2]/7])\n\n## Method: range\n%!assert (normalize ([1,2,3],\"range\"), [0 0.5 1])\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"range\",[0 1]), [1,0.5,0;0.5,1,0.5;0,0,1])\n%!assert (normalize (magic (3),\"range\",[-1 1]), [1 -1 0.6; -1 0 1; -0.6 1 -1], eps)\n\n## Method: scale [mad first iqr number]\n%!assert (normalize ([1,2,3],\"scale\"), [1 2 3])\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"scale\",\"std\"), [1 0 -1; 0 1 0; -1 -1 1])\n%!assert (normalize (magic (3),\"scale\",2), (magic (3)/2))\n\n%!assert (normalize ([1,2,3],\"scale\", \"mad\"), [1 2 3])\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"scale\",\"mad\"), [1 0 -1; 0 1 0; -1 -1 1])\n%!assert (normalize (magic (3),\"scale\",\"mad\"), [8 0.25 6; 3 1.25 7; 4 2.25 2])\n\n%!assert (normalize ([1,2,3],\"scale\", \"first\"), [1 2 3])\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"scale\",\"first\"), [1 NaN 1; 0 Inf 0; -1 -Inf -1])\n%!assert (normalize (magic (3),\"scale\",\"first\"), [1 1 1; 3/8 5 7/6; 0.5 9 1/3])\n%!assert (normalize (magic (3),2,\"scale\",\"first\"), [1 1/8 3/4;1 5/3 7/3;1 9/4 0.5])\n%!test\n%! x = reshape (magic (4),2,2,2,2);\n%! y3 = cat (4, cat (3,ones(2),[1/8 7/9;11/5 7/2]), cat (3,ones(2),[13/3 2; 4/5 1/15]));\n%! y4 = cat (4, ones (2,2,2), cat (3,[3/16 2/3; 2 15/4],[6.5 12/7; 8/11 1/14] ));\n%! assert (normalize (x, 3, \"scale\", \"first\"), y3);\n%! assert (normalize (x, 4, \"scale\", \"first\"), y4);\n\n%!assert (normalize ([1,2,3], \"scale\", \"iqr\"), [1 2 3]*2/3)\n%!assert (normalize ([1,2,3]', \"scale\", \"iqr\"), ([1 2 3]')*2/3)\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2],\"scale\",\"iqr\"), [1 0 -1; 0 1 0; -1 -1 1]* 2/3, eps)\n%!assert (normalize (magic (3),\"scale\",\"iqr\"), [[8;3;4]/3.75,[1;5;9]/6,[6;7;2]/3.75],eps)\n\n## Method: center [mean median number]\n%!assert (normalize ([1,2,3], \"center\"), [-1 0 1])\n%!assert (normalize ([1,2,3], 1, \"center\"), [0 0 0])\n%!assert (normalize ([1,2,3], \"center\", 10), [-9 -8 -7])\n%!assert (normalize ([1 2 3 10], \"center\", \"mean\"), [-3 -2 -1 6])\n%!assert (normalize ([1 2 3 10], \"center\", \"median\"), [-1.5 -0.5 0.5 7.5])\n\n## Method: medianiqr\n%!assert (normalize ([1,2,3], \"medianiqr\"), [-1 0 1]*2/3)\n%!assert (normalize ([1,2,3]', \"medianiqr\"), ([-1 0 1]')*2/3)\n%!assert (normalize ([2,0,-2;0,2,0;-2,-2,2], \"medianiqr\"), [1 0 -1; 0 1 0; -1 -1 1]*2/3)\n%!assert (normalize (magic (3), \"medianiqr\"), [8/5 -1 0; -2/5 0 2/5; 0 1 -8/5]*2/3)\n\n## Test NaN and Inf\n%!assert (normalize ([1 2 Inf], 2), [NaN, NaN, NaN])\n%!assert (normalize ([1 2 3], 1), [NaN, NaN, NaN])\n%!assert (normalize ([1 2 3], 3), [NaN, NaN, NaN])\n%!assert (normalize (ones (3,2,2,2)), NaN (3,2,2,2))\n%!assert (normalize (Inf), NaN)\n%!assert (normalize (NaN), NaN)\n%!assert (normalize ([Inf, NaN]), [NaN, NaN])\n%!assert (normalize ([Inf, NaN]'), [NaN, NaN]')\n%!assert (normalize ([Inf, Inf], 1), [NaN, NaN])\n%!assert (normalize ([Inf, Inf], 2), [NaN, NaN])\n%!assert (normalize ([Inf, Inf]', 1), [NaN, NaN]')\n%!assert (normalize ([Inf, Inf]', 2), [NaN, NaN]')\n%!assert (normalize ([1 2 NaN; NaN 3 4], 1), [NaN -1 NaN; NaN 1 NaN]*sqrt(2)/2, eps)\n\n## Two input methods, must be scale and center\n%!assert (normalize (magic (3), \"scale\", \"center\"), normalize (magic (3), \"zscore\"), eps)\n%!assert (normalize (magic (3), \"center\", \"scale\"), normalize (magic (3), \"zscore\"), eps)\n\n## Test additional outputs\n%!test\n%! [z, c, s] = normalize ([1, 2, 3], 2);\n%! assert ({z, c, s}, {[-1 0 1], [2], [1]});\n%! [z, c, s] = normalize (magic (3), \"zscore\", \"std\");\n%! assert ({z, c, s}, {[[3;-2;-1]/sqrt(7),[-1;0;1],[1;2;-3]/sqrt(7)], [5 5 5], [sqrt(7) 4 sqrt(7)]});\n%! [z, c, s] = normalize (magic (3), \"zscore\", \"robust\");\n%! assert ({z, c, s}, {[4 -1 0; -1 0 1; 0 1 -4], [4 5 6], [1 4 1]});\n%! [z, c, s] = normalize (magic (3), \"norm\", 1);\n%! assert ({z, c, s}, {magic(3)/15 , 0, [15 15 15]});\n%! [z, c, s] = normalize ([2,0,-2;0,2,0;-2,-2,2],\"norm\",2);\n%! assert ({z, c, s}, {[1,0,-1;0,1,0;-1,-1,1]*(sqrt(2)/2), 0, [1 1 1]*2*sqrt(2)}, eps);\n%! [z, c, s] = normalize ([1 2 3], \"norm\", Inf);\n%! assert ({z, c, s}, {[1 2 3]/3, 0, 3}, eps);\n%! [z, c, s] = normalize (magic (3),\"range\",[-1 1]);\n%! assert ({z, c, s}, {[1 -1 0.6; -1 0 1; -0.6 1 -1], [5.5 5 4.5], [2.5 4 2.5]}, eps);\n%! [z, c, s] = normalize (magic (3),\"scale\",\"mad\");\n%! assert ({z, c, s}, {[8 0.25 6; 3 1.25 7; 4 2.25 2], 0, [1 4 1]});\n%! [z, c, s] = normalize (magic (3),\"scale\",\"first\");\n%! assert ({z, c, s}, {[1 1 1; 3/8 5 7/6; 0.5 9 1/3],0, [8 1 6]}, eps);\n%! [z, c, s] = normalize ([1,2,3]', \"scale\", \"iqr\");\n%! assert ({z, c, s}, {([1 2 3]')*2/3, 0, 1.5});\n%! [z, c, s] = normalize ([1,2,3], \"center\", 10);\n%! assert ({z, c, s}, {[-9 -8 -7], 10, 1});\n%! [z, c, s] = normalize ([1 2 3 10], \"center\", \"mean\");\n%! assert ({z, c, s}, {[-3 -2 -1 6], 4, 1});\n%! [z, c, s] = normalize ([1 2 3 10], \"center\", \"median\");\n%! assert ({z, c, s}, {[-1.5 -0.5 0.5 7.5], 2.5, 1});\n%! [z, c, s] = normalize (magic (3), \"medianiqr\");\n%! assert ({z, c, s}, {[8/5 -1 0; -2/5 0 2/5; 0 1 -8/5]*2/3, [4 5 6], [3.75 6 3.75]}, eps);\n%! [z, c, s] = normalize ([1 2 Inf], 2);\n%! assert ({z, c, s}, {[NaN, NaN, NaN], Inf, NaN});\n%! [z, c, s] = normalize (Inf);\n%! assert ({z, c, s}, {NaN, Inf, NaN});\n\n## Test sparse and diagonal inputs\n%!test\n%! [z, c, s] = normalize (eye (2));\n%! assert (z, (sqrt(2)/2)*[1, -1; -1, 1], eps);\n%! assert (c, [0.5, 0.5], eps);\n%! assert (s, (sqrt(2)/2)*[1, 1], eps);\n%!test\n%! [z, c, s] = normalize (sparse (eye (2)));\n%! assert (full (z), (sqrt(2)/2)*[1, -1; -1, 1], eps);\n%! assert (full (c), [0.5, 0.5], eps);\n%! assert (full (s), (sqrt(2)/2)*[1, 1], eps);\n%!test\n%! [z, c, s] = normalize (sparse (magic (3)), \"zscore\", \"robust\");\n%! assert (full (z), [4 -1 0; -1 0 1; 0 1 -4], eps);\n%! assert (full (c), [4, 5, 6], eps);\n%! assert (full (s), [1, 4, 1], eps);\n%!test <*55765>\n%! [z, c, s] = normalize (sparse (eye(2)));\n%! assert (issparse (z));\n%! assert (issparse (c));\n%! assert (issparse (s));\n%!test <*55765>\n%! [z, c, s] = normalize (sparse (magic (3)), \"zscore\", \"robust\");\n%! assert (issparse (z));\n%! assert (issparse (c));\n%! assert (issparse (s));\n\n## Test that normalize ignores NaN values\n%!assert <*50571> (normalize ([1 2 NaN], 2), [-1, 1, NaN]*sqrt(2)/2, eps)\n%!assert <*50571> (normalize ([1 2 NaN; 1 2 3], 2), [[-1 1 NaN]*sqrt(2)/2; -1 0 1], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 1 2 NaN], 1), NaN (2, 3))\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2), [sqrt(2)/2*[-1 1 NaN]; -1 0 1], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"zscore\", \"robust\"), [-1 1 NaN; -1 0 1])\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"norm\", 1), [1/3 2/3 NaN; 2/9 1/3 4/9], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"norm\", Inf), [0.5 1 NaN; 0.5 0.75 1], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"range\", [1 2]), [1 2 NaN; 1 1.5 2], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"scale\", 2), [0.5 1 NaN; 1 1.5 2], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"scale\", \"mad\"), [2 4 NaN; 2 3 4], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"scale\", \"first\"), [1 2 NaN; 1 1.5 2], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"scale\", \"iqr\"), [1 2 NaN; 4/3 2 8/3], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"center\", \"mean\"), [-0.5 0.5 NaN; -1 0 1], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"center\", \"median\"), [-0.5 0.5 NaN; -1 0 1], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, \"center\", -1), [2 3 NaN; 3 4 5], eps)\n%!assert <*50571> (normalize ([1 2 NaN; 2 3 NaN], 2, \"center\", \"mean\", \"scale\", \"std\"), sqrt(2)/2*[-1 1 NaN; -1 1 NaN], eps)\n\n## Test input validation\n%!error <Invalid call> normalize ()\n%!error <Invalid call> normalize (1, 2, 3)\n%!error <X must be a numeric> normalize (['A'; 'B'])\n%!error <X must be double or single data type> normalize (int32 ([1; 2]))\n%!error <DIM must be an integer> normalize (1, ones (2,2))\n%!error <DIM must be an integer> normalize (1, 1.5)\n%!error <DIM must be .* a valid dimension> normalize (1, 0)\n%!error <'DataVariables' optional paired argument is only> normalize ([1:4]', \"Datavariables\")\n%!error <more than two methods specified> normalize ([1 2 3], \"scale\", \"center\", \"norm\")\n%!error <methods .* may not be combined> normalize ([1 2 3], \"norm\", \"zscore\")\n%!error <unknown method 'foo'> normalize ([1 2 3], \"norm\", \"foo\")\n%!error <'norm' must be specified as a positive scalar or Inf> normalize ([1 2 3], \"norm\", [1 2])\n%!error <'norm' must be specified as a positive scalar or Inf> normalize ([1 2 3], \"norm\", -1)\n%!error <'range' must be specified as> normalize ([1 2 3], \"range\", [1 2]')\n%!error <'range' must be specified as> normalize ([1 2 3], \"range\", [1 2 3])\n%!error <'range' must be specified as> normalize ([1 2 3], \"range\", 1)\n%!error <scale value must be a scalar> normalize ([1 2 3], \"scale\", [1 2 3])\n%!error <center shift must be a scalar value> normalize ([1 2 3], \"center\", [1 2])\n%!error <unknown method 'foo'> normalize ([1 2 3], \"foo\")\n"
  },
  {
    "path": "scripts/statistics/prctile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} prctile (@var{x})\n## @deftypefnx {} {@var{q} =} prctile (@var{x}, @var{p})\n## @deftypefnx {} {@var{q} =} prctile (@var{x}, @var{p}, @var{dim})\n## @deftypefnx {} {@var{q} =} prctile (@var{x}, @var{p}, @var{vecdim})\n## @deftypefnx {} {@var{q} =} prctile (@var{x}, @var{p}, \"all\")\n## @deftypefnx {} {@var{q} =} prctile (@var{x}, @var{p}, @dots{}, @var{method})\n## Compute the percentiles of the input data @var{x}.\n##\n## If @var{x} is a vector, then @code{prctile (@var{x})} computes the\n## percentiles specified by @var{p} of the data in @var{x}.\n##\n## If @var{x} is a matrix, then @code{prctile (@var{x})} returns a matrix such\n## that the i-th row of @var{q} contains the @var{p}(i)th percentiles of each\n## column of @var{x}.\n##\n## If @var{x} is an array, then @code{prctile (@var{x})} computes the\n## percentiles specified by @var{p} along the first non-singleton dimension of\n## @var{x}.\n##\n## The data in @var{x} must be numeric and any NaN values are ignored.  The\n## size of @var{q} is equal to the size of @var{x} except for the operating\n## dimension, which equals to the number of quantiles specified by @var{p}.\n##\n## @var{p} is a numeric vector specifying the percentiles to be computed.  All\n## elements of @var{p} must be in the range from 0 to 100.  If @var{p} is\n## unspecified, return the percentiles for @code{[0 25 50 75 100]}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return N\n## copies of @var{x} along the operating dimension, where N is the number of\n## specified percentiles.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.  If all dimensions in\n## @var{vecdim} are greater than @code{ndims (@var{x})}, then @code{quantile}\n## will return N copies of @var{x} along the smallest dimension in\n## @var{vecdim}.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{iqr} to operate\n## on all elements of @var{x}, and is equivalent to @code{iqr (@var{x}(:))}.\n##\n## The fourth input argument, @var{methods}, determines the method to calculate\n## the percentiles specified by @var{p}.  The methods available to calculate\n## sample percentiles are the nine methods used by R\n## (@url{https://www.r-project.org/}) and can be specified by the corresponding\n## integer value.  The default value is @w{@var{method} = 5}.\n##\n## Discontinuous sample quantile methods 1, 2, and 3\n##\n## @enumerate 1\n## @item Method 1: Inverse of empirical distribution function.\n##\n## @item Method 2: Similar to method 1 but with averaging at discontinuities.\n##\n## @item Method 3: SAS definition: nearest even order statistic.\n## @end enumerate\n##\n## Continuous sample quantile methods 4 through 9, where\n## @tex\n## $p(k)$\n## @end tex\n## @ifnottex\n## @var{p}(k)\n## @end ifnottex\n## is the linear\n## interpolation function respecting each method's representative cdf.\n##\n## @enumerate 4\n## @item Method 4:\n## @tex\n## $p(k) = k / N$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = k / N.\n## @end ifnottex\n## That is, linear interpolation of the empirical cdf, where @math{N} is the\n## length of @var{P}.\n##\n## @item Method 5:\n## @tex\n## $p(k) = (k - 0.5) / N$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = (k - 0.5) / N.\n## @end ifnottex\n## That is, a piecewise linear function where the knots are the values midway\n## through the steps of the empirical cdf.\n##\n## @item Method 6:\n## @tex\n## $p(k) = k / (N + 1)$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = k / (N + 1).\n## @end ifnottex\n##\n## @item Method 7:\n## @tex\n## $p(k) = (k - 1) / (N - 1)$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = (k - 1) / (N - 1).\n## @end ifnottex\n##\n## @item Method 8:\n## @tex\n## $p(k) = (k - 1/3) / (N + 1/3)$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = (k - 1/3) / (N + 1/3).\n## @end ifnottex\n## The resulting quantile estimates are approximately median-unbiased\n## regardless of the distribution of @var{x}.\n##\n## @item Method 9:\n## @tex\n## $p(k) = (k - 3/8) / (N + 1/4)$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = (k - 3/8) / (N + 1/4).\n## @end ifnottex\n## The resulting quantile estimates are approximately unbiased for the\n## expected order statistics if @var{x} is normally distributed.\n## @end enumerate\n## @seealso{quantile}\n## @end deftypefn\n\nfunction q = prctile (x, p = [], dim, method)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x)))\n    error (\"prctile: X must be a numeric array\");\n  endif\n\n  if (isempty (p))\n    p = [0, 25, 50, 75, 100];\n  endif\n\n  if (! (isnumeric (p) && isvector (p)))\n    error (\"prctile: P must be a numeric vector\");\n  endif\n\n  if (any (p < 0 | p > 100))\n    error (\"prctile: P values must range from 0 to 100\");\n  endif\n\n  ## Convert from percent to decimal.\n  p /= 100;\n\n  if (nargin < 3)\n    q = quantile (x, p);\n  elseif (nargin < 4)\n    q = quantile (x, p, dim);\n  elseif (nargin < 5)\n    q = quantile (x, p, dim, method);\n  endif\n\nendfunction\n\n\n%!test\n%! pct = 50;\n%! q = prctile (1:4, pct);\n%! qa = 2.5;\n%! assert (q, qa);\n%! q = prctile (1:4, pct, 1);\n%! qa = [1, 2, 3, 4];\n%! assert (q, qa);\n%! q = prctile (1:4, pct, 2);\n%! qa = 2.5;\n%! assert (q, qa);\n\n%!test\n%! pct = [50 75];\n%! q = prctile (1:4, pct);\n%! qa = [2.5 3.5];\n%! assert (q, qa);\n%! q = prctile (1:4, pct, 1);\n%! qa = [1, 2, 3, 4; 1, 2, 3, 4];\n%! assert (q, qa);\n%! q = prctile (1:4, pct, 2);\n%! qa = [2.5 3.5];\n%! assert (q, qa);\n\n%!test\n%! pct = 50;\n%! x = [0.1126, 0.1148, 0.0521, 0.2364, 0.1393\n%!      0.1718, 0.7273, 0.2041, 0.4531, 0.1585\n%!      0.2795, 0.7978, 0.3296, 0.5567, 0.7307\n%!      0.4288, 0.8753, 0.6477, 0.6287, 0.8165\n%!      0.9331, 0.9312, 0.9635, 0.7796, 0.8461];\n%! tol = 0.0001;\n%! q = prctile (x, pct, 1);\n%! qa = [0.2795, 0.7978, 0.3296, 0.5567, 0.7307];\n%! assert (q, qa, tol);\n%! q = prctile (x, pct, 2);\n%! qa = [0.1148; 0.2041; 0.5567; 0.6477; 0.9312];\n%! assert (q, qa, tol);\n\n%!test\n%! pct = 50;\n%! tol = 0.0001;\n%! x = [0.1126, 0.1148, 0.0521, 0.2364, 0.1393\n%!      0.1718, 0.7273, 0.2041, 0.4531, 0.1585\n%!      0.2795, 0.7978, 0.3296, 0.5567, 0.7307\n%!      0.4288, 0.8753, 0.6477, 0.6287, 0.8165\n%!      0.9331, 0.9312, 0.9635, 0.7796, 0.8461];\n%! x(5,5) = Inf;\n%! q = prctile (x, pct, 1);\n%! qa = [0.2795, 0.7978, 0.3296, 0.5567, 0.7307];\n%! assert (q, qa, tol);\n%! x(5,5) = -Inf;\n%! q = prctile (x, pct, 1);\n%! qa = [0.2795, 0.7978, 0.3296, 0.5567, 0.1585];\n%! assert (q, qa, tol);\n%! x(1,1) = Inf;\n%! q = prctile (x, pct, 1);\n%! qa = [0.4288, 0.7978, 0.3296, 0.5567, 0.1585];\n%! assert (q, qa, tol);\n\n%!test\n%! pct = 50;\n%! tol = 0.0001;\n%! x = [0.1126, 0.1148, 0.0521, 0.2364, 0.1393\n%!      0.1718, 0.7273, 0.2041, 0.4531, 0.1585\n%!      0.2795, 0.7978, 0.3296, 0.5567, 0.7307\n%!      0.4288, 0.8753, 0.6477, 0.6287, 0.8165\n%!      0.9331, 0.9312, 0.9635, 0.7796, 0.8461];\n%! x(3,3) = Inf;\n%! q = prctile (x, pct, 1);\n%! qa = [0.2795, 0.7978, 0.6477, 0.5567, 0.7307];\n%! assert (q, qa, tol);\n%! q = prctile (x, pct, 2);\n%! qa = [0.1148; 0.2041; 0.7307; 0.6477; 0.9312];\n%! assert (q, qa, tol);\n\n%!test\n%! pct = 50;\n%! tol = 0.0001;\n%! x = [0.1126, 0.1148, 0.0521, 0.2364, 0.1393\n%!      0.1718, 0.7273, 0.2041, 0.4531, 0.1585\n%!      0.2795, 0.7978, 0.3296, 0.5567, 0.7307\n%!      0.4288, 0.8753, 0.6477, 0.6287, 0.8165\n%!      0.9331, 0.9312, 0.9635, 0.7796, 0.8461];\n%! x(5,5) = NaN;\n%! q = prctile (x, pct, 2);\n%! qa = [0.1148; 0.2041; 0.5567; 0.6477; 0.9322];\n%! assert (q, qa, tol);\n%! x(1,1) = NaN;\n%! q = prctile (x, pct, 2);\n%! qa = [0.1270; 0.2041; 0.5567; 0.6477; 0.9322];\n%! assert (q, qa, tol);\n%! x(3,3) = NaN;\n%! q = prctile (x, pct, 2);\n%! qa = [0.1270; 0.2041; 0.6437; 0.6477; 0.9322];\n%! assert (q, qa, tol);\n\n%!assert (prctile ([1:10], 1, 3), [1:10])\n\n## Test input validation\n%!error <Invalid call> prctile ()\n%!error <prctile: X must be a numeric array> prctile (['A'; 'B'], 10)\n%!error <prctile: X must be a numeric array> prctile ([true; false], 10)\n%!error <prctile: X must be a numeric array> prctile ({1, 2, 3}, 10)\n%!error <prctile: P must be a numeric vector> prctile (1:10, [true, false])\n%!error <prctile: P must be a numeric vector> prctile (1:10, ones (2, 3))\n%!error <prctile: P values must range from 0 to 100> prctile (1:10, -20)\n"
  },
  {
    "path": "scripts/statistics/quantile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{q} =} quantile (@var{x})\n## @deftypefnx {} {@var{q} =} quantile (@var{x}, @var{p})\n## @deftypefnx {} {@var{q} =} quantile (@var{x}, @var{n})\n## @deftypefnx {} {@var{q} =} quantile (@var{x}, @dots{}, @var{dim})\n## @deftypefnx {} {@var{q} =} quantile (@var{x}, @dots{}, @var{vecdim})\n## @deftypefnx {} {@var{q} =} quantile (@var{x}, @dots{}, \"all\")\n## @deftypefnx {} {@var{q} =} quantile (@var{x}, @var{p}, @dots{}, @var{method})\n## @deftypefnx {} {@var{q} =} quantile (@var{x}, @var{n}, @dots{}, @var{method})\n## Compute the quantiles of the input data @var{x}.\n##\n## If @var{x} is a vector, then @code{quantile (@var{x})} computes the quantiles\n## specified by @var{p} of the data in @var{x}.\n##\n## If @var{x} is a matrix, then @code{quantile (@var{x})} returns a matrix such\n## that the i-th row of @var{q} contains the @var{p}(i)th quantiles of each\n## column of @var{x}.\n##\n## If @var{x} is an array, then @code{quantile (@var{x})} computes the quantiles\n## specified by @var{p} along the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be numeric and any NaN values are ignored.  The\n## size of @var{q} is equal to the size of @var{x} except for the operating\n## dimension, which equals to the number of quantiles specified by @var{p}\n## or @var{n}.\n##\n## @var{p} is a numeric vector specifying the percentiles to be computed, which\n## correspond to the cumulative probabilities of the data .  All elements of\n## @var{p} must be in the range from 0 to 1.  If @var{p} is unspecified, return\n## the percentiles for @code{[0.00 0.25 0.50 0.75 1.00]}.  Alternatively, the\n## second input argument may be specified as a positive integer value @var{n},\n## in which case @code{quantile} returns the quantiles for @var{n} evenly\n## spaced cumulative probabilities computed as (1/(@var{n} + 1), 2/(@var{n}\n## + 1), @dots{}, @var{n}/(@var{n} + 1)) for @code{@var{n} > 1}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return N\n## copies of @var{x} along the operating dimension, where N is the number of\n## specified quantiles.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.  If all dimensions in\n## @var{vecdim} are greater than @code{ndims (@var{x})}, then @code{quantile}\n## will return N copies of @var{x} along the smallest dimension in\n## @var{vecdim}.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{iqr} to operate\n## on all elements of @var{x}, and is equivalent to @code{iqr (@var{x}(:))}.\n##\n## The fourth input argument, @var{methods}, determines the method to calculate\n## the quantiles specified by @var{p} or @var{n}.  The methods available to\n## calculate sample quantiles are the nine methods used by R\n## (@url{https://www.r-project.org/}) and can be specified by the corresponding\n## integer value.  The default value is @w{@var{method} = 5}.\n##\n## Discontinuous sample quantile methods 1, 2, and 3\n##\n## @enumerate 1\n## @item Method 1: Inverse of empirical distribution function.\n##\n## @item Method 2: Similar to method 1 but with averaging at discontinuities.\n##\n## @item Method 3: SAS definition: nearest even order statistic.\n## @end enumerate\n##\n## Continuous sample quantile methods 4 through 9, where\n## @tex\n## $p(k)$\n## @end tex\n## @ifnottex\n## @var{p}(k)\n## @end ifnottex\n## is the linear\n## interpolation function respecting each method's representative cdf.\n##\n## @enumerate 4\n## @item Method 4:\n## @tex\n## $p(k) = k / N$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = k / N.\n## @end ifnottex\n## That is, linear interpolation of the empirical cdf, where @math{N} is the\n## length of @var{P}.\n##\n## @item Method 5:\n## @tex\n## $p(k) = (k - 0.5) / N$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = (k - 0.5) / N.\n## @end ifnottex\n## That is, a piecewise linear function where the knots are the values midway\n## through the steps of the empirical cdf.\n##\n## @item Method 6:\n## @tex\n## $p(k) = k / (N + 1)$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = k / (N + 1).\n## @end ifnottex\n##\n## @item Method 7:\n## @tex\n## $p(k) = (k - 1) / (N - 1)$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = (k - 1) / (N - 1).\n## @end ifnottex\n##\n## @item Method 8:\n## @tex\n## $p(k) = (k - 1/3) / (N + 1/3)$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = (k - 1/3) / (N + 1/3).\n## @end ifnottex\n## The resulting quantile estimates are approximately median-unbiased\n## regardless of the distribution of @var{x}.\n##\n## @item Method 9:\n## @tex\n## $p(k) = (k - 3/8) / (N + 1/4)$.\n## @end tex\n## @ifnottex\n## @var{p}(k) = (k - 3/8) / (N + 1/4).\n## @end ifnottex\n## The resulting quantile estimates are approximately unbiased for the\n## expected order statistics if @var{x} is normally distributed.\n## @end enumerate\n##\n## @nospell{Hyndman and Fan} (1996) recommend method 8.  Maxima, S, and R\n## (versions prior to 2.0.0) use 7 as their default.  Minitab and SPSS\n## use method 6.  @sc{matlab} uses method 5.\n##\n## References:\n##\n## @itemize @bullet\n## @item @nospell{R. A. Becker, J. M. Chambers, and A. R. Wilks},\n## @cite{The New S Language}, @nospell{Wadsworth & Brooks/Cole}, 1988.\n##\n## @item @nospell{R. J. Hyndman, and Y. Fan}, \"Sample quantiles in statistical\n## packages\", @cite{American Statistician}, 50, @w{pp.@: 361}--365, 1996.\n##\n## @item @cite{R: A Language and Environment for Statistical Computing},\n## @url{https://cran.r-project.org/doc/manuals/fullrefman.pdf}.\n## @end itemize\n##\n## Examples:\n## @c Set example in small font to prevent overfull line\n##\n## @smallexample\n## @group\n## x = randi (1000, [10, 1]);  # Create empirical data in range 1-1000\n## q = quantile (x, [0, 1]);   # Return minimum, maximum of distribution\n## q = quantile (x, [0.25 0.5 0.75]); # Return quartiles of distribution\n## @end group\n## @end smallexample\n## @seealso{prctile}\n## @end deftypefn\n\nfunction q = quantile (x, p = [], dim, method = 5)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x)))\n    error (\"quantile: X must be a numeric array\");\n  endif\n\n  if (isempty (p))\n    p = [0.00, 0.25, 0.50, 0.75, 1.00];\n  endif\n\n  if (! (isnumeric (p) && isvector (p)))\n    error (\"quantile: P must be a numeric vector\");\n  endif\n\n  if (isscalar (p) && fix (p) == p && p > 1)\n    p = [1:p] ./ (p + 1);\n  elseif (any (p < 0 | p > 1))\n    error (strcat (\"quantile: P values must range from 0 to 1, unless\", ...\n                   \" specifying N evenly spaced cumulative probabilities\"));\n  endif\n\n  do_perm = false;\n  nd = ndims (x);\n  sz = size (x);\n  empty_x = isempty (x);\n\n  if (nargin < 3)\n    ## Find the first non-singleton dimension.\n    (dim = find (size (x) > 1, 1)) || (dim = 1);\n\n    ## Return immediately for an empty matrix.\n    if (empty_x)\n      if (nd == 2 && max (sz) <= 1)\n        ## Return the size of vector P\n        sz = size (p);\n      else\n        ## Reduce operating DIM to length of P\n        sz(dim) = numel (p);\n      endif\n      q = NaN (sz);\n      return;\n    endif\n  endif\n\n  if (isnumeric (dim))\n\n    ## Check for DIM argument\n    if (isscalar (dim))\n      if (! (dim == fix (dim) && dim > 0))\n        error (\"quantile: DIM must be a positive integer\");\n      endif\n\n      ## Return immediately for an empty matrix.\n      if (empty_x)\n        ## Reduce operating DIM to length of P\n        sz(dim) = numel (p);\n        ## Mask existing dims, new zero-dims must be 1\n        mask = ones (1, dim);\n        mask(1:nd) = 0;\n        sz(mask & sz == 0) = 1;\n        q = NaN (sz);\n        return;\n      endif\n\n      ## Return numel (p) copies of X if DIM > nd\n      if (dim > nd)\n        sz = ones (1, dim);\n        sz(dim) = numel (p);\n        q = repmat (x, sz);\n        return;\n      endif\n\n      ## Set the permutation vector.\n      perm = 1:(max (ndims (x), dim));\n      perm(1) = dim;\n      perm(dim) = 1;\n      do_perm = true;\n\n      ## Permute dim to the 1st index.\n      x = permute (x, perm);\n\n      ## Save the size of the permuted x N-D array.\n      sx = size (x);\n\n      ## Reshape to a 2-D array.\n      x = reshape (x, sx(1), []);\n\n    ## Check for proper VECDIM (more than 1 dim, no repeats)\n    elseif (isvector (dim) && isindex (dim) && all (diff (sort (dim))))\n\n      ## Discard exceeding dims, unless all dims > nd so keep smallest\n      vecdim = dim(dim <= nd);\n      if (isempty (vecdim))\n        dim = min (dim);\n      else\n        dim = vecdim;\n      endif\n\n      ## Return immediately for an empty matrix.\n      if (empty_x)\n        sz(dim(1)) = numel (p);   # reduce first operating VECDIM to P\n        sz(dim(2:end)) = 1;       # reduce other operating VECDIM to 1\n        ## Mask existing dims, new zero-dims must be 1\n        mask = ones (1, max (dim));\n        mask(1:nd) = 0;\n        sz(mask & sz == 0) = 1;\n        q = NaN (sz);\n        return;\n      endif\n\n      ## Return numel (p) copies of X if remaining DIM > nd\n      if (dim > nd)\n        sz = ones (1, dim);\n        sz(dim) = numel (p);\n        q = repmat (x, sz);\n        return;\n      endif\n\n      ## Return X with X(dim(1)) expanded to P, if all DIM == 1\n      if (all (sz(dim) == 1))\n        sz = ones (1, nd);\n        sz(dim(1)) = numel (p);   # reduce first operating VECDIM to P\n        sz(dim(2:end)) = 1;       # reduce other operating VECDIM to 1\n        q = repmat (x, sz);\n        return;\n      endif\n\n      ## Detect trivial case of DIM being all dimensions (same as \"all\").\n      vecdims = numel (dim);\n      max_dim = max (nd, max (dim));\n      if (vecdims == nd && max_dim == nd)\n        x = x(:);\n        sx = size (x);\n        dim = 1;\n      else\n        ## Algorithm: Move dimensions for operation to the front, keeping the\n        ## order of the remaining dimensions.  Reshape the moved dims into a\n        ## single dimension (row).  Calculate with __quantile__ along dim1 of\n        ## X, then reshape to correct dimensions.\n\n        dim = dim(:).';  # Force row vector\n\n        ## Permutation vector with DIM at front\n        perm = [1:max_dim];\n        perm(dim) = [];\n        perm = [dim, perm];\n        do_perm = true;\n\n        ## Reshape X to put dims to process at front.\n        x = permute (x, perm);\n        sx = size (x);\n\n        ## Preserve trailing singletons when dim > ndims (x).\n        sx = [sx, ones(1, max_dim - numel (sx))];\n        sx = [prod(sx(1:vecdims)), ones(1, (vecdims-1)), sx((vecdims+1):end)];\n\n        ## Size must always have 2 dimensions.\n        if (isscalar (sx))\n          sx = [sx, 1];\n        endif\n\n        ## Collapse dimensions to be processsed into single column.\n        x = reshape (x, sx);\n      endif\n\n    else\n      error (\"quantile: VECDIM must be a vector of non-repeating positive integers\");\n    endif\n\n  elseif (strcmpi (dim, \"all\"))\n\n    ## Return immediately for an empty matrix\n    if (empty_x)\n      ## Always return a column vector.\n      q = NaN (numel (p), 1);\n      return;\n    endif\n\n    ## \"all\" simplifies to collapsing all elements to single vector.\n    x = x(:);\n    sx = size (x);\n    dim = 1;\n\n  else\n    error (\"quantile: DIM must be a positive integer scalar, vector, or 'all'\");\n  endif\n\n  ## Calculate the quantiles.\n  q = __quantile__ (x, p, method);\n\n  ## Return the shape to the original N-D array.\n  q = reshape (q, [numel(p), sx(2:end)]);\n\n  ## Permute the 1st index back to dim.\n  if (do_perm)\n    q = ipermute (q, perm);\n  endif\n\n  ## For Matlab compatibility, return vectors with the same orientation as p\n  if (isvector (q) && ! isscalar (q) && ! isscalar (p))\n    if (isrow (p))\n      q = reshape (q, 1, []);\n    else\n      q = reshape (q, [], 1);\n    endif\n  endif\n\nendfunction\n\n\n%!test\n%! p = 0.50;\n%! q = quantile (1:4, p);\n%! qa = 2.5;\n%! assert (q, qa);\n%! q = quantile (1:4, p, 1);\n%! qa = [1, 2, 3, 4];\n%! assert (q, qa);\n%! q = quantile (1:4, p, 2);\n%! qa = 2.5;\n%! assert (q, qa);\n\n%!test\n%! p = [0.50 0.75];\n%! q = quantile (1:4, p);\n%! qa = [2.5 3.5];\n%! assert (q, qa);\n%! q = quantile (1:4, p, 1);\n%! qa = [1, 2, 3, 4; 1, 2, 3, 4];\n%! assert (q, qa);\n%! q = quantile (1:4, p, 2);\n%! qa = [2.5 3.5];\n%! assert (q, qa);\n\n%!test\n%! p = 0.5;\n%! x = sort (rand (11));\n%! q = quantile (x, p);\n%! assert (q, x(6,:));\n%! x = x.';\n%! q = quantile (x, p, 2);\n%! assert (q, x(:,6));\n\n%!test\n%! p = [0.00, 0.25, 0.50, 0.75, 1.00];\n%! x = [1; 2; 3; 4];\n%! a = [1.0000   1.0000   2.0000   3.0000   4.0000\n%!      1.0000   1.5000   2.5000   3.5000   4.0000\n%!      1.0000   1.0000   2.0000   3.0000   4.0000\n%!      1.0000   1.0000   2.0000   3.0000   4.0000\n%!      1.0000   1.5000   2.5000   3.5000   4.0000\n%!      1.0000   1.2500   2.5000   3.7500   4.0000\n%!      1.0000   1.7500   2.5000   3.2500   4.0000\n%!      1.0000   1.4167   2.5000   3.5833   4.0000\n%!      1.0000   1.4375   2.5000   3.5625   4.0000];\n%! for m = 1:9\n%!   q = quantile (x, p, 1, m);\n%!   assert (q, a(m,:), 0.0001);\n%! endfor\n\n%!test\n%! p = [0.00, 0.25, 0.50, 0.75, 1.00];\n%! x = [1; 2; 3; 4; 5];\n%! a = [1.0000   2.0000   3.0000   4.0000   5.0000\n%!      1.0000   2.0000   3.0000   4.0000   5.0000\n%!      1.0000   1.0000   2.0000   4.0000   5.0000\n%!      1.0000   1.2500   2.5000   3.7500   5.0000\n%!      1.0000   1.7500   3.0000   4.2500   5.0000\n%!      1.0000   1.5000   3.0000   4.5000   5.0000\n%!      1.0000   2.0000   3.0000   4.0000   5.0000\n%!      1.0000   1.6667   3.0000   4.3333   5.0000\n%!      1.0000   1.6875   3.0000   4.3125   5.0000];\n%! for m = 1:9\n%!   q = quantile (x, p, 1, m);\n%!   assert (q, a(m,:), 0.0001);\n%! endfor\n\n%!test\n%! p = [0.00, 0.25, 0.50, 0.75, 1.00];\n%! x = [1; 2; 5; 9];\n%! a = [1.0000   1.0000   2.0000   5.0000   9.0000\n%!      1.0000   1.5000   3.5000   7.0000   9.0000\n%!      1.0000   1.0000   2.0000   5.0000   9.0000\n%!      1.0000   1.0000   2.0000   5.0000   9.0000\n%!      1.0000   1.5000   3.5000   7.0000   9.0000\n%!      1.0000   1.2500   3.5000   8.0000   9.0000\n%!      1.0000   1.7500   3.5000   6.0000   9.0000\n%!      1.0000   1.4167   3.5000   7.3333   9.0000\n%!      1.0000   1.4375   3.5000   7.2500   9.0000];\n%! for m = 1:9\n%!   q = quantile (x, p, 1, m);\n%!   assert (q, a(m,:), 0.0001);\n%! endfor\n\n%!test\n%! p = [0.00, 0.25, 0.50, 0.75, 1.00];\n%! x = [1; 2; 5; 9; 11];\n%! a = [1.0000    2.0000    5.0000    9.0000   11.0000\n%!      1.0000    2.0000    5.0000    9.0000   11.0000\n%!      1.0000    1.0000    2.0000    9.0000   11.0000\n%!      1.0000    1.2500    3.5000    8.0000   11.0000\n%!      1.0000    1.7500    5.0000    9.5000   11.0000\n%!      1.0000    1.5000    5.0000   10.0000   11.0000\n%!      1.0000    2.0000    5.0000    9.0000   11.0000\n%!      1.0000    1.6667    5.0000    9.6667   11.0000\n%!      1.0000    1.6875    5.0000    9.6250   11.0000];\n%! for m = 1:9\n%!   q = quantile (x, p, 1, m);\n%!   assert (q, a(m,:), 0.0001);\n%! endfor\n\n%!test\n%! p = [0.00, 0.25, 0.50, 0.75, 1.00];\n%! x = [16; 11; 15; 12; 15;  8; 11; 12;  6; 10];\n%! a = [6.0000   10.0000   11.0000   15.0000   16.0000\n%!      6.0000   10.0000   11.5000   15.0000   16.0000\n%!      6.0000    8.0000   11.0000   15.0000   16.0000\n%!      6.0000    9.0000   11.0000   13.5000   16.0000\n%!      6.0000   10.0000   11.5000   15.0000   16.0000\n%!      6.0000    9.5000   11.5000   15.0000   16.0000\n%!      6.0000   10.2500   11.5000   14.2500   16.0000\n%!      6.0000    9.8333   11.5000   15.0000   16.0000\n%!      6.0000    9.8750   11.5000   15.0000   16.0000];\n%! for m = 1:9\n%!   q = quantile (x, p, 1, m);\n%!   assert (q, a(m,:), 0.0001);\n%! endfor\n\n%!test\n%! p = [0.00, 0.25, 0.50, 0.75, 1.00];\n%! x = [-0.58851;  0.40048;  0.49527; -2.551500; -0.52057; ...\n%!      -0.17841; 0.057322; -0.62523;  0.042906;  0.12337];\n%! a = [-2.551474  -0.588505  -0.178409   0.123366   0.495271\n%!      -2.551474  -0.588505  -0.067751   0.123366   0.495271\n%!      -2.551474  -0.625231  -0.178409   0.123366   0.495271\n%!      -2.551474  -0.606868  -0.178409   0.090344   0.495271\n%!      -2.551474  -0.588505  -0.067751   0.123366   0.495271\n%!      -2.551474  -0.597687  -0.067751   0.192645   0.495271\n%!      -2.551474  -0.571522  -0.067751   0.106855   0.495271\n%!      -2.551474  -0.591566  -0.067751   0.146459   0.495271\n%!      -2.551474  -0.590801  -0.067751   0.140686   0.495271];\n%! for m = 1:9\n%!   q = quantile (x, p, 1, m);\n%!   assert (q, a(m,:), 0.0001);\n%! endfor\n\n%!test\n%! p = 0.5;\n%! x = [0.112600, 0.114800, 0.052100, 0.236400, 0.139300\n%!      0.171800, 0.727300, 0.204100, 0.453100, 0.158500\n%!      0.279500, 0.797800, 0.329600, 0.556700, 0.730700\n%!      0.428800, 0.875300, 0.647700, 0.628700, 0.816500\n%!      0.933100, 0.931200, 0.963500, 0.779600, 0.846100];\n%! tol = 0.00001;\n%! x(5,5) = NaN;\n%! assert (quantile (x, p, 1),\n%!         [0.27950, 0.79780, 0.32960, 0.55670, 0.44460], tol);\n%! x(1,1) = NaN;\n%! assert (quantile (x, p, 1),\n%!         [0.35415, 0.79780, 0.32960, 0.55670, 0.44460], tol);\n%! x(3,3) = NaN;\n%! assert (quantile (x, p, 1),\n%!         [0.35415, 0.79780, 0.42590, 0.55670, 0.44460], tol);\n\n%!test\n%! sx = [2, 3, 4];\n%! x = rand (sx);\n%! dim = 2;\n%! p = 0.5;\n%! yobs = quantile (x, p, dim);\n%! yexp = median (x, dim);\n%! assert (yobs, yexp);\n\n%!assert <*45455> (quantile ([1 3 2], 0.5, 1), [1 3 2])\n%!assert <*54421> (quantile ([1:10], 0.5, 1), 1:10)\n%!assert <*54421> (quantile ([1:10]', 0.5, 2), [1:10]')\n%!assert <*54421> (quantile ([1:10], [0.25, 0.75]), [3, 8])\n%!assert <*54421> (quantile ([1:10], [0.25, 0.75]'), [3; 8])\n%!assert (quantile ([1:10], 1, 3), [1:10])\n\n## Test empty input arrays\n%!assert (quantile ([], [0.2, 0.5, 0.7]), NaN (1, 3))\n%!assert (quantile (ones (1, 0), [0.2, 0.5, 0.7]), NaN (1, 3))\n%!assert (quantile ([], [0.2, 0.5, 0.7, 0.9]), NaN (1, 4))\n%!assert (quantile (ones (1, 0), [0.2, 0.5, 0.7, 0.9]), NaN (1, 4))\n%!assert (quantile ([], [0.2, 0.5, 0.7], 2), NaN (0, 3))\n%!assert (quantile (ones (1, 0), [0.2, 0.5, 0.7], 2), NaN (1, 3))\n%!assert (quantile (ones (0, 1), [0.2, 0.5, 0.7], 2), NaN (0, 3))\n%!assert (quantile (ones (1, 0), [0.2, 0.5, 0.7], 1), NaN (3, 0))\n%!assert (quantile (ones (1, 0), [0.2, 0.5, 0.7], 3), NaN (1, 0, 3))\n%!assert (quantile (ones (1, 0, 1), [0.2, 0.5, 0.7], 3), NaN (1, 0, 3))\n%!assert (quantile (ones (3, 0, 1, 2), [0.2, 0.5, 0.7]), NaN (3, 0, 1, 2))\n%!assert (quantile (ones (3, 0, 1, 2), [0.2, 0.5, 0.7], 2), NaN (3, 3, 1, 2))\n%!assert (quantile (ones (3, 0, 1, 2), [0.2; 0.5; 0.7]), NaN (3, 0, 1, 2))\n%!assert (quantile (ones (3, 0, 1, 2), [0.2; 0.5; 0.7], 2), NaN (3, 3, 1, 2))\n%!assert (quantile (ones (1, 0), [0.2; 0.5; 0.7]), NaN (3, 1))\n%!assert (quantile (ones (0, 1), [0.2, 0.5, 0.7]), NaN (1, 3))\n%!assert (quantile (ones (5, 0, 1, 2), [0.2, 0.5, 0.7]), NaN (3, 0, 1, 2))\n%!assert (quantile (ones (5, 0), [0.2, 0.5, 0.7]), NaN (3, 0))\n%!assert (quantile (ones (1, 0), [0.2, 0.5, 0.7], 4), NaN (1, 0, 1, 3))\n%!assert (quantile (ones (1, 0), [0.2, 0.5, 0.7], 5), NaN (1, 0, 1, 1, 3))\n%!assert (quantile (ones (5, 0, 1), [0.2, 0.5, 0.7], [4:6]), NaN (5, 0, 1, 3))\n%!assert (quantile (ones (5, 0, 1), [0.2, 0.5, 0.7], [3, 4]), NaN (5, 0, 3))\n%!assert (quantile (ones (5, 0, 2, 2), [0.2, 0.5, 0.7], [2, 3]), NaN (5, 3, 1, 2))\n%!assert (quantile (ones (5, 0, 2, 2), [0.2, 0.5, 0.7], [1, 3]), NaN (3, 0, 1, 2))\n%!assert (quantile (ones (5, 0, 2, 2), [0.2, 0.5, 0.7], 'all'), NaN (3, 1))\n%!assert (quantile (ones (5, 0, 2, 2), [0.2; 0.5; 0.7], 'all'), NaN (3, 1))\n%!assert (quantile (ones (0, 1), [0.2, 0.5, 0.7], 'all'), NaN (3, 1))\n%!assert (quantile (ones (0, 1), [0.2; 0.5; 0.7], 'all'), NaN (3, 1))\n%!assert (quantile (ones (1, 0), [0.2, 0.5, 0.7], 'all'), NaN (3, 1))\n%!assert (quantile (ones (1, 0), [0.2; 0.5; 0.7], 'all'), NaN (3, 1))\n\n## Test DIM and VECDIM with exceeding dimensions\n%!assert (quantile (repmat ([1:10], 5, 1), [0.2, 0.5, 0.7], 2), ...\n%!        repmat ([2.5, 5.5, 7.5], 5, 1))\n%!assert (quantile (repmat ([1:10], 5, 1), [0.2, 0.5, 0.7], 3), ...\n%!        repmat ([1:10], 5, 1, 3))\n%!assert (quantile (repmat ([1:10], 5, 1), [0.2, 0.5, 0.7], 4), ...\n%!        repmat ([1:10], 5, 1, 1, 3))\n%!assert (quantile (repmat ([1:10], 5, 1), [0.2, 0.5, 0.7], [2, 4]), ...\n%!        repmat ([2.5, 5.5, 7.5], 5, 1))\n%!assert (quantile (repmat ([1:10], 5, 1), [0.2, 0.5, 0.7], [3, 5]), ...\n%!        repmat ([1:10], 5, 1, 3))\n%!assert (quantile (repmat ([1:10], 5, 1), [0.2, 0.5, 0.7], [4, 6]), ...\n%!        repmat ([1:10], 5, 1, 1, 3))\n\n## Test DIM and VECCDIM with dimensions of length 1\n%!assert (quantile (ones (5, 1, 2, 2), [0.2, 0.5, 0.7], 2), ones (5, 3, 2, 2))\n%!assert (quantile (ones (5, 1, 1, 2), [0.2, 0.5, 0.7], [2, 3]), ones (5, 3, 1, 2))\n\n## Test direction of P vector\n%!assert (quantile ([1:10], [0.2; 0.5; 0.7]), [2.5; 5.5; 7.5])\n%!assert (quantile ([1:10]', [0.2; 0.5; 0.7]), [2.5; 5.5; 7.5])\n%!assert (quantile ([1:10], [0.2, 0.5, 0.7]), [2.5, 5.5, 7.5])\n%!assert (quantile ([1:10]', [0.2, 0.5, 0.7]), [2.5, 5.5, 7.5])\n\n## Test N evenly spaced cummulative probabilities\n%!assert (quantile ([1:10], 3), [3, 5.5, 8])\n%!assert (quantile ([1:10]', 3), [3, 5.5, 8])\n%!assert (quantile ([1:10], 9), [1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5])\n%!assert (quantile ([1:10]', 9), [1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5])\n\n## Test input validation\n%!error <Invalid call> quantile ()\n%!error <quantile: X must be a numeric array> quantile (['A'; 'B'], 10)\n%!error <quantile: X must be a numeric array> quantile ([true; false], 10)\n%!error <quantile: X must be a numeric array> quantile ({1, 2}, [0.2, 0.5, 0.8])\n%!error <P must be a numeric vector> quantile (1:10, [true, false])\n%!error <P must be a numeric vector> quantile (1:10, ones (2,2))\n%!error <quantile: P values must range from 0 to 1, unless specifying N evenly spaced cumulative probabilities> ...\n%!       quantile (1:10, -1)\n%!error <quantile: P values must range from 0 to 1, unless specifying N evenly spaced cumulative probabilities> ...\n%!       quantile (1:10, [0.2, 0.5, -0.8])\n%!error <quantile: DIM must be a positive integer> quantile (1, 1, 1.5)\n%!error <quantile: DIM must be a positive integer> quantile (1, 1, 0)\n%!error <quantile: VECDIM must be a vector of non-repeating positive integers> ...\n%!       quantile (1, 1, [1, 2, 2])\n%!error <quantile: VECDIM must be a vector of non-repeating positive integers> ...\n%!       quantile (1, 1, [1, 2, 0])\n%!error <quantile: DIM must be a positive integer scalar, vector, or 'all'> ...\n%!       quantile (1, 1, \"some\")\n%!error quantile ((1:5)', 0.5, 1, 0)\n%!error quantile ((1:5)', 0.5, 1, 10)\n\n## For the cumulative probability values in @var{p}, compute the\n## quantiles, @var{q} (the inverse of the cdf), for the sample, @var{x}.\n##\n## The optional input, @var{method}, refers to nine methods available in R\n## (https://www.r-project.org/).  The default is @var{method} = 5.\n## @seealso{prctile, quantile, statistics}\n\n## Description: Quantile function of empirical samples\nfunction inv = __quantile__ (x, p, method = 5)\n\n  if (nargin < 2)\n    print_usage (\"quantile\");\n  endif\n\n  if (isinteger (x) || islogical (x))\n    x = double (x);\n  endif\n\n  ## set shape of quantiles to column vector.\n  p = p(:);\n\n  ## Save length and set shape of samples.\n  x = sort (x, 1);\n  m = sum (! isnan (x));\n  [xr, xc] = size (x);\n\n  ## Initialize output values.\n  inv = Inf (class (x)) * (-(p < 0) + (p > 1));\n  inv = repmat (inv, 1, xc);\n\n  ## Do the work.\n  if (any (k = find ((p >= 0) & (p <= 1))))\n    n = length (k);\n    p = p(k);\n    ## Special case of 1 row.\n    if (xr == 1)\n      inv(k,:) = repmat (x, n, 1);\n      return;\n    endif\n\n    ## The column-distribution indices.\n    pcd = kron (ones (n, 1), xr*(0:xc-1));\n    mm = kron (ones (n, 1), m);\n    switch (method)\n      case {1, 2, 3}\n        switch (method)\n          case 1\n            p = max (ceil (kron (p, m)), 1);\n            inv(k,:) = x(p + pcd);\n\n          case 2\n            p = kron (p, m);\n            p_lr = max (ceil (p), 1);\n            p_rl = min (floor (p + 1), mm);\n            inv(k,:) = (x(p_lr + pcd) + x(p_rl + pcd))/2;\n\n          case 3\n           ## Used by SAS, method PCTLDEF=2.\n           ## http://support.sas.com/onlinedoc/913/getDoc/en/statug.hlp/stdize_sect14.htm\n            t = max (kron (p, m), 1);\n            t = roundb (t);\n            inv(k,:) = x(t + pcd);\n        endswitch\n\n      otherwise\n        switch (method)\n          case 4\n            p = kron (p, m);\n\n          case 5\n            ## Used by Matlab.\n            p = kron (p, m) + 0.5;\n\n          case 6\n            ## Used by Minitab and SPSS.\n            p = kron (p, m+1);\n\n          case 7\n            ## Used by S and R.\n            p = kron (p, m-1) + 1;\n\n          case 8\n            ## Median unbiased.\n            p = kron (p, m+1/3) + 1/3;\n\n          case 9\n            ## Approximately unbiased respecting order statistics.\n            p = kron (p, m+0.25) + 0.375;\n\n          otherwise\n            error (\"quantile: Unknown METHOD, '%d'\", method);\n        endswitch\n\n        ## Duplicate single values.\n        imm1 = (mm(1,:) == 1);\n        x(2,imm1) = x(1,imm1);\n\n        ## Interval indices.\n        pi = max (min (floor (p), mm-1), 1);\n        pr = max (min (p - pi, 1), 0);\n        pi += pcd;\n        inv(k,:) = (1-pr) .* x(pi) + pr .* x(pi+1);\n    endswitch\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/statistics/range.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} range (@var{x})\n## @deftypefnx {} {@var{y} =} range (@var{x}, @var{dim})\n## @deftypefnx {} {@var{y} =} range (@var{x}, @var{vecdim})\n## @deftypefnx {} {@var{y} =} range (@var{x}, \"all\")\n## @deftypefnx {} {@var{y} =} range (@dots{}, @var{nanflag})\n## Return the difference between the maximum and the minimum values of the\n## input data @var{x}.\n##\n## If @var{x} is a vector, then @code{range (@var{x})} returns the difference\n## between the maximum and minimum values of the elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{range (@var{x})} returns a row vector\n## @var{y} with the difference between the maximum and minimum values for each\n## column of @var{x}.\n##\n## If @var{x} is an array, then @code{range (@var{x})} computes the difference\n## between the maximum and minimum values along the first non-singleton\n## dimension of @var{x}.\n##\n## The data in @var{x} must be numeric.  By default, any NaN values are\n## ignored.  The size of @var{r} is equal to the size of @var{x} except for\n## the operating dimension, which becomes 1.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{@var{x}}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{range} to operate\n## on all elements of @var{x}, and is equivalent to @code{range (@var{x}(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"omitnan\"} which does not include NaN values in the result.  If the\n## argument @qcode{\"includenan\"} is given, and there is a NaN present, then the\n## corresponding result will be NaN.\n##\n## Usage Note: The range is a quickly computed measure of the dispersion of a\n## data set, but is less accurate than @code{iqr} if there are outlying data\n## points.\n## @seealso{bounds, iqr, mad, std}\n## @end deftypefn\n\nfunction y = range (x, varargin)\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    error (\"range: X must be a numeric array\");\n  endif\n\n  if (isempty (varargin))\n    y = max (x) - min (x);\n  else\n    y = max (x, [], varargin{:}) - min (x, [], varargin{:});\n  endif\n\nendfunction\n\n\n%!assert (range (1:10), 9)\n%!assert (range (single (1:10)), single (9))\n%!assert (range (magic (3)), [5, 8, 5])\n%!assert (range (magic (3), 2), [7; 4; 7])\n%!assert (range (2), 0)\n%!test\n%! x = magic (3);\n%! x(2,3) = NaN;\n%! assert (range (x), [5, 8, 4]);\n%! assert (range (x, \"omitnan\"), [5, 8, 4]);\n%! assert (range (x, \"includenan\"), [5, 8, NaN]);\n%! assert (range (x, 2), [7; 2; 7]);\n%! assert (range (x, 2, \"omitnan\"), [7; 2; 7]);\n%! assert (range (x, 2, \"includenan\"), [7; NaN; 7]);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! assert (range (x, 3), x(:,:,3) - x(:,:,1));\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! assert (range (x, [2, 3]), x(:,3,3) - x(:,1,1));\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! assert (range (x, [1, 3]), x(3,:,3) - x(1,:,1));\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! assert (range (x, [1, 2, 3]), 26);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! assert (range (x, \"all\"), 26);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! assert (range (x, \"all\"), 26);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! assert (range (x, \"all\", \"omitnan\"), 26);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! assert (range (x, \"all\", \"includenan\"), NaN);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! s = min (x, [], \"includenan\");\n%! l = max (x, [], \"includenan\");\n%! assert (range (x, \"includenan\"), l - s);\n%!test\n%! x = reshape (1:27, [3, 3, 3]);\n%! x(3) = NaN;\n%! y = range (x, 3, \"includenan\");\n%! assert (y(3), NaN);\n\n## Test input validation\n%!error <Invalid call> range ()\n%!error <Invalid call> range (1, 2, 3, 4)\n%!error <range: X must be a numeric array> range (['A'; 'B'])\n%!error <range: X must be a numeric array> range ({1, 2})\n"
  },
  {
    "path": "scripts/statistics/ranks.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} ranks (@var{x})\n## @deftypefnx {} {@var{y} =} ranks (@var{x}, @var{dim})\n## @deftypefnx {} {@var{y} =} ranks (@var{x}, @var{dim}, @var{rtype})\n## Return the ranks (in the sense of order statistics) of @var{x} along the\n## first non-singleton dimension adjusted for ties.\n##\n## If the optional @var{dim} argument is given, operate along this dimension.\n##\n## The optional parameter @var{rtype} determines how ties are handled.  All\n## examples below assume an input of @code{[ 1, 2, 2, 4 ]}.\n##\n## @table @asis\n## @item 0 or @qcode{\"fractional\"} (default) for fractional ranking (1, 2.5,\n## 2.5, 4);\n##\n## @item 1 or @qcode{\"competition\"} for competition ranking (1, 2, 2, 4);\n##\n## @item 2 or @qcode{\"modified\"} for modified competition ranking (1, 3, 3, 4);\n##\n## @item 3 or @qcode{\"ordinal\"} for ordinal ranking (1, 2, 3, 4);\n##\n## @item 4 or @qcode{\"dense\"} for dense ranking (1, 2, 2, 3).\n## @end table\n##\n## @seealso{spearman, kendall}\n## @end deftypefn\n\nfunction y = ranks (x, dim, rtype = 0)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    error (\"ranks: X must be a numeric or logical array\");\n  endif\n\n  nd = ndims (x);\n  sz = size (x);\n\n  if (nargin < 2 || isempty (dim))\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  else\n    if (! (isscalar (dim) && dim == fix (dim) && dim > 0))\n      error (\"ranks: DIM must be an integer and a valid dimension\");\n    endif\n  endif\n\n  if (sz(dim) == 1)\n    y = ones (sz);  # dimension DIM is singleton, so all are ranked first.\n  else\n    ## The algorithm works only on dim = 1, so permute if necessary.\n    ## FIXME: Most all functions now accept a dim argument.\n    ##        Would it be faster not to permute and use the dim argument\n    ##        to sort, find, cumsum, etc.?\n    if (dim != 1)\n      perm = [1 : nd];\n      perm(1) = dim;\n      perm(dim) = 1;\n      x = permute (x, perm);\n      sz = size (x);\n    endif\n\n    [sx, ids] = sort (x);  # sx is sorted x.\n    lin = repmat ((1:rows (x))', [1, sz(2:end)]);  # linearly increasing array.\n\n    switch (rtype)\n      case {0, \"fractional\"}\n        lin = (_competition (lin, sx, sz) + _modified (lin, sx, sz)) / 2;\n      case {1, \"competition\"}\n        lin = _competition (lin, sx, sz);\n      case {2, \"modified\"}\n        lin = _modified (lin, sx, sz);\n      case {3, \"ordinal\"}\n        ## no processing needed here.\n      case {4, \"dense\"}\n        lin = _dense (lin, sx, sz);\n      otherwise\n        if (! ischar (rtype))\n          rtype = num2str (rtype);\n        endif\n        error (\"ranks: unknown RTYPE '%s'\", rtype);\n    endswitch\n\n    y = NaN (size (lin));\n\n    ## Offsets to map indices into each column to indices into the linear array.\n    ## FIXME: Would sub2ind be faster here?\n    idf = zeros (sz);\n    idf(1, :) = 0 : sz(1) : (numel (ids)-1);\n    idf(:, :) = repmat (idf(1, :), [sz(1), ones(1,length(sz)-1)]);\n    y(ids + idf) = lin;\n\n    if (dim != 1)\n      y = permute (y, perm);\n    endif\n  endif\n\nendfunction\n\nfunction linnew = _dense (lin, sx, sz)\n  infvec = -Inf ([1, sz(2:end)]);\n  fnewp = logical (diff ([infvec; sx]));\n  linnew = cumsum (fnewp, 1);\nendfunction\n\nfunction linnew = _competition (lin, sx, sz)\n\n  ## Stop increasing lin when sx does not increase.  Otherwise, same as before.\n  infvec = -Inf ([1, sz(2:end)]);\n  fnewp = find (diff ([infvec; sx]));\n  linnew = zeros (size (lin));\n  linnew(fnewp) = lin(fnewp);\n  linnew = cummax (linnew, 1);\n\nendfunction\n\nfunction linnew = _modified (lin, sx, sz)\n\n  ## Traverse lin backwards.  Stop decreasing it when sx doesn't decrease.\n  infvec = Inf ([1, sz(2:end)]);\n  fnewp = find (diff ([sx; infvec]));\n  linnew = Inf (size (lin));\n  linnew(fnewp) = lin(fnewp);\n  linnew = flip (cummin (flip (linnew, 1)), 1);\n\nendfunction\n\n\n%!assert (ranks (1:2:10), 1:5)\n%!assert (ranks (10:-2:1), 5:-1:1)\n%!assert (ranks ([2, 1, 2, 4]), [2.5, 1, 2.5, 4])\n%!assert (ranks (ones (1, 5)), 3*ones (1, 5))\n%!assert (ranks (1e6*ones (1, 5)), 3*ones (1, 5))\n%!assert (ranks (rand (1, 5), 1), ones (1, 5))\n\n%!assert (ranks ([1, 2, 2, 4], [], \"fractional\"), [1, 2.5, 2.5, 4])\n%!assert (ranks ([1, 2, 2, 4], [], \"competition\"), [1, 2, 2, 4])\n%!assert (ranks ([1, 2, 2, 4], [], \"modified\"), [1, 3, 3, 4])\n%!assert (ranks ([1, 2, 2, 4], [], \"ordinal\"), [1, 2, 3, 4])\n%!assert (ranks ([1, 2, 2, 4], [], \"dense\"), [1, 2, 2, 3])\n\n## Test input validation\n%!error <Invalid call> ranks ()\n%!error <X must be a numeric or logical> ranks ({1, 2})\n%!error <X must be a numeric or logical> ranks (['A'; 'B'])\n%!error <DIM must be an integer> ranks (1, 1.5)\n%!error <DIM must be .* a valid dimension> ranks (1, 0)\n%!error <unknown RTYPE 'foobar'> ranks (ones (2), 1, \"foobar\")\n"
  },
  {
    "path": "scripts/statistics/rms.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} rms (@var{x})\n## @deftypefnx {} {@var{y} =} rms (@var{x}, @var{dim})\n## @deftypefnx {} {@var{y} =} rms (@var{x}, @var{vecdim})\n## @deftypefnx {} {@var{y} =} rms (@var{x}, \"all\")\n## @deftypefnx {} {@var{y} =} rms (@dots{}, @var{nanflag})\n## Compute the root mean square of the input data @var{x}.\n##\n## The root mean square is defined as\n## @tex\n## $$\n## {\\rm rms} (x) = {\\sqrt{{1 \\over N} \\sum_{i=1}^N {|x_i|}^2}}\n## $$\n## where $N$ is the number of elements of @var{x}.\n##\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## rms (@var{x}) = sqrt (1/N SUM_i @var{x}(i)^2)\n## @end group\n## @end example\n##\n## @noindent\n## where @math{N} is the length of the @var{x} vector.\n##\n## @end ifnottex\n## If @var{x} is a vector, then @code{rms (@var{x})} returns the root mean\n## square of the elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{rms (@var{x})} returns a row vector\n## with each element containing the root mean square of the corresponding\n## column in @var{x}.\n##\n## If @var{x} is an array, then @code{rms (@var{x})} computes the root mean\n## square along the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be numeric.  The size of @var{y} is equal to the\n## size of @var{x} except for the operating dimension, which becomes 1.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{@var{x}}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{rms} to operate\n## on all elements of @var{x}, and is equivalent to @code{rms (@var{x}(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\n## NaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\n## will still contain NaN values if @var{x} consists of all NaN values in the\n## operating dimension.\n##\n## @seealso{meansq, var, std, moment}\n## @end deftypefn\n\nfunction y = rms (x, varargin)\n\n  if (nargin < 1 || nargin > 3)\n    print_usage ();\n  endif\n\n  ## Piggyback on existing code \n  y = sqrt (meansq (x, varargin{:}));\n\nendfunction\n\n\n%!assert (rms (1:5), sqrt (11))\n%!assert (rms (single (1:5)), single (sqrt (11)))\n%!assert (rms (magic (4)), sqrt ([94.5, 92.5, 92.5, 94.5]))\n%!assert (rms (magic (4), 2), sqrt ([109.5; 77.5; 77.5; 109.5]))\n%!assert (rms ([1 2], 3), sqrt ([1 4]))\n\n## Test optional arguments DIM, 'all', 'omitnan'.\n%!test\n%! x = [-9:9];\n%! y = [x;x+6;x-6];\n%! assert (rms (x), sqrt (30));\n%! assert (rms (y, 2), sqrt ([30; 66; 66]));\n%! assert (rms (y, 'all'), sqrt (54));\n%! y = y';\n%! y(4,2) = NaN;\n%! assert (rms (y, 'omitnan'), sqrt ([30, 1254/18, 66]));\n%! assert (rms (y, 'all'), NaN);\n%! assert (rms (y, 'all', 'includenan'), NaN);\n%! assert (rms (y, 'all', 'omitnan'), sqrt (3078/56));\n%! exp = sqrt ([30, NaN, 66]);\n%! assert (rms (y), exp);\n%! assert (rms (y, 'includenan'), exp);\n%! exp = sqrt ([30, 1254/18, 66]);\n%! assert (rms (y, 'omitnan'), exp);\n%! assert (rms (y', 2, 'omitnan'), exp');\n\n## Test dimension indexing with vecdim in N-dimensional arrays\n%!test\n%! x = repmat ([1:20;6:25], [5 2 6 3]);\n%! assert (size (rms (x, [3 2])), [10 1 1 3]);\n%! assert (size (rms (x, [1 2])), [1 1 6 3]);\n%! assert (size (rms (x, [1 2 4])), [1 1 6]);\n%! assert (size (rms (x, [1 4 3])), [1 40]);\n%! assert (size (rms (x, [1 2 3 4])), [1 1]);\n\n## Test exceeding dimensions\n%!assert (rms (2*ones (2,2), 3), 2*ones (2,2))\n%!assert (rms (2*ones (2,2,2), 99), 2*ones (2,2,2))\n%!assert (rms (magic (4), 3), (magic (4)))\n%!assert (rms (magic (4), [1 3]), sqrt ([94.5, 92.5, 92.5, 94.5]))\n%!assert (rms (magic (4), [1 99]), sqrt ([94.5, 92.5, 92.5, 94.5]))\n\n## Test results with vecdim in N-dimensional arrays and \"omitnan\"\n%!test\n%! x = repmat ([1:5;11:15], [5 2 6 3]);\n%! m = repmat ([11; 171], [5 1 1 3]);\n%! assert (rms (x, [3 2]), sqrt (m));\n%! x(2,6,6,3) = NaN;\n%! m(2,1,1,3) = 10139/59;\n%! assert (rms (x, [3 2], 'omitnan'), sqrt (m));\n\n## Test input validation\n%!error <Invalid call> rms ()\n%!error <Invalid call> rms (1,2,3,4)\n%!error <X must be a numeric array> rms (['A'; 'B'])\n%!error <X must be a numeric array> rms ([true, false])\n%!error <X must be a numeric array> rms ({1, 2})\n"
  },
  {
    "path": "scripts/statistics/rmse.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{E} =} rmse (@var{F}, @var{A})\n## @deftypefnx {} {@var{E} =} rmse (@var{F}, @var{A}, @var{dim})\n## @deftypefnx {} {@var{E} =} rmse (@var{F}, @var{A}, @var{vecdim})\n## @deftypefnx {} {@var{E} =} rmse (@var{F}, @var{A}, \"all\")\n## @deftypefnx {} {@var{E} =} rmse (@dots{}, @var{nanflag})\n## @deftypefnx {} {@var{E} =} rmse (@dots{}, @qcode{'Weights'}, @var{W})\n## Compute the root mean squared error between arrays.\n##\n## The root mean squared error is defined as\n## @tex\n## $$ {\\rm rmse}(F, A) = {E} = \\sqrt{{1\\over N} \\sum_{i=1}^N {\\left| {A_i - F_i} \\right|}^2} $$\n## where $N$ is the number of elements in @var{F} and @var{A} after\n## broadcasting is applied to the subtraction operation.\n## @end tex\n## @ifnottex\n##\n## @example\n## rmse (@var{F}, @var{A}) = sqrt (SUM_i ((@var{A}(i) - @var{F}(i)) ^ 2) / N)\n## @end example\n##\n## @noindent\n## where @math{N} is the number of elements in @var{F} and @var{A} after\n## broadcasting is applied to the subtraction operation.\n##\n## @end ifnottex\n##\n## The weighted root mean squared error is defined as\n## @tex\n## $$ {\\rm rmse}(F, A) = {E_W} = \\sqrt{\\sum_{i=1}^N W_i{\\left| {A_i - F_i} \\right|}^2 \\over \\sum_{i=1}^N W_i} $$\n## where $N$ is the number of elements in @var{F} and @var{A} after\n## broadcasting is applied to the subtraction operation.\n## @end tex\n## @ifnottex\n##\n## @example\n## weighted_rmse (@var{F}, @var{A}) = sqrt (SUM_i (@var{W}(i) * ((@var{A}(i) - @var{F}(i)) ^ 2)) / SUM_i (@var{W}(i)))\n## @end example\n##\n## @noindent\n## where @math{N} is the number of elements in @var{F} and @var{A} after\n## broadcasting is applied to the subtraction operation.\n##\n## @end ifnottex\n##\n## @var{F} and @var{A} must either be the same size or have compatible sizes.\n##\n## If @var{F} and @var{A} are vectors of the same size, then\n## @code{rmse (@var{F}, @var{A})} returns a scalar with the RMSE between the\n## elements of @var{F} and @var{A}.\n##\n## If @code{@var{A} - @var{F}} is a matrix, then @code{rmse (@var{F}, @var{A})}\n## returns a row vector with each element containing the RMSE between the\n## corresponding columns of @code{@var{A} - @var{F}}.\n##\n## If @code{@var{A} - @var{F}} is an array, then @code{rmse (@var{F}, @var{A})}\n## computes the RMSE along the first non-singleton dimension of the difference\n## between the input arrays @var{F} and @var{A}.  The size of @var{E} along the\n## operating dimension is 1, while all other dimensions are the same as in\n## @code{@var{A} - @var{F}}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension, including any\n## dimension exceeding @code{ndims (@var{A} - @var{F})}, will return\n## @code{abs ((@var{A} - @var{F}) ./ @var{A})}.\n##\n## Specifying the dimensions as @var{vecdim}, a vector of non-repeating\n## dimensions, will return the rmse over the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions in\n## @code{@var{A} - @var{F}}, then it is equivalent to the option @qcode{\"all\"}.\n## Any dimension in @var{vecdim} greater than @code{ndims (@var{A} - @var{F})}\n## is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{rmse} to operate\n## on all elements of @code{@var{A} - @var{F}}, and is equivalent to\n## @code{rmse ((@var{A} - @var{F})(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"includenan\"} which keeps NaN values in the calculation.  To exclude\n## NaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.  The output\n## will still contain NaN values if @code{@var{A} - @var{F}} consists of all\n## NaN values in the operating dimension.\n##\n## The optional paired argument @code{@dots{}, \"Weights\", @var{W}} specifies a\n## weighting scheme @var{W}, which is applied on the difference of the input\n## arrays @var{F} and @var{A}, so that @code{rmse} computes the weighted RMSE.\n## When operating along a single dimension, @var{W} must be a vector of the\n## same length as the operating dimension or it must have the same size as\n## @var{x}.  When operating over an array slice defined by @var{vecdim},\n## @var{W} must have the same size as the operating array slice, i.e.,\n## @code{size (@var{A} - @var{F})(@var{vecdim})}, or the same size as\n## @code{@var{A} - @var{F}}.\n##\n## @seealso{mape, meansq, rms}\n## @end deftypefn\n\nfunction E = rmse (F, A, varargin)\n\n  if (nargin < 2 || nargin > 7)\n    print_usage ();\n  endif\n\n  if (! any (isa (F, {'double', 'single'})))\n    error (\"rmse: F must be a floating point numeric array\");\n  endif\n\n  if (! any (isa (A, {'double', 'single'})))\n    error (\"rmse: A must be a floating point numeric array\");\n  endif\n\n  ## Determine output class\n  if (isa (F, 'single') || isa (A, 'single'))\n    outtype = \"single\";\n    F = double (F);\n    A = double (A);\n  else\n    outtype = \"double\";\n  endif\n\n  ## Check F and A for compatible sizes\n  try\n    AF = A - F;\n  catch\n    error (\"rmse: F and A must have compatible sizes\");\n  end_try_catch\n\n  ## Initialize flags\n  all_flag = false;\n  omitnan  = false;\n  weighted = false;\n\n  ## Process paired argument for Weights\n  w_idx = find (cellfun (@(x) strcmpi (x, \"weights\"), varargin));\n  if (! isempty (w_idx))\n    if (numel (varargin) > w_idx)\n      W = varargin{w_idx+1};\n      if (! (isnumeric (W) && any (isa (W, {'double', 'single'}))))\n        error (\"rmse: WEIGHTS must be single or double\");\n      endif\n      if (any (W(:) < 0))\n        error (\"rmse: WEIGHTS must be nonnegative\");\n      endif\n    else\n      error (\"rmse: paired input argument for 'Weights' is missing\");\n    endif\n    weighted = true;\n    varargin([w_idx, w_idx+1]) = [];\n  endif\n\n  nvarg = numel (varargin);\n  varg_chars = cellfun (\"ischar\", varargin);\n  sz_AF = size (AF);\n  nd_AF = ndims (AF);\n\n  if (nvarg > 1 && ! varg_chars(2:end))\n    ## Only first varargin can be numeric\n    print_usage ();\n  endif\n\n  ## Process any other char arguments.\n  if (any (varg_chars))\n    for argin = varargin(varg_chars)\n      switch (lower (argin{:}))\n        case \"all\"\n          all_flag = true;\n\n        case \"omitnan\"\n          omitnan = true;\n\n        case \"includenan\"\n          omitnan = false;\n\n        otherwise\n          print_usage ();\n\n      endswitch\n    endfor\n\n    varargin(varg_chars) = [];\n    nvarg = numel (varargin);\n  endif\n\n  if (nvarg == 1 && ! isnumeric (varargin{1}))\n    ## After trimming char inputs only one arg can be left, must be numeric.\n    print_usage ();\n  endif\n\n  ## Process special cases of input/output sizes.\n  if (nvarg == 0)\n    ## Single numeric input argument, no dimensions given.\n    if (all_flag)\n      AF = AF(:);\n      n = numel (AF);\n\n      ## Process weights\n      if (weighted)\n        if (isvector (W))\n          if (numel (W) != n)\n            error (strcat (\"rmse: WEIGHTS vector must have the same\", ...\n                           \" length as the operating dimension\"));\n          endif\n        elseif (! isequal (size (W), sz_AF))\n          error (strcat (\"rmse: WEIGHTS array must have the same size as\", ...\n                         \" the difference of the input arrays F and A\"));\n        endif\n        W = W(:);\n        ## Apply sqrt(weights) to differences to prepare for vecnorm\n        AF = AF .* sqrt (W);\n        n = sum (W);\n      endif\n\n      ## Process omitnan\n      if (omitnan)\n        nanAF = isnan (AF);\n        AF(nanAF) = 0;  # zero out NaNs so vecnorm ignores them in sum\n        if (weighted)\n          W(nanAF) = 0;\n          n = sum (W);\n        else\n          n = numel (AF);\n        endif\n      endif\n\n      ## Use vecnorm (2-norm) for robust, fast calculation.\n      ## rmse = norm (AF) / sqrt (N)\n      E = vecnorm (AF, 2, 1) ./ sqrt (n);\n\n    else\n      ## Handle 0x0 empty input, no dimensions given\n      if (nd_AF == 2 && isempty (AF) && sz_AF == [0,0])\n        if (isa (AF, \"single\"))\n          E = NaN (\"single\");\n        else\n          E = NaN;\n        endif\n        return;\n      endif\n\n      ## Find the first non-singleton dimension.\n      (dim = find (sz_AF != 1, 1)) || (dim = 1);\n      n = sz_AF(dim);\n\n      ## Process weights\n      if (weighted)\n        if (isequal (size (W), sz_AF))\n          AF = AF .* sqrt (W);\n        elseif (isvector (W))\n          if (numel (W) != n)\n            error (strcat (\"rmse: WEIGHTS vector must have the same\", ...\n                           \" length as the operating dimension\"));\n          endif\n          sz_W = ones (1, nd_AF);\n          sz_W(dim) = n;\n          W = reshape (W, sz_W);\n          if (! isvector (AF))\n            sz_W = sz_AF;\n            sz_W(dim) = 1;\n            W = repmat (W, sz_W);\n          endif\n          AF = AF .* sqrt (W);\n        else\n          error (strcat (\"rmse: WEIGHTS array must have the same size as\", ...\n                         \" the difference of the input arrays F and A\"));\n        endif\n        n = sum (W, dim);\n      endif\n\n      ## Process omitnan\n      if (omitnan)\n        nanAF = isnan (AF);\n        AF(nanAF) = 0;  # zero out NaNs so vecnorm ignores them in sum\n        if (weighted)\n          W(nanAF) = 0;\n          n = sum (W, dim);\n        else\n          n = sum (! nanAF, dim);\n        endif\n      endif\n\n      E = vecnorm (AF, 2, dim) ./ sqrt (n);\n\n    endif\n\n  else\n    ## Two numeric input arguments, dimensions given.  Note scalar is vector!\n    vecdim = varargin{1};\n    if (isempty (vecdim) || ! (isvector (vecdim) && isindex (vecdim)))\n      error (\"rmse: DIM must be a positive integer scalar or vector\");\n    endif\n\n    if (isscalar (vecdim))\n      dim = vecdim;  # alias for code readability\n\n      if (dim > nd_AF)\n\n        ## Process weights\n        if (weighted)\n          if (! isequal (size (W), sz_AF))\n             error (strcat (\"rmse: WEIGHTS array must have the same size\", ...\n                            \" as 'A - F', when 'DIM > ndims (A - F)'\"));\n          endif\n        endif\n\n        ## If dim > ndims, rmse is just abs(AF) (conceptually norm of scalar)\n        E = abs (AF);\n\n      else\n        n = sz_AF(dim);\n\n        ## Process weights\n        if (weighted)\n          if (isequal (size (W), sz_AF))\n            AF = AF .* sqrt (W);\n          elseif (isvector (W))\n            if (numel (W) != n)\n              error (strcat (\"rmse: WEIGHTS vector must have the same\", ...\n                             \" length as the operating dimension\"));\n            endif\n            sz_W = ones (1, nd_AF);\n            sz_W(dim) = n;\n            W = reshape (W, sz_W);\n            if (! isvector (AF))\n              sz_W = sz_AF;\n              sz_W(dim) = 1;\n              W = repmat (W, sz_W);\n            endif\n            AF = AF .* sqrt (W);\n          else\n          error (strcat (\"rmse: WEIGHTS array must have the same size as\", ...\n                         \" the difference of the input arrays F and A\"));\n          endif\n          n = sum (W, dim);\n        endif\n\n        ## Process omitnan\n        if (omitnan)\n          nanAF = isnan (AF);\n          AF(nanAF) = 0;\n          if (weighted)\n            W(nanAF) = 0;\n            n = sum (W, dim);\n          else\n            n = sum (! nanAF, dim);\n          endif\n        endif\n\n        E = vecnorm (AF, 2, dim) ./ sqrt (n);\n\n      endif\n\n    else\n      vecdim = sort (vecdim);\n      if (! all (diff (vecdim)))\n        error (\"rmse: VECDIM must contain non-repeating positive integers\");\n      endif\n      ## Ignore dimensions in VECDIM larger than actual array.\n      vecdim(vecdim > nd_AF) = [];\n\n      if (isempty (vecdim))\n\n        ## Process weights\n        if (weighted)\n          if (! isequal (size (W), sz_AF))\n             error (strcat (\"rmse: WEIGHTS array must have the same size\", ...\n                            \" as 'A - F', when 'all (VECDIM > ndims (A - F))'\"));\n          endif\n        endif\n\n        E = abs (AF);\n\n      else\n\n        ## Calculate permutation vector\n        remdims = 1:nd_AF;       # All dimensions\n        remdims(vecdim) = [];  # Delete dimensions specified by vecdim\n        nremd = numel (remdims);\n\n        ## If all dimensions are given, it is equivalent to 'all' flag\n        if (nremd == 0)\n          AF = AF(:);\n          n = numel (AF);\n\n          ## Process weights\n          if (weighted)\n            if (isvector (W))\n              if (numel (W) != n)\n                error (strcat (\"rmse: WEIGHTS vector must have the same\", ...\n                               \" length as the operating dimension\"));\n              endif\n            elseif (! isequal (size (W), sz_AF))\n              error (strcat (\"rmse: WEIGHTS array must have the same size\", ...\n                             \" as the difference of the input arrays F and A\"));\n            endif\n            W = W(:);\n            AF = AF .* sqrt (W);\n            n = sum (W);\n          endif\n\n          ## Process omitnan\n          if (omitnan)\n            nanAF = isnan (AF);\n            AF(nanAF) = [];\n            if (weighted)\n              W(nanAF) = [];\n              n = sum (W);\n            else\n              n = numel (AF);\n            endif\n          endif\n\n          E = vecnorm (AF, 2, 1) ./ sqrt (n);\n\n        else\n          ## Weights must either match vecdim page size or the size of F - A\n          if (weighted)\n            page_szw = size (W);\n            if (isequal (size (W), sz_AF))\n              AF = AF .* sqrt (W);\n            elseif (isequal (page_szw, sz_AF(vecdim)))\n              ## Make W to be compatible with AF\n              tmp = ones (1, nd_AF);\n              tmp(vecdim) = page_szw;\n              W = reshape (W, tmp);\n              W = W .* ones (sz_AF);\n              AF = AF .* sqrt (W);\n            else\n              error (strcat (\"rmse: WEIGHTS array must have the same size\", ...\n                             \" as the operating page specified by VECDIM\", ...\n                             \" or the difference of the input arrays F and A\"));\n            endif\n          endif\n\n          ## Permute to push vecdims to back\n          perm = [remdims, vecdim];\n          AF = permute (AF, perm);\n          if (weighted)\n            W = permute (W, perm);\n          endif\n\n          ## Reshape to squash all vecdims in final dimension\n          sznew = [sz_AF(remdims), prod(sz_AF(vecdim))];\n          AF = reshape (AF, sznew);\n          if (weighted)\n            W = reshape (W, sznew);\n          endif\n\n          ## Calculate rmse on final dimension\n          dim = nremd + 1;\n\n          ## Process omitnan\n          if (omitnan)\n            nanAF = isnan (AF);\n            AF(nanAF) = 0;\n            if (weighted)\n              W(nanAF) = 0;\n              n = sum (W, dim);\n            else\n              n = sum (! nanAF, dim);\n            endif\n          else\n            if (weighted)\n              n = sum (W, dim);\n            else\n              n = sznew(dim);\n            endif\n          endif\n\n          E = vecnorm (AF, 2, dim) ./ sqrt (n);\n\n          ## Inverse permute back to correct dimensions\n          E = ipermute (E, perm);\n\n        endif\n      endif\n    endif\n  endif\n\n  ## Convert output if necessary\n  if (strcmp (outtype, 'single'))\n    E = single (E);\n  endif\n\nendfunction\n\n## Test inputs with NaN and zeros\n%!test\n%! F = [2, 11, 6];\n%! A = [3, 10, 8];\n%! assert (rmse (F, A), sqrt (2), eps);\n%! assert (rmse (F, A, 1), [1, 1, 2], eps);\n%! assert (rmse (F, A, 2), sqrt (2), eps);\n%! assert (rmse (F, A, 3), [1, 1, 2], eps);\n%! assert (rmse (F, A, 'all'), sqrt (2), eps);\n%!test\n%! F = [3; 7; 4; NaN];\n%! A = [4; 0; 6; 4];\n%! assert (rmse (F, A), NaN);\n%! assert (rmse (F, A, 'omitnan'), 4.2426, 1e-4);\n%! assert (rmse (F, A, 1, 'omitnan'), 4.2426, 1e-4);\n%! assert (rmse (F, A, 2, 'omitnan'), [1; 7; 2; NaN]);\n%!test\n%! F = [17, 21; 1, 5; 13, 17];\n%! A = [18, 19; 5, 4; 15, 13];\n%! assert (rmse (F, A), [2.6458, 2.6458], 1e-4);\n%! assert (rmse (F, A, 1), [2.6458, 2.6458], 1e-4);\n%! assert (rmse (F, A, 2), [1.5811; 2.9155; 3.1623], 1e-4);\n%! assert (rmse (F, A, 'all'), 2.6458, 1e-4);\n%! assert (rmse (F, A, [1, 2]), 2.6458, 1e-4);\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, 2; 7, -4];\n%! A = [6, 5; NaN, 3];\n%! E = rmse (F, A, [1, 2]);\n%! assert (E(:,:,1), NaN);\n%! assert (E(:,:,2), NaN);\n%! E = rmse (F, A, [1, 2], 'omitnan');\n%! assert (E(:,:,1), 1.8257, 1e-4);\n%! assert (E(:,:,2), 4.5461, 1e-4);\n%! assert (rmse (F, A, [1, 3]), [NaN, 3.8406], 1e-4);\n%! assert (rmse (F, A, [1, 3], 'omitnan'), [2.5495, 3.8406], 1e-4);\n%! assert (rmse (F, A, [2, 3]), [2.3452; NaN], 1e-4);\n%! assert (rmse (F, A, [2, 3], 'omitnan'), [2.3452; 5], 1e-4);\n\n## Test Weights\n%!test\n%! F = [2, 11, 6];\n%! A = [3, 10, 8];\n%! W = [1, 2, 1];\n%! assert (rmse (F, A, 'Weights', W), 1.3229, 1e-4);\n%! assert (rmse (F, A, 1, 'Weights', W), [1, 1, 2]);\n%! assert (rmse (F, A, 2, 'Weights', W), 1.3229, 1e-4);\n%! assert (rmse (F, A, 3, 'Weights', W), [1, 1, 2]);\n%!test\n%! F = [3; 7; 4; NaN];\n%! A = [4; 0; 6; 4];\n%! W = [1, 2, 1, 2];\n%! assert (rmse (F, A, 'Weights', W), NaN);\n%! assert (rmse (F, A, 'omitnan', 'Weights', W), 5.0744, 1e-4);\n%! assert (rmse (F, A, 1, 'omitnan', 'Weights', W), 5.0744, 1e-4);\n%!test\n%! F = [3; 7; 4; NaN];\n%! A = [4; 0; 6; 4];\n%! W = [1; 2; 1; 2];\n%! assert (rmse (F, A, 2, 'Weights', W), [1; 7; 2; NaN], 1e-4);\n%! assert (rmse (F, A, 2, 'omitnan', 'Weights', W), [1; 7; 2; NaN], 1e-4);\n%! assert (rmse (F, A, 3, 'Weights', W), [1; 7; 2; NaN], 1e-4);\n%! assert (rmse (F, A, 3, 'omitnan', 'Weights', W), [1; 7; 2; NaN], 1e-4);\n%!test\n%! F = [3, 4; 7, 5; 4, 3; NaN, 8];\n%! A = [4; 0; 6; 4];\n%! W = [3; 1; 2; 2];\n%! E = rmse (F, A, 1, 'omitnan', 'Weights', W);\n%! assert (E, [3.1623, 3.0619], 1e-4);\n%!test\n%! F = [3, 4; 7, 5; 4, 3; NaN, 8];\n%! A = [4; 0; 6; 4];\n%! W = [3, 0.4; 1, 0.2; 2, 0.2; 2, 0.2];\n%! assert (rmse (F, A, 1, 'Weights', W), [NaN, 3.1623], 1e-4);\n%! assert (rmse (F, A, 1, 'omitnan', 'Weights', W), [3.1623, 3.1623], 1e-4);\n%! assert (rmse (F, A, 2, 'Weights', W), [0.9393; 6.7082; 2.1106; NaN], 1e-4);\n%! E = rmse (F, A, 2, 'omitnan', 'Weights', W);\n%! assert (E, [0.9393; 6.7082; 2.1106; 4], 1e-4);\n\n## Test Weights with VECDIM\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, NaN; 7, -4];\n%! A = [6, 5; 2, 3];\n%! W = [1, 1; 1, 1];\n%! Ew = rmse (F, A, [1, 2], 'omitnan', 'Weights', W);\n%! E = rmse (F, A, [1, 2], 'omitnan');\n%! assert (Ew, E);\n%! Ew = rmse (F, A, [1, 3], 'omitnan','Weights', W);\n%! E = rmse (F, A, [1, 3], 'omitnan');\n%! assert (Ew, E);\n%! Ew = rmse (F, A, [2, 3], 'omitnan','Weights', W);\n%! E = rmse (F, A, [2, 3], 'omitnan');\n%! assert (Ew, E);\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, 2; 7, -4];\n%! A = [6, 5; 0, 3];\n%! W = [1, 2; 1, 1];\n%! F1 = reshape (F, 1, 4, 2);\n%! A1 = reshape (A, 1, 4);\n%! W1 = reshape (W, 1, 4);\n%! E1w = rmse (F1, A1, 2, 'Weights', W1);\n%! assert (E1w(:,:,1), 1.4832, 1e-4);\n%! assert (E1w(:,:,2), 4.8990, 1e-4);\n%! E1 = rmse (F1, A1, 2);\n%! assert (E1(:,:,1), 1.6583, 1e-4);\n%! assert (E1(:,:,2), 5.2678, 1e-4);\n%! assert (rmse (F, A, [1, 2], 'Weights', W), E1w);\n%! assert (rmse (F, A, [1, 2]), E1);\n%!test\n%! F(:,:,1) = [3, 5; -1, 2];\n%! F(:,:,2) = [4, 2; 7, -4];\n%! A = [6, 5; 0, 3];\n%! W = [0.5, 2; 1, 3];\n%! F1 = reshape (F, 2, 4, 1);\n%! A1 = reshape (repmat (A, 1, 1, 2), 2, 4, 1);\n%! W1 = [0.5, 1, 2, 3; 0.5, 1, 2, 3];\n%! E1w = rmse (F1, A1, 2, 'Weights', W1);\n%! assert (E1w, [2.4651; 6.1582], 1e-4);\n%! E1 = rmse (F1, A1, 2);\n%! assert (E1, [2.3452; 5], 1e-4);\n%! assert (rmse (F, A, [2, 3], 'Weights', W), E1w);\n%! assert (rmse (F, A, [2, 3]), E1);\n\n## Test with very large values\n%!test <67918>\n%! A = zeros (10, 1);\n%! A(1) = realmax/2;\n%! A(2) = 2*(realmax/3);\n%! F = ones (10, 1);\n%! assert (rmse (A, F), 4.7373373668443035e307, 2*eps (4.7373373668443035e307));\n\n## Test input validation\n%!error <Invalid call> rmse ()\n%!error <Invalid call> rmse (1)\n%!error <Invalid call> rmse (1, 2, 3, 4, 5, 6, 7, 8)\n%!error <F must be a floating point numeric array> rmse ({1:5}, [1:5])\n%!error <F must be a floating point numeric array> rmse (int32 ([1:5]), [1:5])\n%!error <A must be a floating point numeric array> rmse ([1:5], {1:5})\n%!error <A must be a floating point numeric array> rmse ([1:5], int32 ([1:5]))\n%!error <WEIGHTS must be single or double> rmse ([1:5], [1:5], 'Weights', 'double')\n%!error <WEIGHTS must be single or double> rmse ([1:5], [1:5], 'Weights', uint8 (1))\n%!error <WEIGHTS must be nonnegative> rmse ([1:5], [1:5], 'Weights', -1)\n%!error <paired input argument for 'Weights' is missing> rmse ([1:5], [1:5], 'Weights')\n%!error <Invalid call> rmse ([1:5], [1:5], 2, 3)\n%!error <Invalid call> rmse ([1:5], [1:5], \"all\", 3)\n%!error <Invalid call> rmse ([1:5], [1:5], 'foobar')\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! rmse ([1:5], [1:5], \"all\", 'Weights', [1, 2, 3])\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! rmse ([1:5], 1, \"all\", 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! rmse (ones (5, 3), ones (5, 3), \"all\", 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! rmse (ones (5, 3), ones (1, 3), \"all\", 'Weights', ones (3, 5))\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! rmse ([1:5], [1:5], 'Weights', [1, 2, 3])\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! rmse ([1:5], 1, 'Weights', [1, 2, 3])\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! rmse (ones (5, 3), ones (5, 3), 'Weights', [1, 2, 3])\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! rmse (ones (5, 3), ones (5, 1), 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! rmse (ones (5, 3), ones (5, 3), 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! rmse (ones (5, 3), ones (1, 3), 'Weights', ones (3, 5))\n%!error <DIM must be a positive integer> rmse ([1:5], [1:5], ones (2,2))\n%!error <DIM must be a positive integer> rmse ([1:5], [1:5], 1.5)\n%!error <DIM must be a positive integer> rmse ([1:5], [1:5], 0)\n%!error <DIM must be a positive integer> rmse ([1:5], [1:5], [])\n%!error <DIM must be a positive integer> rmse ([1:5], [1:5], -1)\n%!error <DIM must be a positive integer> rmse ([1:5], [1:5], -1.5)\n%!error <DIM must be a positive integer> rmse ([1:5], [1:5], NaN)\n%!error <DIM must be a positive integer> rmse ([1:5], [1:5], Inf)\n%!error <DIM must be a positive integer> rmse (repmat ([1:5;5:9], [5 2]), repmat ([1:5;5:9], [5 2]), -1)\n%!error <DIM must be a positive integer> rmse (repmat ([1:5;5:9], [5 2]), repmat ([1:5;5:9], [5 2]), [1 -1])\n%!error <DIM must be a positive integer> rmse ([1:5], [1:5], ones (1,0))\n%!error <WEIGHTS array must have the same size as 'A - F', when 'DIM> ...\n%! rmse (ones (5, 1), ones (5, 1), 3, 'Weights', ones (1, 5))\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! rmse ([1:5], [1:5], 2, 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! rmse (ones (5, 3), ones (5, 3), 2, 'Weights', ones (3, 5))\n%!error <VECDIM must contain non-repeating> rmse ([1:5], [1:5], [2 2])\n%!error <WEIGHTS array must have the same size as 'A - F', when 'all> ...\n%! rmse (ones (5, 1), ones (5, 1), [3, 4], 'Weights', ones (1, 5))\n%!error <WEIGHTS vector must have the same length as the operating dimension> ...\n%! rmse ([1:5], [1:5], [1, 2], 'Weights', [1, 2, 3])\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! rmse (ones (5, 3), ones (5, 3), [1, 2], 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the difference> ...\n%! rmse (ones (5, 3), ones (1, 3), [1, 2], 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the operating page> ...\n%! rmse (ones (5, 3, 2), ones (5, 3, 2), [1, 2], 'Weights', ones (3, 5))\n%!error <WEIGHTS array must have the same size as the operating page> ...\n%! rmse (ones (5, 3, 2), ones (5, 1, 2), [1, 2], 'Weights', ones (3, 5))\n"
  },
  {
    "path": "scripts/statistics/run_count.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{cnt} =} run_count (@var{x}, @var{n})\n## @deftypefnx {} {@var{cnt} =} run_count (@var{x}, @var{n}, @var{dim})\n## Count the upward runs along the first non-singleton dimension of @var{x}\n## of length 1, 2, @dots{}, @var{n}-1 and greater than or equal to @var{n}.\n##\n## If the optional argument @var{dim} is given then operate along this\n## dimension.\n## @seealso{runlength}\n## @end deftypefn\n\nfunction cnt = run_count (x, n, dim)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    error (\"run_count: X must be a numeric or logical array\");\n  endif\n\n  if (! (isscalar (n) && n == fix (n) && n > 0))\n    error (\"run_count: N must be a positive integer\");\n  endif\n\n  nd = ndims (x);\n  sz = size (x);\n  if (nargin != 3)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz > 1, 1)) || (dim = 1);\n  else\n    if (!(isscalar (dim) && dim == fix (dim))\n        || !(1 <= dim && dim <= nd))\n      error (\"run_count: DIM must be an integer and a valid dimension\");\n    endif\n  endif\n\n  ## Algorithm works on rows.  Permute array if necessary, ipermute back at end\n  if (dim != 1)\n    perm = [1 : nd];\n    perm(1) = dim;\n    perm(dim) = 1;\n    x = permute (x, perm);\n  endif\n\n  sz = size (x);\n  idx = cell ();\n  for i = 1 : nd\n    idx{i} = 1 : sz(i);\n  endfor\n  c = sz(1);\n  tmp = zeros ([c + 1, sz(2 : end)]);\n  infvec = Inf ([1, sz(2 : end)]);\n\n  ind = find (diff ([infvec; x; -infvec]) < 0);\n  tmp(ind(2:end) - 1) = diff (ind);\n  tmp = tmp(idx{:});\n\n  sz(1) = n;\n  cnt = zeros (sz);\n  for k = 1 : (n-1)\n    idx{1} = k;\n    cnt(idx{:}) = sum (tmp == k);\n  endfor\n  idx{1} = n;\n  cnt(idx{:}) = sum (tmp >= n);\n\n  if (dim != 1)\n    cnt = ipermute (cnt, perm);\n  endif\n\nendfunction\n\n\n%!assert (run_count (magic (3), 4), [1,0,1;1,0,1;0,1,0;0,0,0])\n%!assert (run_count (magic (3), 4, 2), [1,0,1;1,0,1;0,1,0;0,0,0]')\n%!assert (run_count (5:-1:1, 5), [5, 0, 0, 0, 0])\n%!assert (run_count (ones (3), 4), [0,0,0;0,0,0;1,1,1;0,0,0])\n\n## Test input validation\n%!error <Invalid call> run_count ()\n%!error <Invalid call> run_count (1)\n%!error <must be a numeric or logical> run_count ({1, 2}, 3)\n%!error <must be a numeric or logical> run_count (['A'; 'A'; 'B'], 3)\n%!error run_count (1:5, ones (2,2))\n%!error run_count (1:5, 1.5)\n%!error run_count (1:5, -2)\n%!error run_count (1:5, 3, ones (2,2))\n%!error run_count (1:5, 3, 1.5)\n%!error run_count (1:5, 3, 0)\n"
  },
  {
    "path": "scripts/statistics/runlength.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {count =} runlength (@var{x})\n## @deftypefnx {} {[count, value] =} runlength (@var{x})\n## Find the lengths of all sequences of common values.\n##\n## @var{count} is a vector with the lengths of each repeated value.\n##\n## The optional output @var{value} contains the value that was repeated in\n## the sequence.\n##\n## @example\n## @group\n## runlength ([2, 2, 0, 4, 4, 4, 0, 1, 1, 1, 1])\n## @xresult{}   2   1   3   1   4\n## @end group\n## @end example\n## @seealso{run_count}\n## @end deftypefn\n\nfunction [count, value] = runlength (x)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)) || ! isvector (x))\n    error (\"runlength: X must be a numeric or logical vector\");\n  endif\n\n  if (iscolumn (x))\n    x = x.';\n  endif\n\n  idx = [find(x(1:end-1) != x(2:end)), length(x)];\n  count = diff ([0 idx]);\n  if (nargout == 2)\n    value = x(idx);\n  endif\n\nendfunction\n\n\n%!assert (runlength ([2 2 0 4 4 4 0 1 1 1 1]), [2 1 3 1 4])\n%!assert (runlength ([2 2 0 4 4 4 0 1 1 1 1]'), [2 1 3 1 4])\n%!test\n%! [c, v] = runlength ([2 2 0 4 4 4 0 1 1 1 1]);\n%! assert (c, [2 1 3 1 4]);\n%! assert (v, [2 0 4 0 1]);\n\n## Test input validation\n%!error <Invalid call> runlength ()\n%!error <must be a numeric or logical> runlength (['A'; 'B'])\n%!error <must be a .* vector> runlength (ones (2,2))\n"
  },
  {
    "path": "scripts/statistics/skewness.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{y} =} skewness (@var{x})\n## @deftypefnx {} {@var{y} =} skewness (@var{x}, @var{flag})\n## @deftypefnx {} {@var{y} =} skewness (@var{x}, @var{flag}, @var{dim})\n## @deftypefnx {} {@var{y} =} skewness (@var{x}, @var{flag}, @var{vecdim})\n## @deftypefnx {} {@var{y} =} skewness (@var{x}, @var{flag}, \"all\")\n## Compute the sample skewness of the input data @var{x}.\n##\n## The sample skewness is defined as\n## @tex\n## $$\n## {\\rm skewness} (@var{x}) = {{{1\\over N}\\,\n##          \\sum_{i=1}^N (x_i - \\bar{x})^3} \\over \\sigma^3},\n## $$\n## where $N$ is the length of @var{x}, $\\bar{x}$ its mean and $\\sigma$\n## its (uncorrected) standard deviation.\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##                mean ((@var{x} - mean (@var{x})).^3)\n## skewness (@var{X}) = ------------------------.\n##                       std (@var{x}).^3\n## @end group\n## @end example\n##\n## @end ifnottex\n##\n## @noindent\n## The optional argument @var{flag} controls which normalization is used.\n## If @var{flag} is equal to 1 (default value, used when @var{flag} is omitted\n## or empty), return the sample skewness as defined above.  If @var{flag} is\n## equal to 0, return the adjusted skewness coefficient instead:\n## @tex\n## $$\n## {\\rm skewness} (@var{x}) = {\\sqrt{N (N - 1)} \\over N - 2} \\times \\,\n##   {{{1 \\over N} \\sum_{i=1}^N (x_i - \\bar{x})^3} \\over \\sigma^3}\n## $$\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n##                   sqrt (N*(N-1))   mean ((@var{x} - mean (@var{x})).^3)\n## skewness (@var{X}, 0) = -------------- * ------------------------.\n##                       (N - 2)             std (@var{x}).^3\n## @end group\n## @end example\n##\n## @noindent\n## where @math{N} is the length of the @var{x} vector.\n##\n## @end ifnottex\n## The adjusted skewness coefficient is obtained by replacing the sample second\n## and third central moments by their bias-corrected versions.\n##\n## If @var{x} is a vector, then @code{skewness (@var{x})} computes the skewness\n## of the data in @var{x}.\n##\n## If @var{x} is a matrix, then @code{skewness (@var{x})} returns a row vector\n## with each element containing the skewness of the data of the corresponding\n## column in @var{x}.\n##\n## If @var{x} is an array, then @code{skewness (@var{x})} computes the skewness\n## of the data along the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be numeric and any NaN values are ignored.\n## The size of @var{y} is equal to the size of @var{x} except for the operating\n## dimension, which becomes 1.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{@var{x}}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{skewness} to\n## operate on all elements of @var{x}, and is equivalent to\n## @code{skewness (@var{x}(:))}.\n## @seealso{var, kurtosis, moment}\n## @end deftypefn\n\nfunction y = skewness (x, flag, dim)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x)))\n    error (\"skewness: X must be a numeric array\");\n  endif\n\n  if (nargin < 2 || isempty (flag))\n    flag = 1;  # default: do not use the \"bias corrected\" version\n  elseif (! isscalar (flag) || (flag != 0 && flag != 1))\n    error (\"skewness: FLAG must be 0 or 1\");\n  endif\n\n  if (nargin < 3)\n    (dim = find (size (x) != 1, 1)) || (dim = 1);\n  endif\n\n  n = sum (x == x, dim, \"omitnan\");\n\n  x = center (x, dim, \"omitnan\");\n  s = std (x, 1, dim, \"omitnan\");   # normalize with 1/N\n  y = sum (x .^ 3, dim, \"omitnan\");\n  y = y ./ (n .* s .^ 3);\n  idx = (s != 0);\n  y(! idx) = NaN;\n\n  ## Apply bias correction to the second and third central sample moment\n  if (flag == 0)\n    idx = n > 2;\n    nn = n(idx);\n    y(idx) = y(idx) .* sqrt (nn .* (nn - 1)) ./ (nn - 2);\n    y(! idx) = NaN;\n  endif\n\nendfunction\n\n\n%!assert (skewness ([-1, 0, 1]), 0)\n%!assert (skewness ([-2, 0, 1]) < 0)\n%!assert (skewness ([-1, 0, 2]) > 0)\n%!assert (skewness ([-3, 0, 1]) == -1 * skewness ([-1, 0, 3]))\n%!assert (skewness (ones (3, 5)), NaN (1, 5))\n%!assert (skewness (1, [], 3), NaN)\n\n%!test\n%! x = [0; 0; 0; 1];\n%! y = [x, 2*x];\n%! assert (skewness (y), 1.154700538379251 * [1 1], 5*eps);\n\n%!assert (skewness ([1:5 10; 1:5 10],  0, 2), 1.439590274527954 * [1; 1], eps)\n%!assert (skewness ([1:5 10; 1:5 10],  1, 2), 1.051328089232020 * [1; 1], 2*eps)\n%!assert (skewness ([1:5 10; 1:5 10], [], 2), 1.051328089232020 * [1; 1], 2*eps)\n\n## Test behavior on single input\n%!assert (skewness (single ([1:5 10])), single (1.0513283), eps (\"single\"))\n%!assert (skewness (single ([1 2]), 0), single (NaN))\n\n## Test dim\n%!test\n%! x(:,:,1) = [0.5377, 0.3188, 3.5784; 1.8339, -1.3077, 2.7694; ...\n%!             -2.2588, -0.4336, -1.3499; 0.8622, 0.3426, 3.0349];\n%! x(:,:,2) = [0.7254, -0.1241, 0.6715; -0.0631, 1.4897, -1.2075; ...\n%!             0.7147 1.4090 0.7172; -0.2050, 1.4172, 1.6302];\n%! y = skewness (x);\n%! assert (y(:,:,1), [-0.8084, -0.5578, -1.0772], 1e-4);\n%! assert (y(:,:,2), [-0.0403, -1.1472, -0.6632], 1e-4);\n%! y = skewness (x, 1, 2);\n%! assert (y(:,:,1), [0.6956; -0.5575; 0.0049; 0.6033], 1e-4);\n%! assert (y(:,:,2), [-0.6969; 0.1828; 0.7071; -0.6714], 1e-4);\n%! y = skewness (x, 1, 3);\n%! assert (y, zeros (4, 3), 8 * eps);\n\n## Test \"all\" and vecdim\n%!test\n%! x(:,:,1) = [0.5377, 0.3188, 3.5784; 1.8339, -1.3077, 2.7694; ...\n%!             -2.2588, -0.4336, -1.3499; 0.8622, 0.3426, 3.0349];\n%! x(:,:,2) = [0.7254, -0.1241, 0.6715; -0.0631, 1.4897, -1.2075; ...\n%!             0.7147 1.4090 0.7172; -0.2050, 1.4172, 1.6302];\n%! y = skewness (x, 1, \"all\");\n%! assert (y, 0.0916, 1e-4);\n%! y = skewness (x, 1, [1, 2]);\n%! assert (y(:,:,1), 0.1070, 1e-4);\n%! assert (y(:,:,2), -0.6263, 1e-4);\n%! y = skewness (x, 1, [1, 3]);\n%! assert (y, [-1.0755, -0.3108, -0.2209], 1e-4);\n\n## Verify no warnings\n%!test\n%! lastwarn (\"\");  # clear last warning\n%! skewness (1);\n%! assert (lastwarn (), \"\");\n\n## Test input validation\n%!error <Invalid call> skewness ()\n%!error <skewness: X must be a numeric array> skewness (['A'; 'B'])\n%!error <skewness: X must be a numeric array> skewness ([true; false])\n%!error <skewness: X must be a numeric array> skewness ({1, 2, 3})\n%!error <skewness: FLAG must be 0 or 1> skewness (1, 2)\n%!error <skewness: FLAG must be 0 or 1> skewness (1, [1 0])\n"
  },
  {
    "path": "scripts/statistics/spearman.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{rho} =} spearman (@var{x})\n## @deftypefnx {} {@var{rho} =} spearman (@var{x}, @var{y})\n## @cindex Spearman's Rho\n## Compute Spearman's rank correlation coefficient\n## @tex\n## $\\rho$.\n## @end tex\n## @ifnottex\n## @var{rho}.\n## @end ifnottex\n##\n## For two data vectors @var{x} and @var{y}, Spearman's\n## @tex\n## $\\rho$\n## @end tex\n## @ifnottex\n## @var{rho}\n## @end ifnottex\n## is the correlation coefficient of the ranks of @var{x} and @var{y}.\n##\n## If @var{x} and @var{y} are drawn from independent distributions,\n## @tex\n## $\\rho$\n## @end tex\n## @ifnottex\n## @var{rho}\n## @end ifnottex\n## has zero mean and variance\n## @tex\n## $1 / (N - 1)$,\n## @end tex\n## @ifnottex\n## @code{1 / (N - 1)},\n## @end ifnottex\n## where @math{N} is the length of the @var{x} and @var{y} vectors, and is\n## asymptotically normally distributed.\n##\n## @code{spearman (@var{x})} is equivalent to\n## @code{spearman (@var{x}, @var{x})}.\n## @seealso{ranks, kendall}\n## @end deftypefn\n\nfunction rho = spearman (x, y = [])\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (   ! (isnumeric (x) || islogical (x))\n      || ! (isnumeric (y) || islogical (y)))\n    error (\"spearman: X and Y must be numeric matrices or vectors\");\n  endif\n\n  if (ndims (x) != 2 || ndims (y) != 2)\n    error (\"spearman: X and Y must be 2-D matrices or vectors\");\n  endif\n\n  if (isrow (x))\n    x = x.';\n  endif\n\n  if (nargin == 1)\n    rho = corr (ranks (x));\n  else\n    if (isrow (y))\n      y = y.';\n    endif\n    if (rows (x) != rows (y))\n      error (\"spearman: X and Y must have the same number of observations\");\n    endif\n    rho = corr (ranks (x), ranks (y));\n  endif\n\n  ## Restore class cleared by ranks\n  if (isa (x, \"single\") || isa (y, \"single\"))\n    rho = single (rho);\n  endif\n\nendfunction\n\n\n%!test\n%! x = 1:10;\n%! y = exp (x);\n%! assert (spearman (x,y), 1, 5*eps);\n%! assert (spearman (x,-y), -1, 5*eps);\n\n%!assert (spearman ([1 2 3], [-1 1 -2]), -0.5, 5*eps)\n\n%!assert (spearman (1), NaN)\n%!assert (spearman (single (1)), single (NaN))\n\n## Test input validation\n%!error <Invalid call> spearman ()\n%!error spearman (['A'; 'B'])\n%!error spearman (ones (1,2), {1, 2})\n%!error spearman (ones (2,2,2))\n%!error spearman (ones (2,2), ones (2,2,2))\n%!error spearman (ones (2,2), ones (3,2))\n"
  },
  {
    "path": "scripts/statistics/statistics.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{stats} =} statistics (@var{x})\n## @deftypefnx {} {@var{stats} =} statistics (@var{x}, @var{dim})\n## @deftypefnx {} {@var{stats} =} statistics (@var{x}, @var{vecdim})\n## @deftypefnx {} {@var{stats} =} statistics (@var{x}, \"all\")\n## @deftypefnx {} {@var{stats} =} statistics (@dots{}, @var{nanflag})\n## Return a vector with statistics parameters over the input data @var{x}.\n##\n## @code{statistics (@var{x}} operates along the first non-singleton dimension\n## of @var{x} and calculates the following statistical parameters:\n## @enumerate\n## @item minimum\n## @item first quartile\n## @item median\n## @item third quartile\n## @item maximum\n## @item mean\n## @item standard deviation\n## @item skewness\n## @item kurtosis\n## @end enumerate\n##\n## If @var{x} is a row vector, then @code{statistics (@var{x})} returns a row\n## vector with the aforementioned statistical parameters.  If @var{x} is a\n## column vector, then it returns a column vector.\n##\n## If @var{x} is a matrix, then @code{statistics (@var{x})} returns a matrix\n## such that each column contains the statistical parameters calculated over\n## the corresponding column of @var{x}.\n##\n## If @var{x} is an array, then @code{statistics (@var{x})} computes the\n## statistical parameters along the first non-singleton dimension of @var{x}.\n##\n## The data in @var{x} must be numeric and by default any NaN values are\n## ignored from the computations of statistical parameters except for the\n## mean and the standard deviation.  Set the optional argument @var{nanflag}\n## to @qcode{\"omitnan\"} to exclude the NaN values from the calculation of\n## the mean and standard deviation parameters.  Setting @var{nanflag} to\n## @qcode{\"includenan\"} is ignored and it is equivalent to calling the\n## @code{statistics} function without the @var{nanflag} argument.\n##\n## The size of @var{stats} is equal to the size of @var{x} except for the\n## operating dimension, which equals to 9 (i.e., the number of statistical\n## parameters returned).\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{@var{x}}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{statistics} to\n## operate on all elements of @var{x}, and is equivalent to\n## @code{statistics (@var{x}(:))}.\n## @seealso{min, max, median, mean, std, skewness, kurtosis}\n## @end deftypefn\n\nfunction stats = statistics (x, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x)))\n    error (\"statistics: X must be a numeric array\");\n  endif\n\n  sz = size (x);\n\n  if (nargin < 2)\n    ## Find the first non-singleton dimension.\n    (dim = find (sz != 1, 1)) || (dim = 1);\n    nanflag = \"includenan\";\n  else\n    if (any (strcmpi (varargin{1}, {\"omitnan\", \"includenan\"})))\n      (dim = find (sz != 1, 1)) || (dim = 1);\n      nanflag = varargin{1};\n    else\n      dim = varargin{1};\n      if (nargin > 2)\n        nanflag = varargin{2};\n        if (! any (strcmpi (nanflag, {\"omitnan\", \"includenan\"})))\n          error (\"statistics: NANFLAG must be either 'omitnan' or 'includenan'\");\n        endif\n      else\n        nanflag = \"includenan\";\n      endif\n    endif\n  endif\n\n  ## Handle \"all\" option here and test for minimum sample size\n  if (strcmpi (dim, \"all\"))\n    dim = 1;\n    x = x(:);\n    if (numel (x) < 2)\n      error (\"statistics: dimension of X is too small (<2)\");\n    endif\n  endif\n\n  ## Remove exceeding dimensions\n  nd = ndims (x);\n  ed = dim > nd;\n  if (all (ed))\n    stats = x;\n    return;\n  elseif (any (ed))\n    dim(ed) = [];\n  endif\n\n  ## Test operating dim for minimum sample size\n  if (prod (sz(dim)) < 2)\n    error (\"statistics: dimension of X is too small (<2)\");\n  endif\n\n  ## Fix orientation for vector input\n  if (dim(1) == 2)\n    p = [0.25, 0.5, 0.75];\n  else\n    p = [0.25; 0.5; 0.75];\n  endif\n\n  min_val = min (x, [], dim);\n  emp_inv = quantile (x, p, dim, 7);\n  max_val = max (x, [], dim);\n  meanval = mean (x, dim, nanflag);\n  std_val = std (x, [], dim, nanflag);\n\n  stats = cat (dim(1), min_val, emp_inv, max_val, meanval, std_val, ...\n               skewness (x, [], dim), kurtosis (x, [], dim));\n\nendfunction\n\n\n%!test\n%! x = rand (7, 5);\n%! s = statistics (x);\n%! assert (min (x), s(1,:), eps);\n%! assert (median (x), s(3,:), eps);\n%! assert (max (x), s(5,:), eps);\n%! assert (mean (x), s(6,:), eps);\n%! assert (std (x), s(7,:), eps);\n%! assert (skewness (x), s(8,:), eps);\n%! assert (kurtosis (x), s(9,:), eps);\n\n%!test\n%! x = rand (7, 5);\n%! s = statistics (x, 2);\n%! assert (min (x, [], 2), s(:,1), eps);\n%! assert (median (x, 2), s(:,3), eps);\n%! assert (max (x, [], 2), s(:,5), eps);\n%! assert (mean (x, 2), s(:,6), eps);\n%! assert (std (x, [], 2), s(:,7), eps);\n%! assert (skewness (x, [], 2), s(:,8), eps);\n%! assert (kurtosis (x, [], 2), s(:,9), eps);\n\n## Test exceeding dimensions\n%!test\n%! x = rand (7, 5);\n%! assert (statistics (x, 3), x);\n%! assert (statistics (x, [3, 4]), x);\n%! assert (statistics (x, [2, 4]), statistics (x, 2));\n\n## Test vecdim and \"all\"\n%!test\n%! x = rand (7, 5, 3);\n%! s = statistics (x, [2, 3]);\n%! assert (min (x, [], [2, 3]), s(:,1), eps);\n%! assert (median (x, [2, 3]), s(:,3), eps);\n%! assert (max (x, [], [2, 3]), s(:,5), eps);\n%! assert (mean (x, [2, 3]), s(:,6), eps);\n%! assert (std (x, [], [2, 3]), s(:,7), eps);\n%! assert (skewness (x, [], [2, 3]), s(:,8), eps);\n%! assert (kurtosis (x, [], [2, 3]), s(:,9), eps);\n%! assert (statistics (x, [1, 2, 3]), statistics (x, \"all\"));\n\n## Test \"omitnan\" option\n%! x = rand (7, 5);\n%! x(3,1) = NaN;\n%! s = statistics (x, 1, \"omitnan\");\n%! assert (statistics (x, \"omitnan\"), s);\n%! assert (min (x, [], 1), s(1,:), eps);\n%! assert (median (x, 1, \"omitnan\"), s(3,:), eps);\n%! assert (max (x, [], 1), s(5,:), eps);\n%! assert (mean (x, 1, \"omitnan\"), s(6,:), eps);\n%! assert (std (x, [], 1, \"omitnan\"), s(7,:), eps);\n%! assert (skewness (x, [], 1), s(8,:), eps);\n%! assert (kurtosis (x, [], 1), s(9,:), eps);\n\n## Test input validation\n%!error <Invalid call> statistics ()\n%!error <statistics: X must be a numeric array> statistics (['A'; 'B'])\n%!error <statistics: X must be a numeric array> statistics ([true; false])\n%!error <statistics: X must be a numeric array> statistics ({1, 2, 3})\n%!error <statistics: dimension of X is too small \\(<2\\)> statistics (1, \"all\")\n%!error <statistics: dimension of X is too small \\(<2\\)> statistics (1)\n"
  },
  {
    "path": "scripts/statistics/std.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{s} =} std (@var{x})\n## @deftypefnx {} {@var{s} =} std (@var{x}, @var{w})\n## @deftypefnx {} {@var{s} =} std (@var{x}, @var{w}, @var{dim})\n## @deftypefnx {} {@var{s} =} std (@var{x}, @var{w}, @var{vecdim})\n## @deftypefnx {} {@var{s} =} std (@var{x}, @var{w}, @qcode{\"all\"})\n## @deftypefnx {} {@var{s} =} std (@dots{}, @var{nanflag})\n## @deftypefnx {} {[@var{s}, @var{m}] =} std (@dots{})\n## Compute the standard deviation of the elements of @var{x}.\n##\n## The standard deviation is defined as\n## @tex\n## $$ {\\rm std}(x) = \\sqrt{{1\\over N-1} \\sum_{i=1}^N (x_i - \\bar x )^2} $$\n## where $\\bar{x}$ is the mean value of @var{x} and $N$ is the number of\n## elements of @var{x}.\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## std (@var{x}) = sqrt ((1 / (N-1)) * SUM_i ((@var{x}(i) - mean(@var{x}))^2))\n## @end group\n## @end example\n##\n## @noindent\n## where @math{N} is the number of elements of @var{x}.\n## @end ifnottex\n##\n## If @var{x} is a vector, then @code{std (@var{x})} returns the standard\n## deviation of the elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{std (@var{x})} returns a row vector with\n## each element containing the standard deviation of the corresponding column\n## in @var{x}.\n##\n## If @var{x} is an array, then @code{std (@var{x})} computes the standard\n## deviation along the first non-singleton dimension of @var{x}.\n##\n## The optional argument @var{w} determines the weighting scheme to use.  Valid\n## values are:\n##\n## @table @asis\n## @item 0 [default]:\n## Normalize with @math{N-1} (population standard deviation).  This provides\n## the square root of the best unbiased estimator of the standard deviation.\n##\n## @item 1:\n## Normalize with @math{N} (sample standard deviation).  This provides the\n## square root of the second moment around the mean.\n##\n## @item a vector:\n## Compute the weighted standard deviation with non-negative weights.\n## The length of @var{w} must equal the size of @var{x} in the operating\n## dimension.  NaN values are permitted in @var{w}, will be multiplied with the\n## associated values in @var{x}, and can be excluded by the @var{nanflag}\n## option.\n##\n## @item an array:\n## Similar to vector weights, but @var{w} must be the same size as @var{x}.  If\n## the operating dimension is supplied as @var{vecdim} or @qcode{\"all\"} and\n## @var{w} is not a scalar, @var{w} must be an same-sized array.\n## @end table\n##\n## Note: @var{w} must always be specified before specifying any of the\n## following dimension options.  To use the default value for @var{w} you may\n## pass an empty input argument @code{[]}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{zeros (size (@var{x}))}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{std} to operate\n## on all elements of @var{x}, and is equivalent to @code{std (@var{x}(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"includenan\"} which keeps NaN values in the calculation.  To\n## exclude NaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.\n## The output will still contain NaN values if @var{x} consists of all NaN\n## values in the operating dimension.\n##\n## The optional second output variable @var{m} contains the mean of the\n## elements of @var{x} used to calculate the standard deviation.  If @var{v} is\n## the weighted standard deviation, then @var{m} is also the weighted mean.\n##\n## @seealso{var, bounds, mad, range, iqr, mean, median}\n## @end deftypefn\n\nfunction [s, m] = std (varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargout < 2)\n    s = sqrt (var (varargin{:}));\n  else\n    [s, m] = var (varargin{:});\n    s = sqrt (s);\n  endif\n\nendfunction\n\n\n%!test\n%! x = ones (10, 2);\n%! y = [1, 3];\n%! assert (std (x), [0, 0]);\n%! assert (std (y), sqrt (2), sqrt (eps));\n%! assert (std (x, 0, 2), zeros (10, 1));\n\n%!assert (std (ones (3, 1, 2), 0, 2), zeros (3, 1, 2))\n%!assert (std ([1 2], 0), sqrt (2)/2, 5*eps)\n%!assert (std ([1 2], 1), 0.5, 5*eps)\n%!assert (std (1), 0)\n%!assert (std (single (1)), single (0))\n%!assert (std ([1 2 3], [], 3), [0 0 0])\n\n## Test input validation\n%!error <Invalid call> std ()\n"
  },
  {
    "path": "scripts/statistics/var.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{v} =} var (@var{x})\n## @deftypefnx {} {@var{v} =} var (@var{x}, @var{w})\n## @deftypefnx {} {@var{v} =} var (@var{x}, @var{w}, @var{dim})\n## @deftypefnx {} {@var{v} =} var (@var{x}, @var{w}, @var{vecdim})\n## @deftypefnx {} {@var{v} =} var (@var{x}, @var{w}, @qcode{\"all\"})\n## @deftypefnx {} {@var{v} =} var (@dots{}, @var{nanflag})\n## @deftypefnx {} {[@var{v}, @var{m}] =} var (@dots{})\n## Compute the variance of the elements of @var{x}.\n##\n## The variance is defined as\n## @tex\n## $$ {\\rm var}(x) = {1\\over N-1} \\sum_{i=1}^N (x_i - \\bar x )^2 $$\n## where $\\bar{x}$ is the mean value of @var{x} and $N$ is the number of\n## elements of @var{x}.\n## @end tex\n## @ifnottex\n##\n## @example\n## @group\n## var (@var{x}) = (1 / (N-1)) * SUM_i ((@var{x}(i) - mean(@var{x}))^2)\n## @end group\n## @end example\n##\n## @noindent\n## where @math{N} is the number of elements of @var{x}.\n## @end ifnottex\n##\n## If @var{x} is a vector, then @code{var (@var{x})} returns the variance of\n## the elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{var (@var{x})} returns a row vector with\n## each element containing the variance of the corresponding column in @var{x}.\n##\n## If @var{x} is an array, then @code{var (@var{x})} computes the variance\n## along the first non-singleton dimension of @var{x}.\n##\n## The optional argument @var{w} determines the weighting scheme to use.  Valid\n## values are:\n##\n## @table @asis\n## @item 0 [default]:\n## Normalize with @math{N-1} (population variance).  This provides the square\n## root of the best unbiased estimator of the variance.\n##\n## @item 1:\n## Normalize with @math{N} (sample variance).  This provides the square root of\n## the second moment around the mean.\n##\n## @item a vector:\n## Compute the weighted variance with non-negative weights.  The length of\n## @var{w} must equal the size of @var{x} in the operating dimension.  NaN\n## values are permitted in @var{w}, will be multiplied with the associated\n## values in @var{x}, and can be excluded by the @var{nanflag} option.\n##\n## @item an array:\n## Similar to vector weights, but @var{w} must be the same size as @var{x}.  If\n## the operating dimension is supplied as @var{vecdim} or @qcode{\"all\"} and\n## @var{w} is not a scalar, then @var{w} must match the size of the specified\n## array slice.\n## @end table\n##\n## Note: @var{w} must always be specified before specifying any of the\n## following dimension options.  To use the default value for @var{w} you\n## may pass an empty input argument @code{[]}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{zeros (size (@var{x}))}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{var} to operate\n## on all elements of @var{x}, and is equivalent to @code{var (@var{x}(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## NaN values from the calculation using any of the previously specified input\n## argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"includenan\"} which keeps NaN values in the calculation.  To\n## exclude NaN values set the value of @var{nanflag} to @qcode{\"omitnan\"}.\n## The output will still contain NaN values if @var{x} consists of all NaN\n## values in the operating dimension.\n##\n## The optional second output variable @var{m} contains the mean of the\n## elements of @var{x} used to calculate the variance.  If @var{v} is the\n## weighted variance, then @var{m} is also the weighted mean.\n##\n## @seealso{std, mean, cov, skewness, kurtosis, moment}\n## @end deftypefn\n\nfunction [v, m] = var (x, varargin)\n\n  if (nargin < 1 || nargin > 4)\n    print_usage ();\n  endif\n\n  ## initialize variables\n  all_flag = false;\n  omitnan = false;\n  nvarg = numel (varargin);\n  varg_chars = cellfun ('ischar', varargin);\n\n  ## Check all char arguments.\n  if (nvarg == 3 && ! varg_chars(3))\n    print_usage ();\n  endif\n\n  if (any (varg_chars))\n    for argin = varargin(varg_chars)\n      switch (lower (argin{1}))\n        case \"all\"\n          all_flag = true;\n        case \"omitnan\"\n          omitnan = true;\n        case \"includenan\"\n          omitnan = false;\n        otherwise\n          print_usage ();\n      endswitch\n    endfor\n    varargin(varg_chars) = [];\n    nvarg = numel (varargin);\n  endif\n\n  ## FIXME: When sparse can broadcast ops then remove sparse checks and hacks.\n  x_issparse = issparse (x);\n  w = 0;\n  weighted = false; # true if weight vector/array used\n  vecdim = [];\n  vecempty = true;\n  vecdim_scalar_vector = [false, false]; # [false, false] for empty vecdim\n  szx = size (x);\n  ndx = ndims (x);\n\n  ## Check numeric arguments\n  if (! (isfloat (x)))\n    error (\"var: X must be a floating point numeric vector or matrix\");\n  endif\n  if (isa (x, \"single\"))\n    outtype = \"single\";\n  else\n    outtype = \"double\";\n  endif\n\n  if (nvarg > 0)\n    if (nvarg > 2 || any (! cellfun ('isnumeric', varargin)))\n      print_usage ();\n    endif\n    ## Process weight input\n    if (any (varargin{1} < 0))\n      error (\"var: weights must not contain any negative values\");\n    endif\n    if (isscalar (varargin{1}))\n      w = varargin{1};\n      if (! (w == 0 || w == 1) && ! isscalar (x))\n        error (\"var: normalization scalar must be either 0 or 1\");\n      endif\n    elseif (numel (varargin{1}) > 1)\n      weights = varargin{1};\n      weighted = true;\n    endif\n    if (nvarg > 1)\n    ## Process dimension input\n      vecdim = varargin{2};\n      if (! (vecempty = isempty (vecdim)))\n        ## Check for empty vecdim, won't change vsv if nonzero size empty\n        vecdim_scalar_vector = [isscalar(vecdim), isvector(vecdim)];\n      endif\n      if (! (vecdim_scalar_vector(2) && all (vecdim > 0))\n          || any (rem (vecdim, 1)))\n        error (\"var: DIM must be a positive integer scalar or vector\");\n      endif\n      if (vecdim_scalar_vector(1) && vecdim > ndx && ! isempty (x))\n        ## Scalar dimension larger than ndims(x), variance of any single number\n        ## is zero, except for inf, NaN, and empty values of x.\n        v = zeros (szx, outtype);\n        vn = ! isfinite (x);\n        v(vn) = NaN;\n        m = x;\n        return;\n      endif\n      if (all (vecdim_scalar_vector == [0 1]) && (! all (diff (sort (vecdim)))))\n        error (\"var: VECDIM must contain non-repeating positive integers\");\n      endif\n    endif\n  endif\n\n  ## Check for conflicting input arguments\n  if (all_flag && ! vecempty)\n    error (\"var: 'all' flag cannot be used with DIM or VECDIM options\");\n  endif\n  if (weighted)\n    if (all_flag)\n      if (isvector (weights))\n        if (numel (weights) != numel (x))\n          error (\"var: weight vector element count does not match X\");\n        endif\n      elseif (! (isequal (size (weights), szx)))\n        error (\"var: weight matrix or array does not match X in size\");\n      endif\n\n    elseif (vecempty)\n      ## Find the first non-singleton dimension.\n      (dim = find (szx > 1, 1)) || (dim = 1);\n      if (isvector (weights))\n        if (numel (weights) != szx(dim))\n          error (\"var: weight vector length does not match operating dimension\");\n        endif\n      elseif (! isequal (size (weights), szx))\n          error (\"var: weight matrix or array does not match X in size\");\n      endif\n    elseif (vecdim_scalar_vector(1))\n      if (isvector (weights))\n        if (numel (weights) != szx(vecdim))\n          error (\"var: weight vector length does not match operating dimension\");\n        endif\n      elseif (! isequal (size (weights), szx))\n          error (\"var: weight matrix or array does not match X in size\");\n      endif\n\n    elseif (vecdim_scalar_vector(2) && ! (isequal (size (weights), szx)))\n      error (\"var: weight matrix or array does not match X in size\");\n    endif\n  endif\n\n  ## Handle special cases of empty or scalar X and exit early.\n  if (isempty (x))\n    if (vecempty && (ndx == 2 || all (szx == 0)))\n      v = NaN (outtype);\n      if (nargout > 1)\n        m = NaN (outtype);\n      endif\n      return;\n    endif\n    if (vecdim_scalar_vector(1))\n      szx(vecdim) = 1;\n      v = NaN (szx, outtype);\n      if (nargout > 1)\n        m = NaN (szx, outtype);\n      endif\n      return;\n    endif\n  elseif (isscalar (x))\n    if (isfinite (x))\n      v = zeros (outtype);\n    else\n      v = NaN (outtype);\n    endif\n    if (nargout > 1)\n      m = x;\n    endif\n    return;\n  endif\n\n  if (nvarg == 0)\n    ## Only numeric input argument, no dimensions or weights.\n    if (all_flag)\n      x = x(:);\n      if (omitnan)\n        x = x(! isnan (x));\n      endif\n      n = length (x);\n      m = sum (x) ./ n;\n      v = sum (abs (x - m) .^ 2) ./ (n - 1 + w);\n      if (n == 1)\n        v = 0;\n      endif\n    else\n      ## Find the first non-singleton dimension.\n      (dim = find (szx > 1, 1)) || (dim = 1);\n      n = szx(dim);\n      if (omitnan)\n        n = sum (! isnan (x), dim);\n        xn = isnan (x);\n        x(xn) = 0;\n      endif\n      m = sum (x, dim) ./ n;\n      dims = ones (1, ndx);\n      dims(dim) = szx(dim);\n      if (x_issparse)\n        m_exp = repmat (m, dims);\n      else\n        m_exp = m .* ones (dims);\n      endif\n      if (omitnan)\n        x(xn) = m_exp(xn);\n      endif\n      v = sumsq (x - m_exp, dim) ./ (n - 1 + w);\n      if (numel (n) == 1)\n        divby0 = (n .* ones (size (v))) == 1;\n      else\n        divby0 = n == 1;\n      endif\n      v(divby0) = 0;\n    endif\n\n  elseif (nvarg == 1)\n    ## Two numeric input arguments, w or weights given.\n    if (all_flag)\n      x = x(:);\n      if (weighted)\n        weights = weights(:);\n        wx = weights .* x;\n      else\n        weights = ones (length (x), 1);\n        wx = x;\n      endif\n\n      if (omitnan)\n        xn = isnan (wx);\n        wx = wx(! xn);\n        weights = weights(! xn);\n        x = x(! xn);\n      endif\n      n = length (wx);\n      m = sum (wx) ./ sum (weights);\n      if (weighted)\n        v = sum (weights .* (abs (x - m) .^ 2)) ./ sum (weights);\n      else\n        v = sum (weights .* (abs (x - m) .^ 2)) ./ (n - 1 + w);\n        if (n == 1)\n          v = 0;\n        endif\n      endif\n\n    else\n      ## Find the first non-singleton dimension.\n      (dim = find (szx > 1, 1)) || (dim = 1);\n      if (! weighted)\n        weights = ones (szx);\n        wx = x;\n      else\n        if (isvector (weights))\n          dims = 1:ndx;\n          dims([1, dim]) = [dim, 1];\n          weights = zeros (szx) + permute (weights(:), dims);\n        endif\n        wx = weights .* x;\n      endif\n      n = size (wx, dim);\n      if (omitnan)\n        xn = isnan (wx);\n        n = sum (! xn, dim);\n        wx(xn) = 0;\n        weights(xn) = 0;\n      endif\n      m = sum (wx, dim) ./ sum (weights, dim);\n      dims = ones (1, ndims (wx));\n      dims(dim) = size (wx, dim);\n      if (x_issparse)\n        m_exp = repmat (m, dims);\n      else\n        m_exp = m .* ones (dims);\n      endif\n      if (omitnan)\n        x(xn) = m_exp(xn);\n      endif\n      if (weighted)\n        v = sum (weights .* ((x - m_exp) .^ 2), dim) ./ sum (weights, dim);\n      else\n        v = sumsq (x - m_exp, dim) ./ (n - 1 + w);\n        if (numel (n) == 1)\n          divby0 = (n .* ones (size (v))) == 1;\n        else\n          divby0 = n == 1;\n        endif\n        v(divby0) = 0;\n      endif\n    endif\n\n  elseif (nvarg == 2)\n    ## Three numeric input arguments, both w or weights and dim or vecdim given.\n    if (vecdim_scalar_vector(1))\n      if (! weighted)\n        weights = ones (szx);\n        wx = x;\n      else\n        if (isvector (weights))\n          dims = 1:ndx;\n          dims([1, vecdim]) = [vecdim, 1];\n          weights = zeros (szx) + permute (weights(:), dims);\n        endif\n        wx = weights .* x;\n      endif\n      n = size (wx, vecdim);\n      if (omitnan)\n        n = sum (! isnan (wx), vecdim);\n        xn = isnan (wx);\n        wx(xn) = 0;\n        weights(xn) = 0;\n      endif\n      m = sum (wx, vecdim) ./ sum (weights, vecdim);\n      dims = ones (1, ndims (wx));\n      dims(vecdim) = size (wx, vecdim);\n      if (x_issparse)\n        m_exp = repmat (m, dims);\n      else\n        m_exp = m .* ones (dims);\n      endif\n      if (omitnan)\n        x(xn) = m_exp(xn);\n      endif\n      if (weighted)\n        v = sum (weights .* ((x - m_exp) .^ 2), vecdim) ...\n              ./ sum (weights, vecdim);\n      else\n        v = sumsq (x - m_exp, vecdim);\n        vn = isnan (v);\n        v = v ./ (n - 1 + w);\n        if (numel (n) == 1)\n          divby0 = (n .* ones (size (v))) == 1;\n        else\n          divby0 = n == 1;\n        endif\n        v(divby0) = 0;\n        v(vn) = NaN;\n      endif\n\n    else\n      ## Weights and nonscalar vecdim specified\n\n      ## Ignore dimensions in VECDIM larger than actual array.\n      remdims = 1 : ndx;    # All dimensions\n      vecdim(vecdim > ndx) = [];\n      ## Calculate permutation vector\n      remdims(vecdim) = [];     # Delete dimensions specified by vecdim\n      nremd = numel (remdims);\n\n      ## If all dimensions are given, it is equivalent to the 'all' flag.\n      if (nremd == 0)\n        x = x(:);\n        if (weighted)\n          weights = weights(:);\n          wx = weights .* x;\n        else\n          weights = ones (length (x), 1);\n          wx = x;\n        endif\n\n        if (omitnan)\n          xn = isnan (wx);\n          wx = wx(! xn);\n          weights = weights(! xn);\n          x = x(! xn);\n        endif\n        n = length (wx);\n        m = sum (wx) ./ sum (weights);\n        if (weighted)\n          v = sum (weights .* (abs (x - m) .^ 2)) ./ sum (weights);\n        else\n          v = sum (weights .* (abs (x - m) .^ 2)) ./ (n - 1 + w);\n          if (n == 1)\n            v = 0;\n          endif\n        endif\n\n      else\n\n        ## FIXME: much of the reshaping can be skipped once Octave's sum can\n        ##        take a vecdim argument.\n\n        ## Apply weights\n        if (weighted)\n          wx = weights .* x;\n        else\n          weights = ones (szx);\n          wx = x;\n        endif\n\n        ## Permute to push vecdims to back\n        perm = [remdims, vecdim];\n        wx = permute (wx, perm);\n        weights = permute (weights, perm);\n        x = permute (x, perm);\n\n        ## Reshape to squash all vecdims in final dimension\n        szwx = size (wx);\n        sznew = [szwx(1:nremd), prod(szwx(nremd+1:end))];\n        wx = reshape (wx, sznew);\n        weights = reshape (weights, sznew);\n        x = reshape (x, sznew);\n\n        ## Calculate var on final squashed dimension\n        dim = nremd + 1;\n        n = size (wx, dim);\n        if (omitnan)\n          xn = isnan (wx);\n          n = sum (! xn, dim);\n          wx(xn) = 0;\n          weights(xn) = 0;\n        endif\n        m = sum (wx, dim) ./ sum (weights, dim);\n        m_exp = zeros (sznew) + m;\n        if (omitnan)\n          x(xn) = m_exp(xn);\n        endif\n        if (weighted)\n          v = sum (weights .* ((x - m_exp) .^ 2), dim) ./ sum (weights, dim);\n        else\n          v = sumsq (x - m_exp, dim) ./ (n - 1 + w);\n          if (numel (n) == 1)\n            divby0 = n .* ones (size (v)) == 1;\n          else\n            divby0 = n == 1;\n          endif\n          v(divby0) = 0;\n        endif\n\n        ## Inverse permute back to correct dimensions\n        v = ipermute (v, perm);\n        if (nargout > 1)\n          m = ipermute (m, perm);\n        endif\n      endif\n    endif\n  endif\n\n  ## Preserve class type\n  if (nargout < 2)\n    if (strcmp (outtype, \"single\"))\n      v = single (v);\n    else\n      v = double (v);\n    endif\n  else\n    if (strcmp (outtype, \"single\"))\n      v = single (v);\n      m = single (m);\n    else\n      v = double (v);\n      m = double (m);\n    endif\n  endif\n\nendfunction\n\n\n%!assert (var (13), 0)\n%!assert (var (single (13)), single (0))\n%!assert (var ([1,2,3]), 1)\n%!assert (var ([1,2,3], 1), 2/3, eps)\n%!assert (var ([1,2,3], [], 1), [0,0,0])\n%!assert (var ([1,2,3], [], 3), [0,0,0])\n%!assert (var (5, 99), 0)\n%!assert (var (5, 99, 1), 0)\n%!assert (var (5, 99, 2), 0)\n%!assert (var ([5 3], [99 99], 2), 1)\n%!assert (var ([1:7], [1:7]), 3)\n%!assert (var ([eye(3)], [1:3]), [5/36, 2/9, 1/4], eps)\n%!assert (var (ones (2,2,2), [1:2], 3), [(zeros (2,2))])\n%!assert (var ([1 2; 3 4], 0, 'all'), var ([1:4]))\n%!assert (var (reshape ([1:8], 2, 2, 2), 0, [1 3]), [17/3 17/3], eps)\n%!assert (var ([1 2 3;1 2 3], [], [1 2]), 0.8, eps)\n\n## Test single input and optional arguments \"all\", DIM, \"omitnan\")\n%!test\n%! x = [-10:10];\n%! y = [x;x+5;x-5];\n%! assert (var (x), 38.5);\n%! assert (var (y, [], 2), [38.5; 38.5; 38.5]);\n%! assert (var (y, 0, 2), [38.5; 38.5; 38.5]);\n%! assert (var (y, 1, 2), ones (3,1) * 36.66666666666666, 1e-14);\n%! assert (var (y, \"all\"), 54.19354838709678, 1e-14);\n%! y(2,4) = NaN;\n%! assert (var (y, \"all\"), NaN);\n%! assert (var (y, \"all\", \"includenan\"), NaN);\n%! assert (var (y, \"all\", \"omitnan\"), 55.01533580116342, 1e-14);\n%! assert (var (y, 0, 2, \"includenan\"), [38.5; NaN; 38.5]);\n%! assert (var (y, [], 2), [38.5; NaN; 38.5]);\n%! assert (var (y, [], 2, \"omitnan\"), [38.5; 37.81842105263158; 38.5], 1e-14);\n\n## Tests for different weight and omitnan code paths\n%!assert (var ([1 NaN 3], [1 2 3], \"omitnan\"), 0.75, eps)\n%!assert (var ([1 2 3], [1 NaN 3], \"omitnan\"), 0.75, eps)\n%!assert (var (magic(3), [1 NaN 3], \"omitnan\"), [3 12 3], eps)\n%!assert (var ([1 NaN 3], [1 2 3], \"omitnan\", \"all\"), 0.75, eps)\n%!assert (var ([1 NaN 3], [1 2 3], \"all\", \"omitnan\"), 0.75, eps)\n%!assert (var ([1 2 3], [1 NaN 3], \"omitnan\", \"all\"), 0.75, eps)\n%!assert (var ([1 NaN 3], [1 2 3], 2, \"omitnan\"), 0.75, eps)\n%!assert (var ([1 2 3], [1 NaN 3], 2, \"omitnan\"), 0.75, eps)\n%!assert (var (magic(3), [1 NaN 3], 1, \"omitnan\"), [3 12 3], eps)\n%!assert (var (magic(3), [1 NaN 3], 2, \"omitnan\"), [0.75;3;0.75], eps)\n%!assert (var ([4 4; 4 6; 6 6], [1 3], 2, 'omitnan'), [0;0.75;0], eps)\n%!assert (var ([4 NaN; 4 6; 6 6], [1 2 3], 1, 'omitnan'), [1 0])\n%!assert (var ([4 NaN; 4 6; 6 6], [1 3], 2, 'omitnan'), [0;0.75;0], eps)\n%!assert (var (3*reshape(1:18, [3 3 2]), [1 2 3], 1, 'omitnan'), ones(1,3,2)*5)\n%!assert (var (reshape(1:18, [3 3 2]), [1 2 3], 2, 'omitnan'), 5*ones(3,1,2))\n%!assert (var (3*reshape(1:18, [3 3 2]), ones (3,3,2), [1 2], 'omitnan'), ...\n%!        60 * ones (1,1,2))\n%!assert (var (3*reshape(1:18, [3 3 2]), ones (3,3,2), [1 4], 'omitnan'), ...\n%!        6 * ones (1,3,2))\n%!assert (var (6*reshape(1:18, [3 3 2]), ones (3,3,2), [1:3], 'omitnan'), 969)\n%!test\n%! x = reshape(1:18, [3 3 2]);\n%! x([2, 14]) = NaN;\n%! w = ones (3,3,2);\n%! assert (var (16*x, w, [1:3], 'omitnan'), 6519);\n%!test\n%! x = reshape(1:18, [3 3 2]);\n%! w = ones (3,3,2);\n%! w([2, 14]) = NaN;\n%! assert (var (16*x, w, [1:3], 'omitnan'), 6519);\n\n## Test input case insensitivity\n%!assert (var ([1 2 3], \"aLl\"), 1)\n%!assert (var ([1 2 3], \"OmitNan\"), 1)\n%!assert (var ([1 2 3], \"IncludeNan\"), 1)\n\n## Test dimension indexing with vecdim in N-dimensional arrays\n%!test\n%! x = repmat ([1:20;6:25], [5, 2, 6, 3]);\n%! assert (size (var (x, 0, [3 2])), [10, 1, 1, 3]);\n%! assert (size (var (x, 1, [1 2])), [1, 1, 6, 3]);\n%! assert (size (var (x, [], [1 2 4])), [1, 1, 6]);\n%! assert (size (var (x, 0, [1 4 3])), [1, 40]);\n%! assert (size (var (x, [], [1 2 3 4])), [1, 1]);\n\n## Test matrix with vecdim, weighted, matrix weights, omitnan\n%!assert (var (3*magic(3)), [63 144 63])\n%!assert (var (3*magic(3), 'omitnan'), [63 144 63])\n%!assert (var (3*magic(3), 1), [42 96 42])\n%!assert (var (3*magic(3), 1, 'omitnan'), [42 96 42])\n%!assert (var (3*magic(3), ones(1,3), 1), [42 96 42])\n%!assert (var (3*magic(3), ones(1,3), 1, 'omitnan'), [42 96 42])\n%!assert (var (2*magic(3), [1 1 NaN], 1, 'omitnan'), [25 16 1])\n%!assert (var (3*magic(3), ones(3,3)), [42 96 42])\n%!assert (var (3*magic(3), ones(3,3), 'omitnan'), [42 96 42])\n%!assert (var (3*magic(3), [1 1 1; 1 1 1; 1 NaN 1], 'omitnan'), [42 36 42])\n%!assert (var (3*magic(3), ones(3,3), 1), [42 96 42])\n%!assert (var (3*magic(3), ones(3,3), 1, 'omitnan'), [42 96 42])\n%!assert (var (3*magic(3), [1 1 1; 1 1 1; 1 NaN 1], 1, 'omitnan'), [42 36 42])\n%!assert (var (3*magic(3), ones(3,3), [1 4]), [42 96 42])\n%!assert (var (3*magic(3), ones(3,3), [1 4], 'omitnan'), [42 96 42])\n%!assert (var (3*magic(3), [1 1 1; 1 1 1; 1 NaN 1],[1 4],'omitnan'), [42 36 42])\n\n## Test results with vecdim in N-dimensional arrays and \"omitnan\"\n%!test\n%! x = repmat ([1:20;6:25], [5, 2, 6, 3]);\n%! v = repmat (33.38912133891213, [10, 1, 1, 3]);\n%! assert (var (x, 0, [3, 2]), v, 1e-14);\n%! v = repmat (33.250, [10, 1, 1, 3]);\n%! assert (var (x, 1, [3, 2]), v, 1e-14);\n%! x(2,5,6,3) = NaN;\n%! v(2,1,1,3) = NaN;\n%! assert (var (x, 1, [3, 2]), v, 4e-14);\n%! v = repmat (33.38912133891213, [10 1 1 3]);\n%! v(2,1,1,3) = NaN;\n%! assert (var (x, [], [3, 2]), v, 4e-14);\n%! v(2,1,1,3) = 33.40177912169048;\n%! assert (var (x, [], [3, 2], \"omitnan\"), v, 4e-14);\n\n## Testing weights vector & arrays\n%!assert (var (ones (2,2,2), [1:2], 3), [(zeros (2, 2))])\n%!assert (var (magic (3), [1:9], \"all\"), 6.666666666666667, 1e-14)\n\n## Test exceeding dimensions\n%!assert (var (ones (2,2), [], 3), zeros (2,2))\n%!assert (var (ones (2,2,2), [], 99), zeros (2,2,2))\n%!assert (var (magic (3), [], 3), zeros (3,3))\n%!assert (var (magic (3), [], 1), [7, 16, 7])\n%!assert (var (magic (3), [], [1 3]), [7, 16, 7])\n%!assert (var (magic (3), [], [1 99]), [7, 16, 7])\n\n## Test empty inputs\n%!assert (var ([]), NaN)\n%!assert (class (var (single ([]))), \"single\")\n%!assert (var ([],[],1), NaN(1,0))\n%!assert (var ([],[],2), NaN(0,1))\n%!assert (var ([],[],3), [])\n%!assert (class (var (single ([]), [], 1)), \"single\")\n%!assert (var (ones (1,0)), NaN)\n%!assert (var (ones (1,0), [], 1), NaN(1,0))\n%!assert (var (ones (1,0), [], 2), NaN)\n%!assert (var (ones (1,0), [], 3), NaN(1,0))\n%!assert (class (var (ones (1, 0, \"single\"), [], 1)), \"single\")\n%!assert (var (ones (0,1)), NaN)\n%!assert (var (ones (0,1), [], 1), NaN)\n%!assert (var (ones (0,1), [], 2), NaN(0,1))\n%!assert (var (ones (0,1), [], 3), NaN(0,1))\n%!assert (var (ones (1,3,0,2)), NaN(1,1,0,2))\n%!assert (var (ones (1,3,0,2), [], 1), NaN(1,3,0,2))\n%!assert (var (ones (1,3,0,2), [], 2), NaN(1,1,0,2))\n%!assert (var (ones (1,3,0,2), [], 3), NaN(1,3,1,2))\n%!assert (var (ones (1,3,0,2), [], 4), NaN(1,3,0))\n%!test\n%! [~, m] = var ([]);\n%! assert (m, NaN);\n\n## Test optional mean output\n%!test <*62395>\n%! [~, m] = var (13);\n%! assert (m, 13);\n%! [~, m] = var (single(13));\n%! assert (m, single (13));\n%! [~, m] = var ([1, 2, 3; 3 2 1], []);\n%! assert (m, [2 2 2]);\n%! [~, m] = var ([1, 2, 3; 3 2 1], [], 1);\n%! assert (m, [2 2 2]);\n%! [~, m] = var ([1, 2, 3; 3 2 1], [], 2);\n%! assert (m, [2 2]');\n%! [~, m] = var ([1, 2, 3; 3 2 1], [], 3);\n%! assert (m, [1 2 3; 3 2 1]);\n\n## Test mean output, weighted inputs, vector dims\n%!test <*62395>\n%! [~, m] = var (5,99);\n%! assert (m, 5);\n%! [~, m] = var ([1:7], [1:7]);\n%! assert (m, 5);\n%! [~, m] = var ([eye(3)], [1:3]);\n%! assert (m, [1/6, 1/3, 0.5], eps);\n%! [~, m] = var (ones (2,2,2), [1:2], 3);\n%! assert (m, ones (2,2));\n%! [~, m] = var ([1 2; 3 4], 0, 'all');\n%! assert (m, 2.5, eps);\n%! [~, m] = var (reshape ([1:8], 2, 2, 2), 0, [1 3]);\n%! assert (m, [3.5, 5.5], eps);\n%!test\n%! [v, m] = var (4 * eye (2), [1, 3]);\n%! assert (v, [3, 3]);\n%! assert (m, [1, 3]);\n\n## Test mean output, empty inputs, omitnan\n%!test <*62395>\n%! [~, m] = var ([]);\n%! assert (m, NaN);\n#%! [~, m] = var ([],[],1);\n#%! assert (m, NaN(1,0));\n#%! [~, m] = var ([],[],2);\n#%! assert (m, NaN(0,1));\n#%! [~, m] = var ([],[],3);\n#%! assert (m, []);\n#%! [~, m] = var (ones (1,3,0,2));\n#%! assert (m, NaN(1,1,0,2));\n\n## Test mean output, N-D array\n%!test <*62395>\n%! x = repmat ([1:20;6:25], [5, 2, 6, 3]);\n%! [~, m] = var (x, 0, [3 2]);\n%! assert (m, mean (x, [3 2]));\n%! [~, m] = var (x, 0, [1 2]);\n%! assert (m, mean (x, [1 2]));\n%! [~, m] = var (x, 0, [1 3 4]);\n%! assert (m, mean (x, [1 3 4]));\n%!test\n%! x = repmat ([1:20;6:25], [5, 2, 6, 3]);\n%! x(2,5,6,3) = NaN;\n%! [~, m] = var (x, 0, [3 2], \"omitnan\");\n%! assert (m, mean (x, [3 2], \"omitnan\"));\n\n## Test Inf and NaN inputs\n%!test <*63203>\n%! [v, m] = var (Inf);\n%! assert (v, NaN);\n%! assert (m, Inf);\n%!test <*63203>\n%! [v, m] = var (NaN);\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([1, Inf, 3]);\n%! assert (v, NaN);\n%! assert (m, Inf);\n%!test <*63203>\n%! [v, m] = var ([1, Inf, 3]');\n%! assert (v, NaN);\n%! assert (m, Inf);\n%!test <*63203>\n%! [v, m] = var ([1, NaN, 3]);\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([1, NaN, 3]');\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([1, Inf, 3], [], 1);\n%! assert (v, [0, NaN, 0]);\n%! assert (m, [1, Inf, 3]);\n%!test <*63203>\n%! [v, m] = var ([1, Inf, 3], [], 2);\n%! assert (v, NaN);\n%! assert (m, Inf);\n%!test <*63203>\n%! [v, m] = var ([1, Inf, 3], [], 3);\n%! assert (v, [0, NaN, 0]);\n%! assert (m, [1, Inf, 3]);\n%!test <*63203>\n%! [v, m] = var ([1, NaN, 3], [], 1);\n%! assert (v, [0, NaN, 0]);\n%! assert (m, [1, NaN, 3]);\n%!test <*63203>\n%! [v, m] = var ([1, NaN, 3], [], 2);\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([1, NaN, 3], [], 3);\n%! assert (v, [0, NaN, 0]);\n%! assert (m, [1, NaN, 3]);\n%!test <*63203>\n%! [v, m] = var ([1, 2, 3; 3, Inf, 5]);\n%! assert (v, [2, NaN, 2]);\n%! assert (m, [2, Inf, 4]);\n%!test <*63203>\n%! [v, m] = var ([1, Inf, 3; 3, Inf, 5]);\n%! assert (v, [2, NaN, 2]);\n%! assert (m, [2, Inf, 4]);\n%!test <*63203>\n%! [v, m] = var ([1, 2, 3; 3, NaN, 5]);\n%! assert (v, [2, NaN, 2]);\n%! assert (m, [2, NaN, 4]);\n%!test <*63203>\n%! [v, m] = var ([1, NaN, 3; 3, NaN, 5]);\n%! assert (v, [2, NaN, 2]);\n%! assert (m, [2, NaN, 4]);\n%!test <*63203>\n%! [v, m] = var ([Inf, 2, NaN]);\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([Inf, 2, NaN]');\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([NaN, 2, Inf]);\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([NaN, 2, Inf]');\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([Inf, 2, NaN], [], 1);\n%! assert (v, [NaN, 0, NaN]);\n%! assert (m, [Inf, 2, NaN]);\n%!test <*63203>\n%! [v, m] = var ([Inf, 2, NaN], [], 2);\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([NaN, 2, Inf], [], 1);\n%! assert (v, [NaN, 0, NaN]);\n%! assert (m, [NaN, 2, Inf]);\n%!test <*63203>\n%! [v, m] = var ([NaN, 2, Inf], [], 2);\n%! assert (v, NaN);\n%! assert (m, NaN);\n%!test <*63203>\n%! [v, m] = var ([1, 3, NaN; 3, 5, Inf]);\n%! assert (v, [2, 2, NaN]);\n%! assert (m, [2, 4, NaN]);\n%!test <*63203>\n%! [v, m] = var ([1, 3, Inf; 3, 5, NaN]);\n%! assert (v, [2, 2, NaN]);\n%! assert (m, [2, 4, NaN]);\n\n## Test sparse/diagonal inputs\n%!test <*63291>\n%! [v, m] = var (2 * eye (2));\n%! assert (v, [2, 2]);\n%! assert (m, [1, 1]);\n%!test <*63291>\n%! [v, m] = var (4 * eye (2), [1, 3]);\n%! assert (v, [3, 3]);\n%! assert (m, [1, 3]);\n%!test <*63291>\n%! [v, m] = var (sparse (2 * eye (2)));\n%! assert (full (v), [2, 2]);\n%! assert (full (m), [1, 1]);\n%!test <*63291>\n%! [v, m] = var (sparse (4 * eye (2)), [1, 3]);\n%! assert (full (v), [3, 3]);\n%! assert (full (m), [1, 3]);\n%!test <*63291>\n%! [v, m] = var (sparse (eye (2)));\n%! assert (issparse (v));\n%! assert (issparse (m));\n%!test <*63291>\n%! [v, m] = var (sparse (eye (2)), [1, 3]);\n%! assert (issparse (v));\n%! assert (issparse (m));\n\n## Test input validation\n%!error <Invalid call> var ()\n%!error <Invalid call> var (1, 2, \"omitnan\", 3)\n%!error <Invalid call> var (1, 2, 3, 4)\n%!error <Invalid call> var (1, 2, 3, 4, 5)\n%!error <Invalid call> var (1, \"foo\")\n%!error <Invalid call> var (1, [], \"foo\")\n%!error <normalization scalar must be either 0 or 1> var ([1 2 3], 2)\n%!error <normalization scalar must be either 0 or 1> var ([1 2], 2, \"all\")\n%!error <normalization scalar must be either 0 or 1> var ([1 2],0.5, \"all\")\n%!error <weights must not contain any negative values> var (1, -1)\n%!error <weights must not contain any negative values> var (1, [1 -1])\n%!error <weights must not contain any negative values>\n%! var ([1 2 3], [1 -1 0])\n%!error <X must be a floating point numeric vector or matrix> var (int32 (1:5))\n%!error <X must be a floating point numeric vector or matrix> var ({1:5})\n%!error <X must be a floating point numeric vector or matrix> var (\"char\")\n%!error <X must be a floating point numeric vector or matrix> var (['A'; 'B'])\n%!error <DIM must be a positive integer> var (1, [], ones (2,2))\n%!error <DIM must be a positive integer> var (1, 0, 1.5)\n%!error <DIM must be a positive integer> var (1, [], 0)\n%!error <DIM must be a positive integer> var (1, [], 1.5)\n%!error <DIM must be a positive integer> var ([1 2 3], [], [-1 1])\n%!error <VECDIM must contain non-repeating positive integers>\n%! var (repmat ([1:20;6:25], [5 2 6 3]), 0, [1 2 2 2])\n%!error <weight matrix or array does not match X in size>\n%! var ([1 2], eye (2))\n%!error <weight matrix or array does not match X in size>\n%! var ([1 2 3 4], [1 2; 3 4])\n%!error <weight matrix or array does not match X in size>\n%! var ([1 2 3 4], [1 2; 3 4], 1)\n%!error <weight matrix or array does not match X in size>\n%! var ([1 2 3 4], [1 2; 3 4], [2 3])\n%!error <weight matrix or array does not match X in size>\n%! var (ones (2, 2), [1 2], [1 2])\n%!error <weight matrix or array does not match X in size>\n%! var ([1 2 3 4; 5 6 7 8], [1 2 1 2 1; 1 2 1 2 1], 1)\n%!error <weight matrix or array does not match X in size>\n%! var (repmat ([1:20;6:25], [5 2 6 3]), repmat ([1:20;6:25], [5 2 3]), [2 3])\n%!error <weight vector length does not match> var ([1 2 3; 2 3 4], [1 3 4])\n%!error <weight vector length does not match> var ([1 2], [1 2 3])\n%!error <weight vector length does not match> var (1, [1 2])\n%!error <weight vector length does not match> var ([1 2 3; 2 3 4], [1 3 4], 1)\n%!error <weight vector length does not match> var ([1 2 3; 2 3 4], [1 3], 2)\n%!error <weight vector length does not match> var ([1 2], [1 2], 1)\n%!error <'all' flag cannot be used with DIM or VECDIM options>\n%! var (1, [], 1, \"all\")\n%!error <weight vector element count does not match X>\n%! var ([1 2 3; 2 3 4], [1 3], \"all\")\n%!error <weight matrix or array does not match X in size>\n%! var (repmat ([1:20;6:25], [5 2 6 3]), repmat ([1:20;6:25], [5 2 3]), \"all\")\n"
  },
  {
    "path": "scripts/statistics/zscore.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{z} =} zscore (@var{x})\n## @deftypefnx {} {@var{z} =} zscore (@var{x}, @var{opt})\n## @deftypefnx {} {@var{z} =} zscore (@var{x}, @var{opt}, @var{dim})\n## @deftypefnx {} {@var{z} =} zscore (@var{x}, @var{opt}, @var{vecdim})\n## @deftypefnx {} {@var{z} =} zscore (@var{x}, @var{opt}, \"all\")\n## @deftypefnx {} {@var{z} =} zscore (@dots{}, @var{nanflag})\n## @deftypefnx {} {[@var{z}, @var{mu}, @var{sigma}] =} zscore (@dots{})\n## Compute the z-score of @var{x}.\n##\n## @c FIXME: Document mathematical definition as a formula, not just text.\n## For a vector @var{x}, the z-score is calculated by subtracting the mean\n## and dividing by its standard deviation.  If the standard deviation is zero,\n## then divide by 1 instead.\n##\n## If @var{x} is a vector, then @code{zscore (@var{x})} returns the z-score\n## of the elements in @var{x}.\n##\n## If @var{x} is a matrix, then @code{zscore (@var{x})} returns a row vector\n## with each element containing the z-score of the corresponding column in\n## @var{x}.\n##\n## If @var{x} is an array, then @code{zscore (@var{x})} computes the z-score\n## along the first non-singleton dimension of @var{x}.\n##\n## @c FIXME: Don't reference other DOCSTRING.  Document values and what they\n## @c        mean in this function.\n## The optional parameter @var{opt} determines the normalization to use when\n## computing the standard deviation and has the same definition as the\n## corresponding parameter for @code{std}.\n##\n## The optional input @var{dim} specifies the dimension to operate on and must\n## be a positive integer.  Specifying any singleton dimension of @var{x},\n## including any dimension exceeding @code{ndims (@var{x})}, will return\n## @code{zeros (size (@var{x}))}.\n##\n## Specifying multiple dimensions with input @var{vecdim}, a vector of\n## non-repeating dimensions, will operate along the array slice defined by\n## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is\n## equivalent to the option @qcode{\"all\"}.  Any dimension in @var{vecdim}\n## greater than @code{ndims (@var{x})} is ignored.\n##\n## Specifying the dimension as @qcode{\"all\"} will cause @code{zscore} to\n## operate on all elements of @var{x}, and is equivalent to\n## @code{zscore (@var{x}(:))}.\n##\n## The optional variable @var{nanflag} specifies whether to include or exclude\n## @code{NaN} values from the calculation using any of the previously specified\n## input argument combinations.  The default value for @var{nanflag} is\n## @qcode{\"includenan\"} which keeps @code{NaN} values in the calculation.  To\n## exclude @code{NaN} values, set the value of @var{nanflag} to\n## @qcode{\"omitnan\"}.  The output will still contain @code{NaN} values at the\n## same locations as in @var{x}.\n##\n## The optional outputs @var{mu} and @var{sigma} contain the mean and standard\n## deviation.\n##\n## @seealso{mean, std, center}\n## @end deftypefn\n\nfunction [z, mu, sigma] = zscore (x, opt = 0, varargin)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (! (isnumeric (x) || islogical (x)))\n    error (\"zscore: X must be a numeric or logical array\");\n  endif\n\n  if (isempty (opt))\n    opt = 0;\n  elseif (! isscalar (opt) || (opt != 0 && opt != 1))\n    error (\"zscore: normalization OPT must be empty, 0, or 1\");\n  endif\n\n  sz = size (x);\n  if (any (sz == 0))\n    z = mu = sigma = x;\n  else\n\n    if (isinteger (x))\n      x = double (x);\n    endif\n\n    mu = mean (x, varargin{:});\n    sigma = std (x, opt, varargin{:});\n    s = sigma;\n    s(s==0) = 1;\n    z = (x - mu) ./ s;\n  endif\n\nendfunction\n\n\n%!assert (zscore ([1,2,3]), [-1,0,1])\n%!assert (zscore (single ([1,2,3])), single ([-1,0,1]))\n%!assert (zscore (int8 ([1,2,3])), [-1,0,1])\n%!assert (zscore (ones (3,2,2,2)), zeros (3,2,2,2))\n%!assert (zscore ([2,0,-2;0,2,0;-2,-2,2]), [1,0,-1;0,1,0;-1,-1,1])\n%!assert <*54531> (zscore ([1,2,3], [], 2), [-1,0,1])\n%!assert (size (zscore (ones (3,2,0,2))), [3,2,0,2])\n%!assert (ndims (zscore (ones (3,2,0,1))), 3)\n%!test\n%! [z, mu, sigma] = zscore (ones (3,2,0,1));\n%! assert (z, ones (3,2,0,1));\n%! assert (size (mu), [3,2,0]);\n%! assert (isempty (sigma), true);\n%!assert (zscore (repmat (1:3, [3,3,3]), [], 1), zeros (3,9,3))\n%!assert (zscore (repmat (1:3, [3,3,3]), [], [1,3]), zeros (3,9,3))\n%!assert (zscore (repmat (1:3, [3,3,3]), [], [1,2]), ...\n%! repmat ([-1,0,1] * 1.2019, [3,3,3]), 1e-4)\n%!assert (zscore (repmat (1:3, [3,3,3]), [], [2,3]), ...\n%! repmat ([-1,0,1] * 1.2019, [3,3,3]), 1e-4)\n%!assert (zscore (repmat (1:3, [3,3,3]), [], 2), ...\n%! repmat ([-1,0,1] * 1.1547, [3,3,3]), 1e-4)\n%!assert (zscore ([1,2,3;4,5,6;7,8,9], [], 1), [-1,-1,-1;0,0,0;1,1,1])\n%!assert (zscore ([1,2,3;4,5,6;7,8,9], [], 2), [-1,-1,-1;0,0,0;1,1,1]')\n%!assert (zscore ([1,2,3;4,5,6;7,8,9], [], 'all'), ...\n%! [-1.4606,-1.0954,-0.7303;-0.3651,0,0.3651;0.7303,1.0954,1.4606], 1e-4)\n%!assert (zscore ([1,2,NaN;4,5,6;7,8,9]), [-1,-1,NaN;0,0,NaN;1,1,NaN])\n%!assert (zscore ([1,2,NaN;4,5,6;7,8,9], [], 'omitnan'), ...\n%! [-1,-1,NaN;0,0,-0.7071;1,1,0.7071], 1e-4)\n%!test\n%! x = [1,2,NaN;4,5,6;7,8,9];\n%! assert (zscore (x, [], 'all', 'omitnan'), ...\n%! reshape (zscore (x(:), [], 'omitnan'), size (x)))\n\n\n## Test input validation\n%!error <Invalid call> zscore ()\n%!error zscore (1, 2, 3)\n%!error <X must be a numeric or logical> zscore (['A'; 'B'])\n%!error <OPT must be empty, 0, or 1> zscore (1, ones (2,2))\n%!error <OPT must be empty, 0, or 1> zscore (1, 1.5)\n%!error <DIM must be .* scalar or vector> zscore (1, [], ones (2,2))\n%!error <DIM must be .* integer> zscore (1, [], 1.5)\n%!error <DIM must be .* positive> zscore (1, [], 0)\n"
  },
  {
    "path": "scripts/strings/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/strings/base2dec.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{d} =} base2dec (@var{str}, @var{base})\n## Convert @var{str} from a string of digits in base @var{base} to a decimal\n## integer (base 10).\n##\n## @example\n## @group\n## base2dec (\"11120\", 3)\n##    @xresult{} 123\n## @end group\n## @end example\n##\n## If @var{str} is a string matrix, return a column vector with one value per\n## row of @var{str}.  If a row contains invalid symbols then the corresponding\n## value will be NaN@.\n##\n## If @var{str} is a cell array of strings, return a column vector with one\n## value per cell element in @var{str}.\n##\n## If @var{base} is a string, the characters of @var{base} are used as the\n## symbols for the digits of @var{str}.  Space (' ') may not be used as a\n## symbol.\n##\n## @example\n## @group\n## base2dec (\"yyyzx\", \"xyz\")\n##    @xresult{} 123\n## @end group\n## @end example\n## @seealso{dec2base, bin2dec, hex2dec}\n## @end deftypefn\n\nfunction d = base2dec (str, base)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (iscellstr (str))\n    str = char (str);\n  elseif (! ischar (str))\n    error (\"base2dec: STR must be a string or cellstring\");\n  endif\n\n  symbols = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n  if (ischar (base))\n    symbols = base;\n    base = length (symbols);\n    if (length (unique (symbols)) != base)\n      error (\"base2dec: symbols representing digits must be unique\");\n    endif\n    if (any (isspace (symbols)))\n      error (\"base2dec: whitespace characters are not valid symbols\");\n    endif\n  elseif (! isscalar (base))\n    error (\"base2dec: cannot convert from several bases at once\");\n  elseif (! (base >= 2 && base <= length (symbols)))\n    error (\"base2dec: BASE must be between 2 and 36, or a string of symbols\");\n  else\n    str = upper (str);\n  endif\n\n  ## Right justify the values and squeeze out any spaces.\n  ## This looks complicated, but indexing solution is very fast\n  ## compared to alternatives which use cellstr or cellfun or looping.\n  [nr, nc] = size (str);\n  if (nc > 1)   # Bug #35621\n    str = str.';\n    nonbl = str != \" \";\n    num_nonbl = sum (nonbl);\n    nc = max (num_nonbl);\n    num_blank = nc - num_nonbl;\n    R = repmat ([1 2; 0 0], 1, nr);\n    R(2, 1:2:2*nr) = num_blank;\n    R(2, 2:2:2*nr) = num_nonbl;\n    idx = repelems ([false, true], R);\n    idx = reshape (idx, nc, nr);\n\n    ## Create a blank matrix and position the nonblank characters.\n    s2 = repmat (\" \", nc, nr);\n    s2(idx) = str(nonbl);\n    str = s2.';\n  endif\n\n  ## Lookup value of symbols in symbol table, with invalid symbols\n  ## evaluating to NaN and space evaluating to 0.\n  table = NaN (1, 256);\n  table(double (symbols(1:base))) = 0 : base-1;\n  table(double (\" \")) = 0;\n  str = reshape (table(double (str)), size (str));\n\n  ## Multiply the resulting digits by the appropriate power\n  ## and sum the rows.\n  d = str * (base .^ (columns (str)-1 : -1 : 0)');\n\nendfunction\n\n\n%!assert (base2dec (\"11120\", 3), 123)\n%!assert (base2dec (\"yyyzx\", \"xyz\"), 123)\n%!assert (base2dec (\"-1\", 2), NaN)\n%!assert (base2dec ({\"A1\", \"1A\"}, 16), [161; 26])\n\n%!assert <*35621> (base2dec ([\"0\"; \"1\"], 2), [0; 1])\n\n## Test input validation\n%!error <Invalid call> base2dec ()\n%!error base2dec (\"11120\")\n%!error base2dec (\"11120\", 3, 4)\n%!error <symbols .* must be unique> base2dec (\"11120\", \"1231\")\n%!error <whitespace characters are not valid> base2dec (\"11120\", \"12 3\")\n%!error <cannot convert from several bases> base2dec (\"11120\", ones (2))\n%!error <BASE must be between 2 and 36> base2dec (\"11120\", 1)\n%!error <BASE must be between 2 and 36> base2dec (\"11120\", 37)\n%!error <BASE must be between 2 and 36> base2dec (\"11120\", NaN)\n"
  },
  {
    "path": "scripts/strings/bin2dec.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{d} =} bin2dec (@var{str})\n## Return the decimal number corresponding to the binary number represented\n## by the string @var{str}.\n##\n## For example:\n##\n## @example\n## @group\n## bin2dec (\"1110\")\n##      @xresult{} 14\n## @end group\n## @end example\n##\n## Spaces are ignored during conversion and may be used to make the binary\n## number more readable.\n##\n## @example\n## @group\n## bin2dec (\"1000 0001\")\n##      @xresult{} 129\n## @end group\n## @end example\n##\n## If @var{str} is a string matrix, return a column vector with one converted\n## number per row of @var{str}; Invalid rows evaluate to NaN@.\n##\n## If @var{str} is a cell array of strings, return a column vector with one\n## converted number per cell element in @var{str}.\n## @seealso{dec2bin, base2dec, hex2dec}\n## @end deftypefn\n\nfunction d = bin2dec (str)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  d = base2dec (str, 2);\n\nendfunction\n\n\n%!assert (bin2dec (\"0000\"), 0)\n%!assert (bin2dec (\"1110\"), 14)\n%!assert (bin2dec (\"11111111111111111111111111111111111111111111111111111\"),\n%!        2^53-1)\n%!assert (bin2dec ({\"1110\", \"1111\"}), [14; 15])\n%!assert (bin2dec (\"1 0 1\"), 5)\n%!assert (bin2dec (char (\"1 0 1\", \"   1111\")), [5; 15])\n\n## Test input validation\n%!error <Invalid call> bin2dec ()\n%!error <STR must be a string> bin2dec (1)\n"
  },
  {
    "path": "scripts/strings/blanks.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{str} =} blanks (@var{n})\n## Return a string of @var{n} blanks.\n##\n## For example:\n##\n## @example\n## @group\n## blanks (10);\n## whos ans\n##      @xresult{}\n##       Attr Name        Size                     Bytes  Class\n##       ==== ====        ====                     =====  =====\n##            ans         1x10                        10  char\n## @end group\n## @end example\n## @seealso{repmat}\n## @end deftypefn\n\nfunction str = blanks (n)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! (isscalar (n) && n == fix (n) && n >= 0))\n    error (\"blanks: N must be a non-negative integer\");\n  endif\n\n  ## If 1:n is empty, the following expression will create an empty\n  ## character string.  Otherwise, it will create a row vector.\n  str(1:n) = \" \";\n\nendfunction\n\n\n## There really isn't that much to test here\n%!assert (blanks (0), \"\")\n%!assert (blanks (5), \"     \")\n%!assert (blanks (10), \"          \")\n\n## Test input validation\n%!error <Invalid call> blanks ()\n%!error blanks (ones (2))\n%!error blanks (2.1)\n%!error blanks (-2)\n"
  },
  {
    "path": "scripts/strings/cstrcat.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{str} =} cstrcat (@var{s1}, @var{s2}, @dots{})\n## Return a string containing all the arguments concatenated horizontally\n## with trailing white space preserved.\n##\n## For example:\n##\n## @example\n## @group\n## cstrcat (\"ab   \", \"cd\")\n##       @xresult{} \"ab   cd\"\n## @end group\n## @end example\n##\n## @example\n## @group\n## s = [ \"ab\"; \"cde\" ];\n## cstrcat (s, s, s)\n##       @xresult{} \"ab ab ab \"\n##          \"cdecdecde\"\n## @end group\n## @end example\n## @seealso{strcat, char, strvcat}\n## @end deftypefn\n\nfunction str = cstrcat (varargin)\n\n  if (nargin == 0)\n    ## Special case because if varargin is empty, iscellstr still returns\n    ## true but then \"[varargin{:}]\" would be of class double.\n    str = \"\";\n  elseif (iscellstr (varargin))\n    str = [varargin{:}];\n  else\n    error (\"cstrcat: arguments must be character strings\");\n  endif\n\nendfunction\n\n\n## Test the dimensionality\n## 1-D\n%!assert (cstrcat (\"ab \", \"ab \"), \"ab ab \")\n## 2-D\n%!assert (cstrcat ([\"ab \";\"cde\"], [\"ab \";\"cde\"]), [\"ab ab \";\"cdecde\"])\n\n%!assert (cstrcat (\"foo\", \"bar\"), \"foobar\")\n%!assert (cstrcat ([\"a \"; \"bb\"], [\"foo\"; \"bar\"]), [\"a foo\"; \"bbbar\"])\n\n## Special null case\n%!assert (cstrcat (), \"\")\n\n## Test input validation\n%!error <arguments must be character strings> cstrcat (1, 2)\n"
  },
  {
    "path": "scripts/strings/deblank.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{s} =} deblank (@var{s})\n## Remove trailing whitespace and nulls from @var{s}.\n##\n## If @var{s} is a matrix, @var{deblank} trims each row to the length of\n## the longest string.  If @var{s} is a cell array of strings, operate\n## recursively on each string element.\n##\n## Examples:\n##\n## @example\n## @group\n## deblank (\"    abc  \")\n##      @xresult{}  \"    abc\"\n##\n## deblank ([\" abc   \"; \"   def   \"])\n##      @xresult{}  [\" abc  \" ; \"   def\"]\n## @end group\n## @end example\n## @seealso{strtrim}\n## @end deftypefn\n\nfunction s = deblank (s)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  if (isempty (s))\n\n    ## Return empty objects unchanged (Matlab compatibility)\n\n  elseif (ischar (s))\n\n    ## Find indices of non-whitespace characters.  If s is a\n    ## char matrix, the indices are in column major order.\n    k = find (! isspace (s) & s != \"\\0\");\n    if (isempty (k))\n      ## Even if s was a char matrix! (Matlab compatibility)\n      s = \"\";\n    else\n      s = s(:,1:ceil (max (k) / rows (s)));\n    endif\n\n  elseif (iscell (s))\n\n    char_idx = cellfun (\"isclass\", s, \"char\");\n    cell_idx = cellfun (\"isclass\", s, \"cell\");\n    empty_idx = cellfun (\"isempty\", s);\n    if (! all (char_idx | cell_idx | empty_idx))\n      error (\"deblank: S argument must be a string or cellstring\");\n    endif\n\n    ## Divide work load.  Recursive cellfun deblank call is slow\n    ## and avoided where possible.\n    s(char_idx) = regexprep (s(char_idx), \"[\\\\s\\v\\\\0]+$\", '');\n    s(cell_idx) = cellfun (\"deblank\", s(cell_idx), \"UniformOutput\", false);\n\n  else\n    error (\"deblank: S argument must be a string or cellstring\");\n  endif\n\nendfunction\n\n\n%!assert (deblank (\" f o o \\0\"), \" f o o\")\n%!assert (deblank (\" \\t f o o \\t \\0\"), \" \\t f o o\")\n%!assert (deblank (char (\" abc   \", \"   def   \")), [\" abc  \" ; \"   def\"])\n%!assert (deblank ([\"   \"; \"   \"]), \"\")\n%!assert (deblank ('   '), '')\n%!assert (deblank (\"   \"), \"\")\n%!assert (deblank (\"\"), \"\")\n%!assert (deblank ([]), [])\n%!assert (deblank ({}), {})\n%!assert (deblank ({[]}), {[]})\n%!assert (deblank ({[], []}), {[], []})\n%!assert (deblank ({\" abc   \", {\"   def   \"}}), {\" abc\", {\"   def\"}})\n\n%!error <Invalid call to deblank> deblank ()\n%!error <called with too many inputs> deblank (\"foo\", \"bar\")\n%!error <argument must be a string> deblank (1)\n"
  },
  {
    "path": "scripts/strings/dec2base.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{str} =} dec2base (@var{d}, @var{base})\n## @deftypefnx {} {@var{str} =} dec2base (@var{d}, @var{base}, @var{len})\n## @deftypefnx {} {@var{str} =} dec2base (@var{d}, @var{base}, @var{len}, @var{decimals})\n## Return a string of symbols in base @var{base} corresponding to the\n## value @var{d}.\n##\n## @example\n## @group\n## dec2base (123, 3)\n##    @xresult{} \"11120\"\n## @end group\n## @end example\n##\n## If @var{d} is negative, then the result will represent @var{d} in complement\n## notation.  For example, negative binary numbers are in twos-complement, and\n## analogously for other bases.\n##\n## If @var{d} is a matrix or cell array, return a string matrix with one row\n## per element in @var{d}, padded with leading zeros to the width of the\n## largest value.\n##\n## If @var{base} is a string then the characters of @var{base} are used as\n## the symbols for the digits of @var{d}.  Whitespace (spaces, tabs, newlines,\n##, etc.@:) may not be used as a symbol.\n##\n## @example\n## @group\n## dec2base (123, \"aei\")\n##    @xresult{} \"eeeia\"\n## @end group\n## @end example\n##\n## The optional third argument, @var{len}, specifies the minimum number of\n## digits in the integer part of the result.  If this is omitted, then\n## @code{dec2base} uses enough digits to accommodate the input.\n##\n## The optional fourth argument, @var{decimals}, specifies the number of\n## digits to represent the fractional part of the input.  If this is omitted,\n## then it is set to zero, and @code{dec2base} returns an integer output for\n## backward compatibility.\n##\n## @example\n## @group\n## dec2base (100*pi, 16)\n## @xresult{} \"13A\"\n## dec2base (100*pi, 16, 4)\n## @xresult{} \"013A\"\n## dec2base (100*pi, 16, 4, 6)\n## @xresult{} \"013A.28C59D\"\n## dec2base (-100*pi, 16)\n## @xresult{} \"EC6\"\n## dec2base (-100*pi, 16, 4)\n## @xresult{} \"FEC6\"\n## dec2base (-100*pi, 16, 4, 6)\n## @xresult{} \"FEC5.D73A63\"\n## @end group\n## @end example\n##\n## Programming tip: When passing negative inputs to @code{dec2base}, it is\n## best to explicitly specify the length of the output required.\n##\n## @seealso{base2dec, dec2bin, dec2hex}\n## @end deftypefn\n\nfunction str = dec2base (d, base, len, decimals = 0)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (iscell (d))\n    d = cell2mat (d);\n  endif\n\n  ## Create column vector for algorithm\n  d = d(:);\n\n  ## Treat logical as numeric for compatibility with ML\n  if (islogical (d))\n    d = double (d);\n  elseif (! isnumeric (d) || iscomplex (d))\n    error (\"dec2base: input must be real numbers\");\n  endif\n\n  ## Note which elements are negative for processing later.\n  ## This also needs special processing for the corresponding intmax.\n  belowlim = false (size (d));\n  if (isinteger (d))\n    belowlim = (d <= intmin (class (d)));\n  endif\n  neg = (d < 0);\n  d(neg) = -d(neg);\n\n  ## Pull out the fractional part for processing later\n  fracpart = d - floor (d);\n  d = floor (d);\n\n  symbols = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n  if (ischar (base))\n    symbols = base(:).';  # force a row vector\n    base = numel (symbols);\n    if (numel (unique (symbols)) != base)\n      error (\"dec2base: symbols representing digits must be unique\");\n    elseif (any (isspace (symbols)))\n      error (\"dec2base: whitespace characters are not valid symbols\");\n    endif\n  elseif (! isscalar (base) || ! isreal (base) || fix (base) != base\n          || base < 2 || base > 36)\n    error (\"dec2base: BASE must be an integer between 2 and 36, or a string of symbols\");\n  endif\n\n  ## Determine number of digits required to handle all numbers.\n  max_len = round (log (max (max (d), 1)) / log (base)) + 1;\n\n  if (nargin >= 3)\n    if (! (isscalar (len) && isreal (len) && len >= 0 && len == fix (len)))\n      error (\"dec2base: LEN must be a non-negative integer\");\n    endif\n    max_len = max (max_len, len);\n  endif\n\n  ## Determine digits for each number\n  digits = zeros (numel (d), max_len);\n  for k = max_len:-1:1\n    digits(:, k) = mod (d, base);\n    d = round ((d - digits(:, k)) / base);\n  endfor\n\n  ## Compute any fractional part and append\n  digits2 = zeros (rows (digits), decimals);\n  if (nargin == 4 && decimals > 0)\n    for k = 1:decimals\n      fracpart *= base;\n      digits2(:, k) = floor (fracpart);\n      fracpart -= floor (fracpart);\n    endfor\n  endif\n\n  ## Handle negative inputs now\n  for k = find (neg)(:)'\n    digits(k, :) = (base-1) - digits(k, :);\n    if (! isempty (digits2))\n      digits2(k, :) = (base - 1) - digits2(k, :);\n    endif\n\n    if (! isempty (digits2))\n      j = columns (digits2);\n      digits2 (k, j) += 1;  # this is a generalization of two's complement\n      while (digits2(j) >= base && j > 1)\n        digits2(k, j) -= base;\n        digits2(k, j-1) += 1;\n        j -= 1;\n      endwhile\n      if (digits2(k, 1) >= base)  # carry over to integer part\n        digits2(k, 1) -= base;\n        digits(k, end) += 1;\n      endif\n    else  # no fractional part ==> increment integer part\n      digits(k, end) += 1;\n    endif\n\n    if (belowlim (k))  # we need to handle an extra +1\n      digits(k, end) -= 1;\n      ## Reason: consider the input intmin(\"int64\"),\n      ## which is -(2)^64 of type int64.\n      ## The code above takes its negation but that exceeds intmax(\"int64\"),\n      ## so it's pegged back to 1 lower than what it needs to be, due to\n      ## the inherent limitation of the representation.\n      ## We add that 1 back here, but because the original sign was negative,\n      ## and we are dealing with complement notation, we subtract it instead.\n    endif\n\n    j = columns (digits);\n    while (digits(k, j) >= base && j > 1)\n      digits(k, j) -= base;\n      digits(k, j-1) += 1;\n      j -= 1;\n    endwhile\n\n    if (digits(k, 1) >= base)  # augment by one place if really needed\n      digits(k, 1) -= base;\n      digits = [zeros(rows(digits), 1), digits];\n      digits(k, 1) += 1;\n      ## FIXME Should we left-pad with zeros or with (base-1) in this context?\n    endif\n  endfor\n\n  ## Convert digits to symbols: integer part\n  str = reshape (symbols(digits+1), size (digits));\n\n  ## Convert digits to symbols: fractional part\n  ## Append fractional part to str if needed.\n  if (! isempty (digits2))\n    str2 = reshape (symbols(digits2+1), size (digits2));\n    str = [str, repmat('.', rows(str), 1), str2];\n  endif\n\n  ## Check if the first element is the zero symbol.  It seems possible\n  ## that LEN is provided, and is less than the computed MAX_LEN and\n  ## MAX_LEN is computed to be one larger than necessary, so we would\n  ## have a leading zero to remove.  But if LEN >= MAX_LEN, we should\n  ## not remove any leading zeros.\n  if ((nargin == 2 || (nargin >= 3 && max_len > len))\n      && columns (str) != 1 && ! any (str(:,1) != symbols(1))\n      && (! any (neg)))\n    str = str(:,2:end);\n  endif\n\nendfunction\n\n\n%!test\n%! s0 = \"\";\n%! for n = 1:13\n%!   for b = 2:16\n%!     pp = dec2base (b^n+1, b);\n%!     assert (dec2base (b^n, b), ['1',s0,'0']);\n%!     assert (dec2base (b^n+1, b), ['1',s0,'1']);\n%!   endfor\n%!   s0 = [s0,'0'];\n%! endfor\n\n## Test positive fractional inputs\n%!assert (dec2base (pi,  2, 0, 16), \"11.0010010000111111\")\n%!assert (dec2base ( e,  2, 2, 16), \"10.1011011111100001\")\n%!assert (dec2base (pi,  3, 0, 16), \"10.0102110122220102\")\n%!assert (dec2base ( e,  3, 0, 16), \"2.2011011212211020\")\n%!assert (dec2base (pi, 16, 0, 10), \"3.243F6A8885\")\n%!assert (dec2base ( e, 16, 0, 10), \"2.B7E151628A\")\n\n## Test negative inputs: all correct in complement notation\n%!assert (dec2base (-1,   10),        \"9\")\n%!assert (dec2base (-1,   10, 3),     \"999\")\n%!assert (dec2base (-1,   10, 3,  2), \"999.00\")\n%!assert (dec2base (-1.1, 10, 3,  2), \"998.90\")\n%!assert (dec2base (-pi,  2,  8, 16), \"11111100.1101101111000001\")\n%!assert (dec2base (-pi,  3,  8, 16), \"22222212.2120112100002121\")\n%!assert (dec2base (-pi, 16,  8, 10), \"FFFFFFFC.DBC095777B\")\n%!assert (dec2base ( -e,  2,  8, 16), \"11111101.0100100000011111\")\n%!assert (dec2base ( -e,  3,  8, 16), \"22222220.0211211010011210\")\n%!assert (dec2base ( -e, 16,  8, 10), \"FFFFFFFD.481EAE9D76\")\n\n## Test negative inputs close to powers of bases\n%!assert (dec2base (-128, 2), \"10000000\")\n%!assert (dec2base (-129, 2, 9), \"101111111\")\n%!assert (dec2base (-129, 2), \"01111111\")\n## FIXME: should dec2base (-129, 2) return \"01111111\" or \"\"101111111\"?\n## The second is an explicit 9-bit universe.  The first is an implied 9-bit\n## universe but the user needs to be careful not to mistake it for +127, which\n## is true in modular arithmetic anyway (i.e., +127 == -129 in 8-bits).\n## Currently we work around this by telling the user in `help dec2base` to\n## explicitly set the lengths when working with negative numbers.\n\n## Test intmin values\n%!assert (dec2base (intmin (\"int8\"), 2), \"10000000\")\n%!assert (dec2base (intmin (\"int16\"), 2), \"1000000000000000\")\n%!assert (dec2base (intmin (\"int32\"), 2), \"10000000000000000000000000000000\")\n%!assert (dec2base (intmin (\"int64\"), 2), \"1000000000000000000000000000000000000000000000000000000000000000\")\n\n%!test\n%! digits = \"0123456789ABCDEF\";\n%! for n = 1:13\n%!   for b = 2:16\n%!     pm = dec2base (b^n-1, b);\n%!     assert (numel (pm), n);\n%!     assert (all (pm == digits(b)));\n%!   endfor\n%! endfor\n\n%!test\n%! for b = 2:16\n%!   assert (dec2base (0, b), '0');\n%! endfor\n\n%!assert (dec2base (0, 2, 4), \"0000\")\n%!assert (dec2base (2^51-1, 2), ...\n%!        \"111111111111111111111111111111111111111111111111111\")\n%!assert (dec2base (uint64 (2)^63-1, 16), \"7FFFFFFFFFFFFFFF\")\n%!assert (dec2base ([1, 2; 3, 4], 2, 3), [\"001\"; \"011\"; \"010\"; \"100\"])\n%!assert (dec2base ({1, 2; 3, 4}, 2, 3), [\"001\"; \"011\"; \"010\"; \"100\"])\n\n%!test\n%! a = 0:3;\n%! assert (dec2base (! a, 2, 1), [\"1\"; \"0\"; \"0\"; \"0\"]);\n\n%!assert <*56005> (dec2base ([0, 0], 16), [\"0\"; \"0\"])\n\n## Test input validation\n%!error <Invalid call> dec2base ()\n%!error <Invalid call> dec2base (1)\n%!error <dec2base: input must be real numbers> dec2base (\"A\", 10)\n%!error <dec2base: input must be real numbers> dec2base (2i, 10)\n%!error <symbols representing digits must be unique> dec2base (1, \"ABA\")\n%!error <whitespace characters are not valid symbols> dec2base (1, \"A B\")\n%!error <BASE must be an integer> dec2base (1, ones (2))\n%!error <BASE must be an integer> dec2base (1, 2i)\n%!error <BASE must be an integer> dec2base (1, 2.5)\n%!error <BASE must be .* between 2 and 36> dec2base (1, 1)\n%!error <BASE must be .* between 2 and 36> dec2base (1, 37)\n%!error <LEN must be a non-negative integer> dec2base (1, 2, ones (2))\n%!error <LEN must be a non-negative integer> dec2base (1, 2, 2i)\n%!error <LEN must be a non-negative integer> dec2base (1, 2, -1)\n%!error <LEN must be a non-negative integer> dec2base (1, 2, 2.5)\n"
  },
  {
    "path": "scripts/strings/dec2bin.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{bstr} =} dec2bin (@var{d})\n## @deftypefnx {} {@var{bstr} =} dec2bin (@var{d}, @var{len})\n## Return a string of ones and zeros representing the conversion of the integer\n## @var{d} to a binary number.\n##\n## If @var{d} is a matrix or cell array, return a string matrix with one row\n## for each element in @var{d}, padded with leading zeros to the width of the\n## largest value.\n##\n## The optional second argument, @var{len}, specifies the minimum number of\n## digits in the result.\n##\n## For negative elements of @var{d}, return the binary value of the two's\n## complement.  The result is padded with leading ones to 8, 16, 32, or 64\n## bits as appropriate for the magnitude of the input.  Positive input\n## elements are padded with leading zeros to the same width.\n##\n## Examples:\n##\n## @example\n## @group\n## dec2bin (14)\n##      @xresult{} \"1110\"\n##\n## dec2bin (-14)\n##      @xresult{} \"11110010\"\n## @end group\n## @end example\n##\n## Programming tip: @code{dec2bin} discards any fractional part of the input.\n## If you need the fractional part to be converted too, call @code{dec2base}\n## with a nonzero number of decimal places.  You can also use @code{fix} or\n## @code{round} on fractional inputs to ensure predictable rounding behavior.\n##\n## @seealso{bin2dec, dec2base, dec2hex}\n## @end deftypefn\n\nfunction bstr = dec2bin (d, len)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  if (iscell (d))\n    d = cell2mat (d);\n  endif\n  d = d(:);\n\n  if (nargin == 1)\n    bstr = dec2base (d, 2);  # this will use a default len picked by dec2base\n  else  # nargin == 2\n    bstr = dec2base (d, 2, len);\n  endif\n\n  if (all (d >= 0))\n    return;\n  endif\n\n  ## If we are here, there are negative inputs, so we need to\n  ## left-pad those outputs with ones to Matlab-compatible lengths.\n  len = columns (bstr);\n  if (all (d >= -128 & d <= 127))\n    len = max (len, 8);  # pad to 8 bits\n  elseif (all (d >= -32768 & d <= 32767))\n    len = max (len, 16);  # pad to 16 bits\n  elseif (all (d >= -2147483648 & d <= 2147483647))\n    len = max (len, 32);  # pad to 32 bits\n  else\n    len = max (len, 64);  # pad to 64 bits\n  endif\n\n  tmp = repmat (' ', rows (bstr), len);\n  tmp(:, (end+1-columns (bstr)):end) = bstr;  # left-pad with spaces\n  bstr = tmp;\n\n  ## Change spaces to \"1\" for negative inputs\n  tmp = bstr(d < 0, :);\n  tmp(tmp == ' ') = '1';\n  bstr(d < 0, :) = tmp;\n\n  ## Change all other spaces to \"0\".\n  bstr(bstr == ' ') = '0';\n\nendfunction\n\n\n%!assert (dec2bin (3), \"11\")\n%!assert (dec2bin (14), \"1110\")\n%!assert (dec2bin (14, 6), \"001110\")\n%!assert (dec2bin ([1, 2; 3, 4]), [\"001\"; \"011\"; \"010\"; \"100\"])\n%!assert (dec2bin ({1, 2; 3, 4}), [\"001\"; \"011\"; \"010\"; \"100\"])\n%!assert (dec2bin ({1, 2; 3, 4}, 4), [\"0001\"; \"0011\"; \"0010\"; \"0100\"])\n\n## Test negative inputs\n%!assert (dec2bin (-3), \"11111101\")\n%!assert (dec2bin (-3, 3), \"11111101\")\n%!assert (dec2bin (-3, 9), \"111111101\")\n%!assert (dec2bin (-2^7 - 1), \"1111111101111111\")\n%!assert (dec2bin (-2^15 - 1), \"11111111111111110111111111111111\")\n%!assert (dec2bin (-2^31 - 1),\n%!        \"1111111111111111111111111111111101111111111111111111111111111111\")\n%!assert (dec2bin (-2^52),\n%!        \"1111111111110000000000000000000000000000000000000000000000000000\")\n%!assert (dec2bin (-2^63),\n%!        \"1000000000000000000000000000000000000000000000000000000000000000\")\n%!assert (dec2bin (int64 (-2) ^ 63),\n%!        \"1000000000000000000000000000000000000000000000000000000000000000\")\n%!assert (dec2bin (int64 (-2) ^ 63 - 1),\n%!        \"1000000000000000000000000000000000000000000000000000000000000000\")\n%!assert (dec2bin (int64 (-2) ^ 63 + 1),\n%!        \"1000000000000000000000000000000000000000000000000000000000000001\")\n%!assert (dec2bin ([-1, -2; -3, -4]),\n%!        [\"11111111\"; \"11111101\"; \"11111110\"; \"11111100\"])\n%!assert (dec2bin ([1, 2; 3, -4]),\n%!        [\"00000001\"; \"00000011\"; \"00000010\"; \"11111100\"])\n%!assert (dec2bin ({1, 2; 3, -4}),\n%!        [\"00000001\"; \"00000011\"; \"00000010\"; \"11111100\"])\n\n## Test fractional inputs\n%!assert (dec2bin (+2.1), \"10\")\n%!assert (dec2bin (-2.1), \"11111110\")\n%!assert (dec2bin (+2.9), \"10\")\n%!assert (dec2bin (-2.9), \"11111110\")\n\n## Test input validation\n%!error <Invalid call> dec2bin ()\n%!error <input must be real> dec2bin (1+i);\n"
  },
  {
    "path": "scripts/strings/dec2hex.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{hstr} =} dec2hex (@var{d})\n## @deftypefnx {} {@var{hstr} =} dec2hex (@var{d}, @var{len})\n## Return a string representing the conversion of the integer @var{d} to a\n## hexadecimal (base16) number.\n##\n## If @var{d} is negative, return the hexadecimal complement of @var{d}.\n##\n## If @var{d} is a matrix or cell array, return a string matrix with one row\n## for each element in @var{d}, padded with leading zeros to the width of the\n## largest value.\n##\n## The optional second argument, @var{len}, specifies the minimum number of\n## digits in the result.\n##\n## Examples:\n##\n## @example\n## @group\n## dec2hex (2748)\n##      @xresult{} \"ABC\"\n##\n## dec2hex (-2)\n##      @xresult{} \"FE\"\n## @end group\n## @end example\n##\n## Programming tip: @code{dec2hex} discards any fractional part of the input.\n## If you need the fractional part to be converted too, call @code{dec2base}\n## with a nonzero number of decimal places.  You can also use @code{fix} or\n## @code{round} on fractional inputs to ensure predictable rounding behavior.\n##\n## @seealso{hex2dec, dec2base, dec2bin}\n## @end deftypefn\n\nfunction hstr = dec2hex (d, len)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  if (iscell (d))\n    d = cell2mat (d);\n  endif\n  d = d(:);\n\n  neg = (d < 0);\n\n  if (nargin == 2)\n    d = dec2bin (d, len*4);\n  else\n    d = dec2bin (d);\n  endif\n\n  ## Left-pad to a multiple of 4 columns.\n  n = mod (columns (d), 4);\n  if (n > 0)\n    tmp = \"01\"(neg + 1);  # leftpad with \"0\" for positive, \"1\" for negative\n    d = [repmat(tmp(:), 1, 4 - n), d];\n  endif\n\n  d -= '0';  # convert to numeric\n  d = d(:, 1:4:end) * 8 + d(:, 2:4:end) * 4 + d(:, 3:4:end) * 2 + d(:, 4:4:end);\n  ## Elements of d are now in the range 0 to 15.\n\n  hstr = \"0123456789ABCDEF\"(d+1);\n  if (rows (hstr) < rows (d))  # this edge case happens when\n    hstr = hstr(:);            # passing multiple inputs in the range 0 to 15.\n    ## If we don't manually convert it to column, we'd get all those\n    ## hex digits on the same line as one big string instead of one per line.\n    ## Good test for this:    dec2hex (0:15)\n    ## compared with:         dec2hex (uint64 (81985529216486895), 16)\n  endif\n\nendfunction\n\n\n%!assert (dec2hex (2748), \"ABC\")\n%!assert (dec2hex (2748, 5), \"00ABC\")\n%!assert (dec2hex ([2748, 2746]), [\"ABC\"; \"ABA\"])\n%!assert (dec2hex ({2748, 2746}), [\"ABC\"; \"ABA\"])\n%!assert (dec2hex ({2748, 2746}, 4), [\"0ABC\"; \"0ABA\"])\n\n## Test negative inputs\n%!assert (dec2hex (-3), \"FD\")\n%!assert (dec2hex (-3, 1), \"FD\")\n%!assert (dec2hex (-3, 3), \"FFD\")\n%!assert (dec2hex (-2^7 - 1), \"FF7F\")\n%!assert (dec2hex (-2^15 - 1), \"FFFF7FFF\")\n%!assert (dec2hex (-2^31 - 1), \"FFFFFFFF7FFFFFFF\")\n%!assert (dec2hex (-2^52), \"FFF0000000000000\")\n%!assert (dec2hex (-2^63), \"8000000000000000\")\n%!assert (dec2hex (int64 (-2) ^ 63), \"8000000000000000\")\n%!assert (dec2hex (int64 (-2) ^ 63 - 1), \"8000000000000000\")\n%!assert (dec2hex (int64 (-2) ^ 63 + 1), \"8000000000000001\")\n%!assert (dec2hex ([-1, -2; -3, -4]), [\"FF\"; \"FD\"; \"FE\"; \"FC\"])\n%!assert (dec2hex ([1, 2; 3, -4]), [\"01\"; \"03\"; \"02\"; \"FC\"])\n%!assert (dec2hex ({1, 2; 3, -4}), [\"01\"; \"03\"; \"02\"; \"FC\"])\n\n## Test that the output is of the correct shape.\n## Next line should return a column vector:\n%!assert (dec2hex (0:15), \"0123456789ABCDEF\"(:))\n## Next line should return a row vector:\n%!assert (dec2hex (uint64 (18364758544493064720)), \"FEDCBA9876543210\")\n\n## Test input validation\n%!error <Invalid call> dec2hex ()\n"
  },
  {
    "path": "scripts/strings/endsWith.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{retval} =} endsWith (@var{str}, @var{pattern})\n## @deftypefnx {} {@var{retval} =} endsWith (@var{str}, @var{pattern}, \"IgnoreCase\", @var{ignore_case})\n## Check whether string(s) end with pattern(s).\n##\n## Return an array of logical values that indicates which string(s) in the\n## input @var{str} (a single string or cell array of strings) end with\n## the input @var{pattern} (a single string or cell array of strings).\n##\n## If the value of the parameter @qcode{\"IgnoreCase\"} is true, then the\n## function will ignore the letter case of @var{str} and @var{pattern}.  By\n## default, the comparison is case sensitive.\n##\n## Examples:\n##\n## @example\n## @group\n## ## one string and one pattern while considering case\n## endsWith (\"hello\", \"lo\")\n##       @xresult{}  1\n## @end group\n##\n## @group\n## ## one string and one pattern while ignoring case\n## endsWith (\"hello\", \"LO\", \"IgnoreCase\", true)\n##       @xresult{}  1\n## @end group\n##\n## @group\n## ## multiple strings and multiple patterns while considering case\n## endsWith (@{\"tests.txt\", \"mydoc.odt\", \"myFunc.m\", \"results.pptx\"@},\n##           @{\".docx\", \".odt\", \".txt\"@})\n##       @xresult{}  1  1  0  0\n## @end group\n##\n## @group\n## ## multiple strings and one pattern while considering case\n## endsWith (@{\"TESTS.TXT\", \"mydoc.odt\", \"result.txt\", \"myFunc.m\"@},\n##           \".txt\", \"IgnoreCase\", false)\n##       @xresult{}  0  0  1  0\n## @end group\n##\n## @group\n## ## multiple strings and one pattern while ignoring case\n## endsWith (@{\"TESTS.TXT\", \"mydoc.odt\", \"result.txt\", \"myFunc.m\"@},\n##           \".txt\", \"IgnoreCase\", true)\n##       @xresult{}  1  0  1  0\n## @end group\n## @end example\n##\n## @seealso{startsWith, regexp, strncmp, strncmpi}\n## @end deftypefn\n\nfunction retval = endsWith (str, pattern, IgnoreCase, ignore_case)\n\n  if (nargin != 2 && nargin != 4)\n    print_usage ();\n  endif\n\n  ## Validate input str and pattern\n  if (! (iscellstr (str) || ischar (str)))\n    error (\"endsWith: STR must be a string or cell array of strings\");\n  endif\n  if (! (iscellstr (pattern) || ischar (pattern)))\n    error (\"endsWith: PATTERN must be a string or cell array of strings\");\n  endif\n\n  ## reverse str and pattern\n  str = cellfun ('flip', cellstr (str), \"UniformOutput\", false);\n  pattern = cellfun ('flip', cellstr (pattern), \"UniformOutput\", false);\n\n  if (nargin == 2)\n    ignore_case = false;\n  else\n    ## For Matlab compatibility accept any abbreviation of 3rd argument\n    if (! ischar (IgnoreCase) || isempty (IgnoreCase)\n        || ! strncmpi (IgnoreCase, \"IgnoreCase\", length (IgnoreCase)))\n      error ('endsWith: third input must be \"IgnoreCase\"');\n    endif\n\n    if (! isscalar (ignore_case) || ! isreal (ignore_case))\n      error ('endsWith: \"IgnoreCase\" value must be a logical scalar');\n    endif\n    ignore_case = logical (ignore_case);\n  endif\n\n  retval = false (size (str));\n  if (ignore_case)\n    for j = 1:numel (pattern)\n      retval |= strncmpi (str, pattern{j}, length (pattern{j}));\n    endfor\n  else\n    for j = 1:numel (pattern)\n      retval |= strncmp (str, pattern{j}, length (pattern{j}));\n    endfor\n  endif\n\nendfunction\n\n\n## Test simple use with one string and one pattern\n%!assert (endsWith (\"hello\", \"lo\"))\n%!assert (! endsWith (\"hello\", \"LO\"))\n%!assert (endsWith (\"hello\", \"LO\", \"i\", 5))\n%!assert (! endsWith (\"hello\", \"no\"))\n\n## Test multiple strings with a single pattern\n%!test\n%! str = {\"myFile.odt\", \"results.ppt\", \"myCode.m\"; ...\n%!        \"data-analysis.ppt\", \"foundations.txt\", \"data.odt\"};\n%! pattern = \".odt\";\n%! expected = [true, false, false; false, false, true];\n%! assert (endsWith (str, pattern), expected);\n\n## Test multiple strings with multiple patterns\n%!test\n%! str = {\"tests.txt\", \"mydoc.odt\", \"myFunc.m\", \"results.pptx\"};\n%! pattern = {\".docx\", \".odt\", \".txt\"};\n%! expected = [true, true, false, false];\n%! assert (endsWith (str, pattern), expected);\n\n## Test IgnoreCase\n%!test\n%! str = {\"TESTS.TXT\", \"mydoc.odt\", \"result.txt\", \"myFunc.m\"};\n%! pattern = \".txt\";\n%! expected_ignore = [true, false, true, false];\n%! expected_wo_ignore = [false, false, true, false];\n%! assert (endsWith (str, pattern, \"IgnoreCase\", true), expected_ignore);\n%! assert (endsWith (str, pattern, \"IgnoreCase\", false), expected_wo_ignore);\n%! assert (endsWith (str, pattern, \"I\", 500), expected_ignore);\n%! assert (endsWith (str, pattern, \"iG\", 0), expected_wo_ignore);\n\n## Test input validation\n%!error <Invalid call> endsWith ()\n%!error endsWith (\"A\")\n%!error endsWith (\"A\", \"B\", \"C\")\n%!error endsWith (\"A\", \"B\", \"C\", \"D\", \"E\")\n%!error <STR must be a string> endsWith (152, \"hi\")\n%!error <STR must be a .* cell array of strings> endsWith ({152}, \"hi\")\n%!error <PATTERN must be a string> endsWith (\"hi\", 152)\n%!error <PATTERN must be a .* cell array of strings> endsWith (\"hi\", {152})\n%!error <third input must be \"IgnoreCase\"> endsWith (\"hello\", \"lo\", 1, 1)\n%!error <third input must be \"IgnoreCase\"> endsWith (\"hello\", \"lo\", \"\", 1)\n%!error <third input must be \"IgnoreCase\"> endsWith (\"hello\", \"lo\", \"foo\", 1)\n%!error <\"IgnoreCase\" value must be a logical scalar>\n%! endsWith (\"hello\", \"hi\", \"i\", \"true\");\n%!error <\"IgnoreCase\" value must be a logical scalar>\n%! endsWith (\"hello\", \"hi\", \"i\", {true});\n"
  },
  {
    "path": "scripts/strings/erase.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{newstr} =} erase (@var{str}, @var{ptn})\n## Delete all occurrences of @var{ptn} within @var{str}.\n##\n## @var{str} and @var{ptn} can be ordinary strings, cell array of strings, or\n## character arrays.\n##\n## Examples\n##\n## @example\n## @group\n## ## string, single pattern\n## erase (\"Hello World!\", \" World\")\n##     @xresult{} \"Hello!\"\n##\n## ## cellstr, single pattern\n## erase (@{\"Hello\", \"World!\"@}, \"World\")\n##     @xresult{} @{\"Hello\", \"!\"@}\n##\n## ## string, multiple patterns\n## erase (\"The Octave interpreter is fabulous\", ...\n##        @{\"interpreter \", \"The \"@})\n##     @xresult{} \"Octave is fabulous\"\n##\n## ## cellstr, multiple patterns\n## erase (@{\"The \", \"Octave interpreter \", \"is fabulous\"@}, ...\n##        @{\"interpreter \", \"The \"@})\n##     @xresult{} @{\"\", \"Octave \", \"is fabulous\"@}\n## @end group\n## @end example\n##\n## Programming Note: @code{erase} deletes the first instance of a pattern in a\n## string when there are overlapping occurrences.  For example:\n##\n## @example\n## @group\n## erase (\"abababa\", \"aba\")\n##     @xresult{} \"b\"\n## @end group\n## @end example\n##\n## For processing overlaps, @pxref{XREFstrrep,,@code{strrep}}.\n##\n## @seealso{strrep, regexprep}\n## @end deftypefn\n\n\nfunction newstr = erase (str, ptn)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  ischarmatrix = false;\n  if (ischar (str))\n    if (rows (str) > 1)\n      ## Convert to cell.  Can't use cellstr which trims spaces.\n      str = mat2cell (str, ones (1, rows (str)));\n      ischarmatrix = true;\n    endif\n  elseif (! iscellstr (str))\n    error (\"erase: STR must be a string or cell array of strings\");\n  endif\n\n  if (ischar (ptn))\n    if (rows (ptn) > 1)\n      warning (\"Octave:erase:chararray\",\n               \"erase: using character array for PTN is not recommended, consider cell array of strings instead\");\n      ## Convert to cell.  Can't use cellstr which trims spaces.\n      ptn = mat2cell (ptn, ones (1, rows (ptn)));\n    endif\n  elseif (! iscellstr (ptn))\n    error (\"erase: PTN must be a string or cell array of strings\");\n  endif\n\n  nptn = ifelse (ischar (ptn), 1, numel (ptn));\n  if (nptn == 1)\n    newstr = strrep (str, ptn, \"\", \"overlaps\", false);\n  else\n    ptn = regexptranslate (\"escape\", ptn(:).');\n    ptn = strjoin (ptn, '|');\n    newstr = regexprep (str, ptn, '');\n  endif\n\n  if (ischarmatrix)\n    newstr = char (newstr);\n  endif\n\nendfunction\n\n\n%!assert (erase (\"Hello World!\", \" World\"), \"Hello!\")\n%!assert (erase ({\"Hello World!\"}, \" World\"), {\"Hello!\"})\n%!assert (erase (char (\"Hello\", \"World!\"), \"World\"), char (\"Hello \", \"!\"))\n%!assert (erase ({\"Hello\", \"World!\"}, \"World\"), {\"Hello\", \"!\"})\n%!assert (erase (\"Hello World!\", {\"o\"; \"World\"; \" \"}), \"Hell!\")\n\n## Test overlaps\n## from https://savannah.gnu.org/bugs/?52647#comment5\n%!assert (erase ('ababa', 'aba'), 'ba')\n%!assert (erase ('abababa', 'aba'), 'b')\n%!assert (erase ('ababababa', 'aba'), 'bba')\n%!assert (erase ('ababababa', {'aba', 'bba'}), 'bba')\n%!assert (erase ('ababababa ', {'aba', 'bba'}), 'bba ')\n%!assert (erase ({' ababababa '}, {'aba', 'bba'}), {' bba '})\n%!assert (erase (' ababa ', {'aba', 'baba'}), ' ba ')\n%!assert (erase (' Hello World t ', {'t';'llo'}), ' He World  ')\n%!assert (erase ({' Hello World t '}, [ 'o ']), {' HellWorld t '})\n%!assert (erase ( 'Hello World t ', {'ld '; 'o '}), 'HellWort ')\n%!assert (erase ('aba', 'aba'), '')\n%!assert (erase ({'aba'}, 'aba'), ({\"\"}))\n%!assert (erase ('', 'aba'), '')\n%!assert (erase ({'abbabbabba'},{'abba'}), {'bb'})\n%!assert (erase ({'ababababa';'abbabbabba'}, 'aba'), {'bba';'abbabbabba'})\n%!assert (erase ({''}, {''}), {''})\n%!assert (erase ({'pppppppp'}, 'p'), {''})\n%!assert (erase ('Hello World t ', {'ld '; 'o '}), 'HellWort ')\n%!assert (erase ({'Hello World t '}, {'ld '; 'o '}), {'HellWort '})\n\n## Test input validation\n%!error <Invalid call> erase ()\n%!error erase (\"a\")\n%!error erase (\"a\", \"b\", \"c\")\n%!error <STR must be a string> erase ([1], \"foo\")\n%!error <PTN must be a string> erase (\"foo\", [1])\n%!warning <using character array for PTN is not recommended>\n%! erase ('a', ['a';'b']);\n"
  },
  {
    "path": "scripts/strings/hex2dec.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{d} =} hex2dec (@var{str})\n## Return the integer corresponding to the hexadecimal number represented by\n## the string @var{str}.\n##\n## For example:\n##\n## @example\n## @group\n## hex2dec (\"12B\")\n##       @xresult{} 299\n## hex2dec (\"12b\")\n##       @xresult{} 299\n## @end group\n## @end example\n##\n## If @var{str} is a string matrix, return a column vector with one converted\n## number per row of @var{str}; Invalid rows evaluate to NaN@.\n##\n## If @var{str} is a cell array of strings, return a column vector with one\n## converted number per cell element in @var{str}.\n##\n## @seealso{dec2hex, base2dec, bin2dec}\n## @end deftypefn\n\nfunction d = hex2dec (str)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  d = base2dec (str, 16);\n\nendfunction\n\n\n%!assert (hex2dec (\"0000\"), 0)\n%!assert (hex2dec (\"1FFFFFFFFFFFFF\"), 2^53-1)\n%!assert (hex2dec ([\"12b\"; \"12B\"]), [299; 299])\n%!assert (hex2dec ({\"A1\", \"1A\"}), [161; 26])\n\n## Test input validation\n%!error <Invalid call> hex2dec ()\n%!error <STR must be a string> hex2dec (1)\n"
  },
  {
    "path": "scripts/strings/index.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{n} =} index (@var{s}, @var{t})\n## @deftypefnx {} {@var{n} =} index (@var{s}, @var{t}, @var{direction})\n## Return the position of the first occurrence of the string @var{t} in the\n## string @var{s}, or 0 if no occurrence is found.\n##\n## @var{s} may also be a string array or cell array of strings.\n##\n## For example:\n##\n## @example\n## @group\n## index (\"Teststring\", \"t\")\n##     @xresult{} 4\n## @end group\n## @end example\n##\n## If @var{direction} is @qcode{\"first\"}, return the first element found.\n## If @var{direction} is @qcode{\"last\"}, return the last element found.\n##\n## @seealso{find, rindex}\n## @end deftypefn\n\nfunction n = index (s, t, direction = \"first\")\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (ischar (s))\n    if (! isrow (s))\n      s = cellstr (s);  # Handle string arrays by conversion to cellstr\n    endif\n  elseif (! iscellstr (s))\n    error (\"index: S must be a string, string array, or cellstr\");\n  endif\n\n  f = strfind (s, t);\n  if (isempty (f))\n    f = 0;\n  elseif (iscell (f))\n    f(cellfun (\"isempty\", f)) = {0};\n  endif\n\n  direction = lower (direction);\n\n  if (strcmp (direction, \"first\"))\n    if (iscell (f))\n      n = cellfun (\"min\", f);\n    else\n      n = f(1);\n    endif\n  elseif (strcmp (direction, \"last\"))\n    if (iscell (f))\n      n = cellfun (\"max\", f);\n    else\n      n = f(end);\n    endif\n  else\n    error ('index: DIRECTION must be either \"first\" or \"last\"');\n  endif\n\nendfunction\n\n\n%!assert (index (\"foobarbaz\", \"b\"), 4)\n%!assert (index (\"foobarbaz\", \"z\"), 9)\n\n%!assert (index (\"astringbstringcstring\", \"s\"), 2)\n%!assert (index (\"astringbstringcstring\", \"st\"), 2)\n%!assert (index (\"astringbstringcstring\", \"str\"), 2)\n%!assert (index (\"astringbstringcstring\", \"string\"), 2)\n%!assert (index (\"abc---\", \"abc+++\"), 0)\n\n## test everything out in reverse\n%!assert (index (\"astringbstringcstring\", \"s\", \"last\"), 16)\n%!assert (index (\"astringbstringcstring\", \"st\", \"last\"), 16)\n%!assert (index (\"astringbstringcstring\", \"str\", \"last\"), 16)\n%!assert (index (\"astringbstringcstring\", \"string\", \"last\"), 16)\n%!assert (index (\"abc---\", \"abc+++\", \"last\"), 0)\n\n%!test\n%! str = char (\"Hello\", \"World\", \"Goodbye\", \"World\");\n%! assert (index (str, \"o\"), [5; 2; 2; 2]);\n%! assert (index (str, \"o\", \"last\"), [5; 2; 3; 2]);\n%! str = cellstr (str);\n%! assert (index (str, \"o\"), [5; 2; 2; 2]);\n%! assert (index (str, \"o\", \"last\"), [5; 2; 3; 2]);\n\n## Test input validation\n%!error <Invalid call> index ()\n%!error index (\"a\")\n%!error index (\"a\", \"b\", \"first\", \"d\")\n%!error index (1, \"bar\")\n%!error index (\"foo\", \"bar\", 3)\n"
  },
  {
    "path": "scripts/strings/isletter.m",
    "content": "########################################################################\n##\n## Copyright (C) 1998-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isletter (@var{s})\n## Return a logical array which is true where the elements of @var{s}\n## are letters and false where they are not.\n##\n## This is an alias for the @code{isalpha} function.\n## @seealso{isalpha, isdigit, ispunct, isspace, iscntrl, isalnum}\n## @end deftypefn\n\nfunction tf = isletter (s)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = isalpha (s);\n\nendfunction\n\n\n%!error <Invalid call> isletter ()\n%!error isletter (\"a\", \"b\")\n"
  },
  {
    "path": "scripts/strings/isstring.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} isstring (@var{s})\n## Return true if @var{s} is a string array.\n##\n## A string array is a data type that stores strings (row vectors of\n## characters) at each element in the array.  It is distinct from character\n## arrays which are N-dimensional arrays where each element is a single 1x1\n## character.  It is also distinct from cell arrays of strings which store\n## strings at each element, but use cell indexing @samp{@{@}} to access\n## elements rather than string arrays which use ordinary array indexing\n## @samp{()}.\n##\n## Programming Note: Octave does not yet implement string arrays so this\n## function will always return false.\n## @seealso{ischar, iscellstr, isfloat, isinteger, islogical, isnumeric, isa}\n## @end deftypefn\n\nfunction tf = isstring (s)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  tf = isa (s, 'string');\n\nendfunction\n\n\n%!assert (isstring ([]), false)\n%!assert (isstring (1), false)\n%!assert (isstring ('a'), false)\n## FIXME: when string arrays are implemented, this should return true.\n%!#assert (isstring (\"b\"), true)\n%!assert (isstring ({'a'}), false)\n%!assert (isstring ({\"b\"}), false)\n\n%!error <Invalid call> isstring ()\n"
  },
  {
    "path": "scripts/strings/isstrprop.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} isstrprop (@var{str}, @var{prop})\n## @deftypefnx {} {@var{tf} =} isstrprop (@var{str}, @var{prop}, 'ForceCellOutput', @var{flag})\n## Test character string properties.\n##\n## For example:\n##\n## @example\n## @group\n## isstrprop (\"abc123\", \"alpha\")\n## @xresult{} [1, 1, 1, 0, 0, 0]\n## @end group\n## @end example\n##\n## If @var{str} is a cell array, @code{isstrpop} is applied recursively to\n## each element of the cell array.\n##\n## Numeric arrays are converted to character strings.\n##\n## The second argument @var{prop} must be one of\n##\n## @table @asis\n## @item @qcode{\"alpha\"}\n## True for characters that are alphabetic (letters).\n##\n## @item  @nospell{@qcode{\"alnum\"}}\n## @itemx @nospell{@qcode{\"alphanum\"}}\n## True for characters that are alphabetic or digits.\n##\n## @item @qcode{\"lower\"}\n## True for lowercase letters.\n##\n## @item @qcode{\"upper\"}\n## True for uppercase letters.\n##\n## @item @qcode{\"digit\"}\n## True for decimal digits (0-9).\n##\n## @item @nospell{@qcode{\"xdigit\"}}\n## True for hexadecimal digits (@nospell{a-fA-F0-9}).\n##\n## @item  @qcode{\"space\"}\n## @itemx @nospell{@qcode{\"wspace\"}}\n## True for whitespace characters (space, formfeed, newline, carriage return,\n## tab, vertical tab).\n##\n## @item @nospell{@qcode{\"punct\"}}\n## True for punctuation characters (printing characters except space or\n## letter or digit).\n##\n## @item @nospell{@qcode{\"cntrl\"}}\n## True for control characters.\n##\n## @item  @qcode{\"graph\"}\n## @itemx @qcode{\"graphic\"}\n## True for printing characters except space.\n##\n## @item @qcode{\"print\"}\n## True for printing characters including space.\n##\n## @item @qcode{\"ascii\"}\n## True for characters that are in the range of ASCII encoding.\n##\n## @end table\n##\n## If the option @nospell{@qcode{'ForceCellOutput'}} is given and @var{flag} is\n## true then a cell value is returned rather than a logical array.\n##\n## @seealso{isalpha, isalnum, islower, isupper, isdigit, isxdigit,\n## isspace, ispunct, iscntrl, isgraph, isprint, isascii}\n## @end deftypefn\n\nfunction tf = isstrprop (str, prop, opt, flag)\n\n  if (nargin != 2 && nargin != 4)\n    print_usage ();\n  endif\n\n  force_cell_output = false;\n  if (nargin > 2)\n    if (! (isrow (opt) && strcmpi (opt, 'ForceCellOutput')))\n      error (\"isstrprop: only accepted option is 'ForceCellOutput'\");\n    elseif (! (isscalar (flag) && isreal (flag)))\n      error (\"isstrprop: FLAG must be a real scalar\");\n    endif\n    force_cell_output = flag;\n  endif\n\n  switch (prop)\n    case \"alpha\"\n      tf = isalpha (str);\n    case {\"alnum\", \"alphanum\"}\n      tf = isalnum (str);\n    case \"ascii\"\n      tf = isascii (str);\n    case \"cntrl\"\n      tf = iscntrl (str);\n    case \"digit\"\n      tf = isdigit (str);\n    case {\"graph\", \"graphic\"}\n      tf = isgraph (str);\n    case \"lower\"\n      tf = islower (str);\n    case \"print\"\n      tf = isprint (str);\n    case \"punct\"\n      tf = ispunct (str);\n    case {\"space\", \"wspace\"}\n      tf = isspace (str);\n    case \"upper\"\n      tf = isupper (str);\n    case \"xdigit\"\n      tf = isxdigit (str);\n    otherwise\n      error (\"isstrprop: invalid string property\");\n  endswitch\n\n  if (force_cell_output)\n    tf = {tf};\n  endif\n\nendfunction\n\n\n%!assert (isstrprop (\"abc123\", \"alpha\"), logical ([1, 1, 1, 0, 0, 0]))\n%!assert (isstrprop (\"abc123\", \"digit\"), logical ([0, 0, 0, 1, 1, 1]))\n%!assert (isstrprop (\"Hello World\", \"wspace\"), isspace (\"Hello World\"))\n%!assert (isstrprop (\"Hello World\", \"graphic\"), isgraph (\"Hello World\"))\n%!assert (isstrprop (char (\"AbC\", \"123\"), \"upper\"), logical ([1 0 1; 0 0 0]))\n%!assert (isstrprop (char (\"AbC\", \"123\"), \"upper\", 'ForceCellOutput', true),\n%!        {logical([1 0 1; 0 0 0])})\n%!assert (isstrprop ({\"AbC\", \"123\"}, \"lower\"),\n%!        {logical([0 1 0]), logical([0 0 0])})\n\n## Test input validation\n%!error <Invalid call> isstrprop ()\n%!error <Invalid call> isstrprop (\"abc\")\n%!error <Invalid call> isstrprop (\"abc\", 'alpha', 'ForceCellOutput')\n%!error <only accepted option is 'ForceCellOutput'>\n%! isstrprop ('a', 'alpha', ['ForceCellOutput';'ForceCellOutput'], true)\n%!error <only accepted option is 'ForceCellOutput'>\n%! isstrprop ('a', 'alpha', 'Foobar', true)\n%!error <FLAG must be a real scalar>\n%! isstrprop ('a', 'alpha', 'ForceCellOutput', [true, true])\n%!error <FLAG must be a real scalar>\n%! isstrprop ('a', 'alpha', 'ForceCellOutput', {true})\n%!error <invalid string property> isstrprop (\"abc123\", \"foo\")\n"
  },
  {
    "path": "scripts/strings/mat2str.m",
    "content": "########################################################################\n##\n## Copyright (C) 2002-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{s} =} mat2str (@var{x})\n## @deftypefnx {} {@var{s} =} mat2str (@var{x}, @var{n})\n## @deftypefnx {} {@var{s} =} mat2str (@var{x}, [@var{n1}, @var{n2}])\n## @deftypefnx {} {@var{s} =} mat2str (@dots{}, \"class\")\n## Format real, complex, and logical matrices as strings.\n##\n## The returned string may be used to reconstruct the original matrix by using\n## the @code{eval} function.\n##\n## The precision of the values is given by @var{n}.  If @var{n} is a scalar\n## then both real and imaginary parts of the matrix are printed to the same\n## precision.  Otherwise @code{@var{n}(1)} defines the precision of the real\n## part and @code{@var{n}(2)} defines the precision of the imaginary part.\n## The default for @var{n} is 15.\n##\n## If the argument @qcode{\"class\"} is given then the class of @var{x} is\n## included in the string in such a way that @code{eval} will result in the\n## construction of a matrix of the same class.\n##\n## @example\n## @group\n## mat2str (pi)\n##      @xresult{} \"3.14159265358979\"\n##\n## mat2str (pi, 5)\n##      @xresult{} \"3.1416\"\n##\n## mat2str ([ -1/3 + i/7; 1/3 - i/7 ], [4 2])\n##      @xresult{} \"[-0.3333+0.14i;0.3333-0.14i]\"\n##\n## mat2str ([ -1/3 +i/7; 1/3 -i/7 ], [4 2])\n##      @xresult{} \"[-0.3333+0i 0+0.14i;0.3333+0i -0-0.14i]\"\n##\n## mat2str (int16 ([1 -1]), \"class\")\n##      @xresult{} \"int16([1 -1])\"\n##\n## mat2str (logical (eye (2)))\n##      @xresult{} \"[true false;false true]\"\n##\n## isequal (x, eval (mat2str (x)))\n##      @xresult{} 1\n## @end group\n## @end example\n##\n## @seealso{sprintf, num2str, int2str}\n## @end deftypefn\n\nfunction s = mat2str (x, n = 15, cls = \"\")\n\n  if (nargin < 1 || ! (isnumeric (x) || islogical (x)))\n    print_usage ();\n  endif\n\n  if (ndims (x) > 2)\n    error (\"mat2str: X must be 2-D array\");\n  endif\n\n  if (nargin == 2 && ischar (n))\n    cls = n;\n    n = 15;\n  elseif (isempty (n))\n    n = 15;   # Default precision\n  elseif (numel (n) > 2)\n    error (\"mat2str: N must have only 1 or 2 elements\");\n  else\n    n = fix (n);\n  endif\n\n  x_islogical = islogical (x);\n  x_iscomplex = iscomplex (x);\n\n  if (x_iscomplex)\n    if (isscalar (n))\n      n = [n, n];\n    endif\n    if (any (! isfinite (imag (x(:)))))\n      fmt = sprintf (\"complex(%%.%dg,%%.%dg)\", n(1), n(2));\n    else\n      fmt = sprintf (\"%%.%dg%%+.%dgi\", n(1), n(2));\n    endif\n  elseif (x_islogical)\n    v = {\"false\", \"true\"};\n    fmt = \"%s\";\n  else\n    fmt = sprintf (\"%%.%dg\", n(1));\n  endif\n\n  nel = numel (x);\n\n  if (nel == 0)\n    ## Empty, only print brackets\n    s = \"[]\";\n  elseif (nel == 1)\n    ## Scalar X, don't print brackets\n    if (x_iscomplex)\n      s = sprintf (fmt, real (x), imag (x));\n    elseif (x_islogical)\n      s = v{x+1};\n    else\n      s = sprintf (fmt, x);\n    endif\n  else\n    ## Nonscalar X, print brackets\n    fmt = [fmt \" \"];\n    if (x_iscomplex)\n      t = x.';\n      s = sprintf (fmt, [real(t(:))'; imag(t(:))']);\n    elseif (x_islogical)\n      t = v(x.'+1);\n      s = cstrcat (sprintf (fmt, t{:}));\n    else\n      s = sprintf (fmt, x.');\n    endif\n\n    s = [\"[\" s];\n    s(end) = \"]\";\n    idx = strfind (s, \" \");\n    nc = columns (x);\n    s(idx(nc:nc:end)) = \";\";\n  endif\n\n  if (strcmp (\"class\", cls))\n    s = [class(x) \"(\" s \")\"];\n  endif\n\nendfunction\n\n\n%!assert (mat2str (0.7), \"0.7\")\n%!assert (mat2str (pi), \"3.14159265358979\")\n%!assert (mat2str (pi, 5), \"3.1416\")\n%!assert (mat2str (single (pi), 5, \"class\"), \"single(3.1416)\")\n%!assert (mat2str (complex (NaN, 2)), \"NaN+2i\")\n%!assert (mat2str ([-1/3 + i/7; 1/3 - i/7], [4 2]),\n%!        \"[-0.3333+0.14i;0.3333-0.14i]\")\n%!assert (mat2str ([-1/3 +i/7; 1/3 -i/7], [4 2]),\n%!        \"[-0.3333+0i 0+0.14i;0.3333+0i -0-0.14i]\")\n%!assert (mat2str (int16 ([1 -1]), \"class\"), \"int16([1 -1])\")\n%!assert (mat2str (true), \"true\")\n%!assert (mat2str (false), \"false\")\n%!assert (mat2str (logical (eye (2))), \"[true false;false true]\")\n%!assert (mat2str (logical ([0 1; 0 0])), \"[false true;false false]\")\n\n%!test <*67462>\n%! x = [complex(1,0); complex(0, Inf)];\n%! s = mat2str (x);\n%! y = eval (s);\n%! assert (y, x);\n\n## Test input validation\n%!error <Invalid call> mat2str ()\n%!error <Invalid call> mat2str ([\"Hello\"])\n%!error <X must be 2-D array> mat2str (ones (3,3,2))\n%!error <N must have only 1 or 2 elements> mat2str (ones (3,3), [1 2 3])\n"
  },
  {
    "path": "scripts/strings/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/base2dec.m \\\n  %reldir%/bin2dec.m \\\n  %reldir%/blanks.m \\\n  %reldir%/cstrcat.m \\\n  %reldir%/deblank.m \\\n  %reldir%/dec2base.m \\\n  %reldir%/dec2bin.m \\\n  %reldir%/dec2hex.m \\\n  %reldir%/endsWith.m \\\n  %reldir%/erase.m \\\n  %reldir%/hex2dec.m \\\n  %reldir%/index.m \\\n  %reldir%/isletter.m \\\n  %reldir%/isstring.m \\\n  %reldir%/isstrprop.m \\\n  %reldir%/mat2str.m \\\n  %reldir%/native2unicode.m \\\n  %reldir%/ostrsplit.m \\\n  %reldir%/regexptranslate.m \\\n  %reldir%/rindex.m \\\n  %reldir%/startsWith.m \\\n  %reldir%/str2num.m \\\n  %reldir%/strcat.m \\\n  %reldir%/strchr.m \\\n  %reldir%/strjoin.m \\\n  %reldir%/strjust.m \\\n  %reldir%/strsplit.m \\\n  %reldir%/strtok.m \\\n  %reldir%/strtrim.m \\\n  %reldir%/strtrunc.m \\\n  %reldir%/substr.m \\\n  %reldir%/unicode2native.m \\\n  %reldir%/untabify.m \\\n  %reldir%/validatestring.m\n\n%canon_reldir%dir = $(fcnfiledir)/strings\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/strings/native2unicode.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{utf8_str} =} native2unicode (@var{native_bytes}, @var{codepage})\n## @deftypefnx {} {@var{utf8_str} =} native2unicode (@var{native_bytes})\n## Convert byte stream @var{native_bytes} to UTF-8 using @var{codepage}.\n##\n## The numbers in the vector @var{native_bytes} are rounded and clipped to\n## integers between 0 and 255.  This byte stream is then mapped into the\n## code page given by the string @var{codepage} and returned in the string\n## @var{utf8_str}.  Octave uses UTF-8 as its internal encoding.  The string\n## @var{codepage} must be an identifier of a valid code page.  Examples for\n## valid code pages are @qcode{\"ISO-8859-1\"}, @qcode{\"Shift-JIS\"}, or\n## @qcode{\"UTF-16\"}.  For a list of supported code pages, see\n## @url{https://www.gnu.org/software/libiconv}.  If @var{codepage} is omitted\n## or empty, the system default codepage is used.\n##\n## If @var{native_bytes} is a string vector, it is returned as is.\n##\n## @seealso{unicode2native}\n## @end deftypefn\n\nfunction utf8_str = native2unicode (native_bytes, codepage = \"\")\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ischar (native_bytes))\n    utf8_str = native_bytes;\n    return;\n  endif\n\n  if (! isnumeric (native_bytes) || ! isvector (native_bytes))\n    error (\"native2unicode: NATIVE_BYTES must be a numeric vector\");\n  endif\n\n  if (! (ischar (codepage) && (isrow (codepage) || isempty (codepage))))\n    error (\"native2unicode: CODEPAGE must be a string\");\n  endif\n\n  ## Convert to uint8 which rounds and clips values to range [0, 255]3\n  native_bytes = uint8 (native_bytes);\n\n  utf8_str = __native2unicode__ (native_bytes, codepage);\n\n  if (! isrow (native_bytes))\n    utf8_str = utf8_str.';\n  endif\n\nendfunction\n\n\n## \"ЄЅІЇЈЉЊ\"\n%!testif HAVE_ICONV\n%! assert (double (native2unicode (164:170, 'ISO-8859-5')),\n%!         [208 132 208 133 208 134 208 135 208 136 208 137 208 138]);\n## [\"ЄЅІ\" 0 \"ЇЈЉЊ\"]\n%!testif HAVE_ICONV\n%! assert (double (native2unicode ([164:166 0 167:170], 'ISO-8859-5')),\n%!         [208 132 208 133 208 134 0 208 135 208 136 208 137 208 138]);\n\n%!assert (native2unicode (\"foobar\"), \"foobar\")\n%!assert <*54384> (double (native2unicode ([0 0 120.3 0 0 122.6 0 0])),\n%!                 [0 0 120 0 0 123 0 0])\n%!testif HAVE_ICONV <*64331>\n%! assert (! isempty (native2unicode (97:99)));\n%!testif HAVE_ICONV <*64331>\n%! assert (! isempty (native2unicode (97:99, \"\")));\n\n%!error <Invalid call> native2unicode ()\n%!error <called with too many inputs> native2unicode (1, 'ISO-8859-1', 'test')\n%!error <NATIVE_BYTES must be a numeric vector> native2unicode ([1 2; 3 4])\n%!error <NATIVE_BYTES must be a numeric vector> native2unicode ({1 2 3 4})\n%!error <CODEPAGE must be a string> native2unicode (164:170, 123)\n%!error <CODEPAGE must be a string> native2unicode (164:170, ['ISO-8859-1']')\n%!testif HAVE_ICONV\n%! fail (\"native2unicode (234, 'foo')\",\n%!       \"converting from codepage 'foo' to UTF-8\");\n"
  },
  {
    "path": "scripts/strings/ostrsplit.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{cstr}] =} ostrsplit (@var{s}, @var{sep})\n## @deftypefnx {} {[@var{cstr}] =} ostrsplit (@var{s}, @var{sep}, @var{strip_empty})\n## Split the string @var{s} using one or more separators @var{sep} and return\n## a cell array of strings.\n##\n## Consecutive separators and separators at boundaries result in empty\n## strings, unless @var{strip_empty} is true.  The default value of\n## @var{strip_empty} is false.\n##\n## 2-D character arrays are split at separators and at the original column\n## boundaries.\n##\n## Example:\n##\n## @example\n## @group\n## ostrsplit (\"a,b,c\", \",\")\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] = b\n##             [1,3] = c\n##           @}\n##\n## ostrsplit ([\"a,b\" ; \"cde\"], \",\")\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] = b\n##             [1,3] = cde\n##           @}\n## @end group\n## @end example\n## @seealso{strsplit, strtok}\n## @end deftypefn\n\nfunction cstr = ostrsplit (s, sep, strip_empty = false)\n\n  if (nargin < 2)\n    print_usage ();\n  elseif (! ischar (s) || ! ischar (sep))\n    error (\"ostrsplit: S and SEP must be string values\");\n  elseif (! isscalar (strip_empty))\n    error (\"ostrsplit: STRIP_EMPTY must be a scalar value\");\n  endif\n\n  if (isempty (s))\n    cstr = cell (size (s));\n  else\n    if (rows (s) > 1)\n      ## For 2-D arrays, add separator character at line boundaries\n      ## and transform to single string\n      s(:, end+1) = sep(1);\n      s = reshape (s.', 1, numel (s));\n      s(end) = [];\n    endif\n\n    ## Split s according to delimiter\n    if (isscalar (sep))\n      ## Single separator\n      idx = find (s == sep);\n    else\n      ## Multiple separators\n      idx = strchr (s, sep);\n    endif\n\n    ## Get substring lengths.\n    if (isempty (idx))\n      strlens = length (s);\n    else\n      strlens = [idx(1)-1, diff(idx)-1, numel(s)-idx(end)];\n    endif\n    ## Remove separators.\n    s(idx) = [];\n    if (strip_empty)\n      ## Omit zero lengths.\n      strlens = strlens(strlens != 0);\n    endif\n\n    ## Convert!\n    cstr = mat2cell (s, 1, strlens);\n  endif\n\nendfunction\n\n\n%!assert (ostrsplit (\"road to hell\", \" \"), {\"road\", \"to\", \"hell\"})\n%!assert (ostrsplit (\"road to^hell\", \" ^\"), {\"road\", \"to\", \"hell\"})\n%!assert (ostrsplit (\"road   to--hell\", \" -\", true), {\"road\", \"to\", \"hell\"})\n%!assert (ostrsplit (char (\"a,bc\", \",de\"), \",\"),\n%!        {\"a\", \"bc\", char(ones(1,0)), \"de \"})\n%!assert (ostrsplit (char (\"a,bc\", \",de\"), \",\", true), {\"a\", \"bc\", \"de \"})\n%!assert (ostrsplit (char (\"a,bc\", \",de\"), \", \", true), {\"a\", \"bc\", \"de\"})\n\n## Test input validation\n%!error <Invalid call> ostrsplit ()\n%!error ostrsplit (\"abc\")\n%!error ostrsplit (\"abc\", \"b\", true, 4)\n%!error <S and SEP must be string values> ostrsplit (123, \"b\")\n%!error <S and SEP must be string values> ostrsplit (\"abc\", 1)\n%!error <STRIP_EMPTY must be a scalar value> ostrsplit (\"abc\", \"def\", ones (3,3))\n"
  },
  {
    "path": "scripts/strings/regexptranslate.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{str} =} regexptranslate (@var{op}, @var{s})\n## Translate a string for use in a regular expression.\n##\n## This may include either wildcard replacement or special character escaping.\n##\n## The behavior is controlled by @var{op} which can take the following\n## values\n##\n## @table @asis\n## @item @qcode{\"wildcard\"}\n## The wildcard characters @code{.}, @code{*}, and @code{?} are replaced with\n## wildcards that are appropriate for a regular expression.  For example:\n##\n## @example\n## @group\n## regexptranslate (\"wildcard\", \"*.m\")\n##      @xresult{} '.*\\.m'\n## @end group\n## @end example\n##\n## @item @qcode{\"escape\"}\n## The characters @code{$.?[]}, that have special meaning for regular\n## expressions are escaped so that they are treated literally.  For example:\n##\n## @example\n## @group\n## regexptranslate (\"escape\", \"12.5\")\n##      @xresult{} '12\\.5'\n## @end group\n## @end example\n##\n## @end table\n## @seealso{regexp, regexpi, regexprep}\n## @end deftypefn\n\nfunction str = regexptranslate (op, s)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  if (! ischar (op))\n    error (\"regexptranslate: operation OP must be a string\");\n  endif\n\n  op = lower (op);\n  if (strcmp (\"wildcard\", op))\n    str = strrep (strrep (strrep (s, '.', '\\.'),\n                                     '*', '.*'),\n                                     '?', '.');\n  elseif (strcmp (\"escape\", op))\n    str = regexprep (s, '([][(){}.*+?^$|\\\\])', '\\\\$1');\n  else\n    error (\"regexptranslate: invalid operation OP\");\n  endif\n\nendfunction\n\n\n%!assert (regexptranslate (\"wildcard\", \"/a*b?c.\"), \"/a.*b.c\\\\.\")\n%!assert (regexptranslate (\"escape\", '^.?[abc]$'), '\\^\\.\\?\\[abc\\]\\$')\n\n## Test input validation\n%!error <Invalid call to regexptranslate> regexptranslate ()\n%!error <Invalid call to regexptranslate> regexptranslate (\"wildcard\")\n%!error <called with too many inputs> regexptranslate (\"a\", \"b\", \"c\")\n%!error <invalid operation> regexptranslate (\"foo\", \"abc\")\n%!error <operation OP must be a string> regexptranslate (10, \"abc\")\n"
  },
  {
    "path": "scripts/strings/rindex.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{n} =} rindex (@var{s}, @var{t})\n## Return the position of the last occurrence of the character string\n## @var{t} in the character string @var{s}, or 0 if no occurrence is\n## found.\n##\n## @var{s} may also be a string array or cell array of strings.\n##\n## For example:\n##\n## @example\n## @group\n## rindex (\"Teststring\", \"t\")\n##      @xresult{} 6\n## @end group\n## @end example\n##\n## The @code{rindex} function is equivalent to @code{index} with\n## @var{direction} set to @qcode{\"last\"}.\n##\n## @seealso{find, index}\n## @end deftypefn\n\nfunction n = rindex (s, t)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  n = index (s, t, \"last\");\n\nendfunction\n\n\n%!assert (rindex (\"foobarbaz\", \"b\"), 7)\n%!assert (rindex (\"foobarbaz\", \"o\"), 3)\n\n%!test\n%! str = char (\"Hello\", \"World\", \"Goodbye\", \"World\");\n%! assert (rindex (str, \"o\"), [5; 2; 3; 2]);\n%! str = cellstr (str);\n%! assert (rindex (str, \"o\"), [5; 2; 3; 2]);\n\n## Test input validation\n%!error <Invalid call> rindex ()\n%!error rindex (\"foo\")\n%!error rindex (\"foo\", \"bar\", \"last\")\n"
  },
  {
    "path": "scripts/strings/startsWith.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{retval} =} startsWith (@var{str}, @var{pattern})\n## @deftypefnx {} {@var{retval} =} startsWith (@var{str}, @var{pattern}, \"IgnoreCase\", @var{ignore_case})\n## Check whether string(s) start with pattern(s).\n##\n## Return an array of logical values that indicates which string(s) in the\n## input @var{str} (a single string or cell array of strings) begin with\n## the input @var{pattern} (a single string or cell array of strings).\n##\n## If the value of the parameter @qcode{\"IgnoreCase\"} is true, then the\n## function will ignore the letter case of @var{str} and @var{pattern}.  By\n## default, the comparison is case sensitive.\n##\n## Examples:\n##\n## @example\n## @group\n## ## one string and one pattern while considering case\n## startsWith (\"hello\", \"he\")\n##       @xresult{}  1\n## @end group\n##\n## @group\n## ## one string and one pattern while ignoring case\n## startsWith (\"hello\", \"HE\", \"IgnoreCase\", true)\n##       @xresult{}  1\n## @end group\n##\n## @group\n## ## multiple strings and multiple patterns while considering case\n## startsWith (@{\"lab work.pptx\", \"data.txt\", \"foundations.ppt\"@},\n##             @{\"lab\", \"data\"@})\n##       @xresult{}  1  1  0\n## @end group\n##\n## @group\n## ## multiple strings and one pattern while considering case\n## startsWith (@{\"DATASHEET.ods\", \"data.txt\", \"foundations.ppt\"@},\n##             \"data\", \"IgnoreCase\", false)\n##       @xresult{}  0  1  0\n## @end group\n##\n## @group\n## ## multiple strings and one pattern while ignoring case\n## startsWith (@{\"DATASHEET.ods\", \"data.txt\", \"foundations.ppt\"@},\n##             \"data\", \"IgnoreCase\", true)\n##       @xresult{}  1  1  0\n## @end group\n## @end example\n##\n## @seealso{endsWith, regexp, strncmp, strncmpi}\n## @end deftypefn\n\nfunction retval = startsWith (str, pattern, IgnoreCase, ignore_case)\n\n  if (nargin != 2 && nargin != 4)\n    print_usage ();\n  endif\n\n  ## Validate input str and pattern\n  if (! (iscellstr (str) || ischar (str)))\n    error (\"startsWith: STR must be a string or cell array of strings\");\n  endif\n  if (! (iscellstr (pattern) || ischar (pattern)))\n    error (\"startsWith: PATTERN must be a string or cell array of strings\");\n  endif\n\n  str = cellstr (str);\n  pattern = cellstr (pattern);\n\n  if (nargin == 2)\n    ignore_case = false;\n  else\n    ## For Matlab compatibility accept any abbreviation of 3rd argument\n    if (! ischar (IgnoreCase) || isempty (IgnoreCase)\n        || ! strncmpi (IgnoreCase, \"IgnoreCase\", length (IgnoreCase)))\n      error ('startsWith: third input must be \"IgnoreCase\"');\n    endif\n\n    if (! isscalar (ignore_case) || ! isreal (ignore_case))\n      error ('startsWith: \"IgnoreCase\" value must be a logical scalar');\n    endif\n    ignore_case = logical (ignore_case);\n  endif\n\n  retval = false (size (str));\n  if (ignore_case)\n    for j = 1:numel (pattern)\n      retval |= strncmpi (str, pattern{j}, length (pattern{j}));\n    endfor\n  else\n    for j = 1:numel (pattern)\n      retval |= strncmp (str, pattern{j}, length (pattern{j}));\n    endfor\n  endif\n\nendfunction\n\n\n## Test simple use with one string and one pattern\n%!assert (startsWith (\"hello\", \"he\"))\n%!assert (! startsWith (\"hello\", \"HE\"))\n%!assert (startsWith (\"hello\", \"HE\", \"i\", 5))\n%!assert (! startsWith (\"hello\", \"no\"))\n\n## Test multiple strings with a single pattern\n%!test\n%! str = {\"data science\", \"dataSheet.ods\", \"myFunc.m\"; \"foundations.ppt\", ...\n%!        \"results.txt\", \"myFile.odt\"};\n%! pattern = \"data\";\n%! expected = [true, true, false; false, false, false];\n%! assert (startsWith (str, pattern), expected);\n\n## Test multiple strings with multiple patterns\n%!test\n%! str = {\"lab work.pptx\", \"myFile.odt\", \"data.txt\", \"foundations.ppt\"};\n%! pattern = {\"lab\", \"data\"};\n%! expected = [true, false, true, false];\n%! assert (startsWith (str, pattern), expected);\n\n## Test IgnoreCase\n%!test\n%! str = {\"DATASHEET.ods\", \"myFile.odt\", \"data.txt\", \"foundations.ppt\"};\n%! pattern = \"data\";\n%! expected_ignore = [true, false, true, false];\n%! expected_wo_ignore = [false, false, true, false];\n%! assert (startsWith (str, pattern, \"IgnoreCase\", true), expected_ignore);\n%! assert (startsWith (str, pattern, \"IgnoreCase\", false), expected_wo_ignore);\n%! assert (startsWith (str, pattern, \"I\", 500), expected_ignore);\n%! assert (startsWith (str, pattern, \"iG\", 0), expected_wo_ignore);\n\n## Test input validation\n%!error <Invalid call> startsWith ()\n%!error startsWith (\"A\")\n%!error startsWith (\"A\", \"B\", \"C\")\n%!error startsWith (\"A\", \"B\", \"C\", \"D\", \"E\")\n%!error <STR must be a string> startsWith (152, \"hi\")\n%!error <STR must be a .* cell array of strings> startsWith ({152}, \"hi\")\n%!error <PATTERN must be a string> startsWith (\"hi\", 152)\n%!error <PATTERN must be a .* cell array of strings> startsWith (\"hi\", {152})\n%!error <third input must be \"IgnoreCase\"> startsWith (\"hello\", \"he\", 1, 1)\n%!error <third input must be \"IgnoreCase\"> startsWith (\"hello\", \"he\", \"\", 1)\n%!error <third input must be \"IgnoreCase\"> startsWith (\"hello\", \"he\", \"foo\", 1)\n%!error <\"IgnoreCase\" value must be a logical scalar>\n%! startsWith (\"hello\", \"hi\", \"i\", \"true\");\n%!error <\"IgnoreCase\" value must be a logical scalar>\n%! startsWith (\"hello\", \"hi\", \"i\", {true});\n"
  },
  {
    "path": "scripts/strings/str2num.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{x} =} str2num (@var{s})\n## @deftypefnx {} {[@var{x}, @var{state}] =} str2num (@var{s})\n## Convert the string (or character array) @var{s} to a number (or an array).\n##\n## Examples:\n##\n## @example\n## @group\n## str2num (\"3.141596\")\n##       @xresult{} 3.141596\n##\n## str2num ([\"1, 2, 3\"; \"4, 5, 6\"])\n##       @xresult{} 1  2  3\n##          4  5  6\n## @end group\n## @end example\n##\n## The optional second output, @var{state}, is logically true when the\n## conversion is successful.  If the conversion fails the numeric output,\n## @var{x}, is empty and @var{state} is false.\n##\n## @strong{Caution:} As @code{str2num} uses the @code{eval} function to do the\n## conversion, @code{str2num} will execute any code contained in the string\n## @var{s}.  Use @code{str2double} for a safer and faster conversion.\n##\n## For cell array of strings use @code{str2double}.\n## @seealso{str2double, eval}\n## @end deftypefn\n\nfunction [m, state] = str2num (s)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! ischar (s))\n    error (\"str2num: S must be a string or string array\");\n  endif\n\n  s(:, end+1) = \";\";\n  s = sprintf (\"m = [%s];\", reshape (s', 1, numel (s)));\n  state = true;\n  ## Swallow any errors from eval (bug #55939).\n  try\n    eval (s);\n  catch\n    m = [];\n    state = false;\n  end_try_catch\n\n  if (ischar (m))\n    m = [];\n    state = false;\n  endif\n\nendfunction\n\n\n%!assert (str2num (\"-1.3e2\"), -130)\n%!assert (str2num (\"[1, 2; 3, 4]\"), [1, 2; 3, 4])\n%!assert (str2num (\"1.000444\"), 1.000444)\n\n%!assert (str2num (\"1e999\"), Inf)\n%!assert (str2num (\"-1e999\"), -Inf)\n\n%!test\n%! [x, state] = str2num (\"pi\");\n%! assert (state);\n%! [x, state] = str2num (\"Hello World\");\n%! assert (! state);\n\n## Test input validation\n%!error <Invalid call> str2num ()\n%!error <S must be a string> str2num ({\"string\"})\n"
  },
  {
    "path": "scripts/strings/strcat.m",
    "content": "########################################################################\n##\n## Copyright (C) 1994-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{str} =} strcat (@var{s1}, @var{s2}, @dots{})\n## Return a string containing all the arguments concatenated horizontally.\n##\n## If the arguments are cell strings, @code{strcat} returns a cell string\n## with the individual cells concatenated.  For numerical input, each element\n## is converted to the corresponding ASCII character.  Trailing white space\n## for any character string input is eliminated before the strings are\n## concatenated.  Note that cell string values do @strong{not} have\n## whitespace trimmed.\n##\n## For example:\n##\n## @example\n## @group\n## strcat (\"|\", \" leading space is preserved\", \"|\")\n##     @xresult{} | leading space is preserved|\n## @end group\n## @end example\n##\n## @example\n## @group\n## strcat (\"|\", \"trailing space is eliminated \", \"|\")\n##     @xresult{} |trailing space is eliminated|\n## @end group\n## @end example\n##\n## @example\n## @group\n## strcat (\"homogeneous space |\", \"  \", \"| is also eliminated\")\n##     @xresult{} homogeneous space || is also eliminated\n## @end group\n## @end example\n##\n## @example\n## @group\n## s = [ \"ab\"; \"cde\" ];\n## strcat (s, s, s)\n##     @xresult{}\n##         \"ababab   \"\n##         \"cdecdecde\"\n## @end group\n## @end example\n##\n## @example\n## @group\n## s = @{ \"ab\"; \"cd \" @};\n## strcat (s, s, s)\n##     @xresult{}\n##         @{\n##           [1,1] = ababab\n##           [2,1] = cd cd cd\n##         @}\n## @end group\n## @end example\n##\n## @seealso{cstrcat, char, strvcat}\n## @end deftypefn\n\nfunction str = strcat (varargin)\n\n  if (nargin == 0)\n    str = \"\";\n  elseif (nargin == 1)\n    if (iscellstr (varargin{1}))\n      str = varargin{1};\n    elseif (isreal (varargin{1}) || ischar (varargin{1}))\n      str = char (cellstr (varargin{1}));\n    else\n      error (\"strcat: inputs must be strings or cells of strings\");\n    endif\n  else\n    ## Convert to cells of strings\n    uo = \"uniformoutput\";\n    reals = cellfun (\"isreal\", varargin);\n    if (any (reals))\n      varargin(reals) = cellfun (\"char\", varargin(reals), uo, false);\n    endif\n    chars = cellfun (\"isclass\", varargin, \"char\");\n    allchar = all (chars);\n    varargin(chars) = cellfun (\"cellstr\", varargin(chars), uo, false);\n    if (! all (cellfun (\"isclass\", varargin, \"cell\")))\n      error (\"strcat: inputs must be strings or cells of strings\");\n    endif\n\n    ## We don't actually need to bring all cells to common size, because\n    ## cellfun can now expand scalar cells.\n    err = common_size (varargin{:});\n\n    if (err)\n      error (\"strcat: arguments must be the same size, or be scalars\");\n    endif\n\n    ## Cellfun handles everything for us.\n    str = cellfun (\"horzcat\", varargin{:}, uo, false);\n\n    if (allchar)\n      ## If all inputs were strings, return strings.\n      str = char (str);\n    endif\n  endif\n\nendfunction\n\n\n## test the dimensionality\n## 1-D\n%!assert (strcat (\"ab \", \"ab \"), \"abab\")\n%!assert (strcat ({\"ab \"}, \"ab \"), {\"ab ab\"})\n%!assert (strcat (\"ab \", {\"ab \"}), {\"abab \"})\n%!assert (strcat ({\"ab \"}, {\"ab \"}), {\"ab ab \"})\n%!assert (strcat (\"\", \"ab\"), \"ab\")\n%!assert (strcat (\"\", {\"ab\"}, {\"\"}), {\"ab\"})\n## 2-D\n%!assert (strcat ([\"ab \";\"cde\"], [\"ab \";\"cde\"]), [\"abab  \";\"cdecde\"])\n\n## test for deblanking implied trailing spaces of character input\n%!assert (strcat (\"foo\", \"bar\"), \"foobar\")\n%!assert (strcat ([\"a \"; \"bb\"], [\"foo\"; \"bar\"]), [\"afoo \"; \"bbbar\"])\n\n## test for mixing character and cell inputs\n%!assert (strcat (\"a\", {\"bc\", \"de\"}, \"f\"), {\"abcf\", \"adef\"})\n\n## test for scalar strings with vector strings\n%!assert (strcat ([\"a\"; \"b\"], \"c\"), [\"ac\"; \"bc\"])\n\n## test with cells with strings of differing lengths\n%!assert (all (strcmp (strcat ({\"a\", \"bb\"}, \"ccc\"), {\"accc\", \"bbccc\"})))\n%!assert (all (strcmp (strcat (\"a\", {\"bb\", \"ccc\"}), {\"abb\", \"accc\"})))\n\n## test with a single string or cell input\n%!assert <*49094> (strcat (\"foo    \"), \"foo\")\n%!assert <*49094> (strcat ({\"foo\"}), {\"foo\"})\n\n%!assert (strcat (1), char (1))\n%!assert (strcat (1, 2), strcat (char (1), char (2)))\n%!assert (strcat (\"\", 2), strcat ([], char (2)))\n\n%!assert (strcat (), \"\")\n"
  },
  {
    "path": "scripts/strings/strchr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{idx} =} strchr (@var{str}, @var{chars})\n## @deftypefnx {} {@var{idx} =} strchr (@var{str}, @var{chars}, @var{n})\n## @deftypefnx {} {@var{idx} =} strchr (@var{str}, @var{chars}, @var{n}, @var{direction})\n## @deftypefnx {} {[@var{i}, @var{j}] =} strchr (@dots{})\n## Search through the string @var{str} for occurrences of characters from the\n## set @var{chars}.\n##\n## The return value(s), as well as the @var{n} and @var{direction} arguments\n## behave identically as in @code{find}.\n##\n## This will be faster than using @code{regexp} in most cases.\n##\n## @seealso{find}\n## @end deftypefn\n\nfunction varargout = strchr (str, chars, varargin)\n\n  if (nargin < 2 || nargin > 4)\n    print_usage ();\n  elseif (! ischar (str))\n    error (\"strchr: STR argument must be a string or string array\");\n  elseif (! ischar (chars))\n    error (\"strchr: CHARS argument must be a string\");\n  endif\n\n  if (isempty (chars))\n    mask = false (size (str));\n  elseif (length (chars) <= 4)\n    ## With a few characters, it pays off to build the mask incrementally.\n    ## We do it via a for loop to save memory.\n    mask = str == chars(1);\n    for i = 2:length (chars)\n      mask |= str == chars(i);\n    endfor\n  else\n    ## Index the str into a mask of valid values.\n    ## This is slower than it could be because of the +1 issue.\n    f = false (256, 1);\n    f(uint8 (chars) + 1) = true;\n    ## Default goes via double -- unnecessarily long.\n    si = uint32 (str);\n    ## in-place is faster than str+1\n    ++si;\n    mask = reshape (f(si), size (str));\n  endif\n\n  varargout = cell (1, nargout);\n  varargout{1} = [];\n  [varargout{:}] = find (mask, varargin{:});\n\nendfunction\n\n\n%!assert (strchr (\"Octave is the best software\", \"\"), zeros (1,0))\n%!assert (strchr (\"Octave is the best software\", \"best\"),\n%!        [3, 6, 9, 11, 13, 15, 16, 17, 18, 20, 23, 27])\n%!assert (strchr (\"Octave is the best software\", \"software\"),\n%!        [3, 4, 6, 9, 11, 13, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27])\n\n## Test input validation\n%!error <Invalid call> strchr ()\n%!error <Invalid call> strchr (1)\n%!error <Invalid call> strchr (\"s\", \"a\", 1, \"last\", 5)\n%!error <STR argument must be a string> strchr (1, \"aeiou\")\n%!error <CHARS argument must be a string> strchr (\"aeiou\", 1)\n"
  },
  {
    "path": "scripts/strings/strjoin.m",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{str} =} strjoin (@var{cstr})\n## @deftypefnx {} {@var{str} =} strjoin (@var{cstr}, @var{delimiter})\n## Join the elements of the cell string array, @var{cstr}, into a single\n## string.\n##\n## If no @var{delimiter} is specified, the elements of @var{cstr} are\n## separated by a space.\n##\n## If @var{delimiter} is specified as a string, the cell string array is\n## joined using the string.  Escape sequences are supported.\n##\n## If @var{delimiter} is a cell string array whose length is one less than\n## @var{cstr}, then the elements of @var{cstr} are joined by interleaving the\n## cell string elements of @var{delimiter}.  Escape sequences are not\n## supported.\n##\n## @example\n## @group\n## strjoin (@{'Octave','Scilab','Lush','Yorick'@}, '*')\n##       @xresult{} 'Octave*Scilab*Lush*Yorick'\n## @end group\n## @end example\n## @seealso{strsplit}\n## @end deftypefn\n\nfunction rval = strjoin (cstr, delimiter = \" \")\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! (iscellstr (cstr) && (ischar (delimiter) || iscellstr (delimiter))))\n    print_usage ();\n  endif\n\n  if (numel (cstr) == 1)\n    rval = cstr{1};\n    return;\n  endif\n\n  if (ischar (delimiter))\n    delimiter = do_string_escapes (delimiter);\n    delimiter = {delimiter};\n  endif\n\n  num = numel (cstr);\n  if (numel (delimiter) == 1 && num > 1)\n    delimiter = repmat (delimiter, 1, num);\n    delimiter(end) = {''};\n  elseif (num > 0 && numel (delimiter) != num - 1)\n    error (\"Octave:strjoin:cellstring_delimiter_mismatch\",\n      \"strjoin: the number of delimiters does not match the number of strings\");\n  else\n    delimiter(end+1) = {''};\n  endif\n\n  if (num == 0)\n    rval = '';\n  else\n    rval = [[cstr(:).'; delimiter(:).']{:}];\n  endif\n\nendfunction\n\n\n%!assert (strjoin ({\"hello\"}, \"-\"), \"hello\")\n%!assert (strjoin ({\"hello\", \"world\"}), \"hello world\")\n%!assert (strjoin ({\"Octave\", \"Scilab\", \"Lush\", \"Yorick\"}, \"*\"),\n%!  \"Octave*Scilab*Lush*Yorick\")\n%!assert (strjoin ({\"space\", \"comma\", \"dash\", \"semicolon\", \"done\"},\n%!  {\" \", \",\", \"-\", \";\"}), \"space comma,dash-semicolon;done\")\n%!assert (strjoin ({'Octave','Scilab'},'\\n'), \"Octave\\nScilab\")\n%!assert (strjoin ({'Octave','Scilab'},{'\\n'}), \"Octave\\\\nScilab\")\n%!assert (strjoin ({},'foo'), \"\")\n"
  },
  {
    "path": "scripts/strings/strjust.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{str} =} strjust (@var{s})\n## @deftypefnx {} {@var{str} =} strjust (@var{s}, @var{pos})\n## Return the text, @var{s}, justified according to @var{pos}, which may\n## be @qcode{\"left\"}, @qcode{\"center\"}, or @qcode{\"right\"}.\n##\n## If @var{pos} is omitted it defaults to @qcode{\"right\"}.\n##\n## Null characters are replaced by spaces.  All other character data are\n## treated as non-white space.\n##\n## Example:\n##\n## @example\n## @group\n## strjust ([\"a\"; \"ab\"; \"abc\"; \"abcd\"])\n##      @xresult{}\n##         \"   a\"\n##         \"  ab\"\n##         \" abc\"\n##         \"abcd\"\n## @end group\n## @end example\n## @seealso{deblank, strrep, strtrim, untabify}\n## @end deftypefn\n\nfunction str = strjust (s, pos = \"right\")\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! ischar (s) || ndims (s) > 2)\n    error (\"strjust: S must be a string or 2-D character matrix\");\n  endif\n\n  if (isempty (s))\n    str = s;\n    return;\n  endif\n\n  ## Apparently, Matlab considers nulls to be blanks as well; however, does\n  ## not preserve the nulls, but rather converts them to blanks.  That's a\n  ## bit unexpected, but it allows simpler processing, because we can move\n  ## just the nonblank characters.  So we'll do the same here.\n\n  [nr, nc] = size (s);\n  ## Find the indices of all nonblanks.\n  nonbl = s != \" \" & s != \"\\0\";\n  [idx, jdx] = find (nonbl);\n\n  if (strcmpi (pos, \"right\"))\n    ## We wish to find the maximum column index for each row.  Because jdx is\n    ## sorted, we can take advantage of the fact that assignment is processed\n    ## sequentially and for duplicate indices the last value will remain.\n    maxs = repmat (nc, [nr, 1]);\n    maxs(idx) = jdx;\n    shift = nc - maxs;\n  elseif (strcmpi (pos, \"left\"))\n    ## See above for explanation.\n    mins = ones (nr, 1);\n    mins(flipud (idx(:))) = flipud (jdx(:));\n    shift = 1 - mins;\n  else\n    ## Use both of the above to achieve centering.\n    mins = ones (nr, 1);\n    mins(flipud (idx(:))) = flipud (jdx(:));\n    maxs = repmat (nc, [nr, 1]);\n    maxs(idx) = jdx;\n    shift = floor ((nc + 1 - maxs - mins) / 2);\n  endif\n\n  ## Adjust the column indices.\n  jdx += shift(idx);\n\n  ## Create a blank matrix and position the nonblank characters.\n  str = repmat (\" \", nr, nc);\n  str(sub2ind ([nr, nc], idx, jdx)) = s(nonbl);\n\nendfunction\n\n\n%!assert (strjust (char (\"a\", \"ab\", \"abc\", \"abcd\")),\n%!        [\"   a\";\"  ab\"; \" abc\"; \"abcd\"])\n%!assert (strjust (char (\" a\", \"  ab\", \"abc\", \"abcd\"), \"left\"),\n%!        [\"a   \"; \"ab  \"; \"abc \"; \"abcd\"])\n%!assert (strjust (char (\"a\", \"ab\", \"abc\", \"abcd\"), \"CENTER\"),\n%!        [\" a  \"; \" ab \"; \"abc \"; \"abcd\"])\n%!assert (strjust ([\"\";\"\"]), \"\")\n\n## Test input validation\n%!error <Invalid call to strjust> strjust ()\n%!error <called with too many inputs> strjust ([\"a\";\"ab\"], \"center\", 1)\n%!error <S must be a string> strjust (ones (3,3))\n%!error <S must be a string> strjust (char (ones (3,3,3)))\n"
  },
  {
    "path": "scripts/strings/strsplit.m",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{cstr}] =} strsplit (@var{str})\n## @deftypefnx {} {[@var{cstr}] =} strsplit (@var{str}, @var{del})\n## @deftypefnx {} {[@var{cstr}] =} strsplit (@dots{}, @var{name}, @var{value})\n## @deftypefnx {} {[@var{cstr}, @var{matches}] =} strsplit (@dots{})\n## Split the string @var{str} using the delimiters specified by @var{del} and\n## return a cell string array of substrings.\n##\n## If a delimiter is not specified the string is split at whitespace\n## @code{@{\" \", \"\\f\", \"\\n\", \"\\r\", \"\\t\", \"\\v\"@}}.  Otherwise, the delimiter,\n## @var{del} must be a string or cell array of strings.  By default,\n## consecutive delimiters in the input string @var{s} are collapsed into one\n## resulting in a single split.\n##\n## Supported @var{name}/@var{value} pair arguments are:\n##\n## @itemize\n## @item @var{collapsedelimiters} which may take the value of @code{true}\n## (default) or @code{false}.\n##\n## @item @var{delimitertype} which may take the value of @qcode{\"simple\"}\n## (default) or @nospell{@qcode{\"regularexpression\"}}.  A simple delimiter\n## matches the text exactly as written.  Otherwise, the syntax for regular\n## expressions outlined in @code{regexp} is used.\n## @end itemize\n##\n## The optional second output, @var{matches}, returns the delimiters which were\n## matched in the original string.\n##\n## Examples with simple delimiters:\n##\n## @example\n## strsplit (\"a b c\")\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] = b\n##             [1,3] = c\n##           @}\n##\n## strsplit (\"a,b,c\", \",\")\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] = b\n##             [1,3] = c\n##           @}\n##\n## strsplit (\"a foo b,bar c\", @{\" \", \",\", \"foo\", \"bar\"@})\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] = b\n##             [1,3] = c\n##           @}\n##\n## strsplit (\"a,,b, c\", @{\",\", \" \"@}, \"collapsedelimiters\", false)\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] =\n##             [1,3] = b\n##             [1,4] =\n##             [1,5] = c\n##           @}\n##\n## @end example\n##\n## Examples with @nospell{regularexpression} delimiters:\n##\n## @smallexample\n## strsplit (\"a foo b,bar c\", ',|\\s|foo|bar', ...\n##           \"delimitertype\", \"regularexpression\")\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] = b\n##             [1,3] = c\n##           @}\n##\n## strsplit (\"a,,b, c\", '[, ]', \"collapsedelimiters\", false, ...\n##           \"delimitertype\", \"regularexpression\")\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] =\n##             [1,3] = b\n##             [1,4] =\n##             [1,5] = c\n##           @}\n##\n## strsplit (\"a,\\t,b, c\", @{',', '\\s'@}, \"delimitertype\", \"regularexpression\")\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] = b\n##             [1,3] = c\n##           @}\n##\n## strsplit (\"a,\\t,b, c\", @{',', ' ', '\\t'@}, \"collapsedelimiters\", false)\n##       @xresult{}\n##           @{\n##             [1,1] = a\n##             [1,2] =\n##             [1,3] =\n##             [1,4] = b\n##             [1,5] =\n##             [1,6] = c\n##           @}\n## @end smallexample\n##\n## @seealso{ostrsplit, strjoin, strtok, regexp}\n## @end deftypefn\n\nfunction [cstr, matches] = strsplit (str, del, varargin)\n\n  args.collapsedelimiters = true;\n  args.delimitertype = \"simple\";\n\n  [reg, params] = parseparams (varargin);\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (numel (reg) > 1)\n    print_usage ();\n  elseif (numel (reg) == 1)\n    ## This is undocumented behavior to accept a logical 3rd arg.\n    if (islogical (reg{1}))\n      args.collapsedelimiters = reg{1};\n    else\n      print_usage ();\n    endif\n  endif\n  fields = fieldnames (args);\n  for n = 1:2:numel (params)\n    if (any (strcmpi (params{n}, fields)))\n      args.(lower (params{n})) = params{n+1};\n    elseif (ischar (varargin{n}))\n      error (\"Octave:strsplit:invalid_parameter_name\",\n             \"strsplit: invalid parameter name, '%s'\", varargin{n});\n    else\n      print_usage ();\n    endif\n  endfor\n\n  ## Save the length of the \"delimitertype\" parameter\n  length_deltype = length (args.delimitertype);\n\n  if (nargin == 1 || (nargin > 1 && islogical (del)))\n    if (nargin > 1)\n      ## Second input is the \"collapsedelimiters\" parameter\n      args.collapsedelimiters = del;\n    endif\n    ## Set proper default for the delimiter type\n    if (strncmpi (args.delimitertype, \"simple\", length_deltype))\n      del = {\" \", \"\\f\", \"\\n\", \"\\r\", \"\\t\", \"\\v\"};\n    else\n      del = '\\s';\n    endif\n  endif\n\n  if (! ischar (str) || (! ischar (del) && ! iscellstr (del)))\n    error (\"strsplit: S and DEL must be string values\");\n  elseif (! isempty (str) && ! isrow (str))\n    error (\"strsplit: S must be a char row vector\");\n  elseif (! isscalar (args.collapsedelimiters))\n    error (\"strsplit: COLLAPSEDELIMITERS must be a scalar value\");\n  endif\n\n  if (strncmpi (args.delimitertype, \"simple\", length_deltype))\n    is_simple = true;\n  elseif (strncmpi (args.delimitertype, \"regularexpression\", length_deltype))\n    is_simple = false;\n  else\n    error (\"Octave:strsplit:invalid_delimitertype\", \"strsplit: Invalid DELIMITERTYPE\");\n  endif\n\n  if (is_simple)\n    if (iscellstr (del))\n      del = cellfun ('do_string_escapes', del, \"uniformoutput\", false);\n    else\n      del = do_string_escapes (del);\n    endif\n    ## Escape characters which have a special meaning in regexp.\n    del = regexprep (del, '([{}()[\\]^$.*?+|\\\\])', '\\\\$1');\n  endif\n\n  if (isempty (str))\n    cstr = {str};\n  else\n    if (iscellstr (del))\n      del = sprintf (\"%s|\", del{:});\n      del(end) = [];\n    endif\n    if (args.collapsedelimiters)\n      del = [ \"(\" del \")+\" ];\n    endif\n    [cstr, matches] = regexp (str, del, \"split\", \"match\");\n  endif\n\nendfunction\n\n\n%!shared str\n%! str = \"The rain in Spain stays mainly in the plain.\";\n\n## Split on all whitespace.\n%!assert (strsplit (str), {\"The\", \"rain\", \"in\", \"Spain\", \"stays\", ...\n%!                         \"mainly\", \"in\", \"the\", \"plain.\"})\n## Split on \"ain\".\n%!assert (strsplit (str, \"ain\"), {\"The r\", \" in Sp\", \" stays m\", ...\n%!                                \"ly in the pl\", \".\"})\n## Split on \" \" and \"ain\" (treating multiple delimiters as one).\n%!test\n%! s = strsplit (str, '\\s|ain', true, \"delimitertype\", \"r\");\n%! assert (s, {\"The\", \"r\", \"in\", \"Sp\", \"stays\", ...\n%!             \"m\", \"ly\", \"in\", \"the\", \"pl\", \".\"});\n%!test\n%! s = strsplit (str, '\\s|ain', true, \"delimitertype\", \"r\");\n%! assert (s, {\"The\", \"r\", \"in\", \"Sp\", \"stays\", ...\n%!             \"m\", \"ly\", \"in\", \"the\", \"pl\", \".\"});\n%!test\n%! [s, m] = strsplit (str, {'\\s', 'ain'}, true, \"delimitertype\", \"r\");\n%! assert (s, {\"The\", \"r\", \"in\", \"Sp\", \"stays\", ...\n%!             \"m\", \"ly\", \"in\", \"the\", \"pl\", \".\"});\n%! assert (m, {\" \", \"ain \", \" \", \"ain \", \" \", \"ain\", \" \", \" \", \" \", \"ain\"});\n## Split on \" \" and \"ain\", and treat multiple delimiters separately.\n%!test\n%! [s, m] = strsplit (str, {\" \", \"ain\"}, \"collapsedelimiters\", false);\n%! assert (s, {\"The\", \"r\", \"\", \"in\", \"Sp\", \"\", \"stays\", ...\n%!             \"m\", \"ly\", \"in\", \"the\", \"pl\", \".\"});\n%! assert (m, {\" \", \"ain\", \" \", \" \", \"ain\", \" \", \" \", \"ain\", ...\n%!             \" \", \" \", \" \", \"ain\"});\n\n%!assert (strsplit (\"road to hell\"), {\"road\", \"to\", \"hell\"})\n%!assert (strsplit (\"road to hell\", \" \"), {\"road\", \"to\", \"hell\"})\n%!assert (strsplit (\"road to^hell\", {\" \",\"^\"}), {\"road\", \"to\", \"hell\"})\n%!assert (strsplit (\"road   to--hell\", {\" \",\"-\"}, true), {\"road\", \"to\", \"hell\"})\n%!assert (strsplit ([\"a,bc,,de\"], \",\", false, \"delimitertype\", \"s\"),\n%!        {\"a\", \"bc\", \"\", \"de\"})\n%!assert (strsplit ([\"a,bc,,de\"], \",\", false), {\"a\", \"bc\", \"\", \"de\"})\n%!assert (strsplit ([\"a,bc,de\"], \",\", true), {\"a\", \"bc\", \"de\"})\n%!assert (strsplit ([\"a,bc,de\"], {\",\",\" \"}, true), {\"a\", \"bc\", \"de\"})\n\n%!assert (strsplit (\"road to hell\", \" \", \"delimitertype\", \"r\"),\n%!        {\"road\", \"to\", \"hell\"})\n%!assert (strsplit (\"road to^hell\", '\\^| ', \"delimitertype\", \"r\"),\n%!        {\"road\", \"to\", \"hell\"})\n%!assert (strsplit (\"road to^hell\", \"[ ^]\", \"delimitertype\", \"r\"),\n%!        {\"road\", \"to\", \"hell\"})\n%!assert (strsplit (\"road   to--hell\", \"[ -]\", false, \"delimitertype\", \"r\"),\n%!        {\"road\", \"\", \"\", \"to\", \"\", \"hell\"})\n%!assert (strsplit ([\"a,bc,de\"], \",\", \"delimitertype\", \"r\"), {\"a\", \"bc\", \"de\"})\n%!assert (strsplit ([\"a,bc,,de\"], \",\", false, \"delimitertype\", \"r\"),\n%!        {\"a\", \"bc\", \"\", \"de\"})\n%!assert (strsplit ([\"a,bc,de\"], \",\", true, \"delimitertype\", \"r\"),\n%!        {\"a\", \"bc\", \"de\"})\n%!assert (strsplit ([\"a,bc,de\"], \"[, ]\", true, \"delimitertype\", \"r\"),\n%!        {\"a\", \"bc\", \"de\"})\n%!assert (strsplit (\"hello \\t world\", true, \"delimitertype\", \"r\"),\n%!        {\"hello\", \"world\"})\n\n%!assert (strsplit (\"foo\\tbar\", '\\t', \"delimitertype\", \"r\"), {\"foo\", \"bar\"})\n%!assert (strsplit (\"foo\\tbar\", '\\t', \"delimitertype\", \"s\"), {\"foo\", \"bar\"})\n\n## Test \"match\" for consecutive delmiters\n%!test\n%! [a, m] = strsplit (\"a\\t \\nb\", '\\s', \"delimitertype\", \"regularexpression\",\n%!   \"collapsedelimiters\", false);\n%! assert (a, {\"a\", \"\", \"\", \"b\"});\n%! assert (m, {\"\\t\", \" \", \"\\n\"});\n%!test\n%! [a, m] = strsplit (\"a\\t \\nb\", '\\s', false, \"delimitertype\", \"regularexpression\");\n%! assert (a, {\"a\", \"\", \"\", \"b\"});\n%! assert (m, {\"\\t\", \" \", \"\\n\"});\n%!test\n%! [a, m] = strsplit (\"a\\t \\nb\", '\\s', \"delimitertype\", \"regularexpression\");\n%! assert (a, {\"a\", \"b\"});\n%! assert (m, {\"\\t \\n\"});\n%!test\n%! [a, m] = strsplit (\"a\\t \\nb\", {\"\\t\", \" \", \"\\n\"}, \"delimitertype\", \"simple\");\n%! assert (a, {\"a\", \"b\"});\n%! assert (m, {\"\\t \\n\"});\n%!test\n%! [s, m] = strsplit (\"hello \\t world\", true);\n%! assert (s, {\"hello\", \"world\"});\n%! assert (m, {\" \\t \"});\n\n## Compatibility\n%! assert (strsplit (\"\", \"a\"), {\"\"});\n%! assert (strsplit (\"a\", \"a\"), {\"\", \"\"});\n%! assert (strsplit (\"aa\", \"a\"), {\"\", \"\"});\n%! assert (strsplit (\"aaa\", \"a\"), {\"\", \"\"});\n\n%!assert <*44641> (strsplit (\"xxx<yyy\", \"<\"), {\"xxx\", \"yyy\"})\n%!assert <*44641> (strsplit ('xxx\\yyy', '\\'), {\"xxx\", \"yyy\"})\n\n%!assert <*47403> (strsplit ('xxx+yyy', '+'), {\"xxx\", \"yyy\"})\n\n## Test input validation\n%!error <Invalid call> strsplit ()\n%!error strsplit (\"abc\", \"b\", true, 4)\n%!error <invalid parameter name, 'foo'> strsplit (\"abc\", \"b\", \"foo\", \"true\")\n%!error <S and DEL must be string values> strsplit (123, \"b\")\n%!error <S must be a char row vector> strsplit ([\"abc\"; \"xyz\"])\n%!error <S must be a char row vector> strsplit (reshape (\"axbycz\", [1 3 2]))\n%!error <COLLAPSEDELIMITERS must be a scalar value> strsplit (\"abc\", \"def\", \"collapsedelimiters\", ones (3,3))\n%!error <Invalid DELIMITERTYPE> strsplit (\"abc\", \"b\", \"delimitertype\", \"foobar\")\n"
  },
  {
    "path": "scripts/strings/strtok.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{tok}, @var{rem}] =} strtok (@var{str})\n## @deftypefnx {} {[@var{tok}, @var{rem}] =} strtok (@var{str}, @var{delim})\n##\n## Find all characters in the string @var{str} up to, but not including, the\n## first character which is in the string @var{delim}.\n##\n## @var{str} may also be a cell array of strings in which case the function\n## executes on every individual string and returns a cell array of tokens and\n## remainders.\n##\n## Leading delimiters are ignored.  If @var{delim} is not specified,\n## whitespace is assumed.\n##\n## If @var{rem} is requested, it contains the remainder of the string, starting\n## at the first delimiter.\n##\n## Examples:\n##\n## @example\n## @group\n## strtok (\"this is the life\")\n##      @xresult{} \"this\"\n##\n## [tok, rem] = strtok (\"14*27+31\", \"+-*/\")\n##      @xresult{}\n##         tok = 14\n##         rem = *27+31\n## @end group\n## @end example\n## @seealso{index, strsplit, strchr, isspace}\n## @end deftypefn\n\nfunction [tok, rem] = strtok (str, delim)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! (ischar (str) || iscellstr (str)))\n    error (\"strtok: STR must be a string or cell array of strings\");\n  elseif (ischar (str) && ! isvector (str) &&! isempty (str))\n    error (\"strtok: STR cannot be a 2-D character array\");\n  endif\n\n  if (nargin < 2 || isempty (delim))\n    ws_delim = true;\n  else\n    ws_delim = false;\n  endif\n\n  if (isempty (str))\n    tok = rem = \"\";\n  elseif (ischar (str))\n    if (ws_delim)\n      idx = isspace (str);\n    elseif (length (delim) <= 7)\n      ## Build index of delimiters incrementally for low N.\n      idx = str == delim(1);\n      for i = 2:length (delim)\n        idx |= str == delim(i);\n      endfor\n    else\n      ## Index the str into a mask of valid values.  Faster for large N.\n      f = false (256, 1);\n      ## This is slower than it could be because of the +1 issue.\n      f(uint8 (delim)+1) = true;\n      ## Default goes via double -- unnecessarily long.\n      si = uint32 (str);\n      ## in-place is faster than str+1\n      ++si;\n      idx = f(si);\n    endif\n\n    idx_dlim = find (idx, 1);\n    idx_nodlim = find (! idx, 1);\n    if (isempty (idx_dlim))\n      ## No delimiter.  Return whole string.\n      tok = str;\n      rem = \"\";\n    elseif (idx_dlim > idx_nodlim)\n      ## Normal case.  No leading delimiters and at least 1 delimiter in STR.\n      tok = str(1:idx_dlim-1);\n      rem = str(idx_dlim:end);\n    else\n      ## Leading delimiter found.\n      idx_dlim = find (idx(idx_nodlim+1:end), 1);\n      if (isempty (idx_dlim))\n        ## No further delimiters.  Return STR stripped of delimiter prefix.\n        tok = str(idx_nodlim:end);\n        rem = \"\";\n      else\n        ## Strip delimiter prefix.  Return STR up to 1st delimiter\n        tok = str(idx_nodlim:(idx_dlim + idx_nodlim -1));\n        rem = str((idx_dlim + idx_nodlim):end);\n      endif\n    endif\n  else    # Cell array of strings\n    if (ws_delim)\n      delim = '\\s';\n    endif\n    ptn = [ '^[' delim ']*','([^' delim ']+)','([' delim '].*)$' ];\n    matches = regexp (str, ptn, \"tokens\");\n    eidx = cellfun (\"isempty\", matches);\n    midx = ! eidx;\n    tok = cell (size (str));\n    tok(eidx) = regexprep (str(eidx), [ '^[' delim ']+' ], '');\n    ## Unwrap doubly nested cell array from regexp\n    tmp = [matches{midx}];\n    if (! isempty (tmp))\n      tmp = [tmp{:}];\n    endif\n    tok(midx) = tmp(1:2:end);\n    if (nargout > 1)\n      rem = cell (size (str));\n      rem(eidx) = {\"\"};\n      rem(midx) = tmp(2:2:end);\n    endif\n  endif\n\nendfunction\n\n\n%!demo\n%! strtok (\"this is the life\")\n%! # split at the first space, returning \"this\"\n\n%!demo\n%! s = \"14*27+31\"\n%! while (1)\n%!   [t, s] = strtok (s, \"+-*/\");\n%!   printf (\"<%s>\", t);\n%!   if (isempty (s))\n%!     break;\n%!   endif\n%!   printf (\"<%s>\", s(1));\n%! endwhile\n%! printf (\"\\n\");\n%! % ----------------------------------------------------\n%! % Demonstrates processing of an entire string split on\n%! % a variety of delimiters.  Tokens and delimiters are\n%! % printed one after another in angle brackets.\n\n## Test the tokens for all cases\n%!assert (strtok (\"\"), \"\");             # no string\n%!assert (strtok (\"this\"), \"this\");     # no delimiter in string\n%!assert (strtok (\"this \"), \"this\");    # delimiter at end\n%!assert (strtok (\"this is\"), \"this\");  # delimiter in middle\n%!assert (strtok (\" this\"), \"this\");    # delimiter at start\n%!assert (strtok (\" this \"), \"this\");   # delimiter at start and end\n%!assert (strtok (\" \"), \"\"(1:0));       # delimiter only\n\n## Test the remainder for all cases\n%!test [t,r] = strtok (\"\"); assert (r, \"\");\n%!test [t,r] = strtok (\"this\"); assert (r, \"\");\n%!test [t,r] = strtok (\"this \"); assert (r, \" \");\n%!test [t,r] = strtok (\"this is\"); assert (r, \" is\");\n%!test [t,r] = strtok (\" this\"); assert (r, \"\");\n%!test [t,r] = strtok (\" this \"); assert (r, \" \");\n%!test [t,r] = strtok (\" \"); assert (r, \"\");\n\n## Test all tokens and remainders with cell array input\n%!test\n%! str = {\"\", \"this\", \"this \", \"this is\", \" this\", \" this \", \" \"};\n%! [t, r] = strtok (str);\n%! assert (t{1}, \"\");\n%! assert (r{1}, \"\");\n%! assert (t{2}, \"this\");\n%! assert (r{2}, \"\");\n%! assert (t{3}, \"this\");\n%! assert (r{3}, \" \");\n%! assert (t{4}, \"this\");\n%! assert (r{4}, \" is\");\n%! assert (t{5}, \"this\");\n%! assert (r{5}, \"\");\n%! assert (t{6}, \"this\");\n%! assert (r{6}, \" \");\n%! assert (t{7}, \"\");\n%! assert (r{7}, \"\");\n\n## Simple check for 2, 3, and 4 delimiters\n%!assert (strtok (\"this is\", \"i \"), \"th\")\n%!assert (strtok (\"this is\", \"ij \"), \"th\")\n%!assert (strtok (\"this is\", \"ijk \"), \"th\")\n\n## Test all cases for 8 delimiters since a different\n%!# algorithm is used when more than 7 delimiters\n%!assert (strtok (\"\",\"jklmnop \"), \"\")\n%!assert (strtok (\"this\",\"jklmnop \"), \"this\")\n%!assert (strtok (\"this \",\"jklmnop \"), \"this\")\n%!assert (strtok (\"this is\",\"jklmnop \"), \"this\")\n%!assert (strtok (\" this\",\"jklmnop \"), \"this\")\n%!assert (strtok (\" this \",\"jklmnop \"), \"this\")\n%!assert (strtok (\" \",\"jklmnop \"), \"\"(1:0))\n\n## Test 'bad' string orientations\n%!assert (strtok (\" this \".'), \"this\".');   # delimiter at start and end\n%!assert (strtok (\" this \".',\"jkl \"), \"this\".')\n\n## Test with TAB, LF, VT, FF, and CR\n%!test\n%! for ch = \"\\t\\n\\v\\f\\r\"\n%!   [t, r] = strtok ([\"beg\", ch, \"end\"]);\n%!   assert (t, \"beg\");\n%!   assert (r, [ch, \"end\"]);\n%! endfor\n\n## Test input validation\n%!error <Invalid call> strtok ()\n%!error <STR must be a string> strtok (1, \"b\")\n%!error <STR cannot be a 2-D> strtok (char (\"hello\", \"world\"), \"l\")\n"
  },
  {
    "path": "scripts/strings/strtrim.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{s} =} strtrim (@var{s})\n## Remove leading and trailing whitespace from @var{s}.\n##\n## If @var{s} is a matrix, @var{strtrim} trims each row to the length of\n## longest string.  If @var{s} is a cell array of strings, operate recursively\n## on each string element.\n##\n## For example:\n##\n## @example\n## @group\n## strtrim (\"    abc  \")\n##      @xresult{}  \"abc\"\n##\n## strtrim ([\" abc   \"; \"   def   \"])\n##      @xresult{}  [\"abc  \"  ; \"  def\"]\n## @end group\n## @end example\n## @seealso{deblank}\n## @end deftypefn\n\n## This function was derived from deblank.\n\nfunction s = strtrim (s)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ischar (s))\n\n    k = find (! isspace (s));\n    if (isempty (s) || isempty (k))\n      s = \"\";\n    else\n      s = s(:, ceil (min (k) / rows (s)):ceil (max (k) / rows (s)));\n    endif\n\n  elseif (iscell (s))\n\n    char_idx = cellfun (\"isclass\", s, \"char\");\n    cell_idx = cellfun (\"isclass\", s, \"cell\");\n    if (! all (char_idx | cell_idx))\n      error (\"strtrim: S argument must be a string or cellstring\");\n    endif\n\n    ## Divide work load.  Recursive cellfun strtrim call is slow\n    ## and avoided where possible.\n    s(char_idx) = regexprep (s(char_idx), \"^[\\\\s\\v]+|[\\\\s\\v]+$\", '');\n    s(cell_idx) = cellfun (\"strtrim\", s(cell_idx), \"UniformOutput\", false);\n\n  else\n    error (\"strtrim: S argument must be a string or cellstring\");\n  endif\n\nendfunction\n\n\n%!assert (strtrim (\"    abc  \"), \"abc\")\n%!assert (strtrim (\"  \"), \"\")\n%!assert (strtrim (\"abc\"), \"abc\")\n%!assert (strtrim (char (\" abc   \", \"   def   \")), [\"abc  \"; \"  def\"])\n%!assert (strtrim ({\" abc   \"; \"   def   \"}), {\"abc\"; \"def\"})\n%!assert (strtrim ({\" abc   \", {\"   def   \"}}), {\"abc\", {\"def\"}})\n\n%!error <Invalid call to strtrim> strtrim ()\n%!error <called with too many inputs> strtrim (\"abc\", \"def\")\n%!error <argument must be a string> strtrim (1)\n%!error <argument must be a string> strtrim ({[]})\n"
  },
  {
    "path": "scripts/strings/strtrunc.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{s} =} strtrunc (@var{s}, @var{n})\n## Truncate the character string @var{s} to length @var{n}.\n##\n## If @var{s} is a character matrix, then the number of columns is adjusted.\n##\n## If @var{s} is a cell array of strings, then the operation is performed\n## on each cell element and the new cell array is returned.\n## @end deftypefn\n\nfunction s = strtrunc (s, n)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  n = fix (n);\n  if (! isscalar (n) || n < 0)\n    error (\"strtrunc: length N must be a positive integer (N >= 0)\");\n  endif\n\n  if (ischar (s))\n    if (n < columns (s))\n      s = s(:, 1:n);\n    endif\n  elseif (iscellstr (s))\n    ## Convoluted approach converts cellstr to char matrix, trims the character\n    ## matrix using indexing, and then converts back to cellstr with mat2cell.\n    ## This approach is 24X faster than using cellfun with call to strtrunc\n    idx = cellfun (\"size\", s, 2) > n;\n    rows = cellfun (\"size\", s(idx), 1);\n    if (! isempty (rows))\n      s(idx) = mat2cell (char (s(idx))(:, 1:n), rows);\n    endif\n  else\n    error (\"strtrunc: S must be a character string or a cell array of strings\");\n  endif\n\nendfunction\n\n\n%!assert (strtrunc (\"abcdefg\", 4), \"abcd\")\n%!assert (strtrunc (\"abcdefg\", 10), \"abcdefg\")\n%!assert (strtrunc (char (\"abcdef\", \"fedcba\"), 3), [\"abc\"; \"fed\"])\n%!assert (strtrunc ({\"abcdef\", \"fedcba\"}, 3), {\"abc\", \"fed\"})\n%!assert (strtrunc ({\"\", \"1\", \"21\", \"321\"}, 1), {\"\", \"1\", \"2\", \"3\"})\n%!assert (strtrunc ({\"1\", \"\", \"2\"}, 1), {\"1\", \"\", \"2\"})\n%!test\n%! cstr = {\"line1\"; [\"line2\"; \"line3\"]; \"line4\"};\n%! y = strtrunc (cstr, 4);\n%! assert (size (y), [3, 1]);\n%! assert (size (y{2}), [2, 4]);\n%! assert (y{2}, repmat (\"line\", 2, 1));\n\n## Test input validation\n%!error <Invalid call> strtrunc ()\n%!error strtrunc (\"abcd\")\n%!error strtrunc (\"abcd\", 4, 5)\n%!error <N must be a positive integer> strtrunc (\"abcd\", ones (2,2))\n%!error <N must be a positive integer> strtrunc (\"abcd\", -1)\n%!error <S must be a character string or a cell array of strings> strtrunc (1, 1)\n"
  },
  {
    "path": "scripts/strings/substr.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{str} =} substr (@var{s}, @var{offset})\n## @deftypefnx {} {} substr (@var{s}, @var{offset}, @var{len})\n## Return the substring of @var{s} which starts at character number\n## @var{offset} and is @var{len} characters long.\n##\n## Position numbering for offsets begins with 1.  If @var{offset} is negative,\n## extraction starts that far from the end of the string.\n##\n## If @var{len} is omitted, the substring extends to the end of @var{s}.  A\n## negative value for @var{len} extracts to within @var{len} characters of\n## the end of the string\n##\n## Examples:\n##\n## @example\n## @group\n## substr (\"This is a test string\", 6, 9)\n##      @xresult{} \"is a test\"\n## substr (\"This is a test string\", -11)\n##      @xresult{} \"test string\"\n## substr (\"This is a test string\", -11, -7)\n##      @xresult{} \"test\"\n## @end group\n## @end example\n##\n## This function is patterned after the equivalent function in Perl.\n## @end deftypefn\n\nfunction str = substr (s, offset, len)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! ischar (s))\n    error (\"substr: S must be a string or string array\");\n  elseif (! isscalar (offset) || (nargin == 3 && ! isscalar (len)))\n    error (\"substr: OFFSET and LEN must be scalar integers\");\n  endif\n\n  offset = fix (offset);\n  nc = columns (s);\n  if (abs (offset) > nc || offset == 0)\n    error (\"substr: OFFSET = %d out of range\", offset);\n  endif\n\n  if (offset <= 0)\n    offset += nc + 1;\n  endif\n\n  if (nargin == 2)\n    eos = nc;\n  else\n    len = fix (len);\n    if (len < 0)\n      eos = nc + len;\n    else\n      eos = offset + len - 1;\n    endif\n  endif\n\n  if (eos > nc)\n    error (\"substr: length LEN = %d out of range\", len);\n  elseif (offset > eos && len != 0)\n    error (\"substr: No overlap with chosen values of OFFSET and LEN\");\n  endif\n\n  str = s(:, offset:eos);\n\nendfunction\n\n\n%!assert (substr (\"This is a test string\", 6, 9), \"is a test\")\n%!assert (substr (\"This is a test string\", -11), \"test string\")\n%!assert (substr (\"This is a test string\", -11, 4), \"test\")\n%!assert (substr (\"This is a test string\", -11, -7), \"test\")\n%!assert (substr (\"This is a test string\", 1, -7), \"This is a test\")\n%!assert (isempty (substr (\"This is a test string\", 1, 0)))\n\n## Test input validation\n%!error <Invalid call> substr ()\n%!error substr (\"foo\", 2, 3, 4)\n%!error substr (ones (5, 1), 1, 1)\n%!error substr (\"foo\", ones (2,2))\n%!error substr (\"foo\", 1, ones (2,2))\n%!error substr (\"foo\", 0)\n%!error substr (\"foo\", 5)\n%!error substr (\"foo\", 1, 5)\n%!error substr (\"foo\", -1, 5)\n%!error substr (\"foo\", 2, -5)\n"
  },
  {
    "path": "scripts/strings/unicode2native.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{native_bytes} =} unicode2native (@var{utf8_str}, @var{codepage})\n## @deftypefnx {} {@var{native_bytes} =} unicode2native (@var{utf8_str})\n## Convert UTF-8 string @var{utf8_str} to byte stream using @var{codepage}.\n##\n## The character vector @var{utf8_str} is converted to a byte stream\n## @var{native_bytes} using the code page given by @var{codepage}.  The\n## string @var{codepage} must be an identifier of a valid code page.\n## Examples for valid code pages are @qcode{\"ISO-8859-1\"},\n## @qcode{\"Shift-JIS\"}, or @qcode{\"UTF-16\"}.  For a list of supported code\n## pages, see @url{https://www.gnu.org/software/libiconv}.  If @var{codepage}\n## is omitted or empty, the system default codepage is used.\n##\n## If any of the characters cannot be mapped into the codepage @var{codepage},\n## they are replaced with the appropriate substitution sequence for that\n## codepage.\n##\n## @seealso{native2unicode}\n## @end deftypefn\n\nfunction native_bytes = unicode2native (utf8_str, codepage = \"\")\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## For Matlab compatibility, return empty output for empty input.\n  if (isempty (utf8_str))\n    native_bytes = uint8 ([]);\n    return;\n  endif\n\n  if (! ischar (utf8_str) || ! isvector (utf8_str))\n    error (\"unicode2native: UTF8_STR must be a character vector\");\n  endif\n\n  if (! (ischar (codepage) && (isrow (codepage) || isempty (codepage))))\n    error (\"unicode2native: CODEPAGE must be a string\");\n  endif\n\n  native_bytes = __unicode2native__ (utf8_str, codepage);\n\n  if (! isrow (utf8_str))\n    native_bytes = native_bytes.';\n  endif\n\nendfunction\n\n\n%!testif HAVE_ICONV\n%! assert (unicode2native (\"ЄЅІЇЈЉЊ\", \"ISO-8859-5\"), uint8 (164:170));\n%!testif HAVE_ICONV\n%! assert (unicode2native ([\"ЄЅІ\" \"\\0\" \"ЇЈЉЊ\"], \"ISO-8859-5\"),\n%!         uint8 ([164:166 0 167:170]));\n%!assert <*60480> (unicode2native (''), uint8 ([]))\n%!testif HAVE_ICONV <*64331>\n%! assert (! isempty (unicode2native (\"abc\")));\n%!testif HAVE_ICONV <*64331>\n%! assert (! isempty (unicode2native (\"abc\", \"\")));\n\n## short character arrays with invalid UTF-8\n%!testif HAVE_ICONV <*63930>\n%! assert (unicode2native (char (230), 'windows-1252'), uint8 (63));\n%!testif HAVE_ICONV <*63930>\n%! assert (unicode2native (char (249), 'windows-1252'), uint8 (63));\n%!testif HAVE_ICONV <*63930>\n%! assert (unicode2native (char (230:231), 'windows-1252'), uint8 ([63, 63]));\n%!testif HAVE_ICONV <*63930>\n%! assert (unicode2native (char (230:234), 'windows-1252'),\n%!         uint8 ([63, 63, 63, 63, 63]));\n%!testif HAVE_ICONV <*63930>\n%! assert (unicode2native (char ([230, 10]), 'windows-1252'),\n%!         uint8 ([63, 10]));\n\n## target encoding with surrogates larger than one byte\n%!testif HAVE_ICONV\n%! assert (size (unicode2native ('a',\n%!                               ['utf-16', nthargout(3, 'computer'), 'e'])),\n%!         [1, 2]);\n%!testif HAVE_ICONV\n%! assert (typecast (unicode2native ('a',\n%!                                   ['utf-16', nthargout(3, 'computer'), 'e']),\n%!                   'uint16'),\n%!         uint16 (97));\n%!testif HAVE_ICONV\n%! assert (typecast (unicode2native ('ab',\n%!                                   ['utf-16', nthargout(3, 'computer'), 'e']),\n%!                   'uint16'),\n%!         uint16 (97:98));\n%!testif HAVE_ICONV\n%! assert (typecast (unicode2native ('abc',\n%!                                   ['utf-16', nthargout(3, 'computer'), 'e']),\n%!                   'uint16'),\n%!         uint16 (97:99));\n%!testif HAVE_ICONV\n%! assert (typecast (unicode2native ('abcd',\n%!                                   ['utf-16', nthargout(3, 'computer'), 'e']),\n%!                   'uint16'),\n%!         uint16 (97:100));\n%!testif HAVE_ICONV <*64139>\n%! assert (typecast (unicode2native ('abcde',\n%!                                   ['utf-16', nthargout(3, 'computer'), 'e']),\n%!                   'uint16'),\n%!         uint16 (97:101));\n%!testif HAVE_ICONV\n%! assert (size (unicode2native ('a',\n%!                               ['utf-32', nthargout(3, 'computer'), 'e'])),\n%!         [1, 4]);\n%!testif HAVE_ICONV\n%! assert (typecast (unicode2native ('a',\n%!                                   ['utf-32', nthargout(3, 'computer'), 'e']),\n%!                   'uint32'),\n%!         uint32 (97));\n%!testif HAVE_ICONV\n%! assert (typecast (unicode2native ('ab',\n%!                                   ['utf-32', nthargout(3, 'computer'), 'e']),\n%!                   'uint32'),\n%!         uint32 (97:98));\n%!testif HAVE_ICONV\n%! assert (typecast (unicode2native ('abc',\n%!                                   ['utf-32', nthargout(3, 'computer'), 'e']),\n%!                   'uint32'),\n%!         uint32 (97:99));\n%!testif HAVE_ICONV\n%! assert (typecast (unicode2native ('abcd',\n%!                                   ['utf-32', nthargout(3, 'computer'), 'e']),\n%!                   'uint32'),\n%!         uint32 (97:100));\n\n%!error <Invalid call> unicode2native ()\n%!error <called with too many inputs> unicode2native ('a', 'ISO-8859-1', 'test')\n%!error <UTF8_STR must be a character vector> unicode2native (['ab'; 'cd'])\n%!error <UTF8_STR must be a character vector> unicode2native ({1 2 3 4})\n%!error <CODEPAGE must be a string> unicode2native ('ЄЅІЇЈЉЊ', 123)\n%!error <CODEPAGE must be a string> unicode2native ('ЄЅІЇЈЉЊ', ['ISO-8859-1'].')\n%!testif HAVE_ICONV\n%! fail (\"unicode2native ('a', 'foo')\",\n%!       \"converting from UTF-8 to codepage 'foo'\");\n"
  },
  {
    "path": "scripts/strings/untabify.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{str} =} untabify (@var{t})\n## @deftypefnx {} {@var{str} =} untabify (@var{t}, @var{tw})\n## @deftypefnx {} {@var{str} =} untabify (@var{t}, @var{tw}, @var{deblank})\n## Replace TAB characters in @var{t} with spaces.\n##\n## The input, @var{t}, may be either a 2-D character array, or a cell array of\n## character strings.  The output is the same class as the input.\n##\n## The tab width is specified by @var{tw}, and defaults to eight.\n##\n## If the optional argument @var{deblank} is true, then the spaces will be\n## removed from the end of the character data.\n##\n## The following example reads a file and writes an untabified version of the\n## same file with trailing spaces stripped.\n##\n## @example\n## @group\n## fid = fopen (\"tabbed_script.m\");\n## text = char (fread (fid, \"uchar\")');\n## fclose (fid);\n## fid = fopen (\"untabified_script.m\", \"w\");\n## text = untabify (strsplit (text, \"\\n\"), 8, true);\n## fprintf (fid, \"%s\\n\", text@{:@});\n## fclose (fid);\n## @end group\n## @end example\n##\n## @seealso{strjust, strsplit, deblank}\n## @end deftypefn\n\nfunction str = untabify (t, tw = 8, deblank_arg = false)\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! (ischar (t) || iscellstr (t)))\n    error (\"untabify: T must be a string or cellstring\");\n  endif\n\n  if (ischar (t))\n    str = replace_tabs (t, tw);\n  else\n    str = cellfun ('replace_tabs', t, {tw}, \"uniformoutput\", false);\n  endif\n\n  if (deblank_arg)\n    str = deblank (str);\n  endif\n\nendfunction\n\nfunction s = replace_tabs (t, tw)\n\n  if (ndims (t) != 2)\n    error (\"untabify: character strings to untabify must have 2 dimensions\");\n  endif\n\n  if (isempty (t))\n    s = t;\n  else\n    nr = rows (t);\n    sc = cell (nr, 1);\n    for j = 1:nr\n      n = 1:numel (t(j,:));\n      m = find (t(j,:) == \"\\t\");\n      t(j,m) = \" \";\n      for i = 1:numel (m)\n        k = tw * ceil (n(m(i)) / tw);\n        dn = k - n(m(i));\n        n(m(i):end) += dn;\n      endfor\n      sc{j} = blanks (n(end));\n      sc{j}(n) = t(j,:);\n    endfor\n    s = char (sc);\n  endif\n\nendfunction\n\n\n%!test\n%! s = untabify (\"\\thello\\t\");\n%! assert (s, [blanks(8) \"hello\" blanks(3)]);\n\n%!test\n%! s = untabify (\"\\thello\\t\", 2);\n%! assert (s, [blanks(2) \"hello\" blanks(1)]);\n\n%!test\n%! s = untabify (\"\\thello\\t\", 4, true);\n%! assert (s, [blanks(4) \"hello\"]);\n\n%!assert (isempty (untabify (\"\")))\n\n%!test\n%! s = char (randi ([97 97+25], 3, 3));\n%! assert (untabify (s), char (untabify (cellstr (s))));\n\n## Test input validation\n%!error <Invalid call> untabify ()\n%!error <must be a string> untabify (1)\n"
  },
  {
    "path": "scripts/strings/validatestring.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{validstr} =} validatestring (@var{str}, @var{strarray})\n## @deftypefnx {} {@var{validstr} =} validatestring (@var{str}, @var{strarray}, @var{funcname})\n## @deftypefnx {} {@var{validstr} =} validatestring (@var{str}, @var{strarray}, @var{funcname}, @var{varname})\n## @deftypefnx {} {@var{validstr} =} validatestring (@dots{}, @var{position})\n## Verify that @var{str} is an element, or substring of an element, in\n## @var{strarray}.\n##\n## When @var{str} is a character string to be tested, and @var{strarray} is a\n## cell array of strings of valid values, then @var{validstr} will be the\n## validated form of @var{str} where validation is defined as @var{str} being\n## a member or substring of @var{validstr}.  This is useful for both verifying\n## and expanding short options, such as @qcode{\"r\"}, to their longer forms,\n## such as @qcode{\"red\"}.  If @var{str} is a substring of @var{validstr},\n## and there are multiple matches, the shortest match will be returned if\n## all matches are substrings of each other.  Otherwise, an error will be\n## raised because the expansion of @var{str} is ambiguous.  All comparisons\n## are case insensitive.\n##\n## The additional inputs @var{funcname}, @var{varname}, and @var{position}\n## are optional and will make any generated validation error message more\n## specific.\n##\n## Examples:\n## @c Set example in small font to prevent overfull line\n##\n## @smallexample\n## @group\n## validatestring (\"r\", @{\"red\", \"green\", \"blue\"@})\n## @xresult{} \"red\"\n##\n## validatestring (\"b\", @{\"red\", \"green\", \"blue\", \"black\"@})\n## @xresult{} error: validatestring: multiple unique matches were found for 'b':\n##    blue, black\n## @end group\n## @end smallexample\n##\n## @seealso{strcmp, strcmpi, validateattributes, inputParser}\n## @end deftypefn\n\nfunction str = validatestring (str, strarray, varargin)\n\n  if (nargin < 2 || nargin > 5)\n    print_usage ();\n  endif\n\n  ## Process input arguments\n  position = 0;\n  if (! isempty (varargin) && isnumeric (varargin{end}))\n    position = fix (varargin{end});\n    varargin(end) = [];\n    if (position < 1)\n      error (\"validatestring: POSITION must be >= 1\");\n    endif\n  endif\n\n  funcname = varname = \"\";\n  char_idx = cellfun (\"isclass\", varargin, \"char\");\n  n_chararg = sum (char_idx);\n  if (n_chararg > 2)\n    error (\"validatestring: invalid number of character inputs (> 3)\");\n  elseif (n_chararg == 2)\n    [funcname, varname] = deal (varargin{char_idx});\n  elseif (n_chararg == 1)\n    funcname = varargin{char_idx};\n  endif\n\n  ## Validate the inputs\n  if (! (ischar (str) && isrow (str)))\n    error (\"validatestring: STR must be a single character string\");\n  elseif (! iscellstr (strarray))\n    error (\"validatestring: STRARRAY must be a cellstr\");\n  elseif (! isempty (funcname) && ! isrow (funcname))\n    error (\"validatestring: FUNCNAME must be a single character string\");\n  elseif (! isempty (varname) && ! isrow (varname))\n    error (\"validatestring: VARNAME must be a single character string\");\n  endif\n\n  ## Make static part of error string that uses funcname, varname, and position\n  if (isempty (funcname))\n    funcname = \"validatestring\";\n  endif\n  errstr = [funcname \": '\" str \"' \"];\n  if (! isempty (varname))\n    if (position > 0)\n      errstr = sprintf (\"%s(variable %s, argument #%i) \", ...\n                        errstr, varname, position);\n    else\n      errstr = sprintf (\"%s(variable %s) \", errstr, varname);\n    endif\n  else\n    if (position > 0)\n      errstr = sprintf (\"%s(argument #%i) \", errstr, position);\n    endif\n  endif\n\n  matches = strncmpi (str, strarray(:), numel (str));\n  nmatches = sum (matches);\n  if (nmatches == 0)\n    error (\"%sdoes not match any of\\n%s\", errstr,\n           sprintf (\"'%s', \", strarray{:})(1:end-2));\n  elseif (nmatches == 1)\n    str = strarray{matches};\n  else\n    ## Are the matches substrings of each other?\n    ## If true, choose the shortest.  If not, raise an error.\n    match_idx = find (matches);\n    match_len = cellfun (\"length\", strarray(match_idx));\n    [min_len, min_idx] = min (match_len);\n    short_str = strarray{match_idx(min_idx)};\n    submatch = strncmpi (short_str, strarray(match_idx), min_len);\n    if (all (submatch))\n      str = short_str;\n    else\n      error (\"%smatches multiple possible values:\\n%s\", errstr,\n             sprintf (\"'%s', \", strarray{match_idx})(1:end-2));\n    endif\n  endif\n\nendfunction\n\n\n%!shared strarray\n%! strarray = {\"octave\" \"Oct\" \"octopus\" \"octaves\"};\n%!assert (validatestring (\"octave\", strarray), \"octave\")\n%!assert (validatestring (\"oct\", strarray), \"Oct\")\n%!assert (validatestring (\"octa\", strarray), \"octave\")\n%! strarray = {\"abc1\" \"def\" \"abc2\"};\n%!assert (validatestring (\"d\", strarray), \"def\")\n\n%!error <'xyz' does not match any> validatestring (\"xyz\", strarray)\n%!error <DUMMY_TEST: 'xyz' does not match any>\n%! validatestring (\"xyz\", strarray, \"DUMMY_TEST\")\n%!error <DUMMY_TEST: 'xyz' \\(variable DUMMY_VAR\\) does not match>\n%! validatestring (\"xyz\", strarray, \"DUMMY_TEST\", \"DUMMY_VAR\")\n%!error <DUMMY_TEST: 'xyz' \\(variable DUMMY_VAR, argument #5\\) does>\n%! validatestring (\"xyz\", strarray, \"DUMMY_TEST\", \"DUMMY_VAR\", 5)\n%!error <'abc' matches multiple possible values:> validatestring (\"abc\", strarray)\n\n## Test input validation\n%!error <Invalid call> validatestring (\"xyz\")\n%!error <Invalid call> validatestring (\"xyz\", {\"xyz\"}, \"3\", \"4\", 5, 6)\n%!error <POSITION must be .= 1> validatestring (\"xyz\", {\"xyz\"}, \"3\", \"4\", -5)\n%!error <invalid number of character inputs>\n%! validatestring (\"xyz\", {\"xyz\"}, \"3\", \"4\", \"5\")\n%!error <STR must be a single character string>\n%! validatestring (1, {\"xyz\"}, \"3\", \"4\", 5)\n%!error <STR must be a single character string>\n%! validatestring (['xyz';'def'], {\"xyz\"}, \"3\", \"4\", 5)\n%!error <STRARRAY must be a cellstr> validatestring (\"xyz\", \"xyz\", \"3\", \"4\", 5)\n%!error <FUNCNAME must be a single character string>\n%! validatestring (\"xyz\", {\"xyz\"}, [\"3\";\"3\"], \"4\", 5)\n%!error <VARNAME must be a single character string>\n%! validatestring (\"xyz\", {\"xyz\"}, \"3\", [\"4\";\"4\"], 5)\n"
  },
  {
    "path": "scripts/testfun/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/testfun/__debug_octave__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} __debug_octave__ ()\n## @deftypefnx {} {} __debug_octave__ (@var{command_string})\n## Try to open a terminal window with gdb connected to the current\n## Octave process.\n##\n## If @var{command_string} is not supplied, it should have a single\n## @code{%d} format option that will be replaced by the process ID\n## for the current Octave process, as returned by @code{getpid}.  For\n## example, on Windows systems the following two commands are\n## equivalent:\n##\n## @example\n## @group\n## __debug_octave__ ()\n## __debug_octave__ (\"cmd /c start gdb -p %d\")\n## @end group\n## @end example\n## @end deftypefn\n\nfunction __debug_octave__ (command_string)\n\n  if (nargin == 0)\n    if (ismac ())\n      status = system (\"lldb --version\");\n      if (status != 0)\n        error (\"unable to execute lldb\");\n      endif\n      command_string = \"osascript -e 'tell application \\\"Terminal\\\" to do script \\\"lldb -p %d\\\"'\";\n\n    elseif (isunix ())\n      status = system (\"gdb --version\");\n      if (status != 0)\n        error (\"unable to execute gdb\");\n      endif\n      command_string = \"x-terminal-emulator -e gdb -p %d\";\n\n    elseif (ispc ())\n      status = system (\"gdb --version\");\n      if (status != 0)\n        error (\"unable to execute gdb\");\n      endif\n      command_string = \"cmd /c start gdb -p %d\";\n\n    else\n      error (\"unknown system -- unable to determine how to start debugger\");\n    endif\n  endif\n\n  system (sprintf (command_string, getpid ()), false, \"async\");\n\nendfunction\n"
  },
  {
    "path": "scripts/testfun/__have_feature__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{tf} =} __have_feature__ (feature)\n## Undocumented internal function.\n## @end deftypefn\n\nfunction tf = __have_feature__ (feature)\n\n  if (strncmp (feature, \"ENABLE_\", 7))\n    features = __octave_config_info__ ();\n  else\n    features = __octave_config_info__ (\"build_features\");\n  endif\n\n  if (iscellstr (feature))\n    tf = (all (isfield (features, feature))\n              && all (cellfun (@(x) features.(x), feature)));\n  elseif (ischar (feature))\n    tf = isfield (features, feature) && features.(feature);\n  else\n    tf = false;\n  endif\n\nendfunction\n\n\n%!assert (islogical (__have_feature__ (\"MAGICK\")))\n%!assert (isscalar (__have_feature__ (\"MAGICK\")))\n%!assert (__have_feature__ (\"MAGICK\"), __have_feature__ ({\"MAGICK\", \"MAGICK\"}))\n\n## Test that an empty feature set returns true\n%!assert (__have_feature__ ({}))\n"
  },
  {
    "path": "scripts/testfun/__printf_assert__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} __printf_assert__ (@dots{})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction __printf_assert__ (varargin)\n  global __assert_printf__ = \"\";\n\n  __assert_printf__ = cat (2, __assert_printf__, sprintf (varargin{:}));\n\nendfunction\n\n\n## No test coverage for internal function.  It is tested through calling fcn.\n%!assert (1)\n"
  },
  {
    "path": "scripts/testfun/__prog_output_assert__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{retval} =} __prog_output_assert__ (@var{str})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction retval = __prog_output_assert__ (str)\n  global __assert_printf__ = \"\";\n\n  if (isempty (__assert_printf__))\n    retval = isempty (str);\n  elseif (__assert_printf__(end) == \"\\n\")\n    retval = strcmp (__assert_printf__(1:(end-1)), str);\n  else\n    retval = strcmp (__assert_printf__, str);\n  endif\n\n  __assert_printf__ = \"\";\n\nendfunction\n\n\n## No test coverage for internal function.  It is tested through calling fcn.\n%!assert (1)\n"
  },
  {
    "path": "scripts/testfun/__run_test_suite__.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{pass}, @var{fail}, @var{xfail}, @var{xbug}, @var{skip}, @var{rtskip}, @var{regress}] =} __run_test_suite__ (@var{fcndirs}, @var{fixedtestdirs})\n## @deftypefnx {} {[@var{pass}, @var{fail}, @var{xfail}, @var{xbug}, @var{skip}, @var{rtskip}, @var{regress}] =} __run_test_suite__ (@var{fcndirs}, @var{fixedtestdirs}, @var{topsrcdir}, @var{topbuilddir})\n## Undocumented internal function.\n## @end deftypefn\n\nfunction [pass, fail, xfail, xbug, skip, rtskip, regress] = __run_test_suite__ (fcndirs, fixedtestdirs, topsrcdir = [], topbuilddir = [])\n\n  testsdir = __octave_config_info__ (\"octtestsdir\");\n  libinterptestdir = fullfile (testsdir, \"libinterp\");\n  liboctavetestdir = fullfile (testsdir, \"liboctave\");\n  fixedtestdir = fullfile (testsdir, \"fixed\");\n  fcnfiledir = __octave_config_info__ (\"fcnfiledir\");\n  if (nargin == 0)\n    fcndirs = { liboctavetestdir, libinterptestdir, fcnfiledir };\n    fixedtestdirs = { fixedtestdir };\n  endif\n  files_with_no_tests = {};\n  files_with_tests = {};\n  summary_failure_info = struct ([]);\n  ## FIXME: These names don't really make sense if we are running\n  ##        tests for an installed copy of Octave.\n  if (isempty (topsrcdir))\n    topsrcdir = fcnfiledir;\n  endif\n  if (isempty (topbuilddir))\n    topbuilddir = testsdir;\n  endif\n\n  pso = page_screen_output ();\n  orig_wquiet = warning (\"query\", \"quiet\");\n  orig_wstate = warning ();\n  orig_mfile_encoding = mfile_encoding (\"utf-8\");\n  logfile = make_absolute_filename (\"fntests.log\");\n  unwind_protect\n    page_screen_output (false);\n    warning (\"on\", \"quiet\");\n    warning (\"off\", \"Octave:deprecated-function\");\n    warning (\"off\", \"Octave:legacy-function\");\n    nfail = dp = dn = dxf = dxb = dsk = drtsk = drgrs = 0;\n    try\n      fid = fopen (logfile, \"wt\");\n      if (fid < 0)\n        error (\"__run_test_suite__: could not open %s for writing\", logfile);\n      endif\n      tot_cpu_tm = cputime ();\n      tot_tic_tag = tic ();\n      test (\"\", \"explain\", fid);\n      puts (\"\\nIntegrated test scripts:\\n\");\n      printf (\"%101s\\n\", \"[ CPU    |  CLOCK ]\");\n      for i = 1:length (fcndirs)\n        [p, n, xf, xb, sk, rtsk, rgrs] = run_test_dir (fid, fcndirs{i}, false);\n        dp += p;\n        dn += n;\n        dxf += xf;\n        dxb += xb;\n        dsk += sk;\n        drtsk += rtsk;\n        drgrs += rgrs;\n      endfor\n      puts (\"\\nFixed test scripts:\\n\\n\");\n      for i = 1:length (fixedtestdirs)\n        [p, n, xf, xb, sk, rtsk, rgrs] = run_test_dir (fid, fixedtestdirs{i}, true);\n        dp += p;\n        dn += n;\n        dxf += xf;\n        dxb += xb;\n        dsk += sk;\n        drtsk += rtsk;\n        drgrs += rgrs;\n      endfor\n      tot_clock_tm = toc (tot_tic_tag);\n      tot_cpu_tm = cputime () - tot_cpu_tm;\n      printf (\"%80s  [%6.1fs | %6.1fs]\", \"total time (CPU | CLOCK)\", tot_cpu_tm, tot_clock_tm);\n      if (! isempty (summary_failure_info))\n        puts (\"\\nFailure Summary:\\n\\n\");\n        for i = 1:numel (summary_failure_info)\n          info = summary_failure_info(i);\n          print_test_file_name (info.name);\n          print_pass_fail (info);\n        endfor\n      endif\n      puts (\"\\nSummary:\\n\\n\");\n      nfail = dn - dp - dxf - dxb - drgrs;\n      printf (\"  %-30s %6d\\n\", \"PASS\", dp);\n      printf (\"  %-30s %6d\\n\", \"FAIL\", nfail);\n      if (drgrs > 0)\n        printf (\"  %-30s %6d\\n\", \"REGRESSION\", drgrs);\n      endif\n      if (dxb > 0)\n        printf (\"  %-30s %6d\\n\", \"XFAIL (reported bug)\", dxb);\n      endif\n      if (dxf > 0)\n        printf (\"  %-30s %6d\\n\", \"XFAIL (expected failure)\", dxf);\n      endif\n      if (dsk > 0)\n        printf (\"  %-30s %6d\\n\", \"SKIP (missing feature)\", dsk);\n      endif\n      if (drtsk > 0)\n        printf (\"  %-30s %6d\\n\", \"SKIP (run-time condition)\", drtsk);\n      endif\n      puts (\"\\n\");\n      printf (\"See the file %s for additional details.\\n\", logfile);\n      if (dxf > 0 || dxb > 0)\n        puts (\"\\n\");\n        puts (\"XFAIL items are known bugs or expected failures.\\n\");\n        puts (\"Bug report numbers may be found in the log file:\\n\");\n        puts (logfile);\n        puts (\"\\nPlease help improve Octave by contributing fixes for them.\\n\");\n      endif\n      if (dsk > 0 || drtsk > 0)\n        puts (\"\\n\");\n        puts (\"Tests are often skipped because required features were\\n\");\n        puts (\"disabled or were not present when Octave was built.\\n\");\n        puts (\"The configure script should have printed a summary\\n\");\n        puts (\"indicating which dependencies were not found.\\n\");\n      endif\n\n      ## Weed out deprecated, legacy, and private functions\n      weed_idx = cellfun ('isempty', regexp (files_with_tests, '\\<deprecated\\>|\\<legacy\\>|\\<private\\>', 'once'));\n      files_with_tests = files_with_tests(weed_idx);\n      weed_idx = cellfun ('isempty', regexp (files_with_no_tests, '\\<deprecated\\>|\\<legacy\\>|\\<private\\>', 'once'));\n      files_with_no_tests = files_with_no_tests(weed_idx);\n\n      report_files_with_no_tests (files_with_tests, files_with_no_tests, \".m\");\n\n      puts (\"\\nPlease help improve Octave by contributing tests for these files\\n\");\n      printf (\"(see the list in the file %s).\\n\\n\", logfile);\n\n      fprintf (fid, \"\\nFiles with no tests:\\n\\n%s\",\n                    list_in_columns (files_with_no_tests, 80));\n      fclose (fid);\n    catch\n      disp (lasterr ());\n    end_try_catch\n  unwind_protect_cleanup\n    warning (\"off\", \"all\");\n    warning (orig_wstate);\n    warning (orig_wquiet.state, \"quiet\");\n    mfile_encoding (orig_mfile_encoding);\n    page_screen_output (pso);\n  end_unwind_protect\n\n  if (nargout > 0)\n    pass = dp;\n    fail = nfail;\n    xfail = dxf;\n    xbug = dxb;\n    skip = dsk;\n    rtskip = drtsk;\n    regress = drgrs;\n  endif\n\n  function [dp, dn, dxf, dxb, dsk, drtsk, drgrs] = run_test_dir (fid, d, is_fixed = false)\n\n    lst = dir (d);\n    dp = dn = dxf = dxb = dsk = drtsk = drgrs = 0;\n    for i = 1:length (lst)\n      nm = lst(i).name;\n      if (lst(i).isdir && nm(1) != \".\" && ! strcmp (nm, \"private\"))\n        [p, n, xf, xb, sk, rtsk, rgrs] = run_test_dir (fid, [d, filesep, nm], is_fixed);\n        dp += p;\n        dn += n;\n        dxf += xf;\n        dxb += xb;\n        dsk += sk;\n        drtsk += rtsk;\n        drgrs += rgrs;\n      endif\n    endfor\n\n    saved_dir = pwd ();\n    unwind_protect\n      [dnm, fnm] = fileparts (d);\n      if (fnm(1) != \"@\")\n        cd (d);\n      endif\n      for i = 1:length (lst)\n        nm = lst(i).name;\n        ## Ignore hidden files\n        if (nm(1) == '.')\n          continue;\n        endif\n        if ((! is_fixed && length (nm) > 2 && strcmpi (nm((end-1):end), \".m\"))\n            || (! is_fixed && length (nm) > 4 && strcmpi (nm((end-3):end), \"-tst\"))\n            || (is_fixed && length (nm) > 4 && strcmpi (nm((end-3):end), \".tst\")))\n          p = n = xf = xb = sk = rtsk = rgrs = 0;\n          ffnm = fullfile (d, nm);\n          if (! isfile (ffnm))\n            continue;\n          endif\n\n          ## Only run if contains %!test, %!assert, %!error, %!fail, or %!warning\n          if (has_tests (ffnm))\n            tmp = reduce_test_file_name (ffnm, topbuilddir, topsrcdir);\n            print_test_file_name (tmp);\n            cpu_tm = cputime ();\n            tic_tag = tic ();\n            [p, n, xf, xb, sk, rtsk, rgrs] = test (ffnm, \"quiet\", fid);\n            clock_tm = toc (tic_tag);\n            cpu_tm = cputime () - cpu_tm;\n            print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs, cpu_tm, clock_tm);\n            dp += p;\n            dn += n;\n            dxf += xf;\n            dxb += xb;\n            dsk += sk;\n            drtsk += rtsk;\n            drgrs += rgrs;\n            files_with_tests(end+1) = ffnm;\n            if (n - p > 0)\n              ## Save info for summary if there were any failed\n              ## tests for this file.\n              failure_info = struct (\"name\", tmp, \"pass\", p, \"ntst\", n,\n                                     \"xf\", xf, \"xb\", xb, \"rgrs\", rgrs);\n              summary_failure_info(end+1) = failure_info;\n            endif\n          else\n            ## To reduce the list length, only mark .cc files that contain\n            ## DEFUN definitions.\n            files_with_no_tests(end+1) = ffnm;\n          endif\n        endif\n      endfor\n    unwind_protect_cleanup\n      cd (saved_dir);\n    end_unwind_protect\n\n  endfunction\n\nendfunction\n\nfunction print_test_file_name (nm)\n\n  nmlen = numel (nm);\n  filler = repmat (\".\", 1, 63-nmlen);\n  if (nmlen > 63)\n    nm = [\"..\", nm(nmlen-60:end)];\n  endif\n  printf (\"  %s %s\", nm, filler);\n\nendfunction\n\nfunction fail_info = print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs, cpu_tm, clock_tm)\n\n  if (nargin == 1)\n    ## The summary info struct just contains info about failures, not\n    ## skipped tests or timings.\n    info = p;\n    p = info.pass;\n    n = info.ntst;\n    xf = info.xf;\n    xb = info.xb;\n    sk = 0;\n    rtsk = 0;\n    rgrs = info.rgrs;\n    cpu_tm = 0;\n    clock_tm = 0;\n  endif\n\n  if ((n + sk + rtsk + rgrs) > 0)\n    printf (\" pass %4d/%-4d\", p, n);\n    if (cpu_tm != 0 || clock_tm != 0)\n      printf (\" [%6.3fs | %6.3fs]\", cpu_tm, clock_tm);\n    endif\n    nfail = n - p - xf - xb - rgrs;\n    if (nfail > 0)\n      printf (\"\\n%72s %3d\", \"FAIL \", nfail);\n    endif\n    if (rgrs > 0)\n      printf (\"\\n%72s %3d\", \"REGRESSION\", rgrs);\n    endif\n    if (sk > 0)\n      printf (\"\\n%72s %3d\", \"(missing feature) SKIP \", sk);\n    endif\n    if (rtsk > 0)\n      printf (\"\\n%72s %3d\", \"(run-time condition) SKIP \", rtsk);\n    endif\n    if (xb > 0)\n      printf (\"\\n%72s %3d\", \"(reported bug) XFAIL\", xb);\n    endif\n    if (xf > 0)\n      printf (\"\\n%72s %3d\", \"(expected failure) XFAIL\", xf);\n    endif\n  endif\n  puts (\"\\n\");\n\nendfunction\n\nfunction retval = reduce_test_file_name (nm, builddir, srcdir)\n\n  ## Reduce the given absolute file name to a relative path by removing one\n  ## of the likely root directory prefixes.\n\n  prefix = { builddir, fullfile(builddir, \"scripts\"), ...\n             srcdir, fullfile(srcdir, \"scripts\"), ...\n             srcdir, fullfile(srcdir, \"test\") };\n\n  retval = nm;\n\n  for i = 1:numel (prefix)\n    tmp = strrep (nm, [prefix{i}, filesep], \"\");\n    if (length (tmp) < length (retval))\n      retval = tmp;\n    endif\n  endfor\n\nendfunction\n\nfunction retval = has_functions (f)\n\n  n = length (f);\n  if (n > 3 && strcmpi (f((end-2):end), \".cc\"))\n    fid = fopen (f);\n    if (fid < 0)\n      error (\"__run_test_suite__: fopen failed: %s\", f);\n    endif\n    str = fread (fid, \"*char\")';\n    fclose (fid);\n    retval = ! isempty (regexp (str,'^(DEFUN|DEFUN_DLD)\\>',\n                                    'lineanchors', 'once'));\n  elseif (n > 2 && strcmpi (f((end-1):end), \".m\"))\n    retval = true;\n  else\n    retval = false;\n  endif\n\nendfunction\n\nfunction retval = has_tests (f)\n\n  fid = fopen (f);\n  if (fid < 0)\n    error (\"__run_test_suite__: fopen failed: %s\", f);\n  endif\n\n  str = fread (fid, \"*char\")';\n  fclose (fid);\n  retval = ! isempty (regexp (str,\n                              '^%!(assert|error|fail|test|xtest|warning)',\n                              'lineanchors', 'once'));\n\nendfunction\n\nfunction n = num_elts_matching_pattern (lst, pat)\n  n = sum (! cellfun (\"isempty\", regexp (lst, pat, 'once')));\nendfunction\n\nfunction report_files_with_no_tests (with, without, typ)\n\n  pat = ['\\' typ \"$\"];\n  n_with = num_elts_matching_pattern (with, pat);\n  n_without = num_elts_matching_pattern (without, pat);\n  n_tot = n_with + n_without;\n  printf (\"\\n%d (of %d) %s files have no tests.\\n\", n_without, n_tot, typ);\n\nendfunction\n\n\n## No test coverage for internal function.  It is tested through calling fcn.\n%!assert (1)\n"
  },
  {
    "path": "scripts/testfun/assert.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} assert (@var{cond})\n## @deftypefnx {} {} assert (@var{cond}, @var{errmsg})\n## @deftypefnx {} {} assert (@var{cond}, @var{errmsg}, @dots{})\n## @deftypefnx {} {} assert (@var{cond}, @var{msg_id}, @var{errmsg}, @dots{})\n## @deftypefnx {} {} assert (@var{observed}, @var{expected})\n## @deftypefnx {} {} assert (@var{observed}, @var{expected}, @var{tol})\n##\n## Produce an error if the specified condition is not met.\n##\n## @code{assert} can be called in three different ways.\n##\n## @table @code\n## @item  assert (@var{cond})\n## @itemx assert (@var{cond}, @var{errmsg})\n## @itemx assert (@var{cond}, @var{errmsg}, @dots{})\n## @itemx assert (@var{cond}, @var{msg_id}, @var{errmsg}, @dots{})\n## Called with a single argument @var{cond}, @code{assert} produces an error if\n## @var{cond} is false (numeric zero).\n##\n## Any additional arguments are passed to the @code{error} function for\n## processing.\n##\n## @item assert (@var{observed}, @var{expected})\n## Produce an error if observed is not the same as expected.\n##\n## Note that @var{observed} and @var{expected} can be scalars, vectors,\n## matrices, strings, cell arrays, or structures.\n##\n## @item assert (@var{observed}, @var{expected}, @var{tol})\n## Produce an error if observed is not the same as expected but equality\n## comparison for numeric data uses a tolerance @var{tol}.\n##\n## If @var{tol} is positive then it is an absolute tolerance which will produce\n## an error if @code{abs (@var{observed} - @var{expected}) > abs (@var{tol})}.\n##\n## If @var{tol} is negative then it is a relative tolerance which will produce\n## an error if @code{abs (@var{observed} - @var{expected}) >\n## abs (@var{tol} * @var{expected})}.\n##\n## If @var{expected} is zero @var{tol} will always be interpreted as an\n## absolute tolerance.\n##\n## If @var{tol} is not scalar its dimensions must agree with those of\n## @var{observed} and @var{expected} and tests are performed on an\n## element-by-element basis.\n## @end table\n## @seealso{fail, test, error, isequal}\n## @end deftypefn\n\nfunction assert (cond, varargin)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  persistent call_depth = -1;\n  persistent errmsg;\n\n  unwind_protect\n\n    call_depth += 1;\n\n    if (call_depth == 0)\n      errmsg = \"\";\n    endif\n\n    if (nargin == 1 || (nargin > 1 && islogical (cond) && ischar (varargin{1})))\n      if ((! isnumeric (cond) && ! islogical (cond))\n          || isempty (cond) || ! all (cond(:)))\n\n        ## We don't want to start the debugger here if debug_on_error is\n        ## true so we set it to false and make the change local.  Then\n        ## debug_on_error will be reset to true after this function\n        ## returns and the debugger will start at the location of the\n        ## call to print_usage.\n        debug_on_error (false, \"local\");\n\n        if (nargin == 1)\n          ## Perhaps, say which elements failed?\n          argin = [\"(\" inputname(1, false) \")\"];\n          error (\"assert %s failed\", argin);\n        else\n          error (varargin{:});\n        endif\n      endif\n    else\n      expected = varargin{1};\n      if (nargin < 3)\n        tol = 0;\n      elseif (nargin == 3)\n        tol = varargin{2};\n      else\n        print_usage ();\n      endif\n\n      ## Add to list as the errors accumulate.  If empty at end then no errors.\n      err.index = {};\n      err.observed = {};\n      err.expected = {};\n      err.reason = {};\n\n      if (ischar (expected))\n        if (! ischar (cond))\n          err.index{end+1} = \".\";\n          err.expected{end+1} = [\"'\" expected \"'\"];\n          if (isnumeric (cond))\n            err.observed{end+1} = num2str (cond);\n            err.reason{end+1} = \"Expected string, but observed number\";\n          else\n            err.observed{end+1} = \"O\";\n            err.reason{end+1} = [\"Expected string, but observed \" class(cond)];\n          endif\n        elseif (! strcmp (cond, expected))\n          err.index{end+1} = \"[]\";\n          err.observed{end+1} = [\"'\" cond(:).' \"'\"];\n          err.expected{end+1} = [\"'\" expected(:).' \"'\"];\n          err.reason{end+1} = \"Strings don't match\";\n        endif\n\n      elseif (iscell (expected))\n        if (! iscell (cond))\n          err.index{end+1} = \".\";\n          err.observed{end+1} = \"O\";\n          err.expected{end+1} = \"E\";\n          err.reason{end+1} = [\"Expected cell, but observed \" class(cond)];\n        elseif (ndims (cond) != ndims (expected)\n                || any (size (cond) != size (expected)))\n          err.index{end+1} = \".\";\n          err.observed{end+1} = [\"O(\" sprintf(\"%dx\", size(cond))(1:end-1) \")\"];\n          err.expected{end+1} = [\"E(\" sprintf(\"%dx\", size(expected))(1:end-1) \")\"];\n          err.reason{end+1} = \"Dimensions don't match\";\n        else\n          try\n            ## Recursively compare cell arrays\n            for i = 1:length (expected(:))\n              assert (cond{i}, expected{i}, tol);\n            endfor\n          catch\n            err.index{end+1} = \"{}\";\n            err.observed{end+1} = \"O\";\n            err.expected{end+1} = \"E\";\n            err.reason{end+1} = \"Cell configuration error\";\n          end_try_catch\n        endif\n\n      elseif (is_function_handle (expected))\n        if (! is_function_handle (cond))\n          err.index{end+1} = \"@\";\n          err.observed{end+1} = \"O\";\n          err.expected{end+1} = \"E\";\n          err.reason{end+1} = [\"Expected function handle, but observed \" class(cond)];\n        elseif (! isequal (cond, expected))\n          err.index{end+1} = \"@\";\n          err.observed{end+1} = \"O\";\n          err.expected{end+1} = \"E\";\n          err.reason{end+1} = \"Function handles don't match\";\n        endif\n\n      elseif (isstruct (expected))\n        if (! isstruct (cond))\n          err.index{end+1} = \".\";\n          err.observed{end+1} = \"O\";\n          err.expected{end+1} = \"E\";\n          err.reason{end+1} = [\"Expected struct, but observed \" class(cond)];\n        elseif (ndims (cond) != ndims (expected)\n                || any (size (cond) != size (expected))\n                || numfields (cond) != numfields (expected))\n\n          err.index{end+1} = \".\";\n          err.observed{end+1} = [\"O(\" sprintf(\"%dx\", size(cond))(1:end-1) \")\"];\n          err.expected{end+1} = [\"E(\" sprintf(\"%dx\", size(expected))(1:end-1) \")\"];\n          err.reason{end+1} = \"Structure sizes don't match\";\n        elseif (! strcmp (sort (fieldnames (cond)),\n                          sort (fieldnames (expected))))\n          err.index{end+1} = \".\";\n          err.observed{end+1} = \"O\";\n          err.expected{end+1} = \"E\";\n          err.reason{end+1} = \"Structure fieldname mismatch\";\n        else\n          try\n            ## Test if both structs are empty, i.e., 0x0, Nx0, or Nx0 structs.\n            ## In this case the values cannot be extracted for comparison as\n            ## they are not assignable and not defined.\n            assert (isempty (cond), isempty (expected));\n\n            if (! isempty (cond))\n              for [v, k] = cond\n                if (numel (cond) == 1)\n                  v = {v};\n                else\n                  v = v(:)';\n                endif\n                ## Recursively call assert for struct array values\n                assert (v, {expected.(k)}, tol);\n              endfor\n            endif\n          catch\n            err.index{end+1} = \".\";\n            err.observed{end+1} = \"O\";\n            err.expected{end+1} = \"E\";\n            err.reason{end+1} = \"Structure configuration error\";\n          end_try_catch\n        endif\n\n      elseif (ndims (cond) != ndims (expected)\n              || any (size (cond) != size (expected)))\n        err.index{end+1} = \".\";\n        err.observed{end+1} = [\"O(\" sprintf(\"%dx\", size(cond))(1:end-1) \")\"];\n        err.expected{end+1} = [\"E(\" sprintf(\"%dx\", size(expected))(1:end-1) \")\"];\n        err.reason{end+1} = \"Dimensions don't match\";\n\n      else  # Numeric comparison\n        if (nargin < 3)\n          ## Without explicit tolerance, be more strict.\n          if (! strcmp (class (cond), class (expected)))\n            err.index{end+1} = \"()\";\n            err.observed{end+1} = \"O\";\n            err.expected{end+1} = \"E\";\n            err.reason{end+1} = [\"Class \" class(cond) \" != \" class(expected)];\n          elseif (isnumeric (cond) || islogical (cond))\n            if (issparse (cond) != issparse (expected))\n              err.index{end+1} = \"()\";\n              err.observed{end+1} = \"O\";\n              err.expected{end+1} = \"E\";\n              if (issparse (cond))\n                err.reason{end+1} = \"sparse != non-sparse\";\n              else\n                err.reason{end+1} = \"non-sparse != sparse\";\n              endif\n            elseif (iscomplex (cond) != iscomplex (expected))\n              err.index{end+1} = \"()\";\n              err.observed{end+1} = \"O\";\n              err.expected{end+1} = \"E\";\n             if (iscomplex (cond))\n                err.reason{end+1} = \"complex != real\";\n              else\n                err.reason{end+1} = \"real != complex\";\n              endif\n            endif\n          endif\n        endif\n\n        if (isempty (err.index))\n\n          A = cond;\n          B = expected;\n\n          if (isinteger (A) && isinteger (B))\n            ## Non-floating point numbers can't have exceptional or complex\n            ## values so skip tests.\n            A_null = A;\n            B_null = B;\n          else\n            ## Check exceptional values.\n            is_real = (isreal (A) && isreal (B));\n            if (is_real)\n              errvec = (isna (A) != isna (B));\n            else\n              errvec = (  isna (real (A)) != isna (real (B))\n                        | isna (imag (A)) != isna (imag (B)));\n            endif\n            erridx = find (errvec);\n            if (! isempty (erridx))\n              err.index(end+1:end+length (erridx)) = ...\n                ind2tuple (size (A), erridx);\n              err.observed(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (A(erridx) (:))));\n              err.expected(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (B(erridx) (:))));\n              err.reason(end+1:end+length (erridx)) = ...\n                repmat ({\"'NA' mismatch\"}, length (erridx), 1);\n            endif\n            errseen = errvec;\n\n            if (is_real)\n              errvec = (isnan (A) != isnan (B));\n            else\n              errvec = (  isnan (real (A)) != isnan (real (B))\n                        | isnan (imag (A)) != isnan (imag (B)));\n            endif\n            erridx = find (errvec & ! errseen);\n            if (! isempty (erridx))\n              err.index(end+1:end+length (erridx)) = ...\n                ind2tuple (size (A), erridx);\n              err.observed(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (A(erridx) (:))));\n              err.expected(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (B(erridx) (:))));\n              err.reason(end+1:end+length (erridx)) = ...\n                repmat ({\"'NaN' mismatch\"}, length (erridx), 1);\n            endif\n            errseen |= errvec;\n\n            if (is_real)\n              errvec = ((isinf (A) | isinf (B)) & (real (A) != real (B)));\n            else\n              errvec =   ((isinf (real (A)) | isinf (real (B))) ...\n                          & (real (A) != real (B)))             ...\n                       | ((isinf (imag (A)) | isinf (imag (B))) ...\n                          & (imag (A) != imag (B)));\n            endif\n            erridx = find (errvec & ! errseen);\n            if (! isempty (erridx))\n              err.index(end+1:end+length (erridx)) = ...\n                ind2tuple (size (A), erridx);\n              err.observed(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (A(erridx) (:))));\n              err.expected(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (B(erridx) (:))));\n              err.reason(end+1:end+length (erridx)) = ...\n                repmat ({\"'Inf' mismatch\"}, length (erridx), 1);\n            endif\n            errseen |= errvec;\n\n            ## Check normal values.\n            ## Replace exceptional values already checked above by zero.\n            if (is_real)\n              A_null_real = A;\n              B_null_real = B;\n            else\n              A_null_real = real (A);\n              B_null_real = real (B);\n            endif\n            if (issparse (errseen))\n              exclude = errseen ...\n                        | isnan (A_null_real) | isinf (A_null_real) ...\n                        | isnan (B_null_real) | isinf (B_null_real);\n            else\n              exclude = errseen ...\n                        | ! isfinite (A_null_real) & ! isfinite (B_null_real);\n            endif\n            A_null_real(exclude) = 0;\n            B_null_real(exclude) = 0;\n\n            if (is_real)\n              A_null = A_null_real;\n              B_null = B_null_real;\n            else\n              A_null_imag = imag (A);\n              B_null_imag = imag (B);\n              if (issparse (errseen))\n                exclude = errseen ...\n                          | isnan (A_null_imag) | isinf (A_null_imag) ...\n                          | isnan (B_null_imag) | isinf (B_null_imag);\n              else\n                exclude = errseen ...\n                          | ! isfinite (A_null_imag) & ! isfinite (B_null_imag);\n              endif\n\n              A_null_imag(exclude) = 0;\n              B_null_imag(exclude) = 0;\n              A_null = complex (A_null_real, A_null_imag);\n              B_null = complex (B_null_real, B_null_imag);\n            endif\n\n            clear A_null_real B_null_real;\n            clear A_null_imag B_null_imag;\n          endif\n\n          if (isscalar (tol))\n            mtol = tol * ones (size (A));\n          else\n            mtol = tol;\n          endif\n\n          k = (mtol == 0);\n          erridx = find ((A_null != B_null) & k);\n          if (! isempty (erridx))\n            err.index(end+1:end+length (erridx)) = ...\n              ind2tuple (size (A), erridx);\n            err.observed(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (A(erridx) (:))));\n            err.expected(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (B(erridx) (:))));\n            err.reason(end+1:end+length (erridx)) = ...\n              ostrsplit (deblank (\n                         sprintf (\"Abs err %.5g exceeds tol %.5g by %.1g\\n\",\n                [abs(A_null(erridx) - B_null(erridx))(:), mtol(erridx)(:), ...\n                 abs(A_null(erridx) - B_null(erridx))(:)-mtol(erridx)(:)].')),\n                         \"\\n\");\n          endif\n\n          k = (mtol > 0);\n          erridx = find ((abs (A_null - B_null) > mtol) & k);\n          if (! isempty (erridx))\n            err.index(end+1:end+length (erridx)) = ...\n              ind2tuple (size (A), erridx);\n            err.observed(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (A(erridx) (:))));\n            err.expected(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (B(erridx) (:))));\n            err.reason(end+1:end+length (erridx)) = ...\n              ostrsplit (deblank (\n                         sprintf (\"Abs err %.5g exceeds tol %.5g by %.1g\\n\",\n                [abs(A_null(erridx) - B_null(erridx))(:), mtol(erridx)(:), ...\n                 abs(A_null(erridx) - B_null(erridx))(:)-mtol(erridx)(:)].')),\n                         \"\\n\");\n          endif\n\n          k = (mtol < 0);\n          if (any (k(:)))\n            ## Test for absolute error where relative error can't be calculated.\n            erridx = find ((B_null == 0) & abs (A_null) > abs (mtol) & k);\n            if (! isempty (erridx))\n              err.index(end+1:end+length (erridx)) = ...\n                ind2tuple (size (A), erridx);\n              err.observed(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (A(erridx) (:))));\n              err.expected(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (B(erridx) (:))));\n              err.reason(end+1:end+length (erridx)) = ...\n                ostrsplit (deblank (\n                           sprintf (\"Abs err %.5g exceeds tol %.5g by %.1g\\n\",\n                      [abs(A_null(erridx) - B_null(erridx)), -mtol(erridx), ...\n                       abs(A_null(erridx) - B_null(erridx))+mtol(erridx)].')),\n                           \"\\n\");\n            endif\n            ## Test for relative error\n            Bdiv = Inf (size (B_null));\n            Bdiv(k & (B_null != 0)) = B_null(k & (B_null != 0));\n            relerr = abs ((A_null - B_null) ./ abs (Bdiv));\n            erridx = find ((relerr > abs (mtol)) & k);\n            if (! isempty (erridx))\n              err.index(end+1:end+length (erridx)) = ...\n                ind2tuple (size (A), erridx);\n              err.observed(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (A(erridx) (:))));\n              err.expected(end+1:end+length (erridx)) = ...\n                strtrim (cellstr (num2str (B(erridx) (:))));\n              err.reason(end+1:end+length (erridx)) = ...\n                ostrsplit (deblank (\n                           sprintf (\"Rel err %.5g exceeds tol %.5g by %.1g\\n\",\n                                    [relerr(erridx)(:), -mtol(erridx)(:), ...\n                                     relerr(erridx)(:)+mtol(erridx)(:)].')),\n                           \"\\n\");\n            endif\n          endif\n        endif\n\n      endif\n\n      ## Print any errors\n      if (! isempty (err.index))\n        arg_names = cell (nargin, 1);\n        for i = 1:nargin\n          arg_names{i} = inputname (i, false);\n        endfor\n        argin = [\"(\" strjoin(arg_names, \",\") \")\"];\n        if (! isempty (errmsg))\n          errmsg = [errmsg \"\\n\"];\n        endif\n        errmsg = [errmsg, pprint(argin, err)];\n      endif\n\n    endif\n\n  unwind_protect_cleanup\n    call_depth -= 1;\n  end_unwind_protect\n\n  if (call_depth == -1)\n    ## Last time through.  If there were any errors on any pass, raise a flag.\n    if (! isempty (errmsg))\n\n      ## We don't want to start the debugger here if debug_on_error is\n      ## true so we set it to false and make the change local.  Then\n      ## debug_on_error will be reset to true after this function\n      ## returns and the debugger will start at the location of the call\n      ## to print_usage.\n      debug_on_error (false, \"local\");\n\n      error (errmsg);\n    endif\n  endif\n\nendfunction\n\n\n## empty input\n%!error assert ([])\n%!error assert (\"\")\n%!error assert ({})\n%!error assert (struct ([]))\n%!assert (zeros (3,0), zeros (3,0))\n%!error <O\\(3x0\\)\\s+E\\(0x2\\)> assert (zeros (3,0), zeros (0,2))\n%!error <Dimensions don't match> assert (zeros (3,0), [])\n%!error <Dimensions don't match> assert (zeros (2,0,2), zeros (2,0))\n\n## conditions\n%!assert (isempty ([]))\n%!assert (1)\n%!error assert (0)\n%!assert (ones (3,1))\n%!assert (ones (1,3))\n%!assert (ones (3,4))\n%!error assert ([1,0,1])\n%!error assert ([1;1;0])\n%!error assert ([1,0;1,1])\n%!error <2-part error> assert (false, \"%s %s\", \"2-part\", \"error\")\n%!error <2-part error> assert (false, \"TST:msg_id\", \"%s %s\", \"2-part\", \"error\")\n\n## scalars\n%!error <Dimensions don't match> assert (3, [3,3])\n%!error <Dimensions don't match> assert (3, [3,3; 3,3])\n%!error <Dimensions don't match> assert ([3,3; 3,3], 3)\n%!assert (3, 3)\n%!error <Abs err 1 exceeds tol> assert (3, 4)\n%!assert (3+eps, 3, eps)\n%!assert (3, 3+eps, eps)\n%!error <Abs err 4.4409e-0?16 exceeds tol> assert (3+2*eps, 3, eps)\n%!error <Abs err 4.4409e-0?16 exceeds tol> assert (3, 3+2*eps, eps)\n\n## vectors\n%!assert ([1,2,3],[1,2,3])\n%!assert ([1;2;3],[1;2;3])\n%!error <Abs err 1 exceeds tol 0> assert ([2,2,3,3],[1,2,3,4])\n%!error <Abs err 1 exceeds tol 0.5> assert ([2,2,3,3],[1,2,3,4],0.5)\n%!error <Rel err 1 exceeds tol 0.1> assert ([2,2,3,5],[1,2,3,4],-0.1)\n%!error <Abs err 1 exceeds tol 0> assert ([6;6;7;7],[5;6;7;8])\n%!error <Abs err 1 exceeds tol 0.5> assert ([6;6;7;7],[5;6;7;8],0.5)\n%!error <Rel err .* exceeds tol 0.1> assert ([6;6;7;7],[5;6;7;8],-0.1)\n%!error <Dimensions don't match> assert ([1,2,3],[1;2;3])\n%!error <Dimensions don't match> assert ([1,2],[1,2,3])\n%!error <Dimensions don't match> assert ([1;2;3],[1;2])\n\n## matrices\n%!assert ([1,2;3,4],[1,2;3,4])\n%!error <\\(1,2\\)\\s+4\\s+2> assert ([1,4;3,4],[1,2;3,4])\n%!error <Dimensions don't match> assert ([1,3;2,4;3,5],[1,2;3,4])\n%!test  # 2-D matrix\n%! A = [1 2 3]'*[1,2];\n%! assert (A, A);\n%! fail (\"assert (A.*(A!=2),A)\");\n%!test  # N-D matrix\n%! X = zeros (2,2,3);\n%! Y = X;\n%! Y(1,2,3) = 1.5;\n%! fail (\"assert (X,Y)\", \"\\(1,2,3\\).*Abs err 1.5 exceeds tol 0\");\n\n## must give a small tolerance for floating point errors on relative\n%!assert (100+100*eps, 100, -2*eps)\n%!assert (100, 100+100*eps, -2*eps)\n%!error <Rel err .* exceeds tol> assert (100+300*eps, 100, -2*eps)\n%!error <Rel err .* exceeds tol> assert (100, 100+300*eps, -2*eps)\n\n## test relative vs. absolute tolerances\n%!test  assert (0.1+eps, 0.1, 2*eps);\n%!error <Rel err 2.2204e-0?15 exceeds tol> assert (0.1+eps, 0.1, -2*eps)\n%!test  assert (100+100*eps, 100, -2*eps);\n%!error <Abs err 2.8422e-0?14 exceeds tol> assert (100+100*eps, 100, 2*eps)\n\n## Corner case of relative tolerance with 0 divider\n%!error <Abs err 2 exceeds tol 0.1> assert (2, 0, -0.1)\n\n## Extra checking of inputs when tolerance unspecified.\n%!error <Class single != double> assert (single (1), 1)\n%!error <Class uint8 != uint16> assert (uint8 (1), uint16 (1))\n%!error <sparse != non-sparse> assert (sparse([1]), [1])\n%!error <non-sparse != sparse> assert ([1], sparse([1]))\n%!error <complex != real> assert (1+i, 1)\n%!error <real != complex> assert (1, 1+i)\n\n## exceptional values\n%!assert ([NaN, NA, Inf, -Inf, 1+eps, eps], [NaN, NA, Inf, -Inf, 1, 0], eps)\n\n%!error <'NaN' mismatch> assert (NaN, 1)\n%!error <'NaN' mismatch> assert ([NaN 1], [1 NaN])\n%!test\n%! try\n%!   assert ([NaN 1], [1 NaN]);\n%! catch\n%!   errmsg = lasterr ();\n%!   if (sum (errmsg () == \"\\n\") != 4)\n%!     error (\"Too many errors reported for NaN assert\");\n%!   elseif (strfind (errmsg, \"NA\"))\n%!     error (\"NA reported for NaN assert\");\n%!   elseif (strfind (errmsg, \"Abs err NaN exceeds tol 0\"))\n%!     error (\"Abs err reported for NaN assert\");\n%!   endif\n%! end_try_catch\n\n%!error <'NA' mismatch> assert (NA, 1)\n%!error assert ([NA 1]', [1 NA]')\n%!test\n%! try\n%!   assert ([NA 1]', [1 NA]');\n%! catch\n%!   errmsg = lasterr ();\n%!   if (sum (errmsg () == \"\\n\") != 4)\n%!     error (\"Too many errors reported for NA assert\");\n%!   elseif (strfind (errmsg, \"NaN\"))\n%!     error (\"NaN reported for NA assert\");\n%!   elseif (strfind (errmsg, \"Abs err NA exceeds tol 0\"))\n%!     error (\"Abs err reported for NA assert\");\n%!   endif\n%! end_try_catch\n%!error assert ([(complex (NA, 1)) (complex (2, NA))], [(complex (NA, 2)) 2])\n\n%!error <'Inf' mismatch> assert (-Inf, Inf)\n%!error <'Inf' mismatch> assert ([-Inf Inf], [Inf -Inf])\n%!test\n%! try\n%!   assert (complex (Inf, 0.2), complex (-Inf, 0.2 + 2*eps), eps);\n%! catch\n%!   errmsg = lasterr ();\n%!   if (sum (errmsg () == \"\\n\") != 3)\n%!     error (\"Too many errors reported for Inf assert\");\n%!   elseif (strfind (errmsg, \"Abs err\"))\n%!     error (\"Abs err reported for Inf assert\");\n%!   endif\n%! end_try_catch\n%!error <Abs err> assert (complex (Inf, 0.2), complex (Inf, 0.2 + 2*eps), eps)\n\n## strings\n%!assert (\"dog\", \"dog\")\n%!error <Strings don't match> assert (\"dog\", \"cat\")\n%!error <Expected string, but observed number> assert (3, \"dog\")\n%!error <Class char != double> assert (\"dog\", [3 3 3])\n%!error <Expected string, but observed cell> assert ({\"dog\"}, \"dog\")\n%!error <Expected string, but observed struct> assert (struct (\"dog\", 3), \"dog\")\n\n## cell arrays\n%!error <Expected cell, but observed double> assert (1, {1})\n%!error <Dimensions don't match> assert (cell (1,2,3), cell (3,2,1))\n%!test\n%! x = {{{1}}, 2};  # cell with multiple levels\n%! y = x;\n%! assert (x,y);\n%! y{1}{1}{1} = 3;\n%! fail (\"assert (x,y)\", \"Abs err 2 exceeds tol 0\");\n\n## function handles\n%!assert (@sin, @sin)\n%!error <Function handles don't match> assert (@sin, @cos)\n%!error <Expected function handle, but observed double> assert (pi, @cos)\n%!error <Class function_handle != double> assert (@sin, pi)\n\n%!test\n%! x = {[3], [1,2,3]; 100+100*eps, \"dog\"};\n%! y = x;\n%! assert (x, y);\n%! y = x; y(1,1) = [2];\n%! fail (\"assert (x, y)\");\n%! y = x; y(1,2) = [0, 2, 3];\n%! fail (\"assert (x, y)\");\n%! y = x; y(2,1) = 101;\n%! fail (\"assert (x, y)\");\n%! y = x; y(2,2) = \"cat\";\n%! fail (\"assert (x, y)\");\n%! y = x; y(1,1) = [2]; y(1,2) = [0, 2, 3]; y(2,1) = 101; y(2,2) = \"cat\";\n%! fail (\"assert (x, y)\");\n\n## structures\n%!error <Expected struct, but observed double> assert (1, struct (\"a\", 1))\n%!error <Structure sizes don't match>\n%! x(1,2,3).a = 1;\n%! y(1,2).a = 1;\n%! assert (x,y);\n%!error <Structure sizes don't match>\n%! x(1,2,3).a = 1;\n%! y(3,2,2).a = 1;\n%! assert (x,y);\n%!error <Structure sizes don't match>\n%! x.a = 1;\n%! x.b = 1;\n%! y.a = 1;\n%! assert (x,y);\n%!error <Structure fieldname mismatch>\n%! x.b = 1;\n%! y.a = 1;\n%! assert (x,y);\n\n%!test\n%! x.a = 1; x.b=[2, 2];\n%! y.a = 1; y.b=[2, 2];\n%! assert (x, y);\n%! y.b=3;\n%! fail (\"assert (x, y)\");\n%! fail (\"assert (3, x)\");\n%! fail (\"assert (x, 3)\");\n%! ## Empty structures\n%! x = resize (x, 0, 1);\n%! y = resize (y, 0, 1);\n%! assert (x, y);\n\n## vector of tolerances\n%!test\n%! x = [-40:0];\n%! y1 = (10.^x).*(10.^x);\n%! y2 = 10.^(2*x);\n%! ## Increase tolerance from eps (y1) to 4*eps (y1) because of an upstream bug\n%! ## in mingw-w64: https://sourceforge.net/p/mingw-w64/bugs/466/\n%! assert (y1, y2, 4*eps (y1));\n%! fail (\"assert (y1, y2 + eps*1e-70, eps (y1))\");\n\n## Multiple tolerances\n%!test\n%! x = [1 2; 3 4];\n%! y = [0 -1; 1 2];\n%! tol = [-0.1 0; -0.2 0.3];\n%! try\n%!   assert (x, y, tol);\n%! catch\n%!   errmsg = lasterr ();\n%!   if (sum (errmsg () == \"\\n\") != 6)\n%!     error (\"Incorrect number of errors reported\");\n%!   endif\n%!   assert (! isempty (regexp (errmsg, '\\(1,2\\).*Abs err 3 exceeds tol 0\\>')));\n%!   assert (! isempty (regexp (errmsg, '\\(2,2\\).*Abs err 2 exceeds tol 0.3')));\n%!   assert (! isempty (regexp (errmsg, '\\(1,1\\).*Abs err 1 exceeds tol 0.1')));\n%!   assert (! isempty (regexp (errmsg, '\\(2,1\\).*Rel err 2 exceeds tol 0.2')));\n%! end_try_catch\n\n%!test <*57615>\n%! try\n%!   assert (complex (pi*1e-17,2*pi), 0, 1e-1);\n%! catch\n%!   errmsg = lasterr ();\n%!   assert (isempty (strfind (errmsg, \"sprintf: invalid field width\")));\n%! end_try_catch\n\n%!test <*63988>\n%! A = [\"ab\"; \"cd\"];\n%! B = [\"ad\"; \"cb\"];\n%! try\n%!   assert (A, B);\n%! catch\n%!   errmsg = lasterr ();\n%!   if (regexp (errmsg, 'horizontal dimensions mismatch'))\n%!     error (\"assert failed for char arrays with multiple rows\");\n%!   endif\n%! end_try_catch\n\n## test input validation\n%!error <Invalid call> assert ()\n%!error <Invalid call> assert (1,2,3,4)\n\n\n## Convert all error indices into tuple format\nfunction cout = ind2tuple (matsize, erridx)\n\n  tmp = cell (1, numel (matsize));\n  [tmp{:}] = ind2sub (matsize, erridx(:));\n  subs = [tmp{:}];\n  if (numel (matsize) == 2)\n    subs = subs(:, matsize != 1);  # For vectors, use 1-D index\n  endif\n  fmt = repmat ('%d,', 1, max (columns (subs), 1));\n  fmt(end) = [];   # delete final extra comma\n  cout = ostrsplit (sprintf (['(' fmt ')', '$'], subs'), '$');\n  cout(end) = [];  # delete extra cell from final '$'\n  cout = cout.';   # return column vector\n\nendfunction\n\n\n## Pretty print the various errors in a condensed tabular format.\nfunction str = pprint (argin, err)\n\n  str = [\"ASSERT errors for:  assert \" argin \"\\n\"];\n  str = [str, \"\\n  Location  |  Observed  |  Expected  |  Reason\\n\"];\n\n  pos = numel (str);\n  str(pos + 100 * numel (err.index)) = ' ';\n  for i = 1:numel (err.index)\n    leni = numel (err.index{i});\n    leno = numel (err.observed{i});\n    lene = numel (err.expected{i});\n    tmp = sprintf (\"%*s%*s %*s%*s %*s%*s   %s\\n\",\n                   6+fix(leni/2), err.index{i}   , max (6-fix(leni/2), 0), \"\",\n                   6+fix(leno/2), err.observed{i}, max (6-fix(leno/2), 0), \"\",\n                   6+fix(lene/2), err.expected{i}, max (6-fix(lene/2), 0), \"\",\n                   err.reason{i});\n    if (pos + numel (tmp) > numel (str))\n      str(end + 1e6) = ' ';\n    endif\n    str((pos + 1):(pos + numel (tmp))) = tmp;\n    pos += numel (tmp);\n  endfor\n  str = str(1:pos);\n\nendfunction\n"
  },
  {
    "path": "scripts/testfun/assert_equal.m",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} assert_equal (@var{observed}, @var{expected})\n## @deftypefnx {} {} assert_equal (@var{observed}, @var{expected}, @var{tol})\n##\n## Produce an error if observed is not the same as expected.\n##\n## @code{assert_equal (@var{observed}, @var{expected})} tests for the two input\n## arguments being equal with respect to their class, size, and value.  All\n## octave values are supported as input for @var{observed} and @var{expected}\n## and compared for equality according to the following rules.\n##\n## @itemize\n## @item Numeric inputs that support exceptional values (i.e., Inf, -Inf, NaN,\n## NA) are treated under the additional assumption that they are equal.  They\n## are also tested for sparsity and complexity.\n##\n## @item Logical inputs are additionally tested for sparsity.\n##\n## @item Character arrays are compared with the @code{strcmp} function.\n##\n## @item Structures are additionally checked against having the same unordered\n## fieldnames.\n##\n## @item Cell arrays are recursively tested on an element by element basis.\n##\n## @item Function handles are tested with the @code{isequal} function.\n##\n## @item Classdef objects are explicitly tested if and only if they have an\n## overloaded @code{eq} method and unless @code{all (eq (@var{observed},\n## @var{expected}), \"all\")} is true, an error is produced.  The handling of\n## missing values is strictly defined by the overloaded @code{eq} method.\n## @end itemize\n##\n## @code{assert_equal (@var{observed}, @var{expected}, @var{tol})} further\n## specifies a tolerance value, which is explicitly used for numerical inputs.\n## Specifying @var{tol} as 0, is equivalent to calling @code{assert_equal} with\n## only two input arguments.  Any nonzero tolerance is also ignored when\n## @var{observed} and @var{expected} are non-numeric.  Logical and character\n## arrays are not considered to be numeric.\n##\n## If @var{tol} is positive then it is an absolute tolerance which will produce\n## an error if @code{abs (@var{observed} - @var{expected}) > abs (@var{tol})}.\n##\n## If @var{tol} is negative then it is a relative tolerance which will produce\n## an error if @code{abs (@var{observed} - @var{expected}) >\n## abs (@var{tol} * @var{expected})}.\n##\n## If @var{expected} is zero @var{tol} will always be interpreted as an\n## absolute tolerance.\n##\n## If @var{tol} is not scalar its dimensions must agree with those of\n## @var{observed} and @var{expected} and tests are performed on an\n## element-by-element basis.\n## @seealso{fail, test, error, isequal, eq, strcmp, assert}\n## @end deftypefn\n\nfunction assert_equal (observed, expected, tol = 0)\n\n  if (nargin < 2 || nargin > 3)\n    print_usage ();\n  endif\n\n  ## Capture argument names for display at the top level only.\n  arg_names = cell (nargin, 1);\n  for i = 1:nargin\n    arg_names{i} = inputname (i, false);\n  endfor\n  argin = [\"(\" strjoin(arg_names, \",\") \")\"];\n\n  ## Delegate to implementation function which handles recursion.\n  __assert_impl__ (observed, expected, tol, argin);\n\nendfunction\n\n\n## Implementation function for assert comparison.\n## This is separated to preserve display names across recursive calls.\nfunction __assert_impl__ (observed, expected, tol, argin)\n\n  persistent call_depth = -1;\n  persistent errmsg;\n\n  unwind_protect\n\n    call_depth += 1;\n\n    if (call_depth == 0)\n      errmsg = \"\";\n    endif\n\n    ## Add to list as the errors accumulate.  If empty at end then no errors.\n    err.index = {};\n    err.observed = {};\n    err.expected = {};\n    err.reason = {};\n\n    if (isobject (expected))\n      if (! isobject (observed))\n        err.index{end+1} = \".\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = [\"Expected classdef object, but observed \" class(observed)];\n      elseif (! strcmp (class (observed), class (expected)))\n        err.index{end+1} = \".\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = [\"Expected '\" class(expected) \"' but observed '\" class(observed) \"'\"];\n      elseif (ndims (observed) != ndims (expected)\n              || any (size (observed) != size (expected)))\n        err.index{end+1} = \".\";\n        err.observed{end+1} = [\"O(\" sprintf(\"%dx\", size(observed))(1:end-1) \")\"];\n        err.expected{end+1} = [\"E(\" sprintf(\"%dx\", size(expected))(1:end-1) \")\"];\n        err.reason{end+1} = \"Dimensions don't match\";\n      elseif (! ismember (\"eq\", methods (expected)))\n        err.index{end+1} = \".\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = \"Expected classdef object does not have an 'eq' method\";\n      elseif (! all (eq (observed, expected), \"all\"))\n        err.index{end+1} = \"()\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = \"Classdef objects do not match\";\n      endif\n\n    elseif (ischar (expected))\n      if (! ischar (observed))\n        err.index{end+1} = \".\";\n        err.expected{end+1} = [\"'\" expected \"'\"];\n        if (isnumeric (observed))\n          err.observed{end+1} = num2str (observed);\n          err.reason{end+1} = \"Expected string, but observed number\";\n        else\n          err.observed{end+1} = \"O\";\n          err.reason{end+1} = [\"Expected string, but observed \" class(observed)];\n        endif\n      elseif (! strcmp (observed, expected))\n        err.index{end+1} = \"[]\";\n        err.observed{end+1} = [\"'\" observed(:).' \"'\"];\n        err.expected{end+1} = [\"'\" expected(:).' \"'\"];\n        err.reason{end+1} = \"Strings don't match\";\n      endif\n\n    elseif (iscell (expected))\n      if (! iscell (observed))\n        err.index{end+1} = \".\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = [\"Expected cell, but observed \" class(observed)];\n      elseif (ndims (observed) != ndims (expected)\n              || any (size (observed) != size (expected)))\n        err.index{end+1} = \".\";\n        err.observed{end+1} = [\"O(\" sprintf(\"%dx\", size(observed))(1:end-1) \")\"];\n        err.expected{end+1} = [\"E(\" sprintf(\"%dx\", size(expected))(1:end-1) \")\"];\n        err.reason{end+1} = \"Dimensions don't match\";\n      else\n        try\n          ## Recursively compare cell arrays\n          for i = 1:length (expected(:))\n            __assert_impl__ (observed{i}, expected{i}, tol, argin);\n          endfor\n        catch\n          err.index{end+1} = \"{}\";\n          err.observed{end+1} = \"O\";\n          err.expected{end+1} = \"E\";\n          err.reason{end+1} = \"Cell configuration error\";\n        end_try_catch\n      endif\n\n    elseif (is_function_handle (expected))\n      if (! is_function_handle (observed))\n        err.index{end+1} = \"@\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = [\"Expected function handle, but observed \" class(observed)];\n      elseif (! isequal (observed, expected))\n        err.index{end+1} = \"@\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = \"Function handles don't match\";\n      endif\n\n    elseif (isstruct (expected))\n      if (! isstruct (observed))\n        err.index{end+1} = \".\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = [\"Expected struct, but observed \" class(observed)];\n      elseif (ndims (observed) != ndims (expected)\n              || any (size (observed) != size (expected))\n              || numfields (observed) != numfields (expected))\n\n        err.index{end+1} = \".\";\n        err.observed{end+1} = [\"O(\" sprintf(\"%dx\", size(observed))(1:end-1) \")\"];\n        err.expected{end+1} = [\"E(\" sprintf(\"%dx\", size(expected))(1:end-1) \")\"];\n        err.reason{end+1} = \"Structure sizes don't match\";\n      elseif (! strcmp (sort (fieldnames (observed)),\n                        sort (fieldnames (expected))))\n        err.index{end+1} = \".\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = \"Structure fieldname mismatch\";\n      else\n        try\n          ## Test if both structs are empty, i.e., 0x0, Nx0, or 0xN structs.\n          ## In this case the values cannot be extracted for comparison as\n          ## they are not assignable and not defined.\n          __assert_impl__ (isempty (observed), isempty (expected), 0, argin);\n\n          if (! isempty (observed))\n            for [v, k] = observed\n              if (numel (observed) == 1)\n                v = {v};\n              else\n                v = v(:)';\n              endif\n              ## Recursively call assert for struct array values\n              __assert_impl__ (v, {expected.(k)}, tol, argin);\n            endfor\n          endif\n        catch\n          err.index{end+1} = \".\";\n          err.observed{end+1} = \"O\";\n          err.expected{end+1} = \"E\";\n          err.reason{end+1} = \"Structure configuration error\";\n        end_try_catch\n      endif\n\n    elseif (ndims (observed) != ndims (expected)\n            || any (size (observed) != size (expected)))\n      err.index{end+1} = \".\";\n      err.observed{end+1} = [\"O(\" sprintf(\"%dx\", size(observed))(1:end-1) \")\"];\n      err.expected{end+1} = [\"E(\" sprintf(\"%dx\", size(expected))(1:end-1) \")\"];\n      err.reason{end+1} = \"Dimensions don't match\";\n\n    else  ## Numeric comparison\n      ## Always require matching class, sparsity, and complexity,\n      ## regardless of whether a tolerance was provided.\n      if (! strcmp (class (observed), class (expected)))\n        err.index{end+1} = \"()\";\n        err.observed{end+1} = \"O\";\n        err.expected{end+1} = \"E\";\n        err.reason{end+1} = [\"Class \" class(observed) \" != \" class(expected)];\n      elseif (isnumeric (observed) || islogical (observed))\n        if (issparse (observed) != issparse (expected))\n          err.index{end+1} = \"()\";\n          err.observed{end+1} = \"O\";\n          err.expected{end+1} = \"E\";\n          if (issparse (observed))\n            err.reason{end+1} = \"sparse != non-sparse\";\n          else\n            err.reason{end+1} = \"non-sparse != sparse\";\n          endif\n        elseif (iscomplex (observed) != iscomplex (expected))\n          err.index{end+1} = \"()\";\n          err.observed{end+1} = \"O\";\n          err.expected{end+1} = \"E\";\n          if (iscomplex (observed))\n            err.reason{end+1} = \"complex != real\";\n          else\n            err.reason{end+1} = \"real != complex\";\n          endif\n        endif\n      endif\n\n      if (isempty (err.index))\n\n        A = observed;\n        B = expected;\n\n        if (isinteger (A) && isinteger (B))\n          ## Non-floating point numbers can't have exceptional or complex\n          ## values so skip tests.\n          A_null = A;\n          B_null = B;\n        elseif (islogical (A) && islogical (B))\n          ## Logical values can't have exceptional or complex\n          ## values so skip tests.  Ignore tolerance for logical values.\n          A_null = A;\n          B_null = B;\n          mtol = 0;\n        else\n          ## Check exceptional values.\n          is_real = (isreal (A) && isreal (B));\n          if (is_real)\n            errvec = (isna (A) != isna (B));\n          else\n            errvec = (  isna (real (A)) != isna (real (B))\n                      | isna (imag (A)) != isna (imag (B)));\n          endif\n          erridx = find (errvec);\n          if (! isempty (erridx))\n            err.index(end+1:end+length (erridx)) = ...\n              ind2tuple (size (A), erridx);\n            err.observed(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (A(erridx) (:))));\n            err.expected(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (B(erridx) (:))));\n            err.reason(end+1:end+length (erridx)) = ...\n              repmat ({\"'NA' mismatch\"}, length (erridx), 1);\n          endif\n          errseen = errvec;\n\n          if (is_real)\n            errvec = (isnan (A) != isnan (B));\n          else\n            errvec = (  isnan (real (A)) != isnan (real (B))\n                      | isnan (imag (A)) != isnan (imag (B)));\n          endif\n          erridx = find (errvec & ! errseen);\n          if (! isempty (erridx))\n            err.index(end+1:end+length (erridx)) = ...\n              ind2tuple (size (A), erridx);\n            err.observed(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (A(erridx) (:))));\n            err.expected(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (B(erridx) (:))));\n            err.reason(end+1:end+length (erridx)) = ...\n              repmat ({\"'NaN' mismatch\"}, length (erridx), 1);\n          endif\n          errseen |= errvec;\n\n          if (is_real)\n            errvec = ((isinf (A) | isinf (B)) & (real (A) != real (B)));\n          else\n            errvec =   ((isinf (real (A)) | isinf (real (B))) ...\n                        & (real (A) != real (B)))             ...\n                     | ((isinf (imag (A)) | isinf (imag (B))) ...\n                        & (imag (A) != imag (B)));\n          endif\n          erridx = find (errvec & ! errseen);\n          if (! isempty (erridx))\n            err.index(end+1:end+length (erridx)) = ...\n              ind2tuple (size (A), erridx);\n            err.observed(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (A(erridx) (:))));\n            err.expected(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (B(erridx) (:))));\n            err.reason(end+1:end+length (erridx)) = ...\n              repmat ({\"'Inf' mismatch\"}, length (erridx), 1);\n          endif\n          errseen |= errvec;\n\n          ## Check normal values.\n          ## Replace exceptional values already checked above by zero.\n          if (is_real)\n            A_null_real = A;\n            B_null_real = B;\n          else\n            A_null_real = real (A);\n            B_null_real = real (B);\n          endif\n          if (issparse (errseen))\n            exclude = errseen ...\n                      | isnan (A_null_real) | isinf (A_null_real) ...\n                      | isnan (B_null_real) | isinf (B_null_real);\n          else\n            exclude = errseen ...\n                      | ! isfinite (A_null_real) & ! isfinite (B_null_real);\n          endif\n          A_null_real(exclude) = 0;\n          B_null_real(exclude) = 0;\n\n          if (is_real)\n            A_null = A_null_real;\n            B_null = B_null_real;\n          else\n            A_null_imag = imag (A);\n            B_null_imag = imag (B);\n            if (issparse (errseen))\n              exclude = errseen ...\n                        | isnan (A_null_imag) | isinf (A_null_imag) ...\n                        | isnan (B_null_imag) | isinf (B_null_imag);\n            else\n              exclude = errseen ...\n                        | ! isfinite (A_null_imag) & ! isfinite (B_null_imag);\n            endif\n\n            A_null_imag(exclude) = 0;\n            B_null_imag(exclude) = 0;\n            A_null = complex (A_null_real, A_null_imag);\n            B_null = complex (B_null_real, B_null_imag);\n          endif\n\n          clear A_null_real B_null_real;\n          clear A_null_imag B_null_imag;\n        endif\n\n        if (isscalar (tol))\n          mtol = tol * ones (size (A));\n        else\n          mtol = tol;\n        endif\n\n        k = (mtol == 0);\n        erridx = find ((A_null != B_null) & k);\n        if (! isempty (erridx))\n          err.index(end+1:end+length (erridx)) = ...\n            ind2tuple (size (A), erridx);\n          err.observed(end+1:end+length (erridx)) = ...\n            strtrim (cellstr (num2str (A(erridx) (:))));\n          err.expected(end+1:end+length (erridx)) = ...\n            strtrim (cellstr (num2str (B(erridx) (:))));\n          err.reason(end+1:end+length (erridx)) = ...\n            ostrsplit (deblank (\n                       sprintf (\"Abs err %.5g exceeds tol %.5g by %.1g\\n\",\n              [abs(A_null(erridx) - B_null(erridx))(:), mtol(erridx)(:), ...\n               abs(A_null(erridx) - B_null(erridx))(:)-mtol(erridx)(:)].')),\n                       \"\\n\");\n        endif\n\n        k = (mtol > 0);\n        erridx = find ((abs (A_null - B_null) > mtol) & k);\n        if (! isempty (erridx))\n          err.index(end+1:end+length (erridx)) = ...\n            ind2tuple (size (A), erridx);\n          err.observed(end+1:end+length (erridx)) = ...\n            strtrim (cellstr (num2str (A(erridx) (:))));\n          err.expected(end+1:end+length (erridx)) = ...\n            strtrim (cellstr (num2str (B(erridx) (:))));\n          err.reason(end+1:end+length (erridx)) = ...\n            ostrsplit (deblank (\n                       sprintf (\"Abs err %.5g exceeds tol %.5g by %.1g\\n\",\n              [abs(A_null(erridx) - B_null(erridx))(:), mtol(erridx)(:), ...\n               abs(A_null(erridx) - B_null(erridx))(:)-mtol(erridx)(:)].')),\n                       \"\\n\");\n        endif\n\n        k = (mtol < 0);\n        if (any (k(:)))\n          ## Test for absolute error where relative error can't be calculated.\n          erridx = find ((B_null == 0) & abs (A_null) > abs (mtol) & k);\n          if (! isempty (erridx))\n            err.index(end+1:end+length (erridx)) = ...\n              ind2tuple (size (A), erridx);\n            err.observed(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (A(erridx) (:))));\n            err.expected(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (B(erridx) (:))));\n            err.reason(end+1:end+length (erridx)) = ...\n              ostrsplit (deblank (\n                         sprintf (\"Abs err %.5g exceeds tol %.5g by %.1g\\n\",\n                    [abs(A_null(erridx) - B_null(erridx)), -mtol(erridx), ...\n                     abs(A_null(erridx) - B_null(erridx))+mtol(erridx)].')),\n                         \"\\n\");\n          endif\n          ## Test for relative error\n          Bdiv = Inf (size (B_null));\n          Bdiv(k & (B_null != 0)) = B_null(k & (B_null != 0));\n          relerr = abs ((A_null - B_null) ./ abs (Bdiv));\n          erridx = find ((relerr > abs (mtol)) & k);\n          if (! isempty (erridx))\n            err.index(end+1:end+length (erridx)) = ...\n              ind2tuple (size (A), erridx);\n            err.observed(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (A(erridx) (:))));\n            err.expected(end+1:end+length (erridx)) = ...\n              strtrim (cellstr (num2str (B(erridx) (:))));\n            err.reason(end+1:end+length (erridx)) = ...\n              ostrsplit (deblank (\n                         sprintf (\"Rel err %.5g exceeds tol %.5g by %.1g\\n\",\n                                  [relerr(erridx)(:), -mtol(erridx)(:), ...\n                                   relerr(erridx)(:)+mtol(erridx)(:)].')),\n                         \"\\n\");\n          endif\n        endif\n      endif\n\n    endif\n\n    ## Print any errors\n    if (! isempty (err.index))\n      if (! isempty (errmsg))\n        errmsg = [errmsg \"\\n\"];\n      endif\n      errmsg = [errmsg, pprint(argin, err)];\n    endif\n\n  unwind_protect_cleanup\n    call_depth -= 1;\n  end_unwind_protect\n\n  if (call_depth == -1)\n    ## Last time through.  If there were any errors on any pass, raise a flag.\n    if (! isempty (errmsg))\n\n      ## We don't want to start the debugger here if debug_on_error is\n      ## true so we set it to false and make the change local.  Then\n      ## debug_on_error will be reset to true after this function\n      ## returns and the debugger will start at the location of the call\n      ## to print_usage.\n      debug_on_error (false, \"local\");\n\n      error (errmsg);\n    endif\n  endif\n\nendfunction\n\n\n## empty input\n%!error assert_equal ([])\n%!error assert_equal (\"\")\n%!error assert_equal ({})\n%!error assert_equal (struct ([]))\n%!assert_equal (zeros (3,0), zeros (3,0))\n%!error <O\\(3x0\\)\\s+E\\(0x2\\)> assert_equal (zeros (3,0), zeros (0,2))\n%!error <Dimensions don't match> assert_equal (zeros (3,0), [])\n%!error <Dimensions don't match> assert_equal (zeros (2,0,2), zeros (2,0))\n\n## scalars\n%!error <Dimensions don't match> assert_equal (3, [3,3])\n%!error <Dimensions don't match> assert_equal (3, [3,3; 3,3])\n%!error <Dimensions don't match> assert_equal ([3,3; 3,3], 3)\n%!assert_equal (3, 3)\n%!error <Abs err 1 exceeds tol> assert_equal (3, 4)\n%!assert_equal (3+eps, 3, eps)\n%!assert_equal (3, 3+eps, eps)\n%!error <Abs err 4.4409e-0?16 exceeds tol> assert_equal (3+2*eps, 3, eps)\n%!error <Abs err 4.4409e-0?16 exceeds tol> assert_equal (3, 3+2*eps, eps)\n\n## vectors\n%!assert_equal ([1,2,3],[1,2,3])\n%!assert_equal ([1;2;3],[1;2;3])\n%!error <Abs err 1 exceeds tol 0> assert_equal ([2,2,3,3],[1,2,3,4])\n%!error <Abs err 1 exceeds tol 0.5> assert_equal ([2,2,3,3],[1,2,3,4],0.5)\n%!error <Rel err 1 exceeds tol 0.1> assert_equal ([2,2,3,5],[1,2,3,4],-0.1)\n%!error <Abs err 1 exceeds tol 0> assert_equal ([6;6;7;7],[5;6;7;8])\n%!error <Abs err 1 exceeds tol 0.5> assert_equal ([6;6;7;7],[5;6;7;8],0.5)\n%!error <Rel err .* exceeds tol 0.1> assert_equal ([6;6;7;7],[5;6;7;8],-0.1)\n%!error <Dimensions don't match> assert_equal ([1,2,3],[1;2;3])\n%!error <Dimensions don't match> assert_equal ([1,2],[1,2,3])\n%!error <Dimensions don't match> assert_equal ([1;2;3],[1;2])\n\n## matrices\n%!assert_equal ([1,2;3,4],[1,2;3,4])\n%!error <\\(1,2\\)\\s+4\\s+2> assert_equal ([1,4;3,4],[1,2;3,4])\n%!error <Dimensions don't match> assert_equal ([1,3;2,4;3,5],[1,2;3,4])\n%!test  # 2-D matrix\n%! A = [1 2 3]'*[1,2];\n%! assert_equal (A, A);\n%! fail (\"assert_equal (A.*(A!=2),A)\");\n%!test  # N-D matrix\n%! X = zeros (2,2,3);\n%! Y = X;\n%! Y(1,2,3) = 1.5;\n%! fail (\"assert_equal (X,Y)\", \"\\(1,2,3\\).*Abs err 1.5 exceeds tol 0\");\n\n## must give a small tolerance for floating point errors on relative\n%!assert_equal (100+100*eps, 100, -2*eps)\n%!assert_equal (100, 100+100*eps, -2*eps)\n%!error <Rel err .* exceeds tol> assert_equal (100+300*eps, 100, -2*eps)\n%!error <Rel err .* exceeds tol> assert_equal (100, 100+300*eps, -2*eps)\n\n## test relative vs. absolute tolerances\n%!test  assert_equal (0.1+eps, 0.1, 2*eps);\n%!error <Rel err 2.2204e-0?15 exceeds tol> assert_equal (0.1+eps, 0.1, -2*eps)\n%!test  assert_equal (100+100*eps, 100, -2*eps);\n%!error <Abs err 2.8422e-0?14 exceeds tol> assert_equal (100+100*eps, 100, 2*eps)\n\n## Corner case of relative tolerance with 0 divider\n%!error <Abs err 2 exceeds tol 0.1> assert_equal (2, 0, -0.1)\n\n## Extra checking of inputs when tolerance unspecified.\n%!error <Class single != double> assert_equal (single (1), 1)\n%!error <Class uint8 != uint16> assert_equal (uint8 (1), uint16 (1))\n%!error <sparse != non-sparse> assert_equal (sparse([1]), [1])\n%!error <non-sparse != sparse> assert_equal ([1], sparse([1]))\n%!error <complex != real> assert_equal (1+i, 1)\n%!error <real != complex> assert_equal (1, 1+i)\n\n## exceptional values\n%!assert_equal ([NaN, NA, Inf, -Inf, 1+eps, eps], [NaN, NA, Inf, -Inf, 1, 0], eps)\n\n%!error <'NaN' mismatch> assert_equal (NaN, 1)\n%!error <'NaN' mismatch> assert_equal ([NaN 1], [1 NaN])\n%!test\n%! try\n%!   assert_equal ([NaN 1], [1 NaN]);\n%! catch\n%!   errmsg = lasterr ();\n%!   if (sum (errmsg () == \"\\n\") != 4)\n%!     error (\"Too many errors reported for NaN assert_equal\");\n%!   elseif (strfind (errmsg, \"NA\"))\n%!     error (\"NA reported for NaN assert_equal\");\n%!   elseif (strfind (errmsg, \"Abs err NaN exceeds tol 0\"))\n%!     error (\"Abs err reported for NaN assert_equal\");\n%!   endif\n%! end_try_catch\n\n%!error <'NA' mismatch> assert_equal (NA, 1)\n%!error assert_equal ([NA 1]', [1 NA]')\n%!test\n%! try\n%!   assert_equal ([NA 1]', [1 NA]');\n%! catch\n%!   errmsg = lasterr ();\n%!   if (sum (errmsg () == \"\\n\") != 4)\n%!     error (\"Too many errors reported for NA assert_equal\");\n%!   elseif (strfind (errmsg, \"NaN\"))\n%!     error (\"NaN reported for NA assert_equal\");\n%!   elseif (strfind (errmsg, \"Abs err NA exceeds tol 0\"))\n%!     error (\"Abs err reported for NA assert_equal\");\n%!   endif\n%! end_try_catch\n%!error assert_equal ([(complex (NA, 1)) (complex (2, NA))], [(complex (NA, 2)) 2])\n\n%!error <'Inf' mismatch> assert_equal (-Inf, Inf)\n%!error <'Inf' mismatch> assert_equal ([-Inf Inf], [Inf -Inf])\n%!test\n%! try\n%!   assert_equal (complex (Inf, 0.2), complex (-Inf, 0.2 + 2*eps), eps);\n%! catch\n%!   errmsg = lasterr ();\n%!   if (sum (errmsg () == \"\\n\") != 3)\n%!     error (\"Too many errors reported for Inf assert_equal\");\n%!   elseif (strfind (errmsg, \"Abs err\"))\n%!     error (\"Abs err reported for Inf assert_equal\");\n%!   endif\n%! end_try_catch\n%!error <Abs err> assert_equal (complex (Inf, 0.2), complex (Inf, 0.2 + 2*eps), eps)\n\n## strings\n%!assert_equal (\"dog\", \"dog\")\n%!error <Strings don't match> assert_equal (\"dog\", \"cat\")\n%!error <Expected string, but observed number> assert_equal (3, \"dog\")\n%!error <Class char != double> assert_equal (\"dog\", [3 3 3])\n%!error <Expected string, but observed cell> assert_equal ({\"dog\"}, \"dog\")\n%!error <Expected string, but observed struct> assert_equal (struct (\"dog\", 3), \"dog\")\n\n## cell arrays\n%!error <Expected cell, but observed double> assert_equal (1, {1})\n%!error <Dimensions don't match> assert_equal (cell (1,2,3), cell (3,2,1))\n%!test\n%! x = {{{1}}, 2};  # cell with multiple levels\n%! y = x;\n%! assert_equal (x,y);\n%! y{1}{1}{1} = 3;\n%! fail (\"assert_equal (x,y)\", \"Abs err 2 exceeds tol 0\");\n%!test\n%! try\n%!   assert_equal ({2}, {single(2)});\n%! catch\n%!   errmsg = lasterr ();\n%!   if (sum (errmsg () == \"\\n\") != 3)\n%!     error (\"Incorrect number of errors reported\");\n%!   endif\n%!   assert_equal (! isempty (regexp (errmsg, 'Class double != single')), true);\n%! end_try_catch\n\n## function handles\n%!assert_equal (@sin, @sin)\n%!error <Function handles don't match> assert_equal (@sin, @cos)\n%!error <Expected function handle, but observed double> assert_equal (pi, @cos)\n%!error <Class function_handle != double> assert_equal (@sin, pi)\n\n%!test\n%! x = {[3], [1,2,3]; 100+100*eps, \"dog\"};\n%! y = x;\n%! assert_equal (x, y);\n%! y = x; y(1,1) = [2];\n%! fail (\"assert_equal (x, y)\");\n%! y = x; y(1,2) = [0, 2, 3];\n%! fail (\"assert_equal (x, y)\");\n%! y = x; y(2,1) = 101;\n%! fail (\"assert_equal (x, y)\");\n%! y = x; y(2,2) = \"cat\";\n%! fail (\"assert_equal (x, y)\");\n%! y = x; y(1,1) = [2]; y(1,2) = [0, 2, 3]; y(2,1) = 101; y(2,2) = \"cat\";\n%! fail (\"assert_equal (x, y)\");\n\n## structures\n%!error <Expected struct, but observed double> assert_equal (1, struct (\"a\", 1))\n%!error <Structure sizes don't match>\n%! x(1,2,3).a = 1;\n%! y(1,2).a = 1;\n%! assert_equal (x,y);\n%!error <Structure sizes don't match>\n%! x(1,2,3).a = 1;\n%! y(3,2,2).a = 1;\n%! assert_equal (x,y);\n%!error <Structure sizes don't match>\n%! x.a = 1;\n%! x.b = 1;\n%! y.a = 1;\n%! assert_equal (x,y);\n%!error <Structure fieldname mismatch>\n%! x.b = 1;\n%! y.a = 1;\n%! assert_equal (x,y);\n%!error <Abs err 1 exceeds tol 0 by 1>\n%! x.a = 1;\n%! y.a = 2;\n%! assert_equal (x,y);\n\n%!test\n%! x.a = 1; x.b=[2, 2];\n%! y.a = 1; y.b=[2, 2];\n%! assert_equal (x, y);\n%! y.b=3;\n%! fail (\"assert_equal (x, y)\");\n%! fail (\"assert_equal (3, x)\");\n%! fail (\"assert_equal (x, 3)\");\n%! ## Empty structures\n%! x = resize (x, 0, 1);\n%! y = resize (y, 0, 1);\n%! assert_equal (x, y);\n\n## vector of tolerances\n%!test\n%! x = [-40:0];\n%! y1 = (10.^x).*(10.^x);\n%! y2 = 10.^(2*x);\n%! ## Increase tolerance from eps (y1) to 4*eps (y1) because of an upstream bug\n%! ## in mingw-w64: https://sourceforge.net/p/mingw-w64/bugs/466/\n%! assert_equal (y1, y2, 4*eps (y1));\n%! fail (\"assert_equal (y1, y2 + eps*1e-70, eps (y1))\");\n\n## Multiple tolerances\n%!test\n%! x = [1 2; 3 4];\n%! y = [0 -1; 1 2];\n%! tol = [-0.1 0; -0.2 0.3];\n%! try\n%!   assert_equal (x, y, tol);\n%! catch\n%!   errmsg = lasterr ();\n%!   if (sum (errmsg () == \"\\n\") != 6)\n%!     error (\"Incorrect number of errors reported\");\n%!   endif\n%!   assert_equal (! isempty (regexp (errmsg, '\\(1,2\\).*Abs err 3 exceeds tol 0\\>')), true);\n%!   assert_equal (! isempty (regexp (errmsg, '\\(2,2\\).*Abs err 2 exceeds tol 0.3')), true);\n%!   assert_equal (! isempty (regexp (errmsg, '\\(1,1\\).*Abs err 1 exceeds tol 0.1')), true);\n%!   assert_equal (! isempty (regexp (errmsg, '\\(2,1\\).*Rel err 2 exceeds tol 0.2')), true);\n%! end_try_catch\n\n%!test <*57615>\n%! try\n%!   assert_equal (complex (pi*1e-17,2*pi), 0, 1e-1);\n%! catch\n%!   errmsg = lasterr ();\n%!   assert_equal (isempty (strfind (errmsg, \"sprintf: invalid field width\")), true);\n%! end_try_catch\n\n%!test <*63988>\n%! A = [\"ab\"; \"cd\"];\n%! B = [\"ad\"; \"cb\"];\n%! try\n%!   assert_equal (A, B);\n%! catch\n%!   errmsg = lasterr ();\n%!   if (regexp (errmsg, 'horizontal dimensions mismatch'))\n%!     error (\"assert_equal failed for char arrays with multiple rows\");\n%!   endif\n%! end_try_catch\n\n## classdef\n%!error <Expected classdef object, but observed double> assert_equal (5, containers.Map ())\n%!error <Expected classdef object does not have an 'eq' method> ...\n%!       assert_equal (containers.Map (), containers.Map ())\n%!test\n%! try\n%!   assert_equal (containers.Map ([1, 2], {1, 2}), containers.Map ());\n%! catch\n%!   errmsg = lasterr ();\n%!   assert_equal (! isempty (regexp (errmsg, 'O\\(2x1\\)')), true);\n%!   assert_equal (! isempty (regexp (errmsg, 'E\\(0x1\\)')), true);\n%!   assert_equal (! isempty (regexp (errmsg, \"Dimensions don't match\")), true);\n%! end_try_catch\n\n## test input validation\n%!error <Invalid call> assert_equal ()\n%!error <assert_equal: function called with too many inputs> assert_equal (1,2,3,4)\n\n\n## Convert all error indices into tuple format\nfunction cout = ind2tuple (matsize, erridx)\n\n  tmp = cell (1, numel (matsize));\n  [tmp{:}] = ind2sub (matsize, erridx(:));\n  subs = [tmp{:}];\n  if (numel (matsize) == 2)\n    subs = subs(:, matsize != 1);  # For vectors, use 1-D index\n  endif\n  fmt = repmat ('%d,', 1, max (columns (subs), 1));\n  fmt(end) = [];   # delete final extra comma\n  cout = ostrsplit (sprintf (['(' fmt ')', '$'], subs'), '$');\n  cout(end) = [];  # delete extra cell from final '$'\n  cout = cout.';   # return column vector\n\nendfunction\n\n\n## Pretty print the various errors in a condensed tabular format.\nfunction str = pprint (argin, err)\n\n  str = [\"ASSERT errors for:  assert_equal \" argin \"\\n\"];\n  str = [str, \"\\n  Location  |  Observed  |  Expected  |  Reason\\n\"];\n\n  pos = numel (str);\n  str(pos + 100 * numel (err.index)) = ' ';\n  for i = 1:numel (err.index)\n    leni = numel (err.index{i});\n    leno = numel (err.observed{i});\n    lene = numel (err.expected{i});\n    tmp = sprintf (\"%*s%*s %*s%*s %*s%*s   %s\\n\",\n                   6+fix(leni/2), err.index{i}   , max (6-fix(leni/2), 0), \"\",\n                   6+fix(leno/2), err.observed{i}, max (6-fix(leno/2), 0), \"\",\n                   6+fix(lene/2), err.expected{i}, max (6-fix(lene/2), 0), \"\",\n                   err.reason{i});\n    if (pos + numel (tmp) > numel (str))\n      str(end + 1e6) = ' ';\n    endif\n    str((pos + 1):(pos + numel (tmp))) = tmp;\n    pos += numel (tmp);\n  endfor\n  str = str(1:pos);\n\nendfunction\n"
  },
  {
    "path": "scripts/testfun/demo.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} demo @var{name}\n## @deftypefnx {} {} demo @var{name} @var{n}\n## @deftypefnx {} {} demo (\"@var{name}\")\n## @deftypefnx {} {} demo (\"@var{name}\", @var{n})\n##\n## Run example code block @var{n} associated with the function @var{name}.\n##\n## If @var{n} is not specified, all examples are run.\n##\n## The preferred location for example code blocks is embedded within the script\n## m-file immediately following the code that it exercises.  Alternatively,\n## the examples may be stored in a file with the same name but no extension\n## located on Octave's load path.  To separate examples from regular script\n## code all lines are prefixed by @code{%!}.  Each example must also be\n## introduced by the keyword @qcode{\"demo\"} flush left to the prefix with no\n## intervening spaces.  The remainder of the example can contain arbitrary\n## Octave code.  For example:\n##\n## @example\n## @group\n## %!demo\n## %! t = 0:0.01:2*pi;\n## %! x = sin (t);\n## %! plot (t, x);\n## %! title (\"one cycle of a sine wave\");\n## %! #-------------------------------------------------\n## %! # the figure window shows one cycle of a sine wave\n## @end group\n## @end example\n##\n## Note that the code is displayed before it is executed so that a simple\n## comment at the end suffices for labeling what is being shown.  For plots,\n## labeling can also be done with @code{title} or @code{text}.  It is generally\n## @strong{not} necessary to use @code{disp} or @code{printf} within the demo.\n##\n## Demos are run in a stand-alone function environment with no access to\n## external variables.  This means that every demo must have separate\n## initialization code.  Alternatively, all demos can be combined into a single\n## large demo with the code\n##\n## @example\n## %! input (\"Press <enter> to continue: \", \"s\");\n## @end example\n##\n## @noindent\n## between the sections, but this usage is discouraged.  Other techniques to\n## avoid multiple initialization blocks include using multiple plots with a new\n## @code{figure} command between each plot, or using @code{subplot} to put\n## multiple plots in the same window.\n##\n## Finally, because @code{demo} evaluates within a function context it is not\n## possible to define new functions within the code.  Anonymous functions make\n## a good substitute in most instances.  If function blocks @strong{must} be\n## used then the code @code{eval (example (\"function\", n))} will allow Octave\n## to see them.  This has its own problems, however, as @code{eval} only\n## evaluates one line or statement at a time.  In this case the function\n## declaration must be wrapped with @qcode{\"if 1 <demo stuff> endif\"} where\n## @qcode{\"if\"} is on the same line as @qcode{\"demo\"}.  For example:\n##\n## @example\n## @group\n## %!demo if 1\n## %!  function y = f(x)\n## %!    y = x;\n## %!  endfunction\n## %!  f(3)\n## %! endif\n## @end group\n## @end example\n##\n## @seealso{rundemos, example, test}\n## @end deftypefn\n\n## FIXME: modify subplot so that gnuplot_has_multiplot == 0 causes it to\n## use the current figure window but pause if not plotting in the\n## first subplot.\n\nfunction demo (name, n = 0)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ischar (n))\n    n = str2double (n);\n  endif\n\n  if (! (isreal (n) && isscalar (n) && n == fix (n)))\n    error (\"demo: N must be a scalar integer\");\n  endif\n\n  ## Paging causes Qt graphics to hang on some demos.\n  page_screen_output (false, \"local\");\n\n  [code, idx] = test (name, \"grabdemo\");\n\n  if (idx == -1)\n    warning (\"demo: no function %s found\", name);\n    return;\n  elseif (isempty (idx))\n    warning (\"demo: no demo available for %s\", name);\n    return;\n  elseif (n >= length (idx))\n    warning (\"demo: only %d demos available for %s\", length (idx) - 1, name);\n    return;\n  endif\n\n  if (n > 0)\n    doidx = n;\n  else\n    doidx = 1:(length (idx) - 1);\n  endif\n  clear_figures ();\n  for i = 1:length (doidx)\n    ## Pause between demos\n    if (i > 1)\n      input (\"Press <enter> to continue: \", \"s\");\n      clear_figures ();\n    endif\n\n    ## Process each demo without failing\n    try\n      block = code(idx(doidx(i)):idx(doidx(i)+1)-1);\n      ## Use an environment without variables\n      eval ([\"function __demo__ ()\\n\" block \"\\nendfunction\"]);\n      ## Display the code that will be executed before executing it\n      printf (\"%s example %d:%s\\n\\n\", name, doidx(i), block);\n      __demo__;\n    catch\n      ## Let the programmer know which demo failed.\n      printf (\"%s example %d: failed\\n%s\\n\", name, doidx(i), lasterr ());\n    end_try_catch\n    clear __demo__;\n  endfor\n\nendfunction\n\nfunction clear_figures ()\n\n  ## Prevent proliferation of figure windows.  If any figure windows exist,\n  ## close all but one and clear the one remaining.\n  figs = __go_figure_handles__ ();\n  if (! isempty (figs))\n    if (numel (figs) > 1)\n      figs = sort (figs);\n      figs(1) = [];\n      close (figs);\n    endif\n    clf (\"reset\");\n  endif\n\nendfunction\n\n\n%!demo\n%! t = 0:0.01:2*pi;\n%! x = sin (t);\n%! plot (t, x);\n%! title (\"one cycle of a sine wave\");\n%! #-------------------------------------------------\n%! # the figure window shows one cycle of a sine wave\n\n%!error <Invalid call> demo ()\n%!error <N must be a scalar integer> demo (\"demo\", {1})\n%!error <N must be a scalar integer> demo (\"demo\", ones (2,2))\n%!error <N must be a scalar integer> demo (\"demo\", 1.5)\n%!warning <no function .* found> demo (\"_%NOT_A_FUNCTION%_\");\n%!warning <only 1 demos available for demo> demo (\"demo\", 10);\n"
  },
  {
    "path": "scripts/testfun/example.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} example @var{name}\n## @deftypefnx {} {} example @var{name} @var{n}\n## @deftypefnx {} {} example (\"@var{name}\")\n## @deftypefnx {} {} example (\"@var{name}\", @var{n})\n## @deftypefnx {} {[@var{codestr}, @var{codeidx}] =} example (@dots{})\n##\n## Display the code for example @var{n} associated with the function\n## @var{name}, but do not run it.\n##\n## If @var{n} is not specified, all examples are displayed.\n##\n## When called with output arguments, the examples are returned in the form of\n## a string @var{codestr}, with @var{codeidx} indicating the ending position of\n## the various examples.\n##\n## For a complete explanation @pxref{XREFdemo,,demo}.\n## @seealso{demo, test}\n## @end deftypefn\n\nfunction [codestr, codeidx] = example (name, n = 0)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ischar (n))\n    n = str2double (n);\n  endif\n\n  if (! (isreal (n) && isscalar (n) && n == fix (n)))\n    error (\"example: N must be a scalar integer\");\n  endif\n\n  [code, idx] = test (name, \"grabdemo\");\n\n  if (idx == -1)\n    warning (\"example: no function %s found\", name);\n    return;\n  elseif (isempty (idx))\n    warning (\"example: no example available for %s\", name);\n    return;\n  elseif (n >= length (idx))\n    warning (\"example: only %d examples available for %s\",\n             length (idx) - 1, name);\n    return;\n  endif\n\n  if (nargout > 0)\n    if (n > 0)\n      if (n <= length (idx))\n        codestr = code(idx(n):idx(n+1)-1);\n        codeidx = [1, length(codestr)+1];\n      else\n        codestr = \"\";\n        codeidx = [];\n      endif\n    else\n      codestr = code;\n      codeidx = idx;\n    endif\n  else\n    if (n > 0)\n      doidx = n;\n    else\n      doidx = 1:length (idx) - 1;\n    endif\n\n    for i = 1:length (doidx)\n      block = code(idx(doidx(i)):idx(doidx(i)+1)-1);\n      printf (\"%s example %d:%s\\n\\n\", name, doidx(i), block);\n    endfor\n  endif\n\nendfunction\n\n\n## WARNING: don't modify the demos without modifying the tests!\n%!demo\n%! example (\"example\");\n\n%!demo\n%! clf;\n%! t = 0:0.01:2*pi;\n%! x = sin (t);\n%! plot (t,x)\n\n%!assert (example (\"example\", 1), \"\\n example (\\\"example\\\");\")\n\n%!test\n%! [code, idx] = example (\"example\");\n%! assert (code, ...\n%!         \"\\n example (\\\"example\\\");\\n clf;\\n t = 0:0.01:2*pi;\\n x = sin (t);\\n plot (t,x)\");\n%! assert (idx, [1, 23, 73]);\n\n## Test input validation\n%!error <Invalid call> example ()\n%!error <N must be a scalar integer> example (\"example\", {1})\n%!error <N must be a scalar integer> example (\"example\", ones (2,2))\n%!error <N must be a scalar integer> example (\"example\", 1.5)\n%!warning <no function .* found> example (\"_%NOT_A_FUNCTION%_\");\n%!warning <only 2 examples available for example> example (\"example\", 10);\n"
  },
  {
    "path": "scripts/testfun/fail.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n##\n## Original version by Paul Kienzle distributed as free software in the\n## public domain.\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{status} =} fail (@var{code})\n## @deftypefnx {} {@var{status} =} fail (@var{code}, @var{pattern})\n## @deftypefnx {} {@var{status} =} fail (@var{code}, \"warning\")\n## @deftypefnx {} {@var{status} =} fail (@var{code}, \"warning\", @var{pattern})\n##\n## Return true if @var{code} fails with an error message matching\n## @var{pattern}, otherwise produce an error.\n##\n## @var{code} must be in the form of a string that is passed to the Octave\n## interpreter via the @code{evalin} function, i.e., a (quoted) string constant\n## or a string variable.\n##\n## Note that if @var{code} runs successfully, rather than failing, the error\n## printed is:\n##\n## @example\n##           expected error <.> but got none\n## @end example\n##\n## If called with two arguments, the return value will be true only if\n## @var{code} fails with an error message containing @var{pattern}\n## (case sensitive).  If the code fails with a different error than the one\n## specified in @var{pattern} then the message produced is:\n##\n## @example\n## @group\n##           expected <@var{pattern}>\n##           but got <text of actual error>\n## @end group\n## @end example\n##\n## The angle brackets are not part of the output.\n##\n## When called with the @qcode{\"warning\"} option @code{fail} will produce an\n## error if executing the code produces no warning.\n## @seealso{assert, error}\n## @end deftypefn\n\nfunction status = fail (code, pattern, warning_pattern)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Parse input arguments\n  test_warning = false;\n  if (nargin == 1)\n    pattern = \"\";\n  elseif (nargin == 2 && ! strcmp (pattern, \"warning\"))\n    ## Normal error test\n  elseif (nargin >= 2 && strcmp (pattern, \"warning\"))\n    test_warning = true;\n    if (nargin == 2)\n      pattern = \"\";\n    else\n      pattern = warning_pattern;\n    endif\n  else\n    print_usage ();\n  endif\n\n  ## Match any nonempty message\n  if (isempty (pattern))\n    pattern = \".\";\n  endif\n\n  ## Allow assert (fail ())\n  if (nargout)\n    status = true;\n  endif\n\n  if (test_warning)\n    ## Perform the warning test.\n    ## Clear old warnings.\n    lastwarn (\"\");\n    ## Make sure warnings are turned on.\n    wstate = warning (\"query\", \"quiet\");\n    warning (\"on\", \"quiet\");\n    try\n      evalin (\"caller\", [code \";\"]);\n      ## Retrieve new warnings.\n      warn = lastwarn ();\n      warning (wstate.state, \"quiet\");\n      if (isempty (warn))\n        msg = sprintf (\"expected warning <%s> but got none\", pattern);\n      else\n        if (! isempty (regexp (warn, pattern, \"once\")))\n          return;\n        endif\n        msg = sprintf (\"expected warning <%s>\\nbut got <%s>\", pattern, warn);\n      endif\n    catch\n      warning (wstate.state, \"quiet\");\n      err = lasterr ();\n      msg = sprintf (\"expected warning <%s>\\nbut got error <%s>\", pattern, err);\n    end_try_catch\n\n  else\n    ## Perform the error test.\n    try\n      evalin (\"caller\", [code \";\"]);\n      msg = sprintf (\"expected error <%s> but got none\", pattern);\n    catch\n      err = lasterr ();\n      if (! isempty (regexp (err, pattern, \"once\")))\n        return;\n      endif\n      msg = sprintf (\"expected error <%s>\\nbut got <%s>\", pattern, err);\n    end_try_catch\n  endif\n\n  ## If we get here, then code didn't fail or error didn't match.\n  error (msg);\n\nendfunction\n\n\n%!fail (\"[1,2]*[2,3]\", \"nonconformant\")\n%!fail (\"fail ('[1,2]*[2;3]', 'nonconformant')\", \"expected error <nonconformant> but got none\")\n%!fail (\"fail ('[1,2]*[2,3]', 'usage:')\", \"expected error <usage:>\\nbut got.*nonconformant\")\n%!fail (\"warning ('test warning')\", \"warning\", \"test warning\")\n%!fail (\"warning ('next test')\", 'warning', 'next test')\n\n## Test that fail() itself will generate an error\n%!error <expected error> fail (\"1\")\n%!error <'__a__' undefined> fail (\"__a__*[2;3]\", \"nonconformant\")\n%!error <expected error .usage:>  fail (\"__a__*[2,3]\", \"usage:\")\n%!error <warning failure> fail (\"warning ('warning failure')\", \"warning\", \"success\")\n\n## Test input validation\n%!error <Invalid call> fail ()\n%!error fail (1, \"nowarning\", \"foo\")\n"
  },
  {
    "path": "scripts/testfun/module.mk",
    "content": "FCN_FILE_DIRS += \\\n  %reldir% \\\n  %reldir%/private\n\n%canon_reldir%_PRIVATE_FCN_FILES = \\\n  %reldir%/private/compare_plot_demos.m \\\n  %reldir%/private/dump_demos.m \\\n  %reldir%/private/html_compare_plot_demos.m \\\n  %reldir%/private/html-plot-demos-template.html\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/__debug_octave__.m \\\n  %reldir%/__have_feature__.m \\\n  %reldir%/__printf_assert__.m \\\n  %reldir%/__prog_output_assert__.m \\\n  %reldir%/__run_test_suite__.m \\\n  %reldir%/assert.m \\\n  %reldir%/assert_equal.m \\\n  %reldir%/demo.m \\\n  %reldir%/example.m \\\n  %reldir%/fail.m \\\n  %reldir%/rundemos.m \\\n  %reldir%/oruntests.m \\\n  %reldir%/speed.m \\\n  %reldir%/test.m\n\n%canon_reldir%dir = $(fcnfiledir)/testfun\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\n%canon_reldir%_privatedir = $(fcnfiledir)/testfun/private\n\n%canon_reldir%_private_DATA = $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nFCN_FILES += \\\n  $(%canon_reldir%_FCN_FILES) \\\n  $(%canon_reldir%_PRIVATE_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/testfun/oruntests.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} oruntests ()\n## @deftypefnx {} {} oruntests (@var{directory})\n## Execute built-in tests for all m-files in the specified @var{directory}.\n##\n## Test blocks in any C++ source files (@file{*.cc}) will also be executed\n## for use with dynamically linked oct-file functions.\n##\n## If no directory is specified, operate on all directories in Octave's search\n## path for functions.\n## @seealso{rundemos, test, path}\n## @end deftypefn\n\nfunction oruntests (directory)\n\n  if (nargin == 0)\n    dirs = ostrsplit (path (), pathsep ());\n    do_class_dirs = true;\n  else\n    dirs = {canonicalize_file_name(directory)};\n    if (isempty (dirs{1}) || ! isfolder (dirs{1}))\n      ## Search for directory name in path\n      if (directory(end) == '/' || directory(end) == '\\')\n        directory(end) = [];\n      endif\n      fullname = dir_in_loadpath (directory);\n      if (isempty (fullname))\n        error (\"oruntests: DIRECTORY argument must be a valid pathname\");\n      endif\n      dirs = {fullname};\n    endif\n    do_class_dirs = false;\n  endif\n\n  for i = 1:numel (dirs)\n    d = dirs{i};\n    run_all_tests (d, do_class_dirs);\n  endfor\n\nendfunction\n\nfunction run_all_tests (directory, do_class_dirs)\n\n  flist = readdir (directory);\n  dirs = {};\n  no_tests = {};\n  printf (\"Processing files in %s:\\n\\n\", directory);\n  fflush (stdout);\n  unwind_protect\n    old_dir = cd (directory);\n    for i = 1:numel (flist)\n      f = flist{i};\n      if ((length (f) > 2 && strcmpi (f((end-1):end), \".m\"))\n          || (length (f) > 3 && strcmpi (f((end-2):end), \".cc\")))\n        ff = fullfile (directory, f);\n        if (! isfile (ff))\n          continue;\n        endif\n        if (has_tests (ff))\n          print_test_file_name (f);\n          [p, n, xf, xb, sk, rtsk, rgrs] = test (ff, \"quiet\");\n          print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs);\n          fflush (stdout);\n        elseif (has_functions (ff))\n          no_tests(end+1) = f;\n        endif\n      elseif (f(1) == \"@\")\n        f = fullfile (directory, f);\n        if (isfolder (f))\n          dirs(end+1) = f;\n        endif\n      endif\n    endfor\n  unwind_protect_cleanup\n    cd (old_dir);\n  end_unwind_protect\n  if (! isempty (no_tests))\n    printf (\"\\nThe following files in %s have no tests:\\n\\n\", directory);\n    printf (\"%s\", list_in_columns (no_tests));\n  endif\n\n  ## Recurse into class directories since they are implied in the path\n  if (do_class_dirs)\n    for i = 1:numel (dirs)\n      d = dirs{i};\n      run_all_tests (d, false);\n    endfor\n  endif\n\nendfunction\n\nfunction retval = has_functions (f)\n\n  n = length (f);\n  if (n > 3 && strcmpi (f((end-2):end), \".cc\"))\n    fid = fopen (f);\n    if (fid < 0)\n      error (\"oruntests: fopen failed: %s\", f);\n    endif\n    str = fread (fid, \"*char\")';\n    fclose (fid);\n    enc = dir_encoding (fileparts (f));\n    if (! strcmp (enc, \"utf-8\"))\n      ## convert from input encoding to UTF-8\n      str = native2unicode (uint8 (str), enc);\n    endif\n    retval = ! isempty (regexp (str,'^(?:DEFUN|DEFUN_DLD|DEFUNX)\\>',\n                                    'lineanchors', 'once'));\n  elseif (n > 2 && strcmpi (f((end-1):end), \".m\"))\n    retval = true;\n  else\n    retval = false;\n  endif\n\nendfunction\n\nfunction retval = has_tests (f)\n\n  fid = fopen (f);\n  if (fid < 0)\n    error (\"oruntests: fopen failed: %s\", f);\n  endif\n\n  str = fread (fid, \"*char\").';\n  fclose (fid);\n  enc = dir_encoding (fileparts (f));\n  if (! strcmp (enc, \"utf-8\"))\n    ## convert from input encoding to UTF-8\n    str = native2unicode (uint8 (str), enc);\n  endif\n  retval = ! isempty (regexp (str,\n                              '^%!(assert|error|fail|test|xtest|warning)',\n                              'lineanchors', 'once'));\n\nendfunction\n\nfunction print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs)\n\n  if ((n + sk + rtsk + rgrs) > 0)\n    printf (\" PASS   %4d/%-4d\", p, n);\n    nfail = n - p - xf - xb - rgrs;\n    if (nfail > 0)\n      printf (\"\\n%71s %3d\", \"FAIL \", nfail);\n    endif\n    if (rgrs > 0)\n      printf (\"\\n%71s %3d\", \"REGRESSION\", rgrs);\n    endif\n    if (xb > 0)\n      printf (\"\\n%71s %3d\", \"(reported bug) XFAIL\", xb);\n    endif\n    if (xf > 0)\n      printf (\"\\n%71s %3d\", \"(expected failure) XFAIL\", xf);\n    endif\n    if (sk > 0)\n      printf (\"\\n%71s %3d\", \"(missing feature) SKIP\", sk);\n    endif\n    if (rtsk > 0)\n      printf (\"\\n%71s %3d\", \"(run-time condition) SKIP\", rtsk);\n    endif\n  endif\n  puts (\"\\n\");\n\nendfunction\n\nfunction print_test_file_name (nm)\n  filler = repmat (\".\", 1, 60-length (nm));\n  printf (\"  %s %s\", nm, filler);\nendfunction\n\n\n%!error oruntests (\"foo\", 1)\n%!error <DIRECTORY argument> oruntests (\"#_TOTALLY_/_INVALID_/_PATHNAME_#\")\n"
  },
  {
    "path": "scripts/testfun/private/compare_plot_demos.m",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} compare_plot_demos ()\n## @deftypefnx {} {} compare_plot_demos (\"toolkits\", @{@var{toolkit1}, @var{toolkit2}, @dots{}@})\n##\n## Use @code{dump_demos} and @code{html_compare_plot_demos} to produce an\n## html comparison of the plot demos for each of Octave's graphics toolkits.\n##\n## An m-file named @file{dump_plots.m} will be created in the current working\n## directory.  This function will be used to render and save the plot demo\n## images.\n##\n## If they do not already exist, directories for each available graphics\n## toolkit are created.  Each toolkit's directory will be populated with images\n## of each plot demo in the png format.\n##\n## Finally, an html document named @file{compare_plot_demos.html} is produced.\n## This page places each toolkit's images side by side for a convenient\n## comparison of the results.\n##\n## If the property @qcode{\"toolkits\"} is given then compare only the listed\n## toolkits in the cell string.  The list may also include the toolkit\n## @qcode{\"matlab\"}.\n##\n## @end deftypefn\n\nfunction compare_plot_demos (varargin)\n\n  arg.toolkits = available_graphics_toolkits ();\n  arg.directories = fullfile (\"plot\", {\"appearance\", \"draw\", \"util\"});\n  arg.directories(end + 1) = \"image\";\n  arg.fmt = \"png\";\n  arg.fcn_file = \"dump_plot_demos.m\";\n  arg.replace_images = false;\n\n  for n = 1:2:numel (varargin)\n    if (! ischar (varargin{n}))\n      print_usage ();\n    else\n      arg.(varargin{n}) = varargin{n+1};\n    endif\n  endfor\n\n  if (ischar (arg.toolkits))\n    arg.toolkits = {arg.toolkits};\n  elseif (! iscellstr (arg.toolkits))\n    error ('compare_plot_demos: Invalid value for \"toolkits\"');\n  endif\n\n  if (ischar (arg.directories))\n    arg.directories = {arg.directories};\n  elseif (! iscellstr (arg.directories))\n    error ('compare_plot_demos: Invalid value for \"directory\"');\n  endif\n\n  if (! ischar (arg.fmt))\n    error ('compare_plot_demos: Invalid value for \"fmt\"');\n  endif\n\n  ## Generate arg.fcn_file for rendering/saving the plot demo images\n  dump_demos (arg.directories, arg.fcn_file, arg.fmt);\n\n  [~, fcn_name] = fileparts (arg.fcn_file);\n\n  ## Generate the plot demo images for each toolkit\n  cwd = pwd ();\n  unwind_protect\n    addpath (pwd);\n    for n = 1:numel (arg.toolkits)\n      if (! isfolder (fullfile (cwd, arg.toolkits{n})))\n        mkdir (arg.toolkits{n});\n      endif\n      cd (arg.toolkits{n});\n      if (arg.replace_images && ! isempty (dir ([\"*.\" arg.fmt])))\n        delete ([\"*.\" arg.fmt]);\n      endif\n      if (! strcmp (arg.toolkits{n}, \"matlab\"))\n        close all;\n        graphics_toolkit (arg.toolkits{n});\n        try\n          eval (fcn_name);\n        catch\n          printf (\"Error running plot demos for \"\"%s\"\" toolkit\\n\",\n                  arg.toolkits{n});\n          disp (lasterror);\n        end_try_catch\n      endif\n      cd (cwd);\n    endfor\n  unwind_protect_cleanup\n    rmpath (cwd);\n  end_unwind_protect\n\n  if (! strcmp (arg.toolkits, \"matlab\"))\n    ## Generate the html comparison of the images\n    html_compare_plot_demos (arg.toolkits);\n  else\n    ## We need to run matlab manually before the html page can be created\n    printf ('\\nNow run %s in Matlab.\\nAfter this run html_compare_plot_demos,\\n', arg.fcn_file);\n    printf ('for example html_compare_plot_demos ({\"fltk\", \"gnuplot\", \"matlab\"}), to create the html page.\\n');\n  endif\n\nendfunction\n"
  },
  {
    "path": "scripts/testfun/private/dump_demos.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} dump_demos ()\n## @deftypefnx {} {} dump_demos (@var{dirs})\n## @deftypefnx {} {} dump_demos (@var{dirs}, @var{mfile})\n## @deftypefnx {} {} dump_demos (@var{dirs}, @var{mfile}, @var{fmt})\n## Produce a script, with the name specified by @var{mfile}, containing\n## the demos in the directories, @var{dirs}.  The demos are assumed to produce\n## graphical output, whose renderings are saved with the specified format,\n## @var{fmt}.\n##\n## The defaults for each input are;\n##\n## @table @var\n##   @item @var{dirs}\n##   @code{@{\"plot/appearance\", \"plot/draw\", \"plot/util\", \"image\"@}}\n##\n##   @item @var{mfile}\n##   @qcode{\"dump.m\"}\n##\n##   @item @var{fmt}\n##   @qcode{\"png\"}\n## @end table\n##\n## For example, to produce PNG output for all demos of the functions\n## in the plot directory;\n##\n## @example\n## dump_demos plot dump.m png\n## @end example\n## @seealso{fntests, test, demo}\n## @end deftypefn\n\nfunction dump_demos (dirs={\"plot/appearance\", \"plot/draw\", \"plot/util\", \"image\"}, mfile=\"dump_plot_demos.m\", fmt=\"png\")\n\n  if (ischar (dirs))\n    dirs = {dirs};\n  elseif (! iscellstr (dirs))\n    error (\"dump_demos: DIRS must be a cell array of strings with directory names\");\n  endif\n\n  if (! isunix ())\n    dirs = strrep (dirs, \"/\", filesep ());\n  endif\n\n  [~, funcname, ext] = fileparts (mfile);\n  if (isempty (ext))\n    mfile = [mfile \".m\"];\n  endif\n\n  ## Create script beginning (close figures, etc.)\n  fid = fopen (mfile, \"w\");\n  fprintf (fid, \"%% DO NOT EDIT!  Generated automatically by dump_demos.m\\n\");\n  fprintf (fid, \"function %s ()\\n\", funcname);\n  fprintf (fid, \"set (0, 'DefaultAxesColorOrder', ...\\n\");\n  fprintf (fid, \"  [ 0.00000   0.44700   0.74100 ;\\n\");\n  fprintf (fid, \"    0.85000   0.32500   0.09800 ;\\n\");\n  fprintf (fid, \"    0.92900   0.69400   0.12500 ;\\n\");\n  fprintf (fid, \"    0.49400   0.18400   0.55600 ;\\n\");\n  fprintf (fid, \"    0.46600   0.67400   0.18800 ;\\n\");\n  fprintf (fid, \"    0.30100   0.74500   0.93300 ;\\n\");\n  fprintf (fid, \"    0.63500   0.07800   0.18400 ]);\\n\");\n  fprintf (fid, \"set (0, 'DefaultFigureColorMap', ...\\n\");\n  fprintf (fid, \"  [ 0.2670040   0.0048743   0.3294152 ;\\n\");\n  fprintf (fid, \"    0.2726517   0.0258457   0.3533673 ;\\n\");\n  fprintf (fid, \"    0.2771063   0.0509139   0.3762361 ;\\n\");\n  fprintf (fid, \"    0.2803562   0.0742015   0.3979015 ;\\n\");\n  fprintf (fid, \"    0.2823900   0.0959536   0.4182508 ;\\n\");\n  fprintf (fid, \"    0.2832046   0.1168933   0.4371789 ;\\n\");\n  fprintf (fid, \"    0.2828093   0.1373502   0.4545959 ;\\n\");\n  fprintf (fid, \"    0.2812308   0.1574799   0.4704339 ;\\n\");\n  fprintf (fid, \"    0.2785162   0.1773480   0.4846539 ;\\n\");\n  fprintf (fid, \"    0.2747355   0.1969692   0.4972505 ;\\n\");\n  fprintf (fid, \"    0.2699818   0.2163303   0.5082545 ;\\n\");\n  fprintf (fid, \"    0.2643686   0.2354047   0.5177319 ;\\n\");\n  fprintf (fid, \"    0.2580262   0.2541617   0.5257802 ;\\n\");\n  fprintf (fid, \"    0.2510987   0.2725732   0.5325222 ;\\n\");\n  fprintf (fid, \"    0.2437329   0.2906195   0.5380971 ;\\n\");\n  fprintf (fid, \"    0.2360733   0.3082910   0.5426518 ;\\n\");\n  fprintf (fid, \"    0.2282632   0.3255865   0.5463354 ;\\n\");\n  fprintf (fid, \"    0.2204250   0.3425172   0.5492871 ;\\n\");\n  fprintf (fid, \"    0.2126666   0.3591022   0.5516350 ;\\n\");\n  fprintf (fid, \"    0.2050791   0.3753661   0.5534932 ;\\n\");\n  fprintf (fid, \"    0.1977219   0.3913409   0.5549535 ;\\n\");\n  fprintf (fid, \"    0.1906314   0.4070615   0.5560891 ;\\n\");\n  fprintf (fid, \"    0.1838194   0.4225638   0.5569522 ;\\n\");\n  fprintf (fid, \"    0.1772724   0.4378855   0.5575761 ;\\n\");\n  fprintf (fid, \"    0.1709575   0.4530630   0.5579740 ;\\n\");\n  fprintf (fid, \"    0.1648329   0.4681295   0.5581427 ;\\n\");\n  fprintf (fid, \"    0.1588454   0.4831171   0.5580587 ;\\n\");\n  fprintf (fid, \"    0.1529512   0.4980530   0.5576847 ;\\n\");\n  fprintf (fid, \"    0.1471316   0.5129595   0.5569733 ;\\n\");\n  fprintf (fid, \"    0.1414022   0.5278543   0.5558645 ;\\n\");\n  fprintf (fid, \"    0.1358330   0.5427501   0.5542887 ;\\n\");\n  fprintf (fid, \"    0.1305821   0.5576525   0.5521757 ;\\n\");\n  fprintf (fid, \"    0.1258984   0.5725631   0.5494454 ;\\n\");\n  fprintf (fid, \"    0.1221631   0.5874763   0.5460234 ;\\n\");\n  fprintf (fid, \"    0.1198724   0.6023824   0.5418306 ;\\n\");\n  fprintf (fid, \"    0.1196266   0.6172658   0.5367956 ;\\n\");\n  fprintf (fid, \"    0.1220459   0.6321070   0.5308480 ;\\n\");\n  fprintf (fid, \"    0.1276677   0.6468818   0.5239242 ;\\n\");\n  fprintf (fid, \"    0.1368349   0.6615629   0.5159668 ;\\n\");\n  fprintf (fid, \"    0.1496433   0.6761197   0.5069243 ;\\n\");\n  fprintf (fid, \"    0.1659673   0.6905190   0.4967519 ;\\n\");\n  fprintf (fid, \"    0.1855384   0.7047252   0.4854121 ;\\n\");\n  fprintf (fid, \"    0.2080305   0.7187010   0.4728733 ;\\n\");\n  fprintf (fid, \"    0.2331273   0.7324064   0.4591059 ;\\n\");\n  fprintf (fid, \"    0.2605315   0.7458020   0.4440959 ;\\n\");\n  fprintf (fid, \"    0.2900007   0.7588465   0.4278259 ;\\n\");\n  fprintf (fid, \"    0.3213300   0.7714979   0.4102927 ;\\n\");\n  fprintf (fid, \"    0.3543553   0.7837140   0.3914876 ;\\n\");\n  fprintf (fid, \"    0.3889303   0.7954531   0.3714207 ;\\n\");\n  fprintf (fid, \"    0.4249331   0.8066739   0.3500988 ;\\n\");\n  fprintf (fid, \"    0.4622468   0.8173376   0.3275447 ;\\n\");\n  fprintf (fid, \"    0.5007536   0.8274091   0.3037990 ;\\n\");\n  fprintf (fid, \"    0.5403370   0.8368582   0.2789167 ;\\n\");\n  fprintf (fid, \"    0.5808612   0.8456634   0.2530009 ;\\n\");\n  fprintf (fid, \"    0.6221708   0.8538156   0.2262237 ;\\n\");\n  fprintf (fid, \"    0.6640873   0.8613210   0.1988794 ;\\n\");\n  fprintf (fid, \"    0.7064038   0.8682063   0.1714949 ;\\n\");\n  fprintf (fid, \"    0.7488853   0.8745222   0.1450376 ;\\n\");\n  fprintf (fid, \"    0.7912731   0.8803462   0.1212910 ;\\n\");\n  fprintf (fid, \"    0.8333021   0.8857801   0.1033262 ;\\n\");\n  fprintf (fid, \"    0.8747175   0.8909453   0.0953508 ;\\n\");\n  fprintf (fid, \"    0.9152963   0.8959735   0.1004700 ;\\n\");\n  fprintf (fid, \"    0.9548396   0.9010058   0.1178764 ;\\n\");\n  fprintf (fid, \"    0.9932479   0.9061566   0.1439362 ]);\\n\");\n\n  fprintf (fid, \"close all\\n\");\n  fprintf (fid, \"more off\\n\");\n  fprintf (fid, \"diary diary.log\\n\");\n\n  ## Run and print the demos in each directory\n  for i = 1:numel (dirs)\n    d = dirs{i};\n    if (! is_absolute_filename (d))\n      d = dir_in_loadpath (d);\n    endif\n    if (! isfolder (d))\n      error (\"dump_demos: directory %s does not exist\", d);\n    endif\n    dump_all_demos (d, fid, fmt);\n  endfor\n\n  ## Add helper functions like sombrero\n  dump_helper_fcns (fid);\n\n  ## Stop and flush diary\n  fprintf (fid, \"\\ndiary off\\n\");\n\n  ## Create script ending\n  fprintf (fid, \"end\\n\\n\");\n\n  ## Close script\n  fclose (fid);\n\nendfunction\n\nfunction dump_all_demos (directory, fid, fmt)\n\n  dirinfo = dir (fullfile (directory, \"*.m\"));\n  flist = {dirinfo.name};\n  ## Remove uigetdir, uigetfile, uiputfile, etc.\n  flist = flist(! strncmp (flist, \"ui\", 2));\n  ## Remove linkaxes, linkprops\n  flist = flist(! strncmp (flist, \"link\", 4));\n  ## Remove colormap\n  flist = flist(! strncmp (flist, \"colormap\", 8));\n  for i = 1:numel (flist)\n    fcn = flist{i};\n    fcn(end-1:end) = [];  # remove .m\n    demos = get_demos (fcn);\n    for d = 1:numel (demos)\n      idx = sprintf (\"%02d\", d);\n      base_fcn = sprintf (\"%s_%s\", fcn, idx);\n      fn = sprintf ('%s.%s', base_fcn, fmt);\n      ## Wrap each demo in a function which create a local scope\n      ## to prevent that a previous demo overwrites i or pi, for example\n      fprintf (fid, \"\\nfunction %s ()\\n\", base_fcn);\n      fprintf (fid, \"    %s\\n\\n\", demos{d});\n      fprintf (fid, \"end\\n\\n\");\n\n      fprintf (fid, \"try\\n\");\n      ## First check if the file already exists, skip demo if found\n      fprintf (fid, \"  if (~ exist ('%s', 'file'))\\n\", fn);\n      ## Invoke the ancient, deprecated random seed generators, but there is an\n      ## initialization mismatch with the more modern generators reported\n      ## here (https://savannah.gnu.org/bugs/?42557).\n      fprintf (fid, \"    rand ('seed', 1);\\n\");\n      fprintf (fid, \"    tic ();\\n\");\n      fprintf (fid, \"    %s ();\\n\", base_fcn);\n      fprintf (fid, \"    t_plot = toc ();\\n\");\n      fprintf (fid, \"    fig = (get (0, 'currentfigure'));\\n\");\n      fprintf (fid, \"    if (~ isempty (fig))\\n\");\n      fprintf (fid, \"      figure (fig);\\n\");\n      fprintf (fid, \"      fprintf ('Printing \"\"%s\"\" ... ');\\n\", fn);\n      fprintf (fid, \"      tic ();\\n\");\n      fprintf (fid, \"      print ('-d%s', '%s');\\n\", fmt, fn);\n      fprintf (fid, \"      t_print = toc ();\\n\");\n      fprintf (fid, \"      fprintf ('[%%f %%f] done\\\\n',t_plot, t_print);\\n\");\n      fprintf (fid, \"    end\\n\");\n      ## Temporary fix for cruft accumulating in figure window.\n      fprintf (fid, \"    close ('all');\\n\");\n      fprintf (fid, \"  else\\n\");\n      fprintf (fid, \"    fprintf ('File \"\"%s\"\" already exists.\\\\n');\\n\", fn);\n      fprintf (fid, \"  end\\n\");\n      fprintf (fid, \"catch\\n\");\n      fprintf (fid, \"  fprintf ('ERROR in %s: %%s\\\\n', lasterr ());\\n\", base_fcn);\n      fprintf (fid, \"  err_fid = fopen ('%s.err', 'w');\\n\", base_fcn);\n      fprintf (fid, \"  fprintf (err_fid, '%%s', lasterr ());\\n\");\n      fprintf (fid, \"  fclose (err_fid);\\n\");\n      fprintf (fid, \"end\\n\");\n    endfor\n  endfor\n  fprintf (fid, \"\\nclose all\\n\");\n\nendfunction\n\nfunction retval = get_demos (fcn)\n\n  [code, idx] = test (fcn, \"grabdemo\");\n  num_demos = length (idx) - 1;\n  retval = cell (1, num_demos);\n  ## Now split the demos into a cell array\n  for k = 1:num_demos\n    retval{k} = oct2mat (code(idx(k):idx(k+1)-1));\n  endfor\n\nendfunction\n\nfunction code = oct2mat (code)\n\n  ## Simple hacks to make things Matlab compatible\n  code = strrep (code, \"%!\", \"%%\");    # system operator !\n  code = strrep (code, \"!\", \"~\");      # logical not operator\n\n  ## Simply replacing double quotes with single quotes\n  ## causes problems with strings like 'hello \"world\"' or transpose.\n\n  ## Test input for double quote replacement:\n  ## title (\"bar\");\n  ## a'\n  ## foo 'bar' \"baz\"\n  ## image (repmat ((1:64)', 1, 64));\n  ## fprintf ('File \"brighten_01.png\" already exists.\\n');\n  ## title ({'x^2 + y^2'; 'plotted over circular disk with \"circ\"'});\n  ## annotation ('textbox', [0.1 0 0.8 1], 'string', ...\n  ##             '\"headstyle\" property:', ...\n\n  code = regexprep (code, \"[(,;\\n][ ]*'[^']*'(*SKIP)(*F)|\\\"\", \"'\",\n                          \"lineanchors\", \"dotexceptnewline\");\n\n  ## replace # not inside single quotes\n  code = regexprep (code, \"[(,;\\n][ ]*'[^']*'(*SKIP)(*F)|#\", \"%\");\n\n  ## Shorten all long forms of endXXX to 'end'\n  endkeywords = {\"endfor\", \"endfunction\", \"endif\", \"endwhile\", \"end_try_catch\"};\n  for k = 1:numel (endkeywords)\n    code = strrep (code, endkeywords{k}, \"end\");\n  endfor\n  ## Comment keywords unknown to Matlab\n  commentkeywords = {\"unwind_protect\", \"end_unwind_protect\"};\n  for k = 1:numel (commentkeywords)\n    code = strrep (code, commentkeywords{k}, [\"%\" commentkeywords{k}]);\n  endfor\n  ## Fix in-place operators\n  code = regexprep (code, '(\\S+)(\\s*)(.?[+-/*])=', '$1 = $1 $3');\n  ## Fix x = y = z = XXX assignment\n  code = regexprep (code, '^\\s*([^=\\s]+)\\s*=\\s*([^=\\s]+)\\s*=\\s*([^=\\s]+)\\s*=\\s*([^=\\n]+)$', ...\n                          \"$1 = $4\\n$2 = $4\\n$3 = $4\", \"lineanchors\");\n  ## Fix x = y = XXX assignment\n  code = regexprep (code, '^\\s*([^=\\s]+)\\s*=\\s*([^=\\s]+)\\s*=\\s*([^=\\n]+)$', ...\n                          \"$1 = $3\\n$2 = $3\", \"lineanchors\");\n\nendfunction\n\nfunction dump_helper_fcns (fid)\n\n  fprintf (fid, \"\\n%s\\n\", repmat (\"%\", [1, 60]));\n  fdisp (fid, \"% Helper functions\");\n  fprintf (fid, \"%s\\n\", repmat (\"%\", [1, 60]));\n\n  ## Add sombrero function\n  fdisp (fid, [\n\"function [x, y, z] = sombrero (n)                                            \"\n\"                                                                             \"\n\"  if (nargin == 0)                                                           \"\n\"    n = 41;                                                                  \"\n\"  end                                                                        \"\n\"                                                                             \"\n\"  [xx, yy] = meshgrid (linspace (-8, 8, n));                                 \"\n\"  r = sqrt (xx.^2 + yy.^2) + eps;  % eps prevents div/0 errors               \"\n\"  zz = sin (r) ./ r;                                                         \"\n\"                                                                             \"\n\"  if (nargout == 0)                                                          \"\n\"    surf (xx, yy, zz);                                                       \"\n\"  elseif (nargout == 1)                                                      \"\n\"    x = zz;                                                                  \"\n\"  else                                                                       \"\n\"    x = xx;                                                                  \"\n\"    y = yy;                                                                  \"\n\"    z = zz;                                                                  \"\n\"  end                                                                        \"\n\"                                                                             \"\n\"end                                                                          \"\n]);  # End of sombrero dump\n\n  fprintf (fid, \"\\n\");\n\n  ## Add rgbplot function\n  fdisp (fid, [\n\"function h = rgbplot (cmap, style)                                           \"\n\"                                                                             \"\n\"  if (nargin == 1)                                                           \"\n\"    style = 'profile';                                                       \"\n\"  end                                                                        \"\n\"                                                                             \"\n\"  idx = 1:rows (cmap);                                                       \"\n\"  switch (lower (style))                                                     \"\n\"    case 'profile'                                                           \"\n\"      htmp = plot (idx, cmap(:,1), 'r', ...                                  \"\n\"                   idx, cmap(:,2), 'g', ...                                  \"\n\"                   idx, cmap(:,3), 'b');                                     \"\n\"      set (gca (), 'ytick', 0:0.1:1);                                        \"\n\"      set (gca (), 'xlim', [0 rows(cmap)]);                                  \"\n\"    case 'composite'                                                         \"\n\"      htmp = image (idx);                                                    \"\n\"      set (gca, 'ytick', []);                                                \"\n\"      colormap (cmap);                                                       \"\n\"  end                                                                        \"\n\"  xlabel ('color index');                                                    \"\n\"                                                                             \"\n\"  if (nargout > 0)                                                           \"\n\"    h = htmp;                                                                \"\n\"  end                                                                        \"\n\"                                                                             \"\n\"end                                                                          \"\n]);  # End of rgbplot dump\n\n  fprintf (fid, \"\\n\");\n\n  fprintf (fid, \"\\n%s\\n\", repmat (\"%\", [1, 60]));\n\nendfunction\n"
  },
  {
    "path": "scripts/testfun/private/html-plot-demos-template.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en-US\">\n<head>\n<title>Comparison of plots</title>\n<meta charset=\"utf-8\">\n<style>\ntable, td, th {\n  border: 1px solid black;\n  text-align: center;\n}\ntable {\n  border-collapse: collapse;\n}\n</style>\n</head>\n<body>\n<section>\n<!-- ##ADD TABLE HERE## -->\n</section>\n</body>\n</html>\n"
  },
  {
    "path": "scripts/testfun/private/html_compare_plot_demos.m",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} html_compare (@var{toolkits})\n## @deftypefnx {} {} html_compare (@var{toolkits}, @var{name}, @var{value}, @dots{})\n##\n## Produce an html document to compare the plot demos produced by\n## @var{toolkits}.\n##\n## Valid property names, and their defaults, are:\n##\n## @table @samp\n##   @item fmt\n##   @code{\"png\"}\n##\n##   @item output\n##   @code{\"compare-plot-demos.html\"}\n##\n##   @item template\n##   @code{\"html-plot-demos-template.html\"}\n##\n##   @item column_width\n##   @code{600}\n## @end table\n##\n## The template parameter refers to a specially formatted html file\n## which accompanies this m-file script.\n##\n## Additional toolkit description can be added to the column header\n## with a parameter named equal to the toolkit.  For example:\n##\n## @smallexample\n## @code{html_compare_plot_demos (@{\"gnuplot\", \"fltk\"@}, \"gnuplot\", \" 4.6 patchlevel 5\")}\n## @end smallexample\n##\n## @seealso{compare_plot_demos, dump_demos, demo}\n## @end deftypefn\n\nfunction html_compare_plot_demos (toolkits, varargin)\n\n  ## Set defaults\n  in.fmt = \"png\";\n  in.figfiles = {};\n  in.output_fmt = @(p) sprintf (\"compare-plot-demos-%02i.html\", p);\n  in.template = \"html-plot-demos-template.html\";\n  in.column_width = 600;\n  in.plots_per_page = 50;\n\n  ## Parse inputs\n  for n = 1:2:numel (varargin)\n    in.(lower(varargin{n})) = varargin{n+1};\n  endfor\n\n  ## Compile a list of all files for all toolkits\n  for t = 1:numel (toolkits)\n    filter = sprintf (\"%s/*.%s\", toolkits{t}, in.fmt);\n    in.figfiles = union (in.figfiles, {dir(filter).name});\n  endfor\n\n  fid = fopen (which (in.template), \"r\");\n  template = char (fread (fid)) .';\n  fclose (fid);\n\n  anchor = \"<!-- ##ADD TABLE HERE## -->\";\n  n = strfind (template, anchor);\n  header = strtrim (template(1:n-1));\n  trailer = strtrim (template(n+numel (anchor):end));\n\n  page = 1;\n  do\n    start_fig = (page - 1) * in.plots_per_page + 1;\n    stop_fig = page * in.plots_per_page;\n    last_page = stop_fig >= numel (in.figfiles);\n    if (last_page)\n      stop_fig = numel (in.figfiles);\n    endif\n\n    fid = fopen (in.output_fmt (page), \"w\");\n    unwind_protect\n      fprintf (fid, \"%s\\n\", header);\n      fprintf (fid, \"<h2>Generated on %s by %s with GNU Octave %s</h2>\\n\", ...\n               datestr (now (), 0), mfilename, version);\n\n      ## Create page previous/next\n      if (page > 1)\n        prev_page_link = sprintf (['<p><a href=\"%s\">%s</a></p>' \"\\n\"], ...\n                                  in.output_fmt (page - 1), \"previous page\");\n      else\n        prev_page_link = \"\";\n      endif\n\n      if (! last_page)\n        next_page_link = sprintf (['<p><a href=\"%s\">%s</a></p>' \"\\n\"], ...\n                                  in.output_fmt (page + 1), \"next page\");\n      else\n        next_page_link = \"\";\n      endif\n\n      fprintf (fid, \"%s%s\", prev_page_link, next_page_link);\n\n      ## Create table header\n      fprintf (fid, \"<table>\\n<tr>\\n\");\n      for t = 1:numel (toolkits)\n        ## set default\n        column_header = upper (toolkits{t});\n        if (isfield (in, toolkits{t}))\n          column_header = [column_header, in.(toolkits{t})];\n        endif\n        fprintf (fid, ['<th>%s <a href=\"%s/diary.log\">diary</a></th>' \"\\n\"],\n                 column_header, toolkits{t});\n      endfor\n      fprintf (fid, \"</tr>\\n\");\n      for m = start_fig:stop_fig\n        [~, file] = fileparts (in.figfiles{m});\n        fn = [file \".\" in.fmt];\n        fprintf (fid, ['<tr id=\"%s\">' \"\\n\"], file);\n        for k = toolkits\n          ffn = fullfile (k{:}, fn);\n          fprintf (fid, \"<td><span>%s</span><br>\", ffn);\n          if (exist (ffn, \"file\"))\n            fprintf (fid, ...\n                     '<img alt=\"%s\" src=\"%s\" style=\"width:%dpx\">', ...\n                     file, ffn, in.column_width);\n          else\n            err_fn = strrep (ffn, \".png\", \".err\");\n            if (! exist (err_fn, \"file\"))\n              warning (\"File %s doesn't exist...\", err_fn);\n            else\n              err_fid = fopen (err_fn);\n              msg = char (fread (err_fid))';\n              fclose (err_fid);\n              fprintf (fid, \"<span>%s</span>\", strrep (msg, \"\\n\", \"<br>\"));\n            endif\n          endif\n          fprintf (fid, \"</td>\\n\");\n        endfor\n        fprintf (fid, \"</tr>\\n\");\n      endfor\n\n      fprintf (fid, \"</table>\\n\");\n      fprintf (fid, \"%s%s\", prev_page_link, next_page_link);\n\n      fprintf (fid, \"%s\\n\", trailer);\n      page++;\n    unwind_protect_cleanup\n      fclose (fid);\n    end_unwind_protect\n  until (stop_fig == numel (in.figfiles))\n\nendfunction\n"
  },
  {
    "path": "scripts/testfun/rundemos.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} rundemos ()\n## @deftypefnx {} {} rundemos (@var{directory})\n## Execute built-in demos for all m-files in the specified @var{directory}.\n##\n## Demo blocks in any C++ source files (@file{*.cc}) will also be executed\n## for use with dynamically linked oct-file functions.\n##\n## If no directory is specified, operate on all directories in Octave's search\n## path for functions.\n## @seealso{demo, oruntests, path}\n## @end deftypefn\n\nfunction rundemos (directory)\n\n  if (nargin == 0)\n    dirs = ostrsplit (path (), pathsep ());\n    do_class_dirs = true;\n  elseif (nargin == 1)\n    dirs = {canonicalize_file_name(directory)};\n    if (isempty (dirs{1}) || ! isfolder (dirs{1}))\n      ## Search for directory name in path\n      if (directory(end) == '/' || directory(end) == '\\')\n        directory(end) = [];\n      endif\n      fullname = dir_in_loadpath (directory);\n      if (isempty (fullname))\n        error (\"rundemos: DIRECTORY argument must be a valid pathname\");\n      endif\n      dirs = {fullname};\n    endif\n    do_class_dirs = false;\n  else\n    print_usage ();\n  endif\n\n  for i = 1:numel (dirs)\n    d = dirs{i};\n    run_all_demos (d, do_class_dirs);\n  endfor\n\nendfunction\n\nfunction run_all_demos (directory, do_class_dirs)\n\n  flist = readdir (directory);\n  dirs = {};\n  for i = 1:numel (flist)\n    f = flist{i};\n    if ((length (f) > 2 && strcmpi (f((end-1):end), \".m\"))\n        || (length (f) > 3 && strcmpi (f((end-2):end), \".cc\")))\n      f = fullfile (directory, f);\n      if (has_demos (f))\n        try\n          demo (f);\n        catch\n          printf (\"error: %s\\n\\n\", lasterror ().message);\n        end_try_catch\n        if (i != numel (flist))\n          input (\"Press <enter> to continue: \", \"s\");\n        endif\n      endif\n    elseif (f(1) == \"@\")\n      f = fullfile (directory, f);\n      if (isfolder (f))\n        dirs(end+1) = f;\n      endif\n    endif\n  endfor\n\n  ## Recurse into class directories since they are implied in the path\n  if (do_class_dirs)\n    for i = 1:numel (dirs)\n      d = dirs{i};\n      run_all_demos (d, false);\n    endfor\n  endif\n\nendfunction\n\nfunction retval = has_demos (f)\n\n  fid = fopen (f);\n  if (f < 0)\n    error (\"rundemos: fopen failed: %s\", f);\n  endif\n\n  str = fread (fid, \"*char\").';\n  fclose (fid);\n  retval = ! isempty (regexp (str, '^%!demo', 'lineanchors', 'once'));\n\nendfunction\n\n\n%!error rundemos (\"foo\", 1)\n%!error <DIRECTORY argument> rundemos (\"#_TOTALLY_/_INVALID_/_PATHNAME_#\")\n"
  },
  {
    "path": "scripts/testfun/speed.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} speed (@var{f}, @var{init}, @var{max_n}, @var{f2}, @var{tol})\n## @deftypefnx {} {[@var{order}, @var{n}, @var{T_f}, @var{T_f2}] =} speed (@dots{})\n##\n## Determine the execution time of an expression (@var{f}) for various input\n## values (@var{n}).\n##\n## The @var{n} are log-spaced from 1 to @var{max_n}.  For each @var{n}, an\n## initialization expression (@var{init}) is computed to create any data needed\n## for the test.  If a second expression (@var{f2}) is given then the\n## execution times of the two expressions are compared.  When called without\n## output arguments the results are printed to stdout and displayed\n## graphically.\n##\n## @table @code\n## @item @var{f}\n## The code expression to evaluate.\n##\n## @item @var{max_n}\n## The maximum test length to run.  The default value is 100.  Alternatively,\n## use @code{[min_n, max_n]} or specify the @var{n} exactly with\n## @code{[n1, n2, @dots{}, nk]}.\n##\n## @item @var{init}\n## Initialization expression for function argument values.  Use @var{k} for\n## the test number and @var{n} for the size of the test.  This should compute\n## values for all variables used by @var{f}.  Note that @var{init} will be\n## evaluated first for @math{k = 0}, so things which are constant throughout\n## the test series can be computed once.  The default value is\n## @code{@var{x} = randn (@var{n}, 1)}.\n##\n## @item @var{f2}\n## An alternative expression to evaluate, so that the speed of two\n## expressions can be directly compared.  The default is @code{[]}.\n##\n## @item @var{tol}\n## Tolerance used to compare the results of expression @var{f} and expression\n## @var{f2}.  If @var{tol} is positive, the tolerance is an absolute one.\n## If @var{tol} is negative, the tolerance is a relative one.  The default is\n## @code{eps}.  If @var{tol} is @code{Inf}, then no comparison will be made.\n##\n## @item @var{order}\n## The time complexity of the expression @math{O(a*n^p)}.  This is a\n## structure with fields @code{a} and @code{p}.\n##\n## @item @var{n}\n## The values @var{n} for which the expression was calculated @strong{AND}\n## the execution time was greater than zero.\n##\n## @item @var{T_f}\n## The nonzero execution times recorded for the expression @var{f} in seconds.\n##\n## @item @var{T_f2}\n## The nonzero execution times recorded for the expression @var{f2} in seconds.\n## If required, the mean time ratio is simply @code{mean (T_f ./ T_f2)}.\n##\n## @end table\n##\n## The slope of the execution time graph shows the approximate power of the\n## asymptotic running time @math{O(n^p)}.  This power is plotted for the\n## region over which it is approximated (the latter half of the graph).  The\n## estimated power is not very accurate, but should be sufficient to\n## determine the general order of an algorithm.  It should indicate if, for\n## example, the implementation is unexpectedly @math{O(n^2)} rather than\n## @math{O(n)} because it extends a vector each time through the loop rather\n## than pre-allocating storage.  In the current version of Octave, the\n## following is not the expected @math{O(n)}.\n##\n## @example\n## speed (\"for i = 1:n, y@{i@} = x(i); endfor\", \"\", [1000, 10000])\n## @end example\n##\n## @noindent\n## But it is if you preallocate the cell array @code{y}:\n##\n## @example\n## @group\n## speed (\"for i = 1:n, y@{i@} = x(i); endfor\", ...\n##        \"x = rand (n, 1); y = cell (size (x));\", [1000, 10000])\n## @end group\n## @end example\n##\n## An attempt is made to approximate the cost of individual operations, but\n## it is wildly inaccurate.  You can improve the stability somewhat by doing\n## more work for each @code{n}.  For example:\n##\n## @example\n## speed (\"airy(x)\", \"x = rand (n, 10)\", [10000, 100000])\n## @end example\n##\n## When comparing two different expressions (@var{f}, @var{f2}), the slope of\n## the line on the speedup ratio graph should be larger than 1 if the new\n## expression is faster.  Better algorithms have a shallow slope.  Generally,\n## vectorizing an algorithm will not change the slope of the execution time\n## graph, but will shift it relative to the original.  For example:\n##\n## @example\n## @group\n## speed (\"sum (x)\", \"\", [10000, 100000], ...\n##        \"v = 0; for i = 1:length (x), v += x(i); endfor\")\n## @end group\n## @end example\n##\n## The following is a more complex example.  If there was an original version\n## of @code{xcorr} using for loops and a second version using an FFT, then\n## one could compare the run speed for various lags as follows, or for a fixed\n## lag with varying vector lengths as follows:\n##\n## @example\n## @group\n## speed (\"xcorr (x, n)\", \"x = rand (128, 1);\", 100,\n##        \"xcorr_orig (x, n)\", -100*eps)\n## speed (\"xcorr (x, 15)\", \"x = rand (20+n, 1);\", 100,\n##        \"xcorr_orig (x, n)\", -100*eps)\n## @end group\n## @end example\n##\n## Assuming one of the two versions is in xcorr_orig, this would compare their\n## speed and their output values.  Note that the FFT version is not exact, so\n## one must specify an acceptable tolerance on the comparison @code{100*eps}.\n## In this case, the comparison should be computed relatively, as\n## @code{abs ((@var{x} - @var{y}) ./ @var{y})} rather than absolutely as\n## @code{abs (@var{x} - @var{y})}.\n##\n## Type @kbd{example (\"speed\")} to see some real examples or\n## @kbd{demo (\"speed\")} to run them.\n##\n## @end deftypefn\n\n## Programming Note: All variables for speed must use the internal prefix \"__\".\n## Shared variables are eval'ed into the current workspace and therefore might\n## collide with the names used in the speed.m function itself.\n\n## FIXME: consider two-dimensional speedup surfaces for functions like kron.\nfunction [__order, __test_n, __tnew, __torig] = speed (__f1, __init, __max_n = 100, __f2 = \"\", __tol = eps)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (nargin < 2 || isempty (__init))\n    __init = \"x = randn (n, 1)\";\n  endif\n\n  if (isempty (__max_n))\n    __max_n = 100;\n  endif\n\n  __numtests = 15;\n\n  ## Let user specify range of n.\n  if (isscalar (__max_n))\n    __min_n = 1;\n    assert (__max_n > __min_n);\n    __test_n = logspace (0, log10 (__max_n), __numtests);\n  elseif (length (__max_n) == 2)\n    [__min_n, __max_n] = deal (__max_n(1), __max_n(2));\n    assert (__min_n >= 1);\n    assert (__max_n > __min_n);\n    __test_n = logspace (log10 (__min_n), log10 (__max_n), __numtests);\n  else\n    assert (all (__max_n > 0));\n    __test_n = __max_n;\n  endif\n  ## Force n to be an integer.\n  __test_n = unique (round (__test_n));\n  assert (__test_n >= 1);\n\n  __torig = __tnew = zeros (size (__test_n));\n\n  ## Print and plot the data if no output is requested.\n  do_display = (nargout == 0);\n\n  if (do_display)\n    disp ([\"testing \" __f1 \"\\ninit: \" __init]);\n  endif\n\n  ## Add semicolon closure to all code fragments in case user has not done so.\n  __init(end+1) = \";\";\n  __f1(end+1) = \";\";\n  if (! isempty (__f2))\n    __f2(end+1) = \";\";\n  endif\n\n  ## Make sure the functions are freshly loaded by evaluating them at\n  ## test_n(1); first have to initialize the args though.\n  n = 1;\n  k = 0;\n  eval (__init);\n  eval (__f1);\n  if (! isempty (__f2))\n    eval (__f2);\n  endif\n\n  ## Run the tests.\n  for k = 1:length (__test_n)\n    n = __test_n(k);\n    eval (__init);\n\n    if (do_display)\n      printf (\"n%i = %i  \", k, n);\n      fflush (stdout);\n    endif\n\n    eval ([\"__tid = tic();\" __f1 \"__v1=ans; __t = toc(__tid);\"]);\n    if (__t < 0.25)\n      eval ([\"__tid = tic();\" __f1 \"__t2 = toc(__tid);\"]);\n      eval ([\"__tid = tic();\" __f1 \"__t3 = toc(__tid);\"]);\n      __t = min ([__t, __t2, __t3]);\n    endif\n    __tnew(k) = __t;\n\n    if (! isempty (__f2))\n      eval ([\"__tid = tic();\" __f2 \"__v2=ans; __t = toc(__tid);\"]);\n      if (__t < 0.25)\n        eval ([\"__tid = tic();\" __f2 \"__t2 = toc(__tid);\"]);\n        eval ([\"__tid = tic();\" __f2 \"__t3 = toc(__tid);\"]);\n        __t = min ([__t, __t2, __t3]);\n      endif\n      __torig(k) = __t;\n      if (! isinf (__tol))\n        assert (__v1, __v2, __tol);\n      endif\n    endif\n\n  endfor\n\n  ## Drop times of zero.\n  if (isempty (__f2))\n    zidx = (__tnew < 100*eps);\n    __test_n(zidx) = [];\n    __tnew(zidx) = [];\n  else\n    zidx = (__tnew < 100*eps | __torig < 100*eps);\n    __test_n(zidx) = [];\n    __tnew(zidx) = [];\n    __torig(zidx) = [];\n  endif\n\n  if (isempty (__test_n))\n    error ([\"speed: All running times were zero.\\n\",\n            \"error: speed: Choose larger MAX_N or do more work per function evaluation\"]);\n  endif\n\n  ## Approximate time complexity and return it if requested.\n  tailidx = ceil (length (__test_n)/2):length (__test_n);\n  p = polyfit (log (__test_n(tailidx)), log (__tnew(tailidx)), 1);\n  if (nargout > 0)\n    __order.p = p(1);\n    __order.a = exp (p(2));\n  endif\n\n  if (do_display)\n    figure ();\n    ## Strip semicolon added to code fragments before displaying\n    __init(end) = \"\";\n    __f1(end) = \"\";\n    if (! isempty (__f2))\n      __f2(end) = \"\";\n    endif\n  endif\n\n  if (do_display && isempty (__f2))\n\n    loglog (__test_n, __tnew*1000, \"*-g;execution time;\");\n    xlabel (\"test length\");\n    ylabel (\"best execution time (ms)\");\n    title ({__f1, [\"init: \" __init]});\n\n  elseif (do_display)\n\n    subplot (1, 2, 1);\n    semilogx (__test_n, __tnew ./ __torig, \"-*g\",\n              __test_n, __torig ./ __tnew, \"-*r\");\n    legend ({[strrep(__f1, \";\", \".\") \" / \" strrep(__f2, \";\", \".\")],\n             [strrep(__f2, \";\", \".\") \" / \" strrep(__f1, \";\", \".\")]},\n            \"location\", \"northwest\");\n    title (\"Speedup Ratio\");\n    xlabel (\"test length\");\n    ylabel (\"speedup ratio\");\n\n    subplot (1, 2, 2);\n    loglog (__test_n, __tnew*1000, \"*-g\",\n            __test_n, __torig*1000, \"*-r\");\n    legend ({strrep(__f1,\";\",\".\"),\n             strrep(__f2,\";\",\".\")},\n            \"location\", \"northwest\");\n    title ({\"Execution Times\", [\"init: \" __init]});\n    xlabel (\"test length\");\n    ylabel (\"best execution time (ms)\");\n\n    ratio = mean (__torig ./ __tnew);\n    printf (\"\\n\\nMean runtime ratio = %.3g for '%s' vs '%s'\\n\",\n            ratio, __f2, __f1);\n\n  endif\n\n  if (do_display)\n\n    ## Plot time complexity approximation (using milliseconds).\n    figure;   # Open second plot window\n\n    order = round (10*p(1))/10;\n    if (order >= 0.1)\n      order = sprintf (\"O(n^%g)\", order);\n    else\n      order = \"O(1)\";\n    endif\n    v = polyval (p, log (__test_n(tailidx)));\n\n    loglog (__test_n(tailidx), exp (v) * 1000, sprintf (\"b;%s;\", order));\n    title ({\"Time Complexity\", __f1});\n    xlabel (\"test length\");\n\n    ## Get base time to 1 digit of accuracy.\n    dt = exp (p(2));\n    dt = floor (dt/10^floor (log10 (dt)))*10^floor (log10 (dt));\n    if (log10 (dt) >= -0.5)\n      time = sprintf (\"%g s\", dt);\n    elseif (log10 (dt) >= -3.5)\n      time = sprintf (\"%g ms\", dt*1e3);\n    elseif (log10 (dt) >= -6.5)\n      time = sprintf (\"%g us\", dt*1e6);\n    else\n      time = sprintf (\"%g ns\", dt*1e9);\n    endif\n\n    ## Display nicely formatted complexity.\n    printf (\"\\nFor %s:\\n\", __f1);\n    printf (\"  asymptotic power: %s\\n\", order);\n    printf (\"  approximate time per operation: %s\\n\", time);\n\n  endif\n\nendfunction\n\n\n## FIXME: Demos with declared functions do not work.  See bug #31815.\n##        A workaround has been hacked by not declaring the functions\n##        but using eval to create them in the proper context.\n##        Unfortunately, we can't remove them from the user's workspace\n##        because of another bug (#34497).\n%!demo\n%! fstr_build_orig = cstrcat (\n%!   \"function x = build_orig (n)\\n\",\n%!   \"  ## extend the target vector on the fly\\n\",\n%!   \"  for i=0:n-1, x([1:100]+i*100) = 1:100; endfor\\n\",\n%!   \"endfunction\");\n%! fstr_build = cstrcat (\n%!   \"function x = build (n)\\n\",\n%!   \"  ## preallocate the target vector\\n\",\n%!   \"  x = zeros (1, n*100);\\n\",\n%!   \"  for i=0:n-1, x([1:100]+i*100) = 1:100; endfor\\n\",\n%!   \"endfunction\");\n%!\n%! disp (\"-----------------------\");\n%! disp (fstr_build_orig);\n%! disp (\"-----------------------\");\n%! disp (fstr_build);\n%! disp (\"-----------------------\");\n%!\n%! ## Eval functions strings to create them in the current context\n%! eval (fstr_build_orig);\n%! eval (fstr_build);\n%!\n%! disp (\"Preallocated vector test.\\nThis takes a little while...\");\n%! speed (\"build (n)\", \"\", 1000, \"build_orig (n)\");\n%! clear -f build build_orig\n%! disp (\"-----------------------\");\n%! disp (\"Note how much faster it is to pre-allocate a vector.\");\n%! disp (\"Notice the peak speedup ratio.\");\n\n%!demo\n%! fstr_build_orig = cstrcat (\n%!   \"function x = build_orig (n)\\n\",\n%!   \"  for i=0:n-1, x([1:100]+i*100) = 1:100; endfor\\n\",\n%!   \"endfunction\");\n%! fstr_build = cstrcat (\n%!   \"function x = build (n)\\n\",\n%!   \"  idx = [1:100]';\\n\",\n%!   \"  x = idx(:,ones (1,n));\\n\",\n%!   \"  x = reshape (x, 1, n*100);\\n\",\n%!   \"endfunction\");\n%!\n%! disp (\"-----------------------\");\n%! disp (fstr_build_orig);\n%! disp (\"-----------------------\");\n%! disp (fstr_build);\n%! disp (\"-----------------------\");\n%!\n%! ## Eval functions strings to create them in the current context\n%! eval (fstr_build_orig);\n%! eval (fstr_build);\n%!\n%! disp (\"Vectorized test.\\nThis takes a little while...\");\n%! speed (\"build (n)\", \"\", 1000, \"build_orig (n)\");\n%! clear -f build build_orig\n%! disp (\"-----------------------\");\n%! disp (\"This time, the for loop is done away with entirely.\");\n%! disp (\"Notice how much bigger the speedup is than in example 1.\");\n\n## FIXME: Tests may fail on operating systems with low resolution timers such\n##        as MinGW.  If a failure is reported, it might be better to either\n##        force the tests to do more work, or use %!testif to check the OS.\n%!test\n%! [order, n, T_f1, T_f2] = speed (\"airy (x)\", \"x = rand (n, 10)\", [100, 1000]);\n%! assert (isstruct (order));\n%! assert (size (order), [1, 1]);\n%! assert (fieldnames (order), {\"p\"; \"a\"});\n%! assert (isnumeric (n));\n%! assert (length (n) > 10);\n%! assert (isnumeric (T_f1));\n%! assert (size (T_f1), size (n));\n%! assert (isnumeric (T_f2));\n%! assert (length (T_f2) > 10);\n\n%!test\n%! [order, n, T_f1, T_f2] = speed (\"sum (x)\", \"\", [100, 1000], ...\n%!                            \"v = 0; for i = 1:length (x), v += x(i); endfor\");\n%! assert (isstruct (order));\n%! assert (size (order), [1, 1]);\n%! assert (fieldnames (order), {\"p\"; \"a\"});\n%! assert (isnumeric (n));\n%! assert (length (n) > 10);\n%! assert (isnumeric (T_f1));\n%! assert (size (T_f1), size (n));\n%! assert (isnumeric (T_f2));\n%! assert (length (T_f2) > 10);\n\n## Test input validation\n%!error <Invalid call> speed ()\n"
  },
  {
    "path": "scripts/testfun/test.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {} test @var{name}\n## @deftypefnx {} {} test @var{name} quiet|normal|verbose\n## @deftypefnx {} {} test (\"@var{name}\", \"quiet|normal|verbose\", @var{fid})\n## @deftypefnx {} {} test (\"@var{name}\", \"quiet|normal|verbose\", @var{fname})\n## @deftypefnx {} {@var{success} =} test (@dots{})\n## @deftypefnx {} {[@var{n}, @var{nmax}, @var{nxfail}, @var{nbug}, @var{nskip}, @var{nrtskip}, @var{nregression}] =} test (@dots{})\n## @deftypefnx {} {[@var{code}, @var{idx}] =} test (\"@var{name}\", \"grabdemo\")\n## @deftypefnx {} {} test ([], \"explain\", @var{fid})\n## @deftypefnx {} {} test ([], \"explain\", @var{fname})\n##\n## Perform built-in self-tests from the first file in the loadpath matching\n## @var{name}.\n##\n## @code{test} can be called in either command or functional form.  The exact\n## operation of test is determined by a combination of mode (interactive or\n## batch), reporting level (@qcode{\"quiet\"}, @qcode{\"normal\"},\n## @qcode{\"verbose\"}), and whether a logfile or summary output variable is\n## used.\n##\n## The default mode when @code{test} is called from the command line is\n## interactive.  In this mode, tests will be run until the first error is\n## encountered, or all tests complete successfully.  In batch mode, all tests\n## are run regardless of any failures, and the results are collected for\n## reporting.  Tests which require user interaction, i.e., demo blocks,\n## are never run in batch mode.\n##\n## Batch mode is enabled by either 1) specifying a logfile using the third\n## argument @var{fname} or @var{fid}, or 2) requesting an output argument\n## such as @var{success}, @var{n}, etc.\n##\n## The optional second argument determines the amount of output to generate and\n## which types of tests to run.  The default value is @qcode{\"normal\"}.\n## Requesting an output argument will suppress printing the final summary\n## message and any intermediate warnings, unless verbose reporting is\n## enabled.\n##\n## @table @asis\n## @item @qcode{\"quiet\"}\n## Print a summary message when all tests pass, or print an error with the\n## results of the first bad test when a failure occurs.  Don't run tests which\n## require user interaction.\n##\n## @item @qcode{\"normal\"}\n## Display warning messages about skipped tests or failing xtests during test\n## execution.\n## Print a summary message when all tests pass, or print an error with the\n## results of the first bad test when a failure occurs.  Don't run tests which\n## require user interaction.\n##\n## @item @qcode{\"verbose\"}\n## Display tests before execution.  Print all warning messages.  In interactive\n## mode, run all tests including those which require user interaction.\n## @end table\n##\n## The optional third input argument specifies a logfile where results of the\n## tests should be written.  The logfile may be a character string\n## (@var{fname}) or an open file descriptor ID (@var{fid}).  To enable batch\n## processing, but still print the results to the screen, use @code{stdout} for\n## @var{fid}.\n##\n## When called with just a single output argument @var{success}, @code{test}\n## returns true if all of the tests were successful.  If called with more\n## than one output argument then the number of successful tests (@var{n}),\n## the total number of tests in the file (@var{nmax}), the number of xtest\n## failures (@var{nxfail}), the number of tests failed due known bugs\n## (@var{nbug}), the number of tests skipped due to missing features\n## (@var{nskip}), the number of tests skipped due to run-time\n## conditions (@var{nrtskip}), and the number of regressions\n## (@var{nregression}) are returned.\n##\n## Example\n##\n## @example\n## @group\n## test sind\n## @xresult{}\n## PASSES 5 out of 5 tests\n##\n## [n, nmax] = test (\"sind\")\n## @xresult{}\n## n =  5\n## nmax =  5\n## @end group\n## @end example\n##\n## Additional Calling Syntaxes\n##\n## If the second argument is the string @qcode{\"grabdemo\"}, the contents of\n## any built-in demo blocks are extracted but not executed.  The text for all\n## code blocks is concatenated and returned as @var{code} with @var{idx} being\n## a vector of positions of the ends of each demo block.  For an easier way to\n## extract demo blocks from files, @xref{XREFexample,,example}.\n##\n## If the second argument is @qcode{\"explain\"} then @var{name} is ignored and\n## an explanation of the line markers used in @code{test} output reports is\n## written to the file specified by @var{fname} or @var{fid}.\n##\n## @seealso{assert, fail, demo, example, error}\n## @end deftypefn\n\n## Programming Note: All variables for test() must use the internal prefix \"__\".\n## %!share variables are eval'ed into the current workspace and therefore might\n## collide with the names used in the test.m function itself.\n\nfunction [__n, __nmax, __nxfail, __nbug, __nskip, __nrtskip, __nregression] = test (__name, __flag = \"normal\", __fid = [])\n\n  ## Output from test is prefixed by a \"key\" to quickly understand the issue.\n  persistent __signal_fail  = \"!!!!! \";\n  persistent __signal_empty = \"????? \";\n  persistent __signal_block = \"***** \";\n  persistent __signal_file  = \">>>>> \";\n  persistent __signal_skip  = \"----- \";\n\n  __nxfail = 0;\n  __nbug = 0;\n  __nskip = 0;\n  __nrtskip = 0;\n  __nregression = 0;\n\n  if (nargin < 1)\n    print_usage ();\n  elseif (! isempty (__name) && ! ischar (__name))\n    error (\"test: NAME must be a string\");\n  elseif (! ischar (__flag))\n    error (\"test: second argument must be a string\");\n  elseif (isempty (__name) && (nargin != 3 || ! strcmp (__flag, \"explain\")))\n    print_usage ();\n  endif\n\n  ## Decide if error messages should be collected.\n  __logfile = ! isempty (__fid);\n  __batch = __logfile || nargout > 0;\n  __close_fid = false;\n  if (__logfile)\n    if (ischar (__fid))\n      __fname = __fid;\n      __fid = fopen (__fname, \"wt\");\n      if (__fid < 0)\n        error (\"test: could not open log file %s\", __fname);\n      endif\n      __close_fid = true;\n    endif\n    if (! strcmp (__flag, \"explain\"))\n      fprintf (__fid, \"%sprocessing %s\\n\", __signal_file, __name);\n      fflush (__fid);\n    endif\n  else\n    __fid = stdout;\n  endif\n\n  if (strcmp (__flag, \"normal\"))\n    __grabdemo = false;\n    __rundemo  = false;\n    if (__logfile)\n      __verbose = 1;\n    elseif (__batch)\n      __verbose = -1;\n    else\n      __verbose = 0;\n    endif\n  elseif (strcmp (__flag, \"quiet\"))\n    __grabdemo = false;\n    __rundemo  = false;\n    __verbose  = -1;\n  elseif (strcmp (__flag, \"verbose\"))\n    __grabdemo = false;\n    __rundemo  = ! __batch;\n    __verbose  = 1;\n  elseif (strcmp (__flag, \"grabdemo\"))\n    __grabdemo = true;\n    __rundemo  = false;\n    __verbose  = -1;\n    __demo_code = \"\";\n    __demo_idx = [];\n  elseif (strcmp (__flag, \"explain\"))\n    fprintf (__fid, \"# %s new test file\\n\", __signal_file);\n    fprintf (__fid, \"# %s no tests in file\\n\", __signal_empty);\n    fprintf (__fid, \"# %s test had an unexpected result\\n\", __signal_fail);\n    fprintf (__fid, \"# %s test was skipped\\n\", __signal_skip);\n    fprintf (__fid, \"# %s code for the test\\n\\n\", __signal_block);\n    fprintf (__fid, \"# Search for the unexpected results in the file\\n\");\n    fprintf (__fid, \"# then page back to find the filename which caused it.\\n\");\n    fprintf (__fid, \"# The result may be an unexpected failure (in which\\n\");\n    fprintf (__fid, \"# case an error will be reported) or an unexpected\\n\");\n    fprintf (__fid, \"# success (in which case no error will be reported).\\n\");\n    fflush (__fid);\n    if (__close_fid)\n      fclose (__fid);\n    endif\n    return;\n  else\n    error (\"test: unknown flag '%s'\", __flag);\n  endif\n\n  ## Locate the file with tests.\n  __file = file_in_loadpath (__name, \"all\");\n  for suffix = {\".m\", \".cc\", \".cc-tst\", \".c-tst\", \".C-tst\", \".cpp-tst\", ...\n                \".cxx-tst\"}\n    if (! isempty (__file))\n      break;\n    endif\n    __file = file_in_loadpath ([__name, suffix{1}], \"all\");\n  endfor\n  if (iscell (__file))\n    if (isempty (__file))\n      __file = \"\";\n    else\n      __file = __file{1};  # If repeats, return first in path.\n    endif\n  endif\n  if (isempty (__file))\n    if (__grabdemo)\n      __n = \"\";\n      __nmax = -1;\n    else\n      ftype = exist (__name);\n      if (ftype == 3)\n        fprintf (__fid, \"%s%s source code with tests for dynamically linked function not found\\n\", __signal_empty, __name);\n      elseif (ftype == 5)\n        fprintf (__fid, \"%s%s is a built-in function\\n\", __signal_empty, __name);\n      elseif (any (strcmp (__operators__ (), __name)))\n        fprintf (__fid, \"%s%s is an operator\\n\", __signal_empty, __name);\n      elseif (any (strcmp (__keywords__ (), __name)))\n        fprintf (__fid, \"%s%s is a keyword\\n\", __signal_empty, __name);\n      else\n        fprintf (__fid, \"%s%s does not exist in path\\n\", __signal_empty, __name);\n      endif\n      fflush (__fid);\n      if (nargout > 0)\n        if (nargout == 1)\n          __n = false;\n        else\n          __n = __nmax = 0;\n        endif\n      endif\n    endif\n    if (__close_fid)\n      fclose (__fid);\n    endif\n    return;\n  endif\n\n  ## Grab the test code from the file.\n  __body = __extract_test_code (__file);\n\n  if (isempty (__body))\n    if (__grabdemo)\n      __n = \"\";\n      __nmax = [];\n    else\n      fprintf (__fid, \"%s%s has no tests available\\n\", __signal_empty, __file);\n      fflush (__fid);\n      if (nargout > 0)\n        if (nargout == 1)\n          __n = false;\n        else\n          __n = __nmax = 0;\n        endif\n      endif\n    endif\n    if (__close_fid)\n      fclose (__fid);\n    endif\n    return;\n  else\n    ## Add a dummy comment block to the end for ease of indexing.\n    if (__body(end) == \"\\n\")\n      __body = [\"\\n\" __body \"#\"];\n    else\n      __body = [\"\\n\" __body \"\\n#\"];\n    endif\n  endif\n\n  ## Chop it up into blocks for evaluation.\n  __lineidx = find (__body == \"\\n\");\n  __blockidx = __lineidx(find (! isspace (__body(__lineidx+1))))+1;\n\n  ## Ready to start tests.\n  ## If in batch mode, with a logfile, report what is happening.\n  if (__verbose > 0)\n    disp ([__signal_file, __file]);\n  endif\n\n  ## Track file descriptor leaks\n  __fid_list_orig = fopen (\"all\");\n\n  ## Track variable leaks\n  __base_variables_orig = evalin (\"base\", \"who\");\n  ## Add automatic variable \"ans\" which may not have been created yet.\n  __base_variables_orig{end+1} = \"ans\";\n\n  ## Track variable leaks\n  __global_variables_orig = who (\"global\");\n\n  ## Assume all tests will pass.\n  __all_success = true;\n\n  ## Process each block separately, initially with no shared variables.\n  __tests = __successes = 0;\n  __xfail = __xbug = __xskip = __xrtskip = __xregression = 0;\n  __shared = \" \";\n  __shared_r = \" \";\n  __clearfcn = \"\";\n  for __i = 1:numel (__blockidx)-1\n\n    ## FIXME: Should other global settings be similarly saved and restored?\n    orig_wstate = warning ();\n    unwind_protect\n\n      ## Extract the block.\n      __block = __body(__blockidx(__i):__blockidx(__i+1)-2);\n\n      ## Print the code block before execution if in verbose mode.\n      if (__verbose > 0)\n        fprintf (__fid, \"%s%s\\n\", __signal_block, __block);\n        fflush (__fid);\n      endif\n\n      ## Split __block into __type and __code.\n      __idx = find (! isletter (__block));\n      if (isempty (__idx))\n        __type = __block;\n        __code = \"\";\n      else\n        __type = __block(1:__idx(1)-1);\n        __code = __block(__idx(1):length (__block));\n      endif\n\n      ## Assume the block will succeed.\n      __success = true;\n      __msg = [];\n      __istest = false;\n      __isxtest = false;\n      __bug_id = \"\";\n      __fixed_bug = false;\n\n### DEMO\n\n      ## If in __grabdemo mode, then don't process any other block type.\n      ## So that the other block types don't have to worry about\n      ## this __grabdemo mode, the demo block processor grabs all block\n      ## types and skips those which aren't demo blocks.\n\n      __isdemo = strcmp (__type, \"demo\");\n      if (__grabdemo || __isdemo)\n        if (__grabdemo && __isdemo)\n          if (isempty (__demo_code))\n            __demo_code = __code;\n            __demo_idx = [1, length(__demo_code)+1];\n          else\n            __demo_code = [__demo_code, __code];\n            __demo_idx = [__demo_idx, length(__demo_code)+1];\n          endif\n\n        elseif (__rundemo && __isdemo)\n          try\n            ## process the code in an environment without variables\n            eval (sprintf (\"function __test__ ()\\n%s\\nendfunction\", __code));\n            __test__;\n            input (\"Press <enter> to continue: \", \"s\");\n          catch\n            __success = false;\n            __msg = [__signal_fail \"demo failed\\n\" lasterr()];\n          end_try_catch\n          clear __test__;\n\n        endif\n        ## Code already processed.\n        __code = \"\";\n\n### SHARED\n\n      elseif (strcmp (__type, \"shared\"))\n        ## Separate initialization code from variables.\n        __idx = find (__code == \"\\n\");\n        if (isempty (__idx))\n          __vars = __code;\n          __code = \"\";\n        else\n          __vars = __code (1:__idx(1)-1);\n          __code = __code (__idx(1):length (__code));\n        endif\n\n        ## Strip comments off the variables.\n        __idx = find (__vars == \"%\" | __vars == \"#\");\n        if (! isempty (__idx))\n          __vars = __vars(1:__idx(1)-1);\n        endif\n\n        if (! isempty (deblank (__shared)))\n          ## Explicitly clear any existing shared variables so that\n          ## onCleanup actions will be executed.\n          __shared_vars = strtrim (ostrsplit (__shared, \",\"));\n          if (! isempty (__shared_vars))\n            clear (__shared_vars{:});\n          endif\n        endif\n\n        ## Assign default values to variables.\n        try\n          __vars = deblank (__vars);\n          if (! isempty (__vars))\n            eval ([strrep(__vars, \",\", \"=[];\"), \"=[];\"]);\n            __shared = __vars;\n            __shared_r = [\"[ \" __vars \"] = \"];\n          else\n            __shared = \" \";\n            __shared_r = \" \";\n          endif\n        catch\n          ## Couldn't declare, so don't initialize.\n          __code = \"\";\n          __success = false;\n          __msg = [__signal_fail \"shared variable initialization failed\\n\"];\n        end_try_catch\n\n        ## Initialization code will be evaluated below.\n\n### FUNCTION\n\n      elseif (strcmp (__type, \"function\"))\n        __name_position = function_name (__block);\n        if (isempty (__name_position))\n          __success = false;\n          __msg = [__signal_fail \"test failed: missing function name\\n\"];\n        else\n          __name = __block(__name_position(1):__name_position(2));\n          __code = __block;\n          try\n            eval (__code);  # Define the function\n            __clearfcn = sprintf (\"%sclear %s;\\n\", __clearfcn, __name);\n          catch\n            __success = false;\n            __msg = [__signal_fail \"test failed: syntax error\\n\" lasterr()];\n          end_try_catch\n        endif\n        __code = \"\";\n\n### ENDFUNCTION\n\n      elseif (strcmp (__type, \"endfunction\"))\n        ## endfunction simply declares the end of a previous function block.\n        ## There is no processing to be done here, just skip to next block.\n        __code = \"\";\n\n### ASSERT\n### ASSERT <BUG-ID>\n### FAIL\n### FAIL <BUG-ID>\n###\n###   BUG-ID is a bug number from the bug tracker.  A prefix of '*'\n###   indicates a bug that has been fixed.  Tests that fail for fixed\n###   bugs are reported as regressions.\n\n      elseif (strcmp (__type, \"assert\") || strcmp (__type, \"fail\"))\n        [__bug_id, __code, __fixed_bug] = getbugid (__code);\n        if (isempty (__bug_id))\n          __istest = true;\n        else\n          __isxtest = true;\n        endif\n        ## Put the keyword back on the code.\n        __code = [__type __code];\n        ## The code will be evaluated below as a test block.\n\n### ERROR/WARNING\n\n      elseif (strcmp (__type, \"error\") || strcmp (__type, \"warning\"))\n        __istest = true;\n        __iswarning = strcmp (__type, \"warning\");\n        [__pattern, __id, __code] = getpattern (__code);\n        if (__id)\n          __patstr = [\"id=\" __id];\n        else\n          if (! strcmp (__pattern, '.'))\n            __patstr = [\"<\" __pattern \">\"];\n          else\n            __patstr = ifelse (__iswarning, \"a warning\", \"an error\");\n          endif\n        endif\n        try\n          eval (sprintf (\"function __test__(%s)\\n%s\\nendfunction\",\n                         __shared, __code));\n        catch\n          __success = false;\n          __msg = [__signal_fail \"test failed: syntax error\\n\" lasterr()];\n        end_try_catch\n\n        if (__success)\n          __success = false;\n          ## Setting the \"quiet\" warning state means that no warnings are\n          ## emitted to the command prompt and the lastwarn message and id are\n          ## not set for warnings which are set to \"off\".\n          __warnstate = warning (\"query\", \"quiet\");\n          warning (\"on\", \"quiet\");\n          ## Clear error and warning strings before starting\n          lasterr (\"\");\n          lastwarn (\"\");\n          try\n            eval (sprintf (\"__test__(%s);\", __shared));\n            if (! __iswarning)\n              __msg = [__signal_fail \"error failed.\\n\" ...\n                                     \"Expected \" __patstr \", but got no error\\n\"];\n            else\n              if (! isempty (__id))\n                [~, __err] = lastwarn ();\n                __mismatch = ! strcmp (__err, __id);\n              else\n                __err = trimerr (lastwarn (), \"warning\");\n                __mismatch = isempty (regexp (__err, __pattern, \"once\"));\n              endif\n              warning (__warnstate.state, \"quiet\");\n              if (isempty (__err))\n                __msg = [__signal_fail \"warning failed.\\n\" ...\n                                       \"Expected \" __patstr \", but got no warning\\n\"];\n              elseif (__mismatch)\n                __msg = [__signal_fail \"warning failed.\\n\" ...\n                                       \"Expected \" __patstr \", but got <\" __err \">\\n\"];\n              else\n                __success = true;\n              endif\n            endif\n\n          catch\n            if (! isempty (__id))\n              [~, __err] = lasterr ();\n              __mismatch = ! strcmp (__err, __id);\n            else\n              __err = trimerr (lasterr (), \"error\");\n              __mismatch = isempty (regexp (__err, __pattern, \"once\"));\n            endif\n            warning (__warnstate.state, \"quiet\");\n            if (__iswarning)\n              __msg = [__signal_fail \"warning failed.\\n\" ...\n                                     \"Expected warning \" __patstr ...\n                                     \", but got error <\" __err \">\\n\"];\n            elseif (__mismatch)\n              __msg = [__signal_fail \"error failed.\\n\" ...\n                                     \"Expected \" __patstr \", but got <\" __err \">\\n\"];\n            else\n              __success = true;\n            endif\n          end_try_catch\n          clear __test__;\n        endif\n        ## Code already processed.\n        __code = \"\";\n\n### TESTIF HAVE_FEATURE\n### TESTIF HAVE_FEATURE ; RUNTIME_CONDITION\n### TESTIF HAVE_FEATURE <BUG-ID>\n### TESTIF HAVE_FEATURE ; RUNTIME_CONDITION <BUG-ID>\n###\n###   HAVE_FEATURE is a comma- or whitespace separated list of\n###   macro names that may be checked with __have_feature__.\n###\n###   RUNTIME_CONDITION is an expression to evaluate to check\n###   whether some condition is met when the test is executed.  For\n###   example, have_window_system.\n###\n###   BUG-ID is a bug number from the bug tracker.  A prefix of '*'\n###   indicates a bug that has been fixed.  Tests that fail for fixed\n###   bugs are reported as regressions.\n\n      elseif (strcmp (__type, \"testif\"))\n        __e = regexp (__code, '.$', 'lineanchors', 'once');\n        ## Strip any comment and bug-id from testif line before\n        ## looking for features\n        __feat_line = strtok (__code(1:__e), '#%');\n        __idx1 = index (__feat_line, \"<\");\n        if (__idx1)\n          __tmp = __feat_line(__idx1+1:end);\n          __idx2 = index (__tmp, \">\");\n          if (__idx2)\n            __bug_id = __tmp(1:__idx2-1);\n            if (strncmp (__bug_id, \"*\", 1))\n              __bug_id = __bug_id(2:end);\n              __fixed_bug = true;\n            endif\n            __feat_line = __feat_line(1:__idx1-1);\n          endif\n        endif\n        __idx = index (__feat_line, \";\");\n        if (__idx)\n          __runtime_feat_test = __feat_line(__idx+1:end);\n          __feat_line = __feat_line(1:__idx-1);\n        else\n          __runtime_feat_test = \"\";\n        endif\n        __feat = regexp (__feat_line, '\\w+', 'match');\n        __feat = strrep (__feat, \"HAVE_\", \"\");\n        __have_feat = __have_feature__ (__feat);\n        if (__have_feat)\n          if (isempty (__runtime_feat_test) || eval (__runtime_feat_test))\n            if (isempty (__bug_id))\n              __istest = true;\n            else\n              __isxtest = true;\n            endif\n            __code = __code(__e + 1 : end);\n          else\n            __xrtskip += 1;\n            __code = \"\"; # Skip the code.\n            __msg = [__signal_skip \"skipped test (runtime test)\\n\"];\n          endif\n        else\n          __xskip += 1;\n          __code = \"\"; # Skip the code.\n          __msg = [__signal_skip \"skipped test (missing feature)\\n\"];\n        endif\n\n### TEST\n### TEST <BUG-ID>\n###\n###   BUG-ID is a bug number from the bug tracker.  A prefix of '*'\n###   indicates a bug that has been fixed.  Tests that fail for fixed\n###   bugs are reported as regressions.\n\n      elseif (strcmp (__type, \"test\"))\n        [__bug_id, __code, __fixed_bug] = getbugid (__code);\n        if (! isempty (__bug_id))\n          __isxtest = true;\n        else\n          __istest = true;\n        endif\n        ## Code will be evaluated below.\n\n### XTEST\n### XTEST <BUG-ID>\n###\n###   BUG-ID is a bug number from the bug tracker.  A prefix of '*'\n###   indicates a bug that has been fixed.  Tests that fail for fixed\n###   bugs are reported as regressions.\n\n      elseif (strcmp (__type, \"xtest\"))\n        __isxtest = true;\n        [__bug_id, __code, __fixed_bug] = getbugid (__code);\n        ## Code will be evaluated below.\n\n### Comment block.\n\n      elseif (strcmp (__block(1:1), \"#\"))\n        __code = \"\"; # skip the code\n\n### Unknown block.\n\n      else\n        __istest = true;\n        __success = false;\n        __msg = [__signal_fail \"unknown test type!\\n\"];\n        __code = \"\"; # skip the code\n      endif\n\n      ## evaluate code for test, shared, and assert.\n      if (! isempty (__code))\n        try\n          eval (sprintf (\"function %s__test__(%s)\\n%s\\nendfunction\",\n                         __shared_r, __shared, __code));\n          eval (sprintf (\"%s__test__(%s);\", __shared_r, __shared));\n        catch\n          if (isempty (lasterr ()))\n            error (\"test: empty error text, probably Ctrl-C --- aborting\");\n          else\n            __success = false;\n            if (__isxtest)\n              if (isempty (__bug_id))\n                if (__fixed_bug)\n                  __xregression += 1;\n                  __msg = \"regression\";\n                else\n                  __xfail += 1;\n                  __msg = \"known failure\";\n                endif\n              else\n                if (__fixed_bug)\n                  __xregression += 1;\n                else\n                  __xbug += 1;\n                endif\n                if (all (isdigit (__bug_id)))\n                  __bug_id = [\"https://octave.org/testfailure/?\" __bug_id];\n                endif\n                if (__fixed_bug)\n                  __msg = [\"regression: \" __bug_id];\n                else\n                  __msg = [\"known bug: \" __bug_id];\n                endif\n              endif\n            else\n              __msg = \"test failed\";\n            endif\n            __msg = [__signal_fail __msg \"\\n\" lasterr()];\n          endif\n        end_try_catch\n        clear __test__;\n      endif\n\n      ## All done.  Remember if we were successful and print any messages.\n      if (! isempty (__msg) && (__verbose >= 0 || __logfile))\n        ## Make sure the user knows what caused the error.\n        if (__verbose < 1)\n          fprintf (__fid, \"%s%s\\n\", __signal_block, __block);\n          fflush (__fid);\n        endif\n        fprintf (__fid, \"%s\\n\", __msg);\n        ## Show the variable context.\n        if (! strcmp (__type, \"error\")\n            && ! strcmp (__type, \"testif\")\n            && ! strcmp (__type, \"xtest\")\n            && ! all (__shared == \" \"))\n          fdisp (__fid, \"shared variables \");\n          eval (sprintf (\"fdisp (__fid,var2struct(%s));\", __shared));\n        endif\n        fflush (__fid);\n      endif\n      if (! __success && ! __isxtest)\n        __all_success = false;\n        ## Stop after 1 error if not in batch mode or only pass/fail requested.\n        if (! __batch || nargout == 1)\n          if (nargout > 0)\n            if (nargout == 1)\n              __n = false;\n            else\n              __n = __nmax = 0;\n            endif\n          endif\n          if (__close_fid)\n            fclose (__fid);\n          endif\n          return;\n        endif\n      endif\n      __tests += (__istest || __isxtest);\n      __successes += __success && (__istest || __isxtest);\n\n    unwind_protect_cleanup\n      warning (\"off\", \"all\");\n      warning (orig_wstate);\n    end_unwind_protect\n  endfor\n\n  ## Verify test file did not leak file descriptors.\n  if (! isempty (setdiff (fopen (\"all\"), __fid_list_orig)))\n    warning (\"test: file %s leaked file descriptors\\n\", __file);\n  endif\n\n  ## Verify test file did not leak variables in to base workspace.\n  __leaked_vars = setdiff (evalin (\"base\", \"who\"), __base_variables_orig);\n  if (! isempty (__leaked_vars))\n    warning (\"test: file %s leaked variables to base workspace:%s\\n\",\n             __file, sprintf (\" %s\", __leaked_vars{:}));\n  endif\n\n  ## Verify test file did not leak global variables.\n  __leaked_vars = setdiff (who (\"global\"), __global_variables_orig);\n  if (! isempty (__leaked_vars))\n    warning (\"test: file %s leaked global variables:%s\\n\",\n             __file, sprintf (\" %s\", __leaked_vars{:}));\n  endif\n\n  ## Explicitly clear any existing shared variables so that onCleanup\n  ## actions will be executed.\n  __shared_vars = strtrim (ostrsplit (__shared, \",\"));\n  if (! isempty (__shared_vars))\n    clear (__shared_vars{:});\n  endif\n\n  ## Clear any functions created during test run.\n  eval (__clearfcn, \"\");\n\n  if (nargout == 0)\n    if (__tests || __xfail || __xbug || __xskip || __xrtskip)\n      if (__xfail || __xbug)\n        if (__xfail && __xbug)\n          printf (\"PASSES %d out of %d test%s (%d known failure%s; %d known bug%s)\\n\",\n                  __successes, __tests, ifelse (__tests > 1, \"s\", \"\"),\n                  __xfail, ifelse (__xfail > 1, \"s\", \"\"),\n                  __xbug, ifelse (__xbug > 1, \"s\", \"\"));\n        elseif (__xfail)\n          printf (\"PASSES %d out of %d test%s (%d known failure%s)\\n\",\n                  __successes, __tests, ifelse (__tests > 1, \"s\", \"\"),\n                  __xfail, ifelse (__xfail > 1, \"s\", \"\"));\n        elseif (__xbug)\n          printf (\"PASSES %d out of %d test%s (%d known bug%s)\\n\",\n                  __successes, __tests, ifelse (__tests > 1, \"s\", \"\"),\n                  __xbug, ifelse (__xbug > 1, \"s\", \"\"));\n        endif\n      else\n        printf (\"PASSES %d out of %d test%s\\n\", __successes, __tests,\n               ifelse (__tests > 1, \"s\", \"\"));\n      endif\n      if (__xskip)\n        printf (\"Skipped %d test%s due to missing features\\n\", __xskip,\n                ifelse (__xskip > 1, \"s\", \"\"));\n      endif\n      if (__xrtskip)\n        printf (\"Skipped %d test%s due to run-time conditions\\n\", __xrtskip,\n                ifelse (__xrtskip > 1, \"s\", \"\"));\n      endif\n    else\n      printf (\"%s%s has no tests available\\n\", __signal_empty, __file);\n    endif\n  elseif (__grabdemo)\n    __n    = __demo_code;\n    __nmax = __demo_idx;\n  elseif (nargout == 1)\n    __n = __all_success;\n  else\n    __n = __successes;\n    __nmax = __tests;\n    __nxfail = __xfail;\n    __nbug = __xbug;\n    __nskip = __xskip;\n    __nrtskip = __xrtskip;\n    __nregression = __xregression;\n  endif\n\nendfunction\n\n\n## Create structure with fieldnames the name of the input variables.\nfunction s = var2struct (varargin)\n  for i = 1:nargin\n    s.(inputname (i, true)) = varargin{i};\n  endfor\nendfunction\n\n## Find [start,end] of fn in 'function [a,b] = fn'.\nfunction pos = function_name (def)\n\n  pos = [];\n\n  ## Find the end of the name.\n  right = find (def == \"(\", 1);\n  if (isempty (right))\n    right = numel (def);\n  endif\n  right = find (def(1:right-1) != \" \", 1, \"last\");\n\n  ## Find the beginning of the name.\n  left = max ([find(def(1:right)==\" \", 1, \"last\"), ...\n               find(def(1:right)==\"=\", 1, \"last\")]);\n  if (isempty (left))\n    return;\n  endif\n  left += 1;\n\n  ## Return the end points of the name.\n  pos = [left, right];\n\nendfunction\n\n## Strip <pattern> from '<pattern> code'.\n## Optionally also handles 'id=ID code'\nfunction [pattern, id, rest] = getpattern (str)\n\n  pattern = \".\";\n  id = [];\n  rest = str;\n  str = trimleft (str);\n  if (! isempty (str) && str(1) == \"<\")\n    close = index (str, \">\");\n    if (close)\n      pattern = str(2:close-1);\n      rest = str(close+1:end);\n    endif\n  elseif (strncmp (str, \"id=\", 3))\n    [id, rest] = strtok (str(4:end));\n  endif\n\nendfunction\n\n## Strip <bug-id> from '<pattern> code'.\nfunction [bug_id, rest, fixed] = getbugid (str)\n\n  bug_id = \"\";\n  rest = str;\n  fixed = false;\n\n  str = trimleft (str);\n  if (! isempty (str) && str(1) == \"<\")\n    close = index (str, \">\");\n    if (close)\n      bug_id = str(2:close-1);\n      if (strncmp (bug_id, \"*\", 1))\n        bug_id = bug_id(2:end);\n        fixed = true;\n      endif\n      rest = str(close+1:end);\n    endif\n  endif\n\nendfunction\n\n\n## Strip '.*prefix:' from '.*prefix: msg\\n' and strip trailing blanks.\nfunction msg = trimerr (msg, prefix)\n\n  idx = index (msg, [prefix \":\"]);\n  if (idx > 0)\n    msg(1:idx+length (prefix)) = [];\n  endif\n  msg = strtrim (msg);\n\nendfunction\n\n## Strip leading blanks from string.\nfunction str = trimleft (str)\n  idx = find (! isspace (str), 1);\n  str = str(idx:end);\nendfunction\n\nfunction body = __extract_test_code (nm)\n\n  filedir = fileparts (nm);\n  if (is_same_file (filedir, pwd ()))\n    ## The canonical current directory is not added as key to the load path.\n    ## So it doesn't work as key for \"dir_encoding\". Use \".\" instead.\n    filedir = \".\";\n  endif\n  fid = fopen (nm, \"rt\", \"n\", dir_encoding (filedir));\n  body = \"\";\n  if (fid >= 0)\n    while (ischar (ln = fgets (fid)))\n      if (strncmp (ln, \"%!\", 2))\n        body = [body, ln(3:end)];\n      endif\n    endwhile\n    fclose (fid);\n  endif\n\nendfunction\n\n\n## example from toeplitz\n%!shared msg1,msg2\n%! msg1 = \"C must be a vector\";\n%! msg2 = \"C and R must be vectors\";\n%!fail (\"toeplitz ([])\", msg1)\n%!fail (\"toeplitz ([1,2;3,4])\", msg1)\n%!fail (\"toeplitz ([1,2],[])\", msg2)\n%!fail (\"toeplitz ([1,2],[1,2;3,4])\", msg2)\n%!fail (\"toeplitz ([1,2;3,4],[1,2])\", msg2)\n%!test fail (\"toeplitz\", \"Invalid call to toeplitz\")\n%!fail (\"toeplitz (1, 2, 3)\", \"called with too many inputs\")\n%!test assert (toeplitz ([1,2,3], [1,4]), [1,4; 2,1; 3,2])\n%!assert (toeplitz ([1,2,3], [1,4]), [1,4; 2,1; 3,2])\n%!demo toeplitz ([1,2,3,4],[1,5,6])\n\n## example from kron\n%!error <Invalid call to kron> kron ()\n%!error <Invalid call to kron> kron (1)\n%!test assert (isempty (kron ([], rand (3, 4))))\n%!test assert (isempty (kron (rand (3, 4), [])))\n%!test assert (isempty (kron ([], [])))\n%!shared A, B\n%!test\n%! A = [1, 2, 3; 4, 5, 6];\n%! B = [1, -1; 2, -2];\n%!assert (size (kron (zeros (3, 0), A)), [ 3*rows(A), 0 ])\n%!assert (size (kron (zeros (0, 3), A)), [ 0, 3*columns(A) ])\n%!assert (size (kron (A, zeros (3, 0))), [ 3*rows(A), 0 ])\n%!assert (size (kron (A, zeros (0, 3))), [ 0, 3*columns(A) ])\n%!assert (kron (pi, e), pi*e)\n%!assert (kron (pi, A), pi*A)\n%!assert (kron (A, e), e*A)\n%!assert (kron ([1, 2, 3], A), [ A, 2*A, 3*A ])\n%!assert (kron ([1; 2; 3], A), [ A; 2*A; 3*A ])\n%!assert (kron ([1, 2; 3, 4], A), [ A, 2*A; 3*A, 4*A ])\n%!test\n%! res = [1,-1,2,-2,3,-3; 2,-2,4,-4,6,-6; 4,-4,5,-5,6,-6; 8,-8,10,-10,12,-12];\n%! assert (kron (A, B), res);\n%!shared  # clear out shared variables\n\n## Now verify test() itself\n\n## Test 'fail' keyword\n%!fail (\"test\", \"Invalid call to test\")  # no args, generates usage()\n%!fail (\"test (1,2,3,4)\", \"called with too many inputs\") # too many args\n%!fail ('test (\"test\", \"invalid\")', \"unknown flag\")  # incorrect args\n%!fail ('garbage','garbage.*undefined')  # usage on nonexistent function should be\n\n## Test 'error' keyword\n%!error <Invalid call> test              # no args, generates usage()\n%!error <unknown flag> test (\"test\", \"invalid\"); # incorrect args\n%!error test (\"test\", \"invalid\");        # test without pattern\n%!error <'garbage' undefined> garbage; # usage on nonexistent function is error\n\n## Test 'warning' keyword\n%!warning warning (\"warning message\");   # no pattern\n%!warning <warning message> warning (\"warning message\");   # with pattern\n\n## Test 'shared' keyword\n%!shared a                # create a shared variable\n%!test a = 3;             # assign to a shared variable\n%!test assert (a, 3)      # variable should equal 3\n%!shared b,c              # replace shared variables\n%!test assert (! exist (\"a\", \"var\"));  # a no longer exists\n%!test assert (isempty (b));   # variables start off empty\n%!shared a,b,c            # recreate a shared variable\n%!test assert (isempty (a));   # value is empty even if it had a previous value\n%!test a=1; b=2; c=3;   # give values to all variables\n%!test assert ([a,b,c], [1,2,3]); # test all of them together\n%!test c=6;               # update a value\n%!test assert ([a,b,c], [1,2,6]); # show that the update sticks\n%!shared                  # clear all shared variables\n%!test assert (! exist (\"a\", \"var\")) # show that they are cleared\n%!shared a,b,c            # support for initializer shorthand\n%! a=1; b=2; c=4;\n%!shared                  # clear all shared variables for remainder of tests\n\n## Test 'function' keyword\n%!function x = __test_a (y)\n%!  x = 2*y;\n%!endfunction\n%!assert (__test_a (2), 4)  # Test a test function\n\n%!function __test_a (y)\n%!  x = 2*y;\n%!endfunction\n%!test\n%! __test_a (2);            # Test a test function with no return value\n\n%!function [x,z] = __test_a (y)\n%!  x = 2*y;\n%!  z = 3*y;\n%!endfunction\n%!test\n%! [x,z] = __test_a (3);    # Test a test function with multiple returns\n%! assert (x,6);\n%! assert (z,9);\n\n## Test 'assert' keyword\n%!assert (isempty ([]))     # support for test assert shorthand\n%!assert (size (ones (1,2,3)), [1 2 3])\n\n## Test 'demo' keyword\n%!demo                      # multiline demo block\n%! t = [0:0.01:2*pi]; x = sin (t);\n%! plot (t,x);\n%! % you should now see a sine wave in your figure window\n\n%!demo a=3                  # single line demo blocks work too\n\n%!test\n%! [code, idx] = test (\"test\", \"grabdemo\");\n%! assert (numel (idx), 4);\n%! assert (code(idx(3):end),\n%!         \" a=3                  # single line demo blocks work too\");\n\n## Test 'testif' keyword\n%!testif HAVE_INVALID_FEATURE\n%! error (\"testif executed code despite not having feature\");\n\n## Test 'xtest' keyword\n%!xtest\n%! assert (1, 1);      # Test passes\n%!test <53613>\n%! assert (0, 1);      # Test fails\n\n## Test comment block.  It can contain anything.\n%!##\n%! it is the \"#\" as the block type that makes it a comment\n%! and it stays as a comment even through continuation lines\n%! which means that it works well with commenting out whole tests\n\n## Test test() input validation\n%!error <NAME must be a string> test (1)\n%!error <second argument must be a string> test (\"ls\", 1)\n%!error test ([], \"normal\")\n\n## All of the following tests should fail.  These tests should\n## be disabled unless you are developing test() since users don't\n## like to be presented with known failures.\n## %!test   error (\"---------Failure tests.  Use test('test','verbose',1)\");\n## %!test   assert ([a,b,c],[1,3,6]);   # variables have wrong values\n## %!invalid                   # unknown block type\n## %!error  toeplitz ([1,2,3]); # correct usage\n## %!test   syntax errors)     # syntax errors fail properly\n## %!shared garbage in         # variables must be comma-separated\n## %!error  syntax++error      # error test fails on syntax errors\n## %!error  \"succeeds.\";       # error test fails if code succeeds\n## %!error <wrong pattern> error (\"message\")  # error pattern must match\n## %!demo   with syntax error  # syntax errors in demo fail properly\n## %!shared a,b,c\n## %!demo                      # shared variables not available in demo\n## %! assert (exist (\"a\", \"var\"))\n## %!error\n## %! test ('/etc/passwd');\n## %! test (\"nonexistent file\");\n## %! ## These don't signal an error, so the test for an error fails.  Note\n## %! ## that the call doesn't reference the current fid (it is unavailable),\n## %! ## so of course the informational message is not printed in the log.\n"
  },
  {
    "path": "scripts/time/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/time/addtodate.m",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{d} =} addtodate (@var{d}, @var{q}, @var{f})\n## Add @var{q} amount of time (with units @var{f}) to the serial datenum,\n## @var{d}.\n##\n## @var{f} must be one of @qcode{\"year\"}, @qcode{\"month\"}, @qcode{\"day\"},\n## @qcode{\"hour\"}, @qcode{\"minute\"}, @qcode{\"second\"}, or\n## @qcode{\"millisecond\"}.\n## @seealso{datenum, datevec, etime}\n## @end deftypefn\n\nfunction d = addtodate (d, q, f)\n\n  persistent mult = struct (\"day\", 1, \"hour\", 1/24, \"minute\", 1/1440, ...\n                            \"second\", 1/86400, \"millisecond\", 1/86400000);\n\n  if (nargin != 3)\n    print_usage ();\n  elseif (! (ischar (f) && isrow (f)))\n    error (\"addtodate: F must be a single character string\");\n  endif\n\n  if (isscalar (d) && ! isscalar (q))\n    ## expand d to size of q to make later addition easier.\n    d = repmat (d, size (q));\n  endif\n\n  ## in case the user gives f as a plural, remove the 's'\n  if (\"s\" == f(end))\n    f(end) = [];\n  endif\n\n  if (any (strcmpi ({\"year\" \"month\"}, f)))\n    dtmp = datevec (d);\n    if (strcmpi (\"year\", f))\n      dtmp(:,1) += q(:);\n    elseif (strcmpi (\"month\", f))\n      dtmp(:,2) += q(:);\n      ## adjust the years and months if the date rolls over a year\n      dtmp(:,1) += floor ((dtmp(:,2)-1)/12);\n      dtmp(:,2) = mod (dtmp(:,2)-1, 12) + 1;\n      ## avoid days beyond end of month\n      beyondEOM = dtmp(:,3) > eomday (dtmp(:,1), dtmp(:,2));\n      dtmp(beyondEOM,3) = eomday (dtmp(beyondEOM,1), dtmp(beyondEOM,2));\n    endif\n    dnew = datenum (dtmp);\n    ## make the output the right shape\n    if (numel (d) == numel (dnew))\n      d = reshape (dnew, size (d));\n    else\n      d = reshape (dnew, size (q));\n    endif\n  elseif (any (strcmpi ({\"day\" \"hour\" \"minute\" \"second\", \"millisecond\"}, f)))\n    d += q .* mult.(f);\n  else\n    error (\"addtodate: Invalid time unit: %s\", f);\n  endif\n\nendfunction\n\n\n## tests\n%!shared d\n%! d = datenum (2008, 1, 1);\n## Identity\n%!assert (addtodate (d, 0, \"year\"), d)\n%!assert (addtodate (d, 0, \"month\"), d)\n%!assert (addtodate (d, 0, \"day\"), d)\n%!assert (addtodate (d, 0, \"hour\"), d)\n%!assert (addtodate (d, 0, \"minute\"), d)\n%!assert (addtodate (d, 0, \"second\"), d)\n%!assert (addtodate (d, 0, \"millisecond\"), d)\n## Add one of each\n## leap year\n%!assert (addtodate (d, 1, \"year\"), d+366)\n%!assert (addtodate (d, 1, \"month\"), d+31)\n%!assert (addtodate (d, 1, \"day\"), d+1)\n%!assert (addtodate (d, 1, \"hour\"), d+1/24)\n%!assert (addtodate (d, 1, \"minute\"), d+1/1440)\n%!assert (addtodate (d, 1, \"second\"), d+1/86400)\n%!assert (addtodate (d, 1, \"millisecond\"), d+1/86400000)\n## subtract one of each\n%!assert (addtodate (d, -1, \"year\"), d-365)\n%!assert (addtodate (d, -1, \"month\"), d-31)\n%!assert (addtodate (d, -1, \"day\"), d-1)\n%!assert (addtodate (d, -1, \"hour\"), d-1/24)\n%!assert (addtodate (d, -1, \"minute\"), d-1/1440)\n%!assert (addtodate (d, -1, \"second\"), d-1/86400)\n%!assert (addtodate (d, -1, \"millisecond\"), d-1/86400000)\n## rollover\n%!assert (addtodate (d, 12, \"month\"), d+366)\n%!assert (addtodate (d, 13, \"month\"), d+366+31)\n## multiple inputs and output orientation\n%!assert (addtodate ([d d], [1 13], \"month\"), [d+31 d+366+31])\n%!assert (addtodate ([d;d], [1;13], \"month\"), [d+31;d+366+31])\n%!assert (addtodate (d, [1;13], \"month\"), [d+31;d+366+31])\n%!assert (addtodate (d, [1 13], \"month\"), [d+31 d+366+31])\n%!assert (addtodate ([d;d+1], 1, \"month\"), [d+31;d+1+31])\n%!assert (addtodate ([d d+1], 1, \"month\"), [d+31 d+1+31])\n\n## end of month days\n%!assert <*60671> (addtodate (datenum (\"2020-12-31\"), -1, \"month\"), 738125)\n%!assert <*60671> (addtodate (datenum (\"2020-12-30\"), -1, \"month\"), 738125)\n%!assert <*60671> (addtodate (datenum (\"2020-12-29\"), -1, \"month\"), 738124)\n%!assert <*60671> (addtodate (datenum (\"2021-03-31\"), -1, \"month\"), 738215)\n%!assert <*60671> (addtodate (datenum (\"2021-03-29\"), -1, \"month\"), 738215)\n%!assert <*60671> (addtodate (datenum (\"2020-03-30\"), -1, \"month\"), 737850)\n%!assert <*60671> (addtodate (datenum (\"2020-03-29\"), -1, \"month\"), 737850)\n%!assert <*60671> (addtodate (datenum (\"2020-03-28\"), -1, \"month\"), 737849)\n%!assert <*60671> (addtodate (datenum (\"2020-02-29\"), -1, \"month\"), 737819)\n%!assert <*60671> (addtodate (datenum (\"2020-02-28\"), -1, \"month\"), 737818)\n%!assert <*60671> (addtodate (datenum (\"2020-01-31\"), +1, \"month\"), 737850)\n\n\n## Test input validation\n%!error <Invalid call> addtodate ()\n%!error <Invalid call> addtodate (1)\n%!error <Invalid call> addtodate (1,2)\n%!error <F must be a single character string> addtodate (1,2,3)\n%!error <F must be a single character string> addtodate (1,2,\"month\"')\n%!error <Invalid time unit> addtodate (1,2,\"abc\")\n"
  },
  {
    "path": "scripts/time/asctime.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{str} =} asctime (@var{tm_struct})\n## Convert a time structure to a string using the following\n## format: @qcode{\"ddd mmm mm HH:MM:SS yyyy@backslashchar{}n\"}.\n##\n## For example:\n##\n## @example\n## @group\n## asctime (localtime (time ()))\n##      @xresult{} \"Mon Feb 17 01:15:06 1997@backslashchar{}n\"\n## @end group\n## @end example\n##\n## This is equivalent to @code{ctime (time ())}.\n## @seealso{ctime, localtime, time}\n## @end deftypefn\n\nfunction str = asctime (tm_struct)\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  str = strftime (\"%a %b %d %H:%M:%S %Y\\n\", tm_struct);\n\nendfunction\n\n\n%!test\n%! t = time ();\n%! assert (strcmp (asctime (localtime (t)), ctime (t)));\n\n%!assert (asctime (localtime (time ()))(end), \"\\n\")\n\n%!error <Invalid call> asctime ()\n"
  },
  {
    "path": "scripts/time/calendar.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{c} =} calendar ()\n## @deftypefnx {} {@var{c} =} calendar (@var{d})\n## @deftypefnx {} {@var{c} =} calendar (@var{y}, @var{m})\n## @deftypefnx {} {} calendar (@dots{})\n## Return the current monthly calendar in a 6x7 matrix.\n##\n## If @var{d} is specified, return the calendar for the month containing the\n## date @var{d}, which must be a serial date number or a date string.\n##\n## If @var{y} and @var{m} are specified, return the calendar for year @var{y}\n## and month @var{m}.\n##\n## If no output arguments are specified, print the calendar on the screen\n## instead of returning a matrix.\n## @seealso{datenum, datestr}\n## @end deftypefn\n\nfunction c = calendar (y, m)\n\n  switch (nargin)\n    case 0\n      v = clock ();\n      y = v(1);\n      m = v(2);\n      d = v(3);\n\n    case 1\n      v = datevec (y);\n      y = v(1);\n      m = v(2);\n      d = v(3);\n\n    case 2\n      d = [];\n\n  endswitch\n\n  cal = zeros (7, 6);\n  dayone = datenum (y, m, 1);\n  ndays = eomday (y, m);\n  cal(weekday (dayone) - 1 + [1:ndays]) = 1:ndays;\n\n  if (nargout > 0)\n    c = cal';\n  else\n    ## Layout the calendar days, 6 columns per day, 7 days per row.\n    str = sprintf (\"    %2d    %2d    %2d    %2d    %2d    %2d    %2d\\n\", cal);\n\n    ## Print an asterisk before the specified date.\n    if (! isempty (d))\n      pos = weekday (dayone) + d - 1;\n      idx = 6*pos + fix (pos / 7.1) - ifelse (d < 10, 1, 2);\n      str(idx) = \"*\";\n    endif\n\n    ## Display the calendar.\n    s.year = y - 1900;\n    s.mon = m - 1;\n    puts (strftime (\"                    %b %Y\\n\", s));\n    puts (\"     S     M    Tu     W    Th     F     S\\n\");\n    puts (str);\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Calendar for current month\n%! calendar ()\n\n%!demo\n%! ## Calendar for October, 1957\n%! calendar (1957, 10)\n\n%!assert ((calendar(2000,2))'(2:31), [0:29])\n%!assert ((calendar(1957,10))'(2:33), [0:31])\n"
  },
  {
    "path": "scripts/time/clock.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{datevec} =} clock ()\n## @deftypefnx {} {[@var{datevec}, @var{isdst}] =} clock ()\n## Return the current local date and time as a date vector.\n##\n## The date vector contains the following fields: current year, month (1-12),\n## day (1-31), hour (0-23), minute (0-59), and second (0-61).  The seconds\n## field has a fractional part after the decimal point for extended accuracy.\n##\n## The optional second output @var{isdst} is true if Daylight Savings Time\n## (DST) is in effect for the system's time zone.\n##\n## For example:\n##\n## @example\n## @group\n## fix (clock ())\n##   @xresult{}   1993      8     20      4     56      1\n## @end group\n## @end example\n##\n## @code{clock} is more accurate on systems that have the @code{gettimeofday}\n## function.\n## @seealso{now, date, datevec}\n## @end deftypefn\n\nfunction [datevec, isdst] = clock ()\n\n  tm = localtime (time ());\n\n  datevec = zeros (1, 6);\n  datevec(1) = tm.year + 1900;\n  datevec(2) = tm.mon + 1;\n  datevec(3) = tm.mday;\n  datevec(4) = tm.hour;\n  datevec(5) = tm.min;\n  datevec(6) = tm.sec + tm.usec / 1e6;\n\n  isdst = tm.isdst;\n\nendfunction\n\n\n%!test\n%! t1 = clock ();\n%! t2 = str2num (strftime (\"[%Y, %m, %d, %H, %M, %S]\", localtime (time ())));\n%! assert (etime (t1, t2) < 1);\n"
  },
  {
    "path": "scripts/time/ctime.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{str} =} ctime (@var{t})\n## Convert a value returned from @code{time} (or any other non-negative\n## integer), to the local time and return a string of the same form as\n## @code{asctime}.\n##\n## The function @code{ctime (time)} is equivalent to\n## @code{asctime (localtime (time))}.  For example:\n##\n## @example\n## @group\n## ctime (time ())\n##    @xresult{} \"Mon Feb 17 01:15:06 1997@backslashchar{}n\"\n## @end group\n## @end example\n## @seealso{asctime, time, localtime}\n## @end deftypefn\n\nfunction str = ctime (t)\n\n  if (nargin != 1)\n    print_usage ();\n  endif\n\n  str = asctime (localtime (t));\n\nendfunction\n\n\n%!test\n%! t = time ();\n%! assert (strcmp (asctime (localtime (t)), ctime (t)));\n\n%!assert (ctime (time ())(end), \"\\n\")\n\n%!error <Invalid call> ctime ()\n"
  },
  {
    "path": "scripts/time/date.m",
    "content": "########################################################################\n##\n## Copyright (C) 1995-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{str} =} date ()\n## Return the current date as a character string in the form DD-MMM-YYYY@.\n##\n## For example:\n##\n## @example\n## @group\n## date ()\n##   @xresult{} 20-Aug-1993\n## @end group\n## @end example\n## @seealso{now, clock, datestr, localtime}\n## @end deftypefn\n\nfunction str = date ()\n\n  str = strftime (\"%d-%b-%Y\", localtime (time ()));\n\nendfunction\n\n\n%!assert (strcmp (date (), strftime (\"%d-%b-%Y\", localtime (time ()))))\n"
  },
  {
    "path": "scripts/time/datenum.m",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{days} =} datenum (@var{datevec})\n## @deftypefnx {} {@var{days} =} datenum (@var{year}, @var{month}, @var{day})\n## @deftypefnx {} {@var{days} =} datenum (@var{year}, @var{month}, @var{day}, @var{hour})\n## @deftypefnx {} {@var{days} =} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute})\n## @deftypefnx {} {@var{days} =} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute}, @var{second})\n## @deftypefnx {} {@var{days} =} datenum (\"datestr\")\n## @deftypefnx {} {@var{days} =} datenum (\"datestr\", @var{f})\n## @deftypefnx {} {@var{days} =} datenum (\"datestr\", @var{p})\n## @deftypefnx {} {[@var{days}, @var{secs}] =} datenum (@dots{})\n## Return the date/time input as a serial day number, with Jan 1, 0000\n## defined as day 1.\n##\n## The integer part, @code{floor (@var{days})} counts the number of\n## complete days in the date input.\n##\n## The fractional part, @code{rem (@var{days}, 1)} corresponds to the time\n## on the given day.\n##\n## The input may be a date vector (@pxref{XREFdatevec,,@code{datevec}}),\n## date string (@pxref{XREFdatestr,,@code{datestr}}), or directly specified\n## as input.\n##\n## When processing input datestrings, @var{f} is the format string used to\n## interpret date strings (@pxref{XREFdatestr,,@code{datestr}}).  If no\n## format @var{f} is specified, then a relatively slow search is performed\n## through various formats.  It is always preferable to specify the format\n## string @var{f} if it is known.  Formats which do not specify a particular\n## time component will have the value set to zero.  Formats which do not\n## specify a date will default to January 1st of the current year.\n##\n## When passing separate @var{year}, @var{month}, @var{day}, etc.@: arguments,\n## each may be a scalar or nonscalar array.  Nonscalar inputs must all be of\n## the same size.  Scalar inputs will be expanded to be the size of the\n## nonscalar inputs.\n##\n## @var{p} is the year at the start of the century to which two-digit years\n## will be referenced.  If not specified, it defaults to the current year\n## minus 50.\n##\n## The optional output @var{secs} holds the time on the specified day with\n## greater precision than @var{days}.\n##\n## Notes:\n##\n## @itemize\n## @item\n## Years can be negative and/or fractional.\n##\n## @item\n## Months below 1 are considered to be January.\n##\n## @item\n## Days of the month start at 1.\n##\n## @item\n## Days beyond the end of the month go into subsequent months.\n##\n## @item\n## Days before the beginning of the month go to the previous month.\n##\n## @item\n## Days can be fractional.\n## @end itemize\n##\n## Examples:\n##\n## @example\n## @group\n## Convert from datestrs:\n## d = datenum (\"1966-06-14\")\n## @xresult{} d = 718232\n## @end group\n##\n## @group\n## d = datenum (@{\"1966-06-14\", \"1966-06-15\", \"1966-06-16\"@})\n## @xresult{} d =\n##       718232\n##       718233\n##       718234\n## @end group\n##\n## @group\n## Convert from datevec:\n## d = datenum ([1966 06 14])\n## @xresult{} d = 718232\n## @end group\n##\n## @group\n## d = datenum ([1966 06 14 23 59 59])\n## @xresult{} d = 718232.9999884259\n## @end group\n##\n## @group\n## Specify date components separately:\n## d = datenum (1966, 6, 14)\n## @xresult{} d = 718232\n## @end group\n##\n## @group\n## d = datenum (1966, magic(3), 1)\n## @xresult{} d =\n##\n##       718280   718068   718219\n##       718127   718188   718249\n##       718158   718311   718099\n## @end group\n## @end example\n##\n## @strong{Caution:} datenums represent a specific time for the Earth as a\n## whole.  They do not take in to account time zones (shifts in time based\n## on location), nor seasonal changes due to Daylight Savings Time (shifts in\n## time based on local regulation).  Be aware that it is possible to create\n## datenums that, when interpreted by a function which accounts for time zone\n## and DST shifts such as @code{datestr}, are nonexistent or ambiguous.\n##\n## @strong{Caution:} this function does not attempt to handle Julian calendars\n## so dates before October 15, 1582 are wrong by as much as eleven days.  Also,\n## be aware that only Roman Catholic countries adopted the calendar in 1582.\n## It took until 1924 for it to be adopted everywhere.  See the Wikipedia entry\n## on the Gregorian calendar for more details.\n##\n## @strong{Warning:} leap seconds are ignored.  A table of leap seconds is\n## available on the Wikipedia entry for leap seconds.\n##\n## @seealso{datestr, datevec, now, clock, date}\n## @end deftypefn\n\n## Algorithm: Peter Baum (http://vsg.cape.com/~pbaum/date/date0.htm)\n\nfunction [days, secs] = datenum (year, month = [], day = [], hour = 0, minute = 0, second = 0)\n\n  ## Days until start of month assuming year starts March 1.\n  persistent monthstart = [306; 337; 0; 31; 61; 92; 122; 153; 184; 214; 245; 275];\n  persistent monthlength = [31; 28; 31; 30; 31; 30; 31; 31; 30; 31; 30; 31];\n\n  if (nargin == 0 || (nargin > 2 && (ischar (year) || iscellstr (year))))\n    print_usage ();\n  endif\n\n  do_reshape = false;\n  if (ischar (year) || iscellstr (year))\n    [year, month, day, hour, minute, second] = datevec (year, month);\n  else\n    if (nargin == 1)\n      nc = columns (year);\n      if (nc > 6 || nc < 3)\n        error (\"datenum: expected date vector containing [YEAR, MONTH, DAY, HOUR, MINUTE, SECOND]\");\n      endif\n      if (nc >= 6) second = year(:,6); endif\n      if (nc >= 5) minute = year(:,5); endif\n      if (nc >= 4) hour   = year(:,4); endif\n      day   = year(:,3);\n      month = year(:,2);\n      year  = year(:,1);\n    else\n      [err, year, month, day] = common_size (year, month, day);\n      if (err)\n        error (\"datenum: incompatible sizes for YEAR, MONTH, DAY\");\n      endif\n      ## Preserve shape if necessary, and work with column vectors\n      ## for the remainder of the function.\n      do_reshape = ! iscolumn (day);\n      if (do_reshape)\n        sz_reshape = size (day);\n        year = year(:);\n        month = month(:);\n        day = day(:);\n      endif\n    endif\n  endif\n\n  if (! (isa (year, \"double\") && isa (month, \"double\")\n         && isa (day, \"double\") && isa (hour, \"double\")\n         && isa (minute, \"double\") && isa (second, \"double\")))\n    error (\"datenum: all inputs must be of class double\");\n  endif\n\n  ## For Matlab compatibility.  Otherwise, could allow negative months.\n  month(month < 1) = 1;\n\n  ## Treat fractional months, by converting the fraction to days\n  if (any (month != fix (month)))\n    fracmonth = month - floor (month);\n    month = floor (month);\n    ## Separate regular months from leap months\n    idx = mod (month-1,12) + 1 != 2 | ! is_leap_year (floor (year));\n    day(idx) += fracmonth(idx) .* monthlength(mod (month(idx)-1,12) + 1);\n    day(! idx) += fracmonth(! idx) * 29;\n  endif\n\n  ## Set start of year to March by moving Jan. and Feb. to previous year.\n  ## Correct for months > 12 by moving to subsequent years.\n  year += ceil ((month-14)/12);\n\n  ## Lookup number of days since start of the current year.\n  day += monthstart(mod (month-1,12) + 1) + 60;\n\n  ## Treat fractional years, by converting the fraction to days\n  if (any (year != fix (year)))\n    fracyear = year - floor (year);\n    year = floor (year);\n    day += fracyear .* (365 + is_leap_year (year+1));\n  endif\n\n  ## Add number of days to the start of the current year.  Correct\n  ## for leap year every 4 years except centuries not divisible by 400.\n  day += 365*year + floor (year/4) - floor (year/100) + floor (year/400);\n\n  if (do_reshape)\n    day = reshape (day, sz_reshape);\n  endif\n\n  ## Add fraction representing current second of the day.\n  days = day + (hour + (minute + second/60)/60)/24;\n\n  ## Output seconds if asked so that etime can be more accurate\n  if (nargout > 1)\n    secs = day*86400 + hour*3600 + minute*60 + second;\n  endif\n\nendfunction\n\n\n%!shared part\n%! part = 0.514623842592593;\n%!assert (datenum (2001,5,19), 730990)\n%!assert (datenum ([1417,6,12]), 517712)\n%!assert (datenum ([2001,5,19;1417,6,12]), [730990;517712])\n%!assert (datenum (2001,5,19,12,21,3.5), 730990+part, eps)\n%!assert (datenum ([1417,6,12,12,21,3.5]), 517712+part, eps)\n\n## Test vector inputs\n%!test\n%! t = [2001,5,19,12,21,3.5; 1417,6,12,12,21,3.5];\n%! n = [730990; 517712] + part;\n%! assert (datenum (t), n, 2*eps);\n%! ## Check that vectors can have either orientation\n%! t = t';\n%! n = n';\n%! assert (datenum (t(1,:), t(2,:), t(3,:), t(4,:), t(5,:), t(6,:)), n, 2*eps);\n\n%!assert (size (datenum (2000, 1, ones(1, 1, 3))), [1 1 3])\n\n## Test fractional years including leap years\n%!assert (fix (datenum ([2001.999 1 1; 2001.999 2 1])), [731216; 731247])\n%!assert (fix (datenum ([2004.999 1 1; 2004.999 2 1])), [732312; 732343])\n\n## Test fractional months including leap months\n%!assert (fix (datenum ([2001 1.999 1; 2001 2.999 1])), [730882; 730910])\n%!assert (fix (datenum ([2004 1.999 1; 2004 2.999 1])), [731977; 732006])\n\n\n## Test mixed vectors and scalars\n%!assert (datenum ([2008;2009],1,1), [datenum(2008,1,1);datenum(2009,1,1)])\n%!assert (datenum (2008, [1;2], 1), [datenum(2008,1,1);datenum(2008,2,1)])\n%!assert (datenum (2008, 1, [1;2]), [datenum(2008,1,1);datenum(2008,1,2)])\n%!assert (datenum ([2008;2009], [1;2], 1),\n%!        [datenum(2008,1,1);datenum(2009,2,1)])\n%!assert (datenum ([2008;2009], 1, [1;2]),\n%!        [datenum(2008,1,1);datenum(2009,1,2)])\n%!assert (datenum (2008, [1;2], [1;2]), [datenum(2008,1,1);datenum(2008,2,2)])\n## And the other orientation\n%!assert (datenum ([2008 2009], 1, 1), [datenum(2008,1,1) datenum(2009,1,1)])\n%!assert (datenum (2008, [1 2], 1), [datenum(2008,1,1) datenum(2008,2,1)])\n%!assert (datenum (2008, 1, [1 2]), [datenum(2008,1,1) datenum(2008,1,2)])\n%!assert (datenum ([2008 2009], [1 2], 1),\n%!        [datenum(2008,1,1) datenum(2009,2,1)])\n%!assert (datenum ([2008 2009], 1, [1 2]),\n%!        [datenum(2008,1,1) datenum(2009,1,2)])\n%!assert (datenum (2008, [1 2], [1 2]), [datenum(2008,1,1) datenum(2008,2,2)])\n\n## Test string and cellstr inputs\n%!assert (datenum (\"5/19/2001\"), 730990)\n%!assert (datenum ({\"5/19/2001\"}), 730990)\n%!assert (datenum (char (\"5/19/2001\", \"6/6/1944\")), [730990; 710189])\n%!assert (datenum ({\"5/19/2001\", \"6/6/1944\"}), [730990; 710189])\n\n## Test string input with format string\n%!assert (datenum (\"5-19, 2001\", \"mm-dd, yyyy\"), 730990)\n\n## Test input validation\n%!error <Invalid call> datenum ()\n%!error <expected date vector containing> datenum ([1, 2])\n%!error <expected date vector containing> datenum ([1,2,3,4,5,6,7])\n%!error <all inputs must be of class double> datenum (int32 (2000), int32 (1), int32 (1))\n"
  },
  {
    "path": "scripts/time/datestr.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{str} =} datestr (@var{date})\n## @deftypefnx {} {@var{str} =} datestr (@var{date}, @var{f})\n## @deftypefnx {} {@var{str} =} datestr (@var{date}, @var{f}, @var{p})\n## Format the given date/time according to the format @var{f} and return\n## the result in @var{str}.\n##\n## @var{date} is a serial date number (@pxref{XREFdatenum,,@code{datenum}}), a\n## date vector (@pxref{XREFdatevec,,@code{datevec}}), or a string or cell array\n## of strings.  In the latter case, it is passed to @code{datevec} to guess the\n## input date format.\n##\n## @var{f} can be an integer which corresponds to one of the codes in the table\n## below, or a date format string.\n##\n## @var{p} is the year at the start of the century in which two-digit years are\n## to be interpreted in.  If not specified, it defaults to the current year\n## minus 50.\n##\n## For example, the date 730736.65149 (2000-09-07 15:38:09.0934) would be\n## formatted as follows:\n##\n## @multitable @columnfractions 0.1 0.45 0.35\n## @headitem Code @tab Format @tab Example\n## @item 0 @tab dd-mmm-yyyy HH:MM:SS    @tab 07-Sep-2000 15:38:09\n## @item 1 @tab dd-mmm-yyyy             @tab 07-Sep-2000\n## @item 2 @tab mm/dd/yy                @tab 09/07/00\n## @item 3 @tab mmm                     @tab Sep\n## @item 4 @tab m                       @tab S\n## @item 5 @tab mm                      @tab 09\n## @item 6 @tab mm/dd                   @tab 09/07\n## @item 7 @tab dd                      @tab 07\n## @item 8 @tab ddd                     @tab Thu\n## @item 9 @tab d                       @tab T\n## @item 10 @tab yyyy                   @tab 2000\n## @item 11 @tab yy                     @tab 00\n## @item 12 @tab mmmyy                  @tab Sep00\n## @item 13 @tab HH:MM:SS               @tab 15:38:09\n## @item 14 @tab HH:MM:SS PM            @tab  3:38:09 PM\n## @item 15 @tab HH:MM                  @tab 15:38\n## @item 16 @tab HH:MM PM               @tab  3:38 PM\n## @item 17 @tab QQ-YY                  @tab Q3-00\n## @item 18 @tab QQ                     @tab Q3\n## @item 19 @tab dd/mm                  @tab 07/09\n## @item 20 @tab dd/mm/yy               @tab 07/09/00\n## @item 21 @tab mmm.dd,yyyy HH:MM:SS   @tab Sep.07,2000 15:38:08\n## @item 22 @tab mmm.dd,yyyy            @tab Sep.07,2000\n## @item 23 @tab mm/dd/yyyy             @tab 09/07/2000\n## @item 24 @tab dd/mm/yyyy             @tab 07/09/2000\n## @item 25 @tab yy/mm/dd               @tab 00/09/07\n## @item 26 @tab yyyy/mm/dd             @tab 2000/09/07\n## @item 27 @tab QQ-YYYY                @tab Q3-2000\n## @item 28 @tab mmmyyyy                @tab Sep2000\n## @item 29 @tab yyyy-mm-dd             @tab 2000-09-07\n## @item 30 @tab yyyymmddTHHMMSS        @tab 20000907T153808\n## @item 31 @tab yyyy-mm-dd HH:MM:SS    @tab 2000-09-07 15:38:08\n## @end multitable\n##\n## If @var{f} is a format string, the following symbols are recognized:\n##\n## @multitable @columnfractions 0.1 0.7 0.2\n## @headitem Symbol @tab Meaning @tab Example\n## @item yyyy @tab Full year                                    @tab 2005\n## @item yy   @tab Two-digit year                               @tab 05\n## @item mmmm @tab Full month name                              @tab December\n## @item mmm  @tab Abbreviated month name                       @tab Dec\n## @item mm   @tab Numeric month number (padded with zeros)     @tab 01, 08, 12\n## @item m    @tab First letter of month name (capitalized)     @tab D\n## @item dddd @tab Full weekday name                            @tab Sunday\n## @item ddd  @tab Abbreviated weekday name                     @tab Sun\n## @item dd   @tab Numeric day of month (padded with zeros)     @tab 11\n## @item d    @tab First letter of weekday name (capitalized)   @tab S\n## @item HH   @tab Hour of day, padded with zeros,              @tab 09:00\n## @item      @tab or padded with spaces if PM is set           @tab  9:00 AM\n## @item MM   @tab Minute of hour (padded with zeros)           @tab 10:05\n## @item SS   @tab Second of minute (padded with zeros)         @tab 10:05:03\n## @item FFF  @tab Milliseconds of second (padded with zeros)   @tab 10:05:03.012\n## @item AM   @tab Use 12-hour time format                      @tab 11:30 AM\n## @item PM   @tab Use 12-hour time format                      @tab 11:30 PM\n## @end multitable\n##\n## If @var{f} is not specified or is @code{-1}, then use 0, 1 or 16, depending\n## on whether the date portion or the time portion of @var{date} is empty.\n##\n## If @var{p} is not specified, it defaults to the current year minus 50.\n##\n## If a matrix or cell array of dates is given, a column vector of date strings\n## is returned.\n##\n## @seealso{datenum, datevec, date, now, clock}\n## @end deftypefn\n\n## FIXME: parse arbitrary code strings.\n## e.g., for Wednesday 2001-03-05 09:04:06 AM, use\n##     yy    01\n##     yyyy  2001\n##     m     M\n##     mm    03\n##     mmm   Mar\n##     d     W\n##     dd    05\n##     ddd   Wed\n##     HH    09\n##     MM    04\n##     SS    06\n##     PM    AM\n## FIXME: Vectorize.  It is particularly easy since all the codes are\n##    fixed width.  Just generate the parts in separate arrays and\n##    concatenate.\n\nfunction retval = datestr (date, f = [], p = [])\n\n  persistent dateform names_mmmm names_m names_d;\n\n  if (isempty (dateform))\n    dateform = cell (32, 1);\n    dateform{1}  = \"dd-mmm-yyyy HH:MM:SS\";\n    dateform{2}  = \"dd-mmm-yyyy\";\n    dateform{3}  = \"mm/dd/yy\";\n    dateform{4}  = \"mmm\";\n    dateform{5}  = \"m\";\n    dateform{6}  = \"mm\";\n    dateform{7}  = \"mm/dd\";\n    dateform{8}  = \"dd\";\n    dateform{9}  = \"ddd\";\n    dateform{10} = \"d\";\n    dateform{11} = \"yyyy\";\n    dateform{12} = \"yy\";\n    dateform{13} = \"mmmyy\";\n    dateform{14} = \"HH:MM:SS\";\n    dateform{15} = \"HH:MM:SS PM\";\n    dateform{16} = \"HH:MM\";\n    dateform{17} = \"HH:MM PM\";\n    dateform{18} = \"QQ-YY\";\n    dateform{19} = \"QQ\";\n    dateform{20} = \"dd/mm\";\n    dateform{21} = \"dd/mm/yy\";\n    dateform{22} = \"mmm.dd,yyyy HH:MM:SS\";\n    dateform{23} = \"mmm.dd,yyyy\";\n    dateform{24} = \"mm/dd/yyyy\";\n    dateform{25} = \"dd/mm/yyyy\";\n    dateform{26} = \"yy/mm/dd\";\n    dateform{27} = \"yyyy/mm/dd\";\n    dateform{28} = \"QQ-YYYY\";\n    dateform{29} = \"mmmyyyy\";\n    dateform{30} = \"yyyy-mm-dd\";\n    dateform{31} = \"yyyymmddTHHMMSS\";\n    dateform{32} = \"yyyy-mm-dd HH:MM:SS\";\n\n    names_m = {\"J\", \"F\", \"M\", \"A\", \"M\", \"J\", \"J\", \"A\", \"S\", \"O\", \"N\", \"D\"};\n    names_d = {\"S\", \"M\", \"T\", \"W\", \"T\", \"F\", \"S\"};\n  endif\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  ## Guess input type.  We might be wrong.\n  if (ischar (date) || iscellstr (date) || columns (date) != 6)\n    v = datevec (date, p);\n  else\n    v = [];\n    if (columns (date) == 6)\n      ## Make sure that the input really is a datevec.\n      maxdatevec = [Inf, 12, 31, 23, 59, 60];\n      if (any (max (date, 1) > maxdatevec)\n          || any (date(:,1:5) != floor (date(:,1:5))))\n        v = datevec (date, p);\n      endif\n    endif\n    if (isempty (v))\n      v = date;\n    endif\n  endif\n\n  ## Round fractional seconds >= 0.9995 s to next full second.\n  idx = v(:,6) - fix (v(:,6)) >= 0.9995;\n  if (any (idx))\n    v(idx,6) = fix (v(idx,6)) + 1;\n    v(idx,:) = datevec (datenum (v(idx,:)));\n  endif\n\n  ## Automatic format selection\n  if (isempty (f))\n    if (v(:,4:6) == 0)\n      f = 1;\n    elseif (v(:,1:3) == [-1, 12, 31])\n      f = 16;\n    else\n      f = 0;\n    endif\n  endif\n\n  retval = \"\";\n  for i = 1 : rows (v)\n\n    if (isnumeric (f))\n      df = dateform{f + 1};\n    else\n      df = f;\n    endif\n\n    df_orig = df;\n    df = strrep (df, \"AM\", \"%p\");\n    df = strrep (df, \"PM\", \"%p\");\n    if (strcmp (df, df_orig))\n      ## PM not set.\n      df = strrep (df, \"HH\", \"%H\");\n    else\n      hr = mod (v(i,4), 12);\n      if (hr == 0)\n        hr = 12;\n      endif\n      df = strrep (df, \"HH\", sprintf (\"%2d\", hr));\n    endif\n\n    df = regexprep (df, \"[Yy][Yy][Yy][Yy]\", \"%Y\");\n\n    df = regexprep (df, \"[Yy][Yy]\", \"%y\");\n\n    df = regexprep (df, \"[Dd][Dd][Dd][Dd]\", \"%A\");\n\n    df = regexprep (df, \"[Dd][Dd][Dd]\", \"%a\");\n\n    df = regexprep (df, \"[Dd][Dd]\", \"%d\");\n\n    wday = weekday (datenum (v(i,1), v(i,2), v(i,3)));\n    tmp = names_d{wday};\n    df = regexprep (df, \"([^%])[Dd]\", sprintf (\"$1%s\", tmp));\n    df = regexprep (df, \"^[Dd]\", sprintf (\"%s\", tmp));\n\n    df = strrep (df, \"mmmm\", \"%B\");\n\n    df = strrep (df, \"mmm\", \"%b\");\n\n    df = strrep (df, \"mm\", \"%m\");\n\n    tmp = names_m{v(i,2)};\n    pos = regexp (df, \"[^%]m\") + 1;\n    df(pos) = tmp;\n    df = regexprep (df, \"^m\", tmp);\n\n    df = strrep (df, \"MM\", \"%M\");\n\n    df = regexprep (df, \"[Ss][Ss]\", \"%S\");\n\n    df = strrep (df, \"FFF\", sprintf (\"%03d\",\n                                     round (1000 * (v(i,6) - fix (v(i,6))))));\n\n    df = strrep (df, \"QQ\", sprintf (\"Q%d\", fix ((v(i,2) + 2) / 3)));\n\n    vi = v(i,:);\n    tm.year = vi(1) - 1900;\n    tm.mon = vi(2) - 1;\n    tm.mday = vi(3);\n    tm.hour = vi(4);\n    tm.min = vi(5);\n    sec = vi(6);\n    tm.sec = fix (sec);\n    tm.usec = fix ((sec - tm.sec) * 1e6);\n    tm.wday = wday - 1;\n    ## FIXME: Do we need YDAY and DST?  How should they be computed?\n    ## We don't want to use \"localtime (mktime (tm))\" because that\n    ## doesn't correctly handle dates before 1970-01-01 on some systems.\n    ## tm.yday = ?;\n    ## tm.isdst = ?;\n\n    str = strftime (df, tm);\n\n    retval = [retval; str];\n\n  endfor\n\nendfunction\n\n\n%!demo\n%! ## Current date and time in default format\n%! datestr (now ())\n\n%!demo\n%! ## Current date (integer portion of datenum)\n%! datestr (fix (now ()))\n\n%!demo\n%! ## Current time (fractional portion of datenum)\n%! datestr (rem (now (), 1))\n\n%!shared testtime\n%! testtime = [2005.0000, 12.0000, 18.0000, 2.0000, 33.0000, 17.3822];\n%!assert (datestr (testtime,0), \"18-Dec-2005 02:33:17\")\n%!assert (datestr (testtime,1), \"18-Dec-2005\")\n%!assert (datestr (testtime,2), \"12/18/05\")\n%!assert (datestr (testtime,3), \"Dec\")\n%!assert (datestr (testtime,4), \"D\")\n%!assert (datestr (testtime,5), \"12\")\n%!assert (datestr (testtime,6), \"12/18\")\n%!assert (datestr (testtime,7), \"18\")\n%!assert (datestr (testtime,8), \"Sun\")\n%!assert (datestr (testtime,9), \"S\")\n%!assert (datestr (testtime,10), \"2005\")\n%!assert (datestr (testtime,11), \"05\")\n%!assert (datestr (testtime,12), \"Dec05\")\n%!assert (datestr (testtime,13), \"02:33:17\")\n## Mac OS X interprets %p parameter to strftime as lowercase am/pm indicator.\n## Accommodate this, although no other UNIX-based OS does this.\n%!test\n%! obs = upper (datestr (testtime,14));\n%! assert (obs, \" 2:33:17 AM\");\n%!assert (datestr (testtime,15), \"02:33\")\n%!test\n%! obs = upper (datestr (testtime,16));\n%! assert (obs, \" 2:33 AM\");\n%!test <*48071>\n%! testtime2 = testtime;\n%! testtime2(4) = 15;\n%! obs = upper (datestr (testtime2,16));\n%! assert (obs, \" 3:33 PM\");\n%!assert (datestr (testtime,17), \"Q4-05\")\n%!assert (datestr (testtime,18), \"Q4\")\n%!assert (datestr (testtime,19), \"18/12\")\n%!assert (datestr (testtime,20), \"18/12/05\")\n%!assert (datestr (testtime,21), \"Dec.18,2005 02:33:17\")\n%!assert (datestr (testtime,22), \"Dec.18,2005\")\n%!assert (datestr (testtime,23), \"12/18/2005\")\n%!assert (datestr (testtime,24), \"18/12/2005\")\n%!assert (datestr (testtime,25), \"05/12/18\")\n%!assert (datestr (testtime,26), \"2005/12/18\")\n%!assert (datestr (testtime,27), \"Q4-2005\")\n%!assert (datestr (testtime,28), \"Dec2005\")\n%!assert (datestr (testtime,29), \"2005-12-18\")\n%!assert (datestr (testtime,30), \"20051218T023317\")\n%!assert (datestr (testtime,31), \"2005-12-18 02:33:17\")\n%!assert (datestr (testtime+[0 0 3 0 0 0], \"dddd\"), \"Wednesday\")\n## Test possible bug where input is a vector of datenums that is exactly 6 wide\n%!assert (datestr ([1944, 6, 6, 6, 30, 0], 0), \"06-Jun-1944 06:30:00\")\n## Test fractional millisecond time extension\n%!assert (datestr (testtime, \"HH:MM:SS:FFF\"), \"02:33:17:382\")\n## Test automatic format detection over vectors\n%!assert (datestr ([2017 03 16 0 0 0; 2017 03 16 0 0 1]),\n%!        char (\"16-Mar-2017 00:00:00\", \"16-Mar-2017 00:00:01\"))\n## Test for correct millisecond rounding\n%!assert (datestr (datenum (\"1:00\") - datenum (\"0:55\"), \"HH:MM:SS.FFF\"),\n%!                 \"00:05:00.000\")\n\n## Test input validation\n%!error <Invalid call> datestr ()\n"
  },
  {
    "path": "scripts/time/datevec.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{v} =} datevec (@var{date})\n## @deftypefnx {} {@var{v} =} datevec (@var{date}, @var{f})\n## @deftypefnx {} {@var{v} =} datevec (@var{date}, @var{p})\n## @deftypefnx {} {@var{v} =} datevec (@var{date}, @var{f}, @var{p})\n## @deftypefnx {} {[@var{y}, @var{m}, @var{d}, @var{h}, @var{mi}, @var{s}] =} datevec (@dots{})\n## Convert a serial date number (@pxref{XREFdatenum,,@code{datenum}}) or date\n## string (@pxref{XREFdatestr,,@code{datestr}}) into a date vector.\n##\n## A date vector is a row vector with six members, representing the year,\n## month, day, hour, minute, and seconds respectively.\n##\n## Date number inputs can be either a scalar or nonscalar array.  Date string\n## inputs can be either a single date string, a two-dimensional character\n## array of dates with each row being a date string, or a cell string array of\n## any dimension with each cell element containing a single date string.\n##\n## @var{v} is a two-dimensional array of date vectors, one date vector per\n## row.  For array inputs, ordering of @var{v} is based on column major order\n## of dates in @var{data}.\n##\n## @var{f} is the format string used to interpret date strings\n## (@pxref{XREFdatestr,,@code{datestr}}).  If @var{date} is a string or a cell\n## array of strings, but no format is specified, heuristics are used to guess\n## the input format.  These heuristics could lead to matches that differ from\n## the result a user might expect.  Additionally, this involves a relatively\n## slow search through various formats.  It is always preferable to specify\n## the format string @var{f} if it is known.  Formats which do not specify a\n## particular time component will have the value set to zero.  Formats which\n## do not specify a particular date component will default that component to\n## January 1st of the current year.  Trailing characters are ignored for the\n## purpose of calculating the date vector, even if the characters contain\n## additional time/date information.\n##\n## @var{p} is the year at the start of the century to which two-digit years\n## will be referenced.  If not specified, it defaults to the current year\n## minus 50.\n## @seealso{datenum, datestr, clock, now, date}\n## @end deftypefn\n\n## Algorithm: Peter Baum (http://vsg.cape.com/~pbaum/date/date0.htm)\n\n## The function __date_str2vec__ is based on datesplit by Bill Denney.\n\nfunction [y, m, d, h, mi, s] = datevec (date, f = [], p = [])\n\n  persistent std_formats nfmt;\n\n  if (isempty (std_formats))\n    std_formats = cell ();\n    nfmt = 0;\n    ## These formats are specified by Matlab documentation to be parsed\n    ## The '# XX' refers to the datestr numerical format code\n    std_formats{++nfmt} = \"dd-mmm-yyyy HH:MM:SS\";   # 0\n    std_formats{++nfmt} = \"dd-mmm-yyyy\";            # 1\n    std_formats{++nfmt} = \"mm/dd/yy\";               # 2\n    std_formats{++nfmt} = \"mm/dd\";                  # 6\n    std_formats{++nfmt} = \"HH:MM:SS\";               # 13\n    std_formats{++nfmt} = \"HH:MM:SS PM\";            # 14\n    std_formats{++nfmt} = \"HH:MM\";                  # 15\n    std_formats{++nfmt} = \"HH:MM PM\";               # 16\n    std_formats{++nfmt} = \"mm/dd/yyyy\";             # 23\n\n    ## These formats are undocumented but parsed by Matlab\n    std_formats{++nfmt} = \"mmmyy\";                  # 12\n    std_formats{++nfmt} = \"mmm.dd,yyyy HH:MM:SS\";   # 21\n    std_formats{++nfmt} = \"mmm.dd,yyyy\";            # 22\n    std_formats{++nfmt} = \"yyyy/mm/dd\";             # 26\n    std_formats{++nfmt} = \"yyyy-mm-dd\";             # 29\n    std_formats{++nfmt} = \"yyyy-mm-dd HH:MM:SS\";    # 31\n\n    ## These are other formats that Octave tries\n    std_formats{++nfmt} = \"mmm-dd-yyyy HH:MM:SS\";\n    std_formats{++nfmt} = \"mmm-dd-yyyy\";\n    std_formats{++nfmt} = \"dd mmm yyyy HH:MM:SS\";\n    std_formats{++nfmt} = \"dd mmm yyyy\";\n    std_formats{++nfmt} = \"mmm dd yyyy HH:MM:SS\";\n    std_formats{++nfmt} = \"mmm dd yyyy\";\n    std_formats{++nfmt} = \"dd.mmm.yyyy HH:MM:SS\";\n    std_formats{++nfmt} = \"dd.mmm.yyyy\";\n    std_formats{++nfmt} = \"mmm.dd.yyyy HH:MM:SS\";\n    std_formats{++nfmt} = \"mmm.dd.yyyy\";\n    std_formats{++nfmt} = \"mm/dd/yyyy HH:MM\";\n\n    ## These are ISO 8601 conform formats used in several SW\n    std_formats{++nfmt} = \"yyyy\";\n    std_formats{++nfmt} = \"yyyy-mm\";\n    std_formats{++nfmt} = \"yyyy-mm-ddTHH:MM:SSZ\";\n    std_formats{++nfmt} = \"yyyy-mm-ddTHH:MM:SS.FFFZ\";\n  endif\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (ischar (date))\n    date = cellstr (date);\n  endif\n\n  if (isnumeric (f))\n    p = f;\n    f = [];\n  endif\n\n  if (isempty (f))\n    f = -1;\n  endif\n\n  if (isempty (p))\n    p = (localtime (time ())).year + 1900 - 50;\n  endif\n\n  do_resize = false;\n\n  if (iscell (date))\n\n    nd = numel (date);\n\n    y = m = d = h = mi = s = zeros (nd, 1);\n\n    if (f == -1)\n      for k = 1:nd\n        found = false;\n        for l = 1:nfmt\n          [f, rY, ry, fy, fm, fd, fh, fmi, fs] = ...\n            __date_vfmt2sfmt__ (std_formats{l});\n          [found y(k) m(k) d(k) h(k) mi(k) s(k)] = ...\n            __date_str2vec__ (date{k}, p, f, rY, ry, fy, fm, fd, fh, fmi, ...\n                              fs, true);\n          if (found)\n            break;\n          endif\n        endfor\n        if (! found)\n          error (\"datevec: none of the standard formats match the DATE string\");\n        endif\n      endfor\n    else\n      ## Decipher the format string just once for speed.\n      [f, rY, ry, fy, fm, fd, fh, fmi, fs] = __date_vfmt2sfmt__ (f);\n      for k = 1:nd\n        [found y(k) m(k) d(k) h(k) mi(k) s(k)] = ...\n          __date_str2vec__ (date{k}, p, f, rY, ry, fy, fm, fd, fh, fmi, ...\n                            fs, false);\n        if (! found)\n          error (\"datevec: DATE not parsed correctly with given format\");\n        endif\n      endfor\n    endif\n\n  else   # datenum input\n\n    if (! iscolumn (date))\n      date_sz = size (date);\n      do_resize = true;\n    endif\n    date = date(:);\n\n    ## Move day 0 from midnight -0001-12-31 to midnight 0000-3-1\n    z = double (floor (date) - 60);\n    ## Calculate number of centuries; K1 = 0.25 is to avoid rounding problems.\n    a = floor ((z - 0.25) / 36524.25);\n    ## Days within century; K2 = 0.25 is to avoid rounding problems.\n    b = z - 0.25 + a - floor (a / 4);\n    ## Calculate the year (year starts on March 1).\n    y = floor (b / 365.25);\n    ## Calculate day in year.\n    c = fix (b - floor (365.25 * y)) + 1;\n    ## Calculate month in year.\n    m = fix ((5 * c + 456) / 153);\n    d = c - fix ((153 * m - 457) / 5);\n    ## Move to Jan 1 as start of year.\n    ++y(m > 12);\n    m(m > 12) -= 12;\n\n    ## Convert hour-minute-seconds.  Attempt to account for precision of\n    ## datenum format.\n\n    fracd = date - floor (date);\n    tmps = abs (eps*86400*date);\n    tmps(tmps == 0) = 1;\n    srnd = 2 .^ floor (- log2 (tmps));\n    s = round (86400 * fracd .* srnd) ./ srnd;\n    h = floor (s / 3600);\n    s -= 3600 * h;\n    mi = floor (s / 60);\n    s -= 60 * mi;\n\n  endif\n\n  if (nargout <= 1)\n    y = [y, m, d, h, mi, s];\n  elseif (do_resize)\n    y = reshape (y, date_sz);\n    m = reshape (m, date_sz);\n    d = reshape (d, date_sz);\n    h = reshape (h, date_sz);\n    mi = reshape (mi, date_sz);\n    s = reshape (s, date_sz);\n  endif\n\nendfunction\n\nfunction [f, rY, ry, fy, fm, fd, fh, fmi, fs] = __date_vfmt2sfmt__ (f)\n\n  original_f = f;   # Store for error messages.\n\n  if (any (strchr (f, \"hsfYD\", 1)))\n    warning (\"Octave:datevec:date-format-spec\", ...\n             [\"datevec: Format specifiers for dates should be lowercase,\", ...\n              \" format specifiers for time should be uppercase. \", ...\n              \" Possible issue with 'm' (month) and 'M' (minutes)?\"]);\n  endif\n\n  ## Play safe with percent signs.\n  f = strrep (f, \"%\", \"%%\");\n\n  if (! isempty (strfind (f, \"PM\")) || ! isempty (strfind (f, \"AM\")))\n    ampm = true;\n  else\n    ampm = false;\n  endif\n\n  ## Date part.\n  f = regexprep (f, '[Yy][Yy][Yy][Yy]', \"%Y\");\n  f = regexprep (f, '[Yy][Yy]', \"%y\");\n  f = strrep (f, \"mmmm\", \"%B\");\n  f = strrep (f, \"mmm\", \"%b\");\n  f = strrep (f, \"mm\", \"%m\");\n  f = regexprep (f, '[Dd][Dd][Dd][Dd]', \"%A\");\n  f = regexprep (f, '[Dd][Dd][Dd]', \"%a\");\n  f = regexprep (f, '[Dd][Dd]', \"%d\");\n\n  ## Time part.\n  if (ampm)\n    f = strrep (f, \"HH\", \"%I\");\n    f = strrep (f, \"PM\", \"%p\");\n    f = strrep (f, \"AM\", \"%p\");\n  else\n    f = strrep (f, \"HH\", \"%H\");\n  endif\n  f = strrep (f, \"MM\", \"%M\");\n  f = regexprep (f, '[Ss][Ss]', \"%S\");\n\n  ## Check for conflicting or repeated fields.\n  ## Only warn, not error, if we may be confused by an original '%'s.\n  if (index (original_f, \"%\"))\n    err_or_warn = @warning;\n  else\n    err_or_warn = @error;\n  endif\n\n  if (numel (strfind (f, \"%Y\")) + numel (strfind (f, \"%y\")) > 1)\n    err_or_warn (\"datevec: multiple year specifiers in %s\", original_f);\n  elseif (numel (strfind (f, \"%m\")) + numel (strfind (f, \"%b\"))\n          + numel (strfind (f, \"%B\")) > 1)\n    err_or_warn (\"datevec: multiple month specifiers in %s\", original_f);\n  elseif (numel (strfind (f, \"%d\")) > 1)\n    err_or_warn (\"datevec: multiple day specifiers in %s\", original_f);\n  elseif (numel (strfind (f, \"%a\"))+ numel (strfind (f, \"%A\")) > 1)\n    err_or_warn (\"datevec: multiple day of week specifiers in %s\", original_f);\n  elseif (numel (strfind (f, \"%H\")) + numel (strfind (f, \"%I\")) > 1)\n    err_or_warn (\"datevec: multiple hour specifiers in %s\", original_f);\n  elseif (numel (strfind (f, \"%M\")) > 1)\n    err_or_warn (\"datevec: multiple minute specifiers in %s\", original_f);\n  elseif (numel (strfind (f, \"%S\")) > 1)\n    err_or_warn (\"datevec: multiple second specifiers in %s\", original_f);\n  endif\n\n  rY = rindex (f, \"%Y\");\n  ry = rindex (f, \"%y\");\n\n  ## Check whether we need to give default values.\n  ## Possible error when string contains \"%%\".\n  fy = rY || ry;\n  fm = index (f, \"%m\") || index (f, \"%b\") || index (f, \"%B\");\n  fd = index (f, \"%d\") || index (f, \"%a\") || index (f, \"%A\");\n  fh = index (f, \"%H\") || index (f, \"%I\");\n  fmi = index (f, \"%M\");\n  fs = index (f, \"%S\");\n\nendfunction\n\nfunction [found, y, m, d, h, mi, s] = __date_str2vec__ (ds, p, f, rY, ry, fy, fm, fd, fh, fmi, fs, exact_match)\n\n  ## Local time zone is irrelevant, and potentially dangerous, when using\n  ## strptime to simply convert a string into a broken down struct tm.\n  ## Set and restore TZ so time is parsed exactly as-is.  See bug #36954.\n  TZ_orig = getenv (\"TZ\");\n  unwind_protect\n    setenv (\"TZ\", \"UTC0\");\n\n    idx = strfind (f, \"FFF\");\n    if (! isempty (idx))\n      ## Kludge to handle FFF millisecond format since strptime does not.\n\n      ## Find location of FFF in ds.\n      ## Might not match idx because of things like yyyy -> %y.\n      [~, nc] = strptime (ds, f(1:idx-1));\n\n      if (! isempty (nc) && nc != 0)\n        msec = ds(nc:min (nc+2,end));  # pull 3-digit fractional seconds.\n        msec_idx = find (! isdigit (msec), 1);\n\n        if (! isempty (msec_idx))  # non-digits in msec\n          msec = msec(1:msec_idx-1);\n          msec(end+1:3) = \"0\";  # pad msec with trailing zeros\n          ds = [ds(1:(nc-1)), msec, ds((nc-1)+msec_idx:end)];  # zero pad ds\n        elseif (numel (msec) < 3)  # less than three digits in msec\n          m_len = numel (msec);\n          msec(end+1:3) = \"0\";  # pad msec with trailing zeros\n          ds = [ds(1:(nc-1)), msec, ds(nc+m_len:end)];  # zero pad ds as well\n        endif\n\n        ## replace FFF with digits to guarantee match in strptime.\n        f(idx:idx+2) = msec;\n\n        if (nc > 0)\n          [tm, nc] = strptime (ds, f);\n          tm.usec = 1000 * str2double (msec);\n        endif\n      endif\n\n    else\n      [tm, nc] = strptime (ds, f);\n    endif\n  unwind_protect_cleanup\n    if (isempty (TZ_orig))\n      unsetenv (\"TZ\");\n    else\n      setenv (\"TZ\", TZ_orig);\n    endif\n  end_unwind_protect\n\n  ## Require an exact match unless the user supplied a format to use, then use\n  ## that format as long as it matches the start of the string and ignore any\n  ## trailing characters.\n  if ((! exact_match && nc > 0) || (nc == columns (ds) + 1))\n    found = true;\n    y = tm.year + 1900; m = tm.mon + 1; d = tm.mday;\n    h = tm.hour; mi = tm.min; s = tm.sec + tm.usec / 1e6;\n    if (rY < ry)\n      if (y > 1999)\n        y -= 2000;\n      else\n        y -= 1900;\n      endif\n      y += p - mod (p, 100);\n      if (y < p)\n        y += 100;\n      endif\n    endif\n    if (! fy && ! fm && ! fd)\n      tmp = localtime (time ());\n      ## default is January 1st of current year\n      y = tmp.year + 1900;\n      m = 1;\n      d = 1;\n    elseif (! fy && fm && fd)\n      tmp = localtime (time ());\n      y = tmp.year + 1900;\n    elseif (fy && fm && ! fd)\n      d = 1;\n    endif\n    if (! fh && ! fmi && ! fs)\n      h = mi = s = 0;\n    elseif (fh && fmi && ! fs)\n      s = 0;\n    endif\n  else\n    y = m = d = h = mi = s = 0;\n    found = false;\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Current date and time\n%! datevec (now ())\n\n%!shared yr\n%! yr = datevec (now)(1);  # Some tests could fail around midnight!\n## tests for standard formats: 0, 1, 2, 6, 13, 14, 15, 16, 23\n%!assert (datevec (\"07-Sep-2000 15:38:09\"), [2000,9,7,15,38,9])\n%!assert (datevec (\"07-Sep-2000\"), [2000,9,7,0,0,0])\n%!assert (datevec (\"09/07/00\"), [2000,9,7,0,0,0])\n%!assert (datevec (\"09/13\"), [yr,9,13,0,0,0])\n%!assert (datevec (\"15:38:09\"), [yr,1,1,15,38,9])\n%!assert (datevec (\"3:38:09 PM\"), [yr,1,1,15,38,9])\n%!assert (datevec (\"15:38\"), [yr,1,1,15,38,0])\n%!assert (datevec (\"03:38 PM\"), [yr,1,1,15,38,0])\n%!assert (datevec (\"03/13/1962\"), [1962,3,13,0,0,0])\n\n## Test millisecond format FFF\n%!assert (datevec (\"15:38:21.2\", \"HH:MM:SS.FFF\"), [yr,1,1,15,38,21.2])\n%!assert (datevec (\"15:38:21.25\", \"HH:MM:SS.FFF\"), [yr,1,1,15,38,21.25])\n%!assert (datevec (\"15:38:21.251\", \"HH:MM:SS.FFF\"), [yr,1,1,15,38,21.251])\n\n## Test millisecond format FFF with AM/PM, and 1,2, or 3 FFF digits\n%!assert (datevec (\"06/01/2015 3:07:12.102 PM\", \"mm/dd/yyyy HH:MM:SS.FFF PM\"),\n%!        [2015,6,1,15,7,12.102])\n%!assert (datevec (\"06/01/2015 11:07:12.102 PM\", \"mm/dd/yyyy HH:MM:SS.FFF PM\"),\n%!        [2015,6,1,23,7,12.102])\n%!assert (datevec (\"06/01/2015 3:07:12.102 AM\", \"mm/dd/yyyy HH:MM:SS.FFF PM\"),\n%!        [2015,6,1,3,7,12.102])\n%!assert (datevec (\"06/01/2015 11:07:12.102 AM\", \"mm/dd/yyyy HH:MM:SS.FFF PM\"),\n%!        [2015,6,1,11,7,12.102])\n%!assert (datevec (\"06/01/2015 3:07:12.1 PM\", \"mm/dd/yyyy HH:MM:SS.FFF PM\"),\n%!        [2015,6,1,15,7,12.1])\n%!assert (datevec (\"06/01/2015 3:07:12.12 AM\", \"mm/dd/yyyy HH:MM:SS.FFF PM\"),\n%!        [2015,6,1,3,7,12.12])\n%!assert (datevec (\"06/01/2015 3:07:12.12 PM\", \"mm/dd/yyyy HH:MM:SS.FFF PM\"),\n%!        [2015,6,1,15,7,12.12])\n\n## Test ISO 8601 conform formats\n%!assert (datevec (\"1998\"), [1998, 1, 0, 0, 0, 0])\n%!assert (datevec (\"1998-07\"), [1998, 7, 1, 0, 0, 0])\n%!assert (datevec (\"1998-07-19T15:03:47Z\"), [1998, 7, 19, 15, 3, 47])\n%!assert (datevec (\"1998-07-19T15:03:47.219Z\"), [1998, 7, 19, 15, 3, 47.219])\n\n## Test structure of return value\n%!test <*42334>\n%! [~, ~, d] = datevec ([1 2; 3 4]);\n%! assert (d, [1 2; 3 4]);\n\n## Other tests\n%!assert (datenum (datevec ([-1e4:1e4])), [-1e4:1e4]')\n%!test\n%! t = linspace (-2e5, 2e5, 10993);\n%! assert (all (abs (datenum (datevec (t)) - t') < 1e-5));\n%!assert (double (datevec (int64 (datenum ([2014 6 1])))),\n%!        datevec (datenum ([2014 6 1])))\n%!assert (double (datevec (int64 (datenum ([2014 6 18])))),\n%!        datevec (datenum ([2014 6 18])))\n\n## Test parsing of date strings that fall within daylight saving transition\n%!testif ; isunix () <*36954>\n%! zones = { \"UTC0\"                                 ...\n%!           \"EST+5EDT,M3.2.0/2,M11.1.0/2\"          ... America/New_York\n%!           \"CET-1CEST,M3.5.0/2,M10.5.0/2\"         ... Europe/Berlin\n%!           \"CLT+4CLST,M8.2.0/0,M5.2.0/0\"          ... America/Santiago\n%!           \"LHST-10:30LHDT-11,M10.1.0/2,M4.1.0/2\" ... Australia/Lord_Howe\n%!           \":America/Caracas\"                     ...\n%!         };\n%! TZ_orig = getenv (\"TZ\");\n%! unwind_protect\n%!   for i = 1:numel (zones)\n%!     setenv (\"TZ\", zones{i});\n%!     ## These specific times were chosen to test conversion during the loss\n%!     ## of some amount of local time at the start of daylight saving time in\n%!     ## each of the zones listed above.  We test all in each time zone to be\n%!     ## exhaustive, even though each is problematic for only one of the zones.\n%!     assert (datevec (\"2017-03-12 02:15:00\"), [2017  3 12 2 15 0]);\n%!     assert (datevec (\"2017-03-26 02:15:00\"), [2017  3 26 2 15 0]);\n%!     assert (datevec (\"2017-08-13 00:15:00\"), [2017  8 13 0 15 0]);\n%!     assert (datevec (\"2017-10-01 02:15:00\"), [2017 10  1 2 15 0]);\n%!     ## This tests a one-time loss of 30 minutes in Venezuela's local time\n%!     assert (datevec (\"2016-05-01 02:40:00\"), [2016  5  1 2 40 0]);\n%!   endfor\n%! unwind_protect_cleanup\n%!   if (isempty (TZ_orig))\n%!     unsetenv (\"TZ\");\n%!   else\n%!     setenv (\"TZ\", TZ_orig);\n%!   endif\n%! end_unwind_protect\n\n## Test matching string and ignoring trailing characters\n%!test <*42241>\n%! fail (\"datevec ('2013-08-15 09:00:35/xyzpdq')\");\n%! assert (datevec (\"15-Aug-2013 09:00:35.123\", \"dd-mmm-yyyy HH:MM:SS\"), ...\n%!              [2013, 8, 15, 9, 0, 35]);\n%! assert (datevec (\"2013-08-15 09:00:35/xyzpdq\", \"yyyy-mm-dd HH:MM:SS\"), ...\n%!              [2013, 8, 15, 9, 0, 35]);\n\n## Test all other standard formats specified in function with/without trailing\n## characters with format specified.\n\n## 0 dd-mm-yyyy HH:MM:SS\n%!assert <*42241> (datevec (\"15-aug-2013 09:00:35\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"15-aug-2013 09:00:35\", \"dd-mmm-yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"15-aug-2013 09:00:35ABC\", \"dd-mmm-yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n\n## 1 dd-mmm-yyyy\n%!assert <*42241> (datevec (\"15-aug-2013\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15-aug-2013\", \"dd-mmm-yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15-aug-2013 09:00:35\", \"dd-mmm-yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15-aug-2013ABC\", \"dd-mmm-yyyy\"), [2013, 8, 15, 0, 0, 0])\n\n## 2 mm/dd/yy\n%!assert <*42241> (datevec (\"08/15/13\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15/13\", \"mm/dd/yy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15/13 09:00:35\", \"mm/dd/yy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15/13ABC\", \"mm/dd/yy\"), [2013, 8, 15, 0, 0, 0])\n\n## 3 mmm\n%!assert <*42241> (datevec (\"Aug\", \"mmm\"), [1900, 8, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug 15\", \"mmm\"), [1900, 8, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"AugABC\", \"mmm\"), [1900, 8, 0, 0, 0, 0])\n\n## 4 m datestr std format 4 -  datevec(\"A\", \"m\") does not resolve\n\n## 5 mm\n%!assert <*42241> (datevec (\"08\"), [8, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"08\", \"mm\"), [1900, 8, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15/2013\", \"mm\"), [1900, 8, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"08ABC\", \"mm\"), [1900, 8, 0, 0, 0, 0])\n\n## 6 mm/dd\n%!assert <*42241> (datevec (\"08/15\"), [yr, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15\", \"mm/dd\"), [yr, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15/13\", \"mm/dd\"), [yr, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15ABC\", \"mm/dd\"), [yr, 8, 15, 0, 0, 0])\n\n## 7 dd\n%!assert <*42241> (datevec (\"15\"), [15, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"15\", \"dd\"), [1900, 1, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15-Aug-2013\", \"dd\"), [1900, 1, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15ABC\", \"dd\"), [1900, 1, 15, 0, 0, 0])\n\n## 8 ddd\n%!assert <*42241> (datevec (\"Fri\", \"ddd\"), [1900, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"Fri, Aug 15 2013\", \"ddd\"), [1900, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"FriABC\", \"ddd\"), [1900, 1, 0, 0, 0, 0])\n\n## 9 d datestr std format 9 -  datevec(\"F\", \"d\") does not resolve\n\n## 10 yyyy\n%!assert <*42241> (datevec (\"2013\"), [2013, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013\", \"yyyy\"), [2013, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013/08/15\", \"yyyy\"), [2013, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013ABC\", \"yyyy\"), [2013, 1, 0, 0, 0, 0])\n\n## 11 yy\n%!assert <*42241> (datevec (\"13\"), [13, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"13\", \"yy\"), [2013, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"13/08/15\", \"yy\"), [2013, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"13ABC\", \"yy\"), [2013, 1, 0, 0, 0, 0])\n\n## 12 mmmyy\n%!assert <*42241> (datevec (\"AUG13\"), [2013, 8, 1, 0, 0, 0])\n%!assert <*42241> (datevec (\"AUG13\", \"mmmyy\"), [2013, 8, 1, 0, 0, 0])\n%!assert <*42241> (datevec (\"AUG2013\", \"mmmyy\"), [2020, 8, 1, 0, 0, 0])\n%!assert <*42241> (datevec (\"AUG13ABC\", \"mmmyy\"), [2013, 8, 1, 0, 0, 0])\n\n## 13 HH:MM:SS\n%!assert <*42241> (datevec (\"09:00:35\"), [yr, 1, 1, 9, 0, 35])\n%!assert <*42241> (datevec (\"09:00:35\", \"HH:MM:SS\"), [yr, 1, 1, 9, 0, 35])\n%!assert <*42241> (datevec (\"09:00:35 AM\", \"HH:MM:SS\"), [yr, 1, 1, 9, 0, 35])\n%!assert <*42241> (datevec (\"09:00:35ABC\", \"HH:MM:SS\"), [yr, 1, 1, 9, 0, 35])\n\n## 14 HH:MM:SS PM\n%!assert <*42241> (datevec (\"09:00:35 AM\"), [yr, 1, 1, 9, 0, 35])\n%!assert <*42241> (datevec (\"09:00:35 AM\", \"HH:MM:SS PM\"), [yr, 1, 1, 9, 0, 35])\n%!assert <*42241> (datevec (\"09:00:35 am\", \"HH:MM:SS PM\"), [yr, 1, 1, 9, 0, 35])\n%!assert <*42241> (datevec (\"09:00:35 PM\", \"HH:MM:SS PM\"), [yr, 1, 1, 21, 0, 35])\n%!assert <*42241> (datevec (\"09:00:35 AMABC\", \"HH:MM:SS PM\"), [yr, 1, 1, 9, 0, 35])\n\n## 15 HH:MM\n%!assert <*42241> (datevec (\"09:00\"), [yr, 1, 1, 9, 0, 0])\n%!assert <*42241> (datevec (\"09:00\", \"HH:MM\"), [yr, 1, 1, 9, 0, 0])\n%!assert <*42241> (datevec (\"09:00:35\", \"HH:MM\"), [yr, 1, 1, 9, 0, 0])\n%!assert <*42241> (datevec (\"09:00ABC\", \"HH:MM\"), [yr, 1, 1, 9, 0, 0])\n\n## 16 HH:MM PM\n%!assert <*42241> (datevec (\"09:00 AM\"), [yr, 1, 1, 9, 0, 0])\n%!assert <*42241> (datevec (\"09:00 AM\", \"HH:MM PM\"), [yr, 1, 1, 9, 0, 0])\n%!assert <*42241> (datevec (\"09:00 PM\", \"HH:MM PM\"), [yr, 1, 1, 21, 0, 0])\n%!assert <*42241> (datevec (\"09:00 AMABC\", \"HH:MM PM\"), [yr, 1, 1, 9, 0, 0])\n\n## 17 QQ-YY datestr std format 17 -  datevec(\"Q1-13\", \"QQ-YY\") does not resolve\n\n## 18 QQ datestr std format 18 -  datevec(\"Q1\", \"QQ\") does not resolve\n\n## 19 dd/mm\n%!assert <*42241> (datevec (\"15/08\", \"dd/mm\"), [yr, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15/08/2023\", \"dd/mm\"), [yr, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15/08ABC\", \"dd/mm\"), [yr, 8, 15, 0, 0, 0])\n\n## 20 dd/mm/yy\n%!assert <*42241> (datevec (\"15/08/13\"), [15, 8, 13, 0, 0, 0])\n%!assert <*42241> (datevec (\"15/08/13\", \"dd/mm/yy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15/08/13 09:00:35\", \"dd/mm/yy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15/08/13ABC\", \"dd/mm/yy\"), [2013, 8, 15, 0, 0, 0])\n\n## 21 mmm.dd,yyyy HH:MM:SS\n%!assert <*42241> (datevec (\"aug.15,2013 09:00:35\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"aug.15,2013 09:00:35\", \"mmm.dd,yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"aug.15,2013 09:00:35 PM\", \"mmm.dd,yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"aug.15,2013 09:00:35ABC\", \"mmm.dd,yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n\n## 22 mm.dd,yyyy\n%!assert <*42241> (datevec (\"aug.15,2013\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"aug.15,2013\", \"mmm.dd,yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"aug.15,2013 09:00:35\", \"mmm.dd,yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"aug.15,2013ABC\", \"mmm.dd,yyyy\"), [2013, 8, 15, 0, 0, 0])\n\n## 23 mm/dd/yyyy\n%!assert <*42241> (datevec (\"08/15/2013\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15/2013\", \"mm/dd/yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15/2013 09:00:35\", \"mm/dd/yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"08/15/2013ABC\", \"mm/dd/yyyy\"), [2013, 8, 15, 0, 0, 0])\n\n## 24 dd/mm/yyyy\n%!assert <*42241> (datevec (\"15/08/2013\", \"dd/mm/yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15/08/2013 09:00:35\", \"dd/mm/yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15/08/2013ABC\", \"dd/mm/yyyy\"), [2013, 8, 15, 0, 0, 0])\n\n## 25 yy/mm/dd\n%!assert <*42241> (datevec (\"13/08/15\"), [13, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"13/08/15\", \"yy/mm/dd\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"13/08/15 09:00:35\", \"yy/mm/dd\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"13/08/15ABC\", \"yy/mm/dd\"), [2013, 8, 15, 0, 0, 0])\n\n## 26 yyyy/mm/dd\n%!assert <*42241> (datevec (\"2013/08/15\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013/08/15\", \"yyyy/mm/dd\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013/08/15 09:00:35\", \"yyyy/mm/dd\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013/08/15ABC\", \"yyyy/mm/dd\"), [2013, 8, 15, 0, 0, 0])\n\n## 27 QQ-YYYY datestr std format 27 -  datevec(\"Q1-2013\", \"QQ-YYYY\") does not resolve\n\n## 28 mmmyyyy\n%!assert <*42241> (datevec (\"Aug2013\"), [13, 8, 20, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug2013\", \"mmmyyyy\"), [2013, 8, 1, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug2013 09:00:35\", \"mmmyyyy\"), [2013, 8, 1, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug2013ABC\", \"mmmyyyy\"), [2013, 8, 1, 0, 0, 0])\n\n## 29 yyyy-mm-dd\n%!assert <*42241> (datevec (\"2013-08-15\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013-08-15\", \"yyyy-mm-dd\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013-08-15 09:00:35\", \"yyyy-mm-dd\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013-08-15ABC\", \"yyyy-mm-dd\"), [2013, 8, 15, 0, 0, 0])\n\n## 30 yyyymmddTHHMMSS\n%!assert <*42241> (datevec (\"20130815T090035\", \"yyyymmddTHHMMSS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"20130815T090035\", \"yyyymmddTHHMMSS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"20130815T090035\", \"yyyymmddTHHMMSS\"), [2013, 8, 15, 9, 0, 35])\n\n## 31 yyyy-mm-dd HH:MM:SS\n%!assert <*42241> (datevec (\"2013-08-15 09:00:35\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"2013-08-15 09:00:35\", \"yyyy-mm-dd HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"2013-08-15 09:00:35 PM\", \"yyyy-mm-dd HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"2013-08-15 09:00:35ABC\", \"yyyy-mm-dd HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n\n## mmm-dd-yyyy HH:MM:SS\n%!assert <*42241> (datevec (\"Aug-15-2013 09:00:35\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"Aug-15-2013 09:00:35\", \"mmm-dd-yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"Aug-15-2013 09:00:35 PM\", \"mmm-dd-yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"Aug-15-2013 09:00:35ABC\", \"mmm-dd-yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n\n## mmm-dd-yyyy\n%!assert <*42241> (datevec (\"Aug-15-2013\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug-15-2013\", \"mmm-dd-yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug-15-2013 09:00:35\", \"mmm-dd-yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug-15-2013ABC\", \"mmm-dd-yyyy\"), [2013, 8, 15, 0, 0, 0])\n\n## dd mmm yyyy HH:MM:SS\n%!assert <*42241> (datevec (\"15 Aug 2013 09:00:35\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"15 Aug 2013 09:00:35\", \"dd mmm yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"15 Aug 2013 09:00:35 PM\", \"dd mmm yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"15 Aug 2013 09:00:35ABC\", \"dd mmm yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n\n## dd mmm yyyy\n%!assert <*42241> (datevec (\"15 Aug 2013\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15 Aug 2013\", \"dd mmm yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15 Aug 2013 09:00:35\", \"dd mmm yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15 Aug 2013ABC\", \"dd mmm yyyy\"), [2013, 8, 15, 0, 0, 0])\n\n## mmm dd yyyy HH:MM:SS\n%!assert <*42241> (datevec (\"Aug 15 2013 09:00:35\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"Aug 15 2013 09:00:35\", \"mmm dd yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"Aug 15 2013 09:00:35 PM\", \"mmm dd yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"Aug 15 2013 09:00:35ABC\", \"mmm dd yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n\n## mmm dd yyyy\n%!assert <*42241> (datevec (\"Aug 15 2013\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug 15 2013\", \"mmm dd yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug 15 2013 09:00:35\", \"mmm dd yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug 15 2013ABC\", \"mmm dd yyyy\"), [2013, 8, 15, 0, 0, 0])\n\n## dd.mmm.yyyy HH:MM:SS\n%!assert <*42241> (datevec (\"15.Aug.2013 09:00:35\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"15.Aug.2013 09:00:35\", \"dd.mmm.yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"15.Aug.2013 09:00:35 PM\", \"dd.mmm.yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"15.Aug.2013 09:00:35ABC\", \"dd.mmm.yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n\n## dd.mmm.yyyy\n%!assert <*42241> (datevec (\"15.Aug.2013\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15.Aug.2013\", \"dd.mmm.yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15.Aug.2013 09:00:35\", \"dd.mmm.yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"15.Aug.2013ABC\", \"dd.mmm.yyyy\"), [2013, 8, 15, 0, 0, 0])\n\n## mmm.dd.yyyy HH:MM:SS\n%!assert <*42241> (datevec (\"Aug.15.2013 09:00:35\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"Aug.15.2013 09:00:35\", \"mmm.dd.yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"Aug.15.2013 09:00:35 PM\", \"mmm.dd.yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"Aug.15.2013 09:00:35ABC\", \"mmm.dd.yyyy HH:MM:SS\"), [2013, 8, 15, 9, 0, 35])\n\n## mmm.dd.yyyy\n%!assert <*42241> (datevec (\"Aug.15.2013\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug.15.2013\", \"mmm.dd.yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug.15.2013 09:00:35\", \"mmm.dd.yyyy\"), [2013, 8, 15, 0, 0, 0])\n%!assert <*42241> (datevec (\"Aug.15.2013ABC\", \"mmm.dd.yyyy\"), [2013, 8, 15, 0, 0, 0])\n\n## mm/dd/yyyy HH:MM\n%!assert <*42241> (datevec (\"08/15/2013 09:00\"), [2013, 8, 15, 9, 0, 0])\n%!assert <*42241> (datevec (\"08/15/2013 09:00\", \"mm/dd/yyyy HH:MM\"), [2013, 8, 15, 9, 0, 0])\n%!assert <*42241> (datevec (\"08/15/2013 09:00:35\", \"mm/dd/yyyy HH:MM\"), [2013, 8, 15, 9, 0, 0])\n%!assert <*42241> (datevec (\"08/15/2013 09:00ABC\", \"mm/dd/yyyy HH:MM\"), [2013, 8, 15, 9, 0, 0])\n\n## yyyy\n%!assert <*42241> (datevec (\"2013\"), [2013, 1, 0, 0, 0, 0]) # Octave uses Jan 0 as origin\n%!assert <*42241> (datevec (\"2013\", \"yyyy\"), [2013, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013-08-15\", \"yyyy\"), [2013, 1, 0, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013ABC\", \"yyyy\"), [2013, 1, 0, 0, 0, 0])\n\n## yyyy-mm\n%!assert <*42241> (datevec (\"2013-08\"), [2013, 8, 1, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013-08\", \"yyyy-mm\"), [2013, 8, 1, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013-08-15\", \"yyyy-mm\"), [2013, 8, 1, 0, 0, 0])\n%!assert <*42241> (datevec (\"2013-08ABC\", \"yyyy-mm\"), [2013, 8, 1, 0, 0, 0])\n\n## yyyy-mm-ddTHH:MM:SSZ\n%!assert <*42241> (datevec (\"2013-08-15T09:00:35Z\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"2013-08-15T09:00:35Z\", \"yyyy-mm-ddTHH:MM:SSZ\"), [2013, 8, 15, 9, 0, 35])\n%!assert <*42241> (datevec (\"2013-08-15T09:00:35ZABC\", \"yyyy-mm-ddTHH:MM:SSZ\"), [2013, 8, 15, 9, 0, 35])\n\n## yyyy-mm-ddTHH:MM:SS.FFFZ\n%!assert <*42241> (datevec (\"2013-08-15T09:00:35.123Z\"), [2013, 8, 15, 9, 0, 35.123])\n%!assert <*42241> (datevec (\"2013-08-15T09:00:35.123Z\", \"yyyy-mm-ddTHH:MM:SS.FFFZ\"), [2013, 8, 15, 9, 0, 35.123])\n%!assert <*42241> (datevec (\"2013-08-15T09:00:35.123ZABC\", \"yyyy-mm-ddTHH:MM:SS.FFFZ\"), [2013, 8, 15, 9, 0, 35.123])\n\n\n## Test input validation\n%!error <Invalid call> datevec ()\n%!error <none of the standard formats match> datevec (\"foobar\")\n%!error <DATE not parsed correctly with given format> datevec (\"foobar\", \"%d\")\n%!error <multiple year specifiers> datevec (\"1/2/30\", \"mm/yy/yy\")\n%!error <multiple month specifiers> datevec (\"1/2/30\", \"mm/mm/yy\")\n%!error <multiple day specifiers> datevec (\"1/2/30\", \"mm/dd/dd\")\n%!error <multiple hour specifiers> datevec (\"15:38:21.251\", \"HH:HH:SS\")\n%!error <multiple minute specifiers> datevec (\"15:38:21.251\", \"MM:MM:SS\")\n%!error <multiple second specifiers> datevec (\"15:38:21.251\", \"HH:SS:SS\")\n%!fail (\"datevec ('2015-03-31 0:00','YYYY-mm-DD HH:MM')\", ...\n%!      \"warning\", \"Format specifiers for dates should be lowercase\");\n%!fail (\"datevec ('2015-03-31 hh:00','yyyy-mm-dd hh:MM')\", ...\n%!      \"warning\", \"format specifiers for time should be uppercase\");\n"
  },
  {
    "path": "scripts/time/eomday.m",
    "content": "########################################################################\n##\n## Copyright (C) 2004-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{e} =} eomday (@var{y}, @var{m})\n## Return the last day of the month @var{m} for the year @var{y}.\n## @seealso{weekday, datenum, datevec, is_leap_year, calendar}\n## @end deftypefn\n\nfunction e = eomday (y, m)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  eom = [31, 28, 31, 30 ,31, 30, 31, 31, 30, 31, 30, 31];\n  e = reshape (eom(m), size (m));\n  e += (m == 2) & (mod (y, 4) == 0 & (mod (y, 100) != 0 | mod (y, 400) == 0));\n\nendfunction\n\n\n%!demo\n%! ## Find leap years in the 20th century\n%! y = 1900:1999;\n%! e = eomday (y, repmat (2, [1, 100]));\n%! y(find (e == 29))\n\n%!assert (eomday ([-4:4],2), [29,28,28,28,29,28,28,28,29])\n%!assert (eomday ([-901,901],2), [28,28])\n%!assert (eomday ([-100,100],2), [28,28])\n%!assert (eomday ([-900,900],2), [28,28])\n%!assert (eomday ([-400,400],2), [29,29])\n%!assert (eomday ([-800,800],2), [29,29])\n%!assert (eomday (2001,1:12), [31,28,31,30,31,30,31,31,30,31,30,31])\n%!assert (eomday (1:3,1:3), [31,28,31])\n%!assert (eomday (1:2000,2)', datevec (datenum (1:2000,3,0))(:,3))\n%!assert ([1900:1999](find (eomday (1900:1999,2*ones(1,100))==29)),\n%!        [1904,1908,1912,1916,1920,1924,1928,1932,1936,1940,1944,1948,1952,1956,1960,1964,1968,1972,1976,1980,1984,1988,1992,1996])\n%!assert (eomday ([2004;2005], [2;2]), [29;28])\n\n## Test input validation\n%!error <Invalid call> eomday ()\n%!error <Invalid call> eomday (1)\n"
  },
  {
    "path": "scripts/time/etime.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {@var{secs} =} etime (@var{t2}, @var{t1})\n## Return the difference in seconds between two time values returned from\n## @code{clock} (@math{@var{t2} - @var{t1}}).\n##\n## For example:\n##\n## @example\n## @group\n## t0 = clock ();\n## # many computations later@dots{}\n## elapsed_time = etime (clock (), t0);\n## @end group\n## @end example\n##\n## @noindent\n## will set the variable @code{elapsed_time} to the number of seconds since the\n## variable @code{t0} was set.\n## @seealso{tic, toc, clock, cputime, addtodate}\n## @end deftypefn\n\nfunction secs = etime (t2, t1)\n\n  if (nargin != 2)\n    print_usage ();\n  endif\n\n  [~, s2] = datenum (t2);\n  [~, s1] = datenum (t1);\n\n  secs = s2 - s1;\n\nendfunction\n\n\n%!assert (etime ([1900,12,31,23,59,59], [1901,1,1,0,0,0]), -1)\n%!assert (etime ([1900,2,28,23,59,59], [1900,3,1,0,0,0]), -1)\n%!assert (etime ([2000,2,28,23,59,59], [2000,3,1,0,0,0]), -86401)\n%!assert (etime ([1996,2,28,23,59,59], [1996,3,1,0,0,0]), -86401)\n%!test\n%! t1 = [1900,12,31,23,59,59; 1900,2,28,23,59,59];\n%! t2 = [1901,1,1,0,0,0; 1900,3,1,0,0,0];\n%! assert (etime (t2, t1), [1;1]);\n\n%!test\n%! t1 = [1993, 8, 20, 4, 56, 1];\n%! t2 = [1993, 8, 21, 4, 56, 1];\n%! t3 = [1993, 8, 20, 5, 56, 1];\n%! t4 = [1993, 8, 20, 4, 57, 1];\n%! t5 = [1993, 8, 20, 4, 56, 14];\n%!\n%! assert (etime (t2, t1), 86400);\n%! assert (etime (t3, t1), 3600);\n%! assert (etime (t4, t1), 60);\n%! assert (etime (t5, t1), 13);\n\n## Test input validation\n%!error <Invalid call> etime ()\n%!error <Invalid call> etime (1)\n"
  },
  {
    "path": "scripts/time/is_leap_year.m",
    "content": "########################################################################\n##\n## Copyright (C) 1996-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{tf} =} is_leap_year ()\n## @deftypefnx {} {@var{tf} =} is_leap_year (@var{year})\n## Return true if @var{year} is a leap year and false otherwise.\n##\n## If no year is specified, @code{is_leap_year} uses the current year.\n##\n## For example:\n##\n## @example\n## @group\n## is_leap_year (2000)\n##    @xresult{} 1\n## @end group\n## @end example\n## @seealso{weekday, eomday, calendar}\n## @end deftypefn\n\nfunction tf = is_leap_year (year)\n\n  if (nargin == 0)\n    t = clock ();\n    year = t(1);\n  endif\n\n  tf = (rem (year, 4) == 0 & rem (year, 100) != 0) | (rem (year, 400) == 0);\n\nendfunction\n\n\n%!assert (is_leap_year (2000), true)\n%!assert (is_leap_year (1976), true)\n%!assert (is_leap_year (1000), false)\n%!assert (is_leap_year (1800), false)\n%!assert (is_leap_year (1600), true)\n"
  },
  {
    "path": "scripts/time/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/addtodate.m \\\n  %reldir%/asctime.m \\\n  %reldir%/calendar.m \\\n  %reldir%/clock.m \\\n  %reldir%/ctime.m \\\n  %reldir%/date.m \\\n  %reldir%/datenum.m \\\n  %reldir%/datestr.m \\\n  %reldir%/datevec.m \\\n  %reldir%/eomday.m \\\n  %reldir%/etime.m \\\n  %reldir%/is_leap_year.m \\\n  %reldir%/now.m \\\n  %reldir%/weekday.m\n\n%canon_reldir%dir = $(fcnfiledir)/time\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/time/now.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {t =} now ()\n## Return the current local date/time as a serial day number\n## (@pxref{XREFdatenum,,@code{datenum}}).\n##\n## The integral part, @code{floor (now)} corresponds to the number of days\n## between today and Jan 1, 0000.\n##\n## The fractional part, @code{rem (now, 1)} corresponds to the current time.\n## @seealso{clock, date, datenum}\n## @end deftypefn\n\nfunction t = now ()\n\n  t = datenum (clock ());\n\n  ## The following doesn't work (e.g., one hour off on 2005-10-04):\n  ##\n  ##   seconds since 1970-1-1 corrected by seconds from GMT to local time\n  ##   divided by 86400 sec/day plus day num for 1970-1-1\n  ##   t = (time - mktime(gmtime(0)))/86400 + 719529;\n  ##\n  ## mktime (gmtime (0)) does indeed return the offset from Greenwich to the\n  ## local time zone, but we need to account for daylight saving time\n  ## changing by an hour the offset from CUT for part of the year.\n\nendfunction\n\n\n%!assert (isnumeric (now ()))\n%!assert (now () > 0)\n%!assert (now () <= now ())\n"
  },
  {
    "path": "scripts/time/weekday.m",
    "content": "########################################################################\n##\n## Copyright (C) 2000-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {[@var{n}, @var{s}] =} weekday (@var{d})\n## @deftypefnx {} {[@var{n}, @var{s}] =} weekday (@var{d}, @var{format})\n## Return the day of the week as a number in @var{n} and as a string in\n## @var{s}.\n##\n## The days of the week are numbered 1--7 with the first day being Sunday.\n##\n## @var{d} is a serial date number or a date string.\n##\n## If the string @var{format} is not present or is equal to @qcode{\"short\"}\n## then @var{s} will contain the abbreviated name of the weekday.  If\n## @var{format} is @qcode{\"long\"} then @var{s} will contain the full name.\n##\n## Table of return values based on @var{format}:\n##\n## @multitable @columnfractions .06 .13 .16\n## @headitem @var{n} @tab @qcode{\"short\"} @tab @qcode{\"long\"}\n## @item 1 @tab Sun @tab Sunday\n## @item 2 @tab Mon @tab Monday\n## @item 3 @tab Tue @tab Tuesday\n## @item 4 @tab Wed @tab Wednesday\n## @item 5 @tab Thu @tab Thursday\n## @item 6 @tab Fri @tab Friday\n## @item 7 @tab Sat @tab Saturday\n## @end multitable\n##\n## @seealso{eomday, is_leap_year, calendar, datenum, datevec}\n## @end deftypefn\n\nfunction [d, s] = weekday (d, format = \"short\")\n\n  if (nargin < 1)\n    print_usage ();\n  endif\n\n  if (iscellstr (d) || isnumeric (d))\n    endsize = size (d);\n  elseif (ischar (d))\n    endsize = [rows(d), 1];\n  endif\n  if (ischar (d) || iscellstr (d))\n    ## Make sure the date is numeric\n    d = datenum (d);\n  endif\n  ## Find the offset from a known Sunday (2008-Jan-6), mod 7.\n  d = floor (reshape (mod (d - 733048, 7), endsize));\n  ## Make Saturdays a 7 and not a 0.\n  d(! d) = 7;\n\n  if (nargout > 1)\n    if (strcmpi (format, \"long\"))\n      names = {\"Sunday\" \"Monday\" \"Tuesday\" \"Wednesday\" \"Thursday\" ...\n               \"Friday\" \"Saturday\"};\n    else\n      names = {\"Sun\" \"Mon\" \"Tue\" \"Wed\" \"Thu\" \"Fri\" \"Sat\"};\n    endif\n    s = strvcat (names(d));\n  endif\n\nendfunction\n\n\n%!demo\n%! ## Current weekday\n%! [n, s] = weekday (now ())\n\n%!demo\n%! ## Weekday from datenum input\n%! [n, s] = weekday (728647)\n\n%!demo\n%! ## Weekday of new millennium from datestr input\n%! [n, s] = weekday (\"1-Jan-2000\")\n\n%!assert (weekday (728647), 2)\n## Test vector inputs for both directions\n%!assert (weekday ([728647 728648]), [2 3])\n%!assert (weekday ([728647;728648]), [2;3])\n## Test a full week before our reference day\n%!assert (weekday (\"19-Dec-1994\"), 2)\n%!assert (weekday (\"20-Dec-1994\"), 3)\n%!assert (weekday (\"21-Dec-1994\"), 4)\n%!assert (weekday (\"22-Dec-1994\"), 5)\n%!assert (weekday (\"23-Dec-1994\"), 6)\n%!assert (weekday (\"24-Dec-1994\"), 7)\n%!assert (weekday (\"25-Dec-1994\"), 1)\n## Test our reference day\n%!assert (weekday (\"6-Jan-2008\"), 1)\n## Test a full week after our reference day\n%!assert (weekday (\"1-Feb-2008\"), 6)\n%!assert (weekday (\"2-Feb-2008\"), 7)\n%!assert (weekday (\"3-Feb-2008\"), 1)\n%!assert (weekday (\"4-Feb-2008\"), 2)\n%!assert (weekday (\"5-Feb-2008\"), 3)\n%!assert (weekday (\"6-Feb-2008\"), 4)\n%!assert (weekday (\"7-Feb-2008\"), 5)\n## Test fractional dates\n%!assert (weekday (728647.1), 2)\n## Test \"long\" option\n%!test\n%! [n, s] = weekday (\"25-Dec-1994\", \"long\");\n%! assert (n, 1);\n%! assert (s, \"Sunday\");\n"
  },
  {
    "path": "scripts/web/.oct-config",
    "content": "encoding=utf-8\n"
  },
  {
    "path": "scripts/web/module.mk",
    "content": "FCN_FILE_DIRS += %reldir%\n\n%canon_reldir%_FCN_FILES = \\\n  %reldir%/.oct-config \\\n  %reldir%/web.m \\\n  %reldir%/weboptions.m \\\n  %reldir%/webread.m \\\n  %reldir%/webwrite.m\n\n%canon_reldir%dir = $(fcnfiledir)/web\n\n%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)\n\nFCN_FILES += $(%canon_reldir%_FCN_FILES)\n\nPKG_ADD_FILES += %reldir%/PKG_ADD\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n"
  },
  {
    "path": "scripts/web/web.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{status} =} web ()\n## @deftypefnx {} {@var{status} =} web (@var{url})\n## @deftypefnx {} {@var{status} =} web (@var{url}, @var{option})\n## @deftypefnx {} {@var{status} =} web (@var{url}, @var{option_1}, @dots{}, @var{option_N})\n## @deftypefnx {} {[@var{status}, @var{h}, @var{url}] =} web (@dots{})\n##\n## Open @var{url} in the default system web browser.\n##\n## With no arguments given, the address @url{https://www.octave.org} is\n## opened.\n##\n## Additional options can be passed for @sc{matlab} compatibility, but are\n## ignored.\n##\n## @itemize @bullet\n## @item\n## @samp{-browser} Open @var{url} in the default system browser.\n##\n## @item\n## @samp{-new} No effect on the system browser.\n##\n## @item\n## @samp{-noaddressbox} No effect on the system browser.\n##\n## @item\n## @samp{-notoolbar} No effect on the system browser.\n##\n## @end itemize\n##\n## The return value @var{status} has one of the values:\n##\n## @itemize @bullet\n## @item\n## @samp{0} Found and opened system browser successfully.\n##\n## @item\n## @samp{1} Cannot find the system browser.\n##\n## @item\n## @samp{2} System browser found, but an error occurred.\n##\n## @end itemize\n##\n## The return values @var{handle} and @var{url} are currently unimplemented\n## but given for compatibility.\n##\n## @seealso{weboptions, webread, webwrite, urlread, urlwrite}\n## @end deftypefn\n\nfunction [status, h, url] = web (url, varargin)\n\n  if (nargin == 0)\n    url = \"https://www.octave.org\";\n  endif\n\n  if (! (ischar (url) && isrow (url)))\n    error (\"web: URL must be a string\");\n  endif\n\n  for i = 1:numel (varargin)\n    validatestring (varargin{i},\n                    {\"-browser\", \"-new\", \"-noaddressbox\", \"-notoolbar\"});\n  endfor\n\n  ## Store text after \"text://\" to a temporary file and open it.\n  if (strncmpi (url, \"text://\", 7))\n    fname = [tempname() \".html\"];\n    fid = fopen (fname, \"w\");\n    if (fid < 0)\n      error (\"web: could not open temporary file for text:// content\");\n    endif\n    fprintf (fid, \"%s\", url(8:end));\n    fclose (fid);\n    url = [\"file://\" fname];\n  endif\n\n  sts = __open_with_system_app__ (url);\n  sts = ifelse (sts == 1, 0, 2);\n\n  h = [];  # Empty handle, as we cannot control an external browser.\n\n  ## For Matlab compatibility.\n  if (any (strcmp (varargin, \"-browser\")))\n    url = [];\n  endif\n\n  if (nargout > 0)\n    status = sts;\n  endif\n\nendfunction\n\n\n%!error <URL must be a string> web (1)\n%!error <URL must be a string> web ('')\n%!error <'-invalid_Option' does not match>\n%!  web (\"https://www.octave.org\", \"-invalid_Option\")\n"
  },
  {
    "path": "scripts/web/weboptions.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nclassdef weboptions < handle\n\n  ## -*- texinfo -*-\n  ## @deftypefn  {} {@var{options} =} weboptions ()\n  ## @deftypefnx {} {@var{options} =} weboptions (@var{name1}, @var{value1}, @dots{})\n  ##\n  ## Specify parameters for RESTful web services.\n  ##\n  ## When called with no inputs return a default @code{weboptions} object\n  ## to specify parameters for a request to a web service.  A @code{weboptions}\n  ## object is an optional input argument to the @code{webread} and\n  ## @code{webwrite} functions.\n  ##\n  ## Multiple name and value pair arguments may be specified in any order as\n  ## @var{name1}, @var{value1}, @var{name2}, @var{value2}, etc.\n  ##\n  ## The option names must match @strong{exactly} one of those specified in the\n  ## table below.\n  ##\n  ## The following options are available:\n  ##\n  ## @itemize @bullet\n  ## @item\n  ## @samp{CharacterEncoding} --- Specify the character encoding of the data:\n  ##\n  ## @samp{auto} (default), @samp{UTF-8}, @samp{US-ASCII}.\n  ## @samp{auto} chooses an encoding based on the content-type of the data.\n  ##\n  ## @item\n  ## @samp{UserAgent} --- Specify the User Agent for the connection.\n  ##\n  ## Default value is @samp{Octave/VERSION}, where @samp{VERSION} is the\n  ## current version of Octave as returned by @code{version}.\n  ##\n  ## @item\n  ## @samp{Timeout} --- Specify the timeout value for the connection in\n  ## seconds.\n  ##\n  ## Default is 5 seconds.  The special value @samp{Inf} sets the timeout to\n  ## the maximum value of 2147.483647 seconds.\n  ##\n  ## @item\n  ## @samp{Username} --- User identifier for a basic HTTP connection.\n  ##\n  ## Default is @qcode{\"\"}.  It must be a string or character vector.\n  ##\n  ## @item\n  ## @samp{Password} --- User authentication password for HTTP connection.\n  ##\n  ## Default is @qcode{\"\"}.  It must be a string or character vector.\n  ##\n  ## Programming Note: If you display a @code{weboption} object with the\n  ## Password property set, the value is displayed as a string containing\n  ## @qcode{'*'}.  However, the object stores the value of the Password\n  ## property as plain text.\n  ##\n  ## @item\n  ## @samp{KeyName} --- Specify the name of an additional key to be added to\n  ## the HTTP request header.\n  ##\n  ## It must be a string or character vector.  It should be coupled with\n  ## @samp{KeyValue}.\n  ##\n  ## @item\n  ## @samp{KeyValue} --- Specify the value of the key @samp{KeyName}.\n  ##\n  ## @samp{KeyName} must already be assigned in order to specify this field.\n  ##\n  ## @item\n  ## @samp{ContentType} --- Specify the content type of the data.\n  ##\n  ## The following values are available:\n  ## @samp{auto}, @samp{text}, @samp{json}\n  ##\n  ## Default is @samp{auto}.  It automatically determines the content type.\n  ## All other formats like @samp{audio}, @samp{binary}, etc.@: available in\n  ## @sc{matlab} are not currently supported.\n  ##\n  ## @item\n  ## @samp{ContentReader} --- Not yet implemented.  Only for @sc{matlab}\n  ## compatibility.\n  ##\n  ## @item\n  ## @samp{MediaType} --- Not yet implemented.  Only for @sc{matlab}\n  ## compatibility.\n  ##\n  ## @item\n  ## @samp{RequestMethod} --- Specifies the type of request to be made.\n  ##\n  ## The following methods are available:\n  ## @samp{get}, @samp{put}, @samp{post}, @samp{delete}, @samp{patch}\n  ##\n  ## @code{webread} uses the HTTP GET method.  @code{webwrite} uses the HTTP\n  ## POST method as default.\n  ##\n  ## @item\n  ## @samp{ArrayFormat} -- Not yet implemented.  Only for @sc{matlab}\n  ## compatibility.\n  ##\n  ## @item\n  ## @samp{@nospell{HeaderFields}} --- Specify header fields for the\n  ## connection.\n  ##\n  ## Names and values of header fields, specified as an m-by-2 cell array of\n  ## strings, to add to the HTTP request header.\n  ## @code{@nospell{HeaderFields}@{i,1@}} is the name of a field and\n  ## @code{@nospell{HeaderFields}@{i,2@}} is its value.\n  ##\n  ## @example\n  ## @group\n  ## weboptions (\"HeaderFields\",\n  ##             @{\"Content-Length\", \"78\" ;\n  ##              \"Content-Type\", \"application/json\"@})\n  ## @end group\n  ## @end example\n  ##\n  ## @noindent\n  ## creates a weboptions object that contains two header fields:\n  ## @code{Content-Length} with value @code{78} and @code{Content-Type} with\n  ## value @code{application/json}.\n  ##\n  ## @item\n  ## @samp{CertificateFilename} --- Not yet implemented.  Only for @sc{matlab}\n  ## compatibility.\n  ## @end itemize\n  ##\n  ## @seealso{webread, webwrite}\n  ## @end deftypefn\n\n  properties\n    CharacterEncoding = \"auto\";\n    UserAgent = [\"Octave/\", version()];\n    Timeout = 5;\n    Username = \"\";\n    Password = \"\";\n    KeyName = \"\";\n    KeyValue = \"\";\n    ContentType = \"auto\";\n    ContentReader = \"\";\n    MediaType = \"auto\";\n    RequestMethod = \"auto\";\n    ArrayFormat = \"csv\";\n    HeaderFields = {};\n    CertificateFilename = \"\";\n  endproperties\n\n  methods\n\n    function f = weboptions (varargin)\n\n      if (rem (numel (varargin), 2) != 0)\n        error (\"weboptions: invalid number of arguments\");\n      elseif (numel (varargin) > 28)\n        error (\"weboptions: invalid number of arguments\");\n      endif\n\n      propnames = properties (f);\n      for i = 1:2:numel (varargin)\n        idx = find (strcmpi (varargin{i}, propnames), 1);\n        if (isempty (idx))\n          error (\"weboptions: Undefined field '%s'\", varargin{i});\n        endif\n        f.(propnames{idx}) = varargin{i+1};\n      endfor\n\n    endfunction\n\n    function f = set.CharacterEncoding (f, value)\n      ## FIXME: Why validate this?  There are many other possible encodings.\n      if (! any (strcmpi (value, {'auto', 'US-ASCII', 'UTF-8'})))\n        error (\"weboptions: Invalid CharacterEncoding value\");\n      endif\n      f.CharacterEncoding = value;\n    endfunction\n\n    function f = set.UserAgent (f, value)\n      if (isempty (value))\n        value = \"\";\n      elseif (! (ischar (value) && isrow (value)))\n        error (\"weboptions: UserAgent must be a string\");\n      endif\n      f.UserAgent = value;\n    endfunction\n\n    function f = set.Timeout (f, value)\n      if (! (isreal (value) && isscalar (value) && value > 0))\n        error (\"weboptions: Timeout must be a real scalar > 0\");\n      endif\n      if (value == Inf)\n        f.Timeout = 2147.483647;\n      else\n        f.Timeout = value;\n      endif\n    endfunction\n\n    function f = set.Username (f, value)\n      if (isempty (value))\n        value = \"\";\n      elseif (! (ischar (value) && isrow (value)))\n        error (\"weboptions: Username must be a string\");\n      endif\n      f.Username = value;\n    endfunction\n\n    function f = set.Password (f, value)\n      if (isempty (value))\n        value = \"\";\n      elseif (! (ischar (value) && isrow (value)))\n        error (\"weboptions: Password must be a string\");\n      endif\n      f.Password = value;\n    endfunction\n\n    function f = set.KeyName (f, value)\n      if (isempty (value))\n        value = \"\";\n      elseif (! (ischar (value) && isrow (value)))\n        error (\"weboptions: KeyName must be a string\");\n      endif\n      f.KeyName = value;\n    endfunction\n\n    function f = set.KeyValue (f, value)\n      if (isempty (f.KeyName) && ! isempty (value))\n        error (\"weboptions: KeyName field empty.  Cannot set KeyValue.\");\n      endif\n      if (isempty (value))\n        value = \"\";\n      elseif (! (ischar (value) && isrow (value)))\n        if (! (isnumeric (value) || islogical (value)) || ! isscalar (value))\n          error (\"weboptions: KeyValue must be a string or a logical/numeric scalar\");\n        endif\n        ## FIXME: Matab keeps original class of value rather than a string.\n        value = num2str (value);\n      endif\n      f.KeyValue = value;\n    endfunction\n\n    function f = set.ContentType (f, value)\n      if (! any (strcmpi (value, {\"auto\", \"json\", \"text\"})))\n        error (\"weboptions: invalid ContentType value\");\n      endif\n      f.ContentType = value;\n    endfunction\n\n    function f = set.ContentReader (f, value)\n      ## FIXME: Should emit a warning about unimplemented feature\n      if (isempty (value))\n        value = \"\";\n      elseif (! is_function_handle (value))\n        error (\"weboptions: ContentReader must be a function handle\");\n      endif\n      f.ContentReader = value;\n    endfunction\n\n    function f = set.MediaType (f, value)\n      ## FIXME: Should emit a warning about unimplemented feature\n      if (isempty (value))\n        value = \"\";\n      elseif (! (ischar (value) && isrow (value)))\n        error (\"weboptions: MediaType must be a string\");\n      endif\n      f.MediaType = value;\n    endfunction\n\n    function f = set.RequestMethod (f, value)\n      if (! any (strcmpi (value,\n                          {\"auto\", \"get\", \"put\", \"post\", \"delete\", \"patch\"})))\n        error (\"weboptions: invalid RequestMethod value\");\n      endif\n      f.RequestMethod = value;\n\n    endfunction\n\n    function f = set.ArrayFormat (f, value)\n      if (! any (strcmpi (value, {\"csv\", \"json\", \"php\", \"repeating\"})))\n        error (\"weboptions: invalid ArrayFormat value\");\n      endif\n      f.ArrayFormat = value;\n    endfunction\n\n    function f = set.HeaderFields (f, value)\n\n      if (! isempty (value))\n        if (! iscellstr (value))\n          error (\"weboptions: HeaderFields must be a cell array of strings\");\n        elseif (ndims (value) != 2 || columns (value) != 2)\n          error (\"weboptions: HeaderFields must be of size m-by-2\");\n        endif\n      endif\n      ## C++ code requires row vector of \"prop\", \"value\" pairs.\n      f.HeaderFields = (value')(:)';\n\n    endfunction\n\n    function f = set.CertificateFilename (f, value)\n      ## FIXME: Should emit a warning about unimplemented feature\n      if (isempty (value))\n        value = \"\";\n      elseif (! (ischar (value) && isrow (value)))\n        error (\"weboptions: CertificateFilename must be a string\");\n      endif\n      f.CertificateFilename = value;\n    endfunction\n\n    function disp (f)\n\n      Timeout = num2str (f.Timeout);\n      Password = repmat (\"*\", 1, numel (num2str (f.Password)));\n\n      if (! isempty (f.ContentReader))\n        ## Strip newline from output of disp()\n        ContentReader = (disp (f.ContentReader))(1:end-1);\n      else\n        ContentReader = \"[]\";\n      endif\n\n      if (! isempty (f.HeaderFields))\n        HeaderFields = ['{\"', strjoin(f.HeaderFields, '\", \"'), '\"}'];\n      else\n        HeaderFields = \"{}\";\n      endif\n\n      if (! isempty (f.KeyValue))\n        KeyValue = num2str (f.KeyValue);\n      else\n        KeyValue = \"''\";\n      endif\n\n      output = [\"  weboptions with properties:\\n\",...\n                \"\\n      CharacterEncoding: '\", f.CharacterEncoding, \"'\",...\n                \"\\n              UserAgent: '\", f.UserAgent, \"'\",...\n                \"\\n                Timeout: \" , Timeout,...\n                \"\\n               Username: '\", f.Username, \"'\",...\n                \"\\n               Password: '\", Password, \"'\",...\n                \"\\n                KeyName: '\", f.KeyName, \"'\",...\n                \"\\n               KeyValue: \" , KeyValue,...\n                \"\\n            ContentType: '\", f.ContentType, \"'\",...\n                \"\\n          ContentReader: \" , ContentReader,...\n                \"\\n              MediaType: '\", f.MediaType, \"'\",...\n                \"\\n          RequestMethod: '\", f.RequestMethod, \"'\",...\n                \"\\n            ArrayFormat: '\", f.ArrayFormat, \"'\",...\n                \"\\n           HeaderFields: \" , HeaderFields,...\n                \"\\n    CertificateFilename: '\", f.CertificateFilename \"'\"];\n      disp (output);\n\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "scripts/web/webread.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{response} =} webread (@var{url})\n## @deftypefnx {} {@var{response} =} webread (@var{url}, @var{name1}, @var{value1}, @dots{})\n## @deftypefnx {} {@var{response} =} webread (@dots{}, @var{options})\n##\n## Read content from RESTful web service.\n##\n## Read content from the web service specified by @var{url} and return the\n## content in @var{response}.\n##\n## All name-value pairs given (@var{name1}, @var{value1}, @dots{}) are appended\n## as query parameters to @var{url}.  To place a query in the body of the\n## message, use @code{webwrite}.  The web service defines the acceptable query\n## parameters.\n##\n## @var{options} is a @code{weboptions} object that may be used to add other\n## HTTP request options.  This argument can be used with either calling form.\n## See @code{help weboptions} for a complete list of supported HTTP options.\n##\n## @seealso{weboptions, webwrite}\n## @end deftypefn\n\nfunction response = webread (url, varargin)\n\n  if (nargin == 0)\n    print_usage ();\n  endif\n\n  if (! (ischar (url) && isrow (url)))\n    error (\"webread: URL must be a string\");\n  endif\n\n  if (nargin > 1 && isa (varargin{end}, \"weboptions\"))\n    has_weboptions = true;\n    options = varargin{end};\n    varargin(end) = [];\n  else\n    has_weboptions = false;\n    options = weboptions ();\n  endif\n\n  has_nameval_pairs = false;\n  if (! isempty (varargin))\n    has_nameval_pairs = true;\n    if (rem (numel (varargin), 2) != 0)\n      error (\"webread: NAMES/VALUES must occur in pairs\");\n    elseif (! iscellstr (varargin))\n      error (\"webread: NAMES and VALUES must be strings\");\n    endif\n  endif\n\n  if (strcmp (options.MediaType, \"auto\"))\n    options.MediaType = \"application/x-www-form-urlencoded\";\n  endif\n\n  ## If MediaType is set by the user, append it to other headers.\n  if (! strcmp (options.CharacterEncoding, \"auto\"))\n    options.HeaderFields{end+1,1} = \"Content-Type\";\n    options.HeaderFields{end,2} = [options.MediaType, ...\n                                   \"; charset=\", options.CharacterEncoding];\n  endif\n\n  if (! isempty (options.KeyName))\n    options.HeaderFields{end+1,1} = options.KeyName;\n    options.HeaderFields{end,2} = options.KeyValue;\n  endif\n\n  if (strcmp (options.RequestMethod, \"auto\"))\n    options.RequestMethod = \"get\";\n  endif\n\n  if (has_nameval_pairs)\n    response = __restful_service__ (url, varargin, options);\n  else\n    response = __restful_service__ (url, cell (), options);\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> webread ()\n%!error <URL must be a string> webread (1)\n%!error <URL must be a string> webread ([\"a\";\"b\"])\n%!error <NAMES/VALUES must occur in pairs> webread (\"URL\", \"KEY1\")\n%!error <NAMES and VALUES must be strings> webread (\"URL\", \"NAME1\", 5)\n"
  },
  {
    "path": "scripts/web/webwrite.m",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn  {} {@var{response} =} webwrite (@var{url}, @var{name1}, @var{value1}, @dots{})\n## @deftypefnx {} {@var{response} =} webwrite (@var{url}, @var{data})\n## @deftypefnx {} {@var{response} =} webwrite (@dots{}, @var{options})\n##\n## Write data to RESTful web services.\n##\n## Write content to the web service specified by @var{url} and return the\n## response in @var{response}.\n##\n## All name-value pairs given (@var{name1}, @var{value1}, @dots{}) are added\n## as pairs of query parameters to the body of request method (@code{get},\n## @code{post}, @code{put}, etc.).\n##\n## @var{options} is a @code{weboptions} object that may be used to add other\n## HTTP request options.  This argument can be used with either calling form.\n## See @code{help weboptions} for a complete list of supported HTTP options.\n##\n## @seealso{weboptions, webread}\n## @end deftypefn\n\nfunction response = webwrite (url, varargin)\n\n  if (nargin < 2)\n    print_usage ();\n  endif\n\n  if (! (ischar (url) && isrow (url)))\n    error (\"webwrite: URL must be a string\");\n  endif\n\n  if (isa (varargin{end}, \"weboptions\"))\n    has_weboptions = true;\n    options = varargin{end};\n    varargin(end) = [];\n  else\n    has_weboptions = false;\n    options = weboptions ();\n  endif\n\n  has_param = false;\n  nargs = numel (varargin);\n  if (nargs == 0)\n    error (\"webwrite: missing DATA or NAMES/VALUES arguments\");\n\n  elseif (nargs == 1)\n\n    if (! iscellstr (varargin))\n      error (\"webwrite: DATA must be a string\");\n    elseif (ischar (varargin{1}) && isrow (varargin{1}))\n      param = regexp (varargin{1}, '([^=]*)=([^&]*)&?', 'tokens');\n      if (isempty (param) || isempty (param{1}))\n        error (\"webwrite: DATA not a valid query string\");\n      endif\n      has_param = true;\n      param = [param{:}];\n    endif\n\n  elseif (rem (nargs, 2) != 0)\n    error (\"webwrite: NAMES/VALUES must occur in pairs\");\n\n  elseif (! iscellstr (varargin))\n    error (\"webwrite: NAMES and VALUES must be strings\");\n\n  endif\n\n  if (strcmp (options.MediaType, \"auto\"))\n    options.MediaType = \"application/x-www-form-urlencoded\";\n  endif\n\n  ## If MediaType is set by the user, append it to other headers.\n  if (! strcmp (options.CharacterEncoding, \"auto\"))\n    options.HeaderFields{end+1, 1} = \"Content-Type\";\n    options.HeaderFields{end, 2} = [options.MediaType, ...\n                                    \"; charset=\", options.CharacterEncoding];\n  endif\n\n  if (! isempty (options.KeyName))\n    options.HeaderFields{end+1, 1} = options.KeyName;\n    options.HeaderFields{end, 2} = options.KeyValue;\n  endif\n\n  if (strcmp (options.RequestMethod, \"auto\"))\n    options.RequestMethod = \"post\";\n  endif\n\n  if (has_param)\n    response = __restful_service__ (url, param, options);\n  else\n    response = __restful_service__ (url, varargin, options);\n  endif\n\nendfunction\n\n\n## Test input validation\n%!error <Invalid call> webwrite ()\n%!error <Invalid call> webwrite (\"abc\")\n%!error <URL must be a string> webwrite (1, \"NAME1\", \"VALUE1\")\n%!error <URL must be a string> webwrite ([\"a\";\"b\"], \"NAME1\", \"VALUE1\")\n%!error <missing DATA or NAMES/VALUES> webwrite (\"URL\", weboptions ())\n%!error <DATA must be a string> webwrite (\"URL\", 1)\n%!error <DATA must be a string> webwrite (\"URL\", 1, weboptions ())\n%!error <DATA not a valid query string> webwrite (\"URL\", \"foobar\")\n%!error <NAMES/VALUES must occur in pairs> webwrite (\"URL\", \"KEY1\", \"VAL1\", \"A\")\n%!error <NAMES and VALUES must be strings> webwrite (\"URL\", \"NAME1\", 5)\n"
  },
  {
    "path": "src/display-available.c",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <stdlib.h>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <windows.h>\n#elif defined (HAVE_FRAMEWORK_CARBON)\n#  include <Carbon/Carbon.h>\n#else\n#  if defined (HAVE_X_WINDOWS)\n#    include <X11/Xlib.h>\n#  endif\n#  if defined (HAVE_WAYLAND_CLIENT)\n#    include <wayland-client.h>\n#  endif\n#endif\n\n#include \"display-available.h\"\n\nconst char *\ndisplay_available (int *dpy_avail)\n{\n  *dpy_avail = 0;\n\n  const char *err_msg = \"\";\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n  HDC hdc = GetDC (0);\n\n  if (hdc)\n    *dpy_avail = 1;\n  else\n    err_msg = \"no graphical display found\";\n\n#elif defined (HAVE_FRAMEWORK_CARBON)\n\n  CGDirectDisplayID display = CGMainDisplayID ();\n\n  if (display)\n    *dpy_avail = 1;\n  else\n    err_msg = \"no graphical display found\";\n\n#elif defined (HAVE_X_WINDOWS) || defined (HAVE_WAYLAND_CLIENT)\n\n#if defined (HAVE_X_WINDOWS)\n  const char *display_name = getenv (\"DISPLAY\");\n\n  if (display_name && *display_name)\n    {\n      Display *display = XOpenDisplay (display_name);\n\n      if (display)\n        {\n          Screen *screen = DefaultScreenOfDisplay (display);\n\n          if (! screen)\n            err_msg = \"X11 display has no default screen\";\n\n          XCloseDisplay (display);\n\n          *dpy_avail = 1;\n        }\n#  if ! defined (HAVE_WAYLAND_CLIENT)\n      else\n        err_msg = \"unable to open X11 DISPLAY\";\n#  endif\n    }\n#  if ! defined (HAVE_WAYLAND_CLIENT)\n  else\n    err_msg = \"X11 DISPLAY environment variable not set\";\n#  endif\n#endif\n\n#if defined (HAVE_WAYLAND_CLIENT)\n  if (*dpy_avail == 0)\n    {\n      struct wl_display *display = wl_display_connect (NULL);\n      if (display)\n        {\n          wl_display_disconnect (display);\n\n          *dpy_avail = 1;\n        }\n      else\n#  if defined (HAVE_X_WINDOWS)\n        err_msg = \"No working Wayland or X11 display is connected or X11 DISPLAY environment variable not set\";\n#  else\n        err_msg = \"No working Wayland display is connected\";\n#  endif\n    }\n#endif\n\n#else\n\n  err_msg = \"no graphical display found\";\n\n#endif\n\n  return err_msg;\n}\n"
  },
  {
    "path": "src/display-available.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_display_available_h)\n#define octave_display_available_h 1\n\n#if defined (__cplusplus)\n#  include <new>\nextern \"C\" {\n#endif\n\nextern const char * display_available (int *dpy_avail);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/main-cli.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n\n#include <iostream>\n#include <string>\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\n#  include <vector>\n#  include <locale>\n#  include <codecvt>\n#  include <windows.h>\n#  include <versionhelpers.h>\n#endif\n\n#include \"liboctave-build-info.h\"\n\n#include \"liboctinterp-build-info.h\"\n\n#include \"liboctmex-build-info.h\"\n\n#include \"oct-env.h\"\n#include \"signal-wrappers.h\"\n\n#include \"octave.h\"\n#include \"octave-build-info.h\"\n#include \"sysdep.h\"\n\n#include \"shared-sysdep.h\"\n\nstatic void\ncheck_hg_versions ()\n{\n  bool ok = true;\n\n  // Each library and executable has its own definition of the hg\n  // id.  They should always match but may be different because of a\n  // botched installation or incorrect LD_LIBRARY_PATH or some other\n  // unusual problem.\n\n  std::string octave_id = octave_hg_id ();\n  std::string liboctave_id = liboctave_hg_id ();\n  std::string liboctinterp_id = liboctinterp_hg_id ();\n  std::string liboctmex_id = liboctmex_hg_id ();\n\n  if (octave_id != liboctave_id)\n    {\n      std::cerr << \"octave hg id (\"\n                << octave_id\n                << \") does not match liboctave hg id (\"\n                << liboctave_id\n                << ')' << std::endl;\n      ok = false;\n    }\n\n  if (octave_id != liboctinterp_id)\n    {\n      std::cerr << \"octave hg id (\"\n                << octave_id\n                << \") does not match liboctinterp hg id (\"\n                << liboctinterp_id\n                << ')' << std::endl;\n      ok = false;\n    }\n\n  if (octave_id != liboctmex_id)\n    {\n      std::cerr << \"octave hg id (\"\n                << octave_id\n                << \") does not match liboctmex hg id (\"\n                << liboctmex_id\n                << ')' << std::endl;\n      ok = false;\n    }\n\n  if (! ok)\n    std::exit (EXIT_FAILURE);\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\nextern \"C\"\nint\nwmain (int argc, wchar_t **wargv)\n{\n  char **argv = convert_wargv_to_utf8 (argc, wargv);\n\n  unsigned int old_console_codepage = 0;\n  unsigned int old_console_output_codepage = 0;\n\n  if (IsWindows7OrGreater ())\n    {\n      // save old console input and output codepages\n      old_console_codepage = GetConsoleCP ();\n      old_console_output_codepage = GetConsoleOutputCP ();\n\n      // set console input and output codepages to UTF-8\n      SetConsoleCP (65001);\n      SetConsoleOutputCP (65001);\n    }\n\n#else\nint\nmain (int argc, char **argv)\n{\n#endif\n  check_hg_versions ();\n\n  octave_block_async_signals ();\n\n  octave::sys::env::set_program_name (argv[0]);\n\n  octave::cli_application app (argc, argv);\n\n  int ret = app.execute ();\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\n  if (IsWindows7OrGreater ())\n    {\n      // restore previous console input and output codepages\n      if (old_console_codepage)\n        SetConsoleCP (old_console_codepage);\n      if (old_console_output_codepage)\n        SetConsoleOutputCP (old_console_output_codepage);\n    }\n#endif\n\n  return ret;\n}\n"
  },
  {
    "path": "src/main-gui.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n\n#include <iostream>\n#include <string>\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\n#  include <vector>\n#  include <locale>\n#  include <codecvt>\n#  include <windows.h>\n#  include <versionhelpers.h>\n#endif\n\n#include \"liboctave-build-info.h\"\n\n#include \"liboctinterp-build-info.h\"\n\n#include \"liboctgui-build-info.h\"\n\n#include \"liboctmex-build-info.h\"\n\n#include \"oct-env.h\"\n\n#include \"octave.h\"\n#include \"octave-build-info.h\"\n#include \"qt-application.h\"\n#include \"sysdep.h\"\n#include \"version.h\"\n\n#include \"shared-sysdep.h\"\n\nstatic void\ncheck_hg_versions ()\n{\n  bool ok = true;\n\n  // Each library and executable has its own definition of the hg\n  // id.  They should always match but may be different because of a\n  // botched installation or incorrect LD_LIBRARY_PATH or some other\n  // unusual problem.\n\n  std::string octave_id = octave_hg_id ();\n  std::string liboctave_id = liboctave_hg_id ();\n  std::string liboctinterp_id = liboctinterp_hg_id ();\n  std::string liboctgui_id = liboctgui_hg_id ();\n  std::string liboctmex_id = liboctmex_hg_id ();\n\n  if (octave_id != liboctave_id)\n    {\n      std::cerr << \"octave hg id (\"\n                << octave_id\n                << \") does not match liboctave hg id (\"\n                << liboctave_id\n                << ')' << std::endl;\n      ok = false;\n    }\n\n  if (octave_id != liboctinterp_id)\n    {\n      std::cerr << \"octave hg id (\"\n                << octave_id\n                << \") does not match liboctinterp hg id (\"\n                << liboctinterp_id\n                << ')' << std::endl;\n      ok = false;\n    }\n\n  if (octave_id != liboctgui_id)\n    {\n      std::cerr << \"octave hg id (\"\n                << octave_id\n                << \") does not match liboctgui hg id (\"\n                << liboctgui_id\n                << ')' << std::endl;\n      ok = false;\n    }\n\n  if (octave_id != liboctmex_id)\n    {\n      std::cerr << \"octave hg id (\"\n                << octave_id\n                << \") does not match liboctmex hg id (\"\n                << liboctmex_id\n                << ')' << std::endl;\n      ok = false;\n    }\n\n  if (! ok)\n    std::exit (EXIT_FAILURE);\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\nextern \"C\"\nint\nwmain (int argc, wchar_t **wargv)\n{\n  char **argv = convert_wargv_to_utf8 (argc, wargv);\n\n  unsigned int old_console_codepage = 0;\n  unsigned int old_console_output_codepage = 0;\n\n  if (IsWindows7OrGreater ())\n    {\n      // save old console input and output codepages\n      old_console_codepage = GetConsoleCP ();\n      old_console_output_codepage = GetConsoleOutputCP ();\n\n      // set console input and output codepages to UTF-8\n      SetConsoleCP (65001);\n      SetConsoleOutputCP (65001);\n    }\n\n#else\nint\nmain (int argc, char **argv)\n{\n#endif\n  check_hg_versions ();\n\n  octave::sys::env::set_program_name (argv[0]);\n\n  std::string app_name (\"octave-gui\");\n  std::string settings_file = octave::sys::env::getenv (\"OCTAVE_GUI_SETTINGS\");\n  if (! settings_file.empty ())\n    app_name = settings_file;\n\n  octave::qt_application app (\"octave\", app_name, OCTAVE_VERSION,\n                              argc, argv);\n\n  int ret = app.execute ();\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\n  if (IsWindows7OrGreater ())\n    {\n      // restore previous console input and output codepages\n      if (old_console_codepage)\n        SetConsoleCP (old_console_codepage);\n      if (old_console_output_codepage)\n        SetConsoleOutputCP (old_console_output_codepage);\n    }\n#endif\n\n  return ret;\n}\n"
  },
  {
    "path": "src/main.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2012-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// NOTE: This program is supposed to be a small wrapper that exists\n// primarily to give up the controlling TTY and then exec Octave with\n// its GUI.  It may also execute Octave without the GUI or the command\n// line version of Octave that is not linked with GUI libraries.  So\n// that it remains small, it should NOT depend on or be linked with\n// liboctave or libinterp.\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <cstdlib>\n#include <cstring>\n\n#include <algorithm>\n#include <iostream>\n#include <string>\n\n// We are linking against static libs so do not decorate with dllimport.\n// FIXME: This should be done by the build system.\n#undef OCTAVE_API\n#define OCTAVE_API\n#include \"fcntl-wrappers.h\"\n#include \"getopt-wrapper.h\"\n#include \"signal-wrappers.h\"\n#include \"unistd-wrappers.h\"\n#include \"wait-wrappers.h\"\n\n#if ! defined (OCTAVE_VERSION)\n#  define OCTAVE_VERSION %OCTAVE_VERSION%\n#endif\n\n#if ! defined (OCTAVE_ARCHLIBDIR)\n#  define OCTAVE_ARCHLIBDIR %OCTAVE_ARCHLIBDIR%\n#endif\n\n#if ! defined (OCTAVE_BINDIR)\n#  define OCTAVE_BINDIR %OCTAVE_BINDIR%\n#endif\n\n#if ! defined (OCTAVE_PREFIX)\n#  define OCTAVE_PREFIX %OCTAVE_PREFIX%\n#endif\n\n#if ! defined (OCTAVE_EXEC_PREFIX)\n#  define OCTAVE_EXEC_PREFIX %OCTAVE_EXEC_PREFIX%\n#endif\n\n#include \"display-available.h\"\n#include \"options.h\"\n#include \"shared-fcns.h\"\n\n#if defined (HAVE_OCTAVE_QT_GUI) && ! defined (OCTAVE_USE_WINDOWS_API)\nstatic bool fork_and_exec = true;\n#else\nstatic bool fork_and_exec = false;\n#endif\n\n// If we fork and exec, we'll need the following signal handling code to\n// forward signals to the GUI process.\n\nstatic pid_t gui_pid = 0;\n\nstatic int caught_signal = -1;\n\nstatic void\ngui_driver_sig_handler (int sig)\n{\n  if (gui_pid > 0)\n    caught_signal = sig;\n}\n\nstatic void\ngui_driver_set_signal_handler (const char *signame,\n                               octave_sig_handler *handler)\n{\n  octave_set_signal_handler_by_name (signame, handler, false);\n}\n\nstatic void\ninstall_signal_handlers ()\n{\n  // FIXME: do we need to handle and forward all the signals that Octave\n  // handles, or is it sufficient to only forward things like SIGINT,\n  // SIGBREAK, SIGABRT, SIGQUIT, and possibly a few others?\n\n  gui_driver_set_signal_handler (\"SIGINT\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGBREAK\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGABRT\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGALRM\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGBUS\", gui_driver_sig_handler);\n\n  // SIGCHLD\n  // SIGCLD\n  // SIGCONT\n\n  gui_driver_set_signal_handler (\"SIGEMT\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGFPE\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGHUP\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGILL\", gui_driver_sig_handler);\n\n  // SIGINFO\n  // SIGINT\n\n  gui_driver_set_signal_handler (\"SIGIOT\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGLOST\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGPIPE\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGPOLL\", gui_driver_sig_handler);\n\n  // SIGPROF\n  // SIGPWR\n\n  gui_driver_set_signal_handler (\"SIGQUIT\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGSEGV\", gui_driver_sig_handler);\n\n  // SIGSTOP\n\n  gui_driver_set_signal_handler (\"SIGSYS\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGTERM\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGTRAP\", gui_driver_sig_handler);\n\n  // SIGTSTP\n  // SIGTTIN\n  // SIGTTOU\n  // SIGURG\n\n  gui_driver_set_signal_handler (\"SIGUSR1\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGUSR2\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGVTALRM\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGIO\", gui_driver_sig_handler);\n\n  // SIGWINCH\n\n  gui_driver_set_signal_handler (\"SIGXCPU\", gui_driver_sig_handler);\n  gui_driver_set_signal_handler (\"SIGXFSZ\", gui_driver_sig_handler);\n}\n\nstatic std::string\nget_octave_bindir ()\n{\n  // Accept value from the environment literally, but substitute\n  // OCTAVE_HOME in the configuration value OCTAVE_BINDIR in case Octave\n  // has been relocated to some installation directory other than the\n  // one originally configured.\n\n  std::string obd = octave_getenv (\"OCTAVE_BINDIR\");\n\n  return obd.empty () ? prepend_octave_exec_home (std::string (OCTAVE_BINDIR))\n                      : obd;\n}\n\nstatic std::string\nget_octave_archlibdir ()\n{\n  // Accept value from the environment literally, but substitute\n  // OCTAVE_HOME in the configuration value OCTAVE_ARCHLIBDIR in case\n  // Octave has been relocated to some installation directory other than\n  // the one originally configured.\n\n  std::string dir = octave_getenv (\"OCTAVE_ARCHLIBDIR\");\n\n  return dir.empty () ? prepend_octave_exec_home (std::string (OCTAVE_ARCHLIBDIR))\n                      : dir;\n}\n\nstatic int\noctave_exec (const std::string& file, char **argv)\n{\n  int status = octave_execv_wrapper (file.c_str (), argv);\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  // The above wrapper uses spawn(P_WAIT,...) instead of exec on Windows.\n  if (status == -1)\n#endif\n  std::cerr << argv[0] << \": failed to exec '\" << file << \"'\" << std::endl;\n\n  return status;\n}\n\nstatic char *\nstrsave (const char *s)\n{\n  if (! s)\n    return nullptr;\n\n  int len = strlen (s);\n  char *tmp = new char [len+1];\n  tmp = strcpy (tmp, s);\n  return tmp;\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\nextern \"C\"\nint\nwmain (int argc, wchar_t **wargv)\n{\n  char **argv = convert_wargv_to_utf8 (argc, wargv);\n\n#else\nint\nmain (int argc, char **argv)\n{\n#endif\n  int retval = 0;\n\n  int idx_gui = -1;\n  bool server = false;\n  bool start_gui = false;\n  bool gui_libs = true;\n\n  bool eval_code = false;\n  bool persist_octave = false;\n\n  set_octave_home ();\n\n  std::string octave_bindir = get_octave_bindir ();\n  std::string octave_archlibdir = get_octave_archlibdir ();\n  std::string octave_cli\n    = octave_bindir + dir_sep_char + \"octave-cli-\" OCTAVE_VERSION;\n  std::string octave_gui = octave_archlibdir + dir_sep_char + \"octave-gui\";\n\n#if defined (HAVE_OCTAVE_QT_GUI)\n  // The Octave version number is already embedded in the\n  // octave_archlibdir directory name so we don't need to append it to\n  // the octave-gui filename.\n\n  std::string file = octave_gui;\n#else\n  std::string file = octave_cli;\n#endif\n\n  // Declaring new_argv static avoids leak warnings when using GCC's\n  // --address-sanitizer option.\n  static char **new_argv = new char * [argc + 2];\n\n  int next_optind = 1;\n  int k = 1;\n\n  bool warn_display = true;\n  bool no_display = false;\n\n  // Disable error reporting in getopt.  We want to silently recognize\n  // and process a few special arguments here and pass everything on to\n  // the real Octave program where incorrect usage errors may be\n  // reported.\n\n  octave_set_opterr_wrapper (0);\n\n  while (true)\n    {\n      int long_idx;\n\n      int optc = octave_getopt_long_wrapper (argc, argv, short_opts, long_opts,\n                                             &long_idx);\n      int old_optind = next_optind;\n      next_optind = octave_optind_wrapper ();\n\n      if (optc < 0)\n        break;\n\n      switch (optc)\n        {\n        case NO_GUI_LIBS_OPTION:\n          // Run the version of Octave that is not linked with any GUI\n          // libraries.  It may not be possible to do plotting or any ui*\n          // calls, but it will be a little faster to start and require less\n          // memory.  Don't pass the --no-gui-libs option on as that option\n          // is not recognized by Octave.\n          gui_libs = false;\n          file = octave_cli;\n          break;\n\n        case 'G':\n          // option \"--no-gui\"\n          // If we see this option, then we can just exec octave; we don't\n          // have to create a child process and wait for it to exit.  But do\n          // exec \"octave-gui\", not \"octave-cli\", because even if the\n          // --no-gui option is given, we may be asked to do some plotting or\n          // ui* calls.\n          start_gui = false;\n          new_argv[k++] = argv[old_optind];\n          break;\n\n        case 'g':\n          // option \"--gui\"\n          // If we see this option, then we fork and exec octave with the\n          // --gui option, while continuing to handle signals in the terminal.\n          // Do not copy the arg now, since we still not know if the gui\n          // should really be launched.  Just store the index.\n          start_gui = true;\n          idx_gui = old_optind;\n          break;\n\n        case EXPERIMENTAL_TERMINAL_WIDGET_OPTION:\n          // If we see this option, then we don't fork and exec.\n          fork_and_exec = false;\n          new_argv[k++] = argv[old_optind];\n          break;\n\n        case PERSIST_OPTION:\n          // FIXME: How can we reliably detect if this option appears after\n          //        a FILE argument.  In this case octave ignores the option,\n          //        but the GUI might still be launched if --gui is also\n          //        given.\n          persist_octave = true;\n          new_argv[k++] = argv[old_optind];\n          break;\n\n        case SERVER_OPTION:\n          server = true;\n          new_argv[k++] = argv[old_optind];\n          break;\n\n        case 'e':\n          // option \"--eval\"\n          eval_code = true;\n          for (int i = old_optind; i < next_optind; i++)\n            new_argv[k++] = argv[i];\n          break;\n\n        case 'q':\n          // options \"--quiet\" or \"--silent\"\n          warn_display = false;\n          new_argv[k++] = argv[old_optind];\n          break;\n\n        case 'W':\n          // option \"--no-window-system\"\n          no_display = true;\n          new_argv[k++] = argv[old_optind];\n          break;\n\n        default:\n          for (int i = old_optind; i < next_optind; i++)\n            new_argv[k++] = argv[i];\n          break;\n        }\n    }\n\n  // Treat trailing arguments as commands to be executed\n  if (next_optind < argc)\n    {\n      eval_code = true;\n      for (int i = next_optind; i < argc; i++)\n        new_argv[k++] = argv[i];\n    }\n\n  if (start_gui && eval_code && ! persist_octave)\n    start_gui = false;\n\n  // At this point, we definitely know whether the gui has to\n  // be launched or not.\n  // gui_libs and start_gui are just about options, not\n  // the environment.  Exit if they don't make sense.\n  if (start_gui)\n    {\n      // GUI should be started\n      if (! gui_libs)\n        {\n          std::cerr << \"octave: conflicting options: --no-gui-libs and --gui\"\n                    << std::endl;\n          return 1;\n        }\n\n      if (server)\n        {\n          std::cerr << \"octave: conflicting options: --server and --gui\"\n                    << std::endl;\n          return 1;\n        }\n\n#if ! defined (HAVE_OCTAVE_QT_GUI)\n      std::cerr << \"octave: GUI features missing or disabled in this build\"\n                << std::endl;\n      return 1;\n#endif\n\n      // Finally, add --gui to the command line options.  We can not\n      // just append it since options after a given file are ignored.\n      for (int j = k; j > 1; j--)\n        new_argv[j] = new_argv[j-1];\n\n      new_argv[1] = argv[idx_gui];\n      k++;\n    }\n\n  new_argv[k] = nullptr;\n\n  if (no_display)\n    {\n      start_gui = false;\n      gui_libs = false;\n\n      file = octave_cli;\n    }\n  else if (gui_libs || start_gui)\n    {\n      int dpy_avail;\n\n      const char *display_check_err_msg = display_available (&dpy_avail);\n\n      if (! dpy_avail)\n        {\n          start_gui = false;\n          gui_libs = false;\n\n          file = octave_cli;\n\n          if (warn_display)\n            {\n              if (! display_check_err_msg)\n                display_check_err_msg = \"graphical display unavailable\";\n\n              std::cerr << \"octave: \" << display_check_err_msg << std::endl;\n              std::cerr << \"octave: disabling GUI features\" << std::endl;\n            }\n        }\n    }\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  file += \".exe\";\n#endif\n\n  new_argv[0] = strsave (file.c_str ());\n\n  // The Octave interpreter may be multithreaded.  If so, we attempt to\n  // ensure that signals are delivered to the main interpreter thread\n  // and no others by blocking signals before we exec the Octave\n  // interpreter executable.  When that process starts, it will unblock\n  // signals in the main interpreter thread.  When running the GUI as a\n  // subprocess, we also unblock signals that the parent process handles\n  // so we can forward them to the child.\n\n  octave_block_async_signals ();\n  octave_block_signal_by_name (\"SIGTSTP\");\n\n  if (fork_and_exec && gui_libs && start_gui)\n    {\n      // Fork and exec when starting the GUI so that we will call\n      // setsid to give up the controlling terminal (if any) and so that\n      // the GUI process will be in a separate process group.\n      //\n      // The GUI process must be in a separate process group so that we\n      // can send an interrupt signal to all child processes when\n      // interrupting the interpreter.  See also bug #49609 and the\n      // function pthread_thread_manager::interrupt in the file\n      // libgui/src/thread-manager.cc.\n\n      gui_pid = octave_fork_wrapper ();\n\n      if (gui_pid < 0)\n        {\n          std::cerr << \"octave: fork failed!\" << std::endl;\n\n          retval = 1;\n        }\n      else if (gui_pid == 0)\n        {\n          // Child.\n\n          if (octave_setsid_wrapper () < 0)\n            {\n              std::cerr << \"octave: error calling setsid!\" << std::endl;\n\n              retval = 1;\n            }\n          else\n            retval = octave_exec (file, new_argv);\n        }\n      else\n        {\n          // Parent.  Forward signals to child while waiting for it to exit.\n\n          install_signal_handlers ();\n\n          octave_unblock_async_signals ();\n          octave_unblock_signal_by_name (\"SIGTSTP\");\n\n          int status;\n\n          while (true)\n            {\n              octave_waitpid_wrapper (gui_pid, &status, 0);\n\n              if (caught_signal > 0)\n                {\n                  int sig = caught_signal;\n\n                  caught_signal = -1;\n\n                  octave_kill_wrapper (gui_pid, sig);\n                }\n              else if (octave_wifexited_wrapper (status))\n                {\n                  retval = octave_wexitstatus_wrapper (status);\n                  break;\n                }\n              else if (octave_wifsignaled_wrapper (status))\n                {\n                  std::cerr << \"octave exited with signal \"\n                            << octave_wtermsig_wrapper (status) << std::endl;\n                  break;\n                }\n            }\n        }\n    }\n  else\n    {\n      retval = octave_exec (file, new_argv);\n\n      if (retval < 0)\n        std::cerr << argv[0] << \": \" << std::strerror (errno) << std::endl;\n    }\n\n\n  return retval;\n}\n"
  },
  {
    "path": "src/mkoctfile.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n#include <cstring>\n#include <map>\n#include <list>\n#include <algorithm>\n#include <iostream>\n#include <fstream>\n#include <sstream>\n#include <vector>\n#include <cstdio>\n#include <cstdlib>\n\n// Programming note: The CROSS macro here refers to building a\n// cross-compiler aware version of mkoctfile that can be used to cross\n// compile .oct file for Windows builds of Octave, not that mkoctfile\n// itself is being cross compiled.\n//\n// We don't use the wrapper and gnulib functions when we are building\n// with CROSS defined.  This configuration is only expected to work on\n// modern systems that should not need to have gnulib to fix POSIX\n// portability problems.  So we just assume a working POSIX system when\n// CROSS is defined.\n\n#if defined (CROSS)\n#  include <stdlib.h>\n#  include <sys/types.h>\n#  include <sys/wait.h>\n#  include <unistd.h>\n#  ifndef OCTAVE_UNUSED\n#    define OCTAVE_UNUSED\n#  endif\n#else\n// We are linking against static libs so do not decorate with dllimport.\n// FIXME: This should be done by the build system.\n#  undef OCTAVE_API\n#  define OCTAVE_API\n#  include \"mkostemps-wrapper.h\"\n#  include \"uniconv-wrappers.h\"\n#  include \"unistd-wrappers.h\"\n#  include \"wait-wrappers.h\"\n#endif\n\n#if ! defined (OCTAVE_VERSION)\n#  define OCTAVE_VERSION %OCTAVE_CONF_VERSION%\n#endif\n\n#if ! defined (OCTAVE_PREFIX)\n#  define OCTAVE_PREFIX %OCTAVE_CONF_PREFIX%\n#endif\n\n#if ! defined (OCTAVE_EXEC_PREFIX)\n#  define OCTAVE_EXEC_PREFIX %OCTAVE_CONF_EXEC_PREFIX%\n#endif\n\n#include \"shared-fcns.h\"\n\n#if defined (CROSS)\n\nstatic int\noctave_mkostemps_wrapper (char *tmpl, int suffixlen)\n{\n  return mkostemps (tmpl, suffixlen, 0);\n}\n\nstatic int\noctave_unlink_wrapper (const char *nm)\n{\n  return unlink (nm);\n}\n\nstatic bool\noctave_wifexited_wrapper (int status)\n{\n  return WIFEXITED (status);\n}\n\nstatic int\noctave_wexitstatus_wrapper (int status)\n{\n  return WEXITSTATUS (status);\n}\n\n#endif\n\nstatic std::string\nget_line (FILE *fp)\n{\n  std::ostringstream buf;\n\n  while (true)\n    {\n      int c = std::fgetc (fp);\n\n      if (c == '\\n' || c == EOF)\n        break;\n\n      buf << static_cast<char> (c);\n    }\n\n  return buf.str ();\n}\n\nstatic std::string\nget_variable (const char *name, const std::string& defval)\n{\n  const char *val = getenv (name);\n\n  if (val && *val)\n    return std::string (val);\n  else\n    return defval;\n}\n\nstatic std::string\nquote_path (const std::string& s)\n{\n  if (s.find (' ') != std::string::npos && s[0] != '\"')\n    return '\"' + s + '\"';\n  else\n    return s;\n}\n\nstatic std::string\nreplace_prefix (std::string s)\n{\n#if defined (OCTAVE_REPLACE_PREFIX)\n  const std::string match = \"${prefix}\";\n  const std::string repl = Voctave_exec_home;\n  std::size_t pos = s.find (match);\n  while (pos != std::string::npos )\n    {\n      // Quote replacement path if the input isn't quoted.\n      if (pos > 0 && s[pos-1] != '\"' && s[pos-1] != '\\'')\n        s.replace (pos, match.length (), quote_path (repl));\n      else\n        s.replace (pos, match.length (), repl);\n      pos = s.find (match);\n    }\n#endif\n\n  return s;\n}\n\nstatic std::map<std::string, std::string>\nmake_vars_map (bool link_stand_alone, bool verbose, bool debug)\n{\n  set_octave_home ();\n\n  std::map<std::string, std::string> vars;\n\n  vars[\"OCTAVE_HOME\"] = Voctave_home;\n  vars[\"OCTAVE_EXEC_HOME\"] = Voctave_exec_home;\n\n  vars[\"API_VERSION\"] = %OCTAVE_API_VERSION%;\n  vars[\"CANONICAL_HOST_TYPE\"] = %OCTAVE_CANONICAL_HOST_TYPE%;\n  vars[\"DEFAULT_PAGER\"] = %OCTAVE_DEFAULT_PAGER%;\n  vars[\"EXEEXT\"] = %OCTAVE_EXEEXT%;\n  vars[\"MAN1EXT\"] = %OCTAVE_MAN1EXT%;\n  vars[\"OCTAVE_VERSION\"] = %OCTAVE_VERSION%;\n\n  vars[\"ARCHLIBDIR\"] = prepend_octave_exec_home (%OCTAVE_ARCHLIBDIR%);\n  vars[\"BINDIR\"] = prepend_octave_exec_home (%OCTAVE_BINDIR%);\n  vars[\"DATADIR\"] = prepend_octave_home (%OCTAVE_DATADIR%);\n  vars[\"DATAROOTDIR\"] = prepend_octave_home (%OCTAVE_DATAROOTDIR%);\n  vars[\"FCNFILEDIR\"] = prepend_octave_home (%OCTAVE_FCNFILEDIR%);\n  vars[\"IMAGEDIR\"] = prepend_octave_home (%OCTAVE_IMAGEDIR%);\n  vars[\"INFODIR\"] = prepend_octave_home (%OCTAVE_INFODIR%);\n  vars[\"INFOFILE\"] = prepend_octave_home (%OCTAVE_INFOFILE%);\n  vars[\"LIBEXECDIR\"] = prepend_octave_exec_home (%OCTAVE_LIBEXECDIR%);\n  vars[\"LOCALAPIARCHLIBDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIARCHLIBDIR%);\n  vars[\"LOCALAPIFCNFILEDIR\"] = prepend_octave_home (%OCTAVE_LOCALAPIFCNFILEDIR%);\n  vars[\"LOCALAPIOCTFILEDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIOCTFILEDIR%);\n  vars[\"LOCALAPIPKGDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIPKGDIR%);\n  vars[\"LOCALARCHLIBDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALARCHLIBDIR%);\n  vars[\"LOCALFCNFILEDIR\"] = prepend_octave_home (%OCTAVE_LOCALFCNFILEDIR%);\n  vars[\"LOCALOCTFILEDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALOCTFILEDIR%);\n  vars[\"LOCALSTARTUPFILEDIR\"] = prepend_octave_home (%OCTAVE_LOCALSTARTUPFILEDIR%);\n  vars[\"LOCALVERARCHLIBDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALVERARCHLIBDIR%);\n  vars[\"LOCALVERFCNFILEDIR\"] = prepend_octave_home (%OCTAVE_LOCALVERFCNFILEDIR%);\n  vars[\"LOCALVEROCTFILEDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALVEROCTFILEDIR%);\n  vars[\"MAN1DIR\"] = prepend_octave_home (%OCTAVE_MAN1DIR%);\n  vars[\"MANDIR\"] = prepend_octave_home (%OCTAVE_MANDIR%);\n  vars[\"OCTDATADIR\"] = prepend_octave_home (%OCTAVE_OCTDATADIR%);\n  vars[\"OCTDOCDIR\"] = prepend_octave_home (%OCTAVE_OCTDOCDIR%);\n  vars[\"OCTFILEDIR\"] = prepend_octave_exec_home (%OCTAVE_OCTFILEDIR%);\n  vars[\"OCTFONTSDIR\"] = prepend_octave_home (%OCTAVE_OCTFONTSDIR%);\n  vars[\"STARTUPFILEDIR\"] = prepend_octave_home (%OCTAVE_STARTUPFILEDIR%);\n\n  vars[\"OCTINCLUDEDIR\"]\n    = get_variable (\"OCTINCLUDEDIR\",\n                    prepend_octave_home (%OCTAVE_CONF_OCTINCLUDEDIR%));\n\n  vars[\"INCLUDEDIR\"]\n    = get_variable (\"INCLUDEDIR\",\n                    prepend_octave_home (%OCTAVE_CONF_INCLUDEDIR%));\n\n  vars[\"LIBDIR\"]\n    = get_variable (\"LIBDIR\", prepend_octave_exec_home (%OCTAVE_CONF_LIBDIR%));\n\n  vars[\"OCTLIBDIR\"]\n    = get_variable (\"OCTLIBDIR\",\n                    prepend_octave_exec_home (%OCTAVE_CONF_OCTLIBDIR%));\n\n  std::string DEFAULT_INCFLAGS;\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  DEFAULT_INCFLAGS = \"-I\" + quote_path (vars[\"OCTINCLUDEDIR\"] + R\"(\\..)\")\n                     + \" -I\" + quote_path (vars[\"OCTINCLUDEDIR\"]);\n#else\n  DEFAULT_INCFLAGS = \"-I\" + quote_path (vars[\"OCTINCLUDEDIR\"] + \"/..\")\n                     + \" -I\" + quote_path (vars[\"OCTINCLUDEDIR\"]);\n#endif\n\n  if (vars[\"INCLUDEDIR\"] != \"/usr/include\")\n    DEFAULT_INCFLAGS += \" -I\" + quote_path (vars[\"INCLUDEDIR\"]);\n\n  std::string DEFAULT_LDFLAGS;\n\n  if (vars[\"LIBDIR\"] != \"/usr/lib\")\n    DEFAULT_LDFLAGS += \" -L\" + quote_path (vars[\"LIBDIR\"]);\n\n  vars[\"CPPFLAGS\"] = get_variable (\"CPPFLAGS\",\n                                   replace_prefix (%OCTAVE_CONF_CPPFLAGS%));\n\n  vars[\"INCFLAGS\"] = get_variable (\"INCFLAGS\", DEFAULT_INCFLAGS);\n\n  vars[\"F77\"] = get_variable (\"F77\", %OCTAVE_CONF_MKOCTFILE_F77%);\n\n  vars[\"FFLAGS\"] = get_variable (\"FFLAGS\", %OCTAVE_CONF_FFLAGS%);\n\n  vars[\"FPICFLAG\"] = get_variable (\"FPICFLAG\", %OCTAVE_CONF_FPICFLAG%);\n\n  vars[\"CC\"] = get_variable (\"CC\", %OCTAVE_CONF_MKOCTFILE_CC%);\n  if (verbose && vars[\"CC\"] == \"cc-msvc\")\n    vars[\"CC\"] += \" -d\";\n\n  vars[\"CFLAGS\"] = get_variable (\"CFLAGS\", %OCTAVE_CONF_CFLAGS%);\n\n  vars[\"CPICFLAG\"] = get_variable (\"CPICFLAG\", %OCTAVE_CONF_CPICFLAG%);\n\n  vars[\"CXX\"] = get_variable (\"CXX\", %OCTAVE_CONF_MKOCTFILE_CXX%);\n  if (verbose && vars[\"CXX\"] == \"cc-msvc\")\n    vars[\"CXX\"] += \" -d\";\n\n  vars[\"CXXFLAGS\"] = get_variable (\"CXXFLAGS\", %OCTAVE_CONF_CXXFLAGS%);\n\n  vars[\"CXXLD\"] = get_variable (\"CXXLD\", vars[\"CXX\"]);\n  if (verbose && vars[\"CXXLD\"] == \"cc-msvc\")\n    vars[\"CXXLD\"] += \" -d\";\n\n  vars[\"CXXPICFLAG\"] = get_variable (\"CXXPICFLAG\", %OCTAVE_CONF_CXXPICFLAG%);\n\n  vars[\"XTRA_CFLAGS\"] = get_variable (\"XTRA_CFLAGS\", %OCTAVE_CONF_XTRA_CFLAGS%);\n\n  vars[\"XTRA_CXXFLAGS\"] = get_variable (\"XTRA_CXXFLAGS\",\n                                        %OCTAVE_CONF_XTRA_CXXFLAGS%);\n\n  vars[\"AR\"] = get_variable (\"AR\", %OCTAVE_CONF_MKOCTFILE_AR%);\n\n  vars[\"RANLIB\"] = get_variable (\"RANLIB\", %OCTAVE_CONF_MKOCTFILE_RANLIB%);\n\n  vars[\"DEPEND_FLAGS\"] = get_variable (\"DEPEND_FLAGS\",\n                                       %OCTAVE_CONF_DEPEND_FLAGS%);\n\n  vars[\"DEPEND_EXTRA_SED_PATTERN\"]\n    = get_variable (\"DEPEND_EXTRA_SED_PATTERN\",\n                    %OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%);\n\n  vars[\"DL_LDFLAGS\"] = get_variable (\"DL_LDFLAGS\",\n                                     %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%);\n\n  if (! link_stand_alone)\n    DEFAULT_LDFLAGS += ' ' + vars[\"DL_LDFLAGS\"];\n\n  vars[\"RDYNAMIC_FLAG\"] = get_variable (\"RDYNAMIC_FLAG\",\n                                        %OCTAVE_CONF_RDYNAMIC_FLAG%);\n\n  vars[\"LIBOCTAVE\"] = \"-loctave\";\n\n  vars[\"LIBOCTINTERP\"] = \"-loctinterp\";\n\n  vars[\"LIBOCTMEX\"] = \"-loctmex\";\n\n  vars[\"READLINE_LIBS\"] = %OCTAVE_CONF_READLINE_LIBS%;\n\n  vars[\"LAPACK_LIBS\"] = get_variable (\"LAPACK_LIBS\", %OCTAVE_CONF_LAPACK_LIBS%);\n\n  vars[\"BLAS_LIBS\"] = get_variable (\"BLAS_LIBS\", %OCTAVE_CONF_BLAS_LIBS%);\n\n  vars[\"FFTW3_LDFLAGS\"]\n    = get_variable (\"FFTW3_LDFLAGS\",\n                    replace_prefix (%OCTAVE_CONF_FFTW3_LDFLAGS%));\n\n  vars[\"FFTW3_LIBS\"] = get_variable (\"FFTW3_LIBS\", %OCTAVE_CONF_FFTW3_LIBS%);\n\n  vars[\"FFTW3F_LDFLAGS\"]\n    = get_variable (\"FFTW3F_LDFLAGS\",\n                    replace_prefix (%OCTAVE_CONF_FFTW3F_LDFLAGS%));\n\n  vars[\"FFTW3F_LIBS\"] = get_variable (\"FFTW3F_LIBS\", %OCTAVE_CONF_FFTW3F_LIBS%);\n\n  vars[\"LIBS\"] = get_variable (\"LIBS\", %OCTAVE_CONF_LIBS%);\n\n  vars[\"FLIBS\"] = get_variable (\"FLIBS\",\n                                replace_prefix (%OCTAVE_CONF_FLIBS%));\n\n  vars[\"OCTAVE_LINK_DEPS\"] = get_variable (\"OCTAVE_LINK_DEPS\",\n                                           replace_prefix (%OCTAVE_CONF_MKOCTFILE_OCTAVE_LINK_DEPS%));\n\n  vars[\"OCTAVE_LINK_OPTS\"] = get_variable (\"OCTAVE_LINK_OPTS\",\n                                           %OCTAVE_CONF_OCTAVE_LINK_OPTS%);\n\n  vars[\"OCT_LINK_DEPS\"] = get_variable (\"OCT_LINK_DEPS\",\n                                        replace_prefix (%OCTAVE_CONF_MKOCTFILE_OCT_LINK_DEPS%));\n\n  vars[\"OCT_LINK_OPTS\"]\n    = get_variable (\"OCT_LINK_OPTS\",\n                    replace_prefix (%OCTAVE_CONF_OCT_LINK_OPTS%));\n\n  vars[\"LDFLAGS\"] = get_variable (\"LDFLAGS\", DEFAULT_LDFLAGS);\n\n  vars[\"LD_STATIC_FLAG\"] = get_variable (\"LD_STATIC_FLAG\",\n                                         %OCTAVE_CONF_LD_STATIC_FLAG%);\n\n  vars[\"F77_INTEGER8_FLAG\"] = get_variable (\"F77_INTEGER8_FLAG\",\n                                            %OCTAVE_CONF_F77_INTEGER_8_FLAG%);\n  vars[\"ALL_FFLAGS\"] = vars[\"FFLAGS\"] + ' ' + vars[\"F77_INTEGER8_FLAG\"];\n  if (debug)\n    vars[\"ALL_FFLAGS\"] += \" -g\";\n\n  vars[\"ALL_CFLAGS\"]\n    = vars[\"INCFLAGS\"] + ' ' + vars[\"XTRA_CFLAGS\"] + ' ' + vars[\"CFLAGS\"];\n  if (debug)\n    vars[\"ALL_CFLAGS\"] += \" -g\";\n\n  vars[\"ALL_CXXFLAGS\"]\n    = vars[\"INCFLAGS\"] + ' ' + vars[\"XTRA_CXXFLAGS\"] + ' ' + vars[\"CXXFLAGS\"];\n  if (debug)\n    vars[\"ALL_CXXFLAGS\"] += \" -g\";\n\n  vars[\"ALL_LDFLAGS\"]\n    = vars[\"LD_STATIC_FLAG\"] + ' ' + vars[\"CPICFLAG\"] + ' ' + vars[\"LDFLAGS\"];\n\n  vars[\"OCTAVE_LIBS\"]\n    = (vars[\"LIBOCTINTERP\"] + ' ' + vars[\"LIBOCTAVE\"] + ' '\n       + vars[\"SPECIAL_MATH_LIB\"]);\n\n  vars[\"FFTW_LIBS\"] = vars[\"FFTW3_LDFLAGS\"] + ' ' + vars[\"FFTW3_LIBS\"] + ' '\n                      + vars[\"FFTW3F_LDFLAGS\"] + ' ' + vars[\"FFTW3F_LIBS\"];\n\n  return vars;\n}\n\nstatic std::string usage_msg = \"usage: mkoctfile [options] file ...\";\n\nstatic std::string version_msg = \"mkoctfile, version \" OCTAVE_VERSION;\n\nstatic std::string help_msg =\n  \"\\n\"\n  \"Options:\\n\"\n  \"\\n\"\n  \"  -h, -?, --help          Print this message.\\n\"\n  \"\\n\"\n  \"  -IDIR                   Add -IDIR to compile commands.\\n\"\n  \"\\n\"\n  \"  -idirafter DIR          Add -idirafter DIR to compile commands.\\n\"\n  \"\\n\"\n  \"  -DDEF                   Add -DDEF to compile commands.\\n\"\n  \"\\n\"\n  \"  -lLIB                   Add library LIB to link command.\\n\"\n  \"\\n\"\n  \"  -LDIR                   Add -LDIR to link command.\\n\"\n  \"\\n\"\n  \"  -M, --depend            Generate dependency files (.d) for C and C++\\n\"\n  \"                          source files.\\n\"\n#if ! defined (OCTAVE_USE_WINDOWS_API)\n  \"\\n\"\n  \"  -pthread                Add -pthread to link command.\\n\"\n#endif\n  \"\\n\"\n  \"  -RDIR                   Add -RDIR to link command.\\n\"\n  \"\\n\"\n  \"  -Wl,...                 Pass flags though the linker like -Wl,-rpath=...\\n\"\n  \"\\n\"\n  \"  -W...                   Pass flags though the compiler like -Wa,OPTION.\\n\"\n  \"\\n\"\n  \"  -c, --compile           Compile, but do not link.\\n\"\n  \"\\n\"\n  \"  -o FILE, --output FILE  Output filename.  Default extension is .oct\\n\"\n  \"                          (or .mex if --mex is specified) unless linking\\n\"\n  \"                          a stand-alone executable.\\n\"\n  \"\\n\"\n  \"  -g                      Enable debugging options for compilers.\\n\"\n  \"\\n\"\n  \"  -p VAR, --print VAR     Print configuration variable VAR.  There are\\n\"\n  \"                          three categories of variables:\\n\"\n  \"\\n\"\n  \"                          Octave configuration variables that users may\\n\"\n  \"                          override with environment variables.  These are\\n\"\n  \"                          used in commands that mkoctfile executes.\\n\"\n  \"\\n\"\n  \"                            ALL_CFLAGS                  INCLUDEDIR\\n\"\n  \"                            ALL_CXXFLAGS                LAPACK_LIBS\\n\"\n  \"                            ALL_FFLAGS                  LDFLAGS\\n\"\n  \"                            ALL_LDFLAGS                 LD_STATIC_FLAG\\n\"\n  \"                            BLAS_LIBS                   LIBDIR\\n\"\n  \"                            CC                          LIBOCTAVE\\n\"\n  \"                            CFLAGS                      LIBOCTINTERP\\n\"\n  \"                            CPICFLAG                    LIBOCTMEX\\n\"\n  \"                            CPPFLAGS                    OCTAVE_LINK_OPTS\\n\"\n  \"                            CXX                         OCTINCLUDEDIR\\n\"\n  \"                            CXXFLAGS                    OCTAVE_LIBS\\n\"\n  \"                            CXXLD                       OCTAVE_LINK_DEPS\\n\"\n  \"                            CXXPICFLAG                  OCTLIBDIR\\n\"\n  \"                            DL_LDFLAGS                  OCT_LINK_DEPS\\n\"\n  \"                            F77                         OCT_LINK_OPTS\\n\"\n  \"                            F77_INTEGER8_FLAG           RDYNAMIC_FLAG\\n\"\n  \"                            FFLAGS                      SPECIAL_MATH_LIB\\n\"\n  \"                            FPICFLAG                    XTRA_CFLAGS\\n\"\n  \"                            INCFLAGS                    XTRA_CXXFLAGS\\n\"\n  \"\\n\"\n  \"                          Octave configuration variables as above, but\\n\"\n  \"                          currently unused by mkoctfile.\\n\"\n  \"\\n\"\n  \"                            AR\\n\"\n  \"                            DEPEND_EXTRA_SED_PATTERN\\n\"\n  \"                            DEPEND_FLAGS\\n\"\n  \"                            FFTW3F_LDFLAGS\\n\"\n  \"                            FFTW3F_LIBS\\n\"\n  \"                            FFTW3_LDFLAGS\\n\"\n  \"                            FFTW3_LIBS\\n\"\n  \"                            FFTW_LIBS\\n\"\n  \"                            FLIBS\\n\"\n  \"                            LIBS\\n\"\n  \"                            RANLIB\\n\"\n  \"                            READLINE_LIBS\\n\"\n  \"\\n\"\n  \"                          Octave configuration variables that are provided\\n\"\n  \"                          for informational purposes only.  Except for\\n\"\n  \"                          OCTAVE_HOME and OCTAVE_EXEC_HOME, users may not\\n\"\n  \"                          override these variables.\\n\"\n  \"\\n\"\n  \"                          If OCTAVE_HOME or OCTAVE_EXEC_HOME are set in\\n\"\n  \"                          the environment, then other variables are adjusted\\n\"\n  \"                          accordingly with OCTAVE_HOME or OCTAVE_EXEC_HOME\\n\"\n  \"                          substituted for the original value of the directory\\n\"\n  \"                          specified by the --prefix or --exec-prefix options\\n\"\n  \"                          that were used when Octave was configured.\\n\"\n  \"\\n\"\n  \"                            API_VERSION                 LOCALFCNFILEDIR\\n\"\n  \"                            ARCHLIBDIR                  LOCALOCTFILEDIR\\n\"\n  \"                            BINDIR                      LOCALSTARTUPFILEDIR\\n\"\n  \"                            CANONICAL_HOST_TYPE         LOCALVERARCHLIBDIR\\n\"\n  \"                            DATADIR                     LOCALVERFCNFILEDIR\\n\"\n  \"                            DATAROOTDIR                 LOCALVEROCTFILEDIR\\n\"\n  \"                            DEFAULT_PAGER               MAN1DIR\\n\"\n  \"                            EXEC_PREFIX                 MAN1EXT\\n\"\n  \"                            EXEEXT                      MANDIR\\n\"\n  \"                            FCNFILEDIR                  OCTAVE_EXEC_HOME\\n\"\n  \"                            IMAGEDIR                    OCTAVE_HOME\\n\"\n  \"                            INFODIR                     OCTAVE_VERSION\\n\"\n  \"                            INFOFILE                    OCTDATADIR\\n\"\n  \"                            LIBEXECDIR                  OCTDOCDIR\\n\"\n  \"                            LOCALAPIARCHLIBDIR          OCTFILEDIR\\n\"\n  \"                            LOCALAPIFCNFILEDIR          OCTFONTSDIR\\n\"\n  \"                            LOCALAPIOCTFILEDIR          STARTUPFILEDIR\\n\"\n  \"                            LOCALARCHLIBDIR\\n\"\n  \"\\n\"\n  \"  --link-stand-alone      Link a stand-alone executable file.\\n\"\n  \"\\n\"\n  \"  --mex                   Assume we are creating a MEX file.  Set the\\n\"\n  \"                          default output extension to \\\".mex\\\".  Link to\\n\"\n  \"                          liboctmex instead of liboctinterp and liboctave.\\n\"\n  \"\\n\"\n  \"  -s, --strip             Strip output file.\\n\"\n  \"\\n\"\n  \"  -n, --just-print, --dry-run\\n\"\n  \"                          Print commands, but do not execute them.\\n\"\n  \"\\n\"\n  \"  -v, --verbose           Echo commands as they are executed.\\n\"\n  \"\\n\"\n  \"  -V, --version           Print version information.\\n\"\n  \"\\n\"\n  \"  --quiet                 Ignored.  Intended to suppress output from\\n\"\n  \"                          compiler steps.\\n\"\n  \"\\n\"\n  \"  FILE                    Compile or link FILE.  Recognized file types are:\\n\"\n  \"\\n\"\n  \"                            .c    C source\\n\"\n  \"                            .cc   C++ source\\n\"\n  \"                            .cp   C++ source\\n\"\n  \"                            .cpp  C++ source\\n\"\n  \"                            .CPP  C++ source\\n\"\n  \"                            .cxx  C++ source\\n\"\n  \"                            .c++  C++ source\\n\"\n  \"                            .C    C++ source\\n\"\n  \"                            .f    Fortran source (fixed form)\\n\"\n  \"                            .F    Fortran source (fixed form)\\n\"\n  \"                            .f90  Fortran source (free form)\\n\"\n  \"                            .F90  Fortran source (free form)\\n\"\n  \"                            .o    object file\\n\"\n  \"                            .a    library file\\n\"\n#if defined (_MSC_VER)\n  \"                            .lib  library file\\n\"\n#endif\n  \"\\n\";\n\nstatic std::string\nbasename (const std::string& s, bool strip_path = false)\n{\n  std::string retval;\n\n  std::size_t pos = s.rfind ('.');\n\n  if (pos == std::string::npos)\n    retval = s;\n  else\n    retval = s.substr (0, pos);\n\n  if (strip_path)\n    {\n      std::size_t p1 = retval.rfind ('/'), p2 = retval.rfind ('\\\\');\n\n      pos = (p1 != std::string::npos && p2 != std::string::npos\n             ? std::max (p1, p2) : (p2 != std::string::npos ? p2 : p1));\n\n      if (pos != std::string::npos)\n        retval = retval.substr (++pos, std::string::npos);\n    }\n\n  return retval;\n}\n\ninline bool\nstarts_with (const std::string& s, const std::string& prefix)\n{\n  return (s.length () >= prefix.length () && s.find (prefix) == 0);\n}\n\ninline bool\nends_with (const std::string& s, const std::string& suffix)\n{\n  return (s.length () >= suffix.length ()\n          && s.rfind (suffix) == s.length () - suffix.length ());\n}\n\nstatic int\nrun_command (const std::string& cmd, bool verbose, bool printonly = false)\n{\n  if (printonly)\n    {\n      std::cout << cmd << std::endl;\n      return 0;\n    }\n\n  if (verbose)\n    std::cout << cmd << std::endl;\n\n  // FIXME: Call _wsystem on Windows or octave::sys::system.\n  int result = system (cmd.c_str ());\n\n  if (octave_wifexited_wrapper (result))\n    result = octave_wexitstatus_wrapper (result);\n\n  return result;\n}\n\nbool\nis_true (const std::string& s)\n{\n  return (s == \"yes\" || s == \"true\");\n}\n\nstatic std::string\nget_temp_directory ()\n{\n  std::string tempd;\n\n  tempd = octave_getenv (\"TMPDIR\");\n\n#if defined (__MINGW32__) || defined (_MSC_VER)\n\n  if (tempd.empty ())\n    tempd = octave_getenv (\"TEMP\");\n\n  if (tempd.empty ())\n    tempd = octave_getenv (\"TMP\");\n\n#if defined (P_tmpdir)\n  if (tempd.empty ())\n    tempd = P_tmpdir;\n#endif\n\n  // Some versions of MinGW and MSVC either don't define P_tmpdir, or\n  // define it to a single backslash.  In such cases just use C:\\temp.\n  if (tempd.empty () || tempd == R\"(\\)\")\n    tempd = R\"(c:\\temp)\";\n\n#else\n\n#if defined (P_tmpdir)\n  if (tempd.empty ())\n    tempd = P_tmpdir;\n#else\n  if (tempd.empty ())\n    tempd = \"/tmp\";\n#endif\n\n#endif\n\n  return tempd;\n}\n\nstatic std::string\ncreate_extra_mex_object_file (bool interleaved_complex)\n{\n  std::string tmpl = get_temp_directory () + \"/oct-XXXXXX.c\";\n\n  char *ctmpl = new char [tmpl.length () + 1];\n\n  ctmpl = strcpy (ctmpl, tmpl.c_str ());\n\n  // mkostemps will open the file and return a file descriptor.  We\n  // won't worry about closing it because we will need the file until we\n  // are done and then the file will be closed when mkoctfile exits.\n  int fd = octave_mkostemps_wrapper (ctmpl, 2);\n\n  // Make C++ string from filled-in template.\n  std::string retval (ctmpl);\n  delete [] ctmpl;\n\n  // Write symbol definition(s) to file.\n  FILE *fid = fdopen (fd, \"w\");\n\n  fprintf (fid, \"const int __octave_mex_soversion__ = %d;\\n\",\n           OCTAVE_MEX_SOVERSION);\n\n  if (interleaved_complex)\n    fputs (\"const int __mx_has_interleaved_complex__ = 1;\\n\", fid);\n\n  fclose (fid);\n\n  return retval;\n}\n\nstatic std::string\ntmp_objfile_name ()\n{\n  std::string tmpl = get_temp_directory () + \"/oct-XXXXXX.o\";\n\n  char *ctmpl = new char [tmpl.length () + 1];\n\n  ctmpl = strcpy (ctmpl, tmpl.c_str ());\n\n  // mkostemps will open the file and return a file descriptor.  We\n  // won't worry about closing it because we will need the file until we\n  // are done and then the file will be closed when mkoctfile exits.\n  octave_mkostemps_wrapper (ctmpl, 2);\n\n  std::string retval (ctmpl);  // make C++ string from filled-in template\n  delete [] ctmpl;\n\n  return retval;\n}\n\nstatic void\nclean_up_tmp_files (const std::list<std::string>& tmp_files)\n{\n  for (const auto& file : tmp_files)\n    octave_unlink_wrapper (file.c_str ());\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\nextern \"C\"\nint\nwmain (int argc, wchar_t **wargv)\n{\n  char **sys_argv = convert_wargv_to_utf8 (argc, wargv);\n\n#else\nint\nmain (int argc, char **sys_argv)\n{\n#endif\n  std::vector<std::string> argv;\n\n  // Save args as vector of std::string objects for later processing.\n  for (int i_arg = 0; i_arg < argc; i_arg++)\n    argv.push_back (sys_argv[i_arg]);\n\n  if (argc == 1)\n    {\n      std::cout << usage_msg << std::endl;\n      return 1;\n    }\n\n  if (argc == 2 && (argv[1] == \"-V\" || argv[1] == \"--version\"))\n    {\n      std::cout << version_msg << std::endl;\n      return 0;\n    }\n\n  std::list<std::string> cfiles, ccfiles, f77files, tmp_files;\n  std::string output_ext = \".oct\";\n  std::string objfiles, libfiles, octfile, outputfile;\n  std::string incflags, defs, ldflags, pass_on_options;\n  std::string var_to_print;\n  bool debug = false;\n  bool verbose = false;\n  bool strip = false;\n  bool no_oct_file_strip_on_this_platform = is_true (\"%NO_OCT_FILE_STRIP%\");\n  bool compile_only = false;\n  bool link_stand_alone = false;\n  bool depend = false;\n  bool printonly = false;\n  bool output_file_option = false;\n  bool creating_mex_file = false;\n  bool r2017b_option = false;\n  bool r2018a_option = false;\n  // The default for this may change in the future.\n  bool mx_has_interleaved_complex = false;\n  bool pass_on_followup = false;\n\n  for (int i = 1; i < argc; i++)\n    {\n      std::string arg = argv[i];\n\n      std::string file;\n\n      bool found_unknown_dash_arg = false;\n\n      if (ends_with (arg, \".c\"))\n        {\n          file = arg;\n          cfiles.push_back (file);\n        }\n      else if (ends_with (arg, \".cc\") || ends_with (arg, \".cp\")\n               || ends_with (arg, \".cpp\") || ends_with (arg, \".CPP\")\n               || ends_with (arg, \".cxx\") || ends_with (arg, \".c++\")\n               || ends_with (arg, \".C\"))\n        {\n          file = arg;\n          ccfiles.push_back (file);\n        }\n      else if (ends_with (arg, \".f\") || ends_with (arg, \".F\")\n               || ends_with (arg, \"f90\") || ends_with (arg, \".F90\"))\n        {\n          file = arg;\n          f77files.push_back (file);\n        }\n      else if (ends_with (arg, \".o\") || ends_with (arg, \".obj\"))\n        {\n          file = arg;\n          objfiles += (' ' + quote_path (arg));\n        }\n      else if (ends_with (arg, \".lib\") || ends_with (arg, \".a\"))\n        {\n          file = arg;\n          libfiles += (' ' + quote_path (arg));\n        }\n      else if (arg == \"-d\" || arg == \"-debug\" || arg == \"--debug\"\n               || arg == \"-v\" || arg == \"-verbose\" ||  arg == \"--verbose\")\n        {\n          verbose = true;\n        }\n      else if (arg == \"-silent\" || arg == \"--silent\"\n               || arg == \"-quiet\" || arg == \"--quiet\")\n        {\n          // Ignored for now.\n        }\n      else if (arg == \"-h\" || arg == \"-?\" || arg == \"-help\" || arg == \"--help\")\n        {\n          std::cout << usage_msg << std::endl;\n          std::cout << help_msg << std::endl;\n          return 0;\n        }\n      else if (starts_with (arg, \"-I\"))\n        {\n          incflags += (' ' + quote_path (arg));\n        }\n      else if (arg == \"-idirafter\")\n        {\n          if (i < argc-1)\n            {\n              arg = argv[++i];\n              incflags += (\" -idirafter \" + arg);\n            }\n          else\n            std::cerr << \"mkoctfile: include directory name missing\"\n                      << std::endl;\n        }\n      else if (starts_with (arg, \"-D\"))\n        {\n          defs += (' ' + arg);\n        }\n      else if (arg == \"-largeArrayDims\" || arg == \"-compatibleArrayDims\")\n        {\n          std::cerr << \"mkoctfile: warning: -largeArrayDims and -compatibleArrayDims are accepted for compatibility, but ignored\" << std::endl;\n        }\n      else if (arg == \"-R2017b\")\n        {\n          if (r2018a_option)\n            {\n              std::cerr << \"mkoctfile: only one of -R2017b and -R2018a may be used\" << std::endl;\n              return 1;\n            }\n\n          r2017b_option = true;\n        }\n      else if (arg == \"-R2018a\")\n        {\n          if (r2017b_option)\n            {\n              std::cerr << \"mkoctfile: only one of -R2017b and -R2018a may be used\" << std::endl;\n              return 1;\n            }\n\n          r2018a_option = true;\n          mx_has_interleaved_complex = true;\n        }\n      else if (starts_with (arg, \"-Wl,\") || starts_with (arg, \"-l\")\n               || starts_with (arg, \"-L\") || starts_with (arg, \"-R\"))\n        {\n          ldflags += (' ' + quote_path (arg));\n        }\n#if ! defined (OCTAVE_USE_WINDOWS_API)\n      else if (arg == \"-pthread\")\n        {\n          ldflags += (' ' + arg);\n        }\n#endif\n      else if (arg == \"-M\" || arg == \"-depend\" || arg == \"--depend\")\n        {\n          depend = true;\n        }\n      else if (arg == \"-o\" || arg == \"-output\" || arg == \"--output\")\n        {\n          output_file_option = true;\n\n          if (i < argc-1)\n            {\n              arg = argv[++i];\n              outputfile = arg;\n            }\n          else\n            std::cerr << \"mkoctfile: output filename missing\" << std::endl;\n        }\n      else if (arg == \"-n\" || arg == \"--dry-run\" || arg == \"--just-print\")\n        {\n          printonly = true;\n        }\n      else if (arg == \"-p\" || arg == \"-print\" || arg == \"--print\")\n        {\n          if (i < argc-1)\n            {\n              ++i;\n\n              if (! var_to_print.empty ())\n                std::cerr << \"mkoctfile: warning: only one '\" << arg\n                          << \"' option will be processed\" << std::endl;\n              else\n                var_to_print = argv[i];\n            }\n          else\n            std::cerr << \"mkoctfile: --print requires argument\" << std::endl;\n        }\n      else if (arg == \"-s\" || arg == \"-strip\" || arg == \"--strip\")\n        {\n          if (no_oct_file_strip_on_this_platform)\n            std::cerr << \"mkoctfile: stripping disabled on this platform\"\n                      << std::endl;\n          else\n            strip = true;\n        }\n      else if (arg == \"-c\" || arg == \"-compile\" || arg == \"--compile\")\n        {\n          compile_only = true;\n        }\n      else if (arg == \"-g\")\n        {\n          debug = true;\n        }\n      else if (arg == \"-link-stand-alone\" || arg == \"--link-stand-alone\")\n        {\n          link_stand_alone = true;\n        }\n      else if (arg == \"-mex\" || arg == \"--mex\")\n        {\n          creating_mex_file = true;\n\n          incflags += \" -I.\";\n#if defined (_MSC_VER)\n          ldflags += \" -Wl,-export:mexFunction\";\n#endif\n          output_ext = \".mex\";\n        }\n      else if (starts_with (arg, \"-W\"))\n        {\n          pass_on_options += (' ' + arg);\n        }\n      else if (starts_with (arg, \"-O\"))\n        {\n          pass_on_options += (' ' + arg);\n        }\n      else if (starts_with (arg, \"-\"))\n        {\n          found_unknown_dash_arg = true;\n\n          // Pass through any unrecognized options.\n          pass_on_options += (' ' + arg);\n\n          // Don't pass on the final position which is typically a file.\n          // FIXME: Does it make sense to have that exception for the last\n          //        argument?\n          if (i < argc-2)\n            pass_on_followup = true;\n        }\n      else if (pass_on_followup)\n        {\n          // Pass through a followup argument.\n          pass_on_options += (' ' + arg);\n        }\n      else\n        {\n          std::cerr << \"mkoctfile: unrecognized argument \" << arg << std::endl;\n          return 1;\n        }\n\n      // reset pass_on_followup if anything but an unknown argument was found\n      if (! found_unknown_dash_arg)\n        pass_on_followup = false;\n\n      if (! file.empty () && octfile.empty ())\n        octfile = file;\n    }\n\n  std::map<std::string, std::string> vars\n    = make_vars_map (link_stand_alone, verbose, debug);\n\n  if (! var_to_print.empty ())\n    {\n      if (vars.find (var_to_print) == vars.end ())\n        {\n          std::cerr << \"mkoctfile: unknown variable '\" << var_to_print << \"'\"\n                    << std::endl;\n          return 1;\n        }\n\n      std::cout << vars[var_to_print] << std::endl;\n\n      return 0;\n    }\n\n  if (creating_mex_file)\n    {\n      if (vars[\"ALL_CFLAGS\"].find (\"-g\") != std::string::npos)\n        defs += \" -DMEX_DEBUG\";\n\n      if (! compile_only)\n        {\n          // Create tmp C source file that defines extern symbols that can be\n          // checked when loading the .mex file\n          // * to make sure the SOVERSION of liboctmex matches between the .mex\n          //   file and the Octave version attempting to load it,\n          // * and to indicate whether file was compiled expecting interleaved\n          //   complex values.\n          std::string tmp_file\n            = create_extra_mex_object_file (mx_has_interleaved_complex);\n\n          cfiles.push_back (tmp_file);\n\n          // clean up temporary C file with object files\n          tmp_files.push_back (tmp_file);\n        }\n\n      if (mx_has_interleaved_complex)\n        defs += \" -DMX_HAS_INTERLEAVED_COMPLEX=1\";\n    }\n  else\n    {\n      if (r2017b_option)\n        std::cerr << \"mkoctfile: warning: -R2017b option ignored unless creating mex file\"\n                  << std::endl;\n\n      if (r2018a_option)\n        std::cerr << \"mkoctfile: warning: -R2018a option ignored unless creating mex file\"\n                  << std::endl;\n    }\n\n  if (compile_only && output_file_option\n      && (cfiles.size () + ccfiles.size () + f77files.size ()) > 1)\n    {\n      std::cerr << \"mkoctfile: may not use -c and -o with multiple source files\"\n                << std::endl;\n      return 1;\n    }\n\n  std::string output_option;\n\n  if (link_stand_alone)\n    {\n      if (! outputfile.empty ())\n        output_option = \"-o \" + outputfile;\n    }\n  else\n    {\n      if (! outputfile.empty ())\n        {\n          // FIXME: should probably do a better job of finding the\n          // filename extension instead of just looking at the filename\n          // length.\n\n          octfile = outputfile;\n          std::size_t len = octfile.length ();\n          std::size_t len_ext = output_ext.length ();\n          if (len <= len_ext || octfile.substr (len-len_ext) != output_ext)\n            octfile += output_ext;\n        }\n      else\n        octfile = basename (octfile, true) + output_ext;\n    }\n\n  if (depend)\n    {\n      for (const auto& f : cfiles)\n        {\n          std::string dfile = basename (f, true) + \".d\", line;\n\n          octave_unlink_wrapper (dfile.c_str ());\n\n          std::string cmd\n            = (vars[\"CC\"] + ' ' + vars[\"DEPEND_FLAGS\"] + ' '\n               + vars[\"CPPFLAGS\"] + ' ' + vars[\"ALL_CFLAGS\"] + ' '\n               + incflags  + ' ' + defs + ' ' + quote_path (f));\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n          FILE *fd;\n          int size16;\n          wchar_t *wcmd = convert_utf8_to_utf16 (cmd.c_str (), -1, size16);\n          if (wcmd)\n            {\n              fd = ::_wpopen (wcmd, L\"r\");\n              delete[] wcmd;\n            }\n          else\n            fd = ::popen (cmd.c_str (), \"r\");\n\n          std::ofstream fo;\n          wchar_t *wfile = convert_utf8_to_utf16 (dfile.c_str (), -1, size16);\n          if (wfile)\n            {\n              fo.open (wfile);\n              delete[] wfile;\n            }\n          else\n            fo.open (dfile.c_str ());\n#else\n          FILE *fd = popen (cmd.c_str (), \"r\");\n\n          std::ofstream fo (dfile.c_str ());\n#endif\n\n          std::size_t pos;\n          while (! feof (fd))\n            {\n              line = get_line (fd);\n              if ((pos = line.rfind (\".o:\")) != std::string::npos)\n                {\n                  std::size_t spos = line.rfind ('/', pos);\n                  std::string ofile\n                    = (spos == std::string::npos\n                       ? line.substr (0, pos+2)\n                       : line.substr (spos+1, pos-spos+1));\n                  fo << \"pic/\" << ofile << ' ' << ofile << ' '\n                     << dfile << line.substr (pos) << std::endl;\n                }\n              else\n                fo << line << std::endl;\n            }\n          pclose (fd);\n          fo.close ();\n        }\n\n      for (const auto& f : ccfiles)\n        {\n          std::string dfile = basename (f, true) + \".d\", line;\n\n          octave_unlink_wrapper (dfile.c_str ());\n\n          std::string cmd\n            = (vars[\"CXX\"] + ' ' + vars[\"DEPEND_FLAGS\"] + ' '\n               + vars[\"CPPFLAGS\"] + ' ' + vars[\"ALL_CXXFLAGS\"] + ' '\n               + incflags  + ' ' + defs + ' ' + quote_path (f));\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n          FILE *fd;\n          int size16;\n          wchar_t *wcmd = convert_utf8_to_utf16 (cmd.c_str (), -1, size16);\n          if (wcmd)\n            {\n              fd = ::_wpopen (wcmd, L\"r\");\n              delete[] wcmd;\n            }\n          else\n            fd = ::popen (cmd.c_str (), \"r\");\n\n          std::ofstream fo;\n          wchar_t *wfile = convert_utf8_to_utf16 (dfile.c_str (), -1, size16);\n          if (wfile)\n            {\n              fo.open (wfile);\n              delete[] wfile;\n            }\n          else\n            fo.open (dfile.c_str ());\n#else\n          FILE *fd = popen (cmd.c_str (), \"r\");\n\n          std::ofstream fo (dfile.c_str ());\n#endif\n\n          std::size_t pos;\n          while (! feof (fd))\n            {\n              line = get_line (fd);\n              if ((pos = line.rfind (\".o:\")) != std::string::npos)\n                {\n                  std::size_t spos = line.rfind ('/', pos);\n                  std::string ofile\n                    = (spos == std::string::npos\n                       ? line.substr (0, pos+2)\n                       : line.substr (spos+1, pos-spos+1));\n                  fo << \"pic/\" << ofile << ' ' << ofile << ' '\n                     << dfile << line.substr (pos+2) << std::endl;\n                }\n              else\n                fo << line << std::endl;\n            }\n          pclose (fd);\n          fo.close ();\n        }\n\n      return 0;\n    }\n\n  for (const auto& f : f77files)\n    {\n      if (! vars[\"F77\"].empty ())\n        {\n          std::string o;\n          if (compile_only)\n            {\n              if (! outputfile.empty ())\n                o = outputfile;\n              else\n                o = basename (f, true) + \".o\";\n            }\n          else\n            {\n              o = tmp_objfile_name ();\n\n              tmp_files.push_back (o);\n\n              objfiles += (' ' + o);\n            }\n\n          std::string cmd\n            = (vars[\"F77\"] + \" -c \" + vars[\"FPICFLAG\"] + ' '\n               + vars[\"ALL_FFLAGS\"] + ' ' + incflags + ' ' + defs + ' '\n               + pass_on_options + ' ' + quote_path (f)\n               + \" -o \" + quote_path (o));\n\n          int status = run_command (cmd, verbose, printonly);\n\n          if (status)\n            return status;\n        }\n      else\n        {\n          std::cerr << \"mkoctfile: no way to compile Fortran file \" << f\n                    << std::endl;\n          return 1;\n        }\n    }\n\n  for (const auto& f : cfiles)\n    {\n      if (! vars[\"CC\"].empty ())\n        {\n          std::string o;\n          if (compile_only)\n            {\n              if (! outputfile.empty ())\n                o = outputfile;\n              else\n                o = basename (f, true) + \".o\";\n            }\n          else\n            {\n              o = tmp_objfile_name ();\n\n              tmp_files.push_back (o);\n\n              objfiles += (' ' + o);\n            }\n\n          std::string cmd\n            = (vars[\"CC\"] + \" -c \" + vars[\"CPPFLAGS\"] + ' '\n               + vars[\"CPICFLAG\"] + ' ' + vars[\"ALL_CFLAGS\"] + ' '\n               + pass_on_options + ' ' + incflags + ' ' + defs + ' '\n               + quote_path (f) + \" -o \" + quote_path (o));\n\n          int status = run_command (cmd, verbose, printonly);\n\n          if (status)\n            return status;\n        }\n      else\n        {\n          std::cerr << \"mkoctfile: no way to compile C file \" << f\n                    << std::endl;\n          return 1;\n        }\n    }\n\n  for (const auto& f : ccfiles)\n    {\n      if (! vars[\"CXX\"].empty ())\n        {\n          std::string o;\n          if (compile_only)\n            {\n              if (! outputfile.empty ())\n                o = outputfile;\n              else\n                o = basename (f, true) + \".o\";\n            }\n          else\n            {\n              o = tmp_objfile_name ();\n\n              tmp_files.push_back (o);\n\n              objfiles += (' ' + o);\n            }\n\n          std::string cmd\n            = (vars[\"CXX\"] + \" -c \" + vars[\"CPPFLAGS\"] + ' '\n               + vars[\"CXXPICFLAG\"] + ' ' + vars[\"ALL_CXXFLAGS\"] + ' '\n               + pass_on_options + ' ' + incflags + ' ' + defs + ' '\n               + quote_path (f) + \" -o \" + quote_path (o));\n\n          int status = run_command (cmd, verbose, printonly);\n\n          if (status)\n            return status;\n        }\n      else\n        {\n          std::cerr << \"mkoctfile: no way to compile C++ file \" << f\n                    << std::endl;\n          return 1;\n        }\n    }\n\n  // If we are only compiling, we are done.\n\n  if (compile_only)\n    return 0;\n\n  if (objfiles.empty ())\n    {\n      std::cerr << \"mkoctfile: no objects to link\" << std::endl;\n      return 1;\n    }\n\n  std::string octave_libs;\n\n  if (link_stand_alone)\n    {\n      if (! vars[\"CXXLD\"].empty ())\n        {\n          octave_libs = \"-L\" + quote_path (vars[\"OCTLIBDIR\"])\n                        + ' ' + vars[\"OCTAVE_LIBS\"];\n\n          std::string cmd\n            = (vars[\"CXXLD\"] + ' ' + vars[\"CPPFLAGS\"] + ' '\n               + vars[\"ALL_CXXFLAGS\"] + ' ' + vars[\"RDYNAMIC_FLAG\"] + ' '\n               + pass_on_options + ' ' + output_option + ' ' + objfiles + ' '\n               + libfiles + ' ' + ldflags + ' ' + vars[\"ALL_LDFLAGS\"] + ' '\n               + octave_libs + ' '\n               + vars[\"OCTAVE_LINK_OPTS\"] + ' ' + vars[\"OCTAVE_LINK_DEPS\"]);\n\n          int status = run_command (cmd, verbose, printonly);\n\n          clean_up_tmp_files (tmp_files);\n\n          if (status)\n            return status;\n        }\n      else\n        {\n          std::cerr\n            << \"mkoctfile: no way to link stand-alone executable file\"\n            << std::endl;\n          return 1;\n        }\n    }\n  else\n    {\n      if (creating_mex_file)\n        octave_libs = (\" -L\" + quote_path (vars[\"OCTLIBDIR\"]) + ' '\n                       + vars[\"LIBOCTMEX\"]);\n\n      std::string cmd\n        = (vars[\"CXXLD\"] + ' ' + vars[\"ALL_CXXFLAGS\"] + ' '\n           + pass_on_options + \" -o \" + quote_path (octfile) + ' '\n           + objfiles + ' ' + libfiles + ' ' + ldflags + ' '\n           + vars[\"DL_LDFLAGS\"] + ' ' + vars[\"LDFLAGS\"] + ' '\n           + octave_libs + ' ' + vars[\"OCT_LINK_OPTS\"]);\n\n      if (! creating_mex_file)\n        cmd += ' ' + vars[\"OCT_LINK_DEPS\"];\n\n#if defined (OCTAVE_USE_WINDOWS_API) || defined (CROSS) || defined (OCTAVE_LINK_ALL_DEPS)\n      if (! f77files.empty () && ! vars[\"FLIBS\"].empty ())\n        cmd += ' ' + vars[\"FLIBS\"];\n#endif\n\n      int status = run_command (cmd, verbose, printonly);\n\n      clean_up_tmp_files (tmp_files);\n\n      if (status)\n        return status;\n    }\n\n  if (strip)\n    {\n      std::string cmd = \"strip \" + quote_path (octfile);\n\n      int status = run_command (cmd, verbose, printonly);\n\n      if (status)\n        return status;\n    }\n\n  return 0;\n}\n"
  },
  {
    "path": "src/module.mk",
    "content": "%canon_reldir%_EXTRA_DIST =\n\n%canon_reldir%_CLEANFILES =\n%canon_reldir%_DISTCLEANFILES =\n%canon_reldir%_MAINTAINERCLEANFILES =\n\n## Search local directories before those specified by the user.\n\nSRC_DIR_CPPFLAGS = \\\n  -Iliboctave -I$(srcdir)/liboctave \\\n  -I$(srcdir)/liboctave/array \\\n  -I$(srcdir)/liboctave/numeric \\\n  -I$(srcdir)/liboctave/system \\\n  -I$(srcdir)/liboctave/util \\\n  -Iliboctave/wrappers -I$(srcdir)/liboctave/wrappers \\\n  -Ilibinterp -I$(srcdir)/libinterp \\\n  -Ilibinterp/corefcn -I$(srcdir)/libinterp/corefcn \\\n  -I$(srcdir)/libinterp/octave-value \\\n  -I$(srcdir)/libinterp/template-inst \\\n  -Ilibmex -I$(srcdir)/libmex \\\n  -I$(srcdir)/%reldir%\n\nEXTRA_DIST += \\\n  %reldir%/main.in.cc \\\n  %reldir%/mkoctfile.in.cc \\\n  %reldir%/octave-build-info.in.cc \\\n  %reldir%/octave-config.in.cc\n\nbin_PROGRAMS += \\\n  %reldir%/mkoctfile \\\n  %reldir%/octave \\\n  %reldir%/octave-cli \\\n  %reldir%/octave-config\n\nOCTAVE_INTERPRETER_TARGETS += \\\n  $(bin_PROGRAMS) \\\n  $(OCTAVE_VERSION_LINKS)\n\noctinclude_HEADERS += \\\n  %reldir%/octave-build-info.h\n\nnoinst_HEADERS += \\\n  %reldir%/display-available.h \\\n  %reldir%/octave-qsvghandler.h \\\n  %reldir%/shared-fcns.h \\\n  %reldir%/shared-sysdep.h\n\nOCTAVE_VERSION_LINKS += %reldir%/octave-cli-$(version)$(EXEEXT)\n\nif AMCOND_BUILD_QT_GUI\n  archlib_PROGRAMS += %reldir%/octave-gui\n  OCTAVE_VERSION_LINKS += %reldir%/octave-gui-$(version)$(EXEEXT)\n\n  OCTAVE_INTERPRETER_TARGETS += %reldir%/octave-gui$(EXEEXT)\nendif\n\nif AMCOND_BUILD_QT_GUI\n  archlib_PROGRAMS += %reldir%/octave-svgconvert\n  OCTAVE_INTERPRETER_TARGETS += %reldir%/octave-svgconvert$(EXEEXT)\nendif\n\nOCTAVE_CORE_LIBS = \\\n  libmex/liboctmex.la \\\n  libinterp/liboctinterp.la \\\n  liboctave/liboctave.la \\\n  libgnu/libgnu.la\n\nnodist_%canon_reldir%_octave_SOURCES = %reldir%/main.cc\n\n%canon_reldir%_octave_SOURCES = %reldir%/display-available.c\n\n%canon_reldir%_octave_LDADD = \\\n  liboctave/wrappers/libwrappers.la \\\n  libgnu/libgnu.la \\\n  $(X11_LIBS) \\\n  $(WAYLAND_CLIENT_LIBS) \\\n  $(CARBON_LIBS) \\\n  $(GNULIB_LINK_DEPS)\n\n%canon_reldir%_octave_LDFLAGS = \\\n  $(AM_LDFLAGS) \\\n  $(NO_UNDEFINED_LDFLAG) \\\n  $(OCTAVE_LINK_OPTS) \\\n  $(WARN_LDFLAGS) \\\n  $(OCTAVE_UNICODE_EXE_LDFLAGS) \\\n  $(WAYLAND_CLIENT_LDFLAGS)\n\n\nif AMCOND_BUILD_QT_GUI\n  OCTAVE_CPPFLAGS = -DHAVE_OCTAVE_QT_GUI\nendif\n\n%canon_reldir%_octave_CPPFLAGS = \\\n  $(SRC_DIR_CPPFLAGS) \\\n  $(OCTAVE_CPPFLAGS) \\\n  $(WAYLAND_CLIENT_CPPFLAGS)\n\n%canon_reldir%_octave_cli_SOURCES = %reldir%/main-cli.cc\nnodist_%canon_reldir%_octave_cli_SOURCES = %reldir%/octave-build-info.cc\n\n%canon_reldir%_octave_cli_LDADD = \\\n  $(OCTAVE_CORE_LIBS) \\\n  $(OCTAVE_LINK_DEPS)\n\n%canon_reldir%_octave_cli_LDFLAGS = \\\n  $(NO_UNDEFINED_LDFLAG) \\\n  $(OCTAVE_LINK_OPTS) \\\n  $(OCTAVE_CLI_LTLDFLAGS) \\\n  $(WARN_LDFLAGS) \\\n  $(OCTAVE_UNICODE_EXE_LDFLAGS)\n\n%canon_reldir%_octave_cli_CPPFLAGS = \\\n  $(SRC_DIR_CPPFLAGS) \\\n  $(OCTAVE_CPPFLAGS)\n\nif AMCOND_BUILD_QT_GUI\n  %canon_reldir%_octave_gui_SOURCES = %reldir%/main-gui.cc\n  nodist_%canon_reldir%_octave_gui_SOURCES = %reldir%/octave-build-info.cc\n  OCTAVE_GUI_LIBS = libgui/liboctgui.la\n  OCTAVE_GUI_CPPFLAGS = -I$(srcdir)/libgui -Ilibgui/src -I$(srcdir)/libgui/src\nendif\n\n%canon_reldir%_octave_gui_CPPFLAGS = \\\n  $(SRC_DIR_CPPFLAGS) \\\n  $(OCTAVE_GUI_CPPFLAGS)\n\n%canon_reldir%_octave_gui_LDADD = \\\n  $(OCTAVE_GUI_LIBS) \\\n  $(OCTAVE_CORE_LIBS) \\\n  $(OCTAVE_GUI_LINK_DEPS)\n\n%canon_reldir%_octave_gui_LDFLAGS = \\\n  $(NO_UNDEFINED_LDFLAG) \\\n  $(OCTAVE_GUI_LINK_OPTS) \\\n  $(OCTAVE_GUI_LTLDFLAGS) \\\n  $(WARN_LDFLAGS) \\\n  $(OCTAVE_UNICODE_EXE_LDFLAGS)\n\n%canon_reldir%_octave_svgconvert_SOURCES = %reldir%/octave-svgconvert.cc\n\n%canon_reldir%_octave_svgconvert_CPPFLAGS = $(QT_CPPFLAGS)\n\n%canon_reldir%_octave_svgconvert_LDADD = $(QT_LIBS)\n\n%canon_reldir%_octave_svgconvert_LDFLAGS = \\\n  $(QT_LDFLAGS) \\\n  $(OCTAVE_UNICODE_EXE_LDFLAGS)\n\n%canon_reldir%_mkoctfile_SOURCES =\n\nnodist_%canon_reldir%_mkoctfile_SOURCES = %reldir%/mkoctfile.cc\n\n%canon_reldir%_mkoctfile_LDADD = \\\n  liboctave/wrappers/libwrappers.la \\\n  libgnu/libgnu.la $(LIBS)\n\n%canon_reldir%_mkoctfile_LDFLAGS = \\\n  $(OCTAVE_UNICODE_EXE_LDFLAGS)\n\n%canon_reldir%_mkoctfile_CPPFLAGS = \\\n  $(SRC_DIR_CPPFLAGS) \\\n  $(OCTAVE_CPPFLAGS) \\\n  -DOCTAVE_MEX_SOVERSION=\"$(OCTAVE_LIBOCTMEX_SOVERSION_MAJOR)\"\n\n%canon_reldir%_octave_config_SOURCES =\n\nnodist_%canon_reldir%_octave_config_SOURCES = %reldir%/octave-config.cc\n\n%canon_reldir%_octave_config_LDADD = \\\n  libinterp/corefcn/libcorefcn.la \\\n  libgnu/libgnu.la \\\n  $(LIBS)\n\n%canon_reldir%_octave_config_LDFLAGS = \\\n  $(OCTAVE_UNICODE_EXE_LDFLAGS)\n\n%canon_reldir%_octave_config_CPPFLAGS = \\\n  $(SRC_DIR_CPPFLAGS) \\\n  $(OCTAVE_CPPFLAGS)\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\nmostlyclean-local: src-mostlyclean-local\n.PHONY: src-mostlyclean-local\n\nif AMCOND_CROSS_TOOLS\n\n## Building cross mkoctfile.\n\nOCTAVE_CROSS_TOOLS += %reldir%/$(host_triplet)-mkoctfile$(BUILD_EXEEXT)\n\nif AMCOND_RELOCATE_ALL\n  OCTAVE_REPLACE_PREFIX_CPPFLAGS = -DOCTAVE_REPLACE_PREFIX\nendif\n\n%reldir%/$(host_triplet)-mkoctfile$(BUILD_EXEEXT): %reldir%/$(host_triplet)-mkoctfile.cc\n\t$(BUILD_CXX) -o %reldir%/$(host_triplet)-mkoctfile$(BUILD_EXEEXT) $(OCTAVE_REPLACE_PREFIX_CPPFLAGS) -DOCTAVE_MEX_SOVERSION=\"$(OCTAVE_LIBOCTMEX_SOVERSION_MAJOR)\" -DCROSS=1 $(DEFAULT_INCLUDES) $(BUILD_CXXFLAGS) $(BUILD_LDFLAGS) -I$(srcdir)/src %reldir%/$(host_triplet)-mkoctfile.cc\n\n%reldir%/$(host_triplet)-mkoctfile.cc: %reldir%/mkoctfile.in.cc build-aux/subst-cross-config-vals.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-cross-config-vals.sh)\n\n## Building cross octave-config.\n\nOCTAVE_CROSS_TOOLS += %reldir%/$(host_triplet)-octave-config$(BUILD_EXEEXT)\n\n%reldir%/$(host_triplet)-octave-config$(BUILD_EXEEXT): %reldir%/$(host_triplet)-octave-config.cc\n\t$(BUILD_CXX) -o %reldir%/$(host_triplet)-octave-config$(BUILD_EXEEXT) -DCROSS=1 $(DEFAULT_INCLUDES) $(BUILD_CXXFLAGS) $(BUILD_LDFLAGS) -I$(srcdir)/src %reldir%/$(host_triplet)-octave-config.cc\n\n%reldir%/$(host_triplet)-octave-config.cc: %reldir%/octave-config.in.cc build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)\n\nsrc-mostlyclean-local:\n\t-rm -f $(OCTAVE_CROSS_TOOLS)\n\nelse\n\nsrc-mostlyclean-local:\n\nendif\n\n%reldir%/octave-config.cc: %reldir%/octave-config.in.cc build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)\n\n%reldir%/mkoctfile.cc: %reldir%/mkoctfile.in.cc build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)\n\n%reldir%/main.cc: %reldir%/main.in.cc build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)\n\n%reldir%/octave-build-info.cc: %reldir%/octave-build-info.in.cc HG-ID | %reldir%/$(octave_dirstamp)\n\t$(AM_V_GEN)$(build-info-commands)\n\nALL_LOCAL_TARGETS += $(OCTAVE_CROSS_TOOLS)\n\ninstall-exec-hook: make-version-links\n\nuninstall-local: remove-version-links\n\nmake-version-links:\n\tcd $(DESTDIR)$(bindir) && \\\n\tfor f in $(notdir $(basename $(bin_PROGRAMS))); do \\\n\t  mv $$f$(EXEEXT) $$f-$(version)$(EXEEXT) && \\\n\t    $(LN_S) $$f-$(version)$(EXEEXT) $$f$(EXEEXT); \\\n\tdone\n\nremove-version-links:\n\tfor f in $(notdir $(basename $(bin_PROGRAMS))); do \\\n\t  rm -f $(DESTDIR)$(bindir)/$$f-$(version)$(EXEEXT); \\\n\tdone\n\n.PHONY: make-version-links remove-version-links\n\n## We need these filenames in the build tree because the wrapper\n## program (main.cc) will try to invoke the versioned binaries.\n\n%reldir%/octave-cli-$(version)$(EXEEXT): %reldir%/octave-cli$(EXEEXT)\n\t$(AM_V_GEN)rm -f $@ && \\\n\tcd $(@D) && $(LN_S) $(<F) $(@F)\n\n%reldir%/octave-gui-$(version)$(EXEEXT): %reldir%/octave-gui$(EXEEXT)\n\t$(AM_V_GEN)rm -f $@ && \\\n\tcd $(@D) && $(LN_S) $(<F) $(@F)\n\n%canon_reldir%_CLEANFILES += \\\n  $(OCTAVE_VERSION_LINKS) \\\n  %reldir%/main.cc \\\n  %reldir%/mkoctfile.cc \\\n  %reldir%/octave-build-info.cc \\\n  %reldir%/octave-config.cc\n\nCLEANFILES += $(%canon_reldir%_CLEANFILES)\nDISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)\nMAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)\n\nsrc-clean:\n\trm -f $(%canon_reldir%_CLEANFILES)\n\nsrc-distclean: src-clean\n\trm -f $(%canon_reldir%_DISTCLEANFILES)\n\nsrc-maintainer-clean: src-distclean\n\trm -f $(%canon_reldir%_MAINTAINERCLEANFILES)\n"
  },
  {
    "path": "src/octave-build-info.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if ! defined (octave_octave_build_info_h)\n#define octave_octave_build_info_h 1\n\n#include \"octave-config.h\"\n\n#include <string>\n\nextern std::string octave_hg_id ();\n\n#endif\n"
  },
  {
    "path": "src/octave-build-info.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2016-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include \"octave-build-info.h\"\n\nstd::string\noctave_hg_id ()\n{\n  return \"%OCTAVE_HG_ID%\";\n}\n"
  },
  {
    "path": "src/octave-config.in.cc",
    "content": "// %NO_EDIT_WARNING%\n\n////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <string>\n#include <map>\n#include <iostream>\n#include <algorithm>\n#include <cstdlib>\n\n#if ! defined (OCTAVE_PREFIX)\n#  define OCTAVE_PREFIX %OCTAVE_PREFIX%\n#endif\n\n#if ! defined (OCTAVE_EXEC_PREFIX)\n#  define OCTAVE_EXEC_PREFIX %OCTAVE_EXEC_PREFIX%\n#endif\n\n#ifndef OCTAVE_UNUSED\n#  define OCTAVE_UNUSED\n#endif\n\n#include \"shared-fcns.h\"\n\nstatic std::map<std::string, std::string> vars;\n\nstatic std::string usage_msg = \"usage: octave-config [options]\";\n\nstatic std::string help_msg =\n  \"\\n\"\n  \"Options:\\n\"\n  \"\\n\"\n  \"  -h, -?, --help        Print this message.\\n\"\n  \"\\n\"\n  \"  --m-site-dir          Print the name of the directory where Octave\\n\"\n  \"                        expects to find locally installed .m files.\\n\"\n  \"\\n\"\n  \"  --oct-site-dir        Print the name of the directory where Octave\\n\"\n  \"                        expects to find locally installed .oct files.\\n\"\n  \"\\n\"\n  \"  -p VAR, --print VAR   Print the value of the given configuration\\n\"\n  \"                        variable VAR.  Recognized variables are:\\n\"\n  \"\\n\"\n  \"                          API_VERSION            LOCALARCHLIBDIR\\n\"    \n  \"                          ARCHLIBDIR             LOCALFCNFILEDIR\\n\"    \n  \"                          BINDIR                 LOCALOCTFILEDIR\\n\"    \n  \"                          CANONICAL_HOST_TYPE    LOCALSTARTUPFILEDIR\\n\"\n  \"                          DATADIR                LOCALVERARCHLIBDIR\\n\" \n  \"                          DATAROOTDIR            LOCALVERFCNFILEDIR\\n\" \n  \"                          DEFAULT_PAGER          LOCALVEROCTFILEDIR\\n\" \n  \"                          EXEC_PREFIX            MAN1DIR\\n\"            \n  \"                          EXEEXT                 MAN1EXT\\n\"            \n  \"                          FCNFILEDIR             MANDIR\\n\"             \n  \"                          IMAGEDIR               OCTAVE_EXEC_HOME\\n\"   \n  \"                          INCLUDEDIR             OCTAVE_HOME\\n\"        \n  \"                          INFODIR                OCTDATADIR\\n\"         \n  \"                          INFOFILE               OCTDOCDIR\\n\"          \n  \"                          LIBDIR                 OCTFILEDIR\\n\"         \n  \"                          LIBEXECDIR             OCTFONTSDIR\\n\"        \n  \"                          LOCALAPIARCHLIBDIR     OCTINCLUDEDIR\\n\"      \n  \"                          LOCALAPIFCNFILEDIR     OCTLIBDIR\\n\"          \n  \"                          LOCALAPIOCTFILEDIR     STARTUPFILEDIR\\n\"     \n  \"                          LOCALAPIPKGDIR         VERSION\\n\"            \n  \"\\n\"\n  \"  -v, --version         Print the Octave version number.\\n\"\n  \"\\n\";\n\nstatic void\ninitialize ()\n{\n  set_octave_home ();\n\n  vars[\"OCTAVE_HOME\"] = Voctave_home;\n  vars[\"OCTAVE_EXEC_HOME\"] = Voctave_exec_home;\n\n  vars[\"API_VERSION\"] = %OCTAVE_API_VERSION%;\n  vars[\"CANONICAL_HOST_TYPE\"] = %OCTAVE_CANONICAL_HOST_TYPE%;\n  vars[\"DEFAULT_PAGER\"] = %OCTAVE_DEFAULT_PAGER%;\n  vars[\"EXEEXT\"] = %OCTAVE_EXEEXT%;\n  vars[\"MAN1EXT\"] = %OCTAVE_MAN1EXT%;\n  vars[\"VERSION\"] = %OCTAVE_VERSION%;\n\n  vars[\"ARCHLIBDIR\"] = prepend_octave_exec_home (%OCTAVE_ARCHLIBDIR%);\n  vars[\"BINDIR\"] = prepend_octave_exec_home (%OCTAVE_BINDIR%);\n  vars[\"DATADIR\"] = prepend_octave_home (%OCTAVE_DATADIR%);\n  vars[\"DATAROOTDIR\"] = prepend_octave_home (%OCTAVE_DATAROOTDIR%);\n  vars[\"FCNFILEDIR\"] = prepend_octave_home (%OCTAVE_FCNFILEDIR%);\n  vars[\"IMAGEDIR\"] = prepend_octave_home (%OCTAVE_IMAGEDIR%);\n  vars[\"INCLUDEDIR\"] = prepend_octave_home (%OCTAVE_INCLUDEDIR%);\n  vars[\"INFODIR\"] = prepend_octave_home (%OCTAVE_INFODIR%);\n  vars[\"INFOFILE\"] = prepend_octave_home (%OCTAVE_INFOFILE%);\n  vars[\"LIBDIR\"] = prepend_octave_exec_home (%OCTAVE_LIBDIR%);\n  vars[\"LIBEXECDIR\"] = prepend_octave_exec_home (%OCTAVE_LIBEXECDIR%);\n  vars[\"LOCALAPIARCHLIBDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIARCHLIBDIR%);\n  vars[\"LOCALAPIFCNFILEDIR\"] = prepend_octave_home (%OCTAVE_LOCALAPIFCNFILEDIR%);\n  vars[\"LOCALAPIOCTFILEDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIOCTFILEDIR%);\n  vars[\"LOCALAPIPKGDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIPKGDIR%);\n  vars[\"LOCALARCHLIBDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALARCHLIBDIR%);\n  vars[\"LOCALFCNFILEDIR\"] = prepend_octave_home (%OCTAVE_LOCALFCNFILEDIR%);\n  vars[\"LOCALOCTFILEDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALOCTFILEDIR%);\n  vars[\"LOCALSTARTUPFILEDIR\"] = prepend_octave_home (%OCTAVE_LOCALSTARTUPFILEDIR%);\n  vars[\"LOCALVERARCHLIBDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALVERARCHLIBDIR%);\n  vars[\"LOCALVERFCNFILEDIR\"] = prepend_octave_home (%OCTAVE_LOCALVERFCNFILEDIR%);\n  vars[\"LOCALVEROCTFILEDIR\"] = prepend_octave_exec_home (%OCTAVE_LOCALVEROCTFILEDIR%);\n  vars[\"MAN1DIR\"] = prepend_octave_home (%OCTAVE_MAN1DIR%);\n  vars[\"MANDIR\"] = prepend_octave_home (%OCTAVE_MANDIR%);\n  vars[\"OCTDATADIR\"] = prepend_octave_home (%OCTAVE_OCTDATADIR%);\n  vars[\"OCTDOCDIR\"] = prepend_octave_home (%OCTAVE_OCTDOCDIR%);\n  vars[\"OCTFILEDIR\"] = prepend_octave_exec_home (%OCTAVE_OCTFILEDIR%);\n  vars[\"OCTFONTSDIR\"] = prepend_octave_home (%OCTAVE_OCTFONTSDIR%);\n  vars[\"OCTINCLUDEDIR\"] = prepend_octave_home (%OCTAVE_OCTINCLUDEDIR%);\n  vars[\"OCTLIBDIR\"] = prepend_octave_exec_home (%OCTAVE_OCTLIBDIR%);\n  vars[\"STARTUPFILEDIR\"] = prepend_octave_home (%OCTAVE_STARTUPFILEDIR%);\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\nextern \"C\"\nint\nwmain (int argc, wchar_t **wargv)\n{\n  char **argv = convert_wargv_to_utf8 (argc, wargv);\n\n#else\nint\nmain (int argc, char **argv)\n{\n#endif\n  initialize ();\n\n  if (argc == 1)\n    {\n      std::cout << usage_msg << std::endl;\n      return 1;\n    }\n\n  for (int i = 1; i < argc; i++)\n    {\n      std::string arg (argv[i]);\n\n      if (arg == \"-h\" || arg == \"-?\" || arg == \"--help\")\n        {\n          std::cout << usage_msg << std::endl;\n          std::cout << help_msg;\n          return 0;\n        }\n      else if (arg == \"--m-site-dir\")\n        std::cout << vars[\"LOCALVERFCNFILEDIR\"] << std::endl;\n      else if (arg == \"--oct-site-dir\")\n        std::cout << vars[\"LOCALVEROCTFILEDIR\"] << std::endl;\n      else if (arg == \"-v\" || arg == \"--version\")\n        std::cout << vars[\"VERSION\"] << std::endl;\n      else if (arg == \"-p\" || arg == \"--print\")\n        {\n          if (i < argc-1)\n            {\n              arg = argv[++i];\n              std::cout << vars[arg] << std::endl;\n            }\n          else\n            {\n              std::cerr << \"octave-config: \" << arg\n                        << \" options requires argument\" << std::endl;\n              return 1;\n            }\n        }\n      else\n        {\n          std::cerr << \"octave-config: unrecognized argument \" << arg\n                    << std::endl;\n          return 1;\n        }\n    }\n\n  return 0;\n}\n"
  },
  {
    "path": "src/octave-qsvghandler.h",
    "content": "/****************************************************************************\n**\n** Copyright (C) 2016 The Qt Company Ltd.\n** Contact: https://www.qt.io/licensing/\n**\n** This file is part of the Qt SVG module of the Qt Toolkit.\n**\n** $QT_BEGIN_LICENSE:LGPL$\n** Commercial License Usage\n** Licensees holding valid commercial Qt licenses may use this file in\n** accordance with the commercial license agreement provided with the\n** Software or, alternatively, in accordance with the terms contained in\n** a written agreement between you and The Qt Company. For licensing terms\n** and conditions see https://www.qt.io/terms-conditions. For further\n** information use the contact form at https://www.qt.io/contact-us.\n**\n** GNU Lesser General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU Lesser\n** General Public License version 3 as published by the Free Software\n** Foundation and appearing in the file LICENSE.LGPL3 included in the\n** packaging of this file. Please review the following information to\n** ensure the GNU Lesser General Public License version 3 requirements\n** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.\n**\n** GNU General Public License Usage\n** Alternatively, this file may be used under the terms of the GNU\n** General Public License version 2.0 or (at your option) the GNU General\n** Public license version 3 or any later version approved by the KDE Free\n** Qt Foundation. The licenses are as published by the Free Software\n** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3\n** included in the packaging of this file. Please review the following\n** information to ensure the GNU General Public License requirements will\n** be met: https://www.gnu.org/licenses/gpl-2.0.html and\n** https://www.gnu.org/licenses/gpl-3.0.html.\n**\n** $QT_END_LICENSE$\n**\n****************************************************************************/\n\n// --------------------------------------------------------------------------\n// Build a QPainterPath from the \"d\" attribute of a path element\n// These functions were originally extracted from Qt-5.12 sources\n//   (qsvghandler.cpp)\n// Modifications:\n//   * use static_cast<qreal> to avoid old style cast warning.\n// Some portions are extracted from Qt6.5:\n// https://github.com/qt/qtsvg/blob/6.5.0/src/svg/qsvghandler.cpp\n// --------------------------------------------------------------------------\n\n#include <cmath>\n\n#include <QPainterPath>\n\nstatic inline bool isDigit(ushort ch)\n{\n    static quint16 magic = 0x3ff;\n    return ((ch >> 4) == 3) && (magic >> (ch & 15));\n}\n\nstatic qreal toDouble(const QChar *&str)\n{\n    const int maxLen = 255;//technically doubles can go til 308+ but whatever\n    char temp[maxLen+1];\n    int pos = 0;\n\n    if (*str == QLatin1Char('-')) {\n        temp[pos++] = '-';\n        ++str;\n    } else if (*str == QLatin1Char('+')) {\n        ++str;\n    }\n    while (isDigit(str->unicode()) && pos < maxLen) {\n        temp[pos++] = str->toLatin1();\n        ++str;\n    }\n    if (*str == QLatin1Char('.') && pos < maxLen) {\n        temp[pos++] = '.';\n        ++str;\n    }\n    while (isDigit(str->unicode()) && pos < maxLen) {\n        temp[pos++] = str->toLatin1();\n        ++str;\n    }\n    bool exponent = false;\n    if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) {\n        exponent = true;\n        temp[pos++] = 'e';\n        ++str;\n        if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {\n            temp[pos++] = str->toLatin1();\n            ++str;\n        }\n        while (isDigit(str->unicode()) && pos < maxLen) {\n            temp[pos++] = str->toLatin1();\n            ++str;\n        }\n    }\n\n    temp[pos] = '\\0';\n\n    qreal val;\n    if (!exponent && pos < 10) {\n        int ival = 0;\n        const char *t = temp;\n        bool neg = false;\n        if(*t == '-') {\n            neg = true;\n            ++t;\n        }\n        while(*t && *t != '.') {\n            ival *= 10;\n            ival += (*t) - '0';\n            ++t;\n        }\n        if(*t == '.') {\n            ++t;\n            int div = 1;\n            while(*t) {\n                ival *= 10;\n                ival += (*t) - '0';\n                div *= 10;\n                ++t;\n            }\n            val = static_cast<qreal> (ival)/static_cast<qreal> (div);\n        } else {\n            val = ival;\n        }\n        if (neg)\n            val = -val;\n    } else {\n        val = QByteArray::fromRawData(temp, pos).toDouble();\n        // Do not tolerate values too wild to be represented normally by floats\n        if (std::fpclassify (static_cast<float> (val)) != FP_NORMAL)\n            val = 0;\n    }\n    return val;\n\n}\n\nstatic inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points,\n                                     const char *pattern = nullptr)\n{\n    const size_t patternLen = qstrlen(pattern);\n    while (str->isSpace())\n        ++str;\n    while (isDigit(str->unicode()) ||\n           *str == QLatin1Char('-') || *str == QLatin1Char('+') ||\n           *str == QLatin1Char('.')) {\n\n        if (patternLen && pattern[points.size() % patternLen] == 'f') {\n            // flag expected, may only be 0 or 1\n            if (*str != QLatin1Char('0') && *str != QLatin1Char('1'))\n                return;\n            points.append(*str == QLatin1Char('0') ? 0.0 : 1.0);\n            ++str;\n        } else {\n            points.append(toDouble(str));\n        }\n\n        while (str->isSpace())\n            ++str;\n        if (*str == QLatin1Char(','))\n            ++str;\n\n        //eat the rest of space\n        while (str->isSpace())\n            ++str;\n    }\n}\n\nstatic void pathArcSegment(QPainterPath &path,\n                           qreal xc, qreal yc,\n                           qreal th0, qreal th1,\n                           qreal rx, qreal ry, qreal xAxisRotation)\n{\n    qreal sinTh, cosTh;\n    qreal a00, a01, a10, a11;\n    qreal x1, y1, x2, y2, x3, y3;\n    qreal t;\n    qreal thHalf;\n\n    sinTh = qSin(xAxisRotation * (3.141592653589793 / 180.0));\n    cosTh = qCos(xAxisRotation * (3.141592653589793 / 180.0));\n\n    a00 =  cosTh * rx;\n    a01 = -sinTh * ry;\n    a10 =  sinTh * rx;\n    a11 =  cosTh * ry;\n\n    thHalf = 0.5 * (th1 - th0);\n    t = (8.0 / 3.0) * qSin(thHalf * 0.5) * qSin(thHalf * 0.5) / qSin(thHalf);\n    x1 = xc + qCos(th0) - t * qSin(th0);\n    y1 = yc + qSin(th0) + t * qCos(th0);\n    x3 = xc + qCos(th1);\n    y3 = yc + qSin(th1);\n    x2 = x3 + t * qSin(th1);\n    y2 = y3 - t * qCos(th1);\n\n    path.cubicTo(a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,\n                 a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,\n                 a00 * x3 + a01 * y3, a10 * x3 + a11 * y3);\n}\n\n// the arc handling code underneath is from XSVG (BSD license)\n/*\n * Copyright  2002 USC/Information Sciences Institute\n *\n * Permission to use, copy, modify, distribute, and sell this software\n * and its documentation for any purpose is hereby granted without\n * fee, provided that the above copyright notice appear in all copies\n * and that both that copyright notice and this permission notice\n * appear in supporting documentation, and that the name of\n * Information Sciences Institute not be used in advertising or\n * publicity pertaining to distribution of the software without\n * specific, written prior permission.  Information Sciences Institute\n * makes no representations about the suitability of this software for\n * any purpose.  It is provided \"as is\" without express or implied\n * warranty.\n *\n * INFORMATION SCIENCES INSTITUTE DISCLAIMS ALL WARRANTIES WITH REGARD\n * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL INFORMATION SCIENCES\n * INSTITUTE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL\n * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA\n * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n * PERFORMANCE OF THIS SOFTWARE.\n *\n */\nstatic void pathArc(QPainterPath &path,\n                    qreal               rx,\n                    qreal               ry,\n                    qreal               x_axis_rotation,\n                    int         large_arc_flag,\n                    int         sweep_flag,\n                    qreal               x,\n                    qreal               y,\n                    qreal curx, qreal cury)\n{\n    const qreal Pr1 = rx * rx;\n    const qreal Pr2 = ry * ry;\n\n    if (!Pr1 || !Pr2)\n        return;\n\n    qreal sin_th, cos_th;\n    qreal a00, a01, a10, a11;\n    qreal x0, y0, x1, y1, xc, yc;\n    qreal d, sfactor, sfactor_sq;\n    qreal th0, th1, th_arc;\n    int i, n_segs;\n    qreal dx, dy, dx1, dy1, Px, Py, check;\n\n    rx = qAbs(rx);\n    ry = qAbs(ry);\n\n    sin_th = qSin(x_axis_rotation * (3.141592653589793 / 180.0));\n    cos_th = qCos(x_axis_rotation * (3.141592653589793 / 180.0));\n\n    dx = (curx - x) / 2.0;\n    dy = (cury - y) / 2.0;\n    dx1 =  cos_th * dx + sin_th * dy;\n    dy1 = -sin_th * dx + cos_th * dy;\n    Px = dx1 * dx1;\n    Py = dy1 * dy1;\n    /* Spec : check if radii are large enough */\n    check = Px / Pr1 + Py / Pr2;\n    if (check > 1) {\n        rx = rx * qSqrt(check);\n        ry = ry * qSqrt(check);\n    }\n\n    a00 =  cos_th / rx;\n    a01 =  sin_th / rx;\n    a10 = -sin_th / ry;\n    a11 =  cos_th / ry;\n    x0 = a00 * curx + a01 * cury;\n    y0 = a10 * curx + a11 * cury;\n    x1 = a00 * x + a01 * y;\n    y1 = a10 * x + a11 * y;\n    /* (x0, y0) is current point in transformed coordinate space.\n       (x1, y1) is new point in transformed coordinate space.\n\n       The arc fits a unit-radius circle in this space.\n    */\n    d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);\n    if (!d)\n        return;\n    sfactor_sq = 1.0 / d - 0.25;\n    if (sfactor_sq < 0) sfactor_sq = 0;\n    sfactor = qSqrt(sfactor_sq);\n    if (sweep_flag == large_arc_flag) sfactor = -sfactor;\n    xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);\n    yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);\n    /* (xc, yc) is center of the circle. */\n\n    th0 = qAtan2(y0 - yc, x0 - xc);\n    th1 = qAtan2(y1 - yc, x1 - xc);\n\n    th_arc = th1 - th0;\n    if (th_arc < 0 && sweep_flag)\n        th_arc += 2 * 3.141592653589793;\n    else if (th_arc > 0 && !sweep_flag)\n        th_arc -= 2 * 3.141592653589793;\n\n    n_segs = qCeil(qAbs(th_arc / (3.141592653589793 * 0.5 + 0.001)));\n\n    for (i = 0; i < n_segs; i++) {\n        pathArcSegment(path, xc, yc,\n                       th0 + i * th_arc / n_segs,\n                       th0 + (i + 1) * th_arc / n_segs,\n                       rx, ry, x_axis_rotation);\n    }\n}\n\n#if HAVE_QSTRINGVIEW\nstatic QTransform parseTransformationMatrix(QStringView value)\n#else\nstatic QTransform parseTransformationMatrix(const QStringRef &value)\n#endif\n{\n    if (value.isEmpty())\n        return QTransform();\n\n    QTransform matrix;\n#if HAVE_QSTRINGVIEW\n    const QChar *str = value.data();\n    const QChar *end = str + value.size();\n#else\n    const QChar *str = value.constData();\n    const QChar *end = str + value.length();\n#endif\n\n    while (str < end) {\n        if (str->isSpace() || *str == QLatin1Char(',')) {\n            ++str;\n            continue;\n        }\n        enum State {\n            Matrix,\n            Translate,\n            Rotate,\n            Scale,\n            SkewX,\n            SkewY\n        };\n        State state = Matrix;\n        if (*str == QLatin1Char('m')) {  //matrix\n            const char *ident = \"atrix\";\n            for (int i = 0; i < 5; ++i)\n                if (*(++str) != QLatin1Char(ident[i]))\n                    goto error;\n            ++str;\n            state = Matrix;\n        } else if (*str == QLatin1Char('t')) { //translate\n            const char *ident = \"ranslate\";\n            for (int i = 0; i < 8; ++i)\n                if (*(++str) != QLatin1Char(ident[i]))\n                    goto error;\n            ++str;\n            state = Translate;\n        } else if (*str == QLatin1Char('r')) { //rotate\n            const char *ident = \"otate\";\n            for (int i = 0; i < 5; ++i)\n                if (*(++str) != QLatin1Char(ident[i]))\n                    goto error;\n            ++str;\n            state = Rotate;\n        } else if (*str == QLatin1Char('s')) { //scale, skewX, skewY\n            ++str;\n            if (*str == QLatin1Char('c')) {\n                const char *ident = \"ale\";\n                for (int i = 0; i < 3; ++i)\n                    if (*(++str) != QLatin1Char(ident[i]))\n                        goto error;\n                ++str;\n                state = Scale;\n            } else if (*str == QLatin1Char('k')) {\n                if (*(++str) != QLatin1Char('e'))\n                    goto error;\n                if (*(++str) != QLatin1Char('w'))\n                    goto error;\n                ++str;\n                if (*str == QLatin1Char('X'))\n                    state = SkewX;\n                else if (*str == QLatin1Char('Y'))\n                    state = SkewY;\n                else\n                    goto error;\n                ++str;\n            } else {\n                goto error;\n            }\n        } else {\n            goto error;\n        }\n\n\n        while (str < end && str->isSpace())\n            ++str;\n        if (*str != QLatin1Char('('))\n            goto error;\n        ++str;\n        QVarLengthArray<qreal, 8> points;\n        parseNumbersArray(str, points);\n        if (*str != QLatin1Char(')'))\n            goto error;\n        ++str;\n\n        if(state == Matrix) {\n            if(points.count() != 6)\n                goto error;\n            matrix = QTransform(points[0], points[1],\n                                points[2], points[3],\n                                points[4], points[5]) * matrix;\n        } else if (state == Translate) {\n            if (points.count() == 1)\n                matrix.translate(points[0], 0);\n            else if (points.count() == 2)\n                matrix.translate(points[0], points[1]);\n            else\n                goto error;\n        } else if (state == Rotate) {\n            if(points.count() == 1) {\n                matrix.rotate(points[0]);\n            } else if (points.count() == 3) {\n                matrix.translate(points[1], points[2]);\n                matrix.rotate(points[0]);\n                matrix.translate(-points[1], -points[2]);\n            } else {\n                goto error;\n            }\n        } else if (state == Scale) {\n            if (points.count() < 1 || points.count() > 2)\n                goto error;\n            qreal sx = points[0];\n            qreal sy = sx;\n            if(points.count() == 2)\n                sy = points[1];\n            matrix.scale(sx, sy);\n        } else if (state == SkewX) {\n            if (points.count() != 1)\n                goto error;\n            const qreal deg2rad = qreal(0.017453292519943295769);\n            matrix.shear(qTan(points[0]*deg2rad), 0);\n        } else if (state == SkewY) {\n            if (points.count() != 1)\n                goto error;\n            const qreal deg2rad = qreal(0.017453292519943295769);\n            matrix.shear(0, qTan(points[0]*deg2rad));\n        }\n    }\n  error:\n    return matrix;\n}\n\n#if HAVE_QSTRINGVIEW\nstatic bool parsePathDataFast(QStringView dataStr, QPainterPath &path)\n#else\nstatic bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)\n#endif\n{\n    const int maxElementCount = 0x7fff; // Assume file corruption if more path elements than this\n    qreal x0 = 0, y0 = 0;              // starting point\n    qreal x = 0, y = 0;                // current point\n    char lastMode = 0;\n    QPointF ctrlPt;\n#if HAVE_QSTRINGVIEW\n    const QChar *str = dataStr.data();\n#else\n    const QChar *str = dataStr.constData();\n#endif\n    const QChar *end = str + dataStr.size();\n\n    bool ok = true;\n    while (ok && str != end) {\n        while (str->isSpace() && (str + 1) != end)\n            ++str;\n        QChar pathElem = *str;\n        ++str;\n        QChar endc = *end;\n        *const_cast<QChar *>(end) = u'\\0'; // parseNumbersArray requires 0-termination that QStringView cannot guarantee\n        const char *pattern = nullptr;\n        if (pathElem == QLatin1Char('a') || pathElem == QLatin1Char('A'))\n            pattern = \"rrrffrr\";\n        QVarLengthArray<qreal, 8> arg;\n        parseNumbersArray(str, arg, pattern);\n        *const_cast<QChar *>(end) = endc;\n        if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))\n            arg.append(0);//dummy\n        const qreal *num = arg.constData();\n        int count = arg.count();\n        while (ok && count > 0) {\n            qreal offsetX = x;        // correction offsets\n            qreal offsetY = y;        // for relative commands\n            switch (pathElem.unicode()) {\n            case 'm': {\n                if (count < 2) {\n                    ok = false;\n                    break;\n                }\n                x = x0 = num[0] + offsetX;\n                y = y0 = num[1] + offsetY;\n                num += 2;\n                count -= 2;\n                path.moveTo(x0, y0);\n\n                 // As per 1.2  spec 8.3.2 The \"moveto\" commands\n                 // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,\n                 // the subsequent pairs shall be treated as implicit 'lineto' commands.\n                 pathElem = QLatin1Char('l');\n            }\n                break;\n            case 'M': {\n                if (count < 2) {\n                    ok = false;\n                    break;\n                }\n                x = x0 = num[0];\n                y = y0 = num[1];\n                num += 2;\n                count -= 2;\n                path.moveTo(x0, y0);\n\n                // As per 1.2  spec 8.3.2 The \"moveto\" commands\n                // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,\n                // the subsequent pairs shall be treated as implicit 'lineto' commands.\n                pathElem = QLatin1Char('L');\n            }\n                break;\n            case 'z':\n            case 'Z': {\n                x = x0;\n                y = y0;\n                count--; // skip dummy\n                num++;\n                path.closeSubpath();\n            }\n                break;\n            case 'l': {\n                if (count < 2) {\n                    ok = false;\n                    break;\n                }\n                x = num[0] + offsetX;\n                y = num[1] + offsetY;\n                num += 2;\n                count -= 2;\n                path.lineTo(x, y);\n\n            }\n                break;\n            case 'L': {\n                if (count < 2) {\n                    ok = false;\n                    break;\n                }\n                x = num[0];\n                y = num[1];\n                num += 2;\n                count -= 2;\n                path.lineTo(x, y);\n            }\n                break;\n            case 'h': {\n                x = num[0] + offsetX;\n                num++;\n                count--;\n                path.lineTo(x, y);\n            }\n                break;\n            case 'H': {\n                x = num[0];\n                num++;\n                count--;\n                path.lineTo(x, y);\n            }\n                break;\n            case 'v': {\n                y = num[0] + offsetY;\n                num++;\n                count--;\n                path.lineTo(x, y);\n            }\n                break;\n            case 'V': {\n                y = num[0];\n                num++;\n                count--;\n                path.lineTo(x, y);\n            }\n                break;\n            case 'c': {\n                if (count < 6) {\n                    ok = false;\n                    break;\n                }\n                QPointF c1(num[0] + offsetX, num[1] + offsetY);\n                QPointF c2(num[2] + offsetX, num[3] + offsetY);\n                QPointF e(num[4] + offsetX, num[5] + offsetY);\n                num += 6;\n                count -= 6;\n                path.cubicTo(c1, c2, e);\n                ctrlPt = c2;\n                x = e.x();\n                y = e.y();\n                break;\n            }\n            case 'C': {\n                if (count < 6) {\n                    ok = false;\n                    break;\n                }\n                QPointF c1(num[0], num[1]);\n                QPointF c2(num[2], num[3]);\n                QPointF e(num[4], num[5]);\n                num += 6;\n                count -= 6;\n                path.cubicTo(c1, c2, e);\n                ctrlPt = c2;\n                x = e.x();\n                y = e.y();\n                break;\n            }\n            case 's': {\n                if (count < 4) {\n                    ok = false;\n                    break;\n                }\n                QPointF c1;\n                if (lastMode == 'c' || lastMode == 'C' ||\n                    lastMode == 's' || lastMode == 'S')\n                    c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());\n                else\n                    c1 = QPointF(x, y);\n                QPointF c2(num[0] + offsetX, num[1] + offsetY);\n                QPointF e(num[2] + offsetX, num[3] + offsetY);\n                num += 4;\n                count -= 4;\n                path.cubicTo(c1, c2, e);\n                ctrlPt = c2;\n                x = e.x();\n                y = e.y();\n                break;\n            }\n            case 'S': {\n                if (count < 4) {\n                    ok = false;\n                    break;\n                }\n                QPointF c1;\n                if (lastMode == 'c' || lastMode == 'C' ||\n                    lastMode == 's' || lastMode == 'S')\n                    c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());\n                else\n                    c1 = QPointF(x, y);\n                QPointF c2(num[0], num[1]);\n                QPointF e(num[2], num[3]);\n                num += 4;\n                count -= 4;\n                path.cubicTo(c1, c2, e);\n                ctrlPt = c2;\n                x = e.x();\n                y = e.y();\n                break;\n            }\n            case 'q': {\n                if (count < 4) {\n                    ok = false;\n                    break;\n                }\n                QPointF c(num[0] + offsetX, num[1] + offsetY);\n                QPointF e(num[2] + offsetX, num[3] + offsetY);\n                num += 4;\n                count -= 4;\n                path.quadTo(c, e);\n                ctrlPt = c;\n                x = e.x();\n                y = e.y();\n                break;\n            }\n            case 'Q': {\n                if (count < 4) {\n                    ok = false;\n                    break;\n                }\n                QPointF c(num[0], num[1]);\n                QPointF e(num[2], num[3]);\n                num += 4;\n                count -= 4;\n                path.quadTo(c, e);\n                ctrlPt = c;\n                x = e.x();\n                y = e.y();\n                break;\n            }\n            case 't': {\n                if (count < 2) {\n                    ok = false;\n                    break;\n                }\n                QPointF e(num[0] + offsetX, num[1] + offsetY);\n                num += 2;\n                count -= 2;\n                QPointF c;\n                if (lastMode == 'q' || lastMode == 'Q' ||\n                    lastMode == 't' || lastMode == 'T')\n                    c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());\n                else\n                    c = QPointF(x, y);\n                path.quadTo(c, e);\n                ctrlPt = c;\n                x = e.x();\n                y = e.y();\n                break;\n            }\n            case 'T': {\n                if (count < 2) {\n                    ok = false;\n                    break;\n                }\n                QPointF e(num[0], num[1]);\n                num += 2;\n                count -= 2;\n                QPointF c;\n                if (lastMode == 'q' || lastMode == 'Q' ||\n                    lastMode == 't' || lastMode == 'T')\n                    c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());\n                else\n                    c = QPointF(x, y);\n                path.quadTo(c, e);\n                ctrlPt = c;\n                x = e.x();\n                y = e.y();\n                break;\n            }\n            case 'a': {\n                if (count < 7) {\n                    ok = false;\n                    break;\n                }\n                qreal rx = (*num++);\n                qreal ry = (*num++);\n                qreal xAxisRotation = (*num++);\n                qreal largeArcFlag  = (*num++);\n                qreal sweepFlag = (*num++);\n                qreal ex = (*num++) + offsetX;\n                qreal ey = (*num++) + offsetY;\n                count -= 7;\n                qreal curx = x;\n                qreal cury = y;\n                pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),\n                        int(sweepFlag), ex, ey, curx, cury);\n\n                x = ex;\n                y = ey;\n            }\n                break;\n            case 'A': {\n                if (count < 7) {\n                    ok = false;\n                    break;\n                }\n                qreal rx = (*num++);\n                qreal ry = (*num++);\n                qreal xAxisRotation = (*num++);\n                qreal largeArcFlag  = (*num++);\n                qreal sweepFlag = (*num++);\n                qreal ex = (*num++);\n                qreal ey = (*num++);\n                count -= 7;\n                qreal curx = x;\n                qreal cury = y;\n                pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),\n                        int(sweepFlag), ex, ey, curx, cury);\n\n                x = ex;\n                y = ey;\n            }\n                break;\n            default:\n                ok = false;\n                break;\n            }\n            lastMode = pathElem.toLatin1();\n            if (path.elementCount() > maxElementCount)\n                ok = false;\n        }\n    }\n    return ok;\n}\n"
  },
  {
    "path": "src/octave-svgconvert.cc",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2017-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n#if defined (HAVE_CONFIG_H)\n#  include \"config.h\"\n#endif\n\n#include <iostream>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n#  include <vector>\n#  include <locale>\n#  include <codecvt>\n#endif\n\n#include <QtCore>\n#include <QtXml>\n\n#include <QGuiApplication>\n#include <QFontDatabase>\n#include <QImage>\n#include <QPainter>\n#include <QPdfWriter>\n#include <QRegularExpression>\n\n// Include a set of path rendering functions extracted from Qt-5.12 source\n#include \"octave-qsvghandler.h\"\n\n#include \"shared-sysdep.h\"\n\n// Helper function to configure a minimal Qt application.\n// Use offscreen rendering and minimal threading.\nvoid\nconfigure_minimal_qtapp ()\n{\n  // Use \"offscreen\" platform instead of standard GUI.\n  // This makes the biggest impact on performance (object creation time).\n  qputenv (\"QT_QPA_PLATFORM\", \"offscreen\");\n\n  // Disable unnecessary threads in Qt\n  // Explicitly disable DBus which is responsible for most of the deadlocks\n  // Many of these may be unnecessary, but won't harm application.\n  qputenv (\"QT_DBUS_DISABLED\", \"1\");\n}\n\n// Render to PDF\nclass pdfpainter : public QPainter\n{\npublic:\n\n  pdfpainter () = delete;\n\n  pdfpainter (QString fname, QRectF sz)\n    : m_pdfWriter (fname)\n  {\n    // PDF Writer settings\n    m_pdfWriter.setPageSize (QPageSize (sz.size (), QPageSize::Point,\n                                        QString (\"custom\"),\n                                        QPageSize::ExactMatch));\n    m_pdfWriter.setPageMargins (QMarginsF (0, 0, 0, 0));\n    m_pdfWriter.setResolution (600);\n\n    // Set document metadata\n    m_pdfWriter.setCreator (\"Octave\");\n\n    // Painter settings\n    begin (&m_pdfWriter);\n    setWindow (sz.toRect ());\n  }\n\n  OCTAVE_DISABLE_COPY_MOVE (pdfpainter)\n\n  ~pdfpainter () { end (); }\n\nprivate:\n\n  QPdfWriter m_pdfWriter;\n};\n\n// String conversion functions\nQVector<double>\nqstr2vectorf (QString str)\n{\n  QVector<double> pts;\n  QStringList coords = str.split (\",\");\n  for (auto& p : coords)\n    pts.append (p.toDouble ());\n\n  return pts;\n}\n\n// FIXME: What's the difference between qstr2vectorf and qstr2vectord?\n// Can one be called from the other to avoid code duplication, or deleted?\nQVector<double>\nqstr2vectord (QString str)\n{\n  QVector<double> pts;\n  QStringList coords = str.split (\",\");\n  for (auto& p : coords)\n    pts.append (p.toDouble ());\n\n  return pts;\n}\n\nQVector<QPointF>\nqstr2ptsvector (QString str)\n{\n  QVector<QPointF> pts;\n  str = str.trimmed ();\n  str.replace (\" \", \",\");\n  QStringList coords = str.split (\",\");\n  for (QStringList::iterator p = coords.begin (); p != coords.end (); p += 2)\n    {\n      QPointF pt ((*p).toDouble (), (*(p+1)).toDouble ());\n      pts.append (pt);\n    }\n  return pts;\n}\n\n// FIXME: What's the difference between qstr2ptsvector and qstr2ptsvectord?\n// Can one be called from the other to avoid code duplication, or deleted?\nQVector<QPoint>\nqstr2ptsvectord (QString str)\n{\n  QVector<QPoint> pts;\n  str = str.trimmed ();\n  str.replace (\" \", \",\");\n  QStringList coords = str.split (\",\");\n  for (QStringList::iterator p = coords.begin (); p != coords.end (); p += 2)\n    {\n      QPoint pt ((*p).toDouble (), (*(p+1)).toDouble ());\n      pts.append (pt);\n    }\n  return pts;\n}\n\n// Extract field arguments in a style-like string, e.g.,\n// \"bla field(1,34,56) bla\"\nQString\nget_field (QString str, QString field)\n{\n  QRegularExpression rx (field + \"\\\\(([^\\\\)]*)\\\\)\");\n  QRegularExpressionMatch match = rx.match (str);\n  QString retval = match.captured (1);\n\n  return retval;\n}\n\n// Polygon reconstruction class\nclass octave_polygon\n{\npublic:\n\n  octave_polygon (QPolygonF p)\n  { m_polygons.push_back (p); }\n\n  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (octave_polygon)\n\n  int count () const\n  { return m_polygons.count (); }\n\n  void reset ()\n  { m_polygons.clear (); }\n\n  QList<QPolygonF> reconstruct (int reconstruct_level)\n  {\n    if (m_polygons.isEmpty ())\n      return QList<QPolygonF> ();\n    else if (reconstruct_level < 2)\n      return m_polygons;\n\n    // Once a polygon has been merged to another, it is marked unsuded\n    QVector<bool> unused (m_polygons.count (), false);\n\n    bool tryagain = (m_polygons.count () > 1);\n\n    while (tryagain)\n      {\n        tryagain = false;\n        for (auto ii = 0; ii < m_polygons.count (); ii++)\n          {\n            if (! unused[ii])\n              {\n                QPolygonF polygon = m_polygons[ii];\n                for (auto jj = ii+1; jj < m_polygons.count (); jj++)\n                  {\n                    if (! unused[jj])\n                      {\n                        QPolygonF newpoly = mergepoly (polygon, m_polygons[jj]);\n                        if (newpoly.count ())\n                          {\n                            polygon = newpoly;\n                            m_polygons[ii] = newpoly;\n                            unused[jj] = true;\n                            tryagain = true;\n                          }\n                      }\n                  }\n              }\n          }\n      }\n\n    // Try to remove cracks in polygons\n    for (auto ii = 0; ii < m_polygons.count (); ii++)\n      {\n        QPolygonF polygon = m_polygons[ii];\n        tryagain = ! unused[ii];\n\n        while (tryagain && polygon.count () > 4)\n          {\n            tryagain = false;\n            QVector<int> del;\n\n            for (auto jj = 1; jj < (polygon.count () - 1); jj++)\n              if (polygon[jj-1] == polygon[jj+1])\n                {\n                  if (! del.contains (jj))\n                    del.push_front (jj);\n\n                  del.push_front (jj+1);\n                }\n\n            for (auto idx : del)\n              polygon.remove (idx);\n\n            if (del.count ())\n              tryagain = true;\n          }\n        m_polygons[ii] = polygon;\n      }\n\n    // FIXME: There may still be residual cracks, we should do something like\n    //   resetloop = 2;\n    //   while (resetloop)\n    //     currface = shift (currface, 1);\n    //     if (currface(1) == currface(3))\n    //       currface([2 3]) = [];\n    //       resetloop = 2;\n    //     else\n    //       resetloop--;\n    //     endif\n    //   endwhile\n\n    QList<QPolygonF> retval;\n    for (int ii = 0; ii < m_polygons.count (); ii++)\n      {\n        QPolygonF polygon = m_polygons[ii];\n        if (! unused[ii] && polygon.count () > 2)\n          retval.push_back (polygon);\n      }\n\n    return retval;\n  }\n\n  static inline\n  bool eq (QPointF p1, QPointF p2)\n  {\n    return ((qAbs (p1.x () - p2.x ())\n             <= 0.00001 * qMin (qAbs (p1.x ()), qAbs (p2.x ())))\n            && (qAbs (p1.y () - p2.y ())\n                <= 0.00001 * qMin (qAbs (p1.y ()), qAbs (p2.y ()))));\n  }\n\n  static\n  QPolygonF mergepoly (QPolygonF poly1, QPolygonF poly2)\n  {\n    // Close polygon contour\n    poly1.push_back (poly1[0]);\n    poly2.push_back (poly2[0]);\n\n    for (int ii = 0; ii < (poly1.size () - 1); ii++)\n      {\n        for (int jj = 0; jj < (poly2.size () - 1); jj++)\n          {\n            bool forward = (eq (poly1[ii], poly2[jj])\n                            && eq (poly1[ii+1], poly2[jj+1]));\n            bool backward = ! forward && (eq (poly1[ii], poly2[jj+1])\n                                          && eq (poly1[ii+1], poly2[jj]));\n\n            if (forward || backward)\n              {\n                // Unclose contour\n                poly1.pop_back ();\n                poly2.pop_back ();\n\n                QPolygonF merged;\n                for (int kk = 0; kk < (ii+1); kk++)\n                  merged.push_back (poly1[kk]);\n\n                // Shift vertices and eliminate the common edge\n                std::rotate (poly2.begin (), poly2.begin () + jj, poly2.end ());\n                poly2.erase (poly2.begin ());\n                poly2.erase (poly2.begin ());\n\n                if (forward)\n                  for (int kk = poly2.size (); kk > 0; kk--)\n                    merged.push_back (poly2[kk-1]);\n                else\n                  for (int kk = 0; kk < poly2.size (); kk++)\n                    merged.push_back (poly2[kk]);\n\n                for (int kk = ii+1; kk < poly1.size (); kk++)\n                  merged.push_back (poly1[kk]);\n\n                // Return row vector\n                QPolygonF out (merged.size ());\n                for (int kk = 0; kk < merged.size (); kk++)\n                  out[kk] = merged[kk];\n\n                return out;\n              }\n          }\n      }\n    return QPolygonF ();\n  }\n\n  void add (QPolygonF p)\n  {\n    if (m_polygons.count () == 0)\n      m_polygons.push_back (p);\n    else\n      {\n        QPolygonF tmp = mergepoly (m_polygons.back (), p);\n        if (tmp.count ())\n          m_polygons.back () = tmp;\n        else\n          m_polygons.push_back (p);\n      }\n  }\n\nprivate:\n  QList<QPolygonF> m_polygons;\n};\n\nvoid\ndraw (QDomElement& parent_elt, pdfpainter& painter)\n{\n  QDomNodeList nodes = parent_elt.childNodes ();\n\n  static QString clippath_id;\n  static QMap< QString, QVector<QPoint>> clippath;\n\n  // tspan elements must have access to the font and position extracted from\n  // their parent text element\n  static QFont font;\n  static double dx = 0, dy = 0;\n\n  // Store path defined in <defs> in a map\n  static bool in_defs = false;\n  static QMap< QString, QPainterPath> path_map;\n\n  for (int i = 0; i < nodes.count (); i++)\n    {\n      QDomNode node = nodes.at (i);\n      if (! node.isElement ())\n        continue;\n\n      QDomElement elt = node.toElement ();\n\n      if (elt.tagName () == \"clipPath\")\n        {\n          clippath_id = \"#\" + elt.attribute (\"id\");\n          draw (elt, painter);\n          clippath_id = QString ();\n        }\n      else if (elt.tagName () == \"g\")\n        {\n          QString str = elt.attribute (\"font-family\");\n          if (! str.isEmpty ())\n            {\n              // Font\n              font = QFont (str);\n\n              str = elt.attribute (\"font-weight\");\n              if (! str.isEmpty () && str != \"normal\")\n                font.setWeight (QFont::Bold);\n\n              str = elt.attribute (\"font-style\");\n              if (! str.isEmpty () && str != \"normal\")\n                font.setStyle (QFont::StyleItalic);\n\n              str = elt.attribute (\"font-size\");\n              if (! str.isEmpty ())\n                font.setPixelSize (str.toDouble ());\n\n              painter.setFont (font);\n\n              // Translation and rotation\n              painter.save ();\n              str = get_field (elt.attribute (\"transform\"), \"translate\");\n              if (! str.isEmpty ())\n                {\n                  QStringList trans = str.split (\",\");\n                  dx = trans[0].toDouble ();\n                  dy = trans[1].toDouble ();\n\n                  str = get_field (elt.attribute (\"transform\"), \"rotate\");\n                  if (! str.isEmpty ())\n                    {\n                      QStringList rot = str.split (\",\");\n                      painter.translate (dx+rot[1].toDouble (),\n                                         dy+rot[2].toDouble ());\n                      painter.rotate (rot[0].toDouble ());\n                      dx = rot[1].toDouble ();\n                      dy = rot[2].toDouble ();\n                    }\n                  else\n                    {\n                      painter.translate (dx, dy);\n                      dx = 0;\n                      dy = 0;\n                    }\n                }\n\n              draw (elt, painter);\n              painter.restore ();\n            }\n          else\n            {\n              bool current_clipstate = painter.hasClipping ();\n              QRegion current_clippath = painter.clipRegion ();\n\n              str = elt.attribute (\"clip-path\");\n              if (! str.isEmpty ())\n                {\n                  QVector<QPoint> pts = clippath[get_field (str, \"url\")];\n                  if (! pts.isEmpty ())\n                    {\n                      painter.setClipRegion (QRegion (QPolygon (pts)));\n                      painter.setClipping (true);\n                    }\n                }\n\n              // Fill color\n              str = get_field (elt.attribute (\"fill\"), \"rgb\");\n              if (! str.isEmpty ())\n                {\n                  QStringList clist = str.split (\",\");\n                  painter.setBrush (QColor (clist[0].toInt (),\n                                            clist[1].toInt (),\n                                            clist[2].toInt ()));\n                }\n\n              // Transform\n              str = elt.attribute (\"transform\");\n              painter.save ();\n              if (! str.isEmpty ())\n                {\n#if HAVE_QSTRINGVIEW\n                  QStringView tf {str};\n#else\n                  QStringRef tf {&str};\n#endif\n                  QTransform tform =\n                    parseTransformationMatrix (tf) * painter.transform ();\n                  painter.setTransform (tform);\n                }\n\n              draw (elt, painter);\n\n              // Restore previous clipping settings\n              painter.restore  ();\n              painter.setClipRegion (current_clippath);\n              painter.setClipping (current_clipstate);\n            }\n        }\n      else if (elt.tagName () == \"defs\")\n        {\n          in_defs = true;\n          draw (elt, painter);\n          in_defs = false;\n        }\n      else if (elt.tagName () == \"path\")\n        {\n          // Store QPainterPath for latter use\n          QString id = elt.attribute (\"id\");\n          if (! id.isEmpty ())\n            {\n              QString d = elt.attribute (\"d\");\n\n              if (! d.isEmpty ())\n                {\n#if HAVE_QSTRINGVIEW\n                  QStringView data {d};\n#else\n                  QStringRef data {&d};\n#endif\n                  QPainterPath path;\n                  if (! parsePathDataFast (data, path))\n                    continue; // Something went wrong, pass\n                  else if (path.isEmpty ())\n                    std::cout << \"Empty path for data:\"\n                              << d.toStdString () << std::endl;\n                  else if (in_defs)\n                    path_map[\"#\" + id] = path;\n                  else\n                    painter.drawPath (path);\n\n\n                  if (path_map[\"#\" + id].isEmpty ())\n                    std::cout << \"Empty path for data:\"\n                              << d.toStdString () << std::endl;\n                }\n            }\n        }\n      else if (elt.tagName () == \"use\")\n        {\n          painter.setPen (Qt::NoPen);\n\n          QString str = elt.attribute (\"xlink:href\");\n          if (! str.isEmpty () && str.size () > 2)\n            {\n              QPainterPath path = path_map[str];\n              if (! path.isEmpty ())\n                {\n                  str = elt.attribute (\"x\");\n                  double x = elt.attribute (\"x\").toDouble ();\n                  str = elt.attribute (\"y\");\n                  double y = elt.attribute (\"y\").toDouble ();\n                  painter.translate (x, y);\n                  painter.drawPath (path);\n                  painter.translate (-x, -y);\n                }\n            }\n        }\n      else if (elt.tagName () == \"text\")\n        {\n          // Font\n          QFont saved_font (font);\n\n          QString str = elt.attribute (\"font-family\");\n          if (! str.isEmpty ())\n            {\n              // QFont::setFamily() doesn't seem to work properly in Qt6\n              // (see bug #66306). Use the QFont constructor to update\n              // the current font.\n              font = QFont (str, -1, font.weight (),\n                            font.style () ==  QFont::StyleItalic);\n              font.setPixelSize (saved_font.pixelSize ());\n            }\n\n          str = elt.attribute (\"font-weight\");\n          if (! str.isEmpty ())\n            {\n              if (str != \"normal\")\n                font.setWeight (QFont::Bold);\n              else\n                font.setWeight (QFont::Normal);\n            }\n\n          str = elt.attribute (\"font-style\");\n          if (! str.isEmpty ())\n            {\n              if (str != \"normal\")\n                font.setStyle (QFont::StyleItalic);\n              else\n                font.setStyle (QFont::StyleNormal);\n            }\n\n          str = elt.attribute (\"font-size\");\n          if (! str.isEmpty ())\n            font.setPixelSize (str.toDouble ());\n\n          painter.setFont (font);\n\n          // Color is specified in rgb\n          str = get_field (elt.attribute (\"fill\"), \"rgb\");\n          if (! str.isEmpty ())\n            {\n              QStringList clist = str.split (\",\");\n              painter.setPen (QColor (clist[0].toInt (), clist[1].toInt (),\n                                      clist[2].toInt ()));\n            }\n\n          QStringList xx = elt.attribute (\"x\").split (\" \");\n          int y = elt.attribute (\"y\").toInt ();\n          str = elt.text ();\n          if (! str.isEmpty ())\n            {\n              int ii = 0;\n              for (const QString& s : xx)\n                if (ii < str.size ())\n                  painter.drawText (s.toInt ()-dx, y-dy, str.at (ii++));\n            }\n\n          draw (elt, painter);\n          font = saved_font;\n        }\n      else if (elt.tagName () == \"polyline\")\n        {\n          // Color\n          QColor c (elt.attribute (\"stroke\"));\n          QString str = elt.attribute (\"stroke-opacity\");\n          if (! str.isEmpty () && str.toDouble () != 1.0\n              && str.toDouble () >= 0.0)\n            c.setAlphaF (str.toDouble ());\n\n          QPen pen;\n          pen.setColor (c);\n\n          // Line properties\n          str = elt.attribute (\"stroke-width\");\n          if (! str.isEmpty ())\n            {\n              double w = str.toDouble ();\n              if (w > 0)\n                pen.setWidthF (w);\n            }\n\n          str = elt.attribute (\"stroke-linecap\");\n          pen.setCapStyle (Qt::SquareCap);\n          if (str == \"round\")\n            pen.setCapStyle (Qt::RoundCap);\n          else if (str == \"butt\")\n            pen.setCapStyle (Qt::FlatCap);\n\n          str = elt.attribute (\"stroke-linejoin\");\n          pen.setJoinStyle (Qt::MiterJoin);\n          if (str == \"round\")\n            pen.setJoinStyle (Qt::RoundJoin);\n          else if (str == \"bevel\")\n            pen.setJoinStyle (Qt::BevelJoin);\n\n          str = elt.attribute (\"stroke-dasharray\");\n          pen.setStyle (Qt::SolidLine);\n          if (! str.isEmpty ())\n            {\n              QVector<double> pat = qstr2vectord (str);\n              if (pat.count () != 2 || pat[1] != 0)\n                {\n                  // Express pattern in linewidth units\n                  for (auto& p : pat)\n                    p /= pen.widthF ();\n\n                  pen.setDashPattern (pat);\n                }\n            }\n\n          painter.setPen (pen);\n          painter.drawPolyline (qstr2ptsvector (elt.attribute (\"points\")));\n        }\n      else if (elt.tagName () == \"image\")\n        {\n          // Images are represented as a base64 stream of png formatted data\n          QString href_att = elt.attribute (\"xlink:href\");\n          QString prefix (\"data:image/png;base64,\");\n          QByteArray data\n            = QByteArray::fromBase64 (href_att.mid (prefix.length ()).toLatin1 ());\n          QImage img;\n          if (img.loadFromData (data, \"PNG\"))\n            {\n              QRect pos(elt.attribute (\"x\").toInt (),\n                        elt.attribute (\"y\").toInt (),\n                        elt.attribute (\"width\").toInt (),\n                        elt.attribute (\"height\").toInt ());\n\n              // Translate\n              painter.save ();\n              QString str = get_field (elt.attribute (\"transform\"), \"matrix\");\n              if (! str.isEmpty ())\n                {\n                  QVector<double> m = qstr2vectorf (str);\n                  QTransform tform(m[0], m[1], m[2],\n                                   m[3], m[4], m[5]);\n                  painter.setTransform (tform);\n                }\n\n              painter.setRenderHint (QPainter::Antialiasing, false);\n#if defined (HAVE_QPAINTER_RENDERHINT_LOSSLESS)\n              painter.setRenderHint (QPainter::LosslessImageRendering);\n#endif\n              painter.drawImage (pos, img);\n              painter.setRenderHint (QPainter::Antialiasing, true);\n              painter.restore  ();\n            }\n        }\n      else if (elt.tagName () == \"rect\")\n        {\n          // Position\n          double x = elt.attribute (\"x\").toDouble ();\n          double y = elt.attribute (\"y\").toDouble ();\n\n          // Size\n          double wd = elt.attribute (\"width\").toDouble ();\n          double hg = elt.attribute (\"height\").toDouble ();\n\n          // Color\n          QColor saved_color = painter.brush ().color ();\n\n          QString str = elt.attribute (\"fill\");\n          if (! str.isEmpty ())\n            painter.setBrush (QColor (str));\n\n          painter.setPen (Qt::NoPen);\n\n          painter.drawRect (QRectF (x, y, wd, hg));\n\n          if (! str.isEmpty ())\n            painter.setBrush (saved_color);\n        }\n      else if (elt.tagName () == \"polygon\")\n        {\n          if (! clippath_id.isEmpty ())\n            clippath[clippath_id] = qstr2ptsvectord (elt.attribute (\"points\"));\n          else\n            {\n              QString str = elt.attribute (\"fill\");\n              if (! str.isEmpty ())\n                {\n                  QColor color (str);\n\n                  str = elt.attribute (\"fill-opacity\");\n                  if (! str.isEmpty () && str.toDouble () != 1.0\n                      && str.toDouble () >= 0.0)\n                    color.setAlphaF (str.toDouble ());\n\n                  QPolygonF p (qstr2ptsvector (elt.attribute (\"points\")));\n\n                  if (p.count () > 2)\n                    {\n                      painter.setBrush (color);\n                      painter.setPen (Qt::NoPen);\n\n                      painter.setRenderHint (QPainter::Antialiasing, false);\n                      painter.drawPolygon (p);\n                      painter.setRenderHint (QPainter::Antialiasing, true);\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Append a list of reconstructed child polygons to a QDomElement and remove\n// the original nodes\n\nvoid\nreplace_polygons (QDomElement& parent_elt, QList<QDomNode> orig,\n                  QList<QPolygonF> polygons)\n{\n  if (! orig.count () || (orig.count () == polygons.count ()))\n    return;\n\n  QDomNode last = orig.last ();\n  for (int ii = 0; ii < polygons.count (); ii++)\n    {\n      QPolygonF polygon = polygons[ii];\n\n      QDomNode node = last.cloneNode ();\n\n      QString pts;\n\n      for (int jj = 0; jj < polygon.count (); jj++)\n        {\n          pts += QString (\"%1,%2 \").arg (polygon[jj].x ())\n                 .arg (polygon[jj].y ());\n        }\n\n      node.toElement ().setAttribute (\"points\", pts.trimmed ());\n\n      if (! last.isNull ())\n        last = parent_elt.insertAfter (node, last);\n    }\n\n  for (int ii = 0; ii < orig.count (); ii++)\n    parent_elt.removeChild (orig.at (ii));\n}\n\nvoid\nreconstruct_polygons (QDomElement& parent_elt, int reconstruct_level)\n{\n  QDomNodeList nodes = parent_elt.childNodes ();\n  QColor current_color;\n  QList<QDomNode> replaced_nodes;\n  octave_polygon current_polygon;\n\n  // Collection of child nodes to be removed and polygons to be added\n  QList< QPair<QList<QDomNode>, QList<QPolygonF>>> collection;\n\n  for (int ii = 0; ii < nodes.count (); ii++)\n    {\n      QDomNode node = nodes.at (ii);\n      if (! node.isElement ())\n        continue;\n\n      QDomElement elt = node.toElement ();\n\n      if (elt.tagName () == \"polygon\")\n        {\n          QString str = elt.attribute (\"fill\");\n          if (! str.isEmpty ())\n            {\n              QColor color (str);\n              str = elt.attribute (\"fill-opacity\");\n              if (! str.isEmpty ())\n                {\n                  double alpha = str.toDouble ();\n                  if (alpha != 1.0 && alpha >= 0.0)\n                    color.setAlphaF (alpha);\n                }\n\n              if (! current_polygon.count ())\n                current_color = color;\n\n              if (color != current_color)\n                {\n                  // Reconstruct the previous series of triangles\n                  QList<QPolygonF> polygons\n                    = current_polygon.reconstruct (reconstruct_level);\n                  collection.push_back (QPair<QList<QDomNode>, QList<QPolygonF>>\n                                        (replaced_nodes, polygons));\n\n                  replaced_nodes.clear ();\n                  current_polygon.reset ();\n\n                  current_color = color;\n                }\n\n              QPolygonF p (qstr2ptsvector (elt.attribute (\"points\")));\n              current_polygon.add (p);\n              replaced_nodes.push_back (node);\n            }\n        }\n      else\n        {\n          if (current_polygon.count ())\n            {\n              QList<QPolygonF> polygons = current_polygon.reconstruct (reconstruct_level);\n              collection.push_back (QPair<QList<QDomNode>, QList<QPolygonF>>\n                                    (replaced_nodes, polygons));\n              replaced_nodes.clear ();\n              current_polygon.reset ();\n            }\n          reconstruct_polygons (elt, reconstruct_level);\n        }\n    }\n\n  // Finish\n  collection.push_back (QPair<QList<QDomNode>, QList<QPolygonF>>\n                        (replaced_nodes,\n                         current_polygon.reconstruct (reconstruct_level)));\n\n  for (int ii = 0; ii < collection.count (); ii++)\n    replace_polygons (parent_elt, collection[ii].first, collection[ii].second);\n}\n\nvoid\nadd_custom_properties (QDomElement& parent_elt)\n{\n  QDomNodeList nodes = parent_elt.childNodes ();\n\n  for (int ii = 0; ii < nodes.count (); ii++)\n    {\n      QDomNode node = nodes.at (ii);\n      if (! node.isElement ())\n        continue;\n\n      QDomElement elt = node.toElement ();\n\n      if (elt.tagName () == \"image\")\n        elt.setAttribute (\"image-rendering\", \"optimizeSpeed\");\n      else\n        add_custom_properties (elt);\n    }\n\n}\n\n#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)\nextern \"C\"\nint\nwmain (int argc, wchar_t **wargv)\n{\n  char **argv = convert_wargv_to_utf8 (argc, wargv);\n\n#else\nint\nmain (int argc, char **argv)\n{\n#endif\n  const char *doc = \"See \\\"octave-svgconvert -h\\\"\";\n  const char *help = \"Usage:\\n\\\noctave-svgconvert infile fmt dpi font reconstruct outfile\\n\\n\\\nConvert svg file to pdf, or svg.  All arguments are mandatory:\\n\\\n* infile: input svg file or \\\"-\\\" to indicate that the input svg file should be \\\nread from stdin\\n\\\n* fmt: format of the output file.  May be one of pdf or svg\\n\\\n* dpi: device dependent resolution in screen pixel per inch\\n\\\n* font: specify a file name for the default FreeSans font\\n\\\n* reconstruct: specify whether to reconstruct triangle to polygons\\n\\\n  0: no reconstruction (merging) of polygons\\n\\\n  1: merge consecutive triangles if they share an edge\\n\\\n  2: merge all triangles that share edges (might take a long time)\\n\\\n* outfile: output file name\\n\";\n\n  if ((argc > 1) && (strcmp (argv[1], \"-h\") == 0))\n    {\n      std::cout << help;\n      return 0;\n    }\n  else if (argc != 7)\n    {\n      std::cerr << help;\n      return -1;\n    }\n\n  // Open svg file\n  QFile file;\n  if (strcmp (argv[1], \"-\") != 0)\n    {\n      // Read from file\n      file.setFileName (argv[1]);\n      if (! file.open (QIODevice::ReadOnly | QIODevice::Text))\n        {\n          std::cerr << \"Unable to open file \" << argv[1] << \"\\n\";\n          std::cerr << help;\n          return -1;\n        }\n    }\n  else\n    {\n      // Read from stdin\n      if (! file.open (stdin, QIODevice::ReadOnly | QIODevice::Text))\n        {\n          std::cerr << \"Unable to read from stdin\\n\";\n          std::cerr << doc;\n          return -1;\n        }\n    }\n\n  // Create a DOM document and load the svg file\n  QDomDocument document;\n#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)\n  QDomDocument::ParseResult parseResult = document.setContent (&file);\n  if (! parseResult)\n    {\n      std::cerr << \"Failed to parse XML contents\" << std::endl\n                << \"in line \" << parseResult.errorLine\n                << \" column \" << parseResult.errorColumn << \":\" << std::endl\n                << parseResult.errorMessage.toStdString () <<  std::endl;\n      file.close ();\n      return -1;\n    }\n#else\n  QString msg;\n  if (! document.setContent (&file, false, &msg))\n    {\n      std::cerr << \"Failed to parse XML contents\" << std::endl\n                << msg.toStdString () << std::endl;\n      file.close ();\n      return -1;\n    }\n#endif\n\n  file.close ();\n\n  // Format\n  if (strcmp (argv[2], \"pdf\") != 0 && strcmp (argv[2], \"svg\") != 0)\n    {\n      std::cerr << \"Unhandled output file format \" << argv[2] << \"\\n\";\n      std::cerr << doc;\n      return -1;\n    }\n\n  // Resolution (Currently unused). Keep the DPI argument in case\n  // we implement raster outputs.\n  // double dpi = QString (argv[3]).toDouble ();\n\n  // Get the viewport from the root element\n  QDomElement root = document.firstChildElement();\n  double x0, y0, dx, dy;\n  QString s = root.attribute (\"viewBox\");\n  QTextStream (&s) >> x0 >> y0 >> dx >> dy;\n  QRectF vp (x0, y0, dx, dy);\n\n  // Configure a minimal Qt application (offscreen rendering, minimal threads)\n  configure_minimal_qtapp ();\n  QGuiApplication app (argc, argv);\n\n  // When printing to PDF we may need the default FreeSans font\n  if (! strcmp (argv[2], \"pdf\"))\n    {\n      QFont font (\"FreeSans\");\n      if (! font.exactMatch ())\n        {\n          QString fontpath (argv[4]);\n          if (! fontpath.isEmpty ())\n            {\n              int id = QFontDatabase::addApplicationFont (fontpath);\n              if (id < 0)\n                std::cerr << \"warning: print: \"\n                             \"Unable to add default font to database\\n\";\n            }\n          else\n            std::cerr << \"warning: print: FreeSans font not found\\n\";\n        }\n    }\n\n  // First render in a temporary file\n  QTemporaryFile fout;\n  if (! fout.open ())\n    {\n      std::cerr << \"Could not open temporary file\\n\";\n      return -1;\n    }\n\n  // Do basic polygons reconstruction\n  int reconstruct_level = QString (argv[5]).toInt ();\n  if (reconstruct_level)\n    reconstruct_polygons (root, reconstruct_level);\n\n  // Add custom properties to SVG\n  add_custom_properties (root);\n\n  // Draw\n  if (! strcmp (argv[2], \"pdf\"))\n    {\n      // PDF painter\n      pdfpainter painter (fout.fileName (), vp);\n\n      draw (root, painter);\n    }\n  else\n    {\n      // Return modified svg document\n      QTextStream out (&fout);\n#if HAVE_QTEXTSTREAM_SETENCODING\n      out.setEncoding (QStringConverter::Utf8);\n#else\n      out.setCodec (\"UTF-8\");\n#endif\n      out << document.toByteArray ();\n    }\n\n  // Delete output file before writing with new data\n  if (QFile::exists (argv[6]))\n    if (! QFile::remove (argv[6]))\n      {\n        std::cerr << \"Unable to replace existing file \" << argv[6] << \"\\n\";\n        return -1;\n      }\n\n  fout.copy (argv[6]);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/shared-fcns.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2008-2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions are also defined in liboctave or libinterp.  They\n// are repeated here to avoid having to link the main Octave program\n// with the Octave libraries.\n\n#if ! defined (octave_shared_fcns_h)\n#define octave_shared_fcns_h 1\n\n#include <cctype>\n\n#include \"shared-sysdep.h\"\n\nstatic std::string\noctave_getenv (const std::string& name)\n{\n  char *value = ::getenv (name.c_str ());\n\n  return value ? value : \"\";\n}\n\nstatic std::string Voctave_home;\nstatic std::string Voctave_exec_home;\n\nstatic void\nset_octave_home ()\n{\n  std::string op = OCTAVE_PREFIX;\n  std::string oep = OCTAVE_EXEC_PREFIX;\n\n  std::string oh = octave_getenv (\"OCTAVE_HOME\");\n  std::string oeh = octave_getenv (\"OCTAVE_EXEC_HOME\");\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n  if (oh.empty ())\n    oh = w32_get_octave_home ();\n#endif\n\n  // If OCTAVE_HOME is set in the environment, use that.  Otherwise,\n  // default to ${prefix} from configure.\n\n  Voctave_home = (oh.empty () ? op : oh);\n\n  // If OCTAVE_EXEC_HOME is set in the environment, use that.\n  // Otherwise, if ${prefix} and ${exec_prefix} from configure are set\n  // to the same value, use OCTAVE_HOME from the environment if it is set.\n  // Otherwise, default to ${exec_prefix} from configure.\n\n  if (! oeh.empty ())\n    Voctave_exec_home = oeh;\n  else if (op == oep && ! oh.empty ())\n    Voctave_exec_home = oh;\n  else\n    Voctave_exec_home = oep;\n}\n\nstatic bool is_dir_sep (char c)\n{\n  return dir_sep_chars.find (c) != std::string::npos;\n}\n\nstatic bool\nabsolute_pathname (const std::string& s)\n{\n  std::size_t len = s.length ();\n\n  if (len == 0)\n    return false;\n\n  if (is_dir_sep (s[0]))\n    return true;\n\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)\n  if ((len == 2 && isalpha (s[0]) && s[1] == ':')\n      || (len > 2 && isalpha (s[0]) && s[1] == ':'\n          && is_dir_sep (s[2])))\n    return true;\n#endif\n\n  return false;\n}\n\nstatic std::string\nprepend_home_dir (const std::string& hd, const std::string& s)\n{\n  std::string retval = s;\n\n  if (! absolute_pathname (retval))\n    retval = hd + dir_sep_char + s;\n\n  if (dir_sep_char != '/')\n    std::replace (retval.begin (), retval.end (), '/', dir_sep_char);\n\n  return retval;\n}\n\n// prepend_octave_home is used in mkoctfile.in.cc and\n// octave-config.in.cc but not in main.in.cc.  Tagging it as unused\n// avoids warnings from GCC about an unused function but should not\n// cause trouble in the event that it actually is used.\n\nOCTAVE_UNUSED\nstatic std::string\nprepend_octave_home (const std::string& s)\n{\n  return prepend_home_dir (Voctave_home, s);\n}\n\nstatic std::string\nprepend_octave_exec_home (const std::string& s)\n{\n  return prepend_home_dir (Voctave_exec_home, s);\n}\n\n#endif\n"
  },
  {
    "path": "src/shared-sysdep.h",
    "content": "////////////////////////////////////////////////////////////////////////\n//\n// Copyright (C) 2026 The Octave Project Developers\n//\n// See the file COPYRIGHT.md in the top-level directory of this\n// distribution or <https://octave.org/copyright/>.\n//\n// This file is part of Octave.\n//\n// Octave is free software: you can redistribute it and/or modify it\n// under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Octave is distributed in the hope that it will be useful, but\n// WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Octave; see the file COPYING.  If not, see\n// <https://www.gnu.org/licenses/>.\n//\n////////////////////////////////////////////////////////////////////////\n\n// These functions are also defined in liboctave or libinterp.  They\n// are repeated here to avoid having to link the main Octave program\n// with the Octave libraries.\n\n#if ! defined (octave_shared_sysdep_h)\n#define octave_shared_sysdep_h 1\n\n#include <cctype>\n\n#if defined (OCTAVE_USE_WINDOWS_API)\n\n#  include <windows.h>\n#  include <tlhelp32.h>\n\n#  if defined (_MSC_VER)\n#    define popen _popen\n#    define pclose _pclose\n#  endif\n\nchar *\nconvert_utf16_to_utf8 (const wchar_t *utf16, const int size16, int &size8)\n{\n  // convert UTF-16 encoded wide character string to multibyte UTF-8 string\n\n  // get required size of converted string\n  size8 = WideCharToMultiByte (CP_UTF8, 0, utf16, size16, nullptr, 0, nullptr,\n                               nullptr);\n\n  if (size8 <= 0)\n    return nullptr;\n\n  // allocate buffer for UTF-8 string - must be freed by calling function\n  char *utf8 = new char[size8];\n\n  // actually convert to UTF-8\n  WideCharToMultiByte (CP_UTF8, 0, utf16, size16, utf8, size8, nullptr,\n                       nullptr);\n\n  return utf8;\n}\n\nwchar_t *\nconvert_utf8_to_utf16 (const char *utf8, const int size8, int &size16)\n{\n  // convert multibyte UTF-8 string to UTF-16 encoded wide character string\n\n  // get required size of converted string\n  size16 = MultiByteToWideChar (CP_UTF8, 0, utf8, size8, nullptr, 0);\n\n  if (size16 <= 0)\n    return nullptr;\n\n  // allocate buffer for UTF-16 string - must be freed by calling function\n  wchar_t *utf16 = new wchar_t[size16];\n\n  // actually convert to UTF-16\n  MultiByteToWideChar (CP_UTF8, 0, utf8, size8, utf16, size16);\n\n  return utf16;\n}\n\n#if defined (_UNICODE)\nstatic char **\nconvert_wargv_to_utf8 (int argc, wchar_t **wargv)\n{\n    // allocate array of char* (argv-style)\n    char **argv = new char*[argc + 1];\n    int size8;\n\n    for (int i = 0; i < argc; ++i)\n      {\n        argv[i] = convert_utf16_to_utf8 (wargv[i], -1, size8);\n      }\n\n    argv[argc] = nullptr;\n\n    return argv;\n}\n#endif\n\nstd::string\nw32_get_octave_home ()\n{\n  std::string retval;\n\n  std::string bin_dir;\n\n  wchar_t namebuf[MAX_PATH+1];\n  DWORD size16\n    = GetModuleFileNameW (GetModuleHandle (nullptr), namebuf, MAX_PATH);\n  if (size16 < MAX_PATH)\n    {\n      // convert wide character string to multibyte UTF-8 string\n      int size8;\n      char *name_u8 = convert_utf16_to_utf8 (namebuf, size16, size8);\n      if (name_u8)\n        {\n          std::string exe_name (name_u8, size8);\n          delete[] name_u8;\n\n          std::size_t pos = exe_name.rfind ('\\\\');\n\n          if (pos != std::string::npos)\n            bin_dir = exe_name.substr (0, pos + 1);\n        }\n    }\n\n  if (! bin_dir.empty ())\n    {\n      std::size_t pos = bin_dir.rfind (R\"(\\bin\\)\");\n\n      if (pos != std::string::npos)\n        retval = bin_dir.substr (0, pos);\n    }\n\n  return retval;\n}\n\n#endif\n\n// Find the directory where the octave binary is supposed to be\n// installed.\n\n#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)           \\\n     && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))\nstatic const char dir_sep_char = '\\\\';\n#else\nstatic const char dir_sep_char = '/';\n#endif\n\n#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)\nstatic std::string dir_sep_chars = R\"(/\\)\";\n#else\nstatic std::string dir_sep_chars = \"/\";\n#endif\n\n#endif\n"
  },
  {
    "path": "test/Makefile.am",
    "content": "BUILT_SOURCES =\nDIRSTAMP_FILES =\nEXTRA_DIST =\nCLEANFILES =\nDISTCLEANFILES =\nMAINTAINERCLEANFILES =\nTEST_FILES =\nnoinst_TEST_FILES =\n\noctave_dirstamp = $(am__leading_dot)octave-dirstamp\n\nDIRSTAMP_FILES += $(octave_dirstamp)\n\n$(DIRSTAMP_FILES):\n\t$(AM_V_GEN)$(MKDIR_P) $(@D) && \\\n\t: > $@\n\nTEST_FILES += \\\n  fntests.m \\\n  anonymous-function.tst \\\n  args.tst \\\n  bug-31371.tst \\\n  bug-40117.tst \\\n  bug-45969.tst \\\n  bug-45972.tst \\\n  bug-46330.tst \\\n  bug-49904.tst \\\n  bug-53579.tst \\\n  bug-53599.tst \\\n  bug-54490.tst \\\n  bug-55308.tst \\\n  bug-55321.tst \\\n  bug-55322.tst \\\n  bug-59950.tst \\\n  bug-61201.tst \\\n  bug-65153.tst \\\n  colormaps.tst \\\n  command.tst \\\n  complex.tst \\\n  deprecate-props.tst \\\n  diag-perm.tst \\\n  error.tst \\\n  eval-catch.tst \\\n  eval-command.tst \\\n  for.tst \\\n  func.tst \\\n  global.tst \\\n  if.tst \\\n  index.tst \\\n  inline-fcn.tst \\\n  integer.tst \\\n  io.tst \\\n  leftdiv.tst \\\n  line-continue.tst \\\n  logical-index.tst \\\n  null-assign.tst \\\n  parser.tst \\\n  prefer.tst \\\n  range.tst \\\n  recursion.tst \\\n  return.tst \\\n  single-index.tst \\\n  slice.tst \\\n  sparse-assign.tst \\\n  sparse-broadcasting.tst \\\n  struct.tst \\\n  switch.tst \\\n  system.tst \\\n  transpose.tst \\\n  try.tst \\\n  unwind.tst \\\n  while.tst\n\ninclude bug-35448/module.mk\ninclude bug-35881/module.mk\ninclude bug-36025/module.mk\ninclude bug-38236/module.mk\ninclude bug-38691/module.mk\ninclude bug-41723/module.mk\ninclude bug-44643/module.mk\ninclude bug-44940/module.mk\ninclude bug-45351/module.mk\ninclude bug-46660/module.mk\ninclude bug-47680/module.mk\ninclude bug-48693/module.mk\ninclude bug-49379/module.mk\ninclude bug-50014/module.mk\ninclude bug-50035/module.mk\ninclude bug-50395/module.mk\ninclude bug-50716/module.mk\ninclude bug-50831/module.mk\ninclude bug-51192/module.mk\ninclude bug-51532/module.mk\ninclude bug-51534/module.mk\ninclude bug-51599/module.mk\ninclude bug-52075/module.mk\ninclude bug-52722/module.mk\ninclude bug-52851/module.mk\ninclude bug-53027/module.mk\ninclude bug-53468/module.mk\ninclude bug-53956/module.mk\ninclude bug-54995/module.mk\ninclude bug-55758/module.mk\ninclude bug-56068/module.mk\ninclude bug-58572/module.mk\ninclude bug-58593/module.mk\ninclude bug-59451/module.mk\ninclude bug-59617/module.mk\ninclude bug-59661/module.mk\ninclude bug-59704/module.mk\ninclude bug-59937/module.mk\ninclude bug-60237/module.mk\ninclude bug-60726/module.mk\ninclude bug-60882/module.mk\ninclude bug-61105/module.mk\ninclude bug-61191/module.mk\ninclude bug-63841/module.mk\ninclude bug-64620/module.mk\ninclude bug-65037/module.mk\ninclude bug-67096/module.mk\ninclude bug-67403/module.mk\ninclude bug-67964/module.mk\ninclude class-concat/module.mk\ninclude classdef/module.mk\ninclude classdef-debug/module.mk\ninclude classdef-load-save/module.mk\ninclude classdef-multiple-inheritance/module.mk\ninclude classes/module.mk\ninclude colon-op/module.mk\ninclude ctor-vs-method/module.mk\ninclude fcn-handle/module.mk\ninclude file-encoding/module.mk\ninclude help/module.mk\ninclude json/module.mk\ninclude jupyter-notebook/module.mk\ninclude load-path/module.mk\ninclude local-functions/module.mk\ninclude mex/module.mk\ninclude nest/module.mk\ninclude pkg/module.mk\ninclude private-functions/module.mk\ninclude publish/module.mk\n\n# run-octave (optional-prepare-commands)\n\ndefine run-octave-tests\n  ( $(SHELL) ../run-octave $(RUN_OCTAVE_OPTIONS) --no-init-file --quiet  \\\n      --no-history -p $(abs_top_builddir)/test/mex \\\n      $(abs_top_srcdir)/test/fntests.m $(abs_top_srcdir)/test \"$(1)\" ) && \\\n  if $(AM_V_P); then \\\n    echo \"\"; \\\n    if [ -f fntests.log ]; then \\\n      echo \"Contents of test/fntests.log:\"; \\\n      echo \"\"; \\\n      $(AWK) -f $(srcdir)/show-failures.awk fntests.log; \\\n    else \\\n      echo \"fntests.log is missing!\"; \\\n    fi; \\\n  fi\nendef\n\ncheck-local: $(GENERATED_TEST_FILES) $(MEX_TEST_FUNCTIONS) | $(OCTAVE_INTERPRETER_TARGETS) $(octave_dirstamp)\n\t$(AM_V_at)$(call run-octave-tests)\n\nCOVERAGE_DIR = coverage\nCOVERAGE_INFO = $(COVERAGE_DIR)/$(PACKAGE).info\n\n## FIXME: To get something useful out of 'make coverage', you should use gcc\n## and configure with compiler flags set to '-g --coverage'.  Adding the\n## --coverage option to either WARN_CXXFLAGS or XTRA_CXXFLAGS resulted in\n## link errors, so some work still needed to get a '--enable-coverage-flags'\n## option working.\n\ncoverage: all\n\tlcov --directory . --zerocounters\n\t$(MAKE) $(AM_MAKEFLAGS) check\n\t$(MKDIR_P) $(COVERAGE_DIR)\n\tlcov --directory . --capture --output-file $(COVERAGE_INFO)\n\tgenhtml --output-directory $(COVERAGE_DIR) $(COVERAGE_INFO)\n\t@echo \"\"\n\t@echo \"Code coverage report successfully built.  Open the file\"\n\t@echo \"\"\n\t@echo \"   $(abs_top_builddir)/$(COVERAGE_DIR)/index.html\"\n\t@echo \"\"\n\t@echo \"in a web browser to view the results.\"\n\t@echo \"\"\n.PHONY: coverage\n\nconv.tst: mk-conv-tst.sh | $(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(SHELL) $(srcdir)/mk-conv-tst.sh > $@-t && \\\n\tmv $@-t $@\n\nsparse.tst: mk-sparse-tst.sh | $(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t$(SHELL) $(srcdir)/mk-sparse-tst.sh > $@-t && \\\n\tmv $@-t $@\n\nGENERATED_BC_OVERLOADS_DIRS := \\\n  $(shell $(SHELL) $(srcdir)/mk-bc-overloads-tst.sh $(abs_top_builddir)/test --list-dirs)\n\nGENERATED_BC_OVERLOADS_FILES := \\\n  $(shell $(SHELL) $(srcdir)/mk-bc-overloads-tst.sh $(abs_top_builddir)/test --list-files)\n\n$(GENERATED_BC_OVERLOADS_FILES): mk-bc-overloads-tst-stamp\n\n.bc-overload-tests-stamp: mk-bc-overloads-tst.sh bc-overloads-expected | $(octave_dirstamp)\n\t$(AM_V_GEN)rm -f $@ && \\\n\t$(SHELL) $(srcdir)/mk-bc-overloads-tst.sh $(abs_top_builddir)/test $(srcdir)/bc-overloads-expected && \\\n\ttouch $@\n\nGENERATED_TEST_FILES = \\\n  conv.tst \\\n  sparse.tst \\\n  .bc-overload-tests-stamp\n\nfixedtestsdir := $(octtestsdir)/fixed\n\nTEST_INST_FILES = \\\n  conv.tst \\\n  sparse.tst \\\n  $(GENERATED_BC_OVERLOADS_FILES) \\\n  $(filter-out fntests.m, $(TEST_FILES))\n\ninstall-data-local: install-test-files\n\nuninstall-local: uninstall-test-files\n\ninstall-test-files:\n\tfor f in $(TEST_INST_FILES); do \\\n\t  if test -f \"$$f\"; then d=; else d=\"$(srcdir)/\"; fi; \\\n\t  $(MKDIR_P) $(DESTDIR)$(fixedtestsdir)/`echo $$f | $(SED) 's,/*[^/]*$$,,'`; \\\n\t  $(INSTALL_DATA) $$d$$f $(DESTDIR)$(fixedtestsdir)/$$f; \\\n\tdone\n.PHONY: install-test-files\n\nuninstall-test-files:\n\tfor f in $(TEST_INST_FILES); do \\\n\t  rm -f $(DESTDIR)$(fixedtestsdir)/$$f; \\\n\tdone\n.PHONY: uninstall-test-files\n\nBUILT_SOURCES += \\\n  $(GENERATED_TEST_FILES) \\\n  $(DIRSTAMP_FILES)\n\nEXTRA_DIST += \\\n  bc-overloads-expected \\\n  mk-bc-overloads-tst.sh \\\n  mk-conv-tst.sh \\\n  mk-sparse-tst.sh \\\n  mk_bc_overloads_expected.m \\\n  show-failures.awk \\\n  $(addprefix $(srcdir)/, $(TEST_FILES)) \\\n  $(addprefix $(srcdir)/, $(noinst_TEST_FILES)) \\\n  $(MEX_TEST_SRC)\n\nCLEANFILES += \\\n  $(GENERATED_BC_OVERLOADS_FILES) \\\n  $(GENERATED_TEST_FILES)\n\nDISTCLEANFILES += \\\n  fntests.log \\\n  $(DIRSTAMP_FILES)\n\nclean-local: test-clean\n\ntest-clean:\n\trm -f $(CLEANFILES)\n\trm -rf $(GENERATED_BC_OVERLOADS_DIRS)\n\trm -rf $(COVERAGE_DIR)\n\trm -rf $(MEX_TEST_FUNCTIONS)\n\ntest-distclean: test-clean\n\trm -f $(DISTCLEANFILES)\n\ntest-maintainer-clean: test-distclean\n\trm -f $(MAINTAINERCLEANFILES)\n"
  },
  {
    "path": "test/anonymous-function.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2024-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*64783>\n%! s = struct ('re',{pi,2}, 'im',{3,4});\n%! f = @(x) x.re ;\n%! f(s);\n%! assert (ans, pi);\n"
  },
  {
    "path": "test/args.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n########################################\n## No inputs or no outputs\n\n## no input or output arguments\n%!function f ()\n%!  assert (nargin, 0);\n%!  assert (nargout, 0);\n%!endfunction\n%!test\n%! f;\n%!error <function called with too many inputs> f (1)\n%!error <function called with too many outputs> y = f ()\n\n## one input with two possible inputs\n%!function f (x, y)\n%!  assert (nargin, 1);\n%!  assert (nargout, 0);\n%!endfunction\n%!test\n%! f (1);\n%!error <function called with too many inputs> f (1, 2, 3)\n%!error <function called with too many outputs> y = f ()\n\n## no inputs, one of multiple outputs\n%!function [x, y] = f ()\n%!  assert (nargin, 0);\n%!  assert (nargout, 1);\n%!  x = 2;\n%!endfunction\n%!test\n%! assert (f (), 2);\n%!error <function called with too many inputs> f (1)\n%!error <function called with too many outputs> [x, y, z] = f ()\n\n## one of multiple inputs, one of multiple outputs\n%!function [x, y] = f (a, b)\n%!  assert (nargin, 1);\n%!  assert (nargout, 1);\n%!  x = a;\n%!endfunction\n%!test\n%! assert (f (1), 1);\n%!error <function called with too many inputs> f (1, 2, 3)\n%!error <function called with too many outputs> [x, y, z] = f ()\n\n########################################\n## Varargin, varargout\n\n## varargin and varargout with no inputs or outputs\n%!function [varargout] = f (varargin)\n%!  assert (nargin, 0);\n%!  assert (nargout, 0);\n%!endfunction\n%!test\n%! f;\n\n## varargin and varargout with one input\n%!function [varargout] = f (x, varargin)\n%!  assert (nargin, 1);\n%!  assert (nargout, 0);\n%!endfunction\n%!test\n%! f (1);\n\n## varargin and varargout with one output\n%!function [x, varargout] = f (varargin)\n%!  assert (nargin, 0);\n%!  assert (nargout, 1);\n%!  x = 2;\n%!endfunction\n%!test\n%! assert (f (), 2);\n\n## varargin and varargout with one input and output\n%!function [varargout] = f (varargin)\n%!  assert (nargin, 1);\n%!  assert (nargout, 1);\n%!  varargout{1} = varargin{1};\n%!endfunction\n%!test\n%! assert (f (1), 1);\n\n## multiple inputs, multiple outputs, but not all of either\n## WARNING: The original test did not assign the outputs, it just\n## requested them, and I think that is supposed to be an error.  It also\n## still has a non-assigned output argument.\n%!function [x, y, z] = f (a, b, c, d, e)\n%!  assert (nargin, 4);\n%!  assert (nargout, 2);\n%!  x = a;\n%!  y = b;\n%!endfunction\n%!test\n%! [s, t] = f (1, 2, 3, 4);\n%! assert ([s t], [1 2]);\n\n## Fully used varargin and varargout\n%!function [varargout] = f (varargin)\n%!  assert (nargin, 3);\n%!  assert (nargout, 4);\n%!  varargout{1} = varargin{1};\n%!  varargout{2} = varargin{2};\n%!  varargout{3} = varargin{3};\n%!  varargout{4} = 4;\n%!endfunction\n%!test\n%! [s, t, u, v] = f (1, 2, 3);\n%! assert ([s t u v], [1 2 3 4]);\n\n## Wrapper functions\n%!function [x, y, z] = f (varargin)\n%!  assert (nargin, 0);\n%!  assert (nargout, 0);\n%!  x = 3;\n%!  y = 2;\n%!  z = 1;\n%!endfunction\n%!function varargout = wrapper_1 (varargin)\n%!  assert (nargout, 0);\n%!  [varargout{1:nargout}] = f ();\n%!endfunction\n%!function varargout = wrapper_2 (varargin)\n%!  assert (nargout, 0);\n%!  varargout = cell (1, nargout);\n%!  [varargout{1:nargout}] = f ();\n%!endfunction\n%!function varargout = wrapper_3 (varargin)\n%!  assert (nargout, 0);\n%!  varargout = cell (1, nargout);\n%!  [varargout{:}] = f ();\n%!endfunction\n%!test\n%! wrapper_1 ();\n%! assert (ans, 3);\n%! wrapper_2 ();\n%! assert (ans, 3);\n%! wrapper_3 ();\n%! assert (ans, 3);\n\n## Test default arguments\n## numeric\n%!function f (x = 0)\n%!  assert (x, 0);\n%!endfunction\n%!test\n%! f()\n\n## numeric vector (spaces)\n%!function f (x = [0 1 2])\n%!  assert (x, [0 1 2]);\n%!endfunction\n%!test\n%! f()\n\n## numeric vector (range)\n%!function f (x = 1:3)\n%!  assert (x, 1:3);\n%!endfunction\n%!test\n%! f()\n\n## numeric vector (commas)\n%!function f (x = [0,1,2])\n%!  assert (x, [0 1 2]);\n%!endfunction\n%!test\n%! f()\n\n## numeric vector (commas and spaces)\n%!function f (x = [0, 1, 2])\n%!  assert (x, [0 1 2]);\n%!endfunction\n%!test\n%! f()\n\n## numeric matrix\n%!function f (x = [0, 1, 2;3, 4, 5])\n%!  assert (x, [0 1 2;3 4 5]);\n%!endfunction\n%!test\n%! f()\n\n## empty cell\n%!function f (x = {})\n%!  assert (x, {});\n%!endfunction\n%!test\n%! f()\n\n## full cell\n%!function f (x = {1})\n%!  assert (x, {1});\n%!endfunction\n%!test\n%! f()\n\n## many cells\n%!function f (x = {1 'a' \"b\" 2.0 struct(\"a\", 3)})\n%!  assert (x, {1 'a' \"b\" 2.0 struct(\"a\", 3)});\n%!endfunction\n%!test\n%! f()\n\n## struct\n%!function f (x = struct (\"a\", 3))\n%!  assert (x, struct (\"a\", 3));\n%!endfunction\n%!test\n%! f()\n\n## char (double quotes)\n%!function f (x = \"a\")\n%!  assert (x, \"a\");\n%!endfunction\n%!test\n%! f()\n\n## char (single quotes)\n%!function f (x = 'a')\n%!  assert (x, \"a\");\n%!endfunction\n%!test\n%! f()\n\n## char (string, double quotes)\n%!function f (x = \"abc123\")\n%!  assert (x, \"abc123\");\n%!endfunction\n%!test\n%! f()\n\n## char (string, double quotes, punctuation)\n%!function f (x = \"abc123`1234567890-=~!@#$%^&*()_+[]{}|;':\\\",./<>?\\\\\")\n%!  assert (x, \"abc123`1234567890-=~!@#$%^&*()_+[]{}|;':\\\",./<>?\\\\\");\n%!endfunction\n%!test\n%! f()\n\n## Function handle (builtin)\n%!function f (x = @sin)\n%!  finfo = functions (x);\n%!  fname = finfo.function;\n%!  assert (is_function_handle (x) && strcmp (fname, \"sin\"));\n%!endfunction\n%!test\n%! f()\n\n## Function handle (anonymous)\n%!function f (x = @(x) x.^2)\n%!  finfo = functions (x);\n%!  ftype = finfo.type;\n%!  assert (is_function_handle (x) && strcmp (ftype, \"anonymous\"));\n%!endfunction\n%!test\n%! f()\n"
  },
  {
    "path": "test/bc-overloads-expected",
    "content": "double double double\ndouble single single\ndouble logical double\ndouble char double\ndouble int8 int8\ndouble int16 int16\ndouble int32 int32\ndouble int64 int64\ndouble uint8 uint8\ndouble uint16 uint16\ndouble uint32 uint32\ndouble uint64 uint64\ndouble cell cell\ndouble struct struct\ndouble function_handle function_handle\nsingle double single\nsingle single single\nsingle logical single\nsingle char single\nsingle int8 int8\nsingle int16 int16\nsingle int32 int32\nsingle int64 int64\nsingle uint8 uint8\nsingle uint16 uint16\nsingle uint32 uint32\nsingle uint64 uint64\nsingle cell cell\nsingle struct struct\nsingle function_handle function_handle\nlogical double double\nlogical single single\nlogical logical logical\nlogical char char\nlogical int8 int8\nlogical int16 int16\nlogical int32 int32\nlogical int64 int64\nlogical uint8 uint8\nlogical uint16 uint16\nlogical uint32 uint32\nlogical uint64 uint64\nlogical cell cell\nlogical struct struct\nlogical function_handle function_handle\nchar double char\nchar single single\nchar logical char\nchar char char\nchar int8 int8\nchar int16 int16\nchar int32 int32\nchar int64 int64\nchar uint8 uint8\nchar uint16 uint16\nchar uint32 uint32\nchar uint64 uint64\nchar cell cell\nchar struct struct\nchar function_handle function_handle\nint8 double int8\nint8 single int8\nint8 logical int8\nint8 char int8\nint8 int8 int8\nint8 int16 int8\nint8 int32 int8\nint8 int64 int8\nint8 uint8 int8\nint8 uint16 int8\nint8 uint32 int8\nint8 uint64 int8\nint8 cell cell\nint8 struct struct\nint8 function_handle function_handle\nint16 double int16\nint16 single int16\nint16 logical int16\nint16 char int16\nint16 int8 int16\nint16 int16 int16\nint16 int32 int16\nint16 int64 int16\nint16 uint8 int16\nint16 uint16 int16\nint16 uint32 int16\nint16 uint64 int16\nint16 cell cell\nint16 struct struct\nint16 function_handle function_handle\nint32 double int32\nint32 single int32\nint32 logical int32\nint32 char int32\nint32 int8 int32\nint32 int16 int32\nint32 int32 int32\nint32 int64 int32\nint32 uint8 int32\nint32 uint16 int32\nint32 uint32 int32\nint32 uint64 int32\nint32 cell cell\nint32 struct struct\nint32 function_handle function_handle\nint64 double int64\nint64 single int64\nint64 logical int64\nint64 char int64\nint64 int8 int64\nint64 int16 int64\nint64 int32 int64\nint64 int64 int64\nint64 uint8 int64\nint64 uint16 int64\nint64 uint32 int64\nint64 uint64 int64\nint64 cell cell\nint64 struct struct\nint64 function_handle function_handle\nuint8 double uint8\nuint8 single uint8\nuint8 logical uint8\nuint8 char uint8\nuint8 int8 uint8\nuint8 int16 uint8\nuint8 int32 uint8\nuint8 int64 uint8\nuint8 uint8 uint8\nuint8 uint16 uint8\nuint8 uint32 uint8\nuint8 uint64 uint8\nuint8 cell cell\nuint8 struct struct\nuint8 function_handle function_handle\nuint16 double uint16\nuint16 single uint16\nuint16 logical uint16\nuint16 char uint16\nuint16 int8 uint16\nuint16 int16 uint16\nuint16 int32 uint16\nuint16 int64 uint16\nuint16 uint8 uint16\nuint16 uint16 uint16\nuint16 uint32 uint16\nuint16 uint64 uint16\nuint16 cell cell\nuint16 struct struct\nuint16 function_handle function_handle\nuint32 double uint32\nuint32 single uint32\nuint32 logical uint32\nuint32 char uint32\nuint32 int8 uint32\nuint32 int16 uint32\nuint32 int32 uint32\nuint32 int64 uint32\nuint32 uint8 uint32\nuint32 uint16 uint32\nuint32 uint32 uint32\nuint32 uint64 uint32\nuint32 cell cell\nuint32 struct struct\nuint32 function_handle function_handle\nuint64 double uint64\nuint64 single uint64\nuint64 logical uint64\nuint64 char uint64\nuint64 int8 uint64\nuint64 int16 uint64\nuint64 int32 uint64\nuint64 int64 uint64\nuint64 uint8 uint64\nuint64 uint16 uint64\nuint64 uint32 uint64\nuint64 uint64 uint64\nuint64 cell cell\nuint64 struct struct\nuint64 function_handle function_handle\ncell double cell\ncell single cell\ncell logical cell\ncell char cell\ncell int8 cell\ncell int16 cell\ncell int32 cell\ncell int64 cell\ncell uint8 cell\ncell uint16 cell\ncell uint32 cell\ncell uint64 cell\ncell cell cell\ncell struct cell\ncell function_handle function_handle\nstruct double struct\nstruct single struct\nstruct logical struct\nstruct char struct\nstruct int8 struct\nstruct int16 struct\nstruct int32 struct\nstruct int64 struct\nstruct uint8 struct\nstruct uint16 struct\nstruct uint32 struct\nstruct uint64 struct\nstruct cell struct\nstruct struct struct\nstruct function_handle function_handle\nfunction_handle double function_handle\nfunction_handle single function_handle\nfunction_handle logical function_handle\nfunction_handle char function_handle\nfunction_handle int8 function_handle\nfunction_handle int16 function_handle\nfunction_handle int32 function_handle\nfunction_handle int64 function_handle\nfunction_handle uint8 function_handle\nfunction_handle uint16 function_handle\nfunction_handle uint32 function_handle\nfunction_handle uint64 function_handle\nfunction_handle cell function_handle\nfunction_handle struct function_handle\nfunction_handle function_handle function_handle\n"
  },
  {
    "path": "test/bug-31371.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*31371>\n%! % Work around MATLAB bug where f(x)(y) is invalid syntax\n%! % (This bug does not apply to Octave)\n%!\n%! C = @(fcn,x) fcn(x);\n%! C2 = @(fcn,x,y) fcn(x,y);\n%!\n%! % Church Booleans\n%! T = @(t,f) t;\n%! F = @(t,f) f;\n%!\n%! % Church Numerals\n%! Zero  = @(fcn,x) x;\n%! One   = @(fcn,x) fcn(x);\n%! Two   = @(fcn,x) fcn(fcn(x));\n%! Three = @(fcn,x) fcn(fcn(fcn(x)));\n%! Four  = @(fcn,x) fcn(fcn(fcn(fcn(x))));\n%!\n%! % Arithmetic Operations\n%! Inc = @(a) @(f,x) f(a(f,x)); % Increment\n%! Add = @(a,b) @(f,x) a(f,b(f,x));\n%! Mult = @(a,b) @(f,x) a(@(x) b(f,x),x);\n%! Dec = @(a) @(f,x) C(a(@(g) @(h) h(g(f)), @(u) x), @(u) u); % Decrement\n%! Sub = @(a,b) b(Dec, a);\n%!\n%! % Renderer - Convert church numeral to \"real\" number\n%! Render = @(n) n(@(n) n+1,0);\n%!\n%! % Predicates\n%! Iszero = @(n) n(@(x) F, T);\n%!\n%! % Y combinator implements recursion\n%! Ycomb = @(f) C(@(g) f(@(x) C(g(g), x)), ...\n%!                @(g) f(@(x) C(g(g), x)));\n%!\n%! Factorial = Ycomb(@(f) @(n) C(C2(Iszero(n), ...\n%!                   @(d) One, @(d) Mult(n, f(Dec(n)))),0));\n%!\n%! assert (Render (Factorial (Two)), 2);\n%! assert (Render (Factorial (Three)), 6);\n%! assert (Render (Factorial (Four)), 24);\n"
  },
  {
    "path": "test/bug-35448/bug-35448.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*35448>\n%! global gfun;\n%! gfun = @fB;\n%! y = fA (e);\n%! assert (y, e);\n%! clear -global gfun;  # cleanup after test\n\n%!test <*35448>\n%! global gfun;\n%! gfun = @fC;\n%! y = fA (e);\n%! assert (y, e);\n%! clear -global gfun;  # cleanup after test\n"
  },
  {
    "path": "test/bug-35448/fA.m",
    "content": "## fA.m\nfunction y = fA (x, f)\n  global gfun\n  if (nargin < 2)\n    y = fA (x, gfun);\n  else\n    w = feval (f, x);\n    y = feval (@fB, w);\n  endif\nendfunction\n"
  },
  {
    "path": "test/bug-35448/fB.m",
    "content": "## fB.m\nfunction y = fB (x)\n  y = x;\nendfunction\n"
  },
  {
    "path": "test/bug-35448/fC.m",
    "content": "## fC.m\nfunction y = fC (x)\n  y = x;\nendfunction\n"
  },
  {
    "path": "test/bug-35448/module.mk",
    "content": "bug_35448_TEST_FILES = \\\n  %reldir%/bug-35448.tst \\\n  %reldir%/fA.m \\\n  %reldir%/fB.m \\\n  %reldir%/fC.m\n\nTEST_FILES += $(bug_35448_TEST_FILES)\n"
  },
  {
    "path": "test/bug-35881/bug-35881.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*35881>\n%! global _tstvar_;  # Final test does \"clear all\" which removes this var.\n%!\n%! _tstvar_ = struct (\"init1\",-1, \"a1\",-1, \"init2\",-1, \"a2\",-1);\n%! bug35881 (0);\n%! assert (_tstvar_, struct (\"init1\",true, \"a1\",1, \"init2\",false, \"a2\",1));\n%! clear -f bug35881\n%!\n%! _tstvar_ = struct (\"init1\",-1, \"a1\",-1, \"init2\",-1, \"a2\",-1);\n%! bug35881 (1);\n%! assert (_tstvar_, struct (\"init1\",true, \"a1\",1, \"init2\",false, \"a2\",1));\n%!\n%! _tstvar_ = struct (\"init1\",-1, \"a1\",-1, \"init2\",-1, \"a2\",-1);\n%! fail (\"bug35881 (2)\", \"'a' undefined near line\");\n"
  },
  {
    "path": "test/bug-35881/bug35881.m",
    "content": "function bug35881 (flag = 0)\n  persistent a;\n  global _tstvar_;\n\n  if (isempty (a))\n    a = 1;\n  endif\n\n  _tstvar_.init1 = subf ();\n  _tstvar_.a1 = a;\n  ##ML:fprintf ('a=%d\\n', a);\n\n  switch (flag)\n    case 0\n      clear subf;\n    case 1\n      clear functions;\n    case 2\n      clear all;\n  endswitch\n\n  _tstvar_.init2 = subf ();\n  _tstvar_.a2 = a;\n  ##ML:fprintf ('a=%d\\n', a);\n  ##ML:fprintf ('------\\n\\n');\nendfunction\n\nfunction retval = subf ()\n  persistent x;\n\n  retval = false;\n  ##ML:fprintf ('subf: ');\n  if (isempty (x))\n    x = 1;\n    retval = true;\n    ##ML:fprintf ('INIT, ');\n  endif\n\nendfunction\n\n## Expected results from Matlab 2016A\n## Uncomment \"##ML:\"\n#{\n>> clear all;  bug35881 (0)\nsubf: INIT, a=1\nsubf: a=1\n------\n\n>> clear all;  bug35881 (1)\nsubf: INIT, a=1\nsubf: a=1\n------\n\n>> clear all;  bug35881 (2)\nsubf: INIT, a=1\nsubf: Reference to a cleared variable a.\nError in test_clear_inside_function (line 13)\nsubf ();  fprintf ('a=%d\\n', a);\n#}\n"
  },
  {
    "path": "test/bug-35881/module.mk",
    "content": "bug_35881_TEST_FILES = \\\n  %reldir%/bug-35881.tst \\\n  %reldir%/bug35881.m\n\nTEST_FILES += $(bug_35881_TEST_FILES)\n"
  },
  {
    "path": "test/bug-36025/@testclass/one.m",
    "content": "%% function ONE return item \"X\"\n\nfunction a = one (m)\n  a = m.x;\nendfunction\n"
  },
  {
    "path": "test/bug-36025/@testclass/testclass.m",
    "content": "function m = testclass (x,y)\n  m = struct ('x',x,'y',y);\n  m = class (m,\"testclass\");\nendfunction\n"
  },
  {
    "path": "test/bug-36025/@testclass/two.m",
    "content": "%% function TWO returns item \"Y\"\n\nfunction a = one (m)\n  a = m.y;\nendfunction\n"
  },
  {
    "path": "test/bug-36025/bug-36025.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*36025>\n%! warning (\"off\", \"Octave:function-name-clash\", \"local\");\n%! f = testclass (1, 2);\n%! assert (one (f), 1);\n%! assert (two (f), 2);\n%! rehash ();\n%! assert (one (f), 1);\n%! assert (two (f), 2);\n%! assert (two (f), 2);\n"
  },
  {
    "path": "test/bug-36025/module.mk",
    "content": "bug_36025_TEST_FILES = \\\n  %reldir%/@testclass/one.m \\\n  %reldir%/@testclass/testclass.m \\\n  %reldir%/@testclass/two.m \\\n  %reldir%/bug-36025.tst\n\nTEST_FILES += $(bug_36025_TEST_FILES)\n"
  },
  {
    "path": "test/bug-38236/bug-38236.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*38236>\n%! u_vr\n"
  },
  {
    "path": "test/bug-38236/df_vr.m",
    "content": "## df_vr.m\nvr = 7;\n"
  },
  {
    "path": "test/bug-38236/module.mk",
    "content": "bug_38236_TEST_FILES = \\\n  %reldir%/bug-38236.tst \\\n  %reldir%/df_vr.m \\\n  %reldir%/u_vr.m\n\nTEST_FILES += $(bug_38236_TEST_FILES)\n"
  },
  {
    "path": "test/bug-38236/u_vr.m",
    "content": "## u_vr.m\n\n## define and exectute \"__demo__\" once\neval (\"function __demo__ ();  df_vr;  v = vr * 2; endfunction\");\n__demo__;\n\n## clear definition of \"__demo__\"\nclear __demo__\n\n## define and exectute \"__demo__\" once more\neval (\"function __demo__ ();  df_vr;  v = vr * 2; endfunction\");\n__demo__;\n"
  },
  {
    "path": "test/bug-38691/bug-38691.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*38691>\n%! path_orig = path ();\n%! unwind_protect\n%!   addpath dir1;\n%!   [d1_r, d1_f1, d1_f2, d1_f3] = func1 (0);\n%!   addpath dir2;\n%!   [d2_r, d2_f1, d2_f2, d2_f3] = func1 (0);\n%!   assert (d1_r, 0);\n%!   assert (d2_r, 1);\n%!   assert (d1_f1, \"dir1/func1\");\n%!   assert (d1_f2, \"dir1/func2\");\n%!   assert (d1_f3, \"dir1/func3\");\n%!   assert (d2_f1, \"dir2/func1\");\n%!   assert (d2_f2, \"dir2/func2\");\n%!   assert (d2_f3, \"dir2/func3\");\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-38691/dir1/func1.m",
    "content": "function [r, f1, f2, f3] = func1 (x)\n  f1 = \"dir1/func1\";\n  [r, f2, f3] = feval (\"func2\", x);\nendfunction\n\nfunction [r, f2, f3] = func2 (x)\n  f2 = \"dir1/func2\";\n  [r, f3] = feval (\"func3\", x);\nendfunction\n\nfunction [r, f3] = func3 (x)\n  f3 = \"dir1/func3\";\n  r = x;\nendfunction\n"
  },
  {
    "path": "test/bug-38691/dir2/func1.m",
    "content": "function [r, f1, f2, f3] = func1 (x)\n  f1 = \"dir2/func1\";\n  [r, f2, f3] = feval (\"func2\", x);\nendfunction\n"
  },
  {
    "path": "test/bug-38691/dir2/func2.m",
    "content": "function [r, f2, f3] = func2 (x)\n  f2 = \"dir2/func2\";\n  [r, f3] = feval (\"func3\", x);\nendfunction\n"
  },
  {
    "path": "test/bug-38691/dir2/func3.m",
    "content": "function [r, f3] = func3 (x)\n  f3 = \"dir2/func3\";\n  r = 1;\nendfunction\n"
  },
  {
    "path": "test/bug-38691/module.mk",
    "content": "bug_38691_TEST_FILES = \\\n  %reldir%/bug-38691.tst \\\n  %reldir%/dir1/func1.m \\\n  %reldir%/dir2/func1.m \\\n  %reldir%/dir2/func2.m \\\n  %reldir%/dir2/func3.m\n\nTEST_FILES += $(bug_38691_TEST_FILES)\n"
  },
  {
    "path": "test/bug-40117.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!function __mktestfun_40117__ (file, varargin)\n%!  unwind_protect\n%!    fid = fopen (file, \"w\");\n%!    fprintf (fid, \"%s\\n\", varargin{:});\n%!  unwind_protect_cleanup\n%!    if (fid > 0)\n%!      fclose (fid);\n%!    endif\n%!  end_unwind_protect\n%!endfunction\n\n%!test <*40117>\n%! unwind_protect\n%!   tmp_dir = tempname ();\n%!   mkdir (tmp_dir);\n%!   a_dir = fullfile (tmp_dir, \"a\");\n%!   a_private_dir = fullfile (a_dir, \"private\");\n%!   mkdir (a_dir);\n%!   mkdir (a_private_dir);\n%!   __mktestfun_40117__ (fullfile (a_dir, \"main_40117.m\"),\n%!                        \"function r = main_40117 ()\",\n%!                        \"  r = p1_40117 ();\",\n%!                        \"endfunction\");\n%!   __mktestfun_40117__ (fullfile (a_private_dir, \"p1_40117.m\"),\n%!                        \"function r = p1_40117 ()\",\n%!                        \"  r = p2_40117 ();\",\n%!                        \"endfunction\");\n%!   __mktestfun_40117__ (fullfile (a_private_dir, \"p2_40117.m\"),\n%!                        \"function r = p2_40117 ()\",\n%!                        \"  r = 'a_p2_40117';\",\n%!                        \"endfunction\");\n%!   addpath (a_dir);\n%!   assert (main_40117 (), \"a_p2_40117\");\n%!\n%!   ## Update the secondary private function, attempting to avoid\n%!   ## filesystem timestamp resolution problems.\n%!   pause (1);\n%!   __mktestfun_40117__ (fullfile (a_private_dir, \"p2_40117.m\"),\n%!                        \"function r = p2_40117 ()\",\n%!                        \"  r = 'new function!';\",\n%!                        \"endfunction\");\n%!\n%!   ## Force new functions to be found.\n%!   rehash ();\n%!\n%!   assert (main_40117 (), \"new function!\");\n%! unwind_protect_cleanup\n%!   rmpath (a_dir);\n%!   confirm_recursive_rmdir (false, \"local\");\n%!   rmdir (tmp_dir, \"s\");\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-41723/bug-41723.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*41723>\n%! a = class_bug41723 ();\n%! assert (a.value, 42);\n%! assert (a.getval (), 84);\n"
  },
  {
    "path": "test/bug-41723/class_bug41723.m",
    "content": "classdef class_bug41723 < handle\n  properties\n    value\n  endproperties\n  methods\n    function obj = class_bug41723 ()\n      obj.value = helper_function ();\n    endfunction\n    function val = getval (obj)\n      val = helper_function_2 ();\n    endfunction\n  endmethods\nendclassdef\n\nfunction y = helper_function ()\n  y = 42;\nendfunction\n\nfunction y = helper_function_2 (in)\n  if (! nargin)\n    y = helper_function_2 (true);\n  else\n    y = 2 * helper_function ();\n  endif\nendfunction\n"
  },
  {
    "path": "test/bug-41723/module.mk",
    "content": "bug_41723_TEST_FILES = \\\n  %reldir%/bug-41723.tst \\\n  %reldir%/class_bug41723.m\n\nTEST_FILES += $(bug_41723_TEST_FILES)\n"
  },
  {
    "path": "test/bug-44643/bug-44643.tst",
    "content": "%!test <44643>\n%! a = bug44643 ();\n%! b = bug44643 ();\n%! a.parent = b;\n%! b.child  = a;\n%!\n%! assert (isequal (a, b));\n%! assert (isequal (a, a));\n"
  },
  {
    "path": "test/bug-44643/bug44643.m",
    "content": "classdef bug44643 < handle\n  properties\n    child\n    parent\n  end\nend\n"
  },
  {
    "path": "test/bug-44643/module.mk",
    "content": "bug_44643_TEST_FILES = \\\n  %reldir%/bug-44643.tst \\\n  %reldir%/bug44643.m\n\nTEST_FILES += $(bug_44643_TEST_FILES)\n"
  },
  {
    "path": "test/bug-44940/bug-44940.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2015-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*44940>\n%! a = class_bug44940 ();\n%! b = a;\n%! c = a ();\n%! a.child = 100;\n%! assert (a.child, b.child);\n%! assert (a.child, c.child);\n%! c.child = 500;\n%! assert (a.child, b.child);\n%! assert (a.child, c.child);\n"
  },
  {
    "path": "test/bug-44940/class_bug44940.m",
    "content": "classdef class_bug44940 < handle\n  properties\n    child\n  endproperties\nendclassdef\n"
  },
  {
    "path": "test/bug-44940/module.mk",
    "content": "bug_44940_TEST_FILES = \\\n  %reldir%/bug-44940.tst \\\n  %reldir%/class_bug44940.m\n\nTEST_FILES += $(bug_44940_TEST_FILES)\n"
  },
  {
    "path": "test/bug-45351/bug-45351.tst",
    "content": "%!shared obj, h1, h2, h3\n%! obj = bug45351 ();\n%! [h1, h2, h3] = obj.get_handles ();\n%!assert <*45351> (obj.bar (1), 'bug45351.foo: 1')\n%!assert <*45351> (obj.bar (2), 'bug45351.foo: 2')\n%!assert <*45351> (obj.bar (3), 'bug45351.foo: 3')\n%!assert <*45351> (h1 (obj, 1), 'bug45351.foo: 1')\n%!assert <*45351> (h2 (obj, 2), 'bug45351.foo: 2')\n%!assert <*45351> (h3 (obj, 3), 'bug45351.foo: 3')\n%!error (obj.h1 (1))\n%!error (obj.h2 (2))\n%!error (obj.h3 (3))\n"
  },
  {
    "path": "test/bug-45351/bug45351.m",
    "content": "classdef bug45351\n\n  properties (Hidden, SetAccess = protected)\n    h1 = [];% handle to function\n    h2 = [];% handle to function\n    h3 = [];% handle to function\n  end\n\n  methods\n    function self = bug45351 ()\n      self.h1 = @foo;\n      self.h2 = @(self, n) self.foo (n);\n      self.h3 = @(~, n) self.foo (n);\n    end\n    function [h1, h2, h3] = get_handles (self)\n      h1 = self.h1;\n      h2 = self.h2;\n      h3 = self.h3;\n    end\n    function r = bar (self, hnum)\n      switch (hnum)\n        case 1\n          r = self.h1 (self, hnum);\n        case 2\n          r = self.h2 (self, hnum);\n        case 3\n          r = self.h3 (self, hnum);\n      end\n    end\n  end\n\n  methods (Hidden, Access = protected)\n    function r = foo (self, n)\n      r = sprintf ('bug45351.foo: %d', n);\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-45351/module.mk",
    "content": "bug_45351_TEST_FILES = \\\n  %reldir%/bug45351.m \\\n  %reldir%/bug-45351.tst\n\nTEST_FILES += $(bug_45351_TEST_FILES)\n"
  },
  {
    "path": "test/bug-45969.tst",
    "content": "%!test <*45969>\n%! text_filename = tempname ();\n%! binary_filename = tempname ();\n%! a = 2;\n%! b = 10;\n%! c = 20;\n%! f1 = @ (f, x) f (x) + a;\n%! f2 = @ (y) f1 (@ (z) z^2 + b * y, y) + c;\n%! f2_arg = 5;\n%! save_default_options (\"-text\", \"local\");\n%! unwind_protect\n%!   save (text_filename, \"f2\");\n%!   save (\"-binary\", binary_filename, \"f2\");\n%!   text = load (text_filename);\n%!   binary = load (binary_filename);\n%!   assert (f2 (f2_arg), text.f2 (f2_arg));\n%!   assert (f2 (f2_arg), binary.f2 (f2_arg));\n%! unwind_protect_cleanup\n%!   delete ([text_filename, '*']);\n%!   delete ([binary_filename, '*']);\n%! end_unwind_protect\n\n%!testif HAVE_HDF5 <*45969>\n%! hdf5_filename = tempname ();\n%! a = 2;\n%! b = 10;\n%! c = 20;\n%! f1 = @ (f, x) f (x) + a;\n%! f2 = @ (y) f1 (@ (z) z^2 + b * y, y) + c;\n%! f2_arg = 5;\n%! save_default_options (\"-text\", \"local\");\n%! unwind_protect\n%!   save (\"-hdf5\", hdf5_filename, \"f2\");\n%!   hdf5 = load (hdf5_filename);\n%!   assert (f2 (f2_arg), hdf5.f2 (f2_arg));\n%! unwind_protect_cleanup\n%!   delete ([hdf5_filename, '*']);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-45972.tst",
    "content": "%!test <*45972>\n%! ascii_filename = tempname ();\n%! binary_filename = tempname ();\n%! f = @ (x, y, varargin) x + y + varargin{1};\n%! unwind_protect\n%!   save (\"-text\", ascii_filename, \"f\");\n%!   save (\"-binary\", binary_filename, \"f\");\n%!   ascii = load (ascii_filename);\n%!   binary = load (binary_filename);\n%!   assert (f (1, 2, 3), ascii.f (1, 2, 3));\n%!   assert (f (1, 2, 3), binary.f (1, 2, 3));\n%! unwind_protect_cleanup\n%!   delete ([ascii_filename, '*']);\n%!   delete ([binary_filename, '*']);\n%! end_unwind_protect\n\n%!testif HAVE_HDF5 <*45972>\n%! hdf5_filename = tempname ();\n%! f = @ (x, y, varargin) x + y + varargin{1};\n%! unwind_protect\n%!   save (\"-hdf5\", hdf5_filename, \"f\");\n%!   hdf5 = load (hdf5_filename);\n%!   assert (f (1, 2, 3), hdf5.f (1, 2, 3));\n%! unwind_protect_cleanup\n%!   delete ([hdf5_filename, '*']);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-46330.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## bug #46330: segfault with matrices containing Inf & NaN\n\n%!warning\n%! a = [-0.46E-01,            0.10681415316, 0.0,   -0.17121680433;\n%!      -0.1675901504661613, -0.515,         1.0,    0.6420630320636088E-02;\n%!       0.1543104215347786, -0.547945,     -0.906, -0.1521689385990753E-02;\n%!       0.0,                 0.0,           1.0,    0.0];\n%!\n%! b = [0.1602300107479095,      0.2111848453E-02;\n%!      0.8196877780963616E-02, -0.3025E-01;\n%!      0.9173594317692437E-01, -0.75283075;\n%!      0.0,                     0.0];\n%!\n%! c = [1.0, 0.0, 0.0, 0.0;\n%!      0.0, 0.0, 0.0, 1.0];\n%!\n%! ## This statement caused an error in LAPACK and eventually caused\n%! ## a segmentation fault.\n%! ## Triggers \"warning: matrix singular to machine precision\"\n%! assert (c / (i * diag (Inf (1, 4)) - a) * b, zeros (2, 2));\n"
  },
  {
    "path": "test/bug-46660/bug-46660.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*46660>\n%! a(1) = class_bug46660 ();\n%! a(2) = class_bug46660 ();\n%! a(2).x = 123;\n%! assert (a(2).x, 123);\n%! assert (isempty (a(2).y));\n%!\n%! # writing into a(2).y may not alter a(2).x\n%! a(2).y = 321;\n%! assert (a(2).x, 123);\n%! assert (a(2).y, 321);\n"
  },
  {
    "path": "test/bug-46660/class_bug46660.m",
    "content": "classdef class_bug46660\n  properties\n    x\n    y\n  endproperties\nendclassdef\n"
  },
  {
    "path": "test/bug-46660/module.mk",
    "content": "bug_46660_TEST_FILES = \\\n  %reldir%/bug-46660.tst \\\n  %reldir%/class_bug46660.m\n\nTEST_FILES += $(bug_46660_TEST_FILES)\n"
  },
  {
    "path": "test/bug-47680/bug-47680.tst",
    "content": "%!shared obj\n%! obj = sub_bug47680 (\"foo\");\n%!assert <*47680> (obj.meth1 (), \"foo:super:meth1:sub:meth1\")\n%!assert <*47680> (obj.meth2 (), \"foo:super:meth2:sub:meth2\")\n%!assert <*47680> (obj.meth3 (), \"foo:super:meth3:sub:meth3\")\n%!assert <*47680> (obj.meth4 (), \"foo:super:meth4:sub:meth4\")\n"
  },
  {
    "path": "test/bug-47680/module.mk",
    "content": "bug_47680_TEST_FILES = \\\n  %reldir%/bug-47680.tst \\\n  %reldir%/sub_bug47680.m \\\n  %reldir%/super_bug47680.m\n\nTEST_FILES += $(bug_47680_TEST_FILES)\n"
  },
  {
    "path": "test/bug-47680/sub_bug47680.m",
    "content": "classdef sub_bug47680 < super_bug47680\n  methods\n    function obj = sub_bug47680 (x)\n      obj = obj@super_bug47680 (x);\n    endfunction\n    function r = meth1 (obj)\n      r = meth1@super_bug47680 (obj, \"sub:meth1\");\n    endfunction\n    function r = meth2 (obj)\n      r = obj.meth2@super_bug47680 (\"sub:meth2\");\n    endfunction\n    function r = meth3 (obj)\n      r = meth3@super_bug47680 (obj, \"sub:meth3\");\n    endfunction\n    function r = meth4 (obj)\n      r = obj.meth4@super_bug47680 (\"sub:meth4\");\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-47680/super_bug47680.m",
    "content": "classdef super_bug47680\n  properties\n    tag;\n  endproperties\n  methods\n    function obj = super_bug47680 (x)\n      obj.tag = x;\n    endfunction\n    function r = meth1 (obj, x)\n      r = [obj.tag \":super:meth1:\" x];\n    endfunction\n    function r = meth2 (obj, x)\n      r = [obj.tag \":super:meth2:\" x];\n    endfunction\n    function r = meth3 (obj, x)\n      r = [obj.tag \":super:meth3:\" x];\n    endfunction\n    function r = meth4 (obj, x)\n      r = [obj.tag \":super:meth4:\" x];\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-48693/bug-48693.tst",
    "content": "%!test\n%! x = bug48693();\n%! assert ({x{1:10}}, num2cell (zeros(1,10)));\n"
  },
  {
    "path": "test/bug-48693/bug48693.m",
    "content": "classdef bug48693 < handle\n  methods\n    function varargout = subsref (x, idx)\n      varargout = num2cell (zeros (size (idx(1).subs{1})));\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-48693/module.mk",
    "content": "bug_48693_TEST_FILES = \\\n  %reldir%/bug48693.m \\\n  %reldir%/bug-48693.tst\n\nTEST_FILES += $(bug_48693_TEST_FILES)\n"
  },
  {
    "path": "test/bug-49379/bug-49379.tst",
    "content": "%!test <49379>\n%! a1 = 1;\n%! a2 = 2;\n%! obj = class_bug49379 (a1, a2);\n%! assert (obj.ctor_arg_names (), {\"a1\", \"a2\"});\n%! meth (obj, a2, a1);\n%! assert (obj.meth_arg_names (), {\"obj\", \"a2\", \"a1\"});\n%! obj.meth (a2, a1);\n%! assert (obj.meth_arg_names (), {\"obj\", \"a2\", \"a1\"});\n"
  },
  {
    "path": "test/bug-49379/class_bug49379.m",
    "content": "classdef class_bug49379 < handle\n  properties\n    m_ctor_arg_names = {};\n    m_meth_arg_names = {};\n  endproperties\n  methods\n    function obj = class_bug49379 (x, y)\n      obj.m_ctor_arg_names = {inputname(1), inputname(2)};\n    endfunction\n    function meth (obj, x, y)\n      obj.m_meth_arg_names = {inputname(1), inputname(2), inputname(3)};\n    endfunction\n    function names = ctor_arg_names (obj)\n      names = obj.m_ctor_arg_names;\n    endfunction\n    function names = meth_arg_names (obj)\n      names = obj.m_meth_arg_names;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-49379/module.mk",
    "content": "bug_49379_TEST_FILES = \\\n  %reldir%/bug-49379.tst \\\n  %reldir%/class_bug49379.m\n\nTEST_FILES += $(bug_49379_TEST_FILES)\n"
  },
  {
    "path": "test/bug-49904.tst",
    "content": "%!shared A\n%! A = [ ...\n%!  1.00003+0.00000i, -0.68292+0.26406i, -0.57670+0.25291i,  0.34986+0.03335i;\n%! -0.68292-0.26406i,  0.94539+0.00000i,  0.69006-0.03967i, -0.43847+0.38619i;\n%! -0.57670-0.25291i,  0.69006+0.03967i,  0.95260+0.00000i, -0.34734+0.40728i;\n%!  0.34986-0.03335i, -0.43847-0.38619i, -0.34734-0.40728i,  0.98356+0.00000i];\n%!\n\n%!test <*49904>\n%! [Ainv, rcond] = inv (A);\n%! assert (ishermitian (Ainv));\n%! assert (A * Ainv, eye (4, 'double'), eps ('double') / rcond);\n\n%!test <*49904>\n%! [Ainv, rcond] = inv (single (A));\n%! assert (ishermitian (Ainv));\n%! assert (A * Ainv, eye (4, 'single'), eps ('single') / rcond);\n"
  },
  {
    "path": "test/bug-50014/bug-50014.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!error <duplicate subfunction or nested function name>\n%! duplicate_nested_function ()\n\n%!assert <*50014> (duplicate_nested_in_subfunction_ok (), 3)\n\n%!error <duplicate subfunction or nested function name>\n%! duplicate_nested_parent_function ()\n\n%!error <duplicate subfunction or nested function name>\n%! duplicate_parent_nested2 ()\n\n%!error <duplicate subfunction or nested function name>\n%! duplicate_parent_nested_function ()\n\n%!error <duplicate subfunction or nested function name>\n%! duplicate_primary_nested_function ()\n\n%!error <duplicate subfunction or nested function name>\n%! duplicate_primary_subfunction_old_syntax ()\n\n%!error <duplicate subfunction or nested function name>\n%! duplicate_primary_subfunction ()\n\n%!error <duplicate subfunction or nested function name>\n%! duplicate_subfunction ()\n\n%!error <duplicate subfunction or nested function name>\n%! duplicate_subfunction_old_syntax ()\n\n%!assert <*50014> (duplicate_subfunction_separate_scope_ok (), 3)\n"
  },
  {
    "path": "test/bug-50014/duplicate_nested_function.m",
    "content": "## Test duplicate nested function names\nfunction duplicate_nested_function ()\n\n  function r = nested_fcn_1 ()\n    r = 1;\n  endfunction\n\n  function r = nested_fcn_1 ()\n    r = 2;\n  endfunction\n\nendfunction\n"
  },
  {
    "path": "test/bug-50014/duplicate_nested_in_subfunction_ok.m",
    "content": "## Test that duplicate names in separate subfunctions are OK.\n\nfunction retval = duplicate_nested_in_subfunction_ok ()\n  retval = sub1 () + sub2 ();\nendfunction\n\nfunction r = sub1 ()\n  function notbug ()\n    r = 1;\n  endfunction\n  notbug ();\nendfunction\n\nfunction r = sub2 ()\n  function notbug ()\n    r = 2;\n  endfunction\n  notbug ();\nendfunction\n"
  },
  {
    "path": "test/bug-50014/duplicate_nested_parent_function.m",
    "content": "## Test nested function that duplicates nested function name\nfunction duplicate_nested_parent_function ()\n  function bug ()\n    function bug ()\n    endfunction\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/bug-50014/duplicate_parent_nested2.m",
    "content": "## Test that we detect the correct error.\nfunction duplicate_parent_nested2 ()\n  function notbug ()\n    function bug ()\n    endfunction\n  endfunction\n  function bug ()  # no error here\n    function bug ()  # error here (duplicates parent name)\n    endfunction\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/bug-50014/duplicate_parent_nested_function.m",
    "content": "## Test nested function that duplicates nested function name\nfunction duplicate_parent_nested_function ()\n  function bug ()\n    function bug ()\n    endfunction\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/bug-50014/duplicate_primary_nested_function.m",
    "content": "## Test duplicate primary/nested function names\nfunction duplicate_primary_nested_function ()\n\n  function r = duplicate_primary_nested_function ()\n    r = 1;\n  endfunction\n\nendfunction\n"
  },
  {
    "path": "test/bug-50014/duplicate_primary_subfunction.m",
    "content": "## Test duplicate primary/subfunction name\nfunction r = duplicate_primary_subfunction ()\n  r = 1;\nendfunction\n\nfunction r = duplicate_primary_subfunction ()\n  r = 2;\nendfunction\n"
  },
  {
    "path": "test/bug-50014/duplicate_primary_subfunction_old_syntax.m",
    "content": "## Test old-style subfunctions with no END statements\n\nfunction r = duplicate_primary_subfunction_old_syntax ()\n  r = 0;\n  notbug ();\n\nfunction r = notbug ()\n  r = 1\n\nfunction r = duplicate_primary_subfunction_old_syntax ()\n  r = 2\n"
  },
  {
    "path": "test/bug-50014/duplicate_subfunction.m",
    "content": "## Test duplicate subfunctions\nfunction x = duplicate_subfunction ()\n  x = 1;\nendfunction\n\nfunction y = duplicate_subfcn_1 ()\n  y = 2;\nendfunction\n\nfunction z = duplicate_subfcn_1 ()\n  z = 3;\nendfunction\n"
  },
  {
    "path": "test/bug-50014/duplicate_subfunction_old_syntax.m",
    "content": "## Test old-style subfunctions with no END statements.\n\nfunction r = duplicate_subfunction_old_syntax ()\n  r = 0;\n  bug ();\n\nfunction r = bug ()\n  r = 1\n\nfunction r = bug ()\n  r = 2\n"
  },
  {
    "path": "test/bug-50014/duplicate_subfunction_separate_scope_ok.m",
    "content": "## Test that nested functions with the same name are OK if they are\n## defined inside other nested functions with different names.\n\nfunction retval = duplicate_subfunction_separate_scope_ok ()\n  function r = suba ()\n    function sub2 ()\n      r = 1;\n    endfunction\n    sub2 ();\n  endfunction\n  function subb ()\n    function sub2 ()\n      y = 2;\n    endfunction\n    sub2 ();\n  endfunction\n  subb ();\n  retval = y + suba ();\nendfunction\n"
  },
  {
    "path": "test/bug-50014/module.mk",
    "content": "bug_50014_TEST_FILES = \\\n  %reldir%/bug-50014.tst \\\n  %reldir%/duplicate_nested_function.m \\\n  %reldir%/duplicate_nested_in_subfunction_ok.m \\\n  %reldir%/duplicate_nested_parent_function.m \\\n  %reldir%/duplicate_parent_nested2.m \\\n  %reldir%/duplicate_parent_nested_function.m \\\n  %reldir%/duplicate_primary_nested_function.m \\\n  %reldir%/duplicate_primary_subfunction.m \\\n  %reldir%/duplicate_primary_subfunction_old_syntax.m \\\n  %reldir%/duplicate_subfunction.m \\\n  %reldir%/duplicate_subfunction_old_syntax.m \\\n  %reldir%/duplicate_subfunction_separate_scope_ok.m\n\nTEST_FILES += $(bug_50014_TEST_FILES)\n"
  },
  {
    "path": "test/bug-50035/@bug50035/bug50035.m",
    "content": "function s = bug50035 ()\n  s = class (struct (), \"bug50035\");\nendfunction\n"
  },
  {
    "path": "test/bug-50035/@bug50035/display.m",
    "content": "function display (x)\n  global in_name;\n  in_name = inputname (1);\nendfunction\n"
  },
  {
    "path": "test/bug-50035/bug-50035.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*50035>\n%! global in_name;\n%! in_name = \"\";\n%! x = bug50035 ()\n%! assert (in_name, \"x\");\n%! y = bug50035 ()\n%! assert (in_name, \"y\");\n%! bug50035 ()\n%! assert (in_name, \"ans\");\n%! x\n%! assert (in_name, \"x\");\n%! bug50035 ()\n%! assert (in_name, \"ans\");\n%! clear -global in_name;  # cleanup after test\n"
  },
  {
    "path": "test/bug-50035/module.mk",
    "content": "bug_50035_TEST_FILES = \\\n  %reldir%/@bug50035/bug50035.m \\\n  %reldir%/@bug50035/display.m \\\n  %reldir%/bug-50035.tst\n\nTEST_FILES += $(bug_50035_TEST_FILES)\n"
  },
  {
    "path": "test/bug-50395/bug-50395.tst",
    "content": "%!test <50395>\n%! a = bug50395_a ();\n%! clear all\n%! c = 3;\n%! a = bug50395_a ();\n"
  },
  {
    "path": "test/bug-50395/bug50395_a.m",
    "content": "classdef bug50395_a < bug50395_c\n  methods\n     function obj = bug50395_a ()\n     end\n  end\nend\n"
  },
  {
    "path": "test/bug-50395/bug50395_c.m",
    "content": "classdef bug50395_c\nend\n"
  },
  {
    "path": "test/bug-50395/module.mk",
    "content": "bug_50395_TEST_FILES = \\\n  %reldir%/bug-50395.tst \\\n  %reldir%/bug50395_a.m \\\n  %reldir%/bug50395_c.m\n\nTEST_FILES += $(bug_50395_TEST_FILES)\n"
  },
  {
    "path": "test/bug-50716/bug-50716.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*50716>\n%! obj = myclass ();\n%! str = \"Octave\";\n%! val = obj.methodA (str(1:end));\n%! assert (val, str);\n\n%!test <*50716>\n%! obj = myclass ();\n%! foo = {obj};\n%! str = \"Octave\";\n%! val = foo{1}.methodA (str(1:end));\n%! assert (val, str);\n\n%!test <*50716>\n%! obj = myclass ();\n%! foo = {obj};\n%! str = \"Octave\";\n%! val = foo{end}.methodA (str(1:end));\n%! assert (val, str);\n"
  },
  {
    "path": "test/bug-50716/module.mk",
    "content": "bug_50716_TEST_FILES = \\\n  %reldir%/bug-50716.tst \\\n  %reldir%/myclass.m\n\nTEST_FILES += $(bug_50716_TEST_FILES)\n"
  },
  {
    "path": "test/bug-50716/myclass.m",
    "content": "classdef myclass < handle\n\n  methods\n    function obj = myclass\n    endfunction\n\n    function r = methodA (obj, val)\n      r = val;\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/bug-50831/bug-50831.tst",
    "content": "%!test <*50831>\n%! filename = tempname ();\n%! s.(\"a-b\") = \"bad fieldname\";\n%! unwind_protect\n%!   save (\"-text\", filename, \"s\");\n%!   filevar = load (filename);\n%!   assert (filevar.s, s);\n%! unwind_protect_cleanup\n%!   delete ([filename, '*']);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-50831/module.mk",
    "content": "bug_50831_TEST_FILES = \\\n  %reldir%/bug-50831.tst\n\nTEST_FILES += $(bug_50831_TEST_FILES)\n"
  },
  {
    "path": "test/bug-51192/bug-51192.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*51192>\n%! a = class_bug51192 ();\n%! a.foo (\"asd\")\n%! class_bug51192.foo (\"asd\");\n"
  },
  {
    "path": "test/bug-51192/class_bug51192.m",
    "content": "classdef class_bug51192\n  methods (Static)\n    function foo (val)\n      val;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-51192/module.mk",
    "content": "bug_51192_TEST_FILES = \\\n  %reldir%/bug-51192.tst \\\n  %reldir%/class_bug51192.m\n\nTEST_FILES += $(bug_51192_TEST_FILES)\n"
  },
  {
    "path": "test/bug-51532/+package_bug51532/foo.m",
    "content": "function retval = foo (val)\n  retval = val;\nendfunction\n"
  },
  {
    "path": "test/bug-51532/bug-51532.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Test for value returned from a +package function\n%!test <*51532>\n%! r = package_bug51532.foo (\"asdf\");\n%! assert (ischar (r));\n%! assert (r, \"asdf\");\n"
  },
  {
    "path": "test/bug-51532/module.mk",
    "content": "bug_51532_TEST_FILES = \\\n  %reldir%/+package_bug51532/foo.m \\\n  %reldir%/bug-51532.tst\n\nTEST_FILES += $(bug_51532_TEST_FILES)\n"
  },
  {
    "path": "test/bug-51534/bug-51534.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*51534>\n%! a = child_bug51534 (\"asd\");\n%! assert (a.prop, \"asd\");\n"
  },
  {
    "path": "test/bug-51534/child_bug51534.m",
    "content": "classdef child_bug51534 < parent_bug51534\n  methods\n    function self = child_bug51534 (val)\n      self@parent_bug51534 (val);\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-51534/module.mk",
    "content": "bug_51534_TEST_FILES = \\\n  %reldir%/bug-51534.tst \\\n  %reldir%/child_bug51534.m \\\n  %reldir%/parent_bug51534.m\n\nTEST_FILES += $(bug_51534_TEST_FILES)\n"
  },
  {
    "path": "test/bug-51534/parent_bug51534.m",
    "content": "classdef parent_bug51534 < handle\n  properties\n    prop\n  endproperties\n  methods\n    function self = parent_bug51534 (val)\n      self.prop = val;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-51599/bug-51599.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Check if a function handle to a local function of a classdef class\n## can be called from an instance of that class.\n%!test <*51599>\n%! a = class_bug51599 ();\n%! a.foo ();\n%! assert (a.bar (0), 2);\n"
  },
  {
    "path": "test/bug-51599/class_bug51599.m",
    "content": "classdef class_bug51599 < handle\n  properties\n    anon_fcn\n  endproperties\n  methods\n    function foo (obj)\n      obj.anon_fcn = @(x) my_helper (x + 1);\n    endfunction\n    function ret = bar (obj, val)\n      ret = obj.anon_fcn (val);\n    endfunction\n  endmethods\nendclassdef\n\nfunction ret = my_helper (val)\n  ret = val + 1;\nendfunction\n"
  },
  {
    "path": "test/bug-51599/module.mk",
    "content": "bug_51599_TEST_FILES = \\\n  %reldir%/bug-51599.tst \\\n  %reldir%/class_bug51599.m\n\nTEST_FILES += $(bug_51599_TEST_FILES)\n"
  },
  {
    "path": "test/bug-52075/bug-52075.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2015-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*52075>\n%! a = class_bug52075 ();\n%! assert (a.duplicate, 'method');\n%! assert (a.call_local_dup, 'local_foo');\n"
  },
  {
    "path": "test/bug-52075/class_bug52075.m",
    "content": "classdef class_bug52075\n  methods\n    function ret = duplicate (self)\n      ret = 'method';\n    end\n    function ret = call_local_dup (self)\n      ret = duplicate ();\n    end\n  end\nend\n\nfunction ret = duplicate\n  ret = 'local_foo';\nend\n"
  },
  {
    "path": "test/bug-52075/module.mk",
    "content": "bug_52075_TEST_FILES = \\\n  %reldir%/bug-52075.tst \\\n  %reldir%/class_bug52075.m\n\nTEST_FILES += $(bug_52075_TEST_FILES)\n"
  },
  {
    "path": "test/bug-52722/bug-52722.tst",
    "content": "%!test <*52722>\n%! include_globals\n%! clear -global a b c;  # cleanup after test\n"
  },
  {
    "path": "test/bug-52722/define_globals.m",
    "content": "global a b c\n"
  },
  {
    "path": "test/bug-52722/include_globals.m",
    "content": "## Include script globals.m which defines global variables\ndefine_globals\n\n## Test for presence of a global variable defined above\nif (! isglobal (\"c\"))\n  error (\"global variable 'c' not defined\");\nendif\n"
  },
  {
    "path": "test/bug-52722/module.mk",
    "content": "bug_52722_TEST_FILES = \\\n  %reldir%/bug-52722.tst \\\n  %reldir%/define_globals.m  \\\n  %reldir%/include_globals.m\n\nTEST_FILES += $(bug_52722_TEST_FILES)\n"
  },
  {
    "path": "test/bug-52851/bug-52851.tst",
    "content": "%!test <*52851>\n%! script1\n%! assert (r11, 1);\n%! assert (r21, 2);\n%! assert (r22, 2);\n\n%!test <*52851>\n%! script2\n%! assert (r1, 1);\n%! assert (r2, 2);\n\n%!test <*52851>\n%! flag = true;\n%! script3\n%! assert (r, 1);\n%! flag = false;\n%! script3\n%! assert (r, 2);\n\n%!test <*52851>\n%! script4\n%! assert (r1, 1);\n%! assert (r2, 2);\n"
  },
  {
    "path": "test/bug-52851/module.mk",
    "content": "bug_52851_TEST_FILES = \\\n  %reldir%/bug-52851.tst \\\n  %reldir%/script1.m \\\n  %reldir%/script2.m \\\n  %reldir%/script3.m \\\n  %reldir%/script4.m\n\nTEST_FILES += $(bug_52851_TEST_FILES)\n"
  },
  {
    "path": "test/bug-52851/script1.m",
    "content": "1; %script identifier\n\nfunction r = caller (fun, num)\n  persistent funarray\n  if (isempty (fun))\n    r = funarray(num).fun ();\n  else\n    if (isempty (funarray))\n      funarray(1).fun = fun;\n    else\n      funarray(num).fun = fun;\n    endif\n  endif\nendfunction\n\nfunction r = computation ()\n  r = 1;\nendfunction\n\ncaller (@computation, 1);\n\nr11 = caller ([], 1);\n\nfunction r = computation ()\n  r = 2;\nendfunction\n\ncaller (@computation, 2);\n\nr21 = caller ([], 1);\nr22 = caller ([], 2);\n"
  },
  {
    "path": "test/bug-52851/script2.m",
    "content": "1; %script identifier\n\nfunction r = caller (fun)\n  r = fun ();\nendfunction\n\nfunction r = computation ()\n  r = 1;\nendfunction\n\nr1 = caller (@computation);\n\nfunction r = computation ()\n  r = 2;\nendfunction\n\nr2 = caller (@computation);\n"
  },
  {
    "path": "test/bug-52851/script3.m",
    "content": "1; %script identifier\n\nif (flag)\n  function r = computation ()\n    r = 1;\n  endfunction\n\n  r = computation ();\nelse\n  function r = computation ()\n    r = 2;\n  endfunction\n\n  r = computation ();\nendif\n"
  },
  {
    "path": "test/bug-52851/script4.m",
    "content": "1; %script identifier\n\nfunction r = computation ()\n  r = 1;\nendfunction\n\nr1 = computation ();\n\nfunction r = computation ()\n  r = 2;\nendfunction\n\nr2 = computation ();\n"
  },
  {
    "path": "test/bug-53027/bug-53027.tst",
    "content": "%!function load53027 (fname)\n%!  global X;\n%!  X = 2;\n%!  load (fname);\n%!  assert (X, 1);\n%!endfunction\n\n%!function save53027 (fname)\n%!  global X;\n%!  X = 1;\n%!  save (fname, \"X\");\n%!endfunction\n\n%!test <*53027>\n%! global X;\n%! X = 0;\n%! fname = tempname ();\n%! unwind_protect\n%!   save53027 (fname);\n%!   assert (X, 1);\n%!   load53027 (fname);\n%!   assert (X, 1);\n%!   load53027 (fname);\n%!   assert (X, 1);\n%!   clear X\n%!   assert (exist (\"X\"), 0);\n%! unwind_protect_cleanup\n%!   clear -global X\n%!   delete ([fname, '*']);  # remove temp file\n%! end_unwind_protect\n\n%!test <*53027>\n%! [a, b] = ntest53027a ();\n%! unwind_protect\n%!   assert ([a, b], [0, 0]);\n%! unwind_protect_cleanup\n%!   clear -global x\n%! end_unwind_protect\n\n%!test <*53027>\n%! [a, b] = ntest53027b ();\n%! unwind_protect\n%!   assert ([a, b], [0, 0]);\n%! unwind_protect_cleanup\n%!   clear -global x\n%! end_unwind_protect\n\n%!test <*53027>\n%! [a, b] = ntest53027c ();\n%! unwind_protect\n%!   assert ([a, b], [0, 0]);\n%! unwind_protect_cleanup\n%!   clear -global x\n%! end_unwind_protect\n\n## Previous bugs have caused segfaults when executing script twice.\n%!test <*53027>\n%! unwind_protect\n%!   gtest53027\n%!   assert (isempty (a) && isempty (c));\n%!   assert (isglobal (\"a\") && isglobal (\"c\"));\n%!   assert (! exist (\"b\"));\n%!   assert (isempty (xx) && ! isglobal (\"xx\"));\n%!   gtest53027\n%!   assert (isempty (a) && isempty (c));\n%!   assert (isglobal (\"a\") && isglobal (\"c\"));\n%!   assert (! exist (\"b\"));\n%!   assert (isempty (xx) && ! isglobal (\"xx\"));\n%! unwind_protect_cleanup\n%!   clear -global a b c\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-53027/globals53027.m",
    "content": "global a b c\n"
  },
  {
    "path": "test/bug-53027/gtest53027.m",
    "content": "globals53027\n\nxx = a;\nclear b\n"
  },
  {
    "path": "test/bug-53027/module.mk",
    "content": "bug_53027_TEST_FILES = \\\n  %reldir%/bug-53027.tst \\\n  %reldir%/globals53027.m \\\n  %reldir%/gtest53027.m \\\n  %reldir%/ntest53027a.m \\\n  %reldir%/ntest53027b.m \\\n  %reldir%/ntest53027c.m\n\nTEST_FILES += $(bug_53027_TEST_FILES)\n"
  },
  {
    "path": "test/bug-53027/ntest53027a.m",
    "content": "function [m_exist, n_exist] = ntest53027a ()\n  global x\n  x = 3;\n  n_exist = nest ();\n  m_exist = exist (\"x\", 'var');\n  function n_exist = nest ()\n    x = 1;\n    clear x\n    n_exist = exist (\"x\", \"var\");\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/bug-53027/ntest53027b.m",
    "content": "function [m_exist, n_exist] = ntest53027b ()\n  global x\n  x = 3;\n  n_exist = nest ();\n  m_exist = exist (\"x\", 'var');\n  function n_exist = nest ()\n    ## The clear statement should operate on the variable in the\n    ## parent scope even though there is no explicit varabiable\n    ## reference in the code (the clear function just sees a string\n    ## containing the name of the variable and the parser (correctly)\n    ## does not treat this as a special case.\n    clear x\n    n_exist = exist (\"x\", \"var\");\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/bug-53027/ntest53027c.m",
    "content": "function [m_exist, n_exist] = ntest53027c ()\n  ## In this test, x is not global.\n  x = 3;\n  n_exist = nest ();\n  m_exist = exist (\"x\", 'var');\n  function n_exist = nest ()\n    ## The clear statement should operate on the variable in the\n    ## parent scope even though there is no explicit varabiable\n    ## reference in the code (the clear function just sees a string\n    ## containing the name of the variable and the parser (correctly)\n    ## does not treat this as a special case.\n    clear x\n    n_exist = exist (\"x\", \"var\");\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/bug-53468/bug-53468.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Load an Octave 4.0.3 figure file\n%!test <*53468>\n%! unwind_protect\n%!   hf = hgload (\"ofig403.ofig\");\n%! unwind_protect_cleanup\n%!   if (exist (\"hf\", \"var\") && isfigure (hf))\n%!     close (hf)\n%!   endif\n%! end_unwind_protect\n\n## Load an Octave 4.2.1 figure file\n%!test <*53468>\n%! unwind_protect\n%!   hf = hgload (\"ofig421.ofig\");\n%! unwind_protect_cleanup\n%!   if (exist (\"hf\", \"var\") && isfigure (hf))\n%!     close (hf)\n%!   endif\n%! end_unwind_protect\n\n## Load an Octave 5.1 figure file\n%!test <*53468>\n%! unwind_protect\n%!   hf = hgload (\"ofig51.ofig\");\n%! unwind_protect_cleanup\n%!   if (exist (\"hf\", \"var\") && isfigure (hf))\n%!     close (hf)\n%!   endif\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-53468/module.mk",
    "content": "bug_53468_TEST_FILES = \\\n  %reldir%/bug-53468.tst \\\n  %reldir%/ofig403.ofig \\\n  %reldir%/ofig421.ofig \\\n  %reldir%/ofig51.ofig\n\nTEST_FILES += $(bug_53468_TEST_FILES)\n"
  },
  {
    "path": "test/bug-53579.tst",
    "content": "%!function [raa, rbb, igaa, igbb] = sub1 (aa, bb)\n%!  global aa bb;\n%!  aa = 1;\n%!  raa = aa;\n%!  rbb = bb;\n%!  igaa = isglobal (\"aa\");\n%!  igbb = isglobal (\"bb\");\n%!endfunction\n\n%!test <*53579>\n%! global aa bb;\n%! assert (isglobal (\"aa\"));\n%! assert (isglobal (\"bb\"));\n%! aa = 3;\n%! xx = 5;\n%! warning ('off', 'Octave:global-local-conflict', 'local');\n%! [raa, rbb, igaa, igbb] = sub1 (aa, xx);\n%! assert (raa, 1);\n%! assert (rbb, []);\n%! assert (igaa);\n%! assert (igbb);\n%! assert (xx, 5);\n%! clear -global aa bb;  # cleanup after test\n"
  },
  {
    "path": "test/bug-53599.tst",
    "content": "%!function rval = sggval (val)\n%!  global gval;\n%!  if (nargin == 1)\n%!    gval = val;\n%!  else\n%!    rval = gval;\n%!  endif\n%!endfunction\n\n%!test <*53599>\n%! global gval;\n%! assert (isempty (gval));\n%! sggval (13);\n%! assert (sggval (), 13);\n%! assert (gval, 13);\n%! clear global gval\n%! assert (sggval (), []);\n%! gval = 42;\n%! assert (sggval (), []);\n%! clear gval\n%! global gval;\n%! gval = 42;\n%! assert (sggval (), 42);\n%! clear -global gval;  # cleanup after test\n"
  },
  {
    "path": "test/bug-53956/bug-53956.tst",
    "content": "%!test <*53956>\n%! global dtor2_called dtor4_called;\n%!\n%! dtor2_called = dtor4_called = 0;\n%! x = bug53956_class_3 ();\n%! clear x\n%! assert (dtor2_called, 1);\n%!\n%! dtor2_called = dtor4_called = 0;\n%! x = bug53956_class_4 ();\n%! clear x\n%! assert (dtor2_called, 1);\n%! assert (dtor4_called, 1);\n%!\n%! clear -global dtor2_called dtor4_called;  # cleanup after test\n"
  },
  {
    "path": "test/bug-53956/bug53956_class_2.m",
    "content": "classdef bug53956_class_2 < handle\n  properties\n  end\n  methods\n    function delete (self)\n      global dtor2_called\n      dtor2_called++;\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-53956/bug53956_class_3.m",
    "content": "classdef bug53956_class_3 < bug53956_class_2\n  properties\n  end\n  methods\n  end\nend\n"
  },
  {
    "path": "test/bug-53956/bug53956_class_4.m",
    "content": "classdef bug53956_class_4 < bug53956_class_3\n  properties\n  end\n  methods\n    function delete (self)\n      global dtor4_called\n      dtor4_called++;\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-53956/module.mk",
    "content": "bug_53956_TEST_FILES = \\\n  %reldir%/bug-53956.tst \\\n  %reldir%/bug53956_class_2.m \\\n  %reldir%/bug53956_class_3.m \\\n  %reldir%/bug53956_class_4.m\n\nTEST_FILES += $(bug_53956_TEST_FILES)\n"
  },
  {
    "path": "test/bug-54490.tst",
    "content": "%!function out = bug54490 ()\n%!  global k;\n%!  k = 1;\n%!  out = 3;\n%!endfunction\n\n%!test <*54490>\n%! global k;\n%! k = 2;\n%! a = [5, 6];\n%! a(k) = bug54490 ();\n%! assert (a, [5, 3]);\n%! k = 2;\n%! a = [5, 6];\n%! [a(k)] = bug54490 ();\n%! assert (a, [5, 3]);\n%! clear -global k;  # cleanup after test\n"
  },
  {
    "path": "test/bug-54995/@testclass54995/subsref.m",
    "content": "function val = subsref (obj, S)\n  val = builtin (\"subsref\", obj, S);\nendfunction\n"
  },
  {
    "path": "test/bug-54995/@testclass54995/testclass54995.m",
    "content": "function obj = testclass54995 ()\n  obj = struct (\"x\", eye (4));\n  obj = class (obj, \"testclass54995\");\nendfunction\n"
  },
  {
    "path": "test/bug-54995/bug-54995.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*54995>\n%! obj = testclass54995 ();\n%! assert (obj.x(1), 1);\n"
  },
  {
    "path": "test/bug-54995/module.mk",
    "content": "bug_54995_TEST_FILES = \\\n  %reldir%/@testclass54995/testclass54995.m \\\n  %reldir%/@testclass54995/subsref.m \\\n  %reldir%/bug-54995.tst\n\nTEST_FILES += $(bug_54995_TEST_FILES)\n"
  },
  {
    "path": "test/bug-55308.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*55308>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hg = hggroup ();\n%!   axis ([-2, 2, -2, 2]);\n%!   hl = line ([0;1], [0;0], \"color\", \"r\");\n%!   set (hl, \"parent\", hg);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-55321.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!function cb_children (hg, ~)\n%!  hl = get (hg, \"children\");\n%!  color = get (hl, \"color\");\n%!  set (hl, \"userdata\", isequal (color, [1 0 0]));\n%!endfunction\n\n%!test <*55321>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hg = hggroup ();\n%!   addlistener (hg, \"children\", @cb_children);\n%!   hl = line ([0, 1], [1, 1], \"color\", \"r\", \"parent\", hg);\n%!   assert (get (hl, \"userdata\"), true);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-55322.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*55322>\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   hax = axes (\"parent\", hf);\n%!   hg = hggroup ();\n%!   hl = line (hax, [0, 1], [1, 1], \"parent\", hax, \"parent\", hg);\n%!   assert (get (hax, \"children\"), hg);\n%!   assert (get (hg, \"children\"), hl);\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-55758/bug-55758.tst",
    "content": "%!test <*55758>\n%! global class_bug_55758_dtor_called;\n%! class_bug_55758_dtor_called = false;\n%!\n%! assert (class_bug_55758 (5).value, 5);\n%! assert (class_bug_55758_dtor_called);\n%!\n%! assert (class_bug_55758 (5)(1), 5);\n%! assert (class_bug_55758_dtor_called);\n%!\n%! assert (size (class_bug_55758 (5)), [1, 1]);\n%! assert (class_bug_55758_dtor_called);\n%!\n%! assert (numel (class_bug_55758 (5)), 1);\n%! assert (class_bug_55758_dtor_called);\n%! clear -global class_bug_55758_dtor_called;  # cleanup after test\n"
  },
  {
    "path": "test/bug-55758/class_bug_55758.m",
    "content": "classdef class_bug_55758 < handle\n  properties\n    value\n  endproperties\n\n  methods\n    function self = class_bug_55758 (val)\n      if (nargin < 1)\n        val = 0;\n      endif\n      self.value = val;\n    endfunction\n\n    function delete (self)\n      global class_bug_55758_dtor_called;\n      class_bug_55758_dtor_called = true;\n    endfunction\n\n    function ret = subsref (self, idx)\n      ret = self.value;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-55758/module.mk",
    "content": "bug_55758_TEST_FILES = \\\n  %reldir%/bug-55758.tst \\\n  %reldir%/class_bug_55758.m\n\nTEST_FILES += $(bug_55758_TEST_FILES)\n"
  },
  {
    "path": "test/bug-56068/bug-56068.tst",
    "content": "%!test <*56068>\n%! res = textscan (evalc (\"bug_56068\"), \"%s\", \"delimiter\", \"\\n\");\n%! f_cell = textscan (fileread (\"bug_56068.m\"), \"%s\", \"delimiter\", \"\\n\");\n%! f_echo = cellfun (@(x) sprintf ([PS4 \"%s\"], x), ...\n%!                   f_cell{1}([2,3,4,5,8,9,10,11]), ...\n%!                   \"uniformoutput\", false);\n%!\n%! assert (numel (res{1}), 15);\n%! assert (all (strcmp (res{1}([2,3,5,7,10,11,13,15]), f_echo)));\n"
  },
  {
    "path": "test/bug-56068/bug_56068.m",
    "content": "a = 1 + 1\necho on\nb = 2 + 1\nB = 2 + 1\necho\nc = 3 + 1\nC = 3 + 1\necho\nd = 4 + 1\nD = 4 + 1\necho\n"
  },
  {
    "path": "test/bug-56068/module.mk",
    "content": "bug_56068_TEST_FILES = \\\n  %reldir%/bug-56068.tst \\\n  %reldir%/bug_56068.m\n\nTEST_FILES += $(bug_56068_TEST_FILES)\n"
  },
  {
    "path": "test/bug-58572/bug-58572.tst",
    "content": "%!test <*58572>\n%! obj = bug58572 ();\n%! assert (use_num (obj), false);\n%! assert (obj.use_num (), false);\n%! assert (isnumeric (obj), true);\n%! assert (obj.isnumeric (), true);\n"
  },
  {
    "path": "test/bug-58572/bug58572.m",
    "content": "classdef bug58572\n  methods\n    function rslt = use_num (obj)\n      rslt = cellfun ('isnumeric', {'a_name'});\n    endfunction\n    function rslt = isnumeric (obj)\n      if (! isa (obj, 'bug58572'))\n        error ('bug58572.isnumeric called without object!');\n      endif\n      rslt = true;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-58572/module.mk",
    "content": "bug_58572_TEST_FILES = \\\n  %reldir%/bug-58572.tst \\\n  %reldir%/bug58572.m\n\nTEST_FILES += $(bug_58572_TEST_FILES)\n"
  },
  {
    "path": "test/bug-58593/bug-58593.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*58593>\n%! obj = myclass1 ();\n%! assert (obj.data (plus (minus (end,1), 1)), 1005);\n\n%!test <*58593>\n%! obj = myclass2 ();\n%! assert (obj.alldata, 1001:1005);\n\n%!test <*58593>\n%! obj = myclass2 ();\n%! assert (obj(end), 1004);\n\n%!test <*58593>\n%! obj = myclass2 ();\n%! assert (obj.data(end), 1005);\n\n%!test <*58593>\n%! obj = myclass2 ();\n%! obj.alldata = 1:5;\n%! assert (obj.data, 1:5);\n\n%!test <*58593>\n%! obj = myclass2 ();\n%! obj(end) = -1;\n%! assert (obj.data, [1001:1003, -1, 1005]);\n\n%!test <*58593>\n%! obj = myclass2 ();\n%! obj.data(end) = -1;\n%! assert (obj.data, [1001:1004, -1]);\n"
  },
  {
    "path": "test/bug-58593/module.mk",
    "content": "bug_58593_TEST_FILES = \\\n  %reldir%/bug-58593.tst \\\n  %reldir%/myclass1.m \\\n  %reldir%/myclass2.m\n\nTEST_FILES += $(bug_58593_TEST_FILES)\n"
  },
  {
    "path": "test/bug-58593/myclass1.m",
    "content": "classdef myclass1 < handle\n  properties\n    data\n  end\n  methods\n    function obj = myclass1 ()\n      obj.data = 1001:1005;\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-58593/myclass2.m",
    "content": "classdef myclass2 < handle\n  properties\n    data_\n  end\n\n  methods\n    function obj = myclass2 ()\n      obj.data_ = 1001:1005;\n    end\n\n    function r = subsref (obj, S)\n      switch (S(1).type)\n      case '.'\n        switch (S(1).subs)\n        case 'data'\n          %% Transform: obj.data --> obj.data_\n          r = obj.data_;\n          if (length (S) > 1)\n            r = subsref (r, S(2:end));\n          end\n        case 'alldata'\n          %% Transform: obj.data --> obj.data_(1:end)\n          %% This statement should trigger *builtin* subsref *twice* (one\n          %% for the evaluation of 'end', and the other for the whole rvalue).\n          %% 'end' here is also builtin 'end'\n          r = obj.data_(1:end);\n\n          if (length (S) > 1)\n            r = subsref (r, S(2:end));\n          end\n        otherwise\n          error ('Incorrect usage');\n        end\n      case '()'\n        %% Transform: obj(index) --> obj.data_(index)\n        r = subsref (obj.data_, S);\n      otherwise\n        error ('Incorrect usage');\n      end\n    end\n\n    function obj = subsasgn (obj, S, B)\n      switch (S(1).type)\n      case '.'\n        switch (S(1).subs)\n        case 'data'\n          %% Transform: obj.data --> obj.data_\n          if (length (S)>1)\n            B = subsasgn (obj.data_, S(2:end), B);\n          end\n          obj.data_ = B;\n        case 'alldata'\n          %% Transform: obj.data --> obj.data_(1:end)\n          if (length (S)>1)\n            B = subsasgn (obj.data_(1:end), S(2:end), B);\n          end\n          %% This statement should trigger *builtin* subsref to evaluate 'end',\n          %% then *builtin* subsasgn for the whole assignment expression\n          %% 'end' here is also builtin 'end'\n          obj.data_(1:end) = B;\n        otherwise\n          error ('Incorrect usage');\n        end\n      case '()'\n        %% Transform: obj(index) --> obj.data_(index)\n        obj.data_ = subsasgn (obj.data_, S, B);\n      otherwise\n        error ('Incorrect usage');\n      end\n    end\n\n    function r = end (obj, k, n)\n      %% We subtract 1 from the \"real\" end of obj.data_\n      r = builtin ('end', obj.data_, k, n) - 1;\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-59451/bug-59451.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Test if function handles correctly dispatch to class methods while keeping\n## a link to the original function file.\n%!test <*59451>\n%! dpi = pi;\n%! spi = single (pi);\n%! ## Create function handle\n%! fh = @bug59451;\n%! ## All of these must dispatch to the corresponding function file.\n%! assert (fh (dpi, dpi), \"none\");\n%! assert (fh (dpi, spi), \"none\");\n%! assert (fh (spi, spi), \"none\");\n%! assert (fh (spi, dpi), \"none\");\n%! assert (fh ({}, {}), \"none\");\n%! ## cd to a directory that contains class overloads\n%! cd foo\n%! ## The overloads must take precedence.\n%! assert (fh (dpi, dpi), \"double\");\n%! assert (fh (dpi, spi), \"single\");\n%! assert (fh (spi, spi), \"single\");\n%! assert (fh (spi, dpi), \"single\");\n%! ## This must still dispatch to the original function file.\n%! assert (fh ({}, {}), \"none\");\n"
  },
  {
    "path": "test/bug-59451/bug59451.m",
    "content": "function s = bug59451 (x, y)\n  s = \"none\";\nendfunction\n"
  },
  {
    "path": "test/bug-59451/foo/@double/bug59451.m",
    "content": "function s = bug59451 (x, y)\n  s = \"double\";\nendfunction\n"
  },
  {
    "path": "test/bug-59451/foo/@single/bug59451.m",
    "content": "function s = bug59451 (x, y)\n  s = \"single\";\nendfunction\n"
  },
  {
    "path": "test/bug-59451/module.mk",
    "content": "bug_59451_TEST_FILES = \\\n  %reldir%/bug-59451.tst \\\n  %reldir%/bug59451.m \\\n  %reldir%/foo/@double/bug59451.m \\\n  %reldir%/foo/@single/bug59451.m\n\nTEST_FILES += $(bug_59451_TEST_FILES)\n"
  },
  {
    "path": "test/bug-59617/@bug59617/bug59617.m",
    "content": "function obj = bug59617 ()\n\n  obj = class (struct (), \"bug59617\");\n\nendfunction\n"
  },
  {
    "path": "test/bug-59617/@bug59617/max.m",
    "content": "function r = max (a, b)\n  if (nargin != 2)\n    error (\"@bug59617/max: invalid number of arguments\");\n  endif\n  if (! isa (a, \"bug59617\") && ! isa (b, \"bug59617\"))\n    error (\"@bug59617/max: expecting one argument to be a bug59617 object\");\n  endif\n  r = \"@bug59617/max\";\nendfunction\n"
  },
  {
    "path": "test/bug-59617/bug-59617.tst",
    "content": "%!test <*59617>\n%! obj = bug59617 ();\n%! assert (max (@() 1, obj), \"@bug59617/max\");\n%! assert (max (obj, @() 2), \"@bug59617/max\");\n%! assert (max (obj, obj), \"@bug59617/max\");\n"
  },
  {
    "path": "test/bug-59617/module.mk",
    "content": "bug_59617_TEST_FILES = \\\n  %reldir%/@bug59617/bug59617.m \\\n  %reldir%/@bug59617/max.m \\\n  %reldir%/bug-59617.tst\n\nTEST_FILES += $(bug_59617_TEST_FILES)\n"
  },
  {
    "path": "test/bug-59661/bug-59661.tst",
    "content": "%!test <*59661>\n%! a = bug59661 (1);\n%! b = bug59661 (1, 2);\n%! assert (a == b, [true, false]);\n"
  },
  {
    "path": "test/bug-59661/bug59661.m",
    "content": "classdef bug59661 < handle\n\n  properties\n    p = [];\n  endproperties\n\n  methods\n\n    function o = bug59661 (varargin)\n      o.p = [varargin{:}];\n    endfunction\n\n    function res = eq (a, b)\n\n      if (numel (a.p) > 1 && numel (b.p) > 1 && ! isequal (size (a.p), size (b.p)))\n        res = false;\n        return;\n      endif\n\n      if (isequal (size (a.p), size (b.p)))\n        res = eq (a.p, b.p);\n      else\n        res = bsxfun (@eq, a.p, b.p);\n      endif\n\n    endfunction\n\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-59661/module.mk",
    "content": "bug_59661_TEST_FILES = \\\n  %reldir%/bug59661.m \\\n  %reldir%/bug-59661.tst\n\nTEST_FILES += $(bug_59661_TEST_FILES)\n"
  },
  {
    "path": "test/bug-59704/bug-59704.tst",
    "content": "%!test <*59704>\n%! o = bug59704_1 ();\n%! o.test ();\n%! assert (o.p, []);\n\n%!test <*59704>\n%! o = bug59704_2 ();\n%! [~, o(1)] = size (rand (2, 5));\n%! assert (o(1), 5);\n"
  },
  {
    "path": "test/bug-59704/bug59704_1.m",
    "content": "classdef bug59704_1 < handle\n\n  properties\n    p\n  endproperties\n\n  methods\n\n    function n = numel (this, varargin)\n      n = 1;\n    endfunction\n\n    function test (this)\n      [~, this.p] = bug59704_1_test (this.p);\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/bug-59704/bug59704_1_test.m",
    "content": "function [retval, input] = bug59704_1_test (input)\nretval = 1;\nendfunction\n"
  },
  {
    "path": "test/bug-59704/bug59704_2.m",
    "content": "classdef bug59704_2 < handle\n\n  properties\n    data_\n  endproperties\n\n  methods\n\n    function obj = bug59704_2 ()\n      obj.data_ = 1001:1005;\n    endfunction\n\n    function r = subsref (obj, S)\n      ## Transform: obj(index) --> obj.data_(index)\n      if strcmp (S(1).type, '()')\n        r = subsref (obj.data_, S);\n      else\n        r = builtin('subsref', obj, S);\n      endif\n    endfunction\n\n    function obj = subsasgn (obj, S, B)\n      ## Transform: obj(index) --> obj.data_(index)\n      if strcmp (S(1).type, '()')\n        obj.data_ = subsasgn (obj.data_, S, B);\n      else\n        obj = builtin ('subsasgn', obj, S, B);\n      endif\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/bug-59704/module.mk",
    "content": "bug_59704_TEST_FILES = \\\n  %reldir%/bug59704_1.m \\\n  %reldir%/bug59704_1_test.m \\\n  %reldir%/bug59704_2.m \\\n  %reldir%/bug-59704.tst\n\nTEST_FILES += $(bug_59704_TEST_FILES)\n"
  },
  {
    "path": "test/bug-59937/bug-59937.tst",
    "content": "%!test <*59973>\n%! eval_global_script\n%! assert (isglobal (new_var_name));\n%! assert (__varval__ (new_var_name), []);\n%! eval (sprintf (\"clear -global %s\", new_var_name));\n"
  },
  {
    "path": "test/bug-59937/eval_global_script.m",
    "content": "new_var_name = matlab.lang.makeUniqueStrings ('somevar', who ());\neval (sprintf (\"global %s\", new_var_name))\n"
  },
  {
    "path": "test/bug-59937/module.mk",
    "content": "bug_59937_TEST_FILES = \\\n  %reldir%/bug-59937.tst \\\n  %reldir%/eval_global_script.m\n\nTEST_FILES += $(bug_59937_TEST_FILES)\n"
  },
  {
    "path": "test/bug-59950.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## The following tests are for undocumented Matlab behavior.\n\n%!shared x\n%! x = 13;\n%!assert <*59950>  (exist (''), 0)\n%!assert <*59950>  (exist ([]), 0)\n%!assert <*59950>  (exist ({}), 0)\n%!assert <*59950>  (exist (1:0), 0)\n%!assert <*59950>  (exist ('', 'var'), 0)\n%!assert <*59950>  (exist ([], 'builtin'), 0)\n%!assert <*59950>  (exist ({}, 'dir'), 0)\n%!assert <*59950>  (exist (1:0, 'file'), 0)\n%!error exist (containers.Map ())\n%!error exist (containers.Map ())\n%!assert <*59950>  (exist ('x', ''), 0)\n%!assert <*59950>  (exist ('x', []), 0)\n%!assert <*59950>  (exist ('x', {}), 0)\n%!assert <*59950>  (exist ('x', struct ([])), 0)\n%!error exist ('x', containers.Map ())\n%!assert <*59950> (exist (containers.Map (), ''), 0)\n%!assert <*59950> (exist (containers.Map (), []), 0)\n%!assert <*59950> (exist (containers.Map (), {}), 0)\n%!assert <*59950> (exist (containers.Map (), struct ([])), 0)\n%!error exist (containers.Map (), containers.Map ())\n"
  },
  {
    "path": "test/bug-60237/bug-60237.tst",
    "content": "%!assert <*60237> (bug_60237 (), 5)\n"
  },
  {
    "path": "test/bug-60237/bug_60237.m",
    "content": "function r = bug_60237 ()\n  d = 2;\n  function c = bm (a)\n    c = a + d;\n  endfunction;\n  r = ancall (@(a) bm (a), 2);\nendfunction\n\nfunction r = ancall (f, a)\n  r = f (a) + 1;\nendfunction\n"
  },
  {
    "path": "test/bug-60237/module.mk",
    "content": "bug_60237_TEST_FILES = \\\n  %reldir%/bug-60237.tst \\\n  %reldir%/bug_60237.m\n\nTEST_FILES += $(bug_60237_TEST_FILES)\n"
  },
  {
    "path": "test/bug-60726/@class2_bug60726/class2_bug60726.m",
    "content": "function y = class2_bug60726 ()\n  y = class (struct (), 'class2_bug60726');\nend\n"
  },
  {
    "path": "test/bug-60726/@class2_bug60726/subsref.m",
    "content": "function varargout = subsref (obj, s)\n  varargout = num2cell (repelem (nargout, max (nargout, 1)));\nend\n"
  },
  {
    "path": "test/bug-60726/bug60726.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%%\n%% Testing nargout when calling subsref for classdef classes\n%%\n\n%!test <60726>\n%! x = class_bug60726;\n%! x{1};\n%! assert (ans, 1);\n\n%!test <60726>\n%! x = class_bug60726;\n%! x.a;\n%! assert (ans, 0);\n\n%!test <60726>\n%! x = class_bug60726;\n%! x(1).a;\n%! assert (ans, 1);\n\n%!test <60726>\n%! x = class_bug60726;\n%! x{1}.a;\n%! assert (ans, 1);\n\n%%\n%% Testing nargout when calling subsref for struct-based classes\n%%\n\n%!test <60726>\n%! x = class2_bug60726;\n%! x{1};\n%! assert (ans, 1);\n\n%!test <60726>\n%! x = class2_bug60726;\n%! x.a;\n%! assert (ans, 0);\n\n%!test <60726>\n%! x = class2_bug60726;\n%! x(1).a;\n%! assert (ans, 1);\n\n%!test <60726>\n%! x = class2_bug60726;\n%! x{1}.a;\n%! assert (ans, 1);\n\n"
  },
  {
    "path": "test/bug-60726/class_bug60726.m",
    "content": "classdef class_bug60726 < handle\n  methods\n    function varargout = subsref (obj, s)\n      varargout = num2cell (repelem (nargout, max (nargout, 1)));\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-60726/module.mk",
    "content": "bug_60726_TEST_FILES = \\\n  %reldir%/@class2_bug60726/class2_bug60726.m \\\n  %reldir%/@class2_bug60726/subsref.m \\\n  %reldir%/bug60726.tst \\\n  %reldir%/class_bug60726.m\n\nTEST_FILES += $(bug_60726_TEST_FILES)\n"
  },
  {
    "path": "test/bug-60882/bug-60882.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## bug #60882: error parsing command syntax\n\n%!assert <60882> (bug_60882 (), 42)\n"
  },
  {
    "path": "test/bug-60882/bug_60882.m",
    "content": "function retval = bug_60882 ()\n\n  job.foobar = {};\n\n  foobar off\n\n  retval = 42;\n\nendfunction\n\nfunction foobar (opt)\n  assert (opt, 'off');\nendfunction\n"
  },
  {
    "path": "test/bug-60882/module.mk",
    "content": "bug_60882_TEST_FILES = \\\n  %reldir%/bug-60882.tst \\\n  %reldir%/bug_60882.m\n\nTEST_FILES += $(bug_60882_TEST_FILES)\n"
  },
  {
    "path": "test/bug-61105/bug-61105.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!assert <*61105> (nested_test_1 (2), 24)\n\n%!assert <*61105> (nested_test_2 (), 24)\n\n%!test <*61105>\n%!  fh = nested_test_3 ();\n%!  assert (fh (2), 24);\n"
  },
  {
    "path": "test/bug-61105/module.mk",
    "content": "bug_61105_TEST_FILES = \\\n  %reldir%/bug-61105.tst \\\n  %reldir%/nested_test_1.m \\\n  %reldir%/nested_test_2.m \\\n  %reldir%/nested_test_3.m\n\nTEST_FILES += $(bug_61105_TEST_FILES)\n"
  },
  {
    "path": "test/bug-61105/nested_test_1.m",
    "content": "function r = nested_test_1 (val)\n  a = 3;\n  b = 5;\n  c = 7;\n  function r = f1 (f, x)\n    r = f(x) + a;\n  endfunction\n  function r = f2 (y)\n    function r2 = f3 (z)\n      r2 = z^2 + b*y;\n    endfunction\n    r = f1 (@f3, y) + c;\n  endfunction\n  r = f2 (val);\nendfunction\n"
  },
  {
    "path": "test/bug-61105/nested_test_2.m",
    "content": "function r = nested_test_2 ()\n  a = 3;\n  b = 5;\n  c = 7;\n  f1 = @(f, x) f(x) + a;\n  f2 = @(y) f1 (@(z) z^2 + b*y, y) + c;\n  r = f2 (2);\nendfunction\n"
  },
  {
    "path": "test/bug-61105/nested_test_3.m",
    "content": "function fh = nested_test_3 ()\n  a = 3;\n  b = 5;\n  c = 7;\n  f1 = @(f, x) f(x) + a;\n  fh = @(y) f1 (@(z) z^2 + b*y, y) + c;\nendfunction\n"
  },
  {
    "path": "test/bug-61191/bug-61191.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*61191>\n%! unwind_protect\n%!   addpath (\"subdir\");\n%!   omc_1 = rand (3, 1);\n%!   Tc_1 = rand (3, 1);\n%!   bug_61191\n%!   assert (omckk, omc_1);\n%!   assert (Tckk, Tc_1);\n%! unwind_protect_cleanup\n%!   rmpath (\"subdir\");\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-61191/module.mk",
    "content": "bug_61191_TEST_FILES = \\\n  %reldir%/bug-61191.tst \\\n  %reldir%/subdir/bug_61191.m\n\nTEST_FILES += $(bug_61191_TEST_FILES)\n"
  },
  {
    "path": "test/bug-61191/subdir/bug_61191.m",
    "content": "kk = 1;\neval (['omckk = omc_' num2str(kk) ';']);\neval (['Tckk = Tc_' num2str(kk) ';']);\neval (['omc_' num2str(kk) ' = omckk;']);\n"
  },
  {
    "path": "test/bug-61201.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!function lineno = test_conditional_lines (type)\n%!  lineno = -42;\n%!  warning (\"error\", \"Octave:possible-matlab-short-circuit-operator\", \"local\");\n%!  try\n%!    switch (type)\n%!      case \"while\"\n%!        k = 0;\n%!        while (k < 2 & true)  ## line 8\n%!          k++;\n%!        endwhile\n%!      case \"until\"\n%!        k = 0;\n%!        do\n%!          k++;\n%!        until (k > 2 & true);  ## line 15, but see below...\n%!      case \"if\"\n%!        k = 2;\n%!        if (k < 2 & true)  ## line 18\n%!        endif\n%!      case \"elseif\"\n%!        k = 2;\n%!        if (false)\n%!        elseif (k < 2 & true)  ## line 23\n%!        endif\n%!    endswitch\n%!  catch (ex)\n%!    lineno = ex.stack(1).line;\n%!  end_try_catch\n%!endfunction\n\n%!assert<*61201> (test_conditional_lines (\"while\"), 8)\n\n%!assert<*61201> (test_conditional_lines (\"if\"), 18)\n\n%!assert<*61201> (test_conditional_lines (\"elseif\"), 23)\n\n## Because the DO-UNTIL statement is not part of Matlab it is not\n## eligible for Matlab-style short-circuit behavior in Octave.\n%!assert<*61201> (test_conditional_lines (\"until\"), -42)\n"
  },
  {
    "path": "test/bug-63841/@cls2_b63841/cls2_b63841.m",
    "content": "function y = cls2_b63841 ()\n  y.a_property = 1;\n  y = class (y, 'cls2_b63841');\nend\n"
  },
  {
    "path": "test/bug-63841/@cls2_b63841/subsref.m",
    "content": "function varargout = subsref(obj, s)\n  varargout = {nargout, s(1).type, 'arg3'};\nend\n"
  },
  {
    "path": "test/bug-63841/bug-63841.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2023-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%%\n%% Testing nargout when calling subsref for classdef classes\n%%\n\n%!test <*63841>\n%! cm = containers.Map;\n%! cm('first') = cls_b63841;\n%! a_63841 = 0;\n%! try\n%!   if cm('first').a_property\n%!     a_63841 = 1;\n%!   endif\n%! catch\n%! end_try_catch\n%! assert (a_63841, 1);\n\n%!test <*63841>\n%! ti = cls_b63841;\n%! a = 0;\n%! if ti(1:5).a_property\n%!   a = 1;\n%! endif\n%! assert (a, 1);\n\n%!test <*63841>\n%! ti = cls_b63841;\n%! a = 0;\n%! for x = ti(1:5).a_property\n%!   a = 1;\n%! endfor\n%! assert (a, 1);\n\n%!test <*63841>\n%! ti = cls_b63841;\n%! [n_arg, b] = ti.call_a_method;\n%! assert (n_arg, 2);\n\n%!test <*63841>\n%! ti = cls_b63841;\n%! [n_arg, b] = ti{1};\n%! assert (n_arg, 2);\n\n%!test <*63841>\n%! ti = cls_b63841;\n%! [n_arg, b] = ti(1);\n%! assert (n_arg, 2);\n\n%!test <*63841>\n%! ti = cls_b63841;\n%! [n_arg, b] = ti(1).a_property;\n%! assert (n_arg, 2);\n\n%!test <*63841>\n%! ti = cls_b63841;\n%! [n_arg, b, c] = ti.call_a_method;\n%! assert (n_arg, 3);\n\n%!test <*63841>\n%! ti = cls_b63841;\n%! [n_arg, b, c] = ti{1};\n%! assert (n_arg, 3);\n\n%!test <*63841>\n%! ti = cls_b63841;\n%! [n_arg, b, c] = ti(1);\n%! assert (n_arg, 3);\n\n%%\n%% Testing nargout when calling subsref for struct-based classes\n%%\n\n%!test <*63841>\n%! ti = cls2_b63841;\n%! a = 0;\n%! if ti(1:5).a_property\n%!   a = 1;\n%! endif\n%! assert (a, 1);\n\n%!test <*63841>\n%! ti = cls2_b63841;\n%! a = 0;\n%! for x = ti(1:5).a_property\n%!   a = 1;\n%! endfor\n%! assert (a, 1);\n\n%!test <*63841>\n%! ti = cls2_b63841;\n%! [n_arg, b] = ti.call_a_method;\n%! assert (n_arg, 2);\n\n%!test <*63841>\n%! ti = cls2_b63841;\n%! [n_arg, b] = ti{1};\n%! assert (n_arg, 2);\n\n%!test <*63841>\n%! ti = cls2_b63841;\n%! [n_arg, b] = ti(1);\n%! assert (n_arg, 2);\n\n%!test <*63841>\n%! ti = cls2_b63841;\n%! [n_arg, b] = ti(1).a_property;\n%! assert (n_arg, 2);\n\n%%\n%% Different expressions that should produce errors (classdef and struct-based classes)\n%%\n\n%!shared ti, ti2\n%! ti = cls_b63841;\n%! ti2 = cls2_b63841;\n\n%% binary operator\n%!error <binary operator \\'\\+\\' not implemented for \\'scalar\\' by \\'cs-list\\' operations> 1 + ti(1:3).a_property\n%!error <binary operator \\'\\+\\' not implemented for \\'cs-list\\' by \\'scalar\\' operations> ti(1:3).a_property + 1\n%!error <binary operator \\'\\+\\' not implemented for \\'cs-list\\' by \\'cs-list\\' operations> ti(1:3).a_property + ti(1:3).a_property\n%!error <binary operator \\'\\+\\' not implemented for \\'scalar\\' by \\'cs-list\\' operations> 1 + ti2(1:3).a_property\n%!error <binary operator \\'\\+\\' not implemented for \\'cs-list\\' by \\'scalar\\' operations> ti2(1:3).a_property + 1\n%!error <binary operator \\'\\+\\' not implemented for \\'cs-list\\' by \\'cs-list\\' operations> ti2(1:3).a_property + ti2(1:3).a_property\n\n%% unary postfix operator\n%!error <unary operator \\'\\'\\' not implemented for \\'cs-list\\' operands> ti(1:3).a_property'\n%!error <unary operator \\'\\'\\' not implemented for \\'cs-list\\' operands> ti2(1:3).a_property'\n\n%% unary prefix operator\n%!error <unary operator \\'!\\' not implemented for \\'cs-list\\' operands> ~ti(1:3).a_property\n%!error <unary operator \\'!\\' not implemented for \\'cs-list\\' operands> ~ti2(1:3).a_property\n\n%% compound binary operation\n%!error <unary operator \\'\\'\\' not implemented for \\'cs-list\\' operands> 3*ti(1:3).a_property'\n%!error <unary operator \\'\\'\\' not implemented for \\'cs-list\\' operands> ti(1:3).a_property'*3\n%!error <unary operator \\'\\'\\' not implemented for \\'cs-list\\' operands> 3*ti2(1:3).a_property'\n%!error <unary operator \\'\\'\\' not implemented for \\'cs-list\\' operands> ti2(1:3).a_property'*3\n"
  },
  {
    "path": "test/bug-63841/cls_b63841.m",
    "content": "classdef cls_b63841\n  properties\n    a_property = 1;\n  end\n  methods\n    function varargout = subsref(obj, s)\n      varargout = {nargout, s(1).type, 'arg3'};\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-63841/module.mk",
    "content": "bug_63841_TEST_FILES = \\\n  %reldir%/@cls2_b63841/cls2_b63841.m \\\n  %reldir%/@cls2_b63841/subsref.m \\\n  %reldir%/bug-63841.tst \\\n  %reldir%/cls_b63841.m\n\nTEST_FILES += $(bug_63841_TEST_FILES)\n"
  },
  {
    "path": "test/bug-64620/bug-64620.tst",
    "content": "% Nested functions frame stored in handles would prevent parent frame\n% from being released causing memory leak.\n\n%!test <*64620>\n%! global cdef_alive_objects_cntr % Counts amount of alive cdef_counts_self handle objects\n%! cdef_alive_objects_cntr = 0;\n%! bug_64620_1;\n%! assert (cdef_alive_objects_cntr == 0);\n%!\n%! clear -global cdef_alive_objects_cntr\n\n%!test <*64620>\n%! bug_64620_2; % Asserts inside itself\n%! clear -global cdef_alive_objects_cntr\n"
  },
  {
    "path": "test/bug-64620/bug_64620_1.m",
    "content": "function bug_64620_1\n  h = subby;\nend\n\nfunction h = subby % The h return is needed for the bug to show\n  function nested_fn\n    % This framed stored shared pointer to subby's frame when put in handle\n  end\n\n  h = @nested_fn;\n\n  obj = cdef_counts_self;\n  % obj destructor was not triggered\nend\n"
  },
  {
    "path": "test/bug-64620/bug_64620_2.m",
    "content": "function bug_64620_2()\n  % Two levels of nested nesting\n  global cdef_alive_objects_cntr = 0;\n  cdef_alive_objects_cntr = 0;\n\n  h = sub_returns_nested_fn2;\n  h ();\n  h = 3; % Clear handle, triggers dtors\n\n  assert (cdef_alive_objects_cntr == 0);\nend\n\nfunction h1 = sub_returns_nested_fn2\n  c2 = cdef_counts_self;\n\n  function h2 = nested_fn1\n    c3 = cdef_counts_self;\n\n    function nested_fn2\n      c4 = cdef_counts_self;\n    end\n\n    h2 = @nested_fn2;\n  end\n\n  h1 = nested_fn1 ();\nend\n"
  },
  {
    "path": "test/bug-64620/cdef_counts_self.m",
    "content": "classdef cdef_counts_self < handle\n  methods\n    function obj = cdef_counts_self ()\n      global cdef_alive_objects_cntr = 0;\n      cdef_alive_objects_cntr++;\n    end\n    function delete (self)\n      global cdef_alive_objects_cntr = 0;\n      cdef_alive_objects_cntr--;\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-64620/module.mk",
    "content": "bug_64620_TEST_FILES = \\\n  %reldir%/bug-64620.tst \\\n  %reldir%/cdef_counts_self.m \\\n  %reldir%/bug_64620_1.m \\\n  %reldir%/bug_64620_2.m\n\nTEST_FILES += $(bug_64620_TEST_FILES)\n"
  },
  {
    "path": "test/bug-65037/bug-65037.tst",
    "content": "%!test <65037>\n%! base_1 = bug65037_base ('base class arg');\n%! derived = bug65037_derived ('derived class arg');\n%! base_2 = bug65037_base (base_1);\n%! base_3 = bug65037_base (derived);\n%! assert (base_1.ctor_nargin, 1);\n%! assert (derived.ctor_nargin, 1);\n%! assert (base_2.ctor_nargin, 1);\n%! assert (base_3.ctor_nargin, 1);\n"
  },
  {
    "path": "test/bug-65037/bug65037_base.m",
    "content": "classdef bug65037_base\n  properties\n    ctor_nargin;\n  end\n  methods\n    function obj = bug65037_base (varargin)\n      obj.ctor_nargin = nargin;\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-65037/bug65037_derived.m",
    "content": "classdef bug65037_derived < bug65037_base\n  methods\n    function obj = bug65037_derived (varargin)\n      obj@bug65037_base (varargin{:});\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-65037/module.mk",
    "content": "bug_65037_TEST_FILES = \\\n  %reldir%/bug-65037.tst \\\n  %reldir%/bug65037_base.m \\\n  %reldir%/bug65037_derived.m\n\nTEST_FILES += $(bug_65037_TEST_FILES)\n"
  },
  {
    "path": "test/bug-65153.tst",
    "content": "%!function retval = bug65153_flipud (x)\n%!  global bug65153_global_isargout\n%!  bug65153_global_isargout = isargout (1);\n%!  retval = flipud (x);\n%!endfunction\n\n## Bug 65153 revealed two problems related to the way Octave was\n## attempting to handle ignored function outputs.  One is that an\n## ignored output can propagate from one function to another in some\n## contexts.  For example, evaluating\n##\n##   [~, y] = bug65153_1 ()\n##\n## results in isargout(1) -> false in the call to bug65153_flipud.\n## The second problem is that even though the return value is always\n## set in bug65153_flipud, Octave was using the equivalent of the\n## isargout information internally and not assigning the return value\n## internally, so the matrix construction failed.  The second problem\n## is easier to solve than the first.  We test for each problem\n## separately here.\n\n%!function [x, y] = bug65153_1 ()\n%!  n = 10;\n%!  x = (1:n)';\n%!  y = (1:n)';\n%!  [(1:n)', bug65153_flipud((1:n)')];\n%!endfunction\n\n## The bug65153_2 function tests the same problem as bug65153_1 but for\n## a different context.  ANS should be assigned after the call to\n## bug65153_flipud but it was not because of Octave's incorrect internal\n## handling of ignored outputs.\n\n%!function x = bug65153_2 ()\n%!  global bug65153_global\n%!  bug65153_flipud ((1:10)');\n%!  x = ans;\n%!  bug65153_global = x;\n%!endfunction\n\n%!test <65153>\n%! global bug65153_global bug65153_global_isargout\n%! unwind_protect\n%!   [~, y] = bug65153_1 ();\n%!   assert (y, (1:10)');\n%! unwind_protect_cleanup\n%!   clear -global bug65153_global bug65153_global_isargout\n%! end_unwind_protect\n\n%!test <65153>\n%! global bug65153_global bug65153_global_isargout\n%! unwind_protect\n%!   [~, y] = bug65153_1 ();\n%!   assert (bug65153_global_isargout, true);\n%! unwind_protect_cleanup\n%!   clear -global bug65153_global bug65153_global_isargout\n%! end_unwind_protect\n\n%!test <65153>\n%! global bug65153_global bug65153_global_isargout\n%! unwind_protect\n%!   [~] = bug65153_2 ();\n%!   assert (bug65153_global, flipud ((1:10)'));\n%! unwind_protect_cleanup\n%!   clear -global bug65153_global bug65153_global_isargout\n%! end_unwind_protect\n\n%!test <65153>\n%! global bug65153_global bug65153_global_isargout\n%! unwind_protect\n%!   [~] = bug65153_2 ();\n%!   assert (bug65153_global_isargout, true);\n%! unwind_protect_cleanup\n%!   clear -global bug65153_global bug65153_global_isargout\n%! end_unwind_protect\n"
  },
  {
    "path": "test/bug-67096/bug-67096.tst",
    "content": "## Test nargout in classdef methods when the method call has no \"()\" and is\n## followed by another indexing operation\n\n%!test <*67096>\n%! cb = class_bug67096;\n%! [a, b] = cb.get_struct.data;\n%! assert( [a, b], [1, 2]);\n\n%!test <*67096>\n%! cb = class_bug67096;\n%! [a, b] = cb.get_cell{1:2};\n%! assert( [a, b], [1, 2]);\n"
  },
  {
    "path": "test/bug-67096/class_bug67096.m",
    "content": "classdef class_bug67096\n  methods\n    function r = get_struct (obj)\n      r = struct ('data', num2cell (nargout:nargout+4));\n    end\n    function r = get_cell (obj)\n      r = num2cell (nargout:nargout+4);\n    end\n  end\nend\n"
  },
  {
    "path": "test/bug-67096/module.mk",
    "content": "bug_67096_TEST_FILES = \\\n  %reldir%/bug-67096.tst \\\n  %reldir%/class_bug67096.m\n\nTEST_FILES += $(bug_67096_TEST_FILES)\n"
  },
  {
    "path": "test/bug-67403/bug-67403.tst",
    "content": "%!test <*67403>\n%! cb = class_bug67403 ();\n%! # Check numArgumentsFromSubscript is not called\n%! [a, b, c] = cb (1);\n%! assert ([a, b, c], [3, 3, 3]);\n%! assert (cb(1:3), 1);\n%! assert (cb{1}.a(1:3), 1);\n%! # Check numArgumentsFromSubscript is called\n%! assert ([cb{1:10}], [2, 2]);\n%! assert ([cb.a], [2, 2]);\n"
  },
  {
    "path": "test/bug-67403/class_bug67403.m",
    "content": "classdef class_bug67403\n  methods\n    function [varargout] = subsref (obj, s)\n      varargout = cell(1, max (nargout, 1));\n      varargout(:) = {nargout};\n    endfunction\n    function n = numArgumentsFromSubscript(obj, s, indexingContext)\n      n = 2;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/bug-67403/module.mk",
    "content": "bug_67403_TEST_FILES = \\\n  %reldir%/bug-67403.tst \\\n  %reldir%/class_bug67403.m\n\nTEST_FILES += $(bug_67403_TEST_FILES)\n"
  },
  {
    "path": "test/bug-67964/bug-67964.tst",
    "content": "## load anonymous function handle that does not require workspace context\n%!testif HAVE_ZLIB <*67964>\n%! ## file saved in MATLAB on amd64 using the following commands:\n%! ## f = @() x + 1;\n%! ## save ('foo1.mat', 'f', '-v7');\n%! l = load (\"foo1.mat\");\n%! assert (isfield (l, \"f\"));\n%! assert (isa (l.f, \"function_handle\"));\n%! assert (l.f (1), 2);\n\n## load anonymous function handle with associated workspace context\n%!testif HAVE_ZLIB <*67964>\n%! ## file saved in MATLAB on amd64 using the following commands:\n%! ## a = 3;\n%! ## g = @() x + a;\n%! ## save ('foo2.mat', 'g', '-v7');\n%! l = load (\"foo2.mat\");\n%! assert (isfield (l, \"g\"));\n%! assert (isa (l.g, \"function_handle\"));\n%! assert (l.g (1), 4);\n"
  },
  {
    "path": "test/bug-67964/module.mk",
    "content": "bug_67964_TEST_FILES = \\\n  %reldir%/bug-67964.tst \\\n  %reldir%/foo1.mat \\\n  %reldir%/foo2.mat\n\nTEST_FILES += $(bug_67964_TEST_FILES)\n"
  },
  {
    "path": "test/class-concat/@foo/foo.m",
    "content": "function r = foo ()\n  r = class (struct (), 'foo');\nendfunction\n"
  },
  {
    "path": "test/class-concat/class-concat.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2011-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! f = foo ();\n%! x = [f,f];\n%! assert (size (x), [1, 2]);\n%! assert (class (x), \"foo\");\n\n%!test\n%! f = foo ();\n%! x = [f,f];\n%! tmp = num2cell (x);\n%! assert (iscell (tmp));\n%! assert (size (tmp), [1, 2]);\n%! assert (class (tmp{1}), \"foo\");\n%! assert (class (tmp{2}), \"foo\");\n"
  },
  {
    "path": "test/class-concat/module.mk",
    "content": "class_concat_TEST_FILES = \\\n  %reldir%/@foo/foo.m \\\n  %reldir%/class-concat.tst\n\nTEST_FILES += $(class_concat_TEST_FILES)\n"
  },
  {
    "path": "test/classdef/@class_bug62802/amethod.m",
    "content": "function amethod (obj)\n## This method is stored in a separate file.\nendfunction\n"
  },
  {
    "path": "test/classdef/@class_bug62802/class_bug62802.m",
    "content": "classdef class_bug62802\n## Test class with methods in a @folder and in the classdef definition\n\n  methods\n\n    function obj = class_bug62802 ()\n    endfunction\n\n    function foo (obj)\n    endfunction\n\n    function disp (obj)\n      fprintf (\"Hello\\n\");\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef/@class_bug67362/class_bug67362.m",
    "content": "classdef class_bug67362\n## Test class with property that shares the name with a method in a @folder\n\n  properties\n    shared_name = 42;  # property shares name with method in @folder\n  endproperties\n\n  methods\n\n    function obj = class_bug67362 ()\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef/@class_bug67362/shared_name.m",
    "content": "function retval = shared_name (obj)\n## This method shares a name with a property.\n\nretval = 1;\n\nendfunction\n"
  },
  {
    "path": "test/classdef/@osc/osc.m",
    "content": "function obj = osc (data)\n  if (nargin == 0)\n    data = 0;\n  endif\n\n  s = struct;\n  s.data = data;\n  obj = class (s, 'osc');\nendfunction\n"
  },
  {
    "path": "test/classdef/bug_60763.m",
    "content": "classdef bug_60763\n  properties\n    some_property;\n  endproperties\n  methods\n    function p = foobar (instance)\n      p = properties (instance);\n    endfunction\n    function m = methods (instance)\n      m = 42;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/cdef_array_break_cycles.m",
    "content": "function fcn = cdef_array_break_cycles ()\n  obj_array(1) = foo_value_class ();\n  obj_array(2) = foo_value_class ();\n\n  function result = nested_func (x)\n    result = obj_array;\n  endfunction\n\n  fcn = @nested_func;\nendfunction\n"
  },
  {
    "path": "test/classdef/class_bug50011_1.m",
    "content": "classdef class_bug50011_1 < class_bug50011_1A & class_bug50011_1B\n  methods\n    function m_c (obj)\n      obj.m_meth ();\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug50011_1A.m",
    "content": "classdef class_bug50011_1A\n  methods\n    function v = m_meth (~)\n      v = 'class_bug50011_1A';\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug50011_1B.m",
    "content": "classdef class_bug50011_1B\n  methods\n    function v = m_meth (~)\n      v = 'class_bug50011_1B';\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug50011_2.m",
    "content": "classdef class_bug50011_2 < class_bug50011_2A & class_bug50011_2B\n  methods\n    function m_c (obj)\n      obj.m_prop;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug50011_2A.m",
    "content": "classdef class_bug50011_2A\n  properties\n    m_prop = \"class_bug50011_2A\"\n  endproperties\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug50011_2B.m",
    "content": "classdef class_bug50011_2B\n  properties\n    m_prop = \"class_bug50011_2B\"\n  endproperties\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug52614A.m",
    "content": "classdef class_bug52614A < handle\n  properties\n    a\n  end\n\n  methods\n    function obj = class_bug52614A ()\n      obj.foo ();\n    end\n\n    function foo (obj)\n      obj.a = 1;\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/class_bug52614B.m",
    "content": "classdef class_bug52614B < class_bug52614A\n  properties\n    b\n  end\n\n  methods\n    function obj = class_bug52614B ()\n      obj = obj@class_bug52614A ();\n    end\n\n    function foo (obj)\n      foo@class_bug52614A (obj);\n      obj.b = 2;\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/class_bug55766.m",
    "content": "classdef class_bug55766\n\n  properties\n    testprop = 0;\n  end\n\n  properties (Access = public)\n    publictestprop = 0;\n  end\n\n  properties (Access = protected)\n    protectedtestprop = 0;\n  end\n\n  properties (Hidden)\n    hiddentestprop = 0;\n  end\n\n  properties (Hidden = true)\n    anotherhiddentestprop = 0;\n  end\n\n  properties (Hidden = false)\n    notahiddentestprop = 0;\n  end\n\nend\n"
  },
  {
    "path": "test/classdef/class_bug59775A.m",
    "content": "classdef class_bug59775A\n  properties\n    A = 1\n  endproperties\n  methods\n    function obj = class_bug59775A (a)\n      if (nargin > 0)\n        if isscalar (a)\n          obj.A = a;\n        else\n          obj (size (a)) = class_bug59775A ();\n        endif\n      endif\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug59775B.m",
    "content": "classdef class_bug59775B\n  properties\n    A\n  endproperties\n  methods\n    function obj = class_bug59775B (a)\n      if (nargin > 0)\n        if (isscalar (a))\n          obj.A = a;\n        else\n          obj (size (a)) = class_bug59775B ();\n\n          for (kk = 1:numel (a))\n            obj(kk).A = a(kk);\n          endfor\n        endif\n      endif\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug60723A.m",
    "content": "classdef class_bug60723A\n  properties\n    c = 3;\n  end\n  methods\n    function n = numel (this)\n      n = 6;\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/class_bug60723B.m",
    "content": "classdef class_bug60723B\n  methods\n    function [varargout] = subsref (obj, s)\n      varargout = num2cell (repelem(nargout, max(nargout, 1)));\n    end\n    function n = numel (obj, idx)\n      n = 2;\n    end\n  end\nend\n\n"
  },
  {
    "path": "test/classdef/class_bug60723C.m",
    "content": "classdef class_bug60723C\n  methods\n    function [varargout] = subsref (obj, s)\n      varargout = num2cell (repelem(nargout, max(nargout, 1)));\n    end\n    function ind = end (obj, k, n)\n      ind = 4;\n    end\n  end\nend\n\n"
  },
  {
    "path": "test/classdef/class_bug66930A.m",
    "content": "classdef class_bug66930A\n\n  properties\n    bar = {}\n  endproperties\n\n  methods\n    function out = class_bug66930A (x, varargin)\n      out.bar = {x};\n    endfunction\n\n    function out = foofcn (x, varargin)\n      out = x;\n    endfunction\n\n    function out = foofcn (x, varargin)\n      out = x;\n    endfunction\n\n    function out = foofcn (x, varargin)\n      out = x;\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug66930B.m",
    "content": "classdef class_bug66930B\n\n  properties\n    bar = {}\n    bar = {}\n    bar = {}\n    bar = {}\n    bar = {}\n  endproperties\n\n  methods\n    function out =  class_bug66930B (x, varargin)\n      out.bar = {x};\n    endfunction\n\n    function out = foofcn1 (x, varargin)\n      out = x;\n    endfunction\n\n    function out = foofcn2 (x, varargin)\n      out = x;\n    endfunction\n\n    function out = foofcn3 (x, varargin)\n      out = x;\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug67845A.m",
    "content": "classdef class_bug67845A\n  properties\n    prop\n  endproperties\n\n  methods\n    function [obj, val_out] = class_bug67845A (val_in)\n      if (nargin < 1)\n        val_out = 0;\n        obj.prop = 0;\n      else\n        val_out = val_in;\n        obj.prop = val_in;\n      endif\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug67845A_handle.m",
    "content": "classdef class_bug67845A_handle < handle\n  properties\n    prop\n  endproperties\n\n  methods\n    function [obj, val_out] = class_bug67845A_handle (val_in)\n      if (nargin < 1)\n        val_out = 0;\n        obj.prop = 0;\n      else\n        val_out = val_in;\n        obj.prop = val_in;\n      endif\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug67845B.m",
    "content": "classdef class_bug67845B < class_bug67845A\n  methods\n    function [obj, val] = class_bug67845B ()\n      val = obj.prop;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug67845B_handle.m",
    "content": "classdef class_bug67845B_handle < class_bug67845A_handle\n  methods\n    function [obj, val] = class_bug67845B_handle ()\n      val = obj.prop;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug67845C.m",
    "content": "classdef class_bug67845C\n  methods\n    function [obj, val1, val2, val3, val4] ...\n        = class_bug67845C (val1_in, val2_in, val3_in, val4_in)\n\n      val1 = 1;\n      val2 = 2;\n      val3 = 3;\n      val4 = 4;\n\n      if (nargin >= 1)\n        val1 = val1_in;\n      endif\n\n      if (nargin >= 2)\n        val2 = val2_in;\n      endif\n\n      if (nargin >= 3)\n        val3 = val3_in;\n      endif\n\n      if (nargin >= 4)\n        val4 = val4_in;\n      endif\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_bug67845C_handle.m",
    "content": "classdef class_bug67845C_handle < handle\n  methods\n    function [obj, val1, val2, val3, val4] ...\n        = class_bug67845C_handle (val1_in, val2_in, val3_in, val4_in)\n\n      val1 = 1;\n      val2 = 2;\n      val3 = 3;\n      val4 = 4;\n\n      if (nargin >= 1)\n        val1 = val1_in;\n      endif\n\n      if (nargin >= 2)\n        val2 = val2_in;\n      endif\n\n      if (nargin >= 3)\n        val3 = val3_in;\n      endif\n\n      if (nargin >= 4)\n        val4 = val4_in;\n      endif\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_pair.m",
    "content": "classdef class_pair\n  properties\n    first\n    second\n  endproperties\n  methods\n    function this = class_pair (first, varargin)\n      if (isa (first, 'class_pair_elem'))\n        this.first = first.value;\n        this.second = 0;\n      else\n        this.first = first;\n        this.second = varargin{1};\n      endif\n    endfunction\n    function pe = class_pair_elem (this)\n      pe = class_pair_elem (this.first);\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_pair_elem.m",
    "content": "classdef class_pair_elem\n  properties\n    value\n  endproperties\n  methods\n    function this = class_pair_elem (value)\n      this.value = value;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_pair_elem_dominant.m",
    "content": "classdef (InferiorClasses = ?class_pair_elem) class_pair_elem_dominant\n  properties\n    value\n  endproperties\n\n  methods\n\n    function this = class_pair_elem_dominant (value)\n      this.value = value;\n    endfunction\n\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_pair_elem_dominant_handle.m",
    "content": "classdef (InferiorClasses = ?class_pair_elem_handle) class_pair_elem_dominant_handle < handle\n  properties\n    value\n  endproperties\n\n  methods\n\n    function this = class_pair_elem_dominant_handle (value)\n      this.value = value;\n    endfunction\n\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_pair_elem_handle.m",
    "content": "classdef class_pair_elem_handle < handle\n  properties\n    value\n  endproperties\n\n  methods\n\n    function this = class_pair_elem_handle (value)\n      this.value = value;\n    endfunction\n\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/class_pair_handle.m",
    "content": "classdef class_pair_handle < handle\n  properties\n    first\n    second\n  endproperties\n  methods\n    function this = class_pair_handle (first, varargin)\n      if (isa (first, 'class_pair_elem_handle'))\n        this.first = first.value;\n        this.second = 0;\n      else\n        this.first = first;\n        this.second = varargin{1};\n      endif\n    endfunction\n    function pe = class_pair_elem_handle (this)\n      pe = class_pair_elem_handle (this.first);\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/classdef.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%%  Test script for classdef OOP.\n%%  Requires the path to contain the test classes.\n%%\n%%  Note: This script and all classes are also intended to run\n%%        in MATLAB to test compatibility.  Don't break that!\n%%\n%%  FIXME: This script tests to ensure that things done correctly work\n%%         correctly.  It should also check that things done incorrectly\n%%         error properly.\n%%\n%%  The classes used for the tests reside in the test/classdef with others\n%%  in the test directory.\n%%\n%%  The classes provide the ability to test most of the major features\n%%  of the classdef OOP facilities.  There are a number of classes, mostly\n%%  kind of the same, that create a hierarchy.\n\n%%  Basic classdef tests for value class\n%!shared p, q, i, amt\n%! q = foo_value_class ();\n%! p = foo_value_class (4, 4*12, 50e3);\n%! i = p.rate / (12 * 100);\n%! amt = (p.principle * i) / (1 - (1 + i)^(-p.term));\n%!assert (isempty (q.rate))\n%!assert (isempty (q.principle))\n%!assert (isempty (q.term))\n%!assert (strcmp (class (p), 'foo_value_class'))\n%!assert (p.term == 48)\n%!assert (p.rate == 4.0)\n%!assert (p.principle == 50e3)\n%!assert (p.amount, amt, eps ())\n%!assert (amount (p), amt, eps ())\n%!test <55961>\n%! assert (properties (p), {'rate'; 'term'; 'principle'});\n%!test <*55858>\n%! assert (methods (p), {'amount'; 'foo_value_class'});\n%!assert (isempty (foo_value_class().rate))\n%!error <property 'rate' is not constant> foo_value_class.rate\n%!shared  # clear all shared variables for remainder of tests\n\n%%  Static method and Constant Property\n%!assert (foo_static_method_constant_property.radians_per_cycle == 2*pi)\n%!assert (foo_static_method_constant_property().radians_per_cycle == 2*pi)\n%!assert (foo_static_method_constant_property().pie == pi)\n%!error <property 'frequency' is not constant> foo_static_method_constant_property.frequency\n%!error <method 'cosine' is not static> foo_static_method_constant_property.cosine\n%!test\n%! obj = foo_static_method_constant_property;\n%! obj.frequency = 10;\n%! assert (obj.cosine (0.1), cos (2 * pi * 10 * 0.1), eps ());\n%! assert (obj.sine (0.1), sin (2 * pi * 10 * 0.1), eps ());\n\n%!test\n%! obj = foo_method_changes_property_size (3);\n%! obj = obj.move_element_to_end (2);\n%! assert (isequal (obj.element, [1 3 2]));\n\n%!error <syntax error> plist_t1\n%!assert (strcmp (class (plist_t2), 'plist_t2'))\n%!assert (strcmp (class (plist_t3), 'plist_t3'))\n\n%!test\n%! obj = struct_wrapper ();\n%! obj{'a'} = 1;\n%! assert (obj{'a'} == 1);\n%! obj{'bc'} = 2;\n%! assert (obj{'bc'} == 2);\n%! assert (isequal (obj{'a', 'bc'}, [1 2]));\n\n%% Test for meta.class.fromName\n%!test <*51935>\n%! meta.class.fromName (\"inputParser\");\n\n%% Do not change this to \"containers.Map()\".  This test is intended to\n%% ensure that calling a function in a +package directory will work\n%% properly.\n%!test <*51715>\n%! x = containers.Map;\n%! assert (isobject (x));\n\n%!assert <*52096> (isempty (meta.class.fromName (\"__nonexi$tent_cl@$$__\")))\n%!assert <*52096> (isempty (meta.package.fromName (\"__nonexi$tent_p@ck@ge__\")))\n\n%% Test overloaded subsref and subsasgn functions.\n%% (bug #54783, bug #54966, and bug #55223)\n%!test <*54783>\n%! obj = foo_subsref_subsasgn (1);\n%! obj(2) = 3;\n%! assert (obj(2) == 3);\n%! assert (obj{2} == 3);\n%! assert (isequal (obj.x, [1 3 3 4]));\n%! obj{2} = 4;\n%! assert (obj(2) == 4);\n%! assert (obj{2} == 4);\n%! assert (isequal (obj.x, [1 4 3 4]));\n%! obj(end) = 6;\n%! assert (obj(end) == 6);\n%! assert (obj{end} == 6);\n%! assert (isequal (obj.x, [1 4 3 6]));\n%! obj{end} = 8;\n%! assert (obj(end) == 8);\n%! assert (obj{end} == 8);\n%! assert (isequal (obj.x, [1 4 3 8]));\n%! obj.x = 1:4;\n%! assert (isequal (obj.x, 1:4));\n%! obj(1:3) = 7:9;\n%! assert (isequal (obj(1:3), 7:9));\n%! assert (isequal (obj.x, [7 8 9 4]));\n%! obj(2:end) = 5:7;\n%! assert (isequal (obj(2:end), 5:7));\n%! assert (isequal (obj.x, [7 5 6 7]));\n\n%!test <*54966>\n%! obj = foo_subsref_subsasgn (1);\n%! obj{1:3} = 5:7;\n%! assert (isequal ([obj{1:3}], 5:7));\n%! assert (isequal (obj.x, [5 6 7 4]));\n%! obj{2:end} = 7:9;\n%! assert (isequal ([obj{2:end}], 7:9));\n%! assert (isequal (obj.x, [5 7 8 9]));\n%! fail (\"[obj{1:3}] = 5:7;\", \"invalid number of output arguments\");\n\n%!test <*54783>\n%! obj = foo_subsref_subsasgn (1);\n%! obj.x(2) = 3;\n%! assert (obj.x(2) == 3);\n%! assert (obj.x{2} == 3);\n%! assert (isequal (obj.x, [1 3 3 4]));\n%! obj.x{2} = 4;\n%! assert (obj.x(2) == 4);\n%! assert (obj.x{2} == 4);\n%! assert (isequal (obj.x, [1 4 3 4]));\n%! obj.x(end) = 6;\n%! assert (obj.x(end) == 6);\n%! assert (obj.x{end} == 6);\n%! assert (isequal (obj.x, [1 4 3 6]));\n%! obj.x{end} = 8;\n%! assert (obj.x(end) == 8);\n%! assert (obj.x{end} == 8);\n%! assert (isequal (obj.x, [1 4 3 8]));\n%! obj.x = 1:4;\n%! assert (isequal (obj.x, 1:4));\n%! obj.x(1:3) = 7:9;\n%! assert (isequal (obj.x(1:3), 7:9));\n%! assert (isequal (obj.x, [7 8 9 4]));\n%! obj.x(2:end) = 5:7;\n%! assert (isequal (obj.x(2:end), 5:7));\n%! assert (isequal (obj.x, [7 5 6 7]));\n\n%!test <*54966>\n%! obj = foo_subsref_subsasgn (1);\n%! obj.x{1:3} = 5:7;\n%! assert (isequal ([obj.x{1:3}], 5:7));\n%! assert (isequal (obj.x, [5 6 7 4]));\n%! obj.x{2:end} = 7:9;\n%! assert (isequal ([obj.x{2:end}], 7:9));\n%! assert (isequal (obj.x, [5 7 8 9]));\n%! fail (\"[obj.x{1:3}] = 5:7;\", \"invalid number of output arguments\");\n\n%!test <*60723>\n%! # Check that numel is not called in subsasgn, simple assignment\n%! obj = class_bug60723A;\n%! obj.c = 20;\n%! assert (obj.c, 20);\n\n%!test <60723>\n%! # Check that numel is not called in subsasgn, multi-assignment\n%! obj = class_bug60723A ();\n%! [obj.c] = 20;\n%! assert (obj.c, 20);\n\n%!test <60723>\n%! # Check that numel is not called in subsref\n%! obj = class_bug60723B ();\n%! assert ([obj{1:5}], repelem (5, 5));\n%! assert ([obj(1:5).a], repelem (5, 5));\n\n%!test <*60723>\n%! obj = class_bug60723C ();\n%! assert ([obj{1:end}], repelem (4, 4));\n%! [a, b] = obj.x{1:end};\n\n%!test <*55223>\n%! obj = foo_subsref_subsasgn (2);\n%! obj{2}(2) = 3;\n%! assert (obj{2}(2) == 3);\n%! obj{2}{2} = 4;\n%! assert (obj{2}{2} == 4);\n\n%!test <*54966>\n%! obj = foo_subsref_subsasgn (2);\n%! obj{1:2}(1:2) = ones (2);\n%! assert (isequal (obj{1:2}(1:2), ones (2)));\n%! obj{3:4}(3:4) = 4 * ones (2);\n%! assert (isequal (obj{3:4}(3:4), 4 * ones (2)));\n\n%!test <*52614>\n%! A = class_bug52614A ();\n%! assert (A.a, 1);\n%! B = class_bug52614B ();\n%! assert (B.a, 1);\n%! assert (B.b, 2);\n\n%!test <*55766>\n%! x = class_bug55766 ();\n%! props = {\"testprop\"; \"publictestprop\"; \"notahiddentestprop\"};\n%! assert (properties (x), props);\n\n%!test <*60763>\n%! x = bug_60763 ();\n%! assert (x.foobar (), {\"some_property\"});\n%! assert (x.methods (), 42);\n\n## Multi-output constructor tests (bug #67845).\n\n## two-output constructor, no input args\n%!test <*67845>\n%! [obj, val] = class_bug67845A ();\n%! assert (isa (obj, \"class_bug67845A\"));\n%! assert (val, 0);\n\n## previous test, but with handle classes\n%!test <*67845>\n%! [obj, val] = class_bug67845A_handle ();\n%! assert (isa (obj, \"class_bug67845A_handle\"));\n%! assert (val, 0);\n%! obj2 = obj;\n%! assert (obj2.prop, 0);\n\n## two-output constructor with input args\n%!test <*67845>\n%! [obj, val] = class_bug67845A (5);\n%! assert (isa (obj, \"class_bug67845A\"));\n%! assert (val, 5);\n\n## previous test, but with handle classes\n%!test <*67845>\n%! [obj, val] = class_bug67845A_handle (5);\n%! assert (isa (obj, \"class_bug67845A_handle\"));\n%! assert (val, 5);\n%! obj2 = obj;\n%! obj.prop = 10;\n%! assert (obj2.prop, 10);\n\n## single-output call to two-output-declared constructor\n%!test <*67845>\n%! obj = class_bug67845A ();\n%! assert (isa (obj, \"class_bug67845A\"));\n%! assert (obj.prop, 0);\n\n## previous test, but with handle classes\n%!test <*67845>\n%! obj = class_bug67845A_handle ();\n%! assert (isa (obj, \"class_bug67845A_handle\"));\n%! assert (obj.prop, 0);\n\n## double-output with implicit superclass constructor\n%!test <*67845>\n%! [obj, val] = class_bug67845B ();\n%! assert (isa (obj, \"class_bug67845B\"));\n%! assert (isa (obj, \"class_bug67845A\"));\n%! assert (obj.prop, 0);\n\n## previous test, but with handle classes\n%!test <*67845>\n%! [obj, status] = class_bug67845B_handle ();\n%! assert (isa (obj, \"class_bug67845B_handle\"));\n%! assert (isa (obj, \"class_bug67845B_handle\"));\n%! assert (obj.prop, 0);\n\n## quad-output constructor with zero input args\n%!test <*67845>\n%! [obj, val1, val2, val3, val4] = class_bug67845C ();\n%! assert (isa (obj, 'class_bug67845C'));\n%! assert (val1, 1);\n%! assert (val2, 2);\n%! assert (val3, 3);\n%! assert (val4, 4);\n\n## previous test, but with handle classes\n%!test <*67845>\n%! [obj, val1, val2, val3, val4] = class_bug67845C_handle ();\n%! assert (isa (obj, 'class_bug67845C_handle'));\n%! assert (val1, 1);\n%! assert (val2, 2);\n%! assert (val3, 3);\n%! assert (val4, 4);\n\n## quad-output constructor with two input args\n%!test <*67845>\n%! [obj, val1, val2, val3, val4] = class_bug67845C ('5', {3});\n%! assert (isa (obj, 'class_bug67845C'));\n%! assert (val1, '5');\n%! assert (val2, {3});\n%! assert (val3, 3);\n%! assert (val4, 4);\n\n## previous test, but with handle classes\n%!test <*67845>\n%! [obj, val1, val2, val3, val4] = class_bug67845C_handle ('5', {3});\n%! assert (isa (obj, 'class_bug67845C_handle'));\n%! assert (val1, '5');\n%! assert (val2, {3});\n%! assert (val3, 3);\n%! assert (val4, 4);\n\n## quad-output constructor with four input args\n%!test <*67845>\n%! ## Have to declare func handle separately to check equality\n%! f = @(x) x + 1;\n%! [obj, val1, val2, val3, val4] = ...\n%!   class_bug67845C ('5', [10, 11; 12, 13], {15}, f);\n%! assert (isa (obj, 'class_bug67845C'));\n%! assert (val1, '5');\n%! assert (val2, [10, 11; 12, 13]);\n%! assert (val3, {15});\n%! assert (val4, f);\n\n## previous test, but with handle classes\n%!test <*67845>\n%! ## Have to declare func handle separately to check equality\n%! f = @(x) x + 1;\n%! [obj, val1, val2, val3, val4] = ...\n%!   class_bug67845C_handle ('5', [10, 11; 12, 13], {15}, f);\n%! assert (isa (obj, 'class_bug67845C_handle'));\n%! assert (val1, '5');\n%! assert (val2, [10, 11; 12, 13]);\n%! assert (val3, {15});\n%! assert (val4, f);\n\n## test class with methods in @folder and in classdef definition\n%!assert <*62802> (numel (methods (\"class_bug62802\")), 4)\n\n## Test class with duplicate definitions for methods (A) and properties (B)\n## This is bug #66930.\n%!error <duplicate method>   A = class_bug66930A ([1 2 3], 3);\n%!error <duplicate property> B = class_bug66930B ([1 2 3], 3);\n\n## break closure cycles for classdef arrays\n%!test <*67749>\n%! fcn = cdef_array_break_cycles ();\n%! result = fcn ([]);\n%! assert (numel (result), 2);\n%! assert (class (result), \"foo_value_class\");\n\n## duplicate definitions of methods in parent classes (bug #50011)\n%!error <method .* conflicting>\n%! cls_50011 = class_bug50011_1 ();\n%! cls_50011.m_c ();\n\n## duplicate definitions of properties in parent classes (bug #50011)\n%!error <property .* conflicting>\n%! cls_50011 = class_bug50011_2 ();\n%! cls_50011.m_c ();\n\n## sizeof tests (bug #55810)\n\n## sizeof a value classdef with no values inside properties\n%!test <*55810>\n%! obj = value_class ();\n%! assert (sizeof (obj), 0)\n\n## previous test, but with a classdef array\n%!test <*55810>\n%! obj(2, 2) = value_class ();\n%! assert (sizeof (obj), 0)\n\n## sizeof a value classdef with clearly defined value sizes inside properties\n%!test <*55810>\n%! obj = value_class ();\n%! obj.a = uint8 (1);\n%! obj.b = uint16 (1);\n%! obj.c = uint32 (1);\n%! obj.d = uint64 (1);\n%! true_size = sum ([sizeof(obj.a), sizeof(obj.b), ...\n%!   sizeof(obj.c), sizeof(obj.d)]);\n%! assert (sizeof (obj), true_size);\n\n## previous test, but with a classdef array\n%!test <*55810>\n%! obj(2, 2) = value_class ();\n%! for i = 1:numel (obj)\n%!   obj(i).a = uint8 (1);\n%!   obj(i).b = uint16 (1);\n%!   obj(i).c = uint32 (1);\n%!   obj(i).d = uint64 (1);\n%! endfor\n%! true_size = sum ([sizeof([obj.a]), sizeof([obj.b]), ...\n%!   sizeof([obj.c]), sizeof([obj.d])]);\n%! assert (sizeof (obj), true_size);\n\n## sizeof a value classdef that contains a classdef\n%!test <*55810>\n%! obj = value_class ();\n%! obj_inner = value_class ();\n%! obj_inner.a = uint8 (1);\n%! obj_inner.b = uint16 (1);\n%! obj_inner.c = uint32 (1);\n%! obj_inner.d = uint64 (1);\n%! obj.a = obj_inner;\n%! true_size = sum ([sizeof(obj.a), sizeof(obj.b), ...\n%!   sizeof(obj.c), sizeof(obj.d)]);\n%! assert (sizeof (obj), true_size);\n\n## previous test, but with a classdef array\n%!test <*55810>\n%! obj(2, 2) = value_class ();\n%! obj_inner = value_class ();\n%! obj_inner.a = uint8 (1);\n%! obj_inner.b = uint16 (1);\n%! obj_inner.c = uint32 (1);\n%! obj_inner.d = uint64 (1);\n%! for i = 1:numel (obj)\n%!   obj(i).a = obj_inner;\n%! endfor\n%! true_size = sum ([sizeof([obj.a]), sizeof([obj.b]), ...\n%!   sizeof([obj.c]), sizeof([obj.d])]);\n%! assert (sizeof (obj), true_size);\n\n## sizeof a value classdef that is a subclass of another\n%!test <*55810>\n%! obj = value_class_subclass ();\n%! obj.a = uint8 (1);\n%! obj.b = uint16 (1);\n%! obj.c = uint32 (1);\n%! obj.d = uint64 (1);\n%! true_size = sum ([sizeof(obj.a), sizeof(obj.b), ...\n%!   sizeof(obj.c), sizeof(obj.d)]);\n%! assert (sizeof (obj), true_size);\n%! obj.z = uint64 (1);\n%! true_size = true_size + sizeof (obj.z);\n%! assert (sizeof (obj), true_size);\n\n## overloaded sizeof method\n%!test <*55810>\n%! obj = overloaded_sizeof_class ();\n%! assert (sizeof (obj), -5);  # the retval of the overloaded method\n%! obj.a = uint8 (1);\n%! assert (sizeof (obj), -5);\n%! assert (builtin ('sizeof', obj), 1);\n\n## sizeof a handle class\n%!test <*55810>\n%! obj = handle_class ();\n%! [computer, maxsize] = computer ();\n%! if (maxsize == 2^(63))  # if machine is 64-bit:\n%!   assert (sizeof (obj), 8);  # size is the machine word\n%! endif\n\n## reshape array of value class objects\n%!test <*65179>\n%! obj(1,1) = value_class ();\n%! obj(2,3) = value_class ();\n%! assert (size (obj), [2, 3]);\n%! assert (size (reshape (obj, [3, 2])), [3, 2]);\n\n## reshape array of handle class objects\n%!test <*65179>\n%! obj1(1,1) = handle_class ();\n%! obj1(2,3) = handle_class ();\n%! assert (size (obj1), [2, 3]);\n%! obj2 = reshape (obj1, [3, 2]);\n%! assert (size (obj2), [3, 2]);\n%! obj1(2,3).a = 42;\n%! assert (obj2(3,2).a, 42);\n\n## reshape array of value class objects with overloaded reshape function\n%!test <*65179>\n%! obj1(1,1) = value_class_reshape ();\n%! obj1(2,3) = value_class_reshape ();\n%! assert (size (obj1), [2, 3]);\n%! obj2 = reshape (obj1, [3, 2]);\n%! assert (size (obj2), [2, 3]);\n%! assert (obj2(end).a, [3, 2]);\n\n## reshape on scalar objects only works for all-one dimensions\n%!test <*65179>\n%! assert (size (reshape (value_class (), [1, 1])), [1, 1]);\n\n%!error <cannot reshape scalar .* to .* array>\n%! reshape (value_class (), [3, 2]);\n\n## subsasgn of classdef array with fewer ()-indices than array dimensions\n%!test <*65179>\n%! obj(2,3,2) = value_class ();\n%! obj(12).a = 42;\n%! assert (size (obj), [2, 3, 2]);\n%! assert (obj(2,3,2).a, 42);\n%! obj(2,4).a = 33;\n%! assert (size (obj), [2, 3, 2]);\n%! assert (obj(2,1,2).a, 33);\n\n## properties take precedence over methods with the same name\n%!test <*67362>\n%! obj = class_bug67362 ();\n%! assert (obj.shared_name, 42);\n\n## concatenation of value classes without conversion\n%!test <*44665>\n%! p = class_pair (3, 5);\n%! p2 = class_pair (7, 4);\n%! y = [p, [p2, p]];\n%! assert (size (y), [1, 3]);\n%! assert ([y.first; y.second], [3, 7, 3; 5, 4, 5]);\n%! z = [y; p2, [p2, p]];\n%! assert (size (z), [2, 3]);\n%! assert ([z.first; z.second], [3, 7, 7, 7, 3, 3; 5, 4, 4, 4, 5, 5]);\n%! v = [z, z; y, p, [p2, p]];\n%! assert (size (v), [3, 6]);\n\n## concatenation of value classes using functions\n%!test <*44665>\n%! p = class_pair (3, 5);\n%! p2 = class_pair (7, 4);\n%! assert( size (horzcat (p, p2, p)), [1, 3]);\n%! assert( size (vertcat (p, p2, p)), [3, 1]);\n%! assert( size (cat (4, p, p2)), [1, 1, 1, 2]);\n\n## concatenation with handle class\n%!test <*44665>\n%! h = handle_class ();\n%! h.a = 1;\n%! h2 = handle_class ();\n%! h2.a = 2;\n%! arr = [h, h2, h];\n%! assert (size (arr), [1, 3]);\n%! assert ([arr(:).a], [1, 2, 1]);\n%! h(1).a = 3;\n%! assert ([arr(:).a], [3, 2, 3]);\n\n## error message when concatenating incompatible classdefs, no constructors\n%!error <cat: cannot convert from type \"handle_class\" to type \"value_class\">\n%! v = value_class ();\n%! h = handle_class ();\n%! [ v, h ];\n\n## previous test, but try type converting value class to handle class\n%!error <cat: cannot convert from type \"value_class\" to type \"handle_class\">\n%! v = value_class ();\n%! h = handle_class ();\n%! [ h, v ];\n\n## error message when concatenating classdef and builtin-type, no constructor\n%!error <cat: cannot convert from type \"double\" to type \"value_class\">\n%! v = value_class ();\n%! [ v, 3 ];\n\n## previous test, but try type converting value class to handle class\n%!error <cat: cannot convert from type \"double\" to type \"handle_class\">\n%! h = handle_class ();\n%! [ h, 3 ];\n\n## concatenation of empty object with value class\n%!test <*44665>\n%! v = value_class ();\n%! arr = [ [] v [] ];\n%! arr = [ [] arr [] ];\n%! assert (size(arr), [1 1]);\n\n## previous test, but with handle class\n%!test <*44665>\n%! h = handle_class ();\n%! arr = [ [] h [] ];\n%! arr = [ [] arr [] ];\n%! assert (size(arr), [1 1]);\n\n## error message when concatenating incompatible classdefs, failed constructor\n## FIXME: May change this error in the future to indicate that the type\n## conversion was tried explicitly during a concatenation.  Right now, this\n## error is thrown in the function \"attempt_type_conversion\" in data.cc, which\n## may not necessarily be called by only \"cat\".\n%!error <foo_value_class constructor failed for class_pair_elem argument>\n%! f = foo_value_class (4, 12, 20000);\n%! p = class_pair_elem (5);\n%! [ f, p ];\n\n## classdef concatenation of value classes using conversion method of\n## non-dominant class.\n## Since neither class in this example has a defined dominance relation, the\n## dominant class is the left-most class in the concatenation.\n%!test <*44665>\n%! y = [class_pair_elem(7), class_pair(3, 5)];\n%! assert (class (y), 'class_pair_elem');\n%! assert (size (y), [1, 2]);\n%! assert ([y.value], [7, 3]);\n\n## previous test, but with handle classes\n%!test <*44665>\n%! y = [class_pair_elem_handle(7), class_pair_handle(3, 5)];\n%! assert (class (y), 'class_pair_elem_handle');\n%! assert (size (y), [1, 2]);\n%! assert ([y.value], [7, 3]);\n\n## classdef concatenation using constructor of dominant class to convert other\n## classdefs\n%!test <*44665>\n%! y = [class_pair(3, 5), class_pair_elem(7)];\n%! assert (class (y), 'class_pair');\n%! assert ([y.first; y.second], [3, 7; 5, 0]);\n\n## pprevious test, but with handle classes\n%!test <*44665>\n%! y = [class_pair_handle(3, 5), class_pair_elem_handle(7)];\n%! assert (class (y), 'class_pair_handle');\n%! assert ([y.first; y.second], [3, 7; 5, 0]);\n\n## classdef concatenation of value classes using constructor of dominant class\n## to convert built-in types\n%!test <*44665>\n%! y = class_pair_elem (1);\n%! y = [y, double(2)];\n%! y = [y, single(3)];\n%! y = [y, int8(4)];\n%! y = [y, uint8(5)];\n%! y = [y, int16(6)];\n%! y = [y, uint16(7)];\n%! y = [y, int32(8)];\n%! y = [y, uint32(9)];\n%! y = [y, 'a'];\n%! y = [y, true];\n%! ## Have to declare func handle separately to check equality\n%! f = @(x) x + 1;\n%! y = [y, f];\n%! y = [y, struct(\"foo\", 1)];\n%! y = [y, {1, 2, 3}];\n%! assert (class (y), 'class_pair_elem');\n%! assert (size (y), [1, 14]);\n%! assert (y(2).value, double (2));\n%! assert (y(3).value, single (3));\n%! assert (y(4).value, int8 (4));\n%! assert (y(5).value, uint8 (5));\n%! assert (y(6).value, int16 (6));\n%! assert (y(7).value, uint16 (7));\n%! assert (y(8).value, int32 (8));\n%! assert (y(9).value, uint32 (9));\n%! assert (y(10).value, 'a');\n%! assert (y(11).value, true);\n%! assert (y(12).value, f);\n%! assert (y(13).value, struct (\"foo\", 1));\n%! assert (y(14).value, {1, 2, 3});\n\n## previous test, but with handle classes\n%!test <*44665>\n%! y = class_pair_elem_handle (1);\n%! y = [y, double(2)];\n%! y = [y, single(3)];\n%! y = [y, int8(4)];\n%! y = [y, uint8(5)];\n%! y = [y, int16(6)];\n%! y = [y, uint16(7)];\n%! y = [y, int32(8)];\n%! y = [y, uint32(9)];\n%! y = [y, 'a'];\n%! y = [y, true];\n%! ## Have to declare func handle separately to check equality\n%! f = @(x) x + 1;\n%! y = [y, f];\n%! y = [y, struct(\"foo\", 1)];\n%! y = [y, {1, 2, 3}];\n%! assert (class (y), 'class_pair_elem_handle');\n%! assert (size (y), [1, 14]);\n%! assert (y(2).value, double (2));\n%! assert (y(3).value, single (3));\n%! assert (y(4).value, int8 (4));\n%! assert (y(5).value, uint8 (5));\n%! assert (y(6).value, int16 (6));\n%! assert (y(7).value, uint16 (7));\n%! assert (y(8).value, int32 (8));\n%! assert (y(9).value, uint32 (9));\n%! assert (y(10).value, 'a');\n%! assert (y(11).value, true);\n%! assert (y(12).value, f);\n%! assert (y(13).value, struct (\"foo\", 1));\n%! assert (y(14).value, {1, 2, 3});\n\n## concatenation of value classdef (dominant arg) and old-style classes\n%!test <*44665>\n%! p = class_pair_elem (1);\n%! o = osc (2);\n%! arr = [ p, o ];\n%! assert (class (arr), 'class_pair_elem');\n%! assert (size (arr), [1 2]);\n\n## concatenation of value classdef (dominant arg) and old-style classes\n%!test <*44665>\n%! p = class_pair_elem_handle (1);\n%! o = osc (2);\n%! arr = [ p, o ];\n%! assert (class (arr), 'class_pair_elem_handle');\n%! assert (size (arr), [1 2]);\n\n## concatenation of old-style class (dominant arg) and value classdef\n%!test <*44665>\n%! p = class_pair_elem (1);\n%! o = osc (2);\n%! arr = [ o, p ];\n%! assert (class (arr), 'osc');\n%! assert (size (arr), [1 2]);\n\n## concatenation of old-style class (dominant arg) and handle classdef\n%!test <*44665>\n%! p = class_pair_elem_handle (1);\n%! o = osc (2);\n%! arr = [ o, p ];\n%! assert (class (arr), 'osc');\n%! assert (size (arr), [1 2]);\n\n## classdef array concatenation of value classes has value semantics\n%!test <*44665>\n%! p1 = class_pair_elem (1);\n%! p2 = class_pair_elem (2);\n%! arr = [p1, p2];\n%! p1.value = 3;\n%! ## Array elements should be independent copies (value semantics)\n%! assert (arr(1).value, 1);\n%! assert (arr(2).value, 2);\n%! assert (p1.value, 3);\n\n## classdef array concatenation of handle classes has handle semantics\n%!test <*44665>\n%! p1 = class_pair_elem_handle (1);\n%! p2 = class_pair_elem_handle (2);\n%! arr = [p1, p2];\n%! p1.value = 3;\n%! ## Array elements should be pointers to the same underlying object\n%! assert (arr(1).value, 3);\n%! assert (arr(2).value, 2);\n%! assert (p1.value, 3);\n\n## concatenation edge cases - single object operations\n%!test <*44665>\n%! p1 = class_pair (1, 2);\n%! ## Concatenating single object should preserve dimensions\n%! result = [p1];\n%! assert (size (result), [1, 1]);\n%! assert (result.first, 1);\n%! ## Test assignment with a 1x1 object -- should work the same as a scalar\n%! result.first = 2;\n%! assert (result.first, 2);\n%! ## Using cat with single object\n%! result2 = cat (1, p1);\n%! assert (size (result2), [1, 1]);\n%! assert (result2.first, 1);\n\n## previous test, but with handle classes\n%!test <*44665>\n%! h = class_pair_handle (1, 2);\n%! ## Concatenating single object should preserve dimensions\n%! result = [h];\n%! assert (size (result), [1, 1]);\n%! assert (result.first, 1);\n%! ## Test assignment with a 1x1 object -- should work the same as a scalar\n%! result.first = 2;\n%! assert (result.first, 2);\n%! ## Using cat with single object\n%! result2 = cat (1, h);\n%! assert (size (result2), [1, 1]);\n%! assert (result2.first, 2);\n\n## Concatenation with overloaded \"cat\" method, value class\n%!test <*44665>\n%! o1 = overloaded_cat_class ();\n%! o1.data = 1;\n%! o2 = overloaded_cat_class ();\n%! o2.data = 2;\n%! arr = horzcat(o1, o2);\n%! # See \"overloaded_cat_class.m\" for specifics how cat is implemented\n%! assert (size (arr), [1, 1]);\n%! assert (numel ({arr.data}), 1);\n%! assert (arr.data, [1, 2]);\n%! arr = vertcat (arr, arr);\n%! assert (size (arr), [1, 1]);\n%! assert (numel ({arr.data}), 1);\n%! assert (arr.data, [1, 2; 1, 2]);\n%! arr = cat (3, arr, arr);\n%! assert (numel ({arr.data}), 1);\n%! assert (arr.data, cat (3, [1, 2; 1, 2], [1, 2; 1, 2]));\n\n## previous test, but with handle classes\n%!test <*44665>\n%! o1 = overloaded_cat_class_handle ();\n%! o1.data = 1;\n%! o2 = overloaded_cat_class_handle ();\n%! o2.data = 2;\n%! arr = horzcat (o1, o2);\n%! # See \"overloaded_cat_class.m\" for specifics how cat is implemented\n%! assert (size (arr), [1, 1]);\n%! assert (numel ({arr.data}), 1);\n%! assert (arr.data, [1, 2]);\n%! arr = vertcat (arr, arr);\n%! assert (size (arr), [1, 1]);\n%! assert (numel ({arr.data}), 1);\n%! assert (arr.data, [1, 2; 1, 2]);\n%! arr = cat (3, arr, arr);\n%! assert (numel ({arr.data}), 1);\n%! assert (arr.data, cat (3, [1, 2; 1, 2], [1, 2; 1, 2]));\n\n## Test concatenation of classdef that overloads horzcat and vertcat, but not cat\n## See \"overloaded_horzcat_vertcat_class.m\" for more specifics\n%!test <*44665>\n%! o1 = overloaded_horzcat_vertcat_class ();\n%! o1.data = 1;\n%! o2 = overloaded_horzcat_vertcat_class ();\n%! o2.data = 2;\n%! arr = horzcat(o1, o2);\n%! assert (size (arr), [1, 1]);\n%! assert (numel ({arr.data}), 1);\n%! assert (arr.data, [1, 2]);\n%! o1.data = 1;\n%! o2.data = 2;\n%! arr = vertcat (o1, o2);\n%! assert (size (arr), [1, 1]);\n%! assert (numel ({arr.data}), 1);\n%! assert (arr.data, [1; 2]);\n%! o1.data = 1;\n%! o2.data = 2;\n%! arr = [o1, o2; o1, o2];\n%! assert (size (arr), [1, 1]);\n%! assert (numel ({arr.data}), 1);\n%! assert (arr.data, [1, 2; 1, 2]);\n%! o1.data = 1;\n%! o2.data = 2;\n%! arr = cat (3, o1, o2);\n%! assert (size (arr), [1, 1, 2]);\n%! assert (numel ({arr.data}), 2);\n%! assert (cat (3, arr.data), cat (3, 1, 2));\n\n## previous test, but with handle classes\n%!test <*44665>\n%! o1 = overloaded_horzcat_vertcat_class_handle ();\n%! o1.data = 1;\n%! o2 = overloaded_horzcat_vertcat_class_handle ();\n%! o2.data = 2;\n%! arr_horzcat = horzcat (o1, o2);\n%! assert (size (arr_horzcat), [1, 1]);\n%! assert (numel ({arr_horzcat.data}), 1);\n%! assert (arr_horzcat.data, [1, 2]);\n%! o1.data = 1;\n%! o2.data = 2;\n%! arr_vertcat = vertcat (o1, o2);\n%! assert (size (arr_vertcat), [1, 1]);\n%! assert (numel ({arr_vertcat.data}), 1);\n%! assert (arr_vertcat.data, [1; 2]);\n%! o1.data = 1;\n%! o2.data = 2;\n%! arr_matrix = [o1, o2; o1, o2];\n%! assert (size (arr_matrix), [1, 1]);\n%! assert (numel ({arr_matrix.data}), 1);\n%! assert (arr_matrix.data, [1, 2, 2; 1, 2, 2]);\n%! o1.data = 1;\n%! o2.data = 2;\n%! arr = cat (3, o1, o2);\n%! assert (size (arr), [1, 1, 2]);\n%! assert (numel ({arr.data}), 2);\n%! assert (cat (3, arr.data), cat (3, 1, 2));\n\n# selection of dominant class when concatenating classdefs\n# FIXME: This relies on the \"InferiorClasses\" attribute being supported.\n%!test <44665>\n%! p1 = class_pair_elem (1);\n%! p2 = class_pair_elem_dominant (2);\n%! arr = [ p1, p2 ];\n%! assert (class (arr), 'class_pair_elem_dominant');\n\n## previous test, but with handle classes\n%!test <44665>\n%! p1 = class_pair_elem_handle (1);\n%! p2 = class_pair_elem_dominant_handle (2);\n%! arr = [ p1, p2 ];\n%! assert (class (arr), 'class_pair_elem_dominant_handle');\n\n## deep copy (on write) of value class arrays\n%!test <*54028>\n%! arr1 = value_class ();\n%! arr1.a = 1;\n%! arr1(2) = arr1;\n%! arr2 = arr1;\n%! arr2(1).a = 2;\n%! assert (arr1(1).a, 1);\n\n## same thing with handle class arrays\n%!test\n%! arr1 = handle_class ();\n%! arr1.a = 1;\n%! arr1(2) = arr1;\n%! arr2 = arr1;\n%! arr2(1).a = 2;\n%! assert (arr1(1).a, 2);\n\n## Test classdef permutation\n\n## scalar permute with value class - should return scalar unchanged\n%!test <*65179>\n%! obj = foo_value_class (4, 48, 50000);\n%! result = permute (obj, [1, 2]);  # permute ignores out-of-bounds dims on scalars\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n\n## previous test, but with handle classes\n%!test <*65179>\n%! obj = foo_handle_class (4, 48, 50000);\n%! result = permute (obj, [1, 2]);  # permute ignores out-of-bounds dims on scalars\n%! assert (isequal (obj.rate, result.rate));\n%! obj.rate = 5;  # stress test handle semantics\n%! assert (isequal (obj.rate, result.rate));\n%! assert (isequal (obj.term, result.term));\n%! assert (isequal (obj.principle, result.principle));\n\n## scalar permute with value class and extra dim - should return scalar unchanged\n%!test <*65179>\n%! obj = foo_value_class (3, 36, 25000);\n%! result = permute (obj, [2, 1, 3]);  # permute ignores extra ndims on scalars\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n\n## previous test, but with handle classes\n%!test <*65179>\n%! obj = foo_handle_class (3, 36, 25000);\n%! result = permute (obj, [2, 1, 3]);  # permute ignores extra ndims on scalars\n%! assert (isequal (obj.rate, result.rate));\n%! obj.rate = 4;  # stress test handle semantics\n%! assert (isequal (obj.rate, result.rate));\n%! assert (isequal (obj.term, result.term));\n%! assert (isequal (obj.principle, result.principle));\n\n## array permute - 2-D transpose\n%!test <*65179>\n%! obj1 = foo_value_class (4, 48, 50000);\n%! obj2 = foo_value_class (3, 36, 25000);\n%! obj3 = foo_value_class (5, 60, 75000);\n%! obj4 = foo_value_class (6, 72, 10000);\n%! arr = [obj1, obj2; obj3, obj4];\n%! result = permute (arr, [2, 1]);\n%! assert (size (result), [2, 2]);\n%! assert (result(1,1).rate, arr(1,1).rate);\n%! assert (result(1,2).rate, arr(2,1).rate);\n%! assert (result(2,1).rate, arr(1,2).rate);\n%! assert (result(2,2).rate, arr(2,2).rate);\n\n## previous test, but with handle classes\n%!test <*65179>\n%! obj1 = foo_handle_class (4, 48, 50000);\n%! obj2 = foo_handle_class (3, 36, 25000);\n%! obj3 = foo_handle_class (5, 60, 75000);\n%! obj4 = foo_handle_class (6, 72, 10000);\n%! arr = [obj1, obj2; obj3, obj4];\n%! result = permute (arr, [2, 1]);\n%! assert (size (result), [2, 2]);\n%! assert (result(1,1).rate, arr(1,1).rate);\n%! assert (result(1,2).rate, arr(2,1).rate);\n%! assert (result(2,1).rate, arr(1,2).rate);\n%! assert (result(2,2).rate, arr(2,2).rate);\n%! arr(1,1).rate = 7;  # stress test handle semantics\n%! assert (result(1,1).rate, arr(1,1).rate);\n\n## 3-D array permute\n%!test <*65179>\n%! obj1 = foo_value_class (4, 48, 50000);\n%! obj2 = foo_value_class (3, 36, 25000);\n%! obj3 = foo_value_class (5, 60, 75000);\n%! obj4 = foo_value_class (6, 72, 10000);\n%! arr = cat (3, [obj1; obj2], [obj3; obj4]);  # 2x1x2 array\n%! result = permute (arr, [2, 1, 3]);  # 1x2x2 array\n%! assert (size (result), [1, 2, 2]);\n%! assert (result(1,1,1).rate, arr(1,1,1).rate);\n%! assert (result(1,2,1).rate, arr(2,1,1).rate);\n%! assert (result(1,1,2).rate, arr(1,1,2).rate);\n%! assert (result(1,2,2).rate, arr(2,1,2).rate);\n\n## previous test, but with handle classes\n%!test <*65179>\n%! obj1 = foo_handle_class (4, 48, 50000);\n%! obj2 = foo_handle_class (3, 36, 25000);\n%! obj3 = foo_handle_class (5, 60, 75000);\n%! obj4 = foo_handle_class (6, 72, 10000);\n%! arr = cat (3, [obj1; obj2], [obj3; obj4]);  # 2x1x2 array\n%! result = permute (arr, [2, 1, 3]);  # 1x2x2 array\n%! assert (size (result), [1, 2, 2]);\n%! assert (result(1,1,1).rate, arr(1,1,1).rate);\n%! assert (result(1,2,1).rate, arr(2,1,1).rate);\n%! assert (result(1,1,2).rate, arr(1,1,2).rate);\n%! assert (result(1,2,2).rate, arr(2,1,2).rate);\n%! arr(1,1,1).rate = 7;  # stress test handle semantics\n%! assert (result(1,1,1).rate, arr(1,1,1).rate);\n\n## test overloaded \"permute\" method\n## see \"overloaded_permute_class.m\" for more specifics\n%!test <*65179>\n%! obj1 = overloaded_permute_class;\n%! obj2 = overloaded_permute_class;\n%! obj3 = overloaded_permute_class;\n%! obj4 = overloaded_permute_class;\n%! arr = [obj1, obj2, obj3, obj4];\n%! result = permute (arr, [2, 1]);\n%! assert (size (result), [1, 4]);  # unchanged\n%! result(1).data = 5;\n%! assert (obj1.data, []);  # stress test value semantics\n%! ## Make it into a 3-D array\n%! arr = cat (3, arr, arr);\n%! result = permute (arr, [1, 2, 3]);\n%! assert (size (result), [2, 1, 4]);  # [1, 4, 2] -> [2, 1, 4]\n\n## previous test, but with handle classes\n%!test <*65179>\n%! obj1 = overloaded_permute_class_handle;\n%! obj2 = overloaded_permute_class_handle;\n%! obj3 = overloaded_permute_class_handle;\n%! obj4 = overloaded_permute_class_handle;\n%! arr = [obj1, obj2, obj3, obj4];\n%! result = permute (arr, [2, 1]);\n%! assert (size (result), [1, 4])  # unchanged\n%! result(1).data = 5;\n%! assert (obj1.data, 5);  # stress test handle semantics\n%! ## Make it into a 3-D array\n%! arr = cat (3, arr, arr);\n%! result = permute (arr, [1, 2, 3]);\n%! assert (size (result), [2, 1, 4]);  # [1, 4, 2] -> [2, 1, 4]\n\n## Test classdef transpose and ctranspose\n\n## scalar transpose - should return scalar unchanged\n%!test\n%! obj = foo_value_class (4, 48, 50000);\n%! result = transpose (obj);\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n%! assert (size (result), [1, 1]);\n%! obj.rate = 2;\n%! assert (result.rate, 4);  # stress test value semantics\n\n## previous test, but with handle classes\n%!test\n%! obj = foo_handle_class (4, 48, 50000);\n%! result = transpose (obj);\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n%! assert (size (result), [1, 1]);\n%! obj.rate = 2;\n%! assert (result.rate, 2);  # stress test handle semantics\n\n## scalar transpose operator - should return scalar unchanged\n%!test\n%! obj = foo_value_class (4, 48, 50000);\n%! result = obj.';  # Test .' operator\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n%! assert (size (result), [1, 1]);\n%! obj.rate = 2;\n%! assert (result.rate, 4);  # stress test value semantics\n\n## previous test, but with handle classes\n%!test\n%! obj = foo_handle_class (4, 48, 50000);\n%! result = obj.';  # Test .' operator\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n%! assert (size (result), [1, 1]);\n%! obj.rate = 2;\n%! assert (result.rate, 2);  # stress test handle semantics\n\n## scalar ctranspose - should work same as transpose for classdef\n%!test\n%! obj = foo_value_class (4, 48, 50000);\n%! result = ctranspose (obj);\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n%! assert (size (result), [1, 1]);\n%! obj.rate = 2;\n%! assert (result.rate, 4);  # stress test value semantics\n\n## previous test, but with handle classes\n%!test\n%! obj = foo_handle_class (4, 48, 50000);\n%! result = ctranspose (obj);\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n%! assert (size (result), [1, 1]);\n%! obj.rate = 2;\n%! assert (result.rate, 2);  # stress test handle semantics\n\n## scalar ctranspose operator - should work same as transpose for classdef\n%!test\n%! obj = foo_value_class (4, 48, 50000);\n%! result = obj';  # Test ' operator\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n%! assert (size (result), [1, 1]);\n%! obj.rate = 2;\n%! assert (result.rate, 4);  # stress test value semantics\n\n## previous test, but with handle classes\n%!test\n%! obj = foo_handle_class (4, 48, 50000);\n%! result = obj';  # Test ' operator\n%! assert (obj.rate, result.rate);\n%! assert (obj.term, result.term);\n%! assert (obj.principle, result.principle);\n%! assert (size (result), [1, 1]);\n%! obj.rate = 2;\n%! assert (result.rate, 2);  # stress test handle semantics\n\n## 1-D array transpose, dims [1 3] -> dims[3 1], value classes\n%!test\n%! obj1 = foo_value_class (4, 48, 50000);\n%! obj2 = foo_value_class (3, 36, 25000);\n%! obj3 = foo_value_class (5, 60, 75000);\n%! arr = [obj1, obj2, obj3];  # 1x3 row vector\n%! result = transpose (arr);\n%! assert (size (result), [3, 1]);\n%! assert (result(1,1).rate, arr(1,1).rate);\n%! assert (result(2,1).rate, arr(1,2).rate);\n%! assert (result(3,1).rate, arr(1,3).rate);\n\n## previous test, but with handle classes\n%!test\n%! obj1 = foo_handle_class (4, 48, 50000);\n%! obj2 = foo_handle_class (3, 36, 25000);\n%! obj3 = foo_handle_class (5, 60, 75000);\n%! arr = [obj1, obj2, obj3];  # 1x3 row vector\n%! result = transpose (arr);\n%! assert (size (result), [3, 1]);\n%! assert (result(1,1).rate, arr(1,1).rate);\n%! assert (result(2,1).rate, arr(1,2).rate);\n%! assert (result(3,1).rate, arr(1,3).rate);\n%! arr(1,1).rate = 6;  # stress test handle semantics\n%! assert (result(1,1).rate, arr(1,1).rate);\n\n## 1-D array transpose, dims [3 1] -> [1 3], value classes\n%!test\n%! obj1 = foo_value_class (4, 48, 50000);\n%! obj2 = foo_value_class (3, 36, 25000);\n%! obj3 = foo_value_class (5, 60, 75000);\n%! arr = [obj1; obj2; obj3];  # 3x1 column vector\n%! result = arr.';\n%! assert (size (result), [1, 3]);\n%! assert (result(1).rate, obj1.rate);\n%! assert (result(2).rate, obj2.rate);\n%! assert (result(3).rate, obj3.rate);\n\n## previous test, but with handle classes\n%!test\n%! obj1 = foo_handle_class (4, 48, 50000);\n%! obj2 = foo_handle_class (3, 36, 25000);\n%! obj3 = foo_handle_class (5, 60, 75000);\n%! arr = [obj1; obj2; obj3];  # 3x1 column vector\n%! result = arr.';\n%! assert (size (result), [1, 3]);\n%! assert (result(1).rate, obj1.rate);\n%! assert (result(2).rate, obj2.rate);\n%! assert (result(3).rate, obj3.rate);\n%! arr(1).rate = 6;  # stress test handle semantics\n%! assert (result(1).rate, obj1.rate);\n\n## 2-D array transpose, dims [2 2] -> [2 2]\n%!test\n%! obj1 = foo_value_class (4, 48, 50000);\n%! obj2 = foo_value_class (3, 36, 25000);\n%! obj3 = foo_value_class (5, 60, 75000);\n%! obj4 = foo_value_class (2, 24, 40000);\n%! arr = [obj1, obj2; obj3, obj4];  # 2x2 matrix\n%! result = transpose (arr);\n%! assert( size (result), [2, 2]);\n%! assert (result(1,1).rate, arr(1,1).rate);\n%! assert (result(1,2).rate, arr(2,1).rate);\n%! assert (result(2,1).rate, arr(1,2).rate);\n%! assert (result(2,2).rate, arr(2,2).rate);\n\n## previous test, but with handle classes\n%!test\n%! obj1 = foo_handle_class (4, 48, 50000);\n%! obj2 = foo_handle_class (3, 36, 25000);\n%! obj3 = foo_handle_class (5, 60, 75000);\n%! obj4 = foo_handle_class (2, 24, 40000);\n%! arr = [obj1, obj2; obj3, obj4];  # 2x2 matrix\n%! result = transpose (arr);\n%! assert( size (result), [2, 2]);\n%! assert (result(1,1).rate, arr(1,1).rate);\n%! assert (result(1,2).rate, arr(2,1).rate);\n%! assert (result(2,1).rate, arr(1,2).rate);\n%! assert (result(2,2).rate, arr(2,2).rate);\n%! arr(1,1).rate = 6;  # stress test handle semantics\n%! assert (result(1,1).rate, obj1.rate);\n\n## 2-D array transpose, dims [2 3] -> [3 2]\n%!test\n%! obj1 = foo_value_class (1, 12, 10000);\n%! obj2 = foo_value_class (2, 24, 20000);\n%! obj3 = foo_value_class (3, 36, 30000);\n%! obj4 = foo_value_class (4, 48, 40000);\n%! obj5 = foo_value_class (5, 60, 50000);\n%! obj6 = foo_value_class (6, 72, 60000);\n%! arr = [obj1, obj2, obj3; obj4, obj5, obj6];  # 2x3 matrix\n%! result = arr';\n%! assert (size (result), [3, 2]);\n%! assert (result(1,1).rate, arr(1,1).rate);\n%! assert (result(1,2).rate, arr(2,1).rate);\n%! assert (result(2,1).rate, arr(1,2).rate);\n%! assert (result(2,2).rate, arr(2,2).rate);\n%! assert (result(3,1).rate, arr(1,3).rate);\n%! assert (result(3,2).rate, arr(2,3).rate);\n\n## previous test, but with handle classes\n%!test\n%! obj1 = foo_handle_class (1, 12, 10000);\n%! obj2 = foo_handle_class (2, 24, 20000);\n%! obj3 = foo_handle_class (3, 36, 30000);\n%! obj4 = foo_handle_class (4, 48, 40000);\n%! obj5 = foo_handle_class (5, 60, 50000);\n%! obj6 = foo_handle_class (6, 72, 60000);\n%! arr = [obj1, obj2, obj3; obj4, obj5, obj6];  # 2x3 matrix\n%! result = arr';\n%! assert (size (result), [3, 2]);\n%! assert (result(1,1).rate, arr(1,1).rate);\n%! assert (result(1,2).rate, arr(2,1).rate);\n%! assert (result(2,1).rate, arr(1,2).rate);\n%! assert (result(2,2).rate, arr(2,2).rate);\n%! assert (result(3,1).rate, arr(1,3).rate);\n%! assert (result(3,2).rate, arr(2,3).rate);\n%! arr(1,1).rate = 6;  # stress test handle semantics\n%! assert (result(1,1).rate, obj1.rate);\n\n## ctranspose on arrays - should work same as transpose\n%!test\n%! obj1 = foo_value_class (4, 48, 50000);\n%! obj2 = foo_value_class (3, 36, 25000);\n%! arr = [obj1, obj2];\n%! result1 = transpose (arr);\n%! result2 = ctranspose (arr);\n%! assert (size (result1), size (result2));\n%! assert (result1(1).rate, result2(1).rate);\n%! assert (result1(2).rate, result2(2).rate);\n\n## previous test, but with handle classes\n%!test\n%! obj1 = foo_handle_class (4, 48, 50000);\n%! obj2 = foo_handle_class (3, 36, 25000);\n%! arr = [obj1, obj2];\n%! result1 = transpose (arr);\n%! result2 = ctranspose (arr);\n%! assert (size (result1), size (result2));\n%! assert (result1(1).rate, result2(1).rate);\n%! assert (result1(2).rate, result2(2).rate);\n\n## double transpose returns original\n%!test\n%! obj1 = foo_value_class (4, 48, 50000);\n%! obj2 = foo_value_class (3, 36, 25000);\n%! obj3 = foo_value_class (5, 60, 75000);\n%! obj4 = foo_value_class (2, 24, 40000);\n%! arr = [obj1, obj2; obj3, obj4];\n%! result = transpose (transpose (arr));\n%! assert (size (result), size (arr));\n%! assert ([result.rate], [arr.rate])\n\n## previous test, but with handle classes\n%!test\n%! obj1 = foo_handle_class (4, 48, 50000);\n%! obj2 = foo_handle_class (3, 36, 25000);\n%! obj3 = foo_handle_class (5, 60, 75000);\n%! obj4 = foo_handle_class (2, 24, 40000);\n%! arr = [obj1, obj2; obj3, obj4];\n%! result = transpose (transpose (arr));\n%! assert (size (result), size (arr));\n%! assert ([result.rate], [arr.rate])\n\n## test if transpose/ctranspose throws an error for classdef arrays of dim >2\n##\n## this test has four parts to it\n## *.1) (value classes) show that direct function call throws an error\n## *.2) (handle classes) show that direct function call throws an error\n## *.3) (value classes) show that operator usage throws an error\n## *.4) (handle classes) show that operator usage throws an error\n\n## 1.1) (value classes) show that direct function call \"transpose\" throws an error\n%!error <transpose not defined for N-D objects of value_class class>\n%! arr(1,1,3) = value_class ();\n%! result = transpose (arr);\n\n## 1.2) (handle classes) show that direct function call \"transpose\" throws an error\n%!error <transpose not defined for N-D objects of handle_class class>\n%! arr(1,1,3) = handle_class ();\n%! result = transpose (arr);\n\n## 1.3) (value classes) show that operator \"transpose\" usage throws an error\n%!error <transpose not defined for N-D objects of value_class class>\n%! arr(1,1,3) = value_class ();\n%! result = arr.';\n\n## 1.4) (handle classes) show that operator \"transpose\" usage throws an error\n%!error <transpose not defined for N-D objects of handle_class class>\n%! arr(1,1,3) = handle_class ();\n%! result = arr.';\n\n## 2.1) (value classes) show that direct function call \"ctranspose\" throws an error\n%!error <ctranspose not defined for N-D objects of value_class class>\n%! arr(1,1,3) = value_class ();\n%! result = ctranspose (arr);\n\n## 2.2) (handle classes) show that direct function call \"ctranspose\" throws an error\n%!error <ctranspose not defined for N-D objects of handle_class class>\n%! arr(1,1,3) = handle_class ();\n%! result = ctranspose (arr);\n\n## 2.3) (value classes) show that operator \"ctranspose\" usage throws an error\n%!error <ctranspose not defined for N-D objects of value_class class>\n%! arr(1,1,3) = value_class ();\n%! result = arr';\n\n## 2.4) (handle classes) show that operator \"ctranspose\" usage throws an error\n%!error <ctranspose not defined for N-D objects of handle_class class>\n%! arr(1,1,3) = handle_class ();\n%! result = arr';\n\n## test overloaded \"transpose\" method for value classes\n##\n## see \"overloaded_transpose_class.m\" for more specifics\n##\n## NOTE: \"overloaded_transpose_class\" does not overload \"ctranspose\"\n## likewise with the handle class version\n##\n## this test has three parts to it\n## 1.1) test direct call to \"transpose\", value classes\n%!test\n%! obj1 = overloaded_transpose_class ();\n%! obj2 = overloaded_transpose_class ();\n%! obj3 = overloaded_transpose_class ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = transpose (arr);\n%! assert (size (result), [1, 3]);  # unchanged\n%! assert (result(1,1).data, [1; 2; 3]);\n%! assert (result(1,2).data, [4; 5; 6]);\n%! assert (result(1,3).data, [7; 8; 9]);\n\n## 1.2) test direct call to \"transpose\", handle classes\n%!test\n%! obj1 = overloaded_transpose_class_handle ();\n%! obj2 = overloaded_transpose_class_handle ();\n%! obj3 = overloaded_transpose_class_handle ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = transpose (arr);\n%! assert (size (result), [1, 3]);  # unchanged\n%! assert (result(1,1).data, [1; 2; 3]);\n%! assert (result(1,2).data, [4; 5; 6]);\n%! assert (result(1,3).data, [7; 8; 9]);\n\n## 2.1) test that the .' operator calls the overloaded method, value classes\n%!test\n%! obj1 = overloaded_transpose_class ();\n%! obj2 = overloaded_transpose_class ();\n%! obj3 = overloaded_transpose_class ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = arr.';\n%! assert (size (result), [1, 3]);  # unchanged\n%! assert (result(1,1).data, [1; 2; 3]);\n%! assert (result(1,2).data, [4; 5; 6]);\n%! assert (result(1,3).data, [7; 8; 9]);\n\n## 2.2) test that the .' operator calls the overloaded method, handle classes\n%!test\n%! obj1 = overloaded_transpose_class_handle ();\n%! obj2 = overloaded_transpose_class_handle ();\n%! obj3 = overloaded_transpose_class_handle ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = arr.';\n%! assert (size (result), [1, 3]);  # unchanged\n%! assert (result(1,1).data, [1; 2; 3]);\n%! assert (result(1,2).data, [4; 5; 6]);\n%! assert (result(1,3).data, [7; 8; 9]);\n\n## 3.1) test that the ' operator does NOT call the overloaded method, value classes\n%!test\n%! obj1 = overloaded_transpose_class ();\n%! obj2 = overloaded_transpose_class ();\n%! obj3 = overloaded_transpose_class ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = arr';\n%! assert (size (result), [3, 1]);  # regular ctranspose\n%! assert (result(1,1).data, [1, 2, 3]);\n%! assert (result(2,1).data, [4, 5, 6]);\n%! assert (result(3,1).data, [7, 8, 9]);\n\n## 3.2) test that the ' operator does NOT call the overloaded method, handle classes\n%!test\n%! obj1 = overloaded_transpose_class_handle ();\n%! obj2 = overloaded_transpose_class_handle ();\n%! obj3 = overloaded_transpose_class_handle ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = arr';\n%! assert (size (result), [3, 1]);  # regular ctranspose\n%! assert (result(1,1).data, [1, 2, 3]);\n%! assert (result(2,1).data, [4, 5, 6]);\n%! assert (result(3,1).data, [7, 8, 9]);\n\n## test overloaded \"ctranspose\" method for value classes\n##\n## see \"overloaded_ctranspose_class.m\" for more specifics\n##\n## NOTE: \"overloaded_ctranspose_class\" does not overload \"transpose\"\n## likewise with the handle class version\n##\n## this test has three parts to it\n## 1.1) test direct call to \"ctranspose\", value classes\n%!test\n%! obj1 = overloaded_ctranspose_class ();\n%! obj2 = overloaded_ctranspose_class ();\n%! obj3 = overloaded_ctranspose_class ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = ctranspose (arr);\n%! assert (size (result), [1, 3]);  # unchanged\n%! assert (result(1,1).data, [1; 2; 3]);\n%! assert (result(1,2).data, [4; 5; 6]);\n%! assert (result(1,3).data, [7; 8; 9]);\n\n## 1.2) test direct call to \"ctranspose\", handle classes\n%!test\n%! obj1 = overloaded_ctranspose_class_handle ();\n%! obj2 = overloaded_ctranspose_class_handle ();\n%! obj3 = overloaded_ctranspose_class_handle ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = ctranspose (arr);\n%! assert (size (result), [1, 3]);  # unchanged\n%! assert (result(1,1).data, [1; 2; 3]);\n%! assert (result(1,2).data, [4; 5; 6]);\n%! assert (result(1,3).data, [7; 8; 9]);\n\n## 2.1) test that the .' operator calls the overloaded method, value classes\n%!test\n%! obj1 = overloaded_ctranspose_class ();\n%! obj2 = overloaded_ctranspose_class ();\n%! obj3 = overloaded_ctranspose_class ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = arr';\n%! assert (size (result), [1, 3]);  # unchanged\n%! assert (result(1,1).data, [1; 2; 3]);\n%! assert (result(1,2).data, [4; 5; 6]);\n%! assert (result(1,3).data, [7; 8; 9]);\n\n## 2.2) test that the .' operator calls the overloaded method, handle classes\n%!test\n%! obj1 = overloaded_ctranspose_class_handle ();\n%! obj2 = overloaded_ctranspose_class_handle ();\n%! obj3 = overloaded_ctranspose_class_handle ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = ctranspose (arr);\n%! assert (size (result), [1, 3]);  # unchanged\n%! assert (result(1,1).data, [1; 2; 3]);\n%! assert (result(1,2).data, [4; 5; 6]);\n%! assert (result(1,3).data, [7; 8; 9]);\n\n## 3.1) test that the .' operator does NOT call the overloaded method, value classes\n%!test\n%! obj1 = overloaded_ctranspose_class ();\n%! obj2 = overloaded_ctranspose_class ();\n%! obj3 = overloaded_ctranspose_class ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = arr.';\n%! assert (size (result), [3, 1]);  # regular transpose\n%! assert (result(1,1).data, [1, 2, 3]);\n%! assert (result(2,1).data, [4, 5, 6]);\n%! assert (result(3,1).data, [7, 8, 9]);\n\n## 3.2) test that the .' operator does NOT call the overloaded method, handle classes\n%!test\n%! obj1 = overloaded_ctranspose_class_handle ();\n%! obj2 = overloaded_ctranspose_class_handle ();\n%! obj3 = overloaded_ctranspose_class_handle ();\n%! obj1.data = [1, 2, 3];\n%! obj2.data = [4, 5, 6];\n%! obj3.data = [7, 8, 9];\n%! arr = [obj1, obj2, obj3];\n%! result = arr.';\n%! assert (size (result), [3, 1]);  # regular transpose\n%! assert (result(1,1).data, [1, 2, 3]);\n%! assert (result(2,1).data, [4, 5, 6]);\n%! assert (result(3,1).data, [7, 8, 9]);\n\n## make sure that default transpose doesn't call overridden permute\n##\n## Default transpose is essentially the same thing as \"permute(A, [2, 1])\".\n## We want to make sure that default transpose does not call to this overrided\n## permute function (which will essentially run \"permute(A, [1, 2])\").\n%!test\n%! obj1 = overloaded_permute_class ();\n%! obj2 = overloaded_permute_class ();\n%! obj3 = overloaded_permute_class ();\n%! arr = [obj1, obj2, obj3];\n%! result = arr.';\n%! assert (size (result), [3, 1]);  # regular transpose\n\n# same as previous test, but for handle classes\n%!test\n%! obj1 = overloaded_permute_class_handle ();\n%! obj2 = overloaded_permute_class_handle ();\n%! obj3 = overloaded_permute_class_handle ();\n%! arr = [obj1, obj2, obj3];\n%! result = arr.';\n%! assert (size (result), [3, 1]);  # regular transpose\n\n## same as last two tests, but testing \"ctranspose\"\n%!test\n%! obj1 = overloaded_permute_class ();\n%! obj2 = overloaded_permute_class ();\n%! obj3 = overloaded_permute_class ();\n%! arr = [obj1, obj2, obj3];\n%! result = arr';\n%! assert (size (result), [3, 1]);  # regular ctranspose\n\n## same as previous test, but for handle classes\n%!test\n%! obj1 = overloaded_permute_class_handle ();\n%! obj2 = overloaded_permute_class_handle ();\n%! obj3 = overloaded_permute_class_handle ();\n%! arr = [obj1, obj2, obj3];\n%! result = arr';\n%! assert (size (result), [3, 1]);  # regular ctranspose\n\n## Test classdef resize method\n\n## test resize method, scalar input and scalar output\n%!test\n%! obj = value_class ();\n%! obj.a = 1;\n%! result = resize (obj, 1);\n%! assert (size (result), [1, 1]);\n%! assert (obj.a, 1);\n%! result.a = 2;  # stress test value semantics\n%! assert (obj.a, 1);\n\n## previous test, but with handle classes\n%!test\n%! obj = handle_class ();\n%! obj.a = 1;\n%! result = resize (obj, 1);\n%! assert (size (result), [1, 1]);\n%! assert (obj.a, 1);\n%! result.a = 2;  # stress test handle semantics\n%! assert (obj.a, 2);\n\n## test resize method, scalar input with constructor that requires arguments\n##\n## Rationale: resizing an input array to be larger requires the classdef to\n## implement a default (no-argument) constructor.  We want to ensure that the\n## default constructor is not required when the output array is smaller or\n## equal in size to the input array.\n##\n%!test\n%! obj = class_pair_elem (1);\n%! result = resize (obj, 1);\n%! assert (size (result), [1, 1]);\n%! assert (obj.value, 1);\n%! result.value = 2;  # stress test value semantics\n%! assert (obj.value, 1);\n\n## previous test, but with handle classes\n%!test\n%! obj = class_pair_elem_handle (1);\n%! result = resize (obj, 1);\n%! assert (size (result), [1, 1]);\n%! assert (obj.value, 1);\n%! result.value = 2;  # stress test handle semantics\n%! assert (obj.value, 2);\n\n## test resize method to make empty 0x0 arrays\n%!test\n%! obj = value_class ();\n%! result = resize (obj, 0);\n%! assert (size (result), [0, 0]);\n%! assert (class (result), 'value_class');\n\n## previous test, but with handle classes\n%!test\n%! obj = handle_class ();\n%! result = resize (obj, 0);\n%! assert (size (result), [0, 0]);\n%! assert (class (result), 'handle_class');\n\n## test resize method to make empty 0x1 arrays\n%!test\n%! obj = value_class ();\n%! result = resize (obj, 0, 1);\n%! assert (size (result), [0, 1]);\n%! assert (class (result), 'value_class');\n\n## previous test, but with handle classes\n%!test\n%! obj = handle_class ();\n%! result = resize (obj, 0, 1);\n%! assert (size (result), [0, 1]);\n%! assert (class (result), 'handle_class');\n\n## test resize method to make empty 1x0 arrays\n%!test\n%! obj = value_class ();\n%! result = resize (obj, 1, 0);\n%! assert (size (result), [1, 0]);\n%! assert (class (result), 'value_class');\n\n## previous test, but with handle classes\n%!test\n%! obj = handle_class ();\n%! result = resize (obj, 1, 0);\n%! assert (size (result), [1, 0]);\n%! assert (class (result), 'handle_class');\n\n## test resize method, scalar input and array 1x3 output, default constructor\n%!test\n%! obj = value_class ();\n%! obj.a = 1;\n%! result = resize (obj, 1, 3);\n%! assert (size (result), [1, 3]);\n%! assert (result(1).a, 1);\n%! assert (result(2).a, []);\n%! assert (result(3).a, []);\n\n## previous test, but with handle classes\n%!test\n%! obj = handle_class ();\n%! obj.a = 1;\n%! result = resize (obj, 1, 3);\n%! assert (size (result), [1, 3]);\n%! assert (result(1).a, 1);\n%! assert (result(2).a, []);\n%! assert (result(3).a, []);\n%! result(2).a = 2;  # each entry should be a unique handle object\n%! assert (result(1).a, 1);\n%! assert (result(2).a, 2);\n%! assert (result(3).a, []);\n\n## test resize method, scalar input and array 3x1 output, default constructor\n%!test\n%! obj = value_class ();\n%! obj.a = 1;\n%! result = resize (obj, 3, 1);\n%! assert (size (result), [3, 1]);\n%! assert (result(1).a, 1);\n%! assert (result(2).a, []);\n%! assert (result(3).a, []);\n\n## previous test, but with handle classes\n%!test\n%! obj = handle_class ();\n%! obj.a = 1;\n%! result = resize (obj, 3, 1);\n%! assert (size (result), [3, 1]);\n%! assert (result(1).a, 1);\n%! assert (result(2).a, []);\n%! assert (result(3).a, []);\n%! result(2).a = 2;  # each entry should be a unique handle object\n%! assert (result(1).a, 1);\n%! assert (result(2).a, 2);\n%! assert (result(3).a, []);\n\n## test resize method, scalar input and array 3x3 output, default constructor\n%!test\n%! obj = value_class ();\n%! obj.a = 1;\n%! result = resize (obj, 3, 3);\n%! assert (size (result), [3, 3]);\n%! assert (result(1,1).a, 1);\n%! assert (result(2,2).a, []);\n%! assert (result(3,3).a, []);\n\n## previous test, but with handle classes\n%!test\n%! obj = handle_class ();\n%! obj.a = 1;\n%! result = resize (obj, 3, 3);\n%! assert (size (result), [3, 3]);\n%! assert (result(1,1).a, 1);\n%! assert (result(2,2).a, []);\n%! assert (result(3,3).a, []);\n%! result(2,2).a = 2;  # each entry should be a unique handle object\n%! assert (result(1,1).a, 1);\n%! assert (result(2,2).a, 2);\n%! assert (result(3,3).a, []);\n\n## test resize method, array 2x2 input and array 4x4 output, default constructor\n%!test\n%! arr = [ value_class(), value_class() ; value_class(), value_class() ];\n%! arr(1,1).a = 1;\n%! arr(1,2).a = 2;\n%! arr(2,1).a = 3;\n%! arr(2,2).a = 4;\n%! result = resize (arr, 4, 4);\n%! assert (size (result), [4, 4]);\n%! assert (result(1,1).a, 1);\n%! assert (result(1,2).a, 2);\n%! assert (result(2,1).a, 3);\n%! assert (result(2,2).a, 4);\n%! assert (result(3,3).a, []);\n%! assert (result(4,4).a, []);\n\n## previous test, but with handle classes\n%!test\n%! arr = [ handle_class(), handle_class() ; handle_class(), handle_class() ];\n%! arr(1,1).a = 1;\n%! arr(1,2).a = 2;\n%! arr(2,1).a = 3;\n%! arr(2,2).a = 4;\n%! result = resize (arr, 4, 4);\n%! assert (size (result), [4, 4]);\n%! assert (result(1,1).a, 1);\n%! assert (result(1,2).a, 2);\n%! assert (result(2,1).a, 3);\n%! assert (result(2,2).a, 4);\n%! assert (result(3,3).a, []);\n%! assert (result(4,4).a, []);\n%! result(3,3).a = 10;\n%! assert (result(1,1).a, 1);\n%! assert (result(1,2).a, 2);\n%! assert (result(2,1).a, 3);\n%! assert (result(2,2).a, 4);\n%! assert (result(3,3).a, 10);\n%! assert (result(4,4).a, []);\n\n## Additional test resize of classdef objects\n## Using built-in classdef (inputParser()).\n\n%!test\n%! ## Test resize of scalar classdef object to array\n%! obj = inputParser ();  # use classdef with implementation in core Octave\n%! obj.KeepUnmatched = true;\n%! arr = resize (obj, [2, 3]);\n%! assert (size (arr), [2, 3]);\n%! assert (arr(1,1).KeepUnmatched, true);\n%! ## New elements should be default-constructed\n%! assert (arr(1,2).KeepUnmatched, false);\n\n%!test\n%! ## Resize to empty\n%! obj = inputParser ();\n%! arr = resize (obj, [0, 5]);\n%! assert (size (arr), [0, 5]);\n%! assert (numel (arr), 0);\n\n%!test\n%! ## Resize scalar to scalar\n%! obj = inputParser ();\n%! obj.CaseSensitive = true;\n%! obj2 = resize (obj, [1, 1]);\n%! assert (size (obj2), [1, 1]);\n%! assert (obj2.CaseSensitive, true);\n\n%!test\n%! ## Resize to 3-D\n%! obj = inputParser ();\n%! arr = resize (obj, [2, 2, 2]);\n%! assert (size (arr), [2, 2, 2]);\n%! assert (numel (arr), 8);\n\n## test resize method, scalar input and array 1x3 output, no default constructor\n## FIXME: provide a proper error message when the default construction of a\n## classdef object fails.  Right now, the error message is something like\n## <'value' undefined near line 7, column 20>, but that is the actual failure\n## point in the .m file code and not the general gist of what went wrong.\n%!error\n%! obj = class_pair_elem (1);\n%! result = resize (obj, 1, 3);\n\n## test resize method, array 1x2 input and array 1x3 output, no default constructor\n%!error\n%! obj = [ class_pair_elem(1); class_pair_elem(2) ];\n%! result = resize (obj, 1, 3);\n\n## arr(i) = [] deletion syntax tests (bug #55983).\n\n## test arr(i) = [] deletion syntax on single index positions\n%!test <*55983>\n%! arr(5) = value_class ();\n%! arr(1).a = 1;\n%! arr(2).a = 2;\n%! arr(3).a = 3;\n%! arr(4).a = 4;\n%! arr(5).a = 5;\n%! arr(4) = [];\n%! assert (size (arr), [1, 4]);\n%! assert ([arr.a], [1, 2, 3, 5]);\n%! arr(1:2) = [];\n%! assert (size (arr), [1, 2]);\n%! assert ([arr.a], [3, 5]);\n\n## previous test, but with handle classes\n%!test <*55983>\n%! arr(5) = handle_class ();\n%! arr(1).a = 1;\n%! arr(2).a = 2;\n%! arr(3).a = 3;\n%! arr(4).a = 4;\n%! arr(5).a = 5;\n%! arr(4) = [];\n%! assert (size (arr), [1, 4]);\n%! assert ([arr.a], [1, 2, 3, 5]);\n%! arr(1:2) = [];\n%! assert (size (arr), [1, 2]);\n%! assert ([arr.a], [3, 5]);\n\n## test arr(i) = [] deletion syntax on multiple index positions\n%!test <*55983>\n%! arr(5,5) = value_class ();\n%! for i = 1:numel (arr)\n%!   arr(i).a = i;\n%! endfor\n%! arr(:,4) = [];\n%! assert (size (arr), [5, 4]);\n%! assert ([arr(:,1).a], [1, 2, 3, 4, 5]);\n%! assert ([arr(:,2).a], [6, 7, 8, 9, 10]);\n%! assert ([arr(:,3).a], [11, 12, 13, 14, 15]);\n%! assert ([arr(:,4).a], [21, 22, 23, 24, 25]);\n%! arr(3:4,:) = [];\n%! assert (size (arr), [3, 4]);\n%! assert ([arr(:,1).a], [1, 2, 5]);\n%! assert ([arr(:,2).a], [6, 7, 10]);\n%! assert ([arr(:,3).a], [11, 12, 15]);\n%! assert ([arr(:,4).a], [21, 22, 25]);\n\n## previous test, but with handle classes\n%!test <*55983>\n%! arr(5,5) = handle_class ();\n%! for i = 1:numel (arr)\n%!   arr(i).a = i;\n%! endfor\n%! arr(:,4) = [];\n%! assert (size (arr), [5, 4]);\n%! assert ([arr(:,1).a], [1, 2, 3, 4, 5]);\n%! assert ([arr(:,2).a], [6, 7, 8, 9, 10]);\n%! assert ([arr(:,3).a], [11, 12, 13, 14, 15]);\n%! assert ([arr(:,4).a], [21, 22, 23, 24, 25]);\n%! arr(3:4,:) = [];\n%! assert (size (arr), [3, 4]);\n%! assert ([arr(:,1).a], [1, 2, 5]);\n%! assert ([arr(:,2).a], [6, 7, 10]);\n%! assert ([arr(:,3).a], [11, 12, 15]);\n%! assert ([arr(:,4).a], [21, 22, 25]);\n\n## test arr(i) = [] fails if more than one non-colon index is supplied\n%!error <a null assignment can only have one non-colon index>\n%! arr(2,2) = value_class ();\n%! arr(2,2) = [];\n\n## previous test, but for handle classes\n%!error <a null assignment can only have one non-colon index>\n%! arr(2,2) = value_class ();\n%! arr(2,2) = [];\n\n## test that array deletion syntax on entire array returns a 0x0 object,\n## value classes\n%!test <*55983>\n%! arr(2) = value_class ();\n%! arr(:) = [];\n%! assert (size (arr), [0, 0]);\n%! assert (class (arr), 'value_class');\n\n## previous test, but with handle classes\n%!test <*55983>\n%! arr(2) = handle_class ();\n%! arr(:) = [];\n%! assert (size (arr), [0, 0]);\n%! assert (class (arr), 'handle_class');\n\n## test that array deletion syntax on row vector returns a 1x0 object,\n## value classes\n%!test <*55983>\n%! arr(2) = value_class ();\n%! arr(2) = [];\n%! arr(1) = [];\n%! assert (size (arr), [1, 0]);\n%! assert (class (arr), 'value_class');\n\n## previous test, but with handle classes\n%!test <*55983>\n%! arr(2) = handle_class ();\n%! arr(2) = [];\n%! arr(1) = [];\n%! assert (size (arr), [1, 0]);\n%! assert (class (arr), 'handle_class');\n\n## test that array deletion syntax on column vector returns a 0x1 object,\n## value classes\n%!test <*55983>\n%! arr(2,1) = value_class ();\n%! arr(2,:) = [];\n%! arr(1,:) = [];\n%! assert (size (arr), [0, 1]);\n%! assert (class (arr), 'value_class');\n\n## previous test, but with handle classes\n%!test <*55983>\n%! arr(2,1) = handle_class ();\n%! arr(2,:) = [];\n%! arr(1,:) = [];\n%! assert (size (arr), [0, 1]);\n%! assert (class (arr), 'handle_class');\n\n## \"all\" and \"any\" tests\n\n## error on calling \"all\" on a classdef with no overloaded \"all\" method\n%!error <wrong type argument 'object'>\n%! obj = value_class ();\n%! all (obj);\n\n## previous test, but with handle classes\n%!error <wrong type argument 'object'>\n%! obj = handle_class ();\n%! all (obj);\n\n## error on calling \"all\" on a classdef ARRAY with no overloaded \"all\" method\n%!error <wrong type argument 'object'>\n%! obj(1, 2) = value_class ();\n%! all (obj);\n\n## previous test, but with handle classes\n%!error <wrong type argument 'object'>\n%! obj(1, 2) = handle_class ();\n%! all (obj);\n\n## call \"all\" method when present inside a classdef\n%!test\n%! obj = overloaded_all_class ();\n%! assert (all (obj), -1);\n\n## previous test, but with handle classes\n%!test\n%! obj = overloaded_all_class_handle ();\n%! assert (all (obj), -1);\n\n## error on calling \"any\" on a classdef with no overloaded \"any\" method\n%!error <wrong type argument 'object'>\n%! obj = value_class ();\n%! any (obj);\n\n## previous test, but with handle classes\n%!error <wrong type argument 'object'>\n%! obj = handle_class ();\n%! any (obj);\n\n## error on calling \"any\" on a classdef ARRAY with no overloaded \"any\" method\n%!error <wrong type argument 'object'>\n%! obj(1, 2) = value_class ();\n%! any (obj);\n\n## previous test, but with handle classes\n%!error <wrong type argument 'object'>\n%! obj(1, 2) = handle_class ();\n%! any (obj);\n\n## call \"any\" method when present inside a classdef\n%!test\n%! obj = overloaded_any_class ();\n%! assert (any (obj), -1);\n\n## previous test, but with handle classes\n%!test\n%! obj = overloaded_any_class_handle ();\n%! assert (any (obj), -1);\n\n## save classdef object with overloaded subsref in struct\n%!test <67894>\n%! file_format = {'-binary', '-float-binary', '-text', '-v6'};\n%! for i_format = 1:numel (file_format)\n%!   S.obj = overloaded_subsref ();\n%!   S.obj.a = 1;\n%!   savefile = tempname ();\n%!   unwind_protect\n%!     save (file_format{i_format}, savefile, 'S');\n%!     clear S;\n%!     load (savefile);\n%!     assert (S.obj.a, 1);\n%!   unwind_protect_cleanup\n%!     delete ([savefile, '*']);\n%!   end_unwind_protect\n%! endfor\n\n%!testif HAVE_HDF5 <67894>\n%! file_format = {'-hdf5', '-float-hdf5'};\n%! for i_format = 1:numel (file_format)\n%!   S.obj = overloaded_subsref ();\n%!   S.obj.a = 1;\n%!   savefile = tempname ();\n%!   unwind_protect\n%!     save (file_format{i_format}, savefile, 'S');\n%!     clear S;\n%!     load (savefile);\n%!     assert (S.obj.a, 1);\n%!   unwind_protect_cleanup\n%!     delete ([savefile, '*']);\n%!   end_unwind_protect\n%! endfor\n\n%!testif HAVE_ZLIB <67894>\n%! file_format = {'-v7'};\n%! for i_format = 1:numel (file_format)\n%!   S.obj = overloaded_subsref ();\n%!   S.obj.a = 1;\n%!   savefile = tempname ();\n%!   unwind_protect\n%!     save (file_format{i_format}, savefile, 'S');\n%!     clear S;\n%!     load (savefile);\n%!     assert (S.obj.a, 1);\n%!   unwind_protect_cleanup\n%!     delete ([savefile, '*']);\n%!   end_unwind_protect\n%! endfor\n\n## save classdef object with overloaded subsref in cell\n%!test <67894>\n%! file_format = {'-binary', '-float-binary', '-text', '-v6'};\n%! for i_format = 1:numel (file_format)\n%!   C{1} = overloaded_subsref ();\n%!   C{1}.a = 1;\n%!   savefile = tempname ();\n%!   unwind_protect\n%!     save (file_format{i_format}, savefile, 'C');\n%!     clear C;\n%!     load (savefile);\n%!     assert (C{1}.a, 1);\n%!   unwind_protect_cleanup\n%!     delete ([savefile, '*']);\n%!   end_unwind_protect\n%! endfor\n\n%!testif HAVE_HDF5 <67894>\n%! file_format = {'-hdf5', '-float-hdf5'};\n%! for i_format = 1:numel (file_format)\n%!   C{1} = overloaded_subsref ();\n%!   C{1}.a = 1;\n%!   savefile = tempname ();\n%!   unwind_protect\n%!     save (file_format{i_format}, savefile, 'C');\n%!     clear C;\n%!     load (savefile);\n%!     assert (C{1}.a, 1);\n%!   unwind_protect_cleanup\n%!     delete ([savefile, '*']);\n%!   end_unwind_protect\n%! endfor\n\n%!testif HAVE_ZLIB <67894>\n%! file_format = {'-v7'};\n%! for i_format = 1:numel (file_format)\n%!   C{1} = overloaded_subsref ();\n%!   C{1}.a = 1;\n%!   savefile = tempname ();\n%!   unwind_protect\n%!     save (file_format{i_format}, savefile, 'C');\n%!     clear C;\n%!     load (savefile);\n%!     assert (C{1}.a, 1);\n%!   unwind_protect_cleanup\n%!     delete ([savefile, '*']);\n%!   end_unwind_protect\n%! endfor\n\n%!test <*59775>\n%! m = class_bug59775A ([1, 2, 3]);\n%! assert ([m.A], [1, 1, 1]);\n\n%!test <*59775>\n%! m = class_bug59775B ([1, 2, 3]);\n%! assert ([m.A], [1, 2, 3]);\n\n%!test <*59775>\n%! m = class_bug59775B ([1, 3, 5; 2, 4, 6]);\n%! assert ([m.A], [1, 2, 3, 4, 5, 6]);\n"
  },
  {
    "path": "test/classdef/foo_handle_class.m",
    "content": "classdef foo_handle_class < handle\n  properties\n    rate;\n    term;\n    principle;\n  end\n  methods\n    function obj = foo_handle_class (r, t, p)\n      if (nargin == 3)\n        obj.rate = r;\n        obj.term = t;\n        obj.principle = p;\n      elseif (nargin ~= 0)\n        error ('foo_handle_class:SyntaxError', ...\n               'foo_handle_class: Invalid syntax');\n      end\n    end\n    function amt = amount (obj)\n      i = obj.rate / (12 * 100);\n      if (i == 0 && obj.term == 0)\n        amt = obj.principle;\n      else\n        amt = (obj.principle * i) / (1 - (1 + i)^(-obj.term));\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/foo_method_changes_property_size.m",
    "content": "classdef foo_method_changes_property_size\n  properties\n    element;\n  end\n  methods\n    function obj = foo_method_changes_property_size (n)\n      obj.element = 1:n;\n    end\n    function obj = move_element_to_end (obj, n)\n      obj.element(end+1) = obj.element(n);\n      obj.element(n) = [];\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/foo_static_method_constant_property.m",
    "content": "classdef foo_static_method_constant_property\n  properties\n    frequency;\n  end\n  properties (Constant = true)\n    pie = pi;\n  end\n  methods\n    function obj = foo_static_method_constant_property (f)\n      if (nargin == 1)\n        obj.frequency = f;\n      elseif (nargin ~= 0)\n        error ('foo_static_method_constant_property:SyntaxError', ...\n               'foo_static_method_constant_property: Invalid syntax')\n      end\n    end\n    function res = cosine (obj, t)\n      res = cos (obj.radians_per_cycle () * obj.frequency * t);\n    end\n    function res = sine (obj, t)\n      res = sin (obj.radians_per_cycle () * obj.frequency * t);\n    end\n  end\n  methods (Static)\n    function res = radians_per_cycle ()\n      res = 2 * foo_static_method_constant_property.pie;\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/foo_subsref_subsasgn.m",
    "content": "classdef foo_subsref_subsasgn < handle\n  properties\n    x\n  end\n\n  methods\n    function obj = foo_subsref_subsasgn (dims)\n      switch (dims)\n        case 1\n          obj.x = 1:4;\n        case 2\n          obj.x = eye (4);\n        otherwise\n          error ('foo_subsref_subsasgn:SyntaxError', ...\n            'foo_subsref_subsasgn: Invalid syntax');\n      end\n    end\n\n    function ind = end (obj, k, n)\n      sz = size (obj.x);\n      if (k < n)\n        ind = sz(k);\n      else\n        ind = prod (sz(k:end));\n      end\n    end\n\n    function varargout = subsref (obj, S)\n      switch (length (S))\n        case 1\n          if (S(1).type == \"()\")\n            varargout = {obj.x(S(1).subs{1})};\n          elseif (S(1).type == \"{}\")\n            %% Note in ML R2018b \"x{1:3}\" expects \"nargout == 3\".\n            varargout = num2cell (obj.x(S(1).subs{1}));\n          elseif (S(1).type == \".\" && S(1).subs == 'x')\n            varargout = {obj.x};\n          else\n            error ('foo_subsref_subsasgn:SyntaxError', ...\n              'foo_subsref_subsasgn: Invalid syntax');\n          end\n        case 2\n          %% Note in ML R2018b \"x(1)(1)\" is not allowed.\n          if (S(1).type == \"{}\" && (S(2).type == \"{}\" || S(2).type == \"()\"))\n            varargout = {obj.x(S(1).subs{1}, S(2).subs{1})};\n          elseif (S(1).type == \".\" && S(1).subs == 'x' ...\n              && (S(2).type == \"{}\" || S(2).type == \"()\"))\n            varargout = {obj.x(S(2).subs{1})};\n          else\n            error ('foo_subsref_subsasgn:SyntaxError', ...\n              'foo_subsref_subsasgn: Invalid syntax');\n          end\n        otherwise\n          error ('foo_subsref_subsasgn:SyntaxError', ...\n            'foo_subsref_subsasgn: Invalid syntax');\n      end\n    end\n\n    function obj = subsasgn (obj, S, varargin)\n      switch (length (S))\n        case 1\n          if (S(1).type == \"{}\" || S(1).type == \"()\")\n            obj.x(S(1).subs{1}) = varargin{1};\n          elseif (S(1).type == \".\" && S(1).subs == 'x')\n            obj.x = varargin{1};\n          else\n            error ('foo_subsref_subsasgn:SyntaxError', ...\n              'foo_subsref_subsasgn: Invalid syntax');\n          end\n        case 2\n          %% Note in ML R2018b \"x(1)(1)\" is not allowed.\n          if (S(1).type == \"{}\" && (S(2).type == \"{}\" || S(2).type == \"()\"))\n            obj.x(S(1).subs{1}, S(2).subs{1}) = varargin{1};\n          elseif (S(1).type == \".\" && S(1).subs == 'x' ...\n              && (S(2).type == \"{}\" || S(2).type == \"()\"))\n            obj.x(S(2).subs{1}) = varargin{1};\n          else\n            error ('foo_subsref_subsasgn:SyntaxError', ...\n              'foo_subsref_subsasgn: Invalid syntax');\n          end\n        otherwise\n          error ('foo_subsref_subsasgn:SyntaxError', ...\n            'foo_subsref_subsasgn: Invalid syntax');\n      end\n    end\n\n  end\nend\n"
  },
  {
    "path": "test/classdef/foo_value_class.m",
    "content": "classdef foo_value_class\n  properties\n    rate;\n    term;\n    principle;\n  end\n  methods\n    function obj = foo_value_class (r, t, p)\n      if (nargin == 3)\n        obj.rate = r;\n        obj.term = t;\n        obj.principle = p;\n      elseif (nargin ~= 0)\n        error ('foo_value_class:SyntaxError', ...\n               'foo_value_class: Invalid syntax')\n      end\n    end\n    function amt = amount (obj)\n      i = obj.rate / (12 * 100);\n      if (i == 0 && obj.term == 0)\n        amt = obj.principle;\n      else\n        amt = (obj.principle * i) / (1 - (1 + i)^(-obj.term));\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/handle_class.m",
    "content": "classdef handle_class < handle\n  properties\n    a\n    b\n    c\n    d\n    e\n  endproperties\nendclassdef\n"
  },
  {
    "path": "test/classdef/module.mk",
    "content": "classdef_TEST_FILES = \\\n  %reldir%/@class_bug62802/amethod.m \\\n  %reldir%/@class_bug62802/class_bug62802.m \\\n  %reldir%/@class_bug67362/class_bug67362.m \\\n  %reldir%/@class_bug67362/shared_name.m \\\n  %reldir%/@osc/osc.m \\\n  %reldir%/bug_60763.m \\\n  %reldir%/cdef_array_break_cycles.m \\\n  %reldir%/class_bug50011_1.m \\\n  %reldir%/class_bug50011_1A.m \\\n  %reldir%/class_bug50011_1B.m \\\n  %reldir%/class_bug50011_2.m \\\n  %reldir%/class_bug50011_2A.m \\\n  %reldir%/class_bug50011_2B.m \\\n  %reldir%/class_bug52614A.m \\\n  %reldir%/class_bug52614B.m \\\n  %reldir%/class_bug55766.m \\\n  %reldir%/class_bug59775A.m \\\n  %reldir%/class_bug59775B.m \\\n  %reldir%/class_bug60723A.m \\\n  %reldir%/class_bug60723B.m \\\n  %reldir%/class_bug60723C.m \\\n  %reldir%/class_bug67845A.m \\\n  %reldir%/class_bug67845A_handle.m \\\n  %reldir%/class_bug67845B.m \\\n  %reldir%/class_bug67845B_handle.m \\\n  %reldir%/class_bug67845C.m \\\n  %reldir%/class_bug67845C_handle.m \\\n  %reldir%/class_bug66930A.m \\\n  %reldir%/class_bug66930B.m \\\n  %reldir%/class_pair.m \\\n  %reldir%/class_pair_elem.m \\\n  %reldir%/class_pair_elem_dominant.m \\\n  %reldir%/class_pair_elem_dominant_handle.m \\\n  %reldir%/class_pair_elem_handle.m \\\n  %reldir%/class_pair_handle.m \\\n  %reldir%/classdef.tst \\\n  %reldir%/foo_method_changes_property_size.m \\\n  %reldir%/foo_static_method_constant_property.m \\\n  %reldir%/foo_subsref_subsasgn.m \\\n  %reldir%/foo_value_class.m \\\n  %reldir%/foo_handle_class.m \\\n  %reldir%/handle_class.m \\\n  %reldir%/overloaded_all_class.m \\\n  %reldir%/overloaded_all_class_handle.m \\\n  %reldir%/overloaded_any_class.m \\\n  %reldir%/overloaded_any_class_handle.m \\\n  %reldir%/overloaded_cat_class.m \\\n  %reldir%/overloaded_cat_class_handle.m \\\n  %reldir%/overloaded_ctranspose_class.m \\\n  %reldir%/overloaded_ctranspose_class_handle.m \\\n  %reldir%/overloaded_horzcat_vertcat_class.m \\\n  %reldir%/overloaded_horzcat_vertcat_class_handle.m \\\n  %reldir%/overloaded_permute_class.m \\\n  %reldir%/overloaded_permute_class_handle.m \\\n  %reldir%/overloaded_subsref.m \\\n  %reldir%/overloaded_sizeof_class.m \\\n  %reldir%/overloaded_transpose_class.m \\\n  %reldir%/overloaded_transpose_class_handle.m \\\n  %reldir%/plist_t1.m \\\n  %reldir%/plist_t2.m \\\n  %reldir%/plist_t3.m \\\n  %reldir%/struct_wrapper.m \\\n  %reldir%/value_class.m \\\n  %reldir%/value_class_subclass.m \\\n  %reldir%/value_class_reshape.m\n\nTEST_FILES += $(classdef_TEST_FILES)\n"
  },
  {
    "path": "test/classdef/overloaded_all_class.m",
    "content": "classdef overloaded_all_class\n  methods\n    function tf = all (obj, varargin)\n      tf = -1;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/overloaded_all_class_handle.m",
    "content": "classdef overloaded_all_class_handle < handle\n  methods\n    function tf = all (obj, varargin)\n      tf = -1;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/overloaded_any_class.m",
    "content": "classdef overloaded_any_class\n  methods\n    function tf = any (obj, varargin)\n      tf = -1;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/overloaded_any_class_handle.m",
    "content": "classdef overloaded_any_class_handle < handle\n  methods\n    function tf = any (obj, varargin)\n      tf = -1;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/overloaded_cat_class.m",
    "content": "classdef overloaded_cat_class\n  properties\n    data\n  endproperties\n\n  methods\n\n    ## Overload of the cat function\n    ## Concatenates the underlying \"data\" property of each object (of type\n    ## 'overloaded_cat_class), but always outputs a single object of the\n    ## same type.\n    ##\n    ## NOTE: Concatenating objects using the square bracket syntax will NOT\n    ## call \"cat\", it will call combinations of \"horzcat\" and \"vertcat\"\n    ##\n    ## E.g.\n    ##\n    ## >> o1 = overloaded_cat_class;\n    ## >> o1.data = 1;\n    ## >> o2 = overloaded_cat_class;\n    ## >> o2.data = 2;\n    ## >> arr = cat (2, o1, o2);\n    ##\n    ## arr =\n    ##\n    ##   overloaded_cat_class object with properties:\n    ##\n    ##       data: [1, 2]\n    ##\n    ## >> size (arr)\n    ##\n    ## ans =\n    ##\n    ##    1   1\n    ##\n    function retval = cat (varargin)\n      n = numel (varargin);\n\n      if (n < 2)\n        error (\"overloaded_cat_class.cat: must be called with at least two arguments\");\n      endif\n\n      dim = varargin{1};\n\n      if (! isnumeric (dim) || ! isscalar (dim) || ! (floor (dim) == dim))\n        error (\"overloaded_cat_class.cat: DIM must be an integer\");\n      endif\n\n      dominant_obj = varargin{2};\n\n      new_data = [];\n\n      for i = 2:n\n        if (! strcmp (class (varargin{i}), 'overloaded_cat_class'))\n          error ('overloaded_cat_class.cat: inputs must be of the same time');\n        endif\n        new_data = cat (dim, new_data, varargin{i}.data);\n      endfor\n\n      retval = dominant_obj;\n      retval.data = new_data;\n    endfunction\n\n    function retval = horzcat (varargin)\n      retval = cat (2, varargin{:});\n    endfunction\n\n    function retval = vertcat (varargin)\n      retval = cat (1, varargin{:});\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef/overloaded_cat_class_handle.m",
    "content": "classdef overloaded_cat_class_handle < handle\n  properties\n    data\n  endproperties\n\n  methods\n\n    ## Overload of the cat function\n    ## Concatenates the underlying \"data\" property of each object (of type\n    ## 'overloaded_cat_class_handle), but always outputs a single object of the\n    ## same type.\n    ##\n    ## NOTE: Concatenating objects using the square bracket syntax will NOT\n    ## call \"cat\", it will call combinations of \"horzcat\" and \"vertcat\"\n    ##\n    ## E.g.\n    ##\n    ## >> o1 = overloaded_cat_class_handle;\n    ## >> o1.data = 1;\n    ## >> o2 = overloaded_cat_class_handle;\n    ## >> o2.data = 2;\n    ## >> arr = cat (2, o1, o2);\n    ##\n    ## arr =\n    ##\n    ##   overloaded_cat_class_handle object with properties:\n    ##\n    ##       data: [1, 2]\n    ##\n    ## >> size (arr)\n    ##\n    ## ans =\n    ##\n    ##    1   1\n    ##\n    function retval = cat (varargin)\n      n = numel (varargin);\n\n      if (n < 2)\n        error (\"overloaded_cat_class_handle.cat: must be called with at least two arguments\");\n      endif\n\n      dim = varargin{1};\n\n      if (! isnumeric (dim) || ! isscalar (dim) || ! (floor (dim) == dim))\n        error (\"overloaded_cat_class_handle.cat: DIM must be an integer\");\n      endif\n\n      dominant_obj = varargin{2};\n\n      new_data = [];\n\n      for i = 2:n\n        if (! strcmp (class (varargin{i}), 'overloaded_cat_class_handle'))\n          error ('overloaded_cat_class_handle.cat: inputs must be of the same time');\n        endif\n        new_data = cat (dim, new_data, varargin{i}.data);\n      endfor\n\n      retval = dominant_obj;\n      retval.data = new_data;\n    endfunction\n\n    function retval = horzcat (varargin)\n      retval = cat (2, varargin{:});\n    endfunction\n\n    function retval = vertcat (varargin)\n      retval = cat (1, varargin{:});\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef/overloaded_ctranspose_class.m",
    "content": "classdef overloaded_ctranspose_class\n  properties\n    data\n  end\n\n  methods\n    function B = ctranspose (A)\n      n = numel (A);\n\n      for i = 1:n\n        A(i).data = A(i).data.';\n      end\n\n      B = A;\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/overloaded_ctranspose_class_handle.m",
    "content": "classdef overloaded_ctranspose_class_handle < handle\n  properties\n    data\n  end\n\n  methods\n    function B = ctranspose (A)\n      n = numel (A);\n\n      for i = 1:n\n        A(i).data = A(i).data.';\n      end\n\n      B = A;\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/overloaded_horzcat_vertcat_class.m",
    "content": "classdef overloaded_horzcat_vertcat_class\n  properties\n    data\n  endproperties\n\n  methods\n\n    ## Overload of the \"horzcat\" and \"vertcat\" functions, but not \"cat\"\n    ##\n    ## See overloaded_cat_class.m for details on how the concatenation works.\n    ## The implementation of \"fakecat\" is the exact same as the real \"cat\"\n    ## function in overloaded_cat_class.\n    ##\n    ## The idea behind overloading only horzcat and vertcat is that 2-D object\n    ## concatenation can be overloaded using the bracket syntax like so:\n    ##\n    ## >> o1 = overloaded_horzcat_vertcat_class;\n    ## >> o1.data = 1;\n    ## >> o2 = overloaded_horzcat_vertcat_class;\n    ## >> o2.data = 2;\n    ## >> [o1, o2]\n    ## ans =\n    ##\n    ##   overloaded_horzcat_vertcat_class object with properties:\n    ##\n    ##       data: [1, 2]\n    ##\n    ## >> [o1; o2]\n    ## ans =\n    ##\n    ##   overloaded_horzcat_vertcat_class object with properties:\n    ##\n    ##       data: [1; 2]\n    ##\n    ## ... but 3-D object concatenation or directly using the \"cat\" function\n    ## will not be overloaded.\n    ##\n    ## >> arr = cat(3, o1, o2);\n    ## arr =\n    ##\n    ##   overloaded_horzcat_vertcat_class object array with properties:\n    ##\n    ##       data\n    ##\n    ## >> size(arr)\n    ## ans =\n    ##    1   1   2\n    ##\n    function retval = fakecat (varargin)\n      n = numel (varargin);\n\n      if (n < 2)\n        error (\"overloaded_horzcat_vertcat_class.cat: must be called with at least two arguments\");\n      endif\n\n      dim = varargin{1};\n\n      if (! isnumeric (dim) || ! isscalar (dim) || ! (floor (dim) == dim))\n        error (\"overloaded_horzcat_vertcat_class.cat: DIM must be an integer\");\n      endif\n\n      dominant_obj = varargin{2};\n\n      new_data = [];\n\n      for i = 2:n\n        if (! strcmp (class (varargin{i}), 'overloaded_horzcat_vertcat_class'))\n          error ('overloaded_horzcat_vertcat_class.cat: inputs must be of the same time');\n        endif\n        new_data = cat (dim, new_data, varargin{i}.data);\n      endfor\n\n      retval = dominant_obj;\n      retval.data = new_data;\n    endfunction\n\n    function retval = horzcat (varargin)\n      retval = fakecat (2, varargin{:});\n    endfunction\n\n    function retval = vertcat (varargin)\n      retval = fakecat (1, varargin{:});\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef/overloaded_horzcat_vertcat_class_handle.m",
    "content": "classdef overloaded_horzcat_vertcat_class_handle < handle\n  properties\n    data\n  endproperties\n\n  methods\n\n    ## Overload of the \"horzcat\" and \"vertcat\" functions, but not \"cat\"\n    ##\n    ## See overloaded_cat_class.m for details on how the concatenation works.\n    ## The implementation of \"fakecat\" is the exact same as the real \"cat\"\n    ## function in overloaded_cat_class.\n    ##\n    ## The idea behind overloading only horzcat and vertcat is that 2-D object\n    ## concatenation can be overloaded using the bracket syntax like so:\n    ##\n    ## >> o1 = overloaded_horzcat_vertcat_class;\n    ## >> o1.data = 1;\n    ## >> o2 = overloaded_horzcat_vertcat_class;\n    ## >> o2.data = 2;\n    ## >> [o1, o2]\n    ## ans =\n    ##\n    ##   overloaded_horzcat_vertcat_class object with properties:\n    ##\n    ##       data: [1, 2]\n    ##\n    ## >> [o1; o2]\n    ## ans =\n    ##\n    ##   overloaded_horzcat_vertcat_class object with properties:\n    ##\n    ##       data: [1; 2]\n    ##\n    ## ... but 3-D object concatenation or directly using the \"cat\" function\n    ## will not be overloaded.\n    ##\n    ## >> arr = cat(3, o1, o2);\n    ## arr =\n    ##\n    ##   overloaded_horzcat_vertcat_class object array with properties:\n    ##\n    ##       data\n    ##\n    ## >> size(arr)\n    ## ans =\n    ##    1   1   2\n    ##\n    function retval = fakecat (varargin)\n      n = numel (varargin);\n\n      if (n < 2)\n        error (\"overloaded_horzcat_vertcat_class_handle.cat: must be called with at least two arguments\");\n      endif\n\n      dim = varargin{1};\n\n      if (! isnumeric (dim) || ! isscalar (dim) || ! (floor (dim) == dim))\n        error (\"overloaded_horzcat_vertcat_class_handle.cat: DIM must be an integer\");\n      endif\n\n      dominant_obj = varargin{2};\n\n      new_data = [];\n\n      for i = 2:n\n        if (! strcmp (class (varargin{i}), 'overloaded_horzcat_vertcat_class_handle'))\n          error ('overloaded_horzcat_vertcat_class_handle.cat: inputs must be of the same time');\n        endif\n        new_data = cat (dim, new_data, varargin{i}.data);\n      endfor\n\n      retval = dominant_obj;\n      retval.data = new_data;\n    endfunction\n\n    function retval = horzcat (varargin)\n      retval = fakecat (2, varargin{:});\n    endfunction\n\n    function retval = vertcat (varargin)\n      retval = fakecat (1, varargin{:});\n    endfunction\n\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef/overloaded_permute_class.m",
    "content": "classdef overloaded_permute_class\n  properties\n    data\n  end\n\n  % Overload of the \"permute\" method\n  %\n  % The overloaded permute method first does a circshift on the dimorder\n  % argument, so\n  %\n  % >> permute(A, [1, 2, 3, 4])\n  %\n  % what is ultimately called is \"permute(A, [4, 1, 2, 3])\"\n\n  methods\n    function B = permute (A, dimorder)\n      if (numel (A) == 1)\n        B = A;\n        return;\n      end\n\n      % Do a right circshift on dimorder\n      dimorder = circshift (dimorder, 1);\n\n      B = builtin ('permute', A, dimorder);\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/overloaded_permute_class_handle.m",
    "content": "classdef overloaded_permute_class_handle < handle\n  properties\n    data\n  end\n\n  % Overload of the \"permute\" method\n  %\n  % The overloaded permute method first does a circshift on the dimorder\n  % argument, so\n  %\n  % >> permute(A, [1, 2, 3, 4])\n  %\n  % what is ultimately called is \"permute(A, [4, 1, 2, 3])\"\n\n  methods\n    function B = permute (A, dimorder)\n      if (numel (A) == 1)\n        B = A;\n        return;\n      end\n\n      % Do a right circshift on dimorder\n      dimorder = circshift (dimorder, 1);\n\n      B = builtin ('permute', A, dimorder);\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/overloaded_sizeof_class.m",
    "content": "classdef overloaded_sizeof_class\n  properties\n    a\n  endproperties\n\n  methods\n    function retval = sizeof (obj)\n      retval = -5;  # Impossible for sizeof to return a negative normally\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/overloaded_subsref.m",
    "content": "classdef overloaded_subsref\n\n  properties\n    a\n  end\n\n  methods\n    function B = subsref (A, s)\n      if (strcmp (s(1).type, '()') && numel (s(1).subs) == 1 && s(1).subs{1} == 1)\n        error ('unsupported syntax');\n      else\n        B = builtin ('subsref', A, s);\n      end\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classdef/overloaded_transpose_class.m",
    "content": "classdef overloaded_transpose_class\n  properties\n    data\n  end\n\n  methods\n    function B = transpose (A)\n      n = numel (A);\n\n      for i = 1:n\n        A(i).data = A(i).data.';\n      end\n\n      B = A;\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/overloaded_transpose_class_handle.m",
    "content": "classdef overloaded_transpose_class_handle < handle\n  properties\n    data\n  end\n\n  methods\n    function B = transpose (A)\n      n = numel (A);\n\n      for i = 1:n\n        A(i).data = A(i).data.';\n      end\n\n      B = A;\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/plist_t1.m",
    "content": "classdef plist_t1\n  properties\n    a = 1 b\n  end\nend\n"
  },
  {
    "path": "test/classdef/plist_t2.m",
    "content": "classdef plist_t2\n  properties\n    a = 1; b\n  end\nend\n"
  },
  {
    "path": "test/classdef/plist_t3.m",
    "content": "classdef plist_t3\n  properties\n    a = 1\n    b\n  end\nend\n"
  },
  {
    "path": "test/classdef/struct_wrapper.m",
    "content": "classdef struct_wrapper\n  properties\n    s;\n  end\n  methods\n    function o = struct_wrapper ()\n      if (nargin == 0)\n        o.s = struct ();\n      else\n        error ('struct_wrapper:SyntaxError', ...\n               'struct_wrapper: Invalid syntax');\n      end\n    end\n    function n = numel (o, varargin)\n      n = 1;\n    end\n    function varargout = subsref (o, p)\n      if (isequal (p(1).type, '{}'))\n        r = [];\n        for i = 1:numel (p(1).subs)\n          r = [r, getfield(o.s, p(1).subs{i})];\n        end\n        varargout = {r};\n      else\n        error ('struct_wrapper:SyntaxError', ...\n               'struct_wrapper: Invalid syntax');\n      end\n    end\n    function o = subsasgn (o, p, varargin)\n      if (isequal (p(1).type, '{}'))\n        for i = 1:numel (p(1).subs)\n          o.s = setfield (o.s, p(1).subs{i}, varargin{1}(i));\n        end\n      else\n        error ('struct_wrapper:SyntaxError', ...\n               'struct_wrapper: Invalid syntax');\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/classdef/value_class.m",
    "content": "classdef value_class\n  properties\n    a\n    b\n    c\n    d\n    e\n  endproperties\nendclassdef\n"
  },
  {
    "path": "test/classdef/value_class_reshape.m",
    "content": "classdef value_class_reshape\n  properties\n    a\n    b\n    c\n    d\n    e\n  endproperties\n\n  methods\n    function this = reshape(this, new_size)\n      this(end,end).a = new_size;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef/value_class_subclass.m",
    "content": "classdef value_class_subclass < value_class\n  properties\n    z\n  endproperties\nendclassdef\n"
  },
  {
    "path": "test/classdef-debug/classdef_breakpoints.m",
    "content": "classdef classdef_breakpoints\n  properties\n    m_prop = [];\n  endproperties\n  methods\n    function this = classdef_breakpoints (prop)\n      this.m_prop = prop;\n    endfunction\n    function this = foo (this, prop)\n      this.m_prop = prop;\n    endfunction\n    function this = bar (this)\n      printf (\"prop: %f\\n\", this.m_prop);\n    endfunction\n  endmethods\nendclassdef\n\nfunction my_subfunction (n)\n  ## my_subfunction hello\n  printf (\"subfunction: %f\\n\", n);\nendfunction\n"
  },
  {
    "path": "test/classdef-debug/classdef_breakpoints2.m",
    "content": "classdef classdef_breakpoints2 < handle\n  properties (Dependent)\n    m_prop;\n  endproperties\n  properties (SetAccess=private)\n    m_prop_value = [];\n  endproperties\n  methods\n    function this = classdef_breakpoints2 (prop)\n      this.m_prop = prop;\n    endfunction\n    function val = get.m_prop (this)\n      val = this.m_prop_value;\n    endfunction\n    function set.m_prop (this, val)\n      this.m_prop_value = val;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef-debug/module.mk",
    "content": "classdef_breakpoints_TEST_FILES = \\\n  %reldir%/classdef_breakpoints.m \\\n  %reldir%/classdef_breakpoints2.m \\\n  %reldir%/test-classdef-breakpoints.tst\n\nTEST_FILES += $(classdef_breakpoints_TEST_FILES)\n"
  },
  {
    "path": "test/classdef-debug/test-classdef-breakpoints.tst",
    "content": "##  Test script for setting breakpoints in classdefs\n##  using line numbers or method names.\n\n%!function assert_dbstatus (bp0)\n%!  dbs = dbstatus ();\n%!  bp = [dbs(:).line];\n%!  assert (length (bp) == length (bp0),\n%!          'Number of breakpoints set must match');\n%!  if (length (bp) != 0)\n%!    assert (sort (bp) == bp0, 'Breakpoint line numbers must be equal');\n%!  endif\n%!endfunction\n\n## Set breakpoints by line numbers\n%!test <*46451>\n%! if (isguirunning ())\n%!   orig_show_dbg = __event_manager_gui_preference__ (\"editor/show_dbg_file\",\n%!                                                     \"false\");\n%! endif\n%! unwind_protect\n%!   ## Add breakpoints in different member functions using line numbers.\n%!   dbstop classdef_breakpoints 13 7 10;\n%!   assert_dbstatus ([7, 10, 13]);\n%!\n%!   ## Remove one breakpoint and confirm the others remain.\n%!   dbclear classdef_breakpoints 10;\n%!   assert_dbstatus ([7, 13]);\n%!\n%!   ## Clear all breakpoints, none should be left.\n%!   dbclear classdef_breakpoints;\n%!   assert_dbstatus ([]);\n%! unwind_protect_cleanup\n%!   dbclear classdef_breakpoints;\n%!   if (isguirunning ())\n%!     __event_manager_gui_preference__ (\"editor/show_dbg_file\", orig_show_dbg);\n%!   endif\n%! end_unwind_protect\n\n## Set breakpoints by method name\n%!test\n%! if (isguirunning ())\n%!   orig_show_dbg = __event_manager_gui_preference__ (\"editor/show_dbg_file\",\n%!                                                     \"false\");\n%! endif\n%! unwind_protect\n%!   ## Add breakpoint in constructor\n%!   dbstop @classdef_breakpoints/classdef_breakpoints;\n%!   assert_dbstatus ([7]);\n%!\n%!   ## Add breakpoints in methods.\n%!   dbstop @classdef_breakpoints/foo;\n%!   dbstop @classdef_breakpoints/bar;\n%!   assert_dbstatus ([7, 10, 13]);\n%!\n%!   ## Remove breakpoint from one method.\n%!   dbclear @classdef_breakpoints/foo;\n%!   assert_dbstatus ([7, 13]);\n%!\n%!   ## Clear all breakpoints, none should be left.\n%!   dbclear classdef_breakpoints;\n%!   assert_dbstatus ([]);\n%! unwind_protect_cleanup\n%!   dbclear classdef_breakpoints;\n%!   if (isguirunning ())\n%!     __event_manager_gui_preference__ (\"editor/show_dbg_file\", orig_show_dbg);\n%!   endif\n%! end_unwind_protect\n\n## Try to add breakpoint in non-existent method\n%!test <*65610>\n%! if (isguirunning ())\n%!   orig_show_dbg = __event_manager_gui_preference__ (\"editor/show_dbg_file\",\n%!                                                     \"false\");\n%! endif\n%! unwind_protect\n%!   fail (\"dbstop @classdef_breakpoints/baz;\", \"unable to find function\");\n%! unwind_protect_cleanup\n%!   dbclear classdef_breakpoints;\n%!   if (isguirunning ())\n%!     __event_manager_gui_preference__ (\"editor/show_dbg_file\", orig_show_dbg);\n%!   endif\n%! end_unwind_protect\n\n%!test <46451>\n%! if (isguirunning ())\n%!   orig_show_dbg = __event_manager_gui_preference__ (\"editor/show_dbg_file\",\n%!                                                     \"false\");\n%! endif\n%! unwind_protect\n%!   ## Add breakpoint in local function.\n%!   dbstop classdef_breakpoints 19;\n%!   assert_dbstatus ([20]);\n%! unwind_protect_cleanup\n%!   dbclear classdef_breakpoints;\n%!   if (isguirunning ())\n%!     __event_manager_gui_preference__ (\"editor/show_dbg_file\", orig_show_dbg);\n%!   endif\n%! end_unwind_protect\n\n## Set breakpoints in set or get methods by line numbers\n%!test <*65610>\n%! if (isguirunning ())\n%!   orig_show_dbg = __event_manager_gui_preference__ (\"editor/show_dbg_file\",\n%!                                                     \"false\");\n%! endif\n%! unwind_protect\n%!   ## Add breakpoints in different member functions using line numbers.\n%!   dbstop classdef_breakpoints2 13 16 10;\n%!   assert_dbstatus ([10, 13, 16]);\n%!\n%!   ## Remove one breakpoint and confirm the others remain.\n%!   dbclear classdef_breakpoints2 16;\n%!   assert_dbstatus ([10, 13]);\n%!\n%!   ## Clear all breakpoints, none should be left.\n%!   dbclear classdef_breakpoints2;\n%!   assert_dbstatus ([]);\n%! unwind_protect_cleanup\n%!   dbclear classdef_breakpoints2;\n%!   if (isguirunning ())\n%!     __event_manager_gui_preference__ (\"editor/show_dbg_file\", orig_show_dbg);\n%!   endif\n%! end_unwind_protect\n\n## Set breakpoints in set or get methods by method name\n%!test\n%! if (isguirunning ())\n%!   orig_show_dbg = __event_manager_gui_preference__ (\"editor/show_dbg_file\",\n%!                                                     \"false\");\n%! endif\n%! unwind_protect\n%!   ## Add breakpoint in constructor\n%!   dbstop @classdef_breakpoints2/classdef_breakpoints2;\n%!   assert_dbstatus ([10]);\n%!\n%!   ## Add breakpoints in methods.\n%!   dbstop @classdef_breakpoints2/get.m_prop;\n%!   dbstop @classdef_breakpoints2/set.m_prop;\n%!   assert_dbstatus ([10, 13, 16]);\n%!\n%!   ## Remove breakpoint from one method.\n%!   dbclear @classdef_breakpoints2/get.m_prop;\n%!   assert_dbstatus ([10, 16]);\n%!\n%!   ## Clear all breakpoints, none should be left.\n%!   dbclear classdef_breakpoints2;\n%!   assert_dbstatus ([]);\n%! unwind_protect_cleanup\n%!   dbclear classdef_breakpoints2;\n%!   if (isguirunning ())\n%!     __event_manager_gui_preference__ (\"editor/show_dbg_file\", orig_show_dbg);\n%!   endif\n%! end_unwind_protect\n\n"
  },
  {
    "path": "test/classdef-load-save/changed-class/loadobj_changed_class.m",
    "content": "classdef loadobj_changed_class\n\n    properties\n      a\n      prop_later\n    endproperties\n\n    methods (Static)\n      function obj = loadobj (s)\n        obj = loadobj_changed_class ();\n        if isstruct (s)\n          obj.a = \"changed-struct\";\n        else\n          obj.a = \"changed-object\";\n        endif\n      endfunction\n    endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/classdef-load-save-text.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj\n%!test\n%! obj = regular_class ();\n%! obj.a = 1;\n%! obj.b = \"Regular Class\";\n%! obj.c = [[1, 2], [3, 4]];\n%! obj.d = struct (\"a\", 1, \"b\", 2);\n%! obj.e = {1, \"Regular Class\"};\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%!   assert (obj.b, \"Regular Class\");\n%!   assert (obj.c, [[1, 2], [3, 4]]);\n%!   assert (obj.d, struct (\"a\", 1, \"b\", 2));\n%!   assert (obj.e, {1, \"Regular Class\"});\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor defined, ConstructOnLoad = false, no loadobj/saveobj\n## (ensures that constructor is NOT called on load)\n%!test\n%! obj = regular_class_with_constructor ();\n%! obj.a = [];\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object\n%!test\n%! obj = regular_class ();\n%! obj.a = regular_class_with_constructor ();\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a), \"regular_class_with_constructor\");\n%!   assert (obj.a.a, 1);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object inside a struct\n%!test\n%! obj = regular_class ();\n%! s.obj_field = regular_class_with_constructor ();\n%! obj.a = s;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a.obj_field), \"regular_class_with_constructor\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object inside struct array\n%!test\n%! obj = regular_class ();\n%! s(2,3).obj_field = regular_class_with_constructor ();\n%! obj.a = s;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a(2,3).obj_field), \"regular_class_with_constructor\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object inside cell array\n%!test\n%! obj = regular_class ();\n%! c{2,3}.obj_field = regular_class_with_constructor ();\n%! obj.a = c;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a{2,3}.obj_field), \"regular_class_with_constructor\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Vector of value class objects.\n%!test\n%! obj = regular_class;\n%! obj.a = 1;\n%! obj(2) = regular_class;\n%! obj(2).a = 2;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj(1).a, 1);\n%!   assert (obj(2).a, 2);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Matrix of value class objects.\n%!test <*65179>\n%! obj = regular_class;\n%! obj.a = 1;\n%! obj(2,3) = regular_class;\n%! obj(2,3).a = 2;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj(1).a, 1);\n%!   assert (obj(6).a, 2);\n%!   assert (size (obj), [2, 3]);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, saveobj returns an object, no loadobj\n%!test\n%! obj = saveobj_obj_class ();\n%! obj.a = 1;\n%! obj.b = 3;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert(obj.a, 2);\n%!   assert(obj.b, 3);\n%!   assert(obj.c, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, saveobj returns a struct, no loadobj\n%!test\n%! obj = saveobj_struct_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert(obj.a, []);\n%!   assert(obj.b, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, loadobj is defined, no saveobj\n%!test\n%! obj = loadobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, loadobj is defined, no saveobj\n## Class definition changes between saving and loading the object\n%!test <*67414>\n%! clear classes;\n%! obj = loadobj_changed_class ();\n%! obj.a = 0;\n%! savefile = fullfile (tempdir (), \"oct-changed-class.sav\");\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, \"object\");\n%!   clear obj;\n%!   ## change to directory with classdef with renamed property name\n%!   cd (\"changed-class\");\n%!   clear classes;  # includes \"clear all\"\n%!   savefile = fullfile (tempdir (), \"oct-changed-class.sav\");\n%!   load (savefile);\n%!   assert (obj.a, \"changed-struct\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%!   [~, curr_dir] = fileparts (pwd ());\n%!   if (strcmp (curr_dir, \"changed-class\"))\n%!     cd ..\n%!   endif\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, loadobj is defined, saveobj is defined\n%!test\n%! obj = loadobj_saveobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor defined, ConstructOnLoad = false, custom return type for loadobj/saveobj\n%!test\n%! obj = custom_saveobj ();\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, \"abcde\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, undefined return variable from saveobj (should return default initialized classdef)\n%!test\n%! obj = invalid_saveobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, undefined return variable from saveobj (should emit a warning)\n%!warning <saveobj.*does not return.*value>\n%! obj = invalid_saveobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! delete (savefile);\n\n## Handle class, no constructor, ConstructOnLoad = false, no loadobj/saveobj\n%!test\n%! obj1 = regular_handle_class ();\n%! obj2 = obj1;\n%! obj2.a = 1;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj1', 'obj2');\n%! unwind_protect\n%!   clear obj1 obj2;\n%!   load (savefile);\n%!   obj2.b = 2;\n%!   assert (obj1.b, 2);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Handle class, no constructor, ConstructOnLoad = false, no loadobj/saveobj, circular references\n%!test\n%! obj = regular_handle_class ();\n%! obj.a = regular_handle_class ();\n%! obj.c = 1;\n%! obj.a.b = obj;\n%! obj.a.d = 2;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.c, 1);\n%!   obj.c = 3;\n%!   assert (obj.a.b.c, 3);\n%!   assert (obj.a.d, 2);\n%!   obj.a.d = 4;\n%!   assert (obj.a.b.a.d, 4);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Handle class, no constructor, ConstructOnLoad = false, no loadobj/saveobj, vector\n%!test\n%! obj = regular_handle_class ();\n%! obj(2) = regular_handle_class ();\n%! obj(3) = obj(1);\n%! obj(1).a = 1;\n%! obj(2).a = 2;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj(1).a, 1);\n%!   assert (obj(2).a, 2);\n%!   obj(1).a = 3;\n%!   assert (obj(3).a, 3);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor, ConstructOnLoad = false, Transient property\n%!test\n%! obj = transient_property_class ();\n%! obj.a = 1;\n%! obj.transient_property = 6;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%!   ## Transient property should not be saved and loaded\n%!   assert (obj.transient_property, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor, ConstructOnLoad = true, Transient property, no loadobj/saveobj\n%!test\n%! obj = regular_class_construct_on_load ();\n%! obj.a = 10;\n%! obj.f = 16;\n%! savefile = tempname ();\n%! save ('-text', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 10);\n%!   assert (obj.f, 6);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/classdef-load-save/classdef-load-save-v6.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj\n%!test\n%! obj = regular_class ();\n%! obj.a = 1;\n%! obj.b = \"Regular Class\";\n%! obj.c = [[1, 2], [3, 4]];\n%! obj.d = struct (\"a\", 1, \"b\", 2);\n%! obj.e = {1, \"Regular Class\"};\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%!   assert (obj.b, \"Regular Class\");\n%!   assert (obj.c, [[1, 2], [3, 4]]);\n%!   assert (obj.d, struct (\"a\", 1, \"b\", 2));\n%!   assert (obj.e, {1, \"Regular Class\"});\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor defined, ConstructOnLoad = false, no loadobj/saveobj\n## (ensures that constructor is NOT called on load)\n%!test\n%! obj = regular_class_with_constructor ();\n%! obj.a = [];\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object\n%!test\n%! obj = regular_class ();\n%! obj.a = regular_class_with_constructor ();\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a), \"regular_class_with_constructor\");\n%!   assert (obj.a.a, 1);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object inside a struct\n%!test <*45833>\n%! obj = regular_class ();\n%! s.obj_field = regular_class_with_constructor ();\n%! obj.a = s;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a.obj_field), \"regular_class_with_constructor\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object inside struct array\n%!test <*45833>\n%! obj = regular_class ();\n%! s(2,3).obj_field = regular_class_with_constructor ();\n%! obj.a = s;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a(2,3).obj_field), \"regular_class_with_constructor\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object inside cell array\n%!test <*45833>\n%! obj = regular_class ();\n%! c{2,3}.obj_field = regular_class_with_constructor ();\n%! obj.a = c;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a{2,3}.obj_field), \"regular_class_with_constructor\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Vector of value class objects.\n%!test\n%! obj = regular_class;\n%! obj.a = 1;\n%! obj(2) = regular_class;\n%! obj(2).a = 2;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj(1).a, 1);\n%!   assert (obj(2).a, 2);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Matrix of value class objects.\n%!test <*65179>\n%! obj = regular_class;\n%! obj.a = 1;\n%! obj(2,3) = regular_class;\n%! obj(2,3).a = 2;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj(1).a, 1);\n%!   assert (obj(6).a, 2);\n%!   assert (size (obj), [2, 3]);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, saveobj returns an object, no loadobj\n%!test\n%! obj = saveobj_obj_class ();\n%! obj.a = 1;\n%! obj.b = 3;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert(obj.a, 2);\n%!   assert(obj.b, 3);\n%!   assert(obj.c, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, saveobj returns a struct, no loadobj\n%!test\n%! obj = saveobj_struct_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert(obj.a, []);\n%!   assert(obj.b, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, loadobj is defined, no saveobj\n%!test\n%! obj = loadobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, loadobj is defined, no saveobj\n## Class definition changes between saving and loading the object\n%!test <*67414>\n%! clear classes;\n%! obj = loadobj_changed_class ();\n%! obj.a = 0;\n%! savefile = fullfile (tempdir (), \"oct-changed-class.sav\");\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, \"object\");\n%!   clear obj;\n%!   ## change to directory with classdef with renamed property name\n%!   cd (\"changed-class\");\n%!   clear classes;  # includes \"clear all\"\n%!   savefile = fullfile (tempdir (), \"oct-changed-class.sav\");\n%!   load (savefile);\n%!   assert (obj.a, \"changed-struct\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%!   [~, curr_dir] = fileparts (pwd ());\n%!   if (strcmp (curr_dir, \"changed-class\"))\n%!     cd ..\n%!   endif\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, loadobj is defined, saveobj is defined\n%!test\n%! obj = loadobj_saveobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor defined, ConstructOnLoad = false, custom return type for loadobj/saveobj\n%!test\n%! obj = custom_saveobj ();\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, \"abcde\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, undefined return variable from saveobj (should return default initialized classdef)\n%!test\n%! obj = invalid_saveobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, []);  # fails in MATLAB\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, undefined return variable from saveobj (should emit a warning)\n%!warning <saveobj.*does not return.*value>\n%! obj = invalid_saveobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! delete (savefile);\n\n## Handle class, no constructor, ConstructOnLoad = false, no loadobj/saveobj\n%!test\n%! obj1 = regular_handle_class ();\n%! obj2 = obj1;\n%! obj2.a = 1;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj1', 'obj2');\n%! unwind_protect\n%!   clear obj1 obj2;\n%!   load (savefile);\n%!   obj2.b = 2;\n%!   assert (obj1.b, 2);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Handle class, no constructor, ConstructOnLoad = false, no loadobj/saveobj, circular references\n%!test\n%! obj = regular_handle_class ();\n%! obj.a = regular_handle_class ();\n%! obj.c = 1;\n%! obj.a.b = obj;\n%! obj.a.d = 2;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.c, 1);\n%!   obj.c = 3;\n%!   assert (obj.a.b.c, 3);\n%!   assert (obj.a.d, 2);\n%!   obj.a.d = 4;\n%!   assert (obj.a.b.a.d, 4);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Handle class, no constructor, ConstructOnLoad = false, no loadobj/saveobj, vector\n%!test\n%! obj = regular_handle_class ();\n%! obj(2) = regular_handle_class ();\n%! obj(3) = obj(1);\n%! obj(1).a = 1;\n%! obj(2).a = 2;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj(1).a, 1);\n%!   assert (obj(2).a, 2);\n%!   obj(1).a = 3;\n%!   assert (obj(3).a, 3);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor, ConstructOnLoad = false, Transient property\n%!test\n%! obj = transient_property_class ();\n%! obj.a = 1;\n%! obj.transient_property = 6;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%!   ## Transient property should not be saved and loaded\n%!   assert (obj.transient_property, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor, ConstructOnLoad = true, Transient property, no loadobj/saveobj\n%!test\n%! obj = regular_class_construct_on_load ();\n%! obj.a = 10;\n%! obj.f = 16;\n%! savefile = tempname ();\n%! save ('-v6', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 10);\n%!   assert (obj.f, 6);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/classdef-load-save/classdef-load-save-v7.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj\n%!testif HAVE_ZLIB\n%! obj = regular_class ();\n%! obj.a = 1;\n%! obj.b = \"Regular Class\";\n%! obj.c = [[1, 2], [3, 4]];\n%! obj.d = struct (\"a\", 1, \"b\", 2);\n%! obj.e = {1, \"Regular Class\"};\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%!   assert (obj.b, \"Regular Class\");\n%!   assert (obj.c, [[1, 2], [3, 4]]);\n%!   assert (obj.d, struct (\"a\", 1, \"b\", 2));\n%!   assert (obj.e, {1, \"Regular Class\"});\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor defined, ConstructOnLoad = false, no loadobj/saveobj\n## (ensures that constructor is NOT called on load)\n%!testif HAVE_ZLIB\n%! obj = regular_class_with_constructor ();\n%! obj.a = [];\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object\n%!testif HAVE_ZLIB\n%! obj = regular_class ();\n%! obj.a = regular_class_with_constructor ();\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a), \"regular_class_with_constructor\");\n%!   assert (obj.a.a, 1);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object inside a struct\n%!testif HAVE_ZLIB  <*45833>\n%! obj = regular_class ();\n%! s.obj_field = regular_class_with_constructor ();\n%! obj.a = s;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a.obj_field), \"regular_class_with_constructor\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object inside struct array\n%!testif HAVE_ZLIB  <*45833>\n%! obj = regular_class ();\n%! s(2,3).obj_field = regular_class_with_constructor ();\n%! obj.a = s;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a(2,3).obj_field), \"regular_class_with_constructor\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, no loadobj/saveobj, nested object inside cell array\n%!testif HAVE_ZLIB  <*45833>\n%! obj = regular_class ();\n%! c{2,3}.obj_field = regular_class_with_constructor ();\n%! obj.a = c;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (class (obj.a{2,3}.obj_field), \"regular_class_with_constructor\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Vector of value class objects.\n%!testif HAVE_ZLIB\n%! obj = regular_class;\n%! obj.a = 1;\n%! obj(2) = regular_class;\n%! obj(2).a = 2;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj(1).a, 1);\n%!   assert (obj(2).a, 2);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Matrix of value class objects.\n%!testif HAVE_ZLIB  <*65179>\n%! obj = regular_class;\n%! obj.a = 1;\n%! obj(2,3) = regular_class;\n%! obj(2,3).a = 2;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj(1).a, 1);\n%!   assert (obj(6).a, 2);\n%!   assert (size (obj), [2, 3]);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, saveobj returns an object, no loadobj\n%!testif HAVE_ZLIB\n%! obj = saveobj_obj_class ();\n%! obj.a = 1;\n%! obj.b = 3;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert(obj.a, 2);\n%!   assert(obj.b, 3);\n%!   assert(obj.c, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, saveobj returns a struct, no loadobj\n%!testif HAVE_ZLIB\n%! obj = saveobj_struct_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert(obj.a, []);\n%!   assert(obj.b, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, loadobj is defined, no saveobj\n%!testif HAVE_ZLIB\n%! obj = loadobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, loadobj is defined, no saveobj\n## Class definition changes between saving and loading the object\n%!testif HAVE_ZLIB  <*67414>\n%! clear classes;\n%! obj = loadobj_changed_class ();\n%! obj.a = 0;\n%! savefile = fullfile (tempdir (), \"oct-changed-class.sav\");\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, \"object\");\n%!   clear obj;\n%!   ## change to directory with classdef with renamed property name\n%!   cd (\"changed-class\");\n%!   clear classes;  # includes \"clear all\"\n%!   savefile = fullfile (tempdir (), \"oct-changed-class.sav\");\n%!   load (savefile);\n%!   assert (obj.a, \"changed-struct\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%!   [~, curr_dir] = fileparts (pwd ());\n%!   if (strcmp (curr_dir, \"changed-class\"))\n%!     cd ..\n%!   endif\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, loadobj is defined, saveobj is defined\n%!testif HAVE_ZLIB\n%! obj = loadobj_saveobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor defined, ConstructOnLoad = false, custom return type for loadobj/saveobj\n%!testif HAVE_ZLIB\n%! obj = custom_saveobj ();\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, \"abcde\");\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, undefined return variable from saveobj (should return default initialized classdef)\n%!testif HAVE_ZLIB\n%! obj = invalid_saveobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, []);  # fails in MATLAB\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## No constructor, ConstructOnLoad = false, undefined return variable from saveobj (should emit a warning)\n%!testif HAVE_ZLIB\n%! obj = invalid_saveobj_class ();\n%! obj.a = 1;\n%! savefile = tempname ();\n%! lastwarn (\"\");\n%! unwind_protect\n%!   save ('-v7', savefile, 'obj');\n%!   assert (! isempty (regexp (lastwarn (), \"saveobj.*does not return.*value\", \"once\")));\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Handle class, no constructor, ConstructOnLoad = false, no loadobj/saveobj\n%!testif HAVE_ZLIB\n%! obj1 = regular_handle_class ();\n%! obj2 = obj1;\n%! obj2.a = 1;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj1', 'obj2');\n%! unwind_protect\n%!   clear obj1 obj2;\n%!   load (savefile);\n%!   obj2.b = 2;\n%!   assert (obj1.b, 2);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Handle class, no constructor, ConstructOnLoad = false, no loadobj/saveobj, circular references\n%!testif HAVE_ZLIB\n%! obj = regular_handle_class ();\n%! obj.a = regular_handle_class ();\n%! obj.c = 1;\n%! obj.a.b = obj;\n%! obj.a.d = 2;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.c, 1);\n%!   obj.c = 3;\n%!   assert (obj.a.b.c, 3);\n%!   assert (obj.a.d, 2);\n%!   obj.a.d = 4;\n%!   assert (obj.a.b.a.d, 4);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Handle class, no constructor, ConstructOnLoad = false, no loadobj/saveobj, vector\n%!testif HAVE_ZLIB\n%! obj = regular_handle_class ();\n%! obj(2) = regular_handle_class ();\n%! obj(3) = obj(1);\n%! obj(1).a = 1;\n%! obj(2).a = 2;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj(1).a, 1);\n%!   assert (obj(2).a, 2);\n%!   obj(1).a = 3;\n%!   assert (obj(3).a, 3);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor, ConstructOnLoad = false, Transient property\n%!testif HAVE_ZLIB\n%! obj = transient_property_class ();\n%! obj.a = 1;\n%! obj.transient_property = 6;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 1);\n%!   ## Transient property should not be saved and loaded\n%!   assert (obj.transient_property, []);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n\n## Constructor, ConstructOnLoad = true, Transient property, no loadobj/saveobj\n%!testif HAVE_ZLIB\n%! obj = regular_class_construct_on_load ();\n%! obj.a = 10;\n%! obj.f = 16;\n%! savefile = tempname ();\n%! save ('-v7', savefile, 'obj');\n%! unwind_protect\n%!   clear obj;\n%!   load (savefile);\n%!   assert (obj.a, 10);\n%!   assert (obj.f, 6);\n%! unwind_protect_cleanup\n%!   delete (savefile);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/classdef-load-save/custom_saveobj.m",
    "content": "classdef custom_saveobj < regular_class\n    methods\n        function s = saveobj (obj)\n            s.a = \"abcde\";\n        end\n    end\n\n    methods (Static)\n        function obj = loadobj (s)\n            obj = custom_saveobj ();\n            obj.a = s.a;\n        end\n    end\nend\n"
  },
  {
    "path": "test/classdef-load-save/invalid_saveobj_class.m",
    "content": "classdef invalid_saveobj_class < regular_class\n  methods\n    function s = saveobj (obj);\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/loadobj_changed_class.m",
    "content": "classdef loadobj_changed_class\n\n    properties\n      a\n      prop_prior\n    endproperties\n\n    methods (Static)\n      function obj = loadobj (s)\n        obj = loadobj_changed_class ();\n        if isstruct (s)\n          obj.a = \"struct\";\n        else\n          obj.a = \"object\";\n        endif\n      endfunction\n    endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/loadobj_class.m",
    "content": "classdef loadobj_class < regular_class\n  methods (Static)\n    function obj = loadobj (s)\n      obj = loadobj_class ();\n      obj.a = s.a;\n      obj.b = s.b;\n      obj.c = s.c;\n      obj.d = s.d;\n      obj.e = s.e;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/loadobj_saveobj_class.m",
    "content": "classdef loadobj_saveobj_class < regular_class\n  methods (Static)\n    function obj = loadobj (s)\n      obj = loadobj_saveobj_class ();\n      obj.a = s.a;\n      obj.b = s.b;\n      obj.c = s.c;\n      obj.d = s.d;\n      obj.e = s.e;\n    endfunction\n  endmethods\n\n  methods\n    function s = saveobj (obj)\n      s.a = obj.a;\n      s.b = obj.b;\n      s.c = obj.c;\n      s.d = obj.d;\n      s.e = obj.e;\n    endfunction\n  endmethods\n\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/module.mk",
    "content": "classdef_load_save_TEST_FILES = \\\n  %reldir%/changed-class/loadobj_changed_class.m \\\n  %reldir%/classdef-load-save-text.tst \\\n  %reldir%/classdef-load-save-v6.tst \\\n  %reldir%/classdef-load-save-v7.tst \\\n  %reldir%/custom_saveobj.m \\\n  %reldir%/invalid_saveobj_class.m \\\n  %reldir%/loadobj_changed_class.m \\\n  %reldir%/loadobj_class.m \\\n  %reldir%/loadobj_saveobj_class.m \\\n  %reldir%/regular_class.m \\\n  %reldir%/regular_class_construct_on_load.m \\\n  %reldir%/regular_class_with_constructor.m \\\n  %reldir%/regular_handle_class.m \\\n  %reldir%/saveobj_obj_class.m \\\n  %reldir%/saveobj_struct_class.m \\\n  %reldir%/transient_property_class.m\n\nTEST_FILES += $(classdef_load_save_TEST_FILES)\n"
  },
  {
    "path": "test/classdef-load-save/regular_class.m",
    "content": "classdef regular_class\n    properties\n      a\n      b\n      c\n      d\n      e\n    endproperties\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/regular_class_construct_on_load.m",
    "content": "classdef (ConstructOnLoad) regular_class_construct_on_load < regular_class\n  properties (Transient)\n    f\n  endproperties\n  methods\n    function obj = regular_class_construct_on_load ()\n      obj.a = 1;\n      obj.b = 2;\n      obj.c = 3;\n      obj.d = 4;\n      obj.e = 5;\n      obj.f = 6;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/regular_class_with_constructor.m",
    "content": "classdef regular_class_with_constructor < regular_class\n    methods\n      function obj = regular_class_with_constructor ()\n        obj.a = 1;\n        obj.b = 2;\n        obj.c = 3;\n        obj.d = 4;\n        obj.e = 5;\n      endfunction\n    endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/regular_handle_class.m",
    "content": "classdef regular_handle_class < handle\n  properties\n    a\n    b\n    c\n    d\n    e\n  endproperties\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/saveobj_obj_class.m",
    "content": "classdef saveobj_obj_class < regular_class\n  methods\n    function obj = saveobj (obj)\n      obj.a = 2;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/saveobj_struct_class.m",
    "content": "classdef saveobj_struct_class < regular_class\n  methods\n    function s = saveobj (obj)\n      s.a = obj.a;\n      s.b = obj.b;\n      s.c = obj.c;\n      s.d = obj.d;\n      s.e = obj.e;\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/classdef-load-save/transient_property_class.m",
    "content": "classdef transient_property_class < regular_class\n  properties (Transient)\n    transient_property\n  endproperties\nendclassdef\n"
  },
  {
    "path": "test/classdef-multiple-inheritance/base_1.m",
    "content": "classdef base_1\nend\n"
  },
  {
    "path": "test/classdef-multiple-inheritance/base_2.m",
    "content": "classdef base_2\nend\n"
  },
  {
    "path": "test/classdef-multiple-inheritance/child_from_base_1.m",
    "content": "classdef child_from_base_1 < base_1\nend\n"
  },
  {
    "path": "test/classdef-multiple-inheritance/child_from_base_1_and_2.m",
    "content": "classdef child_from_base_1_and_2 < base_1 & base_2\nend\n"
  },
  {
    "path": "test/classdef-multiple-inheritance/classdef-multiple-inheritance.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%%  Test script for classdef OOP.\n%%  Requires the path to contain the test classes.\n%%\n%%  Note: This script and all classes are also intended to run\n%%        in MATLAB to test compatibility.  Don't break that!\n%%\n%%  The classes used for the tests reside in the\n%%  test/classdef_multiple_inheritance with others in the test directory.\n%%\n%%  The classes provide the ability to test most of the major features\n%%  of the classdef OOP facilities.  There are a number of classes, mostly\n%%  kind of the same, that create a hierarchy.\n\n%%  Basic classdef tests for multiple inheritance (bug #49973)\n%!test\n%! obj1 = child_from_base_1 ();\n%! obj2 = child_from_base_1_and_2 ();\n%! assert (class (obj1), 'child_from_base_1');\n%! assert (class (obj2), \"child_from_base_1_and_2\");\n"
  },
  {
    "path": "test/classdef-multiple-inheritance/module.mk",
    "content": "classdef_multiple_inheritance_TEST_FILES = \\\n  %reldir%/base_1.m \\\n  %reldir%/base_2.m \\\n  %reldir%/child_from_base_1.m \\\n  %reldir%/child_from_base_1_and_2.m \\\n  %reldir%/classdef-multiple-inheritance.tst\n\nTEST_FILES += $(classdef_multiple_inheritance_TEST_FILES)\n"
  },
  {
    "path": "test/classes/@Blork/Blork.m",
    "content": "function s = Blork (bleek)\n%% Test class.\n\n  if (nargin == 1 && isa (bleek, 'Blork'))\n    s = bleek;\n  else\n    if (nargin == 0)\n      s.bleek = 1;\n    else\n      s.bleek = bleek;\n    end\n    s = class (s, 'Blork');\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Blork/bleek.m",
    "content": "function out = bleek (in, val)\n\n  if (nargin == 1)\n    out = in.bleek;\n  else\n    in.bleek = val;\n    out = in;\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Blork/display.m",
    "content": "function display (s)\n\n  disp ([inputname(1),'.bleek = ']);\n  disp (' ');\n  disp (s.bleek);\n\nend\n"
  },
  {
    "path": "test/classes/@Blork/get.m",
    "content": "function v = get (s, propName)\n\n  switch (propName)\n    case 'bleek'\n      v = s.bleek;\n    otherwise\n      error ([propName, ' is not a valid Blork property']);\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Blork/set.m",
    "content": "function s = set (s, varargin)\n\n  propArgs = varargin;\n  while (length (propArgs) >= 2)\n    propName  = propArgs{1};\n    propValue = propArgs{2};\n    propArgs  = propArgs(3:end);\n    switch (propName)\n      case 'bleek'\n        s.bleek = propValue;\n      otherwise\n        error ([propName, ' is not a valid Blork property']);\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester1/CPrecedenceTester1.m",
    "content": "function x = CPrecedenceTester1 ()\n\n  x = struct ('useless_data', pi);\n  x = class (x, 'CPrecedenceTester1');\n\n  %% don't change anything as far as precedence is concerned\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester1/double.m",
    "content": "function x = double (snk)\n\n  x = snk.useless_data;\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester1/plus.m",
    "content": "function s = plus (s1, s2)\n\n  s = 'CPrecedenceTester1';\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester1/tattack.m",
    "content": "function s = tattack (x, y)\n\n  s = 'CPrecedenceTester1';\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester2/CPrecedenceTester2.m",
    "content": "function x = CPrecedenceTester2 (flag)\n\n  x = struct ('useless_data', pi^2);\n  x = class (x, 'CPrecedenceTester2');\n\n  switch (flag)\n    case 1  % CPrecedencetester2 > Snork\n      superiorto ('Snork');\n    case 2  % CPrecedencetester2 < Snork\n      inferiorto ('Snork');\n    otherwise\n      error ('Incorrect value for argument flag: %d', flag);\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester2/double.m",
    "content": "function x = double (snk)\n\n  x = snk.useless_data;\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester2/plus.m",
    "content": "function s = plus (s1, s2)\n\n  s = 'CPrecedenceTester2';\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester2/tattack.m",
    "content": "function s = tattack (x, y)\n\n  s = 'CPrecedenceTester2';\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester3/CPrecedenceTester3.m",
    "content": "function x = CPrecedenceTester3 (flag)\n\n  x = struct ('useless_data', pi^3);\n  x = class (x, 'CPrecedenceTester3');\n\n  switch (flag)\n    case 1  % CPrecedencetester3 > Snork\n      superiorto ('Snork');\n    case 2  % CPrecedencetester3 < Snork\n      inferiorto ('Snork');\n    otherwise\n      error ('Incorrect value for argument flag: %d', flag);\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester3/double.m",
    "content": "function x = double (snk)\n\n  x = snk.useless_data;\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester3/plus.m",
    "content": "function s = plus (s1, s2)\n\n  s = 'CPrecedenceTester3';\n\nend\n"
  },
  {
    "path": "test/classes/@CPrecedenceTester3/tattack.m",
    "content": "function s = tattack (x, y)\n\n  s = 'CPrecedenceTester3';\n\nend\n"
  },
  {
    "path": "test/classes/@Cork/Cork.m",
    "content": "function s = Cork (click)\n%% Test class.\n\n  if (nargin == 1 && isa (click, 'Cork'))\n    s = click;\n    return;\n  end\n\n  if (nargin < 1)\n    s.click = 1;\n  else\n    s.click = click;\n  end\n  s = class (s, 'Cork');\n\nend\n"
  },
  {
    "path": "test/classes/@Cork/click.m",
    "content": "function out = click (in, val)\n\n  if (nargin == 1)\n    out = in.click;\n  else\n    in.click = val;\n    out = in;\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Cork/display.m",
    "content": "function display (s)\n\n  disp ([inputname(1),'.click = ']);\n  disp (' ');\n  disp (s.click);\n\nend\n"
  },
  {
    "path": "test/classes/@Cork/get.m",
    "content": "function v = get (s, propName)\n\n  switch (propName)\n    case 'click'\n      v = s.click;\n    otherwise\n      error ([propName, ' is not a valid Cork property']);\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Cork/set.m",
    "content": "function s = set (s, varargin)\n\n  propArgs = varargin;\n  while (length (propArgs) >= 2)\n    propName  = propArgs{1};\n    propValue = propArgs{2};\n    propArgs  = propArgs(3:end);\n    switch (propName)\n      case 'click'\n        s.click = propValue;\n      otherwise\n        error ([propName, ' is not a valid Cork property']);\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Dork/Dork.m",
    "content": "function s = Dork (gick, gack)\n\n  if (nargin == 1 && isa (gick, 'Dork'))\n    s = gick;\n  else\n    s.gack = 0;\n    if (nargin == 0)\n      s0 = Snork ();\n    elseif (nargin == 1)\n      s0 = Snork (gick);\n    else\n      s0 = Snork (gick);\n      s.gack = gack;\n    end\n    s = class (s, 'Dork', s0);\n   end\n\nend\n"
  },
  {
    "path": "test/classes/@Dork/bling.m",
    "content": "function out = bling (m1, m2)\n\n  out = 1;\n\nend\n"
  },
  {
    "path": "test/classes/@Dork/display.m",
    "content": "function display (s)\n%%  Display the critical info for an amplifier\n\n   gick = get (s, 'gick');\n   disp ([inputname(1),'.gick = ']);\n   disp (' ');\n   disp (gick);\n   disp (' ');\n   disp ([inputname(1),'.gack = ']);\n   disp (' ');\n   disp (s.gack);\n\nend\n"
  },
  {
    "path": "test/classes/@Dork/gack.m",
    "content": "function out = gack (in, val)\n\n  if (nargin == 1)\n    out = in.gack;\n  else\n    in.gack = val;\n    out = in;\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Dork/get.m",
    "content": "function v = get (s, propName)\n\n  switch (propName)\n    case 'gack'\n      v = s.gack;\n    otherwise\n      v = get (s.Snork,propName);\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Dork/getStash.m",
    "content": "function out = getStash (cls)\n\n  out = myStash ();\n\nend\n"
  },
  {
    "path": "test/classes/@Dork/private/myStash.m",
    "content": "function out = myStash ()\n\n  out = 2;\n\nend\n"
  },
  {
    "path": "test/classes/@Dork/set.m",
    "content": "function s = set (s, varargin)\n\n  propArgs = varargin;\n  while (length (propArgs) >= 2)\n    propName  = propArgs{1};\n    propValue = propArgs{2};\n    propArgs  = propArgs(3:end);\n    switch (propName)\n      case 'gack'\n        s.gack = propValue;\n      otherwise\n        s.Snork = set (s.Snork, propName, propValue);\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Gork/Gork.m",
    "content": "function s = Gork (g)\n\n  if (nargin == 1 && isa (g, 'Gork'))\n    s = sprk;\n    return;\n  end\n\n  drk  = Dork ();\n  prk  = Pork ();\n  blrk = Blork ();\n  s.Cork = Cork (17);  % Aggregation.\n  s.gark = -2;\n  s.gyrk = -3;\n  s = class (s,'Gork',drk,prk,blrk);\n\nend\n"
  },
  {
    "path": "test/classes/@Gork/cork.m",
    "content": "function out = cork (in, val)\n\n  if (nargin == 1)\n    out = in.Cork;\n  else\n    in.Cork = val;\n    out = in;\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Gork/display.m",
    "content": "function display (s)\n%%  Display the critical info for a Gork.\n\n   dork_base = s.Dork\n   %pork_base = s.Pork\n   %sprk = s.sprk;\n   gark = get (s, 'gark');\n   disp ([inputname(1),'.gark = ']);\n   disp (' ');\n   disp (gark);\n   disp ([inputname(1),'.Cork= ']);\n   disp (' ');\n   disp (click(s.Cork));\n\nend\n"
  },
  {
    "path": "test/classes/@Gork/gark.m",
    "content": "function out = gark (in, val)\n\n  if (nargin == 1)\n    out = in.gark;\n  else\n    in.gark = val;\n    out = in;\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Gork/get.m",
    "content": "function v = get (s, propName)\n\n  switch (propName)\n    case 'cork'\n      v = s.Cork;\n    case 'gark'\n      v = s.gark;\n    otherwise\n      %% Note that get/set for multiple parents is hard.  We only do one\n      %% branch of the parent tree just to test this stuff out.\n      v = get (s.Dork,propName);\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Gork/set.m",
    "content": "function s = set (s, varargin)\n\n  propArgs = varargin;\n  while (length (propArgs) >= 2)\n    propName  = propArgs{1};\n    propValue = propArgs{2};\n    propArgs  = propArgs(3:end);\n    switch (propName)\n      case 'cork'\n        if (isa (propValue, 'Cork'))\n          s.Cork = propValue;\n        else\n          s.Cork = set (s.Cork, 'click', propValue);\n        end\n      case 'gark'\n        s.gark = propValue;\n      otherwise\n        %% Note that get/set for multiple parents is hard.  We only do one\n        %% branch of the parent tree just to test this stuff out.\n        s.Dork = set (s.Dork, propName, propValue);\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Gork/subsasgn.m",
    "content": "function g = subsasgn (g, s, x)\n\n  switch (s.type)\n  case '.'\n    switch (s.subs)\n    case 'gyrk'\n      g.gyrk = x;\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Gork/subsref.m",
    "content": "function x = subsref (g, s)\n\n  switch (s.type)\n  case '.'\n    switch (s.subs)\n    case 'gyrk'\n      x = g.gyrk;\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Pork/Pork.m",
    "content": "function s = Pork (geek, gurk)\n\n  if (nargin == 1 && isa (geek, 'Pork'))\n    s = geek;\n  else\n    s.gurk = 0;\n    if (nargin == 0)\n      s0 = Spork ();\n    elseif (nargin == 1)\n      s0 = Spork (geek);\n    else\n      s0 = Spork (geek);\n      s.gurk = gurk;\n    end\n    s = class (s, 'Pork', s0);\n   end\n   superiorto ('Dork');\n\nend\n"
  },
  {
    "path": "test/classes/@Pork/bling.m",
    "content": "function out = bling (m1, m2)\n\n  out = 2;\n\nend\n"
  },
  {
    "path": "test/classes/@Pork/display.m",
    "content": "function display (s)\n%%  Display the critical info for an amplifier\n\n   geek = get (s, 'geek');\n   disp ([inputname(1),'.geek = ']);\n   disp (' ');\n   disp (geek);\n   disp (' ');\n   disp ([inputname(1),'.gurk = ']);\n   disp (' ');\n   disp (s.gurk);\n\nend\n"
  },
  {
    "path": "test/classes/@Pork/get.m",
    "content": "function v = get (s, propName)\n\n  switch (propName)\n    case 'gurk'\n      v = s.gurk;\n    otherwise\n      v = get (s.Spork, propName);\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Pork/gurk.m",
    "content": "function out = gurk (in, val)\n\n  if (nargin == 1)\n    out = in.gurk;\n  else\n    in.gurk = val;\n    out = in;\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Pork/private/myStash.m",
    "content": "function out = myStash ()\n\n  out = 4;\n\nend\n"
  },
  {
    "path": "test/classes/@Pork/set.m",
    "content": "function s = set (s, varargin)\n\n  propArgs = varargin;\n  while (length (propArgs) >= 2)\n    propName  = propArgs{1};\n    propValue = propArgs{2};\n    propArgs  = propArgs(3:end);\n    switch (propName)\n      case 'gurk'\n        s.gurk = propValue;\n      otherwise\n        s.Spork = set (s.Spork, propName, propValue);\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@SizeTester/SizeTester.m",
    "content": "function x = SizeTester (desired_size)\n\n  x = struct (\"desired_size\", desired_size);\n  x = class (x, \"SizeTester\");\n\nend\n"
  },
  {
    "path": "test/classes/@SizeTester/numel.m",
    "content": "function n = numel (this)\n\n  n = prod (this.desired_size);\n\nend\n"
  },
  {
    "path": "test/classes/@SizeTester/size.m",
    "content": "function s = size (this)\n\n  s = this.desired_size;\n\nend\n"
  },
  {
    "path": "test/classes/@Sneetch/Sneetch.m",
    "content": "function s = Sneetch (mcbean)\n%% Test class: should produce error.\n\n  if (nargin == 1 && isa (mcbean, 'Sneetch'))\n    s = mcbean;\n  else\n    if (nargin == 0)\n      s.mcbean = 1;\n    else\n      s.mcbean = mcbean;\n    end\n    s = class (s, 'Sneetch');\n    s.sylvester = 1;\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Sneetch/display.m",
    "content": "function display ( s )\n\n  disp ([inputname(1),'.mcbean = ']);\n  disp (' ');\n  disp (s.mcbean);\n  disp ([inputname(1),'.sylvester = ']);\n  disp (' ');\n  disp (s.sylvester);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/Snork.m",
    "content": "function s = Snork (gick)\n%% Test class.\n\n  if (nargin == 1 && isa (gick, 'Snork'))\n    s = gick;\n  else\n    s.cack = [0 1 2 3];\n    if (nargin == 0)\n      s.gick = 1;\n    else\n      s.gick = gick;\n    end\n    s = class (s, 'Snork');\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/cack.m",
    "content": "function out = cack (in)\n\n  out = in.cack;\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/ctranspose.m",
    "content": "function s = ctranspose (s)\n\n  x = double (s);\n\n  s = Snork (x' + 4);  % +4 To make sure some non-standard tranpose is called.\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/display.m",
    "content": "function display (s)\n\n  disp ([inputname(1),'.gick = ']);\n  disp (' ');\n  disp (s.gick);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/double.m",
    "content": "function x = double (snk)\n\n  x = snk.gick;\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/end.m",
    "content": "function r = end (snk, index_pos, num_indices)\n\n  if (num_indices ~= 1)\n    error ('Snork object may only have one index');\n  end\n\n  r = length (snk.cack);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/eq.m",
    "content": "function b = eq (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  b = isequal (x1, x2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/ge.m",
    "content": "function b = ge (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  b = (x1(1) >= x2(1));\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/get.m",
    "content": "function v = get (s, propName)\n\n  switch (propName)\n    case 'gick'\n      v = s.gick;\n    otherwise\n      error ([propName, ' is not a valid Snork property']);\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/getStash.m",
    "content": "function out = getStash (l)\n\n  out = myStash ();\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/gick.m",
    "content": "function out = gick (in, val)\n\n  if (nargin == 1)\n    out = in.gick;\n  else\n    in.gick = val;\n    out = in;\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/gt.m",
    "content": "function b = gt (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  b = (x1(1) > x2(1));\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/horzcat.m",
    "content": "function s = horzcat (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork ([x1 x2]);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/ldivide.m",
    "content": "function s = ldivide (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork(x1 .\\ x2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/le.m",
    "content": "function b = le (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  b = (x1(1) <= x2(1));\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/loadobj.m",
    "content": "function out = loadobj (in)\n\n  out = in;\n  out.cack = [-1 -2 -3 -4];\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/lt.m",
    "content": "function b = lt (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  b = (x1(1) < x2(1));\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/minus.m",
    "content": "function s = minus (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork (x1 - x2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/mldivide.m",
    "content": "function s = mldivide (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork (x1 \\ x2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/mpower.m",
    "content": "function s = mpower (s1, x)\n\n  if (~isa (s1, 'Snork') || isa (x, 'Snork'))\n    error ('mpower Snork!!!');\n  end\n\n  s = s1;\n  s.gick = s.gick ^ x;\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/mrdivide.m",
    "content": "function s = mrdivide (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork (x1 / x2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/mtimes.m",
    "content": "function s = mtimes (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork (x1 * x2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/ne.m",
    "content": "function b = ne (s1, s2)\n\n  b = ~(s1 == s2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/plus.m",
    "content": "function s = plus (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork (x1 + x2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/power.m",
    "content": "function s = power (s1, x)\n\n  if (~isa (s1, 'Snork') || isa (x, 'Snork'))\n    error ('power Snork!!!');\n  end\n\n  s = s1;\n  s.gick = s.gick .^ x;\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/private/myStash.m",
    "content": "function out = myStash ()\n\n  out = 1;\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/rdivide.m",
    "content": "function s = rdivide (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork(x1 ./ x2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/saveobj.m",
    "content": "function out = saveobj (in)\n\n  out = in;\n  out.cack = [];\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/set.m",
    "content": "function s = set (s, varargin)\n\n  propArgs = varargin;\n  while (length (propArgs) >= 2)\n    propName  = propArgs{1};\n    propValue = propArgs{2};\n    propArgs  = propArgs(3:end);\n    switch (propName)\n      case 'gick'\n        s.gick = propValue;\n      otherwise\n        error ([propName, ' is not a valid Snork property']);\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/subsasgn.m",
    "content": "function snk = subsasgn (snk, s, val)\n\n  if (length (s) < 1)\n    error ('Snork: needs index');\n  end\n  switch (s(1).type)\n    case '()'\n      ind = s(1).subs;\n      if (numel (ind) ~= 1)\n        error ('Snork: need exactly one index');\n      else\n        if (length (s) == 1)\n          snk.cack(ind{1}) = val;\n        else\n          error ('Snork: chained subscripts not allowed for {}');\n        end\n      end\n    case '{}'\n      ind = s(1).subs;\n      if (numel (ind) ~= 1)\n        error ('Snork: need exactly one index');\n      else\n        if (length (s) == 1)\n          snk.cack(ind{1}) = val;\n        else\n          error ('Snork: chained subscripts not allowed for {}');\n        end\n      end\n    case '.'\n      fld = s(1).subs;\n      if (strcmp (fld, 'gick'))\n        snk.gick = val;\n      else\n        error ('Snork/subsasgn: invalid property \\\"%s\\\"', fld);\n      end\n    otherwise\n      error ('invalid subscript type');\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/subsindex.m",
    "content": "function out = subsindex (obj)\n\n  out = 0;\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/subsref.m",
    "content": "function b = subsref (snk, s)\n\n  if (isempty (s))\n    error ('Snork: missing index');\n  end\n  switch (s(1).type)\n    case '()'\n      ind = s(1).subs;\n      if (numel (ind) ~= 1)\n        error ('Snork: need exactly one index');\n      else\n        b = snk.cack(ind{1});\n      end\n    case '{}'\n      ind = s(1).subs;\n      if (numel (ind) ~= 1)\n        error ('Snork: need exactly one index');\n      else\n        b = snk.cack(ind{1});\n      end\n    case '.'\n      fld = s.subs;\n      if (strcmp (fld, 'gick'))\n        b = snk.gick;\n      else\n        error ('Snork/subsref: invalid property \\\"%s\\\"', fld);\n      end\n    otherwise\n      error ('invalid subscript type');\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/tattack.m",
    "content": "function s = tattack (x, y)\n\n  s = 'Snork';\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/times.m",
    "content": "function s = times (s1, s2, s3)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork (x1 .* x2);\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/transpose.m",
    "content": "function s = transpose (s)\n\n  x = double (s);\n\n  s = Snork (x.' + 2);  % +2 To make sure some non-standard tranpose is called.\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/uminus.m",
    "content": "function s = uminus (s1)\n\n  s = s1;\n  s.gick = - s.gick;\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/uplus.m",
    "content": "function s = uplus (s1)\n\n  s = s1;\n\nend\n"
  },
  {
    "path": "test/classes/@Snork/vertcat.m",
    "content": "function s = vertcat (s1, s2)\n\n  x1 = double (s1);\n  x2 = double (s2);\n\n  s = Snork ([x1; x2]);\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/Spork.m",
    "content": "function s = Spork (geek)\n%% Test class.\n\n    if (nargin == 1 && isa (geek, 'Spork'))\n      s = geek;\n    else\n      s.cack = [-1 -2 -3 -4];\n      if (nargin == 0)\n        s.geek = 1;\n      else\n        s.geek = geek;\n      end\n      s = class (s, 'Spork');\n    end\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/cack.m",
    "content": "function out = cack (in)\n\n  out = in.cack;\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/display.m",
    "content": "function display (s)\n\n  disp ([inputname(1),'.geek = ']);\n  disp (' ');\n  disp (s.geek);\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/geek.m",
    "content": "function out = geek (in, val)\n\n  if (nargin == 1)\n    out = in.geek;\n  else\n    in.geek = val;\n    out = in;\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/get.m",
    "content": "function v = get (s, propName)\n\n  switch (propName)\n    case 'geek'\n      v = s.geek;\n    otherwise\n      error ([propName, ' is not a valid Spork property']);\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/getStash.m",
    "content": "function out = getStash (cls)\n\n  out = myStash ();\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/loadobj.m",
    "content": "function out = loadobj (in)\n\n  out = in;\n  if (~isa (in, 'Spork'))\n    out.cack = [];\n  end\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/private/myStash.m",
    "content": "function out = myStash ()\n\n  out = 3;\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/saveobj.m",
    "content": "function out = saveobj (in)\n\n  out = in;\n  %rmfield (out,'cack');\n\nend\n"
  },
  {
    "path": "test/classes/@Spork/set.m",
    "content": "function s = set (s, varargin)\n\n  propArgs = varargin;\n  while (length (propArgs) >= 2)\n    propName  = propArgs{1};\n    propValue = propArgs{2};\n    propArgs  = propArgs(3:end);\n    switch (propName)\n      case 'geek'\n        s.geek = propValue;\n      otherwise\n        error ([propName, ' is not a valid Spork property']);\n    end\n  end\n\nend\n"
  },
  {
    "path": "test/classes/classes.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%% Test script for legacy OOP.\n%% Requires the path to contain the test classes.\n%%\n%% Note: This script and all classes are also intended to run\n%%       in MATLAB to test compatibility.  Don't break that!\n%%\n%%       Note(JBect, 2013/01/27) : in order to ease to process of testing\n%%       Matlab compatibility, the syntax assert(observed, expected) should\n%%       be avoided.  I use assert(isequal(observed, expected) instead.\n%%\n%% FIXME: This script tests to ensure that things done correctly work\n%%        corrrectly.  It should also check that things done incorrectly\n%%        error properly.\n%%\n%% The classes used for the tests reside in the test directory.\n%%\n%% The classes provide the ability to test most of the major features\n%% of the legacy OOP facilities.  There are a number of classes, mostly\n%% kind of the same, that create a hierarchy.\n\n%% Test the Snork class.  The Snork class has a number of the standard\n%% methods that the others don't so we can test indexing and other\n%% features.\n%!shared snk, snk1, snk2\n%!test snk = Snork ();\n%! assert (isequal (gick (snk), 1));\n%! assert (isequal (snk.gick, 1));\n%! assert (isequal (snk(2), 1));\n%! assert (isequal (snk{end}, 3));\n%!test snk = gick (snk, 2);\n%! assert (isequal (gick (snk), 2));\n%!test snk = set (snk, 'gick', 7);\n%! assert (isequal (get (snk, 'gick'), 7));\n%!test snk.gick = 4;\n%! assert (isequal (gick (snk),4));\n%!  snk(1) = 3;\n%!test snk{end} = 9;\n%! assert (isequal (cack (snk), [3 1 2 9]));\n%! assert (isequal (getStash (snk), 1));             % Check private functions.\n%! assert (isobject (snk));\n%! assert (isequal (class (snk), 'Snork'));\n%! assert (isa (snk, 'Snork'));\n%! assert (! isa (snk, 'Sneetch'));\n%! assert (ismethod (snk, 'gick'));\n%! assert (! ismethod (snk, 'bletch'));\n%! assert (exist ('snk') == 1);\n%! assert (exist ('blink') == 0);\n%!test snk1 = Snork (snk);\n%! assert (isequal (class (snk1), 'Snork'));\n%! assert (isequal (gick (snk1), 4));\n%!test snk2 = Snork (-3);\n%! assert (isequal (class (snk2), 'Snork'));\n%! assert (isequal (gick (snk2), -3));\n%!test x = [1 2 3 4];\n%! assert (isequal (x(snk), 1));\n\n%% x = methods ('Snork');                % Need to test the methods function.\n%% save temp snk;\n%% load temp                             % This load causes a segfault.\n%% assert (isequal (cack(snk), [-1 -2 -3 -4]));      % This is a major bug!\n\n%% The Spork class is a near clone of Snork but without as many standard\n%% methods.  We are testing no new octave features, but this is makes\n%% sure that we haven't bollixed up the Spork class if we should make\n%% changes.  We use Spork in the class hierarchy.\n%!shared sprk\n%!test sprk = Spork ();\n%! assert (isequal (geek (sprk), 1));\n%!test sprk = geek (sprk, 3);\n%! assert (isequal (geek (sprk), 3));\n%!test sprk = set (sprk,'geek',7);\n%! assert (isequal (get (sprk, 'geek'), 7));\n%! assert (isequal (class (sprk), 'Spork'));\n%! assert (isa (sprk, 'Spork'));\n\n%%  The Blork class is a near clone of Snork but without as many standard\n%%  methods.  We are testing no new octave features, but this is makes\n%%  sure that we haven't bollixed up the Blork class if we should make\n%%  changes.  We use Blork in the class hierarchy.\n%!shared blrk\n%!test blrk = Blork ();\n%! assert (isequal (bleek(blrk), 1));\n%!test blrk = bleek (blrk, 3);\n%! assert (isequal (bleek (blrk), 3));\n%!test blrk = set (blrk, 'bleek', 13);\n%! assert (isequal (get (blrk, 'bleek'), 13));\n%! assert (isequal (class (blrk), 'Blork'));\n%! assert (isa (blrk, 'Blork'));\n\n%%  The Cork class is a near clone of Snork but without as many standard\n%%  methods.  We are testing no new octave features, but this is makes\n%%  sure that we haven't bollixed up the Cork class if we should make\n%%  changes.  We use Cork in the class hierarchy.\n%!shared crk\n%!test crk = Cork (23);\n%! assert (isequal (click(crk), 23));\n%!test crk = click(crk,3);\n%! assert (isequal (click(crk), 3));\n%!test crk = set (crk, 'click', 13);\n%! assert (isequal (get (crk, 'click'), 13));\n%! assert (isequal (class (crk), 'Cork'));\n%! assert (isa (crk, 'Cork'));\n\n%%  The Dork class tests single inheritance.\n%!shared drk\n%!test drk = Dork ();\n%! assert (isequal (gack (drk),0));\n%!test drk = gack (drk,-2);\n%! assert (isequal (gack (drk),-2));\n%!test drk = gick (drk,2);\n%! assert (isequal (gick (drk),2));\n%!test drk = set (drk, 'gick',3, 'gack',-3);\n%! assert (isequal (get (drk, 'gick'), 3));\n%! assert (isequal (get (drk, 'gack'), -3));\n%! assert (isequal (class (drk), 'Dork'));\n%! assert (isa (drk, 'Dork'));\n%! assert (isa (drk, 'Snork'));\n%! assert (isequal (getStash (drk), 2));\n%!test drk1 = Dork (drk);\n%! assert (isequal (class (drk1), 'Dork'));\n%! assert (isa (drk1, 'Snork'));\n%! assert (isequal (gick (drk1), 3));\n%! assert (isequal (gack (drk1), -3));\n%!test drk2 = Dork (-4, 4);\n%! assert (isequal (class (drk2), 'Dork'));\n%! assert (isa (drk2, 'Snork'));\n%! assert (isequal (gick (drk2), -4));\n%! assert (isequal (gack (drk2), 4));\n\n%%  The Pork class is essentially a clone of Dork.  It is used as part\n%%  of the multiple inheritance test.\n%!shared prk, drk\n%!test prk = Pork ();\n%! assert (isequal (geek (prk), 1));\n%! assert (isequal (gurk (prk), 0));\n%!test prk = gurk (prk,-3);\n%! assert (isequal (gurk (prk), -3));\n%!test prk = geek (prk,9);\n%! assert (isequal (geek (prk), 9));\n%! assert (isequal (class (prk), 'Pork'));\n%! assert (isa (prk, 'Pork'));\n%! assert (isa (prk, 'Spork'));\n%!test drk = Dork ();                   % Precedence.\n%! assert (isequal (bling (drk, prk), 2));\n%! assert (isequal (bling (prk, drk), 2));\n\n%%  The Gork class tests aggregation and multiple inheritance.\n%!shared grk\n%!test grk = Gork ();\n%! assert (isequal (gick (grk), 1));\n%! assert (isequal (geek (grk), 1));\n%! assert (isequal (gack (grk), 0));\n%! assert (isequal (gurk (grk), 0));\n%! assert (isequal (bleek (grk), 1));\n%! assert (isequal (gark(grk), -2));\n%! assert (isequal (click (cork (grk)), 17));\n%! assert (isequal (class (cork (grk)), 'Cork'));\n%!test grk = gick (grk, 3);\n%!test grk = geek (grk, 4);\n%!test grk = gack (grk, -9);\n%!test grk = gurk (grk, -8);\n%!test grk = bleek (grk, -7);\n%!test grk = gark (grk, -6);\n%!test grk = cork (grk, click (cork (grk), 23));\n%! assert (isequal (gick (grk), 3));\n%! assert (isequal (geek (grk), 4));\n%! assert (isequal (gack (grk), -9));\n%! assert (isequal (gurk (grk), -8));\n%! assert (isequal (bleek (grk), -7));\n%! assert (isequal (gark (grk), -6));\n%! assert (isequal (click (cork (grk)), 23));\n%!test\n%! cork1 = Cork (13);\n%! grk = set (grk, 'gick', -5, 'gack', -6, 'gark', -7, 'cork', cork1);\n%! assert (isequal (get (grk, 'gick'), -5));\n%! assert (isequal (get (grk, 'gack'), -6));\n%! assert (isequal (get (grk, 'gark'), -7));\n%! assert (isequal (click(get (grk, 'cork')), 13));\n%!test grk = set (grk, 'cork', 12);\n%! assert (isequal (click(get (grk, 'cork')),12));\n%! assert (isequal (class (cork(grk)), 'Cork'));\n%! assert (isequal (class (grk), 'Gork'));\n%! assert (isa (grk, 'Gork'));\n%! assert (isa (grk, 'Dork'));\n%! assert (isa (grk, 'Pork'));\n%! assert (isa (grk, 'Blork'));\n%! assert (isa (grk, 'Snork'));\n%! assert (isa (grk, 'Spork'));\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%% Testing (some) overloaded operators %%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n%% Common variables for testing overloaded operators\n%!shared x1, x2, x3, s1, s2, s3\n%!  x1 = 1 + rand (3);    s1 = Snork (x1);\n%!  x2 = 1 + rand (3);    s2 = Snork (x2);\n%!  x3 = diag ([1 2 3]);  s3 = Snork (x3);\n\n%% Test overloaded plus (+) and uplus (unitary +) for the Snork class\n%!test  s = s1 + s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 + x2));\n%!test  s = s1 + x2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 + x2));\n%!test  s = x1 + s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 + x2));\n%!test  s = +s1;      assert (isequal (s, s1));\n\n%% Test overloaded minus (-) for the Snork class\n%!test  s = s1 - s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 - x2));\n%!test  s = s1 - x2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 - x2));\n%!test  s = x1 - s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 - x2));\n%!test  s = -s1;      assert (isequal (s, Snork (-x1)));\n\n%% Test overloaded mtimes (*) for the Snork class\n%!test  s = s1 * s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 * x2));\n%!test  s = s1 * x2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 * x2));\n%!test  s = x1 * s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 * x2));\n\n%% Test overloaded times (.*) for the Snork class\n%!test  s = s1 .* s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 .* x2));\n%!test  s = s1 .* x2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 .* x2));\n%!test  s = x1 .* s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 .* x2));\n\n%% Test overloaded mpower (^) for the Snork class\n%!test  s = s1 ^ 3;   assert (isa (s, 'Snork') && isequal (s.gick, x1 ^ 3));\n%!error <mpower Snork!!!>  s = s1 ^ s1\n%!error <mpower Snork!!!>  s = 20 ^ s1\n\n%% Test overloaded power (.^) for the Snork class\n%!test  s = s1 .^ 2;   assert (isa (s, 'Snork') && isequal (s.gick, x1 .^ 2));\n%!error <power Snork!!!>  s = s1 .^ s1\n%!error <power Snork!!!>  s = 20 .^ s1\n\n%% Test overloaded rdivide (./) for the Snork class\n%!test  s = s1 ./ s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 ./ x2));\n%!test  s = s1 ./ x2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 ./ x2));\n%!test  s = x1 ./ s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 ./ x2));\n\n%% Test overloaded ldivide (.\\) for the Snork class\n%!test  s = s1 .\\ s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 .\\ x2));\n%!test  s = s1 .\\ x2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 .\\ x2));\n%!test  s = x1 .\\ s2;  assert (isa (s, 'Snork') && isequal (s.gick, x1 .\\ x2));\n\n%% Test overloaded mrdivide (/) for the Snork class\n%!test  s = s1 / s3;  assert (isa (s, 'Snork') && isequal (s.gick, x1 / x3));\n%!test  s = s1 / x3;  assert (isa (s, 'Snork') && isequal (s.gick, x1 / x3));\n%!test  s = x1 / s3;  assert (isa (s, 'Snork') && isequal (s.gick, x1 / x3));\n\n%% Test overloaded mldivide (\\) for the Snork class\n%!test  s = s3 \\ s2;  assert (isa (s, 'Snork') && isequal (s.gick, x3 \\ x2));\n%!test  s = s3 \\ x2;  assert (isa (s, 'Snork') && isequal (s.gick, x3 \\ x2));\n%!test  s = x3 \\ s2;  assert (isa (s, 'Snork') && isequal (s.gick, x3 \\ x2));\n\n%% Test overloaded eq (==) for the Snork class\n%!assert (s1 == s1)\n%!assert (s1 == x1)\n%!assert (x1 == s1)\n%!assert (~(s1 == (s1 + 1)))\n%!assert (~(s1 == (x1 + 1)))\n%!assert (~(x1 == (s1 + 1)))\n\n%% Test overloaded ne (~=) for the Snork class\n%!assert (~(s1 ~= s1))\n%!assert (~(s1 ~= x1))\n%!assert (~(x1 ~= s1))\n%!assert (s1 ~= (s1 + 1))\n%!assert (x1 ~= (s1 + 1))\n%!assert (s1 ~= (x1 + 1))\n\n%% Test overloaded lt (<) for the Snork class\n%!assert (s1 < (s1 + 1))\n%!assert (s1 < (x1 + 1))\n%!assert (x1 < (s1 + 1))\n\n%% Test overloaded gt (>) for the Snork class\n%!assert (s1 > (s1 - 1))\n%!assert (s1 > (x1 - 1))\n%!assert (x1 > (s1 - 1))\n\n%% Test overloaded lt (<=) for the Snork class\n%!assert (s1 <= (s1 + 1))\n%!assert (s1 <= (x1 + 1))\n%!assert (x1 <= (s1 + 1))\n\n%% Test overloaded gt (>=) for the Snork class\n%!assert (s1 >= (s1 - 1))\n%!assert (s1 >= (x1 - 1))\n%!assert (x1 >= (s1 - 1))\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%% Testing concatenation and transposition %%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n%% Test overloaded (c)transpose for the Snork class\n%!assert (isequal (s1',  Snork (double (s1)'  + 4)))  % +4 is intentional\n%!assert (isequal (s1.', Snork (double (s1).' + 2)))  % +2 is intentional\n\n%% Test overloaded vertcat() for the Snork class\n%!test <*38128>\n%! s = [s1; s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2]));\n%!test <*38128>\n%! s = [s1; x2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2]));\n%!test <*38128>\n%! s = [x1; s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2]));\n\n%% Test overloaded horzcat() for the Snork class\n%!test <*38128>\n%! s = [s1 s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2]));\n%!test <*38128>\n%! s = [s1 x2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2]));\n%!test <*38128>\n%! s = [x1 s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2]));\n\n%% Test with the Blork class, where neither ctranspose(), transpose(),\n%% vertcat() nor horzcat() is overloaded\n%!shared x1, x2, x3\n%!test x1 = Blork ();\n%!test x2 = [x1 x1];\n%!assert (isa (x2, 'Blork') && isequal (size (x2), [1 2]))\n%!test x2 = [x1 51];\n%!assert (isa (x2, 'Blork') && isequal (size (x2), [1 2]))\n%!test x3 = [x2; x2];\n%!assert (isa (x3, 'Blork') && isequal (size (x3), [2 2]))\n%!test x3 = [x2; [51 x1]];\n%!assert (isa (x3, 'Blork') && isequal (size (x3), [2 2]))\n%!error <dimension mismatch> x4 = [x1, x3]\n%!error <dimension mismatch> x4 = [x1; x3]\n%!test x2 = [x1 x1];\n%!assert (isequal (x2',  [x1; x1]) && isequal (size (x2'),  [2 1]))\n%!assert (isequal (x2.', [x1; x1]) && isequal (size (x2.'), [2 1]))\n\n%%%%%%%%%%%%%%%%%%%%%%%%\n%% Testing precedence %%\n%%%%%%%%%%%%%%%%%%%%%%%%\n\n%% default: leftmost or superior class (bug #42735) object wins\n%!shared A, B\n%!test A = Snork (rand (2));\n%!test B = CPrecedenceTester1 ();  % no call to inferiorto/superiorto\n%!assert (isequal (tattack (A, B), 'Snork'))\n%!assert (isequal (tattack (B, A), 'CPrecedenceTester1'))  % idem\n%!assert <*42735> (isequal (class (A + B), 'Snork'))\n%!assert <*42735> (isequal (B + A, 'CPrecedenceTester1'))  % idem\n\n%!shared A, B\n%!test A = Snork (rand (2));\n%!test B = CPrecedenceTester2 (1);  % CPrecedenceTester2 > Snork\n%!assert (isequal (tattack (A, B), 'CPrecedenceTester2'))\n%!assert (isequal (tattack (B, A), 'CPrecedenceTester2'))\n%!assert <*42735> (isequal (A + B, 'CPrecedenceTester2'))\n%!assert <*42735> (isequal (B + A, 'CPrecedenceTester2'))\n%% Trying to change to CPrecendenceTester < Snork\n%!error D = CPrecedenceTester2 (2)\n\n%!shared A, B\n%!test A = Snork (rand (2));\n%!test B = CPrecedenceTester3 (2);  % CPrecedenceTester3 < Snork\n%!assert (isequal (tattack (A, B), 'Snork'))\n%!assert (isequal (tattack (B, A), 'Snork'))\n%!assert <*42735> (isequal (class (A + B), 'Snork'))\n%!assert <*42735> (isequal (class (B + A), 'Snork'))\n%% Trying to change to CPrecendenceTester3 > Snork\n%!error D = CPrecedenceTester3 (1)\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%% Testing overridden size+numel method     %%\n%% (builtin size method and similar methods %%\n%% use the size of the struct container)    %%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n%!shared st\n%!test st = SizeTester ([1 1]);\n%! assert (isequal (size (st), [1 1]));\n%! assert (isequal (numel (st), 1));\n%!assert (isequal (ndims (st), 2))\n%!assert (isequal (rows (st), 1))\n%!assert (isequal (columns (st), 1))\n%!assert (isequal (st, st))\n%!assert (isscalar (st))\n%!assert (isvector (st))\n\n%!test st = SizeTester ([1 2]);\n%! assert (isequal (size (st), [1 2]));\n%! assert (isequal (numel (st), 2));\n%!assert (isequal (ndims (st), 2))\n%!assert (isequal (rows (st), 1))\n%!assert <*51308> (isequal (columns (st), 2))\n%!assert <*44334> (isequal (st, st))\n%!assert <*44498> (not (isscalar (st)))\n%!assert (isvector (st))\n\n%!test st = SizeTester ([2 3]);\n%! assert (isequal (size (st), [2 3]));\n%! assert (isequal (numel (st), 6));\n%!assert (isequal (ndims (st), 2))\n%!assert <*51308> (isequal (rows (st), 2))\n%!assert <*51308> (isequal (columns (st), 3))\n%!assert <*44334> (isequal (st, st))\n%!assert <*44498> (not (isscalar (st)))\n%!assert <*44498> (not (isvector (st)))\n\n%!test st = SizeTester ([2 3 4]);\n%! assert (isequal (size (st), [2 3 4]));\n%! assert (isequal (numel (st), 24));\n%!assert <*51308> (isequal (ndims (st), 3))\n%!assert <*51308> (isequal (rows (st), 2))\n%!assert <*51308> (isequal (columns (st), 3))\n%!assert <*44334> (isequal (st, st))\n%!assert <*44498> (not (isscalar (st)))\n%!assert <*44498> (not (isvector (st)))\n"
  },
  {
    "path": "test/classes/module.mk",
    "content": "class_Blork_TEST_FILES = \\\n  %reldir%/@Blork/Blork.m \\\n  %reldir%/@Blork/bleek.m \\\n  %reldir%/@Blork/display.m \\\n  %reldir%/@Blork/get.m \\\n  %reldir%/@Blork/set.m\n\nclass_Cork_TEST_FILES = \\\n  %reldir%/@Cork/Cork.m \\\n  %reldir%/@Cork/click.m \\\n  %reldir%/@Cork/display.m \\\n  %reldir%/@Cork/get.m \\\n  %reldir%/@Cork/set.m\n\nclass_Dork_TEST_FILES = \\\n  %reldir%/@Dork/Dork.m \\\n  %reldir%/@Dork/bling.m \\\n  %reldir%/@Dork/display.m \\\n  %reldir%/@Dork/gack.m \\\n  %reldir%/@Dork/get.m \\\n  %reldir%/@Dork/getStash.m \\\n  %reldir%/@Dork/private/myStash.m \\\n  %reldir%/@Dork/set.m\n\nclass_Gork_TEST_FILES = \\\n  %reldir%/@Gork/Gork.m \\\n  %reldir%/@Gork/cork.m \\\n  %reldir%/@Gork/display.m \\\n  %reldir%/@Gork/gark.m \\\n  %reldir%/@Gork/get.m \\\n  %reldir%/@Gork/set.m \\\n  %reldir%/@Gork/subsasgn.m \\\n  %reldir%/@Gork/subsref.m\n\nclass_Pork_TEST_FILES = \\\n  %reldir%/@Pork/Pork.m \\\n  %reldir%/@Pork/bling.m \\\n  %reldir%/@Pork/display.m \\\n  %reldir%/@Pork/get.m \\\n  %reldir%/@Pork/gurk.m \\\n  %reldir%/@Pork/private/myStash.m \\\n  %reldir%/@Pork/set.m\n\nclass_Sneetch_TEST_FILES = \\\n  %reldir%/@Sneetch/Sneetch.m \\\n  %reldir%/@Sneetch/display.m\n\nclass_Snork_TEST_FILES = \\\n  %reldir%/@Snork/Snork.m \\\n  %reldir%/@Snork/cack.m \\\n  %reldir%/@Snork/ctranspose.m \\\n  %reldir%/@Snork/display.m \\\n  %reldir%/@Snork/double.m \\\n  %reldir%/@Snork/end.m \\\n  %reldir%/@Snork/eq.m \\\n  %reldir%/@Snork/ge.m \\\n  %reldir%/@Snork/get.m \\\n  %reldir%/@Snork/getStash.m \\\n  %reldir%/@Snork/gick.m \\\n  %reldir%/@Snork/gt.m \\\n  %reldir%/@Snork/horzcat.m \\\n  %reldir%/@Snork/ldivide.m \\\n  %reldir%/@Snork/le.m \\\n  %reldir%/@Snork/loadobj.m \\\n  %reldir%/@Snork/lt.m \\\n  %reldir%/@Snork/minus.m \\\n  %reldir%/@Snork/mldivide.m \\\n  %reldir%/@Snork/mpower.m \\\n  %reldir%/@Snork/mrdivide.m \\\n  %reldir%/@Snork/mtimes.m \\\n  %reldir%/@Snork/ne.m \\\n  %reldir%/@Snork/plus.m \\\n  %reldir%/@Snork/power.m \\\n  %reldir%/@Snork/private/myStash.m \\\n  %reldir%/@Snork/rdivide.m \\\n  %reldir%/@Snork/saveobj.m \\\n  %reldir%/@Snork/set.m \\\n  %reldir%/@Snork/subsasgn.m \\\n  %reldir%/@Snork/subsindex.m \\\n  %reldir%/@Snork/subsref.m \\\n  %reldir%/@Snork/tattack.m \\\n  %reldir%/@Snork/times.m \\\n  %reldir%/@Snork/transpose.m \\\n  %reldir%/@Snork/uminus.m \\\n  %reldir%/@Snork/uplus.m \\\n  %reldir%/@Snork/vertcat.m\n\nclass_Spork_TEST_FILES = \\\n  %reldir%/@Spork/Spork.m \\\n  %reldir%/@Spork/cack.m \\\n  %reldir%/@Spork/display.m \\\n  %reldir%/@Spork/geek.m \\\n  %reldir%/@Spork/get.m \\\n  %reldir%/@Spork/getStash.m \\\n  %reldir%/@Spork/loadobj.m \\\n  %reldir%/@Spork/private/myStash.m \\\n  %reldir%/@Spork/saveobj.m \\\n  %reldir%/@Spork/set.m\n\nclass_CPrecedenceTester1_TEST_FILES = \\\n  %reldir%/@CPrecedenceTester1/CPrecedenceTester1.m \\\n  %reldir%/@CPrecedenceTester1/double.m \\\n  %reldir%/@CPrecedenceTester1/plus.m \\\n  %reldir%/@CPrecedenceTester1/tattack.m\n\nclass_CPrecedenceTester2_TEST_FILES = \\\n  %reldir%/@CPrecedenceTester2/CPrecedenceTester2.m \\\n  %reldir%/@CPrecedenceTester2/double.m \\\n  %reldir%/@CPrecedenceTester2/plus.m \\\n  %reldir%/@CPrecedenceTester2/tattack.m\n\nclass_CPrecedenceTester3_TEST_FILES = \\\n  %reldir%/@CPrecedenceTester3/CPrecedenceTester3.m \\\n  %reldir%/@CPrecedenceTester3/double.m \\\n  %reldir%/@CPrecedenceTester3/plus.m \\\n  %reldir%/@CPrecedenceTester3/tattack.m\n\nclass_SizeTester_TEST_FILES = \\\n  %reldir%/@SizeTester/SizeTester.m \\\n  %reldir%/@SizeTester/numel.m \\\n  %reldir%/@SizeTester/size.m\n\nclasses_TEST_FILES = \\\n  $(class_Blork_TEST_FILES) \\\n  $(class_Cork_TEST_FILES) \\\n  $(class_Dork_TEST_FILES) \\\n  $(class_Gork_TEST_FILES) \\\n  $(class_Pork_TEST_FILES) \\\n  $(class_Sneetch_TEST_FILES) \\\n  $(class_Snork_TEST_FILES) \\\n  $(class_Spork_TEST_FILES) \\\n  $(class_CPrecedenceTester1_TEST_FILES) \\\n  $(class_CPrecedenceTester2_TEST_FILES) \\\n  $(class_CPrecedenceTester3_TEST_FILES) \\\n  $(class_SizeTester_TEST_FILES) \\\n  %reldir%/classes.tst\n\nTEST_FILES += $(classes_TEST_FILES)\n"
  },
  {
    "path": "test/colon-op/@legacy_colon_op/colon.m",
    "content": "function r = colon (a, b, c)\n  if (nargin == 2)\n    r = sprintf (\"%s:%s\", class (a), class (b));\n  else\n    r = sprintf (\"%s:%s:%s\", class (a), class (b), class (c));\n  endif\nendfunction\n"
  },
  {
    "path": "test/colon-op/@legacy_colon_op/legacy_colon_op.m",
    "content": "function obj = legacy_colon_op ()\n  obj = class (struct (), \"legacy_colon_op\");\nendfunction\n"
  },
  {
    "path": "test/colon-op/colon-op.tst",
    "content": "%!test\n%! x = colon_op ();\n%! assert (x:2:3, \"colon_op:double:double\");\n%! assert (1:x:3, \"double:colon_op:double\");\n%! assert (1:2:x, \"double:double:colon_op\");\n%! assert (x:x:3, \"colon_op:colon_op:double\");\n%! assert (1:x:x, \"double:colon_op:colon_op\");\n%! assert (x:2:x, \"colon_op:double:colon_op\");\n%! assert (x:x:x, \"colon_op:colon_op:colon_op\");\n%! assert (x:2, \"colon_op:double\");\n%! assert (1:x, \"double:colon_op\");\n%! assert (x:x, \"colon_op:colon_op\");\n\n%!test\n%! x = legacy_colon_op ();\n%! assert (x:2:3, \"legacy_colon_op:double:double\");\n%! assert (1:x:3, \"double:legacy_colon_op:double\");\n%! assert (1:2:x, \"double:double:legacy_colon_op\");\n%! assert (x:x:3, \"legacy_colon_op:legacy_colon_op:double\");\n%! assert (1:x:x, \"double:legacy_colon_op:legacy_colon_op\");\n%! assert (x:2:x, \"legacy_colon_op:double:legacy_colon_op\");\n%! assert (x:x:x, \"legacy_colon_op:legacy_colon_op:legacy_colon_op\");\n%! assert (x:2, \"legacy_colon_op:double\");\n%! assert (1:x, \"double:legacy_colon_op\");\n%! assert (x:x, \"legacy_colon_op:legacy_colon_op\");\n"
  },
  {
    "path": "test/colon-op/colon_op.m",
    "content": "classdef colon_op\n  methods\n    function r = colon (a, b, c)\n      if (nargin == 2)\n        r = sprintf (\"%s:%s\", class (a), class (b));\n      else\n        r = sprintf (\"%s:%s:%s\", class (a), class (b), class (c));\n      endif\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/colon-op/module.mk",
    "content": "colon_op_TEST_FILES = \\\n  %reldir%/@legacy_colon_op/colon.m \\\n  %reldir%/@legacy_colon_op/legacy_colon_op.m \\\n  %reldir%/colon-op.tst \\\n  %reldir%/colon_op.m\n\nTEST_FILES += $(colon_op_TEST_FILES)\n"
  },
  {
    "path": "test/colormaps.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## This is a test that should be used on all Octave colormaps.\n## Because there is no function to get a list of all colormap\n## functions, they should be added here manually.\n\n%!test\n%! hf = figure (\"visible\", \"off\");\n%! unwind_protect\n%!   all_colormaps = {@autumn, @bone, @cool, @copper, @cubehelix, ...\n%!                    @flag, @gray, @hot, @hsv, @jet, @lines, @ocean, ...\n%!                    @pink, @prism, @rainbow, @spring, @summer, ...\n%!                    @viridis, @white, @winter};\n%!\n%!   for i = 1:numel (all_colormaps)\n%!     f = all_colormaps{i};\n%!\n%!     assert (iscolormap (f (1)));\n%!     assert (iscolormap (f (12)));\n%!     assert (iscolormap (f (200)));\n%!\n%!     ## bug #44070\n%!     assert (class (f (uint8 (12))), \"double\");\n%!     assert (iscolormap (f (uint8 (12))));\n%!\n%!     assert (f (0), zeros (0, 3));\n%!   endfor\n%! unwind_protect_cleanup\n%!   close (hf);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/command.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2014-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Don't alter the spacing in the command_test lines.  These are\n## specifically testing for possible differences in things like\n##   A(X) or A( X ) or A (X) or A ( X )\n\n%!function command_test (varargin)\n%!  assignin ('caller', 'cmd_out', ['|', sprintf('%s|', varargin{:})]);\n%!endfunction\n\n%!function gobble_command (varargin)\n%!endfunction\n\n## 0, 1, 2, 3 simple arguments\n%!test\n%! command_test\n%! assert (cmd_out, '|');\n%!test\n%! command_test a\n%! assert (cmd_out, '|a|');\n%!test\n%! command_test aa     b\n%! assert (cmd_out, '|aa|b|');\n%!test\n%! command_test aaa  bb    c\n%! assert (cmd_out, '|aaa|bb|c|');\n\n## continuation\n%!test\n%! command_test a...\n%!  bb ccc\n%! assert (cmd_out, '|a|bb|ccc|');\n%!test\n%! command_test a ...\n%!  bb ccc\n%! assert (cmd_out, '|a|bb|ccc|');\n%!test\n%! command_test aa(...\n%!  bb cc\n%! assert (cmd_out, '|aa(|bb|cc|');\n%!test\n%! command_test aa(   ...\n%!  bb cc\n%! assert (cmd_out, '|aa(   |bb|cc|');\n\n## comments\n%!test\n%! command_test aa bb cc%comment\n%! assert (cmd_out, '|aa|bb|cc|');\n%!test\n%! command_test aa bb cc#comment\n%! assert (cmd_out, '|aa|bb|cc|');\n%!test\n%! command_test aa bb cc   %comment\n%! assert (cmd_out, '|aa|bb|cc|');\n%!test\n%! command_test aa bb cc   #comment\n%! assert (cmd_out, '|aa|bb|cc|');\n%!test\n%! command_test aa bb cc(  %comment\n%! assert (cmd_out, '|aa|bb|cc(  |');\n%!test\n%! command_test aa bb cc(  #comment\n%! assert (cmd_out, '|aa|bb|cc(  |');\n\n## semicolons and commas; multiple commands\n%!test\n%! command_test aa bb, gobble_command cc\n%! assert (cmd_out, '|aa|bb|');\n%!test\n%! command_test aa bb ; gobble_command cc\n%! assert (cmd_out, '|aa|bb|');\n%!test\n%! command_test aa bb ; command_test cc dd\n%! assert (cmd_out, '|cc|dd|');\n%!test\n%! command_test aa bb\n%!test\n%! command_test cc dd\n%! assert (cmd_out, '|cc|dd|');\n\n## parenthesis matching\n%!test\n%! command_test aa(bb,cc,dd) ee(ff,gg) hh\n%! assert (cmd_out, '|aa(bb,cc,dd)|ee(ff,gg)|hh|');\n%!test\n%! command_test aa([bb,cc)]\n%! assert (cmd_out, '|aa([bb,cc)]|');\n%!test\n%! command_test aa(,@!$@\"bb\"'cc'\n%! assert (cmd_out, '|aa(,@!$@\"bb\"''cc''|');\n%!test\n%! command_test aa(bb,cc,dd)\n%! assert (cmd_out, '|aa(bb,cc,dd)|');\n%!test\n%! command_test aa( bb,cc,dd )\n%! assert (cmd_out, '|aa( bb,cc,dd )|');\n%!test\n%! command_test aa (bb,cc,dd)\n%! assert (cmd_out, '|aa|(bb,cc,dd)|');\n%!test\n%! command_test aa ( bb,cc,dd )\n%! assert (cmd_out, '|aa|( bb,cc,dd )|');\n%!test\n%! command_test aa(bb, cc, dd)\n%! assert (cmd_out, '|aa(bb, cc, dd)|');\n%!test\n%! command_test aa( bb, cc, dd )\n%! assert (cmd_out, '|aa( bb, cc, dd )|');\n%!test\n%! command_test aa (bb, cc, dd)\n%! assert (cmd_out, '|aa|(bb, cc, dd)|');\n%!test\n%! command_test aa ( bb, cc, dd )\n%! assert (cmd_out, '|aa|( bb, cc, dd )|');\n\n## single and double quotes\n%!test\n%! command_test \"aa\" 'bb' cc\n%! assert (cmd_out, '|aa|bb|cc|');\n%!test\n%! command_test \"aa\"'bb'cc\n%! assert (cmd_out, '|aabbcc|');\n%!test\n%! command_test aa'bb'\"cc\"\n%! assert (cmd_out, '|aabbcc|');\n%!test\n%! command_test \"aa\"bb'cc'\n%! assert (cmd_out, '|aabbcc|');\n\n## CVX-inspired\n%!test\n%! command_test Z(n,n) hermitian toeplitz\n%! assert (cmd_out, '|Z(n,n)|hermitian|toeplitz|');\n%!test\n%! command_test X( n, n ) symmetric\n%! assert (cmd_out, '|X( n, n )|symmetric|');\n%!test\n%! command_test xw( nm-1, nv );\n%! assert (cmd_out, '|xw( nm-1, nv )|');\n%!test\n%! command_test x( sx ) y( sx ) z( sx )\n%! assert (cmd_out, '|x( sx )|y( sx )|z( sx )|');\n%!test\n%! command_test coeffs(deg+1) complex;\n%! assert (cmd_out, '|coeffs(deg+1)|complex|');\n%!test\n%! command_test w( 1, npairs * nv ) v( 1, npairs * nv )\n%! assert (cmd_out, '|w( 1, npairs * nv )|v( 1, npairs * nv )|');\n%!test\n%! command_test w(m,1)   % edge weights\n%! assert (cmd_out, '|w(m,1)|');\n%!test\n%! command_test x2( size ( x ) )\n%! assert (cmd_out, '|x2( size ( x ) )|');\n"
  },
  {
    "path": "test/complex.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Test ordering of complex values by magnitude and then by phase\n%!test\n%! x = [0 i 1+i 2 3i 3+4i];\n%! assert (sort (x, \"descend\"), fliplr (x));\n%! assert (sort (single (x), \"descend\"), fliplr (single (x)));\n\n%!test\n%! x = [1, -1, i, -i];\n%! xs = [-i, 1, i, -1];\n%! assert (sort (x), xs);\n%! assert (sort (x, \"descend\"), fliplr (xs));\n%! assert (sort (single (x)), single (xs));\n%! assert (sort (single (x), \"descend\"), fliplr (single (xs)));\n\n## bug #44071, issorted incorrect because it uses different sort routine.\n%!assert (issorted ([1, -1, i, -i]), false)\n%!assert (issorted (single ([1, -1, i, -i])), false)\n\n## bug #43313, -1 is both '>' and '==' to (-1 - 0i)\n%!test\n%! assert (complex (-1,0) == complex (-1,-0), true);\n%! assert (complex (-1,0) > complex (-1,-0), false);\n%! assert (complex (-1,0) < complex (-1,-0), false);\n\n## Test that sort and issorted both agree on boundary case\n%!test\n%! x = [complex(-1,0), complex(-1,-0), i, -i, 1];\n%! xs = sort (x);\n%! xf = single (x);\n%! xfs = sort (xf);\n%! assert (issorted (xs));\n%! assert (issorted (xfs));\n%! assert (double (xfs), xs);\n\n## Finally, test that sort and issorted agree on NaNs\n%!test\n%! x = [complex(NaN,-1), complex(NaN,NaN), ...\n%!      complex(-1,0), complex(-1,-0), i, -i, 1, ...\n%!      complex(1,NaN)];\n%! xs = sort (x);\n%! xf = single (x);\n%! xfs = sort (xf);\n%! assert (issorted (xs));\n%! assert (issorted (xfs));\n%! assert (double (xfs), xs);\n"
  },
  {
    "path": "test/ctor-vs-method/@derived/derived.m",
    "content": "function r = derived (varargin)\n  __trace__ ('begin derived/derived');\n  r = class (struct (), 'derived', parent ());\n  __trace__ ('end derived/derived');\nend\n"
  },
  {
    "path": "test/ctor-vs-method/@derived/parent.m",
    "content": "function r = parent (a)\n  __trace__ ('begin derived/parent');\n  if (isa (a, 'parent'))\n    r = parent (a.parent);\n  else\n    error ('foo');\n  end\n  __trace__ ('end derived/parent');\nend\n"
  },
  {
    "path": "test/ctor-vs-method/@other/other.m",
    "content": "function r = other (varargin)\n  __trace__ ('begin other/other');\n  r = class (struct (), 'other');\n  __trace__ ('end other/other');\nend\n"
  },
  {
    "path": "test/ctor-vs-method/@other/parent.m",
    "content": "function r = parent (a)\n  __trace__ ('begin other/parent');\n  __trace__ ('end other/parent');\nend\n"
  },
  {
    "path": "test/ctor-vs-method/@parent/method.m",
    "content": "function r = method (a)\n  __trace__ ('begin parent/method');\n  r = parent (a);\n  __trace__ ('end parent/method');\nend\n"
  },
  {
    "path": "test/ctor-vs-method/@parent/parent.m",
    "content": "function rot = parent (a)\n  __trace__ ('begin parent/parent');\n  if (nargin == 0)\n    rot = class (struct (), 'parent');\n  else\n    switch (class (a))\n      case 'parent'\n        %% copy constructor\n        rot = a;\n      otherwise\n        error ('type mismatch in parent constructor');\n    end\n  end\n  __trace__ ('end parent/parent');\nend\n"
  },
  {
    "path": "test/ctor-vs-method/__trace__.m",
    "content": "function r = __trace__ (t)\n  persistent history\n\n  if (isempty (history))\n    history = {};\n  end\n  if (nargin == 0)\n    if (nargout == 0)\n      history = {};\n    else\n      r = history;\n    end\n  elseif (nargin == 1);\n    history = [history; t];\n  else\n    error ('incorrect call to __trace__');\n  end\n\nend\n"
  },
  {
    "path": "test/ctor-vs-method/ctor-vs-method.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%%  Test script for legacy OOP.\n%%  Requires the path to contain the directory ctor-vs-method.\n%%\n%%  Note: This script and all classes are also intended to run\n%%        in Matlab to test compatibility.  Don't break that!\n\n%!shared d, o\n%! d = derived ();\n%! o = other ();\n%!\n%!error method (o)\n\n%!test\n%! ctrace = {'begin parent/method';\n%!           'begin derived/parent';\n%!           'begin parent/parent';\n%!           'end parent/parent';\n%!           'end derived/parent';\n%!           'end parent/method'};\n%! __trace__ ();  # clear call trace info\n%! method (d);\n%! assert (__trace__ (), ctrace);\n\n%!test\n%! ctrace = {'begin other/parent';\n%!           'end other/parent'};\n%! __trace__ ();  # clear call trace info\n%! parent (o);\n%! assert (__trace__ (), ctrace);\n\n%!test\n%! ctrace = {'begin derived/parent';\n%!           'begin parent/parent';\n%!           'end parent/parent';\n%!           'end derived/parent'};\n%! __trace__ ();  # clear call trace info\n%! parent (d);\n%! assert (__trace__ (), ctrace);\n"
  },
  {
    "path": "test/ctor-vs-method/module.mk",
    "content": "ctor_vs_method_TEST_FILES = \\\n  %reldir%/@derived/derived.m \\\n  %reldir%/@derived/parent.m \\\n  %reldir%/@other/other.m \\\n  %reldir%/@other/parent.m \\\n  %reldir%/@parent/method.m \\\n  %reldir%/@parent/parent.m \\\n  %reldir%/__trace__.m \\\n  %reldir%/ctor-vs-method.tst\n\nTEST_FILES += $(ctor_vs_method_TEST_FILES)\n"
  },
  {
    "path": "test/deprecate-props.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Put graphics properties here that should be removed, or for which some\n## values (radio strings only) should not be accepted, in a given future\n## version.  Don't forget to add a note in the NEWS file.\n\n%!function testprop (h, prop, removal_version, val = [])\n%!  if (compare_versions (version (), removal_version, \">=\"))\n%!    if (isempty (val) && isprop (h, prop))\n%!      error (\"Please remove %s property %s\", get (h, \"type\"), prop);\n%!    elseif (! isempty (val) && any (strcmp (val, set (h, prop))))\n%!      error (\"Please remove '%s' from allowed values for %s property %s\",\n%!             val, get (h, \"type\"), prop);\n%!    endif\n%!  endif\n%!endfunction\n"
  },
  {
    "path": "test/diag-perm.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2009-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n########################################\n## Permutation matrices\n\n## row permutation\n%!test\n%! n = 5;\n%! A = rand (n);\n%! perm = randperm (n);\n%! Prow = eye (n) (perm, :);\n%! assert (A(perm, :), Prow * A);\n%! invperm(perm) = 1:n;\n%! assert (Prow \\ A, A(invperm, :));\n%! assert (Prow' * A, A(invperm, :));\n\n## column permutation\n%!test\n%! n = 7;\n%! A = rand (n);\n%! perm = randperm (n);\n%! Pcol = eye (n) (:, perm);\n%! assert (A(:, perm), A * Pcol);\n%! invperm(perm) = 1:n;\n%! assert (A / Pcol, A(:, invperm));\n%! assert (A * Pcol.', A(:, invperm));\n\n## fall back to a matrix in addition\n%!test\n%! n = 4;\n%! P1 = eye (n) (:, randperm (n));\n%! A = zeros (n) + P1;\n%! assert (sum (A), full (ones (1, n)));\n%! assert (sum (A, 2), full (ones (n, 1)));\n\n## preserve dense matrix structure\n%!test\n%! n = 7;\n%! Pc = eye (n) (:, randperm (n));\n%! Pr = eye (n) (randperm (n), :);\n%! assert (typeinfo (rand (n) * Pc), \"matrix\");\n%! assert (typeinfo (Pr * rand (n)), \"matrix\");\n\n## preserve sparse matrix structure\n%!test\n%! n = 7;\n%! Pc = eye (n) (:, randperm (n));\n%! Ac = sprand (n-3, n, .5) + I () * sprand (n-3, n, .5);\n%! Pr = eye (n) (randperm (n), :);\n%! Ar = sprand (n, n+2, .5);\n%! assert (typeinfo (Ac * Pc), \"sparse complex matrix\");\n%! assert (full (Ac * Pc), full (Ac) * Pc);\n%! assert (full (Ac / Pc), full (Ac) / Pc);\n%! assert (typeinfo (Pr * Ar), \"sparse matrix\");\n%! assert (full (Pr * Ar), Pr * full (Ar));\n%! assert (full (Pr \\ Ar), Pr \\ full (Ar));\n\n## structure rules for 1x1 dense / scalar and 1x1 perm\n%!test\n%! n = 7;\n%! P1 = eye (1) (:, [1]);\n%! A1 = 1;\n%! P = eye (n) (:, randperm (n));\n%! A = rand (n-3, n);\n%! assert (typeinfo (A * P1), \"matrix\");\n%! assert (full (A * P1), full (A) * P1);\n%! assert (typeinfo (P1 * A), \"matrix\");\n%! assert (full (P1 * A), P1 * full (A));\n%! assert (typeinfo (A1 * P), \"matrix\");\n%! assert (full (A1 * P), full (A1) * P);\n%! assert (typeinfo (P * A1), \"matrix\");\n%! assert (full (P * A1), P * full (A1));\n\n## structure rules for 1x1 sparse and 1x1 perm\n%!test\n%! n = 7;\n%! P1 = eye (1) (:, [1]);\n%! A1 = sparse (1, 1, 2);\n%! P = eye (n) (:, randperm (n));\n%! A = sprand (n-3, n, .5);\n%! assert (typeinfo (A * P1), \"sparse matrix\");\n%! assert (full (A * P1), full (A) * P1);\n%! assert (typeinfo (P1 * A), \"sparse matrix\");\n%! assert (full (P1 * A), P1 * full (A));\n%! assert (typeinfo (A1 * P), \"sparse matrix\");\n%! assert (full (A1 * P), full (A1) * P);\n%! assert (typeinfo (P * A1), \"sparse matrix\");\n%! assert (full (P * A1), P * full (A1));\n\n## permuting a matrix with exceptional values does not introduce new ones.\n%!test\n%! n = 5;\n%! pc = randperm (n);\n%! Pc = eye (n) (:, pc);\n%! pr = randperm (n);\n%! Pr = eye (n) (pr, :);\n%! A = rand (n);\n%! A(n, n-2) = NaN;\n%! A(3, 1) = Inf;\n%! assert (Pr * A * Pc, A(pr, pc));\n\n## conversion to sparse form\n%!test\n%! n = 7;\n%! P = eye (n) (:, randperm (n));\n%! sP = sparse (P);\n%! assert (full (sP), full (P));\n%! assert (size (find (sP), 1), n);\n%! [I, J, V] = find (sP);\n%! assert (all (V == 1));\n\n########################################\n## Diagonal matrices\n\n## square row scaling\n%!test\n%! m = 7;\n%! n = 11;\n%! A = rand (m, n);\n%! scalefact = rand (m, 1);\n%! Dr = diag (scalefact);\n%! assert (Dr * A, repmat (scalefact, 1, n) .* A);\n%! assert (Dr \\ A, A ./ repmat (scalefact, 1, n));\n%! scalefact(m-1) = Inf;\n%! Dr(m-1, m-1) = 0;\n%! assert (Dr \\ A, A ./ repmat (scalefact, 1, n));\n\n## square column scaling\n%!test\n%! m = 13;\n%! n = 11;\n%! A = rand (m, n);\n%! scalefact = rand (1, n);\n%! Dc = diag (scalefact);\n%! assert (A * Dc, repmat (scalefact, m, 1) .* A);\n%! assert (A / Dc, A ./ repmat (scalefact, m, 1));\n%! scalefact(n-1) = Inf;\n%! Dc(n-1, n-1) = 0;\n%! assert (A / Dc, A ./ repmat (scalefact, m, 1));\n\n## arithmetic\n%!test\n%! m = 9;\n%! n = 7;\n%! mn = min (m, n);\n%! d1 = rand (mn, 1) + I () * rand (mn, 1);\n%! D1 = diag (d1, m, n);\n%! d2 = rand (mn, 1);\n%! D2 = diag (d2, m, n);\n%! D1D2 = D1 + D2;\n%! assert (typeinfo (D1D2), \"complex diagonal matrix\");\n%! assert (diag (D1D2), d1 + d2);\n%! D1D2 = D2.' * D1;\n%! assert (typeinfo (D1D2), \"complex diagonal matrix\");\n%! assert (diag (D1D2), d1 .* d2);\n\n## slicing\n## preserving diagonal matrix type is not possible if indices are\n## general matrix objects.\n%!test\n%! m = 13;\n%! n = 6;\n%! mn = min (m, n);\n%! d = rand (mn, 1);\n%! D = diag (d, m, n);\n%! Dslice = D (1:(m-3), 1:(n-2));\n%! if (optimize_range ())\n%!   assert (typeinfo (Dslice), \"diagonal matrix\");\n%! else\n%!   assert (typeinfo (Dslice), \"matrix\");\n%! endif\n\n## preserve dense matrix structure when scaling\n%!assert (typeinfo (rand (8) * (3 * eye (8))), \"matrix\")\n%!assert (typeinfo ((3 * eye (8)) * rand (8)), \"matrix\")\n\n## preserve sparse matrix structure when scaling\n%!assert (typeinfo (sprand (8, 8, .5) * (3 * eye (8))), \"sparse matrix\")\n%!assert (typeinfo (sprand (8, 8, .5) * (3 * eye (8))'), \"sparse matrix\")\n%!assert (typeinfo (((3 + 2 * I ()) * eye (8)) * sprand (8, 8, .5)), \"sparse complex matrix\")\n%!assert (typeinfo (((3 + 2 * I ()) * eye (8))' * sprand (8, 8, .5)), \"sparse complex matrix\")\n%!assert (typeinfo (sprand (8, 8, .5) * ((3 + 2 * I ()) * eye (8)).'), \"sparse complex matrix\")\n\n## scaling a matrix with exceptional values does not introduce new ones.\n%!test\n%! n = 6;\n%! dr = rand (n, 1);\n%! Dr = diag (dr);\n%! dc = rand (1, n);\n%! Dc = diag (dc);\n%! A = rand (n);\n%! A(n, n-2) = NaN;\n%! A(4, 1) = Inf;\n%! assert (Dr * A * Dc, A .* kron (dr, dc), eps);\n\n## sparse inverse row scaling with a zero factor\n%!test\n%! n = 8;\n%! A = sprand (n, n, .5);\n%! scalefact = rand (n, 1);\n%! Dr = diag (scalefact);\n%! scalefact(n-1) = Inf;\n%! Dr(n-1, n-1) = 0;\n%! assert (full (Dr \\ A), full (A) ./ repmat (scalefact, 1, n));\n\n## narrow sparse inverse row scaling\n%!test\n%! n = 8;\n%! A = sprand (n, n, .5);\n%! scalefact = rand (n-2, 1);\n%! Dr = diag (scalefact, n, n-2);\n%! assert (full (Dr \\ A), Dr \\ full (A));\n\n## sparse inverse column scaling with a zero factor\n%!test\n%! n = 11;\n%! A = sprand (n, n, .5);\n%! scalefact = rand (1, n);\n%! Dc = diag (scalefact);\n%! scalefact(n-1) = Inf;\n%! Dc(n-1, n-1) = 0;\n%! assert (full (A / Dc), full (A) / Dc);\n\n## short sparse inverse column scaling\n%!test\n%! n = 7;\n%! A = sprand (n, n, .5);\n%! scalefact = rand (1, n-2) + I () * rand (1, n-2);\n%! Dc = diag (scalefact, n-2, n);\n%! assert (full (A / Dc), full (A) / Dc);\n\n## adding sparse and diagonal stays sparse\n%!test\n%! n = 9;\n%! A = sprand (n, n, .5);\n%! D = 2 * eye (n);\n%! assert (typeinfo (A + D), \"sparse matrix\");\n%! assert (typeinfo (A - D), \"sparse matrix\");\n%! D = D * I () + D;\n%! assert (typeinfo (A - D), \"sparse complex matrix\");\n%! A = A * I () + A;\n%! assert (typeinfo (D - A), \"sparse complex matrix\");\n\n## adding sparse and diagonal stays sparse\n%!test\n%! n = 9;\n%! A = sprand (n, n, .5);\n%! D = 2 * eye (n);\n%! assert (full (A + D), full (A) + D);\n%! assert (full (A - D), full (A) - D);\n%! D = D * I () + D;\n%! assert (full (D + A), D + full (A));\n%! A = A * I () + A;\n%! A(6, 4) = NaN ();\n%! assert (full (D - A), D - full (A));\n\n## inverse preserves diagonal structure even for singular matrices (bug #46103)\n## but set all the diagonal elements to Inf (bug #56232)\n%!test\n%! x = diag (1:3);\n%! assert (inv (x), diag ([1 1/2 1/3]));\n%!warning <matrix singular> A = inv (diag (0:2));\n%! assert (A, diag ([Inf Inf Inf]));\n\n## assignment to diagonal elements preserves diagonal structure (bug #36932)\n%!test\n%! x = diag (1:3);\n%! x(1,1) = -1;\n%! assert (typeinfo (x), \"diagonal matrix\");\n%! x(3,3) = -1;\n%! assert (typeinfo (x), \"diagonal matrix\");\n\n%!test\n%! x = diag (1:3);\n%! x(1) = -1;\n%! assert (typeinfo (x), \"diagonal matrix\");\n%! x(9) = -1;\n%! assert (typeinfo (x), \"diagonal matrix\");\n\n## diagonal broadcasting with dense vectors and matrices\n%!assert (diag (1:3) + ones (1, 3), full (diag (1:3)) + ones (1, 3))\n%!assert (diag (1:3) - ones (1, 3), full (diag (1:3)) - ones (1, 3))\n%!assert (eye (3) + ones (3, 1), full (eye (3)) + ones (3, 1))\n%!assert (eye (3) - ones (3, 1), full (eye (3)) - ones (3, 1))\n%!assert (eye (3) .* ones (1, 3), full (eye (3)))\n%!assert (ones (1, 4) + diag (1:4), diag (1:4) + ones (4, 1))\n%!assert (ones (1, 4) - diag (1:4), - diag (1:4) + ones (4, 1))\n%!assert (diag (1:3) + ones (3), ones (3) + diag (1:3))\n\n## diagonal broadcasting with sparse vectors and matrices\n%!assert (diag (1:3) + sparse ([1, 1, 1]), sparse (full (diag (1:3)) + ones (1, 3)))\n%!assert (diag (1:3) - sparse ([1, 1, 1]), sparse (full (diag (1:3)) - ones (1, 3)))\n%!assert (eye (3) + sparse ([1; 1; 1]), sparse (full (eye (3)) + sparse ([1; 1; 1])))\n%!assert (eye (3) - sparse ([1; 1; 1]), sparse (full (eye (3)) - sparse ([1; 1; 1])))\n%!assert (eye (3) .* sparse ([1, 1, 1]), eye (3) .* sparse ([1; 1; 1]))\n%!assert (sparse ([1, 1, 1, 1]) + diag (1:4), sparse (diag (1:4) + ones (4, 1)))\n%!assert (sparse ([1, 1, 1, 1]) - diag (1:4), sparse (-diag (1:4) + ones (4, 1)))\n%!assert (diag (1:3) + sparse (ones (3)), sparse (ones (3) + full (diag (1:3))))\n\n## arithmetic operations with (non-finite) scalars (bug #35787)\n%!assert (eye (3) * 1, eye (3))\n%!assert (typeinfo (eye (3) * 1), \"diagonal matrix\")\n%!assert (eye (3) * Inf, full (eye (3)) * Inf)\n%!assert (typeinfo (eye (3) * Inf), \"matrix\")\n%!assert (eye (3) * NaN, full (eye (3)) * NaN)\n%!assert (typeinfo (eye (3) * NaN), \"matrix\")\n%!assert (1 * eye (3), eye (3))\n%!assert (typeinfo (1 * eye (3)), \"diagonal matrix\")\n%!assert (Inf * eye (3), Inf * full (eye (3)))\n%!assert (typeinfo (Inf * eye (3)), \"matrix\")\n%!assert (NaN * eye (3), NaN * full (eye (3)))\n%!assert (typeinfo (NaN * eye (3)), \"matrix\")\n%!assert (eye (3) / 1, eye (3))\n%!assert (typeinfo (eye (3) / 1), \"diagonal matrix\")\n%!assert (eye (3) / 0, full (eye (3)) / 0)\n%!assert (typeinfo (eye (3) / 0), \"matrix\")\n%!assert (eye (3) / NaN, full (eye (3)) / NaN)\n%!assert (typeinfo (eye (3) / NaN), \"matrix\")\n%!assert (1 \\ eye (3), eye (3))\n%!assert (typeinfo (1 \\ eye (3)), \"diagonal matrix\")\n%!assert (0 \\ eye (3), 0 \\ full (eye (3)))\n%!assert (typeinfo (0 \\ eye (3)), \"matrix\")\n%!assert (NaN \\ eye (3), NaN \\ full (eye (3)))\n%!assert (typeinfo (NaN \\ eye (3)), \"matrix\")\n"
  },
  {
    "path": "test/error.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Test %!error usage\n\n%!function g ()\n%!  error (\"foo\");\n%!endfunction\n%!function f ()\n%!  g ();\n%!endfunction\n%!error <foo> f ()\n\n%!function g ()\n%!  error (\"foo\\n\");\n%!endfunction\n%!function f ()\n%!  g\n%!endfunction\n%!error <foo> f ()\n\n%!error error ()\n\n%!error <foo> error (\"foo\\n\")\n\n## Test %!warning usage\n\n%!function g ()\n%!  warning (\"foo\");\n%!endfunction\n%!function f ()\n%!  g;\n%!endfunction\n%!warning <foo> f ()\n\n%!test\n%! st.identifier = \"backtrace\";\n%! ws = warning (\"query\", \"backtrace\");\n%! warning (\"on\", \"backtrace\");\n%! st.state = \"on\";\n%! assert (warning (\"query\", \"backtrace\"), st);\n%! warning (\"off\", \"backtrace\");\n%! st.state = \"off\";\n%! assert (warning (\"query\", \"backtrace\"), st);\n%! warning (ws.state, \"backtrace\");\n\n%!test\n%! saved_opts = warning ();\n%! saved_id = {saved_opts.identifier};\n%! saved_state = {saved_opts.state};\n%! warning (\"off\", \"all\");\n%! assert (warning (), struct (\"identifier\", {\"all\"}, \"state\", {\"off\"}));\n%! warning (\"off\", \"all\");\n%! warning (saved_opts);\n%! t1_opts = struct (\"identifier\", {\"foo:bar\"}, \"state\", {\"off\"});\n%! t1_id = {t1_opts.identifier};\n%! t1_state = {t1_opts.state};\n%! warning (t1_opts);\n%! t2_opts = struct (\"identifier\", [saved_id, t1_id], \"state\", [saved_state, t1_state]);\n%! assert (warning (), t2_opts);\n%! warning (\"off\", \"all\");\n%! warning (saved_opts);\n\n## Bug 36393\n\n%!test\n%! w0 = warning;\n%! warnoffId = \"MATLAB:singularMatrix\";\n%! warnstat = warning (\"query\", warnoffId);\n%! warnoff = warnstat;\n%! warnoff.state = \"off\";\n%! warning (warnoff);  # update warning status\n%! warning (warnstat); # reset warning status\n%! w = warning;\n%! assert (w, w0);\n\n%!error <ERR struct must contain the fields> rethrow (struct ())\n\n%!error <STACK struct must contain the fields>\n%! rethrow (struct (\"message\", \"foo\", \"identifier\", \"\", \"stack\", struct ()))\n\n%!test\n%! try\n%!   union ({'a'}, 1);\n%! catch\n%!   x = lasterror ();\n%!   try\n%!     rethrow (lasterror ());\n%!   catch\n%!     assert (x, lasterror ());\n%!   end_try_catch\n%! end_try_catch\n\n%!test\n%! try\n%!   union ({'a'}, 1);\n%! catch\n%!   x = lasterror ();\n%!   try\n%!     y = struct (\"message\", \"msg\", \"identifier\", \"\", \"stack\",\n%!                 struct (\"file\", \"foo.m\", \"name\", \"foo\", \"line\", 13));\n%!     rethrow (y);\n%!   catch\n%!     stk = y.stack;\n%!     [stk.column] = deal (-1);\n%!     y.stack = stk;\n%!     assert (y, lasterror ());\n%!   end_try_catch\n%! end_try_catch\n"
  },
  {
    "path": "test/eval-catch.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! eval (\"clear a; a;\", \"\");\n\n%!test\n%! eval (\"\", \"error ('Should not get here');\");\n\n%!test\n%! eval (\"clear a; a; x = 0;\", \"x = 1;\");\n%! assert (x, 1);\n\n%!test\n%! eval (\"clear a; a; str = '';\", \"str=lasterr;\");\n%! assert (lasterr ()(1:13), \"'a' undefined\");\n%! assert (str(1:13), \"'a' undefined\");\n\n%!test\n%! eval (\"error ('user-defined error'); str = '';\", \"str = lasterr;\");\n%! assert (lasterr ()(1:18), \"user-defined error\");\n%! assert (str(1:18), \"user-defined error\");\n\n%!function ms = mangle (s)\n%!  ## Wrap angle brackets around S.\n%!  ms = [\"<\" s \">\"];\n%!endfunction\n%!test\n%! eval (\"clear a; a; str='';\", \"str = mangle (lasterr);\");\n%! assert (mangle (lasterr)(1:14), \"<'a' undefined\");\n%! assert (str(1:14), \"<'a' undefined\");\n\n%!test\n%! eval (\"eval (\\\"clear a; a;str1='';\\\", \\\"str1=lasterr;\\\"); clear b; b; str2='';\",\n%! \"str2 = lasterr;\");\n%! assert (str1(1:13), \"'a' undefined\");\n%! assert (str2(1:13), \"'b' undefined\");\n\n%!test\n%! eval (\"clear a; a; str1='';\",\n%! \"eval (\\\"clear b; b; str2='';\\\", \\\"str2=lasterr;\\\"); str1=lasterr;\");\n%! assert (str1(1:13), \"'b' undefined\");\n%! assert (str2(1:13), \"'b' undefined\");\n\n%!test\n%! eval (\"eval (\\\"clear a; a; str='';\\\",\\\"error (cstrcat (\\\\\\\"rethrow: \\\\\\\", lasterr));str='';\\\");\",\n%! \"str=lasterr;\");\n%! assert (str(1:22), \"rethrow: 'a' undefined\");\n"
  },
  {
    "path": "test/eval-command.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2013-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!function r = sigma (opt)\n%!  global sigma_call;\n%!  if (nargin == 0)\n%!    sigma_call = \"function\";\n%!    r = 1;\n%!  elseif (ischar (opt))\n%!    sigma_call = \"command\";\n%!    r = 1;\n%!  else\n%!    sigma_call = \"unexpected\";\n%!  endif\n%!endfunction\n%!\n%!function f1 ()\n%!  ## ERROR; sigma used as variable and later parsed as command\n%!  sigma = svd (1);\n%!  eval (\"sigma -1;\");\n%!endfunction\n%!\n%!function f1a ()\n%!  ## Assignment of eval result means eval code is not parsed as command.\n%!  sigma = svd (1);\n%!  val = eval (\"sigma -1;\");\n%!endfunction\n%!\n%!function f2 ()\n%!  ## ERROR; sigma used as variable and later parsed as command\n%!  [u, sigma, v] = svd (1);\n%!  eval (\"sigma -1;\");\n%!endfunction\n%!\n%!function f2a ()\n%!  ## Assignment of eval result means eval code is not parsed as command.\n%!  [u, sigma, v] = svd (1);\n%!  val = eval (\"sigma -1;\");\n%!endfunction\n%!\n%!function f3 (sigma)\n%!  ## No assignment of eval result means eval code is parsed as command.\n%!  ## If f3 is called with a value for sigma, it will be used.  Otherwise,\n%!  ## search for the function sigma and call with no arguments.\n%!  eval (\"sigma -1;\");\n%!endfunction\n%!\n%!function f3a (sigma)\n%!  ## Assignment of eval result means eval code is not parsed as command.\n%!  val = eval (\"sigma -1;\");\n%!endfunction\n%!\n%!function f4 ()\n%!  ## No assignment of eval result means eval code is parsed as command.\n%!  eval (\"sigma -1;\");\n%!endfunction\n%!\n%!function f4a ()\n%!  ## Assignment of eval result means eval code is not parsed as command.\n%!  val = eval (\"sigma -1;\");\n%!endfunction\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! ## Matlab complains about sigma previously being used as a variable\n%! ## before being used as a command.\n%! fail (\"f1 ()\", \"used as variable and later as function\");\n%! assert (sigma_call, \"none\");\n%! clear -global sigma_call\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! f1a ();\n%! assert (sigma_call, \"none\");\n%! clear -global sigma_call\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! ## Matlab complains about sigma previously being used as a variable\n%! ## before being used as a command.\n%! fail (\"f2 ()\", \"used as variable and later as function\");\n%! assert (sigma_call, \"none\");\n%! clear -global sigma_call\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! f2a ();\n%! assert (sigma_call, \"none\");\n%! clear -global sigma_call\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! f3 ();\n%! assert (sigma_call, \"command\");\n%! clear -global sigma_call\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! f3a ();\n%! assert (sigma_call, \"function\");\n%! clear -global sigma_call\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! ## NOTE: this result disagrees with Matlab, which evaluates sigma\n%! ## as a command-style function even though there is a variable named\n%! ## sigma defined in the workspace prior to evaluating the function\n%! ## call (compare with f1() and f2() above).\n%! fail (\"f3 (1)\", \"used as variable and later as function\");\n%! assert (sigma_call, \"none\");\n%! clear -global sigma_call\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! f3a (1);\n%! assert (sigma_call, \"none\");\n%! clear -global sigma_call\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! f4 ();\n%! assert (sigma_call, \"command\");\n%! clear -global sigma_call\n%!\n%!test <55610>\n%! global sigma_call;\n%! sigma_call = \"none\";\n%! f4a ();\n%! assert (sigma_call, \"function\");\n%! clear -global sigma_call\n\n%!function r = f_eval_fun ()\n%!  evalin_value = \"this is f_eval_fun\";\n%!  r = evalin (\"caller\", \"evalin_value\");\n%!endfunction\n%!function r = g_eval_fun ()\n%!  evalin_value = \"this is g_eval_fun\";\n%!  r = evalin (\"caller\", \"f_eval_fun ()\");\n%!endfunction\n%!function r = h_eval_fun ()\n%!  evalin_value = \"this is h_eval_fun\";\n%!  r = f_eval_fun ();\n%!endfunction\n\n%!shared evalin_value\n%! evalin_value = \"this is the caller\";\n%!assert <*59847> (f_eval_fun (), \"this is the caller\")\n%!assert <*59847> (g_eval_fun (), \"this is the caller\")\n%!assert <*59847> (h_eval_fun (), \"this is h_eval_fun\")\n\n%!function r = f_asgn_fun ()\n%!  asgnin_value = \"this is f_asgn_fun\";\n%!  assignin (\"caller\", \"asgnin_value\", \"f value\");\n%!  r = asgnin_value;\n%!endfunction\n%!function r = g_asgn_fun ()\n%!  asgnin_value = \"this is g_asgn_fun\";\n%!  evalin (\"caller\", \"f_asgn_fun ();\");\n%!  r = asgnin_value;\n%!endfunction\n%!function r = h_asgn_fun ()\n%!  asgnin_value = \"this is h_asgn_fun\";\n%!  f_asgn_fun ();\n%!  r = asgnin_value;\n%!endfunction\n\n%!test <*59847>\n%! asgnin_value = \"this is the caller\";\n%! assert (f_asgn_fun (), \"this is f_asgn_fun\");\n%! assert (asgnin_value, \"f value\");\n\n%!test <*59847>\n%! asgnin_value = \"this is the caller\";\n%! assert (g_asgn_fun (), \"this is g_asgn_fun\");\n%! assert (asgnin_value, \"f value\");\n\n%!test <*59847>\n%! asgnin_value = \"this is the caller\";\n%! assert (h_asgn_fun (), \"f value\");\n%! assert (asgnin_value, \"this is the caller\");\n"
  },
  {
    "path": "test/fcn-handle/+pkga/+pkgb/bug51709_a.m",
    "content": "classdef bug51709_a\n  methods (Static)\n    function r = smeth ()\n      r = \"pkg bug51709_a\";\n    end\n  end\nend\n"
  },
  {
    "path": "test/fcn-handle/+pkga/+pkgb/bug51709_b.m",
    "content": "classdef bug51709_b\n  methods (Static)\n    function r = smeth ()\n      r = \"pkg bug51709_b\";\n    end\n  end\nend\n"
  },
  {
    "path": "test/fcn-handle/+pkga/+pkgb/f1.m",
    "content": "function r = f1 ()\n  r = \"pkg f1\";\nendfunction\n"
  },
  {
    "path": "test/fcn-handle/+pkga/+pkgb/f2.m",
    "content": "function r = f2 ()\n  r = \"pkg f2\";\nendfunction\n"
  },
  {
    "path": "test/fcn-handle/@fhdr_derived/fhdr_derived.m",
    "content": "function r = fhdr_derived (n)\n  s.a = n;\n  p = fhdr_parent (n);\n  r = class (s, 'fhdr_derived', p);\nend\n"
  },
  {
    "path": "test/fcn-handle/@fhdr_other/fhdr_other.m",
    "content": "function r = fhdr_other (n)\n  s.d = fhdr_derived (n);\n  r = class (s, 'fhdr_other');\nend\n"
  },
  {
    "path": "test/fcn-handle/@fhdr_other/getsize_arrayfun.m",
    "content": "function r = getsize_arrayfun (x)\n  r = arrayfun (@(i) numel (x(i).d), 1:numel (x), 'uniformoutput', true);\nend\n"
  },
  {
    "path": "test/fcn-handle/@fhdr_other/getsize_cellfun.m",
    "content": "function r = getsize_cellfun (x)\n  ## Must use @numel so that function overloading can occur, rather than\n  ## 'numel'  which is built in to cellfun().\n  r = cellfun (@numel, {x.d});\nend\n"
  },
  {
    "path": "test/fcn-handle/@fhdr_other/getsize_loop.m",
    "content": "function r = getsize_loop (x)\n  n = numel (x);\n  r = zeros (1, n);\n  for i = 1:n\n    r(i) = numel (x(i).d);\n  end\nend\n"
  },
  {
    "path": "test/fcn-handle/@fhdr_parent/fhdr_parent.m",
    "content": "function r = fhdr_parent (n)\n  s.a = rand (n, 1);\n  r = class (s, 'fhdr_parent');\nend\n"
  },
  {
    "path": "test/fcn-handle/@fhdr_parent/numel.m",
    "content": "function r = numel (x, varargin)\n  r = numel (x.a, varargin{:});\nend\n"
  },
  {
    "path": "test/fcn-handle/bug-51567.tst",
    "content": "%!shared a\n%! a = bug51567 ();\n%!\n%!assert <51567> (a.doit_1 (), 13)\n%!assert <51567> (a.doit_2 (), 42)\n"
  },
  {
    "path": "test/fcn-handle/bug-57941.tst",
    "content": "%!test <*57941>\n%! [r1, r2] = bug57941a (2);\n%! assert (r1, 6);\n%! assert (r2, 24);\n\n%!test <*57941>\n%! [fh1, fh2] = bug57941b (2);\n%! assert (fh1 (3), 6);\n%! assert (fh2 (3, 4), 24);\n"
  },
  {
    "path": "test/fcn-handle/bug51567.m",
    "content": "classdef bug51567 < handle\n  properties\n    fh1;\n    fh2;\n  endproperties\n  methods\n    function obj = bug51567 (self)\n      obj.fh1 = str2func (\"bar\");\n      obj.fh2 = @baz;\n    endfunction\n    function r = bar (obj)\n      r = 13;\n    endfunction\n    function r = baz (obj)\n      r = 42;\n    endfunction\n    function r = doit_1 (obj)\n      r = obj.fh1 ();\n    endfunction\n    function r = doit_2 (obj)\n      r = obj.fh2 ();\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/fcn-handle/bug51709_a.m",
    "content": "classdef bug51709_a\n  methods (Static)\n    function r = smeth ()\n      r = \"top bug51709_a\";\n    end\n  end\nend\n"
  },
  {
    "path": "test/fcn-handle/bug51709_c.m",
    "content": "classdef bug51709_c\n  methods\n    function out = meth (varargin)\n      out = {\"meth\", varargin};\n    endfunction\n  endmethods\n  methods (Static)\n    function out = smeth (varargin)\n      out = {\"smeth\", varargin};\n    endfunction\n  endmethods\nendclassdef\n"
  },
  {
    "path": "test/fcn-handle/bug57941a.m",
    "content": "function [r1, r2] = bug57941a (A)\n  fh1 = @nested1;\n  function z = nested1 (x)\n    z = A * x;\n  end\n  fh2 = @nested2;\n  function z = nested2 (x,y)\n    z = A * x .* y;\n  end\n  r1 = fh1 (3);\n  r2 = fh2 (3, 4);\nend\n"
  },
  {
    "path": "test/fcn-handle/bug57941b.m",
    "content": "function [fh1, fh2] = bug57941b (A)\n  fh1 = @nested1;\n  function z = nested1 (x)\n    z = A * x;\n  end\n  fh2 = @nested2;\n  function z = nested2 (x,y)\n    z = A * x .* y;\n  end\nend\n"
  },
  {
    "path": "test/fcn-handle/bug58519.tst",
    "content": "%!test <*58519>\n%! fieldname = \"a\";\n%! structure = struct (fieldname, 42);\n%! anonfunc = @ () structure.(fieldname);\n%! assert (anonfunc (), 42);\n"
  },
  {
    "path": "test/fcn-handle/bug60845.m",
    "content": "function output = bug60845 (varargin)\n  ## ahandle is a boolean variable\n  [Ahandle, static, fcn_handle] = checkInput (varargin{:});\n\n  ## execute nested function using handle\n  output = fcn_handle ();\n\n  function [Ahandle, static, fcn_handle] = checkInput (varargin)\n    ## initialize\n    Ahandle = true;\n    static = false;\n    ## get a handle to nested (sibling) function.\n    fcn_handle = @nestfcn;\n  endfunction\n\n  function r = nestfcn ()\n    if (islogical (Ahandle))\n      r = true;\n    else\n      r = false;\n    end\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/fcn-handle/derived-resolution.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2012-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%%  Test script for legacy OOP.\n%%  Requires the path to contain the directory ctor-vs-method.\n%%\n%%  Note: This script and all classes are also intended to run\n%%        in Matlab to test compatibility.  Don't break that!\n\n%% FIXME: Can't use 'clear -classes' because it also clears all functions in the\n%% namespace of test.m (bug #35881).  This is a problem only if Octave would\n%% re-use a class definition that was defined somewhere else.  Unfortunately,\n%% that is exactly the case when running 'make check' since the ctor-vs-method\n%% test also uses an @parent, @derived, and @other class.\n%% Until the bug is fixed, it suffices to make the class names unique so that\n%% there is no re-use.  Using the prefix fhdr (fcn-handle/derived-resolution)\n%% for this directory.\n%%!shared\n%%! #clear -classes\n\n%!test\n%! p = fhdr_parent (7);\n%! assert (numel (p), 7);\n\n%!test\n%! d = fhdr_derived (13);\n%! assert (numel (d), 13);\n\n%!test\n%! p = fhdr_parent (11);\n%! f = @numel;\n%! assert (f (p), 11);\n\n%!test\n%! d = fhdr_parent (21);\n%! f = @numel;\n%! assert (f (d), 21);\n\n%!test\n%! o(1) = fhdr_other (13);\n%! o(2) = fhdr_other (42);\n%! assert (getsize_loop (o), [13, 42]);\n\n%!test\n%! o(1) = fhdr_other (13);\n%! o(2) = fhdr_other (42);\n%! assert (getsize_cellfun (o), [13, 42]);\n\n%!test\n%! o(1) = fhdr_other (13);\n%! o(2) = fhdr_other (42);\n%! assert (getsize_arrayfun (o), [13, 42]);\n"
  },
  {
    "path": "test/fcn-handle/f1.m",
    "content": "function r = f1 ()\n  r = \"top f1\";\nendfunction\n"
  },
  {
    "path": "test/fcn-handle/handle-to-sibling.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!assert <*60845> (bug60845 (), true)\n"
  },
  {
    "path": "test/fcn-handle/keyword.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2020-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*57988>\n%! fh = @get;\n%! fh = @set;\n%! fh = @enumeration;\n%! fh = @events;\n%! fh = @methods;\n%! fh = @properties;\n\n%!test <*57988>\n%!  kwords = iskeyword ();\n%!  for i = 1:numel (kwords)\n%!    unexpected_success = true;\n%!    kword = kwords{i};\n%!    try\n%!      eval (sprintf (\"@%s;\", kword));\n%!    catch\n%!      unexpected_success = false;\n%!    end_try_catch\n%!    if (unexpected_success)\n%!      error (\"constructing function handle from keyword '%s' succeeded!\",\n%!             kword);\n%!    endif\n%!  endfor\n"
  },
  {
    "path": "test/fcn-handle/module.mk",
    "content": "fcn_handle_TEST_FILES = \\\n  %reldir%/+pkga/+pkgb/bug51709_a.m \\\n  %reldir%/+pkga/+pkgb/bug51709_b.m \\\n  %reldir%/+pkga/+pkgb/f1.m \\\n  %reldir%/+pkga/+pkgb/f2.m \\\n  %reldir%/@fhdr_derived/fhdr_derived.m \\\n  %reldir%/@fhdr_other/fhdr_other.m \\\n  %reldir%/@fhdr_other/getsize_arrayfun.m \\\n  %reldir%/@fhdr_other/getsize_cellfun.m \\\n  %reldir%/@fhdr_other/getsize_loop.m \\\n  %reldir%/@fhdr_parent/fhdr_parent.m \\\n  %reldir%/@fhdr_parent/numel.m \\\n  %reldir%/bug-51567.tst \\\n  %reldir%/bug-57941.tst \\\n  %reldir%/bug51567.m \\\n  %reldir%/bug51709_a.m \\\n  %reldir%/bug51709_c.m \\\n  %reldir%/bug57941a.m \\\n  %reldir%/bug57941b.m \\\n  %reldir%/bug58519.tst \\\n  %reldir%/bug60845.m \\\n  %reldir%/derived-resolution.tst \\\n  %reldir%/f1.m \\\n  %reldir%/handle-to-sibling.tst \\\n  %reldir%/keyword.tst \\\n  %reldir%/object-method.tst \\\n  %reldir%/package-function.tst \\\n  %reldir%/shared-ctx.tst \\\n  %reldir%/shared_ctx.m \\\n  %reldir%/static-method.tst\n\nTEST_FILES += $(fcn_handle_TEST_FILES)\n"
  },
  {
    "path": "test/fcn-handle/object-method.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!function [fhm, fhsm] = object_method_fcns ()\n%!  obj = bug51709_c ();\n%!  fhm = @obj.meth;\n%!  fhsm = @obj.smeth;\n%!endfunction\n\n%!test <*51709>\n%! [fhm, fhsm] = object_method_fcns ();\n%!\n%! out = fhm (42);\n%! assert (out{1}, \"meth\");\n%! tmp = out{2};\n%! assert (numel (tmp), 2);\n%! assert (isobject (tmp{1}));\n%! assert (tmp{2}, 42);\n\n%!test <*51709>\n%! [fhm, fhsm] = object_method_fcns ();\n%!\n%! out = fhsm (42);\n%! assert (out{1}, \"smeth\");\n%! tmp = out{2};\n%! assert (numel (tmp), 1);\n%! assert (tmp{1}, 42);\n\n%!test <*51709>\n%! fhm = @obj.meth;\n%!\n%! obj = bug51709_c ();\n%!\n%! out = fhm (42);\n%! assert (out{1}, \"meth\");\n%! tmp = out{2};\n%! assert (numel (tmp), 2);\n%! assert (isobject (tmp{1}));\n%! assert (tmp{2}, 42);\n\n%!test <*51709>\n%! fhsm = @obj.smeth;\n%!\n%! obj = bug51709_c ();\n%!\n%! out = fhsm (42);\n%! assert (out{1}, \"smeth\");\n%! tmp = out{2};\n%! assert (numel (tmp), 1);\n%! assert (tmp{1}, 42);\n"
  },
  {
    "path": "test/fcn-handle/package-function.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*46659>\n%! fh = @pkga.pkgb.f2;\n%! assert (fh (), \"pkg f2\");\n\n%!test <*55975>\n%! fh = @pkga.pkgb.f1;\n%! assert (fh (), \"pkg f1\");\n\n## Also test without function handle.\n%!assert <*55975> (pkga.pkgb.f1 (), \"pkg f1\")\n%!assert (pkga.pkgb.f2 (), \"pkg f2\")\n"
  },
  {
    "path": "test/fcn-handle/shared-ctx.tst",
    "content": "## Test that multiple handles to nested functions created in the same\n## context share that call stack context, but that separately created\n## handles have a separate (shared) context.\n\n%!test\n%! [add10, sub10, mul10, div10] = shared_ctx (10);\n%! [add100, sub100, mul100, div100] = shared_ctx (100);\n%! assert (add10 (2), 12);\n%! assert (add100 (20), 120);\n%! assert (sub10 (4), 8);\n%! assert (sub100 (40), 80);\n%! assert (mul10 (5), 40);\n%! assert (mul100 (50), 4000);\n%! assert (div10 (4), 10);\n%! assert (div100 (40), 100);\n"
  },
  {
    "path": "test/fcn-handle/shared_ctx.m",
    "content": "function [add, sub, mul, div] = shared_ctx (val)\n  add = @add_fun;\n  sub = @sub_fun;\n  mul = @mul_fun;\n  div = @div_fun;\n  function r = add_fun (x)\n    val += x;\n    r = val;\n  endfunction\n  function r = sub_fun (x)\n    val -= x;\n    r = val;\n  endfunction\n  function r = mul_fun (x)\n    val *= x;\n    r = val;\n  endfunction\n  function r = div_fun (x)\n    val /= x;\n    r = val;\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/fcn-handle/static-method.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2019-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*51709>\n%! fh = @pkga.pkgb.bug51709_a.smeth;\n%! assert (fh (), \"pkg bug51709_a\");\n\n%!test <*55975>\n%! fh = @pkga.pkgb.bug51709_b.smeth;\n%! assert (fh (), \"pkg bug51709_b\");\n\n## Also test without function handle.\n%!assert <*55975> (pkga.pkgb.bug51709_a.smeth (), \"pkg bug51709_a\")\n%!assert (pkga.pkgb.bug51709_b.smeth (), \"pkg bug51709_b\")\n"
  },
  {
    "path": "test/file-encoding/.oct-config",
    "content": "encoding=windows-1252\n"
  },
  {
    "path": "test/file-encoding/CP1251/.oct-config",
    "content": "encoding=windows-1251\n"
  },
  {
    "path": "test/file-encoding/CP1251/test_CP1251.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This program is free software; you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as\n## published by the Free Software Foundation; either version 3 of the\n## License, or (at your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n## General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with this program; if not, see <http://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} test_CP1251 ()\n## Test function with some characters from CP1251\n##\n##  \n##\n## @end deftypefn\n\nfunction test_CP1251 ()\n  help (\"test_CP1251\");\nendfunction\n\n%!assert (double (\" \"),\n%!        [208 148 208 166 208 172 208 180 209 134 209 140 32 ...\n%!         208 137 208 139 209 153 209 155])\n"
  },
  {
    "path": "test/file-encoding/file-encoding.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Note: The cache of dir_encoding from .oct-config files in the load path\n## persists even after removing the folder from the load path.\n## Explictily, delete it when removing the path.\n\n## test file in current directory\n\n%!assert (dir_encoding (\".\"), \"windows-1252\")\n%!assert (dir_encoding (pwd ()), \"windows-1252\")\n\n%!test\n%! help_str = get_help_text (\"test_CP1252\");\n%! ## The help text contains the string \"ÄÖÜäöü ŠŽšž\".  Compare to the\n%! ## corresponding UTF-8 byte sequence to make sure this test is independent\n%! ## of how this .tst file is interpreted.\n%! ref_str = char ([195 132 195 150 195 156 195 164 195 182 195 188 32 ...\n%!                  197 160 197 189 197 161 197 190]);\n%! assert (strfind (help_str, ref_str));\n\n\n## test file in load path (relative)\n\n%!test\n%! path_orig = path ();\n%! unwind_protect\n%!   addpath (\"CP1251\");\n%!   assert (dir_encoding (\"CP1251\"), \"windows-1251\");\n%!   assert (dir_encoding (fullfile (pwd (), \"CP1251\")), \"windows-1251\");\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%!   dir_encoding (canonicalize_file_name (\"CP1251\"), \"delete\");\n%! end_unwind_protect\n\n%!test\n%! path_orig = path ();\n%! unwind_protect\n%!   addpath (\"CP1251\");\n%!   help_str = get_help_text (\"test_CP1251\");\n%!   ## The help text contains the string \"ДЦЬдць ЉЋљћ\".  Compare to the\n%!   ## corresponding UTF-8 byte sequence to make sure this test is independent\n%!   ## of how this .tst of how this .tst file is interpreted.\n%!   ref_str = char ([208 148 208 166 208 172 208 180 209 134 209 140 32 ...\n%!                    208 137 208 139 209 153 209 155]);\n%!   assert (strfind (help_str, ref_str));\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%!   dir_encoding (canonicalize_file_name (\"CP1251\"), \"delete\");\n%! end_unwind_protect\n\n\n## test file in load path (absolute)\n\n%!test\n%! clear all;  # make sure files are re-parsed\n%! path_orig = path ();\n%! unwind_protect\n%!   new_path = canonicalize_file_name (\"CP1251\");\n%!   addpath (new_path);\n%!   assert (dir_encoding (new_path), \"windows-1251\");\n%!   assert (dir_encoding (\"CP1251\"), \"windows-1251\");\n%!   assert (dir_encoding (fullfile (pwd (), \"CP1251\")), \"windows-1251\");\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%!   dir_encoding (canonicalize_file_name (\"CP1251\"), \"delete\");\n%! end_unwind_protect\n\n%!test\n%! clear all;  # make sure files are re-parsed\n%! path_orig = path ();\n%! unwind_protect\n%!   addpath (canonicalize_file_name (\"CP1251\"));\n%!   help_str = get_help_text (\"test_CP1251\");\n%!   ## The help text contains the string \"ДЦЬдць ЉЋљћ\".  Compare to the UTF-8\n%!   ## byte sequence to make sure this test is independent of how this .tst\n%!   ## file is interpreted.\n%!   ref_str = char ([208 148 208 166 208 172 208 180 209 134 209 140 32 ...\n%!                    208 137 208 139 209 153 209 155]);\n%!   assert (strfind (help_str, ref_str));\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%!   dir_encoding (canonicalize_file_name (\"CP1251\"), \"delete\");\n%! end_unwind_protect\n\n\n## oruntests with file in current folder with .oct-config file\n%!test <*62780>\n%! ## wrap in \"evalc\" to suppress output to the log\n%! evalc ('oruntests (\".\");');\n\n## oruntests with file in different folder (not in load path) with\n## \"dir_encoding\"\n%!test <*62780>\n%! unwind_protect\n%!   dir_encoding (canonicalize_file_name (\"CP1251\"), \"windows-1251\");\n%!   ## use \"evalc\" to suppress output to the log\n%!   evalc ('oruntests (\"CP1251\");');\n%! unwind_protect_cleanup\n%!   dir_encoding (canonicalize_file_name (\"CP1251\"), \"delete\");\n%! end_unwind_protect\n\n## oruntests with file in different folder (not in load path) with\n## \"mfile_encoding\"\n%!test <*62780>\n%! old_mfile_encoding = mfile_encoding (\"windows-1251\");\n%! unwind_protect\n%!   ## use \"evalc\" to suppress output to the log\n%!   evalc ('oruntests (\"CP1251\");');\n%! unwind_protect_cleanup\n%!   mfile_encoding (old_mfile_encoding);\n%! end_unwind_protect\n\n## oruntests with file in different folder with .oct-config file (in load path)\n%!test <*62780>\n%! path_orig = path ();\n%! unwind_protect\n%!   addpath (canonicalize_file_name (\"CP1251\"));\n%!   ## use \"evalc\" to suppress output to the log\n%!   evalc ('oruntests (\"CP1251\");');\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%!   dir_encoding (canonicalize_file_name (\"CP1251\"), \"delete\");\n%! end_unwind_protect\n"
  },
  {
    "path": "test/file-encoding/module.mk",
    "content": "file_encoding_TEST_FILES = \\\n    %reldir%/.oct-config \\\n    %reldir%/file-encoding.tst \\\n    %reldir%/test_CP1252.m \\\n    %reldir%/CP1251/.oct-config \\\n    %reldir%/CP1251/test_CP1251.m\n\nTEST_FILES += $(file_encoding_TEST_FILES)\n"
  },
  {
    "path": "test/file-encoding/test_CP1252.m",
    "content": "########################################################################\n##\n## Copyright (C) 2022-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This program is free software; you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as\n## published by the Free Software Foundation; either version 3 of the\n## License, or (at your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n## General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with this program; if not, see <http://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## -*- texinfo -*-\n## @deftypefn {} {} test_CP1252 ()\n## Test function with some characters from CP1252\n##\n##  \n##\n## @end deftypefn\n\nfunction test_CP1252 ()\n  help (\"test_CP1252\");\nendfunction\n\n%!assert (double (\" \"),\n%!        [195 132 195 150 195 156 195 164 195 182 195 188 32 ...\n%!         197 160 197 189 197 161 197 190])\n"
  },
  {
    "path": "test/fntests.m",
    "content": "########################################################################\n##\n## Copyright (C) 2005-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nclear all;\n\ncurrdir = canonicalize_file_name (\".\");\n\ndebug_on_error (true);\n\nif (nargin > 0)\n  xdir = argv (){1};\nelse\n  xdir = \".\";\nendif\n\nif (nargin > 1)\n  eval (argv (){2});\nendif\n\nsrcdir = canonicalize_file_name (xdir);\ntopsrcdir = canonicalize_file_name (fullfile (xdir, \"..\"));\ntopbuilddir = canonicalize_file_name (fullfile (currdir, \"..\"));\n\nif (is_same_file (currdir, srcdir))\n  testdirs = {srcdir};\nelse\n  testdirs = {currdir, srcdir};\nendif\n\nliboctave_tree = canonicalize_file_name (fullfile (topbuilddir, \"liboctave\"));\nsrc_tree = canonicalize_file_name (fullfile (topbuilddir, \"libinterp\"));\nscript_tree = canonicalize_file_name (fullfile (topsrcdir, \"scripts\"));\nlocal_script_tree = canonicalize_file_name (fullfile (currdir, \"../scripts\"));\n\nfundirs = {liboctave_tree, src_tree, script_tree};\n\nif (! is_same_file (currdir, srcdir))\n  fundirs{end+1} = local_script_tree;\nendif\n\n__run_test_suite__ (fundirs, testdirs, topsrcdir, topbuilddir);\n"
  },
  {
    "path": "test/for.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! for i = 1\n%!   __printf_assert__ (\"%d\", i);\n%! end  # \"end\" is part of test, check not using \"endfor\"\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"1\"));\n\n%!test\n%! for i = 1:4\n%!   __printf_assert__ (\"%d\", i);\n%! endfor\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"1234\"));\n\n%!test\n%! for i = [1,2,3,4]\n%!   __printf_assert__ (\"%d\", i);\n%! endfor\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"1234\"));\n\n%!test\n%! for i = [1,2;3,4]\n%!   __printf_assert__ (\"%d\", i(1,1));\n%!   __printf_assert__ (\"%d\", i(2,1));\n%! endfor\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"1324\"));\n\n%!test\n%! for i = I\n%!   __printf_assert__ (\"%d\", imag (i));\n%! endfor\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"1\"));\n\n%!test\n%! for i = [1,2,3,4]*I\n%!   __printf_assert__ (\"%d\", imag (i));\n%! endfor\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"1234\"));\n\n%!test\n%! for i = [1,2;3,4]*I\n%!   __printf_assert__ (\"%d\", imag (i(1,1)));\n%!   __printf_assert__ (\"%d\", imag (i(2,1)));\n%! endfor\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"1324\"));\n\n%!test\n%! for i = [1,2,3,4]\n%!   if (i > 2)\n%!     break;\n%!   endif\n%!   __printf_assert__ (\"%d\", i);\n%! endfor\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"12\"));\n\n%!test\n%! for i = [1,2,3,4]\n%!   if (i < 3)\n%!     continue;\n%!   endif\n%!   __printf_assert__ (\"%d\", i);\n%! endfor\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"34\"));\n\n%!test\n%! a = [1,3;2,4];\n%! j = 0;\n%! for i = cat (3, a, 4 + a)\n%!   assert (i, [1;2] + 2*j++);\n%! endfor\n\n%!test\n%! a = {1,3;2,4};\n%! j = 0;\n%! for i = cat (3, a, cellfun (@(x) 4 + x, a, \"UniformOutput\", 0))\n%!   assert (i, {1 + 2*j; 2 + 2*j++});\n%! endfor\n\n## test parsing of single-quoted character string appearing at the\n## beginning of a for loop\n%!test\n%! for i = 1:5\n%!   'foo';\n%! endfor\n%! assert (i, 5);\n\n%!test\n%! parfor i = 1\n%!   __printf_assert__ (\"%d\", i);\n%! end  # \"end\" is part of test, check not using \"endparfor\"\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"1\"));\n\n%!test\n%! parfor i = 1:4\n%!   __printf_assert__ (\"%d\", i);\n%! endparfor\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"1234\"));\n\n%!test <*55622>\n%! cnt = 0;\n%! for k = zeros (0,3)\n%!   cnt++;\n%! endfor\n%! assert (cnt, 3);\n%! assert (k, zeros (0,1));\n\n%!test <*55622>\n%! cnt = 0;\n%! for k = zeros (3,0)\n%!   cnt++;\n%! endfor\n%! assert (cnt, 0);\n%! assert (k, zeros (3,0));\n\n%!test <*50893>\n%! cnt = 0;\n%! for k = zeros (3,0, \"uint32\")\n%!   cnt++;\n%! endfor\n%! assert (cnt, 0);\n%! assert (k, zeros (3,0, \"uint32\"));\n\n%!test <*50893>\n%! cnt = 0;\n%! for k = cell (0,3)\n%!   cnt++;\n%! endfor\n%! assert (cnt, 3);\n%! assert (k, cell (0,1));\n\n%!test <*55622>\n%! cnt = 0;\n%! for k = zeros (1,2,3);\n%!   cnt++;\n%! endfor\n%! assert (cnt, 6);\n%! assert (k, 0);\n\n%!test <*55622>\n%! cnt = 0;\n%! for k = zeros (1,2,0);\n%!   cnt++;\n%! endfor\n%! assert (cnt, 0);\n%! assert (k, zeros (1,0));\n\n%!test <*45143>\n%! warning (\"on\", \"Octave:infinite-loop\", \"local\");\n%! fail (\"for i = 0:inf; break; end\", \"warning\",\n%!       \"FOR loop limit is infinite\");\n%!\n%! fail (\"for i = 0:-1:-inf; break; end\", \"warning\",\n%!       \"FOR loop limit is infinite\");\n%!\n%! fail (\"for i = inf:-1:1; break; end\", \"warning\",\n%!       \"FOR loop limit is infinite\");\n%!\n%! fail (\"for i = -inf:+1:1; break; end\", \"warning\",\n%!       \"FOR loop limit is infinite\");\n\n%!test <*45143>\n%! warning (\"on\", \"Octave:infinite-loop\", \"local\");\n%\n%! code = cstrcat (\"k = 0;               \",\n%!                 \"for i = 1:Inf;       \",\n%!                 \"  if (++k > 10);     \",\n%!                 \"    break;           \",\n%!                 \"  endif;             \",\n%!                 \"endfor;              \",\n%!                 \"assert (i, 11);      \");\n%! fail (code, \"warning\", \"FOR loop limit is infinite\");\n%!\n%! code = cstrcat (\"k = 0;               \",\n%!                 \"for i = -1:-1:-Inf;  \",\n%!                 \"  if (++k > 10);     \",\n%!                 \"    break;           \",\n%!                 \"  endif;             \",\n%!                 \"endfor;              \",\n%!                 \"assert (i, -11);     \");\n%! fail (code, \"warning\", \"FOR loop limit is infinite\");\n%!\n%! code = cstrcat (\"k = 0;               \",\n%!                 \"for i = Inf:-1:1;    \",\n%!                 \"  if (++k > 10);     \",\n%!                 \"    break;           \",\n%!                 \"  endif;             \",\n%!                 \"endfor;              \",\n%!                 \"assert (i, Inf);     \");\n%! fail (code, \"warning\", \"FOR loop limit is infinite\");\n%!\n%! code = cstrcat (\"k = 0;               \",\n%!                 \"for i = -Inf:+1:1;   \",\n%!                 \"  if (++k > 10);     \",\n%!                 \"    break;           \",\n%!                 \"  endif;             \",\n%!                 \"endfor;              \",\n%!                 \"assert (i, -Inf);    \");\n%! fail (code, \"warning\", \"FOR loop limit is infinite\");\n%!\n%! k = 0;\n%! for i = 1:-Inf\n%!   if (++k > 10)\n%!     break;\n%!   endif\n%! endfor\n%! assert (i, zeros (1,0));\n%!\n%! k = 0;\n%! for i = 0:-1:Inf\n%!   if (++k > 10)\n%!     break;\n%!   endif\n%! endfor\n%! assert (i, zeros (1,0));\n"
  },
  {
    "path": "test/func.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## This piece of test code ensures that all operations which work on\n## dimensions alone (squeeze, triu, etc.) work for all objects and\n## preserve type.  Even if the object is an empty matrix.  This code is\n## not to check that the function itself returns the correct result,\n## just that the results are consistent for all types.\n\n%!function __fntestfunc__ (fn, mn, varargin)\n%!  typ = {\"double\", \"complex\", \"logical\", \"sparse\", \"complex sparse\", ...\n%!         \"logical sparse\", \"int8\", \"int16\", \"int32\", \"int64\", \"uint8\", ...\n%!         \"uint16\", \"uint32\", \"uint64\", \"char\", \"cell\", \"struct\", ...\n%!         \"single\", \"single complex\"};\n%!\n%!  cmplx = [2, 5, 18];\n%!  nlogical = [3, 6];\n%!  ninteger = [7, 8, 9, 10, 11, 12, 13, 14];\n%!  nsparse = [4, 5, 6];\n%!  skip = {};\n%!\n%!  if (length (varargin) > 0 && iscell (varargin{1}))\n%!    skip = varargin{1};\n%!    varargin(1) = [];\n%!  endif\n%!\n%!  for i = 1 : length (typ)\n%!    if (any (strcmp (skip, typ {i})))\n%!      continue;\n%!    endif\n%!    m = mn;\n%!\n%!    if (any (nsparse == i))\n%!      if (ndims (m) > 2)\n%!        sz = size (m);\n%!        m = reshape (m, [sz(1), prod(sz(2:end))]);\n%!      endif\n%!      if (any (cmplx == i))\n%!        m = sparse ((1 + 1i) * m);\n%!      else\n%!        m = sparse (m);\n%!      endif\n%!    else\n%!      if (any (cmplx == i))\n%!        m = (1 + 1i) * m;\n%!      endif\n%!    endif\n%!    if (any (nlogical == i))\n%!      m = cast (m, \"logical\");\n%!    endif\n%!    if (any (ninteger == i))\n%!      m = cast (m, typ{i});\n%!    endif\n%!    if (strcmp (typ{i}, \"cell\"))\n%!      m = num2cell (m);\n%!    elseif (strcmp (typ{i}, \"struct\"))\n%!      m = struct (\"fld\", num2cell (m));\n%!    endif\n%!\n%!    y = feval (fn, m, varargin{:});\n%!    y2 = feval (fn, reshape (mn, size (m)), varargin{:});\n%!    if (! strcmp (class (y), class (m)) ||\n%!         issparse (y) != issparse (m) || ! size_equal (y, y2))\n%!      error (\"failed for type %s\\n\", typ{i});\n%!    endif\n%!    if (!(strcmp (typ{i}, \"cell\") || strcmp (typ{i}, \"struct\")) &&\n%!        any (vec (cast (real (y), \"double\")) !=\n%!             vec (feval (fn , cast (real (m), \"double\"), varargin{:}))))\n%!      error (\"failed for type %s\\n\", typ{i});\n%!    endif\n%!  endfor\n%!endfunction\n\n%!shared m0, m1, m2, m3\n%! m0 = [1:5];\n%! m1 = reshape ([1 : 30], [5, 6]);\n%! m2 = reshape ([1 : 30], [5, 1, 6]);\n%! m3 = [];\n\n%!test\n%! __fntestfunc__ (\"triu\", m1, {\"struct\"});\n%!test\n%! __fntestfunc__ (\"triu\", m1, {\"struct\"}, -1);\n%!test\n%! __fntestfunc__ (\"triu\", m1, {\"struct\"}, 1);\n%!test\n%! __fntestfunc__ (\"triu\", m3, {\"struct\"});\n%!test\n%! __fntestfunc__ (\"tril\", m1, {\"struct\"});\n%!test\n%! __fntestfunc__ (\"tril\", m1, {\"struct\"}, -1);\n%!test\n%! __fntestfunc__ (\"tril\", m1, {\"struct\"}, 1);\n%!test\n%! __fntestfunc__ (\"tril\", m3, {\"struct\"});\n%!test\n%! __fntestfunc__ (\"squeeze\", m2);\n%!test\n%! __fntestfunc__ (\"squeeze\", m3);\n%!test\n%! __fntestfunc__ (\"permute\", m1, [2, 1]);\n%!test\n%! __fntestfunc__ (\"permute\", m2, {\"sparse\", \"logical sparse\", \"complex sparse\"}, [3, 1, 2]);\n%!test\n%! __fntestfunc__ (\"permute\", m3, [2, 1]);\n%!test\n%! __fntestfunc__ (\"ipermute\", m1, [2, 1]);\n%!test\n%! __fntestfunc__ (\"ipermute\", m2, {\"sparse\", \"logical sparse\", \"complex sparse\"}, [3, 1, 2]);\n%!test\n%! __fntestfunc__ (\"ipermute\", m3, [2, 1]);\n%!test\n%! __fntestfunc__ (\"shiftdim\", m2, 1);\n%!test\n%! __fntestfunc__ (\"shiftdim\", m2, {\"sparse\", \"logical sparse\", \"complex sparse\"}, -1);\n%!test\n%! __fntestfunc__ (\"shiftdim\", m3, 1);\n%!test\n%! __fntestfunc__ (\"circshift\", m2, 1);\n%!test\n%! __fntestfunc__ (\"circshift\", m2, [1, -1]);\n%!test\n%! __fntestfunc__ (\"circshift\", m3, 1);\n%!test\n%! __fntestfunc__ (\"reshape\", m2, [6, 5]);\n%!test\n%! __fntestfunc__ (\"reshape\", m3, [1, 0]);\n%!test\n%! __fntestfunc__ (\"diag\", m0, {\"struct\"});\n%!test\n%! __fntestfunc__ (\"diag\", m0, {\"struct\"}, 1);\n%!test\n%! __fntestfunc__ (\"diag\", m0, {\"struct\"}, -1);\n%!test\n%! __fntestfunc__ (\"diag\", m1, {\"struct\"});\n%!test\n%! __fntestfunc__ (\"diag\", m1, {\"struct\"}, 1);\n%!test\n%! __fntestfunc__ (\"diag\", m1, {\"struct\"}, -1);\n%!test\n%! __fntestfunc__ (\"diag\", m3, {\"struct\"});\n%!test\n%! __fntestfunc__ (\"fliplr\", m1);\n%!test\n%! __fntestfunc__ (\"fliplr\", m3);\n%!test\n%! __fntestfunc__ (\"flipud\", m1);\n%!test\n%! __fntestfunc__ (\"flipud\", m3);\n%!test\n%! __fntestfunc__ (\"flip\", m1, 2);\n%!test\n%! __fntestfunc__ (\"flip\", m3, 2);\n%!test\n%! __fntestfunc__ (\"transpose\", m1);\n%!test\n%! __fntestfunc__ (\"transpose\", m3);\n%!test\n%! __fntestfunc__ (\"ctranspose\", m1);\n%!test\n%! __fntestfunc__ (\"ctranspose\", m3);\n%!test\n%! __fntestfunc__ (\"rot90\", m1);\n%!test\n%! __fntestfunc__ (\"rot90\", m1, 2);\n%!test\n%! __fntestfunc__ (\"rot90\", m1, -1);\n%!test\n%! __fntestfunc__ (\"rot90\", m3);\n%!test\n%! __fntestfunc__ (\"rotdim\", m2, 1, [1, 2]);\n%!test\n%! __fntestfunc__ (\"rotdim\", m2, 2, [1, 2]);\n%!test\n%! __fntestfunc__ (\"rotdim\", m2, -1, [1, 2]);\n%!test\n%! __fntestfunc__ (\"rotdim\", m3, 1, [1, 2]);\n\n## Check for error if function parameter is made persistent\n%!function retval = __fnpersist1__ (in1)\n%!  persistent retval;\n%!\n%!  retval = 1;\n%!endfunction\n\n%!function retval = __fnpersist2__ (in1)\n%!  persistent in1;\n%!\n%!  retval = in1;\n%!endfunction\n\n%!error <can't make function parameter retval persistent> __fnpersist1__ (1)\n%!error <can't make function parameter in1 persistent> __fnpersist2__ (1)\n\n## Check nargin, nargout validation by interpreter\n%!function __fn_nargout0__ (in1)\n%!endfunction\n%!function [out1] = __fn_nargin2__ (in1, in2)\n%!endfunction\n%!function [out1] = __fn_nargin0__ ()\n%!endfunction\n%!function [] = __fn_narginout0__ ()\n%!endfunction\n%!function __fn_no_arg_list__\n%!endfunction\n\n%!error <function called with too many outputs> r = __fn_nargout0__ ()\n%!error <function called with too many inputs>  r = __fn_nargin2__ (1,2,3)\n%!error <function called with too many inputs>  r = __fn_nargin0__ (1)\n%!error <function called with too many inputs>  __fn_narginout0__ (1)\n%!error <function called with too many outputs> r = __fn_narginout0__ ()\n%!error <function called with too many inputs>  __fn_no_arg_list__ (1)\n%!error <function called with too many outputs>  r = __fn_no_arg_list__ ()\n"
  },
  {
    "path": "test/global.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! global G = 1;\n%! assert (G,1);\n%! clear -global G;  # cleanup after test\n\n%!function f ()\n%!  global G;\n%!  assert (G,1);\n%!endfunction\n%!test\n%! global G = 1;\n%! f;\n%! clear -global G;  # cleanup after test\n\n%!function f ()\n%!  fail (\"G\");\n%!endfunction\n%!test\n%! global G = 1;\n%! f ();\n%! clear -global G;  # cleanup after test\n\n%!function f ()\n%!  global H = 1;\n%!endfunction\n%!test\n%! f;\n%! fail (\"H\");\n%! clear -global H;  # cleanup after test\n\n%!function f ()\n%!  global H = 1;\n%!endfunction\n%!test\n%!function g ()\n%!  fail (\"H\");\n%!test\n%! g ();\n%! clear -global H;  # cleanup after test\n\n%!function f ()\n%!  global H = 1;\n%!endfunction\n%!function g ()\n%!  global H;\n%!  assert (H,1);\n%!endfunction\n%!test\n%! f ();\n%! g ();\n%! clear -global H;  # cleanup after test\n\n%!test\n%!function f ()\n%!  global H = 1;\n%!endfunction\n%!test\n%! fail (\"H\");\n%! clear -global H;  # cleanup after test\n\n%!function f ()\n%!  global H = 1;\n%!endfunction\n%!function g ()\n%!  global H;\n%!  assert (H,1);\n%!endfunction\n%!test\n%! f;\n%! clear H;\n%! g;\n%! clear -global H;  # cleanup after test\n\n%!function r = f ()\n%!  x = 1;\n%!  global x;\n%!  r = x;\n%!endfunction\n%!test\n%! warning (\"off\", \"Octave:global-local-conflict\", \"local\");\n%! clear global x      ## clears global and local value\n%! global x;\n%! x = 0;\n%! assert (f (), 0);\n%! global x;\n%! assert (x, 0);\n%!test\n%! warning (\"off\", \"Octave:global-local-conflict\", \"local\");\n%! clear global x      ## clears global and local value\n%! assert (f (), 1);\n%! global x;\n%! assert (x, 1);\n%! clear -global x;  # cleanup after test\n\n%!function r = f ()\n%!  x = 1;\n%!  global x = 3;\n%!  r = x;\n%!endfunction\n%!test\n%! warning (\"off\", \"Octave:global-local-conflict\", \"local\");\n%! clear global x      ## clears global and local value\n%! global x;\n%! x = 0;\n%! assert (f (), 0);\n%! global x;\n%! assert (x, 0);\n%!test\n%! warning (\"off\", \"Octave:global-local-conflict\", \"local\");\n%! clear global x\n%! assert (f (), 1);\n%! global x;\n%! assert (x, 1);\n%! clear -global x;  # cleanup after test\n\n%!test\n%! warning (\"off\", \"Octave:global-local-conflict\", \"local\");\n%! clear global x      ## clears global and local value\n%! x = 42;             ## local value\n%! global x;           ## link to undefined global, global gets local value\n%! assert (x, 42);\n%! clear x             ## clears local; global still defined\n%! x = 13;             ## new local value\n%! global x;           ## link to existing global, local gets global value\n%! assert (x, 42);\n%! clear global x      ## clears global and local value\n%! assert (exist (\"x\"), 0);\n%! clear -global x;  # cleanup after test\n"
  },
  {
    "path": "test/help/cdefdir/cdef_help1.m",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%\n%% Copyright (C) 2024-2026 The Octave Project Developers\n%%\n%% See the file COPYRIGHT.md in the top-level directory of this\n%% distribution or <https://octave.org/copyright/>.\n%%\n%% This file is part of Octave.\n%%\n%% Octave is free software: you can redistribute it and/or modify it\n%% under the terms of the GNU General Public License as published by\n%% the Free Software Foundation, either version 3 of the License, or\n%% (at your option) any later version.\n%%\n%% Octave is distributed in the hope that it will be useful, but\n%% WITHOUT ANY WARRANTY; without even the implied warranty of\n%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n%% GNU General Public License for more details.\n%%\n%% You should have received a copy of the GNU General Public License\n%% along with Octave; see the file COPYING.  If not, see\n%% <https://www.gnu.org/licenses/>.\n%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% class cdef_help1 : class help text ABOVE classdef keyword.\n%\n% Type 'help cdef_help1'\n\nclassdef cdef_help1\n  % -*- texinfo -*-\n  % class cdef_help1 : class help text BELOW classdef keyword.\n  %\n  % Type 'help cdef_help1'\n\n  properties\n    % prop1: property help text ABOVE property name.\n    % Type \"help cdef_help1.prop1\"\n    prop1   % prop1: EOL-comment text.  Should not be displayed\n    prop2   % prop2: property help text in EOL-comment for property PROP2.  Type \"help cdef_help1.prop2\"\n  end\n\n  methods\n\n    % cdef_help1: constructor help text ABOVE function keyword\n    % Type 'help cdef_help1.cdef_help1'.\n    function obj = cdef_help1 (p1, p2)\n      % cdef_help1: constructor help text BELOW function keyword\n      % Type 'help cdef_help1.cdef_help1'.\n      if (nargin ~= 2)\n        obj.prop1 = 'default';\n        obj.prop2 = 42;\n      else\n        obj.prop1 = p1;\n        obj.prop2 = p2;\n      end\n    end\n\n    % meth1: method help text ABOVE function\n    %\n    % Type 'help cdef_help1.meth1'.\n    function obj2 = meth1 (obj, n)\n      obj2 = n + obj;\n    end\n\n    function obj2 = meth2 (obj, n)\n\n      % meth2: method help text BELOW function\n      % The blank line between function and comment is intentional.\n      % Type 'help cdef_help1.meth2'.\n      obj2 = n - obj;\n    end\n\n    % meth3: method help text ABOVE function\n    % Type 'help cdef_help1.meth3'.\n    % This should not be shown.\n    function obj3 = meth3 (obj, n)\n      % meth3: method help text BELOW function\n      % Type 'help cdef_help1.meth3'.\n      % This should be displayed.\n      obj3 = obj + n;\n    end\n\n    function obj4 = meth4 (obj, n)\n\n      obj4 = n - obj;\n      if (n)\n        % meth4: pure comment text.  This should *never* be displayed.\n        % Type 'help cdef_help1.meth4'.\n      end\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "test/help/cdefdir/cdef_help2.m",
    "content": "########################################################################\n##\n## Copyright (C) 2024-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nclassdef cdef_help2\n  # -*- texinfo -*-\n  # class cdef_help2 : class help text BELOW classdef keyword.\n  #\n  # Type 'help cdef_help2'\n\n  properties\n    # prop1: property help text ABOVE property name.\n    # Type \"help cdef_help2.prop1\"\n    prop1   # prop1: EOL-comment text.  Should not be displayed\n    prop2   # prop2: property help text in EOL-comment for property PROP2.  Type \"help cdef_help2.prop2\"\n  end\n\n  methods\n\n    # cdef_help2: constructor help text ABOVE function keyword\n    # Type 'help cdef_help2.cdef_help2'.\n    # This should be shown because Octave comment character '#' is used.\n    function obj = cdef_help2 (p1, p2)\n      # cdef_help2: constructor help text BELOW function keyword\n      # Type 'help cdef_help2.cdef_help2'.\n      if (nargin ~= 2)\n        obj.prop1 = 'default';\n        obj.prop2 = 42;\n      else\n        obj.prop1 = p1;\n        obj.prop2 = p2;\n      end\n    end\n\n    # meth1: method help text ABOVE function\n    #\n    # Type 'help cdef_help2.meth1'.\n    function obj2 = meth1 (obj, n)\n      obj2 = n + obj;\n    end\n\n    function obj2 = meth2 (obj, n)\n\n      # meth2: method help text BELOW function\n      # The blank line between function and comment is intentional.\n      # Type 'help cdef_help2.meth2'.\n      obj2 = n - obj;\n    end\n\n    # meth3: method help text ABOVE function\n    # Type 'help cdef_help2.meth3'.\n    # This should be shown because Octave comment character '#' is used.\n    function obj3 = meth3 (obj, n)\n      # meth3: method help text BELOW function\n      # Type 'help cdef_help2.meth3'.\n      # This should NOT be displayed.\n      obj3 = obj + n;\n    end\n\n    function obj4 = meth4 (obj, n)\n\n      obj4 = n - obj;\n      if (n)\n        # meth4: pure comment text.  This should *never* be displayed.\n        # Type 'help cdef_help2.meth4'.\n      end\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "test/help/cdefdir/cdef_help3.m",
    "content": "########################################################################\n##\n## Copyright (C) 2024-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nclassdef cdef_help3\n  properties\n    prop1 = 13;\n    prop2 = 42;\n  end\n\n  methods\n    function obj = cdef_help3 (p1, p2)\n      obj.prop1 = p1;\n      obj.prop2 = p2;\n    end\n  end\nend\n"
  },
  {
    "path": "test/help/cdefdir/cdef_help4.m",
    "content": "########################################################################\n##\n## Copyright (C) 2024-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nclassdef cdef_help4\n  properties\n    prop1 = 13;\n    prop2 = 42;\n  end\nend\n"
  },
  {
    "path": "test/help/function_with_utf_8_doc_string.m",
    "content": "## -*- texinfo -*-\n## This is a very naïve function with Unicode in its first line.\nfunction function_with_utf_8_doc_string ()\nendfunction\n"
  },
  {
    "path": "test/help/help.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2024-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   ## Check methods first (bug was disguised if class checked first)\n%!   s = help ('cdef_help1.meth1');\n%!   assert (regexp (s, 'meth1: method help text ABOVE function'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help1.meth2');\n%!   assert (regexp (s, 'meth2: method help text BELOW function'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help1.meth3');\n%!   assert (regexp (s, 'meth3: method help text BELOW function'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65258>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help1.meth4');\n%!   assert (regexp (s, 'undocumented method: obj4 = meth4 \\(obj, n\\)'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   ## Check documentation for entire class\n%!   s = help ('cdef_help1');\n%!   assert (regexp (s, 'class cdef_help1 : class help text ABOVE classdef'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   ## Check documentation for constructor\n%!   s = help ('cdef_help1.cdef_help1');\n%!   assert (regexp (s, 'cdef_help1: constructor help text BELOW function'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   ## Check documentation for properties\n%!   s = help ('cdef_help1.prop1');\n%!   assert (regexp (s, 'prop1: property help text ABOVE property'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help1.prop2');\n%!   assert (regexp (s, 'prop2: property help text in EOL-comment'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   ## Check methods first (bug was disguised if class checked first)\n%!   s = help ('cdef_help2.meth1');\n%!   assert (regexp (s, 'meth1: method help text ABOVE function'));\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help2.meth2');\n%!   assert (regexp (s, 'meth2: method help text BELOW function'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help2.meth3');\n%!   assert (regexp (s, 'meth3: method help text ABOVE function'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help2.meth4');\n%!   assert (regexp (s, 'undocumented method: obj4 = meth4 \\(obj, n\\)'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   ## Check documentation for entire class\n%!   s = help ('cdef_help2');\n%!   assert (regexp (s, 'class cdef_help2 : class help text BELOW classdef'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   ## Check documentation for constructor\n%!   s = help ('cdef_help2.cdef_help2');\n%!   assert (regexp (s, 'cdef_help2: constructor help text ABOVE function'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   ## Check documentation for properties\n%!   s = help ('cdef_help2.prop1');\n%!   assert (regexp (s, 'prop1: property help text ABOVE property'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65220>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help2.prop2');\n%!   assert (regexp (s, 'prop2: property help text in EOL-comment'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65258>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help3');\n%!   assert (regexp (s, 'undocumented constructor: obj = cdef_help3 \\(p1, p2\\)'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65258>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help3.cdef_help3');\n%!   assert (regexp (s, 'undocumented constructor: obj = cdef_help3 \\(p1, p2\\)'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65258>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help4');\n%!   assert (regexp (s, 'default constructor: obj = cdef_help4 \\(\\)'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!test <*65258>\n%! unwind_protect\n%!   addpath ('cdefdir');\n%!\n%!   s = help ('cdef_help4.cdef_help4');\n%!   assert (regexp (s, 'default constructor: obj = cdef_help4 \\(\\)'));\n%!\n%! unwind_protect_cleanup\n%!   rmpath ('cdefdir');\n%! end_unwind_protect\n\n%!assert <*65258> (regexp (help ('undoc_fcn'), 'undocumented function: \\[x, y, z\\] = undoc_fcn \\(a, b, ~, c = 3\\)'))\n\n## patch #10541\n%!assert (get_first_help_sentence ('function_with_utf_8_doc_string', 21), ...\n%!        'This is a very naï...')\n"
  },
  {
    "path": "test/help/module.mk",
    "content": "help_TEST_FILES = \\\n  %reldir%/function_with_utf_8_doc_string.m \\\n  %reldir%/help.tst \\\n  %reldir%/undoc_fcn.m \\\n  %reldir%/cdefdir/cdef_help1.m \\\n  %reldir%/cdefdir/cdef_help2.m \\\n  %reldir%/cdefdir/cdef_help3.m \\\n  %reldir%/cdefdir/cdef_help4.m\n\nTEST_FILES += $(help_TEST_FILES)\n"
  },
  {
    "path": "test/help/undoc_fcn.m",
    "content": "function [x, y, z] = undoc_fcn (a, b, ~, c = 3)\n  x = a;\n  y = b;\n  z = c;\nend\n"
  },
  {
    "path": "test/if.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! i = 0;\n%! if (i == 0)\n%!   i++;\n%!   __printf_assert__ (\"%d\\n\", i);\n%! end  # \"end\" is part of test, check not using \"endif\"\n%! assert (__prog_output_assert__ (\"1\"));\n\n%!test\n%! if (eye (2))\n%!   __printf_assert__ (\"fail\\n\");\n%! else\n%!   __printf_assert__ (\"pass\\n\");\n%! endif\n%! assert (__prog_output_assert__ (\"pass\"));\n\n%!test\n%! x = 2;\n%! if (eye (2))\n%!   __printf_assert__ (\"fail\\n\");\n%! elseif (x)\n%!   __printf_assert__ (\"pass\\n\");\n%! endif\n%! assert (__prog_output_assert__ (\"pass\"));\n\n%!test <63935>\n%! if (true (4, 1) & true (4, 1))\n%!   __printf_assert__ (\"pass\\n\");\n%! elseif (x)\n%!   __printf_assert__ (\"fail\\n\");\n%! endif\n%! assert (__prog_output_assert__ (\"pass\"));\n\n%!test\n%! x = 0;\n%! y = -2;\n%! if (eye (2))\n%!   __printf_assert__ (\"fail\\n\");\n%! elseif (x)\n%!   __printf_assert__ (\"fail\\n\");\n%! elseif (y)\n%!   __printf_assert__ (\"pass\\n\");\n%! endif\n%! assert (__prog_output_assert__ (\"pass\"));\n\n%!test\n%! x = 0;\n%! y = -2;\n%! if (eye (2))\n%!   __printf_assert__ (\"fail\\n\");\n%! elseif (x)\n%!   __printf_assert__ (\"fail\\n\");\n%! elseif (x)\n%!   __printf_assert__ (\"fail\\n\");\n%! else\n%!   __printf_assert__ (\"pass\\n\");\n%! endif\n%! assert (__prog_output_assert__ (\"pass\"));\n\n%!test\n%! x = 0;\n%! y = -2;\n%! if (y)\n%!   __printf_assert__ (\"pass\\n\");\n%! elseif (x)\n%!   __printf_assert__ (\"fail\\n\");\n%! elseif (x)\n%!   __printf_assert__ (\"fail\\n\");\n%! endif\n%! assert (__prog_output_assert__ (\"pass\"));\n\n## test parsing of single-quoted character string appearing at the\n## beginning of an if condition\n%!test\n%! if (1)\n%!   'foo';\n%!   x = 13;\n%! endif\n%! assert (x, 13);\n\n## test parsing of single-quoted character string appearing at the\n## beginning of an if condition\n%!test\n%! if (0)\n%!   x = 42;\n%! elseif (1)\n%!   'foo';\n%!   x = 13;\n%! endif\n%! assert (x, 13);\n\n## test \"is_true\" of different data types\n%!error diag (NaN) || 0\n%!test\n%! d1 = diag ([])    || 0;\n%! d2 = diag (1)     || 0;\n%! d3 = diag ([1 2]) || 0;\n%! assert ([d1 d2 d3], [false true false]);\n\n%!error sparse (NaN) || 0\n%!error sparse ([1 1 ; 1 NaN]) || 0\n%!test\n%! s1 = sparse ([])  || 0;\n%! s2 = sparse (1)   || 0;\n%! s3 = sparse ([1 0 ; 0 2])   || 0;\n%! s4 = sparse ([1 1 ; 1 1])   || 0;\n%! assert ([s1 s2 s3 s4], [false true false true]);\n\n%!test\n%! r1 = (1:10) || 0;\n%! r2 = (-10:-1) || 0;\n%! r3 = (-1:1) || 0;\n%! assert ([r1 r2 r3], [true true false]);\n\n%!test\n%! c1 = [2i 4i] || 0;\n%! c2 = [22 4i] || 0;\n%! c3 = i || 0;\n%! c4 = complex (0) || 0;\n%! assert ([c1 c2 c3 c4], [true true true false]);\n"
  },
  {
    "path": "test/index.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! a = [];\n%! assert (isempty (a));\n\n%!shared a\n%! a = 1;\n%!assert (a(1), 1)\n%!assert (a(:), 1)\n%!assert (a(:,:), 1)\n%!assert (a(1,:), 1)\n%!assert (a(:,1), 1)\n%!assert (isempty (a(logical (0))))\n%!error a(-1)\n%!error a(0)\n%!error a(1.5)\n%!error a(2)\n%!error a(2,:)\n%!error a(:,2)\n%!error a(-1,:)\n%!error a(:,-1)\n%!error a(0,:)\n%!error a(:,0)\n%!error a(1.5,:)\n%!error a(:,1.5)\n%!error a([1,2,3])\n%!error a([1;2;3])\n%!error a([1,2;3,4])\n%!error a([-1,0])\n%!error a([-1;0])\n%!error a([0,1])\n%!error a([0;1])\n%!error a([1.5,1])\n%!error a([1.5;1])\n%!error a([1,1.5])\n%!error a([1,1.5])\n\n%!shared a, a_prime, mid_a\n%! a = [4,3,2,1];\n%! a_prime = [4;3;2;1];\n%! mid_a = [3,2];\n\n%!assert (a(1),4)\n%!assert (a(2),3)\n%!assert (all (a(:) == a_prime))\n%!assert (all (a(1,:) == a))\n%!assert (a(:,3),2)\n%!assert (all (a(:,:) == a))\n%!assert (all (a(logical ([0,1,1,0])) == mid_a))\n%!error a(0)\n%!error a(5)\n%!error a(0,1)\n%!assert (isempty (a(logical (0),:)))\n%!error a(:,0)\n%!assert (isempty (a([])))\n%!assert (isempty (a([],:)))\n%!assert (isempty (a(:,[])))\n\n%!shared a, a_fvec, a_col_1, a_col_2, a_row_1, a_row_2\n%! a = [1,2;3,4];\n%! a_fvec = [1;3;2;4];\n%! a_col_1 = [1;3];\n%! a_col_2 = [2;4];\n%! a_row_1 = [1,2];\n%! a_row_2 = [3,4];\n\n%!assert (all (all (a(:,:) == a)))\n%!assert (all (a(:) == a_fvec))\n%!error a(0)\n%!assert (a(2), 3)\n\n## Additional tests\n\n%!shared a, b\n%! a = [1,2;3,4];\n%! b = a;\n%! b(:,:,2) = [5,6;7,8];\n\n%!assert (a(:), [1;3;2;4])\n%!assert (a(1:2), [1,3])\n%!assert (a(:,:), [1,2;3,4])\n%!assert (a(:,1), [1;3])\n%!assert (a(1,1), 1)\n%!assert (a(1:2,1), [1;3])\n%!assert (a(:,:,1), [1,2;3,4])\n\n%!test\n%! c(:,:,1) = [1,2;3,4];\n%! c(:,:,2) = [1,2;3,4];\n%! assert (a(:,:,[1,1]), c);\n\n%!test\n%! c(:,:,1,1) = [1,2;3,4];\n%! c(:,:,1,2) = [1,2;3,4];\n%! assert (a(:,:,1,[1,1]), c);\n\n%!test\n%! c(:,:,1,1) = [1,2;3,4];\n%! c(:,:,2,1) = [1,2;3,4];\n%! c(:,:,1,2) = [1,2;3,4];\n%! c(:,:,2,2) = [1,2;3,4];\n%! assert (a(:,:,[1,1],[1,1]), c);\n\n%!assert (a(1,[]), zeros (1,0))\n%!assert (a(1,[],[1,1]), zeros (1,0,2))\n%!assert (a(1,1,[]), zeros (1,1,0))\n\n%!test\n%! c (1:10,1) = 1:10;\n%! assert (c, [1:10]');\n\n%!assert (b(:), [1; 3; 2; 4; 5; 7; 6; 8])\n%!assert (b(:,:), [1, 2, 5, 6; 3, 4, 7, 8])\n%!assert (b(:,1), [1;3])\n%!assert (b(:,:,:), reshape ([1,3,2,4,5,7,6,8], [2,2,2]))\n%!assert (b(:,1,1), [1;3])\n%!assert (b(:,1,1,[1,1]),reshape ([1,3,1,3], [2,1,1,2]))\n%!assert (b(1,3), 5)\n%!assert (b(1,[3,4]), [5,6])\n%!assert (b(1,1:4), [1,2,5,6])\n%!assert (b(1,[],:), zeros (1,0,2))\n%!assert (b(1,[]), zeros (1,0))\n%!assert (b(:,3), [5;7])\n%!assert (b([1,2],3), [5;7])\n%!assert (b(true (2,1), 3), [5;7])\n%!assert (b(false (2,1), 3), zeros (0,1))\n%!assert (b([],3), zeros (0,1))\n\n%!shared x\n%! ## Dummy shared block to clear any previous definitions\n%! x = 1;\n\n%!test\n%! a(1,:) = [1,3];\n%! assert (a, [1,3]);\n\n%!test\n%! a(1,:) = [1;3];\n%! assert (a, [1,3]);\n\n%!test\n%! a(:,1) = [1;3];\n%! assert (a, [1;3]);\n\n%!test\n%! a = [1,2;3,4];\n%! b (1,:,:) = a;\n%! assert (b, reshape (a, [1,2,2]));\n\n%!test\n%! a(1,1:4,2) = reshape (1:4, [1,1,4]);\n%! b(:,:,2) = 1:4;\n%! assert (a, b);\n\n%!test\n%! a(:,:,:) = 1:4;\n%! assert (a, [1:4]);\n\n%!test\n%! a(:,:,1) = 1:4;\n%! assert (a, [1:4]);\n\n%!test\n%! a(:,:,1) = [1:4]';\n%! assert (a, [1:4]');\n\n%!test\n%! a(:,:,1) = reshape (1:4,[1,1,4]);\n%! assert (a, [1:4]');\n\n%!test\n%! a(:,1,:) = 1:4;\n%! assert (a, reshape (1:4,[1,1,4]));\n\n%!test\n%! a(:,1,:) = [1:4]';\n%! assert (a, [1:4]');\n\n%!test\n%! a(:,1,:) = reshape (1:4,[1,1,4]);\n%! assert (a, [1:4]');\n\n%!test\n%! a(1,:,:) = 1:4;\n%! assert (a, reshape (1:4,[1,1,4]));\n\n%!test\n%! a(1,:,:) = [1:4]';\n%! assert (a, [1:4]);\n\n%!test\n%! a(1,:,:) = reshape (1:4,[1,1,4]);\n%! assert (a, [1:4]);\n\n%!test\n%! a(1,:,:,:) = reshape (1:4,[1,1,4]);\n%! assert (a, reshape (1:4,[1,1,1,4]));\n\n%!error (a(1:2,1:2) = 1:4)\n\n## bug #38357\n%!shared d, dd\n%! d = diag ([1, 2, 3]);\n%! dd = diag ([1, 2, 3], 6, 3);\n%!assert (d(1), 1)\n%!assert (dd(1), 1)\n%!assert (d(3, 3), 3)\n%!assert (dd(3, 3), 3)\n%!assert (d(2), 0)\n%!assert (dd(2), 0)\n%!assert (dd(6,1), 0)\n%!error d(6,6)\n%!error dd(6,6)\n%!error d(3,6)\n%!error dd(3,6)\n\n## bug 31287\n%!test\n%! y = ones (2, 2, 2);\n%! x = ones (2, 2, 2);\n%! x(false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2, 2);\n%! x = ones (2, 2, 2);\n%! x(false,[]) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2, 2);\n%! x = ones (2, 2, 2);\n%! x(false,[],false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2, 2);\n%! x = ones (2, 2, 2);\n%! x(false, 1) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2, 2);\n%! x = ones (2, 2, 2);\n%! x(false, false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x([], []) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse (ones (2, 2));\n%! x = sparse (ones (2, 2));\n%! x([], []) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(1, []) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x([], 1, []) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(1, [], 1, 1) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x([], 1, 1) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! ea2 = ones (3, 2, 0, 2);\n%! x(1, ea2) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse (ones (2, 2));\n%! x = sparse (ones (2, 2));\n%! ea2 = ones (3, 2, 0, 2);\n%! x(1, ea2) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! ea2 = ones (3, 2, 0, 2);\n%! x([], 1, ea2) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! ea2 = ones (3, 2, 0, 2);\n%! x(1, ea2, ea2) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! ea2 = ones (3, 2, 0, 2);\n%! x(1, ea2, 1) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(false, 1) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse (ones (2, 2));\n%! x = sparse (ones (2, 2));\n%! x(false, 1) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(1, [], false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(false, false) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse (ones (2, 2));\n%! x = sparse (ones (2, 2));\n%! x(false, false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(false, [], false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x([], false, false, false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(1, [], false, false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(:, false) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse (ones (2, 2));\n%! x = sparse (ones (2, 2));\n%! x(:, false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(false, :) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse (ones (2, 2));\n%! x = sparse (ones (2, 2));\n%! x(false, :) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(false, :, [], 1) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(:, [], false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%!error x(1, 1, []) = []\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(false, false, 1) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(false, false, []) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(false, false, [], false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(1, false, [], false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(:, false, 1) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x([]) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse (ones (2, 2));\n%! x = sparse (ones (2, 2));\n%! x([]) = [];\n%! assert (x, y);\n\n%!test\n%! y = [];\n%! x = ones (2, 2);\n%! x(:) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse ([]);\n%! x = sparse (ones (2, 2));\n%! x(:) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x(false) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse (ones (2, 2));\n%! x = sparse (ones (2, 2));\n%! x(false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x([], false) = [];\n%! assert (x, y);\n\n%!test\n%! y = sparse (ones (2, 2));\n%! x = sparse (ones (2, 2));\n%! x([], false) = [];\n%! assert (x, y);\n\n%!test\n%! y = ones (2, 2);\n%! x = ones (2, 2);\n%! x([], false, :) = [];\n%! assert (x, y);\n\n## Test deletion of non-existent dimensions\n%!test\n%! x = ones (10, 10, 2);\n%! x(:, :, 1) = [];\n%! x(:, :, 1) = [];\n%! assert (size (x), [10, 10, 0]);\n\n%!test\n%! x = ones (10, 10);\n%! x(:,:,:, 1) = [];\n%! assert (size (x), [10, 10, 1, 0]);\n\n%!test\n%! x = ones (10, 10);\n%! try\n%!   x(:,:,2) = [];\n%! catch\n%!   m = strfind (lasterr (), 'index out of bounds: value 2 out of bound 1');\n%!   assert (m > 0);\n%! end_try_catch\n%! assert (size (x), [10, 10]);\n\n##  Test indexing with extreme values\n%!shared a\n%! a = ones (1e6,0);\n%!error <a\\(-[Ii][Nn][Ff]\\): subscripts> a(-Inf)\n%!error <a\\([Ii][Nn][Ff]\\): subscripts>  a(Inf)\n%!error <a\\(-?[Nn][Aa][Nn]\\): subscripts> a(-NaN)\n%!error <a\\([Nn][Aa][Nn]\\): subscripts>  a(NaN)\n%!error <a\\(.+\\): subscripts> a(flintmax + 2)\n%!testif ; __have_feature__ ('ENABLE_64')\n%! fail ('a(intmax (\"int64\"))', 'a\\(9223372036854775807\\): out of bound');\n%! fail ('a(double (intmax (\"int64\")))', 'a\\(.+\\): subscripts');\n%! a = zeros ((intmax ('int64') - 512), 0);\n%! fail ('a(intmax (\"uint64\"))', 'a\\(18446744073709551615\\): subscripts');\n%!testif ; ! __have_feature__ ('ENABLE_64')\n%! fail ('a(intmax (\"int32\"))', 'a\\(2147483647\\): out of bound');\n%! fail ('a(double (intmax (\"int32\")))', 'a\\(.+\\): subscripts');\n%! a = zeros ((intmax ('int32') - 1), 0);\n%! fail ('a(double (intmax (\"uint32\")))', 'a\\(.+\\): subscripts');\n%! fail ('a(intmax (\"uint64\"))', 'a\\(18446744073709551615\\): subscripts');\n\n##  Test indexing of unnamed constants\n%!error <index \\(0\\): subscripts must be>     1(0)\n%!error <index \\(-1\\): subscripts must be>    1(-1)\n%!error <index \\(_,0.5\\): subscripts>                 {}(1,0.5)\n%!error <index \\([Nn][aA][Nn],_\\): subscripts>                 1(NaN,1)\n%!error <index \\(_,_,<cell....\\[x8\\]...\\): subscripts> [](1,1,{},1,1,1,1,1,1,1,1)\n%!error <index \\(...\\[x9\\]...-1,_\\): subscript>      1(1,1,1,1,1,1,1,1,1,-1,1)\n%!error <index \\(2\\): out of bound 1>                1(2)\n%!error <index \\(1\\): out of bound 0>                [](1)\n%!error <index \\(-1\\): subscripts>                   1(1)(-1)(1)\n%!error <index \\(_,1\\): out of bound 0 \\(dimensions are 5x0\\)> zeros (5,0)(3,1)\n%!error <index \\(3,_\\): out of bound 0 \\(dimensions are 0x5\\)> zeros (0,5)(3,1)\n%!\n%!shared abc\n%! abc = [1, 2];\n%! ##  Test full matrices in variables\n%!error <abc\\(3\\): out of bound 2>      abc([false, true, true])\n%!error <abc\\(-1\\): subscripts>         abc(-1)(1)(1)\n%! ## xerror <index \\(-1\\): subscripts> abc(1)(-1)(1)   ## why no 'xerror' test?\n\n%!shared abc\n%! abc = [1 2; 3 4];\n%!error <abc\\(5\\): out of bound 4>         abc(5)\n%!error <abc\\(_,3\\): out of bound 2 \\(dimensions are 2x2\\)> abc(2,3)\n%!error <abc\\(_,_,0.5\\): subscripts>       exp (abc(2,3,0.5))\n\n%!shared abc\n%! abc = [1 2; 3 4]; abc(1,1,2) = 1;\n%!error <abc\\(_,5\\): out of bound 4>                            abc(2,5)\n%!error <abc\\(_,3,_\\): out of bound 2 \\(dimensions are 2x2x2\\)> abc(2,3,2)\n%!error <A\\(..,I,..\\) = \\[\\]: .* value 3 out of bound 2>        abc(3,:) = []\n%!error <A\\(I\\) = \\[\\]: .* value 50 out of bound 8>             abc(3:50) = []\n%!error <a null assignment can only have one non-colon index>   abc(3,5) = []\n%!error <=: nonconformant arguments \\(op1 is 1x1, op2 is 1x5\\)> abc(3,5) = 1:5\n\n##  Test diagonal matrices, and access of function results\n%!error <index \\(_,_,5\\): out of bound 1 \\(dimensions are 3x3\\)> eye (3)(2,3,5)\n%!error <index \\(-2,_\\): subscripts>               eye (4)(-2,3)\n\n##  Test cells\n%!shared abc\n%! abc = {1, 2; 3, 4};\n%!error <abc\\(_,0.3,_\\): subscripts>  abc(2,0.3,5)\n%!error <abc\\(_,0.3,_\\): subscripts>  abc{2,0.3,5}\n%!error <abc\\(-2,_,_,_\\): subscripts> abc{-2,1,1,1}\n%!error <abc\\(0,_,_,_\\): subscripts>  abc(0,1,1,1) = 1\n\n##  Test permutation matrices\n%!shared abc\n%! abc = eye(3)([3 1 2],:);\n%!error <abc\\([Nn][aA][Nn]\\): subscripts>         abc(NA)\n%!error <abc\\(_,_,_,[Ii][nN][Ff],_\\): subscripts> abc(1,1,1,Inf,1)\n\n##  Test sparse matrices\n%!shared abc\n%! abc = sparse (3,3);\n%!error <abc\\(-1\\): subscripts>                abc(-1)\n%!error <abc\\(-1\\): subscripts>                abc(-1) = 1\n%!error <abc\\(-1,_\\): subscripts>              abc(-1,1)\n%!error <abc\\(-1,_\\): subscripts>              abc(-1,1) = 1\n%!error <only 2-D indexing is allowed for sparse arrays> abc(1,1,1,1)\n%!error <only 2-D indexing is allowed for sparse arrays>\n%! ndidx(:,:,1) = [4, 9];\n%! ndidx(:,:,2) = [1, 6];\n%! abc(ndidx);\n%!error <abc\\(4,_\\): out of bound 3 \\(dimensions are 3x3\\)> abc(4,1)\n\n##  Test ranges\n%!shared abc\n%! abc = 1:10;\n%!error <abc\\(-1\\): subscripts>             abc(-1)\n%!error <abc\\(-1,_\\): subscripts>           abc(-1,1)\n%!error <abc\\(4,_\\): out of bound 1 \\(dimensions are 1x10\\)> abc(4,1)\n\n##  Test complex\n%!shared abc, z\n%! abc = [1 2];\n%!error <abc\\(0\\+1i\\): subscripts must be real>     abc(i)\n%! abc = [1 2; 3 4];\n%!error <abc\\(1\\+0i\\): subscripts must be real>     abc(complex (1))\n%!error <abc\\(1\\+0.5i,_\\): subscripts must be real> abc(1+0.5*i,3)\n%!error <abc\\(_,0-2i\\): subscripts must be real>    abc(2,0-2*i)\n\n%!test <*35841>\n%! a(1,1,1).b(1) = 2;\n%! a(1,1,1).b(1) = 3;\n\n%!test <*39789>\n%! c = cell (1,1,1);\n%! c{1,1,1} = zeros(5, 2);\n%! c{1,1,1}(:, 1) = 1;\n"
  },
  {
    "path": "test/inline-fcn.tst",
    "content": "## INLINE contstructor\n\n%!shared fn\n%! fn = inline (\"x.^2 + 1\");\n%!assert (feval (fn, 6), 37)\n%!assert (fn (6), 37)\n%!assert (feval (inline (\"sum (x(:))\"), [1 2; 3 4]), 10)\n%!assert (feval (inline (\"sqrt (x^2 + y^2)\", \"x\", \"y\"), 3, 4), 5)\n%!assert (feval (inline (\"exp (P1*x) + P2\", 3), 3, 4, 5), exp (3*4) + 5)\n\n## Test input validation\n%!error inline ()\n%!error <EXPR must be a string> inline (1)\n%!error <N must be an integer> inline (\"2\", ones (2,2))\n%!error <N must be a positive integer> inline (\"2\", -1)\n%!error <additional arguments must be strings> inline (\"2\", \"x\", -1, \"y\")\n\n## FORMULA\n\n%!assert (formula (fn), \"x.^2 + 1\")\n%!assert (formula (fn), char (fn))\n\n## ARGNAMES\n\n%!assert (argnames (fn), {\"x\"})\n%!assert (argnames (inline (\"1e-3*y + 2e4*z\")), {\"y\"; \"z\"})\n%!assert (argnames (inline (\"2\", 2)), {\"x\"; \"P1\"; \"P2\"})\n\n## VECTORIZE\n\n%!assert (formula (vectorize (fn)), \"x.^2 + 1\")\n%!assert (formula (vectorize (inline (\"1e-3*y + 2e4*z\"))), \"1e-3.*y + 2e4.*z\")\n%!assert (formula (vectorize (inline (\"2^x^5\"))), \"2.^x.^5\")\n"
  },
  {
    "path": "test/integer.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Test saturation mechanics of lower bound\n%!test\n%! for cls = {\"int8\", \"uint8\", \"int16\", \"uint16\", \"int32\", \"uint32\", \"int64\", \"uint64\"}\n%!   clsmin = intmin (cls{1});\n%!   xplus = clsmin + (-1);\n%!   assert (xplus, clsmin);\n%!   xminus = clsmin -1;\n%!   assert (xminus, clsmin);\n%!   xmult = clsmin * 2;\n%!   assert (xmult, clsmin);\n%!   xdiv = clsmin / 0.5;\n%!   assert (xdiv, clsmin);\n%! endfor\n\n## Test saturation mechanics of upper bound\n%!test\n%! for cls = {\"int8\", \"uint8\", \"int16\", \"uint16\", \"int32\", \"uint32\", \"int64\", \"uint64\"}\n%!   clsmax = intmax (cls{1});\n%!   xplus = clsmax + 1;\n%!   assert (xplus, clsmax);\n%!   xminus = clsmax - (-1);\n%!   assert (xminus, clsmax);\n%!   xmult = clsmax * 2;\n%!   assert (xmult, clsmax);\n%!   xdiv = clsmax / 0.5;\n%!   assert (xdiv, clsmax);\n%! endfor\n\n## Tests for binary constants\n%!assert (0b1, uint8 (2^0))\n%!assert (0b10000000, uint8 (2^7))\n%!assert (0b11111111, intmax (\"uint8\"))\n%!assert (0b100000000, uint16 (2^8))\n%!assert (0b1000000000000000, uint16 (2^15))\n%!assert (0b1111111111111111, intmax (\"uint16\"))\n%!assert (0b10000000000000000, uint32 (2^16))\n%!assert (0b10000000000000000000000000000000, uint32 (2^31))\n%!assert (0b11111111111111111111111111111111, intmax (\"uint32\"))\n%!assert (0b100000000000000000000000000000000, uint64 (2^32))\n%!assert (0b1000000000000000000000000000000000000000000000000000000000000000, uint64 (2^63))\n%!assert (0b1111111111111111111111111111111111111111111111111111111111111111, intmax (\"uint64\"))\n%!error <too many digits for binary constant> eval (\"0b11111111111111111111111111111111111111111111111111111111111111111\")\n\n%!assert (0b1u16, uint16 (2^0))\n%!assert (0b10000000u16, uint16 (2^7))\n\n%!assert (0b1u32, uint32 (2^0))\n%!assert (0b10000000u32, uint32 (2^7))\n%!assert (0b1000000000000000u32, uint32 (2^15))\n\n%!assert (0b1u64, uint64 (2^0))\n%!assert (0b10000000u64, uint64 (2^7))\n%!assert (0b1000000000000000u64, uint64 (2^15))\n%!assert (0b10000000000000000000000000000000u64, uint64 (2^31))\n\n%!assert (0b1s16, int16 (2^0))\n%!assert (0b10000000s16, int16 (2^7))\n\n%!assert (0b1s32, int32 (2^0))\n%!assert (0b10000000s32, int32 (2^7))\n%!assert (0b1000000000000000s32, int32 (2^15))\n\n%!assert (0b1s64, int64 (2^0))\n%!assert (0b10000000s64, int64 (2^7))\n%!assert (0b1000000000000000s64, int64 (2^15))\n%!assert (0b10000000000000000000000000000000s64, int64 (2^31))\n\n## Tests for hexadecimal constants\n%!assert (0x1, uint8 (2^0))\n%!assert (0x80, uint8 (2^7))\n%!assert (0xff, intmax (\"uint8\"))\n%!assert (0x100, uint16 (2^8))\n%!assert (0x8000, uint16 (2^15))\n%!assert (0xffff, intmax (\"uint16\"))\n%!assert (0x10000, uint32 (2^16))\n%!assert (0x80000000, uint32 (2^31))\n%!assert (0xffffffff, intmax (\"uint32\"))\n%!assert (0x100000000, uint64 (2^32))\n%!assert (0x8000000000000000, uint64 (2^63))\n%!assert (0xffffffffffffffff, intmax (\"uint64\"))\n%!error <too many digits for hexadecimal constant> eval (\"0xfffffffffffffffff\")\n\n%!assert (0x1u16, uint16 (2^0))\n%!assert (0x80u16, uint16 (2^7))\n\n%!assert (0x1u32, uint32 (2^0))\n%!assert (0x80u32, uint32 (2^7))\n%!assert (0x8000u32, uint32 (2^15))\n\n%!assert (0x1u64, uint64 (2^0))\n%!assert (0x80u64, uint64 (2^7))\n%!assert (0x8000u64, uint64 (2^15))\n%!assert (0x80000000u64, uint64 (2^31))\n\n%!assert (0x1s16, int16 (2^0))\n%!assert (0x80s16, int16 (2^7))\n\n%!assert (0x1s32, int32 (2^0))\n%!assert (0x80s32, int32 (2^7))\n%!assert (0x8000s32, int32 (2^15))\n\n%!assert (0x1s64, int64 (2^0))\n%!assert (0x80s64, int64 (2^7))\n%!assert (0x8000s64, int64 (2^15))\n%!assert (0x80000000s64, int64 (2^31))\n\n## Tests for decimal constants with extreme values\n\n%!assert (uint64 (9007199254740992), uint64 (flintmax ()))\n%!assert (int64 (9007199254740992), int64 (flintmax ()))\n%!assert (uint64 (-9007199254740992), uint64 (-flintmax ()))\n%!assert (int64 (-9007199254740992), int64 (-flintmax ()))\n\n%!assert (uint64 (9007199254740993), uint64 (flintmax ())+1)\n%!assert (int64 (9007199254740993), int64 (flintmax ())+1)\n%!assert (uint64 (-9007199254740993), uint64 (-flintmax ())-1)\n%!assert (int64 (-9007199254740993), int64 (-flintmax ())-1)\n\n%!assert (uint64 (18446744073709551615), intmax (\"uint64\"))\n\n%!assert (int64 (9223372036854775807), intmax (\"int64\"))\n%!assert (int64 (-9223372036854775808), intmin (\"int64\"))\n\n%!test\n%! a = int64 ([9223372036854775803; 9223372036854775804; 9223372036854775805; 9223372036854775806; 9223372036854775807]);\n%! bval = int64 (9223372036854775807);\n%! b = [bval; bval; bval; bval; bval];\n%! assert (a, b);\n\n%!test\n%! a = int64 ([int64(9223372036854775803); 9223372036854775804; 9223372036854775805; 9223372036854775806; 9223372036854775807]);\n%! b0val = int64 (9223372036854775803);\n%! bval = int64 (9223372036854775807);\n%! b = [b0val; bval; bval; bval; bval];\n%! assert (a, b);\n"
  },
  {
    "path": "test/io.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## FIXME: we should skip (or mark as a known bug) the test for\n## saving sparse matrices to MAT files when using 64-bit indexing since\n## that is not implemented yet.\n\n%!function [ret, files] = testls (input, t_pfix)\n%!  ## flag a1 global so as to test the storage of global flags\n%!  global a1;\n%!\n%!  ## Input or output, so as to be able to exchange between versions\n%!  if (nargin < 1)\n%!    input = 0;\n%!  endif\n%!\n%!  ## Setup some variable to be saved or compared to loaded variables\n%!\n%!  ## scalar\n%!  a1 = 1;\n%!  ## matrix\n%!  persistent a2 = hilb (3);\n%!  ## complex scalar\n%!  persistent a3 = 1 + 1i;\n%!  ## complex matrix\n%!  persistent a4 = hilb (3) + 1i*hilb (3);\n%!  ## bool\n%!  persistent a5 = (1 == 1);\n%!  ## bool matrix\n%!  persistent a6 = ([ones(1,5), zeros(1,5)] == ones (1,10));\n%!  ## range\n%!  persistent a7 = 1:10;\n%!  ## structure\n%!  persistent a8 = struct (\"a\", a1, \"b\", a3);\n%!  ## cell array\n%!  persistent a9 = {a1, a3};\n%!  ## string\n%!  persistent a10 = [\"test\"; \"strings\"];\n%!  ## int8 array\n%!  persistent a11 = int8 (floor (256*rand (2,2)));\n%!  ## int16 array\n%!  persistent a12 = int16 (floor (65536*rand (2,2)));\n%!  ## int32 array\n%!  persistent a13 = int32 (floor (1e6*rand (2,2)));\n%!  ## int64 array\n%!  persistent a14 = int64 (floor (10*rand (2,2)));\n%!  ## uint8 array\n%!  persistent a15 = uint8 (floor (256*rand (2,2)));\n%!  ## uint16 array\n%!  persistent a16 = uint16 (floor (65536*rand (2,2)));\n%!  ## int32 array\n%!  persistent a17 = uint32 (floor (1e6*rand (2,2)));\n%!  ## uint64 array\n%!  persistent a18 = uint64 (floor (10*rand (2,2)));\n%!  ## sparse\n%!  persistent a19 = sprandn (100,100,0.01);\n%!  ## complex sparse\n%!  persistent a20 = sprandn (100,100,0.01) + 1i * sprandn (100,100,0.01);\n%!\n%!  ret = 0;\n%!\n%!  files = fullfile (t_pfix, {\"text.mat\", \"binary.mat\", \"mat5.mat\", \"mat7.mat\"});\n%!  opts = {\"-z -text\", \"-z -binary\", \"-z -mat\", \"-v7\"};\n%!  tols = {2*eps, 0, 0, 0};\n%!\n%!  vars = \"a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20\";\n%!  if (! input)\n%!    for i = 1:length (files)\n%!      eval (sprintf (\"save %s %s %s\", opts{i}, files{i}, vars));\n%!    endfor\n%!  else\n%!    b1 = a1; b2 = a2; b3 = a3; b4 = a4; b5 = a5;\n%!    b6 = a6; b7 = a7; b8 = a8; b9 = a9;\n%!    b10 = a10; b11 = a11; b12 = a12; b13 = a13; b14 = a14; b15 = a15;\n%!    b16 = a16; b17 = a17; b18 = a18; b19 = a19; b20 = a20;\n%!\n%!    for i = length (files)\n%!\n%!      clear a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a19 a20;\n%!\n%!      file = files{i};\n%!      tol = tols{i};\n%!\n%!      load (file);\n%!\n%!      assert (a1, b1, tol);\n%!      assert (a2, b2, tol);\n%!      assert (a3, b3, tol);\n%!      assert (a4, b4, tol);\n%!\n%!      if (! isequal (a5, b5))\n%!        error (\"failed: %s boolean\", file);\n%!      endif\n%!\n%!      if (! strcmp (file, \"mat5\") && ! strcmp (file, \"mat7\"))\n%!        if (! isequal (a6, b6))\n%!          error (\"failed: %s boolean matrix\", file);\n%!        endif\n%!      endif\n%!\n%!      assert ([a7], [b7], tol);\n%!\n%!      if (! isequal (a8, b8))\n%!        error (\"failed: %s struct\", file);\n%!      endif\n%!\n%!      if (! isequal (a9, b9))\n%!        error (\"failed: %s cell\", file);\n%!      endif\n%!\n%!      if (! isequal (a10, b10))\n%!        error (\"failed: %s string\", file);\n%!      endif\n%!\n%!      if (! isequal (a11, b11))\n%!        error (\"failed: %s int8\", file);\n%!      endif\n%!\n%!      if (! isequal (a12, b12))\n%!        error (\"failed: %s int16\", file);\n%!      endif\n%!\n%!      if (! isequal (a13, b13))\n%!        error (\"failed: %s int32\", file);\n%!      endif\n%!\n%!      if (! isequal (a14, b14))\n%!        error (\"failed: %s int64\", file);\n%!      endif\n%!\n%!      if (! isequal (a15, b15))\n%!        error (\"failed: %s uint8\", file);\n%!      endif\n%!\n%!      if (! isequal (a16, b16))\n%!        error (\"failed: %s uint16\", file);\n%!      endif\n%!\n%!      if (! isequal (a17, b17))\n%!        error (\"failed: %s uint32\", file);\n%!      endif\n%!\n%!      if (! isequal (a18, b18))\n%!        error (\"failed: %s uint64\", file);\n%!      endif\n%!\n%!      assert (a19, b19, tol);\n%!      assert (a20, b20, tol);\n%!\n%!      ## Test for global flags\n%!      if (! isglobal (\"a1\") || isglobal (\"a2\") || isglobal (\"a3\")\n%!          || isglobal (\"a4\") || isglobal (\"a5\") || isglobal (\"a6\")\n%!          || isglobal (\"a7\") || isglobal (\"a8\") || isglobal (\"a9\")\n%!          || isglobal (\"a10\") || isglobal (\"a11\") || isglobal (\"a12\")\n%!          || isglobal (\"a13\") || isglobal (\"a14\") || isglobal (\"a15\")\n%!          || isglobal (\"a16\") || isglobal (\"a17\") || isglobal (\"a18\")\n%!          || isglobal (\"a19\") || isglobal (\"a20\"))\n%!        error (\"failed: %s global test\", file);\n%!      endif\n%!    endfor\n%!  endif\n%!\n%!  ## Cleanup after test\n%!  clear -global a1;\n%!\n%!  ret = 1;\n%!endfunction\n\n%!testif HAVE_ZLIB\n%!\n%! ## Random prefix for files\n%! t_pfix = tempname ();\n%! mkdir (t_pfix);\n%!\n%! unwind_protect\n%!   [save_status, save_files] = testls (0, t_pfix);\n%!   [load_status, load_files] = testls (1, t_pfix);\n%! unwind_protect_cleanup\n%!   ## cleanup after test\n%!   confirm_recursive_rmdir (false, \"local\");\n%!   rmdir (t_pfix, \"s\");\n%!   clear -global a1;\n%! end_unwind_protect\n%!\n%! assert (save_status && load_status);\n\n%!testif HAVE_HDF5\n%!\n%! s8  =   int8 (fix ((2^8  - 1) * (rand (2, 2) - 0.5)));\n%! u8  =  uint8 (fix ((2^8  - 1) * (rand (2, 2) - 0.5)));\n%! s16 =  int16 (fix ((2^16 - 1) * (rand (2, 2) - 0.5)));\n%! u16 = uint16 (fix ((2^16 - 1) * (rand (2, 2) - 0.5)));\n%! s32 =  int32 (fix ((2^32 - 1) * (rand (2, 2) - 0.5)));\n%! u32 = uint32 (fix ((2^32 - 1) * (rand (2, 2) - 0.5)));\n%! s64 =  int64 (fix ((2^64 - 1) * (rand (2, 2) - 0.5)));\n%! u64 = uint64 (fix ((2^64 - 1) * (rand (2, 2) - 0.5)));\n%! s8t = s8; u8t = u8; s16t = s16; u16t = u16; s32t = s32; u32t = u32;\n%! s64t = s64; u64t = u64;\n%! h5file = tempname ();\n%! unwind_protect\n%!   eval (sprintf (\"save -hdf5 %s %s\", h5file, \"s8 u8 s16 u16 s32 u32 s64 u64\"));\n%!   clear s8 u8 s16 u16 s32 u32 s64 u64;\n%!   load (h5file);\n%!   assert (s8, s8t);\n%!   assert (u8, u8t);\n%!   assert (s16, s16t);\n%!   assert (u16, u16t);\n%!   assert (s32, s32t);\n%!   assert (u32, u32t);\n%!   assert (s64, s64t);\n%!   assert (u64, u64t);\n%! unwind_protect_cleanup\n%!   sts = unlink (h5file);\n%! end_unwind_protect\n\n%!test\n%!\n%! STR.scalar_fld = 1;\n%! STR.matrix_fld = [1.1,2;3,4];\n%! STR.string_fld = \"Octave\";\n%! STR.struct_fld.x = 0;\n%! STR.struct_fld.y = 1;\n%!\n%! struct_dat = fullfile (P_tmpdir, \"struct.dat\");\n%! save_default_options (\"-text\", \"local\");\n%! save_precision (17, \"local\");\n%! save (struct_dat, \"-struct\", \"STR\");\n%! STR = load (struct_dat);\n%!\n%! assert (STR.scalar_fld == 1 && ...\n%!         STR.matrix_fld == [1.1,2;3,4] && ...\n%!         STR.string_fld == \"Octave\" && ...\n%!         STR.struct_fld.x == 0 && ...\n%!         STR.struct_fld.y == 1 );\n%!\n%!\n%! save (\"-binary\", struct_dat,\n%!       \"-struct\", \"STR\", \"matrix_fld\", \"str*_fld\");\n%! STR = load (struct_dat);\n%!\n%! assert (! isfield (STR,\"scalar_fld\") && ...\n%!         STR.matrix_fld == [1.1,2;3,4] && ...\n%!         STR.string_fld == \"Octave\" && ...\n%!         STR.struct_fld.x == 0 && ...\n%!         STR.struct_fld.y == 1);\n%!\n%! delete (struct_dat);\n\n## Test for handling filenames with Unicode characters outside the BMP.\n%!test\n%! olddir = pwd ();\n%! for opt = {'-binary', '-float-binary', '-text', '-v6'}\n%!   ## NOTE: opt = '-ascii' causes problems with loading \"unknown format\".\n%!   ##       opt = '-v7.3' cannot save (not implemented yet).\n%!   ##       opt = '-v4' cannot save structs, including 'opt' itself.\n%!   ## The other opts listed above *should* work properly.\n%!\n%!   tmpdir = tempname ();\n%!   mkdir (tmpdir);\n%!   cd (tmpdir);\n%!   protect_tmpdir = onCleanup (@() rmdir (tmpdir));\n%!   filename = sprintf (\"𝕋𝘌𝙎𝐓_%s.𝑚𝖆𝚝\", char (opt)(2:end));\n%!\n%!   foo = 123;\n%!   foostr = \"123\";\n%!   foostruct.a = 1;\n%!   foostruct.b = \"23\";\n%!   foocell = {\"12\", 3};\n%!   ## TODO In future, add variables for classdef and other kinds.\n%!\n%!   unwind_protect\n%!     save (char (opt), filename, \"foo*\");\n%!     clear foo foostr foostruct foocell;\n%!\n%!     newfile = ls (tmpdir);  # get filename recorded by file system\n%!     assert (rows (newfile), 1);  # ensure only one file was created\n%!     assert (newfile, filename);  # check file name (trap encoding errors)\n%!\n%!     load (filename);\n%!     assert (foo, 123);\n%!     assert (foostr, \"123\");\n%!     assert (foostruct.a, 1);\n%!     assert (foostruct.b, \"23\");\n%!     assert (foocell, {\"12\", 3});\n%!   unwind_protect_cleanup\n%!     if isfile (filename)\n%!       unlink (filename);\n%!     endif\n%!     cd (olddir);\n%!   end_unwind_protect\n%! endfor\n\n%!testif HAVE_HDF5\n%! olddir = pwd ();\n%! for opt = {'-hdf5', '-float-hdf5'}\n%!   tmpdir = tempname ();\n%!   mkdir (tmpdir);\n%!   cd (tmpdir);\n%!   protect_tmpdir = onCleanup (@() rmdir (tmpdir));\n%!   filename = sprintf (\"𝕋𝘌𝙎𝐓_%s.𝑚𝖆𝚝\", char (opt)(2:end));\n%!\n%!   foo = 123;\n%!   foostr = \"123\";\n%!   foostruct.a = 1;\n%!   foostruct.b = \"23\";\n%!   foocell = {\"12\", 3};\n%!   ## TODO In future, add variables for classdef and other kinds.\n%!\n%!   unwind_protect\n%!     save (char (opt), filename, \"foo*\");\n%!     clear foo foostr foostruct foocell;\n%!\n%!     newfile = ls (tmpdir);  # get filename recorded by file system\n%!     assert (rows (newfile), 1);  # ensure only one file was created\n%!     assert (newfile, filename);  # check file name (trap encoding errors)\n%!\n%!     load (filename);\n%!     assert (foo, 123);\n%!     assert (foostr, \"123\");\n%!     assert (foostruct.a, 1);\n%!     assert (foostruct.b, \"23\");\n%!     assert (foocell, {\"12\", 3});\n%!   unwind_protect_cleanup\n%!     unlink (filename);\n%!     cd (olddir);\n%!   end_unwind_protect\n%! endfor\n\n%!testif HAVE_ZLIB ; ! ispc () || __have_feature__ (\"WINDOWS_UTF8_LOCALE\")\n%! olddir = pwd ();\n%! for opt = {'-binary', '-float-binary', '-text', '-v7'}\n%!   tmpdir = tempname ();\n%!   mkdir (tmpdir);\n%!   cd (tmpdir);\n%!   protect_tmpdir = onCleanup (@() rmdir (tmpdir));\n%!   filename = sprintf (\"𝕋𝘌𝙎𝐓_%s.𝑚𝖆𝚝\", char (opt)(2:end));\n%!\n%!   foo = 123;\n%!   foostr = \"123\";\n%!   foostruct.a = 1;\n%!   foostruct.b = \"23\";\n%!   foocell = {\"12\", 3};\n%!   ## TODO In future, add variables for classdef and other kinds.\n%!\n%!   unwind_protect\n%!     save (char (opt), \"-zip\", filename, \"foo*\");\n%!     clear foo foostr foostruct foocell;\n%!\n%!     newfile = ls (tmpdir);  # get filename recorded by file system\n%!     assert (rows (newfile), 1);  # ensure only one file was created\n%!     assert (newfile, filename);  # check file name (trap encoding errors)\n%!\n%!     load (filename);\n%!     assert (foo, 123);\n%!     assert (foostr, \"123\");\n%!     assert (foostruct.a, 1);\n%!     assert (foostruct.b, \"23\");\n%!     assert (foocell, {\"12\", 3});\n%!   unwind_protect_cleanup\n%!     if isfile (filename)\n%!       unlink (filename);\n%!     endif\n%!     cd (olddir);\n%!   end_unwind_protect\n%! endfor\n\n%!testif HAVE_ZLIB, HAVE_HDF5\n%! for opt = {'-hdf5', '-float-hdf5'}\n%!   olddir = pwd ();\n%!   tmpdir = tempname ();\n%!   mkdir (tmpdir);\n%!   cd (tmpdir);\n%!   protect_tmpdir = onCleanup (@() rmdir (tmpdir));\n%!   filename = sprintf (\"𝕋𝘌𝙎𝐓_%s.𝑚𝖆𝚝\", char (opt)(2:end));\n%!\n%!   foo = 123;\n%!   foostr = \"123\";\n%!   foostruct.a = 1;\n%!   foostruct.b = \"23\";\n%!   foocell = {\"12\", 3};\n%!   ## TODO In future, add variables for classdef and other kinds.\n%!\n%!   unwind_protect\n%!     save (char (opt), \"-zip\", filename, \"foo*\");\n%!     clear foo foostr foostruct foocell;\n%!\n%!     newfile = ls (tmpdir);  # get filename recorded by file system\n%!     assert (rows (newfile), 1);  # ensure only one file was created\n%!     assert (newfile, filename);  # check file name (trap encoding errors)\n%!\n%!     load (filename);\n%!     assert (foo, 123);\n%!     assert (foostr, \"123\");\n%!     assert (foostruct.a, 1);\n%!     assert (foostruct.b, \"23\");\n%!     assert (foocell, {\"12\", 3});\n%!   unwind_protect_cleanup\n%!     if isfile (filename)\n%!       unlink (filename);\n%!     endif\n%!     cd (olddir);\n%!   end_unwind_protect\n%! endfor\n\n%!test\n%! matrix1 = rand (100, 2);\n%! matrix_ascii = fullfile (P_tmpdir, \"matrix.ascii\");\n%! save (\"-ascii\", matrix_ascii, \"matrix1\");\n%! matrix2 = load (matrix_ascii);\n%! assert (matrix1, matrix2, 1e-9);\n%!\n%! delete (matrix_ascii);\n\n%!error <unable to find file> load (\"\")\n\n%% FIXME: This test is disabled as it writes to stdout and there is no easy\n%% way to recover output.  Need to spawn new octave process and pipe stdout\n%% somewhere to treat this case.\n%!#test\n%! puts (\"foo\\n\");\n\n%!assert (puts (1),-1)\n\n%!error <Invalid call to puts> puts ()\n%!error <Invalid call to puts> puts (1, 2)\n\n%!assert (sscanf ('123456', '%10c'), '123456')\n%!assert (sscanf ('123456', '%10s'), '123456')\n\n%!assert (sscanf (['ab'; 'cd'], '%s'), 'acbd')\n\n%!assert (sscanf ('02:08:30', '%i:%i:%i'), [2; 0])\n%!assert (sscanf ('02:08:30', '%d:%d:%d'), [2; 8; 30])\n\n%!assert (sscanf ('0177 08', '%i'), [127; 0; 8])\n%!assert (sscanf ('0177 08', '%d'), [177; 8])\n\n## Extensive testing of '%c'\n%!test\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%c');\n%! assert (val, 'abcde');\n%! assert (cnt, 5);\n%! assert (msg, '');\n%! assert (pos, 6);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%10c');\n%! assert (val, 'abcde');\n%! assert (cnt, 1);\n%! assert (msg, '');\n%! assert (pos, 6);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%3c');\n%! assert (val, 'abcde');\n%! assert (cnt, 2);\n%! assert (msg, '');\n%! assert (pos, 6);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%3c', 1);\n%! assert (val, 'abc');\n%! assert (cnt, 1);\n%! assert (msg, '');\n%! assert (pos, 4);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%c', 5);\n%! assert (val, 'abcde');\n%! assert (cnt, 5);\n%! assert (msg, '');\n%! assert (pos, 6);\n\n## Extensive testing of '%s'\n%!test\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%s');\n%! assert (val, 'abcde');\n%! assert (cnt, 1);\n%! assert (msg, '');\n%! assert (pos, 6);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%10s');\n%! assert (val, 'abcde');\n%! assert (cnt, 1);\n%! assert (msg, '');\n%! assert (pos, 6);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%3s');\n%! assert (val, 'abcde');\n%! assert (cnt, 2);\n%! assert (msg, '');\n%! assert (pos, 6);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%3s', 1);\n%! assert (val, 'abc');\n%! assert (cnt, 1);\n%! assert (msg, '');\n%! assert (pos, 4);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%1s', 5);\n%! assert (val, 'abcde');\n%! assert (cnt, 5);\n%! assert (msg, '');\n%! assert (pos, 6);\n\n## Extensive testing of '%[]'\n%!test\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%[a-c]');\n%! assert (val, 'abc');\n%! assert (cnt, 1);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 4);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%10[a-c]');\n%! assert (val, 'abc');\n%! assert (cnt, 1);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 4);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[a-c]');\n%! assert (val, 'abc');\n%! assert (cnt, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 4);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[a-c]', 1);\n%! assert (val, 'ab');\n%! assert (cnt, 1);\n%! assert (msg, '');\n%! assert (pos, 3);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%[a-c]', 1);\n%! assert (val, 'abc');\n%! assert (cnt, 1);\n%! assert (msg, '');\n%! assert (pos, 4);\n\n## Extensive testing of '%[^]'\n%!test\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%[^de]');\n%! assert (val, 'abc');\n%! assert (cnt, 1);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 4);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%10[^de]');\n%! assert (val, 'abc');\n%! assert (cnt, 1);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 4);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[^de]');\n%! assert (val, 'abc');\n%! assert (cnt, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 4);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[^de]', 1);\n%! assert (val, 'ab');\n%! assert (cnt, 1);\n%! assert (msg, '');\n%! assert (pos, 3);\n%! [val, cnt, msg, pos] = sscanf ('abcde', '%[^de]', 1);\n%! assert (val, 'abc');\n%! assert (cnt, 1);\n%! assert (msg, '');\n%! assert (pos, 4);\n\n## bug #47741\n%!assert (sscanf ('2147483647', '%d'), 2147483647)\n%!assert (sscanf ('2147483647', '%i'), 2147483647)\n%!assert (sscanf ('4294967295', '%u'), 4294967295)\n%!assert (sscanf ('37777777777', '%o'), 4294967295)\n%!assert (sscanf ('ffffffff', '%x'), 4294967295)\n## FIXME: scanf should return int64/uint64 if all conversions are %l[dioux].\n## Until then only test values that are within precision range of a double.\n%!assert (sscanf ('281474976710655', '%ld'), 281474976710655)\n%!assert (sscanf ('281474976710655', '%li'), 281474976710655)\n%!assert (sscanf ('281474976710655', '%lu'), 281474976710655)\n%!assert (sscanf ('7777777777777777', '%lo'), 281474976710655)\n%!assert (sscanf ('ffffffffffff', '%lx'), 281474976710655)\n\n## bug #47759\n%!assert (sscanf ('999999999999999', '%d'), double (intmax (\"int32\")))\n%!assert (sscanf ('999999999999999', '%i'), double (intmax (\"int32\")))\n%!assert (sscanf ('999999999999999', '%u'), double (intmax (\"uint32\")))\n%!assert (sscanf ('777777777777777', '%o'), double (intmax (\"uint32\")))\n%!assert (sscanf ('fffffffffffffff', '%x'), double (intmax (\"uint32\")))\n## FIXME: scanf should return int64/uint64 if all conversions are %l[dioux].\n## Until then cast to a double (and lose precision) for comparison.\n%!assert (sscanf ('9999999999999999999999', '%ld'), double (intmax (\"int64\")))\n%!assert (sscanf ('9999999999999999999999', '%li'), double (intmax (\"int64\")))\n%!assert (sscanf ('9999999999999999999999', '%lu'), double (intmax (\"uint64\")))\n%!assert (sscanf ('7777777777777777777777', '%lo'), double (intmax (\"uint64\")))\n%!assert (sscanf ('ffffffffffffffffffffff', '%lx'), double (intmax (\"uint64\")))\n\n## bug 51794\n%!assert (sscanf ('2147483647', '%d', 'C'), 2147483647)\n%!assert (sscanf ('2147483647', '%i', 'C'), 2147483647)\n%!assert (sscanf ('4294967295', '%u', 'C'), 4294967295)\n%!assert (sscanf ('37777777777', '%o', 'C'), 4294967295)\n%!assert (sscanf ('ffffffff', '%x', 'C'), 4294967295)\n## FIXME: scanf should return int64/uint64 if all conversions are %l[dioux].\n## Until then only test values that are within precision range of a double.\n%!assert (sscanf ('281474976710655', '%ld', 'C'), 281474976710655)\n%!assert (sscanf ('281474976710655', '%li', 'C'), 281474976710655)\n%!assert (sscanf ('281474976710655', '%lu', 'C'), 281474976710655)\n%!assert (sscanf ('7777777777777777', '%lo', 'C'), 281474976710655)\n%!assert (sscanf ('ffffffffffff', '%lx', 'C'), 281474976710655)\n\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! [val, count, msg, pos] = sscanf (\"3I2\", \"%f\");\n%! assert (val, 3);\n%! assert (count, 1);\n%! assert (msg, \"sscanf: format failed to match\");\n%! assert (pos, 2);\n\n%!testif HAVE_LLVM_LIBCXX  <47413>\n%! ## Same test code as above, intended only for test statistics with libc++.\n%! [val, count, msg, pos] = sscanf (\"3I2\", \"%f\");\n%! assert (val, 3);\n%! assert (count, 1);\n%! assert (msg, \"sscanf: format failed to match\");\n%! assert (pos, 2);\n\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! [val, count, msg, pos] = sscanf (\"3In2\", \"%f\");\n%! assert (val, 3);\n%! assert (count, 1);\n%! assert (msg, \"sscanf: format failed to match\");\n%! assert (pos, 2);\n\n%!testif HAVE_LLVM_LIBCXX  <47413>\n%! ## Same test code as above, intended only for test statistics with libc++.\n%! [val, count, msg, pos] = sscanf (\"3In2\", \"%f\");\n%! assert (val, 3);\n%! assert (count, 1);\n%! assert (msg, \"\");\n%! assert (pos, 2);\n\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! [val, count, msg, pos] = sscanf (\"3Inf2\", \"%f\");\n%! assert (val, [3; Inf; 2]);\n%! assert (count, 3);\n%! assert (msg, \"\");\n%! assert (pos, 6);\n\n%!testif HAVE_LLVM_LIBCXX  <47413>\n%! ## Same test code as above, intended only for test statistics with libc++.\n%! [val, count, msg, pos] = sscanf (\"3Inf2\", \"%f\");\n%! assert (val, [3; Inf; 2]);\n%! assert (count, 3);\n%! assert (msg, \"\");\n%! assert (pos, 6);\n\n%!test <*62723>\n%! [val, count, msg, pos] = sscanf (\"p\", \"%c\");\n%! assert (val, 'p');\n%! assert (count, 1);\n%! assert (msg, '');\n%! assert (pos, 2);\n\n%!test <*62723>\n%! [val, count, msg, pos] = sscanf (' ,1 ', ' %s ', 1);\n%! assert (val, ',1');\n%! assert (count, 1);\n%! assert (msg, '');\n%! assert (pos, 5);\n\n## Test NaN at EOF\n%!test <*63383>\n%! [val, count, msg, pos] = sscanf ('2 3 n', '%f');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('2 3 na', '%f');\n%! assert (val, [2; 3; NA]);\n%! assert (count, 3);\n%! assert (msg, '');\n%! assert (pos, 7);\n%! [val, count, msg, pos] = sscanf ('2 3 nan', '%f');\n%! assert (val, [2; 3; NaN]);\n%! assert (count, 3);\n%! assert (msg, '');\n%! assert (pos, 8);\n\n## Test NaN within string\n%!test <*63383>\n%! [val, count, msg, pos] = sscanf ('2 3 n 4', '%f');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('2 3 na 4', '%f');\n%! assert (val, [2; 3; NA; 4]);\n%! assert (count, 4);\n%! assert (msg, '');\n%! assert (pos, 9);\n%! [val, count, msg, pos] = sscanf ('2 3 nan 4', '%f');\n%! assert (val, [2; 3; NaN; 4]);\n%! assert (count, 4);\n%! assert (msg, '');\n%! assert (pos, 10);\n\n## Test Inf at EOF\n%!test <*63383>\n%! [val, count, msg, pos] = sscanf ('2 3 i', '%f');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('2 3 in', '%f');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('2 3 inf', '%f');\n%! assert (val, [2; 3; Inf]);\n%! assert (count, 3);\n%! assert (msg, '');\n%! assert (pos, 8);\n\n## Test Inf within string\n%!test <*63383>\n%! [val, count, msg, pos] = sscanf ('2 3 i 4', '%f');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('2 3 in 4', '%f');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('2 3 inf 4', '%f');\n%! assert (val, [2; 3; Inf; 4]);\n%! assert (count, 4);\n%! assert (msg, '');\n%! assert (pos, 10);\n\n## Test '-' at EOF\n%!test <*63383>\n%! [val, count, msg, pos] = sscanf ('2 3 -', '%d');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('2 3 -', '%f');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n\n## Test '-' within string\n%!test <*63383>\n%! [val, count, msg, pos] = sscanf ('1 2 - 3', '%d');\n%! assert (val, [1; 2]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('1 2 - 3', '%f');\n%! assert (val, [1; 2]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n\n## Test '+' at EOF\n%!test <*63383>\n%! [val, count, msg, pos] = sscanf ('2 3 +', '%d');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('2 3 +', '%f');\n%! assert (val, [2; 3]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n\n## Test '+' within string\n%!test <*63383>\n%! [val, count, msg, pos] = sscanf ('1 2 + 3', '%d');\n%! assert (val, [1; 2]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('1 2 + 3', '%f');\n%! assert (val, [1; 2]);\n%! assert (count, 2);\n%! assert (msg, 'sscanf: format failed to match');\n%! assert (pos, 5);\n\n## Test +NA, -NA, +NAN, -NAN\n%!test <*63383>\n%! [val, count, msg, pos] = sscanf ('+NA -NA 1 +NAN -NAN', '%f');\n%! assert (val, [NA; NA; 1; NaN; NaN]);\n%! assert (count, 5);\n%! assert (msg, '');\n%! assert (pos, 20);\n%! [val, count, msg, pos] = sscanf ('-NA', '%f');\n%! assert (val, NA);\n%! assert (count, 1);\n%! assert (msg, '');\n%! assert (pos, 4);\n%! [val, count, msg, pos] = sscanf ('+NA', '%f');\n%! assert (val, NA);\n%! assert (count, 1);\n%! assert (msg, '');\n%! assert (pos, 4);\n%! [val, count, msg, pos] = sscanf ('-NaN', '%f');\n%! assert (val, NaN);\n%! assert (count, 1);\n%! assert (msg, '');\n%! assert (pos, 5);\n%! [val, count, msg, pos] = sscanf ('+NaN', '%f');\n%! assert (val, NaN);\n%! assert (count, 1);\n%! assert (msg, '');\n%! assert (pos, 5);\n\n## Test space at end of input string\n%!test <63467>\n%! [val, count, msg, pos] = sscanf ('1 2 ', '%f');\n%! assert (val, [1; 2]);\n%! assert (count, 2);\n%! assert (msg, '');\n%! assert (pos, 5);\n\n## Test newline at end of input string\n%!test <65390>\n%! [val, count, msg, pos] = sscanf (\"1 2\\n\", '%f');\n%! assert (val, [1; 2]);\n%! assert (count, 2);\n%! assert (msg, '');\n%! assert (pos, 5);\n\n%!test\n%! [a, b, c] = sscanf (\"1.2 3 foo\", \"%f%d%s\", \"C\");\n%! [v1, c1, m1] = sscanf (\"1 2 3 4 5 6\", \"%d\");\n%! [v2, c2, m2] = sscanf (\"1 2 bar 3 4 5 6\", \"%d\");\n%!\n%! assert ((a == 1.2 && b == 3 && c == \"foo\"\n%!          && v1 == [1; 2; 3; 4; 5; 6] && c1 == 6 && ischar (m1)\n%!          && v2 == [1; 2] && c2 == 2 && ischar (m2)));\n\n%!test\n%! [x, n] = sscanf (\"   0.024000 0.200 0.200 2.000         1987           5           0  0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 2 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 4 5 1 2    2 5 5 8 2 8 12 6 15 18 28 26 47 88 118 162 192 130 88 56 27 23 14 9 6 3 4 1 0    2 3 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0   0.026000 0.250 0.250 2.100         3115           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0    0 0 0 0 1 0 1 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 1 0 1    1 1 0 1 0 1 3 2 0 5 15 25 44 66 145 179 193 172 104 57 17 11 12 2 1 0 1 1 0 1    0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.028000 0.300 0.300 2.200         4929           3           0  1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0    1 0 1 0 1 2 2 3 2 3 14 21 49 80 148 184 218 159 124 63 37 13 12 3 1 1 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0    0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.030000 0.350 0.350 2.300         7051           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0    0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1    0 0 1 0 0 0 2 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1    0 0 0 2 0 0 0 1 5 6 14 28 51 88 154 177 208 169 124 65 39 15 5 3 3 2 1 0 1 0 1   0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.032000 0.400 0.400 2.400         9113           4           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0    1 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 2 0    1 0 0 1 1 0 2 3 5 3 17 30 60 117 156 189 209 129 102 64 56 16 11 4 2 2 0 0 0 0   1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0   0.034000 0.450 0.450 2.500        11811           6           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0    0 0 2 1 0 0 1 0 5 5 15 21 57 99 149 190 195 159 130 69 41 16 10 2 5 3 0 1 0 0    0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.036000 0.500 0.500 2.600        14985           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 0 0    0 0 0 0 1 0 0 2 2 6 10 34 60 95 126 177 194 155 99 71 44 17 6 7 2 0 0 0 3 0 0    1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.038000 0.550 0.550 2.700        18391           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0    0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 2 0 0 1 1 0 1    2 1 0 0 0 1 0 1 3 6 19 27 52 95 161 154 169 134 94 64 37 19 9 6 0 2 1 0 0 0 0    1 2 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 2 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0    0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.040000 0.600 0.600 2.800        22933           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1    0 0 0 0 0 2 0 3 4 7 18 27 47 82 134 163 133 138 101 58 34 26 10 5 2 1 2 1 1 0    2 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0   0.042000 0.650 0.650 2.900        27719           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 0 0 1 1 2 8 16 37 51 87 128 153 146 123 105 62 35 24 8 3 5 0 1 2 1 0 0   0 1 1 1 0 0 0 1 0 1 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0    0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.044000 0.700 0.700 3.000        32922           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 2 0    0 0 0 0 0 0 0 2 1 0 0 0 0 1 1 1 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1    1 1 0 0 0 1 4 3 5 5 15 35 54 88 132 168 149 105 92 62 30 16 17 4 5 1 0 0 1 0 1   1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.046000 0.750 0.750 3.100        38973           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0    0 0 0 1 0 0 0 4 3 5 20 37 56 94 110 135 149 124 84 58 36 17 14 7 1 0 2 0 1 0 0   1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 0 1    1 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0    1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.048000 0.800 0.800 3.200        45376           5           0  1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0    0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 1 0 0 2 1 1 2 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0    0 0 0 1 0 0 0 0 1 3 18 34 55 82 104 135 116 99 79 60 51 29 10 4 3 1 1 1 0 0 1    0 0 0 1 0 0 3 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1    0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.050000 0.850 0.850 3.300        52060           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1    0 0 0 0 0 2 2 1 3 12 24 40 39 107 121 127 138 100 86 68 44 23 15 7 3 1 1 0 1 1   0 0 2 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 2 0 0 0 1 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.052000 0.900 0.900 3.400        59454           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 1    0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0    0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 1 0 0 2 0 2 1 0 0 0 1 0    0 1 0 0 0 0 0 3 3 6 21 32 68 90 132 111 122 107 73 57 47 24 11 7 4 2 2 1 0 0 0   0 0 0 0 0 1 0 0 1 0 0 2 0 1 1 0 0 1 0 0 0 0 0 3 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0    0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0   0.054000 0.950 0.950 3.500        67013           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 1 0 0 0 0 1 0 0 1 1 0 0 0    1 0 1 0 1 2 4 3 7 9 28 31 71 94 115 96 108 78 82 60 38 17 12 11 4 3 1 1 0 2 1    0 0 0 2 1 3 0 0 0 0 3 0 0 1 0 0 0 0 0 0 0 2 0 0 0 1 0 2 0 1 0 2 0 1 0 0 1 0 0    0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0   0.056000 1.000 1.000 3.600        75475           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 2 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 3 0 0 1    1 2 0 1 4 0 1 8 6 7 17 41 56 71 109 113 84 103 72 54 35 22 6 9 1 7 5 4 0 0 1 0   0 0 0 0 0 1 0 0 2 1 0 0 0 0 2 0 0 1 0 0 1 0 0 0 0 0 0 1 0 2 0 1 0 0 0 0 1 0 1    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 3 0 0 0 1 0 0 0 0 0 0 1 1 0 0 2 0 0 0 0    0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0   0.058000 1.050 1.050 3.700        83558           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0    0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 2 0 0    2 0 0 1 0 3 2 3 6 15 27 41 77 73 94 94 92 76 61 56 42 23 13 11 6 2 1 2 0 1 2 0   0 1 0 1 0 0 1 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 0 0 0 2 0 0 0 0 0 1 2 0    0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0   0.060000 1.100 1.100 3.800        93087           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1    0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 2 2 0 0 0 1 0 1 1 0 0 0 1 1 0 4    0 0 1 2 0 3 1 3 5 13 33 31 65 75 77 96 97 80 59 45 36 32 18 2 5 0 1 0 0 1 0 0    3 0 0 0 0 1 0 0 0 0 0 1 0 0 1 2 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 2 0 0 2 0 1 0    0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0    0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.062000 1.150 1.150 3.900       102829           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 0 0 1 1 1 0 1 0 1 1 0 1 1 0 2 0 2    1 2 0 0 2 4 3 5 11 9 23 43 53 68 65 87 83 77 59 49 34 18 15 9 4 2 3 2 0 0 0 4    0 1 1 0 0 2 0 0 1 0 0 0 0 1 1 1 0 1 0 0 0 0 2 0 0 0 0 1 0 0 1 1 1 1 0 0 0 1 0    0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0   0.064000 1.200 1.200 4.000       113442           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0    0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 1 1 0 0 0 1    2 0 0 0 2 0 4 5 11 13 29 39 61 68 61 75 76 74 73 44 37 29 19 6 3 3 2 0 1 2 1 0   0 0 0 1 1 1 0 1 1 0 0 0 1 0 1 1 0 1 2 0 2 1 1 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0    0 0 0 0 1 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0    0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0   0.066000 1.250 1.250 4.100       126668           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1    0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 1 0 0 0 1 1 2 3 0 2 1 2 0 1 0 3 0 0 0 1 0 1 1 3    0 0 1 3 0 2 4 3 12 12 30 48 56 66 77 78 71 82 52 31 32 19 20 16 8 2 1 3 0 0 2    1 0 1 0 1 0 0 0 1 3 1 0 1 0 1 1 1 0 0 0 0 0 2 0 2 0 0 0 0 0 1 0 0 0 0 1 1 0 0    0 0 0 1 0 0 0 0 0 2 0 3 1 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.068000 1.300 1.300 4.200       138042           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 2 0 0 1 0 1 0 0 0 0 0    0 0 0 1 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0    0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 3 0 0 1 0 0 1 2 0 0 0 3 0 1 0 0 3 0    1 0 1 1 3 1 4 7 11 14 27 36 44 68 72 70 71 45 44 46 29 13 16 11 5 2 0 3 0 0 0    0 1 1 2 0 0 1 1 2 1 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 2 0 0 1 1 0 1 1 1 0    0 1 0 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0    0 0 0 1 0 0 1 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.070000 1.350 1.350 4.300       152335           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0    1 0 0 0 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 1 1 1 0 1 1 0 1 1 1 1 0 2 0    0 0 0 0 2 0 1 7 14 19 34 35 54 72 68 72 68 58 48 36 37 27 25 17 1 4 1 0 0 0 1    2 2 0 0 1 1 1 2 1 0 3 1 0 1 0 2 1 0 0 0 1 1 1 2 0 0 0 0 1 1 0 1 1 0 2 1 1 1 1    0 0 0 1 1 0 0 2 0 0 1 0 0 0 1 1 0 2 1 1 0 0 0 0 2 0 0 0 0 0 0 0 1 1 0 0 0 0 1    0 0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0   0.072000 1.400 1.400 4.400       166280           4           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0    0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0    2 0 0 0 0 0 0 0 1 0 1 0 1 1 1 0 0 1 0 1 0 0 3 4 2 2 0 0 0 0 0 1 1 3 1 0 3 2 2    1 2 2 0 2 2 1 8 14 26 24 29 47 47 68 65 63 55 42 41 26 29 17 8 4 4 1 0 1 2 0 0   0 1 1 2 0 1 2 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 1 2 1 2 1 0 0 0 0 0 1 1 2 0 2 2 0    0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0    0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0   0.074000 1.450 1.450 4.500       179484           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0    1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 1 0    0 0 1 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 2 0 0 1 1 2 1 0    1 1 2 2 0 1 5 6 10 20 43 50 57 62 53 62 66 45 42 33 27 26 23 14 3 0 2 0 1 0 0    1 1 0 0 2 1 1 0 0 3 0 1 1 1 0 1 1 0 1 0 1 2 1 0 0 1 2 0 2 0 0 0 0 1 1 3 1 0 0    2 1 1 1 0 0 0 0 0 0 1 2 0 1 0 0 0 0 0 1 1 0 2 0 0 0 0 0 1 0 2 1 0 0 0 0 0 0 1    0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0   0.076000 1.500 1.500 4.600       197657           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0    0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 2 0 0 0 1 0 0 0 0    0 0 1 0 1 0 0 0 0 0 0 0 0 1 2 0 0 0 2 1 1 0 1 1 0 1 1 3 2 1 1 2 1 0 1 0 0 0 0    0 1 1 1 0 5 3 7 12 24 38 32 41 48 54 66 71 49 46 31 38 25 15 8 6 6 5 0 1 3 0 1   1 1 1 1 0 1 2 0 1 0 0 0 1 0 2 1 2 0 0 0 0 1 3 1 0 0 0 0 1 1 0 1 0 1 1 1 1 1 0    4 1 1 1 0 3 0 0 0 2 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0   0.078000 1.550 1.550 4.700       212054           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0    0 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1    0 0 2 0 0 0 1 0 0 1 0 1 1 0 1 3 1 0 0 1 2 0 0 0 1 0 0 0 0 0 2 1 2 1 1 1 0 0 1    5 1 1 2 3 5 7 9 11 22 31 37 48 50 52 54 57 37 38 38 33 24 11 19 11 3 1 2 0 3 3   2 1 0 1 3 0 1 1 1 1 1 2 0 0 0 1 1 2 0 1 1 3 0 1 1 0 0 1 0 2 0 1 0 0 1 3 0 2 0    1 0 1 2 0 1 1 1 1 1 0 3 0 1 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0    0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0   0.080000 1.600 1.600 4.800       231971           3           0  0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 1 1 0 1 0 0 0 0 1 0 1 1    0 0 0 0 2 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 2 1 0 1 1 1 0 1 0 0 1 0 1 3 0 0 0 1 0    0 0 1 1 1 0 0 4 1 1 0 2 0 1 1 1 2 0 0 0 1 0 1 2 1 2 3 2 0 1 0 4 3 1 1 1 1 3 1    0 0 0 2 1 0 2 7 17 13 29 47 58 59 52 38 51 51 38 34 35 21 14 13 4 1 0 1 1 1 0    2 2 4 1 0 1 1 4 0 0 0 2 0 2 2 2 0 0 1 3 2 1 1 2 2 2 2 1 0 3 0 2 1 2 1 2 2 0 0    1 1 0 2 0 2 2 0 1 0 2 2 3 1 2 3 1 1 0 1 0 2 0 1 2 1 2 0 2 1 0 0 3 0 0 1 1 1 1    0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0   0.082000 1.650 1.650 4.900       252503           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 0 0    0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0    0 0 0 0 2 0 0 1 0 1 2 2 2 1 0 2 0 1 0 1 1 2 2 0 3 0 0 4 1 0 0 3 0 0 1 2 0 1 1    1 3 0 1 0 2 9 11 25 27 34 53 41 49 43 47 36 31 38 22 30 22 18 9 5 9 2 2 1 2 2    3 1 4 1 1 0 0 1 2 0 2 1 0 0 1 3 2 2 1 0 0 0 1 2 1 0 0 0 2 1 1 0 2 0 0 1 0 0 2    1 3 1 1 1 0 2 1 1 0 2 1 0 1 3 0 0 0 0 2 0 0 1 0 0 0 0 0 1 2 1 1 1 0 2 1 0 0 0    2 0 1 0 0 0 0 1 0 0 0 0 1 0 0 2 0 1 0 1 0 0 0 0 0 0 0 0 0 0   0.084000 1.700 1.700 5.000       267889           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 1    0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0    0 1 0 1 1 0 3 0 1 1 1 0 1 2 1 0 2 0 2 4 0 1 0 0 0 1 1 0 1 3 2 0 2 0 4 0 0 2 0    1 4 2 4 3 3 6 10 14 28 37 54 36 40 52 40 50 46 40 32 26 29 12 18 5 2 0 2 4 1 2   1 0 2 1 2 2 1 0 1 0 2 1 2 4 1 1 5 1 0 2 0 1 2 3 2 2 1 2 1 0 2 1 2 1 1 4 1 2 1    4 0 2 2 0 0 3 1 0 2 0 0 1 1 1 0 0 2 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0   0.086000 1.750 1.750 5.100       290294           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0    0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 3 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 2    1 0 1 0 1 0 0 2 2 0 1 2 2 0 2 0 2 0 1 0 0 1 1 1 3 1 1 1 1 3 4 1 1 2 2 2 1 0 3    0 0 0 2 4 5 6 16 18 20 31 40 54 55 46 41 52 35 27 21 28 27 20 15 8 6 7 1 0 0 3   0 0 2 2 0 3 1 3 1 1 2 0 0 1 2 1 3 2 0 1 2 1 3 1 1 1 1 1 2 0 2 1 0 1 1 1 3 1 1    2 0 1 0 1 0 2 1 1 0 0 1 2 0 3 1 1 0 0 0 1 3 1 1 1 0 0 1 2 1 0 0 1 1 1 0 0 1 0    0 0 0 0 0 2 0 1 0 0 0 2 1 0 2 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0   0.088000 1.800 1.800 5.200       312476           6           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0    0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 2 0 0 0 1 0 1 0 0 0 0 0 0 2    1 0 0 1 0 0 1 1 1 1 4 2 0 1 0 0 3 0 0 0 0 0 1 1 4 0 0 0 0 1 1 2 1 0 3 0 0 2 2    4 0 3 1 6 9 10 13 21 24 32 43 33 41 43 49 50 32 26 31 27 12 16 17 3 3 3 5 0 3    0 2 1 3 3 2 1 2 3 1 2 1 1 1 2 0 1 1 0 2 0 3 0 0 2 0 0 0 0 1 0 1 1 3 3 0 1 1 1    1 1 1 2 2 2 0 3 1 0 2 2 2 0 0 0 0 3 1 2 5 1 1 2 0 0 3 3 0 2 2 0 0 0 0 1 2 0 0    1 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0   0.090000 1.850 1.850 5.300       337348           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 2 0 1 0 1 0 0 0 1 0 0 0    0 0 0 1 0 0 0 0 2 0 1 1 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0    2 0 0 0 1 3 2 0 0 2 2 3 3 2 2 2 0 0 1 1 3 1 3 0 0 0 0 0 0 1 2 1 2 1 2 2 2 0 1    1 0 4 2 2 7 6 15 22 21 39 37 50 31 51 30 33 34 34 26 21 14 13 10 9 4 3 3 4 2 2   0 1 2 3 3 0 1 3 2 5 3 2 2 4 0 2 3 0 4 2 1 2 2 2 4 2 1 3 1 3 2 1 3 1 2 4 1 1 1    1 2 4 1 3 3 3 1 0 4 1 0 1 1 1 1 2 3 0 3 0 0 4 1 1 1 0 2 2 2 1 2 2 0 1 1 0 0 0    2 0 1 0 1 0 0 1 0 0 0 1 3 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 0   0.092000 1.900 1.900 5.400       357303           3           0  0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 1 1 0 1 0 0 1 0    0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 3 1 0 1 0 0 0 0 1 0 0 1 0 0 1 1 2 2 0 0 2    2 1 1 1 1 1 1 0 1 0 0 1 1 1 3 1 1 1 1 1 0 1 4 0 1 1 1 3 0 1 1 2 2 2 0 2 3 2 2    2 2 1 2 1 3 8 22 14 32 36 46 39 42 39 29 36 38 26 24 26 18 16 19 10 9 3 6 5 0    3 2 1 1 1 2 0 2 1 1 0 1 1 3 1 0 2 4 2 2 1 4 1 2 2 1 1 0 1 2 0 2 2 2 4 2 1 1 0    2 1 3 1 2 3 4 2 3 2 3 0 1 2 1 0 0 0 4 1 1 1 2 1 3 1 0 5 1 0 0 0 0 0 0 1 0 2 0    1 2 1 0 1 0 0 0 0 0 1 1 0 1 0 1 4 0 0 0 1 0 1 0 0 0 0 0 0 0 0   0.094000 1.950 1.950 5.500       383138           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 0 1 0 0 0 0 0 1 0    0 0 1 0 0 2 1 0 1 1 1 0 0 0 0 0 0 1 1 0 1 0 0 1 1 0 1 0 0 0 0 0 0 0 2 1 1 1 1    2 1 0 2 0 1 0 3 2 1 3 0 1 3 1 1 0 5 0 1 0 1 2 0 0 1 1 2 0 0 6 1 0 3 2 2 3 4 5    0 4 2 1 5 4 11 15 22 27 28 57 38 38 40 38 39 38 27 26 30 18 14 10 10 4 4 4 3 3   2 2 2 2 1 1 1 1 2 2 3 4 1 2 3 1 2 1 2 2 2 1 3 2 1 5 0 1 1 1 3 2 2 2 1 3 1 1 0    3 2 2 0 0 2 2 2 0 0 0 2 0 1 3 1 2 3 2 1 1 0 1 1 1 0 3 2 2 1 0 0 1 3 1 1 0 1 0    0 0 0 0 1 0 0 0 0 1 0 0 3 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0   0.096000 2.000 2.000 5.600       409868           3           0  0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 2 0 0    1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 2 0 1 0 0 2 0 2 0 0 0 0 1 0 0 2 1    2 2 2 1 2 1 1 1 1 1 2 0 0 1 1 0 1 0 2 1 2 0 2 0 3 1 2 1 3 1 5 0 2 2 1 2 4 1 2    0 3 1 4 7 5 9 13 22 19 31 27 28 41 34 39 37 22 23 21 22 17 23 15 8 9 3 8 0 3 1   2 2 2 3 1 0 4 2 4 2 2 2 2 4 2 1 1 0 2 0 3 0 3 2 2 1 2 2 1 4 1 2 2 1 1 5 2 1 2    1 2 2 1 0 2 4 3 2 1 2 2 3 2 3 1 2 1 1 1 1 2 1 1 2 2 1 2 3 2 1 1 0 2 2 4 0 1 1    1 1 1 0 0 1 1 3 0 0 0 0 0 1 0 0 2 0 1 2 0 1 1 1 0 1 0 1 0 0   0.098000 2.050 2.050 5.700       439102           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 1 0 0 1 0 1 0 1 0 0 0 0 1 1 0 1 0 0 1 1 0    0 1 1 0 0 1 1 0 1 0 0 0 0 0 0 0 1 2 0 0 1 1 1 1 2 0 1 1 0 0 0 0 1 1 1 0 4 0 0    0 2 1 1 0 3 4 0 1 2 2 1 0 3 0 3 2 0 0 2 0 1 0 0 1 0 1 3 1 3 5 0 2 2 3 5 2 2 2    0 3 2 3 6 5 16 21 19 23 28 29 35 42 42 44 39 33 23 30 18 25 24 15 13 5 4 2 2 0   3 3 0 0 1 3 0 1 1 3 2 4 3 4 2 1 1 1 3 1 0 0 2 2 4 2 2 1 4 2 4 2 2 2 1 2 2 1 2    0 4 2 2 3 1 2 1 1 2 2 1 2 4 2 1 4 1 2 2 2 2 0 2 0 3 0 1 0 2 1 0 4 2 1 3 2 1 0    2 1 1 1 1 0 1 1 2 1 1 1 2 0 1 0 2 1 1 0 0 1 0 0 1 0 0 0 0 0 0   0.100000 2.100 2.100 5.800       467340           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 0 1 2 0 0 0 0 0 1 0 2 0 0 2 0 0 1 1 0 0    0 1 0 0 1 1 0 0 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 1 2 0 2    2 4 1 0 1 1 2 3 4 1 4 1 5 1 2 1 0 2 2 2 1 5 4 1 5 4 0 1 2 4 2 2 0 2 1 2 5 4 1    1 1 2 5 7 9 16 23 31 15 22 36 36 44 42 29 31 28 28 18 35 12 10 13 8 4 3 2 2 5    1 2 3 3 1 3 3 5 2 0 3 4 1 2 2 3 0 0 5 2 3 6 2 1 2 5 3 4 3 1 1 1 1 2 2 4 0 2 3    1 2 1 2 4 5 4 3 5 2 1 2 0 5 0 2 2 4 1 0 4 1 0 2 1 2 0 0 1 3 2 4 3 0 2 3 3 3 4    2 2 0 0 0 0 1 1 0 3 2 0 1 2 0 4 2 1 1 1 2 0 0 0 0 0 0 0 0 0 0   0.102000 2.150 2.150 5.900       497495           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 0 2 1 0 0 0 0 1 0 1 0 0 0 0 1 2    0 0 0 0 0 2 0 0 1 0 1 0 0 0 0 1 1 0 0 0 1 1 1 1 2 0 0 1 0 0 0 1 0 2 2 1 0 0 0    2 0 2 1 1 1 6 3 2 0 3 2 2 2 1 1 3 4 1 0 1 2 4 2 3 3 1 1 1 1 3 3 1 4 1 3 4 3 2    3 1 2 2 5 11 11 14 26 27 28 28 28 36 39 42 29 33 24 20 29 18 13 17 13 6 10 4 3   3 6 1 0 1 0 2 1 3 2 3 1 2 3 1 2 1 2 0 2 2 3 1 3 1 1 2 4 4 1 4 3 2 2 3 5 5 3 0    2 5 3 5 1 4 1 1 3 4 2 2 2 2 1 3 0 1 1 2 2 4 2 1 3 2 0 1 2 1 0 2 3 1 2 0 0 0 2    0 0 1 3 0 0 1 2 0 3 1 0 3 1 2 2 1 1 2 0 0 0 0 2 0 0 1 0 0 0 0 0   0.104000 2.200 2.200 6.000       529288           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0    0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 3 0 2 0 2 0 0    3 2 2 0 4 0 3 2 2 1 3 1 7 3 1 1 0 4 3 2 1 0 0 3 2 3 5 2 1 4 1 5 1 0 3 2 3 0 1    2 4 7 3 7 8 12 15 20 24 34 39 34 35 27 36 34 23 22 26 15 24 12 12 14 5 3 0 7 1   1 3 5 1 2 2 2 4 3 1 2 5 2 2 3 1 1 4 2 1 3 0 4 5 4 6 4 5 3 3 3 3 1 1 5 0 6 1 2    4 2 3 2 1 3 2 0 0 0 1 3 3 0 1 4 0 3 2 3 0 3 3 0 2 3 4 3 1 1 1 2 5 3 1 2 1 1 2    4 1 0 2 4 1 3 0 0 3 0 1 3 0 1 0 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0   0.106000 2.250 2.250 6.100       560628           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 0 1 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 0 1    1 0 0 1 1 1 0 1 1 0 0 0 1 1 1 1 0 0 1 1 2 0 0 0 0 2 0 3 1 1 0 0 2 2 2 0 5 2 1    1 1 1 3 1 2 3 0 1 0 0 0 0 1 0 2 2 1 2 1 0 4 3 2 1 2 1 0 4 2 2 0 2 1 1 2 3 1 2    1 2 4 4 11 12 17 19 19 29 30 24 30 35 51 32 36 34 31 19 22 17 11 19 11 7 6 6 3   4 0 3 3 2 0 2 2 2 3 1 5 3 2 3 5 1 0 2 2 5 4 2 3 2 0 1 6 1 2 2 2 2 1 1 2 2 1 4    3 2 2 1 2 5 2 0 2 0 2 5 4 5 2 1 3 6 1 3 4 4 0 0 6 0 2 6 1 2 2 2 0 1 3 1 3 4 2    1 4 2 1 2 3 3 0 3 1 0 2 0 2 1 0 2 1 2 0 0 1 1 0 2 0 0 0 0 0 0 0   0.108000 2.300 2.300 6.200       593293           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 2 0 2 2 1 0 0 2 0 1 0 1 0 0 1 2 2 1 0    0 1 0 2 0 0 0 0 0 1 1 1 1 1 0 0 1 1 0 0 1 1 1 2 2 1 0 1 1 0 1 5 0 2 4 1 0 1 4    2 1 3 2 2 3 2 3 2 0 0 3 4 3 1 3 2 2 0 3 0 2 4 0 3 2 5 1 2 1 4 6 1 2 4 0 3 6 1    7 6 4 5 4 10 16 24 22 20 40 37 44 34 29 21 28 36 36 27 23 24 14 10 4 5 2 5 3 6   2 3 3 1 4 2 1 5 1 3 5 3 2 1 2 2 6 2 3 1 1 0 5 3 3 3 4 5 2 2 3 3 5 5 1 6 2 3 2    6 0 5 2 4 3 5 1 2 2 5 1 2 3 1 2 2 2 4 2 5 5 2 2 2 5 0 1 2 5 2 3 2 3 1 1 2 4 0    2 1 4 2 1 1 1 0 1 2 0 0 1 3 1 0 2 1 1 3 3 2 0 0 0 1 2 0 0 0 0   0.110000 2.350 2.350 6.300       636559           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 1 0 0 0 1 1 2 0 0 1 0 0 0 0 0 0 0    1 2 0 0 1 1 1 0 0 0 0 1 0 1 1 0 0 1 0 0 2 0 1 0 1 0 1 0 0 1 1 3 0 1 2 2 0 2 1    1 1 1 0 1 0 1 3 0 3 2 3 4 3 3 4 3 3 2 6 3 1 1 1 2 4 2 3 1 5 1 3 1 4 5 3 3 2 1    3 7 4 3 10 19 17 19 23 27 28 33 39 36 23 23 32 32 16 19 35 23 12 11 12 8 4 5 7   1 2 2 1 2 3 5 4 2 3 2 6 4 4 2 4 1 2 2 1 2 3 0 4 2 1 2 6 2 2 1 3 3 1 6 4 8 5 2    3 5 2 3 0 3 2 3 1 2 2 3 4 3 8 6 2 1 4 6 3 1 2 0 2 0 2 5 0 3 3 3 3 1 3 3 2 5 4    2 1 4 2 2 4 4 1 3 2 5 2 3 1 2 0 4 0 1 0 6 3 1 2 0 2 0 1 0 0 0 0   0.112000 2.400 2.400 6.400       670484           3           0  0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 1 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 2    0 1 1 1 3 0 0 0 2 1 3 0 1 1 1 0 1 1 1 0 0 1 2 0 1 3 1 5 2 3 0 4 0 2 0 0 1 2 1    0 1 0 0 1 0 2 2 3 2 3 2 2 2 3 4 4 2 3 5 3 3 2 3 3 4 2 4 0 3 2 4 4 1 3 1 3 4 2    2 5 2 8 6 12 17 14 22 27 26 29 39 30 24 36 22 22 20 9 19 15 5 12 16 4 7 5 7 5    5 1 4 5 5 4 4 1 4 4 3 3 3 4 2 2 4 2 4 4 4 4 0 2 3 2 1 4 3 6 1 3 3 3 4 5 4 2 2    2 5 3 0 2 5 4 2 5 3 5 1 1 3 1 1 3 6 6 2 3 2 0 3 2 4 3 4 1 2 2 6 2 0 3 2 2 5 3    3 5 2 1 0 3 1 1 2 2 0 1 1 3 2 3 2 1 1 1 1 3 2 1 0 0 0 0 0 0 0   0.114000 2.450 2.450 6.500       711783           4           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 1 0 2 1 2 0 1 0 0 1 0 0 1 1 1 1 0 0 0 1    1 2 0 1 1 0 0 0 2 1 1 1 1 1 2 1 2 3 3 1 1 1 2 3 1 3 2 2 1 0 1 1 4 4 4 1 0 4 0    0 1 1 2 1 3 2 0 3 4 1 1 1 1 3 2 0 1 3 2 1 2 1 0 3 3 2 5 4 2 5 3 4 2 2 5 3 3 3    3 5 5 8 7 14 12 28 22 24 23 36 33 26 32 27 26 18 30 24 15 13 19 15 17 6 5 7 5    4 3 5 3 1 4 4 9 5 3 1 4 0 0 6 2 5 3 3 3 1 2 3 2 4 1 5 5 3 8 2 1 1 4 1 7 5 6 6    4 4 3 2 6 3 3 3 3 1 3 4 5 4 3 4 3 1 2 3 1 2 1 2 2 6 5 2 2 2 4 2 2 0 2 3 3 2 7    4 4 1 4 2 0 3 1 1 2 1 2 3 1 3 2 2 4 3 1 4 0 0 4 2 2 2 1 0 0 0 0   0.116000 2.500 2.500 6.600       745364           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 2 1 1 2 1 1 1 0 1 0 2 0 1 1    0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 2 3 0 1 4 4 0 4 0 1 0 1 3 3 0 2 1 2 3    2 1 1 1 2 0 4 0 0 4 5 2 5 4 1 3 5 5 4 0 4 4 2 3 2 3 5 2 2 4 2 3 4 2 3 3 3 3 3    2 4 12 10 13 14 19 22 23 24 36 19 32 25 25 36 24 18 20 21 14 18 13 8 6 9 2 9 5   2 5 3 4 4 3 3 0 4 3 2 5 3 4 2 2 6 3 4 0 2 4 1 3 4 7 4 5 3 2 4 5 5 3 4 4 4 2 3    2 4 4 2 1 5 7 1 5 2 4 1 5 5 3 4 4 3 2 4 2 4 0 6 2 3 4 1 2 2 2 4 1 4 2 2 2 5 6    5 1 4 4 2 3 3 3 1 4 3 4 2 6 2 5 3 2 2 1 3 2 2 5 1 1 0 0 1 0 0 0   0.118000 2.550 2.550 6.700       791846           4           0  0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 2 1 1 0 0 0 0 0 1 0 0 0 1 1 0 1 0 1 0 1 1 0 1 0    1 4 1 2 3 0 3 1 0 1 1 1 0 3 1 2 1 1 1 0 0 1 1 1 3 1 3 2 3 1 2 2 1 3 2 4 1 4 0    2 4 1 4 3 2 1 1 2 1 3 2 3 3 2 1 1 5 3 3 3 3 2 3 4 3 5 3 1 1 2 2 3 5 1 2 1 1 4    4 6 9 6 6 13 17 21 20 24 22 25 20 29 23 28 30 26 27 18 20 17 16 17 12 10 8 5 6   6 6 4 3 1 2 4 6 9 2 2 3 5 7 6 2 3 8 5 4 5 6 4 6 5 3 5 3 2 5 3 2 8 3 5 4 5 3 5    4 3 4 8 4 3 8 3 3 3 1 1 2 2 5 4 7 3 2 3 3 2 2 3 6 3 2 2 1 1 5 2 5 6 3 5 3 4 1    3 1 2 1 0 4 1 4 2 2 2 3 1 1 1 1 3 2 0 1 6 1 1 0 2 1 0 1 0 0 0 0   0.120000 2.600 2.600 6.800       833394           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 2 1 1 1 2 1 0 0 0 1 0 1 0 0 0 1 0 0 1 1 2 1 0 0    0 0 0 2 2 0 3 1 0 0 2 1 1 1 1 0 1 2 1 5 0 1 0 2 2 1 2 0 4 2 1 4 3 4 2 2 1 2 1    5 2 3 1 3 0 2 2 2 2 3 4 0 4 2 3 3 4 5 2 2 6 3 4 5 5 5 3 4 6 5 1 3 0 5 4 5 1 3    2 2 6 18 13 17 27 27 21 28 28 24 26 27 29 23 21 16 17 19 22 14 11 9 5 14 7 7 6   4 4 12 3 6 4 5 4 6 4 2 0 1 8 1 6 8 5 2 3 4 5 6 4 2 5 8 3 1 1 6 3 7 8 4 1 6 5 2   8 11 5 6 5 6 2 4 5 1 2 7 2 2 5 5 6 3 3 2 3 8 5 1 9 3 3 2 3 6 3 5 3 2 4 6 3 1 3   5 4 4 4 6 3 3 5 0 2 2 5 1 3 2 2 1 4 2 0 2 2 2 2 4 1 2 1 2 1 1 0   0.122000 2.650 2.650 6.900       876007           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 1 1 1 1 2 2 1 0 0 1 0 0 0 1 1 0 0 0 2 0 0    4 1 0 2 1 2 0 1 2 0 1 3 2 1 0 1 1 0 1 2 1 0 2 3 3 5 3 3 3 0 1 4 0 1 5 3 4 3 1    2 2 2 4 1 3 3 3 2 3 2 3 2 1 4 4 2 2 5 5 3 4 1 2 1 2 4 2 4 7 2 4 4 2 7 3 5 7 5    3 6 8 10 10 18 21 22 24 14 25 27 29 31 22 25 24 21 27 20 19 22 19 14 13 14 10    5 7 3 4 5 5 3 1 4 3 8 4 5 4 0 3 4 3 4 1 7 6 1 1 3 4 4 3 4 3 6 4 3 4 2 4 4 3 5    6 5 1 1 6 2 6 6 3 5 5 3 2 6 5 4 3 4 6 4 3 5 5 6 5 6 2 4 2 1 2 2 4 2 7 6 2 1 3    1 5 2 1 2 4 3 3 3 2 5 2 4 1 4 3 2 2 5 5 1 1 3 3 2 2 2 2 1 0 0 0 0 0   0.124000 2.700 2.700 7.000       925764           3           0  0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 2 1 3 0 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0    1 2 0 0 3 2 0 1 2 1 1 2 0 2 1 2 2 0 0 2 3 2 3 2 2 3 2 2 4 0 2 0 5 1 3 2 3 1 2    3 2 0 6 4 3 6 2 5 0 5 2 1 4 4 5 7 4 2 3 5 2 0 2 5 2 4 7 4 4 4 8 5 3 1 7 2 2 1    5 5 5 14 19 16 22 18 30 29 25 36 23 23 22 25 25 27 26 23 14 20 16 16 10 6 6 6    4 2 6 6 6 6 6 4 6 1 0 3 4 4 5 2 4 3 2 4 4 5 5 5 6 10 6 3 6 8 5 5 8 7 4 6 4 3 4   8 5 5 7 4 6 3 5 8 4 3 4 4 3 4 3 1 3 3 7 2 4 8 3 6 4 3 3 2 5 4 4 3 7 4 5 4 4 3    4 7 2 3 3 4 3 0 2 2 4 3 4 2 4 2 2 6 4 4 6 6 1 5 1 1 2 1 0 0 0 0 0   0.126000 2.750 2.750 7.100       969560           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 1 0 1 2 0 2 0 2 2 0 1 1 1 0 0 1 0 1 1 1 1 2 0    1 2 2 1 2 0 0 1 0 1 0 2 1 0 1 0 1 1 2 0 3 0 3 4 3 1 3 2 0 4 0 1 2 0 3 1 1 2 3    2 2 2 5 1 7 1 5 1 5 4 2 0 0 1 2 1 3 2 3 3 5 4 10 10 2 5 11 4 1 2 1 7 3 5 4 4 1   5 10 8 7 9 9 20 20 21 33 21 28 20 27 32 21 29 22 20 24 15 13 27 14 13 15 10 9    3 11 6 7 5 3 6 8 5 4 4 1 3 3 5 2 7 3 6 6 1 6 4 6 5 3 4 2 4 3 3 9 4 5 4 4 5 2 3   10 4 3 2 6 10 6 3 6 5 5 5 4 8 8 5 4 3 6 4 4 2 4 4 4 5 7 4 4 4 4 5 2 2 3 4 5 2    1 3 2 6 2 7 7 1 6 4 4 6 5 5 4 0 2 2 3 2 7 5 0 4 1 1 4 6 1 0 3 2 0 0 1   0.128000 2.800 2.800 7.200      1022713           5           0  0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 0 1 0 1 1 0 0 1 1 1 0 0 0 2 1 0 0 4 0 0 1 2 3    1 1 0 1 0 1 0 3 1 1 1 2 2 1 1 1 3 1 0 2 4 2 1 2 1 2 0 3 1 3 2 1 5 2 1 3 1 2 1    5 3 2 1 2 5 3 8 2 3 2 5 5 4 3 6 4 4 4 3 2 3 8 4 3 4 5 4 5 4 7 6 5 3 3 3 5 2 9    10 7 9 12 11 13 17 15 22 19 33 24 28 30 26 21 24 22 27 20 26 16 10 10 9 20 10    7 4 5 7 7 2 7 5 3 5 1 6 1 5 7 5 6 3 1 5 1 1 3 4 8 6 3 9 5 5 3 6 7 4 6 7 6 4 2    4 6 2 3 6 5 6 7 6 4 4 9 6 8 6 9 7 1 2 6 2 7 5 4 4 4 4 5 5 4 4 3 6 3 5 3 6 4 3    6 6 2 5 2 8 4 5 3 6 5 4 5 8 4 3 5 6 5 5 2 8 1 2 2 5 4 1 3 0 0 0 0 0   0.130000 2.850 2.850 7.300      1081669           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 5 0 0 2 2 0 0 1 0 0 0 1 1 0 2 0 2 2 2 1 0    1 0 2 2 3 1 1 0 2 0 1 0 2 1 1 2 2 0 1 4 3 0 2 1 1 0 2 5 2 1 0 1 3 2 5 2 1 2 5    2 3 4 3 6 6 6 4 6 6 3 1 3 2 3 4 7 5 2 9 7 4 1 4 4 3 2 2 2 7 4 8 4 7 4 6 8 5 1    8 6 10 18 21 18 15 21 24 21 26 22 30 28 27 23 22 21 17 25 20 17 13 17 9 12 7 8   5 4 4 5 5 2 4 1 1 2 5 7 6 4 9 7 7 5 5 5 5 5 2 4 5 3 6 8 2 4 9 4 10 5 1 4 5 5 5   10 3 2 8 6 5 7 3 13 3 3 6 5 1 4 5 9 5 2 7 4 5 6 3 5 6 5 4 5 9 6 4 3 4 4 4 5 8    5 5 0 3 6 3 4 3 7 5 6 4 3 3 6 8 4 1 3 1 2 7 3 4 6 6 1 3 4 1 0 1 0 0   0.132000 2.900 2.900 7.400      1131887           3           0  0 0 0 0 0 0 0 0 1 0 0 1 2 1 1 0 0 0 1 2 2 1 1 0 2 1 1 0 1 1 1 0 2 2 3 1 0 1 0    1 0 2 0 2 0 1 4 0 1 2 2 0 0 0 2 3 0 1 2 3 0 1 2 3 5 6 2 2 3 1 4 4 8 4 3 3 3 7    2 2 5 7 4 1 2 4 8 1 5 2 7 3 4 2 9 6 5 5 6 2 2 3 6 2 5 6 7 7 2 8 3 3 3 3 6 6 5    3 10 15 15 17 19 13 29 20 23 22 34 28 28 33 20 20 22 17 22 18 15 19 14 11 9 13   6 6 13 4 2 9 8 8 7 6 5 6 4 4 9 6 2 8 9 7 2 6 3 7 3 6 3 7 4 4 5 4 5 6 4 7 5 4     10 2 6 6 8 3 6 6 9 5 8 8 7 6 4 8 5 7 5 5 7 3 5 5 5 10 7 3 8 7 5 7 2 4 4 6 4 10   7 6 4 4 4 4 3 2 4 2 6 5 9 7 3 2 6 2 5 1 5 6 2 2 1 9 2 5 2 5 1 0 0 0 1 1   0.134000 2.950 2.950 7.500      1185706           3           0  0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 3 2 1 0 1 1 0 0 0 0 0 1 0 1 1 2 0 1 0 1 2 0 0 0    1 1 0 1 1 1 0 2 2 0 1 3 3 2 3 0 0 2 2 3 2 1 1 3 0 0 1 1 3 4 3 1 1 9 1 4 0 1 3    4 1 3 2 6 4 7 7 3 2 8 5 2 5 2 4 6 7 3 7 7 8 4 7 2 4 7 7 9 9 2 5 5 8 3 5 7 3 6    10 6 10 15 10 13 14 29 21 23 37 26 20 28 20 16 24 25 16 19 21 20 20 17 11 10     12 8 7 7 5 5 5 4 5 6 7 3 6 5 7 5 11 9 6 8 11 6 4 6 8 8 7 7 7 4 5 4 8 5 4 3 4 8   10 7 9 4 7 6 8 9 7 3 5 7 7 6 2 6 4 7 3 9 8 12 7 6 6 6 4 5 7 2 4 7 3 2 4 4 7 1    4 5 0 4 6 3 10 8 5 4 3 4 5 7 5 7 5 7 3 5 2 5 6 4 5 2 4 1 6 6 2 4 2 0 0 1 0   0.136000 3.000 3.000 7.600      1238426           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 2 4 0 2 0 2 2 0 1 1 1 0 2 1 1 2 1 0 1 1 0 3 1 0    0 1 0 1 0 0 2 1 1 0 4 0 2 6 3 3 4 0 3 1 2 4 0 4 4 0 1 5 2 2 5 1 3 4 3 3 5 2 4    4 6 2 5 3 4 5 4 5 6 7 5 6 2 8 3 4 7 2 4 4 3 7 6 5 1 4 8 3 7 10 3 3 6 1 5 3 8     11 5 7 15 11 15 17 21 23 21 24 28 16 21 29 15 22 27 28 20 13 19 13 7 15 10 11    9 6 8 8 4 7 5 4 6 5 10 6 7 8 9 3 5 5 9 5 9 4 4 4 3 5 7 4 10 6 8 4 9 8 4 6 7 9    11 6 8 3 5 8 12 3 6 9 7 11 9 6 7 4 7 7 7 2 5 4 5 0 2 9 5 5 5 10 7 5 6 3 9 4 4    13 2 7 5 7 4 7 2 0 4 5 4 4 6 8 1 2 5 6 4 7 3 11 4 3 3 5 5 4 4 3 1 4 2 2 1 1 0   0.138000 3.050 3.050 7.700      1299809           6           0  0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 1 2 1 1 0 0 1 0 0 2 0 1 2 0 0 3 0 0 1 3 1    2 0 2 0 1 1 2 1 2 3 2 1 2 5 2 2 2 4 3 2 5 3 0 3 2 4 5 4 3 0 5 4 1 4 3 8 6 4 4    7 4 5 4 3 6 5 6 10 3 6 6 2 6 3 4 4 3 6 7 6 8 3 4 7 5 4 9 2 4 8 5 9 8 3 7 5 7 7   13 7 11 15 17 16 18 18 18 20 17 26 25 19 20 26 31 22 18 20 18 14 11 16 4 7 11    10 8 9 9 6 3 8 8 7 5 6 10 3 5 6 6 3 12 7 8 8 2 10 4 13 9 9 12 4 5 9 7 9 5 7 4    8 9 6 7 8 10 8 7 5 7 11 6 4 4 4 6 4 9 4 5 9 10 7 4 12 7 4 9 5 10 10 6 8 4 7 2    4 7 2 6 8 4 11 3 3 9 7 6 7 3 8 7 4 8 5 3 7 4 5 5 7 4 6 7 5 5 3 5 2 5 4 1 2 0 0   1   0.140000 3.100 3.100 7.800      1361810           3           0  0 0 0 0 0 0 0 0 0 1 0 0 0 0 3 2 1 0 0 0 1 1 1 2 0 0 0 0 1 0 2 2 2 1 0 0 3 3 0    2 0 6 2 3 1 0 3 3 1 2 2 5 3 5 3 3 2 2 7 3 2 2 3 4 2 3 4 4 1 3 7 4 5 4 2 3 5 4    2 1 3 6 3 4 3 8 7 6 5 3 5 11 5 5 3 3 7 3 6 4 4 2 4 4 4 1 5 5 9 6 6 9 3 10 8 6    8 3 10 8 16 16 13 18 23 29 25 19 19 20 27 19 22 27 24 21 15 18 11 20 21 17 12    5 18 6 12 7 9 11 7 12 11 4 8 8 4 8 7 7 2 6 4 4 9 6 9 3 4 7 7 7 4 10 4 11 5 8 8   8 5 4 4 8 6 4 9 8 12 12 8 5 8 3 10 8 7 5 3 5 6 8 5 6 10 7 2 11 2 5 5 6 8 10 2    7 5 5 14 2 7 3 9 3 5 2 8 2 3 4 4 7 9 5 4 7 6 7 5 6 3 5 4 7 6 7 7 9 3 0 2 1 1 1   0 0   0.142000 3.150 3.150 7.900      1429499           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 1 2 1 1 0 0 0 3 0 2 2 1 0 3 0 2 1 3 0 0 1    1 3 1 2 4 1 5 3 5 1 0 7 1 3 2 3 2 2 2 3 0 0 1 3 6 3 2 2 4 4 4 6 4 3 6 4 10 3 7   2 5 4 7 4 5 8 4 7 4 1 7 11 5 2 10 2 11 3 7 8 10 9 6 3 5 3 6 3 10 11 5 5 9 7 10   8 9 5 15 11 9 18 18 15 24 17 23 17 19 25 17 24 18 37 16 17 21 17 14 20 17 15     15 9 4 11 7 3 8 10 8 8 6 8 3 4 5 8 4 6 3 9 9 6 2 10 4 4 3 8 4 9 1 7 5 9 7 10 9   10 4 6 5 8 6 6 10 10 6 5 7 6 6 10 5 7 8 8 8 7 7 11 12 8 3 10 6 9 13 11 4 6 7 6   3 10 5 8 4 7 7 7 5 8 4 9 5 5 7 6 6 7 11 11 7 8 5 3 5 7 7 10 3 3 6 5 7 9 2 3 7    1 0 0 0 0 1   0.144000 3.200 3.200 8.000      1493946           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 2 3 0 0 1 2 1 1 1 4 1 0 1 0 1 2 1 3 1 1 1 1 2    1 1 3 2 6 0 4 0 1 4 2 4 5 2 1 3 0 2 2 4 2 3 2 4 3 5 4 4 4 1 5 1 3 4 5 6 4 7 2    8 8 8 5 3 6 0 7 3 2 2 5 7 5 7 5 8 9 6 4 3 6 8 6 10 2 5 6 3 3 6 6 6 6 17 5 10 6   6 11 11 13 12 21 26 18 24 21 24 23 30 18 22 20 24 19 13 17 25 22 17 15 8 13 7    10 8 9 6 7 9 8 7 8 9 7 7 6 12 5 9 9 12 9 12 6 9 7 10 7 7 4 9 7 4 2 7 4 5 8 8 9   7 6 7 5 9 4 8 13 6 5 4 7 9 6 7 7 9 4 4 5 8 10 9 10 6 6 7 9 12 11 8 8 9 11 5 8    7 5 5 8 5 9 10 5 5 11 11 6 8 8 4 8 5 5 5 4 7 4 5 6 5 6 6 7 7 4 2 6 3 2 1 0 0 0   0 0   0.146000 3.250 3.250 8.100      1562352           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 2 0 1 2 1 1 0 0 1 0 1 2 0 0 0 3 1 2 0 4 4 2 0    0 2 3 2 0 1 3 3 4 0 1 4 3 3 4 5 5 4 2 1 4 2 5 3 2 7 6 3 5 6 5 5 5 1 5 2 7 4 8    7 4 6 5 7 5 3 5 8 1 6 4 6 8 7 6 7 6 3 4 6 3 5 8 4 10 3 3 11 6 5 3 9 6 4 3 17 9   11 11 24 13 15 14 25 26 26 21 17 32 32 22 18 25 29 29 27 24 21 12 23 14 12 11    9 17 7 9 11 3 7 6 5 5 12 3 6 8 7 4 7 11 10 8 9 5 8 2 10 9 8 10 10 7 7 4 7 5 7    7 9 10 8 7 7 16 6 8 10 5 6 6 12 12 7 11 11 8 9 7 8 12 10 7 8 7 11 8 9 7 7 4 9    4 7 14 9 8 8 13 9 8 7 13 5 9 5 7 4 9 5 7 8 7 8 7 3 10 9 3 4 4 4 5 2 6 6 3 5 10   4 4 2 3 0 1 0 0   0.148000 3.300 3.300 8.200      1630559           3           0  0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 4 2 1 1 1 2 1 2 0 2 1 5 0 1 1 4 0 2 1 4 5 3 0    1 1 1 2 1 3 3 3 1 1 1 1 1 3 4 6 6 8 8 4 3 2 7 2 2 1 7 4 4 5 1 10 6 4 4 4 3 3 3   6 11 6 4 5 4 8 5 5 9 4 5 5 7 6 4 13 12 3 6 7 5 2 7 9 7 8 8 4 7 6 4 10 6 8 9 9    9 13 15 17 23 25 13 16 24 22 26 21 27 24 24 21 21 21 15 17 22 25 21 22 17 14     11 8 12 5 9 7 8 5 11 10 6 6 5 9 13 10 9 8 8 8 6 4 9 10 9 9 7 8 7 5 7 8 14 13 5   14 5 12 11 8 9 6 5 4 9 13 7 10 13 11 11 8 5 9 10 8 7 6 7 13 3 13 8 7 13 17 5 8   5 10 7 12 7 6 6 9 7 8 8 11 8 11 9 11 11 8 5 6 10 4 9 3 10 8 7 10 8 7 8 10 10 7   4 11 5 7 8 2 4 3 0 0 1 0 1   0.150000 3.350 3.350 8.300      1707576           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 1 2 1 0 2 0 2 3 1 3 2 2 2 2 0 2 1 4 3 2 2 3    1 2 1 0 2 2 4 2 5 3 3 5 2 8 4 5 4 2 3 6 7 6 1 0 7 4 7 7 6 5 4 3 4 6 6 7 6 2 7    4 4 2 5 5 6 9 3 3 3 6 6 5 3 5 7 8 8 6 8 8 6 8 3 9 6 6 8 8 6 4 8 6 6 10 4 11 6    11 15 23 16 8 17 20 21 19 24 15 14 19 21 30 25 21 15 19 16 18 21 21 15 14 12     16 8 10 12 7 10 9 8 10 10 7 9 8 10 12 6 6 9 11 6 5 9 12 6 7 12 7 5 6 8 5 9 4     11 9 8 8 10 7 6 10 7 11 13 7 4 13 11 8 11 9 16 6 12 11 10 10 19 2 9 11 8 7 8 8   6 13 6 10 12 12 9 12 9 9 8 7 7 9 6 12 8 4 9 9 8 5 7 8 9 5 12 5 7 5 9 10 9 10 3   6 6 8 7 11 3 5 5 4 2 0 0 0 0   0.152000 3.400 3.400 8.400      1777231           3           0  0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 3 1 0 3 4 2 3 3 3 3 3 2 1 1 1 1 3 3 0    1 8 0 0 5 3 7 4 4 4 4 4 3 5 2 2 5 3 6 1 7 6 1 2 2 5 2 1 6 6 8 7 7 5 10 4 1 6 9   3 4 5 3 5 8 4 9 8 11 8 3 2 7 7 9 10 9 10 8 6 8 6 8 7 10 8 7 3 8 4 10 7 6 8 9 6   5 16 9 19 24 23 17 23 24 22 30 21 15 23 27 20 20 20 18 20 23 18 17 15 19 17 18   13 9 4 4 7 12 7 10 4 8 6 10 5 6 13 2 3 8 7 8 7 3 11 8 7 9 7 19 7 8 9 6 14 8 8    11 10 11 13 14 10 16 8 9 13 8 9 9 12 7 12 11 6 9 15 5 9 9 9 11 11 13 6 10 6 4    12 9 9 12 11 8 6 9 16 10 10 10 8 10 10 6 7 4 1 15 6 8 4 9 13 11 8 10 11 9 8 3    3 6 6 7 9 4 6 8 7 4 2 1 2 2 1 0   0.154000 3.450 3.450 8.500      1849489           6           0  0 0 0 0 0 0 0 0 0 0 1 1 3 0 1 2 2 0 1 4 1 1 0 1 0 2 1 0 0 1 1 1 1 6 3 6 1 3 1    3 3 0 6 0 4 2 7 4 6 4 4 3 7 4 5 7 5 5 2 3 9 9 2 5 5 3 9 4 2 7 6 2 8 2 5 7 12 6   5 4 5 10 4 12 10 6 4 14 7 9 10 11 7 7 7 7 3 9 7 4 3 8 7 5 7 9 6 8 9 6 8 8 12 6   5 11 12 13 11 13 21 26 19 23 25 18 23 22 23 23 18 27 20 15 20 25 24 19 18 12     14 13 15 8 15 10 11 7 9 13 11 12 13 11 11 7 11 13 6 5 10 6 6 10 8 14 5 14 11 8   5 9 7 10 10 8 7 15 13 3 13 12 18 15 7 10 9 10 8 15 9 6 8 9 10 10 9 5 7 7 5 10    11 13 12 12 12 10 6 17 10 11 9 4 8 7 6 6 9 12 8 16 18 7 5 10 8 12 10 15 6 13     11 6 10 16 10 11 16 8 9 5 11 10 14 11 5 2 5 7 3 1 1 0 1 0   0.156000 3.500 3.500 8.600      1920727           4           0  0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 2 1 2 0 3 0 1 1 0 1 0 3 0 4 4 1 3 1 2 3 3 4 3    1 2 3 9 5 2 3 7 3 3 6 5 2 6 1 4 3 2 3 6 5 1 8 3 8 5 3 7 6 13 11 9 5 8 7 7 5 8    7 4 8 6 4 10 4 6 5 6 9 9 12 6 7 10 9 9 8 8 3 8 9 8 8 2 12 11 13 8 13 7 8 6 6 9   6 8 16 13 14 16 16 22 20 21 21 17 20 18 19 22 20 11 20 22 21 14 19 15 23 17 15   12 14 19 16 10 11 14 11 9 11 9 12 8 16 14 9 6 18 10 11 7 10 11 17 10 13 8 10     12 9 12 7 7 10 10 11 11 9 8 8 14 10 10 9 14 9 14 13 9 19 16 17 4 11 8 12 11 10   21 6 10 8 9 12 9 7 7 12 7 16 14 10 13 6 13 8 9 10 6 10 8 7 10 4 6 11 19 12 6 7   5 8 11 10 12 13 9 6 10 5 11 11 4 14 10 7 2 6 5 1 2 5 1 1 0 0   0.158000 3.550 3.550 8.700      1999833           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 2 3 2 2 2 1 2 3 0 1 0 1 3 2 0 0 3 2 3 2 5 7 0    3 4 1 10 7 7 4 5 2 3 4 3 8 3 6 4 4 4 8 2 3 4 5 5 7 1 6 7 8 1 6 8 1 4 4 11 9 4    7 11 9 10 5 6 8 4 3 9 7 9 11 5 5 8 8 4 8 7 8 11 9 12 6 4 13 4 12 10 6 9 11 10    11 10 11 11 11 14 15 14 23 18 17 29 16 26 23 15 19 14 18 19 22 31 13 21 20 12    16 15 14 18 17 15 8 12 14 13 10 10 10 10 10 13 11 6 8 11 8 14 8 10 11 11 8 10    13 5 14 7 12 9 10 10 12 15 18 8 6 9 9 12 8 9 20 14 16 10 11 14 5 5 13 6 11 9     11 15 6 9 13 11 7 8 7 10 8 16 12 11 8 10 14 11 17 11 8 16 13 9 10 5 10 17 13     14 16 8 10 9 11 5 10 9 10 12 8 11 12 11 8 6 7 12 15 13 12 7 13 5 0 3 2 0 0 0 0   0.160000 3.600 3.600 8.800      2073149           3           0  0 0 0 0 0 0 0 0 0 1 0 0 0 0 2 1 2 1 2 2 1 0 2 2 1 0 3 6 4 5 5 2 2 2 5 5 3 6 4    6 4 5 2 4 4 3 2 4 6 3 3 6 5 7 4 5 7 5 3 5 6 13 5 3 10 5 9 7 4 5 6 5 10 6 5 5 6   6 4 14 7 6 11 6 9 10 9 8 5 3 8 10 10 6 6 8 9 5 6 14 7 11 10 9 9 11 13 8 4 5 10   12 6 16 8 8 7 19 20 23 10 16 27 25 23 19 26 21 16 20 21 24 18 25 8 11 13 16 18   13 22 18 9 16 4 16 10 12 13 9 7 9 8 17 11 10 13 10 14 4 9 12 16 8 9 16 17 13     11 14 8 8 13 9 11 15 10 11 14 8 6 4 9 11 18 9 9 8 9 15 11 11 11 9 6 13 13 10 7   8 10 15 14 9 7 4 10 12 17 10 14 13 10 10 12 20 9 7 6 11 15 11 10 8 9 6 10 13     17 6 8 9 6 13 13 16 10 15 5 11 14 11 12 6 5 12 9 4 9 2 4 1 1 0 0 0   0.162000 3.650 3.650 8.900      2156456           5           0  0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 2 0 1 1 3 2 3 4 3 3 2 1 3 6 5 2 3 4 4 3 6 2 3    4 4 5 5 3 4 1 4 5 9 3 3 4 3 3 8 5 6 12 2 10 3 4 6 8 9 8 8 2 2 7 5 8 2 8 9 7 2    6 8 6 5 8 2 7 5 6 13 5 6 8 11 6 10 5 6 3 8 10 11 10 10 14 10 11 8 11 8 12 6 12   5 15 12 13 10 13 13 18 23 12 21 18 21 23 20 30 20 23 26 24 24 21 21 29 19 21     16 23 20 13 19 13 16 11 15 13 13 11 8 11 14 14 13 4 16 15 18 13 9 19 8 11 6 9    14 8 13 12 13 10 13 10 14 11 13 11 8 10 13 11 11 14 11 8 14 11 10 9 14 12 14     18 8 12 7 13 12 10 14 14 8 12 17 11 13 9 12 12 15 7 9 13 17 11 11 11 12 17 12    11 16 15 8 9 12 7 13 15 11 16 7 10 7 14 5 18 10 10 8 8 6 6 13 14 6 9 11 9 9 3    5 1 1 3 0 0   0.164000 3.700 3.700 9.000      2234753           3           0  0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 4 1 4 2 1 3 1 1 3 2 3 3 1 3 6 2 4 4 3 3 3 6 5 2    6 4 1 3 3 7 1 4 4 6 12 4 5 2 6 4 9 3 1 8 11 5 2 7 6 3 8 4 7 3 8 3 9 6 7 8 9 2    7 6 9 6 15 6 9 5 9 4 9 17 15 10 2 10 6 8 12 12 11 12 10 9 7 11 8 7 5 11 10 14    16 7 7 7 13 15 10 16 17 21 19 14 18 24 19 27 27 24 20 22 24 21 20 14 24 17 17    18 32 15 12 13 15 12 8 14 11 11 19 11 14 15 18 10 5 12 11 11 9 15 9 7 9 16 12    9 12 10 15 9 18 7 11 12 14 7 20 8 10 13 14 11 6 6 9 11 8 10 16 8 17 13 17 9 16   11 10 9 13 20 17 14 12 10 13 11 9 9 17 20 10 16 8 14 13 14 18 15 15 8 10 12 11   22 12 13 9 12 9 11 14 19 12 12 8 8 12 11 19 11 11 12 15 11 15 13 9 9 10 9 4 9    4 2 1 0 0   0.166000 3.750 3.750 9.100      2327990           3           0  0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 0 1 2 2 1 1 0 0 3 1 4 2 6 4 2 4 3 2 5 5 2 3 1 3    1 2 10 2 7 4 3 4 3 3 4 3 10 6 9 6 3 8 5 5 3 4 4 6 8 4 4 7 5 5 11 14 5 3 6 8 8    7 10 11 7 17 7 11 10 8 7 8 12 13 11 12 6 13 9 7 7 6 5 8 13 10 10 14 11 11 8 12   15 14 9 13 10 9 18 13 18 12 23 14 17 24 15 23 25 31 19 17 29 19 19 19 26 25 19   17 22 19 19 19 11 11 12 22 21 8 10 18 10 14 19 17 13 14 10 6 9 10 15 11 5 13     13 11 11 17 16 9 7 14 7 19 6 10 13 7 12 18 14 7 12 15 13 13 9 13 13 13 12 12     14 12 19 10 16 18 18 12 8 10 10 9 7 14 9 11 13 12 8 15 12 11 10 12 11 17 15 19   14 14 12 7 7 12 11 15 16 12 11 12 10 19 19 12 14 12 15 11 20 13 7 18 9 15 19     16 11 5 9 8 6 2 4 0 2 0 1   0.168000 3.800 3.800 9.200      2406866           3           0  0 0 0 0 0 0 0 0 0 1 0 2 0 1 0 2 3 2 3 1 2 1 2 2 5 2 1 2 3 2 2 2 5 3 5 3 3 1 3    6 8 6 1 3 9 6 3 6 10 5 5 7 4 5 7 12 9 5 7 5 6 6 8 3 5 4 7 8 5 6 5 8 13 4 10 2    10 9 7 7 16 9 10 9 13 8 12 9 13 15 9 15 9 10 11 6 6 6 7 7 6 8 15 9 8 9 6 12 12   11 14 12 11 13 8 17 18 18 11 14 19 14 25 21 15 10 15 19 27 23 22 24 17 19 18     12 16 22 21 25 9 25 15 19 15 21 15 8 11 13 12 10 12 7 13 11 17 11 13 10 16 19    14 23 11 8 12 13 10 9 17 4 14 10 7 10 17 14 11 11 20 18 13 8 12 6 8 13 12 23     15 14 15 16 9 14 9 13 14 17 11 17 11 10 15 17 11 6 12 12 14 15 17 12 16 16 8     17 15 15 10 15 11 10 15 12 13 9 12 9 12 15 12 6 18 7 15 14 12 21 18 11 10 18     11 19 11 7 11 3 2 5 4 0 1 1   0.170000 3.850 3.850 9.300      2508471           7           0  0 0 0 0 0 0 0 0 0 0 0 0 1 3 1 2 1 4 3 3 1 2 7 0 3 2 2 2 2 5 2 3 2 3 3 4 3 7 3    5 3 4 4 6 2 3 10 4 11 3 13 7 7 5 6 3 8 10 6 6 4 10 11 4 12 7 8 9 7 7 8 4 6 7 9   9 5 9 11 5 14 9 10 7 9 8 8 5 6 11 13 14 10 10 10 10 8 9 9 9 9 14 14 13 11 8 18   9 10 9 16 12 13 15 13 10 17 16 20 14 22 20 26 29 29 27 24 20 37 21 24 13 18 13   28 24 22 25 21 13 14 15 9 11 18 8 16 17 16 13 12 16 11 11 17 15 11 15 10 11 12   13 12 12 20 15 14 15 16 12 17 15 15 12 10 14 14 17 15 19 15 13 13 11 12 16 14    17 16 8 16 12 8 14 13 13 10 10 9 12 11 19 20 13 11 4 15 11 14 11 20 18 18 13     20 12 20 21 15 15 12 13 18 18 11 16 9 14 9 18 11 10 11 20 11 13 17 13 13 12 14   16 10 12 12 23 12 11 12 8 8 1 0 1 2 0   0.172000 3.900 3.900 9.400      2591210           3           0  0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 4 4 3 2 1 3 3 2 3 0 3 6 1 3 1 5 5 4 3 9 9 0 4 7    5 3 5 5 8 7 3 3 5 5 8 5 11 10 8 10 3 6 6 6 7 7 8 8 12 9 6 10 8 7 10 8 8 10 4 6   12 20 4 6 11 7 9 10 7 5 10 6 12 11 7 13 13 16 12 6 8 14 13 9 7 5 14 17 17 10     12 11 6 13 11 17 3 23 13 21 12 21 28 11 23 30 28 23 24 26 26 17 21 15 27 23 33   16 22 25 11 20 22 23 21 20 7 21 13 16 12 16 16 13 18 18 9 13 16 15 9 20 13 19    15 8 9 11 14 13 10 9 10 16 15 14 17 15 19 16 12 14 12 14 14 16 19 19 4 24 8 12   15 16 11 15 14 20 14 13 13 14 16 19 14 13 19 14 18 23 15 15 4 14 17 14 8 10 15   20 11 15 19 12 9 13 12 11 16 12 16 13 14 16 13 16 16 19 19 12 11 10 19 15 15     14 12 5 11 18 17 10 13 12 9 6 2 0 0 1 0   0.174000 3.950 3.950 9.500      2675515           3           0  0 0 0 0 0 0 0 0 0 0 2 0 1 1 0 2 1 2 3 3 1 3 1 3 7 5 3 6 4 3 9 4 5 2 5 3 3 3 6    9 5 5 2 6 8 5 8 4 8 5 6 5 6 4 6 3 7 11 6 9 9 3 6 6 7 6 8 7 9 12 18 6 9 8 11 11   8 14 15 15 11 15 13 9 19 10 15 14 9 4 18 5 8 10 8 10 13 9 12 11 8 8 12 6 15 8    9 9 18 7 17 21 9 13 18 14 21 24 18 22 17 26 15 21 23 25 19 26 23 20 27 17 27     20 26 15 22 15 19 15 16 24 12 15 24 13 13 17 11 7 10 21 15 15 16 13 20 22 12     16 12 16 15 14 18 11 12 14 14 24 10 13 16 19 8 11 18 19 15 15 23 16 16 11 12     18 11 13 14 16 10 14 13 18 12 15 15 14 8 11 17 12 22 13 12 14 15 10 11 15 19     15 12 17 8 21 23 13 19 11 8 12 15 11 14 15 19 15 10 17 9 16 14 18 14 16 14 14    23 14 14 13 16 12 14 15 14 9 14 7 5 2 3 1 1 1   0.176000 4.000 4.000 9.600      2779386           5           0  0 0 0 0 0 0 0 0 0 0 0 2 2 3 0 1 3 0 6 2 6 3 1 5 0 4 1 6 5 1 6 3 6 5 6 2 5 4 5    3 9 8 5 7 5 8 4 12 8 12 6 8 5 7 5 7 10 5 5 6 7 9 7 10 7 10 10 8 12 10 6 13 10    11 12 11 10 10 16 9 6 12 9 11 17 10 11 10 14 11 16 7 11 13 12 10 17 14 11 13     12 10 13 16 16 17 17 15 14 11 8 15 13 27 22 14 19 17 22 22 27 18 28 19 27 32     24 33 21 17 23 12 27 25 20 20 17 22 14 15 22 21 14 9 16 12 19 16 17 16 16 20     14 18 15 14 18 10 12 9 16 12 12 10 13 19 12 12 15 14 15 22 12 11 15 18 19 18     10 6 11 14 10 23 17 14 16 19 10 10 16 19 17 23 16 18 19 18 16 12 14 14 14 13     11 10 24 21 22 26 18 18 18 14 17 5 13 17 11 13 16 14 18 16 9 15 15 18 16 14 21   13 22 17 9 8 16 17 16 16 19 7 20 19 18 16 10 6 10 6 3 5 1 0 0 2   0.178000 4.050 4.050 9.700      2869617           3           0  0 0 0 0 0 0 0 0 0 0 2 2 2 0 1 4 1 3 2 2 1 2 3 2 2 4 4 7 5 6 5 3 6 6 5 7 8 1 5    2 3 5 5 8 10 7 6 10 9 6 8 9 7 8 10 15 4 10 5 8 8 6 11 8 8 11 7 5 8 14 5 11 7     13 10 9 7 8 9 14 12 10 9 11 6 14 15 14 13 11 9 18 18 10 14 14 10 12 16 12 9 8    14 15 6 11 11 12 10 14 12 11 18 13 13 27 16 23 23 20 21 32 20 18 25 22 24 32     25 34 19 23 21 25 22 25 19 23 19 21 16 19 16 18 9 18 6 13 12 13 18 12 8 19 14    14 11 16 13 15 14 21 11 14 14 13 11 20 14 14 26 10 22 16 18 15 20 24 18 19 19    16 14 14 14 21 13 19 18 20 13 17 11 17 14 22 17 15 15 20 8 21 15 16 16 23 17     13 19 21 20 12 15 18 15 19 15 18 17 20 15 13 14 24 18 15 15 14 18 20 19 17 19    20 21 21 15 19 19 17 11 16 16 11 23 10 20 13 10 5 10 2 3 1 1 0   0.180000 4.100 4.100 9.800      2975040           3           0  0 0 0 0 0 0 0 0 1 0 0 1 2 2 4 4 2 4 4 1 2 5 0 3 3 5 2 5 5 4 9 2 7 8 4 8 3 11 6   10 4 7 8 6 6 5 8 8 7 11 4 4 11 12 7 11 7 10 11 7 11 11 10 9 7 13 12 18 8 14 12   14 12 8 8 16 10 10 14 16 10 6 8 15 15 15 22 13 19 18 12 6 11 10 7 12 12 24 15    17 9 17 21 10 17 18 14 14 14 9 22 11 23 17 15 23 32 20 11 12 20 15 23 30 20 25   19 26 29 19 27 23 15 19 11 30 16 21 24 18 18 14 8 6 25 13 21 13 13 19 13 21 25   23 18 14 14 13 20 12 14 8 10 25 14 15 20 15 10 15 16 21 8 15 20 21 20 13 16 15   20 11 18 17 17 9 12 24 19 13 18 17 20 14 15 20 10 23 19 25 8 7 13 14 11 15 18    13 10 12 10 17 11 24 16 17 11 12 13 16 20 14 26 12 17 13 14 16 16 6 20 16 23     22 11 17 16 14 25 19 17 21 22 19 13 19 16 18 10 11 7 4 6 0 0 2   0.182000 4.150 4.150 9.900      3083416           6           0  0 0 0 0 0 0 0 0 0 0 2 1 1 4 1 3 4 3 5 6 2 1 4 2 3 5 6 6 7 2 4 1 11 7 5 2 6 6 8   9 8 12 7 11 9 6 12 7 8 9 6 6 8 11 6 6 8 11 8 11 12 11 13 9 10 7 9 6 11 9 13 12   12 8 14 15 8 9 8 8 11 22 16 6 11 16 15 9 13 12 12 13 11 15 9 9 16 14 14 12 21    12 12 12 16 19 10 15 18 8 16 14 16 16 21 30 22 9 25 19 19 26 23 33 25 22 21 19   21 20 20 21 20 26 20 29 27 25 25 21 20 25 21 21 18 14 19 15 6 20 18 16 20 16     13 13 15 15 15 15 22 16 15 15 11 21 19 11 19 13 14 15 17 21 12 18 12 22 18 21    18 13 23 15 18 9 21 11 14 23 18 21 25 18 22 15 21 23 15 15 16 19 21 18 19 21     17 13 24 23 22 19 14 20 22 15 14 14 20 20 23 13 18 15 18 20 20 24 9 12 17 21     21 12 16 17 16 16 21 26 19 15 21 22 24 15 11 13 13 6 8 1 4 0 1 0   0.184000 4.200 4.200 10.00      3174897           3           0  0 0 0 0 0 0 0 0 0 0 1 1 2 3 0 5 4 3 3 0 7 3 2 4 2 8 6 4 5 9 3 8 6 4 2 7 6 8 7    9 3 5 8 5 9 7 7 6 11 14 7 12 9 9 5 15 12 14 15 12 9 11 5 8 13 11 12 10 9 17 12   11 8 17 11 19 11 15 9 11 7 15 14 16 16 16 7 12 10 14 13 13 16 16 11 15 13 14     12 16 11 12 13 17 10 13 19 11 17 11 13 14 13 10 19 19 23 24 22 24 24 31 19 23    22 28 21 25 29 17 23 17 21 30 22 19 25 27 27 22 23 23 17 25 17 20 17 12 23 21    9 17 20 16 19 16 17 20 9 16 11 22 16 15 12 15 17 23 24 16 16 18 26 11 16 20 18   10 14 17 26 19 17 15 17 19 12 21 20 24 17 27 13 16 18 19 23 14 19 14 10 11 18    19 6 15 21 23 25 17 17 18 21 27 20 17 18 20 25 22 20 18 22 18 17 15 24 16 15     22 18 22 14 20 20 22 18 22 25 19 26 12 19 19 13 12 16 19 14 9 7 5 4 2 0 2   0.186000 4.250 4.250 10.10      3283256           3           0  0 0 0 0 0 0 0 1 0 0 1 1 4 1 5 2 5 5 3 4 6 3 2 4 7 8 2 6 6 4 10 7 8 7 5 4 4 9 8   18 10 7 6 6 13 12 10 13 10 7 15 4 7 10 13 12 8 8 13 5 14 6 9 14 9 10 16 12 13    11 8 12 11 10 13 9 11 15 17 23 18 13 10 12 11 12 14 14 14 10 12 12 16 13 15 13   13 14 18 10 13 17 14 14 14 12 12 8 18 14 23 20 16 19 16 16 16 27 18 21 19 20     19 37 22 21 22 28 24 26 18 21 28 21 22 21 21 22 16 15 13 22 22 27 22 11 13 20    10 17 16 19 20 30 18 25 8 7 22 18 17 14 23 16 17 11 16 24 19 18 22 15 15 23 16   13 15 22 14 8 12 18 13 15 22 17 15 15 17 27 21 19 21 24 17 10 12 14 19 17 22     18 19 17 28 19 15 14 16 28 17 20 15 11 22 18 19 16 21 17 24 19 22 22 20 10 20    18 18 18 21 18 23 18 32 26 21 21 22 20 22 16 17 20 22 21 17 13 13 11 9 5 0 1 1   1   0.188000 4.300 4.300 10.20      3396610           5           0  0 0 0 0 0 0 0 0 0 0 1 2 3 0 2 5 5 4 3 3 5 1 2 3 6 9 3 3 3 8 7 2 9 5 7 5 11 8 9   7 6 9 6 4 5 8 6 10 9 14 10 15 6 7 13 15 10 13 7 15 10 10 11 14 14 6 7 17 13 19   3 13 9 6 13 13 14 10 11 12 16 17 13 10 15 15 19 19 11 11 15 11 13 9 13 20 8 18   14 18 23 23 23 15 19 20 14 11 7 18 16 15 22 28 20 24 22 25 17 20 39 24 26 25     25 33 25 25 25 33 15 29 18 29 18 12 18 23 17 24 28 22 16 20 33 23 18 23 26 23    15 24 16 16 16 16 17 15 15 16 14 11 9 23 17 13 13 18 12 19 20 30 20 20 15 21     19 16 18 20 23 19 15 10 11 15 19 13 22 22 18 19 16 19 23 16 10 25 23 20 21 20    31 19 19 18 15 22 18 14 13 21 18 19 22 19 16 17 21 14 20 26 18 26 22 19 26 19    20 22 15 13 24 23 15 21 21 21 27 18 22 19 24 17 22 16 18 23 10 12 3 5 3 3 0 0   0.190000 4.350 4.350 10.30      3502025           3           0  0 0 0 0 0 0 0 0 0 0 0 3 0 3 2 3 4 4 3 4 5 10 7 6 6 4 5 12 10 6 6 13 10 6 7 14    9 6 13 10 12 16 3 9 9 7 5 6 13 11 10 8 11 19 12 14 13 16 13 14 9 12 14 13 14     16 10 14 7 16 18 16 9 15 11 20 15 10 14 14 11 14 17 10 6 16 10 15 12 17 17 20    15 7 12 23 15 8 13 12 8 16 15 20 16 16 20 14 11 20 24 23 20 16 18 27 25 31 27    27 25 21 31 27 20 23 24 32 17 21 34 27 17 19 19 25 30 27 21 24 28 30 19 26 21    14 16 21 23 27 8 17 21 17 11 23 15 22 15 18 10 17 20 23 18 18 17 19 22 15 22     21 19 23 18 18 26 17 18 26 18 24 15 22 23 23 19 23 25 23 24 26 10 21 16 32 23    18 19 24 21 28 26 22 19 19 14 30 21 24 23 22 21 13 27 20 27 24 15 20 22 22 13    25 14 19 32 21 18 18 23 22 22 14 18 20 24 14 19 20 18 17 24 29 27 20 12 18 17    11 9 2 3 2 1 0   0.192000 4.400 4.400 10.40      3593938           3           0  0 0 0 0 0 0 0 0 0 0 1 0 1 1 2 3 4 7 8 1 5 6 8 3 7 5 4 9 8 8 7 7 9 7 9 9 15 5 7   8 15 14 9 9 13 8 8 15 10 7 10 9 10 14 7 8 18 16 17 11 14 15 13 8 15 8 15 18 16   16 22 12 8 16 13 10 13 13 10 21 11 10 16 16 13 13 17 16 20 23 13 22 16 14 15     22 19 22 15 22 24 16 16 16 19 12 15 16 17 20 18 19 26 17 23 18 32 20 28 36 22    25 30 29 31 36 24 24 21 29 24 32 29 30 23 34 19 33 34 25 20 31 27 24 16 14 21    20 13 24 17 28 13 24 16 26 15 26 21 11 15 20 13 20 18 25 23 18 24 26 22 16 22    14 13 16 20 24 25 19 29 20 15 20 16 25 26 21 22 17 24 22 21 17 23 23 15 19 30    23 17 21 19 18 21 26 14 29 24 20 33 19 15 20 23 28 19 23 25 15 19 17 31 23 18    29 26 25 14 24 25 18 19 19 24 35 31 23 23 14 15 19 11 20 19 24 17 16 9 10 12 3   2 2 0 1   0.194000 4.450 4.450 10.50      3712573           7           0  0 0 0 0 0 0 0 0 0 0 0 1 1 1 5 3 5 4 3 11 3 10 4 6 7 8 5 5 5 8 9 12 7 7 11 8 6    7 9 10 13 10 6 13 9 9 9 11 14 14 12 13 10 6 13 13 15 12 13 19 8 14 13 16 11 13   14 15 9 15 16 13 16 17 17 17 23 18 16 19 10 13 18 16 10 9 21 11 22 14 20 14 18   13 15 12 13 14 16 14 15 20 29 17 14 18 8 15 21 15 19 15 22 20 17 15 23 26 16     26 24 23 23 23 23 30 24 29 28 26 35 33 31 22 23 22 20 37 22 27 33 26 27 26 17    16 18 27 22 21 24 18 18 18 17 15 18 14 19 24 22 15 20 21 15 19 25 15 16 26 19    22 29 20 16 13 15 16 32 24 23 13 33 17 22 18 18 23 24 22 21 20 26 21 16 22 18    18 16 15 26 26 17 22 21 13 25 24 13 23 18 18 25 32 20 24 21 17 19 24 24 23 33    19 19 21 32 18 22 23 19 23 32 18 31 22 25 23 23 31 29 21 16 20 20 15 22 14 12    5 10 9 2 1 0 1   0.196000 4.500 4.500 10.60      3829518           3           0  0 0 0 0 0 0 0 0 0 1 2 2 1 6 2 6 5 9 3 5 6 8 6 3 8 10 7 11 9 4 8 9 5 11 10 13 9   16 13 10 9 5 12 9 15 10 13 9 12 18 14 19 9 13 14 12 13 21 17 17 18 16 13 12 16   14 18 10 15 15 16 11 15 22 17 19 17 11 12 26 12 17 19 18 21 20 27 17 18 19 21    14 19 16 12 16 21 20 18 8 17 17 13 13 18 15 19 15 19 20 28 21 29 27 27 34 24     26 31 25 24 16 17 23 23 30 28 18 28 32 28 37 18 26 18 16 33 21 31 21 20 22 19    20 25 18 18 20 11 17 20 22 23 14 14 17 18 20 25 20 19 20 22 19 16 33 25 21 21    24 18 16 22 29 22 16 27 26 28 21 20 22 17 25 23 20 23 18 16 19 26 22 21 22 23    15 20 19 17 23 19 20 15 22 18 22 26 23 23 31 17 29 18 13 15 19 18 24 22 28 22    17 23 24 26 21 23 25 24 29 26 18 41 24 29 22 27 23 28 16 30 24 18 23 19 17 18    21 17 14 8 2 5 2 0 0   0.198000 4.550 4.550 10.70      3950740           3           0  0 0 0 0 0 0 0 0 1 1 1 2 1 3 7 5 6 7 7 7 4 5 6 4 1 8 9 10 9 8 10 8 12 6 10 8 10   8 11 9 10 15 7 11 8 13 11 13 15 15 17 12 10 8 17 12 9 14 12 14 11 14 21 14 15    20 18 16 8 15 22 24 14 10 18 14 15 16 12 10 16 21 16 25 17 20 17 17 20 15 24     15 17 22 25 17 13 22 18 20 19 11 21 22 21 16 21 24 16 22 17 21 17 24 22 24 35    27 24 28 24 32 37 34 25 24 29 37 37 25 28 21 23 24 22 21 20 25 22 32 19 21 22    24 20 21 20 22 18 27 17 14 20 22 22 22 14 19 20 20 21 23 22 14 20 21 23 20 18    23 20 25 31 24 18 22 14 23 22 21 23 27 27 20 21 18 22 23 24 23 21 18 22 17 22    21 35 15 24 24 12 27 30 27 28 22 31 24 24 19 27 24 28 23 25 26 35 27 22 29 21    24 18 19 26 33 29 31 23 25 19 24 26 21 10 23 24 26 28 20 27 26 17 29 22 18 14    22 8 10 11 4 4 1 2 0   0.200000 4.600 4.600 10.80      4068161           5           0  0 0 0 0 0 0 0 0 0 1 1 0 1 5 5 2 9 3 11 6 9 8 7 7 8 3 3 13 10 8 7 5 8 13 8 7 14   12 10 7 15 13 13 11 12 12 14 12 13 12 10 15 11 14 7 16 15 8 15 13 15 13 18 13    17 21 15 12 13 13 17 18 18 18 16 19 20 17 14 17 24 13 12 18 19 19 13 21 18 26    21 23 16 14 18 19 13 33 13 19 20 14 20 23 14 26 19 22 21 21 16 27 30 25 28 22    32 21 30 27 31 21 30 22 27 27 31 27 21 17 38 41 17 21 20 19 30 24 27 20 20 21    30 20 19 19 31 25 24 13 21 23 19 24 33 24 17 20 17 12 25 23 18 24 11 24 25 22    33 20 11 22 31 21 20 26 27 21 26 24 14 23 23 20 20 26 28 10 20 27 24 22 17 27    28 20 23 23 33 20 24 26 32 33 29 21 25 24 17 18 19 27 26 20 24 26 24 24 26 21    19 24 21 36 32 18 33 33 20 23 25 33 19 27 25 27 24 27 21 21 23 28 18 27 25 19    24 15 17 12 15 7 2 1 0 0 \", \"%f \", Inf);\n%! assert (rows (x) == n);\n\n## Test input validation\n%!error <Invalid call to sscanf> sscanf ()\n%!error <STRING must be a string> sscanf (1, \"2\")\n%!error <TEMPLATE must be a string> sscanf (\"1\", 2)\n%!error <Invalid call to sscanf> sscanf (\"foo\", \"bar\", 1, 2)\n\n%% Note use fprintf so output not sent to stdout\n%!test\n%! nm = tempname ();\n%! fid1 = fopen (nm, \"w\");\n%! x = fprintf (fid1, \"%s: %d\\n\", \"test\", 1);\n%! fclose (fid1);\n%! fid2 = fopen (nm, \"r\");\n%! str = fscanf (fid2, \"%s\");\n%! fclose (fid2);\n%! unlink (nm);\n%! assert (x, 8);\n%! assert (str, \"test:1\");\n\n%!error printf (1)\n%!error <Invalid call to printf> printf ()\n\n%!test\n%! [s, msg, status] = sprintf (\"%s: %d\\n\", \"test\", 1);\n%! assert (s == \"test: 1\\n\" && ischar (msg) && status == 8);\n\n%!assert (sprintf (\"%-+6.2f\", Inf), \"+Inf  \")\n%!assert (sprintf (\"%-6.2f\", Inf), \"Inf   \")\n%!assert (sprintf (\"%-+6.2f\", nan), \"+NaN  \")  # lowercase nan is part of test\n%!assert (sprintf (\"%-6.2f\", nan), \"NaN   \")\n%!assert (sprintf (\"%-+6.2f\", NA), \"+NA   \")\n%!assert (sprintf (\"%-6.2f\", NA), \"NA    \")\n\n%!error <Invalid call to sprintf> sprintf ()\n%!error <format TEMPLATE must be a string> sprintf (1)\n\n%!test\n%! arch_list = {\"native\"; \"ieee-le\"; \"ieee-be\"};\n%! warning (\"off\", \"Octave:fopen-mode\");\n%! status = 1;\n%!\n%! for i = 1:3\n%!   arch = arch_list{i};\n%!   for j = 1:4\n%!     if (j == 1)\n%!       mode_list = {\"w\"; \"r\"; \"a\"};\n%!     elseif (j == 2)\n%!       mode_list = {\"w+\"; \"r+\"; \"a+\"};\n%!     elseif (j == 3)\n%!       mode_list = {\"W\"; \"R\"; \"A\"};\n%!     elseif (j == 4)\n%!       mode_list = {\"W+\"; \"R+\"; \"A+\"};\n%!     endif\n%!     nm = tempname ();\n%!     for k = 1:3\n%!       mode = mode_list{k};\n%!       [id, err] = fopen (nm, mode, arch);\n%!       if (id < 0)\n%!         __printf_assert__ (\"open failed: %s (%s, %s): %s\\n\", nm, mode, arch, err);\n%!         status = 0;\n%!         break;\n%!       else\n%!         fclose (id);\n%!       endif\n%!       tmp_mode = [mode, \"b\"];\n%!       [id, err] = fopen (nm, tmp_mode, arch);\n%!       if (id < 0)\n%!         __printf_assert__ (\"open failed: %s (%s, %s): %s\\n\", nm, tmp_mode, arch, err);\n%!         status = 0;\n%!         break;\n%!       else\n%!         fclose (id);\n%!       endif\n%!       tmp_mode = [mode, \"t\"];\n%!       [id, err] = fopen (nm, tmp_mode, arch);\n%!       if (id < 0)\n%!         __printf_assert__ (\"open failed: %s (%s, %s): %s\\n\", nm, tmp_mode, arch, err);\n%!         status = 0;\n%!         break;\n%!       else\n%!         fclose (id);\n%!       endif\n%!     endfor\n%!     unlink (nm);\n%!     if (status == 0)\n%!       break;\n%!     endif\n%!   endfor\n%!   if (status == 0)\n%!     break;\n%!   endif\n%! endfor\n%!\n%! assert (status == 1);\n\n%!test\n%! s.a = 1;\n%! fail (\"fopen (s)\");\n\n%!error fopen (\"foo\", \"x\")\n\n%! fopen (\"foo\", \"wb\", \"noodle\");\n%! assert (__prog_output_assert__ (\"error:\"));\n\n%!error <Invalid call to fopen> fopen ()\n%!error <Invalid call to fopen> fopen (\"foo\", \"wb\", \"native\", \"utf-8\", 1)\n\n%!error fclose (0)\n%!error <Invalid call to fclose> fclose (1, 2)\n\n%!assert (ischar (tempname ()))\n\n%!error <DIR must be a string> tempname (1)\n%!error <PREFIX must be a string> tempname (\"foo\", 1)\n\n%!error <Invalid call to tempname> tempname (1, 2, 3)\n\n%!test\n%! type_list = {\"char\"; \"char*1\"; \"integer*1\"; \"int8\";\n%! \"schar\"; \"signed char\"; \"uchar\"; \"unsigned char\";\n%! \"short\"; \"ushort\"; \"unsigned short\"; \"int\";\n%! \"uint\"; \"unsigned int\"; \"long\"; \"ulong\"; \"unsigned long\";\n%! \"float\"; \"float32\"; \"real*4\"; \"double\"; \"float64\";\n%! \"real*8\"; \"int16\"; \"integer*2\"; \"int32\"; \"integer*4\"};\n%!\n%! n = rows (type_list);\n%! nm = tempname ();\n%! id = fopen (nm, \"wb\");\n%! if (id > 0)\n%!   for i = 1:n\n%!     fwrite (id, i, type_list{i});\n%!   endfor\n%!\n%!   fclose (id);\n%!\n%!   id = fopen (nm, \"rb\");\n%!   if (id > 0)\n%!     x = zeros (1, n);\n%!     for i = 1:n\n%!       x(i) = fread (id, [1, 1], type_list{i});\n%!     endfor\n%!\n%!     fclose (id);\n%!\n%!     if (x == 1:n)\n%!       __printf_assert__ (\"ok\\n\");\n%!     endif\n%!   endif\n%! endif\n%!\n%! unlink (nm);\n%! assert (__prog_output_assert__ (\"ok\"));\n\n%!test\n%! classes = {\"int8\", \"int16\", \"int32\", \"int64\", ...\n%!            \"uint8\", \"uint16\", \"uint32\", \"uint64\", ...\n%!            \"single\", \"double\"};\n%! n = numel (classes);\n%! nm = tempname ();\n%! mode = \"wb+\";\n%! [id, err] = fopen (nm, mode);\n%! if (id < 0)\n%!   __printf_assert__ (\"open failed: %s (%s): %s\\n\", nm, mode, err);\n%! else\n%!   unwind_protect\n%!     for i = 1:n\n%!       cls = classes{i};\n%!       s_in = ones (1, 1, cls);\n%!       m_in = ones (2, 2, cls);\n%!       m_shape = size (m_in);\n%!       frewind (id);\n%!       fwrite (id, s_in, cls);\n%!       fwrite (id, m_in, cls);\n%!       frewind (id);\n%!       s_out = fread (id, numel (s_in), sprintf (\"%s=>%s\", cls, cls));\n%!       m_out = fread (id, numel (m_in), sprintf (\"%s=>%s\", cls, cls));\n%!       m_out = reshape (m_out, m_shape);\n%!       assert (s_in, s_out);\n%!       assert (m_in, m_out);\n%!     endfor\n%!   unwind_protect_cleanup\n%!     fclose (id);\n%!   end_unwind_protect\n%!   unlink (nm);\n%! endif\n\n%!test <54386>\n%! x = char (128:255)';\n%! nm = tempname ();\n%! mode = \"wb\";\n%! [id, err] = fopen (nm, mode);\n%! if (id < 0)\n%!   __printf_assert__ (\"open failed: %s (%s): %s\\n\", nm, mode, err);\n%! else\n%!   fwrite (id, x);\n%!   fclose (id);\n%!   mode = \"rb\";\n%!   [id, err] = fopen (nm, mode);\n%!   if (id < 0)\n%!     __printf_assert__ (\"open failed: %s (%s): %s\\n\", nm, mode, err);\n%!   else\n%!     y = fread (id, Inf, \"uchar=>char\");\n%!     fclose (id);\n%!     assert (y, x);\n%!     unlink (nm);\n%!   endif\n%! endif\n\n%!test\n%! nm = tempname ();\n%! id = fopen (nm, \"wb\");\n%! if (id > 0)\n%!   fprintf (id, \"%d\\n\", 1:100);\n%!   fclose (id);\n%!   mode = \"rb\";\n%!   id = fopen (nm, mode);\n%!   if (id < 0)\n%!     __printf_assert__ (\"open failed: %s (%s): %s\\n\", nm, mode, err);\n%!   else\n%!     for i = 1:101\n%!       fgets (id);\n%!     endfor\n%!     if (feof (id))\n%!       fclose (id);\n%!       mode = \"rb\";\n%!       [id, err] = fopen (nm, mode);\n%!       if (id < 0)\n%!         __printf_assert__ (\"open failed: %s (%s): %s\\n\", nm, mode, err);\n%!       else\n%!         unwind_protect\n%!           pos_one = ftell (id);\n%!           s_one = fgets (id);\n%!           for i = 1:48\n%!             s = fgets (id);\n%!           endfor\n%!           pos_fifty = ftell (id);\n%!           s_fifty = fgets (id);\n%!           fseek (id, pos_one, SEEK_SET);\n%!           s_one_x = fgets (id);\n%!           fseek (id, pos_fifty, SEEK_SET);\n%!           s_fifty_x = fgets (id);\n%!           if (s_one == s_one_x && s_fifty == s_fifty_x)\n%!             frewind (id);\n%!             s_one_x = fgets (id);\n%!             if (s_one != s_one_x)\n%!               error (\"bombed!!\");\n%!             endif\n%!           endif\n%!         unwind_protect_cleanup\n%!           fclose (id);\n%!         end_unwind_protect\n%!       endif\n%!     else\n%!       fclose (id);\n%!       __printf_assert__ (\"EOF not reached when expected to: %s (%s)\\n\", nm, mode);\n%!     endif\n%!   endif\n%!   unlink (nm);\n%! endif\n\n# write to and read from file with encoding\n# FIXME: should be conditional on OCTAVE_HAVE_STRICT_ENCODING_FACET\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\")\n%! temp_file = [tempname(), \".txt\"];\n%! fid = fopen (temp_file, \"wt\", \"n\", \"iso-8859-1\");\n%! unwind_protect\n%!   [name, mode, arch, codepage] = fopen (fid);\n%!   assert (name, temp_file);\n%!   assert (mode, \"w\");\n%!   assert (codepage, \"iso-8859-1\");\n%!   fprintf (fid, \"aäu %s\", \"AÄU\");\n%!   fclose (fid);\n%!   # open in binary mode\n%!   fid2 = fopen (temp_file, \"rb\");\n%!   [name, mode, arch, codepage] = fopen (fid2);\n%!   assert (name, temp_file);\n%!   assert (mode, \"rb\");\n%!   assert (codepage, \"utf-8\");\n%!   read_binary = fread (fid2);\n%!   fclose (fid2);\n%!   assert (read_binary, [97 228 117 32 65 196 85].');\n%!   # open in text mode with correct encoding\n%!   fid3 = fopen (temp_file, \"rt\", \"n\", \"iso-8859-1\");\n%!   read_text = fscanf (fid3, \"%s\");\n%!   fclose (fid3);\n%!   assert (read_text, \"aäuAÄU\");\n%! unwind_protect_cleanup\n%!   unlink (temp_file);\n%! end_unwind_protect\n\n%!assert (fputs (1, 1),-1)\n\n%!error <Invalid call to fputs> fputs ()\n%!error <Invalid call to fputs> fputs (1, \"foo\", 1)\n\n%!error fgetl (\"foo\", 1)\n\n%!error <Invalid call to fgetl> fgetl ()\n%!error <Invalid call to fgetl> fgetl (1, 2, 3)\n\n%!error fgets (\"foo\", 1)\n\n%!error <Invalid call to fgets> fgets ()\n%!error <Invalid call to fgets> fgets (1, 2, 3)\n\n%!test\n%! s.a = 1;\n%! fail (\"fprintf (s)\", \"Invalid call to fprintf\");\n\n%!error <Invalid call to fprintf> fprintf ()\n%!error <Invalid call to fprintf> fprintf (1)\n%!error fprintf (1, 1)\n%!error fprintf (-1, \"foo\")\n\n%!error fscanf (\"foo\", \"bar\")\n\n%!error <Invalid call to fscanf> fscanf ()\n%!error <Invalid call to fscanf> fscanf (1)\n\n%!error <Invalid call to fread> fread ()\n%!error <Invalid call to fread> fread (1, 2, \"char\", 1, \"native\", 2)\n%!error fread (\"foo\")\n\n%!error <Invalid call to fwrite> fwrite ()\n%!error <Invalid call to fwrite> fwrite (1, rand (10), \"char\", 1, \"native\", 2)\n%!error fwrite (\"foo\", 1)\n\n%!error <Invalid call to feof> feof ()\n%!error <Invalid call to feof> feof (1, 2)\n%!error feof (\"foo\")\n\n%!error <Invalid call to ferror> ferror ()\n%!error <Invalid call to ferror> ferror (1, 'clear', 2)\n%!error ferror (\"foo\")\n\n%!error <Invalid call to ftell> ftell ()\n%!error <Invalid call to ftell> ftell (1, 2)\n%!error ftell (\"foo\")\n\n%!error <Invalid call to fseek> fseek ()\n%!error <Invalid call to fseek> fseek (1, 0, SEEK_SET, 1)\n%!error fseek (\"foo\", 0, SEEK_SET)\n\n%!error <Invalid call to frewind> frewind ()\n%!error <Invalid call to frewind> frewind (1, 2)\n%!error frewind (\"foo\")\n\n%!test\n%! [id, msg] = tmpfile ();\n%! if (id < 0)\n%!   __printf_assert__ (\"tmpfile failed: %s\\n\", msg);\n%! else\n%!   unwind_protect\n%!     ## FIXME: better test for endianness?\n%!     big_endian = (bitunpack (uint16 (1))(1) == 0);\n%!     fwrite (id, \"abcdefg\");\n%!     frewind (id);\n%!     [data, count] = fread (id);\n%!     assert (data, [97; 98; 99; 100; 101; 102; 103]);\n%!     assert (count, 7);\n%!     frewind (id);\n%!     [data, count] = fread (id, 'int16');\n%!     expected = [25185; 25699; 26213];\n%!     if (big_endian)\n%!       expected = double (swapbytes (int16 (expected)));\n%!     endif\n%!     assert (data, expected);\n%!     assert (count, 3);\n%!     frewind (id);\n%!     [data, count] = fread (id, [10, 2], 'int16');\n%!     assert (data, expected);\n%!     assert (count, 3);\n%!     frewind (id);\n%!     [data, count] = fread (id, [2, 10], 'int16');\n%!     expected = [25185, 26213; 25699, 0];\n%!     if (big_endian)\n%!       expected = double (swapbytes (int16 (expected)));\n%!     endif\n%!     assert (data, expected);\n%!     assert (count, 3);\n%!   unwind_protect_cleanup\n%!     fclose (id);\n%!   end_unwind_protect\n%! endif\n\n%!test\n%! [id, msg] = tmpfile ();\n%! if (id < 0)\n%!   __printf_assert__ (\"tmpfile failed: %s\\n\", msg);\n%! else\n%!   unwind_protect\n%!     fwrite (id, char (0:15));\n%!     frewind (id);\n%!     [data, count] = fread (id, inf, \"2*uint8\", 2);\n%!     assert (data, [0; 1; 4; 5; 8; 9; 12; 13]);\n%!     assert (count, 8);\n%!   unwind_protect_cleanup\n%!     fclose (id);\n%!   end_unwind_protect\n%! endif\n\n%!test\n%! [id, msg] = tmpfile ();\n%! if (id < 0)\n%!   __printf_assert__ (\"tmpfile failed: %s\\n\", msg);\n%! else\n%!   unwind_protect\n%!     fwrite (id, char (0:15));\n%!     frewind (id);\n%!     [data, count] = fread (id, 3, \"2*uint8\", 3);\n%!     assert (data, [0; 1; 5]);\n%!     assert (count, 3);\n%!     [data, count] = fread (id, 3, \"2*uint8\", 3);\n%!     assert (data, [6; 7; 11]);\n%!     assert (count, 3);\n%!     [data, count] = fread (id, 3, \"2*uint8\", 3);\n%!     assert (data, [12; 13]);\n%!     assert (count, 2);\n%!     [data, count] = fread (id, 3, \"2*uint8\", 3);\n%!     assert (data, []);\n%!     assert (count, 0);\n%!   unwind_protect_cleanup\n%!     fclose (id);\n%!   end_unwind_protect\n%! endif\n\n%!test\n%! [id, msg] = tmpfile ();\n%! if (id < 0)\n%!   __printf_assert__ (\"tmpfile failed: %s\\n\", msg);\n%! else\n%!   unwind_protect\n%!     ## FIXME: better test for endianness?\n%!     big_endian = (bitunpack (uint16 (1))(1) == 0);\n%!     fwrite (id, char (0:15));\n%!     frewind (id);\n%!     [data, count] = fread (id, [1, Inf], \"4*uint16\", 3);\n%!     expected = [256, 770, 1284, 1798, 3083, 3597];\n%!     if (big_endian)\n%!       expected = double (swapbytes (uint16 (expected)));\n%!     endif\n%!     assert (data, expected);\n%!     assert (count, 6);\n%!   unwind_protect_cleanup\n%!     fclose (id);\n%!   end_unwind_protect\n%! endif\n\n%!test\n%! [id, msg] = tmpfile ();\n%! if (id < 0)\n%!   __printf_assert__ (\"tmpfile failed: %s\\n\", msg);\n%! else\n%!   unwind_protect\n%!     ## FIXME: better test for endianness?\n%!     big_endian = (bitunpack (uint16 (1))(1) == 0);\n%!     fwrite (id, char (0:15));\n%!     frewind (id);\n%!     [data, count] = fread (id, [3, Inf], \"4*uint16\", 3);\n%!     expected = [256, 1798; 770, 3083; 1284, 3597];\n%!     if (big_endian)\n%!       expected = double (swapbytes (uint16 (expected)));\n%!     endif\n%!     assert (data, expected);\n%!     assert (count, 6);\n%!   unwind_protect_cleanup\n%!     fclose (id);\n%!   end_unwind_protect\n%! endif\n\n%!test\n%! [id, msg] = tmpfile ();\n%! if (id < 0)\n%!   __printf_assert__ (\"tmpfile failed: %s\\n\", msg);\n%! else\n%!   unwind_protect\n%!     fwrite (id, \"abcd\");\n%!     frewind (id);\n%!     [data, count] = fread (id, [2, 3], \"char\");\n%!     assert (data, [97, 99; 98, 100]);\n%!     assert (count, 4);\n%!   unwind_protect_cleanup\n%!     fclose (id);\n%!   end_unwind_protect\n%! endif\n\n%!assert (sprintf (\"%1s\", \"foo\"), \"foo\")\n%!assert (sprintf (\"%.s\", \"foo\"), char (zeros (1, 0)))\n%!assert (sprintf (\"%1.s\", \"foo\"), \" \")\n%!assert (sprintf (\"%.1s\", \"foo\"), \"f\")\n%!assert (sprintf (\"%1.1s\", \"foo\"), \"f\")\n%!assert (sprintf (\"|%4s|\", \"foo\"), \"| foo|\")\n%!assert (sprintf (\"|%-4s|\", \"foo\"), \"|foo |\")\n%!assert (sprintf (\"|%4.1s|\", \"foo\"), \"|   f|\")\n%!assert (sprintf (\"|%-4.1s|\", \"foo\"), \"|f   |\")\n\n%!assert (sprintf (\"%c \", \"foo\"), \"f o o \")\n%!assert (sprintf (\"%s \", \"foo\"), \"foo \")\n\n%!assert (sprintf (\"|%d|\", \"foo\"), \"|102||111||111|\")\n%!assert (sprintf (\"|%s|\", [102, 111, 111]), \"|foo|\")\n\n%!assert (sprintf (\"%s %d \", [102, 1e5, 111, 1e5, 111]), \"f 100000 o 100000 o \")\n\n%!assert (sprintf (\"%c,%c,%c,%c\", \"abcd\"), \"a,b,c,d\")\n%!assert (sprintf (\"%s,%s,%s,%s\", \"abcd\"), \"abcd,\")\n\n%!assert (sprintf (\"|%x|\", \"Octave\"), \"|4f||63||74||61||76||65|\")\n%!assert (sprintf (\"|%X|\", \"Octave\"), \"|4F||63||74||61||76||65|\")\n%!assert (sprintf (\"|%o|\", \"Octave\"), \"|117||143||164||141||166||145|\")\n\n## bug #47192\n%!assert (sprintf (\"%s\", repmat (\"blah\", 2, 1)), \"bbllaahh\")\n%!assert (sprintf (\"%c\", repmat (\"blah\", 2, 1)), \"bbllaahh\")\n%!assert (sprintf (\"%c %c %s\", repmat (\"blah\", 2, 1)), \"b b llaahh\")\n\n## bug #39735\n%!assert (sprintf (\"a %d b\", []), \"a  b\")\n%!assert (sprintf (\"a %d b\", ''), \"a  b\")\n%!assert (sprintf (\"a %d b\", ' '), \"a 32 b\")\n%!assert (sprintf (\"a %s b\", []), \"a  b\")\n%!assert (sprintf (\"a %s b\", ''), \"a  b\")\n%!assert (sprintf (\"a %s b\", ' '), \"a   b\")\n\n%!assert <*53148> (double (sprintf (\"B\\0B\")), [66, 0, 66])\n%!assert <*53148> (sscanf (\"B\\0B 13\", \"B\\0B %d\"), 13)\n\n%!test <*58055>\n%!  w_modes = {\"wb\", \"wt\"};\n%!  r_modes = {\"rb\", \"rt\"};\n%!  f_texts = {\"foo\\nbar\\nbaz\\n\", \"foo\\rbar\\rbaz\\r\", \"foo\\r\\nbar\\r\\nbaz\\r\\n\"};\n%!  for i = 1:numel (w_modes)\n%!    w_mode = w_modes{i};\n%!    for j = 1:numel (r_modes)\n%!      r_mode = r_modes{j};\n%!      for k = 1:numel (f_texts)\n%!        f_text = f_texts{k};\n%!        fname = tempname ();\n%!        fid = fopen (fname, w_mode);\n%!        unwind_protect\n%!          fprintf (fid, \"%s\", f_text);\n%!          fclose (fid);\n%!          fid = fopen (fname, r_mode);\n%!          fgetl (fid);\n%!          pos = ftell (fid);\n%!          buf1 = fgetl (fid);\n%!          fgetl (fid);\n%!          fseek (fid, pos, SEEK_SET);\n%!          buf2 = fgetl (fid);\n%!          assert (buf1, buf2);\n%!        unwind_protect_cleanup\n%!          fclose (fid);\n%!          unlink (fname);\n%!        end_unwind_protect\n%!      endfor\n%!    endfor\n%!  endfor\n\n# stream with transcoding\n# FIXME: should be conditional on OCTAVE_HAVE_STRICT_ENCODING_FACET\n%!testif ; ! __have_feature__ (\"LLVM_LIBCXX\") <*63930>\n%! w_modes = {\"wb\", \"wt\"};\n%! # 64 non-ASCII characters that can be represented in 'windows-1252'\n%! f_texts{1} = repmat ('ÀÂÈÊÌàäéèêìîöòùû', 1, 4);\n%! # prepend space to misalign surrogate border from a multiple of 2.\n%! f_texts{2} = [' ', f_texts{1}];\n%! # byte values of character sequence in 'windows-1252'\n%! native_bytes{1} = repmat (...\n%!   [192 194 200 202 204 224 228 233 232 234 236 238 246 242 249 251], ...\n%!   1, 4).';\n%! native_bytes{2} = [double(' '); native_bytes{1}];\n%! for i_mode = 1:numel (w_modes)\n%!   for i_text = 1:numel (f_texts)\n%!     fname = tempname ();\n%!     fid = fopen (fname, w_modes{i_mode}, 'n', 'windows-1252');\n%!     unwind_protect\n%!       fprintf (fid, f_texts{i_text});\n%!       fclose (fid);\n%!       # open without encoding facet and read bytes\n%!       fid = fopen (fname, 'rb');\n%!       buf = fread (fid);\n%!       assert (buf, native_bytes{i_text});\n%!     unwind_protect_cleanup\n%!       fclose (fid);\n%!       unlink (fname);\n%!     end_unwind_protect\n%!   endfor\n%! endfor\n"
  },
  {
    "path": "test/json/jsondecode.tst",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%% Unit tests for jsondecode()\n%%\n%% Code in libinterp/corefcn/jsondecode.cc\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%% Note: This script is intended to also run under Matlab to verify\n%%       compatibility.  Preserve Matlab-formatting when making changes.\n\n%%% Test 1: decode null values\n\n%% null, in non-numeric arrays -> Empty double []\n%!testif HAVE_RAPIDJSON\n%! json = '[\"str\", 5, null, true]';\n%! exp  = {'str'; 5; []; true};\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% null, in numeric arrays to NaN (extracted from JSONio)\n%!testif HAVE_RAPIDJSON\n%! json = '[1, 2, null, 3]';\n%! exp  = [1; 2; NaN; 3];\n%! obs  = jsondecode (json);\n%! assert (isequaln (obs, exp));\n\n%% corner case: array of null values\n%!testif HAVE_RAPIDJSON\n%! json = '[null, null, null]';\n%! exp  = [NaN; NaN; NaN];\n%! obs  = jsondecode (json);\n%! assert (isequaln (obs, exp));\n\n%%% Test 2: Decode scalar Boolean, Number, and String values\n\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsondecode ('true'), logical (1)));\n%! assert (isa (jsondecode ('true'), 'logical'));\n%! assert (isequal (jsondecode ('false'), logical (0)));\n%! assert (isa (jsondecode ('false'), 'logical'));\n%! assert (isequal (jsondecode ('123.45'), 123.45));\n%! assert (isequal (jsondecode ('\"hello there\"'), 'hello there'));\n\n%%% Test 3: Decode Array of Booleans, Numbers, and Strings values\n\n%% vectors are always rendered as column vectors\n%!testif HAVE_RAPIDJSON\n%! json = '[true, true, false, true]';\n%! exp  = logical ([1; 1; 0; 1]);\n%! obs  = jsondecode (json);\n%! assert (isa (obs, 'logical'));\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON <*59135>\n%! json = '[[true, true], [false, true]]';\n%! exp  = logical ([1, 1; 0, 1]);\n%! obs  = jsondecode (json);\n%! assert (isa (obs, 'logical'));\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! json = '[\"true\", \"true\", \"false\", \"true\"]';\n%! exp  = {'true'; 'true'; 'false'; 'true'};\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! json = '[\"foo\", \"bar\", [\"foo\", \"bar\"]]';\n%! exp  = {'foo'; 'bar'; {'foo'; 'bar'}};\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% vectors are always rendered as column vectors\n%!testif HAVE_RAPIDJSON\n%! json = '[15000, 5, 12.25, 1502302.3012]';\n%! exp  = [15000; 5; 12.25; 1502302.3012];\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% row vectors are preserved by adding one level of hierarchy\n%% extracted from JSONio\n%!testif HAVE_RAPIDJSON\n%! json = '[[1,2]]';\n%! exp  = [1, 2];\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% If same dimensions -> transform to an array (extracted from JSONio)\n%!testif HAVE_RAPIDJSON\n%! json = '[[1, 2], [3, 4]]';\n%! exp  = [1, 2; 3, 4];\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% extracted from JSONio\n%!testif HAVE_RAPIDJSON\n%! json = '[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]';\n%! exp  = cat (3, [1, 3; 5, 7], [2, 4; 6, 8]);\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% try different dimensions for the array\n%!testif HAVE_RAPIDJSON\n%! json = '[[[1, 2, -1], [3, 4, null]], [[5, 6, Inf], [7, 8, -Inf]]]';\n%! exp  = cat (3, [1, 3; 5, 7], [2, 4; 6, 8], [-1, NaN; Inf, -Inf]);\n%! obs  = jsondecode (json);\n%! assert (isequaln (obs, exp));\n\n%% try different dimensions for the array\n%!testif HAVE_RAPIDJSON\n%! json = '[[[1, 2], [3, 4]], [[5, 6], [7, 8]], [[9, 10], [11, 12]]]';\n%! exp  = cat (3, [1, 3; 5, 7; 9, 11], [2, 4; 6, 8; 10, 12]);\n%! obs  = jsondecode (json);\n%! assert (isequaln (obs, exp));\n\n%% try higher dimensions for the array\n%!testif HAVE_RAPIDJSON\n%! json = ['[[[[1,-1], [2,-2]],[[3,-3],[4,-4]]],[[[5,-5],[6,-6]],[[7,-7],', ...\n%!         '[8,-8]]],[[[9,-9], [10,-10]],[[11,-11],[12,-12]]],', ...\n%!         '[[[13,-13],[14,-14]],[[15,-15],[16,-16]]]]'];\n%! var1 = cat (3, [1, 3; 5, 7; 9, 11; 13, 15], [2, 4; 6, 8; 10, 12; 14, 16]);\n%! var2 = cat (3, [-1, -3; -5, -7; -9, -11; -13, -15], ...\n%!             [-2, -4; -6, -8; -10, -12; -14, -16]);\n%! exp  = cat (4, var1, var2);\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! json = '[[true, false], [true, false], [true, false]]';\n%! exp  = logical ([1 0; 1 0; 1 0]);\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% If different dimensions -> transform to a cell array (extracted from JSONio)\n%!testif HAVE_RAPIDJSON\n%! json = '[[1, 2], [3, 4, 5]]';\n%! exp  = {[1; 2]; [3; 4; 5]};\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% extracted from JSONio\n%%!testif HAVE_RAPIDJSON\n%! json = '[1, 2, [3, 4]]';\n%! exp  = {1; 2; [3; 4]};\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! json = '[true, false, [true, false, false]]';\n%! exp  = {true; false; logical([1; 0; 0])};\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n%! assert (isa (obs{1}, 'logical'));\n%! assert (isa (obs{2}, 'logical'));\n%! assert (isa (obs{3}, 'logical'));\n\n%%% Test 4: decode JSON Objects\n\n%% Check decoding of Boolean, Number, and String values inside an Object\n%!testif HAVE_RAPIDJSON\n%! json = '{\"number\": 3.14, \"string\": \"foobar\", \"boolean\": false}';\n%! exp  = struct ('number', 3.14, 'string', 'foobar', 'boolean', false);\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n%! assert (isa (obs.boolean, 'logical'));\n\n%% Check decoding of null values and arrays inside an object & makeValidName\n%!testif HAVE_RAPIDJSON\n%! json = [ '{\"nonnumeric array\": [\"str\", 5, null],' ...\n%!          '\"numeric array\": [1, 2, null]}' ];\n%! exp  = struct ('nonnumericArray', {{'str'; 5; []}}, ...\n%!                'numericArray', {[1; 2; NaN]});\n%! obs  = jsondecode (json);\n%! assert (isequaln (obs, exp));\n\n%% Check decoding of objects inside an object & makeValidName (from JSONio)\n%!testif HAVE_RAPIDJSON\n%! json = '{\"object\": {\"  field 1   \": 1, \"field-   2\": 2, \"3field\": 3, \"\": 1}}';\n%! exp  = struct ('object', ...\n%!                struct ('field1', 1, 'field_2', 2, 'x3field', 3, 'x', 1));\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% Check decoding of empty objects, empty arrays, and Inf inside an object\n%!testif HAVE_RAPIDJSON\n%! json = '{\"a\": Inf, \"b\": [], \"c\": {}}';\n%! exp  = struct ('a', Inf, 'b', [], 'c', struct ());\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% Check decoding of string arrays inside an object & makeValidName\n%% extracted from JSONio\n%!testif HAVE_RAPIDJSON\n%! json = '{\"%string.array\": [\"Statistical\",\"Parametric\",\"Mapping\"]}';\n%! exp  = struct ('x_string_array', ...\n%!                {{'Statistical'; 'Parametric'; 'Mapping'}});\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% extracted from jsonlab\n%!testif HAVE_RAPIDJSON\n%! json = ['{' , ...\n%!     '\"glossary\": { ', ...\n%!         '\"title\": \"example glossary\",', ...\n%!     '\"GlossDiv\": {', ...\n%!             '\"title\": \"S\",', ...\n%!     '\"GlossList\": {', ...\n%!                 '\"GlossEntry\": {', ...\n%!                     '\"ID\": \"SGML\",', ...\n%!                     '\"SortAs\": \"SGML\",', ...\n%!                     '\"GlossTerm\": \"Standard Generalized Markup Language\",', ...\n%!                     '\"Acronym\": \"SGML\",', ...\n%!                     '\"Abbrev\": \"ISO 8879:1986\",', ...\n%!                     '\"GlossDef\": {', ...\n%!                         '\"para\": \"A meta-markup language, ', ...\n%!                         'used to create markup languages such as DocBook.\",', ...\n%!                         '\"GlossSeeAlso\": [\"GML\", \"XML\"]', ...\n%!                     '},', ...\n%!                     '\"GlossSee\": \"markup\"', ...\n%!                 '}', ...\n%!             '}', ...\n%!         '}', ...\n%!     '}', ...\n%! '}'];\n%! var1 = struct ('para', ['A meta-markup language, used to create ' ...\n%!                         'markup languages such as DocBook.'], ...\n%!                'GlossSeeAlso', {{'GML'; 'XML'}});\n%! var2 = struct ('ID', 'SGML', 'SortAs', 'SGML', ...\n%!                'GlossTerm', 'Standard Generalized Markup Language', ...\n%!                'Acronym', 'SGML', 'Abbrev', 'ISO 8879:1986', ...\n%!                'GlossDef', var1, 'GlossSee', 'markup');\n%! exp  = struct ('glossary', ...\n%!                struct ('title', 'example glossary', ...\n%!                        'GlossDiv', struct ('title', 'S', ...\n%!                                            'GlossList', ...\n%!                                            struct ('GlossEntry', var2))));\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%%% Test 5: decode Array of JSON objects\n\n%% Arrays with the same field names in the same order (extracted from JSONio)\n%!testif HAVE_RAPIDJSON\n%! json = '{\"structarray\": [{\"a\":1,\"b\":2},{\"a\":3,\"b\":4}]}';\n%! exp  = struct ('structarray', struct ('a', {1; 3}, 'b', {2; 4}));\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% Different field names before calling makeValidName, BUT the same after\n%% calling it, resulting in structarray.\n%! json = [ '[', ...\n%!       '{', ...\n%!         '\"i*d\": 0,', ...\n%!         '\"12name\": \"Osborn\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"i/d\": 1,', ...\n%!         '\"12name\": \"Mcdowell\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"i+d\": 2,', ...\n%!         '\"12name\": \"Jewel\"', ...\n%!       '}', ...\n%!     ']'];\n%! exp  = struct ('i_d', {0; 1; 2}, ...\n%!                'x12name', {'Osborn'; 'Mcdowell'; 'Jewel'});\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% Arrays with the same field names in the same order.\n%% JSON text is generated from json-generator.com\n%!testif HAVE_RAPIDJSON\n%! json = ['[', ...\n%!   '{', ...\n%!     '\"x_id\": \"5ee28980fc9ab3\",', ...\n%!     '\"index\": 0,', ...\n%!     '\"guid\": \"b229d1de-f94a\",', ...\n%!     '\"latitude\": -17.124067,', ...\n%!     '\"longitude\": -61.161831,', ...\n%!     '\"friends\": [', ...\n%!       '{', ...\n%!         '\"id\": 0,', ...\n%!         '\"name\": \"Collins\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 1,', ...\n%!         '\"name\": \"Hays\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 2,', ...\n%!         '\"name\": \"Griffin\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '},', ...\n%!   '{', ...\n%!     '\"x_id\": \"5ee28980dd7250\",', ...\n%!     '\"index\": 1,', ...\n%!     '\"guid\": \"39cee338-01fb\",', ...\n%!     '\"latitude\": 13.205994,', ...\n%!     '\"longitude\": -37.276231,', ...\n%!     '\"friends\": [', ...\n%!       '{', ...\n%!         '\"id\": 0,', ...\n%!         '\"name\": \"Osborn\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 1,', ...\n%!         '\"name\": \"Mcdowell\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 2,', ...\n%!         '\"name\": \"Jewel\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '},', ...\n%!   '{', ...\n%!     '\"x_id\": \"5ee289802422ac\",', ...\n%!     '\"index\": 2,', ...\n%!     '\"guid\": \"3db8d55a-663e\",', ...\n%!     '\"latitude\": -35.453456,', ...\n%!     '\"longitude\": 14.080287,', ...\n%!     '\"friends\": [', ...\n%!       '{', ...\n%!         '\"id\": 0,', ...\n%!         '\"name\": \"Socorro\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 1,', ...\n%!         '\"name\": \"Darla\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 2,', ...\n%!         '\"name\": \"Leanne\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '}', ...\n%! ']'];\n%! var1 = struct ('id', {0; 1; 2}, 'name', {'Collins'; 'Hays'; 'Griffin'});\n%! var2 = struct ('id', {0; 1; 2}, 'name', {'Osborn'; 'Mcdowell'; 'Jewel'});\n%! var3 = struct ('id', {0; 1; 2}, 'name', {'Socorro'; 'Darla'; 'Leanne'});\n%! exp  = struct (...\n%!   'x_id', {'5ee28980fc9ab3'; '5ee28980dd7250'; '5ee289802422ac'}, ...\n%!   'index', {0; 1; 2}, ...\n%!   'guid', {'b229d1de-f94a'; '39cee338-01fb'; '3db8d55a-663e'}, ...\n%!   'latitude', {-17.124067; 13.205994; -35.453456}, ...\n%!   'longitude', {-61.161831; -37.276231; 14.080287}, ...\n%!   'friends', {var1; var2; var3});\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% Arrays with the same field names in different order (extracted from JSONio)\n%% Results in cell array, rather than struct array\n%!testif HAVE_RAPIDJSON\n%! json = '{\"cellarray\": [{\"a\":1,\"b\":2},{\"b\":3,\"a\":4}]}';\n%! exp  = struct ('cellarray', {{struct('a', 1, 'b', 2); ...\n%!                               struct('b', 3, 'a', 4)}});\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% Arrays with different field names (extracted from JSONio)\n%!testif HAVE_RAPIDJSON\n%! json = '{\"cellarray\": [{\"a\":1,\"b\":2},{\"a\":3,\"c\":4}]}';\n%! exp  = struct ('cellarray', {{struct('a', 1, 'b', 2); ...\n%!                               struct('a', 3, 'c', 4)}});\n%! obs  = jsondecode (json);\n%! assert (isequal (obs, exp));\n\n%% Arrays with different field names and a big test\n%!testif HAVE_RAPIDJSON\n%! json = ['[', ...\n%!   '{', ...\n%!     '\"x_id\": \"5ee28980fc9ab3\",', ...\n%!     '\"index\": 0,', ...\n%!     '\"guid\": \"b229d1de-f94a\",', ...\n%!     '\"latitude\": -17.124067,', ...\n%!     '\"longitude\": -61.161831,', ...\n%!     '\"friends\": [', ...\n%!       '{', ...\n%!         '\"id\": 0,', ...\n%!         '\"name\": \"Collins\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 1,', ...\n%!         '\"name\": \"Hays\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 2,', ...\n%!         '\"name\": \"Griffin\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '},', ...\n%!   '{\"numeric array\": [\"str\", 5, null], \"nonnumeric array\": [1, 2, null]},', ...\n%!   '{', ...\n%!      '\"firstName\": \"John\",', ...\n%!      '\"lastName\": \"Smith\",', ...\n%!      '\"age\": 25,', ...\n%!      '\"address\":', ...\n%!      '{', ...\n%!          '\"streetAddress\": \"21 2nd Street\",', ...\n%!          '\"city\": \"New York\",', ...\n%!          '\"state\": \"NY\"', ...\n%!      '},', ...\n%!      '\"phoneNumber\":', ...\n%!          '{', ...\n%!            '\"type\": \"home\",', ...\n%!            '\"number\": \"212 555-1234\"', ...\n%!          '}', ...\n%!  '}]'];\n%! var1 = struct ('x_id', '5ee28980fc9ab3', 'index', 0, ...\n%!                'guid', 'b229d1de-f94a', 'latitude', -17.124067, ...\n%!                'longitude', -61.161831, ...\n%!                'friends', ...\n%!                struct ('id', {0; 1; 2}, ...\n%!                        'name', {'Collins'; 'Hays'; 'Griffin'}));\n%! var2 = struct ('numericArray', {{'str'; 5; []}}, ...\n%!                'nonnumericArray', {[1; 2; NaN]});\n%! var3 = struct ('firstName', 'John', 'lastName', 'Smith', 'age', 25, ...\n%!                'address', ...\n%!                struct ('streetAddress', '21 2nd Street', ...\n%!                        'city', 'New York', 'state', 'NY'), ...\n%!                'phoneNumber', ...\n%!                struct ('type', 'home', 'number', '212 555-1234'));\n%! exp = {var1; var2; var3};\n%! obs  = jsondecode (json);\n%! assert (isequaln (obs, exp));\n\n%%% Test 6: decode Array of different JSON data types\n\n%!testif HAVE_RAPIDJSON\n%! json = ['[null, true, Inf, 2531.023, \"hello there\", ', ...\n%!   '{', ...\n%!     '\"x_id\": \"5ee28980dd7250\",', ...\n%!     '\"index\": 1,', ...\n%!     '\"guid\": \"39cee338-01fb\",', ...\n%!     '\"latitude\": 13.205994,', ...\n%!     '\"longitude\": -37.276231,', ...\n%!     '\"friends\": [', ...\n%!       '{', ...\n%!         '\"id\": 0,', ...\n%!         '\"name\": \"Osborn\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 1,', ...\n%!         '\"name\": \"Mcdowell\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\": 2,', ...\n%!         '\"name\": \"Jewel\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '}]'];\n%! var =  struct ('x_id', '5ee28980dd7250', 'index', 1, ...\n%!                'guid', '39cee338-01fb', 'latitude', 13.205994, ...\n%!                'longitude', -37.276231, ...\n%!                'friends', struct ('id', {0; 1; 2}, ...\n%!                                   'name', {'Osborn'; 'Mcdowell'; 'Jewel'}));\n%! exp = {[]; 1; Inf; 2531.023; 'hello there'; var};\n%! obs  = jsondecode (json);\n%! assert (isequaln (obs, exp));\n\n%% Array of arrays\n%!testif HAVE_RAPIDJSON\n%! json = ['[[\"str\", Inf, null], [1, 2, null], [\"foo\", \"bar\", [\"foo\", \"bar\"]],', ...\n%!   '[[[1, 2], [3, 4]], [[5, 6], [7, 8]]],' , ...\n%!   '[', ...\n%!     '{', ...\n%!       '\"x_id\": \"5ee28980fc9ab3\",', ...\n%!       '\"index\": 0,', ...\n%!       '\"guid\": \"b229d1de-f94a\",', ...\n%!       '\"latitude\": -17.124067,', ...\n%!       '\"longitude\": -61.161831,', ...\n%!       '\"friends\": [', ...\n%!         '{', ...\n%!           '\"id\": 0,', ...\n%!           '\"name\": \"Collins\"', ...\n%!         '},', ...\n%!         '{', ...\n%!           '\"id\": 1,', ...\n%!           '\"name\": \"Hays\"', ...\n%!         '},', ...\n%!         '{', ...\n%!           '\"id\": 2,', ...\n%!           '\"name\": \"Griffin\"', ...\n%!         '}', ...\n%!       ']', ...\n%!     '},', ...\n%!     '{\"numeric array\": [\"str\", 5, null], \"nonnumeric array\": [1, 2, null]},', ...\n%!     '{', ...\n%!        '\"firstName\": \"John\",', ...\n%!        '\"lastName\": \"Smith\",', ...\n%!        '\"age\": 25,', ...\n%!        '\"address\":', ...\n%!        '{', ...\n%!            '\"streetAddress\": \"21 2nd Street\",', ...\n%!            '\"city\": \"New York\",', ...\n%!            '\"state\": \"NY\"', ...\n%!        '},', ...\n%!        '\"phoneNumber\":', ...\n%!            '{', ...\n%!              '\"type\": \"home\",', ...\n%!              '\"number\": \"212 555-1234\"', ...\n%!            '}', ...\n%!    '}]]'];\n%! var1 = struct ('x_id', '5ee28980fc9ab3', 'index', 0, ...\n%!                'guid', 'b229d1de-f94a', 'latitude', -17.124067, ...\n%!                'longitude', -61.161831, ...\n%!                'friends', struct ('id', {0; 1; 2}, ...\n%!                                   'name', {'Collins'; 'Hays'; 'Griffin'}));\n%! var2 = struct ('numericArray', {{'str'; 5; []}}, ...\n%!                'nonnumericArray', {[1; 2; NaN]});\n%! var3 = struct ('firstName', 'John', 'lastName', 'Smith', 'age', 25, ...\n%!                'address', ...\n%!                struct ('streetAddress', '21 2nd Street', ...\n%!                        'city', 'New York', 'state', 'NY'), ...\n%!                'phoneNumber', ...\n%!                struct ('type', 'home', 'number', '212 555-1234'));\n%! exp = {{'str'; Inf; []}; [1; 2; NaN]; {'foo'; 'bar'; {'foo'; 'bar'}};\n%!        cat(3, [1, 3; 5, 7], [2, 4; 6, 8]); {var1; var2 ;var3}};\n%! obs  = jsondecode (json);\n%! assert (isequaln (obs, exp));\n\n%%% Test 7: Check \"ReplacementStyle\", \"Prefix\", and \"makeValidName\" options\n%%%         Not Matlab compatible!\n\n%!testif HAVE_RAPIDJSON\n%! json = '{\"1a\": {\"1*a\": {\"1+*/-a\": {\"1#a\": {}}}}}';\n%! exp  = struct ('n1a', ...\n%!                struct ('n1a', struct ('n1a', struct ('n1a', struct ()))));\n%! obs  = jsondecode (json, \"ReplacementStyle\", \"delete\", ...\n%!                          \"Prefix\", \"_\", \"Prefix\", \"n\");\n%! assert (isequal (obs, exp));\n\n%% Check forwarding of \"ReplacementStyle\" and \"Prefix\" options inside arrays\n%!testif HAVE_RAPIDJSON\n%! json = [ '[', ...\n%!       '{', ...\n%!         '\"i*d\": 0,', ...\n%!         '\"12name\": \"Osborn\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"i*d\": 1,', ...\n%!         '\"12name\": \"Mcdowell\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"i*d\": 2,', ...\n%!         '\"12name\": \"Jewel\"', ...\n%!       '}', ...\n%!     ']'];\n%! exp  = struct ('i0x2Ad', {0; 1; 2}, ...\n%!                'm_12name', {'Osborn'; 'Mcdowell'; 'Jewel'});\n%! obs  = jsondecode (json, \"ReplacementStyle\", \"hex\", \"Prefix\", \"m_\");\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! json = '{\"cell*array\": [{\"1a\":1,\"b*1\":2},{\"1a\":3,\"b/2\":4}]}';\n%! exp  = struct ('cell_array', {{struct('x_1a', 1, 'b_1', 2); ...\n%!                                struct('x_1a', 3, 'b_2', 4)}});\n%! obs  = jsondecode (json, \"ReplacementStyle\", \"underscore\", \"Prefix\", \"x_\");\n%! assert (isequal (obs, exp));\n\n%%% Test 8: More tests from https://github.com/apjanke/octave-jsonstuff (bug #60688)\n\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsondecode ('42'), 42));\n%! assert (isequal (jsondecode ('\"foobar\"'), \"foobar\"));\n%! assert (isequal (jsondecode ('null'), []));\n%! assert (isequal (jsondecode ('[]'), []));\n%! assert (isequal (jsondecode ('[[]]'), {[]}));\n%! assert (isequal (jsondecode ('[[[]]]'), {{[]}}));\n%! assert (isequal (jsondecode ('[1, 2, 3]'), [1; 2; 3]));\n%! assert (isequaln (jsondecode ('[1, 2, null]'), [1; 2; NaN]));\n%! assert (isequal (jsondecode ('[1, 2, \"foo\"]'), {1; 2; \"foo\"}));\n%! assert (isequal (jsondecode ('{\"foo\": 42, \"bar\": \"hello\"}'), ...\n%!         struct(\"foo\",42, \"bar\",\"hello\")));\n%! assert (isequal (jsondecode ('[{\"foo\": 42, \"bar\": \"hello\"}, {\"foo\": 1.23, \"bar\": \"world\"}]'), ...\n%!         struct(\"foo\", {42; 1.23}, \"bar\", {\"hello\"; \"world\"})));\n%! assert (isequal (jsondecode ('[1, 2]'), [1; 2]));\n%! assert (isequal (jsondecode ('[[1, 2]]'), [1 2]));\n%! assert (isequal (jsondecode ('[[[1, 2]]]'), cat(3, 1, 2)));\n%! assert (isequal (jsondecode ('[[1, 2], [3, 4]]'), [1 2; 3 4]));\n%! assert (isequal (jsondecode ('[[[1, 2], [3, 4]]]'), cat(3, [1 3], [2 4])));\n%! assert (isequal (jsondecode ('[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]'), ...\n%!         cat(3, [1 3; 5 7], [2 4; 6 8])));\n%! assert (isequal (jsondecode ('{}'), struct));\n%! assert (isequal (jsondecode ('[{}]'), struct));\n%! assert (isequal (jsondecode ('[[{}]]'), struct));\n%! assert (isequal (jsondecode ('[{}, {}]'), [struct; struct]));\n%! assert (isequal (jsondecode ('[[{}, {}]]'), [struct struct]));\n%! assert (isequal (jsondecode ('[[[{}, {}]]]'), cat(3, struct, struct)));\n%! assert (isequal (jsonencode (42), \"42\"));\n%! assert (isequal (jsonencode (\"foo\"), '\"foo\"'));\n%! assert (isequal (jsonencode ([1 2 3]), '[1,2,3]'));\n%! assert (isequal (jsonencode (NaN), 'null'));\n%! assert (isequal (jsonencode ([1 2 NaN]), '[1,2,null]'));\n%! assert (isequal (jsonencode ({}), \"[]\"));\n\n%%% Test 9: And even some more tests for bug #60688.\n\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsondecode ('[[{\"foo\": 42}, {\"foo\": 1.23}], [{\"foo\": 12}, {\"foo\": \"bar\"}]]'), ...\n%!         struct(\"foo\", {42 1.23; 12 \"bar\"})));\n%! assert (isequal (jsondecode ('[[{\"foo\": 42}, {\"foo\": 1.23}], [{\"bar\": 12}, {\"foo\": \"bar\"}]]'), ...\n%!         {struct(\"foo\", {42; 1.23}); {struct(\"bar\", 12); struct(\"foo\", \"bar\")}}));\n\n\n%%% Test 10: Decoding of objects inside an object without using makeValidName.\n%%%          Not Matlab compatible!\n\n%!testif HAVE_RAPIDJSON\n%! json = ['{\"object\": {\"  hi 1   \": 1, \"%string.array\": 2,' ...\n%!                     '\"img/svg+xml\": 3, \"\": 1}}'];\n%! exp  = struct ('object', ...\n%!                struct ('  hi 1   ', 1, '%string.array', 2, ...\n%!                        'img/svg+xml', 3, '', 1));\n%! obs  = jsondecode (json, \"makeValidName\", false);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! json = '{\"1a\": {\"1*a\": {\"1+*/-a\": {\"1#a\": {}}}}}';\n%! exp  = struct ('n1a', ...\n%!                struct ('n1a', struct ('n1a', struct ('n1a', struct ()))));\n%! obs  = jsondecode (json, \"ReplacementStyle\", \"delete\", ...\n%!                          \"makeValidName\", false, ...\n%!                          \"Prefix\", \"_\", ...\n%!                          \"makeValidName\", true, ...\n%!                          \"Prefix\", \"n\");\n%! assert (isequal (obs, exp));\n"
  },
  {
    "path": "test/json/jsonencode.tst",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%% Unit tests for jsonencode()\n%%\n%% Code in libinterp/corefcn/jsonencode.cc\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%% Note: This script is intended to also run under Matlab to verify\n%%       compatibility.  Preserve Matlab-formatting when making changes.\n\n%% Some tests here are just the reverse of tests in jsondecode with\n%% some modifications.\n\n%%% Test 1: Encode logical and numeric scalars, NaN, NA, and Inf\n\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsonencode (logical (1)), 'true'));\n%! assert (isequal (jsonencode (logical (0)), 'false'));\n%! assert (isequal (jsonencode (50.025), '50.025'));\n%! %% FIXME: Uncomment when bug #64960 is fixed\n%! %% assert (isequal (jsonencode (single (50.025)), '50.025'));\n%! assert (isequal (jsonencode (uint64 (1e6)), '1000000'));\n%! assert (isequal (jsonencode (int64 (-1e6)), '-1000000'));\n%! assert (isequal (jsonencode (NaN), 'null'));\n%! assert (isequal (jsonencode (NA), 'null'));    % Octave-only test\n%! assert (isequal (jsonencode (Inf), 'null'));\n%! assert (isequal (jsonencode (-Inf), 'null'));\n\n%% Customized encoding of Nan, NA, Inf, -Inf\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsonencode (NaN, 'ConvertInfAndNaN', true), 'null'));\n%! % Octave-only test for NA\n%! assert (isequal (jsonencode (NA, 'ConvertInfAndNaN', true), 'null'));\n%! assert (isequal (jsonencode (Inf, 'ConvertInfAndNaN', true), 'null'));\n%! assert (isequal (jsonencode (-Inf, 'ConvertInfAndNaN', true), 'null'));\n\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsonencode (NaN, 'ConvertInfAndNaN', false), 'NaN'));\n%! % Octave-only test for NA\n%! assert (isequal (jsonencode (NA, 'ConvertInfAndNaN', false), 'NaN'));\n%! assert (isequal (jsonencode (Inf, 'ConvertInfAndNaN', false), 'Infinity'));\n%! assert (isequal (jsonencode (-Inf, 'ConvertInfAndNaN', false), '-Infinity'));\n\n%%% Test 2: encode character vectors and arrays\n\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsonencode (''), '\"\"'));\n%! assert (isequal (jsonencode ('hello there'), '\"hello there\"'));\n%! assert (isequal (jsonencode (['foo'; 'bar']), '[\"foo\",\"bar\"]'));\n%! assert (isequal (jsonencode (['foo', 'bar'; 'foo', 'bar']), ...\n%!                  '[\"foobar\",\"foobar\"]'));\n\n%% Escape characters inside single-quoted and double-quoted strings\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsonencode ('\\0\\a\\b\\t\\n\\v\\f\\r'), ...\n%!                              '\"\\\\0\\\\a\\\\b\\\\t\\\\n\\\\v\\\\f\\\\r\"'));\n%! % FIXME: Matlab produces a double-escaped string as above.\n%! assert (isequal (jsonencode (\"\\a\\b\\t\\n\\v\\f\\r\"), ...\n%!                              '\"\\u0007\\b\\t\\n\\u000B\\f\\r\"'));\n\n%!testif HAVE_RAPIDJSON\n%! data = [[['foo'; 'bar']; ['foo'; 'bar']], [['foo'; 'bar']; ['foo'; 'bar']]];\n%! exp  = '[\"foofoo\",\"barbar\",\"foofoo\",\"barbar\"]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = cat (3, ['a', 'b'; 'c', 'd'], ['e', 'f'; 'g', 'h']);\n%! exp  = '[[\"ab\",\"ef\"],[\"cd\",\"gh\"]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Try different dimensions for the array\n%!testif HAVE_RAPIDJSON\n%! data = cat (3, ['a', 'b'; 'c', 'd'; '1', '2'], ...\n%!                ['e', 'f'; 'g', 'h'; '3', '4']);\n%! exp  = '[[\"ab\",\"ef\"],[\"cd\",\"gh\"],[\"12\",\"34\"]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Try higher dimensions for the array\n%!testif HAVE_RAPIDJSON\n%! charmat1 = cat (3, ['1', '3'; '5', '7'; '9', 'e'; 'f', 'g'], ...\n%!                    ['2', '4'; '6', '8'; 'a', 'b'; 'c', 'd']);\n%! charmat2 = cat (3, ['1', '3'; '5', '7'; '9', 'e'; 'f', 'g'], ...\n%!                    ['2', '4'; '6', '8'; 'a', 'b'; 'c', 'd']);\n%! data = cat (4, charmat1, charmat2);\n%! exp  = [ '[[[\"13\",\"13\"],[\"24\",\"24\"]],[[\"57\",\"57\"],[\"68\",\"68\"]],', ...\n%!          '[[\"9e\",\"9e\"],[\"ab\",\"ab\"]],[[\"fg\",\"fg\"],[\"cd\",\"cd\"]]]' ];\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Try different dimensions for an array with one of its dimensions equals one\n%!testif HAVE_RAPIDJSON\n%! data = cat (4, ['a'; 'b'], ['c'; 'd']);\n%! exp  = '[[[\"a\",\"c\"]],[[\"b\",\"d\"]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% High dimension, but still a vector, is reduced to a vector\n%!testif HAVE_RAPIDJSON\n%! data = cat (8, ['a'], ['c']);\n%! exp  = '\"ac\"';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = cat (8, ['a'; 'b'; '1'], ['c'; 'd'; '2']);\n%! exp  = '[[[[[[[\"a\",\"c\"]]]]]],[[[[[[\"b\",\"d\"]]]]]],[[[[[[\"1\",\"2\"]]]]]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%%% Test 3: encode numeric and logical arrays (with NaN and Inf)\n\n%% Test simple vectors\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsonencode ([]), '[]'));\n%! assert (isequal (jsonencode ([1, 2, 3, 4]), '[1,2,3,4]'));\n%! % Matlab encodes flints with values above 1e6-1 in scientific notation.  Octave writes integers.\n%! assert (isequal (jsonencode ([1.23e6, 2]), '[1230000,2]'));\n%! assert (isequal (jsonencode ([true; false; true]), '[true,false,true]'));\n\n%% Test arrays\n%!testif HAVE_RAPIDJSON\n%! data = [1, NaN; 3, 4];\n%! exp  = '[[1,null],[3,4]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = cat (3, [NaN, 3; 5, Inf], [2, 4; -Inf, 8]);\n%! exp  = '[[[null,2],[3,4]],[[5,null],[null,8]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Customized encoding of Nan, Inf, -Inf\n%!testif HAVE_RAPIDJSON\n%! data = cat (3, [1, NaN; 5, 7], [2, Inf; 6, -Inf]);\n%! exp  = '[[[1,2],[NaN,Infinity]],[[5,6],[7,-Infinity]]]';\n%! obs  = jsonencode (data, 'ConvertInfAndNaN', false);\n%! assert (isequal (obs, exp));\n\n%% Try different dimensions for the array\n%!testif HAVE_RAPIDJSON\n%! data = cat (3, [1, 3; 5, 7], [2, 4; 6, 8], [-1, NaN; Inf, -Inf]);\n%! exp  = '[[[1,2,-1],[3,4,NaN]],[[5,6,Infinity],[7,8,-Infinity]]]';\n%! obs  = jsonencode (data, 'ConvertInfAndNaN', false);\n%! assert (isequal (obs, exp));\n\n%% Try different dimensions for the array with one of its dimensions equals one\n%!testif HAVE_RAPIDJSON\n%! data = cat (3, [1; 7; 11], [4; 8; 12]);\n%! exp  = '[[[1,4]],[[7,8]],[[11,12]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! array1 = cat (3, [5, 7], [2, 4]);\n%! array2 = cat (3, [-1, -3], [-2, -4]);\n%! data = cat (4, array1, array2);\n%! exp  = '[[[[5,-1],[2,-2]],[[7,-3],[4,-4]]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = cat (4, [1, 3; 5, 7], [-1, -3; -5, -7]);\n%! exp  = '[[[[1,-1]],[[3,-3]]],[[[5,-5]],[[7,-7]]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% High-dimension vector is reduced to just a vector\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 1, 1, 1, 1, 6]);\n%! exp  = '[1,1,1,1,1,1]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 2, 2, 2, 2]);\n%! exp  = '[[[[[1,1],[1,1]],[[1,1],[1,1]]],[[[1,1],[1,1]],[[1,1],[1,1]]]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 2, 2, 1, 2]);\n%! exp  = '[[[[[1,1]],[[1,1]]],[[[1,1]],[[1,1]]]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 2, 1, 2, 1, 2]);\n%! exp  = '[[[[[[1,1]],[[1,1]]]],[[[[1,1]],[[1,1]]]]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 1, 2, 1, 2, 1, 2]);\n%! exp  = '[[[[[[[1,1]],[[1,1]]]],[[[[1,1]],[[1,1]]]]]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 2, 2, 1, 1, 2]);\n%! exp  = '[[[[[[1,1]]],[[[1,1]]]],[[[[1,1]]],[[[1,1]]]]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 2, 1, 3, 1, 1, 1, 2]);\n%! exp  = ['[[[[[[[[1,1]]]],[[[[1,1]]]],[[[[1,1]]]]]],[[[[[[1,1]]]],', ...\n%!         '[[[[1,1]]]],[[[[1,1]]]]]]]]'];\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 1, 1, 1, 2, 1, 1, 1, 2]);\n%! exp  = '[[[[[[[[[1,1]]]],[[[[1,1]]]]]]]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 3, 2, 1, 1, 2, 1, 2, 2]);\n%! exp  = ['[[[[[[[[[1,1],[1,1]]],[[[1,1],[1,1]]]]]],[[[[[[1,1],', ...\n%!         '[1,1]]],[[[1,1],[1,1]]]]]]],[[[[[[[1,1],[1,1]]],[[[1,', ...\n%!         '1],[1,1]]]]]],[[[[[[1,1],[1,1]]],[[[1,1],[1,1]]]]]]],', ...\n%!         '[[[[[[[1,1],[1,1]]],[[[1,1],[1,1]]]]]],[[[[[[1,1],[1,', ...\n%!         '1]]],[[[1,1],[1,1]]]]]]]]]'];\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = ones ([1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 2]);\n%! exp  =  ['[[[[[[[[[[[[[[[[[[[[1,1]]]]]]]],[[[[[[[[1,1]]]]]]]],', ...\n%!          '[[[[[[[[1,1]]]]]]]]],[[[[[[[[[1,1]]]]]]]],[[[[[[[[1,1]]]]]', ...\n%!          ']]],[[[[[[[[1,1]]]]]]]]]],[[[[[[[[[[1,1]]]]]]]],[[[[[[[[1,1]', ...\n%!          ']]]]]]],[[[[[[[[1,1]]]]]]]]],[[[[[[[[[1,1]]]]]]]],[[[[[[', ...\n%!          '[[1,1]]]]]]]],[[[[[[[[1,1]]]]]]]]]]]]],[[[[[[[[[[[[[1,1]', ...\n%!          ']]]]]]],[[[[[[[[1,1]]]]]]]],[[[[[[[[1,1]]]]]]]]],[[[[[[[[', ...\n%!          '[1,1]]]]]]]],[[[[[[[[1,1]]]]]]]],[[[[[[[[1,1]]]]]]]]]],[[[', ...\n%!          '[[[[[[[1,1]]]]]]]],[[[[[[[[1,1]]]]]]]],[[[[[[[[1,1]]]]]]]]],', ...\n%!          '[[[[[[[[[1,1]]]]]]]],[[[[[[[[1,1]]]]]]]],[[[[[[[[1,1]]', ...\n%!          ']]]]]]]]]]]]]]]]]]'];\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Try higher dimensions for the array\n%!testif HAVE_RAPIDJSON\n%! var1 = cat (3, [1, 3; 5, 7; 9, 11; 13, 15], [2, 4; 6, 8; 10, 12; 14, 16]);\n%! var2 = cat (3, [-1, -3; -5, -7; -9, -11; -13, -15], ...\n%!                [-2, -4; -6, -8; -10, -12; -14, -16]);\n%! data = cat (4, var1, var2);\n%! exp  = ['[[[[1,-1],[2,-2]],[[3,-3],[4,-4]]],[[[5,-5],[6,-6]],[[7,-7],', ...\n%!         '[8,-8]]],[[[9,-9],[10,-10]],[[11,-11],[12,-12]]],', ...\n%!         '[[[13,-13],[14,-14]],[[15,-15],[16,-16]]]]'];\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Try logical array (tests above were all with numeric data)\n\n%% 2-D logical array\n%!testif HAVE_RAPIDJSON\n%! data = [true, false; true, false; true, false];\n%! exp  = '[[true,false],[true,false],[true,false]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% N-D logical array\n%!testif HAVE_RAPIDJSON <*59198>\n%! data = true (2,2,2);\n%! data(1,1,2) = false;\n%! exp  = '[[[true,false],[true,true]],[[true,true],[true,true]]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%%% Test 4: encode containers.Map\n\n%% KeyType must be char to encode objects of containers.Map\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsonencode (containers.Map ('1', [1, 2, 3])), ...\n%!                  '{\"1\":[1,2,3]}'));\n\n%!testif HAVE_RAPIDJSON\n%! data = containers.Map ({'foo'; 'bar'; 'baz'}, [1, 2, 3]);\n%! exp  = '{\"bar\":2,\"baz\":3,\"foo\":1}';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON\n%! data = containers.Map ({'foo'; 'bar'; 'baz'}, ...\n%!                        {{1, 'hello', NaN}, true, [2, 3, 4]});\n%! exp  = '{\"bar\":true,\"baz\":[2,3,4],\"foo\":[1,\"hello\",NaN]}';\n%! obs  = jsonencode (data, 'ConvertInfAndNaN', false);\n%! assert (isequal (obs, exp));\n\n%%% Test 5: encode scalar structs\n\n%% Check the encoding of Boolean, Number, and String values inside a struct\n%!testif HAVE_RAPIDJSON\n%! data = struct ('number', 3.14, 'string', 'foobar', 'boolean', false);\n%! exp  = '{\"number\":3.14,\"string\":\"foobar\",\"boolean\":false}';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Check the encoding of NaN, NA, Inf, and -Inf values inside a struct\n%!testif HAVE_RAPIDJSON\n%! % Octave-only test because of NA value\n%! data = struct ('numericArray', [7, NaN, NA, Inf, -Inf]);\n%! exp  = '{\"numericArray\":[7,null,null,null,null]}';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Customized encoding of Nan, NA, Inf, -Inf\n%!testif HAVE_RAPIDJSON\n%! data = struct ('numericArray', [7, NaN, NA, Inf, -Inf]);\n%! exp  = '{\"numericArray\":[7,NaN,NaN,Infinity,-Infinity]}';\n%! obs  = jsonencode (data, 'ConvertInfAndNaN', false);\n%! assert (isequal (obs, exp));\n\n%% Check the encoding of structs inside a struct\n%!testif HAVE_RAPIDJSON\n%! data = struct ('object', struct ('field1', 1, 'field2', 2, 'field3', 3));\n%! exp  = '{\"object\":{\"field1\":1,\"field2\":2,\"field3\":3}}';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Check the encoding of empty structs and empty arrays inside a struct\n%!testif HAVE_RAPIDJSON\n%! data = struct ('a', Inf, 'b', [], 'c', struct ());\n%! exp  = '{\"a\":null,\"b\":[],\"c\":{}}';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% a big test\n%!testif HAVE_RAPIDJSON\n%! var1 = struct ('para', ['A meta-markup language, used to create ' ...\n%!                         'markup languages such as DocBook.'], ...\n%!                'GlossSeeAlso', {{'GML'; 'XML'}});\n%! var2 = struct ('ID', 'SGML', 'SortAs', 'SGML', ...\n%!                'GlossTerm', 'Standard Generalized Markup Language', ...\n%!                'Acronym', 'SGML', 'Abbrev', 'ISO 8879:1986', ...\n%!                'GlossDef', var1, 'GlossSee', 'markup');\n%! data  = struct ('glossary', ...\n%!                struct ('title', 'example glossary', ...\n%!                        'GlossDiv', struct ('title', 'S', ...\n%!                                            'GlossList', ...\n%!                                            struct ('GlossEntry', var2))));\n%! exp = ['{' , ...\n%!     '\"glossary\":{', ...\n%!         '\"title\":\"example glossary\",', ...\n%! \t\t'\"GlossDiv\":{', ...\n%!             '\"title\":\"S\",', ...\n%! \t\t\t'\"GlossList\":{', ...\n%!                 '\"GlossEntry\":{', ...\n%!                     '\"ID\":\"SGML\",', ...\n%! \t\t\t\t\t'\"SortAs\":\"SGML\",', ...\n%! \t\t\t\t\t'\"GlossTerm\":\"Standard Generalized Markup Language\",', ...\n%! \t\t\t\t\t'\"Acronym\":\"SGML\",', ...\n%! \t\t\t\t\t'\"Abbrev\":\"ISO 8879:1986\",', ...\n%! \t\t\t\t\t'\"GlossDef\":{', ...\n%!                         '\"para\":\"A meta-markup language, ', ...\n%!                         'used to create markup languages such as DocBook.\",', ...\n%! \t\t\t\t\t\t'\"GlossSeeAlso\":[\"GML\",\"XML\"]', ...\n%!                     '},', ...\n%! \t\t\t\t\t'\"GlossSee\":\"markup\"', ...\n%!                 '}', ...\n%!             '}', ...\n%!         '}', ...\n%!     '}', ...\n%! '}'];\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%%% Test 6: Encode struct arrays\n\n%!testif HAVE_RAPIDJSON\n%! data = struct ('structarray', struct ('a', {1; 3}, 'b', {2; 4}));\n%! exp  = '{\"structarray\":[{\"a\":1,\"b\":2},{\"a\":3,\"b\":4}]}';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON <*63622>\n%! data = struct ('z', {});\n%! exp  = '[]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n%\n%!testif HAVE_RAPIDJSON <*63622>\n%! data.a = struct ('z', {});\n%! data.b = 1;\n%! exp  = '{\"a\":[],\"b\":1}';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% another big Test\n%!testif HAVE_RAPIDJSON\n%! var1 = struct ('id', {0; 1; 2}, 'name', {'Collins'; 'Hays'; 'Griffin'});\n%! var2 = struct ('id', {0; 1; 2}, 'name', {'Osborn'; 'Mcdowell'; 'Jewel'});\n%! var3 = struct ('id', {0; 1; 2}, 'name', {'Socorro'; 'Darla'; 'Leanne'});\n%! data = struct (...\n%!   'x_id', {'5ee28980fc9ab3'; '5ee28980dd7250'; '5ee289802422ac'}, ...\n%!   'index', {0; 1; 2}, ...\n%!   'guid', {'b229d1de-f94a'; '39cee338-01fb'; '3db8d55a-663e'}, ...\n%!   'latitude', {-17.124067; 13.205994; -35.453456}, ...\n%!   'longitude', {-61.161831; -37.276231; 14.080287}, ...\n%!   'friends', {var1; var2; var3});\n%! exp  = ['[', ...\n%!   '{', ...\n%!     '\"x_id\":\"5ee28980fc9ab3\",', ...\n%!     '\"index\":0,', ...\n%!     '\"guid\":\"b229d1de-f94a\",', ...\n%!     '\"latitude\":-17.124067,', ...\n%!     '\"longitude\":-61.161831,', ...\n%!     '\"friends\":[', ...\n%!       '{', ...\n%!         '\"id\":0,', ...\n%!         '\"name\":\"Collins\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":1,', ...\n%!         '\"name\":\"Hays\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":2,', ...\n%!         '\"name\":\"Griffin\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '},', ...\n%!   '{', ...\n%!     '\"x_id\":\"5ee28980dd7250\",', ...\n%!     '\"index\":1,', ...\n%!     '\"guid\":\"39cee338-01fb\",', ...\n%!     '\"latitude\":13.205994,', ...\n%!     '\"longitude\":-37.276231,', ...\n%!     '\"friends\":[', ...\n%!       '{', ...\n%!         '\"id\":0,', ...\n%!         '\"name\":\"Osborn\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":1,', ...\n%!         '\"name\":\"Mcdowell\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":2,', ...\n%!         '\"name\":\"Jewel\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '},', ...\n%!   '{', ...\n%!     '\"x_id\":\"5ee289802422ac\",', ...\n%!     '\"index\":2,', ...\n%!     '\"guid\":\"3db8d55a-663e\",', ...\n%!     '\"latitude\":-35.453456,', ...\n%!     '\"longitude\":14.080287,', ...\n%!     '\"friends\":[', ...\n%!       '{', ...\n%!         '\"id\":0,', ...\n%!         '\"name\":\"Socorro\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":1,', ...\n%!         '\"name\":\"Darla\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":2,', ...\n%!         '\"name\":\"Leanne\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '}', ...\n%! ']'];\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%%% Test 7: encode cell arrays\n\n%!testif HAVE_RAPIDJSON\n%! assert (isequal (jsonencode ({}), '[]'));\n%! assert (isequal (jsonencode ({5}), '[5]'));\n%! assert (isequal (jsonencode ({'hello there'}), '[\"hello there\"]'));\n\n%% Logical cell arrays\n%!testif HAVE_RAPIDJSON\n%! data = {'true', 'true'; 'false', 'true'};\n%! exp  = '[\"true\",\"false\",\"true\",\"true\"]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Cell array of character vectors\n%!testif HAVE_RAPIDJSON\n%! data = {'foo'; 'bar'; {'foo'; 'bar'}};\n%! exp  = '[\"foo\",\"bar\",[\"foo\",\"bar\"]]';\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% cell array of structs & a big test\n%!testif HAVE_RAPIDJSON\n%! var1 = struct ('x_id', '5ee28980fc9ab3', 'index', 0, ...\n%!                'guid', 'b229d1de-f94a', 'latitude', -17.124067, ...\n%!                'longitude', -61.161831, ...\n%!                'friends', struct ('id', {0; 1; 2}, ...\n%!                                   'name', {'Collins'; 'Hays'; 'Griffin'}));\n%! var2 = struct ('numericArray', {{'str'; 5; []}}, ...\n%!                'nonnumericArray', {[1; 2; NaN]});\n%! var3 = struct ('firstName', 'John', 'lastName', 'Smith', 'age', 25, ...\n%!                'address', ...\n%!                struct ('streetAddress', '21 2nd Street', ...\n%!                        'city', 'New York', 'state', 'NY'), ...\n%!                'phoneNumber', ...\n%!                struct ('type', 'home', 'number', '212 555-1234'));\n%! data = {var1; var2; var3};\n%! exp  = ['[', ...\n%!   '{', ...\n%!     '\"x_id\":\"5ee28980fc9ab3\",', ...\n%!     '\"index\":0,', ...\n%!     '\"guid\":\"b229d1de-f94a\",', ...\n%!     '\"latitude\":-17.124067,', ...\n%!     '\"longitude\":-61.161831,', ...\n%!     '\"friends\":[', ...\n%!       '{', ...\n%!         '\"id\":0,', ...\n%!         '\"name\":\"Collins\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":1,', ...\n%!         '\"name\":\"Hays\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":2,', ...\n%!         '\"name\":\"Griffin\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '},', ...\n%!   '{\"numericArray\":[\"str\",5,[]],\"nonnumericArray\":[1,2,null]},', ...\n%!   '{', ...\n%!      '\"firstName\":\"John\",', ...\n%!      '\"lastName\":\"Smith\",', ...\n%!      '\"age\":25,', ...\n%!      '\"address\":', ...\n%!      '{', ...\n%!          '\"streetAddress\":\"21 2nd Street\",', ...\n%!          '\"city\":\"New York\",', ...\n%!          '\"state\":\"NY\"', ...\n%!      '},', ...\n%!      '\"phoneNumber\":', ...\n%!          '{', ...\n%!            '\"type\":\"home\",', ...\n%!            '\"number\":\"212 555-1234\"', ...\n%!          '}', ...\n%!  '}]'];\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% cell array of diferrent types & Customized encoding of Nan, Inf, -Inf\n%!testif HAVE_RAPIDJSON\n%! var =  struct ('x_id', '5ee28980dd7250', 'index', 1, ...\n%!                'guid', '39cee338-01fb', 'latitude', 13.205994, ...\n%!                'longitude', -37.276231, ...\n%!                'friends', struct ('id', {0; 1; 2}, ...\n%!                                   'name', {'Osborn'; 'Mcdowell'; 'Jewel'}));\n%! data = {NaN; true; Inf; 2531.023; 'hello there'; var};\n%! exp  = ['[NaN,true,Infinity,2531.023,\"hello there\",', ...\n%!   '{', ...\n%!     '\"x_id\":\"5ee28980dd7250\",', ...\n%!     '\"index\":1,', ...\n%!     '\"guid\":\"39cee338-01fb\",', ...\n%!     '\"latitude\":13.205994,', ...\n%!     '\"longitude\":-37.276231,', ...\n%!     '\"friends\":[', ...\n%!       '{', ...\n%!         '\"id\":0,', ...\n%!         '\"name\":\"Osborn\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":1,', ...\n%!         '\"name\":\"Mcdowell\"', ...\n%!       '},', ...\n%!       '{', ...\n%!         '\"id\":2,', ...\n%!         '\"name\":\"Jewel\"', ...\n%!       '}', ...\n%!     ']', ...\n%!   '}]'];\n%! obs  = jsonencode (data, 'ConvertInfAndNaN', false);\n%! assert (isequal (obs, exp));\n\n%% a big example\n%!testif HAVE_RAPIDJSON\n%! var1 = struct ('x_id', '5ee28980fc9ab3', 'index', 0, ...\n%!                'guid', 'b229d1de-f94a', 'latitude', -17.124067, ...\n%!                'longitude', -61.161831, ...\n%!                'friends', struct ('id', {0; 1; 2}, ...\n%!                                   'name', {'Collins'; 'Hays'; 'Griffin'}));\n%! var2 = struct ('numericArray', {{'str'; 5; -Inf}}, ...\n%!                'nonnumericArray', {[1; 2; NaN]});\n%! var3 = struct ('firstName', 'John', 'lastName', 'Smith', 'age', 25, ...\n%!                'address', ...\n%!                struct ('streetAddress', '21 2nd Street', ...\n%!                        'city', 'New York', 'state', 'NY'), ...\n%!                'phoneNumber', ...\n%!                struct ('type', 'home', 'number', '212 555-1234'));\n%! data = {{'str'; Inf; {}}; [1; 2; NaN]; {'foo'; 'bar'; {'foo'; 'bar'}};\n%!        cat(3, [1, 3; 5, 7], [2, 4; 6, 8]); {var1; var2 ;var3}};\n%! exp  = ['[[\"str\",null,[]],[1,2,null],[\"foo\",\"bar\",[\"foo\",\"bar\"]],', ...\n%!   '[[[1,2],[3,4]],[[5,6],[7,8]]],' , ...\n%!   '[', ...\n%!     '{', ...\n%!       '\"x_id\":\"5ee28980fc9ab3\",', ...\n%!       '\"index\":0,', ...\n%!       '\"guid\":\"b229d1de-f94a\",', ...\n%!       '\"latitude\":-17.124067,', ...\n%!       '\"longitude\":-61.161831,', ...\n%!       '\"friends\":[', ...\n%!         '{', ...\n%!           '\"id\":0,', ...\n%!           '\"name\":\"Collins\"', ...\n%!         '},', ...\n%!         '{', ...\n%!           '\"id\":1,', ...\n%!           '\"name\":\"Hays\"', ...\n%!         '},', ...\n%!         '{', ...\n%!           '\"id\":2,', ...\n%!           '\"name\":\"Griffin\"', ...\n%!         '}', ...\n%!       ']', ...\n%!     '},', ...\n%!     '{\"numericArray\":[\"str\",5,null],\"nonnumericArray\":[1,2,null]},', ...\n%!     '{', ...\n%!        '\"firstName\":\"John\",', ...\n%!        '\"lastName\":\"Smith\",', ...\n%!        '\"age\":25,', ...\n%!        '\"address\":', ...\n%!        '{', ...\n%!            '\"streetAddress\":\"21 2nd Street\",', ...\n%!            '\"city\":\"New York\",', ...\n%!            '\"state\":\"NY\"', ...\n%!        '},', ...\n%!        '\"phoneNumber\":', ...\n%!            '{', ...\n%!              '\"type\":\"home\",', ...\n%!              '\"number\":\"212 555-1234\"', ...\n%!            '}', ...\n%!    '}]]'];\n%! obs  = jsonencode (data);\n%! assert (isequal (obs, exp));\n\n%% Just basic tests to ensure option \"PrettyPrint\" is functional.\n%!testif HAVE_RAPIDJSON_PRETTYWRITER\n%! data = {'Hello'; 'World!'};\n%! exp  = do_string_escapes ([ '[\\n', ...\n%!                             '  \"Hello\",\\n', ...\n%!                             '  \"World!\"\\n', ...\n%!                             ']' ]);\n%! obs  = jsonencode (data, 'PrettyPrint', true);\n%! assert (isequal (obs, exp));\n%!\n%! exp  = '[\"Hello\",\"World!\"]';\n%! obs  = jsonencode (data, 'PrettyPrint', false);\n%! assert (isequal (obs, exp));\n\n%!testif HAVE_RAPIDJSON_PRETTYWRITER\n%! data = [1, 2; 3, 4];\n%! exp  = do_string_escapes ([ ...\n%! '[\\n'                       ...\n%! '  [\\n'                   ...\n%! '    1,\\n'              ...\n%! '    2\\n'               ...\n%! '  ],\\n'                  ...\n%! '  [\\n'                   ...\n%! '    3,\\n'              ...\n%! '    4\\n'               ...\n%! '  ]\\n'                   ...\n%! ']' ]);\n%! obs  = jsonencode (data, 'PrettyPrint', true);\n%! assert (isequal (obs, exp));\n%!\n%! exp  = '[[1,2],[3,4]]';\n%! obs  = jsonencode (data, 'PrettyPrint', false);\n%! assert (isequal (obs, exp));\n"
  },
  {
    "path": "test/json/module.mk",
    "content": "json_TEST_FILES = \\\n  %reldir%/jsondecode.tst \\\n  %reldir%/jsonencode.tst\n\nTEST_FILES += $(json_TEST_FILES)\n"
  },
  {
    "path": "test/jupyter-notebook/jupyter-notebook.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Test running a single cell\n%!testif HAVE_RAPIDJSON\n%! visibility = get (0, \"defaultfigurevisible\");\n%! toolkit = graphics_toolkit ();\n%! unwind_protect\n%!   if (! strcmp (graphics_toolkit (), \"qt\"))\n%!     try\n%!       graphics_toolkit (\"gnuplot\");\n%!     catch\n%!       ## The system doesn't support gnuplot for drawing hidden\n%!       ## figures.  Just return and have test marked as passing.\n%!       return;\n%!     end_try_catch\n%!   endif\n%!   set (0, \"defaultfigurevisible\", \"off\");\n%!\n%!   n = jupyter_notebook (fullfile (\"octave-kernel.ipynb\"));\n%!\n%!   ## Test embedding images\n%!   n.run (2);\n%!   assert (n.notebook.cells{2}.outputs{1}.output_type, \"display_data\");\n%!   assert (isfield (n.notebook.cells{2}.outputs{1}.data, \"image/png\"));\n%!   assert (getfield (n.notebook.cells{2}.outputs{1}.data, \"text/plain\"),\n%!           {\"<IPython.core.display.Image object>\"});\n%!\n%!   ## Test running non-code cells\n%!   markdown_cell = n.notebook.cells{1};\n%!   n.run (1);\n%!   assert (markdown_cell, n.notebook.cells{1});\n%! unwind_protect_cleanup\n%!   set (0, \"defaultfigurevisible\", visibility);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n## Test running all cells\n%!testif HAVE_RAPIDJSON\n%! visibility = get (0, \"defaultfigurevisible\");\n%! toolkit = graphics_toolkit ();\n%! unwind_protect\n%!   if (! strcmp (graphics_toolkit (), \"qt\"))\n%!     try\n%!       graphics_toolkit (\"gnuplot\");\n%!     catch\n%!       ## The system doesn't support gnuplot for drawing hidden\n%!       ## figures.  Just return and have test marked as passing.\n%!       return;\n%!     end_try_catch\n%!   endif\n%!   set (0, \"defaultfigurevisible\", \"off\");\n%!\n%!   n = jupyter_notebook (fullfile (\"octave-kernel.ipynb\"));\n%!   n.run_all ();\n%!\n%!   ## Test embedding images\n%!   assert (n.notebook.cells{3}.outputs{1}.output_type, \"display_data\");\n%!   assert (isfield (n.notebook.cells{3}.outputs{1}.data, \"image/png\"));\n%!   assert (getfield (n.notebook.cells{3}.outputs{1}.data, \"text/plain\"),\n%!           {\"<IPython.core.display.Image object>\"});\n%!\n%!   ## Test running non-code cells\n%!   markdown_cell = n.notebook.cells{1};\n%!   n.run (1);\n%!   assert (markdown_cell, n.notebook.cells{1});\n%!\n%!   ## Test embedding textual output\n%!   assert (n.notebook.cells{6}.outputs{1}.output_type, \"stream\");\n%!   assert (n.notebook.cells{6}.outputs{1}.name, \"stdout\");\n%! unwind_protect_cleanup\n%!   set (0, \"defaultfigurevisible\", visibility);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n## Test plot magic\n%!testif HAVE_RAPIDJSON\n%! visibility = get (0, \"defaultfigurevisible\");\n%! toolkit = graphics_toolkit ();\n%! unwind_protect\n%!   if (! strcmp (graphics_toolkit (), \"qt\"))\n%!     try\n%!       graphics_toolkit (\"gnuplot\");\n%!     catch\n%!       ## The system doesn't support gnuplot for drawing hidden\n%!       ## figures.  Just return and have test marked as passing.\n%!       return;\n%!     end_try_catch\n%!   endif\n%!   set (0, \"defaultfigurevisible\", \"off\");\n%!\n%!   n = jupyter_notebook (fullfile (\"plot-magic-and-errors.ipynb\"));\n%!\n%!   ## PNG format\n%!   n.run (1);\n%!   assert (n.notebook.cells{1}.outputs{1}.output_type, \"display_data\");\n%!   assert (isfield (n.notebook.cells{1}.outputs{1}.data, \"image/png\"));\n%!   assert (getfield (n.notebook.cells{1}.outputs{1}.data, \"text/plain\"),\n%!           {\"<IPython.core.display.Image object>\"});\n%!\n%!   ## SVG format\n%!   n.run (2);\n%!   assert (n.notebook.cells{2}.outputs{1}.output_type, \"display_data\");\n%!   assert (isfield (n.notebook.cells{2}.outputs{1}.data, \"image/svg+xml\"));\n%!   assert (getfield (n.notebook.cells{2}.outputs{1}.data, \"text/plain\"),\n%!           {\"<IPython.core.display.SVG object>\"});\n%!\n%!   ## JPG format\n%!   n.run (3);\n%!   assert (n.notebook.cells{3}.outputs{1}.output_type, \"display_data\");\n%!   assert (isfield (n.notebook.cells{3}.outputs{1}.data, \"image/jpeg\"));\n%!   assert (getfield (n.notebook.cells{3}.outputs{1}.data, \"text/plain\"),\n%!           {\"<IPython.core.display.Image object>\"});\n%! unwind_protect_cleanup\n%!   set (0, \"defaultfigurevisible\", visibility);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n## Test errors\n%!testif HAVE_RAPIDJSON\n%! visibility = get (0, \"defaultfigurevisible\");\n%! toolkit = graphics_toolkit ();\n%! unwind_protect\n%!   if (! strcmp (graphics_toolkit (), \"qt\"))\n%!     try\n%!       graphics_toolkit (\"gnuplot\");\n%!     catch\n%!       ## The system doesn't support gnuplot for drawing hidden\n%!       ## figures.  Just return and have test marked as passing.\n%!       return;\n%!     end_try_catch\n%!   endif\n%!   set (0, \"defaultfigurevisible\", \"off\");\n%!\n%!   n = jupyter_notebook (fullfile (\"plot-magic-and-errors.ipynb\"));\n%!\n%!   ## Wrong resolution\n%!   n.run (4);\n%!   assert (n.notebook.cells{4}.outputs{1}.output_type, \"stream\");\n%!   assert (n.notebook.cells{4}.outputs{1}.name, \"stderr\");\n%!   assert (n.notebook.cells{4}.outputs{1}.text,\n%!           {\"A number is required for resolution, not a string\"});\n%!\n%!   ## Wrong width\n%!   n.run (5);\n%!   assert (n.notebook.cells{5}.outputs{1}.output_type, \"stream\");\n%!   assert (n.notebook.cells{5}.outputs{1}.name, \"stderr\");\n%!   assert (n.notebook.cells{5}.outputs{1}.text,\n%!           {\"A number is required for width, not a string\"});\n%!\n%!   ## Wrong height\n%!   n.run (6);\n%!   assert (n.notebook.cells{6}.outputs{1}.output_type, \"stream\");\n%!   assert (n.notebook.cells{6}.outputs{1}.name, \"stderr\");\n%!   assert (n.notebook.cells{6}.outputs{1}.text,\n%!           {\"A number is required for height, not a string\"});\n%!\n%!   ## Empty figure\n%!   n.run (7);\n%!   assert (n.notebook.cells{7}.outputs{1}.output_type, \"stream\");\n%!   assert (n.notebook.cells{7}.outputs{1}.name, \"stderr\");\n%!   assert (n.notebook.cells{7}.outputs{1}.text,\n%!           {\"The figure is empty!\"});\n%!\n%!   ## Wrong format\n%!   n.run (8);\n%!   assert (n.notebook.cells{8}.outputs{1}.output_type, \"stream\");\n%!   assert (n.notebook.cells{8}.outputs{1}.name, \"stderr\");\n%!   assert (n.notebook.cells{8}.outputs{1}.text,\n%!           {\"Cannot embed the 'pdf' image format\\n\"});\n%! unwind_protect_cleanup\n%!   set (0, \"defaultfigurevisible\", visibility);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/jupyter-notebook/module.mk",
    "content": "jupyter_TEST_FILES = \\\n  %reldir%/jupyter-notebook.tst \\\n  %reldir%/octave-kernel.ipynb \\\n  %reldir%/plot-magic-and-errors.ipynb\n\nTEST_FILES += $(jupyter_TEST_FILES)\n"
  },
  {
    "path": "test/jupyter-notebook/octave-kernel.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"This Jupyter notebook is taken from <https://github.com/Calysto/octave_kernel>.\\n\",\n    \"\\n\",\n    \"##### Jupyter Octave Kernel\\n\",\n    \"============\\n\",\n    \"\\n\",\n    \"Interact with Octave in Notebook. All commands are interpreted by Octave.  Since this is a [MetaKernel](https://github.com/Calysto/metakernel), a standard set of magics are available.  Help on commands is available using the `%help` magic or using `?` with a command.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAjAAAAGkCAIAAACgjIjwAAAakUlEQVR42u3dX2ie5d0H8Cuvdu2Ba5SBgzF06cAU3EQajANPxl43KxvWA0cPqiuIbogyxCJVdjA6FNlBCxtCh6hDwQNhshWLVMSC4MRRjGUFISKJLVJlhclWD2rUPO9BXmPa3EmeJ8/95/rz+RyZJu1zPfeV+/r+rt91J470er0AAF37n64HAAAhCCQAIiGQAIiCQAIgCgIJgCgIJACiIJAAiIJAAiAKAgmAKAgkAKIgkACIgkACIAoCCYAoCCQAoiCQAIiCQAIgCgIJgCgIJACiIJAAiIJAAiAKAgmAKAgkAKIgkACIgkACIAoCCYAoCCQAoiCQAIhC8oH0wgsvPP30012PAoBhpR1Iu3fv/u1vf9v1KACowcVdD2AozzzzzHPPPffpp592PRAAhpV2IK1ifHx86YfT7747ftVVLbzuuz87eNXhe7p+92kzWQkxWWmZnp7uegiryTaQwrJLPz0yEnq9Rl9xZM/R3v4fjYSDCx/29v+o2yswPj4e+fffhUZGQgih16txsla6CLFNVqMa+U5YOlkhNHpzDT9Z6d0LtRsZaad0GEbOgXShXi80eecs3DNhyd2y+Cf0ZWkImazIXTBZF/xJvS9lsoa0eCud3zeKUNoPNQys1/tqpauVO2RYy5ezdiert/9HI3uOdn0VElGZPSYrTguT1XBzqC7J75B27drV9RBWTKOF20ZQrW2V4nphmavvdjIjwzJZNKawHdKCWku51e+Zbku5I0eOdPXS8Vh6EWKerNYuQirqnawUr0ANmj84r1eRgURU1rxnmukFsR4xTVbGBUSxSg2kmm6bfloKbptImCzKktr2KJQbSESiz3vGJikGLU5Wn6dHCojMFBxIQ982/Z+4um0SYrLIQYLbo1B0ING5Fu8Zz2sNa6DJGq7aG2iyFBA5KTuQHMAmxGRBn9LcHoXSA2kIKu5h2R7lzbEfgys+kNw2CTFZXYm7erCjPU+y26MgkNZnfRW326YTWx6fNVmQBIFEF1Iu4ujX4DtazdXCCSSSomvXvhSqBzvaPAikgdc4RVxCRvYcnblvbH1/1xpHelKoHlYhkFpljYOVKPUQSLRuyCJO165N6UyWai8DAimEMMBto4grijWOlCTerwsCqX3WuNaoHiAtAol2pV/EMZj+2g+1VA+qvdQJJBLkZKIdqoeEZDFZAulLfaxxdbWAil7jAFYgkGhR3L8SDeiWQCJNHv5uWo3Vw1qTVWP1oP2QNIG0hDWOKtY4YpfFAVIQSP2rtwVkjQO4gECiLQ6QgFUJJGCZ2quHlfvhqgcWCSSS5cyPKsX1w3M5QAoC6UIrrHGKuMIVt8ZBFwRSZ6xxDVE9QKIEEq3IqKvAOlW1H1QPLCWQSJljpCakXz1oPyRKIC2zbI1TxBGsccQp/ephKYHUJWtc7VQPkC6BBEAUBBLNy6urwPqd3w9vdDur/ZAigUTi/M/66qV6oDsCqcqSNa7pM4ki1jigCdlVDwKJfHiiAZImkGhYdkUcQ/my/aB6YDmBRPr8eGxd8qoe9MOTI5BWYI2jijWOWORVPSwQSKvRVQBojUDqnqK7FqoHSN3FXQ+ArOXYVWBYvV4YGen5xmAZgUQWer3eyEjYb40bguqBrmnZAdnKth+eafUgkFY08sCrvQP/2/UoiE62axx0TSBFwRo3JFcPMiCQaEymXQWGpHpgJQIJaJ0fPKeKQCIX1rhh5Lud1Q9PiECq9v8/ZWmNo4o1ji7lWz0IpFhY44DCCSSS55cGQR4EEs3It6vAML6qHvTDWUYgQfFyrx56+3+05fHZrkfB2gQSGVF0Q8oEUoXzziSscVTxEArdyHo7K5AiYo0DSiaQSJtH7CAbAokGZN1VYN0urB70wzmfQCIv1rhBlVE9zNw3ph8eP4EE6+TMj7blXj0IpAtVnEkougGaJ5DiougGiiWQqFuLXQWP2EFOBBLQhurqQT+cJQQS2bHG9S/3Q/Kl9MPjJ5D6Y40DulVA9SCQzuNMgoEouqFGAik61rg+qR4gMwIJgCgIJGpVQJubdVhtO+uAli8JJHJkjetHedWDfnjkBBIAURBIX1njkFzRTRVFN20oYzsrkGJkjQMKJJBIkme+IT8Xdz2AtR04cOC111675JJLHnvssSuuuGLxz+fn56+77rrR0dEQwrXXXnvgwIGuR1q8MroKDEr1QJ9iD6S33377+PHjhw4deuONNx555JEnnnhi8VMffvjh5OTkwYMHux4jMJyFA1rVTPFib9lNTU1NTk6GECYmJo4dO7b0U++///4nn3yyZ8+ehx566NSpU12PlMh4CGV1pQaAA9qYxb5DOnPmzNatW0MIGzduHB0dPXfu3KZNmxY+tWHDhhtuuOH2229/880377777pdffvmCvzs+Pr7430eOHOnn5WZnZ1f79MzM2MjI7MxMO+99jcH04YMPPmhnqAvG6hhz/9Z8rYXxtHARZu4bG9lzdOa+sdbe+6CWX4Q4J6u1K9Dmex/e2JYtszMzYV1j3r59e9fDH0DsgbR58+bTp0+HEObm5s6ePbuYRiGEycnJhc3TjTfe+Oijj3788ceXXXbZ0r87PT3d/wv13+YeG2tn3Zmt5YXaGm37L9fX9Vn4mlZGVc98NWf58OKcrFauQOyTtergB7N0GVxao8cp9pbd9ddfPzU1FUI4ceLEtm3bQgi9Xu+zzz4LITz77LNPPvlkCOHkyZO9Xu/SSy/terB10lhYhUNyyFLsO6SJiYnx8fHdu3eHEPbt2xdCeOedd/bu3Xv48OFbb7117969L7300vz8/P79+0ccGACkLPZACiE8+OCDSz+8+uqrDx8+HELYvHmzR+wiUuohOavrdzvrQTvib9nB+nnQbiVlL/364dESSFADaxwMTyANSNENtKmk7axACiHWp7YU3UBRBBKJibN6AIYnkKhDSV0F+qd6YCACCYiDA9riCSSy1uuNbdnS9SAiYzvrgDZWAmlw6jiqWOOoX2HVg0DS5gaIgkCKmqIbKIdAIiW2s5AxgcTQCmtz06f1VA8OaMsmkKAkqgciJpDI3OzMjKKb5RzQRkggrYvGAlWscdSpvO1s6YHkkBwgEqUHUvwU3YtUD5A3gQRAFAQSwymvzU0/1r+ddUBbMIEExVA9EDeBRAEU3VRxQBsbgbRe1jiqWOOoR5Hb2aIDyVNbAPEoOpBSoegGSiCQSIPtLGRPIDGEItvcrGnY6sEBbakEEgBREEiUQdFtO1vFAW1UBBLUzBrHsEqtHsoNpBoOyRXdAPUpN5DSougGsieQSIBnvqEEAon1KrXNzerqqR70w4skkACIgkCiGAUX3WNbttjOrsQBbTwEEtTPGsf6FdwMLzSQajskL7joBqhXoYGUIkU3kDeBROw88w2FEEisS8FtbqAhAgmoTZ3bWQe05RFIlKTMNW5kZHZmputBRM0BbSQEEkA0ym6GC6ShlVl0sxZFNwyqxEBK96ktaxyQsRIDiYSkWz0AgxJIAERBIDG4ss9dWUn921kHtIURSJA11QPpEEgURtFNFU8MxUAg1cEaRxVrHIMpfjtbXCB5agsgTsUFUuqKKrpVD1AUgQRAFAQSAyq+zU2lprazDmhLIpAAiIJAojzlFN22s4Mo6oA2TgIJGmSNo1+qh9ICqcGntsopugGaUVYg5UHRDWRJIBEpP4QEpRFIDEKbG2iMQAKG1ex21gFtMQQSZMp2dnAOaLslkCiSohviI5DqY42jiqKbtdnOhhCKCiRPbQHErKBAykn2RbfqAQokkACIgkCib9rcVGljO+uAtgwCCXKkeiBBAolSKbqpkv0BbcwEEjTOGsdqbGe/VEogtfTUlqIbYL1KCaT8KLqBzAgkouOHkKBMAon+aHMDDUs7kA4cOLBjx45du3adOnWq67FAidrbzjqgLUDCgfT2228fP3780KFD99577yOPPNL1cEhQrmuc7exwHNB25eKuB7B+U1NTk5OTIYSJiYl77713+ReMj49/9cHPDs7OzrYwqrEQ2nmhBau/1gcffJDl+xrI6hehzffV2gstf1M1fidE9b76t44rkMT7WtP27dvbeRe1SDiQzpw5s3Xr1hDCxo0bR0dHz507t2nTpqVfMD093cGwer2x9urT2bGxsdW/Ys0v6F+N/9Tw76vGkbfzvnr7x9p8WGP5m2rsbdY8WYO+r8b+blvva2Qk9HrNvdLSZTD+bV/CLbvNmzefPn06hDA3N3f27NkL0giAtCQcSNdff/3U1FQI4cSJE9u2bet6OB3IstPtmW8oVsItu4mJifHx8d27d4cQ9u3b1/VwABhKwoEUQnjwwQe7HkIZPLVFlba3swtPRfpWzFfCLTuggiWbZAkkypbrjyIxnPwOaEf2HL3q8D1dj2INAglakt8ax7BsZ88nkBqg6AYYnEBKm6IbyIZAIiJ+CAlKJpBYizY3VVQP1E4gAelwQJs1gUTxclrjbGfrk9MBbSrbWYEEQBQEUjNyKrqpT05FN8OynV1GICXPGgfkQSARi1Ta3EBDBBIAURBIrEqbmypdbmcd0OZLIEEuVA8kTiCBoptqeTwxlNDprECCVuWxxjEs29kqAqkxim6AQQikHCi6gQwIJKKQUJsbaIhAYmXa3FRRPdAQgQSkxgFtpgQShBDSX+NsZ5uR+gFtWttZgQTQLtXDCgRSk1IvumlG6kU3NEQgZcIaB6ROING9tNrcQEMEEivQ5gbaJZCAAcSynXVAmyOBBOmznW1Suge0sVQPfRNI8CVFN3RKIDXMGkeVdItuhmU7uzKBBEAUBFI+Ei26k2tzAw0RSABEQSBRRZubKnFtZx3QZkcgQeJUD+RCIMESim6qpHhAG9d2tj8CqXnWOKqkuMYxLNvZVQkkAKIgkLKi6AbSJZDoUoptbqAhAolltLmpEmP14IA2LwIJgCgIJDhfWkW37Wxb0jqgjXE72weBBJ1Ja41jWKqHtQikVqRVdAN0QSDlRtENJEog0ZlE29xAQwQS59PmporqgRYIJCBlDmgzIpBgmVTWONvZdqVyQJvudlYgQZdSWeMYluqhDwKpLakU3QAdEUgZUnQDKRJIdCPdNjfQEIHEEtrcQHcEErCG2LezDmhzIZCgSvxrnO1sF+I/oI29eliVQIKOxb/GMSzVQ38EUoviL7oBuiOQ8qToBpIjkOhA0m1uoCECiS9pc1MljepBPzwLAgkSpHogRwIJVqDopkrMB7RpbGdXJpDaZY2jSsxrHMOyne2bQAIgCgIpW739P9ry+GzXo6iQelcBaIhAAiAKAokQgjY31VLazjqgTZ9AgtSoHqiSUvWwAoEEK1N0U8VTkQ0RSK2zxlHFGpcn29lBCCQAoiCQcjZz31hsRXcGbW6gIRd3PYC1HThw4LXXXrvkkksee+yxK664YvHP5+fnr7vuutHR0RDCtddee+DAga5HCsD6xR5Ib7/99vHjxw8dOvTGG2888sgjTzzxxOKnPvzww8nJyYMHD3Y9xvRpc1Mlve3swgGtb+Zkxd6ym5qampycDCFMTEwcO3Zs6afef//9Tz75ZM+ePQ899NCpU6e6Him0woIbh9geQkmveqgS+w7pzJkzW7duDSFs3LhxdHT03LlzmzZtWvjUhg0bbrjhhttvv/3NN9+8++67X3755Qv+7vj4+OJ/HzlypOu38pWxEGZn2/ilPh988EHo47VaG8+CNl9r8SKs38zM2MjI7MxMO6NtaLLWfRFanqzhrXR9hv02WEFUN1flC23fvr2dV69FpIH0/PPPHzly5PLLL7/yyitPnz4dQpibmzt79uxiGoUQJicnFzZPN95446OPPvrxxx9fdtllS/+R6enprt/HCnq9sfbq3NmxsbE1v6ifr2lzPPUa/hXbGXNv/1g/de76BrOuv9XBZA1vpTE38F7Wuj4jI6HXa+sKVg9m6TK4tEaPU6SBtHPnzp07d4YQ3nrrrYVTohMnTmzbti2E0Ov1Pv/88w0bNjz77LNzc3N33XXXyZMne73epZde2vWoY7TQWMhgLw9kL9JAWjQxMTE+Pr579+4Qwr59+0II77zzzt69ew8fPnzrrbfu3bv3pZdemp+f379//4ifNo2eaARWEXsghRAefPDBpR9effXVhw8fDiFs3rzZI3Y1cEhOlVSrBw/apSz2p+yAr1hqYxLbg3YZEEiwFr9+kLilup1dRiB1xBpHFUV3PmxnByeQ8meNA5IgkGhJNl0FoCECqWy6ClRJu3rQD0+WQIJEqB7InUCCPii6qRLDAW3a29nzCaTuWOOoEsMax7BsZ9dFIAEQBYFUhM6L7py6CkBDBFLBdBWoonqgKwIJyI4D2jQJJOhPt2uc7Wysuu2HZ7adFUidUsdRpfMzP4aielgvgQRAFARSKTosujPrKgANEUil0lWgiuqBDgkkIEcOaBMkkKBvXa1xtrNx66ofnt92ViB1TR1HFQ/apUr1MASBVBBrHBAzgUSz8usqAA0RSEXSVaBKbtWDfnhqBBLETfWQgvb74blVDyEEgQSDabHoduaXHtXDcARSBDQWAARSaRTdQLQEUnF6B/63ta5Clm1uoCECCeKlehiWfnhSBBIMyBpHlTbjPM/qQSDFwhrHCpz5JWNkZOSBV7seRNoEUomscUCEBBJNybWrADREIBXGD+5RJefqQT88HQIJBtfOGqd6SE07P+eXcfUgkKKhjqOKn2VOg+qhDgKpRNY4IEICiUZk3FUAGnJx1wOgRboKVMm/euj1xnzzp8AOCdal6TM/C2iamu6H5109CKSYeK6BKs78Yqd6qIlAKlSja1zeRRzQEIEEQBQEUjF0FahSyHZ2dmZGPzx+AgnWq7kzP9VDyprrh2dfPQikyLT4XIOj8oSYrHipHuojkKhZ9kUc0BCBVAZFHFXKqh78WEX0BBIMoYk1TvWQviZarCVUDwIpPuo4qjhGipHqoVYCqWjWOCAeAqkALRZxJXQVslHiZGk/xE0gwXDqXeO0gHJRb/uhkOpBIEVJHUcVLda4qB7qJpBKV+MaV0gRBzREIOVOEUeVcqsH7YeICSQYWl1rnOqBKuVUDwIpVuo4qjhGikUf1YPJGpRAop7bppwiDmiIQMrZ2JYtWkAsV3r1oP0QK4EEdRh+jev7AEkjKCHDT1ZR1YNAipj/NxLEyeMnzRBI+RoZmZ2ZaemlSirigIYIJKjJMDtav2+wZYm0H0qbLIEUt0RuG1pmsrqkX9cYgZQpFTeszrN28RFIUJ/1rXGqh4Ssa7LWt6MtcLIEUvR07ahissiPQMqRipsqJutCunaREUgpcNskZNDJckKekCEma9AdbZnVg0DiPAPdNmXeM/HQtSMzAik7Ku6EaK52Lsoz2mInSyAlIr7bpth7Zm3xTRY1UOo1TyDlxT1DlS2Pz6oeVqSAiIZASofbJiH9TFZN1YPJaoPmaisEUlJWX+aW3TPbt29vaCAJ3TPNXYQ1DDhZQ73Uqpk0sufoVYfv6eYiRGONb4OYJiuVO6sJAikXdVdwq9w2hd8zA1hpmVNuRyiCH64wWckH0gsvvPD00093PYoWVd42FrjiVRYQJqsGDdxcuqwrubjrAQxl9+7db7311gMPPND1QNq1kEnNJ9DS22ZhXbPADWz5ZDU5dwvzZbLWqcXJWry5FufIfIUQRnqJP5T13HPPffrpp3feeecFfz4+Pt710Jo1/e67X73Zq65q+uXe/dnBEIKjiPUxWQnpZLJCW/M1PT3dwqusW7aBBEBa0mvZPf/880eOHLn88st///vfdz0WAGqTXiDt3Llz586dXY8CgJol/5QdAHlI/gwJgDzYIQEQBYEEQBQEEgBRyDOQDhw4sGPHjl27dp06darrsbRqfn7+N7/5zS233HLzzTe/8sorxV6NTz755Cc/+cni+y3wCvz1r3/dsWPH9u3b//GPf5R5Eb744ouHH374pz/96S233DI1NVXgRbjg16otf+8xXo1edqampu64445er/f3v//97rvv7no4rXr55Zfvv//+Xq/30Ucf/eAHP/j8888LvBrz8/P333//D3/4w5MnT/aK/H748MMPb7vttrm5uffee++WW24p8yK8+uqr99xzT6/X++c///nzn/+8tIvwi1/84uqrr37qqacWPlz+3uO8GhnukKampiYnJ0MIExMTx44d63o4rfrWt771q1/9KoTwjW984+tf/3qZV+NPf/rTDTfc8J3vfGfhwwKvwOuvv37TTTdt2LDhu9/97qFDh8q8CJdffvm///3vf/3rX9PT09/85jdLuwjPPPPMww8/vPjh8vce59XIMJDOnDnz7W9/O4SwcePG0dHRc+fOdT2i9nzve9/bunXryZMnf/nLX951110XXXRRaVfj9ddf/+ijj2677bbFPyntCoQQTp8+ffz48dtuu+2mm2568cUXy7wIV1111caNG++4445HH310165dZV6ERcvfe5xXI73f1LCmzZs3nz59OoQwNzd39uzZTZs2dT2iVr344ot/+ctf9uzZc8011xR4NZ566qmPP/54586d77333q9//es//OEPpV2BEMKnn346Ojr6+OOP//e//73ppptuvPHGAi/Ck08+ed111913333/+c9/duzY8corrxR4ERYtf+9xXo0Md0jXX3/9whnmiRMntm3b1vVwWnX06NFXX3316aefXkijAq/Gn//857/97W/PP//8Nddc88c//vHKK68s7QqEEL7//e9//vnnIYRer3fRRRdddNFFBV6Ezz777IsvvgghzM/Pz83Nzc/PF3gRFi1/73FejQx3SBMTE+Pj47t37w4h7Nu3r+vhtOro0aPHjh27+eabFz48dOhQyVdjQYFX4Mc//vGbb765Y8eOXq/3u9/97mtf+1qBF+HOO+98+OGHd+zY8cUXX+zbt2/jxo0FXoRFy997nFfDrw4CIAoZtuwASJFAAiAKAgmAKAgkAKIgkACIgkACIAoCCYAoCCQAoiCQAIiCQAIgCgIJgCgIJACiIJAAiIJAAiAKAgmAKAgkAKIgkACIgkACIAoCCYAoCCQAoiCQAIiCQAIgCgIJgCgIJACiIJAAiIJAAiAKAgmAKAgkAKIgkACIgkACIAr/B4r3ltpmDJZrAAAAAElFTkSuQmCC\\n\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"t = linspace(0,6*pi,100);\\n\",\n    \"plot(sin(t))\\n\",\n    \"grid on\\n\",\n    \"hold on\\n\",\n    \"plot(cos(t), 'r')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAjAAAAGkCAIAAACgjIjwAABrLElEQVR42u29fXiU1Z3//5nJTBJCSHRRKjVfwGpJFJevF1l5WEwVCCSpvy1cu/SnV6mlutJeW2hXwICszZo0sBEiib3W/dELK1a77qVbbcXCEigPjSkP1uXhB4pN168h/hBEbDFEQkjCzO+Pz8zJmXPu+8w9j/c5M5/XxaVzP8ydM2fuOe/783A+xxMMBoEgCIIg3MbrdgMIgiAIAoAEiSAIgtAEEiSCIAhCC0iQCIIgCC0gQSIIgiC0gASJIAiC0AISJIIgCEILSJAIgiAILSBBIgiCILSABIkgCILQAhIkgiAIQgtIkAiCIAgtIEEiCIIgtIAEiSAIgtACEiSCIAhCC0iQCIIgCC0gQSIIgiC0gASJIAiC0AISJIIgCEILSJAIgiAILSBBIgiCILSABIkgCILQAhIkgiAIQgtIkAiCIAgtIEEiCIIgtIAEiSAIgtACEiSCIAhCC0iQCIIgCC0gQSIIgiC0gASJIAiC0AISJIIwj66urq6uLrdbQRBJxud2AwiCcASvQDfddFNHRwe/6XbrCCIJkCARhL4IIiQcZXvwNJIlwnRIkAhCL9QiZAmeRrJEmA4JEkFoAdOhuBWFZIkwHRIkgnCNOIyhqJAsEeZCgkQQaSUVIiTDy1JK/xBBJBESJIJIB65oA2U9EGZBgkQQqSI9xpATyI9HGAEJEkEkE31ESIZkidAcEiSCSAIGRWtIlghtIUEiiDjR2RiKCskSoSEkSAQRA0aLkAwl4xFaQYJEENHJ7CGbkvEITSBBIghrMswYcgL58Qh3IUEiiGGyUIRkSJYItyBBIrIdEiFLSJaI9EOCRGQpONSePn26oqLC7bboC8kSkU5IkIgsgoyh+KBkPCI9kCARGQ6JULKgZDwi1ZAgEZkJPc6nDvLjESmCBInIHMgYSickS0TSIUEizIZEyF2wzzs6OkpKSqj/iQQhQSKMhDxyWoFqRNYSkSAkSIQxkDGkOZSMRyQICRKhNSRCxkHJeETckCAR2kEilBlQ1gMRKyRIhC6Qq8c5XV1d586dc7sVjiBZIpxDgkS4CRlDzhH66vTp0wZJOMkS4QQSJCLdkAg5R91XxkVrKOuBUEOCRKQJGoacE2tfmWV/GKejRNogQSJSCBlDzkm8r8ySJRMbTKQaEiQiyZAIOScVfWXcKG9cg4nUQYJEJAfyyDkkPYJt3ChvXIOJVECCRMQPP7YCjSNKXBFs45IISJayHBIkIjbsHvAFcSJAG++lcUkExukokSxIkAhH0OjgEE1EyBKz7A/jdJRIHBIkwhadx1bdMEiwzZIlExtMxA0JEhEBiZBzjO4r40Z54xpMxAEJEmH2wJpmMqyvjBvljWswERMkSNmLQV4m18nsvjIuiYBkKVMhQcouMuwBP6VkW18Zl0RgnI4SUSFBynyybWBNBOorMM3+ME5HCQUkSBkLPTk6h/pKxixZMrHBhAwJUkZBD/jOwb46ffo0UF/ZY9wof9NNN3V1dRnUYIKHBMl4SIScY9lX1GlRMS5aY5yOEggJkqkYNDq4Cwl2sjAuWkOyZBwkSCZBY6tzSLBTh1kDvXHmXTZDgqQ7JELOob5KJ8JArznGmXfZCQmSptADnUNIhNwF+7yjowMM6X+zzLtsgwRJI2hsdQ4JtlaUlJRgehsY8o2QLOkJCZLLyCLU1dVFvxBLSLA1x7hoDcmSbpAguQANrM6hvjIO46I1xuloBmOAIL322ms9PT0PPfSQ2w1JFLrjnUN9lQGYZX8Yp6MZie6CtHjx4sOHD69YscLthsQJPeA7h/rKOV1dXefOnXO7FY4wS5ZMbHAmobsgvfDCCy+99NKVK1fcbkgM0MDqHOor5wh9dfr0aYPsSONGeeManBnoLkgGYdDo4C4kQs5R95VxXibjRnnjGmw6JEgJQWOrc0iwnRNrX5k1bhqXRGBW9xoNCVLMkAg5h/rKOYn3lVnjptHmnRENNhESJKfQjegQEiHnpKKvzJIl4xpsnI6ahQGCtGjRIrf+NI2tMUE/UYek4eHGrFGeGkwgBghSmiERco5QWJO6S4Er95VxXibjRnnjGqw5ZgtSaWlpZ2dnUi5l0I/WXewGVlOqPqcTTR5ujPMykY5mLWYLUmdnZ2lpKb6I4+2ajBdGYNDo4C4631RmjZtG66j+rdUTswUJwlLkXJZ0Hi90g/rKOQYJtnHjplkNNs680wrjBQnhZQkkZaKB1TnUV84xuq/MGuWNa7Bx5p0mZIggIUyHUJna2tpwk+6GqNADnUOMFiEZs0Z5ExuM7TSrwS6SUYLEwNgSff1qMmxsTSmZLdjGeZmMkyXjGuwWmSlIhB0kQs7Jtr4yzstEOpp5kCBlPtk2sCYC9RWYNm6SjmYSJEgZC93xzqG+kjFLlkAa6DXHOB1NDyRIGQU94DsH++r06dNAfWWPibLU1dVlVoPBqB5OKSRIxkMi5BzLvqJOi4pxgyY12FBIkEyFvEzOob5KCsYFP4wb5Y1rcNIhQTIJMoacQ32VIowLfpCOGgQJku7QwOoc6qt0QkkEaWiwQTqaFEiQNCXbbsS4IRFyF+zzjo4OMKT/zbI/jNPRBCFB0gg2tnZ1dWX8nZcgpgh24OOJfcErAFDgyfPe8Ee3m5MqSkpKzCqQY5Ysmdjg+CBBchn5AZ/UyA6zjKHAxxMBoC94pXBs9+dnx3tv+CPuyWBZMs7LZNwob1yDY4UEyR0M+tG6i1kixPjkoxvH3PjR52fHF47tBgDUJHzNXmQqxnmZjBvljWuwc7QQpJaWlvb29sLCwqampnHjxrH9V69e/eEPf3j8+PGcnJz6+vopU6a43dKEMHRsdQWjBVtQI4RpUuHYbjzB7WamHLPGTTLvdMB9QTp69OixY8e2bt164MCBtWvXbt68mR1qb2/v6enZvn37iRMnGhsb//M//9PtxsYMiZBzMqOvLNVIYMyNHyWoSV1dXefOnXP7szrCrHHTaPPOiAarcV+Qjhw5MnXqVAAoLy9funQpf2jMmDF//vOfP/nkk87Ozi984Qtut9QpmTGwpocM66tPPrqxwOt7u3vCeN9QoXQUjSR8EcfFhb46ffq0KYMmmCZLxjXYOB21w31BOn/+fFlZGQDk5eUVFxf39/fn5+fjoYkTJ+bl5T3wwAOffPLJpk2b3G5pFDLmISUNZGRffX52fIHXVzi2G7onWJ7wyUc3dg/57xx/Cs90YiSpBdu4p2OzRnlqcPpxX5CKiorOnDkDAAMDA729vUyNAOCnP/3pnXfeuWzZsp6envnz5//mN7/x+/1utzeCDHvATymZ3Ve/PTXxngndAPB294Q7x5+CsO+OnYCbY0IndAMAnB1vp0kxaYxxT8eko9RgO9wXpGnTpqH1c+LECUxbCAaDQ0NDfr9/cHAQzwkEAgMDA4FAwO3GAmT6wJpcsrmv+ECRpfAUju3+71MTx4Q3E+8rs4Yh0tF0Nlj/1iLuC1J5eXlpaenixYsBoKGhAQBOnjy5evXqbdu2PfTQQ2vWrJk/f/7Vq1cbGhry8vJcbKdBN6LrZFtf/fbUxHsm/BE48whBTcIXlm+8Z8Iff3tq4vjgziT2lXHDkFkNNlpH9W+t+4IEALW1tfzmpEmTtm3bBgCjRo165plnXGxYNj/gx0G26ZBDBDW6c/wpQbdG5t6V9Cxws4YhanB6WtvR0VFRUeF2W1RoIUhaQSLkHKGwJnWXzMnBkSfD9lP6IS8TNZinpKTE7SZEwWxBKi0t7ezsTMqlDPrRuoudYJtS9Tnp2Pnr2KHfnpqoeHvohFROlSUvEzXYFMwWpM7OztLSUnwRx9vJGHIOCXYSkb126cGscZPMuyzEbEGCsBQ5lyUSIedQX0UlqnkEYRtI7bVLvHaDc8waN40274hYMV6QEF6WwEqZDHrOchcSIed0dXWBx+1GxItZsmRcg3kdpfr9zskQQUKYDqEy0djqHBJsh/A3VbeniplHwmlRTSLeaxc2oT6K+q6kY9Yob2KDsZ1mNdhFMkqQGBhboq9fDQm2cywFu/tUSIp+e6nszoIP4ris4Oh790rJPW58OorWUIM1ITMFibCDRMg56r76t87Zk/IA5eS3J6vVgSL56G9PTXy7r6z2trawdZULAEtL9/5b5+ylpXtd+bymR2vMarD+rXUFEqSswKAfrbs4F+xPBwvvKY2QH6Y6UT1veMLbJ6sBQpL2dveE9Pvr7DBr3DRaR/VvbZohQcpYyBhyTiKC3Xyyuva2NufnWwrPneNPNbzztXvc7gce48ZNs9LbjDPv0gMJUkZBIuQc7KvTp09D7H3121MTAcrk/QrziM2QZUdrb2sTxOy3pyYuLf2ji147GRNlCRPbjGiwceZdqiFBMh4SIedY9lVyO02dmKCJUy5WTJQlarCJkCCZChn7zkluX/321MT2z8ueuP0Ny6OfDhZamjj/1jn708Gye+wv+8TtbzS88zU4NRFA04JjxnmZjBvljWtw0iFBMgkyhpyTnr4SfG4N73ztidvf+LfO2XFf8J4Jf4RTE7Xy2gkY52UiHTUIEiTdIRFyThr6CkNE7e98LaZ3MYFBxWL75TCSQZiYRADmDPTG6WhSIEHSlGy7ERMhnX317pWS9khRkUlwOhEaSan+IMmCLbQDhtyrZtkfxulogpAgaQQbWKn4VVTcMhwPfHbzxJHn8HVKjRudvXYyJSUlZhXIMUuWTGxwfJAguYw8sJIa2eG693LRW0temvZsg42/rsHGcnIuLZjX8MTtb9wz4Y/PvrVkafo/YWIYN2hSg3WDBMkdyCPnENdFKD7cLQLkLsYFP4wb5Y1rsHO0EKSWlpb29vbCwsKmpqZx48bxh371q1/97Gc/u3LlSkNDw7Rp09xuaUIYOra6grbDWUO0AJKAIEvMBmJ7FHkNRkuaccEP0lEdcF+Qjh49euzYsa1btx44cGDt2rWbN29mhz7++OP/+I//ePXVVz/88MMVK1Zs3brV7cbGDImQczTvK8FfZ5nwnbbGdHV1nTt3zu0ucYRZ4ybpqLu4L0hHjhyZOnUqAJSXly9dGuE2/93vfldVVeX3+2+++Waz1Chj7o9Uo7kIJUJ8XjtmQr007dlFkWEkoa9Onz5tyqAJpsmScQ02TkftcF+Qzp8/X1ZWBgB5eXnFxcX9/f35+fl46MyZM3/84x8XLlzY29u7bNmyv/mbv3G7sSoyeGxNOoYKdprNIAD4t87ZX819Dl/LfWXc07FZozw1OP24L0hFRUVnzpwBgIGBgd7eXqZGAHDlypXi4uJnnnnm4sWLVVVVlZWVI0aMcLu9EZAIOcfovuL9dc0nqwGgL5Ab9V0HPrtZzpSTw0hqovaVcU/HpKPUYDvcF6Rp06Zt2rQJAE6cODFlyhQACAaDQ0NDfr//L//yL/ft24d7cnJycnJy3G4sgOEDa5rJvL7C0NGcfSv2zGphumIpMKhh+F/1NfsCuShyCc5qMmsYMlpH9W+tiQ0GHQSpvLy8tLR08eLFANDQ0AAAJ0+eXL169bZt2+bOnXvo0KH58+cHg8Ef/ehHubnRn0lTh0EPdK6TkX3V8M7XfvNx2e8qNyT9sk/c/gYqHMoSrh4LAKhnEGMgyrhhyKwGG23e6Y/7ggQAtbW1/OakSZO2bdsGADk5OfX19S42LPMe8FOKQb/SOJDVKFbnm4ycAg4AzSer79q9KkHlM2uUN67Bhpp3HR0dmjdVC0HSChIh5wiPXZnaXYveWjJx5Lnu3mvlQ3aa5MRTZydmtbe1bT2zKiktN2uUpwanmpISTVc2YZgtSKWlpZ2dnUm5VGY/3ScXy74yxSeQOOheY5t/vPSFWK/gxLRiJyRe9MFoL5P+rTWxwdpitiB1dnaWlpbiizjeTsaQc7K5ryaOPPfE7W/85mNrq6W791qFPWSZ17DorSXdvWVP3K76o6H1+iBmtbPDUC8T6WhWYbYgQViKnMtSNg+ssUJ9BSF/HSQe1FGzZ1aLYHghqGd/fU0y/5ZZ46bpOkrEhPGChPCyBFbKZNBzlruQCMkozCNEMIPUASQ8etfu6FEiZiQtLd07te2ffl/9L0n8UGbJknEN5nWU6vc7J0MECWE6hMpEY6tzSLDtOPbxjfymYMekyHL6XeUGvHJYk1KFWaO8iQ3GdprVYBfJKEFiYGyJvn41JNjpgbefnGTfpR+K1lCDNSEzBYmwg0TIOV1dXf/X8RfenV/v5GSmOg4lh9lAUc984vY3Jm2tH5mXcjEzOlqjf2tNbHD6IUHKCgx6+HUXUbCPA6TMLxcTv6/+l6lt/5Sev2XWuEnmXSZBgpSxkDHknPiGs1iFSm3i2CXauYVZ46Zg3umPcTqaHkiQMgoSIedgX50+fRps+mrRW0sAVBkNAs79dXGw6K0lANenv5fMkiUIZxCY0mDj3KSphgQpE6DnLIdYCrZdpx37+EaHAaSoxKFVlkEmt3IiTJQlarCJkCCZChlDzklEsGPyy/3PheudH3Ke1wBhSVNcPw0Y52UybpQ3rsFJhwTJJEiEnJNgX8n+OgFLLbl0JddyBuvUtn+6dCX+xVPenV8/aWv9HTekoduiY5yXiXTUIEiQdIdEyDkp7auoGQeTtta/O78+1blw+sxkMqtGjtE6qn9rkwUJkqYY9EDnOqnoqyQGkJyjTrQLrdenGWyhHTDkXjVroDfOvEsQEiSNYLcdFb+KSkqNIeavS8oMJObEQxMqwau5G0ayo6SkxKwCOSbKkkENjhsSJJeRB1ZSIzvS5r3c/+6XR47uc/vjWmQ96GkkMcwa5anBGkKC5A7ZY4Mnjrt9NWffCnxx5erwj0W2nJj1gyUVHFbmdp5oh3kN+Cf0CSNZYpyXybhR3rgGO0cLQWppaWlvby8sLGxqaho3bpxw9PPPP//bv/3bn/70p/Ihs6D0BOdo0ld5OUMY0ZmwZcOph1bF4cGLY9kIdfbE/1y4/svXnnerQ5xjnJeJdFQH3Beko0ePHjt2bOvWrQcOHFi7du3mzZv5o8FgsK6ubnBw0O1mxokmA6sRaNJXE7ZsGDm679359XftXnW6ayzMGj4U08yhOLhr9yoA3+8qNzCzTP6F/r76XyZs2dA1xozcNjBt3CQddRf3BenIkSNTp04FgPLy8qVLlwpHf/KTn8ycOfOzzz5zu5mxkTH3R6rRRIRk7tq96nTX9aeW1Ar7UZNS9BdR6iZs2XDqoZCFNGffCksJvOmmm06fPm3KoAmmyZJxDTZOR+1wX5DOnz9fVlYGAHl5ecXFxf39/fn5+Xjod7/73ccff/wP//AP27dvd7uZ0dF2bNUQ0wVbbSSxMJLgr+PjQAJ2hteeWS0Tnm2W90/YsuHnX55h3NOxWaM8NTj9uC9IRUVFZ86cAYCBgYHe3l6mRgDw3HPPXbhw4b777nv//fd/8IMf/PjHPx4/frzb7Y2ARMg5BvXVtSP7fle5wVIJAOB01/WCriSYzx3VDSifMOaLn7HXxj0dGzdoUoPThvuCNG3atE2bNgHAiRMnpkyZAgDBYHBoaMjv9z///PN4zoMPPtjQ0KBPUoNBz6TuYpAIIRhAkneeeiglbjoAuHCp4NInI9XnoJ/w3fkb1Mpn1jBE5h01WMZ9QSovLy8tLV28eDEANDQ0AMDJkydXr169bds2t5sWgXFjq4sYNMpYEjVtQeF8Y8SRX6du0l27VwEUAMCph1ZN2LLhATh4qqJCPtOsYcho887EBmuO+4IEALW1EaHjSZMmCWrETKU0QyIUEwb9ShVc/qAIACY82yxnNDjH4QKvqGp2vsFEMEuWjGuwoTra0dGheVO1ECStIBFyjvDYlQHdNXJ03+WeIsUJslDFFEDiTSu7N6IBJDsJf1e5YdLW4fP5MJIdZo3y1OBUU1JS4nYTomC2IJWWlnZ2diblUpnxdJ8eLPvKFJ+AgglbNnh7ij5YvsLJyVG9dp+cuSbpLbz8QVEcCRRGe5n0b62JDdYWswWps7OztLQUX8TxdjKGnJO1fRVfRsOELVGiUM515dSSWjv/YUxtM9TLRDqaVZgtSBCWIueylLUDaxxkW19F9dcJoJGU+N9VSI7AB8tXfKm1BcJuPSdeOxmzxk2jdVT/1uqG8YKERJUlg56zXCc7+2rClg0jR4dfx5LRYGfo2IWCIOF5S0lZxsK4cdOsBvOtpfr9zskQQUJ4WYLse8BPBOorJySYeqchZo3yxjUY14gya6Uod8koQUKYLNHXr4ZEiGfk6L7LHzjNaGBc/qBINoPUoZ1Lfyrw9iT0uwu7CgtiWupCgVmjPDU4g8lAQSIUkAjFREprNChQuPtSByURUINdhwQpKzBolHEFjMpgvoBzvtTa8sHyFVET6hJHznpg+RRJTy43OonAuAbr39o0Q4KUsZAx5JyrR4thfuh1EgNFsqGDm7EqHw8m2qFrccKWDf5P/CnqE7PGTUFH9cc4HU0PJEgZBYmQc7CvTp8+jZtslLfDTqgE1YnP1eY885sRmpn7UP2Xn2z9n8eWp6iXzJIlCOcRmNJg4+zRVEOClAnQc5ZDurq6vrHmlwAQ8Hu8g8Hw7t9DmdftpsXDpT8V4ItpD7R4B4P4oQ6+vDLpf8hEWaIGmwgJkqmQMeSEaQ+0AAA/WLPxGg8BQM/Nnj/UL5fdaElPK2AX5N1uiZD/Ychf99bPhy/FPpcMf1ocGOdlMm6UN67BSYcEySRIhOyYcf9GAAj4PWwPipAwUvODNTtUVt/Kdjr3m1kqShI1zGGi3YQtG/zgn7Blw9hdOaHP9fJKCMsS+4y4KWgVsxFjMqqM8zIZN8ob1+AkQoJkAAY9k6YHlB/gFSj8glegGfdvnHH/RhxtZ9y/Eb1yB19eyXYmC4V4pDSB+w/1y8vqW/9Qv/zLT7YefDkijIT9wBRIsI1wP+s9S52OilkL7ZB5ZwQkSJpCxhCPqECcJQThMZSdw0Dtwf28AsmaxJs7lmnciafeJShLfNaDpcdPVtkZ92986+WVcregNh98eaVgRYFkRPLdawdbaAdMuFGNNu+MaHCCkCBpBLvtqPgVCCIUdr7xw6UQwGeWEHvBds5c+JRwcaZJE7ZsyIfhzOmR/8f37pMhU+O2H7ams1ZQHIl2CHrteJXlPzvfLYI2sy5F9yZI4oT7WZ+ji8/SuCwpKTGrQI5Z9odxOho3JEjuIzz+ZLMasVCQIDb45O4dDL4lGQHy+CibRPtffXTmwqf2v/qofGZ+mZ9lNEx4tnlk+Bdx2w9bT65dDrHYRgobKG7zCM01J++dsGXDqZdXyZ8dUTgqsauFoworasb9G1mOonBBs0Z5arCGkCC5A3nkGLxPiU+BswxsCOMmG0nZRexMIoGZC5/yAniHggChhO8Jzzbz5hEDDRdhp+wxw1iR808dNdFuwrPNBd3+kCiGruyJellffyDgszht5sKnDr76qKw6wBlSvIElW1HD1+KsVZbE+B9Nf8uOG+dlMm6UN67BztFCkFpaWtrb2wsLC5uamsaNG8f2BwKBurq6EydODA4OrlixYu7cuW63NCFIhBiCCLHxThAh+aHe8klf3iObRGwPahUemrBlQ/6HAACBwqunltROeqwVrFAcckKsWoX6d2pJ7W0/bGVXAIBJj1m7EPH6/k/8FQuaO16vBQDhs7NN3mtn2bczFz4V8HlkQ4pZURDp8WMW7f3//CvhZOO8TKSjOuC+IB09evTYsWNbt249cODA2rVrN2/ezA7t3r27r6/vjTfeOHfu3IIFC2bPnp2Tk+N2e2ODRIhHyE2Qo+VyWMhOk/hNAGBjsRpLx92XWlugUPWuSY+1Xv5CEKJhV8Xny0+25vc7LfDDS87JtcuZ5xCR40yYaAfjAABYD/B6LHxk2QaSO4c/ahmOEq6GsJgTH3Z66+crzBo3jdZR/VsbFfcF6ciRI1OnTgWA8vLypUuX8oe++MUvfve73wWA0aNHjxo1yu2WxoBBz1lpgEUd5LAQvhZCFApNYqOhrz/AK1DH67WCJgmDMu65+94ISyX/Q/8f6pdPXt56vDXRzIWy+lbIT7SjvJ/nKJx47z65fNJjraeerJ3wbPOp5bW8xw+NJD5SJdiCPBULmg++XmtnRUGkI9TCWhoK7rfy/nnD+sSHnQRXqkHjplkDvXHmnR3uC9L58+fLysoAIC8vr7i4uL+/Pz8/9Mu+/fbbAaC7u7uhoeHhhx/W3DwiY0hAGIwUYSH+XfI4KIeIAKBiQTNEQx6U27evuvveDe3bo+QICHYJRIZ87GI///PY8kTKyn2ptWXEuehRIgjbSV6I8nPwDgVlq5HJtsKKYn3uHRLtQtn7J3wvIISduKlOLA/ClFEezJQlgxos474gFRUVnTlzBgAGBgZ6e3uZGiG//vWvX3311ZUrV06ePNntllpAIiQzXDRBmnfJnprVfrmD0uyZgy+vFAwg2SQS9qBi5V4O7Nu52rKdd3y/FUbDl1pbCsEDAJMea5UzGtIM2kBOmnFqSa1c64j3Gd5974aO7auELrI0IsHeioJIrZK9fxhzEt6L351cMIJVi0Bb2aBB0yxZMrHBDPcFadq0aZs2bQKAEydOTJkyBQCCweDQ0JDf79+7d++ePXu2bNmim22UAaZx0sGipRCZpABWuQl2CiTokOCUcw5KEXvvrKr1vCYJRlLhh57jrSoBYAoRXwE6tJn46kQMJ1aXgsIPI5SA99qxDyjLtoDvciDgFxWFfwufDCLoFr/Hcp4ThL99y9xxfMHS8/T/KRk3yhvXYNBBkMrLy0tLSxcvXgwADQ0NAHDy5MnVq1dv27Zt7969b7/9dk1NDZ65devWESNGuNVOMoYskav4sEdgdo5CgfgrsKdytsn/oagmEXuXQxnrHw0DxcHcHkdeMjVYv0dxAqvxk7yOBwjLGLu4/xP/4JhBwSfJesmuZ2TLUjgtqhpB2ISFfK8iAVLIHcf/43OMQQaTcdEasyo8uS9IAFBbG/EDmDRp0rZt2wBg7dq17jaMREiBECQAx7kJTIGEB+r4FIh/b8frtbOq1guH9u1cbWkkwZ0xL22HNo3ihPjCSArzSE60UzDyI+jv9wMMCvvt+s2hIXX3vRv2b1/FO/dkfWJv59PKwcpaCthUHcRKuGbJEphjf7AKT5o3VQtB0g2DHn9cAccmbzh4cNCqYJqlF65iQfMQ9xDtXG8UCA46WX4s6fmSf6A4+MHyFZOXi860qALg3LfmRJziXofieOvyyctbhbdfzQc5ZWPO7KaOvWsEy8nSkOJ7UjhNyFe0a5Vcu4ghPKPIk23Zu0wZ5cE0t1hJSYnbTYiC2YJUWlra2dmZlEuRMeSEkLr4PMLKDvIMFQQLBPB7eDMoqgIpjCQ2es6Z3bRn7xp1swWVmlW1Hibm8ic4z2hIiosvbtRZD8f+dfkd32+94/utx/41Ht9g7sWhoRFRgrW5vVeHRoiLGcqpEwfD1pKdPlmWJmLZmJT1kLWYLUidnZ2lpaX4Io63kwg5h+VTWYcEEL/HdzmgDjaoiSpRqEP8OXv2rhE0SWEkoUNv387VmGUweXmrw4wGRm5P9IiRc+SUCueJdgh6EXPtqwqxzuGzOeTcd3Yaf8gyRV6wpRTfl6XjDqKVJuInMJEsZRtmCxKEpci5LJEIOQf7KrTmd/i5WNAhOYlOrUCC5Dg0kvhNAJgzuymOj8NU6o7vt47shz/UW/jr4sBOnwR/nWVew0BxdFGMiiKyJUh1KHgGoJiJxXRLViPWgUyKQHLxCd8mpkrysmS3TAZE3loYahKsJTDhN0uylAjGCxISVZYMuqFdh/WVZSZ31DRuISnLrtI2w1Ki+BNyLw6pnXJRjSQ0jPw9A2noPed5DahPSRFF4HTx0o2q09q3r5Ll3FK3ok4f9l0OCO47u2lPdh5dy+J4LPFBmDptVq0HXpayuX5/rGSIICG8LAEZQ7Eg9NXMhU8NjfCC38NWxBEiRolokuUMVrUIOQkU2cGUad70xqgnqzMamDWTihzuRBCMJAwjWXZaZcW6PR2PR+1P/8VBwe1p6QXl3XdRE1LYxDK57gZim/UQaS2BUbKEamRKg10nowQJYbJEX78aO8FG8RCeXoW5jWgzYTEYRsQjsM8jrAERsenzzKpaj8/XzAsnKJCi5bJJZGck4Qvcs+tQ3bzpjbsO1fWPhpEfDV9NhxoNChSZ35hohxp57UkPhPMawEbCKyvW7e54XNgpn8lOYyIkq5HsvlP77vhNnLQ0lO9V5IjbLchkorUE5MdzTAYKEqFG4b0MZS74PNMeaAEuj85ueQjBFyeMQYLbR37idp7hLeuNGtQzf9/QrkN1wiEMIB1+dnkcGQ0yDgNIzt8YFUXWA++1G/2uo/5U96pdeoi8M/fikCLTQb1pqUZC1sPwBCZjrSUgWXIACVJWENV7iU+swOXROanGrfbFCaEI9QwhYXCMOlbanYBShPstfXSCeRQf6soLGEZK9G8kxp69awR7SNjEDpTfKJzmZF4X/0VYZjoo4HPE2U67VQRla4ktvGRQkJhkSYE38UsQetLFcROHfCaqEa5kA2EpeuvnK/CfdzAoDBb8JivQGSvMpeYQuwGUB0dGNjiij44/QTaYnJN4Olxo7aJI8wjdbvxpaAPFevHDzy7nhRYdd2p8PVc8gwF+j+zTmze9Ufim1PrU8XotWkssKKg2jxgHX17p6w+w9Af27+DLK3lrCe9GrI+H0U28G9ntbUqNHNZaUxqcHshCyihizeOoWNCMPjpcrwik0qhgla1rt1IORDOSYsKhkcRvVpXXJ9J7zov0qLnj+60jE79KXJTVt+aHTbRj//o4ExjL6JFzFHaSHPxTWEsKcRJS8lggU677ji+Y5TTtgRbeTOdHef3tD+PMu1RDgpQJxHdDz7h/o9fnwZ89Xw5VnqsIAOD3CEPDcK6U0nHHI4xrwmZ8gSL+/J2H66vK63cermd7WCIDbpbVt478KCKAFHdGQ9z1UlOdoRfKa7gRAGB3x+OVFevwhXAa6yiFaPFdJyeJQLTsR0yVtEvDU2Tl8asu4aZcHgKtecx9CIQzaHhZAnPcYsZVxksdJEimkmBS+8yFT4HPE/B5WLhYnvEKUiYuLzwR9TR9nrvv3TA8anBr5CRiJAkk3SRSoHnqnR0ok7ikmEPlQ9FyYj/5ewauFqhGDEt9Gp7LXORj94xCnBRL2YK0thYy4/6NWEZEONksWTKxwUmHBMkkkjKzCp9YA/lekGYsRp1gxMOeefHo3fdu4MeCObObBorCd5ffwzQpJiPJMm6kNoni4LYfhsItnqFELhMBminx1ZSTcZj5zcMSK3w9/UG/WKFO6DRLTeLNIwb7RmRzVr0JkfUdgBMh52rE13RgCQ6YEQoA3sEgRjT/vfnv+L9r3ChvXIOTCAmSASTRxTxz4VNegKH8kCkTKvtvtVqrZcRIUXZBtoT4R+DKinVYtAYAvOHSCQx+0ytNQhLGterJdW3Hbae4qr12f6hfXr5kONo/6bHWolMBPixhZxhZDvr5f7JogFqH8v8EOf2JfIEAjuvdsRwHJ7Lt6+m3VCAGO4pfR0zVm3hx4uvhhp6NuClrdmpkWdMBAIQp22isf7P2NfkWNS5ak52yRIKkKakoM1GxoDmQH+GLPyjVEAMITfUQVqe2jBgpwkXyEzSvVcLYx2/KQ2fiNhAyc+FT/dfmHH42NI7jmM4vzoS94dBZV76k9dizyTSDosIsObvMi8PPLi9f0vqHZ0O5fCPOByzFW+5Pdhr7ItTiBAC+nitDxXlsM6p5ZHnIF7nA/MyFT/EZm+hPxtd2ieAQ6cTDhyd8o3coaCdLYM5Ab5yOJggJkkaw2y4Vxa8whQF/pZbreKrLpAoRIxZD5jVJES5yHqiI1Qvn8Px50xuhJLTc8OTlrVfzANVI9kbGl3WdCLLbjbeBsDHFnCV32w9bi08F1Ne84/utIwA+vvsvhF5S95WQA8L3ntp9p2iJw0SVWVXr94fFib+L+JoOACAY9OzuxXTwgN/Du+8UeRNm2R/G6WjckCC5j/D4k3Q1mlW1PuDzeEd4UYrQ524ZHFaUpJMjRu3hVUT5FAYeRdac3cDnhLbjjTF57arK6z0A3p5LTJCKu4bUMzeLTgUujU3+FD00p3ifYVSYLPEpjifXLkfvIgBYGnN/qF9+x/dbhRlj2C3yyUJnOvlqWPdauu8cmkdC9dt9Nmokh5fktSoYvPE0c+FTgXyvusKeWbJkYoNjhQTJHdJW+LViQbPX5xkYlQPccnny7Pdh/B5WpO7gyyv32zjo0BjaHx44WApDR1w5dcIgKChK3JkLOP7iG/FTlC9pnby8tdjBe+2SBdTwHrzE8xrUzkNmP1muqTfy7FV5p7fnUrAgP9ZmOHHf7Txcz2TJznfnxFSKqkYAwG5OsPE2h27vVx+dufAptK4ss3IYxo3yxjXYObpXamhpaZk/f/6iRYs+/PBDt9uSKM5LJySL0LxXgIMvr2TOOn72O+/x8A4Gh6szDAXx+Ro98hULmqOWY+h4vRYVK+D3sPwFHjYnJulYPvujhjmUMfWYpVAmVsw0KjGJ0+TlrUWnArwaWa4TDwDvPrn8ah5YrmGBDVN/cbKtWXPrGrnChdyx8iarkcGUSaFAduaRJUJ2A1+7gd23AMDuXpY7ym5+oZa8JcaVTjCuwU7Q2kI6evTosWPHtm7deuDAgbVr127evNntFsWDWwHJObObAn/hx0VrMPDDphzJS84gQjbdQS6AFCoR5PNYRoyYdw4PDefUjchJs9eOWUU14x8RDpUvaR0sjO6vYyiMpPIlrSw5IlYw9SDutyO8c/XdJ5crBtxLY0MWVM0ttTveb4ZoaYoIr0nOv6PqyXV7jjeCVQ5e3M46WY3Ya4jMu4tw5XH9g49lUVfHQIxLIsgwa0lrQTpy5MjUqVMBoLy8fOnSpW43JwZcX4rp7ns3wIgcVKOAz+MdCkI4p9YyoyFE2F9n6azbHx4gcOUI9c+7nfPmsdC3IrUhQa8dM5Isz7Gs5RPVk+MWqIKW9lDUdzG1Y1+ffB0m55bm0Y73QlrC0u34E+zMIwGcszxUnMeUKeCP4oxhasTKWaFtx+faARdLCxX/BgApMSe0x++Z9kCL73JgPxruPo96oUge45IIjNNRO7QWpPPnz5eVlQFAXl5ecXFxf39/fn7MHvC04boIMWZVrfcCDIzKQTcd+x3a5cvydYMAYObCp0I/e59HHrX3v/oorhxRsaCZn/HKpzDwwoNj03CMIdrAFCvVk0Ma5u3p3dH9NNu/o/vpmvGP4J6RZ6/uf/VRHLKjem/4jyxXPlWgcMpF9dcxa4zZZIopyc7BXDvgzCME1Sjq22tuqd31frPDAJ4sb8wkwisIFVrxRcA37ODFr4Zfm5FXKct4kmzry6UXMbsBDznXJMQs+8M4HZXRWpCKiorOnDkDAAMDA729vRqqkT4ihMyb3jhYnBvweYZGeL1DwY7Xa3E6EQqMUCJInFEY/jELs1/x6XI/l9GA5RU6dq4GgLvv3eAwiwFHmerJdcORJL+Xt4qcO/GqyuvBn4NDKhsEZR9dslCnNiiSF5JbryFqI+0cjHd8v3Ws1VsU5hGPXcq4QqgsD7F1e+WpTrzdzIwqtRrZPV2F4EovsplzaOXHkXRjliyZ2GCG1oI0bdq0TZs2AcCJEyemTJnidnOG0dM0RjUCgPbtq5iPQvbXQbhGcsRvOHLdM8s1yMHKEd++fRWLGLU7qI4qeIoqK9YJTqHhTX+OkKrANnGwYwYQwptEPOivm1W1/rhN5FxtiBR3DQkhn8QjQHYkuMIFapLf6hBvHiGenl47BUJ4o8ouZZyhiEvx4mT5wCGoEd4/UdXIcnlZQaXwNBZAPSiZ9TFh3ChvXINBc0EqLy8vLS1dvHgxADQ0NLjbGN2MIYE5s5uGRud5h4L7dq5G8WAWkuUTJb/6uJ2/Dt/LB5BwnZuO12uFGnT488bAFe7hvXaKCNDujsf5YVHwLAkCY6k3ClCi4Gvj2R5+em9yA0iJ+OsYcauRXckMNNFGnBdn0bKeZJ2vFicA8H76WeC6a9j3GKt5JGCpTOqnGd7Wh/D9jMum8GWugLvVBYnCLmKJoPEV/DUuWiM0WHN0T/uura194YUXXnjhhQkTJqT/r6c/UTs+5sxu8gwG2revGhrhnVW1fv+rj/JqxC8qI6x7xn607AR8L+7H3CQIj3f4wnc5wC+/Blw+d/v2Vfkf90WtcqYIYOx4v7nmluFRNaQozjbtGHn2av+1OVFPY/2ThkwHTD0Qdvo/j/IuIfPbMhH8eOvywULAi/NrJ9rlpu94r6nmVgsNEJ4MEEyjl02lZJlHDCHBAUsKBXwetogfTmPwDgXf+vkKXKaP/4dLTQq3PYRvY8wFD/g9TnLB7eDXAzRirMfWnj592u2GREFrC8ktDHr8AYB50xs9fu/ujscrFjRjcTDeXycU9bJebIKbTgiczx0ncOCgxj+5sCLN8gwSHLBCaXXOjKQkYue1S5CoidrOZyPZUb6kteB8coqNH29dzqcPyG0TXZ3vNUU1j/i34FfpGbxqeWbi5hGqEau7uv/VR2X3neU8WWGBc5BTG3weX1in8Ykt6hSoqJjlFispKXG7CVHQ3UJSU1pamqxLWRpDbn++6FSV1wf83qsFvllV61GNQj+8ywFUFKZGzDBiC5Mzrx0/nZCVp0Qd6ni9Fq/ArCW2UBsODfhamPSKcyQdFoS2e0h39N5oRtLguOv7r80p+nAgvnFH9oPZKZPsFmP7LYsmyDAzlGE3GTYOovgMP+vlDVNL84jH++lnzMxNinnEqxHaLrkXhzper1WrkTDLG29jZieBlU2JhRvQEY1qJBSejw+zrCWdMdtC6uzsRE3q7OyM4+2ah4WiMm96Y6DAf7XAl9M3dLXAF/LX7VzNfsOWQWAhmARcDX/Z587y6/aH5WffztUsgLRv5+rKinXCYyYzhvbsXcNy6gS3jGJmK3rt2IAoGD2J2ECWUZak+OgwaBf321ORJSFfE0NZcu/VjF224+wzYK9DdpE8pklOAksMS2UaGpGDeTH+i4NMokBKbQhVoA/b/YERXpDz68KzkUL7w+l2B7m53ij8PnwxImkP5WZZS3pitiBBWIpikiWzPHJ2zJveiLZRTt/QldG5EC7mz6uRZRAY/B7m1mA/ZsyvY8WScZjGZ3ZhtGU/ZkboMbPAJ8cDmPBUVqyDAn/6vXaXv5AnnxOHCCWlvEJKUSwFcuxfl8+4f+PIoaCT60Q1j3jajjfWjH+krftpu9JN+NrORwd+75zZTb6eK+2Ri6kL2Q14B6KfjQXG5KxRiJyNJPjrhnPtXl7Z8XotLnDMXNwOi3c4gWQpEYwXJCSqLJluDPFUldfjGqCoRgDA/A/4M2NT3DEIJLvdLacigb3PHcKPqMw2YgEkdNbt63gcABSl6nCgqSq3rqfgJIxhh53NVDP+kcFx1/eXFRx+drlDt0wi1pLlPFbcY1lNjilcinQudOVwOHDkR/27Ox5XmEcgZZSwblQkOrJNrNWEaXh4KOjPwQx+oeJDwO/F+8Tf048msiBmgvuOLUvBjCTLrFG8k4XIqOXCkvgb2b99Fb7AyyYeTBLgZSkVq8lkKhkiSAgvS5BZIsSonlwXLMgFgF2H6lj8hlejqEFgNmkDHJQOYsWShR8tbgpt8/X040Mun8LAe+d2Hq7HB3A2szVFXjs8obJiXf6Fq3GPNcKDs2VqXJpxWL4hZLOOyxX2D467Xv3G4Gc9npEFcTtF2XMGfwUs9xB6feuaXe81ARd5YveJYF6jGrHbDL8LZuWANMsbQVliXTTtgRa2ziRL1cEajDMXPgUjvL7Lgfbtq/AOcbheV0xgYAn/Cxk0CqUOs5MaLOns7ERl0jlROz6qJ9cFCnKxLNisqvU5fUOoRgGfZ1bV+vbtq5yokZNiySxlFk9mwfaKBc0YqQKAfTtXz5veOKtqPctoaDveiJoUtao3q8NdPbkO/yWS2oDUjH8E/+3ofjp4oQcAvIOBmOrEOEG2ZqJWo+HTrwUSNI/UWQ+Cgspn8uYRY0f30yxVxKF55BAnRvCc2U0YT/JfHGTPQKw6Ksv2xtwc+e4VuuWtn69g0xj4VJ327asw62dohBcA9u1cPWd209UCX4qq0QNlPTgmoyykzGbe9EYvwK5DoTQBllCAtRj2hQv5CBM4WBCYXWd4+rpVsWQ+uyEQ6XNv5/x17Gr4MM5P89kddt9FjRhhBAIHterJdR4A1CSHvjs+v6666MG2i8/zRysr1vFPW5ZTYmP10eVfcJQvFzdyHCjBinZMk9hDg6UIhfrwuu+0fRoqqO9wjhcjwiSKNI/kiJSdeYRqhLU/mN3vZJa3WOo7/FAll65n0xhw4MPCjOiaxjs5FXYSg8JLUSFBMoN50xu9fQOYHeAdDIT8dQW+nL6hfR2Po8kiT+DAZSNAqr/Cz0YSfsx87gP67lDbMCWpI1zFDgcLrD6371Ad+yUzB93ujscxYrTzcD3vtRPccYy2443D6V63rgG/LyKe4fcL46OgQNVFD0Zc7eLzMxc+NfL05eR+C7m9VxX2kCAeToQkzVkSl27M935hAr5WKBMSvNDjuXZ4LcPUmUdMjXw9V/bsrefVCANIvL8On7Es/XUQLhPM8uuYv04oO4LahnvwrwyNyJkzu2nf3jVJyQJXQ7KkgARJd/CX7O0bCBTkMiOJ93qzABJO4MDEIeBEyK5SMgCw7FjL7AZ0wWPaN6YksTTZnL4hPjaDjRFajhEj55l1O84+g6Mkjlz8AztEUyA7hADSjPs3jjrVZ+nmEvTDYeZVrNWjeZJub1km2h1+djmf5Dbi3BVLKRJ6G2F2kpOIncVrZ+ZRMJxrx98n6BmO8NdxFhJEeiCFunZvRZbCYkYVdk5H5DSGgM/THtYkdAPEvUxXTJAsWZKBMaRMAtUIM5S8fQMAEPB7501v5NUo4PPMmd3Uvn0V1vVxqEbCPNlpD7SgOLHiKzPu3+gdDLLUBu9QcGiE1zsYmt++u+Nx1CS2khtGj0CqDIQJDsFwcW4BhWuo7dPN1dd9x65n2i4+z2uSsFlZsW7k6cvCsMIkh9VMshMnS5KbiIXfReqexy2nfOLHZ8KveDuTfxZSSoV5VFmxrnpyHVtqFsLWEq5vAmHPM++vwxtVUftKiKuxAB5+dlaFiM3y9g4FQ6WBt69Cb6F6wdzkwseWKLwEJEjaUnPrmurJdUG/r3pyHTrrhorzA34v+ut4NfJdvoq/ZzZiOlEjPrUBtQfFCfegF55FkrxDQaZJEDaPmCbhW1hGg/xZ+BQGsEkvjoogOWqE6UcVC5qH8r2CAw0fhIXhLCqKDAUewd5y+C4nxFe+YebCpzCMdOnG/JkLn9px9hle7C3NI57ghR5MGJEPxWceVVasu1rgZ9EatJbwrq6sWMfUFO89jGXif7F4nVC/ji9eh53Dv2awsiP7uemxANC+fRW/LBMmOKRNk8DAynipg1x2OlJz65qg3+cZHAKAoN8XKMitnly3+3gjjqGVFeswI2gfN6edVyP2X5ZWBFYrb8qpDcDNcsd5sm+FNQkAhvK9ub1X58xuwiJ1mMuAYwfzcoSC58Whlav4iJGnp3dH99Pq9bOdPLzbgYolpDYgIz+4iH/U0hvDl4hOEIc5CIk4+mSvY6wuphHnrkDYALXUIdk7yjadePAEBPMIZx35ey7teL9ZuBmwAlYOAC5J7LscYCunyDcqSAtLgjSRLvRGrqIj82qioc/Cou07V0PYPmMxrfT47njIj0eCpBcszQx/xpjnjRYSr0aY8A3hWYT4A8YAEozwdkSuQsbbSYLNhCUY2M9YXk4Gl4LGqne+/gAADBT5mCYxXWRr5aFwglWJM/T8tHU/XT25DgrymVAp5hUJg6YgOXYKhOkMLNJWsaBZXr9cYN70Rt8NMS//mIiu2KFItGPfzrzpjfxAPG96o+V4zYMm2ohIA4s5RdXmEc+O7qerix4Uaq7jC7V5hHdI0J/D5qKxQ8w82hcWA7yTccnjoXwvuwkty6fyH9wuuQ4AQnOPOKcQPkthWJQ9z7GaI3s6HndYjDHpZLMskctOI1CEUIeCfl/NrWvajjcyNcLo0e6Ox1kkY87spoDfy0qdYgBJiGkr1Airr+K/mQufQtcHP6jha3wORc9JICxO6N/Yt3P11QIfWK0o4enrt3PQtR1vbDveGPysp+aWWtl3h0ZSIt2IFoD8kdXwtU3ld8UUQErFGhaCl1WA+VeH8i1+0XJQhNnNshQpzCO2iYGl0IpK4elf8t+tuXUN2vr4dOLp6eXVSFinkc2qxjLBAIC33MGXV+J8I+ZS5pPrDr68Et13/Mw5fi0V9knZ3CMWQGLfOysTjF5ovKsrK9bt2btGvSxhSslOJx5ZSFrA5oTii7ZIC6l6cl2gOH93x+M4rDCXQsDvtZxhbrnapiLXzrKqEMKmvrNydjjk+S5fHSzy80+1gL6jcIY36pBgJ4k1F95vBoCaW2oxq9uJkSQetbKZdl98HjtqaIS34/VaSyehpTdGUQ6OR1hON1b49wrrHFpSsaB51Mf9TnxHKFfs8woXx2ZXVqyDG/NZA6ryF+3sf8nO1amGf1d10YOeMdfh40Xwsx7P9aPxBq4Zu6wNU/ltvt+q8vqrBX5fTz9OaZg3vRGKcwGg/1ofxiwt1X249GL4Fh120IU7DW/Ug9KXha/RqdAhlwkOl8LC+d2707JsioJss5ZIkFwGf8OhoTly+c550xsh7K+D8BhaWbEu6PfOm96451AdcAVX2NATkxrxdSoR5pcXnkPZHu9QMOD3DEEOahKE8+t84Sdx/hE9ZDkVWHjDmNKEnpfDjiB1fEIRKILwsIgdVXPrmo7IzK70hATskg7ikzH84mINsKtl9eDLK/EGQzWCyISRqOaR3WWZF676uu+EbmMpHCiYR4IaeQcDg8W5ADAwKgcAAj4PW04CAEJBTZvljgQHHZZ1gHChLL5oEHNlh2zisL9udzgyysoEz5veqIMmgYHL1MYNuezcoeaWWnRo7Hi/ecf7zaHX4TJf6K/bdaiOVyOsShn0e4UcWbBRIwivOM4vu4kKxP7LMo6ASwTHTSzNwucy4VgQ8HkCPg+m27VvX1VVXo/5dag9uw6FTDoIO+vQQeckrW64aE2ur2bsMvbP7vzqogdxGMUX8T3mQ6RQyYsSgY2/zk5dKivWjfyo3+5vxaRJdroiuOBkj5zlpwCA/a8+yvIPhbe0XXz+6ufR1qzlEMyj4ddW5qyleVRVXu/tucTqeqDvFwAGRuWgpw59ccCt18VW8ELsMrz5HsCqjL7LAbz5h0Z4mbcZk8v5Zb1w/75wgsOuQ3XewQAmBLrou2NkQzIeWUjpI2JxblZu8pZa8Ie+BcFfx06urFgHfm9O3yA+pjFTiVcj/JmxhZmj+p2ExSlAml3I78FxAWPLmIYHAP1/4a+sWJeDAYDwfwFg16E6i4jCpcv4dMx77Xh3HDN98BB7eAeAmrHLqvIXeQrDqQm5/rner+cUFrJBcK73678J/AI7avf7zVhhD40ydVKfJSM/uHhlbKH6nCSmccs49Bw6uQj7eaNo8QZiwO/dHe5hBjOVZEs0Vr0frrsR/rp58yjoz/FyiXaVFev8PQMBv7f/Wh/GKWfcvxE4jxwSmocQDmQidgkdfDfyttHd927A1/KyXsw2GjaPwv2mgyAxMtiPp4UgtbS0tLe3FxYWNjU1jRs3ju0PBAJ1dXUnTpwYHBxcsWLF3Llz3W5pbFhWC42QIn4z0l8H+AwbTvhmTgN+WGGPdbwjwiHCc7oQE5bza4Gvr+wPxZMufyFvxDnI6RscKs739fQPFeczARCjR2efqRm7zPn0o539LzFN2nH2mar8Rfxz91zv1y0HR//ZzwBgsDh3387VilKt6U/ntet2BbwmyXLiBEs7af+rj6Iw1Ny6hs92Y6KOHStM+VKIU1TzSADVCLMb2B5vQW7A70XrTUjmlgvSv/XzFYKhWbGgOfRoxc1zsOtqLO+ND3DMQcSyvVkRLOxzfBYEgJ2H6+N4uEkpGSlL7gvS0aNHjx07tnXr1gMHDqxdu3bz5uEbevfu3X19fW+88ca5c+cWLFgwe/bsnJycBP5UutnxXpOc/xr6Hfp9vBRBuKJo9eQ68PswN2mXtKwqs40A4GqBL4mFA4T1ZO0SwYGLJ6M+Xboxv+ATr6/nCnAVPNEMEtK7gctisPThKOJDvD4BwG8Cv2ADqLCJUXG5NEDSRYjP5WOwiSyWb7GsrWeX1xC3hcRXDux4vVZRRG5w7DX4gu9M5Ornn+cUFlp+HU5MJUvzKFiQXz25ztPT29b9NN4V1ZPr8FHmUskIVqEOIkVIWFECkQNyctknnNXAHAa8kcT6/O57NwidjzXsmfuBZesAwC77ZY5dJMNkyX1BOnLkyNSpUwGgvLx86dKl/KEvfvGL3/3udwFg9OjRo0aNcrulMcA8vP/Pb75nkdkcTmGAwSGFv06o+sXCSKmrRgySMoHkyuPXUsIRpG9MLozJHflRPxpzTIGYqSR/fExh2NH9tDqJLiYqK9b5HZhHApZCxYuEpVrMm964m/OaCuzmMg95MHE/qi7Oqlo/8mwM4Zy4+8ru4/P6xDx4lteJyTzii7sjqEY9t10D3KqvEJ6dDTYTjGQEJydfrQ77M2Qp+j2CLwFfYwSL5YvythH2z65DddWT65jHQjdNggzKenA/qeH8+fMlJSUAkJeXV1xc3N8/HBC+/fbby8rKuru7v/Od7zz88MOam0ddHPxSTJi2gOew1zW31MLg0I73m3HiEQDgC1mN5k1vxMU3dx2qQ+92ej6OUCiMLyCGJ2DWAwCgtXTpxnwcWbDxrEgdy2gQJhjhCYo1DtAqsttEq4jf9J/9bMf7zfl/OMt2xjF2pG64Se6TRNS8Bh7Link73mvyf/p5zqcXBfNI2MRkB5Y2Eqt5BH5/zS211dd9h/cThHyGt9ReujH/wv++Fndi/Sq2rBG799i7FCkMYJ/HwY6y/AU+qYGdgJtsSSRMZ9jd8Tg+QwAAzgjkc3Y0JAOyHlyzkF555ZW2trYxY8aMHz/+zJkzADAwMNDb25ufH5Ei/Otf//rVV19duXLl5MmT3e4raxw+lQzrENj66yIT7XIwjrrL1XxTiLSZ7Fx5zFqacf9G+Ksbrvnvj3F9IwTnwPJDEu+dqxn/COYstH26WZ3VrQC7ER/A1QvBOfTdOZkhJJAUycE/mtwhL/RZwoEoFIOQQTn2mt3v/0LxXkGfWGaj8E0J5hF7zghlMVz3HYjMtZu58KnAX90AUsRIWL8DpJJOEZtcxAgA9nN2Em8z8V9l+/ZVc2Y3hcrWhafW7Q7PPcIvkf8ed3c8HrKNwi67Xccbwdligy5irh/PNUG677777rvvPgA4fPjwpk2bAODEiRNTpkwBgGAwODQ05Pf79+7du2fPni1btuhmG8W9OLqgQwzcxDntEK6w4vanFLGLKgGX9YCy9OcZY72DweKTwPvlam6ptSxVt6P7acxZCJX7zPWzQ0LoSBVJGhy6el1Rztk/WbY8uQGkOK7mUKvYuNkmhSviy2tg4KDsl/bv7njcMrUh6mZ10YOQ62cVWj3+3GHzN9eHFYZC+RGRWoWPLBDOkWGwRYymPdDiuxzAzG88JKcw8AE2fmVkL1cyVQHz2rG1j/kOEfx17LtAlx2etkNKhdUQE2XJ/RhSeXl5aWnp4sWLAaChoQEATp48uXr16m3btu3du/ftt9+uqanBM7du3TpixAi32hm3CFmiuJXR4+fWx4yKIEuWWQ8AEPB7em67BuCa4Y+MNYRGhr5B/hFbUBrM6sbXntxc3lMHAMLmXO/XfV/4ArtsTKiH+KhGkl2sSH0oDUSsiBgeOgUnFUu+GBx7DSqNczUCgKuff842q/IXtfVvZq93StnkAFAz/pE/f2WcEAdi0wm8g0FhESNFCoNdWjyewE/FY+LUwX2Ve/auwQqQwC27zBK+WecAAFaOYJq0i4uJahhGskMIL2mO+4IEALW1EffWpEmTtm3bBgBr1651t2HJFaFMQlEhW7CWQtPsK0vZk7ITpxx/QtSBcsfZZ+ZNb8w5+yfeX5fmAJJD+bE0dJhUJDFt0hJ/z4Cwp+bWNbvfa8JudH4d/ivgFYi95s2jnsrSGfdvhBn/iy+7gKjLLjhMkbfTJzbjFQvs8hVUBVj2Cp/UgCFbwV8XmuV96xrMhq2eXLdp60NgwuCALezo6NC9qcEMZeLEiXG/94MwrrTcrb8bH2+++eabb745/b6n2D/hhOn3PTX1mxvxHx6tGvXt6huWVt+wFF+zM+flfYO9rvQs5C+i2Ky+YWn1zY/Onfaj6nH/GAwGq8sew/1Vf/lDds7caT8SXlhu8m8JXbzsMfVb5ty1VngR9ZBwBeSeeU8Ke+TGyG/k9yg+C+uTYDCIvRQMBqtvfpS1Db8L7FjsW0WHC4fYt8Z/fVWjvo03A/vq2T92juWtwm/+9d81Kzbvmr/BbvMrX11v2bFz7lp7z7wncc/sWf8if1Nzp/1ozl1rcZP1J/bk3Gk/4nuYdSm+UAwXWv2ctWqMJVpYSHFTWlra2dmZlEuRMeScjo4O9rqiogIADlZUgE38ma+Dh8VgvF+9HffXjF3mGWm9NITsQVIftS4PwRXISdFkWHddczzOg0z8af5PI/LLsWMFa0nxRVg66GbcvxG+ers6jRusMrnFMoCROQvAFSnHo3b1LCynHEHk7Ffwe5njTu5DNh8Wwv5PlssQ9PuAm56BHlEA2PFek1nRGj0xW5A6OztLS0vxRRxvJxFyjixCMoIfT173D514zJXnvfsmCEeM2i4+L0SSeOz0qWbsMhg5IvhZjzzTNlCQG6qyGk6jEBKjheFb9tfx68fHgXOtmje9Mb+nT9iZxLwGIQKP18lhh8Yu23H2mZpbaoc+OIVdjacxWbLzlwrOuosLpoS+4nC+5VvSUibyXCLZ6yucgDee3S3HpzAMR4yizSlGfZo3vRFXPNrDfVPYObsP1QEA1toHzl/HL1SGE9jlHiZZSgSzBQnCUhSTLGXA9LH04ESEZA6+vLJ6ch2bkwQ2lfHY2jYXF83Ac4r/6x1MYcBhzq4cAxsoMZ0h+FlP26eb0Txig4Xn/IVd0rKzKE6hkIDjYd2JDCiERz6UYL6cQ9qilRXgF/OtuXUNXLrs+9IEedFxeb6XcELIDPp6OW4qVs/jdyJOVo3CG4/disJ9aKk9FQuacQ4sAPA16yDyKYF9EXNmN4HVlHNFfl1bWN1Dq2zgrINbane832xibps+GC9ISFRZImPIOXY/fudguUxLUwm4VdLBavyCyDw6tfuo5pZa+GyAN49wBGEpyHyWOf86PrvHUkgUtYJiumZ60ohxPvKu7qeZkRTaH1npR3gUwD3ecMbjxQVTAAAWTOGdciAVjJczXwo+GfB/2hdH5gi7FdUGE/Ji60L2GxemHFmCjruq8nr8HndLTwzsCxL8dSBZn0zjeVnSPG9WKzJEkBBeloBEKBbiM4YU4DDtHQz0TiiQZzsK1lKI8MSUz7jHbdlThxL1m8Avam6p5c0jxOFgh8VgFCfIPi6FTYNFXe36IfHOVCD7IcGZ/ceKO4Tq3t66Bj7rhZEjWPeyM9ke5nRF8MHioJVfjv9DBZ8M4NKrnsGrnr5+2QiLCd5gcnKjClOOAIDP8Oa/2Z3hdY8sJyEBpz0Kfx1bH5nJEqoRGUwOyShBQpgs0devJukiJJDTNxj054w61TdYnKu2liwP4eN2YNEM4TGcjZU73m9mEzNrbl0T/OjjUOkHae6tDK5kalebPCb4BUQE/J9+LlfX5Ynbd8eER/iwuBlSqbCXyfYL+vQie82PqlX5i6ryFwUGBj7/v6cDQGDRDAhXeRcKK/AT0QRf3N33bvBfHMTlu1CNgv6ctsTUiBGrLEFkSj1meAMAn+TNjqJWsYRvvn4d76/jy/MDfxv4fSDV8ic/nkMyUJAINYl75Byy83B9za1rrhYX+HsG9u1cPWd2U9+YiCFSsJaEJ2vLGZRsT2j9UDSPCkbseK9JWDEB7P11jKiBFp6kB36iXtCyeU5soJCLaewyNovTsrIAKnrbp5tZz+BXEAhbqAjvVgWr6j74Iv/CEIvWzJve6Pd7d3c8Pmd2Ey4Lm9MHSS8+EocsIUycUJZYQc+d3OKwfOdXT66T58Pu4BLtcI+qtP97TUCy5AASpKwg1caQHfijvVpcUFVe7wMoiCzxIJhEB19eicsGgn1pIogcH6c90AJfGYcv3nJsHvGEFlmPhl31Uj4vQBjuQ+FuqyWgLK/mpBqNt2/Ac/6Cww/ICjWJa1NxayTirNWQI+6vruffbhkWgkhj6ODLK0OJanvXQHgWKpalRzXy9VzBRco9ff2QGuKWJYisyIDfy06rBctxMixz1lVPrvMMDslfGfPXRXwLLG0EN99rIllSQIKUsbglQgKYOY3LZ0B4CLNcSoCfnK9ekIl/F8vWC+2v/NKwpXW39a89qmhZCgPv4EoKsdpbQr6Gc0Ki6/exngl8ZVwoqYSbLQSOw0IHX15ZsaA59+IQTuXhKxIxNcJNVKMkOuvsEJLxYhroWWtDTwn+HL7fZGcdCMl1/Doy+F+Uq8ilOPk9QNaSDSRImUbaPHLO8fYN4E8dwwl7DtfPmd2EkxxRgfjXiGWVvNDVBoOygcViUViySLSiAKDyS3JeH+I5fwGuibLaVqiOuDIgFHF+ZJQ7wUi+on6aUK+W35z2QAv71PC/rwXZuAzXkbMLC0HkrDI2EXXO7CYo8vFWEb7w9wywBSSrJ9ftOd5YWbEubZWCu7q6cCEbiNdgYo8IwwuW+3PkpAawMmdt/XWROiSQMesYJQsSpExAE2PIDnzS9PT1z5veuOtwPdOkPXvXyFKEzFz41MFXHwWriAVuyuF01brXkYbUW2y8BgAA7903BfyeOLKuIxbDjaX8c80ttTmDg867zlKK2NK93rtvGjZ9/B4UIe9g0CvJuZM6cqxL8Zq+/gCKEKoROuggslIcAMyb3ugH2BVetDBkzN1S6x8chIGhmHo1JuwyaVnpNojrF8EraFV5/bBT1++z0yT25MF77Xa83+ykqilrORlMnmAw6HYbUkISqwqlGYezFjQXIRn0bFy9rsgzeBUAhorz8BFbLqMp7MHh0s7Lx69TwL8FX1geCkjZYsCN7/xOfg/WBuWP/sXBsxHrznFpV1GfnXe83yxXlxCyNgDgmv/3U/is98+VXxI+hYUJKO0HyfMJ9kuvWvpI+do86KPjS2UDFzSCsHlRWbEOfXTenkvBgvzE87xlYp3OEbcsWcICSNYMDgmfN45JSKmTJf1nRJEgaYf6ptHQI+ccTHDYdagO48b43zmzm/r/wg+c+042mGbcv9E7FLTTLTlbz9Koskzqkw8Jnj3LkBVDNsVkVZNh5prlfuHKltpp+S67wjxy1ylK+LD9gknERIgJEvrocCdTo90dj1eV14fUqKdXUNxESNCvlVxZiqnZ8TU4FbJEguQamSRIxhlDdtSMXQbXjOI1CZ0hg9cVKNx3/Aps7KisW2qrCGwK1dgdEiY/yfuFo0I9JHbUydDPX5zpmcKl5uSTCp/LsruEfLmIEFEY1B4mQrJ5BOH8dSxk0Ha8MTQHNhlqlPS57emXpQQ1ILmypL8gUQxJUzJGhHgw5J6DS1xfdw2E18bFeR6F/py+/yUW/+a9RmyZHEsrytcfCPg8duEouYin5YxOdsgL1qAnDaxm+IJkXYEy1iXLjNc+Id6yBJyl8w24CJwC71Bwxv0bCz4JmThzZjflhqVI8MvJVbEx5r/vcD1YqVHoOcPvh7hIaYEVdWU8Dcm6ZDy3179IFYmsh+QWuLbQBx988Oabb7rdlhRSXfZY9c2PVo/7x3lTnggGg/hfXHVm3pQn+IVthDVvEGFdHOFMxSI6/HI7wtI7Tg4Jqz3Jp+EeeZkf+b3Cfvmo5cUtP7hl8yzPZDv/+u+a//rvmu+Z9yS/JpDda35z9qx/mTflCfy++CWmqssew6+vetw/4jfLFlhyjiuLkOEvLqV/IomfKPEu0n89JBIk93kzDNvj4vKA6QE1CYe2YKQmBcPqYqlGloeETX7kFd4eVTNilRPLo4Ju8ZpheWWF0ggXt1Ma+cp2Z7L9dqpj95pJUVBSI/zuUI2qRi/hF11U8wGHw7ekgpTKUio+Wtw9pv+oQoLkDm9y2J2jw281dVSNXoJP08GwIAVt7CSGpfFkZ0VZjshBGzVSvyWOqynWz7V8rbZ+hMbIm1FNSeEjxKRGKEXsOwqGBan65kdlNWIr0tqhiQjJpEiWUvcx4+hD3fpchgQpfTgRIUs0/PUmBVxFu3rcPzL3HTOSZE2Sx9y75m+wHIgVh3CnPPrbGVX8OG73rqi2iIClVtn9XYXSCH9CIczooOP3OxckwYoNSmrEvjX2eGGJniIkk3RZSvVHjqlX9e9/LQRp48aNX/va177xjW90d3fLR3t7e+fOnWt5SIE+ghSfCMkY8XuOFaZJgpEUjNQky9H2K19drzakFJImWA/8aVEVKCiJgfMr4E61QRNVZu6av0EdSGObuCdWNar6yx/iP7ZfMI8cqpG2xlBUkvWbDaZLAxx2sv5fhPuCdOTIkQceeCAYDO7fv3/JkiXC0UAg8Mgjj9xzzz1mCVLcxlBUTPx5q2F+HjSVgpzjLqg0g77y1fXBaPEkhaTFYd+o32L5RuceNru/a/mJnLs0g0pBEkJEvA7xIsSbR6FniLLHgsEgJi/wcSNzRciSxH/C6eyHqN2u/5fi/jyk55577vLly8uWLbty5cr06dOPHj3KH920adP111+/ffv2hoaGcePGOb9s+uchpTNRO5PSQKvyF3lycz3XFmMVagAIFo/CYjmYQ8xnfjPuvncDW3uNnWB5ZsWCZrBZ69oyfRwvHvB7YnqL3SG2U5hlJTcV99h9BDzEfxDFhwWAER9bV9fGMhkymKvNahTxFa/xNX41OLUoVFp07DLI9QUv9ECuf9PbobzwzLgnBRKZvZT+qT+KGcT6z0Ny30Jqamr61a9+ha/vvvvuy5cvs0MdHR3//M//HAwGv/3tb2trIaXIEnJCxjyHzsv7RtWobzM7KRi2lpgrD40hhrAZdGBI2e2Xj7I9llGroL11YveH7Owt5zkaQQcmkd0elhEX6moruwex89HNm/JE6Eu5+VHcU132WPUNS6vH/WPVqG9XjV6SGTdhVOL7mbvYOfL4oP835drE2FdeeaWtrW3MmDHjx48/c+YMAAwMDPT29ubn57NznnvuuQsXLtx3333vv//+D37wgx//+Mfjx493W8EBtJm1mjGlgnf2vwQA1UUPssXI2Zo9NeMfqRn/SAFnEvG2EcN3OWB55VlV69t3rpbfYnkRxX7gLBLZjmGbMbWNGT3A2T2WRlLFgmY2IdcOvJRgGAlrAMor/TDszKOa8Y948etgKz/h+hdh26jt082OvmPzSWThJVcwclKt24oY/O///u+///u/xxcPP/xwMBgMBAIDAwP8OTpYSKkLCyWLDDCYMBrBm0pBzmb6ylfXW1ohGCMRIiXCHv6NdvaWpeElvJA3hUPOLx50YA/xlp/iCvhfwRgKJmYesZBe6Fu4+VH8gtiXwl5nIc7HAU1+kqYE9twXpGAwuGHDhm9961vf+ta3urq6gsHgO++8c++99/InuChImouQjBG3nQLZfce/kFWH38kflc+089HhTjuHmzqDXD5kp3x2vkHLT2R5cbuWs9ME+VGokbApqBGTouH+xxmvo5eEshhGfbvSszCY9TgZHLT6MWrVGEu0EKRUkIgg6W8MRcVcWfrggw8qPQurRn0bE7eiapLlpuUoH7SPJ90z70m7tygOqaNWiugU/zqmiytiaYmbRyxuJ3Q4qlEwGKy+Yem8vG/My/tGkIhEMVZo9TPUqjGWmF1cNYmpdJqEhZKFWe5joZ7mbwK/AIDqogerix6E8Gqt7IT8P5zlVynFF4x9O1fzK2rzzJnd5PVbFE3Fi1i+S32oY+dquQEA0L59lSIWBZGhpn1WF5lVtd7yl8lf+e57N4z4/3qH144ryOXPdBg9wqCdhy2JKy3RVF30IAaKasYuC1y4EBgYwG+H4DEuvKQt7qd9J0hpaSkAyLLkRKsyTITs0FaWoqZjzPV+PaewEF+3XXyeDZc14x/pLxsLALIYAEBlxbqg3ysUqOZX8ZFHf0t54zftDlkKEgqYZdvuvncDAMhaxV+Qvdfy4ngF4SI1t64RTrtaXJDz6UW2WFxVeb3308/k9vAixKtRzfhHghd6AADVqCp/EQD85L216u+LAEmWtMq01qox1rhtoiWHiRMnCj46hcvOdHdcfGgS1Yxj4iS67/Af77izdHbNuWttUCpGIOxRhJosw1HqQ86vgDvltgWd5WWwPXzIB2F1E0KbLD/75kdD//j0hGivMZ87GAxWjV5i6aPT4UbSHDbCaNVRWjXGkgwRJISXJUGQMiAslCzSP5okZfY+BpaCnD6h9vDwexTrKQSVoSY7qXOiGU60ylKQgtHyNdimczUKbUZW9FGrEevbYFiNFN8IyVJU3nzzzV/84hdut2IY/b+vjBIkZGIYEiEFqR5NUlFChiU7sEI1vALJ+oRDv51FoshisGuA+i1qo4o/amnAye2XLxKMzIgLSmoUVAqSWpyY3geDQefJCyRLMsKdr88opP83ZXZSg5qHH34YrMJLBKQs6yGls3QxnD7X+3XAYDvA7ovPV1as293xuOX5wsqnPDl9Q3Z/JadvyPKalRXrcmzess8mu4ElRFjGkxiskXafBS+S/38+5aevWsKmr4Y2pSQF4RB2IwC0XXwee/Xq55/P9X7deeaCWekzqUOx0C2LJ1HWQ3TcVsTkMJHD8pDbDdSaxJehdCVAVelZiP/m3LXW0ryYO+1HlvvZToXTTzikeAvujGrfCPDLsFr+Ics9YmZ2XOYRH5MLhk0itD4TnF2UbdZSfHe+i9aS/t+OwRYS5tchCjMID9kl4xEQVwkixfNg2mAGk2f/Mc/UyZbn7O54XGFCCTg5U74g25TfXlmxbp9NA9B6wxcOmyRkwQEADAxhIZ8dZ58Be/MIzSDPtcWCPQRxmUQKMqaWlZoEPyDliKtwWxHTCllLTlA88WmSqiejnhaqCDUlYi05P2RpP9llN1j+XXm1ISyawF5X37AUiykM/5PMoCBnD7EkkdSh562SyGdJ+idKs7Wk/9eRXYKEkCw5gf32TFnhhlcgWZ9wcI/V4WZ3yO5qTjSM3yO30/LiajUKciXmQpuc0jBNYk65NFf90f/OUbc8De1Pmyzp/0Vo57J77bXXenp6HnroIdxsaWlpb28vLCxsamqKaT0kBbwTD8iPZwVzShgUrN51qA7LEwhFChh2HjnvYEBxWcu32HkCHe5X+wbxZN973dXXfceylnbN2GXoo7OkuuhBwSMH4UwQtj+dGJf1kH6XI+/Eg+z24+klSIsXLz58+PCKFStw8+jRo8eOHdu6deuBAwfWrl27eXMyC90zHaLwEsPup2jKaKJQo5y+waDfIkuOaZjlod02F5w3vdGiBlEYtd7wR+UGY0t2h/dUX/cdGBiESJkR4HWLxYTYUU0q/WguSzrERCkZDzQsHfTSSy9duXIFLST1YrLJJWtlyflPUdvRRECu28b2yOrC9sjCwDbtDtlpFQDYmWhgZXIpLiiYOwAQHBhQfHYjas1pciPpIEIKUiFL+pcO0stCEjh//nxZWRkA5OXlFRcX9/f388v3JZesSsaL76eYATlUgkXCv+YP2ZlZircIRy2v4B0M2F1WfgvKD1MjrCYXCKuRNzcXwgsbGoeLN5LmIsSTncl4WgtSUVGR3WKyKSKzZSkpQwB7rybPuTI7D9fzRpJdoWs71ZH3R41OqS8InNlk2Ri8sufYH1B1gBMe3vkG2vjfkkI6byRzn6KyTpbczqoQ+fd///fnnnsOX8uLyaaTzEjGS3WmkLY5VLjkj7DwDzJ32o8s09uCNmlv6kO4X5F3rl4oz66R2UbSbyRTskOdk3gJIv27QmsLqby8vLS0dPHixQDQ0NCQ5r9ubjJeOv0S2garBTuJx9tnHYapnly363ijZXme6sl1dlkMdpYTy5VQGFVgb8BlG0m5kQzyyMVBVmQ9uK2IxqC5waTD86CGT6NybWy2Rzhkt199CHda7g/aG1XMJCLbyJJYbyTX73xXiMNa0r+LSJBiQzdZ0vCnqFV77FTH+SHFaUEHMmanVfOmPEFqpEZ9b+vwBKYDMcmS/n1FghQP7sqSET9FfVoYn+ljJyf8W+KTNNyDaqRJF2mOcUVD0o9DWdK/37Sbh2QQ6UzGM9c5rkN4qXpyHQBYLtygPhTTW9j5whvVm5p0kc6Ye/OnmaixJZqHlMmkIUfc3HRVhg5ZD23HG2tutSiqXXPrGo/NWxSHPIPWaym1HW+01Ko2LlHCUuQyYIJX0rETIRJvBRlQgogspOSQxGS8DH4edHc0qbl1zY73miw37Q4J+9WHcCcAyPtBaYpp1UsuknlFQ9xFNpj0t5AohpRk4gsvZZVz3MWPyVa0s1jazuYQv2n3Gjdxj3xl3GmX3aBhL6WZuO/87OmiRODDS/p3F1lIKcGhHy+bvTRuPeTaGTFo8djZPZaH7Kwl9aYRvZRqkugGyOYfkXPQWiopKdG8l0iQUoilLGWwRy4O0jya4J/73lc3x+Rti+OQ2rMXX7NNv1tSfednRi+lCByLfvrTnz788MM6z/EnQUo5eCu0tbXhJv1gLEndaGI5DiYlaMQSJWKVMd26KHWk//HLxF5KHZaxbZ1rdZIgpRD+btD5JtCHJI4mUW0v5oiDSNngFcjuEChzIiBJhlF8n0sHXG9kNssSG3ZAOeDoWRSNBCnJqO8GPW8C3Yh7NIn1edxONqL66OSjChnTrZdS2h5Ek1bp1kWpw6EIKd6ryYhEgpQcYlUarW4CPXE4miQ4DtbcUgsAO95vlvfU3FLL72eHhPOHj6ZLiuLopZT+dUTbcT9TZSkREbK7musjEgmSm2hyE+iMelV1SNJAg9pjKU64KRwStEp+oyu9lLYx13WPXJa02ZLM9rKQILkPyZIT+IdxSMGwYicq6v2Ii1Ikd1GKBlwjjCHnH8Ssj5BcY0hnSJCcEggE7rzzzuLiYgC44447Wlpaknt9kiVLhHEw1aMJLzOIbCFpKEU8qUgMSdYF9UF/WcoeEeIhQXLKRx99tHbt2k2bNqX0r2S2Pe6QqONgymXJqvBdiMEhDUVIJhEPVcZ4txx+Uq0+pm4jwGuvvdbT0/PQQw/hZktLS3t7e2FhYVNT07hx45L+50iQnLJ///6f/OQnY8aM8fv93/ve91LxZfBkocEU6zio4WiiIenJDTEa128kbY2hxYsXHz58eMWKFShIR48ebW1tffHFFw8cOPCzn/1s8+bNSf+LJEhO+f3vf3/kyJFvfvObhw4dam5u3rlzZxr+aMbLUuLjoOujiRFY9lI2i5BMmu1CbUVI4KWXXrpy5QoK0nPPPXf58uVly5ZduXJl+vTpR48eTfqfo+UnnDJ16tSpU6cCQGVl5bp16y5cuHDttdem+o+mYYWL9JPccZDWbnCC0Ev8TgJhvZHSRxzdPHIxcf78+bKyMgDIy8srLi7u7+/Pz89P7p8gQXLKiy++ODAw8PDDD3d3dweDwWuuuSZtfzozZCmlmpGe0cRcBCkC6iJ7kr6ClynGUFSKiorOnDkDAAMDA729vUlXIyBBcs6CBQtWr179X//1X4FAYOPGjR6PJ/FrxoSJspR+p5AO6wFqgrrzqYvUJHgjZYwI8UybNg2zuk6cODFlypRU/AmKIRmJzoa/PpGJLBxzY+18cnU6wfmNpPMPMz74GBIANDc3v/POOwDQ0NAwYcKEpP85EiSz0cdg0nZoywZZSrzzs6GXEsSuizLSGHILEqRMwC1Z0scYcthUzRsZxydCkvW5Mq+Xkg52UXV1NdtDIpRESJAyh/TIkkEipGi8cS0X2p/Sj0CyZIlgCenjnMgkSJAyjRT9Tkwfyi0/jimfxZXON6uLUoc6LESylFxIkDKTpPxOjDaGnH9APT+aJp2fYQ8iDok1LESylCxIkDKZOHJ+NBkH04k+sqRz5+vTSyki8dwEkqXEIUHKCtQ/FZ3HwbTh4oBrkBWSebKU9ETt0tJS0qS4IUHKIgRZMmgcTBtp6xOjHwJMlyVK1NYWEqTsgv0U29razB1Q0kAqxlyjRcju45jyQUiEjIAEKfOx/CmSv9sJSRlzM9sS1VyWMq90QmZDgpSxOPkp0s/VCXGMuRlmDDn/vDp8WN2MoVQvNp1JkCBlJrFGVslgikpUWco2EVJ0Qvo/vm4ixJOexaYzAxIkYhiSpagIAy6JkCVpkyUjTPw0LzZtNCRIhAjJUlQ6OjoAoKSkhERIQYpkSWdjyBJXFps2FBIkU2lpaWlvby8sLGxqakrFMxfJkoClMaR5SF8HktJFxomQHbNmzfrlL3+ZhsWmDYUW6DOSo0ePHjt2bOvWrQcOHFi7du3mzZuT/idMXA8w6UT1yNF6gFGJu4syRoRcXGzaOMhCMpLnnnvu8uXLy5Ytu3LlyvTp048ePZrSP2eEpz6JxJczRrIUFScdm3k328WLF1evXn3u3LlAIFBXV1deXu52i/SFLCQjOX/+fFlZGQDk5eUVFxf39/enYn17RjbMXko8PYGspajYuTozxhiypKioiFLsHEKCZCRFRUVnzpwBgIGBgd7e3pSqEU+G+fFSkSNHsuSEm266KbNFiIgPEiQjmTZtGj5znThxYsqUKWn+66bLUhpmcfKylNI/ZByyR660tJQKkhIIxZBMpbm5+Z133gGAhoaGCRMmuNUMU2TJ3QlDWW4wOTGGTLmRiJRCgkQkAT1HE91mrWaVLMXnkcu8jAYiJkiQiKShw2iimwjZtVDPtiVOsu4BPR9xiFRDgkQkn/SPJsZFazJJlig9gUgWJEhEqki1LOlvDDn8CCY2nkSISAUkSERqSa4sZYAIKT6U/p9IB68skcGQIBHpIEFZMmjITgQ9DSZ9jKFU128kXIcEiUgfMclSRhpDzj+4ux9ZHxFiHD16tLW19cUXXzxw4MDPfvazVNRvJFyHBIlINwq3T9aKkEz6ZUlDEeJJc/1GwhWoUgORbuTKeFnikYuJtJUgMiUslOb6jYQrkCAR7sDGQZpxoiBFJYg0N4Yscat+I5FOSJCI9KEYB0mWFCRlPUATRYjH3fqNRHqgGBKRcpw7hUiWnBCTLJnikXOCJvUbidRBgkRoRyaNoalDIUumG0NE1kKCROgLGUxRYbJEIkRkACRIRKIEAoE777yzuLgYAO64446WlpbkXp9kSQHpEJFJUFIDkShnz56dOnVq6hZpNn09wKRjJ0Lk6iRMhywkIlH279//k5/8ZMyYMX6//3vf+15Ka7pkrSzFZAllbS8RpkOCRCTK73//+yNHjnzzm988dOhQc3Pzzp07U/0Xs2fATcToyZ5eIjIGEiQiTl555ZW2trYxY8asX7+e7Zw1a9Yvf/nLa6+9Ng0NyFQPVXLDQqWlpRnWP0QGQ4JEJMqLL744MDDw8MMPd3d3L168eN++fR6PJ50NyABTgHITCAJIkIjEuXjx4urVq8+dOxcIBOrq6srLy11phnGyRCJEEAIkSERGob8sZaqnkSAShwSJyEB0kyU9jaFUTyAjiFiheUhEBqLD1CU9RYgn1RPICCJWyEIiMpw0u8gM8silcwIZQTiBLCQiw5HXA0z6n9DfGLLE7/fPnDkTJ5AtWbIkDRPICEINWUhEdpEsWTJUhECDCWQEYQcJEpGNxC1LBnnkouL6BDKCECBBIrIXh7JkrjGkRpMJZATBIEEish1LWcpUESIInSFBIgiASAUCEiGCcAPKsiOyHSEsJCgTQRBpgywkIhuJ6pHTrdYDQWQDJEhEdhGT0pAsEUQ6IUEiiCiQLBFEeiBBIghH0Ep3BJFqvG43gCAS5bXXXtuyZQvbbGlpmT9//qJFiz788MMk/hVSI4JINSRIhNksXrz4iSeeYJtHjx49duzY1q1bly5dunbtWrdbRxBEDJAgEWbzwgsvrFmzhm0eOXJk6tSpAFBeXv7222+nsyXpMdQIIoMhQSIyivPnz5eUlABAXl5ecXFxf39/ev4uGWoEkTgkSIR5vPLKKw8++ODq1avlQ0VFRWfOnAGAgYGB3t7e/Pz89DRJH0ONIMyFKjUQ5nHffffdd999loemTZuGS6CeOHFiypQpbrXw/PnzZWVlwBlqaZNGgjAXEiQioygvLy8tLV28eDEANDQ0pPRvWS4shLhlqBGE0ZAgEcazaNEifrO2tjY9f1d/Q40gzIIEiSCSTzoNNYLIGKhSA0EQBKEFlGVHEARBaAEJEkEQBKEFJEgEQRCEFpAgEQRBEFpAgkQQBEFoAQkSQRAEoQUkSARBEIQWkCARBEEQWkCCRBAEQWgBCRJBEAShBSRIBEEQhBaQIBEEQRBaQIJEEARBaAEJEkEQBKEFJEgEQRCEFpAgEQRBEFpAgkQQBEFoAQkSQRAEoQUkSARBEIQWkCARBEEQWkCCRBAEQWgBCRJBEAShBSRIBEEQhBaQIBEEQRBaQIJEEARBaAEJEkEQBKEFJEgEQRCEFpAgEQRBEFpAgkQQBEFoAQkSQRAEoQUkSARBEIQW/P994UQEj9s4qwAAAABJRU5ErkJggg==\\n\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%plot --format png \\n\",\n    \"tx = ty = linspace (-8, 8, 41)';\\n\",\n    \"[xx, yy] = meshgrid (tx, ty);\\n\",\n    \"r = sqrt (xx .^ 2 + yy .^ 2) + eps;\\n\",\n    \"tz = sin (r) ./ r;\\n\",\n    \"mesh (tx, ty, tz);\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"a =\\n\",\n      \"\\n\",\n      \"   1   2   3\\n\",\n      \"\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"a = [1,2,3]\\n\",\n    \"5+3;\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"ans =  8\\n\",\n      \"a =\\n\",\n      \"\\n\",\n      \"   1   2   3\\n\",\n      \"\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"ans\\n\",\n    \"a\\n\",\n    \"b = a + 3;\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"   4   5   6\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"disp(b)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The width or the height can be specified to constrain the image while maintaining the original aspect ratio.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg height=\\\"450px\\\" viewBox=\\\"0 0 560 420\\\" width=\\\"600px\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\">\\n\",\n       \"\\n\",\n       \"<title>Gnuplot</title>\\n\",\n       \"<desc>Produced by GNUPLOT 5.2 patchlevel 2 </desc>\\n\",\n       \"\\n\",\n       \"<g id=\\\"gnuplot_canvas\\\">\\n\",\n       \"\\n\",\n       \"<rect fill=\\\"none\\\" height=\\\"420\\\" width=\\\"560\\\" x=\\\"0\\\" y=\\\"0\\\"/>\\n\",\n       \"<defs>\\n\",\n       \"\\n\",\n       \"\\t<circle id=\\\"gpDot\\\" r=\\\"0.5\\\" stroke-width=\\\"0.5\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,0 h2 M0,-1 v2\\\" id=\\\"gpPt0\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.222\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,-1 L1,1 M1,-1 L-1,1\\\" id=\\\"gpPt1\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.222\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1\\\" id=\\\"gpPt2\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.222\\\"/>\\n\",\n       \"\\t<rect height=\\\"2\\\" id=\\\"gpPt3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.222\\\" width=\\\"2\\\" x=\\\"-1\\\" y=\\\"-1\\\"/>\\n\",\n       \"\\t<rect fill=\\\"currentColor\\\" height=\\\"2\\\" id=\\\"gpPt4\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.222\\\" width=\\\"2\\\" x=\\\"-1\\\" y=\\\"-1\\\"/>\\n\",\n       \"\\t<circle cx=\\\"0\\\" cy=\\\"0\\\" id=\\\"gpPt5\\\" r=\\\"1\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.222\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt6\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt5\\\"/>\\n\",\n       \"\\t<path d=\\\"M0,-1.33 L-1.33,0.67 L1.33,0.67 z\\\" id=\\\"gpPt7\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.222\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt8\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt7\\\"/>\\n\",\n       \"\\t<use id=\\\"gpPt9\\\" stroke=\\\"currentColor\\\" transform=\\\"rotate(180)\\\" xlink:href=\\\"#gpPt7\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt10\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt9\\\"/>\\n\",\n       \"\\t<use id=\\\"gpPt11\\\" stroke=\\\"currentColor\\\" transform=\\\"rotate(45)\\\" xlink:href=\\\"#gpPt3\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt12\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt11\\\"/>\\n\",\n       \"\\t<path d=\\\"M0,1.330 L1.265,0.411 L0.782,-1.067 L-0.782,-1.076 L-1.265,0.411 z\\\" id=\\\"gpPt13\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.222\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt14\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt13\\\"/>\\n\",\n       \"\\t<filter filterUnits=\\\"objectBoundingBox\\\" height=\\\"1\\\" id=\\\"textbox\\\" width=\\\"1\\\" x=\\\"0\\\" y=\\\"0\\\">\\n\",\n       \"\\t  <feFlood flood-color=\\\"white\\\" flood-opacity=\\\"1\\\" result=\\\"bgnd\\\"/>\\n\",\n       \"\\t  <feComposite in=\\\"SourceGraphic\\\" in2=\\\"bgnd\\\" operator=\\\"atop\\\"/>\\n\",\n       \"\\t</filter>\\n\",\n       \"\\t<filter filterUnits=\\\"objectBoundingBox\\\" height=\\\"1\\\" id=\\\"greybox\\\" width=\\\"1\\\" x=\\\"0\\\" y=\\\"0\\\">\\n\",\n       \"\\t  <feFlood flood-color=\\\"lightgrey\\\" flood-opacity=\\\"1\\\" result=\\\"grey\\\"/>\\n\",\n       \"\\t  <feComposite in=\\\"SourceGraphic\\\" in2=\\\"grey\\\" operator=\\\"atop\\\"/>\\n\",\n       \"\\t</filter>\\n\",\n       \"</defs>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<g shape-rendering=\\\"crispEdges\\\" stroke=\\\"none\\\">\\n\",\n       \"\\t\\t<polygon fill=\\\"rgb(255, 255, 255)\\\" points=\\\"72.8,173.7 506.6,173.7 506.6,31.7 72.8,31.7 \\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,173.7 L506.7,173.7  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,173.7 L85.3,173.7 M506.7,173.7 L494.2,173.7  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,177.0)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-350</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,153.4 L506.7,153.4  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,153.4 L85.3,153.4 M506.7,153.4 L494.2,153.4  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,156.7)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-300</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,133.1 L506.7,133.1  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,133.1 L85.3,133.1 M506.7,133.1 L494.2,133.1  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,136.4)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-250</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,112.8 L506.7,112.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,112.8 L85.3,112.8 M506.7,112.8 L494.2,112.8  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,116.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-200</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,92.5 L506.7,92.5  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,92.5 L85.3,92.5 M506.7,92.5 L494.2,92.5  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,95.8)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-150</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,72.2 L506.7,72.2  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,72.2 L85.3,72.2 M506.7,72.2 L494.2,72.2  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,75.5)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-100</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,51.9 L506.7,51.9  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,51.9 L85.3,51.9 M506.7,51.9 L494.2,51.9  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,55.2)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-50</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,31.6 L506.7,31.6  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,31.6 L85.3,31.6 M506.7,31.6 L494.2,31.6  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,34.9)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,173.7 L72.8,31.6  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,173.7 L72.8,161.2 M72.8,31.6 L72.8,44.1  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(72.8,195.0)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M159.6,173.7 L159.6,31.6  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M159.6,173.7 L159.6,161.2 M159.6,31.6 L159.6,44.1  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(159.6,195.0)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0.2</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M246.4,173.7 L246.4,31.6  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M246.4,173.7 L246.4,161.2 M246.4,31.6 L246.4,44.1  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(246.4,195.0)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0.4</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M333.1,173.7 L333.1,31.6  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M333.1,173.7 L333.1,161.2 M333.1,31.6 L333.1,44.1  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(333.1,195.0)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0.6</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M419.9,173.7 L419.9,31.6  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M419.9,173.7 L419.9,161.2 M419.9,31.6 L419.9,44.1  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(419.9,195.0)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0.8</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M506.7,173.7 L506.7,31.6  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M506.7,173.7 L506.7,161.2 M506.7,31.6 L506.7,44.1  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(506.7,195.0)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">1</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"11.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(16.8,102.7) rotate(-90)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">Magnitude (dB)</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"11.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(289.7,222.3)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">Normalized Frequency (</tspan><tspan font-family=\\\"Symbol\\\">�</tspan><tspan font-family=\\\"Symbol\\\">p</tspan><tspan font-family=\\\"Arial\\\"> rad/sample)</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"\\t<g id=\\\"gnuplot_plot_1a\\\"><title>gnuplot_plot_1a</title>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,31.6 L86.4,31.6 L99.9,31.6 L113.5,31.6 L127.0,31.6 L140.6,31.6 L154.2,31.6 L167.7,31.6   L181.3,31.7 L194.8,31.7 L208.4,31.7 L222.0,31.8 L235.5,31.9 L249.1,32.1 L262.6,32.3 L276.2,32.5   L289.8,32.8 L303.3,33.2 L316.9,33.7 L330.4,34.2 L344.0,34.8 L357.5,35.4 L371.1,36.2 L384.7,37.0   L398.2,37.9 L411.8,38.9 L425.3,40.0 L438.9,41.4 L452.5,43.0 L466.0,45.1 L479.6,47.9 L493.1,52.9   L506.7,154.0  \\\" stroke=\\\"rgb(  0, 114, 189)\\\"/></g>\\n\",\n       \"\\t</g>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0, 114, 189)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,173.7 L506.7,173.7 M72.8,31.6 L506.7,31.6 M72.8,173.7 L72.8,31.6 M506.7,173.7 L506.7,31.6    \\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<g shape-rendering=\\\"crispEdges\\\" stroke=\\\"none\\\">\\n\",\n       \"\\t\\t<polygon fill=\\\"rgb(255, 255, 255)\\\" points=\\\"72.8,373.8 506.6,373.8 506.6,231.9 72.8,231.9 \\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,373.8 L506.7,373.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,373.8 L85.3,373.8 M506.7,373.8 L494.2,373.8  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,377.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-200</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,338.3 L506.7,338.3  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,338.3 L85.3,338.3 M506.7,338.3 L494.2,338.3  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,341.6)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-150</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,302.8 L506.7,302.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,302.8 L85.3,302.8 M506.7,302.8 L494.2,302.8  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,306.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-100</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,267.3 L506.7,267.3  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,267.3 L85.3,267.3 M506.7,267.3 L494.2,267.3  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,270.6)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">-50</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,231.8 L506.7,231.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,231.8 L85.3,231.8 M506.7,231.8 L494.2,231.8  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(64.5,235.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M72.8,373.8 L72.8,231.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,373.8 L72.8,361.3 M72.8,231.8 L72.8,244.3  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(72.8,395.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M159.6,373.8 L159.6,231.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M159.6,373.8 L159.6,361.3 M159.6,231.8 L159.6,244.3  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(159.6,395.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0.2</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M246.4,373.8 L246.4,231.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M246.4,373.8 L246.4,361.3 M246.4,231.8 L246.4,244.3  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(246.4,395.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0.4</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M333.1,373.8 L333.1,231.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M333.1,373.8 L333.1,361.3 M333.1,231.8 L333.1,244.3  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(333.1,395.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0.6</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M419.9,373.8 L419.9,231.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M419.9,373.8 L419.9,361.3 M419.9,231.8 L419.9,244.3  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(419.9,395.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">0.8</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0,   0)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path class=\\\"gridline\\\" d=\\\"M506.7,373.8 L506.7,231.8  \\\" opacity=\\\"0.15\\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<path d=\\\"M506.7,373.8 L506.7,361.3 M506.7,231.8 L506.7,244.3  \\\" stroke=\\\"rgb(  0,   0,   0)\\\"/>\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(506.7,395.1)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">1</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"11.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(16.8,302.8) rotate(-90)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">Phase (degrees)</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<g fill=\\\"rgb(38,38,38)\\\" font-family=\\\"Arial\\\" font-size=\\\"11.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(289.7,422.3)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"Arial\\\">Normalized Frequency (</tspan><tspan font-family=\\\"Symbol\\\">�</tspan><tspan font-family=\\\"Symbol\\\">p</tspan><tspan font-family=\\\"Arial\\\"> rad/sample)</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"\\t<g id=\\\"gnuplot_plot_1b\\\"><title>gnuplot_plot_1b</title>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,231.8 L86.4,234.6 L99.9,237.5 L113.5,240.4 L127.0,243.4 L140.6,246.5 L154.2,249.8 L167.7,253.2   L181.3,256.8 L194.8,260.7 L208.4,264.9 L222.0,269.4 L235.5,274.1 L249.1,279.2 L262.6,284.5 L276.2,290.1   L289.8,295.7 L303.3,301.3 L316.9,306.9 L330.4,312.2 L344.0,317.3 L357.5,322.0 L371.1,326.5 L384.7,330.7   L398.2,334.6 L411.8,338.2 L425.3,341.6 L438.9,344.9 L452.5,348.0 L466.0,351.0 L479.6,353.9 L493.1,356.8   L506.7,359.6  \\\" stroke=\\\"rgb(  0, 114, 189)\\\"/></g>\\n\",\n       \"\\t</g>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0, 114, 189)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,373.8 L506.7,373.8 M72.8,231.8 L506.7,231.8 M72.8,373.8 L72.8,231.8 M506.7,373.8 L506.7,231.8    \\\" stroke=\\\"rgb( 38,  38,  38)\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb( 38,  38,  38)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%plot -f svg -w 600\\n\",\n    \"\\n\",\n    \"% butterworth filter, order 2, cutoff pi/2 radians\\n\",\n    \"b = [0.292893218813452  0.585786437626905  0.292893218813452];\\n\",\n    \"a = [1  0  0.171572875253810];\\n\",\n    \"freqz(b, a, 32);\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Multiple figures can be drawn.  Note that when using imshow the image will be created as a PNG with the raw\\n\",\n    \"image dimensions unless the image has a title or labels.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 24,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"\\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAAwFBMVEUAAAAEBAQICAgMDAwQEBAU\\nFBQYGBgcHBwgICAkJCQoKCgsLCwwMDA0NDQ4ODg8PDxAQEBERERISEhMTExQUFBVVVVZWVldXV1h\\nYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdnZ2hoaGlpaWqqqqu\\nrq6ysrK2tra6urq+vr7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6\\n+vr///+oYj7dAAAaTUlEQVRo3hWa6XLcyrWs8eOEHd7WlshuTDXPcxXQEyl7X/uc93+rmx2hCFFU\\nE41aQ+aXaE56JbbU2+ZuNelsHTUmavv6SJ//1Xcnk/ZJMBdM8IekZpStGtu8cjJbJb08tiJ9ItHY\\nOR/F5Js2oe9SUyaps+rC9RrMpJyNxvM9P9xejbg4lbNLSudQWX8Fa9Z8v5VmB80hJFOkPIQgvJed\\nxEC3rM0cWu46aic5P57JJic+r9lxLdLatuxcmP7bzrIfwW0+pbBFcRuCbSYrfG1yCR9OD5GdEanJ\\nQNPM9xCsrHGlXi+M66vG6YZPTUg2wlXqY1vczgsxco92F9Zre526rru7MFy2WyeuXhppqCpRG6vb\\ntkd55iK85lGaQL3tvKsqzZB6WdMsDC2Po9c6h6rbV73F2oZ0xC0u6A/rfDJKsDilVnjMrQptvMg+\\ndCvszfXs1hS4QmVWy1JwPv5VeXRE42s5aDQPa3SUqRvDD94ZHRG1MfGnEPvchRby8N4Ydm6RiUkl\\nmodK7k54uovVBymaZa7yRbGQKccUGOek8/5Ro5fFonrfdZtXKbWL0akgxMBNbkVzFQsnWuf0E3UZ\\nV5eF56IkOTE77vegSrH7wlnaWGzeRVOoo3Q8XFWKoq/UBKGi35h0X4y+lHV879mS0tCM/UalECjh\\nbHw0m49835Pkh4qr1MSYOs0ptk3oA+MrK9lSTroF0eruBUsLdymEsGTLb3j3M+i9W8/0Q7Byj7dk\\nDiOMbPrucYocm80lZRPSCFqX6BzbknJBTFa0ZoOd79Koyom4J0m9qn09ztiHIs7vjEhznCokr926\\npVBRZi9v/zDEnCa4ULQ+5D3q4yiOXNeAc+5NaT7vxhKms5vwhuyTVjmK+BzG9J/14Bj+vDPVlKWu\\nc16jut1U7j36KnDDVya59lQqyRjHxpWnU5wQwYI0a2lLDJi68/j6ZwzF+hHC5LbVlxCTN0FLbnaj\\n9eKcwNLwXXlmjpiPu1U2fqXqiamV2UfP3thkhd43/OC8hb34/tJDSR7MWdzJfR8xaX15JOjCMVnd\\nCalCpWR1FJ2Lc1CfCRsCfy2W+d2zZrIRXNvDavNYEwuoIppgBYW6YMCuOkJ8IqfuNzZAKxOWEr/i\\noS1PFSWZLHuSYh8lFm0ETVLb1LS5CRuxydjUJGRQ6ri6zaownL7m1XkZy/4lAy+V82zNnogJgZnd\\n2rCsblc0a1y9xqp7jLubnGDQDGPdsuXU9pZP05SypifjIG73pj/9Uih+gDW1yJeJljiVSGBKzqdt\\nDYuy0xULW60neV3dZePHCCLFEuhfgY/fejLFuR1rZbyi3P4MpkTJrxYDfHBpxM+b9+tZ8hJ8i8PN\\nvx6xGG2x6PVXXu2z68Fv6e8d/TpNipCiW/Q487V2lQnWd1kjmVTgWqNnJVOhSS3DmmIp/0rofSIC\\nwr/hmNdhecbFE7/VounOOVbEpu5crurBi5Upkp5Zb7apL+92JvScZGmSiHJOTTUDn5Ci0B5VTtig\\nbGkpV1c2uctzv0jty8Vw3rzndr9r49peBOk12rUYCq0LGPkxG7vuOoaPnOKKcfY2C0UOW6DCudwT\\nkz4Lo4LVPnpvK7tSbFHsm+TpdouRLlWkEb8O1rJRuifFiOBp+CaLH58YY4d3O9SzM265tTVwz6He\\nb9shnvjJv2AfEosRo8e74Fj0zM0o4rM0ZC9Z//I2zOGuy1wPvzXOo/BPCGF6igpJTtEYAeuwP/ym\\nIyNvE2QJc6i6iK4IOtzkYSzGSFtoCuw9EWLhArLoDhvYqrhPPminnSFXtp1YCi+TgoHxn2Hd4mFZ\\nCPJmNEvO6OzP5XJZmerdQw6sqi7x1Y5JQjAExLS2nIQ/qWpUQY1PHf6ol9kzbMyHpuhm8vI7S5Xi\\nVUaBVfHJpdUo9L66r+pyS6t/ebKF4pUeOQ04rk3K6sNMCQaE1zfJO2ZbXjWO7DrK68WmflH7rs5B\\n8uvhDPMdfval3FbE0egW0qMvnsgqAkyV2kB3Bfe5OVWv5GaFH601j9dO1vqPwbqRQmrZQzxh/zcI\\nrvPL7ismEVcR8oxSwiRPjSkkbhfK7ZZ6tnfJmZecio0LXaH68mE2G/tfl4Tz4Kc3lTc6uSH5iAX3\\nsxgOyR7CZxCM2VEFRjH3GAQS8zO5tVCzSUhLFN/kZWzYM8VUOb8pKB+UG1Kaa1EncUFRUFR1zef+\\n/ShTPbF8+qu8bjKZKL0PiSix26ia9lVZ3BAUXeQt6TFTW2OD+JJ0PD38tvL9IcYDQMP1cMlvxYcc\\nDOO50ngj67ifdLCPqZR9cUQZlH4N1cn9nr3UugoYjheEdfU3t85fIY8bn22Bs0kM16JkDUMPE06r\\n/mfncA5OMfPG04oKGDtcGAPuKg+596nVYa0uno3iAoZVmHOEV3ezU1BIFx02K+viRuvxjPxkRrWY\\nEpqdnf7vYLJ/68RiiakR630+nNehKr/G5tKS8gI/mA4IrmxfyrdDKk19sS97/dN0m0fYR7rbOW0U\\nbKEVG5fj+BVFCdwtymfN7+4jyDwoObqW971ojIvQmcNOO7n6bzjkvpl7nCDZszW4610VGwhjo7kW\\nYmj/cCWGVEw09wInvwgrZGMKV7JFMVvSuV4jva99QDj/qXYLLRk7fcDAgrroVxqwReluEMJJFyXA\\nCs5mqvwexz1EH0OGxr7OG7Y9HX4kF9zoK+pgbZZei7D+iVEycelbxrWNrZUMJ84g3NA3ptQVanpT\\nXpN0M/zH9GsWl3VZH3Aqr9Fx20IoOVZ62G3r3jcdzsQ3maoi4HCrn01FkJWuWOdme5OMj0TP3RdY\\nXg2hSewRCc4kPt+d5S7WaZGU1puV+fZ0kPmQvtVOf1VdimFREW5gpO4/OVE0twqhA5QtmKeVpnYh\\nugSpEiPcTuurs3z5a+2B8STDIoMWjJykbmxipzD8KcAI0IH90kzEbvAZ42796V8lqD/pnHLwPLhu\\nmGQX4GXkktyQDXaMIPV/dEENyUf3dvOtJH90xU7P9c2sTTFhp7RKPrM79NpWSXkLwGqZuaXXlUqr\\nFEtHl+cMptd5ASjJqqHm3rUhRFR3nge2AvaJ1SrKc6/NUg9R9PXtluAH3M5l4vDl5AGjlQBmCrpJ\\nHjwHQn3NNl6tzgwYbOQXiqmLkTRw43v6ulOWJbSxoOicKwSU1OjjezegvRwlelKQycYQqdLpVKzY\\n3GTlyrxwISjV+kOIDGd6W/gRS+Hb2hu8Ior8GEq7cEtfP3HK25LY6uPPEiwbxsvZRgDJRyUOek3C\\nlRrJzz6rOGHyn6sMFTEF+CbhanZ9CtAvzzvgPyJy/bD+il3gHJkkzqKt+6HJniK25diuzNyzBQ8Z\\n96uhNcNLGJ6ZfZUIiZ42oMjk5t/CbW8UNxf/2VECd2cyI4U5WqHU+/L65eGqu1+fSR81tdOcqQTS\\nd3Bu2gA0CklwOUmzeo4acYzFXadf+meUGyop8jLx8wnF+SqyMwRBIzxAWPGq1zM+V+8TfyH+gQEC\\nbhc6E0eOFMLhqfh1j5kZ076zopFkBlpV0gZ/b4AFG0CpVBRPsDsTFh4+bspfHRIrazrqQaq/oTkF\\nhOHLt4L/EKMQBN1x18cSwulr+ZZtD+aRe86scYK4KqGb1lSjg1taJ2irDume06zdJNQfmzt6V1xC\\nH+a2BrTBIKkk61bmdh+WLf0fbbe8n3QXou08K37k8Bt5VAyM6LGRZSW5jptNWlDJ9I1GiZLAipbm\\nYVxTEdA8FzyD6mT0eaiBqqGWYHwcQfnQ3AXnUEotBzXdgeSr3/YLfHuvqF0CE1zBKjwAdw4HcrD6\\njOF278cxyzqO4qccur7LxJL/DaiJyfF+Wmd+XeBug+vdpJKQh7VK+FMQNb8J+Or45yVCWRTYLQKp\\ncEJMn347z7EAMa85b+sTcd/ABJC0qPQSjKJg1iAhLXAqbSPHyHRV2HgPVlCnpiHSkJXWDmA9G84I\\noBUpDymaXXQAsUYRNNNpLBBSzNxz8KQvczFn9NPNZ/pbmiT9/ufYRRGoxSd0kPixsm/RotsvFWLL\\nfTbryKeXm59ZcE0ThAjzKs4oTsnpV1upsD7t+y7Duxh2kJszGJs0ef6JQYNf2nQ6pUTb2IiYWr9b\\nJgC828cG4wcopzCg97OGF6oPzvA9qbfo22KVOX3mc4sg6F30AvWrHWlMQuIkQ7UnUXbQdidYg08u\\n4t0COrwyJtxaxu2EaAIp/sKTI00LReEM5dslh/UFaqR5yxeHA3CysUMJ93DD2AzsZJV5ZzGngPiJ\\nilOhhQGYIVfPI1IqBQ1owBsO5jLRUgn27oX57NKfI/uYh747zSjzxEHDuOBkTZw5j4Wy5XU1fksX\\nSIiLu1V75FO4gB1CnxsBY962S+jNFYi9LsSOWtdS2VDPZCPCy9nFwxcGGw8gy9UbGaAJlTC+ZN3X\\nmcvzS2XKoSyuzdeXE07P55yQfhPeK2a0QsN5ED0OBGVKdTyLZjARgLs+vc5loBBabWBersHXwarv\\nul2xGNa6mxLSPIsHrDQpH81xsUAD+tW0Ydq0H4IVKiJhz2C/giEy/r5zM2MvzFYsZnVrSeREtKvc\\npKTvSBR9diVDS+rZI9UiG451Jne4KvI30RyhaD3laCt8EHc1MUn9DZIM/5WfJe9VbJkS2wSLJHmm\\nPo0PUEfEwerCo1ZTYfUId7bszM/p5Kx5y1LyRZVV5Xw7vNYLvUv3DGW70m11cnKSu/Ln9+xDRbLQ\\nVnnQYNtWbw2DathOkPZteMEdvBqYf/ufTw+2bldRxp0fx78RaxIU7AqLXd6mKYRL5tZ6+IeS8Meg\\nP6aEXdcZdukXevCvzTxJU+Wb6eU6435FsYze/QUcEYv/GaBpwWSB3mo3yxLCSPIGQNL677b9wkQZ\\nctr7+X5OgNFKhRI/l+lugLUq5pMBkozHGiFa/SYR14iGxPVJPZYq0QXWQIbUSLB6hACm/JsfJa5K\\ne94e4fITyj74Htyuz5Nfk46k8HrLfuNsunoDFMMyfMhwv7cN2eTl4kXUiKWGfKyADJGLTSvTwmx+\\nVMZDiAim7v3oFqvvenB5+Rt81D2IZx0dTHLHSVyRNfc/XJigesWvoPQkZcd2GIs+fMrvfhcSeMVi\\nlvfrEfsV19Y+rSIMgRC90605jXARFBhWhaFgM4lp1AT1OAQo1AU5zhRKlBOLnonEHrciuUVa0k49\\n4CQAKNcdviEPhzhF/vXNxNMhaiHyxCj3bREeqTT3siFbAsavWA1348Rx8HO5UH2P6TTpXVmJEMQA\\nR+7Mq9v44eftWHj5UjdMnrMpwbytgT+LLbEbstfNRJa42Dkc7Vrtp2d1SyuozsDHZ670bJDAWphL\\nWANDu8sayJTu4DCZg6SFXod41F/Dj1ET7BiNPn2Aleug+AOy7BP56c1ZEBVFLT/Wl7NuT0gViBp6\\nH9fLmvsT+UNL5C7/o3DBBEXgnZqRCQ4brxV8DNVShyPMnCxyazYXSorLo6oS7j78hA1qS4NF6Gr6\\na61MVbF7lerDWShfeGVlF8w9dUhEmKtoLq60XKdisl/qpuKbXzAXF+wZh6qPAz7lUZTNWnUCPtcU\\nnX12mTxS9Swc6O3M4vc1BzbLJlAQiTav0PgLc8fQKiM5B+QlZibM6Wmu4xa6kjEE9ekJv8SYs71b\\ni0Scf3VmQfRfZrYgZkp7AEobRM5cBRFHbLUEyQ+Eql96RJiV0rGwhd1NCN1o9x8zphCS7upUz+7u\\nB99MDpeVMvH/LAv7w0Zc80+Vdj/42iOjEPyE3NKPGHVzIsKnDUKYG1nddPVkAKhEAs3XHaA13rkf\\noDYFp+1TOqwAQtbuL7HRm7GfQu4HLLfYilpxfZ+VhwoG/O+XCpmL9yNgA7RE0Ap+RYaPqsTTPLFu\\nSLcp2Qy4L4CRJNJ1ajHv/cNDJojuqRTEnd19lfCU9zowTptVC5WoT9wHt2sQdGEID/b69DK/DLbX\\nhcOBg4Iy7zgWQhYh4YhO3804WdGVTEj40PXgqk9FwcjNdvHK4m67wia/P+iA0V9CpbPe3JVHrVGd\\n6JGYpHULEe+HNUhYzjjkvSGgLVmxenoV9ixuan84+MlYcq0cQmXCAoxSfmiIle72j5qhjBnMQbBc\\nB8PoJK4NDTRUZ+A4CgkWA3d9ewl0ipaNJSYYRzoiPkd/uZV+beqKcikXoarZK/8TKX1jZIzgw6WU\\nO33s1fghzl2BQ4BP9v0hBms5pTXBxJAXQ+k4HwCHpdNytT55feZ4ZjlMtQxRzBuT1THdsjysPxwA\\n9Z1J2mBXQA8i/PtRAbnpZpSmHYiZuvn6VReHGA6cdqWrPS8fsxXAHLlfCixJMkzBPxg1GMNzv5qj\\nqrtB5pp0EcgmjvIlIi97U/L7QagnVAqD5MACRZLpsAe1e9s3HvzvxsQYzY6WfFiZj0fMQBuaDLKe\\nTI1nWsy4XQpvcc1JuzjhpiI/Vze7itXGPhJ9XbCMHZopkLX9qrnLlcj7jnwF3ke/EHf51pa4J7HG\\nxm+Kvj+eAwrmhjC2AjxclhQr9wFovlk9VXcSFf0eMv38TJt0PPd61LhZYdNjft9cHe8SqWK7tWw/\\nHNpcY+Lpgy7QjrvaUx+0//tnUdQL860QQUgZxO1xEfffJ1kmpKPkTdaMSHmROK6BA2qwTyH4l0ez\\nTyXUJ2N7FFtZqq2JEADvA2HKA8Aw5SgaperWkPiv/XDwhXQiIQUSXHQHFmzSkv9J5emx63zf/0Ig\\n4kFsGPZ1N6T5cU2ZtBQ+8xJBMjd/vf6+OZnUc6CVtHMYXCV2swsIRvPTiI+ukVh5lQNoHWwGdkx6\\nmIgRtjvarM1wAl6gMC9hW62lMdGXTJL9AlPLYMAxJS3jZaBFCoeQa71Fc1efed/8Mqt38k0U8NRl\\nRPgGlMPmSpz6PXAfwX9274Z/pPfzOqRobjtEvjDU70RqyH4AriFQuJ9neIsqjAyMJOTfvfhXpNLR\\ni3PGZxgLI4dnRemCAqvKjL9PaEhEBsoeEA9slEF4IKuXiILgIxe+FWtRAh1Yieb92HqrMw4qeUxS\\nvWHJH7MIAl8neU9/Mu9rgN4h27QLucOtMClIWr4RWflyhh+CJbFL+VlFr1kDFFpLyXQqeiy3RSeN\\n78p1F5oqgpn/dyQY6DPO89pOnW/0vB0WnJw6eJ9K7dBzxZvS04IqMfMaVsIHvb7mj74DmzQXrf8i\\nMb1EkHaTS/peFb0EoOgjc5nHdV8tls2YNRl+fq8WySzKotc+eoALONdByRlByC+TTgaC/rAFeB58\\nrMXGwNIRdd+DxqAgFiNZ0PB+PO+k0AoTAqwiDnY9kkrQum80GHGQVO7EJkeV5InkAYeKAlFeKzdZ\\nyOYV6/p+U0NTMEhizWNzEttSb1F1YdzB+SgNJxVvQM3WK2RT2Vfgt5Yd2utrL39aGZK3jo28qfq6\\nyXM1oS+B6ckLrkw8xWpc+TlHL2hSUqUcrFP0wKxddVbmhpy3zxlx9643pBHaus3U6KQEcE7qYKMG\\ncYLHZ4vQV7O9dUms/BnCARZukmM4ORfgSr2Kq0JkPW2vGny+izqyATQf76T+aonzzAA/uLkvonbd\\njvPjyj+QRI2jxy5wyKjTmoUeWqJWuSdu2/M2BTLS6m4+HOjRFo6wcytp3QAE+MNoowEECUK9O3JD\\n7cDg6q/0GXAd1KqwS0CyTpJqNurGJOvws5qfSiFXRmEROTWfyCu8EBU15R9OSg3Y2qAGpYLQaByd\\n51qc6YkmcUrKZuqEePPEsEv8wo2z5JBOrYBG6fCGZwsSl/4jFsRKYBsiZNqmQNGHWAno3+s0GEon\\nLEU9mYFtLTEzUcoB9q8s3dnxoYj320kzx7YnYNSL01M+ESnsDpE7wOIogUVoW06zStNsOIGp2jAA\\n5WejsrzMarZcaNQkLf8Gwtl3hIOTNOR2k/gxZKsXxWeHiGfKo9o3KBPU2KENh5Lf0F/KMM5Z+YKN\\nthv48/M6CQapAnlIncAoh0ITPOfvx2muDOeOWYpwRdzhAF8qg5p5sOlCM7lt24pMfpf/4ddA1F3d\\nwBfy/+BbVxfqa0HwfP8+invtfEK4V4qhoDvmKT7QQ4DRRhPpcUuEhwzbUG9EsaqcRS3gQG5T/HwC\\nywGRs9JvfIMpfIvzbdl5tR8mUj4MPBf0kVe9TOGHLcW0B9OOAbIK3Y+gCObZOvfk//uXbMG1i9oG\\nXGJWB1Ce2rwityfnSLoDmU37cjK7KBdWLawLjKBhM8xpBjMVfFMTjo99B0VRRpSA11DJqpK+I9hj\\ntgg7fX9/6uFiodvlEjVgfqgzJWLLDOLgLCxqD57p/YlIXY7PT1Y6+MnaBWquCQVIIG1Gn7+k8+7R\\n3x+d5GzI3MxJ3r9J8YxYhSVxBHqyQHqQ234nZBdhMKJA4iww4C03CJ/sXHq349/vLHGzW/tRwwGV\\n0XGyEswZ4vKyI0c3frvz6jIY0HDVB8K+eSJKok00SEiXXKx8MrE9G0ca9K3hBUbsDOwIufuiAFZQ\\n9b7WFRVvVSbRuN6nsEvkH/nLpFs7H3yHKBtKNPgIEUZA9ZdYUBrFNpo39PKqCGdWM4MJiW4uJkTZ\\n+PvDBw0ZDEzB+2X7k3Woa+9W58CnyRGpLn/Z3sRspUgk+NLu3AZMk/ZYuaDsDgGhvOIq4OxoeYda\\n4/XBdCHPSxPc4iVZLKG+P9X+8eBHrtGb93P8b9Yuv28TkY68P0JZjs4oKEQ2ZWPCKJT349lgUi9a\\nb3Sz1F7Yw2pProv4X+OVaQ3wdD90RER0n9gB9yJlRbFpt34fXXnyiyJGvM5J1l1CK+n7syb1ENXx\\nuNh9NR7ooBEBzXl06cQADWlwZTQWXME/AXSuosyGr/URtu8cegxu/e0sML3JWCtinlVY3z7MpAqS\\num9uICIc6u5s0bb0srPPWqhR6mSgWanUNzJ3XamMOvt2FHu4969BKPszwMjFIbMsETlOb9oJMooA\\nsJS0gqUFVNgLsiCMayXqJZeWBqKDlQwqL2pFJkXk3tju70/4dmDWB6BevAmVVFtNednV/oWEfOHF\\nMbo4qh4bpJunpzv+ZRFWHVio/38UADpMY6zUYQAAAABJRU5ErkJggg==\\n\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAAwFBMVEUAAAAEBAQICAgMDAwQEBAU\\nFBQYGBgcHBwgICAkJCQoKCgsLCwwMDA0NDQ4ODg8PDxAQEBERERISEhMTExQUFBVVVVZWVldXV1h\\nYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdnZ2hoaGlpaWqqqqu\\nrq6ysrK2tra6urq+vr7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6\\n+vr///+oYj7dAAAaM0lEQVRo3h2a2XLb3JakcVVddcK2RGLa8zxvDBwk2/+p6uj3f6tOVPjGERJJ\\nYK9cmV+CGppZVNi8j6WY/afvevVzdbR73wJLQUlF+59amC+2JlWcXq2TPCvzFP0UltP0m+nEH8Vk\\nr6ri1qfOutDEEqu5qW7ezGBSvoVHotUSY7hRNCu1kD4r3WPeTlHtpkw/Tpm90GlehTbREW1oNUEr\\nn7Uus/5JYqZS+hqySueplXFd/UheOa5WRQaTWxEytvjwapR+1X3JgfQY5oWtVvtqRrY29SoSt5fz\\nRLxjIQQpRyqqDGbyduWRpFAO0e3Gi46j/yPYzRUjLZ2zdXTQxsU9RaVYiGxecRH8uicdHrbIpNz3\\n0zrbqcfvsLRYQlNSQesgt0eLlAknqFLObPT1Q3sRThddWMUmndD5pvIRo26DqlH/tDFS4z31T1O0\\n/VAi4ICNwFWMZGRP/F/l60N9FrlgLsI0H/KiBHXlQWniurho1DPOq8rl8NIIW7rpM3V173XQ3Ar1\\nyxLvuY1G+hjNWOUtt0qLPDChFOjc3Ed0mT4WN66UuMgXwyTu0LvcPCa+4wzbmtmuvYxW3tfk3XEb\\nD1NsXJsdYlflSNmk1e5SCruFKiLfcQ3/OvrvpTZaE8lZcQGhWaFjSXw/V512SfZ/0jLus9YtxTVk\\nfuCsPSX8EOkVVquqE8I6rwejdldyki6VRkl44HMMTtq0UFJ1tVVCnAk2vh57I71m9Xl+HaoK5q1p\\nWdpsvaDBRTUnGVTIQW/COOOWYIRy1j6kNcOUfAzGlU3zU02nCmrmN+03IU2OkiriuQ9tEyUHz9PN\\n4WPk27qHck4w7Euz0PMuzneIsrmyr/UQrlsrbHQYqs4bfw9cLrgeZUMputoyrsRsNlFppFjOWK+J\\nqL1Eur3JkebiGy+r+/W2IdzL7GI20eicchSyrDq0yA7dgorp17aMOYfItZ4Gz8IeY+ZWu6J0Fnuk\\ndlW2ZGq/Yrz+p2uWgrilhL6+LHQmQ02UQjgcp2U8Z9oHxotIlbNaZi/UCmUm7IbRvridD71yDUkJ\\nGEWYOs4hO0N0SCfT7bgUJ9YNUo1badHWj9zEtaHMWCNN3AUc6Un8FspqLQ9W2i2SXuxSqDxkKUpt\\nuobBL6PiMpDU+vxBVFMqbtHpYLuh4qVkN5v0ijWdnT+Fuq/cJ2ZV/PSht7ptKTmpfY6L3L9nHRMh\\nVJwrLTYdLkfrx2LUAC+YLazMydDqmiqMsGOv10Wsh2MrbKqMmHnFSphRdbkkcY5vT48v3JF3JT37\\noWWi5DOHT4mB0+RUle0ocjcsCefiNihywkCNO7Nabi4JSxQsUaZ2dNlzCpmEkqcR71qc2oNbZTv3\\nuvMc5ge8+4mj53HeY4B67XfuPpsseGxMhUOvk/X33ActNusuRaTgmMkzU4uO6keYhBC7xwbcs7bG\\nJuZ9GKeyPWYm5nyr/5XiV3Pa1WDiU0svc9XML8pvFgfjgmgqrwgRDRMY4iJOw+lzkR2i2av/UvUy\\n251UnTM2M3tSAlGc5uWjun7GwLI8bEw5iQMzO5YZegnMj5BgPGqycXO7J3JKrMZa6MoHyAOBoZuF\\n1mRJ69yD8ZYxFrNLTNHPqrzCOlu4szGOyNA33bT9tNz10qEH5lwJC6asjWYscOO1NJDyLcGElNjz\\nMcC2vpKB1vGZpgQXkk/7obWlNhaZbapM3oPank1oEeqHvxO8pFrXjmRSCZvromj8Hi9dSf5oLhn1\\nIf0s+Ja79qszZjhMRrzARRborQr/GbB/He+DUfRF0rz5nNNXvnuRby0ExatCVih8VHwhnzhxk8It\\nOpWyVR3idrwW3pBx4caV2VKVw2qTrDDENcU71nmx69lS+Lnn2WrJPfabKOblHol4etLXwnV18XUt\\nXqnU+9ScW+CD7oQyvgrsMuYfIuGDqzVibEocesABd5EO8mWZ+Nss3BW5h3CR9rOQ2VG2z4bEAqtP\\n8EtHqbfa6nt5E1HgNklF/OtxLvLcpZb2QgBYYeYABqNhfMKEYSaSJyuVrjv154BpHEY4hUtSsQqK\\nTNv59kqLi/O9b0x6buLcfNs8bGJFxnfH7H2FMyBtDqa26U/mtPWenICtWdZeffBkNpYSTV1o7f4k\\nB6802CxMPO+hOq57iWNDojxk1pDdX+rZdZ/4LHgtLHU7qtG8QmXSp6zlb4xsOZw49vdjdnAKLYdP\\npMuNKTlLRCaDCFV/jpapQiGzYOxzXp2A8DKLeHMRtJOpuDMwE+jyqr/86j1ziUM2Gs4xKR9kSnfv\\n34vSEscXEFomZOrm7hkUkxd7HUdKE5YdgymeGuIbiX0qTBMCRGHwF/orRHX42AOsOWARcajOBv+S\\nMowtqdXr531z6mNsVCpgw2Am7uN0pCLnOL2osKcfWQaqWek+liAe8l652zAHECQs7xkj8TYoR7WN\\nLWTJrWoNYaZzTSkDK9JbT2ZhdtdHNxGWvQ31lSyNS91qxC+ql47v+LQezBVsbUif1W2X8ztEbcFG\\nhUX7HoFAUJk+OwxOpxQ1Bb4cXAVZmtJbmUcCIrANwVJ6GOCLdIJFvbr9dQVRaNiHqqLcQ/wropqS\\nEHfrJvvwxkqdgwwxpGjyiiQtBUco/HfRzVsuX9XKpG2TccvLKmEkek226UFJkrTpSIHRQ8q5vkki\\noD+Z52hnA/R1WyCQXrEH1tg4WiWztCi3xHBIUO0MlNuydM7yjYNwPGPu2yP6st67gFel4ScjS8zW\\npEdAbOcW/7DucKpF4yO9V8lzBbfE5+oQppwShDSLfPheKmjCBLctJlqVEsu64gicxWGiDgA/tYSY\\n5OwGTVc6TTIyl8elIrfhtasFVpp9zzFJHXsNTe5bZ4vuU4108gzjsPlLg1i9x+12ub2gUTGzjZpw\\nnMePG177cI2utsXzNsRR6ILdOs4Wq80Rsrbn5g0M0EtSDlv9hTtT4E5pQfDmFP5glYwZnu3kBSCL\\nMbty/08Ss8IGtOWYZCHced73vAsy3GpanVZjsbqcSiXBdklnSToOM7csQjJ0ORejna5dQVUMiJjg\\ns9jJcd1stEtY/5UFNvue7M9ve4Ac4swQG+vquBe/oxuEs7WvJoIBqIwdlL7yNm/dW7vC40mkDus4\\n7qhiyv+owaWwxhuLSUu1P3li8ipeJda9jeFsAnbADBDhlPJ4mOPpzlgG9v7bgv6lQ4ekF9cAoq7H\\nyxUlUzzHHE4h6xOOp0Q3pfwX4nfDZXOgQWFj+mgOsUtgOp2WeMXnVB0TVgav6A09kQQ7OMyaaprj\\nO0jrFwcdl6MvKF98KU9RGpNm5f/XvlkwuZsHTZs77paADbZNvjE54BKWf2dAVdOJk+BBdyKSq+S8\\nhJicG+QOD3bVanCDE8k9fU/wIQwv1EmBq9hxdDURiANSs+FQYBqt+qgLSwdWtsJcrD9Nm1jKjNLV\\nEIgTJfWwYjtQ2lQaeMcm66j97cCl7EQdUWiglvJ6HSO0Lto93849SW5ckL+z/M0b5rQZYw4u+HQj\\niHJRsbIm7P99GSxpEKpIAjdiVdkYGXjmS2JORZDDfdFLLF3U23HsXQUfXPth5eMWPruK+iqswCns\\nhkNNyER8V696fsgOQ1CrRFW+B0TjqPvYADzIGrMxLcOgOEutlNjyvxDwxKPFAOu2gCojBBqkBJ4q\\nHkKDMNm8PGz+mBxq9dbAhKkwkMaXDRm4ghZtES1fJ9Gd5m9hkr40YVc/qBh6HEF2qwaBmcis2YDi\\nh0PNdh5Fu3CTt+90rEz/j5g9ZmlKLx91QgHjdqmiRVFpVWYVr4/kOq3Bf5mlspmCXTUaThkMoUsA\\nplm/1prJsgO6g7njNGm7qeqJ/7TZvVbJt64yPYJfrFPN+4Vzh98Wbw0JNM5HZ2DR/9kOmffYUt6S\\nWGthdm7jgMOb2Uerc+XK1hAXtYrgm6c31OgW4Woof4jWj65odWuYxSuibZbIBbauHLJKEkSZhXp8\\nng0itZ47l5bMETL4IS5iG8S3D0oAXw9SJoZ4EsGoh+uJ9XLj0Cc+4N+oDGIjI09ahdmmMHvMU1Iv\\nzBH3pTo0HneqJ64o8rgusoZETs2Bw5DcqoZ78KnkcRVJgxFOR5XIju9Qz8OLfQcz+hKeAokPXk91\\nNTx5hbKzcyR7H4GUh1FawUO1HfuqWeLwuQo+Suqwbae8lAHQAk0ltvEPg4Zv47exQub0jTfXNRYt\\ncq7N1FsWK3D0L7IJuW20+c1Q1mRU9yX3suemOHL1D8bFsHQJNv/hcF6pP9VrKGfIf9EnpFC6O1t+\\nbyDhooE+BO2g+Hiiozb3Au9ATOQMzk/qEIVQD+ImXuJdOFL7w53WGUl0DCiMkWygZV34Q57FDpNI\\n5paAs4a+Thy0qyYiDCNq3QswZ/mZt9XGq4i1jPZvCE7m551nm7cdC0Wboik80ZZGhnRJD57Zo/iE\\nEqwpEGML9DW4qIDkQnMM5p/g7EE2iKdSnb76//ohehbAx9uxBhQBHmJuaCCHL0vyFAaNhkVM0AZu\\n+ybV55cy5KH+5Xrm8iQdUJCHgKzzb39y10BYFqxpAgYJC6DNNJPVTmYArGKPtVcU2gJR2YIEcTop\\nZQCMaIk2Eis0KTMKftweSb8QB4srpS7NbmmYDbrqFms10neu562i8CKFXYT3rIpv12B2vMeapQhW\\nXQxv5cSCHm1UslIGm7XMck2e2e8PeD/Acddykhavquj167AdCfcdKJZi4mNZwRsdPSWlfUqWz+lm\\nUQM4TYoBQJS225wQ72lhilV38IJdZz5VsAwDa9v9uru0IqmJQqIUhA7Xw2ti++9qEQ/gUnSBzTzc\\nxMGKlVHBbDor25Rl5kMkvp22UHWN4QGQj1Q1yIVmzeiarqlIIQ110t0QMXr8Ff7e+MwddcOoDDbX\\nswSJwhA/mNd9zQ6B9b/PSxUVsYKetDewBcsrrwzqC8xNd6UW1xmyAifNy3QGClepuX/WUk7Q9Bm3\\nFFPdzaBX9HcX9J6WoJ/qfMhGH1SXtXdZTp/nfIx308A0FAsfuUWOKZZDhWFhq9mK5rtms0Tpl56M\\nDvDkpohhl9mUbZQoaAMKJc6VRoNqUK+CZa1kT5PlnlBjZ42fN9Hnvtj04ou03Vi1Vt7TT5TXCXhK\\nbGP/jglJ/+C9o7fVNlII1+/j9SitEpeG4l+2NBna+mWBliTGaD9bC9GzLPYmXlx05mjRIwKkEoZ7\\niiIcyWM5/IH1E0cJ9D7GcN8DRUixZaOY4YsAt5NeixL6onoUi27wai7YuFyPU3epauXSceQtd2za\\ncINfmJPx2GB4DKvrBcQlqRttMNhnc15Gs04GHTE7tKacm6ir//TO0sMN1d5Pp8D8zmWV8/w/9Ewl\\nOmfUfv9ScyzX4zu9cBZxmSgvwqfzOImyqECaq6S6cNGVP1pPcAiHthmfcOGDbvqhcFkxyGkAeO8/\\nCTXnGbpNsBxD3Jwrux7DXEWRn/5+ephNtOhfOUkzoxM8nFDbfMNsReBKuDeLATKkvwu/npqQVIQL\\nJflMYNV5iCTZfXSNJ4P+ALI6I6Wx8C7yJhcyrWo576nAgd8gaThox/RrORhHfpacRoQEJ4KLQ6ID\\nILsLEQloyqV8e7fplvY6BAImObxAWvUloZRUedHv6pDU6fcC3CPF/Qr+dyZYOBdJB/1mq9/JuPGt\\nn4W2aK9n/QGnzWT2AUlvKZsV7Dl4HcV9GUqceenbZ8tcu1kbnTMqpnVLFxbnifJWyHrwbJBf8cW6\\nDYaf16GQW1/nsOwb2zpOILT8mT3ZO/1KKjnlF1PtYsF9Ciw8UnQnlIEVh65Q4+eno38t7w+FYhiK\\nkgbB9BmLBzx0+bY7zS+4hssTaj1q0kNzzUbzGxVJot03tC35GYUATpu46CMkNqiUdbtdD9B0dJ8S\\nK9Rz8J+fICI/yp97pqIBGMhXhj7tsyiWrN93y+LEjrCBzRRpGm3E2MMlocHWSJ+W0JEd5KwXP8sB\\nBP3aV6zzUZqXxecpqWJsWu8m/m6b6w8gEd+5rgzdBPKQYuUPlqvpuRTteTVu7ZweE8ItogztcEPv\\ncq/sJa1ySeY85FsPoaPpbkqs6S689hKEglKSxeMTM5K+fsFc07Y7TM0h6TXVKDjXV1Eo+5/KhtW5\\nueMEOXFXB+enjFXCx30w8A4Wh2dEDWZAY5TSypQwV2KpmfgYd5CqAvU/IM6aHOUv+HKG/hvattJN\\n9Q1d2fAlxOi6F6/y5JPx/G3dPf4nWkuV0eVffBten5xuYY+HjsfX5G+twZbhM7Etv0Yp9K6fALN6\\nL2jtHtoCCiKazP4OQijkZLb2NCnjBhHOvm/WS3M9ItBVAP+DC6cqAwUTtz0vV/6gjGjhJvZVUac2\\nROpDXvh/OGvxbmCt5D3apWYxq3goGKLUqaLgnB1qEymER+YiNZxI9qac02pqTWMewM/qizT7INKa\\nRkN+Vk8zeH89Ydm2NhRfeSJdgZDkc9XGl6fplNo8umRzLTv/5TQr/3g+17UkKS71M20kJRGYfIHu\\nkE9AZ8kcS+KnHflo10+K4lifm8tbYy+GH+O6PWs72A9Ecqf8EW5mK7LH5Z59bA942vWIAXa/mM3g\\nXmSm3fkas3RUt8EWvdwchMOKux/okuimDxPDlhckAiERiPUz/AlAkrBvH6zSLfeEjj1/YnC+Uf8M\\nbHn55MViEkDM2U1kw/fgBIVwQbVh+HfK+ycwvAqfGxDIff6DDipVTnqWxG9wpEkX9NpCdM3W1CNV\\nbusvH85wP61F9bqetze1AWt63d1ojV0XdwG+p8ZPMaUBhh50KxxxFN+SI32vRJTHfiClT/EdTdmw\\nQBF0dmVAiqzMj4kAkWCjtL6npmxRafEnMFvLHF1LjndkGNd3GyarPRvcFoVcLG39PU/ebNhQlQ5j\\nfoHtWxWh1d/tAiGdcQV5hGqzaJgjKiS5FhhFY9LSIKRbaI/MoAX6CjwV35qDxxb2OwzVGPlLVYQa\\nci4Qs9YZYzfGxeqULOnqbDYyke0Ds8z3LGjZl3uQq8fdNKR8iG2mgMtqnt/N6VthawAIOAUnjgqA\\nYYZsVVtnnZ9O7f56EmzcXOUMv5RUs6NSYylVip10xqFydd6aUPuScamCMYV+/ghuMd+tF6OCe8FW\\nVEAjO9/IJkbEswc/TKwVaS7QcYE6c8D0gnp2O6FNwN4hTfIJYHNBoG76ph3sIWyzbdc3twnlM/K8\\nxgltcUVzJkyj5AMuA+fYloJOuAUxEPTRJ78eLsKnTE9/dMnmp9lwRY8ljAtEwozDHgAUWxIp9zxh\\nIo+p4e3IodV4jyihLKvrSYKeDjnVivGIOE7xhMWYkwxAoJ5qA23l0mjU5yS3vGoZ8uYj9lqAW1ur\\nBY6mYSk1zSVe30JpW/85r0d88erqVtyFaKajzMiVq6Lz7pOcPrbstVsHvSuGN3Jy8TLJGWGSaF1i\\nmE1EPse7qzz7GgLiyNqONpvfR/bojZTMJiOtMDjc0xEtUBzYtzrxG0o2OBCMiQjaUh+cASCKUqsO\\nQEuF2iiVYbQwzzytpNTxMevtx3dScq066m9r+JcpJHrjXg5p48HmaMxJ8UPE66m98jNKfhCHm9e5\\n2S75YBm6HdxPUR8zgbAb2L9t4XoK+aIwLckPdhpTjE6pXeaa5h0xUepD+gxy5ztaJ5A4Gfaya/o7\\nXjUGu/cd7NoEWa0QQ3DKnVEDLbxEOO3sQmwMOsosN6xTi+usOGpRMUk4bOfplau65SbxU76JQD2u\\nCi8FUSt/GqRIhk3QfTplduQBxhoobieTuNClQJQR0WoCd6jZ9fqrDs+QtxTvIS2qHBN4XTnhYk0+\\nGArgEnx/P8HP17fpN9WTQy2XsF8jHvn5ykjQD0fa0MNvG1JSgHN0tiqeRj1AgvF6BmksCLupw6Ti\\n/AHvT6agSu7FiJZxLSE5x9BPhYnXn5TQlOlIDsNbqF4dn9bPTk1KqCFXsSL5ZFDrpaejesiEuqpS\\nlaq566ijk7oWM33/lce9orUj5eMOWK7g8r7qau7hkDjOxYnqtN8kYQQzfnM4l4bQhvAXTdK9sTSi\\njEw5qyOavSjb8ZNV23xiQcAPuZhHoYgGO3rL9tVvSs0ZdPgfAAZ0COPrCzHyKFG6HxrlZls7LHXH\\n/nc3ILWLo13LTSikrVf+jzXsiQbPs9aCabQj7xtcqI4a7XyzP8pSVxX2L3DYpJen2ZDbaZYvrl9H\\nTFBO+mxPxyuAKTvgxDHA+IO5Rc4BlWtKafwOzsCvEzcewD9L9OcssgRbx/16woT7TIkTFmXJ15P8\\nycs7s/W1Piq0e50Bjdv4XK7eyH1/0LMOXmiv1sW723duh6LrecHO9fR89cKCnxNRv5xEoG/JpFv4\\n4pcziGXHPZtHtq6Shbrow1Qoo0GKqNvxAYZI2r2TUlztX0OOggfrI85b3WKpChpGFf6EC2kOWMQN\\n/9QNVLutMUJsxW/cGM4txm/FLHZVgzxoYKnkv2OnBK+UyO7sMQC/Xht0H9RslnvZZSoLE5WhQgss\\nHpr9Xus/oUGWd5ve/Xg6PcN2jUFjqudcbPyxm6x+kKInMcE6UUNhe+CQo5xb1zOcWZr2Q+iHH+6M\\nX1/BCH7nt5c5YmX765Rkuv6e5RhdX1q8Hq3Dq1wJ2DUjvZlcQfKi7/jUn96otRluwMa2OTgoc4m0\\nRLIMBhT5478VGeDnP8Uv5SJ07FDJJ6fGzQfcjlRyzKKjQefxenqrsPyFobQA21Ypvp1Bf7tho0z1\\nDG7g3qDd79pBNB5Fl4+Bk+RaWesAg1a+5Bhvxr6UTagPGwozQwd+YGG3vV5/IlQPo8ynVmUxAZQ5\\nOiC8w02x6894Wqqs4T/STlzpXlST4AzLJHMWTZ6zgXj5B/XHF+SSaVcirmixzQVZjwMN1RNXXI3E\\nERF24Y8AXzURwIXiCq8NdHNTiD4fHgmmTlJSYHJZQ5NuxS7UoJMZ5PUV+H78n26WrAqN1joXNulR\\nB0i0wfk7Go2yr/RAERUOJ05q8dAPoHrhH4nqCA+zWxVnUGF0tvLvmNGI04o2UYqLrP5/ANImVygw\\nJv8AAAAASUVORK5CYII=\\n\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAMAAAD0WI85AAAAwFBMVEX/AAD/BAD/CAD/DAD/EAD/\\nFAD/GAD/HAD/IAD/JAD/KAD/LAD/MAD/NAD/OAD/PAD/QAD/RAD/SAD/TAD/UAD/VQD/WQD/XQD/\\nYQD/ZQD/aQD/bQD/cQD/dQD/eQD/fQD/gQD/hQD/iQD/jQD/kQD/lQD/mQD/nQD/oQD/pQD/qgD/\\nrgD/sgD/tgD/ugD/vgD/wgD/xgD/ygD/zgD/0gD/1gD/2gD/3gD/4gD/5gD/6gD/7gD/8gD/9gD/\\n+gD//wD7V01AAAA1cUlEQVR42h2ch5IbWZJlsdszXcUUEKGe1jokgEySVTWzs///V3ux1mZtRlYm\\nEPGe+/VzQvCkw2ykff9kW9zqbqLXq5W195rPJsznqP0u9ZKicS35YfuYigqNb1EE6ZgamQgixbV1\\n7qnZ38ll+fMqHvtVmG/vXPUP56KgoWnyIThldbrcg7SH80X7cUrUOK9FnX8bpzbKuanBVLdkK2LZ\\ndSyOTTpp77IJqu7Mqcl2nagCf8+0EtoxciE2Hrd2WiZe9GoUlxfKHBd5qkfve9bir2tx9FqVjbte\\nCKndYtcSszMkeO/36O1Cz7MKMrTmv47r91Pc/CFCFFlbNtSkXPbuYq5ap1wWSmkl1oabkloZH+Qi\\nEknOcyN80EUxOnWDumUR8gMfIOI+TsJ617d747Zrqb4xd9PJLXJl7VaqZ9xo46PCL5PhRKLPITlD\\nh2XmjrvPpRrt6aG0uz+ECH5WVHdYqnWVY0edM2n4u+Pz3ivL/M2xfvzJ6sLYSixvXGtzzPjILtPR\\ndPiioL0PjNtWRl2+dqfccnBVabd2W+hGH+V940N2WH2RTbWhUX/dXR1j29uVu9vxqKJfcVzxW97T\\n3DMu46BDLUnFSajLfWX49vGU/FLWOP1s1CWVx4n3WamJbikHqtr7Wm7/yKAGy2LRxYWYpZ/76CdS\\nrGKmLaKkORrRds7pxGY5Sax/4N9GKRxcdW+KhNTZAYd9nan1SURef3rPlpYKF7pVVE2nNI33ptJs\\nPZusLMknZiYxrXaeXExB5WGVN80WJ1VeAxunLk3srsxYGPvWhohTGoSOQ9K5MXtbHbktU8vGu1sV\\n28qkL+zjyjcakwr3Hec+UVkmKbzom8pn58JxlVMn7Ee2WJ9eRjuL1a8kTnYQsRMODdbWq8LS/0Yd\\n6vRYzBxE2AejUkelpvpribRGxgzTerQKv0R7alQJhgvRqvXxiVp2/XNWxpJivFTcLaVmlpZh6U3Y\\nufzzVI6qr1qhVrW/qiaEtkYmrL6US1s9id3stK3DGK10Tt11IY3wGrgp4lmT64OJUfk2LPYwwYtp\\nHr9XzYa57fL8KKVTYqI/xpG9C1a1tSSwOrPrWOY8J6O2eapxqd3G7ZGtGm60TUZX9beIbRPBkmZF\\n/euzIBLosXo9bCt3clQfFY0zm4m9r8oRb26nIZpvMTknq1LGqLt3jHcLl1fH5nT1E606L+YTS285\\nG6vKrVPuJp2i1VsSk210ajWlONtQzZqXHfXL+MK3Ofvue0wiKz6wZVpHRQtPWM2EY1DTXXr83PHv\\n0G8pjnW3XKDj+z73stYu9jFQYhdhaxoJ18IR5kVp48A2HEnYlOVuuOfJf3Uxcm1P1o13m+9CflSn\\nt3OUwWFPNQ1oFpykJiRYL3ZEpnX7YWw69Ere3WhNU7P98vqw5yu/MsnOzR2Z8j4h1ob0YyK28aLQ\\nKjySzuvarY8BNUXsryS0vOjYLMcmVI9Ty8i6Im0n06eZrkYPaV7y24ptr/XHsoxGsKdlRCENrP7w\\nbuyYCqqUWYyWHdJ18pR0Hx/Xha+RHjkYh4ScbMKZC+PWmZRRFuel9uK8uH9yMfJ2zvMZCZ5DYCWG\\nGsI9TGbQb4mqd8SCWq0Q3l//CGXmmzVvsq9DxyaR+acRYhbFzYGK+bwmtlxjpK4aVIB42OF7ZJ5q\\nfLaJ9rNFQunChPLf1tm4zNLf4hzdbcsScdQRo3w9O764cgSqT2HPQWeKrVLeJ4dD8yqL56Sfv2/k\\nxu9T1FsIJn/4gQdj0rsNQoecvLs26Ux5cMzN+y83i+F9Z0qaQLxvqwnULqbSBwaaEt7ZzlGZY/8w\\ndJf1PGDNVK0znxop5a66TQ4Ib2rbpny/z07Oqd4OFPVd+37iMi2YP9Y3v8Uxvhs5JfeBUaBCVFhG\\nz+ZTqrRPavPDm1BmqgmRgHK1l+NJqcR2m94ZX83sEZRLMlypVGRWvsjJS3lTm4qjicRTeTBvqeK8\\nGaJ6JmbdYyRUmsIgiLBxOu61jXpMTA+D0YoYQIL+8hj7SS2zoX5So3C1ZoFxvgb+MCqrUcqBJK11\\nHbH/5dus7ZMVTLC0KlF6YfmNi6nN0ynJyORoNyqJGlKIYJFyw7kadjdhapffca5P+0xzaSvTsr/H\\nLg+XfbR6yOOFIvhnfIU210LNKjbnsK10f9Xc6lhymyqS2/vMfo8OIcDaGm65dtIO3ijrhjn8NZcj\\n87SInBxjh+VmkpZiXNQ4npmdRwpMyns+yPWojof4sOvFnkWg0s1KjQldMxlzSmKIjkzfCFerlR6w\\ngU5ZST63D4pRj6Uk/S7T8ycdktxyqeJm7MhxFNs8FDHLwLAUc1CBV2m/z5QZvxZjVjIapfNc/SQI\\nU4ZF3a0WWa0pnYbR3HRkMbxCFR87H2CREX1vWMjZcl+U09e4YHYyZ7qkBsHIoIYYQ5YYwj/DkDFe\\n7PMHmduE0Of6REVn0AJla0zFF7FdO3mbgVOxeG7p0pmEIBTGkCp4kCWacJljWlezVOrbgiG2pZWm\\nKKxkrSAozlhOOq+Z8zD6zF9HXf+VhT6uJmT7rDidrdmRjmWXK7LPeat/TL+ol/eQOavnnSOxUa5d\\nioNDTEn/pspyvmUWCRYM47jqNmKO0fuIheWGiYmf/nLWrcT4zin1Hhc7vbAIrbuPNbs+Xt6Gijm2\\nT97tv1mRxNvNaOtXJO+Ig/+pxmW0waqwSJcfNSgtExg10EzceskNu4oUl+HN5DDPtvgaJgwhqREx\\nE6sruVGKEly1MP+OjE+loUuluaVOloPcuV4HGTc7YaPbm7uLcf1YFqq3fPGUaGGNiY65ZE96cTiA\\nIDAURuPJAspVjOlIh4hJjj26YYjFp1MlokKpEgvlh8dv4uCJ2M31HLDEPEbPoixABG78fkMGRvHA\\nzD1/Fj0SxInZKZoSVRnTlhRJN+zyzYhPzN/HkD61QzBFr9ayjYekv6Tjj+Dl+yforNf6T+Sj+UMr\\n2kWzLAJR5WzRzs/Af2l/Fjudgp6FkllMTPBWCBumlVxM/K3ILU5af2Ha67DkjvPPj6IWN3Tz5Xaw\\nBxgFxN1v1o+SByKTq82neRLoOOskjfYQq6l8fIQemGVkV+zosR+B9T49nrNF4Dn39Cug11bm37w4\\nPtWZce34ICqfG7ClC0uzJiuDpG8ll6hyOeJNPPTKgwU6zK6wv4kq+TQOiVPs+tUF9YnqbNKOw+do\\nxefiYk2CqmNzUs6DsHQY9Lucr6Mddwr7SMpr8yijp1FMJmfDGP/Kok3gnanZ0k/Yc8amUcwGY2aT\\nl24HyfIp9UuxDRyYOdKx0NZc1rknEafIgI28e6xsejC2Ny32tXj7tX7tvdXSvi3lLTjC/+MzJU3U\\nrRt1QtGN8mQWayJwxmgJIDEj8NWkXf6Mqcz/ZdY4dkacRfrwzM0zBVOrSJOxPtDBnekT/sAJYgEN\\n+Mz4iH+jFGSmYYSInE1KTOBnDxwxGds+qMZQEti0vsaUwrw7DLmqh/AMmzfNL9JasWO4txwDo2mY\\nx11nIWo671SZc48p9X1oRFs55FnSKoFTHl1ixGmmi+4KJA04IfO0/DPEv//6KO6qKRltGrPdgre+\\nd0FyHdL2iS9S6u9f0RBETu5LYYnIpkTuNdfLf1HwgdD6W7BozFC5j47adyCB9zx5g+m6T0l/SPL3\\n3CyRhk8/b06y0B/FzP9j5Rb55Xc1OZ01WDzfJrMgDdl41aPc7DOSu9567hVWpDpvZruuelrpdBp0\\n2lmBeWYmcnZqoYZb7+VvW/N1nFAuDd+DNVVNy9pUFyw0mNgQaI/mqIa32GPEzp/2Znh44b/X005j\\n7rCWx9xF0WsXXCf8BIp8c8gWRAtNDwqIvYj02ZoYCHoq7QvZHv4eL3MJcpyVsOfinxOPPiJ8qnYQ\\nLD8k1c3SKImd15DKzD9+dWO4nbQF8AwXth97MzqumL/QCbvVCxdSy1mczQTmgP8c+8EqnxS4Tjs3\\nN+BrqLaUcWjhQhQsVXPZp58NqlnasM8j4NYOVG2a3tOonVqBDTwlWu3jha6oCimWtuCvyuJ91mMT\\n3rIqiPRcSSgozGAvxSc4rMQ+i+/V/ZnuDSdtLrwzRQ70oP48xXCcpnluDln6WT0IfJoYiyMiQg7s\\njY/XVQLcPzx5yLrZkO95LlOR7FbLDNhk/qHSCHCITo/Zx55RgV81HZNWQyYyzAGB42dC7iPW44gX\\n9eFWEUr8lGFGobGz3pb7MFRHZiB7hgTR2UOmMDLNNh15CBiY0YIorz4htQpU63uYrg4YsY8SVBj0\\nVbGrO8WgKMmy5gHmbISzvP2QvzaabUNca2dzJMdhF4CIdbS5TsUKkFS2mdEpCEYKvbPvAx2Mf8xx\\nygbl5iarC4UxcjdN3lt154EZkpX8aC0EnDBqW9/oa/SpbvDyv52mCDDMeECMyti5HWPZWnO9BeSb\\nARNE5KaNM+3FbWeHyUy7fpprypBNdMPJpA7crbprK1SvTiydQOoUQVY7IMG1pIDk37v4Oa7Ja5Lo\\nfJ3KTJi4DRf48/yCp1rDDVUyK3C49VpilokaIPVWglFFlCguVHX1gaVKBObLrhJkLUqNzpxWNE3B\\n2JPVdSyugwK7O/ThooiKqi2VWXXJrmLQkhI5X35M/rwcWfshR1RvWfa9nsxmexO9J8p+wwVJXBJA\\nwhh9qGlLNqXM6NdNazbDznpEet0v4bmECMgXK1EYFABhPThi7DCqqRRHI2eaYLJQM/MbCzPV7lP6\\nT8F7DP7CjLryvTvrh90AZ5u22yufWHqDuqgAd+m9vLGNZ7ZX3e3K5zaVTmDLUnjbxmqKU4TMwsjF\\nuKo516o3J7jQUI1of6jVuJx/ITO9Mz2tqD5aTEvDLizrhGi+GbVvHbuQVZRw2OQWD/JTwATPaSQO\\najCskk1sZ3a8Xs2VM2PMVuvAJww8UtxFdlWJsZ3fVZSjUA54G74j/w65m+Tq6EQhKZMuGr4j9/BT\\nR08LgbIoLMuX0yJZUAxIXeUErlXZmh10Pd30yVgMtLJlVW96XAX96lfC26qlDD+l7e+rBLp3faLx\\nS/1a743pLsk6U+ZU52Viochevz+0+2OtQfRE8vFiV0l0KCE8xrhqW9jAGffPsl8sSX10fnX3LCg8\\n0AIrBhVyX2+2J117Q7iDKgYibn5Wf4XsRhctAUcl5yTZ+AWwX8yYg0sGYI6tORx5Xa47mcvrqiP4\\nesBwByr0Rqi0OD25sGw+8hXEqMdLI/grUg/YCaPHM6Y6iPzePz6d27THn3lykyZ+rXkDsLXA1imI\\n6w1TcUUyeDKG15VG9OhDtO3fdry7iJ5mqsn7NFYc6xdEtv3kdThT9bd6jgj2VhiNzXgXQhWLAcgG\\nzHD2Awudvy3G/y4cphVL25JP79enKmoNiDzEkL/pc5D73IQKZhm3WVYSeVhR8uqeRM8Fd+5rkYKh\\n/obFA8UnR+mqfcIEMPqmfH24Ema3S+Mk5+IbVjJf3wjV9dzIVEQQT/O1mJQlu09gq7wbdF/V5Jn+\\nYelHmAucTcDYOQLDoYuWef4QqOZelRqIGDdj/kwGB+PR05kKTVtO+hSCmUCKbaTEzVDOwwBMvH+O\\nCkwRqJPZyGrnPPFi/c/Fy9dlUutYm4fB6l9g3ZU7TAfOqN5hwpne7y7DLBunKHSz5ehaUNPfNR6N\\nL46ow+lLok1sxq3cJCVgslNanRwnMcYn0qB050STfcRljzCaKjvzs91JL21TrJteFx0s4hEFfs9p\\nH9JGrD8hyeFRs9RTe1olCDfQwBkAO8UOfWLsNHIrvGuTykbPmR7nde0nja15m4/CVv5rybGgKxiC\\n8nvkTxGzGOUTg4egduf5sRuHYa/3PKSey29yn8moBHu41CqZOeuRM/lWKG/3cic8oGA86s/JNlvD\\na3rZvfIvSAo7L/5vN5/rem6MrvM3mgFGsmZ62ju4oeyyTjJctNXzUMMorpWN1U3sFmZxEzLekvnJ\\nuJpYf5udTQpTdJj8MbZGKMCC9eaXDbOcI9fFLLPAMC78fthqQQ1FmSEyPw/3WH2+D9ROGFVNCqfX\\nPV7MOJBHRM3JWKFsMQm0Dkx/aLpezX30X/6RoUaeBHmuS8/8mhyjtb9cVE/YX1OyZtCnprgbk+Uu\\nepuK28aCsc8xeEugesm9j1JkG8u0JnGRUaEvbEAwzDl0vbHlp6XuPjNOcJiL1dlb+kYMQMwQBkJ9\\nFqKtXGYM3VQp5vcxWv8MvQHRgk+xNYV/+RKS7hQS2nZ0XgDZFEXXZUKupPeKQ5+RYxGGzT/TOlbg\\nSjGiigGAR0d73IvOJ8vrhn0TRqn7A06j/RTA9zfWBDqQXVF4/eJTwGCSh7ARSFJG4svsC4uWcR6d\\n/MrFRoRCZ6GrSqb1Gizp95z4OqY4X3woKVueKnvkkjumR3W1D2BDNN/5wGf6LAMTCy9hSHV5gkb1\\nY6R5VkYd9ugAaiT9sEPUeZ1nGBQpt4F8ronB773XQwruxN6NVum6stetCXS+lnkBjHl0Cazepg5Z\\nLjjyfwNUPtWfVWqo0uiDuGUU+KzYFgCHdgFd+Jh8n3RZpzS6MzLSaVQEm1PBVBZecw/8KQfJRGcY\\nufKMYhQgXUtMk3tdhKRr6dZFMN3SrFySi6tTwci5Ind9o5QtWgDj9L2LF4yAQ1v7SahKKK035f4u\\nmAG36Ox81bZ97nGu2n6CPEibi5H/bbRgXA4RrX95giG8oPnDcm8XOxEvuCEhjjMPA4/AXejjZTLu\\nnEal9SfvjpcD35qlHk0f8j7pZKNVhhmaj8CWjJxI0y+5kh1pfTfmnpirgFLFP5fXbMmYxcMvSaeK\\nlVqc36gTP7t8CyG1wl2Nytw8DDGu9eId/wDdiwPJfVj+vGLd3/+PIGUDA99n74t1BTTY+Gq+kUa9\\nYhijKYb+Z5iczlUeCoESawQ+Hux13dXGQU0KUngMjrfDFuw73HQIOAJFBdDaTcYXIaeH5HRBjFFw\\nCm1qSRAKhGoFwArCqA3GbVEbr3IovgJi5jMx9XWjlId/Of6vOk2bY6f5GgYMlrRMNal1G/gs0Rzd\\n8kQy6vXs7uqHbzBvqKI3fNQH5gp+wkNhkeW1fcD89SONwBWqqZAmTiI36lxBgiwqmeM1jyWCfTCS\\nK/dQPHh+5bnoYqk1XQeRMOwKnjymJvaZQyfDGyxq4gOwOs4zULo9cmTXeK/G5ukhcpIXF+yXW4rq\\n/v7KSIOTqirpSbH+hw7RT0s3PY0TjWa/eZUOyOSsS8OkQ6+O47ZKbtygzUW8SWZk/mpxCeIOmPjz\\nx5YtfjiMUwo6S73bQpK+jkmTKFB02ttxhdyWDTCfVuRx8iE3/O9TBwx8y7cE9aguJCF8T7A1KIR0\\ng/9VzN18AyTZobFPti6dYeJx1vESHkW41d++TkfcZ0ulbJ74EKSBA85ZRn8VOJbuUwKhV7TB7YN+\\naCzwbSgAfy1UzUv4wHiQAXDesocJzQURlXS2YxU7bywgeRdSKTi5z5sww6SaU59AeVXTIyEVsoML\\nznT1LLlEKUH0uVunVKRhUgFJiJ/ho9ydkIvmQ3LYEHOII9puKtGFR8K4M/l1v+D0kw77L7f+dR3r\\nMp6RXOxYuOsk2rEPZbA4N60ge161iU3TA3/yY52P140XSh2myprqN6/QfdC2kGy+6XsF7NHrOcBM\\n9iSx7j2WlUcY4+GOm6LnK8RJu3HxO2ciuNzQABHQ+kX/YgBbZ3b+4VEMKpSv6yTQOEF8vegN1B3v\\nNH7sMtvVMWXLN+ju50hO9HGDElHNFMDsBpscF8VUCLHI73qRlvVjHaEiuRMOGiSt+OTQGg8IT1Za\\n15hlxYGFMUav08RNZMFu1k1+S6IgGct4iGw8KTODuMyjq+85WwSznSbDpX12nK3+yZRWZO7kcr+N\\nXaQaRqxI3NdK5KCeM30acnWYV445sbpYMCZGBBuHhmw5cHLCrmIVW0pHT49edKtek0zSIkHMAr2S\\nLo7njdCpy2ZNz2/a2t5Do/9zNrYSy6Yo5za97sNf1mWVSH/ZMZZmzolFsx29dVD/VsoTVGcf7lmp\\n70RDfZE4jhxL1M8OJ95loDy6WqhyxkJGmjWhh44zcG+WAZ7y1xISmDC4Svq67lqNOlGkug0LxPLk\\nV6VrQuvclAS86c1kxcJEBl1Uz6mxsGY+T5/AFoOVzK/nJO4pxxZXd82ytE+wPCLqESqDLGrj1Dvg\\njU+D26QZAjKncCPVVZlH40pVzPAP9rQTGw0q4RYmJlnko7cGyBk7Kku5gSRsvYhZQzwTveNP1Nl4\\njrV7Pbkx77PhSDe2ZU1L1F8eQ/yECKRwLEnt7eNOy6H5zA7ed1qxO4aDlc0mgnz7HdPCCUEG47jc\\nkjk+cjUvqR8rmhzF0gfRzPqLG3NAs8GtZUkEHDs+ZBJqrmPBSN9NXlgF1vs93Sepx656FSNvDakx\\nI26eImAEostrnoNM8GwMvH+7ARDup9tq5wVZacQmer0QQ2xZUGzQodOIcsYnl9edhOo93PJ1LamM\\nu2Ovo5Q9fIt+PXmTU/vvjgHExYWtpta5Dsc9b14Wf/SkUUPf7KQMD/KvjFyDFtSMiZJHQDMM7iPw\\nINyT1S2CA0T2wIu7zz/FGkx6u1PJlxH+eKSmZ2uVft0rzgjR3vPq4OiMosZDBHml890HX1P2UQNl\\n7PhTiXacvj37NhhkCfN/dHMpK34IiO0xyruWsKDJisDF8s/3/1YvKfJh8HLbeLJ3FsDlcwGl7FUm\\nldY7A/cCKhVahZ/zGVasU2DooiRHlYVdMg7UOcDcJ6C86vTDgVh/FjHX94MA+XmFwvWT6JRsECMX\\nV4F52Sf+latbzC6LIia8nowxbqz7tpH6wLKWdtLgQew3tQoQ7pVYQl4obQgf+yHlrm7orVrGUgy4\\n9nEVg7gFECotD8mYtTkNcgqMcLptUvxQKvnJk9ouMwGmuO0N/xffzfKNskeu0Vn33e64Ptj81Wt6\\nduOEmJAqYN3mYWXFjI9/H7nfR1+qTZxUDdXjzV4hvceI+V6bqpyf0zkYBeRIU0z6zuzJ28oAJ1yz\\n9XWlyjpDAd0+XqFZw06QFxB604Uji6789C+2TpDKel8j6lAqiKGBPXqiFAL19RSTvytrwNsHRtHD\\nzgrhJDZp0WNMGnV3I3XFKE9TRBYS7XdwwL8++40QjUF0D0UvbrVxGUs9/hQTCLwKeka1GfKhSzcQ\\nDXy18rKiGJYVOkCr6+3JZTNrZux7dA6ZJKt5km0Zx0eV4HDbZs9uq/EJnKWi4V359HFY9hnEIHxq\\nTSU0kvkkjX+hhQVIRM3z/78YrpELY+JQ8lDV7J/7MuUFelMx21JAO0ew1/91VM7Bm/eGcafXGWUT\\n0+1GakUDW2P+0LEPty8XeRbtk71V6adUzW/GljYPOp7x/dOdMHdaX5dPnX8EECQGE3LKi0Dovb8o\\n4tSg7Q7oSEa8ri406+eulK9950b7bNq8iJafA02SF+l1GtG6ScvDldeVnkNK+6eEGTSPswFgWu1U\\ntFVmhHGiI3A3Aph9x2b8Z+gk06uqbHrdghJxHfxXzksrWoQp9BNaixme5/M1Tmx19TYuubaKMvqw\\nXofTHaNeSulW4dXrMYfpYpIaqyqNGQ0Bl2muzHwT8ZEQL2KMV5N+T5sCmF66ZVkCG8xgoUJ+POBl\\nVKyKaqJIcmNZ7z+GYVzscNix5ZC9eF39jGcqfnJTsE7cE1hSuodxy49kVVBZ0iIQl3WyG6rDwLd9\\nj587GpiB8yWoTwoSYJeYxcCVWcUuf5gg9YmNPrMfQB0+1TAmoyaXtm9FWolHObckXGwGrb8q2HYw\\nG3N85f7BZTRLhU03fcOR+Ck/XOnypqd/+Hg3LGw1ctvz3m4ucIxjppPjexYliKHZsD5J8LvV3Vj9\\n1bpq+zRO9W6T0GuYrlIwAsPq5uUqec5YfOCI2Pyyu8jKNEyCjkvdOOzybebxLy5OLRqy1DxA4r2e\\nuF2u0FSLoCbIhK9YUtiF91wNa1x7NQa1aVuaWKrsV0Dazf6HgK5OC9NGHphvXmlhuh1VBfNu6t5e\\n15s4uX6K+EzI2lAzpcXDAPNsd67+UP0WS3gjbYl73r63ENiZo1Ou1q6lwDTgD9kizZS70EzqNHOm\\nEaWkdN0wP7Vo3rpPflLqHjRLZ3iJna2U3lUkhAJa+JvkUig1/EZO+bJkBIgy6WVH13l8xt3dDLqH\\nuBfVvn78n0Qo5lZJmetP/cA3dIomsJGVIqn7nSGQs5+jlYbf3c7WL6cevVjsiFEsbEjWfhsQkmJS\\njIgeG93X/JiLHWbz3lfhq2rD61mjKa/9xHp7S47Cp12OZ3ka9Dah+lDPmnvs3uvGbupkONzEx9KM\\nZOS95V5e82oOx51EY7puevRZjm7UIKSOpJUXH9WwVR38/ZLjgx+QUQzHizce6zO4lOk3lN2Bh1Y1\\n8x1DlM3b5kRpS6ImsTRqAbntRwK455PKt2QfxEwtwprBopYiE/XAR+P7dzKMofO5fBg1sj6Xv93P\\nE/FJdmQmAHJEg5nGR/jUhmH0R5m+ifJ+HML9PgUsO2Tv6gwaTDL7u9cvl8QECcgZS/wvZ/iFivpd\\nP11h/qoejlYQi3XiSmMCprlDuySb7gLbarXlrgbKI9MzpTHG+QIF+7SxN+T1H1Gr8VfBaL/Mkb8r\\ncWBEueiidWGeJfmrLpqyb5zekq6bL/EU2bZM53lVtw0Z8bqL/rxcTcY6JY7V+OMxyngRN2pm4ebw\\n5dkT7HNUkad19RPjPI1RLJ4scj2Y2w2ifXaw6oyiNtO2xaYrgHbTqRngQ6gJO7Vl6sIKcM0IpDTy\\nb5xMmx+mtrQqlhnTS7FvaHjA7DkvTyeZK4LlScefLD+9SSkDWp2vyG8nb3Q0J0v6M/Bsz7/i1lt5\\n9WaChVP3emyXY0hxkfQ+QbbmZbKa2deVvJxzUdIxBIrIiTZkbmjjUCOjLw7Kk6Qzn48OjKU5U9nE\\nQWdAabJvC0oiztrS1H9c59fzrMw/irG/jij/U3E4OclZwoBne7dr1DNOOw4JrFHfLj1OTHt5Iz9E\\nMoPYq7b5rtZYF/92+vMCpQM025tq+vlwI9xBPNb3JP6sIWUtvOnWpKfZhj8QOvKJPAx+QltPvyR9\\ne2jSzVLO228J7wrFzP3r7kQEqVwS/6ivgacUkvqxgKbWmX4I6yNZouerMlbyzs44SVOiKmg9I2u6\\nymUZo/Pu5pR26FLfnDS3F62rqZPfynQZI4RP4nwLf1C/s5/zb3sayOvJTSwksHIzs6tIY3pf9TAg\\nIUMOCxc2LQLjEllS5uw+/3Su0G7qXXMP4+gU9d3WPlriEp9JGwtmhvqS44M9Me0Xv8q7Y6u4RCNQ\\niHcjTepr1PxatZQLJj9YZXLXTdKxmRQp6R08vHdOpylNhghx9vPDM5X24Ca3Zbgoxjfzy02247mo\\nqbS0n7TXGN3zfJMDuIBJJ6CWVGAqsMC9jt5CnbVZfc4ffTzmbuO/cjCzveLw3PJhERCq5SnT3/j6\\nyO/2XU36SY0r+34HA0bQljHNtcQRFEPEhkQpX/eacVi7Sp/bwJerHehDxE9gD3SNoJ84l8sEoMkK\\nBLnwFCYu10AEoyNJ8UBzHPn1vHSq9PUkID1tULDaN8tvGgGHbARRq5Gi8BTCH+KwLJjiiq9zvKct\\nnqvqWXrel0fOgFxPiHrjcOkdpFW4OhsO2ItosIBJCww0qcUKkGQOC50+zmYdhk7u1G8ikrBoKUBe\\nDOVHihq3TeQ9RcBqKE73v30j7d4ZMxVgKHbAEXGLYfbLth6p/BKG1ZpEEOEu6onFwB1v68yvZFJk\\nduuWpMxsWMEUmzWrtPT1EDTME9bAX49Hy6/30bsoYjTq9cZHWOZ4/JqFbTQJtNg3Vl2tyirGqQiY\\nHd+s2kPF0JUJyuVF4z4kCm6JbryEm9gB0JphVBZgCXHDXc6m6mVkthNkK7khAD/K6xKGf117TaZ9\\naStniC3j/4x2myqdTgi6sxzvw0KbHmXmrGV/McxLLArEZCLjx+N1Gx5/H0urHlD2f+1E9kUtavQU\\n7RBopkbAhBeag4g/SFrc/pmseyq48uvqkI9H6/vIZ/bw3hb/6KOYr6tqyYVfcRwyM8qQJ5ro9Rj+\\n7GM+/+8tcuq1RwKMwfgg/OFkbLl1BfURy5QIX2BAfYbaaR7paeIGHfn/M9kkfehsFb1clthS2Qj0\\nS0ydQ5E9+KKTX6yZq2hhj2oVdRkl6l8Mbv3KzDaH8/tKg3f8UZQgcJmqnSXDOgUgDrlh49OD/LKP\\noknpncevmBSaHTF5jRcoaUFTQ5lec+/iNKbIETYmJPeltQRO/qWXlTrKaWkUpWfgV3JLhyCW3fIJ\\nzvS6rDtfBCJk3lhsv7vwlDqk0iXNsEJVAq+GNyflneibIiKPmRJ41+sh5dIbOsrR2/DQib6z5yL9\\nrYzD+v3lKmwGqLu/nhG/JebtC907dCws0PplRYsa9a0AV32EkSs/Np7QWMOHG1PC0HYrW4pzgeQp\\nlY/5ddcdY2sdoWkJpWC0TV9ADztltp/6bkJH6mdsSjC+ejvuDKkp/Ce5Jf+6Cfg5fbwuzm6U3CaU\\n17zyXZ9FWdOdHCOxBAdrNuBfSFxieGqCyE18aR6d1C+jof7i17EyMWiFTPC6uXm2AoB/7fo4zJJd\\nDS03HqRBNLh7ckunhWAeNVvDtvT2Dt23bTFvzE+lqkSAS0Oh06sC1jXlAV520rpelOdznUSriviv\\nKKPebBrnzNQDE2k36CCV5/HuaitOyLdBiVketVSQulyFJXSAlKK91w/sAqPlx/q9weazrLPLLZIb\\nPYM6hg+YjXRdv4j8ODZiE9LJcK8KrLgF4I66XnNsfhKKM8dQ2Qkgz8RlofFwcWjlzFt9huEHx+Tl\\n/qOEGEXJyGXWwUeQSyH8FFKXMBASshgVYveeARu6lEStLw8UzELs8pVyuo2toCiA5DqY4/Ve2hSU\\nMIstgeVs5cJIFM3KWkVs188Eu8zZm3HH3GV2RDAhCtGUICqI12yKYT0Xud+pOiqPs9f5ju/kq6QL\\nuz/DtJwvYA8bvXvuig3VFNoQ550ki+BJz/fgUuCn+aPkr0jFfP+PRbVL/nrWNBYya/cZaBR5uPZf\\n9q+p/4O5q3YxuJH/M+k5D80T44F46nMSlvn3Jq8FPjN3n7y1pcWxJvmzbtgX/+0mwezAgs7OpXGs\\nCKle5+v6eXBdUXASi1k3qBYomBUNn7UG2MILVEMRXm7E6bPu2/y6xNSqfd9JMjHvdquBYtK+F3b6\\nmuHXq1q4+7fJAL7rf/nRXke9gOdCEISSbxve79VFxGW4YE756Rv+7cj4ryDDGDHZzyWkZLbFHypp\\nobsZnd1CoXom2eygL5W8s1fjn69Xs0DROoRoEbZK9PMazQ+WVf7Y3LndjohcDMVbIMbmGFFStkFE\\neq+aavRRPDzL+y+b67z3nntTAhe/szlOaeMP9e2PPazBX/gtYV1GblUe743JzgwmlaXdIyflE2gh\\nGAvm8iVwGNwEh4WRn3kYBvknOMFfGVXFFtY7ipUXs7frTt2nRGLVgdQr8aV2bBvlIlht7fXk0KvH\\nkKTZt59AJFNRq8t9muM2TZO91NHKo7312V3UmNpNQiU/xw8eNqxF6+OYVFosmKydbvFWrDg8ZoOs\\nBe3l1Zh5cCYtMktF/3v0i5SX+fXKEgWZhz0ItQ5ReTrvetG+lohS4h46RCxoeQR4myvqV02yPuCn\\n+FDI3I6f89NAQd+xREYYo22oSF7+lTYXl3xP79FWoBVdi0enxpQK+sfSPtm5ZVZ+D/ZhU99UyPGJ\\n9dyIMfr+eqLhaqM+tbJmDBEhB3MLUDrxhcFMhYNsy80hS4fXKwos1TpR47s20mwG+WHPlubdZOgE\\nBm+yIr2PI+yvdV9StyAMSnGFyrhpKO8CVTcXQ9DcEVo38COmrpnJJXHFWlEx+tG/3gksCoO9vh5r\\nhImTppJtytkq2DLxbqYQe2qfk22pZ5S+2WUSxbqaA0DthNkjNsXOR0SGIR0bCrqaCMkDgJ4b9hob\\nPl0XMWo6jiI9XTIYAZu9j4xmufrXzcesdLw217UkEJ19xsA2UTOScni8efwpaDFpruC9m/GfKZJc\\nEWvT+G7z2ufFSp8AAV+HQiIlN7yuPAixJoS9dLpcjAHxheBRsCuw6HXXoCLhYM/dAp75bDmf6LwA\\n5xxrjcxTsfdeKZqFu6qc+ks2QXoM5kvGOfIctDtHX9Z9v/mNf0HsAs6hgG81gXImk/jwuS4OY1v3\\nDHAhrzI/OL3d3zGd5CSgPaal9PsHT1+w4iU499Sz9b3EV7df/QLod3eR7Ja0mQ6h4nJ7u3sZudXA\\nFBbtu7kInQ3b7mZD4Mfgh2nT/bic+tf9pjJ9RLX3oBjhUYgRsLvh9H4mpLV+/nO9WLpYBKV85m4F\\n/yZT3NCBy3w2yCDj5VomxGqlsrP0Rp6WTn/4Qu4epnKpild/93ch6UPF8TdsCTYCydjjHHk0ll12\\n9fxf/KnixS9D0XFeNZ29E/GhwrEcZVRU86rATRzM6WYFL93kPYnOyvscrU3hlO6HNG2+ofCBeK87\\naiBOLDIU8eZy5YvY0bxqLs252ByEicfkEP7ydcPQLpIJhUE8rjgJty0qhUA563o6dv6Mce/DzyVz\\nZKHaK8FowV4azEfIT13kIA0YfUcF2KDHGWyzjeAzqRNv+c6tUB+LUvXq3CIcKiMourzuf4qZGfG+\\n+l7DI4E2QaqTgRY2rbZjVgX8G9bpL43PV1yrWzaos+I4flfbCVBetofLpELDyu6RDQIzC/DLAL4N\\nbKxSji5ZbdnV520OtnGhdM8XQB/kZeSvSxtbGNchh0823elCbm4OZmdISWuggdJNHku5+SVcOEbU\\n4/NmpqzvRM5c5hvL5aLsyB9deQkNRS5sSDpEdjth5KTXtWruBkbGw7HcJPdcN/GQ4t/g6n5SHEZx\\nPXi0zm11RIJ7DpFLceGv11lV9uqhc8c8Jj/xLPwv2OCU7xtIDMDrxkGpaMocnQk++KiL5mUhPaC+\\nrl6rtzY426HfiN/Lxu0Uyr+Xx5kE97q5OdQwocObSCyT2MmUWBEPtOvLJa7hzWciiwgFqhu5OYgj\\n9KiwcFIuPgpeMMTGpi8UcbvQ/5ideI2IMw2ejXqmiGRa9e+hrXYl7msf1H9aq9Ri/fp9HnaWipn8\\nynDCN3CXokOnlstXztOQfBVWrnEWy82kSVrsfqjJ2mm1/ctbKJmWd5mIgKTkPSxYpz/b2nuIxXSl\\nZhRGkCKgJTv7plGHUUlNP5/lFAH8Z51ApzzT2L8e2F0QtpxbtAcTVrzETN0actGlNpNopIAi+QG4\\nOu3+kWr3EoIQu1dG0HNwC37st0aG3OibEiga5a/BJvi0cV1thCvzMJjIuXw1bfTrnnt0+vHPiuFh\\nx8AenU5i8uldh0MudtHi+foMLEeIvgc3SccBdUkCLxjfjbt5u5NTFhhbkpsZXKPS7hm0NG8ZX3Q5\\n61Fr8hXqNVIH/xzBEK83TIKvHJ2vhPo565UTZCOZXy/267BmnBUGmNRZUDY/tF/ioWH4qIlJvPde\\nyZofqpEIioEbfqlp8T2BLH47UkPaYpg/Vz9p+aEimtMmBlR3zy5UH2xE4WOEYLdbcFPE0GHemEo5\\njuHk+GA6koj829HznMSyfKTJ60j7+kEm3qg9Iio0QC/sLZgvpY71ewUtjdh2Nm+AU289BlFnmo/B\\nKG04YqGrAROZ6lStuasvC+iPr5dJK2u3JsSnIYMqznJUt9yM3TxUxVYwHrevh43EglbXTt43ObJZ\\nhbCrtUPc5vv0dPp2jfKX9mFN6Q0oFT+3OJ0m3XnSMKxuL5Zusu9uRrKjIA9moRdLngizGl7vcaQS\\np+AUjsngxDLULGuKpZm+pjCm0qcrTYoxyMC0FaCyeT0yby9a32zJh/Ghf70W7sfX68ivy/CSBFay\\nMqFLKJW1Xl9qjFZQO2h4ufCvxeUOk92fftNFQ5o44HDgGtNNr0chwr6ena/VLvYynnLBzk+mMb8z\\n9SfzY3JhMHWCWgdflhgsoC0uYxYp9ncg7sgY8wxjiSvBbyD5Pipo4PhN4FjoE76xOyBQeXYw9xoT\\nZozzHeNYbvAR+7qa8Hw6/rTcA1B9YRPAApIWy7459OlOHkskZQFRDh0EBWshWPLIAZPA25g/c4DZ\\nBEFnfpW//Z2rdhP8xMXASnfVYtd7fWWwlQMIe+u8rNuk6hqw/IfYpCRt9kHkn0p/R5HKrIWsT/+6\\nlnfWd3TeFILLf4F617C4jSAj+8ubff3DBfZ1381xQ2eFQcw/b0W69W5X7PfcMLGMgbhK/7CKzCkF\\nL4+cqXbmf5JuPnyNWQ5KU1N636VzqBNRfiOXEXtXXg8tFa59OdW/Si2WT/d8H5d8hGEZhq1Apl8v\\nrorg3183WP6Pnb0ym6GrtZWqyCyDEKA58DPxbNGTrvM72IG48no15vVyVWlcvWUxjQgRh5CN9bll\\nkK6NCi5kjHUSjmkMelks0a2FOrMinFVHydVshGT6k0ZnHZv7PCnBMIB8L0KY1nwIUcX4J3Xx5osF\\nZdjpVG3py9AtE0kfDn5RJj3y4OE6s+D6ICSNPzT76j5Hg0SlNX5D0AOX0Y40Rbnwz0V9V2nMypUX\\nWRPRrbunt5v4jfDuLpqJkKX1SkxFozTut5ZWtiVxgA/9t3b0Zn5CK0dgKlWUv0p3xIgveV2i5H3Q\\nGF1jyPZh2NGi2vRXN02OJwkLFhVBtBjAdH8ik970sWuY7fvjmUcXj31Dl5FIDuiYVswsvKkB8dnD\\n9AZvBl3R7zkK2ztfXqqkWOtRdT/AhlKktNx4+Sq/QNoqm9cT8oXp34GW5ccrPR0JwvfblvhnEfxT\\nhZt2y4O/7TOYyH7erBQ9Tasb7S6sutwLGZdJjSbXmO2BQsqzIQHMF4FkNycGHib9XE8mja9/x+d1\\nbbL6vxOJt7nyxvhI6qjU5VPOn781QjMPneV3mfhC/729nsGWbatG9W4pVL2mK6gS+TBFy1HQPvA1\\ntcDIvAQC/zZvmNo62K7sbXzdHv8NmV0sjiX0MMwnQuyPeOZuCbr2X0BYp0Kvr/GKAi+hXsg4xHHS\\nOxySRDbJaYoUxqJ7uBcns1VfJ4nUb3+gLvHdzjLBihEIpVW73PwHQWLd5C82T8lO9k5lTMMQfl3n\\neaFeDoRikCp3n9LrKSTek26213q5jWqzC4OuX0kPcuxp5OPrWc3zD4Ty961sE9HFSa3ZdyZ6lnSg\\niHDE4HTtuHSyydfUQXxY8WRX1fs7qKLMIqcoFlG9ueYkPNlrKusmoOLZnzCRFpScYTLMx5BzsIWN\\nINFuPrOyHNq68V3Xz8n54xp/TLd/swVppR3qfc5+hq9q9bSXRQ0+57hsmnMo4Tqv9kOzyjsBv9DW\\nrqxH/NYr5yhrk8BSzbctDV0S/cR136JBuqEL52j05ssTgoUtloGOtkgpjW2MfSblB6n+7l+vFgsH\\nGYnth+9pDuV6Qr0D+R+oF/eVhw28E5VEys4OLR9XVcS85GpuftY86fhHdxbQ7KJC5n9is+1EQLC8\\nLqEzwt3MbES+zKk/xLdqhzgme/yFo6bJvMmlToza2mRgMIfMMBoGC77f2K1jzw/Pv9nr7QGL48ew\\n5NmYL7+PJZbDm1V+1Ms3B/BT6oINGXbPwfVCFbBd+Nud8hj/0/uD5S8n80o0OPMh5GisRdEF/noJ\\njidLc+RXQz98SrlTa2IWlbHvycVvfKBKW/PDYOag3o3+TwxvbIivduNZ22L/x92H18jNwaMgxpC+\\nbhBQU8ceAOHjh5pcnzgx3STJ7nZhOpgnP0savrrfSYbXS3rUMv/hwqKNSyzN0+shtEGWpb3+wYd4\\npcuJwGjMAWNeszjuOtYWRBQgQ1lkAXLa15OWsQ6aT4LIx1b12DEbpD7r3GZzgzoRGacjKbFZX76Q\\nyhEij9QEJU5oKR8umV5fVw11EcujMAfDNiR5IRuTP5RParlGLSb5WFPXr9PVLdWt8mzCZyN0xSSP\\nD1fVNaX5v7V4eb+u61aRLx0TMpZhZMv8fpqkf13j3YT1SJtsqJw3zCyMLDJD25IND6V2sPT+7RwG\\nhBO3MXqQHOkRKUuxgnc/Z2JcMIh28RyMCkvfqPwWuhIREooa7avljdbhc2lzNvwi4+vFnZVnZI6J\\n0JjXRZJe2XuwzEAMLelEWHXBmb/eYbRr2i0bBKQy7dSuDTb9LfXiyvSb2s2QmI9TjxU+Qt0Vf/1j\\nSdRAY2khHG5FkWcews+b25x0T4Zu5InV/ItLCR4k9dLchJXXts0T0kZSzRlduWSRpts8vx4fzG/p\\nfLej6lwHX5ANUgQkqbchy1G1c5hux+vfR5tfjK4yzvgrraq7WAwRpWMgvy2IVdWtNi1DnV+WRHOn\\nnf+DYErCj4zoKk2a/j8NF8ZQWtGvJAAAAABJRU5ErkJggg==\\n\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"% small image\\n\",\n    \"imshow(randn(100,100))\\n\",\n    \"\\n\",\n    \"% let's change the data range\\n\",\n    \"figure\\n\",\n    \"imshow(randn(100,100), [-10 10])\\n\",\n    \"\\n\",\n    \"% let's try automatic range and different size\\n\",\n    \"figure\\n\",\n    \"imshow(randn(100,200), [])\\n\",\n    \"colormap('autumn')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"\\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsEAIAAAAyRa7WAACAAElEQVR42uzd5dOX5Rc36oOWRkJa\\nWjqlpEuQUkQsEFE6pFMxQEkBaURaJCUVBKRBkBBEGuluUDok9ovv892/5w+4Z/bMnvN44TtnFO77\\nuj7XOtdaZ6zzLQVBEARBEAQxKPb/1/8BQRAEQRAE/38TAlYQBEEQBEEMCwErCIIgCIIghoWAFQRB\\nEARBEMNCwAqCIAiCIIhhIWAFQRAEQRDEsBCwgiAIgiAIYlgIWEEQBEEQBDEsBKwgCIIgCIIYFgJW\\nEARBEARBDAsBKwiCIAiCIIaFgBUEQRAEQRDDQsAKgiAIgiCIYSFgBUEQBEEQxLAQsIIgCIIgCGJY\\nCFhBEARBEAQxLASsIAiCIAiCGBYCVhAEQRAEQQwLASsIgiAIgiCGhYAVBEEQBEEQw0LACoIgCIIg\\niGEhYAVBEARBEMSwELCCIAiCIAhiWAhYQRAEQRAEMSwErCAIgiAIghgWAlYQBEEQBEEMCwErCIIg\\nCIIghoWAFQRBEARBEMNCwAqCIAiCIIhhIWAFQRAEQRDEsBCwgiAIgiAIYlgIWEEQBEEQBDEsBKwg\\nCIIgCIIYFgJWEARBEARBDAsBKwiCIAiCIIaFgBUEQRAEQRDDQsAKgiAIgiCIYSFgBUEQBEEQxLAQ\\nsIIgCIIgCGJYCFhBEARBEAQxLASsIAiCIAiCGBYCVhAEQRAEQQwLASsIgiAIgiCGhYAVBEEQBEEQ\\nw0LACoIgCIIgiGEhYAVBEARBEMSwELCCIAiCIAhiWAhYQRAEQRAEMSwErCAIgiAIghgWAlYQBEEQ\\nBEEMCwErCIIgCIIghoWAFQRBEARBEMNCwAqCIAiCIIhhIWAFQRAEQRDEsBCwgiAIgiAIYlgIWEEQ\\nBEEQBDEsBKwgCIIgCIIYFgJWEARBEARBDAsBKwiCIAiCIIaFgBUEQRAEQRDDQsAKgiAIgiCIYSFg\\nBUEQBEEQxLAQsIIgCIIgCGJYCFhBEARBEAQxLASsIAiCIAiCGBYCVhAEQRAEQQwLASsIgiAIgiCG\\nhYAVBEEQBEEQw0LACoIgCIIgiGEhYAVBEARBEMSwELCCIAiCIAhiWAhYQRAEQRAEMSwErCAIgiAI\\nghgWAlYQBEEQBEEMCwErCIIgCIIghoWAFQRBEARBEMNCwAqCIAiCIIhhIWAFQRAEQRDEsBCwgiAI\\ngiAIYlgIWEEQBEEQBDEsBKwgCIIgCIIYFgJWEARBEARBDAsBKwiCIAiCIIaFgBUEQRAEQRDDQsAK\\ngiAIgiCIYSFgBUEQBEEQxLAQsIIgCIIgCGJYCFhBEARBEAQxLASsIAiCIAiCGBYCVhAEQRAEQQwL\\nASsIgiAIgiCGhYAVBEEQBEEQw0LACoIgCIIgiGEhYAVBEARBEMSwELCCIAiCIAhiWAhYQRAEQRAE\\nMSwErCAIgiAIghgWAlYQBEEQBEEMCwErCIIgCIIghsXig1XQNC78txXeagMJskD/flB2EGzOB4kX\\nQ8et8HgZNI0Np9pCoV1waAAceQ5WHYG8aaDwfdj1DpRbCMtKwvIOUDsLdIkHXzeEj+7BxCOwvxkU\\nOgTtJ0P9hFBoDTxoD1Pbwr3E4DQsmQDrEkC77vDsWjjYE+7XhL67IeNRSJQOKueA42eh4GgYsQXG\\nNYbPZ8Ld3+DVC3A8A7Q5Dg3ywPxV0OlXOJYV1mSEzAtg0TPQvzN0/BL2boJldeCrd+FUJShaHgp1\\ngcxjYN8FaHYbyvSDB7EgYWf4bC20Ww6pRkCzb2FdN/iqNNxvA+mWQOU/4F53uLkabpeFRgXgi6Sw\\n4XVIfB1OzYSWHWHrZSg5GTIshLPpYU0FOPwMvLgPXhwDSQbAlhtwNhZ8/ykUfwbat4VcJ6HWSUg4\\nBy7XhVoL4PW3IP8V+LUmlHgd8kyB77+ESkPh/elQLjNcTQ5XFsLW9jDpLixIDHXfgzcGwIyCsOEo\\n5D0Fd9pDnu0w6yRUeATD2kPr+9CnJ3S+CstHwIRtUD8ZfP8VfHwLOtyHBgXhmXZwcz08LAal2kLc\\n83BpK2QoD28Pgp+PQ5VbsGI8bDgIlX8ExaDmZfj0HHT9AdZ+D0Vrwaj2UKwIdJgE/zWHAfdh9EJo\\ntxY61YEN06BoG8hbHsadhqqRP9WWcLQgpH8Thu2Cv2PB1cJQ5kvIuQrOtIAt38H7gyDORaj1Bpz/\\nCQ5vguqLoFcO+DgulG4Lm7rDZ+dheCc48yLUfBtiZYfzeSH+PIgTH0yFA7khUT3o+gYUOAgDpkK+\\n4XBsGLw0GGZfhNrZoN8XUHov5FgCtZpC3FUwZSx8VxTKzYHZqaBONkg+HyZOh1Ej4aej8FkGONMa\\nqhyDP2fC+VTwQmnI/SbM+R2234VBGSDRMkjWCur8Cj2qQbX9MAaU/wXa5Ye6XeHVU/CkGtR9Hj5v\\nC40WQNWWMO0nODsZFiWBNe0gzwLY8RgKXIInXeBJERj/CLo+ggzJoeVMSHIHHp+Al2LDgEUw6RUY\\nVAD2x4NLvWBWd7g6DFosh3xvwrtP4cZimNcbCo2G9b2gxh3IMxCyPwft/obvX4dJf8DEpTD4IGw5\\nCJXqQ5Wp8MIGmFUf5k+G1a/BkGLwy3xotgBilYBefaHkaHg4CGY/hm+SQb/Y0ORTaJodur8Ng1NA\\nxV9hwqdwIS8krAD/fQ05R8CRg7ByFqx5BTLugI4FYXVXyHMNfu0PJSrBw40w9QaUuQAD34L5X0Oz\\n2pC5AJzNATkTQ4734PNdUCkt/HwIuqaCsV3g3hjImQG+qQ23dkHsWZDlABSrBIPzQvNaMPEzmHQH\\nNm2HiUvgcjp47iR07wYtB8KaqjCzNLw0EdrMhvipYEc3yPIb9HsEH1aHoW3gYT14oxiM2wivZIF4\\nu+HiO9CyCvzUDkp2g+oXIPVc+PsY/H4Lfn0NRi2D35rBuX+h8BSofQb6jIQfF0GH3yBtQShfGGZ/\\nBIueEoucGSFdBqi+BXLHgWMloWhCuJwccp2Hh/3hxdrw8mho2gPu3IOiA2FELqj6AfxbDrrWgJz5\\nIH4p+CUvfLcfLuaDJkUgUQWo2gaabYEixyD7IrhzHo5vh4ezoeMfUOEwpGoNuTYTfXx8+hk0Pgo/\\nvw4TQNy7EKsK1CgOU1fBsXIwcTcU2wvr34X1ieDxbWi8HoqngcZb4eUhMGMofJ8UJjWEIongxVmw\\n5RiUrgp/LYN83WFWPzi+EIomgcax4ZeUkLEbGAgnJkDzYzD3Vai1GQpUhjLz4ackkCnySD0GB+ZC\\n4oMw/yfImwUa94VGZyDjp/BWBuidGCpngDXNYEkS+GQEZB8C/UDW5fDaXciaH77pDbXiQb9CkO4D\\niP8APl4Oe/+EvPnhve9gUE74rQAk7As/DYHiNeH9avBGMkh8Fe58AG/mgbid4XYPSDMNdueGOAeh\\n5ouQqxjcrwHxY8Or52DWEvjiF9icHb67DH1bwOdz4EFRaFcbyqSH/x7C2jnwY0J4vQM8KQWHu8P1\\ntJCoB2w6CM0fQJ+foENjSP8KPNwR+aOEl7LBB6vhXCXY+iLM7At1O8EzCSHLDEhTGyoPhEI14Ieb\\n8PIKqNQDxt+HI4/gr6bQfDt8+C3EvQB1ivzvZyBzHhjSC3o8hiRfQ/c3oNwOqPA+ZG8DS8vDhAUQ\\nOyN8WBfO/gMH3oeKDWB1SZgaF55vA7VLwYN3YV4e6LUI7t+Fe/OhVRp49TTEaQ4vbYezDSDOdigz\\nCf4sDynPQfFTcKQPvFAA8g2Bx5VhUjXI9heczAKzMkLDEVAzNSQ/A0/fhd7D4Z/48Ph7+PcqfP4l\\nvF8UdtSDcv1g3ptQsyPMaATJSsO5u/DdCrhWH57pAy3jQfGEUOMP+C0XpJ0O6VdA8bQwuCXkqQ9p\\n20GjrdB+IDQpBB1TQsFVkLEebFsNk96GPxbD0rfgrZHwXhro+Qek3AVJ80K1mdAhJbw1EP4CfV+D\\nJxtg3XFI8yvcqAo7BsLZorCxELywAg6vgYGDoPtkiH0bhoyC30/CO/khblLIUwxGNIWde6FVWSg2\\nCRqPI/q52OoBfL4ZnsSBS2th7SjoNwGqrYKZRaD+c5DnVTg2AQ4ugp1HYep1uDgB6pyFTVXh3dXw\\nbCpIfxFKlYTC8eHD9rCwOJx8HUbFggx/Q/bp0Kkh5CsOr02AVx5D2pUQrwgkGwR6waB/IHcsqPQI\\n9p+C376EAmWg60g41QTyP4aMXWFkcdiUB55/DH1mwr+dIecBqJsJXvkcctaF+2OgdW74bAaUngoV\\nI4WSF6BVcqi1GG6fgXcrQJ4fINZ9+Dk/ZJwPeT6Hr7+EtD9A/BOQNy4kLAM5ZkHNK9AgKYzLBae6\\nwbyBkCEDPPMhjCoOTkDnEzA8FfRuAB3rwshkUGAG5E4JNX6Byrmh+idwPg288BsceROOVYPDX0C2\\n0/BSNaiaB+qMgGZ1YFVciJccZleCLA/h2anQsxAUTQ7evQafX4dsRWDiEKgd+c5eDeXbQsbykKkg\\nHF0NX++DK1OgTndo+gGsWQ61SsLrkVfRGridEtqXh/olIdMRKF8F0peBAz1hyK9wrz/8MhXmjoKz\\n/SD9fSg2Ee43gKE/wYy60CDyi90LlqSFt/LDnmQQexIMLQnjksDOyvD3RKj6JSSfAJsLQJVE0LQW\\nXK4APcfD2nfg7eGQ4xoMWgh9Ipl9H0wZDyOeh5ffhUmrIMU3sK8cXEsHe2JByrcg/i3YtQAeZoBC\\nk2Hkq9DxCSQ+B6eSwtgpEKsxFM4OVyJZ/mNYnxtSdoWeG6B2W1iwDLIshTuPoOoW2NYNbk6FT6pC\\nv91QcyvkWQl/ZIF/dkOBmjBtGaQeCi/VhIP34OEoqNkFFoyFIalhQVa40RCmL4GT/aHzl5DhQ5ic\\nCbotgVdXQant0GUznMoAJzLCwo1Q7DrMzwmT1kG8S0Rj/cCykP1HSPsAUl6Agr2hexsY1Qgm/wXT\\nN0CiunCkIbTKBC+0haMl4NE7sGEl7JsA7ZPCf59B3N5Q8AtIcQWGdoDDw+HAIEjXBl7+ATZOhiv3\\nYWdsmJkZrkceOhXgy7SwYB3UfweWLoWiCaDkKTiWCk4+By8Ug02XIPMZ6LcIVt+H2gvg8ftwsS3U\\n+A7eSgfDN0PiyCNmEnTOCK3Sw7Nz4UoOmFwPbkRi8QhosAWKtYQH/eHQdKi4BHKOgweloXcv6J4C\\nfm0Gi9vDd7Wg1E/wcVb4Li/sTAIfVYRkD+CtebBhGUw4CwuuQuYbsGg9DLsHs/ZAn0zw+UnI8R2M\\n+5BoCM6wFCaMhsxF4K1esKMUnH0Hcs2Gv3+DCg1gT3socRXmjIGneyDdVlhXBRYlh+aF4fPvIdlW\\n2FcIPl8GJfdByv5QdybETw9/V4IBGeDDj2BPWai1BsYPg1UtoftSSNMGpn8F/3wGVcfB/gXQYDJ8\\n+w80GQkT8kDhv2FBHNi9CtJ8AnWehTz9YfIyyJoRnv8C7l+B85vg7Fswbw+s3we//AMv5IaNTaHn\\nU0jXAy5cg05j4UAuWPsaTC8EDsChL+DSNVj3BcR+AGWnQNWKcPARxD4Lf1yDbmnh7jtQqj/8vgCS\\nH4TDRWBpfPhmDyQfCUWfQOl+UOMstLkI79aHuGUg3xMY+ASyXYW46aHUNHh5ITS4B7OLQPH8sLgg\\nHG4Iid+A6elgRB1I8A3MiQU7ukLyVJB/HFS7AA+zwJqD0Pd56NMfFtyBaXEg+VFI8Rhyb4etCSB5\\ncai7H0bvhYEZYWMrGNEAjtaA2emgykr45w7sLQU7L8CxjnDjDJy5Da8shKPXYNKf8KglnLoNvR5D\\n3jfhdOQdnQ9SpYdeW6BoE6iXDDqehrc+gQOdYPaPMDYRLMoHBTbA3/Mh56tQoQosfB+uvg/fvku0\\nKrlmMlxYD5mGw6Kr8HseODAazrSE5cUgX0d4YRzU+L9ORZZdhoULYWQPiJUDiv8LDVpBrzNw6xk4\\n8xoYOBzS9oD3H8HCfPDHAkhzAJImgdSNIHZduNELsmyBZV/B3qnw+zLI2QXufAk9VsKX1SB1Sbja\\nGl7vCwvuw8ftYOwJuJUOSlyBPV0gTltYWx8m34BcOyH/Q5hdFz4+AccHwZRnoc8FWPw7LIgLjX6G\\nLrvgj0fwTCGYfwzeKwp190KRinDkO+jVArKXhGEroE0Ooi/+apP/94OVryJkOg3708OKqXAiEfxx\\nHsaPg6/TQKzjkDoP5IscfKyFOzmgxQ+wciRkqAe1SkCpgzDvJOxOBye7QrpIwXYQ1LwAf+WCWzMh\\nbwdYfBd++Qjqzoa9/0G2xDBgGpQ9D5mKwpbSUKoAFBgBb/WFbzbDV8fhn9owtBgc3AqpUsA7C6FR\\nI3h6GB5lB7/BrdXQ4T04nQGeZITPEsOidZCrItT5Be78Dd2vw5778FJayPMN9P4IllaGQ91g9yN4\\ncAniN4DR3SDHj3DxMbx8Hc7fgMW1oFweyDgdhkYeT5/C6OnwoC+sTge7hkCLWPD2HMj5C7SvBpvP\\nwrwB8HpZOFYMJq+Dt+JDlgfw3XFo+xx03gaTLkPu/PBcCxibGwoWhzK5IGNpWDgFjraDJGuIfq1u\\nWAxFficaIp/5muhvxFvT4P4SGJkF5nWGR4Xhxilo0g7y34M1ZaFVMSj0E5zfCb/kgYRvwe3tcOgk\\nZJgDnf+FXZfhYSkotQVW7Ic/O8Ow6/BLKsh+AipF6gpz4HRCeLsInHkAk69D6mJwvi6sbQEVdkPq\\ny1C6BZS9BEnXwMZnYeZM2JwE+qWAGb/CJ+/CpsWQoSz0HggDakPZVZC5ApRNDoPGEq0u7zkCybNC\\n0VuwPyu8/TPROmLvo/BDCpgGHj4H33wGu+5DssOwvz60+QJuJYIuf8P+ilB/BKQvDW8PIfrKqZsR\\n/iwLb+yDbuUg6zswbiyUfQYurYeZO+FCY3gcC9IOhwsPoUpeeAw6JIN8xaBFAihyB1Y1gyefwie7\\nIVd76F4Cvu4Ax07ArPUQrxA03QT5dsD0JtBgKtHg2HU9rOoKe7ZB13rQ5wWouwXmVobKX0HiQnCt\\nJXwyGR6UgOrV4UYh+OYixJoNGY9DnjGwKRasmQglksGz6SDPcRi7Hv5JAyOGQOJk0CAflPsX+heC\\nM5dg2H9QrBf0rwH75sL2I3BoGDw6A4uawu/b4fgCuH8b5uyC2l/DzUpQ5jHcGQVDDkOubfD+GJj5\\nPtRpBr9vBF/C9Jvw+k6YPAP6Rj5RcsC+hFBrHNzNCMmqwPBZMH4RlI0NacrBqKZEm2HKboNkL8Gj\\nEVC0FFy8B5/OgJajibZwrGwHHzSG9dnhz+lQ9TmIXw86Z4MXD8K1kTDpCpSJnIaVgyrtYGN8qFke\\nkhSEiyehyRiYfQDG/AaDU0OKeVC8C0zNCHXrQ8si0D0/PCgCedtAzxpwZyJ0OweZ40OlO7ChIjxf\\nCE4dhASrIdNV2LQexs+A5LUh7wLofhrmvQ1O54XLb8JPE+DZanCjAdz+FVY/hN2b4PO+MLgyJLkB\\n5QbDkch5ZA+4Ng6WDoENDeH1+fDax1CkIJSuCw+2w7ksUOsuHE4GvTsRrUJFysstXoV5zSFec3ju\\nc8hwCDKdg9MV4U5++GIffLcAZmSHHg1gaQ9YdRz+PASPOkLL+kRLpnWKQb0kcLUbdL0IPfJAzrdg\\n5gP4rQGcmAj//AAvfQdbb0GtzvBpXTixAtq/Bt+chgKPofIg6D0T6h+G3ZHi8Hvw70twqAwkPQQz\\ni0PG5DBzNbxeG/7oDuNrw8gOsLQXjIsLC1vAkpTwoAw82wW+PQGZu8LmGjAsLvx0BT65D3cbwYmC\\nMOIbOPYSbN8Bi8tB+rJw6Bz8Fvmz+gIWTYIlNeDcNhjzHPy5BA4VgtXbIEMm+PtveLIX3v0bZk6F\\ni19AynWQvSiszQRHXoEbeaD9NWg1FbJeh6XbYF5fqHkL1j+Atr2g7lZIegqaJyLaCbR1MNz4Gg58\\nDuPHQoFK8MJK+GoXPH8NfmwJxXLCyljQNAc0/x3id4QTkb69+pCzJXRMD0NTw5vvQPpIn9B4mB8J\\nHLkh2VV4byTsmQXDT8Lo5ZBwPeS6AlPPQvYU8Hg9rHsGvigGjd+Hf6/Db4Pg9VzwQySUL4YFb8LI\\nZZBmFHxWF/bkglw14Wp1+KoEZP0X8n8Em4vChjywNSW8mBumDYAhHeDBboiTHq5chU4ToW1JGLkL\\nMh2EV55AwcSw6jqUKgV5S8CYY1B/EtQoCHNfgJ4NoHoSKNscnm0LhyvBjv5Q/Tg8bAX/7SRayVvY\\nEkavg/d+hPKZIO18SFEeag0hWrGo+R/RD6EiI6FJanjmW+h8HyoNhunPQcoycHE+dD4Lv0e6jopC\\n4uehUAZ4dBoWHYHh56HLZZiyEdatgGaRGJcA/nsVri+AGpH6TTu49gvMyQV/7YKEleDLA5BhHnQo\\nAfu+gvk9IQd47j840wvmXISVSeGvszD4L3g/F1RoBzlvQutxsGkvJI0FH/eDNPOhz4cwshK8NAiO\\nPw8zE8DqpnDga7iYDrqcgpq54eMDMHMEHL0Ms+vD+jrQLQ+UuQwDi0D3X2Dy55D0A2hcA0p1hvjl\\nYON12PIC3LwN7QfDr9/DOwnhVBF4GBfGnYAHc+FMGyiUApZuhHh1oGNaeHADdpWF5Pvhu0cwpDDR\\nLtXvPoCU9+CdZrC/NlxKDVmqQZWdUKkVDN0N73aBaVeh8auQtQZcKgWpBsPzmaB6LsgZ+RxqDz+l\\nAs/A3XSwISvsSg17MkKOtZD+GDSoCDMnw61UsC0+lAdNO8Lvo6DVEpg5F7q3habdoXc6ePkfKL4a\\nMjSCXKnh6oew/j7sawRF3oDv+kHXb6FaNxhzEga+B1P+hkfHYWIOaNYA/r4ECyZCjq1Q4SGcmA4n\\nD8D8x5Av8hv3Kyw+D1kywsQK8OR5+G83LPoOUr8N47dCvolwKx78eAT2LYUMtyDvE1g9F9L9TFzO\\nfwqpD0Pd12HHn9D5KXwwD975kmi/Qrau8M8u2LkdJtWEwaehdnFodo9o8bbPbPjzJvxXG2rUh0N7\\niDZHR16caepAh0hjdSYo2wSe3oFsiWDmaJj6CtTrDkkGQ/9O8OFGeHY8LMsJr70Gy1dBlafw4afQ\\n8BJUbgmPrkL272DVh7BuPLwVKd5ugz0/wAsXYflQeDMJFDkIY5LAqU5w/QsY+Bm88i7s2QWTa0Ci\\nfNCyKDz/ALJvgRn/waNvoXakYvEQXlkG9UtAvx+gdTbYsxwudYKKg+CHpfBdejj0GkzuBv3nwLKW\\nsHQhnHgeErwI4xfD979A0iZQ9xDRusLu1lA0NtxrD/1ehRzdoWEcqPs2lF0JU87DO0Xg05dhdhfo\\ndwha7oWJr8GaKRD7b/hnK/RuCA9mwrqS8Moi2LAefnsKF9ZAy1xEX5aVmkOW9+DiGBh+CtIOhso3\\nYdU8aDYUTj6BPzZAxc+hzCxIVBx6fwNNt0LGlPBCa+i3Dv79DV7OBs+1hO/rQPkmUDQjDMwCCyfD\\n8qJw5wqkXwlPMsH0PZD2P/izDXz7CpR5DvL2hI03oWhauD4NEl+ACt0h/jXIUx0ql4TDn0KyT+G9\\nwUSL5Ev7wsY3IWNCeK4dFFkOiQtDxuFwpgisWgoNlsOCyZDpfWjSEbregNuTYMQSuJsZJjaB5fkh\\nVQ44XxKaLYUrueCrzrDmC0jwDEw8Bi0jNbCEsHM0vNIHuhyCZ89D7Uvw0Sg4chZy/AcZOsCHhaBr\\nAUj8ECYuhGzpoPVI+PMVWDULTmeGVg/hyT74azDMWQcjWsHNRjCoBHyRHu6mged6Q88TUKQ13JwH\\nvYrDcy/Bxh1wINKtsgTm14FROeHwDsgQCTSVYVtH6DgB+p6AxfEhdWrYnhjaloLBs6BeS1jcHw63\\ngiKDYXxkwCgVfPo6/PIYun8Cz9SCpV2hyRCY/Bt8/Q/UGAGfZIHq06H5EYi3HQZdhkvp4IsBsCsf\\ntPsd+laHRROh+YtQ8A24mRYOdIOHleHCdBibH34uBr+ngLxlYOAQoofL23tCj69hWAf46gh8Php6\\nrIASZ+H5vDDjd+hxFkq8DReOE+0frdAY9tSFR1vgq1vwXiq4uwmKpSZ6/PRlpEvyBsyKPAeKwvQz\\nMLYK0ZdowrTw+xpoUgAaDYQfz0HGxHB7DsSKdET9A3UyQ5tl8Epa6H4YFrWGKbdh0DV4biO8mxOS\\npIRZiaFKP6j9JhytBx1ehgUNYH1e2PAEPpsL/70Bx3LA5vHwZQ+o/DJcrQd3hsLRtjDhcxi1B1Jd\\ngCNz4WoruHsKtmWFlWuhX6QuWx5mPQ+/HoL770Gh9ZC2EfToDhMeQO9IWWcT9L4EL5SFR0cgWQPo\\ntA6KLoCST6HqE7i7H4Zcg0s9oVQ9GBx5OxyAqYegx01o9QysqA4jV8D1F+Cjf+B0ayhenWjcz5kL\\nVr8LCX+GTGNgVzG4lQmOfg+pG8KCSB16LGwoDsu3EZt4HaFJcxhTGmI1hZVH4OcNcKQojK4FS6rC\\nP/OhSC7IMwyufQTDnsDcYfD9Q+i1DmZsgZXFoPodmJgA/mkHzzaBh80gdwrYtAzeqwnt98LnCaHg\\nadhyHGbtgOeXwabd8B7I8iZcqQDnjkLVnJDwEsw5DJ/XJNpVlvcoVC8CpXrDb+dg6BbIUQIWjoET\\nQ2F7Zfg2FawZDweWwHM5oUgq2FMAqj8LFWZAo0PQ6SKMPgLPZoQzlyHfU6jTDqp+CJdqw6NqELs8\\nxHoILWYSLcKfKQr70sC16nDuGrxVFXaVh3unoORt2NECUpSCLdVh+HNw41vofQuebQcH60Pn1rBo\\nOvy8H7Z1IDrfcT4t/FcQrueDq/HgTHmodg+SloFNteC3nNC+OpTaCH3jQJd/4UAxuNsXYreESqfg\\n/fVwKS50rAmx28KWl+H8bFiwEk6MhpWF/vf/nmccdK4Es4dC3FuQ/TTcfgyfn4KP68CyVbAiFTyo\\nC1fnEn2s3480pS6Fhm/ChSIwYDG0qQ2PV8C2O5D/Y2iyGtJdgxK9YWVh2PY2FN8II1+HZE+hyhcw\\n8ww0XQUPOsGoTfDcA7i6C16rQfRYJ2tDWFkdBqYm2t34VmRG9Q5kXgNX0kD/nnA0ctBZDBpWgHkj\\nYNozULIm0cnQQi/Ba4cgzUdQYREUaAVJXoXqY2FJC9hxF+bNhFPziU7/rfwX+rWFnt/C2CtQbynR\\n2nbczZAqO0zJAtNuQqEf4VAiWJwWXs4Dt9sTPRi93wqKvQbTFsDsQZB2IySdBh89DxfTQPJvYWlq\\nmDYNMieGOpGjt6sw7zX48Q8o9QH8eRTqXYDBkcOIyE/4i3BwCsw7Cp/MhcL34ForOF4G7s+ED9LD\\nxVhw4RLROs3I8bD4I3jvIeTIAJ33QO7UkCg1zN0GW3fCS/nhnfdg/wVYdBz6lIL+zaBpIZibHPp3\\ngY9Sw6BckP97GJIPtsaBN6vCgzOwPTbkmQvHesOsn+HjhbD4GlwrC+2OQvqDMLwNDG4FuTZA3odQ\\nYAzM3w6VZsGqhZCoHBRoBBuHQ775sGAk0RnPmpeg43Jo8Q1kXAVHD0K1gVC1HFz/FUpnhM2b4fYy\\n8D4kmwujtsDSNfBaPfi9CByaAbGvQZUN8MZmmLYdan8Mz/wFrw2Cgf/Ba3nh4kxI+yzM2Ai334Gt\\nU+DwX/CoD/S5Cd/nhq9TwpQW8HQ6dDsF9xLC6PwwcirRec9IF9ThyATrCXjuB8jTGxbmhNjfQ64a\\ncOpHeGss/JEHxu6GpJWIzuLNvg35v4Q1x+C7NtDvb1jbFvZfgzgF4Ysf4dNV0D4bNNwLPQ/A2VzQ\\npwSMHwDDT8M7L0PeQVAlMjO4BOZdgdpjifb//ZkEphaDZKdg1xl4fRks/JboWMZ/DWHmd5DvL+gx\\nDnokhQR34F5DyBZpdFkKBVLD7uww7Tz8vRR2FYDK70GGjdCoJjTNC0PuwDMn4NePYG7k6VQVmjyF\\nJNOJS/GjcGM6JB0PL/0CfZdBjyPwTSc4uBlKbIMXXoN692FsAXh2Hez4Fwbsg+4/Q+dPYcsS+Kwr\\nFBkF366FRkthSm6YlQg+/ApmDoErl+GrZLB6NTyJ9CV8DG/8AO0eQa40kPEgdCsLJbbAawPh0BJY\\n8Cck/hna54cuc+H0ffhgM9xoAS/nhL0TodV+/t/axiP4JQVsvgF5U8KpnNA3PtEukNGRwf4hcKAD\\nfFMP4o2Fulmh/yNY1ReOJISWkSS+G+Zugau5oMgauP8v7HwHdjeHj6dB/7dhx154oRJsXQCNm0Df\\nDDA7Miy9jujZ/9VITSgeFEkDWyvCq+Xh932wbiqsTQA778O4aZBkG8xfA2sihyZtYWJv+K4lVD0F\\nOWbAwKPw4mIYETl+zQlr4xFtVf5lLryfFlIuh7jPw/gK8PZBqDMB0g2Dq6ehU1n4sgIUWQbfRxqc\\n78OKxPA4O9TdBzt+gCaJoOohyH8atk+FoV/B6VYwoRpsOQmPCkH7cxCvLuSMA8e/hANnoeN42JEX\\ntnWHnTegazyY/Bg6ZIIzY6BvUWidA2bHhbgbIP4UKJoIzu2AtPvgJ/DjHej0JTxzEdJkgLs94KVG\\nMCYuVNoOdV6E80uhwidQ4TFcbAbdZ0C5xtDnMuT/FQ70gfIr4MY1uFwZRnSDemNgSz5I+BLUWw73\\nT8Le+1AoHdyL1MkOwbH48M4yKH0H7o+GsrEgcWUo2Q86pYWZpcAmyJIIUs6Diunh2GYoVRnefROy\\ntIQaA6F+VchUE/Y+JnpEUug0VDkLUzfCobfgjxZQpRMMyAjN34Ly/WD+t9DoAaToDttOwHdZIXZq\\n+Cgr/JYeWtyCOZGfrsxQ5x7RGlKjq/ByYXjyOjwsC/H+hSmHoch4uLwcvm0CI+vD8Ej34T1IVgd2\\nHYQHHxI9BPw50hv0NRS7TPST6a8qkHsGJNsL35WB8tXhi4dQOvKJWANG54OmZYkehVxqA/9+BnVH\\nQr0uEDfydz0KNsSD+D2h+CWi9YP9X8HUplDxU1h4HNZ0h7lPYX0sqJgLiu+G2+Xgm1kw6Bzs/BA2\\n/gA1asMvmeHhDKg5Ey5khheOwf698PYV6BYJ3z2gRAHYMwOqvgyj90CBZ6F2RXgrDpy+ALUyQ/q8\\nkOkJfFATmjSFBXng5jj4ojbUrQq7I8/MarCqKJyrSnSC+9NYkC5ySB05iE8EayO11fOQ6DzMTg/F\\nI1XMeJD7ZxhfE0ongZUVYEBvOPQpnDwIRa9D/qww+hdo2hra/QUlvyY6dDWnPqxNA7Fnw3vHIE4L\\neKsclEoDeX6Bmruh6J/QJw/kbQSdZsC73aDQDMi1Efplh1r74UJZWH0QziwgOgV5uzMkqwWrEsDT\\nnFBlDgwvDwl2QKWucPcePC4BgwdArPSQuxG02QAJx8MfbYgWdwr0gzV/QoGpMGEtDB0M2apA80i3\\n7lfwdg1oWgHGNYLh+SFtf6LP23txYNcUuJYavsoIzkyH15+B8/fh7cmw/TMYOAzad4BRI6BWDcjV\\nAtashUKZYdFsyNQJ8s6Drp3hy7MQvyTkaQatR8GksvBKPtg/BYqtge1xYf9RuFkMBjWARKWh3mI4\\nNA1a/QiDb8PZNvD0eWh2E/p0g8S7YfAnUOJVWNiZ6Avgp6ewKScsugU/XIEaeWDKG5DlD6ibDjpe\\ngtyF4fR3sHQPDNsNPb4h2lV2dik0aw/v7IHU04i+2hushOY94OMPYVpzqH0QpjeFgtth7PvQOPKw\\nWAnVT8GHx6FJV6K9awsGQo8SEPsOHD4P5VZAxnKQshu80ApSZocXO0PCV+FCTthZDk4vhPa1YP8o\\nSN8Gbt+F2J9CqaHQIyOM2AFt8kG67ZArcjzRCGp1gY3riD4ItuyBz8dDgRKw4yrUzgOVSsDaKjD+\\nIxhwB449hezN4EpkGjHymo/8nw6BietgznzotB+WFYEP1sCUpFD0Dah8Bfp9ChNvw7bLMCgJPIm0\\nMKeFL16GMTXg616Q/mU48BTe2A3ta8CJa5DtF9j+B3RIR3TK74MkMGwNTE4Mq3vB1r+Idl3MGwSN\\nr8HVl+ByXti+HC58AM+XhDVJ4MPIN2gfuP4pJF0C+S5D9mOwfBA83gZlxsMr2+HlgZD1Oxg+B9IV\\nhq2VYd5KSJITpm2CN9NDmuxQYACcaAhp9sCjLLDpJuQYDD89hgrtIc502JcA3usGrdtA1U5wbAXE\\nOQ0De8DWl6HeAHilBfy4DlKegTpjIcmHcPgilJwBebrC2LKwcwNkzQ7vX4cOCWDKh9B1E9ydCS+3\\nh33D4P5SmNgSpneDSadhVgYY/QNk/we2pYSd2eFSpCbdHea0gWRdofEYosevmUtCz/eh0RW4Pxuu\\n7oXXzsGk4tBuNdEDx8haitFbIdMGSHMFXpgNZ4ZCqxdhXTzIlxXiRrpga0Dzs/BONri4F9a9DnHy\\nQuLyUHkPxB8HW9ZC21Hwyib4dDz02g2FksHvS+DHD+BcRbh4FZr+Av8Og+ORvs8P4dev4PI1KHcE\\nbv8A/fZAxmpwdR7R46esteBqJUgxE7bvg6JnYeAeePsq0ZnWDq/DgwuQqyDsOAzN98LNOkTn+9KO\\ng4qRZ+AmyFoE2rwH7cZD1qbw8EvIkxX2XIErdeCdTZBiJ5TMCkcjn/HDoEFeKHoF/joPy29AqfRw\\n9QFMvEV0DCXySfzmq5B0BNzLB78dgyPZYEIG+Kkl9F5NNAg+HgkFMkGnuLBvCKw4BC9ug1HnoeJQ\\nmDMbfmgL2T+Hr2rA8mfhzJew4kW42Rz294W1C4iuTnglEg3Pw8d7icaLaZ/D/QswMTk8fAo1x0HG\\nBvA0ExTsBOlSQpMkkDaykSsjDBoGrYdBk4bwx5uwoR5M6wwHH8JXD6F3f6h5FO6Xg4ZjIWc/mHwF\\n3v8RtrwBp+PA8t+gYSzofBGyxyG6bOWHfyHFUajfEU5GauTZoPpBWFwUsiSA3s/BsTqQcBOU3Qnn\\n8xGXV7fD0bFEy2gnj0K70/D4C1jWB7K9Diu+gUGHoVcp6HHvf38B38SDwS/Ahf9rEcPz42HgQDiz\\nFVLkhT8iOydGwBeRJsc48MUYSPU90WUNm5bCjM1QbwPcXwerFsAzW+G3yC6KKZDuLdjXDrJGvpYG\\nQI9X4dY4OJkB/r4AY8bBwEWwqRQUvEN0FqNyfnhaD/aegIO/w5U/4IXY8GZjaLwRii6C5VngbCro\\nOxVKXiW6BPJMZApvNiTpDn/fg9fzwfw40P8zGP8FNO8A2/dArDlQvxH82QUSroJds+FaA/g+DiQY\\nCom3wZ2OUL0EJPkR4n4CRffDgLswcwrsPQNzP4HqTeB+Zxg6ApZ+D8UiHTbdoXNNSJsVklaACwnh\\n+ZZw7yHsPw+jrsGOCbCiPlybBa/NgL93wPGd8HoOmBBppd8HfWNBywUw6wOiK/Wqn4WLtSHuLPj+\\nAkyeAJXfh1zvQYVjcK4IXPwAEkZGIsrDDy/Cj3Uh4RHotR5SxoaHHSDpFnhhLyT45H9/48WSw9bu\\nkDUvxD0GR+PDzMNQtQNsKgbTO0GzAdDvKcR+Dx78Db1+gYwt4fddRNcBLDgBa7LDqo+heeRPKQdk\\nvwmdZ8EPkY1uBSF5XUh9Fer9DWlvQePPIFE7WHgFMn4HBZrA0u3weAZcrAW1R0L229BxO6y9DbVy\\nQrJ2RB+pSUZB436Q7Tfofxz2PoCpF+DTfHDhPhS+CGXPwdkmUGgxTIl0R22GOG9CgRfh8+Jw/RoU\\nfg+uj4WhLeGbXkSPSNbnhDdqQ+pS8FJk5KUJHN8FSc7AhrvQ+V1Y2AfqR54P82DzX9B/J/w7Hdbt\\ngu3D4OJZqHCTaBfdqPtEu1KG54CRuaHUPEh5HD5eQPQTJX4xaJADlt+Fl1LAe13g38wwITKAgmgl\\nI8sxaPoxDKoOu1ND7FJQNLIxqyscbQMHfoWNGeHrapB8LzwpDk93w/V3oWAV6PMPFLkLH7cm2tu3\\nqxmcSgTJ10HaU5BlAaw/AH+ehuVHYP4Z+KwjrGgCX0SOFF+G3xpD0ueJ9l21PAXVV8I7u2BhJXj2\\nFRhaHuLtgi8qw5MhULUKrPwLrlyAf8pD2ZtEn9s/1oZVB6BnFVhyCqb0g1Px4e3xMLM29M4OW5/C\\nwlfgr9jQajsMfhd6LYZUZ+HV96D8dzD5BaJN8a3ywp4lMOwPKHEYFkR2enWDApehx5+Qrj5IC7+V\\nhQNZ4fvZcLgjHE8IP2aGcpEzk0iLyAz44xXo3Qc27oQOE+GV0UTrxP+Og7ovQJcRcPM8pF4BDXPA\\n2cJQ9Bj/pz9ewezQsDm0nAb7IsMN+2Dj20Sr489HNsNFOrGyweZssPQGfJQXYh+HryJjJR/BiyOg\\n/idQYy80bQr9IgMQmeDTXyHlaZi0GcZWh5yFoMDHUP1fiL8IskyD1ukhZ3m4UhxWzYcjrYimna1f\\nwaTp8HVSWB05pozsHFgPK2pB67owNhe8XxPGzoWyP0Py54lLijgweijEmwprekL5U9A2BwweAndH\\nwZyx0GgGxH8Eyz+GjQ3hQmc4VhSW7YTBEyDvPsjaFb7ORPRLN1IV+Kw30VdUng8hWXzIuRu++gFS\\n7YdiJ6DhBtj0PMyaAisjG5YvQumt8OoWePUh3OkDO/NAn1gwcQGsOgNT5sLWyBlzU/jtJDxND/Nq\\nwJnfiO77/hd80hcGdoSi24keZSbPCa8Og9XzoXUuaAy+eh9+2Qu1F8PoLNDoPch5HK4XhTaH4Ntv\\nYMl2+PIVeDoIOrwGf92HB7fhhwvQvSbk3AztBkG9ZyBNF9g7F9oVhk3JIMN0SLcR/qwLKfvAlR0w\\n4wkUfxtaLYa6xWHFa/D0I/i4PCTKC4cjE1sFocFdGNkV+n8EHZNDih2QuQy8eBRmtCLaT/C0HWyN\\nzDmegme2QP8jcKs5TE4BxY7CgXPwdinotRT+2wZXKsOSBLB+KJz6D1LGhTVjoMwxUB1OPIEeveHP\\nyNFAXaj4O5QqBuOrwQdfwQeTYNUq+GU7dIjMpZaHbY3g4DJI9z18WRh2rYCS0+DWSFjaDTpGZqyG\\nwMF6MH4lvP0pZMwGnc5B/YJwrjkcSgtn/4JExWDqEvh4KizoARPKQu0SUKEO0f1SkVfClNUwIRn0\\nj+wbWwMvRV60v8PgrTD4DqTfAQXqw/bbUPB7SHoSBg2Ae/lhwj6Ynhd+7wtvP4Xqo6H8T5C2ELRt\\nAQ8Gw7C6MOsPmHyK6LFgvDXw9W04V5/oEVVkICPWDvixMOQrDQUqQt5usKI/dHuR6MhOjRVw4j84\\n8Cy8+Rk0iTRoR1oCVsKcFtCyG3ywBM5/TPRug+xfwatn4MOt0CAuJCoPXW/Bz3FhUgO4Nx5S9oNf\\n+kLl4/DHIej9JeTrBm+PgBqdIOErUH800Rb1jn/D0EZwvAmcfQOaTodWkanAwdBxJ4zoAu0jFYIF\\n8NdK6FwANuaCirugX6TGMwGeyQAfpYC2WSBjQRj8MfRdQnRpxboeRJ88j9bB1l3w3L8Qrzh8Ug0u\\nHiC6xHjJx5C+FeTYBjP3Qo3JsKQk1G8P+UvA4QcwZyOcPA3t7kP9AXD3dVi7C+63hyUX4cJyGJsa\\nvr8P21LB9Z6QNy+keQrbIq/qe9D3EZTpDjkvwPjzsPsErLsJDRNC+9NweBbRJ9iVF6F4chhyAtZ/\\nT3RZsaJQaiz8+RzkfAOeOw5Xn4GCNWHzfmicGTplgKxrodtSSLIQ0v8Jfw2HjeXhUlJIlAZSfQ4T\\nP4STu+FxfOicFWrfg5y54WBryFEE5qWBYpHDx67w/FDo1g+2FYby8eC1glD7KCQuDtkrQJYi8ONx\\neDCbaAfY5sjM5h3IWhN25oJqkdi3HJodhZOFoexGqPw2bNkGX34OS1+GP27C4RPw0yjI+gbEzgKx\\nIiWGiVBmJvy8Hj59CtebQOtI2nkZvm0Nz+yC8a/Ch2dh7Q24uhwKdIMUkYXJ9+CjGZAoEfycF0b/\\nBF+Piv60x2ZOBnh6FNokhSePYHAC2NMCvi4F738I70c21VaFLptgSwKQAhq0gEk/wLaCcOMzon0q\\nl2tA/cikW2TKIyG8eAlmXoJvLkG+7NA/Mg+4kegkUaEk8E0ZKPEIku6DWVWh1goY/Svkawy/JIFH\\nH8D1v8Hn8E016JcHLgyGEw+gREOYOBOyPIFxhSFbR3i0B+a0hFVPIVdleDYbXBsNDS7C0MjCul1E\\nL0tpGxe6t4MpmyBzWejaEc5UhpHFYPExKDgJxqcg+lrd0BPGRf7dIlBhEjxKDQ03Qc2qkKomvLIN\\n/q4Mv++H6k+hWUu41Q8uJID7i/F/9onXvAHrXoRt9eBoBqgY2ZISGRJeAocHwPn98LAcNB4MY8cQ\\nvbao6Wzo+SOMrA0LSkHxujBgAbSbDFnLEj1k/C4jlBsFG6vCyM4wJy2ULAL7psDXy2Hu9zD3Lbhz\\nAt5bAUkTwieR4f9IAFoNqTNBre/gz+QwYTw8PAaHVsCiPdBpI9EN3TPyQpvviB4Y1bwLT1pBin4Q\\ntxycHANLd8LqRxD3V6iRBeqUgdqPYcbPcOIjyDoBfqkKZ5bDy62hRWd4fgSkHwPn7kGOfPB1Y3hh\\nOtFOvk1fw/K/4adFkLwi5IwFQz+DnS2IfqhEVonO+xJyp4LGj2A22HSGaNvmhh8h8VI4kxsG/Qur\\nUsP1oZB5L0zqAVnPwotg/GH4vQrc3gpp34V5meB2O2jdGjJWhWIL4dAYiFUM1kYGquvArVvQNRf0\\nzwBHksOja1CnMgw9C+VawksDoPhMqPEFFI+soDwJX3aFTu9BqX9h7tuQLrIr/yHUfQ0aXoYtLeDx\\nHmhzH7J9Dj0jIw6FoOUbRGtmkWnQh4WgfDmibRIdmkGKg3D6PNw7AG2KwNyf4NlyRGeZB9+FIx/C\\nl7fgxlE4sRu+PgXDekGayO/UcBCp60QO5SfDqNrQaijE3gXDj0OOq/AoJ9RMAOUi5wzLoeNJ+GIW\\nFF0BT6vCtWtwJDvMfAGKFINUTeD6dmjYDBb+DYsjuw8PQqZU8MlwWFAYLmyCqWthxXPQsybMaAby\\nQ+meUGIE/HwSfikJZYtDyQewNwPcTgUZ/oMBzaF8Xhj+M9x5F2q8Bx1KwYS7cO5DotOXiWrC7jWQ\\noiHMmwIb4kK6uFD0a/j3NGxcBCX3w6SfYd8n8Mu/0OoAtL4My1dD3eFQ8x4suAVZ5kOCzNDuPP7P\\ntW+lX4O/V0PDazCzKdHflDR54UJBSN8YPlkB3VLBsecgzj6oXwUmTIdZ+SH7r9BmGuQrDA1Xw+p5\\n0KgabN4H2TvA3z/D+cv/+8lsMBamZYb3f4cqsaDWn7C8ARxMCu8cgZYJoN67cH8a3B1AdOBmQOTg\\n+xEU7QFTz8PZHyF1LKjeDwZEtjx+AwmPw+b88N1gOP0HDCsJFZpBl6Fw8DSs7gkNukDxkUTrjhWb\\nwbIXYcZL8PE8olsh1xSAxT/DlhUwrBL8nhEKz4e/ykHzgcThv/VQogVUTgc7s8HG21C7B0wuCFW+\\ng/r1Yd5ZqPUAvt4GOSJ7XJJC9gWQIDIE24jovT/tjsP6vtB/LSxOApV/hQSXofk5SPgxpOoLzdfB\\ntSnwWUvoEw9y7YV778LlVyD9IfjpX6I3kWWbCr+9AU+KEZ2dqXQPdsyCfPEhTjVo/A/8Uh7mvAGJ\\nP4HYQ6FGR1j7A5z8Eja8ChNzw+DXYcBTqLEZmh8n2sRdoDDkPQxr28OfReB6pIH3HKy+SXSP1wvr\\nYMUtWDwGxrWADrGJlih3xYdeReCLo/BWZN6tF9R7jejX9sRJRFP84A+hW3EYHakSnYPOtYhubP/g\\nRZg6EfJOgOd/IXrNSPWa8FIfuLQSkn0MbbtArb5wOC50ygnfrCDabVZ6BBRcCtcaQ7fScOY+/PcC\\n/LwNdoOzu+Dml1BrLjzbFd44Bp8+gEaRV0hF+Kwc7HgHTkfWMbwPxVPD/Mhh6HXYtwViJ4Y5wyBl\\nAbg/C+puIxqnDkW2u6WDLCeI7jR6fTtkqwOdpkPvvJD7AdF1hSXuQp/Io6EC3PoILn4G3oAv1sDb\\njyBfZIauDkz6ET7aBCWLE324LFgM576ADVmgXRy4/yzEOUR0H0+mVdD8BLz4BGLHhtg/wDddYPUp\\noveKZo1L9G6AnN3gaSyiXU1nMkG5uPDJUJh2BbZ2hANJIH5GeLYiFOgOFZJC3lFwNx/8noFoLerj\\nSKdILeg7DuLVgPi9YFELGDUVqtSC2b/BJwkgUwHYlodod0jJ1+Dt0dC9M9Fv35UDib7C+yyE/reh\\na3u4kAtKfwXdy8GFmjArCzzaD3OOw7S+cCYy9XYHqveFfyLLJH+CcbUgfwbYOB0OrIVMxWBiFaLr\\nbOrMhno/wOZ2RC+BydGN6Eb4Pf3g8lJIkBgqloK7kfWtM+DpCbiRClodg6+HQLE0cGAMXKwGn3aC\\njp0g9Xmo0w06F4HhVeDHL+D1N6B6Y5j2ClTaDGkie5UyQ4obMDc1DMsJB4dDzshAfiui14jt6QAL\\nekKLVPDzy1AnN3QtDLPuwDePIGEd+G09TFxJ9E6Lq9dgV3eo0geWHoNyDeGvITCqPGxsR7QqVvwY\\n0bj2XDnYvRIeb4eHt2FfLHhaH7J/BksaQOLX4LO0kGokDM4Dne7BnImwdg/RbrkdkZm44fBJPUja\\nHZbmJTry8vz7UGIz/PkZvFAESvwLJRdB98gpR2mi9+slKwRJPoLPKkONfrDiDaJrkNflhpxzYc8b\\n//tnl6ewtg3UfRNOboaijaDndMiYEzqugI8Gw3vJ4KWnRO/jqx0fmm+E1TNg+l/wwU142BZeGUZ0\\nV+WcPnDjOgxPCi9PhttHid6O8MNxiBwntEhOdGlqpdRQvDFMWQgd4sOpyBhKFqI3ThaYDK3+hBv/\\nwfszocdhmBoZaMgPScpAl0FEVzRX6UC0GDGpF2SLvMtmQd/Iycw+iF8abtUgelfKwWxwaxmMiCxZ\\njVRPJ8G00iBLWfg90s4ZC7o0hTfXw57DcOkjeL0cnPsSftsNfx6Atj/AH8lg9B3I2x1m/A2/34fn\\nN0Kct+HNprClM8ybBvvfgsQ7IdkKohubWiyEfxNArk6wLLLsIDICnRku1YMKKSFdQTj2ECrvh1X7\\n4O2b0KsjxB5MdA/7oN1E92V/XxeSb4RYx6D5SCg8CXKvgdZloH+kcfILohcp9GwLZy5A/epQqA/8\\n+jsUWwnZQOe6kPs01NpI9LGb6yDM+hTSDMP/qScdKQG5s8MrZ6DvUvghMjv2I9FdLy+kgpdKwP2M\\n0K8dVPsWvn4HTsyH0u9B/gTwzgy40xRufgfLI2OukYtZ2sGH1+Cv+rD8MmyK7PjeAruGQ4JjMP88\\nZLgHSdZCkqdET74LjwTLIHY6oq2jNU5DvITQuSdkXAPDE8KbA2BAcTiQAOa8TnSXSelckGo+5CwC\\nHz+ADR2g2ufwY3PY8DP8sxCSPYJq92HJCOgS+TzoDeX3wIU90P1vSD8M0k6FXhmh1h5YdI7o1UwJ\\n6kDbybDxLLw1HNIPhjK14dUOsOR5WP0XLIrMuq6DSfXhh6rw1noomwFenQkpmsOAIUTHwrtVg8eR\\nObtxsPwA/JgLavSF95pD/5QwoTL0WA09NsKT6/BoNKToAjn6wbcvwaf34darRHfwRFrpt+2EZyJb\\nlf+EC8NgSw4oUp5ojefbb2H9BZj/OjRZCrl/h2dGQ7ZniR5z1HkKOy/Cr0dh+28wICXsGAttIn1L\\nC6FVZejwEjR+AJMKQC1wtRfcmg9z08E3z8EzSeCVJnAhPbRMC5nzw+GV0DYyEDMXWl+FFBnhpcKw\\noQzkmgtrKsI/22DaWfhjIHQaDYdfgfUNYNe3cG0TrFoPZ3+Fvf/AN8OJLjcZ8A+kSQODlkOKBlDr\\nIIxLC+c+hgq/wocFYVhriFOG6M0EG3+D0q1gzTPQ4jx0fBn234QpO2DKdNjzDswaQ/TqknjD4aPI\\n6pY08NotqNgCMueCP0vBi1mh8JtQtBpcWAtxFsO0H2DPRPi1DTTODf9ERqA+JRp0Xl0CxV+GY2uh\\ncRcY/h8sOQrTIktMZkDrItA6NtGW+Z+PweKVUDKyFvIALK8NJwrB1ZNEX4HD3obdn8LiSLflPDjX\\nESpmhf11IdNSOJEXMi+Axangz7uQJB7sbgaZr8G2RdDzOPyeDb6eDn3WQvJhRI/az9yCU1ehdB2i\\n+/rrPoLaVaBAdni3HUwvCIWvw5D60CMeFCwFP92Gnq/DtRowswNUmUV0Ee6RJzDxJNE6zc4ekK4d\\nxHkZWr0ETZoQXZoauS7syDeQoQwUWAGxI6dYQyBRdaIrqff/BJ88gNPxYUCkgWcSXPwQ4s2Hiveg\\n6B14/QL81Bly3IRRfWH9Alj6HNFJ5HytIXcl6LAU9qSEkzXh8hiiS38Gfwu7TsOFm9A2slb3R1ib\\nDOK/BZ/lgx2ZoOsuWPUMNHsJUsSGX6fD6Ubw+rfQaQLkXw77XoO35hKLB43h6QIonR6+Twl7csL5\\nilA7clz4GPJkIbp5dtV5OBfpfIo8Dj6HOJtgRn3I9iksiguHrkC6PJBhM/RsBh3HwuXTcOA8bNxG\\n9FWx9V34KxH0rQrlIwc33eF2ZqJTh5E9Ve+ehKkdYGw+GLUAFhSF/POgag2Y+jFMHw2F78AvkYbu\\npHC1FLzzJtHrVxvfJXrRzcS5UHQb9PscNk+B5Gvh52kweheUXgNxLsPGHnDyPjxaQvQS2V774Pdk\\nkPYD+OpFiHUJZuWAbeOhaFLI/DXk3ArlG8L8JdCkHCw9A7/uJNpaOHIyTBwEG7PBs2OgxNcQ6zDE\\njQt/ZoTWJ6FTA/g8M1xtCBsjZ9VvwpRmcOYk0bvYuq+EZ9+B7jfhxD2YuRXe+QvmXoIVNeBmNkhS\\nB76vDIcbw/ltsG4zZDkHjTfA0uWQdyPRb+gCceHwc/B2SbhYGHY/A/3bwsqFsOMPWPYCTF8FtV+D\\nKx/C0PFED0yHvgcPl8GRUbBtPWyMLCdsAnMPQ++4EOcDGPUuDPsOarSCVqkgaVv4YS20jGznig+j\\n4kC1GtDzMew5B/8PU3cVtlXZtm17RbobREBCGlSku7u7kQ5pBaSlVFRKupRO6QbpFJCQbunukoZ/\\nYrzje/5ZJljguq97jPM8jn3ftm9eE6aIDlWC/87Cmx8hUQfoth3iH4R5vaDwRJhXB/74BmZuJ7yW\\nRH0PXwVrqXcQIzmsXwcvzsPFLVCzANR5AHO3ENoJgz7j4ltQqSU0iQnxA6zGXmi9FKp+AunbQ5yZ\\n8KQ3tDwEZevBwt+h722oH8S9o0GjJzC6AeTpCSPvwOHMcLI9vD8Fv7WDyInh6DbI+wrixYP5P0Dh\\noMv2C7z/BAZGJgSmJDkEeUrDJ3/DicSwIYAHPoIvDkPrYCY0G35bACdrwtUyUH40LN8IydvA1vnQ\\nKBHcfQu9t0HHhDC9DrTfALPPw5qOkG0RnM8DXbrAD8cgTzpIewPG3IC9kaFHDejSHzZ8BntiwdzF\\n0OwGvNkAx27CzqRQpSfEOwjTjkCRyTB9HOSpDB9lgi+awra6cC9YEn0OuQfCrBPw9BocLQxTm8Cd\\nzHAoNhzcBQXbQuOFsPoVlJkKMT6GMQuhUhXImQxG3YIY+2FNT7iyFL5qB/GCUsJmWL8I/rgE+24R\\nXu2mx4aJlaBQJbi0Eno+gJvHodJIwuX7mPTwPBbkKQZvlkLSlvBqEjzuDpeCpNQtaJgKdjSF1O0h\\nUhf4rjYhVnTUUNg2nfDdET0u3DkGT1PBptowfgjkSwXHDkDMhTDoLiROBDfvQeO38OkAGBGkmRPD\\n7lfQNDWMOE+4XryxHcasgEtroWZx+CNY01eBf4NDzMdw5zg0mQGFZ8GOOzBpOdT6AjrkhQyfwo8f\\nQJVi0L4nrP4Oau6BdLnhVDqIcQdiHoJ6u+F+Gsh6DaYGA5Hs0GsOPJ8KqfLDZ/MJJVdtikHf6XAi\\nHlRrCo1bQ8z28OVsuDEU+g+GbZuh32OY8iuM/g9+PARpGkPuVIRWht+Hwepu8OdkeLAeVmeD6tPg\\n0laIuxFazoPD1eDX+DCrBBF49QLi5obykwhhAUG9P1gfFEoGvbfCB4/gg8/h4WnIewCOFoerP0D+\\nqTD4BVT5Hqrlg9iLoXxe+HUHdB0C087D0h0wtis07ERYj7+1G2Lch69jQMFMMORTGFYIWvwNvxWG\\ny5HgzQookAeODiPc0E+6CyV/hDevoWJyiHwCag+CmW8hXUrYMxmmDILhveFOWzgbBboXg9LPIGdH\\nQqrQF7lgwhp4EtwDDhE2oYJW14Hv4fIbwmJ//gbQ+gGIAG/zw6bx0O4NNE4GU+/C4vswfjaU2QS1\\nt0PZavCgL6w/C0s/ghtBjbkplC8LT+/C+P8gdxLInRym1YKBtyDvXegchVCTWfsQXOwNs/+GWacg\\ndnn4riJkvgY37sK9xdCiN0z+BxYFmY86sHAMxNkKU8ZBwexQfSc0WAuLvoAZC2HKxxBhASE+tNgH\\ncOsRtNwMmXtB7iJwICPEiQ19+xJOQa52h+aVIEpZmDQW6l6C2UcJD/0JD8HSejC4JZycDJ8Uhbnd\\noVIfSPAOWtyDUcERpxZs/gYmdoMEy6BiAOD9ABqXgXPdYEhHuPoO1t2Cq28I8Y+fboCdeWBZNuhd\\n+H/f5zMBXHQSfHoCPq8Gt6YTzmMOnCeEIs6eBo3/IXzx9GhE2K+83wCWFoOOa2HGCeh+CDIehIQZ\\nYHdAscoBV4dD5rOQtQZszQ8Zv4OGteHMLzBpPcRaDckmwcu5MKcOIaGncFJ4HgW2ZId4l+C7wlCx\\nJXw0AFr8CycXQJfksHcklHsIN3vC9ueQZxXcfwTjV8CIMlC2JOSrAG+7w/JS8K4P/LQZcv4AjbtB\\n7ZiwowXsugKH30Hn2fDiW5gQ5IGS/u/Pg0bwxV9hz5/wbgBUig55B/3vzy+PgxePoVFwlLwOO2ZA\\njEZwbSgUTwEf/wLjU8LPFSFaMfgqJTyYAy/7wPjuEH8h9NlHeMDqEYUQ4vpZfRj3DN4khsbz4fhk\\nqLUKNgWzscZQ+xu4Gzzhy0KnZRD5KJyaCP/Nh1hHoVxW6LoYigc0/1HwdxT4vgccWAYp28PZLvBF\\nARgWAa7mgA+2QPIlUPoHuFkCZu6G8+MJG+v12kOZNDCyFywrC2XiwLb9cH4WoXPw+9SEIrXnf8C9\\nTdA0G6zoC8kqwoHpMCc2rKkOF8vA6KzQrST8mxl6r4QP9sPYAO2RA9YnhB4pIXk5QndkzelwLDXM\\nqAhFyxJuKlo8gBkzoEdd+K0jIZY2VZAwngAL40DUAAwUHTLGhOy/w4lkcOdrqFQCIseD7QGw91fo\\n0ADm/Qv1RhLS2GcHTed/oehjGFcU6gbQzg/gcS3IkAc2PoJZFWBhBBiSBK5nhedDIWYAVp0Fv96E\\nDHNhU2Jo/x6aPYJ0QWBgPXQZBhkawpED0LoZ7HgLEwoRrgK3D4I83WBZOTjQgzD59yZAqSeEE68h\\nR3DdXQV9o8H+jnDnGqF9oW9OKFcQ4pSD6g/5gK5x4ZMYhKqcqtPgg/5wJyt8PgguNoe8wcMoJUSu\\nDadHERJHogQIr6SEULJWKwgD3ZcjQP83hIrNDZ9A7f2QpyZ0Kwzj/oAYBwk7XJuGEyIQE8aCxGkg\\nznWoUh0+CzjFP0DWbTC8CUR5QRik/SUh9K8NGZtCwYYQfS28fgft+hI2pNKPAXXgSH9YfR8qxYZB\\ncWB7QKT9GOJMhMSbYNM8KPgW1tWDmbMJSRtvksGQ7rD+JowqB6dbw9XgsbUBCiSGfl/Dq2Uwox2k\\nSQ4jpkPKmTA2DRSLCFdjw7fBjOQwxLwEo/fDmOAhWxkm7oJSeQnjhFODAvAW+Gw8LOgKkV4RPlam\\nfA+1csCx8pDlR8hzkzAN0KUNlIgG04JfxZgw4yK0fgnHzkDcXVC/EfQoDesOwIm6hACO7xNAjeuE\\nd+vOb+DUNBi1+H+f+Z9toGgHQvrz+GC//gwiT4RJq6BTH1g5lLD0m2MSnM0C20pA3FhwYDA8rg+J\\nK8K5VzDwW4iWEbaPJTQDFkwLVTNCxliQdg381xy+SAD/XocSSeF4Dlj3AZz5CQ4/hGH3odEQqJQY\\n7mSAOBeg3WaItg7++RRifARpasLZfDA/uJ+BvsGyuD/8OxLe7odBKyDKJTjxN2SaA+Paw0/Bd6AW\\nnIlLeHHqGgu+GwA1RsOo3vDbG5h7BvLGhzRRoMHvkCLIri2AUa9gya8wYSMYTgjsmHweSoyH0XWg\\n2j34uQu8CKbvJ2HARUg2HoYuIWzPPT4J0/NCpWSw9xeo+BHEjw+H/oPXG2F0Qlj3CaGvs/VOaLEJ\\nvq0I5TvC62mQvAcoDiVvwbP50Oo8ZIkG+2ZB0c/g+5aQ8T4U/xHedoQ6rWD2MRiyCn6dD10PQIIM\\nUOopjPwNYneC4j0IwQp9rsDGjPAwETSLCr+PgAqvYPpq+DHopQYYl1ywJT78ehmW14Ep/8DKezCz\\nEDzsDlEzwM/n4Ou8kCYrYbO4UQaY0BHGFoQkwwm7onOrQvLh0KoTIcy5ZlQoWQAil4aCv8OVcXBo\\nLzxuBsmTQuuccDpoRp+CtBlgeHLoF3x7X0KRgJQ2BSI2grGtYG8VuNQH0syGK/0g8d8Q80fo8Smh\\nWL33l4TB8zi5Yess2NYQZr6ADAsgxX+QcQ40+AOm1IZoNWD2T5BnETT4Bmbch6iDIOUISP8tJF0L\\nR+LAwe+gTTpIt5vQgvpld+jaBS6uhs9mwop6cGM0IcTkWQ3Y0QYqxYW/ukO1N9B5C7x6TRggiRID\\n2h6GJqlh7Dk4vQD+GQ35ukDBvlC6DjTODgcbQssohFroVOuh4BVI8gXU7AgLt8O2I/BJAli9DFo/\\ngw9Hwo238Ot2mL8V+h+Bl0Ph46uwajnkGAHn3kPjgtDvEDytArkHQLF78G1U2FMOSgd1pcmQcCHE\\nrAgXx0Pn+3A4OazOB7njwoVgFPUhrMkMUb+D1gMg9Xz46QkR+K8r9C0JH/4BVZ9DkQ2w+yZ02Q09\\nkkLd4Kx3F/7JBrlGwsDeMC8KzD0KfafAnzehShaIOxSibIbd4yDRP1C5OzR5C1VWQ8UgNVWBsCje\\n7ClMDx7ue6HfTmi6EwZvJeT6rKkNrTvC5mdQeDIUOQhpO0ONVBDzCxg1E2JUha8TQ6/KsLQZFMgN\\nXQvCb+0JScEBSqDtCMjaHFLth0fNYV2wUpkDTzvDR2/ho4yQJ+DYpoSI3aBvDLjeFMo9gBSpoepe\\nKNgfRn4MA+7DnwmhbUoovAc2tIQ3ceFhOYiWGTZegNF/wqGUkGE+5FlNyE8/dxe6xIDY6eDdp5Ci\\nI6x5BhnWw/2X0K8s5PkUoqaGtt1hdCbYshYqzCNs2ZxKAasbwcTfoO0CmDMSWn8GzSNA/YxwPjMs\\nzA1F0xCyoYPFR96B8NFnsHEVVP4OmieDErXgWXcYfBP++hDu/AXd+8O1uHC6IKEC9nI9+Al8fAtq\\nHoHdEaDBOUhfBwYlhpb7IH8hONUDXn4O+d5CtC6EMtoci6HxVcizFypHhzZdIP1CWFML6l2Ec0Gs\\ntRdUiABZY0OZjoRTmba/wd9/QZQEELMA3FsGmeLC0ydwMwlUzkkYUK0+B/ruhQ61YH012LsL9owj\\n7CTuqQPlR8CWWBDvNCz+GRr0hLHzYH0NQgp/4GtL9RoaV4Lv70GSIOmVBfqugYm34PhM+DgaHJ8N\\nZYdBgSswfxm0SwnjF0HrQhBtFPQdCRe7w8Xr8LI2bCoMCz6Fk9fh98aERYH7e6FKKkhYFXJ1hVp1\\nIc0KiPAJNIwK3Q9Coaswvjoc6AzJW0HGvVCvKFyOAZH2wpXUkKk8YRLr7xHw9Ubo9i8hymFqFUhT\\nGNIvgve74OYh2NIDqg6Fn1PD+aeQbz8MjgBd6kHlbyDtVrhzH9IMgFXtoUAs2HIXImWFa5Xh8kQo\\nPQrGboMPe8E/wWcYE/5bAKdfwonhsPkm3BwISevBh8Uh3QSI3RNmvIRcMQjTvT/lgzyL4dPZcH42\\ndDoMfxeB7lVhcRDq2AsJ/oBNp6BXTuh/HwyCYsdgShsoW58QDNH3EOHBunpjiH4KoseD+mXg+Lcw\\n7zDc2wNHl0KUg9B/HxTdAJMngKUwvT/EfAERn8OHpWDPRULG0tdBF28UXDgCJ+fD/s4Q6TK0GAt7\\nIsPVlbA1NzzfD/uyQfMx8Oo53P8LxhaC3zPBznOEx6NAydzvKSHSVmlYfBMu74RSEWHzE0KgSas7\\nsG8SpBsEXUvD+/WQMj6Mawn/RoTozeCv0/BuAixqDAkfweQ08PdGWLwFru6FD/+E/pVgaW6IOxje\\nBNyplHAoGgx5D4uuQcQekDQW3BgHnQ5Aiprw4RZ4UBvaJ4Qyv0GGMRD7ELT4CDIEIJUWsLMGrLkB\\nCVbDwVlQuQss+xX6p4RzeaDYbHhcGuJUhGe9oHUBOLkPDhyDt4fg0gs49IQg/x2BLPkhUlB+Lg2F\\nSsJ3kQnzTwmmE9aYA8pwlB/gbGqI8SkkiAIjN8GpenCqAXxZCeKMhKEBk/cFYUQ60WjoNgde/ARD\\nu8OLalCgLJS8DzU7wdBfoPwRGHMGav8EuTvBphQwuStEuEnYZbhQDVZegc8jQc0t8P0K6FMJKiSD\\n6Asg5VdQPDl8Mxd2LoOEdSFuBsg1FLa2hQaZYWtJSJmZUMgweQo8rwi3+xKWS+e+gQOdYGB2+H08\\nlLgDTzPB4r7QJTocu0Bo7Y66EdrvgZt74cgL2PkM+o+HDu0gbhzY0BUSdoa/psGAt/BvDRgyDAan\\ngGXpIX1LQiXwgVQwKfiFmQ0x20LJx7BlA3SJDfPuE7ZsziSFaX/AoiRw9zl8VgxuXYIBDwklIb/9\\nBRmnQY6rUG47RFoMx5PB0cfQ+WeI9QPUiwU978HzytD2OaGA6OuMcG4K4Yv25wNwpCkMTwnLXxN2\\nOccHj7+9MOobKJwYVteGkbtgbjyoEwTSN8K1SVD5FdS6TChW6pwNEtchXG8Fn+rBPJDuDRSaBz8f\\ngeI/wKKE0GsQ3MoD7bvDunNQsBREXkLoky/ynHDFsCuIBqeAt22h4kgotgOS5IOITwkTRbmjwrwj\\nECcRlBgFB15BsTbQZA28XAdbA9JYcnicFr6ZCE3Hwsbn0KsPRDgFtQtDiQXwZRko2R96tIehT+FI\\nNYh5Aiqlh69awf4SkCpABNeB/wrD6geQpQqsKwd1PyNc6q14SLjKqTwLzheHXfsh8it4PYDQprqp\\nOuRMB4+CZdwf8KQ6vDsMxUfBhHswYhxMewqrD8CTV/CoAXSYAvsGQOsrEPE+VP4R7haFtIehVTx4\\nsBFaxIBOqwlnVI/LQYupUPwrSJ4Bfo0NnX6Fd2XglzwQdy/ULwTxL8AHr+G7x9D1Bbx9C2N7Qp1q\\nkLsqtPsa6myAOdfgVGW48CUcjgMnW8Oj+IQrvwFZof0YuL8NaiWDNwEu8imUGA4Jb0K53bCsJWxP\\nRjgRuXIERv4MM4JDTDNoHgVqpobDQUmlKdTbCq3/gCwVYWYQhb4Lo4tBl38IieG7bkHSvBBtFuxJ\\nBK2GQaMdhOr3VGDCYhiVDb69AJf+gyQIBTgZcsOPdyDuVfhkKsybAQna8n+nGtd+gY3BeGIsdKgJ\\nB+5AwjNwfRdcWwAbd0DM5XBoNvxVC1bmhggLIXpfaNMMcrSCjw7DlxFgfpDAKw6R50O2jVChG7zO\\nTrgyzh0c4i9Dn9FwYz7UXgijSsHzn2BCTvh5HLz9Hf76nBCvmqIapBsDk4rAn88gSLiMzQbzEsGE\\n53C2IBSsDGWHwr7pkOMvqBkPJt8C76D0bfj5d7j/A1z6ES7PhygFoVg/iPMJbPoFBiSHdmNgXECI\\nmQZT0sH5izBtGNwfARXfwImmcPY72DYBVuYn5H2Ouw7vo8PBo/DhTIj6D+wM/i/ZoWB+mPEBlI8O\\nVq6FPm+h3A3odxnqXoHsy+B2cjg1kLC+eHc3bC4H4+/Abz1g9VqokxhmZoHH62B0Kfi9IbQJSuzp\\nYMpQOBw0lSJDjQJwIcBRXoDKhaDzahg/D5Ikgc/bQ5f5sPIHGPEahg6HcgHfaxYMPgn9voX1qwnJ\\nHD8fh6g/QLvDkK0eLN0KnYvD6fHQNweUGg5r48HslLDpFZwfB398CwMnwLIRUOUqdH8E98vD490w\\nZA58NxgStIfao2D9HuhVCr6MAiX3wOvEkPcWRNlD2MiYdh9+awn5AyLtVnizGCKWhKpF4bunECsG\\nLPkLcnwGMTLChk/hTENCLW5AqG86HXavhhoBRXcCzLoCq+7AyJSQLA6cmQi3CsIXJ6FDbtg8CYa1\\nh1Y5YfpJOLkdhgcjVpDoP9h/H6oF1OY7cCIbLD8AyRLAu6iwNyc8WAblf4JBQ+BWBrhcExIchzTD\\noVhCyFwA7seGY0GjsDy02QCLNsP9TvBZd3hzGQqvgkYxoco62HQMNgfploUwMjPkLAilssOi0nDs\\nC/ioE1wZBacvweDPYWLQLvwPxt4jxH9syQ1bhsKa5fBhQWgXlCF2w/cjIce/0K8JtI4Lw76ClA9h\\n8iu4kZCw4Tjyb/h+Koy6DdcPwOZhUOQM7F8LX12CZ+Xgrwxw9w48OwDtgxzeU7h9kJCRHdy2W4Nx\\n4GVpWB4NLnUhdF/2/wmiPiYsLtxPCsvA0rwwYTm8PQPdjxPyoFNVhfVBQHsVbCsCb1vBggdQ7gTE\\nrwtNTsCKo3DkF9hfC4q9gRorYeMxaDGZ8P7dKQHU+QmaBU3SjHDiAXzRDi5Eg3vZ4a8kEPcb2NMY\\nDn8NlePAlWqwpxF8mg12j4aNu6HyadgYH1bGhtSRYWd3KN+BcEF5ZTgMOwibL0LTunDxAVQIWO1r\\n4LflhKqZi9UJRbaDGsH0wDFwESLXgKbBM6EnJD8Bu7bBuy9hZsCIWg5HD8PzkvC4FMwpCZHPQvaF\\nsDV4nSeAqHNgXhtYdRf2jYP8xSHRJJj8CM6egNOZ4GwLWBoUfSpD4ReElMTPIsDLlNB2LWHmsncP\\n+LgarL4BZRpAk+GwKy0MOUWo656XD3q1gARDYFcD2BSwrKrDxzOhyVBIdwIWlIY0+SB60BPsD9Fi\\nwr7bhH23/wuZrIcH4yHST1B9DyErq3fwYh4MwbY8+zbo1QiWr4bEy+HRUKjTH/4MuHExYXNRmJkG\\nCp+FfAchQiFItRvetIB0s2B6D1jSGOLMgWIz4L/4kCgr1E4EjfvAxsJQYTKMLARtRsKc2jB/J3xe\\nDg6dht7g9BEoUAe29IbTr6H+AZi0Bl7Pg9WHYNEB+GgqdOgOd5vDkLEwYyw8iQmrK0K6slD1M+gW\\nUAMPwvZskHUqHLkA5dfCqNGwrQ2sGUeIa46aBEZehLt/w8lhUPIgrJgEq0pAnwlQbj18vA5SfQUv\\no0GThDA1MR+wIyacPQ+Jg13vDFgzHc62hgaX4eeAJ9uScGcc9WtYdQ+y/EVoX4/RDn7LAMN2QJ9o\\nkL08LLgP06PA8T5w+iE8eQkZ2kGDaLAnN9z+D4odh0PLoPI76LUGUqaBgUfgxBoYWxGiriKUazYP\\nsAUL4H1ArS0PubNAjd8gUzb4IYgNboefi8DnQbTzGlQ5A01awabOkC8txGxEqMoOuCDfFiCU85y/\\nC2/Pwh7QoSEMOkAYKH44FhKsgdyJ4UwQem0MLS5Cz+BweRC6TQcBlPI9xGsNv26D2rugbDcYnwAe\\nb4C69aDpODgVQPnKQOE/4ME+SLYUrgaD0OlwPjHc7Qyfl4WyWaBiMC9ZCmUWEo6LI0SB28eg1BzY\\ntRba7oJPH0LbGvA4HtwrA09XwciANJYIkryGRI1g9UjYlRRGZoNeQSS2NbRvDkVvwy/9oOYwmBgH\\n6uSD91Hhr9ewPRWhXjcQaLReCXP6Q95u8NkgyJGU8HCwKRW0OQkvTsPpzIShy2XDCLVCVQNiWS6I\\ncRFKJ4DEfQll2z9uhkPXoUMBeBpAU+9D42nQ/RhE+g92FyFUdweV/rht4U49mJyDUOu0KC3sWwzT\\n5kHKyLBlImHXKSgHHK8EK/+CHyLBhgUw4QnU/gpOv4cI96HvAyhzFjLehYkT4dJ6aB8PBoyEmE8J\\nQRiBBufvnfDhYygaFS4HXd3glbYJ6l0lXApULQUlGkKsoTBtD8TPAi1yQozz8E0HSD8NdgX1+Dcw\\n4RjsuQXdgoD/frj9EF5lh0jD4PwWaB8TVpaAg09g5DvoMQRGx4f+k6FrDpi5BJ4OhO2R4ZP7MHs8\\nxDlL2Ewcnw+mHYfMJeF4ELfPDJO+hzOtIeV8qJwUPvgKck+EooVh520onBya/gF1BsOMTIRh89i3\\n4FYuWDAMohWBq0+h+j0o9S1cD56iw6BjNTh2Dd7lh0cNochiQgRli3rwdAfkbQpTqkODipBnE3R6\\nC8/ywqOyEHEYxDoG1YvBqJ/hZTKYcAKeXYKm30LEdhDr0//9DWnbw61DUOAetM8F/YcSVqBel4EJ\\naeFhPvh5DvzbCGaVh+SRoMMWaNkCCpUixCBPfgHfr4cXiWDrMTgyAu7Fg3ffQqUTkGgQxE8Nr3+B\\nptsh1lvI1gx6d4eUK6DWRzDyKuTuDI07wMST0BPkXwnd88BvZWD4GVgdFZpdgGwNoN5DGNObcOoZ\\nrGtffADdP4K9DeB4CuiZFiJPha+yword8OwPSH4Tll6Ccb9BtvTwNjNcC97dGaDwELi3Cko8gHQz\\nodq/sGk77OkCzafBoJGE7/FaE+FKSbi2BOJ2gilnCBXyZfJAyqSw9Tn0/Q/WtoAJv8LNtFAtiDGc\\nhVtj4e4pGHYMJk2AOqWh6TbI0gUe34f4FaDbZ5CoCozKDqWaQLRWcC0RvBkFiQpChkJwqQ0knA3f\\nZYJereBtEkgwFMYE255ZYEnA1ZgADzPB71ngagQ4Owi+nApJ40O6NTA9PzSqQCj7rHofWm+AxJ/D\\n1KRQKAdkHwFtW0DC85DnW1jbEH6pAaVGwZDjEO0eROwIPyyCX+fB7E8g3mWIWRfeTYX6D6FXTEh/\\nDz4eDGMuwrDNhOroYBETiIfrtYHzO2DQBNh9EYYfg+xvoPxO2JUcLq8mLBjXnQ4rckPL/jA9J8wP\\nGC3L4eec0OIviJwIau6FgXXhxS44MBYanYCHTyDpZWi5HhLehd6P4WkQpu4Ma9/B8PqwOtj75oKT\\nk6DRGkjRGhJthUgvCXNFs4ZA7DHQfxjhI/LqE5iRCMYPgi1V4L/1kGIl9LgGDYNM3mj4Yx9MbkOo\\nR+i1GUb0g5M9IcFEyDacMHo/byKkGA4dG8LAD+DuRji2DWJfg6qDYEYy+LsP4f1g7ofwwWoYDRb/\\nTWgPLLEdOnclbKMMSA+TfodSWyFeFEhwnXAWuDqo4reBus0gQVaY+C+hc21wYkiSCzbNhdPlIeNw\\nOHwQTucghIbMKQ79nxPSVj6tD/2WQdWuhBi9AELbeAJkfQWLcsOrnPDRQFgTDVKfg/8qQczGhOKm\\n2KWhT37ItxKS34bPX0KdepClETyKBY+qwL7P4MZiiJwKxuQj1Af9eAN6NoXSAT2rLWx5CGvvQOQe\\nELMCYUu3d3z46yRUjAyDD8O6CITLpprVocAjiPQDJOxIGIuu8AOcWQ2b50G/3nA8H3ScAAMywPFW\\ncDfoteWBeL2hexuomBf29oTi/8DIdpC3FLz8BdZMhEpFoFAe+L4UjHsMBQ7A8JuwPDXULw/rPodV\\nn0HEtfDPJYieEbbdhTT34Xw8OJ4WosyDFRngSX9IdA4KV4MT0eH8BkJH3u9boclCaBNEy4NDZCoY\\n2AO+XAw7DkHWT+DMQ7g/CtamgWan4fFeiPs7rA9SSmUgck1Y8R1ETQ/9o8Hm9rD5GlSfB1mnQDow\\nZjREOQQPq8DYwXByGXzYgfD6VCVYle6CiTGgWhFY+gZ2ZIRWwWfVGC5Gg12z4MsHsOkWbJ4CHW5B\\n3TmwuASsKgidm0G6yTA7NRSsBffLwdjn0LAmdGgGSbrD2uDQ1gceRoDumQmXsOUGwK0W8HFXKPQe\\n4jQnxMd03AAbysPh2ND6CNTKAKviwP5FcLgmfBsUtgrD1XkwNSb0DBbonSHJC5gdDZKVgW5X4Yde\\nkHEp4YL7bCW4Fx/WlYC6V6FhBELuY+nl8Pcu+HYRIbb3QoDq/RO6F4GdcwitiDWfQanEsGALXE8M\\niw7B7p+h7WSItwI6FIeudQmfA4Nuw9/1oVgt+DMvnNsMjb6E80/gqydQ42foNQJyPYbDmeBBeXh0\\nCuodg5MB2y8/jMwJg9JD25GwKil8nBl6fgtHbsLDx7D4N1gzDeKVgCzxYP4NGDQf3mSCSeXhRSmY\\n1h3yRYDv+8GdidDtFexYBAM7wMWAp1WQiLz8CKLlhhJDIeF2eFwMWtSCp8ng45XQuSjUrA0FgrTE\\nCUjZFDKUh53T4FR+WNQaMp2Gt4kg+V7omw6ilyeMpI2bAH9sgIKxocnvcG8llPkZjt+BGPVhbxkY\\neBpqtYYdp6BSNogXANDSQ/LDkOMxPDgCu15BwneEI+tPA8TlLSj5KeENL5grbIoPN1vDgeRQOB3E\\njgz/3CLsR6T4BfSA7f2hcTTIHyQMlsLy4fBnHsibBn5KD4dyQNGTEGsjZPgH+j+E7IlhyAxoeR4+\\nuQUrlsDPnWHNFSj6H4xID5XWQInK8DYB1F8L81rClj9h+JcweQO8/RAyHoCvb8CDTtDlABzrCWMS\\nw5cBaKAHvO4HlyfDuM+haHn44jMYWhTKBGvQyNB+E1Q9RAiqDZxZ0ccQ5oEO9ofsaSHnSUj1H/T+\\nDP6LDQ8bQszdsP0HSHIYjveGTNlh3VpIlQSeloF1RWFdHFg6A+LOhIjT4e8B0OpvwrpDohbweBGM\\nKUw4KWweBDAnwvBz8FlSKPAhTPoX3vSFzr3hcDN4PRqS/Q2t9hEu2bumgzudoHdW6HkW5uyCX4KM\\nzmO4nBS2j4bFYyDxDkJsYIOvoNgTKDMdqlaHQgXhWTr48mfYHwlyv4cHiyHpcphbCUb9CrXLw961\\nMD4ynN4KuW7CkMqwIyI0SAxR/4WPp8H8+5ByB6RLDROHQY8DhHWQ/RmhXga4UA4ixYFp0+HTzLA2\\nwJrEgvdHIOdxeDYaRheBDD8RziCnxYMlJ6FyFXj6AjrHhKoVCH2IbUdB4sNwFUzMBD82gTMZ4Nkp\\nKFsEasyD7kVh/22o/DFEHQGtg9pKE+g0EWK9hjzxCOEs5+tCvOGQ9wFcGgwTe8PWX6DyQ2hVHCo8\\ngz6JYMpC+D013PubcDXcLi28+gRWzITUS+CrX6DuMFj5AgYERY3mMDTI4XWArDOh1hrYnxkOp4N9\\nySBlK3iYBvIWgW8ewfUZ0OUZfHodpq+Bm68h7iDY+wR+OwerO0Ky15A6EUR5BI8WQKEgX1if8FlU\\n+Av45y3krwlVLkOvy1Dzd7j8DfwSCXpOJLwmNfgTei2H8gPhci4ovZOQN3Y0HhRrDrnqQK2voExf\\n6F8HTlcgtDgcHgXznsLX6eHn0/BtFEhZCuIugOb7Yd5M2PAAOjeHNIMh7XT4YBd8HhtqPYJJKSFR\\nbBh2Cy7eImTZT+wJy6fA+5YQ6w8YOBmuH4Uki2FzY5j/HqrW4P9l3e7A8fQwrwjcOgAfR4dTsaFX\\nA2jwGez+CfpehBvD4MVNKLwUYhcklH9HTATvvoBxa+DNWvg+JfwwALrthw+6w7j8MOcTKFgbrtWH\\nOS2hSFo4uRku9YeCqSBTapgzFyJngDSv4ad4kG8FpEoHQxrC25WQdCREuQqt00H+ovBxRjj7Fk6s\\ng4U3CDubt3fAusXw2xPIFheiX4V4R+HTFXDtMDxpDZ/PhgQBtaAQEbkbC6ongVfPCIW4O4L96wiY\\n1QsmN4VmNeBQafiiGQyMAc2+hRntIfovkPRnqHAaMnSHukfh2nh4UBEGL4E9QaH9B2i+GR6mgo3l\\noWFq6Hcbdv8CbdbD7y1gagwoHGAhp8OEoPjdAXbvhqh3CEFtVYvDmkjw7gYsqw6J80C/69BmEuS8\\nDcZAi2C9FR8iBRqEVVB8IUTrA2viQuaOcDMN3H0J9edA5D2ES8NOnaD8DHiZA5q8JIRbdo8HGWoR\\nikQqfQjXx8GZwxCpMRwcCAK2bBPonI+wVXHmI8hZFA5/A6s3w8iNUP02jChBqCz9viIcrQQ7o8L+\\naLDoItzeBZliw3HQZBt8UBxuT4Plj+GbuNDjBawpBVvHg9tQOwvcfAXHO8PthPC4A6x/BDuXwqEA\\nDrkMphyGy+fgZNDdiwjTv4WrCwlLyzvSQMJfCfXJgVg0OBruSAZd+8CsdlBhAuwsAkXXwJndUPQ0\\nfBXEq1tAk/vwoBqhLa7dl5D1K0g8h5DKvfAhTNoPmxJB5HfwQy5IvA++/A9edYPFz2D0p7B2BmGh\\nOkEa+Dw9VMwOZdbAhZ9hexBxqgOTfoXcueCbJdCrObx5Cyf/hhfl4IMEsOk6tGwHBw4THn3aroLX\\nQSk6P4xJB0+KwfKOkPAGHGkBox9Ai+6QLhnhynjoUDiXE9KWhSivYeNWiJYGXvaDdjMhe2bY2QAe\\nBIHxkZDkBHx7CE5EgIK3YW4J+LE9XN8D195Ak9Mw9m94PRcyXYNfN8L5CjDuO6gTkHXuEkqUg8bf\\nqQqEhfxvksHuu4QkuQDIcqgUrEoPv/aDBWsJV70LxsDMhTC2Naz4Gf6YC+kvQpfRELcHzCsJyavA\\ngT+hwHp4lRCSL4OlAyDuMVj8Pay6DJv3Q+zhsLE93EsPp4M5cWS41pwQGvJLE8gzE3IXg0sNIdMF\\nQnbUtzHh5TI4+i3k7AQRC0LaBTB3GqSMBNXfQvehkCZ42dwlZHoN3Q/jXsDVApBwHwxsAbc/gqib\\noW9F2J0SyrwjbPy1jgQxX8KAQ4SRhqixoc9zOPkKegR4z3vwSWIo9jEk7QtXl8G5EoRqnQCSGXkU\\nXP8Pnl2BdmUhwXZIsRjy7YOa12HgdCj+F+TrC41iwamAfT8Pck2H8uMha2mI0AYqT4Hr1aFTcVhw\\nAa5UhARH4JfVMDcCDNwGSx5CmUbQLwGMqUVosGjaEvLUgRnB7ijAECSEU7MgXoBozgG5zhKu75dm\\ngzk7Cf0luwrDi5FwNz3MvAd/fA93HkOn99DwGKzvCt9Wh1gloX1qmPgWrvwH7x9Dw5gw8C0svgbx\\nq0KGidDlJdyrBvE+J7xsvL0GYzPAwDWQpzn8HTDJfoIPzsDFfJCzO/QsDWWLwsKhUCsyoZmg905o\\n2Q3qp4BIZ6DjJeg2lSBBxYVfoOEsSJ0OPgK9z0Lf2DB5NszYAtl6wIltkGkzaDMR2uSFA0chRz54\\nnAWiJITsH8E3M2HWIljyGApGgEQBG2kS3DkHf8SEh+2hbTMYVBL+6QvNssC8YDHUDq6NgQHb4eIE\\nmFcFXg2AnIdgzFuYVgpGnIV5teDfooQyjZ8TwcJ3kDEF1J9IOIAdlwfGfgtl/oDE/8HIlnBzCDQ+\\nD7urQJKk8F8sKJ4XJkeAYvngs7PQegLkzEWYhZo8C7bUgEpdIW42SH4D3hWFllvhVVq4suJ/P/in\\nU2FKeSjwLUR4D/snw5alkOomtL0HzSMTpg2iB4/7YKOfijAyf6km7BwA2atC58RQNCVczASlzkKn\\nmDCsOqT+EDIsJlQHnN4M04pBwqdQ8T4s2AlRH8DVepAnLsRIRBiq7TQfJlSDjamhUWcYnBQyt4b8\\nF2BCe6i1Es41gMwtoFF52HMbogdR7oKEYLrzl2HDDuhwHKYGVLM4cLwGRMkNP6SBs6vgakOotBJ6\\nz4bONWBOM9i/A26XhJ33IcU1yPEM2t2ErIngyR9wcyt8cQTyHIPm5WDHbMh+kDBL924+NB0F+x9B\\nnh3w9Vy4HayulkDdvNA/J5RdDQN3w8m+8FMvaNkXRu2Ec5Oh4XcwoxxsqQWlPoFjr+GzGZCkFGya\\nDq+ClugvhK/MnwfCJ70g3wtIEEysD8CByDBrF+GaNUYfeP4OiuyG7kkIZVOzL0Hrw3AiuPHHgWtH\\nYHllWPwGClaCmW3gixjwY2YYNQeGVYMEz6DAPtgaC/r8APkCTG5qeJAMsjyHDD/DtGhQJuDSnYOU\\nUyFPEkKm2tpeUDIOofA4Snl4dQV2RofpaeBwUjiTjNCIMLYu/JsIPqkJ3T+HKxug+zCIuh9urYZH\\nleFU8PqsA6sXwRdLIN8cmFocdpeEjz+FzxrCmuJwqwY0GQwFOkPzGDA5I4z8BtanhPkHCcGe5ZtB\\nu9yQex48PA+tgu9GJvgqgHf8A+8zwfxgIh40HwdCo1nQMAu8/wM+7AodZ0LbcxA1Ksx8TwjfCQLX\\nSytBzWXQMghiB3GROFAgEsx+Dh1iwKlx8DwilP4SSqaD+SVgaRuYcxCuJ4PuPxIuzvbWgm9+gTjp\\n4GXwbwja8ZMgSnO4Ewd+WQoNnsGVY7DpM8g9BypOgBP14MsqUHY9xO8LvwUZ4jyEv92/VYBPFsPR\\nG/DwLTwdCcOOEgIwy3aApOMh+QeQLjKMCA6s+SHZc2i1HbIWhQMR4VhT+LwvpK4A/8aB4oehTimo\\nVRzyJoHD+2BmA7jyCoomgGvJ4auCsDYbzI4JK/pA5ebwbDI0/xzi1YVcwYBgOUQ7AJtKQsSUMLEV\\nTJ0I5+vBytuQoiVkLgvnukDLCDDnFRwMBhDRIWkTeH4A7syDenHhZAPYuByarYOsIyFeFUh1EBpk\\ngz6NIdcbmHMASkQiVF3NygpVd8PVADNRBWLnhk8iQv1jsC05nPsWCtSEr7pBsW+gyyt4GA0e9YF0\\naYjA1KC19C/0vQVV88LEZpDsHtRdBUf3wvzF0OAmJL8GtWJA3NFQND0sSA2D88Lz+9AvNkQO2EWX\\noctN2P8R3JkO9WNCjR1wYhnUjQBJ7kOxcoRO75Qd4KdUsLozxMwPS7+EwrUhejWonwuKtod/JkPV\\n3jC8Pdx/BRGCzst16JYEdgSPgysQ9S9olRHK3YYE1aDJJVhSGjJvhEv7COnk6/rC4siQeDq87Em4\\n5ni7G3qtgHv5YNMBeHMUCmQjDBS/HA+FSxEaxNaeh+nfQ9sk8EVVGPUWPhkN9ydAxxzwWSpC7XTn\\nSTDyB3j4AWSfCaVrwISZMLwjFJwMaTLBD6nh97nQKQ5kOQQZvoFdk2Ba0A2sDl1fweNd8CA7YTYi\\n+FbsfUWY1ehfBvwI++7DX/mh/0JIPQMuRoGjI/73E1kL8uSHNldhfR64XRk2NIT6EaD8fSh8CIZ8\\nA28vQOp7UGAm4a0lWgY4NQl6LoM1t+D3HYTR0SyZoWsJSFAXvl4KGffAoZ4w5xjECMrPaQml0fse\\nQ+rXMO4+5KxLWK3/sj7UrUzIpw7Mbvk+hccnIPpraHAEkt2CuWPg+HW4HBzcSxOm05LMIRSznEoE\\n0+pA3j/gxGTYFgfGdoE1aeDeXMjTHWpMhRIdoeRA2BTcubsSAkpi/AnT4kD13+DzCjAtL6SPBvWq\\nw4IBkOMfKLoE0mSDOGlgdXpofhNKd4R9DWHlSsgTGzIngFuJIM0oyNgcEgRH2FKwMwmcC4oC2SDp\\nHbiRAPLkhSYNofwUiBJMyitDyxkQsRrU7wMpR0Ll1lCuJPTKAV+XgbHJoE5WKJIGjpaFb/dBn4cw\\n71eIWwx6zoeU3Qgb2c+bwby1ELMUvJkOl5JBjUzQOIB6DIM2d6DMSegxCdZmhNbloNBZqN2HcLKe\\nuzE8+R3unIarWeFtASj0GTS9BunzwM/HYPllKBQR0t2FCcPho4lQpAgMnkioA18d9EbTQrp68KA0\\nTMgER04TSn8/Tg3lkkCPm4RZzMi/woShsGENbNoEtyvA6T3Q8CG0HAMHk0HH4No5BVacg4obofZ1\\nwgpR5H3Q4jQhHGTOVDi3gDDlVmgblCkOGQPI5Al4/B28DAheNWBRMClsC3FawLTEEGsVdIwIP30P\\nuT6H8qfh/VzYGgdqHoM4D2HTEfghB+H1ae82mPAfbOkEH1+D019BsvKEErlcPaDmTfggF9wpD28S\\nQpEdMDc3TEsBeRPAkd+gfk84WwsK/wbd2hHKte7chJ0jYesQiNwfKi+DeKVhSRroUQg+DGoQ5WHs\\nPvjnGHTvDbeGw6z0kGU0pF4EI76GTWPhq7iQ5i00AdevwJPoMH4aHIoBO4dBs6LQ6i94Wx4qBSz1\\nPfDRv5BpIGQaBMdTQ4nYUG0gRLsDPW4TthEXLoXvnsOiw7CwAMydA7M7w58N4dc+cKwU7G4HKWNB\\n9gBk/QTOt4e0w0GqDoQu7gGn4PNgyDYNKheAQz9CkaJw4xi8bwdZIsP0Q7C8HdzKAdXqQMu4hCyT\\ngC0x7DsYFBG+LAdb28GEYNwHGkUg7OI9vQ0VY8P9OfD9JjgfCXL+C12CE3EkmL4Ihi6Fl49hcxrY\\n3Q8urCWMeY5ZCz0uw5V3kCwFdFhMSJnK+T3ELA3j6kOl6lA+C+TtC3eOQt6OsOULyDkAFreAJfVh\\naleIegMWt4VGLyBKKWh5BbpGg9xN4XAxiJIaqhyENiWgSQLocxhm34cowctsPPy2GZotgsyVoE9J\\nWLYGBq6HP1YSolODrmUwnxv5EWSuB+9vwOkgK5YZXj+FX8/AmBww6RRs3QdNN8PxIIUQETa1gvU3\\nCKPQVRPB+8Fw7UNCavDJjFCrP/zzCKLGg0u5Cc1uPwZD3T/g6HdQuRl8WQTalYF9QRJoE+xpDQlX\\nQc6sUCwqXJoIjVbAwCxwvip80hYSlYFjR+DQYUjyCVTuBw93w9yTUOM1fB90V+/AhbQQqSvE/ovQ\\ngDl1L0w5CJ/mg5tBGHwITDkCrxvB1S5wqiTUzgd9gvFye/imENzaDEX3wttHMPs6tAL9H0GBRXD/\\nMygeAS4PgzhXoM8DyP8nrPgVDg+Eevth3VU48wzSniVUEg0JGFH5Ye9YuJUVtj+GmFOhYCeIlha6\\nByvRiTCuLPQ8BztBwTnQ8zMYcwDiV4MNJSFp0HN8Bat2Q9eT8DgbJIkA94NpdCz4cCFUSwFR+0Dn\\n45DqFRS5BWfGEAIkP4sBDZ5D1Mjw2wVomhcixoeUB2DBLLjRCkZ9QJiqaV4MqgQpkKSQ/BS8/gtW\\nn4LVneD4Sjh7G/afh5mv4c0QmHUULleD8wHvLZi7lIBiA+F2JIiyjhBbWuYW/DiVEDmRfjXs/hzm\\nN4JKU6BmAMIdAb+kgAt/QJRJUC8pTOoK7bbDuKOQKZgxHCbk9R+bAl9+AENXw+kx0CQWTOsIn2cm\\njAl/sxwGB/S1M7AyNZQrDkl7Q54C8L4W3MsA/5aEJcECNy40+hgWHINf1sPkIHZ9BZ7Fg4WVYPhJ\\nWPEaSnwDUQ/AwijQ+yKMagibvoaGheG/tpCxH/SZS8iOvzQM9gUL08TwV3M4PxkmJISIyWH7cbhw\\nA7q/h+GfEDIjj5+Hg0mhQg2YdZwQCn02KUz/ECp+CQ//hreFCUUr51ZA/+mw6jyMHQYDgvnKS5h7\\nC74bQ4iSqVYPBnQj1DD/eQtynICZO2FkCtg4CpKlg1OvoGx5mFEExn0Pu07C9iSQbCrsXQ5/ToHL\\nsyHXfUKW1fvPYch8+LcrZI4Bgx9CmzywpzvhQjbeQvhqKzTpBHlvQ5830CITfLkG7maGh/Gh1n4Y\\n2ho65iH0Ccb7FArfhIobIMkESH8azv4KeWLAJwXh70lw4h5cLAE/94PZeeDgQUh/GJrug7r/wu/n\\noEc3+Hw41J9ACDEJcMGLgo3NWYQ9nX7bIOkSSLgWkr+D1PFgc0MolA26x4e9B+D5/+/HeWokNC8N\\nu9/A4WyQZitc3g/JN8DgBPBwPUSZC+tfw/40UOEnKLoc7peFfrsg7XoYsJP/J928BLlqQqzfYEtW\\n6FIHomaHRd/Bl0lgQy1olRfSZoZhUeHMAriUHv5sBPUzQNGgczGYUGMcPOyi7oasSeDT3+HsGZiW\\nDhKuILw7XswCk9bBoPLQJS5cvgmRTsKh+fC2DxxaQqhPrtkPXn1HKJ8+FB2yrIBvs0Pkn+FxT+je\\nGH57CLEuEepKEgZE3ZFQfSnM+xa+iQc9B8LkcVD3Afy6D0omhjrBY/Q+HFxHqOCIngPSD4NC/0Dk\\nnhApLWGKovcrOL0BWgdckAHQpjc8+RiOfA6HosCM2LD+b0Kq0JoYhEi3hm0gz3TosQ3GPoQSg+DP\\nM3C8BKFCe30naLcORpSCsR/BX/sJw7lXKsGekfDD71CtE1zISygLn70BNpWFvxNDvjGwqCCk/Bk+\\n3weFO8Anf8LHj2BRe9gWBNa+hFqv4PkYKPkfrK8H82NCy+Vw9xW06w67FkCa/bAkHqHJ8V1v2F0Z\\nnl6GXBvg2QLoNAOmXYIfnvH/4JyvIH0nGF8CohWHNBugRQDCaElYnA5gwvtqwJ1HMKUJPF4KuWfA\\nogLQInjxB827PJB2JizsDfmvQ+cMsGQzPFoEhaPDxqRQpiusuwGPkkPsxND5a4g+F9YugumzoWOw\\ngjkG544S4iIDGP/0XRB1MUTaBdOWwxfnId89qLcFRh+ExENhyEpoNAweXYFCy+BJGSiYjLBnt60k\\nZEkAvRdBrDyE4ppyh6DlGqhxEsaNho7fQIU5EO8a3A8OKDXhwnT4PSWh4rpjPYg6Hxqmg1URoONx\\nmFsEXleG6Q3gdk/IN57wd21AauhWm9AjGasKVAjqEbOgVE14+wFUDA6FJWB8BPjkCGH/OtUeeP8O\\nGvSHODkh2n8QZyFsSQYbr0CB+zCpJ6wLiHRTIF81ODyDcKX4cDakK0cYnDhx/H///po5YMoUWDgY\\nUv0J39WFOSdgdQnC2W2MnTC9O9xID8Vrwc1v4FKAHVkIJXPBsbEwJSoMWgwfN4W/XkLJX+DGHPjv\\nV8LD0MibMKAmNGoO/2SF+wWg2V2Icxee7IOfMhB6U0oH3/96EHEjocthwBb4rhS0egF7rkOMboQz\\n++3HCE0ntW9B3zRQbTA8/wQ2xIJrb2FbS/ijJTRoB/srQZ59EHUXnPiXsGwRoJLXrYbOASltFcS6\\nCk1mQ7nLUK8qNFkEr/dAygmEkKZRawhtqsc2wuFncL0j3GgEH/aFOuXhRl9IugVi14RcyaBwf0jR\\nG/6bCR0+gNkjoX4CWNYGVmeAEwEdsAr0ewsl58HkqzDuL0L/b9oXcOIgodllaHMYlel/3584n8LZ\\nuTAtPUR9BZu7w6Qf4e9X0Ko+/BNASjND1ZKgflVIfRamjof5aWB7drjcHPIvhtTJYfdZWBtsGaNB\\nzGXwy2TCe8nVvrAsA8TtCtOuwNPvIHIcwl/OSgNh6B6Y0BA6XIc8CSDSKegVEerlh6J5YM4M2JkD\\nbr6D5S9hYhf48R7kTwMlvoL9M+Dc33CqDKHM5GVkWJkIcqaCN0E5/wf45TZMK09o3Sq3AhZ1gEGd\\nCU1SZ/pDpTOQYBWszEVY3j75Ayx/BlE/AWnhw/jQZS60vwoT/4Qaq+Fmdoi3A1rOhF4noUltKDsE\\n+gaIyBmQdxasbUKoGq1YAR68hTVPIHk/+OsOfLMIMk2GJvsgxxFoVA5ybIHsUWBfdChWCiYvhipd\\n4Ep3OFULhnwHc3pCvGCvPwN6vIP9WaDax/DuV8j8Am4eg+HzoN0ZeHkN5u6C41eg8zyY/y8M+QoS\\ntYfbQZsmH7xZA712wpGvodlYyP4TjI0Lbd7DuEdwrAm0vQ8F6kL/C5B/HDw7DlXrwYpVsCQnDHsK\\nHw2FD/vA2xTQC6QuBCc2w4HREOMeVCkOd3JBonLwz0io1hruNIb/JsHiJLCuKxQ/SOjubHoZPs8O\\nX30Pj6pB9jRwMieUGg2jXkOOwzBkC7yYACV3wKK+hNT+rF0Jm7zb4kH9rvDFcvhmBkTLD/9mgjUD\\noUBPqB4V1q2DV/Nh/Ra4NYAwKXKgPSyoCif+gb+/gKRJ4GJKiL4e3pWFoR0hxQ0Y3B1G74KlbaHl\\nd4TtzkunYd4vUPQy5G4BE+9A7Xkw/C+odh8WLoEvPoZxDWBDQD4NHs3fQ+RFsKsYXJoDXdfC5khw\\nK+gnHoK4oPsrOPoKtj0kXIpFPQZzgpnoZ7CmL/zbAfrdg0LNIEpdaD0GjgRDyO6QpQ5U3QC9/oF2\\nEWBrJ0iSF0ZkgY+/g0Vfw4jjcGoPJFsB276BXIdgyjNCOfqcbZChJTQOphdtIUUDiP8CHuaAKJVh\\nbQLIGQ9W5IFPr8KG7whtdP+nFwtwJI/hxVjIeQcybofeuxTgHdcAAIAASURBVGHRMFiRED7dSLhm\\nDRZwjdrB5bTwVRrY+D0kvgoXGsKDoJ36L2QMgDjTCVN0S8dAvAGQYRFkO0dI+h6bE96sgo3RoWk1\\nKBEZSh8jVEF/FIFwLRXhL7hZG7Z+Tpi8uZgH7l/436daoycUyA4ll8O825D+NlQYRwhqjrAJVmWG\\nj45C1iBLWg0uT4E3f8DeFLCuMqE6fWZ6SDgIxuyCkQkIpVgzbsHkw9DpOvzaAtKehxpb4Mf6cCgp\\n1J8Nb5dAw0WEq8zVPeHjbPB9Hji1EeK0gt9vwvwkkDkd7KoGYyPCn8vg+5hQJi28OQhDB0D8oBLR\\nEUyAaWeh0Ar4NQ3hVCnA3s5eARsjwM5KULEZLHoO/UpA1c3wXTW49yfcH0J4rrg8HraVgY+awIxL\\ncCcJDKgIzZdBnzswpRvMvQFjUsJv6WDJp7D+LPy+H349AX1fw8dBdjAPfJsL5kwiIl0fQZl1MOM3\\nuB8F5q+E33+CDs8gZXno9gLOjYLCsyBiY6jRkND9lPsfeF8Afr0AUe5BwY3wNB/s6ApDp8GLK/A6\\nQJzNgTcDYchUmP4vlG8LPRbBp2sg+jRIvwwmjICFI2D6eih1Ge59AVcrQ5KVMPg/mLsQYv8Lh4oR\\n6oqDofS89tDuA2gX8KVawZ/v4J8u8CA+fP0v1N8MX8eCH4rCg7twdQYUD1acg2FuQIR6AukHQbb1\\nhLrl/KVh9DLoPBfW9IcbmQk7jxM+hN8rQ9IesPwozC4C8+vCnb5Q6AhU/AQmNYW4P0G8p7Aw6OI9\\ngu09YNk/hBOgdXWhwjJIthYaNiWcaT0PbtWbYOMGSBoXvnwNfa7CntSwagRsvATv48LpQzD1DNSq\\nDLMqQt5a0KM8fPYYYkWDrJUgxRTIBpYmJvTQFckN30eF+PPg25qQbTbMCzhGV6D4IEI2d619sPw2\\nxB0LicsTVpd/TAStP4En/eBUS+gdMKP/hDQZoU4L6BW0aZrDirEwaRr0GwhXc0HjNDDjOiSpBz/F\\nh4Y5oENr+GE3lOwKOV5AhweQYgksyQgHFhBKV+aNggePCAvbTebC/EywuyphjuF+Cmg4DhIngtzd\\n4GhQjEgIk19Cnyfw4VOIEQ3mpINqd2Hwevh7P+z4DrLshYXfQ8Nm0HcU/FAFFu6DOfWg7Bs4WQPO\\n7oBHc2D/Uri8ASI/gs4V4e072DYOoq+CMg9hcDIocwdm1odrRyF3MzjfFyrth4s7IdEjQsl0skGw\\nOxc8jAXn/4ZLK2HPTciZBWaMgFc1YPc5aHcRGhaBNJdh61s4FnxWgyFZ0KpLD7O/hDivIHfA9rsG\\naaJByweQajOUvQwr4xB66D5NDKtvQZ2iUD4VbGgO57LAobPw207Y8QgOVoA296B1AjieEpY+IMwX\\nfnAK4kUDyaB+PUJOfc3tkPEqIUw1z3oY9iEsrgYX20G26/DbLhjVAQZ+AW9Sw5ZTcLU0xPgJGlSB\\nw9/ClyMhTnVoUgZqnIZI1+HkO6i6Bl71gfIxCesFFUvDyutw5TnszAuTFkCODjD+BFyYAicSQrfL\\nUH0T5JoPua/DhXyw+i8o/hEUiwYDgifYRUhRF0r0hwa7YX40GJgUVt6BSOth1T64mB0i5YI2FeBY\\nDrgRGyb0gmTxIG1PuJoNHn8Ac99CpyCx+hoWTIL2ESHbdLgwmbDDm38TdAwCKq1h5g7IsxvKvIYP\\n+sHdzbA7IeTIAbNiQ4v6sKQVJA6mhh/B3NdQ8yDcyQMxvoATreHmQkj+FH4KJtlzCcPjJsO8L6Fe\\nO0hRFiLVgjMVYNB5KD0Wmp+Cg8NhZn74JjK8C2pGbaDGI7iVHroGW6li8EUaOHAXuh+AixegWhmI\\neQm29oPkZ6BVJLhdHurWgvdv4cEQWPYFXKoGS0D3KdC5IJQdB/WCVek/cCIWFDoEs7LDq4dQ9Alk\\nCGIewXHnTD8ovBdKvobvmkLf8jDiIGGb6eu2UD0ivK8G5aPC8HYwJgPs2gJjWsLvu+BZof+Pqbts\\no6psuza8ExLSUtLd3d2gNNJICRJSkiqpIN0poIAS0iEgIN1d0t0d0ilS74f5zO1+/wCx1prXvM5z\\njHEMaNcQcg+GFlUhQRa4kIQwd/DZcujVBkp1gYUpoUhBaLiEcJLOFwGiL4QVmyB2SZge/PgWwJQ5\\nMO9rGDcIWi6GpSehzSA40RKyHYOCg2BlJfhyKHQfAxFyQb5PYd0K6JIeZkyBVEXgs+DSdgYSJ4Am\\nf0L2qtBjOOxrDQemw+J7sD8uLKgLHz0lTDkFxJ2iY6FbcZiZiZDvlWQQDOkNDe9Ar8Yw+2uY0Ala\\nJYD0y+HjVDDlZ9i9lnDl++9++CE/9J8Bvb+Hdf/BFy1ga134uz/UKQcPR0KEvrAnOZTrTXj5aNYQ\\n6syEp0dgZmroHgfWxYJfqsDnNyFakJrpCn8cgyeR4I/vYPbncDAvHKlJyCCpEBGGboAHE+HH2YQ2\\nzy/3EPKIM6aDNgFw8gbEKUbI7z58EGLXgQZlCEGFsx7C6r3wOgrsjABJD8LwDNC5PHyzEP5KBA82\\nw5jfYHlNWH+PkM41N9gFriQ8gIIet9n1IEVGOHoHIv4LMSIRAngXfgtHdsHaf2Dt33AHjNgOnXfD\\npn+hYwpYHR9O9IBDLWH7PcItbLAJy7kWzi+CynHh50KwYAwMfgklgk1hJ6hfFRZUhi6JoOsPkGYo\\nfHgQEuSFJAuhcbr//Vomr4Jbs6DgEJiZEOIGJ09G+KAmNL1IaPyP+hjiDoeq46HRYcg8EP7oDhEr\\nwOCt0OIAVGgBQz6B0i3hVknYNBDmBvutptCrIOR5AK+2wIkGUKIovP4aSmSChoMg2S6IvRMijIKb\\nN+F8b5gUA9aUhkMdYeVqmPANjKoLWe7Dlk6Q8QaUTwnnbkHcntBlD7S4DRlKwJ1/IGt0GFIdeo+D\\nRIFP61dYHxUOr4YKyaF8L8Lx6UELmPYffPMxxF5K6OpbewU6ZYEHy6DWz1DnGXSOCtt2Qf3F8Lgs\\n1BsF334Cmc/D7qxwOZDdY0G3YB+zCJ7Gg6rB8xiVMLr/W2yo3hKiBZzxlzA5SFkGfMRGkCAilDsF\\nbXLDg39hW2/IWwCuN4GPa0Gl3FA3OaQqB1cqwtxrULsQnKwJ71ZB78SEKOyDp+D4NNg7B+4GMMwf\\noFAJSL8NKv8OL17CtbhwYyDhwBbAUQvtJCzhydsYhv4GnZpB2QhweQVkfg2zv4V0UaDRXPhkN9yM\\nR4hN7h0EWe7BvUSwcRh83h4mZocEY6B4IKyvhILnYVQZaFMe9syHoR3gy1lwJx7M7w7rM0LS0xCl\\nJxysSGgSUJXwHPv2IsQL8BYBdnUyXC4NCabA6jsQoRBEngRZOkKuKHCiDHTeB2kDW9FyaNYT1pWG\\nIUUgZm34PBek/BwqvYTfxkLsO/BLZFj4BuZlhtybCEkFMRNAxFIQcSHkKgY/9oOiaQkTjqUTwL8d\\n4O9/Iekt+GYKbEkFsQM38B+QcRURGJ8buuSBRIFxtQr8+i+Mngo5KsA3AUW3N6Hi3nQ/oS/q8WzY\\n9Q5uTYC3r+H6F1BqBCHJd1QimDsF6pyBTbdgURN4tBvifwJXC8HCJFD0V/gwBrzbBw3aQ+liUPo3\\nuN4eHtWFqcugaCsY9S3sXwCjJkDECbA0JvTYQViWOao6/NEYiiWAZs3h7XtoVhM2DoIfZhMujfNH\\ngNMPoXd92ArazoQSq6BVYcIdz9OP4WgMOBQVVuyB8v0IUQUbAg7ZXcKtxtm3sK05tPwIWkeEVAEM\\ndj8UD1waA6HJdcI4a/xe0Okx1EoBh85C1zHw8jYkHQAT9sH6uvBxILwehGOfwfA2cC0GtMsFp/NA\\n1o5QbBPcaghTo8Oo0VA5HqGwWKcBVOtB+OI52wwa9IHhEyDDELgQG+42hPaNocsSKL8IYnwI8adB\\n6YCGlRLKpiKEgPz9ATT/CjpVhSWtoEkPwiKd90egWA549we8TwGtvoU7ZyHpIvi5AUwsCekbQ5xS\\ncPo1nMgKAybD+e3w63y4NgeSZIP+taHke8JYxreL4N1D+OVfeBKBsKnwaZDAzQYpXkKEXyFha8Jc\\n5+V1sDgDVG8KDfvBvUOEnpiKcQir1k8/h9VjoMw0ODYYZgWQw57Q71soMZsQApK1GjzJAz3WwJ2G\\nhLmhIkkJC3N2Vod9a2BDXnga8OSSEqaDtx+G4gcI+xa/ewCN00CbqJD7EkwLvqM4sPoy5C0BkYP4\\nxWzChoMxzWB8MiiTAiIkgGjb4MhxWNWdkPYU9S84/z38WQ1iPYIe/aHLh9DnGhTKA+UPwZgz0Pdr\\nqPkANu+Fe8sh1U9QsT3cCKzcESB9KvhkPORoB4l+AwFl+z5MbAbt6sDCHbDjG6jfAQ6OhE5LIPkX\\ncPM2xJsLm89C3muEOaZK8QijMFuKwRcb4MxmuBQE1NtDvP/g+SewLhchRObzw9BrIJweAvvSwfUk\\nsOksfPMrJPsBOqaBiFlhbGMoXAn2zyRsQsxRFqbOJqxO2v8Gnr2H4kPg3HEoXwxSDoSD1aB0a/gq\\nLlyrDl3Gwqj1sKQpDFgAs0HKU5ClJdSYCk9PwNUj8P0gwi1F4E47kgaS/wldAujPZXj9LXx9HQ4H\\nO9oLUHA/JK4An+yEpoUgyyQo3hq2HICrsWH+FsjUGs7mgfP1IcY7KJYPTt2Ffc+h4U4QFzJEgKjr\\nYcZpmDcYPhpHqIFszgtt28Ot5HDzNexaACUWQ5sAqQ2iN4Zf9sK2KZCjCXQPLsdVYHxOiPkNbHkP\\n5X6HdT3h9+gwcQAkrw5Fl8GAioRhqWrZYEZzOPEdpJ8I9yPA6BnQMDCbB7vb99CrNLRuDx81gjQ/\\nw+Uu8E0F+DsKYePLhrQwbxBceUcYRxgeWDvew4jKhBJwmVwwpRXhk9462OYugNzFoWds+DYP3O0P\\nw/JD9DrQ9i1Miw4JJ8D13YT5xKTTYfpZIjFsBERpA1NGw/Q6hPHy3bXh6miYGBtaFIW0RSBTSsiQ\\nAwbMh0sj4OcrUH81ZK4Pta9Dp46ErdpLGsPJrv/7QcfdCFdTw+ashDPc3dowewfsLQ/DLsKDLYQP\\n3pb5MHI5FPwC9gTsn4FQ/QgUyQcJI8HtFxBnKfz3J/Q6CQe3w52N0L8yjGoNybPAvUDyGwubcsLy\\nHbCrKjyJBvfPwudtIMXnMKo5rJwNu8dAw3yQ+xy8TwiDhsG572BdBFi4nBAEWqAIVC8Ft28R3u47\\ng+OP4NxjyHAQGk6CeSeh5xRY0B4SX4K3J+Ha5zBw0P++r4mjCC+jCyJBxMpQ+hL8tRX6lYJnQ6DS\\nHNhZCJ4EV+23sLYsfJkVyhaAUt0h9XgYuRJWP4RaFSBdbuiaBRa/gOnV4WU7eNMXrs0ghH0EWd6F\\n30PsXvDbpzB3MOwdCRt/gNQv4OhSSJAH9i2Ads3hk78hZn6ovQQWlyZsvhNwv7ZB1kFQox2c+Rte\\nBkHlP+DFakL/WceGkOEaRD8OSdJAh61QIgGkvQT/NIP4R6DCNci9BuIPgWTfwX+tofinUOQUpG0J\\nY0vA4TcwrTOM7AzVY0Krm/DZEsgRAE3WwRfBbrImbA6CCEnh61Rw+ggUGAG3Y8Ofj6HCeOj2COq1\\nghm/QpNrhLJFlqVwvx3UOwdTAsTGHPg1L6xMCb+PghJ34cumcK87dDgFaW7DoMrQaTu07Qblj8CU\\nAO/5A7QAE7dD2uJQtQ/M/gMSRoTdU2DYXZhcC7ZFgJp54Wp7KHgHLj2Hn+cTFjRFSE/IEPp0MHz4\\nBu5shg7LIfm/kKUrJFkGSSfAkemQOjVETwGFHkGHnrA4OSHneuI/cPxz2FwUNu4ntL3HbwtNr8GD\\n3wgb33qPJ/R0vk0Ml+fBi69hWHooHtghCsLhVxClKlRsDJPeQuoo8MUUaPkGdseHj2JAqc3wZRs4\\nnwJSBSbf4bAwyMFdhVR54eZAKF8cxsUjrGla9RX+75mt/xm8TA6vF0KlXbDzCNyvAO0fwrlvYEhn\\nSD8UjrSG2Luh6gNYuhN2fUq4tVo2Bo58C/9lhX6zYOIaQm9i4eYQfwp02wmVLsDeqrDpT/h4M4y7\\nAl/3gB61oPVOaBkXTuWBXzvCjW/gn1/hfeC6iwERZsPQ29D1ClyIDvnywY/HoF1JmPIhYc56aQKo\\nWxXu34NbiWHWLEi6Eequh98HQvr28G4tYbhn73pImRCK5Ib/TkO3dfDJRJi2DW5OgjZDINV8WNgd\\n+rSCbpEIi8JGpib0ME2ODp9kJlya3J8B3QtByRaEg+7m4dDpC8j2FtbMgFet4WRqqF8f2syATp3h\\n0ht4lQtK/AS9t8Dv8eGHpnDhV6jWD2rcgiQpCcMxFxPCxtQQZxlhIV7ZQrA7NXz8EUQcA+9iE3ba\\nvsoNSaPBtNqQLClEbgMP4hD6t7I+gZYJ4cZyKH2OUCDenhzhS3RwoK02hW3zIW5wECSBhtdg80j4\\n5RJE+gHefgZjesOfUQn53U2uQu+C0K8T1CkE2SfDV7XhYRa4VJswXjspMuzZAtFiwrSxMK4WJHkH\\n26JBrQNQ/zl8kxle54Sp16BqCTj5BBqsgxpzoF8TKHUCBgZx305QbDrMGwCbZsK7IbD0AlwaBac+\\ngHt7YXB/yLIS7laBbH3hdV0YXgrizIAX5yD9h7D3S+h7HnYdgmyB2bYyNIsI66/CjgbQMC40WAoT\\nckHEu5At4FflgBY9oXJRyLwBaneCEbOgajzYMQ5uPCPsHj9+DfZcgOt7YFJGQjL7+WDh/Bpy34JW\\nZ2B1Hsh5HYZsgOV9oUWwm/kILl2DuMGubiQcvg4vWkDJjVDkGlzaD0efwIXjsLcwRDkFq4bA2cdw\\nbTgh6+XWK0JZs/gIyNEC4pWAnS9h3CRIlwQGNIYKB2HcdtjUC640g7hZIVVZWPM1lIwBGYfD4/Ww\\nODLEOgsv7xH6sYIrTpZ0kO8VYcnSn8EVJHDLVSNclaf+lrDHPnZvSBMJZnYBL/g/HJgXm+FQZeiW\\nH6YFT2JpaBYV6r2FksErOcgTbYMKH8PqP2DUJRjQC9aegXttIc9zSFcQVgyChvEgTw6o3hjmL4AR\\nt+DDqITMuexdIdoRiHMP+uQipPgsXgAVP4O+JaBpK4j7COKdhy51YFw/GLcSJvwMNbPDqsDQPRxm\\n/wW9t0P81tA9FZROB5F+gk6Z4HkvqPkXbMgJvUZC3oqEXLFYq2FRLlieE8YEW/aokPg7WNAGvrsF\\nY8bB+pkw7QjcmwpV+kL0ohCtA6F5+W5eQtRFcDq1vgRNLsPD7NApBTxvDt89h/TnYGsk+OsJ3M0K\\nsXPB4TWQ7CjUaQJDSsLpRjA7oO4FWbaMMPwQjP4U9v0K82vB3UjwuhL8NQI+LwE38kCEEnB8Gbzp\\nB9nmEnYkjD0EexfCkHdQsww8mg+/D4VxraFEEcgVB/ovh08vwLf3IWst2HuNECk8NACi7oO3zeBE\\nESieHJbngW1ZoMxxaDQJGhWFE9FgZ0/CMz95T1j0Cg4lgbMlofgjyPExtA7gF2kI8+bfRoeOH8La\\n9rC8KVROBRkawO2RcOofSJ0YtrSECsvgfSoYdpMQx13yLUR/B/+8h/7doGBwznwO0YPP/DmcbAyv\\nzkO6T2FkNPjsKeRJADFewKe34OpdOJ8Msv8Jb3sStlgOXwbnfoJ/R8DFrhBxD0xsCodXwdmLsGwY\\nIYt8cVkoWxrO5yfsoiicFH6ZAR9HhWkNoNhUSJ0JBq+A6begRCpoXB26xoOLQyBLNcI+hkO9IOEs\\nSLwNug6Fz7+GpO2gx1nonxKal4NutaDOOsLg3erk8F8jSHcN0mWFb7PDhJIwbgwoBb1aQcbMMHAi\\nLOsN8xpCt0qwaQRETgobYsCvBaBNfjidC+qlJESdxy8H19/BxEPQ8DRsLUxk9jSER79DvFMQuz9U\\nWQs7dkKtLZA/ChzoDl2uQ4/CMLsCzJsLP6eA61FgxXBIVxKW1IEPCkG1vjCtDpSqD1fKQe+hhGUO\\neR/ArbqEltg/R8HkiP/7uXy5FyruhwNDYFda2HYefqwJWT+BfIlhfCZCtOkHSeHFGEJA2cz+kPUq\\nNN8L37UjnJVPXocRR+DDcfBDLmh1DzaC5nMgXiqovRXavYLr5aHXeLhbFLasgx7V4KNpcCQrlBsJ\\n1aMQWtSHZ4K/VxCS3NP8BKevQ6qnUC4zZL0Cc4NJaCK8Pgk/D4Ux30OX5fA6MUyaBB+shKOfwIKN\\n8C4rofpepRE0fQcNqkHqw1CoGaF/Ylk/yJUanr+FwlFh4o8QOzJUHw+pDkL8YzDrDYw5DJ+lhvFH\\nIfYgWBDUGiQkZPuWaArXR0DpPZC1GSSpB7+ch43jIWcWuPwnlKgDgxZC7eDhbwWte0PlWbD+Pdzr\\nB5+mgspvoMNYGPQESjcnrMqZ+ZrQf3OhOqy6Daefwj+noORuWHcETh6B5xXg5SQo0hYqpYS2bQkF\\n1oxg1TuIEw9ebISS66FLdWh3j3AASDIAWmaGf/sS7jj7fw6t0sPfH0GKA/CsFHRMD43rwj+7IONg\\nuLsOMqeDMZNgTIAk/QaKTIAekaBABUg8D6oEmaZfoHlJWDCDsDct6zSIe4fQbRZkxHb8CGMrwMkA\\nfvEe1k7C/9G/aq+A3DOha2TImx2OdIJUm6HMDqiSGaK0hbE/Q4o6cC0HTKsK2/cQlsA07QGRCsLb\\nqhChDJy8B9uCo7wIISnq69Lw+zDCufnozzBiE0wdB1++hG1FIflXhCH5SG3hWEFokAeStobnfeBm\\nXWg0AQo3gWHdIddjeFoZrnSCg23hyzmQLD1cLQqRgqFoORxLArsWQ6q4kCkWVKtM2MMRYCmutoF0\\nH0H20VBtFFSo+L//+/ECsGE0JAmM3oGj6xiceQyjt8F3iWD8H3BnOcy6C59OhaVX4OZ++GAyFP8F\\nbs2Hj0bB/Z/h1Fz4ahO0ewFZJkCTzvBdD8KL75C4kKQuXB0Ow9bA8wNwvSE0OQnfrYPVt+HTmBDl\\nGfzXFOq+g85lIG93eBNgMAORehFcrA4rj0DqcrAjMsSJCXtmwXfZ4OAVaLYC/ukJrSJAkXvw/ShY\\n0wrGp4fBOyFnfVh1CLJ8Bs+nQbQvYdBLeDgA8hWHfMdhV0Q4UhlS54H0o+G3ZvBxUkgUHZJ+Blmi\\nQZNmcKczPGgDMYdCxy3Qsh5hnq7HQvjkEtyIB/2LEDaObPoD5nwNv/aFX/LDgBvw9UPCE2zVFBje\\nElYNh6srCMXHswdgfeD0jQDDCkO37vD0S/i+P/TpBZW+gc8yQvOLUO0V1EwLY+fCZy0gWmL49gZk\\njg4vM8GL7HC6EyyaAnl/g3zVCOXgSsMhTSpYPRzi3YW/SsD12NB6BGwrAK92EhZgBwb8wPw+6y2R\\nabgbch6EmtthdRtoHpdQFuw5DTpUhO+OwbsaMOca9N8OG76EbcXgh9+hQn+4lBD2F4Z7ZaDRLmgY\\nB4q3gr7t4XU+qHQciv8F6xPD/LxwOBMkC+AIO+DNCegVF1p/Aj+UhKH1oE/g0gjMd6vh6WEo2YGw\\nyiNlfLhfDp7VgY2pYPEruJcHvo4M+05D0+9g/HT4pB/saA7va8FX38OqYoQ5vlcZ4FQ6eDgTsjeE\\nyx/BwkUwZBvUnwXtvyE8TAd2gjJgZjGI3Qf+qASZX0LzidDvU8iUEa5tga3fQ5I2MDk/1J8JWYOj\\n8Nz/fhwTNsOa7yHOHji8EnrHhAyPId4IeHUcmgSJrQXQITssqg5zglxbF6jzBxSLD1umQcLFcPN3\\nwtdAyh1Q5iH0OgqvzkGEgDbUBtaPhTR1odxgwpl4QRMo8CXkrgUjukCm5pC2HDRIAoP6EiLyzkUh\\nLG4K7MClf4EaBeBCFmgQpGg/hr47YPIF+OI/yD0XXlaAzWfg4mXo/wySJIJvI0GJr6FFH3geHZb+\\nARPbwz+dIdFhOD4OBkaD/U3gxzfwTwzIOQleBVfqmFAhH0SpAC+C47sdpJsG07bA7+VhXTR4+xyG\\nz4aOc6Bvdrj5BfRLC48D7l1/WBm4Ic/DstXw53go1g/WfQCJlsHRIKAQ7MyeQfF8UOYneJUVWtWD\\n6FthZnz47yHkCrbO1aDBWIh/krCHMTB6H/8WOmSFXMng2/jQuxqcKQj7ThLCFcsWg7wnoE1dQnfa\\n1VFQ9jB81xPu14FHAyBOJ/i8DvReD4ceQdrtcBGkfkqY9ds2AfKuh9opoPNiOLsemkWCZqvhygmI\\ntxIidYIlf0GmbnDrBBwPLPyvIEt02HOIsNvx4hHYHZB45kHu9TD8Krx9AI+WQd0u//vMA/m181uQ\\nDCb2h0/PQ4kg7VUDfn0A06tAzVwQ/ylhUcyiNJB/ATRvB7v3QbHg8roOtvwLEYMLaw+wDdJ8CDOj\\nwd04kGQJvF8Hg2vCh1Xh8E240INQQEwzC573hqPXIOVpeBw4ekfC/BIQL3AGH4aSi6HxJDg5GN7c\\n+N/n8GARvHlMODCXrAKVd8CTDTDiV3g8HOoMgL6joGkmwu1UiYMwuQ8MGwlvm8COe7DiKsTYAmk7\\nQroHcDIObEoG33WCyEMh5zb44D607AJ/dYBO3SH7b7CkKMQ5C03iwPCLMG85XNoLKVpC/iaQKfBG\\nL4RnlyBRDhgTDVL1gTRjoUs6+LUk1BgHHwTiZgboUQ6mvINT9+HuekhwEIrXgI4P4EFwvUsLiSvC\\nlE5QIAHsCJiF6WHbUfh9PlTeC3d6wfcpCe32MwfDpk9g7BPocAaG54SRwX76U2jZEtJugfhXYW5D\\nePsf5JgFKWPAPxWh4WEYEPhWE8LvfWHcbrgfsLX2wqzEUDSgCnwJDX6GYwFH8x0kCE6Y1FAgDoxu\\nAOlbQuXBMD0TEckeEw5chdox4VllWFAa0hyH0jFgf3/Yeg+SpIZtBwhBBiNawJvcMCwIu3aDjDvw\\nfwDAJL/CnBrQpyZ8PB9eNoX3l6BMReiVH5pdhH0zCa3ol0pB5T2wDxQZCpE+h5/Ow/A+UDIBoSG6\\n9HzIng0KboPeV+BqJvgv8OLUguMTINLfkOks3KwFf5+DmN2hY/CyLAC3A4GgLixaAhEnwd/joG58\\nWPkGjqeBEb9D1WHwqCW0TQn/5CS0qV69AtdPwPgjsPF3mDICVraHFYlgQ0LYXgLGbIdkF+B2XNgY\\nmJH3w5yXUCMX9LtKaHne9iPUew4l/4VD4wgf1/VXIH4Z+KUONNkK9/6F6MFnlQEWr4UyM+DcGPiw\\nIGz8HMZGgU3/wN7c0LY23NoC36+D5NXgkyXQMBmh1+FuNuj4FjYFu9LUhPmyyL9D6ctQtRE8eQgd\\n68Nv1WBrLrh6BirfhMXv4UBwADWEE4Vh5hSI1QkmR4VxS+Dlc4gfCDeboPEfsGEbtHoIG2MTsqZW\\nL4Jd7SH/NHhfDQ4vhFEZoElP2LaG0PJ/YQwk2wdNysC64OUUG2I1hdKDYdANWJMb1q6BvqXh0QfQ\\nfxw0Hwbtt0OjHlDyZ9g7AUq/gDHJIO4/hBesk62g6BewcQgMGQDTZoBc8OIsTPoO/l0FLR7Bm6nw\\neRV4Nh+ipYBlg//3NxY5CYcSQt1/4VhmqNsHZnWGXqMIKdh3qsL1LnDrT8IoybMssKQ+SAkLd8HW\\nYfAyMJgfhbQFYH4syDwW5hWCZOMIa7kDmMih4HxbC4knEDL2AujG28nwKDp8+wqSxoFYq6Bkd6i1\\nDk71g1in4PofsD0inG0LdeIRjiLBc1c2DdQoCON/g2V/Q+xX0KENxF0CObPBuBpQ7hF06QOjA/Ds\\nD5D5PgyJDQnjQ/6oUDg3dKoI/Z7AgnuEMN54gajRGYqMgdS5IfmPkC0STFtIaEsYPBM2zIfB38GV\\nzND3Fnz6DIpUh1nF4H0HeL4NnsSHZ10hQSV4WgKyNoSeF2FwXkjYBi7Mg4IBSmMF/B7kcFvC0gyQ\\n7gRUqEu41V7YBz6NDF3ewc7C8HsgKrWCrU1h9DWoHAAzI0GlYJipANkfQvPdEGESpA4gQV9CySbw\\nNjL88x8k7QOFDkCL6hAvFswaBn0LwevD8LI2/PQlNH5MmMcMSJBxnkCVgXCsB4ydAfPiwIQccHwp\\nzNgNUXvCpk0w4kd4FgturoJF5eHkO+i4ECINgXvDYNB0GHkFTgcS9h/wpgg0qwbDGsHQG9CvHVQ+\\nDz+kgvFroOAEeHYGOt0nrIl78S/c6gUL50DhZ5BuKlTOB/1uwoPAl9wGzvwGTWJAmjeEe9Y85eF1\\nL7iWCx4Vh1MroftKGPUfDJ0NkUsRLhrK3oalN2FAPVg9CnKnhM3tCeGoLc7DtJPQJDGc3QhL5sGp\\nGtC4EUS5B/W/IByo6uyCz4YQiR5xYGEBaFIbsi2FER/B9ptwKD/M7wrJK8NfnQkns5bloNlvhJLQ\\nzCrwMD4kewNDHkGVnFAyHWzZRRjhTtAU8neFjnlhfTd4mgz+Kg/1f4ET9WD8cbjeDU7FgKnVofxL\\nOFkFWqYirP88HQs2ZiV0afw4mLB7PPYDmDUQOgXU44aQI/AnBfUp6eDL/+9o25cMRiSGQbdhUSl4\\nOw1ObYcc30PrhtDsDny3C+pkh4gXCAP2sXLC8VyQ+iiMXQNRcsLd4rDoM5iTEioGrJpvCW/QK1NB\\npIWwazzUWgHXYkL63dCkOrxaATu/gdXdYM1kyHoMJtWCChPgTArCh+H0cfggKpxOBoUPwZUHcOUu\\nLKkJ7WtCpBpwKTPsPwFZXsHaiHAgGaxODGOeQJMqUCc4cD+BbybDP+1g1hWodAB29IGBh2DsP7Bo\\nPGTeCo8CAa4hVBgIF09DgdrwaAPED5g6x6BnbqhQDv7bB9sywuKAfD0fci2B69cJm+cfBa6ONdA1\\nGeEOWE6YsgjyByCPfXByJWFgOMMh2NeNcDcZoSCcWAtLLsNv/WHBUMieCGYvg3m14N4ieHsdqt+D\\nxw+h0ziY9TMkjwYvLsLLUtA8KtTeDXP6wYN0hJL0/lbwS0b4EvzcCba+hV1j4d8n8DQzFDoNx97C\\nT1sgQRrIOxsW9YYhc6DkAMI+gLYfw5nx8Os8qJUSYreE3BWg6Eu4uheGRySc0ZNehUKzYG8RGL4G\\nOqcnrKw5kwZqrYR/n8L7bHDtN7gwh3BDnD4AFqyAKjWhZGJY3AiidoVsAfphBjybBcXmQqSo0LU0\\nHOsJn12BzYEDtT5sHgeXEsGqotDoGNxtBh/nh+stoFIfqHALVuSCKvVg01VIshweNoWaEaB2NiiV\\nHCbthELPYdc2SDYNZnwGmVJD218h6ihCvvyonLCnKgxuCbGTQOpFsD0dFE0B+7+H1cFuYzEc/REi\\nDCQcorZ8DpWzQoMT0PU93Pka0iUm7KUd9TeUvAh5W0K5t1CvJfQ8CH1yQOYyhGPe0EEwfzSkygPt\\nF0Hm+LB7B0zPBhNPwi8VCAfdR4UhQSQoFwM6JIVxdSFvOrhaEF7VgVjDCNEwNZ/CuohQ+Tq8C8TT\\nXFD2HbSeBFU+hSux4cZa2B0H4k2C0ZPh7DK4UAYWZIHWWSF/Tki6BnoehZkP4YPrcLsWLE4KW2vD\\nmkOQYz0ciA//rIEEswilvUdrYEcOqPIadiQjTOPeGQcddxGSDn8eCUMvwJhgr58Lip+Gd9PgfnfY\\nlxwmpoBKnaHXB1C0GqRrBTM/hDWP4VyQgb0Luy7CfxFgfVkoWAxiTYGvTkHF1dD1JdytCHXjQJO/\\noOJCaJcDKryBvgdgbj9oXRrWPoIrhyBGCejZBnY3gv+ywOn6kP8wbI1PWClWMjaknwune0L3V/Du\\nJSwI4lbnYGxsiLSDkN04IANcGQtVohOCn8yJRRh+HpQO6l2BuwlhYhVI/i1UGwjbLsP8PnByOBxp\\nCkNGwt7OkPYs5KoB+V9DsY0wJcjUJCEM8BeYQVjsWvFDKDgPcp6BrIlhx5cwKhacawmNAv2+Gxy6\\nALHjQp78MKYIYS7yxwWQvwiUbAxT18CzTPBLPthwEqrOg/9GQMKm8GdzKBfc2edCtirw18+wqxB0\\njwUpEkHL4fCwPaQ5CTO6EuIuSyyDzCuh6j7CVvnFA+DfgJW1Ha4vhOjN4aPNEK0/HI5PKP1srws7\\nfoPWmeHKJhj2F6SoDxFuQLdG8DgmRD0LH/aFjqlg6E9QMjOUvQ+bU0PdoTBgNjT5Dg58DHmiQeHv\\noRAYcAfu9YFFW6B7VOgYF3pcgZEt4MMGhN3j72YSpjgnpIOzDWFlVEKxMlFF2N0dxiaCD27Dup/g\\n/WOYnIzQqdZ4OaFr0HiI8AAqNoVN9eHrFDAzHbQKfAPNIP0dKPYMWgbMqvGQpBc8DXYeF2DpC8iV\\nBGKnheOHoWE02B0IJd8SVu50LQa1ckLDF1C2KfR+BmUTQYGJ0KUu9G8A9f+G/ZXgURbCAqs/s0HK\\nv+BEKdiWBKIngwERoUc/iL4TDq6DiEehcFlCt1OcF3B8CuytAmcLwqI9UPgVrD8DOVpC4qcwIwX8\\nGhCzpkOdfPDXc1izm9C7MPskTD0FK9vAylLwZzmoHOS/1kCl1DCvI4wJiM974atAZk0P+Y7C/L2w\\n+HcYWwqWLIKWTeB6VUh8AF7HgWgrIdlHULYbHCwHg+fDZ82gyC9Q5TlMeg6NKsDlxjAwJmFJS8ZX\\n8L4fXOlLWIK7MgdEHAsZj8K7vZCgHOTqAfHzQsXIcPEbyHEZ6g+GHAfg00iEvrSVAwgNFYV/hKUH\\nIdqf8KwS/PAlVN0I/7WF5wng8Gn4dxbEWAUNW8C+wJvVCJbHhhjrYHYZyFYYzuQgPIEf5YBXgb29\\nJJyqA80awcH6hKnqxYGFYC20PgQnukLN5//7nMcdglrV4IeJhMXe/QrB0fGw6CeIOBLGHYeqP0CU\\nAMjyOcT4D9J8BbsuEYr+P0+Dc+8h8mJYkgl2rIRWT6H+WEh3D7rWhHw/w8VpMHQnrNkKa2NBzA/h\\nZh9Y8hryDIcIn8PTbyF7EnhxCma0gzmDCLlKH3WHuOMIa47WB97QQD7rDI8mQpGUkK4FdE4OG2PC\\n7OOQsS/kSAnf/g2rosIPOWDLV1CmPKyOCSeXw/e7oU8kWPkhHC4MMwIFpgeUG0pYw5XuJ6geDW63\\nh3q3CBOIsxrA7u8gUSTI9xXcjwyDG0PzNpAgNexeB42fwKvdULsvYW9gjtiw6ABkSAXdksOPI2Ba\\nEvj+Boy8DFe+hAwxYG5vWLALBiyBuydgaBMoNhk+7gp7W0KrnXD6K8Kq77/rw+j9MCbAOFeCIyfh\\n65uwcAFhF+ey49BlJ7ToDCmrwpsJUKINFPwTNkeG1QvhSoBdnbMYzt+E4f9C+0/gg+rQODXUuwaJ\\nr0CO6LAiHjxPCqXyw9HesC8qlM4IPQ5A4uVQ/RdosgQm3ISkPxDuXQLV8/s3UD8K/JMYir+HuAvg\\n7F4YdAnqb4Q8xeDoEljzIWRoDcebQJQL8HwtXI8EFXrA7Y2EOYtgtu5zGho3gEHBqnMo1OsCUb+F\\nLZEg/VvCWsdApU6fl7D/POByte8FHdqBk9AjBwz8GG4dgx1vIVEe6Dgc5qaHxQshY2NI0wwSZ4fl\\nJQk72L/NDP+kg5uRId0ZaFkEkhWBtdOhRWFYuBhyFidMBq18BMuWQoVPoVQ1qJ8RTsaDgYFhfz2k\\n+hnWZoL2yaFlA2g1EfL0gApJIUoamPQxdCoD9Z/Cy7TwLLCxV4XRjWBgNzgd7IcOwfwykGcW1BoF\\ng7+BefugVgxodRri9IWK0wmzVBuCzNF6eH8TniWA19tg0D3onR5aZIFEUaHlj9BnJPRIDTErEhpp\\nB9eF1j9DrOLwug6kPQPxTkCSozCyKSHbOihZunQfcpwiDKW3TgrP/4TfO0ORxXDjH+jUEiZPhaRF\\nIX9LuNkCGt+DGPOhRHq4dgxS7oTC4+DJIahXFlr0hvHFYUIaKPYcEueGj9fAjAKw8A7M6g9Fz0PD\\nVbBjONR9Dnv/hpO/QocU0PQAJLsP/ToQ5knjr4XI9eDtHaifmnDLuLgSrOoAJ3fAmMIw/COIPhji\\nNoepKaDxGvi5FQyLCaUCiGg/KBIE1JtB3JyErYXnZ0Le5dC/I9yOAbGDEHUAgC0PIzvC2KuEEtXI\\n8hA/gJFehjalCDNKqcvAstxQqjOk2w/V/oUxn0PaF3ClDVw9Bfl7wYjsUCEv4avrQArIuwZeLIfm\\nkeBZOihfBLrlJtwmXrgPucpC2/fQL+BmbYGOG+BYELxIDG+Wwd+rYHVg5J8HXW/A5QGE3Ri1EkOG\\n0fBzByjWH3IPJ2ToL40E+w9C45MQ9SXESgtn08DDoZD/W0j4BXxxGYqWhDK9oXgVmPUPpA88uych\\n4XwoHoAngnDVVEIPa45c0GsdPN4FlXZC1JrQJhY0LgvvS8DvE+DJTzAqIhxMB3d+gtwToEph6JQN\\nDiWCfQFzfwK8+hlWX4VvxsFfOSDfBzAgL0T6inBP9kVvuPcWBiyDXUXh/F3I+QOs/hJ2B4aZ3vDs\\nBiztClOHwOjUkLAQDLoC4/LA1unw+CW8XgxDAzfeEKhxD+b/AtUDr+E30GcBjNsEewOAdn+Y2BV2\\nZoDz2SFpbDhxHIZuhnPB7v8BnKsK9QbDH3MgRQpo/QpObYCIiwjbPEv2gGfRoUML2D8cDkaBxgfg\\nSmfocJGwA3dPPUibDNo/ghvfQ9ePYdoyiNOV8GJ6Kx6sjQ8P08LRp/D5dbgYJBBfQrvE8HVvWJIA\\nTtSCC8eg7UQoPxYKvoXDPxPu547kgBeB8vAIvi8D5X+DFOug7jGolx+G3IcLE4hAlhqQ8zikvkI4\\nKV6IDD8HZOELcKMi4ZwxISuhyDJ9KDxcAXMTwpViMOsSVF4I97+EAR9A3mKEMMm3vxKuW3ecg+z9\\nIdl+iBPYzIvBlX0QoyIU2g+39kHDu7BgIaHDJn0vyDkZVnSCUZMg5ijYPwmS/gTnPoJR46BFsIEY\\nB2dvwRlQJgiK94UoT+DfMXB0MOzYASt+g9Efw1czoVBqKDwHHqWAjgtg0mV4cAG6RYQqEWBBIIEN\\nhNzL4YeMUD8C3MoO5+pApHmQYAKcaAgxS8K0GnA6eO21hStdoMf3kOdP2JYVSq2CbDkgZ3DVywcV\\n4sGm8nA/4GVHhOUXoFxLiFkYDnYnZMT3ygXLCsOwWfBkN8Q4A9UXQPUM8HkT+CMJvP8bXt+GZolh\\nVV5YngzeHIT5p2F5XbgCDs6DasuhYpAwGgh9j8Gok3BlPRRMDSVmQofUhHJq1WswoQR0zARn98Hd\\nroQXguh54OYjmAMa5oFZTSDOASi5B0oshX1PYdAIuBAQuaZBi2pwfh08zQsNhsLoabAnwOglgv9q\\nwo0fIFYQjEgEb5vCnmxQfh8MzAl9N0GDGfBgGkxMRJiKnQneLYX5F6Dhe7h2G1KkhwMnoERZ2L0c\\ndj+FNO0gzTToVwsK9IZ/Z0CLIB+UGJblhZG1YVI9aPEbTG0CawbD+PoQ/cn/fmm/B9LPDqi2Ef7M\\nCQkCBGhAvk4EE3+D6Ntgc3qYWxyKZIIHAR5wFvyeHrZ+DQl2QZYNcGor5P4HbvSH72JC4TrQoiN8\\nfR9anyXcnD29BUmjwonSsPBfiJ0MykWEt1ngeWVo8QImFSWsJzpYAJaegRix4IencLQkpJ0JY45A\\n/kLwfDtMWQ75XsPhnBDpIFTpDPU7wbn2kPwl7D0INzNBxu3QrBxEOQZzMkOePyBVCdj8FG7vhWXL\\noUV9uNwNJgfPdSBz/wQDrsHyn6DpHbh6H5b8DPc2wMm5cGs2fDsZaq+H2/XgyF6Imx2W5oJ0CyDa\\ncXj9PUyqCfW/I/SSbswHk+5Dudaweg7UXwAJr8LgII3YAF7dhezX4cw5qNATEp2FWcHuIQN0DJAQ\\n/0LJ6HCtHdQ9AjmmQpZMkOYlPE0KyVPAJ3UgyxOIEgsyNIOKl6FPa8geBXLcgbaLIO6/8N11KBAR\\neqWFhM3/962l7gvLg4tjEkiYElb0g/n54MlH8PU30HgeXJwEU/JDhyQQLzFMjAmx3sONptC5FjT/\\nAo5EJeQAxPsMKleFFjsh/SVIlxbmfkGYCe2VFa7+BW8+hPNvIfdZeP4OYmyCaD9Crenw01mIcxRe\\nLIKv90Gbj2FfP5jbFPYVhPZj4e8GkHYhHDkGM6rB8MgwqBfszgtt+kHhgCpbDrInhU4loF/QMFEO\\nzmyCVYHr+j0cn0hoIPEAqs6EI8/g7hTYfg1md4fpZSFGbmjyEVQLUE1NoeA4SPULIWj90eeQeSmR\\nWdkYnvwG7ybCveSQ8itI3Aqe5CSkr54fRljKMeQNzN8Dfy+Gnueh3VGIOA3+LgM7qsHG4lByGCxs\\nAbeXw4OX8N9/0KMprBsNTe7BNwug5nWYURwulyKcUxO2haibYMVpaPsKNgaaa3T4Lyp81R98CtMX\\nwviUkO8HmDwYbpeFHZ9C7vhQYCN8eRz6t4b/ZsG+nwlLbP4rRAjBa3UDvhkOI2bDyCA/dRc++Bjm\\nB36mTrB5CFzdAy8mw38voWl3eL8V/uwG1SJA3oGEjWkZssK7EpA2LxyNBnmSwL/B8rwFPDkK5RLB\\ns+3wdxfomonQJP4sP2Hj+uoaMHYQJCxC6LUKLlI58xK2ELZOA/vHwLA48PtDaHWV0IpYMBdsngDZ\\nShJehTPsJ+zO+7sRbNsAOYrA0rWwdCbEbAtP2kLkb6FjEWgUZPT+v31JldaEweBWDWDTp9DzGGT/\\nAEr/CkduQ9sOkO41Ya5qTj74oiMkugK3+8Hq2pAmClS5D2+ywbZnkOE9pJwCcyJArJ2QMDJMawKl\\nx8An3xBuuSp1gyL5YecuaDUJUryFN5th8WJYNwfyX4a2MaHfUyhWEv4cDXdKwneNYfGXhIWyC9bD\\nitvQZid8nxtORYBG/4JU8Gw5ISV5UxxI9hBG5YJK/0CWuIQF6oeSwZevIFsT+PA/2NYKcqSC+oEZ\\nfDnEqQB7Ajn7B4ifHcqkhpLLIOJS+OoGdCkO10bBiMZwcCKcKwvlnsHBiPBBTziQAf6sCYc7QO7N\\n8NVLeLkbPnoIqdIThrTHPoU1WSB6GniaGGIVhVHJoHUi6PIYLgUoxRLQrCCcbwvlkkOkCfDhv3Bx\\nE3w5jjD+nWUaVFsDXYbBtafQbwLkHwMRvoMmFaDPp/DXOPgqGtT5G+YehnaN4ecpEDk75IsJNYJs\\nVE2oUhIaVyHEikZODKNrwqUr8OwhtJkJxx7A3bJwMx88GARlhkC9jVCmJHx+AqIWhRgZIVNCmBUH\\nro2Acf0hW344XxGyfAiFukPFszCvNKyNB2n3w5Z6UL4F1BwIaftA/uKET1wgne9MA+8XQtUzkK4o\\nLGwKV6rCt5/B/Ytwrw1kag+ZAs/ofvgyMtSrB7NqEAZQHq2EXxPBtSaQcAMUOwq7foPHz6BG4JCL\\nC1tXw9VLEKMpbJgM/apBtN9g1lWIORei9YVLKwiRQAeOw9dt4VpCuHQVsiQk5OQ1uABXLkOdkzDy\\nMERMAcUiQ9uHEK8RJIpJKMS/+h6KzoRPpxN2kyy9C11/JOzP+Cow/3SAG5egwwh41AtunoXzpeC3\\nJdAyA3xzHpL1hsO9CbGlaXfCgOoQoSTMPgezgj8zK+Gpfi7YMl6ExcuhdVvY1xmmFiZ8LxdNCu/3\\nQf4hhMVHdc/A3uFQNS6s2woF7kC/6NArCwxfDPOyQORL8P1I+HYZVNsAsXvA7miQeyz8dR0WzoIu\\nPSDdH5AxHpzLTcTQCxLwspsE2ah+0GIgbK0B/zSBep3gh7owOQr0mwhX88Pc8/BJFMgdsKdfwPht\\nhImYlE9gxQj4qx48C+ah65CoGmToAt0GEr7OG8SBrzLDLynhs7uw+mM4VhZyfQoFU8HHR2HVGch8\\nAw5WIWyj6/wGdqaHl4sgbVRofxl6ToIbqaBcSUh/ChLmgDPbIE5ATNkH1YrC5AhwdB8c/h3SnIbD\\nC2DnQFi4FEpFhzzX4MJLiFYP4qeDNcMhwztYOwxa7YdEUeD6UihdGyJMh5wD4JfV8F99WNIZihWA\\nF8ug7FW4mZiQof9nBogdBZLnhR4JIFcFSFkf2mWB9xmgwAaI0Y+wYCHzQ5gUD0yDx93gfiB47YMR\\nAVL1OlwoBoOPQcbvoFwO6LwSJuaAd+/h+2rQNTp8fR6mbiV8vKsGvKvvIcF7eFEAUreFu0ug1nmo\\n+THsKQM1osGGiLBgD0TZCqM/gf0l4PV/sPwotPsXuiSHbV9C1kOQcCb06gkPUkGtjNC+FkR/CZHj\\nQbmEkK0cNK8DZ2/CrBmQJJiQuhK+0pKXhRLZIfl0KJkDZr+EHL8Rpp8KB9JVNlj5Avbvhe394egE\\n2DsAJn0DXwVy5Bt4dhvGTIbM42DOKcg4grAQI3AHligIK2fAlGPQITk0aQ9380HP1PBBSaiWm9DB\\n9r4gRMkDGsL9qDBhFmFk/aPPYdseWBuwlKbClL/gTDv4JzDABmJQZqhQBKrNg8XzIO1hSFcAFi+F\\ndKmg/WhYuQmi1CT0EdbcS+iPefcI4n8G6Q4SWiMCg2qzE7D1b9gyB9ZPgOrnoU5DwuLwv0dAh+7Q\\n6zj8+isMCaT/IVD5B0KO1K8fwK/b4dE4SFAE7u6HyfPg47WQuhDkawSx2kD6VpCzNmSsA41yQrzM\\nkK4rJCsK1V4QEuDy3YLtgyB+f/g2gNP2gebXCD1YUyNAy1nw7ST4Iti1XyTstzgxEjoFBu3ocCUY\\nRzcRNlukewvJbkKSQpBpOsSPS1iWvGYf7B0PM7PA7xkg4gOYGANmXIFOX8M3e6BLX6j9HArHhmvJ\\nCaugi6eHCq8gaj7oU56wOGVcO5jZAuYWhDLfwF8RIOI8CEBsnQIJbDYMHAxRA6pfE1i4Eg5UhKlV\\noMz3MKAY3MkNMZYSIk/7n4MVk6BnctiVDUb9CPG+gz/GQpbJ0DcqIRz70AaofAQylocUwwiVhNpn\\nYFZS2FwVZsWHSSmhWGm4ux0qZoYYOeBwbRj+BmrMgEhBI0UzOBeBMEbW4zR82AdWJICH9eGrJ9Dt\\nBlSMT1hePrArDJgGoxbBnQhweBGcHwfNskLL2ZA+PrTbCoeKQcd+MBmUOAmlO0H7whA7NWRZDMPr\\nEHYzHH8Ld/JCheJw/QAUPQLTg5DBM4hcGvKtJxwtAvG36QyYdRhydIT6LyB7dviwGZR8CU5Ayg/h\\nu16EIN/l38DS3NA4IcyoSUTOnIFLA2DDQch5A74qCnWzQrrV8FFw9SkClc5D8/3QMlBwt0H5xvA6\\nI+QLpvxX8HF8QpbP006ElQ7Xo8HVe/BiDqQOiERfwJUNcCIbxLoIFfPBnGCZ3B6+zAbpV0OFT2Be\\noKm3hlXNoeYVaBw4JJZApc9gSBfCdM/+sTB5B8z9D6Z+AbcGwNxHED0h/LkTPu8BJ3rBvg3Q5Cic\\n2ASRC8G3n8InN6HrP1DrMnz+B9QYCo+WwvAKsKIMDAkiwTXhz0GEmaCglnhbZzjRHJZ3g9QDYdRg\\nSLQRVn1GWK+7vxQkCKypaeFSTJjbB2r8Bgk+hUSn4asg6n8NHsaBuqVgVE3IURvOjYQyaaB9NXhY\\nBL4oCiWmwKfBrf8uLJ8GpW9CxfoQNxUh5qDPb7A3YLQ8gjRdoFcqmDkdvnsLH0eAVHOgwwdwtQHE\\nXAdvnsDW59D4E/jsJ8h5GkqcIqRdHyvzv2/kk8+g2xPIvxLSVIM/HsPim/Dxenj4CGr+AkXKwLHA\\n+XcZHgfXwbxQLTHcDx7I47CkJByLBtUawRfz4c5jiLsZEqWDnZ/D3kGwvygUqwjTG8KdP2FmDhh0\\nEd6/J/SuvR4BA97AwVpQfSgMegY7KsPTX6BXQ6i6G0pEgp6fwaQi8DI1ZAoOwc1QpTSMCCjGTyB2\\nYBtfBz3Lw76DsL4DvI8KiQNRLC7oCaNGQdGgrCkqdChBCIaN8xPUWQnNVsGmFfBlMXjWkTDveXAf\\n7B4JF2/B4ZHQuBI0jwUflIDyyaDWRfjtb8jYEn6KB+eXQfzekCwV9GgHsWPB160hSn/o+ALa94To\\nBaB2fFj8GjZ0ghNjYMcEGLUAdkeGt+chylSIng12jYOX6SFzbii8G7p1gaMZYew5GFIbqoPu+eFR\\nEejeGZ6egbbfwO9bYNTPELEE/DGXsDp93XdweDec+gpi9oSvr0DPjFCoFAxtBi0nwqWOhB1zL99D\\niSFQ5h8oC1omh3174dZ+SJIQ8uSFgQngTGmocQH6BxuFd7A4wH7+C48/hPlPoPw/8C7w23WCVSVg\\ndDtCuTwoep8/HbI1h2jlYfQGmHQcCr6CfbNgS1L830B4NCfM+gDi1IGZn0HKO4SooF9mQ4sxhET+\\nfKVgzBYo8BGcCgbIc5CrKVy9Da+zQo3ncHYWbGxNuP3KchFS3IPCESHSOIg2E2o8gncFIEJ7OHAR\\ntjyFbi/h8kZ4u57wF34rCySvBF2fw9v98OksGBIfSk+BzaPgxlEotBXmLSNsFM2QAK7Eg/3tCHEP\\nY6fC18vgZja4NZNwx994JrwpD2cvwdWG8NEBOBQfftsBNWvA5d8h6XEoUB5+ygz3h8KH56Hqdlgf\\nHcYEO/vA3v4ZHL4G5XfDkWlQ7BZ88xH8kQi6LYKuxeHgb1CkNjSJCDEKw+odUOo4pJ8EWx/B2g5w\\nvRDETQ+b8kHCI5AkLgQu9i+uwrv2UL8bHJsB74sTgXhFoTSIfPR/X1jrqNC7BTQKUP39YPxownbx\\nMm+gaU94GHihIkOb5VAjBvRJCTfPwdS/4MNh0OADSPEU2r2DKOug/FtYVxYy/g1ZR0Kq+HD3B+jx\\nGKa1gndfwPvLMP0x/N0B8kWA0Vlg7XLIeQXmHoOo0+Hzm9D+RxgRHW5GgZcZoOxAuFYBfvoF+r6G\\nH9bD8Ssw5C/4KhAFHkCxalBgDhSaCvG7QIxycLM9JLoKOZZAlhXQ7g28egabMkLBy7DyZxj4J2zd\\nBd9fgNmjof5QKDwIjk4lFCM6zCOszyxeHDbfh6MZYEhSSNmFkEZTogNUqweXpkOWH6DzEbh9mJCU\\nluBLeBsBuhaFKQ0h7xdQfxks6gfNosDOPwhnvnX9oP8NyHoeVu6FVdPg6YewZTysiAvPGkGax5C4\\nENzbB9luQuIgBv8HpK0HuzbAiunw1T3I+zvEqgZVgs+nECyeCh8mITwsgsB2z2swdB9szwlxpsGh\\nfhCnLDxdAh9fh4xBbm4s7Ayel57QeySs6Ah/3IRjdSHlF/BmMmx6SZhCXRrI6GlhVjI42xp+DbYj\\nsyBOeZhxG150gxjDINFz6P0LnN4Bz7JCs36wJBW0igoNmsCKZXAyI5QKvI/BbuY5PCkC8eJC9AZw\\nINg3fAfdA0NoC7iSEeJOhxkxCXlRCZLAxGJQ8QRkzgwlxkPeVVDxLhzsT5hXPb0QBmaHxAmh2WO4\\nHBPGVYIU+eHMLpgxAkq8gK7b4HwVQtvs+IuQpBzEDnhUf8OnEaBDF1j0H5SaA6MHExLjatSCqOlh\\n9BVIExOyj4elMWD8bsICmbeb4dOk0HoZ5IkAr4tAxtmEKapb6yFRL0g1EAbMgG0poXoLaPMD3LgH\\nU+JAyuQw7m/4bh6M/ALydyfcyryfCcMvQfS1sC0bfHMNSt+GWftg5BYYnwMOrYb8E2HpPKh3EUq1\\nh3RHoXtreNMJCr6E02uhagJo+TNk2QOtPoKPP4eBayBmazhWEn5tA/2bwKb8ULwNLJwNPwTI5c7w\\nVXrY2RyOjYTjqwg7J1ang0kBx38EnG0MS9bAu9fQ8B6kvw9rasLw1VApGyw6Sug2Xp0PFj6C5Bsg\\nZST44wr8FIz3X8NHG+HucBhwlLAfMMFP0KQNnJoKUcfDgF/gTVP4vinkOAJjYsO2MzCgK1wJQL6l\\n4d4FeJsbavWDG+8haTZ4OBn+OEIYSFr3ADrHg+ijoO5KQtE8YmS4sRK+rghnIsLI3JD+IfRoCPE+\\ngqdboX4QTZsPdb+Enu/h3Ci49hCaTYcyGwlzxNcjwLPv4cOm0Ksq7HgHRxdA3uBsCd5KAWMyE7Rb\\nCG0+gLL/wLmE8NdDqHgGtgdvmYHw8iX8VJkQoFB9Fbz5HpoNgiMvId1omLoRGlSFKcXhTD9CRmar\\nCdArHvx1GV63hX8GQ4o9cGPT//5VBwI0UhGIVIKwwXPyPVh7F6Z/AClbgTdBVq4/9IkAP96BGQ/h\\nwwBHFiDRdhJKb2c+gk6JYeUpQuTj3JbwUW14Nx/Kd4C9seBFEL+/AdW7QfnqsLMcZI0MKX6G3BkJ\\ngQgpShNWWsYYAM8fEYZRVyWFA7/B6axwtimkaw0Fk0KBQ/AsDyHjJ1irlt0Kn22Bv7+BH6sQFqzu\\nLEtozJxaBPpPhW274HFfSPgrVA04WClg0Ea4/wRaJYTW2+HOCViVBvq3hE1d4PZO+OspvJoDxS/D\\nuI/gVmV4/BxivicsxdzzBxxoA88LQty30HcCvK8IKwMgXlX4rTlcTgpHv4akuQlTY2uTQNI0MH0Z\\nTDkPpdPAqBrwe2P4IyIh+DH2JjjUBmL1h2aX4aeRsHA7nD0NtZpAl2vQIAf8sQHy5oSmN+BFLRhe\\nD7pugvTdodxy+L0yvJ8C7T+Ft53gnymw8xnsmUFo+ZxzHZK0glI54EACyFoatuyDscVgcQKIOB86\\n14Mn1yBOW2gxFL46A0n6waS7MCcmbJ0FRzpAu12E7ZmrNxPiSOL+CF8NgiuBxDACHk6DElvh6jj4\\nbzCU70TIUMl1AbKdghEdYMljKDsdWl2AJddg/x3CIojPqsDjIjDoCOwoTYj7i50SSh8mLMbZ/ws0\\n2wS9i0PfbwhLV2YdgtmvYf0o+Lg8FC4B94fBzV0wKBFEeQjzv4fbR6BN4F+cDcdzw9Qb8EELWDQa\\njm6Dgbvgn0sw8xSUqwTXRkOHhzAgKhQKdmA1IUIV6BcRXkSB0tUIpahucaFdN8Id1fvTkPMarKkI\\nKTbDzbXw31DoVRrSbICbfWHgbHg8CqYngjEFIF9ZSFYdFgf+p8uQaR6ULUwIcpx4H06OgCStYfcj\\nmPIJXOlJuAMLNoKHGsKNbfA6HvRPDav3w/248OVnsLI13M0EdQMOUzo49h1M/ApuR4dtNWDkEZiU\\nB7JGh3ddoVoOSHkCbgZ8o4CeVQBGpYE5F+HjhlA0AjyNCo3aQ8Q3ML0fLPgVRteBwX9C/J+g1U+w\\n52+IkBXGv4VWb+BQBYh2BdpHhj294MQcuBioGYGRYyYhuSp1Rch2GOZGgmEp4PfxsHMFZIsNMy5A\\nuswwqiNMTws7GkHj6fC+EWSJBaPjQporUGoptMoGWdvD173g95jQrDRs/hBGDIO/dsPEtbBhMSG/\\nfmgNGLIOTo+HfpvhRGSYM/D/MXVXcVTUb9v2v3RLh3R3t7SAoISUNII0SKeUgEpLd5fSKd3dDRIS\\ngoh0SCkl8G7MPc//3WGDDzusNWvmN9d1nMcJlwMUJBBYtIIvb0P0ktA/P9yZB1emQclKMCwBJF0O\\nmwvC5C+gSyPodQgKDIBsveDxVli2A2bGhTTBfT4xvJ8FmRbBz8fg9C2Ifxk+LAQbysLrMlBtKuHK\\n7O4oaDcb/mgAB7PCykegKCEnnaQMJAmevD2hQFzo2hUqXYcsMyHtScjTCHq2gJqboGR9GINwqHGv\\nMMxKAE32wqS38KAItLkGmf6Gv2/B99UIl4PJukPZJ1BwL8yqAXteQrXnMGkC1K0H8w4SqmQCpOr7\\n7XClDbi5G37OD5lqwJTi8DAbIQa75wY02w+VdsH6E3CuCwxdC73rQ70N0LEI/9eu6NxqiHEMSjaC\\nEdUh1Tx4+AcMnAEn1sCImtDgHDxtB2W/hGxlYExryBgBmg2Bdavgh7qw+ya8egTnJkG3AGvNBIdL\\nwm/N4e5kmPQFrJxEKGHL9xh23Yc7wVvUUHifD07MhxnRoe1RmPoOEveGDB8QahTyT4ManeDPj6HD\\nTGicBwr9C6kewZ6vod4iyFAaLpeBswVhRh34eA4MvQv1C8GC+PAmCfR7+r8Lukl/yBSoONvB1/ng\\nWnoYuI/QKp6qP/RfBe3HQbbAWVUdLgyGBXlh1hHCepPOF+G/P+DXjDBsNeRsBetGwfsFMKsFVMgC\\nzT6HiVmg0FaY/hzSxoYPI0OkUlAquKk9hPdLYNWvkKsqfLsLqhyD5JsJIcT2x2FRQ/g4PRRoAX9W\\ng1nTCCmrgPI5+jvs6gGl28Onm6HhP9B2CTz7EDqvgC3pofSf0CoD9D8Fa5/A32vgZBDNnQEHLsCk\\nNPBJUuj2O3RMDDlzQfbKsGkqjH8Kjd4SLh+Pfwaf1odtTyHvDKgXBy5dhAkdYX0uWNUNvp8NC9fC\\nkEww6Bn8Ehe+fwhHK8KWGrDiAjTLA/tjwp0ScG8snKgEmXfByKqQKyHUqwbxukC7OZB3P0xPBj9M\\nhPF5oVhpyFoerga+nHlwLAqhIObMN1A3ISSYDHMPw/SP4fFZaDoFFv0FrY4Q6oXbzoVTxeDFWyi6\\nDIqXIyxoz9wM+taGMnFh/jmI1B1WjCS88s+nhsWTYdRcyNwH5raFgdkIq3Nv/EIIRxsKCz6Eg1cI\\n16kjxsKLBlBgD2xoA8+iwO7dMOMFYSVXq6PwcdAqcRpaBoj0eWj0HG4/gxJ3ocU0eHQeOo6EZE+h\\nw08Q5RJ8cRc+fE04mXgTkHZdoPiPkL4tnLwCm7ZDxcaQIqDKAhFodHgbHVq+gCjjIeJ6yJYWxr4m\\nXAumDl7/ikP3M5DpCvxdAQYNhjwToHpPuLUbngSzMTDnJfz4KYx9A9+0gOo5YORCKB9krmtA+eB4\\ntwJO/w3HC0Cb3+FRbRi9EP5dDruDF5UbkG4SPMoOo7LC3kzwoiiU2Aj7R0HSYoROvsAz/nsL+O01\\npLoBSY4SUkfdvodZF6Hpayj7CLIGS9vK0P4zwmhF790QcxkkDyzqF+FUR6gZpNdfwtwKhOVIQdnU\\nzlrQ+x6sSg1HisHFcjAwmLisJCzYud4VZo6HEl9AxMrw5iHMagzpguljWkjXCoaXhi5tIXZ2iN4K\\nHseGeD2gTnx4eAOG/AFZ18D6bJDrCRxsBPsGwtAXMCEtXO4Eg1pAomDh/hkMvgwdN0PeBjC1K8wJ\\ndNx14JOPYVc3aDAOTseEVP9CpcVQtD/MPEdIs9WIBx/1hPSvoOoTuFoRfngG0c/B5PNwYSYsHwj/\\nlIP3AZOXDHJGhJfFoN8DInH8DpyfBzu7QeWmcH4XjDsDL2bChVswOTYkrwLFR8JPIyH/FohxA97k\\nhsw1YNgJyDsePr8HdwJVZhnY3gtaz4ZiP8EHJWBJEzh7hLA25+ZR+CMO/FAdNkSFwVFhWh94HPgt\\nFkODdbDgYzgxHcYmIrwRdHoKS4/BjiBTcxLudIIuyeF8JDj4LawKuJDHsLQBbMkI3y6CNp0IszbT\\nZkCk/x+uHq0bJIgK6fbC3ngw/TaUfw+1voJ9SeCj2bCmD/9XJvZ/NpRBi6HdYjj6HyTYBvkWw4J1\\ncKYpZF0O3xSAI5/A3s7wwxWImY/Qtp/yG/jyHuFhd8p/0CwtFMlMGKc/EAe+jQOv/4MyAQt1FZq0\\nhpsF4OxwGJwTpv4D3zyEBv0hSxX46h2s/AcuLoBzryF/bCh/Fw5GgcezYPhwyNgPYsSELYFb5Rhs\\njwLjusKeXFCoDbwLKLSvoE0XqBNYZD6HzUUgQhmIPwr+bQ0zCkDzn+HxG0iyCyY8hUuzIXYawqTh\\nT0GS5TfoWR8mXINqZ+HaHahbCc6+gXhPYEIgaK0CMR9CrY6wPZgNzIdHJaFmXujxHob+CmuCWpUl\\nMOcC/Pwj5KkKF57BuAaQqDKcXQcN/oShRSHWXUj1FD7eA40awdnYML0ivKwLax7B60Xw1S7I8Bw+\\nTwmDBsG857BkIDzNSMjE3JoEIzLA8pYwMgcMeQpb8kPJ6NAvI0waD9lzwJH0UOcc/NgT9pWErDWh\\n53j4sxR8eAH6poevosO9XZBrMvxyHm5ehCpHoUwJiHgYmu6DjwPD9Q+QrSJEDEQtqyHaYygSMIjj\\n4NhlQnFx0HhY+kO4vwP+nkrIzZxqR5jf3HEXtgYB/mVwpxKkugbbE8OVYpA1FbzNAz/0hROZIdtD\\nWNQMGg+BX69A3ciwJtATPIHiLWFbTvhuKLQsAQ0Cv3l82PQJYTnY89GQeiZhQCHPMkhSHsrdgu1/\\nQslfCSmftMHkYABUag+ljsHslZCzM7yJCSkuwMD7sKs0pG4Db9rB0t2wPjJ8ch7SrPjfn/90hFf3\\n4fFXsLYkHL4Hr5ZAuXbQrSBsjQ+/boUSZ6BhaUgfH6YcgNUV4L9EMLMB7OoC64MFU/CM2Aory0Hf\\n43CuLsy7A3cWw+4K8HYP3M4FW7fAhkhwuAZsjQifBwGgtpC/KSQ/A0vzQ+5K0GU6PJkJX34Na24S\\npvgDUUigGXr2N6x6C7duwaEBkOANVJ4Gz0bC7TLQuyWsLwtVAifiGiiUEaKPho3xoMxsaDcepsaA\\nb/LDmADniAR5x0HLLJDiFSGj3CkaXFgOgzvC/uNQcBBUWgH9+8Ln/aHDfTj8B0xtDS0jw8Wo0CAj\\nxN8FEW5AshIw6y4cDY6hieFOIfggH+Ex97dSULEX9HgObXvCw4dwfSlsSwXfNoc5/WDiVGj7BJ40\\ngFURIfe/hFPw3/PCB8HrzQHI8wMMWQG1v4VDQdDkYxCnBQx9DrnrE2Y9aq+Ee10IB7mBUyTbF7Bq\\nHNSNBy0Kw45ahJvsl/3gxUTCrfPnceB8OSjyEKqlgIqtoWiQ2osDnaoRTp4WdIG8CyBxcPyKAQ12\\nEeYIJuSDXtkh4wzCxqXtmSFrFKjzERTfDevA9AiwrR6UygP1a0KZnhA3NxwtAB2LwZBkMDCAuzvA\\ntsswIPBwbICTf8CC13DxJFzLDdU+goUTodprWFELBtyHam3g+ULYWgPOJIRIreDfovDbIUh7G6qu\\ngRi5YcZpeP8YfmsHe2MRZj3yLocBVWF9I3ibGYbvhbqr4It/ofYDSHcQ4vwG1T6EYn0gRn34ahyc\\nmQvrv4UV5eHEAtheDfp2hgu7YNUraNUVys2B52/hr4XQNAt8MxSGlYXEgVnqR/jtL0jVjbC/79h8\\naJ8NlnUEo+DZN3A/ErSdAQXbQa0Ane4OH3eDq/Pg6gWINISQlhvVAc5fhL+DH3lG6NsDIr6C7COg\\nbEyoEBuWXISoO2F0I0hQGgo8geSLYMck+LYMjN4Ji97C7lvQ6gS87QMZj0CFg/BLK7h5HL5aARNj\\n/u8bLxkffl4Mv/8IN/6FuJNgwHoY8wxqPIV/48PYVrC3zf++6yalCBmLGZ9A+pSwbBm0zgmZs8Bv\\n56FSXhjQCpq1gW+TwcK50KQqlP8SsqaFxqsJ8dIgDxtYowrXhCQ/QMXT0DkbrPn/3cKC7Gr025D6\\nG+jRForMg6+rQ+v5UL4/RFwNNV9AyovQewI8vgD/noP4EaHsUTgyh5D2yNYO1hWC/Ikgd0S4FfyP\\ngixVACyvgXE14JuSsKAEdPgD1o2D3v2hXCo4+hxavIF/ZsHsu3A5GRzsBs/HQs20MKsR/J0U+gbp\\nrV2E3RhJEsL9WnBpIjw6DB+WIcztRtgOn86CjnFhSaAyqUZYqf6iGYyuBodOQfyHMGMgvCsHu3rD\\n6HtwOz2UKg7JR8K1dnC5MNReDK1HQ44NkGUx3P4Lhl2FNhegclpYVRK+SQLZisCTqVCqNZz7GLbe\\nhusBMLACdgeCm3mwqQ5E3wCHU0Pbm/DbDcISsE8PQ43sMCyYFU2E0VMJ+aGVs6FoVCgbDbpuht+i\\nwSfB0SQv3G4G8Y7ClWDDE/BJyyH/n/BXfBi1G3Z3hSfZYHECyNQJ5sSFUlvh8wnwJiK8OwQ7U8LR\\n9JDgAIypCHUSw/1FMHc+FE4FuWLCm9JQeR38F5gpkxBKQ9o/hfqpINYjyLEf8syANx/C7oARHA0J\\nj8DOg9D9NfzZhTBCEdzZflhHuO8KGNaqW+DfzdCrGHw0CgrPg06FIecwMJYQLZgzFH5YCe1yQ7NR\\n0C8h5HsG1cfD2Tjwfj+sKw6VosDU3RBxHcx9DIWHwpdFIf1EyJgBoueEHSkJy/o+DyI1CWDtAmhe\\nk1AddXY2jHsGrfrDsalQ+COYFihMV8DHsWDQRpgasIPlYG1yGDSXiDTNDGWCdMlu6JsB3kWCdUfh\\n+mBYEojjgh3zHehUAfYE6N96mFMcGqaCQoF3ailEawBlv4d5I6DmEhj5DZwsD9cCq1Pg/I0Olb6G\\nbD/CtoLQPD+US0NYLNDuNtx+DJsKwRdxIPdMmNCa8JZ6dhrMGgoT58C2DXDkHhQL5Gx3YGc1aJgJ\\n+tci7NfLuJLwURcnNhxcRwgpH0sL8Q7A2mzQrDRkrgyrqsGSFJD+AkRdCtc/gYbjIWptmN8RStWH\\nq60h/0b4tDYcawLju0GGfISdaB9WhT+GwbIg9h/cLMbAkNywdj7k+QBy5IYv60GEfYQP+LS94Xqg\\nLvyKsAF+0PcwqiHkSAE/xoaIc+BhBbj9EpKngRf74PY7uHITFkeA+S/gaRLI0B0iP4CvOxCakU+0\\ngravYd9oQv/QpeCoGiTFakORRjA9BpTPAmcWw5TAoHOU8Ji76zuI+AIi5Pjf38RMAw9GwSffQK5q\\nkDU5dKkLYsPVdPBNKijcDpZUgs/ewrv4sCxwxTWDm9fh3Q143ghKj4CzKyFWchh+GmLch8Hd4WJs\\nmF8LWmaAgZdg8RFIswoWfADPq8DMB7BmOqzoDgN/gY8/gLe/Evr0/womKMfg4Ab4ZATEbQIfBqDr\\nYsKH0KhHcKwXnEkLsZZBtg6Qph5MyA/JXsPXoM0jmHoTIj+FPe9hc04YuQle5YGMlyDpRFjSAtrs\\nhEj/QZ3nsGYnNI4LgxdCwhtwKz/MTQqHe8PY23B8KNTIAVPGw9YLMPkzWFEQvjhIqAIutwYG1IV/\\nDkKv6oSlLsE7+v3M8Cgu/BWDUDzYejFsOA9PHsLw9ZDrJfQ+BH8Ug2iTCeWEY2tDvbrQ5gzMTg5Z\\nHkHic/BPAehxHPoNI4wWldwPy1tB/Rkw9C2MuABbbsP5PdDpDRToAeuvwcJasP424TK3SXyIWREm\\n1IchbeHr4dC6OWxvAvPOw4PiMCkelHgFRwvDsO4wZjzEOgpvI0GLZFApNiRITqhaiB0FnmyCSdMg\\naUMolBc63YOMwUtLwG4egiJlYd4YOL8T1gX+rbmwow7caEZId3V8BHFHwb62MGEtFH0MN6YTZtli\\nt4OFZeDWfzD4Etx5ATuKwNRxUPFbeNMe8u+FTRtgfnyoeQrmvYfbBWBtTMKHd8Y50D4jLMoLE3+H\\n+NPht2dwdT9ce0PYgxJ8p4FaaEMtwuhD5ANQPj30Xg93NsKc+pDxBhROQFj4kyARZMgPTfZDl61Q\\ndzQkyQnlOxBuIfJ3gGTLYNszqD8b2neExMHsdg+sbke4LVkVGO2fwYlssP4zmJwEBl6Dzz6AxTXg\\n1WxIvxKyBffDutDkHpyfAFe/h/YJ4F1wt68C+fvDm2zQtCChtavvWNgRHc4dgxonYE8ieJIeUnSH\\niNdgNPi4DLQuBRFTQ/0RcDUipO0AC4sRblSOnIcBf8O71mAP7CsLgxrB2hFE5OUlKJMayseAH2cQ\\ngt77tkCEZnAuBaQbDI8SwL0nMLgnjEwL72oSYp6fzIevesP7+oQ70fZnYc5kKPscYq6BFLEhQ3no\\nHAVqp4Ibi+CPjZBkNxRcAZ0jQ5Y28DYFRE0IGUpAplWEhT+5G8C7LwhrZR8fh+UjYOp1ON4OkgWz\\nmaFQ5C6kiwEzNkLjc/AyLhR6DUdbwbetCX3TgT+s3gPCkuDf8xOCcpPyQuaFkLI37P8IRs6DeLEh\\n1yjIfheqPoSVaaHxeDh3B468hgPtoW1EaFoWJucgHIbPChiRevC2GOzNAkPOwYqdkCA7xP0WYgyH\\nYukh3ntI1Q/ixoJK0Qi7IDc/hSFj4dcq0Gga9KsP+0sTHqZHDIVszaHvVvhvAxQ+CjOLwvS30GE4\\n1F8O4yZC7A+g2xmYsBQ+rgeJHsPQvjBtOhx7DrO+gYIxCQuwqywlVIAe/RfK5YZL6+BpX3h/H26v\\nhbNPoWsG6LUJNmyC9Weh1Qu4sgEav4IYPeH5DRjUFoZcJZw3VJ4DY3PA2LaQZyGUmgjHg8H1O8KR\\n8o04cHkWdP8P0l2B9VNgWX2YlBiaDoW+SSBVZViRF/ZvheHBYSI77P4C0r2CnJthXJAUywKlp0LM\\n7rDkBWS9Dz+ngGEBNvADdD0C0dvDD7UhWy1IkAOW9oPK1wnjCynKQ4d4MGkQPDwIG3+BEZdgYlx4\\n2A/mR4MsMeD7s/DleRixDq4GNrLAdnYeBhWB1jEhb1TYtQdm9IAde6DaOTiUDS6WhwiFCJc4jsOG\\njjClDxRJDIWrQLyt8Ptp6NSNsKMwsKu/208oAo06DQ5HhXzF4OPj8EEn6FEVOtSHUY/huwpw+SJ8\\n9zWsqwwt0kPLM3AoCdxcCbmCaUEsaFMQ3seB08Fd6whsaQ9pV8H7LrCpKGHDQf9xhOqZBp/D+ZQQ\\nOQN8mwoOH4aiLwht75UnQawjcLMWbL0KcevB+p4wqz98tRZuZ4Dhl+GnXPBnAvg6BRR6R1hh3vAS\\nxC0MEWND8XnwVX7Y+g8cvwh/roav08CFn2HgcKgaHUr0hViBTS0ttF0FTX+FSDthXDk4lQKevoXT\\nqeGnodC6KHToBbHiQswUMKs9VKgGhY5C25/hYRGIuQE+LAg3AtB+Nrx9DF3uQJbIsDQvlFkKm4rA\\njXXQPx80bQHRbsDFvlC6IVQ9BRWXQrsD8Fd9eP8LvIwNVadDodRQJA5kiQkV/4NUXWHJbdjTAHoG\\nd7PvoMhIQm74ZDWofoWQDT29BjJ3grxXCbXVqZtCwcIwYwlEaQpVR8G5bLCvDTTfCN/nIBR4Bldd\\n+ubQoj/sXA0bn0KsJzB+FWyIDltywYwPIGkkuPUjJA0mlAH+cQ1u14fFySFVetjUEiZfgVKgTla4\\nFwio18KZFmAcLFkIPy+D/V9Bk2AXERsSzoK8ZSD9IWixFMp2JZSVBK0GlZrCgIIwOyDSfiIi6wLT\\nT1t4GAcmRPvfxZQ8NVxpD6MyQvqhUDknHBkPzx/BVzEhzyqo0xDmziYkGLLWgcnvYNYnsDgd5IlF\\n2Gt27SW0TPG/f5lzG/z2AuYGmPlpqFMKIsyHn7pD1CTw5QXoWAgSDYfeReHtCIi2BJKdhsVR4PfV\\n8DYYm8eElAvh7T2YFg2qnPzfBZT3cyjxHLL0JERlk+aG9EVg1VR4kwJy3obmFSB6W2jdC1LegELF\\nIdUQwnzKJ+fg1DeQsRwk/hwWtoNPAqByLYxYDfWbw6MvCC0ggTFodS9YGQOO5IMc6aF8clh9Cxom\\nBN2gflNoPBzq5oWob+DOPcJDUsJFsCUdIU/T/zUsyA79H8HpYPKUGPbkhAv/QKk20LchnMoHMU7C\\nf5ugyRzotpjQHFb6PWSuBIf+gXuJoFgeeBO0DlSGJbmhTX5oewAObIUiCwih2nezCTHbKP9B3LtQ\\nJyFkTAa3d0COAFheAetvwX9J4ZObUOAC5BkCKZ/DhRNwaiMMPgo3I0CVnDBmNSyfS9iKGC8/XE0L\\nWQ9CsjWwYzDcCHw/LWFZVVhYDwbvg9+2Q6xAmFIJti+FCmf/39eo7i9wdQjUqA6//wmLrsPb/6BI\\nKYj9N0R/BIerwpbvIM9U+HUbfL8Ykh6Aw1/CjLUwYAVcmAwlf4YGf8OORvBdSogZxNfvwhMQbRyc\\nWwRFl0LsSrBiCqQMloZDYFZ86HQflqeGa2kg60qIcAcmvIVzv8PIRHDzFOSKSrjujzkL3paFggFD\\nUw/+nAfVU8OGlhB1DdyaCAdAgpjQpQ7cfwEHq0HzDISF4nHnQ4Wq8ON/kPIgnL8A0XZBubaQ6xVs\\nrAOLi8L9JzBsBySLApWfQveW8PFimN0F0i2AdB0hextI1g0W1INtGeGDBzBrFeTqDjl3Qv4F0CYh\\n/LIIikyBmIfhs/FQJljk1YX/foLZoG0+wkN2o32EoPSUQfDsL6hQBVbNgALJYHd22LcBWvwFYx9A\\n+WmEBGGl5dD0Q2iVFD44ARPPw7zcUKozPL0Pm+ZCm+TwZxYYOQBW5oGIwyFZGdiVF87FgX5X4ctA\\n4HwONmeD0rMIM5VJ7sLXgYYjFYxNDVtOw54aEL0GpMgGE+rCycwwpyOkvwdfN4NGPWFaT7gXFRL0\\nh68HweOLcCcPxPgVSj+ADFkI7YbBIODbnrCtA1ztS2gGHzUCogfLuP2wuiBhUXHmm/C6JUQ8BovL\\nQPIU8OgGFLwDPS/AR8WgyTYovA/2By0jXQkbfnMlgGldoUANuFkZGmSDM22gfxTId4UwalP+B8iw\\nGYomgfEPoMdyePslLFsJXTJDpBIwIj+07wwnl0KqnNCxHXR9BnVOw+Pk8NF5ODEDXhwgDEWd/Qnm\\nF4aK3SD2JOh7E0Y2gBYH4UZ+GLYJLu6GvwrCqk2QbxvM7ES4h8mRDSb/Atm+grxdCYXY727C48GE\\njZz7WxGJZe9gwFdwbAs0+RsS7oahlSHrZfgtSAc8gh9ywp0qcC4tBGvWYFJ1aARE/RhaxSVc4jxc\\nDZvnQ4Je0HUVoYP1/QY4PhJWfAaRBkLHAAd+TSjmL3Ebjv0O3b+GRnUh2SMYHggOdkPGg3D1I8i2\\nHp5mgIoF4cky6F8QrjSBX5fBh73g58qwfSQc+AJqNYWLwRouDrT6B/JdgIwj4efiMD8iVB8DDdoS\\n7rw/HQcHGkGM09AkQMKvQpwbcDAnLN4CBfNAlalQLz08/RguvISU/eHEQbi+BUYFZQ57YOQ6uFkU\\n5jyHBDfg1FD45hg0Gw7ZgptIWoh8A6Z2IQz07psLO6NA45fwYVtInQUaZYd2n8KCzfDvRGh6FarP\\nhZEfQ/3pkOAwFOgLj/+G90GA/wYh+zXwIEyvDvH+gMlV4NS3kHwo3KgF99NA5rLw4xYodRu61IBG\\nSQhfEubchwWR4fhA+OQT+D0HDP8dTjyERq+g/kbYHqSlukDC6BC1CcS4BUeqQMLEEDsXTGwDVcvA\\n9XhweAf0Dg6F6eHmdxA7E7yrD18/hebX4OYHEHEqLHgIH9eGX4PIel2o3ATuTYbbkyBlZhi1BfJM\\ng0JXYEBK2JABUlaHAh8RSh0D81yaxlC2OZTvChE6Qq0G0LsTpKwLq+LCmkmECPOV2NAvMSTPCUs/\\nh9/awqLOUDyYCD6Cq8UJWw4X7oDNf0L67VAo8OVMgza3YHA6eNoYJv8NGQrC23fw2y34eyX8eRoS\\nLIIPCsCWFNDxHVRpBX37wNdzoccbSNMB7v4BB6ZBvESE/XQz5sG2gzBrKnwfGdI9IKS4rlSEN+lg\\n/V2YMQX+WgDRp0LNljBlKTxoDaULQnrQJDDO/wlL2sGFxpCyB/yUFF78DKWbw8locPQTyJ4eGg2B\\n3f2h8GjC2ertfNDpMIz5HSZ/SljtXOQqZB4EY/bD7iNwIjhQTocD2WFteoj9JXxyFiI9hQ9rwKAm\\n0CNAC7rDX8UJ/fKBPrrsApg7DMo9hVJdCbUU9yrAk3HQI2AuuxNKU/eXgsOT4E6glQ6ePgXh+FLY\\nkBNSj4IPN8PZpFAmDuExqG0vGBakbhdDmcAHdhIK7YTSRWHEXzDoJdyuBa3uwOAy0LkV3FoPMVJD\\nxsvwOD/h6jYoDx54Ez68Cx+tgPffwZvP4MhEqH8Hmm6DPtdgVRO40gO+G0cInBRvDh/e+N/nHIAl\\nLx7Ci3Ww6RHEmwJ7/4ZOz+Hge2h0AKpvgQe/EjYN7E4Hac/CN1mhT6Dn2AbRu8HP/eHTLDDvJCz+\\nFD4rCpdOQuM4EO0HON8Y8qWC8x2g4AP4vQcMK0coMggqyc82JdyQDNgC088SdhjczkpYxRZlAxyb\\nC2dPw9MZhBKZ37PAyiswrQZk3wn3W8D9rIR57dFN4OVrSBi46z6AzIsIFRUdVsLcVlC7A7zMBZGi\\nwLF8UHsoHI0Oa7JBje8g1REi8E8nuDgKMqyD2X2hx0l4MARSN4OmG6Bl4IUqAOMewb3acO5HmPcB\\nfPASpt+DWXngxEJYchAOBtmBd9D9CbwfBD0KEKLxpxNCmjpQ6T1MagjfpoHxF+HyS/gvPYyMD9vy\\nQLngtB4RkkWEsYmhfgsoWxt6zYbXJeGfzwkR72AAfuchnM4LafbA5bGw7gX8ehHyn4dXkaH4Wsj3\\nB5S6BNszQaYvCc228V4Q8gRB7uxSXSi7HP56D9lPw8ZDUL4cFPuDEGj96iDkLQv5hsPWjVB7FVw6\\nD/U+gqVfwKVacCctdL4K96tAnp0waD9cyAS/n4McT2DTKEj1ELYEsYZi8G0ESFEU/j4DjztAyQVQ\\n6SkUDlJIe6DtI4gfH84E6aEokPEBNI0Ht7vCq8mwMAkUa0GoHuh1G7LlhJmP4euB0OIE/L0Rok+C\\nksHnX5ywv3LiG4j7Dtb2g2ZbIfVLaPQelt6CZv3gw/0Qvzn83ATWX4CLS+CPIXCsOnxXDP7cB8Ni\\nwOdb4ZeUUK04fP4DTL4PbxrB5u+gQwEo9y9kTQc5DkKXcdCwB3Q6Ag2LERq8Um6FJRVh1ga4dgrW\\n1ocytWF4UAGUGQbshUz5odQ6eFUBUp+G+sMgekp4+wrq7IRUfWFBTTg5CC5FhwZrIU5b6L8bYkyG\\nuDuh0HRIuh1qtoGvt0PP7lA5A7yqC5ceQ5n+UH445DwFcZ5C7uLQ4RlMWQDDlkDNCZDrAHzyKaE8\\n5f55OJIA5v8CF2tDwo7wR294NwI+uwsN2sDqinD1GnSJAdUqQcrmUGYjpPgArkSD6F8QhldSpITy\\nLWF8SzgeFW4dhR/XQ/b7kLwwvDoMOz6ERl/BxUDdMhnmPSIUmcbOCYUWwvDZsDcqHEwEfS5Dyu6w\\nfxM0XQun70PcdhD3AWzpAfVawcRv4FBLePA53D8DJ/tA7+hwaAa0WAcVJ8FHsQn5m+oloUNviBLM\\nBlLC8kjQeyjcjwLLf4Rrl2DsJKjZDAZWg21X4fBoQq/bpGDSsx0arYXar2F4G3iYBCLfhga54fkf\\n0Pw8PC0AMQZBka/gwgSoN5Vwhfo6JnS/RNgnsWg7XNtL2Cxy/zAsqQa1PiFMSR8bBLtuQp6isHIN\\n/Pw5tGwEq8fC+jqQOpAXvIfGqaDucmh4EVKWgLx5oepGyH4ObjSHm/lgS0l4uolwtZpsMawNuhw+\\ng9KVYX4f2NkaXryBwgegZgzYuBxqvoaDgeKnPIybBideQ++l8H1zqPAP1O4K3+WBydcJRdO/fwul\\n5sHTn6D675B1K5wZCLuTwLdHoV0fyDcCNlwinGEX6AeFosGcf+FWBoj1CtY/ghXlYEM1yDMasieF\\n2FcJoYgDeeDaFBhRG7qtgS+jEirN/w1m5LFgTCTYFOBPp6HAJCibHjLvhu+3waUYhF3AlVbD/PSE\\nUuvffoSfvoRYJ2FJVngayE57QsEycGoa5J4NTTZCz4VECtG22Pfh+CuY/ju8jAyFJ0C2wvBTbagf\\nAIx7oM9z6PIcMraCyb2hb094+SW07QQp6hJWiwQasR9bwtlcUPNjyHQMyrWEN4EY8yx8fQwSPIOS\\n12FDYWi/AOL8CMuWQpKOsG4KYcS9TzHCAPDLPyHOOMg8AdK0gcFj4fWvUCUS9KkK/ZpDpNjQYzcM\\nawhxSsCRYMcfC0r9CycXghJwZiRMzQ0xMkDdAH5MBd/Mgmrd4HVW6B18tb2hV2H4exv8GeTIesCz\\n0XDsC8KOueaX4do1WHwTSiWBt7ehZG5IexU2zIVfR8Or4jBqNbxOAfG/hFRZCSULdWLCohlwuAr8\\nWR0yPyYsi327jXC5WTcqZOpP2C/5rjHk2UL4oO14DIrehHyPYMQ5qNcQJgyHT1fB38FPsS4Un0JY\\nMHIhM5RaCsOvQMLlMCFI9t2DnGOg51yI3A82j4APx0KzOhDtFRQI4hrBw+MkoV16wSUY2h8uXIBU\\no6HqCPh4EfyVECr8CUn3wqIF0LAJ9DkMr+PB2QtQfz80vALtB8KwjbBsOtSuCq+/hdb74FROwvD8\\n3T/h4kTC99dIl+B6cAxtA/Mrw+bgdnMbvotHeJS/+CuhfOHfGJBvAwwL0rvP4VYiSNkXkiaDivFh\\newfCQ1L8btD9ARTfDnt/hS3fwy/9IFYQYbkDl0rB3CATVwu+zAy7XkLaWDCuG2w8CYu+hD4JoFcq\\n2LoNRuyC3RMhSj24lByeLYGuz6H+algYG47UhRSB3Wc5zOsEnc5Ap7aEb9WrP4O9P//v07jREdr0\\ngHXLoe06SJwUeu2FIkmhwzYYnRteFYWjveHhDDg3Dq6UhyEtCRWXB6tC3r0wMzGcCnJnD2D0acgQ\\nG87NghEV4eJ5mBs4kJpApj8hamm4Ngy6fgAL2kDODtBvJBTbBG9bQ7FTUKMkocP9dmGYfQtqR4Q/\\nAiq0NCSKDFc6wFeJ4UlSwl9ZrlOE0HeGLoQH+kCV/PQ5IVvZtTnkvQdn+sCr+HAygBbSwOebIVol\\nCPiF8uchVjCZHgozm8Pt9jD3Exi8F0a0hAtbYV3gMb8L8ybBrJww4hnkCA61tWDsOKjfD2I2gSTp\\nINM4Qu1CzqLw+he4fgKiB/OYHTCgBtx9CRuXweR6kC/Y5ByHsaMhV2couwMWTIClZaFwRHiSC3a8\\ng1qbCAuCjjeDxJvh0DBYt50QHZmcCpqkhpWTodlc+OggxD5D2IM5IDG0LQspk8Dx7dCsAmFP6Kr+\\nkOgU/DQPTt6Apftg7BaoGg92FoG3zaE+mPQHPP8MMpWBtpXg4ueQPxP0LQKt0sHMrRC9MCxYA5vG\\nEK6Gg3RtvF5w/xuI1w/2PYQjDSFKTNifA05FhpMJYNxZKFcHLlWAw7EhUwSIVBZmJ4S7reHRHtj8\\nFYz/G/rGgwFjCe2J13NDxivQLDVE7gtjJkOTY1AxcH3dgG7b4ackRGJVTxiYE+quh7RPYPsUqJgQ\\nEh2FGIthUUYoG/if+kKEGVBrCRTtDXdmQa9BUHotdJ1D2Cc4dDZULQtx88N/daBDWqj+I6Q8Dh8l\\ngksLYFwHSBsPupaFMf/CrhwQMTPE3wsf5IV1v0C8ClCxJKSvDfuXwcj2MKg0bOxLeBw5ORgK5IQh\\neSF+YcgbAy5/BOl2QuR8UAGUqw6Ti0L1XnC1F3z2GqKPJQSTa72Bwf9A6/qQKCN81BQixYQs82B4\\ndtgTAJUbIE47iJIWiryBI7shCLoVmgP3RkHB6bDjHxg6D8qvhYFLocB1GB4PonWGSscJc5f5f4Xy\\nR+GjMYQdfE1WQrN4sPQTSBAJzmeDJ6vh6I9QbCU0aQj3l0Kl0TAqWKi9h1lR4V4V+O0O/BATCj6E\\nEjkIibHAVpVoJ/SKBbGC4O5xSD8Dol6EfGng6UD4aR9ErA1dpsL0ozD6R0KJ3KhKUD8pZLgO3X+C\\nRedg/I/wIC1s6ETYJB/tEWQrAMO/INQZ9FoA1WpBh/SwtCs0ewALvoPBd2F2LUJR5Ne/w/DDUD0p\\nfLENjgX5l3WwrTdczA3zYkLH32HKYKhVAtpsIrRd37kKlTvC2QFQZwm03g0jkkDfshBjHrTcBm22\\nwp8tIP4+eFkOjmyFe2vgn9fwPhBDHIfoxaBWFKjWEa78BJEXw4u/oe59mNoYpl6CDSXhdQRCInDI\\np1BtCXw5A8oUh+yP4Xhu2NEChhSHHnEgagq4lB9SToWezwmXI8H6JnjrfX+WMMs8cTB8tZnQ1/XZ\\nE5j4M6xpBfuGQaFnkHYZbL8FG9PCkUDVewbqBxRpDGgyE1JshmVX4V0XuJwG4r+Blc3h28Nw9wEc\\nuQEl00D/1lCiB1RpSai0+C8SPH0DsQIKNnho9YXUZ6DxBELzfqU8cHQQ1A6u7evQMyN8XRJWtIY1\\nyeFSNzi6HlLdhLufwcZ+MCYuNNkFqwrBf1dh0CKo1gWyD4axgyHDLchRgtAzVHMLTK0IS8/C/NVQ\\nZTO0aggZFkKhC5D9M8Kc7/UMMH4f/JMHOmeCGuWgTQS4HDDEGQmLlv/LCs0ywB/HIEZ/yP6cUNxT\\ndQhEGgP9+kOvwLNYDYZ/BZ0DBXcTGLgfbqYnRKH/vAVbDkKSZNB8GTzOBVV6Qt0UhE6sDP1gS3XI\\n3h2+SwWda8HLtlD7KZROCTFOwdjPofcGqJge2iaHHWfh1TZ4OwOWZIAFvaF0T1j4AP6MD//sgrTB\\nEeEnmNkZjr6HzwdBgYmw6xLkOQGdWsLXf8GzyxDhHeSKC3vvQZaI0O4s/F0bsraDlZ2gUmI4Pw7+\\njQzVUsO3P8DtUnA7Kmy/CxvmwdTSECs6YaXSwblQvAWU3ANDisDDnbA3CaFH7VUwQdwCNaNAshxQ\\n8i+4GROuxIPC9SD/GbhdFYolh5h/w7KKMDQnfPATbNpMeO/dOxGiLoCYUSBBNYh2liDUFYlp1wnr\\nU+LFg9lj4acI0OII7F8PP6WEHmeh8WQoGgnal4GV38HTYH6zGWr9Dkm2wfXYMOstfBkBojWFSS8g\\nywxI+wec+RnuD//ff+DFbFixF+7/CxMyE1qeH6WAh/chaT3YXQC+Kwmb7kLRwBf8OfQJVGbTYMgI\\n+GIsfLUbJu6AOMEE5Q1U+X8fFj17QtfHUDQV4cAz4kE4sQw6dIHjH0GvZRC/JLw4BBnOwsuB8Ec5\\nmBkHiq6C+wXhQW348RZk3wsTIsH6vDD8NlSbAp80gW+XQuF/YNYX0GQWvGoC1sL2p1B1FaElZfZo\\nuLwW6uSH7Rfh2Vs4WByO9oWFQYy/FZT/A9Jsh/wvoe5+SFgEEtaFSs3g0/5Qtjd8lxFKNocsaaBY\\nByjbEXrVhISZYNNNKBt4Rx4QLhdqd4I9I2FNI5jcFEbWhfoPYHYyaLoZBjaFiVNgXxCuHgaxisPv\\ncwlfLfatJ3TnVAi28jshYWV4/D30SgArbsOoN9DxR9h8A75sB536wF+rocJgyLqDMFNZfSDELQJ7\\n4sK/f8OjChChKTwrBifewK954PwhyJ8AXkaHPfMg+gcwpS4s3g0nF8EvSeHCBkJDzxqQ8BIcjguJ\\n+0LN6lDnAFz4D37rBcnqQZOsEGUQdAhoxV8gURyINA/uPYVh72HuSphfEO60hzhj4NAmyNobaqeD\\nkc0IC90bjCCUhbZNAENHw6mIkKsMLLsE9X4l5B3jLYU+dSH1HZiRGEZNh48/gs3vIOp4uFMPztYl\\nzGMeuwKfnSP0rk3IA/PuwZiUcH0PPMxP2Ec5+iAMmgKtDsO4RnC+PtzaBh9ugTFZ4GFkSF6NcNGc\\nMCG0uwJTUsOk01B+ARyPCYmHwa74kKgRZFkLH8WD37+A0m8JQ+Y7a8Dup1A5HfRdA8lbQ/zW8PFv\\nEK8orCoPP6yAWq1h6Qfw5gAM/BiGNoNPpsInwbz8FixaChPGQdVUMOAmNLgGfaJBhkKQ8xVhAuuT\\nuHCiNWx5CWnSwbq6EOcBRKoJ5b+DftGh7ys4uQpqJYLMR2FhRYgzF27/DJnSwLkgl92EcPrVcBb8\\nUwFmF4aihyFfdvhgLjx6AGu/gOVNIPkVQmHmhELQeR2kiQjny8Ln26Fzcyi6EeZFh9el4Kcy0GQg\\nvHkHjVJD/B1QLB0MnA7FbsPuodCzGZS4BwP7Q97u8KYVnAtMcrUIq6V2J4Pt0SFBPLi8Aa7ngNlZ\\nIEd8QvFN4Lor/gPsaw1DOsPlX+Byf3ixinAkEZSY1XoLrftD51PwdDCUqwxF+kKjjjBiPVzvC6/G\\nw/RAY9QS6l6Bxykh6lho9xYyjofqX0PuGHCpP2SdDFc6EzYOB3qRfYdg6H7C4cLMPfBRJWjeGmLO\\nhAMzYGEC+Lg+pIwJkYdAhF5QeAy0eQUrvoKEIwkPoCcCIe0M2D4WShSC++cIp7ArukKkbJDsPTyb\\nBLkWQZp+RCTPWqgQC5KshO+3Qo6IhA19Q6JCou+gU3q4kgxmtIbWneD7ptCrMvz1GZxYC0eLwN85\\n4fYa2HkVimSHM2/g2mC42gcW94MWmwhLf9M1g0olINnfEHElocVkcEp4fh1SlICiiyDnWqj7A0z5\\nCr5sDsP2wSf/Qvt38G4mdPsKbqWDafMJUcRvx8OpQrAuCTzrA83jwbTUsHg2lM8FXzaAVEUhSiIY\\n+xKenIJfE8GC1hBhICEdlWcmLPwcOi8kZNTO5IQc92D0QPj1MnwwHw6XhU4Z4KN/oNslaBUJcn4K\\nyf+Cs7WgXFfImhE+7wuT5sGdntCzEkxaCG+OQ60WkG4NrA5G+hGhYHTo0xW2vIOELWBOA9h7Ai5u\\nhenn4PI8mPI5lH0HdZ7ChEqQtgRsjQXTxkOJmrD9PAyrD3E3wa2BkLkOLLkE7+/A6aZQqRNseQ9d\\n4xDG798FS9hJ0CdYmQUL6ypw8jRE3gk7VkO50bBrHv6PQ875CPIEq+qj0HggbM4NTd7Dq5JwoDVE\\nHwTLF0KuMTDxJWGD2PNhhAUO8xfDlTVwuxok6AuV4sLjCLAsWGoMhMWBGDBwqvWF4iuhXyJol4lQ\\nklllGKHv/lqQI9sGw17DpSXwrBvUXQurf4T+2eCHwJ7/Br45CfWWQY4/oWBUiN4Yat6DZ7kg+w1o\\nXwK2p4QRmSFXKkjXCdJvhZ8KEoo2Ik6Ca9Xh4QfQbiDUXAcHOkKiuHD8DKTpCqdeQuzW8K4ljPoP\\nkhWDa/dg31fwdCtUnAHZl8KeD+BWLJg8jLBbYsY3kCn4TG5D0eBxVRQeZoabg2BmHtiaBbb1gCtZ\\nYesE6PYQcnSHh1Gg4mzIcgxS7IL8f8CgYHKTEQZPJNR4HmwNh6bBnIVwsCKk7wD1U0O/WxCpELRo\\nBUcCw3g0mPwnNKsFkfbBvsfwIC98kxHSzCVswftrCiQ8TEgrztoGh/6Exs/hXRxC6UzxxLAxkPpG\\nhvpfwn8nIPE/cGkHnH0BjTJAnm1wqiQ8LwFlrkCWQvBnPMgRG9I3IRRhnI9FqIr9sDXkGwavLkHf\\n0oSv8Z/Vh03RIe4IOHwLZh6ETP/BoV1Qtwrc7Ap1ohCKlHONh8J/Qb09kDAZnGwFO7NB35qEie/+\\ndyH5d3A5A8RoCv02QtmI0AEM/AYm34DZjSDbOuhxCwqUh/01IEkVmFsMCs2EU92hWBr45y7s3gSr\\n90OVePCkFSG8n6McDKoNWRrC2LWQ7gv4vh58fhOqB7GMLyB/F0J+9+V06B8BTk+D0xNga2fYtA3W\\nfwi3G8F/HeCDDBAtMXTYC3djwpxgL/QCvl0A5/MRcnKbg5nfW9j4ORSeBW8aw/4+8DbQlm6DDa0g\\n7gLCWvTUx2HXSsJXxMbJ4coZyNgJ0v4I1YNhRB+IOB26VoAjOeBBT7hfDZqehz7NoFd5KDABnhaG\\nSvshb194tBfa94GEByHx14Qpfj+chk8nwdmSMK0a3FkLxdrB+D+hXh+o/Biqb4Ao96BjL7i7Epqm\\ngbVP4VRnOLYTPowNZ4ZA5pSQ/Sb8tQ2ifAe960Cm21BmFEy7A0WzQrZOkG45xA+mJtMIiaWgCLN6\\nOTgUFcpvgCaNoHpyGPkEptWEBxfgw0NwLQF0HQn/vIK/IkOmRJA1Ify1mVCvMKg/NJ8OuacQvr/W\\nvQ53bsMHA+B2cvj4KGzIA8U7wt+Bh/dDiPoF5J4DP+yCcakhRR2oMQkKZIJWmyHPj9BmKjR+A7cS\\nwsaEcGgRXE8Gd4JB+i+QKWB3MkOB8dCsKJyfS6gTvD8L3iWBCxFh9scw+hBELAPRZkDZlNB1C1wd\\nBXVvQbX8sKIx3OsJCU9Cry/hn/3wVxPY85xQGTo5FkyJAscD9egLuL8Ovl4IcerAtDXw0waIkBjS\\n1IemX8LMpPDpavg5N3RPBWdqQqa2UKECbLlK6OPptB5uvIUr3eFyRljWB84uJawRHZcI2k6BoTUI\\n6ZbWj2HcGNg2Caacg6GNYW9hGLMDMiaHvx5Dtp1wbAT80QqyJ4AyQ6HsVoi0CM6/hhbxIVbgEY4E\\nO9bA8k3wfUFIkQhWbID7ayF7M3i3B8ZfISRjZkaAHJ9C9U/h4ilCRV60C1D0Qyi4BFaOJezrHDUP\\njhyHt8MgT2FYlRd+KA2xb8DLk5CxMnTNDWc3wtX7oDV83x0+vU64sOj2B6HHvGIrOFaJ0BaduDgU\\njg+DTkOVvwlZw+ddIMM8SJcdhg0gbFzYMgdi3INLW2BBASi0AZYFuR0QygAAgABJREFUyeVs0Lw6\\n/HKQ0Dq96nPoVYlwnZdoBQwbCAUCfWtF+PMHKDAZpseH7+ZD5S3QsxX0Gw5LUsLT44SFTjeSwIai\\nsHM7NPwScqwhrOwNZtWLn0PERrDnU1g9nrD/dOYYmDAElqSFv5ZA4dmwuB4UzAwJ2kHnbyFOBGj8\\nMUzdS6hmXdoBSh2HT5fBrpzQIaBIn0ORZ/B9eTiZBt6VhYVdIUUe+Dc5LFoMr+bA02bQbhn88RL/\\n19DQ+Q9INxsiN4PNP0D/S/DTRhjYGn5+Bll+geK9oX0wz1gJJ3LAV1fhm08gY3WItxPSnIf9CaHv\\nTsj+FyyPAGn6wpwTsLw9tDgGBfdB1GAS3AxmtIQuu+B8edgQQBpXYeUFGJgVLn0OPdYQZgxn5CRU\\nQG+cD4n7Qc1gWrwYumaFapshQW3CVr6UVeDZUgg+vMZFodcQOBkDBp+Ef7LDl2+gVXyoloyQd4x7\\nCwrOIMxy5k8Hzw7CvCFw6hdYNxoyV4QPV0PxHIQL4kHJ4FkziHIABveDUnPg40aw9CPoWxk2roYz\\n86F7MJ3dBRczwqV4sPokLFgMvS7D8ShwdhDUDLQLb6HXDUj/FqYEm6iIcDc9lPweJIZUY2Hrfegf\\nRC5yw4o+hMVZ6Z9CvaqEzN+UOfBBZfi2AXQdAcf6w8C6kHU91JgHAx4SgRP1IctI+PF7yFEXco6D\\npeNg6FWo2gTa7YCCMwm7/NL3gAJtCXmmmM/g3B64Xx3GxYevKsLIsfBgNQyoDHHXwe91oP8x+O0k\\n/N2GMLT5SV0Ytxxarod2qeB2HNjyCxzOCPlbwOTR0DXIaAyBFdMIB7+bY8CzbHDjLtQOkom3IHYw\\nto1IKIM4EAWqZIQ/DkHjszCiGOGPM/J+aBcsVaPCn6XhyltoOAq2d4eR42DyK9gSHE8jQ4kl8HVn\\nOFMMUgTRgUGQ5BBUewulVsDcb+BwCRhaEuLFgc9fwKCckCgLzNoFjStCqgPwbRXIWBj6xIf7FaBh\\nEcgX0EIRCQHhLLvhzT2YUQmqR4O7j6DRRFi4GsZngk5xCW8Ki36BgxdgQqBFyAGJu8HwCDDrGMxa\\nAFWfQt3PIM5nMGgeLPsCHhUhlL5e/w/OvAKBEK8j/BIDkq+GwsOhzCF4fx6S3oXjV6DmTRjUndAx\\nVr0DNDoDS+vD8RRQoQNMKgw7/yJsUuvwASwaCqcGQpFEECkI568iLJAJkPzL3aDeC0g1EZbmg3aB\\npi8efF0CIv8GTdLD5jNwqTS8n0NY6xu1Erx4CUXWwK9lIPZi2Jgarm6FGmlgWXJC0WvdBHC1CpQo\\nCN0ywM64kHM+3NwCz0f977otNxlKH4O+s2FKDPjiFWyoDtc3wsbrkPUJ/PUTrCgEJyvDpM+gzUbY\\n9wukbwn9zsC70jD9R9jyFaGWospcuJIAiiyCzmkI7XSro0CDYFWRCX7qAOOiQ4e2MOYI5PkIdv4G\\nY8/D1wcIucAacSH2BPj2CaQpDw3iwI72sDpA+DtCnlkQJ3jX7wbNJ8L0aPBdsICOD/Grw545cD0P\\nYRdn6a1w5Rk0DID69RDxNExdAZmWQtxqUPMhNFkPVzLDxnNw7Ca0CTJijyFmA1hamBDDuNEFCvWD\\n3TMIQ+YdakDZAfDldxDlIYxZAUcrQLWAed0GdSpD9RuQegwUmQkr70CPNJCrGaxcBLcqwNqMUGUw\\nHM8ITydDwboQqzQUmgyLJxFKg/dkIJQmjL8DA6vDgPRQ7Cxc+wJOF4WXZWB/wK4tgBmDoPov0CF4\\nMAd7ktnw42mYsBm+Hw5lx0DREbAxMXyWHQ7+AAW3wdNLsK41LKkOJ4pBo3JQNhP8N42wt2BrFchb\\nEno2gEXLIFcliDQXYnaEnLGhXk5o/zGc/hXexCZMuPc4D2eCzy07JMoNnzaB209gYw9Y9gLiToE5\\nVWFmC9i/GarEheiH4YsxEG8vOE+odf1xDCxIDlFfQNGfoGl6uHSfMEkdO/jt34EDCeGD6nA9IiQP\\nmjDSQrRgTBMf5l6B1PHg59Gw9QVE/gS2/w0lqkGZRLBqDkyqD68nwtub8OcWeJcLxhWDCUXh6UTo\\ncQS27YFIh6H9faizArangRo54eJKeDwWIl2GjCvgp8NQuB+cHQpLG0K9yjBwFHwbBFAaEom+QwmN\\nR3W+gLglIWEu6BhE/aPAhvxwYguhJvFUSngwG+rchTtd4G0RwgzaZ9Wg6ytIOQZePYaorSH5ACgy\\nFb5ZB+cHwOEL8GvwcE0CB1ZCzPcQuRK0qwrnKxA2Bj6uBvHKwdny0GgUbBgDV4Oj0hS4Xh7KvYCh\\nFSBPZBhxH0bega2vIM/XEGEQtJwMnyaDG3dg5c+QtDNk+heOvIPJQdXAj1D/Nxi6DiqMgLxNocZh\\n+OM1xP0LqvWEX6NA2VLQKQFUngw/HIaEzeG3XHAmAVQcCRECh28vyLURjm2G8uvh1TC43Q6OxoPf\\ne8Lq9NBuK2w+BWkC4Wp8SBULrh+EH6ZB6W2Ey7UTu2FUEshQnBBLjxkJVvWDNsngk2Yw4jbk2Art\\nysGKSFBnKiTqCY2/hfyloGs7OLCJ0MqTpiRh/rTWN4R+o6KTYXkaaDoOlnWAj0ZC+Y5w4CXkSgGx\\n10Os/yDBGUKdR4AudusKB7+BDddh0xyoNBgmxYfOEeDf2IQu/iBq8OVaaPwpbLoOqY9BvNWQPjpc\\nyQ6fXYHxY+DgaSh6DNrnhpi14fc8UOoqROkKm1/A98+hQFqoHgXiLYSFK2FKGkgYCyKPI/S+BAVQ\\nN5ZCr12EQ/Jj62HGKDhRD6SGA8lgwVM4H1i8v4XvfoV6SWHZFUJi75OZcGsBfJoORvWHxRng/UNI\\n2gm6FyB0iAdE2oKJMH88zG8D9aPC4cA+FQFGNIEosWFPI3i1GgbFgv0fEhaYXCwIba4Q6jASHYDW\\n12FKPjg4ETrfh2f/Qs2DEHMGzLwBDaJBw/PQ4wG8HgwtZsHJRHB4CKy587+r66dt0GIHbClDmF87\\ntBn2JYW/s8LsIYTv1gWLE2IS2SLAwXGQMyLcaQQfPYXUlQhFD5+dhXVDYPUz6PAn1C0CxYvD7MNw\\nviZsLgzT18DdKtBpKsROAT/8C/3OQcaZEPsb6P0IJpeGyMEUZwT8XQ96NYYh0Qi7IrLcgTfJIHsm\\nGPsMUqyA4v1gRAWYkQP+2QJnahA+2k8MgTRVwS3IvBaq3IYnx6DfUhj4E2wcAHn/gwMF4FZlaNMQ\\nHqyAxC9hwO/waCMs/wlqzIf8gdhlKGydD6cOwvffQ6S4sG08ZLkFG76CJTngWQ1IGri+ekDuhRC1\\nHdycD+sOwIAi/L96pQNwNib0Tw67S0I/cH4Q1LpACC3EnEIovdzZG4a8g7aFIOlmWDIaCqYkpE4r\\nt4ZGy2H8RzB/CXy1jBCTnxgdlu+AvtHgUCeYmABOtIccZyFnIKQILPMpIUNPqP8vZIsFs5pBjCNw\\noCAUbgpXD8Pxd3D3Q3hwH67Fg2N9YWof2LUZdn5GyE+vCKyBk6HGWygZPPWKQ/RfIO9LiDQJ2l4m\\nrPGpHx0KLCYsv7qVFs69hEUfwJnrsKsb3CsLr9JCvoSQNyvczQOJM8G3QStAI8gwHab1Iiw+GpAE\\ndv+KsArj4jX47Ru4EnBLkSDyNTiREXbFhK4D4OZ4qBcdztaDPkvh9S3ImQ8OrIJ1F2B0IcKUUPrs\\n8PcSKNYDHp+AX3LD2uOE8c5k9aH/Hvi1HMxrDiuLwrpzkHgZTDwA9TJD5p2wYCCUS0CIZgc1Gv1z\\nwNvZcOIHiBw8gNMQlraO+whar4fmXeF0Q2jcFxb9CE+rQdGaEG8+1F8C5StDr2dwux98sQNW7IEu\\nsaFRVzjeDzrWIcRF66WAvJvh0nVIXAs+2wadx0LUwO81lTDxETs5tHgMsxZB9a/g54owaC/8Ow0+\\nrwcFfob/WsLW6PDrayhcAobdgNxrIEFH2JoUzt2HL15C8XcweCnMvgbnzhKmjd5dhgMXoU1LiLcc\\nfksEVSrBwBjw2WSo8z0M2AVZq8Gk0VD8G7h1FQ6Vgm/6w4Mgct8OZj6Fc0OhXn04WAdqNQKDIdMK\\neDkJbk2Hbkng9wPw6neouw767oLuKWFNAyhRD3LPh0/PwP1K0KQ9XK4CDW5B5+5wbg0UnwvDPoOa\\nc6DKxxA9FjS7TTjdnJUExuSHfishw1/Q6SAM/J3wtpKsKHzxKXR4Cj8vgNP1IFkdqJoW7sYg9P3E\\nuUU4No/2ARwKpLItoUNJyLAFJraAZ6cJHeJB+mxmL4hYhTA3eiY2xHhPuCzYWx2W3oWyiyFjX/jr\\nGSwbCiU/hBFR/3dtdA5Q6/1Qtgfs+w1qH4bZr+GT05CwJ/yzHVLPh5E5IeUVSJsSGh6Hh+fhjz7w\\naVxCH9v42VA6BdS9Bv89gy9ew6Z1UHstZBoB49b7/5i6q7ChqoZr2yfdHdIg0l0S0iECAtJICdIC\\nEgICUtJdCtIpqJR0NxIC0khKd3fXt7He9T//rhseBzfca8454hoYcAiyTSVMoaW8Az3AxYqQuztM\\nXEFYBNk3AX5bBgMewJ0iUKwx3CwHdbsRdp+33YHLJeHVh1AxwGAuhIJ3YfxzuLsGDtyBu73hTgCe\\njQM3lkD9Y5DyD+h3ENoWhhm34dfxkC0HPD0D8QpDtwRQ81coVRh++hnqxIFTr2BJoG2sgtrLYfFD\\nuPs1XL8MC/fAtC6Q8hPYuRx+mgQFVkL+b+HMNCiRB67fhegR4NJ5SNIXYqeFZcXh5+Iwtz0krwkb\\nj0LFrnCpC3wzBR4dhh9awN7F8MtkSDIEVnSBpathygYodg5q9YEiE+HLtLA8J3w9DzLch5nP4XoB\\nwuB8sN57PB1UjAin/4Clk+DHm4Qo3ctFoe0VuLgFZgSJoqKEGI4k8eFRdBg2EMr/BbUCWG46WJUJ\\nPugKH/8L6V5DyqqQuj4cmg53KsHhQjDqK7j4H9QfAbdiQd9akDaoFiWEiaVgSQNIdRz2F4aGqyFD\\nM3g6gjDoXXU/xBsDVVdAstFQMwe8WQff9IQECSFddJgxHWregIeLYeIEKHEZflwNS87B8ESQ+Q0c\\nfwzlP4HozWBnb9ieDloFEI2xkDozDCkMJW7CqLTwaVLolheaX4br42H/GvhlOLzOD78/IVzYvHQK\\ntr+G7Hng+RCINQ+ijYEsneHINEJk0twIROT7doR3259rwNVuhN7/6E1wcxH0vwznEsGC7PCsP7yt\\nAXEyQJqGMLkaxBoHbYfDkCiwJlBrrsPgs/DkMfz6ADKNIxTPS5SHpFlhe4AEPAaXvoU8O6BBwHSO\\nBkM7QPtfIE07WBbId00hU/AabgdtFxEO3MY5TSjh/rAD4v0Bp76Hf4NuVxxYOAM2fg9bPoQ/FsGX\\nWWDbPYiRDgrMhtF9CeXT7mPhQkf4ZQWs2g5HGkLX9qAodNwMqVrA572gzq+QpRLc3UeoLx5MBaMv\\nQLS20C8ebL4MjYdD06XwMqAGH4a42+HwDkLD5d16qH4Fct2FdKfh9C7okQFqLoGiS2Htt/DqPkxv\\nBhGTw8tl0PExNBoF/YfA2QIwciJszwZVX8L+r6BRT8i1C94OgcfbINIzuHcE0r+Aw6khw1Vo9RKe\\nTICvlsLdl4TTodf+gWYVoUpuaPoFZDoLF58QJiGeLICIhwg/6MUDzTITpMwChePDgX7wTRq4C37o\\nCTuyw9VCMHILxMwDVXvAq3uQdB+8SA2dZ0D5KzDzLTycBlNmwLNMELMMJEwDSzLD5gDTOgpexYIq\\nv8CGN7DsIyhbA5p/ClXaQMKphCHo17NgIrhTBdafhAGfw8Mh0GsPjI4O0ytDpllQPBtMPwH1Z8Kd\\n+FAjPkTaCXHqw5b+0LoaHOoHX7+G1G2gUDKYkgJK3YGE/0K/r2H1d5CjGJxpDI1rQe+RkOFX+DXA\\nPB6HA2ehWU1oUBd6J4T1tyHyd7C3NWHR4YMAFRsPsk+F5NPh9i2o/QwGD4LqcWFAE1j6F4xqBi/y\\nwuLmcGI8YZi34Hv4/C50DL6WyWD2OBiaDnacI7xs9Y4EsfJCxGVQKh8hGKLsHmh5GDr+BGsfQ/Vp\\nECEpRKoCOTpDriNQYzzhDHy+1ZDmDHz1JeEQUI7VhD27C0eh23FoPximlobx0aBEXeh+G/I3hnvz\\n4cNxsC83VK1DCF6O2gMmBQrlJYgS9EbfwPfb4d4pqBENmpSCc28I8ShBF/uHDTA6CuHoddZh8EkX\\nSJIWCnaEO/fhqwCX8CHcaw4L98GN03DjJRRJAhOzQfKZcDgFvKsG1V5A/+1wcxe86QTRysHwndCj\\nOrTfC22+h56N4fc50D0NLFoOt2rBqrbwvhDMXQYRNhHyw+akgASLoF8BiJYRWt2AVN1gw6cwIDdk\\nbAa1h8LzQnApFsQeD/cbQ/8YsC0uHNsCU+9B+WXwaUp4/4RwUTTJGBjYGk4chi4FYGcVeN8XumyF\\nlQMhV0FoWRNaxYIV86DHJZizFa7thGRPYVALKFoWqgV0t6DIlQ/u9IclL6BJ4HT9B1uWwdgsEK8j\\n7EgLv5yG7Z/DxNlQJFhfKAc/JiLMd3aIDEc6QsxXsG4aFFgHXbLDsXOE34Gm66HIS8iXA/bcgypB\\nV3E0bLoMy59D3MOQ4h48/BMm94H8rSDnTMKgwrb3hPuV3ryGeR3h4m2olhk6DoOa66HPD/BjMkg+\\nA9asgRk7YWGACHsG5ZLA47HQ5Gf4Igd0yw5338HR7bB+PHz1McwvDV2DDsJKyNcbamyE34LeVjeY\\nsA26bYEmY6FI8GrJCycnQMKt8KgIzN0MfzyEdgth5miYVRPSD4RMieDBDbjXlhDWl30EZOgNS0ZA\\nqXJwogGc/QyWfwnXvyfE901pAvFjwcHVEC8brDwEQwrAgDUQ8WuIUhjmrIRVk2FVFfisIkTvCMej\\nQpSr0H0+zBgDMXLBo1WE9dQojeCntlD4GOx9CgkSw+UgBr4IVs2HQgvg6Y9w+itYNR3en4C1Z2Bc\\nH1hbDK7lgf5J4ZfG0LAibHsJZcZBu02QpSK8fAQNk0DCdIQI0/olYW0kKJsNGheCAxegb0IYVgQe\\nfATL/4WhGeHo+P/9xKYWhfdJ4Mfs8MV6mNqM8DrepxPsvgDjXsHGs/A0Fzy8BhlvQZKCMLIy1EkK\\nqTbClfVQOyt8dQk+qw+VMkLkRRC1EeyrDzNPQd0GkD3IQpWAxgMgUlHCI/BYALuLBY/mw7loECMC\\nVAy6YK1gc2D8XYQyMaF30AAKStENIVJkuFMfXt+FihOgdWe4Px12L4Bc82DyYPhpOWzfBd27EE4F\\nPykAHfPD9gACmQ+65YJJa6FwcRi7BwZlhPJjCbECQTcnVzLYlQHmBViT7FAmCsR9Bi/Lwal6MHAq\\nvF0P3+2CGI9hU2XYVhBafAQ5TkLJUfBpSei5BBIXh/XzoeRF6P8UZgfR+Fkw+zP46B8oERESvIdY\\nIyBOdkiaG7qtgeg3oNxiKNUUul2EzYWgwjT4dRv83AYSz4OJd2BtL0h3FvqCvV/AkK4QPSD3DCNk\\nra2PA7nzEl4d4maCyUfhZiqIcA8O1oM2OSDKUOi8DfpNhKlj4M7nkG4V4VJFouCKsAnyLIMbx2Fs\\nRJjWm3CWpFNmiLcEVjyEGXcgz49w8Rrh8G3CZjD4A8Ith5Zn4fN0sHgJnL9MuNWxoDFcqQvfDIba\\nX0OH4ZDsK6iSHFr8Dk+XwNgysCMxREwIvT6AV4mgY3HY8pgQmDwvKyEfa+cK6JYYNuyBZDeh20hY\\nVR32fA+5skP9iZA16D73h1v7IcvnUP47mJ0cEvaFWO+h/UIo+RjaHYA4xyDOOnjxCH69A8VOQcIq\\nUOkD+KcX4QBdxabwyyYoWgOirYe3qeHVARi3Fj4+AomqQf8AkpwB9hyBPcMIn+LpKsKmoHDwKczt\\nDYfeQrlt0GQoJLsIT7pAzTOQ/hVcGQC/1YPFHxI2/tafhbv3YcMEeHYbIn0EHS5BxfvwZBgc2gD7\\nLsDtBPAoMbQPnLGpUHI8bIsFiW5D/6PwIA8ciAsfBNWHNoRize+RYU8P2LMOXga/xZ2g8Cn4vS28\\njgAZ30H2KVD5R8LHWJJIUDIb7J8DPwckueBeUQu2r4EuK6B6Ufh2G+EEdaafiMjn5wmxcp/9Cb2H\\nQpGPYU19iLEcrpaE2YFc/xY2RoDb9+DSEEjWHjbfgla74YcgIhcHOnWBNdPhj9Jwey5k3Q4LdsKg\\nk9A96Db+CP0fQeSAjh0ZXm2GO4VhyIew/Dt4PwZyjoMtEaDuWRifAR7Hh6O7oFJOmDWHML/S7FvY\\n8jUcnQ2R40OiGoSu8OTYUOg+HCsDFydCwyLQ5BAMTQNlcsPX66FAL/jlClyoD8PzwoJPYFBc2DgT\\n9iSGBblh/204+xBGfUL4YQpg//k/hR8jQu2WkHMaLDsMLa7CiDLw1SnCD83OjZDoPkyaDbM2wRfV\\n4PpQmJQTJlyECSdgaB/Y8yt8cwS6tYabY+FRD7jYCn57DuUSQMPrkHwLofnytBQsigMbx0HSBNCm\\nEySsSagQdEgHk/6BnWDwVXg5AkpehgE3IHIDaDADLs+FTS/h1C5Y+x4GBPHkCVD/HszYQJj5m/Mf\\nJHkCT99AlpqwfxYcmAwTlsEfQ2BXVlieEK6dhL1doFVqOAi254G0e6HnY/g8EZz5FrrGh3aBKVCP\\nsN/a+Bqcnwt7g+huXEj4DqZ+A2dzwbPMMHw8xCsGr9LB7UeQ7z/IuwRiLiDsyNzuDBdiQ4mfwX7Y\\ntAly9IZpi+GT7dAmC2QvA8daww9fw9t4cC8aVLgLR4ZAgenQeRH8UxHWnYfvJsPRVRD/Q/ikJaHu\\n9W9OeFAWEmWH4zUhw0aIWg3i34RU30OCdbD/PZQoAN+UgiZT4U4viHcParSB6B9A77PwyS/w62K4\\nmw1+PAJNf4RGn8O/TWDmchiyC/4NbNNa8NcfcOEgvLkG/+6AuoNgdV7IOhdeFIb3/8GtZISYktzJ\\nYdUywozLgOOEM8CTT0GKYpD2OVyMQzianqcyNHkNvyWBv36B41Nhz3ZYOhgiPoH0/eG7VISXwqQ7\\n4EAF+KgebCsHeS5AlaBadBBedIa1qSFBYLMugLQzCbWrCumh0BxI2RGKpoSJDaDLvzDtICzOBDXP\\nQ9n4MGM1XGkNVf+BuOch6/dw5mdouxR61IC28+DkAzi0GWYFatBFaPE39N0ES/6GO39Aia5QogSs\\nrAaJrkGTAIbygBBbev8beBEVqkcgnIALNiQaxIMpX8B/aeFRI1g2C3othL5xYUwNWDkMioyAqIuh\\n4UUY0whWdCAcYJl+AMrmhFhVoWIC6FoNWsaFc2lh3k04Uxgm14FOhSB5e4iVCKL3gxzRoOcK+O9v\\niJMYGg2GV43g3W44PZNQMR2RA55th1vdoW0BqH0VZveCXusIcaM1GsCtB/B2GEwaQZhtylOPcHg7\\nkBKe1YH9haDgcNj8DCYlhGqvINEQ+LYbbKwIf3SD6QXgeX1I9ykUeAPbv4Da1SH9HKi4CIb8CMva\\nQPq+kCkpDC8K/y6AB1EJvZcg8ZmxPwxMBFOeEbb+M+WHS1FgWlKYFfhUf0PvmFDhPvy5DQrdgzTl\\niRii9Bd2hdVHYF4nqBZMUmyBlg9hVw/4MODDVoSk8eGf5JBlJSQoQJheCoZrHo6FC13h6jdQvDoM\\n2Q9JY8KQKYSXmA8uQ/wg3ZUJurSCbPuh0L/Qrj6sPg+3hsGl6PDBEfjsMkzvDXsD5k0laP4C9vaC\\nVuUIJ37/WA1dCsPuLFAkD7xqDNEiwMl80PiP//31PHkA02NDm1NwsDKsuQTxAkxAHfhzB+S/DjVe\\nwu2foFJbSFoMHr+BseBhAqjyCo70hqUXYc1uKD4GqvSHpvUIx0qTjoSz9WF/XpgyEqJXgnlb4b8r\\nMOtbuBMJzhSF1b8SQhyCTa7ZD6B9eqhbC1rfgBhDoWp/+KcVPEkO//wAn3WEVE/hbX6YXgE6J4Le\\n/WD9Z7BtHPSOAtlmw9lrMLgwbOgO9R5ArZwwqjD8NwkuJIWi+aDyPVixGaqlhswvYfkKqP8jDIgN\\nS+/D4/aENORps2DT9zAkF1wpA//Ggz9eEsrCdeJChM+gUCyY1g/+iAJ15sCR0pDkCDSfCc+6ExrK\\no1vDg88g3nrInRAGdoUC7eBAH6g+BdJlhhPgaD5oNwsmPYcu16H2PzCzLFRJBQvSwYHMsDtgMuWG\\n+f/CnxWg/UaImQb6zSCMqZZJDUNGEmbR1taErb3g1VUY9Br2VoUFf8L86hC5B1w4A+dOwrI0UCcR\\npMoHo9tBmaCIMADmRYFJe+BNN8IDqUZqiNgBOn8BFR/A+KVw+CyUywx93kHf+dBqNvwVHwZnhm+i\\nw2eDYMWXULoiPE4N7Z/DlmOwM7DPApByVYj6C3wRDVrUhPaZIe0ySBsF9lyHikegbCvIVQA+fAvV\\nG0DTnHAtmEY5BG9/heOzIV0nmPsC/k4Nj3fBt9lh3IfwRcDKmgcDxsKJBXBnGaRZCht7Ek5+He8P\\nv2WBPq/hqxrQ9zHkjg1FokGsnVCnEFSpBckLwIkYcLQVPCgDG9bBlapweRD0GwmZz8CQiFDyEdTb\\nBymDxu5jyDYGomyEI0MJiwXx10H5GpCnFvRKAD1HwKz58P4biBsJop6Fq8sh7iSodQoG7oLYeeDt\\nx9CjGHRJCNv2waKfYesI6JUUVvaDLg9geBTC9c9l3xJahyt+gfy5oHkkQiJUsaew/wDMfgXFOkOT\\nqzC/LlRvBr/lhN3NId0EwtZk0w9hdQbI+QHhPubRC9D7HRT/Er4rCz80gBOd4IMZULEEfL4BvjkB\\nm/dCoalwYjBMSA7L6kKZY4SN+0cfQZvsELUhFOgHMRvB56ug/UAY8hb+qk24z5i4J7yuDwn/g6St\\noGJxODEGLvaBWn0JK0RFfoa+T+H4Chg8FbolhdeVYND3sPI8rAjQoxth31V4fxQ+C0JHTwmRIomj\\nQufoUG42zJ0LN/NCzDtw+wUMyg69lsCFRfD5WXhTGVyCDNkha3fIfxo6ZSDkIJY9Bhfrw5wd8PVp\\n+Ls45LoOn2WDz0pD5mhEoGAgM0aHHMdh8CzCVs7QmzBsLcw8AXPyQvo4cO8arAiSECPh4p/Q8Gco\\n8AtE7AVL1kKMNtCpHUSZAoMbwoynsPMYfP0CynWCnF9D/2PwLCUcngilH0LTt5DyOjRLBn0D2ME5\\nuJ0LIr6BSZ9AlH/hx7QwcxuU3wXfBV2AYVBxEqyfRujsbroClUpAs5fQZg8sSwyXHsMnQcg6D3z1\\nFuoWhuGvCUv4q5JAo+IQ4QD8cBKabYVI86BuUJfNDmuOwIPi8MMNeD4Weu+HDZ1ga3DRvAbDUkOZ\\n76FEdzgbCxI+hIprINN1+OY0xCkIJyNAnLtQegfhltZfsSHpQihxCOZ/ArHewfQG8F9gCS2F9lPg\\ny6SQvBBsuAz+hJKt4PEj6H8OuqQlXBXcehFq9ofdCeD7WDDwLfw9Curfh8EZIe1RaBIH7iSBTHeg\\negnYkg86HoZ47SFOZPj4P5jxC+wuDPViQ9zvofddGHsder6Cm0lgdR7YGLSf5sB3u6HkFRgUDwr8\\nCPH7QOua8HcsKH+WEOQYZQV8Ox3GL4fdmeBsIyjeAUbGh6d3IGtDGFmFEGvSpxsUugwZi0PS2HDv\\nPvT5mjD7NWQsTMwOJ0ZA0keEKZwgcN3yY2g/HVomhhonoWkxWHwAVt2CM8uhzw74Jz8kPQs/DYdm\\ngS27BSqUgJJ14NEVSFkOkqSBKTkgTWDxtIbjxyDjMqhfC2qWhP3V4VVHwuhC5qPwvjk0uQSvosPO\\nl1CsFbRsC0vfwvxB8GANXPsULtSGXGdg4SlI1Qa+Dn5iWSHzUkiVBDI0hxJ74Dn48kNIXgGq5IDR\\nP8GRZVDzDTx7Dy9+gRip4NJmeNcanqeCagPgs9bQZihsHAVzNsOHdwg70QvyQI09cKIYTJ4Gc8tC\\nhxLwcXU4XA/uFYE+92HkOcL12LTv4cYfcPxf6Bo8m/tDyQjwV0coXAJe5oWW0aFjTmhWBp5+D/tS\\nwK2usKgUTGoGb0rCmgRw/CT0XghnV0GxqlAuCDCuJywtPYsIRcdD1qB1/hZuZIYmi6D9Hjj6DBIM\\ngz86Qcwq8HNJuDnif/9msi+GzAF1ryi0/BHOdIPiGeHFNXj5AaFyFqcaVPqHsDk7dgihRjJ1Naz/\\nF47fhmOLocgx+CQ/7A0uZAVg7kzINRx2RIVtxwmtzxMToWhNSPcHpKgJ8WtAmqwwLQCXtIfUO2Hd\\nMBi6BOK2ge9eQf2ckPxnmDgWruWFFxlgfQ1YkhsWn4Pvm8C5QpCsBawJELvB134x3MwE6R5B1lfQ\\nfyn8FQcSnoGttSBJcsL12EMBKXAvbJgE82fBd4ERWRHiBaidCbA1qK+Nhr8CEHRNmHwHPlkA/8SH\\nnBlhXgRCwMSZj+FJU3jeD9I3h5e/QY9xsOQsdJ4L1abDt4kh/Q8wuSJMvQWrK0HPyBAtAezpAHeS\\nw4JmUL8TfHsR1jWGp3Wg+WhY9yn0zwazC0DGiEQi3Q7Ymw465yO8UqxtBuXWEnLe9yWBVxtg7lAo\\nEBHqFYWjpSHXJujTFDoEFOP/oNVdGLIVRqaC6EEHIQHU+5eQCDLnJrT8Cy7EgKoXoe5yiPYT1H8H\\nLS5C4eewewX8PhEm7IK4RwhVnCQdodABSLgb/joOD9LCvW5wJDlMiQQtqkOndPB1R7hzGTbmIOzR\\nbCwM229BnhuwtA68u0/YZmpWGYqfhz8ywOtSsCEj5H8G0UpD2xrwLB4s6gAFasKX/0C1NyAt7I4G\\nC4bDonPQ/Uv4+TGkKw0LWsOMJISM8he94dEEKLwUYn4CS3PAor8h8TL46g3cmAblu0HMbHB4NkzP\\nDikD2NoVyBMdWnwOVzLDnEHQ6kvokwl+yA+3Z8GLz+Crv2B/PRjUBQ58DP8OhJOdIX90mLAeBm2F\\n7HOhczVY2AqGb4BJY6HlZFgxGD6aCJ8mgJ+XQ8lN0KYV1MlDmDKZuRKqL4KxU+HdDEINI3NUGNQQ\\n+j6HXMlhcinYHQk+iAmFi0KyU9AgiLXugJJTYOcvcL0qZFgIVX+CGl3gaXVofBiuTYIzpaBBDTic\\nACIF1e4ksK0o/PAMflkJk3vAs5/wf6jGzC/gxjGYcgKSNIOPDkOEgOzyDGo+gHYBBjMdnC0BmzdD\\ntj4w6xxULgMbN0HlPXD2CuEiW51cUAj0Crqiy+FwbmgUGzJ2gy6LIc4l2FIPEv8AhS5BjxLQJTN0\\nqwTv08HMoOC9A9L0hZwxofqvMKEl9LsFTw/D2SBGvQJ6FYFVx6D7Ixi1BtrvgHIv4b/OUOAFLK4B\\nsxvCirywFtx7AXHbwokycD0foXX1ZgCUug0rJsDFmNDtYzi+FV7dggfrYXt/wnGh6BUgz2RouQH6\\nzYeon8OrsdCgF1SODt81gcRBYysfPN0LX9Qg1C2S94AZuyD1XDgUE8o1gauB/p0HJqwi3G+IVA0+\\nbQOJ2kDK7+CDj2DcQvgwLvwWMOHuwJFY0C3AwDaB1cmgRVuYPw4aj4OoFaH3cpj+BwyPDmsLwtJy\\nUGkXXA/ISfMhRVMoWQGirIWhc2HEMejwF8wtAm++hN/XEC5PTLgJ1evBqTIwszHsPgRLikC2VlCv\\nACweBXG7QvWChE/0YJDtp9MwqARMXAVJZkDCPIR2cOoVkPkRXMwCV1rC5ED3OgAHm0ONIvDtOpiX\\nA4bFhC2RIfs+QtLkou7wbAakqgCvtkOTO7DwAhwrCNtHQZGHkPQp7B4BLQLqYXXo0gia/QPX+8Bv\\n9yBiOuj8A3ToD22ywaKU8MMFaN8MVreCyz0Ip5kuV4LxbyBFa4i5nnAFJHVkKDARng2Hn5LA7ttQ\\n/i0c+R3WtYNkWaH4L3D1OowoChNiw9WLUDUv4WrL+NzQpQXMTQRts0GMyBAzPmGYvXAQsHkPj5JD\\n7yXwMD2czA2XEsPzM7C5ABRZDLWCmMQpiLgW1r4iTGWN+gvOX4fjPYjEpt2w/QhMvQhzZsKNYATm\\nPCE44LcuEO8unCgHU+bApnFQMCt0Cv5LI8KK44SHUD6oa44ivO588iXcSwMPF0KUb2BLX7hzD3o8\\nhHlD4FZsmLgHxv8EORPBhKbQcyAsTgf1X8P5ppBnOPRpD3eCRmE6GHUFYgRkmkB2bg3XOsP2axDr\\nDrw+B7WzwMv3sCyoVQfl+UuQrQS0Ww6RJsOAZbB1EbzZAr+PJ6w0758OQ1bAjD4wtC3EKgQpexKa\\nXK97E6bQgpnMwE3/+x84nBSaJuL/Y9xfhCap4PdpMLYZ5C8MRwdAxs1wpAhkP0oYag5wdjd+g5hx\\noXAXWFYPbu2FVF9Awo1Q8yPov5uwYHypM3zaDbIkIeRKH1sIaQdD7/uwpBUUTw/tUsOlzyFzJ0hQ\\nD2bnhDFfQeO2hFtvH+WE/nVgzWvI9gpG/kMoJtcoChFvwKa/IP9YmLIIJj6C+TvgTRXY+gJOvIKc\\nf8HbXnCmKoyeDzluwOeDYFcjyFcZWkeBfY9g5y0YkAsyfgibM8GI1tB4LAzOAeu/hLYRoWI5aLEP\\nFk6ANw0JX4T/tYdHn0CHsVCkMmSsS1jJPhEbvs9NyICJfxf+fgVzLkC0JVDoLcw8DYm3Q9K98L4Y\\nYSRg/UTYmByu7CXMNPz7J5zoDNHLQLVPCEO1NQpCiYMwqzJcPAWDX8OYtvBFavjqCHx7FjY3JdSw\\n13xDSH6qdAhmz4EmfeD4cmj2AuKVhQKNYc3f0KYoIa9oaF3CfmWkVFA2BYyYBLlnwNvXsKciZPoa\\nZkWHr/+ETTMIueeze0DpV4SrlCmbE2rV0QdBtJMQ+QFEygN/XINII2FcSrg5lzB/tqwCRL0Es4pD\\nnVvQMD0cCsCnU6B1oLIcgYdVCK8as/fDjj6EKkJwwFyYDesmQNxXMCI7pDtKuIcRdL0LJoTKXWFx\\nCzj0JQz6Efoth4hPYXgbaB8HYjaBeD9An1Lw9zvI/xG0fwjXqsG1ytBqNCwPmECD4HEhONkHZk6E\\nlM8hUhwokgK6ZoKilwit52KHIeNtwi9ecDq8bQGrAyO+HuQPQhrZIXtryHgOuiaEkmOg8/+v43Y2\\nEmTMBC37QeYYML8S1C4I8X6DPgHYMyssXg9t90P2eNAiFhxqAu/+gMP3IXbw/A60tOkwugkhY33q\\nKhhxBvZlhn2DIG9UyJYK3o6FD7uC+lA+IqQKbOgScKExITHxzCzovhGynIWUFWHuG4jfDS72hpsJ\\nYMZZSFyaUDLYkBBigvhd4VoxyJMCvvwLBn4GSbJAgwAgkhLuLofNQyDxRKj0Cyx9AFkvw4wsMLMM\\nnFsKx0fBjXWQrit8EyhDZ2HbFujckXBSbOivhL5Tk8WwIDUUfwfVUkH/SYR4oHJ/Qa4P4cYGqJYP\\nCt2FWlXg8E3oGrCsesD4+JBiHJwpSJgJflYVvogCu5pB5OAs2wzHb0CdF0Si+xWYNh/ipoe+Ad0h\\nKzTfA7m+hyobYFgdwmmaEb9Bjb1wvxcsjg9JW0D/jPB0AhSIACt2wopZkPYKpF4K34GPK8DjL6Bk\\nHMLZ1709YVduSBAcda1gdyXosQO2d4FkhwnZGB/tgzET4dQHsL4/9LrJ/4lBlnwGKZNA1Vnw+Cys\\nzwlpK8PN6LCuGvQJYuYLoEZwn40HiYI0WF24FZ1wXOLDZnBlITT4B76LRHi0LK0GeX6G5bXh/gSY\\n+Rf8+haePIGpZyHjdLhxFfb3g4gRYPxeGJwSYrWBaylgRTqYWhUe7CAs/AcIjIw/QYecUHcLjFsM\\nv1WGUmugYVt4NQKKdoek1+Grz+HzxISaZfJPYFwLuFIfTIYOGSDRR9ByFDReCYl2QbTqsLMh1HsP\\nZzNA/SiEg8R/bick9AS/SLcawKpxhMiJc42h3EkYOQfmfAQfN4VSD2FxXnj0O2QcBfFWQ5NmUC8h\\n/Pcp4YZdjp/hzHH4rwycGgdP4kGMHFA9CrwLBOf4MHcX5PseDg2CCuugVUpCotXjO3CvFAz7CQp9\\nDX2jwr4gpxIZqseBskuhchx4VhiipIXmX8O8djAhKtRNA62yQoVMsOgp9AvITz/CkMHQejVUjgF1\\n78LISlCiNFxbDAUHQ4Jp8LIdpAxq9mvhbT5oGpST68GqmBDxLMx+CI9mEMaoA3LYL58RTlPXTQ4z\\nq8P4g/A6iPCPgRqVYFEBGDsAZgUs8kSwugVkawBPMsJHReBMZMj/JzRKDGWD47wF7EwMeR7A7xeg\\n1SjY/yUU/ZVQj3y/GTJ1IlyDiB/QvXdDusaw7THhokOckfAqKyFcdMhkWP01lNgBX/SBVnvhdm04\\nHRuur4V8h6F+NRiQHfZFgorBg6oSdNkFbRbD5o7wpiDUmAw9y0KdytArsCnLwcxDsCgfYVqr9kE4\\nFgMWfwTTU0CTxzBiG6RcCI/OEU7L31tIyMiOfhGaLyJ8ipy4BZ3vQPqWhCNax36EPUHmrAvU+wVS\\nVIc3OSBqDbjZAPqXh7RzYEg7GJ4OBsWGXEHndDd8kgi2voLfC8DSj6HQCnAHSgSH5Ur4/iFk6gBd\\nM8PQTfBxPlg0BRrvhZtfQ9T7kPo/wnmlRhNhYhuIfR72tIcDQXc7gMf2hU82Q5rUsDEePPwOzneG\\nzT/DjJRQrD+hshglA5yP8L+/l4HfwYQO8E83+CQob+2B+Cmgf2NoFg+6j4c1d2HrMCj2Aj4NQuVN\\nYGB0KNoXhueA357C9gdw7i9IHKySlIPq+6FYR9iVEh6uhLbP4OTHsDU/LCxOmHYa9xRiTYT956Fv\\nfyhUHl7nhqx74VJmaPsV9Au4UwhRJqULQ9bUUKQJtCsL/62FsqWhw35I/htM+RLmHYTh9SFDA5h7\\nDzbVhz65CS/WDWJA7m7Q9xPC1ddnm+DiaJgzGj7cBd2WQ9LE8GkswnpHyoZQvhW0iwZZfiYidd7C\\nxUXQ6Sn8WQC+bQ+Jq0PT2/DLcaj3ApbFgRqbIdZ3EG0K3G8IJaNBwQ+h2DqY2RSq7IOBz2HVUMJg\\n49Z3cG4grB4KQxLC5n5w7gnhjOvzPPD+IuRrCznbQ6n3UCMP9I4GbfNB6gWwKi0cPQA/7oKv30Ob\\n7dD+b0Lh8dvS8EdHGFYcvu0H8kC82NDjL3h/BA4Gb6OMhEM0o/LDoX3QYiOMOQNNUsCMf+BsFai3\\nHzZ+AOczQpokUOox3I8Mv06DZlkgWT64+zMczAyJqkDZQ4S8+44BjawDZBxJiJz44QSc3wH53kCG\\n1/CmNzy+Aisqw+Dc8DIutCgKCXpC7pSwYyz8VgjqlYGMx6Hpd4Rl/krRIHsJGLETUuSG7X9DtMEw\\nrCy8awilm0GMBjAuJrxJDbdyQIt/oFFpwtWtaS1hUzeosRRelIEzRyB7bqjfD2q1h9FBrzA/JKoE\\npRfBiDeQM0hlZYUoBWHie6jbHqZGgS7NCK/XxT6EEpXgwkDYfgkylYGsuwnne6PsgSez4Y/CMC3A\\nEIyHy/9B7V4wKBas/R4u7oImSeD+I4jfDqY9g5WJYfJx2LkGoswDESHaf5A1Emw6A4nmwtoNUP8V\\nFCoJO7bDskvQfxZkWAVL+kLF6lB0AvzxDSSODGWaw/Ty8MspQqzDknWEnLOneWHWBbj/BqLkhx3T\\nIPdvEH8t/FcQ0l+HLwIk7DOocJ3Qwi4YJDVB5grwZXDhOAI3A2TJHijZB7L8ChmiQLkM8DIVxCsF\\njXJAnvewry7kywM/VCRcJpg1inCMvE0T+OERtG4ER3tD9Amw+T3U/htuZ4O4lWFcYVj/NaTrAbPi\\nQr+xsDmI8VaDUjXg81FwJogfFIZdU+FQFEgbCyaBl0ehTBGI9w4WBC3XnnA4OB4WQN9vCBXNX/+D\\n8V0haW+oPxRqdYIV30DXMVChM9RuB5vrwZZdhN3MF3ehxk5IuQHeRyLse7aPACUjE7YCd1+FxTGh\\nbHPI+B7SbYMiF2Hr9zD/JGyPAOeiw6qi8OtX8O0MOJgMet6Gw5/BmnlwsCv03AC5k8HMIrDpBlRc\\nQqie/vEBIZ0oUzVYuxny/AQ3KsGJ1zCqDJSsBOfuEC54Ps8IFy/B9HrwRXx4+hxSpiGEWt8eB9WH\\nw+Vn0CEVlNsKI1pBmwCROh0iRIWVF+HffvDph4QoihkHoF0TKFAVbn8Nm5dA88VwbBB8ugOqvoer\\nuSFaKjjzhDD0HYTlU/4G84/BP1sJdzgSb4ZfKhKiN8YPg0H14f5rwuTiui/haGeYGo3wnFpeEHoV\\nhVo9IdoruP8eul+Fo0F/dirhxPW9FLA5AD63h+GzIEUTmHgezv0Gp69Bui8h1Xko1wWaDCQsUb0N\\n/kTF4c0HkD8p4UjOxNWQPC7Mnwtdy0P7SxBzw/9+2rFnQNPZcO0a/DOfEMMbLEkM2wPbDhHiihKk\\nh397EomTowl/hWpvhx9qE/JgdhQnDNiOLEEInwzI3RXjEC6rH/8SPj4OO5pD4m+h2xhCykXuaTDm\\nBHxZCCbUhKJ5YfIC+OMpbEgEGacRFvsbBamIeNBnJTTNDSnbQP3ycD0z4VTOmAlQtTvkjQxXPoHx\\nI2DVETjcjZATU20T1NgAP+SFw5/DzJsw9xREHwDxVsGNeIQc7RklIH8biJcaPsgOp8vAolRQ/D5E\\nTQYp/oYOh6D4VRjyDk7+CJcbwYNVkOoExKsIPwYB2NpQsw1UAHuKQL3TsGI3XChNOCJ7+ynsyA85\\nDhEOV28KOnG54V0t+DbIG+WFGV9A0e+hS3fYdBZ+nQq5K8H2oDz/H6ExUeoWvAoM5TFw8ChsOw2z\\nAuzbdThXAz6+TcjATfkvHBsK3sLs0lAnoCfXhgsroNIR2LkefnkIc4KPeza4lQHe5oQSTyD/UJj5\\nPST9HG4Mh9KrYEFaeLIfou2GHnVhcwJo3xMuXoSvBkP51pBlNSFuMUE8iNaCcCXwXkN4+ww6toAs\\nAwmDpYnPEgIOyvwAL19AqQnQfDKkfw4vs0L1iLCyKWx/BjFWQ4qt8FFiaDIR2kSCvrmgZTz4uCwU\\nuwlLekDZP6BeW0gRgTBvdzErPH8L6YIUVxvofAsyX4U+jQgjorEuQ4oy8N1CeF0ZJt4nDA53KAl/\\nZoVzZaDUTzA8N/zZDWLPhO+7QI8isLUJ3AxacusJW3tBArLPYai7CoocgTxN4HBg2feBqwNgZpCA\\nzAMftYLW8yHzDog4Hjr/CxGKw9bL0OodXK0JZx/AvM2wOS687AlfnoGG/eFiX9iVAiI+hPij4Ocn\\ncGknPOgJ759Dotcwdjm8fg+VtkC5A/DwPFScDdkrQpla8DoN1J0Ob5pBwlUQ8SconwaOJ4ENu2Dy\\nfbh1BYqfhP4HodwtQpTo+DKQ5TWhPbRsHQweAsOPQ/VXsLo6nPkA9ryGSAVh9iSY3gqyt4Lv80HV\\nufBBDJg7Bzp+Bi/vwuu5hJWgpadgyWlYnQuGgRJ9YXRLWHQP6vSB6wFtbhlkKAZ//AdlF8OobbBx\\nEowKFPGqUCM7VAl0/cSw4lfo2QYq34LJyWBGoM1XgdX7YOM5uLYA9oyHvtMI+XlN8kPDzyHhXmgQ\\nDc69gA4xINYBeJqIENmwsjP8G/TiN8GkclDmClRrCnsiQfok0Gk95IsAM1tD6zxwLBJ8FJDWG0CV\\nQdA3Hww8AMn7wLkYsHIa1LoJhZdD/V/g4lmotB66poBIXeH7rbBjE9w4B1cqQcl7hOCGMuvhXF9C\\nAHXfrjDnR7hbC269hg0rYetxGHIbvgwgxp9C7xdw7hDEHgTTnsOc2zD4KXz6KcT7CJ79B5V7Qexo\\nUHsTPArEl4gQ+yMY9hd8NAdWvYQWV2BP4Nt8DHFmQ+fLcHARpL4BCS/BjvXwXy0o9xyq9IK6sWDT\\nORh1G0ZHgkSjocBLhECEyg/gfRP4OSNh4bNIAfi4NqyPC7ViQ5ygj3MbRmyBBlcIwf9pq8GHm6Hv\\nMIg4G4YGL5I68D4BfDkMrmSELJsh8y2IGLwg98Kw4KWYErY0gG9KQ7t80Go4fDgRSgWQ0jcweyMh\\nX7hJJ1jaEfJdh+xFIe9wwqr5zeGw8QGMqAZrisGtlfDtFvj7MUxqB39HgFNNYdVc6HkcEkaGZxVg\\n+FYYGx32pYa9aWBCNzhfE8rehZhz4bPecGU0HP8FntWAVVngp0WQ4lNYUwf6RoKqu2D/IrhbDPo3\\nAGNAPOg6Cyb2g0RZCUdAg7dXye8h1hB4nxUWVYcex+FsZvjuIvQIbJf+ULscVHtMOEuyIwNcOwtt\\nPoOZUaF0EE4cAxW/glaJINlpGBwVamWD56cg6WRCraLyFTh/FY79STh9vfMdpFgAHS/B7JfQqAMU\\nDug79+FpAWhxnHDbLm06eBIDvpgLh+fDhi9gd6BPBEy1xZCyNMRIAr9WgXf1oegYSFcLDp+HHUFy\\nsSc0zQSjEkKkqbCrH5x+DtnqwfQnUPYVoR3zIAshEOHiOCibGR6XgKwJoOpAyP0acuSEyAXhfW9I\\n2gO+ywlLt8O+EnBzD6z9HAqXgpWZ4OdrULIb4dH+T05Y9gSKdYfe8+D3z2H019AxOMCWwflysHgk\\ntFsGE19Bv5twpyJ8dxiK/w5VGkL8jFC5O8xbB/USw6aNsKgm/BvkKYN2TweIXQcaVIVj+yDzc9gw\\nEr48SNjwHR8XPq8Mh5/AyatQ9DNou5Fwby57LfjpR9hfBZ58AAVvEloDpYJyTBRI8wU0nA9lk8PN\\nCPDNYjhYB/Ich1sjYeZ2SNsLzpWCAsGRmR529iGcfOk0Dzash8xjIMVO2BV08V4TblA+XgdL9sOT\\na5C8LiycB1luQNbMhJNQTS7D1gcQ+x94fBeuzIXxiSFtPTiWFn5YTZhWzF4KTqaG34LmVATIFh9S\\nXIXGv8OfNUE6mHoAssSHqjkhWyZY8hK+CsCSp2HLJvj2BTxPC5nywZtvIEuAkygJz6rAjYqQKhuh\\nHVZhDmxrQ/j7NeAbmHgC+ueDGCOgaVpoFDzDfoD5T2HJahhRF3b1gq9bw7vVhDz0a2BMUziRGOZu\\nhyLVoFNv6HoGpvYijED0jwtVpkGFbdD+GFT5kXBTb3rQDewO/ySAXeOgTGzoWAqGpISN1WF6UWj9\\nDs4ehzSfQf6mEPcg4SLqshnwzVIYGBDMd0KW+TD1LbQK8r5zIeN2iBkdfn4HqXrDs2tw+EPC/YOC\\n5wj9qws14PESeDYHegSsuK4QIw1sKQ97TxOm7mbeJew+N/kGvosLVy8TbqTO2wgLPoMe26HBA3iX\\nHB7WItwaXnweqqSHnCdhxl6Y+iMcbwenu0COODBzHuwZAS/Xwu35hPWdbluhWktIHQN65YKn++DQ\\nUyhxHSacIVTvKvWGY+vgdVTw9QKodBCW54M+byFbZ0jUEeIlhOYjYU0uOHERbjeGmNegRkV4EBl+\\njgy11kOptdAm4AmtJBwTfTITIgUQh5kw6C1MPQev4hOK8EVqQPSfoERNyD0C+l2AaM0Ibb6RU+GH\\n0TDvKmHKoedJGD8PVnSGopNh4yz4NxMkOgwlTsDdlYTTHAdvE05dVg6UpHXwIAekjgjrbsH58YSq\\nw4SgKVaRsBqdryHkHQ0VvoLMi2F/cYg4HTJPhegLoXRLuHMQBi6CAhcJSd9dJsPkzLD1HtwoCwde\\nQYQ4hNzhxGkg9QnYuBzaN4TUu2HPN1A/Ify1D+pVhPx3YUtTaBIV8maAyEvhu21QNDpk/RK0gyY1\\nYPktKFwS+vaGj+NCgymQNxbhvHHAp7mzFDYWI5SXT96Cj1cSakIlNsPsKYRjqAuKws5l8PMciFMe\\nateBp38Txoo//ghedIcP00Pqg4TLYgHdpHSgEAyEJ+dgaxRoMgyGR4YzY6BLN3iYCBb/DPVaw8m+\\nhJXsfdegQzSougY614Tun8OKzHC4NKGlO7AWDD4Iqx9C9iSQL+jQlYABR2FiV2icH/ocgqv1IUo2\\niL4VUv0OsQrA9ymgZHd4kA5mRoRMGeFZTFi4EPqshV+aQsWYhB26P86A6zAoBeEU+vYnUPA2NH4M\\nR67A1JeQZhJcSQmJj8LbIPsVXKCjQb/RhI+ZpLMg4iaYeA1yNIf5f0PMVPDLfkh5EhpNgo5T4FJu\\nqBqQcn6HTwpC/WCb4Wv4rTGk2Qtr60OaV4R7Ax/dgZqp4GU9aBQTWh2COMngRlPYMgEWlYRH12Fr\\ncji4B1a0h8xRoHBbKJIPHgdk/EGQNgvsTgtNKkPqu/BJgEVICimrQOy4kOhzyPoUSpaBT4Le9xH4\\nIg8caQ6LfyVEYibrC4uvQ59lcPI+FLgC7QrB7Lvw6ktY0hYe94N1D+HbxdC9DlwKGqPZYFROwtbV\\nkj2w/wuo0AwyBl25aND/OBTYCo9+hR/GQ/nfYPpF6J0P5gyFTs8gchZYlhIK7oDHB6F6asgyHrJd\\nhkjZYPQrOBoT5o2DAX/ChU6Q71cYlhMSg8qdoX4dmPU5JC0FZzbBuOdwcjJsDvJnMSDhp9A4LmHv\\n8kBeWL4KBoyGTx8QIm1jjYXk9+DIh7DwHTTNQ9g9rPkQGt6D44dhz3dwtAtMeQPpKhNS7oKdhtt7\\noOxJGBGIET/BtYEQMT2UDrSrOhC1KDTpCynbQv9MUDsHnCsNv2eG7m/g8miYVhtapoFmU2HWWbh3\\nAE6XhetXoMISmFYefm0Jj4OL11Ao/yusSgOf/QWlXxKuCv6eAd79B60/hu+uQ6EHkGwgPH4B53+A\\nIqsgVy1oVRnWjSA8eQMUcOEK8NcjmJsHGu6GHfehWBVCffrfjVDqDJQaDRV7Q8lEkGQ47N4J7x5D\\nghpw5QZMzAAp90DPSnC+OmRvC3Wrw9EsYGxGGBMUXJcQ7p0NSg4tOkPVLHDoPdxpB8mTEkIvIzSG\\n9rmhyk6YHhAs1kKqEZAlBpQ+A99MhaFN4MAh6HANErWEXOXg9BWI9g4Ov4Gtz6BQPCgcCzIEdtgH\\nMGgkVCwJ71dCrJow+AzkLg0va8H8KYQkpFszod6P8OwEFDsCtd9DxGPQ5gCsCxSdjLAsPlScBikD\\nbeAIjO0HnX6FptkJDce6v0P1k3C7F3T6C9YHL7nr0CgrJEwCMWfBxptwdgS87QCzV0DGCnCnGsze\\nDEviQrQaUHwj4WDwoI8JhwuCxfvhQRRxFSTMAC2DoYlhhDTh4O2bYA0sagoflIE5DWD/VGifDlLP\\nh5E1IOpnUD0SnNwHkzpAowEwZTj8OQDO7IYntWHBbMLS+y9RIMZ0Ql3qbHuokw0SRCe8vL6+ByMK\\nQtr20DAR/JET7j6H7b9Bin6w6DZsmA9H9kPHBtDrLEy/BxPSw+EecHUflN8KXdPDo7NwJAIUuUk4\\nuZo7YJ2/hR1HoHIFGLEV2t6E+4Ph6GtIFQVizYVcdyBVS7h/D5J3hZIVYWFQeM4NST+AaBfh1mWo\\nfQRm9oWBMSDbAMi3Er7+DSJfhyQx4EUX+H4IJAyYT3mhyD+QIsj83YY08aF6XfiuCtTpAB+dhM6r\\noPsYqI5QA24VESovhhxv4NRv8GwNFHgMp4PMZXMY8jEkmgjp8kHB7+F8NJhZFEaOh/5HoEdTwkTU\\nmw1QrDV8VZVwmaBnfqgyHY4O/N+/nHNxYOBZ2LMRmueG5uegQtARywo3I8KpCPDHDVixGJYlgxPX\\nYFp7KL8GlmeCVmnh7nnIdRKuPoRRz+H0NGiYEjpFgNYxYWMe6NMAbrSCeDEh/jyYnpbQ+sn0B7xc\\nQJj4TLoTGjaHS79Bhobw7juYWggS/gBxqhL2izsUg35Ba+xbaHESohSCd8vgYmBN9oFlp+HTsrDo\\nPuEq4tVoUKIVlEoKPYdAx29gARhdCFItJKy4T5oI8XoS9hnnfwjpviIcX6/aFWYF9tMpiLCIsO7Q\\noRes6w5Du8ClDNCzNuRMAFHzw4UlMDQBdDwFG5LDteswZhPEOgeHAmvvNowNOnfR4EEx2JcBMtyE\\nw1nhk7owsghsCXyADHBsJiQK2Pfr4dVeiPgPTFsNi4pCihYQMy/czQT/VoDelyHVNoj6M8xKCRHL\\nwrp9hICJIz/D2b2QdAPU7gFFe8D6INp/GWoGX4DCUPVLSHANSl+FAncgRSNY1R/K/Aa/VIN9+6FC\\n8HVtA00+h5bbYEtS+Kc1JAVdS0LSPvA0NdRrCeOuw5m/4MRW6N4T/qoC2bfCnFfQ9BbsrwQTNsOt\\nOHC1LHzQCTomhupJIM9OmN8U7r+DMv8QYlfbnYAXF2H4B/CyA0zdCDfrQdmaUDEJvEkKc/tDj8fQ\\nNSt0eA2/xYdqlSDZF4RQ0+nb4EjwRP8TkjWEDNEgcV4iM24SVKgOMaNCtxKQfBy0/womfwgnF8Cx\\nVHCqA+HR1S4LRKoAw4bAo85QJz38mYFwrSwADdS+BT/ehwmnYNcSeBH0yzLAF7Gg0Ei4kRTi34AP\\nWsD5CZA+GeR8TjiU0So4/j8kZLv3u0v4Lg8mhBNcgdFXoF92eHsU7syDv36Cv76D4ZUhbgOoERly\\nBNjME7CzIPw0DPokhxsDoclCWJgWVqeB8iPg1F549hampYLlCeDeJmhfF+YchkeZoU1gufaDVqVh\\n8yqIfI+w/P9zZUjXlvBKNLs1fLATJuaHD/LAvmmw8w4kfA6zCsGLn2BVTfjkFnwWaFdnYV8byFiF\\n8HP53wr4eDrcmgcTc8K3a6HeGmiWFtK9g1yzIENswumbD7rDkUQwJD4hPLBBb/hmB7RcD9dzQI4K\\nkOkBpNsKdz+AHbkJ2381zsKsdfAoDyRMCVHLE2L0SmYnHECNWgZ2roIEq2FSkBqJDO1+gOVPofc3\\nkKs5YcxzdCPI8wyG/wu3ysCBCPCwD3R8A/unQPMxMDYaRD4Gt1tC8+Pw03eQ9yFUTwjJa8GT3wkR\\nrG8zQq4ukP0UlIoBa44SQnEn7oRrqWDXbpj4G5z8Hbalhh01YeE6SJMIctSEOx/Dt52gzjzCxbGu\\n9WBacGH6i1BFjvgW0g6Bi5sg6hr46A0MHAmzExHOkrwZQ9g43jcZvlgMJ/6GUoshxjLIUQ9inoek\\nn8DlkYQHao5JhONCcQfCyL/h010w6hBMDajK6eHCFsjRHw4MgP/eQZO0EKcFjM0LyZtCj8XQeD/8\\nPAyONSdM7H2xBKa3hcsTIF9/6FcKPvoOvjgDn6SD0Smh+BAo8Tec6EpYQCkagCTOwzd1IfJdiLQC\\nTvwJU7pD6hqQMBocOgtLFsLj9HC1CiTbBZsywcaXcLgvFEgN7f6G3AngzSYoWhjGFYebdyF/cDgt\\nhn2bYXpZ2F4CdqSHIs2gxWF4F2hFNeBEE/i7L3y0Eaa/huzfwweZCLOhKRNApY9h2HXCIeF5VWH7\\nGfioBTwrBaMaE17Efy4K11/Bu3NwqjyUywktbsO2E7BuJmzvCReKwdA9UH0L1L4BkztAy1hQog4U\\n+RceNIXmY2HCf9ArwO0eh1xz4cYruDcWxnWHSVEgaxN4nBlS9IfijWFkajizA9ofgI8OwP1kMDsb\\nFH0NlfND5ZyQdy6hmdtoBWHUIX0EuNif8AJdaB3srA2nGkC7EZA5BRQ6CbFeQN/AYF0FZzfAkT8h\\n82ooVYxwK3ZfH7jSAvKMh/0p4W12eD0YRvWAjENh5UgoOIYQWttyE/xZFxolhyMHYP1mWPQAbi+A\\nkbehyjLI9hhi94E5T+HuXqicBX6ehv9T049Ug2S1YPEXkP5DKB9kyG5Bu9xweSUU6ARnfodPD8Cf\\nTaDUBTj4J5Q+Dn81goPPIfpq2LMQYvWBHiPgw5WEhITFZaHUVNhwGBoegaJfECkko7SvDGN2w6LV\\n8O8yOFYK6hWH9o+gcgC6XAwpDkL5AlAiNiGUMnoQc9sPk5JD+fmEEmLRdhB3IkyLCPtWQ6V90DIZ\\nJH8Cl7vDDzmhXSAXbyIce+kENl2AhkthwPcQ73c4dhmqNIWjT6FAXxjbEx73gEMvIPFY+DUSbKwH\\nV9rD2ngwKRkcWAlf3ITTcyDGJrgZEzpMg3PXCEm4AzdDmy3QfR38+Qk0nA6VB8DhlHCmMWElNX1c\\n6NgTjieAk+DL36HWJkgfkKzPQoSq0HMhXM0G/+yEnYlg8GyIuQXqp4CVB+FqVlgXoOEmQeQgpNyc\\n0He/1RKqVIdow+HncnCqLBR/AiPiQb2u0DclYX5i7njo8QFkbA1H5kCpPlCvJ8QP/m+zoPRjWJ0K\\nxv8Ng3fCwx6QPxIkPwYb6sLUZfDFZHhYH34bBXlGQPQ8//sJZFsJm17AoTkw7iphv/WL4HUb2CtD\\noNYiQlrVslfwrDREuQt5f4UHAarjY8jdBLYGb/1/YH9pSLwXvgmix9XhdEGIuoFQjn69CDrWgyWb\\nocBN/B+z5NdhkO13KH6DEIfY/ST0Gg+DzkDyKoS4wkHNoNoxSFkftgWc6zYw8UeYkA9W1oVXbQlN\\nrhZZ4EBN+LgURCwOpxYQtlz3LIH3neDYcqhZGVZ0g2aVYPV4MBs+vQlp3kKWVVA/B6RqApMrEGpX\\nZSZDoR6EIxinW0GzeVClA+wJTLTCkOwY3PwXzuaAVnUgSkoYuBfyJoD/2sD2PyFWe6jVHAYEdK4+\\n8HonXL4NeQOc5hRY+TdkHEz4G/HjMDjyKXy1CoYvIMyHBQbcnfdQ/AC8vA0/T4et6eBiCugSFRIP\\ngC9jQ7RL8EdEaFoAZsWEvAOgR03IXxP+mgUTx0HaldB+JcRMDe/eQoZZ8HEXGJcTmgbsvVOQ8BMY\\nmBrGZIeYbWDYWyh1939/xvSrofEn0LET5DpHeHlqMRdSloRUZSHpGFj4CSzLDXvyw7uH0O0qPHkN\\nKavD4lqEycJjx2FCQniSFi62hjhfQcudhFfDlpGh40fw4R5YlhxSV4Vdf0D2OrD4DFyKS7gcOqUV\\nLHoHt1fDk5KEVlrZP6Hx33C+J+w/BxOWw4tc8NkcaJMbsl2ElU8hXlHoexFeBc/vD6B+e2hbAeL1\\ngGVvIPa3sGE6FOlI2INOmBj2HocDs2HZPSi7BWb8CU8qQYZdMGU1nJ4Bv2wnxIJEugEfdoN9S2HN\\nC1h/EJJ8Bls6wpJ2UOU4ZJkBO2dArmEQbyXczAHZs0HeBZA3B8x/B+9fQ97TUGkHxE4KaT+FCheh\\nXIDCbgQxz0Gl23BvOMQNniJrYcgXEHkefBQ8M55Bm7SQ+T7sG0E4v5ZhHNzdBjEbQMx6cCHoj2eA\\n5V/D70tg3GNIkxjqlIICWeBtBDjcGFZdhwJ5IfGPEOFv2LICEl+HIX3hVAVo1YowSxqwQh/NDcrd\\nJQk/pt9MgUHFoORPcGw1DP0XNhyBp5lg4H3odBo2JYQ9UWF7JBgxHGqMhLHpocRy2NgI0myAhi1g\\nWGs43w/6T4FR8+FqCjh4nbBzFKMwfDIASv8FWarA6wA3dx1+qA+fJ4cTEeCz0xA/C+y/Di/SQ9n5\\ncPMlPGwF04vAP0PgbQnocwl2P4ceVeHraxBtDVTsRNg3afY3/LMOCl2HmiugdCn4qgVEvQuzUxJW\\no4Nk0tUysGQ05PgPjgU2RGu42hUiH4U18WHqGbiaFDavhtvVIVYuaNUS3u0l/IQtTQwbwNlNMLwX\\n7KwCv/SAUodgW25IEwuOvIeVySHjf5ByNGGIOHMayBgfyn4EqzdBh4uwszT/j6q/CteqfL//7xcl\\nLS1Id3eDhHQIKF2CCNIh3SEoJY2koCBIgyDdSEinhJR0d3c8G/M3/5/vs8MGG+s41rrvOa/zOscY\\n70H8Q1BiP7TPDB37wbKzsKUrRE8MlR9BvhMw8weInBJe5YUddWF/H0i4HIr2h2rZ4KfBsC8mHI8L\\n//4N4wvA6jhw5yzEWwanX8LpnVC+F3S/CpcPQKXkMDMHJLsEtaJC3QYwpRq8roP/x5v7Lzeh8BSp\\nJwxOAzOSQ+Qy8NtXkDS4px6GRSfhWnS4kxhiP4ZHVeGb1tCpBtz6BbrHhn4/w/Sd8KI2VPwd+i6H\\nLZFgeQoYlwt6ToNaUaD5UMKUXJzYhK+JKdMgzQX46WeY0gNuBLLXNvjsdzgQ2KsD7OF0uDUFDvwJ\\ndb+By8sIpdhca6BcB+i+Coa8h/c34UBbyPoEWh6CQX3gdnHolAN2T4WezyBRkB1ODacmQo2LUGEQ\\n9DkKddtClmXw9AXEfwPZAyZQSSiSDZq2hjiL4PYb2B+BMEgxdSj0PAzfpINOGWHAa8K6qqAWJnBJ\\nfngb2kaHEQfg4kPIvxkOJYJnjeCzZ5A6OmRoBlVjQazqkH8b1OsJMdMSNh/0/xnqxoOLv0PvlNDq\\nNHxRFx60gEGzIXsdWDUPYv0Ey/LDyG5wI4hxdIeVE+DoTOhbHponJsRE1wriO2mhT1fYEg0SZCb0\\nUf2cAualhIWvYFM3SPotDKkHyZZAhixwOhms7w+lkxGmTeffhW4R4Gk+GNQMsh6HA6kg8wXoUwnS\\npINsjaHwevh6MrwK4gjHIV5p2HgIKiyCQyPg4A+QvTEU2Ef4JFb7EGJ8Da0zwaCTcHcirEoGJa7C\\nh71hfAwomBriJILagYj2FJ7PhBp54W19eH8Q2keCKYUgUyCLl4bTFeDD0pCiFZRtRdgD+80mGDwX\\nqm6FCnOgaHw4GRm2vYNXyQiLs47fg46VIfcUuJADNu+CkinheV9ImQyyzofYdeD7erArMXR+A4kz\\nQfwp//tuxD0K1VvA3s3wzWDCJ3HcBSj8DP56C5WTQ5f6kHMgVB8Bsx8QbsePb4JG/wc+3OEcpE0N\\nu4I9Uwf4szEM6QHL3sDNNLBlCRT/A5Y0ItxmfdsA/m0GtbbAznswNB3MrAr/NCdsBFmUHKpehHSX\\noE1A5PoEhqyEs0cIgRcro0Hb9VB0BdzpSKQQPhnQlvd2hHPd4GocmJAZJp+BK0FY8RqU3kw4fl0+\\nAsXOQowoMOIf6B5APo8Q2k7Lp4UTVQhLnRc+hfdn4OuKkG0C1MxC2Hv1xUcQOxGcqgRLe8PtO7Ct\\nOjzYSIiw65wKzn8F58ZDua0QYTKUD7i3lWDUGZhRn7Bm+I+8MHgrtEkCWUcR5i8eZ4c34P5YWLwE\\nymSAeA2hRTqoPxqKPoZKVaFnajhRAiaPge9SEhr0Vt+FjuMhVz34pTnkWgtp58OGfFC+DdydA7sm\\nwZ/HoU0VKFzofx/8zccQ8T6kbwu7HkGmLfDBrxDzFRRYD4fyQaLAA3QMhpSDVufg3n8wsDtsfARx\\nZsOKbJBvJaRqCJuaQqZysLs3IVvo64iwLC+0nQr5t0PK2vDiHuRPRsh0brEOvr8J+f4lrFbNWxoy\\nBpb8IMS+DCa8J2x3rzQWsnaHZk1hQTnCopLg23W5JhxZCdvywfsXEOM65GtG2JsZuywsawVZUsKT\\nOdB6OET6CiadJOx9y7AMZhyAYy8IZbitPeDKeGg/HkpngQv/Qd85kKMmNHoOqTZDk4pQZRT0qQWv\\ngldAL1jYCLJnggGV4cbXcK8anI4KVQvCw6Gwoz6sCb6T02HmY3hbCtK+g6WHocl7yNUWNg2EpZGg\\n8nPYOgBqRoREQZ4xJcwIcmSZYEEK6LYYPskNI8dAstXQYR2UKw5nK8H+CVAtGvy1Bdpehu2B0bU/\\nnK4Fo/6FqdfgYkl4Xh4iVIWCqyHxL/DLKTg/HUbsgmLlIONReDQKkv4Ojd9Dk+3Q5AjkXw56E/ap\\nDckKzUdB6zSE2cCVByDuZGg0A3rEh0ntIFqn//2EIvcJPVVzd8P0DNA/yMYGvr3isLAQRD0OfRfB\\nqUYwfBlhM+bfeaBX4OJ6AofywNdN4WJraPYG/ssJpbtBocgwcgph7XqzgNv0AtJPghid4fZoyD0G\\n8saBE7f+91ucSABdlkPWFFD0BpS8TFjotC4vNJwBjb+Ga7vh0SE4GQOuJYSUd+F8UhjeGlpehUht\\nIGN5mDwSoqSDEcG+ORbEaQlHN8GDD+BtINeegbu1IeJi2DMaMuyFWLXhL5A1OrSaAbFOw8ifYc8N\\n6HoFyq+CmSPgXgHINhOK1YW3z2FlCTjaCaYPhp4ZYOIv0KIQzIsMSQMW3WyY/ishVrRUeZjwANa/\\nhdbVIGsMSFkLWn0LmX6CL0pB1uJwtwWkPQ2T3kC0RoTp8hs/w6lpsG49XEwAdz6BAgMhwlQ415qw\\nuGx9YrhQC7Y/hc6HoXUXWPgLRGkBP2yFk+UJWfbPv4eRF+DxbUgY4Gyqw6ZO0G4gnIoIJ7ZCgXuw\\n8hQ0qAG5dkOU69CqKBSYD8vmwbgusG83PI0Jd7bAnZpwK+gYGAR14sC4zyFZF7g1irCVJOi0SJMZ\\nZieD3AXgy2kwcgNETAFLF8DM4fA+KvRLDy3rwq0AArWOSKzIDCM+gNeJIWJVuHwabl0kpMVMOALz\\nOkDjCDB5KUzOD9dXQO62kCAylDkCryJC5Kzw2QcwMPg4oxFCw0bVg9E/QN/V8EVbWJqMUJPOtgam\\nb4ELx2FxFPg2OyGf6WJdeJ0RSmWG930g02N4MgouViPsSczSB0YsgJZ7INMXUDYxYbNhnAzw6md4\\ntRoexIIuraD1Nrg5GKKVgEqPCIOsiwLg5wRI0BD+7gCD3sLe3+H+XTi+Gjb/Dn//B2V3wkfn4LeZ\\nULQqzAo2Ez1h0GLIcBV+TAbJ+kKRtlDjA6i3GaK8gmmxoWovGHCJsB/+6w7wYiHk2wBd7kPVv2Bs\\nY9jUBqIfgM7vYVw2OFEJ5l+HgV/Atw/hYhT4fTpc/wd+PwZzEkDHiTBlNpz7DE60hBrdIFca6D4S\\n/u1I6NHp9Ss0WA/9n8PkIA+1i5C2tfYHOHkYfn4PDT+BBo9hTlXIGQ9ix4Hb38KrgXD9NPTaQHgv\\n6ZIO2t+AEhHhRkm4+idEOAWTk8KFrDC0GjQKcpc9oGM5uPEePuwApWPDvBgwcjnkTAX7H8OxBhA5\\nFaQpBBfOwvb3kPwlPHkM44Lb4RzoUR02B8bqb6HmL/DpPBgbDzKAHrvhzB+Q7jVELwezykLzG4Qo\\n1xqHYGEOKDwIXk6GA1dhw3HIHYGwM3ToPvijJPQpDoMzEaI9smWGM0WhzBxo8xmMCtCOY6BDNshW\\nGvLXhp/WwMQ9ULAjjPwY9saFxJXg10BkOQTLwIv4UGQf9F0DV2bCiU3wsitUiQC/fg19z8LwhrAg\\nBxxYComLwPqTcP5T+CUqJFgAydJBrxbw+0X4eDPc/hd2boYI0aF7RMJql5wBpDEjxO4PS6NB/5jQ\\nPSEsTQGpHkClg1B0FAzuCQ0vQ6F00DkpZO8CPX+FrIuhdzEwgXAzt2QDPG4Pbx7AlZ+h52q40hC6\\nXoYVOWDUZdg8HTa+gm8ewLSnMOpniLkPVpyDWi/h4hNYngvipgOvIE8yaFcP1gyE/dWhz3qoFSTy\\n5kKUQ/DBSlh2EzZHhzF/QqpLkP8GFLkOx7dC8x9gRDvolxoSB3uyk3C/G9RaDlFnEFa6vX4Fi+/A\\n5fXQ/jWkLkHYlDDpd6h5Da4fhxW9IcrXECEDrK8PpTtDwxIQYykMXgmPB8CjKTAjIDueg0PNYddC\\n6B5scz+AnnEIGw+nX4Dep6DpCegd/HsDrsyFV0lha1uINRL6JYD1n0OsKjAjEnTtDyOSQNw80DIl\\n5DwINbtD3iUgYAIkgxtJCBsOjkWGA2fhzx/h50AJiQ6n6sG0eXCuIvQNbPUBimUlzBgIt2dA2i/h\\nQG2olgt+CIhxJSDeDki/ED5ICsneQu+/CGmXz2/BhNSwrBBsfUWIZv15GkydC/80JgRb3LgDp59A\\nnPLQMwZ0TQyr7kOCi7D6OiTcDR9Uh8uloMgt+L4HVH1EOD9cKwipk0Phj4lEyl8IcxaLf4eir2Bc\\nXSj0Esr1gi2BVTknPIoDmb6CrrNgQGao/gusbQ7tpkDnxvA2PvwbH8YMgj9jws0gmVgZPhgDcYJb\\nZmZoOgj+eQKjV8DLr2BtSUgQBY4Fh1wlaBIFNk2B+kUhwSzwOVRoDH88h4tz4LNvoPGvUOccJA1E\\njU2wuT2UWENoRP2iIiEt7MZSuLwA1hSA4oGHrAcMuAz7UkL1PfBvFPiqIzyKAlHawKAdMP4BYetT\\nkb0wNAM0Ogwxd0LUnDD+KbwtAKc3wKlCsGkLZH4Oi67BnmuQqzzc/pPQc3awHXRICm8/hN6p4NJB\\nGBNIADVhykFo0BjqBGbVlPBfYO0P6D4b4GJxEIAWP4f5vxL6JAIGdMKHhByXS5/CZ0Pgh++g922w\\nA15+DDnaQKLtkCVAt9WGAwmh/VLC+o7Tb2DVQMi1DZqugcfNCWt6c1aAf1JD9SIwIjbEKwIZ7sOX\\nYyD5P3DmEKxLCatLQrnkUD0Y5S/Bw+/hQGyYvh2iZIJWW+BEPti1GAoHav0MKFkTtmSD0x0JAb8Z\\nj8OhYoRgxpWN4PhdmBvslSfBlciQqTjh+J71DWx8Bh9tIUTkHZsCaX6Crbcg7ltIcBIKBuGAXLBl\\nDDT4Cl7dgVopIfZOeP8bPP8Ixq6E88/gfXAJWQLzU8LTKzB1KgyLAdv+JOR09/sRkr2CJIeg8mro\\nvwOqHIbsF6B5dviwDWTqCNt6QbLb0Dnw9xyC5nMhayGIFB+WLyUsqv/gHeyLA+euwJx+sPom7Azk\\nwgvQbRyU3Qj3G0OlUpBqDvyWHTIFYk0ZiD0Qfh4ISYOwyHLYXAiKD4B2w+Hb5xBxJTTuBF/cJBR2\\nA9dd60kwaicsLwMDAtfdFnh0BZLchtUfwuG38KwWIcx2ZlmoEAB738PCnrD4KpS9TFjlEbSnpTwL\\nRW/DX60haiL44DVM3Qjj3sCZWNDoLmSKCLMD2a4P4Te/8t9Q5iHUPgr1N8Dn38P1lLAjKezJDtNu\\nwb8zYH9hyP8csiSC1qdh3iooWQZKzYO50WBXWqj/I5zZAP+tgNqB568PZP8dqq2Fp7cgQX8o0xaq\\ngXOnYFNAky8F7T+Gdwug1Fl4VADW3oapnSFCUTh6DRq2gB4RIVIRmHYaKnWA6nNhylPY9hVU/hcG\\nfArffPC/v0CEYhBxPlzaCeXuQNkbUDgXRJlNWCKU7AcYlALyPYEjEwk9ZFX2w/l3hCfs+kfw4Ub4\\ncz50GwE5jsGZL2FMwMN7CQljwYZ4MP97+L0P5D0BdZNAq7WQbTTsqwiXFkDpeNCrIKS7DfmiQeFs\\nMKgvTGlAuGQpsxCaBMPiPKjfES7lhMHP4Uw8QokwxyY42B96BKS3A5CoKGSKAD9OgLWfQP/7UKkn\\nNEkNzarDw+dQozRsyQwjgwhaN7h5FOblgmSxYdqvkDoP/NEXCh+A9lWgXTEolB0W3YV534J0K+HL\\nGvAoIzy/CRuSwjeRINtPhAbqiTFh4jjIeQ9y5YRoEaDQz7CuBOw7CfWOQpaNMPh7aFgO8sSG1h0g\\nUhNIu4twA9EkN8yvCR2uwvw3UCvgBuWFuB/AonmwqDasW0dI73hyG6Iegd5t4EFRGHsa/toL74dC\\nj+gweQhcfAyfToVJZaDJLMJSggJZCU2OHwQrxwfwKMCupoCbSaFPFVgYyFjBAVMBUg6FnR2hyA34\\ndhFUeABlS0DNQM2tSPhoPfgDPkgJfS5A9EawZAcUOw9frobaE2FGYqhzCI6uhWhdIHE8SHsZrh2D\\nlM9gcEP49S4M/gRypIdszaH9LjgRg7DqNWM7WPwMEt+DDAUIt32t/s84VfWf//3PkFHQ+WNIlR8+\\nu0m45dr5FeT7BOqUgciP4OhKyLeUsKUxACVU2Q4zjkOuc/AiBUy9CM2C8pwyMGomLEtPSOzd0JWw\\niXLWBMKS1G6F4HxLqJwYksSGHQfh8DpI/TEciAoF70G7+rDoU6hwG768C6+rQvzt0G8eRDoEkybC\\n5yUhRg+oOBfW9oXzm+Gz+LDwOuxaApfzwfJfoVsliN0Alt2Fhjeh9HLYMRBuVYHnxWBqAOirDkNS\\nwOss0CwQyvdBorrw2QS4MBROpoEXZ6HJl3AhELj7EO5Nj2WDPo9geA0Ymw5SpYVzZ2D0QojxNyT5\\nP9uI0U9gTm+YEbzKG0CFgO98HyJmgh2lIeUK6NGTMJk75CzkHQfZJkL2x1BhGSReDA3WQeZYsPcd\\nfNYGZmaGacHIXhM2/AVZgrDCVNhUHVJehlhlYcE+ePsL/LkCkjSH24khcTRIkw1m9YbHp2HoAkjT\\nAuZMgSMpocXX0KEWFDgOTQvCm8Uwfi+8PAnDksOq1DDwM6j6PazsA893w6B60OcgRGoJDb6BmkFg\\nYiF03g0zfoGzyWBdVIh6C8blhaPtoX1z+CbYHPQnzCqO7gIDz0HdivAmJmSuB1FuEPZnJC0KP52F\\n9Wtgc2RC71fB4PhfDgeOQ7NRUCsFXIkGtTfC9EjQ4ih0mghbysDco9CrAJxdCk9ewMJkcDI2JNtC\\nWLCz5wLs/xaiDIcaLyFKLtgeCRanhysHCLeJi2tB9aJwrDbMCHzAxSH2BSg+G5pfg9NLYFwG2NqN\\n8Go9bT2UPQzXYkD3R9C+MtxuBgW/hDjJYPl7+G4eLJ8PLefA6nOE5fHHJsL1m9D/J0Lz+MJmMPYq\\nJA3gnxMJ66XT9YcZWwiTjL2iEZa1P90D34+HFjvg70TQMcjbdoIeo+BOeziVAHLOgSaHoXYTOHsc\\nvp4E7UfD3UsQKbBDfAAbN8D9QhDhIHzaHLYGAYhchENwhdKwqRyU7gVJrsGvoyBqDpgTE158DWdS\\nwapIMKYGDHoIFV/D2L/g1mZoXQvadoTkz+HwYViXATJugDlroOAwuN8GskSEg7thYECm7ADrA5PM\\nS1hUjgjcGwJFpsInt+HHb2BuLkh7knB1PDYiDAtCvOsgXTRoPZewMnPJY3hQBM7NgJcvIeIVwna2\\nFSvg5iM4kA+eBpDG53C8JbSrCJ0/gmLRYOFdmH8A+lWH6KWh1VlCJmxA3WjUDKZFhr/Ww/NacLMq\\nvAsEglJwuQbMaQSDrkLdzJDnFRR6D69iQPHA2J4LiqyHYocgfRz48zL8tgnqzoZXtSF9GTjzFLJv\\nggW/wOSqkPkIJHwGW4sS0j5eZoRPtkHvu3CpEiyLAvGvQ5XN8MkJKBkHUn0AOcoSNi1++gruJIS8\\n30C+JZCvN8TYBEVjQckFEDUTGED4SjozDNZ1hj1tYESwPSoLz45AuwpwqBQk6wfDUkPWYbBxMaTb\\nD1dqQO44EDElxNkJ3YvB4ghQJi4c+Q7+mQd7G8OlkvBTE/jjNyh0GKIWJwwG144E89bAV0UgWkK4\\nfBGKbIaz9aBQJjj6Hkr8n0ei5R3IWhduroZkQfYqMG8+hAcHof54iL6BsIRnXnfInRYi7iIsboq2\\nHp6uh2b7IWNDaBSg+Z5CnT9gZm0o+zF8WQ+SZIYGJ+D+VRiWCw5Oh5Oz4cpnsCQzdCgAv/0Hy/+E\\nThFhwEuYOBL2L4PljWBINKjaHR4lhiab4bs2cKgdzO0NXwQR69aEO497u2HvI1j3Cnb8AV/sgbaB\\n7TQTHH4Hm3LDxePwuBWUXAUHe8Ld7NAjI6y9Bnf2QLFHhKPn8HbwOAAI94XEBWF3WWjwNQw9D3Hj\\nQIEf4XEa6FId/rsAbcrBjoZwrg8czworV8KEzXDqOGGByb/joXsrKLgIOgeUteCdswXKRyBEcjTq\\nCaXzwx8DIFpKwh3ksK/g24XweATUGgfD6sP11ITYlFyLIdt4+KEtLOsCU95B3uAwOA9NSsKlqYS5\\n4BhXIWU+KB7gFSbC7FKEbOt/PoFmb6FDIfg+CWw9Dwerwfo+8OJLaFAfmraFm/Hgcj1YdA7m34HS\\nwRE4EsYlhk97wPmc0H8hRHoE3U8RsujuzYF6W2DVe7jeA2qsJMyyla4C499Bj8DevgtyfA1Vj0HF\\njnBjP2zuCbdaQrkAk5sDxjaHT36EAvPgj6aEMtao2LB0PXRNChGXwoV8UOlnKLUJ+m2BkucJi8aj\\nXIUBbaDeJqidFdJlgaufw4pXUKo94QW+Y4CMzgErO8K42PBfJSibG/rfhN8qw65tkGIb4aC8diOU\\n3gp9h8GEL+DoaVjSE7IdhjslIes2+PUEFN0J++rA0ojw6yVCPlbiJ5CzHvxZAHpGhJO7oWV1ePM7\\nYedj34aw+l/4LzpUOAHln0DxB4Tp2hjxIe5zODgfrpWCkkE6Oz9s+wSa74Mu1+D4H7C3OywtBQee\\nQL8FUKA5/PsZHP8d8reBqkvhTSPCJzp3Rki/Gu6dgzjL4Nlywu1+j24QcxIkuAP7M0D1qLDtMAwo\\nAJfLw0fx4c/gO3MClgbqWc3REHMMfDoOzkyEOQGsbCb0vwefR4Ckg+F4dBi3BK6tggP/Qp1AHEkA\\nhVJDnFxQciU0XwmZB8HNErAxDzSOB1v3EWIXvksMMX6CLsPhk83Q6RrcGgIfR4MNzeDpKUIa1vMf\\n4VFT+Oc63CwHkWbDideEPoNfkkOiLoSk47OHoeoT+CMAMB6HYZFg9iEoPgUuNoNheeDiKGgQA0bV\\ngGItoNcc6HAD+u2F6vch5h6omQYyJ4Gdd6HwHuh1FG4sgTRFoU1jWB0kkv5P3idafKgeDRKWhuRr\\nocluiD4c5u8nRMJGDpj4nxOWI+WKBDf3waDPYNgIGJ8M/poEF3YSiibVZkPS7lAiJ6y9A/u6w8Sm\\nhMiDxSmh6CT4uC3sHwUJmsKEDrBhM8y5APk2wrydhA62vzPAJzshc3OYGw9q9IDBF2F/c/iuE1wo\\nAvNewNLAkdMcxj8hxANeywZ3E8LWlrCtDtyrS3iTTr4cGu2GwhWg/Ufw7A00D+hf4+BybRixBJrN\\nhXkVoOrHULgnpI4GkwIizhqIcByKrCHE7Y4fTXhJ2FwWBhaCj2LCiM/gfFs41QESfAP1D8OEn6Fx\\nXHiRDLJ/AA06w39BjizgP02BWU1hzDJI+BvsCphws+DsvxBtDQwsAc/zQPte8Hdr/j+fUwVodBL+\\n2gqLp0GjFJAmoBtXg3vDYXULuFUSskeHKDVg6aeQYTJ0OAsfHoAEFwhj6vl/g33V4cYl2D4FcvwB\\nDQ5A8xHQ7gpk2QwNukK8m7AiCHZ0JvTMHWwApc9DlnVQ+guI3w5qxoUSVWHLFPjrOOxrBBWXQM3N\\n0Ow5HLkH21rC4IiQBhxpBi+3QeQEkDY9fLYMuiaAZRngWlHYEQsOp4HzBwmzZslvw1fHoG1SGPIA\\nIs2Esudg7QKoPxy+jA6/fAopA6RkdGhRHrI+g4r5YOAUqPMWam+Bym3g3RxYlwcGtIDoo6BNemgQ\\nCb7LCcWmwuLT0D64ADeBmCOh4yB4FBEalCFEdUz8ihDpUvw6TKsAda/C+24wtxJhrfiCbHAhAOpm\\ngsn14Ml2WLWTkNK3LilkPkM4tMX7BfpkhsyXocINWFsV5hyAiHGh1DB4HTgIy8L+L+FtIihcCsp1\\nJ4wy1I4IuztAwsbw/eewMzBL9IC8KQhpSVPjQot9cDsODL4MJUZCjx8IfWaJckCEI1B+MbQrCo9z\\nwLcJCTOtnXrB2VvwaD5huXVgOa8dJP2/hWLLofcM+DAVtH5GaBfJ3Be6bYEDWQnbUWNvg3tnoE9h\\niLwf2u6He5khcQNIlhzKB4LjI1jVDq4nh/gBHGcHZDkJWZ7D9CVwOMiYZyTMqD4bAmfzwsxHhDCa\\nxLehXjpCD1++xnB7JxQMntAykHw+YQCu+xtI8Cf8Hg1mrIVUa6D7HhhbGep2JAyu1YsLTwINJy40\\nmQm/BopBUYg0DAb1gm0pIVZBSPs3kYl6B14cIWzdyl0Y2gT2zMxQYAE0Daisq2B8D2j0CB6egkQB\\nbHA/VLoOn92FcxOh6y+Q5hJ8nRnaLYEYpcDXkL0pJCwBHZ/AuMHwpgFMSgVNusKcxvDzx5D2Kfz9\\nGN6nhlNdYViwkG8Krb6GCylg2yQosh0+HQ5zD8PPSaDZdOheFkb0gqPnIGIpeH0SFp2FVfnhhxiE\\nfXm598GkM/DpICi1GmaUg5+SQe2SkKcyNFzG/3+hdYxVMCwDzA5m8w/h7CtIcQru5ICYQ2DsANhS\\nBI5Gg98uwg9XoG5ruPcKUs2E6M0h+ZcwOzbkewwLp8PXU+HdZHj5N5SPQwi7q9UEjn8EbVpAzIAb\\ntBg+3AZ9CkDifvBLIYgTcMWeQdt8sG8WdA/2WAlg5W/QfhAMuwQrg1xYEZhdDVb/CdFuwrxmEL82\\nzOkBJ0vBisnwfSCiFYMJgUehDyTPDM+DhfZWGJEXmnwBw67BXzehdzkY2Qx8AX9Eg52XIfsPcOoK\\noYAe9AfEakjIBLr1BA6OgOSBs+FXmNoG6owgZK2dR1g5EmUVtCxLGEQvWA9ujoA7M+B5bzj7GGr+\\nA3U/gz/aQPe/4f4BiHQNXuSG4dsg6lz4sg789wsUHAiRg5/zAdTqC8VjQ8an0KAYTNsGf0yA6AGs\\nryxU7A+LpsC3DSHF74SM49p74b8gtbQf/rsNO29CtuPwzSwodQeaV4Re8eBaWkj2GD7KAG2iEUqr\\nLTvBHpC3Dow7CqUeQp3L0DQaHLoI+VbB4YiQ4QvYlgGGB/7FRNBgHKz8D8pdg8QD4KdSUOIzuBbs\\nWvJD5u/geiAfvIX7i2HrQ4h0Hh72gOXtoMpAOPgYljyCyRkg20uoHxUOZSNksjcaAc/aQMci8PoP\\n+PRX+O8KtAfxNsKV9rC7BaRKD0/zwPcPgj8TfNgfvmoI0xPC7rdwczg0fwF/JyEMUlR9AX8EYMy1\\nUGceFDoL/7UEhSHdAkjwBK4Uhu4PYNgWiFwEhl0hTBYfCLiD6+FUYpibEEb3hFIZ4VItSP8dNFgE\\nXdZDdpD4N+j5Hlb9AKWOQo2EhFH/Rh1gSVcY1QCmtYI8qaBcNeh+A4qmgiUdIMtA6JIPYmaDdTHh\\ntz+gcj7o8wv07QYxEkH8E9AiSCBegrQ9CTtqn38Ln++Fq58QdrZ+HBu+eAhtL8DnARogJvxcBK7s\\nJdxYHz0EU8rB5PGEto2g9e/botDjNLwsADuPQLYLELMRIf0uRXeYWgr2dIBvE0DbudD6AeRrBJd+\\ngd0fQs5jcHA93LgOv/1DOGqsPw9ndhO2NfROAWmDS9odaDALPqwFa3fBuyRwrhzs60QYc0k0GXJe\\nh6mJoGZn6J8WiseFDA0IXcvvHsDVqdB/HqxtC/0CvaI7FF0Lb7LBs/zwWz/CCu2vj8He1fBtBBjQ\\nGH4Nvp/9IVsCqLkA+pQibHMOrihBvGP7cKizhog0igorj8G6ypDjMbQqC2t+h5dRoFlzWNAO/ttB\\nuM2qHKw3b8PXqSBaCpg1E75OB1O7QLfdkH0mxA8wjIthWATIngRO54NDreH8Sug/HHqcgZN1YHgw\\na9eE9IHqPA8mXoLRE6BZG9i1H0YOh7a5IMV7SL8JYgS2tarw+VvIMgS+CcgoT+DLalDrJ0gPCnwB\\ny1rC7MgQoxCsqg+TNhDycztUg+hV4avzMOwYzJwLy57Bq1XwMCGkyQsPo0HaipAuLVxJCMdnQ5zA\\nGhxo1REhebA520q4DB86Heo0hI9+gzWtYNlDeFqdkD4ceyZEuwaXmkP/3PDkH0hXHnoEW7FrkDkD\\nbP4EWu6DXwfA1EAWGQCdD8Kd0/BmGaTpBhM3wPJPIO9GaNYLstSGT4cSckq2JyQkA3VOBDGXwLPH\\nsHg/YYHG+q6EB/mBm1D5PRzfDJM3QuxvIGcm6HOfkPJ/bTv8kByax4LHJ+FFdugeoAcmQJI2sKQ/\\n9B3+v9+lRTeoPx9yV4LRlyDBXVhaCcq1h6sBjeYJdB4C8y5BrjPwZRdYvh3O/gA5Amzmdlg4CrYu\\ngX9eQKaKcPYELH8Ei1vAt1fg2jJ4khvuN4NIm6HibLi9F9JVg6qj4FUFWD0T7m6GTDsh6xxolANK\\nzIAtH0CkL6FITFheF879BEOmwPPjhE6XsWng34jQrQCk6gbJGkP1i7BkDVReC+WD0SQ5/t/smbkJ\\nzOtLuB0MIIcnnkPqWVC6AnT5G27thW4d4Uo6+PYdIYM7xRL4MXC5vYM8AVVrKWGW7UJj6F4CfvoH\\nDq+E6P8QmnOLRoTpxyFyAKapBL1bw9JcUGI6/LAbLh4gzLhliABzvoJjVeFSkMgrCQUawoiG8OnH\\nUKgDYf1Lhkbwx3VI1Bq+bwrPUsMf96FWJ5j0N5y9BEmqQetB8KAmbFoJRRfApdSEudFrDeBdFzh4\\nHl7/C391JhyqrgagyJVQtzBhfCTDHIj2EDYkhkqz4E0vGF0BvuoPNaNA5Inw8TK4nBVub4JS1+Dg\\nTBj/Cr4fDp1iQO3LsCALZPkFnj6GKhnh3FtYfAgafg7rP4UzA6FneTgwB3bOg3uPYPMpyLMO/s4B\\nE/dDtNLwKsioloah+eBSQfj0GnT+E2qVh/QfQvtCMDIlpA8CPRHhSHo4mxBq/AYPb0P8szC4H5w5\\nTuhvTjgUrp6EqMsgYR8Y9itELgDrc0KSBRD/NUTYDltGQ+SG0HAXzH8Ajw7D25KwtyUUPA+5H8H7\\nFHAjG9z5GXYkhg5PoEcQZXhBCNCelgFGN4TtI+FWJejzI+QYCRFywIjshM2q6xdDinOEb5u6l+D7\\nVjD4JmEQLW9MWBETUgdyYXrC9/yk8hDpOGE3w+VK0PU7uPQnXPwVzuWDYrMhcQe4dAEm/QnXSkDf\\nWNAuEjT4Aronh3/PQI/CsLwTbCwL3bbD++/h1x7w5hw0yQoPesDPCcCLwuAc5NsEhdbCmA3wVX0Y\\neQV6rCAAwFMqEKeGwrRoUPEVHF8G72rw//p/fbQGWkz730f+yQfw7DK0WQi5KxCuYXd2htg/QuRq\\nsPwcIQ35VW/YFcACVkL5mbBhD9woD1XaQ92l0Cc+1OsHX0eHPk9h4J/QYy5sng8JDsODs/DxY9ja\\nCpIshZzPYUMswkOi2iX4aiqhn+DiDWh4kBCIJ2C3JCQMzSYbCxtfQ4ebMOxnSFyT8Cb31RewdAt8\\nNBaO7oN6t6D03/AsBySqAQlywd/R4eEgmPcdXMkIKXbCj+0h+xNY8BPkOQLfl4LtV+DdBHi2Ec6k\\nhLWfEwIgnlSEzQH68gY0zwApa8COrIQaf5I4cGEJ7H8BD3+GT5dDs/OwMcjx5YQX6eDaXFi3FQZl\\ng1eBc+sYnFgAI69B/oiQuBTUiw95qkKFOLA+MDkWIfTDDToA09JC7caQoit07Q1TU8HCVfDdZPhp\\nKBxLArdPQcuX0C0yvBsP7dJCx7GE1dqxNkObVzDhOvxXGPqNhT9nwoBGELUHPL4MG9vCH5Wh5QaI\\nvBO63YbuieGTQC4vDv9mgH/fwbxF0H8S7KsEGdrCx+3g7odQMhr07UJ4HXq6He4OgqpHIP082JQE\\n3iaHo8EAtxvS9IVtHSH9WRhSHErkgF5B5PsQHF8MfaYTVozPbwzls8DqCjB5Hnz0Fg7VgvYv4UFS\\nGJsZUg+Edq2geh949ApmH4Z6O6BJMhg6BbaVgdxnIFIM+CQIc3SAgwFVriGs3AxbEsGMvTDoIMz5\\njLDn7mp1eLULfmxO2KY3ORKUGgi570KSQNaMDaf+hI8qwveN4IPhcDwmZO8FVw7D023wMjK0rgGx\\n8sOEFtA0LSS9CG3PQpXp8F1sOPAR1IgBJ3ZAjOFwvga0SgkFZ8MnseDAGVjyFewIeEix4fcrhE0S\\nTbLDtYCu9wya/Aup4kD6uCAuHAqIa3mg2XootwfefAt390H0UpC8OxwrDDUrwPrjUOYsXH5FeFFs\\nGTDtJkH8/+CDFXC+HBxsBeP+hDo1CCloPxSACkthVkA7SwObmkG0pISYkiKVoHQCSF0N6heAqDEI\\nmz1vJ4XCzeC3iHA4OezfBun6QsGkMHseVNsASbtAv8BX+j1EPAyT28L4oNtjJDxsAQcrQIuEEGU0\\nfNAHzl6A7iuhzB5Y+haW/QC/RYKtqeGnfXC3AmT9Fkb2gftN4EUO2Ps5dPsAHs8lFDEDFFHg8X2+\\ngrDW7HFDqJ+P0DPXegF0nA6r4sP4IAZUHOK+h1NDoFIeWHcd1qYmDMMNighLb8Pc1YQD0IPaEOM+\\nLCwGo3cTAsMb74Y+m6D9TBi9FGJthFGn4W4mwoTposDV1waGdYLtv0HVtIScy1dzYdwmyLQXbs6F\\nnrOg2C5Cx1W37vByEBzpC09zwv5FsC8D5L0Ch1rCmoSENe2/VCIMlCTOCkfXQYZoROZKUlhSgXDn\\nsfQ95A1i8zUJzeYPskD37yHBEFj4NxzJDh3PwZ6okGoPjHkKDYvBj+8g2j5o+oqQS/5BZRh8BUps\\nghLn4JtqkCXwSBWCRwth0Qn4NCNcTwdLD0K2rtCvMhxYQejRyTgU1h6FXHug+Eq4FZWQw3R+KjyZ\\nDE8XQM5bsHUFFM0NKZZBg5vw4meItgAavCWURC8lgFRx4eQ0qH0JiraCO+XgwADIXA5KbCSkOkV4\\nAA/nQoI2kHowdEoEJ87C19kg4iX48CrUbwsHu0CMdvBlKTjWCQoFC94JkHE0/FANXh+CVV9Ck/5Q\\npDyUiwAd68CIiBChNLy7A+2OwujesGYFrI0EA9bCg9IwsyD8+CNs3wlFbkP/O/DdYGhyCWYvghRV\\nYPtfMC0b1JgKEVLBk4cw8Rps+R6y/QNZIkHjF3DuDrToA9+Vgx8Sw8SH8CoArvaHuIfh/Hi4Ww2S\\nnYC19wiNwJMXQeXdED8CzC0C63LC8WSw8QUULA/308DSAfAmGcyaAieXwuNvYHwJeLUPvnoKv8+C\\nrw7DkW2QdDRk3QWpKkOalNBxD1RrAXEKQaNq8MlwiNMChnWE3F2hxS64MoUQVXAsNcwqBPnigGlQ\\n5TWhHbjUKZjTAIYVg31XoXFZyJEajt+C7zpA655Q7wqkHAZN8kP+NfDxWoiSEVpnhAUlIH9uiLiI\\nEKJ44QahMaB9f6iRmbAN88GXhP6wsWXgcBIouhGOZ4ff78H3xeHBGig+GaZ+CqOmwIQlhDVcY+LC\\nmRSQ+y+YehBGnINxHeFUfHgTG9K/hgRlYVZhOHEYptyAE/khQcAxakQIrGmWCHKsh9Z9odJzwoH4\\n/u+EiObNOeDfrjBmCQxdAksbwEvQLB18dxd+WAIf9oTES6FdB3iUC1qPhK+XQIWxsOMiVB0MW9/D\\nlmsQ5y3sGw9tK0PWNVCsN3z3LTTvTUilr/0XNH4Hh1fAuWNQ8jXM7AMxmkO5EvCuKswYBnlLQMWq\\n8P1dwjaLBtVhY1LIdQ/+mQ+FK8LiZLBhABwsRsgfb5wZ+uaEXX9D3YbQdB6c/ZFwGB2/hRBAU78J\\nVE0OkcYRlpzcaQOdoxNy/6vtgmujYOlvsHst9H9GCAH+MQrUOw7t30OZB4SwgLTNIP9giFoUPl4K\\n59pA2p/g0SQoUxhOpoIte2BmD+gyEd5/AZtfEOb6g9LuzIVgwg3ouAVir4DbjSFnBKg3G9a3hXu7\\noNNKSFgSKsaBjy7Dw0eE17bxUWF1NChRGlongWuzoV5e+HI6bN4Hr2/D8z+hylBoHVgjLkOVWjBu\\nOzwaArc/gC9fQqX7cGgv7LpEyLgvcAfqxYCmAe3vBnx0H9INg7GTIUVhyJsH0vWCHm0gwy2IXwlG\\npIOD0aFQKsh/GYo3gd+Kwp2osOMfGJIfiqwgNCEE3uIjvSBVA2jdGx60hGLBvq0/zJ4Aqa9C7tGw\\nqCcRGX4TyrSCQk9h3BcQMxEkrQud8kIWcDg17GsCabcS1m48TQzP1kCK32DAQyjeBt40hzst4YeU\\nkPcjKPg5DM8NLfNCjgAHNwl+SAuFa8HVvpC/I+HrKX5JGDAemhSCncHHXxXqHIRPqkK7RHByCGEn\\n191RhD6S4jUJe5RqBna/YFCLCE3mw6jUkLAuPPiOMCw9OjN0uUzoQEqyC5KMh0+/hcz94OOVUHA8\\ndArI+MNgd2XCxsMg55LpOfxWHcaXgjyt4exMeNIPVvSHupvg4yxwNwlUuw7ffQzDgrtvdqh1G9Zk\\ngm3XYSwoUAOq3YX8zWFsD9i7CSpngrjDYPUSuPOG0J9UOQXITdiZWOQU/LsBJg6AKmPgWi5IcBXi\\nj4eswep1AewdBsuiwZm4EP1veHUJ4paA+AFGJDZM2gIJ48OPE2F4aiiaBUY9gmTFod5eWDMa8uSD\\n3OMJQXN7n8PsM9DgM7gzj9C+urgj3FwIs7+F/n9D5ACB+B6K34e8jSB2JnjaEbK3glaBs6oO5FkG\\ns4ZC74TQcQl0jAH91hN2bq7uRpi97T0fyr+CQRng50dwvT9EeA3bm0Dlr2CNuqE1AAA1+UlEQVRq\\nUpj2PQyJCktSwI4TECkrtF8BUU/A6HeQsTnkOAPJg0OrAyyMCf0Hw3eDoPRj2B4HitWH6q9g0hz4\\nIjm8nwB1U8GiRnDwGdQ4B0NyQ6X4cL8PFD4GE7+BuO0gV2lotAPiZYVl6+Az//vdP/gRuoyC1p9D\\nmyXQ7We4fAvKtIBIm2DFLPgxMnyTBJ49hG/jQuUgrdmYMGrz4y44eA/KdIUEGeB9RRh7Bv59Cw16\\nwTOQOgWsTwf1VkC6OxBrJYzYB5ETwbI5sCsRLP8MKqWAhufh341wPhXUjglHMsLCItBkGyQbCi9a\\nwc4asKYx3CoGlRfDkb3Q+CfCiuigaLn8JMjfDTZ8BJ3qwMVr0GEbIVG9U3cY2Q9qjSSUsZZMhoX5\\nIH9wNQqiCR3g+RUYVB4aRoL05+FWB9j+BGLdgnS94e1lSD+UMAaUYTHkng5HvoAYX0HpTZAjgFaM\\ng36xYfAxSPMfJGgGO1pDr7aQZAWkKA85yhBS+D9f979PISjqrvYbjAve2MmgVVU4nQMuT4N9h2DJ\\nTejcHt6dgj0j4Mcl0P0x3I0PJU/BhlfQKxPU/RGuXoFhgb+tD2yOBtv7wKyMUC02PJ1MOKQOnQkl\\nPyLk59X8HO51ggrrCUfGlh1h5TCoPR9+jA8Rv4IoTWHYc0iSG9pvgbsZoW9N+GY4HIxCuJdt9S8c\\nWQPzrhNyp1IkgQrtYGZWSNMVoreAV0Ph/k1YuBaG/EHophq4FXYfgvWloeEEiLwWMsyFb1sSnt2z\\nexKOzpUqw8no8N1hOPwVfNIbmp4i9KjNzwJV3sCbwG93HvJfh1Xd4Fh9WFgc4mWEHu1h28dwczok\\nnQNvP4NvXsCtwOz/GRTYBT/kh/RfEYEVKSDSB3CrL8R7AOUDzvI+GN0R8oyFlHkISdaHPiB0zASJ\\niam5IXVH6HeAkJZx+BCcSgSZI8K7ACKaD36aB9W3wZJfCGtWI86Edwng7NdwO0CbBiayWVC3Kzyf\\nBSXawYJ1EGEtjPwEHj2GV3MgQ2q4uY4Q93cuiKR+Ae2GQbGIcDMfnI8Dc+fB7JyEFRA718CjwTCt\\nPVT/CrZXg7rDIe5cuDAG4t+DRB0gR06IuRDmfAkbCsCTClC8MaybTUjxWd4WLu+EXcngVC/4/RSk\\nKA0NEsH03vB0L+xIDrHGQZKWsP01tCpAGCJd8wQiVYByy+BsK8I6mqAPruZKuPYcHu6ETxdCmTqQ\\n5A68ew5LC0LfG/D6U0Ii+ZYhcOs/mPgfNL8Aq4L0ZXa41ZwQahCwl5Ifg24J4GBTiP4cWqaHfckh\\n6VDQBL4sDROmQNrrULU0TBoEV0H2AVDvEhRpDEdaQcWfCGXBpx9D1xlQfykcTEWYJA1Gq7cLIf1V\\nyDMDvqgK+z+CL6bA6a1wujIcWg4NlxKWILU8APIQinGvf4O/E8OVryHWHqj9HawJ9nAToNdJGF4G\\nThyCwUFUIvgUosKiRxC3MPwU5DGzQN9gFX8ZPu0E9ZPB/BvwJBO0iAh/boNbu2DIdqjZCUp0genf\\nQ5FR0Kkx4dD8JCbMCY63JYRen+L/wds3EOMinO8FMZbApLRQ7AK0WgXpKkDXRpBpHbyvCrPfQZW0\\nkC8mnGsJEZtCqr8heZDrLAUVi0HFmTDmX0LRtu4sOJoIhn4BxVtDlTbQ+ir8MAw65IBT6+HhNogW\\nAw6uhp7b4dBDmNkC6kyBGTsg+gV4FAhV6yD+BqjVAX6tCl9uhxydYF0XGDMZHnQldKXMKwn3osHK\\nShBhGSRIBfNnQ96tUOE83J8K3bpBpSrw63hoPB9+XQYvF8Cvq2Dax3C5ALTuD8vuQOpUhEPP3dXw\\ncSJC08JXP8PyofBPG8Ian9iZIXcQgD8K8aZAjQIwLS8kKgAdu8Ht5/Dzd9DyPJxvBZmOQtPM0Ocd\\nJE4MGxLA2ArQ5xpMTguxA15aWcjZFxYlg8zFoXJrwtqct/kgUy7oWw8a/gNNF0HcOdDnU2gbXPy+\\ngf2vocQRqDCfsM122h5oUxFmNYD7/8GrIHbwDuoEMNW8cKomtK4CmVZA5/7Q8SOIXxMiZoCcz6BX\\nD8iSHnpth6p/wt0g7nMZqm+HcgPg7SN4MQqSbIdNFQibYfs+hv1rYHVK2PcI8vwHl4PgwmPIXQey\\njoOLmWDdeEj7EG7dhc5dIc8pWLQY+uaGmX/BkHdQIzXsuQ0Rs8LJX+HxEHi0HJb1h6PvYMRZiPwN\\nlLgIv31EGMBaVwjeTiE88atMhrczoFJrKPQMcjaDHPEIu2Su54Y+D+DBDFhfB47EJrxsvKwAC4MT\\ncxn8+wsc2wNFt8L6lfB3XmgUEXIehVUNYMo9AjUmIgOmwJhx0D8GfPcG4sSC0glh7HdQrA/UPU84\\nA57/idBqHaQbqj+AF3nhalHo9CWcLwSxf4U5n0P8HHAgSHC8hyc54P10uDUOvtwCX42DroFMkx3i\\nn4FkbaBxVBibBa6vgyzfwKh8hGa6QoVg6RHCTFCnIAX5ijCH+M9ZmNgMWrWBz9rD/oGwoyLsSQGP\\nl0FkcLcKrG8EiVJCwo/g4xSEMlbGYKsX2CHzw9TEcOIVlAlwGAHfaAqkyg3Pp0PfO1A1HVSaTwiX\\nqwJKX4YTzyDdh3DnCCQ+BJEKwppx8Pgf2JcXLr+DucHotgSyN4Cc/8JPo2FzWqgfAwq+gBcBB2sB\\nZNgAWfZC87PQqxuU3A1zFsL5JVDgMIzcBMt3QrsWsHIhJKwM80dC4SbQ8T08nAoDxsL7HLC7LxQ4\\nCsWDPOYNeBeY+n+Go3/AqA4wOQpsLgyffwB160Kd4G9YiZD6XTpI0gUIzaNQ+QCsWg1l/4SBr+H8\\nWaj3O/zzL5zfBt/2gPRRofBLQjdhodNw+w9YeQj+KwIf3YTMj+D1JSg/Dfp8B8l2QoKOED06rDsO\\nrxJC4X/hTWKY2RcO1IKNVaBUJcj4I2xdDSs/hMbHoGwmqBOQ1nPD5e9h72M4WQt6DYMaSaAMOFAZ\\nXv8Dh/oS+k6Cb1fDJ4QFF03qw6zShCiWHzrBT7Gg0Bg40B3a/A1TlxHSpRt2gj83QNSjcD4N7E4M\\nK+NC82ywsSEMjwIzLsLmdHC6KEypR7j2bx8LdkaFVV8T5nn/jQOtT8GOITCgHLQ8/L9PKvDhpZsD\\nbZPAgKXwcju8OQW7zsL7svBVfCh6BWLcg/lz4dIOGDsUMgUDUC54HQEy1oQ4v8LOvrD3JZxNB1d+\\ngb2loNAvMHoktEgG86ZD5BTQIgV8/DlhIfrzl5D4FGS+BauTwfr0UPM1nKgLA0HTzpBxLWzYDQu/\\ngBX5YMQ0QvP4rULQeBasbgmTGkLta1DnFLS7BjlrQMy/YOJlQvxjULK+9RHEmwORn/L/YSAGETLo\\n238G7XJDspgQoSSUC3Z+ayF1wCTLDzGyQ4rWsLUqbBsPDUtC3LSQvSfUjwSDO8LAjwmfxBNdoONC\\nSLEUJvwDMUZAyl/hVTx48Ank3wn5H8HWMbCmOVxvBZ0HwZQ8cC4gVNWBJUUh+mHoGUCISkG/mdD3\\nOuGO9qdT0H8JDGsNqUpDsXUwrRfU2Af5ZsEvwYn8M2GO+I8VhDXtAeJ1WXao9g/EvQh1OkG+I/D+\\nAmQ9DFHyQedxUOkOLDoKQ2vB3tmQI1CKvoZWkSDPRhjTlLAJoPhYyFkJhkWGH8fBLyMhSUaYPxj2\\nJYb3v0Ob0bDtEmFf5+cN4FAa6LAGkp4kLGuf+BjiZYNe/eD+dXiWDoq0ItQNimchDN71OwJr1sH1\\nezBsBmRPD/dfw6hVkPYJZD4Ed2/BiVWQKBbcrg5ZW8K517D2Z9DxY/ikAdTYD1fHETpC5rWFfFEh\\n5Sy4kBQOx4M8BaDuUfjgFfyVBGLtI7TL/bUMai2AVPvh28fQdRX0PArdHkGDZJAlNhRKDlu/hoU5\\noccdGFkGjqYmlEjmBpDG2FAxcMAUg5dNYPSXsLwerB4J6QLLZ4CH6Awlc0HmrDAkMxRbCc3SwtCd\\n0Ds57CwC7U5C3Yhw+iPCEP7+qoSW1XMdIV07SH0UBsyEw+Ph5kwYdRditoMvNkGlsoTFFKMqwLc1\\nYXRpWFEQLtyFi3Fg/iQoVBXipofJLaHRUKi4FHKngCjDIGNuSDcCPpkOSz+AtP0g5yKI/BoKN4A/\\nckHybHB/GZwJUB0n4MVVmD0QXl+HzV2g60KYfg82xoXksWFhbxjfHu6fgIR/wN/7oFEW+KUubFoA\\nczPC6EowpSm0+wjW9obp0+BCOWg7GWJ1hajrYP8VyPAMEvSBpf/Bk88Id07n9kKkSfC8DZSMARX3\\nwOzB8PYIfFkIWh+CkRvhUHoI4m7DPoSquaHox7BtOPTKCc3vwpqX0D0ddN8Mby7AqsIwIJBT/4Zt\\nD+DtVvjhGOSOB40DztB/sPRXuB4bMv0BY2rBV2Og8k2IEfhXTkKR0/Dt77AvNjR8B8nTw7Az8GtN\\nGPAnfJETxIMlYwnHnRv5CCuwbscmxAzeSQulG8KyQ9ClM8ycB/sfwrX0sG0/IXogyxrCRs5dw6Fn\\nEoi+Bfa+hYl5Yc5RWFMR3u6B8kGmqRisDyL9X0LGCfDTBtgcEYYEZPNP4exsqD8WdryFccdhcEHI\\nNQRuVoEzO6H8Aci4E7b+DnkTwteLoOMnsK4ozH1JGMKPWB5m9ob07QgBlXMzQLzzhFUzBzZBj2A4\\neAXTqkDZLHDwDJTsDJ/sgOP1YN49SFCGMHzzz3jYlAKO1IFhwX66E3RrAssKw5uK8G4opDwOGxNA\\npL/hXELo1g4+b0KYsK6yCGokgEnlYE6QXT0I0zoT+nEL54N8JaHbK8j4N6Q/DYdOwaA0ULoi1HwH\\nH1WFoy1hVTNIfA0i3oCZUwgJZwVbQYfgoG0PuU7A1TwwaxsMuwlRakHNtIRZy4h/wbmIsHcpdHgK\\nuTvDix8heWeomBwWpYJPChCKhiVzQ77v8P/QQm8LEw6vm89AhW6w9jrMqEb4dN+YDH0zwpTo0HgR\\ndJ8G+ePByUiEbrBDfWDaaEKDRKUkkDs1/BBELmrA644wIDp8VRSGpIIoB6FvGviwOrxfDb/sh4gj\\noGwgtlaFvSlgWiFYVBWefwhZ/4JE72BtwAk7DteHQbp1kOodTGoBze9BzmqwLLhIVIF782FtMph0\\nFWotgcZ/wZF9kGMoPLsJh6vBrB+g66dQZCdMHgwxIsJvu+GbgBA2ExKtg+cjoGBgTQmCcbWhy6cw\\nbwxk/RqmRobxSQkrz4+dhkkdYVFGeJwOAm7P9o8JcbunzsLUuoTQk88fwB/tCUgFkXh3BE7kgpe9\\n4EEBeDoUNgaFBh/B5JOwJiZ80BKeBZHvRvDmNSRaBVEyw6la8OdG2DkWcmaHPyvB9hPw72o4mQma\\nzoDJNWH6QPgxBjRICBe/hgOBKLmX8J4R/2/Yu5ww6VNpHYyfDzWPQ6+lcPU1dI8MEwrD/ABZ1hRG\\nzoVerWDTf3D0OWHNcPfRkHAw7MkMkabB/PvQqhRc+QS274L0ESFmJkIPzZgScOkZbD4GXXLBme9g\\ndly40Abe1oKJ/SDtX5DxQ3j5GP54ArufQqXchMTbb85DxJ2w5wUUK0EY6p7zF6RqBN0Pw3fVoUV3\\nmBAHIjSCuntgzw+w/w9IuYiw1z1JRyg8DtoVgsLFYfNfcH0OdP8GFkSEtzmh5UiIcxqypoaH/0Lb\\nyITpvJ5/wePA6fUSGqeEdInhhy6Q4B848AskOQZDOsDfraBMLrgSmHaHQqQ0sHY0bM0LW8F/syD9\\ndDi+AxK0gI3x4J+N8Flb+GsNrFgET2oSyg1/RYH2SaF3LUIEQEBvmjQTYlYnrFIJ2gI6F4R8HeDI\\nIEJfV/Vh8F1L6N4Akr4jhHPW6w+rAgJ4ZMhVG0r9DSubQud+hDfUhr8S+uHSxYcx6eHeLIh/BVpn\\ngmqZoUofuBPYfitCnm9g2FUYNJbw1jhvMdSoB5Gmwp0eEPUKpPsCmhaG/lmgfSDy9oaEX0L5dJC+\\nBaw4Dx13wLzL8CYhLIoDA1pCqQvQrAsceAitAuBFa7g9BlJshCUDCUXqUoFXbBWh/HrjMvwT7BtS\\nwMNNsPRDmAiyB96dDoTer6uVCMvsA1t0IKTGSgVlo0G0rBA/EAc/hKV9IWJh2H8T+k2BLBUhZUaY\\nGBVeDYC9qWFObvg8EUwYDgUaQOfh8LIvrAtQONnhk5/hbTZYdBIGRIRVY6D+DEjTBxqmhM6x4FZZ\\n+Dw+tO8Ie4/ByluElfarTkKzxJCmF4y9ApGCZ+oijMwDl36C4rth+C5CQGjGNPB9IUgTCUbHg8R7\\nCcHC16PA9uawYi0kPAUx58DvB+BxTegdFZ5lhOrPYcQDKDwRMl2Festg1EVI1gM2viREkn42HXb/\\nArmfQotKUL4VlE0Kd54Rbm6uLYf6deGrnnC2DOyIC1Prw5J4cCc55DtAOFIviwVx60C7bPD4EGE1\\n3IfTYMg+wovQy2+gcTZoPAaKnYPaO6FhRiicCSqAx2mh7u9w9xCsqU5YBhVUVAVdAm3HwJzDMKgN\\npGsIE4vBzLSwZTysKA5RgxR2TdjeF868g4Kv4aPShENe0+GQIwmhWtKxBHTNATNLEO4ClwVdHQdh\\nek/YWBPGDYUmfQnNJP1WwhcTYcnv8GQqfP8XXJ8G0wrChq+hyFN4/xN0OQ0rmsOqcpCqFTRMBSeq\\nw5efw+Xz8OEA2P4ejnwLv92AMkth0o8wOxPUSAH9ukDqhZDnPgycB0XuQrmiEPUepIoMeR5C3oIg\\nUzaoFA/W/AoFfoByD2Dua7iSGJrNge0B9SSIX34K2/rDjVHw8RvIOh8SFoAa02DRfNg5B0ZmhSQN\\nYVhz6BcA/SJA1VSw6zAUf0wYBq7SjzC1tyc31IuD/1979/399QD+DfyhrT1ENEQiKSoJlRHJKpU0\\n0EBlRTLaKbQ0hGRGJdpUUkrRIoqWSksT0R4alNT9w+t+3d/7D3ifc59zn+vxO8cHfd7P9+t1Xc/L\\n0Cbw6pXQsDGc2AzP/A07voW3b4GBE0jLHc46Bcuyw4Ke8OQR6N4UXj8T2txGerw2eYmQ/TX4Kyd8\\nvRyeWAmjv4bafaHD1TArFxztC19sg0+/gD774Ppk3+0imFcAXk9mj5Kyvm3QaAd0TZpFHoUcv8EH\\nt8Jdh+Hc/TA3ORpwGBqOg+ITYWQxeGYDvJILDv8Hc7pDlm1w1cvQLxmszgcr58CKRbA1G3x2Myyc\\nDdM7w7i+8FMlaHsMXku27abB4slQ4F9o8Qi8lAtKFYOfVsH0VlCnD8zLB9N6wvCipPuqSa/Se9fB\\n0LZw7VTYuhKm5IYse+DgNLjjFHy8AhbnhkmfQfMjpHNISfHgivvh7WR/5B6ocT0caAQf3A2bW8O8\\nNXDL7dDuNKyrDCcGwPNb4bzpkPsnyDELNg+Dp5bBg6/CtK9g13442A5KTIHVxyDvxTB7IpR7Fk4M\\nh3bzYH41yNsDtheEJ4vB7F/g2xXQKTe82xIajYC2YOfj8G9vOLoe1gyDJ6+A1U3gaFsYdiMM6wqX\\ndYXn34MRg2HVKvg92cmqBhM6QrYf4c120OshyP8zlBoHFbvC6aRt6B54cAosLgJtpsGidTCsEHzy\\nBOkD/7ffh+2t4Jzq8HBWqLsasj8PC0rC/vJwoiTp3cMGR0hPZCQHdFfeBm9thDOGwN2PwHMHYNlF\\n8NpPUOkt0hafYZXglanw2TYYdhO0agJNjsA978P3h2D09zDxVdK5sSzD4KLpsGAetL4Ezv8XxhyC\\nD/LCRX/BmvdIQ9jId2FAFtKFmIfOIC3CrZYTLn8D/vsbOiyGQeVg5k5oNxmaFoQ2u2DEbihaBHrl\\nhUPD4dRm0q/QC5Pg2wi+3Qo3j4SyyT5XHWjwEOw4CIdehR/+haWNocc80n3M62bD6K1QYQacVwQK\\nPQ0Hf4R2y+Hr86DKGNKm7JefhzbJ6/jkueArpMd0a30IHerBfVNgaGHIXQU6rILrK8DLfeGjn+Hd\\nmdDzcniyDOQ6E6rWhWXloGRDmPQMPJIVVvaEc+ZBi5cg6ySYUwzWJy3/R6HuBJgyGS7aCaWXQcG5\\n0OMjaLEB6paBCXn/5+dd8jQU7wZfXkp6WbLem/BBR9K+vRpXw+q8MLkefLUb7vgblowivXTSsTXk\\nfRAKHYJyK2H1UHjyCRg9HoqPhmYXQ8FRcOEfMOAotM0D+z6Cqieg5ddwSxkoXRSWToc5V0LjfPDi\\nIjg4A5pVhxV3wjtPwMsXwsW14cbx8Nt4+PYYPHgKSt8E1afB5LzQqDSMmQZND0ODu6DMfLjtAeiU\\nzKpOhuNVoOB58HNSalMCPt8DZ+clfV24/RgsfQTu2gjZ2sOaK+G3GnBZHfjnLZiTFbLUgxeLQp3y\\nMLs3lOwLOjeBUklJ4NOQ42UYsADGPgAdJ8OL75LGgg/zwAdvw7KzYOvFsHklNHsSip4Dl06G0Y3g\\nwB64+Cx46iP4+k44mAW+7AF3bYD3e8G3N8MvK2BdF/g6C5TdD8s/hg0Pw4wDpGv5c8rBkR3weSu4\\ntQZ82wXyb4c/58PNOWHYr7B9AFw2GM55E65vDp2vgKq9oNdWaLsWFh6AM3rDugZQtjrc0g2m/Q4n\\nqkGLllC8L2nez/IN6Te5Zu2h5kJ4qwB0/Qcee4T0+uHTFWDjb9AnKaI8AD06wPXfQc3q8GABGL0O\\n9r8Lj7QgXf3NtxLeXQDLi8HQO+CWsbBrOOzvABXLk950q9ocqgyDZfWg+ipY/zC81wP6JvMQreH9\\nX2Hda/DBHzAx6fQaC3V/hNbDYF5LqFAddj4K915KeoU+GV6ufwS2N4TjK6FkH1g0mP8zjbQXRraH\\n/pvg7rowrjmcn7zEqQSFqsNlH8DIhbA6D9zxPbTNCn/Mhwu+hZHT4Nn/oFxuuLcqlN4NC/PAPb+S\\nnvQ5rxbpU5Mnk5ezj5NWYKxLuoCvgPZvw+XV4NeboV/yhOkUdNwOB0vCoEtg41zofT1MyA4VysLK\\nc2D93/DBULjtDnhqM2kRQ1JlefIqePl+aNQeaif3G5KXPrng5CtwqjC02AZrs8DMrlCkK1ybGz4Y\\nBm/vgN++hBeSv2ogNPkSLu4GOYdC8R/h/AfhkhWwYwX8MxX/u8M3GTw4eQbkvBVKbYCcs6HpTVBl\\nNwz9BPYXh2V/Qbv5UG4pXPEGVL8Trj4Oq18n7RhLbg52aQ0FB0HXM+CK/PDCMzDoCjg4Bg5cBnVu\\nhjH94f3jkOUNaJcd2teG65OvIuNh9dnQdSDMaw65kiazApD7OfiiJXy6F67qC3t2wtHlcCqZwXoQ\\nGr4Jq/rD2A8hZy/SVvTVz8D0GlBsMMwYDY/dCYcWw75s0KALvJM89U9qV/+Gq3fA/lOwoAfc9wI8\\nPRPynQn71kLBwfBKG/i0A7TPAeOSr17t4JVF0GwuVMoNOadB81HQqg+szAOPjIdBSf1j8so++RLS\\nCPI8AH82gr2n4Xjy8/4O2cvD2oMwqDBMStqt1sHFd0L96qRXPSougAYDYOBH8E0n+GEWVC4GfoIG\\nD0OJY/DGd3CwDXSdDY1Lw1Xnk35p+Ww3PPckXLgQLvgb2rSA+t2h5gmo3wZ2/AO1HoW170DPP6H7\\nFZDja9IO8bFZYcfbsOVauPNtqPEX1HkROj4Ce9+FnatgZtKjVoR0C3JnbThyBOr2gqvHQr/P4NGk\\nQrMI/HoXlO0CIypDj43wSzbSc3BjdsC/I2B0c9L7KEefhBplYHV1WJgbFk2A79fB3AUwehLphun4\\nQnDZTCj8NGwsCaf/hYtugfW3wJMNYMZ/cPZK+PkWOPNnuG4SrOxN+jZpSkGY0RJ+fwpuKgPrK8N5\\nxeHG2tC/JfyxGqoXgfx94fXRULUUZLkNum2BmXth4n4o/waUKQANNsKwfrBpLmdQ5g6oeC8crEm6\\nfHjzVsh5Dvx4ElYPgdpXwqUPwat9YNplsLUVjB0FU/dB6xpw01DItxv+3Uzay3LRcHioEpzdDiZ2\\nhcdrQvmasKoCrC4OncvAfQXh3O1QqDvsvwr2LIX6NaFJSfh6GOnpklq74XAn+OcIPN8cxn4MJ86F\\nG1eR1s0lv+bO/4x0W/C7N2FJ8sf7TyjThnR64NpPoNeX8GZv2NIJOuaEgUknSjJyuxy+qwtHP4HN\\nQ2DjUtLT0bnnwN9jYP9puCn5wzztf/5t5LwWft0Hv3WEm56Chjtg5gtw5UQYNADOvRaeaQZzhkDJ\\n+tDwBqjzHjz7HbxbF5Ym9X35YHAHaJQTciTr0z2hexV4dQfU/xv25obbk4WJ66DFq9BvPCy/hXRs\\ncEsBeLAr3PwD9GkGZ6+C9vOhxo2kr9s2/glZN8Gr42DZNji9EH4rAVvmwJ+9oNViuPFLmFkcnl4H\\nRwvCJQ/D+FlwoA8c6QcNB5E+jr7iRXh1IDz+KPQ5TBr1trSHj+rB9Mvh/SFQrAZ0yAVPJf34K6H0\\nfjivGTS7ABZUgndHw6XrYNBoOFAdfpkIOZ+DWr/CguLw1C3w/goolzymzgY7VsOv46FTY6hXEb6t\\nDzkuhz3TYOyNpJcY/toLOwvC9vrw+zwo/h602AlXXkI66ZXrMbg8K0wuAbdvhS5g0bWwfxjkngZr\\n+pJe/zyVB+r/AwWbwoMfkD6Ef68BbPoR7jsG4x6APj1JX5KOa0+6OvBXV5jfGE49CutPQ/3FcHIZ\\nnPsTHBgB9QZBx91ww2qoVho6lobl1aHbJhidrPg0gLIbYXDyLbwBDEg6pfrDj6PgVNLusxt63Q/1\\nckHRPLB/DdzRCbruhKtnwrfnw0V5oNoQOHcDjD8D7h5J+jqvR/LMpimsfIH0at75TeDJh0ifEL9Z\\nCm6aCaXehnpTYcS9sHQovL8LOuWC87+EeypCzyEw4A34Ziec3gQDc8D3a6F5cdJLlJ1vgPntSZ8s\\nlloHOY5ApafgqaPQfwfMXghvXwGvJl8YmsMvI2HdSnh2E3yyGKo8DC/1Jf0qsnkXZHsG9m2DiwfA\\nezlh21aoexlcsQm6dIKLppLO8H2e/KnJBVmvgLOSAe0G0DorzFwEu1bAT8nbhrxQvjWsOQvaLoWJ\\n9WD/IThvLLw6jDRmDW8F/f6DnVPg1BoY8DYU3gW7ckKJX+C3HbByBzw0CurugJ4V4YGvYFtzWLAf\\npiQxpQ18fSZc/xDccA8sLAfDk79/FdjcCwb9DLNawI6m0CV56nwh/NsTsh2Hws/BpcVIp7H/XQsD\\nn4XhraFh8nMNh7uOwhXL4fzn4IZ/4O3bYEQl2LMX9iyEcQegxm9wzRC4tD4sWQI1HobiufG/6+C+\\n6wOvfgnzL4Gti+GtFfDHXJg2AjpNhFufhzzJE/Rh0GcRLL4F7j4TOv8GdZbA8e/hy0HwxwtQuCOU\\nWQ9bfoEnDsCqM2DxEJicDR5fDgO+gn3bSTsjNzUlG4d+gLMawLGzYeEKODUXCs2Fnkvgw32wYh3p\\nL52T58LSdnBfkt/zwm3FIfdXUPE5eLMzLLsf+kyGhsnWQAeo9j1peUH1H0j3v5oNg3/rwL2HSbc/\\nHn0RFiQfAFmh9HdQ4UOoOhn6fwv5HofsS+CXIlByCOzOClbA2UvguX1QdzbpFtgVFaD2VJh5NeQq\\nCHcchA3jofwaqN8UCiyCq66CxRXhub5wzw7Sl5IFe0LrhnD563BhDTgxAq5JupuPwndnkm57JQ2z\\nSWVr8gEwrCjM/ggu2Q5L/4BzkqdNo+Df7+D2FaA+LJwBvTrDhZ/Db6/AdWXg81+hZg3SeDq3EeTf\\nBnUGwpfnwpKDsLky/JHsvLwIq3ZAv72QYyyUHAcFD8HLxeDe5Mncw+BeaDsNTtxLegV9R084fibc\\n1wem5INP/4Mzm8N9a+DnO6FSD9Lx9iZJR9FiaHUV6X3MYXNIi0nbJw+iD0HvB+D3pTDvNHyxEl76\\nFX5vDoeTaSRwbim4PdkVPQrzy0PNZON1HZSbCpV/gyNnwYqj8EdTmDMZvj8Kba6EuVdBub1wcgjs\\nPwdefAZefAtyN4Xf34MHRkLe2+BwB/iyOWlHXdNacORG2NUfvpsBJZLZqeLwdUc48inc/xFs6QwN\\n9kKPL+Cxr6BIM9KXfXfWhRmL4cJko+0cyFYYjr8Nh6rCVUmj28twbVKW+DR0rw0r+sKFveDQv3BP\\nJbj5STiyFR58B15uAQ+PhQsvh6rfQJ5RcNnj8NVQeCgnPF8ZBg2FI8n8WSH4bQFUOAMmd4SB58GG\\nLqTzQI0nwV2FIOud/J/1/sXwzyFotwPu+g+qFYWqzaDaMCg8HxrOI713tvVyaP4M9LkEVkyBdbPh\\ncA7I2w8qXAOPPQbHNkL3NnDpNhhXGp7qDa8shUVPwoAboFBTKD4ZFmeHe/6EGr9A/a2w4hwoewKu\\nfpT0wubqbfDaTNhYFjovI71vWOUgfH4TLO0BeXORXtc4eSZsOg6PnoS275M+d8/6FXy4ATZvgXs2\\nwOzcUKAetMoNZx2DYsfh2X2w9l2odBE8UQTeGQ3tboB198LJZMQ7F+nRnp3J5mxjuH497LsdRl4M\\nQyuQnvLtVx42tYNV50DWAtDveqgzC/LeDYNOwe1vQJbTcOxRWHgDZL0Xkp2QN/fCP82hwYdwvDXp\\nIkiz52DY2bC/Pml57O5PYN+DsPBR0lGBw4NhTC2o8jQ8Vg1GVobrXoaW38ITueCmt2FlF3hmCKz6\\nCH4dBM8ltcnLIc950OUpWDQMav0IDR+Cw+Ng3EYo1hgePQSbV8HdydrTTHijGBSpD8vHwOqScE0u\\nGNoHyh2BETNh5AtwzSNwbito/D7pRKApkL0ndLwBWtWCSb/Cfy/AjIpwKB/kOg2t88MTQ6H3lzC6\\nNBSvR/pUe8lHUOBPuDgL1LwCDt8B759PehjqvMJQ9gbYsxrqZ4fRj0PO+TAZ5G8LfWrBFQ1A8vUg\\nP5x+HL5cQxb+2g8PzYau30ONy+DPGlDvCFx4Co52Ir1JN+ZPePoOaNgJXgHlK0CbRyHPV7DwU+ha\\nAkqug3494Eh9+KEM1J4GA1rBnwdIawvqTCCdVKh4N7wFXroTev0KrT6FPp1gxylotgumJFsYJeGv\\nZaRdF4P/g9k9/+c/xu7X4K8OUGMinD4NP78HlYtCvzlw9wNw16dQahqMyEL6nKl8Hxi0Eq78EKYn\\neTYn7L0bHr4azmoH5afBlENQYjZsLg+915G+4tl2FC5fBh++Bd2+Ji28+HUHdNwLfyeR9wyo2h8q\\nfQvVepCWqp1RGZ79v5pRpk6HwU3go+7QYiZs2Q2lq0OjZvDt23DX13C4L1SaBT/UhQ/2wN0fw4BF\\npGcffjwEpy6AQrfDwUug98Mwbh2cNxoa3QTZu8A1OaBIEjhAi+SnWwN/XQiPjYO1k6DsEdKLhCPb\\nwkcfw5+1ST8GVrwO7SpB/fdJG+fH7ofKyX7KVFhyKZw4BF3OgUtuhK2t4dmT0GoL5OgPN2aBe0bA\\n1qlw912kw/7N50P5ijBvC5SYDxcMh5Efw7Hc8MUu+OVOeCA/tL0Zuo+F8rXg8ZbQ/jEoe4j0Alrx\\nXDDjZ/iwEPw6Afr+AfXKQtb3oeZlpKdLznoARl0ANU/CU69Cr0fhszWknWSfNoYBG+F4VThcGMbl\\ngP7nwv5LYF1byLIaVtWBV76FWXfBu/kgZyPI9hyUmACzboLKfWFCFzirC1xdCPLdAk/PhgMT4Xhn\\nmNMDsj8HDV+E116Ca86F+YVgeh9oPAw6roD+2eDnC2F7afhrKCydApM/hoM/w9rP4LmkqagtnH8r\\nLE1epZ1DWjlROKkAOAnrq0DvgXDR6zBqOGlx8cSc8Oc1sHwX3PUxrOsBNQ/Buo8ge1KoUQSmb4OG\\n7aDG73A0C8w9DPlnwadtSU9/JBGnxk749CXSTeECm2FCRVCY9LdWtwGQ5Ut4owBs70x6JL7q35B/\\nBbRLftu/Rrr32r8bDFgF/xUmfbn/+vVQYT0MPAuOfQfPbIO/TsGI4fDSd1Atmd7bArtaQPGxcFsx\\n+Ho7ZG8D89+DhU/A3Jkw5moo2oH0PcDyPvDPJ7Dsb+h2G7xyDQz8CtpPhbLjoP0gaLULbhoGLx6H\\nvfWh6Qtw5Qb4JFmySWoOPoEK70DrefBVV/jmP9h/IWnh55GkzuMROLEVWn4Dh66ETSfh4pzQaAl0\\newWqfAHlf4dpt0KRg9D1X6h4H5QoBVOuhlMbYV0l0tPX191Geu3gmlug3+9QdRJU3gevN4I/waw7\\nocXZMKcfvPUItLsAypaACypAlxzQ+wDpafA+LaDCGMj1MJzXArr9AxOTGb4usHYNPHgN6au9Itng\\nkyzwVEPYfCVM6govdYK+OeFka2j8JFT8C7K2hXO6Q/6hcHN70t7EBU/BiIUwpA/ctIT0pvDVdeDK\\nRVC5LNQtCtV7wZ3jSUtZn18DJfdC5xvhhZlwT1uY/gVs6A8tR8Br93MGjX6FsrVh70TY/gbUXk16\\nhe26i+GC7+GzgXB2JWhcFHaWhA7doeAJWLwKbr8WWl4PN9wG13eGRf2h5x+Q+25YmRsG3QU2Q4FX\\n4N47IOs3MK42ZGkP94PmT8PgwZBtD5wqCaWT/bhcUHkIFFoL7yQv+5I+m1rwUXPSs7gNH4ajTeGl\\nVvBzE8j/IRT5Fy7pA2c3hhvehcP1YdwceKYHLC8FubuStuiOPgWqwZYn4YxcUKs2vPQZ5LoMdleC\\nz3PA3GUwdyycHAezd0Gxq2HL7/D9cBh8BHqug1wz4IZO8PoN8Eg1KLQdbjsA//SGl5J/wg2kEzPr\\nj8F1pWDsHaTPIS47CnuGQNWX4Nhw+CAPHD8JI2vCvC/grflQ43648XkYdR9U+xP67YZcSU9xF2j4\\nEWweD50rQ6FTcO8X8MxRmH4XtH4LRt0E1/0Dn+QhfXrRujCsvwFeuwQq9IDrvoA1+WBeNli7gfQg\\nzPNPkR4dalMBer0LpR+HHcPgjh5w+hvSGZ3tv8PJzVB+FOy4GuYvh49zQ8kS8M/ZsOQwHH+LdMdt\\nejGo+h/0SjZPz4LZ98KkfrBzFnS8Dyb2hXt7w4qXoObP0PtaeHsUzCwDF/8DZx+CD0fBv+Wg7Va4\\n/Gq4vSX0rAuvnw9T90PdUXCkFFS6Bz6+HvZ2h7NvhlWt4PMBIAf89DQ0OACjZsCpOyHns5CvEkyt\\nCB8nQ9D3Qvtu0H8j6QWCk5eQNi3Vv/B/fupk2umxG+DFitCtNlSeBftuhM63wOHNpMd2llWEdwvD\\nxOxQojfpmfbsW6D7PNIK4lofw8dZYdgvcEF/qNMe3psF794Bgx+AVqXh8nOgZgNokJQdzId7noAa\\nhWHmCjhjO1zWAP7JBRs+gVkLSD9u50yAI8lMVUmoPQYGLSQdrhjTFJZfRjpm+/p+qFME1reB4cPg\\np/FQrzwkvTS7BkGPzvBDc9L5zmuSXfLF0PV8aNkScuYkvXzXaxHptcGG18K23lChBGS/kLRLfVNj\\nyJp8mpyA6/rAngfguxxwaSG47xPYMAXaPgbV/4NnpsKNL8KdyUrQFthYC15/ATothhaToPgo2DsP\\nmt0Jj+WAFr/Bt4/DFUmc3QMvT4XbRsPgZdAv2cubCE/mIm2wu/kElDoPZneEaRXgmZ2kX/J/rANf\\nvQiNkxKc0qTt4Z+2h7pTIWdBGJUdtpwgXVXpejdUOgntPoPCp2H/OtIzTW1egDIPw537SKeRFlwK\\n1/SELBvg5Z9IHzpMux163wZXdYKZg2FuQ5hfBe7uD8/fD5MHwtLX4JUJ8MVNcGEF0k/wK7PBoWww\\n/CR0ugpumQm/JJ+bC+C3eqSDH0dHQO780DuZkN4Hr3aGDcn/RTfBRTdC/knQ/RXocTbUfAjGvwtH\\nz4OW9eHKpMJpIlzzPulg+/jV0GkPNPkOrr2f9JDOR5/BRRvgv/1w3ZdQIzsMOQK/vQFHKsPj70DL\\nFdB6FjTPCw90hhnJ+5x/oHhhyLWcLPz9EOzKB/8thFNDoGxPyJP0queGvU9Au8dhYLK0fBSOl4LL\\n88KmSyF/AzjQDeo2ga51YGc9yLUEJpaGH+pB1TFQ8k7YNww+fguKT4WaY6BaOXj7DKi4BpoNhNJZ\\n4fGSMO4DOLkebs0DeWbAsVowZDj07w+7JkCtgbB1BeReDFO7wPkvwqx80KYezN0IXarCWVXhi1/g\\nkyqQZwR8NAbeeQQKtYdmSfSsBkMfhyufgKcrke5QbC8O7x2Dnsuh1HTIUxOGfAvFWkDOx+D0DGjx\\nJ9y3E8qWgh7Xw5BjcNU6KPAc7FoKDabDz8Ng0xyoNQoan4Be2aHrOtKDxOWS0fVuMGk0XLIRyt0K\\neQrAQxVh8PfQbiK81Q22N4V6RWBbXmg1EtZMgKtGwfXZ4fXkY6YydDgTRjeEcw7Dj8Vgymtw4jP4\\nuhXpVtHxPaQtX53vg5fXw7aiUOlHqL0JFs6FpvPgjelwZV4onJ+062vlW/DxE7CwDHyWHzY+CbXW\\nw4OXwsY+ULsArNwEL2+DWTWg+S3Q+DBpm3mZxfDOCvhrPOkUyJI2pBWRw5tAqxlQpgS83hAm7IKB\\ns+HMz2H8M9D0UtIzLM/dSjqZN+BbqJi8mLubdGn5wGE4fSM0ugvWD4EOreGnT2DFFsj/OtSaAz9e\\nBLWXQvNZkK87addaxyOwoC68MA5GFIAi1eHirDB9DDS+G34aCpd1gLG1Satri22BP7+BJg3huhGw\\nI3lhfR3keBV+6Qh9l0CuZbDnWdiTFABOhEJ14Pb28GwXqFQUXhhBWnfStQf8NAyuXwt/lId298Gi\\nX6DnVTDnGag+GR4oAhePhxWnYHELaJ5MPo2B8+vCi2dD9qqwtSKUuAP6DYdXzoPNVWDlENIn5Seu\\nhZovwzXJN/VTUOVHuDkPTK8OzWbD72/CinxwZDvU+560wKXoJthaAY4mww+1YFdjeL8cdFgLl86C\\n4y+StrhVzAstX4fzH4ay7aFRdmhUGfoXha1XQI+1pDvORzqSvri/6A/YtgRaPAAL+sLBSXDl41Di\\nO2hyLdTLAhfcCse6wicVYEojqFuS9HJA2d/hq7Vw+wxofS+cdwms2k66k/hA8sRiBDT/A0qcgNxf\\nQ9Hu0KYHtKxL+lq533p4rSdsmwQ7k6nZa+GWE6RFzeM3Q9GScNUgeKkJDO4Lt9eAW/LASydIo17y\\n22xCGfhhJExfCP9tghE3QpWV8PEBqHMcrtoItzaBTeXh3Wvg4qSE+XNYXgTePQh/fwzlHoW89eHc\\nerBmF3SrBHsLwt53oHoyZfsFDGoKt50ivWUy/S3SvqsHX4F626DCWqg0F0adhK3JlPDlsLEUXLAb\\n6nWBbROgcgF4bxL89xmMrAK7D8Jr+6FaZdiX/JucCDl2w+L3oOFe0oLcHhfBO0Pg9V5wtAZcvRd2\\n3Azbt8Osp+CScqQFzg26wZ4W8FVFqP8g7LmI9BNn+8+wahE07w6jHiFdNjqVC9bPgzlN4b2iUHAt\\nZ8AfyTxMCCGEEELIgCz/r/8BQgghhBD+fxMBK4QQQgghwyJghRBCCCFkWASsEEIIIYQMi4AVQggh\\nhJBhEbBCCCGEEDIsAlYIIYQQQoZFwAohhBBCyLAIWCGEEEIIGRYBK4QQQgghwyJghRBCCCFkWASs\\nEEIIIYQMi4AVQgghhJBhEbBCCCGEEDIsAlYIIYQQQoZFwAohhBBCyLAIWCGEEEIIGRYBK4QQQggh\\nwyJghRBCCCFkWASsEEIIIYQMi4AVQgghhJBhEbBCCCGEEDIsAlYIIYQQQoZFwAohhBBCyLAIWCGE\\nEEIIGRYBK4QQQgghwyJghRBCCCFkWASsEEIIIYQMi4AVQgghhJBhEbBCCCGEEDIsAlYIIYQQQoZF\\nwAohhBBCyLAIWCGEEEIIGRYBK4QQQgghwyJghRBCCCFkWASsEEIIIYQMi4AVQgghhJBhEbBCCCGE\\nEDIsAlYIIYQQQoZFwAohhBBCyLAIWCGEEEIIGRYBK4QQQgghwyJghRBCCCFkWASsEEIIIYQMi4AV\\nQgghhJBhEbBCCCGEEDIsAlYIIYQQQoZFwAohhBBCyLAIWCGEEEIIGRYBK4QQQgghwyJghRBCCCFk\\nWASsEEIIIYQMi4AVQgghhJBhEbBCCCGEEDIsAlYIIYQQQoZFwAohhBBCyLAIWCGEEEIIGRYBK4QQ\\nQgghwyJghRBCCCFkWASsEEIIIYQMi4AVQgghhJBhEbBCCCGEEDIsAlYIIYQQQoZFwAohhBBCyLAI\\nWCGEEEIIGRYBK4QQQgghwyJghRBCCCFkWASsEEIIIYQMi4AVQgghhJBhEbBCCCGEEDIsAlYIIYQQ\\nQoZFwAohhBBCyLAIWCGEEEIIGRYBK4QQQgghwyJghRBCCCFkWASsEEIIIYQMi4AVQgghhJBhEbBC\\nCCGEEDIsAlYIIYQQQoZFwAohhBBCyLAIWCGEEEIIGRYBK4QQQgghwyJghRBCCCFkWASsEEIIIYQM\\ni4AVQgghhJBhEbBCCCGEEDIsAlYIIYQQQoZFwAohhBBCyLAIWCGEEEIIGRYBK4QQQgghwyJghRBC\\nCCFkWASsEEIIIYQMi4AVQgghhJBhEbBCCCGEEDIsAlYIIYQQQoZFwAohhBBCyLAIWCGEEEIIGRYB\\nK4QQQgghwyJghRBCCCFk2P8CIYLjWY1OH1IAAAAASUVORK5CYII=\\n\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"% Create an RGB image with no title or labels\\n\",\n    \"image = zeros(300,400,3);\\n\",\n    \"image(1:100,:,1) = 0.9;  % Red\\n\",\n    \"image(101:200,:,2) = rand(100,400);  % Green\\n\",\n    \"image(201:300,:,3) = 0.9;  % Blue\\n\",\n    \"imshow(image)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"\\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg height=\\\"420px\\\" viewBox=\\\"0 0 560 420\\\" width=\\\"560px\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\">\\n\",\n       \"\\n\",\n       \"<title>Gnuplot</title>\\n\",\n       \"<desc>Produced by GNUPLOT 5.1 patchlevel 0 </desc>\\n\",\n       \"\\n\",\n       \"<g id=\\\"gnuplot_canvas\\\">\\n\",\n       \"\\n\",\n       \"<rect fill=\\\"none\\\" height=\\\"420\\\" width=\\\"560\\\" x=\\\"0\\\" y=\\\"0\\\"/>\\n\",\n       \"<defs>\\n\",\n       \"\\n\",\n       \"\\t<circle id=\\\"gpDot\\\" r=\\\"0.5\\\" stroke-width=\\\"0.5\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,0 h2 M0,-1 v2\\\" id=\\\"gpPt0\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,-1 L1,1 M1,-1 L-1,1\\\" id=\\\"gpPt1\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1\\\" id=\\\"gpPt2\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<rect height=\\\"2\\\" id=\\\"gpPt3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\" width=\\\"2\\\" x=\\\"-1\\\" y=\\\"-1\\\"/>\\n\",\n       \"\\t<rect fill=\\\"currentColor\\\" height=\\\"2\\\" id=\\\"gpPt4\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\" width=\\\"2\\\" x=\\\"-1\\\" y=\\\"-1\\\"/>\\n\",\n       \"\\t<circle cx=\\\"0\\\" cy=\\\"0\\\" id=\\\"gpPt5\\\" r=\\\"1\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt6\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt5\\\"/>\\n\",\n       \"\\t<path d=\\\"M0,-1.33 L-1.33,0.67 L1.33,0.67 z\\\" id=\\\"gpPt7\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt8\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt7\\\"/>\\n\",\n       \"\\t<use id=\\\"gpPt9\\\" stroke=\\\"currentColor\\\" transform=\\\"rotate(180)\\\" xlink:href=\\\"#gpPt7\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt10\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt9\\\"/>\\n\",\n       \"\\t<use id=\\\"gpPt11\\\" stroke=\\\"currentColor\\\" transform=\\\"rotate(45)\\\" xlink:href=\\\"#gpPt3\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt12\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt11\\\"/>\\n\",\n       \"\\t<path d=\\\"M0,1.330 L1.265,0.411 L0.782,-1.067 L-0.782,-1.076 L-1.265,0.411 z\\\" id=\\\"gpPt13\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt14\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt13\\\"/>\\n\",\n       \"\\t<filter filterUnits=\\\"objectBoundingBox\\\" height=\\\"1\\\" id=\\\"textbox\\\" width=\\\"1\\\" x=\\\"0\\\" y=\\\"0\\\">\\n\",\n       \"\\t  <feFlood flood-color=\\\"white\\\" flood-opacity=\\\"1\\\" result=\\\"bgnd\\\"/>\\n\",\n       \"\\t  <feComposite in=\\\"SourceGraphic\\\" in2=\\\"bgnd\\\" operator=\\\"atop\\\"/>\\n\",\n       \"\\t</filter>\\n\",\n       \"\\t<filter filterUnits=\\\"objectBoundingBox\\\" height=\\\"1\\\" id=\\\"greybox\\\" width=\\\"1\\\" x=\\\"0\\\" y=\\\"0\\\">\\n\",\n       \"\\t  <feFlood flood-color=\\\"lightgrey\\\" flood-opacity=\\\"1\\\" result=\\\"grey\\\"/>\\n\",\n       \"\\t  <feComposite in=\\\"SourceGraphic\\\" in2=\\\"grey\\\" operator=\\\"atop\\\"/>\\n\",\n       \"\\t</filter>\\n\",\n       \"</defs>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"\\t<g id=\\\"gnuplot_plot_1a\\\"><title>gnuplot_plot_1a</title>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"<image height=\\\"342.2\\\" preserveAspectRatio=\\\"none\\\" width=\\\"342.2\\\" x=\\\"118.6\\\" xlink:href=\\\"gp_image_01.png\\\" y=\\\"31.6\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\t</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"% image that is too small to display raw (<100 pixels)\\n\",\n    \"imshow(rand(50,50))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 48,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"\\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg height=\\\"420px\\\" viewBox=\\\"0 0 560 420\\\" width=\\\"560px\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\">\\n\",\n       \"\\n\",\n       \"<title>Gnuplot</title>\\n\",\n       \"<desc>Produced by GNUPLOT 5.1 patchlevel 0 </desc>\\n\",\n       \"\\n\",\n       \"<g id=\\\"gnuplot_canvas\\\">\\n\",\n       \"\\n\",\n       \"<rect fill=\\\"none\\\" height=\\\"420\\\" width=\\\"560\\\" x=\\\"0\\\" y=\\\"0\\\"/>\\n\",\n       \"<defs>\\n\",\n       \"\\n\",\n       \"\\t<circle id=\\\"gpDot\\\" r=\\\"0.5\\\" stroke-width=\\\"0.5\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,0 h2 M0,-1 v2\\\" id=\\\"gpPt0\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,-1 L1,1 M1,-1 L-1,1\\\" id=\\\"gpPt1\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1\\\" id=\\\"gpPt2\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<rect height=\\\"2\\\" id=\\\"gpPt3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\" width=\\\"2\\\" x=\\\"-1\\\" y=\\\"-1\\\"/>\\n\",\n       \"\\t<rect fill=\\\"currentColor\\\" height=\\\"2\\\" id=\\\"gpPt4\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\" width=\\\"2\\\" x=\\\"-1\\\" y=\\\"-1\\\"/>\\n\",\n       \"\\t<circle cx=\\\"0\\\" cy=\\\"0\\\" id=\\\"gpPt5\\\" r=\\\"1\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt6\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt5\\\"/>\\n\",\n       \"\\t<path d=\\\"M0,-1.33 L-1.33,0.67 L1.33,0.67 z\\\" id=\\\"gpPt7\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt8\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt7\\\"/>\\n\",\n       \"\\t<use id=\\\"gpPt9\\\" stroke=\\\"currentColor\\\" transform=\\\"rotate(180)\\\" xlink:href=\\\"#gpPt7\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt10\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt9\\\"/>\\n\",\n       \"\\t<use id=\\\"gpPt11\\\" stroke=\\\"currentColor\\\" transform=\\\"rotate(45)\\\" xlink:href=\\\"#gpPt3\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt12\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt11\\\"/>\\n\",\n       \"\\t<path d=\\\"M0,1.330 L1.265,0.411 L0.782,-1.067 L-0.782,-1.076 L-1.265,0.411 z\\\" id=\\\"gpPt13\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt14\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt13\\\"/>\\n\",\n       \"\\t<filter filterUnits=\\\"objectBoundingBox\\\" height=\\\"1\\\" id=\\\"textbox\\\" width=\\\"1\\\" x=\\\"0\\\" y=\\\"0\\\">\\n\",\n       \"\\t  <feFlood flood-color=\\\"white\\\" flood-opacity=\\\"1\\\" result=\\\"bgnd\\\"/>\\n\",\n       \"\\t  <feComposite in=\\\"SourceGraphic\\\" in2=\\\"bgnd\\\" operator=\\\"atop\\\"/>\\n\",\n       \"\\t</filter>\\n\",\n       \"\\t<filter filterUnits=\\\"objectBoundingBox\\\" height=\\\"1\\\" id=\\\"greybox\\\" width=\\\"1\\\" x=\\\"0\\\" y=\\\"0\\\">\\n\",\n       \"\\t  <feFlood flood-color=\\\"lightgrey\\\" flood-opacity=\\\"1\\\" result=\\\"grey\\\"/>\\n\",\n       \"\\t  <feComposite in=\\\"SourceGraphic\\\" in2=\\\"grey\\\" operator=\\\"atop\\\"/>\\n\",\n       \"\\t</filter>\\n\",\n       \"</defs>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(289.7,14.3)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">Hello</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"\\t<g id=\\\"gnuplot_plot_1a\\\"><title>gnuplot_plot_1a</title>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"<image height=\\\"342.2\\\" preserveAspectRatio=\\\"none\\\" width=\\\"342.2\\\" x=\\\"118.6\\\" xlink:href=\\\"gp_image_01.png\\\" y=\\\"31.6\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\t</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg height=\\\"420px\\\" viewBox=\\\"0 0 560 420\\\" width=\\\"560px\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\">\\n\",\n       \"\\n\",\n       \"<title>Gnuplot</title>\\n\",\n       \"<desc>Produced by GNUPLOT 5.1 patchlevel 0 </desc>\\n\",\n       \"\\n\",\n       \"<g id=\\\"gnuplot_canvas\\\">\\n\",\n       \"\\n\",\n       \"<rect fill=\\\"none\\\" height=\\\"420\\\" width=\\\"560\\\" x=\\\"0\\\" y=\\\"0\\\"/>\\n\",\n       \"<defs>\\n\",\n       \"\\n\",\n       \"\\t<circle id=\\\"gpDot\\\" r=\\\"0.5\\\" stroke-width=\\\"0.5\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,0 h2 M0,-1 v2\\\" id=\\\"gpPt0\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,-1 L1,1 M1,-1 L-1,1\\\" id=\\\"gpPt1\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<path d=\\\"M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1\\\" id=\\\"gpPt2\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<rect height=\\\"2\\\" id=\\\"gpPt3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\" width=\\\"2\\\" x=\\\"-1\\\" y=\\\"-1\\\"/>\\n\",\n       \"\\t<rect fill=\\\"currentColor\\\" height=\\\"2\\\" id=\\\"gpPt4\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\" width=\\\"2\\\" x=\\\"-1\\\" y=\\\"-1\\\"/>\\n\",\n       \"\\t<circle cx=\\\"0\\\" cy=\\\"0\\\" id=\\\"gpPt5\\\" r=\\\"1\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt6\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt5\\\"/>\\n\",\n       \"\\t<path d=\\\"M0,-1.33 L-1.33,0.67 L1.33,0.67 z\\\" id=\\\"gpPt7\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt8\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt7\\\"/>\\n\",\n       \"\\t<use id=\\\"gpPt9\\\" stroke=\\\"currentColor\\\" transform=\\\"rotate(180)\\\" xlink:href=\\\"#gpPt7\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt10\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt9\\\"/>\\n\",\n       \"\\t<use id=\\\"gpPt11\\\" stroke=\\\"currentColor\\\" transform=\\\"rotate(45)\\\" xlink:href=\\\"#gpPt3\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt12\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt11\\\"/>\\n\",\n       \"\\t<path d=\\\"M0,1.330 L1.265,0.411 L0.782,-1.067 L-0.782,-1.076 L-1.265,0.411 z\\\" id=\\\"gpPt13\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"0.333\\\"/>\\n\",\n       \"\\t<use fill=\\\"currentColor\\\" id=\\\"gpPt14\\\" stroke=\\\"none\\\" xlink:href=\\\"#gpPt13\\\"/>\\n\",\n       \"\\t<filter filterUnits=\\\"objectBoundingBox\\\" height=\\\"1\\\" id=\\\"textbox\\\" width=\\\"1\\\" x=\\\"0\\\" y=\\\"0\\\">\\n\",\n       \"\\t  <feFlood flood-color=\\\"white\\\" flood-opacity=\\\"1\\\" result=\\\"bgnd\\\"/>\\n\",\n       \"\\t  <feComposite in=\\\"SourceGraphic\\\" in2=\\\"bgnd\\\" operator=\\\"atop\\\"/>\\n\",\n       \"\\t</filter>\\n\",\n       \"\\t<filter filterUnits=\\\"objectBoundingBox\\\" height=\\\"1\\\" id=\\\"greybox\\\" width=\\\"1\\\" x=\\\"0\\\" y=\\\"0\\\">\\n\",\n       \"\\t  <feFlood flood-color=\\\"lightgrey\\\" flood-opacity=\\\"1\\\" result=\\\"grey\\\"/>\\n\",\n       \"\\t  <feComposite in=\\\"SourceGraphic\\\" in2=\\\"grey\\\" operator=\\\"atop\\\"/>\\n\",\n       \"\\t</filter>\\n\",\n       \"</defs>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"\\t<g shape-rendering=\\\"crispEdges\\\" stroke=\\\"none\\\">\\n\",\n       \"\\t\\t<polygon fill=\\\"rgb(255, 255, 255)\\\" points=\\\"72.8,373.8 252.4,373.8 252.4,31.7 72.8,31.7 \\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"rgb(255, 255, 255)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,373.8 L81.2,373.8 M252.5,373.8 L244.1,373.8  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(67.2,377.5)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">1</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,288.2 L81.2,288.2 M252.5,288.2 L244.1,288.2  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(67.2,291.9)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">1.5</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,202.7 L81.2,202.7 M252.5,202.7 L244.1,202.7  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(67.2,206.4)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">2</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,117.1 L81.2,117.1 M252.5,117.1 L244.1,117.1  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(67.2,120.8)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">2.5</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,31.6 L81.2,31.6 M252.5,31.6 L244.1,31.6  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"end\\\" transform=\\\"translate(67.2,35.3)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">3</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,373.8 L72.8,365.4 M72.8,31.6 L72.8,40.0  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(72.8,389.5)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">1</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M117.7,373.8 L117.7,365.4 M117.7,31.6 L117.7,40.0  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(117.7,389.5)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">1.5</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M162.7,373.8 L162.7,365.4 M162.7,31.6 L162.7,40.0  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(162.7,389.5)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">2</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M207.6,373.8 L207.6,365.4 M207.6,31.6 L207.6,40.0  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(207.6,389.5)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">2.5</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M252.5,373.8 L252.5,365.4 M252.5,31.6 L252.5,40.0  \\\" stroke=\\\"black\\\"/>\\t<g fill=\\\"rgb(0,0,0)\\\" font-family=\\\"{}\\\" font-size=\\\"10.00\\\" stroke=\\\"none\\\" text-anchor=\\\"middle\\\" transform=\\\"translate(252.5,389.5)\\\">\\n\",\n       \"\\t\\t<text><tspan font-family=\\\"{}\\\">3</tspan></text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,31.6 L72.8,373.8 L252.5,373.8 L252.5,31.6 L72.8,31.6 Z  \\\" stroke=\\\"black\\\"/></g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"\\t<g id=\\\"gnuplot_plot_1a\\\"><title>gnuplot_plot_1a</title>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"\\t<path d=\\\"M72.8,373.8 L162.7,202.7 L252.5,31.6  \\\" stroke=\\\"rgb(  0,   0, 255)\\\"/></g>\\n\",\n       \"\\t</g>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"rgb(  0,   0, 255)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"\\t<g id=\\\"gnuplot_plot_1b\\\"><title>gnuplot_plot_1b</title>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"1.00\\\">\\n\",\n       \"<image height=\\\"179.7\\\" preserveAspectRatio=\\\"none\\\" width=\\\"179.7\\\" x=\\\"327.0\\\" xlink:href=\\\"gp_image_01.png\\\" y=\\\"112.9\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\t</g>\\n\",\n       \"<g color=\\\"white\\\" fill=\\\"none\\\" stroke=\\\"rgb(148,   0, 211)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"2.00\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"black\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"<g color=\\\"black\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-width=\\\"0.50\\\">\\n\",\n       \"</g>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"% let's add a title - this produces full figure\\n\",\n    \"imshow(rand(100,100))\\n\",\n    \"title('Hello')\\n\",\n    \"\\n\",\n    \"% let's create an image next to a plot\\n\",\n    \"figure\\n\",\n    \"subplot(121)\\n\",\n    \"plot([1,2,3])\\n\",\n    \"subplot(122)\\n\",\n    \"imshow(randn(100,100))\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"anaconda-cloud\": {},\n  \"kernelspec\": {\n   \"display_name\": \"Octave\",\n   \"language\": \"octave\",\n   \"name\": \"octave\"\n  },\n  \"language_info\": {\n   \"file_extension\": \".m\",\n   \"help_links\": [\n    {\n     \"text\": \"GNU Octave\",\n     \"url\": \"https://www.gnu.org/software/octave/support.html\"\n    },\n    {\n     \"text\": \"Octave Kernel\",\n     \"url\": \"https://github.com/Calysto/octave_kernel\"\n    },\n    {\n     \"text\": \"MetaKernel Magics\",\n     \"url\": \"https://metakernel.readthedocs.io/en/latest/source/README.html\"\n    }\n   ],\n   \"mimetype\": \"text/x-octave\",\n   \"name\": \"octave\",\n   \"version\": \"6.3.0\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 4\n}\n"
  },
  {
    "path": "test/jupyter-notebook/plot-magic-and-errors.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"id\": \"healthy-group\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAABLAAAAOECAIAAAA+D1+tAABPq0lEQVR42u3deXxU5aH44TMkiBggIexEFjdwrY3I1VpBENS6QIFCW6ylFWxrb8WCqKDFa+2ntLZY8YprtLYuFGVTa9GCqCBYEatoFTUliiyCyCaLiQLJ/P6Y352bGyAMyeBA3uf5a3Lmncl7zpwJ82XOnInF4/EIAACA8NTL9AQAAADIDEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIAAAQKEEIB4olS5bE/sdzzz1X5dr3338/ee2TTz6ZWHjvvfcmlnTt2nVff93f/va3J5988sknn1y3bl2mV/3AtXnz5h/96EcFBQX169fPzc397LPPUrnVBRdcEIvFBg8evNtr//rXv55zzjktW7Y87LDDOnXqdM0112zYsCGVu03xhukdVrfdcMMNiWdQ//7997Qk7caNG5f4Feeff35iyZf5RN71d+2nVd4ff2F23XQHpoNlnl++L+H5BdRAdqYnAGTG4MGDt23bFkXRnDlzevXqlenpHKCuu+66+++/P3F5y5Ytqdxk+vTpzzzzzJ6u/dWvfnXjjTcmf1y6dOktt9wyderUf/zjH23btq3mblO8YXqHceA7YJ/IB+zEAKjCO4RwEGvcuHHHjh07duzYpk2bTM+lbpo9e3biQrdu3W699dZDDjlkt8MqKirWrl07f/78H//4x9/5znf2dG+vvfbaL3/5y8TlU045pV+/focddlgURcuXL7/iiiuqmUaKN0zvML40X+YT2R8NAKrwDiEcxC6++OKLL74407Ooy9auXZu4MHr06AsvvHBPwyZMmHD11Vfv9d4eeeSReDweRVGfPn2efPLJWCw2c+bMiy66KIqimTNnfvrpp3l5ebW5YXqH8aX5Mp/I/mgAUIV3COEgttuPHu3YseOee+7p1q1b27ZtGzVqdNJJJ33/+99/8803kwOuu+66WCyWOJoriqLevXvHYrHKn45bu3btL37xi3POOadVq1atWrXq3bv3mDFjPvroo10nUFJS0r9//2bNmuXl5Q0YMGD16tWJO4/FYjfccENiTOUPjezcufO//uu/Dj/88P/6r/9KXFtRUfHoo4/27NmzQ4cOhx56aIcOHXr06PHggw/u2LEj+VuS9zBo0KCPP/74kksu6dixY5MmTXr37v3yyy9HUfTKK6985zvf6dixY7NmzXr27Dl37ty9brq9ruO6deuWL19eUVGR+PHTTz9dvnz5zp07a/xgxePxqVOnJi4PHz48FotFUXThhRd26tQpiqLt27c/9dRTtblheoftVuWHctOmTT/96U8LCgpycnK++tWv/uY3v6n8kKW+I1Wze9TycU9l19qryy67LDGHdu3aVV7+0UcfJT/T+/bbb1dzDytWrPjOd77TvHnz1q1bDxgw4IUXXth1TNqfyNVs1eo/r1hcXPz973//qKOOatu27be//e0XX3xxTw9W5eWDBw9OLL/mmmuiFP7CvP/++1deeeUZZ5zRuHHjo4466lvf+tbrr79es01X/V5ayz84Ke7nqc9zn54Raflzl/q6pPjgpnGG1e9sKe4q1T/ce30SAf9fHDgwVH5ZOWfOnCrXlpSUJK994oknEgvvueeexJJTTz01seTzzz//j//4j12f6bFY7M4770yMGTNmzK4Dtm3blrj2H//4R35+/q4DmjRp8uyzz1ae0ksvvdS8efPKY4488shvf/vbictjx45NDBs7dmxiSb9+/X74wx9WuTY5voqBAwcmf1HyHrp06dKhQ4fKww455JDf//739evXr7Kyc+fOrWZTp7KO/fr123XAe++9t9s73LRpU8n/SK7jd7/73cpjVqxYkZze1q1bk8t//OMfJ5Zffvnlu73zFG+Y3mG7lXwgevTocdxxx1XZOIMGDdrXjVz97lHLx32fdq1+/frtdsmcOXOSN3zzzTeTN/zTn/6UWHjsscdWs6e9+uqrrVu3rvzbs7Kyevbsmbj8jW98Yz89kavZqrv+ruTgwsLCKg9Z/fr177nnnmo2V8J3v/vdxPKrr746vre/ME8//XTDhg13Xa+rrrqqBpuumr209n9wUtnPU5/nvj4j0vLnLvV1SfHBreUMU9/ZUtxVqnm4U3kSAQneIYQD0ZAhQ475v84+++xUbjhu3LhFixZFUZSTk/PNb35z+PDhp512WhRF8Xj85z//+XvvvRdF0dVXX11SUpL42FgURQ8++GDyx7Kysosvvnjjxo1RFB166KHnnXfeBRdckLhqy5Yt3//+97du3Zq41eeffz5o0KD169dHUXTIIYecccYZbdu2/eCDD6ZMmbKnuf3zn//885//XHnJlClTEuNjsdjZZ589ZMiQk046KXHVtGnTnn/++Sr38Nprr61cufKrX/3qUUcdlViyffv2a6+9dseOHccdd9yJJ56YWBiPx2+66aY9TSP1dUxdXl7eUf9jT8dbJrZV4qFp1KhRcnnyJC57OslnijdM77DqzZ0799133+3QocNpp5126KGHJhZOnTr11VdfrfFG3nX3qM3jvq+71p706NGjVatWictPP/10cnnyw6V7CozEJAcOHPjxxx9HUZSdnX366ad37NixvLw8lXe6avlETmWr7mrx4sUbN25s2bJl9+7dc3JyoijasWPHz372s3feeSfFe0ioZmJbtmz5wQ9+UFZWFkXR2Wef/ctf/nLw4MH16tWLx+O33nrrAw88UPtNV8267+tesdf9PPV51uAZkZY/d6mvSw3UZoZ73dlS3FWqebhTeRIBCYIQDkSrV68u+b+Sb+xUL/ma5re//e0TTzxx++23L1y48JxzzomiaOfOnYlvs2jWrNlRRx1Vr97/f/oXFBQcddRRiUMHx48f/+GHH0ZR1KRJkxdffPHvf//7zJkzFy5cmHgn8OOPP/7Nb36TuNXdd9+9evXqKIpyc3MXLlz40ksvrVy58rLLLqtmbqtWrTr++OMfeeSRhQsXXnrppVEU/f3vf09cNXLkyOeee+7BBx/817/+lZhtFEWvvfbarnfy1FNPLV68eOnSpYMGDUouvO22295555233npr9OjRiSVvvfXWnqaR4jo+/vjj8Xg8mUyJ92w7d+5c48c0GVqVMyyxARMXkqlWsxumd9heTZw48cMPP1y4cOHixYuTry+TLy5T35GSdt09KtvXx70Gu9ZuZWVlJX9jMgjj8fizzz6buFxNEN5///3Lly+Poqhx48YLFix4+eWXly1bNmLEiFR+by2fyClu1V317dt3xYoV8+bNe/fdd48++ugoisrLy3/xi1+kuLkSqpnYzTffnPgWioEDBz733HM33njjX/7yl9tuuy0xMpkNtdl01ax7DfaK6vfz1OdZg2dElI4/d6mvS83UZobV72wp7irVPNypPImABEEIdUri/1OjKLrzzjsfeOCBxDlRHn744bfffvvtt9/+1re+Vf3NZ86cmbhw5ZVXJj9idNJJJ1111VVVBiTfCbziiisKCwujKKpXr97tt9/esmXLPd35YYcd9uyzz37ve9877bTTjjzyyCiKvvOd7zzyyCOPPPJI8iXUli1bVq1albic+N/0yk499dQLLrggiqJYLHbeeeclFubl5V155ZWJy8lv/fr0009rv47ptXnz5sSF5EuxhGSY7WnOKd4wvcOqd+KJJybPR3rsscd269YtcTnx4rhmG3nX3SOpBo/7vu5a1UgeMvePf/xj06ZNURQtXrw4kc3HHXfcCSecsKcbTp48OXEh+dZEFEU333xzixYt9vpLa/lETmWr7qp+/fp33XVXgwYNoihq167db3/728Typ59+ury8PPUtVo1kkiUPUY6iaOjQoVlZWVEUrVixIlEOtdl01az7vu4Ve93PU59nDZ4Raflzl/q61EBtZrjXnS3FXaWahztdTyIIgSCEA9GunyFM/O/yXiX/VS4uLh42bFibNm26dOkyceLEzz777IQTTqjyWZddFRcXV7mfhHPPPTdxYenSpYnzrPz73//edWTDhg2r3LCywsLCKt9xd955533ve9+74IILXnrppauvvrpXr16HH374u+++u6d7KCgoSF7Ozv7/J0lu27Zt8l2R5MK0rGN6NWnSJHGhtLS08vLkj1XestvXG6Z3WPWSR4glJD8LlNxuNdjIu+4eSTV43Pd116rGGWeckTijTHl5eeJI0VSOF40qPUcqfzt5gwYNkhuhGrV8IqeyVXd14oknVt7UyWlv3749xb8/e7V06dLEhXPPPTd5Vp5GjRolgzOx0Wqz6apZ933dK/a6n6c+zxo8I9Ly5y71damB2sxwrztbirtK0m4f7uTGr82TCEIgCKFOuemmm6666qrki/54PP7666+PGzfutNNO6969e+IInD3ZsmVL8u2jKt9RlvyH9vPPP1+7du2WLVuS/5te5d/gKidjrKzKGWiiKNq+ffuoUaNatmw5ePDgP/zhD88//3x2dnY1X49W5XC4hOSRaalIfR1r/1hUkXwFVuUL7pPz2XX77NMN0zuselUeiCo/1mwjV/N7a/C47+uuVf3KJr9bMnHUaDIIKx8mV8W2bds++eSTxOUqLz3bt2+/119amydyilt1V8lPSybk5OQkDyRO8ZD16m3ZsiV56tE9Wb9+fS03XTXrXss/OFV+TH2eNXtG1P7PXerrkpb73KcZVr+zpbirVP5x14c7XU8iCIEghDqlfv36f/jDHz766KPHHnvse9/7XtOmTZNXzZ8//9prr63mtk2aNEn+k7xmzZrKVyV/POSQQ1q0aNG4cePkAYdV/lWuJqV2ffUwbty4W2+9defOne3atbv55pvffPPNdevWJY5B2k9SX8e0/+rk65XPP/88+eqw8hbb02v3FG+Y3mFf/kZOyyvUpPTuWsmjRp955pmtW7e+9NJL0d6OF23YsGHyXIvJbEiovNn3pDZP5Bpv1cTJUZLKysqSU63mP3pS16RJk8aNGycuz549u2R3Bg8eXMtNV826p3evSH2eGfyzc8CqfmdLcVepfA+7PtzpehJBCAQh1B1ffPHF2rVr165d+8UXX3z7299+5JFHPvnkk2effTZ56u158+ZVfw/Jk6Ykz5lR5cdjjjkmOzs7FosdccQRiSWVz6e3c+fO1M/fGEXRXXfdlbgwffr00aNHf+UrX8nKykp+pGc/SXEd0/57O3TokDxFe+UHIrkBk5/qqdkN0zvsIN3ISendtbp06ZI46cW6detuueWW7du3R3s7XjQrKyv5HJk1a1ZyeTwe3+v3ZNb+iVwz77zzTuJMUVWmfcghhyTWJfmau8pHwqrkUDUSmzGKop07dx5VSdOmTfPy8vLy8ho2bFibTVe99O4V+zTPjD8j9qr2D+4+2evOlsquUs39Z+pJBAcpQQh1x7vvvtu6devWrVu3b98+eSb03r17Dxs2LDFgt9+IUPmf/+R/lv/3f//34sWLE5fffvvt8ePHJy4nP+lx1llnJS7ceuutifN3x+Px66+/ftmyZSnOduvWrcl3F5P/N/zaa6/tU1LWQOrrmHbJ0xj84Q9/SETFU089lTjNev369S+66KLEtTNnznzssccee+yx5Fcwp3jD9A47SDdytH92reSbhLfcckviQvVBGEXRqaeemrhw++23Jx/K3/zmN3v9FofaP5FrZvv27cOHD098WfmaNWuSXyfYp0+fxJk8ku8TvvLKK8lPcM2YMaP6Tqs8sd69eycuFBUVxePxxOXp06c3a9asefPmRxxxROJAwRpvumrsj70i9Xlm9hmRipo9uDW2150txV1lT2r2JIJgZfK/o4D0+spXvtKqVau1a9eWlpYWFhZedNFFjRo1euedd1588cXEgP79+ycH5+XlJf5BHT9+/LJly37+85/Xr1//2muv/dOf/rR8+fLNmzd//etf7927d7169ebMmfPZZ59FUdSmTZsbbrghcfPrrrvugQce2L59+7p167p06XLaaactX778gw8+SH22jRo1atSoUWIO3/zmN3v37h2Lxf7+978nXiLsP6mvY9pdcsklt912W0VFxYsvvtihQ4e2bdv+61//SlzVp0+f5BFNI0aMKCkpiaLoiiuuOOWUU1K/YXqHHaQbOdo/u9Z3v/vdX//619H/nH3n+OOPP/744/e6ESZPnhyPxz/99NOvfe1rp5122rp161L59rPaP5FrvJozZsw44ogjjj322FdffTXxKdOsrKxx48Ylrk3sjVEUlZWVFRYWnnLKKevWrUueLqWK3U7suuuuu//++zdt2vTEE0+cffbZZ5111pIlS5In2LzqqqsSu1+NN1019sdekfo8M/uMSMU+PbhpUf3OluKusif79CQCvEMIdUe9evUef/zxxIE0H3/88f3333/bbbfNnj37888/j6KoR48elT81kXyL75VXXrnmmmsS7xQ1bNhw0qRJiX9oy8rKnnrqqSeffDLxkqVDhw5TpkxJfkC/ffv2d955Z+KlZ2lp6QsvvPDBBx+0bNky+aVeexWLxS688MLE5dLS0r/+9a9PPvlkQUFB8j+Gq3zYJl1SX8e0KywsTERF4gF6/fXXd+7cGUXRUUcddeedd9b+hukddpBu5Gj/7FonnHBC8ou2oxTeHoyi6OSTT05+zGn79u3z589/77336tWrt9eDcmv/RK6ZvLy8evXqffTRR88991ziBfohhxxy3333JQ937NKlS/Kd0tLS0gULFhQXFx955JHJDVvZbifWtGnTe++9N3Fs5Ny5c2+66aZp06Ylvh7g8ssvv/HGG2u56aqxP/aK1OeZ2WdEKvbpwa29ve5sKe4qe7JPTyJAEEKd8rWvfa2kpGTs2LFdu3Zt27ZtgwYNOnXq1KdPnz/+8Y/PP/984kufEiZMmHDxxRe3bNkyJyfnxBNPTJ4a7utf//o777xz3XXX9erVq1WrVs2bN+/Zs+f111//1ltvnXnmmZV/12WXXTZnzpwBAwa0bdu2oKDgW9/61iuvvJL8b+ZUTJgw4aSTToqiqF69eieffPLIkSMXL17cp0+fxLWTJ0+ucmLxdEl9HdPuuuuumzlz5jnnnNOiRYtDDz30mGOOGT169KuvvrrXc6CneMP0DjtIN3K0f3at5MvlqNrzi1Z2//33Dxw4MHG5ZcuWffv2feaZZ6r5apak2j+Ra6BHjx7z5s3r06fP4Ycf3qZNm29/+9svvPBCla+zf+ihh8aNG3fSSSc1bNiwVatWw4YNS367+q4PwW4nNmjQoH/+85/Dhg075ZRTDjvssCOPPLJfv37z5s27++67K58XpMabrhr7Y69IfZ6ZfUakIvUHt/ZS2dlS3FX2JPUnERBLHpkNUHs/+MEPHnrooSiK7rnnnp/85Cd7Hb9jx46nnnoqFos5gKeyd95554QTTrj++uuTB1Cxr9K+a7388stnnHFGFEXHH3/8kiVLUr/hq6++Onfu3J/85CcZfxfooJP2Tbef/uB4iIGDms8QAjXx4x//+NVXX42i6MILL0wef7ht27bkV7Ql/id+r+rXrz9gwIBMr80BJ3HaicrHKLKv0r5rvfzyy4kLqRwvWlnXrl27du2a6e1xUEr7pttPf3A8xMBBTRACNdGmTZs33ngjiqIlS5Z07NixT58+q1atuvbaaxPnczvxxBO7dOmS6TkerB588MGrr766U6dOffv2zfRciOLx+L333rty5cpbb701sWRfgxAADmQOGQVqorS09LzzzluwYMGuVzVr1mzu3Lne3aqxnj17HnvssTfeeGMaP9FHjZWXl1f+grj+/fvPmDEj05MCgLQRhEANffHFF4899tiDDz74wQcfrFmzpnnz5h07djz33HNHjBjhgzTUGeXl5U2aNMnOzj7mmGMuuuii6667zukoAKhLBCEAAECgfO0EAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoARhTXzwwQedO3d+8803d3vt1KlTBw0aVFhYeOaZZ15//fXr1q3bf2MAAABqTBDWxMMPP7ynqyZMmDB27NiSkpKuXbvm5ORMnz590KBBGzdu3B9jAAAAakMQ7oMtW7a89tprN95441/+8pfdDiguLi4qKmrVqtWsWbOKiopmzZo1ZMiQNWvWTJw4Me1jAAAAakkQ7oM+ffpcfPHFjz766J4GTJ06taKiYsSIES1btkwsGTNmTG5u7qxZsyoqKtI7BgAAoJYE4T4YN27cXXfdddddd51xxhm7HbBo0aJ69er16NEjuSQrK6t79+4bNmxYvHhxescAAADUkiDcB2eeeWavXr169epVUFCw67XxeLykpCQ/Pz8/P7/y8k6dOkVRtHLlyjSOAQAAqD1BmDalpaXl5eV5eXlVlufm5kZRlDgfTLrGAAAA1F52pidQd5SVlUVRlJOTU2V5o0aNoijavHlzGsdUr3PnzpneGAAAkGbFxcWZnkIdJAjTJi8vLxaLlZaWVlm+bdu2KIqaNGmSxjHV6Ny5s6cKByO7Lgcj+y0HKbsuByPveewnDhlNm+zs7Nzc3F3fwduyZUsURYnzhaZrDAAAQO0JwnRq1arVhg0bEuWWtGzZssRV6R0DAABQS4IwnXr16lVeXj5//vzkkng8Pm/evPz8/MLCwvSOAQAAqCVBmE4DBw6MxWJ33HFH4vN+URQVFRWtX79+wIAB9evXT+8YAACAWnJSmXQqKCi49NJLH3jggb59+3br1m358uULFy5s27bt0KFD0z4GAACglgRhmo0ePbp9+/aTJk2aMWNG48aN+/fvP2rUqGbNmu2PMQAAALURi8fjmZ4D6eRE0hyk7LocjOy3HKTsuhyM7Lf7ic8QAgAABEoQAgcE/+fHwch+y0HKrgskCUIAAIBACUIAAIBACUIAAIBACUIAAIBA+R5CAEiDWCy2P+7Wt0MBsF8JQgBIj96xgem9wznxaZleJwDqOIeMAgAABEoQAgAABEoQAgAABEoQAgAABEoQAgAABEoQAgAABMrXTgAQnP30nYEAcNARhACEyHcGAkDkkFEAAIBgCUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBAZWd6AgDAHsVisbTfZzwez/RqAXCgEIQAcODqHRuY3jucE5+W6XUC4ADikFEAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBAZWd6AgCwR7FYLNNTAIC6TBACcEDrHRuY9vucE5+W6dUCgAOCQ0YBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAAClZ3pCdQ127dvf/DBB5955plly5Y1bdr0pJNOuuKKK4455pgqw6ZOnTplypSSkpKcnJzu3buPHDmyRYsWNRgDAABQY94hTKfy8vIf/OAHt9xyy6ZNm7p161ZQUDBr1qxvfvObr776auVhEyZMGDt2bElJSdeuXXNycqZPnz5o0KCNGzfu6xgAAIDaEITp9Nhjj73++uvnn3/+s88+e/vttz/88MN/+tOfoigaO3ZsckxxcXFRUVGrVq1mzZpVVFQ0a9asIUOGrFmzZuLEifs0BgAAoJYEYTq9/vrrURT94Ac/yM7+/8fifu1rXzvuuOM+/PDD5Jt7U6dOraioGDFiRMuWLRNLxowZk5ubO2vWrIqKitTHAAAA1JIgTKf69etHUVT5wM6KiopPP/20Xr16yURctGhRvXr1evTokRyTlZXVvXv3DRs2LF68OPUxAAAAtSQI02nIkCG5ubnjxo17+eWXy8rKVq9e/V//9V+rVq0aMmRIkyZNoiiKx+MlJSX5+fn5+fmVb9ipU6coilauXJniGAAAgNpzltF0Ou644x577LGBAwf+8Ic/TC68/PLLR44cmbhcWlpaXl6el5dX5Ya5ubnR/7y1mMoYAACA2hOE6bRly5brr79+27ZtJ5xwwoknnrhx48YFCxY88sgjJ5544jnnnBNFUVlZWRRFOTk5VW7YqFGjKIo2b96c4pjqde7ceU9XFRcXZ3ojAQDAHlXzUpb9QRCm0zXXXPP666+PGTPm0ksvTSz56KOPBg8ePHLkyKeeeuqII47Iy8uLxWKlpaVVbrht27YoihKHlaYypnqqDwCAg9SeXsoKxf3EZwjT5pNPPpk7d+7RRx+drMEoigoKCv7zP/9zx44dM2bMiKIoOzs7Nzd313f5tmzZEkVR4pyiqYwBAACoPUGYNhs2bIiiqGPHjlWWH3nkkVEUrVu3LvFjq1atNmzYkKi7pGXLliWuSn0MAABALQnCtOnYsWNWVtbSpUvj8Xjl5Yl3vY8++ujEj7169SovL58/f35yQDwenzdvXn5+fmFhYepjAAAAakkQpk3Dhg27d+++fPny22+/Pfn18UuXLr3rrrsOOeSQnj17JpYMHDgwFovdcccdic8ERlFUVFS0fv36AQMGJL7GMMUxAFAzsf0j06sFQE04qUw6/frXvx44cOBdd931zDPPHH/88evXr3/ttdcqKirGjh171FFHJcYUFBRceumlDzzwQN++fbt167Z8+fKFCxe2bdt26NChyftJZQwA1Ezv2MC03+ec+LRMrxYANSEI06l58+ZPP/30Pffcs2DBghdeeKFp06ZnnXXWT3/605NOOqnysNGjR7dv337SpEkzZsxo3Lhx//79R40a1axZs30dAwAAUBuCMM0OO+ywq6666qqrrqp+2ODBgwcPHlz7MQAAADXmM4QAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBys70BACoI2KxWKanAADsG0EIQNr0jg1M7x3OiU/L9DoBQF3mkFEAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBACUIAAIBAZWd6AgBkQCwWy/QUAIDME4QAgeodG5jeO5wTn5bpdQIA9o1DRgEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAKVnekJ1EFvvfXWvffeu2TJkm3btnXu3Hn48OGnnXZalTFTp06dMmVKSUlJTk5O9+7dR44c2aJFixqMAQAAqDHvEKbZ888/P3jw4Oeff75ly5aFhYWLFy8eMmTI888/X3nMhAkTxo4dW1JS0rVr15ycnOnTpw8aNGjjxo37OgYAAKA2BGE6bd68efTo0dnZ2Q8//PBjjz1WVFQ0efLkQw455IYbbqioqEiMKS4uLioqatWq1axZs4qKimbNmjVkyJA1a9ZMnDgxeT+pjAEAAKglQZhO06dP37Jly+WXX96lS5fEkq985Svnn3/++vXr33rrrcSSqVOnVlRUjBgxomXLloklY8aMyc3NnTVrVjIaUxkDAABQS4IwnV588cVYLNavX7/KC3//+98XFxeffPLJiR8XLVpUr169Hj16JAdkZWV17959w4YNixcvTn0MAABALTmpTDq9/fbbTZs2bd269T//+c/Fixd/+umnxx13XK9evRo2bJgYEI/HS0pK8vPz8/PzK9+wU6dOURStXLmyS5cuqYzJ9IoCQFWxWCzt9xmPxzO9WgB1nCBMm+3bt2/duvXoo4/+5S9/OXny5OTy9u3bT5gw4cQTT4yiqLS0tLy8PC8vr8ptc3NzoyhKnDMmlTHV69y5856uKi4uzvR2AqBu6h0bmN47nBOflul1AjKgmpey7A+CMG22bt0aRVFJScm6detuvvnmHj16fPHFF9OmTbvzzjt//vOf/+1vf2vYsGFZWVkURTk5OVVu26hRoyiKNm/eHEVRKmOqp/oAADhI7emlrFDcT3yGMG0OPfTQxIWbb765f//+iWNHr7jiiv79+69atWrmzJlRFOXl5cVisdLS0iq33bZtWxRFTZo0SXEMAABA7QnCtMnJyTn00EMbNmzYs2fPyst79eoVRdF7770XRVF2dnZubu6u7/Jt2bIliqLEOUVTGQMAAFB7gjCdWrZsWb9+/Sqfqj/ssMOiKNq5c2fix1atWm3YsCFRd0nLli1LXJX6GAAAgFoShOnUs2fPLVu2/Pvf/6688PXXX4+i6Nhjj0382KtXr/Ly8vnz5ycHxOPxefPm5efnFxYWpj4GAACglgRhOvXv3z+KorFjx27atCmx5K233vrjH/+Ym5t7zjnnJJYMHDgwFovdcccdic8ERlFUVFS0fv36AQMG1K9fP/UxAAAAteQso+l03HHHDR48ePLkyeedd17Xrl0/++yzV199NRaLjRs3rlmzZokxBQUFl1566QMPPNC3b99u3botX7584cKFbdu2HTp0aPJ+UhkDAABQS4IwzW688cbOnTs/+uijL730UtOmTXv16jV8+PBjjjmm8pjRo0e3b99+0qRJM2bMaNy4cf/+/UeNGpUsxtTHAAAA1IYgTLNYLDZ48ODBgwdXPyxdYwAAAGrMZwgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAAClZ3pCQCwF7FYLNNTAADqJkEIcBDoHRuY3jucE5+W6XUCADLPIaMAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBEoQAAACBquNBWFhYOH78+D1dO3z48PPOOy/TcwQAAMiMOh6EpaWlO3bs2NNVK1as+OijjzI9RwAAgMzIzvQE0m/evHk//elPkz8+9NBDjzzyyK7DKioq4vF4+/btMz1fAACAzKiDQZiVldWkSZPE5U2bNh1yyCGHHXbYbkfm5uZed911mZ4vAABAZtTBIDzzzDMXLlyYuNy5c+fvfve7119/faYnBQAAcMCpg0FY2bBhw0499dRMzwIAAOBAVMeD8Nprr830FAAAAA5QdTwIoyh65plnHnrooQ8//DAej+92QPL4UgAAgKDU8SCcM2fOiBEjEpezsrIyPR0AAIADSB0Pwvvvvz+Koh/84Ac/+9nPcnNzMz0dAGAfxGKxtN/nno4YAghTHQ/CkpKSww8/fMyYMfXq1cv0XACAfdM7NjC9dzgnPi3T6wRwYKnLmbRjx46tW7e2a9dODQIAAOyqLpdSvXr1cnNzly5dWlFRkem5AAAAHHDqchBmZWVddtll69evnzBhQqbnAgAAcMCp458hvOCCC1auXFlUVLRw4cILLrigoKDgkEMOqTKmR48emZ4mAABABtTxIOzVq1fiwr/+9a9//etfux1TXFyc6WkCAABkQB0Pwr59+2Z6CgAAAAeoOh6E48ePz/QUAAAADlB1+aQyAAAAVKOOv0N4+umn73XMwoULMz1NAACADKjjQbhly5YqS+LxePJrCVu3bt28efNMzxEAACAz6ngQvvPOO1WWlJeXr169+tlnn7377ru/+OKLX/7yl5meIwAAQGYE9xnCrKysdu3aDR06dOLEiZs3bx45cmQ8Hs/0pAAAADIguCBMOv30048++uiVK1euXLky03MBAADIgHCDMIqili1bRlHUrFmzTE8EAAAgA8INwtLS0nfeead58+Y5OTmZngsAAEAG1PGTyrz88su7Xb5p06ZHHnlk48aNvXv3zvQcAQAAMqOOB+EPf/jDaq5t3Ljxz3/+80zPEQAAIDPqeBD27dt3T1e1b9++X79+7dq1y/QcAQAAMqOOB+H48eMzPQUAAIADVB0PwqSPP/743XffXb58+Y4dO4488sjjjjuubdu2mZ4UAABAJtX9INy0adPEiRMfffTR8vLy5MKsrKxvf/vbI0eOzM3NzfQEAQAAMqOOB2F5eflPf/rTxYsXN2jQoHfv3h06dMjKylq2bNncuXMnT5783nvvTZo0KSsrK9PTBAAAyIA6HoR//vOfFy9e/NWvfnXixImJr6FPWLdu3fDhwxcvXvznP/952LBhmZ4mAABABtTxL6afP39+LBa77bbbKtdgFEUtWrT47//+73r16s2bNy/TcwQAAMiMOh6E7733XocOHdq0abPrVa1atTrqqKPee++9TM8RAAAgM+p4EDZo0KCsrGxP15aVlTVs2DDTcwQAAMiMOh6Exx9//Nq1axcvXrzrVW+//faqVauOPfbYTM8RAAAgM+p4EPbt2zeKoiuvvPLFF1+svHzBggVXXHFFFEV9+vTJ9BwBAAAyo46fZfT888+fO3fuE0888aMf/ahNmzYdO3aMomj58uWrV6+OoqhPnz4XXXRRpucIAACQGXU8CKMouvnmm0877bTbbrttzZo1a9asSSxs0aLFyJEj+/fvn+nZAQAAZEzdD8JYLDZgwIABAwZ88sknH374YTwe79ixY6tWrTI9LwAAgAyr+0GY1LJly4qKigYNGjRt2jTTcwEAAMi8unlSmZ07d/71r3/96U9/+sILL1RePnv27K997Wt9+/a95557du7cmelpAgAAZFIdfIdw3bp1w4cPT3zVRL9+/f7P2mZnx+Px4uLi4uLi2bNn33rrrYnTzAAAAASorr1DWF5ePmTIkMWLFzdr1uyKK6449dRTK1978cUXz549+9prr23cuPGSJUt+9KMfVfO19QAAAHVbXQvCxx9//IMPPujQocP06dOHDx/erFmzKgM6dOgwbNiwZ555pqCgYMWKFVOmTMn0lAEAADKjrgXh008/HUXRVVdd1aZNm2qGtWjRYuzYsVEULVy4MNNTBgAAyIy6FoQrVqyIouiss87a68ivfe1rsVjsww8/zPSUAQAAMqOuBeEnn3zSpEmThg0b7nVkw4YNmzZt+tFHH2V6ygAAAJlR14KwWbNmW7du3bp1615Hbt68eePGjU2aNMn0lAEAADKjrgVhu3bt4vH4W2+9tdeRb775ZhRFhx9+eKanDAAAkBl1LQgvuOCCKIr++Mc/xuPxaoaVlZX97ne/i6LoG9/4RqanDAAAkBl1LQj79OnTtm3bBQsWjBkz5tNPP93tmPXr148cObKkpKR58+b9+/fP9JQBAAAyIzvTE0iznJycCRMmDB069Iknnpg9e/bFF1/ctWvXww8/vGXLluvWrVuxYsU///nPSZMmlZWVNWjQ4JZbbsnNzc30lAEAADKjrgVhFEVf/epXH3vssWuuuebdd9+9//7777///l3HdOzY8fe///3JJ5+c6ckCAABkTB0MwiiKjjnmmMcff/z555+fOXPmO++8s2bNms8//7x+/fpt2rTp1KnTN77xjQsuuCArKyvT0wQAAMikuhmEURTFYrFevXr16tUr8eOWLVsaN24ci8UyPS8AAIADRZ0Nwip83yAAAEAVde0sowAAAKRIEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAARKEAIAAAQqO9MTAKg7YrFYpqcAALAPBCFAOvWODUz7fc6JT8v0agEAdZNDRgEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCPej1atXd+nS5Zprrtn1qqlTpw4aNKiwsPDMM8+8/vrr161bV7MxAAAANSYI95d4PD569Oht27btetWECRPGjh1bUlLStWvXnJyc6dOnDxo0aOPGjfs6BgAAoDYE4f7y5z//edGiRbsuLy4uLioqatWq1axZs4qKimbNmjVkyJA1a9ZMnDhxn8YAAADUkiDcL5YuXTphwoRjjz1216umTp1aUVExYsSIli1bJpaMGTMmNzd31qxZFRUVqY8BAACoJUGYfjt37rz22mubNm06ZsyYXa9dtGhRvXr1evTokVySlZXVvXv3DRs2LF68OPUxAAAAtSQI02/ixInvvvvub3/72yZNmlS5Kh6Pl5SU5Ofn5+fnV17eqVOnKIpWrlyZ4hgAAIDay870BOqaN95447777rvkkkvOOOOMJUuWVLm2tLS0vLw8Ly+vyvLc3NwoihLnjEllTPU6d+68p6uKi4szvYUAAGCPqnkpy/4gCNOprKzs2muvbdeu3ahRo/Y0IIqinJycKssbNWoURdHmzZtTHFM91QcAwEFqTy9lheJ+IgjT6Xe/+92qVasmT57csGHD3Q7Iy8uLxWKlpaVVlie+nSJxiGkqYwAAAGrPZwjTZtGiRZMnT/7JT35y8skn72lMdnZ2bm7uru/ybdmyJYqixDlFUxkDAABQe4IwbZYuXRpF0V133dX5fwwYMCCKor/+9a+dO3e+6KKLEsNatWq1YcOGRN0lLVu2LHFV6mMAAABqySGjadOhQ4cLL7yw8pLNmzcvWLCgbdu2hYWFrVu3Tizs1atXcXHx/Pnzk4Pj8fi8efPy8/MLCwtTHwMAAFBLgjBtzjzzzDPPPLPykiVLlixYsODUU08dP358cuHAgQPvvvvuO+6446yzzkqcJ6aoqGj9+vWXXXZZ/fr1Ux8DAABQS4Lwy1ZQUHDppZc+8MADffv27dat2/LlyxcuXNi2bduhQ4fu0xgAAIBaEoQZMHr06Pbt20+aNGnGjBmNGzfu37//qFGjmjVrtq9jAAAAakMQ7kcnnHDCnr5HZfDgwYMHD67+5qmMAQAAqDFnGQUAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAhUdqYnAADw5YnFYvvjbuPxeKbXDKAmBCEAEJDesYFpv8858WmZXi2AGnLIKAAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKAEIQAAQKCyMz0BgMyIxWKZngIAQIYJQiBcvWMD03uHc+LTMr1OAAD7wCGjAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgcrO9AQAAA56sVgs7fcZj8czvVpA3ScIAQBqq3dsYHrvcE58WqbXCQiCQ0YBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAAClZ3pCQDsXSwWy/QUAADqIEEIHBx6xwam9w7nxKdlep0AADLMIaMAAACB8g5hmpWVlU2ZMmXatGmrVq1q1KhRp06dhg4d+vWvf73KsKlTp06ZMqWkpCQnJ6d79+4jR45s0aJFDcYAAADUmHcI02nnzp0//OEPf/Ob36xdu/b0008/+uijX3nllaFDh955552Vh02YMGHs2LElJSVdu3bNycmZPn36oEGDNm7cuK9jAAAAakMQptOUKVPeeOONLl26zJs37+677/7Tn/70+OOP5+Xl3Xnnne+++25iTHFxcVFRUatWrWbNmlVUVDRr1qwhQ4asWbNm4sSJyftJZQwAAEAtCcJ0+vvf/x5F0S9+8YuGDRsmlhxzzDGXX355eXn5Sy+9lFgyderUioqKESNGtGzZMrFkzJgxubm5s2bNqqioSH0MAABALQnCdFq2bFlOTs4JJ5xQeWGHDh2iKFq5cmXix0WLFtWrV69Hjx7JAVlZWd27d9+wYcPixYtTHwMAAFBLgjCd7r333kcffbTKwoULF0ZR1K5duyiK4vF4SUlJfn5+fn5+5TGdOnWK/icaUxkDAABQe84ymk7HH398lSULFy6cNm1agwYN+vXrF0VRaWlpeXl5Xl5elWG5ublRFCXOGZPKGAAAgNoThPtLeXn5pEmTfv/73+/cufPWW29t3rx5FEVlZWVRFOXk5FQZ3KhRoyiKNm/enOKY6nXu3HlPVxUXF2d6wwAAwB5V81KW/UEQ7hevvPLKTTfd9P7777dp02bcuHHJ7yHMy8uLxWKlpaVVxm/bti2KoiZNmqQ4pnqqDwCAg9SeXsoKxf1EEKbZ9u3bx48f//DDDx966KHDhw8fNmxY8oyjURRlZ2fn5ubu+i7fli1boihKnFM0lTEAAAC1JwjTqaKiYtSoUbNnzy4sLJwwYUKbNm12HdOqVauSkpItW7ZUfq9v2bJliatSHwMAAFBLzjKaTg8//PDs2bMHDhw4adKk3dZgFEW9evUqLy+fP39+ckk8Hp83b15+fn5hYWHqYwAAAGpJEKZNPB5/5JFHGjdufMMNN2RlZe1p2MCBA2Ox2B133JH4TGAURUVFRevXrx8wYED9+vVTHwMAAFBLDhlNm3Xr1q1YsaJhw4bf+973dr22f//+l1xySRRFBQUFl1566QMPPNC3b99u3botX7584cKFbdu2HTp0aHJwKmMAAABqSRCmzapVq6IoKisre/vtt3e99owzzkheHj16dPv27SdNmjRjxozGjRv3799/1KhRzZo1qzw+lTEAAAC1IQjT5pRTTkn9+x4GDx48ePDg2o8BAACoMZ8hBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACFR2picAAMBuxGKxtN9nPB7P9GoBBxZBCABwIOodG5jeO5wTn5bpdQIOOA4ZBQAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACFR2picA1CmxWCzTUwAAIFWCEEiz3rGBab/POfFpmV4tAIA6yCGjAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgRKEAAAAgcrO9AQAAPiSxGKxtN9nPB7P9GoBNScIAQBC0Ts2ML13OCc+LdPrBNSKQ0YBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAACJQgBAAAClZ3pCQAZE4vFMj0FAAAySRBC0HrHBqb3DufEp2V6nQAASJVDRgEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAIlCAEAAAKVnekJAABwEIvFYpmeQqri8XimpwAHHEEIAEDN9Y4NTPt9zolPS/vdzolP+5K2CBxUHDIKAAAQKEEIAAAQKEEIAAAQKEEIAAAQKCeVgYPDQXQONwAADhaCEA4azrcGAEB6OWQUAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUIIQAAAgUNmZngDUQbFYLNNTAACAvROEsF/0jg1M7x3OiU/L9DoBAFDXOGQUAAAgUIIQAAAgUA4ZBQAgCPvjQ/7xeDzTqwW1IggBAAiCT/jDrhwyCgAAECjvEBI03w8BAEDIBCGhS/vRI5EDSAAgGPvpP5d9NJEvjSAEAIAa8j/LHOwE4YFr6tSpU6ZMKSkpycnJ6d69+8iRI1u0aJHpSQEAAHWHk8ocoCZMmDB27NiSkpKuXbvm5ORMnz590KBBGzduzPS8AACAukMQHoiKi4uLiopatWo1a9asoqKiWbNmDRkyZM2aNRMnTsz01AAA2O9i+0Gm14kDlENGD0RTp06tqKgYMWJEy5YtE0vGjBnz5JNPzpo164YbbqhXT8YDANRlvjKRL420OBAtWrSoXr16PXr0SC7Jysrq3r37hg0bFi9enPZfd7D8F9TBMk8AADhYeIfwgBOPx0tKSvLz8/Pz8ysv79SpUxRFK1eu7NKlSxp/XSwW2x9nx9pPreV/ywAAII0E4QGntLS0vLw8Ly+vyvLc3Nwoig6i88qINwAAOMDFfOvlgWb9+vVf//rXTz755ClTplRePnPmzKuuuuryyy8fOXJk9ffgSEgAAOoe5bI/eIfwgJOXlxeLxUpLS6ss37ZtWxRFTZo02es9eKoAAACpcFKZA052dnZubu7mzZurLN+yZUsURcnzjgIAANSSIDwQtWrVasOGDYkCTFq2bFniqkzPDgAAqCME4YGoV69e5eXl8+fPTy6Jx+Pz5s3Lz88vLCzM9OwAAIA6QhAeiAYOHBiLxe64447E5wajKCoqKlq/fv2AAQPq16+f6dkBAAB1hLOMHqB+97vfPfDAAwUFBd26dVu+fPnChQvbtGkzbdq0Zs2aZXpqAABAHSEID1yTJ0+eNGnS8uXLGzdufNZZZ40aNap58+aZnhQAAFB3CEIAAIBA+QwhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoAQhAABAoARhHbd69eouXbpcc801mZ4I7EVZWdmDDz7Yp0+fwsLCbt26DRs27KWXXsr0pGCPpk6dOmjQoMLCwjPPPPP6669ft25dpmcEe+cvLQc7r2z3h+xMT4D9KB6Pjx49etu2bZmeCOzFzp07f/jDH77xxhu5ubmnn376559//sorryxYsODKK6/82c9+lunZQVUTJky45557DjvssK5duy5fvnz69On/+Mc/ZsyYkZ+fn+mpwR75S8vBzivb/UQQ1mV//vOfFy1alOlZwN5NmTLljTfe6NKlyx//+MeGDRtGUbR06dJLLrnkzjvvPPvss4877rhMTxD+V3FxcVFRUatWraZNm9ayZcsoisaNG/fQQw9NnDjxxhtvzPTsYI/8peVg55XtfuKQ0Tpr6dKlEyZMOPbYYzM9Edi7v//971EU/eIXv0i8Romi6Jhjjrn88svLy8sdzsSBZurUqRUVFSNGjEjUYBRFY8aMyc3NnTVrVkVFRaZnB3vkLy0HNa9s9x9BWDft3Lnz2muvbdq06ZgxYzI9F9i7ZcuW5eTknHDCCZUXdujQIYqilStXZnp28H8sWrSoXr16PXr0SC7Jysrq3r37hg0bFi9enOnZwR75S8vByyvb/coho3XTxIkT33333QceeKBJkyaZngvs3b333pudXfXP0cKFC6MoateuXaZnB/8rHo+XlJTk5+dX+bhgp06doihauXJlly5dMj1H2D1/aTl4eWW7X3mHsA5644037rvvvksuueSMM87I9FwgJccff3zi9XTSwoULp02b1qBBg379+mV6dvC/SktLy8vL8/LyqizPzc2Nomjjxo2ZniDskb+0HKS8st3fBGFdU1ZWdu2117Zr127UqFGZngvURHl5+UMPPXTZZZeVlpbefPPNzZs3z/SM4H+VlZVFUZSTk1NleaNGjaIo2rx5c6YnCCnxl5aDhVe2XwKHjB6sdu7ced999yV/zMrK+vGPfxxF0e9+97tVq1ZNnjw5+ZFxOHDsab9NeuWVV2666ab333+/TZs248aN+/rXv57pKcP/kZeXF4vFSktLqyxPnAbdsUwcFPyl5SDile2XQBAerHbs2HHbbbclf2zQoMGPf/zjRYsWTZ48+T//8z9PPvnkTE8QdmO3+23i8vbt28ePH//www8feuihw4cPHzZsmD/9HICys7Nzc3N3fSdwy5YtURQlzzsKByZ/aTm4eGX75YjF4/FMz4G0mTRp0q9+9as9XXvMMcf87W9/y/QcYTcqKip+/vOfz549u7CwcMKECW3atMn0jGCP+vbtW1JSsnDhwsrvB15//fXTp09/+OGH/+M//iPTE4Td85eWg45Xtl8O7xDWKR06dLjwwgsrL9m8efOCBQvatm1bWFjYunXrTE8Qdu/hhx+ePXv2wIEDf/WrX2VlZWV6OlCdXr16FRcXz58/P/n3Nh6Pz5s3Lz8/v7CwMNOzgz3yl5aDjle2Xw7vENZxS5YsGTBgQN++fcePH5/pucDuxePxc889d9OmTQsWLDj00EMzPR3Yi48++qhXr15HHHHE1KlTE+eSuffee2+99dbLLrvsmmuuyfTsYPf8paVu8Mp2f/AOIZBh69atW7FiRcOGDb/3ve/tem3//v0vueSSTM8R/ldBQcGll176wAMP9O3bt1u3bsuXL1+4cGHbtm2HDh2a6anBHvlLC+yJIAQybNWqVVEUlZWVvf3227te60uHOACNHj26ffv2kyZNmjFjRuPGjfv37z9q1KhmzZplel6wR/7SAnvikFEAAIBA+WJ6AACAQAlCAACAQAlCAACAQAlCAACAQAlCAACAQAlCAACAQAlCAACAQAlCAACAQAlCAACAQAlCAACAQAlCAEJxxx13dO7ceeDAgXsaUFZWdvLJJ3fu3HnRokUp3uc111zTuXPnuXPnZnrlAKAmBCEAoejTp08URW+99daKFSt2O+DFF1/8/PPPW7Roceqpp2Z6sgDwZRCEAISiQ4cOX/nKV6IoeuaZZ3Y74Nlnn42i6Pzzz69Xz7+PAATBP3gABCTxJuHTTz+961U7dux44YUXoii64IILMj1NAPiSCEIAAnLBBRdkZWW99957H3zwQZWr/vGPf2zbtq1t27Zf/epXMz1NAPiSCEIAAtK8efPTTz892t2bhLNnz46i6Pzzz4/FYsmF69evv/XWWy+44IJTTjnllFNOufDCC2+++ea1a9fu6f4T55h5+eWXqyw//vjjE7836aWXXrryyit79+598sknf+Mb3/jDH/6wdevWTG8eAIIjCAEIy26PGi0vL3/uueeiKLrwwguTC9evX3/JJZfce++9q1evbt++fUFBwcqVK//0pz8NHjx406ZNtZnDLbfcMmzYsFmzZu3cufPwww9fsWJFUVHRt771rfXr12d68wAQFkEIQFjOPffcBg0avP/++//+97+TC//5z39u2rSpffv2J5xwQnLh9OnTly1bdvbZZ7/00ktPPPHEU089tWDBglNPPfWjjz5K1GPNvPDCC/fdd1+7du2mTp06d+7cmTNnvvjii2edddby5cvvueeeTG8eAMIiCAEIS05OTs+ePaMomjlzZnJh4njRKqeT2blzZ8+ePa+++uqcnJzEkiZNmnzzm9+Momj58uU1nsDvfve7KIpuu+22xClPoyhq3rz5bbfd1qpVq2nTpn366aeZ3kIABEQQAhCcvn37RpWOGo3H44kvnKgShD/72c/uueeeo446Krlk2bJltfwO+k2bNi1btuzII4+s/FZkFEWHHXbYGWecUVZW9vbbb2d68wAQkOxMTwAAvmzdu3dv0qTJihUrlixZcsIJJ7z55ptr16496qijOnfuXGXkRx999OKLL7722msrVqxYvnx57d++S5zd9IMPPtj1dyV8/PHHmd48AAREEAIQnPr163/jG9+YMmXKzJkzTzjhhN2+PRhF0eTJk3/961/v3Lmzffv2p556au/evU888cRly5b96le/2qdfV15eHo/HE5e3b98eRVFBQUHv3r13O7hNmzaZ3jwABEQQAhCiPn36TJky5Zlnnrnmmmt2+wHClStX3nTTTYceeui999575plnJpfX4B281atXV1RUJC4fccQRURQddthh119/faa3AQD4DCEAQeratWvr1q1Xr1796KOPrlix4thjjz3yyCMrD/jggw/i8fgpp5xSuQajKCouLt7rnVf5UorEO5AJrVu3btGixfvvv79kyZLKY8rLy7/1rW9169bNN08A8GUShACEKBaLXXTRRVEUjR8/Ptrd8aLt2rWLoui9995LFlp5efmjjz768MMPR1FUVla227tt3759FEWPPPJIaWlpYsnChQvvvvvuymNGjhxZUVFx1VVXvfvuu4kln3322XXXXff222+feOKJzZs3z/S2ASAgDhkFIFAXXXTR/fff/9lnn0VRdP7551e59sgjj+zVq9dzzz137rnndunSpaKiori4uLS09Dvf+c5f/vKXGTNmbN26NfEFEpX169fvwQcffO2113r16nX88cd/8sknJSUlubm5rVu3/uKLLxJjBgwY8Oqrrz7++OP9+vUrKCjIz89///33S0tLO3bs+Jvf/CbTWwWAsHiHEIBAHXfccUcffXQURSeeeGLinb0q/vCHPwwfPrx169avvvrq2rVru3fv/re//W3s2LHnnXdeeXn5m2++uetN2rVr95e//KV379716tVbsGDBv//974KCgvvuu6/y+36xWOzmm2++/fbbe/bsWV5evmzZsiOOOGLkyJFPPPFE06ZNM71VAAhLLHneMwAgjT777LMNGza0a9cuFotlei4AsHuCEAAAIFAOGQUAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAiUIAQAAAjU/wOKXc6sbFrpbgAAAABJRU5ErkJggg==\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"metadata\": {\n      \"image/png\": {\n       \"height\": \"480\",\n       \"width\": \"640\"\n      }\n     },\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%plot --format png\\n\",\n    \"randn (\\\"state\\\", 1);\\n\",\n    \"hist (randn (10000, 1), 30);\\n\",\n    \"xlabel (\\\"Value\\\");\\n\",\n    \"ylabel (\\\"Count\\\");\\n\",\n    \"title (\\\"Histogram of 10,000 normally distributed random numbers\\\");\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 21,\n   \"id\": \"diverse-hypothetical\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<?xml version='1.0' encoding='UTF-8' standalone='no'?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"480px\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"640px\\\" viewBox=\\\"0 0 576 432\\\"> <title>gl2ps_renderer figure</title> <desc>Creator: GL2PS 1.4.0, (C) 1999-2017 C. GeuzaineFor: OctaveCreationDate: Sat Aug 14 21:07:48 2021</desc> <defs/> <polygon fill=\\\"#ffffff\\\" points=\\\"0,0 576,0 576,432 0,432\\\"/> <g>  <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#ffffff\\\" points=\\\"0,432 576,432 576,0 0,0\\\"/>  <clipPath id=\\\"cp00576432\\\">   <polygon points=\\\"0,432 576,432 576,0 0,0\\\"/>  </clipPath>  <g clip-path=\\\"url(#cp00576432)\\\">   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#ffffff\\\" points=\\\"74.88,384.48 521.28,384.48 521.28,32.4 74.88,32.4\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"149.28,384.48 149.28,380.015\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"149.28,32.4 149.28,36.865\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"223.68,384.48 223.68,380.015\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"223.68,32.4 223.68,36.865\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"298.08,384.48 298.08,380.015\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"298.08,32.4 298.08,36.865\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"372.48,384.48 372.48,380.015\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"372.48,32.4 372.48,36.865\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"446.88,384.48 446.88,380.015\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"446.88,32.4 446.88,36.865\\\"/>   <text transform=\\\"translate(146.28,399.982) rotate(-0,3,-8)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">1</tspan>   </text>   <text transform=\\\"translate(220.68,399.982) rotate(-0,3,-8)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">2</tspan>   </text>   <text transform=\\\"translate(295.08,399.982) rotate(-0,3,-8)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">3</tspan>   </text>   <text transform=\\\"translate(369.48,399.982) rotate(-0,3,-8)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">4</tspan>   </text>   <text transform=\\\"translate(443.88,399.982) rotate(-0,3,-8)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">5</tspan>   </text>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"74.88,384.48 79.348,384.48\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"521.28,384.48 516.812,384.48\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"74.88,314.064 79.348,314.064\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"521.28,314.064 516.812,314.064\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"74.88,243.648 79.348,243.648\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"521.28,243.648 516.812,243.648\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"74.88,173.232 79.348,173.232\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"521.28,173.232 516.812,173.232\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"74.88,102.816 79.348,102.816\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"521.28,102.816 516.812,102.816\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"74.88,32.4 79.348,32.4\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"521.28,32.4 516.812,32.4\\\"/>   <text transform=\\\"translate(63.8755,388.48) rotate(-0,6,-4)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">0</tspan>   </text>   <text transform=\\\"translate(54.8755,318.064) rotate(-0,15,-4)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 6 9 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">0.2</tspan>   </text>   <text transform=\\\"translate(54.8755,247.648) rotate(-0,15,-4)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 6 9 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">0.4</tspan>   </text>   <text transform=\\\"translate(54.8755,177.232) rotate(-0,15,-4)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 6 9 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">0.6</tspan>   </text>   <text transform=\\\"translate(54.8755,106.816) rotate(-0,15,-4)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 6 9 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">0.8</tspan>   </text>   <text transform=\\\"translate(63.8755,36.4) rotate(-0,6,-4)\\\" font-size=\\\"10\\\" font-family=\\\"FreeSans\\\" font-style=\\\"normal\\\" font-weight=\\\"normal\\\" xml:space=\\\"preserve\\\">    <tspan x=\\\"0 \\\" y=\\\"-0\\\" fill=\\\"rgb(38,38,38)\\\">1</tspan>   </text>   <polyline stroke-dasharray=\\\"16,0\\\" fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"square\\\" stroke-linejoin=\\\"miter\\\" points=\\\"74.88,384.48 521.28,384.48\\\"/>   <polyline stroke-dasharray=\\\"16,0\\\" fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"square\\\" stroke-linejoin=\\\"miter\\\" points=\\\"74.88,32.4 521.28,32.4\\\"/>   <polyline stroke-dasharray=\\\"16,0\\\" fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"square\\\" stroke-linejoin=\\\"miter\\\" points=\\\"74.88,384.48 74.88,32.4\\\"/>   <polyline stroke-dasharray=\\\"16,0\\\" fill=\\\"none\\\" stroke=\\\"#262626\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"square\\\" stroke-linejoin=\\\"miter\\\" points=\\\"521.28,384.48 521.28,32.4\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#440154\\\" points=\\\"127.258,208.44 127.258,301.217 123.091,301.217 123.091,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#440154\\\" points=\\\"201.658,208.44 201.658,187.111 197.491,187.111 197.491,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#440154\\\" points=\\\"276.058,208.44 276.058,78.9365 271.891,78.9365 271.891,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#440154\\\" points=\\\"350.458,208.44 350.458,335.381 346.291,335.381 346.291,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#440154\\\" points=\\\"424.858,208.44 424.858,194.566 420.691,194.566 420.691,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"127.258,301.217 123.091,301.217 123.091,208.44 127.258,208.44 127.258,301.217\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"201.658,187.111 197.491,187.111 197.491,208.44 201.658,208.44 201.658,187.111\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"276.058,78.9365 271.891,78.9365 271.891,208.44 276.058,208.44 276.058,78.9365\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"350.458,335.381 346.291,335.381 346.291,208.44 350.458,208.44 350.458,335.381\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"424.858,194.566 420.691,194.566 420.691,208.44 424.858,208.44 424.858,194.566\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"round\\\" points=\\\"74.88,208.44 521.28,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#472877\\\" points=\\\"132.614,208.44 132.614,147.41 128.448,147.41 128.448,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#472877\\\" points=\\\"207.014,208.44 207.014,198.422 202.848,198.422 202.848,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#472877\\\" points=\\\"281.414,208.44 281.414,371.42 277.248,371.42 277.248,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#472877\\\" points=\\\"355.814,208.44 355.814,103.928 351.648,103.928 351.648,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#472877\\\" points=\\\"430.214,208.44 430.214,97.966 426.048,97.966 426.048,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"132.614,147.41 128.448,147.41 128.448,208.44 132.614,208.44 132.614,147.41\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"207.014,198.422 202.848,198.422 202.848,208.44 207.014,208.44 207.014,198.422\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"281.414,371.42 277.248,371.42 277.248,208.44 281.414,208.44 281.414,371.42\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"355.814,103.928 351.648,103.928 351.648,208.44 355.814,208.44 355.814,103.928\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"430.214,97.966 426.048,97.966 426.048,208.44 430.214,208.44 430.214,97.966\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#3e4a89\\\" points=\\\"137.971,208.44 137.971,177.694 133.805,177.694 133.805,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#3e4a89\\\" points=\\\"212.371,208.44 212.371,63.0867 208.205,63.0867 208.205,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#3e4a89\\\" points=\\\"286.771,208.44 286.771,185.31 282.605,185.31 282.605,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#3e4a89\\\" points=\\\"361.171,208.44 361.171,37.2878 357.005,37.2878 357.005,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#3e4a89\\\" points=\\\"435.571,208.44 435.571,270.568 431.405,270.568 431.405,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"137.971,177.694 133.805,177.694 133.805,208.44 137.971,208.44 137.971,177.694\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"212.371,63.0867 208.205,63.0867 208.205,208.44 212.371,208.44 212.371,63.0867\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"286.771,185.31 282.605,185.31 282.605,208.44 286.771,208.44 286.771,185.31\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"361.171,37.2878 357.005,37.2878 357.005,208.44 361.171,208.44 361.171,37.2878\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"435.571,270.568 431.405,270.568 431.405,208.44 435.571,208.44 435.571,270.568\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#30678d\\\" points=\\\"143.328,208.44 143.328,314.875 139.162,314.875 139.162,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#30678d\\\" points=\\\"217.728,208.44 217.728,338.211 213.562,338.211 213.562,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#30678d\\\" points=\\\"292.128,208.44 292.128,82.1371 287.962,82.1371 287.962,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#30678d\\\" points=\\\"366.528,208.44 366.528,378.65 362.362,378.65 362.362,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#30678d\\\" points=\\\"440.928,208.44 440.928,130.736 436.762,130.736 436.762,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"143.328,314.875 139.162,314.875 139.162,208.44 143.328,208.44 143.328,314.875\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"217.728,338.211 213.562,338.211 213.562,208.44 217.728,208.44 217.728,338.211\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"292.128,82.1371 287.962,82.1371 287.962,208.44 292.128,208.44 292.128,82.1371\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"366.528,378.65 362.362,378.65 362.362,208.44 366.528,208.44 366.528,378.65\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"440.928,130.736 436.762,130.736 436.762,208.44 440.928,208.44 440.928,130.736\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#25828e\\\" points=\\\"148.685,208.44 148.685,316.418 144.518,316.418 144.518,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#25828e\\\" points=\\\"223.085,208.44 223.085,272.508 218.918,272.508 218.918,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#25828e\\\" points=\\\"297.485,208.44 297.485,377.905 293.318,377.905 293.318,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#25828e\\\" points=\\\"371.885,208.44 371.885,115.65 367.718,115.65 367.718,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#25828e\\\" points=\\\"446.285,208.44 446.285,43.8772 442.118,43.8772 442.118,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"148.685,316.418 144.518,316.418 144.518,208.44 148.685,208.44 148.685,316.418\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"223.085,272.508 218.918,272.508 218.918,208.44 223.085,208.44 223.085,272.508\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"297.485,377.905 293.318,377.905 293.318,208.44 297.485,208.44 297.485,377.905\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"371.885,115.65 367.718,115.65 367.718,208.44 371.885,208.44 371.885,115.65\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"446.285,43.8772 442.118,43.8772 442.118,208.44 446.285,208.44 446.285,43.8772\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#1e9d88\\\" points=\\\"154.042,208.44 154.042,130.872 149.875,130.872 149.875,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#1e9d88\\\" points=\\\"228.442,208.44 228.442,345.054 224.275,345.054 224.275,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#1e9d88\\\" points=\\\"302.842,208.44 302.842,329.216 298.675,329.216 298.675,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#1e9d88\\\" points=\\\"377.242,208.44 377.242,306.808 373.075,306.808 373.075,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#1e9d88\\\" points=\\\"451.642,208.44 451.642,292.758 447.475,292.758 447.475,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"154.042,130.872 149.875,130.872 149.875,208.44 154.042,208.44 154.042,130.872\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"228.442,345.054 224.275,345.054 224.275,208.44 228.442,208.44 228.442,345.054\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"302.842,329.216 298.675,329.216 298.675,208.44 302.842,208.44 302.842,329.216\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"377.242,306.808 373.075,306.808 373.075,208.44 377.242,208.44 377.242,306.808\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"451.642,292.758 447.475,292.758 447.475,208.44 451.642,208.44 451.642,292.758\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#35b778\\\" points=\\\"159.398,208.44 159.398,210.172 155.232,210.172 155.232,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#35b778\\\" points=\\\"233.798,208.44 233.798,373.205 229.632,373.205 229.632,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#35b778\\\" points=\\\"308.198,208.44 308.198,36.8672 304.032,36.8672 304.032,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#35b778\\\" points=\\\"382.598,208.44 382.598,380.047 378.432,380.047 378.432,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#35b778\\\" points=\\\"456.998,208.44 456.998,313.569 452.832,313.569 452.832,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"159.398,210.172 155.232,210.172 155.232,208.44 159.398,208.44 159.398,210.172\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"233.798,373.205 229.632,373.205 229.632,208.44 233.798,208.44 233.798,373.205\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"308.198,36.8672 304.032,36.8672 304.032,208.44 308.198,208.44 308.198,36.8672\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"382.598,380.047 378.432,380.047 378.432,208.44 382.598,208.44 382.598,380.047\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"456.998,313.569 452.832,313.569 452.832,208.44 456.998,208.44 456.998,313.569\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#6ccd59\\\" points=\\\"164.755,208.44 164.755,157.739 160.589,157.739 160.589,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#6ccd59\\\" points=\\\"239.155,208.44 239.155,150.734 234.989,150.734 234.989,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#6ccd59\\\" points=\\\"313.555,208.44 313.555,76.7126 309.389,76.7126 309.389,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#6ccd59\\\" points=\\\"387.955,208.44 387.955,120.49 383.789,120.49 383.789,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#6ccd59\\\" points=\\\"462.355,208.44 462.355,168.895 458.189,168.895 458.189,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"164.755,157.739 160.589,157.739 160.589,208.44 164.755,208.44 164.755,157.739\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"239.155,150.734 234.989,150.734 234.989,208.44 239.155,208.44 239.155,150.734\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"313.555,76.7126 309.389,76.7126 309.389,208.44 313.555,208.44 313.555,76.7126\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"387.955,120.49 383.789,120.49 383.789,208.44 387.955,208.44 387.955,120.49\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"462.355,168.895 458.189,168.895 458.189,208.44 462.355,208.44 462.355,168.895\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#b4dd2b\\\" points=\\\"170.112,208.44 170.112,182.297 165.946,182.297 165.946,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#b4dd2b\\\" points=\\\"244.512,208.44 244.512,103.737 240.346,103.737 240.346,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#b4dd2b\\\" points=\\\"318.912,208.44 318.912,159.873 314.746,159.873 314.746,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#b4dd2b\\\" points=\\\"393.312,208.44 393.312,216.359 389.146,216.359 389.146,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#b4dd2b\\\" points=\\\"467.712,208.44 467.712,154.435 463.546,154.435 463.546,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"170.112,182.297 165.946,182.297 165.946,208.44 170.112,208.44 170.112,182.297\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"244.512,103.737 240.346,103.737 240.346,208.44 244.512,208.44 244.512,103.737\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"318.912,159.873 314.746,159.873 314.746,208.44 318.912,208.44 318.912,159.873\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"393.312,216.359 389.146,216.359 389.146,208.44 393.312,208.44 393.312,216.359\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"467.712,154.435 463.546,154.435 463.546,208.44 467.712,208.44 467.712,154.435\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#fde724\\\" points=\\\"175.469,208.44 175.469,156.357 171.302,156.357 171.302,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#fde724\\\" points=\\\"249.869,208.44 249.869,162.487 245.702,162.487 245.702,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#fde724\\\" points=\\\"324.269,208.44 324.269,74.8864 320.102,74.8864 320.102,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#fde724\\\" points=\\\"398.669,208.44 398.669,372.603 394.502,372.603 394.502,208.44\\\"/>   <polygon shape-rendering=\\\"crispEdges\\\" fill=\\\"#fde724\\\" points=\\\"473.069,208.44 473.069,72.8917 468.902,72.8917 468.902,208.44\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"175.469,156.357 171.302,156.357 171.302,208.44 175.469,208.44 175.469,156.357\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"249.869,162.487 245.702,162.487 245.702,208.44 249.869,208.44 249.869,162.487\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"324.269,74.8864 320.102,74.8864 320.102,208.44 324.269,208.44 324.269,74.8864\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"398.669,372.603 394.502,372.603 394.502,208.44 398.669,208.44 398.669,372.603\\\"/>   <polyline fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.5\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" points=\\\"473.069,72.8917 468.902,72.8917 468.902,208.44 473.069,208.44 473.069,72.8917\\\"/>  </g> </g></svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%plot -f svg\\n\",\n    \"h = bar (rand (5, 10));\\n\",\n    \"set (h(1), \\\"basevalue\\\", 0.5);\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"id\": \"regulation-analysis\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/jpeg\": \"/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCANrBI4DASIAAhEBAxEB/8QAHAABAQADAQEBAQAAAAAAAAAAAAUDBAYHAgEI/8QAVhAAAQMDAQQECQkECQEGBAYDAAECAwQFEQYSEyExIkFRYRQVFiM2cXWz0wcyM1JUVoGTlWJ0gpEkNUKSlKGytNIINDdVcrHRFyVz8DhDRFNYhGPD1P/EABcBAQEBAQAAAAAAAAAAAAAAAAACAwH/xAArEQEAAQEFBwQDAQEAAAAAAAAAAQIDESEy8BIxUWFxweFBgZGxodHxIkL/2gAMAwEAAhEDEQA/APfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMNVVU9DSyVVXURU9PE3akllejGMTtVV4Ih5XcvlM1Pctb3LTejrPbZ321VbM+vn2XSuRcORjdpvXlOvtXBuVWrq2/fJFqGtvWm30VZSwvjnoqxkjYpsInFFRWuVq9y8Mc+sD0ejraS40kdXQ1UNVTSIqsmgkR7HcccHJwXiimc8Ld8o1fo75JdIXC0Wq3RsrZZY302xK9jGo93zMybWV71XmU6n5UdY2DU1qh1TpeloLRdJkjgVk23NGiqidJUcqZTaRVTCAesV1xobXA2e4VtPSQuejEkqJWxtVy8kyqpxXsNk8qvci6t+XW12CRdq3afpvGM0fU+dcbGfVtRqn8XabWqPlDuui/lBoKG9wUTdL17V3VayN6SRuROKOXaVFw7GcInByL1KB6NU1NPRU0lTVTxwU8TVfJLK9GtY1Oaqq8EQ/aeohq6eOoppo5oJWo+OSNyOa9q8UVFTgqL2nn3yd6qvfyh0t3rLpbqKDTsj309JGkb97M1VVF2lVyoqI1cLhEyqrywafyPVk9vk1FoupkdItirXNpnuXisD1dsp/ln+ID06WWOCJ8ssjY42IrnPeuEaic1VepDXt11t13gdPbK+lrYWvVjpKaZsjUciIqoqtVUzxTh3nn/AMudbcqb5N62KjoN9Sz7LaupSZGLTt3jMdFeL9pejw5ZyRdGalh0B8ibLzXWFtEiqxadkdQj1uD3sbiRVT5mcLlF4ojfUgHsoPF5/lT13YqCiv2otJUkVgqnN6VPKu+ja7iiqiuXiqcURUTs4ZKuu/lSr9M6h07BaqKC40F1hSbZSN6zSo5U2Ujw5ERVynNF5gepgg6PuF/udiSp1JbI7bXuleiU8a5RrP7KquV4/wD3hDktUfKHddF/KDQUN7gom6Xr2ruq1kb0kjcicUcu0qLh2M4RODkXqUD0sHn/AMmestQa5S43WsoqOksbZnRUGxG9JpMLzcquVFREwi4RMrnlg6y/aitOmaBtdea1lJTOkSJJHtVUVyoqonBF6kX+QFQHEf8Axf0D95Kf8uT/AInbMe2RjXtXLXJlF7UA/TWrrjQ2uFs1wraekic9I2vqJWxtVy8moqqnFew2T+c/lfseorbcrLWXjVEl0pqi4YgpfB0iZBhUVOCLhy4XGcZA/otzmsYr3uRrWplVVcIiGhQX6z3WZ8Nuu1DWSx8Xsp6lkjm+tGquDzj/AKgbrU0GgIaOmerFuFYyCTC4VWI1zlT8VRv4HK/KBpS1/JjctG3zT0TqaaGqSGpckjl36JhVV2V6020XHUvcB/QJOrNQWW3VbKSuu9BS1L8bMM9Sxj3Z5YRVypzz9b1kfyg1Omn6fqEooIFm8abbt27EaPxjYx14+d1HkmhNG27X+h9WamvkTqi71FROkM6vd5lzY0eiomfrOxhepEQD+jUXKZTkDzj5DbvUXb5MaNKmRZH0c0lKjnLlVa3CtT8EciepEN/5RrHqK7WqaW0aoktFLBSyOnhjp0c6bCZ+flHN4Jjh2gdfQ3GhukCz2+tp6uFr1YslPK2RqOTmmUVeKdhsnlX/AE+f92f/APel/wDRpa01qm9a7sN4ZFbZ9M1sLkip55033FU+ejXMai4xy48wOyfcaGO4xW+Stp210rFkjpnStSR7U5uRucqnBeJ+1tdR22mdU11VBSwN+dLPIjGp61XgeEabtl1tH/UbDSXm9SXerSie9ap7NjgsaqjUblURE7E4FXX9PHq35ctM6TuG0+0xUzqmWFHKiPdiRy5x2pG1PxXtA9goLlQXWn8It1bTVkGcb2nlbI3PZlqqhtHiOmKGDRP/AFB1mn7U10NquVFvEptpVaxyN2spnsVr8dzlPbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP5110/SFTq66x6u0vdrJXNk/o1ytr94lYiLwfhURuVTZXhleKoqoqGxptdRO+RHWbrvLXSW5YnJbVrkVJFYiLtLxVV2fm9eM5wf0EAP5gv/8A3N/Jx++ye8cdz8vf0+jvaK/+rD2YAeT2xPFf/Urem1HRS7WpklMq/wBrZSNFRPy3/wAiR8rVbNrvVts+TmypE6aOTwmsqHN2khVGrhM9WGqqr2qrU7T0TVujnX+6WS8UNW2iutpqN5HM5m0kka/PjciKnBf8uPadWB5X8iep/CbHNpG4RNprvY3OhfCiI3bjRyptY7UdlF/Besx/JqnjH5Utf3mLjS+EspWPTk9zco7H91P7yHp9xiqp7bUxUM7IKt8TmwzPbtJG9UwjlTrwvHBH0TpOn0ZpintEEm+kRVkqJ1TCzSu+c5f8kTuRAIXy1/8AdFffVB7+M4/Umma/U/8A06afitsT56mjgp6pIWJl0iJGrVRE61w/OO49uAH896t+UN/ygaKp9I2ew3J17qnQsqYnQ4bCrFRy4XPLLU4qiYTOcG5qm2Os3ykfJZa5HpI+jggp3OTk5WK1uf8AI94AA8Q+Vqtm13q22fJzZUidNHJ4TWVDm7SQqjVwmerDVVV7VVqdp7eAPK/kT1P4TY5tI3CJtNd7G50L4URG7caOVNrHajsov4L1nU/KBUOptPRvbpFmqVWpangL2I5G9F3nMKx3Lly/tczqwB4R43l//j9T/kR//wDOe3vgbV250D2rE2aJWOa3m1FTGE9RsADzfSXyL2DR2oqe90Ffc5aiBr2tZO+NWLtNVq5wxF5L2kH/AKgfodKe0V/9GnswA80+XHTdbqHQSOt0Mk9VQVLalIo25c9mHNdhOtU2s/gcJfdTP+WO9aWs1qtVdElLUJPc5JY0RsPzdrCoq8ERHc8ZyiH9DADj/LugqflDqNDOo6jwpsG26fLd2qLGjsc88nYPHbBqif5LbDqXRV0tVe+4TTSrb3xxZZMr2IxFzn5vRavDPNU5n9JADx3S9x/+D3yO2+svlBUvmq6tXSU7MI+NZEVW5z+yxMpzRVwekXOrbX6KrKxjVaye3Pla13NEdGq4X+ZaAHlX/T5/3Z//AN6X/wBGnT6E1/Ra9p6+aio6imSjlSJ6TK3pKqKuUwvcdcAPGX//AIp4/Z3/APqUfKWyq0n8qWntfJRVFVbIIVpqvcM2lj4PblfWknDPDLeZ7MAPFNDyz68+WWt1vBQ1NNZqWk3FNJOzZWRytRuOzrevBVxw7T2sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5LXOtY9JWud8VLPUV2624kSne6JuVwivemERM9Wc/wAzqYHrLTxyOxlzUcuO9AMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOT+Uz/u4vf/0E/wBSHTUn/Y4P/pt/9DFc7ZR3i2z2+vh31LO3Zkj2lbtJnPNFRU5G0xjWMaxqYa1MIncBI1ZNLTaNvk8Er4po7fO9kjHK1zHJG5UVFTkqL1nx5KW77TeP1mr+KNZeg2oPZtT7pxbAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KRbRaaB1mqKyvr7wu7rquFHeN6vOyypkjY1EbJxXCNaiIiqq45qp2pAt9BE27Pghc91Lb55p1V6plamdzpHJwRODGSrjmipKnWwqmL96apu3b2rR6Ra+qZWz3C9wN47NCl3ncxG4wm2qvVVdxyuyqInBEzjadgbpqG2VEEVZcrxV0s70iZO+7VTJI3qiqm8VJUaqOXooqI3CqxMOV2U7A+JYo54nxSxtkje1WvY9Mo5F4Kip1od2/Sdydi7GJx1r6R/JS3fabx+s1fxR5KW77TeP1mr+KbNnlkZFLb6iRz6iickaveuXSx845FVeKqreCu4Ir2vxyKRNUXTcqmrai9E8lLd9pvH6zV/FHkpbvtN4/Wav4pbBxSJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4pLgsFK/VdwonVl4WnioaWVjPHFXwe986OXO8zxRjf5es681Y6CKO61FxRz99PBFA5qqmyjY3SORU4c8yuz6k/EJ3kpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4pPqdO0lRUOoaGrvDZG439R44q1SBFTOEzJhZFRUVEXgiKjnf2Wv6G5Vvi+glqEj3siYbFHnZ3kjlRrG56suVEyvBM5UW+i8BpGxvk307ulPOqYWaTCIrlTq5cE5IiIicERC4i6NqUVTfOzDnF0NsQMbDqK/PlY5zkdU3KZ7XZREw5GPYqomFVMOTivHKcDPb7Dbq2nc50t4imje6KaLx3VrsPav/1EXCphyKqJlrmrhMnTEq5/0Grp7s3hGzzNX3xOXg9f/I7C5VcNY6Res7E7eE73JjYxjcw+Slu+03j9Zq/ijyUt32m8frNX8UtgzaInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/iku62ClprlY4oay8NZVVzopk8cVa7TEp5n44ycOkxq8Ow681augirKmhnkc9HUU6zxo1UwrljfHheHLEi9nFEAneSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgCJ5KW77TeP1mr+KPJS3fabx+s1fxS2AInkpbvtN4/Wav4o8lLd9pvH6zV/FLYAieSlu+03j9Zq/ijyUt32m8frNX8UtgDn6nTtppKd089XeGxtxx8cViqqquERESTKqqqiIicVVURCf5FLW+fkvOobftfNp4LvM7Yb1bSuc7Lu3C4TkmcbTra//Mr0+N3SpKDZ22ryfULh7cp+w3ZcnNFWRF4KwqmmTqzzzycemmobU+NKy5Xiro5HtibM67VTZY3uVEbt7MqNciuVG5a1uz0coqKrkq+Slu+03j9Zq/iliWKOeJ8UsbZI3tVr2PTKOReCoqdaGhZ5ZGRS2+okc+oonJGr3rl0sfOORVXiqq3gruCK9r8cjk/6i/1I/wAzd6NbyUt32m8frNX8UeSlu+03j9Zq/ilsENETyUt32m8frNX8UeSlu+03j9Zq/ilsARPJS3fabx+s1fxR5KW77TeP1mr+KWwBE8lLd9pvH6zV/FHkpbvtN4/Wav4pbAETyUt32m8frNX8Ul6msFLb9KXitpay8R1FPQzSxP8AHFWuy9rFVFwsmF4p1nXkTWXoNqD2bU+6cBbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOLYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa9dWR0FFLVSo5zY25RjEy568ka1OtyrhETrVUQxWijkobVTwTq11Rs7c72LwfK5VdI5O5XK5eSc+ScjXuf9Judtt/9hz3VcqLycyLGEzzykj4nd6NXPYtUucKYjjr9s4xrmeGGvwAAholXH+h3OhuDeix70pKlepWP+jVUTiqpJsNTnhJH9qqlU1bnReMLZU0iSbp8rFRkuMrG/8AsvTvauFTinFEFsrfGFsp6tY90+ViK+LOVjf/AGmL3tXKLwTiilzjTE8NftnGFcxxx/fZtAAhoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJUn9N1FCxOlDb2Okf2JO9NlmFTrRiyZReqRi4XKKlUlaf89bPGC8X3B61eevYdjdoqckVI0jauOtq8+a1S7TCdngzs8Y2uOOvYPiWKOeJ8UsbZI3tVr2PTKOReCoqdaH2CGibZJZFon0k8jnz0UrqZ7nrtOcicY3OXrc6NWOVe1y8uSUiV/wBj1L2RV8Hqaksa/wCbnMd68Q9aJwql177+KLPddw19AAIWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGjcLza7Ru/GVyo6Le53fhM7Y9vGM42lTOMp/NDeIlV6c2r2bW+9pQHllpb7yWf8Ax0X/ACMVVrnS1NSTVHlBbJd0xz93FWROe/CZw1Nriq9SHQAQS5e06n01Q22OKbU1lWdznyzKyvj2d49yvfs5XOztOXGeOMZN3yy0t95LP/jov+RbB2Zvm+XKYimLoRPLLS33ks/+Oi/5E2t1bpqG60NdBqG0qjnLTVOzWxr5tyKrXKiOyqtejUReKNSR68EVVTrQKZulyqm+ETyy0t95LP8A46L/AJDyy0t95LP/AI6L/kWzDUVlNSbrwmohh30iRR716N23ryamear1InE4pK8stLfeSz/46L/kPLLS33ks/wDjov8AkWwBE8stLfeSz/46L/kPLLS33ks/+Oi/5FdKiF1S6mSaNZ2sR7okcm0jVVURVTnhVRePconnhpaeSoqJWQwxNV8kkjka1jU4qqqvBEQCR5ZaW+8ln/x0X/IsQzRVMEc8ErJYZGo9kjHI5r2qmUVFTmip1n2ioqZRcopE0p/U8/tKv/3cwFsiay9BtQezan3Ti2RNZeg2oPZtT7pwFsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARNZeg2oPZtT7pxbImsvQbUHs2p904tgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADFVVMNHSTVVQ/YhhY6SR2FXDUTKrhOPJBEX4QTN2Mp9t/pF3utZ1I9lJG5vzXMjbtKveqPkkav8A5cc0Uqk+x001JZaSOpZs1Ss3lQmUXzz+lIvDhxe5y8OHZwKBdpP+sEWcf5i/V4ACFhKtn9Gudyt/9hr21cSJyayXOUzzysjJXdyOTHYlUlVv9Gv9sqG//qd5RyNThtdFZWuXt2d29ET/APyKuU4ot0Y3wzrwunWOCqACGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABK1F52yz0TfpK7FGxE4qm86LnInXstVz1TsavFOaVSVP/SdS0kPzo6OB9Q9OWxI9diNe/Ld+mOXb/ZLs81/DFnaZbuOCqACGgAAJWovN2h9YnBaJ7KtXJ85GRuR0iN71Yj29WdrC8FUqnxLFHPE+KWNskb2q17HplHIvBUVOtDQsEsklmhZLI6SSnc+mfK9crKsT3Rq9e92xtdfPmvMvfR07/wAZ7q+sfX9UgAQ0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJVenNq9m1vvaUtkSq9ObV7Nrfe0oG9WXi2W+VIq25UdNIrdpGTTtYqpyzhV5cF/ka/lPYP/ABy2f4uP/wByqC4mj1j8+ETFd+Ex8eUrynsH/jls/wAXH/7jynsH/jls/wAXH/7lUC+jhPz4cur4x8eUrynsH/jls/xcf/ubFHeLZcJViorlR1MiN2lZDO16onLOEXlxT+ZugTNHpH58OxFd+Mx8eXH631ZV6dq7RQ0jrdTPuL5GrXXNzm08OwiLsu2cdJ2eCZTkpoVV/u3iqyS3i12iWea/QUscsa7+GSN2cTxccsdzRM8UwvaXNUW2/VslJLZ57fJExHsqbfco1WCoRcYXaRFVqtVOxUXJzFB8nVxpaandvLbBK6/QXWWkpGvjpoGRtwrYkVFXaXnxREVezBC36mrNaV8Oo623UllZRWWsqYMVKSq+pSJc4TDsNXZxxXKKq8kRDu7NcW3ixW+5tjWNtZTR1CMVcq1HtR2M/iQbZpitorFqahklp1lutZWVECtc7Za2ZOijuHBU68Z/Es6ct01o0xabZUOY6ajo4aeR0aqrVcxiNVUyiLjKdgHKWKqu1Vpa96mtEUFRdK6umkhiqEXD4YXrEyJFRUwqtjXC8tpyqvNTf03qmTWtZPJRUjE09HTpFK+pickktQ5EV0aIq4RrEXDsouXLhOSk+z0d3ptOXzS1ongpbjSV0rYZ51XzdNO9ZWytREXaciPeick2mLleBu2DSy6HuFStBUxM03JTJJPFUSu24Z2IiLK1cYVHNTLsqnFM9YGx8n9TI7Ts1ule6R9prZ7dtuXKuZE9UYq/wKw39Kf1PP7Sr/8AdzGloGklh05JXVEboprrVz3F0bkwrElermIqdSozYz3m7pT+p5/aVf8A7uYC2RNZeg2oPZtT7pxbImsvQbUHs2p904C2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImsvQbUHs2p904tkTWXoNqD2bU+6cWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABK1B52gjoU4urp46dWfXjVcypnq802TjwXhw44KpKn/AKTqWkh+dHRwPqHpy2JHrsRr35bv0xy7f7Jdnmv4M7TLdxwVQAQ0AAAJWpOhYKmo5+CbFZs/X3Lkl2e7OxjPVnOF5FUFUzs1RKaqdqmY4gJWm+jp2ip1+fSs8EevUr4lWNyp3KrFx3Y5FUVRs1TBTVtUxPEABKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlWr+kV90rl6TXzpTwv5ZjiTCpjulWbivFe9MFKWWOCJ8ssjY42NVz3vXCNROKqq9SGhp+KSLT9Dv43MqJIkmna9MLvX9ORVTqXac5cdXLgXGFMyzqxriPfXypAAhoAAASqDzN/u9P87e7ms2uWNpqxbP4bjOf2sY4ZWqSq/zN/tFR87e76j2eWNpqS7X4bjGP2s54YW6PWOXnszrwunn47qoAIaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzV5udBatZWie411NRwut9YxJKiVsbVdvKZcZcqccIvDuOlAETyy0t95LP/jov+Q8stLfeSz/46L/kZqnz+paCFenHTwS1DkT+xIqtYxV7MtdMiIvBcL9XhVKmLrkxVfM8kTyy0t95LP8A46L/AJDyy0t95LP/AI6L/kWwSpE8stLfeSz/AOOi/wCQ8stLfeSz/wCOi/5FsARPLLS33ks/+Oi/5Dyy0t95LP8A46L/AJFslab6Fgpqfn4Jt0e19fcuWLa7s7GcdWcZXmVd/m9O1/qIYfLLS33ks/8Ajov+Q8stLfeSz/46L/kWwSpBTVukkmWZNQ2Teq1Gq/w2LaVE4omc8uK/zEurdJTxPim1DZJI3orXMfWxKjkXmioq8S8AInllpb7yWf8Ax0X/ACMejpoqmwPnglZLDJcK57JGORzXtWqlVFRU5oqdZfAAiay9BtQezan3Ti2RNZeg2oPZtT7pwFsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARNZeg2oPZtT7pxbImsvQbUHs2p904tgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVbvPXy8VDuD43xUiInLYbGkiL68zP8AwRO/NUlab6dgpqjl4Xt1mz9TfOWXZ78beM9eM4TkXThTM+2vhnVjVEe/buqgAhoAAAAAJVt/o93utH1K9lXG1vzWskbsqncqvjkcv/mzzVSqSpvMaopXp0GVVLJHI5eT3sc10bfWiPmXCc0yvHZ4VS6/SeXhnZ4XxwnyAAhoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlaj6Vjmp1+ZVPipHr1oyWRsblTvRHrjvxzKpKr/PX+0U/wA3db6s2uedlqRbP47/ADn9nGOOUql1YUxHvr4Z041TPt37gAIaAAAErUXm7Q+sTgtE9lWrk+cjI3I6RG96sR7erO1heCqVTFVU0NZSTUtQzbhmY6ORuVTLVTCplOPJSqJuqiZTXG1TMQygn2Opmq7DQT1D9qpdAzfrhEVJUTD0VE5KjkVFTqVFQoHKoumYdpnaiJgABx0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKt3nr5eKh3B8b4qRETlsNjSRF9eZn/gid+apK0307BTVHLwvbrNn6m+csuz3428Z68ZwnIql2maY4YfDOyyxPHH5xAAQ0AAAJVt/o93utH1K9lXG1vzWskbsqncqvjkcv/mzzVSqSqnzGpaCZehHUQS07lT+3IitexF7cNbMqKvBMr9bjdGN8a4s68Lp5/eCqACGgAAAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOAtgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunFsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACbqCWSLT9duJHMqJIlhgcxcLvX9CNEXqXac1M9XPgb8UUcETIoo2xxsajWMYmEaicERE6kJt687La6R30dRXM21Tmm7a6ZuP4omovcq+tKpc4URDOMa5kABDQAAAAASr35rxdWc/B66LofW3mYOfVje7Xfs44ZylUn3ymmq7DXwU7NqpdA/cJlEVJUTLFRV5KjkRUXqVEU26WphrKSGqp37cMzGyRuwqZaqZRcLx5KXONETrW9EYVzGtbmUAELAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASqbz+pa+ZOnHTwRU7VX+xIque9E7MtdCqqnBcJ9XhVJVk874xrOXhFdL0Pq7vEHPrzutru2sccZWqXaZrkWeW/iAAhYAAAAAlWTzXjGj5+D10vT+tvMT8urG92e/ZzwzhKpKh8xqiqYvQZVUsckbU5PexzmyO9aI+FMrzTCcdnhVLtN9/FFnlu4a+gAELAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn3ypmpLDXz079mpbA/cLhFVZVTDERF5qrlRETrVUQoEq9+d8XUfLwiui6f1d3mfl153Wz3bWeOMLdnH+ovRaTdTNyhS00NHSQ0tOzYhhY2ONuVXDUTCJlePJDKARM3riLsIAAAAAAlX3zUVDVt+kp66HYReS7x25dn+GVyp3onqWqT75TTVdhr4Kdm1UugfuEyiKkqJlioq8lRyIqL1KiKXZz/AKi9FpF9E3KAMVLUw1lJDVU79uGZjZI3YVMtVMouF48lMpExcuJvxgAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunAWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABE1l6Dag9m1PunFsiay9BtQezan3Ti2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKm8/qilYnTZS0skkjV5Me9zWxu9aoyZMpyTKcNrjVJVu89fLxUO4PjfFSIicthsaSIvrzM/8ETvzVLr9I5eUWfrPPx2AAQsAAAAACVpvoWCmp+fgm3R7X19y5YtruzsZx1ZxleZVJVq83cbxT/NRKpskcfLDHxMVXInYr0k49btrryXTjTMa1izqwriesd+yqACGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGKqqYaOkmqqh+xDCx0kjsKuGomVXCceSGUlak6dgqafl4XsUe19TfOSLa78becdeMZTmVRG1VESmudmmZhlsdNNSWGggqGbNS2Bm/TKKqyqmXqqpzVXKqqvWqqpQAOVTfMy7TGzERAADjoAAAAAlXHzN8s9Q3i+R8tIqLy2HRrIq+vMLPwVe7FUlah83a0qvm+CTxVDpE5xxteiyKnX9HtoqJxVFVOOcFUurGmJ1rFnThVMe/bsAAhoGpcLrbrTAk9yr6WihVcJJUzNjaq9mXKhtnnupfB7p8ocFDSaeprvdqS37xX3Go2Kanje/GUbsuVz1VvNG8ExxA7RLza1ti3JLlRrQJzqt+3dJxx8/OOa45kLU+rm2tbYy2T0VTJNeqa21bFftrC2RVR2Ua5Nl+OWf5HlNbHJR6G+VGl2aGHc1dOu5t2Ugjeu72kYnVxTC8E4ovI6n5S9O2Gx6OslCynipKGS+UiVkzU2XyN6SPe9/NXYyu0q5A9Kob1arnNLDQXOjq5YvpGQTtkcz1oi8CBXaudY7FqO63OptErLdPKylip6nZV+yxHNikVc4lVc8ETrTgQNXWez2PUeiqiw0VLRXN91jgRtJG1iy0qtdvco3m1EwuV5fiT3xRy6L+VfeMa/Zr61zdpM4VKdmFTvA9DteqbPc7VQ1zblQtSsiWRjEqmO4tbtSNRc8VZ19mOODYmv9mprfFcJ7vQRUUv0dS+pY2N/qcq4U82u1mobncfkvts8DPA5oZ3SxNTZbIiUzXqionNFVOKdaZyUr3S26bXNJZ7Tpahr66323aa2slSGjpInvwmzGjHZcqt6m8E6wO6S82tbYtyS5Ua0Cc6rft3SccfPzjmuOZ+NvlodW+BNulEtWsixbhKhm3tomVbs5zlE4454PDa2OSj0N8qNLs0MO5q6ddzbspBG9d3tIxOrimF4JxReR3etNL0WntDsuFioYoqqyVMVzRzGoj51jXzivdzcqsV+VXOQO/fXUkVbFRSVUDKuZrnxQOkRHvanNUbzVE68HP6r1tbtJ1lop6yalR1fVNhfvqpsSwxqjlWVUXm1FaidSceZH0hURaq1zfNVwu3tDTRstVvf1KiYklcnrc5Ez+yffyjU0E1z0YssMb1dfomKrmouW7uTh6u4Drq29Wq2wxTV9zo6WKX6N887WNf6lVePND7kulvibSukrqVjatyMpldM1EmcqZRGcekq9iHlfgN0u/yo6pRlq0/cJaRtPDBFd5XpuYFjRU3bUjcmyrlXK9vA+aC2UFJ8m2qqe911vZbqavkkpktUr5EoJk2VSOJXNau0kiphE4dLAHqVfe7XbHPZW3KjppGQrOrJp2sXdouNrCr83OEzyyTdF6spNZabprtT7mOSRvnqaOdJVgdlei5URMLjjxROZyXyaI65019qtRsc/Vaq2G4w1EaIsUSNzE1reWwqdLvcq9iFj5Iooo/kusTo42Nc+BVerWoiuXadxXtA7YAAAAAAAAlTef1RSsTpspaWSSRq8mPe5rY3etUZMmU5JlOG1xqkqg89f7vUfN3W5o9nnnZasu1+O/xj9nOeOEuj1nl4RXjdHPz2VQAQsAAAAAAABK050bHDTp8ylfLSMXrVkUjo2qveqMTPfnkVSVa/M3S70q9Hz7aiONOSRvY1Mp1JmRkqqnPOVXnlapdpmmePdnZZIjhh8YAAIaAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOAtgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunFsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGvXVkdvt9TWyo50dPE6V6MTKqjUVVx38DsRfN0OTMRF8tLT/Tt0tQvSWeqqJEk57xiyuSN2etNhGYX6qNxwwVTSs9HJb7JQUUqtdJT00cT1YuUVWtRFx3cDdKrm+qZhNnExRESAAhYAAAAAEr6DVn1vDKH1bG5f/nnwj8Nnrzwqkq5eavFlmZwkfPJTuXtjdE96p/eijXPPo965ujfMcpZ2m6J5x+lUAENAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJV185cbPT/ORap0kkfPLGRPVHKnYj1j49TtnrwVSU7z2rI9nh4JQu3mevfPbs49W4fn1pz44ujff1Z2m6I5wqgAhoAAAAAAAA1bnReMrTWUO83fhMD4dvGdnaaqZx18xbK3xlaaOu3e78JgZNsZzs7TUXGevmbRK070bO2FPo6eeeniT6sccr2MTvw1qJleK44l/wDHvr6ZzhXHTX2qgAhoEO96OsGoquGrulvSaphbsMmZK+N+znOyrmKiqncvAuADl3/J1pJ8dZElmijjrYGU9RHDI+NsjGqitRUa5EyitTinHv4le82G16hpYqW7UbKuCKZs7Y5FXZ225wqoi8U4rwXKL2FEAc7ZNC6Z07XLXWu0xQVSt2ElV75HMb2N2lXZTuTBvRadtMNPdKdtG1YbrI+WtY5znJM57Ua7OV4ZRETCYQqACDQaMsFsW1rSULmLa3SOo9qeR+6WRuy/5zlzlOGFzjqwfV70dYNRVcNXdLek1TC3YZMyV8b9nOdlXMVFVO5eBcAHLv8Ak60k+OsiSzRRx1sDKeojhkfG2RjVRWoqNciZRWpxTj38TZ1jcKuh07UNobNU3aoqWup2U8DWqiK5q4WTKphnUq95fAHPaG043SejLZZujvYIUWZW8lld0nrnrTaVcd2DdvunbVqWijo7vSJUQxypMxN45isemcORzVRUXivJesqADn7zojTl/fBJc7YyaWCPdxytkfHIjPqq9qo5U7lXt7TKmkLA2it1Ey2xMpLdMk9LAxzmsZImcOVqLhy5VV6WePHmWwBPWx25b9478Hxcdx4MszXuTajznZc1F2XceWUVUMNh01aNMU0tNZ6TwWCV+8dGkr3NRe5HKuyncmEKwAAAAAAAAAEqwedo6irXi+qqppN51SMR6sjcnVhY2R4VOaYXjnK7tdWR2+31NbKjnR08TpXoxMqqNRVXHfwMVno5LfZKCilVrpKemjierFyiq1qIuO7gXGFE616M5xrjWvVugAhoAAAAAAAAlfQas+t4ZQ+rY3L/APPPhH4bPXnhVJV06N1sj28Huqnxq5OasWCVyt9Sqxi47WovUhVLr3RPJnRvmOfkABDQAAAiay9BtQezan3Ti2RNZeg2oPZtT7pwFsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARNZeg2oPZtT7pxbImsvQbUHs2p904tgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlaj6Vjmp1+ZVPipHr1oyWRsblTvRHrjvxzKpKuvnLjZ6f5yLVOkkj55YyJ6o5U7EesfHqds9eC7PNE8OzO1yTHHD5wVQAQ0AAAAAAAACVqLo2d0y/R088FRKv1Y45WPevfhrVXCcVxwKpq3Oi8ZWmsod5u/CYHw7eM7O01Uzjr5lUTEVRMotImaJiG0DVtlb4ytNHXbvd+EwMm2M52dpqLjPXzNo5MTE3SqJiYvgABx0AAAAAAAAAAAAAAAAAAAAAAAAAAAlW7z18vFQ7g+N8VIiJy2GxpIi+vMz/wRO/NUlWDpUNTI7jI+uqtty83bMz2NyvXhrWtTsRqJ1F04UzOtYM6saoj37d1UAENAAAAAAAAAlW3zV4vUL+Ej546hqdsbomMRf70UiY59HvTNUlfQas+t4ZQ+rY3L/wDPPhH4bPXnhdG6Y5Ir3xPPwqgAhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlaj6Vjmp1+ZVPipHr1oyWRsblTvRHrjvxzKpKvPTqbRTu4xTVybxvbsRySt/k+Ni/hjkqoVS5wpiNawRTjXM9I18gAIWAAAAAAAAlai6NndMv0dPPBUSr9WOOVj3r34a1VwnFccCqatzovGVprKHebvwmB8O3jOztNVM46+Ytlb4ytNHXbvd+EwMm2M52dpqLjPXzL/499fSN1ftr7bQAIWAAARNZeg2oPZtT7pxbImsvQbUHs2p904C2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImsvQbUHs2p904tkTWXoNqD2bU+6cWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASpPO6sp9jj4PQy739nePj2PXndScuWzxxlM1SVQeev93qPm7rc0ezzzstWXa/Hf4x+znPHCXR6zy8Irxujn57KoAIWAAAAAAAAAACVpzo2OGnT5lK+WkYvWrIpHRtVe9UYme/PIqkq0dGuvUbeEbK5Nhqcm7UMT3YTqy5znL2q5V6yqXaZpnj3Z2WSI4YfGAACGgAAAAAAAAAAAAAAAAAAAAAAAAAAMVVUw0dJNVVD9iGFjpJHYVcNRMquE48kNSxU01Hp620tQzYmhpYo5G5RcORiIqZThzQxak6dgqafl4XsUe19TfOSLa78becdeMZTmVS91HWfr+o319I+/4AAhYAAAAAAAASrl5q8WWZnCR88lO5e2N0T3qn96KNc8+j3rmqStQdC3RVCdFYKqnkWTlu2JK1JHZ6k2Fflfqq7PDJdnmu492dplv4Y/GKqACGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlSed1ZT7HHwehl3v7O8fHsevO6k5ctnjjKZqkqi89qK61DeDI2QUiovPbajpFX1YmZ+KL3Zql1+kcvKLP1nn47AAIWAAAAAAAAErTvRs7YU+jp556eJPqxxyvYxO/DWomV4rjiVSVa+jdb2x3B7qpkiNXmrFgiajvUqseme1qp1KXTjTMe+vlnVhVE+3fsqgAhoAAARNZeg2oPZtT7pxbImsvQbUHs2p904C2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5i7a5t1quNRQsorlXzUrEfVLQ029bToqZTbXKY4ccJlcF6319LdbfBX0UzZqadiPje3rRf/AL5AbIOaves6ey3ltqbaLtcapadKlW0EDZNhiuVqKuXJjiilOyXdb1ROqVttwt+zIrN1XwpHIuERdpERV4cefcoGvq9Gu0Vfkc7ZatuqEV2M4Tdu4lWlqYaykhqqd+3DMxskbsKmWqmUXC8eSknWXoNqD2bU+6cZtN9HTtFTr8+lZ4I9epXxKsblTuVWLjuxyKujZvRfO3EKoAJWAAAAAAAAAAAAAAAAAAAAAAAAAAASrD06asqHcZZq6o3ju3YkdE3+TI2J+GeaqpVJWmeOl7U9eL5KWOR7utz3NRznL2qqqqqvWqqpcZJ9u7Oc8e/ZVABDQAAAAAAAAAAEqPzWrKjb4eEUMW6/a3b5Nv1Y3sfPntcM4XFUlVvmdRWqodxZIyekRE57bkbIi+rEL/xVO/FUuv0nl4Z0esc/PcABDQAAAAAAAAAAAAAAAAAAAAAAAAAAEq9edltdI76OormbapzTdtdM3H8UTUXuVfWlUlVPS1RbWO4sbS1MiNXkj0dC1HetEe9M9jlTrUql1ZY16s6c1WvQABDQAAAAAAAAJ99ppqzT1ypadm3NNSyxxtyiZcrFREyvDmpQB2mdmYmHKo2omJYqWphrKSGqp37cMzGyRuwqZaqZRcLx5KZSVpvoWCmp+fgm3R7X19y5YtruzsZx1ZxleZVO1xdVMOUTtUxMgAJUAAAAAAAAAAAAAAAAAAAAAAAAAACVYvOxV1W76SorpttE5Ju3bluP4Ymqveq+pKpK010tNW6ZfpKiBtRKv1pJE23r3Zc5VwnBM8CqXaZ5Z2WSAAENAAAAAAAAAlR+a1ZUbfDwihi3X7W7fJt+rG9j589rhnC4qkqv8zf7RUfO3u+o9nljaaku1+G4xj9rOeGFuj1jl5Z2mF08/HdVABDQAAAiay9BtQezan3Ti2RNZeg2oPZtT7pwFsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxnyfJl+qZH8ZnX+qa9evCbKNT1YP35MejpF8TPoI66pZAnUjEldjH+ZmrtI13jWurrJf5bUlwwtXElO2VHPRNnbZlU2HY5rx7TdTTctv0rT2Sw3F9tWn2UZULE2Zyoi5dlFwiq7jle8CXXaY1DUayr7vQ3unt0E9NFAxzadJ5cNyqoqO6LUy5V4ZVeHI3dIXm4163S23dYn3C11O4knhbstmarUc1+OpVReKHzcNKVi3you9jvb7VUVbWtq2LTtnjlVqYa7ZVUw5E4Z/yKOntPw2CkmYlRLVVVTKs9VVTY25pF5rw4InDCInJAMesvQbUHs2p904m2mm1Gx9wpIbramtpqx6K59skcrnSI2Zy8J0wmZVRE48ETipS1l6Dag9m1PunGai8zqK607eLJGQVaqvPbcjo1T1YhZ+Kr3YunLMIqzUzrd4UoUlbBGk72PmRqI97GK1rnY4qiKq4TPVlfWp9gELAAAAAAAAAAAAAAAAAAAAAAAAAABK1Nx0vdWJxfJSyRsb1ue5qta1O1VVURE61VEKpKvvnYqGkb9JUV0Owq8k3bt87P8MTkTvVPWlUucke/ZEZ59u4ACFgAAAAAAAAAAlXvzXi6s5+D10XQ+tvMwc+rG92u/ZxwzlKpK1J0dO1tQnz6VnhbE6lfEqSNRe5VYme7PIqlzkieqIzzHTX4AAQsAAAAAAAAAAAAAAAAAAAAAAAAAAEqm6WqLk9vFjaWmjVyckejpnK31oj2Ljsci9aFUlWbp1N3qG8Ypq5d27t2I44nfyfG9PwzyVFKpdpm+PpFnl+fsABCwAAAAAAAAAASrL5qW6Ujfo6eufsKvNd41szs/xSuRO5E9a1SVSea1LdIWcI3wU9Q5O2RyyMVf7sUaY5dHvXNUu0zfH0izy/P2AAhYAAAAAAAAAAAAAAAAAAAAAAAAStTcdL3VicXyUskbG9bnuarWtTtVVVEROtVRCqSr906ajp28ZZq6n3be3YkbK7+TI3r+GOaohdnnhFrklVABCwAAAAAAAAAACVffNRUNW36SnrodhF5LvHbl2f4ZXKneiepapK1L0dNXGZPpKeB1REv1ZI022L34c1FwvBccS7PPCLXJKqACFgAA+JkldBIkD2MmVqox72K5rXY4KqIqZTPVlPWhx+rKbUbdG3xZ7ranwpb51exlska5zd27KIqzrhcdeF9SnZkTWXoNqD2bU+6cBbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETWXoNqD2bU+6cZpPNasp9jh4RQy739rdvj2PVjeycue1xzhMYdZeg2oPZtT7pxmunRutke3g91U+NXJzViwSuVvqVWMXHa1F6kLs9/tP0ztN0dY+1UAENAAAAAAAAAAAAAAAAAAAAAAAAAAASq/z1/tFP83db6s2uedlqRbP47/Of2cY45SqSvp9WfV8DofXt75/+WPB/x2urHGqXXuiOTOjfM8/AACGgAAAAAAAAAAMVVTQ1lJNS1DNuGZjo5G5VMtVMKmU48lNSxVM1Zp621VQ/bmmpYpJHYRMuViKq4ThzUoErT39Wzfv1Z/uJC4yT1/bOc8dJ7KoAIaAAAAAAAAAAAAAAAAAAAAAAAAABq3Ot8W2msrt3vPBoHzbGcbWy1Vxnq5HYiZm6HJmIi+WppzpWOGoT5lU+WrYnWjJZHSNRe9Eeme/PMqmrbKLxbaaOh3m88GgZDt4xtbLUTOOrkbR2uYmqZhNnExRESAAlYAAAAAAAAAAJU3Q1ZR7PR3tDPvMcNvZfDs57cbb8dm0vapVJV36NdZZHcI2Vy7bl5N2oZWNyvVlzmtTtVyJ1lUurdGvWWdG+rr2gABDQAAAAAAAAAAAAAAAAAAAAAAAAJVx89fLPTt4PjfLVqq8thsaxqnrzMz8EXuzVJX0+rPq+B0Pr298//LHg/wCO11Y43RvmeUs7TdEc4/aqACGgAAAAAAAAAAB8SxRzxPiljbJG9qtex6ZRyLwVFTrQ+wBN07LJPpm1SyyOkkfRwue965VyqxFVVXrUpEqwdGhqY3cJGV1VttXm3ame9uU6stc1ydqOResql2meUWWSOgACFhE1l6Dag9m1PunFsiay9BtQezan3TgLYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiay9BtQezan3TjNqHhamvXgyOqppHu6msbPG5zl7EREVVXqRFUw6y9BtQezan3TjbvtNNWaeuVLTs25pqWWONuUTLlYqImV4c1Ls5uriZ4otIvomI4KAMVLUw1lJDVU79uGZjZI3YVMtVMouF48lMpExcuJvxgAAAAAAAAAAAAAAAAAAAAAAAAAAEq3eevl4qHcHxvipEROWw2NJEX15mf+CJ35qkqw9OmrKh3GWauqN47t2JHRN/kyNifhnmqqVS7TNdw7Is8t/HH5AAQsAAAAAAAAAAAlWvo3W9sdwe6qZIjV5qxYImo71KrHpntaqdSlUlR+a1ZUbfDwihi3X7W7fJt+rG9j589rhnC4ujdV07wivfT17SqgAhYAAAAAAAAAAAAAAAAAAAAAAAAStR9KxzU6/MqnxUj160ZLI2Nyp3oj1x345lUlXnp1Nop3cYpq5N43t2I5JW/wAnxsX8MclVC7PNE8OyLXJMccPlVABCwAAAAAAAAAAAABK1F0bO6Zfo6eeColX6sccrHvXvw1qrhOK44FUn32mmrNPXKlp2bc01LLHG3KJlysVETK8Oam3S1MNZSQ1VO/bhmY2SN2FTLVTKLhePJS5yR1nsiM89I7soAIWAAAAAAAAAAAAAAAAAAAAAAAAEq3eevl4qHcHxvipEROWw2NJEX15mf+CJ35qkqxedirqt30lRXTbaJyTdu3LcfwxNVe9V9SXThTM61girGqmNaxVQAQsAAAAAAAAAAAAASrb5q8XqF/CR88dQ1O2N0TGIv96KRMc+j3pmqSm+Z1ZJtcfC6Fu7x1bl7trPr37MepeXDNUu03xPKEWe6Y5z9gAIWETWXoNqD2bU+6cWyJrL0G1B7NqfdOAtgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunFsCVpro6at0K/SU8DaeVPqyRpsPTvw5qplOC44FUlWLzUVdSO+kp66bbVOS7x2+bj+GVqL3ovrWqXaZ5Z2WSAAENAAAAAAAAAAAAAAAAAAAAAAAJWp/RO8/uM/wDoUqmNqqITVVs0zPA0zx0vanrxfJSxyPd1ue5qOc5e1VVVVV61VVKoAqnaqmSmnZpiOAACVAAAAAAAAAAAEqt8zqK1VDuLJGT0iInPbcjZEX1Yhf8Aiqd+KpKvXmpbXVu+jp65m2ic13jXQtx/FK1V7kX1Ldnm+fpnaZfj7VQAQ0AAAAAAAAAAAAAAAAAAAAAAAACVU9LVFtY7ixtLUyI1eSPR0LUd60R70z2OVOtSqSoenqys2uluqGDd547G0+bax2Z2GZ7dlOxC6PWeXhnaY3Rz89lUAENAAAAAAAAAAAAAAJWm+jp2ip1+fSs8EevUr4lWNyp3KrFx3Y5FUlWTzXjGj5+D10vT+tvMT8urG92e/ZzwzhLjJMdGc54nrr8KoAIaAAAAAAAAAAAAAAAAAAAAAAAABK010tNW6ZfpKiBtRKv1pJE23r3Zc5VwnBM8D71FLJBpm7SxSOjkZRzOY9i4VqoxVRUXqU34oo4ImRRRtjjY1GsYxMI1E4IiJ1IXuo6z9f1nvr6R9/x9gAhoAAAAAAAAAAAAAJVb5nUVqqHcWSMnpEROe25GyIvqxC/8VTvxVJV7814urOfg9dF0PrbzMHPqxvdrv2ccM5SqXVliWdOaqNbvAACGgRNZeg2oPZtT7pxbImsvQbUHs2p904C2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImsvQbUHs2p904tkTWXoNqD2bU+6cWwJVu8zfLxTu4vkfFVoqcth0aRonrzC/8FTvxVJX0GrPreGUPq2Ny/wDzz4R+Gz154VS698TyhFnumOc/sABCwAAAAAAAAAAAAAAAAAAAAAJV/wClQ00beMj66l2GpzdszMe7CdeGtc5exGqvUVSVdOldbIxvF7ap8itTmjEglarvUivYme1yJ1oXZ5r+HZnaZbuOHzgqgAhoAAAAAAAAAAAAABK1J0LBU1HPwTYrNn6+5ckuz3Z2MZ6s5wvIqmrc6Lxlaayh3m78JgfDt4zs7TVTOOvmVRMRVEyi0iZomIbQNW2VvjK00ddu934TAybYznZ2mouM9fM2jkxMTdKomJi+AAHHQAAAAAAAAAAAAAAAAAAAAAJVp/rK+/vzf9vCVSVp7janPTiySqqZGO6nMdPI5rk7UVFRUXrRUUunCmZ9tfDOrGqI9+3dVABDQAAAAAAAAAAAAACVQeZv93p/nb3c1m1yxtNWLZ/DcZz+1jHDK1SU7zOrI9nj4XQu3mercvbs49e/fn1Jy45ujdMcvKK98Tz8KoAIWAAAAAAAAAAAAAAAAAAAAAAAAlah42prF4skqqaN7epzHTxtc1e1FRVRU60VUKpKu39ZWL9+d/t5iqXVhTEe+vhnTjVM+3fuAAhoAAAAAAAAAAAAAJWpOjp2tqE+fSs8LYnUr4lSRqL3KrEz3Z5FU166jjuFvqaKVXNjqInRPVi4VEciouO/iYrPWSXCyUFbKjWyVFNHK9GJhEVzUVcd3EvfR0nX0jdX1j6/rdABCwiay9BtQezan3Ti2RNZeg2oPZtT7pwFsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARNZeg2oPZtT7pxbImsvQbUHs2p904tgSq/wAzf7RUfO3u+o9nljaaku1+G4xj9rOeGFqkq++aioatv0lPXQ7CLyXeO3Ls/wAMrlTvRPUtUurLE61izpwqqjWsAAENAAAAAAAAAAAAAAAAAAAAAAJUnndWU+xx8HoZd7+zvHx7HrzupOXLZ44ymapKpPO6lukzOMbIKencvZI1ZHqn92WNc8ul3Li6PWeXhFeN0c/PZVABCwAAAAAAAAAAAAAAAErTnRscNOnzKV8tIxetWRSOjaq96oxM9+eRVJVl81LdKRv0dPXP2FXmu8a2Z2f4pXIncietapdpnmWdlkiOHYABDQAAAAAAAAAAAAAAAAAAAAAfEsscET5ZZGxxsarnveuEaicVVV6kNDTsUkGmbVFLG6ORlHC17HphWqjERUVOpT41L0tNXGFPpKiB1PEn1pJE2GJ3Zc5EyvBM8SqXuo6z9f1nvr6R9/wABDQAAAAAAAAAAAAACVcfM3yz1DeL5Hy0iovLYdGsir68ws/BV7sVSVfuhTUdQ3hLDXU+7d2bcjYnfzZI9PxzzRFLs813HuztMt/DH4VQAQ0AAAAAAAAAAAAAAAAAAAAAAAASpunqyj2eluqGfeY47G0+HZz2Z2H47dlexSqSqbpaouT28WNpaaNXJyR6OmcrfWiPYuOxyL1oVS6/SOXlnZ+s8/HYABDQAAAAAAAAAAAAACVp3o2dsKfR0889PEn1Y45XsYnfhrUTK8VxxKpKs3QqbvTt4RQ1y7tvZtxxyu/m+R6/jjkiIXGNMxrWLOrCuJ6xr4VQAQ0CJrL0G1B7NqfdOLZE1l6Dag9m1PunAWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABE1l6Dag9m1PunFsiay9BtQezan3Ti2BK1J0dO1tQnz6VnhbE6lfEqSNRe5VYme7PIqmvXUcdwt9TRSq5sdRE6J6sXCojkVFx38TFZ6yS4WSgrZUa2Sopo5XoxMIiuairju4l76Ok6+kbq+sfX9boAIWAAAAAAAAAAAAAAAAAAAAABKs3TqbvUN4xTVy7t3bsRxxO/k+N6fhnkqKVSVpzpWOGoT5lU+WrYnWjJZHSNRe9Eeme/PMuMKZnWsGdWNcR1nXyqgAhoAAAAAAAAAAAAAAAAlUnmtS3SFnCN8FPUOTtkcsjFX+7FGmOXR71zVJUnmtWU+xw8IoZd7+1u3x7HqxvZOXPa45wmKpdfpPLwiz9Y5+e4ACFgAAAAAAAAAAAAAAAAAAAACVfunTUdO3jLNXU+7b27EjZXfyZG9fwxzVEKpKuXnbxZYWcZGTyVDk7I2xPYq/3pY0xz6XcuKpdWFMRrWDOnGqqfbXyAAhoAAAAAAAAAAAAABK1L0dNXGZPpKeB1REv1ZI022L34c1FwvBccSqYqqmhrKSalqGbcMzHRyNyqZaqYVMpx5KVROzVEymuNqmYhlBPsVTNWaettVUP25pqWKSR2ETLlYiquE4c1KByqLpmHaZ2oiYAAcdAAAAAAAAAAAAAAAAAAAAAEqzdOpu9Q3jFNXLu3duxHHE7+T43p+GeSopVJWnelZ2zJ9HUTz1ES/Wjkle9i92WuRcLxTPEql2maY4dmdlkieOPyAAhoAAAAAAAAAAAAABKpPNalukLOEb4KeocnbI5ZGKv92KNMcuj3rmqSpuhqyj2ejvaGfeY4bey+HZz242347Npe1S6PWOXlnXhdPPx3VQAQ0CJrL0G1B7NqfdOLZE1l6Dag9m1PunAWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABE1l6Dag9m1PunFsiay9BtQezan3Ti2AJWnejZ2wp9HTzz08SfVjjlexid+GtRMrxXHEqkqzdCpu9O3hFDXLu29m3HHK7+b5Hr+OOSIhcY0zGtYs6sK4nrGvhVABDQAAAAAAAAAAAAAAAAAAAAAa9dWR2+31NbKjnR08TpXoxMqqNRVXHfwMVno5LfZKCilVrpKemjierFyiq1qIuO7ga+pOlp2tp0+fVM8EYvUj5VSNqr3Ir0z3Z5lUvdR1nX2jfX0j7/gACFgAAAAAAAAAAAAAAAJVy81eLLMzhI+eSncvbG6J71T+9FGuefR71zVJV+6FNR1DeEsNdT7t3ZtyNid/Nkj0/HPNEUql1Y0xOtYs6cKqo99fAACGgAAAAAAAAAAAAAAAAAAAAAlSed1ZT7HHwehl3v7O8fHsevO6k5ctnjjKZqkqi89qK61DeDI2QUiovPbajpFX1YmZ+KL3Zql1+kcvKLP1nn47AAIWAAAAAAAAAAAAAAAAlae4WpzE4MjqqmNjeprGzyNa1OxERERE6kREKpKtHRrr1G3hGyuTYanJu1DE92E6suc5y9quVesql2maZ492dlkiOGHxgAAhoAAAAAAAAAAAAAAAAAAAYqqpho6SaqqH7EMLHSSOwq4aiZVcJx5IZSVqXpaauMKfSVEDqeJPrSSJsMTuy5yJleCZ4lURtVREprnZpmYZbFTTUenrbS1DNiaGlijkblFw5GIiplOHNCgAcqm+Zl2mNmIiAAHHQAAAAAAAAAAAAAJV06N1sj28Huqnxq5OasWCVyt9Sqxi47WovUhVJV/6NDTSN4SMrqXYcnNu1MxjsL1Za5zV7UcqdZdnmu492dplv4Y/GKqACGgRNZeg2oPZtT7pxbImsvQbUHs2p904C2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImsvQbUHs2p904tkTWXoNqD2bU+6cWwBKpPNalukLOEb4KeocnbI5ZGKv92KNMcuj3rmqSpPNasp9jh4RQy739rdvj2PVjeycue1xzhMXR6xy8orwunn47qoAIWAAAAAAAAAAAAAAAAAAAAAJV987FQ0jfpKiuh2FXkm7dvnZ/hicid6p60qkq4+evlnp28Hxvlq1VeWw2NY1T15mZ+CL3Zql1ZYjWsGdONVU61iAAhoAAAAAAAAAAAAAAAAlam4aXur04PjpZJGO62va1XNcnYqKiKi9SoilU+JYo54nxSxtkje1WvY9Mo5F4Kip1oaGnZZJ9M2qWWR0kj6OFz3vXKuVWIqqq9al76Ok/f8Z7q+sfX9UgAQ0AAAAAAAAAAAAAAAAAAAAAEqy+dlulW36Oorn7CLzTdtbC7P8UTlTuVPUlUlac6VjhqE+ZVPlq2J1oyWR0jUXvRHpnvzzKpdpnmGdlkiePcABDQAAAAAAAAAAAAAAABKpujqi5MbwY6lppFanJXq6Zqu9aoxiZ7GonUhVJU3Q1ZR7PR3tDPvMcNvZfDs57cbb8dm0vapVLr9J5eGdn6xz89wAENAAAAAAAAAAAAAAAAAAACVffOxUNI36SorodhV5Ju3b52f4YnIneqetKpKuPnr5Z6dvB8b5atVXlsNjWNU9eZmfgi92bs817O0y3ce6qACGgAAAAAAAAAAAAAAAAStTcNL3V6cHx0skjHdbXtarmuTsVFRFRepURSqCqZ2aolNVO1TMcQErTHonZv3GD/QhVFUbNUwU1bVMTxCJrL0G1B7NqfdOLZE1l6Dag9m1PunEqWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5quuWpa2qlprHa4KaKN6sdW3Nyo1youF2I29JydjlVEXqygHSg47xLrpF3qavonO//AGVtTdj+e1k37dctRU1XFSX21QyNkXZbXW1yujRf22O6TPXxT1AdEAAAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunFsASrp0brZHt4PdVPjVyc1YsErlb6lVjFx2tRepCqSr/wBGhppG8JGV1LsOTm3amYx2F6stc5q9qOVOsuzzXce7O0y38MfjFVABDQAAAAAAAAAAAAAAAAAAAAASvp9WfV8DofXt75/+WPB/x2urHGqSqDz1/u9R83dbmj2eedlqy7X47/GP2c544SqXXviOUIs90zzn9AAIWAAAAAAAAAAAAAAAAErT3C1OYnBkdVUxsb1NY2eRrWp2IiIiInUiIhVJVo6Ndeo28I2VybDU5N2oYnuwnVlznOXtVyr1l040zGtYs6sK4nrHfsqgAhoAAAAAAAAAAAAAAAAAAAa9dWR2+31NbKjnR08TpXoxMqqNRVXHfwNglak6Wna2nT59UzwRi9SPlVI2qvcivTPdnmVRF9URKa5mKZmGxZ6OS32SgopVa6Snpo4nqxcoqtaiLju4G6Acmb5vl2mIpi6AAHHQAAAAAAAAAAAAAAAEq6dG62R7eD3VT41cnNWLBK5W+pVYxcdrUXqQqkrUP9Ww/v1H/uIyqXVjTE+2vlnThVMe/bsAAhoAAAAAAAAAAAAAAAAAAASnee1ZHs8PBKF28z1757dnHq3D8+tOfHFUlUXntRXWobwZGyCkVF57bUdIq+rEzPxRe7N0bpnl4RXviOflVABCwAAAAAAAAAAAAAAAAAAStPf1bN+/Vn+4kKpKtP8AWV9/fm/7eEql2maZ44/LOyyxHDD4wCJrL0G1B7NqfdOLZE1l6Dag9m1PunENFsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ19o/D7LU0/jCa35RHpVxPRrolaqORcrwxw49qZQonJXy+6fqkqLHqiKSghklRG+GIrIahrXo5qtkTo4XZRVaqovUqAcd/wDEW/SwMtyTUUcLqhabynWJ/gq8OaNVuNvq57Oe7ienWO3+K7NT0nh09crUVy1M79p8qucrlXPZleHdg1H3TS62taV9faPF6s2N0s0e62OzGcYJunb1YoWU9j0xFPXUsL3I6WDLoKdquVy5ldwXnwRqqvIDrQAAAAAGrXXOgtkbZLhXU1Ixy4a6olbGir2IqqhsRyRzRNlie18b02muauUVO1FAjay9BtQezan3Ti2RNZeg2oPZtT7pxbAErU3DS91enB8dLJIx3W17Wq5rk7FRURUXqVEUqnxLFHPE+KWNskb2q17HplHIvBUVOtCqJ2aolNdO1TMPsE3Tssk+mbVLLI6SR9HC573rlXKrEVVVetSkcqjZmYKatqmJ4gAOKAAAAAAAAAAAAAAAAAABKsnnfGNZy8Irpeh9Xd4g59ed1td21jjjK1SVpvp2CmqOXhe3WbP1N85Zdnvxt4z14zhORVLtM8wzsskSAAhoAAAAAAAAAAAAAAAAEqm6OqLkxvBjqWmkVqclerpmq71qjGJnsaidSFUlTdDVlHs9He0M+8xw29l8Ozntxtvx2bS9ql0escvLOvC6efjuqgAhoAAAAAAAAAAAAAAAAAAASr353xdR8vCK6Lp/V3eZ+XXndbPdtZ44wtUlV/nr/aKf5u631Ztc87LUi2fx3+c/s4xxyl2ea9naZbun2qgAhoAAAAAAAAAAAAAAAAAACVqf0TvP7jP/AKFKoJWmPROzfuMH+hC99HSfv+M91fWPr+qoAIaAAAAAAAAAAAAAAAAAAAEqy+dlulW36Oorn7CLzTdtbC7P8UTlTuVPUlUlac6VjhqE+ZVPlq2J1oyWR0jUXvRHpnvzzLjCiZ6a/DOrGuI66/KqACGgAAAAAAAAAAAAAAAAAAJVP6WXD9xpf9c5VJVR6WW/9xqv9cBVLr9J5eOzOj1jn57hE1l6Dag9m1PunFsiay9BtQezan3TiGi2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGOeCGphdDPEyWJ3BzJGo5q+tFMhB1pe59O6Rr7pSsY6oia1saSfNRzntYir3Irs/gATRGlWzb1NO2vbzn/srMfyxgtxRRwRNihjZHG1MNYxMIidyIcYzTmunMa6TXsbHqmXNZZ4nIi9iKqplDqbTTV1HbIYLlcPGFW3a3lTuUi28uVU6CcEwmE/DIG6AAAAA4Sit9JqD5TNSPulNFVstkNNTUsc7Ee1iSMV712V4ZVevsM+gGpQVGo7JFlKS33JyUzM8I43tR+wnciqv8z7rqC92PV1be7NbW3OnuUEbKmnSobC9kseUa9FdwVNlcKnM3tH2astdHXVVz3aXG5Vb6udkbtpsecI1iL14RE4+sDY1l6Dag9m1PunDyrt32a8fo1X8Iay9BtQezan3Ti2B8QytngjmYj0bI1HIj2KxyIqZ4tciKi9yoiofYAErT3C1OYnBkdVUxsb1NY2eRrWp2IiIiInUiIhVJVo6Ndeo28I2VybDU5N2oYnuwnVlznOXtVyr1lUu0zTPHuzsskRww+MAAENAAAAAAAAAAAAAAAAA1bnW+LbTWV273ng0D5tjONrZaq4z1cjaJWpOnYKmn5eF7FHtfU3zki2u/G3nHXjGU5lURE1REotJmKJmG3bKLxbaaOh3m88GgZDt4xtbLUTOOrkbQByZmZvlURERdAADjoAAAAAAAAAAAAAAAASrt/WVi/fnf7eYqkrUP8AVsP79R/7iMuzzRHHD5Z2mWZ4Y/GKqACGgAAAAAAAAAAAAAAAAAABK+n1Z9XwOh9e3vn/AOWPB/x2urHGqSqDz1/u9R83dbmj2eedlqy7X47/ABj9nOeOEujdM8kV74jn5VQAQsAAAAAAAAAAAAAAAAAAAlae/q2b9+rP9xIVSVaf6yvv783/AG8JdONMx76+WdWFUT7d+yqACGgAAAAAAAAAAAAAAAAAANeurI7fb6mtlRzo6eJ0r0YmVVGoqrjv4GKz0clvslBRSq10lPTRxPVi5RVa1EXHdwNfUnS07W06fPqmeCMXqR8qpG1V7kV6Z7s8yqXuo6zr7Rvr6R9/wABCwAAAAAAAAAAAAAAAAAASrt/WVi/fnf7eYqkrUPC1NevBkdVTSPd1NY2eNznL2IiIqqvUiKpVLqxpifbXyzpwqmPft2fE0rYIJJno9WxtVyoxivcqImeDWoqqvciKqnH6s1LQT6NvkLILqjpLfO1FfaapjUVY3Jxc6NERO9VREOzImsvQbUHs2p904hotgAAAAAAAAAAAAAAAAAAAAAAAAAAAABy+o7hZ7xpe80q3unpYIXpTVdQrGyJA7bRFa5ruGV+b+J1BB1TXUenNL3K5ut8M6NRHuh2ERJZHORG7XD6ypxA88pKqgoaWOmg+V2RIo02Wo6Nj1ROzLsqelaYlbPp2lkZePG7V28V2yjd7016k4cPm/gchcX3uWvttit9ssEN5dROra58lPtQsajtlrG9fFeGe46vSF1jvelLfcY6aOlSZi7UMaYax6OVrkTu2kUC2AAAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunFsAAAJVN0dUXJjeDHUtNIrU5K9XTNV3rVGMTPY1E6kKpKm6GrKPZ6O9oZ95jht7L4dnPbjbfjs2l7VKpdfpPLwzs/WOfnuAAhoAAAAAAAAAAAAAAAAEq9+d8XUfLwiui6f1d3mfl153Wz3bWeOMLVJVb57UVqp3cGRsnq0VOe21GxonqxM/8UTvzdnmvZ2mW7p9qoAIaAAAAAAAAAAAAAAAAAAAErU/onef3Gf8A0KVQVTOzVEpqp2qZjiAlaY9E7N+4wf6EKoqjZqmCmrapieIACVAAAAAAAAAAAAAAAABKsnnfGNZy8Irpeh9Xd4g59ed1td21jjjK1SVpvp2CmqOXhe3WbP1N85Zdnvxt4z14zhORcZJnoznPEddflVABDQAAAAAAAAAAAAAAAAAAAlU/pZcP3Gl/1zlUlVHpZb/3Gq/1wF0escvPZnXhdPPx3VQAQ0AAAAAAAAAAAAAAAAAABKvfnfF1Hy8Iroun9Xd5n5ded1s921njjC1SVX+ev9op/m7rfVm1zzstSLZ/Hf5z+zjHHKVS6ssQzpzVTrd5AAQ0AAAAAAAAAAAAAAAAAABN1FFJPpm7RRRukkfRzNYxiZVyqxURETrU34pY54mSxSNkje1HMexco5F4oqL1ofZK0zw0vamLwfHSxxvb1te1qNc1exUVFRU6lRUL30dJ+/4z3V9Y+v6qkTWXoNqD2bU+6cWyJrL0G1B7NqfdOIaLYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT73Z6a/wBlq7VWbW4qWbDlYuHN60VO9FRF/AoADjKLRVyoqW6TJqWea9V0ccDbjJTtzDExfmozOFXCrxzzwvM6Kw2an09YqS00rnOhpmbKOfzcucqq+tVVfxKIAAAAAAAAAiay9BtQezan3Ti2RNZeg2oPZtT7pxbAAACVdv6ysX787/bzFUlah/q2H9+o/wDcRlUurGmJ9tfLOnCqY9+3YABDQAAAAAAAAAAAAAAAAJTfPask2uHglC3d4698921n1bhmPWvPhiqSrd56+XiodwfG+KkRE5bDY0kRfXmZ/wCCJ35ujdM8kV76Y59pVQAQsAAAAAAAAAAAAAAAAAAAAAStPf1bN+/Vn+4kKpKtP9ZX39+b/t4SqXaZpnjj8s7LLEcMPjAABDQAAAAAAAAAAAAAAABq3Ot8W2msrt3vPBoHzbGcbWy1Vxnq5C2UXi200dDvN54NAyHbxja2WomcdXI1NSdOwVNPy8L2KPa+pvnJFtd+NvOOvGMpzKpf/Hvr7Rvr9tfQACFgAAAAAAAAAAAAAAAAAAEq79GussjuEbK5dty8m7UMrG5Xqy5zWp2q5E6yqStQ8LU168GR1VNI93U1jZ43OcvYiIiqq9SIql2eaI492drkmeGPxiqgAhoAAAAAAAAAAAAAAAAAACV9Pqz6vgdD69vfP/yx4P8AjtdWONUlUHnr/d6j5u63NHs887LVl2vx3+Mfs5zxwlUuvfEcoRZ7pnnP6AAQsAAAAAAAAAAAAAAAAAAAlWDo0NTG7hIyuqttq827Uz3tynVlrmuTtRyL1lUlWvo3W9sdwe6qZIjV5qxYImo71KrHpntaqdSl040zGtYs6sKon279lUiay9BtQezan3Ti2RNZeg2oPZtT7pxDRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOLYAAAStT+id5/cZ/wDQpVBK0x6J2b9xg/0IXvo6T9/xnur6x9f1VABDQAAAAAAAAAAAAAAAAJVi87FXVbvpKium20Tkm7duW4/hiaq96r6kqkrTfS07RVC/PqmeFvTqR8qrI5E7kV647scy4yT7d2c549+yqACGgAAAAAAAAAAAAAAAAAAAAAlU/pZcP3Gl/wBc5VJVT0dUW17uDHUtTGjl5K9XQuRvrVGPXHY1V6lKpdfpPLx2Z0esc/PcABDQAAAAAAAAAAAAAAABKvXnZbXSO+jqK5m2qc03bXTNx/FE1F7lX1pVJVb57UVqp3cGRsnq0VOe21GxonqxM/8AFE781S6ssa9WdOarXoAAhoAAAAAAAAAAAAAAAAAAATdRRST6Zu0UUbpJH0czWMYmVcqsVERE61KQO0zszEpqp2omHxFLHPEyWKRskb2o5j2LlHIvFFRetD7JWmeGl7UxeD46WON7etr2tRrmr2KioqKnUqKhVO1Rs1TBRVtUxPEABKgAAAAAAAAAAAAAAAEqyed8Y1nLwiul6H1d3iDn153W13bWOOMrVJWm+nYKao5eF7dZs/U3zll2e/G3jPXjOE5FUu0zzDOyyRIACGgAAAAAAAAAAAAAAAAAABKh6GrKza6O9oYN3nht7L5trHbjbZns2k7UKpKq/Naltcz+Eb4KinavbI5Y3on92KRc8uj3pm6PWOXlnaYXTz8d1Uiay9BtQezan3Ti2RNZeg2oPZtT7pxDRbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOLYAAACVYOjQ1MbuEjK6q22rzbtTPe3KdWWua5O1HIvWVSVa+jdb2x3B7qpkiNXmrFgiajvUqseme1qp1KXTjTMa1izqwqifbv2VQAQ0AAAAAAAAAAAAAAAAaV4rJLfZK+tiRrpKemklYj0yiq1qqme7gZaGjjt9vpqKJXOjp4mxMV65VUaiIme/gaWoulZ3Qr9HUTwU8qfWjklYx6d2WuVMpxTPAqlzkjr+kRnnp+wAELAAAAAAAAAAAAAAAAAAAAAEq79GussjuEbK5dty8m7UMrG5Xqy5zWp2q5E6yqStQ8LU168GR1VNI93U1jZ43OcvYiIiqq9SIqlUurGmJ1rFnThXMe/bsAAhoAAAAAAAAAAAAAAAAlN89qyTa4eCULd3jr3z3bWfVuGY9a8+GKpKt3nr5eKh3B8b4qRETlsNjSRF9eZn/gid+apdpviOUIs90zzn7AAQsAAAAAAAAAAAAAAAAAAAAASrB0aGpjdwkZXVW21ebdqZ725Tqy1zXJ2o5F6yqSrb5q8XqF/CR88dQ1O2N0TGIv8AeikTHPo96Zql2ma/j3Z2eW7hh8YAAIaAAAAAAAAAAAAAAaV4rJLfZK+tiRrpKemklYj0yiq1qqme7gbpK1H0rHNTr8yqfFSPXrRksjY3KneiPXHfjmXZxfXESi0mYomY4N2ho47fb6aiiVzo6eJsTFeuVVGoiJnv4GwATM3zfKoiIi6AAHHQAAAAAAAAAAAAAAAAAACVeehU2iodwihrk3juzbjkib/N8jE/HPJFUqkrUXRs7pl+jp54KiVfqxxyse9e/DWquE4rjgXZ5ojj3Ra5Jnhj8KpE1l6Dag9m1PunFsiay9BtQezan3TiFrYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiay9BtQezan3Ti2RNZeg2oPZtT7pxbAAAASoehqys2ujvaGDd54bey+bax2422Z7NpO1CqSqno6otr3cGOpamNHLyV6uhcjfWqMeuOxqr1KXR6xy8s7TC6efjuqgAhoAAAAAAAAAAAAAAAAlXnp1Nop3cYpq5N43t2I5JW/yfGxfwxyVUKpKq/O6ltcL+MbIKioanZI1Y2Iv92WRMcul3JiqXVlp16s6M1WvSAAENAAAAAAAAAAAAAAAAAAAAABN1FFJPpm7RRRukkfRzNYxiZVyqxURETrU34pY54mSxSNkje1HMexco5F4oqL1ofZK010dNW6FfpKeBtPKn1ZI02Hp34c1UynBccC99HSfv8AjPdX1j6/qqACGgAAAAAAAAAAAAAAACVYenTVlQ7jLNXVG8d27Ejom/yZGxPwzzVVKpK010tNW6ZfpKiBtRKv1pJE23r3Zc5VwnBM8CqXaZ5Z2WSAAENAAAAAAAAAAAAAAAAAAAAABKj81qyo2+HhFDFuv2t2+Tb9WN7Hz57XDOFxVJVX5rUtrmfwjfBUU7V7ZHLG9E/uxSLnl0e9M1S6/SeXhnR6xz89wAENAAAAAAAAAAAAAAJV687La6R30dRXM21Tmm7a6ZuP4omovcq+tKpKq/O6ltcL+MbIKioanZI1Y2Iv92WRMcul3Ji7PN8/TO0y/H2qgAhoAAAAAAAAAAAAAAAAAAAAABPvtNNWaeuVLTs25pqWWONuUTLlYqImV4c1KAO0zszEw5VG1ExLFS1MNZSQ1VO/bhmY2SN2FTLVTKLhePJSTrL0G1B7NqfdOM2m+jp2ip1+fSs8EevUr4lWNyp3KrFx3Y5GHWXoNqD2bU+6cdri6qYconapiZWwASoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABE1l6Dag9m1PunFsiay9BtQezan3Ti2AAAAlXnoVNoqHcIoa5N47s245Im/wA3yMT8c8kVSqStRdGzumX6OnngqJV+rHHKx7178Naq4TiuOBdnmiOPdFrkmeGPwqgAhYAAAAAAAAAAAAAAACVD09WVm10t1QwbvPHY2nzbWOzOwzPbsp2IVSVa+ldb293F7apkaOXmjEgicjfUiveuO1yr1qVS7Tf7R9Is93vP2AAhYAAAAAAAAAAAAAAAAAAAAAEqw9CmrKd3CWGuqN43s25HSt/myRi/jjmioVSVbvM3y8U7uL5HxVaKnLYdGkaJ68wv/BU78XTjTMa1iirCqmfbXwqgAhYAAAAAAAAAAAAAE++1M1Hp65VVO/YmhpZZI3YRcORiqi4XhzQoErUPG1NYvFklVTRvb1OY6eNrmr2oqKqKnWiqhdnF9cRPFFpN1EzHBQpaaGjpIaWnZsQwsbHG3KrhqJhEyvHkhlAImb1xF2EAAAAAAAAAAAAAAAAAAAAAAAAJV681La6t30dPXM20Tmu8a6FuP4pWqvci+papK1H0bHNUL8ylfFVvTrVkUjZHIneqMXHfjkVS5yRPXX5RThXMdNfgABCwAAAAAAAAAAAAAJUfndWVG3x8HoYt1+zvHybfrzuo+fLZ4YyuapKtvnbxepn8ZGTx07V7I2xMeif3pZFzz6XcmLo3VdO8Ir309e0qoAIWAAAAAAAAAAAAAAAAAAAAAAAAlWLzUVdSO+kp66bbVOS7x2+bj+GVqL3ovrXDrL0G1B7NqfdOM1u8zfLxTu4vkfFVoqcth0aRonrzC/8ABU78YdZeg2oPZtT7pxdpmvRZ5buHZbABCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOLYAAADSvFHJcLJX0UStbJUU0kTFeuERXNVEz3cTdB2Jum+HKoiYulr0NZHcLfTVsSObHURNlYj0wqI5EVM9/E2CVpvo6doqdfn0rPBHr1K+JVjcqdyqxcd2ORVO1xdVMQ5RM1UxMgAJUAAAAAAAAAAAAfEsscET5ZZGxxsarnveuEaicVVV6kAm2DpUNTI7jI+uqtty83bMz2NyvXhrWtTsRqJ1FUm6dikg0zaopY3RyMo4WvY9MK1UYiKip1KUi7TPKLLJHQABCwAAAAAAAAAAAAAAAAAAAAAJTfM6sk2uPhdC3d46ty921n179mPUvLhmqSq/wAzf7RUfO3u+o9nljaaku1+G4xj9rOeGFuj1jl5Z2m6J5x+lUAENAAAAAAAAAAAAAAJV36VdZY3cY31y7bV5O2YZXtynXhzWuTsVqL1FUlVHpZb/wBxqv8AXAXZ7/n6Z2mX3j7VQAQ0AAAAAAAAAAAAAAAAAAAAAAAAatzovGVprKHebvwmB8O3jOztNVM46+Ytlb4ytNHXbvd+EwMm2M52dpqLjPXzNolab6Fgpqfn4Jt0e19fcuWLa7s7GcdWcZXmX/x76+mc4Vx019qoAIaAAAAAAAAAAAAAASrB0qGpkdxkfXVW25ebtmZ7G5Xrw1rWp2I1E6iqStM8dL2p68XyUscj3dbnuajnOXtVVVVVetVVS4yT7d2c546T2VQAQ0AAAAAAAAAAAAAAAAAAAAAAAASvoNWfW8MofVsbl/8Annwj8Nnrzww6y9BtQezan3TjNcfM3yz1DeL5Hy0iovLYdGsir68ws/BV7sYdZeg2oPZtT7pxde6J5M6N8xz8rYAIaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImsvQbUHs2p904tkTWXoNqD2bU+6cWwAAAAACVZPNeMaPn4PXS9P628xPy6sb3Z79nPDOEqkqi8zqK607eLJGQVaqvPbcjo1T1YhZ+Kr3Yql2ma9Fnlu6/YACFgAAAAAAAAAAErU3HS91YnF8lLJGxvW57mq1rU7VVVRETrVUQqkq/dOmo6dvGWaup923t2JGyu/kyN6/hjmqIXZ54Ra5JVQAQsAAAAAAAAAAAAAAAAAAAAAAAAJV7814urOfg9dF0PrbzMHPqxvdrv2ccM5SqStSdHTtbUJ8+lZ4WxOpXxKkjUXuVWJnuzyLs88Qi1yTKqACFgAAAAAAAAAAAAASqbpaouT28WNpaaNXJyR6OmcrfWiPYuOxyL1oVSVaOlXXqRvGN9cmw5OTtmGJjsL14c1zV7FaqdRdO6rp3hFeanr2lVABCwAAAAAAAAAAAAAAAAAAAAAAAAlWXzUt0pG/R09c/YVea7xrZnZ/ilcidyJ61qkqi8zqK607eLJGQVaqvPbcjo1T1YhZ+Kr3YunLVr1RVmp16KoAIWAAAAAAAAAAAAAJWp/RO8/uM/+hSqSr/0qGmjbxkfXUuw1ObtmZj3YTrw1rnL2I1V6iqXOSOs9kRnnpHcABCwAAAAAAAAAAAAAAAAAAAAAAAEq++aioatv0lPXQ7CLyXeO3Ls/wAMrlTvRPUuHWXoNqD2bU+6cZtS9HTVxmT6SngdURL9WSNNti9+HNRcLwXHEw6y9BtQezan3Ti5yR79kRnn27rYAIWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiay9BtQezan3Ti2RNZeg2oPZtT7pxbAAAAAAJTvM6sj2ePhdC7eZ6ty9uzj179+fUnLjmqSrl5q8WWZnCR88lO5e2N0T3qn96KNc8+j3rmqXXuieTOjfVHPtAACGgAAAAAAAAAABKuPnr5Z6dvB8b5atVXlsNjWNU9eZmfgi92apKd57Vkezw8EoXbzPXvnt2cercPz6058cXRvmeUs7TdEc4+1UAENAAAAAAAAAAAAAAAAAAAAAAAAAxVVNDWUk1LUM24ZmOjkblUy1UwqZTjyUygRN2MExfhKfYqmas09baqoftzTUsUkjsImXKxFVcJw5qUCVp3o2dsKfR0889PEn1Y45XsYnfhrUTK8VxxKpdpF1cos5voiZ4AAIWAAAAAAAAAAAStO9KztmT6OonnqIl+tHJK97F7stci4XimeJu11ZHb7fU1sqOdHTxOlejEyqo1FVcd/AxWejkt9koKKVWukp6aOJ6sXKKrWoi47uBcZJ6s5zx0/TdABDQAAAAAAAAAAAAAAAAAAAAAAAAJUnmtWU+xw8IoZd7+1u3x7HqxvZOXPa45wmKpKunRutke3g91U+NXJzViwSuVvqVWMXHa1F6kLs9/tP0ztN0dY+1UAENAAAAAAAAAAAAABKuXnbxZYWcZGTyVDk7I2xPYq/3pY0xz6XcuKpKd57Vkezw8EoXbzPXvnt2cercPz6058cVS690RyZ0b6p59oAAQ0AAAAAAAAAAAAAAAAAAAAAAAAYqqmhrKSalqGbcMzHRyNyqZaqYVMpx5Kczdamas+Satqqh+3NNYpJJHYRMuWBVVcJw5qdWcfceHyY6iYnBkdPco2N6msa6VrWp2IiIiInUiIhcZJ6/tnOeOk9nYAAhoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiay9BtQezan3Ti2RNZeg2oPZtT7pxbAAAAAAJV/6NDTSN4SMrqXYcnNu1MxjsL1Za5zV7UcqdZVJuoopJ9M3aKKN0kj6OZrGMTKuVWKiIidam/FLHPEyWKRskb2o5j2LlHIvFFRetC5yR1nsiM89I7vsAELAAAAAAAAAAAJVB56/wB3qPm7rc0ezzzstWXa/Hf4x+znPHCVSVYvOxV1W76SorpttE5Ju3bluP4Ymqveq+pLpwpmdawRVjVTGtYqoAIWAAAAAAAAAAAAAAAAAAAAAAAAAACVaOjXXqNvCNlcmw1OTdqGJ7sJ1Zc5zl7Vcq9ZVJUPQ1ZWbXR3tDBu88NvZfNtY7cbbM9m0nahVLtN/tH0iz3e8/YACFgAAAAAAAAAAlak6dgqafl4XsUe19TfOSLa78becdeMZTmVSVevOy2ukd9HUVzNtU5pu2umbj+KJqL3KvrSqXOSI66/CKca5npr8gAIWAAAAAAAAAAAAAAAAAAAAAAAAErUPC1NevBkdVTSPd1NY2eNznL2IiIqqvUiKpVJ99ppqzT1ypadm3NNSyxxtyiZcrFREyvDmpdnN1cTPFFpF9ExHBQBipamGspIaqnftwzMbJG7CplqplFwvHkplImLlxN+MAAAAAAAAAAAAACVQeev93qPm7rc0ezzzstWXa/Hf4x+znPHCVSVZPO+Mazl4RXS9D6u7xBz687ra7trHHGVql2ma5Fnlv6/YACFgAAAAAAAAAAAAAAAAAAAAAAABx9+6OnNdsdwe6nlkRq81YtIxqO9SqxyZ7WqnUp2Bx+rvNUWqNvh4Rp+TdftbtJtv1Y3sfPntcM4XF0bquneEV76evaXYAAhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARp7BLPeUuKX67RMR7H+BxyRpAuzjo4VirhccePWvIDl6WluOtbrfalb9crbS0FY+go4qGXdptxom09/Dp5cvJepC/oe8VV70rT1FerVronyU9QrUwjnscrVX8cIv4nOWy/UOh7pqK33t0sCVFwkr6NyROclQyVEVWswnFyORUx3m7pipi0foGO4X/bo1qah9RKxWOc6N0siq1qoiZzhUz2ARtWXShk1/PR3TUt1tNFS0EWzHb6iRiySuc5VVWsRc4bjjjsO00lHQMsbZLbequ70s0iyNqaupWd6cETZyvFETHLqVVJtbqm0ae1RWsvNvZbXSxsWC5JEr0rG44tVzW5RWrw2VVTHoGnest+ukVNJS2+416zUkUjFYqt2URZNleSOXiBY1l6Dag9m1PunFsiay9BtQezan3Th5G6W+7dn/wMX/EC2D4hhipoI4IImRQxtRjI2NRrWNRMIiInJETqPsAAABK010dNW6FfpKeBtPKn1ZI02Hp34c1UynBccCqSrF5qKupHfSU9dNtqnJd47fNx/DK1F70X1rcZJ9u7Oc8e/ZVABDQAAAAAAAAAAAlaa6WmrdMv0lRA2olX60kibb17sucq4TgmeB96hlkh05cnQyOZOtM9sKsXDt4rVRiNxx2lcqImOOVTBvxRRwRMiijbHGxqNYxiYRqJwRETqQvdR1n6/rPfX0j7/j7ABDQAAAAAAAAAAAAAAAAAAAAAAAAAAEqr81qW1zP4RvgqKdq9sjljeif3YpFzy6PemapKvXmpbXVu+jp65m2ic13jXQtx/FK1V7kX1LVLqyxr1Z05qtegACGgAAAAAAAAAAJVX53UtrhfxjZBUVDU7JGrGxF/uyyJjl0u5MVSVD09WVm10t1QwbvPHY2nzbWOzOwzPbsp2IVS6/SOXlnR6zz8dgAENAAAAAAAAAAAAAAAAAAAAAAAAAAAStN9HTtFTr8+lZ4I9epXxKsblTuVWLjuxyKpKsnmvGNHz8Hrpen9beYn5dWN7s9+znhnCVS7TPMs7LJEAAIaAAAAAAAAABN1FLJBpm7SxSOjkZRzOY9i4VqoxVRUXqU7TG1MQmqrZiZfGmulpq3TL9JUQNqJV+tJIm29e7LnKuE4JngVT4iijgiZFFG2ONjUaxjEwjUTgiInUh9nap2qpkop2aYjgAAlQAAAAAAAAAAAAAAAAAAAAAAAAcfr/wAzaKuodxZJabhSIic9t0W8RfViF34qnfjrZoYqmCSCeJksMjVY+N7Uc17VTCoqLzRU6jz75RNM2G2aKr7hSWS2wPp43Z3VJGxXbbHRpxRP7LntenexOXNLs81zO0y39Pt6IACGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunFsAAAAAAEqi8zqK607eLJGQVaqvPbcjo1T1YhZ+Kr3YqkqTzWrKfY4eEUMu9/a3b49j1Y3snLntcc4TF0escvKK8Lp5+O6qACFgAAAAAAAAAAlX7p01HTt4yzV1Pu29uxI2V38mRvX8Mc1RCqSrj56+WenbwfG+WrVV5bDY1jVPXmZn4IvdmqXVhTEa1gzpxqqn218gAIaAAAAAAAAAAAAAAAAAAAAAAAAAAAlak6Ona2oT59KzwtidSviVJGovcqsTPdnkVTFVU0NZSTUtQzbhmY6ORuVTLVTCplOPJTUsVTNWaettVUP25pqWKSR2ETLlYiquE4c1L30dJ+/4jdX1j6/qgACFgAAAAAAAAAAlWbp1N3qG8Ypq5d27t2I44nfyfG9PwzyVFKpK050rHDUJ8yqfLVsTrRksjpGoveiPTPfnmVS7TNMcOzOyyRPHH5AAQ0AAAAAAAAAAAAAAAAAAAAAAAAAABKovM6iutO3iyRkFWqrz23I6NU9WIWfiq92KpKm6GrKPZ6O9oZ95jht7L4dnPbjbfjs2l7VKpdfpPLwzs/WOfnuAAhoAAAAAAAAEq/8ASoaaNvGR9dS7DU5u2ZmPdhOvDWucvYjVXqKpKuPnr5Z6dvB8b5atVXlsNjWNU9eZmfgi92bs81/DsztMt3HD5wVQAQ0AAAAAAAAAAAAAAAAAAAAAAAAAAAIesqOCu0ZeYKlm3F4JI/ZyqcWtVzV4d6IpcImsvQbUHs2p904qmdmqJTVTtUzHFbABKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOLYAAAAAAJV183cbPUfNRKp0cknLDHxPRGqvYr0j4dbtnrwVSVqPo2OaoX5lK+KrenWrIpGyORO9UYuO/HIuzzRHHuztckzwx+MVUAENAAAAAAAAAAASm+e1ZJtcPBKFu7x1757trPq3DMetefDFUlWvpXW9vdxe2qZGjl5oxIInI31Ir3rjtcq9alUu03xHKEWe6Z5z9gAIWAAAAAAAAAAAAAAAAAAAAAAAAAAASrB0aGpjdwkZXVW21ebdqZ725Tqy1zXJ2o5F6yqSrd5m+XindxfI+KrRU5bDo0jRPXmF/4Knfi6caZjWsWdWFUT7d+yqACGgAAAAAAAAaV4rJLfZK+tiRrpKemklYj0yiq1qqme7gbpK1F0rO6Ffo6ieCnlT60ckrGPTuy1yplOKZ4F2cX1xEotJmKJmODdoaOO32+moolc6OnibExXrlVRqIiZ7+BsAEzN83yqIiIugABx0AAAAAAAAAAAAAAAAAAAAAAAAAAEq89CptFQ7hFDXJvHdm3HJE3+b5GJ+OeSKpVJWo+jY5qhfmUr4qt6dasikbI5E71Ri478ciqXONMTrWKKcK5jpOvgABCwAAAAAAAAlfT6s+r4HQ+vb3z/APLHg/47XVjjVJVt87eL1M/jIyeOnavZG2Jj0T+9LIuefS7kxdG6Z5Ir3xHPyqgAhYAAAAAAAAAAAAAAAAAAAAAAAAAABE1l6Dag9m1PunFsiay9BtQezan3TgLYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiay9BtQezan3Ti2RNZeg2oPZtT7pxbAAAAAABq3Oi8ZWmsod5u/CYHw7eM7O01Uzjr5m0DsTMTfDkxExdLVtlb4ytNHXbvd+EwMm2M52dpqLjPXzNolad6NnbCn0dPPPTxJ9WOOV7GJ34a1EyvFccSqdriIqmITZzM0RMgAJWAAAAAABq3Ot8W2msrt3vPBoHzbGcbWy1Vxnq5HYiZm6HJmIi+Wpp3pWdsyfR1E89REv1o5JXvYvdlrkXC8UzxKpq2yi8W2mjod5vPBoGQ7eMbWy1Ezjq5G0drmJqmYTZxMUREgAJWAAAAAAAAAAAAAAAAAAAAAAAAAAASneZ1ZHs8fC6F28z1bl7dnHr378+pOXHNUlXXzdxs9R81EqnRyScsMfE9Eaq9ivSPh1u2evBdG+7qztN0TzhVABDQAAAAAAAAJVy87eLLCzjIyeSocnZG2J7FX+9LGmOfS7lxVJX0+rPq+B0Pr298/wDyx4P+O11Y43RvmeUs7TdEc4/aqACGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA166jjuFvqaKVXNjqInRPVi4VEciouO/iYrPWSXCyUFbKjWyVFNHK9GJhEVzUVcd3E3SVp/oW6WnXorBVVEaR8t2xJXLG3HUmwrMJ9VW44YLjJLOcK46KoAIaAAAAAAAABK09xtTnpxZJVVMjHdTmOnkc1ydqKioqL1oqKbtdWR2+31NbKjnR08TpXoxMqqNRVXHfwMVno5LfZKCilVrpKemjierFyiq1qIuO7gXGSerOc8dP03QAQ0AAAAAAAAAAAAAAAAAAAAAAAAAAAImsvQbUHs2p904tkTWXoNqD2bU+6cBbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOLYAAAAAAAAEq2+avF6hfwkfPHUNTtjdExiL/eikTHPo96Zqkp3mdWR7PHwuhdvM9W5e3Zx69+/PqTlxzVLr3xPKP0iz3THOf2AAhYAAAAAErUXSs7oV+jqJ4KeVPrRySsY9O7LXKmU4pngVSVcfPXyz07eD43y1aqvLYbGsap68zM/BF7s3Z5onhj8M7TLMccPnBVABDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVqLo2d0y/R088FRKv1Y45WPevfhrVXCcVxwKpr11HHcLfU0UqubHUROierFwqI5FRcd/EqibqomU1xM0zENgGlZ6yS4WSgrZUa2Sopo5XoxMIiuairju4m6cmLpul2mYqi+AAHHQAAAAAJVt87eL1M/jIyeOnavZG2Jj0T+9LIuefS7kxVJWnelZ2zJ9HUTz1ES/Wjkle9i92WuRcLxTPEunCmZ9tfDOrGqI9+3dVABDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVbvM3y8U7uL5HxVaKnLYdGkaJ68wv/BU78VSU7zOrI9nj4XQu3mercvbs49e/fn1Jy45ujdMcvKK98Tz8KoAIWAAAAAAAAlaj6Vjmp1+ZVPipHr1oyWRsblTvRHrjvxzKpKuXnbxZYWcZGTyVDk7I2xPYq/3pY0xz6XcuKpdWFMR76+GdONUz7d+4ACGgAAAAAAAAAAAAAAAAAAAAAAAAAABE1l6Dag9m1PunFsiay9BtQezan3TgLYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiay9BtQezan3Ti2RNZeg2oPZtT7pxbAAAAAAAAAlXXzdxs9R81EqnRyScsMfE9Eaq9ivSPh1u2evBVJWpOhYKmo5+CbFZs/X3Lkl2e7OxjPVnOF5FUurGmJ1rFnThXMe/bsAAhoAAAAABKb57Vkm1w8EoW7vHXvnu2s+rcMx6158MVSVaPPVl2q/nMkqt3FIvPYjY1it7URJEl4dqqqc8rdG6ZRXjMRrV9yqACFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJVg81R1FIvB9LVTR7vqjYr1fG1OrCRvjwickwnDGEqkqg8zf7vT/O3u5rNrljaasWz+G4zn9rGOGVql2ma/j3RZ5buGHwAAhYAAAAA1bnW+LbTWV273ng0D5tjONrZaq4z1chbKLxbaaOh3m88GgZDt4xtbLUTOOrkal/87R09InF9VVQx7vqkYj0fI1erCxskyi80ynHOFqlzhRHPX7RGNc8tfoABCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJV38zWWmr+ayOq3csic9iRjmI3tVFkWLh2oiryylUlak6Ona2oT59KzwtidSviVJGovcqsTPdnkXZ5ojj3Ra5Jnhj8KoAIWAAAAAAAAlfT6s+r4HQ+vb3z/8seD/AI7XVjjVJVo89WXar+cySq3cUi89iNjWK3tREkSXh2qqpzytUu033cNfaLPdfx19AAIWAAAAAAAAAAAAAAAAAAAAAAAAAAARNZeg2oPZtT7pxbImsvQbUHs2p904C2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImsvQbUHs2p904tkTWXoNqD2bU+6cWwAAAAAAAAPiWKOeJ8UsbZI3tVr2PTKOReCoqdaGhp+WSXT9Dv5HPqI4khnc9crvWdCRFXrXaa5M9fPiUiVZfNS3Skb9HT1z9hV5rvGtmdn+KVyJ3InrW4xomGc4VxKqACGgAAAAAErTfS07RVC/PqmeFvTqR8qrI5E7kV647scxqTpadradPn1TPBGL1I+VUjaq9yK9M92eZVL3UdZ+v6z319I+/4AAhoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlVPmNS0Ey9COoglp3Kn9uRFa9iL24a2ZUVeCZX63GqSr75qKhq2/SU9dDsIvJd47cuz/DK5U70T1LVLqxpiWdOFVUAAIaAAAAACVW+e1Faqd3BkbJ6tFTnttRsaJ6sTP/ABRO/NUlU3n9S18ydOOngip2qv8AYkVXPeidmWuhVVTguE+rwql1+kcvLOj1nn47AAIaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfEsUc8T4pY2yRvarXsemUci8FRU60PsATdPyyS6fod/I59RHEkM7nrld6zoSIq9a7TXJnr58SkSrL5qW6Ujfo6eufsKvNd41szs/xSuRO5E9a1S7TNKLPJAACFgAAAE3UEskWn67cSOZUSRLDA5i4Xev6EaIvUu05qZ6ufA7TG1MQmqrZiZfGm+nYKao5eF7dZs/U3zll2e/G3jPXjOE5FU+Ioo4ImRRRtjjY1GsYxMI1E4IiJ1IfZ2qdqqZKKdmmI4AAJUAAAAAAAAAAAAAAAAAAAAAAAAAAARNZeg2oPZtT7pxbImsvQbUHs2p904C2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImsvQbUHs2p904tkTWXoNqD2bU+6cWwAAAAAAAABKb5nVkm1x8LoW7vHVuXu2s+vfsx6l5cM1SVdf6PX2uuTotZOtPM/niOVMImO+VIeKcU7kyXRvmOLO0wiJ4a+lUAENAAAAABKu/nqy00nzmSVW8ljTnsRsc9HdqIkiRce1UReeFqkpvntWSbXDwShbu8de+e7az6twzHrXnwxVLrwiIZ0YzM61feAAhoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0rxRyXCyV9FErWyVFNJExXrhEVzVRM93Ey0NZHcLfTVsSObHURNlYj0wqI5EVM9/E2CVp/zVBJQrwdQzyU6M+pGi5iTPX5p0fHivHjxyXGNHTX6ZzhX11+1UAENAAAADVudb4ttNZXbveeDQPm2M42tlqrjPVyOxEzN0OTMRF8tSwedo6irXi+qqppN51SMR6sjcnVhY2R4VOaYXjnK1TVtlF4ttNHQ7zeeDQMh28Y2tlqJnHVyNo7XMTVMwmziYpiJAASsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKb5nVkm1x8LoW7vHVuXu2s+vfsx6l5cM1SVd/M1lpq/msjqt3LInPYkY5iN7VRZFi4dqIq8spVLrxiJZ0YTMa1feAAhoAAASrx5+otlDzSaqbJIjfnNZEiyI7uTbbG1V/bxwVUKpK+n1Z9XwOh9e3vn/5Y8H/AB2urHG7Pffw19s7TGLuOp/CqACGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOAtgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunFsAAAAAAAAATdQRSS6frtxG59RHEs0DWJld6zpxqida7TWrjr5cSkDtM7MxKaqdqJh8RSxzxMlikbJG9qOY9i5RyLxRUXrQ+yVp/zNs8Xrwfb3rSY69huN2qryVVjWNy463Ly5JVO1RdVMFFW1TEgAJUAGrc63xbaayu3e88GgfNsZxtbLVXGerkdiJmbocmYiL5alk874xrOXhFdL0Pq7vEHPrzutru2sccZWqatsovFtpo6HebzwaBkO3jG1stRM46uRtHa5iapuTRExTF+8ABKwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlQf0bUtXD82OsgZUMTntyMXYkXuw3cJjl2f2iqSrn/AEa5224f2GvdSSqvJrJcYXHPKyMib3I5c9qXRjMxxZ2mERPBVABDQAAAlXvzvi6j5eEV0XT+ru8z8uvO62e7azxxhapK+n1Z9XwOh9e3vn/5Y8H/AB2urHG7PCb+Go/LO0xi7jqfwqgAhoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACffKaarstXHTM2qpGbynTKJ55nSjXjw4Pa1ePDt4G3S1MNZSQ1VO/bhmY2SN2FTLVTKLhePJTKStP+aoJKFeDqGeSnRn1I0XMSZ6/NOj48V48eOS99HRnur69tSqgAhoAAASrJ53xjWcvCK6XofV3eIOfXndbXdtY44yu3c63xbaayu3e88GgfNsZxtbLVXGerkLZReLbTR0O83ng0DIdvGNrZaiZx1ci4womeOv0znGuI4a/baABDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunAWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABE1l6Dag9m1PunFsiay9BtQezan3Ti2AAAAAAAAAAAEqD+jalq4fmx1kDKhic9uRi7Ei92G7hMcuz+0VSVev6P4Hck4eCTpvVThmJ/QftO6mt2kkXPDzSZxjKVS68YirWGoRRhM06x83gAIWEq9effb6Bvz56qORVTirGRKkqux2KrGMz1LInci1SVTf0vUVbULxZRMbSRovBWvciSSL3oqLDz62Ly67owna4ItMY2eOvpVABCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACffKaarstXHTM2qpGbynTKJ55nSjXjw4Pa1ePDt4FAHaZ2ZiYcqjaiYlipamGspIaqnftwzMbJG7CplqplFwvHkplJVl/o/hltXh4JOu6ReGYn9Nmy3qa3aWNMcPNLjGMJVO1xdN0OUTfTEyAAlQSrH55ldXpwZW1TpGJzTYajYmuRetHJGj0XsenPmuW+VM1JZauSmfs1Ss3dOuEXzz+jGnHhxe5qceHbwNulpoaOkhpadmxDCxscbcquGomETK8eSFxhRfx1+kTjXdw1+2UAELAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJUX9E1LPCn0ddAlQ1E4+cjVrHqvZlroURE4dFeXXVJV6/o/gdyTh4JOm9VOGYn9B+07qa3aSRc8PNJnGMpdnjN3HX2ztMI2uGp/CqACGgAAJV6/pHgdtTj4XOm9ROOImdN+03ra7ZSNc8POpnOcLVJUX9L1LPMn0dDAlO1U4eckVr3ovbhrYVRU4dJefVVLqwiI1j4uZ0YzNWsPN4ACGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETWXoNqD2bU+6cWyJrL0G1B7NqfdOAtgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJrL0G1B7NqfdOLZE1l6Dag9m1PunFsAAAAAAAAAAAMVVTQ1lJNS1DNuGZjo5G5VMtVMKmU48lNSyVM1VaIHVD9upj2oJ34REdLG5WPcmOpXNVU4JwVOCcigSm/0HUTmJwhuLFkXPBEnjRrefWrmY4cMJCq4XKql040zT7616M6sKoq9ta9VUAENGKqqYaOkmqqh+xDCx0kjsKuGomVXCceSGpZqaanoNupZs1VQ91RM1VRytc9coxXJ87YTZYi9jExhMIYrr/TKujtP/wCXUbU0+f7UUatyzv2nPYioqYVivTsKpc4U9WcY138AAENAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKqf6JqKiqE4MrWOpJETirntRZI17kREm5db059VU1blReMKCWnSTdSLh0UmNrdyNVHMdjrw5EXC8FxhRba3xhQRVCx7qRctljztbuRqq17c9eHIqZTguMoXONMT7a16M6cKpjjj+9c20AfEsscET5ZZGxxsarnveuEaicVVV6kIaJtZ/Tb1R0TeMdLisqEXkvzmxNVOvLtp6LxwsScOKKVSbZ4pHNqK6ojc2eqlc5EemFbE1VbEmF4tTZRHK1eTnv4JlUSkXXvu4Io3bXEABCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADFVU0NZSTUtQzbhmY6ORuVTLVTCplOPJTKBE3YwTF+Ep9kqZqq0QOqH7dTHtQTvwiI6WNyse5MdSuaqpwTgqcE5FAlf1ff+yC5f5VDG/wA+lG3uRN12uKpdcY3x6os5wunfAYqqpho6SaqqH7EMLHSSOwq4aiZVcJx5IZSVd/6a+G1R9JZXskqccUZAi7S7SclR6t3eF5o5y4VGuQ5RF847na5ui+N7LZqaanoNupZs1VQ91RM1VRytc9coxXJ87YTZYi9jExhMIUADlU3ze7TGzF0AAOOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAARNZeg2oPZtT7pxbImsvQbUHs2p904C2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEa7XW70NW2Kg07UXGJWI5Zo6qGNEXK9HD3IvUi55cQNTV2tbTpC3yy1c8T6xI9uGjSTEkvHCdSqiZReOOpToYpN7CyTGNtqOx2ZOT+U6GJ/wAnt6ldExZGwJh6tTKdJOs6mk/7HB/9Nv8A6AStZeg2oPZtT7pxbNW50EV1tVZbp3PbDVwPge5iojka5qtVUyi8cKTvEdx+9d4/KpPgAWwRPEdx+9d4/KpPgDxHcfvXePyqT4AFsETxHcfvXePyqT4A8R3H713j8qk+ABbBE8R3H713j8qk+APEdx+9d4/KpPgAWwRPEdx+9d4/KpPgDxHcfvXePyqT4AFs1bhReHUjo2SbmdvSgnRMrDJhURyJ18+KclRVReCqhO8R3H713j8qk+APEdx+9d4/KpPgHYmYm+HJiJi6VG31vhtO5zo91NG90U0Wc7D2r+C4VMORVRMtc1cJky1NTDSU7p537MbcccKqqqrhERE4qqqqIiJxVVREIfktMtfHXP1FdHVMbdhJN1SNcrePRVUgRVbxzsrwzheaIJtMVE9fHWLqW8JLG3ZYmKZWN59JGrCqI7Cqm1jOFVM4Kup3/hF9cYflRtdNMxklZVs2K2r2Xysyi7lETCRIvWjePcrnOciJtYSgRPEdx+9d4/KpPgDxHcfvXePyqT4BNU3zeumNmLlsETxHcfvXePyqT4A8R3H713j8qk+AcdWwRPEdx+9d4/KpPgDxHcfvXePyqT4AFsETxHcfvXePyqT4A8R3H713j8qk+ABbBE8R3H713j8qk+APEdx+9d4/KpPgAWwRPEdx+9d4/KpPgDxHcfvXePyqT4AFsETxHcfvXePyqT4A8R3H713j8qk+ABbJen6yeuts0tQ/be2uq4kXCJ0GVEjGpw7GtRPwMHiO4/eu8flUnwDBSaXqqGF0VPqi8MY6WSVU3dIvTe9XuXjB1ucq/iB0QIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtgieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtgieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtkp3/yq5tcnChrXoxWpwbDOu0u12Ij1wnV08cFWRVTD4juP3rvH5VJ8A+JdPVs8T4pdT3aSN7Va9j4aNUci8FRU3HFCqZu3pqpv3b14lXD/wCZ1DbbF0oWva6ud1IxE2ki7FVy7OW4XoK7ONpudWLTU8FuWhi1Hd2Q7LmIrUp2uYi54NVIujjPDGMIiImMIflNpqrpKdsEGqLw2NueG7pFVVVcqqqsGVVVVVVV4qqqqlRdTjE3pnaqwmLodACJ4juP3rvH5VJ8AeI7j967x+VSfAM2i2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtgieI7j967x+VSfAHiO4/eu8flUnwALZLgrJ36ruFE5+aeKhpZWMwnB73zo5c8+KMb/L1mDxHcfvXePyqT4BgbpeqZXS1rdUXhKiWJkT37uk4sYrlamNxjgr3fz9QHRAieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtgieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtgieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtgieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAo3Ki8YUEtOkm6kXDopMbW7kaqOY7HXhyIuF4LjCihrfDGStfHuqiB+6njztI1+Edwd1oqOaqLw4KmURcok7xHcfvXePyqT4Bqy6SlnrYqyTUl38IiVMSsZSscrUXOw5zYUVWZ4q1VwvYXExddKKomJ2qXQVNTDSU7p537MbcccKqqqrhERE4qqqqIiJxVVREIDn1tHcrVNKu7nulxeydi4dswtp5nRx544xsNcuFVNtX4XDj7m0xUT18dYupbwksbdliYplY3n0kasKojsKqbWM4VUzg/J9L1VTNTSzaovDn0sqywru6RNl6sczPCDj0XuTj2iZiIugiJmb5dECJ4juP3rvH5VJ8AeI7j967x+VSfAIWtgieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtgieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtgieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtgieI7j967x+VSfAHiO4/eu8flUnwALYIniO4/eu8flUnwB4juP3rvH5VJ8AC2CJ4juP3rvH5VJ8AeI7j967x+VSfAAtkTWXoNqD2bU+6cPEdx+9d4/KpPgGCt0vVXChqKKq1ReJKeoidFKzd0ibTHJhUykGU4L1AdEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACffbPT6gslVaqt8rIKlmw90SojkTKLwVUVOrsN6NiRRMjbnDURqZ7j6AAHH1uuWM1na9P0dJOqz1EkVRPPTvYxEYxy4Yq42lyicUymPWb+qdQVNo8X0Ntpo6m63KZYaaOVytY3CbTnuVOOy1OziB0IOWsd/u3lFPp/UFPRx1yU6VUE1Grt1NHtbKph3FHIuOH/2vUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgqG864vstwqLQmno6CGtmpofCo5lkc1jlbtLsuxxA70GGl8I8Dg8MWJardt325zsbeOls544znGTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiqqmKjpJqqd2zDDG6R7uxqJlV/khwPlpqaCyw6pq7XQM09K5r3Qte9aqOFzkRsir81eaLhOpf5B6GD8a5HNRzVRUVMoqdZ+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADiJbzq+56lvFDYUsbKO3SRxbdcyVXvc6NHL8x2OCrjkB24NO1+MktsPjdaVa7jvVpEckXNcbO1x5Y59eTcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1rhXw2yglrKhJViiRFckUTpHLlccGtRVXmQdG6qk1Ul2mWldTw0tYtPCyRisk2UY1cvRV4LlV7OGAOnBxc+otSXW7XSn0zR219NbJNxLLXPeizzImXMZs8sZRMr1qXtNXyLUmn6S6xRLFvmqj4nLlY3tVWuavqVFArAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGp36mW8q2pp7S217b8PinkWfZ47PRViNzyzx7eZZAHHas9NdF/vdR7lT51QqU2v9GVsy7NOklVTK9eSSSRJsJ612VQ6ertVFXVtFWVMO3UUT3Pp37Tk2HOTZVcIuF4duRdLTQXqgfRXKljqaZ6oqsf2pyVFTii96AcxVKlV8r1uZCuVo7VK+dU/so96I1F7+Crg7Ml2bTtp0/HKy10bYN8qOlernPe9U5Zc5VVcesqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARYJNS+OHJVU9pS1I9+HxTSun2OOz0VZs55ZTPbjJxtNo7RdVpKqu9DW1UqIk00dykqHskgeiqq4Too3Ds8NlO/J6Yc5U6C0vV3B9dPZ4XzSP3j02nIx7u1zEXZVfWgGfRtbW3HRtorLhlauamY6RyphXcODl9aYX8S4fjWo1qNaiI1EwiJ1H6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABJ1TTS1ukbzSwNV001DNGxqc1crFREOOutxpZvkHjkje16TWyGmja3iqyKjWbKJ1qjsp+B6Oc/FofTUF1S5R2mFtS2TetXadsNf9ZGZ2UXvRALFBC+nt1LDIuXxxMY71oiIpsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgqXR+jb/AF16rFkqK2fwyRKnezPj8GlTgqNamzjknS45xzU705+6aI05ea91bX2uOSpeiI97XvZvET6yNVEd+OQNP5OayqrdIsWpqJKpsVRNDBUyLl00TXqjXKvXwTGe46wx09PDSU8dPTRMhhjajWRxtRrWonJERORkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHHaH/rbV/tl/wDoYdiadDaqK2y1ktJDu31kyzzrtOXbeqIirxXhwROCcAOW0JJHRz6spJ3tjmhvVRUSI9cKkciNc169ypnj3GT5MmuXSHhOFSOqrKieJFTHQdI7H/v+JUu+jdP32sSruNtZNUbKMV6PexXtTqdsqm0ncuSzBBFTQRwQRsihjajGMYmGtROCIidSAZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhq6qKipJqqdXJDCxXvVrFeqNRMrwRFVfwQnzans0FhhvclczxdNs7qVrXOV6uXCIjUTaVc9WM8+wrKqIiqvI8ZsTqBmvaaVzJ00pJXTeJleqbhKzDdpUT6qrt7HVnOOsD2VF2moqZwvHimD9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMFbRwXGhno6lrnQTsWORrXuYqtXmmWqip+CmjVabs9ZYo7LNQsW3RIxI4Wuc3Y2fmqjkVFRUxzzkqgD8a1GtRqZwiY4rlf5qfoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/9k=\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"metadata\": {\n      \"image/jpeg\": {\n       \"height\": \"480\",\n       \"width\": \"640\"\n      }\n     },\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%plot --format jpg \\n\",\n    \"x = -10:0.1:10;\\n\",\n    \"plot (x, sin (x));\\n\",\n    \"title (\\\"sin(x) for x = -10:0.1:10\\\");\\n\",\n    \"xlabel (\\\"x\\\");\\n\",\n    \"ylabel (\\\"sin (x)\\\");\\n\",\n    \"text (pi, 0.7, \\\"arbitrary text\\\");\\n\",\n    \"legend (\\\"sin (x)\\\");\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"id\": \"global-latex\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"A number is required for resolution, not a string\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%plot -f jpg -r 1a0\\n\",\n    \"plot([5 4])\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"id\": \"designing-greece\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"A number is required for width, not a string\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%plot -f jpg --width 1a0\\n\",\n    \"plot([5 4])\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"id\": \"configured-eating\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"A number is required for height, not a string\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%plot -f jpg -h 1a0\\n\",\n    \"plot([5 4])\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"id\": \"specified-omega\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"The figure is empty!\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"figure\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"id\": \"serious-exhibit\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Cannot embed the 'pdf' image format\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%plot -f pdf\\n\",\n    \"plot([5 4])\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Octave\",\n   \"language\": \"octave\",\n   \"name\": \"octave\"\n  },\n  \"language_info\": {\n   \"file_extension\": \".m\",\n   \"help_links\": [\n    {\n     \"text\": \"GNU Octave\",\n     \"url\": \"https://www.gnu.org/software/octave/support.html\"\n    },\n    {\n     \"text\": \"Octave Kernel\",\n     \"url\": \"https://github.com/Calysto/octave_kernel\"\n    },\n    {\n     \"text\": \"MetaKernel Magics\",\n     \"url\": \"https://metakernel.readthedocs.io/en/latest/source/README.html\"\n    }\n   ],\n   \"mimetype\": \"text/x-octave\",\n   \"name\": \"octave\",\n   \"version\": \"6.3.0\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 5\n}\n"
  },
  {
    "path": "test/leftdiv.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## There are many corner cases for left division operator\n%!assert (0 \\ 1, Inf)\n%!assert (0 \\ single (1), single (Inf))\n## FIXME: Should return Inf, but not coded correctly yet.\n%#!assert (0 \\ i, Inf)\n%#!assert (0 \\ single (i), single (Inf))\n\n################################################################################\n## Series of tests for memory leaks in function\n## sparse_qr<SPARSE_T>min2norm_solve<RHS_T, RET_T> (A, b)\n## in sparse-qr.cc.\n################################################################################\n%!testif HAVE_SPQR, HAVE_CHOLMOD, HAVE_CXSPARSE\n%! # <RHS=real full>, <RET=Matrix>, (real sparse, real full)\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);\n%! x0 = mldivide (A, ones (m,1));\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD, HAVE_CXSPARSE\n%! # <RHS=real sparse>, <RET=SparseMatrix>, (real sparse, real sparse)\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);\n%! b = sparse (ones (m,1));\n%! x0 = mldivide (A, b);\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD, HAVE_CXSPARSE\n%! # <RHS=complex full>, <RET=ComplexMatrix>, (real sparse, complex full)\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);\n%! b = ones (m,1) + i;\n%! x0 = mldivide (A, b);\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD, HAVE_CXSPARSE\n%! # <RHS=complex sparse>, <RET=SparseComplexMatrix>, (real sparse, complex sparse)\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);\n%! b = sparse (ones (m, 1) + i);\n%! x0 = A \\ b;\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD, HAVE_CXSPARSE\n%! # <RHS=complex sparse>, <RET=SparseComplexMatrix>, (real sparse, complex sparse)\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);\n%! b = sparse (ones (m, 1) + i);\n%! x0 = A \\ b;\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD, HAVE_CXSPARSE\n%! # <RHS=complex full>, <RET=ComplexMatrix>, (complex sparse, complex full)\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1) + i, -ones(mn,1)],[-1,0,1], m, n);\n%! b = ones (m, 1) + i;\n%! x0 = A \\ b;\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD, HAVE_CXSPARSE\n%! # <RHS=real full>, <RET=ComplexMatrix>, (complex sparse, real full)\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1) + i, -ones(mn,1)],[-1,0,1], m, n);\n%! b = ones (m, 1);\n%! x0 = A \\ b;\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD, HAVE_CXSPARSE\n%! # <RHS=complex sparse>, <RET=SparseComplexMatrix>, (complex sparse, complex sparse)\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1) + i, -ones(mn,1)],[-1,0,1], m, n);\n%! b = sparse (ones (m, 1) + i);\n%! x0 = A \\ b;\n\n%!testif HAVE_SPQR, HAVE_CHOLMOD, HAVE_CXSPARSE\n%! # <RHS=real sparse>, <RET=SparseComplexMatrix>, (complex sparse, real sparse)\n%! m = 11; n = 10; mn = max (m ,n);\n%! A = spdiags ([ones(mn,1), 10*ones(mn,1) + i, -ones(mn,1)],[-1,0,1], m, n);\n%! b = sparse (ones (m, 1));\n\n%!warning <matrix singular to machine precision>\n%! warning ('on', 'Octave:singular-matrix', 'local');\n%! assert ([Inf, 0; 0, 0] \\ [1; 1], zeros (2,1));\n%!warning <matrix singular to machine precision>\n%! warning ('on', 'Octave:singular-matrix', 'local');\n%! assert ([Inf, 0; 0, 0] \\ single ([1; 1]), zeros (2,1, \"single\"));\n%!warning <matrix singular to machine precision>\n%! warning ('on', 'Octave:singular-matrix', 'local');\n%! assert ([Inf, 0; 0, 0] \\ [i; 1], zeros (2,1));\n%!warning <matrix singular to machine precision>\n%! warning ('on', 'Octave:singular-matrix', 'local');\n%! assert ([Inf, 0; 0, 0] \\ single ([i; 1]), zeros (2,1, \"single\"));\n"
  },
  {
    "path": "test/line-continue.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!shared x, a, b\n%! x = [1,2];\n%! a = 1;\n%! b = 2;\n\n%!test\n%! y = [a... # comments here ok\n%! b];\n%! assert (y, x);\n\n## String continuation using '\\'\n%!assert ([\"abc\\\n%! def\"], \"abc def\")\n\n%!test\n%!assert (1 == 1\n%! && 2 == 2\n%! || 3 == 5);\n\n%!test\n%! x = [1, ...\n%!\n%! ...\n%!\n%! 2];\n%! y = [1;2];\n%! assert (y, x);\n\n%!test\n%! x = [1 ,...\n%! 2];\n%! y = [1,2];\n%! assert (y, x);\n\n%!test\n%! x = [ 1 , ...\n%! 2];\n%! y = [1,2];\n%! assert  (y, x);\n\n%!test\n%! x = [ 1 , ...anything after the ... is ignored\n%! 2];\n%! y = [1,2];\n%! assert  (y, x);\n"
  },
  {
    "path": "test/load-path/in-load-path/load_path_fcn.m",
    "content": "function out = load_path_fcn ()\nout = \"in-load-path\";\nendfunction"
  },
  {
    "path": "test/load-path/module.mk",
    "content": "load_path_TEST_FILES = \\\n    %reldir%/refresh-load-path.tst \\\n    %reldir%/in-load-path/load_path_fcn.m \\\n    %reldir%/namespace-builtin/+namespace_test/quad.m \\\n    %reldir%/namespace-corelib/+namespace_test/plot.m \\\n    %reldir%/not-in-load-path/load_path_fcn.m \\\n    %reldir%/shadowed-builtin/quad.m \\\n    %reldir%/shadowed-corelib/plot.m\n\nTEST_FILES += $(load_path_TEST_FILES)\n"
  },
  {
    "path": "test/load-path/namespace-builtin/+namespace_test/quad.m",
    "content": "## function which has the same name as a builtin function but that resides\n## inside a +namespace folder\nfunction quad ()\nendfunction"
  },
  {
    "path": "test/load-path/namespace-corelib/+namespace_test/plot.m",
    "content": "## function which has the same name as a function in Octave's core library but\n## that resides inside a +namespace folder\nfunction plot ()\nendfunction"
  },
  {
    "path": "test/load-path/not-in-load-path/load_path_fcn.m",
    "content": "function out = load_path_fcn ()\nout = \"not-in-load-path\";\nendfunction\n"
  },
  {
    "path": "test/load-path/refresh-load-path.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2024-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test <*65406>\n%! path_orig = path ();\n%! pwd_orig = pwd ();\n%! unwind_protect\n%!   addpath (fullfile (pwd_orig, \"in-load-path\"));\n%!   assert (load_path_fcn (), \"in-load-path\");\n%!\n%!   cd (\"not-in-load-path\");\n%!   assert (load_path_fcn (), \"not-in-load-path\");\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%!   cd (pwd_orig);\n%! end_unwind_protect\n\n%!warning <shadows a built-in function>\n%! path_orig = path ();\n%! unwind_protect\n%!   addpath (fullfile (pwd (), \"shadowed-builtin\"));\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%! end_unwind_protect\n\n%!warning <shadows a core library function>\n%! path_orig = path ();\n%! orig_sys_path = __pathorig__ ();\n%! unwind_protect\n%!   ## Temporarily override sys_path so this test works even before Octave\n%!   ## has been installed and __pathorig__ is empty by default.\n%!    __pathorig__ (path_orig);\n%!   addpath (fullfile (pwd (), \"shadowed-corelib\"));\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%!   __pathorig__ (orig_sys_path);\n%! end_unwind_protect\n\n## Test that no shadowing warning is emitted if a function with the same name\n## as a builtin function is added inside a (different) +namespace.\n%!test <*46849>\n%! path_orig = path ();\n%! lastwarn (\"\");\n%! unwind_protect\n%!   addpath (fullfile (pwd (), \"namespace-builtin\"));\n%!   assert (lastwarn (), \"\");\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%! end_unwind_protect\n\n## Test that no shadowing warning is emitted if a function with the same name\n## as a function from the core library is added inside a (different) +namespace.\n%!test <*46849>\n%! path_orig = path ();\n%! lastwarn (\"\");\n%! unwind_protect\n%!   addpath (fullfile (pwd (), \"namespace-corelib\"));\n%!   assert (lastwarn (), \"\");\n%! unwind_protect_cleanup\n%!   path (path_orig);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/load-path/shadowed-builtin/quad.m",
    "content": "## function which shadows a built-in function with the same name\nfunction var ()\nendfunction"
  },
  {
    "path": "test/load-path/shadowed-corelib/plot.m",
    "content": "## function which shadows a function with the same name in Octave's core library\nfunction plot ()\nendfunction"
  },
  {
    "path": "test/local-functions/local-functions.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n################################################################################\n## This file actually executes the tests on functions with local functions.\n##\n## It relies on the function files defined in the local-functions/ directory.\n################################################################################\n\n%!assert (local_function_eval (), 1)\n"
  },
  {
    "path": "test/local-functions/local_function_eval.m",
    "content": "function status = local_function_eval ()\n  eval (\"y = 5;\");\n  status = local_fcn (\"y = 6;\");\nendfunction\n\nfunction status = local_fcn (expr)\n  eval (expr);\n  status = exist (\"y\", \"var\");\nendfunction\n"
  },
  {
    "path": "test/local-functions/module.mk",
    "content": "local_functions_TEST_FILES = \\\n  %reldir%/local-functions.tst \\\n  %reldir%/local_function_eval.m\n\nTEST_FILES += $(local_functions_TEST_FILES)\n"
  },
  {
    "path": "test/logical-index.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! a = [];\n%! fail (\"a(0);\");\n\n%!shared a\n%! a = 2;\n%!assert (a(1), 2)\n%!error id=Octave:index-out-of-bounds a(logical ([1,1]))\n\n%!shared a\n%! a = [9,8,7,6];\n%!assert (isempty (a(logical ([0,0,0,0]))))\n%!assert (a(logical ([1,1,1,1])), [9,8,7,6])\n%!assert (a(logical ([0,1,1,0])), [8,7])\n%!assert (a(logical ([1,1])), [9,8])\n\n%!shared a\n%! a = [9,8;7,6];\n%!assert (isempty (a(logical ([0,0,0,0]))))\n%!assert (a(logical ([1,1,1,1])), [9,7,8,6])\n%!assert (a(logical ([0,1,1,0])), [7,8])\n%!assert (a(logical (0:1),logical (0:1)), 6)\n%!assert (a(logical (0:1),2:-1:1), [6,7])\n%!assert (a(logical (0:1),logical ([0,1])), 6)\n%!assert (a(logical (0:1),[2,1]), [6,7])\n%!assert (a(logical (0:1),:), [7,6])\n%!assert (a(logical (0:1),1), 7)\n%!assert (a(logical (0:1),logical ([1,1])), [7,6])\n%!assert (a(2:-1:1,logical (0:1)), [6;8])\n%!assert (a(2:-1:1,logical ([0,1])), [6;8])\n%!assert (a(2:-1:1,logical ([1,1])), [7,6;9,8])\n%!assert (a(logical ([0,1]),logical (0:1)), 6)\n%!assert (a(logical ([0,1]),2:-1:1), [6,7])\n%!assert (a(logical ([0,1]),logical ([0,1])), 6)\n%!assert (a(logical ([0,1]),[2,1]), [6,7])\n%!assert (a(logical ([0,1]),:), [7,6])\n%!assert (a(logical ([0,1]),1), 7)\n%!assert (a(logical ([0,1]),logical ([1,1])), [7,6])\n%!assert (a([2,1],logical (0:1)), [6;8])\n%!assert (a([2,1],logical ([0,1])), [6;8])\n%!assert (a([2,1],logical ([1,1])), [7,6;9,8])\n%!assert (a(:,logical (0:1)), [8;6])\n%!assert (a(:,logical ([0,1])), [8;6])\n%!assert (a(:,logical ([1,1])), [9,8;7,6])\n%!assert (a(1,logical (0:1)), 8)\n%!assert (a(1,logical ([0,1])), 8)\n%!assert (a(1,logical ([1,1])), [9,8])\n%!assert (a(logical ([1,1]),logical (0:1)), [8;6])\n%!assert (a(logical ([1,1]),2:-1:1), [8,9;6,7])\n%!assert (a(logical ([1,1]),logical ([0,1])), [8;6])\n%!assert (a(logical ([1,1]),[2,1]), [8,9;6,7])\n%!assert (a(logical ([1,1]),:), [9,8;7,6])\n%!assert (a(logical ([1,1]),1), [9;7])\n%!assert (a(logical ([1,1]),logical ([1,1])), [9,8;7,6])\n"
  },
  {
    "path": "test/mex/bug-51725.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!assert (bug_51725 (), [])\n## Note: ';' is required to suppress output\n%!error <element number 2 undefined in return list> [x,y,z] = bug_51725 ();\n"
  },
  {
    "path": "test/mex/bug-54096.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! s = bug_54096 ();\n%! assert (s, struct (\"field\", []));\n%! assert (s.field, []);\n"
  },
  {
    "path": "test/mex/bug_51725.c",
    "content": "#include \"mex.h\"\n\nvoid mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])\n{\n  if (nlhs > 0)\n    plhs[0] = mxCreateDoubleMatrix (0, 0, mxREAL);\n\n  if (nlhs > 2)\n    plhs[2] = mxCreateDoubleMatrix (0, 0, mxREAL);\n}\n"
  },
  {
    "path": "test/mex/bug_54096.c",
    "content": "#include \"mex.h\"\n\nstatic const char* field_names[] = {\"field\"};\n\nvoid mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])\n{\n  mxArray *tmp_val;\n\n  plhs[0] = mxCreateStructMatrix (1, 1, 1, field_names);\n\n  mxSetFieldByNumber (plhs[0], 0, 0, NULL);\n\n  tmp_val = mxGetFieldByNumber (plhs[0], 0, 0);\n\n  if (tmp_val)\n    mexErrMsgTxt (\"struct elements set to NULL should be NULL internally\");\n\n  /* But in the interpreter, they should appear as [].  */\n}\n"
  },
  {
    "path": "test/mex/mexnumtst.c",
    "content": "#include \"mex.h\"\n\n// To be called with\n//\n//   single array\n//   complex single array\n//   double array\n//   complex double array\n//\n// Returns copies of the input arrays to test the mxArray ->\n// octave_value conversion.\n\n#define MAKE_INTERLEAVED_COPY(TYPE, ID, CPLXTY, RHS, GET, LHS, SET)     \\\n  do                                                                    \\\n    {                                                                   \\\n      size_t i;                                                         \\\n      TYPE *data = GET (RHS);                                           \\\n      const mwSize *data_dims = mxGetDimensions (RHS);                  \\\n      mwSize data_ndims = mxGetNumberOfDimensions (RHS);                \\\n      size_t numel = mxGetNumberOfElements (RHS);                       \\\n      TYPE *data_copy = mxMalloc (numel * sizeof (TYPE));               \\\n      for (i = 0; i < numel; i++)                                       \\\n        data_copy[i] = data[i];                                         \\\n      LHS = mxCreateNumericMatrix (0, 0, ID, CPLXTY);                   \\\n      SET (LHS, data_copy);                                             \\\n      mxSetDimensions (LHS, data_dims, data_ndims);                     \\\n    }                                                                   \\\n  while (0)\n\n#define MAKE_REAL_COPY(TYPE, ID, RHS, LHS)                      \\\n  do                                                            \\\n    {                                                           \\\n      size_t i;                                                 \\\n      TYPE *data = mxGetData (RHS);                             \\\n      const mwSize *data_dims = mxGetDimensions (RHS);          \\\n      mwSize data_ndims = mxGetNumberOfDimensions (RHS);        \\\n      size_t numel = mxGetNumberOfElements (RHS);               \\\n      TYPE *data_copy = mxMalloc (numel * sizeof (TYPE));       \\\n      for (i = 0; i < numel; i++)                               \\\n        data_copy[i] = data[i];                                 \\\n      LHS = mxCreateNumericMatrix (0, 0, ID, mxREAL);           \\\n      mxSetData (LHS, data_copy);                               \\\n      mxSetDimensions (LHS, data_dims, data_ndims);             \\\n    }                                                           \\\n  while (0)\n\n#define MAKE_CPLX_COPY(TYPE, ID, RHS, LHS)                      \\\n  do                                                            \\\n    {                                                           \\\n      size_t i;                                                 \\\n      TYPE *real_data = mxGetData (RHS);                        \\\n      TYPE *imag_data = mxGetImagData (RHS);                    \\\n      const mwSize *data_dims = mxGetDimensions (RHS);          \\\n      mwSize data_ndims = mxGetNumberOfDimensions (RHS);        \\\n      size_t numel = mxGetNumberOfElements (RHS);               \\\n      TYPE *real_data_copy = mxMalloc (numel * sizeof (TYPE));  \\\n      TYPE *imag_data_copy = mxMalloc (numel * sizeof (TYPE));  \\\n      for (i = 0; i < numel; i++)                               \\\n        {                                                       \\\n          real_data_copy[i] = real_data[i];                     \\\n          imag_data_copy[i] = imag_data[i];                     \\\n        }                                                       \\\n      LHS = mxCreateNumericMatrix (0, 0, ID, mxCOMPLEX);        \\\n      mxSetData (LHS, real_data_copy);                          \\\n      mxSetImagData (LHS, imag_data_copy);                      \\\n      mxSetDimensions (LHS, data_dims, data_ndims);             \\\n    }                                                           \\\n  while (0)\n\nvoid\nmexFunction (int nlhs, mxArray *plhs[],\n             int nrhs, const mxArray *prhs[])\n{\n  if (nrhs != 4 || nlhs != 4)\n    mexErrMsgTxt (\"invalid arguments\");\n\n#if MX_HAS_INTERLEAVED_COMPLEX\n\n  MAKE_INTERLEAVED_COPY (mxSingle, mxSINGLE_CLASS, mxREAL, prhs[0],\n                         mxGetSingles, plhs[0], mxSetSingles);\n\n  MAKE_INTERLEAVED_COPY (mxComplexSingle, mxSINGLE_CLASS, mxCOMPLEX, prhs[1],\n                         mxGetComplexSingles, plhs[1], mxSetComplexSingles);\n\n  MAKE_INTERLEAVED_COPY (mxDouble, mxDOUBLE_CLASS, mxREAL, prhs[2],\n                         mxGetDoubles, plhs[2], mxSetDoubles);\n\n  MAKE_INTERLEAVED_COPY (mxComplexDouble, mxDOUBLE_CLASS, mxCOMPLEX, prhs[3],\n                         mxGetComplexDoubles, plhs[3], mxSetComplexDoubles);\n\n#else\n\n  MAKE_REAL_COPY (mxSingle, mxSINGLE_CLASS, prhs[0], plhs[0]);\n\n  MAKE_CPLX_COPY (mxSingle, mxSINGLE_CLASS, prhs[1], plhs[1]);\n\n  MAKE_REAL_COPY (mxDouble, mxDOUBLE_CLASS, prhs[2], plhs[2]);\n\n  MAKE_CPLX_COPY (mxDouble, mxDOUBLE_CLASS, prhs[3], plhs[3]);\n\n#endif\n\n}\n"
  },
  {
    "path": "test/mex/mexnumtst.tst",
    "content": "%!test\n%! s = rand (3, 4, \"single\");\n%! sc = s + i * rand (3, 4, \"single\");\n%! d = rand (3, 4, \"double\");\n%! dc = d + i * rand (3, 4, \"double\");\n%!\n%! [sx, scx, dx, dcx] = mexnumtst (s, sc, d, dc);\n%! assert (s, sx);\n%! assert (sc, scx);\n%! assert (d, dx);\n%! assert (dc, dcx);\n"
  },
  {
    "path": "test/mex/module.mk",
    "content": "mex_TEST_FILES = \\\n  %reldir%/bug-54096.tst \\\n  %reldir%/bug-51725.tst \\\n  %reldir%/mexnumtst.tst \\\n  $(MEX_TEST_SRC)\n\nMEX_TEST_SRC = \\\n  %reldir%/bug_54096.c \\\n  %reldir%/bug_51725.c \\\n  %reldir%/mexnumtst.c\n\nMEX_TEST_FUNCTIONS = $(MEX_TEST_SRC:%.c=%.mex)\n\n## Since these definitions for MKOCTFILE and MKMEXFILE are only used\n## here, defining them in this file is probably OK.  If they are ever\n## used elsewhere, maybe then they could be moved to build-aux/module.mk\n## or the main Makefile.am file.  The MKOCTFILE variables are included\n## for completeness, in case we someday want to test building .oct\n## files as well.\n\nAM_V_mkmexfile = $(am__v_mkmexfile_@AM_V@)\nam__v_mkmexfile_ = $(am__v_mkmexfile_@AM_DEFAULT_V@)\nam__v_mkmexfile_0 = @echo \"  MKMEXFILE     \" $@;\nam__v_mkmexfile_1 =\n\nAM_VOPT_mkmexfile = $(am__vopt_mkmexfile_@AM_V@)\nam__vopt_mkmexfile_ = $(am__vopt_mkmexfile_@AM_DEFAULT_V@)\nam__vopt_mkmexfile_0 =\nam__vopt_mkmexfile_1 = -v\n\n## And probably many others...\nMKOCTFILECPPFLAGS = \\\n  -I$(top_builddir) \\\n  -I$(top_srcdir)/libinterp/corefcn \\\n  -I$(top_builddir)/libinterp/corefcn\nMKOCTFILELDFLAGS = \\\n  -L$(top_builddir)/libinterp/.libs \\\n  -L$(top_builddir)/liboctave/.libs\n\nMKOCTFILE = \\\n  OCT_LINK_DEPS=\"$(OCT_LINK_DEPS)\" \\\n  DL_LDFLAGS=\"$(DL_LDFLAGS)\" \\\n  $(top_builddir)/src/mkoctfile $(MKOCTFILECPPFLAGS) $(MKOCTFILELDFLAGS)\n\nMKMEXFILECPPFLAGS = \\\n  -I$(top_builddir) \\\n  -I$(top_srcdir)/libmex \\\n  -I$(top_srcdir)/libinterp/corefcn \\\n  -I$(top_builddir)/libinterp/corefcn\nMKMEXFILELDFLAGS = \\\n  -L$(top_builddir)/libmex/.libs\n\nMKMEXFILE = \\\n  OCT_LINK_DEPS=\"\" \\\n  DL_LDFLAGS=\"$(DL_LDFLAGS)\" \\\n  $(top_builddir)/src/mkoctfile --mex $(MKMEXFILECPPFLAGS) $(MKMEXFILELDFLAGS)\n\n$(MEX_TEST_FUNCTIONS) : %.mex : %.c | %reldir%/$(octave_dirstamp)\n\t$(AM_V_mkmexfile)$(MKMEXFILE) $(AM_VOPT_mkmexfile) $< -o $@ || rm -f $@\n\nDIRSTAMP_FILES += %reldir%/$(octave_dirstamp)\n\n## Until we decide how to handle installing the executable MEX files,\n## don't install them or the associated test files.\nnoinst_TEST_FILES += $(mex_TEST_FILES)\n"
  },
  {
    "path": "test/mk-bc-overloads-tst.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nCLASSES=\"\n  double\n  single\n  char\n  logical\n  int8\n  int16\n  int32\n  int64\n  uint8\n  uint16\n  uint32\n  uint64\n  struct\n  cell\n  function_handle\n\"\n\nif [ $# -eq 2 ]; then\n  output_dir=\"$1\"\n  shift\n  case \"$1\" in\n    --list-files)\n      echo tbcover.m\n      echo bc-overloads.tst\n      for class in $CLASSES; do\n        echo @$class/tbcover.m\n      done\n      exit\n    ;;\n    --list-dirs)\n      for class in $CLASSES; do\n        echo @$class\n      done\n      exit\n    ;;\n    --list-classes)\n      echo $CLASSES\n      exit\n    ;;\n    *)\n      expected_results_file=\"$1\"\n    ;;\n  esac\nelse\n  echo \"usage: mk-bc-overload-tst.sh output_dir option\" 1>&2\n  exit 1\nfi\n\nfor class in $CLASSES; do\n  DIR=\"@$class\"\n  test -d $DIR || mkdir $DIR || { echo \"error: could not create $DIR\"; exit; }\n  cat > $DIR/tbcover.m << EOF\n% !!! DO NOT EDIT !!!\n% generated automatically by mk-bc-overload-tst.sh\nfunction s = tbcover (x, y)\n  s = '$class';\nEOF\ndone\n\ncat > $output_dir/tbcover.m << EOF\n% !!! DO NOT EDIT !!!\n% generated automatically by mk-bc-overload-tst.sh\nfunction s = tbcover (x, y)\n  s = 'none';\nEOF\n\nif test \"$1\" = \"overloads_only\" ; then\n  exit\nfi\n\ncat > $output_dir/bc-overloads.tst << EOF\n## !!! DO NOT EDIT !!!\n## THIS IS AN AUTOMATICALLY GENERATED FILE\n## modify mk-bc-overloads-tst.sh to generate the tests you need.\n\n%!shared ex\n%! ex.double = 1;\n%! ex.single = single (1);\n%! ex.logical = true;\n%! ex.char = 'char';\n%! ex.int8  = int8 (1);\n%! ex.int16 = int16 (1);\n%! ex.int32 = int32 (1);\n%! ex.int64 = int64 (1);\n%! ex.uint8  = uint8 (1);\n%! ex.uint16 = uint16 (1);\n%! ex.uint32 = uint32 (1);\n%! ex.uint64 = uint64 (1);\n%! ex.cell = {};\n%! ex.struct = struct ();\n%! ex.function_handle = @numel;\n\nEOF\n\ncat $expected_results_file | \\\nwhile read cl1 cl2 clr ; do\n  cat >> $output_dir/bc-overloads.tst << EOF\n%% Name call\n%!assert (tbcover (ex.$cl1, ex.$cl2), \"$clr\")\n%% Handle call\n%!assert ((@tbcover) (ex.$cl1, ex.$cl2), \"$clr\")\n\nEOF\ndone\n\ncat >> $output_dir/bc-overloads.tst << EOF\n%%test handles through cellfun\n%!test\n%! f = fieldnames (ex);\n%! n = numel (f);\n%! s = c1 = c2 = cell (n);\n%! for i = 1:n\n%!   for j = 1:n\n%!     c1{i,j} = ex.(f{i});\n%!     c2{i,j} = ex.(f{j});\n%!     s{i,j} = tbcover (ex.(f{i}), ex.(f{j}));\n%!   endfor\n%! endfor\n%! assert (cellfun (@tbcover, c1, c2, \"uniformoutput\", false), s);\nEOF\n"
  },
  {
    "path": "test/mk-conv-tst.sh",
    "content": "#!/bin/sh\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\ncat <<EOF\n## !!! DO NOT EDIT !!!\n## THIS IS AN AUTOMATICALLY GENERATED FILE\n## modify mk-conv-tst.sh to generate the tests you need.\n\n\n%!shared r,dq,sq,b,bm,dm,cdm,fdm,fcdm,pm,sm,sbm,scm,s,m,cs,cm,fs,fm,fcs,fcm,i8s,i16s,i32s,i64s,i8m,i16m,i32m,i64m,ui8s,ui16s,ui32s,ui64s,ui8m,ui16m,ui32m,ui64m\n%!test\n%! r = 1:5;\n%! dq = \"foo\";\n%! sq = 'bar';\n%! b = true;\n%! bm = rand (5) > 0.5;\n%! dm = eye (5);\n%! cdm = eye (5) * i;\n%! fdm = eye (5, \"single\");\n%! fcdm = eye (5, \"single\") * single (i);\n%! [~, ~, pm] = qr (rand (5));\n%! sm = sprand (5, 5, 0.1);\n%! sbm = sparse (rand (5) > 0.5);\n%! scm = sprand (5, 5, 0.1) * i;\n%! s = rand ();\n%! m = rand (5);\n%! cs = 13 * i;\n%! cm = rand (5) * i;\n%! fs = rand (\"single\");\n%! fm = rand (5, \"single\");\n%! fcs = rand (\"single\") * single (i);\n%! fcm = rand (5, \"single\") * single (i);\n%! i8s = int8 (rand () * 10);\n%! i16s = int16 (rand () * 10);\n%! i32s = int32 (rand () * 10);\n%! i64s = int64 (rand () * 10);\n%! i8m = int8 (rand (5) * 10);\n%! i16m = int16 (rand (5) * 10);\n%! i32m = int32 (rand (5) * 10);\n%! i64m = int64 (rand (5) * 10);\n%! ui8s = uint8 (rand () * 10);\n%! ui16s = uint16 (rand () * 10);\n%! ui32s = uint32 (rand () * 10);\n%! ui64s = uint64 (rand () * 10);\n%! ui8m = uint8 (rand (5) * 10);\n%! ui16m = uint16 (rand (5) * 10);\n%! ui32m = uint32 (rand (5) * 10);\n%! ui64m = uint64 (rand (5) * 10);\n%!\n%!test\n%! if (optimize_range ())\n%!   assert (typeinfo (r), \"double_range\");\n%! else\n%!   assert (typeinfo (r), \"matrix\");\n%! endif\n%!assert (typeinfo (dq), \"string\")\n%!assert (typeinfo (sq), \"sq_string\")\n%!assert (typeinfo (b), \"bool\")\n%!assert (typeinfo (bm), \"bool matrix\")\n%!assert (typeinfo (dm), \"diagonal matrix\")\n%!assert (typeinfo (cdm), \"complex diagonal matrix\")\n%!assert (typeinfo (fdm), \"float diagonal matrix\")\n%!assert (typeinfo (fcdm), \"float complex diagonal matrix\")\n%!assert (typeinfo (pm), \"permutation matrix\")\n%!assert (typeinfo (sm), \"sparse matrix\")\n%!assert (typeinfo (sbm), \"sparse bool matrix\")\n%!assert (typeinfo (scm), \"sparse complex matrix\")\n%!assert (typeinfo (s), \"scalar\")\n%!assert (typeinfo (m), \"matrix\")\n%!assert (typeinfo (cs), \"complex scalar\")\n%!assert (typeinfo (cm), \"complex matrix\")\n%!assert (typeinfo (fs), \"float scalar\")\n%!assert (typeinfo (fm), \"float matrix\")\n%!assert (typeinfo (fcs), \"float complex scalar\")\n%!assert (typeinfo (fcm), \"float complex matrix\")\n%!assert (typeinfo (i8s), \"int8 scalar\")\n%!assert (typeinfo (i16s), \"int16 scalar\")\n%!assert (typeinfo (i32s), \"int32 scalar\")\n%!assert (typeinfo (i64s), \"int64 scalar\")\n%!assert (typeinfo (i8m), \"int8 matrix\")\n%!assert (typeinfo (i16m), \"int16 matrix\")\n%!assert (typeinfo (i32m), \"int32 matrix\")\n%!assert (typeinfo (i64m), \"int64 matrix\")\n%!assert (typeinfo (ui8s), \"uint8 scalar\")\n%!assert (typeinfo (ui16s), \"uint16 scalar\")\n%!assert (typeinfo (ui32s), \"uint32 scalar\")\n%!assert (typeinfo (ui64s), \"uint64 scalar\")\n%!assert (typeinfo (ui8m), \"uint8 matrix\")\n%!assert (typeinfo (ui16m), \"uint16 matrix\")\n%!assert (typeinfo (ui32m), \"uint32 matrix\")\n%!assert (typeinfo (ui64m), \"uint64 matrix\")\n%!\n%!assert (class (r), \"double\")\n%!assert (class (dq), \"char\")\n%!assert (class (sq), \"char\")\n%!assert (class (b), \"logical\")\n%!assert (class (bm), \"logical\")\n%!assert (class (dm), \"double\")\n%!assert (class (cdm), \"double\")\n%!assert (class (fdm), \"single\")\n%!assert (class (fcdm), \"single\")\n%!assert (class (pm), \"double\")\n%!assert (class (sm), \"double\")\n%!assert (class (sbm), \"logical\")\n%!assert (class (scm), \"double\")\n%!assert (class (s), \"double\")\n%!assert (class (m), \"double\")\n%!assert (class (cs), \"double\")\n%!assert (class (cm), \"double\")\n%!assert (class (fs), \"single\")\n%!assert (class (fm), \"single\")\n%!assert (class (fcs), \"single\")\n%!assert (class (fcm), \"single\")\n%!assert (class (i8s), \"int8\")\n%!assert (class (i16s), \"int16\")\n%!assert (class (i32s), \"int32\")\n%!assert (class (i64s), \"int64\")\n%!assert (class (i8m), \"int8\")\n%!assert (class (i16m), \"int16\")\n%!assert (class (i32m), \"int32\")\n%!assert (class (i64m), \"int64\")\n%!assert (class (ui8s), \"uint8\")\n%!assert (class (ui16s), \"uint16\")\n%!assert (class (ui32s), \"uint32\")\n%!assert (class (ui64s), \"uint64\")\n%!assert (class (ui8m), \"uint8\")\n%!assert (class (ui16m), \"uint16\")\n%!assert (class (ui32m), \"uint32\")\n%!assert (class (ui64m), \"uint64\")\nEOF\n\n## There are no single or integer sparse matrices.\n\nsparse_vars=\"sm sbm scm\"\nsparse_conversions=\"double logical\"\n\nfor c in $sparse_conversions; do\n  echo \"\"\n  for v in $sparse_vars; do\n    echo \"%!assert (class ($c ($v)), \\\"$c\\\")\"\n  done\ndone\n\nchar_vars=\"dq sq\"\nbool_vars=\"b bm\"\nreal_vars=\"r s m fs fm dm fdm pm\"\ncomplex_vars=\"cs cm fcs fcm cdm fcdm\"\nsigned_int_vars=\"i8s i16s i32s i64s i8m i16m i32m i64m\"\nunsigned_int_vars=\"ui8s ui16s ui32s ui64s ui8m ui16m ui32m ui64m\"\nint_vars=\"$signed_int_vars $unsigned_int_vars\"\n\nbool_conversions=\"logical\"\nfloat_conversions=\"double single\"\nint_conversions=\"int8 int16 int32 int64 uint8 uint16 uint32 uint64\"\nall_conversions=\"$bool_conversions $float_conversions $int_conversions\"\n\n## Strings can't be converted to logical.\n\nfor v in $char_vars; do\n  echo \"\"\n  for c in $float_conversions $int_conversions; do\n    echo \"%!assert (class ($c ($v)), \\\"$c\\\")\"\n  done\ndone\n\n## Octave doesn't have complex integers.\n\nfor v in $complex_vars; do\n  echo \"\"\n  for c in $bool_conversions $float_conversions; do\n    echo \"%!assert (class ($c ($v)), \\\"$c\\\")\"\n  done\ndone\n\n## Logical and real-value numeric values should be convertible to any\n## double, single, logical or integer type.\n\nfor v in $bool_vars $real_vars $int_vars; do\n  echo \"\"\n  for c in $all_conversions; do\n    echo \"%!assert (class ($c ($v)), \\\"$c\\\")\"\n  done\ndone\n"
  },
  {
    "path": "test/mk-sparse-tst.sh",
    "content": "#! /bin/sh\n\n########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n# If any tests are known to be broken,\n# comment them out and tag them with \"# fails\".\n\n# ./mk-sparse-tst.sh preset\n#    creates sparse.tst with preset tests.\n#    Use \"test sparse.tst\" from octave to run the tests.\n#\n# ./mk-sparse-tst.sh random\n#    Creates sprandom.tst with randomly generated matrices.\n#    Use \"test sprandom.tst\" from octave to run the tests.\n\n# mk-sparse-tst.sh generates tests for real and complex sparse matrices.\n# Also, we want to run both fixed tests with known outputs (quick tests)\n# and longer tests with unknown outputs (thorough tests).  This requires\n# two sets of tests -- one which uses preset matrices and another which\n# uses randomly generated matrices.\n#\n# The tests are mostly identical for each case but the code is different,\n# so it is important that the tests be run on all cases.  Because our test\n# harness doesn't have support for looping or macros (it is only needed\n# for new data types), but sh does, we use sh to generate inline versions of\n# the tests for each case.\n#\n# Our 'macros' use shared variables as parameters.  This allows us to\n# for example define A complex and include all the unary ops tests,\n# then set A=real(A) and include all the unary ops tests.  Thus the\n# same tests work for real and complex.  For binary tests it is even\n# more complicated because we want full X sparse, sparse X full and\n# sparse X sparse tested.\n#\n# We use the following macros:\n#\n#    gen_section\n#        place a separator in the test file\n#    gen_function\n#        define the function definion\n#    helper gen_specific\n#        specific tests such as error handling and null input\n#    helper gen_eat_zeros\n#        make sure sparse-scalar ops which generate 0 work\n#    gen_specific_tests\n#        specific and eat zeros tests\n#    helper gen_ordering_tests\n#        ordered comparison operators for real valued tests\n#    helper gen_sparsesparse_ordering_tests\n#        ordered comparison operators for real valued sparse-sparse tests\n#    helper gen_elementop_tests\n#        element-wise matrix binary operators, including scalar-matrix ops.\n#        horizontal/vertical concatenation are here as well.\n#    helper gen_sparsesparse_elementop_tests\n#        element-wise matrix binary operators, for sparse-sparse ops.\n#        horizontal/vertical concatenation are here as well.\n#    helper gen_divop_tests\n#        left and right matrix division operators of rectangular matrices.\n#        Needs QR solvers\n#    helper gen_square_divop_tests\n#        left and right matrix division operators of square matrices.\n#    helper gen_matrixop_tests\n#        rectangular matrix binary operators: *\n#    helper gen_matrixdiag_tests\n#        Tests extract of diag and creation of diagonal matrices using\n#        diag and spdiags functions\n#    helper gen_matrixreshape_tests\n#        Test the reshape function on sparse matrices\n#    helper print_mapper_test\n#        sub-helper function of gen_mapper_tests to print individual tests\n#    helper gen_mapper_tests\n#        Tests all of the one argument mapper functions.  There are a few\n#        specific tests that abs, real and imag return real values.\n#    helper gen_unaryop_tests\n#        functions and operators which transform a single matrix\n#    helper gen_save_tests\n#        Tests the load/save functionality for ascii/binary and hdf5 formats\n#    gen_scalar_tests\n#        element ops for real and complex scalar and sparse\n#    gen_rectangular_tests\n#        unary, element, and matrix tests for a and full/sparse b\n#    gen_square_tests\n#        operations which require square matrices: lu, inv, \\\n#        A square non-singular matrix is defined from the rectangular\n#        inputs A and B.\n#    gen_assembly_tests\n#        test for sparse constructors with 'sum' vs. 'unique'\n#    gen_select_tests\n#        indexing and assignment tests\n#    gen_solver_tests\n#        Tests the solve function with triangular/banded, etc matrices\n\ncase $1 in\n    random) preset=false ;;\n    preset) preset=true ;;\n    '') preset=true ;;\n    *) echo \"mk-sparse-tst.sh random|preset\" && exit 1 ;;\nesac\n\n# create initial file\ncat <<EOF\n## !!! DO NOT EDIT !!!\n## THIS IS AN AUTOMATICALLY GENERATED FILE\n## modify mk-sparse-tst.sh to generate the tests you need.\nEOF\n\n\n# define all functions\n\n\n# =======================================================\n# Section separator\n\ngen_section() {\ncat <<EOF\n\n# ==============================================================\n\nEOF\n}\n\n\n# =======================================================\n# Specific preset tests\n\n# =======================================================\n# If a sparse operation yields zeros, then those elements\n# of the returned sparse matrix should be eaten.\ngen_eat_zeros() {\ncat <<EOF\n%% Make sure newly introduced zeros get eaten\n%!assert (nnz (sparse ([bf,bf,1]).^realmax), 1)\n%!assert (nnz (sparse ([1,bf,bf]).^realmax), 1)\n%!assert (nnz (sparse ([bf,bf,bf]).^realmax), 0)\n\n%!assert (nnz (sparse ([bf;bf;1]).^realmax), 1)\n%!assert (nnz (sparse ([1;bf;bf]).^realmax), 1)\n%!assert (nnz (sparse ([0.5;bf;bf]).^realmax), 0)\n\n%!assert (nnz (sparse ([bf,bf,1])*realmin), 1)\n%!assert (nnz (sparse ([1,bf,bf])*realmin), 1)\n%!assert (nnz (sparse ([bf,bf,bf])*realmin), 0)\n\n%!assert (nnz (sparse ([bf;bf;1])*realmin), 1)\n%!assert (nnz (sparse ([1;bf;bf])*realmin), 1)\n%!assert (nnz (sparse ([bf;bf;bf])*realmin), 0)\n\nEOF\n}\n\ngen_specific() {\ncat <<EOF\n\n%% error handling in constructor\n%!error <Invalid call> sparse ()\n%!error <Invalid call> sparse (1,2,3,4,5,6,7)\n%!error <A must be a 2-D matrix> sparse (ones (2,2,2))\n%!warning <input array cast to double>\n%! warning (\"on\", \"Octave:sparse:double-conversion\", \"local\");\n%! s = sparse (single ([1 2]));\n%!error <wrong type argument 'uint8 matrix'>\n%! s = sparse (uint8 ([1 2]));\n%!error <M must be a non-negative integer> sparse ({1}, 2)\n%!error <N must be a non-negative integer> sparse (1, {2})\n%!error <dimensions M and N must be non-negative> sparse (-1, 2)\n%!error <dimensions M and N must be non-negative> sparse (1, -2)\n%!error <dimension mismatch> sparse (1,[2,3],[1,2,3])\n%!error <invalid option: foobar> sparse ([1,1],[1,1],[1,2],\"foobar\")\n%% negative subscripts are disallowed\n%!error <subscripts must be> sparse ([1,3],[1,-4],[3,5],2,2)\n%!error <subscripts must be> sparse ([1,3],[1,-4],[3,5i],2,2)\n%!error <M must be a non-negative integer> sparse ([1,1],[1,1],[1,2], {1}, 2)\n%!error <N must be a non-negative integer> sparse ([1,1],[1,1],[1,2], 1, {2})\n%!error <dimensions M and N must be non-negative> sparse ([1,1],[1,1],[1,2], -1, 2)\n%!error <dimensions M and N must be non-negative> sparse ([1,1],[1,1],[1,2], 1, -2)\n%!warning <input array cast to double>\n%! warning (\"on\", \"Octave:sparse:double-conversion\", \"local\");\n%! s = sparse ([1,1],[1,1], single ([1,2]), 2, 2);\n%!error <wrong type argument 'uint8 matrix'>\n%! s = sparse ([1,1],[1,1], uint8 ([1,2]), 2, 2);\n\n%!test # segfault test from edd@debian.org\n%! n = 510;\n%! sparse (kron ((1:n)', ones (n,1)), kron (ones (n,1), (1:n)'), ones (n));\n\n%% segfault tests from Fabian@isas-berlin.de\n%% Note that the last four do not fail, but rather give a warning\n%% of a singular matrix, which is consistent with the full matrix\n%% behavior.  They are therefore disabled.\n%!testif HAVE_UMFPACK\n%! assert (inv (sparse ([1,1;1,1+1i])), sparse ([1-1i,1i;1i,-1i]), 10*eps);\n%#!error inv ( sparse ([1,1;1,1]  ) );\n%#!error inv ( sparse ([0,0;0,1]  ) );\n%#!error inv ( sparse ([0,0;0,1+1i]) );\n%#!error inv ( sparse ([0,0;0,0]  ) );\n\nEOF\n}\n\n\ngen_specific_tests() {\n    gen_section\n    gen_specific\n    gen_section\n    echo '%!shared bf'\n    echo '%!test bf=realmin;'\n    gen_eat_zeros\n    echo '%!test bf=realmin+realmin*1i;'\n    gen_eat_zeros\n    cat <<EOF\n%!assert (nnz (sparse ([-1,realmin,realmin]).^1.5), 1)\n%!assert (nnz (sparse ([-1,realmin,realmin,1]).^1.5), 2)\n\n## Make sure scalar v==0 doesn't confuse matters\n%!assert (nnz (sparse (1,1,0)), 0)\n%!assert (nnz (sparse (eye (3))*0), 0)\n%!assert (nnz (sparse (eye (3))-sparse (eye (3))), 0)\n\n## Make sure scalar v==0 and v==NaN does not ignore zero elements (bug #36562)\n%!assert (full (sparse (eye (3)) / 0), full (eye (3)) / 0)\n%!assert (full (0 \\ sparse (eye (3))), 0 \\ full (eye (3)))\n%!assert (full (sparse (eye (3)) / NaN), full (eye (3)) / NaN)\n%!assert (full (NaN \\ sparse (eye (3))), NaN \\ full (eye (3)))\n%!assert (0 \\ sparse ([1, 2i]), sparse (complex ([Inf, NaN], [-NaN, Inf])))\n%!assert (sparse ([1, 2i]) / 0, sparse (complex ([Inf, NaN], [-NaN, Inf])))\n\nEOF\n}\n\n\n# =======================================================\n# Main function definition\n\ngen_function() {\n    if $preset; then\n        cat <<EOF\n##\n## test_sparse\n##\n##    run preset sparse tests.  All should pass.\nfunction [passes, tests] = test_sparse\n  disp (\"writing test output to sptest.log\");\n  test (\"sparse.tst\", \"normal\", \"sptest.log\");\nendfunction\n\nEOF\n    else\n        cat <<EOF\n##\n## test_sprandom\n##\n##  total_passes=0; total_tests=0;\n##  for i=1:10\n##     [passes,tests] = sprandomtest;\n##    total_passes += passes;\n##    total_tests += tests;\n##  end\n##  The test log is appended to sprandomtest.log\nfunction [passes,total] = test_sprandom\n  warning (\"untested --- fix the source in mk-sparse-tst.sh\");\n  disp (\"appending test output to sprandomtest.log\");\n  fid = fopen (\"sprandomtest.log\", \"at\");\n  test (\"sprandom.tst\", \"normal\", fid);\n  ##[passes, total] = test (\"sprandomtest\", \"normal\", fid);\n  fclose (fid);\nendfunction\n\nEOF\n    fi\n\n}\n\n\n# =======================================================\n# matrix ops\n\n# test ordered comparisons: uses as,af,bs,bf\ngen_ordering_tests() {\n    cat <<EOF\n%% real values can be ordered (uses as,af)\n%!assert (as<=bf, sparse (af<=bf))\n%!assert (bf<=as, sparse (bf<=af))\n\n%!assert (as>=bf, sparse (af>=bf))\n%!assert (bf>=as, sparse (bf>=af))\n\n%!assert (as<bf, sparse (af<bf))\n%!assert (bf<as, sparse (bf<af))\n\n%!assert (as>bf, sparse (af>bf))\n%!assert (bf>as, sparse (bf>af))\n\nEOF\n}\n\ngen_sparsesparse_ordering_tests() {\n    cat <<EOF\n%!assert (as<=bs, sparse (af<=bf))\n%!assert (as>=bs, sparse (af>=bf))\n%!assert (as<bs, sparse (af<bf))\n%!assert (as>bs, sparse (af>bf))\nEOF\n}\n\n# test element-wise binary operations: uses as,af,bs,bf,scalar\ngen_elementop_tests() {\n    cat <<EOF\n%% Elementwise binary tests (uses as,af,bs,bf,scalar)\n%!assert (as==bs, sparse (af==bf))\n%!assert (bf==as, sparse (bf==af))\n\n%!assert (as!=bf, sparse (af!=bf))\n%!assert (bf!=as, sparse (bf!=af))\n\n%!assert (as+bf, af+bf)\n%!assert (bf+as, bf+af)\n\n%!assert (as-bf, af-bf)\n%!assert (bf-as, bf-af)\n\n%!assert (as.*bf, sparse (af.*bf))\n%!assert (bf.*as, sparse (bf.*af))\n\n%!assert (as./bf, sparse (af./bf), 100*eps)\n%!assert (bf.\\as, sparse (bf.\\af), 100*eps)\n\n%!test\n%! sv = as.^bf;\n%! fv = af.^bf;\n%! idx = find (af!=0);\n%! assert (sv(:)(idx), sparse (fv(:)(idx)), 100*eps);\n\nEOF\n}\n\ngen_sparsesparse_elementop_tests() {\n    cat <<EOF\n%!assert (as==bs, sparse (af==bf))\n%!assert (as!=bs, sparse (af!=bf))\n%!assert (as+bs, sparse (af+bf))\n%!assert (as-bs, sparse (af-bf))\n%!assert (as.*bs, sparse (af.*bf))\n%!assert (as./bs, sparse (af./bf), 100*eps)\n%!test\n%! sv = as.^bs;\n%! fv = af.^bf;\n%! idx = find (af!=0);\n%! assert(sv(:)(idx), sparse (fv(:)(idx)), 100*eps);\n\nEOF\n}\n\n# test matrix-matrix left and right division: uses as,af,bs,bf\ngen_divop_tests() {\n    cat <<EOF\n%% Matrix-matrix operators (uses af,as,bs,bf)\n%!assert (as/bf, af/bf, 100*eps)\n%!assert (af/bs, af/bf, 100*eps)\n%!assert (as/bs, sparse (af/bf), 100*eps)\n%!assert (bs\\af', bf\\af', 100*eps)\n%!assert (bf\\as', bf\\af', 100*eps)\n%!assert (bs\\as', sparse (bf\\af'), 100*eps)\n\nEOF\n}\n\n# test matrix-matrix left and right division: uses as,af,bs,bf\ngen_square_divop_tests() {\n    cat <<EOF\n%% Matrix-matrix operators (uses af,as,bs,bf)\n%!assert (as/bf, af/bf, 100*eps)\n%!assert (af/bs, af/bf, 100*eps)\n%!assert (as/bs, sparse (af/bf), 100*eps)\n%!assert (bs\\af', bf\\af', 100*eps)\n%!assert (bf\\as', bf\\af', 100*eps)\n%!assert (bs\\as', sparse (bf\\af'), 100*eps)\n\nEOF\n}\n\n# test matrix-matrix operations: uses as,af,bs,bf\ngen_matrixop_tests() {\n    cat <<EOF\n%% Matrix-matrix operators (uses af,as,bs,bf)\n%!assert (as*bf', af*bf')\n%!assert (af*bs', af*bf')\n%!assert (as*bs', sparse (af*bf'))\n\nEOF\n}\n\n# test diagonal operations\ngen_matrixdiag_tests() {\n    cat <<EOF\n%% Matrix diagonal tests (uses af,as,bf,bs)\n%!assert (diag (as), sparse (diag (af)))\n%!assert (diag (bs), sparse (diag (bf)))\n%!assert (diag (as,1), sparse (diag (af,1)))\n%!assert (diag (bs,1), sparse (diag (bf,1)))\n%!assert (diag (as,-1), sparse (diag (af,-1)))\n%!assert (diag (bs,-1), sparse (diag (bf,-1)))\n%!assert (diag (as(:)), sparse (diag (af(:))))\n%!assert (diag (as(:),1), sparse (diag (af(:),1)))\n%!assert (diag (as(:),-1), sparse (diag (af(:),-1)))\n%!assert (diag (as(:)'), sparse (diag (af(:)')))\n%!assert (diag (as(:)',1), sparse (diag (af(:)',1)))\n%!assert (diag (as(:)',-1), sparse (diag (af(:)',-1)))\n%!assert (spdiags (as,[0,1]), [diag(af,0), diag(af,1)])\n%!test\n%! [tb,tc] = spdiags (as);\n%! assert (spdiags (tb,tc,sparse (zeros (size (as)))), as);\n%! assert (spdiags (tb,tc,rows (as),columns (as)), as);\n\nEOF\n}\n\n# test matrix reshape operations\ngen_matrixreshape_tests() {\n    cat <<EOF\n%% Matrix diagonal tests (uses af,as,bf,bs)\n%!assert (reshape (as,1,prod(size(as))), sparse (reshape (af,1,prod(size(af)))))\n%!assert (reshape (as,prod(size(as)),1), sparse (reshape (af,prod(size(af)),1)))\n%!assert (reshape (as,fliplr(size(as))), sparse (reshape (af,fliplr(size(af)))))\n%!assert (reshape (bs,1,prod(size(as))), sparse (reshape (bf,1,prod(size(af)))))\n%!assert (reshape (bs,prod(size(as)),1), sparse (reshape (bf,prod(size(af)),1)))\n%!assert (reshape (bs,fliplr(size(as))), sparse (reshape (bf,fliplr(size(af)))))\n\nEOF\n}\n\n# test mapper matrix operations: uses as,af\nprint_mapper_test() {\necho \"%!assert ($1(as), sparse ($1(af)))\"\n}\n\nprint_real_mapper_test() {\n    cat <<EOF\n%!test\n%! wn2s = warning (\"query\", \"Octave:num-to-str\");\n%! warning (\"off\", \"Octave:num-to-str\");\n%! if (isreal (af))\n%!   if ($2)\n%!     assert ($1(as), sparse ($1(af)));\n%!   else\n%!     assert ($1(as), $1(af));\n%!   endif\n%! endif\n%! warning (wn2s.state, \"Octave:num-to-str\");\n\nEOF\n}\n\ngen_mapper_tests() {\necho \"%% Unary matrix tests (uses af,as)\"\nprint_mapper_test abs\nprint_mapper_test acos\nprint_mapper_test acosh\nprint_mapper_test angle\nprint_mapper_test arg\nprint_mapper_test asin\nprint_mapper_test asinh\nprint_mapper_test atan\nprint_mapper_test atanh\nprint_mapper_test ceil\nprint_mapper_test conj\nprint_mapper_test cos\nprint_mapper_test cosh\nprint_mapper_test exp\nprint_mapper_test isfinite\nprint_mapper_test fix\nprint_mapper_test floor\nprint_mapper_test imag\nprint_mapper_test isinf\nprint_mapper_test isna\nprint_mapper_test isnan\nprint_mapper_test log\nprint_mapper_test log10\nprint_mapper_test real\nprint_mapper_test round\nprint_mapper_test sign\nprint_mapper_test sin\nprint_mapper_test sinh\nprint_mapper_test sqrt\nprint_mapper_test tan\nprint_mapper_test tanh\n\n# Specific tests for certain mapper functions\n    cat <<EOF\n%!assert (issparse (abs (as))  && isreal (abs (as)))\n%!assert (issparse (real (as)) && isreal (real (as)))\n%!assert (issparse (imag (as)) && isreal (imag (as)))\n\nEOF\n}\n\ngen_real_mapper_tests() {\necho \"%% Unary matrix tests (uses af,as)\"\nprint_real_mapper_test erf 1\nprint_real_mapper_test erfc 1\n#print_real_mapper_test gamma 1\nprint_real_mapper_test isalnum 0\nprint_real_mapper_test isalpha 0\nprint_real_mapper_test isascii 0\nprint_real_mapper_test iscntrl 0\nprint_real_mapper_test isdigit 0\nprint_real_mapper_test isgraph 0\nprint_real_mapper_test islower 0\nprint_real_mapper_test isprint 0\nprint_real_mapper_test ispunct 0\nprint_real_mapper_test isspace 0\nprint_real_mapper_test isupper 0\nprint_real_mapper_test isxdigit 0\n#print_real_mapper_test gammaln 1\n\n# Specific tests for certain mapper functions\n    cat <<EOF\n\n%!test\n%! wn2s = warning (\"query\", \"Octave:num-to-str\");\n%! warning (\"off\", \"Octave:num-to-str\");\n%! if (isreal (af))\n%!   assert (lower (as), as);\n%!   assert (upper (as), as);\n%! endif\n%! warning (wn2s.state, \"Octave:num-to-str\");\n\nEOF\n}\n\n# test matrix operations: uses as,af\ngen_unaryop_tests() {\n    cat <<EOF\n%% Unary matrix tests (uses af,as)\n%!assert (issparse (as))\n%!assert (!issparse (af))\n%!assert (! (issparse (af) && iscomplex (af)))\n%!assert (! (issparse (af) && isreal (af)))\n%!assert (sum (as), sparse (sum (af)))\n%!assert (sum (as,1), sparse (sum (af,1)))\n%!assert (sum (as,2), sparse (sum (af,2)))\n%!assert (cumsum (as), sparse (cumsum (af)))\n%!assert (cumsum (as,1), sparse (cumsum (af,1)))\n%!assert (cumsum (as,2), sparse (cumsum (af,2)))\n%!assert (sumsq (as), sparse (sumsq (af)))\n%!assert (sumsq (as,1), sparse (sumsq (af,1)))\n%!assert (sumsq (as,2), sparse (sumsq (af,2)))\n%!assert (prod (as), sparse (prod (af)))\n%!assert (prod (as,1), sparse (prod (af,1)))\n%!assert (prod (as,2), sparse (prod (af,2)))\n%!assert (cumprod (as), sparse (cumprod (af)))\n%!assert (cumprod (as,1), sparse (cumprod (af,1)))\n%!assert (cumprod (as,2), sparse (cumprod (af,2)))\n\n%!assert (min (as), sparse (min (af)))\n%!assert (full (min (as(:))), min (af(:)))\n%!assert (min (as,[],1), sparse (min (af,[],1)))\n%!assert (min (as,[],2), sparse (min (af,[],2)))\n%!assert (min (as,[],1), sparse (min (af,[],1)))\n%!assert (min (as,0), sparse (min (af,0)))\n%!assert (min (as,bs), sparse (min (af,bf)))\n%!assert (max (as), sparse (max (af)))\n%!assert (full (max (as(:))), max (af(:)))\n%!assert (max (as,[],1), sparse (max (af,[],1)))\n%!assert (max (as,[],2), sparse (max (af,[],2)))\n%!assert (max (as,[],1), sparse (max (af,[],1)))\n%!assert (max (as,0), sparse (max (af,0)))\n%!assert (max (as,bs), sparse (max (af,bf)))\n\n%!assert (as==as)\n%!assert (as==af)\n%!assert (af==as)\n%!test\n%! [ii,jj,vv,nr,nc] = find (as);\n%! assert (af, full (sparse (ii,jj,vv,nr,nc)));\n%!assert (nnz (as), sum (af(:)!=0))\n%!assert (nnz (as), nnz (af))\n%!assert (issparse (as.'))\n%!assert (issparse (as'))\n%!assert (issparse (-as))\n%!assert (!as, sparse (!af))\n%!assert (as.', sparse (af.'))\n%!assert (as',  sparse (af'))\n%!assert (-as, sparse (-af))\n%!assert (!as, sparse (!af))\n%!error [i,j] = size (af);as(i-1,j+1)\n%!error [i,j] = size (af);as(i+1,j-1)\n%!test\n%! [Is,Js,Vs] = find (as);\n%! [If,Jf,Vf] = find (af);\n%! assert (Is, If);\n%! assert (Js, Jf);\n%! assert (Vs, Vf);\n%!error as(0,1)\n%!error as(1,0)\n%!assert (find (as), find (af))\n%!test\n%! [i,j,v] = find (as);\n%! [m,n] = size (as);\n%! x = sparse (i,j,v,m,n);\n%! assert (x, as);\n%!test\n%! [i,j,v,m,n] = find (as);\n%! x = sparse (i,j,v,m,n);\n%! assert (x, as);\n%!assert (issparse (horzcat (as,as)))\n%!assert (issparse (vertcat (as,as)))\n%!assert (issparse (cat (1,as,as)))\n%!assert (issparse (cat (2,as,as)))\n%!assert (issparse ([as,as]))\n%!assert (issparse ([as;as]))\n%!assert (horzcat (as,as), sparse ([af,af]))\n%!assert (vertcat (as,as), sparse ([af;af]))\n%!assert (horzcat (as,as,as), sparse ([af,af,af]))\n%!assert (vertcat (as,as,as), sparse ([af;af;af]))\n%!assert ([as,as], sparse ([af,af]))\n%!assert ([as;as], sparse ([af;af]))\n%!assert ([as,as,as], sparse ([af,af,af]))\n%!assert ([as;as;as], sparse ([af;af;af]))\n%!assert (cat (2,as,as), sparse ([af,af]))\n%!assert (cat (1,as,as), sparse ([af;af]))\n%!assert (cat (2,as,as,as), sparse ([af,af,af]))\n%!assert (cat (1,as,as,as), sparse ([af;af;af]))\n%!assert (issparse ([as,af]))\n%!assert (issparse ([af,as]))\n%!assert ([as,af], sparse ([af,af]))\n%!assert ([as;af], sparse ([af;af]))\n\nEOF\n}\n\n# operations which require square matrices.\ngen_square_tests() {\n# The \\ and / operator tests on square matrices\n    gen_square_divop_tests\n\n    cat <<EOF\n%!testif HAVE_UMFPACK\n%! assert(det(bs+speye(size(bs))), det(bf+eye(size(bf))), 100*eps*abs(det(bf+eye(size(bf)))));\n\n%!testif HAVE_UMFPACK\n%! ## Yes, we want to test lu with fewer than 4 output arguments\n%! ## and sparse input while also avoiding the warning.  So use\n%! ## warning (\"off\", ...) instead of additional outputs.\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! [l,u] = lu (sparse ([1,1;1,1]));\n%! assert (l*u, [1,1;1,1], 10*eps);\n\n%!testif HAVE_UMFPACK\n%! ## Yes, we want to test lu with fewer than 4 output arguments\n%! ## and sparse input while also avoiding the warning.  So use\n%! ## warning (\"off\", ...) instead of additional outputs.\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! [l,u] = lu (sparse ([1,1;1,1+1i]));\n%! assert (l, sparse ([1,2,2],[1,1,2],1), 10*eps);\n%! assert (u, sparse ([1,1,2],[1,2,2],[1,1,1i]), 10*eps);\n\n%!testif HAVE_UMFPACK   # permuted LU\n%! ## Yes, we want to test lu with fewer than 4 output arguments\n%! ## and sparse input while also avoiding the warning.  So use\n%! ## warning (\"off\", ...) instead of additional outputs.\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! [L,U] = lu (bs);\n%! assert (L*U, bs, 1e-10);\n\n%!testif HAVE_UMFPACK   # simple LU + row permutations\n%! ## Yes, we want to test lu with fewer than 4 output arguments\n%! ## and sparse input while also avoiding the warning.  So use\n%! ## warning (\"off\", ...) instead of additional outputs.\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! [L,U,P] = lu (bs);\n%! assert (P'*L*U, bs, 1e-10);\n%! ## triangularity\n%! [i,j,v] = find (L);\n%! assert (i-j>=0);\n%! [i,j,v] = find (U);\n%! assert (j-i>=0);\n\n%!testif HAVE_UMFPACK   # simple LU + row/col permutations\n%! [L,U,P,Q] = lu (bs);\n%! assert (P'*L*U*Q', bs, 1e-10);\n%! ## triangularity\n%! [i,j,v] = find (L);\n%! assert (i-j>=0);\n%! [i,j,v] = find (U);\n%! assert (j-i>=0);\n\n%!testif HAVE_UMFPACK   # LU with vector permutations\n%! [L,U,P,Q] = lu (bs,'vector');\n%! assert (L(P,:)*U(:,Q), bs, 1e-10);\n%! ## triangularity\n%! [i,j,v] = find (L);\n%! assert (i-j>=0);\n%! [i,j,v] = find (U);\n%! assert (j-i>=0);\n\n%!testif HAVE_UMFPACK   # LU with scaling\n%! [L,U,P,Q,R] = lu (bs);\n%! assert (R*P'*L*U*Q', bs, 1e-10);\n%! ## triangularity\n%! [i,j,v] = find (L);\n%! assert (i-j>=0);\n%! [i,j,v] = find (U);\n%! assert (j-i>=0);\n\n%!testif HAVE_UMFPACK\n%! ## Yes, we want to test lu with fewer than 4 output arguments\n%! ## and sparse input while also avoiding the warning.  So use\n%! ## warning (\"off\", ...) instead of additional outputs.\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! n = 100;\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! A = sprandn (n, n, 0.1);\n%! [L, U] = lu (A);\n%! # mldivide with permuted lower triangular matrix L with different rhs\n%! brf = rand (n, 1);\n%! x = U \\ (L \\ brf);\n%! assert (norm (A*x - brf), 0, 20*eps*n);\n%! brs = sprand (n, 1, 0.5);\n%! x = U \\ (L \\ brs);\n%! assert (norm (A*x - brs), 0, 20*eps*n);\n%! bif = rand (n, 1) + 1i * rand (n, 1);\n%! x = U \\ (L \\ bif);\n%! assert (norm (A*x - bif), 0, 50*eps*n);\n%! bis = sprand (n, 1, 0.3) + 1i * sprand (n, 1, 0.3);\n%! x = U \\ (L \\ bis);\n%! assert (norm (A*x - bis), 0, 50*eps*n);\n\n%!testif HAVE_UMFPACK\n%! ## Yes, we want to test lu with fewer than 4 output arguments\n%! ## and sparse input while also avoiding the warning.  So use\n%! ## warning (\"off\", ...) instead of additional outputs.\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! n = 100;\n%! rand (\"state\", 42);\n%! randn (\"state\", 42);\n%! A = sprandn (n, n, 0.1) + 1i * sprandn (n, n, 0.1);\n%! [L, U] = lu (A);\n%! # mldivide with permuted lower triangular matrix L with different rhs\n%! brf = rand (n, 1);\n%! x = U \\ (L \\ brf);\n%! assert (norm (A*x - brf), 0, 20*eps*n);\n%! brs = sprand (n, 1, 0.5);\n%! x = U \\ (L \\ brs);\n%! assert (norm (A*x - brs), 0, 20*eps*n);\n%! bif = rand (n, 1) + 1i * rand (n, 1);\n%! x = U \\ (L \\ bif);\n%! assert (norm (A*x - bif), 0, 50*eps*n);\n%! bis = sprand (n, 1, 0.3) + 1i * sprand (n, 1, 0.3);\n%! x = U \\ (L \\ bis);\n%! assert (norm (A*x - bis), 0, 50*eps*n);\n\n%!testif HAVE_UMFPACK   # inverse\n%! assert (inv (bs)*bs, sparse (eye (rows (bs))), 1e-10);\n\n%!assert (bf\\as', bf\\af', 100*eps)\n%!assert (bs\\af', bf\\af', 100*eps)\n%!assert (bs\\as', sparse (bf\\af'), 100*eps)\n\nEOF\n}\n\n# Cholesky tests\ngen_cholesky_tests() {\n    cat <<EOF\n%!testif HAVE_CHOLMOD\n%! assert (chol (bs)'*chol (bs), bs, 1e-10);\n%!testif HAVE_CHOLMOD\n%! assert (chol (bs,'lower')*chol (bs,'lower')', bs, 1e-10);\n%!testif HAVE_CHOLMOD\n%! assert (chol (bs,'lower'), chol (bs)', 1e-10);\n\n%!testif HAVE_CHOLMOD   # Return Partial Cholesky factorization\n%! [RS,PS] = chol (bs);\n%! assert (RS'*RS, bs, 1e-10);\n%! assert (PS, 0);\n%! [LS,PS] = chol (bs,'lower');\n%! assert (LS*LS', bs, 1e-10);\n%! assert (PS, 0);\n\n%!testif HAVE_CHOLMOD   # Permuted Cholesky factorization\n%! [RS,PS,QS] = chol (bs);\n%! assert (RS'*RS, QS*bs*QS', 1e-10);\n%! assert (PS, 0);\n%! [LS,PS,QS] = chol (bs,'lower');\n%! assert (LS*LS', QS*bs*QS', 1e-10);\n%! assert (PS, 0);\n\nEOF\n}\n\n# test scalar operations: uses af and real scalar bf; modifies as,bf,bs\ngen_scalar_tests() {\n    echo '%!test as = sparse (af);'\n    echo '%!test bs = bf;'\n    gen_elementop_tests\n    gen_ordering_tests\n    echo '%!test bf = bf+1i;'\n    echo '%!test bs = bf;'\n    gen_elementop_tests\n}\n\n# test matrix operations: uses af and bf; modifies as,bs\ngen_rectangular_tests() {\n    echo '%!test as = sparse(af);'\n    echo '%!test bs = sparse(bf);'\n    gen_mapper_tests\n    gen_real_mapper_tests\n    gen_unaryop_tests\n    gen_elementop_tests\n    gen_sparsesparse_elementop_tests\n    gen_matrixop_tests\n    # gen_divop_tests # Disable rectangular \\ and / for now\n    gen_matrixdiag_tests\n    gen_matrixreshape_tests\n    cat <<EOF\n%!testif HAVE_UMFPACK   # permuted LU\n%! ## Yes, we want to test lu with fewer than 4 output arguments\n%! ## and sparse input while also avoiding the warning.  So use\n%! ## warning (\"off\", ...) instead of additional outputs.\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! [L,U] = lu (bs);\n%! assert (L*U, bs, 1e-10);\n\n%!testif HAVE_UMFPACK   # simple LU + row permutations\n%! ## Yes, we want to test lu with fewer than 4 output arguments\n%! ## and sparse input while also avoiding the warning.  So use\n%! ## warning (\"off\", ...) instead of additional outputs.\n%! warning (\"off\", \"Octave:lu:sparse_input\", \"local\");\n%! [L,U,P] = lu (bs);\n%! assert (P'*L*U, bs, 1e-10);\n%! ## triangularity\n%! [i,j,v] = find (L);\n%! assert (i-j>=0);\n%! [i,j,v] = find (U);\n%! assert (j-i>=0);\n\n%!testif HAVE_UMFPACK   # simple LU + row/col permutations\n%! [L,U,P,Q] = lu (bs);\n%! assert (P'*L*U*Q', bs, 1e-10);\n%! ## triangularity\n%! [i,j,v] = find (L);\n%! assert (i-j>=0);\n%! [i,j,v] = find (U);\n%! assert (j-i>=0);\n\n%!testif HAVE_UMFPACK   # LU with vector permutations\n%! [L,U,P,Q] = lu (bs,'vector');\n%! assert (L (P,:)*U (:,Q), bs, 1e-10);\n%! ## triangularity\n%! [i,j,v] = find (L);\n%! assert (i-j>=0);\n%! [i,j,v] = find (U);\n%! assert (j-i>=0);\n\n%!testif HAVE_UMFPACK   # LU with scaling\n%! [L,U,P,Q,R] = lu (bs);\n%! assert (R*P'*L*U*Q', bs, 1e-10);\n%! ## triangularity\n%! [i,j,v] = find (L);\n%! assert (i-j>=0);\n%! [i,j,v] = find (U);\n%! assert (j-i>=0);\n\nEOF\n}\n\n\n# =======================================================\n# sparse assembly tests\n\ngen_assembly_tests() {\ncat <<EOF\n%%Assembly tests\n%!test\n%! m = max ([m;r(:)]);\n%! n = max ([n;c(:)]);\n%! funiq = fsum = zeros (m,n);\n%! funiq(r(:) + m*(c(:)-1) ) = ones (size (r(:)));\n%! funiq = sparse (funiq);\n%! for k=1:length (r)\n%!   fsum(r(k),c(k)) += 1;\n%! endfor\n%! fsum = sparse (fsum);\n%!assert (sparse (r,c,1), sparse (fsum(1:max(r), 1:max(c))))\n%!assert (sparse (r,c,1,\"sum\"), sparse (fsum(1:max (r),1:max (c))))\n%!assert (sparse (r,c,1,\"unique\"), sparse (funiq(1:max (r),1:max (c))))\n%!assert (sparse (r,c,1,m,n), sparse (fsum))\n%!assert (sparse (r,c,1,m,n,\"sum\"), sparse (fsum))\n%!assert (sparse (r,c,1,m,n,\"unique\"), sparse (funiq))\n\n%!assert (sparse (r,c,1i), sparse (fsum(1:max (r),1:max (c))*1i))\n%!assert (sparse (r,c,1i,\"sum\"), sparse (fsum(1:max (r),1:max (c))*1i))\n%!assert (sparse (r,c,1i,\"unique\"), sparse (funiq(1:max (r),1:max (c))*1i))\n%!assert (sparse (r,c,1i,m,n), sparse (fsum*1i))\n%!assert (sparse (r,c,1i,m,n,\"sum\"), sparse (fsum*1i))\n%!assert (sparse (r,c,1i,m,n,\"unique\"), sparse (funiq*1i))\n\n%!test\n%! if (issparse (funiq))\n%!   assert (sparse (full (1i*funiq)), sparse (1i*funiq));\n%! endif\n\n%!assert (sparse (full (funiq)), funiq)\n\n\nEOF\n}\n\n# =======================================================\n# sparse selection tests\n\ngen_scalar_select_tests () {\n    cat <<EOF\n%!assert (sparse (42)([1,1]), sparse ([42,42]))\n%!assert (sparse (42*1i)([1,1]), sparse ([42,42].*1i))\nEOF\n}\n\ngen_select_tests() {\n    cat <<EOF\n%!test as = sparse (af);\n\n%% Point tests\n%!test idx = ridx(:) + rows (as) * (cidx (:)-1);\n%!assert (sparse (as(idx)), sparse (af(idx)))\n%!assert (as(idx), sparse (af(idx)))\n%!assert (as(idx'), sparse (af(idx')))\n%!assert (as(flipud (idx(:))), sparse (af(flipud (idx(:)))))\n%!assert (as([idx,idx]), sparse (af([idx,idx])))\n\n%% Slice tests\n%!assert (as(ridx,cidx), sparse (af(ridx,cidx)))\n%!assert (as(ridx,:), sparse (af(ridx,:)))\n%!assert (as(:,cidx), sparse (af(:,cidx)))\n%!assert (as(:,:), sparse (af(:,:)))\n%!assert (as((rows (as):-1:1),:), sparse (af((size (af,1):-1:1),:)))\n%!assert (as(:,(columns (as):-1:1)), sparse (af(:, (size (af,2):-1:1))))\n\n%% Indexing tests\n%!assert (full (as([1,1],:)), af([1,1],:))\n%!assert (full (as(:,[1,1])), af(:,[1,1]))\n%!test\n%! [i,j,v] = find (as);\n%! assert (as(i(1),j(1))([1,1]), sparse ([v(1), v(1)]));\n\n%% Assignment test\n%!test\n%! ts = as; ts(:,:) = ts(fliplr (1:rows (as)),:);\n%! tf = af; tf(:,:) = tf(fliplr (1:rows (af)),:);\n%! assert (ts, sparse (tf));\n%!test\n%! ts = as; ts(fliplr (1:rows (as)),:) = ts;\n%! tf = af; tf(fliplr (1:rows (af)),:) = tf;\n%! assert (ts, sparse (tf));\n%!test\n%! ts = as; ts(:,fliplr (1:columns (as))) = ts;\n%! tf = af; tf(:,fliplr (1:columns (af))) = tf;\n%! assert (ts, sparse (tf));\n%!test\n%! ts(fliplr (1:rows (as))) = as(:,1);\n%! tf(fliplr (1:rows (af))) = af(:,1);\n%! assert (ts, sparse (tf));\n\n%% Deletion tests\n%!test\n%! ts = as; ts(1,:) = []; tf = af; tf(1,:) = [];\n%! assert (ts, sparse (tf));\n%!test\n%! ts = as; ts(:,1) = []; tf = af; tf(:,1) = [];\n%! assert (ts, sparse (tf));\n%!test\n%! xs = sparse (magic (3));\n%! ndidx(:,:,1) = [4, 9]; \n%! ndidx(:,:,2) = [4, 9]; \n%! xs(ndidx) = [];\n%! assert (xs, sparse ([8 3 4 5 9 6 7]));\n\n%% Test \"end\" keyword\n%!assert (full (as(end)), af(end))\n%!assert (full (as(1,end)), af(1,end))\n%!assert (full (as(end,1)), af(end,1))\n%!assert (full (as(end,end)), af(end,end))\n%!assert (as(2:end,2:end), sparse (af(2:end,2:end)))\n%!assert (as(1:end-1,1:end-1), sparse (af(1:end-1,1:end-1)))\nEOF\n}\n\n# =======================================================\n# sparse save and load tests\n\ngen_save_tests() {\n    cat <<EOF\n%!test # save ascii\n%! savefile = tempname ();\n%! as_save = as;\n%! save (\"-text\", savefile, \"bf\", \"as_save\", \"af\");\n%! clear as_save;\n%! load (savefile, \"as_save\");\n%! unlink (savefile);\n%! assert (as_save, sparse (af));\n%!test # save binary\n%! savefile = tempname ();\n%! as_save = as;\n%! save (\"-binary\", savefile, \"bf\", \"as_save\", \"af\");\n%! clear as_save;\n%! load (savefile, \"as_save\");\n%! unlink (savefile);\n%! assert (as_save, sparse (af));\n%!testif HAVE_HDF5   # save hdf5\n%! savefile = tempname ();\n%! as_save = as;\n%! save (\"-hdf5\", savefile, \"bf\", \"as_save\", \"af\");\n%! clear as_save;\n%! load (savefile, \"as_save\");\n%! unlink (savefile);\n%! assert (as_save, sparse (af));\n## FIXME: We should skip (or mark as a known bug) the test for\n## saving sparse matrices to MAT files when using 64-bit indexing since\n## that is not implemented yet.\n%!test # save matlab\n%! savefile = tempname ();\n%! as_save = as;\n%! save (\"-mat\", savefile, \"bf\", \"as_save\", \"af\");\n%! clear as_save;\n%! load (savefile, \"as_save\");\n%! unlink (savefile);\n%! assert (as_save, sparse (af));\nEOF\n}\n\n# =============================================================\n# Specific solver tests for matrices that will test all of the solver\n# code.  Uses alpha and beta\ngen_solver_tests() {\n\nif $preset; then\n  cat <<EOF\n%! n=8;\n%! lf=diag (1:n); lf(n-1,1)=0.5*alpha; lf(n,2)=0.25*alpha; ls=sparse (lf);\n%! uf=diag (1:n); uf(1,n-1)=2*alpha; uf(2,n)=alpha; us=sparse (uf);\n%! ts=spdiags (ones (n,3),-1:1,n,n) + diag (1:n); tf = full (ts);\nEOF\nelse\n  cat <<EOF\n%! n = floor (lognrnd (8,2)+1)';\n%! ls = tril (sprandn (8,8,0.2),-1).*alpha + n*speye (8); lf = full (ls);\n%! us = triu (sprandn (8,8,0.2),1).*alpha + n*speye (8); uf = full (us);\n%! ts = spdiags (randn (8,3),-1:1,8,8).*alpha; tf = full (ts);\nEOF\nfi\n\ncat <<EOF\n%! df = diag (1:n).* alpha; ds = sparse (df);\n%! pdf = df(randperm (n), randperm (n));\n%! pds = sparse (pdf);\n%! plf = lf(randperm (n), randperm (n));\n%! pls = sparse (plf);\n%! puf = uf(randperm (n), randperm (n));\n%! pus = sparse (puf);\n%! bs = spdiags (repmat ([1:n]',1,4),-2:1,n,n).*alpha;\n%! bf = full (bs);\n%! cf = lf + lf'; cs = sparse (cf);\n%! bcf = bf + bf'; bcs = sparse (bcf);\n%! tcf = tf + tf'; tcs = sparse (tcf);\n%! xf = diag (1:n) + fliplr (diag (1:n)).*beta;\n%! xs = sparse (xf);\n%!assert (ds\\xf, df\\xf, 1e-10)\n%!assert (ds\\xs, sparse (df\\xf), 1e-10)\n%!assert (pds\\xf, pdf\\xf, 1e-10)\n%!assert (pds\\xs, sparse (pdf\\xf), 1e-10)\n%!assert (ls\\xf, lf\\xf, 1e-10)\n%!assert (sparse (ls\\xs), sparse (lf\\xf), 1e-10)\n%!testif HAVE_UMFPACK\n%! assert (pls\\xf, plf\\xf, 1e-10);\n%!testif HAVE_UMFPACK\n%! assert (sparse (pls\\xs), sparse (plf\\xf), 1e-10);\n%!assert (us\\xf, uf\\xf, 1e-10)\n%!assert (sparse (us\\xs), sparse (uf\\xf), 1e-10)\n%!testif HAVE_UMFPACK\n%! assert (pus\\xf, puf\\xf, 1e-10);\n%!testif HAVE_UMFPACK\n%! assert (sparse (pus\\xs), sparse (puf\\xf), 1e-10);\n%!assert (bs\\xf, bf\\xf, 1e-10)\n%!assert (sparse (bs\\xs), sparse (bf\\xf), 1e-10)\n%!testif HAVE_UMFPACK\n%! assert (cs\\xf, cf\\xf, 1e-10);\n%!testif HAVE_UMFPACK\n%! assert (sparse (cs\\xs), sparse (cf\\xf), 1e-10);\n%!testif HAVE_UMFPACK\n%! assert (bcs\\xf, bcf\\xf, 1e-10);\n%!testif HAVE_UMFPACK\n%! assert (sparse (bcs\\xs), sparse (bcf\\xf), 1e-10);\n%!assert (ts\\xf, tf\\xf, 1e-10)\n%!assert (sparse (ts\\xs), sparse (tf\\xf), 1e-10)\n%!assert (tcs\\xf, tcf\\xf, 1e-10)\n%!assert (sparse (tcs\\xs), sparse (tcf\\xf), 1e-10)\n\nEOF\n\ncat <<EOF\n%% QR solver tests\n\n%!function f (a, sz, feps)\n%! b = randn (sz);\n%! x = a \\ b;\n%! assert (a * x, b, feps);\n%! b = randn (sz) + 1i*randn (sz);\n%! x = a \\ b;\n%! assert (a * x, b, feps);\n%! b = sprandn (sz(1),sz(2),0.2);\n%! x = a \\ b;\n%! assert (sparse (a * x), b, feps);\n%! b = sprandn (sz(1),sz(2),0.2) + 1i*sprandn (sz(1),sz(2),0.2);\n%! x = a \\ b;\n%! assert (sparse (a * x), b, feps);\n%!endfunction\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! a = alpha*sprandn (10,11,0.2) + speye (10,11);\n%! f (a,[10,2],1e-10);\n%! ## Test this by forcing matrix_type, as can't get a certain\n%! ## result for over-determined systems.\n%! a = alpha*sprandn (10,10,0.2) + speye (10,10);\n%! matrix_type (a, \"Singular\");\n%! f (a,[10,2],1e-10);\n\n%% Rectanguar solver tests that don't use QR\n\n%!test\n%! ds = alpha * spdiags ([1:11]',0,10,11);\n%! df = full (ds);\n%! xf = beta * ones (10,2);\n%! xs = speye (10,10);\n%!assert (ds\\xf, df\\xf, 100*eps)\n%!assert (ds\\xs, sparse (df\\xs), 100*eps)\n%!test\n%! pds = ds([2,1,3:10],:);\n%! pdf = full (pds);\n%!assert (pds\\xf, pdf\\xf, 100*eps)\n%!assert (pds\\xs, sparse (pdf\\xs), 100*eps)\n%!test\n%! ds = alpha * spdiags ([1:11]',0,11,10);\n%! df = full (ds);\n%! xf = beta * ones (11,2);\n%! xs = speye (11,11);\n%!assert (ds\\xf, df\\xf, 100*eps)\n%!assert (ds\\xs, sparse (df\\xs), 100*eps)\n%!test\n%! pds = ds([2,1,3:11],:);\n%! pdf = full (pds);\n%!assert (pds\\xf, pdf\\xf, 100*eps)\n%!assert (pds\\xs, sparse (pdf\\xs), 100*eps)\n%!test\n%! us = alpha*[[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]];\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! assert (us*(us\\xf), xf, 100*eps);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! assert (us*(us\\xs), xs, 100*eps);\n%!test\n%! pus = us(:,[2,1,3:12]);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! assert (pus*(pus\\xf), xf, 100*eps);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! assert (pus*(pus\\xs), xs, 100*eps);\n%!test\n%! us = alpha*[speye(11,9),[1;sparse(8,1);1;0]];\n%!testif HAVE_CXSPARSE\n%! [c,r] = qr (us, xf);\n%! assert (us\\xf, r\\c, 100*eps);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! [c,r] = qr (us, xs);\n%! r = matrix_type (r, \"Singular\"); ## Force Matrix Type\n%! assert (us\\xs, r\\c, 100*eps);\n%!test\n%! pus = us(:,[1:8,10,9]);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! [c,r] = qr (pus, xf);\n%! r = matrix_type (r, \"Singular\"); ## Force Matrix Type\n%! assert (pus\\xf, r\\c, 100*eps);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! [c,r] = qr (pus, xs);\n%! r = matrix_type (r, \"Singular\"); ## Force Matrix Type\n%! assert (pus\\xs, r\\c, 100*eps);\n%!test\n%! ls = alpha*[speye(9,11);[1, sparse(1,8),1,0]];\n%! xf = beta * ones (10,2);\n%! xs = speye (10,10);\n%!assert (ls*(ls\\xf), xf, 100*eps)\n%!assert (ls*(ls\\xs), xs, 100*eps)\n%!test\n%! pls = ls([1:8,10,9],:);\n%!assert (pls*(pls\\xf), xf, 100*eps)\n%!assert (pls*(pls\\xs), xs, 100*eps)\n%!test\n%! ls = alpha*[speye(10,10), sparse(10,1);[1;1], sparse(2,9),[1;1]];\n%! xf = beta * ones (12,2);\n%! xs = speye (12,12);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! [c,r] = qr (ls, xf);\n%! assert (ls\\xf, r\\c, 100*eps);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! [c,r] = qr (ls, xs);\n%! r = matrix_type (r, \"Singular\"); ## Force Matrix Type\n%! assert (ls\\xs, r\\c, 100*eps);\n%!test\n%! pls = ls(:,[1:8,10,9]);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! [c,r] = qr (pls, xf);\n%! r = matrix_type (r, \"Singular\"); ## Force Matrix Type\n%! assert (pls\\xf, r\\c, 100*eps);\n%!testif HAVE_UMFPACK, HAVE_CXSPARSE\n%! [c,r] = qr (pls, xs);\n%! r = matrix_type (r, \"Singular\"); ## Force Matrix Type\n%! assert (pls\\xs, r\\c, 100*eps);\n\nEOF\n}\n\n\n# =============================================================\n# Putting it all together: defining the combined tests\n\n\n# initial function\ngen_function\ngen_section\n\n# specific tests\nif $preset; then\n    gen_specific_tests\n    gen_section\nfi\n\n# scalar operations\necho '%!shared as,af,bs,bf'\nif $preset; then\n    echo '%!test af=[1+1i,2-1i,0,0;0,0,0,3+2i;0,0,0,4];'\n    echo '%!test bf=3;'\nelse\n    cat <<EOF\n%!test\n%! % generate m,n from 1 to <5000\n%! m = floor (lognrnd (8,2)+1);\n%! n = floor (lognrnd (8,2)+1);\n%! as = sprandn (m,n,0.3);\n%! af = full (as + 1i*sprandn (as));\n%! bf = randn;\nEOF\nfi\n\ngen_scalar_tests\ngen_section\n\n# rectangular operations\nif $preset; then\n    echo '%!test af=[1+1i,2-1i,0,0;0,0,0,3+2i;0,0,0,4];'\n    echo '%!test bf=[0,1-1i,0,0;2+1i,0,0,0;3-1i,2+3i,0,0];'\nelse\n    cat <<EOF\n%!test\n%! m = floor (lognrnd (8,2)+1);\n%! n = floor (lognrnd (8,2)+1);\n%! as = sprandn (m,n,0.3);\n%! af = full (as + 1i*sprandn (as));\n%! bs = sprandn (m,n,0.3);\n%! bf = full (bs + 1i*sprandn (bs));\nEOF\nfi\n\ngen_rectangular_tests\ngen_section\ngen_save_tests\ngen_section\necho '%!test bf = real (bf);'\ngen_rectangular_tests\ngen_section\ngen_sparsesparse_ordering_tests\ngen_section\necho '%!test af = real (af);'\ngen_rectangular_tests\ngen_section\ngen_save_tests\ngen_section\necho '%!test bf = bf+1i*(bf!=0);'\ngen_rectangular_tests\ngen_section\n\n# square operations\nif $preset; then\n    echo '%!test af = [1+1i,2-1i,0,0;0,0,0,3+2i;0,0,0,4];'\n    echo '%! as = sparse (af);'\n    echo '%!test bf = [0,1-1i,0,0;2+1i,0,0,0;3-1i,2+3i,0,0];'\nelse\n    cat <<EOF\n%!test\n%! m = floor (lognrnd (8,2)+1);\n%! n = floor (lognrnd (8,2)+1);\n%! as = sprandn (m,n,0.3);\n%! af = full (as + 1i*sprandn (as));\n%! bs = sprandn (m,n,0.3);\n%! bf = full (bs + 1i*sprandn (bs));\nEOF\nfi\n\ncat <<EOF\n%!test ;# invertible matrix\n%! bf = af'*bf+max (abs ([af(:);bf(:)]))*sparse (eye (columns (as)));\n%! bs = sparse (bf);\n\nEOF\n\ngen_square_tests\ngen_section\necho '%!test bf = real (bf);'\necho '%! bs = sparse (bf);'\ngen_square_tests\ngen_section\necho '%!test af = real (af);'\necho '%! as = sparse (af);'\ngen_square_tests\ngen_section\necho '%!test bf = bf+1i*(bf!=0);'\necho '%! bs = sparse (bf);'\ngen_square_tests\ngen_section\n\n# cholesky tests\nif $preset; then\n  echo '%!test bf = [5,0,1+1i,0;0,5,0,1-2i;1-1i,0,5,0;0,1+2i,0,5];'\n  echo '%! bs = sparse (bf);'\nelse\n  echo '# This has a small chance of failing to create a positive definite matrix'\n  echo '%!test n = floor (lognrnd (8,2)+1)'\n  echo '%! bs = n*speye (n,n) + sprandn (n,n,0.3);'\n  echo '%! bf = full (bs);'\nfi\n\ngen_cholesky_tests\ngen_section\necho '%!test bf = real (bf);'\necho '%! bs = sparse (bf);'\ngen_cholesky_tests\ngen_section\n\n# assembly tests\necho '%!shared r,c,m,n,fsum,funiq'\nif $use_preset; then\n    cat <<EOF\n%!test\n%! r = [1,1,2,1,2,3];\n%! c = [2,1,1,1,2,1];\n%! m = n = 0;\nEOF\nelse\n    cat <<EOF\n%!test\n%! % generate m,n from 1 to <5000\n%! m = floor (lognrnd (8,2)+1);\n%! n = floor (lognrnd (8,2)+1);\n%! nz = ceil ((m+n)/2);\n%! r = floor (rand (5,nz)*n)+1;\n%! c = floor (rand (5,nn)*m)+1;\nEOF\nfi\ngen_assembly_tests #includes real and complex tests\ngen_section\n\n# slicing tests\necho '%!shared ridx,cidx,idx,as,af'\nif $use_preset; then\n    cat <<EOF\n%!test\n%! af = [1+1i,2-1i,0,0;0,0,0,3+2i;0,0,0,4];\n%! ridx = [1,3];\n%! cidx = [2,3];\nEOF\nelse\n    cat <<EOF\n%!test\n%! % generate m,n from 1 to <5000\n%! m = floor (lognrnd (8,2)+1);\n%! n = floor (lognrnd (8,2)+1);\n%! as = sprandn (m,n,0.3);\n%! af = full (as + 1i*sprandn (as));\n%! ridx = ceil (m*rand (1,ceil (rand*m));\n%! cidx = ceil (n*rand (1,ceil (rand*n));\nEOF\nfi\ngen_scalar_select_tests\ngen_select_tests\necho '%!test af = real (af);'\ngen_select_tests\ngen_section\necho '%!shared alpha,beta,df,pdf,lf,plf,uf,puf,bf,cf,bcf,tf,tcf,xf,ds,pds,ls,pls,us,pus,bs,cs,bcs,ts,tcs,xs'\necho '%!test alpha=1; beta=1;'\necho '%! old_state = rand (\"state\");'\necho '%! restore_state = onCleanup (@() rand (\"state\", old_state));'\necho '%! rand (\"state\", 42);  # initialize generator to make tests reproducible'\ngen_solver_tests\necho '%!test alpha=1; beta=1i;'\ngen_solver_tests\necho '%!test alpha=1i; beta=1;'\ngen_solver_tests\necho '%!test alpha=1i; beta=1i;'\ngen_solver_tests\ngen_section\n"
  },
  {
    "path": "test/mk_bc_overloads_expected.m",
    "content": "%% this script is intended to be Matlab compatible\n%% first, run the script\n%\n%%   ./mk-bc-overloads-tst.sh overloads_only\n%\n%% to generate the overloaded functions.\n%\nex.double = 1;\nex.single = single (1);\nex.logical = true;\nex.char = 'char';\nex.int8  = int8 (1);\nex.int16 = int16 (1);\nex.int32 = int32 (1);\nex.int64 = int64 (1);\nex.uint8  = uint8 (1);\nex.uint16 = uint16 (1);\nex.uint32 = uint32 (1);\nex.uint64 = uint64 (1);\nex.cell = {};\nex.struct = struct ();\nex.function_handle = @numel;\n\nf = fieldnames (ex);\nn = numel (f);\n\nfid = fopen ('bc_overloads_expected','w');\nfid\nfor i = 1:n\n  for j = 1:n\n    s = tbcover (ex.(f{i}), ex.(f{j}));\n    fprintf (fid, '%s %s %s\\n', f{i}, f{j}, s);\n  end\nend\nfclose (fid)\n"
  },
  {
    "path": "test/nest/arg_nest.m",
    "content": "## arg_nest.m\nfunction x = arg_nest\n  x = 1;\n  A (x);\n  function A (x)\n    x = 2;\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/arg_ret.m",
    "content": "function a = arg_ret\n  a = 10;\n  f;\n  function a = f\n    a = 5;\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/bug_59989.m",
    "content": "function y = bug_59989 ()\n  unpacker = @(x) sum (x);\n  function y = nest1 (x, a)\n    y = a + unpacker (x);\n  endfunction\n  function y = nest2 (fh)\n    x = [2, 3];\n    y = fh (x);\n  endfunction\n  a = 1;\n  y = nest2 (@(x) nest1 (x, a));\nendfunction\n"
  },
  {
    "path": "test/nest/counter.m",
    "content": "function fcnHandle = counter\n  value = 0;\n  function currentValue = increment\n    value = value+1;\n    currentValue = value;\n  end\n  fcnHandle = @increment;\nend\n"
  },
  {
    "path": "test/nest/module.mk",
    "content": "nest_TEST_FILES = \\\n  %reldir%/arg_nest.m \\\n  %reldir%/arg_ret.m \\\n  %reldir%/bug_59989.m \\\n  %reldir%/counter.m \\\n  %reldir%/nest.tst \\\n  %reldir%/nest_eval.m \\\n  %reldir%/no_closure.m \\\n  %reldir%/nst1.m \\\n  %reldir%/nst2.m \\\n  %reldir%/nst3.m \\\n  %reldir%/persistent_nest.m \\\n  %reldir%/recursive_nest.m \\\n  %reldir%/recursive_nest2.m \\\n  %reldir%/recursive_nest3.m \\\n  %reldir%/scope0.m \\\n  %reldir%/scope1.m \\\n  %reldir%/scope2.m \\\n  %reldir%/scope3.m \\\n  %reldir%/script_nest.m \\\n  %reldir%/script_nest_2.m \\\n  %reldir%/script_nest_script.m \\\n  %reldir%/script_nest_script_2.m \\\n  %reldir%/varg_nest.m \\\n  %reldir%/varg_nest2.m\n\nTEST_FILES += $(nest_TEST_FILES)\n"
  },
  {
    "path": "test/nest/nest.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n################################################################################\n## This file actually executes the tests on nested functions.\n##\n## It relies on the function files defined in the nest/ directory.\n################################################################################\n\n%!test\n%! assert (recursive_nest (), 25);\n%! clear -global recursive_nest_inc;  # cleanup after test\n\n%!assert (recursive_nest2 (), 20)\n\n%!assert (recursive_nest3 (), 5)\n\n## FIXME: The following test works in Matlab R2020b, but in Octave it never\n##        worked.  The output of \"script_nest\" is unassigned.  This got\n##        revealed by fixing bug #58686.\n\n%!test <*58691> assert (script_nest (), 5)\n\n%!assert (arg_ret (), 10)\n\n%!assert (arg_nest, 1)\n\n%!assert (varg_nest (-1), 6)\n\n%!assert (varg_nest2, 5)\n\n%!test\n%! scope0;\n\n%!test\n%! scope1 (1);\n\n%!test\n%! scope3;\n\n%!assert (nest_eval (\"x = 5;\", \"x = 6;\"), 6)\n\n%!error <can not add variable \"y\" to a static workspace>\n%! nest_eval (\"x = 5;\", \"y = 6;\");\n\n%!error <can not add variable \"y\" to a static workspace>\n%! nest_eval (\"x = -5; x = abs (x);\", \"y = 6;\")\n\n%!test\n%! f = no_closure (0);\n%! assert (f(\"foo\"), \"nested foo\");\n%! assert (f(\"foo\"), \"nested foo\");\n\n%!test <*39257>\n%! f = no_closure (1);\n%! assert (f(), \"nested\");\n%! assert (f(\"foo\"), \"nested foo\");\n\n%!error <D' undefined near line 7> scope2\n%!error <can not add variable \"y\" to a static workspace> nest_eval (\"y = 5;\", \"\")\n%!error <can not add variable \"y\" to a static workspace> nest_eval (\"y;\", \"\")\n\n## Test the way that non-local variables referenced by nested functions\n## work with function handles.\n\n## FH1 and FH2 were created separately so will have distinct\n## closure contexts.handles, FH3 is a copy of FH2 so they will\n## share the same context.\n\n%!test <*39257>\n%! fh1 = nst1 (13);\n%! fh2 = nst1 (13);\n%! fh3 = fh2;\n%!\n%! assert (fh1 (), 13);\n%! assert (fh2 (), 13);\n%! assert (fh3 (), 13);\n%!\n%! assert (fh1 (42), 42);\n%! assert (fh2 (), 13);\n%! assert (fh3 (), 13);\n%!\n%! assert (fh2 (pi), pi);\n%! assert (fh1 (), 42);\n%! assert (fh3 (), pi);\n\n## Similar to the test above, but with persistent variables.  These are\n## stored in the function, not the closure context, so are shared among\n## all handles whether they are created separately or copied.\n\n%!test\n%! fh1 = nst2 (13);\n%! fh2 = nst2 (13);\n%! fh3 = fh2;\n%!\n%! assert (fh1 (), 13);\n%! assert (fh2 (), 13);\n%! assert (fh3 (), 13);\n%!\n%! assert (fh1 (42), 42);\n%! assert (fh2 (), 42);\n%! assert (fh3 (), 42);\n%!\n%! assert (fh2 (pi), pi);\n%! assert (fh1 (), pi);\n%! assert (fh3 (), pi);\n\n## And again with global variables.\n\n%!test\n%! fh1 = nst3 (13);\n%! fh2 = nst3 (13);\n%! fh3 = fh2;\n%!\n%! assert (fh1 (), 13);\n%! assert (fh2 (), 13);\n%! assert (fh3 (), 13);\n%!\n%! assert (fh1 (42), 42);\n%! assert (fh2 (), 42);\n%! assert (fh3 (), 42);\n%!\n%! assert (fh2 (pi), pi);\n%! assert (fh1 (), pi);\n%! assert (fh3 (), pi);\n%!\n%! clear -global g;  # cleanup after tests\n\n## Test case from <https://stackoverflow.com/q/26238491/6579744>\n%!test\n%! f1 = counter ();\n%! f2 = counter ();\n%! observed = [f1(), f1(), f2(), f1(), f2()];\n%! assert (observed, [1, 2, 1, 3, 2]);\n\n## Test visibility of nested function from script called from parent.\n%!assert (script_nest_2 (42), 84)\n%!error script_nest_2 (0)\n\n%!assert (bug_59989 (), 6)\n"
  },
  {
    "path": "test/nest/nest_eval.m",
    "content": "function x = nest_eval (a, b)\n  eval (a);\n  nested ();\n\n  function nested ()\n    eval (b);\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/no_closure.m",
    "content": "## no_closure.m\nfunction r = no_closure (n)\n  if (ischar (n))\n    r = nested (n);\n  else\n    if (n == 0)\n      r = @no_closure;\n    elseif (n == 1)\n      r = @nested;\n    endif\n  endif\n  function r = nested (x)\n    if (nargin == 1)\n      r = [\"nested \", x];\n    else\n      r = \"nested\";\n    endif\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/nst1.m",
    "content": "function fh = nst1 (xval)\n  if (nargin > 0)\n    x = xval;\n  end\n  fh = @nst;\n  function r = nst (xval)\n    if (nargin > 0)\n      x = xval;\n    end\n    r = x;\n  end\nend\n"
  },
  {
    "path": "test/nest/nst2.m",
    "content": "function fh = nst2 (pval)\n  persistent p\n  if (nargin > 0)\n    p = pval;\n  end\n  fh = @nst;\n  function r = nst (pval)\n    if (nargin > 0)\n      p = pval;\n    end\n    r = p;\n  end\nend\n"
  },
  {
    "path": "test/nest/nst3.m",
    "content": "function fh = nst3 (gval)\n  global g\n  if (nargin > 0)\n    g = gval;\n  end\n  fh = @nst;\n  function r = nst (gval)\n    if (nargin > 0)\n      g = gval;\n    end\n    r = g;\n  end\nend\n"
  },
  {
    "path": "test/nest/persistent_nest.m",
    "content": "## persistent_nest\nfunction y = persistent_nest ()\n  persistent x = 0;\n  g;\n  y = x;\n\n  function g\n    x = x + 1;\n  end\nend\n"
  },
  {
    "path": "test/nest/recursive_nest.m",
    "content": "## recursive_nest.m\nfunction x = recursive_nest ()\n  global recursive_nest_inc = 1\n  x = 5;\n  f (20);\n\n  function f (n)\n    if (n > 0)\n      x = x + recursive_nest_inc;\n      f (n - 1);\n    end\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/recursive_nest2.m",
    "content": "## recursive_nest2.m\nfunction x = recursive_nest2 ()\n  x = B (20);\n  function v = B (n)\n    Y = 0;\n    BB (n);\n    C;\n    v = Y;\n    function BB (m)\n      if (m > 0)\n        Y = Y + 1;\n        BB(m - 1);\n        C;\n      end\n    endfunction\n  endfunction\n\n  function C\n    Y = 0;\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/recursive_nest3.m",
    "content": "function x = recursive_nest3 ()\n  y = 5;\n  f (y);\n  x = y;\n  g (x);\n  function f (y)\n    y = 10;\n  endfunction\n\n  function g (x)\n    x = 10;\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/scope0.m",
    "content": "## scope0.m\nfunction scope0\n  C;\n  function A\n    B;\n    function B\n    endfunction\n  endfunction\n\n  function C\n    D;\n    function D\n      A;\n    endfunction\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/scope1.m",
    "content": "## scope1.m\nfunction scope1 (n)\n  value = n;\n  if (value)\n    C;\n  end\n  function A\n    B;\n    function B\n      scope1 (0);\n    endfunction\n  endfunction\n\n  function C\n    D;\n    function D\n      A;\n    endfunction\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/scope2.m",
    "content": "## scope2.m\nfunction scope2\n  C;\n  function A\n    B;\n    function B\n      D;\n    endfunction\n  endfunction\n\n  function C\n    D;\n    function D\n      A;\n    endfunction\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/scope3.m",
    "content": "## scope3.m\nfunction scope3\n  C;\n  function A\n    B;\n    function B\n      E;\n    endfunction\n    function E\n    endfunction\n  endfunction\n\n  function C\n    D;\n    function D\n      A;\n    endfunction\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/script_nest.m",
    "content": "## script_nest.m\nfunction x = script_nest\n  A (5)\n  function A (n)\n    if (n <= 0)\n      script_nest_script;\n    else\n      A (n - 1);\n    endif\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/script_nest_2.m",
    "content": "## script_nest.m\nfunction r = script_nest_2 (x)\n  function r = nest_fun ()\n    r = 13;\n  endfunction\n  script_nest_script_2;\nendfunction\n"
  },
  {
    "path": "test/nest/script_nest_script.m",
    "content": "## script_nest_script.m\nx = 5;\n"
  },
  {
    "path": "test/nest/script_nest_script_2.m",
    "content": "## script_nest_script.m\nif (x > 0)\n  r = x * 2;\nelse\n  ## Expect error since nested function should not be\n  ## visible in this context.\n  r = nest_fun ();\nendif\n"
  },
  {
    "path": "test/nest/varg_nest.m",
    "content": "function x = varg_nest (varargin)\n  x = abs (f (-5)) + g;\n\n  function x = f (varargin)\n    x = abs (varargin{1});\n  endfunction\n\n  function x = g\n    x = abs (varargin{1});\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/nest/varg_nest2.m",
    "content": "function x = varg_nest2\n  [a, b] = f;\n  x = a;\n\n  if (nargout == 1)\n    x = a;\n  endif\n\n  function [a, b] = f\n    if (nargout == 2)\n      a = b = 5;\n    endif\n  endfunction\nendfunction\n"
  },
  {
    "path": "test/null-assign.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2008-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! a = 1:3; a(:) = []; assert (size (a), [0, 0]);\n%!test\n%! a = 1:3; a(1:3) = []; assert (size (a), [1, 0]);\n%!test\n%! a = (1:3).'; a(1:3) = []; assert (size (a), [0, 1]);\n%!test\n%! a = ones (3); a(:,:) = []; assert (size (a), [0, 3]);\n%!test\n%! a = ones (3); a(1:3,:) = []; assert (size (a), [0, 3]);\n%!test\n%! a = ones (3); a(:,1:3) = []; assert (size (a), [3, 0]);\n%!test\n%! a = ones (3); fail (\"a(1:2,1:2) = []\", \".*\");\n%!test\n%! a = ones (3); fail (\"a(1:3,1:3) = []\", \".*\");\n\n## null strings should delete. [,] and [;] should delete.\n%!test\n%! a = ones (3); a(1:2,:) = [,]; assert (size (a), [1,3]);\n%!test\n%! a = ones (3); a(1:2,:) = [;]; assert (size (a), [1,3]);\n%!test\n%! a = ones (3); a(1:2,:) = ''; assert (size (a), [1,3]);\n%!test\n%! a = ones (3); a(1:2,:) = \"\"; assert (size (a), [1,3]);\n\n## null matrix stored anywhere should lose its special status\n%!test\n%! a = ones (3); b = []; fail (\"a(:,1:3) = b\", \".\");\n%!test\n%! a = ones (3); b{1} = []; fail (\"a(:,1:3) = b{1}\", \".\");\n%!test\n%! a = ones (3); b.x = []; fail (\"a(:,1:3) = b.x\", \".\");\n\n## filtering a null matrix through a function should not delete\n%!test\n%! a = ones (3); fail (\"a(:,1:3) = double ([])\");\n\n## for compatibility with Matlab, subsasgn allows any 0x0 double array\n## but not other empty arrays (bug #48867)\n%!test\n%! a = ones (3);\n%! a = subsasgn (a, substruct ('()', {':',1:2}), []);\n%! assert (size (a), [3,1]);\n%!test\n%! a = ones (3); b = zeros (0, 0);\n%! a = subsasgn (a, substruct ('()', {':',1:2}), b);\n%! assert (size (a), [3,1]);\n%!test\n%! a = ones (3); b = zeros (0, 0, 2);\n%! fail (\"subsasgn (a, substruct ('()', {':',1:2}), b)\", \".\");\n%!test\n%! a = ones (3); b = zeros (0, 0, \"uint8\");\n%! fail (\"subsasgn (a, substruct ('()', {':',1:2}), b)\", \".\");\n\n%!test\n%! classes = {@int8, @int16, @int32, @int64, ...\n%!   @uint8, @uint16, @uint32, @uint64, ...\n%!   @single, @double, @logical};\n%! for i = 1:numel (classes)\n%!   cls = classes{i};\n%!   x = cls ([1, 2, 3]);\n%!   cls_nm = class (x);\n%!   x(2) = [];\n%!   assert (x, cls ([1, 3]));\n%!   assert (class (x), cls_nm);\n%!   x(2) = [];\n%!   assert (x, cls (1));\n%!   assert (class (x), cls_nm);\n%!   x(1) = [];\n%!   assert (x, cls (zeros (1, 0)));\n%!   assert (class (x), cls_nm);\n%! endfor\n%! for i = 1:numel (classes)\n%!   cls = classes{i};\n%!   x = cls ([1, 2, 3]);\n%!   cls_nm = class (x);\n%!   x(2) = '';\n%!   assert (x, cls ([1, 3]));\n%!   assert (class (x), cls_nm);\n%!   x(2) = '';\n%!   assert (x, cls (1));\n%!   assert (class (x), cls_nm);\n%!   x(1) = '';\n%!   assert (x, cls (zeros (1, 0)));\n%!   assert (class (x), cls_nm);\n%! endfor\n%! for i = 1:numel (classes)\n%!   cls = classes{i};\n%!   x = cls ([1, 2, 3]);\n%!   cls_nm = class (x);\n%!   x(2) = \"\";\n%!   assert (x, cls ([1, 3]));\n%!   assert (class (x), cls_nm);\n%!   x(2) = \"\";\n%!   assert (x, cls (1));\n%!   assert (class (x), cls_nm);\n%!   x(1) = \"\";\n%!   assert (x, cls (zeros (1, 0)));\n%!   assert (class (x), cls_nm);\n%! endfor\n"
  },
  {
    "path": "test/parser.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2010-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Tests for parser problems belong in this file.\n## We need many more tests here!\n\n## Test cell construction operator {}\n%!assert ({1 2 {3 4}}, {1,2,{3,4}})\n%!assert ({1, 2 {3 4}}, {1,2,{3,4}})\n%!assert ({1 2, {3 4}}, {1,2,{3,4}})\n%!assert ({1 2 {3, 4}}, {1,2,{3,4}})\n%!assert ({1, 2, {3 4}}, {1,2,{3,4}})\n%!assert ({1 2,{3 4}}, {1,2,{3,4}})\n%!assert ({1 2,{3,4}}, {1,2,{3,4}})\n%!assert ({1,2,{3 4}}, {1,2,{3,4}})\n\n## bug #43113 using null comma-separated list in constructor\n%!test\n%! z = cell (1,2,3,0,5);\n%! assert ({1, z{:}, 2}, {1, 2});\n%! assert ({1; z{:}; 2}, {1; 2});\n%! assert ({1 2; z{:}; 3 4}, {1, 2; 3 4});\n%! assert ({1 2; 5 z{:} 6; 3 4}, {1, 2; 5 6; 3 4});\n\n## Tests for operator precedence as documented in section 8.8 of manual\n## There are 13 levels of precedence from \"parentheses and indexing\" (highest)\n## down to \"statement operators\" (lowest).\n##\n## Level 13 (parentheses and indexing)\n## Overrides all other levels\n%!test\n%! a.b = 1;\n%! assert (a. b++, 1);\n%! assert (a.b, 2);\n%! clear a;\n%! a.b = [0 1];\n%! b = 2;\n%! assert (a.b', [0;1]);\n%! assert (!a .b, logical ([1 0]));\n%! assert (3*a .b, [0 3]);\n%! assert (a. b-1, [-1 0]);\n%! warning ('off', 'Octave:colon-nonscalar-argument', 'local');\n%! assert (a. b:3, 0:3);\n%! assert (a. b>0.5, logical ([0 1]));\n%! assert (a. b&0, logical ([0 0]));\n%! assert (a. b|0, logical ([0 1]));\n%! a.b = [1 2];\n%! assert (a. b&&0, false);\n%! assert (a. b||0, true);\n%! a.b += a. b*2;\n%! assert (a.b, [3 6]);\n## Level 12 (postfix increment and decrement)\n%!test\n%! a = [3 5];\n%! assert (2.^a ++, [8 32]);\n%! assert (a, [4 6]);\n%! assert (a--', [4; 6]);\n%! assert (a, [3 5]);\n%! a = 0;\n%! assert (!a --, true);\n%! assert (-a ++, 1);\n%! assert (3*a ++, 0);\n%! assert (a++-2, -1);\n%! assert (1:a ++, 1:2);\n%! assert (4>a++, true);\n%! a = [0 -1];\n%! assert ([1 1] & a++, logical ([0 1]));\n%! assert ([0 0] | a++, logical ([1 0]));\n%! a = 0;\n%! assert (1 && a ++, false);\n%! assert (0 || a --, true);\n%! a = 5; b = 2;\n%! b += a ++;\n%! assert (b, 7);\n\n## Level 11 (transpose and exponentiation)\n%!test\n%! a = 2;\n%! assert (2 ^a++, 4);\n%! assert (a, 3);\n%! assert (2 ^--a ^2, 16);\n%! assert (a, 2);\n%! assert (2 ^++a, 8);\n%! assert (a, 3);\n%! assert (a' ^2, 9);\n%! assert (2 ^sin (0), 1);\n%! assert (-2 ^2, -4);\n%! assert (2 ^+1 ^3, 8);\n%! assert (2 ^-1 ^3, 0.125);\n%! assert (2 ^~0 ^2, 4);\n%! assert (!0 ^0, false);\n%! assert (2*3 ^2, 18);\n%! assert (2+3 ^2, 11);\n%! assert ([1:10](1:2 ^2), [1 2 3 4]);\n%! assert (3>2 ^2, false);\n%! assert (1&0 ^0, true);\n%! assert (0|0 ^0, true);\n%! assert (1&&0 ^0, true);\n%! assert (0||0 ^0, true);\n%! a = 3;\n%! a *= 0 ^0;\n%! assert (a, 3);\n## Level 10 (unary plus/minus, prefix increment/decrement, not)\n%!test\n%! a = 2;\n%! assert (++ a*3, 9);\n%! assert (-- a-2, 0);\n%! assert (a, 2);\n%! assert (! a-2, -2);\n%! assert ([1:10](++ a:5), 3:5);\n%! a = [1 0];\n%! assert (! a>=[1 0], [false true]);\n%! a = 0;\n%! assert (++ a&1, true);\n%! assert (-- a|0, false);\n%! assert (-- a&&1, true);\n%! assert (++ a||0, false);\n%! a = 3;\n%! a *= ++a;\n%! assert (a, 16);\n## Level 9 (multiply, divide)\n%!test\n%! assert (3+4 * 5, 23);\n%! assert (5 * 1:6, [5 6]);\n%! assert (3>1 * 5, false);\n%! assert (1&1 * 0, false);\n%! assert (1|1 * 0, true);\n%! assert (1&&1 * 0, false);\n%! assert (1||1 * 0, true);\n%! a = 3;\n%! a /= a * 2;\n%! assert (a, 0.5);\n## Level 8 (add, subtract)\n%!test\n%! assert ([2 + 1:6], 3:6);\n%! assert (3>1 + 5, false);\n%! assert (1&1 - 1, false);\n%! assert (0|1 - 2, true);\n%! assert (1&&1 - 1, false);\n%! assert (0||1 - 2, true);\n%! a = 3;\n%! a *= 1 + 1;\n%! assert (a, 6);\n## Level 7 (colon)\n%!test\n%! assert (5:-1: 3>4, [true false false]);\n%! assert (1: 3&1, [true true true]);\n%! assert (1: 3|0, [true true true]);\n%! assert (-1: 3&&1, false);\n%! assert (-1: 3||0, false);\n%! a = [1:3];\n%! a += 3 : 5;\n%! assert (a, [4 6 8]);\n## Level 6 (relational)\n%!test\n%! assert (0 == -1&0, false);\n%! assert (1 == -1|0, false);\n%! assert (0 == -1&&0, false);\n%! assert (1 == -1||0, false);\n%! a = 2;\n%! a *= 3 > 1;\n%! assert (a, 2);\n## Level 5 (element-wise and)\n%!test\n%! assert (0 & 1|1, true);\n%! assert ([0 1] & 1&&1, false);\n%! assert (0 & 1||1, true);\n%! a = 2;\n%! a *= 3 & 1;\n%! assert (a, 2);\n## Level 4 (element-wise or)\n%!test\n%! assert ([0 1] | 1&&0, false);\n%! assert ([0 1] | 1||0, true);\n%! a = 2;\n%! a *= 0 | 1;\n%! assert (a, 2);\n## Level 3 (logical and)\n%!test\n%! assert (0 && 1||1, true);\n%! a = 2;\n%! a *= 3 && 1;\n%! assert (a, 2);\n## Level 2 (logical or)\n%!test\n%! a = 2;\n%! a *= 0 || 1;\n%! assert (a, 2);\n\n## Tests for operator precedence within each level where ordering should\n## be left to right except for postfix and assignment operators.\n\n## Level 13 (parentheses and indexing)\n%!test\n%! a.b1 = 2;\n%! assert (a.(strcat ('b','1'))++, 2);\n%! assert (a.b1, 3);\n%! b = {1 2 3 4 5};\n%! assert (b{(a. b1 + 1)}, 4);\n%! b = 1:5;\n%! assert (b(a. b1 + 1), 4);\n%! assert ([2 3].^2', [4; 9]);\n## Level 12 (postfix increment and decrement)\n## No tests possible since a++-- is not valid\n## Level 11 (transpose and exponentiation)\n%!test\n%! assert (2^3^2, 64);\n%! assert ([2 3].^2.', [4;9]);\n%! assert ([2 3].'.^2, [4;9]);\n%! assert (3*4i'.', 0 - 12i);\n%! assert (3*4i.'.', 0 + 12i);\n%! assert (2^-4^3, (1/16)^3);\n%! assert (2^+4^3, 16^3);\n%! assert (2^~0^2, 4);\n\n## Level 10 (unary plus/minus, prefix increment/decrement, not)\n%!test\n%! assert (+-+1, -1);\n%! a = -1;\n%! assert (!++a, true);\n%! assert (a, 0);\n%! assert (-~a, -1);\n%! assert (!~--a, true);\n%! assert (a, -1);\n## Level 9 (multiply, divide)\n%!test\n%! assert (3 * 4 / 5, 2.4);\n%! assert (3 ./ 4 .* 5, 3.75);\n%! assert (2 * 4 \\ 6, 0.75);\n%! assert (2 .\\ 4 .* 6, 12);\n## Level 8 (add, subtract)\n%!test\n%! assert (-3 - 4 + 1 + 3 * 2, 0);\n## Level 7 (colon)\n## No tests possible because colon operator can't be combined\n## with second colon operator.\n## Level 6 (relational)\n%!test\n%! assert (0 < 1 <= 0.5 == 0 >= 0.5 > 0, true);\n%! assert (1 < 1 == 0 != 0, true);\n%! assert (1 < 1 == 0 ~= 0, true);\n## Level 5 (element-wise and)\n## No tests possible.  Only one operator (&) at this precedence level\n## and operation is associative.\n## Level 4 (element-wise or)\n## No tests possible.  Only one operator (|) at this precedence level\n## and operation is associative.\n## Level 3 (logical and)\n%!test\n%! a = 1;\n%! assert (1 && 0 && ++a, false);\n%! assert (a, 1);\n## Level 2 (logical or)\n%!test\n%! a = 1;\n%! assert (0 || 1 || ++a, true);\n%! assert (a, 1);\n## Level 1 (assignment)\n%!test\n%! a = 2; b = 5; c = 7;\n%! assert (a += b *= c += 1, 42);\n%! assert (b == 40 && c == 8);\n\n## Test extended number format which allows '_' as NOP character\n%!assert (123_456, 123456)\n%!assert (.123_456, .123456)\n%!assert (123_456.123_456, 123456.123456)\n%!assert (0xAB_CD, uint16 (43981))\n%!assert (2e0_1, 20)\n\n## Test binary constants\n%!assert (0b101, uint8 (5))\n%!assert (0B1100_0001, 0xC1)\n%!assert (class (0b1), \"uint8\")\n\n## Test range of large binary and hexadecimal literals\n%!assert (0x8000_0000_0000_0000, uint64 (2^63))\n%!assert (0xFFFF_FFFF_FFFF_FFFF, uint64 (2^64))\n%!assert (0b10000000_0000000_000000000_00000000_00000000_00000000_00000000_00000000, uint64 (2^63))\n%!assert (0b11111111_1111111_111111111_11111111_11111111_11111111_11111111_11111111, uint64 (2^64))\n\n## Test creation of anonymous functions\n\n%!test\n%! af_in_cell = {@(x) [1 2]};\n%! assert (af_in_cell{1}(), [1, 2]);\n\n%!test\n%! R = @(rot) [cos(rot) -sin(rot); sin(rot) cos(rot)];\n%! assert (R(pi/2), [cos(pi/2), -sin(pi/2); sin(pi/2),cos(pi/2)]);\n\n## Check that xyz is tagged as a variable in the parser.  Both\n## expressions must remain on one line for this test to work as\n## intended.\n%!test\n%! xyz(1) = 1; xyz /= 1;\n%! assert (xyz, 1);\n\n%!test\n%! warning (\"off\", \"Octave:num-to-str\", \"local\");\n%! a = [97 ... % comment\n%!      'b'];\n%! assert (a, 'ab');\n\n## Check that a cell array containing function handles is parsed\n## correctly with or without commas.\n%!test\n%! a = {1, @sin, 2, @cos};\n%! b = {1 @sin 2 @cos};\n%! assert (a, b);\n\n## Maybe unnecessary, but check that further changes to parser don't\n## invalidate error handling (bug #46534).\n#!error <vertical dimensions mismatch \\(1x2 vs 1x1\\)> z = [1, 2; 3]\n\n%!test\n%! f = @(s,t=toeplitz (s),u=t(x=2:end-1,x)=32)t;\n%! assert (f (1), 1);\n%! assert (f (1, 2), 2);\n\n## FIXME: We need a sequence of concatenation tests since this seems\n##        to be a frequently reported source of incompatibilities w/Matlab\n## Check concatenation of empty char matrices (bug #52542)\n%!assert (double ([char(ones(0,3)); 'A']), 65)\n%!assert (double ([char(ones(0,3)); char(ones(2,0)); 'A']), 65)\n\n%!test <*54465>\n%! x = 0;\n%! if (! 0 || (x = 1))\n%! endif\n%! assert (x == 0);\n\n%!function x = matlab_short_circuit ()\n%!  x = 0;\n%!  if (! 0 | (x = 1))\n%!  endif\n%!endfunction\n%!test <*54465>\n%! fail (\"x = matlab_short_circuit ()\", \"warning\", \"Matlab-style short-circuit operation performed for operator |\");\n%! assert (x == 0);\n\n%!test <*56959>\n%! fail (\"i:5\", \"warning\", \"imaginary part of complex colon arguments is ignored\");\n%! fail (\"1:5*i\", \"warning\", \"imaginary part of complex colon arguments is ignored\");\n%! fail (\"1:i:5\", \"warning\", \"imaginary part of complex colon arguments is ignored\");\n"
  },
  {
    "path": "test/pkg/mfile-basic-test/COPYING",
    "content": "Appendix G GNU GENERAL PUBLIC LICENSE\n*************************************\n\n                        Version 3, 29 June 2007\n\n     Copyright (C) 2007 Free Software Foundation, Inc. `http://fsf.org/'\n\n     Everyone is permitted to copy and distribute verbatim copies of this\n     license document, but changing it is not allowed.\n\nPreamble\n========\n\nThe GNU General Public License is a free, copyleft license for software\nand other kinds of works.\n\n   The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains\nfree software for all its users.  We, the Free Software Foundation, use\nthe GNU General Public License for most of our software; it applies\nalso to any other work released this way by its authors.  You can apply\nit to your programs, too.\n\n   When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n   To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you\nhave certain responsibilities if you distribute copies of the software,\nor if you modify it: responsibilities to respect the freedom of others.\n\n   For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n   Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n   For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n   Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the\nmanufacturer can do so.  This is fundamentally incompatible with the\naim of protecting users' freedom to change the software.  The\nsystematic pattern of such abuse occurs in the area of products for\nindividuals to use, which is precisely where it is most unacceptable.\nTherefore, we have designed this version of the GPL to prohibit the\npractice for those products.  If such problems arise substantially in\nother domains, we stand ready to extend this provision to those domains\nin future versions of the GPL, as needed to protect the freedom of\nusers.\n\n   Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n   The precise terms and conditions for copying, distribution and\nmodification follow.\n\nTERMS AND CONDITIONS\n====================\n\n  0. Definitions.\n\n     \"This License\" refers to version 3 of the GNU General Public\n     License.\n\n     \"Copyright\" also means copyright-like laws that apply to other\n     kinds of works, such as semiconductor masks.\n\n     \"The Program\" refers to any copyrightable work licensed under this\n     License.  Each licensee is addressed as \"you\".  \"Licensees\" and\n     \"recipients\" may be individuals or organizations.\n\n     To \"modify\" a work means to copy from or adapt all or part of the\n     work in a fashion requiring copyright permission, other than the\n     making of an exact copy.  The resulting work is called a \"modified\n     version\" of the earlier work or a work \"based on\" the earlier work.\n\n     A \"covered work\" means either the unmodified Program or a work\n     based on the Program.\n\n     To \"propagate\" a work means to do anything with it that, without\n     permission, would make you directly or secondarily liable for\n     infringement under applicable copyright law, except executing it\n     on a computer or modifying a private copy.  Propagation includes\n     copying, distribution (with or without modification), making\n     available to the public, and in some countries other activities as\n     well.\n\n     To \"convey\" a work means any kind of propagation that enables other\n     parties to make or receive copies.  Mere interaction with a user\n     through a computer network, with no transfer of a copy, is not\n     conveying.\n\n     An interactive user interface displays \"Appropriate Legal Notices\"\n     to the extent that it includes a convenient and prominently visible\n     feature that (1) displays an appropriate copyright notice, and (2)\n     tells the user that there is no warranty for the work (except to\n     the extent that warranties are provided), that licensees may\n     convey the work under this License, and how to view a copy of this\n     License.  If the interface presents a list of user commands or\n     options, such as a menu, a prominent item in the list meets this\n     criterion.\n\n  1. Source Code.\n\n     The \"source code\" for a work means the preferred form of the work\n     for making modifications to it.  \"Object code\" means any\n     non-source form of a work.\n\n     A \"Standard Interface\" means an interface that either is an\n     official standard defined by a recognized standards body, or, in\n     the case of interfaces specified for a particular programming\n     language, one that is widely used among developers working in that\n     language.\n\n     The \"System Libraries\" of an executable work include anything,\n     other than the work as a whole, that (a) is included in the normal\n     form of packaging a Major Component, but which is not part of that\n     Major Component, and (b) serves only to enable use of the work\n     with that Major Component, or to implement a Standard Interface\n     for which an implementation is available to the public in source\n     code form.  A \"Major Component\", in this context, means a major\n     essential component (kernel, window system, and so on) of the\n     specific operating system (if any) on which the executable work\n     runs, or a compiler used to produce the work, or an object code\n     interpreter used to run it.\n\n     The \"Corresponding Source\" for a work in object code form means all\n     the source code needed to generate, install, and (for an executable\n     work) run the object code and to modify the work, including\n     scripts to control those activities.  However, it does not include\n     the work's System Libraries, or general-purpose tools or generally\n     available free programs which are used unmodified in performing\n     those activities but which are not part of the work.  For example,\n     Corresponding Source includes interface definition files\n     associated with source files for the work, and the source code for\n     shared libraries and dynamically linked subprograms that the work\n     is specifically designed to require, such as by intimate data\n     communication or control flow between those subprograms and other\n     parts of the work.\n\n     The Corresponding Source need not include anything that users can\n     regenerate automatically from other parts of the Corresponding\n     Source.\n\n     The Corresponding Source for a work in source code form is that\n     same work.\n\n  2. Basic Permissions.\n\n     All rights granted under this License are granted for the term of\n     copyright on the Program, and are irrevocable provided the stated\n     conditions are met.  This License explicitly affirms your unlimited\n     permission to run the unmodified Program.  The output from running\n     a covered work is covered by this License only if the output,\n     given its content, constitutes a covered work.  This License\n     acknowledges your rights of fair use or other equivalent, as\n     provided by copyright law.\n\n     You may make, run and propagate covered works that you do not\n     convey, without conditions so long as your license otherwise\n     remains in force.  You may convey covered works to others for the\n     sole purpose of having them make modifications exclusively for\n     you, or provide you with facilities for running those works,\n     provided that you comply with the terms of this License in\n     conveying all material for which you do not control copyright.\n     Those thus making or running the covered works for you must do so\n     exclusively on your behalf, under your direction and control, on\n     terms that prohibit them from making any copies of your\n     copyrighted material outside their relationship with you.\n\n     Conveying under any other circumstances is permitted solely under\n     the conditions stated below.  Sublicensing is not allowed; section\n     10 makes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n     No covered work shall be deemed part of an effective technological\n     measure under any applicable law fulfilling obligations under\n     article 11 of the WIPO copyright treaty adopted on 20 December\n     1996, or similar laws prohibiting or restricting circumvention of\n     such measures.\n\n     When you convey a covered work, you waive any legal power to forbid\n     circumvention of technological measures to the extent such\n     circumvention is effected by exercising rights under this License\n     with respect to the covered work, and you disclaim any intention\n     to limit operation or modification of the work as a means of\n     enforcing, against the work's users, your or third parties' legal\n     rights to forbid circumvention of technological measures.\n\n  4. Conveying Verbatim Copies.\n\n     You may convey verbatim copies of the Program's source code as you\n     receive it, in any medium, provided that you conspicuously and\n     appropriately publish on each copy an appropriate copyright notice;\n     keep intact all notices stating that this License and any\n     non-permissive terms added in accord with section 7 apply to the\n     code; keep intact all notices of the absence of any warranty; and\n     give all recipients a copy of this License along with the Program.\n\n     You may charge any price or no price for each copy that you convey,\n     and you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n     You may convey a work based on the Program, or the modifications to\n     produce it from the Program, in the form of source code under the\n     terms of section 4, provided that you also meet all of these\n     conditions:\n\n       a. The work must carry prominent notices stating that you\n          modified it, and giving a relevant date.\n\n       b. The work must carry prominent notices stating that it is\n          released under this License and any conditions added under\n          section 7.  This requirement modifies the requirement in\n          section 4 to \"keep intact all notices\".\n\n       c. You must license the entire work, as a whole, under this\n          License to anyone who comes into possession of a copy.  This\n          License will therefore apply, along with any applicable\n          section 7 additional terms, to the whole of the work, and all\n          its parts, regardless of how they are packaged.  This License\n          gives no permission to license the work in any other way, but\n          it does not invalidate such permission if you have separately\n          received it.\n\n       d. If the work has interactive user interfaces, each must display\n          Appropriate Legal Notices; however, if the Program has\n          interactive interfaces that do not display Appropriate Legal\n          Notices, your work need not make them do so.\n\n     A compilation of a covered work with other separate and independent\n     works, which are not by their nature extensions of the covered\n     work, and which are not combined with it such as to form a larger\n     program, in or on a volume of a storage or distribution medium, is\n     called an \"aggregate\" if the compilation and its resulting\n     copyright are not used to limit the access or legal rights of the\n     compilation's users beyond what the individual works permit.\n     Inclusion of a covered work in an aggregate does not cause this\n     License to apply to the other parts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n     You may convey a covered work in object code form under the terms\n     of sections 4 and 5, provided that you also convey the\n     machine-readable Corresponding Source under the terms of this\n     License, in one of these ways:\n\n       a. Convey the object code in, or embodied in, a physical product\n          (including a physical distribution medium), accompanied by the\n          Corresponding Source fixed on a durable physical medium\n          customarily used for software interchange.\n\n       b. Convey the object code in, or embodied in, a physical product\n          (including a physical distribution medium), accompanied by a\n          written offer, valid for at least three years and valid for\n          as long as you offer spare parts or customer support for that\n          product model, to give anyone who possesses the object code\n          either (1) a copy of the Corresponding Source for all the\n          software in the product that is covered by this License, on a\n          durable physical medium customarily used for software\n          interchange, for a price no more than your reasonable cost of\n          physically performing this conveying of source, or (2) access\n          to copy the Corresponding Source from a network server at no\n          charge.\n\n       c. Convey individual copies of the object code with a copy of\n          the written offer to provide the Corresponding Source.  This\n          alternative is allowed only occasionally and noncommercially,\n          and only if you received the object code with such an offer,\n          in accord with subsection 6b.\n\n       d. Convey the object code by offering access from a designated\n          place (gratis or for a charge), and offer equivalent access\n          to the Corresponding Source in the same way through the same\n          place at no further charge.  You need not require recipients\n          to copy the Corresponding Source along with the object code.\n          If the place to copy the object code is a network server, the\n          Corresponding Source may be on a different server (operated\n          by you or a third party) that supports equivalent copying\n          facilities, provided you maintain clear directions next to\n          the object code saying where to find the Corresponding Source.\n          Regardless of what server hosts the Corresponding Source, you\n          remain obligated to ensure that it is available for as long\n          as needed to satisfy these requirements.\n\n       e. Convey the object code using peer-to-peer transmission,\n          provided you inform other peers where the object code and\n          Corresponding Source of the work are being offered to the\n          general public at no charge under subsection 6d.\n\n\n     A separable portion of the object code, whose source code is\n     excluded from the Corresponding Source as a System Library, need\n     not be included in conveying the object code work.\n\n     A \"User Product\" is either (1) a \"consumer product\", which means\n     any tangible personal property which is normally used for personal,\n     family, or household purposes, or (2) anything designed or sold for\n     incorporation into a dwelling.  In determining whether a product\n     is a consumer product, doubtful cases shall be resolved in favor of\n     coverage.  For a particular product received by a particular user,\n     \"normally used\" refers to a typical or common use of that class of\n     product, regardless of the status of the particular user or of the\n     way in which the particular user actually uses, or expects or is\n     expected to use, the product.  A product is a consumer product\n     regardless of whether the product has substantial commercial,\n     industrial or non-consumer uses, unless such uses represent the\n     only significant mode of use of the product.\n\n     \"Installation Information\" for a User Product means any methods,\n     procedures, authorization keys, or other information required to\n     install and execute modified versions of a covered work in that\n     User Product from a modified version of its Corresponding Source.\n     The information must suffice to ensure that the continued\n     functioning of the modified object code is in no case prevented or\n     interfered with solely because modification has been made.\n\n     If you convey an object code work under this section in, or with,\n     or specifically for use in, a User Product, and the conveying\n     occurs as part of a transaction in which the right of possession\n     and use of the User Product is transferred to the recipient in\n     perpetuity or for a fixed term (regardless of how the transaction\n     is characterized), the Corresponding Source conveyed under this\n     section must be accompanied by the Installation Information.  But\n     this requirement does not apply if neither you nor any third party\n     retains the ability to install modified object code on the User\n     Product (for example, the work has been installed in ROM).\n\n     The requirement to provide Installation Information does not\n     include a requirement to continue to provide support service,\n     warranty, or updates for a work that has been modified or\n     installed by the recipient, or for the User Product in which it\n     has been modified or installed.  Access to a network may be denied\n     when the modification itself materially and adversely affects the\n     operation of the network or violates the rules and protocols for\n     communication across the network.\n\n     Corresponding Source conveyed, and Installation Information\n     provided, in accord with this section must be in a format that is\n     publicly documented (and with an implementation available to the\n     public in source code form), and must require no special password\n     or key for unpacking, reading or copying.\n\n  7. Additional Terms.\n\n     \"Additional permissions\" are terms that supplement the terms of\n     this License by making exceptions from one or more of its\n     conditions.  Additional permissions that are applicable to the\n     entire Program shall be treated as though they were included in\n     this License, to the extent that they are valid under applicable\n     law.  If additional permissions apply only to part of the Program,\n     that part may be used separately under those permissions, but the\n     entire Program remains governed by this License without regard to\n     the additional permissions.\n\n     When you convey a copy of a covered work, you may at your option\n     remove any additional permissions from that copy, or from any part\n     of it.  (Additional permissions may be written to require their own\n     removal in certain cases when you modify the work.)  You may place\n     additional permissions on material, added by you to a covered work,\n     for which you have or can give appropriate copyright permission.\n\n     Notwithstanding any other provision of this License, for material\n     you add to a covered work, you may (if authorized by the copyright\n     holders of that material) supplement the terms of this License\n     with terms:\n\n       a. Disclaiming warranty or limiting liability differently from\n          the terms of sections 15 and 16 of this License; or\n\n       b. Requiring preservation of specified reasonable legal notices\n          or author attributions in that material or in the Appropriate\n          Legal Notices displayed by works containing it; or\n\n       c. Prohibiting misrepresentation of the origin of that material,\n          or requiring that modified versions of such material be\n          marked in reasonable ways as different from the original\n          version; or\n\n       d. Limiting the use for publicity purposes of names of licensors\n          or authors of the material; or\n\n       e. Declining to grant rights under trademark law for use of some\n          trade names, trademarks, or service marks; or\n\n       f. Requiring indemnification of licensors and authors of that\n          material by anyone who conveys the material (or modified\n          versions of it) with contractual assumptions of liability to\n          the recipient, for any liability that these contractual\n          assumptions directly impose on those licensors and authors.\n\n     All other non-permissive additional terms are considered \"further\n     restrictions\" within the meaning of section 10.  If the Program as\n     you received it, or any part of it, contains a notice stating that\n     it is governed by this License along with a term that is a further\n     restriction, you may remove that term.  If a license document\n     contains a further restriction but permits relicensing or\n     conveying under this License, you may add to a covered work\n     material governed by the terms of that license document, provided\n     that the further restriction does not survive such relicensing or\n     conveying.\n\n     If you add terms to a covered work in accord with this section, you\n     must place, in the relevant source files, a statement of the\n     additional terms that apply to those files, or a notice indicating\n     where to find the applicable terms.\n\n     Additional terms, permissive or non-permissive, may be stated in\n     the form of a separately written license, or stated as exceptions;\n     the above requirements apply either way.\n\n  8. Termination.\n\n     You may not propagate or modify a covered work except as expressly\n     provided under this License.  Any attempt otherwise to propagate or\n     modify it is void, and will automatically terminate your rights\n     under this License (including any patent licenses granted under\n     the third paragraph of section 11).\n\n     However, if you cease all violation of this License, then your\n     license from a particular copyright holder is reinstated (a)\n     provisionally, unless and until the copyright holder explicitly\n     and finally terminates your license, and (b) permanently, if the\n     copyright holder fails to notify you of the violation by some\n     reasonable means prior to 60 days after the cessation.\n\n     Moreover, your license from a particular copyright holder is\n     reinstated permanently if the copyright holder notifies you of the\n     violation by some reasonable means, this is the first time you have\n     received notice of violation of this License (for any work) from\n     that copyright holder, and you cure the violation prior to 30 days\n     after your receipt of the notice.\n\n     Termination of your rights under this section does not terminate\n     the licenses of parties who have received copies or rights from\n     you under this License.  If your rights have been terminated and\n     not permanently reinstated, you do not qualify to receive new\n     licenses for the same material under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n     You are not required to accept this License in order to receive or\n     run a copy of the Program.  Ancillary propagation of a covered work\n     occurring solely as a consequence of using peer-to-peer\n     transmission to receive a copy likewise does not require\n     acceptance.  However, nothing other than this License grants you\n     permission to propagate or modify any covered work.  These actions\n     infringe copyright if you do not accept this License.  Therefore,\n     by modifying or propagating a covered work, you indicate your\n     acceptance of this License to do so.\n\n 10. Automatic Licensing of Downstream Recipients.\n\n     Each time you convey a covered work, the recipient automatically\n     receives a license from the original licensors, to run, modify and\n     propagate that work, subject to this License.  You are not\n     responsible for enforcing compliance by third parties with this\n     License.\n\n     An \"entity transaction\" is a transaction transferring control of an\n     organization, or substantially all assets of one, or subdividing an\n     organization, or merging organizations.  If propagation of a\n     covered work results from an entity transaction, each party to that\n     transaction who receives a copy of the work also receives whatever\n     licenses to the work the party's predecessor in interest had or\n     could give under the previous paragraph, plus a right to\n     possession of the Corresponding Source of the work from the\n     predecessor in interest, if the predecessor has it or can get it\n     with reasonable efforts.\n\n     You may not impose any further restrictions on the exercise of the\n     rights granted or affirmed under this License.  For example, you\n     may not impose a license fee, royalty, or other charge for\n     exercise of rights granted under this License, and you may not\n     initiate litigation (including a cross-claim or counterclaim in a\n     lawsuit) alleging that any patent claim is infringed by making,\n     using, selling, offering for sale, or importing the Program or any\n     portion of it.\n\n 11. Patents.\n\n     A \"contributor\" is a copyright holder who authorizes use under this\n     License of the Program or a work on which the Program is based.\n     The work thus licensed is called the contributor's \"contributor\n     version\".\n\n     A contributor's \"essential patent claims\" are all patent claims\n     owned or controlled by the contributor, whether already acquired or\n     hereafter acquired, that would be infringed by some manner,\n     permitted by this License, of making, using, or selling its\n     contributor version, but do not include claims that would be\n     infringed only as a consequence of further modification of the\n     contributor version.  For purposes of this definition, \"control\"\n     includes the right to grant patent sublicenses in a manner\n     consistent with the requirements of this License.\n\n     Each contributor grants you a non-exclusive, worldwide,\n     royalty-free patent license under the contributor's essential\n     patent claims, to make, use, sell, offer for sale, import and\n     otherwise run, modify and propagate the contents of its\n     contributor version.\n\n     In the following three paragraphs, a \"patent license\" is any\n     express agreement or commitment, however denominated, not to\n     enforce a patent (such as an express permission to practice a\n     patent or covenant not to sue for patent infringement).  To\n     \"grant\" such a patent license to a party means to make such an\n     agreement or commitment not to enforce a patent against the party.\n\n     If you convey a covered work, knowingly relying on a patent\n     license, and the Corresponding Source of the work is not available\n     for anyone to copy, free of charge and under the terms of this\n     License, through a publicly available network server or other\n     readily accessible means, then you must either (1) cause the\n     Corresponding Source to be so available, or (2) arrange to deprive\n     yourself of the benefit of the patent license for this particular\n     work, or (3) arrange, in a manner consistent with the requirements\n     of this License, to extend the patent license to downstream\n     recipients.  \"Knowingly relying\" means you have actual knowledge\n     that, but for the patent license, your conveying the covered work\n     in a country, or your recipient's use of the covered work in a\n     country, would infringe one or more identifiable patents in that\n     country that you have reason to believe are valid.\n\n     If, pursuant to or in connection with a single transaction or\n     arrangement, you convey, or propagate by procuring conveyance of, a\n     covered work, and grant a patent license to some of the parties\n     receiving the covered work authorizing them to use, propagate,\n     modify or convey a specific copy of the covered work, then the\n     patent license you grant is automatically extended to all\n     recipients of the covered work and works based on it.\n\n     A patent license is \"discriminatory\" if it does not include within\n     the scope of its coverage, prohibits the exercise of, or is\n     conditioned on the non-exercise of one or more of the rights that\n     are specifically granted under this License.  You may not convey a\n     covered work if you are a party to an arrangement with a third\n     party that is in the business of distributing software, under\n     which you make payment to the third party based on the extent of\n     your activity of conveying the work, and under which the third\n     party grants, to any of the parties who would receive the covered\n     work from you, a discriminatory patent license (a) in connection\n     with copies of the covered work conveyed by you (or copies made\n     from those copies), or (b) primarily for and in connection with\n     specific products or compilations that contain the covered work,\n     unless you entered into that arrangement, or that patent license\n     was granted, prior to 28 March 2007.\n\n     Nothing in this License shall be construed as excluding or limiting\n     any implied license or other defenses to infringement that may\n     otherwise be available to you under applicable patent law.\n\n 12. No Surrender of Others' Freedom.\n\n     If conditions are imposed on you (whether by court order,\n     agreement or otherwise) that contradict the conditions of this\n     License, they do not excuse you from the conditions of this\n     License.  If you cannot convey a covered work so as to satisfy\n     simultaneously your obligations under this License and any other\n     pertinent obligations, then as a consequence you may not convey it\n     at all.  For example, if you agree to terms that obligate you to\n     collect a royalty for further conveying from those to whom you\n     convey the Program, the only way you could satisfy both those\n     terms and this License would be to refrain entirely from conveying\n     the Program.\n\n 13. Use with the GNU Affero General Public License.\n\n     Notwithstanding any other provision of this License, you have\n     permission to link or combine any covered work with a work licensed\n     under version 3 of the GNU Affero General Public License into a\n     single combined work, and to convey the resulting work.  The terms\n     of this License will continue to apply to the part which is the\n     covered work, but the special requirements of the GNU Affero\n     General Public License, section 13, concerning interaction through\n     a network will apply to the combination as such.\n\n 14. Revised Versions of this License.\n\n     The Free Software Foundation may publish revised and/or new\n     versions of the GNU General Public License from time to time.\n     Such new versions will be similar in spirit to the present\n     version, but may differ in detail to address new problems or\n     concerns.\n\n     Each version is given a distinguishing version number.  If the\n     Program specifies that a certain numbered version of the GNU\n     General Public License \"or any later version\" applies to it, you\n     have the option of following the terms and conditions either of\n     that numbered version or of any later version published by the\n     Free Software Foundation.  If the Program does not specify a\n     version number of the GNU General Public License, you may choose\n     any version ever published by the Free Software Foundation.\n\n     If the Program specifies that a proxy can decide which future\n     versions of the GNU General Public License can be used, that\n     proxy's public statement of acceptance of a version permanently\n     authorizes you to choose that version for the Program.\n\n     Later license versions may give you additional or different\n     permissions.  However, no additional obligations are imposed on any\n     author or copyright holder as a result of your choosing to follow a\n     later version.\n\n 15. Disclaimer of Warranty.\n\n     THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\n     APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE\n     COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\"\n     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,\n     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE\n     RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.\n     SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL\n     NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n 16. Limitation of Liability.\n\n     IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\n     WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES\n     AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU\n     FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\n     CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE\n     THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA\n     BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\n     PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n     PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF\n     THE POSSIBILITY OF SUCH DAMAGES.\n\n 17. Interpretation of Sections 15 and 16.\n\n     If the disclaimer of warranty and limitation of liability provided\n     above cannot be given local legal effect according to their terms,\n     reviewing courts shall apply local law that most closely\n     approximates an absolute waiver of all civil liability in\n     connection with the Program, unless a warranty or assumption of\n     liability accompanies a copy of the Program in return for a fee.\n\n\nEND OF TERMS AND CONDITIONS\n===========================\n\nHow to Apply These Terms to Your New Programs\n=============================================\n\nIf you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these\nterms.\n\n   To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least the\n\"copyright\" line and a pointer to where the full notice is found.\n\n     ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.\n     Copyright (C) YEAR NAME OF AUTHOR\n\n     This program is free software: you can redistribute it and/or modify\n     it under the terms of the GNU General Public License as published by\n     the Free Software Foundation, either version 3 of the License, or (at\n     your option) any later version.\n\n     This program is distributed in the hope that it will be useful, but\n     WITHOUT ANY WARRANTY; without even the implied warranty of\n     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n     General Public License for more details.\n\n     You should have received a copy of the GNU General Public License\n     along with this program.  If not, see `http://www.gnu.org/licenses/'.\n\n   Also add information on how to contact you by electronic and paper\nmail.\n\n   If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n     PROGRAM Copyright (C) YEAR NAME OF AUTHOR\n     This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n     This is free software, and you are welcome to redistribute it\n     under certain conditions; type `show c' for details.\n\n   The hypothetical commands `show w' and `show c' should show the\nappropriate parts of the General Public License.  Of course, your\nprogram's commands might be different; for a GUI interface, you would\nuse an \"about box\".\n\n   You should also get your employer (if you work as a programmer) or\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  For more information on this, and how to apply and follow\nthe GNU GPL, see `http://www.gnu.org/licenses/'.\n\n   The GNU General Public License does not permit incorporating your\nprogram into proprietary programs.  If your program is a subroutine\nlibrary, you may consider it more useful to permit linking proprietary\napplications with the library.  If this is what you want to do, use the\nGNU Lesser General Public License instead of this License.  But first,\nplease read `http://www.gnu.org/philosophy/why-not-lgpl.html'.\n"
  },
  {
    "path": "test/pkg/mfile-basic-test/DESCRIPTION",
    "content": "Name: mfile-basic-test\nVersion: 0.1.0\nDate: 2017-12-07\nAuthor: hopefully various authors\nMaintainer: hopefully some of those authors.\nTitle: Basic Example Package\nDescription: Basic package structure with only m-files.\nDepends: octave (>= 4.2.1)\nLicense: GPLv3+\n# BuildRequires:\n# SystemRequirements:\n# Url: external homepage\n"
  },
  {
    "path": "test/pkg/mfile-basic-test/INDEX",
    "content": "mfile-basic-example-package >> Basic Example Package.\nExample m-file\n example_mfile\n"
  },
  {
    "path": "test/pkg/mfile-basic-test/NEWS",
    "content": "mfile-basic-example-package 0.1.0\n---------------------------------\n\n* Initial version\n"
  },
  {
    "path": "test/pkg/mfile-basic-test/doc/example-package.txi",
    "content": "\\input texinfo\n@c %**start of header\n@setfilename example-package.info\n@settitle example-package_doc\n@c %**end of header\n\n@c Nowadays the predined function index has entries for each @deftypefn\n@c in additiont to each @findex.\n@defcodeindex mfn\n\n@copying\nManual for the example-package for Octave.\n\nCopyright @copyright{} 2017-2018 @email{Olaf Till <i7tiol@@t-online.de>}\n\nYou can redistribute this documentation and/or modify it under the terms\nof the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any\nlater version.\n\nThis documentation is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\nPublic License for more details.\n\nYou should have received a copy of the GNU General Public License along\nwith this documentation; if not, see <http://www.gnu.org/licenses/>.\n@end copying\n\n@include macros.texi\n\n@titlepage\n@title Manual for the example-package for Octave\n@page\n@vskip 0pt plus 1filll\n@insertcopying\n@end titlepage\n\n@c No table of contents. The table would occupy most of the top node in\n@c html and IMHO misleads the user to use the table instead of the menu\n@c structure of the nodes, which would let some information unused.\n@c\n@c @contents\n\n@c ------------------------------------------------------------------\n\n@node Top\n@top Manual for the example-package for Octave\n\nThis documentation applies to version @PACKAGEVERSION of the\nexample-package.\n\nThis is a template simple m-file based package for users.\n\nNormally, a package manual should be structured and should contain more\nthan just the helptexts of the functions.\n\n@menu\nFunctions\n* example_mfile::                     Placeholder for an mfile.\nIndices\n* Function index::                    Index of functions.\n* Concept index::                     Concept index.\n@end menu\n\n@c ------------------------------------------------------------------\n\n@node example_mfile\n@chapter Placeholder for an mfile\n@mfnindex example_mfile\n\n@c include function helptext here\n@DOCSTRING(example_mfile)\n\n@c ------------------------------------------------------------------\n\n@node Function index\n@unnumbered Index of functions in example-package\n\n@printindex mfn\n\n@c ------------------------------------------------------------------\n\n@node Concept index\n@unnumbered Concept index\n\n@printindex cp\n\n@bye\n"
  },
  {
    "path": "test/pkg/mfile-basic-test/doc/macros.texi",
    "content": "@c ---------------------------------------------------------------------\n@c\n@c Copyright (C) 2012-2026 The Octave Project Developers\n@c See the file COPYRIGHT.md in the top-level directory of this\n@c or <https://octave.org/copyright/>.\n@c\n@c\n@c This file is part of Octave.\n@c\n@c Octave is free software; you can redistribute it and/or modify it\n@c under the terms of the GNU General Public License as published by the\n@c Free Software Foundation; either version 3 of the License, or (at\n@c your option) any later version.\n@c\n@c Octave is distributed in the hope that it will be useful, but WITHOUT\n@c ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n@c FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n@c for more details.\n@c\n@c You should have received a copy of the GNU General Public License\n@c along with Octave; see the file COPYING.  If not, see\n@c <http://www.gnu.org/licenses/>.\n@c\n@c ---------------------------------------------------------------------\n\n@c The following macro marks words that aspell should ignore during\n@c spellchecking.  Within Texinfo it has no effect as it merely replaces\n@c the macro call with the argument itself.\n\n@macro nospell {arg}\n\\arg\\\n@end macro\n\n@c The following macro works around the Info/plain text expansion of @code{XXX}\n@c which is `XXX'.  This looks particularly bad when the macro body is\n@c single or double-quoted text, such as a property value `\"position\"'\n@ifinfo\n@rmacro qcode{arg}\n\\arg\\\n@end rmacro\n@end ifinfo\n@ifnotinfo\n@rmacro qcode{arg}\n@code{\\arg\\}\n@end rmacro\n@end ifnotinfo\n\n@c The following macro is used for the on-line help system, but we don't\n@c want lots of `See also: foo, bar, and baz' strings cluttering the\n@c printed manual (that information should be in the supporting text for\n@c each group of functions and variables).\n@c\n@c Implementation Note:\n@c For TeX, @vskip produces a nice separation.\n@c For Texinfo, '@sp 1' should work, but in practice produces ugly results\n@c for HTML.  We use a simple blank line to produce the correct behavior.\n\n@macro seealso {args}\n@iftex\n@vskip 2pt\n@end iftex\n@ifnottex\n\n@end ifnottex\n@ifnotinfo\n@noindent\n@strong{See also:} \\args\\.\n@end ifnotinfo\n@ifinfo\n@noindent\nSee also: \\args\\.\n@end ifinfo\n@end macro\n\n@c The following macro works around a situation where the Info/plain text\n@c expansion of the @code{XXX} macro is `XXX'.  The use of the apostrophe\n@c can be confusing if the code segment itself ends with a transpose operator.\n@ifinfo\n@macro tcode{arg}\n\\arg\\\n@end macro\n@end ifinfo\n@ifnotinfo\n@macro tcode{arg}\n@code{\\arg\\}\n@end macro\n@end ifnotinfo\n\n@c FIXME: someday, when Texinfo 5.X is standard, we might replace this with\n@c @backslashchar, which is a new addition to Texinfo.\n\n@macro xbackslashchar\n\\\\\n@end macro\n"
  },
  {
    "path": "test/pkg/mfile-basic-test/inst/example_mfile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This program is free software; you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as\n## published by the Free Software Foundation; either version 3 of the\n## License, or (at your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n## General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with this program; if not, see <http://www.gnu.org/licenses/>.\n\n## -*- texinfo -*-\n## @deftypefn {Function File} {@var{ret} =} example_mfile (@var{arg})\n## Placeholder for an mfile function.\n##\n## @var{arg}: argument. @var{ret}: returned value.\n##\n## Although this file is so short, a license text is contained as an\n## example.\n##\n## @seealso{example_open, example_close, example_do_something}\n## @end deftypefn\n\nfunction ret = example_mfile (arg)\n\n  if (nargin () != 1)\n    print_usage ();\n  endif\n\n  ret = arg;\n\nendfunction\n"
  },
  {
    "path": "test/pkg/mfile-minimal-test/COPYING",
    "content": "Appendix G GNU GENERAL PUBLIC LICENSE\n*************************************\n\n                        Version 3, 29 June 2007\n\n     Copyright (C) 2007 Free Software Foundation, Inc. `http://fsf.org/'\n\n     Everyone is permitted to copy and distribute verbatim copies of this\n     license document, but changing it is not allowed.\n\nPreamble\n========\n\nThe GNU General Public License is a free, copyleft license for software\nand other kinds of works.\n\n   The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains\nfree software for all its users.  We, the Free Software Foundation, use\nthe GNU General Public License for most of our software; it applies\nalso to any other work released this way by its authors.  You can apply\nit to your programs, too.\n\n   When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n   To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you\nhave certain responsibilities if you distribute copies of the software,\nor if you modify it: responsibilities to respect the freedom of others.\n\n   For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n   Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n   For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n   Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the\nmanufacturer can do so.  This is fundamentally incompatible with the\naim of protecting users' freedom to change the software.  The\nsystematic pattern of such abuse occurs in the area of products for\nindividuals to use, which is precisely where it is most unacceptable.\nTherefore, we have designed this version of the GPL to prohibit the\npractice for those products.  If such problems arise substantially in\nother domains, we stand ready to extend this provision to those domains\nin future versions of the GPL, as needed to protect the freedom of\nusers.\n\n   Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n   The precise terms and conditions for copying, distribution and\nmodification follow.\n\nTERMS AND CONDITIONS\n====================\n\n  0. Definitions.\n\n     \"This License\" refers to version 3 of the GNU General Public\n     License.\n\n     \"Copyright\" also means copyright-like laws that apply to other\n     kinds of works, such as semiconductor masks.\n\n     \"The Program\" refers to any copyrightable work licensed under this\n     License.  Each licensee is addressed as \"you\".  \"Licensees\" and\n     \"recipients\" may be individuals or organizations.\n\n     To \"modify\" a work means to copy from or adapt all or part of the\n     work in a fashion requiring copyright permission, other than the\n     making of an exact copy.  The resulting work is called a \"modified\n     version\" of the earlier work or a work \"based on\" the earlier work.\n\n     A \"covered work\" means either the unmodified Program or a work\n     based on the Program.\n\n     To \"propagate\" a work means to do anything with it that, without\n     permission, would make you directly or secondarily liable for\n     infringement under applicable copyright law, except executing it\n     on a computer or modifying a private copy.  Propagation includes\n     copying, distribution (with or without modification), making\n     available to the public, and in some countries other activities as\n     well.\n\n     To \"convey\" a work means any kind of propagation that enables other\n     parties to make or receive copies.  Mere interaction with a user\n     through a computer network, with no transfer of a copy, is not\n     conveying.\n\n     An interactive user interface displays \"Appropriate Legal Notices\"\n     to the extent that it includes a convenient and prominently visible\n     feature that (1) displays an appropriate copyright notice, and (2)\n     tells the user that there is no warranty for the work (except to\n     the extent that warranties are provided), that licensees may\n     convey the work under this License, and how to view a copy of this\n     License.  If the interface presents a list of user commands or\n     options, such as a menu, a prominent item in the list meets this\n     criterion.\n\n  1. Source Code.\n\n     The \"source code\" for a work means the preferred form of the work\n     for making modifications to it.  \"Object code\" means any\n     non-source form of a work.\n\n     A \"Standard Interface\" means an interface that either is an\n     official standard defined by a recognized standards body, or, in\n     the case of interfaces specified for a particular programming\n     language, one that is widely used among developers working in that\n     language.\n\n     The \"System Libraries\" of an executable work include anything,\n     other than the work as a whole, that (a) is included in the normal\n     form of packaging a Major Component, but which is not part of that\n     Major Component, and (b) serves only to enable use of the work\n     with that Major Component, or to implement a Standard Interface\n     for which an implementation is available to the public in source\n     code form.  A \"Major Component\", in this context, means a major\n     essential component (kernel, window system, and so on) of the\n     specific operating system (if any) on which the executable work\n     runs, or a compiler used to produce the work, or an object code\n     interpreter used to run it.\n\n     The \"Corresponding Source\" for a work in object code form means all\n     the source code needed to generate, install, and (for an executable\n     work) run the object code and to modify the work, including\n     scripts to control those activities.  However, it does not include\n     the work's System Libraries, or general-purpose tools or generally\n     available free programs which are used unmodified in performing\n     those activities but which are not part of the work.  For example,\n     Corresponding Source includes interface definition files\n     associated with source files for the work, and the source code for\n     shared libraries and dynamically linked subprograms that the work\n     is specifically designed to require, such as by intimate data\n     communication or control flow between those subprograms and other\n     parts of the work.\n\n     The Corresponding Source need not include anything that users can\n     regenerate automatically from other parts of the Corresponding\n     Source.\n\n     The Corresponding Source for a work in source code form is that\n     same work.\n\n  2. Basic Permissions.\n\n     All rights granted under this License are granted for the term of\n     copyright on the Program, and are irrevocable provided the stated\n     conditions are met.  This License explicitly affirms your unlimited\n     permission to run the unmodified Program.  The output from running\n     a covered work is covered by this License only if the output,\n     given its content, constitutes a covered work.  This License\n     acknowledges your rights of fair use or other equivalent, as\n     provided by copyright law.\n\n     You may make, run and propagate covered works that you do not\n     convey, without conditions so long as your license otherwise\n     remains in force.  You may convey covered works to others for the\n     sole purpose of having them make modifications exclusively for\n     you, or provide you with facilities for running those works,\n     provided that you comply with the terms of this License in\n     conveying all material for which you do not control copyright.\n     Those thus making or running the covered works for you must do so\n     exclusively on your behalf, under your direction and control, on\n     terms that prohibit them from making any copies of your\n     copyrighted material outside their relationship with you.\n\n     Conveying under any other circumstances is permitted solely under\n     the conditions stated below.  Sublicensing is not allowed; section\n     10 makes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n     No covered work shall be deemed part of an effective technological\n     measure under any applicable law fulfilling obligations under\n     article 11 of the WIPO copyright treaty adopted on 20 December\n     1996, or similar laws prohibiting or restricting circumvention of\n     such measures.\n\n     When you convey a covered work, you waive any legal power to forbid\n     circumvention of technological measures to the extent such\n     circumvention is effected by exercising rights under this License\n     with respect to the covered work, and you disclaim any intention\n     to limit operation or modification of the work as a means of\n     enforcing, against the work's users, your or third parties' legal\n     rights to forbid circumvention of technological measures.\n\n  4. Conveying Verbatim Copies.\n\n     You may convey verbatim copies of the Program's source code as you\n     receive it, in any medium, provided that you conspicuously and\n     appropriately publish on each copy an appropriate copyright notice;\n     keep intact all notices stating that this License and any\n     non-permissive terms added in accord with section 7 apply to the\n     code; keep intact all notices of the absence of any warranty; and\n     give all recipients a copy of this License along with the Program.\n\n     You may charge any price or no price for each copy that you convey,\n     and you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n     You may convey a work based on the Program, or the modifications to\n     produce it from the Program, in the form of source code under the\n     terms of section 4, provided that you also meet all of these\n     conditions:\n\n       a. The work must carry prominent notices stating that you\n          modified it, and giving a relevant date.\n\n       b. The work must carry prominent notices stating that it is\n          released under this License and any conditions added under\n          section 7.  This requirement modifies the requirement in\n          section 4 to \"keep intact all notices\".\n\n       c. You must license the entire work, as a whole, under this\n          License to anyone who comes into possession of a copy.  This\n          License will therefore apply, along with any applicable\n          section 7 additional terms, to the whole of the work, and all\n          its parts, regardless of how they are packaged.  This License\n          gives no permission to license the work in any other way, but\n          it does not invalidate such permission if you have separately\n          received it.\n\n       d. If the work has interactive user interfaces, each must display\n          Appropriate Legal Notices; however, if the Program has\n          interactive interfaces that do not display Appropriate Legal\n          Notices, your work need not make them do so.\n\n     A compilation of a covered work with other separate and independent\n     works, which are not by their nature extensions of the covered\n     work, and which are not combined with it such as to form a larger\n     program, in or on a volume of a storage or distribution medium, is\n     called an \"aggregate\" if the compilation and its resulting\n     copyright are not used to limit the access or legal rights of the\n     compilation's users beyond what the individual works permit.\n     Inclusion of a covered work in an aggregate does not cause this\n     License to apply to the other parts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n     You may convey a covered work in object code form under the terms\n     of sections 4 and 5, provided that you also convey the\n     machine-readable Corresponding Source under the terms of this\n     License, in one of these ways:\n\n       a. Convey the object code in, or embodied in, a physical product\n          (including a physical distribution medium), accompanied by the\n          Corresponding Source fixed on a durable physical medium\n          customarily used for software interchange.\n\n       b. Convey the object code in, or embodied in, a physical product\n          (including a physical distribution medium), accompanied by a\n          written offer, valid for at least three years and valid for\n          as long as you offer spare parts or customer support for that\n          product model, to give anyone who possesses the object code\n          either (1) a copy of the Corresponding Source for all the\n          software in the product that is covered by this License, on a\n          durable physical medium customarily used for software\n          interchange, for a price no more than your reasonable cost of\n          physically performing this conveying of source, or (2) access\n          to copy the Corresponding Source from a network server at no\n          charge.\n\n       c. Convey individual copies of the object code with a copy of\n          the written offer to provide the Corresponding Source.  This\n          alternative is allowed only occasionally and noncommercially,\n          and only if you received the object code with such an offer,\n          in accord with subsection 6b.\n\n       d. Convey the object code by offering access from a designated\n          place (gratis or for a charge), and offer equivalent access\n          to the Corresponding Source in the same way through the same\n          place at no further charge.  You need not require recipients\n          to copy the Corresponding Source along with the object code.\n          If the place to copy the object code is a network server, the\n          Corresponding Source may be on a different server (operated\n          by you or a third party) that supports equivalent copying\n          facilities, provided you maintain clear directions next to\n          the object code saying where to find the Corresponding Source.\n          Regardless of what server hosts the Corresponding Source, you\n          remain obligated to ensure that it is available for as long\n          as needed to satisfy these requirements.\n\n       e. Convey the object code using peer-to-peer transmission,\n          provided you inform other peers where the object code and\n          Corresponding Source of the work are being offered to the\n          general public at no charge under subsection 6d.\n\n\n     A separable portion of the object code, whose source code is\n     excluded from the Corresponding Source as a System Library, need\n     not be included in conveying the object code work.\n\n     A \"User Product\" is either (1) a \"consumer product\", which means\n     any tangible personal property which is normally used for personal,\n     family, or household purposes, or (2) anything designed or sold for\n     incorporation into a dwelling.  In determining whether a product\n     is a consumer product, doubtful cases shall be resolved in favor of\n     coverage.  For a particular product received by a particular user,\n     \"normally used\" refers to a typical or common use of that class of\n     product, regardless of the status of the particular user or of the\n     way in which the particular user actually uses, or expects or is\n     expected to use, the product.  A product is a consumer product\n     regardless of whether the product has substantial commercial,\n     industrial or non-consumer uses, unless such uses represent the\n     only significant mode of use of the product.\n\n     \"Installation Information\" for a User Product means any methods,\n     procedures, authorization keys, or other information required to\n     install and execute modified versions of a covered work in that\n     User Product from a modified version of its Corresponding Source.\n     The information must suffice to ensure that the continued\n     functioning of the modified object code is in no case prevented or\n     interfered with solely because modification has been made.\n\n     If you convey an object code work under this section in, or with,\n     or specifically for use in, a User Product, and the conveying\n     occurs as part of a transaction in which the right of possession\n     and use of the User Product is transferred to the recipient in\n     perpetuity or for a fixed term (regardless of how the transaction\n     is characterized), the Corresponding Source conveyed under this\n     section must be accompanied by the Installation Information.  But\n     this requirement does not apply if neither you nor any third party\n     retains the ability to install modified object code on the User\n     Product (for example, the work has been installed in ROM).\n\n     The requirement to provide Installation Information does not\n     include a requirement to continue to provide support service,\n     warranty, or updates for a work that has been modified or\n     installed by the recipient, or for the User Product in which it\n     has been modified or installed.  Access to a network may be denied\n     when the modification itself materially and adversely affects the\n     operation of the network or violates the rules and protocols for\n     communication across the network.\n\n     Corresponding Source conveyed, and Installation Information\n     provided, in accord with this section must be in a format that is\n     publicly documented (and with an implementation available to the\n     public in source code form), and must require no special password\n     or key for unpacking, reading or copying.\n\n  7. Additional Terms.\n\n     \"Additional permissions\" are terms that supplement the terms of\n     this License by making exceptions from one or more of its\n     conditions.  Additional permissions that are applicable to the\n     entire Program shall be treated as though they were included in\n     this License, to the extent that they are valid under applicable\n     law.  If additional permissions apply only to part of the Program,\n     that part may be used separately under those permissions, but the\n     entire Program remains governed by this License without regard to\n     the additional permissions.\n\n     When you convey a copy of a covered work, you may at your option\n     remove any additional permissions from that copy, or from any part\n     of it.  (Additional permissions may be written to require their own\n     removal in certain cases when you modify the work.)  You may place\n     additional permissions on material, added by you to a covered work,\n     for which you have or can give appropriate copyright permission.\n\n     Notwithstanding any other provision of this License, for material\n     you add to a covered work, you may (if authorized by the copyright\n     holders of that material) supplement the terms of this License\n     with terms:\n\n       a. Disclaiming warranty or limiting liability differently from\n          the terms of sections 15 and 16 of this License; or\n\n       b. Requiring preservation of specified reasonable legal notices\n          or author attributions in that material or in the Appropriate\n          Legal Notices displayed by works containing it; or\n\n       c. Prohibiting misrepresentation of the origin of that material,\n          or requiring that modified versions of such material be\n          marked in reasonable ways as different from the original\n          version; or\n\n       d. Limiting the use for publicity purposes of names of licensors\n          or authors of the material; or\n\n       e. Declining to grant rights under trademark law for use of some\n          trade names, trademarks, or service marks; or\n\n       f. Requiring indemnification of licensors and authors of that\n          material by anyone who conveys the material (or modified\n          versions of it) with contractual assumptions of liability to\n          the recipient, for any liability that these contractual\n          assumptions directly impose on those licensors and authors.\n\n     All other non-permissive additional terms are considered \"further\n     restrictions\" within the meaning of section 10.  If the Program as\n     you received it, or any part of it, contains a notice stating that\n     it is governed by this License along with a term that is a further\n     restriction, you may remove that term.  If a license document\n     contains a further restriction but permits relicensing or\n     conveying under this License, you may add to a covered work\n     material governed by the terms of that license document, provided\n     that the further restriction does not survive such relicensing or\n     conveying.\n\n     If you add terms to a covered work in accord with this section, you\n     must place, in the relevant source files, a statement of the\n     additional terms that apply to those files, or a notice indicating\n     where to find the applicable terms.\n\n     Additional terms, permissive or non-permissive, may be stated in\n     the form of a separately written license, or stated as exceptions;\n     the above requirements apply either way.\n\n  8. Termination.\n\n     You may not propagate or modify a covered work except as expressly\n     provided under this License.  Any attempt otherwise to propagate or\n     modify it is void, and will automatically terminate your rights\n     under this License (including any patent licenses granted under\n     the third paragraph of section 11).\n\n     However, if you cease all violation of this License, then your\n     license from a particular copyright holder is reinstated (a)\n     provisionally, unless and until the copyright holder explicitly\n     and finally terminates your license, and (b) permanently, if the\n     copyright holder fails to notify you of the violation by some\n     reasonable means prior to 60 days after the cessation.\n\n     Moreover, your license from a particular copyright holder is\n     reinstated permanently if the copyright holder notifies you of the\n     violation by some reasonable means, this is the first time you have\n     received notice of violation of this License (for any work) from\n     that copyright holder, and you cure the violation prior to 30 days\n     after your receipt of the notice.\n\n     Termination of your rights under this section does not terminate\n     the licenses of parties who have received copies or rights from\n     you under this License.  If your rights have been terminated and\n     not permanently reinstated, you do not qualify to receive new\n     licenses for the same material under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n     You are not required to accept this License in order to receive or\n     run a copy of the Program.  Ancillary propagation of a covered work\n     occurring solely as a consequence of using peer-to-peer\n     transmission to receive a copy likewise does not require\n     acceptance.  However, nothing other than this License grants you\n     permission to propagate or modify any covered work.  These actions\n     infringe copyright if you do not accept this License.  Therefore,\n     by modifying or propagating a covered work, you indicate your\n     acceptance of this License to do so.\n\n 10. Automatic Licensing of Downstream Recipients.\n\n     Each time you convey a covered work, the recipient automatically\n     receives a license from the original licensors, to run, modify and\n     propagate that work, subject to this License.  You are not\n     responsible for enforcing compliance by third parties with this\n     License.\n\n     An \"entity transaction\" is a transaction transferring control of an\n     organization, or substantially all assets of one, or subdividing an\n     organization, or merging organizations.  If propagation of a\n     covered work results from an entity transaction, each party to that\n     transaction who receives a copy of the work also receives whatever\n     licenses to the work the party's predecessor in interest had or\n     could give under the previous paragraph, plus a right to\n     possession of the Corresponding Source of the work from the\n     predecessor in interest, if the predecessor has it or can get it\n     with reasonable efforts.\n\n     You may not impose any further restrictions on the exercise of the\n     rights granted or affirmed under this License.  For example, you\n     may not impose a license fee, royalty, or other charge for\n     exercise of rights granted under this License, and you may not\n     initiate litigation (including a cross-claim or counterclaim in a\n     lawsuit) alleging that any patent claim is infringed by making,\n     using, selling, offering for sale, or importing the Program or any\n     portion of it.\n\n 11. Patents.\n\n     A \"contributor\" is a copyright holder who authorizes use under this\n     License of the Program or a work on which the Program is based.\n     The work thus licensed is called the contributor's \"contributor\n     version\".\n\n     A contributor's \"essential patent claims\" are all patent claims\n     owned or controlled by the contributor, whether already acquired or\n     hereafter acquired, that would be infringed by some manner,\n     permitted by this License, of making, using, or selling its\n     contributor version, but do not include claims that would be\n     infringed only as a consequence of further modification of the\n     contributor version.  For purposes of this definition, \"control\"\n     includes the right to grant patent sublicenses in a manner\n     consistent with the requirements of this License.\n\n     Each contributor grants you a non-exclusive, worldwide,\n     royalty-free patent license under the contributor's essential\n     patent claims, to make, use, sell, offer for sale, import and\n     otherwise run, modify and propagate the contents of its\n     contributor version.\n\n     In the following three paragraphs, a \"patent license\" is any\n     express agreement or commitment, however denominated, not to\n     enforce a patent (such as an express permission to practice a\n     patent or covenant not to sue for patent infringement).  To\n     \"grant\" such a patent license to a party means to make such an\n     agreement or commitment not to enforce a patent against the party.\n\n     If you convey a covered work, knowingly relying on a patent\n     license, and the Corresponding Source of the work is not available\n     for anyone to copy, free of charge and under the terms of this\n     License, through a publicly available network server or other\n     readily accessible means, then you must either (1) cause the\n     Corresponding Source to be so available, or (2) arrange to deprive\n     yourself of the benefit of the patent license for this particular\n     work, or (3) arrange, in a manner consistent with the requirements\n     of this License, to extend the patent license to downstream\n     recipients.  \"Knowingly relying\" means you have actual knowledge\n     that, but for the patent license, your conveying the covered work\n     in a country, or your recipient's use of the covered work in a\n     country, would infringe one or more identifiable patents in that\n     country that you have reason to believe are valid.\n\n     If, pursuant to or in connection with a single transaction or\n     arrangement, you convey, or propagate by procuring conveyance of, a\n     covered work, and grant a patent license to some of the parties\n     receiving the covered work authorizing them to use, propagate,\n     modify or convey a specific copy of the covered work, then the\n     patent license you grant is automatically extended to all\n     recipients of the covered work and works based on it.\n\n     A patent license is \"discriminatory\" if it does not include within\n     the scope of its coverage, prohibits the exercise of, or is\n     conditioned on the non-exercise of one or more of the rights that\n     are specifically granted under this License.  You may not convey a\n     covered work if you are a party to an arrangement with a third\n     party that is in the business of distributing software, under\n     which you make payment to the third party based on the extent of\n     your activity of conveying the work, and under which the third\n     party grants, to any of the parties who would receive the covered\n     work from you, a discriminatory patent license (a) in connection\n     with copies of the covered work conveyed by you (or copies made\n     from those copies), or (b) primarily for and in connection with\n     specific products or compilations that contain the covered work,\n     unless you entered into that arrangement, or that patent license\n     was granted, prior to 28 March 2007.\n\n     Nothing in this License shall be construed as excluding or limiting\n     any implied license or other defenses to infringement that may\n     otherwise be available to you under applicable patent law.\n\n 12. No Surrender of Others' Freedom.\n\n     If conditions are imposed on you (whether by court order,\n     agreement or otherwise) that contradict the conditions of this\n     License, they do not excuse you from the conditions of this\n     License.  If you cannot convey a covered work so as to satisfy\n     simultaneously your obligations under this License and any other\n     pertinent obligations, then as a consequence you may not convey it\n     at all.  For example, if you agree to terms that obligate you to\n     collect a royalty for further conveying from those to whom you\n     convey the Program, the only way you could satisfy both those\n     terms and this License would be to refrain entirely from conveying\n     the Program.\n\n 13. Use with the GNU Affero General Public License.\n\n     Notwithstanding any other provision of this License, you have\n     permission to link or combine any covered work with a work licensed\n     under version 3 of the GNU Affero General Public License into a\n     single combined work, and to convey the resulting work.  The terms\n     of this License will continue to apply to the part which is the\n     covered work, but the special requirements of the GNU Affero\n     General Public License, section 13, concerning interaction through\n     a network will apply to the combination as such.\n\n 14. Revised Versions of this License.\n\n     The Free Software Foundation may publish revised and/or new\n     versions of the GNU General Public License from time to time.\n     Such new versions will be similar in spirit to the present\n     version, but may differ in detail to address new problems or\n     concerns.\n\n     Each version is given a distinguishing version number.  If the\n     Program specifies that a certain numbered version of the GNU\n     General Public License \"or any later version\" applies to it, you\n     have the option of following the terms and conditions either of\n     that numbered version or of any later version published by the\n     Free Software Foundation.  If the Program does not specify a\n     version number of the GNU General Public License, you may choose\n     any version ever published by the Free Software Foundation.\n\n     If the Program specifies that a proxy can decide which future\n     versions of the GNU General Public License can be used, that\n     proxy's public statement of acceptance of a version permanently\n     authorizes you to choose that version for the Program.\n\n     Later license versions may give you additional or different\n     permissions.  However, no additional obligations are imposed on any\n     author or copyright holder as a result of your choosing to follow a\n     later version.\n\n 15. Disclaimer of Warranty.\n\n     THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\n     APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE\n     COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\"\n     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,\n     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE\n     RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.\n     SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL\n     NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n 16. Limitation of Liability.\n\n     IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\n     WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES\n     AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU\n     FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\n     CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE\n     THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA\n     BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\n     PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n     PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF\n     THE POSSIBILITY OF SUCH DAMAGES.\n\n 17. Interpretation of Sections 15 and 16.\n\n     If the disclaimer of warranty and limitation of liability provided\n     above cannot be given local legal effect according to their terms,\n     reviewing courts shall apply local law that most closely\n     approximates an absolute waiver of all civil liability in\n     connection with the Program, unless a warranty or assumption of\n     liability accompanies a copy of the Program in return for a fee.\n\n\nEND OF TERMS AND CONDITIONS\n===========================\n\nHow to Apply These Terms to Your New Programs\n=============================================\n\nIf you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these\nterms.\n\n   To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least the\n\"copyright\" line and a pointer to where the full notice is found.\n\n     ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.\n     Copyright (C) YEAR NAME OF AUTHOR\n\n     This program is free software: you can redistribute it and/or modify\n     it under the terms of the GNU General Public License as published by\n     the Free Software Foundation, either version 3 of the License, or (at\n     your option) any later version.\n\n     This program is distributed in the hope that it will be useful, but\n     WITHOUT ANY WARRANTY; without even the implied warranty of\n     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n     General Public License for more details.\n\n     You should have received a copy of the GNU General Public License\n     along with this program.  If not, see `http://www.gnu.org/licenses/'.\n\n   Also add information on how to contact you by electronic and paper\nmail.\n\n   If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n     PROGRAM Copyright (C) YEAR NAME OF AUTHOR\n     This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n     This is free software, and you are welcome to redistribute it\n     under certain conditions; type `show c' for details.\n\n   The hypothetical commands `show w' and `show c' should show the\nappropriate parts of the General Public License.  Of course, your\nprogram's commands might be different; for a GUI interface, you would\nuse an \"about box\".\n\n   You should also get your employer (if you work as a programmer) or\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  For more information on this, and how to apply and follow\nthe GNU GPL, see `http://www.gnu.org/licenses/'.\n\n   The GNU General Public License does not permit incorporating your\nprogram into proprietary programs.  If your program is a subroutine\nlibrary, you may consider it more useful to permit linking proprietary\napplications with the library.  If this is what you want to do, use the\nGNU Lesser General Public License instead of this License.  But first,\nplease read `http://www.gnu.org/philosophy/why-not-lgpl.html'.\n"
  },
  {
    "path": "test/pkg/mfile-minimal-test/DESCRIPTION",
    "content": "Name: mfile-minimal-test\nVersion: 0.1.0\nDate: 2017-12-08\nAuthor: hopefully various authors\nMaintainer: hopefully some of those authors.\nTitle: Example Minimal Package\nDescription: Minimal package structure with only m-files.\nDepends: octave (>= 4.2.1)\nLicense: GPLv3+\nCategories: Test\n# BuildRequires:\n# SystemRequirements:\n# Url: external homepage\n"
  },
  {
    "path": "test/pkg/mfile-minimal-test/inst/example_mfile.m",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This program is free software; you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as\n## published by the Free Software Foundation; either version 3 of the\n## License, or (at your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n## General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with this program; if not, see <http://www.gnu.org/licenses/>.\n\n## -*- texinfo -*-\n## @deftypefn {Function File} {@var{ret} =} example_mfile (@var{arg})\n## Placeholder for an mfile function.\n##\n## @var{arg}: argument. @var{ret}: returned value.\n##\n## Although this file is so short, a license text is contained as an\n## example.\n##\n## @seealso{example_open, example_close, example_do_something}\n## @end deftypefn\n\nfunction ret = example_mfile (arg)\n\n  if (nargin () != 1)\n    print_usage ();\n  endif\n\n  ret = arg;\n\nendfunction\n"
  },
  {
    "path": "test/pkg/module.mk",
    "content": "pkg_TEST_FILES = \\\n    %reldir%/pkg.tst \\\n    %reldir%/mfile-basic-test/INDEX \\\n    %reldir%/mfile-basic-test/NEWS \\\n    %reldir%/mfile-basic-test/DESCRIPTION \\\n    %reldir%/mfile-basic-test/doc/macros.texi \\\n    %reldir%/mfile-basic-test/doc/example-package.txi \\\n    %reldir%/mfile-basic-test/COPYING \\\n    %reldir%/mfile-basic-test/inst/example_mfile.m \\\n    %reldir%/mfile-minimal-test/DESCRIPTION \\\n    %reldir%/mfile-minimal-test/COPYING \\\n    %reldir%/mfile-minimal-test/inst/example_mfile.m\n\nTEST_FILES += $(pkg_TEST_FILES)\n"
  },
  {
    "path": "test/pkg/pkg.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2018-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n############################################################\n## Test suite for pkg.m\n## Tests are organized first by action, and then by options.\n## All actions should be tested, and ideally all options are tested.\n############################################################\n\n%!shared old_prefix, old_archprefix, old_local_list, old_global_list, prefix, restorecfg, restorecache, restoreglobalcache, rmtmpdir, mfile_pkg_name, mfile_pkg_tgz\n\n%!function test_cleanup (prefix)\n%! confirm_recursive_rmdir (0, \"local\");\n%! sts = rmdir (prefix, \"s\");\n%!endfunction\n\n%!testif HAVE_Z\n%! ## Do all tests in a temporary directory\n%! [old_prefix, old_archprefix] = pkg (\"prefix\");\n%! restorecfg = onCleanup (@() pkg (\"prefix\", old_prefix, old_archprefix));\n%! old_local_list = pkg (\"local_list\");\n%! restorecache = onCleanup (@() pkg (\"local_list\", old_local_list));\n%! old_global_list = pkg (\"global_list\");\n%! restoreglobalcache = onCleanup (@() pkg (\"global_list\", old_global_list));\n%! prefix = tempname ();\n%! [status] = mkdir (prefix);\n%! if (! status)\n%!   error (\"pkg.tst: Could not create temporary directory for pkg testing\");\n%!   return;  # abort further testing\n%! endif\n%! pkg (\"prefix\", prefix, prefix);\n%! pkg (\"local_list\", fullfile (prefix, \"octave_packages\"));\n%! pkg (\"global_list\", fullfile (prefix, \"octave_packages\"));\n%! rmtmpdir = @onCleanup (@() test_cleanup (prefix));\n%!\n%! ## Create tar.gz file packages of testing directories in prefix directory\n%! mfile_pkg_name = {\"mfile-basic-test\", \"mfile-minimal-test\"};\n%! mfile_pkg_tar = fullfile (prefix, strcat (mfile_pkg_name, \".tar\"));\n%! mfile_pkg_tgz = strcat (mfile_pkg_tar, \".gz\");\n%! for i = 1:numel (mfile_pkg_name)\n%!   tar (mfile_pkg_tar{i}, mfile_pkg_name{i});\n%!   gzip (mfile_pkg_tar{i});\n%! endfor\n\n## Avoids printing to stdout when installing\n%!function silent_pkg_install (varargin)\n%!  evalc ([\"pkg install\", sprintf(\" %s\", varargin{:})]);\n%!endfunction\n\n## Action install/uninstall\n%!testif HAVE_Z\n%! for i = 1:numel (mfile_pkg_name)\n%!   silent_pkg_install (mfile_pkg_tgz{i});\n%!   if (isunix ())\n%!     system ([\"chmod -Rf u+w '\" prefix \"'\"]);   ## FIXME: Work around bug #53578\n%!   endif\n%!   pkg (\"uninstall\", mfile_pkg_name{i});\n%! endfor\n%!\n%!error pkg (\"install\", \"./nonexistent.zip\")\n\n## -local\n%!testif HAVE_Z\n%! for i = 1:numel (mfile_pkg_name)\n%!   silent_pkg_install (\"-local\", mfile_pkg_tgz{i});\n%!   if (isunix)\n%!     system ([\"chmod -Rf u+w '\" prefix \"'\"]);   ## FIXME: Work around bug #53578\n%!   endif\n%!   pkg (\"uninstall\", mfile_pkg_name{i});\n%! endfor\n\n## -forge (need check for options?)\n## FIXME: Need test\n## We do not test this yet ... fails if no internet connection\n## use dataframe which is an mfile only package\n#%!test\n#%! silent_pkg_install (\"-forge\", \"dataframe\");\n#%! pkg (\"uninstall\", \"dataframe\");\n\n## -nodeps\n## FIXME: Need test\n\n## -verbose\n## FIXME: Need test\n\n## Action load/unload (within install/uninstall)\n%!testif HAVE_Z\n%! save_default_options (\"-binary\", \"local\");\n%! for i = 1:numel (mfile_pkg_name)\n%!   name = mfile_pkg_name{i};\n%!   silent_pkg_install (\"-local\", mfile_pkg_tgz{i});\n%!   unwind_protect\n%!     pkg (\"load\", name);\n%!     pkg (\"unload\", name);\n%!   unwind_protect_cleanup\n%!     if (isunix)\n%!       system ([\"chmod -Rf u+w '\" prefix \"'\"]); ## FIXME: Work around bug #53578\n%!     endif\n%!     pkg (\"uninstall\", name);\n%!   end_unwind_protect\n%! endfor\n%!\n%!error <package foobar is not installed> pkg (\"load\", \"foobar\")\n\n## -nodeps\n## FIXME: Need test\n\n## -verbose\n## FIXME: Need test\n\n## Action list\n%!test\n%! [user_packages, system_packages] = pkg (\"list\");\n\n## -forge\n#%!test\n#%! oct_forge_pkgs = pkg (\"list\", \"-forge\");\n\n## Action describe\n%!testif HAVE_Z\n%! silent_pkg_install (\"-local\", mfile_pkg_tgz{1});\n%! [desc, flag] = pkg (\"describe\", mfile_pkg_name{1});\n%! ## FIXME: this only tests that the describe command runs,\n%! ##        not that the output is in anyway correct.\n%! if (isunix)\n%!   system ([\"chmod -Rf u+w '\" prefix \"'\"]);     ## FIXME: Work around bug #53578\n%! endif\n%! pkg (\"uninstall\", mfile_pkg_name{1});\n\n## -verbose\n## FIXME: Need test\n\n## Action prefix\n%!test\n%! pfx_old = pkg (\"prefix\");\n%! unwind_protect\n%!   pfx_new = pkg (\"prefix\", pwd ());\n%!   assert (pfx_new, pwd ());\n%! unwind_protect_cleanup\n%!   pfx = pkg (\"prefix\", pfx_old);\n%! end_unwind_protect\n\n## Action build\n## FIXME: Need test\n## pkg build -verbose /tmp image-*\n\n## Action rebuild\n## FIXME: Need test\n## pkg rebuild signal\n\n## Future commands\n%!error pkg (\"whereis\", \"myfunc.m\")\n%!error pkg (\"whereis\", \"-forge\", \"myfunc.m\")\n\n############################################################\n## End of Tests\n############################################################\n"
  },
  {
    "path": "test/prefer.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! m = [3 2];\n%! assert (all (m == (3:-1:2)));\n\n%!test\n%! m = [3,\n%! 2];\n%! assert (all (m == (3:-1:2)'));\n\n%!test\n%! a = 2;\n%! assert ([a - 1], 1);\n\n%!test\n%! m = [3,2];\n%! fail (\"[m ']\");\n\n%!assert (all ([3 2] == (3:-1:2)))\n\n%!assert (all ([3, 2] == (3:-1:2)))\n\n%!test\n%! m = [3,2];\n%! assert (all ([m (1)] == (3:-1:1)));\n\n%!test\n%! m = [3,2];\n%! assert ([m(1)],3);\n\n%!test\n%! a = 2;\n%! assert ([a- 1], 1);\n\n%!test\n%! a = 1;\n%! assert (all ([a -1] == (1:-2:-1)));\n\n%!test\n%! wsn = warning (\"query\", \"Octave:str-to-num\");\n%! warning (\"off\", \"Octave:str-to-num\");\n%! assert (\"d\" + 0, 100);\n%! warning (wsn.state, \"Octave:str-to-num\");\n\n%!test\n%! wsn = warning (\"query\", \"Octave:str-to-num\");\n%! warning (\"on\", \"Octave:str-to-num\");\n%! fail (\"'d' + 0\", \"warning\");\n%! warning (wsn.state, \"Octave:str-to-num\");\n\n%!test\n%! wir = warning (\"query\", \"Octave:imag-to-real\");\n%! warning (\"off\", \"Octave:imag-to-real\");\n%! assert (eye (1+i), 1);\n%! warning (wir.state, \"Octave:imag-to-real\");\n\n%!test\n%! wir = warning (\"query\", \"Octave:imag-to-real\");\n%! warning (\"on\", \"Octave:imag-to-real\");\n%! fail (\"eye (1+i)\", \"warning\");\n%! warning (wir.state, \"Octave:imag-to-real\");\n\n%!test\n%! wrre = warning (\"query\", \"Octave:resize-on-range-error\");\n%! warning (\"off\", \"Octave:resize-on-range-error\");\n%! clear a;\n%! a(2) = 1; a(3) = 2;\n%! assert (all (a == [0,1,2]));\n%! warning (wrre.state, \"Octave:resize-on-range-error\");\n\n%!test\n%! clear a;\n%! a(1) = 1; a(2) = 2;\n%! assert (all (a == [1,2]));\n\n%!test\n%! ped = print_empty_dimensions ();\n%! print_empty_dimensions (0);\n%! a = cell (1, 1);\n%! b = type (\"-q\", \"a\");\n%! assert (! isempty (strfind (b{1}, \"[]\")));\n%! assert (isempty (strfind (b{1} ,\"[](0x0)\")));\n%! print_empty_dimensions (ped);\n\n%!test\n%! ped = print_empty_dimensions ();\n%! print_empty_dimensions (1);\n%! a = cell (1, 1);\n%! b = type (\"-q\", \"a\");\n%! assert (! isempty (strfind (b{1}, \"[](0x0)\")));\n%! print_empty_dimensions (ped);\n\n%!assert (all (size (inv ([])) == [0, 0]))\n\n%!assert (all (svd ([]) == zeros (0, 1)))\n\n%!test\n%! sp = save_precision ();\n%! save_precision (1);\n%! x = pi;\n%! nm = tempname ();\n%! save (\"-text\", nm, \"x\");\n%! clear x;\n%! load (nm);\n%! unlink (nm);\n%! assert (x,3);\n%! save_precision (sp);\n\n%!test\n%! sp = save_precision ();\n%! save_precision (5);\n%! x = pi;\n%! nm = tempname ();\n%! save (\"-text\", nm, \"x\");\n%! clear x;\n%! load (nm);\n%! unlink (nm);\n%! assert (x, 3.1416);\n%! save_precision (sp);\n\n%% FIXME: How to capture standard output for comparison?\n%!function f ()\n%! 1\n%!endfunction\n%!#test\n%! sf = silent_functions ();\n%! silent_functions (0);\n%! f\n%! assert (??);\n%! silent_functions (sf);\n\n%% FIXME: Same problem as above!!!\n%!function f ()\n%! 1\n%!endfunction\n%!#test\n%! sf = silent_functions ();\n%! silent_functions (1);\n%! f\n%! assert (??);\n%! silent_functions (sf);\n\n%!test\n%! wndz = warning (\"query\", \"Octave:neg-dim-as-zero\");\n%! warning (\"on\", \"Octave:neg-dim-as-zero\");\n%! fail (\"eye (-1) == []\", \"warning\", \"converting negative dimension\");\n%! warning (wndz.state, \"Octave:neg-dim-as-zero\");\n\n%!test\n%! wndz = warning (\"query\", \"Octave:neg-dim-as-zero\");\n%! warning (\"off\", \"Octave:neg-dim-as-zero\");\n%! assert (all (size (eye (-1)) == [0, 0]));\n%! warning (wndz.state, \"Octave:neg-dim-as-zero\");\n\n%!test\n%! watv = warning (\"query\", \"Octave:assign-as-truth-value\");\n%! warning (\"on\", \"Octave:assign-as-truth-value\");\n%! fail (\"if (x = 1) 1; endif\", \"warning\", \"assignment used as truth value\");\n%! warning (watv.state, \"Octave:assign-as-truth-value\");\n\n%!test\n%! assert (isinf (1/0));\n\n%!test\n%! a = 1;\n%! b = 0;\n%! assert (isinf (a/b));\n"
  },
  {
    "path": "test/private-functions/fcn.m",
    "content": "function retval = fcn ()\n  ## Call private function.\n  assert (pfcn1 (), \"pfcn1\");\n  ## Execute private script.\n  a = \"\";\n  ascript;\n  assert (a, \"ascript\");\n  retval = true;\nendfunction\n"
  },
  {
    "path": "test/private-functions/module.mk",
    "content": "private_functions_TEST_FILES = \\\n  %reldir%/fcn.m \\\n  %reldir%/private-functions.tst \\\n  %reldir%/private/ascript.m \\\n  %reldir%/private/bscript.m \\\n  %reldir%/private/pfcn1.m \\\n  %reldir%/private/pfcn2.m\n\nTEST_FILES += $(private_functions_TEST_FILES)\n"
  },
  {
    "path": "test/private-functions/private/ascript.m",
    "content": "a = \"ascript\";\n\nb = \"\";\nbscript;\nassert (b, \"bscript\");\n"
  },
  {
    "path": "test/private-functions/private/bscript.m",
    "content": "b = \"bscript\";\n"
  },
  {
    "path": "test/private-functions/private/pfcn1.m",
    "content": "function r = pfcn1 ()\n  r = \"pfcn1\";\n  a = \"\";\n  ascript;\n  assert (a, \"ascript\");\n  assert (pfcn2 (), \"pfcn2\");\nendfunction\n"
  },
  {
    "path": "test/private-functions/private/pfcn2.m",
    "content": "function r = pfcn2 ()\n  r = \"pfcn2\";\n  a = \"\";\n  ascript;\n  assert (a, \"ascript\");\nendfunction\n"
  },
  {
    "path": "test/private-functions/private-functions.tst",
    "content": "%!assert (fcn ())\n"
  },
  {
    "path": "test/publish/module.mk",
    "content": "publish_TEST_FILES = \\\n  %reldir%/publish.tst \\\n  %reldir%/test_script.m \\\n  %reldir%/test_script_code_only.m \\\n  %reldir%/test_script_empty.m \\\n  %reldir%/test_script_example.m \\\n  %reldir%/test_script_head_only.m\n\nTEST_FILES += $(publish_TEST_FILES)\n"
  },
  {
    "path": "test/publish/publish.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## test for publish\n\n%!test\n%! visibility = get (0, \"defaultfigurevisible\");\n%! toolkit = graphics_toolkit ();\n%! unwind_protect\n%!   if (! strcmp (graphics_toolkit (), \"qt\"))\n%!     try\n%!       graphics_toolkit (\"gnuplot\");\n%!     catch\n%!       ## The system doesn't support gnuplot for drawing hidden\n%!       ## figures.  Just return and have test marked as passing.\n%!       return;\n%!     end_try_catch\n%!   endif\n%!   set (0, \"defaultfigurevisible\", \"off\");\n%!\n%!   scripts = dir (\"test_script*.m\");\n%!   tmpDir = tempname ();\n%!   mkdir (tmpDir);\n%!   opts.outputDir = tmpDir;\n%!   for fname = {scripts.name}\n%!     publish (fname{1}, opts);\n%!   endfor\n%!   confirm_recursive_rmdir (false, \"local\");\n%!   sts = rmdir (tmpDir, \"s\");\n%! unwind_protect_cleanup\n%!   set (0, \"defaultfigurevisible\", visibility);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n\n## test for grabcode\n\n%!test\n%! visibility = get (0, \"defaultfigurevisible\");\n%! toolkit = graphics_toolkit ();\n%! unwind_protect\n%!   if (! strcmp (graphics_toolkit (), \"qt\"))\n%!     try\n%!       graphics_toolkit (\"gnuplot\");\n%!     catch\n%!       ## The system doesn't support gnuplot for drawing hidden\n%!       ## figures.  Just return and have test marked as passing.\n%!       return;\n%!     end_try_catch\n%!   endif\n%!   set (0, \"defaultfigurevisible\", \"off\");\n%!   ## Create temporary directory\n%!   tmpDir = tempname ();\n%!   mkdir (tmpDir);\n%!   opts.outputDir = tmpDir;\n%!   ## Call publish and grabcode\n%!   publish (\"test_script.m\", opts);\n%!   str1 = fileread (\"test_script.m\");\n%!   str2 = grabcode (fullfile (tmpDir, \"test_script.html\"));\n%!   confirm_recursive_rmdir (false, \"local\");\n%!   sts = rmdir (tmpDir, \"s\");\n%!   ## Canonicalize strings\n%!   str1 = strjoin (deblank (strsplit (str1, \"\\n\")), \"\\n\");\n%!   str2 = strjoin (deblank (strsplit (str2, \"\\n\")), \"\\n\");\n%!   assert (hash (\"md5\", str1), hash (\"md5\", str2));\n%! unwind_protect_cleanup\n%!   set (0, \"defaultfigurevisible\", visibility);\n%!   graphics_toolkit (toolkit);\n%! end_unwind_protect\n"
  },
  {
    "path": "test/publish/test_script.m",
    "content": "%% Headline\n% Headline description with a link\n% <https://www.gnu.org/software/octave |*GNU Octave*| Homepage>\n%\n% Spanning some lines and blanks.\n%\n\n%%\n\ndisp (\"First recognized Octave code after %%\")\n\n%% SECTION TITLE\n% DESCRIPTIVE TEXT\n\n%%% SECTION TITLE WITHOUT SECTION BREAK\n% For Matlab compatibility\n\n## SECTION TITLE\n# DESCRIPTIVE TEXT\n\n### SECTION TITLE WITHOUT SECTION BREAK\n# Should not work in Octave style\n# and should be interpreted as usual Octave code\n\n%%\n%\n\n##\n#\n\n% some real comment\ni = 0:2*pi\n\n# some real comment\ny = sin (i)\n\n%%\n%\n% Content without head.\n%\n\n% some real comment and split code block\nx = 0:2*pi\n\n# some real comment and split code block\ny = sin (x)\n\n%%\n%\n\n% reusing old values\ny = cos (i)\n\n# some real comment and split code block\ny = cos (x)\n\n%% Text formatting\n% PLAIN TEXT _ITALIC TEXT_ *BOLD TEXT* |MONOSPACED TEXT|\n% |MONOSPACED TEXT| PLAIN TEXT _ITALIC TEXT_ *BOLD TEXT*\n% *BOLD TEXT* |MONOSPACED TEXT| PLAIN TEXT _ITALIC TEXT_\n% _ITALIC TEXT_ *BOLD TEXT* |MONOSPACED TEXT| PLAIN TEXT\n% Trademarks:\n% TEXT(TM)\n% TEXT(R)\n%\n% Good inlining should work\n% *BOLD _ITALIC |MONOSPACED| TEXT_*\n% _ITALIC *BOLD |MONOSPACED| TEXT*_\n% |MONOSPACED *BOLD _ITALIC_ TEXT*|\n%\n% Bad inlining should not work |MONOSPACED *BOLD TEXT|*\n\n% figure code\nplot (x,y)\n\n% another plot\nfigure ()\nplot (y,x)\n\n## Text formatting\n# PLAIN TEXT _ITALIC TEXT_ *BOLD TEXT* |MONOSPACED TEXT|\n# |MONOSPACED TEXT| PLAIN TEXT _ITALIC TEXT_ *BOLD TEXT*\n# *BOLD TEXT* |MONOSPACED TEXT| PLAIN TEXT _ITALIC TEXT_\n# _ITALIC TEXT_ *BOLD TEXT* |MONOSPACED TEXT| PLAIN TEXT\n# Trademarks:\n# TEXT(TM)\n# TEXT(R)\n#\n# Good inlining should work\n# *BOLD _ITALIC |MONOSPACED| TEXT_*\n# _ITALIC *BOLD |MONOSPACED| TEXT*_\n# |MONOSPACED *BOLD _ITALIC_ TEXT*|\n#\n# Bad inlining should not work |MONOSPACED *BOLD TEXT|*\n\n% again another plot\nplot (x,y)\n\n%% *BOLD*, _ITALIC_, |MONOSPACED| <http://www.someURL.com *Header* (R)>\n%\n\n## *BOLD*, _ITALIC_, |MONOSPACED| <http://www.someURL.com *Header* (R)>\n#\n\n%% Bulleted List\n%\n% * BULLETED ITEM 1\n% * BULLETED ITEM 2\n% * BULLETED ITEM 3 *BOLD*\n% * BULLETED ITEM 4 <http://www.someURL.com>\n%\n\n## Bulleted List\n#\n# * BULLETED ITEM 1\n# * BULLETED ITEM 2\n# * BULLETED ITEM 3 *BOLD*\n# * BULLETED ITEM 4 <http://www.someURL.com>\n#\n\n%% Numbered List\n%\n% # NUMBERED ITEM 1\n% # NUMBERED ITEM 2\n% # NUMBERED ITEM 3 *BOLD*\n% # NUMBERED ITEM 4 <http://www.someURL.com>\n%\n\n## Numbered List\n#\n# # NUMBERED ITEM 1\n# # NUMBERED ITEM 2\n# # NUMBERED ITEM 3 *BOLD*\n# # NUMBERED ITEM 4 <http://www.someURL.com>\n#\n\n%%\n%\n%  PREFORMATTED\n%  TEXT\n%\n\n##\n#\n#  PREFORMATTED\n#  TEXT\n#\n\n%% GNU Octave Code\n%\n%   for i = 1:10\n%     disp (x)\n%   endfor\n%\n\n## GNU Octave Code\n#\n#   for i = 1:10\n#     disp (x)\n#   endfor\n#\n\n%% External File Content\n%\n% <include>test_script_code_only.m</include>\n%\n\n## External File Content\n#\n# <include>test_script_code_only.m</include>\n#\n\n%% External Graphic\n%\n% <<test_script-1.png>>\n%\n\n## External Graphic\n#\n# <<test_script-1.png>>\n#\n\n%% Inline LaTeX\n% This should be escaped properly: \\, {, }, &, %, #, _, ~, ^, <, >\n%\n% $f(n) = n^5 + 4n^2 + 2 |_{n=17}$\n%\n% $$f(n) = n^5 + 4n^2 + 2 |_{n=17}$$\n%\n% $$e^x = \\lim\\limits_{n\\rightarrow\\infty}\\left(1+\\dfrac{x}{n}\\right)^{n}$$\n%\n\n## Inline LaTeX\n# This should be escaped properly: \\, {, }, &, %, #, _, ~, ^, <, >\n#\n# $f(n) = n^5 + 4n^2 + 2 |_{n=17}$\n#\n# $$f(n) = n^5 + 4n^2 + 2 |_{n=17}$$\n#\n# $$e^x = \\lim\\limits_{n\\rightarrow\\infty}\\left(1+\\dfrac{x}{n}\\right)^{n}$$\n#\n\n%% Links\n% <https://www.gnu.org/software/octave>\n% <https://www.gnu.org/software/octave GNU Octave Homepage>\n% <octave:plot DISPLAYED TEXT FOR PLOT FUNCTION>\n% <octave:abs Nested markup and newline\n% PLAIN TEXT(TM) _ITALIC TEXT_(R) *BOLD TEXT* |MONOSPACED TEXT|>\n% <https://www.gnu.org/software/octave Nested markup and newline\n% PLAIN TEXT(TM) _ITALIC TEXT_(R) *BOLD TEXT* |MONOSPACED TEXT|>\n%\n\n## Links\n# <https://www.gnu.org/software/octave>\n# <https://www.gnu.org/software/octave GNU Octave Homepage>\n# <octave:plot DISPLAYED TEXT FOR PLOT FUNCTION>\n# <octave:abs Nested markup and newline\n# PLAIN TEXT(TM) _ITALIC TEXT_(R) *BOLD TEXT* |MONOSPACED TEXT|>\n# <https://www.gnu.org/software/octave Nested markup and newline\n# PLAIN TEXT(TM) _ITALIC TEXT_(R) *BOLD TEXT* |MONOSPACED TEXT|>\n#\n\n%% Code with HTML/LaTeX special chars\n%\n\nfunction ret = foo (a, b)\n  ret = (a > b) && (a < b^a);\nendfunction\nsprintf (\"(a > b) && (a < b^a) = %f\", foo (0, 1))\n\n%% HTML Markup & < > \"\n% This should be escaped properly: & < > \"\n%\n% The HTML entity should remain visible: &amp; &lt; &gt; &quot;\n%\n% The HTML entity should remain visible: |&amp;| |&lt;| |&gt;| |&quot;|\n%\n\n## HTML Markup & < > \"\n# This should be escaped properly: & < > \"\n#\n# The HTML entity should remain visible: &amp; &lt; &gt; &quot;\n#\n# The HTML entity should remain visible: |&amp;| |&lt;| |&gt;| |&quot;|\n#\n\n%% HTML block markup\n% <html>\n% <table><tr>\n% <td style=\"border: 1px solid black;\">one</td>\n% <td style=\"border: 1px solid black;\">two</td>\n% </tr>\n% </table>\n% </html>\n%\n\n## HTML block markup\n# <html>\n# <table>\n# <tr>\n# <td style=\"border: 1px solid black;\">one</td>\n# <td style=\"border: 1px solid black;\">two</td>\n# </tr>\n# </table>\n# </html>\n#\n\n%% HTML block markup with empty lines\n% <html>\n% <table><tr>\n% <td style=\"border: 1px solid black;\">one</td>\n% <td style=\"border: 1px solid black;\">two</td></tr>\n% </table>\n%\n% and some text.\n% </html>\n%\n\n## HTML block markup with empty lines\n# <html>\n# <table>\n# <tr>\n# <td style=\"border: 1px solid black;\">one</td>\n# <td style=\"border: 1px solid black;\">two</td>\n# </tr>\n# </table>\n#\n# and some text.\n# </html>\n#\n\n%% LaTeX block markup\n% <latex>\n% \\begin{equation}\n% \\begin{pmatrix}\n% 1 & 2 \\\\ 3 & 4\n% \\end{pmatrix}\n% \\end{equation}\n% </latex>\n%\n\n## LaTeX block markup\n# <latex>\n# \\begin{equation}\n# \\begin{pmatrix}\n# 1 & 2 \\\\ 3 & 4\n# \\end{pmatrix}\n# \\end{equation}\n# </latex>\n#\n\n%% LaTeX block markup with empty lines\n% <latex>\n% Some text\n%\n% \\begin{equation}\n% \\begin{pmatrix}\n% 1 & 2 \\\\ 3 & 4\n% \\end{pmatrix}\n% \\end{equation}\n% </latex>\n%\n\n## LaTeX block markup with empty lines\n# <latex>\n# Some text\n#\n# \\begin{equation}\n# \\begin{pmatrix}\n# 1 & 2 \\\\ 3 & 4\n# \\end{pmatrix}\n# \\end{equation}\n# </latex>\n#\n\n%% Long void\n%\n%\n%\n%\n%\n%\n%\n%\n% content\n%\n%\n%\n%\n%\n%\n%\n\n%%\n%\n%\n%\n%\n%\n%\n%\n%\n% and continued\n%\n%\n%\n%\n%\n%\n%\n\n## Long void\n#\n#\n#\n#\n#\n#\n#\n# content\n#\n#\n#\n#\n#\n#\n#\n#\n#\n#\n\n##\n#\n#\n#\n#\n#\n#\n#\n# and continued\n#\n#\n#\n#\n#\n#\n#\n#\n#\n#\n"
  },
  {
    "path": "test/publish/test_script_code_only.m",
    "content": "\n% Code only with a very very very very very very very very very very looong line\n%\nx = 5;\n\nfor i = 1:5\n  x += i;  # Might be useful \"perhaps\"\nendfor\n\n%{\nMultiline comment with keyword if \"if\" and 'if'\n%}\n\nif (x == 'a')\n  y = sin (x);\nendif\n\n#{\nMultiline comment with keyword if \"if\" and 'if'\n#}\n\nstr = \"some % string \\\" ' with %{\";\nstr2 = 'another % string '' \" with %{';\n%\n"
  },
  {
    "path": "test/publish/test_script_empty.m",
    "content": ""
  },
  {
    "path": "test/publish/test_script_example.m",
    "content": "%% Headline title\n%\n% Some *bold*, _italic_, or |monospaced| Text with\n% a <https://www.octave.org link to GNU Octave>.\n%%\n\n# \"Real\" Octave commands to be evaluated\nsombrero ()\n\n## Octave comment style supported as well\n#\n# * Bulleted list item 1\n# * Bulleted list item 2\n#\n# # Numbered list item 1\n# # Numbered list item 2\n"
  },
  {
    "path": "test/publish/test_script_head_only.m",
    "content": "%% Headline\n% Headline description.\n% about some lines no blanks\n%%\n"
  },
  {
    "path": "test/range.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Test values of range\n\n%!assert (full (1:9), [ 1 2 3 4 5 6 7 8 9 ])\n%!assert (full (1:0.4:3), [ 1.0 1.4 1.8 2.2 2.6 3.0 ])\n%!assert (full (9:1), zeros (1,0))\n%!assert (full (9:-1:1), [ 9 8 7 6 5 4 3 2 1 ])\n%!assert (full (1:-1:9), zeros (1,0))\n%!assert (full (1:1:1), 1)\n%!test\n%! warning ('off', 'Octave:colon-complex-argument', 'local');\n%! assert (full (i:2i:10i), zeros (1,0));\n\n## Test mixing integer range with other types\n\n%!shared expect, r, z\n%! expect = [ 1 2 3 4 5 6 7 8 9\n%!            0 0 0 0 0 0 0 0 0 ];\n%! z = zeros (1,9);\n%! r = 1:9;\n\n%!assert ([ r ; z                  ], expect)\n%!assert ([ r ; single(z)          ], single (expect))\n%!assert ([ r ; logical(z)         ], expect)\n%!assert ([ r ; sparse(z)          ], sparse (expect))\n%!assert ([ r ; sparse(logical(z)) ], sparse (expect))\n\n%!assert ([ r ; int8(z)            ], int8 (expect))\n%!assert ([ r ; int16(z)           ], int16 (expect))\n%!assert ([ r ; int32(z)           ], int32 (expect))\n%!assert ([ r ; int64(z)           ], int64 (expect))\n%!assert ([ r ; uint8(z)           ], uint8 (expect))\n%!assert ([ r ; uint16(z)          ], uint16 (expect))\n%!assert ([ r ; uint32(z)          ], uint32 (expect))\n%!assert ([ r ; uint64(z)          ], uint64 (expect))\n\n## Test mixing non-integer range with other types\n\n%!shared expect, r, z\n%! expect = [ 1.0 1.4 1.8 2.2 2.6 3.0\n%!            0   0   0   0   0   0   ];\n%! z = zeros (1,6);\n%! r = 1:0.4:3;\n\n%!assert ([ r ; z                  ], expect)\n%!assert ([ r ; single(z)          ], single (expect))\n%!assert ([ r ; logical(z)         ], expect)\n%!assert ([ r ; sparse(z)          ], sparse (expect))\n%!assert ([ r ; sparse(logical(z)) ], sparse (expect))\n\n%!assert ([ r ; int8(z)            ], int8 (expect))\n%!assert ([ r ; int16(z)           ], int16 (expect))\n%!assert ([ r ; int32(z)           ], int32 (expect))\n%!assert ([ r ; int64(z)           ], int64 (expect))\n%!assert ([ r ; uint8(z)           ], uint8 (expect))\n%!assert ([ r ; uint16(z)          ], uint16 (expect))\n%!assert ([ r ; uint32(z)          ], uint32 (expect))\n%!assert ([ r ; uint64(z)          ], uint64 (expect))\n\n## Test corner cases of ranges (base and limit)\n\n%!shared r, rrev, rneg\n%! r = -0:3;\n%! rrev = 3:-1:-0;\n%! rneg = -3:-0;\n\n%!assert (full (r), [-0 1 2 3])\n%!assert (signbit (full (r)), logical ([1 0 0 0]))\n%!assert (r(1), -0)\n%!assert (signbit (r(1)), true)\n%!assert (signbit (r(1:2)), logical ([1 0]))\n%!assert (signbit (r(2:-1:1)), logical ([0 1]))\n%!assert (signbit (r([2 1 1 3])), logical ([0 1 1 0]))\n\n%!assert (full (rrev), [3 2 1 -0])\n%!assert (signbit (full (rrev)), logical ([0 0 0 1]))\n%!assert (rrev(4), -0)\n%!assert (signbit (rrev(4)), true)\n%!assert (signbit (rrev(3:4)), logical ([0 1]))\n%!assert (signbit (rrev(4:-1:3)), logical ([1 0]))\n%!assert (signbit (rrev([1 4 4 2])), logical ([0 1 1 0]))\n\n%!assert (min (r), -0)\n%!assert (signbit (min (r)), true)\n%!assert (min (rrev), -0)\n%!assert (signbit (min (rrev)), true)\n\n%!assert (max (rneg), -0)\n%!assert (signbit (max (rneg)), true)\n\n%!assert (sort (r, \"descend\"), [3 2 1 -0])\n%!assert (signbit (sort (r, \"descend\")), logical ([0 0 0 1]))\n%!assert (signbit (sort (rrev, \"ascend\")), logical ([1 0 0 0]))\n\n## Test mathematical operations (also, non-finite values and 0)\n%!shared r\n%! r = 1:5;\n\n%!assert (-r, -1:-1:-5)\n%!assert (1 + r, 2:6)\n%!assert (Inf + r, Inf (1,5))\n%!assert (NaN + r, NaN (1,5))\n%!assert (r + 1, 2:6)\n%!assert (r + Inf, Inf (1,5))\n%!assert (r + NaN, NaN (1,5))\n%!assert (1 - r, 0:-1:-4)\n%!assert (Inf - r, Inf (1,5))\n%!assert (NaN - r, NaN (1,5))\n%!assert (r - 1, 0:4)\n%!assert (r - Inf, -Inf (1,5))\n%!assert (r - NaN, NaN (1,5))\n%!assert (2 * r, 2:2:10)\n%!assert (0 * r, zeros (1,5))\n%!assert (Inf * r, Inf (1,5))\n%!assert (NaN * r, NaN (1,5))\n%!assert (r * 2, 2:2:10)\n%!assert (r * 0, zeros (1,5))\n%!assert (r * Inf, Inf (1,5))\n%!assert (r * NaN, NaN (1,5))\n\n## Test sorting of ranges (bug #45739)\n%!shared r, rrev\n%! r = 1:2:10;\n%! rrev = 10:-2:1;\n\n%!assert <*45739> (sort (r, \"descend\"), [9 7 5 3 1])\n%!assert <*45739> (sort (rrev, \"ascend\"), [2 4 6 8 10])\n\n## Test final value within eps of an integer (bug #46859)\n%!test <*46859>\n%! rng = 1 : (1001/250)/(1/250);\n%! assert (rng(end), 1001);\n\n%!test <*46859>\n%! rng = 2000: -1 : (1001/250)/(1/250);\n%! assert (rng(end), 1001);\n\n## This is not Matlab compatible (stops at 1000 with 999 elements)\n## Octave prefers the more intuitive \"pure math\" approach where\n## (1001/250) / (1/250) => (1001/250)*(250/1) => 1001.\n%!test <*46859>\n%! rng = 1 : (1001/250)/(1/250);\n%! assert (numel (1000));\n\n## Combinations of exceptional values and a few normal ones.\n\n%!shared mt_row, inf, nan, zero, pt3, pt6, pt9, one, epsilon\n%! mt_row = zeros (1, 0, 'double');\n%! inf = Inf ('double');\n%! nan = NaN ('double');\n%! zero = double (0.0);\n%! pt3 = double (0.3);\n%! pt6 = double (0.6);\n%! pt9 = double (0.9);\n%! one = double (1.0);\n%! epsilon = eps ('double');\n%!assert <*59229> (nan:-pt3:-one, nan)\n%!assert <*59229> (nan:-pt3:-inf, nan)\n%!assert <*59229> (nan:-pt3:zero, nan)\n%!assert <*59229> (nan:-pt3:one, nan)\n%!assert <*59229> (nan:-pt3:inf, nan)\n%!assert <*59229> (nan:-pt3:nan, nan)\n%!assert <*59229> (nan:-inf:-one, nan)\n%!assert <*59229> (nan:-inf:-inf, nan)\n%!assert <*59229> (nan:-inf:zero, nan)\n%!assert <*59229> (nan:-inf:one, nan)\n%!assert <*59229> (nan:-inf:inf, nan)\n%!assert <*59229> (nan:-inf:nan, nan)\n%!assert <*59229> (nan:zero:-one, nan)\n%!assert <*59229> (nan:zero:-inf, nan)\n%!assert <*59229> (nan:zero:zero, nan)\n%!assert <*59229> (nan:zero:one, nan)\n%!assert <*59229> (nan:zero:inf, nan)\n%!assert <*59229> (nan:zero:nan, nan)\n%!assert <*59229> (nan:pt3:-one, nan)\n%!assert <*59229> (nan:pt3:-inf, nan)\n%!assert <*59229> (nan:pt3:zero, nan)\n%!assert <*59229> (nan:pt3:one, nan)\n%!assert <*59229> (nan:pt3:inf, nan)\n%!assert <*59229> (nan:pt3:nan, nan)\n%!assert <*59229> (nan:inf:-one, nan)\n%!assert <*59229> (nan:inf:-inf, nan)\n%!assert <*59229> (nan:inf:zero, nan)\n%!assert <*59229> (nan:inf:one, nan)\n%!assert <*59229> (nan:inf:inf, nan)\n%!assert <*59229> (nan:inf:nan, nan)\n%!assert <*59229> (nan:nan:-one, nan)\n%!assert <*59229> (nan:nan:-inf, nan)\n%!assert <*59229> (nan:nan:zero, nan)\n%!assert <*59229> (nan:nan:one, nan)\n%!assert <*59229> (nan:nan:inf, nan)\n%!assert <*59229> (nan:nan:nan, nan)\n%!assert <*59229> (-inf:-pt3:nan, nan)\n%!assert <*59229> (-inf:-inf:nan, nan)\n%!assert <*59229> (-inf:zero:nan, nan)\n%!assert <*59229> (-inf:pt3:nan, nan)\n%!assert <*59229> (-inf:inf:nan, nan)\n%!assert <*59229> (zero:-pt3:nan, nan)\n%!assert <*59229> (zero:-inf:nan, nan)\n%!assert <*59229> (zero:zero:nan, nan)\n%!assert <*59229> (zero:pt3:nan, nan)\n%!assert <*59229> (zero:inf:nan, nan)\n%!assert <*59229> (inf:-pt3:nan, nan)\n%!assert <*59229> (inf:-inf:nan, nan)\n%!assert <*59229> (inf:zero:nan, nan)\n%!assert <*59229> (inf:pt3:nan, nan)\n%!assert <*59229> (inf:inf:nan, nan)\n%!assert <*59229> (-inf:nan:-one, nan)\n%!assert <*59229> (-inf:nan:-inf, nan)\n%!assert <*59229> (-inf:nan:zero, nan)\n%!assert <*59229> (-inf:nan:one, nan)\n%!assert <*59229> (-inf:nan:inf, nan)\n%!assert <*59229> (-inf:nan:nan, nan)\n%!assert <*59229> (zero:nan:-one, nan)\n%!assert <*59229> (zero:nan:-inf, nan)\n%!assert <*59229> (zero:nan:zero, nan)\n%!assert <*59229> (zero:nan:one, nan)\n%!assert <*59229> (zero:nan:inf, nan)\n%!assert <*59229> (zero:nan:nan, nan)\n%!assert <*59229> (inf:nan:-one, nan)\n%!assert <*59229> (inf:nan:-inf, nan)\n%!assert <*59229> (inf:nan:zero, nan)\n%!assert <*59229> (inf:nan:one, nan)\n%!assert <*59229> (inf:nan:inf, nan)\n%!assert <*59229> (inf:nan:nan, nan)\n%!assert <*59229> (inf:-pt3:inf, nan)\n%!assert <*59229> (-inf:-pt3:-inf, nan)\n%!assert <*59229> (inf:pt3:inf, nan)\n%!assert <*59229> (-inf:pt3:-inf, nan)\n%!assert <*59229> (-inf:-inf:-inf, nan)\n%!assert <*59229> (zero:-inf:-inf, nan)\n%!assert <*59229> (inf:-inf:-one, nan)\n%!assert <*59229> (inf:-inf:-inf, nan)\n%!assert <*59229> (inf:-inf:zero, nan)\n%!assert <*59229> (inf:-inf:one, nan)\n%!assert <*59229> (inf:-inf:inf, nan)\n%!assert <*59229> (-inf:inf:-one, nan)\n%!assert <*59229> (-inf:inf:-inf, nan)\n%!assert <*59229> (-inf:inf:zero, nan)\n%!assert <*59229> (-inf:inf:one, nan)\n%!assert <*59229> (-inf:inf:inf, nan)\n%!assert <*59229> (zero:inf:inf, nan)\n%!assert <*59229> (inf:inf:inf, nan)\n%!assert <*59229> (zero:zero:-one, mt_row)\n%!assert <*59229> (zero:zero:zero, mt_row)\n%!assert <*59229> (zero:zero:one, mt_row)\n%!assert <*59229> (zero:zero:-inf, mt_row)\n%!assert <*59229> (zero:zero:inf, mt_row)\n%!assert <*59229> (-inf:zero:-one, mt_row)\n%!assert <*59229> (-inf:zero:zero, mt_row)\n%!assert <*59229> (-inf:zero:one, mt_row)\n%!assert <*59229> (-inf:zero:-inf, mt_row)\n%!assert <*59229> (-inf:zero:inf, mt_row)\n%!assert <*59229> (inf:zero:-one, mt_row)\n%!assert <*59229> (inf:zero:zero, mt_row)\n%!assert <*59229> (inf:zero:one, mt_row)\n%!assert <*59229> (inf:zero:-inf, mt_row)\n%!assert <*59229> (inf:zero:inf, mt_row)\n%!assert <*59229> (zero:pt3:-one, mt_row)\n%!assert <*59229> (zero:pt3:-inf, mt_row)\n%!assert <*59229> (inf:pt3:-one, mt_row)\n%!assert <*59229> (inf:pt3:zero, mt_row)\n%!assert <*59229> (inf:pt3:one, mt_row)\n%!assert <*59229> (inf:pt3:-inf, mt_row)\n%!assert <*59229> (zero:inf:-one, mt_row)\n%!assert <*59229> (zero:inf:-inf, mt_row)\n%!assert <*59229> (inf:inf:-one, mt_row)\n%!assert <*59229> (inf:inf:zero, mt_row)\n%!assert <*59229> (inf:inf:one, mt_row)\n%!assert <*59229> (inf:inf:-inf, mt_row)\n%!assert <*59229> (zero:-pt3:one, mt_row)\n%!assert <*59229> (zero:-pt3:inf, mt_row)\n%!assert <*59229> (-inf:-pt3:-one, mt_row)\n%!assert <*59229> (-inf:-pt3:zero, mt_row)\n%!assert <*59229> (-inf:-pt3:one, mt_row)\n%!assert <*59229> (-inf:-pt3:inf, mt_row)\n%!assert <*59229> (zero:-inf:one, mt_row)\n%!assert <*59229> (zero:-inf:inf, mt_row)\n%!assert <*59229> (-inf:-inf:-one, mt_row)\n%!assert <*59229> (-inf:-inf:zero, mt_row)\n%!assert <*59229> (-inf:-inf:one, mt_row)\n%!assert <*59229> (-inf:-inf:inf, mt_row)\n%!assert <*59229> (zero:-inf:-one, zero)\n%!assert <*59229> (zero:-inf:zero, zero)\n%!assert <*59229> (zero:inf:zero, zero)\n%!assert <*59229> (zero:inf:one, zero)\n%!assert <*59229> (zero:-pt3:zero, zero)\n%!assert <*59229> (zero:pt3:zero, zero)\n%!assert <*59229> (zero:-pt3:-one, [zero, -pt3, -pt6, -pt9], epsilon)\n%!assert <*59229> (zero:pt3:one, [zero, pt3, pt6, pt9], epsilon)\n%!error <range with infinite number of elements cannot be stored> zero:-pt3:-inf\n%!error <range with infinite number of elements cannot be stored> inf:-pt3:-one\n%!error <range with infinite number of elements cannot be stored> inf:-pt3:zero\n%!error <range with infinite number of elements cannot be stored> inf:-pt3:one\n%!error <range with infinite number of elements cannot be stored> inf:-pt3:-inf\n%!error <range with infinite number of elements cannot be stored> zero:pt3:inf\n%!error <range with infinite number of elements cannot be stored> -inf:pt3:-one\n%!error <range with infinite number of elements cannot be stored> -inf:pt3:zero\n%!error <range with infinite number of elements cannot be stored> -inf:pt3:one\n%!error <range with infinite number of elements cannot be stored> -inf:pt3:inf\n\n## Again, this time with singles.\n%!shared mt_row, inf, nan, zero, pt3, pt6, pt9, one, epsilon\n%! mt_row = zeros (1, 0, 'single');\n%! inf = Inf ('single');\n%! nan = NaN ('single');\n%! zero = single (0.0);\n%! pt3 = single (0.3);\n%! pt6 = single (0.6);\n%! pt9 = single (0.9);\n%! one = single (1.0);\n%! epsilon = eps ('single');\n%!assert <*59229> (nan:-pt3:-one, nan)\n%!assert <*59229> (nan:-pt3:-inf, nan)\n%!assert <*59229> (nan:-pt3:zero, nan)\n%!assert <*59229> (nan:-pt3:one, nan)\n%!assert <*59229> (nan:-pt3:inf, nan)\n%!assert <*59229> (nan:-pt3:nan, nan)\n%!assert <*59229> (nan:-inf:-one, nan)\n%!assert <*59229> (nan:-inf:-inf, nan)\n%!assert <*59229> (nan:-inf:zero, nan)\n%!assert <*59229> (nan:-inf:one, nan)\n%!assert <*59229> (nan:-inf:inf, nan)\n%!assert <*59229> (nan:-inf:nan, nan)\n%!assert <*59229> (nan:zero:-one, nan)\n%!assert <*59229> (nan:zero:-inf, nan)\n%!assert <*59229> (nan:zero:zero, nan)\n%!assert <*59229> (nan:zero:one, nan)\n%!assert <*59229> (nan:zero:inf, nan)\n%!assert <*59229> (nan:zero:nan, nan)\n%!assert <*59229> (nan:pt3:-one, nan)\n%!assert <*59229> (nan:pt3:-inf, nan)\n%!assert <*59229> (nan:pt3:zero, nan)\n%!assert <*59229> (nan:pt3:one, nan)\n%!assert <*59229> (nan:pt3:inf, nan)\n%!assert <*59229> (nan:pt3:nan, nan)\n%!assert <*59229> (nan:inf:-one, nan)\n%!assert <*59229> (nan:inf:-inf, nan)\n%!assert <*59229> (nan:inf:zero, nan)\n%!assert <*59229> (nan:inf:one, nan)\n%!assert <*59229> (nan:inf:inf, nan)\n%!assert <*59229> (nan:inf:nan, nan)\n%!assert <*59229> (nan:nan:-one, nan)\n%!assert <*59229> (nan:nan:-inf, nan)\n%!assert <*59229> (nan:nan:zero, nan)\n%!assert <*59229> (nan:nan:one, nan)\n%!assert <*59229> (nan:nan:inf, nan)\n%!assert <*59229> (nan:nan:nan, nan)\n%!assert <*59229> (-inf:-pt3:nan, nan)\n%!assert <*59229> (-inf:-inf:nan, nan)\n%!assert <*59229> (-inf:zero:nan, nan)\n%!assert <*59229> (-inf:pt3:nan, nan)\n%!assert <*59229> (-inf:inf:nan, nan)\n%!assert <*59229> (zero:-pt3:nan, nan)\n%!assert <*59229> (zero:-inf:nan, nan)\n%!assert <*59229> (zero:zero:nan, nan)\n%!assert <*59229> (zero:pt3:nan, nan)\n%!assert <*59229> (zero:inf:nan, nan)\n%!assert <*59229> (inf:-pt3:nan, nan)\n%!assert <*59229> (inf:-inf:nan, nan)\n%!assert <*59229> (inf:zero:nan, nan)\n%!assert <*59229> (inf:pt3:nan, nan)\n%!assert <*59229> (inf:inf:nan, nan)\n%!assert <*59229> (-inf:nan:-one, nan)\n%!assert <*59229> (-inf:nan:-inf, nan)\n%!assert <*59229> (-inf:nan:zero, nan)\n%!assert <*59229> (-inf:nan:one, nan)\n%!assert <*59229> (-inf:nan:inf, nan)\n%!assert <*59229> (-inf:nan:nan, nan)\n%!assert <*59229> (zero:nan:-one, nan)\n%!assert <*59229> (zero:nan:-inf, nan)\n%!assert <*59229> (zero:nan:zero, nan)\n%!assert <*59229> (zero:nan:one, nan)\n%!assert <*59229> (zero:nan:inf, nan)\n%!assert <*59229> (zero:nan:nan, nan)\n%!assert <*59229> (inf:nan:-one, nan)\n%!assert <*59229> (inf:nan:-inf, nan)\n%!assert <*59229> (inf:nan:zero, nan)\n%!assert <*59229> (inf:nan:one, nan)\n%!assert <*59229> (inf:nan:inf, nan)\n%!assert <*59229> (inf:nan:nan, nan)\n%!assert <*59229> (inf:-pt3:inf, nan)\n%!assert <*59229> (-inf:-pt3:-inf, nan)\n%!assert <*59229> (inf:pt3:inf, nan)\n%!assert <*59229> (-inf:pt3:-inf, nan)\n%!assert <*59229> (-inf:-inf:-inf, nan)\n%!assert <*59229> (zero:-inf:-inf, nan)\n%!assert <*59229> (inf:-inf:-one, nan)\n%!assert <*59229> (inf:-inf:-inf, nan)\n%!assert <*59229> (inf:-inf:zero, nan)\n%!assert <*59229> (inf:-inf:one, nan)\n%!assert <*59229> (inf:-inf:inf, nan)\n%!assert <*59229> (-inf:inf:-one, nan)\n%!assert <*59229> (-inf:inf:-inf, nan)\n%!assert <*59229> (-inf:inf:zero, nan)\n%!assert <*59229> (-inf:inf:one, nan)\n%!assert <*59229> (-inf:inf:inf, nan)\n%!assert <*59229> (zero:inf:inf, nan)\n%!assert <*59229> (inf:inf:inf, nan)\n%!assert <*59229> (zero:zero:-one, mt_row)\n%!assert <*59229> (zero:zero:zero, mt_row)\n%!assert <*59229> (zero:zero:one, mt_row)\n%!assert <*59229> (zero:zero:-inf, mt_row)\n%!assert <*59229> (zero:zero:inf, mt_row)\n%!assert <*59229> (-inf:zero:-one, mt_row)\n%!assert <*59229> (-inf:zero:zero, mt_row)\n%!assert <*59229> (-inf:zero:one, mt_row)\n%!assert <*59229> (-inf:zero:-inf, mt_row)\n%!assert <*59229> (-inf:zero:inf, mt_row)\n%!assert <*59229> (inf:zero:-one, mt_row)\n%!assert <*59229> (inf:zero:zero, mt_row)\n%!assert <*59229> (inf:zero:one, mt_row)\n%!assert <*59229> (inf:zero:-inf, mt_row)\n%!assert <*59229> (inf:zero:inf, mt_row)\n%!assert <*59229> (zero:pt3:-one, mt_row)\n%!assert <*59229> (zero:pt3:-inf, mt_row)\n%!assert <*59229> (inf:pt3:-one, mt_row)\n%!assert <*59229> (inf:pt3:zero, mt_row)\n%!assert <*59229> (inf:pt3:one, mt_row)\n%!assert <*59229> (inf:pt3:-inf, mt_row)\n%!assert <*59229> (zero:inf:-one, mt_row)\n%!assert <*59229> (zero:inf:-inf, mt_row)\n%!assert <*59229> (inf:inf:-one, mt_row)\n%!assert <*59229> (inf:inf:zero, mt_row)\n%!assert <*59229> (inf:inf:one, mt_row)\n%!assert <*59229> (inf:inf:-inf, mt_row)\n%!assert <*59229> (zero:-pt3:one, mt_row)\n%!assert <*59229> (zero:-pt3:inf, mt_row)\n%!assert <*59229> (-inf:-pt3:-one, mt_row)\n%!assert <*59229> (-inf:-pt3:zero, mt_row)\n%!assert <*59229> (-inf:-pt3:one, mt_row)\n%!assert <*59229> (-inf:-pt3:inf, mt_row)\n%!assert <*59229> (zero:-inf:one, mt_row)\n%!assert <*59229> (zero:-inf:inf, mt_row)\n%!assert <*59229> (-inf:-inf:-one, mt_row)\n%!assert <*59229> (-inf:-inf:zero, mt_row)\n%!assert <*59229> (-inf:-inf:one, mt_row)\n%!assert <*59229> (-inf:-inf:inf, mt_row)\n%!assert <*59229> (zero:-inf:-one, zero)\n%!assert <*59229> (zero:-inf:zero, zero)\n%!assert <*59229> (zero:inf:zero, zero)\n%!assert <*59229> (zero:inf:one, zero)\n%!assert <*59229> (zero:-pt3:zero, zero)\n%!assert <*59229> (zero:pt3:zero, zero)\n%!assert <*59229> (zero:-pt3:-one, [zero, -pt3, -pt6, -pt9], epsilon)\n%!assert <*59229> (zero:pt3:one, [zero, pt3, pt6, pt9], epsilon)\n%!error <range with infinite number of elements cannot be stored> zero:-pt3:-inf\n%!error <range with infinite number of elements cannot be stored> inf:-pt3:-one\n%!error <range with infinite number of elements cannot be stored> inf:-pt3:zero\n%!error <range with infinite number of elements cannot be stored> inf:-pt3:one\n%!error <range with infinite number of elements cannot be stored> inf:-pt3:-inf\n%!error <range with infinite number of elements cannot be stored> zero:pt3:inf\n%!error <range with infinite number of elements cannot be stored> -inf:pt3:-one\n%!error <range with infinite number of elements cannot be stored> -inf:pt3:zero\n%!error <range with infinite number of elements cannot be stored> -inf:pt3:one\n%!error <range with infinite number of elements cannot be stored> -inf:pt3:inf\n\n## Tests with different input classes\n%!error <invalid types found in range> ({1}:1:5)\n%!error <invalid types found in range> (1:{1}:5)\n%!error <invalid types found in range> (1:1:{5})\n%!error <incompatible types found in range> (int8(1):int16(1):5)\n%!error <incompatible types found in range> (int8(1):1:int16(5))\n\n## Tests with mixed integer/floating point values\n%!error <colon operator lower bound invalid> (1.5:uint8(1):5)\n%!error <colon operator lower bound invalid> (-1:uint8(1):5)\n%!error <colon operator increment invalid> (uint8(1):1.5:5)\n%!error <colon operator increment invalid> (uint8(1):NaN:5)\n%!error <colon operator upper bound invalid> (uint8(1):1:5.5)\n%!error <colon operator upper bound invalid> (uint8(1):1:256)\n%!error <colon operator upper bound invalid> (uint8(1):-1:-6)\n\n## Extreme integer values.\n%!test <*61132>\n%! types = {\"int8\", \"int16\", \"int32\", \"int64\", ...\n%!          \"uint8\", \"uint16\", \"uint32\", \"uint64\"};\n%! for i = 1:numel (types)\n%!   cls = types{i};\n%!   lo = intmin (cls);\n%!   hi = intmax (cls);\n%!   n = 99;\n%!   rlo = lo:(lo+n);\n%!   rhi = (hi-n):hi;\n%!   assert (class (rlo), cls);\n%!   assert (class (rhi), cls);\n%!   assert (numel (rlo), n+1);\n%!   assert (numel (rhi), n+1);\n%! endfor\n\n## Test that ranges do not exceed limits for integer types\n\n## Ascending ranges, signed and unsigned\n%!test <*61300>\n%! types = {@int8, @int16, @int32, @int64, @uint8, @uint16, @uint32, @uint64};\n%! start = 0:5;\n%! finish = start + 6 * floor ((100 - start) / 6);\n%! for i_type = 1:numel (types)\n%!   for i_start = 1:numel(start)\n%!     assert ((types{i_type} (start(i_start)) : 6 : 100)([1,end]), ...\n%!             [types{i_type}(start(i_start)), types{i_type}(finish(i_start))]);\n%!   endfor\n%! endfor\n\n## Descending ranges, signed\n%!test <*61300>\n%! types = {@int8, @int16, @int32, @int64};\n%! start = 100:-1:95;\n%! finish = start - 6 * floor (start / 6);\n%! for i_type = 1:numel (types)\n%!   for i_start = 1:numel(start)\n%!     assert ((types{i_type} (start(i_start)) : -6 : 0)([1,end]), ...\n%!             [types{i_type}(start(i_start)), types{i_type}(finish(i_start))]);\n%!   endfor\n%! endfor\n\n## Descending ranges, unsigned\n%!test <*61132>\n%! types = {@uint8, @uint16, @uint32, @uint64};\n%! start = 100:-1:95;\n%! finish = start - 6 * floor (start / 6);\n%! for i_type = 1:numel (types)\n%!   for i_start = 1:numel(start)\n%!     assert ((types{i_type} (start(i_start)) : -6 : 0)([1,end]), ...\n%!             [types{i_type}(start(i_start)), types{i_type}(finish(i_start))]);\n%!   endfor\n%! endfor\n\n## Class of range operator output\n%!test\n%! types = {@double, @single, ...\n%!          @int8, @int16, @int32, @int64, ...\n%!          @uint8, @uint16, @uint32, @uint64};\n%! for i_type = 1:numel (types)\n%!   ## with implicit increment\n%!   assert (class (types{i_type} (0) : types{i_type} (10)), ...\n%!           func2str (types{i_type}));\n%!   ## with matching increment\n%!   assert (class (types{i_type} (0) : types{i_type} (2) : types{i_type} (10)), ...\n%!           func2str (types{i_type}));\n%!   ## with double increment (ascending)\n%!   assert (class (types{i_type} (0) : 2 : types{i_type} (10)), ...\n%!           func2str (types{i_type}));\n%!   ## with double increment (descending)\n%!   assert (class (types{i_type} (10) : -2 : types{i_type} (0)), ...\n%!           func2str (types{i_type}));\n%! endfor\n\n## Signed integer ranges with large span\n%!test <*61788>  # ascending ranges\n%! assert (int8 (-100) : int8 (50) : int8 (100), ...\n%!         int8 ([-100, -50, 0, 50, 100]));\n%! assert (int16 (-3e4) : int16 (1.5e4) : int16 (3e4), ...\n%!         int16 ([-3e4, -1.5e4, 0, 1.5e4, 3e4]));\n%! assert (int32 (-2e9) : int32 (1e9) : int32 (2e9), ...\n%!         int32 ([-2e9, -1e9, 0, 1e9, 2e9]));\n%! assert (int64 (-9e18) : int64 (4.5e18) : int64 (9e18), ...\n%!         [int64(-9e18), int64(-4.5e18), 0, int64(4.5e18), int64(9e18)]);\n%!test <*61788>  # descending ranges\n%! assert (int8 (100) : int8 (-50) : int8 (-100), ...\n%!         int8 ([100, 50, 0, -50, -100]));\n%! assert (int16 (3e4) : int16 (-1.5e4) : int16 (-3e4), ...\n%!         int16 ([3e4, 1.5e4, 0, -1.5e4, -3e4]));\n%! assert (int32 (2e9) : int32 (-1e9) : int32 (-2e9), ...\n%!         int32 ([2e9, 1e9, 0, -1e9, -2e9]));\n%! assert (int64 (9e18) : int64 (-4.5e18) : int64 (-9e18), ...\n%!         [int64(9e18), int64(4.5e18), 0, int64(-4.5e18), int64(-9e18)]);\n\n## integer ranges with double increments\n%!test  # ascending ranges\n%! types = {@int8, @int16, @int32, @int64, ...\n%!          @uint8, @uint16, @uint32, @uint64};\n%! for i_type = 1:numel (types)\n%!   assert (types{i_type} (0) : 2 : types{i_type} (10), ...\n%!           types{i_type} ([0, 2, 4, 6, 8, 10]));\n%! endfor\n%!test  # descending ranges\n%! types = {@int8, @int16, @int32, @int64, ...\n%!          @uint8, @uint16, @uint32, @uint64};\n%! for i_type = 1:numel (types)\n%!   assert (types{i_type} (10) : -2 : types{i_type} (0), ...\n%!           types{i_type} ([10, 8, 6, 4, 2, 0]));\n%! endfor\n\n## integer range with large double increments\n%!test <*62212>  # ascending ranges\n%! types = {\"int8\", \"int16\", \"int32\", \"int64\"};\n%! for i_type = 1:numel (types)\n%!   assert (intmin (types{i_type}) : -double (intmin (types{i_type})) : intmax (types{i_type}), ...\n%!           [intmin(types{i_type}), 0]);\n%!   assert (intmin (types{i_type}) : -2*double (intmin (types{i_type})) : intmax (types{i_type}), ...\n%!           intmin (types{i_type}));\n%!   if (! strcmp (types, \"int64\"))\n%!     ## The increment cannot be represented in double precision for \"int64\"\n%!     assert (intmin (types{i_type}) : 2*double (intmax (types{i_type})) : intmin (types{i_type}), ...\n%!             [intmin(types{i_type}), intmax(types{i_type})-1]);\n%!   endif\n%! endfor\n%!test <*62212>  # descending ranges\n%! types = {\"int8\", \"int16\", \"int32\", \"int64\"};\n%! for i_type = 1:numel (types)\n%!   assert (intmax (types{i_type}) : double (intmin (types{i_type})) : intmin (types{i_type}), ...\n%!           [intmax(types{i_type}), -1]);\n%!   assert (intmax (types{i_type}) : 2*double (intmin (types{i_type})) : intmin (types{i_type}), ...\n%!           intmax (types{i_type}));\n%!   if (! strcmp (types, \"int64\"))\n%!     ## The increment cannot be represented in double precision for \"int64\"\n%!     assert (intmax (types{i_type}) : -2*double (intmax (types{i_type})) : intmin (types{i_type}), ...\n%!             [intmax(types{i_type}), -intmax(types{i_type})]);\n%!   endif\n%! endfor\n\n## integer range near intmax\n%!test\n%! types = {\"int8\", \"int16\", \"int32\", \"int64\", ...\n%!          \"uint8\", \"uint16\", \"uint32\", \"uint64\"};\n%! for i_type = 1:numel (types)\n%!   hi = intmax (types{i_type});\n%!   lo = hi - 5;\n%!   ## ascending range\n%!   assert (lo:hi, ...\n%!           intmax(types{i_type}) - 5 + (0:5));\n%!   ## descending range\n%!   assert (hi:-1:lo, ...\n%!           intmax(types{i_type}) - 5 + (5:-1:0));\n%! endfor\n\n## integer range near intmin\n%!test\n%! types = {\"int8\", \"int16\", \"int32\", \"int64\", ...\n%!          \"uint8\", \"uint16\", \"uint32\", \"uint64\"};\n%! for i_type = 1:numel (types)\n%!   lo = intmin (types{i_type});\n%!   hi = lo + 5;\n%!   ## ascending range\n%!   assert (lo:hi, ...\n%!           intmin(types{i_type}) + (0:5));\n%!   ## descending range\n%!   assert (hi:-1:lo, ...\n%!           intmin(types{i_type}) + (5:-1:0));\n%! endfor\n"
  },
  {
    "path": "test/recursion.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!function y = f (x)\n%!  if (x == 1)\n%!    y = x;\n%!    return;\n%!  else\n%!    y = x * f (x-1);\n%!  endif\n%!endfunction\n%!\n%!assert (f (5), 120)\n\n%!function y = f (x)\n%!  if (x == 1)\n%!    y = x;\n%!    return;\n%!  else\n%!    y = f (x-1) * x;\n%!  endif\n%!endfunction\n%!\n%!assert (f (5), 120)\n\n%!function r = f (x)\n%!  persistent p = 1;\n%!  if (x == 1)\n%!    f (x + 1);\n%!    r = p;\n%!  else\n%!    clear p\n%!    p = 13;\n%!  endif\n%!endfunction\n%!\n%!error <'p' undefined> f (1)\n\n%!function r = f (x)\n%!  persistent p = 1;\n%!  if (x == 1)\n%!    f (x + 1);\n%!    r = p;\n%!  else\n%!    p = 13;\n%!  endif\n%!endfunction\n%!\n%!assert (f (1), 13)\n\n\n%%FIXME: Need test for maximum recursion depth\n"
  },
  {
    "path": "test/return.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!function y = f ()\n%!  y = 1;\n%!  return;\n%!  y = 2;\n%!endfunction\n%!\n%!assert (f (), 1)\n\n%!test\n%! return;\n"
  },
  {
    "path": "test/show-failures.awk",
    "content": "#! /usr/bin/awk -f\n\n########################################################################\n##\n## Copyright (C) 2016-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by the\n## Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\nBEGIN {\n  buf = \"\";\n  limit_output = 0;\n  line = 0;\n  line_limit = 32;\n}\n## Make the decision to print or not when we get to the next file\n/^>>>>> |^Files with no tests:/ {\n  print buf;\n\n  buf = \"\";\n  line = 0;\n  limit_output = 0;\n}\n## The first line of the output from a failing test\n/^\\*\\*\\*\\*\\* / {\n  line = 0;\n  limit_output = 0;\n}\n/^!!!!! known (bug|failure)|^----- skipped test/ {\n  limit_output = 1;\n}\n## Accumulate all lines that display the test code and up to line_limit\n## lines of output from failed test.\n{\n  if (buf == \"\")\n    {\n      buf = $0;\n    }\n  else\n    {\n      if (limit_output)\n        {\n          if (line < line_limit)\n            buf = buf \"\\n\" $0;\n          else if (line == line_limit)\n            buf = buf \"\\n[skipping remaining output]\";\n\n          line++;\n        }\n      else\n        buf = buf \"\\n\" $0;\n    }\n}\n"
  },
  {
    "path": "test/single-index.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2017-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!shared rv,cv,ndv,wm,tm,nd,lrv,lcv,lwm,ltm,lndv1,lndv2,lnd1,lnd2,rrv,rcv,rndv1,rndv2\n%! rv = [1,2,3,4,5,6,7,8,9,10,11,12];\n%! cv = rv';\n%! ndv = reshape (rv, 1, 1, 12);\n%! wm = reshape (rv, 2, 6);\n%! tm = reshape (rv, 6, 2);\n%! nd = reshape (rv, 2, 2, 3);\n%! lrv = logical ([1,0,0,1,1,0,0,1,1,0,0,1]);\n%! lcv = lrv';\n%! lwm = reshape (lrv, 2, 6);\n%! ltm = reshape (lrv, 6, 2);\n%! lndv1 = reshape (lrv, 1, 1, 12);\n%! lndv2 = reshape (lrv, 1, 1, 1, 12);\n%! lnd1 = reshape (lrv, 2, 2, 3);\n%! lnd2 = reshape (lrv, 2, 3, 2);\n%! rrv = [1,4,5,8,9,12];\n%! rcv = rrv';\n%! rndv1 = reshape (rrv, 1, 1, 6);\n%! rndv2 = reshape (rrv, 1, 1, 1, 6);\n%!assert (rv(lrv), rrv)\n%!assert (rv(lcv), rrv)\n%!assert (rv(lwm), rrv)\n%!assert (rv(ltm), rrv)\n%!assert (rv(lndv1), rrv)\n%!assert (rv(lndv2), rrv)\n%!assert (rv(lnd1), rrv)\n%!assert (rv(lnd2), rrv)\n%!assert (cv(lrv), rcv)\n%!assert (cv(lcv), rcv)\n%!assert (cv(lwm), rcv)\n%!assert (cv(ltm), rcv)\n%!assert (cv(lndv1), rcv)\n%!assert (cv(lndv2), rcv)\n%!assert (cv(lnd1), rcv)\n%!assert (cv(lnd2), rcv)\n%!assert (ndv(lrv), rndv1)\n%!assert (ndv(lcv), rndv1)\n%!assert (ndv(lwm), rndv1)\n%!assert (ndv(ltm), rndv1)\n%!assert (ndv(lndv1), rndv1)\n%!assert (ndv(lndv2), rndv1)\n%!assert (ndv(lnd1), rndv1)\n%!assert (ndv(lnd2), rndv1)\n%!assert (wm(lrv), rrv)\n%!assert (wm(lcv), rcv)\n%!assert (wm(lwm), rcv)\n%!assert (wm(ltm), rcv)\n%!assert (wm(lndv1), rndv1)\n%!assert (wm(lndv2), rndv2)\n%!assert (wm(lnd1), rcv)\n%!assert (wm(lnd2), rcv)\n%!assert (tm(lrv), rrv)\n%!assert (tm(lcv), rcv)\n%!assert (tm(lwm), rcv)\n%!assert (tm(ltm), rcv)\n%!assert (tm(lndv1), rndv1)\n%!assert (tm(lndv2), rndv2)\n%!assert (tm(lnd1), rcv)\n%!assert (tm(lnd2), rcv)\n%!assert (nd(lrv), rrv)\n%!assert (nd(lcv), rcv)\n%!assert (nd(lwm), rcv)\n%!assert (nd(ltm), rcv)\n%!assert (nd(lndv1), rndv1)\n%!assert (nd(lndv2), rndv2)\n%!assert (nd(lnd1), rcv)\n%!assert (nd(lnd2), rcv)\n\n%!shared rv,cv,ndv,wm,tm,nd,lrv,lcv,lwm,ltm,lndv1,lndv2,lnd1,lnd2,rrv,rcv,rndv1,rndv2\n%! rv = [1,2,3,4,5,6,7,8,9,10,11,12];\n%! cv = rv';\n%! ndv = reshape (rv, 1, 1, 12);\n%! wm = reshape (rv, 2, 6);\n%! tm = reshape (rv, 6, 2);\n%! nd = reshape (rv, 2, 2, 3);\n%! lrv = logical ([1,1,1,1,1,1,1,1,1,1,1,1]);\n%! lcv = lrv';\n%! lwm = reshape (lrv, 2, 6);\n%! ltm = reshape (lrv, 6, 2);\n%! lndv1 = reshape (lrv, 1, 1, 12);\n%! lndv2 = reshape (lrv, 1, 1, 1, 12);\n%! lnd1 = reshape (lrv, 2, 2, 3);\n%! lnd2 = reshape (lrv, 2, 3, 2);\n%! rrv = [1,2,3,4,5,6,7,8,9,10,11,12];\n%! rcv = rrv';\n%! rndv1 = reshape (rrv, 1, 1, 12);\n%! rndv2 = reshape (rrv, 1, 1, 1, 12);\n%!assert (rv(lrv), rrv)\n%!assert (rv(lcv), rrv)\n%!assert (rv(lwm), rrv)\n%!assert (rv(ltm), rrv)\n%!assert (rv(lndv1), rrv)\n%!assert (rv(lndv2), rrv)\n%!assert (rv(lnd1), rrv)\n%!assert (rv(lnd2), rrv)\n%!assert (cv(lrv), rcv)\n%!assert (cv(lcv), rcv)\n%!assert (cv(lwm), rcv)\n%!assert (cv(ltm), rcv)\n%!assert (cv(lndv1), rcv)\n%!assert (cv(lndv2), rcv)\n%!assert (cv(lnd1), rcv)\n%!assert (cv(lnd2), rcv)\n%!assert (ndv(lrv), rndv1)\n%!assert (ndv(lcv), rndv1)\n%!assert (ndv(lwm), rndv1)\n%!assert (ndv(ltm), rndv1)\n%!assert (ndv(lndv1), rndv1)\n%!assert (ndv(lndv2), rndv1)\n%!assert (ndv(lnd1), rndv1)\n%!assert (ndv(lnd2), rndv1)\n%!assert (wm(lrv), rrv)\n%!assert (wm(lcv), rcv)\n%!assert (wm(lwm), rcv)\n%!assert (wm(ltm), rcv)\n%!assert (wm(lndv1), rndv1)\n%!assert (wm(lndv2), rndv2)\n%!assert (wm(lnd1), rcv)\n%!assert (wm(lnd2), rcv)\n%!assert (tm(lrv), rrv)\n%!assert (tm(lcv), rcv)\n%!assert (tm(lwm), rcv)\n%!assert (tm(ltm), rcv)\n%!assert (tm(lndv1), rndv1)\n%!assert (tm(lndv2), rndv2)\n%!assert (tm(lnd1), rcv)\n%!assert (tm(lnd2), rcv)\n%!assert (nd(lrv), rrv)\n%!assert (nd(lcv), rcv)\n%!assert (nd(lwm), rcv)\n%!assert (nd(ltm), rcv)\n%!assert (nd(lndv1), rndv1)\n%!assert (nd(lndv2), rndv2)\n%!assert (nd(lnd1), rcv)\n%!assert (nd(lnd2), rcv)\n\n%!shared rv,cv,ndv,wm,tm,nd,irv,icv,iwm,itm,indv1,indv2,ind1,ind2,rrv,rcv,rndv1,rndv2\n%! rv = [1,2,3,4,5,6,7,8,9,10,11,12];\n%! cv = rv';\n%! ndv = reshape (rv, 1, 1, 12);\n%! wm = reshape (rv, 2, 6);\n%! tm = reshape (rv, 6, 2);\n%! nd = reshape (rv, 2, 2, 3);\n%! irv = [1,3,5,7,9,11];\n%! icv = irv';\n%! iwm = reshape (irv, 2, 3);\n%! itm = reshape (irv, 3, 2);\n%! indv1 = reshape (irv, 1, 1, 6);\n%! indv2 = reshape (irv, 1, 1, 1, 6);\n%! ind1 = reshape (irv, 2, 1, 3);\n%! ind2 = reshape (irv, 1, 3, 2);\n%! rrv = [1,3,5,7,9,11];\n%! rcv = rrv';\n%! rndv1 = reshape (rrv, 1, 1, 6);\n%! rndv2 = reshape (rrv, 1, 1, 1, 6);\n%!assert (rv(irv), rrv)\n%!assert (rv(icv), rrv)\n%!assert (rv(iwm), iwm)\n%!assert (rv(itm), itm)\n%!assert (rv(indv1), rrv)\n%!assert (rv(indv2), rrv)\n%!assert (rv(ind1), ind1)\n%!assert (rv(ind2), ind2)\n%!assert (cv(irv), rcv)\n%!assert (cv(icv), rcv)\n%!assert (cv(iwm), iwm)\n%!assert (cv(itm), itm)\n%!assert (cv(indv1), rcv)\n%!assert (cv(indv2), rcv)\n%!assert (cv(ind1), ind1)\n%!assert (cv(ind2), ind2)\n%!assert (ndv(irv), rndv1)\n%!assert (ndv(icv), rndv1)\n%!assert (ndv(iwm), iwm)\n%!assert (ndv(itm), itm)\n%!assert (ndv(indv1), rndv1)\n%!assert (ndv(indv2), rndv1)\n%!assert (ndv(ind1), ind1)\n%!assert (ndv(ind2), ind2)\n%!assert (wm(irv), rrv)\n%!assert (wm(icv), rcv)\n%!assert (wm(iwm), iwm)\n%!assert (wm(itm), itm)\n%!assert (wm(indv1), rndv1)\n%!assert (wm(indv2), rndv2)\n%!assert (wm(ind1), ind1)\n%!assert (wm(ind2), ind2)\n%!assert (tm(irv), rrv)\n%!assert (tm(icv), rcv)\n%!assert (tm(iwm), iwm)\n%!assert (tm(itm), itm)\n%!assert (tm(indv1), rndv1)\n%!assert (tm(indv2), rndv2)\n%!assert (tm(ind1), ind1)\n%!assert (tm(ind2), ind2)\n%!assert (nd(irv), rrv)\n%!assert (nd(icv), rcv)\n%!assert (nd(iwm), iwm)\n%!assert (nd(itm), itm)\n%!assert (nd(indv1), rndv1)\n%!assert (nd(indv2), rndv2)\n%!assert (nd(ind1), ind1)\n%!assert (nd(ind2), ind2)\n\n%!shared rv,cv,ndv,wm,tm,nd,irv,icv,iwm,itm,indv1,indv2,ind1,ind2,rrv,rcv,rndv1,rndv2\n%! rv = [1,2,3,4,5,6,7,8,9,10,11,12];\n%! cv = rv';\n%! ndv = reshape (rv, 1, 1, 12);\n%! wm = reshape (rv, 2, 6);\n%! tm = reshape (rv, 6, 2);\n%! nd = reshape (rv, 2, 2, 3);\n%! irv = [1,2,3,4,5,6,7,8,9,10,11,12];\n%! icv = irv';\n%! iwm = reshape (irv, 2, 6);\n%! itm = reshape (irv, 6, 2);\n%! indv1 = reshape (irv, 1, 1, 12);\n%! indv2 = reshape (irv, 1, 1, 1, 12);\n%! ind1 = reshape (irv, 2, 2, 3);\n%! ind2 = reshape (irv, 2, 3, 2);\n%! rrv = [1,2,3,4,5,6,7,8,9,10,11,12];\n%! rcv = rrv';\n%! rndv1 = reshape (rrv, 1, 1, 12);\n%! rndv2 = reshape (rrv, 1, 1, 1, 12);\n%!assert (rv(irv), rrv)\n%!assert (rv(icv), rrv)\n%!assert (rv(iwm), iwm)\n%!assert (rv(itm), itm)\n%!assert (rv(indv1), rrv)\n%!assert (rv(indv2), rrv)\n%!assert (rv(ind1), ind1)\n%!assert (rv(ind2), ind2)\n%!assert (cv(irv), rcv)\n%!assert (cv(icv), rcv)\n%!assert (cv(iwm), iwm)\n%!assert (cv(itm), itm)\n%!assert (cv(indv1), rcv)\n%!assert (cv(indv2), rcv)\n%!assert (cv(ind1), ind1)\n%!assert (cv(ind2), ind2)\n%!assert (ndv(irv), rndv1)\n%!assert (ndv(icv), rndv1)\n%!assert (ndv(iwm), iwm)\n%!assert (ndv(itm), itm)\n%!assert (ndv(indv1), rndv1)\n%!assert (ndv(indv2), rndv1)\n%!assert (ndv(ind1), ind1)\n%!assert (ndv(ind2), ind2)\n%!assert (wm(irv), rrv)\n%!assert (wm(icv), rcv)\n%!assert (wm(iwm), iwm)\n%!assert (wm(itm), itm)\n%!assert (wm(indv1), rndv1)\n%!assert (wm(indv2), rndv2)\n%!assert (wm(ind1), ind1)\n%!assert (wm(ind2), ind2)\n%!assert (tm(irv), rrv)\n%!assert (tm(icv), rcv)\n%!assert (tm(iwm), iwm)\n%!assert (tm(itm), itm)\n%!assert (tm(indv1), rndv1)\n%!assert (tm(indv2), rndv2)\n%!assert (tm(ind1), ind1)\n%!assert (tm(ind2), ind2)\n%!assert (nd(irv), rrv)\n%!assert (nd(icv), rcv)\n%!assert (nd(iwm), iwm)\n%!assert (nd(itm), itm)\n%!assert (nd(indv1), rndv1)\n%!assert (nd(indv2), rndv2)\n%!assert (nd(ind1), ind1)\n%!assert (nd(ind2), ind2)\n"
  },
  {
    "path": "test/slice.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2007-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!function x = set_slice (size, dim, slice)\n%!  x = ones (size);\n%!  switch (dim)\n%!    case 11\n%!      x(slice) = 2;\n%!    case 21\n%!      x(slice, :) = 2;\n%!    case 22\n%!      x(:, slice) = 2;\n%!    case 31\n%!      x(slice, :, :) = 2;\n%!    case 32\n%!      x(:, slice, :) = 2;\n%!    case 33\n%!      x(:, :, slice) = 2;\n%!    otherwise\n%!      error (\"invalid dim, '%d'\", dim);\n%!  endswitch\n%!endfunction\n\n## size = [2 0]\n%!assert (set_slice ([2 0], 11, []), zeros ([2 0]))\n%!error id=Octave:invalid-resize set_slice ([2 0], 11, 1)\n%!error id=Octave:invalid-resize set_slice ([2 0], 11, 2)\n%!error id=Octave:invalid-resize set_slice ([2 0], 11, 3)\n%!assert (set_slice ([2 0], 21, []), zeros ([2 0]))\n%!assert (set_slice ([2 0], 21, 1), zeros ([2 0]))\n%!assert (set_slice ([2 0], 21, 2), zeros ([2 0]))\n%!assert (set_slice ([2 0], 21, 3), zeros ([3 0]))\n%!assert (set_slice ([2 0], 22, []), zeros ([2 0]))\n%!assert (set_slice ([2 0], 22, 1), [2 2]')\n%!assert (set_slice ([2 0], 22, 2), [0 0;2 2]')\n%!assert (set_slice ([2 0], 22, 3), [0 0;0 0;2 2]')\n%!assert (set_slice ([2 0], 31, []), zeros ([2 0]))\n%!assert (set_slice ([2 0], 31, 1), zeros ([2 0]))\n%!assert (set_slice ([2 0], 31, 2), zeros ([2 0]))\n%!assert (set_slice ([2 0], 31, 3), zeros ([3 0]))\n%!assert (set_slice ([2 0], 32, []), zeros ([2 0]))\n%!assert (set_slice ([2 0], 32, 1), [2 2]')\n%!assert (set_slice ([2 0], 32, 2), [0 0;2 2]')\n%!assert (set_slice ([2 0], 32, 3), [0 0;0 0;2 2]')\n%!assert (set_slice ([2 0], 33, []), zeros ([2 0]))\n%!assert (set_slice ([2 0], 33, 1), zeros ([2 0]))\n%!assert (set_slice ([2 0], 33, 2), zeros ([2 0 2]))\n%!assert (set_slice ([2 0], 33, 3), zeros ([2 0 3]))\n\n## size = [0 2]\n%!assert (set_slice ([0 2], 11, []), zeros ([0 2]))\n%!assert (set_slice ([0 2], 11, 1), 2)\n%!assert (set_slice ([0 2], 11, 2), [0, 2])\n%!assert (set_slice ([0 2], 11, 3), [0, 0, 2])\n%!assert (set_slice ([0 2], 21, []), zeros ([0 2]))\n%!assert (set_slice ([0 2], 21, 1), [2 2])\n%!assert (set_slice ([0 2], 21, 2), [0 0;2 2])\n%!assert (set_slice ([0 2], 21, 3), [0 0;0 0;2 2])\n%!assert (set_slice ([0 2], 22, []), zeros ([0 2]))\n%!assert (set_slice ([0 2], 22, 1), zeros ([0 2]))\n%!assert (set_slice ([0 2], 22, 2), zeros ([0 2]))\n%!assert (set_slice ([0 2], 22, 3), zeros ([0 3]))\n%!assert (set_slice ([0 2], 31, []), zeros ([0 2]))\n%!assert (set_slice ([0 2], 31, 1), [2 2])\n%!assert (set_slice ([0 2], 31, 2), [0 0;2 2])\n%!assert (set_slice ([0 2], 31, 3), [0 0;0 0;2 2])\n%!assert (set_slice ([0 2], 32, []), zeros ([0 2]))\n%!assert (set_slice ([0 2], 32, 1), zeros ([0 2]))\n%!assert (set_slice ([0 2], 32, 2), zeros ([0 2]))\n%!assert (set_slice ([0 2], 32, 3), zeros ([0 3]))\n%!assert (set_slice ([0 2], 33, []), zeros ([0 2]))\n%!assert (set_slice ([0 2], 33, 1), zeros ([0 2]))\n%!assert (set_slice ([0 2], 33, 2), zeros ([0 2 2]))\n%!assert (set_slice ([0 2], 33, 3), zeros ([0 2 3]))\n\n## size = [2 1]\n%!assert (set_slice ([2 1], 11, []), ones ([2 1]))\n%!assert (set_slice ([2 1], 11, 1), [2 1]')\n%!assert (set_slice ([2 1], 11, 2), [1 2]')\n%!assert (set_slice ([2 1], 11, 3), [1 1 2]')\n%!assert (set_slice ([2 1], 11, 4), [1 1 0 2]')\n%!assert (set_slice ([2 1], 21, []), ones ([2 1]))\n%!assert (set_slice ([2 1], 21, 1), [2 1]')\n%!assert (set_slice ([2 1], 21, 2), [1 2]')\n%!assert (set_slice ([2 1], 21, 3), [1 1 2]')\n%!assert (set_slice ([2 1], 21, 4), [1 1 0 2]')\n%!assert (set_slice ([2 1], 22, []), ones ([2 1]))\n%!assert (set_slice ([2 1], 22, 1), [2 2]')\n%!assert (set_slice ([2 1], 22, 2), [1 1;2 2]')\n%!assert (set_slice ([2 1], 22, 3), [1 1;0 0;2 2]')\n%!assert (set_slice ([2 1], 31, []), ones ([2 1]))\n%!assert (set_slice ([2 1], 31, 1), [2 1]')\n%!assert (set_slice ([2 1], 31, 2), [1 2]')\n%!assert (set_slice ([2 1], 31, 3), [1 1 2]')\n%!assert (set_slice ([2 1], 31, 4), [1 1 0 2]')\n%!assert (set_slice ([2 1], 32, []), ones ([2 1]))\n%!assert (set_slice ([2 1], 32, 1), [2 2]')\n%!assert (set_slice ([2 1], 32, 2), [1 1;2 2]')\n%!assert (set_slice ([2 1], 32, 3), [1 1;0 0;2 2]')\n%!assert (set_slice ([2 1], 33, []), ones ([2 1]))\n%!assert (set_slice ([2 1], 33, 1), [2 2]')\n%!assert (set_slice ([2 1], 33, 2), reshape ([1 1 2 2],[2 1 2]))\n%!assert (set_slice ([2 1], 33, 3), reshape ([1 1 0 0 2 2],[2 1 3]))\n\n## size = [1 2]\n%!assert (set_slice ([1 2], 11, []), full (ones ([1 2])))\n%!assert (set_slice ([1 2], 11, 1), [2 1])\n%!assert (set_slice ([1 2], 11, 2), [1 2])\n%!assert (set_slice ([1 2], 11, 3), [1 1 2])\n%!assert (set_slice ([1 2], 11, 4), [1 1 0 2])\n%!assert (set_slice ([1 2], 21, []), full (ones ([1 2])))\n%!assert (set_slice ([1 2], 21, 1), [2 2])\n%!assert (set_slice ([1 2], 21, 2), [1 1;2 2])\n%!assert (set_slice ([1 2], 21, 3), [1 1;0 0;2 2])\n%!assert (set_slice ([1 2], 22, []), full (ones ([1 2])))\n%!assert (set_slice ([1 2], 22, 1), [2 1])\n%!assert (set_slice ([1 2], 22, 2), [1 2])\n%!assert (set_slice ([1 2], 22, 3), [1 1 2])\n%!assert (set_slice ([1 2], 22, 4), [1 1 0 2])\n%!assert (set_slice ([1 2], 31, []), full (ones ([1 2])))\n%!assert (set_slice ([1 2], 31, 1), [2 2])\n%!assert (set_slice ([1 2], 31, 2), [1 1;2 2])\n%!assert (set_slice ([1 2], 31, 3), [1 1;0 0;2 2])\n%!assert (set_slice ([1 2], 32, []), full (ones ([1 2])))\n%!assert (set_slice ([1 2], 32, 1), [2 1])\n%!assert (set_slice ([1 2], 32, 2), [1 2])\n%!assert (set_slice ([1 2], 32, 3), [1 1 2])\n%!assert (set_slice ([1 2], 32, 4), [1 1 0 2])\n%!assert (set_slice ([1 2], 33, []), full (ones ([1 2])))\n%!assert (set_slice ([1 2], 33, 1), [2 2])\n%!assert (set_slice ([1 2], 33, 2), reshape ([1 1 2 2],[1 2 2]))\n%!assert (set_slice ([1 2], 33, 3), reshape ([1 1 0 0 2 2],[1 2 3]))\n\n## size = [2 2]\n%!assert (set_slice ([2 2], 11, []), ones ([2 2]))\n%!assert (set_slice ([2 2], 11, 1), [2 1;1 1])\n%!assert (set_slice ([2 2], 11, 2), [1 1;2 1])\n%!assert (set_slice ([2 2], 11, 3), [1 2;1 1])\n%!assert (set_slice ([2 2], 11, 4), [1 1;1 2])\n%!error id=Octave:invalid-resize set_slice ([2 2], 11, 5)\n%!error id=Octave:invalid-resize set_slice ([2 2], 11, 6)\n%!assert (set_slice ([2 2], 21, []), ones ([2 2]))\n%!assert (set_slice ([2 2], 21, 1), [2 2;1 1])\n%!assert (set_slice ([2 2], 21, 2), [1 1;2 2])\n%!assert (set_slice ([2 2], 21, 3), [1 1;1 1;2 2])\n%!assert (set_slice ([2 2], 21, 4), [1 1;1 1;0 0;2 2])\n%!assert (set_slice ([2 2], 22, []), ones ([2 2]))\n%!assert (set_slice ([2 2], 22, 1), [2 2;1 1]')\n%!assert (set_slice ([2 2], 22, 2), [1 1;2 2]')\n%!assert (set_slice ([ 2 2], 22, 3), [1 1;1 1;2 2]')\n%!assert (set_slice ([2 2], 22, 4), [1 1;1 1;0 0;2 2]')\n%!assert (set_slice ([2 2], 31, []), ones ([2 2]))\n%!assert (set_slice ([2 2], 31, 1), [2 2;1 1])\n%!assert (set_slice ([2 2], 31, 2), [1 1;2 2])\n%!assert (set_slice ( [2 2], 31, 3), [1 1;1 1;2 2])\n%!assert (set_slice ([2 2], 31, 4), [1 1;1 1;0 0;2 2])\n%!assert (set_slice ([2 2], 32, []), ones ([2 2]))\n%!assert (set_slice ([2 2], 32, 1), [2 2;1 1]')\n%!assert (set_slice ([2 2], 32, 2), [1 1;2 2]')\n%!assert (set_slice ([ 2 2], 32, 3), [1 1;1 1;2 2]')\n%!assert (set_slice ([2 2], 32, 4), [1 1;1 1;0 0;2 2]')\n%!assert (set_slice ([2 2], 33, []), ones ([2 2]))\n%!assert (set_slice ([2 2], 33, 1), [2 2;2 2])\n%!assert (set_slice ([2 2], 33, 2), reshape ([1 1 1 1 2 2 2 2],[2 2 2]))\n%!assert (set_slice ([ 2 2], 33, 3), reshape ([1 1 1 1 0 0 0 0 2 2 2 2],[2 2 3]))\n"
  },
  {
    "path": "test/sparse-assign.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2021-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## FIXME: will also need tests for if assignment of integer values\n## once that is implemented.  The pattern can be the same.\n\n%!shared lr, lc, rr, rc, si, sj, mi, mj, sm_lhs, csm_lhs, s, m, sm, cs, cm, csm\n%! lr = 6;\n%! lc = 8;\n%! rr = 2;\n%! rc = 3;\n%! si = 2;\n%! sj = 3;\n%! mi = (1:rr)+2;\n%! mj = (1:rc)+3;\n%! sm_lhs = sprand (lr, lc, 0.1);\n%! csm_lhs = sm_lhs + 1i * sprand (lr, lc, 0.1);\n%! s = rand ();\n%! m = rand (rr, rc);\n%! sm = sprand (rr, rc, 0.1);\n%! cs = s + 1i * rand ();\n%! cm = m + 1i * rand (rr, rc);\n%! csm = cm + 1i * sprand (rr, rc, 0.1);\n\n%% Indexed assignment of double scalar, sparse with a single element,\n%% complex scalar, and sparse complex with a single element to sparse matrix.\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = s;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = sparse (s);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = cs;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = sparse (cs);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%% Indexed assignment of double scalar, sparse with a single element,\n%% complex scalar, and sparse complex with a single element to complex\n%% sparse matrix.\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = s;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = sparse (s);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = cs;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = sparse (cs);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%% Indexed assignment of matrix, sparse matrix, complex matrix,\n%% and complex sparse matrix to sparse matrix.\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = m;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = sm;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = cm;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = csm;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%% Indexed assignment of matrix, sparse matrix, complex matrix,\n%% and complex sparse matrix to complex sparse matrix.\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = m;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = sm;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = cm;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = csm;\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%% Indexed assignment of float scalar, float complex scalar, float matrix,\n%% and float complex matrix to sparse matrix.\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = single (s);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = single (cs);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = single (m);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = sm_lhs;\n%! rhs = single (cm);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%% Indexed assignment of float scalar, float complex scalar, float matrix,\n%% and float complex matrix to complex sparse matrix.\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = single (s);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = single (cs);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(si,sj) = rhs;\n%! flhs(si,sj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = single (m);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test\n%! lhs = csm_lhs;\n%! rhs = single (cm);\n%! flhs = full (lhs);\n%! frhs = full (rhs);\n%! lhs(mi,mj) = rhs;\n%! flhs(mi,mj) = frhs;\n%! assert (issparse (lhs));\n%! assert (full (lhs), flhs);\n%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));\n\n%!test <*66516>\n%! a = sparse (magic (3));\n%! a(6:-1:4, 6:-1:4) = magic (3);  # extend matrix and assign\n%! assert (a(4:6, 4:6), sparse (fliplr (flipud (magic (3)))));\n"
  },
  {
    "path": "test/sparse-broadcasting.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2025-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n## Tests for SparseMatrix\n\n## Test broadcasting of empty matrices with math operators.\n## This has been fixed in MSparse.cc and Sparse-op-defs.h\n%!assert (sparse (zeros (0,1)) + sparse ([1, 2, 3, 4]), sparse (zeros (0,4)))\n%!error <operator \\+: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) + sparse ([1, 2, 3, 4])\n%!assert (sparse (zeros (0,1)) - sparse ([1, 2, 3, 4]), sparse (zeros (0,4)))\n%!error <operator -: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) - sparse ([1, 2, 3, 4])\n%!assert (sparse (zeros (0,1)) * sparse ([1, 2, 3, 4]), sparse (zeros (0,4)))\n%!error <operator \\*: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) * sparse ([1, 2, 3, 4])\n%!assert (sparse (zeros (0,1)) .* sparse ([1, 2, 3, 4]), sparse (zeros (0,4)))\n%!error <product: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) .* sparse ([1, 2, 3, 4])\n%!assert (sparse (zeros (0,1)) ./ sparse ([1, 2, 3, 4]), sparse (zeros (0,4)))\n%!error <quotient: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) ./ sparse ([1, 2, 3, 4])\n%!test\n%! a = sparse (zeros (0,1));\n%! assert (a += sparse ([1, 2, 3, 4]), sparse (zeros (0,4)));\n%! assert (a -= sparse ([1, 2, 3, 4]), sparse (zeros (0,4)));\n\n%!assert (sparse (zeros (1,0)) + sparse ([1; 2; 3; 4]), sparse (zeros (4,0)))\n%!error <operator \\+: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) + sparse ([1; 2; 3; 4])\n%!assert (sparse (zeros (1,0)) - sparse ([1; 2; 3; 4]), sparse (zeros (4,0)))\n%!error <operator -: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) - sparse ([1; 2; 3; 4])\n%!error <operator \\*: nonconformant arguments \\(op1 is 1x0, op2 is 4x1\\)>\n%! sparse (zeros (1,0)) * sparse ([1; 2; 3; 4])\n%!error <operator \\*: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) * sparse ([1; 2; 3; 4])\n%!assert (sparse (zeros (1,0)) .* sparse ([1; 2; 3; 4]), sparse (zeros (4,0)))\n%!error <product: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) .* sparse ([1; 2; 3; 4])\n%!assert (sparse (zeros (1,0)) ./ sparse ([1; 2; 3; 4]), sparse (zeros (4,0)))\n%!error <quotient: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) ./ sparse ([1; 2; 3; 4])\n%!test\n%! a = sparse (zeros (1,0));\n%! assert (a += sparse ([1; 2; 3; 4]), sparse (zeros (4,0)));\n%! assert (a -= sparse ([1; 2; 3; 4]), sparse (zeros (4,0)));\n\n## Test broadcasting of sparse matrices with math operators\n%!assert (full (sparse ([1, 2, 3]) + sparse ([1, 2, 3; 4, 5, 6])),\n%!        [1, 2, 3] + [1, 2, 3; 4, 5, 6])\n%!assert (full (sparse ([1, 0, NaN]) + sparse ([1, 0, 0; 0, NaN, 6])),\n%!        [1, 0, NaN] + [1, 0, 0; 0, NaN, 6])\n%!assert (full (sparse ([1; 2; 3]) + sparse ([1, 2; 1, 2; 1, 2])),\n%!        [1; 2; 3] + [1, 2; 1, 2; 1, 2])\n%!assert (full (sparse ([1; 0; NaN]) + sparse ([0, 0; NaN, 2; 0, 2])),\n%!        [1; 0; NaN] + [0, 0; NaN, 2; 0, 2])\n%!assert (full (sparse ([1, 2, 3]) + sparse ([1; 2; 3; 4])),\n%!        [1, 2, 3] + [1; 2; 3; 4])\n%!assert (full (sparse ([NaN, 0, 0]) + sparse ([1; 0; 0; NaN])),\n%!        [NaN, 0, 0] + [1; 0; 0; NaN])\n%!assert (full (sparse ([1; 2; 3]) + sparse ([1, 2, 3, 4, 5])),\n%!        [1; 2; 3] + [1, 2, 3, 4, 5])\n%!assert (full (sparse ([1; 0; NaN]) + sparse ([0, 0, 3, 0, 5])),\n%!        [1; 0; NaN] + [0, 0, 3, 0, 5])\n%!assert (full (sparse ([1, 0, 3]) + sparse ([1, 0, 3; 0, 5, 6])),\n%!        [1, 0, 3] + [1, 0, 3; 0, 5, 6])\n%!assert (full (sparse ([NaN, 0, 3]) + sparse ([1, 0, 3; 0, 5, NaN])),\n%!        [NaN, 0, 3] + [1, 0, 3; 0, 5, NaN])\n%!assert (full (sparse ([1; 2; 0]) + sparse ([1, 2; 1, 0; 0, 0])),\n%!        [1; 2; 0] + [1, 2; 1, 0; 0, 0])\n%!assert (full (sparse ([0; 2; 0]) + sparse ([1, NaN; 1, 0; 0, 0])),\n%!        [0; 2; 0] + [1, NaN; 1, 0; 0, 0])\n%!assert (full (sparse ([0, 0, 3]) + sparse ([1; 2; 3; 4])),\n%!        [0, 0, 3] + [1; 2; 3; 4])\n%!assert (full (sparse ([0, 0, NaN]) + sparse ([1; 2; 3; 4])),\n%!        [0, 0, NaN] + [1; 2; 3; 4])\n%!assert (full (sparse ([1; 2; 3]) + sparse ([1, 0, 0, 0, 5])),\n%!        [1; 2; 3] + [1, 0, 0, 0, 5])\n%!assert (full (sparse ([1; 2; 0]) + sparse ([NaN, 0, 0, 0, NaN])),\n%!        [1; 2; 0] + [NaN, 0, 0, 0, NaN])\n%!assert (full (sparse ([1, 2, 3; 4, 5, 6]) + sparse ([1, 2, 3])),\n%!        [1, 2, 3; 4, 5, 6] + [1, 2, 3])\n%!assert (full (sparse ([1, 0, 0; 4, 0, 0]) + sparse ([NaN, 2, 0])),\n%!        [1, 0, 0; 4, 0, 0] + [NaN, 2, 0])\n%!assert (full (sparse ([1, 2; 1, 2; 1, 2]) + sparse ([1; 2; 3])),\n%!        [1, 2; 1, 2; 1, 2] + [1; 2; 3])\n%!assert (full (sparse ([1, 0; 0, 0; 0, 2]) + sparse ([1; NaN; 3])),\n%!        [1, 0; 0, 0; 0, 2] + [1; NaN; 3])\n%!assert (full (sparse ([1; 2; 3; 4]) + sparse ([1, 2, 3])),\n%!        [1; 2; 3; 4] + [1, 2, 3])\n%!assert (full (sparse ([1; 0; NaN; NaN]) + sparse ([1, 0, 0])),\n%!        [1; 0; NaN; NaN] + [1, 0, 0])\n%!assert (full (sparse ([1, 2, 3, 4, 5]) + sparse ([1; 2; 3])),\n%!        [1, 2, 3, 4, 5] + [1; 2; 3])\n%!assert (full (sparse ([1, 2, 0, 0, 0]) + sparse ([1; NaN; 0])),\n%!        [1, 2, 0, 0, 0] + [1; NaN; 0])\n%!assert (full (sparse ([1, 0, 3; 0, 5, 6]) + sparse ([1, 0, 3])),\n%!        [1, 0, 3; 0, 5, 6] + [1, 0, 3])\n%!assert (full (sparse ([1, 0, NaN; 0, NaN, 6]) + sparse ([1, 0, 3])),\n%!        [1, 0, NaN; 0, NaN, 6] + [1, 0, 3])\n%!assert (full (sparse ([1, 2; 1, 0; 0, 0]) + sparse ([1; 2; 0])),\n%!        [1, 2; 1, 0; 0, 0] + [1; 2; 0])\n%!assert (full (sparse ([0, NaN; NaN, 0; 0, 0]) + sparse ([1; 0; 0])),\n%!        [0, NaN; NaN, 0; 0, 0] + [1; 0; 0])\n%!assert (full (sparse ([1; 2; 3; 4]) + sparse ([0, 0, 3])),\n%!        [1; 2; 3; 4] + [0, 0, 3])\n%!assert (full (sparse ([1; 2; 0; 4]) + sparse ([0, 0, NaN])),\n%!        [1; 2; 0; 4] + [0, 0, NaN])\n%!assert (full (sparse ([1, 0, 0, 0, 5]) + sparse ([1; 2; 3])),\n%!        [1, 0, 0, 0, 5] + [1; 2; 3])\n%!assert (full (sparse ([NaN, 0, 0, 0, 5]) + sparse ([1; NaN; 0])),\n%!        [NaN, 0, 0, 0, 5] + [1; NaN; 0])\n\n%!assert (sparse (1) + sparse ([1, 2, 3]), sparse ([2, 3, 4]))\n%!assert (sparse (1) + sparse ([1, 2; 3, 4]), sparse ([2, 3; 4, 5]))\n%!assert (sparse ([1, 2, 3]) + sparse (1), sparse ([2, 3, 4]))\n%!assert (sparse ([1, 2; 3, 4]) + sparse (1), sparse ([2, 3; 4, 5]))\n%!assert (sparse (NaN) + sparse ([1, 2, 3]), sparse ([NaN, NaN, NaN]))\n%!assert (sparse (NaN) + sparse ([1, 2; 3, 4]), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (sparse ([1, 2, 3]) + sparse (NaN), sparse ([NaN, NaN, NaN]))\n%!assert (sparse ([1, 2; 3, 4]) + sparse (NaN), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (full (sparse ([1; 2]) + sparse ([1, 0, 2, 0, 4])),\n%!        [1; 2] + [1, 0, 2, 0, 4])\n%!assert (full (sparse ([1, 0, 2, 0, 4]) + sparse ([1; 2])),\n%!        [1, 0, 2, 0, 4] + [1; 2])\n%!assert (full (sparse ([1, 2]) + sparse ([1; 0; 2; 0; 4])),\n%!        [1, 2] + [1; 0; 2; 0; 4])\n%!assert (full (sparse ([1; 0; 2; 0; 4]) + sparse ([1, 2])),\n%!        [1; 0; 2; 0; 4] + [1, 2])\n%!assert (full (sparse ([1, 0, 3]) + sparse ([1, 2, 3; 4, 0, 0])),\n%!        [1, 0, 3] + [1, 2, 3; 4, 0, 0])\n%!assert (full (sparse ([10, 0, 3; 4, 5, 0]) + sparse ([1, 0, 3])),\n%!        [10, 0, 3; 4, 5, 0] + [1, 0, 3])\n%!assert (full (sparse ([1; 2; 0]) + sparse ([0, 2; 3, 4; 5, 0])),\n%!        [1; 2; 0] + [0, 2; 3, 4; 5, 0])\n%!assert (full (sparse ([1, 2; 0, 0; 0, 6]) + sparse ([0; 2; 3])),\n%!        [1, 2; 0, 0; 0, 6] + [0; 2; 3])\n\n%!assert (full (sparse ([1, 2, 3]) - sparse ([1, 2, 3; 4, 5, 6])),\n%!        [1, 2, 3] - [1, 2, 3; 4, 5, 6])\n%!assert (full (sparse ([1, 0, NaN]) - sparse ([1, 0, 0; 0, NaN, 6])),\n%!        [1, 0, NaN] - [1, 0, 0; 0, NaN, 6])\n%!assert (full (sparse ([1; 2; 3]) - sparse ([1, 2; 1, 2; 1, 2])),\n%!        [1; 2; 3] - [1, 2; 1, 2; 1, 2])\n%!assert (full (sparse ([1; 0; NaN]) - sparse ([0, 0; NaN, 2; 0, 2])),\n%!        [1; 0; NaN] - [0, 0; NaN, 2; 0, 2])\n%!assert (full (sparse ([1, 2, 3]) - sparse ([1; 2; 3; 4])),\n%!        [1, 2, 3] - [1; 2; 3; 4])\n%!assert (full (sparse ([NaN, 0, 0]) - sparse ([1; 0; 0; NaN])),\n%!        [NaN, 0, 0] - [1; 0; 0; NaN])\n%!assert (full (sparse ([1; 2; 3]) - sparse ([1, 2, 3, 4, 5])),\n%!        [1; 2; 3] - [1, 2, 3, 4, 5])\n%!assert (full (sparse ([1; 0; NaN]) - sparse ([0, 0, 3, 0, 5])),\n%!        [1; 0; NaN] - [0, 0, 3, 0, 5])\n%!assert (full (sparse ([1, 0, 3]) - sparse ([1, 0, 3; 0, 5, 6])),\n%!        [1, 0, 3] - [1, 0, 3; 0, 5, 6])\n%!assert (full (sparse ([NaN, 0, 3]) - sparse ([1, 0, 3; 0, 5, NaN])),\n%!        [NaN, 0, 3] - [1, 0, 3; 0, 5, NaN])\n%!assert (full (sparse ([1; 2; 0]) - sparse ([1, 2; 1, 0; 0, 0])),\n%!        [1; 2; 0] - [1, 2; 1, 0; 0, 0])\n%!assert (full (sparse ([0; 2; 0]) - sparse ([1, NaN; 1, 0; 0, 0])),\n%!        [0; 2; 0] - [1, NaN; 1, 0; 0, 0])\n%!assert (full (sparse ([0, 0, 3]) - sparse ([1; 2; 3; 4])),\n%!        [0, 0, 3] - [1; 2; 3; 4])\n%!assert (full (sparse ([0, 0, NaN]) - sparse ([1; 2; 3; 4])),\n%!        [0, 0, NaN] - [1; 2; 3; 4])\n%!assert (full (sparse ([1; 2; 3]) - sparse ([1, 0, 0, 0, 5])),\n%!        [1; 2; 3] - [1, 0, 0, 0, 5])\n%!assert (full (sparse ([1; 2; 0]) - sparse ([NaN, 0, 0, 0, NaN])),\n%!        [1; 2; 0] - [NaN, 0, 0, 0, NaN])\n%!assert (full (sparse ([1, 2, 3; 4, 5, 6]) - sparse ([1, 2, 3])),\n%!        [1, 2, 3; 4, 5, 6] - [1, 2, 3])\n%!assert (full (sparse ([1, 0, 0; 4, 0, 0]) - sparse ([NaN, 2, 0])),\n%!        [1, 0, 0; 4, 0, 0] - [NaN, 2, 0])\n%!assert (full (sparse ([1, 2; 1, 2; 1, 2]) - sparse ([1; 2; 3])),\n%!        [1, 2; 1, 2; 1, 2] - [1; 2; 3])\n%!assert (full (sparse ([1, 0; 0, 0; 0, 2]) - sparse ([1; NaN; 3])),\n%!        [1, 0; 0, 0; 0, 2] - [1; NaN; 3])\n%!assert (full (sparse ([1; 2; 3; 4]) - sparse ([1, 2, 3])),\n%!        [1; 2; 3; 4] - [1, 2, 3])\n%!assert (full (sparse ([1; 0; NaN; NaN]) - sparse ([1, 0, 0])),\n%!        [1; 0; NaN; NaN] - [1, 0, 0])\n%!assert (full (sparse ([1, 2, 3, 4, 5]) - sparse ([1; 2; 3])),\n%!        [1, 2, 3, 4, 5] - [1; 2; 3])\n%!assert (full (sparse ([1, 2, 0, 0, 0]) - sparse ([1; NaN; 0])),\n%!        [1, 2, 0, 0, 0] - [1; NaN; 0])\n%!assert (full (sparse ([1, 0, 3; 0, 5, 6]) - sparse ([1, 0, 3])),\n%!        [1, 0, 3; 0, 5, 6] - [1, 0, 3])\n%!assert (full (sparse ([1, 0, NaN; 0, NaN, 6]) - sparse ([1, 0, 3])),\n%!        [1, 0, NaN; 0, NaN, 6] - [1, 0, 3])\n%!assert (full (sparse ([1, 2; 1, 0; 0, 0]) - sparse ([1; 2; 0])),\n%!        [1, 2; 1, 0; 0, 0] - [1; 2; 0])\n%!assert (full (sparse ([0, NaN; NaN, 0; 0, 0]) - sparse ([1; 0; 0])),\n%!        [0, NaN; NaN, 0; 0, 0] - [1; 0; 0])\n%!assert (full (sparse ([1; 2; 3; 4]) - sparse ([0, 0, 3])),\n%!        [1; 2; 3; 4] - [0, 0, 3])\n%!assert (full (sparse ([1; 2; 0; 4]) - sparse ([0, 0, NaN])),\n%!        [1; 2; 0; 4] - [0, 0, NaN])\n%!assert (full (sparse ([1, 0, 0, 0, 5]) - sparse ([1; 2; 3])),\n%!        [1, 0, 0, 0, 5] - [1; 2; 3])\n%!assert (full (sparse ([NaN, 0, 0, 0, 5]) - sparse ([1; NaN; 0])),\n%!        [NaN, 0, 0, 0, 5] - [1; NaN; 0])\n\n%!assert (sparse (1) - sparse ([1, 2, 3]), sparse ([0, -1, -2]))\n%!assert (sparse (1) - sparse ([1, 2; 3, 4]), sparse ([0, -1; -2, -3]))\n%!assert (sparse ([1, 2, 3]) - sparse (1), sparse ([0, 1, 2]))\n%!assert (sparse ([1, 2; 3, 4]) - sparse (1), sparse ([0, 1; 2, 3]))\n%!assert (sparse (NaN) - sparse ([1, 2, 3]), sparse ([NaN, NaN, NaN]))\n%!assert (sparse (NaN) - sparse ([1, 2; 3, 4]), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (sparse ([1, 2, 3]) - sparse (NaN), sparse ([NaN, NaN, NaN]))\n%!assert (sparse ([1, 2; 3, 4]) - sparse (NaN), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (full (sparse ([1; 2]) - sparse ([1, 0, 2, 0, 4])),\n%!        [1; 2] - [1, 0, 2, 0, 4])\n%!assert (full (sparse ([1, 0, 2, 0, 4]) - sparse ([1; 2])),\n%!        [1, 0, 2, 0, 4] - [1; 2])\n%!assert (full (sparse ([1, 2]) - sparse ([1; 0; 2; 0; 4])),\n%!        [1, 2] - [1; 0; 2; 0; 4])\n%!assert (full (sparse ([1; 0; 2; 0; 4]) - sparse ([1, 2])),\n%!        [1; 0; 2; 0; 4] - [1, 2])\n%!assert (full (sparse ([1, 0, 3]) - sparse ([1, 2, 3; 4, 0, 0])),\n%!        [1, 0, 3] - [1, 2, 3; 4, 0, 0])\n%!assert (full (sparse ([10, 0, 3; 4, 5, 0]) - sparse ([1, 0, 3])),\n%!        [10, 0, 3; 4, 5, 0] - [1, 0, 3])\n%!assert (full (sparse ([1; 2; 0]) - sparse ([0, 2; 3, 4; 5, 0])),\n%!        [1; 2; 0] - [0, 2; 3, 4; 5, 0])\n%!assert (full (sparse ([1, 2; 0, 0; 0, 6]) - sparse ([0; 2; 3])),\n%!        [1, 2; 0, 0; 0, 6] - [0; 2; 3])\n\n%!assert (full (sparse ([1, 2, 3]) .* sparse ([1, 2, 3; 4, 5, 6])),\n%!        [1, 2, 3] .* [1, 2, 3; 4, 5, 6])\n%!assert (full (sparse ([1, 0, NaN]) .* sparse ([1, 0, 0; 0, NaN, 6])),\n%!        [1, 0, NaN] .* [1, 0, 0; 0, NaN, 6])\n%!assert (full (sparse ([1; 2; 3]) .* sparse ([1, 2; 1, 2; 1, 2])),\n%!        [1; 2; 3] .* [1, 2; 1, 2; 1, 2])\n%!assert (full (sparse ([1; 0; NaN]) .* sparse ([0, 0; NaN, 2; 0, 2])),\n%!        [1; 0; NaN] .* [0, 0; NaN, 2; 0, 2])\n%!assert (full (sparse ([1, 2, 3]) .* sparse ([1; 2; 3; 4])),\n%!        [1, 2, 3] .* [1; 2; 3; 4])\n%!assert (full (sparse ([NaN, 0, 0]) .* sparse ([1; 0; 0; NaN])),\n%!        [NaN, 0, 0] .* [1; 0; 0; NaN])\n%!assert (full (sparse ([1; 2; 3]) .* sparse ([1, 2, 3, 4, 5])),\n%!        [1; 2; 3] .* [1, 2, 3, 4, 5])\n%!assert (full (sparse ([1; 0; NaN]) .* sparse ([0, 0, 3, 0, 5])),\n%!        [1; 0; NaN] .* [0, 0, 3, 0, 5])\n%!assert (full (sparse ([1, 0, 3]) .* sparse ([1, 0, 3; 0, 5, 6])),\n%!        [1, 0, 3] .* [1, 0, 3; 0, 5, 6])\n%!assert (full (sparse ([NaN, 0, 3]) .* sparse ([1, 0, 3; 0, 5, NaN])),\n%!        [NaN, 0, 3] .* [1, 0, 3; 0, 5, NaN])\n%!assert (full (sparse ([1; 2; 0]) .* sparse ([1, 2; 1, 0; 0, 0])),\n%!        [1; 2; 0] .* [1, 2; 1, 0; 0, 0])\n%!assert (full (sparse ([0; 2; 0]) .* sparse ([1, NaN; 1, 0; 0, 0])),\n%!        [0; 2; 0] .* [1, NaN; 1, 0; 0, 0])\n%!assert (full (sparse ([0, 0, 3]) .* sparse ([1; 2; 3; 4])),\n%!        [0, 0, 3] .* [1; 2; 3; 4])\n%!assert (full (sparse ([0, 0, NaN]) .* sparse ([1; 2; 3; 4])),\n%!        [0, 0, NaN] .* [1; 2; 3; 4])\n%!assert (full (sparse ([1; 2; 3]) .* sparse ([1, 0, 0, 0, 5])),\n%!        [1; 2; 3] .* [1, 0, 0, 0, 5])\n%!assert (full (sparse ([1; 2; 0]) .* sparse ([NaN, 0, 0, 0, NaN])),\n%!        [1; 2; 0] .* [NaN, 0, 0, 0, NaN])\n%!assert (full (sparse ([1, 2, 3; 4, 5, 6]) .* sparse ([1, 2, 3])),\n%!        [1, 2, 3; 4, 5, 6] .* [1, 2, 3])\n%!assert (full (sparse ([1, 0, 0; 4, 0, 0]) .* sparse ([NaN, 2, 0])),\n%!        [1, 0, 0; 4, 0, 0] .* [NaN, 2, 0])\n%!assert (full (sparse ([1, 2; 1, 2; 1, 2]) .* sparse ([1; 2; 3])),\n%!        [1, 2; 1, 2; 1, 2] .* [1; 2; 3])\n%!assert (full (sparse ([1, 0; 0, 0; 0, 2]) .* sparse ([1; NaN; 3])),\n%!        [1, 0; 0, 0; 0, 2] .* [1; NaN; 3])\n%!assert (full (sparse ([1; 2; 3; 4]) .* sparse ([1, 2, 3])),\n%!        [1; 2; 3; 4] .* [1, 2, 3])\n%!assert (full (sparse ([1; 0; NaN; NaN]) .* sparse ([1, 0, 0])),\n%!        [1; 0; NaN; NaN] .* [1, 0, 0])\n%!assert (full (sparse ([1, 2, 3, 4, 5]) .* sparse ([1; 2; 3])),\n%!        [1, 2, 3, 4, 5] .* [1; 2; 3])\n%!assert (full (sparse ([1, 2, 0, 0, 0]) .* sparse ([1; NaN; 0])),\n%!        [1, 2, 0, 0, 0] .* [1; NaN; 0])\n%!assert (full (sparse ([1, 0, 3; 0, 5, 6]) .* sparse ([1, 0, 3])),\n%!        [1, 0, 3; 0, 5, 6] .* [1, 0, 3])\n%!assert (full (sparse ([1, 0, NaN; 0, NaN, 6]) .* sparse ([1, 0, 3])),\n%!        [1, 0, NaN; 0, NaN, 6] .* [1, 0, 3])\n%!assert (full (sparse ([1, 2; 1, 0; 0, 0]) .* sparse ([1; 2; 0])),\n%!        [1, 2; 1, 0; 0, 0] .* [1; 2; 0])\n%!assert (full (sparse ([0, NaN; NaN, 0; 0, 0]) .* sparse ([1; 0; 0])),\n%!        [0, NaN; NaN, 0; 0, 0] .* [1; 0; 0])\n%!assert (full (sparse ([1; 2; 3; 4]) .* sparse ([0, 0, 3])),\n%!        [1; 2; 3; 4] .* [0, 0, 3])\n%!assert (full (sparse ([1; 2; 0; 4]) .* sparse ([0, 0, NaN])),\n%!        [1; 2; 0; 4] .* [0, 0, NaN])\n%!assert (full (sparse ([1, 0, 0, 0, 5]) .* sparse ([1; 2; 3])),\n%!        [1, 0, 0, 0, 5] .* [1; 2; 3])\n%!assert (full (sparse ([NaN, 0, 0, 0, 5]) .* sparse ([1; NaN; 0])),\n%!        [NaN, 0, 0, 0, 5] .* [1; NaN; 0])\n\n%!assert (sparse (1) .* sparse ([1, 2, 3]), sparse ([1, 2, 3]))\n%!assert (sparse (1) .* sparse ([1, 2; 3, 4]), sparse ([1, 2; 3, 4]))\n%!assert (sparse ([1, 2, 3]) .* sparse (1), sparse ([1, 2, 3]))\n%!assert (sparse ([1, 2; 3, 4]) .* sparse (1), sparse ([1, 2; 3, 4]))\n%!assert (sparse (NaN) .* sparse ([1, 2, 3]), sparse ([NaN, NaN, NaN]))\n%!assert (sparse (NaN) .* sparse ([1, 2; 3, 4]), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (sparse ([1, 2, 3]) .* sparse (NaN), sparse ([NaN, NaN, NaN]))\n%!assert (sparse ([1, 2; 3, 4]) .* sparse (NaN), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (sparse (NaN) .* sparse ([1, 0, 0]), sparse ([NaN, NaN, NaN]))\n%!assert (sparse (NaN) .* sparse ([1, 0; 3, 0]), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (sparse ([0, 0, 3]) .* sparse (NaN), sparse ([NaN, NaN, NaN]))\n%!assert (sparse ([1, 0; 0, 0]) .* sparse (NaN), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (full (sparse ([1; 2]) .* sparse ([1, 0, 2, 0, 4])),\n%!        [1; 2] .* [1, 0, 2, 0, 4])\n%!assert (full (sparse ([1, 0, 2, 0, 4]) .* sparse ([1; 2])),\n%!        [1, 0, 2, 0, 4] .* [1; 2])\n%!assert (full (sparse ([1, 2]) .* sparse ([1; 0; 2; 0; 4])),\n%!        [1, 2] .* [1; 0; 2; 0; 4])\n%!assert (full (sparse ([1; 0; 2; 0; 4]) .* sparse ([1, 2])),\n%!        [1; 0; 2; 0; 4] .* [1, 2])\n%!assert (full (sparse ([1, 0, 3]) .* sparse ([1, 2, 3; 4, 0, 0])),\n%!        [1, 0, 3] .* [1, 2, 3; 4, 0, 0])\n%!assert (full (sparse ([10, 0, 3; 4, 5, 0]) .* sparse ([1, 0, 3])),\n%!        [10, 0, 3; 4, 5, 0] .* [1, 0, 3])\n%!assert (full (sparse ([1; 2; 0]) .* sparse ([0, 2; 3, 4; 5, 0])),\n%!        [1; 2; 0] .* [0, 2; 3, 4; 5, 0])\n%!assert (full (sparse ([1, 2; 0, 0; 0, 6]) .* sparse ([0; 2; 3])),\n%!        [1, 2; 0, 0; 0, 6] .* [0; 2; 3])\n\n%!assert (full (sparse ([1, 2, 3]) ./ sparse ([1, 2, 3; 4, 5, 6])),\n%!        [1, 2, 3] ./ [1, 2, 3; 4, 5, 6])\n%!assert (full (sparse ([1, 0, NaN]) ./ sparse ([1, 0, 0; 0, NaN, 6])),\n%!        [1, 0, NaN] ./ [1, 0, 0; 0, NaN, 6])\n%!assert (full (sparse ([1; 2; 3]) ./ sparse ([1, 2; 1, 2; 1, 2])),\n%!        [1; 2; 3] ./ [1, 2; 1, 2; 1, 2])\n%!assert (full (sparse ([1; 0; NaN]) ./ sparse ([0, 0; NaN, 2; 0, 2])),\n%!        [1; 0; NaN] ./ [0, 0; NaN, 2; 0, 2])\n%!assert (full (sparse ([1, 2, 3]) ./ sparse ([1; 2; 3; 4])),\n%!        [1, 2, 3] ./ [1; 2; 3; 4])\n%!assert (full (sparse ([NaN, 0, 0]) ./ sparse ([1; 0; 0; NaN])),\n%!        [NaN, 0, 0] ./ [1; 0; 0; NaN])\n%!assert (full (sparse ([1; 2; 3]) ./ sparse ([1, 2, 3, 4, 5])),\n%!        [1; 2; 3] ./ [1, 2, 3, 4, 5])\n%!assert (full (sparse ([1; 0; NaN]) ./ sparse ([0, 0, 3, 0, 5])),\n%!        [1; 0; NaN] ./ [0, 0, 3, 0, 5])\n%!assert (full (sparse ([1, 0, 3]) ./ sparse ([1, 0, 3; 0, 5, 6])),\n%!        [1, 0, 3] ./ [1, 0, 3; 0, 5, 6])\n%!assert (full (sparse ([NaN, 0, 3]) ./ sparse ([1, 0, 3; 0, 5, NaN])),\n%!        [NaN, 0, 3] ./ [1, 0, 3; 0, 5, NaN])\n%!assert (full (sparse ([1; 2; 0]) ./ sparse ([1, 2; 1, 0; 0, 0])),\n%!        [1; 2; 0] ./ [1, 2; 1, 0; 0, 0])\n%!assert (full (sparse ([0; 2; 0]) ./ sparse ([1, NaN; 1, 0; 0, 0])),\n%!        [0; 2; 0] ./ [1, NaN; 1, 0; 0, 0])\n%!assert (full (sparse ([0, 0, 3]) ./ sparse ([1; 2; 3; 4])),\n%!        [0, 0, 3] ./ [1; 2; 3; 4])\n%!assert (full (sparse ([0, 0, NaN]) ./ sparse ([1; 2; 3; 4])),\n%!        [0, 0, NaN] ./ [1; 2; 3; 4])\n%!assert (full (sparse ([1; 2; 3]) ./ sparse ([1, 0, 0, 0, 5])),\n%!        [1; 2; 3] ./ [1, 0, 0, 0, 5])\n%!assert (full (sparse ([1; 2; 0]) ./ sparse ([NaN, 0, 0, 0, NaN])),\n%!        [1; 2; 0] ./ [NaN, 0, 0, 0, NaN])\n%!assert (full (sparse ([1, 2, 3; 4, 5, 6]) ./ sparse ([1, 2, 3])),\n%!        [1, 2, 3; 4, 5, 6] ./ [1, 2, 3])\n%!assert (full (sparse ([1, 0, 0; 4, 0, 0]) ./ sparse ([NaN, 2, 0])),\n%!        [1, 0, 0; 4, 0, 0] ./ [NaN, 2, 0])\n%!assert (full (sparse ([1, 2; 1, 2; 1, 2]) ./ sparse ([1; 2; 3])),\n%!        [1, 2; 1, 2; 1, 2] ./ [1; 2; 3])\n%!assert (full (sparse ([1, 0; 0, 0; 0, 2]) ./ sparse ([1; NaN; 3])),\n%!        [1, 0; 0, 0; 0, 2] ./ [1; NaN; 3])\n%!assert (full (sparse ([1; 2; 3; 4]) ./ sparse ([1, 2, 3])),\n%!        [1; 2; 3; 4] ./ [1, 2, 3])\n%!assert (full (sparse ([1; 0; NaN; NaN]) ./ sparse ([1, 0, 0])),\n%!        [1; 0; NaN; NaN] ./ [1, 0, 0])\n%!assert (full (sparse ([1, 2, 3, 4, 5]) ./ sparse ([1; 2; 3])),\n%!        [1, 2, 3, 4, 5] ./ [1; 2; 3])\n%!assert (full (sparse ([1, 2, 0, 0, 0]) ./ sparse ([1; NaN; 0])),\n%!        [1, 2, 0, 0, 0] ./ [1; NaN; 0])\n%!assert (full (sparse ([1, 0, 3; 0, 5, 6]) ./ sparse ([1, 0, 3])),\n%!        [1, 0, 3; 0, 5, 6] ./ [1, 0, 3])\n%!assert (full (sparse ([1, 0, NaN; 0, NaN, 6]) ./ sparse ([1, 0, 3])),\n%!        [1, 0, NaN; 0, NaN, 6] ./ [1, 0, 3])\n%!assert (full (sparse ([1, 2; 1, 0; 0, 0]) ./ sparse ([1; 2; 0])),\n%!        [1, 2; 1, 0; 0, 0] ./ [1; 2; 0])\n%!assert (full (sparse ([0, NaN; NaN, 0; 0, 0]) ./ sparse ([1; 0; 0])),\n%!        [0, NaN; NaN, 0; 0, 0] ./ [1; 0; 0])\n%!assert (full (sparse ([1; 2; 3; 4]) ./ sparse ([0, 0, 3])),\n%!        [1; 2; 3; 4] ./ [0, 0, 3])\n%!assert (full (sparse ([1; 2; 0; 4]) ./ sparse ([0, 0, NaN])),\n%!        [1; 2; 0; 4] ./ [0, 0, NaN])\n%!assert (full (sparse ([1, 0, 0, 0, 5]) ./ sparse ([1; 2; 3])),\n%!        [1, 0, 0, 0, 5] ./ [1; 2; 3])\n%!assert (full (sparse ([NaN, 0, 0, 0, 5]) ./ sparse ([1; NaN; 0])),\n%!        [NaN, 0, 0, 0, 5] ./ [1; NaN; 0])\n\n%!assert (sparse (1) ./ sparse ([1, 2, 3]), sparse ([1, 1/2, 1/3]))\n%!assert (sparse (1) ./ sparse ([1, 2; 3, 4]), sparse ([1, 1/2; 1/3, 1/4]))\n%!assert (sparse ([1, 2, 3]) ./ sparse (1), sparse ([1, 2, 3]))\n%!assert (sparse ([1, 2; 3, 4]) ./ sparse (1), sparse ([1, 2; 3, 4]))\n%!assert (sparse (0) ./ sparse ([1, 0, 3]), sparse ([0, NaN, 0]))\n%!assert (sparse (0) ./ sparse ([1, 2; 0, 4]), sparse ([0, 0; NaN, 0]))\n%!assert (sparse ([-1, 0, 3]) ./ sparse (0), sparse ([-Inf, NaN, Inf]))\n%!assert (sparse ([1, 2; 0, -4]) ./ sparse (0), sparse ([Inf, Inf; NaN, -Inf]))\n%!assert (sparse (NaN) ./ sparse ([1, 2, 3]), sparse ([NaN, NaN, NaN]))\n%!assert (sparse (NaN) ./ sparse ([1, 2; 3, 4]), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (sparse ([1, 2, 3]) ./ sparse (NaN), sparse ([NaN, NaN, NaN]))\n%!assert (sparse ([1, 2; 3, 4]) ./ sparse (NaN), sparse ([NaN, NaN; NaN, NaN]))\n%!assert (full (sparse ([1; 2]) ./ sparse ([1, 0, 2, 0, 4])),\n%!        [1; 2] ./ [1, 0, 2, 0, 4])\n%!assert (full (sparse ([1, 0, 2, 0, 4]) ./ sparse ([1; 2])),\n%!        [1, 0, 2, 0, 4] ./ [1; 2])\n%!assert (full (sparse ([1, 2]) ./ sparse ([1; 0; 2; 0; 4])),\n%!        [1, 2] ./ [1; 0; 2; 0; 4])\n%!assert (full (sparse ([1; 0; 2; 0; 4]) ./ sparse ([1, 2])),\n%!        [1; 0; 2; 0; 4] ./ [1, 2])\n%!assert (full (sparse ([1, 0, 3]) ./ sparse ([1, 2, 3; 4, 0, 0])),\n%!        [1, 0, 3] ./ [1, 2, 3; 4, 0, 0])\n%!assert (full (sparse ([10, 0, 3; 4, 5, 0]) ./ sparse ([1, 0, 3])),\n%!        [10, 0, 3; 4, 5, 0] ./ [1, 0, 3])\n%!assert (full (sparse ([1; 2; 0]) ./ sparse ([0, 2; 3, 4; 5, 0])),\n%!        [1; 2; 0] ./ [0, 2; 3, 4; 5, 0])\n%!assert (full (sparse ([1, 2; 0, 0; 0, 6]) ./ sparse ([0; 2; 3])),\n%!        [1, 2; 0, 0; 0, 6] ./ [0; 2; 3])\n\n## Test broadcasting for math operations with scalar and sparse matrix\n%!assert (sparse ([1, 2]) + 1, [2, 3])\n%!assert (sparse ([1, 0]) + NaN, [NaN, NaN])\n%!assert (1 + sparse ([1, 2]), [2, 3])\n%!assert (1 + sparse ([0, NaN]), [1, NaN])\n%!assert (sparse ([1, 2]) - 1, [0, 1])\n%!assert (1 - sparse ([1, 2]), [0, -1])\n%!assert (sparse ([0, 0]) - NaN, [NaN, NaN])\n%!assert (1 - sparse ([1, NaN]), [0, NaN])\n%!assert (sparse ([1, 2]) .* 1, sparse ([1, 2]))\n%!assert (sparse ([1, Inf]) .* 0, sparse ([0, NaN]))\n%!assert (sparse ([0, Inf]) .* -Inf, sparse ([NaN, -Inf]))\n%!assert (1 .* sparse ([1, 2]), sparse ([1, 2]))\n%!assert (NaN .* sparse ([0, 2]), sparse ([NaN, NaN]))\n%!assert (sparse ([1, 2]) ./ 1, sparse ([1, 2]))\n%!assert (sparse ([0, Inf]) ./ Inf, sparse ([0, NaN]))\n%!assert (1 ./ sparse ([1, 2]), [1, 0.5])\n%!assert (0 ./ sparse ([1, 0]), [0, NaN])\n%!assert (NaN ./ sparse ([1, 0]), [NaN, NaN])\n%!error <operator /: nonconformant arguments \\(op1 is 1x1, op2 is 1x2\\)>\n%! 1 / sparse ([1, 2])\n\n## Test broadcasting for math operations with matrix and sparse matrix\n%!assert (sparse ([1, 2]) + [1, 1], [2, 3])\n%!assert (sparse ([1, NaN]) + [1, 1], [2, NaN])\n%!assert ([1, 1] + sparse ([1, 2]), [2, 3])\n%!assert ([1, NaN] + sparse ([0, 0]), [1, NaN])\n%!assert (sparse ([1; 2]) + [1; 1], [2; 3])\n%!assert (sparse ([-Inf; 0]) + [Inf; NaN], [NaN; NaN])\n%!assert ([1; 1] + sparse ([1; 2]), [2; 3])\n%!assert ([0; NaN] + sparse ([0; 0]), [0; NaN])\n%!assert (sparse ([1, 2, 3]) + ones (3), repmat ([2:4], 3, 1))\n%!assert (sparse ([1, 0, NaN]) + ones (3), repmat ([2, 1, NaN], 3, 1))\n%!assert (sparse ([1; 2; 3]) + ones (3), repmat ([2:4]', 1, 3))\n%!assert (sparse ([-Inf; 0; NaN]) + ones (3) * Inf, repmat ([NaN, Inf, NaN]', 1, 3))\n%!assert (ones (3) + sparse ([1, 2, 3]), repmat ([2:4], 3, 1))\n%!assert (ones (3) + sparse ([1; 2; 3]), repmat ([2:4]', 1, 3))\n%!assert (sparse ([1, 2]) + [1; 2], [2, 3; 3, 4])\n%!assert (sparse ([0, 0]) + [NaN; 2], [NaN, NaN; 2, 2])\n%!assert ([1; 2] + sparse ([1, 2]), [2, 3; 3, 4])\n%!assert (sparse ([1; 2]) + [1, 2], [2, 3; 3, 4])\n%!assert ([1, 2] + sparse ([1; 2]), [2, 3; 3, 4])\n%!error <operator \\+: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2]) + [1, 1, 1]\n%!error <operator \\+: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3]) + ones (4)\n%!error <operator \\+: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2; 3]) + ones (4, 3)\n\n%!assert (sparse ([1, 2]) - [1, 1], [0, 1])\n%!assert ([1, 1] - sparse ([1, 2]), [0, -1])\n%!assert (sparse ([1; 2]) - [1; 1], [0; 1])\n%!assert ([1; 1] - sparse ([1; 2]), [0; -1])\n%!assert (sparse ([1, 2, 3]) - ones (3), repmat ([0:2], 3, 1))\n%!assert (sparse ([1; 2; 3]) - ones (3), repmat ([0:2]', 1, 3))\n%!assert (ones (3) - sparse ([1, 2, 3]), repmat ([0:-1:-2], 3, 1))\n%!assert (ones (3) - sparse ([1; 2; 3]), repmat ([0:-1:-2]', 1, 3))\n%!assert (sparse ([1, 2]) - [1; 2], [0, 1; -1, 0])\n%!assert ([1; 2] - sparse ([1, 2]), [0, -1; 1, 0])\n%!assert (sparse ([1; 2]) - [1, 2], [0, -1; 1, 0])\n%!assert ([1, 2] - sparse ([1; 2]), [0, 1; -1, 0])\n%!error <operator -: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2]) - [1, 1, 1]\n%!error <operator -: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3]) - ones (4)\n%!error <operator -: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2; 3]) - ones (4, 3)\n\n%!assert (sparse ([1, 2]) .* [1, 1], sparse ([1, 2]))\n%!assert ([1, 1] .* sparse ([1, 2]), sparse ([1, 2]))\n%!assert (sparse ([1; 2]) .* [1; 1], sparse ([1; 2]))\n%!assert ([1; 1] .* sparse ([1; 2]), sparse ([1; 2]))\n%!assert (sparse ([1, 2, 3]) .* ones (3), sparse (repmat ([1:3], 3, 1)))\n%!assert (sparse ([0, NaN, 0]) .* ones (3), sparse (repmat ([0, NaN, 0], 3, 1)))\n%!assert (sparse ([1; 2; 3]) .* ones (3), sparse (repmat ([1:3]', 1, 3)))\n%!assert (ones (3) .* sparse ([1, 2, 3]), sparse (repmat ([1:3], 3, 1)))\n%!assert (ones (3) .* sparse ([1; 2; 3]), sparse (repmat ([1:3]', 1, 3)))\n%!assert (sparse ([1, 2]) .* [1; 2], sparse ([1, 2; 2, 4]))\n%!assert ([1; 2] .* sparse ([1, 2]), sparse ([1, 2; 2, 4]))\n%!assert (sparse ([1; 2]) .* [1, 2], sparse ([1, 2; 2, 4]))\n%!assert ([1, 2] .* sparse ([1; 2]), sparse ([1, 2; 2, 4]))\n%!error <product: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2]) .* [1, 1, 1]\n%!error <product: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3]) .* ones (4)\n%!error <product: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2; 3]) .* ones (4, 3)\n%!error <operator \\*: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2]) * [1, 1, 1]\n%!error <operator \\*: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3]) * ones (4)\n%!error <operator \\*: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2; 3]) * ones (4, 3)\n\n%!assert (sparse ([1, 2]) ./ [1, 1], sparse ([1, 2]))\n%!assert (sparse ([1, Inf]) ./ [1, Inf], sparse ([1, NaN]))\n%!assert ([1, 1] ./ sparse ([1, 2]), [1, 0.5])\n%!assert ([1, 1] ./ sparse ([NaN, 2]), [NaN, 0.5])\n%!assert (sparse ([1; 2]) ./ [1; 1], sparse ([1; 2]))\n%!assert (sparse ([0; 0]) ./ [1; 0], sparse ([0; NaN]))\n%!assert ([1; 1] ./ sparse ([1; 2]), [1; 0.5])\n%!assert (sparse ([1, 2, 3]) ./ ones (3), sparse (repmat ([1:3], 3, 1)))\n%!assert (sparse ([1; 2; 3]) ./ ones (3), sparse (repmat ([1:3]', 1, 3)))\n%!assert (ones (3) ./ sparse ([1, 2, 3]), repmat ([1, 0.5, 1/3], 3, 1))\n%!assert (ones (3) ./ sparse ([1; 2; 3]), repmat ([1, 0.5, 1/3]', 1, 3))\n%!assert (sparse ([1, 2]) ./ [1; 2], sparse ([1, 2; 0.5, 1]))\n%!assert ([1; 2] ./ sparse ([1, 2]), [1, 0.5; 2, 1])\n%!assert (sparse ([1; 2]) ./ [1, 2], sparse ([1, 0.5; 2, 1]))\n%!assert ([1, 2] ./ sparse ([1; 2]), [1, 2; 0.5, 1])\n%!error <quotient: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2]) ./ [1, 1, 1]\n%!error <quotient: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3]) ./ ones (4)\n%!error <quotient: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2; 3]) ./ ones (4, 3)\n%!error <operator /: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2]) / [1, 1, 1]\n%!error <operator /: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3]) / ones (4)\n%!error <operator /: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2; 3]) / ones (4, 3)\n\n## Tests from bug report #36562\n%!test<*36562>\n%! out = rdivide (NaN, sparse ([1,3], [1,3], [1,3]));\n%! assert (out, nan (3));\n%!test<*36562>\n%! Mfull = [1, 0; 0, 3];\n%! Msparse = sparse (Mfull);\n%! assert (NaN .* Mfull, full (NaN .* Msparse));\n%!test<*36562>\n%! Msparse = sparse ([1, 0; 0, 3]);\n%! assert (NaN .* Msparse, sparse ([NaN, NaN; NaN, NaN]));\n%!test<*36562>\n%! xs = sparse ([1, 0; 0, 2]);\n%! ys = sparse ([1, NaN; 0, 0]);\n%! assert (xs .* ys, sparse ([1, NaN; 0, 0]));\n\n## Tests for product operations involving Inf values\n%!test\n%! x = speye (3);\n%! y = sparse (3,3);\n%! y(1,3) = Inf;\n%! out = y;\n%! out(1,3) = NaN;\n%! assert (x .* y, out);\n%!test\n%! out = speye (3) .* sparse ([0, 0, Inf]);\n%! assert (out, sparse ([0, 0, NaN; 0, 0, NaN; 0, 0, Inf]));\n%!test\n%! out = speye (3) .* sparse ([0; 0; Inf]);\n%! assert (out, sparse ([0, 0, 0; 0, 0, 0; NaN, NaN, Inf]));\n%!test\n%! out = sparse (1, 3) .* sparse ([0; 0; Inf]);\n%! assert (out, sparse ([0, 0, 0; 0, 0, 0; NaN, NaN, NaN]));\n%!test\n%! out = sparse (3, 1) .* sparse ([0, 0, Inf]);\n%! assert (out, sparse ([0, 0, NaN; 0, 0, NaN; 0, 0, NaN]));\n\n## Test broadcasting for comparison and boolean operators\n## for sparse matrix to matrix and matrix to sparse matrix\n%!assert (sparse ([1, 1, 0]) == [0, 1, 1], sparse (logical ([0, 1, 0])))\n%!assert (sparse ([1; 1; 0]) == [0, 1, 1], sparse ([1; 1; 0] == [0, 1, 1]))\n%!assert (sparse ([1, 1, 0]) == [0; 1; 1; 0], ...\n%!        sparse ([1, 1, 0] == [0; 1; 1; 0]))\n%!assert (sparse ([1, 1, 0]) == [0, 1, 1; 0, 1, 1], ...\n%!        sparse (logical ([0, 1, 0; 0, 1, 0])))\n%!assert (sparse ([1; 1; 0]) == [0, 1; 1, 1; 0, 1], ...\n%!        sparse (logical ([0, 1; 1, 1; 1, 0])))\n%!assert ([1, 0, 1] == sparse ([1, 1, 0]), sparse (logical ([1, 0, 0])))\n%!assert ([0, 1, 1] == sparse ([1; 1; 0]), sparse ([0, 1, 1] == [1; 1; 0]))\n%!assert ([0; 1; 1; 0] == sparse ([1, 1, 0]), ...\n%!        sparse ([0; 1; 1; 0] == [1, 1, 0]))\n%!assert ([0, 1, 1; 0, 1, 1] == sparse ([1, 1, 0]), ...\n%!        sparse (logical ([0, 1, 0; 0, 1, 0])))\n%!assert ([0, 1; 1, 1; 0, 1] == sparse ([1; 1; 0]), ...\n%!        sparse (logical ([0, 1; 1, 1; 1, 0])))\n\n%!assert (sparse ([1, 1, 0]) != [0, 1, 1], sparse (logical ([1, 0, 1])))\n%!assert (sparse ([1; 1; 0]) != [0, 1, 1], sparse ([1; 1; 0] != [0, 1, 1]))\n%!assert (sparse ([1, 1, 0]) != [0; 1; 1; 0], ...\n%!        sparse ([1, 1, 0] != [0; 1; 1; 0]))\n%!assert (sparse ([1, 1, 0]) != [0, 1, 1; 0, 1, 1], ...\n%!        sparse (logical ([1, 0, 1; 1, 0, 1])))\n%!assert (sparse ([1; 1; 0]) != [0, 1; 1, 1; 0, 1], ...\n%!        sparse (logical ([1, 0; 0, 0; 0, 1])))\n%!assert ([1, 0, 1] != sparse ([1, 1, 0]), sparse (logical ([0, 1, 1])))\n%!assert ([0, 1, 1] != sparse ([1; 1; 0]), sparse ([0, 1, 1] != [1; 1; 0]))\n%!assert ([0; 1; 1; 0] != sparse ([1, 1, 0]), ...\n%!        sparse ([0; 1; 1; 0] != [1, 1, 0]))\n%!assert ([0, 1, 1; 0, 1, 1] != sparse ([1, 1, 0]), ...\n%!        sparse (logical ([1, 0, 1; 1, 0, 1])))\n%!assert ([0, 1; 1, 1; 0, 1] != sparse ([1; 1; 0]), ...\n%!        sparse (logical ([1, 0; 0, 0; 0, 1])))\n\n%!assert (sparse ([1, 1, 0]) <= [0, 1, 1], sparse (logical ([0, 1, 1])))\n%!assert (sparse ([1; 1; 0]) <= [0, 1, 1], sparse ([1; 1; 0] <= [0, 1, 1]))\n%!assert (sparse ([1, 1, 0]) <= [0; 1; 1; 0], ...\n%!        sparse ([1, 1, 0] <= [0; 1; 1; 0]))\n%!assert (sparse ([1, 1, 0]) <= [0, 1, 1; 0, 1, 1], ...\n%!        sparse (logical ([0, 1, 1; 0, 1, 1])))\n%!assert (sparse ([1; 1; 0]) <= [0, 1; 1, 1; 0, 1], ...\n%!        sparse (logical ([0, 1; 1, 1; 1, 1])))\n%!assert ([1, 0, 1] <= sparse ([1, 1, 0]), sparse (logical ([1, 1, 0])))\n%!assert ([0, 1, 1] <= sparse ([1; 1; 0]), sparse ([0, 1, 1] <= [1; 1; 0]))\n%!assert ([0; 1; 1; 0] <= sparse ([1, 1, 0]), ...\n%!        sparse ([0; 1; 1; 0] <= [1, 1, 0]))\n%!assert ([0, 1, 1; 0, 1, 1] <= sparse ([1, 1, 0]), ...\n%!        sparse (logical ([1, 1, 0; 1, 1, 0])))\n%!assert ([0, 1; 1, 1; 0, 1] <= sparse ([1; 1; 0]), ...\n%!        sparse (logical ([1, 1; 1, 1; 1, 0])))\n\n%!assert (sparse ([1, 1, 0]) >= [0, 1, 1], sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1; 1; 0]) >= [0, 1, 1], sparse ([1; 1; 0] >= [0, 1, 1]))\n%!assert (sparse ([1, 1, 0]) >= [0; 1; 1; 0], ...\n%!        sparse ([1, 1, 0] >= [0; 1; 1; 0]))\n%!assert (sparse ([1, 1, 0]) >= [0, 1, 1; 0, 1, 1], ...\n%!        sparse (logical ([1, 1, 0; 1, 1, 0])))\n%!assert (sparse ([1; 1; 0]) >= [0, 1; 1, 1; 0, 1], ...\n%!        sparse (logical ([1, 1; 1, 1; 1, 0])))\n%!assert ([1, 0, 1] >= sparse ([1, 1, 0]), sparse (logical ([1, 0, 1])))\n%!assert ([0, 1, 1] >= sparse ([1; 1; 0]), sparse ([0, 1, 1] >= [1; 1; 0]))\n%!assert ([0; 1; 1; 0] >= sparse ([1, 1, 0]), ...\n%!        sparse ([0; 1; 1; 0] >= [1, 1, 0]))\n%!assert ([0, 1, 1; 0, 1, 1] >= sparse ([1, 1, 0]), ...\n%!        sparse (logical ([0, 1, 1; 0, 1, 1])))\n%!assert ([0, 1; 1, 1; 0, 1] >= sparse ([1; 1; 0]), ...\n%!        sparse (logical ([0, 1; 1, 1; 1, 1])))\n\n%!assert (sparse ([1, 1, 0]) < [0, 1, 1], sparse (logical ([0, 0, 1])))\n%!assert (sparse ([1; 1; 0]) < [0, 1, 1], sparse ([1; 1; 0] < [0, 1, 1]))\n%!assert (sparse ([1, 1, 0]) < [0; 1; 1; 0], sparse ([1, 1, 0] < [0; 1; 1; 0]))\n%!assert (sparse ([1, 1, 0]) < [0, 1, 1; 0, 1, 1], ...\n%!        sparse (logical ([0, 0, 1; 0, 0, 1])))\n%!assert (sparse ([1; 1; 0]) < [0, 1; 1, 1; 0, 1], ...\n%!        sparse (logical ([0, 0; 0, 0; 0, 1])))\n%!assert ([1, 0, 1] < sparse ([1, 1, 0]), sparse (logical ([0, 1, 0])))\n%!assert ([0, 1, 1] < sparse ([1; 1; 0]), sparse ([0, 1, 1] < [1; 1; 0]))\n%!assert ([0; 1; 1; 0] < sparse ([1, 1, 0]), sparse ([0; 1; 1; 0] < [1, 1, 0]))\n%!assert ([0, 1, 1; 0, 1, 1] < sparse ([1, 1, 0]), ...\n%!        sparse (logical ([1, 0, 0; 1, 0, 0])))\n%!assert ([0, 1; 1, 1; 0, 1] < sparse ([1; 1; 0]), ...\n%!        sparse (logical ([1, 0; 0, 0; 0, 0])))\n\n%!assert (sparse ([1, 1, 0]) > [0, 1, 1], sparse (logical ([1, 0, 0])))\n%!assert (sparse ([1; 1; 0]) > [0, 1, 1], sparse ([1; 1; 0] > [0, 1, 1]))\n%!assert (sparse ([1, 1, 0]) > [0; 1; 1; 0], sparse ([1, 1, 0] > [0; 1; 1; 0]))\n%!assert (sparse ([1, 1, 0]) > [0, 1, 1; 0, 1, 1], ...\n%!        sparse (logical ([1, 0, 0; 1, 0, 0])))\n%!assert (sparse ([1; 1; 0]) > [0, 1; 1, 1; 0, 1], ...\n%!        sparse (logical ([1, 0; 0, 0; 0, 0])))\n%!assert ([1, 0, 1] > sparse ([1, 1, 0]), sparse (logical ([0, 0, 1])))\n%!assert ([0, 1, 1] > sparse ([1; 1; 0]), sparse ([0, 1, 1] > [1; 1; 0]))\n%!assert ([0; 1; 1; 0] > sparse ([1, 1, 0]), sparse ([0; 1; 1; 0] > [1, 1, 0]))\n%!assert ([0, 1, 1; 0, 1, 1] > sparse ([1, 1, 0]), ...\n%!        sparse (logical ([0, 0, 1; 0, 0, 1])))\n%!assert ([0, 1; 1, 1; 0, 1] > sparse ([1; 1; 0]), ...\n%!        sparse (logical ([0, 0; 0, 0; 0, 1])))\n\n%!assert (sparse ([1, 1, 0]) & [0, 1, 1], sparse (logical ([0, 1, 0])))\n%!assert (sparse ([1; 1; 0]) & [0, 1, 1], sparse ([1; 1; 0] & [0, 1, 1]))\n%!assert (sparse ([1, 1, 0]) & [0; 1; 1; 0], sparse ([1, 1, 0] & [0; 1; 1; 0]))\n%!assert (sparse ([1, 1, 0]) & [0, 1, 1; 0, 1, 1], ...\n%!        sparse (logical ([0, 1, 0; 0, 1, 0])))\n%!assert (sparse ([1; 1; 0]) & [0, 1; 1, 1; 0, 1], ...\n%!        sparse (logical ([0, 1; 1, 1; 0, 0])))\n%!assert ([1, 0, 1] & sparse ([1, 1, 0]), sparse (logical ([1, 0, 0])))\n%!assert ([0, 1, 1] & sparse ([1; 1; 0]), sparse ([0, 1, 1] & [1; 1; 0]))\n%!assert ([0; 1; 1; 0] & sparse ([1, 1, 0]), sparse ([0; 1; 1; 0] & [1, 1, 0]))\n%!assert ([0, 1, 1; 0, 1, 1] & sparse ([1, 1, 0]), ...\n%!        sparse (logical ([0, 1, 0; 0, 1, 0])))\n%!assert ([0, 1; 1, 1; 0, 1] & sparse ([1; 1; 0]), ...\n%!        sparse (logical ([0, 1; 1, 1; 0, 0])))\n\n## Test boolean OR operations should return dense logical arrays\n%!assert (sparse ([1, 1, 0]) | [0, 1, 1], logical ([1, 1, 1]))\n%!assert (sparse ([1; 1; 0]) | [0, 1, 1], [1; 1; 0] | [0, 1, 1])\n%!assert (sparse ([1, 1, 0]) | [0; 1; 1; 0], [1, 1, 0] | [0; 1; 1; 0])\n%!assert (sparse ([1, 1, 0]) | [0, 1, 1; 0, 1, 1], logical ([1, 1, 1; 1, 1, 1]))\n%!assert (sparse ([1; 1; 0]) | [0, 1; 1, 1; 0, 1], logical ([1, 1; 1, 1; 0, 1]))\n%!assert ([1, 0, 1] | sparse ([1, 1, 0]), logical ([1, 1, 1]))\n%!assert ([0, 1, 1] | sparse ([1; 1; 0]), [0, 1, 1] | [1; 1; 0])\n%!assert ([0; 1; 1; 0] | sparse ([1, 1, 0]), [0; 1; 1; 0] | [1, 1, 0])\n%!assert ([0, 1, 1; 0, 1, 1] | sparse ([1, 1, 0]), logical ([1, 1, 1; 1, 1, 1]))\n%!assert ([0, 1; 1, 1; 0, 1] | sparse ([1; 1; 0]), logical ([1, 1; 1, 1; 0, 1]))\n\n## Test broadcasting for comparison and boolean operators\n## for sparse matrix to scalar and scalar to sparse matrix\n%!assert (sparse ([1, 1, 0]) == 1, sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1, 1, 0]) != 1, sparse (logical ([0, 0, 1])))\n%!assert (sparse ([1, 1, 0]) <= 1, sparse (logical ([1, 1, 1])))\n%!assert (sparse ([1, 1, 0]) >= 1, sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1, 1, 0]) < 1, sparse (logical ([0, 0, 1])))\n%!assert (sparse ([1, 1, 0]) > 0, sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1, 1, 0]) & 1, sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1, 1, 0]) | 1, logical ([1, 1, 1]))\n%!assert (sparse ([1, 1, 0]) == 1, 1 == sparse ([1, 1, 0]))\n%!assert (sparse ([1, 1, 0]) != 1, 1 != sparse ([1, 1, 0]))\n%!assert (sparse ([1, 1, 0]) <= 1, 1 >= sparse ([1, 1, 0]))\n%!assert (sparse ([1, 1, 0]) >= 1, 1 <= sparse ([1, 1, 0]))\n%!assert (sparse ([1, 1, 0]) < 1, 1 > sparse ([1, 1, 0]))\n%!assert (sparse ([1, 1, 0]) > 0, 0 < sparse ([1, 1, 0]))\n%!assert (sparse ([1, 1, 0]) & 1, 1 & sparse ([1, 1, 0]))\n%!assert (sparse ([1, 1, 0]) | 1, 1 | sparse ([1, 1, 0]))\n\n## Test some empty edge cases\n%!assert (sparse (1) | sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (1 | sparse (ones(0,1)), logical (ones (0, 1)))\n%!assert (sparse (1) & sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (1 & sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (sparse (1) | sparse (ones(2,0)), sparse (logical (ones (2, 0))))\n%!assert (1 | sparse (ones(2, 0)), logical (ones (2, 0)))\n%!assert (sparse (1) & sparse (ones(2,0)), sparse (logical (ones (2, 0))))\n%!assert (1 & sparse (ones(2, 0)), sparse (logical (ones (2, 0))))\n%!assert (sparse (1) == sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (1 != sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (sparse (1) <= sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (1 >= sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (sparse (1) < sparse (ones(2,0)), sparse (logical (ones (2, 0))))\n%!assert (1 > sparse (ones(2, 0)), sparse (logical (ones (2, 0))))\n\n## Test errors\n%!error <mx_el_eq: nonconformant arguments \\(op1 is 0x2, op2 is 2x0\\)>\n%! sparse (ones (0,2)) == ones (2,0)\n%!error <mx_el_ne: nonconformant arguments \\(op1 is 0x2, op2 is 2x0\\)>\n%! sparse (ones (0,2)) != ones (2,0)\n%!error <mx_el_le: nonconformant arguments \\(op1 is 0x2, op2 is 2x0\\)>\n%! sparse (ones (0,2)) <= ones (2,0)\n%!error <mx_el_ge: nonconformant arguments \\(op1 is 0x2, op2 is 2x0\\)>\n%! sparse (ones (0,2)) >= ones (2,0)\n%!error <mx_el_lt: nonconformant arguments \\(op1 is 0x2, op2 is 2x0\\)>\n%! sparse (ones (0,2)) < ones (2,0)\n%!error <mx_el_gt: nonconformant arguments \\(op1 is 0x2, op2 is 2x0\\)>\n%! sparse (ones (0,2)) > ones (2,0)\n%!error <mx_el_and: nonconformant arguments \\(op1 is 0x2, op2 is 2x0\\)>\n%! sparse (ones (0,2)) & ones (2,0)\n%!error <mx_el_or: nonconformant arguments \\(op1 is 0x2, op2 is 2x0\\)>\n%! sparse (ones (0,2)) | ones (2,0)\n\n## Test broadcasting for comparison and boolean operators\n## for sparse matrix to sparse matrix\n%!assert (sparse([1, 1, 0]) == sparse([0, 1, 1]), ...\n%!        sparse ([1, 1, 0] == [0, 1, 1]))\n%!assert (sparse([1; 1; 0]) == sparse([0, 1, 1]),...\n%!        sparse ([1; 1; 0] == [0, 1, 1]))\n%!assert (sparse([1, 1, 0]) == sparse([0; 1; 1; 0]), ...\n%!        sparse ([1, 1, 0] == [0; 1; 1; 0]))\n%!assert (sparse([1, 1, 0]) == sparse([0, 1, 1; 0, 1, 1]), ...\n%!        sparse ([1, 1, 0] == [0, 1, 1; 0, 1, 1]))\n%!assert (sparse([1; 1; 0]) == sparse([0, 1; 1, 1; 0, 1]), ...\n%!        sparse ([1; 1; 0] == [0, 1; 1, 1; 0, 1]))\n%!assert (sparse([1, 1, 0]) != sparse([0, 1, 1]), ...\n%!        sparse ([1, 1, 0] != [0, 1, 1]))\n%!assert (sparse([1; 1; 0]) != sparse([0, 1, 1]), ...\n%!        sparse ([1; 1; 0] != [0, 1, 1]))\n%!assert (sparse([1, 1, 0]) != sparse([0; 1; 1; 0]), ...\n%!        sparse ([1, 1, 0] != [0; 1; 1; 0]))\n%!assert (sparse([1, 1, 0]) != sparse([0, 1, 1; 0, 1, 1]), ...\n%!        sparse ([1, 1, 0] != [0, 1, 1; 0, 1, 1]))\n%!assert (sparse([1; 1; 0]) != sparse([0, 1; 1, 1; 0, 1]), ...\n%!        sparse ([1; 1; 0] != [0, 1; 1, 1; 0, 1]))\n%!assert (sparse([1, 1, 0]) <= sparse([0, 1, 1]), ...\n%!        sparse ([1, 1, 0] <= [0, 1, 1]))\n%!assert (sparse([1; 1; 0]) <= sparse([0, 1, 1]), ...\n%!        sparse ([1; 1; 0] <= [0, 1, 1]))\n%!assert (sparse([1, 1, 0]) <= sparse([0; 1; 1; 0]), ...\n%!        sparse ([1, 1, 0] <= [0; 1; 1; 0]))\n%!assert (sparse([1, 1, 0]) <= sparse([0, 1, 1; 0, 1, 1]), ...\n%!        sparse ([1, 1, 0] <= [0, 1, 1; 0, 1, 1]))\n%!assert (sparse([1; 1; 0]) <= sparse([0, 1; 1, 1; 0, 1]), ...\n%!        sparse ([1; 1; 0] <= [0, 1; 1, 1; 0, 1]))\n%!assert (sparse([1, 1, 0]) >= sparse([0, 1, 1]), ...\n%!        sparse ([1, 1, 0] >= [0, 1, 1]))\n%!assert (sparse([1; 1; 0]) >= sparse([0, 1, 1]), ...\n%!        sparse ([1; 1; 0] >= [0, 1, 1]))\n%!assert (sparse([1, 1, 0]) >= sparse([0; 1; 1; 0]), ...\n%!        sparse ([1, 1, 0] >= [0; 1; 1; 0]))\n%!assert (sparse([1, 1, 0]) >= sparse([0, 1, 1; 0, 1, 1]), ...\n%!        sparse ([1, 1, 0] >= [0, 1, 1; 0, 1, 1]))\n%!assert (sparse([1; 1; 0]) >= sparse([0, 1; 1, 1; 0, 1]), ...\n%!        sparse ([1; 1; 0] >= [0, 1; 1, 1; 0, 1]))\n%!assert (sparse([1, 1, 0]) < sparse([0, 1, 1]), ...\n%!        sparse ([1, 1, 0] < [0, 1, 1]))\n%!assert (sparse([1; 1; 0]) < sparse([0, 1, 1]), ...\n%!        sparse ([1; 1; 0] < [0, 1, 1]))\n%!assert (sparse([1, 1, 0]) < sparse([0; 1; 1; 0]), ...\n%!        sparse ([1, 1, 0] < [0; 1; 1; 0]))\n%!assert (sparse([1, 1, 0]) < sparse([0, 1, 1; 0, 1, 1]), ...\n%!        sparse ([1, 1, 0] < [0, 1, 1; 0, 1, 1]))\n%!assert (sparse([1; 1; 0]) < sparse([0, 1; 1, 1; 0, 1]), ...\n%!        sparse ([1; 1; 0] < [0, 1; 1, 1; 0, 1]))\n%!assert (sparse([1, 1, 0]) > sparse([0, 1, 1]), ...\n%!        sparse ([1, 1, 0] > [0, 1, 1]))\n%!assert (sparse([1; 1; 0]) > sparse([0, 1, 1]), ...\n%!        sparse ([1; 1; 0] > [0, 1, 1]))\n%!assert (sparse([1, 1, 0]) > sparse([0; 1; 1; 0]), ...\n%!        sparse ([1, 1, 0] > [0; 1; 1; 0]))\n%!assert (sparse([1, 1, 0]) > sparse([0, 1, 1; 0, 1, 1]), ...\n%!        sparse ([1, 1, 0] > [0, 1, 1; 0, 1, 1]))\n%!assert (sparse([1; 1; 0]) > sparse([0, 1; 1, 1; 0, 1]), ...\n%!        sparse ([1; 1; 0] > [0, 1; 1, 1; 0, 1]))\n%!assert (sparse([1, 1, 0]) & sparse([0, 1, 1]), ...\n%!        sparse ([1, 1, 0] & [0, 1, 1]))\n%!assert (sparse([1; 1; 0]) & sparse([0, 1, 1]), ...\n%!        sparse ([1; 1; 0] & [0, 1, 1]))\n%!assert (sparse([1, 1, 0]) & sparse([0; 1; 1; 0]), ...\n%!        sparse ([1, 1, 0] & [0; 1; 1; 0]))\n%!assert (sparse([1, 1, 0]) & sparse([0, 1, 1; 0, 1, 1]), ...\n%!        sparse ([1, 1, 0] & [0, 1, 1; 0, 1, 1]))\n%!assert (sparse([1; 1; 0]) & sparse([0, 1; 1, 1; 0, 1]), ...\n%!        sparse ([1; 1; 0] & [0, 1; 1, 1; 0, 1]))\n%!assert (sparse([1, 1, 0]) | sparse([0, 1, 1]), ...\n%!        sparse ([1, 1, 0] | [0, 1, 1]))\n%!assert (sparse([1; 1; 0]) | sparse([0, 1, 1]), ...\n%!        sparse ([1; 1; 0] | [0, 1, 1]))\n%!assert (sparse([1, 1, 0]) | sparse([0; 1; 1; 0]), ...\n%!        sparse ([1, 1, 0] | [0; 1; 1; 0]))\n%!assert (sparse([1, 1, 0]) | sparse([0, 1, 1; 0, 1, 1]), ...\n%!        sparse ([1, 1, 0] | [0, 1, 1; 0, 1, 1]))\n%!assert (sparse([1; 1; 0]) | sparse([0, 1; 1, 1; 0, 1]), ...\n%!        sparse ([1; 1; 0] | [0, 1; 1, 1; 0, 1]))\n\n## Tests for SparseComplexMatrix\n\n## Test broadcasting of empty matrices with math operators.\n## This has been fixed in MSparse.cc and Sparse-op-defs.h\n%!assert (sparse (zeros (0,1)) + sparse ([1, 2, 3, 4i]), sparse (zeros (0,4)))\n%!error <operator \\+: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) + sparse ([1, 2, 3, 4i])\n%!assert (sparse (zeros (0,1)) - sparse ([1, 2, 3, 4i]), sparse (zeros (0,4)))\n%!error <operator -: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) - sparse ([1, 2, 3, 4i])\n%!assert (sparse (zeros (0,1)) * sparse ([1, 2, 3, 4i]), sparse (zeros (0,4)))\n%!error <operator \\*: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) * sparse ([1, 2, 3, 4i])\n%!assert (sparse (zeros (0,1)) .* sparse ([1, 2, 3, 4i]), sparse (zeros (0,4)))\n%!error <product: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) .* sparse ([1, 2, 3, 4i])\n%!assert (sparse (zeros (0,1)) ./ sparse ([1, 2, 3, 4i]), sparse (zeros (0,4)))\n%!error <quotient: nonconformant arguments \\(op1 is 0x2, op2 is 1x4\\)>\n%! sparse (zeros (0,2)) ./ sparse ([1, 2, 3, 4i])\n%!test\n%! a = sparse (zeros (0,1));\n%! assert (a += sparse ([1, 2, 3, 4i]), sparse (zeros (0,4)));\n%! assert (a -= sparse ([1, 2, 3, 4i]), sparse (zeros (0,4)));\n\n%!assert (sparse (zeros (1,0)) + sparse ([1; 2; 3; 4i]), sparse (zeros (4,0)))\n%!error <operator \\+: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) + sparse ([1; 2; 3; 4i])\n%!assert (sparse (zeros (1,0)) - sparse ([1; 2; 3; 4i]), sparse (zeros (4,0)))\n%!error <operator -: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) - sparse ([1; 2; 3; 4i])\n%!error <operator \\*: nonconformant arguments \\(op1 is 1x0, op2 is 4x1\\)>\n%!       sparse (zeros (1,0)) * sparse ([1; 2; 3; 4i])\n%!error <operator \\*: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) * sparse ([1; 2; 3; 4i])\n%!assert (sparse (zeros (1,0)) .* sparse ([1; 2; 3; 4i]), sparse (zeros (4,0)))\n%!error <product: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) .* sparse ([1; 2; 3; 4i])\n%!assert (sparse (zeros (1,0)) ./ sparse ([1; 2; 3; 4i]), sparse (zeros (4,0)))\n%!error <quotient: nonconformant arguments \\(op1 is 2x0, op2 is 4x1\\)>\n%! sparse (zeros (2,0)) ./ sparse ([1; 2; 3; 4i])\n%!test\n%! a = sparse (zeros (1,0));\n%! assert (a += sparse ([1; 2; 3; 4i]), sparse (zeros (4,0)));\n%! assert (a -= sparse ([1; 2; 3; 4i]), sparse (zeros (4,0)));\n\n## Test broadcasting of sparse matrices with math operators\n%!assert (full (sparse ([1, 2i, 3]) + sparse ([1, 2i, 3; 4i, 5, 6])),\n%!        [1, 2i, 3] + [1, 2i, 3; 4i, 5, 6])\n%!assert (full (sparse ([1; 2; 3i]) + sparse ([1, 2; 1, 2i; 1, 2i])),\n%!        [1; 2; 3i] + [1, 2; 1, 2i; 1, 2i])\n%!assert (full (sparse ([1i, 2, 3]) + sparse ([1i; 2; 3; 4])),\n%!        [1i, 2, 3] + [1i; 2; 3; 4])\n%!assert (full (sparse ([1; 2i; 3]) + sparse ([1i, 2i, 3, 4, 5])),\n%!        [1; 2i; 3] + [1i, 2i, 3, 4, 5])\n%!assert (full (sparse ([1, 0, 3i]) + sparse ([1, 0, 3i; 0i, 5, 6])),\n%!        [1, 0, 3i] + [1, 0, 3i; 0i, 5, 6])\n%!assert (full (sparse ([1; 2i; 0]) + sparse ([1i, 2i; 1, 0; 0, 0])),\n%!        [1; 2i; 0] + [1i, 2i; 1, 0; 0, 0])\n%!assert (full (sparse ([0, 0, 3i]) + sparse ([1; 2i; 3i; 4])),\n%!        [0, 0, 3i] + [1; 2i; 3i; 4])\n%!assert (full (sparse ([1; 2; 3i]) + sparse ([1, 0, 0, 0i, 5i])),\n%!        [1; 2; 3i] + [1, 0, 0, 0i, 5i])\n%!assert (full (sparse ([1, 2i, 3; 4, 5, 6]) + sparse ([1, 2, 3])),\n%!        [1, 2i, 3; 4, 5, 6] + [1, 2, 3])\n%!assert (full (sparse ([1, 2; 1, 2i; 1, 2]) + sparse ([1; 2i; 3])),\n%!        [1, 2; 1, 2i; 1, 2] + [1; 2i; 3])\n%!assert (full (sparse ([1; 2; 3; 4]) + sparse ([1, 2, 3i])),\n%!        [1; 2; 3; 4] + [1, 2, 3i])\n%!assert (full (sparse ([1, 2, 3, 4, 5i]) + sparse ([1; 2; 3])),\n%!        [1, 2, 3, 4, 5i] + [1; 2; 3])\n%!assert (full (sparse ([1i, 0, 3; 0, 5, 6]) + sparse ([1, 0, 3])),\n%!        [1i, 0, 3; 0, 5, 6] + [1, 0, 3])\n%!assert (full (sparse ([1i, 2; 1, 0; 0, 0]) + sparse ([1; 2; 0])),\n%!        [1i, 2; 1, 0; 0, 0] + [1; 2; 0])\n%!assert (full (sparse ([1; 2i; 3i; 4]) + sparse ([0, 0, 3])),\n%!        [1; 2i; 3i; 4] + [0, 0, 3])\n%!assert (full (sparse ([1, 0, 0, 0, 5i]) + sparse ([1; 2; 3i])),\n%!        [1, 0, 0, 0, 5i] + [1; 2; 3i])\n\n%!assert (sparse (1) + sparse ([1, 2i, 3]), sparse ([2, 1+2i, 4]))\n%!assert (sparse (1) + sparse ([1, 2i; 3, 4]), sparse ([2, 1+2i; 4, 5]))\n%!assert (sparse ([1, 2, 3i]) + sparse (1), sparse ([2, 3, 1+3i]))\n%!assert (sparse ([1, 2; 3, 4]) + sparse (1i), sparse ([1+i, 2+i; 3+i, 4+i]))\n%!assert (full (sparse ([1i; 2]) + sparse ([1, 0, 2, 0, 4])),\n%!        [1i; 2] + [1, 0, 2, 0, 4])\n%!assert (full (sparse ([1i, 0, 2, 0, 4]) + sparse ([1i; 2])),\n%!        [1i, 0, 2, 0, 4] + [1i; 2])\n%!assert (full (sparse ([1, 2i]) + sparse ([1; 0; 2; 0; 4])),\n%!        [1, 2i] + [1; 0; 2; 0; 4])\n%!assert (full (sparse ([1; 0; 2; 0i; 4i]) + sparse ([1, 2i])),\n%!        [1; 0; 2; 0i; 4i] + [1, 2i])\n%!assert (full (sparse ([1, 0, 3i]) + sparse ([1, 2, 3; 4, 0, 0i])),\n%!        [1, 0, 3i] + [1, 2, 3; 4, 0, 0i])\n%!assert (full (sparse ([10i, 0, 3; 4, 5, 0]) + sparse ([1, 0, 3])),\n%!        [10i, 0, 3; 4, 5, 0] + [1, 0, 3])\n%!assert (full (sparse ([1; 2i; 0]) + sparse ([0, 2; 3, 4; 5i, 0])),\n%!        [1; 2i; 0] + [0, 2; 3, 4; 5i, 0])\n%!assert (full (sparse ([1i, 2; 0, 0; 0, 6]) + sparse ([0; 2i; 3])),\n%!        [1i, 2; 0, 0; 0, 6] + [0; 2i; 3])\n\n%!assert (full (sparse ([1, 2, 3i]) - sparse ([1, 2, 3; 4i, 5, 6])),\n%!        [1, 2, 3i] - [1, 2, 3; 4i, 5, 6])\n%!assert (full (sparse ([1; 2; 3i]) - sparse ([1, 2; 1i, 2; 1, 2])),\n%!        [1; 2; 3i] - [1, 2; 1i, 2; 1, 2])\n%!assert (full (sparse ([1, 2, 3i]) - sparse ([1; 2; 3; 4])),\n%!        [1, 2, 3i] - [1; 2; 3; 4])\n%!assert (full (sparse ([1i; 2; 3]) - sparse ([1i, 2, 3i, 4, 5])),\n%!        [1i; 2; 3] - [1i, 2, 3i, 4, 5])\n%!assert (full (sparse ([1, 0, 3i]) - sparse ([1, 0i, 3; 0, 5, 6])),\n%!        [1, 0, 3i] - [1, 0i, 3; 0, 5, 6])\n%!assert (full (sparse ([1i; 2; 0]) - sparse ([1, 2; 1, 0; 0, 0])),\n%!        [1i; 2; 0] - [1, 2; 1, 0; 0, 0])\n%!assert (full (sparse ([0, 0, 3]) - sparse ([1; 2i; 3i; 4])),\n%!        [0, 0, 3] - [1; 2i; 3i; 4])\n%!assert (full (sparse ([1; 2; 3]) - sparse ([1, 0, 0, 0, 5i])),\n%!        [1; 2; 3] - [1, 0, 0, 0, 5i])\n%!assert (full (sparse ([1, 2, 3; 4, 5i, 6i]) - sparse ([1i, 2, 3])),\n%!        [1, 2, 3; 4, 5i, 6i] - [1i, 2, 3])\n%!assert (full (sparse ([1i, 2; 1, 2; 1, 2]) - sparse ([1; 2; 3])),\n%!        [1i, 2; 1, 2; 1, 2] - [1; 2; 3])\n%!assert (full (sparse ([1; 2; 3i; 4]) - sparse ([1, 2, 3i])),\n%!        [1; 2; 3i; 4] - [1, 2, 3i])\n%!assert (full (sparse ([1, 2, 3, 4, 5]) - sparse ([1; 2; 3i])),\n%!        [1, 2, 3, 4, 5] - [1; 2; 3i])\n%!assert (full (sparse ([1, 0, 3; 0, 5, 6i]) - sparse ([1, 0, 3])),\n%!        [1, 0, 3; 0, 5, 6i] - [1, 0, 3])\n%!assert (full (sparse ([1i, 2; 1, 0; 0, 0]) - sparse ([1i; 2; 0])),\n%!        [1i, 2; 1, 0; 0, 0] - [1i; 2; 0])\n%!assert (full (sparse ([1; 2i; 3; 4]) - sparse ([0, 0i, 3])),\n%!        [1; 2i; 3; 4] - [0, 0i, 3])\n%!assert (full (sparse ([1, 0, 0, 0, 5i]) - sparse ([1i; 2; 3])),\n%!        [1, 0, 0, 0, 5i] - [1i; 2; 3])\n\n%!assert (sparse (1) - sparse ([1, 2, 3i]), sparse ([0, -1, 1-3i]))\n%!assert (sparse (1) - sparse ([1i, 2; 3, 4]), sparse ([1-1i, -1; -2, -3]))\n%!assert (sparse ([1, 2i, 3]) - sparse (1), sparse ([0, -1+2i, 2]))\n%!assert (sparse ([1, 2; 3, 4i]) - sparse (1), sparse ([0, 1; 2, -1+4i]))\n%!assert (full (sparse ([1; 2i]) - sparse ([1, 0, 2, 0, 4])),\n%!        [1; 2i] - [1, 0, 2, 0, 4])\n%!assert (full (sparse ([1, 0, 2i, 0, 4]) - sparse ([1i; 2])),\n%!        [1, 0, 2i, 0, 4] - [1i; 2])\n%!assert (full (sparse ([1, 2i]) - sparse ([1; 0; 2; 0i; 4i])),\n%!        [1, 2i] - [1; 0; 2; 0i; 4i])\n%!assert (full (sparse ([1; 0; 2; 0; 4]) - sparse ([1, 2i])),\n%!        [1; 0; 2; 0; 4] - [1, 2i])\n%!assert (full (sparse ([1i, 0, 3]) - sparse ([1, 2, 3; 4, 0, 0])),\n%!        [1i, 0, 3] - [1, 2, 3; 4, 0, 0])\n%!assert (full (sparse ([10, 0, 3; 4i, 5i, 0]) - sparse ([1, 0, 3i])),\n%!        [10, 0, 3; 4i, 5i, 0] - [1, 0, 3i])\n%!assert (full (sparse ([1; 2i; 0]) - sparse ([0, 2; 3i, 4i; 5, 0])),\n%!        [1; 2i; 0] - [0, 2; 3i, 4i; 5, 0])\n%!assert (full (sparse ([1, 2; 0, 0; 0, 6i]) - sparse ([0; 2; 3i])),\n%!        [1, 2; 0, 0; 0, 6i] - [0; 2; 3i])\n\n%!assert (full (sparse ([1, 2i, 3]) .* sparse ([1, 2, 3; 4, 5, 6])),\n%!        [1, 2i, 3] .* [1, 2, 3; 4, 5, 6])\n%!assert (full (sparse ([1; 2; 3i]) .* sparse ([1, 2; 1i, 2; 1, 2])),\n%!        [1; 2; 3i] .* [1, 2; 1i, 2; 1, 2])\n%!assert (full (sparse ([1, 2, 3]) .* sparse ([1; 2; 3; 4i])),\n%!        [1, 2, 3] .* [1; 2; 3; 4i])\n%!assert (full (sparse ([1; 2i; 3i]) .* sparse ([1, 2, 3, 4, 5])),\n%!        [1; 2i; 3i] .* [1, 2, 3, 4, 5])\n%!assert (full (sparse ([1, 0, 3i]) .* sparse ([1i, 0, 3; 0, 5, 6])),\n%!        [1, 0, 3i] .* [1i, 0, 3; 0, 5, 6])\n%!assert (full (sparse ([1; 2i; 0]) .* sparse ([1, 2i; 1i, 0; 0, 0])),\n%!        [1; 2i; 0] .* [1, 2i; 1i, 0; 0, 0])\n%!assert (full (sparse ([0, 0i, 3i]) .* sparse ([1; 2; 3; 4])),\n%!        [0, 0i, 3i] .* [1; 2; 3; 4])\n%!assert (full (sparse ([1; 2; 3i]) .* sparse ([1, 0, 0i, 0, 5])),\n%!        [1; 2; 3i] .* [1, 0, 0i, 0, 5])\n%!assert (full (sparse ([1, 2, 3i; 4, 5, 6]) .* sparse ([1, 2, 3])),\n%!        [1, 2, 3i; 4, 5, 6] .* [1, 2, 3])\n%!assert (full (sparse ([1, 2; 1i, 2; 1, 2]) .* sparse ([1i; 2; 3])),\n%!        [1, 2; 1i, 2; 1, 2] .* [1i; 2; 3])\n%!assert (full (sparse ([1; 2; 3; 4]) .* sparse ([1, 2i, 3])),\n%!        [1; 2; 3; 4] .* [1, 2i, 3])\n%!assert (full (sparse ([1, 2i, 3, 4, 5]) .* sparse ([1i; 2; 3])),\n%!        [1, 2i, 3, 4, 5] .* [1i; 2; 3])\n%!assert (full (sparse ([1, 0, 3; 0, 5, 6]) .* sparse ([1, 0, 3i])),\n%!        [1, 0, 3; 0, 5, 6] .* [1, 0, 3i])\n%!assert (full (sparse ([1, 2i; 1, 0; 0i, 0]) .* sparse ([1; 2; 0])),\n%!        [1, 2i; 1, 0; 0i, 0] .* [1; 2; 0])\n%!assert (full (sparse ([1; 2i; 3; 4]) .* sparse ([0, 0, 3])),\n%!        [1; 2i; 3; 4] .* [0, 0, 3])\n%!assert (full (sparse ([1, 0, 0, 0, 5i]) .* sparse ([1; 2i; 3i])),\n%!        [1, 0, 0, 0, 5i] .* [1; 2i; 3i])\n\n%!assert (sparse (1) .* sparse ([1, 2i, 3]), sparse ([1, 2i, 3]))\n%!assert (sparse (1) .* sparse ([1, 2; 3i, 4]), sparse ([1, 2; 3i, 4]))\n%!assert (sparse ([1 2 3]) .* sparse (1i), sparse ([1i, 2i, 3i]))\n%!assert (sparse ([1, 2; 3i, 4i]) .* sparse (1), sparse ([1, 2; 3i, 4i]))\n%!assert (full (sparse ([1; 2]) .* sparse ([1, 0, 2i, 0, 4])),\n%!        [1; 2] .* [1, 0, 2i, 0, 4])\n%!assert (full (sparse ([1i, 0, 2, 0, 4]) .* sparse ([1; 2])),\n%!        [1i, 0, 2, 0, 4] .* [1; 2])\n%!assert (full (sparse ([1, 2i]) .* sparse ([1; 0; 2i; 0i; 4])),\n%!        [1, 2i] .* [1; 0; 2i; 0i; 4])\n%!assert (full (sparse ([1i; 0; 2; 0; 4]) .* sparse ([1, 2])),\n%!        [1i; 0; 2; 0; 4] .* [1, 2])\n%!assert (full (sparse ([1, 0, 3i]) .* sparse ([1i, 2i, 3; 4, 0, 0])),\n%!        [1, 0, 3i] .* [1i, 2i, 3; 4, 0, 0])\n%!assert (full (sparse ([10, 0, 3; 4, 5, 0]) .* sparse ([1i, 0, 3])),\n%!        [10, 0, 3; 4, 5, 0] .* [1i, 0, 3])\n%!assert (full (sparse ([1; 2i; 0]) .* sparse ([0, 2i; 3i, 4; 5, 0])),\n%!        [1; 2i; 0] .* [0, 2i; 3i, 4; 5, 0])\n%!assert (full (sparse ([1, 2i; 0, 0; 0, 6]) .* sparse ([0; 2; 3])),\n%!        [1, 2i; 0, 0; 0, 6] .* [0; 2; 3])\n\n%!assert (full (sparse ([1, 2, 3i]) ./ sparse ([1, 2, 3; 4, 5, 6])),\n%!        [1, 2, 3i] ./ [1, 2, 3; 4, 5, 6])\n%!assert (full (sparse ([1; 2; 3i]) ./ sparse ([1, 2; 1i, 2; 1, 2])),\n%!        [1; 2; 3i] ./ [1, 2; 1i, 2; 1, 2])\n%!assert (full (sparse ([1, 2, 3]) ./ sparse ([1; 2i; 3i; 4])),\n%!        [1, 2, 3] ./ [1; 2i; 3i; 4])\n%!assert (full (sparse ([1; 2i; 3]) ./ sparse ([1, 2, 3, 4, 5])),\n%!        [1; 2i; 3] ./ [1, 2, 3, 4, 5])\n%!assert (full (sparse ([1, 0, 3i]) ./ sparse ([1, 0, 3i; 0, 5, 6])),\n%!        [1, 0, 3i] ./ [1, 0, 3i; 0, 5, 6])\n%!assert (full (sparse ([1; 2; 0]) ./ sparse ([1, 2; 1i, 0; 0i, 0i])),\n%!        [1; 2; 0] ./ [1, 2; 1i, 0; 0i, 0i])\n%!assert (full (sparse ([0, 0, 3i]) ./ sparse ([1; 2; 3; 4])),\n%!        [0, 0, 3i] ./ [1; 2; 3; 4])\n%!assert (full (sparse ([1i; 2; 3]) ./ sparse ([1i, 0, 0, 0, 5])),\n%!        [1i; 2; 3] ./ [1i, 0, 0, 0, 5])\n%!assert (full (sparse ([1, 2, 3i; 4i, 5i, 6]) ./ sparse ([1, 2, 3])),\n%!        [1, 2, 3i; 4i, 5i, 6] ./ [1, 2, 3])\n%!assert (full (sparse ([1i, 2; 1, 2; 1, 2]) ./ sparse ([1i; 2; 3])),\n%!        [1i, 2; 1, 2; 1, 2] ./ [1i; 2; 3])\n%!assert (full (sparse ([1; 2; 3; 4]) ./ sparse ([1, 2i, 3])),\n%!        [1; 2; 3; 4] ./ [1, 2i, 3])\n%!assert (full (sparse ([1, 2i, 3, 4, 5]) ./ sparse ([1; 2; 3])),\n%!        [1, 2i, 3, 4, 5] ./ [1; 2; 3])\n%!assert (full (sparse ([1, 0, 3i; 0, 5i, 6]) ./ sparse ([1, 0, 3i])),\n%!        [1, 0, 3i; 0, 5i, 6] ./ [1, 0, 3i])\n%!assert (full (sparse ([1, 2; 1, 0; 0, 0]) ./ sparse ([1i; 2; 0])),\n%!        [1, 2; 1, 0; 0, 0] ./ [1i; 2; 0])\n%!assert (full (sparse ([1; 2i; 3; 4]) ./ sparse ([0, 0, 3])),\n%!        [1; 2i; 3; 4] ./ [0, 0, 3])\n%!assert (full (sparse ([1i, 0, 0, 0, 5i]) ./ sparse ([1; 2i; 3])),\n%!        [1i, 0, 0, 0, 5i] ./ [1; 2i; 3])\n\n%!assert (sparse (1) ./ sparse ([1, 2i, 3]), sparse ([1, -0.5i, 1/3]))\n%!assert (sparse (1) ./ sparse ([1i, 2; 3, 4]), sparse ([-1i, 0.5; 1/3, 0.25]))\n%!assert (sparse ([1 2 3i]) ./ sparse (1), sparse ([1, 2, 3i]))\n%!assert (sparse ([1, 2; 3i, 4]) ./ sparse (1), sparse ([1, 2; 3i, 4]))\n%!assert (full (sparse ([1; 2i]) ./ sparse ([1, 0, 2i, 0, 4])),\n%!        [1; 2i] ./ [1, 0, 2i, 0, 4])\n%!assert (full (sparse ([1, 0, 2, 0, 4i]) ./ sparse ([1; 2])),\n%!        [1, 0, 2, 0, 4i] ./ [1; 2])\n%!assert (full (sparse ([1i, 2]) ./ sparse ([1; 0; 2; 0i; 4i])),\n%!        [1i, 2] ./ [1; 0; 2; 0i; 4i])\n%!assert (full (sparse ([1i; 0; 2; 0; 4]) ./ sparse ([1, 2])),\n%!        [1i; 0; 2; 0; 4] ./ [1, 2])\n%!assert (full (sparse ([1, 0, 3i]) ./ sparse ([1, 2, 3; 4, 0, 0])),\n%!        [1, 0, 3i] ./ [1, 2, 3; 4, 0, 0])\n%!assert (full (sparse ([10i, 0, 3; 4, 5, 0]) ./ sparse ([1, 0, 3])),\n%!        [10i, 0, 3; 4, 5, 0] ./ [1, 0, 3])\n%!assert (full (sparse ([1; 2i; 0]) ./ sparse ([0, 2; 3, 4; 5, 0])),\n%!        [1; 2i; 0] ./ [0, 2; 3, 4; 5, 0])\n%!assert (full (sparse ([1i, 2i; 0, 0; 0, 6]) ./ sparse ([0; 2; 3])),\n%!        [1i, 2i; 0, 0; 0, 6] ./ [0; 2; 3])\n\n## Test broadcasting for math operations with scalar and sparse matrix\n%!assert (sparse ([1, 2i]) + 1, [2, 1+2i])\n%!assert (1 + sparse ([1, 2i]), [2, 1+2i])\n%!assert (sparse ([1, 2]) - 1i, [1-1i, 2-1i])\n%!assert (1i - sparse ([1, 2]), [-1+1i, -2+1i])\n%!assert (sparse ([1, 2]) .* 1i, sparse ([1i, 2i]))\n%!assert (1 .* sparse ([1i, 2]), sparse ([1i, 2]))\n%!assert (sparse ([1, 2i]) ./ 1, sparse ([1, 2i]))\n%!assert (1 ./ sparse ([1i, 2]), [-1i, 0.5])\n%!error <operator /: nonconformant arguments \\(op1 is 1x1, op2 is 1x2\\)>\n%! 1 / sparse ([1i, 2])\n\n## Test broadcasting for math operations with matrix and sparse matrix\n%!assert (sparse ([1, 2]) + [1, 1i], [2, 2+1i])\n%!assert ([1, 1] + sparse ([1i, 2]), [1+1i, 3])\n%!assert (sparse ([1; 2i]) + [1; 1], [2; 1+2i])\n%!assert ([1; 1i] + sparse ([1; 2]), [2; 2+1i])\n%!assert (sparse ([1, 2, 3i]) + ones (3), repmat ([2, 3, 1+3i], 3, 1))\n%!assert (sparse ([1; 2; 3]) + ones (3)*i, repmat ([1; 2; 3]+i, 1, 3))\n%!assert (ones (3)*i + sparse ([1, 2, 3]), repmat ([1, 2, 3]+i, 3, 1))\n%!assert (ones (3) + sparse ([1; 2i; 3]), repmat ([2; 1+2i; 4], 1, 3))\n%!assert (sparse ([1, 2]) + [1; 2i], [2, 3; 1+2i, 2+2i])\n%!assert ([1; 2] + sparse ([1, 2i]), [2, 1+2i; 3, 2+2i])\n%!assert (sparse ([1; 2]) + [1, 2i], [2, 1+2i; 3, 2+2i])\n%!assert ([1, 2i] + sparse ([1; 2i]), [2, 1+2i; 1+2i, 4i])\n%!error <operator \\+: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2i]) + [1, 1i, 1]\n%!error <operator \\+: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2i, 3]) + ones (4)\n%!error <operator \\+: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2; 3]) + ones (4, 3)*i\n\n%!assert (sparse ([1, 2i]) - [1, 1], [0, -1+2i])\n%!assert ([1, 1] - sparse ([1, 2i]), [0, 1-2i])\n%!assert (sparse ([1; 2]) - [1; 1i], [0; 2-1i])\n%!assert ([1; 1i] - sparse ([1; 2]), [0; -2+1i])\n%!assert (sparse ([1, 2, 3]) - ones (3)*i, repmat ([1:3]-i, 3, 1))\n%!assert (sparse ([1; 2; 3i]) - ones (3), repmat ([0; 1; -1+3i], 1, 3))\n%!assert (ones (3) - sparse ([1i, 2, 3]), repmat ([1-1i, -1, -2], 3, 1))\n%!assert (ones (3)*i - sparse ([1; 2; 3]), repmat ([-1; -2; -3]+i, 1, 3))\n%!assert (sparse ([1, 2]) - [1; 2i], [1, 2] - [1; 2i])\n%!assert ([1; 2i] - sparse ([1i, 2]), [1; 2i] - [1i, 2])\n%!assert (sparse ([1; 2i]) - [1, 2], [1; 2i] - [1, 2])\n%!assert ([1i, 2] - sparse ([1; 2i]), [1i, 2] - [1; 2i])\n%!error <operator -: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2i]) - [1, 1i, 1]\n%!error <operator -: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3i]) - ones (4)\n%!error <operator -: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2; 3i]) - ones (4, 3)\n\n%!assert (sparse ([1, 2i]) .* [1, 1], sparse ([1, 2i]))\n%!assert ([1, 1i] .* sparse ([1, 2]), sparse ([1, 2i]))\n%!assert (sparse ([1i; 2]) .* [1; 1], sparse ([1i; 2]))\n%!assert ([1i; 1] .* sparse ([1; 2i]), sparse ([1i; 2i]))\n%!assert (sparse ([1, 2, 3i]) .* ones (3), sparse (repmat ([1, 2, 3i], 3, 1)))\n%!assert (sparse ([1; 2; 3]) .* ones (3)*i, sparse (repmat ([1:3]'*i, 1, 3)))\n%!assert (ones (3) .* sparse ([1, 2, 3i]), sparse (repmat ([1, 2, 3i], 3, 1)))\n%!assert (ones (3) .* sparse ([1i; 2i; 3i]), sparse (repmat ([1:3]'*i, 1, 3)))\n%!assert (sparse ([1i, 2]) .* [1; 2], sparse ([1i, 2] .* [1; 2]))\n%!assert ([1; 2i] .* sparse ([1, 2]), sparse ([1; 2i] .* [1, 2]))\n%!assert (sparse ([1; 2i]) .* [1, 2i], sparse ([1; 2i] .* [1, 2i]))\n%!assert ([1i, 2i] .* sparse ([1i; 2]), sparse ([1i, 2i] .* [1i; 2]))\n%!error <product: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2i]) .* [1, 1, 1]\n%!error <product: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3i]) .* ones (4)\n%!error <product: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2i; 3]) .* ones (4, 3)\n%!error <operator \\*: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2]) * [1, 1i, 1]\n%!error <operator \\*: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3i]) * ones (4)\n%!error <operator \\*: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2; 3i]) * ones (4, 3)\n\n%!assert (sparse ([1, 2i]) ./ [1, 1], sparse ([1, 2i]))\n%!assert ([1, 1i] ./ sparse ([1, 2]), [1, 0.5i])\n%!assert (sparse ([1; 2]) ./ [1; 1i], sparse ([1; -2i]))\n%!assert ([1i; 1] ./ sparse ([1; 2i]), [1i; -0.5i])\n%!assert (sparse ([1, 2i, 3]) ./ ones (3), sparse (repmat ([1, 2i, 3], 3, 1)))\n%!assert (sparse ([1; 2; 3]) ./ (ones (3)*i), ...\n%!        sparse (repmat (-[1i; 2i; 3i], 1, 3)))\n%!assert (ones (3) ./ sparse ([1, 2i, 3]), repmat ([1, -0.5i, 1/3], 3, 1))\n%!assert ((ones (3)*(-i)) ./ sparse ([1; 2; 3]),\n%!        repmat (-[1; 0.5; 1/3]*i, 1, 3))\n%!assert (sparse ([1, 2i]) ./ [1; 2], sparse ([1, 2i] ./ [1; 2]))\n%!assert ([1i; 2] ./ sparse ([1i, 2i]), [1i; 2] ./ [1i, 2i])\n%!assert (sparse ([1; 2i]) ./ [1, 2], sparse ([1; 2i] ./ [1, 2]))\n%!assert ([1i, 2i] ./ sparse ([1; 2i]), [1i, 2i] ./ [1; 2i])\n%!error <quotient: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2i]) ./ [1, 1, 1]\n%!error <quotient: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3i]) ./ ones (4)\n%!error <quotient: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1; 2i; 3]) ./ ones (4, 3)\n%!error <operator /: nonconformant arguments \\(op1 is 1x2, op2 is 1x3\\)>\n%! sparse ([1, 2i]) / [1, 1i, 1]\n%!error <operator /: nonconformant arguments \\(op1 is 1x3, op2 is 4x4\\)>\n%! sparse ([1, 2, 3i]) / ones (4)\n%!error <operator /: nonconformant arguments \\(op1 is 3x1, op2 is 4x3\\)>\n%! sparse ([1i; 2i; 3i]) / ones (4, 3)\n\n## Tests for product operations involving Inf values\n%!test\n%! x = speye (3) * i;\n%! y = sparse (3,3);\n%! y(1,3) = Inf;\n%! out = y;\n%! out(1,3) = NaN*i;\n%! assert (x .* y, out);\n%!test\n%! out = speye (3)*i .* sparse ([0, 0, Inf]);\n%! assert (out, sparse ([0, 0, NaN*i; 0, 0, NaN*i; 0, 0, Inf*i]));\n%!test\n%! out = speye (3)*i .* sparse ([0; 0; Inf]);\n%! assert (out, sparse ([0, 0, 0; 0, 0, 0; NaN*i, NaN*i, Inf*i]));\n%!test\n%! out = sparse (1, 3) .* sparse ([i; 0; Inf]);\n%! assert (out, sparse ([0, 0, 0; 0, 0, 0; NaN, NaN, NaN]));\n%!test\n%! out = sparse (3, 1) .* sparse ([i, 0, Inf]);\n%! assert (out, sparse ([0, 0, NaN; 0, 0, NaN; 0, 0, NaN]));\n\n## Test broadcasting for comparison and boolean operators\n## for sparse matrix to matrix and matrix to sparse matrix\n%!assert (sparse ([1, 1i, 0]) == [0, 1, 1]*i, sparse (logical ([0, 1, 0])))\n%!assert (sparse ([1; 1i; 0]) == [0, 1, 1]*i, ...\n%!        sparse ([1; 1i; 0] == [0, 1, 1]*i))\n%!assert (sparse ([1, 1i, 0]) == [0; 1; 1; 0]*i, ...\n%!        sparse ([1, 1i, 0] == [0; 1; 1; 0]*i))\n%!assert (sparse ([1, 1i, 0]) == [0, 1, 1; 0, 1, 1]*i, ...\n%!        sparse (logical ([0, 1, 0; 0, 1, 0])))\n%!assert (sparse ([1; 1i; 0]) == [0, 1; 1, 1; 0, 1]*i, ...\n%!        sparse (logical ([0, 0; 1, 1; 1, 0])))\n%!assert ([1i, 0, 1] == sparse ([1, 1, 0]*i), sparse (logical ([1, 0, 0])))\n%!assert ([0, 1, 1i] == sparse ([1; 1; 0]*i), ...\n%!        sparse ([0, 1, 1i] == [1; 1; 0]*i))\n%!assert ([0; 1; 1i; 0] == sparse ([1, 1, 0]*i), ...\n%!        sparse ([0; 1; 1i; 0] == [1, 1, 0]*i))\n%!assert ([0, 1, 1i; 0+i, 1, 1] == sparse ([1, 1, 0]+i), ...\n%!        sparse (logical ([0, 0, 1; 0, 0, 0])))\n%!assert ([0, 1; 1, 1; 0, 1]+i == sparse ([1; 1; 0]+i), ...\n%!        sparse (logical ([0, 1; 1, 1; 1, 0])))\n\n%!assert (sparse ([1, 1i, 0]) != [0, 1, 1]*i, sparse (logical ([1, 0, 1])))\n%!assert (sparse ([1; 1i; 0]) != [0, 1, 1]*i, ...\n%!        sparse ([1; 1i; 0] != [0, 1, 1]*i))\n%!assert (sparse ([1, 1i, 0]) != [0; 1; 1; 0]*i, ...\n%!        sparse ([1, 1i, 0] != [0; 1; 1; 0]*i))\n%!assert (sparse ([1, 1i, 0]) != [0, 1, 1; 0, 1, 1]*i, ...\n%!        sparse (logical ([1, 0, 1; 1, 0, 1])))\n%!assert (sparse ([1; 1i; 0]) != [0, 1; 1, 1; 0, 1]*i, ...\n%!        sparse (logical ([1, 1; 0, 0; 0, 1])))\n%!assert ([1i, 0, 1] != sparse ([1, 1, 0]*i), sparse (logical ([0, 1, 1])))\n%!assert ([0, 1, 1i] != sparse ([1; 1; 0]*i), ...\n%!        sparse ([0, 1, 1i] != [1; 1; 0]*i))\n%!assert ([0; 1; 1i; 0] != sparse ([1, 1, 0]*i), ...\n%!        sparse ([0; 1; 1i; 0] != [1, 1, 0]*i))\n%!assert ([0, 1, 1i; 0+i, 1, 1] != sparse ([1, 1, 0]+i), ...\n%!        sparse (logical ([1, 1, 0; 1, 1, 1])))\n%!assert ([0, 1; 1, 1; 0, 1]+i != sparse ([1; 1; 0]+i), ...\n%!        sparse (logical ([1, 0; 0, 0; 0, 1])))\n\n%!assert (sparse ([1, 1i, 0]) <= [0, 1, 1]*i, sparse (logical ([0, 1, 1])))\n%!assert (sparse ([1; 1i; 0]) <= [0, 1, 1]*i, sparse ([1; 1; 0] <= [0, 1, 1]))\n%!assert (sparse ([1, 1i, 0]) <= [0; 1; 1; 0]*i, ...\n%!        sparse ([1, 1i, 0] <= [0; 1; 1; 0]*i))\n%!assert (sparse ([1, 1i, 0]) <= [0, 1, 1; 0, 1, 1]*i, ...\n%!        sparse (logical ([0, 1, 1; 0, 1, 1])))\n%!assert (sparse ([1; 1i; 0]) <= [0, 1; 1, 1; 0, 1]*i, ...\n%!        sparse (logical ([0, 1; 1, 1; 1, 1])))\n%!assert ([1i, 0, 1] <= sparse ([1, 1, 0]*i), sparse (logical ([1, 1, 0])))\n%!assert ([0, 1, 1i] <= sparse ([1; 1; 0]*i), ...\n%!        sparse ([0, 1i, 1] <= [1; 1; 0]*i))\n%!assert ([0; 1; 1i; 0] <= sparse ([1, 1, 0]*i), ...\n%!        sparse ([0; 1; 1i; 0] <= [1, 1, 0]*i))\n%!assert ([0, 1, 1i; 0+i, 1, 1] <= sparse ([1, 1, 0]+i), ...\n%!        sparse (logical ([1, 1, 1; 1, 1, 1])))\n%!assert ([0, 1; 1, 1; 0, 1]+i <= sparse ([1; 1; 0]+i), ...\n%!        sparse (logical ([1, 1; 1, 1; 1, 0])))\n\n%!assert (sparse ([1, 1i, 0]) >= [0, 1, 1]*i, sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1; 1i; 0]) >= [0, 1, 1]*i, ...\n%!        sparse ([1; 1i; 0] >= [0, 1, 1]*i))\n%!assert (sparse ([1, 1i, 0]) >= [0; 1; 1; 0]*i, ...\n%!        sparse ([1, 1i, 0] >= [0; 1; 1; 0]*i))\n%!assert (sparse ([1, 1i, 0]) >= [0, 1, 1; 0, 1, 1]*i, ...\n%!        sparse (logical ([1, 1, 0; 1, 1, 0])))\n%!assert (sparse ([1; 1i; 0]) >= [0, 1; 1, 1; 0, 1]*i, ...\n%!        sparse (logical ([1, 0; 1, 1; 1, 0])))\n%!assert ([1i, 0, 1] >= sparse ([1, 1, 0]*i), sparse (logical ([1, 0, 1])))\n%!assert ([0, 1, 1i] >= sparse ([1; 1; 0]*i), ...\n%!        sparse ([0, 1, 1i] >= [1; 1; 0]*i))\n%!assert ([0; 1; 1i; 0] >= sparse ([1, 1, 0]*i), ...\n%!        sparse ([0; 1; 1i; 0] >= [1, 1, 0]*i))\n%!assert ([0, 1, 1i; 0+i, 1, 1] >= sparse ([1, 1, 0]+i), ...\n%!        sparse (logical ([0, 0, 1; 0, 0, 0])))\n%!assert ([0, 1; 1, 1; 0, 1]+i >= sparse ([1; 1; 0]+i), ...\n%!        sparse (logical ([0, 1; 1, 1; 1, 1])))\n\n%!assert (sparse ([1, 1i, 0]) < [0, 1, 1]*i, sparse (logical ([0, 0, 1])))\n%!assert (sparse ([1; 1i; 0]) < [0, 1, 1]*i, sparse ([1; 1i; 0] < [0, 1, 1]*i))\n%!assert (sparse ([1, 1i, 0]) < [0; 1; 1; 0]*i, ...\n%!        sparse ([1, 1i, 0] < [0; 1; 1; 0]*i))\n%!assert (sparse ([1, 1i, 0]) < [0, 1, 1; 0, 1, 1]*i, ...\n%!        sparse (logical ([0, 0, 1; 0, 0, 1])))\n%!assert (sparse ([1; 1i; 0]) < [0, 1; 1, 1; 0, 1]*i, ...\n%!        sparse (logical ([0, 1; 0, 0; 0, 1])))\n%!assert ([1i, 0, 1] < sparse ([1, 1, 0]*i), sparse (logical ([0, 1, 0])))\n%!assert ([0, 1, 1i] < sparse ([1; 1; 0]*i), sparse ([0, 1, 1i] < [1; 1; 0]*i))\n%!assert ([0; 1; 1i; 0] < sparse ([1, 1, 0]*i), ...\n%!        sparse ([0; 1; 1i; 0] < [1, 1, 0]*i))\n%!assert ([0, 1, 1i; 0+i, 1, 1] < sparse ([1, 1, 0]+i), ...\n%!        sparse (logical ([1, 1, 0; 1, 1, 1])))\n%!assert ([0, 1; 1, 1; 0, 1]+i < sparse ([1; 1; 0]+i), ...\n%!        sparse (logical ([1, 0; 0, 0; 0, 0])))\n\n%!assert (sparse ([1, 1i, 0]) > [0, 1, 1]*i, sparse (logical ([1, 0, 0])))\n%!assert (sparse ([1; 1i; 0]) > [0, 1, 1]*i, sparse ([1; 1i; 0] > [0, 1, 1]*i))\n%!assert (sparse ([1, 1i, 0]) > [0; 1; 1; 0]*i, ...\n%!        sparse ([1, 1i, 0] > [0; 1; 1; 0]*i))\n%!assert (sparse ([1, 1i, 0]) > [0, 1, 1; 0, 1, 1]*i, ...\n%!        sparse (logical ([1, 0, 0; 1, 0, 0])))\n%!assert (sparse ([1; 1i; 0]) > [0, 1; 1, 1; 0, 1]*i, ...\n%!        sparse (logical ([1, 0; 0, 0; 0, 0])))\n%!assert ([1i, 0, 1] > sparse ([1, 1, 0]*i), sparse (logical ([0, 0, 1])))\n%!assert ([0, 1, 1i] > sparse ([1; 1; 0]*i), sparse ([0, 1, 1i] > [1; 1; 0]*i))\n%!assert ([0; 1; 1i; 0] > sparse ([1, 1, 0]*i), ...\n%!        sparse ([0; 1; 1i; 0] > [1, 1, 0]*i))\n%!assert ([0, 1, 1i; 0+i, 1, 1] > sparse ([1, 1, 0]+i), ...\n%!        sparse (logical ([0, 0, 0; 0, 0, 0])))\n%!assert ([0, 1; 1, 1; 0, 1]+i > sparse ([1; 1; 0]+i), ...\n%!        sparse (logical ([0, 0; 0, 0; 0, 1])))\n\n%!assert (sparse ([1, 1i, 0]) & [0, 1, 1]*i, sparse (logical ([0, 1, 0])))\n%!assert (sparse ([1; 1i; 0]) & [0, 1, 1]*i, sparse ([1; 1i; 0] & [0, 1, 1]*i))\n%!assert (sparse ([1, 1i, 0]) & [0; 1; 1; 0]*i, ...\n%!        sparse ([1, 1i, 0] & [0; 1; 1; 0]*i))\n%!assert (sparse ([1, 1i, 0]) & [0, 1, 1; 0, 1, 1]*i, ...\n%!        sparse (logical ([0, 1, 0; 0, 1, 0])))\n%!assert (sparse ([1; 1i; 0]) & [0, 1; 1, 1; 0, 1]*i, ...\n%!        sparse (logical ([0, 1; 1, 1; 0, 0])))\n%!assert ([1i, 0, 1] & sparse ([1, 1, 0]*i), sparse (logical ([1, 0, 0])))\n%!assert ([0, 1, 1i] & sparse ([1; 1; 0]*i), sparse ([0, 1, 1i] & [1; 1; 0]*i))\n%!assert ([0; 1; 1i; 0] & sparse ([1, 1, 0]*i), ...\n%!        sparse ([0; 1; 1i; 0] & [1, 1, 0]*i))\n%!assert ([0, 1, 1i; 0+i, 1, 1] & sparse ([1, 1, 0]+i), ...\n%!        sparse (logical ([0, 1, 1; 1, 1, 1])))\n%!assert ([0, 1; 1, 1; 0, 1]+i & sparse ([1; 1; 0]+i), ...\n%!        sparse (logical ([1, 1; 1, 1; 1, 1])))\n\n## Test boolean OR operations should return dense logical arrays\n%!assert (sparse ([1, 1i, 0]) | [0, 1, 1]*i, logical ([1, 1, 1]))\n%!assert (sparse ([1; 1i; 0]) | [0, 1, 1]*i, [1; 1i; 0] | [0, 1, 1]*i)\n%!assert (sparse ([1, 1i, 0]) | [0; 1; 1; 0]*i, [1, 1i, 0] | [0; 1; 1; 0]*i)\n%!assert (sparse ([1, 1i, 0]) | [0, 1, 1; 0, 1, 1]*i,\n%!        logical ([1, 1, 1; 1, 1, 1]))\n%!assert (sparse ([1; 1i; 0]) | [0, 1; 1, 1; 0, 1]*i,\n%!        logical ([1, 1; 1, 1; 0, 1]))\n%!assert ([1i, 0, 1] | sparse ([1, 1, 0]*i), logical ([1, 1, 1]))\n%!assert ([0, 1, 1i] | sparse ([1; 1; 0]*i), [0, 1, 1i] | [1; 1; 0]*i)\n%!assert ([0; 1; 1i; 0] | sparse ([1, 1, 0]*i), [0; 1; 1i; 0] | [1, 1, 0]*i)\n%!assert ([0, 1, 1i; 0+i, 1, 1] | sparse ([1, 1, 0]+i),\n%!        logical ([1, 1, 1; 1, 1, 1]))\n%!assert ([0, 1; 1, 1; 0, 1]+i | sparse ([1; 1; 0]+i),\n%!        logical ([1, 1; 1, 1; 1, 1]))\n\n## Test broadcasting for comparison and boolean operators\n## for sparse matrix to scalar and scalar to sparse matrix\n%!assert (sparse ([1, 1, 0]*i) == 1i, sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1, 1, 0]*i) != 1i, sparse (logical ([0, 0, 1])))\n%!assert (sparse ([1, 1, 0]*i) <= 1i, sparse (logical ([1, 1, 1])))\n%!assert (sparse ([1, 1, 0]*i) >= 1i, sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1, 1, 0]*i) < 1i, sparse (logical ([0, 0, 1])))\n%!assert (sparse ([1, 1, 0]*i) > 0i, sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1, 1, 0]*i) & 1i, sparse (logical ([1, 1, 0])))\n%!assert (sparse ([1, 1, 0]*i) | 1i, logical ([1, 1, 1]))\n%!assert (sparse ([1, 1, 0]+i) == 1+i, 1+i == sparse ([1, 1, 0]+i))\n%!assert (sparse ([1, 1, 0]+i) != 1+i, 1+i != sparse ([1, 1, 0]+i))\n%!assert (sparse ([1, 1, 0]+i) <= 1+i, 1+i >= sparse ([1, 1, 0]+i))\n%!assert (sparse ([1, 1, 0]+i) >= 1+i, 1+i <= sparse ([1, 1, 0]+i))\n%!assert (sparse ([1, 1, 0]+i) < 1+i, 1+i > sparse ([1, 1, 0]+i))\n%!assert (sparse ([1, 1, 0]+i) > 0+i, 0+i < sparse ([1, 1, 0]+i))\n%!assert (sparse ([1, 1, 0]+i) & 1+i, 1+i & sparse ([1, 1, 0]+i))\n%!assert (sparse ([1, 1, 0]+i) | 1+i, 1+i | sparse ([1, 1, 0]+i))\n\n## Test some empty edge cases\n%!assert (sparse (1i) | sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (1i | sparse (ones(0,1)), logical (ones (0, 1)))\n%!assert (sparse (1i) & sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (1i & sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (sparse (1i) | sparse (ones(2,0)), sparse (logical (ones (2, 0))))\n%!assert (1i | sparse (ones(2, 0)), logical (ones (2, 0)))\n%!assert (sparse (1i) & sparse (ones(2,0)), sparse (logical (ones (2, 0))))\n%!assert (1i & sparse (ones(2, 0)), sparse (logical (ones (2, 0))))\n%!assert (sparse (1i) == sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (1i != sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (sparse (1i) <= sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (1i >= sparse (ones(0,1)), sparse (logical (ones (0, 1))))\n%!assert (sparse (1i) < sparse (ones(2,0)), sparse (logical (ones (2, 0))))\n%!assert (1i > sparse (ones(2, 0)), sparse (logical (ones (2, 0))))\n\n## Test errors\n%!error <mx_el_eq: nonconformant arguments \\(op1 is 0x2, op2 is 2x2\\)>\n%! sparse (ones (0,2)) == ones (2,2)*i\n%!error <mx_el_ne: nonconformant arguments \\(op1 is 0x2, op2 is 2x2\\)>\n%! sparse (ones (0,2)) != ones (2,2)*i\n%!error <mx_el_le: nonconformant arguments \\(op1 is 0x2, op2 is 2x2\\)>\n%! sparse (ones (0,2)) <= ones (2,2)*i\n%!error <mx_el_ge: nonconformant arguments \\(op1 is 0x2, op2 is 2x2\\)>\n%! sparse (ones (0,2)) >= ones (2,2)*i\n%!error <mx_el_lt: nonconformant arguments \\(op1 is 0x2, op2 is 2x2\\)>\n%! sparse (ones (0,2)) < ones (2,2)*i\n%!error <mx_el_gt: nonconformant arguments \\(op1 is 0x2, op2 is 2x2\\)>\n%! sparse (ones (0,2)) > ones (2,2)*i\n%!error <mx_el_and: nonconformant arguments \\(op1 is 0x2, op2 is 2x2\\)>\n%! sparse (ones (0,2)) & ones (2,2)*i\n%!error <mx_el_or: nonconformant arguments \\(op1 is 0x2, op2 is 2x2\\)>\n%! sparse (ones (0,2)) | ones (2,2)*i\n\n## Test broadcasting for comparison and boolean operators\n## for sparse matrix to sparse matrix\n%!assert (sparse([1i, 1, 0]) == sparse([0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] == [0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) == sparse([0, 1, 1]+i), ...\n%!        sparse ([1i; 1; 0] == [0, 1, 1]+i))\n%!assert (sparse([1i, 1, 0]) == sparse([0; 1; 1; 0]+i), ...\n%!        sparse ([1i, 1, 0] == [0; 1; 1; 0]+i))\n%!assert (sparse([1i, 1, 0]) == sparse([0, 1, 1; 0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] == [0, 1, 1; 0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) == sparse([0, 1; 1, 1; 0, 1]+i), ...\n%!        sparse ([1i; 1; 0] == [0, 1; 1, 1; 0, 1]+i))\n%!assert (sparse([1i, 1, 0]) != sparse([0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] != [0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) != sparse([0, 1, 1]+i), ...\n%!        sparse ([1i; 1; 0] != [0, 1, 1]+i))\n%!assert (sparse([1i, 1, 0]) != sparse([0; 1; 1; 0]+i), ...\n%!        sparse ([1i, 1, 0] != [0; 1; 1; 0]+i))\n%!assert (sparse([1i, 1, 0]) != sparse([0, 1, 1; 0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] != [0, 1, 1; 0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) != sparse([0, 1; 1, 1; 0, 1]+i), ...\n%!        sparse ([1i; 1; 0] != [0, 1; 1, 1; 0, 1]+i))\n%!assert (sparse([1i, 1, 0]) <= sparse([0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] <= [0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) <= sparse([0, 1, 1]+i), ...\n%!        sparse ([1i; 1; 0] <= [0, 1, 1]+i))\n%!assert (sparse([1i, 1, 0]) <= sparse([0; 1; 1; 0]+i), ...\n%!        sparse ([1i, 1, 0] <= [0; 1; 1; 0]+i))\n%!assert (sparse([1i, 1, 0]) <= sparse([0, 1, 1; 0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] <= [0, 1, 1; 0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) <= sparse([0, 1; 1, 1; 0, 1]+i), ...\n%!        sparse ([1i; 1; 0] <= [0, 1; 1, 1; 0, 1]+i))\n%!assert (sparse([1i, 1, 0]) >= sparse([0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] >= [0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) >= sparse([0, 1, 1]+i), ...\n%!        sparse ([1i; 1; 0] >= [0, 1, 1]+i))\n%!assert (sparse([1i, 1, 0]) >= sparse([0; 1; 1; 0]+i), ...\n%!        sparse ([1i, 1, 0] >= [0; 1; 1; 0]+i))\n%!assert (sparse([1i, 1, 0]) >= sparse([0, 1, 1; 0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] >= [0, 1, 1; 0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) >= sparse([0, 1; 1, 1; 0, 1]+i), ...\n%!        sparse ([1i; 1; 0] >= [0, 1; 1, 1; 0, 1]+i))\n%!assert (sparse([1i, 1, 0]) < sparse([0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] < [0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) < sparse([0, 1, 1]+i), ...\n%!        sparse ([1i; 1; 0] < [0, 1, 1]+i))\n%!assert (sparse([1i, 1, 0]) < sparse([0; 1; 1; 0]+i), ...\n%!        sparse ([1i, 1, 0] < [0; 1; 1; 0]+i))\n%!assert (sparse([1i, 1, 0]) < sparse([0, 1, 1; 0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] < [0, 1, 1; 0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) < sparse([0, 1; 1, 1; 0, 1]+i), ...\n%!        sparse ([1i; 1; 0] < [0, 1; 1, 1; 0, 1]+i))\n%!assert (sparse([1i, 1, 0]) > sparse([0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] > [0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) > sparse([0, 1, 1]+i), ...\n%!        sparse ([1i; 1; 0] > [0, 1, 1]+i))\n%!assert (sparse([1i, 1, 0]) > sparse([0; 1; 1; 0]+i), ...\n%!        sparse ([1i, 1, 0] > [0; 1; 1; 0]+i))\n%!assert (sparse([1i, 1, 0]) > sparse([0, 1, 1; 0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] > [0, 1, 1; 0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) > sparse([0, 1; 1, 1; 0, 1]+i), ...\n%!        sparse ([1i; 1; 0] > [0, 1; 1, 1; 0, 1]+i))\n%!assert (sparse([1i, 1, 0]) & sparse([0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] & [0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) & sparse([0, 1, 1]+i), ...\n%!        sparse ([1i; 1; 0] & [0, 1, 1]+i))\n%!assert (sparse([1i, 1, 0]) & sparse([0; 1; 1; 0]+i), ...\n%!        sparse ([1i, 1, 0] & [0; 1; 1; 0]+i))\n%!assert (sparse([1i, 1, 0]) & sparse([0, 1, 1; 0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] & [0, 1, 1; 0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) & sparse([0, 1; 1, 1; 0, 1]+i), ...\n%!        sparse ([1i; 1; 0] & [0, 1; 1, 1; 0, 1]+i))\n%!assert (sparse([1i, 1, 0]) | sparse([0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] | [0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) | sparse([0, 1, 1]+i), ...\n%!        sparse ([1i; 1; 0] | [0, 1, 1]+i))\n%!assert (sparse([1i, 1, 0]) | sparse([0; 1; 1; 0]+i), ...\n%!        sparse ([1i, 1, 0] | [0; 1; 1; 0]+i))\n%!assert (sparse([1i, 1, 0]) | sparse([0, 1, 1; 0, 1, 1]+i), ...\n%!        sparse ([1i, 1, 0] | [0, 1, 1; 0, 1, 1]+i))\n%!assert (sparse([1i; 1; 0]) | sparse([0, 1; 1, 1; 0, 1]+i), ...\n%!        sparse ([1i; 1; 0] | [0, 1; 1, 1; 0, 1]+i))\n"
  },
  {
    "path": "test/struct.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! s.a = 1;\n%! c = fieldnames (s);\n%! assert (iscell (c) && strcmp (c{1}, \"a\"));\n\n%!test\n%! s.a.b = 1;\n%! c = fieldnames (s.a);\n%! assert (iscell (c) && strcmp (c{1}, \"b\"));\n\n%!error <Invalid call to fieldnames> fieldnames ()\n\n%!test\n%! s.a = 1;\n%! fail (\"fieldnames (s, 1)\", \"called with too many inputs\");\n\n%!error fieldnames (1)\n\n%!test\n%! s.aaa = 1;\n%! s.a = 2;\n%! assert (isfield (s, \"a\"));\n\n%!test\n%! s.aaa = 1;\n%! s.a = 2;\n%! assert (!(isfield (s, \"b\")));\n\n%!error <Invalid call to isfield> isfield ()\n\n%!test\n%! s.aaa = 1;\n%! s.a = 2;\n%! fail (\"isfield (s, 'a', 3);\", \"Invalid call to isfield\");\n\n%!assert (isfield (1, \"m\") == 0)\n\n%!test\n%! s.a = 2;\n%! assert (isfield (s, 2) == 0);\n\n%!assert (isstruct (1), false)\n%!assert (isstruct ([1, 2]), false)\n%!assert (isstruct ([]), false)\n%!assert (isstruct ([1, 2; 3, 4]), false)\n%!assert (isstruct (\"t\"), false)\n%!assert (isstruct (\"test\"), false)\n%!assert (isstruct ([\"test\"; \"ing\"]), false)\n%!assert (isstruct ({1}), false)\n\n%!test\n%! s.a = 1;\n%! assert (isstruct (s));\n\n%!test\n%! s.a.b = 1;\n%! assert (isstruct (s.a));\n\n%!error <Invalid call to isstruct> isstruct ()\n\n%!test\n%! s.a = 1;\n%! fail (\"isstruct (s, 1)\", \"Invalid call to isstruct\");\n\n## increment element of matrix stored in struct array field\n%!test\n%! a = struct (\"c\", {[1, 2, 3], [4, 5, 6], [7, 8, 9]});\n%! a(2).c(3)++;\n%! assert (a(2).c, [4, 5, 7]);\n\n## create struct array by assignment to cs-list\n%!test\n%! [a(1:2).x] = deal (1, 3);\n%! assert (a, struct (\"x\", {1, 3}));\n%! assert ({a(1:2).x}, {1, 3});\n\n## assign to subrange of struct array field\n%!test\n%! b = struct (\"name\", {\"a\", \"b\", \"c\"; \"d\", \"e\", \"f\"}, \"value\", 100);\n%! [b(1:2, [1,3]).name] = deal (\"aaa\", \"ddd\", \"ccc\", \"fff\");\n%! assert ({b.name}, {\"aaa\", \"ddd\", \"b\", \"e\", \"ccc\", \"fff\"});\n\n## index into nested struct arrays\n%!test\n%! a = struct (\"name\", {\"a\", \"b\", \"c\"; \"d\", \"e\", \"f\"}, \"value\", 0);\n%! a(2).value = a;\n%! assert (a(2).value(2,3).name, \"f\");\n\n## assign to subrange of field in nested struct array\n%!test\n%! b = struct (\"name\", {\"a\", \"b\", \"c\"; \"d\", \"e\", \"f\"}, \"value\", 0);\n%! b(3, 1).value = b;\n%! [b(3, 1).value(1, [1, 3]).name] = deal (\"aaa\", \"ccc\");\n%! assert (size (b), [3, 3]);\n%! assert (b(3,1).value(1, 3).name, \"ccc\");\n\n## test 4-dimensional struct array\n%!test\n%! c(4, 4, 4, 4).name  = \"a\";\n%! c(3, 3, 3, 3).value = 1;\n%! assert (c(2,2,2,2), struct (\"name\", [], \"value\", []));\n\n## assign to subrange of field in 4-D struct array\n%!test\n%! c(4, 4, 4, 4).name  = \"a\";\n%! c(3, 3, 3, 3).value = 1;\n%! [c([1, 3], 2, :, [3, 4]).value] = deal (1);\n%! assert (length (find ([c.value] == 1)), 17);\n%! assert (length (find ([c.value])), 17);\n\n## swap elements of struct array\n%!test\n%! b = struct (\"name\", {\"a\", \"b\", \"c\"; \"d\", \"e\", \"f\"}, \"value\", 0);\n%! [b([2, 1], [3, 1]).name] = deal (b([1, 2], [1, 2]).name);\n%! assert ({b.name}, {\"e\", \"b\", \"b\", \"e\", \"d\", \"a\"});\n\n## test internal ordering of struct array fields\n%!test\n%! c(4, 4, 4, 4).value = 3;\n%! c(1, 2, 3, 4).value = 2;\n%! c(3, 3, 3, 3).value = 1;\n%! d = reshape ({c.value}, size (c));\n%! assert ([d{4, 4, 4, 4}, d{1, 2, 3, 4}, d{3, 3, 3, 3}], [3, 2, 1]);\n\n## test assignment to mixed cs-list of field element subranges\n%!test\n%! b = struct (\"name\", {\"a\", \"b\", \"c\"; \"d\", \"e\", \"f\"}, \"value\", 100);\n%! [b(1:2, [1, 3]).name, b(2, 1:3).value] = ...\n%!   deal (1, 2, 3, 4, \"5\", \"6\", \"7\");\n%! assert ({b.name}, {1, 2, \"b\", \"e\", 3, 4});\n%! assert ({b.value}, {100, \"5\", 100, \"6\", 100, \"7\"});\n\n%!error <deal: nargin>\n%! [a(1:3).x] = deal ([1, 5], [3, 7], [8, 9]);\n%! [a(2:3).x(2)] = deal (10, 11);\n\n%!error <a cs-list cannot be further indexed>\n%! [a(1:3).x] = deal ([1, 5], [3, 7], [8, 9]);\n%! [a(2:3).x(2)] = 1;\n\n%!error <a cs-list cannot be further indexed>\n%! [a(1:3).x] = deal ([1, 5], [3, 7], [8, 9]);\n%! a(2:3).x(2);\n\n%!error id=Octave:index-out-of-bounds\n%! a(1).x.x = 1;\n%! a(2).x;\n\n%!error <invalid number of output arguments for constant expression>\n%! a = struct (\"value\", {1, 2, 3, 4, 5});\n%! [a(2:4).value] = 1;\n\n%!error <invalid assignment to cs-list outside multiple assignment>\n%! c(4, 4, 4, 4).name  = \"a\";\n%! c(3, 3, 3, 3).value = 1;\n%! c([1, 3], 2, :, [3, 4]).value = 1;\n\n## test lazy copying in structs: nested assignment to self\n%!test\n%! a.a = 1;\n%! a.b = a;\n%! a.b.c = a;\n%! assert (a.b.c.b, struct (\"a\", 1));\n\n## test lazy copying in structs: indirect nested assignment to self\n%!test\n%! a.a = 1;\n%! a.b = 2;\n%! b.c = a;\n%! b.d = 3;\n%! c.d = b;\n%! c.e = 4;\n%! a.b = c;\n%! a.b.e = a;\n%! assert (a.b.e.b.d.c, struct (\"a\", 1, \"b\", 2));\n\n## test lazy copying in structs: nested assignment via function\n%!function aa = do_nest (a)\n%!  aa   = a;\n%!  aa.b = a;\n%!endfunction\n%!test\n%! a.c = 1;\n%! a = do_nest (a);\n%! a = do_nest (a);\n%! a = do_nest (a);\n%! assert (a.b.b.b, struct (\"c\", 1));\n\n## test lazy copying in structs: nested assignment via function\n%!function aa = do_nest (a)\n%!  aa   = a;\n%!  aa.b = a;\n%!  aa.b.c = aa;\n%!endfunction\n%!test\n%! a.c = 1;\n%! a = do_nest (a);\n%! a = do_nest (a);\n%! a = do_nest (a);\n%! assert (a.b.c.b.b.c.b.b.c.b, struct (\"c\", 1));\n\n## test lazy copying in structs: nested assignment on different levels.\n%!test\n%! a.b = 1;\n%! b.c = a;\n%! b.d.e = a;\n%! b.f.g.h = a;\n%! b.i.j.k.l = a;\n%! a.m = b;\n%! a.m.c.b = a;\n%! assert (a.m.c.b.m.i.j.k.l, struct (\"b\", 1));\n\n## test indexed assignment into empty struct array\n%!test\n%! s = resize (struct (), 3,2);\n%! s(3).foo = 42;\n%! assert (s(3), struct (\"foo\", 42));\n\n## empty index should return entire struct\n%!test <*51633>\n%! x.a = 1:10;\n%! y = x;\n%! assert (! isempty (y));\n%! assert (y, x);\n%! warning ('off', 'Octave:empty-index', 'local');\n%! z = x();\n%! assert (! isempty (z));\n%! assert (z, x);\n%! assert (z, y);\n\n## test assigning to multi-dim struct with trailing singleton dimensions,\n%!test <*35841>\n%! a(1,1,1).b(1) = 1;\n%! a(1,1,1).b(1) = 2;\n%! a(1,1,:).b(1) = 3;\n%! assert (a(1,1,1).b(1) == 3);\n\n%!error id=Octave:index-out-of-bounds\n%! s = resize (struct (),3,2);\n%! s(3).foo = 42;\n%! s(7);\n"
  },
  {
    "path": "test/switch.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! a = 1;\n%! b = 2;\n%! c = 3;\n%!\n%! ## \"end\" is part of test, check not using \"endswitch\"\n%! switch (0) case 1 x = a; case 2 x = b; otherwise x = c; end\n%! switch (1) case 1 y = a; case 2 y = b; otherwise y = c; endswitch\n%! switch (2) case 1 z = a; case 2 z = b; otherwise z = c; endswitch\n%! switch (3) case 1 p = a; case 2 p = b; otherwise p = c; endswitch\n%!\n%! assert (x == c && y == a && z == b && p == c);\n\n%!test\n%! a = 1;\n%! b = 2;\n%! c = 3;\n%!\n%! x = zeros (1, 4);\n%!\n%! k = 1;\n%!\n%! for i = 0:3\n%! switch (i)\n%!   case a\n%!     x(k) = a;\n%!   case b\n%!     x(k) = b;\n%!   otherwise\n%!     x(k) = c;\n%!   endswitch\n%!   k++;\n%! endfor\n%!\n%! assert (all (x == [3, 1, 2, 3]));\n\n%!test\n%! a = 1;\n%! b = 2;\n%! c = 3;\n%!\n%! x = zeros (1, 4);\n%!\n%! k = 1;\n%!\n%! for i = 0:3\n%!   switch (i)\n%!     case a\n%!       x(k) = a;\n%!   endswitch\n%!   k++;\n%! endfor\n%!\n%! assert (all (x == [0, 1, 0, 0]));\n\n%!test\n%! a = 1;\n%!\n%! switch (1)\n%!   otherwise\n%!     a = 2;\n%! endswitch\n%!\n%! assert (a == 2);\n\n\n%!error <syntax error> eval (\"switch endswitch\")\n\n%!error <syntax error> eval (\"switch case endswitch\")\n\n%!error <syntax error> eval (\"switch 1 default 1; endswitch\")\n\n%% test parsing of single-quoted character string appearing immediately\n%% after a switch case\n%!test\n%! switch (1)\n%!   case 1\n%!     'foo';\n%!     x = 13;\n%! endswitch\n%! assert (x, 13);\n"
  },
  {
    "path": "test/system.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! [t1, u1, s1] = cputime ();\n%! for i = 1:200\n%!   sin (i);\n%! endfor\n%! [t2, u2, s2] = cputime ();\n%! assert (t1, u1 + s1, 2*eps (t1));\n%! assert (t2, u2 + s2, 2*eps (t2));\n%! assert (t2 >= t1);\n%! assert (u2 >= u2);\n%! assert (s2 >= s2);\n\n%!test\n%! tic ();\n%! pause (2);\n%! assert (toc () > 0);\n\n%!test\n%! pause (0);\n%! __printf_assert__ (\"ok\\n\");\n%! assert (__prog_output_assert__ (\"ok\"));\n\n%!error <Invalid call to pause> pause (1, 2)\n\n%!test\n%! from = tempname ();\n%! to = tempname ();\n%! id = fopen (from, \"wb\");\n%! if (id > 0 && fclose (id) == 0)\n%!   [s, e] = stat (from);\n%!   if (! e)\n%!     if (rename (from, to) == 0)\n%!       [s, e] = stat (from);\n%!       if (e < 0)\n%!         [s, e] = stat (to);\n%!         assert (e == 0);\n%!         unlink (to);\n%!       endif\n%!     endif\n%!   endif\n%! endif\n\n%!error <Invalid call to rename> rename ()\n%!error <Invalid call to rename> rename (\"foo\", \"bar\", 1)\n\n%!test\n%! nm = tempname ();\n%! if ((id = fopen (nm, \"wb\")) > 0)\n%!   [s, err] = stat (nm);\n%!   if (! err && fclose (id) == 0 && unlink (nm) == 0)\n%!     [s, err] = stat (nm);\n%!     assert (err < 0);\n%!   endif\n%! endif\n\n%!error <Invalid call to unlink> unlink ()\n%!error <Invalid call to unlink> unlink (\"foo\", 1)\n%!error <FILE must be a string> unlink ({})\n\n%!test\n%! [files, status, msg] = readdir (filesep);\n%! assert (iscell (files) && status == 0 && strcmp (msg, \"\"));\n\n%!error <Invalid call to readdir> readdir ()\n%!error <Invalid call to readdir> readdir (\"foo\", 1)\n\n%!test\n%! nm = tempname ();\n%! e1 = mkdir (nm);\n%! [s2, e2] = stat (nm);\n%! e3 = rmdir (nm);\n%! [s4, e4] = stat (nm);\n%! assert ((e1 && strcmp (s2.modestr(1), \"d\") && e3 && e4 < 0));\n\n%!error <Invalid call to mkdir> mkdir ()\n%!error <called with too many inputs> mkdir (\"foo\", 1, 2)\n%!error <Invalid call to rmdir> rmdir ()\n\n%!test <61166>\n%! crr = confirm_recursive_rmdir ();\n%! orig_dir = pwd ();\n%! unwind_protect\n%!   confirm_recursive_rmdir (0);\n%!   tmp_dir = tempname ();\n%!   e1 = mkdir (tmp_dir);\n%!   ## parent dir that exists\n%!   mkdir (tmp_dir, \"d1\");\n%!   mkdir (tmp_dir, \"d2/foo\");\n%!   mkdir (tmp_dir, \"d3/foo.bar\");\n%!   assert (isfolder (fullfile (tmp_dir, \"d1\")));\n%!   assert (isfolder (fullfile (tmp_dir, \"d2/foo\")));\n%!   assert (isfolder (fullfile (tmp_dir, \"d3/foo.bar\")));\n%!   ## parent dir that does not exist\n%!   d4 = fullfile (tmp_dir, \"d4\");\n%!   d5 = fullfile (tmp_dir, \"d5\");\n%!   d6 = fullfile (tmp_dir, \"d6\");\n%!   mkdir (d4, \"foo\");\n%!   mkdir (d5, \"foo/bar\");\n%!   mkdir (d6, \"foo/bar.baz\");\n%!   assert (isfolder (fullfile (d4, \"foo\")));\n%!   assert (isfolder (fullfile (d5, \"foo/bar\")));\n%!   assert (isfolder (fullfile (d6, \"foo/bar.baz\")));\n%!   d7 = fullfile (tmp_dir, \"d7/foo\");\n%!   d8 = fullfile (tmp_dir, \"d8/foo/bar\");\n%!   d9 = fullfile (tmp_dir, \"d9/foo/bar.baz\");\n%!   mkdir (d7);\n%!   mkdir (d8);\n%!   mkdir (d9);\n%!   assert (isfolder (d7));\n%!   assert (isfolder (d8));\n%!   assert (isfolder (d9));\n%!   chdir (tmp_dir);\n%!   mkdir (\"d10\", \"foo\");\n%!   mkdir (\"d11\", \"foo/bar\");\n%!   mkdir (\"d12\", \"foo/bar.baz\");\n%!   assert (isfolder (fullfile (\"d10\", \"foo\")));\n%!   assert (isfolder (fullfile (\"d11\", \"foo/bar\")));\n%!   assert (isfolder (fullfile (\"d12\", \"foo/bar.baz\")));\n%! unwind_protect_cleanup\n%!   rmdir (tmp_dir, \"s\");\n%!   confirm_recursive_rmdir (crr);\n%!   chdir (orig_dir);\n%! end_unwind_protect\n\n%!test\n%! crr = confirm_recursive_rmdir ();\n%! confirm_recursive_rmdir (0);\n%! assert (! rmdir (\"foo\", \"s\"));\n%! confirm_recursive_rmdir (crr);\n\n%!test\n%! ## Test makes no sense on Windows systems\n%! if (isunix ())\n%!   orig_umask = umask (0);\n%!   nm = tempname ();\n%!   id = fopen (nm, \"wb\");\n%!   s1 = stat (nm);\n%!   fclose (id);\n%!   unlink (nm);\n%!\n%!   umask (777);\n%!   nm = tempname ();\n%!   id = fopen (nm, \"wb\");\n%!   s2 = stat (nm);\n%!   fclose (id);\n%!   unlink (nm);\n%!\n%!   assert (deblank (s1.modestr), \"-rw-rw-rw-\");\n%!   assert (deblank (s2.modestr), \"----------\");\n%!   ## Restore original umask value\n%!   umask (orig_umask);\n%! endif\n\n%!error <Invalid call to umask> umask ()\n%!error <Invalid call to umask> umask (1, 2)\n\n%!test\n%! [s, err, msg] = stat (filesep);\n%! assert (err == 0\n%!         && isstruct (s)\n%!         && isfield (s, \"dev\")\n%!         && isfield (s, \"ino\")\n%!         && isfield (s, \"modestr\")\n%!         && isfield (s, \"nlink\")\n%!         && isfield (s, \"uid\")\n%!         && isfield (s, \"gid\")\n%!         && isfield (s, \"size\")\n%!         && isfield (s, \"atime\")\n%!         && isfield (s, \"mtime\")\n%!         && isfield (s, \"ctime\")\n%!         && ischar (msg));\n\n%!error <Invalid call to stat> stat ()\n%!error <Invalid call to stat> stat (\"foo\", 1)\n\n%!test\n%! [s, err, msg] = lstat (filesep);\n%! assert (err == 0\n%!         && isstruct (s)\n%!         && isfield (s, \"dev\")\n%!         && isfield (s, \"ino\")\n%!         && isfield (s, \"modestr\")\n%!         && isfield (s, \"nlink\")\n%!         && isfield (s, \"uid\")\n%!         && isfield (s, \"gid\")\n%!         && isfield (s, \"size\")\n%!         && isfield (s, \"atime\")\n%!         && isfield (s, \"mtime\")\n%!         && isfield (s, \"ctime\")\n%!         && ischar (msg));\n\n%!error <Invalid call to lstat> lstat ()\n%!error <Invalid call to lstat> lstat (\"foo\", 1)\n\n%!test\n%! if (isunix ())\n%!   assert (S_ISCHR (stat (\"/dev/null\").mode));\n%!   if (exist (\"/dev/initctl\"))\n%!     assert (S_ISFIFO (stat (\"/dev/initctl\").mode));\n%!   endif\n%!   if (exist (\"/dev/core\"))\n%!     assert (S_ISLNK (lstat (\"/dev/core\").mode));\n%!   endif\n%! endif\n%! nm = tempname ();\n%! fid = fopen (nm, \"wb\");\n%! fclose (fid);\n%! r = [ S_ISREG(stat(nm).mode)\n%!       S_ISDIR(stat(nm).mode)\n%!       S_ISCHR(stat(nm).mode)\n%!       S_ISBLK(stat(nm).mode)\n%!       S_ISFIFO(stat(nm).mode)\n%!       S_ISLNK(lstat(nm).mode)\n%!       S_ISSOCK(stat(nm).mode) ];\n%! unlink (nm);\n%! assert (r(:), [true; false; false; false; false; false; false]);\n\n%!error <S_ISREG: invalid MODE value> S_ISREG ({})\n%!error <S_ISDIR: invalid MODE value> S_ISDIR ({})\n%!error <S_ISCHR: invalid MODE value> S_ISCHR ({})\n%!error <S_ISBLK: invalid MODE value> S_ISBLK ({})\n%!error <S_ISFIFO: invalid MODE value> S_ISFIFO ({})\n%!error <S_ISLNK: invalid MODE value> S_ISLNK ({})\n%!error <S_ISSOCK: invalid MODE value> S_ISSOCK ({})\n\n%!error <Invalid call to S_ISREG> S_ISREG ()\n%!error <Invalid call to S_ISDIR> S_ISDIR ()\n%!error <Invalid call to S_ISCHR> S_ISCHR ()\n%!error <Invalid call to S_ISBLK> S_ISBLK ()\n%!error <Invalid call to S_ISFIFO> S_ISFIFO ()\n%!error <Invalid call to S_ISLNK> S_ISLNK ()\n%!error <Invalid call to S_ISSOCK> S_ISSOCK ()\n\n%!assert (iscell (glob ([filesep \"*\"])))\n\n%!error <Invalid call to glob> glob ()\n%!error <Invalid call to glob> glob (\"foo\", 1)\n\n%!assert (ischar (file_in_path (path (), \"date.m\")))\n\n%!error <file_in_path: optional third argument must be a string> file_in_path (\"foo\", \"bar\", 1)\n%!error <Invalid call to file_in_path> file_in_path ()\n%!error <Invalid call to file_in_path> file_in_path (\"foo\", \"bar\", \"baz\", \"ooka\")\n\n%!testif HAVE_GETPWUID\n%! x = getpwuid (getuid ());\n%! assert (x.dir, tilde_expand (sprintf (\"~%s\", x.name)));\n%! assert (\"foobar\", tilde_expand (\"foobar\"));\n\n%!error <Invalid call to tilde_expand> tilde_expand ()\n%!error <Invalid call to tilde_expand> tilde_expand (\"str\", 2)\n\n%!testif HAVE_GETPGRP\n%! assert (getpgrp () >= 0);\n\n%!error <... getpgrp> getpgrp (1)\n\n%!assert (getpid () > 0)\n\n%!error <... getpid> getpid (1)\n\n%!testif HAVE_GETPPID\n%! assert (getppid () >= 0);\n\n%!error <... getppid> getppid (1)\n\n%!testif HAVE_GETEUID\n%! assert (geteuid () >= 0);\n\n%!error <... geteuid> geteuid (1)\n\n%!testif HAVE_GETUID\n%! assert (getuid () >= 0);\n\n%!error <... getuid> getuid (1)\n\n%!testif HAVE_GETEGID\n%! assert (getegid () >= 0);\n\n%!error <... getegid> getegid (1)\n\n%!testif HAVE_GETGID\n%! assert (getgid () >= 0);\n\n%!error <... getgid> getgid (1)\n\n%!testif ; isfolder (\"~\")\n%! assert (get_home_directory (), tilde_expand (\"~\"));\n\n%!error <Invalid call to getenv> getenv ()\n%!error <Invalid call to getenv> getenv (\"foo\", 1)\n\n%!test\n%! wns = warning (\"query\", \"Octave:num-to-str\");\n%! warning (\"on\", \"Octave:num-to-str\");\n%! fail (\"getenv (1)\", \"warning\");\n%! warning (wns.state, \"Octave:num-to-str\");\n\n%!test\n%! setenv (\"foobar\", \"baz\");\n%! assert (getenv (\"foobar\"), \"baz\");\n\n%!error <Invalid call to setenv> setenv ()\n%!error <Invalid call to setenv> setenv (\"foo\", \"bar\", 1)\n\n%!error <VAR must be a string> setenv (1, 2)\n\n%!test\n%! xdir = pwd ();\n%! ydir = cd ();\n%! assert (xdir, ydir);\n%! cd /\n%! d1 = pwd ();\n%! cd (xdir);\n%! if (ispc ())\n%!   ## should be a drive letter\n%!   assert (length (d1), 3);\n%!   assert (d1(2), \":\");\n%!   assert (d1(3), \"\\\\\");\n%! else\n%!   assert (\"/\", d1);\n%! endif\n%! assert (pwd (), xdir);\n\n%!error cd (1)\n\n%!assert (ischar (pwd ()))\n\n%!testif HAVE_GETPWENT, HAVE_SETPWENT, HAVE_ENDPWENT\n%! setpwent ();\n%! s = getpwent ();\n%! endpwent ();\n%! assert (isstruct (s)\n%!         && isfield (s, \"name\")\n%!         && isfield (s, \"passwd\")\n%!         && isfield (s, \"uid\")\n%!         && isfield (s, \"gid\")\n%!         && isfield (s, \"gecos\")\n%!         && isfield (s, \"dir\")\n%!         && isfield (s, \"shell\"));\n\n%!error <Invalid call to getpwent> getpwent (1)\n\n%!testif HAVE_GETPWUID, HAVE_GETPWENT, HAVE_SETPWENT, HAVE_ENDPWENT\n%! setpwent ();\n%! x = getpwent ();\n%! setpwent ();\n%! y = getpwuid (x.uid);\n%! endpwent ();\n%! assert (strcmp (x.name, y.name) && x.uid == y.uid && x.gid == y.gid);\n\n%!error <Invalid call to getpwuid> getpwuid ()\n%!error <Invalid call to getpwuid> getpwuid (1, 2)\n\n%!testif HAVE_GETPWNAM, HAVE_SETPWENT, HAVE_GETPWENT\n%! setpwent ();\n%! x = getpwent ();\n%! y = getpwnam (x.name);\n%! endpwent ();\n%! assert (strcmp (x.name, y.name) && x.uid == y.uid && x.gid == y.gid);\n\n%!error <Invalid call to getpwnam> getpwnam ()\n%!error <Invalid call to getpwnam> getpwnam (\"foo\", 1)\n\n%!testif HAVE_SETPWENT, HAVE_GETPWENT, HAVE_ENDPWENT\n%! setpwent ();\n%! x = getpwent ();\n%! setpwent ();\n%! y = getpwent ();\n%! endpwent ();\n%! assert (strcmp (x.name, y.name) && x.uid == y.uid && x.gid == y.gid);\n\n%!error <Invalid call to setpwent> setpwent (1)\n%!error <Invalid call to endpwent> endpwent (1)\n\n%!testif HAVE_GETGRENT\n%! endgrent ();\n%! x = getgrent ();\n%! endgrent ();\n%! assert (isstruct (x)\n%!         && isfield (x, \"name\")\n%!         && isfield (x, \"passwd\")\n%!         && isfield (x, \"gid\")\n%!         && isfield (x, \"mem\"));\n\n%!error <Invalid call to getgrent> getgrent (1)\n\n%!testif HAVE_GETGRGID\n%! endgrent ();\n%! x = getgrent ();\n%! y = getgrgid (x.gid);\n%! endgrent ();\n%! assert (strcmp (x.name, y.name) && x.gid == y.gid);\n\n%!error <Invalid call to getgrgid> getgrgid ()\n%!error <Invalid call to getgrgid> getgrgid (1, 2)\n\n%!testif HAVE_GETGRNAM\n%! endgrent ();\n%! x = getgrent ();\n%! y = getgrnam (x.name);\n%! endgrent ();\n%! assert (strcmp (x.name, y.name) && x.gid == y.gid);\n\n%!error <Invalid call to getgrnam> getgrnam ()\n%!error <Invalid call to getgrnam> getgrnam (\"foo\", 1)\n\n%!testif HAVE_SETGRENT\n%! endgrent ();\n%! x = getgrent ();\n%! setgrent ();\n%! y = getgrent ();\n%! endgrent ();\n%! assert (strcmp (x.name, y.name) && x.gid == y.gid);\n\n%!error <Invalid call to setgrent> setgrent (1)\n%!error <Invalid call to endgrent> endgrent (1)\n\n%!assert (isieee () == 1 || isieee () == 0)\n\n%!assert (isstruct (__octave_config_info__ ()))\n\n%!assert (isstruct (getrusage ()))\n"
  },
  {
    "path": "test/transpose.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%% Basic tests\n%!test\n%! scalar = 2;\n%! assert (scalar', 2);\n\n%!test\n%! range = 1:4;\n%! assert (range', [1;2;3;4]);\n\n%!test\n%! vector = [1;2;3;4];\n%! assert (vector', [1,2,3,4]);\n\n%!test\n%! matrix = [1,2;3,4];\n%! assert (matrix', [1,3;2,4]);\n\n%% Basic tests on complex numbers\n%!test\n%! scalar = 2i;\n%! assert (scalar', -2i);\n\n%!test\n%! range = (1:4)*i;\n%! assert (range', [-1i;-2i;-3i;-4i]);\n\n%!test\n%! vector = [1;2;3;4]*i;\n%! assert (vector', [-1i,-2i,-3i,-4i]);\n\n%!test\n%! matrix = [1,2;3,4]*i;\n%! assert (matrix', [-1i,-3i;-2i,-4i]);\n\n%% Test non-Hermitian transpose\n%!test\n%! scalar = 2i;\n%! assert (scalar.', 2i);\n\n%!test\n%! range = (1:4)*i;\n%! assert (range.', [1i;2i;3i;4i]);\n\n%!test\n%! vector = [1;2;3;4]*i;\n%! assert (vector.', [1i,2i,3i,4i]);\n\n%!test\n%! matrix = [1,2;3,4]*i;\n%! assert (matrix.', [1i,3i;2i,4i]);\n\n%% Basic tests on float complex numbers\n%!test\n%! scalar = single (2i);\n%! assert (scalar', single (-2i));\n\n%!test\n%! range = single ((1:4)*i);\n%! assert (range', single ([-1i;-2i;-3i;-4i]));\n\n%!test\n%! vector = single ([1;2;3;4]*i);\n%! assert (vector', single ([-1i,-2i,-3i,-4i]));\n\n%!test\n%! matrix = single ([1,2;3,4]*i);\n%! assert (matrix', single ([-1i,-3i;-2i,-4i]));\n"
  },
  {
    "path": "test/try.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! try\n%! catch\n%!   error (\"Shouldn't get here\");\n%! end  # \"end\" is part of test, check not using \"end_try_catch\"\n\n%!test\n%! try\n%!   clear a;\n%!   a;\n%! catch\n%! end_try_catch\n%! a = 1;\n%! assert (a,1);\n\n%!test\n%! clear x;\n%! try\n%!   clear a;\n%!   a;\n%!   x = 1;\n%! catch\n%! end_try_catch\n%! a = 2;\n%! assert (! exist ('x'));\n%! assert (a,2);\n\n%!test\n%! try\n%!   clear a;\n%!   a;\n%! catch\n%!   x = 1;\n%! end_try_catch\n%! assert (exist ('x'));\n\n%!test\n%! try\n%!   clear a;\n%!   a;\n%!   error (\"Shouldn't get here\");\n%! catch\n%!   assert (lasterr ()(1:13), \"'a' undefined\");\n%! end_try_catch\n%! assert (lasterr ()(1:13), \"'a' undefined\");\n\n%!test\n%! try\n%!   error (\"user-defined error\");\n%! catch\n%!   assert (lasterr, \"user-defined error\");\n%! end_try_catch\n\n%!function ms = mangle (s)\n%!  ## Wrap angle brackets around S.\n%!  ms = [\"<\" s \">\"];\n%!endfunction\n%!test\n%! try\n%!   clear a;\n%!   a;\n%!   error (\"Shouldn't get here\");\n%! catch\n%!   assert (mangle (lasterr)(1:14), \"<'a' undefined\");\n%! end_try_catch\n\n%!test\n%! try\n%!   try\n%!     clear a;\n%!     a;\n%!     error (\"Shouldn't get here\");\n%!   catch\n%!     assert (lasterr ()(1:13), \"'a' undefined\");\n%!   end_try_catch\n%!   clear b;\n%!   b;\n%!   error (\"Shouldn't get here\");\n%! catch\n%!   assert (lasterr ()(1:13), \"'b' undefined\");\n%! end_try_catch\n\n%!test\n%! try\n%!   clear a;\n%!   a;\n%!   error (\"Shouldn't get here\");\n%! catch\n%!   try\n%!     assert (lasterr ()(1:13), \"'a' undefined\");\n%!     clear b;\n%!     b;\n%!     error (\"Shouldn't get here\");\n%!   catch\n%!     assert (lasterr ()(1:13), \"'b' undefined\");\n%!   end_try_catch\n%! end_try_catch\n\n%!test\n%! try\n%!   try\n%!     clear a;\n%!     a;\n%!     error (\"Shouldn't get here\");\n%!   catch\n%!     error ([\"rethrow: \" lasterr]);\n%!   end_try_catch\n%! catch\n%!   assert (lasterr ()(1:22), \"rethrow: 'a' undefined\");\n%! end_try_catch\n\n%!test\n%! clear myerr;\n%! try\n%!   error (\"user-defined error\");\n%! catch myerr\n%!   assert (myerr.message, \"user-defined error\");\n%! end_try_catch\n\n%!test\n%! try\n%!   clear a;\n%!   error (\"user-defined error\");\n%! catch a=1;\n%!   assert (lasterr, \"user-defined error\");\n%!   assert (a, 1);\n%! end_try_catch\n\n%!test\n%! clear myerr1\n%! clear myerr2\n%! try\n%!   try\n%!     clear a;\n%!     a;\n%!   catch myerr1\n%!     error (myerr1);\n%!   end_try_catch\n%! catch myerr2\n%!   assert (myerr1.message, myerr2.message);\n%!   assert (myerr1.identifier, myerr2.identifier);\n%! end_try_catch\n\n%!test\n%! x = 1;\n%! try error (\"foo\"); catch x; assert (x.message, \"foo\"); end_try_catch\n\n%!test\n%! x = 1;\n%! try error (\"foo\"); catch x; end_try_catch\n%! assert (x.message, \"foo\");\n\n%!test\n%! x = 1;\n%! try error (\"foo\"); catch, x; assert (x, 1); end_try_catch\n\n%!test\n%! x = 1;\n%! try error (\"foo\"); catch; x; assert (x, 1); end_try_catch\n\n%!test\n%! x = 1;\n%! try error (\"foo\"); catch\n%!   x; assert (x, 1); end_try_catch\n"
  },
  {
    "path": "test/unwind.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!function y = f (x)\n%!  global g;\n%!  save_g = g;\n%!  unwind_protect\n%!    g = 0;\n%!    y = g;\n%!    [1,2;x];\n%!    g = 1;\n%!    y = [y, g];\n%!  unwind_protect_cleanup\n%!    g = save_g;\n%!    y = [y, g];\n%!  end  # \"end\" is part of test, check not using \"end_unwind_protect\"\n%!endfunction\n%!\n%!test\n%! global g = -1;\n%! y = f ([3,4]);\n%! assert (y, [0,1,-1]);\n\n%!function y = f (x)\n%!  global g;\n%!  save_g = g;\n%!  unwind_protect\n%!    g = 0;\n%!    y = g;\n%!    [1,2;x];\n%!    g = 1;\n%!    y = [y, g];\n%!  unwind_protect_cleanup\n%!    g = save_g;\n%!    y = [y, g];\n%!    assert (y, [0,-1]);\n%!  end_unwind_protect\n%!endfunction\n%!\n%!test\n%! global g = -1;\n%! fail (\"y = f (3);\", \"mismatch\");\n%! clear -global g;  # cleanup after test\n"
  },
  {
    "path": "test/while.tst",
    "content": "########################################################################\n##\n## Copyright (C) 2006-2026 The Octave Project Developers\n##\n## See the file COPYRIGHT.md in the top-level directory of this\n## distribution or <https://octave.org/copyright/>.\n##\n## This file is part of Octave.\n##\n## Octave is free software: you can redistribute it and/or modify it\n## under the terms of the GNU General Public License as published by\n## the Free Software Foundation, either version 3 of the License, or\n## (at your option) any later version.\n##\n## Octave is distributed in the hope that it will be useful, but\n## WITHOUT ANY WARRANTY; without even the implied warranty of\n## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n## GNU General Public License for more details.\n##\n## You should have received a copy of the GNU General Public License\n## along with Octave; see the file COPYING.  If not, see\n## <https://www.gnu.org/licenses/>.\n##\n########################################################################\n\n%!test\n%! i = 0;\n%! while (eye (2))\n%!   i++;\n%!   __printf_assert__ (\"%d\\n\", i);\n%! end  # \"end\" is part of test, check not using \"endwhile\"\n%! assert (__prog_output_assert__ (\"\"));\n\n%!test\n%! i = 5;\n%! while (--i)\n%!   __printf_assert__ (\"%d\", i);\n%! endwhile\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"4321\"));\n\n%!test\n%! i = 5;\n%! while (i)\n%!   i--;\n%!   __printf_assert__ (\"%d\", i);\n%! endwhile\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"43210\"));\n\n%!test\n%! i = 0;\n%! while (i++ < 20)\n%!   if (i > 2)\n%!     break;\n%!   endif\n%!   __printf_assert__ (\"%d\", i);\n%! endwhile\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"12\"));\n\n%!test\n%! i = 0;\n%! while (++i < 5)\n%!   if (i < 3)\n%!     continue;\n%!   endif\n%!   __printf_assert__ (\"%d\", i);\n%! endwhile\n%! __printf_assert__ (\"\\n\");\n%! assert (__prog_output_assert__ (\"34\"));\n\n%% test parsing of single-quoted character string appearing immediately\n%% after a while condition.\n%!test\n%! i = 0;\n%! while (++i < 5)\n%!   'foo';\n%! endwhile\n%! assert (i, 5);\n"
  }
]